From 45b7e912f1b96091802210b850453f24326e2921 Mon Sep 17 00:00:00 2001 From: David Tang Date: Wed, 6 Nov 2019 14:55:08 -0800 Subject: [PATCH] # This is a combination of 64 commits. # This is the 1st commit message: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WIP Tracerbench Travis setup # This is the commit message #2: dont checkin results # This is the commit message #3: configure azure job, make first thing for testing # This is the commit message #4: config updates # This is the commit message #5: Able to get results from Tracerbench # This is the commit message #6: redirect for tracerbench # This is the commit message #7: Update URLs to include ?tracerbench=true # This is the commit message #8: wip # This is the commit message #9: moves .server-replay.json to root # This is the commit message #10: wip # This is the commit message #11: cleanup # This is the commit message #12: cleanup # This is the commit message #13: cleanup # This is the commit message #14: cleanup # This is the commit message #15: change command # This is the commit message #16: Make process terminate with exit code 0 # This is the commit message #17: Ignore tracerbench-results files # This is the commit message #18: Delete generated JSON file # This is the commit message #19: rename directory # This is the commit message #20: Bump ember-decorators-polyfill from 1.0.6 to 1.1.0 Bumps [ember-decorators-polyfill](https://github.com/pzuraq/ember-decorators-polyfill) from 1.0.6 to 1.1.0. - [Release notes](https://github.com/pzuraq/ember-decorators-polyfill/releases) - [Commits](https://github.com/pzuraq/ember-decorators-polyfill/compare/1.0.6...1.1.0) Signed-off-by: dependabot-preview[bot] # This is the commit message #21: Bump @ember/optional-features from 1.0.0 to 1.1.0 Bumps [@ember/optional-features](https://github.com/emberjs/ember-optional-features) from 1.0.0 to 1.1.0. - [Release notes](https://github.com/emberjs/ember-optional-features/releases) - [Changelog](https://github.com/emberjs/ember-optional-features/blob/master/CHANGELOG.md) - [Commits](https://github.com/emberjs/ember-optional-features/compare/v1.0.0...v1.1.0) Signed-off-by: dependabot-preview[bot] # This is the commit message #22: [CHORE] fix Typo (#6635) Happen to run into this typo. Been using Ember for years, love your work! Good luck! Co-authored-by: igorT # This is the commit message #23: Update Changelog for v3.13.0 # This is the commit message #24: update changelog for v3.13.1 # This is the commit message #25: [CHORE] adds infra for testing calls to Ember warn|deprecate|assert (#6626) * [CHORE] adds infra for testing calls to Ember warn|deprecate|assert * fix production tests * address feedback * feedback on labels * remove id checks # This is the commit message #26: [CHORE] Refactor integration/multiple-stores-test.js in order to remove run loop usage (#6632) # This is the commit message #27: Bump ember-simple-tree from 0.7.0 to 0.7.1 Bumps [ember-simple-tree](https://github.com/btecu/ember-simple-tree) from 0.7.0 to 0.7.1. - [Release notes](https://github.com/btecu/ember-simple-tree/releases) - [Commits](https://github.com/btecu/ember-simple-tree/compare/0.7.0...0.7.1) Signed-off-by: dependabot-preview[bot] # This is the commit message #28: Bump ember-decorators-polyfill from 1.1.0 to 1.1.1 Bumps [ember-decorators-polyfill](https://github.com/pzuraq/ember-decorators-polyfill) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/pzuraq/ember-decorators-polyfill/releases) - [Commits](https://github.com/pzuraq/ember-decorators-polyfill/compare/1.1.0...1.1.1) Signed-off-by: dependabot-preview[bot] # This is the commit message #29: cleanup serializer documentation (#6575) # This is the commit message #30: ISSUE-6012: test: added test for meta property and bug fix. (#6640) # This is the commit message #31: [FEAT links] ensures full links object support for relationships (#6606) * [FEAT links] ensures full links object support for relationships * fix lint * add feature flags # This is the commit message #32: [BUGFIX release] Enable `store.createRecord` in FastBoot (#6568) * Add FastBoot test for store.createRecord Fails at the moment. * Enable store.createRecord in FastBoot Changes the V4 UUID generation to leverage `FastBoot.require` when possible. This currently requires that the host application add the following to their `package.json`: ``` "fastbootDependencies": [ "crypto" ] ``` * fix types # This is the commit message #33: [CHORE] rename and restructure packages to clarify unpublished/private status move unpublished packages into directories marked private move published but private into better naming convention move unpublished into better naming convention change -build-infra imports to private-build-infra larger re-org # This is the commit message #34: Bump eslint-config-prettier from 6.4.0 to 6.5.0 Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 6.4.0 to 6.5.0. - [Release notes](https://github.com/prettier/eslint-config-prettier/releases) - [Changelog](https://github.com/prettier/eslint-config-prettier/blob/master/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-config-prettier/compare/v6.4.0...v6.5.0) Signed-off-by: dependabot-preview[bot] # This is the commit message #35: Bump eslint from 6.5.1 to 6.6.0 Bumps [eslint](https://github.com/eslint/eslint) from 6.5.1 to 6.6.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v6.5.1...v6.6.0) Signed-off-by: dependabot-preview[bot] # This is the commit message #36: [CHORE] refactor: Remove runloop usage in destroy module of integration/storeā€¦ (#6646) * refactor: Remove runloop usage in destroy module of integration/store-test * fix linter errors # This is the commit message #37: Bump @types/ember__debug from 3.0.5 to 3.0.6 (#6647) Bumps [@types/ember__debug](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ember__debug) from 3.0.5 to 3.0.6. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/ember__debug) Signed-off-by: dependabot-preview[bot] # This is the commit message #38: Bump eslint-plugin-mocha from 6.2.0 to 6.2.1 Bumps [eslint-plugin-mocha](https://github.com/lo1tuma/eslint-plugin-mocha) from 6.2.0 to 6.2.1. - [Release notes](https://github.com/lo1tuma/eslint-plugin-mocha/releases) - [Changelog](https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/CHANGELOG.md) - [Commits](https://github.com/lo1tuma/eslint-plugin-mocha/compare/6.2.0...6.2.1) Signed-off-by: dependabot-preview[bot] # This is the commit message #39: Bump qunit-dom from 0.9.0 to 0.9.1 Bumps [qunit-dom](https://github.com/simplabs/qunit-dom) from 0.9.0 to 0.9.1. - [Release notes](https://github.com/simplabs/qunit-dom/releases) - [Changelog](https://github.com/simplabs/qunit-dom/blob/master/CHANGELOG.md) - [Commits](https://github.com/simplabs/qunit-dom/compare/v0.9.0...v0.9.1) Signed-off-by: dependabot-preview[bot] # This is the commit message #40: Bump @typescript-eslint/parser from 2.5.0 to 2.6.0 Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.5.0 to 2.6.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.6.0/packages/parser) Signed-off-by: dependabot-preview[bot] # This is the commit message #41: Bump @typescript-eslint/eslint-plugin from 2.5.0 to 2.6.0 Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 2.5.0 to 2.6.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.6.0/packages/eslint-plugin) Signed-off-by: dependabot-preview[bot] # This is the commit message #42: fix tracerbench command for renamed test app folder # This is the commit message #43: Setup har-remix # This is the commit message #44: replace server-replay with har-remix # This is the commit message #45: Use concurrently from node_modules instead of global installation # This is the commit message #46: wip # This is the commit message #47: Update bash script to use ember-data workspace for experiment # This is the commit message #48: relationship performance bash script updates # This is the commit message #49: removes line breaks # This is the commit message #50: removes .travis.yml from test app # This is the commit message #51: cleanup linting # This is the commit message #52: change eslint config # This is the commit message #53: cleanup # This is the commit message #54: remove comments # This is the commit message #55: updates azure-pipelines.yml # This is the commit message #56: adds tracerbench to github action workflow # This is the commit message #57: Update CI to install PM2 globally # This is the commit message #58: [CHORE] allow asserting all tests for deprecations (#6627) * [CHORE] configure the ability to filter deprecations from assertNoDeprecations * turn off helpers until tests are fixed # This is the commit message #59: [DOC] Close code block in the description # This is the commit message #60: Bump ember-qunit from 4.5.1 to 4.6.0 Bumps [ember-qunit](https://github.com/emberjs/ember-qunit) from 4.5.1 to 4.6.0. - [Release notes](https://github.com/emberjs/ember-qunit/releases) - [Changelog](https://github.com/emberjs/ember-qunit/blob/master/CHANGELOG.md) - [Commits](https://github.com/emberjs/ember-qunit/compare/v4.5.1...v4.6.0) Signed-off-by: dependabot-preview[bot] # This is the commit message #61: Bump ember-fetch from 6.7.1 to 6.7.2 Bumps [ember-fetch](https://github.com/ember-cli/ember-fetch) from 6.7.1 to 6.7.2. - [Release notes](https://github.com/ember-cli/ember-fetch/releases) - [Changelog](https://github.com/ember-cli/ember-fetch/blob/v6.7.2/CHANGELOG.md) - [Commits](https://github.com/ember-cli/ember-fetch/compare/v6.7.1...v6.7.2) Signed-off-by: dependabot-preview[bot] # This is the commit message #62: Bump ember-load-initializers from 2.1.0 to 2.1.1 Bumps [ember-load-initializers](https://github.com/ember-cli/ember-load-initializers) from 2.1.0 to 2.1.1. - [Release notes](https://github.com/ember-cli/ember-load-initializers/releases) - [Changelog](https://github.com/ember-cli/ember-load-initializers/blob/master/CHANGELOG.md) - [Commits](https://github.com/ember-cli/ember-load-initializers/compare/v2.1.0...v2.1.1) Signed-off-by: dependabot-preview[bot] # This is the commit message #63: Bump ember-source from 3.13.3 to 3.14.1 Bumps [ember-source](https://github.com/emberjs/ember.js) from 3.13.3 to 3.14.1. - [Release notes](https://github.com/emberjs/ember.js/releases) - [Changelog](https://github.com/emberjs/ember.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/emberjs/ember.js/compare/v3.13.3...v3.14.1) Signed-off-by: dependabot-preview[bot] # This is the commit message #64: Bump eslint-plugin-ember from 7.2.0 to 7.3.0 Bumps [eslint-plugin-ember](https://github.com/ember-cli/eslint-plugin-ember) from 7.2.0 to 7.3.0. - [Release notes](https://github.com/ember-cli/eslint-plugin-ember/releases) - [Changelog](https://github.com/ember-cli/eslint-plugin-ember/blob/master/CHANGELOG.md) - [Commits](https://github.com/ember-cli/eslint-plugin-ember/compare/v7.2.0...v7.3.0) Signed-off-by: dependabot-preview[bot] --- .eslintrc.js | 9 +- .github/workflows/main.yml | 14 + CHANGELOG.md | 21 + azure-pipelines.yml | 9 +- bin/lint-features | 5 +- bin/packages-for-commit.js | 4 +- bin/relationship-performance-check | 24 + package.json | 36 +- packages/-ember-data/ember-cli-build.js | 2 +- packages/-ember-data/index.js | 4 +- packages/-ember-data/package.json | 15 +- .../acceptance/relationships/has-many-test.js | 2 +- .../tests/helpers/deprecated-test.js | 20 +- .../helpers/qunit-asserts/assert-assertion.ts | 90 ++++ .../qunit-asserts/assert-deprecation.ts | 184 +++++++ .../helpers/qunit-asserts/assert-warning.ts | 170 ++++++ .../helpers/qunit-asserts/check-matcher.ts | 16 + .../tests/helpers/qunit-asserts/index.ts | 9 + .../qunit-asserts/utils/is-thenable.ts | 3 + .../tests/helpers/test-in-debug.js | 6 +- .../tests/helpers/watch-property.js | 2 +- .../adapter/record-persistence-test.js | 29 +- .../tests/integration/multiple-stores-test.js | 170 +++--- .../inverse-relationship-load-test.js | 90 +++- .../relationships/relationship-links-test.js | 356 +++++++++++++ .../tests/integration/store-test.js | 223 ++++---- packages/-ember-data/tests/test-helper.js | 52 +- .../tests/unit/promise-proxies-test.js | 71 ++- .../tests/unit/store/peek-record-test.js | 2 +- .../app/routes/person/new.js | 10 + .../app/templates/person/new.hbs | 6 + .../tests/fastboot/person/new-test.js | 16 + packages/adapter/addon/index.js | 4 + .../adapter/blueprints/adapter-test/index.js | 2 +- packages/adapter/blueprints/adapter/index.js | 4 +- packages/adapter/index.js | 2 +- .../node-tests/blueprints/adapter-test.js | 6 +- packages/adapter/package.json | 12 +- packages/canary-features/README.md | 2 +- ...efault-features.js => default-features.ts} | 3 +- .../addon/{index.js => index.ts} | 15 +- packages/canary-features/package.json | 3 +- packages/debug/index.js | 2 +- packages/debug/package.json | 12 +- packages/model/blueprints/model-test/index.js | 2 +- packages/model/blueprints/model/index.js | 2 +- packages/model/index.js | 2 +- .../model/node-tests/blueprints/model-test.js | 6 +- packages/model/package.json | 12 +- .../.npmignore | 0 .../.watchmanconfig | 0 .../LICENSE.md | 0 .../README.md | 2 +- .../config/in-progress-features.json | 0 .../unit/babel-plugin-remove-imports-test.js | 0 .../package.json | 2 +- .../addon-build-config-for-data-package.js | 0 .../src/cli-flags.js | 0 .../src/create-version-module.js | 0 .../src/debug-macros.js | 0 .../src/features.js | 2 +- .../src/stripped-build-plugins.js | 0 .../transforms/babel-plugin-remove-imports.js | 0 .../src/transforms/package.json | 0 .../src/utilities/edition-detector.js | 0 .../extend-from-application-entity.js | 0 .../src/utilities/rollup-private-module.js | 0 .../src/utilities/test-framework-detector.js | 0 .../record-data/addon/-private/coerce-id.ts | 2 +- .../record-data/addon/-private/record-data.ts | 2 +- .../relationships/state/belongs-to.ts | 6 +- .../-private/relationships/state/has-many.ts | 6 +- .../relationships/state/relationship.ts | 46 +- packages/record-data/index.js | 2 +- packages/record-data/package.json | 12 +- packages/serializer/addon/index.js | 1 - .../blueprints/serializer-test/index.js | 2 +- .../serializer/blueprints/serializer/index.js | 4 +- .../blueprints/transform-test/index.js | 2 +- .../serializer/blueprints/transform/index.js | 2 +- packages/serializer/index.js | 2 +- .../node-tests/blueprints/serializer-test.js | 6 +- .../node-tests/blueprints/transform-test.js | 6 +- packages/serializer/package.json | 12 +- .../-private/identifiers/utils/uuid-v4.ts | 26 +- .../store/addon/-private/system/coerce-id.ts | 2 +- .../store/addon/-private/system/many-array.js | 8 +- .../-private/system/model/internal-model.ts | 4 +- .../addon/-private/system/model/states.js | 4 + .../addon/-private/system/promise-proxies.js | 5 +- .../-private/system/references/reference.ts | 34 +- .../-private/system/snapshot-record-array.js | 1 + .../addon/-private/system/store/finders.js | 10 +- .../minimum-serializer-interface.ts | 95 ++-- packages/store/index.js | 2 +- packages/store/package.json | 12 +- packages/store/types/fastboot/index.d.ts | 4 + packages/store/types/qunit/index.d.ts | 20 +- .../.editorconfig | 0 .../.ember-cli | 0 .../.gitignore | 0 .../.template-lintrc.js | 0 .../.watchmanconfig | 0 .../README.md | 0 .../app/app.js | 0 .../app/components/.gitkeep | 0 .../app/controllers/.gitkeep | 0 .../app/helpers/.gitkeep | 0 .../app/index.html | 0 .../app/models/.gitkeep | 0 .../app/resolver.js | 0 .../app/router.js | 0 .../app/routes/.gitkeep | 0 .../app/styles/app.css | 0 .../app/templates/application.hbs | 0 .../app/templates/components/.gitkeep | 0 .../config/environment.js | 0 .../config/optional-features.json | 0 .../config/targets.js | 0 .../ember-cli-build.js | 0 .../package.json | 14 +- .../public/robots.txt | 0 .../testem.js | 0 .../tests/helpers/.gitkeep | 0 .../tests/index.html | 0 .../tests/integration/.gitkeep | 0 .../tests/integration/smoke-test.js | 0 .../tests/test-helper.js | 0 .../tests/unit/.gitkeep | 0 .../vendor/.gitkeep | 0 .../.editorconfig | 0 .../.ember-cli | 0 .../.gitignore | 0 .../.template-lintrc.js | 0 .../.watchmanconfig | 0 .../README.md | 0 .../app/app.js | 0 .../app/components/.gitkeep | 0 .../app/controllers/.gitkeep | 0 .../app/helpers/.gitkeep | 0 .../app/index.html | 0 .../app/models/.gitkeep | 0 .../app/resolver.js | 0 .../app/router.js | 0 .../app/routes/.gitkeep | 0 .../app/styles/app.css | 0 .../app/templates/application.hbs | 0 .../app/templates/components/.gitkeep | 0 .../config/environment.js | 0 .../config/optional-features.json | 0 .../config/targets.js | 0 .../ember-cli-build.js | 0 .../package.json | 14 +- .../public/robots.txt | 0 .../testem.js | 0 .../tests/helpers/.gitkeep | 0 .../tests/index.html | 0 .../tests/integration/.gitkeep | 0 .../tests/integration/smoke-test.js | 0 .../tests/test-helper.js | 0 .../tests/unit/.gitkeep | 0 .../vendor/.gitkeep | 0 .../.editorconfig | 0 .../.ember-cli | 0 .../.gitignore | 0 .../.template-lintrc.js | 0 .../.watchmanconfig | 0 .../README.md | 0 .../app/adapters/application.ts | 0 .../app/app.ts | 0 .../app/config/environment.d.ts | 0 .../app/helpers/.gitkeep | 0 .../app/index.html | 0 .../app/models/.gitkeep | 0 .../app/models/person.js | 0 .../app/resolver.ts | 0 .../app/router.ts | 6 +- .../app/routes/.gitkeep | 0 .../app/routes/index.js | 0 .../app/serializers/application.ts | 0 .../app/styles/app.css | 0 .../app/templates/.gitkeep | 0 .../app/templates/application.hbs | 0 .../app/templates/index.hbs | 0 .../config/environment.js | 0 .../config/optional-features.json | 0 .../config/targets.js | 0 .../ember-cli-build.js | 0 .../package.json | 21 +- .../public/robots.txt | 0 .../testem.js | 0 .../tests/fastboot/index-test.js | 0 .../tests/helpers/.gitkeep | 0 .../tests/index.html | 0 .../tests/integration/.gitkeep | 0 .../tests/test-helper.js | 0 .../tests/unit/.gitkeep | 0 .../tsconfig.json | 0 .../types/fastboot-test-app/index.d.ts | 0 .../types/global.d.ts | 0 .../vendor/.gitkeep | 0 .../.editorconfig | 0 .../.gitignore | 0 .../.template-lintrc.js | 0 .../.watchmanconfig | 0 .../README.md | 0 .../app/app.js | 0 .../app/components/.gitkeep | 0 .../app/controllers/.gitkeep | 0 .../app/helpers/.gitkeep | 0 .../app/index.html | 0 .../app/models/.gitkeep | 0 .../app/resolver.js | 0 .../app/router.js | 0 .../app/routes/.gitkeep | 0 .../app/styles/app.css | 0 .../app/templates/application.hbs | 0 .../app/templates/components/.gitkeep | 0 .../config/environment.js | 0 .../config/optional-features.json | 0 .../config/targets.js | 0 .../ember-cli-build.js | 0 .../package.json | 14 +- .../public/robots.txt | 0 .../testem.js | 0 .../tests/helpers/.gitkeep | 0 .../tests/index.html | 0 .../tests/integration/.gitkeep | 0 .../tests/integration/smoke-test.js | 0 .../tests/test-helper.js | 0 .../tests/unit/.gitkeep | 0 .../vendor/.gitkeep | 0 .../.editorconfig | 0 .../.ember-cli | 0 .../.gitignore | 0 .../.template-lintrc.js | 0 .../.watchmanconfig | 0 .../README.md | 0 .../app/app.js | 0 .../app/components/.gitkeep | 0 .../app/controllers/.gitkeep | 0 .../app/helpers/.gitkeep | 0 .../app/index.html | 0 .../app/models/.gitkeep | 0 .../app/resolver.js | 0 .../app/router.js | 0 .../app/routes/.gitkeep | 0 .../app/styles/app.css | 0 .../app/templates/application.hbs | 0 .../app/templates/components/.gitkeep | 0 .../config/environment.js | 0 .../config/optional-features.json | 0 .../config/targets.js | 0 .../ember-cli-build.js | 0 .../package.json | 14 +- .../public/robots.txt | 0 .../testem.js | 0 .../tests/helpers/.gitkeep | 0 .../tests/index.html | 0 .../tests/integration/.gitkeep | 0 .../tests/integration/smoke-test.js | 0 .../tests/test-helper.js | 0 .../tests/unit/.gitkeep | 0 .../vendor/.gitkeep | 0 .../.gitignore | 2 + .../.travis.yml | 24 - .../PERFORMANCE_BENCHMARKING.md | 9 +- .../bin/har-remix.js | 42 ++ .../bin/localhost.har | 482 ++++++++++++------ .../bin/tracerbench.js | 15 +- .../ember-cli-build.js | 4 +- .../package.json | 18 +- .../.editorconfig | 0 .../.ember-cli | 0 .../.gitignore | 0 .../.template-lintrc.js | 0 .../.watchmanconfig | 0 .../README.md | 0 .../app/app.js | 0 .../app/components/.gitkeep | 0 .../app/controllers/.gitkeep | 0 .../app/helpers/.gitkeep | 0 .../app/index.html | 0 .../app/models/.gitkeep | 0 .../app/resolver.js | 0 .../app/router.js | 0 .../app/routes/.gitkeep | 0 .../app/services/store.js | 0 .../app/styles/app.css | 0 .../app/templates/application.hbs | 0 .../app/templates/components/.gitkeep | 0 .../config/environment.js | 0 .../config/optional-features.json | 0 .../config/targets.js | 0 .../ember-cli-build.js | 0 .../package.json | 15 +- .../public/robots.txt | 0 .../testem.js | 0 .../tests/helpers/.gitkeep | 0 .../tests/helpers/test-in-debug.js | 0 .../tests/index.html | 0 .../tests/integration/.gitkeep | 0 .../tests/integration/create-record-test.js | 0 .../tests/integration/delete-record-test.js | 0 .../tests/integration/errors-test.js | 0 .../tests/integration/normalize-test.js | 2 +- .../tests/integration/push-payload-test.js | 2 +- .../tests/integration/relationships-test.js | 0 .../tests/integration/requests-test.js | 0 .../tests/integration/serialize-test.js | 0 .../tests/integration/smoke-test.js | 0 .../tests/integration/update-record-test.js | 0 .../tests/test-helper.js | 0 .../tests/unit/.gitkeep | 0 .../vendor/.gitkeep | 0 .../.npmignore | 0 .../.watchmanconfig | 0 .../LICENSE.md | 0 .../README.md | 2 +- .../package.json | 3 +- .../src/node-test-helpers/fixture.js | 0 .../generate-fake-package-manifest.js | 0 .../setup-test-environment.js | 0 yarn.lock | 461 ++++++++++++----- 324 files changed, 2461 insertions(+), 810 deletions(-) create mode 100755 bin/relationship-performance-check create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/assert-assertion.ts create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/assert-deprecation.ts create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/assert-warning.ts create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/check-matcher.ts create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/index.ts create mode 100644 packages/-ember-data/tests/helpers/qunit-asserts/utils/is-thenable.ts create mode 100644 packages/-ember-data/tests/integration/relationships/relationship-links-test.js create mode 100644 packages/-fastboot-test-app/app/routes/person/new.js create mode 100644 packages/-fastboot-test-app/app/templates/person/new.hbs create mode 100644 packages/-fastboot-test-app/tests/fastboot/person/new-test.js rename packages/canary-features/addon/{default-features.js => default-features.ts} (90%) rename packages/canary-features/addon/{index.js => index.ts} (61%) rename packages/{-build-infra => private-build-infra}/.npmignore (100%) rename packages/{-adapter-encapsulation-test-app => private-build-infra}/.watchmanconfig (100%) rename packages/{-build-infra => private-build-infra}/LICENSE.md (100%) rename packages/{-build-infra => private-build-infra}/README.md (90%) rename packages/{-build-infra => private-build-infra}/config/in-progress-features.json (100%) rename packages/{-build-infra => private-build-infra}/node-tests/unit/babel-plugin-remove-imports-test.js (100%) rename packages/{-build-infra => private-build-infra}/package.json (97%) rename packages/{-build-infra => private-build-infra}/src/addon-build-config-for-data-package.js (100%) rename packages/{-build-infra => private-build-infra}/src/cli-flags.js (100%) rename packages/{-build-infra => private-build-infra}/src/create-version-module.js (100%) rename packages/{-build-infra => private-build-infra}/src/debug-macros.js (100%) rename packages/{-build-infra => private-build-infra}/src/features.js (95%) rename packages/{-build-infra => private-build-infra}/src/stripped-build-plugins.js (100%) rename packages/{-build-infra => private-build-infra}/src/transforms/babel-plugin-remove-imports.js (100%) rename packages/{-build-infra => private-build-infra}/src/transforms/package.json (100%) rename packages/{-build-infra => private-build-infra}/src/utilities/edition-detector.js (100%) rename packages/{-build-infra => private-build-infra}/src/utilities/extend-from-application-entity.js (100%) rename packages/{-build-infra => private-build-infra}/src/utilities/rollup-private-module.js (100%) rename packages/{-build-infra => private-build-infra}/src/utilities/test-framework-detector.js (100%) create mode 100644 packages/store/types/fastboot/index.d.ts rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/.editorconfig (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/.ember-cli (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/.gitignore (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/.template-lintrc.js (100%) rename packages/{-build-infra => unpublished-adapter-encapsulation-test-app}/.watchmanconfig (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/README.md (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/app.js (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/components/.gitkeep (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/controllers/.gitkeep (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/helpers/.gitkeep (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/index.html (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/models/.gitkeep (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/resolver.js (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/router.js (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/routes/.gitkeep (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/styles/app.css (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/templates/application.hbs (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/app/templates/components/.gitkeep (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/config/environment.js (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/config/optional-features.json (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/config/targets.js (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/ember-cli-build.js (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/package.json (85%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/public/robots.txt (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/testem.js (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/tests/helpers/.gitkeep (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/tests/index.html (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/tests/integration/.gitkeep (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/tests/integration/smoke-test.js (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/tests/test-helper.js (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/tests/unit/.gitkeep (100%) rename packages/{-adapter-encapsulation-test-app => unpublished-adapter-encapsulation-test-app}/vendor/.gitkeep (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/.editorconfig (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/.ember-cli (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/.gitignore (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/.template-lintrc.js (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/.watchmanconfig (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/README.md (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/app.js (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/components/.gitkeep (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/controllers/.gitkeep (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/helpers/.gitkeep (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/index.html (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/models/.gitkeep (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/resolver.js (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/router.js (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/routes/.gitkeep (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/styles/app.css (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/templates/application.hbs (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/app/templates/components/.gitkeep (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/config/environment.js (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/config/optional-features.json (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/config/targets.js (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/ember-cli-build.js (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/package.json (85%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/public/robots.txt (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/testem.js (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/tests/helpers/.gitkeep (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/tests/index.html (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/tests/integration/.gitkeep (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/tests/integration/smoke-test.js (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/tests/test-helper.js (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/tests/unit/.gitkeep (100%) rename packages/{-debug-encapsulation-test-app => unpublished-debug-encapsulation-test-app}/vendor/.gitkeep (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/.editorconfig (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/.ember-cli (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/.gitignore (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/.template-lintrc.js (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/.watchmanconfig (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/README.md (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/adapters/application.ts (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/app.ts (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/config/environment.d.ts (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/helpers/.gitkeep (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/index.html (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/models/.gitkeep (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/models/person.js (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/resolver.ts (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/router.ts (70%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/routes/.gitkeep (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/routes/index.js (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/serializers/application.ts (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/styles/app.css (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/templates/.gitkeep (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/templates/application.hbs (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/app/templates/index.hbs (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/config/environment.js (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/config/optional-features.json (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/config/targets.js (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/ember-cli-build.js (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/package.json (82%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/public/robots.txt (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/testem.js (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/tests/fastboot/index-test.js (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/tests/helpers/.gitkeep (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/tests/index.html (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/tests/integration/.gitkeep (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/tests/test-helper.js (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/tests/unit/.gitkeep (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/tsconfig.json (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/types/fastboot-test-app/index.d.ts (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/types/global.d.ts (100%) rename packages/{-fastboot-test-app => unpublished-fastboot-test-app}/vendor/.gitkeep (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/.editorconfig (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/.gitignore (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/.template-lintrc.js (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/.watchmanconfig (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/README.md (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/app.js (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/components/.gitkeep (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/controllers/.gitkeep (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/helpers/.gitkeep (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/index.html (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/models/.gitkeep (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/resolver.js (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/router.js (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/routes/.gitkeep (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/styles/app.css (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/templates/application.hbs (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/app/templates/components/.gitkeep (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/config/environment.js (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/config/optional-features.json (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/config/targets.js (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/ember-cli-build.js (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/package.json (85%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/public/robots.txt (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/testem.js (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/tests/helpers/.gitkeep (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/tests/index.html (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/tests/integration/.gitkeep (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/tests/integration/smoke-test.js (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/tests/test-helper.js (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/tests/unit/.gitkeep (100%) rename packages/{-model-encapsulation-test-app => unpublished-model-encapsulation-test-app}/vendor/.gitkeep (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/.editorconfig (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/.ember-cli (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/.gitignore (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/.template-lintrc.js (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/.watchmanconfig (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/README.md (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/app.js (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/components/.gitkeep (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/controllers/.gitkeep (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/helpers/.gitkeep (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/index.html (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/models/.gitkeep (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/resolver.js (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/router.js (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/routes/.gitkeep (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/styles/app.css (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/templates/application.hbs (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/app/templates/components/.gitkeep (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/config/environment.js (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/config/optional-features.json (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/config/targets.js (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/ember-cli-build.js (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/package.json (85%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/public/robots.txt (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/testem.js (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/tests/helpers/.gitkeep (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/tests/index.html (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/tests/integration/.gitkeep (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/tests/integration/smoke-test.js (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/tests/test-helper.js (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/tests/unit/.gitkeep (100%) rename packages/{-record-data-encapsulation-test-app => unpublished-record-data-encapsulation-test-app}/vendor/.gitkeep (100%) delete mode 100644 packages/unpublished-relationship-performance-test-app/.travis.yml create mode 100644 packages/unpublished-relationship-performance-test-app/bin/har-remix.js rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/.editorconfig (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/.ember-cli (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/.gitignore (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/.template-lintrc.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/.watchmanconfig (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/README.md (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/app.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/components/.gitkeep (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/controllers/.gitkeep (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/helpers/.gitkeep (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/index.html (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/models/.gitkeep (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/resolver.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/router.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/routes/.gitkeep (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/services/store.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/styles/app.css (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/templates/application.hbs (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/app/templates/components/.gitkeep (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/config/environment.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/config/optional-features.json (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/config/targets.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/ember-cli-build.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/package.json (83%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/public/robots.txt (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/testem.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/helpers/.gitkeep (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/helpers/test-in-debug.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/index.html (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/integration/.gitkeep (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/integration/create-record-test.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/integration/delete-record-test.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/integration/errors-test.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/integration/normalize-test.js (98%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/integration/push-payload-test.js (98%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/integration/relationships-test.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/integration/requests-test.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/integration/serialize-test.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/integration/smoke-test.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/integration/update-record-test.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/test-helper.js (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/tests/unit/.gitkeep (100%) rename packages/{-serializer-encapsulation-test-app => unpublished-serializer-encapsulation-test-app}/vendor/.gitkeep (100%) rename packages/{-test-infra => unpublished-test-infra}/.npmignore (100%) rename packages/{-test-infra => unpublished-test-infra}/.watchmanconfig (100%) rename packages/{-test-infra => unpublished-test-infra}/LICENSE.md (100%) rename packages/{-test-infra => unpublished-test-infra}/README.md (90%) rename packages/{-test-infra => unpublished-test-infra}/package.json (86%) rename packages/{-test-infra => unpublished-test-infra}/src/node-test-helpers/fixture.js (100%) rename packages/{-test-infra => unpublished-test-infra}/src/node-test-helpers/generate-fake-package-manifest.js (100%) rename packages/{-test-infra => unpublished-test-infra}/src/node-test-helpers/setup-test-environment.js (100%) diff --git a/.eslintrc.js b/.eslintrc.js index f7bc9c90bde..382f20680fd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -57,8 +57,9 @@ module.exports = { '.eslintrc.js', '.prettierrc.js', 'bin/*', - 'packages/-build-infra/src/**/*.js', - 'packages/-test-infra/src/**/*.js', + 'packages/private-build-infra/src/**/*.js', + 'packages/unpublished-relationship-performance-test-app/bin/*.js', + 'packages/unpublished-test-infra/src/**/*.js', 'packages/*/.ember-cli.js', 'packages/*/.eslintrc.js', 'packages/*/.template-lintrc.js', @@ -91,7 +92,7 @@ module.exports = { // node tests { - files: ['packages/*/node-tests/**', 'packages/-test-infra/src/node-test-helpers/**/*'], + files: ['packages/*/node-tests/**', 'packages/unpublished-test-infra/src/node-test-helpers/**/*'], env: { mocha: true, }, @@ -108,7 +109,7 @@ module.exports = { // bin files { - files: ['bin/*'], + files: ['bin/*', 'packages/unpublished-relationship-performance-test-app/bin/*'], // eslint-disable-next-line node/no-unpublished-require rules: Object.assign({}, require('eslint-plugin-node').configs.recommended.rules, { 'no-console': 'off', diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bbb49682794..a64197f9767 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -185,3 +185,17 @@ jobs: CI: true run: yarn test-external:${{ matrix.partner }} continue-on-error: ${{ matrix['continue-on-error'] == true }} + + performance: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - uses: actions/setup-node@v1 + with: + node-version: 12.x + - name: TracerBench CLI Install + run: yarn global add tracerbench + - name: PM2 CLI Install + run: yarn global add pm2 + - name: TracerBench Compare + run: ./bin/relationship-performance-check diff --git a/CHANGELOG.md b/CHANGELOG.md index de33cee15b0..8345362df7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,27 @@ ### Master +## Release 3.13.1 (September 24, 2019) + +- [0ff38fb1](https://github.com/emberjs/data/commit/0ff38fb1c0a8d75c7ad03f5dc8eaf8193d7f6e80) [DOC serializer] implements MinimumSerializerInterface (#6451) (#6499) + +## Release 3.13.0 (September 20, 2019) + +- [b29baa17](https://github.com/emberjs/data/commit/b29baa176f91b87ffc28a0c11c2fdd1c079e5ad9) [DOCS BETA RELEASE] Fix @ember-data/model package is blank (#6444) (#6445) +- [8320ff4c](https://github.com/emberjs/data/commit/8320ff4c51012631af3af2ff50aa0ca679402b3f) [BUGFIX BETA RELEASE] Fix missing @babel/plugin-transform-block-scoping dependency (#6432) +- [d7454364](https://github.com/emberjs/data/commit/d7454364e262743206d86a9b88607d03fe4ae46f) [BUGFIX BETA] ensure produced artifacts correctly lock with each other (#6309) +- [a029725f](https://github.com/emberjs/data/commit/a029725f7372bae73b8cfbda307c3d2569b45b07) [BUGFIX beta] Fix Rollup warning about unresolved dependency +- [69749b86](https://github.com/emberjs/data/commit/69749b86fe7d3effea974edf0b12fc4316e02ebf) [BUGFIX release beta canary] Fix Model lifecycle event deprecations +- [#6312](https://github.com/emberjs/data/pull/6312) [BETA] Add environment variable to opt-out of rolling up `-private` (#6312) +- [#6292](https://github.com/emberjs/data/pull/6292) chore: ensure * deps are hoisted (#6292) +- [#6337](https://github.com/emberjs/data/pull/6337) [CHORE] fix test observers to match ember canary changes (#6337) +- [#6411](https://github.com/emberjs/data/pull/6411) [BUGFIX beta] Adds support for parenless attr, belongsTo, and hasMany (#6339) +- [#6434](https://github.com/emberjs/data/pull/6434) [BUGFIX BETA RELEASE] make fetch function JIT (#6430) (#6434) +- [#6436](https://github.com/emberjs/data/pull/6436) fix: Strip Symbol from production builds (#6389) (#6436) +- [#6452](https://github.com/emberjs/data/pull/6452) [BUGFIX beta] Update edition detection logic. +- [#6334](https://github.com/emberjs/data/pull/6334) [BUGFIX BETA CANARY] usage of recordDataFor for client side create needs to be in correct cache +- [#6430](https://github.com/emberjs/data/pull/6430) [BUGFIX BETA RELEASE] make fetch function JIT + ## Release 3.12.3 (LTS) (September 20, 2019) - [#6441](https://github.com/emberjs/data/pull/6441) [BUGFIX] Await potentially async operations (#6441) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4a91590d1e1..1c88c2d67d6 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -26,10 +26,13 @@ jobs: versionSpec: '12.x' # The version we're installing - script: | yarn global add tracerbench - displayName: Tracerbench CLI Install + displayName: TracerBench CLI Install - script: | - yarn run tracerbench:compare - displayName: Tracerbench Compare + yarn global add pm2 + displayName: PM2 CLI Install + - script: | + ./bin/relationship-performance-check + displayName: TracerBench Compare - job: Lint dependsOn: Performance diff --git a/bin/lint-features b/bin/lint-features index adbd634940c..e13272799c5 100755 --- a/bin/lint-features +++ b/bin/lint-features @@ -2,10 +2,7 @@ const fs = require('fs'); const path = require('path'); -const configPath = path.join( - __dirname, - '../packages/-build-infra/config/in-progress-features.json' -); +const configPath = path.join(__dirname, '../packages/private-build-infra/config/in-progress-features.json'); const beginsWithDS = /^ds-/; const violations = []; diff --git a/bin/packages-for-commit.js b/bin/packages-for-commit.js index f925cdea217..7e930c487f1 100644 --- a/bin/packages-for-commit.js +++ b/bin/packages-for-commit.js @@ -8,9 +8,9 @@ project without publishing the commit to a registry. The tarballs produced will reference each other appropriately. For instance - if `@ember-data/store` has a dependency on `@ember-data/-build-infra` the + if `@ember-data/store` has a dependency on `@ember-data/private-build-infra` the tarball for `@ember-data/store` will have a package.json file whose version - of `@ember-data/-build-infra` is the tarball for the commit for that package. + of `@ember-data/private-build-infra` is the tarball for the commit for that package. */ 'use strict'; diff --git a/bin/relationship-performance-check b/bin/relationship-performance-check new file mode 100755 index 00000000000..fb95b4b2077 --- /dev/null +++ b/bin/relationship-performance-check @@ -0,0 +1,24 @@ +#!/bin/bash + +APP_PATH=packages/unpublished-relationship-performance-test-app +HAR_REMIX_SCRIPT="$APP_PATH/bin/har-remix.js" +WORKSPACE=relationship-performance-test-app +CONTROl_BRANCH=master +EXPERIMENT_BRANCH=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p') + +git checkout $CONTROl_BRANCH + +if test -f $HAR_REMIX_SCRIPT; then + yarn install + yarn workspace $WORKSPACE ember build -e production --output-path dist-control + git checkout $EXPERIMENT_BRANCH + yarn install + yarn workspace $WORKSPACE ember build -e production --output-path dist-experiment + HR_PORT=4200 HR_GROUP=control pm2 start $HAR_REMIX_SCRIPT --name control + HR_PORT=4201 HR_GROUP=experiment pm2 start $HAR_REMIX_SCRIPT --name experiment + yarn workspace $WORKSPACE tracerbench:compare + pm2 kill +else + echo "har-remix.js does not exist on the $CONTROl_BRANCH branch" + git checkout $EXPERIMENT_BRANCH +fi \ No newline at end of file diff --git a/package.json b/package.json index 39aee70d018..6df60e358d2 100644 --- a/package.json +++ b/package.json @@ -35,23 +35,21 @@ "test-external:factory-guy": "./bin/test-external-partner-project.js factory-guy https://github.com/danielspaniel/ember-data-factory-guy.git", "test-external:ilios-frontend": "./bin/test-external-partner-project.js ilios-frontend https://github.com/ilios/frontend.git --skip-smoke-test", "test-external:ember-resource-metadata": "./bin/test-external-partner-project.js ember-resource-metadata https://github.com/ef4/ember-resource-metadata.git", - "test-external:ember-data-relationship-tracker": "./bin/test-external-partner-project.js ember-data-relationship-tracker https://github.com/ef4/ember-data-relationship-tracker.git", - "tracerbench": "concurrently 'server-replay ./packages/-$APP/bin/localhost.har --port 4200' 'yarn workspace $APP tracerbench:compare' --kill-others --success first" + "test-external:ember-data-relationship-tracker": "./bin/test-external-partner-project.js ember-data-relationship-tracker https://github.com/ef4/ember-data-relationship-tracker.git" }, "devDependencies": { "@babel/plugin-transform-typescript": "^7.6.3", - "@ember/optional-features": "^1.0.0", - "@tracerbench/core": "^2.3.0", + "@ember/optional-features": "^1.1.0", "@types/ember": "^3.1.1", "@types/ember-qunit": "^3.4.7", "@types/ember-test-helpers": "~1.0.6", "@types/ember-testing-helpers": "~0.0.3", - "@types/ember__debug": "3.0.5", + "@types/ember__debug": "3.0.6", "@types/ember__test-helpers": "~0.7.9", "@types/qunit": "^2.5.3", "@types/rsvp": "^4.0.3", - "@typescript-eslint/eslint-plugin": "^2.5.0", - "@typescript-eslint/parser": "^2.5.0", + "@typescript-eslint/eslint-plugin": "^2.6.0", + "@typescript-eslint/parser": "^2.6.0", "babel-eslint": "^10.0.3", "babel-plugin-debug-macros": "^0.3.3", "babel-plugin-feature-flags": "^0.3.1", @@ -94,29 +92,27 @@ "ember-cli-version-checker": "^3.1.2", "ember-cli-yuidoc": "^0.8.8", "ember-compatibility-helpers": "^1.2.0", - "ember-decorators-polyfill": "^1.1.0", + "ember-decorators-polyfill": "^1.1.1", "ember-disable-prototype-extensions": "^1.1.3", "ember-export-application-global": "^2.0.0", - "ember-fetch": "^6.7.1", - "ember-load-initializers": "^2.1.0", + "ember-fetch": "^6.7.2", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", - "ember-qunit-assert-helpers": "^0.2.2", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-simple-tree": "^0.7.0", - "ember-source": "^3.13.3", + "ember-simple-tree": "^0.7.1", + "ember-source": "^3.14.1", "ember-source-channel-url": "^2.0.1", "ember-try": "^1.2.1", - "eslint": "^6.5.1", - "eslint-config-prettier": "^6.4.0", - "eslint-plugin-ember": "^7.2.0", - "eslint-plugin-mocha": "^6.2.0", + "eslint": "^6.6.0", + "eslint-config-prettier": "^6.5.0", + "eslint-plugin-ember": "^7.3.0", + "eslint-plugin-mocha": "^6.2.1", "eslint-plugin-node": "^10.0.0", "eslint-plugin-prettier": "^3.1.1", "eslint-plugin-qunit": "^4.0.0", "execa": "^3.2.0", "fromentries": "^1.2.0", - "fs-extra": "^8.1.0", "git-repo-info": "^2.1.1", "github": "^1.1.1", "glob": "^7.1.5", @@ -128,7 +124,7 @@ "pre-commit": "^1.2.2", "prettier": "~1.18.2", "qunit": "^2.9.3", - "qunit-dom": "^0.9.0", + "qunit-dom": "^0.9.1", "rimraf": "^3.0.0", "rsvp": "^4.8.5", "semver": "^6.2.0", diff --git a/packages/-ember-data/ember-cli-build.js b/packages/-ember-data/ember-cli-build.js index a47da076b2a..99732d4e727 100644 --- a/packages/-ember-data/ember-cli-build.js +++ b/packages/-ember-data/ember-cli-build.js @@ -7,7 +7,7 @@ module.exports = function(defaults) { babel: { // this ensures that the same `@ember-data/canary-features` processing that the various // ember-data addons do is done in the dummy app - plugins: [...require('@ember-data/-build-infra/src/debug-macros')()], + plugins: [...require('@ember-data/private-build-infra/src/debug-macros')()], }, 'ember-cli-babel': { throwUnlessParallelizable: true, diff --git a/packages/-ember-data/index.js b/packages/-ember-data/index.js index 63df18138c5..0b177d0974e 100644 --- a/packages/-ember-data/index.js +++ b/packages/-ember-data/index.js @@ -1,8 +1,8 @@ 'use strict'; -const addonBuildConfigForDataPackage = require('@ember-data/-build-infra/src/addon-build-config-for-data-package'); +const addonBuildConfigForDataPackage = require('@ember-data/private-build-infra/src/addon-build-config-for-data-package'); const addonBaseConfig = addonBuildConfigForDataPackage('ember-data'); -const version = require('@ember-data/-build-infra/src/create-version-module'); +const version = require('@ember-data/private-build-infra/src/create-version-module'); const merge = require('broccoli-merge-trees'); module.exports = Object.assign({}, addonBaseConfig, { diff --git a/packages/-ember-data/package.json b/packages/-ember-data/package.json index 894c35e911a..abfcaa1f4b1 100644 --- a/packages/-ember-data/package.json +++ b/packages/-ember-data/package.json @@ -23,7 +23,7 @@ "author": "", "license": "MIT", "dependencies": { - "@ember-data/-build-infra": "3.15.0-alpha.1", + "@ember-data/private-build-infra": "3.15.0-alpha.1", "@ember-data/adapter": "3.15.0-alpha.1", "@ember-data/debug": "3.15.0-alpha.1", "@ember-data/model": "3.15.0-alpha.1", @@ -39,12 +39,12 @@ }, "devDependencies": { "@babel/plugin-transform-typescript": "^7.6.3", - "@ember/optional-features": "^1.0.0", + "@ember/optional-features": "^1.1.0", "@types/ember": "^3.1.1", "@types/ember-qunit": "^3.4.7", "@types/ember-test-helpers": "~1.0.6", "@types/ember-testing-helpers": "~0.0.3", - "@types/ember__debug": "3.0.5", + "@types/ember__debug": "3.0.6", "@types/ember__test-helpers": "~0.7.9", "@types/qunit": "^2.5.3", "@types/rsvp": "^4.0.3", @@ -68,15 +68,14 @@ "ember-cli-uglify": "3.0.0", "ember-cli-yuidoc": "^0.8.8", "ember-compatibility-helpers": "^1.2.0", - "ember-decorators-polyfill": "^1.1.0", + "ember-decorators-polyfill": "^1.1.1", "ember-disable-prototype-extensions": "^1.1.3", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", - "ember-qunit-assert-helpers": "^0.2.2", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", + "ember-source": "^3.14.1", "ember-source-channel-url": "^2.0.1", "ember-try": "^1.2.1", "github": "^1.1.1", diff --git a/packages/-ember-data/tests/acceptance/relationships/has-many-test.js b/packages/-ember-data/tests/acceptance/relationships/has-many-test.js index e386719a15e..fbf5d5717c3 100644 --- a/packages/-ember-data/tests/acceptance/relationships/has-many-test.js +++ b/packages/-ember-data/tests/acceptance/relationships/has-many-test.js @@ -457,7 +457,7 @@ module('async has-many rendering tests', function(hooks) { assert.equal(!!RelationshipPromiseCache['children'], false, 'The relationship has no fetch promise'); assert.equal(!!RelationshipProxyCache['children'], true, 'The relationship has a promise proxy'); assert.equal(relationshipState.hasFailedLoadAttempt === true, true, 'The relationship has attempted a load'); - assert.equal(!!relationshipState.link, true, 'The relationship has a link'); + assert.equal(!!(relationshipState.links && relationshipState.links.related), true, 'The relationship has a link'); Ember.onerror = originalOnError; }); diff --git a/packages/-ember-data/tests/helpers/deprecated-test.js b/packages/-ember-data/tests/helpers/deprecated-test.js index d486a3293c9..25bf20ccd67 100644 --- a/packages/-ember-data/tests/helpers/deprecated-test.js +++ b/packages/-ember-data/tests/helpers/deprecated-test.js @@ -1,5 +1,11 @@ import { test } from 'qunit'; import VERSION from 'ember-data/version'; +import { DEBUG } from '@glimmer/env'; + +// temporary so that we can split out test fixes +// from landing this. If working locally turn this +// on to have tests fail that require being fixed. +export const SHOULD_ASSERT_ALL = false; // small comparison function for major and minor semver values function gte(EDVersion, DeprecationVersion) { @@ -22,8 +28,20 @@ export function deprecatedTest(testName, deprecation, testCallback) { throw new Error(`deprecatedTest expects { id } to be a meaningful string`); } + async function interceptor(assert) { + await testCallback.call(this, assert); + if (DEBUG) { + if (SHOULD_ASSERT_ALL) { + if (typeof assert.test.expected === 'number') { + assert.test.expected += 1; + } + assert.expectDeprecation(deprecation); + } + } + } + if (gte(VERSION, deprecation.until)) { - test(`DEPRECATION ${deprecation.id} until ${deprecation.until} | ${testName}`, testCallback); + test(`DEPRECATION ${deprecation.id} until ${deprecation.until} | ${testName}`, interceptor); } else { test(`DEPRECATION ${deprecation.id} until ${deprecation.until} | ${testName}`, function(assert) { if (deprecation.refactor === true) { diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/assert-assertion.ts b/packages/-ember-data/tests/helpers/qunit-asserts/assert-assertion.ts new file mode 100644 index 00000000000..b65acedaf85 --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/assert-assertion.ts @@ -0,0 +1,90 @@ +import QUnit from 'qunit'; +import { checkMatcher } from './check-matcher'; +import { DEBUG } from '@glimmer/env'; +import isThenable from './utils/is-thenable'; + +let HAS_REGISTERED = false; + +interface AssertSomeResult { + result: boolean; + actual: string; + expected: string; + message: string; +} +interface AssertNoneResult { + result: boolean; + actual: string; + expected: ''; + message: string; +} + +function verifyAssertion(message: string, matcher: string | RegExp, label?: string): AssertSomeResult { + let passed = checkMatcher(message, matcher); + + return { + result: passed, + actual: message, + expected: String(matcher), + message: label || `Expected an assertion during the test`, + }; +} + +function verifyNoAssertion(message: string | undefined, label?: string): AssertNoneResult { + let passed = !message; + return { + result: passed, + actual: message || '', + expected: '', + message: label || `Expected no assertions during test`, + }; +} + +export function configureAssertionHandler() { + if (HAS_REGISTERED === true) { + throw new Error(`Attempting to re-register the assert-assertion handler`); + } + HAS_REGISTERED = true; + + QUnit.assert.expectAssertion = async function( + cb: () => unknown, + matcher: string | RegExp, + label?: string + ): Promise { + let outcome; + if (DEBUG) { + try { + let result = cb(); + if (isThenable(result)) { + await result; + } + outcome = verifyAssertion('', matcher, label); + } catch (e) { + outcome = verifyAssertion(e.message, matcher, label); + } + } else { + outcome = { + result: true, + actual: '', + expected: '', + message: `Assertions do not run in production environments`, + }; + } + + this.pushResult(outcome); + }; + + QUnit.assert.expectNoAssertion = async function(cb: () => unknown, label?: string) { + let outcome; + try { + let result = cb(); + if (isThenable(result)) { + await result; + } + outcome = verifyNoAssertion('', label); + } catch (e) { + outcome = verifyNoAssertion(e.message, label); + } + + this.pushResult(outcome); + }; +} diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/assert-deprecation.ts b/packages/-ember-data/tests/helpers/qunit-asserts/assert-deprecation.ts new file mode 100644 index 00000000000..5f64ae46878 --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/assert-deprecation.ts @@ -0,0 +1,184 @@ +import QUnit from 'qunit'; +import { registerDeprecationHandler } from '@ember/debug'; +import { checkMatcher } from './check-matcher'; +import isThenable from './utils/is-thenable'; + +let HAS_REGISTERED = false; +let DEPRECATIONS_FOR_TEST: FoundDeprecation[]; +let HANDLED_DEPRECATIONS_FOR_TEST: FoundDeprecation[]; + +interface DeprecationConfig { + id: string; + count?: number; + until: string; + message?: string | RegExp; + url?: string; +} +interface FoundDeprecation { + message: string; + options: { + id: string; + message?: string; + until: string; + url?: string; + }; +} + +interface AssertSomeResult { + result: boolean; + actual: { id: string; count: number }; + expected: { id: string; count: number }; + message: string; +} +interface AssertNoneResult { + result: boolean; + actual: FoundDeprecation[]; + expected: FoundDeprecation[]; + message: string; +} + +/** + * Returns a qunit assert result object which passes if the given deprecation + * `id` was found *exactly* `count` times. + * + * Fails if not found or found more or less than `count`. + * Fails if `until` not specified + * Optionally fails if `until` has been passed. + */ +function verifyDeprecation(config: DeprecationConfig, label?: string): AssertSomeResult { + // TODO optionally throw if `until` is the current version or older than current version + let matchedDeprecations = DEPRECATIONS_FOR_TEST.filter(deprecation => { + let isMatched = deprecation.options.id === config.id; + if (!isMatched && config.message) { + // TODO when we hit this we should throw an error in the near future + isMatched = checkMatcher(deprecation.message, config.message); + } + return isMatched; + }); + DEPRECATIONS_FOR_TEST = DEPRECATIONS_FOR_TEST.filter(deprecation => { + return matchedDeprecations.indexOf(deprecation) === -1; + }); + HANDLED_DEPRECATIONS_FOR_TEST.push(...matchedDeprecations); + + let expectedCount = typeof config.count === 'number' ? config.count : 1; + let passed = matchedDeprecations.length === expectedCount; + + return { + result: passed, + actual: { id: config.id, count: matchedDeprecations.length }, + expected: { id: config.id, count: expectedCount }, + message: + label || + `Expected ${expectedCount} deprecation${expectedCount === 1 ? '' : 's'} for ${config.id} during test, ${ + passed ? expectedCount : 'but ' + matchedDeprecations.length + } deprecations were found.`, + }; +} + +function verifyNoDeprecation(filter?: (deprecation: FoundDeprecation) => boolean, label?: string): AssertNoneResult { + let UNHANDLED_DEPRECATIONS; + + if (filter) { + UNHANDLED_DEPRECATIONS = DEPRECATIONS_FOR_TEST.filter(filter); + DEPRECATIONS_FOR_TEST = DEPRECATIONS_FOR_TEST.filter(deprecation => { + return UNHANDLED_DEPRECATIONS.indexOf(deprecation) === -1; + }); + } else { + UNHANDLED_DEPRECATIONS = DEPRECATIONS_FOR_TEST; + DEPRECATIONS_FOR_TEST = []; + } + + let deprecationStr = UNHANDLED_DEPRECATIONS.reduce((a, b) => { + return `${a}${b.message}\n`; + }, ''); + + let passed = UNHANDLED_DEPRECATIONS.length === 0; + + return { + result: passed, + actual: UNHANDLED_DEPRECATIONS, + expected: [], + message: + label || + `Expected 0 deprecations during test, ${ + passed ? '0' : 'but ' + UNHANDLED_DEPRECATIONS.length + } deprecations were found.\n${deprecationStr}`, + }; +} + +export function configureDeprecationHandler() { + if (HAS_REGISTERED === true) { + throw new Error(`Attempting to re-register the assert-deprecation handler`); + } + HAS_REGISTERED = true; + + QUnit.testStart(function() { + DEPRECATIONS_FOR_TEST = []; + HANDLED_DEPRECATIONS_FOR_TEST = []; + }); + + registerDeprecationHandler(function(message, options /*, next*/) { + if (DEPRECATIONS_FOR_TEST) { + DEPRECATIONS_FOR_TEST.push({ message, options }); + } + // we do not call next to avoid spamming the console + }); + + QUnit.assert.expectDeprecation = async function( + cb: () => unknown, + config: string | RegExp | DeprecationConfig, + label?: string + ): Promise { + let origDeprecations = DEPRECATIONS_FOR_TEST; + let callback: (() => unknown) | null = null; + + if (typeof cb !== 'function') { + config = cb; + callback = null; + } else { + callback = cb; + } + + if (typeof config === 'string' || config instanceof RegExp) { + config = { + id: 'unknown-data-deprecation', + count: 1, + message: config, + until: '4.0', + }; + } + + if (callback) { + DEPRECATIONS_FOR_TEST = []; + let result = callback(); + if (isThenable(result)) { + await result; + } + } + + let result = verifyDeprecation(config, label); + this.pushResult(result); + if (callback) { + DEPRECATIONS_FOR_TEST = origDeprecations.concat(DEPRECATIONS_FOR_TEST); + } + }; + QUnit.assert.expectNoDeprecation = async function( + cb?: () => unknown, + label?: string, + filter?: (deprecation: FoundDeprecation) => boolean + ) { + let origDeprecations = DEPRECATIONS_FOR_TEST; + + if (cb) { + DEPRECATIONS_FOR_TEST = []; + let result = cb(); + if (isThenable(result)) { + await result; + } + } + + let result = verifyNoDeprecation(filter, label); + this.pushResult(result); + DEPRECATIONS_FOR_TEST = origDeprecations.concat(DEPRECATIONS_FOR_TEST); + }; +} diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/assert-warning.ts b/packages/-ember-data/tests/helpers/qunit-asserts/assert-warning.ts new file mode 100644 index 00000000000..51f8022fa5d --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/assert-warning.ts @@ -0,0 +1,170 @@ +import QUnit from 'qunit'; +import { registerWarnHandler } from '@ember/debug'; +import { checkMatcher } from './check-matcher'; +import isThenable from './utils/is-thenable'; + +let HAS_REGISTERED = false; +let WARNINGS_FOR_TEST: FoundWarning[]; +let HANDLED_WARNINGS_FOR_TEST: FoundWarning[]; + +interface WarningConfig { + id: string; + count?: number; + until?: string; + message?: string | RegExp; + url?: string; +} +interface FoundWarning { + message: string; + options: { + id: string; + message?: string; + until?: string; + url?: string; + }; +} + +interface AssertSomeResult { + result: boolean; + actual: { id: string; count: number }; + expected: { id: string; count: number }; + message: string; +} +interface AssertNoneResult { + result: boolean; + actual: FoundWarning[]; + expected: FoundWarning[]; + message: string; +} + +/** + * Returns a qunit assert result object which passes if the given warning + * `id` was found *exactly* `count` times. + * + * Fails if not found or found more or less than `count`. + * Fails if `until` not specified + * Optionally fails if `until` has been passed. + */ +function verifyWarning(config: WarningConfig, label?: string): AssertSomeResult { + // TODO optionally throw if `until` is the current version or older than current version + let matchedWarnings = WARNINGS_FOR_TEST.filter(warning => { + let isMatched = warning.options.id === config.id; + if (!isMatched && config.message) { + // TODO when we hit this we should throw an error in the near future + isMatched = checkMatcher(warning.message, config.message); + } + return isMatched; + }); + WARNINGS_FOR_TEST = WARNINGS_FOR_TEST.filter(warning => { + matchedWarnings.indexOf(warning) === -1; + }); + HANDLED_WARNINGS_FOR_TEST.push(...matchedWarnings); + + let expectedCount = typeof config.count === 'number' ? config.count : 1; + let passed = matchedWarnings.length === expectedCount; + + return { + result: passed, + actual: { id: config.id, count: matchedWarnings.length }, + expected: { id: config.id, count: expectedCount }, + message: + label || + `Expected ${expectedCount} warning${expectedCount === 1 ? '' : 's'} for ${config.id} during test, ${ + passed ? expectedCount : 'but ' + matchedWarnings.length + } warnings were found.`, + }; +} + +function verifyNoWarning(label?: string): AssertNoneResult { + const UNHANDLED_WARNINGS = WARNINGS_FOR_TEST; + WARNINGS_FOR_TEST = []; + + let warningStr = UNHANDLED_WARNINGS.reduce((a, b) => { + return `${a}${b.message}\n`; + }, ''); + + let passed = UNHANDLED_WARNINGS.length === 0; + + return { + result: passed, + actual: UNHANDLED_WARNINGS, + expected: [], + message: + label || + `Expected 0 warnings during test, ${ + passed ? '0' : 'but ' + UNHANDLED_WARNINGS.length + } warnings were found.\n${warningStr}`, + }; +} + +export function configureWarningHandler() { + if (HAS_REGISTERED === true) { + throw new Error(`Attempting to re-register the assert-warning handler`); + } + HAS_REGISTERED = true; + + QUnit.testStart(function() { + WARNINGS_FOR_TEST = []; + HANDLED_WARNINGS_FOR_TEST = []; + }); + + registerWarnHandler(function(message, options /*, next*/) { + if (WARNINGS_FOR_TEST) { + WARNINGS_FOR_TEST.push({ message, options }); + } + // we do not call next to avoid spamming the console + }); + + QUnit.assert.expectWarning = async function( + cb: () => unknown, + config: string | RegExp | WarningConfig, + label?: string + ): Promise { + let origWarnings = WARNINGS_FOR_TEST; + let callback: (() => unknown) | null = null; + + if (typeof cb !== 'function') { + config = cb; + callback = null; + } else { + callback = cb; + } + + if (typeof config === 'string' || config instanceof RegExp) { + config = { + id: 'unknown-data-warning', + count: 1, + message: config, + until: '4.0', + }; + } + + if (callback) { + WARNINGS_FOR_TEST = []; + let result = callback(); + if (isThenable(result)) { + await result; + } + } + + let result = verifyWarning(config, label); + this.pushResult(result); + WARNINGS_FOR_TEST = origWarnings.concat(WARNINGS_FOR_TEST); + }; + + QUnit.assert.expectNoWarning = async function(cb, label?: string) { + let origWarnings = WARNINGS_FOR_TEST; + + if (cb) { + WARNINGS_FOR_TEST = []; + let result = cb(); + if (isThenable(result)) { + await result; + } + } + + let result = verifyNoWarning(label); + this.pushResult(result); + WARNINGS_FOR_TEST = origWarnings.concat(WARNINGS_FOR_TEST); + }; +} diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/check-matcher.ts b/packages/-ember-data/tests/helpers/qunit-asserts/check-matcher.ts new file mode 100644 index 00000000000..0a32e455482 --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/check-matcher.ts @@ -0,0 +1,16 @@ +function includes(message, search) { + return message.includes ? message.includes(search) : message.indexOf(search) !== -1; +} + +export function checkMatcher(message, matcher) { + if (typeof matcher === 'string') { + return includes(message, matcher); + } else if (matcher instanceof RegExp) { + return !!message.match(matcher); + } else if (matcher) { + throw new Error(`Assert helpers can only match Strings and RegExps. "${typeof matcher}" was provided.`); + } + + // No matcher always returns true. Makes the code easier elsewhere. + return true; +} diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/index.ts b/packages/-ember-data/tests/helpers/qunit-asserts/index.ts new file mode 100644 index 00000000000..8993fa5e150 --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/index.ts @@ -0,0 +1,9 @@ +import { configureAssertionHandler } from './assert-assertion'; +import { configureDeprecationHandler } from './assert-deprecation'; +import { configureWarningHandler } from './assert-warning'; + +export default function configureAsserts() { + configureAssertionHandler(); + configureDeprecationHandler(); + configureWarningHandler(); +} diff --git a/packages/-ember-data/tests/helpers/qunit-asserts/utils/is-thenable.ts b/packages/-ember-data/tests/helpers/qunit-asserts/utils/is-thenable.ts new file mode 100644 index 00000000000..da0404e8a70 --- /dev/null +++ b/packages/-ember-data/tests/helpers/qunit-asserts/utils/is-thenable.ts @@ -0,0 +1,3 @@ +export default function isThenable(obj: unknown): boolean { + return typeof obj === 'object' && obj !== null && 'then' in obj; +} diff --git a/packages/-ember-data/tests/helpers/test-in-debug.js b/packages/-ember-data/tests/helpers/test-in-debug.js index 949b64daac2..fbdfb345688 100644 --- a/packages/-ember-data/tests/helpers/test-in-debug.js +++ b/packages/-ember-data/tests/helpers/test-in-debug.js @@ -1,10 +1,10 @@ import { DEBUG } from '@glimmer/env'; import { test, skip } from 'qunit'; -export default function testInDebug() { +export default function testInDebug(label, callback) { if (DEBUG) { - test(...arguments); + test(`[DEBUG-ONLY] ${label}`, callback); } else { - skip(...arguments); + skip(`[DEBUG-ONLY] ${label}`, callback); } } diff --git a/packages/-ember-data/tests/helpers/watch-property.js b/packages/-ember-data/tests/helpers/watch-property.js index 6d2ebac7abb..ed4872d8971 100644 --- a/packages/-ember-data/tests/helpers/watch-property.js +++ b/packages/-ember-data/tests/helpers/watch-property.js @@ -90,7 +90,7 @@ QUnit.assert.watchedPropertyCounts = function assertWatchedPropertyCount(watched expectedCount = expectedCount[0]; } - assertionText += ` | Expected ${expectedCount} change notifications for ${propertyName} but recieved ${counter.count}`; + assertionText += ` | Expected ${expectedCount} change notifications for ${propertyName} but received ${counter.count}`; if (counter === undefined) { throw new Error(`Cannot assert expected count for ${propertyName} as there is no watcher for that property`); diff --git a/packages/-ember-data/tests/integration/adapter/record-persistence-test.js b/packages/-ember-data/tests/integration/adapter/record-persistence-test.js index 1db25975ad0..16de7339aa7 100644 --- a/packages/-ember-data/tests/integration/adapter/record-persistence-test.js +++ b/packages/-ember-data/tests/integration/adapter/record-persistence-test.js @@ -28,7 +28,7 @@ module('integration/adapter/record_persistence - Persisting Records', function(h this.owner.register('serializer:application', JSONAPISerializer.extend()); }); - test("When a store is committed, the adapter's `commit` method should be called with records that have been changed.", function(assert) { + test("When a store is committed, the adapter's `updateRecord` method should be called with records that have been changed.", async function(assert) { assert.expect(2); let store = this.owner.lookup('service:store'); @@ -42,27 +42,18 @@ module('integration/adapter/record_persistence - Persisting Records', function(h return run(RSVP, 'resolve'); }; - run(() => { - store.push({ - data: { - type: 'person', - id: '1', - attributes: { - name: 'Braaaahm Dale', - }, + const tom = store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale', }, - }); + }, }); - let tom; - - return run(() => { - return store.findRecord('person', 1).then(person => { - tom = person; - set(tom, 'name', 'Tom Dale'); - return tom.save(); - }); - }); + set(tom, 'name', 'Tom Dale'); + await tom.save(); }); test("When a store is committed, the adapter's `commit` method should be called with records that have been created.", function(assert) { diff --git a/packages/-ember-data/tests/integration/multiple-stores-test.js b/packages/-ember-data/tests/integration/multiple-stores-test.js index d0beaa9035e..6f5ae571f57 100644 --- a/packages/-ember-data/tests/integration/multiple-stores-test.js +++ b/packages/-ember-data/tests/integration/multiple-stores-test.js @@ -1,7 +1,5 @@ -import { run } from '@ember/runloop'; import { setupTest } from 'ember-qunit'; import { module, test } from 'qunit'; -import { get } from '@ember/object'; // we intentionally test against the ember-data version here // because the ember-data/store uses DefaultRecordData while @ember-data/store does not import Store from 'ember-data/store'; @@ -18,7 +16,6 @@ module('integration/multiple_stores - Multiple Stores Tests', function(hooks) { firstName: attr('string'), lastName: attr('string'), homePlanet: belongsTo('home-planet', { inverse: 'villains', async: false }), - evilMinions: hasMany('evil-minion', { async: false }), }); const HomePlanet = Model.extend({ @@ -26,14 +23,8 @@ module('integration/multiple_stores - Multiple Stores Tests', function(hooks) { villains: hasMany('super-villain', { inverse: 'homePlanet', async: false }), }); - const EvilMinion = Model.extend({ - superVillain: belongsTo('super-villain', { async: false }), - name: attr('string'), - }); - this.owner.register('model:super-villain', SuperVillain); this.owner.register('model:home-planet', HomePlanet); - this.owner.register('model:evil-minion', EvilMinion); this.owner.register('adapter:application', RESTAdapter); this.owner.register('serializer:application', RESTSerializer); @@ -42,7 +33,7 @@ module('integration/multiple_stores - Multiple Stores Tests', function(hooks) { this.owner.register('store:store-b', Store); }); - test('should be able to push into multiple stores', function(assert) { + test('should be able to push into multiple stores', async function(assert) { this.owner.register( 'adapter:home-planet', RESTAdapter.extend({ @@ -50,34 +41,29 @@ module('integration/multiple_stores - Multiple Stores Tests', function(hooks) { }) ); - let store = this.owner.lookup('service:store'); - let store_a = this.owner.lookup('store:store-a'); - let store_b = this.owner.lookup('store:store-b'); + const andromedaStore = this.owner.lookup('service:store'); + const cartwheelStore = this.owner.lookup('store:store-a'); + const cigarStore = this.owner.lookup('store:store-b'); - let home_planet_main = { id: '1', name: 'Earth' }; - let home_planet_a = { id: '1', name: 'Mars' }; - let home_planet_b = { id: '1', name: 'Saturn' }; + const earth = { id: '1', name: 'Earth' }; + const mars = { id: '1', name: 'Mars' }; + const saturn = { id: '1', name: 'Saturn' }; - run(() => { - store.push(store.normalize('home-planet', home_planet_main)); - store_a.push(store_a.normalize('home-planet', home_planet_a)); - store_b.push(store_b.normalize('home-planet', home_planet_b)); - }); + andromedaStore.push(andromedaStore.normalize('home-planet', earth)); + cartwheelStore.push(cartwheelStore.normalize('home-planet', mars)); + cigarStore.push(cigarStore.normalize('home-planet', saturn)); - return store - .findRecord('home-planet', 1) - .then(homePlanet => { - assert.equal(homePlanet.get('name'), 'Earth'); + let homePlanet = await andromedaStore.findRecord('home-planet', '1'); - return store_a.findRecord('homePlanet', 1); - }) - .then(homePlanet => { - assert.equal(homePlanet.get('name'), 'Mars'); - return store_b.findRecord('homePlanet', 1); - }) - .then(homePlanet => { - assert.equal(homePlanet.get('name'), 'Saturn'); - }); + assert.equal(homePlanet.name, 'Earth'); + + homePlanet = await cartwheelStore.findRecord('home-planet', '1'); + + assert.equal(homePlanet.name, 'Mars'); + + homePlanet = await cigarStore.findRecord('home-planet', '1'); + + assert.equal(homePlanet.name, 'Saturn'); }); test('embedded records should be created in multiple stores', function(assert) { @@ -90,15 +76,15 @@ module('integration/multiple_stores - Multiple Stores Tests', function(hooks) { }) ); - let store = this.owner.lookup('service:store'); - let store_a = this.owner.lookup('store:store-a'); - let store_b = this.owner.lookup('store:store-b'); + const andromedaStore = this.owner.lookup('service:store'); + const cartwheelStore = this.owner.lookup('store:store-a'); + const cigarStore = this.owner.lookup('store:store-b'); - let serializer_main = store.serializerFor('home-planet'); - let serializer_a = store_a.serializerFor('home-planet'); - let serializer_b = store_b.serializerFor('home-planet'); + const andromedaSerializer = andromedaStore.serializerFor('home-planet'); + const cartwheelSerializer = cartwheelStore.serializerFor('home-planet'); + const cigarSerializer = cigarStore.serializerFor('home-planet'); - let json_hash_main = { + const andromedaJsonPayload = { homePlanet: { id: '1', name: 'Earth', @@ -111,7 +97,7 @@ module('integration/multiple_stores - Multiple Stores Tests', function(hooks) { ], }, }; - let json_hash_a = { + const cartWheelJsonPayload = { homePlanet: { id: '1', name: 'Mars', @@ -124,71 +110,91 @@ module('integration/multiple_stores - Multiple Stores Tests', function(hooks) { ], }, }; - let json_hash_b = { + const cigarJsonPayload = { homePlanet: { id: '1', name: 'Saturn', villains: [ { id: '1', - firstName: 'Jade', - lastName: 'John', + firstName: 'Damita', + lastName: 'Giraldo', }, ], }, }; - let json_main, json_a, json_b; - - run(() => { - json_main = serializer_main.normalizeResponse( - store, - store.modelFor('home-planet'), - json_hash_main, - 1, - 'findRecord' - ); - store.push(json_main); - assert.equal(store.hasRecordForId('super-villain', '1'), true, 'superVillain should exist in service:store'); - }); - run(() => { - json_a = serializer_a.normalizeResponse(store_a, store_a.modelFor('home-planet'), json_hash_a, 1, 'findRecord'); - store_a.push(json_a); - assert.equal(store_a.hasRecordForId('super-villain', '1'), true, 'superVillain should exist in store:store-a'); - }); + const normalizedAndromedaPayload = andromedaSerializer.normalizeResponse( + andromedaStore, + andromedaStore.modelFor('home-planet'), + andromedaJsonPayload, + '1', + 'findRecord' + ); - run(() => { - json_b = serializer_b.normalizeResponse(store_b, store_a.modelFor('home-planet'), json_hash_b, 1, 'findRecord'); - store_b.push(json_b); - assert.equal(store_b.hasRecordForId('super-villain', '1'), true, 'superVillain should exist in store:store-b'); - }); + andromedaStore.push(normalizedAndromedaPayload); + assert.equal( + andromedaStore.hasRecordForId('super-villain', '1'), + true, + 'superVillain should exist in service:store' + ); + + const normalizedCartWheelPayload = cartwheelSerializer.normalizeResponse( + cartwheelStore, + cartwheelStore.modelFor('home-planet'), + cartWheelJsonPayload, + '1', + 'findRecord' + ); + + cartwheelStore.push(normalizedCartWheelPayload); + assert.equal( + cartwheelStore.hasRecordForId('super-villain', '1'), + true, + 'superVillain should exist in store:store-a' + ); + + const normalizedCigarPayload = cigarSerializer.normalizeResponse( + cigarStore, + cigarStore.modelFor('home-planet'), + cigarJsonPayload, + '1', + 'findRecord' + ); + cigarStore.push(normalizedCigarPayload); + + assert.equal(cigarStore.hasRecordForId('super-villain', '1'), true, 'superVillain should exist in store:store-b'); }); test('each store should have a unique instance of the serializers', function(assert) { this.owner.register('serializer:home-planet', RESTSerializer.extend({})); - let store_a = this.owner.lookup('store:store-a'); - let store_b = this.owner.lookup('store:store-b'); + const andromedaStore = this.owner.lookup('store:store-a'); + const cigarStore = this.owner.lookup('store:store-b'); - let serializer_a = store_a.serializerFor('home-planet'); - let serializer_b = store_b.serializerFor('home-planet'); + const andromedaSerializer = andromedaStore.serializerFor('home-planet'); + const cigarSerializer = cigarStore.serializerFor('home-planet'); - assert.equal(get(serializer_a, 'store'), store_a, "serializer_a's store prop should be sotre_a"); - assert.equal(get(serializer_b, 'store'), store_b, "serializer_b's store prop should be sotre_b"); - assert.notEqual(serializer_a, serializer_b, 'serialier_a and serialier_b should be unique instances'); + assert.equal( + andromedaSerializer.store, + andromedaStore, + "andromedaSerializer's store prop should be andromedaStore" + ); + assert.equal(cigarSerializer.store, cigarStore, "cigarSerializer's store prop should be cigarStore"); + assert.notEqual(andromedaSerializer, cigarSerializer, 'andromedaStore and cigarStore should be unique instances'); }); test('each store should have a unique instance of the adapters', function(assert) { this.owner.register('adapter:home-planet', Adapter.extend({})); - let store_a = this.owner.lookup('store:store-a'); - let store_b = this.owner.lookup('store:store-b'); + const andromedaStore = this.owner.lookup('store:store-a'); + const cigarStore = this.owner.lookup('store:store-b'); - let adapter_a = store_a.adapterFor('home-planet'); - let adapter_b = store_b.adapterFor('home-planet'); + const andromedaAdapter = andromedaStore.adapterFor('home-planet'); + const cigarAdapter = cigarStore.adapterFor('home-planet'); - assert.equal(get(adapter_a, 'store'), store_a); - assert.equal(get(adapter_b, 'store'), store_b); - assert.notEqual(adapter_a, adapter_b); + assert.equal(andromedaAdapter.store, andromedaStore); + assert.equal(cigarAdapter.store, cigarStore); + assert.notEqual(andromedaAdapter, cigarAdapter); }); }); diff --git a/packages/-ember-data/tests/integration/relationships/inverse-relationship-load-test.js b/packages/-ember-data/tests/integration/relationships/inverse-relationship-load-test.js index 9c58a4d114e..615dd682871 100644 --- a/packages/-ember-data/tests/integration/relationships/inverse-relationship-load-test.js +++ b/packages/-ember-data/tests/integration/relationships/inverse-relationship-load-test.js @@ -1523,7 +1523,10 @@ module('inverse relationship load test', function(hooks) { }); let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); assert.equal(dogs.get('length'), 2); @@ -1629,7 +1632,10 @@ module('inverse relationship load test', function(hooks) { }); let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); assert.equal(dogs.get('length'), 2); @@ -1729,7 +1735,10 @@ module('inverse relationship load test', function(hooks) { }); let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); assert.equal(dogs.get('length'), 2); @@ -1829,7 +1838,10 @@ module('inverse relationship load test', function(hooks) { }); let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); assert.equal(dogs.get('length'), 2); @@ -1918,7 +1930,10 @@ module('inverse relationship load test', function(hooks) { }); let dog = await person.get('dog'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); @@ -2010,7 +2025,10 @@ module('inverse relationship load test', function(hooks) { }); let dog = await person.get('dog'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = store.peekRecord('dog', '1'); @@ -2100,7 +2118,10 @@ module('inverse relationship load test', function(hooks) { }); let dog = await person.get('dog'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); @@ -2190,7 +2211,10 @@ module('inverse relationship load test', function(hooks) { }); let dog = await person.get('dog'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); @@ -2285,7 +2309,10 @@ module('inverse relationship load test', function(hooks) { }); let person = await dog.get('person'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); assert.equal(dogFromStore.belongsTo('person').id(), '1', 'dog relationship is set up correctly'); @@ -2370,7 +2397,10 @@ module('inverse relationship load test', function(hooks) { }); let person = await dog.get('person'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); assert.equal(dogFromStore.belongsTo('person').id(), '1', 'dog relationship is set up correctly'); @@ -2450,7 +2480,10 @@ module('inverse relationship load test', function(hooks) { }); let person = await dog.get('person'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); assert.equal(dogFromStore.belongsTo('person').id(), '1', 'dog relationship is set up correctly'); @@ -2530,7 +2563,10 @@ module('inverse relationship load test', function(hooks) { }); let person = await dog.get('person'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 1, + }); let dogFromStore = await store.peekRecord('dog', '1'); assert.equal(dogFromStore.belongsTo('person').id(), '1', 'dog relationship is set up correctly'); @@ -2644,7 +2680,10 @@ module('inverse relationship load test', function(hooks) { let person1Dogs = await person1.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person1.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); @@ -2817,7 +2856,10 @@ module('inverse relationship load test', function(hooks) { let person1Dogs = await person1.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person1.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); @@ -2971,7 +3013,10 @@ module('inverse relationship load test', function(hooks) { await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); @@ -3090,7 +3135,10 @@ module('inverse relationship load test', function(hooks) { await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); @@ -3209,7 +3257,10 @@ module('inverse relationship load test', function(hooks) { let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); @@ -3327,7 +3378,10 @@ module('inverse relationship load test', function(hooks) { let dogs = await person.get('dogs'); - assert.expectDeprecation(/Encountered mismatched relationship/); + assert.expectDeprecation({ + id: 'mismatched-inverse-relationship-data-from-payload', + count: 2, + }); assert.equal(person.hasMany('dogs').hasManyRelationship.relationshipIsEmpty, false); let dog1 = store.peekRecord('dog', '1'); diff --git a/packages/-ember-data/tests/integration/relationships/relationship-links-test.js b/packages/-ember-data/tests/integration/relationships/relationship-links-test.js new file mode 100644 index 00000000000..070cb57f3ef --- /dev/null +++ b/packages/-ember-data/tests/integration/relationships/relationship-links-test.js @@ -0,0 +1,356 @@ +import EmberObject from '@ember/object'; +import { test, module } from 'qunit'; +import { setupTest } from 'ember-qunit'; +import Store from '@ember-data/store'; +import Model, { attr, hasMany } from '@ember-data/model'; +import { resolve } from 'rsvp'; +import { FULL_LINKS_ON_RELATIONSHIPS } from '@ember-data/canary-features'; + +module('JSON:API links access on relationships', function(hooks) { + setupTest(hooks); + let store; + + hooks.beforeEach(function() { + const { owner } = this; + owner.register('service:store', Store); + store = owner.lookup('service:store'); + }); + + if (FULL_LINKS_ON_RELATIONSHIPS) { + test('We can access links from a hasMany', async function(assert) { + class ApplicationAdapter extends EmberObject { + findRecord() {} + findHasMany() { + return resolve({ + data: [], + }); + } + shouldBackgroundReloadRecord() { + return false; + } + shouldReloadRecord() { + return false; + } + } + class User extends Model { + @attr name; + @hasMany('tool', { inverse: null, async: true }) + tools; + } + class Tool extends Model { + @attr name; + } + class ApplicationSerializer extends EmberObject { + normalizeResponse(_, __, data) { + return data; + } + } + this.owner.register('adapter:application', ApplicationAdapter); + this.owner.register('serializer:application', ApplicationSerializer); + this.owner.register('model:user', User); + this.owner.register('model:tool', Tool); + + const user = store.push({ + data: { + id: '1', + type: 'user', + attributes: { + name: '@runspired', + }, + relationships: { + tools: { + links: { + self: '/the/original/path', + related: '/the/related/link', + first: '/the/related/link?page=1', + prev: null, + last: '/the/related/link?page=3', + next: '/the/related/link?page=2', + }, + }, + }, + }, + }); + + // Test we have access via the HasManyReference + const toolsRef = user.hasMany('tools'); + let links = toolsRef.links(); + assert.strictEqual(!!links, true, 'We have a links value on the relationship HasManyReference'); + assert.strictEqual(links.related, '/the/related/link', 'The related link is correctly available'); + assert.strictEqual(links.first, '/the/related/link?page=1', 'The first link is correctly available'); + assert.strictEqual(links.last, '/the/related/link?page=3', 'The last link is correctly available'); + assert.strictEqual(links.prev, null, 'The prev link is correctly available'); + assert.strictEqual(links.next, '/the/related/link?page=2', 'The next link is correctly available'); + assert.strictEqual(links.self, '/the/original/path', 'The self link is correctly available'); + + // Test we have access via the ManyArray + const toolsRel = await user.tools; + links = toolsRel.links; + assert.strictEqual(!!links, true, 'We have a links value on the relationship ManyArray'); + assert.strictEqual(links.related, '/the/related/link', 'The related link is correctly available'); + assert.strictEqual(links.first, '/the/related/link?page=1', 'The first link is correctly available'); + assert.strictEqual(links.last, '/the/related/link?page=3', 'The last link is correctly available'); + assert.strictEqual(links.prev, null, 'The prev link is correctly available'); + assert.strictEqual(links.next, '/the/related/link?page=2', 'The next link is correctly available'); + assert.strictEqual(links.self, '/the/original/path', 'The self link is correctly available'); + }); + + test('We preserve { href } link objects', async function(assert) { + class ApplicationAdapter extends EmberObject { + findRecord() {} + findHasMany() { + return resolve({ + data: [], + }); + } + shouldBackgroundReloadRecord() { + return false; + } + shouldReloadRecord() { + return false; + } + } + class User extends Model { + @attr name; + @hasMany('tool', { inverse: null, async: true }) + tools; + } + class Tool extends Model { + @attr name; + } + class ApplicationSerializer extends EmberObject { + normalizeResponse(_, __, data) { + return data; + } + } + this.owner.register('adapter:application', ApplicationAdapter); + this.owner.register('serializer:application', ApplicationSerializer); + this.owner.register('model:user', User); + this.owner.register('model:tool', Tool); + + const user = store.push({ + data: { + id: '1', + type: 'user', + attributes: { + name: '@runspired', + }, + relationships: { + tools: { + links: { + self: { href: '/the/original/path' }, + related: { href: '/the/related/link' }, + first: { href: '/the/related/link?page=1' }, + prev: null, + last: { href: '/the/related/link?page=3' }, + next: { href: '/the/related/link?page=2' }, + }, + }, + }, + }, + }); + + // Test we have access via the HasManyReference + const toolsRef = user.hasMany('tools'); + let links = toolsRef.links(); + assert.strictEqual(!!links, true, 'We have a links value on the relationship HasManyReference'); + assert.deepEqual(links.related, { href: '/the/related/link' }, 'The related link is correctly available'); + assert.deepEqual(links.first, { href: '/the/related/link?page=1' }, 'The first link is correctly available'); + assert.deepEqual(links.last, { href: '/the/related/link?page=3' }, 'The last link is correctly available'); + assert.deepEqual(links.prev, null, 'The prev link is correctly available'); + assert.deepEqual(links.next, { href: '/the/related/link?page=2' }, 'The next link is correctly available'); + assert.deepEqual(links.self, { href: '/the/original/path' }, 'The self link is correctly available'); + + // Test we have access via the ManyArray + const toolsRel = await user.tools; + links = toolsRel.links; + assert.strictEqual(!!links, true, 'We have a links value on the relationship ManyArray'); + assert.deepEqual(links.related, { href: '/the/related/link' }, 'The related link is correctly available'); + assert.deepEqual(links.first, { href: '/the/related/link?page=1' }, 'The first link is correctly available'); + assert.deepEqual(links.last, { href: '/the/related/link?page=3' }, 'The last link is correctly available'); + assert.deepEqual(links.prev, null, 'The prev link is correctly available'); + assert.deepEqual(links.next, { href: '/the/related/link?page=2' }, 'The next link is correctly available'); + assert.deepEqual(links.self, { href: '/the/original/path' }, 'The self link is correctly available'); + }); + + test('We unwrap the { href } link object when related link is accessed directly', async function(assert) { + class ApplicationAdapter extends EmberObject { + findRecord() {} + findHasMany() { + return resolve({ + data: [], + }); + } + shouldBackgroundReloadRecord() { + return false; + } + shouldReloadRecord() { + return false; + } + } + class User extends Model { + @attr name; + @hasMany('tool', { inverse: null, async: true }) + tools; + } + class Tool extends Model { + @attr name; + } + class ApplicationSerializer extends EmberObject { + normalizeResponse(_, __, data) { + return data; + } + } + this.owner.register('adapter:application', ApplicationAdapter); + this.owner.register('serializer:application', ApplicationSerializer); + this.owner.register('model:user', User); + this.owner.register('model:tool', Tool); + + const user = store.push({ + data: { + id: '1', + type: 'user', + attributes: { + name: '@runspired', + }, + relationships: { + tools: { + links: { + related: { href: '/the/related/link' }, + }, + }, + }, + }, + }); + + // Test we have access via the HasManyReference + const toolsRef = user.hasMany('tools'); + let links = toolsRef.links(); + assert.strictEqual(!!links, true, 'We have a links value on the relationship HasManyReference'); + assert.deepEqual(links.related, { href: '/the/related/link' }, 'The related link is correctly available'); + + let link = toolsRef.link(); + assert.strictEqual(link, '/the/related/link', 'The related link is unwrapped when accessed directly'); + + // Test we have access via the ManyArray + const toolsRel = await user.tools; + links = toolsRel.links; + assert.strictEqual(!!links, true, 'We have a links value on the relationship ManyArray'); + assert.deepEqual(links.related, { href: '/the/related/link' }, 'The related link is correctly available'); + }); + + test('Links in the top-level of a relationship-document update the relationship links', async function(assert) { + class ApplicationAdapter extends EmberObject { + findRecord() {} + findHasMany() { + return resolve({ + data: [], + links: { + self: { href: '/some/other/path' }, + related: { href: '/the/new/related/link?page=3' }, + first: { href: '/the/new/related/link?page=1' }, + prev: { href: '/the/new/related/link?page=2' }, + last: { href: '/the/new/related/link?page=5' }, + next: { href: '/the/new/related/link?page=4' }, + }, + }); + } + shouldBackgroundReloadRecord() { + return false; + } + shouldReloadRecord() { + return false; + } + } + class User extends Model { + @attr name; + @hasMany('tool', { inverse: null, async: true }) + tools; + } + class Tool extends Model { + @attr name; + } + class ApplicationSerializer extends EmberObject { + normalizeResponse(_, __, data) { + return data; + } + } + this.owner.register('adapter:application', ApplicationAdapter); + this.owner.register('serializer:application', ApplicationSerializer); + this.owner.register('model:user', User); + this.owner.register('model:tool', Tool); + + const user = store.push({ + data: { + id: '1', + type: 'user', + attributes: { + name: '@runspired', + }, + relationships: { + tools: { + links: { + self: { href: '/the/original/path' }, + related: { href: '/the/related/link' }, + first: { href: '/the/related/link?page=1' }, + prev: null, + last: { href: '/the/related/link?page=3' }, + next: { href: '/the/related/link?page=2' }, + }, + }, + }, + }, + }); + + // Test we have access via the HasManyReference + const toolsRef = user.hasMany('tools'); + let links = toolsRef.links(); + assert.strictEqual(!!links, true, 'We have a links value on the relationship HasManyReference'); + assert.deepEqual(links.related, { href: '/the/related/link' }, 'The related link is correctly available'); + assert.deepEqual(links.first, { href: '/the/related/link?page=1' }, 'The first link is correctly available'); + assert.deepEqual(links.last, { href: '/the/related/link?page=3' }, 'The last link is correctly available'); + assert.deepEqual(links.prev, null, 'The prev link is correctly available'); + assert.deepEqual(links.next, { href: '/the/related/link?page=2' }, 'The next link is correctly available'); + assert.deepEqual(links.self, { href: '/the/original/path' }, 'The self link is correctly available'); + + // Test we have access via the PromiseManyArray + links = user.tools.links; + assert.deepEqual(links.related, { href: '/the/related/link' }, 'The related link is correctly available'); + assert.deepEqual(links.first, { href: '/the/related/link?page=1' }, 'The first link is correctly available'); + assert.deepEqual(links.last, { href: '/the/related/link?page=3' }, 'The last link is correctly available'); + assert.deepEqual(links.prev, null, 'The prev link is correctly available'); + assert.deepEqual(links.next, { href: '/the/related/link?page=2' }, 'The next link is correctly available'); + assert.deepEqual(links.self, { href: '/the/original/path' }, 'The self link is correctly available'); + + // Make a request that returns top-level relationship links + const toolsRel = await user.tools; + + links = toolsRef.links(); + assert.strictEqual(!!links, true, 'We have a links value on the relationship HasManyReference'); + assert.deepEqual( + links.related, + { href: '/the/new/related/link?page=3' }, + 'The related link is correctly available' + ); + assert.deepEqual(links.first, { href: '/the/new/related/link?page=1' }, 'The first link is correctly available'); + assert.deepEqual(links.last, { href: '/the/new/related/link?page=5' }, 'The last link is correctly available'); + assert.deepEqual(links.prev, { href: '/the/new/related/link?page=2' }, 'The prev link is correctly available'); + assert.deepEqual(links.next, { href: '/the/new/related/link?page=4' }, 'The next link is correctly available'); + assert.deepEqual(links.self, { href: '/some/other/path' }, 'The self link is correctly available'); + + // Test we have access via the ManyArray + links = toolsRel.links; + assert.strictEqual(!!links, true, 'We have a links value on the relationship ManyArray'); + assert.deepEqual( + links.related, + { href: '/the/new/related/link?page=3' }, + 'The related link is correctly available' + ); + assert.deepEqual(links.first, { href: '/the/new/related/link?page=1' }, 'The first link is correctly available'); + assert.deepEqual(links.last, { href: '/the/new/related/link?page=5' }, 'The last link is correctly available'); + assert.deepEqual(links.prev, { href: '/the/new/related/link?page=2' }, 'The prev link is correctly available'); + assert.deepEqual(links.next, { href: '/the/new/related/link?page=4' }, 'The next link is correctly available'); + assert.deepEqual(links.self, { href: '/some/other/path' }, 'The self link is correctly available'); + }); + } +}); diff --git a/packages/-ember-data/tests/integration/store-test.js b/packages/-ember-data/tests/integration/store-test.js index dcbe559f596..afc215b3893 100644 --- a/packages/-ember-data/tests/integration/store-test.js +++ b/packages/-ember-data/tests/integration/store-test.js @@ -1,5 +1,5 @@ import { Promise, resolve } from 'rsvp'; -import { run, next } from '@ember/runloop'; +import { run } from '@ember/runloop'; import { setupTest } from 'ember-qunit'; import Ember from 'ember'; import testInDebug from 'dummy/tests/helpers/test-in-debug'; @@ -8,6 +8,7 @@ import { module, test } from 'qunit'; import RESTAdapter from '@ember-data/adapter/rest'; import RESTSerializer from '@ember-data/serializer/rest'; import JSONAPISerializer from '@ember-data/serializer/json-api'; +import { settled } from '@ember/test-helpers'; import DS from 'ember-data'; @@ -36,7 +37,7 @@ Car.reopenClass({ function ajaxResponse(value) { return function(url, verb, hash) { - return run(() => resolve(deepCopy(value))); + return resolve(deepCopy(value)); }; } @@ -68,18 +69,21 @@ module('integration/store - destroy', function(hooks) { this.owner.register('serializer:application', JSONAPISerializer.extend()); }); - test("destroying record during find doesn't cause error", function(assert) { - assert.expect(0); - let done = assert.async(); + test("destroying record during find doesn't cause unexpected error (find resolves)", async function(assert) { + assert.expect(1); let store = this.owner.lookup('service:store'); let TestAdapter = DS.Adapter.extend({ findRecord(store, type, id, snapshot) { return new Promise((resolve, reject) => { - next(() => { - store.unloadAll(type.modelName); - reject(); + store.unloadAll(type.modelName); + resolve({ + data: { + type: 'car', + id: '1', + attributes: {}, + }, }); }); }, @@ -88,20 +92,49 @@ module('integration/store - destroy', function(hooks) { this.owner.register('adapter:application', TestAdapter); let type = 'car'; - let id = 1; + let id = '1'; + + try { + await store.findRecord(type, id); + assert.ok(true, 'we have no error'); + } catch (e) { + assert.ok(false, `we should have no error, received: ${e.message}`); + } + }); + + test("destroying record during find doesn't cause unexpected error (find rejects)", async function(assert) { + assert.expect(1); + + let store = this.owner.lookup('service:store'); + + let TestAdapter = DS.Adapter.extend({ + findRecord(store, type, id, snapshot) { + return new Promise((resolve, reject) => { + store.unloadAll(type.modelName); + reject(new Error('Record Was Not Found')); + }); + }, + }); + + this.owner.register('adapter:application', TestAdapter); + + let type = 'car'; + let id = '1'; - return run(() => store.findRecord(type, id).then(done, done)); + try { + await store.findRecord(type, id); + assert.ok(false, 'we have no error, but we should'); + } catch (e) { + assert.strictEqual(e.message, 'Record Was Not Found', `we should have a NotFound error`); + } }); testInDebug('find calls do not resolve when the store is destroyed', async function(assert) { assert.expect(2); - let done = assert.async(); let store = this.owner.lookup('service:store'); let next; - let nextPromise = new Promise(resolve => { - next = resolve; - }); + let nextPromise = new Promise(resolve => (next = resolve)); let TestAdapter = DS.Adapter.extend({ findRecord() { next(); @@ -125,11 +158,11 @@ module('integration/store - destroy', function(hooks) { store.shouldTrackAsyncRequests = true; store.push = function() { - assert('The test should have destroyed the store by now', store.get('isDestroyed')); + assert('The test should have destroyed the store by now', store.isDestroyed); throw new Error("We shouldn't be pushing data into the store when it is destroyed"); }; - store.findRecord('car', '1'); + let requestPromise = store.findRecord('car', '1'); await nextPromise; @@ -138,66 +171,66 @@ module('integration/store - destroy', function(hooks) { }, /Async Request leaks detected/); next(); + await nextPromise; // ensure we allow the internal store promises // to flush, potentially pushing data into the store - setTimeout(() => { - assert.ok(true, 'We made it to the end'); - done(); - }, 0); + await settled(); + assert.ok(true, 'we made it to the end'); + await requestPromise; + assert.ok(false, 'we should never make it here'); }); - test('destroying the store correctly cleans everything up', function(assert) { + test('destroying the store correctly cleans everything up', async function(assert) { let car, person; let store = this.owner.lookup('service:store'); let adapter = store.adapterFor('application'); adapter.shouldBackgroundReloadRecord = () => false; - run(() => { - store.push({ - data: [ - { - type: 'car', - id: '1', - attributes: { - make: 'BMC', - model: 'Mini', - }, - relationships: { - person: { - data: { type: 'person', id: '1' }, - }, - }, + store.push({ + data: [ + { + type: 'car', + id: '1', + attributes: { + make: 'BMC', + model: 'Mini', }, - { - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale', + relationships: { + person: { + data: { type: 'person', id: '1' }, }, - relationships: { - cars: { - data: [{ type: 'car', id: '1' }], - }, + }, + }, + { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + relationships: { + cars: { + data: [{ type: 'car', id: '1' }], }, }, - ], - }); - car = store.peekRecord('car', 1); - person = store.peekRecord('person', 1); + }, + ], }); + car = store.peekRecord('car', '1'); + person = store.peekRecord('person', '1'); + let personWillDestroy = tap(person, 'willDestroy'); let carWillDestroy = tap(car, 'willDestroy'); - let carsWillDestroy = run(() => tap(car.get('person.cars'), 'willDestroy')); + let carsWillDestroy = tap(car.get('person.cars'), 'willDestroy'); adapter.query = function() { return { data: [ { - id: 2, + id: '2', type: 'person', attributes: { name: 'Yehuda' }, }, @@ -205,15 +238,13 @@ module('integration/store - destroy', function(hooks) { }; }; - let adapterPopulatedPeople = run(() => { - return store.query('person', { - someCrazy: 'query', - }); + let adapterPopulatedPeople = await store.query('person', { + someCrazy: 'query', }); - let adapterPopulatedPeopleWillDestroy = tap(adapterPopulatedPeople.get('content'), 'willDestroy'); + let adapterPopulatedPeopleWillDestroy = tap(adapterPopulatedPeople, 'willDestroy'); - run(() => store.findRecord('person', 2)); + await store.findRecord('person', '2'); assert.equal(personWillDestroy.called.length, 0, 'expected person.willDestroy to not have been called'); assert.equal(carWillDestroy.called.length, 0, 'expected car.willDestroy to not have been called'); @@ -226,15 +257,17 @@ module('integration/store - destroy', function(hooks) { assert.equal(car.get('person'), person, "expected car's person to be the correct person"); assert.equal(person.get('cars.firstObject'), car, " expected persons cars's firstRecord to be the correct car"); - run(store, 'destroy'); + store.destroy(); - assert.equal(personWillDestroy.called.length, 1, 'expected person to have recieved willDestroy once'); - assert.equal(carWillDestroy.called.length, 1, 'expected car to recieve willDestroy once'); - assert.equal(carsWillDestroy.called.length, 1, 'expected person.cars to recieve willDestroy once'); + await settled(); + + assert.equal(personWillDestroy.called.length, 1, 'expected person to have received willDestroy once'); + assert.equal(carWillDestroy.called.length, 1, 'expected car to have received willDestroy once'); + assert.equal(carsWillDestroy.called.length, 1, 'expected person.cars to have received willDestroy once'); assert.equal( adapterPopulatedPeopleWillDestroy.called.length, 1, - 'expected adapterPopulatedPeople to recieve willDestroy once' + 'expected adapterPopulatedPeople to receive willDestroy once' ); }); }); @@ -274,45 +307,49 @@ module('integration/store - findRecord', function(hooks) { }); }); - test('store#findRecord returns cached record immediately and reloads record in the background', function(assert) { - assert.expect(2); + test('store#findRecord returns cached record immediately and reloads record in the background', async function(assert) { + assert.expect(4); let store = this.owner.lookup('service:store'); let adapter = store.adapterFor('application'); - - run(() => { - store.push({ - data: { - type: 'car', - id: '1', - attributes: { - make: 'BMC', - model: 'Mini', - }, - }, - }); - }); - - adapter.ajax = ajaxResponse({ - cars: [ - { - id: 1, + adapter.shouldReloadRecord = () => false; + adapter.shouldBackgroundReloadRecord = () => true; + + store.push({ + data: { + type: 'car', + id: '1', + attributes: { make: 'BMC', - model: 'Princess', + model: 'Mini', }, - ], + }, }); - run(() => { - return store.findRecord('car', 1).then(car => { - assert.equal(car.get('model'), 'Mini', 'cached car record is returned'); + adapter.ajax = () => { + return new Promise(resolve => setTimeout(resolve, 1)).then(() => { + return { + cars: [ + { + id: '1', + make: 'BMC', + model: 'Princess', + }, + ], + }; }); - }); + }; - run(() => { - let car = store.peekRecord('car', 1); - assert.equal(car.get('model'), 'Princess', 'car record was reloaded'); - }); + const promiseCar = store.findRecord('car', '1'); + const car = await promiseCar; + + assert.equal(promiseCar.get('model'), 'Mini', 'promiseCar is from cache'); + assert.equal(car.get('model'), 'Mini', 'car record is returned from cache'); + + await settled(); + + assert.equal(promiseCar.get('model'), 'Princess', 'promiseCar is updated'); + assert.equal(car.get('model'), 'Princess', 'Updated car record is returned'); }); test('store#findRecord { reload: true } ignores cached record and reloads record from server', function(assert) { @@ -561,7 +598,7 @@ module('integration/store - findRecord', function(hooks) { badValues.map(item => { assert.expectAssertion(() => { store.findRecord('car', item); - }, `Expected id to be a string or number, recieved ${String(item)}`); + }, `Expected id to be a string or number, received ${String(item)}`); }); }); } diff --git a/packages/-ember-data/tests/test-helper.js b/packages/-ember-data/tests/test-helper.js index 6bde911fcfa..baefbda919a 100644 --- a/packages/-ember-data/tests/test-helper.js +++ b/packages/-ember-data/tests/test-helper.js @@ -3,38 +3,60 @@ import config from '../config/environment'; import RSVP from 'rsvp'; import { setApplication } from '@ember/test-helpers'; import { start } from 'ember-qunit'; +import { DEBUG } from '@glimmer/env'; import QUnit from 'qunit'; -import DS from 'ember-data'; import { wait, asyncEqual, invokeAsync } from 'dummy/tests/helpers/async'; +import configureAsserts from 'dummy/tests/helpers/qunit-asserts'; +import { SHOULD_ASSERT_ALL } from './helpers/deprecated-test'; + +configureAsserts(); setApplication(Application.create(config.APP)); const { assert } = QUnit; -const transforms = { - boolean: DS.BooleanTransform.create(), - date: DS.DateTransform.create(), - number: DS.NumberTransform.create(), - string: DS.StringTransform.create(), -}; QUnit.begin(() => { + function assertAllDeprecations(assert) { + if (typeof assert.test.expected === 'number') { + assert.test.expected += 1; + } + assert.expectNoDeprecation(undefined, undefined, deprecation => { + // only assert EmberData deprecations + const id = deprecation.options.id; + const isEmberDataDeprecation = id.includes('DS') || id.includes('EmberData') || id.includes('ember-data'); + + if (!isEmberDataDeprecation) { + // eslint-disable-next-line no-console + console.log('Detected Non-Ember-Data Deprecation', deprecation); + } + + return isEmberDataDeprecation; + }); + } + // ensure we don't regress quietly + // this plays nicely with `expectDeprecation` + if (DEBUG) { + QUnit.config.modules.forEach(mod => { + const hooks = (mod.hooks.afterEach = mod.hooks.afterEach || []); + + if (mod.tests.length !== 0) { + if (SHOULD_ASSERT_ALL) { + hooks.unshift(assertAllDeprecations); + } + } + }); + } + RSVP.configure('onerror', reason => { // only print error messages if they're exceptions; // otherwise, let a future turn of the event loop // handle the error. + // TODO kill this off if (reason && reason instanceof Error) { throw reason; } }); - - // Prevent all tests involving serialization to require a container - // TODO kill the need for this - DS.JSONSerializer.reopen({ - transformFor(attributeType) { - return this._super(attributeType, true) || transforms[attributeType]; - }, - }); }); assert.wait = wait; diff --git a/packages/-ember-data/tests/unit/promise-proxies-test.js b/packages/-ember-data/tests/unit/promise-proxies-test.js index bf1222fd5c3..9ab60916590 100644 --- a/packages/-ember-data/tests/unit/promise-proxies-test.js +++ b/packages/-ember-data/tests/unit/promise-proxies-test.js @@ -1,6 +1,9 @@ import { Promise as EmberPromise } from 'rsvp'; import { A } from '@ember/array'; - +import Model, { belongsTo } from '@ember-data/model'; +import Adapter from '@ember-data/adapter'; +import JSONAPISerializer from '@ember-data/serializer/json-api'; +import { setupTest } from 'ember-qunit'; import { module, test } from 'qunit'; import DS from 'ember-data'; @@ -110,3 +113,69 @@ module('PromiseManyArray', function() { }); }); }); + +module('unit/PromiseBelongsTo', function(hooks) { + setupTest(hooks); + + class Parent extends Model { + @belongsTo('child', { async: true }) + child; + } + class Child extends Model { + @belongsTo('parent', { async: false }) + parent; + } + class ChildAdapter extends Adapter { + findRecord(store, type, id, snapshot) { + const ChildRecord = { + data: { + id: '1', + type: 'child', + relationships: { + parent: { + data: { + id: 1, + type: 'parent', + }, + }, + }, + }, + }; + return EmberPromise.resolve(ChildRecord); + } + } + + test('meta property exists', function(assert) { + const { owner } = this; + owner.register('model:parent', Parent); + owner.register('model:child', Child); + owner.register('adapter:child', ChildAdapter); + owner.register('serializer:application', JSONAPISerializer.extend()); + const store = owner.lookup('service:store'); + const meta = { + example: 'example meta', + }; + const parent = store.push({ + data: { + id: '1', + type: 'parent', + relationships: { + child: { + data: { + type: 'child', + id: '1', + }, + meta, + }, + }, + }, + }); + + const belongsToProxy = parent.child; + + assert.expectAssertion(() => { + belongsToProxy.get('meta'); + }, 'You attempted to access meta on the promise for the async belongsTo relationship ' + `child:child'.` + '\nUse `record.belongsTo(relationshipName).meta()` instead.'); + assert.equal(parent.belongsTo('child').meta(), meta); + }); +}); diff --git a/packages/-ember-data/tests/unit/store/peek-record-test.js b/packages/-ember-data/tests/unit/store/peek-record-test.js index 018ceebee79..ec310b1c007 100644 --- a/packages/-ember-data/tests/unit/store/peek-record-test.js +++ b/packages/-ember-data/tests/unit/store/peek-record-test.js @@ -50,7 +50,7 @@ module('unit/store/peekRecord - Store peekRecord', function(hooks) { run(() => { assert.expectAssertion(() => { store.peekRecord('my-id'); - }, /Expected id to be a string or number, recieved undefined/); + }, /Expected id to be a string or number, received undefined/); }); }); diff --git a/packages/-fastboot-test-app/app/routes/person/new.js b/packages/-fastboot-test-app/app/routes/person/new.js new file mode 100644 index 00000000000..29d4d380b62 --- /dev/null +++ b/packages/-fastboot-test-app/app/routes/person/new.js @@ -0,0 +1,10 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; + +export default Route.extend({ + store: service(), + + model() { + return this.store.createRecord('person'); + }, +}); diff --git a/packages/-fastboot-test-app/app/templates/person/new.hbs b/packages/-fastboot-test-app/app/templates/person/new.hbs new file mode 100644 index 00000000000..f16b2fa3520 --- /dev/null +++ b/packages/-fastboot-test-app/app/templates/person/new.hbs @@ -0,0 +1,6 @@ +
+ +
diff --git a/packages/-fastboot-test-app/tests/fastboot/person/new-test.js b/packages/-fastboot-test-app/tests/fastboot/person/new-test.js new file mode 100644 index 00000000000..8aaf0940e66 --- /dev/null +++ b/packages/-fastboot-test-app/tests/fastboot/person/new-test.js @@ -0,0 +1,16 @@ +import { module, test } from 'qunit'; +import { setup, visit } from 'ember-cli-fastboot-testing/test-support'; + +module('FastBoot | /person/new', function(hooks) { + setup(hooks); + + test('it does not error in SSR (GH#6563)', async function(assert) { + await visit('/person/new'); + + // from application.hbs + assert.dom('h1').hasText('Ember Data'); + assert.dom('a').hasAttribute('href', '/tests'); + + assert.dom('.person-name').exists(); + }); +}); diff --git a/packages/adapter/addon/index.js b/packages/adapter/addon/index.js index c7f1824eb5f..042f53daaec 100644 --- a/packages/adapter/addon/index.js +++ b/packages/adapter/addon/index.js @@ -1,4 +1,6 @@ /** + * + * @module @ember-data/adapter @main @ember-data/adapter */ @@ -56,6 +58,7 @@ import EmberObject from '@ember/object'; For an example of the implementation, see `RESTAdapter`, the included REST adapter. + @module @ember-data/adapter @class Adapter @extends EmberObject */ @@ -77,6 +80,7 @@ export default EmberObject.extend({ }); ``` + @deprecated @property defaultSerializer @type {String} */ diff --git a/packages/adapter/blueprints/adapter-test/index.js b/packages/adapter/blueprints/adapter-test/index.js index 77f6b5a9f88..0e78312068b 100644 --- a/packages/adapter/blueprints/adapter-test/index.js +++ b/packages/adapter/blueprints/adapter-test/index.js @@ -1,5 +1,5 @@ const testInfo = require('ember-cli-test-info'); -const useTestFrameworkDetector = require('@ember-data/-build-infra/src/utilities/test-framework-detector'); +const useTestFrameworkDetector = require('@ember-data/private-build-infra/src/utilities/test-framework-detector'); const path = require('path'); module.exports = useTestFrameworkDetector({ diff --git a/packages/adapter/blueprints/adapter/index.js b/packages/adapter/blueprints/adapter/index.js index 1c26faa54eb..77ab1bcb103 100644 --- a/packages/adapter/blueprints/adapter/index.js +++ b/packages/adapter/blueprints/adapter/index.js @@ -1,5 +1,5 @@ -const extendFromApplicationEntity = require('@ember-data/-build-infra/src/utilities/extend-from-application-entity'); -const useEditionDetector = require('@ember-data/-build-infra/src/utilities/edition-detector'); +const extendFromApplicationEntity = require('@ember-data/private-build-infra/src/utilities/extend-from-application-entity'); +const useEditionDetector = require('@ember-data/private-build-infra/src/utilities/edition-detector'); module.exports = useEditionDetector({ description: 'Generates an ember-data adapter.', diff --git a/packages/adapter/index.js b/packages/adapter/index.js index ae1f17ebf02..9e3bb99154d 100644 --- a/packages/adapter/index.js +++ b/packages/adapter/index.js @@ -1,7 +1,7 @@ 'use strict'; const name = require('./package').name; -const addonBuildConfigForDataPackage = require('@ember-data/-build-infra/src/addon-build-config-for-data-package'); +const addonBuildConfigForDataPackage = require('@ember-data/private-build-infra/src/addon-build-config-for-data-package'); const addonBaseConfig = addonBuildConfigForDataPackage(name); module.exports = Object.assign({}, addonBaseConfig, { diff --git a/packages/adapter/node-tests/blueprints/adapter-test.js b/packages/adapter/node-tests/blueprints/adapter-test.js index 4d4836304de..060fca37d78 100644 --- a/packages/adapter/node-tests/blueprints/adapter-test.js +++ b/packages/adapter/node-tests/blueprints/adapter-test.js @@ -12,10 +12,10 @@ const expect = chai.expect; const SilentError = require('silent-error'); -const generateFakePackageManifest = require('@ember-data/-test-infra/src/node-test-helpers/generate-fake-package-manifest'); -const fixture = require('@ember-data/-test-infra/src/node-test-helpers/fixture'); +const generateFakePackageManifest = require('@ember-data/unpublished-test-infra/src/node-test-helpers/generate-fake-package-manifest'); +const fixture = require('@ember-data/unpublished-test-infra/src/node-test-helpers/fixture'); -const setupTestEnvironment = require('@ember-data/-test-infra/src/node-test-helpers/setup-test-environment'); +const setupTestEnvironment = require('@ember-data/unpublished-test-infra/src/node-test-helpers/setup-test-environment'); const enableOctane = setupTestEnvironment.enableOctane; describe('Acceptance: generate and destroy adapter blueprints', function() { diff --git a/packages/adapter/package.json b/packages/adapter/package.json index 432f17c2f80..61f12a09d9a 100644 --- a/packages/adapter/package.json +++ b/packages/adapter/package.json @@ -20,7 +20,7 @@ "test:node": "mocha" }, "dependencies": { - "@ember-data/-build-infra": "3.15.0-alpha.1", + "@ember-data/private-build-infra": "3.15.0-alpha.1", "@ember-data/store": "3.15.0-alpha.1", "@ember/edition-utils": "^1.1.1", "ember-cli-babel": "^7.12.0", @@ -28,8 +28,8 @@ "ember-cli-typescript": "^3.0.0" }, "devDependencies": { - "@ember-data/-test-infra": "3.15.0-alpha.1", - "@ember/optional-features": "^1.0.0", + "@ember-data/unpublished-test-infra": "3.15.0-alpha.1", + "@ember/optional-features": "^1.1.0", "broccoli-asset-rev": "^3.0.0", "ember-cli": "~3.13.1", "ember-cli-blueprint-test-helpers": "^0.19.1", @@ -40,11 +40,11 @@ "ember-cli-uglify": "3.0.0", "ember-disable-prototype-extensions": "^1.1.3", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", + "ember-source": "^3.14.1", "ember-source-channel-url": "^2.0.1", "ember-try": "^1.2.1", "loader.js": "^4.7.0", diff --git a/packages/canary-features/README.md b/packages/canary-features/README.md index 6b5e98b4260..acb84c1d340 100644 --- a/packages/canary-features/README.md +++ b/packages/canary-features/README.md @@ -1,4 +1,4 @@ -# @ember-data/-build-infra +# @ember-data/private-build-infra !! This is an internal package for use by `@ember-data` only. !! diff --git a/packages/canary-features/addon/default-features.js b/packages/canary-features/addon/default-features.ts similarity index 90% rename from packages/canary-features/addon/default-features.js rename to packages/canary-features/addon/default-features.ts index 1dabac4872a..3f46c1075bc 100644 --- a/packages/canary-features/addon/default-features.js +++ b/packages/canary-features/addon/default-features.ts @@ -3,7 +3,7 @@ */ /* - This list of features is used both at build time (by `@ember-data/-build-infra`) + This list of features is used both at build time (by `@ember-data/private-build-infra`) and at runtime (by `@ember-data/canary-features`). The valid values are: @@ -19,4 +19,5 @@ export default { IDENTIFIERS: true, REQUEST_SERVICE: null, CUSTOM_MODEL_CLASS: null, + FULL_LINKS_ON_RELATIONSHIPS: null, }; diff --git a/packages/canary-features/addon/index.js b/packages/canary-features/addon/index.ts similarity index 61% rename from packages/canary-features/addon/index.js rename to packages/canary-features/addon/index.ts index 0850dc7e680..411026363c6 100644 --- a/packages/canary-features/addon/index.js +++ b/packages/canary-features/addon/index.ts @@ -7,9 +7,19 @@ import { assign } from '@ember/polyfills'; import DEFAULT_FEATURES from './default-features'; -const ENV = typeof EmberDataENV === 'object' && EmberDataENV !== null ? EmberDataENV : {}; +interface ConfigEnv { + ENABLE_OPTIONAL_FEATURES?: boolean; + FEATURES?: { + [key in keyof typeof DEFAULT_FEATURES]: boolean | null; + }; +} + +declare global { + export const EmberDataENV: ConfigEnv | undefined | null; +} +const ENV: ConfigEnv = typeof EmberDataENV === 'object' && EmberDataENV !== null ? EmberDataENV : {}; -function featureValue(value) { +function featureValue(value: boolean | null): boolean | null { if (ENV.ENABLE_OPTIONAL_FEATURES && value === null) { return true; } @@ -24,3 +34,4 @@ export const RECORD_DATA_STATE = featureValue(FEATURES.RECORD_DATA_STATE); export const REQUEST_SERVICE = featureValue(FEATURES.REQUEST_SERVICE); export const IDENTIFIERS = featureValue(FEATURES.IDENTIFIERS); export const CUSTOM_MODEL_CLASS = featureValue(FEATURES.CUSTOM_MODEL_CLASS); +export const FULL_LINKS_ON_RELATIONSHIPS = featureValue(FEATURES.FULL_LINKS_ON_RELATIONSHIPS); diff --git a/packages/canary-features/package.json b/packages/canary-features/package.json index cd118594cc3..8572e013c63 100644 --- a/packages/canary-features/package.json +++ b/packages/canary-features/package.json @@ -14,7 +14,8 @@ }, "scripts": {}, "dependencies": { - "ember-cli-babel": "^7.12.0" + "ember-cli-babel": "^7.12.0", + "ember-cli-typescript": "^3.0.0" }, "devDependencies": { "babel-plugin-debug-macros": "^0.3.3", diff --git a/packages/debug/index.js b/packages/debug/index.js index aa6c2f47bc7..386a0497cf9 100644 --- a/packages/debug/index.js +++ b/packages/debug/index.js @@ -1,7 +1,7 @@ 'use strict'; const name = require('./package').name; -const addonBuildConfigForDataPackage = require('@ember-data/-build-infra/src/addon-build-config-for-data-package'); +const addonBuildConfigForDataPackage = require('@ember-data/private-build-infra/src/addon-build-config-for-data-package'); const addonBaseConfig = addonBuildConfigForDataPackage(name); module.exports = Object.assign({}, addonBaseConfig, { diff --git a/packages/debug/package.json b/packages/debug/package.json index 4f08831cab9..465c041516b 100644 --- a/packages/debug/package.json +++ b/packages/debug/package.json @@ -19,15 +19,15 @@ "test:all": "ember try:each" }, "dependencies": { - "@ember-data/-build-infra": "3.15.0-alpha.1", + "@ember-data/private-build-infra": "3.15.0-alpha.1", "@ember/edition-utils": "^1.1.1", "ember-cli-babel": "^7.12.0", "ember-cli-test-info": "^1.0.0", "ember-cli-typescript": "^3.0.0" }, "devDependencies": { - "@ember-data/-test-infra": "3.15.0-alpha.1", - "@ember/optional-features": "^1.0.0", + "@ember-data/unpublished-test-infra": "3.15.0-alpha.1", + "@ember/optional-features": "^1.1.0", "broccoli-asset-rev": "^3.0.0", "ember-cli": "~3.13.1", "ember-cli-blueprint-test-helpers": "^0.19.1", @@ -38,11 +38,11 @@ "ember-cli-uglify": "3.0.0", "ember-disable-prototype-extensions": "^1.1.3", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", + "ember-source": "^3.14.1", "ember-source-channel-url": "^2.0.1", "ember-try": "^1.2.1", "loader.js": "^4.7.0", diff --git a/packages/model/blueprints/model-test/index.js b/packages/model/blueprints/model-test/index.js index d77848a9046..78d90a51089 100644 --- a/packages/model/blueprints/model-test/index.js +++ b/packages/model/blueprints/model-test/index.js @@ -1,6 +1,6 @@ const ModelBlueprint = require('../model'); const testInfo = require('ember-cli-test-info'); -const useTestFrameworkDetector = require('@ember-data/-build-infra/src/utilities/test-framework-detector'); +const useTestFrameworkDetector = require('@ember-data/private-build-infra/src/utilities/test-framework-detector'); const path = require('path'); module.exports = useTestFrameworkDetector({ diff --git a/packages/model/blueprints/model/index.js b/packages/model/blueprints/model/index.js index 6e93e69a0d2..0e7f3560d45 100644 --- a/packages/model/blueprints/model/index.js +++ b/packages/model/blueprints/model/index.js @@ -1,7 +1,7 @@ const inflection = require('inflection'); const stringUtils = require('ember-cli-string-utils'); const EOL = require('os').EOL; -const useEditionDetector = require('@ember-data/-build-infra/src/utilities/edition-detector'); +const useEditionDetector = require('@ember-data/private-build-infra/src/utilities/edition-detector'); const { has } = require('@ember/edition-utils'); module.exports = useEditionDetector({ diff --git a/packages/model/index.js b/packages/model/index.js index 5816ec32ad2..764cd8cccd0 100644 --- a/packages/model/index.js +++ b/packages/model/index.js @@ -1,7 +1,7 @@ 'use strict'; const name = require('./package').name; -const addonBuildConfigForDataPackage = require('@ember-data/-build-infra/src/addon-build-config-for-data-package'); +const addonBuildConfigForDataPackage = require('@ember-data/private-build-infra/src/addon-build-config-for-data-package'); const addonBaseConfig = addonBuildConfigForDataPackage(name); module.exports = Object.assign({}, addonBaseConfig, { diff --git a/packages/model/node-tests/blueprints/model-test.js b/packages/model/node-tests/blueprints/model-test.js index c0e1b48d3a7..a2541d68c8d 100644 --- a/packages/model/node-tests/blueprints/model-test.js +++ b/packages/model/node-tests/blueprints/model-test.js @@ -9,10 +9,10 @@ const modifyPackages = blueprintHelpers.modifyPackages; const chai = require('ember-cli-blueprint-test-helpers/chai'); const expect = chai.expect; -const generateFakePackageManifest = require('@ember-data/-test-infra/src/node-test-helpers/generate-fake-package-manifest'); -const fixture = require('@ember-data/-test-infra/src/node-test-helpers/fixture'); +const generateFakePackageManifest = require('@ember-data/unpublished-test-infra/src/node-test-helpers/generate-fake-package-manifest'); +const fixture = require('@ember-data/unpublished-test-infra/src/node-test-helpers/fixture'); -const setupTestEnvironment = require('@ember-data/-test-infra/src/node-test-helpers/setup-test-environment'); +const setupTestEnvironment = require('@ember-data/unpublished-test-infra/src/node-test-helpers/setup-test-environment'); const enableOctane = setupTestEnvironment.enableOctane; describe('Acceptance: generate and destroy model blueprints', function() { diff --git a/packages/model/package.json b/packages/model/package.json index 410c0e7c4f7..3aa23db7d2b 100644 --- a/packages/model/package.json +++ b/packages/model/package.json @@ -21,7 +21,7 @@ "test:node": "mocha" }, "dependencies": { - "@ember-data/-build-infra": "3.15.0-alpha.1", + "@ember-data/private-build-infra": "3.15.0-alpha.1", "@ember-data/canary-features": "3.15.0-alpha.1", "@ember-data/store": "3.15.0-alpha.1", "@ember/edition-utils": "^1.1.1", @@ -33,8 +33,8 @@ "inflection": "1.12.0" }, "devDependencies": { - "@ember-data/-test-infra": "3.15.0-alpha.1", - "@ember/optional-features": "^1.0.0", + "@ember-data/unpublished-test-infra": "3.15.0-alpha.1", + "@ember/optional-features": "^1.1.0", "broccoli-asset-rev": "^3.0.0", "ember-cli": "~3.13.1", "ember-cli-blueprint-test-helpers": "^0.19.1", @@ -45,11 +45,11 @@ "ember-cli-uglify": "3.0.0", "ember-disable-prototype-extensions": "^1.1.3", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", + "ember-source": "^3.14.1", "ember-source-channel-url": "^2.0.1", "ember-try": "^1.2.1", "loader.js": "^4.7.0", diff --git a/packages/-build-infra/.npmignore b/packages/private-build-infra/.npmignore similarity index 100% rename from packages/-build-infra/.npmignore rename to packages/private-build-infra/.npmignore diff --git a/packages/-adapter-encapsulation-test-app/.watchmanconfig b/packages/private-build-infra/.watchmanconfig similarity index 100% rename from packages/-adapter-encapsulation-test-app/.watchmanconfig rename to packages/private-build-infra/.watchmanconfig diff --git a/packages/-build-infra/LICENSE.md b/packages/private-build-infra/LICENSE.md similarity index 100% rename from packages/-build-infra/LICENSE.md rename to packages/private-build-infra/LICENSE.md diff --git a/packages/-build-infra/README.md b/packages/private-build-infra/README.md similarity index 90% rename from packages/-build-infra/README.md rename to packages/private-build-infra/README.md index 6b5e98b4260..acb84c1d340 100644 --- a/packages/-build-infra/README.md +++ b/packages/private-build-infra/README.md @@ -1,4 +1,4 @@ -# @ember-data/-build-infra +# @ember-data/private-build-infra !! This is an internal package for use by `@ember-data` only. !! diff --git a/packages/-build-infra/config/in-progress-features.json b/packages/private-build-infra/config/in-progress-features.json similarity index 100% rename from packages/-build-infra/config/in-progress-features.json rename to packages/private-build-infra/config/in-progress-features.json diff --git a/packages/-build-infra/node-tests/unit/babel-plugin-remove-imports-test.js b/packages/private-build-infra/node-tests/unit/babel-plugin-remove-imports-test.js similarity index 100% rename from packages/-build-infra/node-tests/unit/babel-plugin-remove-imports-test.js rename to packages/private-build-infra/node-tests/unit/babel-plugin-remove-imports-test.js diff --git a/packages/-build-infra/package.json b/packages/private-build-infra/package.json similarity index 97% rename from packages/-build-infra/package.json rename to packages/private-build-infra/package.json index aa7488d5194..f6e3169a966 100644 --- a/packages/-build-infra/package.json +++ b/packages/private-build-infra/package.json @@ -1,5 +1,5 @@ { - "name": "@ember-data/-build-infra", + "name": "@ember-data/private-build-infra", "version": "3.15.0-alpha.1", "description": "The default blueprint for ember-data private packages.", "keywords": [], diff --git a/packages/-build-infra/src/addon-build-config-for-data-package.js b/packages/private-build-infra/src/addon-build-config-for-data-package.js similarity index 100% rename from packages/-build-infra/src/addon-build-config-for-data-package.js rename to packages/private-build-infra/src/addon-build-config-for-data-package.js diff --git a/packages/-build-infra/src/cli-flags.js b/packages/private-build-infra/src/cli-flags.js similarity index 100% rename from packages/-build-infra/src/cli-flags.js rename to packages/private-build-infra/src/cli-flags.js diff --git a/packages/-build-infra/src/create-version-module.js b/packages/private-build-infra/src/create-version-module.js similarity index 100% rename from packages/-build-infra/src/create-version-module.js rename to packages/private-build-infra/src/create-version-module.js diff --git a/packages/-build-infra/src/debug-macros.js b/packages/private-build-infra/src/debug-macros.js similarity index 100% rename from packages/-build-infra/src/debug-macros.js rename to packages/private-build-infra/src/debug-macros.js diff --git a/packages/-build-infra/src/features.js b/packages/private-build-infra/src/features.js similarity index 95% rename from packages/-build-infra/src/features.js rename to packages/private-build-infra/src/features.js index a0294389571..89b09cbb057 100644 --- a/packages/-build-infra/src/features.js +++ b/packages/private-build-infra/src/features.js @@ -2,7 +2,7 @@ const requireEsm = require('esm')(module); function getFeatures() { - const { default: features } = requireEsm('@ember-data/canary-features/addon/default-features.js'); + const { default: features } = requireEsm('@ember-data/canary-features/addon/default-features.ts'); const FEATURE_OVERRIDES = process.env.EMBER_DATA_FEATURE_OVERRIDE; if (FEATURE_OVERRIDES === 'ENABLE_ALL_OPTIONAL') { diff --git a/packages/-build-infra/src/stripped-build-plugins.js b/packages/private-build-infra/src/stripped-build-plugins.js similarity index 100% rename from packages/-build-infra/src/stripped-build-plugins.js rename to packages/private-build-infra/src/stripped-build-plugins.js diff --git a/packages/-build-infra/src/transforms/babel-plugin-remove-imports.js b/packages/private-build-infra/src/transforms/babel-plugin-remove-imports.js similarity index 100% rename from packages/-build-infra/src/transforms/babel-plugin-remove-imports.js rename to packages/private-build-infra/src/transforms/babel-plugin-remove-imports.js diff --git a/packages/-build-infra/src/transforms/package.json b/packages/private-build-infra/src/transforms/package.json similarity index 100% rename from packages/-build-infra/src/transforms/package.json rename to packages/private-build-infra/src/transforms/package.json diff --git a/packages/-build-infra/src/utilities/edition-detector.js b/packages/private-build-infra/src/utilities/edition-detector.js similarity index 100% rename from packages/-build-infra/src/utilities/edition-detector.js rename to packages/private-build-infra/src/utilities/edition-detector.js diff --git a/packages/-build-infra/src/utilities/extend-from-application-entity.js b/packages/private-build-infra/src/utilities/extend-from-application-entity.js similarity index 100% rename from packages/-build-infra/src/utilities/extend-from-application-entity.js rename to packages/private-build-infra/src/utilities/extend-from-application-entity.js diff --git a/packages/-build-infra/src/utilities/rollup-private-module.js b/packages/private-build-infra/src/utilities/rollup-private-module.js similarity index 100% rename from packages/-build-infra/src/utilities/rollup-private-module.js rename to packages/private-build-infra/src/utilities/rollup-private-module.js diff --git a/packages/-build-infra/src/utilities/test-framework-detector.js b/packages/private-build-infra/src/utilities/test-framework-detector.js similarity index 100% rename from packages/-build-infra/src/utilities/test-framework-detector.js rename to packages/private-build-infra/src/utilities/test-framework-detector.js diff --git a/packages/record-data/addon/-private/coerce-id.ts b/packages/record-data/addon/-private/coerce-id.ts index 26db1c73e37..e9f341d774a 100644 --- a/packages/record-data/addon/-private/coerce-id.ts +++ b/packages/record-data/addon/-private/coerce-id.ts @@ -30,7 +30,7 @@ export function ensureStringId(id: Coercable): string { } if (DEBUG && normalized === null) { - throw new Error(`Expected id to be a string or number, recieved ${String(id)}`); + throw new Error(`Expected id to be a string or number, received ${String(id)}`); } return normalized!; diff --git a/packages/record-data/addon/-private/record-data.ts b/packages/record-data/addon/-private/record-data.ts index a937b33f692..de613af39b1 100644 --- a/packages/record-data/addon/-private/record-data.ts +++ b/packages/record-data/addon/-private/record-data.ts @@ -135,7 +135,7 @@ export default class RecordDataDefault implements RelationshipRecordData { } getErrors(): JsonApiValidationError[] { - assert('Can not call getErrors unless the RECORD_DATA_ERRORS feature flag is on', RECORD_DATA_ERRORS); + assert('Can not call getErrors unless the RECORD_DATA_ERRORS feature flag is on', !!RECORD_DATA_ERRORS); if (RECORD_DATA_ERRORS) { let errors: JsonApiValidationError[] = this._errors || []; return errors; diff --git a/packages/record-data/addon/-private/relationships/state/belongs-to.ts b/packages/record-data/addon/-private/relationships/state/belongs-to.ts index 44408472acf..f449a3d8473 100644 --- a/packages/record-data/addon/-private/relationships/state/belongs-to.ts +++ b/packages/record-data/addon/-private/relationships/state/belongs-to.ts @@ -178,10 +178,8 @@ export default class BelongsToRelationship extends Relationship { if (this.inverseRecordData === null && this.hasAnyRelationshipData) { data = null; } - if (this.link) { - payload.links = { - related: this.link, - }; + if (this.links) { + payload.links = this.links; } if (data !== undefined) { payload.data = data; diff --git a/packages/record-data/addon/-private/relationships/state/has-many.ts b/packages/record-data/addon/-private/relationships/state/has-many.ts index ac78a79f8a8..0b4292294af 100755 --- a/packages/record-data/addon/-private/relationships/state/has-many.ts +++ b/packages/record-data/addon/-private/relationships/state/has-many.ts @@ -223,10 +223,8 @@ export default class ManyRelationship extends Relationship { if (this.hasAnyRelationshipData) { payload.data = this.currentState.map(recordData => recordData.getResourceIdentifier()); } - if (this.link) { - payload.links = { - related: this.link, - }; + if (this.links) { + payload.links = this.links; } if (this.meta) { payload.meta = this.meta; diff --git a/packages/record-data/addon/-private/relationships/state/relationship.ts b/packages/record-data/addon/-private/relationships/state/relationship.ts index 0bb97b2fb88..97d948b54fc 100644 --- a/packages/record-data/addon/-private/relationships/state/relationship.ts +++ b/packages/record-data/addon/-private/relationships/state/relationship.ts @@ -8,6 +8,7 @@ import { RelationshipRecordData } from '../../ts-interfaces/relationship-record- import { JsonApiRelationship } from '@ember-data/store/-private/ts-interfaces/record-data-json-api'; import { RelationshipSchema } from '@ember-data/store/-private/ts-interfaces/record-data-schemas'; import { CUSTOM_MODEL_CLASS } from '@ember-data/canary-features'; +import { PaginationLinks } from '@ember-data/store/-private/ts-interfaces/ember-data-json-api'; /** @module @ember-data/store @@ -41,7 +42,7 @@ export default class Relationship { hasAnyRelationshipData: boolean; relationshipIsEmpty: boolean; hasFailedLoadAttempt: boolean = false; - link?: string | null; + links?: PaginationLinks; willSync?: boolean; constructor( @@ -569,20 +570,8 @@ export default class Relationship { this.store._updateRelationshipState(this); } - updateLink(link: string | null) { - warn( - `You pushed a record of type '${this.recordData.modelName}' with a relationship '${this.key}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload. EmberData will treat this relationship as known-to-be-empty.`, - this.isAsync || this.hasAnyRelationshipData, - { - id: 'ds.store.push-link-for-sync-relationship', - } - ); - assert( - `You have pushed a record of type '${this.recordData.modelName}' with '${this.key}' as a link, but the value of that link is not a string.`, - typeof link === 'string' || link === null - ); - - this.link = link; + updateLinks(links: PaginationLinks): void { + this.links = links; } updateRecordDatasFromAdapter(recordDatas?: RelationshipRecordData[]) { @@ -646,11 +635,28 @@ export default class Relationship { this.updateData(data, initial); } - if (payload.links && payload.links.related) { - let relatedLink = _normalizeLink(payload.links.related); - if (relatedLink && relatedLink.href && relatedLink.href !== this.link) { - hasLink = true; - this.updateLink(relatedLink.href); + if (payload.links) { + let originalLinks = this.links; + this.updateLinks(payload.links); + if (payload.links.related) { + let relatedLink = _normalizeLink(payload.links.related); + let currentLink = originalLinks && originalLinks.related ? _normalizeLink(originalLinks.related) : null; + let currentLinkHref = currentLink ? currentLink.href : null; + + if (relatedLink && relatedLink.href && relatedLink.href !== currentLinkHref) { + warn( + `You pushed a record of type '${this.recordData.modelName}' with a relationship '${this.key}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload. EmberData will treat this relationship as known-to-be-empty.`, + this.isAsync || this.hasAnyRelationshipData, + { + id: 'ds.store.push-link-for-sync-relationship', + } + ); + assert( + `You have pushed a record of type '${this.recordData.modelName}' with '${this.key}' as a link, but the value of that link is not a string.`, + typeof relatedLink.href === 'string' || relatedLink.href === null + ); + hasLink = true; + } } } diff --git a/packages/record-data/index.js b/packages/record-data/index.js index a2bb42327df..e045674e509 100644 --- a/packages/record-data/index.js +++ b/packages/record-data/index.js @@ -1,7 +1,7 @@ 'use strict'; const name = require('./package').name; -const addonBuildConfigForDataPackage = require('@ember-data/-build-infra/src/addon-build-config-for-data-package'); +const addonBuildConfigForDataPackage = require('@ember-data/private-build-infra/src/addon-build-config-for-data-package'); const addonBaseConfig = addonBuildConfigForDataPackage(name); module.exports = Object.assign({}, addonBaseConfig, { diff --git a/packages/record-data/package.json b/packages/record-data/package.json index 2edd96a23dd..a312e8d26b7 100644 --- a/packages/record-data/package.json +++ b/packages/record-data/package.json @@ -19,7 +19,7 @@ "test:all": "ember try:each" }, "dependencies": { - "@ember-data/-build-infra": "3.15.0-alpha.1", + "@ember-data/private-build-infra": "3.15.0-alpha.1", "@ember-data/canary-features": "3.15.0-alpha.1", "@ember-data/store": "3.15.0-alpha.1", "@ember/edition-utils": "^1.1.1", @@ -29,8 +29,8 @@ "ember-cli-typescript": "^3.0.0" }, "devDependencies": { - "@ember-data/-test-infra": "3.15.0-alpha.1", - "@ember/optional-features": "^1.0.0", + "@ember-data/unpublished-test-infra": "3.15.0-alpha.1", + "@ember/optional-features": "^1.1.0", "broccoli-asset-rev": "^3.0.0", "ember-cli": "~3.13.1", "ember-cli-blueprint-test-helpers": "^0.19.1", @@ -41,11 +41,11 @@ "ember-cli-uglify": "3.0.0", "ember-disable-prototype-extensions": "^1.1.3", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", + "ember-source": "^3.14.1", "ember-source-channel-url": "^2.0.1", "ember-try": "^1.2.1", "loader.js": "^4.7.0", diff --git a/packages/serializer/addon/index.js b/packages/serializer/addon/index.js index f2ef4d0e95c..a6138cc0961 100644 --- a/packages/serializer/addon/index.js +++ b/packages/serializer/addon/index.js @@ -1,6 +1,5 @@ /** @module @ember-data/serializer - @main @ember-data/serializer */ import EmberObject from '@ember/object'; diff --git a/packages/serializer/blueprints/serializer-test/index.js b/packages/serializer/blueprints/serializer-test/index.js index 174017c3138..345c7228413 100644 --- a/packages/serializer/blueprints/serializer-test/index.js +++ b/packages/serializer/blueprints/serializer-test/index.js @@ -1,5 +1,5 @@ const testInfo = require('ember-cli-test-info'); -const useTestFrameworkDetector = require('@ember-data/-build-infra/src/utilities/test-framework-detector'); +const useTestFrameworkDetector = require('@ember-data/private-build-infra/src/utilities/test-framework-detector'); const path = require('path'); module.exports = useTestFrameworkDetector({ diff --git a/packages/serializer/blueprints/serializer/index.js b/packages/serializer/blueprints/serializer/index.js index 2fe7017ff69..1bd401b7eb5 100644 --- a/packages/serializer/blueprints/serializer/index.js +++ b/packages/serializer/blueprints/serializer/index.js @@ -1,5 +1,5 @@ -const extendFromApplicationEntity = require('@ember-data/-build-infra/src/utilities/extend-from-application-entity'); -const useEditionDetector = require('@ember-data/-build-infra/src/utilities/edition-detector'); +const extendFromApplicationEntity = require('@ember-data/private-build-infra/src/utilities/extend-from-application-entity'); +const useEditionDetector = require('@ember-data/private-build-infra/src/utilities/edition-detector'); module.exports = useEditionDetector({ description: 'Generates an ember-data serializer.', diff --git a/packages/serializer/blueprints/transform-test/index.js b/packages/serializer/blueprints/transform-test/index.js index 047e45ab6fd..b3b72ae37e8 100644 --- a/packages/serializer/blueprints/transform-test/index.js +++ b/packages/serializer/blueprints/transform-test/index.js @@ -1,5 +1,5 @@ const testInfo = require('ember-cli-test-info'); -const useTestFrameworkDetector = require('@ember-data/-build-infra/src/utilities/test-framework-detector'); +const useTestFrameworkDetector = require('@ember-data/private-build-infra/src/utilities/test-framework-detector'); const path = require('path'); module.exports = useTestFrameworkDetector({ diff --git a/packages/serializer/blueprints/transform/index.js b/packages/serializer/blueprints/transform/index.js index 903f7af1b7d..f3a140349ec 100644 --- a/packages/serializer/blueprints/transform/index.js +++ b/packages/serializer/blueprints/transform/index.js @@ -1,4 +1,4 @@ -const useEditionDetector = require('@ember-data/-build-infra/src/utilities/edition-detector'); +const useEditionDetector = require('@ember-data/private-build-infra/src/utilities/edition-detector'); module.exports = useEditionDetector({ description: 'Generates an ember-data value transform.', diff --git a/packages/serializer/index.js b/packages/serializer/index.js index 335b27c5cb8..d01c6668098 100644 --- a/packages/serializer/index.js +++ b/packages/serializer/index.js @@ -1,7 +1,7 @@ 'use strict'; const name = require('./package').name; -const addonBuildConfigForDataPackage = require('@ember-data/-build-infra/src/addon-build-config-for-data-package'); +const addonBuildConfigForDataPackage = require('@ember-data/private-build-infra/src/addon-build-config-for-data-package'); const addonBaseConfig = addonBuildConfigForDataPackage(name); module.exports = Object.assign({}, addonBaseConfig, { diff --git a/packages/serializer/node-tests/blueprints/serializer-test.js b/packages/serializer/node-tests/blueprints/serializer-test.js index e1eda605325..1363034c403 100644 --- a/packages/serializer/node-tests/blueprints/serializer-test.js +++ b/packages/serializer/node-tests/blueprints/serializer-test.js @@ -12,10 +12,10 @@ const expect = chai.expect; const SilentError = require('silent-error'); -const generateFakePackageManifest = require('@ember-data/-test-infra/src/node-test-helpers/generate-fake-package-manifest'); -const fixture = require('@ember-data/-test-infra/src/node-test-helpers/fixture'); +const generateFakePackageManifest = require('@ember-data/unpublished-test-infra/src/node-test-helpers/generate-fake-package-manifest'); +const fixture = require('@ember-data/unpublished-test-infra/src/node-test-helpers/fixture'); -const setupTestEnvironment = require('@ember-data/-test-infra/src/node-test-helpers/setup-test-environment'); +const setupTestEnvironment = require('@ember-data/unpublished-test-infra/src/node-test-helpers/setup-test-environment'); const enableOctane = setupTestEnvironment.enableOctane; describe('Acceptance: generate and destroy serializer blueprints', function() { diff --git a/packages/serializer/node-tests/blueprints/transform-test.js b/packages/serializer/node-tests/blueprints/transform-test.js index 4b300ef2997..6df8c17e6be 100644 --- a/packages/serializer/node-tests/blueprints/transform-test.js +++ b/packages/serializer/node-tests/blueprints/transform-test.js @@ -9,10 +9,10 @@ const modifyPackages = blueprintHelpers.modifyPackages; const chai = require('ember-cli-blueprint-test-helpers/chai'); const expect = chai.expect; -const generateFakePackageManifest = require('@ember-data/-test-infra/src/node-test-helpers/generate-fake-package-manifest'); -const fixture = require('@ember-data/-test-infra/src/node-test-helpers/fixture'); +const generateFakePackageManifest = require('@ember-data/unpublished-test-infra/src/node-test-helpers/generate-fake-package-manifest'); +const fixture = require('@ember-data/unpublished-test-infra/src/node-test-helpers/fixture'); -const setupTestEnvironment = require('@ember-data/-test-infra/src/node-test-helpers/setup-test-environment'); +const setupTestEnvironment = require('@ember-data/unpublished-test-infra/src/node-test-helpers/setup-test-environment'); const enableOctane = setupTestEnvironment.enableOctane; describe('Acceptance: generate and destroy transform blueprints', function() { diff --git a/packages/serializer/package.json b/packages/serializer/package.json index bdaac1e2c61..f99f13e3145 100644 --- a/packages/serializer/package.json +++ b/packages/serializer/package.json @@ -21,15 +21,15 @@ "test:node": "mocha" }, "dependencies": { - "@ember-data/-build-infra": "3.15.0-alpha.1", + "@ember-data/private-build-infra": "3.15.0-alpha.1", "@ember-data/store": "3.15.0-alpha.1", "ember-cli-babel": "^7.12.0", "ember-cli-test-info": "^1.0.0", "ember-cli-typescript": "^3.0.0" }, "devDependencies": { - "@ember-data/-test-infra": "3.15.0-alpha.1", - "@ember/optional-features": "^1.0.0", + "@ember-data/unpublished-test-infra": "3.15.0-alpha.1", + "@ember/optional-features": "^1.1.0", "broccoli-asset-rev": "^3.0.0", "ember-cli": "~3.13.1", "ember-cli-blueprint-test-helpers": "^0.19.1", @@ -40,11 +40,11 @@ "ember-cli-uglify": "3.0.0", "ember-disable-prototype-extensions": "^1.1.3", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", + "ember-source": "^3.14.1", "ember-source-channel-url": "^2.0.1", "ember-try": "^1.2.1", "loader.js": "^4.7.0", diff --git a/packages/store/addon/-private/identifiers/utils/uuid-v4.ts b/packages/store/addon/-private/identifiers/utils/uuid-v4.ts index d32511f080c..407fd007103 100644 --- a/packages/store/addon/-private/identifiers/utils/uuid-v4.ts +++ b/packages/store/addon/-private/identifiers/utils/uuid-v4.ts @@ -9,10 +9,28 @@ declare global { } } -const CRYPTO = - typeof window !== 'undefined' && window.msCrypto && typeof window.msCrypto.getRandomValues === 'function' - ? window.msCrypto - : window.crypto; +const CRYPTO = (() => { + const hasWindow = typeof window !== 'undefined'; + const isFastBoot = typeof FastBoot !== 'undefined'; + + if (isFastBoot) { + return { + getRandomValues(buffer: Uint8Array) { + return (FastBoot as FastBoot).require('crypto').randomFillSync(buffer); + }, + }; + } else if (hasWindow && typeof window.crypto !== 'undefined') { + return window.crypto; + } else if ( + hasWindow && + typeof window.msCrypto !== 'undefined' && + typeof window.msCrypto.getRandomValues === 'function' + ) { + return window.msCrypto; + } else { + throw new Error('ember-data: Cannot find a valid way to generate local identifiers'); + } +})(); // we might be able to optimize this by requesting more bytes than we need at a time function rng() { diff --git a/packages/store/addon/-private/system/coerce-id.ts b/packages/store/addon/-private/system/coerce-id.ts index 8739ba5ecf0..d5659675e98 100644 --- a/packages/store/addon/-private/system/coerce-id.ts +++ b/packages/store/addon/-private/system/coerce-id.ts @@ -33,7 +33,7 @@ export function ensureStringId(id: Coercable): string { } if (DEBUG && normalized === null) { - throw new Error(`Expected id to be a string or number, recieved ${String(id)}`); + throw new Error(`Expected id to be a string or number, received ${String(id)}`); } return normalized!; diff --git a/packages/store/addon/-private/system/many-array.js b/packages/store/addon/-private/system/many-array.js index aba0367daa0..c302b0417e3 100644 --- a/packages/store/addon/-private/system/many-array.js +++ b/packages/store/addon/-private/system/many-array.js @@ -13,7 +13,8 @@ import { PromiseArray } from './promise-proxies'; import { _objectIsAlive } from './store/common'; import diffArray from './diff-array'; import recordDataFor from './record-data-for'; -import { CUSTOM_MODEL_CLASS } from '@ember-data/canary-features'; +import { CUSTOM_MODEL_CLASS, FULL_LINKS_ON_RELATIONSHIPS } from '@ember-data/canary-features'; + /** A `ManyArray` is a `MutableArray` that represents the contents of a has-many relationship. @@ -229,6 +230,11 @@ export default EmberObject.extend(MutableArray, DeprecatedEvent, { if (jsonApi.meta) { this.set('meta', jsonApi.meta); } + if (FULL_LINKS_ON_RELATIONSHIPS) { + if (jsonApi.links) { + this.set('links', jsonApi.links); + } + } this.flushCanonical(internalModels, true); }, diff --git a/packages/store/addon/-private/system/model/internal-model.ts b/packages/store/addon/-private/system/model/internal-model.ts index 4ea5fd6e83a..b26350fcbb0 100644 --- a/packages/store/addon/-private/system/model/internal-model.ts +++ b/packages/store/addon/-private/system/model/internal-model.ts @@ -27,6 +27,7 @@ import { RECORD_DATA_STATE, REQUEST_SERVICE, CUSTOM_MODEL_CLASS, + FULL_LINKS_ON_RELATIONSHIPS, } from '@ember-data/canary-features'; import { identifierCacheFor } from '../../identifiers/cache'; import { StableRecordIdentifier } from '../../ts-interfaces/identifier'; @@ -729,6 +730,7 @@ export default class InternalModel { type: this.store.modelFor(relationshipMeta.type), recordData: this._recordData, meta: jsonApi.meta, + links: FULL_LINKS_ON_RELATIONSHIPS ? jsonApi.links : undefined, key, isPolymorphic: relationshipMeta.options.polymorphic, initialState: initialState.slice(), @@ -1137,7 +1139,7 @@ export default class InternalModel { } notifyStateChange(key?) { - assert('Cannot notify state change if Record Data State flag is not on', RECORD_DATA_STATE); + assert('Cannot notify state change if Record Data State flag is not on', !!RECORD_DATA_STATE); if (this.hasRecord) { if (CUSTOM_MODEL_CLASS) { this.store._notificationManager.notify(this.identifier, 'state'); diff --git a/packages/store/addon/-private/system/model/states.js b/packages/store/addon/-private/system/model/states.js index 7ed863ff68c..8f22bfa1fd5 100644 --- a/packages/store/addon/-private/system/model/states.js +++ b/packages/store/addon/-private/system/model/states.js @@ -506,6 +506,10 @@ const RootState = { internalModel.triggerLater('didLoad'); internalModel.triggerLater('ready'); }, + + // Record is already in an empty state, triggering transition to empty here + // produce an error. + notFound() {}, }, // A record enters this state when the store asks diff --git a/packages/store/addon/-private/system/promise-proxies.js b/packages/store/addon/-private/system/promise-proxies.js index df006fc97cf..a60933612f1 100644 --- a/packages/store/addon/-private/system/promise-proxies.js +++ b/packages/store/addon/-private/system/promise-proxies.js @@ -5,6 +5,7 @@ import { get, computed } from '@ember/object'; import { reads } from '@ember/object/computed'; import { Promise } from 'rsvp'; import { assert } from '@ember/debug'; +import { FULL_LINKS_ON_RELATIONSHIPS } from '@ember-data/canary-features'; /** @module @ember-data/store @@ -91,7 +92,7 @@ export const PromiseBelongsTo = PromiseObject.extend({ meta: computed(function() { assert( 'You attempted to access meta on the promise for the async belongsTo relationship ' + - `${this.get('_belongsToState').internalModel.modelName}:${this.get('_belongsToState').key}'.` + + `${this.get('_belongsToState').modelName}:${this.get('_belongsToState').key}'.` + '\nUse `record.belongsTo(relationshipName).meta()` instead.', false ); @@ -128,6 +129,8 @@ export function proxyToContent(method) { @extends Ember.ArrayProxy */ export const PromiseManyArray = PromiseArray.extend({ + links: FULL_LINKS_ON_RELATIONSHIPS ? reads('content.links') : undefined, + reload(options) { assert('You are trying to reload an async manyArray before it has been created', get(this, 'content')); this.set('promise', this.get('content').reload(options)); diff --git a/packages/store/addon/-private/system/references/reference.ts b/packages/store/addon/-private/system/references/reference.ts index 75281b6c6ec..f53e2d62eef 100644 --- a/packages/store/addon/-private/system/references/reference.ts +++ b/packages/store/addon/-private/system/references/reference.ts @@ -2,6 +2,10 @@ import InternalModel from '../model/internal-model'; import recordDataFor from '../record-data-for'; import { Object as JSONObject, Value as JSONValue } from 'json-typescript'; import CoreStore from '../core-store'; +import { PaginationLinks, LinkObject } from '../../ts-interfaces/ember-data-json-api'; +import { JsonApiRelationship } from '../../ts-interfaces/record-data-json-api'; +import { FULL_LINKS_ON_RELATIONSHIPS } from '@ember-data/canary-features'; +import { Dict } from '../../ts-interfaces/utils'; /** @module @ember-data/store @@ -14,7 +18,9 @@ interface ResourceIdentifier { meta?: JSONObject; } -function isResourceIdentiferWithRelatedLinks(value: any): value is ResourceIdentifier & { links: { related: string } } { +function isResourceIdentiferWithRelatedLinks( + value: any +): value is ResourceIdentifier & { links: { related: string | LinkObject | null } } { return value && value.links && value.links.related; } @@ -24,13 +30,16 @@ function isResourceIdentiferWithRelatedLinks(value: any): value is ResourceIdent @class Reference */ -export default abstract class Reference { +interface Reference { + links(): PaginationLinks | null; +} +abstract class Reference { public recordData: InternalModel['_recordData']; constructor(public store: CoreStore, public internalModel: InternalModel) { this.recordData = recordDataFor(this); } - public _resource(): ResourceIdentifier | (JSONObject & { meta?: { [k: string]: JSONValue } }) | void {} + public _resource(): ResourceIdentifier | JsonApiRelationship | void {} /** This returns a string that represents how the reference will be @@ -118,16 +127,17 @@ export default abstract class Reference { @method link @return {String} The link Ember Data will use to fetch or reload this belongs-to relationship. */ - link() { - let link: string | null = null; + link(): string | null { + let link; let resource = this._resource(); if (isResourceIdentiferWithRelatedLinks(resource)) { if (resource.links) { link = resource.links.related; + link = !link || typeof link === 'string' ? link : link.href; } } - return link; + return link || null; } /** @@ -170,7 +180,7 @@ export default abstract class Reference { @return {Object} The meta information for the belongs-to relationship. */ meta() { - let meta: { [k: string]: JSONValue } | null = null; + let meta: Dict | null = null; let resource = this._resource(); if (resource && resource.meta && typeof resource.meta === 'object') { meta = resource.meta; @@ -178,3 +188,13 @@ export default abstract class Reference { return meta; } } + +if (FULL_LINKS_ON_RELATIONSHIPS) { + Reference.prototype.links = function links(): PaginationLinks | null { + let resource = this._resource(); + + return resource && resource.links ? resource.links : null; + }; +} + +export default Reference; diff --git a/packages/store/addon/-private/system/snapshot-record-array.js b/packages/store/addon/-private/system/snapshot-record-array.js index 8ef15952757..93ca9f0baca 100644 --- a/packages/store/addon/-private/system/snapshot-record-array.js +++ b/packages/store/addon/-private/system/snapshot-record-array.js @@ -109,6 +109,7 @@ export default class SnapshotRecordArray { return fetch(url).then((response) => response.json()) } }); + ``` @property include @type {String|Array} diff --git a/packages/store/addon/-private/system/store/finders.js b/packages/store/addon/-private/system/store/finders.js index 5f91898f5cd..f5cb10d4e78 100644 --- a/packages/store/addon/-private/system/store/finders.js +++ b/packages/store/addon/-private/system/store/finders.js @@ -178,7 +178,7 @@ function ensureRelationshipIsSetToParent(payload, parentInternalModel, store, pa let expectedModel = Ember.inspect(parentInternalModel); let got = Ember.inspect(relationshipData); let prefix = typeof index === 'number' ? `data[${index}]` : `data`; - let path = `${prefix}.relationships.${inverse}.data`; + let path = `${prefix}.relationships.${inverseKey}.data`; let other = relationshipData ? `<${relationshipData.type}:${relationshipData.id}>` : null; let relationshipFetched = `${Ember.inspect(parentInternalModel)}.${parentRelationship.kind}("${ parentRelationship.name @@ -274,7 +274,9 @@ function validateRelationshipEntry({ id }, { id: parentModelID }) { export function _findHasMany(adapter, store, internalModel, link, relationship, options) { let snapshot = internalModel.createSnapshot(options); let modelClass = store.modelFor(relationship.type); - let promise = adapter.findHasMany(store, snapshot, link, relationship); + let useLink = !link || typeof link === 'string'; + let relatedLink = useLink ? link : link.href; + let promise = adapter.findHasMany(store, snapshot, relatedLink, relationship); let label = `DS: Handle Adapter#findHasMany of '${internalModel.modelName}' : '${relationship.type}'`; promise = guardDestroyedStore(promise, store, label); @@ -302,7 +304,9 @@ export function _findHasMany(adapter, store, internalModel, link, relationship, export function _findBelongsTo(adapter, store, internalModel, link, relationship, options) { let snapshot = internalModel.createSnapshot(options); let modelClass = store.modelFor(relationship.type); - let promise = adapter.findBelongsTo(store, snapshot, link, relationship); + let useLink = !link || typeof link === 'string'; + let relatedLink = useLink ? link : link.href; + let promise = adapter.findBelongsTo(store, snapshot, relatedLink, relationship); let label = `DS: Handle Adapter#findBelongsTo of ${internalModel.modelName} : ${relationship.type}`; promise = guardDestroyedStore(promise, store, label); diff --git a/packages/store/addon/-private/ts-interfaces/minimum-serializer-interface.ts b/packages/store/addon/-private/ts-interfaces/minimum-serializer-interface.ts index f6819d9c2d7..fd5a8cd6bb6 100644 --- a/packages/store/addon/-private/ts-interfaces/minimum-serializer-interface.ts +++ b/packages/store/addon/-private/ts-interfaces/minimum-serializer-interface.ts @@ -1,26 +1,26 @@ /** ## Overview - In order to properly manage and present your data, `EmberData` + In order to properly manage and present your data, EmberData needs to understand the structure of data it receives. `Serializers` convert data between the server's API format and - the format `EmberData` understands. + the format EmberData understands. - Data received from an API response is `"normalized"` into + Data received from an API response is **normalized** into [JSON:API](https://jsonapi.org/) (the format used internally - by `EmberData`), while data sent to an API is `"serialized"` + by EmberData), while data sent to an API is **serialized** into the format the API expects. ### Implementing a Serializer There are only two required serializer methods, one for - normalizing data from the server API format into `JSON:API`, and - another for serializing records via `Snapshot`s into the expected + normalizing data from the server API format into JSON:API, and + another for serializing records via `Snapshots` into the expected server API format. To implement a serializer, export a class that conforms to the structure - described by the [MinimumSerializerInterface](MinimumSerializerInterface) + described by the [MinimumSerializerInterface](/ember-data/release/classes/MinimumSerializerInterface) from the `app/serializers/` directory. An example is below. ```ts @@ -44,10 +44,10 @@ ``` - #### Serializer Resolution + ### Serializer Resolution `store.serializerFor(name)` will lookup serializers defined in - `app/serializers` and return an instance. If no serializer is found, an + `app/serializers/` and return an instance. If no serializer is found, an error will be thrown. `serializerFor` first attempts to find a serializer with an exact match on `name`, @@ -61,9 +61,9 @@ // app/serializers/application.js ``` - Most requests in `ember-data` are made with respect to a particular `type` (or `modelName`) + Most requests in EmberData are made with respect to a particular `type` (or `modelName`) (e.g., "get me the full collection of **books**" or "get me the **employee** whose id is 37"). We - refer to this as the *"primary"* resource `type`. + refer to this as the **primary** resource `type`. Typically `serializerFor` will be used to find a serializer with a name matching that of the primary resource `type` for the request, falling back to the `application` serializer for those types that @@ -80,11 +80,11 @@ ### Using a Serializer - Any serializer in `app/serializers` can be looked up by `name` using `store.serializerFor(name)`. + Any serializer in `app/serializers/` can be looked up by `name` using `store.serializerFor(name)`. ### Default Serializers - For applications whose APIs are *very close to* or *exactly* the `REST` or `JSON:API` + For applications whose APIs are *very close to* or *exactly* the **REST** format or **JSON:API** format the `@ember-data/serializer` package contains implementations these applications can extend. It also contains a simple `JSONSerializer` for serializing to/from very basic JSON objects. @@ -97,7 +97,6 @@ @module @ember-data/serializer @main @ember-data/serializer - @class MinimumSerializerInterface @public */ @@ -110,6 +109,17 @@ import { Dict } from './utils'; type OptionsHash = Dict; +/** + The following documentation describes the methods an application + serializer should implement with descriptions around when an + application might expect these methods to be called. + + Methods that are not required are marked as **optional**. + + @module @ember-data/serializer + @class MinimumSerializerInterface + @public +*/ interface Serializer { /** * This method is responsible for normalizing the value resolved from the promise returned @@ -128,18 +138,18 @@ interface Serializer { * * @method normalizeResponse * @public - * @param {Store} store - the store service that initiated the request being normalized - * @param {ShimModelClass} schema - An object with methods for accessing information about + * @param {Store} store The store service that initiated the request being normalized + * @param {ShimModelClass} schema An object with methods for accessing information about * the type, attributes and relationships of the primary type associated with the request. - * @param {JSONObject} rawPayload - The raw JSON response data returned from an API request. + * @param {JSONObject} rawPayload The raw JSON response data returned from an API request. * This correlates to the value the promise returned by the adapter method that performed * the request resolved to. - * @param {string|null} id - For a `findRecord` request, this is the `id` initially provided - * in the call to `store.findRecord`. Else this value is `null`. - * @param {'findRecord' | 'queryRecord' | 'findAll' | 'findBelongsTo' | 'findHasMany' | 'findMany' | 'query' | 'createRecord' | 'deleteRecord' | 'updateRecord'} requestType - The + * @param {string|null} id For a findRecord request, this is the id initially provided + * in the call to store.findRecord. Else this value is null. + * @param {'findRecord' | 'queryRecord' | 'findAll' | 'findBelongsTo' | 'findHasMany' | 'findMany' | 'query' | 'createRecord' | 'deleteRecord' | 'updateRecord'} requestType The * type of request the Adapter had been asked to perform. * - * @returns {JsonApiDocument} - a document following the structure of a [JSON:API Document](https://jsonapi.org/format/#document-structure). + * @returns {JsonApiDocument} a document following the structure of a JSON:API Document. */ normalizeResponse( store: Store, @@ -173,7 +183,7 @@ interface Serializer { * * @method serialize * @public - * @param {Snapshot} snapshot - A Snapshot for the record to serialize + * @param {Snapshot} snapshot A Snapshot for the record to serialize * @param {object} [options] */ serialize(snapshot: Snapshot, options?: OptionsHash): JSONObject; @@ -182,7 +192,7 @@ interface Serializer { * This method is intended to normalize data into a [JSON:API Document](https://jsonapi.org/format/#document-structure) * with a data member containing a single [Resource](https://jsonapi.org/format/#document-resource-objects). * - * - `type` should be formatted in the `singular` `dasherized` `lowercase` form + * - `type` should be formatted in the singular, dasherized and lowercase form * - `members` (the property names of attributes and relationships) should be formatted * to match their definition in the corresponding `Model` definition. Typically this * will be `camelCase`. @@ -196,7 +206,7 @@ interface Serializer { * * This method may be called when also using the `RESTSerializer` * when `serializer.pushPayload` is called by `store.pushPayload`. - * It is recommended to use `store.push` over `store.pushPayload` after normalizing + * However, it is recommended to use `store.push` over `store.pushPayload` after normalizing * the payload directly. * * Example: @@ -223,21 +233,22 @@ interface Serializer { * @method normalize [OPTIONAL] * @public * @optional - * @param {ShimModelClass} schema - An object with methods for accessing information about + * @param {ShimModelClass} schema An object with methods for accessing information about * the type, attributes and relationships of the primary type associated with the request. - * @param {JSONObject} rawPayload - Some raw JSON data to be normalized into a [JSON:API Resource](https://jsonapi.org/format/#document-resource-objects). - * @param {string} [prop] - When called by the `EmbeddedRecordsMixin` this param will be the + * @param {JSONObject} rawPayload Some raw JSON data to be normalized into a JSON:API Resource. + * @param {string} [prop] When called by the EmbeddedRecordsMixin this param will be the * property at which the object provided as rawPayload was found. - * @returns {SingleResourceDocument} - A [JSON:API Document](https://jsonapi.org/format/#document-structure) - * containing a single [JSON:API Resource](https://jsonapi.org/format/#document-resource-objects) + * @returns {SingleResourceDocument} A JSON:API Document + * containing a single JSON:API Resource * as its primary data. */ normalize?(schema: ShimModelClass, rawPayload: JSONObject, prop?: string): SingleResourceDocument; /** * When using `JSONAPIAdapter` or `RESTAdapter` this method is called - * by `adapter.updateRecord` and `adapter.createRecord` if `Serializer.serializeIntoHash` - * is not implemented. + * by `adapter.updateRecord` and `adapter.createRecord` if `serializer.serializeIntoHash` + * is implemented. If this method is not implemented, `serializer.serialize` + * will be called in this case. * * You can use this method to customize the root keys serialized into the payload. * The hash property should be modified by reference. @@ -265,11 +276,11 @@ interface Serializer { * @method serializeIntoHash [OPTIONAL] * @public * @optional - * @param hash - a top most object of the request payload onto + * @param hash A top most object of the request payload onto * which to append the serialized record - * @param {ShimModelClass} schema - An object with methods for accessing information about + * @param {ShimModelClass} schema An object with methods for accessing information about * the type, attributes and relationships of the primary type associated with the request. - * @param {Snapshot} snapshot - A Snapshot for the record to serialize + * @param {Snapshot} snapshot A Snapshot for the record to serialize * @param [options] * @returns {void} */ @@ -279,10 +290,14 @@ interface Serializer { * This method allows for normalization of data when `store.pushPayload` is called * and should be implemented if you want to use that method. * - * The output should be a [JSON:API Document](https://jsonapi.org/format/#document-structure) + * The method is responsible for pushing new data to the store using `store.push` + * once any necessary normalization has occurred, and no data in the store will be + * updated unless it does so. + * + * The normalized form pushed to the store should be a [JSON:API Document](https://jsonapi.org/format/#document-structure) * with the following additional restrictions: * - * - `type` should be formatted in the `singular` `dasherized` `lowercase` form + * - `type` should be formatted in the singular, dasherized and lowercase form * - `members` (the property names of attributes and relationships) should be formatted * to match their definition in the corresponding `Model` definition. Typically this * will be `camelCase`. @@ -308,12 +323,12 @@ interface Serializer { * @method pushPayload [OPTIONAL] * @public * @optional - * @param {Store} store - the store service that initiated the request being normalized - * @param {JSONObject} rawPayload - The raw JSON response data returned from an API request. + * @param {Store} store The store service that initiated the request being normalized + * @param {JSONObject} rawPayload The raw JSON response data returned from an API request. * This JSON should be in the API format expected by the serializer. - * @returns {JsonApiDocument} - a document following the structure of a [JSON:API Document](https://jsonapi.org/format/#document-structure) + * @returns {void} */ - pushPayload?(store: Store, rawPayload: JSONObject): JsonApiDocument; + pushPayload?(store: Store, rawPayload: JSONObject): void; } export default Serializer; diff --git a/packages/store/index.js b/packages/store/index.js index ccce266bf81..55a910a9bc4 100644 --- a/packages/store/index.js +++ b/packages/store/index.js @@ -1,7 +1,7 @@ 'use strict'; const name = require('./package').name; -const addonBuildConfigForDataPackage = require('@ember-data/-build-infra/src/addon-build-config-for-data-package'); +const addonBuildConfigForDataPackage = require('@ember-data/private-build-infra/src/addon-build-config-for-data-package'); const addonBaseConfig = addonBuildConfigForDataPackage(name); module.exports = Object.assign({}, addonBaseConfig, { diff --git a/packages/store/package.json b/packages/store/package.json index 7da0d4b3bd9..62df688fd75 100644 --- a/packages/store/package.json +++ b/packages/store/package.json @@ -20,7 +20,7 @@ "test:all": "ember try:each" }, "dependencies": { - "@ember-data/-build-infra": "3.15.0-alpha.1", + "@ember-data/private-build-infra": "3.15.0-alpha.1", "@ember-data/canary-features": "3.15.0-alpha.1", "ember-cli-babel": "^7.12.0", "ember-cli-path-utils": "^1.0.0", @@ -28,8 +28,8 @@ "heimdalljs": "^0.3.0" }, "devDependencies": { - "@ember-data/-test-infra": "3.15.0-alpha.1", - "@ember/optional-features": "^1.0.0", + "@ember-data/unpublished-test-infra": "3.15.0-alpha.1", + "@ember/optional-features": "^1.1.0", "@types/ember": "^3.1.1", "@types/rsvp": "^4.0.3", "broccoli-asset-rev": "^3.0.0", @@ -41,11 +41,11 @@ "ember-cli-uglify": "3.0.0", "ember-disable-prototype-extensions": "^1.1.3", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", + "ember-source": "^3.14.1", "ember-source-channel-url": "^2.0.1", "ember-try": "^1.2.1", "loader.js": "^4.7.0" diff --git a/packages/store/types/fastboot/index.d.ts b/packages/store/types/fastboot/index.d.ts new file mode 100644 index 00000000000..818a8a945a4 --- /dev/null +++ b/packages/store/types/fastboot/index.d.ts @@ -0,0 +1,4 @@ +interface FastBoot { + require(moduleName: string): any; +} +const FastBoot: undefined | FastBoot; diff --git a/packages/store/types/qunit/index.d.ts b/packages/store/types/qunit/index.d.ts index 55a51047435..4e567630e29 100644 --- a/packages/store/types/qunit/index.d.ts +++ b/packages/store/types/qunit/index.d.ts @@ -3,17 +3,33 @@ interface DeprecationConfig { count?: number; until: string; message?: string; + url?: string; +} +interface WarningConfig { + id: string; + count?: number; + until?: string; + message?: string; + url?: string; } interface Assert { - expectDeprecation(callback: () => unknown, options: DeprecationConfig | string): Promise; + expectDeprecation(callback: () => unknown, options: DeprecationConfig | string | RegExp): Promise; expectNoDeprecation(callback: () => unknown): Promise; + expectWarning(callback: () => unknown, options: WarningConfig | string | RegExp): Promise; + expectNoWarning(callback: () => unknown): Promise; + expectAssertion(callback: () => unknown, matcher: string | RegExp): Promise; + expectNoAssertion(callback: () => unknown): Promise; } declare namespace QUnit { export interface Assert { - expectDeprecation(callback: () => unknown, options: DeprecationConfig | string): Promise; + expectDeprecation(callback: () => unknown, options: DeprecationConfig | string | RegExp): Promise; expectNoDeprecation(callback: () => unknown): Promise; + expectWarning(callback: () => unknown, options: WarningConfig | string | RegExp): Promise; + expectNoWarning(callback: () => unknown): Promise; + expectAssertion(callback: () => unknown, matcher: string | RegExp): Promise; + expectNoAssertion(callback: () => unknown): Promise; } } diff --git a/packages/-adapter-encapsulation-test-app/.editorconfig b/packages/unpublished-adapter-encapsulation-test-app/.editorconfig similarity index 100% rename from packages/-adapter-encapsulation-test-app/.editorconfig rename to packages/unpublished-adapter-encapsulation-test-app/.editorconfig diff --git a/packages/-adapter-encapsulation-test-app/.ember-cli b/packages/unpublished-adapter-encapsulation-test-app/.ember-cli similarity index 100% rename from packages/-adapter-encapsulation-test-app/.ember-cli rename to packages/unpublished-adapter-encapsulation-test-app/.ember-cli diff --git a/packages/-adapter-encapsulation-test-app/.gitignore b/packages/unpublished-adapter-encapsulation-test-app/.gitignore similarity index 100% rename from packages/-adapter-encapsulation-test-app/.gitignore rename to packages/unpublished-adapter-encapsulation-test-app/.gitignore diff --git a/packages/-adapter-encapsulation-test-app/.template-lintrc.js b/packages/unpublished-adapter-encapsulation-test-app/.template-lintrc.js similarity index 100% rename from packages/-adapter-encapsulation-test-app/.template-lintrc.js rename to packages/unpublished-adapter-encapsulation-test-app/.template-lintrc.js diff --git a/packages/-build-infra/.watchmanconfig b/packages/unpublished-adapter-encapsulation-test-app/.watchmanconfig similarity index 100% rename from packages/-build-infra/.watchmanconfig rename to packages/unpublished-adapter-encapsulation-test-app/.watchmanconfig diff --git a/packages/-adapter-encapsulation-test-app/README.md b/packages/unpublished-adapter-encapsulation-test-app/README.md similarity index 100% rename from packages/-adapter-encapsulation-test-app/README.md rename to packages/unpublished-adapter-encapsulation-test-app/README.md diff --git a/packages/-adapter-encapsulation-test-app/app/app.js b/packages/unpublished-adapter-encapsulation-test-app/app/app.js similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/app.js rename to packages/unpublished-adapter-encapsulation-test-app/app/app.js diff --git a/packages/-adapter-encapsulation-test-app/app/components/.gitkeep b/packages/unpublished-adapter-encapsulation-test-app/app/components/.gitkeep similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/components/.gitkeep rename to packages/unpublished-adapter-encapsulation-test-app/app/components/.gitkeep diff --git a/packages/-adapter-encapsulation-test-app/app/controllers/.gitkeep b/packages/unpublished-adapter-encapsulation-test-app/app/controllers/.gitkeep similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/controllers/.gitkeep rename to packages/unpublished-adapter-encapsulation-test-app/app/controllers/.gitkeep diff --git a/packages/-adapter-encapsulation-test-app/app/helpers/.gitkeep b/packages/unpublished-adapter-encapsulation-test-app/app/helpers/.gitkeep similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/helpers/.gitkeep rename to packages/unpublished-adapter-encapsulation-test-app/app/helpers/.gitkeep diff --git a/packages/-adapter-encapsulation-test-app/app/index.html b/packages/unpublished-adapter-encapsulation-test-app/app/index.html similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/index.html rename to packages/unpublished-adapter-encapsulation-test-app/app/index.html diff --git a/packages/-adapter-encapsulation-test-app/app/models/.gitkeep b/packages/unpublished-adapter-encapsulation-test-app/app/models/.gitkeep similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/models/.gitkeep rename to packages/unpublished-adapter-encapsulation-test-app/app/models/.gitkeep diff --git a/packages/-adapter-encapsulation-test-app/app/resolver.js b/packages/unpublished-adapter-encapsulation-test-app/app/resolver.js similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/resolver.js rename to packages/unpublished-adapter-encapsulation-test-app/app/resolver.js diff --git a/packages/-adapter-encapsulation-test-app/app/router.js b/packages/unpublished-adapter-encapsulation-test-app/app/router.js similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/router.js rename to packages/unpublished-adapter-encapsulation-test-app/app/router.js diff --git a/packages/-adapter-encapsulation-test-app/app/routes/.gitkeep b/packages/unpublished-adapter-encapsulation-test-app/app/routes/.gitkeep similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/routes/.gitkeep rename to packages/unpublished-adapter-encapsulation-test-app/app/routes/.gitkeep diff --git a/packages/-adapter-encapsulation-test-app/app/styles/app.css b/packages/unpublished-adapter-encapsulation-test-app/app/styles/app.css similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/styles/app.css rename to packages/unpublished-adapter-encapsulation-test-app/app/styles/app.css diff --git a/packages/-adapter-encapsulation-test-app/app/templates/application.hbs b/packages/unpublished-adapter-encapsulation-test-app/app/templates/application.hbs similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/templates/application.hbs rename to packages/unpublished-adapter-encapsulation-test-app/app/templates/application.hbs diff --git a/packages/-adapter-encapsulation-test-app/app/templates/components/.gitkeep b/packages/unpublished-adapter-encapsulation-test-app/app/templates/components/.gitkeep similarity index 100% rename from packages/-adapter-encapsulation-test-app/app/templates/components/.gitkeep rename to packages/unpublished-adapter-encapsulation-test-app/app/templates/components/.gitkeep diff --git a/packages/-adapter-encapsulation-test-app/config/environment.js b/packages/unpublished-adapter-encapsulation-test-app/config/environment.js similarity index 100% rename from packages/-adapter-encapsulation-test-app/config/environment.js rename to packages/unpublished-adapter-encapsulation-test-app/config/environment.js diff --git a/packages/-adapter-encapsulation-test-app/config/optional-features.json b/packages/unpublished-adapter-encapsulation-test-app/config/optional-features.json similarity index 100% rename from packages/-adapter-encapsulation-test-app/config/optional-features.json rename to packages/unpublished-adapter-encapsulation-test-app/config/optional-features.json diff --git a/packages/-adapter-encapsulation-test-app/config/targets.js b/packages/unpublished-adapter-encapsulation-test-app/config/targets.js similarity index 100% rename from packages/-adapter-encapsulation-test-app/config/targets.js rename to packages/unpublished-adapter-encapsulation-test-app/config/targets.js diff --git a/packages/-adapter-encapsulation-test-app/ember-cli-build.js b/packages/unpublished-adapter-encapsulation-test-app/ember-cli-build.js similarity index 100% rename from packages/-adapter-encapsulation-test-app/ember-cli-build.js rename to packages/unpublished-adapter-encapsulation-test-app/ember-cli-build.js diff --git a/packages/-adapter-encapsulation-test-app/package.json b/packages/unpublished-adapter-encapsulation-test-app/package.json similarity index 85% rename from packages/-adapter-encapsulation-test-app/package.json rename to packages/unpublished-adapter-encapsulation-test-app/package.json index d5bfe7d4265..85dcfc1d78b 100644 --- a/packages/-adapter-encapsulation-test-app/package.json +++ b/packages/unpublished-adapter-encapsulation-test-app/package.json @@ -26,7 +26,7 @@ "ember-inflector": "^3.0.1" }, "devDependencies": { - "@ember/optional-features": "^1.0.0", + "@ember/optional-features": "^1.1.0", "broccoli-asset-rev": "^3.0.0", "ember-cli": "~3.13.1", "ember-cli-app-version": "^3.2.0", @@ -36,16 +36,16 @@ "ember-cli-inject-live-reload": "^2.0.2", "ember-cli-template-lint": "^1.0.0-beta.1", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", - "eslint": "^6.5.1", - "eslint-plugin-ember": "^7.2.0", + "ember-source": "^3.14.1", + "eslint": "^6.6.0", + "eslint-plugin-ember": "^7.3.0", "eslint-plugin-node": "^10.0.0", "loader.js": "^4.7.0", - "qunit-dom": "^0.9.0" + "qunit-dom": "^0.9.1" }, "engines": { "node": "8.* || >= 10.*" diff --git a/packages/-adapter-encapsulation-test-app/public/robots.txt b/packages/unpublished-adapter-encapsulation-test-app/public/robots.txt similarity index 100% rename from packages/-adapter-encapsulation-test-app/public/robots.txt rename to packages/unpublished-adapter-encapsulation-test-app/public/robots.txt diff --git a/packages/-adapter-encapsulation-test-app/testem.js b/packages/unpublished-adapter-encapsulation-test-app/testem.js similarity index 100% rename from packages/-adapter-encapsulation-test-app/testem.js rename to packages/unpublished-adapter-encapsulation-test-app/testem.js diff --git a/packages/-adapter-encapsulation-test-app/tests/helpers/.gitkeep b/packages/unpublished-adapter-encapsulation-test-app/tests/helpers/.gitkeep similarity index 100% rename from packages/-adapter-encapsulation-test-app/tests/helpers/.gitkeep rename to packages/unpublished-adapter-encapsulation-test-app/tests/helpers/.gitkeep diff --git a/packages/-adapter-encapsulation-test-app/tests/index.html b/packages/unpublished-adapter-encapsulation-test-app/tests/index.html similarity index 100% rename from packages/-adapter-encapsulation-test-app/tests/index.html rename to packages/unpublished-adapter-encapsulation-test-app/tests/index.html diff --git a/packages/-adapter-encapsulation-test-app/tests/integration/.gitkeep b/packages/unpublished-adapter-encapsulation-test-app/tests/integration/.gitkeep similarity index 100% rename from packages/-adapter-encapsulation-test-app/tests/integration/.gitkeep rename to packages/unpublished-adapter-encapsulation-test-app/tests/integration/.gitkeep diff --git a/packages/-adapter-encapsulation-test-app/tests/integration/smoke-test.js b/packages/unpublished-adapter-encapsulation-test-app/tests/integration/smoke-test.js similarity index 100% rename from packages/-adapter-encapsulation-test-app/tests/integration/smoke-test.js rename to packages/unpublished-adapter-encapsulation-test-app/tests/integration/smoke-test.js diff --git a/packages/-adapter-encapsulation-test-app/tests/test-helper.js b/packages/unpublished-adapter-encapsulation-test-app/tests/test-helper.js similarity index 100% rename from packages/-adapter-encapsulation-test-app/tests/test-helper.js rename to packages/unpublished-adapter-encapsulation-test-app/tests/test-helper.js diff --git a/packages/-adapter-encapsulation-test-app/tests/unit/.gitkeep b/packages/unpublished-adapter-encapsulation-test-app/tests/unit/.gitkeep similarity index 100% rename from packages/-adapter-encapsulation-test-app/tests/unit/.gitkeep rename to packages/unpublished-adapter-encapsulation-test-app/tests/unit/.gitkeep diff --git a/packages/-adapter-encapsulation-test-app/vendor/.gitkeep b/packages/unpublished-adapter-encapsulation-test-app/vendor/.gitkeep similarity index 100% rename from packages/-adapter-encapsulation-test-app/vendor/.gitkeep rename to packages/unpublished-adapter-encapsulation-test-app/vendor/.gitkeep diff --git a/packages/-debug-encapsulation-test-app/.editorconfig b/packages/unpublished-debug-encapsulation-test-app/.editorconfig similarity index 100% rename from packages/-debug-encapsulation-test-app/.editorconfig rename to packages/unpublished-debug-encapsulation-test-app/.editorconfig diff --git a/packages/-debug-encapsulation-test-app/.ember-cli b/packages/unpublished-debug-encapsulation-test-app/.ember-cli similarity index 100% rename from packages/-debug-encapsulation-test-app/.ember-cli rename to packages/unpublished-debug-encapsulation-test-app/.ember-cli diff --git a/packages/-debug-encapsulation-test-app/.gitignore b/packages/unpublished-debug-encapsulation-test-app/.gitignore similarity index 100% rename from packages/-debug-encapsulation-test-app/.gitignore rename to packages/unpublished-debug-encapsulation-test-app/.gitignore diff --git a/packages/-debug-encapsulation-test-app/.template-lintrc.js b/packages/unpublished-debug-encapsulation-test-app/.template-lintrc.js similarity index 100% rename from packages/-debug-encapsulation-test-app/.template-lintrc.js rename to packages/unpublished-debug-encapsulation-test-app/.template-lintrc.js diff --git a/packages/-debug-encapsulation-test-app/.watchmanconfig b/packages/unpublished-debug-encapsulation-test-app/.watchmanconfig similarity index 100% rename from packages/-debug-encapsulation-test-app/.watchmanconfig rename to packages/unpublished-debug-encapsulation-test-app/.watchmanconfig diff --git a/packages/-debug-encapsulation-test-app/README.md b/packages/unpublished-debug-encapsulation-test-app/README.md similarity index 100% rename from packages/-debug-encapsulation-test-app/README.md rename to packages/unpublished-debug-encapsulation-test-app/README.md diff --git a/packages/-debug-encapsulation-test-app/app/app.js b/packages/unpublished-debug-encapsulation-test-app/app/app.js similarity index 100% rename from packages/-debug-encapsulation-test-app/app/app.js rename to packages/unpublished-debug-encapsulation-test-app/app/app.js diff --git a/packages/-debug-encapsulation-test-app/app/components/.gitkeep b/packages/unpublished-debug-encapsulation-test-app/app/components/.gitkeep similarity index 100% rename from packages/-debug-encapsulation-test-app/app/components/.gitkeep rename to packages/unpublished-debug-encapsulation-test-app/app/components/.gitkeep diff --git a/packages/-debug-encapsulation-test-app/app/controllers/.gitkeep b/packages/unpublished-debug-encapsulation-test-app/app/controllers/.gitkeep similarity index 100% rename from packages/-debug-encapsulation-test-app/app/controllers/.gitkeep rename to packages/unpublished-debug-encapsulation-test-app/app/controllers/.gitkeep diff --git a/packages/-debug-encapsulation-test-app/app/helpers/.gitkeep b/packages/unpublished-debug-encapsulation-test-app/app/helpers/.gitkeep similarity index 100% rename from packages/-debug-encapsulation-test-app/app/helpers/.gitkeep rename to packages/unpublished-debug-encapsulation-test-app/app/helpers/.gitkeep diff --git a/packages/-debug-encapsulation-test-app/app/index.html b/packages/unpublished-debug-encapsulation-test-app/app/index.html similarity index 100% rename from packages/-debug-encapsulation-test-app/app/index.html rename to packages/unpublished-debug-encapsulation-test-app/app/index.html diff --git a/packages/-debug-encapsulation-test-app/app/models/.gitkeep b/packages/unpublished-debug-encapsulation-test-app/app/models/.gitkeep similarity index 100% rename from packages/-debug-encapsulation-test-app/app/models/.gitkeep rename to packages/unpublished-debug-encapsulation-test-app/app/models/.gitkeep diff --git a/packages/-debug-encapsulation-test-app/app/resolver.js b/packages/unpublished-debug-encapsulation-test-app/app/resolver.js similarity index 100% rename from packages/-debug-encapsulation-test-app/app/resolver.js rename to packages/unpublished-debug-encapsulation-test-app/app/resolver.js diff --git a/packages/-debug-encapsulation-test-app/app/router.js b/packages/unpublished-debug-encapsulation-test-app/app/router.js similarity index 100% rename from packages/-debug-encapsulation-test-app/app/router.js rename to packages/unpublished-debug-encapsulation-test-app/app/router.js diff --git a/packages/-debug-encapsulation-test-app/app/routes/.gitkeep b/packages/unpublished-debug-encapsulation-test-app/app/routes/.gitkeep similarity index 100% rename from packages/-debug-encapsulation-test-app/app/routes/.gitkeep rename to packages/unpublished-debug-encapsulation-test-app/app/routes/.gitkeep diff --git a/packages/-debug-encapsulation-test-app/app/styles/app.css b/packages/unpublished-debug-encapsulation-test-app/app/styles/app.css similarity index 100% rename from packages/-debug-encapsulation-test-app/app/styles/app.css rename to packages/unpublished-debug-encapsulation-test-app/app/styles/app.css diff --git a/packages/-debug-encapsulation-test-app/app/templates/application.hbs b/packages/unpublished-debug-encapsulation-test-app/app/templates/application.hbs similarity index 100% rename from packages/-debug-encapsulation-test-app/app/templates/application.hbs rename to packages/unpublished-debug-encapsulation-test-app/app/templates/application.hbs diff --git a/packages/-debug-encapsulation-test-app/app/templates/components/.gitkeep b/packages/unpublished-debug-encapsulation-test-app/app/templates/components/.gitkeep similarity index 100% rename from packages/-debug-encapsulation-test-app/app/templates/components/.gitkeep rename to packages/unpublished-debug-encapsulation-test-app/app/templates/components/.gitkeep diff --git a/packages/-debug-encapsulation-test-app/config/environment.js b/packages/unpublished-debug-encapsulation-test-app/config/environment.js similarity index 100% rename from packages/-debug-encapsulation-test-app/config/environment.js rename to packages/unpublished-debug-encapsulation-test-app/config/environment.js diff --git a/packages/-debug-encapsulation-test-app/config/optional-features.json b/packages/unpublished-debug-encapsulation-test-app/config/optional-features.json similarity index 100% rename from packages/-debug-encapsulation-test-app/config/optional-features.json rename to packages/unpublished-debug-encapsulation-test-app/config/optional-features.json diff --git a/packages/-debug-encapsulation-test-app/config/targets.js b/packages/unpublished-debug-encapsulation-test-app/config/targets.js similarity index 100% rename from packages/-debug-encapsulation-test-app/config/targets.js rename to packages/unpublished-debug-encapsulation-test-app/config/targets.js diff --git a/packages/-debug-encapsulation-test-app/ember-cli-build.js b/packages/unpublished-debug-encapsulation-test-app/ember-cli-build.js similarity index 100% rename from packages/-debug-encapsulation-test-app/ember-cli-build.js rename to packages/unpublished-debug-encapsulation-test-app/ember-cli-build.js diff --git a/packages/-debug-encapsulation-test-app/package.json b/packages/unpublished-debug-encapsulation-test-app/package.json similarity index 85% rename from packages/-debug-encapsulation-test-app/package.json rename to packages/unpublished-debug-encapsulation-test-app/package.json index 39775a9e989..f2287b220fd 100644 --- a/packages/-debug-encapsulation-test-app/package.json +++ b/packages/unpublished-debug-encapsulation-test-app/package.json @@ -25,7 +25,7 @@ "ember-inflector": "^3.0.1" }, "devDependencies": { - "@ember/optional-features": "^1.0.0", + "@ember/optional-features": "^1.1.0", "broccoli-asset-rev": "^3.0.0", "ember-cli": "~3.13.1", "ember-cli-app-version": "^3.2.0", @@ -35,16 +35,16 @@ "ember-cli-inject-live-reload": "^2.0.2", "ember-cli-template-lint": "^1.0.0-beta.1", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", - "eslint": "^6.5.1", - "eslint-plugin-ember": "^7.2.0", + "ember-source": "^3.14.1", + "eslint": "^6.6.0", + "eslint-plugin-ember": "^7.3.0", "eslint-plugin-node": "^10.0.0", "loader.js": "^4.7.0", - "qunit-dom": "^0.9.0" + "qunit-dom": "^0.9.1" }, "engines": { "node": "8.* || >= 10.*" diff --git a/packages/-debug-encapsulation-test-app/public/robots.txt b/packages/unpublished-debug-encapsulation-test-app/public/robots.txt similarity index 100% rename from packages/-debug-encapsulation-test-app/public/robots.txt rename to packages/unpublished-debug-encapsulation-test-app/public/robots.txt diff --git a/packages/-debug-encapsulation-test-app/testem.js b/packages/unpublished-debug-encapsulation-test-app/testem.js similarity index 100% rename from packages/-debug-encapsulation-test-app/testem.js rename to packages/unpublished-debug-encapsulation-test-app/testem.js diff --git a/packages/-debug-encapsulation-test-app/tests/helpers/.gitkeep b/packages/unpublished-debug-encapsulation-test-app/tests/helpers/.gitkeep similarity index 100% rename from packages/-debug-encapsulation-test-app/tests/helpers/.gitkeep rename to packages/unpublished-debug-encapsulation-test-app/tests/helpers/.gitkeep diff --git a/packages/-debug-encapsulation-test-app/tests/index.html b/packages/unpublished-debug-encapsulation-test-app/tests/index.html similarity index 100% rename from packages/-debug-encapsulation-test-app/tests/index.html rename to packages/unpublished-debug-encapsulation-test-app/tests/index.html diff --git a/packages/-debug-encapsulation-test-app/tests/integration/.gitkeep b/packages/unpublished-debug-encapsulation-test-app/tests/integration/.gitkeep similarity index 100% rename from packages/-debug-encapsulation-test-app/tests/integration/.gitkeep rename to packages/unpublished-debug-encapsulation-test-app/tests/integration/.gitkeep diff --git a/packages/-debug-encapsulation-test-app/tests/integration/smoke-test.js b/packages/unpublished-debug-encapsulation-test-app/tests/integration/smoke-test.js similarity index 100% rename from packages/-debug-encapsulation-test-app/tests/integration/smoke-test.js rename to packages/unpublished-debug-encapsulation-test-app/tests/integration/smoke-test.js diff --git a/packages/-debug-encapsulation-test-app/tests/test-helper.js b/packages/unpublished-debug-encapsulation-test-app/tests/test-helper.js similarity index 100% rename from packages/-debug-encapsulation-test-app/tests/test-helper.js rename to packages/unpublished-debug-encapsulation-test-app/tests/test-helper.js diff --git a/packages/-debug-encapsulation-test-app/tests/unit/.gitkeep b/packages/unpublished-debug-encapsulation-test-app/tests/unit/.gitkeep similarity index 100% rename from packages/-debug-encapsulation-test-app/tests/unit/.gitkeep rename to packages/unpublished-debug-encapsulation-test-app/tests/unit/.gitkeep diff --git a/packages/-debug-encapsulation-test-app/vendor/.gitkeep b/packages/unpublished-debug-encapsulation-test-app/vendor/.gitkeep similarity index 100% rename from packages/-debug-encapsulation-test-app/vendor/.gitkeep rename to packages/unpublished-debug-encapsulation-test-app/vendor/.gitkeep diff --git a/packages/-fastboot-test-app/.editorconfig b/packages/unpublished-fastboot-test-app/.editorconfig similarity index 100% rename from packages/-fastboot-test-app/.editorconfig rename to packages/unpublished-fastboot-test-app/.editorconfig diff --git a/packages/-fastboot-test-app/.ember-cli b/packages/unpublished-fastboot-test-app/.ember-cli similarity index 100% rename from packages/-fastboot-test-app/.ember-cli rename to packages/unpublished-fastboot-test-app/.ember-cli diff --git a/packages/-fastboot-test-app/.gitignore b/packages/unpublished-fastboot-test-app/.gitignore similarity index 100% rename from packages/-fastboot-test-app/.gitignore rename to packages/unpublished-fastboot-test-app/.gitignore diff --git a/packages/-fastboot-test-app/.template-lintrc.js b/packages/unpublished-fastboot-test-app/.template-lintrc.js similarity index 100% rename from packages/-fastboot-test-app/.template-lintrc.js rename to packages/unpublished-fastboot-test-app/.template-lintrc.js diff --git a/packages/-fastboot-test-app/.watchmanconfig b/packages/unpublished-fastboot-test-app/.watchmanconfig similarity index 100% rename from packages/-fastboot-test-app/.watchmanconfig rename to packages/unpublished-fastboot-test-app/.watchmanconfig diff --git a/packages/-fastboot-test-app/README.md b/packages/unpublished-fastboot-test-app/README.md similarity index 100% rename from packages/-fastboot-test-app/README.md rename to packages/unpublished-fastboot-test-app/README.md diff --git a/packages/-fastboot-test-app/app/adapters/application.ts b/packages/unpublished-fastboot-test-app/app/adapters/application.ts similarity index 100% rename from packages/-fastboot-test-app/app/adapters/application.ts rename to packages/unpublished-fastboot-test-app/app/adapters/application.ts diff --git a/packages/-fastboot-test-app/app/app.ts b/packages/unpublished-fastboot-test-app/app/app.ts similarity index 100% rename from packages/-fastboot-test-app/app/app.ts rename to packages/unpublished-fastboot-test-app/app/app.ts diff --git a/packages/-fastboot-test-app/app/config/environment.d.ts b/packages/unpublished-fastboot-test-app/app/config/environment.d.ts similarity index 100% rename from packages/-fastboot-test-app/app/config/environment.d.ts rename to packages/unpublished-fastboot-test-app/app/config/environment.d.ts diff --git a/packages/-fastboot-test-app/app/helpers/.gitkeep b/packages/unpublished-fastboot-test-app/app/helpers/.gitkeep similarity index 100% rename from packages/-fastboot-test-app/app/helpers/.gitkeep rename to packages/unpublished-fastboot-test-app/app/helpers/.gitkeep diff --git a/packages/-fastboot-test-app/app/index.html b/packages/unpublished-fastboot-test-app/app/index.html similarity index 100% rename from packages/-fastboot-test-app/app/index.html rename to packages/unpublished-fastboot-test-app/app/index.html diff --git a/packages/-fastboot-test-app/app/models/.gitkeep b/packages/unpublished-fastboot-test-app/app/models/.gitkeep similarity index 100% rename from packages/-fastboot-test-app/app/models/.gitkeep rename to packages/unpublished-fastboot-test-app/app/models/.gitkeep diff --git a/packages/-fastboot-test-app/app/models/person.js b/packages/unpublished-fastboot-test-app/app/models/person.js similarity index 100% rename from packages/-fastboot-test-app/app/models/person.js rename to packages/unpublished-fastboot-test-app/app/models/person.js diff --git a/packages/-fastboot-test-app/app/resolver.ts b/packages/unpublished-fastboot-test-app/app/resolver.ts similarity index 100% rename from packages/-fastboot-test-app/app/resolver.ts rename to packages/unpublished-fastboot-test-app/app/resolver.ts diff --git a/packages/-fastboot-test-app/app/router.ts b/packages/unpublished-fastboot-test-app/app/router.ts similarity index 70% rename from packages/-fastboot-test-app/app/router.ts rename to packages/unpublished-fastboot-test-app/app/router.ts index 8f6f4598916..c4ff0a4c695 100644 --- a/packages/-fastboot-test-app/app/router.ts +++ b/packages/unpublished-fastboot-test-app/app/router.ts @@ -6,6 +6,10 @@ const Router = EmberRouter.extend({ rootURL: config.rootURL, }); -Router.map(function() {}); +Router.map(function() { + this.route('person', function() { + this.route('new'); + }); +}); export default Router; diff --git a/packages/-fastboot-test-app/app/routes/.gitkeep b/packages/unpublished-fastboot-test-app/app/routes/.gitkeep similarity index 100% rename from packages/-fastboot-test-app/app/routes/.gitkeep rename to packages/unpublished-fastboot-test-app/app/routes/.gitkeep diff --git a/packages/-fastboot-test-app/app/routes/index.js b/packages/unpublished-fastboot-test-app/app/routes/index.js similarity index 100% rename from packages/-fastboot-test-app/app/routes/index.js rename to packages/unpublished-fastboot-test-app/app/routes/index.js diff --git a/packages/-fastboot-test-app/app/serializers/application.ts b/packages/unpublished-fastboot-test-app/app/serializers/application.ts similarity index 100% rename from packages/-fastboot-test-app/app/serializers/application.ts rename to packages/unpublished-fastboot-test-app/app/serializers/application.ts diff --git a/packages/-fastboot-test-app/app/styles/app.css b/packages/unpublished-fastboot-test-app/app/styles/app.css similarity index 100% rename from packages/-fastboot-test-app/app/styles/app.css rename to packages/unpublished-fastboot-test-app/app/styles/app.css diff --git a/packages/-fastboot-test-app/app/templates/.gitkeep b/packages/unpublished-fastboot-test-app/app/templates/.gitkeep similarity index 100% rename from packages/-fastboot-test-app/app/templates/.gitkeep rename to packages/unpublished-fastboot-test-app/app/templates/.gitkeep diff --git a/packages/-fastboot-test-app/app/templates/application.hbs b/packages/unpublished-fastboot-test-app/app/templates/application.hbs similarity index 100% rename from packages/-fastboot-test-app/app/templates/application.hbs rename to packages/unpublished-fastboot-test-app/app/templates/application.hbs diff --git a/packages/-fastboot-test-app/app/templates/index.hbs b/packages/unpublished-fastboot-test-app/app/templates/index.hbs similarity index 100% rename from packages/-fastboot-test-app/app/templates/index.hbs rename to packages/unpublished-fastboot-test-app/app/templates/index.hbs diff --git a/packages/-fastboot-test-app/config/environment.js b/packages/unpublished-fastboot-test-app/config/environment.js similarity index 100% rename from packages/-fastboot-test-app/config/environment.js rename to packages/unpublished-fastboot-test-app/config/environment.js diff --git a/packages/-fastboot-test-app/config/optional-features.json b/packages/unpublished-fastboot-test-app/config/optional-features.json similarity index 100% rename from packages/-fastboot-test-app/config/optional-features.json rename to packages/unpublished-fastboot-test-app/config/optional-features.json diff --git a/packages/-fastboot-test-app/config/targets.js b/packages/unpublished-fastboot-test-app/config/targets.js similarity index 100% rename from packages/-fastboot-test-app/config/targets.js rename to packages/unpublished-fastboot-test-app/config/targets.js diff --git a/packages/-fastboot-test-app/ember-cli-build.js b/packages/unpublished-fastboot-test-app/ember-cli-build.js similarity index 100% rename from packages/-fastboot-test-app/ember-cli-build.js rename to packages/unpublished-fastboot-test-app/ember-cli-build.js diff --git a/packages/-fastboot-test-app/package.json b/packages/unpublished-fastboot-test-app/package.json similarity index 82% rename from packages/-fastboot-test-app/package.json rename to packages/unpublished-fastboot-test-app/package.json index ce7f18afc76..18706a68c1b 100644 --- a/packages/-fastboot-test-app/package.json +++ b/packages/unpublished-fastboot-test-app/package.json @@ -22,7 +22,7 @@ "ember-inflector": "^3.0.1" }, "devDependencies": { - "@ember/optional-features": "^1.0.0", + "@ember/optional-features": "^1.1.0", "@types/ember": "^3.1.1", "@types/ember-qunit": "^3.4.7", "@types/ember__test-helpers": "~0.7.9", @@ -41,21 +41,24 @@ "ember-cli-typescript": "^3.0.0", "ember-cli-typescript-blueprints": "^3.0.0", "ember-export-application-global": "^2.0.0", - "ember-fetch": "^6.7.1", - "ember-load-initializers": "^2.1.0", + "ember-fetch": "^6.7.2", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-simple-tree": "^0.7.0", - "ember-source": "^3.13.3", - "eslint": "^6.5.1", - "eslint-plugin-ember": "^7.2.0", + "ember-simple-tree": "^0.7.1", + "ember-source": "^3.14.1", + "eslint": "^6.6.0", + "eslint-plugin-ember": "^7.3.0", "eslint-plugin-node": "^10.0.0", "loader.js": "^4.7.0", "qunit": "^2.9.3", - "qunit-dom": "^0.9.0", + "qunit-dom": "^0.9.1", "typescript": "~3.6.4" }, + "fastbootDependencies": [ + "crypto" + ], "engines": { "node": "8.* || >= 10.*" } diff --git a/packages/-fastboot-test-app/public/robots.txt b/packages/unpublished-fastboot-test-app/public/robots.txt similarity index 100% rename from packages/-fastboot-test-app/public/robots.txt rename to packages/unpublished-fastboot-test-app/public/robots.txt diff --git a/packages/-fastboot-test-app/testem.js b/packages/unpublished-fastboot-test-app/testem.js similarity index 100% rename from packages/-fastboot-test-app/testem.js rename to packages/unpublished-fastboot-test-app/testem.js diff --git a/packages/-fastboot-test-app/tests/fastboot/index-test.js b/packages/unpublished-fastboot-test-app/tests/fastboot/index-test.js similarity index 100% rename from packages/-fastboot-test-app/tests/fastboot/index-test.js rename to packages/unpublished-fastboot-test-app/tests/fastboot/index-test.js diff --git a/packages/-fastboot-test-app/tests/helpers/.gitkeep b/packages/unpublished-fastboot-test-app/tests/helpers/.gitkeep similarity index 100% rename from packages/-fastboot-test-app/tests/helpers/.gitkeep rename to packages/unpublished-fastboot-test-app/tests/helpers/.gitkeep diff --git a/packages/-fastboot-test-app/tests/index.html b/packages/unpublished-fastboot-test-app/tests/index.html similarity index 100% rename from packages/-fastboot-test-app/tests/index.html rename to packages/unpublished-fastboot-test-app/tests/index.html diff --git a/packages/-fastboot-test-app/tests/integration/.gitkeep b/packages/unpublished-fastboot-test-app/tests/integration/.gitkeep similarity index 100% rename from packages/-fastboot-test-app/tests/integration/.gitkeep rename to packages/unpublished-fastboot-test-app/tests/integration/.gitkeep diff --git a/packages/-fastboot-test-app/tests/test-helper.js b/packages/unpublished-fastboot-test-app/tests/test-helper.js similarity index 100% rename from packages/-fastboot-test-app/tests/test-helper.js rename to packages/unpublished-fastboot-test-app/tests/test-helper.js diff --git a/packages/-fastboot-test-app/tests/unit/.gitkeep b/packages/unpublished-fastboot-test-app/tests/unit/.gitkeep similarity index 100% rename from packages/-fastboot-test-app/tests/unit/.gitkeep rename to packages/unpublished-fastboot-test-app/tests/unit/.gitkeep diff --git a/packages/-fastboot-test-app/tsconfig.json b/packages/unpublished-fastboot-test-app/tsconfig.json similarity index 100% rename from packages/-fastboot-test-app/tsconfig.json rename to packages/unpublished-fastboot-test-app/tsconfig.json diff --git a/packages/-fastboot-test-app/types/fastboot-test-app/index.d.ts b/packages/unpublished-fastboot-test-app/types/fastboot-test-app/index.d.ts similarity index 100% rename from packages/-fastboot-test-app/types/fastboot-test-app/index.d.ts rename to packages/unpublished-fastboot-test-app/types/fastboot-test-app/index.d.ts diff --git a/packages/-fastboot-test-app/types/global.d.ts b/packages/unpublished-fastboot-test-app/types/global.d.ts similarity index 100% rename from packages/-fastboot-test-app/types/global.d.ts rename to packages/unpublished-fastboot-test-app/types/global.d.ts diff --git a/packages/-fastboot-test-app/vendor/.gitkeep b/packages/unpublished-fastboot-test-app/vendor/.gitkeep similarity index 100% rename from packages/-fastboot-test-app/vendor/.gitkeep rename to packages/unpublished-fastboot-test-app/vendor/.gitkeep diff --git a/packages/-model-encapsulation-test-app/.editorconfig b/packages/unpublished-model-encapsulation-test-app/.editorconfig similarity index 100% rename from packages/-model-encapsulation-test-app/.editorconfig rename to packages/unpublished-model-encapsulation-test-app/.editorconfig diff --git a/packages/-model-encapsulation-test-app/.gitignore b/packages/unpublished-model-encapsulation-test-app/.gitignore similarity index 100% rename from packages/-model-encapsulation-test-app/.gitignore rename to packages/unpublished-model-encapsulation-test-app/.gitignore diff --git a/packages/-model-encapsulation-test-app/.template-lintrc.js b/packages/unpublished-model-encapsulation-test-app/.template-lintrc.js similarity index 100% rename from packages/-model-encapsulation-test-app/.template-lintrc.js rename to packages/unpublished-model-encapsulation-test-app/.template-lintrc.js diff --git a/packages/-model-encapsulation-test-app/.watchmanconfig b/packages/unpublished-model-encapsulation-test-app/.watchmanconfig similarity index 100% rename from packages/-model-encapsulation-test-app/.watchmanconfig rename to packages/unpublished-model-encapsulation-test-app/.watchmanconfig diff --git a/packages/-model-encapsulation-test-app/README.md b/packages/unpublished-model-encapsulation-test-app/README.md similarity index 100% rename from packages/-model-encapsulation-test-app/README.md rename to packages/unpublished-model-encapsulation-test-app/README.md diff --git a/packages/-model-encapsulation-test-app/app/app.js b/packages/unpublished-model-encapsulation-test-app/app/app.js similarity index 100% rename from packages/-model-encapsulation-test-app/app/app.js rename to packages/unpublished-model-encapsulation-test-app/app/app.js diff --git a/packages/-model-encapsulation-test-app/app/components/.gitkeep b/packages/unpublished-model-encapsulation-test-app/app/components/.gitkeep similarity index 100% rename from packages/-model-encapsulation-test-app/app/components/.gitkeep rename to packages/unpublished-model-encapsulation-test-app/app/components/.gitkeep diff --git a/packages/-model-encapsulation-test-app/app/controllers/.gitkeep b/packages/unpublished-model-encapsulation-test-app/app/controllers/.gitkeep similarity index 100% rename from packages/-model-encapsulation-test-app/app/controllers/.gitkeep rename to packages/unpublished-model-encapsulation-test-app/app/controllers/.gitkeep diff --git a/packages/-model-encapsulation-test-app/app/helpers/.gitkeep b/packages/unpublished-model-encapsulation-test-app/app/helpers/.gitkeep similarity index 100% rename from packages/-model-encapsulation-test-app/app/helpers/.gitkeep rename to packages/unpublished-model-encapsulation-test-app/app/helpers/.gitkeep diff --git a/packages/-model-encapsulation-test-app/app/index.html b/packages/unpublished-model-encapsulation-test-app/app/index.html similarity index 100% rename from packages/-model-encapsulation-test-app/app/index.html rename to packages/unpublished-model-encapsulation-test-app/app/index.html diff --git a/packages/-model-encapsulation-test-app/app/models/.gitkeep b/packages/unpublished-model-encapsulation-test-app/app/models/.gitkeep similarity index 100% rename from packages/-model-encapsulation-test-app/app/models/.gitkeep rename to packages/unpublished-model-encapsulation-test-app/app/models/.gitkeep diff --git a/packages/-model-encapsulation-test-app/app/resolver.js b/packages/unpublished-model-encapsulation-test-app/app/resolver.js similarity index 100% rename from packages/-model-encapsulation-test-app/app/resolver.js rename to packages/unpublished-model-encapsulation-test-app/app/resolver.js diff --git a/packages/-model-encapsulation-test-app/app/router.js b/packages/unpublished-model-encapsulation-test-app/app/router.js similarity index 100% rename from packages/-model-encapsulation-test-app/app/router.js rename to packages/unpublished-model-encapsulation-test-app/app/router.js diff --git a/packages/-model-encapsulation-test-app/app/routes/.gitkeep b/packages/unpublished-model-encapsulation-test-app/app/routes/.gitkeep similarity index 100% rename from packages/-model-encapsulation-test-app/app/routes/.gitkeep rename to packages/unpublished-model-encapsulation-test-app/app/routes/.gitkeep diff --git a/packages/-model-encapsulation-test-app/app/styles/app.css b/packages/unpublished-model-encapsulation-test-app/app/styles/app.css similarity index 100% rename from packages/-model-encapsulation-test-app/app/styles/app.css rename to packages/unpublished-model-encapsulation-test-app/app/styles/app.css diff --git a/packages/-model-encapsulation-test-app/app/templates/application.hbs b/packages/unpublished-model-encapsulation-test-app/app/templates/application.hbs similarity index 100% rename from packages/-model-encapsulation-test-app/app/templates/application.hbs rename to packages/unpublished-model-encapsulation-test-app/app/templates/application.hbs diff --git a/packages/-model-encapsulation-test-app/app/templates/components/.gitkeep b/packages/unpublished-model-encapsulation-test-app/app/templates/components/.gitkeep similarity index 100% rename from packages/-model-encapsulation-test-app/app/templates/components/.gitkeep rename to packages/unpublished-model-encapsulation-test-app/app/templates/components/.gitkeep diff --git a/packages/-model-encapsulation-test-app/config/environment.js b/packages/unpublished-model-encapsulation-test-app/config/environment.js similarity index 100% rename from packages/-model-encapsulation-test-app/config/environment.js rename to packages/unpublished-model-encapsulation-test-app/config/environment.js diff --git a/packages/-model-encapsulation-test-app/config/optional-features.json b/packages/unpublished-model-encapsulation-test-app/config/optional-features.json similarity index 100% rename from packages/-model-encapsulation-test-app/config/optional-features.json rename to packages/unpublished-model-encapsulation-test-app/config/optional-features.json diff --git a/packages/-model-encapsulation-test-app/config/targets.js b/packages/unpublished-model-encapsulation-test-app/config/targets.js similarity index 100% rename from packages/-model-encapsulation-test-app/config/targets.js rename to packages/unpublished-model-encapsulation-test-app/config/targets.js diff --git a/packages/-model-encapsulation-test-app/ember-cli-build.js b/packages/unpublished-model-encapsulation-test-app/ember-cli-build.js similarity index 100% rename from packages/-model-encapsulation-test-app/ember-cli-build.js rename to packages/unpublished-model-encapsulation-test-app/ember-cli-build.js diff --git a/packages/-model-encapsulation-test-app/package.json b/packages/unpublished-model-encapsulation-test-app/package.json similarity index 85% rename from packages/-model-encapsulation-test-app/package.json rename to packages/unpublished-model-encapsulation-test-app/package.json index c1eba9662d5..9a18a125bd6 100644 --- a/packages/-model-encapsulation-test-app/package.json +++ b/packages/unpublished-model-encapsulation-test-app/package.json @@ -24,7 +24,7 @@ "ember-inflector": "^3.0.1" }, "devDependencies": { - "@ember/optional-features": "^1.0.0", + "@ember/optional-features": "^1.1.0", "broccoli-asset-rev": "^3.0.0", "ember-cli": "~3.13.1", "ember-cli-app-version": "^3.2.0", @@ -34,16 +34,16 @@ "ember-cli-inject-live-reload": "^2.0.2", "ember-cli-template-lint": "^1.0.0-beta.1", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", - "eslint": "^6.5.1", - "eslint-plugin-ember": "^7.2.0", + "ember-source": "^3.14.1", + "eslint": "^6.6.0", + "eslint-plugin-ember": "^7.3.0", "eslint-plugin-node": "^10.0.0", "loader.js": "^4.7.0", - "qunit-dom": "^0.9.0" + "qunit-dom": "^0.9.1" }, "engines": { "node": "8.* || >= 10.*" diff --git a/packages/-model-encapsulation-test-app/public/robots.txt b/packages/unpublished-model-encapsulation-test-app/public/robots.txt similarity index 100% rename from packages/-model-encapsulation-test-app/public/robots.txt rename to packages/unpublished-model-encapsulation-test-app/public/robots.txt diff --git a/packages/-model-encapsulation-test-app/testem.js b/packages/unpublished-model-encapsulation-test-app/testem.js similarity index 100% rename from packages/-model-encapsulation-test-app/testem.js rename to packages/unpublished-model-encapsulation-test-app/testem.js diff --git a/packages/-model-encapsulation-test-app/tests/helpers/.gitkeep b/packages/unpublished-model-encapsulation-test-app/tests/helpers/.gitkeep similarity index 100% rename from packages/-model-encapsulation-test-app/tests/helpers/.gitkeep rename to packages/unpublished-model-encapsulation-test-app/tests/helpers/.gitkeep diff --git a/packages/-model-encapsulation-test-app/tests/index.html b/packages/unpublished-model-encapsulation-test-app/tests/index.html similarity index 100% rename from packages/-model-encapsulation-test-app/tests/index.html rename to packages/unpublished-model-encapsulation-test-app/tests/index.html diff --git a/packages/-model-encapsulation-test-app/tests/integration/.gitkeep b/packages/unpublished-model-encapsulation-test-app/tests/integration/.gitkeep similarity index 100% rename from packages/-model-encapsulation-test-app/tests/integration/.gitkeep rename to packages/unpublished-model-encapsulation-test-app/tests/integration/.gitkeep diff --git a/packages/-model-encapsulation-test-app/tests/integration/smoke-test.js b/packages/unpublished-model-encapsulation-test-app/tests/integration/smoke-test.js similarity index 100% rename from packages/-model-encapsulation-test-app/tests/integration/smoke-test.js rename to packages/unpublished-model-encapsulation-test-app/tests/integration/smoke-test.js diff --git a/packages/-model-encapsulation-test-app/tests/test-helper.js b/packages/unpublished-model-encapsulation-test-app/tests/test-helper.js similarity index 100% rename from packages/-model-encapsulation-test-app/tests/test-helper.js rename to packages/unpublished-model-encapsulation-test-app/tests/test-helper.js diff --git a/packages/-model-encapsulation-test-app/tests/unit/.gitkeep b/packages/unpublished-model-encapsulation-test-app/tests/unit/.gitkeep similarity index 100% rename from packages/-model-encapsulation-test-app/tests/unit/.gitkeep rename to packages/unpublished-model-encapsulation-test-app/tests/unit/.gitkeep diff --git a/packages/-model-encapsulation-test-app/vendor/.gitkeep b/packages/unpublished-model-encapsulation-test-app/vendor/.gitkeep similarity index 100% rename from packages/-model-encapsulation-test-app/vendor/.gitkeep rename to packages/unpublished-model-encapsulation-test-app/vendor/.gitkeep diff --git a/packages/-record-data-encapsulation-test-app/.editorconfig b/packages/unpublished-record-data-encapsulation-test-app/.editorconfig similarity index 100% rename from packages/-record-data-encapsulation-test-app/.editorconfig rename to packages/unpublished-record-data-encapsulation-test-app/.editorconfig diff --git a/packages/-record-data-encapsulation-test-app/.ember-cli b/packages/unpublished-record-data-encapsulation-test-app/.ember-cli similarity index 100% rename from packages/-record-data-encapsulation-test-app/.ember-cli rename to packages/unpublished-record-data-encapsulation-test-app/.ember-cli diff --git a/packages/-record-data-encapsulation-test-app/.gitignore b/packages/unpublished-record-data-encapsulation-test-app/.gitignore similarity index 100% rename from packages/-record-data-encapsulation-test-app/.gitignore rename to packages/unpublished-record-data-encapsulation-test-app/.gitignore diff --git a/packages/-record-data-encapsulation-test-app/.template-lintrc.js b/packages/unpublished-record-data-encapsulation-test-app/.template-lintrc.js similarity index 100% rename from packages/-record-data-encapsulation-test-app/.template-lintrc.js rename to packages/unpublished-record-data-encapsulation-test-app/.template-lintrc.js diff --git a/packages/-record-data-encapsulation-test-app/.watchmanconfig b/packages/unpublished-record-data-encapsulation-test-app/.watchmanconfig similarity index 100% rename from packages/-record-data-encapsulation-test-app/.watchmanconfig rename to packages/unpublished-record-data-encapsulation-test-app/.watchmanconfig diff --git a/packages/-record-data-encapsulation-test-app/README.md b/packages/unpublished-record-data-encapsulation-test-app/README.md similarity index 100% rename from packages/-record-data-encapsulation-test-app/README.md rename to packages/unpublished-record-data-encapsulation-test-app/README.md diff --git a/packages/-record-data-encapsulation-test-app/app/app.js b/packages/unpublished-record-data-encapsulation-test-app/app/app.js similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/app.js rename to packages/unpublished-record-data-encapsulation-test-app/app/app.js diff --git a/packages/-record-data-encapsulation-test-app/app/components/.gitkeep b/packages/unpublished-record-data-encapsulation-test-app/app/components/.gitkeep similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/components/.gitkeep rename to packages/unpublished-record-data-encapsulation-test-app/app/components/.gitkeep diff --git a/packages/-record-data-encapsulation-test-app/app/controllers/.gitkeep b/packages/unpublished-record-data-encapsulation-test-app/app/controllers/.gitkeep similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/controllers/.gitkeep rename to packages/unpublished-record-data-encapsulation-test-app/app/controllers/.gitkeep diff --git a/packages/-record-data-encapsulation-test-app/app/helpers/.gitkeep b/packages/unpublished-record-data-encapsulation-test-app/app/helpers/.gitkeep similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/helpers/.gitkeep rename to packages/unpublished-record-data-encapsulation-test-app/app/helpers/.gitkeep diff --git a/packages/-record-data-encapsulation-test-app/app/index.html b/packages/unpublished-record-data-encapsulation-test-app/app/index.html similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/index.html rename to packages/unpublished-record-data-encapsulation-test-app/app/index.html diff --git a/packages/-record-data-encapsulation-test-app/app/models/.gitkeep b/packages/unpublished-record-data-encapsulation-test-app/app/models/.gitkeep similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/models/.gitkeep rename to packages/unpublished-record-data-encapsulation-test-app/app/models/.gitkeep diff --git a/packages/-record-data-encapsulation-test-app/app/resolver.js b/packages/unpublished-record-data-encapsulation-test-app/app/resolver.js similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/resolver.js rename to packages/unpublished-record-data-encapsulation-test-app/app/resolver.js diff --git a/packages/-record-data-encapsulation-test-app/app/router.js b/packages/unpublished-record-data-encapsulation-test-app/app/router.js similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/router.js rename to packages/unpublished-record-data-encapsulation-test-app/app/router.js diff --git a/packages/-record-data-encapsulation-test-app/app/routes/.gitkeep b/packages/unpublished-record-data-encapsulation-test-app/app/routes/.gitkeep similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/routes/.gitkeep rename to packages/unpublished-record-data-encapsulation-test-app/app/routes/.gitkeep diff --git a/packages/-record-data-encapsulation-test-app/app/styles/app.css b/packages/unpublished-record-data-encapsulation-test-app/app/styles/app.css similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/styles/app.css rename to packages/unpublished-record-data-encapsulation-test-app/app/styles/app.css diff --git a/packages/-record-data-encapsulation-test-app/app/templates/application.hbs b/packages/unpublished-record-data-encapsulation-test-app/app/templates/application.hbs similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/templates/application.hbs rename to packages/unpublished-record-data-encapsulation-test-app/app/templates/application.hbs diff --git a/packages/-record-data-encapsulation-test-app/app/templates/components/.gitkeep b/packages/unpublished-record-data-encapsulation-test-app/app/templates/components/.gitkeep similarity index 100% rename from packages/-record-data-encapsulation-test-app/app/templates/components/.gitkeep rename to packages/unpublished-record-data-encapsulation-test-app/app/templates/components/.gitkeep diff --git a/packages/-record-data-encapsulation-test-app/config/environment.js b/packages/unpublished-record-data-encapsulation-test-app/config/environment.js similarity index 100% rename from packages/-record-data-encapsulation-test-app/config/environment.js rename to packages/unpublished-record-data-encapsulation-test-app/config/environment.js diff --git a/packages/-record-data-encapsulation-test-app/config/optional-features.json b/packages/unpublished-record-data-encapsulation-test-app/config/optional-features.json similarity index 100% rename from packages/-record-data-encapsulation-test-app/config/optional-features.json rename to packages/unpublished-record-data-encapsulation-test-app/config/optional-features.json diff --git a/packages/-record-data-encapsulation-test-app/config/targets.js b/packages/unpublished-record-data-encapsulation-test-app/config/targets.js similarity index 100% rename from packages/-record-data-encapsulation-test-app/config/targets.js rename to packages/unpublished-record-data-encapsulation-test-app/config/targets.js diff --git a/packages/-record-data-encapsulation-test-app/ember-cli-build.js b/packages/unpublished-record-data-encapsulation-test-app/ember-cli-build.js similarity index 100% rename from packages/-record-data-encapsulation-test-app/ember-cli-build.js rename to packages/unpublished-record-data-encapsulation-test-app/ember-cli-build.js diff --git a/packages/-record-data-encapsulation-test-app/package.json b/packages/unpublished-record-data-encapsulation-test-app/package.json similarity index 85% rename from packages/-record-data-encapsulation-test-app/package.json rename to packages/unpublished-record-data-encapsulation-test-app/package.json index e3f6742a982..8fd7592ef17 100644 --- a/packages/-record-data-encapsulation-test-app/package.json +++ b/packages/unpublished-record-data-encapsulation-test-app/package.json @@ -26,7 +26,7 @@ "ember-inflector": "^3.0.1" }, "devDependencies": { - "@ember/optional-features": "^1.0.0", + "@ember/optional-features": "^1.1.0", "broccoli-asset-rev": "^3.0.0", "ember-cli": "~3.13.1", "ember-cli-app-version": "^3.2.0", @@ -36,16 +36,16 @@ "ember-cli-inject-live-reload": "^2.0.2", "ember-cli-template-lint": "^1.0.0-beta.1", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", - "eslint": "^6.5.1", - "eslint-plugin-ember": "^7.2.0", + "ember-source": "^3.14.1", + "eslint": "^6.6.0", + "eslint-plugin-ember": "^7.3.0", "eslint-plugin-node": "^10.0.0", "loader.js": "^4.7.0", - "qunit-dom": "^0.9.0" + "qunit-dom": "^0.9.1" }, "engines": { "node": "8.* || >= 10.*" diff --git a/packages/-record-data-encapsulation-test-app/public/robots.txt b/packages/unpublished-record-data-encapsulation-test-app/public/robots.txt similarity index 100% rename from packages/-record-data-encapsulation-test-app/public/robots.txt rename to packages/unpublished-record-data-encapsulation-test-app/public/robots.txt diff --git a/packages/-record-data-encapsulation-test-app/testem.js b/packages/unpublished-record-data-encapsulation-test-app/testem.js similarity index 100% rename from packages/-record-data-encapsulation-test-app/testem.js rename to packages/unpublished-record-data-encapsulation-test-app/testem.js diff --git a/packages/-record-data-encapsulation-test-app/tests/helpers/.gitkeep b/packages/unpublished-record-data-encapsulation-test-app/tests/helpers/.gitkeep similarity index 100% rename from packages/-record-data-encapsulation-test-app/tests/helpers/.gitkeep rename to packages/unpublished-record-data-encapsulation-test-app/tests/helpers/.gitkeep diff --git a/packages/-record-data-encapsulation-test-app/tests/index.html b/packages/unpublished-record-data-encapsulation-test-app/tests/index.html similarity index 100% rename from packages/-record-data-encapsulation-test-app/tests/index.html rename to packages/unpublished-record-data-encapsulation-test-app/tests/index.html diff --git a/packages/-record-data-encapsulation-test-app/tests/integration/.gitkeep b/packages/unpublished-record-data-encapsulation-test-app/tests/integration/.gitkeep similarity index 100% rename from packages/-record-data-encapsulation-test-app/tests/integration/.gitkeep rename to packages/unpublished-record-data-encapsulation-test-app/tests/integration/.gitkeep diff --git a/packages/-record-data-encapsulation-test-app/tests/integration/smoke-test.js b/packages/unpublished-record-data-encapsulation-test-app/tests/integration/smoke-test.js similarity index 100% rename from packages/-record-data-encapsulation-test-app/tests/integration/smoke-test.js rename to packages/unpublished-record-data-encapsulation-test-app/tests/integration/smoke-test.js diff --git a/packages/-record-data-encapsulation-test-app/tests/test-helper.js b/packages/unpublished-record-data-encapsulation-test-app/tests/test-helper.js similarity index 100% rename from packages/-record-data-encapsulation-test-app/tests/test-helper.js rename to packages/unpublished-record-data-encapsulation-test-app/tests/test-helper.js diff --git a/packages/-record-data-encapsulation-test-app/tests/unit/.gitkeep b/packages/unpublished-record-data-encapsulation-test-app/tests/unit/.gitkeep similarity index 100% rename from packages/-record-data-encapsulation-test-app/tests/unit/.gitkeep rename to packages/unpublished-record-data-encapsulation-test-app/tests/unit/.gitkeep diff --git a/packages/-record-data-encapsulation-test-app/vendor/.gitkeep b/packages/unpublished-record-data-encapsulation-test-app/vendor/.gitkeep similarity index 100% rename from packages/-record-data-encapsulation-test-app/vendor/.gitkeep rename to packages/unpublished-record-data-encapsulation-test-app/vendor/.gitkeep diff --git a/packages/unpublished-relationship-performance-test-app/.gitignore b/packages/unpublished-relationship-performance-test-app/.gitignore index c40a1b2aba3..08ab0dd20b6 100644 --- a/packages/unpublished-relationship-performance-test-app/.gitignore +++ b/packages/unpublished-relationship-performance-test-app/.gitignore @@ -2,6 +2,8 @@ # compiled output /dist/ +/dist-control/ +/dist-experiment/ /tmp/ # dependencies diff --git a/packages/unpublished-relationship-performance-test-app/.travis.yml b/packages/unpublished-relationship-performance-test-app/.travis.yml deleted file mode 100644 index f09af517e4e..00000000000 --- a/packages/unpublished-relationship-performance-test-app/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: node_js -node_js: - - '10' -services: - - mongodb -sudo: false -dist: trusty - -addons: - chrome: stable - -cache: - directories: - - $HOME/.npm - -env: - global: - - JOBS=1 - -before_install: - - npm config set spin false - -script: - - yarn tracerbench:compare diff --git a/packages/unpublished-relationship-performance-test-app/PERFORMANCE_BENCHMARKING.md b/packages/unpublished-relationship-performance-test-app/PERFORMANCE_BENCHMARKING.md index a27b11ed11c..370cae484cb 100644 --- a/packages/unpublished-relationship-performance-test-app/PERFORMANCE_BENCHMARKING.md +++ b/packages/unpublished-relationship-performance-test-app/PERFORMANCE_BENCHMARKING.md @@ -1,16 +1,13 @@ # Performance Benchmarking ``` -npm install -g concurrently -npm i -g server-replay +npm install -g tracerbench pm2 ``` -A HAR file has already been created for this app from a production build. It can be found at `packages/-relationship-performance-test-app/bin/localhost.har`. - -=`const samplesCount = 2;` in `packages/-relationship-performance-test-app/bin/tracerbench.js` controls the number of samples run. +A HAR file has already been created for this app from a production build. It can be found at `packages/unpublished-relationship-performance-test-app/bin/localhost.har`. Next, run the following from the root of this repository: ``` -APP=relationship-performance-test-app yarn tracerbench +./bin/relationship-performance-check ``` diff --git a/packages/unpublished-relationship-performance-test-app/bin/har-remix.js b/packages/unpublished-relationship-performance-test-app/bin/har-remix.js new file mode 100644 index 00000000000..7afbcf897ca --- /dev/null +++ b/packages/unpublished-relationship-performance-test-app/bin/har-remix.js @@ -0,0 +1,42 @@ +const { default: HARRemix } = require('har-remix'); +const { URL } = require('url'); +const fs = require('fs'); + +const { HR_PORT, HR_GROUP } = process.env; + +if (!HR_GROUP) { + throw new Error('You need to set the HR_GROUP environment variable to either "control" or "experiment"'); +} + +const harRemix = new HARRemix({ + keyForArchiveEntry(entry) { + let { request, response } = entry; + let { status } = response; + + if (status >= 200 && status < 300 && request.method !== 'OPTIONS') { + const { method, url: requestUrl } = request; + return `${method} ${new URL(requestUrl).pathname}`; + } + }, + + keyForServerRequest(request) { + const { method, url } = request; + + if (url.includes('?')) { + return `${method} ${url.replace(/\?.+/, '')}`; + } + + return `${method} ${url}`; + }, + + textFor(entry, key, text) { + if (key.includes('vendor.js')) { + return fs.readFileSync(`${__dirname}/../dist-${HR_GROUP}/assets/vendor.js`, 'utf8'); + } + + return text; + }, +}); + +harRemix.loadArchive(`${__dirname}/localhost.har`); +harRemix.createServer().listen(HR_PORT || 4200); diff --git a/packages/unpublished-relationship-performance-test-app/bin/localhost.har b/packages/unpublished-relationship-performance-test-app/bin/localhost.har index 451429e1d56..ca3c835c623 100644 --- a/packages/unpublished-relationship-performance-test-app/bin/localhost.har +++ b/packages/unpublished-relationship-performance-test-app/bin/localhost.har @@ -7,27 +7,27 @@ }, "pages": [ { - "startedDateTime": "2019-10-25T21:01:03.330Z", - "id": "page_4", - "title": "http://localhost:5000/", + "startedDateTime": "2019-10-31T20:32:57.788Z", + "id": "page_1", + "title": "http://localhost:4200/", "pageTimings": { - "onContentLoad": 8967.207000008784, - "onLoad": 9004.921999992803 + "onContentLoad": 8941.248000000996, + "onLoad": 8992.373000000953 } } ], "entries": [ { - "startedDateTime": "2019-10-25T21:01:03.329Z", - "time": 2.3480000090785325, + "startedDateTime": "2019-10-31T20:32:57.787Z", + "time": 2.787999999782187, "request": { "method": "GET", - "url": "http://localhost:5000/", + "url": "http://localhost:4200/", "httpVersion": "HTTP/1.1", "headers": [ { "name": "Host", - "value": "localhost:5000" + "value": "localhost:4200" }, { "name": "Connection", @@ -43,11 +43,7 @@ }, { "name": "User-Agent", - "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36" - }, - { - "name": "Sec-Fetch-Mode", - "value": "navigate" + "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36" }, { "name": "Sec-Fetch-User", @@ -61,6 +57,10 @@ "name": "Sec-Fetch-Site", "value": "same-origin" }, + { + "name": "Sec-Fetch-Mode", + "value": "navigate" + }, { "name": "Accept-Encoding", "value": "gzip, deflate, br" @@ -71,27 +71,27 @@ }, { "name": "Cookie", - "value": "amplitude_id_5e201f0eac128f83637a72cc714578f0=eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MTg1NTA0NzUyMCwibGFzdEV2ZW50VGltZSI6MTU3MTg1NTA0NzUyMiwiZXZlbnRJZCI6MTU5LCJpZGVudGlmeUlkIjo5MCwic2VxdWVuY2VOdW1iZXIiOjI0OX0=; io=dlxJjRUQi1enTuAbAAAB" + "value": "io=wIu7CXtmPvSmDD1VAAAM; amplitude_id_5e201f0eac128f83637a72cc714578f0=eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MjM4NjI4OTk2MiwibGFzdEV2ZW50VGltZSI6MTU3MjM4ODkwNjkxNiwiZXZlbnRJZCI6MTgyLCJpZGVudGlmeUlkIjo5NCwic2VxdWVuY2VOdW1iZXIiOjI3Nn0=" } ], "queryString": [], "cookies": [ { - "name": "amplitude_id_5e201f0eac128f83637a72cc714578f0", - "value": "eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MTg1NTA0NzUyMCwibGFzdEV2ZW50VGltZSI6MTU3MTg1NTA0NzUyMiwiZXZlbnRJZCI6MTU5LCJpZGVudGlmeUlkIjo5MCwic2VxdWVuY2VOdW1iZXIiOjI0OX0=", + "name": "io", + "value": "wIu7CXtmPvSmDD1VAAAM", "expires": null, "httpOnly": false, "secure": false }, { - "name": "io", - "value": "dlxJjRUQi1enTuAbAAAB", + "name": "amplitude_id_5e201f0eac128f83637a72cc714578f0", + "value": "eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MjM4NjI4OTk2MiwibGFzdEV2ZW50VGltZSI6MTU3MjM4ODkwNjkxNiwiZXZlbnRJZCI6MTgyLCJpZGVudGlmeUlkIjo5NCwic2VxdWVuY2VOdW1iZXIiOjI3Nn0=", "expires": null, "httpOnly": false, "secure": false } ], - "headersSize": 858, + "headersSize": 857, "bodySize": 0 }, "response": { @@ -101,11 +101,11 @@ "headers": [ { "name": "Host", - "value": "localhost:5000" + "value": "localhost:4200" }, { "name": "Date", - "value": "Fri, 25 Oct 2019 21:01:03 +0000" + "value": "Thu, 31 Oct 2019 20:32:57 +0000" }, { "name": "Connection", @@ -117,31 +117,31 @@ }, { "name": "Content-Length", - "value": "1308" + "value": "1176" } ], "cookies": [], "content": { - "size": 1308, + "size": 1176, "mimeType": "text/html", "compression": 0, - "text": "\n\n \n \n \n RelationshipPerformance\n \n \n\n \n\n\n \n \n\n \n \n \n \n\n \n \n\n \n \n\n" + "text": "\n\n \n \n \n RelationshipPerformance\n \n \n\n \n\n\n \n \n\n \n \n \n \n\n \n \n\n \n \n\n" }, "redirectURL": "", "headersSize": 161, - "bodySize": 1308, - "_transferSize": 1469 + "bodySize": 1176, + "_transferSize": 1337 }, "cache": {}, "timings": { - "blocked": 1.7400000006742775, + "blocked": 1.5549999996882398, "dns": -1, "ssl": -1, "connect": -1, - "send": 0.059, - "wait": 0.2559999892488122, - "receive": 0.2930000191554427, - "_blocked_queueing": 1.3990000006742775 + "send": 0.08499999999999996, + "wait": 0.759999999709311, + "receive": 0.3880000003846362, + "_blocked_queueing": 0.9339999996882398 }, "serverIPAddress": "[::1]", "_initiator": { @@ -149,349 +149,525 @@ }, "_priority": "VeryHigh", "_resourceType": "document", - "connection": "1052998", - "pageref": "page_4" + "connection": "50804", + "pageref": "page_1" }, { - "startedDateTime": "2019-10-25T21:01:03.341Z", - "time": 5.769999988842756, + "startedDateTime": "2019-10-31T20:32:57.804Z", + "time": 4.0960000005725306, "request": { "method": "GET", - "url": "http://localhost:5000/assets/vendor-d41d8cd98f00b204e9800998ecf8427e.css", - "httpVersion": "http/1.1", + "url": "http://localhost:4200/assets/vendor.css", + "httpVersion": "HTTP/1.1", "headers": [ + { + "name": "Host", + "value": "localhost:4200" + }, + { + "name": "Connection", + "value": "keep-alive" + }, + { + "name": "User-Agent", + "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36" + }, + { + "name": "Accept", + "value": "text/css,*/*;q=0.1" + }, + { + "name": "Sec-Fetch-Site", + "value": "same-origin" + }, { "name": "Sec-Fetch-Mode", "value": "no-cors" }, { "name": "Referer", - "value": "http://localhost:5000/" + "value": "http://localhost:4200/" }, { - "name": "User-Agent", - "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36" + "name": "Accept-Encoding", + "value": "gzip, deflate, br" + }, + { + "name": "Accept-Language", + "value": "en-US,en;q=0.9" + }, + { + "name": "Cookie", + "value": "io=wIu7CXtmPvSmDD1VAAAM; amplitude_id_5e201f0eac128f83637a72cc714578f0=eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MjM4NjI4OTk2MiwibGFzdEV2ZW50VGltZSI6MTU3MjM4ODkwNjkxNiwiZXZlbnRJZCI6MTgyLCJpZGVudGlmeUlkIjo5NCwic2VxdWVuY2VOdW1iZXIiOjI3Nn0=" } ], "queryString": [], - "cookies": [], - "headersSize": -1, + "cookies": [ + { + "name": "io", + "value": "wIu7CXtmPvSmDD1VAAAM", + "expires": null, + "httpOnly": false, + "secure": false + }, + { + "name": "amplitude_id_5e201f0eac128f83637a72cc714578f0", + "value": "eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MjM4NjI4OTk2MiwibGFzdEV2ZW50VGltZSI6MTU3MjM4ODkwNjkxNiwiZXZlbnRJZCI6MTgyLCJpZGVudGlmeUlkIjo5NCwic2VxdWVuY2VOdW1iZXIiOjI3Nn0=", + "expires": null, + "httpOnly": false, + "secure": false + } + ], + "headersSize": 730, "bodySize": 0 }, "response": { "status": 200, "statusText": "OK", - "httpVersion": "http/1.1", + "httpVersion": "HTTP/1.1", "headers": [ + { + "name": "Host", + "value": "localhost:4200" + }, { "name": "Date", - "value": "Fri, 25 Oct 2019 21:01:03 +0000" + "value": "Thu, 31 Oct 2019 20:32:57 +0000" }, { "name": "Connection", "value": "close" }, { - "name": "Host", - "value": "localhost:5000" + "name": "Content-Type", + "value": "text/css; charset=UTF-8" }, { "name": "Content-Length", "value": "0" - }, - { - "name": "Content-Type", - "value": "text/css; charset=UTF-8" } ], "cookies": [], "content": { "size": 0, "mimeType": "text/css", + "compression": 0, "text": "" }, "redirectURL": "", - "headersSize": -1, - "bodySize": -1, + "headersSize": 157, + "bodySize": 0, "_transferSize": 157 }, "cache": {}, "timings": { - "blocked": 4.054000007221475, + "blocked": 2.6490000003272436, "dns": -1, "ssl": -1, "connect": -1, - "send": 0.07900000000000001, - "wait": 1.36600001356937, - "receive": 0.2709999680519104, - "_blocked_queueing": 3.8040000072214752 + "send": 0.08400000000000002, + "wait": 1.102999999537482, + "receive": 0.26000000070780516, + "_blocked_queueing": 2.3920000003272435 }, "serverIPAddress": "[::1]", "_initiator": { "type": "parser", - "url": "http://localhost:5000/", + "url": "http://localhost:4200/", "lineNumber": 12 }, "_priority": "VeryHigh", "_resourceType": "stylesheet", - "connection": "1053000", - "pageref": "page_4" + "connection": "50806", + "pageref": "page_1" }, { - "startedDateTime": "2019-10-25T21:01:03.341Z", - "time": 7.316000002391636, + "startedDateTime": "2019-10-31T20:32:57.804Z", + "time": 4.8509999992650705, "request": { "method": "GET", - "url": "http://localhost:5000/assets/relationship-performance-test-app-d41d8cd98f00b204e9800998ecf8427e.css", - "httpVersion": "http/1.1", + "url": "http://localhost:4200/assets/relationship-performance-test-app.css", + "httpVersion": "HTTP/1.1", "headers": [ + { + "name": "Host", + "value": "localhost:4200" + }, + { + "name": "Connection", + "value": "keep-alive" + }, + { + "name": "User-Agent", + "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36" + }, + { + "name": "Accept", + "value": "text/css,*/*;q=0.1" + }, + { + "name": "Sec-Fetch-Site", + "value": "same-origin" + }, { "name": "Sec-Fetch-Mode", "value": "no-cors" }, { "name": "Referer", - "value": "http://localhost:5000/" + "value": "http://localhost:4200/" }, { - "name": "User-Agent", - "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36" + "name": "Accept-Encoding", + "value": "gzip, deflate, br" + }, + { + "name": "Accept-Language", + "value": "en-US,en;q=0.9" + }, + { + "name": "Cookie", + "value": "io=wIu7CXtmPvSmDD1VAAAM; amplitude_id_5e201f0eac128f83637a72cc714578f0=eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MjM4NjI4OTk2MiwibGFzdEV2ZW50VGltZSI6MTU3MjM4ODkwNjkxNiwiZXZlbnRJZCI6MTgyLCJpZGVudGlmeUlkIjo5NCwic2VxdWVuY2VOdW1iZXIiOjI3Nn0=" } ], "queryString": [], - "cookies": [], - "headersSize": -1, + "cookies": [ + { + "name": "io", + "value": "wIu7CXtmPvSmDD1VAAAM", + "expires": null, + "httpOnly": false, + "secure": false + }, + { + "name": "amplitude_id_5e201f0eac128f83637a72cc714578f0", + "value": "eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MjM4NjI4OTk2MiwibGFzdEV2ZW50VGltZSI6MTU3MjM4ODkwNjkxNiwiZXZlbnRJZCI6MTgyLCJpZGVudGlmeUlkIjo5NCwic2VxdWVuY2VOdW1iZXIiOjI3Nn0=", + "expires": null, + "httpOnly": false, + "secure": false + } + ], + "headersSize": 757, "bodySize": 0 }, "response": { "status": 200, "statusText": "OK", - "httpVersion": "http/1.1", + "httpVersion": "HTTP/1.1", "headers": [ + { + "name": "Host", + "value": "localhost:4200" + }, { "name": "Date", - "value": "Fri, 25 Oct 2019 21:01:03 +0000" + "value": "Thu, 31 Oct 2019 20:32:57 +0000" }, { "name": "Connection", "value": "close" }, { - "name": "Host", - "value": "localhost:5000" + "name": "Content-Type", + "value": "text/css; charset=UTF-8" }, { "name": "Content-Length", "value": "0" - }, - { - "name": "Content-Type", - "value": "text/css; charset=UTF-8" } ], "cookies": [], "content": { "size": 0, "mimeType": "text/css", + "compression": 0, "text": "" }, "redirectURL": "", - "headersSize": -1, - "bodySize": -1, + "headersSize": 157, + "bodySize": 0, "_transferSize": 157 }, "cache": {}, "timings": { - "blocked": 4.975000022199005, - "dns": 0.02300000000000002, + "blocked": 3.1370000003630993, + "dns": 0.01200000000000001, "ssl": -1, - "connect": 0.293, - "send": 0.9550000000000001, - "wait": 0.8659999984428286, - "receive": 0.20399998174980283, - "_blocked_queueing": 4.536000022199005 + "connect": 0.38899999999999996, + "send": 0.631, + "wait": 0.32799999911361377, + "receive": 0.35399999978835694, + "_blocked_queueing": 2.6930000003630994 }, "serverIPAddress": "[::1]", "_initiator": { "type": "parser", - "url": "http://localhost:5000/", + "url": "http://localhost:4200/", "lineNumber": 13 }, "_priority": "VeryHigh", "_resourceType": "stylesheet", - "connection": "1053024", - "pageref": "page_4" + "connection": "50822", + "pageref": "page_1" }, { - "startedDateTime": "2019-10-25T21:01:03.341Z", - "time": 97.68099999945052, + "startedDateTime": "2019-10-31T20:32:57.804Z", + "time": 93.0799999994532, "request": { "method": "GET", - "url": "http://localhost:5000/assets/vendor-85624127e93637d6efbee477f022bec1.js", - "httpVersion": "http/1.1", + "url": "http://localhost:4200/assets/vendor.js", + "httpVersion": "HTTP/1.1", "headers": [ + { + "name": "Host", + "value": "localhost:4200" + }, + { + "name": "Connection", + "value": "keep-alive" + }, + { + "name": "User-Agent", + "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36" + }, + { + "name": "Accept", + "value": "*/*" + }, + { + "name": "Sec-Fetch-Site", + "value": "same-origin" + }, { "name": "Sec-Fetch-Mode", "value": "no-cors" }, { "name": "Referer", - "value": "http://localhost:5000/" + "value": "http://localhost:4200/" }, { - "name": "User-Agent", - "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36" + "name": "Accept-Encoding", + "value": "gzip, deflate, br" + }, + { + "name": "Accept-Language", + "value": "en-US,en;q=0.9" + }, + { + "name": "Cookie", + "value": "io=wIu7CXtmPvSmDD1VAAAM; amplitude_id_5e201f0eac128f83637a72cc714578f0=eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MjM4NjI4OTk2MiwibGFzdEV2ZW50VGltZSI6MTU3MjM4ODkwNjkxNiwiZXZlbnRJZCI6MTgyLCJpZGVudGlmeUlkIjo5NCwic2VxdWVuY2VOdW1iZXIiOjI3Nn0=" } ], "queryString": [], - "cookies": [], - "headersSize": -1, + "cookies": [ + { + "name": "io", + "value": "wIu7CXtmPvSmDD1VAAAM", + "expires": null, + "httpOnly": false, + "secure": false + }, + { + "name": "amplitude_id_5e201f0eac128f83637a72cc714578f0", + "value": "eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MjM4NjI4OTk2MiwibGFzdEV2ZW50VGltZSI6MTU3MjM4ODkwNjkxNiwiZXZlbnRJZCI6MTgyLCJpZGVudGlmeUlkIjo5NCwic2VxdWVuY2VOdW1iZXIiOjI3Nn0=", + "expires": null, + "httpOnly": false, + "secure": false + } + ], + "headersSize": 714, "bodySize": 0 }, "response": { "status": 200, "statusText": "OK", - "httpVersion": "http/1.1", + "httpVersion": "HTTP/1.1", "headers": [ + { + "name": "Host", + "value": "localhost:4200" + }, { "name": "Date", - "value": "Fri, 25 Oct 2019 21:01:03 +0000" + "value": "Thu, 31 Oct 2019 20:32:57 +0000" }, { "name": "Connection", "value": "close" }, { - "name": "Host", - "value": "localhost:5000" + "name": "Content-Type", + "value": "application/javascript" }, { "name": "Content-Length", - "value": "2798111" - }, - { - "name": "Content-Type", - "value": "application/javascript" + "value": "2799137" } ], "cookies": [], "content": { - "size": 2798111, + "size": 2799137, "mimeType": "application/javascript", - "text": "d2luZG93LkVtYmVyRU5WID0geyJGRUFUVVJFUyI6e30sIkVYVEVORF9QUk9UT1RZUEVTIjp7IkRhdGUiOmZhbHNlfSwiX0pRVUVSWV9JTlRFR1JBVElPTiI6ZmFsc2V9Owp2YXIgcnVubmluZ1Rlc3RzID0gZmFsc2U7CgoKCjt2YXIgbG9hZGVyLCBkZWZpbmUsIHJlcXVpcmVNb2R1bGUsIHJlcXVpcmUsIHJlcXVpcmVqczsKCihmdW5jdGlvbiAoZ2xvYmFsKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICBmdW5jdGlvbiBkaWN0KCkgewogICAgdmFyIG9iaiA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBvYmpbJ19fJ10gPSB1bmRlZmluZWQ7CiAgICBkZWxldGUgb2JqWydfXyddOwogICAgcmV0dXJuIG9iajsKICB9CgogIC8vIFNhdmUgb2ZmIHRoZSBvcmlnaW5hbCB2YWx1ZXMgb2YgdGhlc2UgZ2xvYmFscywgc28gd2UgY2FuIHJlc3RvcmUgdGhlbSBpZiBzb21lb25lIGFza3MgdXMgdG8KICB2YXIgb2xkR2xvYmFscyA9IHsKICAgIGxvYWRlcjogbG9hZGVyLAogICAgZGVmaW5lOiBkZWZpbmUsCiAgICByZXF1aXJlTW9kdWxlOiByZXF1aXJlTW9kdWxlLAogICAgcmVxdWlyZTogcmVxdWlyZSwKICAgIHJlcXVpcmVqczogcmVxdWlyZWpzCiAgfTsKCiAgcmVxdWlyZWpzID0gcmVxdWlyZSA9IHJlcXVpcmVNb2R1bGUgPSBmdW5jdGlvbiAoaWQpIHsKICAgIHZhciBwZW5kaW5nID0gW107CiAgICB2YXIgbW9kID0gZmluZE1vZHVsZShpZCwgJyhyZXF1aXJlKScsIHBlbmRpbmcpOwoKICAgIGZvciAodmFyIGkgPSBwZW5kaW5nLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgIHBlbmRpbmdbaV0uZXhwb3J0cygpOwogICAgfQoKICAgIHJldHVybiBtb2QubW9kdWxlLmV4cG9ydHM7CiAgfTsKCiAgbG9hZGVyID0gewogICAgbm9Db25mbGljdDogZnVuY3Rpb24gKGFsaWFzZXMpIHsKICAgICAgdmFyIG9sZE5hbWUsIG5ld05hbWU7CgogICAgICBmb3IgKG9sZE5hbWUgaW4gYWxpYXNlcykgewogICAgICAgIGlmIChhbGlhc2VzLmhhc093blByb3BlcnR5KG9sZE5hbWUpKSB7CiAgICAgICAgICBpZiAob2xkR2xvYmFscy5oYXNPd25Qcm9wZXJ0eShvbGROYW1lKSkgewogICAgICAgICAgICBuZXdOYW1lID0gYWxpYXNlc1tvbGROYW1lXTsKCiAgICAgICAgICAgIGdsb2JhbFtuZXdOYW1lXSA9IGdsb2JhbFtvbGROYW1lXTsKICAgICAgICAgICAgZ2xvYmFsW29sZE5hbWVdID0gb2xkR2xvYmFsc1tvbGROYW1lXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0sCiAgICAvLyBPcHRpb24gdG8gZW5hYmxlIG9yIGRpc2FibGUgdGhlIGdlbmVyYXRpb24gb2YgZGVmYXVsdCBleHBvcnRzCiAgICBtYWtlRGVmYXVsdEV4cG9ydDogdHJ1ZQogIH07CgogIHZhciByZWdpc3RyeSA9IGRpY3QoKTsKICB2YXIgc2VlbiA9IGRpY3QoKTsKCiAgdmFyIHV1aWQgPSAwOwoKICBmdW5jdGlvbiB1bnN1cHBvcnRlZE1vZHVsZShsZW5ndGgpIHsKICAgIHRocm93IG5ldyBFcnJvcignYW4gdW5zdXBwb3J0ZWQgbW9kdWxlIHdhcyBkZWZpbmVkLCBleHBlY3RlZCBgZGVmaW5lKGlkLCBkZXBzLCBtb2R1bGUpYCBpbnN0ZWFkIGdvdDogYCcgKyBsZW5ndGggKyAnYCBhcmd1bWVudHMgdG8gZGVmaW5lYCcpOwogIH0KCiAgdmFyIGRlZmF1bHREZXBzID0gWydyZXF1aXJlJywgJ2V4cG9ydHMnLCAnbW9kdWxlJ107CgogIGZ1bmN0aW9uIE1vZHVsZShpZCwgZGVwcywgY2FsbGJhY2ssIGFsaWFzKSB7CiAgICB0aGlzLnV1aWQgPSB1dWlkKys7CiAgICB0aGlzLmlkID0gaWQ7CiAgICB0aGlzLmRlcHMgPSAhZGVwcy5sZW5ndGggJiYgY2FsbGJhY2subGVuZ3RoID8gZGVmYXVsdERlcHMgOiBkZXBzOwogICAgdGhpcy5tb2R1bGUgPSB7IGV4cG9ydHM6IHt9IH07CiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7CiAgICB0aGlzLmhhc0V4cG9ydHNBc0RlcCA9IGZhbHNlOwogICAgdGhpcy5pc0FsaWFzID0gYWxpYXM7CiAgICB0aGlzLnJlaWZpZWQgPSBuZXcgQXJyYXkoZGVwcy5sZW5ndGgpOwoKICAgIC8qCiAgICAgICBFYWNoIG1vZHVsZSBub3JtYWxseSBwYXNzZXMgdGhyb3VnaCB0aGVzZSBzdGF0ZXMsIGluIG9yZGVyOgogICAgICAgICBuZXcgICAgICAgOiBpbml0aWFsIHN0YXRlCiAgICAgICAgIHBlbmRpbmcgICA6IHRoaXMgbW9kdWxlIGlzIHNjaGVkdWxlZCB0byBiZSBleGVjdXRlZAogICAgICAgICByZWlmeWluZyAgOiB0aGlzIG1vZHVsZSdzIGRlcGVuZGVuY2llcyBhcmUgYmVpbmcgZXhlY3V0ZWQKICAgICAgICAgcmVpZmllZCAgIDogdGhpcyBtb2R1bGUncyBkZXBlbmRlbmNpZXMgZmluaXNoZWQgZXhlY3V0aW5nIHN1Y2Nlc3NmdWxseQogICAgICAgICBlcnJvcmVkICAgOiB0aGlzIG1vZHVsZSdzIGRlcGVuZGVuY2llcyBmYWlsZWQgdG8gZXhlY3V0ZQogICAgICAgICBmaW5hbGl6ZWQgOiB0aGlzIG1vZHVsZSBleGVjdXRlZCBzdWNjZXNzZnVsbHkKICAgICAqLwogICAgdGhpcy5zdGF0ZSA9ICduZXcnOwogIH0KCiAgTW9kdWxlLnByb3RvdHlwZS5tYWtlRGVmYXVsdEV4cG9ydCA9IGZ1bmN0aW9uICgpIHsKICAgIHZhciBleHBvcnRzID0gdGhpcy5tb2R1bGUuZXhwb3J0czsKICAgIGlmIChleHBvcnRzICE9PSBudWxsICYmICh0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIGV4cG9ydHMgPT09ICdmdW5jdGlvbicpICYmIGV4cG9ydHNbJ2RlZmF1bHQnXSA9PT0gdW5kZWZpbmVkICYmIE9iamVjdC5pc0V4dGVuc2libGUoZXhwb3J0cykpIHsKICAgICAgZXhwb3J0c1snZGVmYXVsdCddID0gZXhwb3J0czsKICAgIH0KICB9OwoKICBNb2R1bGUucHJvdG90eXBlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7CiAgICAvLyBpZiBmaW5hbGl6ZWQsIHRoZXJlIGlzIG5vIHdvcmsgdG8gZG8uIElmIHJlaWZ5aW5nLCB0aGVyZSBpcyBhCiAgICAvLyBjaXJjdWxhciBkZXBlbmRlbmN5IHNvIHdlIG11c3QgcmV0dXJuIG91ciAocGFydGlhbCkgZXhwb3J0cy4KICAgIGlmICh0aGlzLnN0YXRlID09PSAnZmluYWxpemVkJyB8fCB0aGlzLnN0YXRlID09PSAncmVpZnlpbmcnKSB7CiAgICAgIHJldHVybiB0aGlzLm1vZHVsZS5leHBvcnRzOwogICAgfQoKCiAgICBpZiAobG9hZGVyLndyYXBNb2R1bGVzKSB7CiAgICAgIHRoaXMuY2FsbGJhY2sgPSBsb2FkZXIud3JhcE1vZHVsZXModGhpcy5pZCwgdGhpcy5jYWxsYmFjayk7CiAgICB9CgogICAgdGhpcy5yZWlmeSgpOwoKICAgIHZhciByZXN1bHQgPSB0aGlzLmNhbGxiYWNrLmFwcGx5KHRoaXMsIHRoaXMucmVpZmllZCk7CiAgICB0aGlzLnJlaWZpZWQubGVuZ3RoID0gMDsKICAgIHRoaXMuc3RhdGUgPSAnZmluYWxpemVkJzsKCiAgICBpZiAoISh0aGlzLmhhc0V4cG9ydHNBc0RlcCAmJiByZXN1bHQgPT09IHVuZGVmaW5lZCkpIHsKICAgICAgdGhpcy5tb2R1bGUuZXhwb3J0cyA9IHJlc3VsdDsKICAgIH0KICAgIGlmIChsb2FkZXIubWFrZURlZmF1bHRFeHBvcnQpIHsKICAgICAgdGhpcy5tYWtlRGVmYXVsdEV4cG9ydCgpOwogICAgfQogICAgcmV0dXJuIHRoaXMubW9kdWxlLmV4cG9ydHM7CiAgfTsKCiAgTW9kdWxlLnByb3RvdHlwZS51bnNlZSA9IGZ1bmN0aW9uICgpIHsKICAgIHRoaXMuc3RhdGUgPSAnbmV3JzsKICAgIHRoaXMubW9kdWxlID0geyBleHBvcnRzOiB7fSB9OwogIH07CgogIE1vZHVsZS5wcm90b3R5cGUucmVpZnkgPSBmdW5jdGlvbiAoKSB7CiAgICBpZiAodGhpcy5zdGF0ZSA9PT0gJ3JlaWZpZWQnKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuc3RhdGUgPSAncmVpZnlpbmcnOwogICAgdHJ5IHsKICAgICAgdGhpcy5yZWlmaWVkID0gdGhpcy5fcmVpZnkoKTsKICAgICAgdGhpcy5zdGF0ZSA9ICdyZWlmaWVkJzsKICAgIH0gZmluYWxseSB7CiAgICAgIGlmICh0aGlzLnN0YXRlID09PSAncmVpZnlpbmcnKSB7CiAgICAgICAgdGhpcy5zdGF0ZSA9ICdlcnJvcmVkJzsKICAgICAgfQogICAgfQogIH07CgogIE1vZHVsZS5wcm90b3R5cGUuX3JlaWZ5ID0gZnVuY3Rpb24gKCkgewogICAgdmFyIHJlaWZpZWQgPSB0aGlzLnJlaWZpZWQuc2xpY2UoKTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVpZmllZC5sZW5ndGg7IGkrKykgewogICAgICB2YXIgbW9kID0gcmVpZmllZFtpXTsKICAgICAgcmVpZmllZFtpXSA9IG1vZC5leHBvcnRzID8gbW9kLmV4cG9ydHMgOiBtb2QubW9kdWxlLmV4cG9ydHMoKTsKICAgIH0KICAgIHJldHVybiByZWlmaWVkOwogIH07CgogIE1vZHVsZS5wcm90b3R5cGUuZmluZERlcHMgPSBmdW5jdGlvbiAocGVuZGluZykgewogICAgaWYgKHRoaXMuc3RhdGUgIT09ICduZXcnKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB0aGlzLnN0YXRlID0gJ3BlbmRpbmcnOwoKICAgIHZhciBkZXBzID0gdGhpcy5kZXBzOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVwcy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgZGVwID0gZGVwc1tpXTsKICAgICAgdmFyIGVudHJ5ID0gdGhpcy5yZWlmaWVkW2ldID0geyBleHBvcnRzOiB1bmRlZmluZWQsIG1vZHVsZTogdW5kZWZpbmVkIH07CiAgICAgIGlmIChkZXAgPT09ICdleHBvcnRzJykgewogICAgICAgIHRoaXMuaGFzRXhwb3J0c0FzRGVwID0gdHJ1ZTsKICAgICAgICBlbnRyeS5leHBvcnRzID0gdGhpcy5tb2R1bGUuZXhwb3J0czsKICAgICAgfSBlbHNlIGlmIChkZXAgPT09ICdyZXF1aXJlJykgewogICAgICAgIGVudHJ5LmV4cG9ydHMgPSB0aGlzLm1ha2VSZXF1aXJlKCk7CiAgICAgIH0gZWxzZSBpZiAoZGVwID09PSAnbW9kdWxlJykgewogICAgICAgIGVudHJ5LmV4cG9ydHMgPSB0aGlzLm1vZHVsZTsKICAgICAgfSBlbHNlIHsKICAgICAgICBlbnRyeS5tb2R1bGUgPSBmaW5kTW9kdWxlKHJlc29sdmUoZGVwLCB0aGlzLmlkKSwgdGhpcy5pZCwgcGVuZGluZyk7CiAgICAgIH0KICAgIH0KICB9OwoKICBNb2R1bGUucHJvdG90eXBlLm1ha2VSZXF1aXJlID0gZnVuY3Rpb24gKCkgewogICAgdmFyIGlkID0gdGhpcy5pZDsKICAgIHZhciByID0gZnVuY3Rpb24gKGRlcCkgewogICAgICByZXR1cm4gcmVxdWlyZShyZXNvbHZlKGRlcCwgaWQpKTsKICAgIH07CiAgICByWydkZWZhdWx0J10gPSByOwogICAgci5tb2R1bGVJZCA9IGlkOwogICAgci5oYXMgPSBmdW5jdGlvbiAoZGVwKSB7CiAgICAgIHJldHVybiBoYXMocmVzb2x2ZShkZXAsIGlkKSk7CiAgICB9OwogICAgcmV0dXJuIHI7CiAgfTsKCiAgZGVmaW5lID0gZnVuY3Rpb24gKGlkLCBkZXBzLCBjYWxsYmFjaykgewogICAgdmFyIG1vZHVsZSA9IHJlZ2lzdHJ5W2lkXTsKCiAgICAvLyBJZiBhIG1vZHVsZSBmb3IgdGhpcyBpZCBoYXMgYWxyZWFkeSBiZWVuIGRlZmluZWQgYW5kIGlzIGluIGFueSBzdGF0ZQogICAgLy8gb3RoZXIgdGhhbiBgbmV3YCAobWVhbmluZyBpdCBoYXMgYmVlbiBvciBpcyBjdXJyZW50bHkgYmVpbmcgcmVxdWlyZWQpLAogICAgLy8gdGhlbiB3ZSByZXR1cm4gZWFybHkgdG8gYXZvaWQgcmVkZWZpbml0aW9uLgogICAgaWYgKG1vZHVsZSAmJiBtb2R1bGUuc3RhdGUgIT09ICduZXcnKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHsKICAgICAgdW5zdXBwb3J0ZWRNb2R1bGUoYXJndW1lbnRzLmxlbmd0aCk7CiAgICB9CgogICAgaWYgKCFBcnJheS5pc0FycmF5KGRlcHMpKSB7CiAgICAgIGNhbGxiYWNrID0gZGVwczsKICAgICAgZGVwcyA9IFtdOwogICAgfQoKICAgIGlmIChjYWxsYmFjayBpbnN0YW5jZW9mIEFsaWFzKSB7CiAgICAgIHJlZ2lzdHJ5W2lkXSA9IG5ldyBNb2R1bGUoY2FsbGJhY2suaWQsIGRlcHMsIGNhbGxiYWNrLCB0cnVlKTsKICAgIH0gZWxzZSB7CiAgICAgIHJlZ2lzdHJ5W2lkXSA9IG5ldyBNb2R1bGUoaWQsIGRlcHMsIGNhbGxiYWNrLCBmYWxzZSk7CiAgICB9CiAgfTsKCiAgZGVmaW5lLmV4cG9ydHMgPSBmdW5jdGlvbiAobmFtZSwgZGVmYXVsdEV4cG9ydCkgewogICAgdmFyIG1vZHVsZSA9IHJlZ2lzdHJ5W25hbWVdOwoKICAgIC8vIElmIGEgbW9kdWxlIGZvciB0aGlzIG5hbWUgaGFzIGFscmVhZHkgYmVlbiBkZWZpbmVkIGFuZCBpcyBpbiBhbnkgc3RhdGUKICAgIC8vIG90aGVyIHRoYW4gYG5ld2AgKG1lYW5pbmcgaXQgaGFzIGJlZW4gb3IgaXMgY3VycmVudGx5IGJlaW5nIHJlcXVpcmVkKSwKICAgIC8vIHRoZW4gd2UgcmV0dXJuIGVhcmx5IHRvIGF2b2lkIHJlZGVmaW5pdGlvbi4KICAgIGlmIChtb2R1bGUgJiYgbW9kdWxlLnN0YXRlICE9PSAnbmV3JykgewogICAgICByZXR1cm47CiAgICB9CgogICAgbW9kdWxlID0gbmV3IE1vZHVsZShuYW1lLCBbXSwgbm9vcCwgbnVsbCk7CiAgICBtb2R1bGUubW9kdWxlLmV4cG9ydHMgPSBkZWZhdWx0RXhwb3J0OwogICAgbW9kdWxlLnN0YXRlID0gJ2ZpbmFsaXplZCc7CiAgICByZWdpc3RyeVtuYW1lXSA9IG1vZHVsZTsKCiAgICByZXR1cm4gbW9kdWxlOwogIH07CgogIGZ1bmN0aW9uIG5vb3AoKSB7fQogIC8vIHdlIGRvbid0IHN1cHBvcnQgYWxsIG9mIEFNRAogIC8vIGRlZmluZS5hbWQgPSB7fTsKCiAgZnVuY3Rpb24gQWxpYXMoaWQpIHsKICAgIHRoaXMuaWQgPSBpZDsKICB9CgogIGRlZmluZS5hbGlhcyA9IGZ1bmN0aW9uIChpZCwgdGFyZ2V0KSB7CiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgewogICAgICByZXR1cm4gZGVmaW5lKHRhcmdldCwgbmV3IEFsaWFzKGlkKSk7CiAgICB9CgogICAgcmV0dXJuIG5ldyBBbGlhcyhpZCk7CiAgfTsKCiAgZnVuY3Rpb24gbWlzc2luZ01vZHVsZShpZCwgcmVmZXJyZXIpIHsKICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGZpbmQgbW9kdWxlIGAnICsgaWQgKyAnYCBpbXBvcnRlZCBmcm9tIGAnICsgcmVmZXJyZXIgKyAnYCcpOwogIH0KCiAgZnVuY3Rpb24gZmluZE1vZHVsZShpZCwgcmVmZXJyZXIsIHBlbmRpbmcpIHsKICAgIHZhciBtb2QgPSByZWdpc3RyeVtpZF0gfHwgcmVnaXN0cnlbaWQgKyAnL2luZGV4J107CgogICAgd2hpbGUgKG1vZCAmJiBtb2QuaXNBbGlhcykgewogICAgICBtb2QgPSByZWdpc3RyeVttb2QuaWRdIHx8IHJlZ2lzdHJ5W21vZC5pZCArICcvaW5kZXgnXTsKICAgIH0KCiAgICBpZiAoIW1vZCkgewogICAgICBtaXNzaW5nTW9kdWxlKGlkLCByZWZlcnJlcik7CiAgICB9CgogICAgaWYgKHBlbmRpbmcgJiYgbW9kLnN0YXRlICE9PSAncGVuZGluZycgJiYgbW9kLnN0YXRlICE9PSAnZmluYWxpemVkJykgewogICAgICBtb2QuZmluZERlcHMocGVuZGluZyk7CiAgICAgIHBlbmRpbmcucHVzaChtb2QpOwogICAgfQogICAgcmV0dXJuIG1vZDsKICB9CgogIGZ1bmN0aW9uIHJlc29sdmUoY2hpbGQsIGlkKSB7CiAgICBpZiAoY2hpbGQuY2hhckF0KDApICE9PSAnLicpIHsKICAgICAgcmV0dXJuIGNoaWxkOwogICAgfQoKCiAgICB2YXIgcGFydHMgPSBjaGlsZC5zcGxpdCgnLycpOwogICAgdmFyIG5hbWVQYXJ0cyA9IGlkLnNwbGl0KCcvJyk7CiAgICB2YXIgcGFyZW50QmFzZSA9IG5hbWVQYXJ0cy5zbGljZSgwLCAtMSk7CgogICAgZm9yICh2YXIgaSA9IDAsIGwgPSBwYXJ0cy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgdmFyIHBhcnQgPSBwYXJ0c1tpXTsKCiAgICAgIGlmIChwYXJ0ID09PSAnLi4nKSB7CiAgICAgICAgaWYgKHBhcmVudEJhc2UubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBhY2Nlc3MgcGFyZW50IG1vZHVsZSBvZiByb290Jyk7CiAgICAgICAgfQogICAgICAgIHBhcmVudEJhc2UucG9wKCk7CiAgICAgIH0gZWxzZSBpZiAocGFydCA9PT0gJy4nKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcGFyZW50QmFzZS5wdXNoKHBhcnQpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHBhcmVudEJhc2Uuam9pbignLycpOwogIH0KCiAgZnVuY3Rpb24gaGFzKGlkKSB7CiAgICByZXR1cm4gISEocmVnaXN0cnlbaWRdIHx8IHJlZ2lzdHJ5W2lkICsgJy9pbmRleCddKTsKICB9CgogIHJlcXVpcmVqcy5lbnRyaWVzID0gcmVxdWlyZWpzLl9lYWtfc2VlbiA9IHJlZ2lzdHJ5OwogIHJlcXVpcmVqcy5oYXMgPSBoYXM7CiAgcmVxdWlyZWpzLnVuc2VlID0gZnVuY3Rpb24gKGlkKSB7CiAgICBmaW5kTW9kdWxlKGlkLCAnKHVuc2VlKScsIGZhbHNlKS51bnNlZSgpOwogIH07CgogIHJlcXVpcmVqcy5jbGVhciA9IGZ1bmN0aW9uICgpIHsKICAgIHJlcXVpcmVqcy5lbnRyaWVzID0gcmVxdWlyZWpzLl9lYWtfc2VlbiA9IHJlZ2lzdHJ5ID0gZGljdCgpOwogICAgc2VlbiA9IGRpY3QoKTsKICB9OwoKICAvLyBUaGlzIGNvZGUgcHJpbWVzIHRoZSBKUyBlbmdpbmUgZm9yIGdvb2QgcGVyZm9ybWFuY2UgYnkgd2FybWluZyB0aGUKICAvLyBKSVQgY29tcGlsZXIgZm9yIHRoZXNlIGZ1bmN0aW9ucy4KICBkZWZpbmUoJ2ZvbycsIGZ1bmN0aW9uICgpIHt9KTsKICBkZWZpbmUoJ2Zvby9iYXInLCBbXSwgZnVuY3Rpb24gKCkge30pOwogIGRlZmluZSgnZm9vL2FzZGYnLCBbJ21vZHVsZScsICdleHBvcnRzJywgJ3JlcXVpcmUnXSwgZnVuY3Rpb24gKG1vZHVsZSwgZXhwb3J0cywgcmVxdWlyZSkgewogICAgaWYgKHJlcXVpcmUuaGFzKCdmb28vYmFyJykpIHsKICAgICAgcmVxdWlyZSgnZm9vL2JhcicpOwogICAgfQogIH0pOwogIGRlZmluZSgnZm9vL2JheicsIFtdLCBkZWZpbmUuYWxpYXMoJ2ZvbycpKTsKICBkZWZpbmUoJ2Zvby9xdXonLCBkZWZpbmUuYWxpYXMoJ2ZvbycpKTsKICBkZWZpbmUuYWxpYXMoJ2ZvbycsICdmb28vcXV4Jyk7CiAgZGVmaW5lKCdmb28vYmFyJywgWydmb28nLCAnLi9xdXonLCAnLi9iYXonLCAnLi9hc2RmJywgJy4vYmFyJywgJy4uL2ZvbyddLCBmdW5jdGlvbiAoKSB7fSk7CiAgZGVmaW5lKCdmb28vbWFpbicsIFsnZm9vL2JhciddLCBmdW5jdGlvbiAoKSB7fSk7CiAgZGVmaW5lLmV4cG9ydHMoJ2Zvby9leHBvcnRzJywge30pOwoKICByZXF1aXJlKCdmb28vZXhwb3J0cycpOwogIHJlcXVpcmUoJ2Zvby9tYWluJyk7CiAgcmVxdWlyZS51bnNlZSgnZm9vL2JhcicpOwoKICByZXF1aXJlanMuY2xlYXIoKTsKCiAgaWYgKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cykgewogICAgbW9kdWxlLmV4cG9ydHMgPSB7IHJlcXVpcmU6IHJlcXVpcmUsIGRlZmluZTogZGVmaW5lIH07CiAgfQp9KSh0aGlzKTsKOy8qKgogKiBDb3B5cmlnaHQgKGMpIDIwMTQsIEZhY2Vib29rLCBJbmMuCiAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiAqCiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIEJTRC1zdHlsZSBsaWNlbnNlIGZvdW5kIGluIHRoZQogKiBodHRwczovL3Jhdy5naXRodWIuY29tL2ZhY2Vib29rL3JlZ2VuZXJhdG9yL21hc3Rlci9MSUNFTlNFIGZpbGUuIEFuCiAqIGFkZGl0aW9uYWwgZ3JhbnQgb2YgcGF0ZW50IHJpZ2h0cyBjYW4gYmUgZm91bmQgaW4gdGhlIFBBVEVOVFMgZmlsZSBpbgogKiB0aGUgc2FtZSBkaXJlY3RvcnkuCiAqLwoKIShmdW5jdGlvbihnbG9iYWwpIHsKICAidXNlIHN0cmljdCI7CgogIHZhciBoYXNPd24gPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5OwogIHZhciB1bmRlZmluZWQ7IC8vIE1vcmUgY29tcHJlc3NpYmxlIHRoYW4gdm9pZCAwLgogIHZhciAkU3ltYm9sID0gdHlwZW9mIFN5bWJvbCA9PT0gImZ1bmN0aW9uIiA/IFN5bWJvbCA6IHt9OwogIHZhciBpdGVyYXRvclN5bWJvbCA9ICRTeW1ib2wuaXRlcmF0b3IgfHwgIkBAaXRlcmF0b3IiOwogIHZhciB0b1N0cmluZ1RhZ1N5bWJvbCA9ICRTeW1ib2wudG9TdHJpbmdUYWcgfHwgIkBAdG9TdHJpbmdUYWciOwoKICB2YXIgaW5Nb2R1bGUgPSB0eXBlb2YgbW9kdWxlID09PSAib2JqZWN0IjsKICB2YXIgcnVudGltZSA9IGdsb2JhbC5yZWdlbmVyYXRvclJ1bnRpbWU7CiAgaWYgKHJ1bnRpbWUpIHsKICAgIGlmIChpbk1vZHVsZSkgewogICAgICAvLyBJZiByZWdlbmVyYXRvclJ1bnRpbWUgaXMgZGVmaW5lZCBnbG9iYWxseSBhbmQgd2UncmUgaW4gYSBtb2R1bGUsCiAgICAgIC8vIG1ha2UgdGhlIGV4cG9ydHMgb2JqZWN0IGlkZW50aWNhbCB0byByZWdlbmVyYXRvclJ1bnRpbWUuCiAgICAgIG1vZHVsZS5leHBvcnRzID0gcnVudGltZTsKICAgIH0KICAgIC8vIERvbid0IGJvdGhlciBldmFsdWF0aW5nIHRoZSByZXN0IG9mIHRoaXMgZmlsZSBpZiB0aGUgcnVudGltZSB3YXMKICAgIC8vIGFscmVhZHkgZGVmaW5lZCBnbG9iYWxseS4KICAgIHJldHVybjsKICB9CgogIC8vIERlZmluZSB0aGUgcnVudGltZSBnbG9iYWxseSAoYXMgZXhwZWN0ZWQgYnkgZ2VuZXJhdGVkIGNvZGUpIGFzIGVpdGhlcgogIC8vIG1vZHVsZS5leHBvcnRzIChpZiB3ZSdyZSBpbiBhIG1vZHVsZSkgb3IgYSBuZXcsIGVtcHR5IG9iamVjdC4KICBydW50aW1lID0gZ2xvYmFsLnJlZ2VuZXJhdG9yUnVudGltZSA9IGluTW9kdWxlID8gbW9kdWxlLmV4cG9ydHMgOiB7fTsKCiAgZnVuY3Rpb24gd3JhcChpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCkgewogICAgLy8gSWYgb3V0ZXJGbiBwcm92aWRlZCBhbmQgb3V0ZXJGbi5wcm90b3R5cGUgaXMgYSBHZW5lcmF0b3IsIHRoZW4gb3V0ZXJGbi5wcm90b3R5cGUgaW5zdGFuY2VvZiBHZW5lcmF0b3IuCiAgICB2YXIgcHJvdG9HZW5lcmF0b3IgPSBvdXRlckZuICYmIG91dGVyRm4ucHJvdG90eXBlIGluc3RhbmNlb2YgR2VuZXJhdG9yID8gb3V0ZXJGbiA6IEdlbmVyYXRvcjsKICAgIHZhciBnZW5lcmF0b3IgPSBPYmplY3QuY3JlYXRlKHByb3RvR2VuZXJhdG9yLnByb3RvdHlwZSk7CiAgICB2YXIgY29udGV4dCA9IG5ldyBDb250ZXh0KHRyeUxvY3NMaXN0IHx8IFtdKTsKCiAgICAvLyBUaGUgLl9pbnZva2UgbWV0aG9kIHVuaWZpZXMgdGhlIGltcGxlbWVudGF0aW9ucyBvZiB0aGUgLm5leHQsCiAgICAvLyAudGhyb3csIGFuZCAucmV0dXJuIG1ldGhvZHMuCiAgICBnZW5lcmF0b3IuX2ludm9rZSA9IG1ha2VJbnZva2VNZXRob2QoaW5uZXJGbiwgc2VsZiwgY29udGV4dCk7CgogICAgcmV0dXJuIGdlbmVyYXRvcjsKICB9CiAgcnVudGltZS53cmFwID0gd3JhcDsKCiAgLy8gVHJ5L2NhdGNoIGhlbHBlciB0byBtaW5pbWl6ZSBkZW9wdGltaXphdGlvbnMuIFJldHVybnMgYSBjb21wbGV0aW9uCiAgLy8gcmVjb3JkIGxpa2UgY29udGV4dC50cnlFbnRyaWVzW2ldLmNvbXBsZXRpb24uIFRoaXMgaW50ZXJmYWNlIGNvdWxkCiAgLy8gaGF2ZSBiZWVuIChhbmQgd2FzIHByZXZpb3VzbHkpIGRlc2lnbmVkIHRvIHRha2UgYSBjbG9zdXJlIHRvIGJlCiAgLy8gaW52b2tlZCB3aXRob3V0IGFyZ3VtZW50cywgYnV0IGluIGFsbCB0aGUgY2FzZXMgd2UgY2FyZSBhYm91dCB3ZQogIC8vIGFscmVhZHkgaGF2ZSBhbiBleGlzdGluZyBtZXRob2Qgd2Ugd2FudCB0byBjYWxsLCBzbyB0aGVyZSdzIG5vIG5lZWQKICAvLyB0byBjcmVhdGUgYSBuZXcgZnVuY3Rpb24gb2JqZWN0LiBXZSBjYW4gZXZlbiBnZXQgYXdheSB3aXRoIGFzc3VtaW5nCiAgLy8gdGhlIG1ldGhvZCB0YWtlcyBleGFjdGx5IG9uZSBhcmd1bWVudCwgc2luY2UgdGhhdCBoYXBwZW5zIHRvIGJlIHRydWUKICAvLyBpbiBldmVyeSBjYXNlLCBzbyB3ZSBkb24ndCBoYXZlIHRvIHRvdWNoIHRoZSBhcmd1bWVudHMgb2JqZWN0LiBUaGUKICAvLyBvbmx5IGFkZGl0aW9uYWwgYWxsb2NhdGlvbiByZXF1aXJlZCBpcyB0aGUgY29tcGxldGlvbiByZWNvcmQsIHdoaWNoCiAgLy8gaGFzIGEgc3RhYmxlIHNoYXBlIGFuZCBzbyBob3BlZnVsbHkgc2hvdWxkIGJlIGNoZWFwIHRvIGFsbG9jYXRlLgogIGZ1bmN0aW9uIHRyeUNhdGNoKGZuLCBvYmosIGFyZykgewogICAgdHJ5IHsKICAgICAgcmV0dXJuIHsgdHlwZTogIm5vcm1hbCIsIGFyZzogZm4uY2FsbChvYmosIGFyZykgfTsKICAgIH0gY2F0Y2ggKGVycikgewogICAgICByZXR1cm4geyB0eXBlOiAidGhyb3ciLCBhcmc6IGVyciB9OwogICAgfQogIH0KCiAgdmFyIEdlblN0YXRlU3VzcGVuZGVkU3RhcnQgPSAic3VzcGVuZGVkU3RhcnQiOwogIHZhciBHZW5TdGF0ZVN1c3BlbmRlZFlpZWxkID0gInN1c3BlbmRlZFlpZWxkIjsKICB2YXIgR2VuU3RhdGVFeGVjdXRpbmcgPSAiZXhlY3V0aW5nIjsKICB2YXIgR2VuU3RhdGVDb21wbGV0ZWQgPSAiY29tcGxldGVkIjsKCiAgLy8gUmV0dXJuaW5nIHRoaXMgb2JqZWN0IGZyb20gdGhlIGlubmVyRm4gaGFzIHRoZSBzYW1lIGVmZmVjdCBhcwogIC8vIGJyZWFraW5nIG91dCBvZiB0aGUgZGlzcGF0Y2ggc3dpdGNoIHN0YXRlbWVudC4KICB2YXIgQ29udGludWVTZW50aW5lbCA9IHt9OwoKICAvLyBEdW1teSBjb25zdHJ1Y3RvciBmdW5jdGlvbnMgdGhhdCB3ZSB1c2UgYXMgdGhlIC5jb25zdHJ1Y3RvciBhbmQKICAvLyAuY29uc3RydWN0b3IucHJvdG90eXBlIHByb3BlcnRpZXMgZm9yIGZ1bmN0aW9ucyB0aGF0IHJldHVybiBHZW5lcmF0b3IKICAvLyBvYmplY3RzLiBGb3IgZnVsbCBzcGVjIGNvbXBsaWFuY2UsIHlvdSBtYXkgd2lzaCB0byBjb25maWd1cmUgeW91cgogIC8vIG1pbmlmaWVyIG5vdCB0byBtYW5nbGUgdGhlIG5hbWVzIG9mIHRoZXNlIHR3byBmdW5jdGlvbnMuCiAgZnVuY3Rpb24gR2VuZXJhdG9yKCkge30KICBmdW5jdGlvbiBHZW5lcmF0b3JGdW5jdGlvbigpIHt9CiAgZnVuY3Rpb24gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUoKSB7fQoKICB2YXIgR3AgPSBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZS5wcm90b3R5cGUgPSBHZW5lcmF0b3IucHJvdG90eXBlOwogIEdlbmVyYXRvckZ1bmN0aW9uLnByb3RvdHlwZSA9IEdwLmNvbnN0cnVjdG9yID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGU7CiAgR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUuY29uc3RydWN0b3IgPSBHZW5lcmF0b3JGdW5jdGlvbjsKICBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZVt0b1N0cmluZ1RhZ1N5bWJvbF0gPSBHZW5lcmF0b3JGdW5jdGlvbi5kaXNwbGF5TmFtZSA9ICJHZW5lcmF0b3JGdW5jdGlvbiI7CgogIC8vIEhlbHBlciBmb3IgZGVmaW5pbmcgdGhlIC5uZXh0LCAudGhyb3csIGFuZCAucmV0dXJuIG1ldGhvZHMgb2YgdGhlCiAgLy8gSXRlcmF0b3IgaW50ZXJmYWNlIGluIHRlcm1zIG9mIGEgc2luZ2xlIC5faW52b2tlIG1ldGhvZC4KICBmdW5jdGlvbiBkZWZpbmVJdGVyYXRvck1ldGhvZHMocHJvdG90eXBlKSB7CiAgICBbIm5leHQiLCAidGhyb3ciLCAicmV0dXJuIl0uZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHsKICAgICAgcHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbihhcmcpIHsKICAgICAgICByZXR1cm4gdGhpcy5faW52b2tlKG1ldGhvZCwgYXJnKTsKICAgICAgfTsKICAgIH0pOwogIH0KCiAgcnVudGltZS5pc0dlbmVyYXRvckZ1bmN0aW9uID0gZnVuY3Rpb24oZ2VuRnVuKSB7CiAgICB2YXIgY3RvciA9IHR5cGVvZiBnZW5GdW4gPT09ICJmdW5jdGlvbiIgJiYgZ2VuRnVuLmNvbnN0cnVjdG9yOwogICAgcmV0dXJuIGN0b3IKICAgICAgPyBjdG9yID09PSBHZW5lcmF0b3JGdW5jdGlvbiB8fAogICAgICAgIC8vIEZvciB0aGUgbmF0aXZlIEdlbmVyYXRvckZ1bmN0aW9uIGNvbnN0cnVjdG9yLCB0aGUgYmVzdCB3ZSBjYW4KICAgICAgICAvLyBkbyBpcyB0byBjaGVjayBpdHMgLm5hbWUgcHJvcGVydHkuCiAgICAgICAgKGN0b3IuZGlzcGxheU5hbWUgfHwgY3Rvci5uYW1lKSA9PT0gIkdlbmVyYXRvckZ1bmN0aW9uIgogICAgICA6IGZhbHNlOwogIH07CgogIHJ1bnRpbWUubWFyayA9IGZ1bmN0aW9uKGdlbkZ1bikgewogICAgaWYgKE9iamVjdC5zZXRQcm90b3R5cGVPZikgewogICAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YoZ2VuRnVuLCBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSk7CiAgICB9IGVsc2UgewogICAgICBnZW5GdW4uX19wcm90b19fID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGU7CiAgICAgIGlmICghKHRvU3RyaW5nVGFnU3ltYm9sIGluIGdlbkZ1bikpIHsKICAgICAgICBnZW5GdW5bdG9TdHJpbmdUYWdTeW1ib2xdID0gIkdlbmVyYXRvckZ1bmN0aW9uIjsKICAgICAgfQogICAgfQogICAgZ2VuRnVuLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoR3ApOwogICAgcmV0dXJuIGdlbkZ1bjsKICB9OwoKICAvLyBXaXRoaW4gdGhlIGJvZHkgb2YgYW55IGFzeW5jIGZ1bmN0aW9uLCBgYXdhaXQgeGAgaXMgdHJhbnNmb3JtZWQgdG8KICAvLyBgeWllbGQgcmVnZW5lcmF0b3JSdW50aW1lLmF3cmFwKHgpYCwgc28gdGhhdCB0aGUgcnVudGltZSBjYW4gdGVzdAogIC8vIGB2YWx1ZSBpbnN0YW5jZW9mIEF3YWl0QXJndW1lbnRgIHRvIGRldGVybWluZSBpZiB0aGUgeWllbGRlZCB2YWx1ZSBpcwogIC8vIG1lYW50IHRvIGJlIGF3YWl0ZWQuIFNvbWUgbWF5IGNvbnNpZGVyIHRoZSBuYW1lIG9mIHRoaXMgbWV0aG9kIHRvbwogIC8vIGN1dGVzeSwgYnV0IHRoZXkgYXJlIGN1cm11ZGdlb25zLgogIHJ1bnRpbWUuYXdyYXAgPSBmdW5jdGlvbihhcmcpIHsKICAgIHJldHVybiBuZXcgQXdhaXRBcmd1bWVudChhcmcpOwogIH07CgogIGZ1bmN0aW9uIEF3YWl0QXJndW1lbnQoYXJnKSB7CiAgICB0aGlzLmFyZyA9IGFyZzsKICB9CgogIGZ1bmN0aW9uIEFzeW5jSXRlcmF0b3IoZ2VuZXJhdG9yKSB7CiAgICBmdW5jdGlvbiBpbnZva2UobWV0aG9kLCBhcmcsIHJlc29sdmUsIHJlamVjdCkgewogICAgICB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2goZ2VuZXJhdG9yW21ldGhvZF0sIGdlbmVyYXRvciwgYXJnKTsKICAgICAgaWYgKHJlY29yZC50eXBlID09PSAidGhyb3ciKSB7CiAgICAgICAgcmVqZWN0KHJlY29yZC5hcmcpOwogICAgICB9IGVsc2UgewogICAgICAgIHZhciByZXN1bHQgPSByZWNvcmQuYXJnOwogICAgICAgIHZhciB2YWx1ZSA9IHJlc3VsdC52YWx1ZTsKICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBBd2FpdEFyZ3VtZW50KSB7CiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHZhbHVlLmFyZykudGhlbihmdW5jdGlvbih2YWx1ZSkgewogICAgICAgICAgICBpbnZva2UoIm5leHQiLCB2YWx1ZSwgcmVzb2x2ZSwgcmVqZWN0KTsKICAgICAgICAgIH0sIGZ1bmN0aW9uKGVycikgewogICAgICAgICAgICBpbnZva2UoInRocm93IiwgZXJyLCByZXNvbHZlLCByZWplY3QpOwogICAgICAgICAgfSk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHZhbHVlKS50aGVuKGZ1bmN0aW9uKHVud3JhcHBlZCkgewogICAgICAgICAgLy8gV2hlbiBhIHlpZWxkZWQgUHJvbWlzZSBpcyByZXNvbHZlZCwgaXRzIGZpbmFsIHZhbHVlIGJlY29tZXMKICAgICAgICAgIC8vIHRoZSAudmFsdWUgb2YgdGhlIFByb21pc2U8e3ZhbHVlLGRvbmV9PiByZXN1bHQgZm9yIHRoZQogICAgICAgICAgLy8gY3VycmVudCBpdGVyYXRpb24uIElmIHRoZSBQcm9taXNlIGlzIHJlamVjdGVkLCBob3dldmVyLCB0aGUKICAgICAgICAgIC8vIHJlc3VsdCBmb3IgdGhpcyBpdGVyYXRpb24gd2lsbCBiZSByZWplY3RlZCB3aXRoIHRoZSBzYW1lCiAgICAgICAgICAvLyByZWFzb24uIE5vdGUgdGhhdCByZWplY3Rpb25zIG9mIHlpZWxkZWQgUHJvbWlzZXMgYXJlIG5vdAogICAgICAgICAgLy8gdGhyb3duIGJhY2sgaW50byB0aGUgZ2VuZXJhdG9yIGZ1bmN0aW9uLCBhcyBpcyB0aGUgY2FzZQogICAgICAgICAgLy8gd2hlbiBhbiBhd2FpdGVkIFByb21pc2UgaXMgcmVqZWN0ZWQuIFRoaXMgZGlmZmVyZW5jZSBpbgogICAgICAgICAgLy8gYmVoYXZpb3IgYmV0d2VlbiB5aWVsZCBhbmQgYXdhaXQgaXMgaW1wb3J0YW50LCBiZWNhdXNlIGl0CiAgICAgICAgICAvLyBhbGxvd3MgdGhlIGNvbnN1bWVyIHRvIGRlY2lkZSB3aGF0IHRvIGRvIHdpdGggdGhlIHlpZWxkZWQKICAgICAgICAgIC8vIHJlamVjdGlvbiAoc3dhbGxvdyBpdCBhbmQgY29udGludWUsIG1hbnVhbGx5IC50aHJvdyBpdCBiYWNrCiAgICAgICAgICAvLyBpbnRvIHRoZSBnZW5lcmF0b3IsIGFiYW5kb24gaXRlcmF0aW9uLCB3aGF0ZXZlcikuIFdpdGgKICAgICAgICAgIC8vIGF3YWl0LCBieSBjb250cmFzdCwgdGhlcmUgaXMgbm8gb3Bwb3J0dW5pdHkgdG8gZXhhbWluZSB0aGUKICAgICAgICAgIC8vIHJlamVjdGlvbiByZWFzb24gb3V0c2lkZSB0aGUgZ2VuZXJhdG9yIGZ1bmN0aW9uLCBzbyB0aGUKICAgICAgICAgIC8vIG9ubHkgb3B0aW9uIGlzIHRvIHRocm93IGl0IGZyb20gdGhlIGF3YWl0IGV4cHJlc3Npb24sIGFuZAogICAgICAgICAgLy8gbGV0IHRoZSBnZW5lcmF0b3IgZnVuY3Rpb24gaGFuZGxlIHRoZSBleGNlcHRpb24uCiAgICAgICAgICByZXN1bHQudmFsdWUgPSB1bndyYXBwZWQ7CiAgICAgICAgICByZXNvbHZlKHJlc3VsdCk7CiAgICAgICAgfSwgcmVqZWN0KTsKICAgICAgfQogICAgfQoKICAgIGlmICh0eXBlb2YgcHJvY2VzcyA9PT0gIm9iamVjdCIgJiYgcHJvY2Vzcy5kb21haW4pIHsKICAgICAgaW52b2tlID0gcHJvY2Vzcy5kb21haW4uYmluZChpbnZva2UpOwogICAgfQoKICAgIHZhciBwcmV2aW91c1Byb21pc2U7CgogICAgZnVuY3Rpb24gZW5xdWV1ZShtZXRob2QsIGFyZykgewogICAgICBmdW5jdGlvbiBjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZygpIHsKICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7CiAgICAgICAgICBpbnZva2UobWV0aG9kLCBhcmcsIHJlc29sdmUsIHJlamVjdCk7CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBwcmV2aW91c1Byb21pc2UgPQogICAgICAgIC8vIElmIGVucXVldWUgaGFzIGJlZW4gY2FsbGVkIGJlZm9yZSwgdGhlbiB3ZSB3YW50IHRvIHdhaXQgdW50aWwKICAgICAgICAvLyBhbGwgcHJldmlvdXMgUHJvbWlzZXMgaGF2ZSBiZWVuIHJlc29sdmVkIGJlZm9yZSBjYWxsaW5nIGludm9rZSwKICAgICAgICAvLyBzbyB0aGF0IHJlc3VsdHMgYXJlIGFsd2F5cyBkZWxpdmVyZWQgaW4gdGhlIGNvcnJlY3Qgb3JkZXIuIElmCiAgICAgICAgLy8gZW5xdWV1ZSBoYXMgbm90IGJlZW4gY2FsbGVkIGJlZm9yZSwgdGhlbiBpdCBpcyBpbXBvcnRhbnQgdG8KICAgICAgICAvLyBjYWxsIGludm9rZSBpbW1lZGlhdGVseSwgd2l0aG91dCB3YWl0aW5nIG9uIGEgY2FsbGJhY2sgdG8gZmlyZSwKICAgICAgICAvLyBzbyB0aGF0IHRoZSBhc3luYyBnZW5lcmF0b3IgZnVuY3Rpb24gaGFzIHRoZSBvcHBvcnR1bml0eSB0byBkbwogICAgICAgIC8vIGFueSBuZWNlc3Nhcnkgc2V0dXAgaW4gYSBwcmVkaWN0YWJsZSB3YXkuIFRoaXMgcHJlZGljdGFiaWxpdHkKICAgICAgICAvLyBpcyB3aHkgdGhlIFByb21pc2UgY29uc3RydWN0b3Igc3luY2hyb25vdXNseSBpbnZva2VzIGl0cwogICAgICAgIC8vIGV4ZWN1dG9yIGNhbGxiYWNrLCBhbmQgd2h5IGFzeW5jIGZ1bmN0aW9ucyBzeW5jaHJvbm91c2x5CiAgICAgICAgLy8gZXhlY3V0ZSBjb2RlIGJlZm9yZSB0aGUgZmlyc3QgYXdhaXQuIFNpbmNlIHdlIGltcGxlbWVudCBzaW1wbGUKICAgICAgICAvLyBhc3luYyBmdW5jdGlvbnMgaW4gdGVybXMgb2YgYXN5bmMgZ2VuZXJhdG9ycywgaXQgaXMgZXNwZWNpYWxseQogICAgICAgIC8vIGltcG9ydGFudCB0byBnZXQgdGhpcyByaWdodCwgZXZlbiB0aG91Z2ggaXQgcmVxdWlyZXMgY2FyZS4KICAgICAgICBwcmV2aW91c1Byb21pc2UgPyBwcmV2aW91c1Byb21pc2UudGhlbigKICAgICAgICAgIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnLAogICAgICAgICAgLy8gQXZvaWQgcHJvcGFnYXRpbmcgZmFpbHVyZXMgdG8gUHJvbWlzZXMgcmV0dXJuZWQgYnkgbGF0ZXIKICAgICAgICAgIC8vIGludm9jYXRpb25zIG9mIHRoZSBpdGVyYXRvci4KICAgICAgICAgIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnCiAgICAgICAgKSA6IGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKCk7CiAgICB9CgogICAgLy8gRGVmaW5lIHRoZSB1bmlmaWVkIGhlbHBlciBtZXRob2QgdGhhdCBpcyB1c2VkIHRvIGltcGxlbWVudCAubmV4dCwKICAgIC8vIC50aHJvdywgYW5kIC5yZXR1cm4gKHNlZSBkZWZpbmVJdGVyYXRvck1ldGhvZHMpLgogICAgdGhpcy5faW52b2tlID0gZW5xdWV1ZTsKICB9CgogIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhBc3luY0l0ZXJhdG9yLnByb3RvdHlwZSk7CgogIC8vIE5vdGUgdGhhdCBzaW1wbGUgYXN5bmMgZnVuY3Rpb25zIGFyZSBpbXBsZW1lbnRlZCBvbiB0b3Agb2YKICAvLyBBc3luY0l0ZXJhdG9yIG9iamVjdHM7IHRoZXkganVzdCByZXR1cm4gYSBQcm9taXNlIGZvciB0aGUgdmFsdWUgb2YKICAvLyB0aGUgZmluYWwgcmVzdWx0IHByb2R1Y2VkIGJ5IHRoZSBpdGVyYXRvci4KICBydW50aW1lLmFzeW5jID0gZnVuY3Rpb24oaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpIHsKICAgIHZhciBpdGVyID0gbmV3IEFzeW5jSXRlcmF0b3IoCiAgICAgIHdyYXAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpCiAgICApOwoKICAgIHJldHVybiBydW50aW1lLmlzR2VuZXJhdG9yRnVuY3Rpb24ob3V0ZXJGbikKICAgICAgPyBpdGVyIC8vIElmIG91dGVyRm4gaXMgYSBnZW5lcmF0b3IsIHJldHVybiB0aGUgZnVsbCBpdGVyYXRvci4KICAgICAgOiBpdGVyLm5leHQoKS50aGVuKGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAgICAgcmV0dXJuIHJlc3VsdC5kb25lID8gcmVzdWx0LnZhbHVlIDogaXRlci5uZXh0KCk7CiAgICAgICAgfSk7CiAgfTsKCiAgZnVuY3Rpb24gbWFrZUludm9rZU1ldGhvZChpbm5lckZuLCBzZWxmLCBjb250ZXh0KSB7CiAgICB2YXIgc3RhdGUgPSBHZW5TdGF0ZVN1c3BlbmRlZFN0YXJ0OwoKICAgIHJldHVybiBmdW5jdGlvbiBpbnZva2UobWV0aG9kLCBhcmcpIHsKICAgICAgaWYgKHN0YXRlID09PSBHZW5TdGF0ZUV4ZWN1dGluZykgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiR2VuZXJhdG9yIGlzIGFscmVhZHkgcnVubmluZyIpOwogICAgICB9CgogICAgICBpZiAoc3RhdGUgPT09IEdlblN0YXRlQ29tcGxldGVkKSB7CiAgICAgICAgaWYgKG1ldGhvZCA9PT0gInRocm93IikgewogICAgICAgICAgdGhyb3cgYXJnOwogICAgICAgIH0KCiAgICAgICAgLy8gQmUgZm9yZ2l2aW5nLCBwZXIgMjUuMy4zLjMuMyBvZiB0aGUgc3BlYzoKICAgICAgICAvLyBodHRwczovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtZ2VuZXJhdG9ycmVzdW1lCiAgICAgICAgcmV0dXJuIGRvbmVSZXN1bHQoKTsKICAgICAgfQoKICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICB2YXIgZGVsZWdhdGUgPSBjb250ZXh0LmRlbGVnYXRlOwogICAgICAgIGlmIChkZWxlZ2F0ZSkgewogICAgICAgICAgaWYgKG1ldGhvZCA9PT0gInJldHVybiIgfHwKICAgICAgICAgICAgICAobWV0aG9kID09PSAidGhyb3ciICYmIGRlbGVnYXRlLml0ZXJhdG9yW21ldGhvZF0gPT09IHVuZGVmaW5lZCkpIHsKICAgICAgICAgICAgLy8gQSByZXR1cm4gb3IgdGhyb3cgKHdoZW4gdGhlIGRlbGVnYXRlIGl0ZXJhdG9yIGhhcyBubyB0aHJvdwogICAgICAgICAgICAvLyBtZXRob2QpIGFsd2F5cyB0ZXJtaW5hdGVzIHRoZSB5aWVsZCogbG9vcC4KICAgICAgICAgICAgY29udGV4dC5kZWxlZ2F0ZSA9IG51bGw7CgogICAgICAgICAgICAvLyBJZiB0aGUgZGVsZWdhdGUgaXRlcmF0b3IgaGFzIGEgcmV0dXJuIG1ldGhvZCwgZ2l2ZSBpdCBhCiAgICAgICAgICAgIC8vIGNoYW5jZSB0byBjbGVhbiB1cC4KICAgICAgICAgICAgdmFyIHJldHVybk1ldGhvZCA9IGRlbGVnYXRlLml0ZXJhdG9yWyJyZXR1cm4iXTsKICAgICAgICAgICAgaWYgKHJldHVybk1ldGhvZCkgewogICAgICAgICAgICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChyZXR1cm5NZXRob2QsIGRlbGVnYXRlLml0ZXJhdG9yLCBhcmcpOwogICAgICAgICAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgICAgICAgICAgLy8gSWYgdGhlIHJldHVybiBtZXRob2QgdGhyZXcgYW4gZXhjZXB0aW9uLCBsZXQgdGhhdAogICAgICAgICAgICAgICAgLy8gZXhjZXB0aW9uIHByZXZhaWwgb3ZlciB0aGUgb3JpZ2luYWwgcmV0dXJuIG9yIHRocm93LgogICAgICAgICAgICAgICAgbWV0aG9kID0gInRocm93IjsKICAgICAgICAgICAgICAgIGFyZyA9IHJlY29yZC5hcmc7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChtZXRob2QgPT09ICJyZXR1cm4iKSB7CiAgICAgICAgICAgICAgLy8gQ29udGludWUgd2l0aCB0aGUgb3V0ZXIgcmV0dXJuLCBub3cgdGhhdCB0aGUgZGVsZWdhdGUKICAgICAgICAgICAgICAvLyBpdGVyYXRvciBoYXMgYmVlbiB0ZXJtaW5hdGVkLgogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgdmFyIHJlY29yZCA9IHRyeUNhdGNoKAogICAgICAgICAgICBkZWxlZ2F0ZS5pdGVyYXRvclttZXRob2RdLAogICAgICAgICAgICBkZWxlZ2F0ZS5pdGVyYXRvciwKICAgICAgICAgICAgYXJnCiAgICAgICAgICApOwoKICAgICAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDsKCiAgICAgICAgICAgIC8vIExpa2UgcmV0dXJuaW5nIGdlbmVyYXRvci50aHJvdyh1bmNhdWdodCksIGJ1dCB3aXRob3V0IHRoZQogICAgICAgICAgICAvLyBvdmVyaGVhZCBvZiBhbiBleHRyYSBmdW5jdGlvbiBjYWxsLgogICAgICAgICAgICBtZXRob2QgPSAidGhyb3ciOwogICAgICAgICAgICBhcmcgPSByZWNvcmQuYXJnOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KCiAgICAgICAgICAvLyBEZWxlZ2F0ZSBnZW5lcmF0b3IgcmFuIGFuZCBoYW5kbGVkIGl0cyBvd24gZXhjZXB0aW9ucyBzbwogICAgICAgICAgLy8gcmVnYXJkbGVzcyBvZiB3aGF0IHRoZSBtZXRob2Qgd2FzLCB3ZSBjb250aW51ZSBhcyBpZiBpdCBpcwogICAgICAgICAgLy8gIm5leHQiIHdpdGggYW4gdW5kZWZpbmVkIGFyZy4KICAgICAgICAgIG1ldGhvZCA9ICJuZXh0IjsKICAgICAgICAgIGFyZyA9IHVuZGVmaW5lZDsKCiAgICAgICAgICB2YXIgaW5mbyA9IHJlY29yZC5hcmc7CiAgICAgICAgICBpZiAoaW5mby5kb25lKSB7CiAgICAgICAgICAgIGNvbnRleHRbZGVsZWdhdGUucmVzdWx0TmFtZV0gPSBpbmZvLnZhbHVlOwogICAgICAgICAgICBjb250ZXh0Lm5leHQgPSBkZWxlZ2F0ZS5uZXh0TG9jOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RhdGUgPSBHZW5TdGF0ZVN1c3BlbmRlZFlpZWxkOwogICAgICAgICAgICByZXR1cm4gaW5mbzsKICAgICAgICAgIH0KCiAgICAgICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDsKICAgICAgICB9CgogICAgICAgIGlmIChtZXRob2QgPT09ICJuZXh0IikgewogICAgICAgICAgLy8gU2V0dGluZyBjb250ZXh0Ll9zZW50IGZvciBsZWdhY3kgc3VwcG9ydCBvZiBCYWJlbCdzCiAgICAgICAgICAvLyBmdW5jdGlvbi5zZW50IGltcGxlbWVudGF0aW9uLgogICAgICAgICAgY29udGV4dC5zZW50ID0gY29udGV4dC5fc2VudCA9IGFyZzsKCiAgICAgICAgfSBlbHNlIGlmIChtZXRob2QgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgIGlmIChzdGF0ZSA9PT0gR2VuU3RhdGVTdXNwZW5kZWRTdGFydCkgewogICAgICAgICAgICBzdGF0ZSA9IEdlblN0YXRlQ29tcGxldGVkOwogICAgICAgICAgICB0aHJvdyBhcmc7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKGNvbnRleHQuZGlzcGF0Y2hFeGNlcHRpb24oYXJnKSkgewogICAgICAgICAgICAvLyBJZiB0aGUgZGlzcGF0Y2hlZCBleGNlcHRpb24gd2FzIGNhdWdodCBieSBhIGNhdGNoIGJsb2NrLAogICAgICAgICAgICAvLyB0aGVuIGxldCB0aGF0IGNhdGNoIGJsb2NrIGhhbmRsZSB0aGUgZXhjZXB0aW9uIG5vcm1hbGx5LgogICAgICAgICAgICBtZXRob2QgPSAibmV4dCI7CiAgICAgICAgICAgIGFyZyA9IHVuZGVmaW5lZDsKICAgICAgICAgIH0KCiAgICAgICAgfSBlbHNlIGlmIChtZXRob2QgPT09ICJyZXR1cm4iKSB7CiAgICAgICAgICBjb250ZXh0LmFicnVwdCgicmV0dXJuIiwgYXJnKTsKICAgICAgICB9CgogICAgICAgIHN0YXRlID0gR2VuU3RhdGVFeGVjdXRpbmc7CgogICAgICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChpbm5lckZuLCBzZWxmLCBjb250ZXh0KTsKICAgICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJub3JtYWwiKSB7CiAgICAgICAgICAvLyBJZiBhbiBleGNlcHRpb24gaXMgdGhyb3duIGZyb20gaW5uZXJGbiwgd2UgbGVhdmUgc3RhdGUgPT09CiAgICAgICAgICAvLyBHZW5TdGF0ZUV4ZWN1dGluZyBhbmQgbG9vcCBiYWNrIGZvciBhbm90aGVyIGludm9jYXRpb24uCiAgICAgICAgICBzdGF0ZSA9IGNvbnRleHQuZG9uZQogICAgICAgICAgICA/IEdlblN0YXRlQ29tcGxldGVkCiAgICAgICAgICAgIDogR2VuU3RhdGVTdXNwZW5kZWRZaWVsZDsKCiAgICAgICAgICB2YXIgaW5mbyA9IHsKICAgICAgICAgICAgdmFsdWU6IHJlY29yZC5hcmcsCiAgICAgICAgICAgIGRvbmU6IGNvbnRleHQuZG9uZQogICAgICAgICAgfTsKCiAgICAgICAgICBpZiAocmVjb3JkLmFyZyA9PT0gQ29udGludWVTZW50aW5lbCkgewogICAgICAgICAgICBpZiAoY29udGV4dC5kZWxlZ2F0ZSAmJiBtZXRob2QgPT09ICJuZXh0IikgewogICAgICAgICAgICAgIC8vIERlbGliZXJhdGVseSBmb3JnZXQgdGhlIGxhc3Qgc2VudCB2YWx1ZSBzbyB0aGF0IHdlIGRvbid0CiAgICAgICAgICAgICAgLy8gYWNjaWRlbnRhbGx5IHBhc3MgaXQgb24gdG8gdGhlIGRlbGVnYXRlLgogICAgICAgICAgICAgIGFyZyA9IHVuZGVmaW5lZDsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGluZm87CiAgICAgICAgICB9CgogICAgICAgIH0gZWxzZSBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgIHN0YXRlID0gR2VuU3RhdGVDb21wbGV0ZWQ7CiAgICAgICAgICAvLyBEaXNwYXRjaCB0aGUgZXhjZXB0aW9uIGJ5IGxvb3BpbmcgYmFjayBhcm91bmQgdG8gdGhlCiAgICAgICAgICAvLyBjb250ZXh0LmRpc3BhdGNoRXhjZXB0aW9uKGFyZykgY2FsbCBhYm92ZS4KICAgICAgICAgIG1ldGhvZCA9ICJ0aHJvdyI7CiAgICAgICAgICBhcmcgPSByZWNvcmQuYXJnOwogICAgICAgIH0KICAgICAgfQogICAgfTsKICB9CgogIC8vIERlZmluZSBHZW5lcmF0b3IucHJvdG90eXBlLntuZXh0LHRocm93LHJldHVybn0gaW4gdGVybXMgb2YgdGhlCiAgLy8gdW5pZmllZCAuX2ludm9rZSBoZWxwZXIgbWV0aG9kLgogIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhHcCk7CgogIEdwW2l0ZXJhdG9yU3ltYm9sXSA9IGZ1bmN0aW9uKCkgewogICAgcmV0dXJuIHRoaXM7CiAgfTsKCiAgR3BbdG9TdHJpbmdUYWdTeW1ib2xdID0gIkdlbmVyYXRvciI7CgogIEdwLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7CiAgICByZXR1cm4gIltvYmplY3QgR2VuZXJhdG9yXSI7CiAgfTsKCiAgZnVuY3Rpb24gcHVzaFRyeUVudHJ5KGxvY3MpIHsKICAgIHZhciBlbnRyeSA9IHsgdHJ5TG9jOiBsb2NzWzBdIH07CgogICAgaWYgKDEgaW4gbG9jcykgewogICAgICBlbnRyeS5jYXRjaExvYyA9IGxvY3NbMV07CiAgICB9CgogICAgaWYgKDIgaW4gbG9jcykgewogICAgICBlbnRyeS5maW5hbGx5TG9jID0gbG9jc1syXTsKICAgICAgZW50cnkuYWZ0ZXJMb2MgPSBsb2NzWzNdOwogICAgfQoKICAgIHRoaXMudHJ5RW50cmllcy5wdXNoKGVudHJ5KTsKICB9CgogIGZ1bmN0aW9uIHJlc2V0VHJ5RW50cnkoZW50cnkpIHsKICAgIHZhciByZWNvcmQgPSBlbnRyeS5jb21wbGV0aW9uIHx8IHt9OwogICAgcmVjb3JkLnR5cGUgPSAibm9ybWFsIjsKICAgIGRlbGV0ZSByZWNvcmQuYXJnOwogICAgZW50cnkuY29tcGxldGlvbiA9IHJlY29yZDsKICB9CgogIGZ1bmN0aW9uIENvbnRleHQodHJ5TG9jc0xpc3QpIHsKICAgIC8vIFRoZSByb290IGVudHJ5IG9iamVjdCAoZWZmZWN0aXZlbHkgYSB0cnkgc3RhdGVtZW50IHdpdGhvdXQgYSBjYXRjaAogICAgLy8gb3IgYSBmaW5hbGx5IGJsb2NrKSBnaXZlcyB1cyBhIHBsYWNlIHRvIHN0b3JlIHZhbHVlcyB0aHJvd24gZnJvbQogICAgLy8gbG9jYXRpb25zIHdoZXJlIHRoZXJlIGlzIG5vIGVuY2xvc2luZyB0cnkgc3RhdGVtZW50LgogICAgdGhpcy50cnlFbnRyaWVzID0gW3sgdHJ5TG9jOiAicm9vdCIgfV07CiAgICB0cnlMb2NzTGlzdC5mb3JFYWNoKHB1c2hUcnlFbnRyeSwgdGhpcyk7CiAgICB0aGlzLnJlc2V0KHRydWUpOwogIH0KCiAgcnVudGltZS5rZXlzID0gZnVuY3Rpb24ob2JqZWN0KSB7CiAgICB2YXIga2V5cyA9IFtdOwogICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkgewogICAgICBrZXlzLnB1c2goa2V5KTsKICAgIH0KICAgIGtleXMucmV2ZXJzZSgpOwoKICAgIC8vIFJhdGhlciB0aGFuIHJldHVybmluZyBhbiBvYmplY3Qgd2l0aCBhIG5leHQgbWV0aG9kLCB3ZSBrZWVwCiAgICAvLyB0aGluZ3Mgc2ltcGxlIGFuZCByZXR1cm4gdGhlIG5leHQgZnVuY3Rpb24gaXRzZWxmLgogICAgcmV0dXJuIGZ1bmN0aW9uIG5leHQoKSB7CiAgICAgIHdoaWxlIChrZXlzLmxlbmd0aCkgewogICAgICAgIHZhciBrZXkgPSBrZXlzLnBvcCgpOwogICAgICAgIGlmIChrZXkgaW4gb2JqZWN0KSB7CiAgICAgICAgICBuZXh0LnZhbHVlID0ga2V5OwogICAgICAgICAgbmV4dC5kb25lID0gZmFsc2U7CiAgICAgICAgICByZXR1cm4gbmV4dDsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIFRvIGF2b2lkIGNyZWF0aW5nIGFuIGFkZGl0aW9uYWwgb2JqZWN0LCB3ZSBqdXN0IGhhbmcgdGhlIC52YWx1ZQogICAgICAvLyBhbmQgLmRvbmUgcHJvcGVydGllcyBvZmYgdGhlIG5leHQgZnVuY3Rpb24gb2JqZWN0IGl0c2VsZi4gVGhpcwogICAgICAvLyBhbHNvIGVuc3VyZXMgdGhhdCB0aGUgbWluaWZpZXIgd2lsbCBub3QgYW5vbnltaXplIHRoZSBmdW5jdGlvbi4KICAgICAgbmV4dC5kb25lID0gdHJ1ZTsKICAgICAgcmV0dXJuIG5leHQ7CiAgICB9OwogIH07CgogIGZ1bmN0aW9uIHZhbHVlcyhpdGVyYWJsZSkgewogICAgaWYgKGl0ZXJhYmxlKSB7CiAgICAgIHZhciBpdGVyYXRvck1ldGhvZCA9IGl0ZXJhYmxlW2l0ZXJhdG9yU3ltYm9sXTsKICAgICAgaWYgKGl0ZXJhdG9yTWV0aG9kKSB7CiAgICAgICAgcmV0dXJuIGl0ZXJhdG9yTWV0aG9kLmNhbGwoaXRlcmFibGUpOwogICAgICB9CgogICAgICBpZiAodHlwZW9mIGl0ZXJhYmxlLm5leHQgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICByZXR1cm4gaXRlcmFibGU7CiAgICAgIH0KCiAgICAgIGlmICghaXNOYU4oaXRlcmFibGUubGVuZ3RoKSkgewogICAgICAgIHZhciBpID0gLTEsIG5leHQgPSBmdW5jdGlvbiBuZXh0KCkgewogICAgICAgICAgd2hpbGUgKCsraSA8IGl0ZXJhYmxlLmxlbmd0aCkgewogICAgICAgICAgICBpZiAoaGFzT3duLmNhbGwoaXRlcmFibGUsIGkpKSB7CiAgICAgICAgICAgICAgbmV4dC52YWx1ZSA9IGl0ZXJhYmxlW2ldOwogICAgICAgICAgICAgIG5leHQuZG9uZSA9IGZhbHNlOwogICAgICAgICAgICAgIHJldHVybiBuZXh0OwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgbmV4dC52YWx1ZSA9IHVuZGVmaW5lZDsKICAgICAgICAgIG5leHQuZG9uZSA9IHRydWU7CgogICAgICAgICAgcmV0dXJuIG5leHQ7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIG5leHQubmV4dCA9IG5leHQ7CiAgICAgIH0KICAgIH0KCiAgICAvLyBSZXR1cm4gYW4gaXRlcmF0b3Igd2l0aCBubyB2YWx1ZXMuCiAgICByZXR1cm4geyBuZXh0OiBkb25lUmVzdWx0IH07CiAgfQogIHJ1bnRpbWUudmFsdWVzID0gdmFsdWVzOwoKICBmdW5jdGlvbiBkb25lUmVzdWx0KCkgewogICAgcmV0dXJuIHsgdmFsdWU6IHVuZGVmaW5lZCwgZG9uZTogdHJ1ZSB9OwogIH0KCiAgQ29udGV4dC5wcm90b3R5cGUgPSB7CiAgICBjb25zdHJ1Y3RvcjogQ29udGV4dCwKCiAgICByZXNldDogZnVuY3Rpb24oc2tpcFRlbXBSZXNldCkgewogICAgICB0aGlzLnByZXYgPSAwOwogICAgICB0aGlzLm5leHQgPSAwOwogICAgICAvLyBSZXNldHRpbmcgY29udGV4dC5fc2VudCBmb3IgbGVnYWN5IHN1cHBvcnQgb2YgQmFiZWwncwogICAgICAvLyBmdW5jdGlvbi5zZW50IGltcGxlbWVudGF0aW9uLgogICAgICB0aGlzLnNlbnQgPSB0aGlzLl9zZW50ID0gdW5kZWZpbmVkOwogICAgICB0aGlzLmRvbmUgPSBmYWxzZTsKICAgICAgdGhpcy5kZWxlZ2F0ZSA9IG51bGw7CgogICAgICB0aGlzLnRyeUVudHJpZXMuZm9yRWFjaChyZXNldFRyeUVudHJ5KTsKCiAgICAgIGlmICghc2tpcFRlbXBSZXNldCkgewogICAgICAgIGZvciAodmFyIG5hbWUgaW4gdGhpcykgewogICAgICAgICAgLy8gTm90IHN1cmUgYWJvdXQgdGhlIG9wdGltYWwgb3JkZXIgb2YgdGhlc2UgY29uZGl0aW9uczoKICAgICAgICAgIGlmIChuYW1lLmNoYXJBdCgwKSA9PT0gInQiICYmCiAgICAgICAgICAgICAgaGFzT3duLmNhbGwodGhpcywgbmFtZSkgJiYKICAgICAgICAgICAgICAhaXNOYU4oK25hbWUuc2xpY2UoMSkpKSB7CiAgICAgICAgICAgIHRoaXNbbmFtZV0gPSB1bmRlZmluZWQ7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9LAoKICAgIHN0b3A6IGZ1bmN0aW9uKCkgewogICAgICB0aGlzLmRvbmUgPSB0cnVlOwoKICAgICAgdmFyIHJvb3RFbnRyeSA9IHRoaXMudHJ5RW50cmllc1swXTsKICAgICAgdmFyIHJvb3RSZWNvcmQgPSByb290RW50cnkuY29tcGxldGlvbjsKICAgICAgaWYgKHJvb3RSZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgIHRocm93IHJvb3RSZWNvcmQuYXJnOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5ydmFsOwogICAgfSwKCiAgICBkaXNwYXRjaEV4Y2VwdGlvbjogZnVuY3Rpb24oZXhjZXB0aW9uKSB7CiAgICAgIGlmICh0aGlzLmRvbmUpIHsKICAgICAgICB0aHJvdyBleGNlcHRpb247CiAgICAgIH0KCiAgICAgIHZhciBjb250ZXh0ID0gdGhpczsKICAgICAgZnVuY3Rpb24gaGFuZGxlKGxvYywgY2F1Z2h0KSB7CiAgICAgICAgcmVjb3JkLnR5cGUgPSAidGhyb3ciOwogICAgICAgIHJlY29yZC5hcmcgPSBleGNlcHRpb247CiAgICAgICAgY29udGV4dC5uZXh0ID0gbG9jOwogICAgICAgIHJldHVybiAhIWNhdWdodDsKICAgICAgfQoKICAgICAgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgewogICAgICAgIHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTsKICAgICAgICB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbjsKCiAgICAgICAgaWYgKGVudHJ5LnRyeUxvYyA9PT0gInJvb3QiKSB7CiAgICAgICAgICAvLyBFeGNlcHRpb24gdGhyb3duIG91dHNpZGUgb2YgYW55IHRyeSBibG9jayB0aGF0IGNvdWxkIGhhbmRsZQogICAgICAgICAgLy8gaXQsIHNvIHNldCB0aGUgY29tcGxldGlvbiB2YWx1ZSBvZiB0aGUgZW50aXJlIGZ1bmN0aW9uIHRvCiAgICAgICAgICAvLyB0aHJvdyB0aGUgZXhjZXB0aW9uLgogICAgICAgICAgcmV0dXJuIGhhbmRsZSgiZW5kIik7CiAgICAgICAgfQoKICAgICAgICBpZiAoZW50cnkudHJ5TG9jIDw9IHRoaXMucHJldikgewogICAgICAgICAgdmFyIGhhc0NhdGNoID0gaGFzT3duLmNhbGwoZW50cnksICJjYXRjaExvYyIpOwogICAgICAgICAgdmFyIGhhc0ZpbmFsbHkgPSBoYXNPd24uY2FsbChlbnRyeSwgImZpbmFsbHlMb2MiKTsKCiAgICAgICAgICBpZiAoaGFzQ2F0Y2ggJiYgaGFzRmluYWxseSkgewogICAgICAgICAgICBpZiAodGhpcy5wcmV2IDwgZW50cnkuY2F0Y2hMb2MpIHsKICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlKGVudHJ5LmNhdGNoTG9jLCB0cnVlKTsKICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnByZXYgPCBlbnRyeS5maW5hbGx5TG9jKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5maW5hbGx5TG9jKTsKICAgICAgICAgICAgfQoKICAgICAgICAgIH0gZWxzZSBpZiAoaGFzQ2F0Y2gpIHsKICAgICAgICAgICAgaWYgKHRoaXMucHJldiA8IGVudHJ5LmNhdGNoTG9jKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5jYXRjaExvYywgdHJ1ZSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICB9IGVsc2UgaWYgKGhhc0ZpbmFsbHkpIHsKICAgICAgICAgICAgaWYgKHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHsKICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlKGVudHJ5LmZpbmFsbHlMb2MpOwogICAgICAgICAgICB9CgogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJ0cnkgc3RhdGVtZW50IHdpdGhvdXQgY2F0Y2ggb3IgZmluYWxseSIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfSwKCiAgICBhYnJ1cHQ6IGZ1bmN0aW9uKHR5cGUsIGFyZykgewogICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOwogICAgICAgIGlmIChlbnRyeS50cnlMb2MgPD0gdGhpcy5wcmV2ICYmCiAgICAgICAgICAgIGhhc093bi5jYWxsKGVudHJ5LCAiZmluYWxseUxvYyIpICYmCiAgICAgICAgICAgIHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHsKICAgICAgICAgIHZhciBmaW5hbGx5RW50cnkgPSBlbnRyeTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKGZpbmFsbHlFbnRyeSAmJgogICAgICAgICAgKHR5cGUgPT09ICJicmVhayIgfHwKICAgICAgICAgICB0eXBlID09PSAiY29udGludWUiKSAmJgogICAgICAgICAgZmluYWxseUVudHJ5LnRyeUxvYyA8PSBhcmcgJiYKICAgICAgICAgIGFyZyA8PSBmaW5hbGx5RW50cnkuZmluYWxseUxvYykgewogICAgICAgIC8vIElnbm9yZSB0aGUgZmluYWxseSBlbnRyeSBpZiBjb250cm9sIGlzIG5vdCBqdW1waW5nIHRvIGEKICAgICAgICAvLyBsb2NhdGlvbiBvdXRzaWRlIHRoZSB0cnkvY2F0Y2ggYmxvY2suCiAgICAgICAgZmluYWxseUVudHJ5ID0gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIHJlY29yZCA9IGZpbmFsbHlFbnRyeSA/IGZpbmFsbHlFbnRyeS5jb21wbGV0aW9uIDoge307CiAgICAgIHJlY29yZC50eXBlID0gdHlwZTsKICAgICAgcmVjb3JkLmFyZyA9IGFyZzsKCiAgICAgIGlmIChmaW5hbGx5RW50cnkpIHsKICAgICAgICB0aGlzLm5leHQgPSBmaW5hbGx5RW50cnkuZmluYWxseUxvYzsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLmNvbXBsZXRlKHJlY29yZCk7CiAgICAgIH0KCiAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsOwogICAgfSwKCiAgICBjb21wbGV0ZTogZnVuY3Rpb24ocmVjb3JkLCBhZnRlckxvYykgewogICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICB0aHJvdyByZWNvcmQuYXJnOwogICAgICB9CgogICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJicmVhayIgfHwKICAgICAgICAgIHJlY29yZC50eXBlID09PSAiY29udGludWUiKSB7CiAgICAgICAgdGhpcy5uZXh0ID0gcmVjb3JkLmFyZzsKICAgICAgfSBlbHNlIGlmIChyZWNvcmQudHlwZSA9PT0gInJldHVybiIpIHsKICAgICAgICB0aGlzLnJ2YWwgPSByZWNvcmQuYXJnOwogICAgICAgIHRoaXMubmV4dCA9ICJlbmQiOwogICAgICB9IGVsc2UgaWYgKHJlY29yZC50eXBlID09PSAibm9ybWFsIiAmJiBhZnRlckxvYykgewogICAgICAgIHRoaXMubmV4dCA9IGFmdGVyTG9jOwogICAgICB9CiAgICB9LAoKICAgIGZpbmlzaDogZnVuY3Rpb24oZmluYWxseUxvYykgewogICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOwogICAgICAgIGlmIChlbnRyeS5maW5hbGx5TG9jID09PSBmaW5hbGx5TG9jKSB7CiAgICAgICAgICB0aGlzLmNvbXBsZXRlKGVudHJ5LmNvbXBsZXRpb24sIGVudHJ5LmFmdGVyTG9jKTsKICAgICAgICAgIHJlc2V0VHJ5RW50cnkoZW50cnkpOwogICAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7CiAgICAgICAgfQogICAgICB9CiAgICB9LAoKICAgICJjYXRjaCI6IGZ1bmN0aW9uKHRyeUxvYykgewogICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOwogICAgICAgIGlmIChlbnRyeS50cnlMb2MgPT09IHRyeUxvYykgewogICAgICAgICAgdmFyIHJlY29yZCA9IGVudHJ5LmNvbXBsZXRpb247CiAgICAgICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgICAgdmFyIHRocm93biA9IHJlY29yZC5hcmc7CiAgICAgICAgICAgIHJlc2V0VHJ5RW50cnkoZW50cnkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRocm93bjsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIFRoZSBjb250ZXh0LmNhdGNoIG1ldGhvZCBtdXN0IG9ubHkgYmUgY2FsbGVkIHdpdGggYSBsb2NhdGlvbgogICAgICAvLyBhcmd1bWVudCB0aGF0IGNvcnJlc3BvbmRzIHRvIGEga25vd24gY2F0Y2ggYmxvY2suCiAgICAgIHRocm93IG5ldyBFcnJvcigiaWxsZWdhbCBjYXRjaCBhdHRlbXB0Iik7CiAgICB9LAoKICAgIGRlbGVnYXRlWWllbGQ6IGZ1bmN0aW9uKGl0ZXJhYmxlLCByZXN1bHROYW1lLCBuZXh0TG9jKSB7CiAgICAgIHRoaXMuZGVsZWdhdGUgPSB7CiAgICAgICAgaXRlcmF0b3I6IHZhbHVlcyhpdGVyYWJsZSksCiAgICAgICAgcmVzdWx0TmFtZTogcmVzdWx0TmFtZSwKICAgICAgICBuZXh0TG9jOiBuZXh0TG9jCiAgICAgIH07CgogICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgIH0KICB9Owp9KSgKICAvLyBBbW9uZyB0aGUgdmFyaW91cyB0cmlja3MgZm9yIG9idGFpbmluZyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsCiAgLy8gb2JqZWN0LCB0aGlzIHNlZW1zIHRvIGJlIHRoZSBtb3N0IHJlbGlhYmxlIHRlY2huaXF1ZSB0aGF0IGRvZXMgbm90CiAgLy8gdXNlIGluZGlyZWN0IGV2YWwgKHdoaWNoIHZpb2xhdGVzIENvbnRlbnQgU2VjdXJpdHkgUG9saWN5KS4KICB0eXBlb2YgZ2xvYmFsID09PSAib2JqZWN0IiA/IGdsb2JhbCA6CiAgdHlwZW9mIHdpbmRvdyA9PT0gIm9iamVjdCIgPyB3aW5kb3cgOgogIHR5cGVvZiBzZWxmID09PSAib2JqZWN0IiA/IHNlbGYgOiB0aGlzCik7Cgo7KGZ1bmN0aW9uKCkgewovKiEKICogQG92ZXJ2aWV3ICBFbWJlciAtIEphdmFTY3JpcHQgQXBwbGljYXRpb24gRnJhbWV3b3JrCiAqIEBjb3B5cmlnaHQgQ29weXJpZ2h0IDIwMTEtMjAxOSBUaWxkZSBJbmMuIGFuZCBjb250cmlidXRvcnMKICogICAgICAgICAgICBQb3J0aW9ucyBDb3B5cmlnaHQgMjAwNi0yMDExIFN0cm9iZSBJbmMuCiAqICAgICAgICAgICAgUG9ydGlvbnMgQ29weXJpZ2h0IDIwMDgtMjAxMSBBcHBsZSBJbmMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiAqIEBsaWNlbnNlICAgTGljZW5zZWQgdW5kZXIgTUlUIGxpY2Vuc2UKICogICAgICAgICAgICBTZWUgaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS9lbWJlcmpzL2VtYmVyLmpzL21hc3Rlci9MSUNFTlNFCiAqIEB2ZXJzaW9uICAgMy4xMy4zCiAqLwoKLypnbG9iYWxzIHByb2Nlc3MgKi8KdmFyIGRlZmluZSwgcmVxdWlyZSwgRW1iZXI7CgovLyBVc2VkIGluIEBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50L2xpYi9nbG9iYWwuanMKbWFpbkNvbnRleHQgPSB0aGlzOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmCgooZnVuY3Rpb24oKSB7CiAgZnVuY3Rpb24gbWlzc2luZ01vZHVsZShuYW1lLCByZWZlcnJlck5hbWUpIHsKICAgIGlmIChyZWZlcnJlck5hbWUpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgZmluZCBtb2R1bGUgJyArIG5hbWUgKyAnIHJlcXVpcmVkIGJ5OiAnICsgcmVmZXJyZXJOYW1lKTsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGZpbmQgbW9kdWxlICcgKyBuYW1lKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGludGVybmFsUmVxdWlyZShfbmFtZSwgcmVmZXJyZXJOYW1lKSB7CiAgICB2YXIgbmFtZSA9IF9uYW1lOwogICAgdmFyIG1vZCA9IHJlZ2lzdHJ5W25hbWVdOwoKICAgIGlmICghbW9kKSB7CiAgICAgIG5hbWUgPSBuYW1lICsgJy9pbmRleCc7CiAgICAgIG1vZCA9IHJlZ2lzdHJ5W25hbWVdOwogICAgfQoKICAgIHZhciBleHBvcnRzID0gc2VlbltuYW1lXTsKCiAgICBpZiAoZXhwb3J0cyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBleHBvcnRzOwogICAgfQoKICAgIGV4cG9ydHMgPSBzZWVuW25hbWVdID0ge307CgogICAgaWYgKCFtb2QpIHsKICAgICAgbWlzc2luZ01vZHVsZShfbmFtZSwgcmVmZXJyZXJOYW1lKTsKICAgIH0KCiAgICB2YXIgZGVwcyA9IG1vZC5kZXBzOwogICAgdmFyIGNhbGxiYWNrID0gbW9kLmNhbGxiYWNrOwogICAgdmFyIHJlaWZpZWQgPSBuZXcgQXJyYXkoZGVwcy5sZW5ndGgpOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVwcy5sZW5ndGg7IGkrKykgewogICAgICBpZiAoZGVwc1tpXSA9PT0gJ2V4cG9ydHMnKSB7CiAgICAgICAgcmVpZmllZFtpXSA9IGV4cG9ydHM7CiAgICAgIH0gZWxzZSBpZiAoZGVwc1tpXSA9PT0gJ3JlcXVpcmUnKSB7CiAgICAgICAgcmVpZmllZFtpXSA9IHJlcXVpcmU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmVpZmllZFtpXSA9IGludGVybmFsUmVxdWlyZShkZXBzW2ldLCBuYW1lKTsKICAgICAgfQogICAgfQoKICAgIGNhbGxiYWNrLmFwcGx5KHRoaXMsIHJlaWZpZWQpOwoKICAgIHJldHVybiBleHBvcnRzOwogIH0KCiAgdmFyIGlzTm9kZSA9CiAgICB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJyAmJgogICAgdHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmCiAgICB7fS50b1N0cmluZy5jYWxsKHByb2Nlc3MpID09PSAnW29iamVjdCBwcm9jZXNzXSc7CgogIGlmICghaXNOb2RlKSB7CiAgICBFbWJlciA9IHRoaXMuRW1iZXIgPSB0aGlzLkVtYmVyIHx8IHt9OwogIH0KCiAgaWYgKHR5cGVvZiBFbWJlciA9PT0gJ3VuZGVmaW5lZCcpIHsKICAgIEVtYmVyID0ge307CiAgfQoKICBpZiAodHlwZW9mIEVtYmVyLl9fbG9hZGVyID09PSAndW5kZWZpbmVkJykgewogICAgdmFyIHJlZ2lzdHJ5ID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHZhciBzZWVuID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKCiAgICBkZWZpbmUgPSBmdW5jdGlvbihuYW1lLCBkZXBzLCBjYWxsYmFjaykgewogICAgICB2YXIgdmFsdWUgPSB7fTsKCiAgICAgIGlmICghY2FsbGJhY2spIHsKICAgICAgICB2YWx1ZS5kZXBzID0gW107CiAgICAgICAgdmFsdWUuY2FsbGJhY2sgPSBkZXBzOwogICAgICB9IGVsc2UgewogICAgICAgIHZhbHVlLmRlcHMgPSBkZXBzOwogICAgICAgIHZhbHVlLmNhbGxiYWNrID0gY2FsbGJhY2s7CiAgICAgIH0KCiAgICAgIHJlZ2lzdHJ5W25hbWVdID0gdmFsdWU7CiAgICB9OwoKICAgIHJlcXVpcmUgPSBmdW5jdGlvbihuYW1lKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbFJlcXVpcmUobmFtZSwgbnVsbCk7CiAgICB9OwoKICAgIC8vIHNldHVwIGByZXF1aXJlYCBtb2R1bGUKICAgIHJlcXVpcmVbJ2RlZmF1bHQnXSA9IHJlcXVpcmU7CgogICAgcmVxdWlyZS5oYXMgPSBmdW5jdGlvbiByZWdpc3RyeUhhcyhtb2R1bGVOYW1lKSB7CiAgICAgIHJldHVybiBCb29sZWFuKHJlZ2lzdHJ5W21vZHVsZU5hbWVdKSB8fCBCb29sZWFuKHJlZ2lzdHJ5W21vZHVsZU5hbWUgKyAnL2luZGV4J10pOwogICAgfTsKCiAgICByZXF1aXJlLl9lYWtfc2VlbiA9IHJlZ2lzdHJ5OwoKICAgIEVtYmVyLl9fbG9hZGVyID0gewogICAgICBkZWZpbmU6IGRlZmluZSwKICAgICAgcmVxdWlyZTogcmVxdWlyZSwKICAgICAgcmVnaXN0cnk6IHJlZ2lzdHJ5LAogICAgfTsKICB9IGVsc2UgewogICAgZGVmaW5lID0gRW1iZXIuX19sb2FkZXIuZGVmaW5lOwogICAgcmVxdWlyZSA9IEVtYmVyLl9fbG9hZGVyLnJlcXVpcmU7CiAgfQp9KSgpOwoKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9icm93c2VyLWVudmlyb25tZW50L2luZGV4IiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuaGFzRE9NID0gX2V4cG9ydHMuaXNGaXJlZm94ID0gX2V4cG9ydHMuaXNDaHJvbWUgPSBfZXhwb3J0cy51c2VyQWdlbnQgPSBfZXhwb3J0cy5oaXN0b3J5ID0gX2V4cG9ydHMubG9jYXRpb24gPSBfZXhwb3J0cy53aW5kb3cgPSB2b2lkIDA7CiAgLy8gY2hlY2sgaWYgd2luZG93IGV4aXN0cyBhbmQgYWN0dWFsbHkgaXMgdGhlIGdsb2JhbAogIHZhciBoYXNEb20gPSB0eXBlb2Ygc2VsZiA9PT0gJ29iamVjdCcgJiYgc2VsZiAhPT0gbnVsbCAmJiBzZWxmLk9iamVjdCA9PT0gT2JqZWN0ICYmIHR5cGVvZiBXaW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHNlbGYuY29uc3RydWN0b3IgPT09IFdpbmRvdyAmJiB0eXBlb2YgZG9jdW1lbnQgPT09ICdvYmplY3QnICYmIGRvY3VtZW50ICE9PSBudWxsICYmIHNlbGYuZG9jdW1lbnQgPT09IGRvY3VtZW50ICYmIHR5cGVvZiBsb2NhdGlvbiA9PT0gJ29iamVjdCcgJiYgbG9jYXRpb24gIT09IG51bGwgJiYgc2VsZi5sb2NhdGlvbiA9PT0gbG9jYXRpb24gJiYgdHlwZW9mIGhpc3RvcnkgPT09ICdvYmplY3QnICYmIGhpc3RvcnkgIT09IG51bGwgJiYgc2VsZi5oaXN0b3J5ID09PSBoaXN0b3J5ICYmIHR5cGVvZiBuYXZpZ2F0b3IgPT09ICdvYmplY3QnICYmIG5hdmlnYXRvciAhPT0gbnVsbCAmJiBzZWxmLm5hdmlnYXRvciA9PT0gbmF2aWdhdG9yICYmIHR5cGVvZiBuYXZpZ2F0b3IudXNlckFnZW50ID09PSAnc3RyaW5nJzsKICBfZXhwb3J0cy5oYXNET00gPSBoYXNEb207CiAgdmFyIHdpbmRvdyA9IGhhc0RvbSA/IHNlbGYgOiBudWxsOwogIF9leHBvcnRzLndpbmRvdyA9IHdpbmRvdzsKICB2YXIgbG9jYXRpb24kMSA9IGhhc0RvbSA/IHNlbGYubG9jYXRpb24gOiBudWxsOwogIF9leHBvcnRzLmxvY2F0aW9uID0gbG9jYXRpb24kMTsKICB2YXIgaGlzdG9yeSQxID0gaGFzRG9tID8gc2VsZi5oaXN0b3J5IDogbnVsbDsKICBfZXhwb3J0cy5oaXN0b3J5ID0gaGlzdG9yeSQxOwogIHZhciB1c2VyQWdlbnQgPSBoYXNEb20gPyBzZWxmLm5hdmlnYXRvci51c2VyQWdlbnQgOiAnTHlueCAodGV4dG1vZGUpJzsKICBfZXhwb3J0cy51c2VyQWdlbnQgPSB1c2VyQWdlbnQ7CiAgdmFyIGlzQ2hyb21lID0gaGFzRG9tID8gQm9vbGVhbih3aW5kb3cuY2hyb21lKSAmJiAhd2luZG93Lm9wZXJhIDogZmFsc2U7CiAgX2V4cG9ydHMuaXNDaHJvbWUgPSBpc0Nocm9tZTsKICB2YXIgaXNGaXJlZm94ID0gaGFzRG9tID8gdHlwZW9mIEluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJyA6IGZhbHNlOwogIF9leHBvcnRzLmlzRmlyZWZveCA9IGlzRmlyZWZveDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvY29uc29sZS9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVidWcsIF9kZXByZWNhdGVkRmVhdHVyZXMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CiAgLy8gRGVsaXZlciBtZXNzYWdlIHRoYXQgdGhlIGZ1bmN0aW9uIGlzIGRlcHJlY2F0ZWQKICB2YXIgREVQUkVDQVRJT05fTUVTU0FHRSA9ICdVc2Ugb2YgRW1iZXIuTG9nZ2VyIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgYGNvbnNvbGVgIGZvciBsb2dnaW5nLic7CiAgdmFyIERFUFJFQ0FUSU9OX0lEID0gJ2VtYmVyLWNvbnNvbGUuZGVwcmVjYXRlLWxvZ2dlcic7CiAgdmFyIERFUFJFQ0FUSU9OX1VSTCA9ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY191c2UtY29uc29sZS1yYXRoZXItdGhhbi1lbWJlci1sb2dnZXInOwogIC8qKgogICAgIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIEluc2lkZSBFbWJlci1NZXRhbCwgc2ltcGx5IHVzZXMgdGhlIG1ldGhvZHMgZnJvbSBgaW1wb3J0cy5jb25zb2xlYC4KICAgIE92ZXJyaWRlIHRoaXMgdG8gcHJvdmlkZSBtb3JlIHJvYnVzdCBsb2dnaW5nIGZ1bmN0aW9uYWxpdHkuCiAgCiAgICBAY2xhc3MgTG9nZ2VyCiAgICBAZGVwcmVjYXRlZCBVc2UgJ2NvbnNvbGUnIGluc3RlYWQKICAKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEBwdWJsaWMKICAqLwoKICB2YXIgREVQUkVDQVRFRF9MT0dHRVI7CgogIGlmIChfZGVwcmVjYXRlZEZlYXR1cmVzLkxPR0dFUikgewogICAgREVQUkVDQVRFRF9MT0dHRVIgPSB7CiAgICAgIC8qKgogICAgICBMb2dzIHRoZSBhcmd1bWVudHMgdG8gdGhlIGNvbnNvbGUuCiAgICAgIFlvdSBjYW4gcGFzcyBhcyBtYW55IGFyZ3VtZW50cyBhcyB5b3Ugd2FudCBhbmQgdGhleSB3aWxsIGJlIGpvaW5lZCB0b2dldGhlciB3aXRoIGEgc3BhY2UuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHZhciBmb28gPSAxOwogICAgICBFbWJlci5Mb2dnZXIubG9nKCdsb2cgdmFsdWUgb2YgZm9vOicsIGZvbyk7CiAgICAgIC8vICJsb2cgdmFsdWUgb2YgZm9vOiAxIiB3aWxsIGJlIHByaW50ZWQgdG8gdGhlIGNvbnNvbGUKICAgICAgYGBgCiAgICAgIEBtZXRob2QgbG9nCiAgICAgIEBmb3IgRW1iZXIuTG9nZ2VyCiAgICAgIEBwYXJhbSB7Kn0gYXJndW1lbnRzCiAgICAgIEBwdWJsaWMKICAgICAgKi8KICAgICAgbG9nOiBmdW5jdGlvbiBsb2coKSB7CiAgICAgICAgdmFyIF9jb25zb2xlOwoKICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKERFUFJFQ0FUSU9OX01FU1NBR0UsIGZhbHNlLCB7CiAgICAgICAgICBpZDogREVQUkVDQVRJT05fSUQsCiAgICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICAgIHVybDogREVQUkVDQVRJT05fVVJMCiAgICAgICAgfSkpOwogICAgICAgIHJldHVybiAoX2NvbnNvbGUgPSBjb25zb2xlKS5sb2cuYXBwbHkoX2NvbnNvbGUsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tY29uc29sZQogICAgICB9LAoKICAgICAgLyoqCiAgICAgIFByaW50cyB0aGUgYXJndW1lbnRzIHRvIHRoZSBjb25zb2xlIHdpdGggYSB3YXJuaW5nIGljb24uCiAgICAgIFlvdSBjYW4gcGFzcyBhcyBtYW55IGFyZ3VtZW50cyBhcyB5b3Ugd2FudCBhbmQgdGhleSB3aWxsIGJlIGpvaW5lZCB0b2dldGhlciB3aXRoIGEgc3BhY2UuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIEVtYmVyLkxvZ2dlci53YXJuKCdTb21ldGhpbmcgaGFwcGVuZWQhJyk7CiAgICAgIC8vICJTb21ldGhpbmcgaGFwcGVuZWQhIiB3aWxsIGJlIHByaW50ZWQgdG8gdGhlIGNvbnNvbGUgd2l0aCBhIHdhcm5pbmcgaWNvbi4KICAgICAgYGBgCiAgICAgIEBtZXRob2Qgd2FybgogICAgICBAZm9yIEVtYmVyLkxvZ2dlcgogICAgICBAcGFyYW0geyp9IGFyZ3VtZW50cwogICAgICBAcHVibGljCiAgICAgICovCiAgICAgIHdhcm46IGZ1bmN0aW9uIHdhcm4oKSB7CiAgICAgICAgdmFyIF9jb25zb2xlMjsKCiAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKShERVBSRUNBVElPTl9NRVNTQUdFLCBmYWxzZSwgewogICAgICAgICAgaWQ6IERFUFJFQ0FUSU9OX0lELAogICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICB1cmw6IERFUFJFQ0FUSU9OX1VSTAogICAgICAgIH0pKTsKICAgICAgICByZXR1cm4gKF9jb25zb2xlMiA9IGNvbnNvbGUpLndhcm4uYXBwbHkoX2NvbnNvbGUyLCBhcmd1bWVudHMpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGUKICAgICAgfSwKCiAgICAgIC8qKgogICAgICBQcmludHMgdGhlIGFyZ3VtZW50cyB0byB0aGUgY29uc29sZSB3aXRoIGFuIGVycm9yIGljb24sIHJlZCB0ZXh0IGFuZCBhIHN0YWNrIHRyYWNlLgogICAgICBZb3UgY2FuIHBhc3MgYXMgbWFueSBhcmd1bWVudHMgYXMgeW91IHdhbnQgYW5kIHRoZXkgd2lsbCBiZSBqb2luZWQgdG9nZXRoZXIgd2l0aCBhIHNwYWNlLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBFbWJlci5Mb2dnZXIuZXJyb3IoJ0RhbmdlciEgRGFuZ2VyIScpOwogICAgICAvLyAiRGFuZ2VyISBEYW5nZXIhIiB3aWxsIGJlIHByaW50ZWQgdG8gdGhlIGNvbnNvbGUgaW4gcmVkIHRleHQuCiAgICAgIGBgYAogICAgICBAbWV0aG9kIGVycm9yCiAgICAgIEBmb3IgRW1iZXIuTG9nZ2VyCiAgICAgIEBwYXJhbSB7Kn0gYXJndW1lbnRzCiAgICAgIEBwdWJsaWMKICAgICAgKi8KICAgICAgZXJyb3I6IGZ1bmN0aW9uIGVycm9yKCkgewogICAgICAgIHZhciBfY29uc29sZTM7CgogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoREVQUkVDQVRJT05fTUVTU0FHRSwgZmFsc2UsIHsKICAgICAgICAgIGlkOiBERVBSRUNBVElPTl9JRCwKICAgICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgICAgdXJsOiBERVBSRUNBVElPTl9VUkwKICAgICAgICB9KSk7CiAgICAgICAgcmV0dXJuIChfY29uc29sZTMgPSBjb25zb2xlKS5lcnJvci5hcHBseShfY29uc29sZTMsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tY29uc29sZQogICAgICB9LAoKICAgICAgLyoqCiAgICAgIExvZ3MgdGhlIGFyZ3VtZW50cyB0byB0aGUgY29uc29sZS4KICAgICAgWW91IGNhbiBwYXNzIGFzIG1hbnkgYXJndW1lbnRzIGFzIHlvdSB3YW50IGFuZCB0aGV5IHdpbGwgYmUgam9pbmVkIHRvZ2V0aGVyIHdpdGggYSBzcGFjZS4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgdmFyIGZvbyA9IDE7CiAgICAgIEVtYmVyLkxvZ2dlci5pbmZvKCdsb2cgdmFsdWUgb2YgZm9vOicsIGZvbyk7CiAgICAgIC8vICJsb2cgdmFsdWUgb2YgZm9vOiAxIiB3aWxsIGJlIHByaW50ZWQgdG8gdGhlIGNvbnNvbGUKICAgICAgYGBgCiAgICAgIEBtZXRob2QgaW5mbwogICAgICBAZm9yIEVtYmVyLkxvZ2dlcgogICAgICBAcGFyYW0geyp9IGFyZ3VtZW50cwogICAgICBAcHVibGljCiAgICAgICovCiAgICAgIGluZm86IGZ1bmN0aW9uIGluZm8oKSB7CiAgICAgICAgdmFyIF9jb25zb2xlNDsKCiAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKShERVBSRUNBVElPTl9NRVNTQUdFLCBmYWxzZSwgewogICAgICAgICAgaWQ6IERFUFJFQ0FUSU9OX0lELAogICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICB1cmw6IERFUFJFQ0FUSU9OX1VSTAogICAgICAgIH0pKTsKICAgICAgICByZXR1cm4gKF9jb25zb2xlNCA9IGNvbnNvbGUpLmluZm8uYXBwbHkoX2NvbnNvbGU0LCBhcmd1bWVudHMpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGUKICAgICAgfSwKCiAgICAgIC8qKgogICAgICBMb2dzIHRoZSBhcmd1bWVudHMgdG8gdGhlIGNvbnNvbGUgaW4gYmx1ZSB0ZXh0LgogICAgICBZb3UgY2FuIHBhc3MgYXMgbWFueSBhcmd1bWVudHMgYXMgeW91IHdhbnQgYW5kIHRoZXkgd2lsbCBiZSBqb2luZWQgdG9nZXRoZXIgd2l0aCBhIHNwYWNlLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICB2YXIgZm9vID0gMTsKICAgICAgRW1iZXIuTG9nZ2VyLmRlYnVnKCdsb2cgdmFsdWUgb2YgZm9vOicsIGZvbyk7CiAgICAgIC8vICJsb2cgdmFsdWUgb2YgZm9vOiAxIiB3aWxsIGJlIHByaW50ZWQgdG8gdGhlIGNvbnNvbGUKICAgICAgYGBgCiAgICAgIEBtZXRob2QgZGVidWcKICAgICAgQGZvciBFbWJlci5Mb2dnZXIKICAgICAgQHBhcmFtIHsqfSBhcmd1bWVudHMKICAgICAgQHB1YmxpYwogICAgICAqLwogICAgICBkZWJ1ZzogZnVuY3Rpb24gZGVidWcoKSB7CiAgICAgICAgdmFyIF9jb25zb2xlNjsKCiAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKShERVBSRUNBVElPTl9NRVNTQUdFLCBmYWxzZSwgewogICAgICAgICAgaWQ6IERFUFJFQ0FUSU9OX0lELAogICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICB1cmw6IERFUFJFQ0FUSU9OX1VSTAogICAgICAgIH0pKTsKICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovCgogICAgICAgIGlmIChjb25zb2xlLmRlYnVnKSB7CiAgICAgICAgICB2YXIgX2NvbnNvbGU1OwoKICAgICAgICAgIHJldHVybiAoX2NvbnNvbGU1ID0gY29uc29sZSkuZGVidWcuYXBwbHkoX2NvbnNvbGU1LCBhcmd1bWVudHMpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIChfY29uc29sZTYgPSBjb25zb2xlKS5pbmZvLmFwcGx5KF9jb25zb2xlNiwgYXJndW1lbnRzKTsKICAgICAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWNvbnNvbGUgKi8KICAgICAgfSwKCiAgICAgIC8qKgogICAgICBJZiB0aGUgdmFsdWUgcGFzc2VkIGludG8gYEVtYmVyLkxvZ2dlci5hc3NlcnRgIGlzIG5vdCB0cnV0aHkgaXQgd2lsbCB0aHJvdyBhbiBlcnJvciB3aXRoIGEgc3RhY2sgdHJhY2UuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIEVtYmVyLkxvZ2dlci5hc3NlcnQodHJ1ZSk7IC8vIHVuZGVmaW5lZAogICAgICBFbWJlci5Mb2dnZXIuYXNzZXJ0KHRydWUgPT09IGZhbHNlKTsgLy8gVGhyb3dzIGFuIEFzc2VydGlvbiBmYWlsZWQgZXJyb3IuCiAgICAgIEVtYmVyLkxvZ2dlci5hc3NlcnQodHJ1ZSA9PT0gZmFsc2UsICdTb21ldGhpbmcgaW52YWxpZCcpOyAvLyBUaHJvd3MgYW4gQXNzZXJ0aW9uIGZhaWxlZCBlcnJvciB3aXRoIG1lc3NhZ2UuCiAgICAgIGBgYAogICAgICBAbWV0aG9kIGFzc2VydAogICAgICBAZm9yIEVtYmVyLkxvZ2dlcgogICAgICBAcGFyYW0ge0Jvb2xlYW59IGJvb2wgVmFsdWUgdG8gdGVzdAogICAgICBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBBc3NlcnRpb24gbWVzc2FnZSBvbiBmYWlsZWQKICAgICAgQHB1YmxpYwogICAgICAqLwogICAgICBhc3NlcnQ6IGZ1bmN0aW9uIGFzc2VydCgpIHsKICAgICAgICB2YXIgX2NvbnNvbGU3OwoKICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKERFUFJFQ0FUSU9OX01FU1NBR0UsIGZhbHNlLCB7CiAgICAgICAgICBpZDogREVQUkVDQVRJT05fSUQsCiAgICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICAgIHVybDogREVQUkVDQVRJT05fVVJMCiAgICAgICAgfSkpOwogICAgICAgIHJldHVybiAoX2NvbnNvbGU3ID0gY29uc29sZSkuYXNzZXJ0LmFwcGx5KF9jb25zb2xlNywgYXJndW1lbnRzKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlCiAgICAgIH0KICAgIH07CiAgfQoKICB2YXIgX2RlZmF1bHQgPSBERVBSRUNBVEVEX0xPR0dFUjsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL2NvbnRhaW5lci9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9vd25lciIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL3BvbHlmaWxscyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9vd25lciwgX3V0aWxzLCBfZGVidWcsIF9wb2x5ZmlsbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLnByaXZhdGl6ZSA9IHByaXZhdGl6ZTsKICBfZXhwb3J0cy5GQUNUT1JZX0ZPUiA9IF9leHBvcnRzLkNvbnRhaW5lciA9IF9leHBvcnRzLlJlZ2lzdHJ5ID0gdm9pZCAwOwogIHZhciBsZWFrVHJhY2tpbmc7CiAgdmFyIGNvbnRhaW5lcnM7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICAvLyByZXF1aXJlcyB2OAogICAgLy8gY2hyb21lIC0tanMtZmxhZ3M9Ii0tYWxsb3ctbmF0aXZlcy1zeW50YXggLS1leHBvc2UtZ2MiCiAgICAvLyBub2RlIC0tYWxsb3ctbmF0aXZlcy1zeW50YXggLS1leHBvc2UtZ2MKICAgIHRyeSB7CiAgICAgIGlmICh0eXBlb2YgZ2MgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICBsZWFrVHJhY2tpbmcgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAvLyBhdm9pZCBzeW50YXggZXJyb3JzIHdoZW4gLS1hbGxvdy1uYXRpdmVzLXN5bnRheCBub3QgcHJlc2VudAogICAgICAgICAgdmFyIEdldFdlYWtTZXRWYWx1ZXMgPSBuZXcgRnVuY3Rpb24oJ3dlYWtTZXQnLCAncmV0dXJuICVHZXRXZWFrU2V0VmFsdWVzKHdlYWtTZXQsIDApJyk7CiAgICAgICAgICBjb250YWluZXJzID0gbmV3IFdlYWtTZXQoKTsKICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIGhhc0NvbnRhaW5lcnM6IGZ1bmN0aW9uIGhhc0NvbnRhaW5lcnMoKSB7CiAgICAgICAgICAgICAgZ2MoKTsKICAgICAgICAgICAgICByZXR1cm4gR2V0V2Vha1NldFZhbHVlcyhjb250YWluZXJzKS5sZW5ndGggPiAwOwogICAgICAgICAgICB9LAogICAgICAgICAgICByZXNldDogZnVuY3Rpb24gcmVzZXQoKSB7CiAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IEdldFdlYWtTZXRWYWx1ZXMoY29udGFpbmVycyk7CgogICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmFsdWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBjb250YWluZXJzLmRlbGV0ZSh2YWx1ZXNbaV0pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfTsKICAgICAgICB9KCk7CiAgICAgIH0KICAgIH0gY2F0Y2ggKGUpIHsvLyBpZ25vcmUKICAgIH0KICB9CiAgLyoqCiAgIEEgY29udGFpbmVyIHVzZWQgdG8gaW5zdGFudGlhdGUgYW5kIGNhY2hlIG9iamVjdHMuCiAgCiAgIEV2ZXJ5IGBDb250YWluZXJgIG11c3QgYmUgYXNzb2NpYXRlZCB3aXRoIGEgYFJlZ2lzdHJ5YCwgd2hpY2ggaXMgcmVmZXJlbmNlZAogICB0byBkZXRlcm1pbmUgdGhlIGZhY3RvcnkgYW5kIG9wdGlvbnMgdGhhdCBzaG91bGQgYmUgdXNlZCB0byBpbnN0YW50aWF0ZQogICBvYmplY3RzLgogIAogICBUaGUgcHVibGljIEFQSSBmb3IgYENvbnRhaW5lcmAgaXMgc3RpbGwgaW4gZmx1eCBhbmQgc2hvdWxkIG5vdCBiZSBjb25zaWRlcmVkCiAgIHN0YWJsZS4KICAKICAgQHByaXZhdGUKICAgQGNsYXNzIENvbnRhaW5lcgogICAqLwoKCiAgdmFyIENvbnRhaW5lciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENvbnRhaW5lcihyZWdpc3RyeSwgb3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICB0aGlzLnJlZ2lzdHJ5ID0gcmVnaXN0cnk7CiAgICAgIHRoaXMub3duZXIgPSBvcHRpb25zLm93bmVyIHx8IG51bGw7CiAgICAgIHRoaXMuY2FjaGUgPSAoMCwgX3V0aWxzLmRpY3Rpb25hcnkpKG9wdGlvbnMuY2FjaGUgfHwgbnVsbCk7CiAgICAgIHRoaXMuZmFjdG9yeU1hbmFnZXJDYWNoZSA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkob3B0aW9ucy5mYWN0b3J5TWFuYWdlckNhY2hlIHx8IG51bGwpOwogICAgICB0aGlzLmlzRGVzdHJveWVkID0gZmFsc2U7CiAgICAgIHRoaXMuaXNEZXN0cm95aW5nID0gZmFsc2U7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgdGhpcy52YWxpZGF0aW9uQ2FjaGUgPSAoMCwgX3V0aWxzLmRpY3Rpb25hcnkpKG9wdGlvbnMudmFsaWRhdGlvbkNhY2hlIHx8IG51bGwpOwoKICAgICAgICBpZiAoY29udGFpbmVycyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBjb250YWluZXJzLmFkZCh0aGlzKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgIEBwcml2YXRlCiAgICAgQHByb3BlcnR5IHJlZ2lzdHJ5CiAgICAgQHR5cGUgUmVnaXN0cnkKICAgICBAc2luY2UgMS4xMS4wCiAgICAgKi8KCiAgICAvKioKICAgICBAcHJpdmF0ZQogICAgIEBwcm9wZXJ0eSBjYWNoZQogICAgIEB0eXBlIEluaGVyaXRpbmdEaWN0CiAgICAgKi8KCiAgICAvKioKICAgICBAcHJpdmF0ZQogICAgIEBwcm9wZXJ0eSB2YWxpZGF0aW9uQ2FjaGUKICAgICBAdHlwZSBJbmhlcml0aW5nRGljdAogICAgICovCgogICAgLyoqCiAgICAgR2l2ZW4gYSBmdWxsTmFtZSByZXR1cm4gYSBjb3JyZXNwb25kaW5nIGluc3RhbmNlLgogICAgICBUaGUgZGVmYXVsdCBiZWhhdmlvciBpcyBmb3IgbG9va3VwIHRvIHJldHVybiBhIHNpbmdsZXRvbiBpbnN0YW5jZS4KICAgICBUaGUgc2luZ2xldG9uIGlzIHNjb3BlZCB0byB0aGUgY29udGFpbmVyLCBhbGxvd2luZyBtdWx0aXBsZSBjb250YWluZXJzCiAgICAgdG8gYWxsIGhhdmUgdGhlaXIgb3duIGxvY2FsbHkgc2NvcGVkIHNpbmdsZXRvbnMuCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoKTsKICAgICBsZXQgY29udGFpbmVyID0gcmVnaXN0cnkuY29udGFpbmVyKCk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdhcGk6dHdpdHRlcicsIFR3aXR0ZXIpOwogICAgICBsZXQgdHdpdHRlciA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJyk7CiAgICAgIHR3aXR0ZXIgaW5zdGFuY2VvZiBUd2l0dGVyOyAvLyA9PiB0cnVlCiAgICAgIC8vIGJ5IGRlZmF1bHQgdGhlIGNvbnRhaW5lciB3aWxsIHJldHVybiBzaW5nbGV0b25zCiAgICAgbGV0IHR3aXR0ZXIyID0gY29udGFpbmVyLmxvb2t1cCgnYXBpOnR3aXR0ZXInKTsKICAgICB0d2l0dGVyMiBpbnN0YW5jZW9mIFR3aXR0ZXI7IC8vID0+IHRydWUKICAgICAgdHdpdHRlciA9PT0gdHdpdHRlcjI7IC8vPT4gdHJ1ZQogICAgIGBgYAogICAgICBJZiBzaW5nbGV0b25zIGFyZSBub3Qgd2FudGVkLCBhbiBvcHRpb25hbCBmbGFnIGNhbiBiZSBwcm92aWRlZCBhdCBsb29rdXAuCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoKTsKICAgICBsZXQgY29udGFpbmVyID0gcmVnaXN0cnkuY29udGFpbmVyKCk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdhcGk6dHdpdHRlcicsIFR3aXR0ZXIpOwogICAgICBsZXQgdHdpdHRlciA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJywgeyBzaW5nbGV0b246IGZhbHNlIH0pOwogICAgIGxldCB0d2l0dGVyMiA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJywgeyBzaW5nbGV0b246IGZhbHNlIH0pOwogICAgICB0d2l0dGVyID09PSB0d2l0dGVyMjsgLy89PiBmYWxzZQogICAgIGBgYAogICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2QgbG9va3VwCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXQogICAgIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5zb3VyY2VdIFRoZSBmdWxsbmFtZSBvZiB0aGUgcmVxdWVzdCBzb3VyY2UgKHVzZWQgZm9yIGxvY2FsIGxvb2t1cCkKICAgICBAcmV0dXJuIHthbnl9CiAgICAgKi8KCgogICAgdmFyIF9wcm90byA9IENvbnRhaW5lci5wcm90b3R5cGU7CgogICAgX3Byb3RvLmxvb2t1cCA9IGZ1bmN0aW9uIGxvb2t1cChmdWxsTmFtZSwgb3B0aW9ucykgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc0Rlc3Ryb3llZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdleHBlY3RlZCBjb250YWluZXIgbm90IHRvIGJlIGRlc3Ryb3llZCcsICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMucmVnaXN0cnkuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdmdWxsTmFtZSBtdXN0IGJlIGEgcHJvcGVyIGZ1bGwgbmFtZScsIHRoaXMucmVnaXN0cnkuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkpOwogICAgICByZXR1cm4gX2xvb2t1cCh0aGlzLCB0aGlzLnJlZ2lzdHJ5Lm5vcm1hbGl6ZShmdWxsTmFtZSksIG9wdGlvbnMpOwogICAgfQogICAgLyoqCiAgICAgQSBkZXB0aCBmaXJzdCB0cmF2ZXJzYWwsIGRlc3Ryb3lpbmcgdGhlIGNvbnRhaW5lciwgaXRzIGRlc2NlbmRhbnQgY29udGFpbmVycyBhbmQgYWxsCiAgICAgdGhlaXIgbWFuYWdlZCBvYmplY3RzLgogICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2QgZGVzdHJveQogICAgICovCiAgICA7CgogICAgX3Byb3RvLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICBkZXN0cm95RGVzdHJveWFibGVzKHRoaXMpOwogICAgICB0aGlzLmlzRGVzdHJveWluZyA9IHRydWU7CiAgICB9OwoKICAgIF9wcm90by5maW5hbGl6ZURlc3Ryb3kgPSBmdW5jdGlvbiBmaW5hbGl6ZURlc3Ryb3koKSB7CiAgICAgIHJlc2V0Q2FjaGUodGhpcyk7CiAgICAgIHRoaXMuaXNEZXN0cm95ZWQgPSB0cnVlOwogICAgfQogICAgLyoqCiAgICAgQ2xlYXIgZWl0aGVyIHRoZSBlbnRpcmUgY2FjaGUgb3IganVzdCB0aGUgY2FjaGUgZm9yIGEgcGFydGljdWxhciBrZXkuCiAgICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIHJlc2V0CiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lIG9wdGlvbmFsIGtleSB0byByZXNldDsgaWYgbWlzc2luZywgcmVzZXRzIGV2ZXJ5dGhpbmcKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoZnVsbE5hbWUpIHsKICAgICAgaWYgKHRoaXMuaXNEZXN0cm95ZWQpIHJldHVybjsKCiAgICAgIGlmIChmdWxsTmFtZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZGVzdHJveURlc3Ryb3lhYmxlcyh0aGlzKTsKICAgICAgICByZXNldENhY2hlKHRoaXMpOwogICAgICB9IGVsc2UgewogICAgICAgIHJlc2V0TWVtYmVyKHRoaXMsIHRoaXMucmVnaXN0cnkubm9ybWFsaXplKGZ1bGxOYW1lKSk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgIFJldHVybnMgYW4gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gcHJvdmlkZSBhbiBvd25lciB0byBhCiAgICAgbWFudWFsbHkgY3JlYXRlZCBpbnN0YW5jZS4KICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIG93bmVySW5qZWN0aW9uCiAgICAgQHJldHVybnMgeyBPYmplY3QgfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ub3duZXJJbmplY3Rpb24gPSBmdW5jdGlvbiBvd25lckluamVjdGlvbigpIHsKICAgICAgdmFyIF9yZWY7CgogICAgICByZXR1cm4gX3JlZiA9IHt9LCBfcmVmW19vd25lci5PV05FUl0gPSB0aGlzLm93bmVyLCBfcmVmOwogICAgfQogICAgLyoqCiAgICAgR2l2ZW4gYSBmdWxsTmFtZSwgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIGZhY3RvcnkuIFRoZSBjb25zdW1lciBvZiB0aGUgZmFjdG9yeQogICAgIGlzIHJlc3BvbnNpYmxlIGZvciB0aGUgZGVzdHJ1Y3Rpb24gb2YgYW55IGZhY3RvcnkgaW5zdGFuY2VzLCBhcyB0aGVyZSBpcyBubwogICAgIHdheSBmb3IgdGhlIGNvbnRhaW5lciB0byBlbnN1cmUgaW5zdGFuY2VzIGFyZSBkZXN0cm95ZWQgd2hlbiBpdCBpdHNlbGYgaXMKICAgICBkZXN0cm95ZWQuCiAgICAgIEBwdWJsaWMKICAgICBAbWV0aG9kIGZhY3RvcnlGb3IKICAgICBAcGFyYW0ge1N0cmluZ30gZnVsbE5hbWUKICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdCiAgICAgQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLnNvdXJjZV0gVGhlIGZ1bGxuYW1lIG9mIHRoZSByZXF1ZXN0IHNvdXJjZSAodXNlZCBmb3IgbG9jYWwgbG9va3VwKQogICAgIEByZXR1cm4ge2FueX0KICAgICAqLwogICAgOwoKICAgIF9wcm90by5mYWN0b3J5Rm9yID0gZnVuY3Rpb24gZmFjdG9yeUZvcihmdWxsTmFtZSwgb3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc0Rlc3Ryb3llZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdleHBlY3RlZCBjb250YWluZXIgbm90IHRvIGJlIGRlc3Ryb3llZCcsICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgIHZhciBub3JtYWxpemVkTmFtZSA9IHRoaXMucmVnaXN0cnkubm9ybWFsaXplKGZ1bGxOYW1lKTsKICAgICAgKGZhbHNlICYmICEodGhpcy5yZWdpc3RyeS5pc1ZhbGlkRnVsbE5hbWUobm9ybWFsaXplZE5hbWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2Z1bGxOYW1lIG11c3QgYmUgYSBwcm9wZXIgZnVsbCBuYW1lJywgdGhpcy5yZWdpc3RyeS5pc1ZhbGlkRnVsbE5hbWUobm9ybWFsaXplZE5hbWUpKSk7CiAgICAgIChmYWxzZSAmJiAhKGZhbHNlCiAgICAgIC8qIEVNQkVSX01PRFVMRV9VTklGSUNBVElPTiAqLwogICAgICB8fCAhb3B0aW9ucy5uYW1lc3BhY2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnRU1CRVJfTU9EVUxFX1VOSUZJQ0FUSU9OIG11c3QgYmUgZW5hYmxlZCB0byBwYXNzIGEgbmFtZXNwYWNlIG9wdGlvbiB0byBmYWN0b3J5Rm9yJywgZmFsc2UgfHwgIW9wdGlvbnMubmFtZXNwYWNlKSk7CgogICAgICBpZiAob3B0aW9ucy5zb3VyY2UgfHwgb3B0aW9ucy5uYW1lc3BhY2UpIHsKICAgICAgICBub3JtYWxpemVkTmFtZSA9IHRoaXMucmVnaXN0cnkuZXhwYW5kTG9jYWxMb29rdXAoZnVsbE5hbWUsIG9wdGlvbnMpOwoKICAgICAgICBpZiAoIW5vcm1hbGl6ZWROYW1lKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gX2ZhY3RvcnlGb3IodGhpcywgbm9ybWFsaXplZE5hbWUsIGZ1bGxOYW1lKTsKICAgIH07CgogICAgcmV0dXJuIENvbnRhaW5lcjsKICB9KCk7CgogIF9leHBvcnRzLkNvbnRhaW5lciA9IENvbnRhaW5lcjsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIENvbnRhaW5lci5fbGVha1RyYWNraW5nID0gbGVha1RyYWNraW5nOwogIH0KICAvKgogICAqIFdyYXAgYSBmYWN0b3J5IG1hbmFnZXIgaW4gYSBwcm94eSB3aGljaCB3aWxsIG5vdCBwZXJtaXQgcHJvcGVydGllcyB0byBiZQogICAqIHNldCBvbiB0aGUgbWFuYWdlci4KICAgKi8KCgogIGZ1bmN0aW9uIHdyYXBNYW5hZ2VySW5EZXByZWNhdGlvblByb3h5KG1hbmFnZXIpIHsKICAgIGlmIChfdXRpbHMuSEFTX05BVElWRV9QUk9YWSkgewogICAgICB2YXIgdmFsaWRhdG9yID0gewogICAgICAgIHNldDogZnVuY3Rpb24gc2V0KF9vYmosIHByb3ApIHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiWW91IGF0dGVtcHRlZCB0byBzZXQgXCIiICsgcHJvcCArICJcIiBvbiBhIGZhY3RvcnkgbWFuYWdlciBjcmVhdGVkIGJ5IGNvbnRhaW5lciNmYWN0b3J5Rm9yLiBBIGZhY3RvcnkgbWFuYWdlciBpcyBhIHJlYWQtb25seSBjb25zdHJ1Y3QuIik7CiAgICAgICAgfQogICAgICB9OyAvLyBOb3RlOgogICAgICAvLyBXZSBoYXZlIHRvIHByb3h5IGFjY2VzcyB0byB0aGUgbWFuYWdlciBoZXJlIHNvIHRoYXQgcHJpdmF0ZSBwcm9wZXJ0eQogICAgICAvLyBhY2Nlc3MgZG9lc24ndCBjYXVzZSB0aGUgYWJvdmUgZXJyb3JzIHRvIG9jY3VyLgoKICAgICAgdmFyIG0gPSBtYW5hZ2VyOwogICAgICB2YXIgcHJveGllZE1hbmFnZXIgPSB7CiAgICAgICAgY2xhc3M6IG0uY2xhc3MsCiAgICAgICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUocHJvcHMpIHsKICAgICAgICAgIHJldHVybiBtLmNyZWF0ZShwcm9wcyk7CiAgICAgICAgfQogICAgICB9OwogICAgICB2YXIgcHJveHkgPSBuZXcgUHJveHkocHJveGllZE1hbmFnZXIsIHZhbGlkYXRvcik7CiAgICAgIEZBQ1RPUllfRk9SLnNldChwcm94eSwgbWFuYWdlcik7CiAgICB9CgogICAgcmV0dXJuIG1hbmFnZXI7CiAgfQoKICBmdW5jdGlvbiBpc1NpbmdsZXRvbihjb250YWluZXIsIGZ1bGxOYW1lKSB7CiAgICByZXR1cm4gY29udGFpbmVyLnJlZ2lzdHJ5LmdldE9wdGlvbihmdWxsTmFtZSwgJ3NpbmdsZXRvbicpICE9PSBmYWxzZTsKICB9CgogIGZ1bmN0aW9uIGlzSW5zdGFudGlhdGFibGUoY29udGFpbmVyLCBmdWxsTmFtZSkgewogICAgcmV0dXJuIGNvbnRhaW5lci5yZWdpc3RyeS5nZXRPcHRpb24oZnVsbE5hbWUsICdpbnN0YW50aWF0ZScpICE9PSBmYWxzZTsKICB9CgogIGZ1bmN0aW9uIF9sb29rdXAoY29udGFpbmVyLCBmdWxsTmFtZSwgb3B0aW9ucykgewogICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICBvcHRpb25zID0ge307CiAgICB9CgogICAgKGZhbHNlICYmICEoZmFsc2UKICAgIC8qIEVNQkVSX01PRFVMRV9VTklGSUNBVElPTiAqLwogICAgfHwgIW9wdGlvbnMubmFtZXNwYWNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0VNQkVSX01PRFVMRV9VTklGSUNBVElPTiBtdXN0IGJlIGVuYWJsZWQgdG8gcGFzcyBhIG5hbWVzcGFjZSBvcHRpb24gdG8gbG9va3VwJywgZmFsc2UgfHwgIW9wdGlvbnMubmFtZXNwYWNlKSk7CiAgICB2YXIgbm9ybWFsaXplZE5hbWUgPSBmdWxsTmFtZTsKCiAgICBpZiAob3B0aW9ucy5zb3VyY2UgfHwgb3B0aW9ucy5uYW1lc3BhY2UpIHsKICAgICAgbm9ybWFsaXplZE5hbWUgPSBjb250YWluZXIucmVnaXN0cnkuZXhwYW5kTG9jYWxMb29rdXAoZnVsbE5hbWUsIG9wdGlvbnMpOwoKICAgICAgaWYgKCFub3JtYWxpemVkTmFtZSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgfQoKICAgIGlmIChvcHRpb25zLnNpbmdsZXRvbiAhPT0gZmFsc2UpIHsKICAgICAgdmFyIGNhY2hlZCA9IGNvbnRhaW5lci5jYWNoZVtub3JtYWxpemVkTmFtZV07CgogICAgICBpZiAoY2FjaGVkICE9PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gY2FjaGVkOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGluc3RhbnRpYXRlRmFjdG9yeShjb250YWluZXIsIG5vcm1hbGl6ZWROYW1lLCBmdWxsTmFtZSwgb3B0aW9ucyk7CiAgfQoKICBmdW5jdGlvbiBfZmFjdG9yeUZvcihjb250YWluZXIsIG5vcm1hbGl6ZWROYW1lLCBmdWxsTmFtZSkgewogICAgdmFyIGNhY2hlZCA9IGNvbnRhaW5lci5mYWN0b3J5TWFuYWdlckNhY2hlW25vcm1hbGl6ZWROYW1lXTsKCiAgICBpZiAoY2FjaGVkICE9PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuIGNhY2hlZDsKICAgIH0KCiAgICB2YXIgZmFjdG9yeSA9IGNvbnRhaW5lci5yZWdpc3RyeS5yZXNvbHZlKG5vcm1hbGl6ZWROYW1lKTsKCiAgICBpZiAoZmFjdG9yeSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICAmJiBmYWN0b3J5ICYmIHR5cGVvZiBmYWN0b3J5Ll9vbkxvb2t1cCA9PT0gJ2Z1bmN0aW9uJykgewogICAgICBmYWN0b3J5Ll9vbkxvb2t1cChmdWxsTmFtZSk7CiAgICB9CgogICAgdmFyIG1hbmFnZXIgPSBuZXcgRmFjdG9yeU1hbmFnZXIoY29udGFpbmVyLCBmYWN0b3J5LCBmdWxsTmFtZSwgbm9ybWFsaXplZE5hbWUpOwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBtYW5hZ2VyID0gd3JhcE1hbmFnZXJJbkRlcHJlY2F0aW9uUHJveHkobWFuYWdlcik7CiAgICB9CgogICAgY29udGFpbmVyLmZhY3RvcnlNYW5hZ2VyQ2FjaGVbbm9ybWFsaXplZE5hbWVdID0gbWFuYWdlcjsKICAgIHJldHVybiBtYW5hZ2VyOwogIH0KCiAgZnVuY3Rpb24gaXNTaW5nbGV0b25DbGFzcyhjb250YWluZXIsIGZ1bGxOYW1lLCBfcmVmMikgewogICAgdmFyIGluc3RhbnRpYXRlID0gX3JlZjIuaW5zdGFudGlhdGUsCiAgICAgICAgc2luZ2xldG9uID0gX3JlZjIuc2luZ2xldG9uOwogICAgcmV0dXJuIHNpbmdsZXRvbiAhPT0gZmFsc2UgJiYgIWluc3RhbnRpYXRlICYmIGlzU2luZ2xldG9uKGNvbnRhaW5lciwgZnVsbE5hbWUpICYmICFpc0luc3RhbnRpYXRhYmxlKGNvbnRhaW5lciwgZnVsbE5hbWUpOwogIH0KCiAgZnVuY3Rpb24gaXNTaW5nbGV0b25JbnN0YW5jZShjb250YWluZXIsIGZ1bGxOYW1lLCBfcmVmMykgewogICAgdmFyIGluc3RhbnRpYXRlID0gX3JlZjMuaW5zdGFudGlhdGUsCiAgICAgICAgc2luZ2xldG9uID0gX3JlZjMuc2luZ2xldG9uOwogICAgcmV0dXJuIHNpbmdsZXRvbiAhPT0gZmFsc2UgJiYgaW5zdGFudGlhdGUgIT09IGZhbHNlICYmIGlzU2luZ2xldG9uKGNvbnRhaW5lciwgZnVsbE5hbWUpICYmIGlzSW5zdGFudGlhdGFibGUoY29udGFpbmVyLCBmdWxsTmFtZSk7CiAgfQoKICBmdW5jdGlvbiBpc0ZhY3RvcnlDbGFzcyhjb250YWluZXIsIGZ1bGxuYW1lLCBfcmVmNCkgewogICAgdmFyIGluc3RhbnRpYXRlID0gX3JlZjQuaW5zdGFudGlhdGUsCiAgICAgICAgc2luZ2xldG9uID0gX3JlZjQuc2luZ2xldG9uOwogICAgcmV0dXJuIGluc3RhbnRpYXRlID09PSBmYWxzZSAmJiAoc2luZ2xldG9uID09PSBmYWxzZSB8fCAhaXNTaW5nbGV0b24oY29udGFpbmVyLCBmdWxsbmFtZSkpICYmICFpc0luc3RhbnRpYXRhYmxlKGNvbnRhaW5lciwgZnVsbG5hbWUpOwogIH0KCiAgZnVuY3Rpb24gaXNGYWN0b3J5SW5zdGFuY2UoY29udGFpbmVyLCBmdWxsTmFtZSwgX3JlZjUpIHsKICAgIHZhciBpbnN0YW50aWF0ZSA9IF9yZWY1Lmluc3RhbnRpYXRlLAogICAgICAgIHNpbmdsZXRvbiA9IF9yZWY1LnNpbmdsZXRvbjsKICAgIHJldHVybiBpbnN0YW50aWF0ZSAhPT0gZmFsc2UgJiYgKHNpbmdsZXRvbiAhPT0gZmFsc2UgfHwgaXNTaW5nbGV0b24oY29udGFpbmVyLCBmdWxsTmFtZSkpICYmIGlzSW5zdGFudGlhdGFibGUoY29udGFpbmVyLCBmdWxsTmFtZSk7CiAgfQoKICBmdW5jdGlvbiBpbnN0YW50aWF0ZUZhY3RvcnkoY29udGFpbmVyLCBub3JtYWxpemVkTmFtZSwgZnVsbE5hbWUsIG9wdGlvbnMpIHsKICAgIHZhciBmYWN0b3J5TWFuYWdlciA9IF9mYWN0b3J5Rm9yKGNvbnRhaW5lciwgbm9ybWFsaXplZE5hbWUsIGZ1bGxOYW1lKTsKCiAgICBpZiAoZmFjdG9yeU1hbmFnZXIgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm47CiAgICB9IC8vIFNvbWVDbGFzcyB7IHNpbmdsZXRvbjogdHJ1ZSwgaW5zdGFudGlhdGU6IHRydWUgfSB8IHsgc2luZ2xldG9uOiB0cnVlIH0gfCB7IGluc3RhbnRpYXRlOiB0cnVlIH0gfCB7fQogICAgLy8gQnkgZGVmYXVsdCBtYWpvcml0eSBvZiBvYmplY3RzIGZhbGwgaW50byB0aGlzIGNhc2UKCgogICAgaWYgKGlzU2luZ2xldG9uSW5zdGFuY2UoY29udGFpbmVyLCBmdWxsTmFtZSwgb3B0aW9ucykpIHsKICAgICAgcmV0dXJuIGNvbnRhaW5lci5jYWNoZVtub3JtYWxpemVkTmFtZV0gPSBmYWN0b3J5TWFuYWdlci5jcmVhdGUoKTsKICAgIH0gLy8gU29tZUNsYXNzIHsgc2luZ2xldG9uOiBmYWxzZSwgaW5zdGFudGlhdGU6IHRydWUgfQoKCiAgICBpZiAoaXNGYWN0b3J5SW5zdGFuY2UoY29udGFpbmVyLCBmdWxsTmFtZSwgb3B0aW9ucykpIHsKICAgICAgcmV0dXJuIGZhY3RvcnlNYW5hZ2VyLmNyZWF0ZSgpOwogICAgfSAvLyBTb21lQ2xhc3MgeyBzaW5nbGV0b246IHRydWUsIGluc3RhbnRpYXRlOiBmYWxzZSB9IHwgeyBpbnN0YW50aWF0ZTogZmFsc2UgfSB8IHsgc2luZ2xldG9uOiBmYWxzZSwgaW5zdGFudGlhdGlvbjogZmFsc2UgfQoKCiAgICBpZiAoaXNTaW5nbGV0b25DbGFzcyhjb250YWluZXIsIGZ1bGxOYW1lLCBvcHRpb25zKSB8fCBpc0ZhY3RvcnlDbGFzcyhjb250YWluZXIsIGZ1bGxOYW1lLCBvcHRpb25zKSkgewogICAgICByZXR1cm4gZmFjdG9yeU1hbmFnZXIuY2xhc3M7CiAgICB9CgogICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgY3JlYXRlIGZhY3RvcnknKTsKICB9CgogIGZ1bmN0aW9uIHByb2Nlc3NJbmplY3Rpb25zKGNvbnRhaW5lciwgaW5qZWN0aW9ucywgcmVzdWx0KSB7CiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgY29udGFpbmVyLnJlZ2lzdHJ5LnZhbGlkYXRlSW5qZWN0aW9ucyhpbmplY3Rpb25zKTsKICAgIH0KCiAgICB2YXIgaGFzaCA9IHJlc3VsdC5pbmplY3Rpb25zOwoKICAgIGlmIChoYXNoID09PSB1bmRlZmluZWQpIHsKICAgICAgaGFzaCA9IHJlc3VsdC5pbmplY3Rpb25zID0ge307CiAgICB9CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmplY3Rpb25zLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBfaW5qZWN0aW9ucyRpID0gaW5qZWN0aW9uc1tpXSwKICAgICAgICAgIHByb3BlcnR5ID0gX2luamVjdGlvbnMkaS5wcm9wZXJ0eSwKICAgICAgICAgIHNwZWNpZmllciA9IF9pbmplY3Rpb25zJGkuc3BlY2lmaWVyLAogICAgICAgICAgc291cmNlID0gX2luamVjdGlvbnMkaS5zb3VyY2U7CgogICAgICBpZiAoc291cmNlKSB7CiAgICAgICAgaGFzaFtwcm9wZXJ0eV0gPSBfbG9va3VwKGNvbnRhaW5lciwgc3BlY2lmaWVyLCB7CiAgICAgICAgICBzb3VyY2U6IHNvdXJjZQogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIGhhc2hbcHJvcGVydHldID0gX2xvb2t1cChjb250YWluZXIsIHNwZWNpZmllcik7CiAgICAgIH0KCiAgICAgIGlmICghcmVzdWx0LmlzRHluYW1pYykgewogICAgICAgIHJlc3VsdC5pc0R5bmFtaWMgPSAhaXNTaW5nbGV0b24oY29udGFpbmVyLCBzcGVjaWZpZXIpOwogICAgICB9CiAgICB9CiAgfQoKICBmdW5jdGlvbiBidWlsZEluamVjdGlvbnMoY29udGFpbmVyLCB0eXBlSW5qZWN0aW9ucywgaW5qZWN0aW9ucykgewogICAgdmFyIHJlc3VsdCA9IHsKICAgICAgaW5qZWN0aW9uczogdW5kZWZpbmVkLAogICAgICBpc0R5bmFtaWM6IGZhbHNlCiAgICB9OwoKICAgIGlmICh0eXBlSW5qZWN0aW9ucyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHByb2Nlc3NJbmplY3Rpb25zKGNvbnRhaW5lciwgdHlwZUluamVjdGlvbnMsIHJlc3VsdCk7CiAgICB9CgogICAgaWYgKGluamVjdGlvbnMgIT09IHVuZGVmaW5lZCkgewogICAgICBwcm9jZXNzSW5qZWN0aW9ucyhjb250YWluZXIsIGluamVjdGlvbnMsIHJlc3VsdCk7CiAgICB9CgogICAgcmV0dXJuIHJlc3VsdDsKICB9CgogIGZ1bmN0aW9uIGluamVjdGlvbnNGb3IoY29udGFpbmVyLCBmdWxsTmFtZSkgewogICAgdmFyIHJlZ2lzdHJ5ID0gY29udGFpbmVyLnJlZ2lzdHJ5OwoKICAgIHZhciBfZnVsbE5hbWUkc3BsaXQgPSBmdWxsTmFtZS5zcGxpdCgnOicpLAogICAgICAgIHR5cGUgPSBfZnVsbE5hbWUkc3BsaXRbMF07CgogICAgdmFyIHR5cGVJbmplY3Rpb25zID0gcmVnaXN0cnkuZ2V0VHlwZUluamVjdGlvbnModHlwZSk7CiAgICB2YXIgaW5qZWN0aW9ucyA9IHJlZ2lzdHJ5LmdldEluamVjdGlvbnMoZnVsbE5hbWUpOwogICAgcmV0dXJuIGJ1aWxkSW5qZWN0aW9ucyhjb250YWluZXIsIHR5cGVJbmplY3Rpb25zLCBpbmplY3Rpb25zKTsKICB9CgogIGZ1bmN0aW9uIGRlc3Ryb3lEZXN0cm95YWJsZXMoY29udGFpbmVyKSB7CiAgICB2YXIgY2FjaGUgPSBjb250YWluZXIuY2FjaGU7CiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGNhY2hlKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGtleSA9IGtleXNbaV07CiAgICAgIHZhciB2YWx1ZSA9IGNhY2hlW2tleV07CgogICAgICBpZiAodmFsdWUuZGVzdHJveSkgewogICAgICAgIHZhbHVlLmRlc3Ryb3koKTsKICAgICAgfQogICAgfQogIH0KCiAgZnVuY3Rpb24gcmVzZXRDYWNoZShjb250YWluZXIpIHsKICAgIGNvbnRhaW5lci5jYWNoZSA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CiAgICBjb250YWluZXIuZmFjdG9yeU1hbmFnZXJDYWNoZSA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CiAgfQoKICBmdW5jdGlvbiByZXNldE1lbWJlcihjb250YWluZXIsIGZ1bGxOYW1lKSB7CiAgICB2YXIgbWVtYmVyID0gY29udGFpbmVyLmNhY2hlW2Z1bGxOYW1lXTsKICAgIGRlbGV0ZSBjb250YWluZXIuZmFjdG9yeU1hbmFnZXJDYWNoZVtmdWxsTmFtZV07CgogICAgaWYgKG1lbWJlcikgewogICAgICBkZWxldGUgY29udGFpbmVyLmNhY2hlW2Z1bGxOYW1lXTsKCiAgICAgIGlmIChtZW1iZXIuZGVzdHJveSkgewogICAgICAgIG1lbWJlci5kZXN0cm95KCk7CiAgICAgIH0KICAgIH0KICB9CgogIHZhciBGQUNUT1JZX0ZPUiA9IG5ldyBXZWFrTWFwKCk7CiAgX2V4cG9ydHMuRkFDVE9SWV9GT1IgPSBGQUNUT1JZX0ZPUjsKCiAgdmFyIEZhY3RvcnlNYW5hZ2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRmFjdG9yeU1hbmFnZXIoY29udGFpbmVyLCBmYWN0b3J5LCBmdWxsTmFtZSwgbm9ybWFsaXplZE5hbWUpIHsKICAgICAgdGhpcy5jb250YWluZXIgPSBjb250YWluZXI7CiAgICAgIHRoaXMub3duZXIgPSBjb250YWluZXIub3duZXI7CiAgICAgIHRoaXMuY2xhc3MgPSBmYWN0b3J5OwogICAgICB0aGlzLmZ1bGxOYW1lID0gZnVsbE5hbWU7CiAgICAgIHRoaXMubm9ybWFsaXplZE5hbWUgPSBub3JtYWxpemVkTmFtZTsKICAgICAgdGhpcy5tYWRlVG9TdHJpbmcgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuaW5qZWN0aW9ucyA9IHVuZGVmaW5lZDsKICAgICAgRkFDVE9SWV9GT1Iuc2V0KHRoaXMsIHRoaXMpOwogICAgfQoKICAgIHZhciBfcHJvdG8yID0gRmFjdG9yeU1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzIudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgaWYgKHRoaXMubWFkZVRvU3RyaW5nID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLm1hZGVUb1N0cmluZyA9IHRoaXMuY29udGFpbmVyLnJlZ2lzdHJ5Lm1ha2VUb1N0cmluZyh0aGlzLmNsYXNzLCB0aGlzLmZ1bGxOYW1lKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMubWFkZVRvU3RyaW5nOwogICAgfTsKCiAgICBfcHJvdG8yLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShvcHRpb25zKSB7CiAgICAgIHZhciBpbmplY3Rpb25zQ2FjaGUgPSB0aGlzLmluamVjdGlvbnM7CgogICAgICBpZiAoaW5qZWN0aW9uc0NhY2hlID09PSB1bmRlZmluZWQpIHsKICAgICAgICB2YXIgX2luamVjdGlvbnNGb3IgPSBpbmplY3Rpb25zRm9yKHRoaXMuY29udGFpbmVyLCB0aGlzLm5vcm1hbGl6ZWROYW1lKSwKICAgICAgICAgICAgaW5qZWN0aW9ucyA9IF9pbmplY3Rpb25zRm9yLmluamVjdGlvbnMsCiAgICAgICAgICAgIGlzRHluYW1pYyA9IF9pbmplY3Rpb25zRm9yLmlzRHluYW1pYzsKCiAgICAgICAgaW5qZWN0aW9uc0NhY2hlID0gaW5qZWN0aW9uczsKCiAgICAgICAgaWYgKCFpc0R5bmFtaWMpIHsKICAgICAgICAgIHRoaXMuaW5qZWN0aW9ucyA9IGluamVjdGlvbnM7CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgcHJvcHMgPSBpbmplY3Rpb25zQ2FjaGU7CgogICAgICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcHJvcHMgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBpbmplY3Rpb25zQ2FjaGUsIG9wdGlvbnMpOwogICAgICB9CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgdmFyIGxhenlJbmplY3Rpb25zOwogICAgICAgIHZhciB2YWxpZGF0aW9uQ2FjaGUgPSB0aGlzLmNvbnRhaW5lci52YWxpZGF0aW9uQ2FjaGU7IC8vIEVuc3VyZSB0aGF0IGFsbCBsYXp5IGluamVjdGlvbnMgYXJlIHZhbGlkIGF0IGluc3RhbnRpYXRpb24gdGltZQoKICAgICAgICBpZiAoIXZhbGlkYXRpb25DYWNoZVt0aGlzLmZ1bGxOYW1lXSAmJiB0aGlzLmNsYXNzICYmIHR5cGVvZiB0aGlzLmNsYXNzLl9sYXp5SW5qZWN0aW9ucyA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgICAgbGF6eUluamVjdGlvbnMgPSB0aGlzLmNsYXNzLl9sYXp5SW5qZWN0aW9ucygpOwogICAgICAgICAgbGF6eUluamVjdGlvbnMgPSB0aGlzLmNvbnRhaW5lci5yZWdpc3RyeS5ub3JtYWxpemVJbmplY3Rpb25zSGFzaChsYXp5SW5qZWN0aW9ucyk7CiAgICAgICAgICB0aGlzLmNvbnRhaW5lci5yZWdpc3RyeS52YWxpZGF0ZUluamVjdGlvbnMobGF6eUluamVjdGlvbnMpOwogICAgICAgIH0KCiAgICAgICAgdmFsaWRhdGlvbkNhY2hlW3RoaXMuZnVsbE5hbWVdID0gdHJ1ZTsKICAgICAgfQoKICAgICAgaWYgKCF0aGlzLmNsYXNzLmNyZWF0ZSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiRmFpbGVkIHRvIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiAnIiArIHRoaXMubm9ybWFsaXplZE5hbWUgKyAiJy4gTW9zdCBsaWtlbHkgYW4gaW1wcm9wZXJseSBkZWZpbmVkIGNsYXNzIG9yIGFuIGludmFsaWQgbW9kdWxlIGV4cG9ydC4iKTsKICAgICAgfSAvLyByZXF1aXJlZCB0byBhbGxvdyBhY2Nlc3MgdG8gdGhpbmdzIGxpa2UKICAgICAgLy8gdGhlIGN1c3RvbWl6ZWQgdG9TdHJpbmcsIF9kZWJ1Z0NvbnRhaW5lcktleSwKICAgICAgLy8gb3duZXIsIGV0Yy4gd2l0aG91dCBhIGRvdWJsZSBleHRlbmQgYW5kIHdpdGhvdXQKICAgICAgLy8gbW9kaWZ5aW5nIHRoZSBvYmplY3RzIHByb3BlcnRpZXMKCgogICAgICBpZiAodHlwZW9mIHRoaXMuY2xhc3MuX2luaXRGYWN0b3J5ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgdGhpcy5jbGFzcy5faW5pdEZhY3RvcnkodGhpcyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gaW4gdGhlIG5vbi1FbWJlck9iamVjdCBjYXNlIHdlIG5lZWQgdG8gc3RpbGwgc2V0T3duZXIKICAgICAgICAvLyB0aGlzIGlzIHJlcXVpcmVkIGZvciBzdXBwb3J0aW5nIGdsaW1tZXIgZW52aXJvbm1lbnQgYW5kCiAgICAgICAgLy8gdGVtcGxhdGUgaW5zdGFudGlhdGlvbiB3aGljaCByZWx5IGhlYXZpbHkgb24KICAgICAgICAvLyBgb3B0aW9uc1tPV05FUl1gIGJlaW5nIHBhc3NlZCBpbnRvIGBjcmVhdGVgCiAgICAgICAgLy8gVE9ETzogY2xlYW4gdGhpcyB1cCwgYW5kIHJlbW92ZSBpbiBmdXR1cmUgdmVyc2lvbnMKICAgICAgICBpZiAob3B0aW9ucyA9PT0gdW5kZWZpbmVkIHx8IHByb3BzID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIC8vIGF2b2lkIG11dGF0aW5nIGBwcm9wc2AgaGVyZSBzaW5jZSB0aGV5IGFyZSB0aGUgY2FjaGVkIGluamVjdGlvbnMKICAgICAgICAgIHByb3BzID0gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgcHJvcHMpOwogICAgICAgIH0KCiAgICAgICAgKDAsIF9vd25lci5zZXRPd25lcikocHJvcHMsIHRoaXMub3duZXIpOwogICAgICB9CgogICAgICB2YXIgaW5zdGFuY2UgPSB0aGlzLmNsYXNzLmNyZWF0ZShwcm9wcyk7CiAgICAgIEZBQ1RPUllfRk9SLnNldChpbnN0YW5jZSwgdGhpcyk7CiAgICAgIHJldHVybiBpbnN0YW5jZTsKICAgIH07CgogICAgcmV0dXJuIEZhY3RvcnlNYW5hZ2VyOwogIH0oKTsKCiAgdmFyIFZBTElEX0ZVTExfTkFNRV9SRUdFWFAgPSAvXlteOl0rOlteOl0rJC87CiAgLyoqCiAgIEEgcmVnaXN0cnkgdXNlZCB0byBzdG9yZSBmYWN0b3J5IGFuZCBvcHRpb24gaW5mb3JtYXRpb24ga2V5ZWQKICAgYnkgdHlwZS4KICAKICAgQSBgUmVnaXN0cnlgIHN0b3JlcyB0aGUgZmFjdG9yeSBhbmQgb3B0aW9uIGluZm9ybWF0aW9uIG5lZWRlZCBieSBhCiAgIGBDb250YWluZXJgIHRvIGluc3RhbnRpYXRlIGFuZCBjYWNoZSBvYmplY3RzLgogIAogICBUaGUgQVBJIGZvciBgUmVnaXN0cnlgIGlzIHN0aWxsIGluIGZsdXggYW5kIHNob3VsZCBub3QgYmUgY29uc2lkZXJlZCBzdGFibGUuCiAgCiAgIEBwcml2YXRlCiAgIEBjbGFzcyBSZWdpc3RyeQogICBAc2luY2UgMS4xMS4wCiAgKi8KCiAgdmFyIFJlZ2lzdHJ5ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUmVnaXN0cnkob3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICB0aGlzLmZhbGxiYWNrID0gb3B0aW9ucy5mYWxsYmFjayB8fCBudWxsOwogICAgICB0aGlzLnJlc29sdmVyID0gb3B0aW9ucy5yZXNvbHZlciB8fCBudWxsOwogICAgICB0aGlzLnJlZ2lzdHJhdGlvbnMgPSAoMCwgX3V0aWxzLmRpY3Rpb25hcnkpKG9wdGlvbnMucmVnaXN0cmF0aW9ucyB8fCBudWxsKTsKICAgICAgdGhpcy5fdHlwZUluamVjdGlvbnMgPSAoMCwgX3V0aWxzLmRpY3Rpb25hcnkpKG51bGwpOwogICAgICB0aGlzLl9pbmplY3Rpb25zID0gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgICAgdGhpcy5fbG9jYWxMb29rdXBDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHRoaXMuX25vcm1hbGl6ZUNhY2hlID0gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgICAgdGhpcy5fcmVzb2x2ZUNhY2hlID0gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgICAgdGhpcy5fZmFpbFNldCA9IG5ldyBTZXQoKTsKICAgICAgdGhpcy5fb3B0aW9ucyA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CiAgICAgIHRoaXMuX3R5cGVPcHRpb25zID0gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgIH0KICAgIC8qKgogICAgIEEgYmFja3VwIHJlZ2lzdHJ5IGZvciByZXNvbHZpbmcgcmVnaXN0cmF0aW9ucyB3aGVuIG5vIG1hdGNoZXMgY2FuIGJlIGZvdW5kLgogICAgICAgIEBwcml2YXRlCiAgICAgQHByb3BlcnR5IGZhbGxiYWNrCiAgICAgQHR5cGUgUmVnaXN0cnkKICAgICAqLwoKICAgIC8qKgogICAgIEFuIG9iamVjdCB0aGF0IGhhcyBhIGByZXNvbHZlYCBtZXRob2QgdGhhdCByZXNvbHZlcyBhIG5hbWUuCiAgICAgICAgQHByaXZhdGUKICAgICBAcHJvcGVydHkgcmVzb2x2ZXIKICAgICBAdHlwZSBSZXNvbHZlcgogICAgICovCgogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICBAcHJvcGVydHkgcmVnaXN0cmF0aW9ucwogICAgIEB0eXBlIEluaGVyaXRpbmdEaWN0CiAgICAgKi8KCiAgICAvKioKICAgICBAcHJpdmF0ZQogICAgICAgIEBwcm9wZXJ0eSBfdHlwZUluamVjdGlvbnMKICAgICBAdHlwZSBJbmhlcml0aW5nRGljdAogICAgICovCgogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICAgICBAcHJvcGVydHkgX2luamVjdGlvbnMKICAgICBAdHlwZSBJbmhlcml0aW5nRGljdAogICAgICovCgogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICAgICBAcHJvcGVydHkgX25vcm1hbGl6ZUNhY2hlCiAgICAgQHR5cGUgSW5oZXJpdGluZ0RpY3QKICAgICAqLwoKICAgIC8qKgogICAgIEBwcml2YXRlCiAgICAgICAgQHByb3BlcnR5IF9yZXNvbHZlQ2FjaGUKICAgICBAdHlwZSBJbmhlcml0aW5nRGljdAogICAgICovCgogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICAgICBAcHJvcGVydHkgX29wdGlvbnMKICAgICBAdHlwZSBJbmhlcml0aW5nRGljdAogICAgICovCgogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICAgICBAcHJvcGVydHkgX3R5cGVPcHRpb25zCiAgICAgQHR5cGUgSW5oZXJpdGluZ0RpY3QKICAgICAqLwoKICAgIC8qKgogICAgIENyZWF0ZXMgYSBjb250YWluZXIgYmFzZWQgb24gdGhpcyByZWdpc3RyeS4KICAgICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2QgY29udGFpbmVyCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICBAcmV0dXJuIHtDb250YWluZXJ9IGNyZWF0ZWQgY29udGFpbmVyCiAgICAgKi8KCgogICAgdmFyIF9wcm90bzMgPSBSZWdpc3RyeS5wcm90b3R5cGU7CgogICAgX3Byb3RvMy5jb250YWluZXIgPSBmdW5jdGlvbiBjb250YWluZXIob3B0aW9ucykgewogICAgICByZXR1cm4gbmV3IENvbnRhaW5lcih0aGlzLCBvcHRpb25zKTsKICAgIH0KICAgIC8qKgogICAgIFJlZ2lzdGVycyBhIGZhY3RvcnkgZm9yIGxhdGVyIGluamVjdGlvbi4KICAgICAgICBFeGFtcGxlOgogICAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoKTsKICAgICAgICByZWdpc3RyeS5yZWdpc3RlcignbW9kZWw6dXNlcicsIFBlcnNvbiwge3NpbmdsZXRvbjogZmFsc2UgfSk7CiAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJ2ZydWl0OmZhdm9yaXRlJywgT3JhbmdlKTsKICAgICByZWdpc3RyeS5yZWdpc3RlcignY29tbXVuaWNhdGlvbjptYWluJywgRW1haWwsIHtzaW5nbGV0b246IGZhbHNlfSk7CiAgICAgYGBgCiAgICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIHJlZ2lzdGVyCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHBhcmFtIHtGdW5jdGlvbn0gZmFjdG9yeQogICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zLnJlZ2lzdGVyID0gZnVuY3Rpb24gcmVnaXN0ZXIoZnVsbE5hbWUsIGZhY3RvcnksIG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgfQoKICAgICAgKGZhbHNlICYmICEodGhpcy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2Z1bGxOYW1lIG11c3QgYmUgYSBwcm9wZXIgZnVsbCBuYW1lJywgdGhpcy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSk7CiAgICAgIChmYWxzZSAmJiAhKGZhY3RvcnkgIT09IHVuZGVmaW5lZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJBdHRlbXB0aW5nIHRvIHJlZ2lzdGVyIGFuIHVua25vd24gZmFjdG9yeTogJyIgKyBmdWxsTmFtZSArICInIiwgZmFjdG9yeSAhPT0gdW5kZWZpbmVkKSk7CiAgICAgIHZhciBub3JtYWxpemVkTmFtZSA9IHRoaXMubm9ybWFsaXplKGZ1bGxOYW1lKTsKICAgICAgKGZhbHNlICYmICEoIXRoaXMuX3Jlc29sdmVDYWNoZVtub3JtYWxpemVkTmFtZV0pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IHJlLXJlZ2lzdGVyOiAnIiArIGZ1bGxOYW1lICsgIicsIGFzIGl0IGhhcyBhbHJlYWR5IGJlZW4gcmVzb2x2ZWQuIiwgIXRoaXMuX3Jlc29sdmVDYWNoZVtub3JtYWxpemVkTmFtZV0pKTsKCiAgICAgIHRoaXMuX2ZhaWxTZXQuZGVsZXRlKG5vcm1hbGl6ZWROYW1lKTsKCiAgICAgIHRoaXMucmVnaXN0cmF0aW9uc1tub3JtYWxpemVkTmFtZV0gPSBmYWN0b3J5OwogICAgICB0aGlzLl9vcHRpb25zW25vcm1hbGl6ZWROYW1lXSA9IG9wdGlvbnM7CiAgICB9CiAgICAvKioKICAgICBVbnJlZ2lzdGVyIGEgZnVsbE5hbWUKICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJ21vZGVsOnVzZXInLCBVc2VyKTsKICAgICAgICByZWdpc3RyeS5yZXNvbHZlKCdtb2RlbDp1c2VyJykuY3JlYXRlKCkgaW5zdGFuY2VvZiBVc2VyIC8vPT4gdHJ1ZQogICAgICAgIHJlZ2lzdHJ5LnVucmVnaXN0ZXIoJ21vZGVsOnVzZXInKQogICAgIHJlZ2lzdHJ5LnJlc29sdmUoJ21vZGVsOnVzZXInKSA9PT0gdW5kZWZpbmVkIC8vPT4gdHJ1ZQogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCB1bnJlZ2lzdGVyCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zLnVucmVnaXN0ZXIgPSBmdW5jdGlvbiB1bnJlZ2lzdGVyKGZ1bGxOYW1lKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdmdWxsTmFtZSBtdXN0IGJlIGEgcHJvcGVyIGZ1bGwgbmFtZScsIHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkpOwogICAgICB2YXIgbm9ybWFsaXplZE5hbWUgPSB0aGlzLm5vcm1hbGl6ZShmdWxsTmFtZSk7CiAgICAgIHRoaXMuX2xvY2FsTG9va3VwQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBkZWxldGUgdGhpcy5yZWdpc3RyYXRpb25zW25vcm1hbGl6ZWROYW1lXTsKICAgICAgZGVsZXRlIHRoaXMuX3Jlc29sdmVDYWNoZVtub3JtYWxpemVkTmFtZV07CiAgICAgIGRlbGV0ZSB0aGlzLl9vcHRpb25zW25vcm1hbGl6ZWROYW1lXTsKCiAgICAgIHRoaXMuX2ZhaWxTZXQuZGVsZXRlKG5vcm1hbGl6ZWROYW1lKTsKICAgIH0KICAgIC8qKgogICAgIEdpdmVuIGEgZnVsbE5hbWUgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIGZhY3RvcnkuCiAgICAgICAgQnkgZGVmYXVsdCBgcmVzb2x2ZWAgd2lsbCByZXRyaWV2ZSB0aGUgZmFjdG9yeSBmcm9tCiAgICAgdGhlIHJlZ2lzdHJ5LgogICAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoKTsKICAgICByZWdpc3RyeS5yZWdpc3RlcignYXBpOnR3aXR0ZXInLCBUd2l0dGVyKTsKICAgICAgICByZWdpc3RyeS5yZXNvbHZlKCdhcGk6dHdpdHRlcicpIC8vID0+IFR3aXR0ZXIKICAgICBgYGAKICAgICAgICBPcHRpb25hbGx5IHRoZSByZWdpc3RyeSBjYW4gYmUgcHJvdmlkZWQgd2l0aCBhIGN1c3RvbSByZXNvbHZlci4KICAgICBJZiBwcm92aWRlZCwgYHJlc29sdmVgIHdpbGwgZmlyc3QgcHJvdmlkZSB0aGUgY3VzdG9tIHJlc29sdmVyCiAgICAgdGhlIG9wcG9ydHVuaXR5IHRvIHJlc29sdmUgdGhlIGZ1bGxOYW1lLCBvdGhlcndpc2UgaXQgd2lsbCBmYWxsYmFjawogICAgIHRvIHRoZSByZWdpc3RyeS4KICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgcmVnaXN0cnkucmVzb2x2ZXIgPSBmdW5jdGlvbihmdWxsTmFtZSkgewogICAgICAgIC8vIGxvb2t1cCB2aWEgdGhlIG1vZHVsZSBzeXN0ZW0gb2YgY2hvaWNlCiAgICAgIH07CiAgICAgICAgLy8gdGhlIHR3aXR0ZXIgZmFjdG9yeSBpcyBhZGRlZCB0byB0aGUgbW9kdWxlIHN5c3RlbQogICAgIHJlZ2lzdHJ5LnJlc29sdmUoJ2FwaTp0d2l0dGVyJykgLy8gPT4gVHdpdHRlcgogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCByZXNvbHZlCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXQogICAgIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5zb3VyY2VdIHRoZSBmdWxsbmFtZSBvZiB0aGUgcmVxdWVzdCBzb3VyY2UgKHVzZWQgZm9yIGxvY2FsIGxvb2t1cHMpCiAgICAgQHJldHVybiB7RnVuY3Rpb259IGZ1bGxOYW1lJ3MgZmFjdG9yeQogICAgICovCiAgICA7CgogICAgX3Byb3RvMy5yZXNvbHZlID0gZnVuY3Rpb24gcmVzb2x2ZShmdWxsTmFtZSwgb3B0aW9ucykgewogICAgICB2YXIgZmFjdG9yeSA9IF9yZXNvbHZlKHRoaXMsIHRoaXMubm9ybWFsaXplKGZ1bGxOYW1lKSwgb3B0aW9ucyk7CgogICAgICBpZiAoZmFjdG9yeSA9PT0gdW5kZWZpbmVkICYmIHRoaXMuZmFsbGJhY2sgIT09IG51bGwpIHsKICAgICAgICB2YXIgX3RoaXMkZmFsbGJhY2s7CgogICAgICAgIGZhY3RvcnkgPSAoX3RoaXMkZmFsbGJhY2sgPSB0aGlzLmZhbGxiYWNrKS5yZXNvbHZlLmFwcGx5KF90aGlzJGZhbGxiYWNrLCBhcmd1bWVudHMpOwogICAgICB9CgogICAgICByZXR1cm4gZmFjdG9yeTsKICAgIH0KICAgIC8qKgogICAgIEEgaG9vayB0aGF0IGNhbiBiZSB1c2VkIHRvIGRlc2NyaWJlIGhvdyB0aGUgcmVzb2x2ZXIgd2lsbAogICAgIGF0dGVtcHQgdG8gZmluZCB0aGUgZmFjdG9yeS4KICAgICAgICBGb3IgZXhhbXBsZSwgdGhlIGRlZmF1bHQgRW1iZXIgYC5kZXNjcmliZWAgcmV0dXJucyB0aGUgZnVsbAogICAgIGNsYXNzIG5hbWUgKGluY2x1ZGluZyBuYW1lc3BhY2UpIHdoZXJlIEVtYmVyJ3MgcmVzb2x2ZXIgZXhwZWN0cwogICAgIHRvIGZpbmQgdGhlIGBmdWxsTmFtZWAuCiAgICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIGRlc2NyaWJlCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHJldHVybiB7c3RyaW5nfSBkZXNjcmliZWQgZnVsbE5hbWUKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMuZGVzY3JpYmUgPSBmdW5jdGlvbiBkZXNjcmliZShmdWxsTmFtZSkgewogICAgICBpZiAodGhpcy5yZXNvbHZlciAhPT0gbnVsbCAmJiB0aGlzLnJlc29sdmVyLmxvb2t1cERlc2NyaXB0aW9uKSB7CiAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZXIubG9va3VwRGVzY3JpcHRpb24oZnVsbE5hbWUpOwogICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2sgIT09IG51bGwpIHsKICAgICAgICByZXR1cm4gdGhpcy5mYWxsYmFjay5kZXNjcmliZShmdWxsTmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGZ1bGxOYW1lOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICBBIGhvb2sgdG8gZW5hYmxlIGN1c3RvbSBmdWxsTmFtZSBub3JtYWxpemF0aW9uIGJlaGF2aW9yCiAgICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIG5vcm1hbGl6ZUZ1bGxOYW1lCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHJldHVybiB7c3RyaW5nfSBub3JtYWxpemVkIGZ1bGxOYW1lCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zLm5vcm1hbGl6ZUZ1bGxOYW1lID0gZnVuY3Rpb24gbm9ybWFsaXplRnVsbE5hbWUoZnVsbE5hbWUpIHsKICAgICAgaWYgKHRoaXMucmVzb2x2ZXIgIT09IG51bGwgJiYgdGhpcy5yZXNvbHZlci5ub3JtYWxpemUpIHsKICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlci5ub3JtYWxpemUoZnVsbE5hbWUpOwogICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2sgIT09IG51bGwpIHsKICAgICAgICByZXR1cm4gdGhpcy5mYWxsYmFjay5ub3JtYWxpemVGdWxsTmFtZShmdWxsTmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGZ1bGxOYW1lOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICBOb3JtYWxpemUgYSBmdWxsTmFtZSBiYXNlZCBvbiB0aGUgYXBwbGljYXRpb24ncyBjb252ZW50aW9ucwogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBub3JtYWxpemUKICAgICBAcGFyYW0ge1N0cmluZ30gZnVsbE5hbWUKICAgICBAcmV0dXJuIHtzdHJpbmd9IG5vcm1hbGl6ZWQgZnVsbE5hbWUKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMubm9ybWFsaXplID0gZnVuY3Rpb24gbm9ybWFsaXplKGZ1bGxOYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLl9ub3JtYWxpemVDYWNoZVtmdWxsTmFtZV0gfHwgKHRoaXMuX25vcm1hbGl6ZUNhY2hlW2Z1bGxOYW1lXSA9IHRoaXMubm9ybWFsaXplRnVsbE5hbWUoZnVsbE5hbWUpKTsKICAgIH0KICAgIC8qKgogICAgIEBtZXRob2QgbWFrZVRvU3RyaW5nCiAgICAgICAgQHByaXZhdGUKICAgICBAcGFyYW0ge2FueX0gZmFjdG9yeQogICAgIEBwYXJhbSB7c3RyaW5nfSBmdWxsTmFtZQogICAgIEByZXR1cm4ge2Z1bmN0aW9ufSB0b1N0cmluZyBmdW5jdGlvbgogICAgICovCiAgICA7CgogICAgX3Byb3RvMy5tYWtlVG9TdHJpbmcgPSBmdW5jdGlvbiBtYWtlVG9TdHJpbmcoZmFjdG9yeSwgZnVsbE5hbWUpIHsKICAgICAgaWYgKHRoaXMucmVzb2x2ZXIgIT09IG51bGwgJiYgdGhpcy5yZXNvbHZlci5tYWtlVG9TdHJpbmcpIHsKICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlci5tYWtlVG9TdHJpbmcoZmFjdG9yeSwgZnVsbE5hbWUpOwogICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2sgIT09IG51bGwpIHsKICAgICAgICByZXR1cm4gdGhpcy5mYWxsYmFjay5tYWtlVG9TdHJpbmcoZmFjdG9yeSwgZnVsbE5hbWUpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBmYWN0b3J5LnRvU3RyaW5nKCk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgIEdpdmVuIGEgZnVsbE5hbWUgY2hlY2sgaWYgdGhlIGNvbnRhaW5lciBpcyBhd2FyZSBvZiBpdHMgZmFjdG9yeQogICAgIG9yIHNpbmdsZXRvbiBpbnN0YW5jZS4KICAgICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2QgaGFzCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXQogICAgIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5zb3VyY2VdIHRoZSBmdWxsbmFtZSBvZiB0aGUgcmVxdWVzdCBzb3VyY2UgKHVzZWQgZm9yIGxvY2FsIGxvb2t1cHMpCiAgICAgQHJldHVybiB7Qm9vbGVhbn0KICAgICAqLwogICAgOwoKICAgIF9wcm90bzMuaGFzID0gZnVuY3Rpb24gaGFzKGZ1bGxOYW1lLCBvcHRpb25zKSB7CiAgICAgIGlmICghdGhpcy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CgogICAgICB2YXIgc291cmNlID0gb3B0aW9ucyAmJiBvcHRpb25zLnNvdXJjZSAmJiB0aGlzLm5vcm1hbGl6ZShvcHRpb25zLnNvdXJjZSk7CiAgICAgIHZhciBuYW1lc3BhY2UgPSBvcHRpb25zICYmIG9wdGlvbnMubmFtZXNwYWNlIHx8IHVuZGVmaW5lZDsKICAgICAgcmV0dXJuIF9oYXModGhpcywgdGhpcy5ub3JtYWxpemUoZnVsbE5hbWUpLCBzb3VyY2UsIG5hbWVzcGFjZSk7CiAgICB9CiAgICAvKioKICAgICBBbGxvdyByZWdpc3RlcmluZyBvcHRpb25zIGZvciBhbGwgZmFjdG9yaWVzIG9mIGEgdHlwZS4KICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgbGV0IGNvbnRhaW5lciA9IHJlZ2lzdHJ5LmNvbnRhaW5lcigpOwogICAgICAgIC8vIGlmIGFsbCBvZiB0eXBlIGBjb25uZWN0aW9uYCBtdXN0IG5vdCBiZSBzaW5nbGV0b25zCiAgICAgcmVnaXN0cnkub3B0aW9uc0ZvclR5cGUoJ2Nvbm5lY3Rpb24nLCB7IHNpbmdsZXRvbjogZmFsc2UgfSk7CiAgICAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJ2Nvbm5lY3Rpb246dHdpdHRlcicsIFR3aXR0ZXJDb25uZWN0aW9uKTsKICAgICByZWdpc3RyeS5yZWdpc3RlcignY29ubmVjdGlvbjpmYWNlYm9vaycsIEZhY2Vib29rQ29ubmVjdGlvbik7CiAgICAgICAgbGV0IHR3aXR0ZXIgPSBjb250YWluZXIubG9va3VwKCdjb25uZWN0aW9uOnR3aXR0ZXInKTsKICAgICBsZXQgdHdpdHRlcjIgPSBjb250YWluZXIubG9va3VwKCdjb25uZWN0aW9uOnR3aXR0ZXInKTsKICAgICAgICB0d2l0dGVyID09PSB0d2l0dGVyMjsgLy8gPT4gZmFsc2UKICAgICAgICBsZXQgZmFjZWJvb2sgPSBjb250YWluZXIubG9va3VwKCdjb25uZWN0aW9uOmZhY2Vib29rJyk7CiAgICAgbGV0IGZhY2Vib29rMiA9IGNvbnRhaW5lci5sb29rdXAoJ2Nvbm5lY3Rpb246ZmFjZWJvb2snKTsKICAgICAgICBmYWNlYm9vayA9PT0gZmFjZWJvb2syOyAvLyA9PiBmYWxzZQogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBvcHRpb25zRm9yVHlwZQogICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMub3B0aW9uc0ZvclR5cGUgPSBmdW5jdGlvbiBvcHRpb25zRm9yVHlwZSh0eXBlLCBvcHRpb25zKSB7CiAgICAgIHRoaXMuX3R5cGVPcHRpb25zW3R5cGVdID0gb3B0aW9uczsKICAgIH07CgogICAgX3Byb3RvMy5nZXRPcHRpb25zRm9yVHlwZSA9IGZ1bmN0aW9uIGdldE9wdGlvbnNGb3JUeXBlKHR5cGUpIHsKICAgICAgdmFyIG9wdGlvbnNGb3JUeXBlID0gdGhpcy5fdHlwZU9wdGlvbnNbdHlwZV07CgogICAgICBpZiAob3B0aW9uc0ZvclR5cGUgPT09IHVuZGVmaW5lZCAmJiB0aGlzLmZhbGxiYWNrICE9PSBudWxsKSB7CiAgICAgICAgb3B0aW9uc0ZvclR5cGUgPSB0aGlzLmZhbGxiYWNrLmdldE9wdGlvbnNGb3JUeXBlKHR5cGUpOwogICAgICB9CgogICAgICByZXR1cm4gb3B0aW9uc0ZvclR5cGU7CiAgICB9CiAgICAvKioKICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2Qgb3B0aW9ucwogICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZQogICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zLm9wdGlvbnMgPSBmdW5jdGlvbiBvcHRpb25zKGZ1bGxOYW1lLCBfb3B0aW9ucykgewogICAgICB2YXIgbm9ybWFsaXplZE5hbWUgPSB0aGlzLm5vcm1hbGl6ZShmdWxsTmFtZSk7CiAgICAgIHRoaXMuX29wdGlvbnNbbm9ybWFsaXplZE5hbWVdID0gX29wdGlvbnM7CiAgICB9OwoKICAgIF9wcm90bzMuZ2V0T3B0aW9ucyA9IGZ1bmN0aW9uIGdldE9wdGlvbnMoZnVsbE5hbWUpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWROYW1lID0gdGhpcy5ub3JtYWxpemUoZnVsbE5hbWUpOwogICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuX29wdGlvbnNbbm9ybWFsaXplZE5hbWVdOwoKICAgICAgaWYgKG9wdGlvbnMgPT09IHVuZGVmaW5lZCAmJiB0aGlzLmZhbGxiYWNrICE9PSBudWxsKSB7CiAgICAgICAgb3B0aW9ucyA9IHRoaXMuZmFsbGJhY2suZ2V0T3B0aW9ucyhmdWxsTmFtZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBvcHRpb25zOwogICAgfTsKCiAgICBfcHJvdG8zLmdldE9wdGlvbiA9IGZ1bmN0aW9uIGdldE9wdGlvbihmdWxsTmFtZSwgb3B0aW9uTmFtZSkgewogICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuX29wdGlvbnNbZnVsbE5hbWVdOwoKICAgICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zW29wdGlvbk5hbWVdICE9PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gb3B0aW9uc1tvcHRpb25OYW1lXTsKICAgICAgfQoKICAgICAgdmFyIHR5cGUgPSBmdWxsTmFtZS5zcGxpdCgnOicpWzBdOwogICAgICBvcHRpb25zID0gdGhpcy5fdHlwZU9wdGlvbnNbdHlwZV07CgogICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zW29wdGlvbk5hbWVdICE9PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gb3B0aW9uc1tvcHRpb25OYW1lXTsKICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrICE9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZmFsbGJhY2suZ2V0T3B0aW9uKGZ1bGxOYW1lLCBvcHRpb25OYW1lKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH0KICAgIC8qKgogICAgIFVzZWQgb25seSB2aWEgYGluamVjdGlvbmAuCiAgICAgICAgUHJvdmlkZXMgYSBzcGVjaWFsaXplZCBmb3JtIG9mIGluamVjdGlvbiwgc3BlY2lmaWNhbGx5IGVuYWJsaW5nCiAgICAgYWxsIG9iamVjdHMgb2Ygb25lIHR5cGUgdG8gYmUgaW5qZWN0ZWQgd2l0aCBhIHJlZmVyZW5jZSB0byBhbm90aGVyCiAgICAgb2JqZWN0LgogICAgICAgIEZvciBleGFtcGxlLCBwcm92aWRlZCBlYWNoIG9iamVjdCBvZiB0eXBlIGBjb250cm9sbGVyYCBuZWVkZWQgYSBgcm91dGVyYC4KICAgICBvbmUgd291bGQgZG8gdGhlIGZvbGxvd2luZzoKICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgbGV0IGNvbnRhaW5lciA9IHJlZ2lzdHJ5LmNvbnRhaW5lcigpOwogICAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdyb3V0ZXI6bWFpbicsIFJvdXRlcik7CiAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJ2NvbnRyb2xsZXI6dXNlcicsIFVzZXJDb250cm9sbGVyKTsKICAgICByZWdpc3RyeS5yZWdpc3RlcignY29udHJvbGxlcjpwb3N0JywgUG9zdENvbnRyb2xsZXIpOwogICAgICAgIHJlZ2lzdHJ5LnR5cGVJbmplY3Rpb24oJ2NvbnRyb2xsZXInLCAncm91dGVyJywgJ3JvdXRlcjptYWluJyk7CiAgICAgICAgbGV0IHVzZXIgPSBjb250YWluZXIubG9va3VwKCdjb250cm9sbGVyOnVzZXInKTsKICAgICBsZXQgcG9zdCA9IGNvbnRhaW5lci5sb29rdXAoJ2NvbnRyb2xsZXI6cG9zdCcpOwogICAgICAgIHVzZXIucm91dGVyIGluc3RhbmNlb2YgUm91dGVyOyAvLz0+IHRydWUKICAgICBwb3N0LnJvdXRlciBpbnN0YW5jZW9mIFJvdXRlcjsgLy89PiB0cnVlCiAgICAgICAgLy8gYm90aCBjb250cm9sbGVycyBzaGFyZSB0aGUgc2FtZSByb3V0ZXIKICAgICB1c2VyLnJvdXRlciA9PT0gcG9zdC5yb3V0ZXI7IC8vPT4gdHJ1ZQogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCB0eXBlSW5qZWN0aW9uCiAgICAgQHBhcmFtIHtTdHJpbmd9IHR5cGUKICAgICBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHkKICAgICBAcGFyYW0ge1N0cmluZ30gZnVsbE5hbWUKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMudHlwZUluamVjdGlvbiA9IGZ1bmN0aW9uIHR5cGVJbmplY3Rpb24odHlwZSwgcHJvcGVydHksIGZ1bGxOYW1lKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdmdWxsTmFtZSBtdXN0IGJlIGEgcHJvcGVyIGZ1bGwgbmFtZScsIHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkpOwogICAgICB2YXIgZnVsbE5hbWVUeXBlID0gZnVsbE5hbWUuc3BsaXQoJzonKVswXTsKICAgICAgKGZhbHNlICYmICEoZnVsbE5hbWVUeXBlICE9PSB0eXBlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkNhbm5vdCBpbmplY3QgYSAnIiArIGZ1bGxOYW1lICsgIicgb24gb3RoZXIgIiArIHR5cGUgKyAiKHMpLiIsIGZ1bGxOYW1lVHlwZSAhPT0gdHlwZSkpOwogICAgICB2YXIgaW5qZWN0aW9ucyA9IHRoaXMuX3R5cGVJbmplY3Rpb25zW3R5cGVdIHx8ICh0aGlzLl90eXBlSW5qZWN0aW9uc1t0eXBlXSA9IFtdKTsKICAgICAgaW5qZWN0aW9ucy5wdXNoKHsKICAgICAgICBwcm9wZXJ0eTogcHJvcGVydHksCiAgICAgICAgc3BlY2lmaWVyOiBmdWxsTmFtZQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgIERlZmluZXMgaW5qZWN0aW9uIHJ1bGVzLgogICAgICAgIFRoZXNlIHJ1bGVzIGFyZSB1c2VkIHRvIGluamVjdCBkZXBlbmRlbmNpZXMgb250byBvYmplY3RzIHdoZW4gdGhleQogICAgIGFyZSBpbnN0YW50aWF0ZWQuCiAgICAgICAgVHdvIGZvcm1zIG9mIGluamVjdGlvbnMgYXJlIHBvc3NpYmxlOgogICAgICAgICogSW5qZWN0aW5nIG9uZSBmdWxsTmFtZSBvbiBhbm90aGVyIGZ1bGxOYW1lCiAgICAgKiBJbmplY3Rpbmcgb25lIGZ1bGxOYW1lIG9uIGEgdHlwZQogICAgICAgIEV4YW1wbGU6CiAgICAgICAgYGBgamF2YXNjcmlwdAogICAgIGxldCByZWdpc3RyeSA9IG5ldyBSZWdpc3RyeSgpOwogICAgIGxldCBjb250YWluZXIgPSByZWdpc3RyeS5jb250YWluZXIoKTsKICAgICAgICByZWdpc3RyeS5yZWdpc3Rlcignc291cmNlOm1haW4nLCBTb3VyY2UpOwogICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdtb2RlbDp1c2VyJywgVXNlcik7CiAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJ21vZGVsOnBvc3QnLCBQb3N0KTsKICAgICAgICAvLyBpbmplY3Rpbmcgb25lIGZ1bGxOYW1lIG9uIGFub3RoZXIgZnVsbE5hbWUKICAgICAvLyBlZy4gZWFjaCB1c2VyIG1vZGVsIGdldHMgYSBwb3N0IG1vZGVsCiAgICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdtb2RlbDp1c2VyJywgJ3Bvc3QnLCAnbW9kZWw6cG9zdCcpOwogICAgICAgIC8vIGluamVjdGluZyBvbmUgZnVsbE5hbWUgb24gYW5vdGhlciB0eXBlCiAgICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdtb2RlbCcsICdzb3VyY2UnLCAnc291cmNlOm1haW4nKTsKICAgICAgICBsZXQgdXNlciA9IGNvbnRhaW5lci5sb29rdXAoJ21vZGVsOnVzZXInKTsKICAgICBsZXQgcG9zdCA9IGNvbnRhaW5lci5sb29rdXAoJ21vZGVsOnBvc3QnKTsKICAgICAgICB1c2VyLnNvdXJjZSBpbnN0YW5jZW9mIFNvdXJjZTsgLy89PiB0cnVlCiAgICAgcG9zdC5zb3VyY2UgaW5zdGFuY2VvZiBTb3VyY2U7IC8vPT4gdHJ1ZQogICAgICAgIHVzZXIucG9zdCBpbnN0YW5jZW9mIFBvc3Q7IC8vPT4gdHJ1ZQogICAgICAgIC8vIGFuZCBib3RoIG1vZGVscyBzaGFyZSB0aGUgc2FtZSBzb3VyY2UKICAgICB1c2VyLnNvdXJjZSA9PT0gcG9zdC5zb3VyY2U7IC8vPT4gdHJ1ZQogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBpbmplY3Rpb24KICAgICBAcGFyYW0ge1N0cmluZ30gZmFjdG9yeU5hbWUKICAgICBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHkKICAgICBAcGFyYW0ge1N0cmluZ30gaW5qZWN0aW9uTmFtZQogICAgICovCiAgICA7CgogICAgX3Byb3RvMy5pbmplY3Rpb24gPSBmdW5jdGlvbiBpbmplY3Rpb24oZnVsbE5hbWUsIHByb3BlcnR5LCBpbmplY3Rpb25OYW1lKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGluamVjdGlvbk5hbWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkludmFsaWQgaW5qZWN0aW9uTmFtZSwgZXhwZWN0ZWQ6ICd0eXBlOm5hbWUnIGdvdDogIiArIGluamVjdGlvbk5hbWUsIHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGluamVjdGlvbk5hbWUpKSk7CiAgICAgIHZhciBub3JtYWxpemVkSW5qZWN0aW9uTmFtZSA9IHRoaXMubm9ybWFsaXplKGluamVjdGlvbk5hbWUpOwoKICAgICAgaWYgKGZ1bGxOYW1lLmluZGV4T2YoJzonKSA9PT0gLTEpIHsKICAgICAgICByZXR1cm4gdGhpcy50eXBlSW5qZWN0aW9uKGZ1bGxOYW1lLCBwcm9wZXJ0eSwgbm9ybWFsaXplZEluamVjdGlvbk5hbWUpOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISh0aGlzLmlzVmFsaWRGdWxsTmFtZShmdWxsTmFtZSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnZnVsbE5hbWUgbXVzdCBiZSBhIHByb3BlciBmdWxsIG5hbWUnLCB0aGlzLmlzVmFsaWRGdWxsTmFtZShmdWxsTmFtZSkpKTsKICAgICAgdmFyIG5vcm1hbGl6ZWROYW1lID0gdGhpcy5ub3JtYWxpemUoZnVsbE5hbWUpOwogICAgICB2YXIgaW5qZWN0aW9ucyA9IHRoaXMuX2luamVjdGlvbnNbbm9ybWFsaXplZE5hbWVdIHx8ICh0aGlzLl9pbmplY3Rpb25zW25vcm1hbGl6ZWROYW1lXSA9IFtdKTsKICAgICAgaW5qZWN0aW9ucy5wdXNoKHsKICAgICAgICBwcm9wZXJ0eTogcHJvcGVydHksCiAgICAgICAgc3BlY2lmaWVyOiBub3JtYWxpemVkSW5qZWN0aW9uTmFtZQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBrbm93bkZvclR5cGUKICAgICBAcGFyYW0ge1N0cmluZ30gdHlwZSB0aGUgdHlwZSB0byBpdGVyYXRlIG92ZXIKICAgICovCiAgICA7CgogICAgX3Byb3RvMy5rbm93bkZvclR5cGUgPSBmdW5jdGlvbiBrbm93bkZvclR5cGUodHlwZSkgewogICAgICB2YXIgbG9jYWxLbm93biA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CiAgICAgIHZhciByZWdpc3RlcmVkTmFtZXMgPSBPYmplY3Qua2V5cyh0aGlzLnJlZ2lzdHJhdGlvbnMpOwoKICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IHJlZ2lzdGVyZWROYW1lcy5sZW5ndGg7IGluZGV4KyspIHsKICAgICAgICB2YXIgZnVsbE5hbWUgPSByZWdpc3RlcmVkTmFtZXNbaW5kZXhdOwogICAgICAgIHZhciBpdGVtVHlwZSA9IGZ1bGxOYW1lLnNwbGl0KCc6JylbMF07CgogICAgICAgIGlmIChpdGVtVHlwZSA9PT0gdHlwZSkgewogICAgICAgICAgbG9jYWxLbm93bltmdWxsTmFtZV0gPSB0cnVlOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdmFyIGZhbGxiYWNrS25vd24sIHJlc29sdmVyS25vd247CgogICAgICBpZiAodGhpcy5mYWxsYmFjayAhPT0gbnVsbCkgewogICAgICAgIGZhbGxiYWNrS25vd24gPSB0aGlzLmZhbGxiYWNrLmtub3duRm9yVHlwZSh0eXBlKTsKICAgICAgfQoKICAgICAgaWYgKHRoaXMucmVzb2x2ZXIgIT09IG51bGwgJiYgdGhpcy5yZXNvbHZlci5rbm93bkZvclR5cGUpIHsKICAgICAgICByZXNvbHZlcktub3duID0gdGhpcy5yZXNvbHZlci5rbm93bkZvclR5cGUodHlwZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBmYWxsYmFja0tub3duLCBsb2NhbEtub3duLCByZXNvbHZlcktub3duKTsKICAgIH07CgogICAgX3Byb3RvMy5pc1ZhbGlkRnVsbE5hbWUgPSBmdW5jdGlvbiBpc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpIHsKICAgICAgcmV0dXJuIFZBTElEX0ZVTExfTkFNRV9SRUdFWFAudGVzdChmdWxsTmFtZSk7CiAgICB9OwoKICAgIF9wcm90bzMuZ2V0SW5qZWN0aW9ucyA9IGZ1bmN0aW9uIGdldEluamVjdGlvbnMoZnVsbE5hbWUpIHsKICAgICAgdmFyIGluamVjdGlvbnMgPSB0aGlzLl9pbmplY3Rpb25zW2Z1bGxOYW1lXTsKCiAgICAgIGlmICh0aGlzLmZhbGxiYWNrICE9PSBudWxsKSB7CiAgICAgICAgdmFyIGZhbGxiYWNrSW5qZWN0aW9ucyA9IHRoaXMuZmFsbGJhY2suZ2V0SW5qZWN0aW9ucyhmdWxsTmFtZSk7CgogICAgICAgIGlmIChmYWxsYmFja0luamVjdGlvbnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgaW5qZWN0aW9ucyA9IGluamVjdGlvbnMgPT09IHVuZGVmaW5lZCA/IGZhbGxiYWNrSW5qZWN0aW9ucyA6IGluamVjdGlvbnMuY29uY2F0KGZhbGxiYWNrSW5qZWN0aW9ucyk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gaW5qZWN0aW9uczsKICAgIH07CgogICAgX3Byb3RvMy5nZXRUeXBlSW5qZWN0aW9ucyA9IGZ1bmN0aW9uIGdldFR5cGVJbmplY3Rpb25zKHR5cGUpIHsKICAgICAgdmFyIGluamVjdGlvbnMgPSB0aGlzLl90eXBlSW5qZWN0aW9uc1t0eXBlXTsKCiAgICAgIGlmICh0aGlzLmZhbGxiYWNrICE9PSBudWxsKSB7CiAgICAgICAgdmFyIGZhbGxiYWNrSW5qZWN0aW9ucyA9IHRoaXMuZmFsbGJhY2suZ2V0VHlwZUluamVjdGlvbnModHlwZSk7CgogICAgICAgIGlmIChmYWxsYmFja0luamVjdGlvbnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgaW5qZWN0aW9ucyA9IGluamVjdGlvbnMgPT09IHVuZGVmaW5lZCA/IGZhbGxiYWNrSW5qZWN0aW9ucyA6IGluamVjdGlvbnMuY29uY2F0KGZhbGxiYWNrSW5qZWN0aW9ucyk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gaW5qZWN0aW9uczsKICAgIH0KICAgIC8qKgogICAgIEdpdmVuIGEgZnVsbE5hbWUgYW5kIGEgc291cmNlIGZ1bGxOYW1lIHJldHVybnMgdGhlIGZ1bGx5IHJlc29sdmVkCiAgICAgZnVsbE5hbWUuIFVzZWQgdG8gYWxsb3cgZm9yIGxvY2FsIGxvb2t1cC4KICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgICAgLy8gdGhlIHR3aXR0ZXIgZmFjdG9yeSBpcyBhZGRlZCB0byB0aGUgbW9kdWxlIHN5c3RlbQogICAgIHJlZ2lzdHJ5LmV4cGFuZExvY2FsTG9va3VwKCdjb21wb25lbnQ6cG9zdC10aXRsZScsIHsgc291cmNlOiAndGVtcGxhdGU6cG9zdCcgfSkgLy8gPT4gY29tcG9uZW50OnBvc3QvcG9zdC10aXRsZQogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBleHBhbmRMb2NhbExvb2t1cAogICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZQogICAgIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10KICAgICBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuc291cmNlXSB0aGUgZnVsbG5hbWUgb2YgdGhlIHJlcXVlc3Qgc291cmNlICh1c2VkIGZvciBsb2NhbCBsb29rdXBzKQogICAgIEByZXR1cm4ge1N0cmluZ30gZnVsbE5hbWUKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMuZXhwYW5kTG9jYWxMb29rdXAgPSBmdW5jdGlvbiBleHBhbmRMb2NhbExvb2t1cChmdWxsTmFtZSwgb3B0aW9ucykgewogICAgICBpZiAodGhpcy5yZXNvbHZlciAhPT0gbnVsbCAmJiB0aGlzLnJlc29sdmVyLmV4cGFuZExvY2FsTG9va3VwKSB7CiAgICAgICAgKGZhbHNlICYmICEodGhpcy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2Z1bGxOYW1lIG11c3QgYmUgYSBwcm9wZXIgZnVsbCBuYW1lJywgdGhpcy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSk7CiAgICAgICAgKGZhbHNlICYmICEoIW9wdGlvbnMuc291cmNlIHx8IHRoaXMuaXNWYWxpZEZ1bGxOYW1lKG9wdGlvbnMuc291cmNlKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdvcHRpb25zLnNvdXJjZSBtdXN0IGJlIGEgcHJvcGVyIGZ1bGwgbmFtZScsICFvcHRpb25zLnNvdXJjZSB8fCB0aGlzLmlzVmFsaWRGdWxsTmFtZShvcHRpb25zLnNvdXJjZSkpKTsKICAgICAgICB2YXIgbm9ybWFsaXplZEZ1bGxOYW1lID0gdGhpcy5ub3JtYWxpemUoZnVsbE5hbWUpOwogICAgICAgIHZhciBub3JtYWxpemVkU291cmNlID0gdGhpcy5ub3JtYWxpemUob3B0aW9ucy5zb3VyY2UpOwogICAgICAgIHJldHVybiBfZXhwYW5kTG9jYWxMb29rdXAodGhpcywgbm9ybWFsaXplZEZ1bGxOYW1lLCBub3JtYWxpemVkU291cmNlLCBvcHRpb25zLm5hbWVzcGFjZSk7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5mYWxsYmFjayAhPT0gbnVsbCkgewogICAgICAgIHJldHVybiB0aGlzLmZhbGxiYWNrLmV4cGFuZExvY2FsTG9va3VwKGZ1bGxOYW1lLCBvcHRpb25zKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gUmVnaXN0cnk7CiAgfSgpOwoKICBfZXhwb3J0cy5SZWdpc3RyeSA9IFJlZ2lzdHJ5OwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgdmFyIHByb3RvID0gUmVnaXN0cnkucHJvdG90eXBlOwoKICAgIHByb3RvLm5vcm1hbGl6ZUluamVjdGlvbnNIYXNoID0gZnVuY3Rpb24gKGhhc2gpIHsKICAgICAgdmFyIGluamVjdGlvbnMgPSBbXTsKCiAgICAgIGZvciAodmFyIGtleSBpbiBoYXNoKSB7CiAgICAgICAgaWYgKGhhc2guaGFzT3duUHJvcGVydHkoa2V5KSkgewogICAgICAgICAgdmFyIF9oYXNoJGtleSA9IGhhc2hba2V5XSwKICAgICAgICAgICAgICBzcGVjaWZpZXIgPSBfaGFzaCRrZXkuc3BlY2lmaWVyLAogICAgICAgICAgICAgIHNvdXJjZSA9IF9oYXNoJGtleS5zb3VyY2UsCiAgICAgICAgICAgICAgbmFtZXNwYWNlID0gX2hhc2gka2V5Lm5hbWVzcGFjZTsKICAgICAgICAgIChmYWxzZSAmJiAhKHRoaXMuaXNWYWxpZEZ1bGxOYW1lKHNwZWNpZmllcikpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiRXhwZWN0ZWQgYSBwcm9wZXIgZnVsbCBuYW1lLCBnaXZlbiAnIiArIHNwZWNpZmllciArICInIiwgdGhpcy5pc1ZhbGlkRnVsbE5hbWUoc3BlY2lmaWVyKSkpOwogICAgICAgICAgaW5qZWN0aW9ucy5wdXNoKHsKICAgICAgICAgICAgcHJvcGVydHk6IGtleSwKICAgICAgICAgICAgc3BlY2lmaWVyOiBzcGVjaWZpZXIsCiAgICAgICAgICAgIHNvdXJjZTogc291cmNlLAogICAgICAgICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gaW5qZWN0aW9uczsKICAgIH07CgogICAgcHJvdG8udmFsaWRhdGVJbmplY3Rpb25zID0gZnVuY3Rpb24gKGluamVjdGlvbnMpIHsKICAgICAgaWYgKCFpbmplY3Rpb25zKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluamVjdGlvbnMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgX2luamVjdGlvbnMkaTIgPSBpbmplY3Rpb25zW2ldLAogICAgICAgICAgICBzcGVjaWZpZXIgPSBfaW5qZWN0aW9ucyRpMi5zcGVjaWZpZXIsCiAgICAgICAgICAgIHNvdXJjZSA9IF9pbmplY3Rpb25zJGkyLnNvdXJjZSwKICAgICAgICAgICAgbmFtZXNwYWNlID0gX2luamVjdGlvbnMkaTIubmFtZXNwYWNlOwogICAgICAgIChmYWxzZSAmJiAhKHRoaXMuaGFzKHNwZWNpZmllciwgewogICAgICAgICAgc291cmNlOiBzb3VyY2UsCiAgICAgICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZQogICAgICAgIH0pKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF0dGVtcHRpbmcgdG8gaW5qZWN0IGFuIHVua25vd24gaW5qZWN0aW9uOiAnIiArIHNwZWNpZmllciArICInIiwgdGhpcy5oYXMoc3BlY2lmaWVyLCB7CiAgICAgICAgICBzb3VyY2U6IHNvdXJjZSwKICAgICAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlCiAgICAgICAgfSkpKTsKICAgICAgfQogICAgfTsKICB9CgogIGZ1bmN0aW9uIF9leHBhbmRMb2NhbExvb2t1cChyZWdpc3RyeSwgbm9ybWFsaXplZE5hbWUsIG5vcm1hbGl6ZWRTb3VyY2UsIG5hbWVzcGFjZSkgewogICAgdmFyIGNhY2hlID0gcmVnaXN0cnkuX2xvY2FsTG9va3VwQ2FjaGU7CiAgICB2YXIgbm9ybWFsaXplZE5hbWVDYWNoZSA9IGNhY2hlW25vcm1hbGl6ZWROYW1lXTsKCiAgICBpZiAoIW5vcm1hbGl6ZWROYW1lQ2FjaGUpIHsKICAgICAgbm9ybWFsaXplZE5hbWVDYWNoZSA9IGNhY2hlW25vcm1hbGl6ZWROYW1lXSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB9CgogICAgdmFyIGNhY2hlS2V5ID0gbmFtZXNwYWNlIHx8IG5vcm1hbGl6ZWRTb3VyY2U7CiAgICB2YXIgY2FjaGVkID0gbm9ybWFsaXplZE5hbWVDYWNoZVtjYWNoZUtleV07CgogICAgaWYgKGNhY2hlZCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBjYWNoZWQ7CiAgICB9CgogICAgdmFyIGV4cGFuZGVkID0gcmVnaXN0cnkucmVzb2x2ZXIuZXhwYW5kTG9jYWxMb29rdXAobm9ybWFsaXplZE5hbWUsIG5vcm1hbGl6ZWRTb3VyY2UsIG5hbWVzcGFjZSk7CiAgICByZXR1cm4gbm9ybWFsaXplZE5hbWVDYWNoZVtjYWNoZUtleV0gPSBleHBhbmRlZDsKICB9CgogIGZ1bmN0aW9uIF9yZXNvbHZlKHJlZ2lzdHJ5LCBfbm9ybWFsaXplZE5hbWUsIG9wdGlvbnMpIHsKICAgIHZhciBub3JtYWxpemVkTmFtZSA9IF9ub3JtYWxpemVkTmFtZTsgLy8gd2hlbiBgc291cmNlYCBpcyBwcm92aWRlZCBleHBhbmQgbm9ybWFsaXplZE5hbWUKICAgIC8vIGFuZCBzb3VyY2UgaW50byB0aGUgZnVsbCBub3JtYWxpemVkTmFtZQoKICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQgJiYgKG9wdGlvbnMuc291cmNlIHx8IG9wdGlvbnMubmFtZXNwYWNlKSkgewogICAgICBub3JtYWxpemVkTmFtZSA9IHJlZ2lzdHJ5LmV4cGFuZExvY2FsTG9va3VwKF9ub3JtYWxpemVkTmFtZSwgb3B0aW9ucyk7CgogICAgICBpZiAoIW5vcm1hbGl6ZWROYW1lKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICB9CgogICAgdmFyIGNhY2hlZCA9IHJlZ2lzdHJ5Ll9yZXNvbHZlQ2FjaGVbbm9ybWFsaXplZE5hbWVdOwoKICAgIGlmIChjYWNoZWQgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gY2FjaGVkOwogICAgfQoKICAgIGlmIChyZWdpc3RyeS5fZmFpbFNldC5oYXMobm9ybWFsaXplZE5hbWUpKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgcmVzb2x2ZWQ7CgogICAgaWYgKHJlZ2lzdHJ5LnJlc29sdmVyKSB7CiAgICAgIHJlc29sdmVkID0gcmVnaXN0cnkucmVzb2x2ZXIucmVzb2x2ZShub3JtYWxpemVkTmFtZSk7CiAgICB9CgogICAgaWYgKHJlc29sdmVkID09PSB1bmRlZmluZWQpIHsKICAgICAgcmVzb2x2ZWQgPSByZWdpc3RyeS5yZWdpc3RyYXRpb25zW25vcm1hbGl6ZWROYW1lXTsKICAgIH0KCiAgICBpZiAocmVzb2x2ZWQgPT09IHVuZGVmaW5lZCkgewogICAgICByZWdpc3RyeS5fZmFpbFNldC5hZGQobm9ybWFsaXplZE5hbWUpOwogICAgfSBlbHNlIHsKICAgICAgcmVnaXN0cnkuX3Jlc29sdmVDYWNoZVtub3JtYWxpemVkTmFtZV0gPSByZXNvbHZlZDsKICAgIH0KCiAgICByZXR1cm4gcmVzb2x2ZWQ7CiAgfQoKICBmdW5jdGlvbiBfaGFzKHJlZ2lzdHJ5LCBmdWxsTmFtZSwgc291cmNlLCBuYW1lc3BhY2UpIHsKICAgIHJldHVybiByZWdpc3RyeS5yZXNvbHZlKGZ1bGxOYW1lLCB7CiAgICAgIHNvdXJjZTogc291cmNlLAogICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZQogICAgfSkgIT09IHVuZGVmaW5lZDsKICB9CgogIHZhciBwcml2YXRlTmFtZXMgPSAoMCwgX3V0aWxzLmRpY3Rpb25hcnkpKG51bGwpOwogIHZhciBwcml2YXRlU3VmZml4ID0gKCIiICsgTWF0aC5yYW5kb20oKSArIERhdGUubm93KCkpLnJlcGxhY2UoJy4nLCAnJyk7CgogIGZ1bmN0aW9uIHByaXZhdGl6ZShfcmVmNikgewogICAgdmFyIGZ1bGxOYW1lID0gX3JlZjZbMF07CiAgICB2YXIgbmFtZSA9IHByaXZhdGVOYW1lc1tmdWxsTmFtZV07CgogICAgaWYgKG5hbWUpIHsKICAgICAgcmV0dXJuIG5hbWU7CiAgICB9CgogICAgdmFyIF9mdWxsTmFtZSRzcGxpdDIgPSBmdWxsTmFtZS5zcGxpdCgnOicpLAogICAgICAgIHR5cGUgPSBfZnVsbE5hbWUkc3BsaXQyWzBdLAogICAgICAgIHJhd05hbWUgPSBfZnVsbE5hbWUkc3BsaXQyWzFdOwoKICAgIHJldHVybiBwcml2YXRlTmFtZXNbZnVsbE5hbWVdID0gKDAsIF91dGlscy5pbnRlcm4pKHR5cGUgKyAiOiIgKyByYXdOYW1lICsgIi0iICsgcHJpdmF0ZVN1ZmZpeCk7CiAgfQogIC8qCiAgUHVibGljIEFQSSBmb3IgdGhlIGNvbnRhaW5lciBpcyBzdGlsbCBpbiBmbHV4LgogIFRoZSBwdWJsaWMgQVBJLCBzcGVjaWZpZWQgb24gdGhlIGFwcGxpY2F0aW9uIG5hbWVzcGFjZSBzaG91bGQgYmUgY29uc2lkZXJlZCB0aGUgc3RhYmxlIEFQSS4KICAvLyBAbW9kdWxlIGNvbnRhaW5lcgogICAgQHByaXZhdGUKICAqLwoKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvZW52aXJvbm1lbnQvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVwcmVjYXRlZEZlYXR1cmVzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5nZXRMb29rdXAgPSBnZXRMb29rdXA7CiAgX2V4cG9ydHMuc2V0TG9va3VwID0gc2V0TG9va3VwOwogIF9leHBvcnRzLmdldEVOViA9IGdldEVOVjsKICBfZXhwb3J0cy5FTlYgPSBfZXhwb3J0cy5jb250ZXh0ID0gX2V4cG9ydHMuZ2xvYmFsID0gdm9pZCAwOwoKICAvLyBmcm9tIGxvZGFzaCB0byBjYXRjaCBmYWtlIGdsb2JhbHMKICBmdW5jdGlvbiBjaGVja0dsb2JhbCh2YWx1ZSkgewogICAgcmV0dXJuIHZhbHVlICYmIHZhbHVlLk9iamVjdCA9PT0gT2JqZWN0ID8gdmFsdWUgOiB1bmRlZmluZWQ7CiAgfSAvLyBlbGVtZW50IGlkcyBjYW4gcnVpbiBnbG9iYWwgbWlzcyBjaGVja3MKCgogIGZ1bmN0aW9uIGNoZWNrRWxlbWVudElkU2hhZG93aW5nKHZhbHVlKSB7CiAgICByZXR1cm4gdmFsdWUgJiYgdmFsdWUubm9kZVR5cGUgPT09IHVuZGVmaW5lZCA/IHZhbHVlIDogdW5kZWZpbmVkOwogIH0gLy8gZXhwb3J0IHJlYWwgZ2xvYmFsCgoKICB2YXIgZ2xvYmFsJDEgPSBjaGVja0dsb2JhbChjaGVja0VsZW1lbnRJZFNoYWRvd2luZyh0eXBlb2YgZ2xvYmFsID09PSAnb2JqZWN0JyAmJiBnbG9iYWwpKSB8fCBjaGVja0dsb2JhbCh0eXBlb2Ygc2VsZiA9PT0gJ29iamVjdCcgJiYgc2VsZikgfHwgY2hlY2tHbG9iYWwodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgJiYgd2luZG93KSB8fCB0eXBlb2YgbWFpbkNvbnRleHQgIT09ICd1bmRlZmluZWQnICYmIG1haW5Db250ZXh0IHx8IC8vIHNldCBiZWZvcmUgc3RyaWN0IG1vZGUgaW4gRW1iZXIgbG9hZGVyL3dyYXBwZXIKICBuZXcgRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTsgLy8gZXZhbCBvdXRzaWRlIG9mIHN0cmljdCBtb2RlCgogIF9leHBvcnRzLmdsb2JhbCA9IGdsb2JhbCQxOwoKICB2YXIgY29udGV4dCA9IGZ1bmN0aW9uIChnbG9iYWwsIEVtYmVyKSB7CiAgICByZXR1cm4gRW1iZXIgPT09IHVuZGVmaW5lZCA/IHsKICAgICAgaW1wb3J0czogZ2xvYmFsLAogICAgICBleHBvcnRzOiBnbG9iYWwsCiAgICAgIGxvb2t1cDogZ2xvYmFsCiAgICB9IDogewogICAgICAvLyBpbXBvcnQgalF1ZXJ5CiAgICAgIGltcG9ydHM6IEVtYmVyLmltcG9ydHMgfHwgZ2xvYmFsLAogICAgICAvLyBleHBvcnQgRW1iZXIKICAgICAgZXhwb3J0czogRW1iZXIuZXhwb3J0cyB8fCBnbG9iYWwsCiAgICAgIC8vIHNlYXJjaCBmb3IgTmFtZXNwYWNlcwogICAgICBsb29rdXA6IEVtYmVyLmxvb2t1cCB8fCBnbG9iYWwKICAgIH07CiAgfShnbG9iYWwkMSwgZ2xvYmFsJDEuRW1iZXIpOwoKICBfZXhwb3J0cy5jb250ZXh0ID0gY29udGV4dDsKCiAgZnVuY3Rpb24gZ2V0TG9va3VwKCkgewogICAgcmV0dXJuIGNvbnRleHQubG9va3VwOwogIH0KCiAgZnVuY3Rpb24gc2V0TG9va3VwKHZhbHVlKSB7CiAgICBjb250ZXh0Lmxvb2t1cCA9IHZhbHVlOwogIH0KICAvKioKICAgIFRoZSBoYXNoIG9mIGVudmlyb25tZW50IHZhcmlhYmxlcyB1c2VkIHRvIGNvbnRyb2wgdmFyaW91cyBjb25maWd1cmF0aW9uCiAgICBzZXR0aW5ncy4gVG8gc3BlY2lmeSB5b3VyIG93biBvciBvdmVycmlkZSBkZWZhdWx0IHNldHRpbmdzLCBhZGQgdGhlCiAgICBkZXNpcmVkIHByb3BlcnRpZXMgdG8gYSBnbG9iYWwgaGFzaCBuYW1lZCBgRW1iZXJFTlZgIChvciBgRU5WYCBmb3IKICAgIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggZWFybGllciB2ZXJzaW9ucyBvZiBFbWJlcikuIFRoZSBgRW1iZXJFTlZgCiAgICBoYXNoIG11c3QgYmUgY3JlYXRlZCBiZWZvcmUgbG9hZGluZyBFbWJlci4KICAKICAgIEBjbGFzcyBFbWJlckVOVgogICAgQHR5cGUgT2JqZWN0CiAgICBAcHVibGljCiAgKi8KCgogIHZhciBFTlYgPSB7CiAgICBFTkFCTEVfT1BUSU9OQUxfRkVBVFVSRVM6IGZhbHNlLAoKICAgIC8qKgogICAgICBEZXRlcm1pbmVzIHdoZXRoZXIgRW1iZXIgc2hvdWxkIGFkZCB0byBgQXJyYXlgLCBgRnVuY3Rpb25gLCBhbmQgYFN0cmluZ2AKICAgICAgbmF0aXZlIG9iamVjdCBwcm90b3R5cGVzLCBhIGZldyBleHRyYSBtZXRob2RzIGluIG9yZGVyIHRvIHByb3ZpZGUgYSBtb3JlCiAgICAgIGZyaWVuZGx5IEFQSS4KICAgICAgICAgV2UgZ2VuZXJhbGx5IHJlY29tbWVuZCBsZWF2aW5nIHRoaXMgb3B0aW9uIHNldCB0byB0cnVlIGhvd2V2ZXIsIGlmIHlvdSBuZWVkCiAgICAgIHRvIHR1cm4gaXQgb2ZmLCB5b3UgY2FuIGFkZCB0aGUgY29uZmlndXJhdGlvbiBwcm9wZXJ0eQogICAgICBgRVhURU5EX1BST1RPVFlQRVNgIHRvIGBFbWJlckVOVmAgYW5kIHNldCBpdCB0byBgZmFsc2VgLgogICAgICAgICBOb3RlLCB3aGVuIGRpc2FibGVkICh0aGUgZGVmYXVsdCBjb25maWd1cmF0aW9uIGZvciBFbWJlciBBZGRvbnMpLCB5b3Ugd2lsbAogICAgICBpbnN0ZWFkIGhhdmUgdG8gYWNjZXNzIGFsbCBtZXRob2RzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgRW1iZXIKICAgICAgbmFtZXNwYWNlLgogICAgICAgICBAcHJvcGVydHkgRVhURU5EX1BST1RPVFlQRVMKICAgICAgQHR5cGUgQm9vbGVhbgogICAgICBAZGVmYXVsdCB0cnVlCiAgICAgIEBmb3IgRW1iZXJFTlYKICAgICAgQHB1YmxpYwogICAgKi8KICAgIEVYVEVORF9QUk9UT1RZUEVTOiB7CiAgICAgIEFycmF5OiB0cnVlLAogICAgICBGdW5jdGlvbjogdHJ1ZSwKICAgICAgU3RyaW5nOiB0cnVlCiAgICB9LAoKICAgIC8qKgogICAgICBUaGUgYExPR19TVEFDS1RSQUNFX09OX0RFUFJFQ0FUSU9OYCBwcm9wZXJ0eSwgd2hlbiB0cnVlLCB0ZWxscyBFbWJlciB0byBsb2cKICAgICAgYSBmdWxsIHN0YWNrIHRyYWNlIGR1cmluZyBkZXByZWNhdGlvbiB3YXJuaW5ncy4KICAgICAgICAgQHByb3BlcnR5IExPR19TVEFDS1RSQUNFX09OX0RFUFJFQ0FUSU9OCiAgICAgIEB0eXBlIEJvb2xlYW4KICAgICAgQGRlZmF1bHQgdHJ1ZQogICAgICBAZm9yIEVtYmVyRU5WCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBMT0dfU1RBQ0tUUkFDRV9PTl9ERVBSRUNBVElPTjogdHJ1ZSwKCiAgICAvKioKICAgICAgVGhlIGBMT0dfVkVSU0lPTmAgcHJvcGVydHksIHdoZW4gdHJ1ZSwgdGVsbHMgRW1iZXIgdG8gbG9nIHZlcnNpb25zIG9mIGFsbAogICAgICBkZXBlbmRlbnQgbGlicmFyaWVzIGluIHVzZS4KICAgICAgICAgQHByb3BlcnR5IExPR19WRVJTSU9OCiAgICAgIEB0eXBlIEJvb2xlYW4KICAgICAgQGRlZmF1bHQgdHJ1ZQogICAgICBAZm9yIEVtYmVyRU5WCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBMT0dfVkVSU0lPTjogdHJ1ZSwKICAgIFJBSVNFX09OX0RFUFJFQ0FUSU9OOiBmYWxzZSwKICAgIFNUUlVDVFVSRURfUFJPRklMRTogZmFsc2UsCgogICAgLyoqCiAgICAgIFdoZXRoZXIgdG8gaW5zZXJ0IGEgYDxkaXYgY2xhc3M9ImVtYmVyLXZpZXciIC8+YCB3cmFwcGVyIGFyb3VuZCB0aGUKICAgICAgYXBwbGljYXRpb24gdGVtcGxhdGUuIFNlZSBSRkMgIzI4MC4KICAgICAgICAgVGhpcyBpcyBub3QgaW50ZW5kZWQgdG8gYmUgc2V0IGRpcmVjdGx5LCBhcyB0aGUgaW1wbGVtZW50YXRpb24gbWF5IGNoYW5nZSBpbgogICAgICB0aGUgZnV0dXJlLiBVc2UgYEBlbWJlci9vcHRpb25hbC1mZWF0dXJlc2AgaW5zdGVhZC4KICAgICAgICAgQHByb3BlcnR5IF9BUFBMSUNBVElPTl9URU1QTEFURV9XUkFQUEVSCiAgICAgIEBmb3IgRW1iZXJFTlYKICAgICAgQHR5cGUgQm9vbGVhbgogICAgICBAZGVmYXVsdCB0cnVlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX0FQUExJQ0FUSU9OX1RFTVBMQVRFX1dSQVBQRVI6IHRydWUsCgogICAgLyoqCiAgICAgIFdoZXRoZXIgdG8gdXNlIEdsaW1tZXIgQ29tcG9uZW50IHNlbWFudGljcyAoYXMgb3Bwb3NlZCB0byB0aGUgY2xhc3NpYyAiQ3VybHkiCiAgICAgIGNvbXBvbmVudHMgc2VtYW50aWNzKSBmb3IgdGVtcGxhdGUtb25seSBjb21wb25lbnRzLiBTZWUgUkZDICMyNzguCiAgICAgICAgIFRoaXMgaXMgbm90IGludGVuZGVkIHRvIGJlIHNldCBkaXJlY3RseSwgYXMgdGhlIGltcGxlbWVudGF0aW9uIG1heSBjaGFuZ2UgaW4KICAgICAgdGhlIGZ1dHVyZS4gVXNlIGBAZW1iZXIvb3B0aW9uYWwtZmVhdHVyZXNgIGluc3RlYWQuCiAgICAgICAgIEBwcm9wZXJ0eSBfVEVNUExBVEVfT05MWV9HTElNTUVSX0NPTVBPTkVOVFMKICAgICAgQGZvciBFbWJlckVOVgogICAgICBAdHlwZSBCb29sZWFuCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX1RFTVBMQVRFX09OTFlfR0xJTU1FUl9DT01QT05FTlRTOiBmYWxzZSwKCiAgICAvKioKICAgICAgV2hldGhlciB0aGUgYXBwIGlzIHVzaW5nIGpRdWVyeS4gU2VlIFJGQyAjMjk0LgogICAgICAgICBUaGlzIGlzIG5vdCBpbnRlbmRlZCB0byBiZSBzZXQgZGlyZWN0bHksIGFzIHRoZSBpbXBsZW1lbnRhdGlvbiBtYXkgY2hhbmdlIGluCiAgICAgIHRoZSBmdXR1cmUuIFVzZSBgQGVtYmVyL29wdGlvbmFsLWZlYXR1cmVzYCBpbnN0ZWFkLgogICAgICAgICBAcHJvcGVydHkgX0pRVUVSWV9JTlRFR1JBVElPTgogICAgICBAZm9yIEVtYmVyRU5WCiAgICAgIEB0eXBlIEJvb2xlYW4KICAgICAgQGRlZmF1bHQgdHJ1ZQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9KUVVFUllfSU5URUdSQVRJT046IHRydWUsCgogICAgLyoqCiAgICAgIFdoZXRoZXIgdGhlIGFwcCBkZWZhdWx0cyB0byB1c2luZyBhc3luYyBvYnNlcnZlcnMuCiAgICAgICAgIFRoaXMgaXMgbm90IGludGVuZGVkIHRvIGJlIHNldCBkaXJlY3RseSwgYXMgdGhlIGltcGxlbWVudGF0aW9uIG1heSBjaGFuZ2UgaW4KICAgICAgdGhlIGZ1dHVyZS4gVXNlIGBAZW1iZXIvb3B0aW9uYWwtZmVhdHVyZXNgIGluc3RlYWQuCiAgICAgICAgIEBwcm9wZXJ0eSBfREVGQVVMVF9BU1lOQ19PQlNFUlZFUlMKICAgICAgQGZvciBFbWJlckVOVgogICAgICBAdHlwZSBCb29sZWFuCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX0RFRkFVTFRfQVNZTkNfT0JTRVJWRVJTOiBmYWxzZSwKCiAgICAvKioKICAgICAgQ29udHJvbHMgdGhlIG1heGltdW0gbnVtYmVyIG9mIHNjaGVkdWxlZCByZXJlbmRlcnMgd2l0aG91dCAic2V0dGxpbmciLiBJbiBnZW5lcmFsLAogICAgICBhcHBsaWNhdGlvbnMgc2hvdWxkIG5vdCBuZWVkIHRvIG1vZGlmeSB0aGlzIGVudmlyb25tZW50IHZhcmlhYmxlLCBidXQgcGxlYXNlCiAgICAgIG9wZW4gYW4gaXNzdWUgc28gdGhhdCB3ZSBjYW4gZGV0ZXJtaW5lIGlmIGEgYmV0dGVyIGRlZmF1bHQgdmFsdWUgaXMgbmVlZGVkLgogICAgICAgICBAcHJvcGVydHkgX1JFUkVOREVSX0xPT1BfTElNSVQKICAgICAgQGZvciBFbWJlckVOVgogICAgICBAdHlwZSBudW1iZXIKICAgICAgQGRlZmF1bHQgMTAwMAogICAgICBAcHJpdmF0ZQogICAgICovCiAgICBfUkVSRU5ERVJfTE9PUF9MSU1JVDogMTAwMCwKICAgIEVNQkVSX0xPQURfSE9PS1M6IHt9LAogICAgRkVBVFVSRVM6IHt9CiAgfTsKICBfZXhwb3J0cy5FTlYgPSBFTlY7CgogIChmdW5jdGlvbiAoRW1iZXJFTlYpIHsKICAgIGlmICh0eXBlb2YgRW1iZXJFTlYgIT09ICdvYmplY3QnIHx8IEVtYmVyRU5WID09PSBudWxsKSByZXR1cm47CgogICAgZm9yICh2YXIgZmxhZyBpbiBFbWJlckVOVikgewogICAgICBpZiAoIUVtYmVyRU5WLmhhc093blByb3BlcnR5KGZsYWcpIHx8IGZsYWcgPT09ICdFWFRFTkRfUFJPVE9UWVBFUycgfHwgZmxhZyA9PT0gJ0VNQkVSX0xPQURfSE9PS1MnKSBjb250aW51ZTsKICAgICAgdmFyIGRlZmF1bHRWYWx1ZSA9IEVOVltmbGFnXTsKCiAgICAgIGlmIChkZWZhdWx0VmFsdWUgPT09IHRydWUpIHsKICAgICAgICBFTlZbZmxhZ10gPSBFbWJlckVOVltmbGFnXSAhPT0gZmFsc2U7CiAgICAgIH0gZWxzZSBpZiAoZGVmYXVsdFZhbHVlID09PSBmYWxzZSkgewogICAgICAgIEVOVltmbGFnXSA9IEVtYmVyRU5WW2ZsYWddID09PSB0cnVlOwogICAgICB9CiAgICB9CgogICAgdmFyIEVYVEVORF9QUk9UT1RZUEVTID0gRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVM7CgogICAgaWYgKEVYVEVORF9QUk9UT1RZUEVTICE9PSB1bmRlZmluZWQpIHsKICAgICAgaWYgKHR5cGVvZiBFWFRFTkRfUFJPVE9UWVBFUyA9PT0gJ29iamVjdCcgJiYgRVhURU5EX1BST1RPVFlQRVMgIT09IG51bGwpIHsKICAgICAgICBFTlYuRVhURU5EX1BST1RPVFlQRVMuU3RyaW5nID0gRVhURU5EX1BST1RPVFlQRVMuU3RyaW5nICE9PSBmYWxzZTsKCiAgICAgICAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuRlVOQ1RJT05fUFJPVE9UWVBFX0VYVEVOU0lPTlMpIHsKICAgICAgICAgIEVOVi5FWFRFTkRfUFJPVE9UWVBFUy5GdW5jdGlvbiA9IEVYVEVORF9QUk9UT1RZUEVTLkZ1bmN0aW9uICE9PSBmYWxzZTsKICAgICAgICB9CgogICAgICAgIEVOVi5FWFRFTkRfUFJPVE9UWVBFUy5BcnJheSA9IEVYVEVORF9QUk9UT1RZUEVTLkFycmF5ICE9PSBmYWxzZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgaXNFbmFibGVkID0gRVhURU5EX1BST1RPVFlQRVMgIT09IGZhbHNlOwogICAgICAgIEVOVi5FWFRFTkRfUFJPVE9UWVBFUy5TdHJpbmcgPSBpc0VuYWJsZWQ7CgogICAgICAgIGlmIChfZGVwcmVjYXRlZEZlYXR1cmVzLkZVTkNUSU9OX1BST1RPVFlQRV9FWFRFTlNJT05TKSB7CiAgICAgICAgICBFTlYuRVhURU5EX1BST1RPVFlQRVMuRnVuY3Rpb24gPSBpc0VuYWJsZWQ7CiAgICAgICAgfQoKICAgICAgICBFTlYuRVhURU5EX1BST1RPVFlQRVMuQXJyYXkgPSBpc0VuYWJsZWQ7CiAgICAgIH0KICAgIH0gLy8gVE9ETyB0aGlzIGRvZXMgbm90IHNlZW0gdG8gYmUgdXNlZCBieSBhbnl0aGluZywKICAgIC8vICAgICAgY2FuIHdlIHJlbW92ZSBpdD8gZG8gd2UgbmVlZCB0byBkZXByZWNhdGUgaXQ/CgoKICAgIHZhciBFTUJFUl9MT0FEX0hPT0tTID0gRW1iZXJFTlYuRU1CRVJfTE9BRF9IT09LUzsKCiAgICBpZiAodHlwZW9mIEVNQkVSX0xPQURfSE9PS1MgPT09ICdvYmplY3QnICYmIEVNQkVSX0xPQURfSE9PS1MgIT09IG51bGwpIHsKICAgICAgZm9yICh2YXIgaG9va05hbWUgaW4gRU1CRVJfTE9BRF9IT09LUykgewogICAgICAgIGlmICghRU1CRVJfTE9BRF9IT09LUy5oYXNPd25Qcm9wZXJ0eShob29rTmFtZSkpIGNvbnRpbnVlOwogICAgICAgIHZhciBob29rcyA9IEVNQkVSX0xPQURfSE9PS1NbaG9va05hbWVdOwoKICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShob29rcykpIHsKICAgICAgICAgIEVOVi5FTUJFUl9MT0FEX0hPT0tTW2hvb2tOYW1lXSA9IGhvb2tzLmZpbHRlcihmdW5jdGlvbiAoaG9vaykgewogICAgICAgICAgICByZXR1cm4gdHlwZW9mIGhvb2sgPT09ICdmdW5jdGlvbic7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KCiAgICB2YXIgRkVBVFVSRVMgPSBFbWJlckVOVi5GRUFUVVJFUzsKCiAgICBpZiAodHlwZW9mIEZFQVRVUkVTID09PSAnb2JqZWN0JyAmJiBGRUFUVVJFUyAhPT0gbnVsbCkgewogICAgICBmb3IgKHZhciBmZWF0dXJlIGluIEZFQVRVUkVTKSB7CiAgICAgICAgaWYgKCFGRUFUVVJFUy5oYXNPd25Qcm9wZXJ0eShmZWF0dXJlKSkgY29udGludWU7CiAgICAgICAgRU5WLkZFQVRVUkVTW2ZlYXR1cmVdID0gRkVBVFVSRVNbZmVhdHVyZV0gPT09IHRydWU7CiAgICAgIH0KICAgIH0KICB9KShnbG9iYWwkMS5FbWJlckVOViB8fCBnbG9iYWwkMS5FTlYpOwoKICBmdW5jdGlvbiBnZXRFTlYoKSB7CiAgICByZXR1cm4gRU5WOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvZXJyb3ItaGFuZGxpbmcvaW5kZXgiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5nZXRPbmVycm9yID0gZ2V0T25lcnJvcjsKICBfZXhwb3J0cy5zZXRPbmVycm9yID0gc2V0T25lcnJvcjsKICBfZXhwb3J0cy5nZXREaXNwYXRjaE92ZXJyaWRlID0gZ2V0RGlzcGF0Y2hPdmVycmlkZTsKICBfZXhwb3J0cy5zZXREaXNwYXRjaE92ZXJyaWRlID0gc2V0RGlzcGF0Y2hPdmVycmlkZTsKICBfZXhwb3J0cy5vbkVycm9yVGFyZ2V0ID0gdm9pZCAwOwogIHZhciBvbmVycm9yOwogIHZhciBvbkVycm9yVGFyZ2V0ID0gewogICAgZ2V0IG9uZXJyb3IoKSB7CiAgICAgIHJldHVybiBvbmVycm9yOwogICAgfQoKICB9OyAvLyBFbWJlci5vbmVycm9yIGdldHRlcgoKICBfZXhwb3J0cy5vbkVycm9yVGFyZ2V0ID0gb25FcnJvclRhcmdldDsKCiAgZnVuY3Rpb24gZ2V0T25lcnJvcigpIHsKICAgIHJldHVybiBvbmVycm9yOwogIH0gLy8gRW1iZXIub25lcnJvciBzZXR0ZXIKCgogIGZ1bmN0aW9uIHNldE9uZXJyb3IoaGFuZGxlcikgewogICAgb25lcnJvciA9IGhhbmRsZXI7CiAgfQoKICB2YXIgZGlzcGF0Y2hPdmVycmlkZTsgLy8gYWxsb3dzIHRlc3RpbmcgYWRhcHRlciB0byBvdmVycmlkZSBkaXNwYXRjaAoKICBmdW5jdGlvbiBnZXREaXNwYXRjaE92ZXJyaWRlKCkgewogICAgcmV0dXJuIGRpc3BhdGNoT3ZlcnJpZGU7CiAgfQoKICBmdW5jdGlvbiBzZXREaXNwYXRjaE92ZXJyaWRlKGhhbmRsZXIpIHsKICAgIGRpc3BhdGNoT3ZlcnJpZGUgPSBoYW5kbGVyOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvZXh0ZW5zaW9uLXN1cHBvcnQvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZXh0ZW5zaW9uLXN1cHBvcnQvbGliL2RhdGFfYWRhcHRlciIsICJAZW1iZXIvLWludGVybmFscy9leHRlbnNpb24tc3VwcG9ydC9saWIvY29udGFpbmVyX2RlYnVnX2FkYXB0ZXIiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGF0YV9hZGFwdGVyLCBfY29udGFpbmVyX2RlYnVnX2FkYXB0ZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkRhdGFBZGFwdGVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2RhdGFfYWRhcHRlci5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkNvbnRhaW5lckRlYnVnQWRhcHRlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb250YWluZXJfZGVidWdfYWRhcHRlci5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9leHRlbnNpb24tc3VwcG9ydC9saWIvY29udGFpbmVyX2RlYnVnX2FkYXB0ZXIiLCBbImV4cG9ydHMiLCAiQGVtYmVyL3N0cmluZyIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3N0cmluZywgX3J1bnRpbWUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgQGVtYmVyL2RlYnVnCiAgKi8KCiAgLyoqCiAgICBUaGUgYENvbnRhaW5lckRlYnVnQWRhcHRlcmAgaGVscHMgdGhlIGNvbnRhaW5lciBhbmQgcmVzb2x2ZXIgaW50ZXJmYWNlCiAgICB3aXRoIHRvb2xzIHRoYXQgZGVidWcgRW1iZXIgc3VjaCBhcyB0aGUKICAgIFtFbWJlciBJbnNwZWN0b3JdKGh0dHBzOi8vZ2l0aHViLmNvbS9lbWJlcmpzL2VtYmVyLWluc3BlY3RvcikKICAgIGZvciBDaHJvbWUgYW5kIEZpcmVmb3guCiAgCiAgICBUaGlzIGNsYXNzIGNhbiBiZSBleHRlbmRlZCBieSBhIGN1c3RvbSByZXNvbHZlciBpbXBsZW1lbnRlcgogICAgdG8gb3ZlcnJpZGUgc29tZSBvZiB0aGUgbWV0aG9kcyB3aXRoIGxpYnJhcnktc3BlY2lmaWMgY29kZS4KICAKICAgIFRoZSBtZXRob2RzIGxpa2VseSB0byBiZSBvdmVycmlkZGVuIGFyZToKICAKICAgICogYGNhbkNhdGFsb2dFbnRyaWVzQnlUeXBlYAogICAgKiBgY2F0YWxvZ0VudHJpZXNCeVR5cGVgCiAgCiAgICBUaGUgYWRhcHRlciB3aWxsIG5lZWQgdG8gYmUgcmVnaXN0ZXJlZAogICAgaW4gdGhlIGFwcGxpY2F0aW9uJ3MgY29udGFpbmVyIGFzIGBjb250YWluZXItZGVidWctYWRhcHRlcjptYWluYC4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBBcHBsaWNhdGlvbi5pbml0aWFsaXplcih7CiAgICAgIG5hbWU6ICJjb250YWluZXJEZWJ1Z0FkYXB0ZXIiLAogIAogICAgICBpbml0aWFsaXplKGFwcGxpY2F0aW9uKSB7CiAgICAgICAgYXBwbGljYXRpb24ucmVnaXN0ZXIoJ2NvbnRhaW5lci1kZWJ1Zy1hZGFwdGVyOm1haW4nLCByZXF1aXJlKCdhcHAvY29udGFpbmVyLWRlYnVnLWFkYXB0ZXInKSk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBAY2xhc3MgQ29udGFpbmVyRGVidWdBZGFwdGVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHNpbmNlIDEuNS4wCiAgICBAcHVibGljCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfcnVudGltZS5PYmplY3QuZXh0ZW5kKHsKICAgIC8qKgogICAgICBUaGUgcmVzb2x2ZXIgaW5zdGFuY2Ugb2YgdGhlIGFwcGxpY2F0aW9uCiAgICAgIGJlaW5nIGRlYnVnZ2VkLiBUaGlzIHByb3BlcnR5IHdpbGwgYmUgaW5qZWN0ZWQKICAgICAgb24gY3JlYXRpb24uCiAgICAgICBAcHJvcGVydHkgcmVzb2x2ZXIKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwogICAgcmVzb2x2ZXI6IG51bGwsCgogICAgLyoqCiAgICAgIFJldHVybnMgdHJ1ZSBpZiBpdCBpcyBwb3NzaWJsZSB0byBjYXRhbG9nIGEgbGlzdCBvZiBhdmFpbGFibGUKICAgICAgY2xhc3NlcyBpbiB0aGUgcmVzb2x2ZXIgZm9yIGEgZ2l2ZW4gdHlwZS4KICAgICAgIEBtZXRob2QgY2FuQ2F0YWxvZ0VudHJpZXNCeVR5cGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IHR5cGUgVGhlIHR5cGUuIGUuZy4gIm1vZGVsIiwgImNvbnRyb2xsZXIiLCAicm91dGUiLgogICAgICBAcmV0dXJuIHtib29sZWFufSB3aGV0aGVyIGEgbGlzdCBpcyBhdmFpbGFibGUgZm9yIHRoaXMgdHlwZS4KICAgICAgQHB1YmxpYwogICAgKi8KICAgIGNhbkNhdGFsb2dFbnRyaWVzQnlUeXBlOiBmdW5jdGlvbiBjYW5DYXRhbG9nRW50cmllc0J5VHlwZSh0eXBlKSB7CiAgICAgIGlmICh0eXBlID09PSAnbW9kZWwnIHx8IHR5cGUgPT09ICd0ZW1wbGF0ZScpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIHJldHVybiB0cnVlOwogICAgfSwKCiAgICAvKioKICAgICAgUmV0dXJucyB0aGUgYXZhaWxhYmxlIGNsYXNzZXMgYSBnaXZlbiB0eXBlLgogICAgICAgQG1ldGhvZCBjYXRhbG9nRW50cmllc0J5VHlwZQogICAgICBAcGFyYW0ge1N0cmluZ30gdHlwZSBUaGUgdHlwZS4gZS5nLiAibW9kZWwiLCAiY29udHJvbGxlciIsICJyb3V0ZSIuCiAgICAgIEByZXR1cm4ge0FycmF5fSBBbiBhcnJheSBvZiBzdHJpbmdzLgogICAgICBAcHVibGljCiAgICAqLwogICAgY2F0YWxvZ0VudHJpZXNCeVR5cGU6IGZ1bmN0aW9uIGNhdGFsb2dFbnRyaWVzQnlUeXBlKHR5cGUpIHsKICAgICAgdmFyIG5hbWVzcGFjZXMgPSAoMCwgX3J1bnRpbWUuQSkoX3J1bnRpbWUuTmFtZXNwYWNlLk5BTUVTUEFDRVMpOwogICAgICB2YXIgdHlwZXMgPSAoMCwgX3J1bnRpbWUuQSkoKTsKICAgICAgdmFyIHR5cGVTdWZmaXhSZWdleCA9IG5ldyBSZWdFeHAoKDAsIF9zdHJpbmcuY2xhc3NpZnkpKHR5cGUpICsgIiQiKTsKICAgICAgbmFtZXNwYWNlcy5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lc3BhY2UpIHsKICAgICAgICBmb3IgKHZhciBrZXkgaW4gbmFtZXNwYWNlKSB7CiAgICAgICAgICBpZiAoIW5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQoKICAgICAgICAgIGlmICh0eXBlU3VmZml4UmVnZXgudGVzdChrZXkpKSB7CiAgICAgICAgICAgIHZhciBrbGFzcyA9IG5hbWVzcGFjZVtrZXldOwoKICAgICAgICAgICAgaWYgKCgwLCBfcnVudGltZS50eXBlT2YpKGtsYXNzKSA9PT0gJ2NsYXNzJykgewogICAgICAgICAgICAgIHR5cGVzLnB1c2goKDAsIF9zdHJpbmcuZGFzaGVyaXplKShrZXkucmVwbGFjZSh0eXBlU3VmZml4UmVnZXgsICcnKSkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIHR5cGVzOwogICAgfQogIH0pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL2V4dGVuc2lvbi1zdXBwb3J0L2xpYi9kYXRhX2FkYXB0ZXIiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvb3duZXIiLCAiQGVtYmVyL3J1bmxvb3AiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL3N0cmluZyIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX293bmVyLCBfcnVubG9vcCwgX21ldGFsLCBfc3RyaW5nLCBfcnVudGltZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvZGVidWcKICAqLwoKICAvKioKICAgIFRoZSBgRGF0YUFkYXB0ZXJgIGhlbHBzIGEgZGF0YSBwZXJzaXN0ZW5jZSBsaWJyYXJ5CiAgICBpbnRlcmZhY2Ugd2l0aCB0b29scyB0aGF0IGRlYnVnIEVtYmVyIHN1Y2gKICAgIGFzIHRoZSBbRW1iZXIgSW5zcGVjdG9yXShodHRwczovL2dpdGh1Yi5jb20vZW1iZXJqcy9lbWJlci1pbnNwZWN0b3IpCiAgICBmb3IgQ2hyb21lIGFuZCBGaXJlZm94LgogIAogICAgVGhpcyBjbGFzcyB3aWxsIGJlIGV4dGVuZGVkIGJ5IGEgcGVyc2lzdGVuY2UgbGlicmFyeQogICAgd2hpY2ggd2lsbCBvdmVycmlkZSBzb21lIG9mIHRoZSBtZXRob2RzIHdpdGgKICAgIGxpYnJhcnktc3BlY2lmaWMgY29kZS4KICAKICAgIFRoZSBtZXRob2RzIGxpa2VseSB0byBiZSBvdmVycmlkZGVuIGFyZToKICAKICAgICogYGdldEZpbHRlcnNgCiAgICAqIGBkZXRlY3RgCiAgICAqIGBjb2x1bW5zRm9yVHlwZWAKICAgICogYGdldFJlY29yZHNgCiAgICAqIGBnZXRSZWNvcmRDb2x1bW5WYWx1ZXNgCiAgICAqIGBnZXRSZWNvcmRLZXl3b3Jkc2AKICAgICogYGdldFJlY29yZEZpbHRlclZhbHVlc2AKICAgICogYGdldFJlY29yZENvbG9yYAogICAgKiBgb2JzZXJ2ZVJlY29yZGAKICAKICAgIFRoZSBhZGFwdGVyIHdpbGwgbmVlZCB0byBiZSByZWdpc3RlcmVkCiAgICBpbiB0aGUgYXBwbGljYXRpb24ncyBjb250YWluZXIgYXMgYGRhdGFBZGFwdGVyOm1haW5gLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIEFwcGxpY2F0aW9uLmluaXRpYWxpemVyKHsKICAgICAgbmFtZTogImRhdGEtYWRhcHRlciIsCiAgCiAgICAgIGluaXRpYWxpemU6IGZ1bmN0aW9uKGFwcGxpY2F0aW9uKSB7CiAgICAgICAgYXBwbGljYXRpb24ucmVnaXN0ZXIoJ2RhdGEtYWRhcHRlcjptYWluJywgRFMuRGF0YUFkYXB0ZXIpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQGNsYXNzIERhdGFBZGFwdGVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHB1YmxpYwogICovCiAgdmFyIF9kZWZhdWx0ID0gX3J1bnRpbWUuT2JqZWN0LmV4dGVuZCh7CiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgdGhpcy5yZWxlYXNlTWV0aG9kcyA9ICgwLCBfcnVudGltZS5BKSgpOwogICAgfSwKCiAgICAvKioKICAgICAgVGhlIGNvbnRhaW5lci1kZWJ1Zy1hZGFwdGVyIHdoaWNoIGlzIHVzZWQKICAgICAgdG8gbGlzdCBhbGwgbW9kZWxzLgogICAgICAgQHByb3BlcnR5IGNvbnRhaW5lckRlYnVnQWRhcHRlcgogICAgICBAZGVmYXVsdCB1bmRlZmluZWQKICAgICAgQHNpbmNlIDEuNS4wCiAgICAgIEBwdWJsaWMKICAgICoqLwogICAgY29udGFpbmVyRGVidWdBZGFwdGVyOiB1bmRlZmluZWQsCgogICAgLyoqCiAgICAgIFRoZSBudW1iZXIgb2YgYXR0cmlidXRlcyB0byBzZW5kCiAgICAgIGFzIGNvbHVtbnMuIChFbm91Z2ggdG8gbWFrZSB0aGUgcmVjb3JkCiAgICAgIGlkZW50aWZpYWJsZSkuCiAgICAgICBAcHJpdmF0ZQogICAgICBAcHJvcGVydHkgYXR0cmlidXRlTGltaXQKICAgICAgQGRlZmF1bHQgMwogICAgICBAc2luY2UgMS4zLjAKICAgICovCiAgICBhdHRyaWJ1dGVMaW1pdDogMywKCiAgICAvKioKICAgICAgIEVtYmVyIERhdGEgPiB2MS4wLjAtYmV0YS4xOAogICAgICAgcmVxdWlyZXMgc3RyaW5nIG1vZGVsIG5hbWVzIHRvIGJlIHBhc3NlZAogICAgICAgYXJvdW5kIGluc3RlYWQgb2YgdGhlIGFjdHVhbCBmYWN0b3JpZXMuCiAgICAgICAgVGhpcyBpcyBhIHN0YW1wIGZvciB0aGUgRW1iZXIgSW5zcGVjdG9yCiAgICAgICB0byBkaWZmZXJlbnRpYXRlIGJldHdlZW4gdGhlIHZlcnNpb25zCiAgICAgICB0byBiZSBhYmxlIHRvIHN1cHBvcnQgb2xkZXIgdmVyc2lvbnMgdG9vLgogICAgICAgIEBwdWJsaWMKICAgICAgIEBwcm9wZXJ0eSBhY2NlcHRzTW9kZWxOYW1lCiAgICAgKi8KICAgIGFjY2VwdHNNb2RlbE5hbWU6IHRydWUsCgogICAgLyoqCiAgICAgIFN0b3JlcyBhbGwgbWV0aG9kcyB0aGF0IGNsZWFyIG9ic2VydmVycy4KICAgICAgVGhlc2UgbWV0aG9kcyB3aWxsIGJlIGNhbGxlZCBvbiBkZXN0cnVjdGlvbi4KICAgICAgIEBwcml2YXRlCiAgICAgIEBwcm9wZXJ0eSByZWxlYXNlTWV0aG9kcwogICAgICBAc2luY2UgMS4zLjAKICAgICovCiAgICByZWxlYXNlTWV0aG9kczogKDAsIF9ydW50aW1lLkEpKCksCgogICAgLyoqCiAgICAgIFNwZWNpZmllcyBob3cgcmVjb3JkcyBjYW4gYmUgZmlsdGVyZWQuCiAgICAgIFJlY29yZHMgcmV0dXJuZWQgd2lsbCBuZWVkIHRvIGhhdmUgYSBgZmlsdGVyVmFsdWVzYAogICAgICBwcm9wZXJ0eSB3aXRoIGEga2V5IGZvciBldmVyeSBuYW1lIGluIHRoZSByZXR1cm5lZCBhcnJheS4KICAgICAgIEBwdWJsaWMKICAgICAgQG1ldGhvZCBnZXRGaWx0ZXJzCiAgICAgIEByZXR1cm4ge0FycmF5fSBMaXN0IG9mIG9iamVjdHMgZGVmaW5pbmcgZmlsdGVycy4KICAgICAgIFRoZSBvYmplY3Qgc2hvdWxkIGhhdmUgYSBgbmFtZWAgYW5kIGBkZXNjYCBwcm9wZXJ0eS4KICAgICovCiAgICBnZXRGaWx0ZXJzOiBmdW5jdGlvbiBnZXRGaWx0ZXJzKCkgewogICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBGZXRjaCB0aGUgbW9kZWwgdHlwZXMgYW5kIG9ic2VydmUgdGhlbSBmb3IgY2hhbmdlcy4KICAgICAgIEBwdWJsaWMKICAgICAgQG1ldGhvZCB3YXRjaE1vZGVsVHlwZXMKICAgICAgIEBwYXJhbSB7RnVuY3Rpb259IHR5cGVzQWRkZWQgQ2FsbGJhY2sgdG8gY2FsbCB0byBhZGQgdHlwZXMuCiAgICAgIFRha2VzIGFuIGFycmF5IG9mIG9iamVjdHMgY29udGFpbmluZyB3cmFwcGVkIHR5cGVzIChyZXR1cm5lZCBmcm9tIGB3cmFwTW9kZWxUeXBlYCkuCiAgICAgICBAcGFyYW0ge0Z1bmN0aW9ufSB0eXBlc1VwZGF0ZWQgQ2FsbGJhY2sgdG8gY2FsbCB3aGVuIGEgdHlwZSBoYXMgY2hhbmdlZC4KICAgICAgVGFrZXMgYW4gYXJyYXkgb2Ygb2JqZWN0cyBjb250YWluaW5nIHdyYXBwZWQgdHlwZXMuCiAgICAgICBAcmV0dXJuIHtGdW5jdGlvbn0gTWV0aG9kIHRvIGNhbGwgdG8gcmVtb3ZlIGFsbCBvYnNlcnZlcnMKICAgICovCiAgICB3YXRjaE1vZGVsVHlwZXM6IGZ1bmN0aW9uIHdhdGNoTW9kZWxUeXBlcyh0eXBlc0FkZGVkLCB0eXBlc1VwZGF0ZWQpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHZhciBtb2RlbFR5cGVzID0gdGhpcy5nZXRNb2RlbFR5cGVzKCk7CiAgICAgIHZhciByZWxlYXNlTWV0aG9kcyA9ICgwLCBfcnVudGltZS5BKSgpOwogICAgICB2YXIgdHlwZXNUb1NlbmQ7CiAgICAgIHR5cGVzVG9TZW5kID0gbW9kZWxUeXBlcy5tYXAoZnVuY3Rpb24gKHR5cGUpIHsKICAgICAgICB2YXIga2xhc3MgPSB0eXBlLmtsYXNzOwoKICAgICAgICB2YXIgd3JhcHBlZCA9IF90aGlzLndyYXBNb2RlbFR5cGUoa2xhc3MsIHR5cGUubmFtZSk7CgogICAgICAgIHJlbGVhc2VNZXRob2RzLnB1c2goX3RoaXMub2JzZXJ2ZU1vZGVsVHlwZSh0eXBlLm5hbWUsIHR5cGVzVXBkYXRlZCkpOwogICAgICAgIHJldHVybiB3cmFwcGVkOwogICAgICB9KTsKICAgICAgdHlwZXNBZGRlZCh0eXBlc1RvU2VuZCk7CgogICAgICB2YXIgcmVsZWFzZSA9IGZ1bmN0aW9uIHJlbGVhc2UoKSB7CiAgICAgICAgcmVsZWFzZU1ldGhvZHMuZm9yRWFjaChmdW5jdGlvbiAoZm4pIHsKICAgICAgICAgIHJldHVybiBmbigpOwogICAgICAgIH0pOwoKICAgICAgICBfdGhpcy5yZWxlYXNlTWV0aG9kcy5yZW1vdmVPYmplY3QocmVsZWFzZSk7CiAgICAgIH07CgogICAgICB0aGlzLnJlbGVhc2VNZXRob2RzLnB1c2hPYmplY3QocmVsZWFzZSk7CiAgICAgIHJldHVybiByZWxlYXNlOwogICAgfSwKICAgIF9uYW1lVG9DbGFzczogZnVuY3Rpb24gX25hbWVUb0NsYXNzKHR5cGUpIHsKICAgICAgaWYgKHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJykgewogICAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICAgIHZhciBGYWN0b3J5ID0gb3duZXIuZmFjdG9yeUZvcigibW9kZWw6IiArIHR5cGUpOwogICAgICAgIHR5cGUgPSBGYWN0b3J5ICYmIEZhY3RvcnkuY2xhc3M7CiAgICAgIH0KCiAgICAgIHJldHVybiB0eXBlOwogICAgfSwKCiAgICAvKioKICAgICAgRmV0Y2ggdGhlIHJlY29yZHMgb2YgYSBnaXZlbiB0eXBlIGFuZCBvYnNlcnZlIHRoZW0gZm9yIGNoYW5nZXMuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2Qgd2F0Y2hSZWNvcmRzCiAgICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lIFRoZSBtb2RlbCBuYW1lLgogICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gcmVjb3Jkc0FkZGVkIENhbGxiYWNrIHRvIGNhbGwgdG8gYWRkIHJlY29yZHMuCiAgICAgIFRha2VzIGFuIGFycmF5IG9mIG9iamVjdHMgY29udGFpbmluZyB3cmFwcGVkIHJlY29yZHMuCiAgICAgIFRoZSBvYmplY3Qgc2hvdWxkIGhhdmUgdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzOgogICAgICAgIGNvbHVtblZhbHVlczoge09iamVjdH0gVGhlIGtleSBhbmQgdmFsdWUgb2YgYSB0YWJsZSBjZWxsLgogICAgICAgIG9iamVjdDoge09iamVjdH0gVGhlIGFjdHVhbCByZWNvcmQgb2JqZWN0LgogICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gcmVjb3Jkc1VwZGF0ZWQgQ2FsbGJhY2sgdG8gY2FsbCB3aGVuIGEgcmVjb3JkIGhhcyBjaGFuZ2VkLgogICAgICBUYWtlcyBhbiBhcnJheSBvZiBvYmplY3RzIGNvbnRhaW5pbmcgd3JhcHBlZCByZWNvcmRzLgogICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gcmVjb3Jkc1JlbW92ZWQgQ2FsbGJhY2sgdG8gY2FsbCB3aGVuIGEgcmVjb3JkIGhhcyByZW1vdmVkLgogICAgICBUYWtlcyB0aGUgZm9sbG93aW5nIHBhcmFtZXRlcnM6CiAgICAgICAgaW5kZXg6IFRoZSBhcnJheSBpbmRleCB3aGVyZSB0aGUgcmVjb3JkcyB3ZXJlIHJlbW92ZWQuCiAgICAgICAgY291bnQ6IFRoZSBudW1iZXIgb2YgcmVjb3JkcyByZW1vdmVkLgogICAgICAgQHJldHVybiB7RnVuY3Rpb259IE1ldGhvZCB0byBjYWxsIHRvIHJlbW92ZSBhbGwgb2JzZXJ2ZXJzLgogICAgKi8KICAgIHdhdGNoUmVjb3JkczogZnVuY3Rpb24gd2F0Y2hSZWNvcmRzKG1vZGVsTmFtZSwgcmVjb3Jkc0FkZGVkLCByZWNvcmRzVXBkYXRlZCwgcmVjb3Jkc1JlbW92ZWQpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICB2YXIgcmVsZWFzZU1ldGhvZHMgPSAoMCwgX3J1bnRpbWUuQSkoKTsKCiAgICAgIHZhciBrbGFzcyA9IHRoaXMuX25hbWVUb0NsYXNzKG1vZGVsTmFtZSk7CgogICAgICB2YXIgcmVjb3JkcyA9IHRoaXMuZ2V0UmVjb3JkcyhrbGFzcywgbW9kZWxOYW1lKTsKCiAgICAgIHZhciBfcmVsZWFzZTsKCiAgICAgIGZ1bmN0aW9uIHJlY29yZFVwZGF0ZWQodXBkYXRlZFJlY29yZCkgewogICAgICAgIHJlY29yZHNVcGRhdGVkKFt1cGRhdGVkUmVjb3JkXSk7CiAgICAgIH0KCiAgICAgIHZhciByZWNvcmRzVG9TZW5kID0gcmVjb3Jkcy5tYXAoZnVuY3Rpb24gKHJlY29yZCkgewogICAgICAgIHJlbGVhc2VNZXRob2RzLnB1c2goX3RoaXMyLm9ic2VydmVSZWNvcmQocmVjb3JkLCByZWNvcmRVcGRhdGVkKSk7CiAgICAgICAgcmV0dXJuIF90aGlzMi53cmFwUmVjb3JkKHJlY29yZCk7CiAgICAgIH0pOwoKICAgICAgdmFyIGNvbnRlbnREaWRDaGFuZ2UgPSBmdW5jdGlvbiBjb250ZW50RGlkQ2hhbmdlKGFycmF5LCBpZHgsIHJlbW92ZWRDb3VudCwgYWRkZWRDb3VudCkgewogICAgICAgIGZvciAodmFyIGkgPSBpZHg7IGkgPCBpZHggKyBhZGRlZENvdW50OyBpKyspIHsKICAgICAgICAgIHZhciByZWNvcmQgPSAoMCwgX21ldGFsLm9iamVjdEF0KShhcnJheSwgaSk7CgogICAgICAgICAgdmFyIHdyYXBwZWQgPSBfdGhpczIud3JhcFJlY29yZChyZWNvcmQpOwoKICAgICAgICAgIHJlbGVhc2VNZXRob2RzLnB1c2goX3RoaXMyLm9ic2VydmVSZWNvcmQocmVjb3JkLCByZWNvcmRVcGRhdGVkKSk7CiAgICAgICAgICByZWNvcmRzQWRkZWQoW3dyYXBwZWRdKTsKICAgICAgICB9CgogICAgICAgIGlmIChyZW1vdmVkQ291bnQpIHsKICAgICAgICAgIHJlY29yZHNSZW1vdmVkKGlkeCwgcmVtb3ZlZENvdW50KTsKICAgICAgICB9CiAgICAgIH07CgogICAgICB2YXIgb2JzZXJ2ZXIgPSB7CiAgICAgICAgZGlkQ2hhbmdlOiBjb250ZW50RGlkQ2hhbmdlLAogICAgICAgIHdpbGxDaGFuZ2U6IGZ1bmN0aW9uIHdpbGxDaGFuZ2UoKSB7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH07CiAgICAgICgwLCBfbWV0YWwuYWRkQXJyYXlPYnNlcnZlcikocmVjb3JkcywgdGhpcywgb2JzZXJ2ZXIpOwoKICAgICAgX3JlbGVhc2UgPSBmdW5jdGlvbiByZWxlYXNlKCkgewogICAgICAgIHJlbGVhc2VNZXRob2RzLmZvckVhY2goZnVuY3Rpb24gKGZuKSB7CiAgICAgICAgICByZXR1cm4gZm4oKTsKICAgICAgICB9KTsKICAgICAgICAoMCwgX21ldGFsLnJlbW92ZUFycmF5T2JzZXJ2ZXIpKHJlY29yZHMsIF90aGlzMiwgb2JzZXJ2ZXIpOwoKICAgICAgICBfdGhpczIucmVsZWFzZU1ldGhvZHMucmVtb3ZlT2JqZWN0KF9yZWxlYXNlKTsKICAgICAgfTsKCiAgICAgIHJlY29yZHNBZGRlZChyZWNvcmRzVG9TZW5kKTsKICAgICAgdGhpcy5yZWxlYXNlTWV0aG9kcy5wdXNoT2JqZWN0KF9yZWxlYXNlKTsKICAgICAgcmV0dXJuIF9yZWxlYXNlOwogICAgfSwKCiAgICAvKioKICAgICAgQ2xlYXIgYWxsIG9ic2VydmVycyBiZWZvcmUgZGVzdHJ1Y3Rpb24KICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCB3aWxsRGVzdHJveQogICAgKi8KICAgIHdpbGxEZXN0cm95OiBmdW5jdGlvbiB3aWxsRGVzdHJveSgpIHsKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIHRoaXMucmVsZWFzZU1ldGhvZHMuZm9yRWFjaChmdW5jdGlvbiAoZm4pIHsKICAgICAgICByZXR1cm4gZm4oKTsKICAgICAgfSk7CiAgICB9LAoKICAgIC8qKgogICAgICBEZXRlY3Qgd2hldGhlciBhIGNsYXNzIGlzIGEgbW9kZWwuCiAgICAgICBUZXN0IHRoYXQgYWdhaW5zdCB0aGUgbW9kZWwgY2xhc3MKICAgICAgb2YgeW91ciBwZXJzaXN0ZW5jZSBsaWJyYXJ5LgogICAgICAgQHB1YmxpYwogICAgICBAbWV0aG9kIGRldGVjdAogICAgICBAcmV0dXJuIGJvb2xlYW4gV2hldGhlciB0aGUgY2xhc3MgaXMgYSBtb2RlbCBjbGFzcyBvciBub3QuCiAgICAqLwogICAgZGV0ZWN0OiBmdW5jdGlvbiBkZXRlY3QoKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0sCgogICAgLyoqCiAgICAgIEdldCB0aGUgY29sdW1ucyBmb3IgYSBnaXZlbiBtb2RlbCB0eXBlLgogICAgICAgQHB1YmxpYwogICAgICBAbWV0aG9kIGNvbHVtbnNGb3JUeXBlCiAgICAgIEByZXR1cm4ge0FycmF5fSBBbiBhcnJheSBvZiBjb2x1bW5zIG9mIHRoZSBmb2xsb3dpbmcgZm9ybWF0OgogICAgICAgbmFtZToge1N0cmluZ30gVGhlIG5hbWUgb2YgdGhlIGNvbHVtbi4KICAgICAgIGRlc2M6IHtTdHJpbmd9IEh1bWFuaXplZCBkZXNjcmlwdGlvbiAod2hhdCB3b3VsZCBzaG93IGluIGEgdGFibGUgY29sdW1uIG5hbWUpLgogICAgKi8KICAgIGNvbHVtbnNGb3JUeXBlOiBmdW5jdGlvbiBjb2x1bW5zRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5BKSgpOwogICAgfSwKCiAgICAvKioKICAgICAgQWRkcyBvYnNlcnZlcnMgdG8gYSBtb2RlbCB0eXBlIGNsYXNzLgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBvYnNlcnZlTW9kZWxUeXBlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUgVGhlIG1vZGVsIHR5cGUgbmFtZS4KICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gdHlwZXNVcGRhdGVkIENhbGxlZCB3aGVuIGEgdHlwZSBpcyBtb2RpZmllZC4KICAgICAgQHJldHVybiB7RnVuY3Rpb259IFRoZSBmdW5jdGlvbiB0byBjYWxsIHRvIHJlbW92ZSBvYnNlcnZlcnMuCiAgICAqLwogICAgb2JzZXJ2ZU1vZGVsVHlwZTogZnVuY3Rpb24gb2JzZXJ2ZU1vZGVsVHlwZShtb2RlbE5hbWUsIHR5cGVzVXBkYXRlZCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHZhciBrbGFzcyA9IHRoaXMuX25hbWVUb0NsYXNzKG1vZGVsTmFtZSk7CgogICAgICB2YXIgcmVjb3JkcyA9IHRoaXMuZ2V0UmVjb3JkcyhrbGFzcywgbW9kZWxOYW1lKTsKCiAgICAgIGZ1bmN0aW9uIG9uQ2hhbmdlKCkgewogICAgICAgIHR5cGVzVXBkYXRlZChbdGhpcy53cmFwTW9kZWxUeXBlKGtsYXNzLCBtb2RlbE5hbWUpXSk7CiAgICAgIH0KCiAgICAgIHZhciBvYnNlcnZlciA9IHsKICAgICAgICBkaWRDaGFuZ2U6IGZ1bmN0aW9uIGRpZENoYW5nZShhcnJheSwgaWR4LCByZW1vdmVkQ291bnQsIGFkZGVkQ291bnQpIHsKICAgICAgICAgIC8vIE9ubHkgcmUtZmV0Y2ggcmVjb3JkcyBpZiB0aGUgcmVjb3JkIGNvdW50IGNoYW5nZWQKICAgICAgICAgIC8vICh3aGljaCBpcyBhbGwgd2UgY2FyZSBhYm91dCBhcyBmYXIgYXMgbW9kZWwgdHlwZXMgYXJlIGNvbmNlcm5lZCkuCiAgICAgICAgICBpZiAocmVtb3ZlZENvdW50ID4gMCB8fCBhZGRlZENvdW50ID4gMCkgewogICAgICAgICAgICAoMCwgX3J1bmxvb3Auc2NoZWR1bGVPbmNlKSgnYWN0aW9ucycsIHRoaXMsIG9uQ2hhbmdlKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHdpbGxDaGFuZ2U6IGZ1bmN0aW9uIHdpbGxDaGFuZ2UoKSB7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH07CiAgICAgICgwLCBfbWV0YWwuYWRkQXJyYXlPYnNlcnZlcikocmVjb3JkcywgdGhpcywgb2JzZXJ2ZXIpOwoKICAgICAgdmFyIHJlbGVhc2UgPSBmdW5jdGlvbiByZWxlYXNlKCkgewogICAgICAgIHJldHVybiAoMCwgX21ldGFsLnJlbW92ZUFycmF5T2JzZXJ2ZXIpKHJlY29yZHMsIF90aGlzMywgb2JzZXJ2ZXIpOwogICAgICB9OwoKICAgICAgcmV0dXJuIHJlbGVhc2U7CiAgICB9LAoKICAgIC8qKgogICAgICBXcmFwcyBhIGdpdmVuIG1vZGVsIHR5cGUgYW5kIG9ic2VydmVzIGNoYW5nZXMgdG8gaXQuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHdyYXBNb2RlbFR5cGUKICAgICAgQHBhcmFtIHtDbGFzc30ga2xhc3MgQSBtb2RlbCBjbGFzcy4KICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZSBOYW1lIG9mIHRoZSBjbGFzcy4KICAgICAgQHJldHVybiB7T2JqZWN0fSBDb250YWlucyB0aGUgd3JhcHBlZCB0eXBlIGFuZCB0aGUgZnVuY3Rpb24gdG8gcmVtb3ZlIG9ic2VydmVycwogICAgICBGb3JtYXQ6CiAgICAgICAgdHlwZToge09iamVjdH0gVGhlIHdyYXBwZWQgdHlwZS4KICAgICAgICAgIFRoZSB3cmFwcGVkIHR5cGUgaGFzIHRoZSBmb2xsb3dpbmcgZm9ybWF0OgogICAgICAgICAgICBuYW1lOiB7U3RyaW5nfSBUaGUgbmFtZSBvZiB0aGUgdHlwZS4KICAgICAgICAgICAgY291bnQ6IHtJbnRlZ2VyfSBUaGUgbnVtYmVyIG9mIHJlY29yZHMgYXZhaWxhYmxlLgogICAgICAgICAgICBjb2x1bW5zOiB7Q29sdW1uc30gQW4gYXJyYXkgb2YgY29sdW1ucyB0byBkZXNjcmliZSB0aGUgcmVjb3JkLgogICAgICAgICAgICBvYmplY3Q6IHtDbGFzc30gVGhlIGFjdHVhbCBNb2RlbCB0eXBlIGNsYXNzLgogICAgICAgIHJlbGVhc2U6IHtGdW5jdGlvbn0gVGhlIGZ1bmN0aW9uIHRvIHJlbW92ZSBvYnNlcnZlcnMuCiAgICAqLwogICAgd3JhcE1vZGVsVHlwZTogZnVuY3Rpb24gd3JhcE1vZGVsVHlwZShrbGFzcywgbmFtZSkgewogICAgICB2YXIgcmVjb3JkcyA9IHRoaXMuZ2V0UmVjb3JkcyhrbGFzcywgbmFtZSk7CiAgICAgIHZhciB0eXBlVG9TZW5kOwogICAgICB0eXBlVG9TZW5kID0gewogICAgICAgIG5hbWU6IG5hbWUsCiAgICAgICAgY291bnQ6ICgwLCBfbWV0YWwuZ2V0KShyZWNvcmRzLCAnbGVuZ3RoJyksCiAgICAgICAgY29sdW1uczogdGhpcy5jb2x1bW5zRm9yVHlwZShrbGFzcyksCiAgICAgICAgb2JqZWN0OiBrbGFzcwogICAgICB9OwogICAgICByZXR1cm4gdHlwZVRvU2VuZDsKICAgIH0sCgogICAgLyoqCiAgICAgIEZldGNoZXMgYWxsIG1vZGVscyBkZWZpbmVkIGluIHRoZSBhcHBsaWNhdGlvbi4KICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZ2V0TW9kZWxUeXBlcwogICAgICBAcmV0dXJuIHtBcnJheX0gQXJyYXkgb2YgbW9kZWwgdHlwZXMuCiAgICAqLwogICAgZ2V0TW9kZWxUeXBlczogZnVuY3Rpb24gZ2V0TW9kZWxUeXBlcygpIHsKICAgICAgdmFyIF90aGlzNCA9IHRoaXM7CgogICAgICB2YXIgY29udGFpbmVyRGVidWdBZGFwdGVyID0gdGhpcy5nZXQoJ2NvbnRhaW5lckRlYnVnQWRhcHRlcicpOwogICAgICB2YXIgdHlwZXM7CgogICAgICBpZiAoY29udGFpbmVyRGVidWdBZGFwdGVyLmNhbkNhdGFsb2dFbnRyaWVzQnlUeXBlKCdtb2RlbCcpKSB7CiAgICAgICAgdHlwZXMgPSBjb250YWluZXJEZWJ1Z0FkYXB0ZXIuY2F0YWxvZ0VudHJpZXNCeVR5cGUoJ21vZGVsJyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdHlwZXMgPSB0aGlzLl9nZXRPYmplY3RzT25OYW1lc3BhY2VzKCk7CiAgICAgIH0gLy8gTmV3IGFkYXB0ZXJzIHJldHVybiBzdHJpbmdzIGluc3RlYWQgb2YgY2xhc3Nlcy4KCgogICAgICB0eXBlcyA9ICgwLCBfcnVudGltZS5BKSh0eXBlcykubWFwKGZ1bmN0aW9uIChuYW1lKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGtsYXNzOiBfdGhpczQuX25hbWVUb0NsYXNzKG5hbWUpLAogICAgICAgICAgbmFtZTogbmFtZQogICAgICAgIH07CiAgICAgIH0pOwogICAgICB0eXBlcyA9ICgwLCBfcnVudGltZS5BKSh0eXBlcykuZmlsdGVyKGZ1bmN0aW9uICh0eXBlKSB7CiAgICAgICAgcmV0dXJuIF90aGlzNC5kZXRlY3QodHlwZS5rbGFzcyk7CiAgICAgIH0pOwogICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKHR5cGVzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIExvb3BzIG92ZXIgYWxsIG5hbWVzcGFjZXMgYW5kIGFsbCBvYmplY3RzCiAgICAgIGF0dGFjaGVkIHRvIHRoZW0uCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9nZXRPYmplY3RzT25OYW1lc3BhY2VzCiAgICAgIEByZXR1cm4ge0FycmF5fSBBcnJheSBvZiBtb2RlbCB0eXBlIHN0cmluZ3MuCiAgICAqLwogICAgX2dldE9iamVjdHNPbk5hbWVzcGFjZXM6IGZ1bmN0aW9uIF9nZXRPYmplY3RzT25OYW1lc3BhY2VzKCkgewogICAgICB2YXIgX3RoaXM1ID0gdGhpczsKCiAgICAgIHZhciBuYW1lc3BhY2VzID0gKDAsIF9ydW50aW1lLkEpKF9ydW50aW1lLk5hbWVzcGFjZS5OQU1FU1BBQ0VTKTsKICAgICAgdmFyIHR5cGVzID0gKDAsIF9ydW50aW1lLkEpKCk7CiAgICAgIG5hbWVzcGFjZXMuZm9yRWFjaChmdW5jdGlvbiAobmFtZXNwYWNlKSB7CiAgICAgICAgZm9yICh2YXIga2V5IGluIG5hbWVzcGFjZSkgewogICAgICAgICAgaWYgKCFuYW1lc3BhY2UuaGFzT3duUHJvcGVydHkoa2V5KSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0gLy8gRXZlbiB0aG91Z2ggd2Ugd2lsbCBmaWx0ZXIgYWdhaW4gaW4gYGdldE1vZGVsVHlwZXNgLAogICAgICAgICAgLy8gd2Ugc2hvdWxkIG5vdCBjYWxsIGBsb29rdXBGYWN0b3J5YCBvbiBub24tbW9kZWxzCgoKICAgICAgICAgIGlmICghX3RoaXM1LmRldGVjdChuYW1lc3BhY2Vba2V5XSkpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CgogICAgICAgICAgdmFyIG5hbWUgPSAoMCwgX3N0cmluZy5kYXNoZXJpemUpKGtleSk7CiAgICAgICAgICB0eXBlcy5wdXNoKG5hbWUpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiB0eXBlczsKICAgIH0sCgogICAgLyoqCiAgICAgIEZldGNoZXMgYWxsIGxvYWRlZCByZWNvcmRzIGZvciBhIGdpdmVuIHR5cGUuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgZ2V0UmVjb3JkcwogICAgICBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2YgcmVjb3Jkcy4KICAgICAgIFRoaXMgYXJyYXkgd2lsbCBiZSBvYnNlcnZlZCBmb3IgY2hhbmdlcywKICAgICAgIHNvIGl0IHNob3VsZCB1cGRhdGUgd2hlbiBuZXcgcmVjb3JkcyBhcmUgYWRkZWQvcmVtb3ZlZC4KICAgICovCiAgICBnZXRSZWNvcmRzOiBmdW5jdGlvbiBnZXRSZWNvcmRzKCkgewogICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBXcmFwcyBhIHJlY29yZCBhbmQgb2JzZXJ2ZXJzIGNoYW5nZXMgdG8gaXQuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHdyYXBSZWNvcmQKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlY29yZCBUaGUgcmVjb3JkIGluc3RhbmNlLgogICAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSB3cmFwcGVkIHJlY29yZC4gRm9ybWF0OgogICAgICBjb2x1bW5WYWx1ZXM6IHtBcnJheX0KICAgICAgc2VhcmNoS2V5d29yZHM6IHtBcnJheX0KICAgICovCiAgICB3cmFwUmVjb3JkOiBmdW5jdGlvbiB3cmFwUmVjb3JkKHJlY29yZCkgewogICAgICB2YXIgcmVjb3JkVG9TZW5kID0gewogICAgICAgIG9iamVjdDogcmVjb3JkCiAgICAgIH07CiAgICAgIHJlY29yZFRvU2VuZC5jb2x1bW5WYWx1ZXMgPSB0aGlzLmdldFJlY29yZENvbHVtblZhbHVlcyhyZWNvcmQpOwogICAgICByZWNvcmRUb1NlbmQuc2VhcmNoS2V5d29yZHMgPSB0aGlzLmdldFJlY29yZEtleXdvcmRzKHJlY29yZCk7CiAgICAgIHJlY29yZFRvU2VuZC5maWx0ZXJWYWx1ZXMgPSB0aGlzLmdldFJlY29yZEZpbHRlclZhbHVlcyhyZWNvcmQpOwogICAgICByZWNvcmRUb1NlbmQuY29sb3IgPSB0aGlzLmdldFJlY29yZENvbG9yKHJlY29yZCk7CiAgICAgIHJldHVybiByZWNvcmRUb1NlbmQ7CiAgICB9LAoKICAgIC8qKgogICAgICBHZXRzIHRoZSB2YWx1ZXMgZm9yIGVhY2ggY29sdW1uLgogICAgICAgQHB1YmxpYwogICAgICBAbWV0aG9kIGdldFJlY29yZENvbHVtblZhbHVlcwogICAgICBAcmV0dXJuIHtPYmplY3R9IEtleXMgc2hvdWxkIG1hdGNoIGNvbHVtbiBuYW1lcyBkZWZpbmVkCiAgICAgIGJ5IHRoZSBtb2RlbCB0eXBlLgogICAgKi8KICAgIGdldFJlY29yZENvbHVtblZhbHVlczogZnVuY3Rpb24gZ2V0UmVjb3JkQ29sdW1uVmFsdWVzKCkgewogICAgICByZXR1cm4ge307CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIGtleXdvcmRzIHRvIG1hdGNoIHdoZW4gc2VhcmNoaW5nIHJlY29yZHMuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgZ2V0UmVjb3JkS2V5d29yZHMKICAgICAgQHJldHVybiB7QXJyYXl9IFJlbGV2YW50IGtleXdvcmRzIGZvciBzZWFyY2guCiAgICAqLwogICAgZ2V0UmVjb3JkS2V5d29yZHM6IGZ1bmN0aW9uIGdldFJlY29yZEtleXdvcmRzKCkgewogICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSB2YWx1ZXMgb2YgZmlsdGVycyBkZWZpbmVkIGJ5IGBnZXRGaWx0ZXJzYC4KICAgICAgIEBwdWJsaWMKICAgICAgQG1ldGhvZCBnZXRSZWNvcmRGaWx0ZXJWYWx1ZXMKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlY29yZCBUaGUgcmVjb3JkIGluc3RhbmNlLgogICAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSBmaWx0ZXIgdmFsdWVzLgogICAgKi8KICAgIGdldFJlY29yZEZpbHRlclZhbHVlczogZnVuY3Rpb24gZ2V0UmVjb3JkRmlsdGVyVmFsdWVzKCkgewogICAgICByZXR1cm4ge307CiAgICB9LAoKICAgIC8qKgogICAgICBFYWNoIHJlY29yZCBjYW4gaGF2ZSBhIGNvbG9yIHRoYXQgcmVwcmVzZW50cyBpdHMgc3RhdGUuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgZ2V0UmVjb3JkQ29sb3IKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlY29yZCBUaGUgcmVjb3JkIGluc3RhbmNlCiAgICAgIEByZXR1cm4ge1N0cmluZ30gVGhlIHJlY29yZHMgY29sb3IuCiAgICAgICAgUG9zc2libGUgb3B0aW9uczogYmxhY2ssIHJlZCwgYmx1ZSwgZ3JlZW4uCiAgICAqLwogICAgZ2V0UmVjb3JkQ29sb3I6IGZ1bmN0aW9uIGdldFJlY29yZENvbG9yKCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0sCgogICAgLyoqCiAgICAgIE9ic2VydmVzIGFsbCByZWxldmFudCBwcm9wZXJ0aWVzIGFuZCByZS1zZW5kcyB0aGUgd3JhcHBlZCByZWNvcmQKICAgICAgd2hlbiBhIGNoYW5nZSBvY2N1cnMuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2Qgb2JzZXJ2ZXJSZWNvcmQKICAgICAgQHJldHVybiB7RnVuY3Rpb259IFRoZSBmdW5jdGlvbiB0byBjYWxsIHRvIHJlbW92ZSBhbGwgb2JzZXJ2ZXJzLgogICAgKi8KICAgIG9ic2VydmVSZWNvcmQ6IGZ1bmN0aW9uIG9ic2VydmVSZWNvcmQoKSB7CiAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7fTsKICAgIH0KICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9nbGltbWVyL2luZGV4IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvY29udGFpbmVyIiwgIkBnbGltbWVyL29wY29kZS1jb21waWxlciIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9ydW5sb29wIiwgIkBnbGltbWVyL3JlZmVyZW5jZSIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciLCAiQGdsaW1tZXIvcnVudGltZSIsICJAZ2xpbW1lci91dGlsIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzIiwgIkBlbWJlci8taW50ZXJuYWxzL2Jyb3dzZXItZW52aXJvbm1lbnQiLCAiQGVtYmVyL2luc3RydW1lbnRhdGlvbiIsICJAZW1iZXIvc2VydmljZSIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCIsICJAZW1iZXIvc3RyaW5nIiwgIkBnbGltbWVyL3dpcmUtZm9ybWF0IiwgInJzdnAiLCAiQGdsaW1tZXIvbm9kZSIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nIiwgIkBlbWJlci9jb21wb25lbnQvdGVtcGxhdGUtb25seSIsICJAZW1iZXIvZGVwcmVjYXRlZC1mZWF0dXJlcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfcG9seWZpbGxzLCBfY29udGFpbmVyLCBfb3Bjb2RlQ29tcGlsZXIsIF9ydW50aW1lLCBfdXRpbHMsIF9ydW5sb29wLCBfcmVmZXJlbmNlLCBfbWV0YWwsIF9kZWJ1ZywgX3J1bnRpbWUyLCBfdXRpbCwgX293bmVyLCBfdmlld3MsIF9icm93c2VyRW52aXJvbm1lbnQsIF9pbnN0cnVtZW50YXRpb24sIF9zZXJ2aWNlLCBfZW52aXJvbm1lbnQyLCBfc3RyaW5nLCBfd2lyZUZvcm1hdCwgX3JzdnAsIF9ub2RlLCBfcm91dGluZywgX3RlbXBsYXRlT25seSwgX2RlcHJlY2F0ZWRGZWF0dXJlcykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMudGVtcGxhdGUgPSB0ZW1wbGF0ZTsKICBfZXhwb3J0cy5oZWxwZXIgPSBoZWxwZXI7CiAgX2V4cG9ydHMuZXNjYXBlRXhwcmVzc2lvbiA9IGVzY2FwZUV4cHJlc3Npb247CiAgX2V4cG9ydHMuaHRtbFNhZmUgPSBodG1sU2FmZTsKICBfZXhwb3J0cy5pc0hUTUxTYWZlID0gaXNIVE1MU2FmZTsKICBfZXhwb3J0cy5fcmVzZXRSZW5kZXJlcnMgPSBfcmVzZXRSZW5kZXJlcnM7CiAgX2V4cG9ydHMucmVuZGVyU2V0dGxlZCA9IHJlbmRlclNldHRsZWQ7CiAgX2V4cG9ydHMuZ2V0VGVtcGxhdGUgPSBnZXRUZW1wbGF0ZTsKICBfZXhwb3J0cy5zZXRUZW1wbGF0ZSA9IHNldFRlbXBsYXRlOwogIF9leHBvcnRzLmhhc1RlbXBsYXRlID0gaGFzVGVtcGxhdGU7CiAgX2V4cG9ydHMuZ2V0VGVtcGxhdGVzID0gZ2V0VGVtcGxhdGVzOwogIF9leHBvcnRzLnNldFRlbXBsYXRlcyA9IHNldFRlbXBsYXRlczsKICBfZXhwb3J0cy5zZXR1cEVuZ2luZVJlZ2lzdHJ5ID0gc2V0dXBFbmdpbmVSZWdpc3RyeTsKICBfZXhwb3J0cy5zZXR1cEFwcGxpY2F0aW9uUmVnaXN0cnkgPSBzZXR1cEFwcGxpY2F0aW9uUmVnaXN0cnk7CiAgX2V4cG9ydHMuX3JlZ2lzdGVyTWFjcm9zID0gcmVnaXN0ZXJNYWNyb3M7CiAgX2V4cG9ydHMuaXRlcmFibGVGb3IgPSBfaXRlcmFibGVGb3I7CiAgX2V4cG9ydHMuY2FwYWJpbGl0aWVzID0gY2FwYWJpbGl0aWVzOwogIF9leHBvcnRzLnNldENvbXBvbmVudE1hbmFnZXIgPSBzZXRDb21wb25lbnRNYW5hZ2VyOwogIF9leHBvcnRzLmdldENvbXBvbmVudE1hbmFnZXIgPSBnZXRDb21wb25lbnRNYW5hZ2VyOwogIF9leHBvcnRzLnNldE1vZGlmaWVyTWFuYWdlciA9IHNldE1vZGlmaWVyTWFuYWdlcjsKICBfZXhwb3J0cy5nZXRNb2RpZmllck1hbmFnZXIgPSBnZXRNb2RpZmllck1hbmFnZXI7CiAgX2V4cG9ydHMubW9kaWZpZXJDYXBhYmlsaXRpZXMgPSBjYXBhYmlsaXRpZXMkMTsKICBfZXhwb3J0cy5zZXRDb21wb25lbnRUZW1wbGF0ZSA9IHNldENvbXBvbmVudFRlbXBsYXRlOwogIF9leHBvcnRzLmdldENvbXBvbmVudFRlbXBsYXRlID0gZ2V0Q29tcG9uZW50VGVtcGxhdGU7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiRE9NQ2hhbmdlcyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9ydW50aW1lMi5ET01DaGFuZ2VzOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkRPTVRyZWVDb25zdHJ1Y3Rpb24iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcnVudGltZTIuRE9NVHJlZUNvbnN0cnVjdGlvbjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJpc1NlcmlhbGl6YXRpb25GaXJzdE5vZGUiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcnVudGltZTIuaXNTZXJpYWxpemF0aW9uRmlyc3ROb2RlOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIk5vZGVET01UcmVlQ29uc3RydWN0aW9uIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX25vZGUuTm9kZURPTVRyZWVDb25zdHJ1Y3Rpb247CiAgICB9CiAgfSk7CiAgX2V4cG9ydHMuT3V0bGV0VmlldyA9IF9leHBvcnRzLkRlYnVnU3RhY2sgPSBfZXhwb3J0cy5JTlZPS0UgPSBfZXhwb3J0cy5VcGRhdGFibGVSZWZlcmVuY2UgPSBfZXhwb3J0cy5BYnN0cmFjdENvbXBvbmVudE1hbmFnZXIgPSBfZXhwb3J0cy5fZXhwZXJpbWVudGFsTWFjcm9zID0gX2V4cG9ydHMuSW50ZXJhY3RpdmVSZW5kZXJlciA9IF9leHBvcnRzLkluZXJ0UmVuZGVyZXIgPSBfZXhwb3J0cy5SZW5kZXJlciA9IF9leHBvcnRzLlNhZmVTdHJpbmcgPSBfZXhwb3J0cy5FbnZpcm9ubWVudCA9IF9leHBvcnRzLkhlbHBlciA9IF9leHBvcnRzLlJPT1RfUkVGID0gX2V4cG9ydHMuQ29tcG9uZW50ID0gX2V4cG9ydHMuTGlua0NvbXBvbmVudCA9IF9leHBvcnRzLlRleHRBcmVhID0gX2V4cG9ydHMuVGV4dEZpZWxkID0gX2V4cG9ydHMuQ2hlY2tib3ggPSBfZXhwb3J0cy50ZW1wbGF0ZUNhY2hlQ291bnRlcnMgPSBfZXhwb3J0cy5Sb290VGVtcGxhdGUgPSB2b2lkIDA7CgogIHZhciBfQ29yZVZpZXckZXh0ZW5kOwoKICBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3QxMCgpIHsKICAgIHZhciBkYXRhID0gKDAsIF9lbWJlckJhYmVsLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlKShbImNvbXBvbmVudDotZGVmYXVsdCJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3QxMCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDEwKCkgewogICAgICByZXR1cm4gZGF0YTsKICAgIH07CgogICAgcmV0dXJuIGRhdGE7CiAgfQoKICBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3Q5KCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsidGVtcGxhdGUtY29tcGlsZXI6bWFpbiJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3Q5ID0gZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0OSgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0OCgpIHsKICAgIHZhciBkYXRhID0gKDAsIF9lbWJlckJhYmVsLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlKShbInRlbXBsYXRlLWNvbXBpbGVyOm1haW4iXSk7CgogICAgX3RlbXBsYXRlT2JqZWN0OCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDgoKSB7CiAgICAgIHJldHVybiBkYXRhOwogICAgfTsKCiAgICByZXR1cm4gZGF0YTsKICB9CgogIGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDcoKSB7CiAgICB2YXIgZGF0YSA9ICgwLCBfZW1iZXJCYWJlbC50YWdnZWRUZW1wbGF0ZUxpdGVyYWxMb29zZSkoWyJ0ZW1wbGF0ZTpjb21wb25lbnRzLy1kZWZhdWx0Il0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdDcgPSBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3Q3KCkgewogICAgICByZXR1cm4gZGF0YTsKICAgIH07CgogICAgcmV0dXJuIGRhdGE7CiAgfQoKICBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3Q2KCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsidGVtcGxhdGU6LXJvb3QiXSk7CgogICAgX3RlbXBsYXRlT2JqZWN0NiA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDYoKSB7CiAgICAgIHJldHVybiBkYXRhOwogICAgfTsKCiAgICByZXR1cm4gZGF0YTsKICB9CgogIGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDUoKSB7CiAgICB2YXIgZGF0YSA9ICgwLCBfZW1iZXJCYWJlbC50YWdnZWRUZW1wbGF0ZUxpdGVyYWxMb29zZSkoWyJ0ZW1wbGF0ZTotcm9vdCJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3Q1ID0gZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0NSgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0NCgpIHsKICAgIHZhciBkYXRhID0gKDAsIF9lbWJlckJhYmVsLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlKShbImNvbXBvbmVudDotZGVmYXVsdCJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3Q0ID0gZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0NCgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0MygpIHsKICAgIHZhciBkYXRhID0gKDAsIF9lbWJlckJhYmVsLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlKShbInRlbXBsYXRlOmNvbXBvbmVudHMvLWRlZmF1bHQiXSk7CgogICAgX3RlbXBsYXRlT2JqZWN0MyA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDMoKSB7CiAgICAgIHJldHVybiBkYXRhOwogICAgfTsKCiAgICByZXR1cm4gZGF0YTsKICB9CgogIGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDIoKSB7CiAgICB2YXIgZGF0YSA9ICgwLCBfZW1iZXJCYWJlbC50YWdnZWRUZW1wbGF0ZUxpdGVyYWxMb29zZSkoWyJ0ZW1wbGF0ZTpjb21wb25lbnRzLy1kZWZhdWx0Il0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdDIgPSBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3QyKCkgewogICAgICByZXR1cm4gZGF0YTsKICAgIH07CgogICAgcmV0dXJuIGRhdGE7CiAgfQoKICBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3QoKSB7CiAgICB2YXIgZGF0YSA9ICgwLCBfZW1iZXJCYWJlbC50YWdnZWRUZW1wbGF0ZUxpdGVyYWxMb29zZSkoWyJ0ZW1wbGF0ZS1jb21waWxlcjptYWluIl0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdCgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gaXNUZW1wbGF0ZUZhY3RvcnkodGVtcGxhdGUpIHsKICAgIHJldHVybiB0eXBlb2YgdGVtcGxhdGUgPT09ICdmdW5jdGlvbic7CiAgfQoKICB2YXIgY291bnRlcnMgPSB7CiAgICBjYWNoZUhpdDogMCwKICAgIGNhY2hlTWlzczogMAogIH07CiAgX2V4cG9ydHMudGVtcGxhdGVDYWNoZUNvdW50ZXJzID0gY291bnRlcnM7CiAgdmFyIFRFTVBMQVRFX0NPTVBJTEVSX01BSU4gPSAoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdCgpKTsKCiAgZnVuY3Rpb24gdGVtcGxhdGUoanNvbikgewogICAgdmFyIGdsaW1tZXJGYWN0b3J5ID0gKDAsIF9vcGNvZGVDb21waWxlci50ZW1wbGF0ZUZhY3RvcnkpKGpzb24pOwogICAgdmFyIGNhY2hlID0gbmV3IFdlYWtNYXAoKTsKCiAgICB2YXIgZmFjdG9yeSA9IGZ1bmN0aW9uIGZhY3Rvcnkob3duZXIpIHsKICAgICAgdmFyIHJlc3VsdCA9IGNhY2hlLmdldChvd25lcik7CgogICAgICBpZiAocmVzdWx0ID09PSB1bmRlZmluZWQpIHsKICAgICAgICBjb3VudGVycy5jYWNoZU1pc3MrKzsKICAgICAgICB2YXIgY29tcGlsZXIgPSBvd25lci5sb29rdXAoVEVNUExBVEVfQ09NUElMRVJfTUFJTik7CiAgICAgICAgcmVzdWx0ID0gZ2xpbW1lckZhY3RvcnkuY3JlYXRlKGNvbXBpbGVyLCB7CiAgICAgICAgICBvd25lcjogb3duZXIKICAgICAgICB9KTsKICAgICAgICBjYWNoZS5zZXQob3duZXIsIHJlc3VsdCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY291bnRlcnMuY2FjaGVIaXQrKzsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH07CgogICAgZmFjdG9yeS5fX2lkID0gZ2xpbW1lckZhY3RvcnkuaWQ7CiAgICBmYWN0b3J5Ll9fbWV0YSA9IGdsaW1tZXJGYWN0b3J5Lm1ldGE7CiAgICByZXR1cm4gZmFjdG9yeTsKICB9CgogIHZhciBSb290VGVtcGxhdGUgPSB0ZW1wbGF0ZSh7CiAgICAiaWQiOiAiaGpoeFVvcnUiLAogICAgImJsb2NrIjogIntcInN5bWJvbHNcIjpbXSxcInN0YXRlbWVudHNcIjpbWzEsWzI4LFwiY29tcG9uZW50XCIsW1syMywwLFtdXV0sbnVsbF0sZmFsc2VdXSxcImhhc0V2YWxcIjpmYWxzZX0iLAogICAgIm1ldGEiOiB7CiAgICAgICJtb2R1bGVOYW1lIjogInBhY2thZ2VzL0BlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIvbGliL3RlbXBsYXRlcy9yb290LmhicyIKICAgIH0KICB9KTsKICAvKioKICBAbW9kdWxlIEBlbWJlci9jb21wb25lbnQKICAqLwoKICBfZXhwb3J0cy5Sb290VGVtcGxhdGUgPSBSb290VGVtcGxhdGU7CiAgdmFyIFJFQ09NUFVURV9UQUcgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ1JFQ09NUFVURV9UQUcnKTsKCiAgZnVuY3Rpb24gaXNIZWxwZXJGYWN0b3J5KGhlbHBlcikgewogICAgcmV0dXJuIHR5cGVvZiBoZWxwZXIgPT09ICdvYmplY3QnICYmIGhlbHBlciAhPT0gbnVsbCAmJiBoZWxwZXIuY2xhc3MgJiYgaGVscGVyLmNsYXNzLmlzSGVscGVyRmFjdG9yeTsKICB9CgogIGZ1bmN0aW9uIGlzU2ltcGxlSGVscGVyKGhlbHBlcikgewogICAgcmV0dXJuIGhlbHBlci5kZXN0cm95ID09PSB1bmRlZmluZWQ7CiAgfQogIC8qKgogICAgRW1iZXIgSGVscGVycyBhcmUgZnVuY3Rpb25zIHRoYXQgY2FuIGNvbXB1dGUgdmFsdWVzLCBhbmQgYXJlIHVzZWQgaW4gdGVtcGxhdGVzLgogICAgRm9yIGV4YW1wbGUsIHRoaXMgY29kZSBjYWxscyBhIGhlbHBlciBuYW1lZCBgZm9ybWF0LWN1cnJlbmN5YDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxkaXY+e3tmb3JtYXQtY3VycmVuY3kgY2VudHMgY3VycmVuY3k9IiQifX08L2Rpdj4KICAgIGBgYAogIAogICAgQWRkaXRpb25hbGx5IGEgaGVscGVyIGNhbiBiZSBjYWxsZWQgYXMgYSBuZXN0ZWQgaGVscGVyIChzb21ldGltZXMgY2FsbGVkIGEKICAgIHN1YmV4cHJlc3Npb24pLiBJbiB0aGlzIGV4YW1wbGUsIHRoZSBjb21wdXRlZCB2YWx1ZSBvZiBhIGhlbHBlciBpcyBwYXNzZWQKICAgIHRvIGEgY29tcG9uZW50IG5hbWVkIGBzaG93LW1vbmV5YDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7c2hvdy1tb25leSBhbW91bnQ9KGZvcm1hdC1jdXJyZW5jeSBjZW50cyBjdXJyZW5jeT0iJCIpfX0KICAgIGBgYAogIAogICAgSGVscGVycyBkZWZpbmVkIHVzaW5nIGEgY2xhc3MgbXVzdCBwcm92aWRlIGEgYGNvbXB1dGVgIGZ1bmN0aW9uLiBGb3IgZXhhbXBsZToKICAKICAgIGBgYGFwcC9oZWxwZXJzL2Zvcm1hdC1jdXJyZW5jeS5qcwogICAgaW1wb3J0IEhlbHBlciBmcm9tICdAZW1iZXIvY29tcG9uZW50L2hlbHBlcic7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBIZWxwZXIuZXh0ZW5kKHsKICAgICAgY29tcHV0ZShbY2VudHNdLCB7IGN1cnJlbmN5IH0pIHsKICAgICAgICByZXR1cm4gYCR7Y3VycmVuY3l9JHtjZW50cyAqIDAuMDF9YDsKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIEVhY2ggdGltZSB0aGUgaW5wdXQgdG8gYSBoZWxwZXIgY2hhbmdlcywgdGhlIGBjb21wdXRlYCBmdW5jdGlvbiB3aWxsIGJlCiAgICBjYWxsZWQgYWdhaW4uCiAgCiAgICBBcyBpbnN0YW5jZXMsIHRoZXNlIGhlbHBlcnMgYWxzbyBoYXZlIGFjY2VzcyB0byB0aGUgY29udGFpbmVyIGFuZCB3aWxsIGFjY2VwdAogICAgaW5qZWN0ZWQgZGVwZW5kZW5jaWVzLgogIAogICAgQWRkaXRpb25hbGx5LCBjbGFzcyBoZWxwZXJzIGNhbiBjYWxsIGByZWNvbXB1dGVgIHRvIGZvcmNlIGEgbmV3IGNvbXB1dGF0aW9uLgogIAogICAgQGNsYXNzIEhlbHBlcgogICAgQHB1YmxpYwogICAgQHNpbmNlIDEuMTMuMAogICovCgoKICB2YXIgSGVscGVyID0gX3J1bnRpbWUuRnJhbWV3b3JrT2JqZWN0LmV4dGVuZCh7CiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgdGhpc1tSRUNPTVBVVEVfVEFHXSA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVRhZykoKTsKICAgIH0sCgogICAgLyoqCiAgICAgIE9uIGEgY2xhc3MtYmFzZWQgaGVscGVyLCBpdCBtYXkgYmUgdXNlZnVsIHRvIGZvcmNlIGEgcmVjb21wdXRhdGlvbiBvZiB0aGF0CiAgICAgIGhlbHBlcnMgdmFsdWUuIFRoaXMgaXMgYWtpbiB0byBgcmVyZW5kZXJgIG9uIGEgY29tcG9uZW50LgogICAgICAgICBGb3IgZXhhbXBsZSwgdGhpcyBjb21wb25lbnQgd2lsbCByZXJlbmRlciB3aGVuIHRoZSBgY3VycmVudFVzZXJgIG9uIGEKICAgICAgc2Vzc2lvbiBzZXJ2aWNlIGNoYW5nZXM6CiAgICAgICAgIGBgYGFwcC9oZWxwZXJzL2N1cnJlbnQtdXNlci1lbWFpbC5qcwogICAgICBpbXBvcnQgSGVscGVyIGZyb20gJ0BlbWJlci9jb21wb25lbnQvaGVscGVyJwogICAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJwogICAgICBpbXBvcnQgeyBvYnNlcnZlciB9IGZyb20gJ0BlbWJlci9vYmplY3QnCiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IEhlbHBlci5leHRlbmQoewogICAgICAgIHNlc3Npb246IHNlcnZpY2UoKSwKICAgICAgICBvbk5ld1VzZXI6IG9ic2VydmVyKCdzZXNzaW9uLmN1cnJlbnRVc2VyJywgZnVuY3Rpb24oKSB7CiAgICAgICAgICB0aGlzLnJlY29tcHV0ZSgpOwogICAgICAgIH0pLAogICAgICAgIGNvbXB1dGUoKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5nZXQoJ3Nlc3Npb24uY3VycmVudFVzZXIuZW1haWwnKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCByZWNvbXB1dGUKICAgICAgQHB1YmxpYwogICAgICBAc2luY2UgMS4xMy4wCiAgICAqLwogICAgcmVjb21wdXRlOiBmdW5jdGlvbiByZWNvbXB1dGUoKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICAoMCwgX3J1bmxvb3Auam9pbikoZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiAoMCwgX3JlZmVyZW5jZS5kaXJ0eSkoX3RoaXNbUkVDT01QVVRFX1RBR10pOwogICAgICB9KTsKICAgIH0KICB9KTsKCiAgX2V4cG9ydHMuSGVscGVyID0gSGVscGVyOwogIEhlbHBlci5pc0hlbHBlckZhY3RvcnkgPSB0cnVlOwogIHsKICAgICgwLCBfcnVudGltZS5zZXRGcmFtZXdvcmtDbGFzcykoSGVscGVyKTsKICB9CgogIHZhciBXcmFwcGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gV3JhcHBlcihjb21wdXRlKSB7CiAgICAgIHRoaXMuY29tcHV0ZSA9IGNvbXB1dGU7CiAgICAgIHRoaXMuaXNIZWxwZXJGYWN0b3J5ID0gdHJ1ZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gV3JhcHBlci5wcm90b3R5cGU7CgogICAgX3Byb3RvLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgLy8gbmVlZHMgbmV3IGluc3RhbmNlIG9yIHdpbGwgbGVhayBjb250YWluZXJzCiAgICAgIHJldHVybiB7CiAgICAgICAgY29tcHV0ZTogdGhpcy5jb21wdXRlCiAgICAgIH07CiAgICB9OwoKICAgIHJldHVybiBXcmFwcGVyOwogIH0oKTsKICAvKioKICAgIEluIG1hbnkgY2FzZXMsIHRoZSBjZXJlbW9ueSBvZiBhIGZ1bGwgYEhlbHBlcmAgY2xhc3MgaXMgbm90IHJlcXVpcmVkLgogICAgVGhlIGBoZWxwZXJgIG1ldGhvZCBjcmVhdGUgcHVyZS1mdW5jdGlvbiBoZWxwZXJzIHdpdGhvdXQgaW5zdGFuY2VzLiBGb3IKICAgIGV4YW1wbGU6CiAgCiAgICBgYGBhcHAvaGVscGVycy9mb3JtYXQtY3VycmVuY3kuanMKICAgIGltcG9ydCB7IGhlbHBlciB9IGZyb20gJ0BlbWJlci9jb21wb25lbnQvaGVscGVyJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IGhlbHBlcihmdW5jdGlvbihwYXJhbXMsIGhhc2gpIHsKICAgICAgbGV0IGNlbnRzID0gcGFyYW1zWzBdOwogICAgICBsZXQgY3VycmVuY3kgPSBoYXNoLmN1cnJlbmN5OwogICAgICByZXR1cm4gYCR7Y3VycmVuY3l9JHtjZW50cyAqIDAuMDF9YDsKICAgIH0pOwogICAgYGBgCiAgCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBoZWxwZXIgVGhlIGhlbHBlciBmdW5jdGlvbgogICAgQG1ldGhvZCBoZWxwZXIKICAgIEBmb3IgQGVtYmVyL2NvbXBvbmVudC9oZWxwZXIKICAgIEBwdWJsaWMKICAgIEBzaW5jZSAxLjEzLjAKICAqLwoKCiAgZnVuY3Rpb24gaGVscGVyKGhlbHBlckZuKSB7CiAgICByZXR1cm4gbmV3IFdyYXBwZXIoaGVscGVyRm4pOwogIH0KCiAgZnVuY3Rpb24gX3RvQm9vbChwcmVkaWNhdGUpIHsKICAgIGlmICgoMCwgX3J1bnRpbWUuaXNBcnJheSkocHJlZGljYXRlKSkgewogICAgICByZXR1cm4gcHJlZGljYXRlLmxlbmd0aCAhPT0gMDsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBCb29sZWFuKHByZWRpY2F0ZSk7CiAgICB9CiAgfQoKICB2YXIgVVBEQVRFID0gKDAsIF91dGlscy5zeW1ib2wpKCdVUERBVEUnKTsKICB2YXIgSU5WT0tFID0gKDAsIF91dGlscy5zeW1ib2wpKCdJTlZPS0UnKTsKICBfZXhwb3J0cy5JTlZPS0UgPSBJTlZPS0U7CiAgdmFyIEFDVElPTiA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnQUNUSU9OJyk7CgogIHZhciBFbWJlclBhdGhSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBFbWJlclBhdGhSZWZlcmVuY2UoKSB7fQoKICAgIHZhciBfcHJvdG8yID0gRW1iZXJQYXRoUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yLmdldCA9IGZ1bmN0aW9uIGdldChrZXkpIHsKICAgICAgcmV0dXJuIFByb3BlcnR5UmVmZXJlbmNlLmNyZWF0ZSh0aGlzLCBrZXkpOwogICAgfTsKCiAgICByZXR1cm4gRW1iZXJQYXRoUmVmZXJlbmNlOwogIH0oKTsKCiAgdmFyIENhY2hlZFJlZmVyZW5jZSQxID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9FbWJlclBhdGhSZWZlcmVuY2UpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDYWNoZWRSZWZlcmVuY2UkMSwgX0VtYmVyUGF0aFJlZmVyZW5jZSk7CgogICAgZnVuY3Rpb24gQ2FjaGVkUmVmZXJlbmNlJDEoKSB7CiAgICAgIHZhciBfdGhpczI7CgogICAgICBfdGhpczIgPSBfRW1iZXJQYXRoUmVmZXJlbmNlLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXMyLmxhc3RSZXZpc2lvbiA9IG51bGw7CiAgICAgIF90aGlzMi5sYXN0VmFsdWUgPSBudWxsOwogICAgICByZXR1cm4gX3RoaXMyOwogICAgfQoKICAgIHZhciBfcHJvdG8zID0gQ2FjaGVkUmVmZXJlbmNlJDEucHJvdG90eXBlOwoKICAgIF9wcm90bzMudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgdmFyIHRhZyA9IHRoaXMudGFnLAogICAgICAgICAgbGFzdFJldmlzaW9uID0gdGhpcy5sYXN0UmV2aXNpb24sCiAgICAgICAgICBsYXN0VmFsdWUgPSB0aGlzLmxhc3RWYWx1ZTsKCiAgICAgIGlmIChsYXN0UmV2aXNpb24gPT09IG51bGwgfHwgISgwLCBfcmVmZXJlbmNlLnZhbGlkYXRlKSh0YWcsIGxhc3RSZXZpc2lvbikpIHsKICAgICAgICBsYXN0VmFsdWUgPSB0aGlzLmxhc3RWYWx1ZSA9IHRoaXMuY29tcHV0ZSgpOwogICAgICAgIHRoaXMubGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKHRhZyk7CiAgICAgIH0KCiAgICAgIHJldHVybiBsYXN0VmFsdWU7CiAgICB9OwoKICAgIHJldHVybiBDYWNoZWRSZWZlcmVuY2UkMTsKICB9KEVtYmVyUGF0aFJlZmVyZW5jZSk7CgogIHZhciBSb290UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Db25zdFJlZmVyZW5jZSkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFJvb3RSZWZlcmVuY2UsIF9Db25zdFJlZmVyZW5jZSk7CgogICAgZnVuY3Rpb24gUm9vdFJlZmVyZW5jZSh2YWx1ZSQkMSkgewogICAgICB2YXIgX3RoaXMzOwoKICAgICAgX3RoaXMzID0gX0NvbnN0UmVmZXJlbmNlLmNhbGwodGhpcywgdmFsdWUkJDEpIHx8IHRoaXM7CiAgICAgIF90aGlzMy5jaGlsZHJlbiA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHJldHVybiBfdGhpczM7CiAgICB9CgogICAgUm9vdFJlZmVyZW5jZS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUodmFsdWUkJDEpIHsKICAgICAgcmV0dXJuIHZhbHVlVG9SZWYodmFsdWUkJDEpOwogICAgfTsKCiAgICB2YXIgX3Byb3RvNCA9IFJvb3RSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzQuZ2V0ID0gZnVuY3Rpb24gZ2V0KHByb3BlcnR5S2V5KSB7CiAgICAgIHZhciByZWYgPSB0aGlzLmNoaWxkcmVuW3Byb3BlcnR5S2V5XTsKCiAgICAgIGlmIChyZWYgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJlZiA9IHRoaXMuY2hpbGRyZW5bcHJvcGVydHlLZXldID0gbmV3IFJvb3RQcm9wZXJ0eVJlZmVyZW5jZSh0aGlzLmlubmVyLCBwcm9wZXJ0eUtleSk7CiAgICAgIH0KCiAgICAgIHJldHVybiByZWY7CiAgICB9OwoKICAgIHJldHVybiBSb290UmVmZXJlbmNlOwogIH0oX3JlZmVyZW5jZS5Db25zdFJlZmVyZW5jZSk7CgogIHZhciBUd29XYXlGbHVzaERldGVjdGlvblRhZzsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIFR3b1dheUZsdXNoRGV0ZWN0aW9uVGFnID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uICgpIHsKICAgICAgZnVuY3Rpb24gVHdvV2F5Rmx1c2hEZXRlY3Rpb25UYWcodGFnLCBrZXksIHJlZikgewogICAgICAgIHRoaXMudGFnID0gdGFnOwogICAgICAgIHRoaXMua2V5ID0ga2V5OwogICAgICAgIHRoaXMucmVmID0gcmVmOwogICAgICB9CgogICAgICBUd29XYXlGbHVzaERldGVjdGlvblRhZy5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUodGFnLCBrZXksIHJlZikgewogICAgICAgIHJldHVybiBuZXcgVHdvV2F5Rmx1c2hEZXRlY3Rpb25UYWcodGFnLCBrZXksIHJlZik7CiAgICAgIH07CgogICAgICB2YXIgX3Byb3RvNSA9IFR3b1dheUZsdXNoRGV0ZWN0aW9uVGFnLnByb3RvdHlwZTsKCiAgICAgIF9wcm90bzVbX3JlZmVyZW5jZS5DT01QVVRFXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gdGhpcy50YWdbX3JlZmVyZW5jZS5DT01QVVRFXSgpOwogICAgICB9OwoKICAgICAgX3Byb3RvNS5kaWRDb21wdXRlID0gZnVuY3Rpb24gZGlkQ29tcHV0ZShwYXJlbnQpIHsKICAgICAgICAoMCwgX21ldGFsLmRpZFJlbmRlcikocGFyZW50LCB0aGlzLmtleSwgdGhpcy5yZWYpOwogICAgICB9OwoKICAgICAgcmV0dXJuIFR3b1dheUZsdXNoRGV0ZWN0aW9uVGFnOwogICAgfSgpOwogIH0KCiAgdmFyIFByb3BlcnR5UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9DYWNoZWRSZWZlcmVuY2UkKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUHJvcGVydHlSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UkKTsKCiAgICBmdW5jdGlvbiBQcm9wZXJ0eVJlZmVyZW5jZSgpIHsKICAgICAgcmV0dXJuIF9DYWNoZWRSZWZlcmVuY2UkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICBQcm9wZXJ0eVJlZmVyZW5jZS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUocGFyZW50UmVmZXJlbmNlLCBwcm9wZXJ0eUtleSkgewogICAgICBpZiAoKDAsIF9yZWZlcmVuY2UuaXNDb25zdCkocGFyZW50UmVmZXJlbmNlKSkgewogICAgICAgIHJldHVybiB2YWx1ZUtleVRvUmVmKHBhcmVudFJlZmVyZW5jZS52YWx1ZSgpLCBwcm9wZXJ0eUtleSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyBOZXN0ZWRQcm9wZXJ0eVJlZmVyZW5jZShwYXJlbnRSZWZlcmVuY2UsIHByb3BlcnR5S2V5KTsKICAgICAgfQogICAgfTsKCiAgICB2YXIgX3Byb3RvNiA9IFByb3BlcnR5UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG82LmdldCA9IGZ1bmN0aW9uIGdldChrZXkpIHsKICAgICAgcmV0dXJuIG5ldyBOZXN0ZWRQcm9wZXJ0eVJlZmVyZW5jZSh0aGlzLCBrZXkpOwogICAgfTsKCiAgICByZXR1cm4gUHJvcGVydHlSZWZlcmVuY2U7CiAgfShDYWNoZWRSZWZlcmVuY2UkMSk7CgogIHZhciBSb290UHJvcGVydHlSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1Byb3BlcnR5UmVmZXJlbmNlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUm9vdFByb3BlcnR5UmVmZXJlbmNlLCBfUHJvcGVydHlSZWZlcmVuY2UpOwoKICAgIGZ1bmN0aW9uIFJvb3RQcm9wZXJ0eVJlZmVyZW5jZShwYXJlbnRWYWx1ZSwgcHJvcGVydHlLZXkpIHsKICAgICAgdmFyIF90aGlzNDsKCiAgICAgIF90aGlzNCA9IF9Qcm9wZXJ0eVJlZmVyZW5jZS5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzNC5wYXJlbnRWYWx1ZSA9IHBhcmVudFZhbHVlOwogICAgICBfdGhpczQucHJvcGVydHlLZXkgPSBwcm9wZXJ0eUtleTsKICAgICAgewogICAgICAgIF90aGlzNC5wcm9wZXJ0eVRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgfQoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIF90aGlzNC50YWcgPSBUd29XYXlGbHVzaERldGVjdGlvblRhZy5jcmVhdGUoX3RoaXM0LnByb3BlcnR5VGFnLCBwcm9wZXJ0eUtleSwgKDAsIF9lbWJlckJhYmVsLmFzc2VydFRoaXNJbml0aWFsaXplZCkoX3RoaXM0KSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgX3RoaXM0LnRhZyA9IF90aGlzNC5wcm9wZXJ0eVRhZzsKICAgICAgfQoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICYmICF0cnVlCiAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICApIHsKICAgICAgICAgICgwLCBfbWV0YWwud2F0Y2hLZXkpKHBhcmVudFZhbHVlLCBwcm9wZXJ0eUtleSk7CiAgICAgICAgfQoKICAgICAgcmV0dXJuIF90aGlzNDsKICAgIH0KCiAgICB2YXIgX3Byb3RvNyA9IFJvb3RQcm9wZXJ0eVJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNy5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgdmFyIHBhcmVudFZhbHVlID0gdGhpcy5wYXJlbnRWYWx1ZSwKICAgICAgICAgIHByb3BlcnR5S2V5ID0gdGhpcy5wcm9wZXJ0eUtleTsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICB0aGlzLnRhZy5kaWRDb21wdXRlKHBhcmVudFZhbHVlKTsKICAgICAgfQoKICAgICAgdmFyIHJldDsKICAgICAgewogICAgICAgIHZhciB0YWcgPSAoMCwgX21ldGFsLnRyYWNrKShmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXQgPSAoMCwgX21ldGFsLmdldCkocGFyZW50VmFsdWUsIHByb3BlcnR5S2V5KTsKICAgICAgICB9KTsKICAgICAgICAoMCwgX21ldGFsLmNvbnN1bWUpKHRhZyk7CiAgICAgICAgKDAsIF9yZWZlcmVuY2UudXBkYXRlKSh0aGlzLnByb3BlcnR5VGFnLCB0YWcpOwogICAgICB9CiAgICAgIHJldHVybiByZXQ7CiAgICB9OwoKICAgIF9wcm90bzdbVVBEQVRFXSA9IGZ1bmN0aW9uICh2YWx1ZSQkMSkgewogICAgICAoMCwgX21ldGFsLnNldCkodGhpcy5wYXJlbnRWYWx1ZSwgdGhpcy5wcm9wZXJ0eUtleSwgdmFsdWUkJDEpOwogICAgfTsKCiAgICByZXR1cm4gUm9vdFByb3BlcnR5UmVmZXJlbmNlOwogIH0oUHJvcGVydHlSZWZlcmVuY2UpOwoKICB2YXIgTmVzdGVkUHJvcGVydHlSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1Byb3BlcnR5UmVmZXJlbmNlMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE5lc3RlZFByb3BlcnR5UmVmZXJlbmNlLCBfUHJvcGVydHlSZWZlcmVuY2UyKTsKCiAgICBmdW5jdGlvbiBOZXN0ZWRQcm9wZXJ0eVJlZmVyZW5jZShwYXJlbnRSZWZlcmVuY2UsIHByb3BlcnR5S2V5KSB7CiAgICAgIHZhciBfdGhpczU7CgogICAgICBfdGhpczUgPSBfUHJvcGVydHlSZWZlcmVuY2UyLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXM1LnBhcmVudFJlZmVyZW5jZSA9IHBhcmVudFJlZmVyZW5jZTsKICAgICAgX3RoaXM1LnByb3BlcnR5S2V5ID0gcHJvcGVydHlLZXk7CiAgICAgIHZhciBwYXJlbnRSZWZlcmVuY2VUYWcgPSBwYXJlbnRSZWZlcmVuY2UudGFnOwogICAgICB2YXIgcHJvcGVydHlUYWcgPSBfdGhpczUucHJvcGVydHlUYWcgPSAoMCwgX3JlZmVyZW5jZS5jcmVhdGVVcGRhdGFibGVUYWcpKCk7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgdmFyIHRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFtwYXJlbnRSZWZlcmVuY2VUYWcsIHByb3BlcnR5VGFnXSk7CiAgICAgICAgX3RoaXM1LnRhZyA9IFR3b1dheUZsdXNoRGV0ZWN0aW9uVGFnLmNyZWF0ZSh0YWcsIHByb3BlcnR5S2V5LCAoMCwgX2VtYmVyQmFiZWwuYXNzZXJ0VGhpc0luaXRpYWxpemVkKShfdGhpczUpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBfdGhpczUudGFnID0gKDAsIF9yZWZlcmVuY2UuY29tYmluZSkoW3BhcmVudFJlZmVyZW5jZVRhZywgcHJvcGVydHlUYWddKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF90aGlzNTsKICAgIH0KCiAgICB2YXIgX3Byb3RvOCA9IE5lc3RlZFByb3BlcnR5UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG84LmNvbXB1dGUgPSBmdW5jdGlvbiBjb21wdXRlKCkgewogICAgICB2YXIgcGFyZW50UmVmZXJlbmNlID0gdGhpcy5wYXJlbnRSZWZlcmVuY2UsCiAgICAgICAgICBwcm9wZXJ0eVRhZyA9IHRoaXMucHJvcGVydHlUYWcsCiAgICAgICAgICBwcm9wZXJ0eUtleSA9IHRoaXMucHJvcGVydHlLZXk7CgogICAgICB2YXIgX3BhcmVudFZhbHVlID0gcGFyZW50UmVmZXJlbmNlLnZhbHVlKCk7CgogICAgICB2YXIgcGFyZW50VmFsdWVUeXBlID0gdHlwZW9mIF9wYXJlbnRWYWx1ZTsKCiAgICAgIGlmIChwYXJlbnRWYWx1ZVR5cGUgPT09ICdzdHJpbmcnICYmIHByb3BlcnR5S2V5ID09PSAnbGVuZ3RoJykgewogICAgICAgIHJldHVybiBfcGFyZW50VmFsdWUubGVuZ3RoOwogICAgICB9CgogICAgICBpZiAocGFyZW50VmFsdWVUeXBlID09PSAnb2JqZWN0JyAmJiBfcGFyZW50VmFsdWUgIT09IG51bGwgfHwgcGFyZW50VmFsdWVUeXBlID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgdmFyIHBhcmVudFZhbHVlID0gX3BhcmVudFZhbHVlOwoKICAgICAgICBpZiAoZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICYmICF0cnVlCiAgICAgICAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgICAgICAgKSB7CiAgICAgICAgICAgICgwLCBfbWV0YWwud2F0Y2hLZXkpKHBhcmVudFZhbHVlLCBwcm9wZXJ0eUtleSk7CiAgICAgICAgICB9CgogICAgICAgIGlmIChmYWxzZQogICAgICAgIC8qIERFQlVHICovCiAgICAgICAgKSB7CiAgICAgICAgICB0aGlzLnRhZy5kaWRDb21wdXRlKHBhcmVudFZhbHVlKTsKICAgICAgICB9CgogICAgICAgIHZhciByZXQ7CiAgICAgICAgewogICAgICAgICAgdmFyIHRhZyA9ICgwLCBfbWV0YWwudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgcmV0ID0gKDAsIF9tZXRhbC5nZXQpKHBhcmVudFZhbHVlLCBwcm9wZXJ0eUtleSk7CiAgICAgICAgICB9KTsKICAgICAgICAgICgwLCBfbWV0YWwuY29uc3VtZSkodGFnKTsKICAgICAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkocHJvcGVydHlUYWcsIHRhZyk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG84W1VQREFURV0gPSBmdW5jdGlvbiAodmFsdWUkJDEpIHsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMucGFyZW50UmVmZXJlbmNlLnZhbHVlKCkKICAgICAgLyogbGV0IHRoZSBvdGhlciBzaWRlIGhhbmRsZSB0aGUgZXJyb3IgKi8KICAgICAgLCB0aGlzLnByb3BlcnR5S2V5LCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIHJldHVybiBOZXN0ZWRQcm9wZXJ0eVJlZmVyZW5jZTsKICB9KFByb3BlcnR5UmVmZXJlbmNlKTsKCiAgdmFyIFVwZGF0YWJsZVJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW1iZXJQYXRoUmVmZXJlbmNlMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFVwZGF0YWJsZVJlZmVyZW5jZSwgX0VtYmVyUGF0aFJlZmVyZW5jZTIpOwoKICAgIGZ1bmN0aW9uIFVwZGF0YWJsZVJlZmVyZW5jZSh2YWx1ZSQkMSkgewogICAgICB2YXIgX3RoaXM2OwoKICAgICAgX3RoaXM2ID0gX0VtYmVyUGF0aFJlZmVyZW5jZTIuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczYudGFnID0gKDAsIF9yZWZlcmVuY2UuY3JlYXRlVGFnKSgpOwogICAgICBfdGhpczYuX3ZhbHVlID0gdmFsdWUkJDE7CiAgICAgIHJldHVybiBfdGhpczY7CiAgICB9CgogICAgdmFyIF9wcm90bzkgPSBVcGRhdGFibGVSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzkudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX3ZhbHVlOwogICAgfTsKCiAgICBfcHJvdG85LnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZSh2YWx1ZSQkMSkgewogICAgICB2YXIgX3ZhbHVlID0gdGhpcy5fdmFsdWU7CgogICAgICBpZiAodmFsdWUkJDEgIT09IF92YWx1ZSkgewogICAgICAgICgwLCBfcmVmZXJlbmNlLmRpcnR5KSh0aGlzLnRhZyk7CiAgICAgICAgdGhpcy5fdmFsdWUgPSB2YWx1ZSQkMTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gVXBkYXRhYmxlUmVmZXJlbmNlOwogIH0oRW1iZXJQYXRoUmVmZXJlbmNlKTsKCiAgX2V4cG9ydHMuVXBkYXRhYmxlUmVmZXJlbmNlID0gVXBkYXRhYmxlUmVmZXJlbmNlOwoKICB2YXIgQ29uZGl0aW9uYWxSZWZlcmVuY2UkMSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ29uZGl0aW9uYWxSZWZlcmVuY2UpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDb25kaXRpb25hbFJlZmVyZW5jZSQxLCBfQ29uZGl0aW9uYWxSZWZlcmVuY2UpOwoKICAgIENvbmRpdGlvbmFsUmVmZXJlbmNlJDEuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHJlZmVyZW5jZSkgewogICAgICBpZiAoKDAsIF9yZWZlcmVuY2UuaXNDb25zdCkocmVmZXJlbmNlKSkgewogICAgICAgIHZhciB2YWx1ZSQkMSA9IHJlZmVyZW5jZS52YWx1ZSgpOwoKICAgICAgICBpZiAoISgwLCBfdXRpbHMuaXNQcm94eSkodmFsdWUkJDEpKSB7CiAgICAgICAgICByZXR1cm4gX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUoX3RvQm9vbCh2YWx1ZSQkMSkpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIG5ldyBDb25kaXRpb25hbFJlZmVyZW5jZSQxKHJlZmVyZW5jZSk7CiAgICB9OwoKICAgIGZ1bmN0aW9uIENvbmRpdGlvbmFsUmVmZXJlbmNlJDEocmVmZXJlbmNlKSB7CiAgICAgIHZhciBfdGhpczc7CgogICAgICBfdGhpczcgPSBfQ29uZGl0aW9uYWxSZWZlcmVuY2UuY2FsbCh0aGlzLCByZWZlcmVuY2UpIHx8IHRoaXM7CiAgICAgIF90aGlzNy5vYmplY3RUYWcgPSAoMCwgX3JlZmVyZW5jZS5jcmVhdGVVcGRhdGFibGVUYWcpKCk7CiAgICAgIF90aGlzNy50YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShbcmVmZXJlbmNlLnRhZywgX3RoaXM3Lm9iamVjdFRhZ10pOwogICAgICByZXR1cm4gX3RoaXM3OwogICAgfQoKICAgIHZhciBfcHJvdG8xMCA9IENvbmRpdGlvbmFsUmVmZXJlbmNlJDEucHJvdG90eXBlOwoKICAgIF9wcm90bzEwLnRvQm9vbCA9IGZ1bmN0aW9uIHRvQm9vbChwcmVkaWNhdGUpIHsKICAgICAgaWYgKCgwLCBfdXRpbHMuaXNQcm94eSkocHJlZGljYXRlKSkgewogICAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkodGhpcy5vYmplY3RUYWcsICgwLCBfbWV0YWwudGFnRm9yUHJvcGVydHkpKHByZWRpY2F0ZSwgJ2lzVHJ1dGh5JykpOwogICAgICAgIHJldHVybiBCb29sZWFuKCgwLCBfbWV0YWwuZ2V0KShwcmVkaWNhdGUsICdpc1RydXRoeScpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHRoaXMub2JqZWN0VGFnLCAoMCwgX21ldGFsLnRhZ0ZvcikocHJlZGljYXRlKSk7CiAgICAgICAgcmV0dXJuIF90b0Jvb2wocHJlZGljYXRlKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gQ29uZGl0aW9uYWxSZWZlcmVuY2UkMTsKICB9KF9ydW50aW1lMi5Db25kaXRpb25hbFJlZmVyZW5jZSk7CgogIHZhciBTaW1wbGVIZWxwZXJSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NhY2hlZFJlZmVyZW5jZSQyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoU2ltcGxlSGVscGVyUmVmZXJlbmNlLCBfQ2FjaGVkUmVmZXJlbmNlJDIpOwoKICAgIGZ1bmN0aW9uIFNpbXBsZUhlbHBlclJlZmVyZW5jZShoZWxwZXIkJDEsIGFyZ3MpIHsKICAgICAgdmFyIF90aGlzODsKCiAgICAgIF90aGlzOCA9IF9DYWNoZWRSZWZlcmVuY2UkMi5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzOC5oZWxwZXIgPSBoZWxwZXIkJDE7CiAgICAgIF90aGlzOC5hcmdzID0gYXJnczsKICAgICAgdmFyIGNvbXB1dGVUYWcgPSBfdGhpczguY29tcHV0ZVRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgX3RoaXM4LnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFthcmdzLnRhZywgY29tcHV0ZVRhZ10pOwogICAgICByZXR1cm4gX3RoaXM4OwogICAgfQoKICAgIFNpbXBsZUhlbHBlclJlZmVyZW5jZS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoaGVscGVyJCQxLCBhcmdzKSB7CiAgICAgIGlmICgoMCwgX3JlZmVyZW5jZS5pc0NvbnN0KShhcmdzKSkgewogICAgICAgIHZhciBwb3NpdGlvbmFsID0gYXJncy5wb3NpdGlvbmFsLAogICAgICAgICAgICBuYW1lZCA9IGFyZ3MubmFtZWQ7CiAgICAgICAgdmFyIHBvc2l0aW9uYWxWYWx1ZSA9IHBvc2l0aW9uYWwudmFsdWUoKTsKICAgICAgICB2YXIgbmFtZWRWYWx1ZSA9IG5hbWVkLnZhbHVlKCk7CgogICAgICAgIGlmIChmYWxzZQogICAgICAgIC8qIERFQlVHICovCiAgICAgICAgKSB7CiAgICAgICAgICAoMCwgX2RlYnVnLmRlYnVnRnJlZXplKShwb3NpdGlvbmFsVmFsdWUpOwogICAgICAgICAgKDAsIF9kZWJ1Zy5kZWJ1Z0ZyZWV6ZSkobmFtZWRWYWx1ZSk7CiAgICAgICAgfQoKICAgICAgICB2YXIgcmVzdWx0ID0gaGVscGVyJCQxKHBvc2l0aW9uYWxWYWx1ZSwgbmFtZWRWYWx1ZSk7CiAgICAgICAgcmV0dXJuIHZhbHVlVG9SZWYocmVzdWx0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbmV3IFNpbXBsZUhlbHBlclJlZmVyZW5jZShoZWxwZXIkJDEsIGFyZ3MpOwogICAgICB9CiAgICB9OwoKICAgIHZhciBfcHJvdG8xMSA9IFNpbXBsZUhlbHBlclJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMTEuY29tcHV0ZSA9IGZ1bmN0aW9uIGNvbXB1dGUoKSB7CiAgICAgIHZhciBoZWxwZXIkJDEgPSB0aGlzLmhlbHBlciwKICAgICAgICAgIGNvbXB1dGVUYWcgPSB0aGlzLmNvbXB1dGVUYWcsCiAgICAgICAgICBfdGhpcyRhcmdzID0gdGhpcy5hcmdzLAogICAgICAgICAgcG9zaXRpb25hbCA9IF90aGlzJGFyZ3MucG9zaXRpb25hbCwKICAgICAgICAgIG5hbWVkID0gX3RoaXMkYXJncy5uYW1lZDsKICAgICAgdmFyIHBvc2l0aW9uYWxWYWx1ZSA9IHBvc2l0aW9uYWwudmFsdWUoKTsKICAgICAgdmFyIG5hbWVkVmFsdWUgPSBuYW1lZC52YWx1ZSgpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgICgwLCBfZGVidWcuZGVidWdGcmVlemUpKHBvc2l0aW9uYWxWYWx1ZSk7CiAgICAgICAgKDAsIF9kZWJ1Zy5kZWJ1Z0ZyZWV6ZSkobmFtZWRWYWx1ZSk7CiAgICAgIH0KCiAgICAgIHZhciBjb21wdXRlZFZhbHVlOwogICAgICB2YXIgY29tYmluZWRUcmFja2luZ1RhZyA9ICgwLCBfbWV0YWwudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gY29tcHV0ZWRWYWx1ZSA9IGhlbHBlciQkMShwb3NpdGlvbmFsVmFsdWUsIG5hbWVkVmFsdWUpOwogICAgICB9KTsKICAgICAgKDAsIF9yZWZlcmVuY2UudXBkYXRlKShjb21wdXRlVGFnLCBjb21iaW5lZFRyYWNraW5nVGFnKTsKICAgICAgcmV0dXJuIGNvbXB1dGVkVmFsdWU7CiAgICB9OwoKICAgIHJldHVybiBTaW1wbGVIZWxwZXJSZWZlcmVuY2U7CiAgfShDYWNoZWRSZWZlcmVuY2UkMSk7CgogIHZhciBDbGFzc0Jhc2VkSGVscGVyUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9DYWNoZWRSZWZlcmVuY2UkMykgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKENsYXNzQmFzZWRIZWxwZXJSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UkMyk7CgogICAgZnVuY3Rpb24gQ2xhc3NCYXNlZEhlbHBlclJlZmVyZW5jZShpbnN0YW5jZSwgYXJncykgewogICAgICB2YXIgX3RoaXM5OwoKICAgICAgX3RoaXM5ID0gX0NhY2hlZFJlZmVyZW5jZSQzLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXM5Lmluc3RhbmNlID0gaW5zdGFuY2U7CiAgICAgIF90aGlzOS5hcmdzID0gYXJnczsKICAgICAgdmFyIGNvbXB1dGVUYWcgPSBfdGhpczkuY29tcHV0ZVRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgX3RoaXM5LnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFtpbnN0YW5jZVtSRUNPTVBVVEVfVEFHXSwgYXJncy50YWcsIGNvbXB1dGVUYWddKTsKICAgICAgcmV0dXJuIF90aGlzOTsKICAgIH0KCiAgICBDbGFzc0Jhc2VkSGVscGVyUmVmZXJlbmNlLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShpbnN0YW5jZSwgYXJncykgewogICAgICByZXR1cm4gbmV3IENsYXNzQmFzZWRIZWxwZXJSZWZlcmVuY2UoaW5zdGFuY2UsIGFyZ3MpOwogICAgfTsKCiAgICB2YXIgX3Byb3RvMTIgPSBDbGFzc0Jhc2VkSGVscGVyUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xMi5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgdmFyIGluc3RhbmNlID0gdGhpcy5pbnN0YW5jZSwKICAgICAgICAgIGNvbXB1dGVUYWcgPSB0aGlzLmNvbXB1dGVUYWcsCiAgICAgICAgICBfdGhpcyRhcmdzMiA9IHRoaXMuYXJncywKICAgICAgICAgIHBvc2l0aW9uYWwgPSBfdGhpcyRhcmdzMi5wb3NpdGlvbmFsLAogICAgICAgICAgbmFtZWQgPSBfdGhpcyRhcmdzMi5uYW1lZDsKICAgICAgdmFyIHBvc2l0aW9uYWxWYWx1ZSA9IHBvc2l0aW9uYWwudmFsdWUoKTsKICAgICAgdmFyIG5hbWVkVmFsdWUgPSBuYW1lZC52YWx1ZSgpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgICgwLCBfZGVidWcuZGVidWdGcmVlemUpKHBvc2l0aW9uYWxWYWx1ZSk7CiAgICAgICAgKDAsIF9kZWJ1Zy5kZWJ1Z0ZyZWV6ZSkobmFtZWRWYWx1ZSk7CiAgICAgIH0KCiAgICAgIHZhciBjb21wdXRlZFZhbHVlOwogICAgICB2YXIgY29tYmluZWRUcmFja2luZ1RhZyA9ICgwLCBfbWV0YWwudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gY29tcHV0ZWRWYWx1ZSA9IGluc3RhbmNlLmNvbXB1dGUocG9zaXRpb25hbFZhbHVlLCBuYW1lZFZhbHVlKTsKICAgICAgfSk7CiAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkoY29tcHV0ZVRhZywgY29tYmluZWRUcmFja2luZ1RhZyk7CiAgICAgIHJldHVybiBjb21wdXRlZFZhbHVlOwogICAgfTsKCiAgICByZXR1cm4gQ2xhc3NCYXNlZEhlbHBlclJlZmVyZW5jZTsKICB9KENhY2hlZFJlZmVyZW5jZSQxKTsKCiAgdmFyIEludGVybmFsSGVscGVyUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9DYWNoZWRSZWZlcmVuY2UkNCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEludGVybmFsSGVscGVyUmVmZXJlbmNlLCBfQ2FjaGVkUmVmZXJlbmNlJDQpOwoKICAgIGZ1bmN0aW9uIEludGVybmFsSGVscGVyUmVmZXJlbmNlKGhlbHBlciQkMSwgYXJncykgewogICAgICB2YXIgX3RoaXMxMDsKCiAgICAgIF90aGlzMTAgPSBfQ2FjaGVkUmVmZXJlbmNlJDQuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczEwLmhlbHBlciA9IGhlbHBlciQkMTsKICAgICAgX3RoaXMxMC5hcmdzID0gYXJnczsKICAgICAgX3RoaXMxMC50YWcgPSBhcmdzLnRhZzsKICAgICAgcmV0dXJuIF90aGlzMTA7CiAgICB9CgogICAgdmFyIF9wcm90bzEzID0gSW50ZXJuYWxIZWxwZXJSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzEzLmNvbXB1dGUgPSBmdW5jdGlvbiBjb21wdXRlKCkgewogICAgICB2YXIgaGVscGVyJCQxID0gdGhpcy5oZWxwZXIsCiAgICAgICAgICBhcmdzID0gdGhpcy5hcmdzOwogICAgICByZXR1cm4gaGVscGVyJCQxKGFyZ3MpOwogICAgfTsKCiAgICByZXR1cm4gSW50ZXJuYWxIZWxwZXJSZWZlcmVuY2U7CiAgfShDYWNoZWRSZWZlcmVuY2UkMSk7CgogIHZhciBVbmJvdW5kUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Db25zdFJlZmVyZW5jZTIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShVbmJvdW5kUmVmZXJlbmNlLCBfQ29uc3RSZWZlcmVuY2UyKTsKCiAgICBmdW5jdGlvbiBVbmJvdW5kUmVmZXJlbmNlKCkgewogICAgICByZXR1cm4gX0NvbnN0UmVmZXJlbmNlMi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgVW5ib3VuZFJlZmVyZW5jZS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUodmFsdWUkJDEpIHsKICAgICAgcmV0dXJuIHZhbHVlVG9SZWYodmFsdWUkJDEsIGZhbHNlKTsKICAgIH07CgogICAgdmFyIF9wcm90bzE0ID0gVW5ib3VuZFJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMTQuZ2V0ID0gZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICByZXR1cm4gdmFsdWVUb1JlZih0aGlzLmlubmVyW2tleV0sIGZhbHNlKTsKICAgIH07CgogICAgcmV0dXJuIFVuYm91bmRSZWZlcmVuY2U7CiAgfShfcmVmZXJlbmNlLkNvbnN0UmVmZXJlbmNlKTsKCiAgdmFyIFJlYWRvbmx5UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9DYWNoZWRSZWZlcmVuY2UkNSkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFJlYWRvbmx5UmVmZXJlbmNlLCBfQ2FjaGVkUmVmZXJlbmNlJDUpOwoKICAgIGZ1bmN0aW9uIFJlYWRvbmx5UmVmZXJlbmNlKGlubmVyKSB7CiAgICAgIHZhciBfdGhpczExOwoKICAgICAgX3RoaXMxMSA9IF9DYWNoZWRSZWZlcmVuY2UkNS5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMTEuaW5uZXIgPSBpbm5lcjsKICAgICAgX3RoaXMxMS50YWcgPSBpbm5lci50YWc7CiAgICAgIHJldHVybiBfdGhpczExOwogICAgfQoKICAgIHZhciBfcHJvdG8xNSA9IFJlYWRvbmx5UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xNS5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuaW5uZXIudmFsdWUoKTsKICAgIH07CgogICAgX3Byb3RvMTUuZ2V0ID0gZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICByZXR1cm4gdGhpcy5pbm5lci5nZXQoa2V5KTsKICAgIH07CgogICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShSZWFkb25seVJlZmVyZW5jZSwgW3sKICAgICAga2V5OiBJTlZPS0UsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmlubmVyW0lOVk9LRV07CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBSZWFkb25seVJlZmVyZW5jZTsKICB9KENhY2hlZFJlZmVyZW5jZSQxKTsKCiAgZnVuY3Rpb24gcmVmZXJlbmNlRnJvbVBhcnRzKHJvb3QsIHBhcnRzKSB7CiAgICB2YXIgcmVmZXJlbmNlID0gcm9vdDsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHJlZmVyZW5jZSA9IHJlZmVyZW5jZS5nZXQocGFydHNbaV0pOwogICAgfQoKICAgIHJldHVybiByZWZlcmVuY2U7CiAgfQoKICBmdW5jdGlvbiBpc09iamVjdCh2YWx1ZSQkMSkgewogICAgcmV0dXJuIHZhbHVlJCQxICE9PSBudWxsICYmIHR5cGVvZiB2YWx1ZSQkMSA9PT0gJ29iamVjdCc7CiAgfQoKICBmdW5jdGlvbiBpc0Z1bmN0aW9uKHZhbHVlJCQxKSB7CiAgICByZXR1cm4gdHlwZW9mIHZhbHVlJCQxID09PSAnZnVuY3Rpb24nOwogIH0KCiAgZnVuY3Rpb24gaXNQcmltaXRpdmUodmFsdWUkJDEpIHsKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZSQkMTsKICAgICAgcmV0dXJuIHZhbHVlJCQxID09PSB1bmRlZmluZWQgfHwgdmFsdWUkJDEgPT09IG51bGwgfHwgdHlwZSA9PT0gJ2Jvb2xlYW4nIHx8IHR5cGUgPT09ICdudW1iZXInIHx8IHR5cGUgPT09ICdzdHJpbmcnOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgfQoKICBmdW5jdGlvbiB2YWx1ZVRvUmVmKHZhbHVlJCQxLCBib3VuZCkgewogICAgaWYgKGJvdW5kID09PSB2b2lkIDApIHsKICAgICAgYm91bmQgPSB0cnVlOwogICAgfQoKICAgIGlmIChpc09iamVjdCh2YWx1ZSQkMSkpIHsKICAgICAgLy8gcm9vdCBvZiBpbnRlcm9wIHdpdGggZW1iZXIgb2JqZWN0cwogICAgICByZXR1cm4gYm91bmQgPyBuZXcgUm9vdFJlZmVyZW5jZSh2YWx1ZSQkMSkgOiBuZXcgVW5ib3VuZFJlZmVyZW5jZSh2YWx1ZSQkMSk7CiAgICB9IGVsc2UgaWYgKGlzRnVuY3Rpb24odmFsdWUkJDEpKSB7CiAgICAgIC8vIGVtYmVyIGRvZXNuJ3QgZG8gb2JzZXJ2aW5nIHdpdGggZnVuY3Rpb25zCiAgICAgIHJldHVybiBuZXcgVW5ib3VuZFJlZmVyZW5jZSh2YWx1ZSQkMSk7CiAgICB9IGVsc2UgaWYgKGlzUHJpbWl0aXZlKHZhbHVlJCQxKSkgewogICAgICByZXR1cm4gX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUodmFsdWUkJDEpOwogICAgfSBlbHNlIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZSQkMTsKICAgICAgdmFyIG91dHB1dDsKCiAgICAgIHRyeSB7CiAgICAgICAgb3V0cHV0ID0gU3RyaW5nKHZhbHVlJCQxKTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIG91dHB1dCA9IG51bGw7CiAgICAgIH0KCiAgICAgIGlmIChvdXRwdXQpIHsKICAgICAgICB0aHJvdyAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJbQlVHXSBVbmV4cGVjdGVkICIgKyB0eXBlICsgIiAoIiArIG91dHB1dCArICIpIik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiW0JVR10gVW5leHBlY3RlZCAiICsgdHlwZSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHZhbHVlS2V5VG9SZWYodmFsdWUkJDEsIGtleSkgewogICAgaWYgKGlzT2JqZWN0KHZhbHVlJCQxKSkgewogICAgICAvLyByb290IG9mIGludGVyb3Agd2l0aCBlbWJlciBvYmplY3RzCiAgICAgIHJldHVybiBuZXcgUm9vdFByb3BlcnR5UmVmZXJlbmNlKHZhbHVlJCQxLCBrZXkpOwogICAgfSBlbHNlIGlmIChpc0Z1bmN0aW9uKHZhbHVlJCQxKSkgewogICAgICAvLyBlbWJlciBkb2Vzbid0IGRvIG9ic2VydmluZyB3aXRoIGZ1bmN0aW9ucwogICAgICByZXR1cm4gbmV3IFVuYm91bmRSZWZlcmVuY2UodmFsdWUkJDFba2V5XSk7CiAgICB9IGVsc2UgaWYgKGlzUHJpbWl0aXZlKHZhbHVlJCQxKSkgewogICAgICByZXR1cm4gX3J1bnRpbWUyLlVOREVGSU5FRF9SRUZFUkVOQ0U7CiAgICB9IGVsc2UgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgKSB7CiAgICAgIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlJCQxOwogICAgICB2YXIgb3V0cHV0OwoKICAgICAgdHJ5IHsKICAgICAgICBvdXRwdXQgPSBTdHJpbmcodmFsdWUkJDEpOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgb3V0cHV0ID0gbnVsbDsKICAgICAgfQoKICAgICAgaWYgKG91dHB1dCkgewogICAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIltCVUddIFVuZXhwZWN0ZWQgIiArIHR5cGUgKyAiICgiICsgb3V0cHV0ICsgIikiKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aHJvdyAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJbQlVHXSBVbmV4cGVjdGVkICIgKyB0eXBlKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdGhyb3cgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgpOwogICAgfQogIH0KCiAgdmFyIERJUlRZX1RBRyA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnRElSVFlfVEFHJyk7CiAgdmFyIEFSR1MgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ0FSR1MnKTsKICB2YXIgUk9PVF9SRUYgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ1JPT1RfUkVGJyk7CiAgX2V4cG9ydHMuUk9PVF9SRUYgPSBST09UX1JFRjsKICB2YXIgSVNfRElTUEFUQ0hJTkdfQVRUUlMgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ0lTX0RJU1BBVENISU5HX0FUVFJTJyk7CiAgdmFyIEhBU19CTE9DSyA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnSEFTX0JMT0NLJyk7CiAgdmFyIEJPVU5EUyA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnQk9VTkRTJyk7CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvY29tcG9uZW50CiAgKi8KCiAgLyoqCiAgICBBIGNvbXBvbmVudCBpcyBhbiBpc29sYXRlZCBwaWVjZSBvZiBVSSwgcmVwcmVzZW50ZWQgYnkgYSB0ZW1wbGF0ZSBhbmQgYW4KICAgIG9wdGlvbmFsIGNsYXNzLiBXaGVuIGEgY29tcG9uZW50IGhhcyBhIGNsYXNzLCBpdHMgdGVtcGxhdGUncyBgdGhpc2AgdmFsdWUKICAgIGlzIGFuIGluc3RhbmNlIG9mIHRoZSBjb21wb25lbnQgY2xhc3MuCiAgCiAgICAjIyBUZW1wbGF0ZS1vbmx5IENvbXBvbmVudHMKICAKICAgIFRoZSBzaW1wbGVzdCB3YXkgdG8gY3JlYXRlIGEgY29tcG9uZW50IGlzIHRvIGNyZWF0ZSBhIHRlbXBsYXRlIGZpbGUgaW4KICAgIGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHNgLiBGb3IgZXhhbXBsZSwgaWYgeW91IG5hbWUgYSB0ZW1wbGF0ZQogICAgYGFwcC90ZW1wbGF0ZXMvY29tcG9uZW50cy9wZXJzb24tcHJvZmlsZS5oYnNgOgogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmhicwogICAgPGgxPnt7QHBlcnNvbi5uYW1lfX08L2gxPgogICAgPGltZyBzcmM9e3tAcGVyc29uLmF2YXRhcn19PgogICAgPHAgY2xhc3M9J3NpZ25hdHVyZSc+e3tAcGVyc29uLnNpZ25hdHVyZX19PC9wPgogICAgYGBgCiAgCiAgICBZb3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBgPFBlcnNvblByb2ZpbGUgLz5gIHRvIGludm9rZSB0aGlzIGNvbXBvbmVudCBlbHNld2hlcmUKICAgIGluIHlvdXIgYXBwbGljYXRpb246CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2FwcGxpY2F0aW9uLmhicwogICAgPFBlcnNvblByb2ZpbGUgQHBlcnNvbj17e3RoaXMuY3VycmVudFVzZXJ9fSAvPgogICAgYGBgCiAgCiAgICBOb3RlIHRoYXQgY29tcG9uZW50IG5hbWVzIGFyZSBjYXBpdGFsaXplZCBoZXJlIGluIG9yZGVyIHRvIGRpc3Rpbmd1aXNoIHRoZW0KICAgIGZyb20gcmVndWxhciBIVE1MIGVsZW1lbnRzLCBidXQgdGhleSBhcmUgZGFzaGVyaXplZCBpbiB0aGUgZmlsZSBzeXN0ZW0uCiAgCiAgICBXaGlsZSB0aGUgYW5nbGUgYnJhY2tldCBpbnZvY2F0aW9uIGZvcm0gaXMgZ2VuZXJhbGx5IHByZWZlcnJlZCwgaXQgaXMgYWxzbwogICAgcG9zc2libGUgdG8gaW52b2tlIHRoZSBzYW1lIGNvbXBvbmVudCB3aXRoIHRoZSBge3twZXJzb24tcHJvZmlsZX19YCBzeW50YXg6CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2FwcGxpY2F0aW9uLmhicwogICAge3twZXJzb24tcHJvZmlsZSBwZXJzb249dGhpcy5jdXJyZW50VXNlcn19CiAgICBgYGAKICAKICAgIE5vdGUgdGhhdCB3aXRoIHRoaXMgc3ludGF4LCB5b3UgdXNlIGRhc2hlcyBpbiB0aGUgY29tcG9uZW50IG5hbWUgYW5kCiAgICBhcmd1bWVudHMgYXJlIHBhc3NlZCB3aXRob3V0IHRoZSBgQGAgc2lnbi4KICAKICAgIEluIGJvdGggY2FzZXMsIEVtYmVyIHdpbGwgcmVuZGVyIHRoZSBjb250ZW50IG9mIHRoZSBjb21wb25lbnQgdGVtcGxhdGUgd2UKICAgIGNyZWF0ZWQgYWJvdmUuIFRoZSBlbmQgcmVzdWx0IHdpbGwgYmUgc29tZXRoaW5nIGxpa2UgdGhpczoKICAKICAgIGBgYGh0bWwKICAgIDxoMT5Ub21zdGVyPC9oMT4KICAgIDxpbWcgc3JjPSJodHRwczovL2VtYmVyanMuY29tL3RvbXN0ZXIuanBnIj4KICAgIDxwIGNsYXNzPSdzaWduYXR1cmUnPk91dCBvZiBvZmZpY2UgdGhpcyB3ZWVrPC9wPgogICAgYGBgCiAgCiAgICAjIyBGaWxlIFN5c3RlbSBOZXN0aW5nCiAgCiAgICBDb21wb25lbnRzIGNhbiBiZSBuZXN0ZWQgaW5zaWRlIHN1Yi1mb2xkZXJzIGZvciBsb2dpY2FsIGdyb3VwcGluZy4gRm9yCiAgICBleGFtcGxlLCBpZiB3ZSBwbGFjZWQgb3VyIHRlbXBsYXRlIGluCiAgICBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL3BlcnNvbi9zaG9ydC1wcm9maWxlLmhic2AsIHdlIGNhbiBpbnZva2UgaXQgYXMKICAgIGA8UGVyc29uOjpTaG9ydFByb2ZpbGUgLz5gOgogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9hcHBsaWNhdGlvbi5oYnMKICAgIDxQZXJzb246OlNob3J0UHJvZmlsZSBAcGVyc29uPXt7dGhpcy5jdXJyZW50VXNlcn19IC8+CiAgICBgYGAKICAKICAgIE9yIGVxdWl2YWxlbnRseSwgYHt7cGVyc29uL3Nob3J0LXByb2ZpbGV9fWA6CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2FwcGxpY2F0aW9uLmhicwogICAge3twZXJzb24vc2hvcnQtcHJvZmlsZSBwZXJzb249dGhpcy5jdXJyZW50VXNlcn19CiAgICBgYGAKICAKICAgICMjIFlpZWxkaW5nIENvbnRlbnRzCiAgCiAgICBZb3UgY2FuIHVzZSBgeWllbGRgIGluc2lkZSBhIHRlbXBsYXRlIHRvIGluY2x1ZGUgdGhlICoqY29udGVudHMqKiBvZiBhbnkgYmxvY2sKICAgIGF0dGFjaGVkIHRvIHRoZSBjb21wb25lbnQuIFRoZSBibG9jayB3aWxsIGJlIGV4ZWN1dGVkIGluIGl0cyBvcmlnaW5hbCBjb250ZXh0OgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPFBlcnNvblByb2ZpbGUgQHBlcnNvbj17e3RoaXMuY3VycmVudFVzZXJ9fT4KICAgICAgPHA+QWRtaW4gbW9kZTwvcD4KICAgICAge3shIEV4ZWN1dGVkIGluIHRoZSBjdXJyZW50IGNvbnRleHQuIH19CiAgICA8L1BlcnNvblByb2ZpbGU+CiAgICBgYGAKICAKICAgIG9yCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7eyNwZXJzb24tcHJvZmlsZSBwZXJzb249dGhpcy5jdXJyZW50VXNlcn19CiAgICAgIDxwPkFkbWluIG1vZGU8L3A+CiAgICAgIHt7ISBFeGVjdXRlZCBpbiB0aGUgY3VycmVudCBjb250ZXh0LiB9fQogICAge3svcGVyc29uLXByb2ZpbGV9fQogICAgYGBgCiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvcGVyc29uLXByb2ZpbGUuaGJzCiAgICA8aDE+e3tAcGVyc29uLm5hbWV9fTwvaDE+CiAgICB7e3lpZWxkfX0KICAgIGBgYAogIAogICAgIyMgQ3VzdG9taXppbmcgQ29tcG9uZW50cyBXaXRoIEphdmFTY3JpcHQKICAKICAgIElmIHlvdSB3YW50IHRvIGN1c3RvbWl6ZSB0aGUgY29tcG9uZW50IGluIG9yZGVyIHRvIGhhbmRsZSBldmVudHMsIHRyYW5zZm9ybQogICAgYXJndW1lbnRzIG9yIG1haW50YWluIGludGVybmFsIHN0YXRlLCB5b3UgaW1wbGVtZW50IGEgc3ViY2xhc3Mgb2YgYENvbXBvbmVudGAuCiAgCiAgICBPbmUgZXhhbXBsZSBpcyB0byBhZGQgY29tcHV0ZWQgcHJvcGVydGllcyB0byB5b3VyIGNvbXBvbmVudDoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGRpc3BsYXlOYW1lOiBjb21wdXRlZCgncGVyc29uLnRpdGxlJywgJ3BlcnNvbi5maXJzdE5hbWUnLCAncGVyc29uLmxhc3ROYW1lJywgZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IHsgdGl0bGUsIGZpcnN0TmFtZSwgbGFzdE5hbWUgfSA9IHRoaXM7CiAgCiAgICAgICAgaWYgKHRpdGxlKSB7CiAgICAgICAgICByZXR1cm4gYCR7dGl0bGV9ICR7bGFzdE5hbWV9YDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIGAke2ZpcnN0TmFtZX0gJHtsYXN0TmFtZX1gOwogICAgICAgIH0KICAgICAgfSkKICAgIH0pOwogICAgYGBgCiAgCiAgICBBbmQgdGhlbiB1c2UgaXQgaW4gdGhlIGNvbXBvbmVudCdzIHRlbXBsYXRlOgogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmhicwogICAgPGgxPnt7dGhpcy5kaXNwbGF5TmFtZX19PC9oMT4KICAgIHt7eWllbGR9fQogICAgYGBgCiAgCiAgICAjIyBDdXN0b21pemluZyBhIENvbXBvbmVudCdzIEhUTUwgRWxlbWVudCBpbiBKYXZhU2NyaXB0CiAgCiAgICAjIyMgSFRNTCBUYWcKICAKICAgIFRoZSBkZWZhdWx0IEhUTUwgdGFnIG5hbWUgdXNlZCBmb3IgYSBjb21wb25lbnQncyBIVE1MIHJlcHJlc2VudGF0aW9uIGlzIGBkaXZgLgogICAgVGhpcyBjYW4gYmUgY3VzdG9taXplZCBieSBzZXR0aW5nIHRoZSBgdGFnTmFtZWAgcHJvcGVydHkuCiAgCiAgICBDb25zaWRlciB0aGUgZm9sbG93aW5nIGNvbXBvbmVudCBjbGFzczoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL2VtcGhhc2l6ZWQtcGFyYWdyYXBoLmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIHRhZ05hbWU6ICdlbScKICAgIH0pOwogICAgYGBgCiAgCiAgICBXaGVuIGludm9rZWQsIHRoaXMgY29tcG9uZW50IHdvdWxkIHByb2R1Y2Ugb3V0cHV0IHRoYXQgbG9va3Mgc29tZXRoaW5nIGxpa2UKICAgIHRoaXM6CiAgCiAgICBgYGBodG1sCiAgICA8ZW0gaWQ9ImVtYmVyMSIgY2xhc3M9ImVtYmVyLXZpZXciPjwvZW0+CiAgICBgYGAKICAKICAgICMjIyBIVE1MIGBjbGFzc2AgQXR0cmlidXRlCiAgCiAgICBUaGUgSFRNTCBgY2xhc3NgIGF0dHJpYnV0ZSBvZiBhIGNvbXBvbmVudCdzIHRhZyBjYW4gYmUgc2V0IGJ5IHByb3ZpZGluZyBhCiAgICBgY2xhc3NOYW1lc2AgcHJvcGVydHkgdGhhdCBpcyBzZXQgdG8gYW4gYXJyYXkgb2Ygc3RyaW5nczoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGFzc05hbWVzOiBbJ215LWNsYXNzJywgJ215LW90aGVyLWNsYXNzJ10KICAgIH0pOwogICAgYGBgCiAgCiAgICBJbnZva2luZyB0aGlzIGNvbXBvbmVudCB3aWxsIHByb2R1Y2Ugb3V0cHV0IHRoYXQgbG9va3MgbGlrZSB0aGlzOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyBteS1jbGFzcyBteS1vdGhlci1jbGFzcyI+PC9kaXY+CiAgICBgYGAKICAKICAgIGBjbGFzc2AgYXR0cmlidXRlIHZhbHVlcyBjYW4gYWxzbyBiZSBzZXQgYnkgcHJvdmlkaW5nIGEgYGNsYXNzTmFtZUJpbmRpbmdzYAogICAgcHJvcGVydHkgc2V0IHRvIGFuIGFycmF5IG9mIHByb3BlcnRpZXMgbmFtZXMgZm9yIHRoZSBjb21wb25lbnQuIFRoZSByZXR1cm4KICAgIHZhbHVlIG9mIHRoZXNlIHByb3BlcnRpZXMgd2lsbCBiZSBhZGRlZCBhcyBwYXJ0IG9mIHRoZSB2YWx1ZSBmb3IgdGhlCiAgICBjb21wb25lbnRzJ3MgYGNsYXNzYCBhdHRyaWJ1dGUuIFRoZXNlIHByb3BlcnRpZXMgY2FuIGJlIGNvbXB1dGVkIHByb3BlcnRpZXM6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS13aWRnZXQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGNsYXNzTmFtZXM6IFsnbXktY2xhc3MnLCAnbXktb3RoZXItY2xhc3MnXSwKICAgICAgY2xhc3NOYW1lQmluZGluZ3M6IFsncHJvcGVydHlBJywgJ3Byb3BlcnR5QiddLAogIAogICAgICBwcm9wZXJ0eUE6ICdmcm9tLWEnLAogICAgICBwcm9wZXJ0eUI6IGNvbXB1dGVkKGZ1bmN0aW9uKCkgewogICAgICAgIGlmIChzb21lTG9naWMpIHsgcmV0dXJuICdmcm9tLWInOyB9CiAgICAgIH0pCiAgICB9KTsKICAgIGBgYAogIAogICAgSW52b2tpbmcgdGhpcyBjb21wb25lbnQgd2lsbCBwcm9kdWNlIEhUTUwgdGhhdCBsb29rcyBsaWtlOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyBteS1jbGFzcyBteS1vdGhlci1jbGFzcyBmcm9tLWEgZnJvbS1iIj48L2Rpdj4KICAgIGBgYAogIAogICAgTm90ZSB0aGF0IGBjbGFzc05hbWVzYCBhbmQgYGNsYXNzTmFtZUJpbmRpbmdzYCBpcyBpbiBhZGRpdGlvbiB0byB0aGUgYGNsYXNzYAogICAgYXR0cmlidXRlIHBhc3NlZCB3aXRoIHRoZSBhbmdsZSBicmFja2V0IGludm9jYXRpb24gc3ludGF4LiBUaGVyZWZvcmUsIGlmIHRoaXMKICAgIGNvbXBvbmVudCB3YXMgaW52b2tlZCBsaWtlIHNvOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPE15V2lkZ2V0IGNsYXNzPSJmcm9tLWludm9jYXRpb24iIC8+CiAgICBgYGAKICAKICAgIFRoZSByZXN1bHRpbmcgSFRNTCB3aWxsIGxvb2sgc2ltaWxhciB0byB0aGlzOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZnJvbS1pbnZvY2F0aW9uIGVtYmVyLXZpZXcgbXktY2xhc3MgbXktb3RoZXItY2xhc3MgZnJvbS1hIGZyb20tYiI+PC9kaXY+CiAgICBgYGAKICAKICAgIElmIHRoZSB2YWx1ZSBvZiBhIGNsYXNzIG5hbWUgYmluZGluZyByZXR1cm5zIGEgYm9vbGVhbiB0aGUgcHJvcGVydHkgbmFtZQogICAgaXRzZWxmIHdpbGwgYmUgdXNlZCBhcyB0aGUgY2xhc3MgbmFtZSBpZiB0aGUgcHJvcGVydHkgaXMgdHJ1ZS4gVGhlIGNsYXNzIG5hbWUKICAgIHdpbGwgbm90IGJlIGFkZGVkIGlmIHRoZSB2YWx1ZSBpcyBgZmFsc2VgIG9yIGB1bmRlZmluZWRgLgogIAogICAgYGBgYXBwL2NvbXBvbmVudHMvbXktd2lkZ2V0LmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGNsYXNzTmFtZUJpbmRpbmdzOiBbJ2hvdmVyZWQnXSwKICAKICAgICAgaG92ZXJlZDogdHJ1ZQogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDxkaXYgaWQ9ImVtYmVyMSIgY2xhc3M9ImVtYmVyLXZpZXcgaG92ZXJlZCI+PC9kaXY+CiAgICBgYGAKICAKICAgICMjIyBDdXN0b20gQ2xhc3MgTmFtZXMgZm9yIEJvb2xlYW4gVmFsdWVzCiAgCiAgICBXaGVuIHVzaW5nIGJvb2xlYW4gY2xhc3MgbmFtZSBiaW5kaW5ncyB5b3UgY2FuIHN1cHBseSBhIHN0cmluZyB2YWx1ZSBvdGhlcgogICAgdGhhbiB0aGUgcHJvcGVydHkgbmFtZSBmb3IgdXNlIGFzIHRoZSBgY2xhc3NgIEhUTUwgYXR0cmlidXRlIGJ5IGFwcGVuZGluZyB0aGUKICAgIHByZWZlcnJlZCB2YWx1ZSBhZnRlciBhICI6IiBjaGFyYWN0ZXIgd2hlbiBkZWZpbmluZyB0aGUgYmluZGluZzoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGFzc05hbWVCaW5kaW5nczogWydhd2Vzb21lOnNvLXZlcnktY29vbCddLAogIAogICAgICBhd2Vzb21lOiB0cnVlCiAgICB9KTsKICAgIGBgYAogIAogICAgSW52b2tpbmcgdGhpcyBjb21wb25lbnQgd2lsbCBwcm9kdWNlIEhUTUwgdGhhdCBsb29rcyBsaWtlOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyBzby12ZXJ5LWNvb2wiPjwvZGl2PgogICAgYGBgCiAgCiAgICBCb29sZWFuIHZhbHVlIGNsYXNzIG5hbWUgYmluZGluZ3Mgd2hvc2UgcHJvcGVydHkgbmFtZXMgYXJlIGluIGEKICAgIGNhbWVsQ2FzZS1zdHlsZSBmb3JtYXQgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gYSBkYXNoZXJpemVkIGZvcm1hdDoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGFzc05hbWVCaW5kaW5nczogWydpc1VyZ2VudCddLAogIAogICAgICBpc1VyZ2VudDogdHJ1ZQogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDxkaXYgaWQ9ImVtYmVyMSIgY2xhc3M9ImVtYmVyLXZpZXcgaXMtdXJnZW50Ij48L2Rpdj4KICAgIGBgYAogIAogICAgQ2xhc3MgbmFtZSBiaW5kaW5ncyBjYW4gYWxzbyByZWZlciB0byBvYmplY3QgdmFsdWVzIHRoYXQgYXJlIGZvdW5kIGJ5CiAgICB0cmF2ZXJzaW5nIGEgcGF0aCByZWxhdGl2ZSB0byB0aGUgY29tcG9uZW50IGl0c2VsZjoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGFzc05hbWVCaW5kaW5nczogWydtZXNzYWdlcy5lbXB0eSddLAogIAogICAgICBtZXNzYWdlczogRW1iZXJPYmplY3QuY3JlYXRlKHsKICAgICAgICBlbXB0eTogdHJ1ZQogICAgICB9KQogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDxkaXYgaWQ9ImVtYmVyMSIgY2xhc3M9ImVtYmVyLXZpZXcgZW1wdHkiPjwvZGl2PgogICAgYGBgCiAgCiAgICBJZiB5b3Ugd2FudCB0byBhZGQgYSBjbGFzcyBuYW1lIGZvciBhIHByb3BlcnR5IHdoaWNoIGV2YWx1YXRlcyB0byB0cnVlIGFuZAogICAgYW5kIGEgZGlmZmVyZW50IGNsYXNzIG5hbWUgaWYgaXQgZXZhbHVhdGVzIHRvIGZhbHNlLCB5b3UgY2FuIHBhc3MgYSBiaW5kaW5nCiAgICBsaWtlIHRoaXM6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS13aWRnZXQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgY2xhc3NOYW1lQmluZGluZ3M6IFsnaXNFbmFibGVkOmVuYWJsZWQ6ZGlzYWJsZWQnXSwKICAgICAgaXNFbmFibGVkOiB0cnVlCiAgICB9KTsKICAgIGBgYAogIAogICAgSW52b2tpbmcgdGhpcyBjb21wb25lbnQgd2lsbCBwcm9kdWNlIEhUTUwgdGhhdCBsb29rcyBsaWtlOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyBlbmFibGVkIj48L2Rpdj4KICAgIGBgYAogIAogICAgV2hlbiBpc0VuYWJsZWQgaXMgYGZhbHNlYCwgdGhlIHJlc3VsdGluZyBIVE1MIHJlcHJlc2VudGF0aW9uIGxvb2tzIGxpa2UgdGhpczoKICAKICAgIGBgYGh0bWwKICAgIDxkaXYgaWQ9ImVtYmVyMSIgY2xhc3M9ImVtYmVyLXZpZXcgZGlzYWJsZWQiPjwvZGl2PgogICAgYGBgCiAgCiAgICBUaGlzIHN5bnRheCBvZmZlcnMgdGhlIGNvbnZlbmllbmNlIHRvIGFkZCBhIGNsYXNzIGlmIGEgcHJvcGVydHkgaXMgYGZhbHNlYDoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIC8vIEFwcGxpZXMgbm8gY2xhc3Mgd2hlbiBpc0VuYWJsZWQgaXMgdHJ1ZSBhbmQgY2xhc3MgJ2Rpc2FibGVkJyB3aGVuIGlzRW5hYmxlZCBpcyBmYWxzZQogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGNsYXNzTmFtZUJpbmRpbmdzOiBbJ2lzRW5hYmxlZDo6ZGlzYWJsZWQnXSwKICAgICAgaXNFbmFibGVkOiB0cnVlCiAgICB9KTsKICAgIGBgYAogIAogICAgSW52b2tpbmcgdGhpcyBjb21wb25lbnQgd2hlbiB0aGUgYGlzRW5hYmxlZGAgcHJvcGVydHkgaXMgdHJ1ZSB3aWxsIHByb2R1Y2UKICAgIEhUTUwgdGhhdCBsb29rcyBsaWtlOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyI+PC9kaXY+CiAgICBgYGAKICAKICAgIEludm9raW5nIGl0IHdoZW4gdGhlIGBpc0VuYWJsZWRgIHByb3BlcnR5IG9uIHRoZSBjb21wb25lbnQgaXMgYGZhbHNlYCB3aWxsCiAgICBwcm9kdWNlIEhUTUwgdGhhdCBsb29rcyBsaWtlOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyBkaXNhYmxlZCI+PC9kaXY+CiAgICBgYGAKICAKICAgIFVwZGF0ZXMgdG8gdGhlIHZhbHVlIG9mIGEgY2xhc3MgbmFtZSBiaW5kaW5nIHdpbGwgcmVzdWx0IGluIGF1dG9tYXRpYyB1cGRhdGUKICAgIG9mIHRoZSAgSFRNTCBgY2xhc3NgIGF0dHJpYnV0ZSBpbiB0aGUgY29tcG9uZW50J3MgcmVuZGVyZWQgSFRNTAogICAgcmVwcmVzZW50YXRpb24uIElmIHRoZSB2YWx1ZSBiZWNvbWVzIGBmYWxzZWAgb3IgYHVuZGVmaW5lZGAgdGhlIGNsYXNzIG5hbWUKICAgIHdpbGwgYmUgcmVtb3ZlZC4KICAKICAgIEJvdGggYGNsYXNzTmFtZXNgIGFuZCBgY2xhc3NOYW1lQmluZGluZ3NgIGFyZSBjb25jYXRlbmF0ZWQgcHJvcGVydGllcy4gU2VlCiAgICBbRW1iZXJPYmplY3RdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvRW1iZXJPYmplY3QpIGRvY3VtZW50YXRpb24gZm9yIG1vcmUKICAgIGluZm9ybWF0aW9uIGFib3V0IGNvbmNhdGVuYXRlZCBwcm9wZXJ0aWVzLgogIAogICAgIyMjIE90aGVyIEhUTUwgQXR0cmlidXRlcwogIAogICAgVGhlIEhUTUwgYXR0cmlidXRlIHNlY3Rpb24gb2YgYSBjb21wb25lbnQncyB0YWcgY2FuIGJlIHNldCBieSBwcm92aWRpbmcgYW4KICAgIGBhdHRyaWJ1dGVCaW5kaW5nc2AgcHJvcGVydHkgc2V0IHRvIGFuIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIG9uIHRoZSBjb21wb25lbnQuCiAgICBUaGUgcmV0dXJuIHZhbHVlIG9mIHRoZXNlIHByb3BlcnRpZXMgd2lsbCBiZSB1c2VkIGFzIHRoZSB2YWx1ZSBvZiB0aGUgY29tcG9uZW50J3MKICAgIEhUTUwgYXNzb2NpYXRlZCBhdHRyaWJ1dGU6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1hbmNob3IuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgdGFnTmFtZTogJ2EnLAogICAgICBhdHRyaWJ1dGVCaW5kaW5nczogWydocmVmJ10sCiAgCiAgICAgIGhyZWY6ICdodHRwOi8vZ29vZ2xlLmNvbScKICAgIH0pOwogICAgYGBgCiAgCiAgICBJbnZva2luZyB0aGlzIGNvbXBvbmVudCB3aWxsIHByb2R1Y2UgSFRNTCB0aGF0IGxvb2tzIGxpa2U6CiAgCiAgICBgYGBodG1sCiAgICA8YSBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyIgaHJlZj0iaHR0cDovL2dvb2dsZS5jb20iPjwvYT4KICAgIGBgYAogIAogICAgT25lIHByb3BlcnR5IGNhbiBiZSBtYXBwZWQgb24gdG8gYW5vdGhlciBieSBwbGFjaW5nIGEgIjoiIGJldHdlZW4KICAgIHRoZSBzb3VyY2UgcHJvcGVydHkgYW5kIHRoZSBkZXN0aW5hdGlvbiBwcm9wZXJ0eToKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LWFuY2hvci5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICB0YWdOYW1lOiAnYScsCiAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ3VybDpocmVmJ10sCiAgCiAgICAgIHVybDogJ2h0dHA6Ly9nb29nbGUuY29tJwogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDxhIGlkPSJlbWJlcjEiIGNsYXNzPSJlbWJlci12aWV3IiBocmVmPSJodHRwOi8vZ29vZ2xlLmNvbSI+PC9hPgogICAgYGBgCiAgCiAgICBIVE1MIGF0dHJpYnV0ZXMgcGFzc2VkIHdpdGggYW5nbGUgYnJhY2tldCBpbnZvY2F0aW9ucyB3aWxsIHRha2UgcHJlY2VkZW5jZQogICAgb3ZlciB0aG9zZSBzcGVjaWZpZWQgaW4gYGF0dHJpYnV0ZUJpbmRpbmdzYC4gVGhlcmVmb3JlLCBpZiB0aGlzIGNvbXBvbmVudCB3YXMKICAgIGludm9rZWQgbGlrZSBzbzoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxNeUFuY2hvciBocmVmPSJodHRwOi8vYmluZy5jb20iIEB1cmw9Imh0dHA6Ly9nb29nbGUuY29tIiAvPgogICAgYGBgCiAgCiAgICBUaGUgcmVzdWx0aW5nIEhUTUwgd2lsbCBsb29rcyBsaWtlIHRoaXM6CiAgCiAgICBgYGBodG1sCiAgICA8YSBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyIgaHJlZj0iaHR0cDovL2JpbmcuY29tIj48L2E+CiAgICBgYGAKICAKICAgIE5vdGUgdGhhdCB0aGUgYGhyZWZgIGF0dHJpYnV0ZSBpcyB1bHRpbWF0ZWx5IHNldCB0byBgaHR0cDovL2JpbmcuY29tYCwKICAgIGRlc3BpdGUgaXQgaGF2aW5nIGF0dHJpYnV0ZSBiaW5pZG5nIHRvIHRoZSBgdXJsYCBwcm9wZXJ0eSwgd2hpY2ggd2FzCiAgICBzZXQgdG8gYGh0dHA6Ly9nb29nbGUuY29tYC4KICAKICAgIE5hbWVzcGFjZWQgYXR0cmlidXRlcyAoZS5nLiBgeGxpbms6aHJlZmApIGFyZSBzdXBwb3J0ZWQsIGJ1dCBoYXZlIHRvIGJlCiAgICBtYXBwZWQsIHNpbmNlIGA6YCBpcyBub3QgYSB2YWxpZCBjaGFyYWN0ZXIgZm9yIHByb3BlcnRpZXMgaW4gSmF2YXNjcmlwdDoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXVzZS5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICB0YWdOYW1lOiAndXNlJywKICAgICAgYXR0cmlidXRlQmluZGluZ3M6IFsneGxpbmtIcmVmOnhsaW5rOmhyZWYnXSwKICAKICAgICAgeGxpbmtIcmVmOiAnI3RyaWFuZ2xlJwogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDx1c2UgeGxpbms6aHJlZj0iI3RyaWFuZ2xlIj48L3VzZT4KICAgIGBgYAogIAogICAgSWYgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgbW9uaXRvcmVkIGJ5IGBhdHRyaWJ1dGVCaW5kaW5nc2AgaXMgYSBib29sZWFuLCB0aGUKICAgIGF0dHJpYnV0ZSB3aWxsIGJlIHByZXNlbnQgb3IgYWJzZW50IGRlcGVuZGluZyBvbiB0aGUgdmFsdWU6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS10ZXh0LWlucHV0LmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIHRhZ05hbWU6ICdpbnB1dCcsCiAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ2Rpc2FibGVkJ10sCiAgCiAgICAgIGRpc2FibGVkOiBmYWxzZQogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDxpbnB1dCBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyIgLz4KICAgIGBgYAogIAogICAgYGF0dHJpYnV0ZUJpbmRpbmdzYCBjYW4gcmVmZXIgdG8gY29tcHV0ZWQgcHJvcGVydGllczoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXRleHQtaW5wdXQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIHRhZ05hbWU6ICdpbnB1dCcsCiAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ2Rpc2FibGVkJ10sCiAgCiAgICAgIGRpc2FibGVkOiBjb21wdXRlZChmdW5jdGlvbigpIHsKICAgICAgICBpZiAoc29tZUxvZ2ljKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgfSkKICAgIH0pOwogICAgYGBgCiAgCiAgICBUbyBwcmV2ZW50IHNldHRpbmcgYW4gYXR0cmlidXRlIGFsdG9nZXRoZXIsIHVzZSBgbnVsbGAgb3IgYHVuZGVmaW5lZGAgYXMgdGhlCiAgICB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgdXNlZCBpbiBgYXR0cmlidXRlQmluZGluZ3NgOgogIAogICAgYGBgYXBwL2NvbXBvbmVudHMvbXktdGV4dC1pbnB1dC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICB0YWdOYW1lOiAnZm9ybScsCiAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ25vdmFsaWRhdGUnXSwKICAgICAgbm92YWxpZGF0ZTogbnVsbAogICAgfSk7CiAgICBgYGAKICAKICAgIFVwZGF0ZXMgdG8gdGhlIHByb3BlcnR5IG9mIGFuIGF0dHJpYnV0ZSBiaW5kaW5nIHdpbGwgcmVzdWx0IGluIGF1dG9tYXRpYwogICAgdXBkYXRlIG9mIHRoZSAgSFRNTCBhdHRyaWJ1dGUgaW4gdGhlIGNvbXBvbmVudCdzIEhUTUwgb3V0cHV0LgogIAogICAgYGF0dHJpYnV0ZUJpbmRpbmdzYCBpcyBhIGNvbmNhdGVuYXRlZCBwcm9wZXJ0eS4gU2VlCiAgICBbRW1iZXJPYmplY3RdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvRW1iZXJPYmplY3QpIGRvY3VtZW50YXRpb24gZm9yIG1vcmUKICAgIGluZm9ybWF0aW9uIGFib3V0IGNvbmNhdGVuYXRlZCBwcm9wZXJ0aWVzLgogIAogICAgIyMgTGF5b3V0cwogIAogICAgVGhlIGBsYXlvdXRgIHByb3BlcnR5IGNhbiBiZSB1c2VkIHRvIGR5bmFtaWNhbGx5IHNwZWNpZnkgYSB0ZW1wbGF0ZSBhc3NvY2lhdGVkCiAgICB3aXRoIGEgY29tcG9uZW50IGNsYXNzLCBpbnN0ZWFkIG9mIHJlbHlpbmcgb24gRW1iZXIgdG8gbGluayB0b2dldGhlciBhCiAgICBjb21wb25lbnQgY2xhc3MgYW5kIGEgdGVtcGxhdGUgYmFzZWQgb24gZmlsZSBuYW1lcy4KICAKICAgIEluIGdlbmVyYWwsIGFwcGxpY2F0aW9ucyBzaG91bGQgbm90IHVzZSB0aGlzIGZlYXR1cmUsIGJ1dCBpdCdzIGNvbW1vbmx5IHVzZWQKICAgIGluIGFkZG9ucyBmb3IgaGlzdG9yaWNhbCByZWFzb25zLgogIAogICAgVGhlIGBsYXlvdXRgIHByb3BlcnR5IHNob3VsZCBiZSBzZXQgdG8gdGhlIGRlZmF1bHQgZXhwb3J0IG9mIGEgdGVtcGxhdGUKICAgIG1vZHVsZSwgd2hpY2ggaXMgdGhlIG5hbWUgb2YgYSB0ZW1wbGF0ZSBmaWxlIHdpdGhvdXQgdGhlIGAuaGJzYCBleHRlbnNpb24uCiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvcGVyc29uLXByb2ZpbGUuaGJzCiAgICA8aDE+UGVyc29uJ3MgVGl0bGU8L2gxPgogICAgPGRpdiBjbGFzcz0nZGV0YWlscyc+e3t5aWVsZH19PC9kaXY+CiAgICBgYGAKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmpzCiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIGltcG9ydCBsYXlvdXQgZnJvbSAnLi4vdGVtcGxhdGVzL2NvbXBvbmVudHMvcGVyc29uLXByb2ZpbGUnOwogIAogICAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICBsYXlvdXQKICAgICAgfSk7CiAgICBgYGAKICAKICAgIElmIHlvdSBpbnZva2UgdGhlIGNvbXBvbmVudDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxQZXJzb25Qcm9maWxlPgogICAgICA8aDI+Q2hpZWYgQmFza2V0IFdlYXZlcjwvaDI+CiAgICAgIDxoMz5GaXNoZXJtYW4gSW5kdXN0cmllczwvaDM+CiAgICA8L1BlcnNvblByb2ZpbGU+CiAgICBgYGAKICAKICAgIG9yCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7eyNwZXJzb24tcHJvZmlsZX19CiAgICAgIDxoMj5DaGllZiBCYXNrZXQgV2VhdmVyPC9oMj4KICAgICAgPGgzPkZpc2hlcm1hbiBJbmR1c3RyaWVzPC9oMz4KICAgIHt7L3BlcnNvbi1wcm9maWxlfX0KICAgIGBgYAogIAogICAgSXQgd2lsbCByZXN1bHQgaW4gdGhlIGZvbGxvd2luZyBIVE1MIG91dHB1dDoKICAKICAgIGBgYGh0bWwKICAgIDxoMT5QZXJzb24ncyBUaXRsZTwvaDE+CiAgICAgIDxkaXYgY2xhc3M9ImRldGFpbHMiPgogICAgICA8aDI+Q2hpZWYgQmFza2V0IFdlYXZlcjwvaDI+CiAgICAgIDxoMz5GaXNoZXJtYW4gSW5kdXN0cmllczwvaDM+CiAgICA8L2Rpdj4KICAgIGBgYAogIAogICAgIyMgSGFuZGxpbmcgQnJvd3NlciBFdmVudHMKICAKICAgIENvbXBvbmVudHMgY2FuIHJlc3BvbmQgdG8gdXNlci1pbml0aWF0ZWQgZXZlbnRzIGluIG9uZSBvZiB0aHJlZSB3YXlzOiBwYXNzaW5nCiAgICBhY3Rpb25zIHdpdGggYW5nbGUgYnJhY2tldCBpbnZvY2F0aW9uLCBhZGRpbmcgZXZlbnQgaGFuZGxlciBtZXRob2RzIHRvIHRoZQogICAgY29tcG9uZW50J3MgY2xhc3MsIG9yIGFkZGluZyBhY3Rpb25zIHRvIHRoZSBjb21wb25lbnQncyB0ZW1wbGF0ZS4KICAKICAgICMjIyBQYXNzaW5nIEFjdGlvbnMgV2l0aCBBbmdsZSBCcmFja2V0IEludm9hdGlvbgogIAogICAgRm9yIG9uZS1vZmYgZXZlbnRzIHNwZWNpZmljIHRvIHBhcnRpY3VsYXIgaW5zdGFuY2Ugb2YgYSBjb21wb25lbnQsIGl0IGlzIHBvc3NpYmxlCiAgICB0byBwYXNzIGFjdGlvbnMgdG8gdGhlIGNvbXBvbmVudCdzIGVsZW1lbnQgdXNpbmcgYW5nbGUgYnJhY2tldCBpbnZvYXRpb24gc3ludGF4LgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPE15V2lkZ2V0IHt7YWN0aW9uICdmaXJzdFdpZGdldENsaWNrZWQnfX0gLz4KICAKICAgIDxNeVdpZGdldCB7e2FjdGlvbiAnc2Vjb25kV2lkZ2V0Q2xpY2tlZCd9fSAvPgogICAgYGBgCiAgCiAgICBJbiB0aGlzIGNhc2UsIHdoZW4gdGhlIGZpcnN0IGNvbXBvbmVudCBpcyBjbGlja2VkIG9uLCBFbWJlciB3aWxsIGludm9rZSB0aGUKICAgIGBmaXJzdFdpZGdldENsaWNrZWRgIGFjdGlvbi4gV2hlbiB0aGUgc2Vjb25kIGNvbXBvbmVudCBpcyBjbGlja2VkIG9uLCBFbWJlcgogICAgd2lsbCBpbnZva2UgdGhlIGBzZWNvbmRXaWRnZXRDbGlja2VkYCBhY3Rpb24gaW5zdGVhZC4KICAKICAgIEJlc2lkZXMgYHt7YWN0aW9ufX1gLCBpdCBpcyBhbHNvIHBvc3NpYmxlIHRvIHBhc3MgYW55IGFyYml0cmFyeSBlbGVtZW50IG1vZGlmaWVycwogICAgdXNpbmcgdGhlIGFuZ2xlIGJyYWNrZXQgaW52b2NhdGlvbiBzeW50YXguCiAgCiAgICAjIyMgRXZlbnQgSGFuZGxlciBNZXRob2RzCiAgCiAgICBDb21wb25lbnRzIGNhbiBhbHNvIHJlc3BvbmQgdG8gdXNlci1pbml0aWF0ZWQgZXZlbnRzIGJ5IGltcGxlbWVudGluZyBhIG1ldGhvZAogICAgdGhhdCBtYXRjaGVzIHRoZSBldmVudCBuYW1lLiBUaGlzIGFwcHJvYWNoIGlzIGFwcHJvcGlhdGUgd2hlbiB0aGUgc2FtZSBldmVudAogICAgc2hvdWxkIGJlIGhhbmRsZWQgYnkgYWxsIGluc3RhbmNlcyBvZiB0aGUgc2FtZSBjb21wb25lbnQuCiAgCiAgICBBbiBldmVudCBvYmplY3Qgd2lsbCBiZSBwYXNzZWQgYXMgdGhlIGFyZ3VtZW50IHRvIHRoZSBldmVudCBoYW5kbGVyIG1ldGhvZC4KICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGljayhldmVudCkgewogICAgICAgIC8vIGBldmVudC50YXJnZXRgIGlzIGVpdGhlciB0aGUgY29tcG9uZW50J3MgZWxlbWVudCBvciBvbmUgb2YgaXRzIGNoaWxkcmVuCiAgICAgICAgbGV0IHRhZyA9IGV2ZW50LnRhcmdldC50YWdOYW1lLnRvTG93ZXJDYXNlKCk7CiAgICAgICAgY29uc29sZS5sb2coJ2NsaWNrZWQgb24gYSBgPCR7dGFnfT5gIEhUTUwgZWxlbWVudCEnKTsKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIEluIHRoaXMgZXhhbXBsZSwgd2hlbmV2ZXIgdGhlIHVzZXIgY2xpY2tlZCBhbnl3aGVyZSBpbnNpZGUgdGhlIGNvbXBvbmVudCwgaXQKICAgIHdpbGwgbG9nIGEgbWVzc2FnZSB0byB0aGUgY29uc29sZS4KICAKICAgIEl0IGlzIHBvc3NpYmxlIHRvIGhhbmRsZSBldmVudCB0eXBlcyBvdGhlciB0aGFuIGBjbGlja2AgYnkgaW1wbGVtZW50aW5nIHRoZQogICAgZm9sbG93aW5nIGV2ZW50IGhhbmRsZXIgbWV0aG9kcy4gSW4gYWRkaXRpb24sIGN1c3RvbSBldmVudHMgY2FuIGJlIHJlZ2lzdGVyZWQKICAgIGJ5IHVzaW5nIGBBcHBsaWNhdGlvbi5jdXN0b21FdmVudHNgLgogIAogICAgVG91Y2ggZXZlbnRzOgogIAogICAgKiBgdG91Y2hTdGFydGAKICAgICogYHRvdWNoTW92ZWAKICAgICogYHRvdWNoRW5kYAogICAgKiBgdG91Y2hDYW5jZWxgCiAgCiAgICBLZXlib2FyZCBldmVudHM6CiAgCiAgICAqIGBrZXlEb3duYAogICAgKiBga2V5VXBgCiAgICAqIGBrZXlQcmVzc2AKICAKICAgIE1vdXNlIGV2ZW50czoKICAKICAgICogYG1vdXNlRG93bmAKICAgICogYG1vdXNlVXBgCiAgICAqIGBjb250ZXh0TWVudWAKICAgICogYGNsaWNrYAogICAgKiBgZG91YmxlQ2xpY2tgCiAgICAqIGBmb2N1c0luYAogICAgKiBgZm9jdXNPdXRgCiAgCiAgICBGb3JtIGV2ZW50czoKICAKICAgICogYHN1Ym1pdGAKICAgICogYGNoYW5nZWAKICAgICogYGZvY3VzSW5gCiAgICAqIGBmb2N1c091dGAKICAgICogYGlucHV0YAogIAogICAgRHJhZyBhbmQgZHJvcCBldmVudHM6CiAgCiAgICAqIGBkcmFnU3RhcnRgCiAgICAqIGBkcmFnYAogICAgKiBgZHJhZ0VudGVyYAogICAgKiBgZHJhZ0xlYXZlYAogICAgKiBgZHJhZ092ZXJgCiAgICAqIGBkcmFnRW5kYAogICAgKiBgZHJvcGAKICAKICAgICMjIyBge3thY3Rpb259fWAgSGVscGVyCiAgCiAgICBJbnN0ZWFkIG9mIGhhbmRsaW5nIGFsbCBldmVudHMgb2YgYSBwYXJ0aWN1bGFyIHR5cGUgYW55d2hlcmUgaW5zaWRlIHRoZQogICAgY29tcG9uZW50J3MgZWxlbWVudCwgeW91IG1heSBpbnN0ZWFkIHdhbnQgdG8gbGltaXQgaXQgdG8gYSBwYXJ0aWN1bGFyCiAgICBlbGVtZW50IGluIHRoZSBjb21wb25lbnQncyB0ZW1wbGF0ZS4gSW4gdGhpcyBjYXNlLCBpdCB3b3VsZCBiZSBtb3JlCiAgICBjb252ZW5pZW50IHRvIGltcGxlbWVudCBhbiBhY3Rpb24gaW5zdGVhZC4KICAKICAgIEZvciBleGFtcGxlLCB5b3UgY291bGQgaW1wbGVtZW50IHRoZSBhY3Rpb24gYGhlbGxvYCBmb3IgdGhlIGBwZXJzb24tcHJvZmlsZWAKICAgIGNvbXBvbmVudDoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGFjdGlvbnM6IHsKICAgICAgICBoZWxsbyhuYW1lKSB7CiAgICAgICAgICBjb25zb2xlLmxvZygiSGVsbG8iLCBuYW1lKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBBbmQgdGhlbiB1c2UgaXQgaW4gdGhlIGNvbXBvbmVudCdzIHRlbXBsYXRlOgogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmhicwogICAgPGgxPnt7QHBlcnNvbi5uYW1lfX08L2gxPgogIAogICAgPGJ1dHRvbiB7e2FjdGlvbiAnaGVsbG8nIEBwZXJzb24ubmFtZX19PgogICAgICBTYXkgSGVsbG8gdG8ge3tAcGVyc29uLm5hbWV9fQogICAgPC9idXR0b24+CiAgICBgYGAKICAKICAgIFdoZW4gdGhlIHVzZXIgY2xpY2tzIHRoZSBidXR0b24sIEVtYmVyIHdpbGwgaW52b2tlIHRoZSBgaGVsbG9gIGFjdGlvbiwKICAgIHBhc3NpbmcgaW4gdGhlIGN1cnJlbnQgdmFsdWUgb2YgYEBwZXJzb24ubmFtZWAgYXMgYW4gYXJndW1lbnQuCiAgCiAgICBTZWUgW0VtYmVyLlRlbXBsYXRlcy5oZWxwZXJzLmFjdGlvbl0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9FbWJlci5UZW1wbGF0ZXMuaGVscGVycy9tZXRob2RzL2FjdGlvbj9hbmNob3I9YWN0aW9uKS4KICAKICAgIEBjbGFzcyBDb21wb25lbnQKICAgIEBleHRlbmRzIEVtYmVyLkNvcmVWaWV3CiAgICBAdXNlcyBFbWJlci5UYXJnZXRBY3Rpb25TdXBwb3J0CiAgICBAdXNlcyBFbWJlci5DbGFzc05hbWVzU3VwcG9ydAogICAgQHVzZXMgRW1iZXIuQWN0aW9uU3VwcG9ydAogICAgQHVzZXMgRW1iZXIuVmlld01peGluCiAgICBAdXNlcyBFbWJlci5WaWV3U3RhdGVTdXBwb3J0CiAgICBAcHVibGljCiAgKi8KCiAgdmFyIENvbXBvbmVudCA9IF92aWV3cy5Db3JlVmlldy5leHRlbmQoX3ZpZXdzLkNoaWxkVmlld3NTdXBwb3J0LCBfdmlld3MuVmlld1N0YXRlU3VwcG9ydCwgX3ZpZXdzLkNsYXNzTmFtZXNTdXBwb3J0LCBfcnVudGltZS5UYXJnZXRBY3Rpb25TdXBwb3J0LCBfdmlld3MuQWN0aW9uU3VwcG9ydCwgX3ZpZXdzLlZpZXdNaXhpbiwgKF9Db3JlVmlldyRleHRlbmQgPSB7CiAgICBpc0NvbXBvbmVudDogdHJ1ZSwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzW0lTX0RJU1BBVENISU5HX0FUVFJTXSA9IGZhbHNlOwogICAgICB0aGlzW0RJUlRZX1RBR10gPSAoMCwgX3JlZmVyZW5jZS5jcmVhdGVUYWcpKCk7CiAgICAgIHRoaXNbUk9PVF9SRUZdID0gbmV3IFJvb3RSZWZlcmVuY2UodGhpcyk7CiAgICAgIHRoaXNbQk9VTkRTXSA9IG51bGw7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgJiYgdGhpcy5yZW5kZXJlci5fZGVzdGluZWRGb3JET00gJiYgdGhpcy50YWdOYW1lID09PSAnJykgewogICAgICAgIHZhciBldmVudE5hbWVzID0gW107CiAgICAgICAgdmFyIGV2ZW50RGlzcGF0Y2hlciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpLmxvb2t1cCgnZXZlbnRfZGlzcGF0Y2hlcjptYWluJyk7CiAgICAgICAgdmFyIGV2ZW50cyA9IGV2ZW50RGlzcGF0Y2hlciAmJiBldmVudERpc3BhdGNoZXIuX2ZpbmFsRXZlbnRzIHx8IHt9OyAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6Zm9yaW4KCiAgICAgICAgZm9yICh2YXIga2V5IGluIGV2ZW50cykgewogICAgICAgICAgdmFyIG1ldGhvZE5hbWUgPSBldmVudHNba2V5XTsKCiAgICAgICAgICBpZiAodHlwZW9mIHRoaXNbbWV0aG9kTmFtZV0gPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgICAgZXZlbnROYW1lcy5wdXNoKG1ldGhvZE5hbWUpOwogICAgICAgICAgfQogICAgICAgIH0gLy8gSWYgaW4gYSB0YWdsZXNzIGNvbXBvbmVudCwgYXNzZXJ0IHRoYXQgbm8gZXZlbnQgaGFuZGxlcnMgYXJlIGRlZmluZWQKCgogICAgICAgIChmYWxzZSAmJiAhKCFldmVudE5hbWVzLmxlbmd0aCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoCiAgICAgICAgIllvdSBjYW4gbm90IGRlZmluZSBgIiArIGV2ZW50TmFtZXMgKyAiYCBmdW5jdGlvbihzKSB0byBoYW5kbGUgRE9NIGV2ZW50IGluIHRoZSBgIiArIHRoaXMgKyAiYCB0YWdsZXNzIGNvbXBvbmVudCBzaW5jZSBpdCBkb2Vzbid0IGhhdmUgYW55IERPTSBlbGVtZW50LiIsICFldmVudE5hbWVzLmxlbmd0aCkpOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISh0aGlzLm1vdXNlRW50ZXIgPT09IHVuZGVmaW5lZCkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCJVc2luZyBgbW91c2VFbnRlcmAgZXZlbnQgaGFuZGxlciBtZXRob2RzIGluIGNvbXBvbmVudHMgaGFzIGJlZW4gZGVwcmVjYXRlZC4iLCB0aGlzLm1vdXNlRW50ZXIgPT09IHVuZGVmaW5lZCwgewogICAgICAgIGlkOiAnZW1iZXItdmlld3MuZXZlbnQtZGlzcGF0Y2hlci5tb3VzZWVudGVyLWxlYXZlLW1vdmUnLAogICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2NvbXBvbmVudC1tb3VzZWVudGVyLWxlYXZlLW1vdmUnCiAgICAgIH0pKTsKICAgICAgKGZhbHNlICYmICEodGhpcy5tb3VzZUxlYXZlID09PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgiVXNpbmcgYG1vdXNlTGVhdmVgIGV2ZW50IGhhbmRsZXIgbWV0aG9kcyBpbiBjb21wb25lbnRzIGhhcyBiZWVuIGRlcHJlY2F0ZWQuIiwgdGhpcy5tb3VzZUxlYXZlID09PSB1bmRlZmluZWQsIHsKICAgICAgICBpZDogJ2VtYmVyLXZpZXdzLmV2ZW50LWRpc3BhdGNoZXIubW91c2VlbnRlci1sZWF2ZS1tb3ZlJywKICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY19jb21wb25lbnQtbW91c2VlbnRlci1sZWF2ZS1tb3ZlJwogICAgICB9KSk7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMubW91c2VNb3ZlID09PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgiVXNpbmcgYG1vdXNlTW92ZWAgZXZlbnQgaGFuZGxlciBtZXRob2RzIGluIGNvbXBvbmVudHMgaGFzIGJlZW4gZGVwcmVjYXRlZC4iLCB0aGlzLm1vdXNlTW92ZSA9PT0gdW5kZWZpbmVkLCB7CiAgICAgICAgaWQ6ICdlbWJlci12aWV3cy5ldmVudC1kaXNwYXRjaGVyLm1vdXNlZW50ZXItbGVhdmUtbW92ZScsCiAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfY29tcG9uZW50LW1vdXNlZW50ZXItbGVhdmUtbW92ZScKICAgICAgfSkpOwogICAgfSwKICAgIHJlcmVuZGVyOiBmdW5jdGlvbiByZXJlbmRlcigpIHsKICAgICAgKDAsIF9yZWZlcmVuY2UuZGlydHkpKHRoaXNbRElSVFlfVEFHXSk7CgogICAgICB0aGlzLl9zdXBlcigpOwogICAgfQogIH0sIF9Db3JlVmlldyRleHRlbmRbX21ldGFsLlBST1BFUlRZX0RJRF9DSEFOR0VdID0gZnVuY3Rpb24gKGtleSkgewogICAgaWYgKHRoaXNbSVNfRElTUEFUQ0hJTkdfQVRUUlNdKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgYXJncyA9IHRoaXNbQVJHU107CiAgICB2YXIgcmVmZXJlbmNlID0gYXJncyAhPT0gdW5kZWZpbmVkID8gYXJnc1trZXldIDogdW5kZWZpbmVkOwoKICAgIGlmIChyZWZlcmVuY2UgIT09IHVuZGVmaW5lZCAmJiByZWZlcmVuY2VbVVBEQVRFXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJlZmVyZW5jZVtVUERBVEVdKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBrZXkpKTsKICAgIH0KICB9LCBfQ29yZVZpZXckZXh0ZW5kLmdldEF0dHIgPSBmdW5jdGlvbiBnZXRBdHRyKGtleSkgewogICAgLy8gVE9ETyBJbnRpbWF0ZSBBUEkgc2hvdWxkIGJlIGRlcHJlY2F0ZWQKICAgIHJldHVybiB0aGlzLmdldChrZXkpOwogIH0sIF9Db3JlVmlldyRleHRlbmQucmVhZERPTUF0dHIgPSBmdW5jdGlvbiByZWFkRE9NQXR0cihuYW1lKSB7CiAgICAvLyBUT0RPIHJldmlzaXQgdGhpcwogICAgdmFyIF9lbGVtZW50ID0gKDAsIF92aWV3cy5nZXRWaWV3RWxlbWVudCkodGhpcyk7CgogICAgKGZhbHNlICYmICEoX2VsZW1lbnQgIT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IGNhbGwgYHJlYWRET01BdHRyYCBvbiAiICsgdGhpcyArICIgd2hpY2ggZG9lcyBub3QgaGF2ZSBhbiBlbGVtZW50IiwgX2VsZW1lbnQgIT09IG51bGwpKTsKICAgIHZhciBlbGVtZW50ID0gX2VsZW1lbnQ7CiAgICB2YXIgaXNTVkcgPSBlbGVtZW50Lm5hbWVzcGFjZVVSSSA9PT0gX3J1bnRpbWUyLlNWR19OQU1FU1BBQ0U7CgogICAgdmFyIF9ub3JtYWxpemVQcm9wZXJ0eSA9ICgwLCBfcnVudGltZTIubm9ybWFsaXplUHJvcGVydHkpKGVsZW1lbnQsIG5hbWUpLAogICAgICAgIHR5cGUgPSBfbm9ybWFsaXplUHJvcGVydHkudHlwZSwKICAgICAgICBub3JtYWxpemVkID0gX25vcm1hbGl6ZVByb3BlcnR5Lm5vcm1hbGl6ZWQ7CgogICAgaWYgKGlzU1ZHIHx8IHR5cGUgPT09ICdhdHRyJykgewogICAgICByZXR1cm4gZWxlbWVudC5nZXRBdHRyaWJ1dGUobm9ybWFsaXplZCk7CiAgICB9CgogICAgcmV0dXJuIGVsZW1lbnRbbm9ybWFsaXplZF07CiAgfSwgX0NvcmVWaWV3JGV4dGVuZC5kaWRSZWNlaXZlQXR0cnMgPSBmdW5jdGlvbiBkaWRSZWNlaXZlQXR0cnMoKSB7fSwgX0NvcmVWaWV3JGV4dGVuZC5kaWRSZW5kZXIgPSBmdW5jdGlvbiBkaWRSZW5kZXIoKSB7fSwgX0NvcmVWaWV3JGV4dGVuZC53aWxsUmVuZGVyID0gZnVuY3Rpb24gd2lsbFJlbmRlcigpIHt9LCBfQ29yZVZpZXckZXh0ZW5kLmRpZFVwZGF0ZUF0dHJzID0gZnVuY3Rpb24gZGlkVXBkYXRlQXR0cnMoKSB7fSwgX0NvcmVWaWV3JGV4dGVuZC53aWxsVXBkYXRlID0gZnVuY3Rpb24gd2lsbFVwZGF0ZSgpIHt9LCBfQ29yZVZpZXckZXh0ZW5kLmRpZFVwZGF0ZSA9IGZ1bmN0aW9uIGRpZFVwZGF0ZSgpIHt9LCBfQ29yZVZpZXckZXh0ZW5kKSk7CgogIF9leHBvcnRzLkNvbXBvbmVudCA9IENvbXBvbmVudDsKCiAgQ29tcG9uZW50LnRvU3RyaW5nID0gZnVuY3Rpb24gKCkgewogICAgcmV0dXJuICdAZW1iZXIvY29tcG9uZW50JzsKICB9OwoKICBDb21wb25lbnQucmVvcGVuQ2xhc3MoewogICAgaXNDb21wb25lbnRGYWN0b3J5OiB0cnVlLAogICAgcG9zaXRpb25hbFBhcmFtczogW10KICB9KTsKICB7CiAgICAoMCwgX3J1bnRpbWUuc2V0RnJhbWV3b3JrQ2xhc3MpKENvbXBvbmVudCk7CiAgfQogIHZhciBsYXlvdXQgPSB0ZW1wbGF0ZSh7CiAgICAiaWQiOiAiaHZ0c3o3UkYiLAogICAgImJsb2NrIjogIntcInN5bWJvbHNcIjpbXSxcInN0YXRlbWVudHNcIjpbXSxcImhhc0V2YWxcIjpmYWxzZX0iLAogICAgIm1ldGEiOiB7CiAgICAgICJtb2R1bGVOYW1lIjogInBhY2thZ2VzL0BlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIvbGliL3RlbXBsYXRlcy9lbXB0eS5oYnMiCiAgICB9CiAgfSk7CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvY29tcG9uZW50CiAgKi8KCiAgLyoqCiAgICBUaGUgaW50ZXJuYWwgY2xhc3MgdXNlZCB0byBjcmVhdGUgdGV4dCBpbnB1dHMgd2hlbiB0aGUgYHt7aW5wdXR9fWAKICAgIGhlbHBlciBpcyB1c2VkIHdpdGggYHR5cGVgIG9mIGBjaGVja2JveGAuCiAgCiAgICBTZWUgW0VtYmVyLlRlbXBsYXRlcy5oZWxwZXJzLmlucHV0XSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0VtYmVyLlRlbXBsYXRlcy5oZWxwZXJzL21ldGhvZHMvaW5wdXQ/YW5jaG9yPWlucHV0KSAgZm9yIHVzYWdlIGRldGFpbHMuCiAgCiAgICAjIyBEaXJlY3QgbWFuaXB1bGF0aW9uIG9mIGBjaGVja2VkYAogIAogICAgVGhlIGBjaGVja2VkYCBhdHRyaWJ1dGUgb2YgYW4gYENoZWNrYm94YCBvYmplY3Qgc2hvdWxkIGFsd2F5cyBiZSBzZXQKICAgIHRocm91Z2ggdGhlIEVtYmVyIG9iamVjdCBvciBieSBpbnRlcmFjdGluZyB3aXRoIGl0cyByZW5kZXJlZCBlbGVtZW50CiAgICByZXByZXNlbnRhdGlvbiB2aWEgdGhlIG1vdXNlLCBrZXlib2FyZCwgb3IgdG91Y2guIFVwZGF0aW5nIHRoZSB2YWx1ZSBvZiB0aGUKICAgIGNoZWNrYm94IHZpYSBqUXVlcnkgd2lsbCByZXN1bHQgaW4gdGhlIGNoZWNrZWQgdmFsdWUgb2YgdGhlIG9iamVjdCBhbmQgaXRzCiAgICBlbGVtZW50IGxvc2luZyBzeW5jaHJvbml6YXRpb24uCiAgCiAgICAjIyBMYXlvdXQgYW5kIExheW91dE5hbWUgcHJvcGVydGllcwogIAogICAgQmVjYXVzZSBIVE1MIGBpbnB1dGAgZWxlbWVudHMgYXJlIHNlbGYgY2xvc2luZyBgbGF5b3V0YCBhbmQgYGxheW91dE5hbWVgCiAgICBwcm9wZXJ0aWVzIHdpbGwgbm90IGJlIGFwcGxpZWQuCiAgCiAgICBAY2xhc3MgQ2hlY2tib3gKICAgIEBleHRlbmRzIENvbXBvbmVudAogICAgQHB1YmxpYwogICovCgogIHZhciBDaGVja2JveCA9IENvbXBvbmVudC5leHRlbmQoewogICAgbGF5b3V0OiBsYXlvdXQsCgogICAgLyoqCiAgICAgIEJ5IGRlZmF1bHQsIHRoaXMgY29tcG9uZW50IHdpbGwgYWRkIHRoZSBgZW1iZXItY2hlY2tib3hgIGNsYXNzIHRvIHRoZSBjb21wb25lbnQncyBlbGVtZW50LgogICAgICAgICBAcHJvcGVydHkgY2xhc3NOYW1lcwogICAgICBAdHlwZSBBcnJheSB8IFN0cmluZwogICAgICBAZGVmYXVsdCBbJ2VtYmVyLWNoZWNrYm94J10KICAgICAgQHB1YmxpYwogICAgICovCiAgICBjbGFzc05hbWVzOiBbJ2VtYmVyLWNoZWNrYm94J10sCiAgICB0YWdOYW1lOiAnaW5wdXQnLAoKICAgIC8qKgogICAgICBCeSBkZWZhdWx0IHRoaXMgY29tcG9uZW50IHdpbGwgZm9yd2FyZCBhIG51bWJlciBvZiBhcmd1bWVudHMgdG8gYXR0cmlidXRlcyBvbiB0aGUgdGhlCiAgICAgIGNvbXBvbmVudCdzIGVsZW1lbnQ6CiAgICAgICAgICogaW5kZXRlcm1pbmF0ZQogICAgICAqIGRpc2FibGVkCiAgICAgICogdGFiaW5kZXgKICAgICAgKiBuYW1lCiAgICAgICogYXV0b2ZvY3VzCiAgICAgICogcmVxdWlyZWQKICAgICAgKiBmb3JtCiAgICAgICAgIFdoZW4gaW52b2tlZCB3aXRoIGN1cmx5IGJyYWNlcywgdGhpcyBpcyB0aGUgZXhoYXVzdGl2ZSBsaXN0IG9mIEhUTUwgYXR0cmlidXRlcyB5b3UgY2FuCiAgICAgIGN1c3RvbWl6ZSAoaS5lLiBge3tpbnB1dCB0eXBlPSJjaGVja2JveCIgZGlzYWJsZWQ9dHJ1ZX19YCkuCiAgICAgICAgIFdoZW4gaW52b2tlZCB3aXRoIGFuZ2xlIGJyYWNrZXQgaW52b2NhdGlvbiwgdGhpcyBsaXN0IGlzIGlycmVsZXZhbnQsIGJlY2F1c2UgeW91IGNhbiB1c2UgSFRNTAogICAgICBhdHRyaWJ1dGUgc3ludGF4IHRvIGN1c3RvbWl6ZSB0aGUgZWxlbWVudCAoaS5lLgogICAgICBgPElucHV0IEB0eXBlPSJjaGVja2JveCIgZGlzYWJsZWQgZGF0YS1jdXN0b209ImN1c3RvbSB2YWx1ZSIgLz5gKS4gSG93ZXZlciwgYEB0eXBlYCBhbmQKICAgICAgYEBjaGVja2VkYCBtdXN0IGJlIHBhc3NlZCBhcyBuYW1lZCBhcmd1bWVudHMsIG5vdCBhdHRyaWJ1dGVzLgogICAgICAgICBAcHJvcGVydHkgYXR0cmlidXRlQmluZGluZ3MKICAgICAgQHR5cGUgQXJyYXkgfCBTdHJpbmcKICAgICAgQGRlZmF1bHQgWyd0eXBlJywgJ2NoZWNrZWQnLCAnaW5kZXRlcm1pbmF0ZScsICdkaXNhYmxlZCcsICd0YWJpbmRleCcsICduYW1lJywgJ2F1dG9mb2N1cycsICdyZXF1aXJlZCcsICdmb3JtJ10KICAgICAgQHB1YmxpYwogICAgKi8KICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ3R5cGUnLCAnY2hlY2tlZCcsICdpbmRldGVybWluYXRlJywgJ2Rpc2FibGVkJywgJ3RhYmluZGV4JywgJ25hbWUnLCAnYXV0b2ZvY3VzJywgJ3JlcXVpcmVkJywgJ2Zvcm0nXSwKCiAgICAvKioKICAgICAgU2V0cyB0aGUgYHR5cGVgIGF0dHJpYnV0ZSBvZiB0aGUgYENoZWNrYm94YCdzIGVsZW1lbnQKICAgICAgICAgQHByb3BlcnR5IGRpc2FibGVkCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgIEBwcml2YXRlCiAgICAgKi8KICAgIHR5cGU6ICdjaGVja2JveCcsCgogICAgLyoqCiAgICAgIFNldHMgdGhlIGBkaXNhYmxlZGAgYXR0cmlidXRlIG9mIHRoZSBgQ2hlY2tib3hgJ3MgZWxlbWVudAogICAgICAgICBAcHJvcGVydHkgZGlzYWJsZWQKICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgQHB1YmxpYwogICAgICovCiAgICBkaXNhYmxlZDogZmFsc2UsCgogICAgLyoqCiAgICAgIENvcnJlc3BvbmRzIHRvIHRoZSBgaW5kZXRlcm1pbmF0ZWAgcHJvcGVydHkgb2YgdGhlIGBDaGVja2JveGAncyBlbGVtZW50CiAgICAgICAgIEBwcm9wZXJ0eSBkaXNhYmxlZAogICAgICBAZGVmYXVsdCBmYWxzZQogICAgICBAcHVibGljCiAgICAgKi8KICAgIGluZGV0ZXJtaW5hdGU6IGZhbHNlLAoKICAgIC8qKgogICAgICBXaGVuZXZlciB0aGUgY2hlY2tib3ggaXMgaW5zZXJ0ZWQgaW50byB0aGUgRE9NLCBwZXJmb3JtIGluaXRpYWxpemF0aW9uIHN0ZXBzLCB3aGljaCBpbmNsdWRlCiAgICAgIHNldHRpbmcgdGhlIGluZGV0ZXJtaW5hdGUgcHJvcGVydHkgaWYgbmVlZGVkLgogICAgICAgICBJZiB0aGlzIG1ldGhvZCBpcyBvdmVycmlkZGVuLCBgc3VwZXJgIG11c3QgYmUgY2FsbGVkLgogICAgICAgICBAbWV0aG9kCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgZGlkSW5zZXJ0RWxlbWVudDogZnVuY3Rpb24gZGlkSW5zZXJ0RWxlbWVudCgpIHsKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIHRoaXMuZWxlbWVudC5pbmRldGVybWluYXRlID0gQm9vbGVhbih0aGlzLmluZGV0ZXJtaW5hdGUpOwogICAgfSwKCiAgICAvKioKICAgICAgV2hlbmV2ZXIgdGhlIGBjaGFuZ2VgIGV2ZW50IGlzIGZpcmVkIG9uIHRoZSBjaGVja2JveCwgdXBkYXRlIGl0cyBgY2hlY2tlZGAgcHJvcGVydHkgdG8gcmVmbGVjdAogICAgICB3aGV0aGVyIHRoZSBjaGVja2JveCBpcyBjaGVja2VkLgogICAgICAgICBJZiB0aGlzIG1ldGhvZCBpcyBvdmVycmlkZGVuLCBgc3VwZXJgIG11c3QgYmUgY2FsbGVkLgogICAgICAgICBAbWV0aG9kCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgY2hhbmdlOiBmdW5jdGlvbiBjaGFuZ2UoKSB7CiAgICAgICgwLCBfbWV0YWwuc2V0KSh0aGlzLCAnY2hlY2tlZCcsIHRoaXMuZWxlbWVudC5jaGVja2VkKTsKICAgIH0KICB9KTsKICBfZXhwb3J0cy5DaGVja2JveCA9IENoZWNrYm94OwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgdmFyIFVOU0VUID0ge307CiAgICBDaGVja2JveC5yZW9wZW4oewogICAgICB2YWx1ZTogVU5TRVQsCiAgICAgIGRpZFJlY2VpdmVBdHRyczogZnVuY3Rpb24gZGlkUmVjZWl2ZUF0dHJzKCkgewogICAgICAgIHRoaXMuX3N1cGVyKCk7CgogICAgICAgIChmYWxzZSAmJiAhKCEodGhpcy50eXBlID09PSAnY2hlY2tib3gnICYmIHRoaXMudmFsdWUgIT09IFVOU0VUKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJgPElucHV0IEB0eXBlPSdjaGVja2JveCcgQHZhbHVlPXt7Li4ufX0gLz5gIGlzIG5vdCBzdXBwb3J0ZWQ7ICIgKyAicGxlYXNlIHVzZSBgPElucHV0IEB0eXBlPSdjaGVja2JveCcgQGNoZWNrZWQ9e3suLi59fSAvPmAgaW5zdGVhZC4iLCAhKHRoaXMudHlwZSA9PT0gJ2NoZWNrYm94JyAmJiB0aGlzLnZhbHVlICE9PSBVTlNFVCkpKTsKICAgICAgfQogICAgfSk7CiAgfQoKICBDaGVja2JveC50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHsKICAgIHJldHVybiAnQGVtYmVyL2NvbXBvbmVudC9jaGVja2JveCc7CiAgfTsKICAvKioKICBAbW9kdWxlIEBlbWJlci9jb21wb25lbnQKICAqLwoKCiAgdmFyIGlucHV0VHlwZXMgPSBfYnJvd3NlckVudmlyb25tZW50Lmhhc0RPTSA/IE9iamVjdC5jcmVhdGUobnVsbCkgOiBudWxsOwoKICBmdW5jdGlvbiBjYW5TZXRUeXBlT2ZJbnB1dCh0eXBlKSB7CiAgICAvLyBpZiBydW5uaW5nIGluIG91dHNpZGUgb2YgYSBicm93c2VyIGFsd2F5cyByZXR1cm4KICAgIC8vIHRoZSBvcmlnaW5hbCB0eXBlCiAgICBpZiAoIV9icm93c2VyRW52aXJvbm1lbnQuaGFzRE9NKSB7CiAgICAgIHJldHVybiBCb29sZWFuKHR5cGUpOwogICAgfQoKICAgIGlmICh0eXBlIGluIGlucHV0VHlwZXMpIHsKICAgICAgcmV0dXJuIGlucHV0VHlwZXNbdHlwZV07CiAgICB9CgogICAgdmFyIGlucHV0VHlwZVRlc3RFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKTsKCiAgICB0cnkgewogICAgICBpbnB1dFR5cGVUZXN0RWxlbWVudC50eXBlID0gdHlwZTsKICAgIH0gY2F0Y2ggKGUpIHsvLyBpZ25vcmVkCiAgICB9CgogICAgcmV0dXJuIGlucHV0VHlwZXNbdHlwZV0gPSBpbnB1dFR5cGVUZXN0RWxlbWVudC50eXBlID09PSB0eXBlOwogIH0KICAvKioKICAgIFRoZSBpbnRlcm5hbCBjbGFzcyB1c2VkIHRvIGNyZWF0ZSB0ZXh0IGlucHV0cyB3aGVuIHRoZSBgSW5wdXRgIGNvbXBvbmVudCBpcyB1c2VkIHdpdGggYHR5cGVgIG9mIGB0ZXh0YC4KICAKICAgIFNlZSBbRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMuSW5wdXRdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMvbWV0aG9kcy9JbnB1dD9hbmNob3I9SW5wdXQpIGZvciB1c2FnZSBkZXRhaWxzLgogIAogICAgIyMgTGF5b3V0IGFuZCBMYXlvdXROYW1lIHByb3BlcnRpZXMKICAKICAgIEJlY2F1c2UgSFRNTCBgaW5wdXRgIGVsZW1lbnRzIGFyZSBzZWxmIGNsb3NpbmcgYGxheW91dGAgYW5kIGBsYXlvdXROYW1lYAogICAgcHJvcGVydGllcyB3aWxsIG5vdCBiZSBhcHBsaWVkLgogIAogICAgQGNsYXNzIFRleHRGaWVsZAogICAgQGV4dGVuZHMgQ29tcG9uZW50CiAgICBAdXNlcyBFbWJlci5UZXh0U3VwcG9ydAogICAgQHB1YmxpYwogICovCgoKICB2YXIgVGV4dEZpZWxkID0gQ29tcG9uZW50LmV4dGVuZChfdmlld3MuVGV4dFN1cHBvcnQsIHsKICAgIGxheW91dDogbGF5b3V0LAoKICAgIC8qKgogICAgICBCeSBkZWZhdWx0LCB0aGlzIGNvbXBvbmVudCB3aWxsIGFkZCB0aGUgYGVtYmVyLXRleHQtZmllbGRgIGNsYXNzIHRvIHRoZSBjb21wb25lbnQncyBlbGVtZW50LgogICAgICAgICBAcHJvcGVydHkgY2xhc3NOYW1lcwogICAgICBAdHlwZSBBcnJheSB8IFN0cmluZwogICAgICBAZGVmYXVsdCBbJ2VtYmVyLXRleHQtZmllbGQnXQogICAgICBAcHVibGljCiAgICAgKi8KICAgIGNsYXNzTmFtZXM6IFsnZW1iZXItdGV4dC1maWVsZCddLAogICAgdGFnTmFtZTogJ2lucHV0JywKCiAgICAvKioKICAgICAgQnkgZGVmYXVsdCB0aGlzIGNvbXBvbmVudCB3aWxsIGZvcndhcmQgYSBudW1iZXIgb2YgYXJndW1lbnRzIHRvIGF0dHJpYnV0ZXMgb24gdGhlIHRoZQogICAgICBjb21wb25lbnQncyBlbGVtZW50OgogICAgICAgICAqIGFjY2VwdAogICAgICAqIGF1dG9jb21wbGV0ZQogICAgICAqIGF1dG9zYXZlCiAgICAgICogZGlyCiAgICAgICogZm9ybWFjdGlvbgogICAgICAqIGZvcm1lbmN0eXBlCiAgICAgICogZm9ybW1ldGhvZAogICAgICAqIGZvcm1ub3ZhbGlkYXRlCiAgICAgICogZm9ybXRhcmdldAogICAgICAqIGhlaWdodAogICAgICAqIGlucHV0bW9kZQogICAgICAqIGxhbmcKICAgICAgKiBsaXN0CiAgICAgICogdHlwZQogICAgICAqIG1heAogICAgICAqIG1pbgogICAgICAqIG11bHRpcGxlCiAgICAgICogbmFtZQogICAgICAqIHBhdHRlcm4KICAgICAgKiBzaXplCiAgICAgICogc3RlcAogICAgICAqIHZhbHVlCiAgICAgICogd2lkdGgKICAgICAgICAgV2hlbiBpbnZva2VkIHdpdGggYHt7aW5wdXQgdHlwZT0idGV4dCJ9fWAsIHlvdSBjYW4gb25seSBjdXN0b21pemUgdGhlc2UgYXR0cmlidXRlcy4gV2hlbiBpbnZva2VkCiAgICAgIHdpdGggYDxJbnB1dCBAdHlwZT0idGV4dCIgLz5gLCB5b3UgY2FuIGp1c3QgdXNlIEhUTUwgYXR0cmlidXRlcyBkaXJlY3RseS4KICAgICAgICAgQHByb3BlcnR5IGF0dHJpYnV0ZUJpbmRpbmdzCiAgICAgIEB0eXBlIEFycmF5IHwgU3RyaW5nCiAgICAgIEBkZWZhdWx0IFsnYWNjZXB0JywgJ2F1dG9jb21wbGV0ZScsICdhdXRvc2F2ZScsICdkaXInLCAnZm9ybWFjdGlvbicsICdmb3JtZW5jdHlwZScsICdmb3JtbWV0aG9kJywgJ2Zvcm1ub3ZhbGlkYXRlJywgJ2Zvcm10YXJnZXQnLCAnaGVpZ2h0JywgJ2lucHV0bW9kZScsICdsYW5nJywgJ2xpc3QnLCAndHlwZScsICdtYXgnLCAnbWluJywgJ211bHRpcGxlJywgJ25hbWUnLCAncGF0dGVybicsICdzaXplJywgJ3N0ZXAnLCAndmFsdWUnLCAnd2lkdGgnXQogICAgICBAcHVibGljCiAgICAqLwogICAgYXR0cmlidXRlQmluZGluZ3M6IFsnYWNjZXB0JywgJ2F1dG9jb21wbGV0ZScsICdhdXRvc2F2ZScsICdkaXInLCAnZm9ybWFjdGlvbicsICdmb3JtZW5jdHlwZScsICdmb3JtbWV0aG9kJywgJ2Zvcm1ub3ZhbGlkYXRlJywgJ2Zvcm10YXJnZXQnLCAnaGVpZ2h0JywgJ2lucHV0bW9kZScsICdsYW5nJywgJ2xpc3QnLCAndHlwZScsICdtYXgnLCAnbWluJywgJ211bHRpcGxlJywgJ25hbWUnLCAncGF0dGVybicsICdzaXplJywgJ3N0ZXAnLCAndmFsdWUnLCAnd2lkdGgnXSwKCiAgICAvKioKICAgICAgQXMgdGhlIHVzZXIgaW5wdXRzIHRleHQsIHRoaXMgcHJvcGVydHkgaXMgdXBkYXRlZCB0byByZWZsZWN0IHRoZSBgdmFsdWVgIHByb3BlcnR5IG9mIHRoZSBIVE1MCiAgICAgIGVsZW1lbnQuCiAgICAgICAgIEBwcm9wZXJ0eSB2YWx1ZQogICAgICBAdHlwZSBTdHJpbmcKICAgICAgQGRlZmF1bHQgIiIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHZhbHVlOiAnJywKCiAgICAvKioKICAgICAgVGhlIGB0eXBlYCBhdHRyaWJ1dGUgb2YgdGhlIGlucHV0IGVsZW1lbnQuCiAgICAgICAgIEBwcm9wZXJ0eSB0eXBlCiAgICAgIEB0eXBlIFN0cmluZwogICAgICBAZGVmYXVsdCAidGV4dCIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHR5cGU6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKHsKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuICd0ZXh0JzsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoX2tleSwgdmFsdWUkJDEpIHsKICAgICAgICB2YXIgdHlwZSA9ICd0ZXh0JzsKCiAgICAgICAgaWYgKGNhblNldFR5cGVPZklucHV0KHZhbHVlJCQxKSkgewogICAgICAgICAgdHlwZSA9IHZhbHVlJCQxOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHR5cGU7CiAgICAgIH0KICAgIH0pLAoKICAgIC8qKgogICAgICBUaGUgYHNpemVgIG9mIHRoZSB0ZXh0IGZpZWxkIGluIGNoYXJhY3RlcnMuCiAgICAgICAgIEBwcm9wZXJ0eSBzaXplCiAgICAgIEB0eXBlIFN0cmluZwogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBzaXplOiBudWxsLAoKICAgIC8qKgogICAgICBUaGUgYHBhdHRlcm5gIGF0dHJpYnV0ZSBvZiBpbnB1dCBlbGVtZW50LgogICAgICAgICBAcHJvcGVydHkgcGF0dGVybgogICAgICBAdHlwZSBTdHJpbmcKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwogICAgcGF0dGVybjogbnVsbCwKCiAgICAvKioKICAgICAgVGhlIGBtaW5gIGF0dHJpYnV0ZSBvZiBpbnB1dCBlbGVtZW50IHVzZWQgd2l0aCBgdHlwZT0ibnVtYmVyImAgb3IgYHR5cGU9InJhbmdlImAuCiAgICAgICAgIEBwcm9wZXJ0eSBtaW4KICAgICAgQHR5cGUgU3RyaW5nCiAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgQHNpbmNlIDEuNC4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBtaW46IG51bGwsCgogICAgLyoqCiAgICAgIFRoZSBgbWF4YCBhdHRyaWJ1dGUgb2YgaW5wdXQgZWxlbWVudCB1c2VkIHdpdGggYHR5cGU9Im51bWJlciJgIG9yIGB0eXBlPSJyYW5nZSJgLgogICAgICAgICBAcHJvcGVydHkgbWF4CiAgICAgIEB0eXBlIFN0cmluZwogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBzaW5jZSAxLjQuMAogICAgICBAcHVibGljCiAgICAqLwogICAgbWF4OiBudWxsCiAgfSk7CiAgX2V4cG9ydHMuVGV4dEZpZWxkID0gVGV4dEZpZWxkOwoKICBUZXh0RmllbGQudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7CiAgICByZXR1cm4gJ0BlbWJlci9jb21wb25lbnQvdGV4dC1maWVsZCc7CiAgfTsKICAvKioKICBAbW9kdWxlIEBlbWJlci9jb21wb25lbnQKICAqLwoKICAvKioKICAgIFRoZSBgVGV4dGFyZWFgIGNvbXBvbmVudCBpbnNlcnRzIGEgbmV3IGluc3RhbmNlIG9mIGA8dGV4dGFyZWE+YCB0YWcgaW50byB0aGUgdGVtcGxhdGUuCiAgCiAgICBUaGUgYEB2YWx1ZWAgYXJndW1lbnQgcHJvdmlkZXMgdGhlIGNvbnRlbnQgb2YgdGhlIGA8dGV4dGFyZWE+YC4KICAKICAgIFRoaXMgdGVtcGxhdGU6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8VGV4dGFyZWEgQHZhbHVlPSJBIGJ1bmNoIG9mIHRleHQiIC8+CiAgICBgYGAKICAKICAgIFdvdWxkIHJlc3VsdCBpbiB0aGUgZm9sbG93aW5nIEhUTUw6CiAgCiAgICBgYGBodG1sCiAgICA8dGV4dGFyZWEgY2xhc3M9ImVtYmVyLXRleHQtYXJlYSI+CiAgICAgIEEgYnVuY2ggb2YgdGV4dAogICAgPC90ZXh0YXJlYT4KICAgIGBgYAogIAogICAgVGhlIGBAdmFsdWVgIGFyZ3VtZW50IGlzIHR3by13YXkgYm91bmQuIElmIHRoZSB1c2VyIHR5cGVzIHRleHQgaW50byB0aGUgdGV4dGFyZWEsIHRoZSBgQHZhbHVlYAogICAgYXJndW1lbnQgaXMgdXBkYXRlZC4gSWYgdGhlIGBAdmFsdWVgIGFyZ3VtZW50IGlzIHVwZGF0ZWQsIHRoZSB0ZXh0IGluIHRoZSB0ZXh0YXJlYSBpcyB1cGRhdGVkLgogIAogICAgSW4gdGhlIGZvbGxvd2luZyBleGFtcGxlLCB0aGUgYHdyaXR0ZW5Xb3Jkc2AgcHJvcGVydHkgb24gdGhlIGNvbXBvbmVudCB3aWxsIGJlIHVwZGF0ZWQgYXMgdGhlIHVzZXIKICAgIHR5cGVzICdMb3RzIG9mIHRleHQnIGludG8gdGhlIHRleHQgYXJlYSBvZiB0aGVpciBicm93c2VyJ3Mgd2luZG93LgogIAogICAgYGBgYXBwL2NvbXBvbmVudHMvd29yZC1lZGl0b3IuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGdsaW1tZXIvY29tcG9uZW50JzsKICAgIGltcG9ydCB7IHRyYWNrZWQgfSBmcm9tICdAZ2xpbW1lci90cmFja2luZyc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBjbGFzcyBleHRlbmRzIENvbXBvbmVudCB7CiAgICAgIEB0cmFja2VkIHdyaXR0ZW5Xb3JkcyA9ICJMb3RzIG9mIHRleHQgdGhhdCBJUyBib3VuZCI7CiAgICB9CiAgICBgYGAKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxUZXh0YXJlYSBAdmFsdWU9e3t3cml0dGVuV29yZHN9fSAvPgogICAgYGBgCiAgCiAgICBXb3VsZCByZXN1bHQgaW4gdGhlIGZvbGxvd2luZyBIVE1MOgogIAogICAgYGBgaHRtbAogICAgPHRleHRhcmVhIGNsYXNzPSJlbWJlci10ZXh0LWFyZWEiPgogICAgICBMb3RzIG9mIHRleHQgdGhhdCBJUyBib3VuZAogICAgPC90ZXh0YXJlYT4KICAgIGBgYAogIAogICAgSWYgeW91IHdhbnRlZCBhIG9uZSB3YXkgYmluZGluZywgeW91IGNvdWxkIHVzZSB0aGUgYDx0ZXh0YXJlYT5gIGVsZW1lbnQgZGlyZWN0bHksIGFuZCB1c2UgdGhlCiAgICBgdmFsdWVgIERPTSBwcm9wZXJ0eSBhbmQgdGhlIGBpbnB1dGAgZXZlbnQuCiAgCiAgICAjIyMgQWN0aW9ucwogIAogICAgVGhlIGBUZXh0YXJlYWAgY29tcG9uZW50IHRha2VzIGEgbnVtYmVyIG9mIGFyZ3VtZW50cyB3aXRoIGNhbGxiYWNrcyB0aGF0IGFyZSBpbnZva2VkIGluCiAgICByZXNwb25zZSB0byB1c2VyIGV2ZW50cy4KICAKICAgICogYGVudGVyYAogICAgKiBgaW5zZXJ0LW5ld2xpbmVgCiAgICAqIGBlc2NhcGUtcHJlc3NgCiAgICAqIGBmb2N1cy1pbmAKICAgICogYGZvY3VzLW91dGAKICAgICogYGtleS1wcmVzc2AKICAKICAgIFRoZXNlIGNhbGxiYWNrcyBhcmUgcGFzc2VkIHRvIGBUZXh0YXJlYWAgbGlrZSB0aGlzOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPFRleHRhcmVhIEB2YWx1ZT17e3RoaXMuc2VhcmNoV29yZH19IEBlbnRlcj17e3RoaXMucXVlcnl9fSAvPgogICAgYGBgCiAgCiAgICAjIyBDbGFzc2ljIEludm9jYXRpb24gU3ludGF4CiAgCiAgICBUaGUgYFRleHRhcmVhYCBjb21wb25lbnQgY2FuIGFsc28gYmUgaW52b2tlZCB1c2luZyBjdXJseSBicmFjZXMsIGp1c3QgbGlrZSBhbnkgb3RoZXIgRW1iZXIKICAgIGNvbXBvbmVudC4KICAKICAgIEZvciBleGFtcGxlLCB0aGlzIGlzIGFuIGludm9jYXRpb24gdXNpbmcgYW5nbGUtYnJhY2tldCBub3RhdGlvbjoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxUZXh0YXJlYSBAdmFsdWU9e3t0aGlzLnNlYXJjaFdvcmR9fSBAZW50ZXI9e3t0aGlzLnF1ZXJ5fX0gLz4KICAgIGBgYAogIAogICAgWW91IGNvdWxkIGFjY29tcGxpc2ggdGhlIHNhbWUgdGhpbmcgdXNpbmcgY2xhc3NpYyBpbnZvY2F0aW9uOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3t0ZXh0YXJlYSB2YWx1ZT10aGlzLnNlYXJjaFdvcmQgZW50ZXI9dGhpcy5xdWVyeX19CiAgICBgYGAKICAKICAgIFRoZSBtYWluIGRpZmZlcmVuY2UgaXMgdGhhdCBhbmdsZS1icmFja2V0IGludm9jYXRpb24gc3VwcG9ydHMgYW55IEhUTUwgYXR0cmlidXRlIHVzaW5nIEhUTUwKICAgIGF0dHJpYnV0ZSBzeW50YXgsIGJlY2F1c2UgYXR0cmlidXRlcyBhbmQgYXJndW1lbnRzIGhhdmUgZGlmZmVyZW50IHN5bnRheCB3aGVuIHVzaW5nIGFuZ2xlLWJyYWNrZXQKICAgIGludm9jYXRpb24uIEN1cmx5IGJyYWNlIGludm9jYXRpb24sIG9uIHRoZSBvdGhlciBoYW5kLCBvbmx5IGhhcyBhIHNpbmdsZSBzeW50YXggZm9yIGFyZ3VtZW50cywKICAgIGFuZCBjb21wb25lbnRzIG11c3QgbWFudWFsbHkgbWFwIGF0dHJpYnV0ZXMgb250byBjb21wb25lbnQgYXJndW1lbnRzLgogIAogICAgV2hlbiB1c2luZyBjbGFzc2ljIGludm9jYXRpb24gd2l0aCBge3t0ZXh0YXJlYX19YCwgb25seSB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMgYXJlIG1hcHBlZCBvbnRvCiAgICBhcmd1bWVudHM6CiAgCiAgICAqIHJvd3MKICAgICogY29scwogICAgKiBuYW1lCiAgICAqIHNlbGVjdGlvbkVuZAogICAgKiBzZWxlY3Rpb25TdGFydAogICAgKiBhdXRvY29tcGxldGUKICAgICogd3JhcAogICAgKiBsYW5nCiAgICAqIGRpcgogICAgKiB2YWx1ZQogIAogICAgIyMgQ2xhc3NpYyBgbGF5b3V0YCBhbmQgYGxheW91dE5hbWVgIHByb3BlcnRpZXMKICAKICAgIEJlY2F1c2UgSFRNTCBgdGV4dGFyZWFgIGVsZW1lbnRzIGRvIG5vdCBjb250YWluIGlubmVyIEhUTUwgdGhlIGBsYXlvdXRgIGFuZAogICAgYGxheW91dE5hbWVgIHByb3BlcnRpZXMgd2lsbCBub3QgYmUgYXBwbGllZC4KICAKICAgIEBtZXRob2QgVGV4dGFyZWEKICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMKICAgIEBzZWUge1RleHRBcmVhfQogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgU2VlIEVtYmVyLlRlbXBsYXRlcy5jb21wb25lbnRzLlRleHRhcmVhLgogIAogICAgQG1ldGhvZCB0ZXh0YXJlYQogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHNlZSB7RW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMudGV4dGFyZWF9CiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBUaGUgaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gdXNlZCBmb3IgYFRleHRhcmVhYCBpbnZvY2F0aW9ucy4KICAKICAgIEBjbGFzcyBUZXh0QXJlYQogICAgQGV4dGVuZHMgQ29tcG9uZW50CiAgICBAc2VlIHtFbWJlci5UZW1wbGF0ZXMuY29tcG9uZW50cy5UZXh0YXJlYX0KICAgIEB1c2VzIEVtYmVyLlRleHRTdXBwb3J0CiAgICBAcHVibGljCiAgKi8KCgogIHZhciBUZXh0QXJlYSA9IENvbXBvbmVudC5leHRlbmQoX3ZpZXdzLlRleHRTdXBwb3J0LCB7CiAgICBjbGFzc05hbWVzOiBbJ2VtYmVyLXRleHQtYXJlYSddLAogICAgbGF5b3V0OiBsYXlvdXQsCiAgICB0YWdOYW1lOiAndGV4dGFyZWEnLAogICAgYXR0cmlidXRlQmluZGluZ3M6IFsncm93cycsICdjb2xzJywgJ25hbWUnLCAnc2VsZWN0aW9uRW5kJywgJ3NlbGVjdGlvblN0YXJ0JywgJ2F1dG9jb21wbGV0ZScsICd3cmFwJywgJ2xhbmcnLCAnZGlyJywgJ3ZhbHVlJ10sCiAgICByb3dzOiBudWxsLAogICAgY29sczogbnVsbAogIH0pOwogIF9leHBvcnRzLlRleHRBcmVhID0gVGV4dEFyZWE7CgogIFRleHRBcmVhLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkgewogICAgcmV0dXJuICdAZW1iZXIvY29tcG9uZW50L3RleHQtYXJlYSc7CiAgfTsKCiAgdmFyIGxheW91dCQxID0gdGVtcGxhdGUoewogICAgImlkIjogImdpVE54K29wIiwKICAgICJibG9jayI6ICJ7XCJzeW1ib2xzXCI6W1wiJmRlZmF1bHRcIl0sXCJzdGF0ZW1lbnRzXCI6W1s0LFwiaWZcIixbWzI1LDFdXSxudWxsLHtcInN0YXRlbWVudHNcIjpbWzE0LDFdXSxcInBhcmFtZXRlcnNcIjpbXX0se1wic3RhdGVtZW50c1wiOltbMSxbMjMsMCxbXCJsaW5rVGl0bGVcIl1dLGZhbHNlXV0sXCJwYXJhbWV0ZXJzXCI6W119XV0sXCJoYXNFdmFsXCI6ZmFsc2V9IiwKICAgICJtZXRhIjogewogICAgICAibW9kdWxlTmFtZSI6ICJwYWNrYWdlcy9AZW1iZXIvLWludGVybmFscy9nbGltbWVyL2xpYi90ZW1wbGF0ZXMvbGluay10by5oYnMiCiAgICB9CiAgfSk7CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIHZhciBMaW5rQ29tcG9uZW50OwogIHsKICAgIC8qKgogICAgICBUaGUgYExpbmtUb2AgY29tcG9uZW50IHJlbmRlcnMgYSBsaW5rIHRvIHRoZSBzdXBwbGllZCBgcm91dGVOYW1lYCBwYXNzaW5nIGFuIG9wdGlvbmFsbHkKICAgICAgc3VwcGxpZWQgbW9kZWwgdG8gdGhlIHJvdXRlIGFzIGl0cyBgbW9kZWxgIGNvbnRleHQgb2YgdGhlIHJvdXRlLiBUaGUgYmxvY2sgZm9yIGBMaW5rVG9gCiAgICAgIGJlY29tZXMgdGhlIGNvbnRlbnRzIG9mIHRoZSByZW5kZXJlZCBlbGVtZW50OgogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIDxMaW5rVG8gQHJvdXRlPSdwaG90b0dhbGxlcnknPgogICAgICAgIEdyZWF0IEhhbXN0ZXIgUGhvdG9zCiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgVGhpcyB3aWxsIHJlc3VsdCBpbjoKICAgICAgICAgYGBgaHRtbAogICAgICA8YSBocmVmPSIvaGFtc3Rlci1waG90b3MiPgogICAgICAgIEdyZWF0IEhhbXN0ZXIgUGhvdG9zCiAgICAgIDwvYT4KICAgICAgYGBgCiAgICAgICAgICMjIyBEaXNhYmxpbmcgdGhlIGBMaW5rVG9gIGNvbXBvbmVudAogICAgICAgICBUaGUgYExpbmtUb2AgY29tcG9uZW50IGNhbiBiZSBkaXNhYmxlZCBieSB1c2luZyB0aGUgYGRpc2FibGVkYCBhcmd1bWVudC4gQSBkaXNhYmxlZCBsaW5rCiAgICAgIGRvZXNuJ3QgcmVzdWx0IGluIGEgdHJhbnNpdGlvbiB3aGVuIGFjdGl2YXRlZCwgYW5kIGFkZHMgdGhlIGBkaXNhYmxlZGAgY2xhc3MgdG8gdGhlIGA8YT5gCiAgICAgIGVsZW1lbnQuCiAgICAgICAgIChUaGUgY2xhc3MgbmFtZSB0byBhcHBseSB0byB0aGUgZWxlbWVudCBjYW4gYmUgb3ZlcnJpZGRlbiBieSB1c2luZyB0aGUgYGRpc2FibGVkQ2xhc3NgCiAgICAgIGFyZ3VtZW50KQogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIDxMaW5rVG8gQHJvdXRlPSdwaG90b0dhbGxlcnknIEBkaXNhYmxlZD17e3RydWV9fT4KICAgICAgICBHcmVhdCBIYW1zdGVyIFBob3RvcwogICAgICA8L0xpbmtUbz4KICAgICAgYGBgCiAgICAgICAgICMjIyBIYW5kbGluZyBgaHJlZmAKICAgICAgICAgYDxMaW5rVG8+YCB3aWxsIHVzZSB5b3VyIGFwcGxpY2F0aW9uJ3MgUm91dGVyIHRvIGZpbGwgdGhlIGVsZW1lbnQncyBgaHJlZmAgcHJvcGVydHkgd2l0aCBhIFVSTAogICAgICB0aGF0IG1hdGNoZXMgdGhlIHBhdGggdG8gdGhlIHN1cHBsaWVkIGByb3V0ZU5hbWVgLgogICAgICAgICAjIyMgSGFuZGxpbmcgY3VycmVudCByb3V0ZQogICAgICAgICBUaGUgYExpbmtUb2AgY29tcG9uZW50IHdpbGwgYXBwbHkgYSBDU1MgY2xhc3MgbmFtZSBvZiAnYWN0aXZlJyB3aGVuIHRoZSBhcHBsaWNhdGlvbidzIGN1cnJlbnQKICAgICAgcm91dGUgbWF0Y2hlcyB0aGUgc3VwcGxpZWQgcm91dGVOYW1lLiBGb3IgZXhhbXBsZSwgaWYgdGhlIGFwcGxpY2F0aW9uJ3MgY3VycmVudCByb3V0ZSBpcwogICAgICAncGhvdG9HYWxsZXJ5LnJlY2VudCcsIHRoZW4gdGhlIGZvbGxvd2luZyBpbnZvY2F0aW9uIG9mIGBMaW5rVG9gOgogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIDxMaW5rVG8gQHJvdXRlPSdwaG90b0dhbGxlcnkucmVjZW50Jz4KICAgICAgICBHcmVhdCBIYW1zdGVyIFBob3RvcwogICAgICA8L0xpbmtUbz4KICAgICAgYGBgCiAgICAgICAgIHdpbGwgcmVzdWx0IGluCiAgICAgICAgIGBgYGh0bWwKICAgICAgPGEgaHJlZj0iL2hhbXN0ZXItcGhvdG9zL3RoaXMtd2VlayIgY2xhc3M9ImFjdGl2ZSI+CiAgICAgICAgR3JlYXQgSGFtc3RlciBQaG90b3MKICAgICAgPC9hPgogICAgICBgYGAKICAgICAgICAgVGhlIENTUyBjbGFzcyB1c2VkIGZvciBhY3RpdmUgY2xhc3NlcyBjYW4gYmUgY3VzdG9taXplZCBieSBwYXNzaW5nIGFuIGBhY3RpdmVDbGFzc2AgYXJndW1lbnQ6CiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPExpbmtUbyBAcm91dGU9J3Bob3RvR2FsbGVyeS5yZWNlbnQnIEBhY3RpdmVDbGFzcz0iY3VycmVudC11cmwiPgogICAgICAgIEdyZWF0IEhhbXN0ZXIgUGhvdG9zCiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgYGBgaHRtbAogICAgICA8YSBocmVmPSIvaGFtc3Rlci1waG90b3MvdGhpcy13ZWVrIiBjbGFzcz0iY3VycmVudC11cmwiPgogICAgICAgIEdyZWF0IEhhbXN0ZXIgUGhvdG9zCiAgICAgIDwvYT4KICAgICAgYGBgCiAgICAgICAgICMjIyBLZWVwaW5nIGEgbGluayBhY3RpdmUgZm9yIG90aGVyIHJvdXRlcwogICAgICAgICBJZiB5b3UgbmVlZCBhIGxpbmsgdG8gYmUgJ2FjdGl2ZScgZXZlbiB3aGVuIGl0IGRvZXNuJ3QgbWF0Y2ggdGhlIGN1cnJlbnQgcm91dGUsIHlvdSBjYW4gdXNlIHRoZQogICAgICBgY3VycmVudC13aGVuYCBhcmd1bWVudC4KICAgICAgICAgYGBgaGFuZGxlYmFycwogICAgICA8TGlua1RvIEByb3V0ZT0ncGhvdG9HYWxsZXJ5JyBAY3VycmVudC13aGVuPSdwaG90b3MnPgogICAgICAgIFBob3RvIEdhbGxlcnkKICAgICAgPC9MaW5rVG8+CiAgICAgIGBgYAogICAgICAgICBUaGlzIG1heSBiZSBoZWxwZnVsIGZvciBrZWVwaW5nIGxpbmtzIGFjdGl2ZSBmb3I6CiAgICAgICAgICogbm9uLW5lc3RlZCByb3V0ZXMgdGhhdCBhcmUgbG9naWNhbGx5IHJlbGF0ZWQKICAgICAgKiBzb21lIHNlY29uZGFyeSBtZW51IGFwcHJvYWNoZXMKICAgICAgKiAndG9wIG5hdmlnYXRpb24nIHdpdGggJ3N1YiBuYXZpZ2F0aW9uJyBzY2VuYXJpb3MKICAgICAgICAgQSBsaW5rIHdpbGwgYmUgYWN0aXZlIGlmIGBjdXJyZW50LXdoZW5gIGlzIGB0cnVlYCBvciB0aGUgY3VycmVudAogICAgICByb3V0ZSBpcyB0aGUgcm91dGUgdGhpcyBsaW5rIHdvdWxkIHRyYW5zaXRpb24gdG8uCiAgICAgICAgIFRvIG1hdGNoIG11bHRpcGxlIHJvdXRlcyAnc3BhY2Utc2VwYXJhdGUnIHRoZSByb3V0ZXM6CiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPExpbmtUbyBAcm91dGU9J2dhbGxlcnknIEBjdXJyZW50LXdoZW49J3Bob3RvcyBkcmF3aW5ncyBwYWludGluZ3MnPgogICAgICAgIEFydCBHYWxsZXJ5CiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgIyMjIFN1cHBseWluZyBhIG1vZGVsCiAgICAgICAgIEFuIG9wdGlvbmFsIGBtb2RlbGAgYXJndW1lbnQgY2FuIGJlIHVzZWQgZm9yIHJvdXRlcyB3aG9zZQogICAgICBwYXRocyBjb250YWluIGR5bmFtaWMgc2VnbWVudHMuIFRoaXMgYXJndW1lbnQgd2lsbCBiZWNvbWUKICAgICAgdGhlIG1vZGVsIGNvbnRleHQgb2YgdGhlIGxpbmtlZCByb3V0ZToKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoInBob3RvR2FsbGVyeSIsIHtwYXRoOiAiaGFtc3Rlci1waG90b3MvOnBob3RvX2lkIn0pOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPExpbmtUbyBAcm91dGU9J3Bob3RvR2FsbGVyeScgQG1vZGVsPXt7dGhpcy5hUGhvdG99fT4KICAgICAgICB7e2FQaG90by50aXRsZX19CiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgYGBgaHRtbAogICAgICA8YSBocmVmPSIvaGFtc3Rlci1waG90b3MvNDIiPgogICAgICAgIFRvbXN0ZXIKICAgICAgPC9hPgogICAgICBgYGAKICAgICAgICAgIyMjIFN1cHBseWluZyBtdWx0aXBsZSBtb2RlbHMKICAgICAgICAgRm9yIGRlZXAtbGlua2luZyB0byByb3V0ZSBwYXRocyB0aGF0IGNvbnRhaW4gbXVsdGlwbGUKICAgICAgZHluYW1pYyBzZWdtZW50cywgdGhlIGBtb2RlbHNgIGFyZ3VtZW50IGNhbiBiZSB1c2VkLgogICAgICAgICBBcyB0aGUgcm91dGVyIHRyYW5zaXRpb25zIHRocm91Z2ggdGhlIHJvdXRlIHBhdGgsIGVhY2gKICAgICAgc3VwcGxpZWQgbW9kZWwgYXJndW1lbnQgd2lsbCBiZWNvbWUgdGhlIGNvbnRleHQgZm9yIHRoZQogICAgICByb3V0ZSB3aXRoIHRoZSBkeW5hbWljIHNlZ21lbnRzOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgicGhvdG9HYWxsZXJ5IiwgeyBwYXRoOiAiaGFtc3Rlci1waG90b3MvOnBob3RvX2lkIiB9LCBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMucm91dGUoImNvbW1lbnQiLCB7cGF0aDogImNvbW1lbnRzLzpjb21tZW50X2lkIn0pOwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIFRoaXMgYXJndW1lbnQgd2lsbCBiZWNvbWUgdGhlIG1vZGVsIGNvbnRleHQgb2YgdGhlIGxpbmtlZCByb3V0ZToKICAgICAgICAgYGBgaGFuZGxlYmFycwogICAgICA8TGlua1RvIEByb3V0ZT0ncGhvdG9HYWxsZXJ5LmNvbW1lbnQnIEBtb2RlbHM9e3thcnJheSB0aGlzLmFQaG90byB0aGlzLmNvbW1lbnR9fT4KICAgICAgICB7e2NvbW1lbnQuYm9keX19CiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgYGBgaHRtbAogICAgICA8YSBocmVmPSIvaGFtc3Rlci1waG90b3MvNDIvY29tbWVudHMvNzE4Ij4KICAgICAgICBBKysrIHdvdWxkIHNudWdnbGUgYWdhaW4uCiAgICAgIDwvYT4KICAgICAgYGBgCiAgICAgICAgICMjIyBTdXBwbHlpbmcgYW4gZXhwbGljaXQgZHluYW1pYyBzZWdtZW50IHZhbHVlCiAgICAgICAgIElmIHlvdSBkb24ndCBoYXZlIGEgbW9kZWwgb2JqZWN0IGF2YWlsYWJsZSB0byBwYXNzIHRvIGBMaW5rVG9gLAogICAgICBhbiBvcHRpb25hbCBzdHJpbmcgb3IgaW50ZWdlciBhcmd1bWVudCBjYW4gYmUgcGFzc2VkIGZvciByb3V0ZXMgd2hvc2UKICAgICAgcGF0aHMgY29udGFpbiBkeW5hbWljIHNlZ21lbnRzLiBUaGlzIGFyZ3VtZW50IHdpbGwgYmVjb21lIHRoZSB2YWx1ZQogICAgICBvZiB0aGUgZHluYW1pYyBzZWdtZW50OgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgicGhvdG9HYWxsZXJ5IiwgeyBwYXRoOiAiaGFtc3Rlci1waG90b3MvOnBob3RvX2lkIiB9KTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIDxMaW5rVG8gQHJvdXRlPSdwaG90b0dhbGxlcnknIEBtb2RlbD17e2FQaG90b0lkfX0+CiAgICAgICAge3t0aGlzLmFQaG90by50aXRsZX19CiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgYGBgaHRtbAogICAgICA8YSBocmVmPSIvaGFtc3Rlci1waG90b3MvNDIiPgogICAgICAgIFRvbXN0ZXIKICAgICAgPC9hPgogICAgICBgYGAKICAgICAgICAgV2hlbiB0cmFuc2l0aW9uaW5nIGludG8gdGhlIGxpbmtlZCByb3V0ZSwgdGhlIGBtb2RlbGAgaG9vayB3aWxsCiAgICAgIGJlIHRyaWdnZXJlZCB3aXRoIHBhcmFtZXRlcnMgaW5jbHVkaW5nIHRoaXMgcGFzc2VkIGlkZW50aWZpZXIuCiAgICAgICAgICMjIyBBbGxvd2luZyBEZWZhdWx0IEFjdGlvbgogICAgICAgICBCeSBkZWZhdWx0IHRoZSBgPExpbmtUbz5gIGNvbXBvbmVudCBwcmV2ZW50cyB0aGUgZGVmYXVsdCBicm93c2VyIGFjdGlvbiBieSBjYWxsaW5nCiAgICAgIGBwcmV2ZW50RGVmYXVsdCgpYCB0byBhdm9pZCByZWxvYWRpbmcgdGhlIGJyb3dzZXIgcGFnZS4KICAgICAgICAgSWYgeW91IG5lZWQgdG8gdHJpZ2dlciBhIGZ1bGwgYnJvd3NlciByZWxvYWQgcGFzcyBgQHByZXZlbnREZWZhdWx0PXt7ZmFsc2V9fWA6CiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPExpbmtUbyBAcm91dGU9J3Bob3RvR2FsbGVyeScgQG1vZGVsPXt7dGhpcy5hUGhvdG9JZH19IEBwcmV2ZW50RGVmYXVsdD17e2ZhbHNlfX0+CiAgICAgICAge3t0aGlzLmFQaG90b0lkLnRpdGxlfX0KICAgICAgPC9MaW5rVG8+CiAgICAgIGBgYAogICAgICAgICAjIyMgU3VwcGx5aW5nIGEgYHRhZ05hbWVgCiAgICAgICAgIEJ5IGRlZmF1bHQgYDxMaW5rVG8+YCByZW5kZXJzIGFuIGA8YT5gIGVsZW1lbnQuIFRoaXMgY2FuIGJlIG92ZXJyaWRkZW4gZm9yIGEgc2luZ2xlIHVzZSBvZgogICAgICBgPExpbmtUbz5gIGJ5IHN1cHBseWluZyBhIGB0YWdOYW1lYCBhcmd1bWVudDoKICAgICAgICAgYGBgaGFuZGxlYmFycwogICAgICA8TGlua1RvIEByb3V0ZT0ncGhvdG9HYWxsZXJ5JyBAdGFnTmFtZT0nbGknPgogICAgICAgIEdyZWF0IEhhbXN0ZXIgUGhvdG9zCiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgVGhpcyBwcm9kdWNlczoKICAgICAgICAgYGBgaHRtbAogICAgICA8bGk+CiAgICAgICAgR3JlYXQgSGFtc3RlciBQaG90b3MKICAgICAgPC9saT4KICAgICAgYGBgCiAgICAgICAgIEluIGdlbmVyYWwsIHRoaXMgaXMgbm90IHJlY29tbWVuZGVkLiBJbnN0ZWFkLCB5b3UgY2FuIHVzZSB0aGUgYHRyYW5zaXRpb24tdG9gIGhlbHBlciB0b2dldGhlcgogICAgICB3aXRoIGEgY2xpY2sgZXZlbnQgaGFuZGxlciBvbiB0aGUgSFRNTCB0YWcgb2YgeW91ciBjaG9vc2luZy4KICAgICAgICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuY29tcG9uZW50cwogICAgICBAbWV0aG9kIExpbmtUbwogICAgICBAc2VlIHtMaW5rQ29tcG9uZW50fQogICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBAbW9kdWxlIEBlbWJlci9yb3V0aW5nCiAgICAqLwoKICAgIC8qKgogICAgICBTZWUgW0VtYmVyLlRlbXBsYXRlcy5jb21wb25lbnRzLkxpbmtUb10oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9FbWJlci5UZW1wbGF0ZXMuY29tcG9uZW50cy9tZXRob2RzL2lucHV0P2FuY2hvcj1MaW5rVG8pLgogICAgICAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICAgIEBtZXRob2QgbGluay10bwogICAgICBAc2VlIHtFbWJlci5UZW1wbGF0ZXMuY29tcG9uZW50cy5MaW5rVG99CiAgICAgIEBwdWJsaWMKICAgICoqLwoKICAgIC8qKgogICAgICBgTGlua0NvbXBvbmVudGAgaXMgdGhlIGludGVybmFsIGNvbXBvbmVudCBpbnZva2VkIHdpdGggYDxMaW5rVG8+YCBvciBge3tsaW5rLXRvfX1gLgogICAgICAgICBAY2xhc3MgTGlua0NvbXBvbmVudAogICAgICBAZXh0ZW5kcyBDb21wb25lbnQKICAgICAgQHNlZSB7RW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMuTGlua1RvfQogICAgICBAcHVibGljCiAgICAqKi8KICAgIHZhciBVTkRFRklORUQgPSBPYmplY3QuZnJlZXplKHsKICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uIHRvU3RyaW5nKCkgewogICAgICAgIHJldHVybiAnVU5ERUZJTkVEJzsKICAgICAgfQogICAgfSk7CiAgICB2YXIgRU1QVFlfUVVFUllfUEFSQU1TID0gT2JqZWN0LmZyZWV6ZSh7fSk7CiAgICBMaW5rQ29tcG9uZW50ID0gQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGxheW91dDogbGF5b3V0JDEsCiAgICAgIHRhZ05hbWU6ICdhJywKCiAgICAgIC8qKgogICAgICAgIEBwcm9wZXJ0eSByb3V0ZQogICAgICAgIEBjYXRlZ29yeSBFTUJFUl9HTElNTUVSX0FOR0xFX0JSQUNLRVRfQlVJTFRfSU5TCiAgICAgICAgQHB1YmxpYwogICAgICAqLwogICAgICByb3V0ZTogVU5ERUZJTkVELAoKICAgICAgLyoqCiAgICAgICAgQHByb3BlcnR5IG1vZGVsCiAgICAgICAgQGNhdGVnb3J5IEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMKICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgIG1vZGVsOiBVTkRFRklORUQsCgogICAgICAvKioKICAgICAgICBAcHJvcGVydHkgbW9kZWxzCiAgICAgICAgQGNhdGVnb3J5IEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMKICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgIG1vZGVsczogVU5ERUZJTkVELAoKICAgICAgLyoqCiAgICAgICAgQHByb3BlcnR5IHF1ZXJ5CiAgICAgICAgQGNhdGVnb3J5IEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMKICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgIHF1ZXJ5OiBVTkRFRklORUQsCgogICAgICAvKioKICAgICAgICBVc2VkIHRvIGRldGVybWluZSB3aGVuIHRoaXMgYExpbmtDb21wb25lbnRgIGlzIGFjdGl2ZS4KICAgICAgICAgICAgIEBwcm9wZXJ0eSBjdXJyZW50LXdoZW4KICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgICdjdXJyZW50LXdoZW4nOiBudWxsLAoKICAgICAgLyoqCiAgICAgICAgU2V0cyB0aGUgYHRpdGxlYCBhdHRyaWJ1dGUgb2YgdGhlIGBMaW5rQ29tcG9uZW50YCdzIEhUTUwgZWxlbWVudC4KICAgICAgICAgICAgIEBwcm9wZXJ0eSB0aXRsZQogICAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgICBAcHVibGljCiAgICAgICoqLwogICAgICB0aXRsZTogbnVsbCwKCiAgICAgIC8qKgogICAgICAgIFNldHMgdGhlIGByZWxgIGF0dHJpYnV0ZSBvZiB0aGUgYExpbmtDb21wb25lbnRgJ3MgSFRNTCBlbGVtZW50LgogICAgICAgICAgICAgQHByb3BlcnR5IHJlbAogICAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgICBAcHVibGljCiAgICAgICoqLwogICAgICByZWw6IG51bGwsCgogICAgICAvKioKICAgICAgICBTZXRzIHRoZSBgdGFiaW5kZXhgIGF0dHJpYnV0ZSBvZiB0aGUgYExpbmtDb21wb25lbnRgJ3MgSFRNTCBlbGVtZW50LgogICAgICAgICAgICAgQHByb3BlcnR5IHRhYmluZGV4CiAgICAgICAgQGRlZmF1bHQgbnVsbAogICAgICAgIEBwdWJsaWMKICAgICAgKiovCiAgICAgIHRhYmluZGV4OiBudWxsLAoKICAgICAgLyoqCiAgICAgICAgU2V0cyB0aGUgYHRhcmdldGAgYXR0cmlidXRlIG9mIHRoZSBgTGlua0NvbXBvbmVudGAncyBIVE1MIGVsZW1lbnQuCiAgICAgICAgICAgICBAc2luY2UgMS44LjAKICAgICAgICBAcHJvcGVydHkgdGFyZ2V0CiAgICAgICAgQGRlZmF1bHQgbnVsbAogICAgICAgIEBwdWJsaWMKICAgICAgKiovCiAgICAgIHRhcmdldDogbnVsbCwKCiAgICAgIC8qKgogICAgICAgIFRoZSBDU1MgY2xhc3MgdG8gYXBwbHkgdG8gYExpbmtDb21wb25lbnRgJ3MgZWxlbWVudCB3aGVuIGl0cyBgYWN0aXZlYAogICAgICAgIHByb3BlcnR5IGlzIGB0cnVlYC4KICAgICAgICAgICAgIEBwcm9wZXJ0eSBhY3RpdmVDbGFzcwogICAgICAgIEB0eXBlIFN0cmluZwogICAgICAgIEBkZWZhdWx0IGFjdGl2ZQogICAgICAgIEBwdWJsaWMKICAgICAgKiovCiAgICAgIGFjdGl2ZUNsYXNzOiAnYWN0aXZlJywKCiAgICAgIC8qKgogICAgICAgIFRoZSBDU1MgY2xhc3MgdG8gYXBwbHkgdG8gYExpbmtDb21wb25lbnRgJ3MgZWxlbWVudCB3aGVuIGl0cyBgbG9hZGluZ2AKICAgICAgICBwcm9wZXJ0eSBpcyBgdHJ1ZWAuCiAgICAgICAgICAgICBAcHJvcGVydHkgbG9hZGluZ0NsYXNzCiAgICAgICAgQHR5cGUgU3RyaW5nCiAgICAgICAgQGRlZmF1bHQgbG9hZGluZwogICAgICAgIEBwcml2YXRlCiAgICAgICoqLwogICAgICBsb2FkaW5nQ2xhc3M6ICdsb2FkaW5nJywKCiAgICAgIC8qKgogICAgICAgIFRoZSBDU1MgY2xhc3MgdG8gYXBwbHkgdG8gYSBgTGlua0NvbXBvbmVudGAncyBlbGVtZW50IHdoZW4gaXRzIGBkaXNhYmxlZGAKICAgICAgICBwcm9wZXJ0eSBpcyBgdHJ1ZWAuCiAgICAgICAgICAgICBAcHJvcGVydHkgZGlzYWJsZWRDbGFzcwogICAgICAgIEB0eXBlIFN0cmluZwogICAgICAgIEBkZWZhdWx0IGRpc2FibGVkCiAgICAgICAgQHByaXZhdGUKICAgICAgKiovCiAgICAgIGRpc2FibGVkQ2xhc3M6ICdkaXNhYmxlZCcsCgogICAgICAvKioKICAgICAgICBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlIGBMaW5rQ29tcG9uZW50YCB3aWxsIHRyaWdnZXIgcm91dGluZyB2aWEKICAgICAgICB0aGUgYHJlcGxhY2VXaXRoYCByb3V0aW5nIHN0cmF0ZWd5LgogICAgICAgICAgICAgQHByb3BlcnR5IHJlcGxhY2UKICAgICAgICBAdHlwZSBCb29sZWFuCiAgICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgICBAcHVibGljCiAgICAgICoqLwogICAgICByZXBsYWNlOiBmYWxzZSwKCiAgICAgIC8qKgogICAgICAgIEJ5IGRlZmF1bHQgdGhpcyBjb21wb25lbnQgd2lsbCBmb3J3YXJkIGBocmVmYCwgYHRpdGxlYCwgYHJlbGAsIGB0YWJpbmRleGAsIGFuZCBgdGFyZ2V0YAogICAgICAgIGFyZ3VtZW50cyB0byBhdHRyaWJ1dGVzIG9uIHRoZSBjb21wb25lbnQncyBlbGVtZW50LiBXaGVuIGludm9rZWQgd2l0aCBge3tsaW5rLXRvfX1gLCB5b3UgY2FuCiAgICAgICAgb25seSBjdXN0b21pemUgdGhlc2UgYXR0cmlidXRlcy4gV2hlbiBpbnZva2VkIHdpdGggYDxMaW5rVG8+YCwgeW91IGNhbiBqdXN0IHVzZSBIVE1MCiAgICAgICAgYXR0cmlidXRlcyBkaXJlY3RseS4KICAgICAgICAgICAgIEBwcm9wZXJ0eSBhdHRyaWJ1dGVCaW5kaW5ncwogICAgICAgIEB0eXBlIEFycmF5IHwgU3RyaW5nCiAgICAgICAgQGRlZmF1bHQgWyd0aXRsZScsICdyZWwnLCAndGFiaW5kZXgnLCAndGFyZ2V0J10KICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ2hyZWYnLCAndGl0bGUnLCAncmVsJywgJ3RhYmluZGV4JywgJ3RhcmdldCddLAoKICAgICAgLyoqCiAgICAgICAgQnkgZGVmYXVsdCB0aGlzIGNvbXBvbmVudCB3aWxsIHNldCBjbGFzc2VzIG9uIGl0cyBlbGVtZW50IHdoZW4gYW55IG9mIHRoZSBmb2xsb3dpbmcgYXJndW1lbnRzCiAgICAgICAgYXJlIHRydXRoeToKICAgICAgICAgICAgICogYWN0aXZlCiAgICAgICAgKiBsb2FkaW5nCiAgICAgICAgKiBkaXNhYmxlZAogICAgICAgICAgICAgV2hlbiB0aGVzZSBhcmd1bWVudHMgYXJlIHRydXRoeSwgYSBjbGFzcyB3aXRoIHRoZSBzYW1lIG5hbWUgd2lsbCBiZSBzZXQgb24gdGhlIGVsZW1lbnQuIFdoZW4KICAgICAgICBmYWxzeSwgdGhlIGFzc29jaWF0ZWQgY2xhc3Mgd2lsbCBub3QgYmUgb24gdGhlIGVsZW1lbnQuCiAgICAgICAgICAgICBAcHJvcGVydHkgY2xhc3NOYW1lQmluZGluZ3MKICAgICAgICBAdHlwZSBBcnJheQogICAgICAgIEBkZWZhdWx0IFsnYWN0aXZlJywgJ2xvYWRpbmcnLCAnZGlzYWJsZWQnLCAnZW1iZXItdHJhbnNpdGlvbmluZy1pbicsICdlbWJlci10cmFuc2l0aW9uaW5nLW91dCddCiAgICAgICAgQHB1YmxpYwogICAgICAqLwogICAgICBjbGFzc05hbWVCaW5kaW5nczogWydhY3RpdmUnLCAnbG9hZGluZycsICdkaXNhYmxlZCcsICd0cmFuc2l0aW9uaW5nSW4nLCAndHJhbnNpdGlvbmluZ091dCddLAoKICAgICAgLyoqCiAgICAgICAgQnkgZGVmYXVsdCB0aGlzIGNvbXBvbmVudCByZXNwb25kcyB0byB0aGUgYGNsaWNrYCBldmVudC4gV2hlbiB0aGUgY29tcG9uZW50IGVsZW1lbnQgaXMgYW4KICAgICAgICBgPGE+YCBlbGVtZW50LCBhY3RpdmF0aW5nIHRoZSBsaW5rIGluIGFub3RoZXIgd2F5LCBzdWNoIGFzIHVzaW5nIHRoZSBrZXlib2FyZCwgdHJpZ2dlcnMgdGhlCiAgICAgICAgY2xpY2sgZXZlbnQuCiAgICAgICAgICAgICBAcHJvcGVydHkgZXZlbnROYW1lCiAgICAgICAgQHR5cGUgU3RyaW5nCiAgICAgICAgQGRlZmF1bHQgY2xpY2sKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBldmVudE5hbWU6ICdjbGljaycsCiAgICAgIC8vIHRoaXMgaXMgZG9jJ2VkIGhlcmUgc28gaXQgc2hvd3MgdXAgaW4gdGhlIGV2ZW50cwogICAgICAvLyBzZWN0aW9uIG9mIHRoZSBBUEkgZG9jdW1lbnRhdGlvbiwgd2hpY2ggaXMgd2hlcmUKICAgICAgLy8gcGVvcGxlIHdpbGwgbGlrZWx5IGdvIGxvb2tpbmcgZm9yIGl0LgoKICAgICAgLyoqCiAgICAgICAgVHJpZ2dlcnMgdGhlIGBMaW5rQ29tcG9uZW50YCdzIHJvdXRpbmcgYmVoYXZpb3IuIElmCiAgICAgICAgYGV2ZW50TmFtZWAgaXMgY2hhbmdlZCB0byBhIHZhbHVlIG90aGVyIHRoYW4gYGNsaWNrYAogICAgICAgIHRoZSByb3V0aW5nIGJlaGF2aW9yIHdpbGwgdHJpZ2dlciBvbiB0aGF0IGN1c3RvbSBldmVudAogICAgICAgIGluc3RlYWQuCiAgICAgICAgICAgICBAZXZlbnQgY2xpY2sKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwoKICAgICAgLyoqCiAgICAgICAgQW4gb3ZlcnJpZGFibGUgbWV0aG9kIGNhbGxlZCB3aGVuIGBMaW5rQ29tcG9uZW50YCBvYmplY3RzIGFyZSBpbnN0YW50aWF0ZWQuCiAgICAgICAgICAgICBFeGFtcGxlOgogICAgICAgICAgICAgYGBgYXBwL2NvbXBvbmVudHMvbXktbGluay5qcwogICAgICAgIGltcG9ydCBMaW5rQ29tcG9uZW50IGZyb20gJ0BlbWJlci9yb3V0aW5nL2xpbmstY29tcG9uZW50JzsKICAgICAgICAgICAgIGV4cG9ydCBkZWZhdWx0IExpbmtDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICAgIGluaXQoKSB7CiAgICAgICAgICAgIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cyk7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdFdmVudCBpcyAnICsgdGhpcy5nZXQoJ2V2ZW50TmFtZScpKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgICBgYGAKICAgICAgICAgICAgIE5PVEU6IElmIHlvdSBkbyBvdmVycmlkZSBgaW5pdGAgZm9yIGEgZnJhbWV3b3JrIGNsYXNzIGxpa2UgYENvbXBvbmVudGAsCiAgICAgICAgYmUgc3VyZSB0byBjYWxsIGB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpYCBpbiB5b3VyCiAgICAgICAgYGluaXRgIGRlY2xhcmF0aW9uISBJZiB5b3UgZG9uJ3QsIEVtYmVyIG1heSBub3QgaGF2ZSBhbiBvcHBvcnR1bml0eSB0bwogICAgICAgIGRvIGltcG9ydGFudCBzZXR1cCB3b3JrLCBhbmQgeW91J2xsIHNlZSBzdHJhbmdlIGJlaGF2aW9yIGluIHlvdXIKICAgICAgICBhcHBsaWNhdGlvbi4KICAgICAgICAgICAgIEBtZXRob2QgaW5pdAogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsgLy8gTWFwIGRlc2lyZWQgZXZlbnQgbmFtZSB0byBpbnZva2UgZnVuY3Rpb24KCgogICAgICAgIHZhciBldmVudE5hbWUgPSB0aGlzLmV2ZW50TmFtZTsKICAgICAgICB0aGlzLm9uKGV2ZW50TmFtZSwgdGhpcywgdGhpcy5faW52b2tlKTsKICAgICAgfSwKICAgICAgX3JvdXRpbmc6ICgwLCBfc2VydmljZS5pbmplY3QpKCctcm91dGluZycpLAogICAgICBfY3VycmVudFJvdXRlOiAoMCwgX21ldGFsLmFsaWFzKSgnX3JvdXRpbmcuY3VycmVudFJvdXRlTmFtZScpLAogICAgICBfY3VycmVudFJvdXRlclN0YXRlOiAoMCwgX21ldGFsLmFsaWFzKSgnX3JvdXRpbmcuY3VycmVudFN0YXRlJyksCiAgICAgIF90YXJnZXRSb3V0ZXJTdGF0ZTogKDAsIF9tZXRhbC5hbGlhcykoJ19yb3V0aW5nLnRhcmdldFN0YXRlJyksCiAgICAgIF9yb3V0ZTogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ3JvdXRlJywgJ19jdXJyZW50Um91dGVyU3RhdGUnLCBmdW5jdGlvbiBjb21wdXRlTGlua1RvQ29tcG9uZW50Um91dGUoKSB7CiAgICAgICAgdmFyIHJvdXRlID0gdGhpcy5yb3V0ZTsKICAgICAgICByZXR1cm4gcm91dGUgPT09IFVOREVGSU5FRCA/IHRoaXMuX2N1cnJlbnRSb3V0ZSA6IHJvdXRlOwogICAgICB9KSwKICAgICAgX21vZGVsczogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ21vZGVsJywgJ21vZGVscycsIGZ1bmN0aW9uIGNvbXB1dGVMaW5rVG9Db21wb25lbnRNb2RlbHMoKSB7CiAgICAgICAgdmFyIG1vZGVsID0gdGhpcy5tb2RlbCwKICAgICAgICAgICAgbW9kZWxzID0gdGhpcy5tb2RlbHM7CiAgICAgICAgKGZhbHNlICYmICEobW9kZWwgPT09IFVOREVGSU5FRCB8fCBtb2RlbHMgPT09IFVOREVGSU5FRCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgY2Fubm90IHByb3ZpZGUgYm90aCB0aGUgYEBtb2RlbGAgYW5kIGBAbW9kZWxzYCBhcmd1bWVudHMgdG8gdGhlIDxMaW5rVG8+IGNvbXBvbmVudC4nLCBtb2RlbCA9PT0gVU5ERUZJTkVEIHx8IG1vZGVscyA9PT0gVU5ERUZJTkVEKSk7CgogICAgICAgIGlmIChtb2RlbCAhPT0gVU5ERUZJTkVEKSB7CiAgICAgICAgICByZXR1cm4gW21vZGVsXTsKICAgICAgICB9IGVsc2UgaWYgKG1vZGVscyAhPT0gVU5ERUZJTkVEKSB7CiAgICAgICAgICAoZmFsc2UgJiYgIShBcnJheS5pc0FycmF5KG1vZGVscykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnVGhlIGBAbW9kZWxzYCBhcmd1bWVudCBtdXN0IGJlIGFuIGFycmF5LicsIEFycmF5LmlzQXJyYXkobW9kZWxzKSkpOwogICAgICAgICAgcmV0dXJuIG1vZGVsczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIFtdOwogICAgICAgIH0KICAgICAgfSksCiAgICAgIF9xdWVyeTogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ3F1ZXJ5JywgZnVuY3Rpb24gY29tcHV0ZUxpbmtUb0NvbXBvbmVudFF1ZXJ5KCkgewogICAgICAgIHZhciBxdWVyeSA9IHRoaXMucXVlcnk7CgogICAgICAgIGlmIChxdWVyeSA9PT0gVU5ERUZJTkVEKSB7CiAgICAgICAgICByZXR1cm4gRU1QVFlfUVVFUllfUEFSQU1TOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgcXVlcnkpOwogICAgICAgIH0KICAgICAgfSksCgogICAgICAvKioKICAgICAgICBBY2Nlc3NlZCBhcyBhIGNsYXNzbmFtZSBiaW5kaW5nIHRvIGFwcGx5IHRoZSBjb21wb25lbnQncyBgZGlzYWJsZWRDbGFzc2AKICAgICAgICBDU1MgYGNsYXNzYCB0byB0aGUgZWxlbWVudCB3aGVuIHRoZSBsaW5rIGlzIGRpc2FibGVkLgogICAgICAgICAgICAgV2hlbiBgdHJ1ZWAsIGludGVyYWN0aW9ucyB3aXRoIHRoZSBlbGVtZW50IHdpbGwgbm90IHRyaWdnZXIgcm91dGUgY2hhbmdlcy4KICAgICAgICBAcHJvcGVydHkgZGlzYWJsZWQKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBkaXNhYmxlZDogKDAsIF9tZXRhbC5jb21wdXRlZCkoewogICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KF9rZXkpIHsKICAgICAgICAgIC8vIGFsd2F5cyByZXR1cm5zIGZhbHNlIGZvciBgZ2V0YCBiZWNhdXNlIChkdWUgdG8gdGhlIGBzZXRgIGp1c3QgYmVsb3cpCiAgICAgICAgICAvLyB0aGUgY2FjaGVkIHJldHVybiB2YWx1ZSBmcm9tIHRoZSBzZXQgd2lsbCBwcmV2ZW50IHRoaXMgZ2V0dGVyIGZyb20gX2V2ZXJfCiAgICAgICAgICAvLyBiZWluZyBjYWxsZWQgYWZ0ZXIgYSBzZXQgaGFzIG9jY3VyZWQKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9LAogICAgICAgIHNldDogZnVuY3Rpb24gc2V0KF9rZXksIHZhbHVlJCQxKSB7CiAgICAgICAgICB0aGlzLl9pc0Rpc2FibGVkID0gdmFsdWUkJDE7CiAgICAgICAgICByZXR1cm4gdmFsdWUkJDEgPyB0aGlzLmRpc2FibGVkQ2xhc3MgOiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0pLAoKICAgICAgLyoqCiAgICAgICAgQWNjZXNzZWQgYXMgYSBjbGFzc25hbWUgYmluZGluZyB0byBhcHBseSB0aGUgY29tcG9uZW50J3MgYGFjdGl2ZUNsYXNzYAogICAgICAgIENTUyBgY2xhc3NgIHRvIHRoZSBlbGVtZW50IHdoZW4gdGhlIGxpbmsgaXMgYWN0aXZlLgogICAgICAgICAgICAgVGhpcyBjb21wb25lbnQgaXMgY29uc2lkZXJlZCBhY3RpdmUgd2hlbiBpdHMgYGN1cnJlbnRXaGVuYCBwcm9wZXJ0eSBpcyBgdHJ1ZWAKICAgICAgICBvciB0aGUgYXBwbGljYXRpb24ncyBjdXJyZW50IHJvdXRlIGlzIHRoZSByb3V0ZSB0aGlzIGNvbXBvbmVudCB3b3VsZCB0cmlnZ2VyCiAgICAgICAgdHJhbnNpdGlvbnMgaW50by4KICAgICAgICAgICAgIFRoZSBgY3VycmVudFdoZW5gIHByb3BlcnR5IGNhbiBtYXRjaCBhZ2FpbnN0IG11bHRpcGxlIHJvdXRlcyBieSBzZXBhcmF0aW5nCiAgICAgICAgcm91dGUgbmFtZXMgdXNpbmcgdGhlIGAgYCAoc3BhY2UpIGNoYXJhY3Rlci4KICAgICAgICAgICAgIEBwcm9wZXJ0eSBhY3RpdmUKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBhY3RpdmU6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKCdhY3RpdmVDbGFzcycsICdfYWN0aXZlJywgZnVuY3Rpb24gY29tcHV0ZUxpbmtUb0NvbXBvbmVudEFjdGl2ZUNsYXNzKCkgewogICAgICAgIHJldHVybiB0aGlzLl9hY3RpdmUgPyB0aGlzLmFjdGl2ZUNsYXNzIDogZmFsc2U7CiAgICAgIH0pLAogICAgICBfYWN0aXZlOiAoMCwgX21ldGFsLmNvbXB1dGVkKSgnX2N1cnJlbnRSb3V0ZXJTdGF0ZScsICdfcm91dGUnLCAnX21vZGVscycsICdfcXVlcnknLCAnbG9hZGluZycsICdjdXJyZW50LXdoZW4nLCBmdW5jdGlvbiBjb21wdXRlTGlua1RvQ29tcG9uZW50QWN0aXZlKCkgewogICAgICAgIHZhciBzdGF0ZSA9IHRoaXMuX2N1cnJlbnRSb3V0ZXJTdGF0ZTsKCiAgICAgICAgaWYgKHN0YXRlKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5faXNBY3RpdmUoc3RhdGUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9KSwKICAgICAgd2lsbEJlQWN0aXZlOiAoMCwgX21ldGFsLmNvbXB1dGVkKSgnX2N1cnJlbnRSb3V0ZXJTdGF0ZScsICdfdGFyZ2V0Um91dGVyU3RhdGUnLCAnX3JvdXRlJywgJ19tb2RlbHMnLCAnX3F1ZXJ5JywgJ2xvYWRpbmcnLCAnY3VycmVudC13aGVuJywgZnVuY3Rpb24gY29tcHV0ZUxpbmtUb0NvbXBvbmVudFdpbGxCZUFjdGl2ZSgpIHsKICAgICAgICB2YXIgY3VycmVudCA9IHRoaXMuX2N1cnJlbnRSb3V0ZXJTdGF0ZSwKICAgICAgICAgICAgdGFyZ2V0ID0gdGhpcy5fdGFyZ2V0Um91dGVyU3RhdGU7CgogICAgICAgIGlmIChjdXJyZW50ID09PSB0YXJnZXQpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9pc0FjdGl2ZSh0YXJnZXQpOwogICAgICB9KSwKICAgICAgX2lzQWN0aXZlOiBmdW5jdGlvbiBfaXNBY3RpdmUocm91dGVyU3RhdGUpIHsKICAgICAgICBpZiAodGhpcy5sb2FkaW5nKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICB2YXIgY3VycmVudFdoZW4gPSB0aGlzWydjdXJyZW50LXdoZW4nXTsKCiAgICAgICAgaWYgKHR5cGVvZiBjdXJyZW50V2hlbiA9PT0gJ2Jvb2xlYW4nKSB7CiAgICAgICAgICByZXR1cm4gY3VycmVudFdoZW47CiAgICAgICAgfQoKICAgICAgICB2YXIgaXNDdXJyZW50V2hlblNwZWNpZmllZCA9IEJvb2xlYW4oY3VycmVudFdoZW4pOwoKICAgICAgICBpZiAoaXNDdXJyZW50V2hlblNwZWNpZmllZCkgewogICAgICAgICAgY3VycmVudFdoZW4gPSBjdXJyZW50V2hlbi5zcGxpdCgnICcpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjdXJyZW50V2hlbiA9IFt0aGlzLl9yb3V0ZV07CiAgICAgICAgfQoKICAgICAgICB2YXIgbW9kZWxzID0gdGhpcy5fbW9kZWxzLAogICAgICAgICAgICBxdWVyeSA9IHRoaXMuX3F1ZXJ5LAogICAgICAgICAgICByb3V0aW5nID0gdGhpcy5fcm91dGluZzsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjdXJyZW50V2hlbi5sZW5ndGg7IGkrKykgewogICAgICAgICAgaWYgKHJvdXRpbmcuaXNBY3RpdmVGb3JSb3V0ZShtb2RlbHMsIHF1ZXJ5LCBjdXJyZW50V2hlbltpXSwgcm91dGVyU3RhdGUsIGlzQ3VycmVudFdoZW5TcGVjaWZpZWQpKSB7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9LAogICAgICB0cmFuc2l0aW9uaW5nSW46ICgwLCBfbWV0YWwuY29tcHV0ZWQpKCdfYWN0aXZlJywgJ3dpbGxCZUFjdGl2ZScsIGZ1bmN0aW9uIGNvbXB1dGVMaW5rVG9Db21wb25lbnRUcmFuc2l0aW9uaW5nSW4oKSB7CiAgICAgICAgaWYgKHRoaXMud2lsbEJlQWN0aXZlID09PSB0cnVlICYmICF0aGlzLl9hY3RpdmUpIHsKICAgICAgICAgIHJldHVybiAnZW1iZXItdHJhbnNpdGlvbmluZy1pbic7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0pLAogICAgICB0cmFuc2l0aW9uaW5nT3V0OiAoMCwgX21ldGFsLmNvbXB1dGVkKSgnX2FjdGl2ZScsICd3aWxsQmVBY3RpdmUnLCBmdW5jdGlvbiBjb21wdXRlTGlua1RvQ29tcG9uZW50VHJhbnNpdGlvbmluZ091dCgpIHsKICAgICAgICBpZiAodGhpcy53aWxsQmVBY3RpdmUgPT09IGZhbHNlICYmIHRoaXMuX2FjdGl2ZSkgewogICAgICAgICAgcmV0dXJuICdlbWJlci10cmFuc2l0aW9uaW5nLW91dCc7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0pLAoKICAgICAgLyoqCiAgICAgICAgRXZlbnQgaGFuZGxlciB0aGF0IGludm9rZXMgdGhlIGxpbmssIGFjdGl2YXRpbmcgdGhlIGFzc29jaWF0ZWQgcm91dGUuCiAgICAgICAgICAgICBAbWV0aG9kIF9pbnZva2UKICAgICAgICBAcGFyYW0ge0V2ZW50fSBldmVudAogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIF9pbnZva2U6IGZ1bmN0aW9uIF9pbnZva2UoZXZlbnQpIHsKICAgICAgICBpZiAoISgwLCBfdmlld3MuaXNTaW1wbGVDbGljaykoZXZlbnQpKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CgogICAgICAgIHZhciBidWJibGVzID0gdGhpcy5idWJibGVzLAogICAgICAgICAgICBwcmV2ZW50RGVmYXVsdCA9IHRoaXMucHJldmVudERlZmF1bHQ7CiAgICAgICAgdmFyIHRhcmdldCA9IHRoaXMuZWxlbWVudC50YXJnZXQ7CiAgICAgICAgdmFyIGlzU2VsZiA9ICF0YXJnZXQgfHwgdGFyZ2V0ID09PSAnX3NlbGYnOwoKICAgICAgICBpZiAocHJldmVudERlZmF1bHQgIT09IGZhbHNlICYmIGlzU2VsZikgewogICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsKICAgICAgICB9CgogICAgICAgIGlmIChidWJibGVzID09PSBmYWxzZSkgewogICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7CiAgICAgICAgfQoKICAgICAgICBpZiAodGhpcy5faXNEaXNhYmxlZCkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgaWYgKHRoaXMubG9hZGluZykgewogICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aAogICAgICAgICAgKGZhbHNlICYmICgwLCBfZGVidWcud2FybikoJ1RoaXMgbGluayBpcyBpbiBhbiBpbmFjdGl2ZSBsb2FkaW5nIHN0YXRlIGJlY2F1c2UgYXQgbGVhc3Qgb25lIG9mIGl0cyBtb2RlbHMgJyArICdjdXJyZW50bHkgaGFzIGEgbnVsbC91bmRlZmluZWQgdmFsdWUsIG9yIHRoZSBwcm92aWRlZCByb3V0ZSBuYW1lIGlzIGludmFsaWQuJywgZmFsc2UsIHsKICAgICAgICAgICAgaWQ6ICdlbWJlci1nbGltbWVyLmxpbmstdG8uaW5hY3RpdmUtbG9hZGluZy1zdGF0ZScKICAgICAgICAgIH0pKTsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CgogICAgICAgIGlmICghaXNTZWxmKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICB2YXIgcm91dGVOYW1lID0gdGhpcy5fcm91dGUsCiAgICAgICAgICAgIG1vZGVscyA9IHRoaXMuX21vZGVscywKICAgICAgICAgICAgcXVlcnlQYXJhbXMgPSB0aGlzLl9xdWVyeSwKICAgICAgICAgICAgc2hvdWxkUmVwbGFjZSA9IHRoaXMucmVwbGFjZTsKICAgICAgICB2YXIgcGF5bG9hZCA9IHsKICAgICAgICAgIHF1ZXJ5UGFyYW1zOiBxdWVyeVBhcmFtcywKICAgICAgICAgIHJvdXRlTmFtZTogcm91dGVOYW1lCiAgICAgICAgfTsKICAgICAgICAoMCwgX2luc3RydW1lbnRhdGlvbi5mbGFnZ2VkSW5zdHJ1bWVudCkoJ2ludGVyYWN0aW9uLmxpbmstdG8nLCBwYXlsb2FkLCB0aGlzLl9nZW5lcmF0ZVRyYW5zaXRpb24ocGF5bG9hZCwgcm91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zLCBzaG91bGRSZXBsYWNlKSk7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9LAogICAgICBfZ2VuZXJhdGVUcmFuc2l0aW9uOiBmdW5jdGlvbiBfZ2VuZXJhdGVUcmFuc2l0aW9uKHBheWxvYWQsIHF1YWxpZmllZFJvdXRlTmFtZSwgbW9kZWxzLCBxdWVyeVBhcmFtcywgc2hvdWxkUmVwbGFjZSkgewogICAgICAgIHZhciByb3V0aW5nID0gdGhpcy5fcm91dGluZzsKICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgICAgcGF5bG9hZC50cmFuc2l0aW9uID0gcm91dGluZy50cmFuc2l0aW9uVG8ocXVhbGlmaWVkUm91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zLCBzaG91bGRSZXBsYWNlKTsKICAgICAgICB9OwogICAgICB9LAoKICAgICAgLyoqCiAgICAgICAgU2V0cyB0aGUgZWxlbWVudCdzIGBocmVmYCBhdHRyaWJ1dGUgdG8gdGhlIHVybCBmb3IKICAgICAgICB0aGUgYExpbmtDb21wb25lbnRgJ3MgdGFyZ2V0ZWQgcm91dGUuCiAgICAgICAgICAgICBJZiB0aGUgYExpbmtDb21wb25lbnRgJ3MgYHRhZ05hbWVgIGlzIGNoYW5nZWQgdG8gYSB2YWx1ZSBvdGhlcgogICAgICAgIHRoYW4gYGFgLCB0aGlzIHByb3BlcnR5IHdpbGwgYmUgaWdub3JlZC4KICAgICAgICAgICAgIEBwcm9wZXJ0eSBocmVmCiAgICAgICAgQHByaXZhdGUKICAgICAgKi8KICAgICAgaHJlZjogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ19jdXJyZW50Um91dGVyU3RhdGUnLCAnX3JvdXRlJywgJ19tb2RlbHMnLCAnX3F1ZXJ5JywgJ3RhZ05hbWUnLCAnbG9hZGluZycsICdsb2FkaW5nSHJlZicsIGZ1bmN0aW9uIGNvbXB1dGVMaW5rVG9Db21wb25lbnRIcmVmKCkgewogICAgICAgIGlmICh0aGlzLnRhZ05hbWUgIT09ICdhJykgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgaWYgKHRoaXMubG9hZGluZykgewogICAgICAgICAgcmV0dXJuIHRoaXMubG9hZGluZ0hyZWY7CiAgICAgICAgfQoKICAgICAgICB2YXIgcm91dGUgPSB0aGlzLl9yb3V0ZSwKICAgICAgICAgICAgbW9kZWxzID0gdGhpcy5fbW9kZWxzLAogICAgICAgICAgICBxdWVyeSA9IHRoaXMuX3F1ZXJ5LAogICAgICAgICAgICByb3V0aW5nID0gdGhpcy5fcm91dGluZzsKCiAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgIC8qCiAgICAgICAgICAgKiBVbmZvcnR1bmF0ZWx5LCB0byBnZXQgZGVjZW50IGVycm9yIG1lc3NhZ2VzLCB3ZSBuZWVkIHRvIGRvIHRoaXMuCiAgICAgICAgICAgKiBJbiBzb21lIGZ1dHVyZSBzdGF0ZSB3ZSBzaG91bGQgYmUgYWJsZSB0byB1c2UgYSAiZmVhdHVyZSBmbGFnIgogICAgICAgICAgICogd2hpY2ggYWxsb3dzIHVzIHRvIHN0cmlwIHRoaXMgd2l0aG91dCBuZWVkaW5nIHRvIGNhbGwgaXQgdHdpY2UuCiAgICAgICAgICAgKgogICAgICAgICAgICogaWYgKGlzRGVidWdCdWlsZCgpKSB7CiAgICAgICAgICAgKiAgIC8vIERvIHRoZSB1c2VmdWwgZGVidWcgdGhpbmcsIHByb2JhYmx5IGluY2x1ZGluZyB0cnkvY2F0Y2guCiAgICAgICAgICAgKiB9IGVsc2UgewogICAgICAgICAgICogICAvLyBEbyB0aGUgcGVyZm9ybWFudCB0aGluZy4KICAgICAgICAgICAqIH0KICAgICAgICAgICAqLwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcmV0dXJuIHJvdXRpbmcuZ2VuZXJhdGVVUkwocm91dGUsIG1vZGVscywgcXVlcnkpOwogICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoCiAgICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBhdHRlbXB0ZWQgdG8gZ2VuZXJhdGUgYSBsaW5rIGZvciB0aGUgXCIiICsgdGhpcy5yb3V0ZSArICJcIiByb3V0ZSwgYnV0IGRpZCBub3QgIiArICJwYXNzIHRoZSBtb2RlbHMgcmVxdWlyZWQgZm9yIGdlbmVyYXRpbmcgaXRzIGR5bmFtaWMgc2VnbWVudHMuICIgKyBlLm1lc3NhZ2UpKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJvdXRpbmcuZ2VuZXJhdGVVUkwocm91dGUsIG1vZGVscywgcXVlcnkpOwogICAgICAgIH0KICAgICAgfSksCiAgICAgIGxvYWRpbmc6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKCdfcm91dGUnLCAnX21vZGVsc0FyZUxvYWRlZCcsICdsb2FkaW5nQ2xhc3MnLCBmdW5jdGlvbiBjb21wdXRlTGlua1RvQ29tcG9uZW50TG9hZGluZygpIHsKICAgICAgICB2YXIgcm91dGUgPSB0aGlzLl9yb3V0ZSwKICAgICAgICAgICAgbG9hZGVkID0gdGhpcy5fbW9kZWxzQXJlTG9hZGVkOwoKICAgICAgICBpZiAoIWxvYWRlZCB8fCByb3V0ZSA9PT0gbnVsbCB8fCByb3V0ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5sb2FkaW5nQ2xhc3M7CiAgICAgICAgfQogICAgICB9KSwKICAgICAgX21vZGVsc0FyZUxvYWRlZDogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ19tb2RlbHMnLCBmdW5jdGlvbiBjb21wdXRlTGlua1RvQ29tcG9uZW50TW9kZWxzQXJlTG9hZGVkKCkgewogICAgICAgIHZhciBtb2RlbHMgPSB0aGlzLl9tb2RlbHM7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW9kZWxzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICB2YXIgbW9kZWwgPSBtb2RlbHNbaV07CgogICAgICAgICAgaWYgKG1vZGVsID09PSBudWxsIHx8IG1vZGVsID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0pLAoKICAgICAgLyoqCiAgICAgICAgVGhlIGRlZmF1bHQgaHJlZiB2YWx1ZSB0byB1c2Ugd2hpbGUgYSBsaW5rLXRvIGlzIGxvYWRpbmcuCiAgICAgICAgT25seSBhcHBsaWVzIHdoZW4gdGFnTmFtZSBpcyAnYScKICAgICAgICAgICAgIEBwcm9wZXJ0eSBsb2FkaW5nSHJlZgogICAgICAgIEB0eXBlIFN0cmluZwogICAgICAgIEBkZWZhdWx0ICMKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBsb2FkaW5nSHJlZjogJyMnLAogICAgICBkaWRSZWNlaXZlQXR0cnM6IGZ1bmN0aW9uIGRpZFJlY2VpdmVBdHRycygpIHsKICAgICAgICB2YXIgZGlzYWJsZWRXaGVuID0gdGhpcy5kaXNhYmxlZFdoZW47CgogICAgICAgIGlmIChkaXNhYmxlZFdoZW4gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdGhpcy5zZXQoJ2Rpc2FibGVkJywgZGlzYWJsZWRXaGVuKTsKICAgICAgICB9CgogICAgICAgIHZhciBwYXJhbXMgPSB0aGlzLnBhcmFtczsKCiAgICAgICAgaWYgKCFwYXJhbXMgfHwgcGFyYW1zLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgKGZhbHNlICYmICEoISh0aGlzLnJvdXRlID09PSBVTkRFRklORUQgJiYgdGhpcy5tb2RlbCA9PT0gVU5ERUZJTkVEICYmIHRoaXMubW9kZWxzID09PSBVTkRFRklORUQgJiYgdGhpcy5xdWVyeSA9PT0gVU5ERUZJTkVEKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgbXVzdCBwcm92aWRlIGF0IGxlYXN0IG9uZSBvZiB0aGUgYEByb3V0ZWAsIGBAbW9kZWxgLCBgQG1vZGVsc2Agb3IgYEBxdWVyeWAgYXJndW1lbnQgdG8gYDxMaW5rVG8+YC4nLCAhKHRoaXMucm91dGUgPT09IFVOREVGSU5FRCAmJiB0aGlzLm1vZGVsID09PSBVTkRFRklORUQgJiYgdGhpcy5tb2RlbHMgPT09IFVOREVGSU5FRCAmJiB0aGlzLnF1ZXJ5ID09PSBVTkRFRklORUQpKSk7CgogICAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICAgJiYgdGhpcy5xdWVyeSA9PT0gVU5ERUZJTkVEKSB7CiAgICAgICAgICAgIHZhciBtb2RlbHMgPSB0aGlzLl9tb2RlbHM7CiAgICAgICAgICAgIHZhciBsYXN0TW9kZWwgPSBtb2RlbHMubGVuZ3RoID4gMCAmJiBtb2RlbHNbbW9kZWxzLmxlbmd0aCAtIDFdOwogICAgICAgICAgICAoZmFsc2UgJiYgISghKGxhc3RNb2RlbCAmJiBsYXN0TW9kZWwuaXNRdWVyeVBhcmFtcykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnVGhlIGAocXVlcnktcGFyYW1zKWAgaGVscGVyIGNhbiBvbmx5IGJlIHVzZWQgd2hlbiBpbnZva2luZyB0aGUgYHt7bGluay10b319YCBjb21wb25lbnQuJywgIShsYXN0TW9kZWwgJiYgbGFzdE1vZGVsLmlzUXVlcnlQYXJhbXMpKSk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgcGFyYW1zID0gcGFyYW1zLnNsaWNlKCk7IC8vIFByb2Nlc3MgdGhlIHBvc2l0aW9uYWwgYXJndW1lbnRzLCBpbiBvcmRlci4KICAgICAgICAvLyAxLiBJbmxpbmUgbGluayB0aXRsZSBjb21lcyBmaXJzdCwgaWYgcHJlc2VudC4KCiAgICAgICAgaWYgKCF0aGlzW0hBU19CTE9DS10pIHsKICAgICAgICAgIHRoaXMuc2V0KCdsaW5rVGl0bGUnLCBwYXJhbXMuc2hpZnQoKSk7CiAgICAgICAgfSAvLyAyLiBUaGUgbGFzdCBhcmd1bWVudCBpcyBwb3NzaWJseSB0aGUgYHF1ZXJ5YCBvYmplY3QuCgoKICAgICAgICB2YXIgcXVlcnlQYXJhbXMgPSBwYXJhbXNbcGFyYW1zLmxlbmd0aCAtIDFdOwoKICAgICAgICBpZiAocXVlcnlQYXJhbXMgJiYgcXVlcnlQYXJhbXMuaXNRdWVyeVBhcmFtcykgewogICAgICAgICAgdGhpcy5zZXQoJ3F1ZXJ5JywgcGFyYW1zLnBvcCgpLnZhbHVlcyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuc2V0KCdxdWVyeScsIFVOREVGSU5FRCk7CiAgICAgICAgfSAvLyAzLiBJZiB0aGVyZSBpcyBhIGByb3V0ZWAsIGl0IGlzIG5vdyBhdCBpbmRleCAwLgoKCiAgICAgICAgaWYgKHBhcmFtcy5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHRoaXMuc2V0KCdyb3V0ZScsIFVOREVGSU5FRCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuc2V0KCdyb3V0ZScsIHBhcmFtcy5zaGlmdCgpKTsKICAgICAgICB9IC8vIDQuIEFueSByZW1haW5pbmcgaW5kaWNlcyAoaWYgYW55KSBhcmUgYG1vZGVsc2AuCgoKICAgICAgICB0aGlzLnNldCgnbW9kZWwnLCBVTkRFRklORUQpOwogICAgICAgIHRoaXMuc2V0KCdtb2RlbHMnLCBwYXJhbXMpOwogICAgICB9CiAgICB9KTsKCiAgICBMaW5rQ29tcG9uZW50LnRvU3RyaW5nID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gJ0BlbWJlci9yb3V0aW5nL2xpbmstY29tcG9uZW50JzsKICAgIH07CgogICAgTGlua0NvbXBvbmVudC5yZW9wZW5DbGFzcyh7CiAgICAgIHBvc2l0aW9uYWxQYXJhbXM6ICdwYXJhbXMnCiAgICB9KTsKICB9CiAgdmFyIExpbmtUb0NvbXBvbmVudCA9IExpbmtDb21wb25lbnQ7IC8vIEB0cy1jaGVjawoKICBfZXhwb3J0cy5MaW5rQ29tcG9uZW50ID0gTGlua1RvQ29tcG9uZW50OwogIHZhciBEZWJ1Z1N0YWNrOwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgdmFyIEVsZW1lbnQgPSBmdW5jdGlvbiBFbGVtZW50KG5hbWUpIHsKICAgICAgdGhpcy5uYW1lID0gbmFtZTsKICAgIH07CgogICAgdmFyIFRlbXBsYXRlRWxlbWVudCA9CiAgICAvKiNfX1BVUkVfXyovCiAgICBmdW5jdGlvbiAoX0VsZW1lbnQpIHsKICAgICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFRlbXBsYXRlRWxlbWVudCwgX0VsZW1lbnQpOwoKICAgICAgZnVuY3Rpb24gVGVtcGxhdGVFbGVtZW50KCkgewogICAgICAgIHJldHVybiBfRWxlbWVudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICAgIH0KCiAgICAgIHJldHVybiBUZW1wbGF0ZUVsZW1lbnQ7CiAgICB9KEVsZW1lbnQpOwoKICAgIHZhciBFbmdpbmVFbGVtZW50ID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uIChfRWxlbWVudDIpIHsKICAgICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEVuZ2luZUVsZW1lbnQsIF9FbGVtZW50Mik7CgogICAgICBmdW5jdGlvbiBFbmdpbmVFbGVtZW50KCkgewogICAgICAgIHJldHVybiBfRWxlbWVudDIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICB9CgogICAgICByZXR1cm4gRW5naW5lRWxlbWVudDsKICAgIH0oRWxlbWVudCk7IC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1zaGFkb3dlZC12YXJpYWJsZQoKCiAgICBEZWJ1Z1N0YWNrID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uICgpIHsKICAgICAgZnVuY3Rpb24gRGVidWdTdGFjaygpIHsKICAgICAgICB0aGlzLl9zdGFjayA9IFtdOwogICAgICB9CgogICAgICB2YXIgX3Byb3RvMTYgPSBEZWJ1Z1N0YWNrLnByb3RvdHlwZTsKCiAgICAgIF9wcm90bzE2LnB1c2ggPSBmdW5jdGlvbiBwdXNoKG5hbWUpIHsKICAgICAgICB0aGlzLl9zdGFjay5wdXNoKG5ldyBUZW1wbGF0ZUVsZW1lbnQobmFtZSkpOwogICAgICB9OwoKICAgICAgX3Byb3RvMTYucHVzaEVuZ2luZSA9IGZ1bmN0aW9uIHB1c2hFbmdpbmUobmFtZSkgewogICAgICAgIHRoaXMuX3N0YWNrLnB1c2gobmV3IEVuZ2luZUVsZW1lbnQobmFtZSkpOwogICAgICB9OwoKICAgICAgX3Byb3RvMTYucG9wID0gZnVuY3Rpb24gcG9wKCkgewogICAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5fc3RhY2sucG9wKCk7CgogICAgICAgIGlmIChlbGVtZW50KSB7CiAgICAgICAgICByZXR1cm4gZWxlbWVudC5uYW1lOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIF9wcm90bzE2LnBlZWsgPSBmdW5jdGlvbiBwZWVrKCkgewogICAgICAgIHZhciB0ZW1wbGF0ZSA9IHRoaXMuX2N1cnJlbnRUZW1wbGF0ZSgpOwoKICAgICAgICB2YXIgZW5naW5lID0gdGhpcy5fY3VycmVudEVuZ2luZSgpOwoKICAgICAgICBpZiAoZW5naW5lKSB7CiAgICAgICAgICByZXR1cm4gIlwiIiArIHRlbXBsYXRlICsgIlwiIChpbiBcIiIgKyBlbmdpbmUgKyAiXCIpIjsKICAgICAgICB9IGVsc2UgaWYgKHRlbXBsYXRlKSB7CiAgICAgICAgICByZXR1cm4gIlwiIiArIHRlbXBsYXRlICsgIlwiIjsKICAgICAgICB9CiAgICAgIH07CgogICAgICBfcHJvdG8xNi5fY3VycmVudFRlbXBsYXRlID0gZnVuY3Rpb24gX2N1cnJlbnRUZW1wbGF0ZSgpIHsKICAgICAgICByZXR1cm4gdGhpcy5fZ2V0Q3VycmVudEJ5VHlwZShUZW1wbGF0ZUVsZW1lbnQpOwogICAgICB9OwoKICAgICAgX3Byb3RvMTYuX2N1cnJlbnRFbmdpbmUgPSBmdW5jdGlvbiBfY3VycmVudEVuZ2luZSgpIHsKICAgICAgICByZXR1cm4gdGhpcy5fZ2V0Q3VycmVudEJ5VHlwZShFbmdpbmVFbGVtZW50KTsKICAgICAgfTsKCiAgICAgIF9wcm90bzE2Ll9nZXRDdXJyZW50QnlUeXBlID0gZnVuY3Rpb24gX2dldEN1cnJlbnRCeVR5cGUodHlwZSkgewogICAgICAgIGZvciAodmFyIGkgPSB0aGlzLl9zdGFjay5sZW5ndGg7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgICB2YXIgZWxlbWVudCA9IHRoaXMuX3N0YWNrW2ldOwoKICAgICAgICAgIGlmIChlbGVtZW50IGluc3RhbmNlb2YgdHlwZSkgewogICAgICAgICAgICByZXR1cm4gZWxlbWVudC5uYW1lOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfTsKCiAgICAgIHJldHVybiBEZWJ1Z1N0YWNrOwogICAgfSgpOwogIH0KCiAgdmFyIERlYnVnU3RhY2skMSA9IERlYnVnU3RhY2s7CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgVGhlIGB7eyNlYWNofX1gIGhlbHBlciBsb29wcyBvdmVyIGVsZW1lbnRzIGluIGEgY29sbGVjdGlvbi4gSXQgaXMgYW4gZXh0ZW5zaW9uCiAgICBvZiB0aGUgYmFzZSBIYW5kbGViYXJzIGB7eyNlYWNofX1gIGhlbHBlci4KICAKICAgIFRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIGB7eyNlYWNofX1gIGlzIHRvIHlpZWxkIGl0cyBpbm5lciBibG9jayBvbmNlIGZvciBldmVyeQogICAgaXRlbSBpbiBhbiBhcnJheSBwYXNzaW5nIHRoZSBpdGVtIGFzIHRoZSBmaXJzdCBibG9jayBwYXJhbWV0ZXIuCiAgCiAgICBBc3N1bWluZyB0aGUgYEBkZXZlbG9wZXJzYCBhcmd1bWVudCBjb250YWlucyB0aGlzIGFycmF5OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgW3sgbmFtZTogJ1llaHVkYScgfSx7IG5hbWU6ICdUb20nIH0sIHsgbmFtZTogJ1BhdWwnIH1dOwogICAgYGBgCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8dWw+CiAgICAgIHt7I2VhY2ggQGRldmVsb3BlcnMgYXMgfHBlcnNvbnx9fQogICAgICAgIDxsaT5IZWxsbywge3twZXJzb24ubmFtZX19ITwvbGk+CiAgICAgIHt7L2VhY2h9fQogICAgPC91bD4KICAgIGBgYAogIAogICAgVGhlIHNhbWUgcnVsZXMgYXBwbHkgdG8gYXJyYXlzIG9mIHByaW1pdGl2ZXMuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBbJ1llaHVkYScsICdUb20nLCAnUGF1bCddCiAgICBgYGAKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDx1bD4KICAgICAge3sjZWFjaCBAZGV2ZWxvcGVyTmFtZXMgYXMgfG5hbWV8fX0KICAgICAgICA8bGk+SGVsbG8sIHt7bmFtZX19ITwvbGk+CiAgICAgIHt7L2VhY2h9fQogICAgPC91bD4KICAgIGBgYAogIAogICAgRHVyaW5nIGl0ZXJhdGlvbiwgdGhlIGluZGV4IG9mIGVhY2ggaXRlbSBpbiB0aGUgYXJyYXkgaXMgcHJvdmlkZWQgYXMgYSBzZWNvbmQgYmxvY2sKICAgIHBhcmFtZXRlci4KICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDx1bD4KICAgICAge3sjZWFjaCBAZGV2ZWxvcGVycyBhcyB8cGVyc29uIGluZGV4fH19CiAgICAgICAgPGxpPkhlbGxvLCB7e3BlcnNvbi5uYW1lfX0hIFlvdSdyZSBudW1iZXIge3tpbmRleH19IGluIGxpbmU8L2xpPgogICAgICB7ey9lYWNofX0KICAgIDwvdWw+CiAgICBgYGAKICAKICAgICMjIyBTcGVjaWZ5aW5nIEtleXMKICAKICAgIEluIG9yZGVyIHRvIGltcHJvdmUgcmVuZGVyaW5nIHNwZWVkLCBFbWJlciB3aWxsIHRyeSB0byByZXVzZSB0aGUgRE9NIGVsZW1lbnRzCiAgICB3aGVyZSBwb3NzaWJsZS4gU3BlY2lmaWNhbGx5LCBpZiB0aGUgc2FtZSBpdGVtIGlzIHByZXNlbnQgaW4gdGhlIGFycmF5IGJvdGgKICAgIGJlZm9yZSBhbmQgYWZ0ZXIgdGhlIGNoYW5nZSwgaXRzIERPTSBvdXRwdXQgd2lsbCBiZSByZXVzZWQuCiAgCiAgICBUaGUgYGtleWAgb3B0aW9uIGlzIHVzZWQgdG8gdGVsbCBFbWJlciBob3cgdG8gZGV0ZXJtaW5lIGlmIHRoZSBpdGVtcyBpbiB0aGUKICAgIGFycmF5IGJlaW5nIGl0ZXJhdGVkIG92ZXIgd2l0aCBge3sjZWFjaH19YCBoYXMgY2hhbmdlZCBiZXR3ZWVuIHJlbmRlcnMuIEJ5CiAgICBkZWZhdWx0IHRoZSBpdGVtJ3Mgb2JqZWN0IGlkZW50aXR5IGlzIHVzZWQuCiAgCiAgICBUaGlzIGlzIHVzdWFsbHkgc3VmZmljaWVudCwgc28gaW4gbW9zdCBjYXNlcywgdGhlIGBrZXlgIG9wdGlvbiBpcyBzaW1wbHkgbm90CiAgICBuZWVkZWQuIEhvd2V2ZXIsIGluIHNvbWUgcmFyZSBjYXNlcywgdGhlIG9iamVjdHMnIGlkZW50aXRpZXMgbWF5IGNoYW5nZSBldmVuCiAgICB0aG91Z2ggdGhleSByZXByZXNlbnQgdGhlIHNhbWUgdW5kZXJseWluZyBkYXRhLgogIAogICAgRm9yIGV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBwZW9wbGUubWFwKHBlcnNvbiA9PiB7CiAgICAgIHJldHVybiB7IC4uLnBlcnNvbiwgdHlwZTogJ2RldmVsb3BlcicgfTsKICAgIH0pOwogICAgYGBgCiAgCiAgICBJbiB0aGlzIGNhc2UsIGVhY2ggdGltZSB0aGUgYHBlb3BsZWAgYXJyYXkgaXMgYG1hcGAtZWQgb3ZlciwgaXQgd2lsbCBwcm9kdWNlCiAgICBhbiBuZXcgYXJyYXkgd2l0aCBjb21wbGV0ZWx5IGRpZmZlcmVudCBvYmplY3RzIGJldHdlZW4gcmVuZGVycy4gSW4gdGhlc2UgY2FzZXMsCiAgICB5b3UgY2FuIGhlbHAgRW1iZXIgZGV0ZXJtaW5lIGhvdyB0aGVzZSBvYmplY3RzIHJlbGF0ZWQgdG8gZWFjaCBvdGhlciB3aXRoIHRoZQogICAgYGtleWAgb3B0aW9uOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPHVsPgogICAgICB7eyNlYWNoIEBkZXZlbG9wZXJzIGtleT0ibmFtZSIgYXMgfHBlcnNvbnx9fQogICAgICAgIDxsaT5IZWxsbywge3twZXJzb24ubmFtZX19ITwvbGk+CiAgICAgIHt7L2VhY2h9fQogICAgPC91bD4KICAgIGBgYAogIAogICAgQnkgZG9pbmcgc28sIEVtYmVyIHdpbGwgdXNlIHRoZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgc3BlY2lmaWVkIChgcGVyc29uLm5hbWVgCiAgICBpbiB0aGUgZXhhbXBsZSkgdG8gZmluZCBhICJtYXRjaCIgZnJvbSB0aGUgcHJldmlvdXMgcmVuZGVyLiBUaGF0IGlzLCBpZiBFbWJlcgogICAgaGFzIHByZXZpb3VzbHkgc2VlbiBhbiBvYmplY3QgZnJvbSB0aGUgYEBkZXZlbG9wZXJzYCBhcnJheSB3aXRoIGEgbWF0Y2hpbmcKICAgIG5hbWUsIGl0cyBET00gZWxlbWVudHMgd2lsbCBiZSByZS11c2VkLgogIAogICAgIyMjIHt7ZWxzZX19IGNvbmRpdGlvbgogIAogICAgYHt7I2VhY2h9fWAgY2FuIGhhdmUgYSBtYXRjaGluZyBge3tlbHNlfX1gLiBUaGUgY29udGVudHMgb2YgdGhpcyBibG9jayB3aWxsIHJlbmRlcgogICAgaWYgdGhlIGNvbGxlY3Rpb24gaXMgZW1wdHkuCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8dWw+CiAgICAgIHt7I2VhY2ggQGRldmVsb3BlcnMgYXMgfHBlcnNvbnx9fQogICAgICAgIDxsaT57e3BlcnNvbi5uYW1lfX0gaXMgYXZhaWxhYmxlITwvbGk+CiAgICAgIHt7ZWxzZX19CiAgICAgICAgPGxpPlNvcnJ5LCBub2JvZHkgaXMgYXZhaWxhYmxlIGZvciB0aGlzIHRhc2suPC9saT4KICAgICAge3svZWFjaH19CiAgICA8L3VsPgogICAgYGBgCiAgCiAgICBAbWV0aG9kIGVhY2gKICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwdWJsaWMKICAgKi8KCiAgLyoqCiAgICBUaGUgYHt7ZWFjaC1pbn19YCBoZWxwZXIgbG9vcHMgb3ZlciBwcm9wZXJ0aWVzIG9uIGFuIG9iamVjdC4KICAKICAgIEZvciBleGFtcGxlLCBpZiB0aGUgYEB1c2VyYCBhcmd1bWVudCBjb250YWlucyB0aGlzIG9iamVjdDoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIHsKICAgICAgIm5hbWUiOiAiU2hlbGx5IFNhaWxzIiwKICAgICAgImFnZSI6IDQyCiAgICB9CiAgICBgYGAKICAKICAgIFRoaXMgdGVtcGxhdGUgd291bGQgZGlzcGxheSBhbGwgcHJvcGVydGllcyBvbiB0aGUgYEB1c2VyYAogICAgb2JqZWN0IGluIGEgbGlzdDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDx1bD4KICAgIHt7I2VhY2gtaW4gQHVzZXIgYXMgfGtleSB2YWx1ZXx9fQogICAgICA8bGk+e3trZXl9fToge3t2YWx1ZX19PC9saT4KICAgIHt7L2VhY2gtaW59fQogICAgPC91bD4KICAgIGBgYAogIAogICAgT3V0cHV0dGluZyB0aGVpciBuYW1lIGFuZCBhZ2UuCiAgCiAgICBAbWV0aG9kIGVhY2gtaW4KICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwdWJsaWMKICAgIEBzaW5jZSAyLjEuMAogICovCgogIF9leHBvcnRzLkRlYnVnU3RhY2sgPSBEZWJ1Z1N0YWNrJDE7CiAgdmFyIEVBQ0hfSU5fUkVGRVJFTkNFID0gKDAsIF91dGlscy5zeW1ib2wpKCdFQUNIX0lOJyk7CgogIHZhciBFYWNoSW5SZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBFYWNoSW5SZWZlcmVuY2UoaW5uZXIpIHsKICAgICAgdGhpcy5pbm5lciA9IGlubmVyOwogICAgICB0aGlzLnRhZyA9IGlubmVyLnRhZzsKICAgICAgdGhpc1tFQUNIX0lOX1JFRkVSRU5DRV0gPSB0cnVlOwogICAgfQoKICAgIHZhciBfcHJvdG8xNyA9IEVhY2hJblJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMTcudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuaW5uZXIudmFsdWUoKTsKICAgIH07CgogICAgX3Byb3RvMTcuZ2V0ID0gZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICByZXR1cm4gdGhpcy5pbm5lci5nZXQoa2V5KTsKICAgIH07CgogICAgcmV0dXJuIEVhY2hJblJlZmVyZW5jZTsKICB9KCk7CgogIGZ1bmN0aW9uIGlzRWFjaEluKHJlZikgewogICAgcmV0dXJuIHJlZiAhPT0gbnVsbCAmJiB0eXBlb2YgcmVmID09PSAnb2JqZWN0JyAmJiByZWZbRUFDSF9JTl9SRUZFUkVOQ0VdOwogIH0KCiAgZnVuY3Rpb24gZWFjaEluKF92bSwgYXJncykgewogICAgcmV0dXJuIG5ldyBFYWNoSW5SZWZlcmVuY2UoYXJncy5wb3NpdGlvbmFsLmF0KDApKTsKICB9CgogIHZhciBJVEVSQVRPUl9LRVlfR1VJRCA9ICdiZTI3Nzc1Ny1iYmJlLTQ2MjAtOWZjYi0yMTNlZjQzM2NjYTInOwoKICBmdW5jdGlvbiBfaXRlcmFibGVGb3IocmVmLCBrZXlQYXRoKSB7CiAgICBpZiAoaXNFYWNoSW4ocmVmKSkgewogICAgICByZXR1cm4gbmV3IEVhY2hJbkl0ZXJhYmxlKHJlZiwga2V5UGF0aCB8fCAnQGtleScpOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG5ldyBFYWNoSXRlcmFibGUocmVmLCBrZXlQYXRoIHx8ICdAaWRlbnRpdHknKTsKICAgIH0KICB9CgogIHZhciBCb3VuZGVkSXRlcmF0b3IgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBCb3VuZGVkSXRlcmF0b3IobGVuZ3RoLCBrZXlGb3IpIHsKICAgICAgdGhpcy5sZW5ndGggPSBsZW5ndGg7CiAgICAgIHRoaXMua2V5Rm9yID0ga2V5Rm9yOwogICAgICB0aGlzLnBvc2l0aW9uID0gMDsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTggPSBCb3VuZGVkSXRlcmF0b3IucHJvdG90eXBlOwoKICAgIF9wcm90bzE4LmlzRW1wdHkgPSBmdW5jdGlvbiBpc0VtcHR5KCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9OwoKICAgIF9wcm90bzE4Lm1lbW9Gb3IgPSBmdW5jdGlvbiBtZW1vRm9yKHBvc2l0aW9uKSB7CiAgICAgIHJldHVybiBwb3NpdGlvbjsKICAgIH07CgogICAgX3Byb3RvMTgubmV4dCA9IGZ1bmN0aW9uIG5leHQoKSB7CiAgICAgIHZhciBsZW5ndGggPSB0aGlzLmxlbmd0aCwKICAgICAgICAgIGtleUZvciA9IHRoaXMua2V5Rm9yLAogICAgICAgICAgcG9zaXRpb24gPSB0aGlzLnBvc2l0aW9uOwoKICAgICAgaWYgKHBvc2l0aW9uID49IGxlbmd0aCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgdmFsdWUkJDEgPSB0aGlzLnZhbHVlRm9yKHBvc2l0aW9uKTsKICAgICAgdmFyIG1lbW8gPSB0aGlzLm1lbW9Gb3IocG9zaXRpb24pOwogICAgICB2YXIga2V5ID0ga2V5Rm9yKHZhbHVlJCQxLCBtZW1vLCBwb3NpdGlvbik7CiAgICAgIHRoaXMucG9zaXRpb24rKzsKICAgICAgcmV0dXJuIHsKICAgICAgICBrZXk6IGtleSwKICAgICAgICB2YWx1ZTogdmFsdWUkJDEsCiAgICAgICAgbWVtbzogbWVtbwogICAgICB9OwogICAgfTsKCiAgICByZXR1cm4gQm91bmRlZEl0ZXJhdG9yOwogIH0oKTsKCiAgdmFyIEFycmF5SXRlcmF0b3IgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0JvdW5kZWRJdGVyYXRvcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEFycmF5SXRlcmF0b3IsIF9Cb3VuZGVkSXRlcmF0b3IpOwoKICAgIGZ1bmN0aW9uIEFycmF5SXRlcmF0b3IoYXJyYXksIGxlbmd0aCwga2V5Rm9yKSB7CiAgICAgIHZhciBfdGhpczEyOwoKICAgICAgX3RoaXMxMiA9IF9Cb3VuZGVkSXRlcmF0b3IuY2FsbCh0aGlzLCBsZW5ndGgsIGtleUZvcikgfHwgdGhpczsKICAgICAgX3RoaXMxMi5hcnJheSA9IGFycmF5OwogICAgICByZXR1cm4gX3RoaXMxMjsKICAgIH0KCiAgICBBcnJheUl0ZXJhdG9yLmZyb20gPSBmdW5jdGlvbiBmcm9tKGFycmF5LCBrZXlGb3IpIHsKICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDsKCiAgICAgIGlmIChsZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gRU1QVFlfSVRFUkFUT1I7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyB0aGlzKGFycmF5LCBsZW5ndGgsIGtleUZvcik7CiAgICAgIH0KICAgIH07CgogICAgQXJyYXlJdGVyYXRvci5mcm9tRm9yRWFjaGFibGUgPSBmdW5jdGlvbiBmcm9tRm9yRWFjaGFibGUob2JqZWN0LCBrZXlGb3IpIHsKICAgICAgdmFyIGFycmF5ID0gW107CiAgICAgIG9iamVjdC5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgICAgcmV0dXJuIGFycmF5LnB1c2goaXRlbSk7CiAgICAgIH0pOwogICAgICByZXR1cm4gdGhpcy5mcm9tKGFycmF5LCBrZXlGb3IpOwogICAgfTsKCiAgICB2YXIgX3Byb3RvMTkgPSBBcnJheUl0ZXJhdG9yLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xOS52YWx1ZUZvciA9IGZ1bmN0aW9uIHZhbHVlRm9yKHBvc2l0aW9uKSB7CiAgICAgIHJldHVybiB0aGlzLmFycmF5W3Bvc2l0aW9uXTsKICAgIH07CgogICAgcmV0dXJuIEFycmF5SXRlcmF0b3I7CiAgfShCb3VuZGVkSXRlcmF0b3IpOwoKICB2YXIgRW1iZXJBcnJheUl0ZXJhdG9yID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Cb3VuZGVkSXRlcmF0b3IyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRW1iZXJBcnJheUl0ZXJhdG9yLCBfQm91bmRlZEl0ZXJhdG9yMik7CgogICAgZnVuY3Rpb24gRW1iZXJBcnJheUl0ZXJhdG9yKGFycmF5LCBsZW5ndGgsIGtleUZvcikgewogICAgICB2YXIgX3RoaXMxMzsKCiAgICAgIF90aGlzMTMgPSBfQm91bmRlZEl0ZXJhdG9yMi5jYWxsKHRoaXMsIGxlbmd0aCwga2V5Rm9yKSB8fCB0aGlzOwogICAgICBfdGhpczEzLmFycmF5ID0gYXJyYXk7CiAgICAgIHJldHVybiBfdGhpczEzOwogICAgfQoKICAgIEVtYmVyQXJyYXlJdGVyYXRvci5mcm9tID0gZnVuY3Rpb24gZnJvbShhcnJheSwga2V5Rm9yKSB7CiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7CgogICAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIEVNUFRZX0lURVJBVE9SOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBuZXcgdGhpcyhhcnJheSwgbGVuZ3RoLCBrZXlGb3IpOwogICAgICB9CiAgICB9OwoKICAgIHZhciBfcHJvdG8yMCA9IEVtYmVyQXJyYXlJdGVyYXRvci5wcm90b3R5cGU7CgogICAgX3Byb3RvMjAudmFsdWVGb3IgPSBmdW5jdGlvbiB2YWx1ZUZvcihwb3NpdGlvbikgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5vYmplY3RBdCkodGhpcy5hcnJheSwgcG9zaXRpb24pOwogICAgfTsKCiAgICByZXR1cm4gRW1iZXJBcnJheUl0ZXJhdG9yOwogIH0oQm91bmRlZEl0ZXJhdG9yKTsKCiAgdmFyIE9iamVjdEl0ZXJhdG9yID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Cb3VuZGVkSXRlcmF0b3IzKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoT2JqZWN0SXRlcmF0b3IsIF9Cb3VuZGVkSXRlcmF0b3IzKTsKCiAgICBmdW5jdGlvbiBPYmplY3RJdGVyYXRvcihrZXlzLCB2YWx1ZXMsIGxlbmd0aCwga2V5Rm9yKSB7CiAgICAgIHZhciBfdGhpczE0OwoKICAgICAgX3RoaXMxNCA9IF9Cb3VuZGVkSXRlcmF0b3IzLmNhbGwodGhpcywgbGVuZ3RoLCBrZXlGb3IpIHx8IHRoaXM7CiAgICAgIF90aGlzMTQua2V5cyA9IGtleXM7CiAgICAgIF90aGlzMTQudmFsdWVzID0gdmFsdWVzOwogICAgICByZXR1cm4gX3RoaXMxNDsKICAgIH0KCiAgICBPYmplY3RJdGVyYXRvci5mcm9tSW5kZXhhYmxlID0gZnVuY3Rpb24gZnJvbUluZGV4YWJsZShvYmosIGtleUZvcikgewogICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7CiAgICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDsKCiAgICAgIGlmIChsZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gRU1QVFlfSVRFUkFUT1I7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIHZhbHVlcyA9IFtdOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICB2YXIgdmFsdWUkJDEgPSB2b2lkIDA7CiAgICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTsKICAgICAgICAgIHZhbHVlJCQxID0gb2JqW2tleV07IC8vIEFkZCB0aGUgdGFnIG9mIHRoZSByZXR1cm5lZCB2YWx1ZSBpZiBpdCBpcyBhbiBhcnJheSwgc2luY2UgYXJyYXlzCiAgICAgICAgICAvLyBzaG91bGQgYWx3YXlzIGNhdXNlIHVwZGF0ZXMgaWYgdGhleSBhcmUgY29uc3VtZWQgYW5kIHRoZW4gY2hhbmdlZAoKICAgICAgICAgIGlmICh0cnVlCiAgICAgICAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICAgICAgICYmICgwLCBfbWV0YWwuaXNUcmFja2luZykoKSkgewogICAgICAgICAgICAoMCwgX21ldGFsLmNvbnN1bWUpKCgwLCBfbWV0YWwudGFnRm9yUHJvcGVydHkpKG9iaiwga2V5KSk7CgogICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSQkMSkgfHwgKDAsIF91dGlscy5pc0VtYmVyQXJyYXkpKHZhbHVlJCQxKSkgewogICAgICAgICAgICAgICgwLCBfbWV0YWwuY29uc3VtZSkoKDAsIF9tZXRhbC50YWdGb3JQcm9wZXJ0eSkodmFsdWUkJDEsICdbXScpKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQoKICAgICAgICAgIHZhbHVlcy5wdXNoKHZhbHVlJCQxKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBuZXcgdGhpcyhrZXlzLCB2YWx1ZXMsIGxlbmd0aCwga2V5Rm9yKTsKICAgICAgfQogICAgfTsKCiAgICBPYmplY3RJdGVyYXRvci5mcm9tRm9yRWFjaGFibGUgPSBmdW5jdGlvbiBmcm9tRm9yRWFjaGFibGUob2JqLCBrZXlGb3IpIHsKICAgICAgdmFyIF9hcmd1bWVudHMgPSBhcmd1bWVudHM7CiAgICAgIHZhciBrZXlzID0gW107CiAgICAgIHZhciB2YWx1ZXMgPSBbXTsKICAgICAgdmFyIGxlbmd0aCA9IDA7CiAgICAgIHZhciBpc01hcExpa2UgPSBmYWxzZTsKICAgICAgb2JqLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlJCQxLCBrZXkpIHsKICAgICAgICBpc01hcExpa2UgPSBpc01hcExpa2UgfHwgX2FyZ3VtZW50cy5sZW5ndGggPj0gMjsKCiAgICAgICAgaWYgKGlzTWFwTGlrZSkgewogICAgICAgICAga2V5cy5wdXNoKGtleSk7CiAgICAgICAgfQoKICAgICAgICB2YWx1ZXMucHVzaCh2YWx1ZSQkMSk7CiAgICAgICAgbGVuZ3RoKys7CiAgICAgIH0pOwoKICAgICAgaWYgKGxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybiBFTVBUWV9JVEVSQVRPUjsKICAgICAgfSBlbHNlIGlmIChpc01hcExpa2UpIHsKICAgICAgICByZXR1cm4gbmV3IHRoaXMoa2V5cywgdmFsdWVzLCBsZW5ndGgsIGtleUZvcik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyBBcnJheUl0ZXJhdG9yKHZhbHVlcywgbGVuZ3RoLCBrZXlGb3IpOwogICAgICB9CiAgICB9OwoKICAgIHZhciBfcHJvdG8yMSA9IE9iamVjdEl0ZXJhdG9yLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yMS52YWx1ZUZvciA9IGZ1bmN0aW9uIHZhbHVlRm9yKHBvc2l0aW9uKSB7CiAgICAgIHJldHVybiB0aGlzLnZhbHVlc1twb3NpdGlvbl07CiAgICB9OwoKICAgIF9wcm90bzIxLm1lbW9Gb3IgPSBmdW5jdGlvbiBtZW1vRm9yKHBvc2l0aW9uKSB7CiAgICAgIHJldHVybiB0aGlzLmtleXNbcG9zaXRpb25dOwogICAgfTsKCiAgICByZXR1cm4gT2JqZWN0SXRlcmF0b3I7CiAgfShCb3VuZGVkSXRlcmF0b3IpOwoKICB2YXIgTmF0aXZlSXRlcmF0b3IgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBOYXRpdmVJdGVyYXRvcihpdGVyYWJsZSwgcmVzdWx0LCBrZXlGb3IpIHsKICAgICAgdGhpcy5pdGVyYWJsZSA9IGl0ZXJhYmxlOwogICAgICB0aGlzLnJlc3VsdCA9IHJlc3VsdDsKICAgICAgdGhpcy5rZXlGb3IgPSBrZXlGb3I7CiAgICAgIHRoaXMucG9zaXRpb24gPSAwOwogICAgfQoKICAgIE5hdGl2ZUl0ZXJhdG9yLmZyb20gPSBmdW5jdGlvbiBmcm9tKGl0ZXJhYmxlLCBrZXlGb3IpIHsKICAgICAgdmFyIGl0ZXJhdG9yID0gaXRlcmFibGVbU3ltYm9sLml0ZXJhdG9yXSgpOwogICAgICB2YXIgcmVzdWx0ID0gaXRlcmF0b3IubmV4dCgpOwogICAgICB2YXIgdmFsdWUkJDEgPSByZXN1bHQudmFsdWUsCiAgICAgICAgICBkb25lID0gcmVzdWx0LmRvbmU7CgogICAgICBpZiAoZG9uZSkgewogICAgICAgIHJldHVybiBFTVBUWV9JVEVSQVRPUjsKICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHZhbHVlJCQxKSAmJiB2YWx1ZSQkMS5sZW5ndGggPT09IDIpIHsKICAgICAgICByZXR1cm4gbmV3IHRoaXMoaXRlcmF0b3IsIHJlc3VsdCwga2V5Rm9yKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbmV3IEFycmF5TGlrZU5hdGl2ZUl0ZXJhdG9yKGl0ZXJhdG9yLCByZXN1bHQsIGtleUZvcik7CiAgICAgIH0KICAgIH07CgogICAgdmFyIF9wcm90bzIyID0gTmF0aXZlSXRlcmF0b3IucHJvdG90eXBlOwoKICAgIF9wcm90bzIyLmlzRW1wdHkgPSBmdW5jdGlvbiBpc0VtcHR5KCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9OwoKICAgIF9wcm90bzIyLm5leHQgPSBmdW5jdGlvbiBuZXh0KCkgewogICAgICB2YXIgaXRlcmFibGUgPSB0aGlzLml0ZXJhYmxlLAogICAgICAgICAgcmVzdWx0ID0gdGhpcy5yZXN1bHQsCiAgICAgICAgICBwb3NpdGlvbiA9IHRoaXMucG9zaXRpb24sCiAgICAgICAgICBrZXlGb3IgPSB0aGlzLmtleUZvcjsKCiAgICAgIGlmIChyZXN1bHQuZG9uZSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgdmFsdWUkJDEgPSB0aGlzLnZhbHVlRm9yKHJlc3VsdCwgcG9zaXRpb24pOwogICAgICB2YXIgbWVtbyA9IHRoaXMubWVtb0ZvcihyZXN1bHQsIHBvc2l0aW9uKTsKICAgICAgdmFyIGtleSA9IGtleUZvcih2YWx1ZSQkMSwgbWVtbywgcG9zaXRpb24pOwogICAgICB0aGlzLnBvc2l0aW9uKys7CiAgICAgIHRoaXMucmVzdWx0ID0gaXRlcmFibGUubmV4dCgpOwogICAgICByZXR1cm4gewogICAgICAgIGtleToga2V5LAogICAgICAgIHZhbHVlOiB2YWx1ZSQkMSwKICAgICAgICBtZW1vOiBtZW1vCiAgICAgIH07CiAgICB9OwoKICAgIHJldHVybiBOYXRpdmVJdGVyYXRvcjsKICB9KCk7CgogIHZhciBBcnJheUxpa2VOYXRpdmVJdGVyYXRvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfTmF0aXZlSXRlcmF0b3IpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShBcnJheUxpa2VOYXRpdmVJdGVyYXRvciwgX05hdGl2ZUl0ZXJhdG9yKTsKCiAgICBmdW5jdGlvbiBBcnJheUxpa2VOYXRpdmVJdGVyYXRvcigpIHsKICAgICAgcmV0dXJuIF9OYXRpdmVJdGVyYXRvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzIzID0gQXJyYXlMaWtlTmF0aXZlSXRlcmF0b3IucHJvdG90eXBlOwoKICAgIF9wcm90bzIzLnZhbHVlRm9yID0gZnVuY3Rpb24gdmFsdWVGb3IocmVzdWx0KSB7CiAgICAgIHJldHVybiByZXN1bHQudmFsdWU7CiAgICB9OwoKICAgIF9wcm90bzIzLm1lbW9Gb3IgPSBmdW5jdGlvbiBtZW1vRm9yKF9yZXN1bHQsIHBvc2l0aW9uKSB7CiAgICAgIHJldHVybiBwb3NpdGlvbjsKICAgIH07CgogICAgcmV0dXJuIEFycmF5TGlrZU5hdGl2ZUl0ZXJhdG9yOwogIH0oTmF0aXZlSXRlcmF0b3IpOwoKICB2YXIgTWFwTGlrZU5hdGl2ZUl0ZXJhdG9yID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9OYXRpdmVJdGVyYXRvcjIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShNYXBMaWtlTmF0aXZlSXRlcmF0b3IsIF9OYXRpdmVJdGVyYXRvcjIpOwoKICAgIGZ1bmN0aW9uIE1hcExpa2VOYXRpdmVJdGVyYXRvcigpIHsKICAgICAgcmV0dXJuIF9OYXRpdmVJdGVyYXRvcjIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8yNCA9IE1hcExpa2VOYXRpdmVJdGVyYXRvci5wcm90b3R5cGU7CgogICAgX3Byb3RvMjQudmFsdWVGb3IgPSBmdW5jdGlvbiB2YWx1ZUZvcihyZXN1bHQpIHsKICAgICAgcmV0dXJuIHJlc3VsdC52YWx1ZVsxXTsKICAgIH07CgogICAgX3Byb3RvMjQubWVtb0ZvciA9IGZ1bmN0aW9uIG1lbW9Gb3IocmVzdWx0KSB7CiAgICAgIHJldHVybiByZXN1bHQudmFsdWVbMF07CiAgICB9OwoKICAgIHJldHVybiBNYXBMaWtlTmF0aXZlSXRlcmF0b3I7CiAgfShOYXRpdmVJdGVyYXRvcik7CgogIHZhciBFTVBUWV9JVEVSQVRPUiA9IHsKICAgIGlzRW1wdHk6IGZ1bmN0aW9uIGlzRW1wdHkoKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSwKICAgIG5leHQ6IGZ1bmN0aW9uIG5leHQoKSB7CiAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0Nhbm5vdCBjYWxsIG5leHQoKSBvbiBhbiBlbXB0eSBpdGVyYXRvcicpKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgfTsKCiAgdmFyIEVhY2hJbkl0ZXJhYmxlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRWFjaEluSXRlcmFibGUocmVmLCBrZXlQYXRoKSB7CiAgICAgIHRoaXMucmVmID0gcmVmOwogICAgICB0aGlzLmtleVBhdGggPSBrZXlQYXRoOwogICAgICB0aGlzLnZhbHVlVGFnID0gKDAsIF9yZWZlcmVuY2UuY3JlYXRlVXBkYXRhYmxlVGFnKSgpOwogICAgICB0aGlzLnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFtyZWYudGFnLCB0aGlzLnZhbHVlVGFnXSk7CiAgICB9CgogICAgdmFyIF9wcm90bzI1ID0gRWFjaEluSXRlcmFibGUucHJvdG90eXBlOwoKICAgIF9wcm90bzI1Lml0ZXJhdGUgPSBmdW5jdGlvbiBpdGVyYXRlKCkgewogICAgICB2YXIgcmVmID0gdGhpcy5yZWYsCiAgICAgICAgICB2YWx1ZVRhZyA9IHRoaXMudmFsdWVUYWc7CiAgICAgIHZhciBpdGVyYWJsZSA9IHJlZi52YWx1ZSgpOwogICAgICB2YXIgdGFnID0gKDAsIF9tZXRhbC50YWdGb3IpKGl0ZXJhYmxlKTsKCiAgICAgIGlmICgoMCwgX3V0aWxzLmlzUHJveHkpKGl0ZXJhYmxlKSkgewogICAgICAgIC8vIHRoaXMgaXMgYmVjYXVzZSB0aGUgZWFjaC1pbiBkb2Vzbid0IGFjdHVhbGx5IGdldChwcm94eSwgJ2tleScpIGJ1dCBieXBhc3NlcyBpdAogICAgICAgIC8vIGFuZCB0aGUgcHJveHkncyB0YWcgaXMgbGF6eSB1cGRhdGVkIG9uIGFjY2VzcwogICAgICAgIGl0ZXJhYmxlID0gKDAsIF9ydW50aW1lLl9jb250ZW50Rm9yKShpdGVyYWJsZSk7CiAgICAgIH0KCiAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkodmFsdWVUYWcsIHRhZyk7CgogICAgICBpZiAoIWlzSW5kZXhhYmxlKGl0ZXJhYmxlKSkgewogICAgICAgIHJldHVybiBFTVBUWV9JVEVSQVRPUjsKICAgICAgfQoKICAgICAgaWYgKEFycmF5LmlzQXJyYXkoaXRlcmFibGUpIHx8ICgwLCBfdXRpbHMuaXNFbWJlckFycmF5KShpdGVyYWJsZSkpIHsKICAgICAgICByZXR1cm4gT2JqZWN0SXRlcmF0b3IuZnJvbUluZGV4YWJsZShpdGVyYWJsZSwgdGhpcy5rZXlGb3IodHJ1ZSkpOwogICAgICB9IGVsc2UgaWYgKF91dGlscy5IQVNfTkFUSVZFX1NZTUJPTCAmJiBpc05hdGl2ZUl0ZXJhYmxlKGl0ZXJhYmxlKSkgewogICAgICAgIHJldHVybiBNYXBMaWtlTmF0aXZlSXRlcmF0b3IuZnJvbShpdGVyYWJsZSwgdGhpcy5rZXlGb3IoKSk7CiAgICAgIH0gZWxzZSBpZiAoaGFzRm9yRWFjaChpdGVyYWJsZSkpIHsKICAgICAgICByZXR1cm4gT2JqZWN0SXRlcmF0b3IuZnJvbUZvckVhY2hhYmxlKGl0ZXJhYmxlLCB0aGlzLmtleUZvcigpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gT2JqZWN0SXRlcmF0b3IuZnJvbUluZGV4YWJsZShpdGVyYWJsZSwgdGhpcy5rZXlGb3IodHJ1ZSkpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzI1LnZhbHVlUmVmZXJlbmNlRm9yID0gZnVuY3Rpb24gdmFsdWVSZWZlcmVuY2VGb3IoaXRlbSkgewogICAgICByZXR1cm4gbmV3IFVwZGF0YWJsZVJlZmVyZW5jZShpdGVtLnZhbHVlKTsKICAgIH07CgogICAgX3Byb3RvMjUudXBkYXRlVmFsdWVSZWZlcmVuY2UgPSBmdW5jdGlvbiB1cGRhdGVWYWx1ZVJlZmVyZW5jZShyZWYsIGl0ZW0pIHsKICAgICAgcmVmLnVwZGF0ZShpdGVtLnZhbHVlKTsKICAgIH07CgogICAgX3Byb3RvMjUubWVtb1JlZmVyZW5jZUZvciA9IGZ1bmN0aW9uIG1lbW9SZWZlcmVuY2VGb3IoaXRlbSkgewogICAgICByZXR1cm4gbmV3IFVwZGF0YWJsZVJlZmVyZW5jZShpdGVtLm1lbW8pOwogICAgfTsKCiAgICBfcHJvdG8yNS51cGRhdGVNZW1vUmVmZXJlbmNlID0gZnVuY3Rpb24gdXBkYXRlTWVtb1JlZmVyZW5jZShyZWYsIGl0ZW0pIHsKICAgICAgcmVmLnVwZGF0ZShpdGVtLm1lbW8pOwogICAgfTsKCiAgICBfcHJvdG8yNS5rZXlGb3IgPSBmdW5jdGlvbiBrZXlGb3IoaGFzVW5pcXVlS2V5cykgewogICAgICBpZiAoaGFzVW5pcXVlS2V5cyA9PT0gdm9pZCAwKSB7CiAgICAgICAgaGFzVW5pcXVlS2V5cyA9IGZhbHNlOwogICAgICB9CgogICAgICB2YXIga2V5UGF0aCA9IHRoaXMua2V5UGF0aDsKCiAgICAgIHN3aXRjaCAoa2V5UGF0aCkgewogICAgICAgIGNhc2UgJ0BrZXknOgogICAgICAgICAgcmV0dXJuIGhhc1VuaXF1ZUtleXMgPyBPYmplY3RLZXkgOiBVbmlxdWUoTWFwS2V5KTsKCiAgICAgICAgY2FzZSAnQGluZGV4JzoKICAgICAgICAgIHJldHVybiBJbmRleDsKCiAgICAgICAgY2FzZSAnQGlkZW50aXR5JzoKICAgICAgICAgIHJldHVybiBVbmlxdWUoSWRlbnRpdHkpOwoKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgKGZhbHNlICYmICEoa2V5UGF0aFswXSAhPT0gJ0AnKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkludmFsaWQga2V5OiAiICsga2V5UGF0aCwga2V5UGF0aFswXSAhPT0gJ0AnKSk7CiAgICAgICAgICByZXR1cm4gVW5pcXVlKEtleVBhdGgoa2V5UGF0aCkpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBFYWNoSW5JdGVyYWJsZTsKICB9KCk7CgogIHZhciBFYWNoSXRlcmFibGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBFYWNoSXRlcmFibGUocmVmLCBrZXlQYXRoKSB7CiAgICAgIHRoaXMucmVmID0gcmVmOwogICAgICB0aGlzLmtleVBhdGggPSBrZXlQYXRoOwogICAgICB0aGlzLnZhbHVlVGFnID0gKDAsIF9yZWZlcmVuY2UuY3JlYXRlVXBkYXRhYmxlVGFnKSgpOwogICAgICB0aGlzLnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFtyZWYudGFnLCB0aGlzLnZhbHVlVGFnXSk7CiAgICB9CgogICAgdmFyIF9wcm90bzI2ID0gRWFjaEl0ZXJhYmxlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yNi5pdGVyYXRlID0gZnVuY3Rpb24gaXRlcmF0ZSgpIHsKICAgICAgdmFyIHJlZiA9IHRoaXMucmVmLAogICAgICAgICAgdmFsdWVUYWcgPSB0aGlzLnZhbHVlVGFnOwogICAgICB2YXIgaXRlcmFibGUgPSByZWYudmFsdWUoKTsKICAgICAgKDAsIF9yZWZlcmVuY2UudXBkYXRlKSh2YWx1ZVRhZywgKDAsIF9tZXRhbC50YWdGb3JQcm9wZXJ0eSkoaXRlcmFibGUsICdbXScpKTsKCiAgICAgIGlmIChpdGVyYWJsZSA9PT0gbnVsbCB8fCB0eXBlb2YgaXRlcmFibGUgIT09ICdvYmplY3QnKSB7CiAgICAgICAgcmV0dXJuIEVNUFRZX0lURVJBVE9SOwogICAgICB9CgogICAgICB2YXIga2V5Rm9yID0gdGhpcy5rZXlGb3IoKTsKCiAgICAgIGlmIChBcnJheS5pc0FycmF5KGl0ZXJhYmxlKSkgewogICAgICAgIHJldHVybiBBcnJheUl0ZXJhdG9yLmZyb20oaXRlcmFibGUsIGtleUZvcik7CiAgICAgIH0gZWxzZSBpZiAoKDAsIF91dGlscy5pc0VtYmVyQXJyYXkpKGl0ZXJhYmxlKSkgewogICAgICAgIHJldHVybiBFbWJlckFycmF5SXRlcmF0b3IuZnJvbShpdGVyYWJsZSwga2V5Rm9yKTsKICAgICAgfSBlbHNlIGlmIChfdXRpbHMuSEFTX05BVElWRV9TWU1CT0wgJiYgaXNOYXRpdmVJdGVyYWJsZShpdGVyYWJsZSkpIHsKICAgICAgICByZXR1cm4gQXJyYXlMaWtlTmF0aXZlSXRlcmF0b3IuZnJvbShpdGVyYWJsZSwga2V5Rm9yKTsKICAgICAgfSBlbHNlIGlmIChoYXNGb3JFYWNoKGl0ZXJhYmxlKSkgewogICAgICAgIHJldHVybiBBcnJheUl0ZXJhdG9yLmZyb21Gb3JFYWNoYWJsZShpdGVyYWJsZSwga2V5Rm9yKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRU1QVFlfSVRFUkFUT1I7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMjYudmFsdWVSZWZlcmVuY2VGb3IgPSBmdW5jdGlvbiB2YWx1ZVJlZmVyZW5jZUZvcihpdGVtKSB7CiAgICAgIHJldHVybiBuZXcgVXBkYXRhYmxlUmVmZXJlbmNlKGl0ZW0udmFsdWUpOwogICAgfTsKCiAgICBfcHJvdG8yNi51cGRhdGVWYWx1ZVJlZmVyZW5jZSA9IGZ1bmN0aW9uIHVwZGF0ZVZhbHVlUmVmZXJlbmNlKHJlZiwgaXRlbSkgewogICAgICByZWYudXBkYXRlKGl0ZW0udmFsdWUpOwogICAgfTsKCiAgICBfcHJvdG8yNi5tZW1vUmVmZXJlbmNlRm9yID0gZnVuY3Rpb24gbWVtb1JlZmVyZW5jZUZvcihpdGVtKSB7CiAgICAgIHJldHVybiBuZXcgVXBkYXRhYmxlUmVmZXJlbmNlKGl0ZW0ubWVtbyk7CiAgICB9OwoKICAgIF9wcm90bzI2LnVwZGF0ZU1lbW9SZWZlcmVuY2UgPSBmdW5jdGlvbiB1cGRhdGVNZW1vUmVmZXJlbmNlKHJlZiwgaXRlbSkgewogICAgICByZWYudXBkYXRlKGl0ZW0ubWVtbyk7CiAgICB9OwoKICAgIF9wcm90bzI2LmtleUZvciA9IGZ1bmN0aW9uIGtleUZvcigpIHsKICAgICAgdmFyIGtleVBhdGggPSB0aGlzLmtleVBhdGg7CgogICAgICBzd2l0Y2ggKGtleVBhdGgpIHsKICAgICAgICBjYXNlICdAaW5kZXgnOgogICAgICAgICAgcmV0dXJuIEluZGV4OwoKICAgICAgICBjYXNlICdAaWRlbnRpdHknOgogICAgICAgICAgcmV0dXJuIFVuaXF1ZShJZGVudGl0eSk7CgogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAoZmFsc2UgJiYgIShrZXlQYXRoWzBdICE9PSAnQCcpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiSW52YWxpZCBrZXk6ICIgKyBrZXlQYXRoLCBrZXlQYXRoWzBdICE9PSAnQCcpKTsKICAgICAgICAgIHJldHVybiBVbmlxdWUoS2V5UGF0aChrZXlQYXRoKSk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEVhY2hJdGVyYWJsZTsKICB9KCk7CgogIGZ1bmN0aW9uIGhhc0ZvckVhY2godmFsdWUkJDEpIHsKICAgIHJldHVybiB0eXBlb2YgdmFsdWUkJDFbJ2ZvckVhY2gnXSA9PT0gJ2Z1bmN0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGlzTmF0aXZlSXRlcmFibGUodmFsdWUkJDEpIHsKICAgIHJldHVybiB0eXBlb2YgdmFsdWUkJDFbU3ltYm9sLml0ZXJhdG9yXSA9PT0gJ2Z1bmN0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGlzSW5kZXhhYmxlKHZhbHVlJCQxKSB7CiAgICByZXR1cm4gdmFsdWUkJDEgIT09IG51bGwgJiYgKHR5cGVvZiB2YWx1ZSQkMSA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIHZhbHVlJCQxID09PSAnZnVuY3Rpb24nKTsKICB9IC8vIFBvc2l0aW9uIGluIGFuIGFycmF5IGlzIGd1YXJlbnRlZWQgdG8gYmUgdW5pcXVlCgoKICBmdW5jdGlvbiBJbmRleChfdmFsdWUsIF9tZW1vLCBwb3NpdGlvbikgewogICAgcmV0dXJuIFN0cmluZyhwb3NpdGlvbik7CiAgfSAvLyBPYmplY3Qua2V5cyguLi4pIGlzIGd1YXJlbnRlZWQgdG8gYmUgc3RyaW5ncyBhbmQgdW5pcXVlCgoKICBmdW5jdGlvbiBPYmplY3RLZXkoX3ZhbHVlLCBtZW1vKSB7CiAgICByZXR1cm4gbWVtbzsKICB9IC8vIE1hcCBrZXlzIGNhbiBiZSBhbnkgb2JqZWN0cwoKCiAgZnVuY3Rpb24gTWFwS2V5KF92YWx1ZSwgbWVtbykgewogICAgcmV0dXJuIElkZW50aXR5KG1lbW8pOwogIH0KCiAgZnVuY3Rpb24gSWRlbnRpdHkodmFsdWUkJDEpIHsKICAgIHN3aXRjaCAodHlwZW9mIHZhbHVlJCQxKSB7CiAgICAgIGNhc2UgJ3N0cmluZyc6CiAgICAgICAgcmV0dXJuIHZhbHVlJCQxOwoKICAgICAgY2FzZSAnbnVtYmVyJzoKICAgICAgICByZXR1cm4gU3RyaW5nKHZhbHVlJCQxKTsKCiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuICgwLCBfdXRpbHMuZ3VpZEZvcikodmFsdWUkJDEpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gS2V5UGF0aChrZXlQYXRoKSB7CiAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiBTdHJpbmcoKDAsIF9tZXRhbC5nZXQpKHZhbHVlJCQxLCBrZXlQYXRoKSk7CiAgICB9OwogIH0KCiAgZnVuY3Rpb24gVW5pcXVlKGZ1bmMpIHsKICAgIHZhciBzZWVuID0ge307CiAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlJCQxLCBtZW1vLCBwb3NpdGlvbikgewogICAgICB2YXIga2V5ID0gZnVuYyh2YWx1ZSQkMSwgbWVtbywgcG9zaXRpb24pOwogICAgICB2YXIgY291bnQgPSBzZWVuW2tleV07CgogICAgICBpZiAoY291bnQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHNlZW5ba2V5XSA9IDA7CiAgICAgICAgcmV0dXJuIGtleTsKICAgICAgfSBlbHNlIHsKICAgICAgICBzZWVuW2tleV0gPSArK2NvdW50OwogICAgICAgIHJldHVybiAiIiArIGtleSArIElURVJBVE9SX0tFWV9HVUlEICsgY291bnQ7CiAgICAgIH0KICAgIH07CiAgfQogIC8qKgogIEBtb2R1bGUgQGVtYmVyL3RlbXBsYXRlCiAgKi8KCgogIHZhciBTYWZlU3RyaW5nID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gU2FmZVN0cmluZyhzdHJpbmcpIHsKICAgICAgdGhpcy5zdHJpbmcgPSBzdHJpbmc7CiAgICB9CgogICAgdmFyIF9wcm90bzI3ID0gU2FmZVN0cmluZy5wcm90b3R5cGU7CgogICAgX3Byb3RvMjcudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuICIiICsgdGhpcy5zdHJpbmc7CiAgICB9OwoKICAgIF9wcm90bzI3LnRvSFRNTCA9IGZ1bmN0aW9uIHRvSFRNTCgpIHsKICAgICAgcmV0dXJuIHRoaXMudG9TdHJpbmcoKTsKICAgIH07CgogICAgcmV0dXJuIFNhZmVTdHJpbmc7CiAgfSgpOwoKICBfZXhwb3J0cy5TYWZlU3RyaW5nID0gU2FmZVN0cmluZzsKICB2YXIgZXNjYXBlID0gewogICAgJyYnOiAnJmFtcDsnLAogICAgJzwnOiAnJmx0OycsCiAgICAnPic6ICcmZ3Q7JywKICAgICciJzogJyZxdW90OycsCiAgICAiJyI6ICcmI3gyNzsnLAogICAgJ2AnOiAnJiN4NjA7JywKICAgICc9JzogJyYjeDNEOycKICB9OwogIHZhciBwb3NzaWJsZSA9IC9bJjw+IidgPV0vOwogIHZhciBiYWRDaGFycyA9IC9bJjw+IidgPV0vZzsKCiAgZnVuY3Rpb24gZXNjYXBlQ2hhcihjaHIpIHsKICAgIHJldHVybiBlc2NhcGVbY2hyXTsKICB9CgogIGZ1bmN0aW9uIGVzY2FwZUV4cHJlc3Npb24oc3RyaW5nKSB7CiAgICBpZiAodHlwZW9mIHN0cmluZyAhPT0gJ3N0cmluZycpIHsKICAgICAgLy8gZG9uJ3QgZXNjYXBlIFNhZmVTdHJpbmdzLCBzaW5jZSB0aGV5J3JlIGFscmVhZHkgc2FmZQogICAgICBpZiAoc3RyaW5nICYmIHN0cmluZy50b0hUTUwpIHsKICAgICAgICByZXR1cm4gc3RyaW5nLnRvSFRNTCgpOwogICAgICB9IGVsc2UgaWYgKHN0cmluZyA9PT0gbnVsbCB8fCBzdHJpbmcgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiAnJzsKICAgICAgfSBlbHNlIGlmICghc3RyaW5nKSB7CiAgICAgICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpOwogICAgICB9IC8vIEZvcmNlIGEgc3RyaW5nIGNvbnZlcnNpb24gYXMgdGhpcyB3aWxsIGJlIGRvbmUgYnkgdGhlIGFwcGVuZCByZWdhcmRsZXNzIGFuZAogICAgICAvLyB0aGUgcmVnZXggdGVzdCB3aWxsIGRvIHRoaXMgdHJhbnNwYXJlbnRseSBiZWhpbmQgdGhlIHNjZW5lcywgY2F1c2luZyBpc3N1ZXMgaWYKICAgICAgLy8gYW4gb2JqZWN0J3MgdG8gc3RyaW5nIGhhcyBlc2NhcGVkIGNoYXJhY3RlcnMgaW4gaXQuCgoKICAgICAgc3RyaW5nID0gU3RyaW5nKHN0cmluZyk7CiAgICB9CgogICAgaWYgKCFwb3NzaWJsZS50ZXN0KHN0cmluZykpIHsKICAgICAgcmV0dXJuIHN0cmluZzsKICAgIH0KCiAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoYmFkQ2hhcnMsIGVzY2FwZUNoYXIpOwogIH0KICAvKioKICAgIE1hcmsgYSBzdHJpbmcgYXMgc2FmZSBmb3IgdW5lc2NhcGVkIG91dHB1dCB3aXRoIEVtYmVyIHRlbXBsYXRlcy4gSWYgeW91CiAgICByZXR1cm4gSFRNTCBmcm9tIGEgaGVscGVyLCB1c2UgdGhpcyBmdW5jdGlvbiB0bwogICAgZW5zdXJlIEVtYmVyJ3MgcmVuZGVyaW5nIGxheWVyIGRvZXMgbm90IGVzY2FwZSB0aGUgSFRNTC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGh0bWxTYWZlIH0gZnJvbSAnQGVtYmVyL3RlbXBsYXRlJzsKICAKICAgIGh0bWxTYWZlKCc8ZGl2PnNvbWVTdHJpbmc8L2Rpdj4nKQogICAgYGBgCiAgCiAgICBAbWV0aG9kIGh0bWxTYWZlCiAgICBAZm9yIEBlbWJlci90ZW1wbGF0ZQogICAgQHN0YXRpYwogICAgQHJldHVybiB7U2FmZVN0cmluZ30gQSBzdHJpbmcgdGhhdCB3aWxsIG5vdCBiZSBIVE1MIGVzY2FwZWQgYnkgSGFuZGxlYmFycy4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gaHRtbFNhZmUoc3RyKSB7CiAgICBpZiAoc3RyID09PSBudWxsIHx8IHN0ciA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHN0ciA9ICcnOwogICAgfSBlbHNlIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJykgewogICAgICBzdHIgPSBTdHJpbmcoc3RyKTsKICAgIH0KCiAgICByZXR1cm4gbmV3IFNhZmVTdHJpbmcoc3RyKTsKICB9CiAgLyoqCiAgICBEZXRlY3RzIGlmIGEgc3RyaW5nIHdhcyBkZWNvcmF0ZWQgdXNpbmcgYGh0bWxTYWZlYC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGh0bWxTYWZlLCBpc0hUTUxTYWZlIH0gZnJvbSAnQGVtYmVyL3RlbXBsYXRlJzsKICAKICAgIHZhciBwbGFpblN0cmluZyA9ICdwbGFpbiBzdHJpbmcnLAogICAgICAgIHNhZmVTdHJpbmcgPSBodG1sU2FmZSgnPGRpdj5zb21lVmFsdWU8L2Rpdj4nKTsKICAKICAgIGlzSFRNTFNhZmUocGxhaW5TdHJpbmcpOyAvLyBmYWxzZQogICAgaXNIVE1MU2FmZShzYWZlU3RyaW5nKTsgIC8vIHRydWUKICAgIGBgYAogIAogICAgQG1ldGhvZCBpc0hUTUxTYWZlCiAgICBAZm9yIEBlbWJlci90ZW1wbGF0ZQogICAgQHN0YXRpYwogICAgQHJldHVybiB7Qm9vbGVhbn0gYHRydWVgIGlmIHRoZSBzdHJpbmcgd2FzIGRlY29yYXRlZCB3aXRoIGBodG1sU2FmZWAsIGBmYWxzZWAgb3RoZXJ3aXNlLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpc0hUTUxTYWZlKHN0cikgewogICAgcmV0dXJuIHN0ciAhPT0gbnVsbCAmJiB0eXBlb2Ygc3RyID09PSAnb2JqZWN0JyAmJiB0eXBlb2Ygc3RyLnRvSFRNTCA9PT0gJ2Z1bmN0aW9uJzsKICB9CiAgLyogZ2xvYmFscyBtb2R1bGUsIFVSTCAqLwoKCiAgdmFyIG5vZGVVUkw7CiAgdmFyIHBhcnNpbmdOb2RlOwoKICBmdW5jdGlvbiBpbnN0YWxsUHJvdG9jb2xGb3JVUkwoZW52aXJvbm1lbnQpIHsKICAgIHZhciBwcm90b2NvbDsKCiAgICBpZiAoX2Jyb3dzZXJFbnZpcm9ubWVudC5oYXNET00pIHsKICAgICAgcHJvdG9jb2wgPSBicm93c2VyUHJvdG9jb2xGb3JVUkwuY2FsbChlbnZpcm9ubWVudCwgJ2Zvb2JhcjpiYXonKTsKICAgIH0gLy8gVGVzdCB0byBzZWUgaWYgb3VyIERPTSBpbXBsZW1lbnRhdGlvbiBwYXJzZXMKICAgIC8vIGFuZCBub3JtYWxpemVzIFVSTHMuCgoKICAgIGlmIChwcm90b2NvbCA9PT0gJ2Zvb2JhcjonKSB7CiAgICAgIC8vIFN3YXAgaW4gdGhlIG1ldGhvZCB0aGF0IGRvZXNuJ3QgZG8gdGhpcyB0ZXN0IG5vdyB0aGF0CiAgICAgIC8vIHdlIGtub3cgaXQgd29ya3MuCiAgICAgIGVudmlyb25tZW50LnByb3RvY29sRm9yVVJMID0gYnJvd3NlclByb3RvY29sRm9yVVJMOwogICAgfSBlbHNlIGlmICh0eXBlb2YgVVJMID09PSAnb2JqZWN0JykgewogICAgICAvLyBVUkwgZ2xvYmFsbHkgcHJvdmlkZWQsIGxpa2VseSBmcm9tIEZhc3RCb290J3Mgc2FuZGJveAogICAgICBub2RlVVJMID0gVVJMOwogICAgICBlbnZpcm9ubWVudC5wcm90b2NvbEZvclVSTCA9IG5vZGVQcm90b2NvbEZvclVSTDsKICAgIH0gZWxzZSBpZiAodHlwZW9mIG1vZHVsZSAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtb2R1bGUucmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAvLyBPdGhlcndpc2UsIHdlIG5lZWQgdG8gZmFsbCBiYWNrIHRvIG91ciBvd24gVVJMIHBhcnNpbmcuCiAgICAgIC8vIEdsb2JhbCBgcmVxdWlyZWAgaXMgc2hhZG93ZWQgYnkgRW1iZXIncyBsb2FkZXIgc28gd2UgaGF2ZSB0byB1c2UgdGhlIGZ1bGx5CiAgICAgIC8vIHF1YWxpZmllZCBgbW9kdWxlLnJlcXVpcmVgLgogICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tcmVxdWlyZS1pbXBvcnRzCiAgICAgIG5vZGVVUkwgPSBtb2R1bGUucmVxdWlyZSgndXJsJyk7CiAgICAgIGVudmlyb25tZW50LnByb3RvY29sRm9yVVJMID0gbm9kZVByb3RvY29sRm9yVVJMOwogICAgfSBlbHNlIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgZmluZCB2YWxpZCBVUkwgcGFyc2luZyBtZWNoYW5pc20gZm9yIFVSTCBTYW5pdGl6YXRpb24nKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGJyb3dzZXJQcm90b2NvbEZvclVSTCh1cmwpIHsKICAgIGlmICghcGFyc2luZ05vZGUpIHsKICAgICAgcGFyc2luZ05vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7CiAgICB9CgogICAgcGFyc2luZ05vZGUuaHJlZiA9IHVybDsKICAgIHJldHVybiBwYXJzaW5nTm9kZS5wcm90b2NvbDsKICB9CgogIGZ1bmN0aW9uIG5vZGVQcm90b2NvbEZvclVSTCh1cmwpIHsKICAgIHZhciBwcm90b2NvbCA9IG51bGw7CgogICAgaWYgKHR5cGVvZiB1cmwgPT09ICdzdHJpbmcnKSB7CiAgICAgIHByb3RvY29sID0gbm9kZVVSTC5wYXJzZSh1cmwpLnByb3RvY29sOwogICAgfQoKICAgIHJldHVybiBwcm90b2NvbCA9PT0gbnVsbCA/ICc6JyA6IHByb3RvY29sOwogIH0KCiAgdmFyIEVudmlyb25tZW50JDEgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Vudmlyb25tZW50KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRW52aXJvbm1lbnQkMSwgX0Vudmlyb25tZW50KTsKCiAgICBmdW5jdGlvbiBFbnZpcm9ubWVudCQxKGluamVjdGlvbnMpIHsKICAgICAgdmFyIF90aGlzMTU7CgogICAgICBfdGhpczE1ID0gX0Vudmlyb25tZW50LmNhbGwodGhpcywgaW5qZWN0aW9ucykgfHwgdGhpczsKICAgICAgX3RoaXMxNS5pblRyYW5zYWN0aW9uID0gZmFsc2U7CiAgICAgIF90aGlzMTUub3duZXIgPSBpbmplY3Rpb25zW19vd25lci5PV05FUl07CiAgICAgIF90aGlzMTUuaXNJbnRlcmFjdGl2ZSA9IF90aGlzMTUub3duZXIubG9va3VwKCctZW52aXJvbm1lbnQ6bWFpbicpLmlzSW50ZXJhY3RpdmU7IC8vIGNhbiBiZSByZW1vdmVkIG9uY2UgaHR0cHM6Ly9naXRodWIuY29tL3RpbGRlaW8vZ2xpbW1lci9wdWxsLzMwNSBsYW5kcwoKICAgICAgX3RoaXMxNS5kZXN0cm95ZWRDb21wb25lbnRzID0gW107CiAgICAgIGluc3RhbGxQcm90b2NvbEZvclVSTCgoMCwgX2VtYmVyQmFiZWwuYXNzZXJ0VGhpc0luaXRpYWxpemVkKShfdGhpczE1KSk7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgX3RoaXMxNS5kZWJ1Z1N0YWNrID0gbmV3IERlYnVnU3RhY2skMSgpOwogICAgICB9CgogICAgICByZXR1cm4gX3RoaXMxNTsKICAgIH0KCiAgICBFbnZpcm9ubWVudCQxLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShvcHRpb25zKSB7CiAgICAgIHJldHVybiBuZXcgdGhpcyhvcHRpb25zKTsKICAgIH0gLy8gdGhpcyBnZXRzIGNsb2JiZXJlZCBieSBpbnN0YWxsUGxhdGZvcm1TcGVjaWZpY1Byb3RvY29sRm9yVVJMCiAgICAvLyBpdCByZWFsbHkgc2hvdWxkIGp1c3QgZGVsZWdhdGUgdG8gYSBwbGF0Zm9ybSBzcGVjaWZpYyBpbmplY3Rpb24KICAgIDsKCiAgICB2YXIgX3Byb3RvMjggPSBFbnZpcm9ubWVudCQxLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yOC5wcm90b2NvbEZvclVSTCA9IGZ1bmN0aW9uIHByb3RvY29sRm9yVVJMKHMpIHsKICAgICAgcmV0dXJuIHM7CiAgICB9OwoKICAgIF9wcm90bzI4LnRvQ29uZGl0aW9uYWxSZWZlcmVuY2UgPSBmdW5jdGlvbiB0b0NvbmRpdGlvbmFsUmVmZXJlbmNlKHJlZmVyZW5jZSkgewogICAgICByZXR1cm4gQ29uZGl0aW9uYWxSZWZlcmVuY2UkMS5jcmVhdGUocmVmZXJlbmNlKTsKICAgIH07CgogICAgX3Byb3RvMjguaXRlcmFibGVGb3IgPSBmdW5jdGlvbiBpdGVyYWJsZUZvcihyZWYsIGtleSkgewogICAgICByZXR1cm4gX2l0ZXJhYmxlRm9yKHJlZiwga2V5KTsKICAgIH07CgogICAgX3Byb3RvMjguc2NoZWR1bGVJbnN0YWxsTW9kaWZpZXIgPSBmdW5jdGlvbiBzY2hlZHVsZUluc3RhbGxNb2RpZmllcihtb2RpZmllciwgbWFuYWdlcikgewogICAgICBpZiAodGhpcy5pc0ludGVyYWN0aXZlKSB7CiAgICAgICAgX0Vudmlyb25tZW50LnByb3RvdHlwZS5zY2hlZHVsZUluc3RhbGxNb2RpZmllci5jYWxsKHRoaXMsIG1vZGlmaWVyLCBtYW5hZ2VyKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8yOC5zY2hlZHVsZVVwZGF0ZU1vZGlmaWVyID0gZnVuY3Rpb24gc2NoZWR1bGVVcGRhdGVNb2RpZmllcihtb2RpZmllciwgbWFuYWdlcikgewogICAgICBpZiAodGhpcy5pc0ludGVyYWN0aXZlKSB7CiAgICAgICAgX0Vudmlyb25tZW50LnByb3RvdHlwZS5zY2hlZHVsZVVwZGF0ZU1vZGlmaWVyLmNhbGwodGhpcywgbW9kaWZpZXIsIG1hbmFnZXIpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzI4LmRpZERlc3Ryb3kgPSBmdW5jdGlvbiBkaWREZXN0cm95KGRlc3Ryb3lhYmxlKSB7CiAgICAgIGRlc3Ryb3lhYmxlLmRlc3Ryb3koKTsKICAgIH07CgogICAgX3Byb3RvMjguYmVnaW4gPSBmdW5jdGlvbiBiZWdpbigpIHsKICAgICAgdGhpcy5pblRyYW5zYWN0aW9uID0gdHJ1ZTsKCiAgICAgIF9FbnZpcm9ubWVudC5wcm90b3R5cGUuYmVnaW4uY2FsbCh0aGlzKTsKICAgIH07CgogICAgX3Byb3RvMjguY29tbWl0ID0gZnVuY3Rpb24gY29tbWl0KCkgewogICAgICB2YXIgZGVzdHJveWVkQ29tcG9uZW50cyA9IHRoaXMuZGVzdHJveWVkQ29tcG9uZW50czsKICAgICAgdGhpcy5kZXN0cm95ZWRDb21wb25lbnRzID0gW107IC8vIGNvbXBvbmVudHMgcXVldWVkIGZvciBkZXN0cnVjdGlvbiBtdXN0IGJlIGRlc3Ryb3llZCBiZWZvcmUgZmlyaW5nCiAgICAgIC8vIGBkaWRDcmVhdGVgIHRvIHByZXZlbnQgZXJyb3JzIHdoZW4gcmVtb3ZpbmcgYW5kIGFkZGluZyBhIGNvbXBvbmVudAogICAgICAvLyB3aXRoIHRoZSBzYW1lIG5hbWUgKHdvdWxkIHRocm93IGFuIGVycm9yIHdoZW4gYWRkZWQgdG8gdmlldyByZWdpc3RyeSkKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVzdHJveWVkQ29tcG9uZW50cy5sZW5ndGg7IGkrKykgewogICAgICAgIGRlc3Ryb3llZENvbXBvbmVudHNbaV0uZGVzdHJveSgpOwogICAgICB9CgogICAgICB0cnkgewogICAgICAgIF9FbnZpcm9ubWVudC5wcm90b3R5cGUuY29tbWl0LmNhbGwodGhpcyk7CiAgICAgIH0gZmluYWxseSB7CiAgICAgICAgdGhpcy5pblRyYW5zYWN0aW9uID0gZmFsc2U7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEVudmlyb25tZW50JDE7CiAgfShfcnVudGltZTIuRW52aXJvbm1lbnQpOwoKICBfZXhwb3J0cy5FbnZpcm9ubWVudCA9IEVudmlyb25tZW50JDE7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICB2YXIgU3R5bGVBdHRyaWJ1dGVNYW5hZ2VyID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uIChfU2ltcGxlRHluYW1pY0F0dHJpYnUpIHsKICAgICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFN0eWxlQXR0cmlidXRlTWFuYWdlciwgX1NpbXBsZUR5bmFtaWNBdHRyaWJ1KTsKCiAgICAgIGZ1bmN0aW9uIFN0eWxlQXR0cmlidXRlTWFuYWdlcigpIHsKICAgICAgICByZXR1cm4gX1NpbXBsZUR5bmFtaWNBdHRyaWJ1LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgICAgfQoKICAgICAgdmFyIF9wcm90bzI5ID0gU3R5bGVBdHRyaWJ1dGVNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICAgIF9wcm90bzI5LnNldCA9IGZ1bmN0aW9uIHNldChkb20sIHZhbHVlJCQxLCBlbnYpIHsKICAgICAgICAoZmFsc2UgJiYgKDAsIF9kZWJ1Zy53YXJuKSgoMCwgX3ZpZXdzLmNvbnN0cnVjdFN0eWxlRGVwcmVjYXRpb25NZXNzYWdlKSh2YWx1ZSQkMSksIGZ1bmN0aW9uICgpIHsKICAgICAgICAgIGlmICh2YWx1ZSQkMSA9PT0gbnVsbCB8fCB2YWx1ZSQkMSA9PT0gdW5kZWZpbmVkIHx8IGlzSFRNTFNhZmUodmFsdWUkJDEpKSB7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9KCksIHsKICAgICAgICAgIGlkOiAnZW1iZXItaHRtbGJhcnMuc3R5bGUteHNzLXdhcm5pbmcnCiAgICAgICAgfSkpOwoKICAgICAgICBfU2ltcGxlRHluYW1pY0F0dHJpYnUucHJvdG90eXBlLnNldC5jYWxsKHRoaXMsIGRvbSwgdmFsdWUkJDEsIGVudik7CiAgICAgIH07CgogICAgICBfcHJvdG8yOS51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUodmFsdWUkJDEsIGVudikgewogICAgICAgIChmYWxzZSAmJiAoMCwgX2RlYnVnLndhcm4pKCgwLCBfdmlld3MuY29uc3RydWN0U3R5bGVEZXByZWNhdGlvbk1lc3NhZ2UpKHZhbHVlJCQxKSwgZnVuY3Rpb24gKCkgewogICAgICAgICAgaWYgKHZhbHVlJCQxID09PSBudWxsIHx8IHZhbHVlJCQxID09PSB1bmRlZmluZWQgfHwgaXNIVE1MU2FmZSh2YWx1ZSQkMSkpIHsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0oKSwgewogICAgICAgICAgaWQ6ICdlbWJlci1odG1sYmFycy5zdHlsZS14c3Mtd2FybmluZycKICAgICAgICB9KSk7CgogICAgICAgIF9TaW1wbGVEeW5hbWljQXR0cmlidS5wcm90b3R5cGUudXBkYXRlLmNhbGwodGhpcywgdmFsdWUkJDEsIGVudik7CiAgICAgIH07CgogICAgICByZXR1cm4gU3R5bGVBdHRyaWJ1dGVNYW5hZ2VyOwogICAgfShfcnVudGltZTIuU2ltcGxlRHluYW1pY0F0dHJpYnV0ZSk7CgogICAgRW52aXJvbm1lbnQkMS5wcm90b3R5cGUuYXR0cmlidXRlRm9yID0gZnVuY3Rpb24gKGVsZW1lbnQsIGF0dHJpYnV0ZSwgaXNUcnVzdGluZywgbmFtZXNwYWNlKSB7CiAgICAgIGlmIChhdHRyaWJ1dGUgPT09ICdzdHlsZScgJiYgIWlzVHJ1c3RpbmcpIHsKICAgICAgICByZXR1cm4gbmV3IFN0eWxlQXR0cmlidXRlTWFuYWdlcih7CiAgICAgICAgICBlbGVtZW50OiBlbGVtZW50LAogICAgICAgICAgbmFtZTogYXR0cmlidXRlLAogICAgICAgICAgbmFtZXNwYWNlOiBuYW1lc3BhY2UKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9ydW50aW1lMi5FbnZpcm9ubWVudC5wcm90b3R5cGUuYXR0cmlidXRlRm9yLmNhbGwodGhpcywgZWxlbWVudCwgYXR0cmlidXRlLCBpc1RydXN0aW5nLCBuYW1lc3BhY2UpOwogICAgfTsKICB9IC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTptYXgtbGluZS1sZW5ndGgKICAvLyBodHRwczovL2dpdGh1Yi5jb20vZ2xpbW1lcmpzL2dsaW1tZXItdm0vYmxvYi92MC4yNC4wLWJldGEuNC9wYWNrYWdlcy8lNDBnbGltbWVyL3J1bnRpbWUvbGliL2NvbXBvbmVudC9pbnRlcmZhY2VzLnRzI0wyMQoKCiAgdmFyIEFic3RyYWN0TWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEFic3RyYWN0TWFuYWdlcigpIHsKICAgICAgdGhpcy5kZWJ1Z1N0YWNrID0gdW5kZWZpbmVkOwogICAgfQoKICAgIHZhciBfcHJvdG8zMCA9IEFic3RyYWN0TWFuYWdlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMzAucHJlcGFyZUFyZ3MgPSBmdW5jdGlvbiBwcmVwYXJlQXJncyhfc3RhdGUsIF9hcmdzKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfTsKCiAgICBfcHJvdG8zMC5kaWRDcmVhdGVFbGVtZW50ID0gZnVuY3Rpb24gZGlkQ3JlYXRlRWxlbWVudChfY29tcG9uZW50LCBfZWxlbWVudCwgX29wZXJhdGlvbnMpIHt9IC8vIG5vb3AKICAgIC8vIGluaGVyaXRvcnMgc2hvdWxkIGFsc28gY2FsbCBgdGhpcy5kZWJ1Z1N0YWNrLnBvcCgpYCB0bwogICAgLy8gZW5zdXJlIHRoZSByZXJlbmRlcmluZyBhc3NlcnRpb24gbWVzc2FnZXMgYXJlIHByb3Blcmx5CiAgICAvLyBtYWludGFpbmVkCiAgICA7CgogICAgX3Byb3RvMzAuZGlkUmVuZGVyTGF5b3V0ID0gZnVuY3Rpb24gZGlkUmVuZGVyTGF5b3V0KF9jb21wb25lbnQsIF9ib3VuZHMpIHsvLyBub29wCiAgICB9OwoKICAgIF9wcm90bzMwLmRpZENyZWF0ZSA9IGZ1bmN0aW9uIGRpZENyZWF0ZShfYnVja2V0KSB7fSAvLyBub29wCiAgICAvLyBpbmhlcml0b3JzIHNob3VsZCBhbHNvIGNhbGwgYHRoaXMuX3B1c2hUb0RlYnVnU3RhY2tgCiAgICAvLyB0byBlbnN1cmUgdGhlIHJlcmVuZGVyaW5nIGFzc2VydGlvbiBtZXNzYWdlcyBhcmUKICAgIC8vIHByb3Blcmx5IG1haW50YWluZWQKICAgIDsKCiAgICBfcHJvdG8zMC51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoX2J1Y2tldCwgX2R5bmFtaWNTY29wZSkge30gLy8gbm9vcAogICAgLy8gaW5oZXJpdG9ycyBzaG91bGQgYWxzbyBjYWxsIGB0aGlzLmRlYnVnU3RhY2sucG9wKClgIHRvCiAgICAvLyBlbnN1cmUgdGhlIHJlcmVuZGVyaW5nIGFzc2VydGlvbiBtZXNzYWdlcyBhcmUgcHJvcGVybHkKICAgIC8vIG1haW50YWluZWQKICAgIDsKCiAgICBfcHJvdG8zMC5kaWRVcGRhdGVMYXlvdXQgPSBmdW5jdGlvbiBkaWRVcGRhdGVMYXlvdXQoX2J1Y2tldCwgX2JvdW5kcykgey8vIG5vb3AKICAgIH07CgogICAgX3Byb3RvMzAuZGlkVXBkYXRlID0gZnVuY3Rpb24gZGlkVXBkYXRlKF9idWNrZXQpIHsvLyBub29wCiAgICB9OwoKICAgIHJldHVybiBBYnN0cmFjdE1hbmFnZXI7CiAgfSgpOwoKICBfZXhwb3J0cy5BYnN0cmFjdENvbXBvbmVudE1hbmFnZXIgPSBBYnN0cmFjdE1hbmFnZXI7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICBBYnN0cmFjdE1hbmFnZXIucHJvdG90eXBlLl9wdXNoVG9EZWJ1Z1N0YWNrID0gZnVuY3Rpb24gKG5hbWUsIGVudmlyb25tZW50KSB7CiAgICAgIHRoaXMuZGVidWdTdGFjayA9IGVudmlyb25tZW50LmRlYnVnU3RhY2s7CiAgICAgIHRoaXMuZGVidWdTdGFjay5wdXNoKG5hbWUpOwogICAgfTsKCiAgICBBYnN0cmFjdE1hbmFnZXIucHJvdG90eXBlLl9wdXNoRW5naW5lVG9EZWJ1Z1N0YWNrID0gZnVuY3Rpb24gKG5hbWUsIGVudmlyb25tZW50KSB7CiAgICAgIHRoaXMuZGVidWdTdGFjayA9IGVudmlyb25tZW50LmRlYnVnU3RhY2s7CiAgICAgIHRoaXMuZGVidWdTdGFjay5wdXNoRW5naW5lKG5hbWUpOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIGluc3RydW1lbnRhdGlvblBheWxvYWQoZGVmKSB7CiAgICByZXR1cm4gewogICAgICBvYmplY3Q6IGRlZi5uYW1lICsgIjoiICsgZGVmLm91dGxldAogICAgfTsKICB9CgogIHZhciBDQVBBQklMSVRJRVMgPSB7CiAgICBkeW5hbWljTGF5b3V0OiBmYWxzZSwKICAgIGR5bmFtaWNUYWc6IGZhbHNlLAogICAgcHJlcGFyZUFyZ3M6IGZhbHNlLAogICAgY3JlYXRlQXJnczogZmFsc2UsCiAgICBhdHRyaWJ1dGVIb29rOiBmYWxzZSwKICAgIGVsZW1lbnRIb29rOiBmYWxzZSwKICAgIGNyZWF0ZUNhbGxlcjogdHJ1ZSwKICAgIGR5bmFtaWNTY29wZTogdHJ1ZSwKICAgIHVwZGF0ZUhvb2s6IGZhbHNlLAogICAgY3JlYXRlSW5zdGFuY2U6IHRydWUKICB9OwoKICB2YXIgT3V0bGV0Q29tcG9uZW50TWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQWJzdHJhY3RNYW5hZ2VyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoT3V0bGV0Q29tcG9uZW50TWFuYWdlciwgX0Fic3RyYWN0TWFuYWdlcik7CgogICAgZnVuY3Rpb24gT3V0bGV0Q29tcG9uZW50TWFuYWdlcigpIHsKICAgICAgcmV0dXJuIF9BYnN0cmFjdE1hbmFnZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8zMSA9IE91dGxldENvbXBvbmVudE1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzMxLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShlbnZpcm9ubWVudCwgZGVmaW5pdGlvbiwgX2FyZ3MsIGR5bmFtaWNTY29wZSkgewogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgdGhpcy5fcHVzaFRvRGVidWdTdGFjaygidGVtcGxhdGU6IiArIGRlZmluaXRpb24udGVtcGxhdGUucmVmZXJyZXIubW9kdWxlTmFtZSwgZW52aXJvbm1lbnQpOwogICAgICB9CgogICAgICBkeW5hbWljU2NvcGUub3V0bGV0U3RhdGUgPSBkZWZpbml0aW9uLnJlZjsKICAgICAgdmFyIGNvbnRyb2xsZXIgPSBkZWZpbml0aW9uLmNvbnRyb2xsZXI7CiAgICAgIHZhciBzZWxmID0gY29udHJvbGxlciA9PT0gdW5kZWZpbmVkID8gX3J1bnRpbWUyLlVOREVGSU5FRF9SRUZFUkVOQ0UgOiBuZXcgUm9vdFJlZmVyZW5jZShjb250cm9sbGVyKTsKICAgICAgcmV0dXJuIHsKICAgICAgICBzZWxmOiBzZWxmLAogICAgICAgIGZpbmFsaXplOiAoMCwgX2luc3RydW1lbnRhdGlvbi5faW5zdHJ1bWVudFN0YXJ0KSgncmVuZGVyLm91dGxldCcsIGluc3RydW1lbnRhdGlvblBheWxvYWQsIGRlZmluaXRpb24pCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzMxLmdldExheW91dCA9IGZ1bmN0aW9uIGdldExheW91dChfcmVmLCBfcmVzb2x2ZXIpIHsKICAgICAgdmFyIHRlbXBsYXRlID0gX3JlZi50ZW1wbGF0ZTsKICAgICAgLy8gVGhlIHJvdXRlciBoYXMgYWxyZWFkeSByZXNvbHZlZCB0aGUgdGVtcGxhdGUKICAgICAgdmFyIGxheW91dCA9IHRlbXBsYXRlLmFzTGF5b3V0KCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiBsYXlvdXQuY29tcGlsZSgpLAogICAgICAgIHN5bWJvbFRhYmxlOiBsYXlvdXQuc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvMzEuZ2V0Q2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gZ2V0Q2FwYWJpbGl0aWVzKCkgewogICAgICByZXR1cm4gQ0FQQUJJTElUSUVTOwogICAgfTsKCiAgICBfcHJvdG8zMS5nZXRTZWxmID0gZnVuY3Rpb24gZ2V0U2VsZihfcmVmMikgewogICAgICB2YXIgc2VsZiA9IF9yZWYyLnNlbGY7CiAgICAgIHJldHVybiBzZWxmOwogICAgfTsKCiAgICBfcHJvdG8zMS5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoKSB7CiAgICAgIC8vIGFuIG91dGxldCBoYXMgbm8gaG9va3MKICAgICAgcmV0dXJuIF9yZWZlcmVuY2UuQ09OU1RBTlRfVEFHOwogICAgfTsKCiAgICBfcHJvdG8zMS5kaWRSZW5kZXJMYXlvdXQgPSBmdW5jdGlvbiBkaWRSZW5kZXJMYXlvdXQoc3RhdGUpIHsKICAgICAgc3RhdGUuZmluYWxpemUoKTsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICB0aGlzLmRlYnVnU3RhY2sucG9wKCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMzEuZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3IoKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfTsKCiAgICByZXR1cm4gT3V0bGV0Q29tcG9uZW50TWFuYWdlcjsKICB9KEFic3RyYWN0TWFuYWdlcik7CgogIHZhciBPVVRMRVRfTUFOQUdFUiA9IG5ldyBPdXRsZXRDb21wb25lbnRNYW5hZ2VyKCk7CgogIHZhciBPdXRsZXRDb21wb25lbnREZWZpbml0aW9uID0gZnVuY3Rpb24gT3V0bGV0Q29tcG9uZW50RGVmaW5pdGlvbihzdGF0ZSwgbWFuYWdlcikgewogICAgaWYgKG1hbmFnZXIgPT09IHZvaWQgMCkgewogICAgICBtYW5hZ2VyID0gT1VUTEVUX01BTkFHRVI7CiAgICB9CgogICAgdGhpcy5zdGF0ZSA9IHN0YXRlOwogICAgdGhpcy5tYW5hZ2VyID0gbWFuYWdlcjsKICB9OwoKICBmdW5jdGlvbiBjcmVhdGVSb290T3V0bGV0KG91dGxldFZpZXcpIHsKICAgIGlmIChfZW52aXJvbm1lbnQyLkVOVi5fQVBQTElDQVRJT05fVEVNUExBVEVfV1JBUFBFUikgewogICAgICB2YXIgV1JBUFBFRF9DQVBBQklMSVRJRVMgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBDQVBBQklMSVRJRVMsIHsKICAgICAgICBkeW5hbWljVGFnOiB0cnVlLAogICAgICAgIGVsZW1lbnRIb29rOiB0cnVlCiAgICAgIH0pOwoKICAgICAgdmFyIFdyYXBwZWRPdXRsZXRDb21wb25lbnRNYW5hZ2VyID0KICAgICAgLyojX19QVVJFX18qLwogICAgICBmdW5jdGlvbiAoX091dGxldENvbXBvbmVudE1hbmFnKSB7CiAgICAgICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFdyYXBwZWRPdXRsZXRDb21wb25lbnRNYW5hZ2VyLCBfT3V0bGV0Q29tcG9uZW50TWFuYWcpOwoKICAgICAgICBmdW5jdGlvbiBXcmFwcGVkT3V0bGV0Q29tcG9uZW50TWFuYWdlcigpIHsKICAgICAgICAgIHJldHVybiBfT3V0bGV0Q29tcG9uZW50TWFuYWcuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICAgIH0KCiAgICAgICAgdmFyIF9wcm90bzMyID0gV3JhcHBlZE91dGxldENvbXBvbmVudE1hbmFnZXIucHJvdG90eXBlOwoKICAgICAgICBfcHJvdG8zMi5nZXRUYWdOYW1lID0gZnVuY3Rpb24gZ2V0VGFnTmFtZShfY29tcG9uZW50KSB7CiAgICAgICAgICByZXR1cm4gJ2Rpdic7CiAgICAgICAgfTsKCiAgICAgICAgX3Byb3RvMzIuZ2V0TGF5b3V0ID0gZnVuY3Rpb24gZ2V0TGF5b3V0KHN0YXRlKSB7CiAgICAgICAgICAvLyBUaGUgcm91dGVyIGhhcyBhbHJlYWR5IHJlc29sdmVkIHRoZSB0ZW1wbGF0ZQogICAgICAgICAgdmFyIHRlbXBsYXRlID0gc3RhdGUudGVtcGxhdGU7CiAgICAgICAgICB2YXIgbGF5b3V0ID0gdGVtcGxhdGUuYXNXcmFwcGVkTGF5b3V0KCk7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBoYW5kbGU6IGxheW91dC5jb21waWxlKCksCiAgICAgICAgICAgIHN5bWJvbFRhYmxlOiBsYXlvdXQuc3ltYm9sVGFibGUKICAgICAgICAgIH07CiAgICAgICAgfTsKCiAgICAgICAgX3Byb3RvMzIuZ2V0Q2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gZ2V0Q2FwYWJpbGl0aWVzKCkgewogICAgICAgICAgcmV0dXJuIFdSQVBQRURfQ0FQQUJJTElUSUVTOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzMyLmRpZENyZWF0ZUVsZW1lbnQgPSBmdW5jdGlvbiBkaWRDcmVhdGVFbGVtZW50KGNvbXBvbmVudCwgZWxlbWVudCwgX29wZXJhdGlvbnMpIHsKICAgICAgICAgIC8vIHRvIGFkZCBHVUlEIGlkIGFuZCBjbGFzcwogICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ2VtYmVyLXZpZXcnKTsKICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdpZCcsICgwLCBfdXRpbHMuZ3VpZEZvcikoY29tcG9uZW50KSk7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIFdyYXBwZWRPdXRsZXRDb21wb25lbnRNYW5hZ2VyOwogICAgICB9KE91dGxldENvbXBvbmVudE1hbmFnZXIpOwoKICAgICAgdmFyIFdSQVBQRURfT1VUTEVUX01BTkFHRVIgPSBuZXcgV3JhcHBlZE91dGxldENvbXBvbmVudE1hbmFnZXIoKTsKICAgICAgcmV0dXJuIG5ldyBPdXRsZXRDb21wb25lbnREZWZpbml0aW9uKG91dGxldFZpZXcuc3RhdGUsIFdSQVBQRURfT1VUTEVUX01BTkFHRVIpOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG5ldyBPdXRsZXRDb21wb25lbnREZWZpbml0aW9uKG91dGxldFZpZXcuc3RhdGUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gTk9PUCgpIHt9CiAgLyoqCiAgICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBSZXByZXNlbnRzIHRoZSBpbnRlcm5hbCBzdGF0ZSBvZiB0aGUgY29tcG9uZW50LgogIAogICAgQGNsYXNzIENvbXBvbmVudFN0YXRlQnVja2V0CiAgICBAcHJpdmF0ZQogICovCgoKICB2YXIgQ29tcG9uZW50U3RhdGVCdWNrZXQgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDb21wb25lbnRTdGF0ZUJ1Y2tldChlbnZpcm9ubWVudCwgY29tcG9uZW50LCBhcmdzLCBmaW5hbGl6ZXIsIGhhc1dyYXBwZWRFbGVtZW50KSB7CiAgICAgIHRoaXMuZW52aXJvbm1lbnQgPSBlbnZpcm9ubWVudDsKICAgICAgdGhpcy5jb21wb25lbnQgPSBjb21wb25lbnQ7CiAgICAgIHRoaXMuYXJncyA9IGFyZ3M7CiAgICAgIHRoaXMuZmluYWxpemVyID0gZmluYWxpemVyOwogICAgICB0aGlzLmhhc1dyYXBwZWRFbGVtZW50ID0gaGFzV3JhcHBlZEVsZW1lbnQ7CiAgICAgIHRoaXMuY2xhc3NSZWYgPSBudWxsOwogICAgICB0aGlzLmNsYXNzUmVmID0gbnVsbDsKICAgICAgdGhpcy5hcmdzUmV2aXNpb24gPSBhcmdzID09PSBudWxsID8gMCA6ICgwLCBfcmVmZXJlbmNlLnZhbHVlKShhcmdzLnRhZyk7CiAgICB9CgogICAgdmFyIF9wcm90bzMzID0gQ29tcG9uZW50U3RhdGVCdWNrZXQucHJvdG90eXBlOwoKICAgIF9wcm90bzMzLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICB2YXIgY29tcG9uZW50ID0gdGhpcy5jb21wb25lbnQsCiAgICAgICAgICBlbnZpcm9ubWVudCA9IHRoaXMuZW52aXJvbm1lbnQ7CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCd3aWxsRGVzdHJveUVsZW1lbnQnKTsKICAgICAgICBjb21wb25lbnQudHJpZ2dlcignd2lsbENsZWFyUmVuZGVyJyk7CiAgICAgICAgdmFyIGVsZW1lbnQgPSAoMCwgX3ZpZXdzLmdldFZpZXdFbGVtZW50KShjb21wb25lbnQpOwoKICAgICAgICBpZiAoZWxlbWVudCkgewogICAgICAgICAgKDAsIF92aWV3cy5jbGVhckVsZW1lbnRWaWV3KShlbGVtZW50KTsKICAgICAgICAgICgwLCBfdmlld3MuY2xlYXJWaWV3RWxlbWVudCkoY29tcG9uZW50KTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGVudmlyb25tZW50LmRlc3Ryb3llZENvbXBvbmVudHMucHVzaChjb21wb25lbnQpOwogICAgfTsKCiAgICBfcHJvdG8zMy5maW5hbGl6ZSA9IGZ1bmN0aW9uIGZpbmFsaXplKCkgewogICAgICB2YXIgZmluYWxpemVyID0gdGhpcy5maW5hbGl6ZXI7CiAgICAgIGZpbmFsaXplcigpOwogICAgICB0aGlzLmZpbmFsaXplciA9IE5PT1A7CiAgICB9OwoKICAgIHJldHVybiBDb21wb25lbnRTdGF0ZUJ1Y2tldDsKICB9KCk7CgogIGZ1bmN0aW9uIHJlZmVyZW5jZUZvcktleShjb21wb25lbnQsIGtleSkgewogICAgcmV0dXJuIGNvbXBvbmVudFtST09UX1JFRl0uZ2V0KGtleSk7CiAgfQoKICBmdW5jdGlvbiByZWZlcmVuY2VGb3JQYXJ0cyhjb21wb25lbnQsIHBhcnRzKSB7CiAgICB2YXIgaXNBdHRycyA9IHBhcnRzWzBdID09PSAnYXR0cnMnOyAvLyBUT0RPIGRlcHJlY2F0ZSB0aGlzCgogICAgaWYgKGlzQXR0cnMpIHsKICAgICAgcGFydHMuc2hpZnQoKTsKCiAgICAgIGlmIChwYXJ0cy5sZW5ndGggPT09IDEpIHsKICAgICAgICByZXR1cm4gcmVmZXJlbmNlRm9yS2V5KGNvbXBvbmVudCwgcGFydHNbMF0pOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJlZmVyZW5jZUZyb21QYXJ0cyhjb21wb25lbnRbUk9PVF9SRUZdLCBwYXJ0cyk7CiAgfSAvLyBUT0RPIHdlIHNob3VsZCBwcm9iYWJseSBkbyB0aGlzIHRyYW5zZm9ybSBhdCBidWlsZCB0aW1lCgoKICBmdW5jdGlvbiB3cmFwQ29tcG9uZW50Q2xhc3NBdHRyaWJ1dGUoaGFzaCkgewogICAgaWYgKGhhc2ggPT09IG51bGwpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBrZXlzID0gaGFzaFswXSwKICAgICAgICB2YWx1ZXMgPSBoYXNoWzFdOwogICAgdmFyIGluZGV4ID0ga2V5cyA9PT0gbnVsbCA/IC0xIDoga2V5cy5pbmRleE9mKCdjbGFzcycpOwoKICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgdmFyIHZhbHVlJCQxID0gdmFsdWVzW2luZGV4XTsKCiAgICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZSQkMSkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciB0eXBlID0gdmFsdWUkJDFbMF07CgogICAgICBpZiAodHlwZSA9PT0gX3dpcmVGb3JtYXQuT3BzLkdldCB8fCB0eXBlID09PSBfd2lyZUZvcm1hdC5PcHMuTWF5YmVMb2NhbCkgewogICAgICAgIHZhciBwYXRoID0gdmFsdWUkJDFbdmFsdWUkJDEubGVuZ3RoIC0gMV07CiAgICAgICAgdmFyIHByb3BOYW1lID0gcGF0aFtwYXRoLmxlbmd0aCAtIDFdOwogICAgICAgIHZhbHVlc1tpbmRleF0gPSBbX3dpcmVGb3JtYXQuT3BzLkhlbHBlciwgJy1jbGFzcycsIFt2YWx1ZSQkMSwgcHJvcE5hbWVdLCBudWxsXTsKICAgICAgfQogICAgfQogIH0KCiAgdmFyIEF0dHJpYnV0ZUJpbmRpbmcgPSB7CiAgICBwYXJzZTogZnVuY3Rpb24gcGFyc2UobWljcm9zeW50YXgpIHsKICAgICAgdmFyIGNvbG9uSW5kZXggPSBtaWNyb3N5bnRheC5pbmRleE9mKCc6Jyk7CgogICAgICBpZiAoY29sb25JbmRleCA9PT0gLTEpIHsKICAgICAgICAoZmFsc2UgJiYgIShtaWNyb3N5bnRheCAhPT0gJ2NsYXNzJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgY2Fubm90IHVzZSBjbGFzcyBhcyBhbiBhdHRyaWJ1dGVCaW5kaW5nLCB1c2UgY2xhc3NOYW1lQmluZGluZ3MgaW5zdGVhZC4nLCBtaWNyb3N5bnRheCAhPT0gJ2NsYXNzJykpOwogICAgICAgIHJldHVybiBbbWljcm9zeW50YXgsIG1pY3Jvc3ludGF4LCB0cnVlXTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgcHJvcCA9IG1pY3Jvc3ludGF4LnN1YnN0cmluZygwLCBjb2xvbkluZGV4KTsKICAgICAgICB2YXIgYXR0cmlidXRlID0gbWljcm9zeW50YXguc3Vic3RyaW5nKGNvbG9uSW5kZXggKyAxKTsKICAgICAgICAoZmFsc2UgJiYgIShhdHRyaWJ1dGUgIT09ICdjbGFzcycpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGNhbm5vdCB1c2UgY2xhc3MgYXMgYW4gYXR0cmlidXRlQmluZGluZywgdXNlIGNsYXNzTmFtZUJpbmRpbmdzIGluc3RlYWQuJywgYXR0cmlidXRlICE9PSAnY2xhc3MnKSk7CiAgICAgICAgcmV0dXJuIFtwcm9wLCBhdHRyaWJ1dGUsIGZhbHNlXTsKICAgICAgfQogICAgfSwKICAgIGluc3RhbGw6IGZ1bmN0aW9uIGluc3RhbGwoX2VsZW1lbnQsIGNvbXBvbmVudCwgcGFyc2VkLCBvcGVyYXRpb25zKSB7CiAgICAgIHZhciBwcm9wID0gcGFyc2VkWzBdLAogICAgICAgICAgYXR0cmlidXRlID0gcGFyc2VkWzFdLAogICAgICAgICAgaXNTaW1wbGUgPSBwYXJzZWRbMl07CgogICAgICBpZiAoYXR0cmlidXRlID09PSAnaWQnKSB7CiAgICAgICAgdmFyIGVsZW1lbnRJZCA9ICgwLCBfbWV0YWwuZ2V0KShjb21wb25lbnQsIHByb3ApOwoKICAgICAgICBpZiAoZWxlbWVudElkID09PSB1bmRlZmluZWQgfHwgZWxlbWVudElkID09PSBudWxsKSB7CiAgICAgICAgICBlbGVtZW50SWQgPSBjb21wb25lbnQuZWxlbWVudElkOwogICAgICAgIH0KCiAgICAgICAgZWxlbWVudElkID0gX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUoZWxlbWVudElkKTsKICAgICAgICBvcGVyYXRpb25zLnNldEF0dHJpYnV0ZSgnaWQnLCBlbGVtZW50SWQsIHRydWUsIG51bGwpOyAvLyBvcGVyYXRpb25zLmFkZFN0YXRpY0F0dHJpYnV0ZShlbGVtZW50LCAnaWQnLCBlbGVtZW50SWQpOwoKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBpc1BhdGggPSBwcm9wLmluZGV4T2YoJy4nKSA+IC0xOwogICAgICB2YXIgcmVmZXJlbmNlID0gaXNQYXRoID8gcmVmZXJlbmNlRm9yUGFydHMoY29tcG9uZW50LCBwcm9wLnNwbGl0KCcuJykpIDogcmVmZXJlbmNlRm9yS2V5KGNvbXBvbmVudCwgcHJvcCk7CiAgICAgIChmYWxzZSAmJiAhKCEoaXNTaW1wbGUgJiYgaXNQYXRoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJJbGxlZ2FsIGF0dHJpYnV0ZUJpbmRpbmc6ICciICsgcHJvcCArICInIGlzIG5vdCBhIHZhbGlkIGF0dHJpYnV0ZSBuYW1lLiIsICEoaXNTaW1wbGUgJiYgaXNQYXRoKSkpOwoKICAgICAgaWYgKGF0dHJpYnV0ZSA9PT0gJ3N0eWxlJykgewogICAgICAgIHJlZmVyZW5jZSA9IG5ldyBTdHlsZUJpbmRpbmdSZWZlcmVuY2UocmVmZXJlbmNlLCByZWZlcmVuY2VGb3JLZXkoY29tcG9uZW50LCAnaXNWaXNpYmxlJykpOwogICAgICB9CgogICAgICBvcGVyYXRpb25zLnNldEF0dHJpYnV0ZShhdHRyaWJ1dGUsIHJlZmVyZW5jZSwgZmFsc2UsIG51bGwpOyAvLyBvcGVyYXRpb25zLmFkZER5bmFtaWNBdHRyaWJ1dGUoZWxlbWVudCwgYXR0cmlidXRlLCByZWZlcmVuY2UsIGZhbHNlKTsKICAgIH0KICB9OwogIHZhciBESVNQTEFZX05PTkUgPSAnZGlzcGxheTogbm9uZTsnOwogIHZhciBTQUZFX0RJU1BMQVlfTk9ORSA9IGh0bWxTYWZlKERJU1BMQVlfTk9ORSk7CgogIHZhciBTdHlsZUJpbmRpbmdSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NhY2hlZFJlZmVyZW5jZSkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFN0eWxlQmluZGluZ1JlZmVyZW5jZSwgX0NhY2hlZFJlZmVyZW5jZSk7CgogICAgZnVuY3Rpb24gU3R5bGVCaW5kaW5nUmVmZXJlbmNlKGlubmVyLCBpc1Zpc2libGUpIHsKICAgICAgdmFyIF90aGlzMTY7CgogICAgICBfdGhpczE2ID0gX0NhY2hlZFJlZmVyZW5jZS5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMTYuaW5uZXIgPSBpbm5lcjsKICAgICAgX3RoaXMxNi5pc1Zpc2libGUgPSBpc1Zpc2libGU7CiAgICAgIF90aGlzMTYudGFnID0gKDAsIF9yZWZlcmVuY2UuY29tYmluZSkoW2lubmVyLnRhZywgaXNWaXNpYmxlLnRhZ10pOwogICAgICByZXR1cm4gX3RoaXMxNjsKICAgIH0KCiAgICB2YXIgX3Byb3RvMzQgPSBTdHlsZUJpbmRpbmdSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzM0LmNvbXB1dGUgPSBmdW5jdGlvbiBjb21wdXRlKCkgewogICAgICB2YXIgdmFsdWUkJDEgPSB0aGlzLmlubmVyLnZhbHVlKCk7CiAgICAgIHZhciBpc1Zpc2libGUgPSB0aGlzLmlzVmlzaWJsZS52YWx1ZSgpOwoKICAgICAgaWYgKGlzVmlzaWJsZSAhPT0gZmFsc2UpIHsKICAgICAgICByZXR1cm4gdmFsdWUkJDE7CiAgICAgIH0gZWxzZSBpZiAoIXZhbHVlJCQxKSB7CiAgICAgICAgcmV0dXJuIFNBRkVfRElTUExBWV9OT05FOwogICAgICB9IGVsc2UgewogICAgICAgIHZhciBzdHlsZSA9IHZhbHVlJCQxICsgJyAnICsgRElTUExBWV9OT05FOwogICAgICAgIHJldHVybiBpc0hUTUxTYWZlKHZhbHVlJCQxKSA/IGh0bWxTYWZlKHN0eWxlKSA6IHN0eWxlOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBTdHlsZUJpbmRpbmdSZWZlcmVuY2U7CiAgfShfcmVmZXJlbmNlLkNhY2hlZFJlZmVyZW5jZSk7CgogIHZhciBJc1Zpc2libGVCaW5kaW5nID0gewogICAgaW5zdGFsbDogZnVuY3Rpb24gaW5zdGFsbChfZWxlbWVudCwgY29tcG9uZW50LCBvcGVyYXRpb25zKSB7CiAgICAgIG9wZXJhdGlvbnMuc2V0QXR0cmlidXRlKCdzdHlsZScsICgwLCBfcmVmZXJlbmNlLm1hcCkocmVmZXJlbmNlRm9yS2V5KGNvbXBvbmVudCwgJ2lzVmlzaWJsZScpLCB0aGlzLm1hcFN0eWxlVmFsdWUpLCBmYWxzZSwgbnVsbCk7IC8vIC8vIHRoZSB1cHN0cmVhbSB0eXBlIGZvciBhZGREeW5hbWljQXR0cmlidXRlJ3MgYHZhbHVlYCBhcmd1bWVudAogICAgICAvLyAvLyBhcHBlYXJzIHRvIGJlIGluY29ycmVjdC4gSXQgaXMgY3VycmVudGx5IGEgUmVmZXJlbmNlPHN0cmluZz4sIEkKICAgICAgLy8gLy8gdGhpbmsgaXQgc2hvdWxkIGJlIGEgUmVmZXJlbmNlPHN0cmluZ3xudWxsPi4KICAgICAgLy8gb3BlcmF0aW9ucy5hZGREeW5hbWljQXR0cmlidXRlKGVsZW1lbnQsICdzdHlsZScsIHJlZiBhcyBhbnkgYXMgUmVmZXJlbmNlPHN0cmluZz4sIGZhbHNlKTsKICAgIH0sCiAgICBtYXBTdHlsZVZhbHVlOiBmdW5jdGlvbiBtYXBTdHlsZVZhbHVlKGlzVmlzaWJsZSkgewogICAgICByZXR1cm4gaXNWaXNpYmxlID09PSBmYWxzZSA/IFNBRkVfRElTUExBWV9OT05FIDogbnVsbDsKICAgIH0KICB9OwogIHZhciBDbGFzc05hbWVCaW5kaW5nID0gewogICAgaW5zdGFsbDogZnVuY3Rpb24gaW5zdGFsbChfZWxlbWVudCwgY29tcG9uZW50LCBtaWNyb3N5bnRheCwgb3BlcmF0aW9ucykgewogICAgICB2YXIgX21pY3Jvc3ludGF4JHNwbGl0ID0gbWljcm9zeW50YXguc3BsaXQoJzonKSwKICAgICAgICAgIHByb3AgPSBfbWljcm9zeW50YXgkc3BsaXRbMF0sCiAgICAgICAgICB0cnV0aHkgPSBfbWljcm9zeW50YXgkc3BsaXRbMV0sCiAgICAgICAgICBmYWxzeSA9IF9taWNyb3N5bnRheCRzcGxpdFsyXTsKCiAgICAgIHZhciBpc1N0YXRpYyA9IHByb3AgPT09ICcnOwoKICAgICAgaWYgKGlzU3RhdGljKSB7CiAgICAgICAgb3BlcmF0aW9ucy5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUodHJ1dGh5KSwgdHJ1ZSwgbnVsbCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIGlzUGF0aCA9IHByb3AuaW5kZXhPZignLicpID4gLTE7CiAgICAgICAgdmFyIHBhcnRzID0gaXNQYXRoID8gcHJvcC5zcGxpdCgnLicpIDogW107CiAgICAgICAgdmFyIHZhbHVlJCQxID0gaXNQYXRoID8gcmVmZXJlbmNlRm9yUGFydHMoY29tcG9uZW50LCBwYXJ0cykgOiByZWZlcmVuY2VGb3JLZXkoY29tcG9uZW50LCBwcm9wKTsKICAgICAgICB2YXIgcmVmOwoKICAgICAgICBpZiAodHJ1dGh5ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJlZiA9IG5ldyBTaW1wbGVDbGFzc05hbWVCaW5kaW5nUmVmZXJlbmNlKHZhbHVlJCQxLCBpc1BhdGggPyBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXSA6IHByb3ApOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZWYgPSBuZXcgQ29sb25DbGFzc05hbWVCaW5kaW5nUmVmZXJlbmNlKHZhbHVlJCQxLCB0cnV0aHksIGZhbHN5KTsKICAgICAgICB9CgogICAgICAgIG9wZXJhdGlvbnMuc2V0QXR0cmlidXRlKCdjbGFzcycsIHJlZiwgZmFsc2UsIG51bGwpOyAvLyAvLyB0aGUgdXBzdHJlYW0gdHlwZSBmb3IgYWRkRHluYW1pY0F0dHJpYnV0ZSdzIGB2YWx1ZWAgYXJndW1lbnQKICAgICAgICAvLyAvLyBhcHBlYXJzIHRvIGJlIGluY29ycmVjdC4gSXQgaXMgY3VycmVudGx5IGEgUmVmZXJlbmNlPHN0cmluZz4sIEkKICAgICAgICAvLyAvLyB0aGluayBpdCBzaG91bGQgYmUgYSBSZWZlcmVuY2U8c3RyaW5nfG51bGw+LgogICAgICAgIC8vIG9wZXJhdGlvbnMuYWRkRHluYW1pY0F0dHJpYnV0ZShlbGVtZW50LCAnY2xhc3MnLCByZWYgYXMgYW55IGFzIFJlZmVyZW5jZTxzdHJpbmc+LCBmYWxzZSk7CiAgICAgIH0KICAgIH0KICB9OwoKICB2YXIgU2ltcGxlQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ2FjaGVkUmVmZXJlbmNlMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFNpbXBsZUNsYXNzTmFtZUJpbmRpbmdSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UyKTsKCiAgICBmdW5jdGlvbiBTaW1wbGVDbGFzc05hbWVCaW5kaW5nUmVmZXJlbmNlKGlubmVyLCBwYXRoKSB7CiAgICAgIHZhciBfdGhpczE3OwoKICAgICAgX3RoaXMxNyA9IF9DYWNoZWRSZWZlcmVuY2UyLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXMxNy5pbm5lciA9IGlubmVyOwogICAgICBfdGhpczE3LnBhdGggPSBwYXRoOwogICAgICBfdGhpczE3LnRhZyA9IGlubmVyLnRhZzsKICAgICAgX3RoaXMxNy5pbm5lciA9IGlubmVyOwogICAgICBfdGhpczE3LnBhdGggPSBwYXRoOwogICAgICBfdGhpczE3LmRhc2hlcml6ZWRQYXRoID0gbnVsbDsKICAgICAgcmV0dXJuIF90aGlzMTc7CiAgICB9CgogICAgdmFyIF9wcm90bzM1ID0gU2ltcGxlQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMzUuY29tcHV0ZSA9IGZ1bmN0aW9uIGNvbXB1dGUoKSB7CiAgICAgIHZhciB2YWx1ZSQkMSA9IHRoaXMuaW5uZXIudmFsdWUoKTsKCiAgICAgIGlmICh2YWx1ZSQkMSA9PT0gdHJ1ZSkgewogICAgICAgIHZhciBwYXRoID0gdGhpcy5wYXRoLAogICAgICAgICAgICBkYXNoZXJpemVkUGF0aCA9IHRoaXMuZGFzaGVyaXplZFBhdGg7CiAgICAgICAgcmV0dXJuIGRhc2hlcml6ZWRQYXRoIHx8ICh0aGlzLmRhc2hlcml6ZWRQYXRoID0gKDAsIF9zdHJpbmcuZGFzaGVyaXplKShwYXRoKSk7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUkJDEgfHwgdmFsdWUkJDEgPT09IDApIHsKICAgICAgICByZXR1cm4gU3RyaW5nKHZhbHVlJCQxKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gU2ltcGxlQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZTsKICB9KF9yZWZlcmVuY2UuQ2FjaGVkUmVmZXJlbmNlKTsKCiAgdmFyIENvbG9uQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ2FjaGVkUmVmZXJlbmNlMykgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKENvbG9uQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZSwgX0NhY2hlZFJlZmVyZW5jZTMpOwoKICAgIGZ1bmN0aW9uIENvbG9uQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZShpbm5lciwgdHJ1dGh5LCBmYWxzeSkgewogICAgICB2YXIgX3RoaXMxODsKCiAgICAgIGlmICh0cnV0aHkgPT09IHZvaWQgMCkgewogICAgICAgIHRydXRoeSA9IG51bGw7CiAgICAgIH0KCiAgICAgIGlmIChmYWxzeSA9PT0gdm9pZCAwKSB7CiAgICAgICAgZmFsc3kgPSBudWxsOwogICAgICB9CgogICAgICBfdGhpczE4ID0gX0NhY2hlZFJlZmVyZW5jZTMuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczE4LmlubmVyID0gaW5uZXI7CiAgICAgIF90aGlzMTgudHJ1dGh5ID0gdHJ1dGh5OwogICAgICBfdGhpczE4LmZhbHN5ID0gZmFsc3k7CiAgICAgIF90aGlzMTgudGFnID0gaW5uZXIudGFnOwogICAgICByZXR1cm4gX3RoaXMxODsKICAgIH0KCiAgICB2YXIgX3Byb3RvMzYgPSBDb2xvbkNsYXNzTmFtZUJpbmRpbmdSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzM2LmNvbXB1dGUgPSBmdW5jdGlvbiBjb21wdXRlKCkgewogICAgICB2YXIgaW5uZXIgPSB0aGlzLmlubmVyLAogICAgICAgICAgdHJ1dGh5ID0gdGhpcy50cnV0aHksCiAgICAgICAgICBmYWxzeSA9IHRoaXMuZmFsc3k7CiAgICAgIHJldHVybiBpbm5lci52YWx1ZSgpID8gdHJ1dGh5IDogZmFsc3k7CiAgICB9OwoKICAgIHJldHVybiBDb2xvbkNsYXNzTmFtZUJpbmRpbmdSZWZlcmVuY2U7CiAgfShfcmVmZXJlbmNlLkNhY2hlZFJlZmVyZW5jZSk7IC8vIGlucHV0cyBuZWVkZWQgYnkgQ3VybHlDb21wb25lbnRzIChhdHRycyBhbmQgcHJvcHMsIHdpdGggbXV0YWJsZQogIC8vIGNlbGxzLCBldGMpLgoKCiAgZnVuY3Rpb24gcHJvY2Vzc0NvbXBvbmVudEFyZ3MobmFtZWRBcmdzKSB7CiAgICB2YXIga2V5cyA9IG5hbWVkQXJncy5uYW1lczsKICAgIHZhciBhdHRycyA9IG5hbWVkQXJncy52YWx1ZSgpOwogICAgdmFyIHByb3BzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHZhciBhcmdzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHByb3BzW0FSR1NdID0gYXJnczsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIG5hbWUgPSBrZXlzW2ldOwogICAgICB2YXIgcmVmID0gbmFtZWRBcmdzLmdldChuYW1lKTsKICAgICAgdmFyIHZhbHVlJCQxID0gYXR0cnNbbmFtZV07CgogICAgICBpZiAodHlwZW9mIHZhbHVlJCQxID09PSAnZnVuY3Rpb24nICYmIHZhbHVlJCQxW0FDVElPTl0pIHsKICAgICAgICBhdHRyc1tuYW1lXSA9IHZhbHVlJCQxOwogICAgICB9IGVsc2UgaWYgKHJlZltVUERBVEVdKSB7CiAgICAgICAgYXR0cnNbbmFtZV0gPSBuZXcgTXV0YWJsZUNlbGwocmVmLCB2YWx1ZSQkMSk7CiAgICAgIH0KCiAgICAgIGFyZ3NbbmFtZV0gPSByZWY7CiAgICAgIHByb3BzW25hbWVdID0gdmFsdWUkJDE7CiAgICB9CgogICAgcHJvcHMuYXR0cnMgPSBhdHRyczsKICAgIHJldHVybiBwcm9wczsKICB9CgogIHZhciBSRUYgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ1JFRicpOwoKICB2YXIgTXV0YWJsZUNlbGwgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBNdXRhYmxlQ2VsbChyZWYsIHZhbHVlJCQxKSB7CiAgICAgIHRoaXNbX3ZpZXdzLk1VVEFCTEVfQ0VMTF0gPSB0cnVlOwogICAgICB0aGlzW1JFRl0gPSByZWY7CiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZSQkMTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMzcgPSBNdXRhYmxlQ2VsbC5wcm90b3R5cGU7CgogICAgX3Byb3RvMzcudXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKHZhbCkgewogICAgICB0aGlzW1JFRl1bVVBEQVRFXSh2YWwpOwogICAgfTsKCiAgICByZXR1cm4gTXV0YWJsZUNlbGw7CiAgfSgpOwoKICBmdW5jdGlvbiBhbGlhc0lkVG9FbGVtZW50SWQoYXJncywgcHJvcHMpIHsKICAgIGlmIChhcmdzLm5hbWVkLmhhcygnaWQnKSkgewogICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoCiAgICAgIChmYWxzZSAmJiAhKCFhcmdzLm5hbWVkLmhhcygnZWxlbWVudElkJykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGNhbm5vdCBpbnZva2UgYSBjb21wb25lbnQgd2l0aCBib3RoICdpZCcgYW5kICdlbGVtZW50SWQnIGF0IHRoZSBzYW1lIHRpbWUuIiwgIWFyZ3MubmFtZWQuaGFzKCdlbGVtZW50SWQnKSkpOwogICAgICBwcm9wcy5lbGVtZW50SWQgPSBwcm9wcy5pZDsKICAgIH0KICB9IC8vIFdlIG11c3QgdHJhdmVyc2UgdGhlIGF0dHJpYnV0ZUJpbmRpbmdzIGluIHJldmVyc2Uga2VlcGluZyB0cmFjayBvZgogIC8vIHdoYXQgaGFzIGFscmVhZHkgYmVlbiBhcHBsaWVkLiBUaGlzIGlzIGVzc2VudGlhbGx5IHJlZmluaW5nIHRoZSBjb25jYXRlbmF0ZWQKICAvLyBwcm9wZXJ0aWVzIGFwcGx5aW5nIHJpZ2h0IHRvIGxlZnQuCgoKICBmdW5jdGlvbiBhcHBseUF0dHJpYnV0ZUJpbmRpbmdzKGVsZW1lbnQsIGF0dHJpYnV0ZUJpbmRpbmdzLCBjb21wb25lbnQsIG9wZXJhdGlvbnMpIHsKICAgIHZhciBzZWVuID0gW107CiAgICB2YXIgaSA9IGF0dHJpYnV0ZUJpbmRpbmdzLmxlbmd0aCAtIDE7CgogICAgd2hpbGUgKGkgIT09IC0xKSB7CiAgICAgIHZhciBiaW5kaW5nID0gYXR0cmlidXRlQmluZGluZ3NbaV07CiAgICAgIHZhciBwYXJzZWQgPSBBdHRyaWJ1dGVCaW5kaW5nLnBhcnNlKGJpbmRpbmcpOwogICAgICB2YXIgYXR0cmlidXRlID0gcGFyc2VkWzFdOwoKICAgICAgaWYgKHNlZW4uaW5kZXhPZihhdHRyaWJ1dGUpID09PSAtMSkgewogICAgICAgIHNlZW4ucHVzaChhdHRyaWJ1dGUpOwogICAgICAgIEF0dHJpYnV0ZUJpbmRpbmcuaW5zdGFsbChlbGVtZW50LCBjb21wb25lbnQsIHBhcnNlZCwgb3BlcmF0aW9ucyk7CiAgICAgIH0KCiAgICAgIGktLTsKICAgIH0KCiAgICBpZiAoc2Vlbi5pbmRleE9mKCdpZCcpID09PSAtMSkgewogICAgICB2YXIgaWQkJDEgPSBjb21wb25lbnQuZWxlbWVudElkID8gY29tcG9uZW50LmVsZW1lbnRJZCA6ICgwLCBfdXRpbHMuZ3VpZEZvcikoY29tcG9uZW50KTsKICAgICAgb3BlcmF0aW9ucy5zZXRBdHRyaWJ1dGUoJ2lkJywgX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUoaWQkJDEpLCBmYWxzZSwgbnVsbCk7CiAgICB9CgogICAgaWYgKHNlZW4uaW5kZXhPZignc3R5bGUnKSA9PT0gLTEpIHsKICAgICAgSXNWaXNpYmxlQmluZGluZy5pbnN0YWxsKGVsZW1lbnQsIGNvbXBvbmVudCwgb3BlcmF0aW9ucyk7CiAgICB9CiAgfQoKICB2YXIgREVGQVVMVF9MQVlPVVQgPSAoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdDIoKSk7CiAgdmFyIEVNUFRZX1BPU0lUSU9OQUxfQVJHUyA9IFtdOwogICgwLCBfZGVidWcuZGVidWdGcmVlemUpKEVNUFRZX1BPU0lUSU9OQUxfQVJHUyk7CgogIHZhciBDdXJseUNvbXBvbmVudE1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Fic3RyYWN0TWFuYWdlcjIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDdXJseUNvbXBvbmVudE1hbmFnZXIsIF9BYnN0cmFjdE1hbmFnZXIyKTsKCiAgICBmdW5jdGlvbiBDdXJseUNvbXBvbmVudE1hbmFnZXIoKSB7CiAgICAgIHJldHVybiBfQWJzdHJhY3RNYW5hZ2VyMi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzM4ID0gQ3VybHlDb21wb25lbnRNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zOC5nZXRMYXlvdXQgPSBmdW5jdGlvbiBnZXRMYXlvdXQoc3RhdGUsIF9yZXNvbHZlcikgewogICAgICByZXR1cm4gewogICAgICAgIC8vIFRPRE8gZml4CiAgICAgICAgaGFuZGxlOiBzdGF0ZS5oYW5kbGUsCiAgICAgICAgc3ltYm9sVGFibGU6IHN0YXRlLnN5bWJvbFRhYmxlCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzM4LnRlbXBsYXRlRm9yID0gZnVuY3Rpb24gdGVtcGxhdGVGb3IoY29tcG9uZW50KSB7CiAgICAgIHZhciBsYXlvdXQgPSBjb21wb25lbnQubGF5b3V0LAogICAgICAgICAgbGF5b3V0TmFtZSA9IGNvbXBvbmVudC5sYXlvdXROYW1lOwogICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKShjb21wb25lbnQpOwogICAgICB2YXIgZmFjdG9yeTsKCiAgICAgIGlmIChsYXlvdXQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGlmIChsYXlvdXROYW1lICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHZhciBfZmFjdG9yeSA9IG93bmVyLmxvb2t1cCgidGVtcGxhdGU6IiArIGxheW91dE5hbWUpOwoKICAgICAgICAgIChmYWxzZSAmJiAhKF9mYWN0b3J5ICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiTGF5b3V0IGAiICsgbGF5b3V0TmFtZSArICJgIG5vdCBmb3VuZCEiLCBfZmFjdG9yeSAhPT0gdW5kZWZpbmVkKSk7CiAgICAgICAgICBmYWN0b3J5ID0gX2ZhY3Rvcnk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGZhY3RvcnkgPSBvd25lci5sb29rdXAoREVGQVVMVF9MQVlPVVQpOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChpc1RlbXBsYXRlRmFjdG9yeShsYXlvdXQpKSB7CiAgICAgICAgZmFjdG9yeSA9IGxheW91dDsKICAgICAgfSBlbHNlIHsKICAgICAgICAvLyB3ZSB3ZXJlIHByb3ZpZGVkIGFuIGluc3RhbmNlIGFscmVhZHkKICAgICAgICByZXR1cm4gbGF5b3V0OwogICAgICB9CgogICAgICByZXR1cm4gZmFjdG9yeShvd25lcik7CiAgICB9OwoKICAgIF9wcm90bzM4LmdldER5bmFtaWNMYXlvdXQgPSBmdW5jdGlvbiBnZXREeW5hbWljTGF5b3V0KF9yZWYzKSB7CiAgICAgIHZhciBjb21wb25lbnQgPSBfcmVmMy5jb21wb25lbnQ7CiAgICAgIHZhciB0ZW1wbGF0ZSQkMSA9IHRoaXMudGVtcGxhdGVGb3IoY29tcG9uZW50KTsKICAgICAgdmFyIGxheW91dCA9IHRlbXBsYXRlJCQxLmFzV3JhcHBlZExheW91dCgpOwogICAgICByZXR1cm4gewogICAgICAgIGhhbmRsZTogbGF5b3V0LmNvbXBpbGUoKSwKICAgICAgICBzeW1ib2xUYWJsZTogbGF5b3V0LnN5bWJvbFRhYmxlCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzM4LmdldFRhZ05hbWUgPSBmdW5jdGlvbiBnZXRUYWdOYW1lKHN0YXRlKSB7CiAgICAgIHZhciBjb21wb25lbnQgPSBzdGF0ZS5jb21wb25lbnQsCiAgICAgICAgICBoYXNXcmFwcGVkRWxlbWVudCA9IHN0YXRlLmhhc1dyYXBwZWRFbGVtZW50OwoKICAgICAgaWYgKCFoYXNXcmFwcGVkRWxlbWVudCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICByZXR1cm4gY29tcG9uZW50ICYmIGNvbXBvbmVudC50YWdOYW1lIHx8ICdkaXYnOwogICAgfTsKCiAgICBfcHJvdG8zOC5nZXRDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiBnZXRDYXBhYmlsaXRpZXMoc3RhdGUpIHsKICAgICAgcmV0dXJuIHN0YXRlLmNhcGFiaWxpdGllczsKICAgIH07CgogICAgX3Byb3RvMzgucHJlcGFyZUFyZ3MgPSBmdW5jdGlvbiBwcmVwYXJlQXJncyhzdGF0ZSwgYXJncykgewogICAgICBpZiAoYXJncy5uYW1lZC5oYXMoJ19fQVJHU19fJykpIHsKICAgICAgICB2YXIgX19hcmdzX18gPSBhcmdzLm5hbWVkLmdldCgnX19BUkdTX18nKS52YWx1ZSgpOwoKICAgICAgICB2YXIgcHJlcGFyZWQgPSB7CiAgICAgICAgICBwb3NpdGlvbmFsOiBFTVBUWV9QT1NJVElPTkFMX0FSR1MsCiAgICAgICAgICBuYW1lZDogKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgYXJncy5uYW1lZC5jYXB0dXJlKCkubWFwLCBfX2FyZ3NfXykKICAgICAgICB9OwoKICAgICAgICBpZiAoZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICkgewogICAgICAgICAgZGVsZXRlIHByZXBhcmVkLm5hbWVkLl9fQVJHU19fOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHByZXBhcmVkOwogICAgICB9CgogICAgICB2YXIgcG9zaXRpb25hbFBhcmFtcyA9IHN0YXRlLkNvbXBvbmVudENsYXNzLmNsYXNzLnBvc2l0aW9uYWxQYXJhbXM7IC8vIGVhcmx5IGV4aXRzCgogICAgICBpZiAocG9zaXRpb25hbFBhcmFtcyA9PT0gdW5kZWZpbmVkIHx8IHBvc2l0aW9uYWxQYXJhbXMgPT09IG51bGwgfHwgYXJncy5wb3NpdGlvbmFsLmxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgbmFtZWQ7CgogICAgICBpZiAodHlwZW9mIHBvc2l0aW9uYWxQYXJhbXMgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgdmFyIF9uYW1lZDsKCiAgICAgICAgKGZhbHNlICYmICEoIWFyZ3MubmFtZWQuaGFzKHBvc2l0aW9uYWxQYXJhbXMpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3Qgc3BlY2lmeSBwb3NpdGlvbmFsIHBhcmFtZXRlcnMgYW5kIHRoZSBoYXNoIGFyZ3VtZW50IGAiICsgcG9zaXRpb25hbFBhcmFtcyArICJgLiIsICFhcmdzLm5hbWVkLmhhcyhwb3NpdGlvbmFsUGFyYW1zKSkpOwogICAgICAgIG5hbWVkID0gKF9uYW1lZCA9IHt9LCBfbmFtZWRbcG9zaXRpb25hbFBhcmFtc10gPSBhcmdzLnBvc2l0aW9uYWwuY2FwdHVyZSgpLCBfbmFtZWQpOwogICAgICAgICgwLCBfcG9seWZpbGxzLmFzc2lnbikobmFtZWQsIGFyZ3MubmFtZWQuY2FwdHVyZSgpLm1hcCk7CiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShwb3NpdGlvbmFsUGFyYW1zKSAmJiBwb3NpdGlvbmFsUGFyYW1zLmxlbmd0aCA+IDApIHsKICAgICAgICB2YXIgY291bnQgPSBNYXRoLm1pbihwb3NpdGlvbmFsUGFyYW1zLmxlbmd0aCwgYXJncy5wb3NpdGlvbmFsLmxlbmd0aCk7CiAgICAgICAgbmFtZWQgPSB7fTsKICAgICAgICAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKG5hbWVkLCBhcmdzLm5hbWVkLmNhcHR1cmUoKS5tYXApOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgICAgIHZhciBuYW1lID0gcG9zaXRpb25hbFBhcmFtc1tpXTsKICAgICAgICAgIChmYWxzZSAmJiAhKCFhcmdzLm5hbWVkLmhhcyhuYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgY2Fubm90IHNwZWNpZnkgYm90aCBhIHBvc2l0aW9uYWwgcGFyYW0gKGF0IHBvc2l0aW9uICIgKyBpICsgIikgYW5kIHRoZSBoYXNoIGFyZ3VtZW50IGAiICsgbmFtZSArICJgLiIsICFhcmdzLm5hbWVkLmhhcyhuYW1lKSkpOwogICAgICAgICAgbmFtZWRbbmFtZV0gPSBhcmdzLnBvc2l0aW9uYWwuYXQoaSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICByZXR1cm4gewogICAgICAgIHBvc2l0aW9uYWw6IF91dGlsLkVNUFRZX0FSUkFZLAogICAgICAgIG5hbWVkOiBuYW1lZAogICAgICB9OwogICAgfQogICAgLyoKICAgICAqIFRoaXMgaG9vayBpcyByZXNwb25zaWJsZSBmb3IgYWN0dWFsbHkgaW5zdGFudGlhdGluZyB0aGUgY29tcG9uZW50IGluc3RhbmNlLgogICAgICogSXQgYWxzbyBpcyB3aGVyZSB3ZSBwZXJmb3JtIGFkZGl0aW9uYWwgYm9va2tlZXBpbmcgdG8gc3VwcG9ydCBsZWdhY3kKICAgICAqIGZlYXR1cmVzIGxpa2UgZXhwb3NlZCBieSB2aWV3IG1peGlucyBsaWtlIENoaWxkVmlld1N1cHBvcnQsIEFjdGlvblN1cHBvcnQsCiAgICAgKiBldGMuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zOC5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoZW52aXJvbm1lbnQsIHN0YXRlLCBhcmdzLCBkeW5hbWljU2NvcGUsIGNhbGxlclNlbGZSZWYsIGhhc0Jsb2NrKSB7CiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICB0aGlzLl9wdXNoVG9EZWJ1Z1N0YWNrKCJjb21wb25lbnQ6IiArIHN0YXRlLm5hbWUsIGVudmlyb25tZW50KTsKICAgICAgfSAvLyBHZXQgdGhlIG5lYXJlc3QgY29uY3JldGUgY29tcG9uZW50IGluc3RhbmNlIGZyb20gdGhlIHNjb3BlLiAiVmlydHVhbCIKICAgICAgLy8gY29tcG9uZW50cyB3aWxsIGJlIHNraXBwZWQuCgoKICAgICAgdmFyIHBhcmVudFZpZXcgPSBkeW5hbWljU2NvcGUudmlldzsgLy8gR2V0IHRoZSBFbWJlci5Db21wb25lbnQgc3ViY2xhc3MgdG8gaW5zdGFudGlhdGUgZm9yIHRoaXMgY29tcG9uZW50LgoKICAgICAgdmFyIGZhY3RvcnkgPSBzdGF0ZS5Db21wb25lbnRDbGFzczsgLy8gQ2FwdHVyZSB0aGUgYXJndW1lbnRzLCB3aGljaCB0ZWxscyBHbGltbWVyIHRvIGdpdmUgdXMgb3VyIG93biwgc3RhYmxlCiAgICAgIC8vIGNvcHkgb2YgdGhlIEFyZ3VtZW50cyBvYmplY3QgdGhhdCBpcyBzYWZlIHRvIGhvbGQgb24gdG8gYmV0d2VlbiByZW5kZXJzLgoKICAgICAgdmFyIGNhcHR1cmVkQXJncyA9IGFyZ3MubmFtZWQuY2FwdHVyZSgpOwogICAgICB2YXIgcHJvcHMgPSBwcm9jZXNzQ29tcG9uZW50QXJncyhjYXB0dXJlZEFyZ3MpOyAvLyBBbGlhcyBgaWRgIGFyZ3VtZW50IHRvIGBlbGVtZW50SWRgIHByb3BlcnR5IG9uIHRoZSBjb21wb25lbnQgaW5zdGFuY2UuCgogICAgICBhbGlhc0lkVG9FbGVtZW50SWQoYXJncywgcHJvcHMpOyAvLyBTZXQgY29tcG9uZW50IGluc3RhbmNlJ3MgcGFyZW50VmlldyBwcm9wZXJ0eSB0byBwb2ludCB0byBuZWFyZXN0IGNvbmNyZXRlCiAgICAgIC8vIGNvbXBvbmVudC4KCiAgICAgIHByb3BzLnBhcmVudFZpZXcgPSBwYXJlbnRWaWV3OyAvLyBTZXQgd2hldGhlciB0aGlzIGNvbXBvbmVudCB3YXMgaW52b2tlZCB3aXRoIGEgYmxvY2sKICAgICAgLy8gKGB7eyNteS1jb21wb25lbnR9fXt7L215LWNvbXBvbmVudH19YCkgb3Igd2l0aG91dCBvbmUKICAgICAgLy8gKGB7e215LWNvbXBvbmVudH19YCkuCgogICAgICBwcm9wc1tIQVNfQkxPQ0tdID0gaGFzQmxvY2s7IC8vIFNhdmUgdGhlIGN1cnJlbnQgYHRoaXNgIGNvbnRleHQgb2YgdGhlIHRlbXBsYXRlIGFzIHRoZSBjb21wb25lbnQncwogICAgICAvLyBgX3RhcmdldGAsIHNvIGJ1YmJsZWQgYWN0aW9ucyBhcmUgcm91dGVkIHRvIHRoZSByaWdodCBwbGFjZS4KCiAgICAgIHByb3BzLl90YXJnZXQgPSBjYWxsZXJTZWxmUmVmLnZhbHVlKCk7IC8vIHN0YXRpYyBsYXlvdXQgYXNzZXJ0cyBDdXJyaWVkRGVmaW5pdGlvbgoKICAgICAgaWYgKHN0YXRlLnRlbXBsYXRlKSB7CiAgICAgICAgcHJvcHMubGF5b3V0ID0gc3RhdGUudGVtcGxhdGU7CiAgICAgIH0gLy8gTm93IHRoYXQgd2UndmUgYnVpbHQgdXAgYWxsIG9mIHRoZSBwcm9wZXJ0aWVzIHRvIHNldCBvbiB0aGUgY29tcG9uZW50IGluc3RhbmNlLAogICAgICAvLyBhY3R1YWxseSBjcmVhdGUgaXQuCgoKICAgICAgdmFyIGNvbXBvbmVudCA9IGZhY3RvcnkuY3JlYXRlKHByb3BzKTsKICAgICAgdmFyIGZpbmFsaXplciA9ICgwLCBfaW5zdHJ1bWVudGF0aW9uLl9pbnN0cnVtZW50U3RhcnQpKCdyZW5kZXIuY29tcG9uZW50JywgaW5pdGlhbFJlbmRlckluc3RydW1lbnREZXRhaWxzLCBjb21wb25lbnQpOyAvLyBXZSBiZWNvbWUgdGhlIG5ldyBwYXJlbnRWaWV3IGZvciBkb3duc3RyZWFtIGNvbXBvbmVudHMsIHNvIHNhdmUgb3VyCiAgICAgIC8vIGNvbXBvbmVudCBvZmYgb24gdGhlIGR5bmFtaWMgc2NvcGUuCgogICAgICBkeW5hbWljU2NvcGUudmlldyA9IGNvbXBvbmVudDsgLy8gVW5sZXNzIHdlJ3JlIHRoZSByb290IGNvbXBvbmVudCwgd2UgbmVlZCB0byBhZGQgb3Vyc2VsdmVzIHRvIG91ciBwYXJlbnQKICAgICAgLy8gY29tcG9uZW50J3MgY2hpbGRWaWV3cyBhcnJheS4KCiAgICAgIGlmIChwYXJlbnRWaWV3ICE9PSBudWxsICYmIHBhcmVudFZpZXcgIT09IHVuZGVmaW5lZCkgewogICAgICAgICgwLCBfdmlld3MuYWRkQ2hpbGRWaWV3KShwYXJlbnRWaWV3LCBjb21wb25lbnQpOwogICAgICB9CgogICAgICBjb21wb25lbnQudHJpZ2dlcignZGlkUmVjZWl2ZUF0dHJzJyk7CiAgICAgIHZhciBoYXNXcmFwcGVkRWxlbWVudCA9IGNvbXBvbmVudC50YWdOYW1lICE9PSAnJzsgLy8gV2UgdXN1YWxseSBkbyB0aGlzIGluIHRoZSBgZGlkQ3JlYXRlRWxlbWVudGAsIGJ1dCB0aGF0IGhvb2sgZG9lc24ndCBmaXJlIGZvciB0YWdsZXNzIGNvbXBvbmVudHMKCiAgICAgIGlmICghaGFzV3JhcHBlZEVsZW1lbnQpIHsKICAgICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgICAgY29tcG9uZW50LnRyaWdnZXIoJ3dpbGxSZW5kZXInKTsKICAgICAgICB9CgogICAgICAgIGNvbXBvbmVudC5fdHJhbnNpdGlvblRvKCdoYXNFbGVtZW50Jyk7CgogICAgICAgIGlmIChlbnZpcm9ubWVudC5pc0ludGVyYWN0aXZlKSB7CiAgICAgICAgICBjb21wb25lbnQudHJpZ2dlcignd2lsbEluc2VydEVsZW1lbnQnKTsKICAgICAgICB9CiAgICAgIH0gLy8gVHJhY2sgYWRkaXRpb25hbCBsaWZlY3ljbGUgbWV0YWRhdGEgYWJvdXQgdGhpcyBjb21wb25lbnQgaW4gYSBzdGF0ZSBidWNrZXQuCiAgICAgIC8vIEVzc2VudGlhbGx5IHdlJ3JlIHNhdmluZyBvZmYgYWxsIHRoZSBzdGF0ZSB3ZSdsbCBuZWVkIGluIHRoZSBmdXR1cmUuCgoKICAgICAgdmFyIGJ1Y2tldCA9IG5ldyBDb21wb25lbnRTdGF0ZUJ1Y2tldChlbnZpcm9ubWVudCwgY29tcG9uZW50LCBjYXB0dXJlZEFyZ3MsIGZpbmFsaXplciwgaGFzV3JhcHBlZEVsZW1lbnQpOwoKICAgICAgaWYgKGFyZ3MubmFtZWQuaGFzKCdjbGFzcycpKSB7CiAgICAgICAgYnVja2V0LmNsYXNzUmVmID0gYXJncy5uYW1lZC5nZXQoJ2NsYXNzJyk7CiAgICAgIH0KCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICBwcm9jZXNzQ29tcG9uZW50SW5pdGlhbGl6YXRpb25Bc3NlcnRpb25zKGNvbXBvbmVudCwgcHJvcHMpOwogICAgICB9CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSAmJiBoYXNXcmFwcGVkRWxlbWVudCkgewogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCd3aWxsUmVuZGVyJyk7CiAgICAgIH0KCiAgICAgIHJldHVybiBidWNrZXQ7CiAgICB9OwoKICAgIF9wcm90bzM4LmdldFNlbGYgPSBmdW5jdGlvbiBnZXRTZWxmKF9yZWY0KSB7CiAgICAgIHZhciBjb21wb25lbnQgPSBfcmVmNC5jb21wb25lbnQ7CiAgICAgIHJldHVybiBjb21wb25lbnRbUk9PVF9SRUZdOwogICAgfTsKCiAgICBfcHJvdG8zOC5kaWRDcmVhdGVFbGVtZW50ID0gZnVuY3Rpb24gZGlkQ3JlYXRlRWxlbWVudChfcmVmNSwgZWxlbWVudCwgb3BlcmF0aW9ucykgewogICAgICB2YXIgY29tcG9uZW50ID0gX3JlZjUuY29tcG9uZW50LAogICAgICAgICAgY2xhc3NSZWYgPSBfcmVmNS5jbGFzc1JlZiwKICAgICAgICAgIGVudmlyb25tZW50ID0gX3JlZjUuZW52aXJvbm1lbnQ7CiAgICAgICgwLCBfdmlld3Muc2V0Vmlld0VsZW1lbnQpKGNvbXBvbmVudCwgZWxlbWVudCk7CiAgICAgICgwLCBfdmlld3Muc2V0RWxlbWVudFZpZXcpKGVsZW1lbnQsIGNvbXBvbmVudCk7CiAgICAgIHZhciBhdHRyaWJ1dGVCaW5kaW5ncyA9IGNvbXBvbmVudC5hdHRyaWJ1dGVCaW5kaW5ncywKICAgICAgICAgIGNsYXNzTmFtZXMgPSBjb21wb25lbnQuY2xhc3NOYW1lcywKICAgICAgICAgIGNsYXNzTmFtZUJpbmRpbmdzID0gY29tcG9uZW50LmNsYXNzTmFtZUJpbmRpbmdzOwoKICAgICAgaWYgKGF0dHJpYnV0ZUJpbmRpbmdzICYmIGF0dHJpYnV0ZUJpbmRpbmdzLmxlbmd0aCkgewogICAgICAgIGFwcGx5QXR0cmlidXRlQmluZGluZ3MoZWxlbWVudCwgYXR0cmlidXRlQmluZGluZ3MsIGNvbXBvbmVudCwgb3BlcmF0aW9ucyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIGlkJCQxID0gY29tcG9uZW50LmVsZW1lbnRJZCA/IGNvbXBvbmVudC5lbGVtZW50SWQgOiAoMCwgX3V0aWxzLmd1aWRGb3IpKGNvbXBvbmVudCk7CiAgICAgICAgb3BlcmF0aW9ucy5zZXRBdHRyaWJ1dGUoJ2lkJywgX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUoaWQkJDEpLCBmYWxzZSwgbnVsbCk7CiAgICAgICAgSXNWaXNpYmxlQmluZGluZy5pbnN0YWxsKGVsZW1lbnQsIGNvbXBvbmVudCwgb3BlcmF0aW9ucyk7CiAgICAgIH0KCiAgICAgIGlmIChjbGFzc1JlZikgewogICAgICAgIHZhciByZWYgPSBuZXcgU2ltcGxlQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZShjbGFzc1JlZiwgY2xhc3NSZWZbJ3Byb3BlcnR5S2V5J10pOwogICAgICAgIG9wZXJhdGlvbnMuc2V0QXR0cmlidXRlKCdjbGFzcycsIHJlZiwgZmFsc2UsIG51bGwpOwogICAgICB9CgogICAgICBpZiAoY2xhc3NOYW1lcyAmJiBjbGFzc05hbWVzLmxlbmd0aCkgewogICAgICAgIGNsYXNzTmFtZXMuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkgewogICAgICAgICAgb3BlcmF0aW9ucy5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUobmFtZSksIGZhbHNlLCBudWxsKTsKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgaWYgKGNsYXNzTmFtZUJpbmRpbmdzICYmIGNsYXNzTmFtZUJpbmRpbmdzLmxlbmd0aCkgewogICAgICAgIGNsYXNzTmFtZUJpbmRpbmdzLmZvckVhY2goZnVuY3Rpb24gKGJpbmRpbmcpIHsKICAgICAgICAgIENsYXNzTmFtZUJpbmRpbmcuaW5zdGFsbChlbGVtZW50LCBjb21wb25lbnQsIGJpbmRpbmcsIG9wZXJhdGlvbnMpOwogICAgICAgIH0pOwogICAgICB9CgogICAgICBvcGVyYXRpb25zLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCBfcnVudGltZTIuUHJpbWl0aXZlUmVmZXJlbmNlLmNyZWF0ZSgnZW1iZXItdmlldycpLCBmYWxzZSwgbnVsbCk7CgogICAgICBpZiAoJ2FyaWFSb2xlJyBpbiBjb21wb25lbnQpIHsKICAgICAgICBvcGVyYXRpb25zLnNldEF0dHJpYnV0ZSgncm9sZScsIHJlZmVyZW5jZUZvcktleShjb21wb25lbnQsICdhcmlhUm9sZScpLCBmYWxzZSwgbnVsbCk7CiAgICAgIH0KCiAgICAgIGNvbXBvbmVudC5fdHJhbnNpdGlvblRvKCdoYXNFbGVtZW50Jyk7CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCd3aWxsSW5zZXJ0RWxlbWVudCcpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzM4LmRpZFJlbmRlckxheW91dCA9IGZ1bmN0aW9uIGRpZFJlbmRlckxheW91dChidWNrZXQsIGJvdW5kcykgewogICAgICBidWNrZXQuY29tcG9uZW50W0JPVU5EU10gPSBib3VuZHM7CiAgICAgIGJ1Y2tldC5maW5hbGl6ZSgpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuZGVidWdTdGFjay5wb3AoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zOC5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoX3JlZjYpIHsKICAgICAgdmFyIGFyZ3MgPSBfcmVmNi5hcmdzLAogICAgICAgICAgY29tcG9uZW50ID0gX3JlZjYuY29tcG9uZW50OwogICAgICByZXR1cm4gYXJncyA/ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFthcmdzLnRhZywgY29tcG9uZW50W0RJUlRZX1RBR11dKSA6IGNvbXBvbmVudFtESVJUWV9UQUddOwogICAgfTsKCiAgICBfcHJvdG8zOC5kaWRDcmVhdGUgPSBmdW5jdGlvbiBkaWRDcmVhdGUoX3JlZjcpIHsKICAgICAgdmFyIGNvbXBvbmVudCA9IF9yZWY3LmNvbXBvbmVudCwKICAgICAgICAgIGVudmlyb25tZW50ID0gX3JlZjcuZW52aXJvbm1lbnQ7CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIGNvbXBvbmVudC5fdHJhbnNpdGlvblRvKCdpbkRPTScpOwoKICAgICAgICBjb21wb25lbnQudHJpZ2dlcignZGlkSW5zZXJ0RWxlbWVudCcpOwogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCdkaWRSZW5kZXInKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zOC51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoYnVja2V0KSB7CiAgICAgIHZhciBjb21wb25lbnQgPSBidWNrZXQuY29tcG9uZW50LAogICAgICAgICAgYXJncyA9IGJ1Y2tldC5hcmdzLAogICAgICAgICAgYXJnc1JldmlzaW9uID0gYnVja2V0LmFyZ3NSZXZpc2lvbiwKICAgICAgICAgIGVudmlyb25tZW50ID0gYnVja2V0LmVudmlyb25tZW50OwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuX3B1c2hUb0RlYnVnU3RhY2soY29tcG9uZW50Ll9kZWJ1Z0NvbnRhaW5lcktleSwgZW52aXJvbm1lbnQpOwogICAgICB9CgogICAgICBidWNrZXQuZmluYWxpemVyID0gKDAsIF9pbnN0cnVtZW50YXRpb24uX2luc3RydW1lbnRTdGFydCkoJ3JlbmRlci5jb21wb25lbnQnLCByZXJlbmRlckluc3RydW1lbnREZXRhaWxzLCBjb21wb25lbnQpOwoKICAgICAgaWYgKGFyZ3MgJiYgISgwLCBfcmVmZXJlbmNlLnZhbGlkYXRlKShhcmdzLnRhZywgYXJnc1JldmlzaW9uKSkgewogICAgICAgIHZhciBwcm9wcyA9IHByb2Nlc3NDb21wb25lbnRBcmdzKGFyZ3MpOwogICAgICAgIGJ1Y2tldC5hcmdzUmV2aXNpb24gPSAoMCwgX3JlZmVyZW5jZS52YWx1ZSkoYXJncy50YWcpOwogICAgICAgIGNvbXBvbmVudFtJU19ESVNQQVRDSElOR19BVFRSU10gPSB0cnVlOwogICAgICAgIGNvbXBvbmVudC5zZXRQcm9wZXJ0aWVzKHByb3BzKTsKICAgICAgICBjb21wb25lbnRbSVNfRElTUEFUQ0hJTkdfQVRUUlNdID0gZmFsc2U7CiAgICAgICAgY29tcG9uZW50LnRyaWdnZXIoJ2RpZFVwZGF0ZUF0dHJzJyk7CiAgICAgICAgY29tcG9uZW50LnRyaWdnZXIoJ2RpZFJlY2VpdmVBdHRycycpOwogICAgICB9CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCd3aWxsVXBkYXRlJyk7CiAgICAgICAgY29tcG9uZW50LnRyaWdnZXIoJ3dpbGxSZW5kZXInKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zOC5kaWRVcGRhdGVMYXlvdXQgPSBmdW5jdGlvbiBkaWRVcGRhdGVMYXlvdXQoYnVja2V0KSB7CiAgICAgIGJ1Y2tldC5maW5hbGl6ZSgpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuZGVidWdTdGFjay5wb3AoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zOC5kaWRVcGRhdGUgPSBmdW5jdGlvbiBkaWRVcGRhdGUoX3JlZjgpIHsKICAgICAgdmFyIGNvbXBvbmVudCA9IF9yZWY4LmNvbXBvbmVudCwKICAgICAgICAgIGVudmlyb25tZW50ID0gX3JlZjguZW52aXJvbm1lbnQ7CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCdkaWRVcGRhdGUnKTsKICAgICAgICBjb21wb25lbnQudHJpZ2dlcignZGlkUmVuZGVyJyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMzguZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3Ioc3RhdGVCdWNrZXQpIHsKICAgICAgcmV0dXJuIHN0YXRlQnVja2V0OwogICAgfTsKCiAgICByZXR1cm4gQ3VybHlDb21wb25lbnRNYW5hZ2VyOwogIH0oQWJzdHJhY3RNYW5hZ2VyKTsKCiAgZnVuY3Rpb24gcHJvY2Vzc0NvbXBvbmVudEluaXRpYWxpemF0aW9uQXNzZXJ0aW9ucyhjb21wb25lbnQsIHByb3BzKSB7CiAgICAoZmFsc2UgJiYgIShmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBjbGFzc05hbWVCaW5kaW5ncyA9IGNvbXBvbmVudC5jbGFzc05hbWVCaW5kaW5nczsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2xhc3NOYW1lQmluZGluZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgYmluZGluZyA9IGNsYXNzTmFtZUJpbmRpbmdzW2ldOwoKICAgICAgICBpZiAodHlwZW9mIGJpbmRpbmcgIT09ICdzdHJpbmcnIHx8IGJpbmRpbmcubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0oKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJjbGFzc05hbWVCaW5kaW5ncyBtdXN0IGJlIG5vbi1lbXB0eSBzdHJpbmdzOiAiICsgY29tcG9uZW50LCBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBjbGFzc05hbWVCaW5kaW5ncyA9IGNvbXBvbmVudC5jbGFzc05hbWVCaW5kaW5nczsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2xhc3NOYW1lQmluZGluZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgYmluZGluZyA9IGNsYXNzTmFtZUJpbmRpbmdzW2ldOwoKICAgICAgICBpZiAodHlwZW9mIGJpbmRpbmcgIT09ICdzdHJpbmcnIHx8IGJpbmRpbmcubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0oKSkpOwogICAgKGZhbHNlICYmICEoZnVuY3Rpb24gKCkgewogICAgICB2YXIgY2xhc3NOYW1lQmluZGluZ3MgPSBjb21wb25lbnQuY2xhc3NOYW1lQmluZGluZ3M7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNsYXNzTmFtZUJpbmRpbmdzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGJpbmRpbmcgPSBjbGFzc05hbWVCaW5kaW5nc1tpXTsKCiAgICAgICAgaWYgKGJpbmRpbmcuc3BsaXQoJyAnKS5sZW5ndGggPiAxKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0oKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJjbGFzc05hbWVCaW5kaW5ncyBtdXN0IG5vdCBoYXZlIHNwYWNlcyBpbiB0aGVtOiAiICsgY29tcG9uZW50LCBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBjbGFzc05hbWVCaW5kaW5ncyA9IGNvbXBvbmVudC5jbGFzc05hbWVCaW5kaW5nczsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2xhc3NOYW1lQmluZGluZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgYmluZGluZyA9IGNsYXNzTmFtZUJpbmRpbmdzW2ldOwoKICAgICAgICBpZiAoYmluZGluZy5zcGxpdCgnICcpLmxlbmd0aCA+IDEpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiB0cnVlOwogICAgfSgpKSk7CiAgICAoZmFsc2UgJiYgIShjb21wb25lbnQudGFnTmFtZSAhPT0gJycgfHwgIWNvbXBvbmVudC5jbGFzc05hbWVCaW5kaW5ncyB8fCBjb21wb25lbnQuY2xhc3NOYW1lQmluZGluZ3MubGVuZ3RoID09PSAwKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3QgdXNlIGBjbGFzc05hbWVCaW5kaW5nc2Agb24gYSB0YWctbGVzcyBjb21wb25lbnQ6ICIgKyBjb21wb25lbnQsIGNvbXBvbmVudC50YWdOYW1lICE9PSAnJyB8fCAhY29tcG9uZW50LmNsYXNzTmFtZUJpbmRpbmdzIHx8IGNvbXBvbmVudC5jbGFzc05hbWVCaW5kaW5ncy5sZW5ndGggPT09IDApKTsKICAgIChmYWxzZSAmJiAhKGNvbXBvbmVudC50YWdOYW1lICE9PSAnJyB8fCBwcm9wcy5pZCA9PT0gY29tcG9uZW50LmVsZW1lbnRJZCB8fCAhY29tcG9uZW50LmVsZW1lbnRJZCAmJiBjb21wb25lbnQuZWxlbWVudElkICE9PSAnJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgY2Fubm90IHVzZSBgZWxlbWVudElkYCBvbiBhIHRhZy1sZXNzIGNvbXBvbmVudDogIiArIGNvbXBvbmVudCwgY29tcG9uZW50LnRhZ05hbWUgIT09ICcnIHx8IHByb3BzLmlkID09PSBjb21wb25lbnQuZWxlbWVudElkIHx8ICFjb21wb25lbnQuZWxlbWVudElkICYmIGNvbXBvbmVudC5lbGVtZW50SWQgIT09ICcnKSk7CiAgICAoZmFsc2UgJiYgIShjb21wb25lbnQudGFnTmFtZSAhPT0gJycgfHwgIWNvbXBvbmVudC5hdHRyaWJ1dGVCaW5kaW5ncyB8fCBjb21wb25lbnQuYXR0cmlidXRlQmluZGluZ3MubGVuZ3RoID09PSAwKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3QgdXNlIGBhdHRyaWJ1dGVCaW5kaW5nc2Agb24gYSB0YWctbGVzcyBjb21wb25lbnQ6ICIgKyBjb21wb25lbnQsIGNvbXBvbmVudC50YWdOYW1lICE9PSAnJyB8fCAhY29tcG9uZW50LmF0dHJpYnV0ZUJpbmRpbmdzIHx8IGNvbXBvbmVudC5hdHRyaWJ1dGVCaW5kaW5ncy5sZW5ndGggPT09IDApKTsKICB9CgogIGZ1bmN0aW9uIGluaXRpYWxSZW5kZXJJbnN0cnVtZW50RGV0YWlscyhjb21wb25lbnQpIHsKICAgIHJldHVybiBjb21wb25lbnQuaW5zdHJ1bWVudERldGFpbHMoewogICAgICBpbml0aWFsUmVuZGVyOiB0cnVlCiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHJlcmVuZGVySW5zdHJ1bWVudERldGFpbHMoY29tcG9uZW50KSB7CiAgICByZXR1cm4gY29tcG9uZW50Lmluc3RydW1lbnREZXRhaWxzKHsKICAgICAgaW5pdGlhbFJlbmRlcjogZmFsc2UKICAgIH0pOwogIH0KCiAgdmFyIENVUkxZX0NBUEFCSUxJVElFUyA9IHsKICAgIGR5bmFtaWNMYXlvdXQ6IHRydWUsCiAgICBkeW5hbWljVGFnOiB0cnVlLAogICAgcHJlcGFyZUFyZ3M6IHRydWUsCiAgICBjcmVhdGVBcmdzOiB0cnVlLAogICAgYXR0cmlidXRlSG9vazogdHJ1ZSwKICAgIGVsZW1lbnRIb29rOiB0cnVlLAogICAgY3JlYXRlQ2FsbGVyOiB0cnVlLAogICAgZHluYW1pY1Njb3BlOiB0cnVlLAogICAgdXBkYXRlSG9vazogdHJ1ZSwKICAgIGNyZWF0ZUluc3RhbmNlOiB0cnVlCiAgfTsKICB2YXIgQ1VSTFlfQ09NUE9ORU5UX01BTkFHRVIgPSBuZXcgQ3VybHlDb21wb25lbnRNYW5hZ2VyKCk7CgogIHZhciBDdXJseUNvbXBvbmVudERlZmluaXRpb24gPSAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc2hhZG93ZWQtdmFyaWFibGUKICBmdW5jdGlvbiBDdXJseUNvbXBvbmVudERlZmluaXRpb24obmFtZSwgQ29tcG9uZW50Q2xhc3MsIGhhbmRsZSwgdGVtcGxhdGUkJDEsIGFyZ3MpIHsKICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICB0aGlzLkNvbXBvbmVudENsYXNzID0gQ29tcG9uZW50Q2xhc3M7CiAgICB0aGlzLmhhbmRsZSA9IGhhbmRsZTsKICAgIHRoaXMudGVtcGxhdGUgPSB0ZW1wbGF0ZSQkMTsKICAgIHRoaXMubWFuYWdlciA9IENVUkxZX0NPTVBPTkVOVF9NQU5BR0VSOwogICAgdmFyIGxheW91dCA9IHRlbXBsYXRlJCQxICYmIHRlbXBsYXRlJCQxLmFzTGF5b3V0KCk7CiAgICB2YXIgc3ltYm9sVGFibGUgPSBsYXlvdXQgPyBsYXlvdXQuc3ltYm9sVGFibGUgOiB1bmRlZmluZWQ7CiAgICB0aGlzLnN5bWJvbFRhYmxlID0gc3ltYm9sVGFibGU7CiAgICB0aGlzLnRlbXBsYXRlID0gdGVtcGxhdGUkJDE7CiAgICB0aGlzLmFyZ3MgPSBhcmdzOwogICAgdGhpcy5zdGF0ZSA9IHsKICAgICAgbmFtZTogbmFtZSwKICAgICAgQ29tcG9uZW50Q2xhc3M6IENvbXBvbmVudENsYXNzLAogICAgICBoYW5kbGU6IGhhbmRsZSwKICAgICAgdGVtcGxhdGU6IHRlbXBsYXRlJCQxLAogICAgICBjYXBhYmlsaXRpZXM6IENVUkxZX0NBUEFCSUxJVElFUywKICAgICAgc3ltYm9sVGFibGU6IHN5bWJvbFRhYmxlCiAgICB9OwogIH07CgogIHZhciBSb290Q29tcG9uZW50TWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ3VybHlDb21wb25lbnRNYW5hZ2UpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShSb290Q29tcG9uZW50TWFuYWdlciwgX0N1cmx5Q29tcG9uZW50TWFuYWdlKTsKCiAgICBmdW5jdGlvbiBSb290Q29tcG9uZW50TWFuYWdlcihjb21wb25lbnQpIHsKICAgICAgdmFyIF90aGlzMTk7CgogICAgICBfdGhpczE5ID0gX0N1cmx5Q29tcG9uZW50TWFuYWdlLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXMxOS5jb21wb25lbnQgPSBjb21wb25lbnQ7CiAgICAgIHJldHVybiBfdGhpczE5OwogICAgfQoKICAgIHZhciBfcHJvdG8zOSA9IFJvb3RDb21wb25lbnRNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zOS5nZXRMYXlvdXQgPSBmdW5jdGlvbiBnZXRMYXlvdXQoX3N0YXRlKSB7CiAgICAgIHZhciB0ZW1wbGF0ZSA9IHRoaXMudGVtcGxhdGVGb3IodGhpcy5jb21wb25lbnQpOwogICAgICB2YXIgbGF5b3V0ID0gdGVtcGxhdGUuYXNXcmFwcGVkTGF5b3V0KCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiBsYXlvdXQuY29tcGlsZSgpLAogICAgICAgIHN5bWJvbFRhYmxlOiBsYXlvdXQuc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvMzkuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKGVudmlyb25tZW50LCBfc3RhdGUsIF9hcmdzLCBkeW5hbWljU2NvcGUpIHsKICAgICAgdmFyIGNvbXBvbmVudCA9IHRoaXMuY29tcG9uZW50OwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuX3B1c2hUb0RlYnVnU3RhY2soY29tcG9uZW50Ll9kZWJ1Z0NvbnRhaW5lcktleSwgZW52aXJvbm1lbnQpOwogICAgICB9CgogICAgICB2YXIgZmluYWxpemVyID0gKDAsIF9pbnN0cnVtZW50YXRpb24uX2luc3RydW1lbnRTdGFydCkoJ3JlbmRlci5jb21wb25lbnQnLCBpbml0aWFsUmVuZGVySW5zdHJ1bWVudERldGFpbHMsIGNvbXBvbmVudCk7CiAgICAgIGR5bmFtaWNTY29wZS52aWV3ID0gY29tcG9uZW50OwogICAgICB2YXIgaGFzV3JhcHBlZEVsZW1lbnQgPSBjb21wb25lbnQudGFnTmFtZSAhPT0gJyc7IC8vIFdlIHVzdWFsbHkgZG8gdGhpcyBpbiB0aGUgYGRpZENyZWF0ZUVsZW1lbnRgLCBidXQgdGhhdCBob29rIGRvZXNuJ3QgZmlyZSBmb3IgdGFnbGVzcyBjb21wb25lbnRzCgogICAgICBpZiAoIWhhc1dyYXBwZWRFbGVtZW50KSB7CiAgICAgICAgaWYgKGVudmlyb25tZW50LmlzSW50ZXJhY3RpdmUpIHsKICAgICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCd3aWxsUmVuZGVyJyk7CiAgICAgICAgfQoKICAgICAgICBjb21wb25lbnQuX3RyYW5zaXRpb25UbygnaGFzRWxlbWVudCcpOwoKICAgICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgICAgY29tcG9uZW50LnRyaWdnZXIoJ3dpbGxJbnNlcnRFbGVtZW50Jyk7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgcHJvY2Vzc0NvbXBvbmVudEluaXRpYWxpemF0aW9uQXNzZXJ0aW9ucyhjb21wb25lbnQsIHt9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5ldyBDb21wb25lbnRTdGF0ZUJ1Y2tldChlbnZpcm9ubWVudCwgY29tcG9uZW50LCBudWxsLCBmaW5hbGl6ZXIsIGhhc1dyYXBwZWRFbGVtZW50KTsKICAgIH07CgogICAgcmV0dXJuIFJvb3RDb21wb25lbnRNYW5hZ2VyOwogIH0oQ3VybHlDb21wb25lbnRNYW5hZ2VyKTsgLy8gUk9PVCBpcyB0aGUgdG9wLWxldmVsIHRlbXBsYXRlIGl0IGhhcyBub3RoaW5nIGJ1dCBvbmUgeWllbGQuCiAgLy8gaXQgaXMgc3VwcG9zZWQgdG8gaGF2ZSBhIGR1bW15IGVsZW1lbnQKCgogIHZhciBST09UX0NBUEFCSUxJVElFUyA9IHsKICAgIGR5bmFtaWNMYXlvdXQ6IGZhbHNlLAogICAgZHluYW1pY1RhZzogdHJ1ZSwKICAgIHByZXBhcmVBcmdzOiBmYWxzZSwKICAgIGNyZWF0ZUFyZ3M6IGZhbHNlLAogICAgYXR0cmlidXRlSG9vazogdHJ1ZSwKICAgIGVsZW1lbnRIb29rOiB0cnVlLAogICAgY3JlYXRlQ2FsbGVyOiB0cnVlLAogICAgZHluYW1pY1Njb3BlOiB0cnVlLAogICAgdXBkYXRlSG9vazogdHJ1ZSwKICAgIGNyZWF0ZUluc3RhbmNlOiB0cnVlCiAgfTsKCiAgdmFyIFJvb3RDb21wb25lbnREZWZpbml0aW9uID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUm9vdENvbXBvbmVudERlZmluaXRpb24oY29tcG9uZW50KSB7CiAgICAgIHRoaXMuY29tcG9uZW50ID0gY29tcG9uZW50OwogICAgICB2YXIgbWFuYWdlciA9IG5ldyBSb290Q29tcG9uZW50TWFuYWdlcihjb21wb25lbnQpOwogICAgICB0aGlzLm1hbmFnZXIgPSBtYW5hZ2VyOwoKICAgICAgdmFyIGZhY3RvcnkgPSBfY29udGFpbmVyLkZBQ1RPUllfRk9SLmdldChjb21wb25lbnQpOwoKICAgICAgdGhpcy5zdGF0ZSA9IHsKICAgICAgICBuYW1lOiBmYWN0b3J5LmZ1bGxOYW1lLnNsaWNlKDEwKSwKICAgICAgICBjYXBhYmlsaXRpZXM6IFJPT1RfQ0FQQUJJTElUSUVTLAogICAgICAgIENvbXBvbmVudENsYXNzOiBmYWN0b3J5LAogICAgICAgIGhhbmRsZTogbnVsbAogICAgICB9OwogICAgfQoKICAgIHZhciBfcHJvdG80MCA9IFJvb3RDb21wb25lbnREZWZpbml0aW9uLnByb3RvdHlwZTsKCiAgICBfcHJvdG80MC5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoX3JlZjkpIHsKICAgICAgdmFyIGNvbXBvbmVudCA9IF9yZWY5LmNvbXBvbmVudDsKICAgICAgcmV0dXJuIGNvbXBvbmVudFtESVJUWV9UQUddOwogICAgfTsKCiAgICByZXR1cm4gUm9vdENvbXBvbmVudERlZmluaXRpb247CiAgfSgpOwoKICB2YXIgRHluYW1pY1Njb3BlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRHluYW1pY1Njb3BlKHZpZXcsIG91dGxldFN0YXRlKSB7CiAgICAgIHRoaXMudmlldyA9IHZpZXc7CiAgICAgIHRoaXMub3V0bGV0U3RhdGUgPSBvdXRsZXRTdGF0ZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDEgPSBEeW5hbWljU2NvcGUucHJvdG90eXBlOwoKICAgIF9wcm90bzQxLmNoaWxkID0gZnVuY3Rpb24gY2hpbGQoKSB7CiAgICAgIHJldHVybiBuZXcgRHluYW1pY1Njb3BlKHRoaXMudmlldywgdGhpcy5vdXRsZXRTdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzQxLmdldCA9IGZ1bmN0aW9uIGdldChrZXkpIHsKICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aAogICAgICAoZmFsc2UgJiYgIShrZXkgPT09ICdvdXRsZXRTdGF0ZScpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVXNpbmcgYC1nZXQtZHluYW1pYy1zY29wZWAgaXMgb25seSBzdXBwb3J0ZWQgZm9yIGBvdXRsZXRTdGF0ZWAgKHlvdSB1c2VkIGAiICsga2V5ICsgImApLiIsIGtleSA9PT0gJ291dGxldFN0YXRlJykpOwogICAgICByZXR1cm4gdGhpcy5vdXRsZXRTdGF0ZTsKICAgIH07CgogICAgX3Byb3RvNDEuc2V0ID0gZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUkJDEpIHsKICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aAogICAgICAoZmFsc2UgJiYgIShrZXkgPT09ICdvdXRsZXRTdGF0ZScpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVXNpbmcgYC13aXRoLWR5bmFtaWMtc2NvcGVgIGlzIG9ubHkgc3VwcG9ydGVkIGZvciBgb3V0bGV0U3RhdGVgICh5b3UgdXNlZCBgIiArIGtleSArICJgKS4iLCBrZXkgPT09ICdvdXRsZXRTdGF0ZScpKTsKICAgICAgdGhpcy5vdXRsZXRTdGF0ZSA9IHZhbHVlJCQxOwogICAgICByZXR1cm4gdmFsdWUkJDE7CiAgICB9OwoKICAgIHJldHVybiBEeW5hbWljU2NvcGU7CiAgfSgpOwoKICB2YXIgUm9vdFN0YXRlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUm9vdFN0YXRlKHJvb3QsIGVudiwgdGVtcGxhdGUsIHNlbGYsIHBhcmVudEVsZW1lbnQsIGR5bmFtaWNTY29wZSwgYnVpbGRlcikgewogICAgICB2YXIgX3RoaXMyMCA9IHRoaXM7CgogICAgICAoZmFsc2UgJiYgISh0ZW1wbGF0ZSAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3QgcmVuZGVyIGAiICsgc2VsZi52YWx1ZSgpICsgImAgd2l0aG91dCBhIHRlbXBsYXRlLiIsIHRlbXBsYXRlICE9PSB1bmRlZmluZWQpKTsKICAgICAgdGhpcy5pZCA9ICgwLCBfdmlld3MuZ2V0Vmlld0lkKShyb290KTsKICAgICAgdGhpcy5lbnYgPSBlbnY7CiAgICAgIHRoaXMucm9vdCA9IHJvb3Q7CiAgICAgIHRoaXMucmVzdWx0ID0gdW5kZWZpbmVkOwogICAgICB0aGlzLnNob3VsZFJlZmx1c2ggPSBmYWxzZTsKICAgICAgdGhpcy5kZXN0cm95ZWQgPSBmYWxzZTsKICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMgPSB7CiAgICAgICAgYWx3YXlzUmV2YWxpZGF0ZTogZmFsc2UKICAgICAgfTsKCiAgICAgIHRoaXMucmVuZGVyID0gZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBsYXlvdXQgPSB0ZW1wbGF0ZS5hc0xheW91dCgpOwogICAgICAgIHZhciBoYW5kbGUgPSBsYXlvdXQuY29tcGlsZSgpOwogICAgICAgIHZhciBpdGVyYXRvciA9ICgwLCBfcnVudGltZTIucmVuZGVyTWFpbikobGF5b3V0Wydjb21waWxlciddLnByb2dyYW0sIGVudiwgc2VsZiwgZHluYW1pY1Njb3BlLCBidWlsZGVyKGVudiwgewogICAgICAgICAgZWxlbWVudDogcGFyZW50RWxlbWVudCwKICAgICAgICAgIG5leHRTaWJsaW5nOiBudWxsCiAgICAgICAgfSksIGhhbmRsZSk7CiAgICAgICAgdmFyIGl0ZXJhdG9yUmVzdWx0OwoKICAgICAgICBkbyB7CiAgICAgICAgICBpdGVyYXRvclJlc3VsdCA9IGl0ZXJhdG9yLm5leHQoKTsKICAgICAgICB9IHdoaWxlICghaXRlcmF0b3JSZXN1bHQuZG9uZSk7CgogICAgICAgIHZhciByZXN1bHQgPSBfdGhpczIwLnJlc3VsdCA9IGl0ZXJhdG9yUmVzdWx0LnZhbHVlOyAvLyBvdmVycmlkZSAucmVuZGVyIGZ1bmN0aW9uIGFmdGVyIGluaXRpYWwgcmVuZGVyCgogICAgICAgIF90aGlzMjAucmVuZGVyID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuIHJlc3VsdC5yZXJlbmRlcihvcHRpb25zKTsKICAgICAgICB9OwogICAgICB9OwogICAgfQoKICAgIHZhciBfcHJvdG80MiA9IFJvb3RTdGF0ZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNDIuaXNGb3IgPSBmdW5jdGlvbiBpc0Zvcihwb3NzaWJsZVJvb3QpIHsKICAgICAgcmV0dXJuIHRoaXMucm9vdCA9PT0gcG9zc2libGVSb290OwogICAgfTsKCiAgICBfcHJvdG80Mi5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdmFyIHJlc3VsdCA9IHRoaXMucmVzdWx0LAogICAgICAgICAgZW52ID0gdGhpcy5lbnY7CiAgICAgIHRoaXMuZGVzdHJveWVkID0gdHJ1ZTsKICAgICAgdGhpcy5lbnYgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMucm9vdCA9IG51bGw7CiAgICAgIHRoaXMucmVzdWx0ID0gdW5kZWZpbmVkOwogICAgICB0aGlzLnJlbmRlciA9IHVuZGVmaW5lZDsKCiAgICAgIGlmIChyZXN1bHQpIHsKICAgICAgICAvKgogICAgICAgICBIYW5kbGVzIHRoZXNlIHNjZW5hcmlvczoKICAgICAgICAgICAgICAgICogV2hlbiByb290cyBhcmUgcmVtb3ZlZCBkdXJpbmcgc3RhbmRhcmQgcmVuZGVyaW5nIHByb2Nlc3MsIGEgdHJhbnNhY3Rpb24gZXhpc3RzIGFscmVhZHkKICAgICAgICAgICBgLmJlZ2luKClgIC8gYC5jb21taXQoKWAgYXJlIG5vdCBuZWVkZWQuCiAgICAgICAgICogV2hlbiByb290cyBhcmUgYmVpbmcgZGVzdHJveWVkIG1hbnVhbGx5IChgY29tcG9uZW50LmFwcGVuZCgpOyBjb21wb25lbnQuZGVzdHJveSgpIGNhc2UpLCBubwogICAgICAgICAgIHRyYW5zYWN0aW9uIGV4aXN0cyBhbHJlYWR5LgogICAgICAgICAqIFdoZW4gcm9vdHMgYXJlIGJlaW5nIGRlc3Ryb3llZCBkdXJpbmcgYFJlbmRlcmVyI2Rlc3Ryb3lgLCBubyB0cmFuc2FjdGlvbiBleGlzdHMKICAgICAgICAgICAgICAgICovCiAgICAgICAgdmFyIG5lZWRzVHJhbnNhY3Rpb24gPSAhZW52LmluVHJhbnNhY3Rpb247CgogICAgICAgIGlmIChuZWVkc1RyYW5zYWN0aW9uKSB7CiAgICAgICAgICBlbnYuYmVnaW4oKTsKICAgICAgICB9CgogICAgICAgIHRyeSB7CiAgICAgICAgICByZXN1bHQuZGVzdHJveSgpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBpZiAobmVlZHNUcmFuc2FjdGlvbikgewogICAgICAgICAgICBlbnYuY29tbWl0KCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBSb290U3RhdGU7CiAgfSgpOwoKICB2YXIgcmVuZGVyZXJzID0gW107CgogIGZ1bmN0aW9uIF9yZXNldFJlbmRlcmVycygpIHsKICAgIHJlbmRlcmVycy5sZW5ndGggPSAwOwogIH0KCiAgZnVuY3Rpb24gcmVnaXN0ZXIocmVuZGVyZXIpIHsKICAgIChmYWxzZSAmJiAhKHJlbmRlcmVycy5pbmRleE9mKHJlbmRlcmVyKSA9PT0gLTEpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IHJlZ2lzdGVyIHRoZSBzYW1lIHJlbmRlcmVyIHR3aWNlJywgcmVuZGVyZXJzLmluZGV4T2YocmVuZGVyZXIpID09PSAtMSkpOwogICAgcmVuZGVyZXJzLnB1c2gocmVuZGVyZXIpOwogIH0KCiAgZnVuY3Rpb24gZGVyZWdpc3RlcihyZW5kZXJlcikgewogICAgdmFyIGluZGV4ID0gcmVuZGVyZXJzLmluZGV4T2YocmVuZGVyZXIpOwogICAgKGZhbHNlICYmICEoaW5kZXggIT09IC0xKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0Nhbm5vdCBkZXJlZ2lzdGVyIHVua25vd24gdW5yZWdpc3RlcmVkIHJlbmRlcmVyJywgaW5kZXggIT09IC0xKSk7CiAgICByZW5kZXJlcnMuc3BsaWNlKGluZGV4LCAxKTsKICB9CgogIGZ1bmN0aW9uIGxvb3BCZWdpbigpIHsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVuZGVyZXJzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHJlbmRlcmVyc1tpXS5fc2NoZWR1bGVSZXZhbGlkYXRlKCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBLKCkgewogICAgLyogbm9vcCAqLwogIH0KCiAgdmFyIHJlbmRlclNldHRsZWREZWZlcnJlZCA9IG51bGw7CiAgLyoKICAgIFJldHVybnMgYSBwcm9taXNlIHdoaWNoIHdpbGwgcmVzb2x2ZSB3aGVuIHJlbmRlcmluZyBoYXMgc2V0dGxlZC4gU2V0dGxlZCBpbgogICAgdGhpcyBjb250ZXh0IGlzIGRlZmluZWQgYXMgd2hlbiBhbGwgb2YgdGhlIHRhZ3MgaW4gdXNlIGFyZSAiY3VycmVudCIgKGUuZy4KICAgIGByZW5kZXJlcnMuZXZlcnkociA9PiByLl9pc1ZhbGlkKCkpYCkuIFdoZW4gdGhpcyBpcyBjaGVja2VkIGF0IHRoZSBfZW5kXyBvZgogICAgdGhlIHJ1biBsb29wLCB0aGlzIGVzc2VudGlhbGx5IGd1YXJhbnRlZXMgdGhhdCBhbGwgcmVuZGVyaW5nIGlzIGNvbXBsZXRlZC4KICAKICAgIEBtZXRob2QgcmVuZGVyU2V0dGxlZAogICAgQHJldHVybnMge1Byb21pc2U8dm9pZD59IGEgcHJvbWlzZSB3aGljaCBmdWxmaWxscyB3aGVuIHJlbmRlcmluZyBoYXMgc2V0dGxlZAogICovCgogIGZ1bmN0aW9uIHJlbmRlclNldHRsZWQoKSB7CiAgICBpZiAocmVuZGVyU2V0dGxlZERlZmVycmVkID09PSBudWxsKSB7CiAgICAgIHJlbmRlclNldHRsZWREZWZlcnJlZCA9IF9yc3ZwLmRlZmF1bHQuZGVmZXIoKTsgLy8gaWYgdGhlcmUgaXMgbm8gY3VycmVudCBydW5sb29wLCB0aGUgcHJvbWlzZSBjcmVhdGVkIGFib3ZlIHdpbGwgbm90IGhhdmUKICAgICAgLy8gYSBjaGFuY2UgdG8gcmVzb2x2ZSAoYmVjYXVzZSBpdHMgcmVzb2x2ZWQgaW4gYmFja2J1cm5lcidzICJlbmQiIGV2ZW50KQoKICAgICAgaWYgKCEoMCwgX3J1bmxvb3AuZ2V0Q3VycmVudFJ1bkxvb3ApKCkpIHsKICAgICAgICAvLyBlbnN1cmUgYSBydW5sb29wIGhhcyBiZWVuIGtpY2tlZCBvZmYKICAgICAgICBfcnVubG9vcC5iYWNrYnVybmVyLnNjaGVkdWxlKCdhY3Rpb25zJywgbnVsbCwgSyk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcmVuZGVyU2V0dGxlZERlZmVycmVkLnByb21pc2U7CiAgfQoKICBmdW5jdGlvbiByZXNvbHZlUmVuZGVyUHJvbWlzZSgpIHsKICAgIGlmIChyZW5kZXJTZXR0bGVkRGVmZXJyZWQgIT09IG51bGwpIHsKICAgICAgdmFyIHJlc29sdmUgPSByZW5kZXJTZXR0bGVkRGVmZXJyZWQucmVzb2x2ZTsKICAgICAgcmVuZGVyU2V0dGxlZERlZmVycmVkID0gbnVsbDsKCiAgICAgIF9ydW5sb29wLmJhY2tidXJuZXIuam9pbihudWxsLCByZXNvbHZlKTsKICAgIH0KICB9CgogIHZhciBsb29wcyA9IDA7CgogIGZ1bmN0aW9uIGxvb3BFbmQoKSB7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbmRlcmVycy5sZW5ndGg7IGkrKykgewogICAgICBpZiAoIXJlbmRlcmVyc1tpXS5faXNWYWxpZCgpKSB7CiAgICAgICAgaWYgKGxvb3BzID4gX2Vudmlyb25tZW50Mi5FTlYuX1JFUkVOREVSX0xPT1BfTElNSVQpIHsKICAgICAgICAgIGxvb3BzID0gMDsgLy8gVE9ETzogZG8gc29tZXRoaW5nIGJldHRlcgoKICAgICAgICAgIHJlbmRlcmVyc1tpXS5kZXN0cm95KCk7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2luZmluaXRlIHJlbmRlcmluZyBpbnZhbGlkYXRpb24gZGV0ZWN0ZWQnKTsKICAgICAgICB9CgogICAgICAgIGxvb3BzKys7CiAgICAgICAgcmV0dXJuIF9ydW5sb29wLmJhY2tidXJuZXIuam9pbihudWxsLCBLKTsKICAgICAgfQogICAgfQoKICAgIGxvb3BzID0gMDsKICAgIHJlc29sdmVSZW5kZXJQcm9taXNlKCk7CiAgfQoKICBfcnVubG9vcC5iYWNrYnVybmVyLm9uKCdiZWdpbicsIGxvb3BCZWdpbik7CgogIF9ydW5sb29wLmJhY2tidXJuZXIub24oJ2VuZCcsIGxvb3BFbmQpOwoKICB2YXIgUmVuZGVyZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBSZW5kZXJlcihlbnYsIHJvb3RUZW1wbGF0ZSwgdmlld1JlZ2lzdHJ5LCBkZXN0aW5lZEZvckRPTSwgYnVpbGRlcikgewogICAgICBpZiAoZGVzdGluZWRGb3JET00gPT09IHZvaWQgMCkgewogICAgICAgIGRlc3RpbmVkRm9yRE9NID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIGlmIChidWlsZGVyID09PSB2b2lkIDApIHsKICAgICAgICBidWlsZGVyID0gX3J1bnRpbWUyLmNsaWVudEJ1aWxkZXI7CiAgICAgIH0KCiAgICAgIHRoaXMuX2VudiA9IGVudjsKICAgICAgdGhpcy5fcm9vdFRlbXBsYXRlID0gcm9vdFRlbXBsYXRlKGVudi5vd25lcik7CiAgICAgIHRoaXMuX3ZpZXdSZWdpc3RyeSA9IHZpZXdSZWdpc3RyeTsKICAgICAgdGhpcy5fZGVzdGluZWRGb3JET00gPSBkZXN0aW5lZEZvckRPTTsKICAgICAgdGhpcy5fZGVzdHJveWVkID0gZmFsc2U7CiAgICAgIHRoaXMuX3Jvb3RzID0gW107CiAgICAgIHRoaXMuX2xhc3RSZXZpc2lvbiA9IC0xOwogICAgICB0aGlzLl9pc1JlbmRlcmluZ1Jvb3RzID0gZmFsc2U7CiAgICAgIHRoaXMuX3JlbW92ZWRSb290cyA9IFtdOwogICAgICB0aGlzLl9idWlsZGVyID0gYnVpbGRlcjsKICAgIH0gLy8gcmVuZGVyZXIgSE9PS1MKCgogICAgdmFyIF9wcm90bzQzID0gUmVuZGVyZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzQzLmFwcGVuZE91dGxldFZpZXcgPSBmdW5jdGlvbiBhcHBlbmRPdXRsZXRWaWV3KHZpZXcsIHRhcmdldCkgewogICAgICB2YXIgZGVmaW5pdGlvbiA9IGNyZWF0ZVJvb3RPdXRsZXQodmlldyk7CgogICAgICB0aGlzLl9hcHBlbmREZWZpbml0aW9uKHZpZXcsICgwLCBfcnVudGltZTIuY3VycnkpKGRlZmluaXRpb24pLCB0YXJnZXQpOwogICAgfTsKCiAgICBfcHJvdG80My5hcHBlbmRUbyA9IGZ1bmN0aW9uIGFwcGVuZFRvKHZpZXcsIHRhcmdldCkgewogICAgICB2YXIgZGVmaW5pdGlvbiA9IG5ldyBSb290Q29tcG9uZW50RGVmaW5pdGlvbih2aWV3KTsKCiAgICAgIHRoaXMuX2FwcGVuZERlZmluaXRpb24odmlldywgKDAsIF9ydW50aW1lMi5jdXJyeSkoZGVmaW5pdGlvbiksIHRhcmdldCk7CiAgICB9OwoKICAgIF9wcm90bzQzLl9hcHBlbmREZWZpbml0aW9uID0gZnVuY3Rpb24gX2FwcGVuZERlZmluaXRpb24ocm9vdCwgZGVmaW5pdGlvbiwgdGFyZ2V0KSB7CiAgICAgIHZhciBzZWxmID0gbmV3IFVuYm91bmRSZWZlcmVuY2UoZGVmaW5pdGlvbik7CiAgICAgIHZhciBkeW5hbWljU2NvcGUgPSBuZXcgRHluYW1pY1Njb3BlKG51bGwsIF9ydW50aW1lMi5VTkRFRklORURfUkVGRVJFTkNFKTsKICAgICAgdmFyIHJvb3RTdGF0ZSA9IG5ldyBSb290U3RhdGUocm9vdCwgdGhpcy5fZW52LCB0aGlzLl9yb290VGVtcGxhdGUsIHNlbGYsIHRhcmdldCwgZHluYW1pY1Njb3BlLCB0aGlzLl9idWlsZGVyKTsKCiAgICAgIHRoaXMuX3JlbmRlclJvb3Qocm9vdFN0YXRlKTsKICAgIH07CgogICAgX3Byb3RvNDMucmVyZW5kZXIgPSBmdW5jdGlvbiByZXJlbmRlcigpIHsKICAgICAgdGhpcy5fc2NoZWR1bGVSZXZhbGlkYXRlKCk7CiAgICB9OwoKICAgIF9wcm90bzQzLnJlZ2lzdGVyID0gZnVuY3Rpb24gcmVnaXN0ZXIodmlldykgewogICAgICB2YXIgaWQgPSAoMCwgX3ZpZXdzLmdldFZpZXdJZCkodmlldyk7CiAgICAgIChmYWxzZSAmJiAhKCF0aGlzLl92aWV3UmVnaXN0cnlbaWRdKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0F0dGVtcHRlZCB0byByZWdpc3RlciBhIHZpZXcgd2l0aCBhbiBpZCBhbHJlYWR5IGluIHVzZTogJyArIGlkLCAhdGhpcy5fdmlld1JlZ2lzdHJ5W2lkXSkpOwogICAgICB0aGlzLl92aWV3UmVnaXN0cnlbaWRdID0gdmlldzsKICAgIH07CgogICAgX3Byb3RvNDMudW5yZWdpc3RlciA9IGZ1bmN0aW9uIHVucmVnaXN0ZXIodmlldykgewogICAgICBkZWxldGUgdGhpcy5fdmlld1JlZ2lzdHJ5WygwLCBfdmlld3MuZ2V0Vmlld0lkKSh2aWV3KV07CiAgICB9OwoKICAgIF9wcm90bzQzLnJlbW92ZSA9IGZ1bmN0aW9uIHJlbW92ZSh2aWV3KSB7CiAgICAgIHZpZXcuX3RyYW5zaXRpb25UbygnZGVzdHJveWluZycpOwoKICAgICAgdGhpcy5jbGVhbnVwUm9vdEZvcih2aWV3KTsKCiAgICAgIGlmICh0aGlzLl9kZXN0aW5lZEZvckRPTSkgewogICAgICAgIHZpZXcudHJpZ2dlcignZGlkRGVzdHJveUVsZW1lbnQnKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG80My5jbGVhbnVwUm9vdEZvciA9IGZ1bmN0aW9uIGNsZWFudXBSb290Rm9yKHZpZXcpIHsKICAgICAgLy8gbm8gbmVlZCB0byBjbGVhbnVwIHJvb3RzIGlmIHdlIGhhdmUgYWxyZWFkeSBiZWVuIGRlc3Ryb3llZAogICAgICBpZiAodGhpcy5fZGVzdHJveWVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgcm9vdHMgPSB0aGlzLl9yb290czsgLy8gdHJhdmVyc2UgaW4gcmV2ZXJzZSBzbyB3ZSBjYW4gcmVtb3ZlIGl0ZW1zCiAgICAgIC8vIHdpdGhvdXQgbXVja2luZyB1cCB0aGUgaW5kZXgKCiAgICAgIHZhciBpID0gdGhpcy5fcm9vdHMubGVuZ3RoOwoKICAgICAgd2hpbGUgKGktLSkgewogICAgICAgIHZhciByb290ID0gcm9vdHNbaV07CgogICAgICAgIGlmIChyb290LmlzRm9yKHZpZXcpKSB7CiAgICAgICAgICByb290LmRlc3Ryb3koKTsKICAgICAgICAgIHJvb3RzLnNwbGljZShpLCAxKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNDMuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIGlmICh0aGlzLl9kZXN0cm95ZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuX2Rlc3Ryb3llZCA9IHRydWU7CgogICAgICB0aGlzLl9jbGVhckFsbFJvb3RzKCk7CiAgICB9OwoKICAgIF9wcm90bzQzLmdldEJvdW5kcyA9IGZ1bmN0aW9uIGdldEJvdW5kcyh2aWV3KSB7CiAgICAgIHZhciBib3VuZHMgPSB2aWV3W0JPVU5EU107CiAgICAgIHZhciBwYXJlbnRFbGVtZW50ID0gYm91bmRzLnBhcmVudEVsZW1lbnQoKTsKICAgICAgdmFyIGZpcnN0Tm9kZSA9IGJvdW5kcy5maXJzdE5vZGUoKTsKICAgICAgdmFyIGxhc3ROb2RlID0gYm91bmRzLmxhc3ROb2RlKCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgcGFyZW50RWxlbWVudDogcGFyZW50RWxlbWVudCwKICAgICAgICBmaXJzdE5vZGU6IGZpcnN0Tm9kZSwKICAgICAgICBsYXN0Tm9kZTogbGFzdE5vZGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvNDMuY3JlYXRlRWxlbWVudCA9IGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodGFnTmFtZSkgewogICAgICByZXR1cm4gdGhpcy5fZW52LmdldEFwcGVuZE9wZXJhdGlvbnMoKS5jcmVhdGVFbGVtZW50KHRhZ05hbWUpOwogICAgfTsKCiAgICBfcHJvdG80My5fcmVuZGVyUm9vdCA9IGZ1bmN0aW9uIF9yZW5kZXJSb290KHJvb3QpIHsKICAgICAgdmFyIHJvb3RzID0gdGhpcy5fcm9vdHM7CiAgICAgIHJvb3RzLnB1c2gocm9vdCk7CgogICAgICBpZiAocm9vdHMubGVuZ3RoID09PSAxKSB7CiAgICAgICAgcmVnaXN0ZXIodGhpcyk7CiAgICAgIH0KCiAgICAgIHRoaXMuX3JlbmRlclJvb3RzVHJhbnNhY3Rpb24oKTsKICAgIH07CgogICAgX3Byb3RvNDMuX3JlbmRlclJvb3RzID0gZnVuY3Rpb24gX3JlbmRlclJvb3RzKCkgewogICAgICB2YXIgcm9vdHMgPSB0aGlzLl9yb290cywKICAgICAgICAgIGVudiA9IHRoaXMuX2VudiwKICAgICAgICAgIHJlbW92ZWRSb290cyA9IHRoaXMuX3JlbW92ZWRSb290czsKICAgICAgdmFyIGdsb2JhbFNob3VsZFJlZmx1c2ggPSBmYWxzZTsKICAgICAgdmFyIGluaXRpYWxSb290c0xlbmd0aDsKCiAgICAgIGRvIHsKICAgICAgICBlbnYuYmVnaW4oKTsKCiAgICAgICAgdHJ5IHsKICAgICAgICAgIC8vIGVuc3VyZSB0aGF0IGZvciB0aGUgZmlyc3QgaXRlcmF0aW9uIG9mIHRoZSBsb29wCiAgICAgICAgICAvLyBlYWNoIHJvb3QgaXMgcHJvY2Vzc2VkCiAgICAgICAgICBpbml0aWFsUm9vdHNMZW5ndGggPSByb290cy5sZW5ndGg7CiAgICAgICAgICBnbG9iYWxTaG91bGRSZWZsdXNoID0gZmFsc2U7CgogICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb290cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICB2YXIgcm9vdCA9IHJvb3RzW2ldOwoKICAgICAgICAgICAgaWYgKHJvb3QuZGVzdHJveWVkKSB7CiAgICAgICAgICAgICAgLy8gYWRkIHRvIHRoZSBsaXN0IG9mIHJvb3RzIHRvIGJlIHJlbW92ZWQKICAgICAgICAgICAgICAvLyB0aGV5IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIGB0aGlzLl9yb290c2AgbGF0ZXIKICAgICAgICAgICAgICByZW1vdmVkUm9vdHMucHVzaChyb290KTsgLy8gc2tpcCBvdmVyIHJvb3RzIHRoYXQgaGF2ZSBiZWVuIG1hcmtlZCBhcyBkZXN0cm95ZWQKCiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHZhciBzaG91bGRSZWZsdXNoID0gcm9vdC5zaG91bGRSZWZsdXNoOyAvLyB3aGVuIHByb2Nlc3Npbmcgbm9uLWluaXRpYWwgcmVmbHVzaCBsb29wcywKICAgICAgICAgICAgLy8gZG8gbm90IHByb2Nlc3MgbW9yZSByb290cyB0aGFuIG5lZWRlZAoKICAgICAgICAgICAgaWYgKGkgPj0gaW5pdGlhbFJvb3RzTGVuZ3RoICYmICFzaG91bGRSZWZsdXNoKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHJvb3Qub3B0aW9ucy5hbHdheXNSZXZhbGlkYXRlID0gc2hvdWxkUmVmbHVzaDsgLy8gdHJhY2sgc2hvdWxkUmVmbHVzaCBiYXNlZCBvbiB0aGlzIHJvb3RzIHJlbmRlciByZXN1bHQKCiAgICAgICAgICAgIHNob3VsZFJlZmx1c2ggPSByb290LnNob3VsZFJlZmx1c2ggPSAoMCwgX21ldGFsLnJ1bkluVHJhbnNhY3Rpb24pKHJvb3QsICdyZW5kZXInKTsgLy8gZ2xvYmFsU2hvdWxkUmVmbHVzaCBzaG91bGQgYmUgYHRydWVgIGlmICphbnkqIG9mCiAgICAgICAgICAgIC8vIHRoZSByb290cyBuZWVkIHRvIHJlZmx1c2gKCiAgICAgICAgICAgIGdsb2JhbFNob3VsZFJlZmx1c2ggPSBnbG9iYWxTaG91bGRSZWZsdXNoIHx8IHNob3VsZFJlZmx1c2g7CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5fbGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKF9yZWZlcmVuY2UuQ1VSUkVOVF9UQUcpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBlbnYuY29tbWl0KCk7CiAgICAgICAgfQogICAgICB9IHdoaWxlIChnbG9iYWxTaG91bGRSZWZsdXNoIHx8IHJvb3RzLmxlbmd0aCA+IGluaXRpYWxSb290c0xlbmd0aCk7IC8vIHJlbW92ZSBhbnkgcm9vdHMgdGhhdCB3ZXJlIGRlc3Ryb3llZCBkdXJpbmcgdGhpcyB0cmFuc2FjdGlvbgoKCiAgICAgIHdoaWxlIChyZW1vdmVkUm9vdHMubGVuZ3RoKSB7CiAgICAgICAgdmFyIF9yb290ID0gcmVtb3ZlZFJvb3RzLnBvcCgpOwoKICAgICAgICB2YXIgcm9vdEluZGV4ID0gcm9vdHMuaW5kZXhPZihfcm9vdCk7CiAgICAgICAgcm9vdHMuc3BsaWNlKHJvb3RJbmRleCwgMSk7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLl9yb290cy5sZW5ndGggPT09IDApIHsKICAgICAgICBkZXJlZ2lzdGVyKHRoaXMpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQzLl9yZW5kZXJSb290c1RyYW5zYWN0aW9uID0gZnVuY3Rpb24gX3JlbmRlclJvb3RzVHJhbnNhY3Rpb24oKSB7CiAgICAgIGlmICh0aGlzLl9pc1JlbmRlcmluZ1Jvb3RzKSB7CiAgICAgICAgLy8gY3VycmVudGx5IHJlbmRlcmluZyByb290cywgYSBuZXcgcm9vdCB3YXMgYWRkZWQgYW5kIHdpbGwKICAgICAgICAvLyBiZSBwcm9jZXNzZWQgYnkgdGhlIGV4aXN0aW5nIF9yZW5kZXJSb290cyBpbnZvY2F0aW9uCiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIHVzZWQgdG8gcHJldmVudCBjYWxsaW5nIF9yZW5kZXJSb290cyBhZ2FpbiAoc2VlIGFib3ZlKQogICAgICAvLyB3aGlsZSB3ZSBhcmUgYWN0aXZlbHkgcmVuZGVyaW5nIHJvb3RzCgoKICAgICAgdGhpcy5faXNSZW5kZXJpbmdSb290cyA9IHRydWU7CiAgICAgIHZhciBjb21wbGV0ZWRXaXRob3V0RXJyb3IgPSBmYWxzZTsKCiAgICAgIHRyeSB7CiAgICAgICAgdGhpcy5fcmVuZGVyUm9vdHMoKTsKCiAgICAgICAgY29tcGxldGVkV2l0aG91dEVycm9yID0gdHJ1ZTsKICAgICAgfSBmaW5hbGx5IHsKICAgICAgICBpZiAoIWNvbXBsZXRlZFdpdGhvdXRFcnJvcikgewogICAgICAgICAgdGhpcy5fbGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKF9yZWZlcmVuY2UuQ1VSUkVOVF9UQUcpOwoKICAgICAgICAgIGlmICh0aGlzLl9lbnYuaW5UcmFuc2FjdGlvbiA9PT0gdHJ1ZSkgewogICAgICAgICAgICB0aGlzLl9lbnYuY29tbWl0KCk7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB0aGlzLl9pc1JlbmRlcmluZ1Jvb3RzID0gZmFsc2U7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNDMuX2NsZWFyQWxsUm9vdHMgPSBmdW5jdGlvbiBfY2xlYXJBbGxSb290cygpIHsKICAgICAgdmFyIHJvb3RzID0gdGhpcy5fcm9vdHM7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvb3RzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIHJvb3QgPSByb290c1tpXTsKICAgICAgICByb290LmRlc3Ryb3koKTsKICAgICAgfQoKICAgICAgdGhpcy5fcmVtb3ZlZFJvb3RzLmxlbmd0aCA9IDA7CiAgICAgIHRoaXMuX3Jvb3RzID0gW107IC8vIGlmIHJvb3RzIHdlcmUgcHJlc2VudCBiZWZvcmUgZGVzdHJveWluZwogICAgICAvLyBkZXJlZ2lzdGVyIHRoaXMgcmVuZGVyZXIgaW5zdGFuY2UKCiAgICAgIGlmIChyb290cy5sZW5ndGgpIHsKICAgICAgICBkZXJlZ2lzdGVyKHRoaXMpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQzLl9zY2hlZHVsZVJldmFsaWRhdGUgPSBmdW5jdGlvbiBfc2NoZWR1bGVSZXZhbGlkYXRlKCkgewogICAgICBfcnVubG9vcC5iYWNrYnVybmVyLnNjaGVkdWxlT25jZSgncmVuZGVyJywgdGhpcywgdGhpcy5fcmV2YWxpZGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzQzLl9pc1ZhbGlkID0gZnVuY3Rpb24gX2lzVmFsaWQoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZXN0cm95ZWQgfHwgdGhpcy5fcm9vdHMubGVuZ3RoID09PSAwIHx8ICgwLCBfcmVmZXJlbmNlLnZhbGlkYXRlKShfcmVmZXJlbmNlLkNVUlJFTlRfVEFHLCB0aGlzLl9sYXN0UmV2aXNpb24pOwogICAgfTsKCiAgICBfcHJvdG80My5fcmV2YWxpZGF0ZSA9IGZ1bmN0aW9uIF9yZXZhbGlkYXRlKCkgewogICAgICBpZiAodGhpcy5faXNWYWxpZCgpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9yZW5kZXJSb290c1RyYW5zYWN0aW9uKCk7CiAgICB9OwoKICAgIHJldHVybiBSZW5kZXJlcjsKICB9KCk7CgogIF9leHBvcnRzLlJlbmRlcmVyID0gUmVuZGVyZXI7CgogIHZhciBJbmVydFJlbmRlcmVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9SZW5kZXJlcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEluZXJ0UmVuZGVyZXIsIF9SZW5kZXJlcik7CgogICAgZnVuY3Rpb24gSW5lcnRSZW5kZXJlcigpIHsKICAgICAgcmV0dXJuIF9SZW5kZXJlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgSW5lcnRSZW5kZXJlci5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoX3JlZjEwKSB7CiAgICAgIHZhciBlbnYgPSBfcmVmMTAuZW52LAogICAgICAgICAgcm9vdFRlbXBsYXRlID0gX3JlZjEwLnJvb3RUZW1wbGF0ZSwKICAgICAgICAgIF92aWV3UmVnaXN0cnkgPSBfcmVmMTAuX3ZpZXdSZWdpc3RyeSwKICAgICAgICAgIGJ1aWxkZXIgPSBfcmVmMTAuYnVpbGRlcjsKICAgICAgcmV0dXJuIG5ldyB0aGlzKGVudiwgcm9vdFRlbXBsYXRlLCBfdmlld1JlZ2lzdHJ5LCBmYWxzZSwgYnVpbGRlcik7CiAgICB9OwoKICAgIHZhciBfcHJvdG80NCA9IEluZXJ0UmVuZGVyZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzQ0LmdldEVsZW1lbnQgPSBmdW5jdGlvbiBnZXRFbGVtZW50KF92aWV3KSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignQWNjZXNzaW5nIGB0aGlzLmVsZW1lbnRgIGlzIG5vdCBhbGxvd2VkIGluIG5vbi1pbnRlcmFjdGl2ZSBlbnZpcm9ubWVudHMgKHN1Y2ggYXMgRmFzdEJvb3QpLicpOwogICAgfTsKCiAgICByZXR1cm4gSW5lcnRSZW5kZXJlcjsKICB9KFJlbmRlcmVyKTsKCiAgX2V4cG9ydHMuSW5lcnRSZW5kZXJlciA9IEluZXJ0UmVuZGVyZXI7CgogIHZhciBJbnRlcmFjdGl2ZVJlbmRlcmVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9SZW5kZXJlcjIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShJbnRlcmFjdGl2ZVJlbmRlcmVyLCBfUmVuZGVyZXIyKTsKCiAgICBmdW5jdGlvbiBJbnRlcmFjdGl2ZVJlbmRlcmVyKCkgewogICAgICByZXR1cm4gX1JlbmRlcmVyMi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgSW50ZXJhY3RpdmVSZW5kZXJlci5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoX3JlZjExKSB7CiAgICAgIHZhciBlbnYgPSBfcmVmMTEuZW52LAogICAgICAgICAgcm9vdFRlbXBsYXRlID0gX3JlZjExLnJvb3RUZW1wbGF0ZSwKICAgICAgICAgIF92aWV3UmVnaXN0cnkgPSBfcmVmMTEuX3ZpZXdSZWdpc3RyeSwKICAgICAgICAgIGJ1aWxkZXIgPSBfcmVmMTEuYnVpbGRlcjsKICAgICAgcmV0dXJuIG5ldyB0aGlzKGVudiwgcm9vdFRlbXBsYXRlLCBfdmlld1JlZ2lzdHJ5LCB0cnVlLCBidWlsZGVyKTsKICAgIH07CgogICAgdmFyIF9wcm90bzQ1ID0gSW50ZXJhY3RpdmVSZW5kZXJlci5wcm90b3R5cGU7CgogICAgX3Byb3RvNDUuZ2V0RWxlbWVudCA9IGZ1bmN0aW9uIGdldEVsZW1lbnQodmlldykgewogICAgICByZXR1cm4gKDAsIF92aWV3cy5nZXRWaWV3RWxlbWVudCkodmlldyk7CiAgICB9OwoKICAgIHJldHVybiBJbnRlcmFjdGl2ZVJlbmRlcmVyOwogIH0oUmVuZGVyZXIpOwoKICBfZXhwb3J0cy5JbnRlcmFjdGl2ZVJlbmRlcmVyID0gSW50ZXJhY3RpdmVSZW5kZXJlcjsKICB2YXIgVEVNUExBVEVTID0ge307CgogIGZ1bmN0aW9uIHNldFRlbXBsYXRlcyh0ZW1wbGF0ZXMpIHsKICAgIFRFTVBMQVRFUyA9IHRlbXBsYXRlczsKICB9CgogIGZ1bmN0aW9uIGdldFRlbXBsYXRlcygpIHsKICAgIHJldHVybiBURU1QTEFURVM7CiAgfQoKICBmdW5jdGlvbiBnZXRUZW1wbGF0ZShuYW1lKSB7CiAgICBpZiAoVEVNUExBVEVTLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIHJldHVybiBURU1QTEFURVNbbmFtZV07CiAgICB9CiAgfQoKICBmdW5jdGlvbiBoYXNUZW1wbGF0ZShuYW1lKSB7CiAgICByZXR1cm4gVEVNUExBVEVTLmhhc093blByb3BlcnR5KG5hbWUpOwogIH0KCiAgZnVuY3Rpb24gc2V0VGVtcGxhdGUobmFtZSwgdGVtcGxhdGUpIHsKICAgIHJldHVybiBURU1QTEFURVNbbmFtZV0gPSB0ZW1wbGF0ZTsKICB9CgogIHZhciBJbnRlcm5hbENvbXBvbmVudERlZmluaXRpb24gPSBmdW5jdGlvbiBJbnRlcm5hbENvbXBvbmVudERlZmluaXRpb24obWFuYWdlciwgQ29tcG9uZW50Q2xhc3MsIGxheW91dCkgewogICAgdGhpcy5tYW5hZ2VyID0gbWFuYWdlcjsKICAgIHRoaXMuc3RhdGUgPSB7CiAgICAgIENvbXBvbmVudENsYXNzOiBDb21wb25lbnRDbGFzcywKICAgICAgbGF5b3V0OiBsYXlvdXQKICAgIH07CiAgfTsKCiAgdmFyIEludGVybmFsTWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQWJzdHJhY3RNYW5hZ2VyMykgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEludGVybmFsTWFuYWdlciwgX0Fic3RyYWN0TWFuYWdlcjMpOwoKICAgIGZ1bmN0aW9uIEludGVybmFsTWFuYWdlcihvd25lcikgewogICAgICB2YXIgX3RoaXMyMTsKCiAgICAgIF90aGlzMjEgPSBfQWJzdHJhY3RNYW5hZ2VyMy5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMjEub3duZXIgPSBvd25lcjsKICAgICAgcmV0dXJuIF90aGlzMjE7CiAgICB9CgogICAgdmFyIF9wcm90bzQ2ID0gSW50ZXJuYWxNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG80Ni5nZXRMYXlvdXQgPSBmdW5jdGlvbiBnZXRMYXlvdXQoX3JlZjEyKSB7CiAgICAgIHZhciBfbGF5b3V0ID0gX3JlZjEyLmxheW91dDsKCiAgICAgIHZhciBsYXlvdXQgPSBfbGF5b3V0LmFzTGF5b3V0KCk7CgogICAgICByZXR1cm4gewogICAgICAgIGhhbmRsZTogbGF5b3V0LmNvbXBpbGUoKSwKICAgICAgICBzeW1ib2xUYWJsZTogbGF5b3V0LnN5bWJvbFRhYmxlCiAgICAgIH07CiAgICB9OwoKICAgIHJldHVybiBJbnRlcm5hbE1hbmFnZXI7CiAgfShBYnN0cmFjdE1hbmFnZXIpOwoKICB2YXIgQ0FQQUJJTElUSUVTJDEgPSB7CiAgICBkeW5hbWljTGF5b3V0OiBmYWxzZSwKICAgIGR5bmFtaWNUYWc6IGZhbHNlLAogICAgcHJlcGFyZUFyZ3M6IHRydWUsCiAgICBjcmVhdGVBcmdzOiB0cnVlLAogICAgYXR0cmlidXRlSG9vazogZmFsc2UsCiAgICBlbGVtZW50SG9vazogZmFsc2UsCiAgICBjcmVhdGVDYWxsZXI6IHRydWUsCiAgICBkeW5hbWljU2NvcGU6IGZhbHNlLAogICAgdXBkYXRlSG9vazogdHJ1ZSwKICAgIGNyZWF0ZUluc3RhbmNlOiB0cnVlCiAgfTsKICB2YXIgRU1QVFlfUE9TSVRJT05BTF9BUkdTJDEgPSBbXTsKICAoMCwgX2RlYnVnLmRlYnVnRnJlZXplKShFTVBUWV9QT1NJVElPTkFMX0FSR1MkMSk7CgogIHZhciBJbnB1dENvbXBvbmVudE1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0ludGVybmFsTWFuYWdlcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKElucHV0Q29tcG9uZW50TWFuYWdlciwgX0ludGVybmFsTWFuYWdlcik7CgogICAgZnVuY3Rpb24gSW5wdXRDb21wb25lbnRNYW5hZ2VyKCkgewogICAgICByZXR1cm4gX0ludGVybmFsTWFuYWdlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzQ3ID0gSW5wdXRDb21wb25lbnRNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG80Ny5nZXRDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiBnZXRDYXBhYmlsaXRpZXMoKSB7CiAgICAgIHJldHVybiBDQVBBQklMSVRJRVMkMTsKICAgIH07CgogICAgX3Byb3RvNDcucHJlcGFyZUFyZ3MgPSBmdW5jdGlvbiBwcmVwYXJlQXJncyhfc3RhdGUsIGFyZ3MpIHsKICAgICAgKGZhbHNlICYmICEoYXJncy5wb3NpdGlvbmFsLmxlbmd0aCA9PT0gMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgYDxJbnB1dCAvPmAgY29tcG9uZW50IGRvZXMgbm90IHRha2UgYW55IHBvc2l0aW9uYWwgYXJndW1lbnRzJywgYXJncy5wb3NpdGlvbmFsLmxlbmd0aCA9PT0gMCkpOwogICAgICB2YXIgX19BUkdTX18gPSBhcmdzLm5hbWVkLmNhcHR1cmUoKS5tYXA7CiAgICAgIHJldHVybiB7CiAgICAgICAgcG9zaXRpb25hbDogRU1QVFlfUE9TSVRJT05BTF9BUkdTJDEsCiAgICAgICAgbmFtZWQ6IHsKICAgICAgICAgIF9fQVJHU19fOiBuZXcgUm9vdFJlZmVyZW5jZShfX0FSR1NfXyksCiAgICAgICAgICB0eXBlOiBhcmdzLm5hbWVkLmdldCgndHlwZScpCiAgICAgICAgfQogICAgICB9OwogICAgfTsKCiAgICBfcHJvdG80Ny5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoX2VudiwgX3JlZjEzLCBhcmdzLCBfZHluYW1pY1Njb3BlLCBjYWxsZXIpIHsKICAgICAgdmFyIENvbXBvbmVudENsYXNzID0gX3JlZjEzLkNvbXBvbmVudENsYXNzOwogICAgICAoZmFsc2UgJiYgISgoMCwgX3JlZmVyZW5jZS5pc0NvbnN0KShjYWxsZXIpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2NhbGxlciBtdXN0IGJlIGNvbnN0JywgKDAsIF9yZWZlcmVuY2UuaXNDb25zdCkoY2FsbGVyKSkpOwogICAgICB2YXIgdHlwZSA9IGFyZ3MubmFtZWQuZ2V0KCd0eXBlJyk7CiAgICAgIHZhciBpbnN0YW5jZSA9IENvbXBvbmVudENsYXNzLmNyZWF0ZSh7CiAgICAgICAgY2FsbGVyOiBjYWxsZXIudmFsdWUoKSwKICAgICAgICB0eXBlOiB0eXBlLnZhbHVlKCkKICAgICAgfSk7CiAgICAgIHJldHVybiB7CiAgICAgICAgdHlwZTogdHlwZSwKICAgICAgICBpbnN0YW5jZTogaW5zdGFuY2UKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvNDcuZ2V0U2VsZiA9IGZ1bmN0aW9uIGdldFNlbGYoX3JlZjE0KSB7CiAgICAgIHZhciBpbnN0YW5jZSA9IF9yZWYxNC5pbnN0YW5jZTsKICAgICAgcmV0dXJuIG5ldyBSb290UmVmZXJlbmNlKGluc3RhbmNlKTsKICAgIH07CgogICAgX3Byb3RvNDcuZ2V0VGFnID0gZnVuY3Rpb24gZ2V0VGFnKCkgewogICAgICByZXR1cm4gX3JlZmVyZW5jZS5DT05TVEFOVF9UQUc7CiAgICB9OwoKICAgIF9wcm90bzQ3LnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZShfcmVmMTUpIHsKICAgICAgdmFyIHR5cGUgPSBfcmVmMTUudHlwZSwKICAgICAgICAgIGluc3RhbmNlID0gX3JlZjE1Lmluc3RhbmNlOwogICAgICAoMCwgX21ldGFsLnNldCkoaW5zdGFuY2UsICd0eXBlJywgdHlwZS52YWx1ZSgpKTsKICAgIH07CgogICAgX3Byb3RvNDcuZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3IoX3JlZjE2KSB7CiAgICAgIHZhciBpbnN0YW5jZSA9IF9yZWYxNi5pbnN0YW5jZTsKICAgICAgcmV0dXJuIGluc3RhbmNlOwogICAgfTsKCiAgICByZXR1cm4gSW5wdXRDb21wb25lbnRNYW5hZ2VyOwogIH0oSW50ZXJuYWxNYW5hZ2VyKTsKCiAgdmFyIElucHV0Q29tcG9uZW50TWFuYWdlckZhY3RvcnkgPSBmdW5jdGlvbiBJbnB1dENvbXBvbmVudE1hbmFnZXJGYWN0b3J5KG93bmVyKSB7CiAgICByZXR1cm4gbmV3IElucHV0Q29tcG9uZW50TWFuYWdlcihvd25lcik7CiAgfTsKCiAgdmFyIE1BTkFHRVJTID0gbmV3IFdlYWtNYXAoKTsKICB2YXIgZ2V0UHJvdG90eXBlT2YgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Y7CgogIGZ1bmN0aW9uIHNldE1hbmFnZXIod3JhcHBlciwgb2JqKSB7CiAgICBNQU5BR0VSUy5zZXQob2JqLCB3cmFwcGVyKTsKICAgIHJldHVybiBvYmo7CiAgfQoKICBmdW5jdGlvbiBnZXRNYW5hZ2VyKG9iaikgewogICAgdmFyIHBvaW50ZXIgPSBvYmo7CgogICAgd2hpbGUgKHBvaW50ZXIgIT09IHVuZGVmaW5lZCAmJiBwb2ludGVyICE9PSBudWxsKSB7CiAgICAgIHZhciBtYW5hZ2VyID0gTUFOQUdFUlMuZ2V0KHBvaW50ZXIpOwoKICAgICAgaWYgKG1hbmFnZXIgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBtYW5hZ2VyOwogICAgICB9CgogICAgICBwb2ludGVyID0gZ2V0UHJvdG90eXBlT2YocG9pbnRlcik7CiAgICB9CgogICAgcmV0dXJuIG51bGw7CiAgfQogIC8qKgogIEBtb2R1bGUgQGVtYmVyL2NvbXBvbmVudAogICovCgoKICB2YXIgSW5wdXQ7CiAgewogICAgLyoqCiAgICAgIFNlZSBbRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMuSW5wdXRdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMvbWV0aG9kcy9JbnB1dD9hbmNob3I9SW5wdXQpLgogICAgICAgICBAbWV0aG9kIGlucHV0CiAgICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgICAgQHBhcmFtIHtIYXNofSBvcHRpb25zCiAgICAgIEBwdWJsaWMKICAgICAqLwoKICAgIC8qKgogICAgICBUaGUgYElucHV0YCBjb21wb25lbnQgbGV0cyB5b3UgY3JlYXRlIGFuIEhUTUwgYDxpbnB1dD5gIGVsZW1lbnQuCiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPElucHV0IEB2YWx1ZT0iOTg3IiAvPgogICAgICBgYGAKICAgICAgICAgY3JlYXRlcyBhbiBgPGlucHV0PmAgZWxlbWVudCB3aXRoIGB0eXBlPSJ0ZXh0ImAgYW5kIHZhbHVlIHNldCB0byA5ODcuCiAgICAgICAgICMjIyBUZXh0IGZpZWxkCiAgICAgICAgIElmIG5vIGB0eXBlYCBhcmd1bWVudCBpcyBzcGVjaWZpZWQsIGEgZGVmYXVsdCBvZiB0eXBlICd0ZXh0JyBpcyB1c2VkLgogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIFNlYXJjaDoKICAgICAgPElucHV0IEB2YWx1ZT17e3RoaXMuc2VhcmNoV29yZH19PgogICAgICBgYGAKICAgICAgICAgSW4gdGhpcyBleGFtcGxlLCB0aGUgaW5pdGlhbCB2YWx1ZSBpbiB0aGUgYDxpbnB1dD5gIHdpbGwgYmUgc2V0IHRvIHRoZSB2YWx1ZSBvZgogICAgICBgdGhpcy5zZWFyY2hXb3JkYC4gSWYgdGhlIHVzZXIgY2hhbmdlcyB0aGUgdGV4dCwgdGhlIHZhbHVlIG9mIGB0aGlzLnNlYXJjaFdvcmRgIHdpbGwgYWxzbyBiZQogICAgICB1cGRhdGVkLgogICAgICAgICAjIyMgQWN0aW9ucwogICAgICAgICBUaGUgYElucHV0YCBjb21wb25lbnQgdGFrZXMgYSBudW1iZXIgb2YgYXJndW1lbnRzIHdpdGggY2FsbGJhY2tzIHRoYXQgYXJlIGludm9rZWQgaW4gcmVzcG9uc2UgdG8KICAgICAgdXNlciBldmVudHMuCiAgICAgICAgICogYGVudGVyYAogICAgICAqIGBpbnNlcnQtbmV3bGluZWAKICAgICAgKiBgZXNjYXBlLXByZXNzYAogICAgICAqIGBmb2N1cy1pbmAKICAgICAgKiBgZm9jdXMtb3V0YAogICAgICAqIGBrZXktcHJlc3NgCiAgICAgICogYGtleS11cGAKICAgICAgICAgVGhlc2UgY2FsbGJhY2tzIGFyZSBwYXNzZWQgdG8gYElucHV0YCBsaWtlIHRoaXM6CiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPElucHV0IEB2YWx1ZT17e3RoaXMuc2VhcmNoV29yZH19IEBlbnRlcj17e3RoaXMucXVlcnl9fSAvPgogICAgICBgYGAKICAgICAgICAgIyMjIGA8aW5wdXQ+YCBIVE1MIEF0dHJpYnV0ZXMgdG8gQXZvaWQKICAgICAgICAgSW4gbW9zdCBjYXNlcywgaWYgeW91IHdhbnQgdG8gcGFzcyBhbiBhdHRyaWJ1dGUgdG8gdGhlIHVuZGVybHlpbmcgSFRNTCBgPGlucHV0PmAgZWxlbWVudCwgeW91CiAgICAgIGNhbiBwYXNzIHRoZSBhdHRyaWJ1dGUgZGlyZWN0bHksIGp1c3QgbGlrZSBhbnkgb3RoZXIgRW1iZXIgY29tcG9uZW50LgogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIDxJbnB1dCBAdHlwZT0idGV4dCIgc2l6ZT0iMTAiIC8+CiAgICAgIGBgYAogICAgICAgICBJbiB0aGlzIGV4YW1wbGUsIHRoZSBgc2l6ZWAgYXR0cmlidXRlIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgdW5kZXJseWluZyBgPGlucHV0PmAgZWxlbWVudCBpbiB0aGUKICAgICAgb3V0cHV0dGVkIEhUTUwuCiAgICAgICAgIEhvd2V2ZXIsIHRoZXJlIGFyZSBhIGZldyBhdHRyaWJ1dGVzIHdoZXJlIHlvdSAqKm11c3QqKiB1c2UgdGhlIGBAYCB2ZXJzaW9uLgogICAgICAgICAqIGBAdHlwZWA6IFRoaXMgYXJndW1lbnQgaXMgdXNlZCB0byBjb250cm9sIHdoaWNoIEVtYmVyIGNvbXBvbmVudCBpcyB1c2VkIHVuZGVyIHRoZSBob29kCiAgICAgICogYEB2YWx1ZWA6IFRoZSBgQHZhbHVlYCBhcmd1bWVudCBpbnN0YWxscyBhIHR3by13YXkgYmluZGluZyBvbnRvIHRoZSBlbGVtZW50LiBJZiB5b3Ugd2FudGVkIGEKICAgICAgICBvbmUtd2F5IGJpbmRpbmcsIHVzZSBgPGlucHV0PmAgd2l0aCB0aGUgYHZhbHVlYCBwcm9wZXJ0eSBhbmQgdGhlIGBpbnB1dGAgZXZlbnQgaW5zdGVhZC4KICAgICAgKiBgQGNoZWNrZWRgIChmb3IgY2hlY2tib3hlcyk6IGxpa2UgYEB2YWx1ZWAsIHRoZSBgQGNoZWNrZWRgIGFyZ3VtZW50IGluc3RhbGxzIGEgdHdvLXdheSBiaW5kaW5nCiAgICAgICAgb250byB0aGUgZWxlbWVudC4gSWYgeW91IHdhbnRlZCBhIG9uZS13YXkgYmluZGluZywgdXNlIGA8aW5wdXQgdHlwZT0iY2hlY2tib3giPmAgd2l0aAogICAgICAgIGBjaGVja2VkYCBhbmQgdGhlIGBpbnB1dGAgZXZlbnQgaW5zdGVhZC4KICAgICAgICAgIyMjIEV4dGVuZGluZyBgVGV4dEZpZWxkYAogICAgICAgICBJbnRlcm5hbGx5LCBgPElucHV0IEB0eXBlPSJ0ZXh0IiAvPmAgY3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBgVGV4dEZpZWxkYCwgcGFzc2luZyBhcmd1bWVudHMgZnJvbQogICAgICB0aGUgaGVscGVyIHRvIGBUZXh0RmllbGRgJ3MgYGNyZWF0ZWAgbWV0aG9kLiBTdWJjbGFzc2luZyBgVGV4dEZpZWxkYCBpcyBzdXBwb3J0ZWQgYnV0IG5vdAogICAgICByZWNvbW1lbmRlZC4KICAgICAgICAgU2VlIFtUZXh0RmllbGRdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvVGV4dEZpZWxkKQogICAgICAgICAjIyMgQ2hlY2tib3gKICAgICAgICAgVG8gY3JlYXRlIGFuIGA8aW5wdXQgdHlwZT0iY2hlY2tib3giPmA6CiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgRW1iZXJpemUgRXZlcnl0aGluZzoKICAgICAgPElucHV0IEB0eXBlPSJjaGVja2JveCIgQGNoZWNrZWQ9e3t0aGlzLmlzRW1iZXJpemVkfX0gbmFtZT0iaXNFbWJlcml6ZWQiIC8+CiAgICAgIGBgYAogICAgICAgICBUaGlzIHdpbGwgYmluZCB0aGUgY2hlY2tlZCBzdGF0ZSBvZiB0aGlzIGNoZWNrYm94IHRvIHRoZSB2YWx1ZSBvZiBgaXNFbWJlcml6ZWRgIC0tIGlmIGVpdGhlciBvbmUKICAgICAgY2hhbmdlcywgaXQgd2lsbCBiZSByZWZsZWN0ZWQgaW4gdGhlIG90aGVyLgogICAgICAgICAjIyMgRXh0ZW5kaW5nIGBDaGVja2JveGAKICAgICAgICAgSW50ZXJuYWxseSwgYDxJbnB1dCBAdHlwZT0iY2hlY2tib3giIC8+YCBjcmVhdGVzIGFuIGluc3RhbmNlIG9mIGBDaGVja2JveGAuIFN1YmNsYXNzaW5nCiAgICAgIGBUZXh0RmllbGRgIGlzIHN1cHBvcnRlZCBidXQgbm90IHJlY29tbWVuZGVkLgogICAgICAgICBTZWUgW0NoZWNrYm94XSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0NoZWNrYm94KQogICAgICAgICBAbWV0aG9kIElucHV0CiAgICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMKICAgICAgQHNlZSB7VGV4dEZpZWxkfQogICAgICBAc2VlIHtDaGVja2JveH0KICAgICAgQHBhcmFtIHtIYXNofSBvcHRpb25zCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBJbnB1dCA9IF9ydW50aW1lLk9iamVjdC5leHRlbmQoewogICAgICBpc0NoZWNrYm94OiAoMCwgX21ldGFsLmNvbXB1dGVkKSgndHlwZScsIGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gdGhpcy50eXBlID09PSAnY2hlY2tib3gnOwogICAgICB9KQogICAgfSk7CiAgICBzZXRNYW5hZ2VyKHsKICAgICAgZmFjdG9yeTogSW5wdXRDb21wb25lbnRNYW5hZ2VyRmFjdG9yeSwKICAgICAgaW50ZXJuYWw6IHRydWUsCiAgICAgIHR5cGU6ICdjb21wb25lbnQnCiAgICB9LCBJbnB1dCk7CgogICAgSW5wdXQudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAnQGVtYmVyL2NvbXBvbmVudC9pbnB1dCc7CiAgICB9OwogIH0KICB2YXIgSW5wdXQkMSA9IElucHV0OyAvLy88cmVmZXJlbmNlIHBhdGg9Ii4vc2ltcGxlLWRvbS5kLnRzIiAvPgoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBDYWxscyBbU3RyaW5nLmxvY10oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9TdHJpbmcvbWV0aG9kcy9sb2M/YW5jaG9yPWxvYykgd2l0aCB0aGUKICAgIHByb3ZpZGVkIHN0cmluZy4gVGhpcyBpcyBhIGNvbnZlbmllbnQgd2F5IHRvIGxvY2FsaXplIHRleHQgd2l0aGluIGEgdGVtcGxhdGUuCiAgICBGb3IgZXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIEVtYmVyLlNUUklOR1MgPSB7CiAgICAgICdfd2VsY29tZV8nOiAnQm9uam91cicKICAgIH07CiAgICBgYGAKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxkaXYgY2xhc3M9J21lc3NhZ2UnPgogICAgICB7e2xvYyAnX3dlbGNvbWVfJ319CiAgICA8L2Rpdj4KICAgIGBgYAogIAogICAgYGBgaHRtbAogICAgPGRpdiBjbGFzcz0nbWVzc2FnZSc+CiAgICAgIEJvbmpvdXIKICAgIDwvZGl2PgogICAgYGBgCiAgCiAgICBTZWUgW1N0cmluZy5sb2NdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvU3RyaW5nL21ldGhvZHMvbG9jP2FuY2hvcj1sb2MpIGZvciBob3cgdG8KICAgIHNldCB1cCBsb2NhbGl6ZWQgc3RyaW5nIHJlZmVyZW5jZXMuCiAgCiAgICBAbWV0aG9kIGxvYwogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHBhcmFtIHtTdHJpbmd9IHN0ciBUaGUgc3RyaW5nIHRvIGZvcm1hdC4KICAgIEBzZWUge1N0cmluZyNsb2N9CiAgICBAcHVibGljCiAgKi8KCiAgdmFyIGxvYyQxID0gaGVscGVyKGZ1bmN0aW9uIChwYXJhbXMpIHsKICAgIHJldHVybiBfc3RyaW5nLmxvYy5hcHBseShudWxsLCBwYXJhbXMKICAgIC8qIGxldCB0aGUgb3RoZXIgc2lkZSBoYW5kbGUgZXJyb3JzICovCiAgICApOwogIH0pOwoKICB2YXIgQ29tcGlsZVRpbWVMb29rdXAgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDb21waWxlVGltZUxvb2t1cChyZXNvbHZlcikgewogICAgICB0aGlzLnJlc29sdmVyID0gcmVzb2x2ZXI7CiAgICB9CgogICAgdmFyIF9wcm90bzQ4ID0gQ29tcGlsZVRpbWVMb29rdXAucHJvdG90eXBlOwoKICAgIF9wcm90bzQ4LmdldENhcGFiaWxpdGllcyA9IGZ1bmN0aW9uIGdldENhcGFiaWxpdGllcyhoYW5kbGUpIHsKICAgICAgdmFyIGRlZmluaXRpb24gPSB0aGlzLnJlc29sdmVyLnJlc29sdmUoaGFuZGxlKTsKICAgICAgdmFyIG1hbmFnZXIgPSBkZWZpbml0aW9uLm1hbmFnZXIsCiAgICAgICAgICBzdGF0ZSA9IGRlZmluaXRpb24uc3RhdGU7CiAgICAgIHJldHVybiBtYW5hZ2VyLmdldENhcGFiaWxpdGllcyhzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzQ4LmdldExheW91dCA9IGZ1bmN0aW9uIGdldExheW91dChoYW5kbGUpIHsKICAgICAgdmFyIF90aGlzJHJlc29sdmVyJHJlc29sdiA9IHRoaXMucmVzb2x2ZXIucmVzb2x2ZShoYW5kbGUpLAogICAgICAgICAgbWFuYWdlciA9IF90aGlzJHJlc29sdmVyJHJlc29sdi5tYW5hZ2VyLAogICAgICAgICAgc3RhdGUgPSBfdGhpcyRyZXNvbHZlciRyZXNvbHYuc3RhdGU7CgogICAgICB2YXIgY2FwYWJpbGl0aWVzID0gbWFuYWdlci5nZXRDYXBhYmlsaXRpZXMoc3RhdGUpOwoKICAgICAgaWYgKGNhcGFiaWxpdGllcy5keW5hbWljTGF5b3V0KSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KCiAgICAgIHZhciBpbnZvY2F0aW9uID0gbWFuYWdlci5nZXRMYXlvdXQoc3RhdGUsIHRoaXMucmVzb2x2ZXIpOwogICAgICByZXR1cm4gewogICAgICAgIC8vIFRPRE86IHRoaXMgc2VlbXMgd2VpcmQsIGl0IGFscmVhZHkgaXMgY29tcGlsZWQKICAgICAgICBjb21waWxlOiBmdW5jdGlvbiBjb21waWxlKCkgewogICAgICAgICAgcmV0dXJuIGludm9jYXRpb24uaGFuZGxlOwogICAgICAgIH0sCiAgICAgICAgc3ltYm9sVGFibGU6IGludm9jYXRpb24uc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvNDgubG9va3VwSGVscGVyID0gZnVuY3Rpb24gbG9va3VwSGVscGVyKG5hbWUsIHJlZmVycmVyKSB7CiAgICAgIHJldHVybiB0aGlzLnJlc29sdmVyLmxvb2t1cEhlbHBlcihuYW1lLCByZWZlcnJlcik7CiAgICB9OwoKICAgIF9wcm90bzQ4Lmxvb2t1cE1vZGlmaWVyID0gZnVuY3Rpb24gbG9va3VwTW9kaWZpZXIobmFtZSwgcmVmZXJyZXIpIHsKICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZXIubG9va3VwTW9kaWZpZXIobmFtZSwgcmVmZXJyZXIpOwogICAgfTsKCiAgICBfcHJvdG80OC5sb29rdXBDb21wb25lbnREZWZpbml0aW9uID0gZnVuY3Rpb24gbG9va3VwQ29tcG9uZW50RGVmaW5pdGlvbihuYW1lLCByZWZlcnJlcikgewogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlci5sb29rdXBDb21wb25lbnRIYW5kbGUobmFtZSwgcmVmZXJyZXIpOwogICAgfTsKCiAgICBfcHJvdG80OC5sb29rdXBQYXJ0aWFsID0gZnVuY3Rpb24gbG9va3VwUGFydGlhbChuYW1lLCByZWZlcnJlcikgewogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlci5sb29rdXBQYXJ0aWFsKG5hbWUsIHJlZmVycmVyKTsKICAgIH07CgogICAgcmV0dXJuIENvbXBpbGVUaW1lTG9va3VwOwogIH0oKTsKCiAgdmFyIENBUEFCSUxJVElFUyQyID0gewogICAgZHluYW1pY0xheW91dDogZmFsc2UsCiAgICBkeW5hbWljVGFnOiBmYWxzZSwKICAgIHByZXBhcmVBcmdzOiBmYWxzZSwKICAgIGNyZWF0ZUFyZ3M6IHRydWUsCiAgICBhdHRyaWJ1dGVIb29rOiBmYWxzZSwKICAgIGVsZW1lbnRIb29rOiBmYWxzZSwKICAgIGNyZWF0ZUNhbGxlcjogZmFsc2UsCiAgICBkeW5hbWljU2NvcGU6IHRydWUsCiAgICB1cGRhdGVIb29rOiB0cnVlLAogICAgY3JlYXRlSW5zdGFuY2U6IHRydWUKICB9OwoKICBmdW5jdGlvbiBjYXBhYmlsaXRpZXMobWFuYWdlckFQSSwgb3B0aW9ucykgewogICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICBvcHRpb25zID0ge307CiAgICB9CgogICAgKGZhbHNlICYmICEobWFuYWdlckFQSSA9PT0gJzMuNCcgfHwgbWFuYWdlckFQSSA9PT0gJzMuMTMnKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0ludmFsaWQgY29tcG9uZW50IG1hbmFnZXIgY29tcGF0aWJpbGl0eSBzcGVjaWZpZWQnLCBtYW5hZ2VyQVBJID09PSAnMy40JyB8fCBtYW5hZ2VyQVBJID09PSAnMy4xMycpKTsKICAgIHZhciB1cGRhdGVIb29rID0gdHJ1ZTsKICAgIHsKICAgICAgdXBkYXRlSG9vayA9IG1hbmFnZXJBUEkgPT09ICczLjEzJyA/IEJvb2xlYW4ob3B0aW9ucy51cGRhdGVIb29rKSA6IHRydWU7CiAgICB9CiAgICByZXR1cm4gewogICAgICBhc3luY0xpZmVDeWNsZUNhbGxiYWNrczogQm9vbGVhbihvcHRpb25zLmFzeW5jTGlmZWN5Y2xlQ2FsbGJhY2tzKSwKICAgICAgZGVzdHJ1Y3RvcjogQm9vbGVhbihvcHRpb25zLmRlc3RydWN0b3IpLAogICAgICB1cGRhdGVIb29rOiB1cGRhdGVIb29rCiAgICB9OwogIH0KCiAgZnVuY3Rpb24gaGFzQXN5bmNMaWZlQ3ljbGVDYWxsYmFja3MoZGVsZWdhdGUpIHsKICAgIHJldHVybiBkZWxlZ2F0ZS5jYXBhYmlsaXRpZXMuYXN5bmNMaWZlQ3ljbGVDYWxsYmFja3M7CiAgfQoKICBmdW5jdGlvbiBoYXNVcGRhdGVIb29rKGRlbGVnYXRlKSB7CiAgICByZXR1cm4gZGVsZWdhdGUuY2FwYWJpbGl0aWVzLnVwZGF0ZUhvb2s7CiAgfQoKICBmdW5jdGlvbiBoYXNBc3luY1VwZGF0ZUhvb2soZGVsZWdhdGUpIHsKICAgIHJldHVybiBoYXNBc3luY0xpZmVDeWNsZUNhbGxiYWNrcyhkZWxlZ2F0ZSkgJiYgaGFzVXBkYXRlSG9vayhkZWxlZ2F0ZSk7CiAgfQoKICBmdW5jdGlvbiBoYXNEZXN0cnVjdG9ycyhkZWxlZ2F0ZSkgewogICAgcmV0dXJuIGRlbGVnYXRlLmNhcGFiaWxpdGllcy5kZXN0cnVjdG9yOwogIH0KICAvKioKICAgIFRoZSBDdXN0b21Db21wb25lbnRNYW5hZ2VyIGFsbG93cyBhZGRvbnMgdG8gcHJvdmlkZSBjdXN0b20gY29tcG9uZW50CiAgICBpbXBsZW1lbnRhdGlvbnMgdGhhdCBpbnRlZ3JhdGUgc2VhbWxlc3NseSBpbnRvIEVtYmVyLiBUaGlzIGlzIGFjY29tcGxpc2hlZAogICAgdGhyb3VnaCBhIGRlbGVnYXRlLCByZWdpc3RlcmVkIHdpdGggdGhlIGN1c3RvbSBjb21wb25lbnQgbWFuYWdlciwgd2hpY2gKICAgIGltcGxlbWVudHMgYSBzZXQgb2YgaG9va3MgdGhhdCBkZXRlcm1pbmUgY29tcG9uZW50IGJlaGF2aW9yLgogIAogICAgVG8gY3JlYXRlIGEgY3VzdG9tIGNvbXBvbmVudCBtYW5hZ2VyLCBpbnN0YW50aWF0ZSBhIG5ldyBDdXN0b21Db21wb25lbnRNYW5hZ2VyCiAgICBjbGFzcyBhbmQgcGFzcyB0aGUgZGVsZWdhdGUgYXMgdGhlIGZpcnN0IGFyZ3VtZW50OgogIAogICAgYGBganMKICAgIGxldCBtYW5hZ2VyID0gbmV3IEN1c3RvbUNvbXBvbmVudE1hbmFnZXIoewogICAgICAvLyAuLi5kZWxlZ2F0ZSBpbXBsZW1lbnRhdGlvbi4uLgogICAgfSk7CiAgICBgYGAKICAKICAgICMjIERlbGVnYXRlIEhvb2tzCiAgCiAgICBUaHJvdWdob3V0IHRoZSBsaWZlY3ljbGUgb2YgYSBjb21wb25lbnQsIHRoZSBjb21wb25lbnQgbWFuYWdlciB3aWxsIGludm9rZQogICAgZGVsZWdhdGUgaG9va3MgdGhhdCBhcmUgcmVzcG9uc2libGUgZm9yIHN1cmZhY2luZyB0aG9zZSBsaWZlY3ljbGUgY2hhbmdlcyB0bwogICAgdGhlIGVuZCBkZXZlbG9wZXIuCiAgCiAgICAqIGBjcmVhdGUoKWAgLSBpbnZva2VkIHdoZW4gYSBuZXcgaW5zdGFuY2Ugb2YgYSBjb21wb25lbnQgc2hvdWxkIGJlIGNyZWF0ZWQKICAgICogYHVwZGF0ZSgpYCAtIGludm9rZWQgd2hlbiB0aGUgYXJndW1lbnRzIHBhc3NlZCB0byBhIGNvbXBvbmVudCBjaGFuZ2UKICAgICogYGdldENvbnRleHQoKWAgLSByZXR1cm5zIHRoZSBvYmplY3QgdGhhdCBzaG91bGQgYmUKICAqLwoKCiAgdmFyIEN1c3RvbUNvbXBvbmVudE1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Fic3RyYWN0TWFuYWdlcjQpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDdXN0b21Db21wb25lbnRNYW5hZ2VyLCBfQWJzdHJhY3RNYW5hZ2VyNCk7CgogICAgZnVuY3Rpb24gQ3VzdG9tQ29tcG9uZW50TWFuYWdlcigpIHsKICAgICAgcmV0dXJuIF9BYnN0cmFjdE1hbmFnZXI0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDkgPSBDdXN0b21Db21wb25lbnRNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG80OS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoX2VudiwgZGVmaW5pdGlvbiwgYXJncykgewogICAgICB2YXIgZGVsZWdhdGUgPSBkZWZpbml0aW9uLmRlbGVnYXRlOwogICAgICB2YXIgY2FwdHVyZWRBcmdzID0gYXJncy5jYXB0dXJlKCk7CiAgICAgIHZhciB2YWx1ZSQkMTsKICAgICAgdmFyIG5hbWVkQXJnc1Byb3h5ID0ge307CiAgICAgIHsKICAgICAgICBpZiAoX3V0aWxzLkhBU19OQVRJVkVfUFJPWFkpIHsKICAgICAgICAgIHZhciBoYW5kbGVyID0gewogICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldChfdGFyZ2V0LCBwcm9wKSB7CiAgICAgICAgICAgICAgaWYgKGNhcHR1cmVkQXJncy5uYW1lZC5oYXMocHJvcCkpIHsKICAgICAgICAgICAgICAgIHZhciByZWYgPSBjYXB0dXJlZEFyZ3MubmFtZWQuZ2V0KHByb3ApOwogICAgICAgICAgICAgICAgKDAsIF9tZXRhbC5jb25zdW1lKShyZWYudGFnKTsKICAgICAgICAgICAgICAgIHJldHVybiByZWYudmFsdWUoKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGhhczogZnVuY3Rpb24gaGFzKF90YXJnZXQsIHByb3ApIHsKICAgICAgICAgICAgICByZXR1cm4gY2FwdHVyZWRBcmdzLm5hbWVkLmhhcyhwcm9wKTsKICAgICAgICAgICAgfSwKICAgICAgICAgICAgb3duS2V5czogZnVuY3Rpb24gb3duS2V5cyhfdGFyZ2V0KSB7CiAgICAgICAgICAgICAgcmV0dXJuIGNhcHR1cmVkQXJncy5uYW1lZC5uYW1lczsKICAgICAgICAgICAgfSwKICAgICAgICAgICAgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOiBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoX3RhcmdldCwgcHJvcCkgewogICAgICAgICAgICAgIChmYWxzZSAmJiAhKGNhcHR1cmVkQXJncy5uYW1lZC5oYXMocHJvcCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYXJncyBwcm94aWVzIGRvIG5vdCBoYXZlIHJlYWwgcHJvcGVydHkgZGVzY3JpcHRvcnMsIHNvIHlvdSBzaG91bGQgbmV2ZXIgbmVlZCB0byBjYWxsIGdldE93blByb3BlcnR5RGVzY3JpcHRvciB5b3Vyc2VsZi4gVGhpcyBjb2RlIGV4aXN0cyBmb3IgZW51bWVyYWJpbGl0eSwgc3VjaCBhcyBpbiBmb3ItaW4gbG9vcHMgYW5kIE9iamVjdC5rZXlzKCknLCBjYXB0dXJlZEFyZ3MubmFtZWQuaGFzKHByb3ApKSk7CiAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUKICAgICAgICAgICAgICB9OwogICAgICAgICAgICB9CiAgICAgICAgICB9OwoKICAgICAgICAgIGlmIChmYWxzZQogICAgICAgICAgLyogREVCVUcgKi8KICAgICAgICAgICkgewogICAgICAgICAgICBoYW5kbGVyLnNldCA9IGZ1bmN0aW9uIChfdGFyZ2V0LCBwcm9wKSB7CiAgICAgICAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byBzZXQgIiArIGRlZmluaXRpb24uQ29tcG9uZW50Q2xhc3MuY2xhc3MgKyAiIyIgKyBTdHJpbmcocHJvcCkgKyAiIG9uIGEgY29tcG9uZW50cyBhcmd1bWVudHMuIENvbXBvbmVudCBhcmd1bWVudHMgYXJlIGltbXV0YWJsZSBhbmQgY2Fubm90IGJlIHVwZGF0ZWQgZGlyZWN0bHksIHRoZXkgYWx3YXlzIHJlcHJlc2VudCB0aGUgdmFsdWVzIHRoYXQgYXJlIHBhc3NlZCB0byB5b3VyIGNvbXBvbmVudC4gSWYgeW91IHdhbnQgdG8gc2V0IGRlZmF1bHQgdmFsdWVzLCB5b3Ugc2hvdWxkIHVzZSBhIGdldHRlciBpbnN0ZWFkIikpOwogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfTsKICAgICAgICAgIH0KCiAgICAgICAgICBuYW1lZEFyZ3NQcm94eSA9IG5ldyBQcm94eShuYW1lZEFyZ3NQcm94eSwgaGFuZGxlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNhcHR1cmVkQXJncy5uYW1lZC5uYW1lcy5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7CiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShuYW1lZEFyZ3NQcm94eSwgbmFtZSwgewogICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgICAgICAgICAgdmFyIHJlZiA9IGNhcHR1cmVkQXJncy5uYW1lZC5nZXQobmFtZSk7CiAgICAgICAgICAgICAgICAoMCwgX21ldGFsLmNvbnN1bWUpKHJlZi50YWcpOwogICAgICAgICAgICAgICAgcmV0dXJuIHJlZi52YWx1ZSgpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIF9tZXRhbC5BUkdTX1BST1hZX1RBR1Muc2V0KG5hbWVkQXJnc1Byb3h5LCBjYXB0dXJlZEFyZ3MubmFtZWQpOwoKICAgICAgICB2YWx1ZSQkMSA9IHsKICAgICAgICAgIG5hbWVkOiBuYW1lZEFyZ3NQcm94eSwKICAgICAgICAgIHBvc2l0aW9uYWw6IGNhcHR1cmVkQXJncy5wb3NpdGlvbmFsLnZhbHVlKCkKICAgICAgICB9OwogICAgICB9CiAgICAgIHZhciBjb21wb25lbnQgPSBkZWxlZ2F0ZS5jcmVhdGVDb21wb25lbnQoZGVmaW5pdGlvbi5Db21wb25lbnRDbGFzcy5jbGFzcywgdmFsdWUkJDEpOwogICAgICByZXR1cm4gbmV3IEN1c3RvbUNvbXBvbmVudFN0YXRlKGRlbGVnYXRlLCBjb21wb25lbnQsIGNhcHR1cmVkQXJncywgbmFtZWRBcmdzUHJveHkpOwogICAgfTsKCiAgICBfcHJvdG80OS51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoX3JlZjE3KSB7CiAgICAgIHZhciBkZWxlZ2F0ZSA9IF9yZWYxNy5kZWxlZ2F0ZSwKICAgICAgICAgIGNvbXBvbmVudCA9IF9yZWYxNy5jb21wb25lbnQsCiAgICAgICAgICBhcmdzID0gX3JlZjE3LmFyZ3MsCiAgICAgICAgICBuYW1lZEFyZ3NQcm94eSA9IF9yZWYxNy5uYW1lZEFyZ3NQcm94eTsKICAgICAgdmFyIHZhbHVlJCQxOwogICAgICB7CiAgICAgICAgdmFsdWUkJDEgPSB7CiAgICAgICAgICBuYW1lZDogbmFtZWRBcmdzUHJveHksCiAgICAgICAgICBwb3NpdGlvbmFsOiBhcmdzLnBvc2l0aW9uYWwudmFsdWUoKQogICAgICAgIH07CiAgICAgIH0KCiAgICAgIGlmIChoYXNVcGRhdGVIb29rKGRlbGVnYXRlKSkgewogICAgICAgIGRlbGVnYXRlLnVwZGF0ZUNvbXBvbmVudChjb21wb25lbnQsIHZhbHVlJCQxKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG80OS5kaWRDcmVhdGUgPSBmdW5jdGlvbiBkaWRDcmVhdGUoX3JlZjE4KSB7CiAgICAgIHZhciBkZWxlZ2F0ZSA9IF9yZWYxOC5kZWxlZ2F0ZSwKICAgICAgICAgIGNvbXBvbmVudCA9IF9yZWYxOC5jb21wb25lbnQ7CgogICAgICBpZiAoaGFzQXN5bmNMaWZlQ3ljbGVDYWxsYmFja3MoZGVsZWdhdGUpKSB7CiAgICAgICAgZGVsZWdhdGUuZGlkQ3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNDkuZGlkVXBkYXRlID0gZnVuY3Rpb24gZGlkVXBkYXRlKF9yZWYxOSkgewogICAgICB2YXIgZGVsZWdhdGUgPSBfcmVmMTkuZGVsZWdhdGUsCiAgICAgICAgICBjb21wb25lbnQgPSBfcmVmMTkuY29tcG9uZW50OwoKICAgICAgaWYgKGhhc0FzeW5jVXBkYXRlSG9vayhkZWxlZ2F0ZSkpIHsKICAgICAgICBkZWxlZ2F0ZS5kaWRVcGRhdGVDb21wb25lbnQoY29tcG9uZW50KTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG80OS5nZXRDb250ZXh0ID0gZnVuY3Rpb24gZ2V0Q29udGV4dChfcmVmMjApIHsKICAgICAgdmFyIGRlbGVnYXRlID0gX3JlZjIwLmRlbGVnYXRlLAogICAgICAgICAgY29tcG9uZW50ID0gX3JlZjIwLmNvbXBvbmVudDsKICAgICAgZGVsZWdhdGUuZ2V0Q29udGV4dChjb21wb25lbnQpOwogICAgfTsKCiAgICBfcHJvdG80OS5nZXRTZWxmID0gZnVuY3Rpb24gZ2V0U2VsZihfcmVmMjEpIHsKICAgICAgdmFyIGRlbGVnYXRlID0gX3JlZjIxLmRlbGVnYXRlLAogICAgICAgICAgY29tcG9uZW50ID0gX3JlZjIxLmNvbXBvbmVudDsKICAgICAgcmV0dXJuIFJvb3RSZWZlcmVuY2UuY3JlYXRlKGRlbGVnYXRlLmdldENvbnRleHQoY29tcG9uZW50KSk7CiAgICB9OwoKICAgIF9wcm90bzQ5LmdldERlc3RydWN0b3IgPSBmdW5jdGlvbiBnZXREZXN0cnVjdG9yKHN0YXRlKSB7CiAgICAgIGlmIChoYXNEZXN0cnVjdG9ycyhzdGF0ZS5kZWxlZ2F0ZSkpIHsKICAgICAgICByZXR1cm4gc3RhdGU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNDkuZ2V0Q2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gZ2V0Q2FwYWJpbGl0aWVzKF9yZWYyMikgewogICAgICB2YXIgZGVsZWdhdGUgPSBfcmVmMjIuZGVsZWdhdGU7CiAgICAgIHJldHVybiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBDQVBBQklMSVRJRVMkMiwgewogICAgICAgIHVwZGF0ZUhvb2s6IGRlbGVnYXRlLmNhcGFiaWxpdGllcy51cGRhdGVIb29rCiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG80OS5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoX3JlZjIzKSB7CiAgICAgIHZhciBhcmdzID0gX3JlZjIzLmFyZ3M7CiAgICAgIHJldHVybiBhcmdzLnRhZzsKICAgIH07CgogICAgX3Byb3RvNDkuZGlkUmVuZGVyTGF5b3V0ID0gZnVuY3Rpb24gZGlkUmVuZGVyTGF5b3V0KCkge307CgogICAgX3Byb3RvNDkuZ2V0TGF5b3V0ID0gZnVuY3Rpb24gZ2V0TGF5b3V0KHN0YXRlKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiBzdGF0ZS50ZW1wbGF0ZS5hc0xheW91dCgpLmNvbXBpbGUoKSwKICAgICAgICBzeW1ib2xUYWJsZTogc3RhdGUuc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgcmV0dXJuIEN1c3RvbUNvbXBvbmVudE1hbmFnZXI7CiAgfShBYnN0cmFjdE1hbmFnZXIpOwoKICB2YXIgQ1VTVE9NX0NPTVBPTkVOVF9NQU5BR0VSID0gbmV3IEN1c3RvbUNvbXBvbmVudE1hbmFnZXIoKTsKICAvKioKICAgKiBTdG9yZXMgaW50ZXJuYWwgc3RhdGUgYWJvdXQgYSBjb21wb25lbnQgaW5zdGFuY2UgYWZ0ZXIgaXQncyBiZWVuIGNyZWF0ZWQuCiAgICovCgogIHZhciBDdXN0b21Db21wb25lbnRTdGF0ZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEN1c3RvbUNvbXBvbmVudFN0YXRlKGRlbGVnYXRlLCBjb21wb25lbnQsIGFyZ3MsIG5hbWVkQXJnc1Byb3h5KSB7CiAgICAgIHRoaXMuZGVsZWdhdGUgPSBkZWxlZ2F0ZTsKICAgICAgdGhpcy5jb21wb25lbnQgPSBjb21wb25lbnQ7CiAgICAgIHRoaXMuYXJncyA9IGFyZ3M7CiAgICAgIHRoaXMubmFtZWRBcmdzUHJveHkgPSBuYW1lZEFyZ3NQcm94eTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTAgPSBDdXN0b21Db21wb25lbnRTdGF0ZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNTAuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHZhciBkZWxlZ2F0ZSA9IHRoaXMuZGVsZWdhdGUsCiAgICAgICAgICBjb21wb25lbnQgPSB0aGlzLmNvbXBvbmVudDsKCiAgICAgIGlmIChoYXNEZXN0cnVjdG9ycyhkZWxlZ2F0ZSkpIHsKICAgICAgICBkZWxlZ2F0ZS5kZXN0cm95Q29tcG9uZW50KGNvbXBvbmVudCk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEN1c3RvbUNvbXBvbmVudFN0YXRlOwogIH0oKTsKCiAgdmFyIEN1c3RvbU1hbmFnZXJEZWZpbml0aW9uID0gZnVuY3Rpb24gQ3VzdG9tTWFuYWdlckRlZmluaXRpb24obmFtZSwgQ29tcG9uZW50Q2xhc3MsIGRlbGVnYXRlLCB0ZW1wbGF0ZSkgewogICAgdGhpcy5uYW1lID0gbmFtZTsKICAgIHRoaXMuQ29tcG9uZW50Q2xhc3MgPSBDb21wb25lbnRDbGFzczsKICAgIHRoaXMuZGVsZWdhdGUgPSBkZWxlZ2F0ZTsKICAgIHRoaXMudGVtcGxhdGUgPSB0ZW1wbGF0ZTsKICAgIHRoaXMubWFuYWdlciA9IENVU1RPTV9DT01QT05FTlRfTUFOQUdFUjsKICAgIHZhciBsYXlvdXQgPSB0ZW1wbGF0ZS5hc0xheW91dCgpOwogICAgdmFyIHN5bWJvbFRhYmxlID0gbGF5b3V0LnN5bWJvbFRhYmxlOwogICAgdGhpcy5zeW1ib2xUYWJsZSA9IHN5bWJvbFRhYmxlOwogICAgdGhpcy5zdGF0ZSA9IHsKICAgICAgbmFtZTogbmFtZSwKICAgICAgQ29tcG9uZW50Q2xhc3M6IENvbXBvbmVudENsYXNzLAogICAgICB0ZW1wbGF0ZTogdGVtcGxhdGUsCiAgICAgIHN5bWJvbFRhYmxlOiBzeW1ib2xUYWJsZSwKICAgICAgZGVsZWdhdGU6IGRlbGVnYXRlCiAgICB9OwogIH07CgogIHZhciBDQVBBQklMSVRJRVMkMyA9IHsKICAgIGR5bmFtaWNMYXlvdXQ6IGZhbHNlLAogICAgZHluYW1pY1RhZzogZmFsc2UsCiAgICBwcmVwYXJlQXJnczogZmFsc2UsCiAgICBjcmVhdGVBcmdzOiBmYWxzZSwKICAgIGF0dHJpYnV0ZUhvb2s6IGZhbHNlLAogICAgZWxlbWVudEhvb2s6IGZhbHNlLAogICAgY3JlYXRlQ2FsbGVyOiBmYWxzZSwKICAgIGR5bmFtaWNTY29wZTogZmFsc2UsCiAgICB1cGRhdGVIb29rOiBmYWxzZSwKICAgIGNyZWF0ZUluc3RhbmNlOiB0cnVlCiAgfTsKCiAgdmFyIFRlbXBsYXRlT25seUNvbXBvbmVudE1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Fic3RyYWN0TWFuYWdlcjUpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShUZW1wbGF0ZU9ubHlDb21wb25lbnRNYW5hZ2VyLCBfQWJzdHJhY3RNYW5hZ2VyNSk7CgogICAgZnVuY3Rpb24gVGVtcGxhdGVPbmx5Q29tcG9uZW50TWFuYWdlcigpIHsKICAgICAgcmV0dXJuIF9BYnN0cmFjdE1hbmFnZXI1LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTEgPSBUZW1wbGF0ZU9ubHlDb21wb25lbnRNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG81MS5nZXRMYXlvdXQgPSBmdW5jdGlvbiBnZXRMYXlvdXQodGVtcGxhdGUpIHsKICAgICAgdmFyIGxheW91dCA9IHRlbXBsYXRlLmFzTGF5b3V0KCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiBsYXlvdXQuY29tcGlsZSgpLAogICAgICAgIHN5bWJvbFRhYmxlOiBsYXlvdXQuc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvNTEuZ2V0Q2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gZ2V0Q2FwYWJpbGl0aWVzKCkgewogICAgICByZXR1cm4gQ0FQQUJJTElUSUVTJDM7CiAgICB9OwoKICAgIF9wcm90bzUxLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9OwoKICAgIF9wcm90bzUxLmdldFNlbGYgPSBmdW5jdGlvbiBnZXRTZWxmKCkgewogICAgICByZXR1cm4gX3J1bnRpbWUyLk5VTExfUkVGRVJFTkNFOwogICAgfTsKCiAgICBfcHJvdG81MS5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoKSB7CiAgICAgIHJldHVybiBfcmVmZXJlbmNlLkNPTlNUQU5UX1RBRzsKICAgIH07CgogICAgX3Byb3RvNTEuZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3IoKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfTsKCiAgICByZXR1cm4gVGVtcGxhdGVPbmx5Q29tcG9uZW50TWFuYWdlcjsKICB9KEFic3RyYWN0TWFuYWdlcik7CgogIHZhciBNQU5BR0VSID0gbmV3IFRlbXBsYXRlT25seUNvbXBvbmVudE1hbmFnZXIoKTsKCiAgdmFyIFRlbXBsYXRlT25seUNvbXBvbmVudERlZmluaXRpb24gPSBmdW5jdGlvbiBUZW1wbGF0ZU9ubHlDb21wb25lbnREZWZpbml0aW9uKHN0YXRlKSB7CiAgICB0aGlzLnN0YXRlID0gc3RhdGU7CiAgICB0aGlzLm1hbmFnZXIgPSBNQU5BR0VSOwogIH07CgogIHZhciBoZWxwZXIkMTsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIHZhciBDb21wb25lbnRBc3NlcnRpb25SZWZlcmVuY2UgPQogICAgLyojX19QVVJFX18qLwogICAgZnVuY3Rpb24gKCkgewogICAgICBmdW5jdGlvbiBDb21wb25lbnRBc3NlcnRpb25SZWZlcmVuY2UoY29tcG9uZW50LCBtZXNzYWdlKSB7CiAgICAgICAgdGhpcy5jb21wb25lbnQgPSBjb21wb25lbnQ7CiAgICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTsKICAgICAgICB0aGlzLnRhZyA9IGNvbXBvbmVudC50YWc7CiAgICAgIH0KCiAgICAgIHZhciBfcHJvdG81MiA9IENvbXBvbmVudEFzc2VydGlvblJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgICBfcHJvdG81Mi52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgIHZhciB2YWx1ZSQkMSA9IHRoaXMuY29tcG9uZW50LnZhbHVlKCk7CiAgICAgICAgKGZhbHNlICYmICEodHlwZW9mIHZhbHVlJCQxICE9PSAnc3RyaW5nJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMubWVzc2FnZSwgdHlwZW9mIHZhbHVlJCQxICE9PSAnc3RyaW5nJykpOwogICAgICAgIHJldHVybiB2YWx1ZSQkMTsKICAgICAgfTsKCiAgICAgIF9wcm90bzUyLmdldCA9IGZ1bmN0aW9uIGdldChwcm9wZXJ0eSkgewogICAgICAgIHJldHVybiB0aGlzLmNvbXBvbmVudC5nZXQocHJvcGVydHkpOwogICAgICB9OwoKICAgICAgcmV0dXJuIENvbXBvbmVudEFzc2VydGlvblJlZmVyZW5jZTsKICAgIH0oKTsKCiAgICBoZWxwZXIkMSA9IGZ1bmN0aW9uIGhlbHBlciQxKF92bSwgYXJncykgewogICAgICByZXR1cm4gbmV3IENvbXBvbmVudEFzc2VydGlvblJlZmVyZW5jZShhcmdzLnBvc2l0aW9uYWwuYXQoMCksIGFyZ3MucG9zaXRpb25hbC5hdCgxKS52YWx1ZSgpKTsKICAgIH07CiAgfSBlbHNlIHsKICAgIGhlbHBlciQxID0gZnVuY3Rpb24gaGVscGVyJDEoX3ZtLCBhcmdzKSB7CiAgICAgIHJldHVybiBhcmdzLnBvc2l0aW9uYWwuYXQoMCk7CiAgICB9OwogIH0KCiAgdmFyIGNvbXBvbmVudEFzc2VydGlvbkhlbHBlciA9IGhlbHBlciQxOwoKICBmdW5jdGlvbiBjbGFzc0hlbHBlcihfcmVmMjQpIHsKICAgIHZhciBwb3NpdGlvbmFsID0gX3JlZjI0LnBvc2l0aW9uYWw7CiAgICB2YXIgcGF0aCA9IHBvc2l0aW9uYWwuYXQoMCk7CiAgICB2YXIgYXJncyA9IHBvc2l0aW9uYWwubGVuZ3RoOwogICAgdmFyIHZhbHVlJCQxID0gcGF0aC52YWx1ZSgpOwoKICAgIGlmICh2YWx1ZSQkMSA9PT0gdHJ1ZSkgewogICAgICBpZiAoYXJncyA+IDEpIHsKICAgICAgICByZXR1cm4gKDAsIF9zdHJpbmcuZGFzaGVyaXplKShwb3NpdGlvbmFsLmF0KDEpLnZhbHVlKCkpOwogICAgICB9CgogICAgICByZXR1cm4gbnVsbDsKICAgIH0KCiAgICBpZiAodmFsdWUkJDEgPT09IGZhbHNlKSB7CiAgICAgIGlmIChhcmdzID4gMikgewogICAgICAgIHJldHVybiAoMCwgX3N0cmluZy5kYXNoZXJpemUpKHBvc2l0aW9uYWwuYXQoMikudmFsdWUoKSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBudWxsOwogICAgfQoKICAgIHJldHVybiB2YWx1ZSQkMTsKICB9CgogIGZ1bmN0aW9uIGNsYXNzSGVscGVyJDEoX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gbmV3IEludGVybmFsSGVscGVyUmVmZXJlbmNlKGNsYXNzSGVscGVyLCBhcmdzLmNhcHR1cmUoKSk7CiAgfQoKICBmdW5jdGlvbiBpbnB1dFR5cGVIZWxwZXIoX3JlZjI1KSB7CiAgICB2YXIgcG9zaXRpb25hbCA9IF9yZWYyNS5wb3NpdGlvbmFsOwogICAgdmFyIHR5cGUgPSBwb3NpdGlvbmFsLmF0KDApLnZhbHVlKCk7CgogICAgaWYgKHR5cGUgPT09ICdjaGVja2JveCcpIHsKICAgICAgcmV0dXJuICctY2hlY2tib3gnOwogICAgfQoKICAgIHJldHVybiAnLXRleHQtZmllbGQnOwogIH0KCiAgZnVuY3Rpb24gaW5wdXRUeXBlSGVscGVyJDEoX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gbmV3IEludGVybmFsSGVscGVyUmVmZXJlbmNlKGlucHV0VHlwZUhlbHBlciwgYXJncy5jYXB0dXJlKCkpOwogIH0KCiAgZnVuY3Rpb24gbm9ybWFsaXplQ2xhc3MoX3JlZjI2KSB7CiAgICB2YXIgcG9zaXRpb25hbCA9IF9yZWYyNi5wb3NpdGlvbmFsOwogICAgdmFyIGNsYXNzTmFtZVBhcnRzID0gcG9zaXRpb25hbC5hdCgwKS52YWx1ZSgpLnNwbGl0KCcuJyk7CiAgICB2YXIgY2xhc3NOYW1lID0gY2xhc3NOYW1lUGFydHNbY2xhc3NOYW1lUGFydHMubGVuZ3RoIC0gMV07CiAgICB2YXIgdmFsdWUkJDEgPSBwb3NpdGlvbmFsLmF0KDEpLnZhbHVlKCk7CgogICAgaWYgKHZhbHVlJCQxID09PSB0cnVlKSB7CiAgICAgIHJldHVybiAoMCwgX3N0cmluZy5kYXNoZXJpemUpKGNsYXNzTmFtZSk7CiAgICB9IGVsc2UgaWYgKCF2YWx1ZSQkMSAmJiB2YWx1ZSQkMSAhPT0gMCkgewogICAgICByZXR1cm4gJyc7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gU3RyaW5nKHZhbHVlJCQxKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIG5vcm1hbGl6ZUNsYXNzSGVscGVyKF92bSwgYXJncykgewogICAgcmV0dXJuIG5ldyBJbnRlcm5hbEhlbHBlclJlZmVyZW5jZShub3JtYWxpemVDbGFzcywgYXJncy5jYXB0dXJlKCkpOwogIH0KICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBUaGUgYHt7YWN0aW9ufX1gIGhlbHBlciBwcm92aWRlcyBhIHdheSB0byBwYXNzIHRyaWdnZXJzIGZvciBiZWhhdmlvciAodXN1YWxseQogICAganVzdCBhIGZ1bmN0aW9uKSBiZXR3ZWVuIGNvbXBvbmVudHMsIGFuZCBpbnRvIGNvbXBvbmVudHMgZnJvbSBjb250cm9sbGVycy4KICAKICAgICMjIyBQYXNzaW5nIGZ1bmN0aW9ucyB3aXRoIHRoZSBhY3Rpb24gaGVscGVyCiAgCiAgICBUaGVyZSBhcmUgdGhyZWUgY29udGV4dHMgYW4gYWN0aW9uIGhlbHBlciBjYW4gYmUgdXNlZCBpbi4gVGhlIGZpcnN0IHR3bwogICAgY29udGV4dHMgdG8gZGlzY3VzcyBhcmUgYXR0cmlidXRlIGNvbnRleHQsIGFuZCBIYW5kbGViYXJzIHZhbHVlIGNvbnRleHQuCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7eyEgQW4gZXhhbXBsZSBvZiBhdHRyaWJ1dGUgY29udGV4dCB9fQogICAgPGRpdiBvbmNsaWNrPXt7YWN0aW9uICJzYXZlIn19PjwvZGl2PgogICAge3shIEV4YW1wbGVzIG9mIEhhbmRsZWJhcnMgdmFsdWUgY29udGV4dCB9fQogICAge3tpbnB1dCBvbi1pbnB1dD0oYWN0aW9uICJzYXZlIil9fQogICAge3t5aWVsZCAoYWN0aW9uICJyZWZyZXNoRGF0YSIpIGFuZEFub3RoZXJQYXJhbX19CiAgICBgYGAKICAKICAgIEluIHRoZXNlIGNvbnRleHRzLAogICAgdGhlIGhlbHBlciBpcyBjYWxsZWQgYSAiY2xvc3VyZSBhY3Rpb24iIGhlbHBlci4gSXRzIGJlaGF2aW9yIGlzIHNpbXBsZToKICAgIElmIHBhc3NlZCBhIGZ1bmN0aW9uIG5hbWUsIHJlYWQgdGhhdCBmdW5jdGlvbiBvZmYgdGhlIGBhY3Rpb25zYCBwcm9wZXJ0eQogICAgb2YgdGhlIGN1cnJlbnQgY29udGV4dC4gT25jZSB0aGF0IGZ1bmN0aW9uIGlzIHJlYWQsIG9yIGltbWVkaWF0ZWx5IGlmIGEgZnVuY3Rpb24gd2FzCiAgICBwYXNzZWQsIGNyZWF0ZSBhIGNsb3N1cmUgb3ZlciB0aGF0IGZ1bmN0aW9uIGFuZCBhbnkgYXJndW1lbnRzLgogICAgVGhlIHJlc3VsdGluZyB2YWx1ZSBvZiBhbiBhY3Rpb24gaGVscGVyIHVzZWQgdGhpcyB3YXkgaXMgc2ltcGx5IGEgZnVuY3Rpb24uCiAgCiAgICBGb3IgZXhhbXBsZSwgaW4gdGhlIGF0dHJpYnV0ZSBjb250ZXh0OgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3shIEFuIGV4YW1wbGUgb2YgYXR0cmlidXRlIGNvbnRleHQgfX0KICAgIDxkaXYgb25jbGljaz17e2FjdGlvbiAic2F2ZSJ9fT48L2Rpdj4KICAgIGBgYAogIAogICAgVGhlIHJlc3VsdGluZyB0ZW1wbGF0ZSByZW5kZXIgbG9naWMgd291bGQgYmU6CiAgCiAgICBgYGBqcwogICAgdmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgdmFyIGFjdGlvbkZ1bmN0aW9uID0gKGZ1bmN0aW9uKGNvbnRleHQpewogICAgICByZXR1cm4gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIGNvbnRleHQuYWN0aW9ucy5zYXZlLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7CiAgICAgIH07CiAgICB9KShjb250ZXh0KTsKICAgIGRpdi5vbmNsaWNrID0gYWN0aW9uRnVuY3Rpb247CiAgICBgYGAKICAKICAgIFRodXMgd2hlbiB0aGUgZGl2IGlzIGNsaWNrZWQsIHRoZSBhY3Rpb24gb24gdGhhdCBjb250ZXh0IGlzIGNhbGxlZC4KICAgIEJlY2F1c2UgdGhlIGBhY3Rpb25GdW5jdGlvbmAgaXMganVzdCBhIGZ1bmN0aW9uLCBjbG9zdXJlIGFjdGlvbnMgY2FuIGJlCiAgICBwYXNzZWQgYmV0d2VlbiBjb21wb25lbnRzIGFuZCBzdGlsbCBleGVjdXRlIGluIHRoZSBjb3JyZWN0IGNvbnRleHQuCiAgCiAgICBIZXJlIGlzIGFuIGV4YW1wbGUgYWN0aW9uIGhhbmRsZXIgb24gYSBjb21wb25lbnQ6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgYWN0aW9uczogewogICAgICAgIHNhdmUoKSB7CiAgICAgICAgICB0aGlzLmdldCgnbW9kZWwnKS5zYXZlKCk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQWN0aW9ucyBhcmUgYWx3YXlzIGxvb2tlZCB1cCBvbiB0aGUgYGFjdGlvbnNgIHByb3BlcnR5IG9mIHRoZSBjdXJyZW50IGNvbnRleHQuCiAgICBUaGlzIGF2b2lkcyBjb2xsaXNpb25zIGluIHRoZSBuYW1pbmcgb2YgY29tbW9uIGFjdGlvbnMsIHN1Y2ggYXMgYGRlc3Ryb3lgLgogICAgVHdvIG9wdGlvbnMgY2FuIGJlIHBhc3NlZCB0byB0aGUgYGFjdGlvbmAgaGVscGVyIHdoZW4gaXQgaXMgdXNlZCBpbiB0aGlzIHdheS4KICAKICAgICogYHRhcmdldD1zb21lUHJvcGVydHlgIHdpbGwgbG9vayB0byBgc29tZVByb3BlcnR5YCBpbnN0ZWFkIG9mIHRoZSBjdXJyZW50CiAgICAgIGNvbnRleHQgZm9yIHRoZSBgYWN0aW9uc2AgaGFzaC4gVGhpcyBjYW4gYmUgdXNlZnVsIHdoZW4gdGFyZ2V0aW5nIGEKICAgICAgc2VydmljZSBmb3IgYWN0aW9ucy4KICAgICogYHZhbHVlPSJ0YXJnZXQudmFsdWUiYCB3aWxsIHJlYWQgdGhlIHBhdGggYHRhcmdldC52YWx1ZWAgb2ZmIHRoZSBmaXJzdAogICAgICBhcmd1bWVudCB0byB0aGUgYWN0aW9uIHdoZW4gaXQgaXMgY2FsbGVkIGFuZCByZXdyaXRlIHRoZSBmaXJzdCBhcmd1bWVudAogICAgICB0byBiZSB0aGF0IHZhbHVlLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIGF0dGFjaGluZyBhY3Rpb25zIHRvIGV2ZW50IGxpc3RlbmVycy4KICAKICAgICMjIyBJbnZva2luZyBhbiBhY3Rpb24KICAKICAgIENsb3N1cmUgYWN0aW9ucyBjdXJyeSBib3RoIHRoZWlyIHNjb3BlIGFuZCBhbnkgYXJndW1lbnRzLiBXaGVuIGludm9rZWQsIGFueQogICAgYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlIGFkZGVkIHRvIHRoZSBhbHJlYWR5IGN1cnJpZWQgbGlzdC4KICAgIEFjdGlvbnMgc2hvdWxkIGJlIGludm9rZWQgdXNpbmcgdGhlIFtzZW5kQWN0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0NvbXBvbmVudC9tZXRob2RzL3NlbmRBY3Rpb24/YW5jaG9yPXNlbmRBY3Rpb24pCiAgICBtZXRob2QuIFRoZSBmaXJzdCBhcmd1bWVudCB0byBgc2VuZEFjdGlvbmAgaXMgdGhlIGFjdGlvbiB0byBiZSBjYWxsZWQsIGFuZAogICAgYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlIHBhc3NlZCB0byB0aGUgYWN0aW9uIGZ1bmN0aW9uLiBUaGlzIGhhcyBpbnRlcmVzdGluZwogICAgcHJvcGVydGllcyBjb21iaW5lZCB3aXRoIGN1cnJ5aW5nIG9mIGFyZ3VtZW50cy4gRm9yIGV4YW1wbGU6CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvbXktY29tcG9uZW50LmhicwogICAge3tpbnB1dCBvbi1pbnB1dD0oYWN0aW9uIChhY3Rpb24gJ3NldE5hbWUnIG1vZGVsKSB2YWx1ZT0idGFyZ2V0LnZhbHVlIil9fQogICAgYGBgCiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgYWN0aW9uczogewogICAgICAgIHNldE5hbWUobW9kZWwsIG5hbWUpIHsKICAgICAgICAgIG1vZGVsLnNldCgnbmFtZScsIG5hbWUpOwogICAgICAgIH0KICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIFRoZSBmaXJzdCBhcmd1bWVudCAoYG1vZGVsYCkgd2FzIGN1cnJpZWQgb3ZlciwgYW5kIHRoZSBydW4tdGltZSBhcmd1bWVudCAoYGV2ZW50YCkKICAgIGJlY29tZXMgYSBzZWNvbmQgYXJndW1lbnQuIEFjdGlvbiBjYWxscyBjYW4gYmUgbmVzdGVkIHRoaXMgd2F5IGJlY2F1c2UgZWFjaCBzaW1wbHkKICAgIHJldHVybnMgYSBmdW5jdGlvbi4gQW55IGZ1bmN0aW9uIGNhbiBiZSBwYXNzZWQgdG8gdGhlIGB7e2FjdGlvbn19YCBoZWxwZXIsIGluY2x1ZGluZwogICAgb3RoZXIgYWN0aW9ucy4KICAKICAgIEFjdGlvbnMgaW52b2tlZCB3aXRoIGBzZW5kQWN0aW9uYCBoYXZlIHRoZSBzYW1lIGN1cnJ5aW5nIGJlaGF2aW9yIGFzIGRlbW9uc3RyYXRlZAogICAgd2l0aCBgb24taW5wdXRgIGFib3ZlLiBGb3IgZXhhbXBsZToKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LWlucHV0LmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGFjdGlvbnM6IHsKICAgICAgICBzZXROYW1lKG1vZGVsLCBuYW1lKSB7CiAgICAgICAgICBtb2RlbC5zZXQoJ25hbWUnLCBuYW1lKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8TXlJbnB1dCBAc3VibWl0PXt7YWN0aW9uICdzZXROYW1lJyB0aGlzLm1vZGVsfX0gLz4KICAgIGBgYAogICAgb3IKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7bXktaW5wdXQgc3VibWl0PShhY3Rpb24gJ3NldE5hbWUnIG1vZGVsKX19CiAgICBgYGAKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LWNvbXBvbmVudC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGljaygpIHsKICAgICAgICAvLyBOb3RlIHRoYXQgbW9kZWwgaXMgbm90IHBhc3NlZCwgaXQgd2FzIGN1cnJpZWQgaW4gdGhlIHRlbXBsYXRlCiAgICAgICAgdGhpcy5zZW5kQWN0aW9uKCdzdWJtaXQnLCAnYm9iJyk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICAjIyMgQXR0YWNoaW5nIGFjdGlvbnMgdG8gRE9NIGVsZW1lbnRzCiAgCiAgICBUaGUgdGhpcmQgY29udGV4dCBvZiB0aGUgYHt7YWN0aW9ufX1gIGhlbHBlciBjYW4gYmUgY2FsbGVkICJlbGVtZW50IHNwYWNlIi4KICAgIEZvciBleGFtcGxlOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3shIEFuIGV4YW1wbGUgb2YgZWxlbWVudCBzcGFjZSB9fQogICAgPGRpdiB7e2FjdGlvbiAic2F2ZSJ9fT48L2Rpdj4KICAgIGBgYAogIAogICAgVXNlZCB0aGlzIHdheSwgdGhlIGB7e2FjdGlvbn19YCBoZWxwZXIgcHJvdmlkZXMgYSB1c2VmdWwgc2hvcnRjdXQgZm9yCiAgICByZWdpc3RlcmluZyBhbiBIVE1MIGVsZW1lbnQgaW4gYSB0ZW1wbGF0ZSBmb3IgYSBzaW5nbGUgRE9NIGV2ZW50IGFuZAogICAgZm9yd2FyZGluZyB0aGF0IGludGVyYWN0aW9uIHRvIHRoZSB0ZW1wbGF0ZSdzIGNvbnRleHQgKGNvbnRyb2xsZXIgb3IgY29tcG9uZW50KS4KICAgIElmIHRoZSBjb250ZXh0IG9mIGEgdGVtcGxhdGUgaXMgYSBjb250cm9sbGVyLCBhY3Rpb25zIHVzZWQgdGhpcyB3YXkgd2lsbAogICAgYnViYmxlIHRvIHJvdXRlcyB3aGVuIHRoZSBjb250cm9sbGVyIGRvZXMgbm90IGltcGxlbWVudCB0aGUgc3BlY2lmaWVkIGFjdGlvbi4KICAgIE9uY2UgYW4gYWN0aW9uIGhpdHMgYSByb3V0ZSwgaXQgd2lsbCBidWJibGUgdGhyb3VnaCB0aGUgcm91dGUgaGllcmFyY2h5LgogIAogICAgIyMjIEV2ZW50IFByb3BhZ2F0aW9uCiAgCiAgICBge3thY3Rpb259fWAgaGVscGVycyBjYWxsZWQgaW4gZWxlbWVudCBzcGFjZSBjYW4gY29udHJvbCBldmVudCBidWJibGluZy4gTm90ZQogICAgdGhhdCB0aGUgY2xvc3VyZSBzdHlsZSBhY3Rpb25zIGNhbm5vdC4KICAKICAgIEV2ZW50cyB0cmlnZ2VyZWQgdGhyb3VnaCB0aGUgYWN0aW9uIGhlbHBlciB3aWxsIGF1dG9tYXRpY2FsbHkgaGF2ZQogICAgYC5wcmV2ZW50RGVmYXVsdCgpYCBjYWxsZWQgb24gdGhlbS4gWW91IGRvIG5vdCBuZWVkIHRvIGRvIHNvIGluIHlvdXIgZXZlbnQKICAgIGhhbmRsZXJzLiBJZiB5b3UgbmVlZCB0byBhbGxvdyBldmVudCBwcm9wYWdhdGlvbiAodG8gaGFuZGxlIGZpbGUgaW5wdXRzIGZvcgogICAgZXhhbXBsZSkgeW91IGNhbiBzdXBwbHkgdGhlIGBwcmV2ZW50RGVmYXVsdD1mYWxzZWAgb3B0aW9uIHRvIHRoZSBge3thY3Rpb259fWAgaGVscGVyOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPGRpdiB7e2FjdGlvbiAic2F5SGVsbG8iIHByZXZlbnREZWZhdWx0PWZhbHNlfX0+CiAgICAgIDxpbnB1dCB0eXBlPSJmaWxlIiAvPgogICAgICA8aW5wdXQgdHlwZT0iY2hlY2tib3giIC8+CiAgICA8L2Rpdj4KICAgIGBgYAogIAogICAgVG8gZGlzYWJsZSBidWJibGluZywgcGFzcyBgYnViYmxlcz1mYWxzZWAgdG8gdGhlIGhlbHBlcjoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxidXR0b24ge3thY3Rpb24gJ2VkaXQnIHBvc3QgYnViYmxlcz1mYWxzZX19PkVkaXQ8L2J1dHRvbj4KICAgIGBgYAogIAogICAgVG8gZGlzYWJsZSBidWJibGluZyB3aXRoIGNsb3N1cmUgc3R5bGUgYWN0aW9ucyB5b3UgbXVzdCBjcmVhdGUgeW91ciBvd24KICAgIHdyYXBwZXIgaGVscGVyIHRoYXQgbWFrZXMgdXNlIG9mIGBldmVudC5zdG9wUHJvcGFnYXRpb24oKWA6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8ZGl2IG9uY2xpY2s9e3tkaXNhYmxlLWJ1YmJsaW5nIChhY3Rpb24gInNheUhlbGxvIil9fT5IZWxsbzwvZGl2PgogICAgYGBgCiAgCiAgICBgYGBhcHAvaGVscGVycy9kaXNhYmxlLWJ1YmJsaW5nLmpzCiAgICBpbXBvcnQgeyBoZWxwZXIgfSBmcm9tICdAZW1iZXIvY29tcG9uZW50L2hlbHBlcic7CiAgCiAgICBleHBvcnQgZnVuY3Rpb24gZGlzYWJsZUJ1YmJsaW5nKFthY3Rpb25dKSB7CiAgICAgIHJldHVybiBmdW5jdGlvbihldmVudCkgewogICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOwogICAgICAgIHJldHVybiBhY3Rpb24oZXZlbnQpOwogICAgICB9OwogICAgfQogICAgZXhwb3J0IGRlZmF1bHQgaGVscGVyKGRpc2FibGVCdWJibGluZyk7CiAgICBgYGAKICAKICAgIElmIHlvdSBuZWVkIHRoZSBkZWZhdWx0IGhhbmRsZXIgdG8gdHJpZ2dlciB5b3Ugc2hvdWxkIGVpdGhlciByZWdpc3RlciB5b3VyCiAgICBvd24gZXZlbnQgaGFuZGxlciwgb3IgdXNlIGV2ZW50IG1ldGhvZHMgb24geW91ciB2aWV3IGNsYXNzLiBTZWUKICAgIFsiUmVzcG9uZGluZyB0byBCcm93c2VyIEV2ZW50cyJdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvQ29tcG9uZW50KQogICAgaW4gdGhlIGRvY3VtZW50YXRpb24gZm9yIGBDb21wb25lbnRgIGZvciBtb3JlIGluZm9ybWF0aW9uLgogIAogICAgIyMjIFNwZWNpZnlpbmcgRE9NIGV2ZW50IHR5cGUKICAKICAgIGB7e2FjdGlvbn19YCBoZWxwZXJzIGNhbGxlZCBpbiBlbGVtZW50IHNwYWNlIGNhbiBzcGVjaWZ5IGFuIGV2ZW50IHR5cGUuCiAgICBCeSBkZWZhdWx0IHRoZSBge3thY3Rpb259fWAgaGVscGVyIHJlZ2lzdGVycyBmb3IgRE9NIGBjbGlja2AgZXZlbnRzLiBZb3UgY2FuCiAgICBzdXBwbHkgYW4gYG9uYCBvcHRpb24gdG8gdGhlIGhlbHBlciB0byBzcGVjaWZ5IGEgZGlmZmVyZW50IERPTSBldmVudCBuYW1lOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPGRpdiB7e2FjdGlvbiAiYW5BY3Rpb25OYW1lIiBvbj0iZG91YmxlQ2xpY2sifX0+CiAgICAgIGNsaWNrIG1lCiAgICA8L2Rpdj4KICAgIGBgYAogIAogICAgU2VlIFsiRXZlbnQgTmFtZXMiXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0NvbXBvbmVudCkgZm9yIGEgbGlzdCBvZgogICAgYWNjZXB0YWJsZSBET00gZXZlbnQgbmFtZXMuCiAgCiAgICAjIyMgU3BlY2lmeWluZyB3aGl0ZWxpc3RlZCBtb2RpZmllciBrZXlzCiAgCiAgICBge3thY3Rpb259fWAgaGVscGVycyBjYWxsZWQgaW4gZWxlbWVudCBzcGFjZSBjYW4gc3BlY2lmeSBtb2RpZmllciBrZXlzLgogICAgQnkgZGVmYXVsdCB0aGUgYHt7YWN0aW9ufX1gIGhlbHBlciB3aWxsIGlnbm9yZSBjbGljayBldmVudHMgd2l0aCBwcmVzc2VkIG1vZGlmaWVyCiAgICBrZXlzLiBZb3UgY2FuIHN1cHBseSBhbiBgYWxsb3dlZEtleXNgIG9wdGlvbiB0byBzcGVjaWZ5IHdoaWNoIGtleXMgc2hvdWxkIG5vdCBiZSBpZ25vcmVkLgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPGRpdiB7e2FjdGlvbiAiYW5BY3Rpb25OYW1lIiBhbGxvd2VkS2V5cz0iYWx0In19PgogICAgICBjbGljayBtZQogICAgPC9kaXY+CiAgICBgYGAKICAKICAgIFRoaXMgd2F5IHRoZSBhY3Rpb24gd2lsbCBmaXJlIHdoZW4gY2xpY2tpbmcgd2l0aCB0aGUgYWx0IGtleSBwcmVzc2VkIGRvd24uCiAgICBBbHRlcm5hdGl2ZWx5LCBzdXBwbHkgImFueSIgdG8gdGhlIGBhbGxvd2VkS2V5c2Agb3B0aW9uIHRvIGFjY2VwdCBhbnkgY29tYmluYXRpb24gb2YgbW9kaWZpZXIga2V5cy4KICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxkaXYge3thY3Rpb24gImFuQWN0aW9uTmFtZSIgYWxsb3dlZEtleXM9ImFueSJ9fT4KICAgICAgY2xpY2sgbWUgd2l0aCBhbnkga2V5IHByZXNzZWQKICAgIDwvZGl2PgogICAgYGBgCiAgCiAgICAjIyMgU3BlY2lmeWluZyBhIFRhcmdldAogIAogICAgQSBgdGFyZ2V0YCBvcHRpb24gY2FuIGJlIHByb3ZpZGVkIHRvIHRoZSBoZWxwZXIgdG8gY2hhbmdlCiAgICB3aGljaCBvYmplY3Qgd2lsbCByZWNlaXZlIHRoZSBtZXRob2QgY2FsbC4gVGhpcyBvcHRpb24gbXVzdCBiZSBhIHBhdGgKICAgIHRvIGFuIG9iamVjdCwgYWNjZXNzaWJsZSBpbiB0aGUgY3VycmVudCBjb250ZXh0OgogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9hcHBsaWNhdGlvbi5oYnMKICAgIDxkaXYge3thY3Rpb24gImFuQWN0aW9uTmFtZSIgdGFyZ2V0PXNvbWVTZXJ2aWNlfX0+CiAgICAgIGNsaWNrIG1lCiAgICA8L2Rpdj4KICAgIGBgYAogIAogICAgYGBgYXBwL2NvbnRyb2xsZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgQ29udHJvbGxlciBmcm9tICdAZW1iZXIvY29udHJvbGxlcic7CiAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbnRyb2xsZXIuZXh0ZW5kKHsKICAgICAgc29tZVNlcnZpY2U6IHNlcnZpY2UoKQogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgYWN0aW9uCiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGFjdGlvbihfdm0sIGFyZ3MpIHsKICAgIHZhciBuYW1lZCA9IGFyZ3MubmFtZWQsCiAgICAgICAgcG9zaXRpb25hbCA9IGFyZ3MucG9zaXRpb25hbDsKICAgIHZhciBjYXB0dXJlZEFyZ3MgPSBwb3NpdGlvbmFsLmNhcHR1cmUoKTsgLy8gVGhlIGZpcnN0IHR3byBhcmd1bWVudCBzbG90cyBhcmUgcmVzZXJ2ZWQuCiAgICAvLyBwb3NbMF0gaXMgdGhlIGNvbnRleHQgKG9yIGB0aGlzYCkKICAgIC8vIHBvc1sxXSBpcyB0aGUgYWN0aW9uIG5hbWUgb3IgZnVuY3Rpb24KICAgIC8vIEFueXRoaW5nIGVsc2UgaXMgYW4gYWN0aW9uIGFyZ3VtZW50LgoKICAgIHZhciBfY2FwdHVyZWRBcmdzJHJlZmVyZW4gPSBjYXB0dXJlZEFyZ3MucmVmZXJlbmNlcywKICAgICAgICBjb250ZXh0ID0gX2NhcHR1cmVkQXJncyRyZWZlcmVuWzBdLAogICAgICAgIGFjdGlvbiA9IF9jYXB0dXJlZEFyZ3MkcmVmZXJlblsxXSwKICAgICAgICByZXN0QXJncyA9IF9jYXB0dXJlZEFyZ3MkcmVmZXJlbi5zbGljZSgyKTsgLy8gVE9ETzogSXMgdGhlcmUgYSBiZXR0ZXIgd2F5IG9mIGRvaW5nIHRoaXM/CgoKICAgIHZhciBkZWJ1Z0tleSA9IGFjdGlvbi5wcm9wZXJ0eUtleTsKICAgIHZhciB0YXJnZXQgPSBuYW1lZC5oYXMoJ3RhcmdldCcpID8gbmFtZWQuZ2V0KCd0YXJnZXQnKSA6IGNvbnRleHQ7CiAgICB2YXIgcHJvY2Vzc0FyZ3MgPSBtYWtlQXJnc1Byb2Nlc3NvcihuYW1lZC5oYXMoJ3ZhbHVlJykgJiYgbmFtZWQuZ2V0KCd2YWx1ZScpLCByZXN0QXJncyk7CiAgICB2YXIgZm47CgogICAgaWYgKHR5cGVvZiBhY3Rpb25bSU5WT0tFXSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICBmbiA9IG1ha2VDbG9zdXJlQWN0aW9uKGFjdGlvbiwgYWN0aW9uLCBhY3Rpb25bSU5WT0tFXSwgcHJvY2Vzc0FyZ3MsIGRlYnVnS2V5KTsKICAgIH0gZWxzZSBpZiAoKDAsIF9yZWZlcmVuY2UuaXNDb25zdCkodGFyZ2V0KSAmJiAoMCwgX3JlZmVyZW5jZS5pc0NvbnN0KShhY3Rpb24pKSB7CiAgICAgIGZuID0gbWFrZUNsb3N1cmVBY3Rpb24oY29udGV4dC52YWx1ZSgpLCB0YXJnZXQudmFsdWUoKSwgYWN0aW9uLnZhbHVlKCksIHByb2Nlc3NBcmdzLCBkZWJ1Z0tleSk7CiAgICB9IGVsc2UgewogICAgICBmbiA9IG1ha2VEeW5hbWljQ2xvc3VyZUFjdGlvbihjb250ZXh0LnZhbHVlKCksIHRhcmdldCwgYWN0aW9uLCBwcm9jZXNzQXJncywgZGVidWdLZXkpOwogICAgfQoKICAgIGZuW0FDVElPTl0gPSB0cnVlOwogICAgcmV0dXJuIG5ldyBVbmJvdW5kUmVmZXJlbmNlKGZuKTsKICB9CgogIGZ1bmN0aW9uIE5PT1AkMShhcmdzKSB7CiAgICByZXR1cm4gYXJnczsKICB9CgogIGZ1bmN0aW9uIG1ha2VBcmdzUHJvY2Vzc29yKHZhbHVlUGF0aFJlZiwgYWN0aW9uQXJnc1JlZikgewogICAgdmFyIG1lcmdlQXJnczsKCiAgICBpZiAoYWN0aW9uQXJnc1JlZi5sZW5ndGggPiAwKSB7CiAgICAgIG1lcmdlQXJncyA9IGZ1bmN0aW9uIG1lcmdlQXJncyhhcmdzKSB7CiAgICAgICAgcmV0dXJuIGFjdGlvbkFyZ3NSZWYubWFwKGZ1bmN0aW9uIChyZWYpIHsKICAgICAgICAgIHJldHVybiByZWYudmFsdWUoKTsKICAgICAgICB9KS5jb25jYXQoYXJncyk7CiAgICAgIH07CiAgICB9CgogICAgdmFyIHJlYWRWYWx1ZTsKCiAgICBpZiAodmFsdWVQYXRoUmVmKSB7CiAgICAgIHJlYWRWYWx1ZSA9IGZ1bmN0aW9uIHJlYWRWYWx1ZShhcmdzKSB7CiAgICAgICAgdmFyIHZhbHVlUGF0aCA9IHZhbHVlUGF0aFJlZi52YWx1ZSgpOwoKICAgICAgICBpZiAodmFsdWVQYXRoICYmIGFyZ3MubGVuZ3RoID4gMCkgewogICAgICAgICAgYXJnc1swXSA9ICgwLCBfbWV0YWwuZ2V0KShhcmdzWzBdLCB2YWx1ZVBhdGgpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGFyZ3M7CiAgICAgIH07CiAgICB9CgogICAgaWYgKG1lcmdlQXJncyAmJiByZWFkVmFsdWUpIHsKICAgICAgcmV0dXJuIGZ1bmN0aW9uIChhcmdzKSB7CiAgICAgICAgcmV0dXJuIHJlYWRWYWx1ZShtZXJnZUFyZ3MoYXJncykpOwogICAgICB9OwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG1lcmdlQXJncyB8fCByZWFkVmFsdWUgfHwgTk9PUCQxOwogICAgfQogIH0KCiAgZnVuY3Rpb24gbWFrZUR5bmFtaWNDbG9zdXJlQWN0aW9uKGNvbnRleHQsIHRhcmdldFJlZiwgYWN0aW9uUmVmLCBwcm9jZXNzQXJncywgZGVidWdLZXkpIHsKICAgIC8vIFdlIGRvbid0IGFsbG93IHVuZGVmaW5lZC9udWxsIHZhbHVlcywgc28gdGhpcyBjcmVhdGVzIGEgdGhyb3ctYXdheSBhY3Rpb24gdG8gdHJpZ2dlciB0aGUgYXNzZXJ0aW9ucwogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgKSB7CiAgICAgIG1ha2VDbG9zdXJlQWN0aW9uKGNvbnRleHQsIHRhcmdldFJlZi52YWx1ZSgpLCBhY3Rpb25SZWYudmFsdWUoKSwgcHJvY2Vzc0FyZ3MsIGRlYnVnS2V5KTsKICAgIH0KCiAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gbWFrZUNsb3N1cmVBY3Rpb24oY29udGV4dCwgdGFyZ2V0UmVmLnZhbHVlKCksIGFjdGlvblJlZi52YWx1ZSgpLCBwcm9jZXNzQXJncywgZGVidWdLZXkpLmFwcGx5KHZvaWQgMCwgYXJndW1lbnRzKTsKICAgIH07CiAgfQoKICBmdW5jdGlvbiBtYWtlQ2xvc3VyZUFjdGlvbihjb250ZXh0LCB0YXJnZXQsIGFjdGlvbiwgcHJvY2Vzc0FyZ3MsIGRlYnVnS2V5KSB7CiAgICB2YXIgc2VsZjsKICAgIHZhciBmbjsKICAgIChmYWxzZSAmJiAhKGFjdGlvbiAhPT0gdW5kZWZpbmVkICYmIGFjdGlvbiAhPT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJBY3Rpb24gcGFzc2VkIGlzIG51bGwgb3IgdW5kZWZpbmVkIGluIChhY3Rpb24pIGZyb20gIiArIHRhcmdldCArICIuIiwgYWN0aW9uICE9PSB1bmRlZmluZWQgJiYgYWN0aW9uICE9PSBudWxsKSk7CgogICAgaWYgKHR5cGVvZiBhY3Rpb25bSU5WT0tFXSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICBzZWxmID0gYWN0aW9uOwogICAgICBmbiA9IGFjdGlvbltJTlZPS0VdOwogICAgfSBlbHNlIHsKICAgICAgdmFyIHR5cGVvZkFjdGlvbiA9IHR5cGVvZiBhY3Rpb247CgogICAgICBpZiAodHlwZW9mQWN0aW9uID09PSAnc3RyaW5nJykgewogICAgICAgIHNlbGYgPSB0YXJnZXQ7CiAgICAgICAgZm4gPSB0YXJnZXQuYWN0aW9ucyAmJiB0YXJnZXQuYWN0aW9uc1thY3Rpb25dOwogICAgICAgIChmYWxzZSAmJiAhKGZuKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkFuIGFjdGlvbiBuYW1lZCAnIiArIGFjdGlvbiArICInIHdhcyBub3QgZm91bmQgaW4gIiArIHRhcmdldCwgZm4pKTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2ZBY3Rpb24gPT09ICdmdW5jdGlvbicpIHsKICAgICAgICBzZWxmID0gY29udGV4dDsKICAgICAgICBmbiA9IGFjdGlvbjsKICAgICAgfSBlbHNlIHsKICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoCiAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQW4gYWN0aW9uIGNvdWxkIG5vdCBiZSBtYWRlIGZvciBgIiArIChkZWJ1Z0tleSB8fCBhY3Rpb24pICsgImAgaW4gIiArIHRhcmdldCArICIuIFBsZWFzZSBjb25maXJtIHRoYXQgeW91IGFyZSB1c2luZyBlaXRoZXIgYSBxdW90ZWQgYWN0aW9uIG5hbWUgKGkuZS4gYChhY3Rpb24gJyIgKyAoZGVidWdLZXkgfHwgJ215QWN0aW9uJykgKyAiJylgKSBvciBhIGZ1bmN0aW9uIGF2YWlsYWJsZSBpbiAiICsgdGFyZ2V0ICsgIi4iLCBmYWxzZSkpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkyID0gMDsgX2tleTIgPCBfbGVuOyBfa2V5MisrKSB7CiAgICAgICAgYXJnc1tfa2V5Ml0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICB9CgogICAgICB2YXIgcGF5bG9hZCA9IHsKICAgICAgICB0YXJnZXQ6IHNlbGYsCiAgICAgICAgYXJnczogYXJncywKICAgICAgICBsYWJlbDogJ0BnbGltbWVyL2Nsb3N1cmUtYWN0aW9uJwogICAgICB9OwogICAgICByZXR1cm4gKDAsIF9pbnN0cnVtZW50YXRpb24uZmxhZ2dlZEluc3RydW1lbnQpKCdpbnRlcmFjdGlvbi5lbWJlci1hY3Rpb24nLCBwYXlsb2FkLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIF9ydW5sb29wLmpvaW4uYXBwbHkodm9pZCAwLCBbc2VsZiwgZm5dLmNvbmNhdChwcm9jZXNzQXJncyhhcmdzKSkpOwogICAgICB9KTsKICAgIH07CiAgfQogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgICBVc2UgdGhlIGB7e2FycmF5fX1gIGhlbHBlciB0byBjcmVhdGUgYW4gYXJyYXkgdG8gcGFzcyBhcyBhbiBvcHRpb24gdG8geW91cgogICAgIGNvbXBvbmVudHMuCiAgCiAgICAgYGBgaGFuZGxlYmFycwogICAgIDxNeUNvbXBvbmVudCBAcGVvcGxlPXt7YXJyYXkKICAgICAgICdUb20gRGFkZScKICAgICAgICdZZWh1ZGEgS2F0eicKICAgICAgIHRoaXMubXlPdGhlclBlcnNvbn19CiAgICAgLz4KICAgICBgYGAKICAgICAgb3IKICAgICBgYGBoYW5kbGViYXJzCiAgICAge3tteS1jb21wb25lbnQgcGVvcGxlPShhcnJheQogICAgICAgJ1RvbSBEYWRlJwogICAgICAgJ1llaHVkYSBLYXR6JwogICAgICAgdGhpcy5teU90aGVyUGVyc29uKQogICAgIH19CiAgICAgYGBgCiAgCiAgICAgV291bGQgcmVzdWx0IGluIGFuIG9iamVjdCBzdWNoIGFzOgogIAogICAgIGBgYGpzCiAgICAgWydUb20gRGF0ZScsICdZZWh1ZGEgS2F0eicsIHRoaXMuZ2V0KCdteU90aGVyUGVyc29uJyldCiAgICAgYGBgCiAgCiAgICAgV2hlcmUgdGhlIDNyZCBpdGVtIGluIHRoZSBhcnJheSBpcyBib3VuZCB0byB1cGRhdGVzIG9mIHRoZSBgbXlPdGhlclBlcnNvbmAgcHJvcGVydHkuCiAgCiAgICAgQG1ldGhvZCBhcnJheQogICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgICBAcGFyYW0ge0FycmF5fSBvcHRpb25zCiAgICAgQHJldHVybiB7QXJyYXl9IEFycmF5CiAgICAgQHNpbmNlIDMuOC4wCiAgICAgQHB1YmxpYwogICAqLwoKCiAgZnVuY3Rpb24gYXJyYXkoX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gYXJncy5wb3NpdGlvbmFsLmNhcHR1cmUoKTsKICB9CgogIHZhciBpc0VtcHR5ID0gZnVuY3Rpb24gaXNFbXB0eSh2YWx1ZSQkMSkgewogICAgcmV0dXJuIHZhbHVlJCQxID09PSBudWxsIHx8IHZhbHVlJCQxID09PSB1bmRlZmluZWQgfHwgdHlwZW9mIHZhbHVlJCQxLnRvU3RyaW5nICE9PSAnZnVuY3Rpb24nOwogIH07CgogIHZhciBub3JtYWxpemVUZXh0VmFsdWUgPSBmdW5jdGlvbiBub3JtYWxpemVUZXh0VmFsdWUodmFsdWUkJDEpIHsKICAgIGlmIChpc0VtcHR5KHZhbHVlJCQxKSkgewogICAgICByZXR1cm4gJyc7CiAgICB9CgogICAgcmV0dXJuIFN0cmluZyh2YWx1ZSQkMSk7CiAgfTsKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBDb25jYXRlbmF0ZXMgdGhlIGdpdmVuIGFyZ3VtZW50cyBpbnRvIGEgc3RyaW5nLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7c29tZS1jb21wb25lbnQgbmFtZT0oY29uY2F0IGZpcnN0TmFtZSAiICIgbGFzdE5hbWUpfX0KICAKICAgIHt7ISB3b3VsZCBwYXNzIG5hbWU9IjxmaXJzdCBuYW1lIHZhbHVlPiA8bGFzdCBuYW1lIHZhbHVlPiIgdG8gdGhlIGNvbXBvbmVudH19CiAgICBgYGAKICAKICAgIG9yIGZvciBhbmdsZSBicmFja2V0IGludm9jYXRpb24sIHlvdSBhY3R1YWxseSBkb24ndCBuZWVkIGNvbmNhdCBhdCBhbGwuCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8U29tZUNvbXBvbmVudCBAbmFtZT0ie3tmaXJzdE5hbWV9fSB7e2xhc3ROYW1lfX0iIC8+CiAgICBgYGAKICAKICAgIEBwdWJsaWMKICAgIEBtZXRob2QgY29uY2F0CiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAc2luY2UgMS4xMy4wCiAgKi8KCgogIGZ1bmN0aW9uIGNvbmNhdChfcmVmMjcpIHsKICAgIHZhciBwb3NpdGlvbmFsID0gX3JlZjI3LnBvc2l0aW9uYWw7CiAgICByZXR1cm4gcG9zaXRpb25hbC52YWx1ZSgpLm1hcChub3JtYWxpemVUZXh0VmFsdWUpLmpvaW4oJycpOwogIH0KCiAgZnVuY3Rpb24gY29uY2F0JDEoX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gbmV3IEludGVybmFsSGVscGVyUmVmZXJlbmNlKGNvbmNhdCwgYXJncy5jYXB0dXJlKCkpOwogIH0KCiAgZnVuY3Rpb24gYnVpbGRVbnRvdWNoYWJsZVRoaXMoc291cmNlKSB7CiAgICB2YXIgY29udGV4dCA9IG51bGw7CgogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgJiYgX3V0aWxzLkhBU19OQVRJVkVfUFJPWFkpIHsKICAgICAgdmFyIGFzc2VydE9uUHJvcGVydHkgPSBmdW5jdGlvbiBhc3NlcnRPblByb3BlcnR5KHByb3BlcnR5KSB7CiAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGFjY2Vzc2VkIGB0aGlzLiIgKyBTdHJpbmcocHJvcGVydHkpICsgImAgZnJvbSBhIGZ1bmN0aW9uIHBhc3NlZCB0byB0aGUgIiArIHNvdXJjZSArICIsIGJ1dCB0aGUgZnVuY3Rpb24gaXRzZWxmIHdhcyBub3QgYm91bmQgdG8gYSB2YWxpZCBgdGhpc2AgY29udGV4dC4gQ29uc2lkZXIgdXBkYXRpbmcgdG8gdXNhZ2Ugb2YgYEBhY3Rpb25gLiIpKTsKICAgICAgfTsKCiAgICAgIGNvbnRleHQgPSBuZXcgUHJveHkoe30sIHsKICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldChfdGFyZ2V0LCBwcm9wZXJ0eSkgewogICAgICAgICAgYXNzZXJ0T25Qcm9wZXJ0eShwcm9wZXJ0eSk7CiAgICAgICAgfSwKICAgICAgICBzZXQ6IGZ1bmN0aW9uIHNldChfdGFyZ2V0LCBwcm9wZXJ0eSkgewogICAgICAgICAgYXNzZXJ0T25Qcm9wZXJ0eShwcm9wZXJ0eSk7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfSwKICAgICAgICBoYXM6IGZ1bmN0aW9uIGhhcyhfdGFyZ2V0LCBwcm9wZXJ0eSkgewogICAgICAgICAgYXNzZXJ0T25Qcm9wZXJ0eShwcm9wZXJ0eSk7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KCiAgICByZXR1cm4gY29udGV4dDsKICB9CgogIHZhciBjb250ZXh0ID0gYnVpbGRVbnRvdWNoYWJsZVRoaXMoJ2BmbmAgaGVscGVyJyk7CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgVGhlIGBmbmAgaGVscGVyIGFsbG93cyB5b3UgdG8gZW5zdXJlIGEgZnVuY3Rpb24gdGhhdCB5b3UgYXJlIHBhc3Npbmcgb2ZmCiAgICB0byBhbm90aGVyIGNvbXBvbmVudCwgaGVscGVyLCBvciBtb2RpZmllciBoYXMgYWNjZXNzIHRvIGFyZ3VtZW50cyB0aGF0IGFyZQogICAgYXZhaWxhYmxlIGluIHRoZSB0ZW1wbGF0ZS4KICAKICAgIEZvciBleGFtcGxlLCBpZiB5b3UgaGF2ZSBhbiBgZWFjaGAgaGVscGVyIGxvb3Bpbmcgb3ZlciBhIG51bWJlciBvZiBpdGVtcywgeW91CiAgICBtYXkgbmVlZCB0byBwYXNzIGEgZnVuY3Rpb24gdGhhdCBleHBlY3RzIHRvIHJlY2VpdmUgdGhlIGl0ZW0gYXMgYW4gYXJndW1lbnQKICAgIHRvIGEgY29tcG9uZW50IGludm9rZWQgd2l0aGluIHRoZSBsb29wLiBIZXJlJ3MgaG93IHlvdSBjb3VsZCB1c2UgdGhlIGBmbmAKICAgIGhlbHBlciB0byBwYXNzIGJvdGggdGhlIGZ1bmN0aW9uIGFuZCBpdHMgYXJndW1lbnRzIHRvZ2V0aGVyOgogIAogICAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvaXRlbXMtbGlzdGluZy5oYnMKICAgIHt7I2VhY2ggQGl0ZW1zIGFzIHxpdGVtfH19CiAgICAgIDxEaXNwbGF5SXRlbSBAaXRlbT1pdGVtIEBzZWxlY3Q9e3tmbiB0aGlzLmhhbmRsZVNlbGVjdGVkIGl0ZW19fSAvPgogICAge3svZWFjaH19CiAgICBgYGAKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL2l0ZW1zLWxpc3QuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGdsaW1tZXIvY29tcG9uZW50JzsKICAgIGltcG9ydCB7IGFjdGlvbiB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgY2xhc3MgSXRlbXNMaXN0IGV4dGVuZHMgQ29tcG9uZW50IHsKICAgICAgQGFjdGlvbgogICAgICBoYW5kbGVTZWxlY3RlZChpdGVtKSB7CiAgICAgICAgLy8gLi4uc25pcC4uLgogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIEluIHRoaXMgY2FzZSB0aGUgYGRpc3BsYXktaXRlbWAgY29tcG9uZW50IHdpbGwgcmVjZWl2ZSBhIG5vcm1hbCBmdW5jdGlvbgogICAgdGhhdCBpdCBjYW4gaW52b2tlLiBXaGVuIGl0IGludm9rZXMgdGhlIGZ1bmN0aW9uLCB0aGUgYGhhbmRsZVNlbGVjdGVkYAogICAgZnVuY3Rpb24gd2lsbCByZWNlaXZlIHRoZSBgaXRlbWAgYW5kIGFueSBhcmd1bWVudHMgcGFzc2VkLCB0aGFua3MgdG8gdGhlCiAgICBgZm5gIGhlbHBlci4KICAKICAgIExldCdzIHRha2UgbG9vayBhdCB3aGF0IHRoYXQgbWVhbnMgaW4gYSBjb3VwbGUgY2lyY3Vtc3RhbmNlczoKICAKICAgIC0gV2hlbiBpbnZva2VkIGFzIGB0aGlzLmFyZ3Muc2VsZWN0KClgIHRoZSBgaGFuZGxlU2VsZWN0ZWRgIGZ1bmN0aW9uIHdpbGwKICAgICAgcmVjZWl2ZSB0aGUgYGl0ZW1gIGZyb20gdGhlIGxvb3AgYXMgaXRzIGZpcnN0IGFuZCBvbmx5IGFyZ3VtZW50LgogICAgLSBXaGVuIGludm9rZWQgYXMgYHRoaXMuYXJncy5zZWxlY3QoJ2ZvbycpYCB0aGUgYGhhbmRsZVNlbGVjdGVkYCBmdW5jdGlvbgogICAgICB3aWxsIHJlY2VpdmUgdGhlIGBpdGVtYCBmcm9tIHRoZSBsb29wIGFzIGl0cyBmaXJzdCBhcmd1bWVudCBhbmQgdGhlCiAgICAgIHN0cmluZyBgJ2ZvbydgIGFzIGl0cyBzZWNvbmQgYXJndW1lbnQuCiAgCiAgICBJbiB0aGUgZXhhbXBsZSBhYm92ZSwgd2UgdXNlZCBgQGFjdGlvbmAgdG8gZW5zdXJlIHRoYXQgYGhhbmRsZVNlbGVjdGVkYCBpcwogICAgcHJvcGVybHkgYm91bmQgdG8gdGhlIGBpdGVtcy1saXN0YCwgYnV0IGxldCdzIGV4cGxvcmUgd2hhdCBoYXBwZW5zIGlmIHdlCiAgICBsZWZ0IG91dCBgQGFjdGlvbmA6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9pdGVtcy1saXN0LmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BnbGltbWVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBjbGFzcyBJdGVtc0xpc3QgZXh0ZW5kcyBDb21wb25lbnQgewogICAgICBoYW5kbGVTZWxlY3RlZChpdGVtKSB7CiAgICAgICAgLy8gLi4uc25pcC4uLgogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIEluIHRoaXMgZXhhbXBsZSwgd2hlbiBgaGFuZGxlU2VsZWN0ZWRgIGlzIGludm9rZWQgaW5zaWRlIHRoZSBgZGlzcGxheS1pdGVtYAogICAgY29tcG9uZW50LCBpdCB3aWxsICoqbm90KiogaGF2ZSBhY2Nlc3MgdG8gdGhlIGNvbXBvbmVudCBpbnN0YW5jZS4gSW4gb3RoZXIKICAgIHdvcmRzLCBpdCB3aWxsIGhhdmUgbm8gYHRoaXNgIGNvbnRleHQsIHNvIHBsZWFzZSBtYWtlIHN1cmUgeW91ciBmdW5jdGlvbnMKICAgIGFyZSBib3VuZCAodmlhIGBAYWN0aW9uYCBvciBvdGhlciBtZWFucykgYmVmb3JlIHBhc3NpbmcgaW50byBgZm5gIQogIAogICAgU2VlIGFsc28gW3BhcnRpYWwgYXBwbGljYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BhcnRpYWxfYXBwbGljYXRpb24pLgogIAogICAgQG1ldGhvZCBmbgogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHB1YmxpYwogICAgQHNpbmNlIDMuMTEuMAogICovCgogIGZ1bmN0aW9uIGZuSGVscGVyKF9yZWYyOCkgewogICAgdmFyIHBvc2l0aW9uYWwgPSBfcmVmMjgucG9zaXRpb25hbDsKICAgIHZhciBjYWxsYmFja1JlZiA9IHBvc2l0aW9uYWwuYXQoMCk7CgogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgJiYgdHlwZW9mIGNhbGxiYWNrUmVmW0lOVk9LRV0gIT09ICdmdW5jdGlvbicpIHsKICAgICAgdmFyIGNhbGxiYWNrID0gY2FsbGJhY2tSZWYudmFsdWUoKTsKICAgICAgKGZhbHNlICYmICEodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBtdXN0IHBhc3MgYSBmdW5jdGlvbiBhcyB0aGUgYGZuYCBoZWxwZXJzIGZpcnN0IGFyZ3VtZW50LCB5b3UgcGFzc2VkICIgKyBjYWxsYmFjaywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICB9CgogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIF9wb3NpdGlvbmFsJHZhbHVlID0gcG9zaXRpb25hbC52YWx1ZSgpLAogICAgICAgICAgZm4gPSBfcG9zaXRpb25hbCR2YWx1ZVswXSwKICAgICAgICAgIGFyZ3MgPSBfcG9zaXRpb25hbCR2YWx1ZS5zbGljZSgxKTsKCiAgICAgIGZvciAodmFyIF9sZW4yID0gYXJndW1lbnRzLmxlbmd0aCwgaW52b2NhdGlvbkFyZ3MgPSBuZXcgQXJyYXkoX2xlbjIpLCBfa2V5MyA9IDA7IF9rZXkzIDwgX2xlbjI7IF9rZXkzKyspIHsKICAgICAgICBpbnZvY2F0aW9uQXJnc1tfa2V5M10gPSBhcmd1bWVudHNbX2tleTNdOwogICAgICB9CgogICAgICBpZiAodHlwZW9mIGNhbGxiYWNrUmVmW0lOVk9LRV0gPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAvLyByZWZlcmVuY2VzIHdpdGggdGhlIElOVk9LRSBzeW1ib2wgZXhwZWN0IHRoZSBmdW5jdGlvbiBiZWhpbmQKICAgICAgICAvLyB0aGUgc3ltYm9sIHRvIGJlIGJvdW5kIHRvIHRoZSByZWZlcmVuY2UKICAgICAgICByZXR1cm4gY2FsbGJhY2tSZWZbSU5WT0tFXS5hcHBseShjYWxsYmFja1JlZiwgYXJncy5jb25jYXQoaW52b2NhdGlvbkFyZ3MpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gZm5bJ2NhbGwnXS5hcHBseShmbiwgW2NvbnRleHRdLmNvbmNhdChhcmdzLCBpbnZvY2F0aW9uQXJncykpOwogICAgICB9CiAgICB9OwogIH0KCiAgZnVuY3Rpb24gZm4oX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gbmV3IEludGVybmFsSGVscGVyUmVmZXJlbmNlKGZuSGVscGVyLCBhcmdzLmNhcHR1cmUoKSk7CiAgfQogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIER5bmFtaWNhbGx5IGxvb2sgdXAgYSBwcm9wZXJ0eSBvbiBhbiBvYmplY3QuIFRoZSBzZWNvbmQgYXJndW1lbnQgdG8gYHt7Z2V0fX1gCiAgICBzaG91bGQgaGF2ZSBhIHN0cmluZyB2YWx1ZSwgYWx0aG91Z2ggaXQgY2FuIGJlIGJvdW5kLgogIAogICAgRm9yIGV4YW1wbGUsIHRoZXNlIHR3byB1c2FnZXMgYXJlIGVxdWl2YWxlbnQ6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e3BlcnNvbi5oZWlnaHR9fQogICAge3tnZXQgcGVyc29uICJoZWlnaHQifX0KICAgIGBgYAogIAogICAgSWYgdGhlcmUgd2VyZSBzZXZlcmFsIGZhY3RzIGFib3V0IGEgcGVyc29uLCB0aGUgYHt7Z2V0fX1gIGhlbHBlciBjYW4gZHluYW1pY2FsbHkKICAgIHBpY2sgb25lOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3tnZXQgcGVyc29uIGZhY3ROYW1lfX0KICAgIGBgYAogIAogICAgRm9yIGEgbW9yZSBjb21wbGV4IGV4YW1wbGUsIHRoaXMgdGVtcGxhdGUgd291bGQgYWxsb3cgdGhlIHVzZXIgdG8gc3dpdGNoCiAgICBiZXR3ZWVuIHNob3dpbmcgdGhlIHVzZXIncyBoZWlnaHQgYW5kIHdlaWdodCB3aXRoIGEgY2xpY2s6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e2dldCBwZXJzb24gZmFjdE5hbWV9fQogICAgPGJ1dHRvbiB7e2FjdGlvbiAoZm4gKG11dCBmYWN0TmFtZSkpICJoZWlnaHQifX0+U2hvdyBoZWlnaHQ8L2J1dHRvbj4KICAgIDxidXR0b24ge3thY3Rpb24gKGZuIChtdXQgZmFjdE5hbWUpKSAid2VpZ2h0In19PlNob3cgd2VpZ2h0PC9idXR0b24+CiAgICBgYGAKICAKICAgIFRoZSBge3tnZXR9fWAgaGVscGVyIGNhbiBhbHNvIHJlc3BlY3QgbXV0YWJsZSB2YWx1ZXMgaXRzZWxmLiBGb3IgZXhhbXBsZToKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7aW5wdXQgdmFsdWU9KG11dCAoZ2V0IHBlcnNvbiBmYWN0TmFtZSkpIHR5cGU9InRleHQifX0KICAgIDxidXR0b24ge3thY3Rpb24gKGZuIChtdXQgZmFjdE5hbWUpKSAiaGVpZ2h0In19PlNob3cgaGVpZ2h0PC9idXR0b24+CiAgICA8YnV0dG9uIHt7YWN0aW9uIChmbiAobXV0IGZhY3ROYW1lKSkgIndlaWdodCJ9fT5TaG93IHdlaWdodDwvYnV0dG9uPgogICAgYGBgCiAgCiAgICBXb3VsZCBhbGxvdyB0aGUgdXNlciB0byBzd2FwIHdoYXQgZmFjdCBpcyBiZWluZyBkaXNwbGF5ZWQsIGFuZCBhbHNvIGVkaXQKICAgIHRoYXQgZmFjdCB2aWEgYSB0d28td2F5IG11dGFibGUgYmluZGluZy4KICAKICAgIEBwdWJsaWMKICAgIEBtZXRob2QgZ2V0CiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAc2luY2UgMi4xLjAKICAgKi8KCgogIGZ1bmN0aW9uIGdldCQxKF92bSwgYXJncykgewogICAgcmV0dXJuIEdldEhlbHBlclJlZmVyZW5jZS5jcmVhdGUoYXJncy5wb3NpdGlvbmFsLmF0KDApLCBhcmdzLnBvc2l0aW9uYWwuYXQoMSkpOwogIH0KCiAgZnVuY3Rpb24gcmVmZXJlbmNlRnJvbVBhdGgoc291cmNlLCBwYXRoKSB7CiAgICB2YXIgaW5uZXJSZWZlcmVuY2U7CgogICAgaWYgKHBhdGggPT09IHVuZGVmaW5lZCB8fCBwYXRoID09PSBudWxsIHx8IHBhdGggPT09ICcnKSB7CiAgICAgIGlubmVyUmVmZXJlbmNlID0gX3J1bnRpbWUyLk5VTExfUkVGRVJFTkNFOwogICAgfSBlbHNlIGlmICh0eXBlb2YgcGF0aCA9PT0gJ3N0cmluZycgJiYgcGF0aC5pbmRleE9mKCcuJykgPiAtMSkgewogICAgICBpbm5lclJlZmVyZW5jZSA9IHJlZmVyZW5jZUZyb21QYXJ0cyhzb3VyY2UsIHBhdGguc3BsaXQoJy4nKSk7CiAgICB9IGVsc2UgewogICAgICBpbm5lclJlZmVyZW5jZSA9IHNvdXJjZS5nZXQocGF0aCk7CiAgICB9CgogICAgcmV0dXJuIGlubmVyUmVmZXJlbmNlOwogIH0KCiAgdmFyIEdldEhlbHBlclJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ2FjaGVkUmVmZXJlbmNlJDYpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShHZXRIZWxwZXJSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UkNik7CgogICAgR2V0SGVscGVyUmVmZXJlbmNlLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShzb3VyY2VSZWZlcmVuY2UsIHBhdGhSZWZlcmVuY2UpIHsKICAgICAgaWYgKCgwLCBfcmVmZXJlbmNlLmlzQ29uc3QpKHBhdGhSZWZlcmVuY2UpKSB7CiAgICAgICAgdmFyIHBhdGggPSBwYXRoUmVmZXJlbmNlLnZhbHVlKCk7CiAgICAgICAgcmV0dXJuIHJlZmVyZW5jZUZyb21QYXRoKHNvdXJjZVJlZmVyZW5jZSwgcGF0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyBHZXRIZWxwZXJSZWZlcmVuY2Uoc291cmNlUmVmZXJlbmNlLCBwYXRoUmVmZXJlbmNlKTsKICAgICAgfQogICAgfTsKCiAgICBmdW5jdGlvbiBHZXRIZWxwZXJSZWZlcmVuY2Uoc291cmNlUmVmZXJlbmNlLCBwYXRoUmVmZXJlbmNlKSB7CiAgICAgIHZhciBfdGhpczIyOwoKICAgICAgX3RoaXMyMiA9IF9DYWNoZWRSZWZlcmVuY2UkNi5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMjIuc291cmNlUmVmZXJlbmNlID0gc291cmNlUmVmZXJlbmNlOwogICAgICBfdGhpczIyLnBhdGhSZWZlcmVuY2UgPSBwYXRoUmVmZXJlbmNlOwogICAgICBfdGhpczIyLmxhc3RQYXRoID0gbnVsbDsKICAgICAgX3RoaXMyMi5pbm5lclJlZmVyZW5jZSA9IF9ydW50aW1lMi5OVUxMX1JFRkVSRU5DRTsKICAgICAgdmFyIGlubmVyVGFnID0gX3RoaXMyMi5pbm5lclRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgX3RoaXMyMi50YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShbc291cmNlUmVmZXJlbmNlLnRhZywgcGF0aFJlZmVyZW5jZS50YWcsIGlubmVyVGFnXSk7CiAgICAgIHJldHVybiBfdGhpczIyOwogICAgfQoKICAgIHZhciBfcHJvdG81MyA9IEdldEhlbHBlclJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNTMuY29tcHV0ZSA9IGZ1bmN0aW9uIGNvbXB1dGUoKSB7CiAgICAgIHZhciBsYXN0UGF0aCA9IHRoaXMubGFzdFBhdGgsCiAgICAgICAgICBpbm5lclJlZmVyZW5jZSA9IHRoaXMuaW5uZXJSZWZlcmVuY2UsCiAgICAgICAgICBpbm5lclRhZyA9IHRoaXMuaW5uZXJUYWc7CiAgICAgIHZhciBwYXRoID0gdGhpcy5wYXRoUmVmZXJlbmNlLnZhbHVlKCk7CgogICAgICBpZiAocGF0aCAhPT0gbGFzdFBhdGgpIHsKICAgICAgICBpbm5lclJlZmVyZW5jZSA9IHJlZmVyZW5jZUZyb21QYXRoKHRoaXMuc291cmNlUmVmZXJlbmNlLCBwYXRoKTsKICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKGlubmVyVGFnLCBpbm5lclJlZmVyZW5jZS50YWcpOwogICAgICAgIHRoaXMuaW5uZXJSZWZlcmVuY2UgPSBpbm5lclJlZmVyZW5jZTsKICAgICAgICB0aGlzLmxhc3RQYXRoID0gcGF0aDsKICAgICAgfQoKICAgICAgcmV0dXJuIGlubmVyUmVmZXJlbmNlLnZhbHVlKCk7CiAgICB9OwoKICAgIF9wcm90bzUzW1VQREFURV0gPSBmdW5jdGlvbiAodmFsdWUkJDEpIHsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMuc291cmNlUmVmZXJlbmNlLnZhbHVlKCksIHRoaXMucGF0aFJlZmVyZW5jZS52YWx1ZSgpLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIHJldHVybiBHZXRIZWxwZXJSZWZlcmVuY2U7CiAgfShDYWNoZWRSZWZlcmVuY2UkMSk7CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgIFVzZSB0aGUgYHt7aGFzaH19YCBoZWxwZXIgdG8gY3JlYXRlIGEgaGFzaCB0byBwYXNzIGFzIGFuIG9wdGlvbiB0byB5b3VyCiAgICAgY29tcG9uZW50cy4gVGhpcyBpcyBzcGVjaWFsbHkgdXNlZnVsIGZvciBjb250ZXh0dWFsIGNvbXBvbmVudHMgd2hlcmUgeW91IGNhbgogICAgIGp1c3QgeWllbGQgYSBoYXNoOgogIAogICAgIGBgYGhhbmRsZWJhcnMKICAgICB7e3lpZWxkIChoYXNoCiAgICAgICAgbmFtZT0nU2FyYWgnCiAgICAgICAgdGl0bGU9b2ZmaWNlCiAgICAgKX19CiAgICAgYGBgCiAgCiAgICAgV291bGQgcmVzdWx0IGluIGFuIG9iamVjdCBzdWNoIGFzOgogIAogICAgIGBgYGpzCiAgICAgeyBuYW1lOiAnU2FyYWgnLCB0aXRsZTogdGhpcy5nZXQoJ29mZmljZScpIH0KICAgICBgYGAKICAKICAgICBXaGVyZSB0aGUgYHRpdGxlYCBpcyBib3VuZCB0byB1cGRhdGVzIG9mIHRoZSBgb2ZmaWNlYCBwcm9wZXJ0eS4KICAKICAgICBOb3RlIHRoYXQgdGhlIGhhc2ggaXMgYW4gZW1wdHkgb2JqZWN0IHdpdGggbm8gcHJvdG90eXBlIGNoYWluLCB0aGVyZWZvcmUKICAgICBjb21tb24gbWV0aG9kcyBsaWtlIGB0b1N0cmluZ2AgYXJlIG5vdCBhdmFpbGFibGUgaW4gdGhlIHJlc3VsdGluZyBoYXNoLgogICAgIElmIHlvdSBuZWVkIHRvIHVzZSBzdWNoIGEgbWV0aG9kLCB5b3UgY2FuIHVzZSB0aGUgYGNhbGxgIG9yIGBhcHBseWAKICAgICBhcHByb2FjaDoKICAKICAgICBgYGBqcwogICAgIGZ1bmN0aW9uIHRvU3RyaW5nKG9iaikgewogICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuYXBwbHkob2JqKTsKICAgICB9CiAgICAgYGBgCiAgCiAgICAgQG1ldGhvZCBoYXNoCiAgICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgQHJldHVybiB7T2JqZWN0fSBIYXNoCiAgICAgQHNpbmNlIDIuMy4wCiAgICAgQHB1YmxpYwogICAqLwoKCiAgZnVuY3Rpb24gaGFzaChfdm0sIGFyZ3MpIHsKICAgIHJldHVybiBhcmdzLm5hbWVkLmNhcHR1cmUoKTsKICB9CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgoKICB2YXIgQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NhY2hlZFJlZmVyZW5jZSQ3KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UkNyk7CgogICAgQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKF9jb25kUmVmLCB0cnV0aHlSZWYsIGZhbHN5UmVmKSB7CiAgICAgIHZhciBjb25kUmVmID0gQ29uZGl0aW9uYWxSZWZlcmVuY2UkMS5jcmVhdGUoX2NvbmRSZWYpOwoKICAgICAgaWYgKCgwLCBfcmVmZXJlbmNlLmlzQ29uc3QpKGNvbmRSZWYpKSB7CiAgICAgICAgcmV0dXJuIGNvbmRSZWYudmFsdWUoKSA/IHRydXRoeVJlZiA6IGZhbHN5UmVmOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBuZXcgQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UoY29uZFJlZiwgdHJ1dGh5UmVmLCBmYWxzeVJlZik7CiAgICAgIH0KICAgIH07CgogICAgZnVuY3Rpb24gQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UoY29uZCwgdHJ1dGh5LCBmYWxzeSkgewogICAgICB2YXIgX3RoaXMyMzsKCiAgICAgIF90aGlzMjMgPSBfQ2FjaGVkUmVmZXJlbmNlJDcuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczIzLmJyYW5jaFRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgX3RoaXMyMy50YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShbY29uZC50YWcsIF90aGlzMjMuYnJhbmNoVGFnXSk7CiAgICAgIF90aGlzMjMuY29uZCA9IGNvbmQ7CiAgICAgIF90aGlzMjMudHJ1dGh5ID0gdHJ1dGh5OwogICAgICBfdGhpczIzLmZhbHN5ID0gZmFsc3k7CiAgICAgIHJldHVybiBfdGhpczIzOwogICAgfQoKICAgIHZhciBfcHJvdG81NCA9IENvbmRpdGlvbmFsSGVscGVyUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG81NC5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgdmFyIGJyYW5jaCA9IHRoaXMuY29uZC52YWx1ZSgpID8gdGhpcy50cnV0aHkgOiB0aGlzLmZhbHN5OwogICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHRoaXMuYnJhbmNoVGFnLCBicmFuY2gudGFnKTsKICAgICAgcmV0dXJuIGJyYW5jaC52YWx1ZSgpOwogICAgfTsKCiAgICByZXR1cm4gQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2U7CiAgfShDYWNoZWRSZWZlcmVuY2UkMSk7CiAgLyoqCiAgICBUaGUgYGlmYCBoZWxwZXIgYWxsb3dzIHlvdSB0byBjb25kaXRpb25hbGx5IHJlbmRlciBvbmUgb2YgdHdvIGJyYW5jaGVzLAogICAgZGVwZW5kaW5nIG9uIHRoZSAidHJ1dGhpbmVzcyIgb2YgYSBwcm9wZXJ0eS4KICAgIEZvciBleGFtcGxlIHRoZSBmb2xsb3dpbmcgdmFsdWVzIGFyZSBhbGwgZmFsc2V5OiBgZmFsc2VgLCBgdW5kZWZpbmVkYCwgYG51bGxgLCBgIiJgLCBgMGAsIGBOYU5gIG9yIGFuIGVtcHR5IGFycmF5LgogIAogICAgVGhpcyBoZWxwZXIgaGFzIHR3byBmb3JtcywgYmxvY2sgYW5kIGlubGluZS4KICAKICAgICMjIEJsb2NrIGZvcm0KICAKICAgIFlvdSBjYW4gdXNlIHRoZSBibG9jayBmb3JtIG9mIGBpZmAgdG8gY29uZGl0aW9uYWxseSByZW5kZXIgYSBzZWN0aW9uIG9mIHRoZSB0ZW1wbGF0ZS4KICAKICAgIFRvIHVzZSBpdCwgcGFzcyB0aGUgY29uZGl0aW9uYWwgdmFsdWUgdG8gdGhlIGBpZmAgaGVscGVyLAogICAgdXNpbmcgdGhlIGJsb2NrIGZvcm0gdG8gd3JhcCB0aGUgc2VjdGlvbiBvZiB0ZW1wbGF0ZSB5b3Ugd2FudCB0byBjb25kaXRpb25hbGx5IHJlbmRlci4KICAgIExpa2Ugc286CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7eyEgd2lsbCBub3QgcmVuZGVyIGlmIGZvbyBpcyBmYWxzZXl9fQogICAge3sjaWYgZm9vfX0KICAgICAgV2VsY29tZSB0byB0aGUge3tmb28uYmFyfX0KICAgIHt7L2lmfX0KICAgIGBgYAogIAogICAgWW91IGNhbiBhbHNvIHNwZWNpZnkgYSB0ZW1wbGF0ZSB0byBzaG93IGlmIHRoZSBwcm9wZXJ0eSBpcyBmYWxzZXkgYnkgdXNpbmcKICAgIHRoZSBgZWxzZWAgaGVscGVyLgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3shIGlzIGl0IHJhaW5pbmcgb3V0c2lkZT99fQogICAge3sjaWYgaXNSYWluaW5nfX0KICAgICAgWWVzLCBncmFiIGFuIHVtYnJlbGxhIQogICAge3tlbHNlfX0KICAgICAgTm8sIGl0J3MgbG92ZWx5IG91dHNpZGUhCiAgICB7ey9pZn19CiAgICBgYGAKICAKICAgIFlvdSBhcmUgYWxzbyBhYmxlIHRvIGNvbWJpbmUgYGVsc2VgIGFuZCBgaWZgIGhlbHBlcnMgdG8gY3JlYXRlIG1vcmUgY29tcGxleAogICAgY29uZGl0aW9uYWwgbG9naWMuCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7eyNpZiBpc01vcm5pbmd9fQogICAgICBHb29kIG1vcm5pbmcKICAgIHt7ZWxzZSBpZiBpc0FmdGVybm9vbn19CiAgICAgIEdvb2QgYWZ0ZXJub29uCiAgICB7e2Vsc2V9fQogICAgICBHb29kIG5pZ2h0CiAgICB7ey9pZn19CiAgICBgYGAKICAKICAgICMjIElubGluZSBmb3JtCiAgCiAgICBUaGUgaW5saW5lIGBpZmAgaGVscGVyIGNvbmRpdGlvbmFsbHkgcmVuZGVycyBhIHNpbmdsZSBwcm9wZXJ0eSBvciBzdHJpbmcuCiAgCiAgICBJbiB0aGlzIGZvcm0sIHRoZSBgaWZgIGhlbHBlciByZWNlaXZlcyB0aHJlZSBhcmd1bWVudHMsIHRoZSBjb25kaXRpb25hbCB2YWx1ZSwKICAgIHRoZSB2YWx1ZSB0byByZW5kZXIgd2hlbiB0cnV0aHksIGFuZCB0aGUgdmFsdWUgdG8gcmVuZGVyIHdoZW4gZmFsc2V5LgogIAogICAgRm9yIGV4YW1wbGUsIGlmIGB1c2VMb25nR3JlZXRpbmdgIGlzIHRydXRoeSwgdGhlIGZvbGxvd2luZzoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7aWYgdXNlTG9uZ0dyZWV0aW5nICJIZWxsbyIgIkhpIn19IEFsZXgKICAgIGBgYAogIAogICAgV2lsbCByZW5kZXI6CiAgCiAgICBgYGBodG1sCiAgICBIZWxsbyBBbGV4CiAgICBgYGAKICAKICAgICMjIyBOZXN0ZWQgYGlmYAogIAogICAgWW91IGNhbiB1c2UgdGhlIGBpZmAgaGVscGVyIGluc2lkZSBhbm90aGVyIGhlbHBlciBhcyBhIG5lc3RlZCBoZWxwZXI6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8U29tZUNvbXBvbmVudCBAaGVpZ2h0PXt7aWYgaXNCaWcgIjEwMCIgIjEwIn19IC8+CiAgICBgYGAKICAKICAgIG9yCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e3NvbWUtY29tcG9uZW50IGhlaWdodD0oaWYgaXNCaWcgIjEwMCIgIjEwIil9fQogICAgYGBgCiAgCiAgICBPbmUgZGV0YWlsIHRvIGtlZXAgaW4gbWluZCBpcyB0aGF0IGJvdGggYnJhbmNoZXMgb2YgdGhlIGBpZmAgaGVscGVyIHdpbGwgYmUgZXZhbHVhdGVkLAogICAgc28gaWYgeW91IGhhdmUgYHt7aWYgY29uZGl0aW9uICJmb28iIChleHBlbnNpdmUtb3BlcmF0aW9uICJiYXIiKWAsCiAgICBgZXhwZW5zaXZlLW9wZXJhdGlvbmAgd2lsbCBhbHdheXMgY2FsY3VsYXRlLgogIAogICAgQG1ldGhvZCBpZgogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpbmxpbmVJZihfdm0sIF9yZWYyOSkgewogICAgdmFyIHBvc2l0aW9uYWwgPSBfcmVmMjkucG9zaXRpb25hbDsKICAgIChmYWxzZSAmJiAhKHBvc2l0aW9uYWwubGVuZ3RoID09PSAzIHx8IHBvc2l0aW9uYWwubGVuZ3RoID09PSAyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBpbmxpbmUgZm9ybSBvZiB0aGUgYGlmYCBoZWxwZXIgZXhwZWN0cyB0d28gb3IgdGhyZWUgYXJndW1lbnRzLCBlLmcuICcgKyAnYHt7aWYgdHJpYWxFeHBpcmVkICJFeHBpcmVkIiBleHBpcnlEYXRlfX1gLicsIHBvc2l0aW9uYWwubGVuZ3RoID09PSAzIHx8IHBvc2l0aW9uYWwubGVuZ3RoID09PSAyKSk7CiAgICByZXR1cm4gQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UuY3JlYXRlKHBvc2l0aW9uYWwuYXQoMCksIHBvc2l0aW9uYWwuYXQoMSksIHBvc2l0aW9uYWwuYXQoMikpOwogIH0KICAvKioKICAgIFRoZSBgdW5sZXNzYCBoZWxwZXIgaXMgdGhlIGludmVyc2Ugb2YgdGhlIGBpZmAgaGVscGVyLiBJdCBkaXNwbGF5cyBpZiBhIHZhbHVlCiAgICBpcyBmYWxzZXkgKCJub3QgdHJ1ZSIgb3IgImlzIGZhbHNlIikuIEV4YW1wbGUgdmFsdWVzIHRoYXQgd2lsbCBkaXNwbGF5IHdpdGgKICAgIGB1bmxlc3NgOiBgZmFsc2VgLCBgdW5kZWZpbmVkYCwgYG51bGxgLCBgIiJgLCBgMGAsIGBOYU5gIG9yIGFuIGVtcHR5IGFycmF5LgogIAogICAgIyMgSW5saW5lIGZvcm0KICAKICAgIFRoZSBpbmxpbmUgYHVubGVzc2AgaGVscGVyIGNvbmRpdGlvbmFsbHkgcmVuZGVycyBhIHNpbmdsZSBwcm9wZXJ0eSBvciBzdHJpbmcuCiAgICBUaGlzIGhlbHBlciBhY3RzIGxpa2UgYSB0ZXJuYXJ5IG9wZXJhdG9yLiBJZiB0aGUgZmlyc3QgcHJvcGVydHkgaXMgZmFsc3ksCiAgICB0aGUgc2Vjb25kIGFyZ3VtZW50IHdpbGwgYmUgZGlzcGxheWVkLCBvdGhlcndpc2UsIHRoZSB0aGlyZCBhcmd1bWVudCB3aWxsIGJlCiAgICBkaXNwbGF5ZWQKICAKICAgIEZvciBleGFtcGxlLCBpZiBgdXNlTG9uZ0dyZWV0aW5nYCBpcyBmYWxzZSBiZWxvdzoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7dW5sZXNzIHVzZUxvbmdHcmVldGluZyAiSGkiICJIZWxsbyJ9fSBCZW4KICAgIGBgYAogIAogICAgVGhlbiBpdCB3aWxsIGRpc3BsYXk6CiAgCiAgICBgYGBodG1sCiAgICBIaQogICAgYGBgCiAgCiAgICBZb3UgY2FuIHVzZSB0aGUgYHVubGVzc2AgaGVscGVyIGluc2lkZSBhbm90aGVyIGhlbHBlciBhcyBhIHN1YmV4cHJlc3Npb24uCiAgICBJZiBpc0JpZyBpcyBub3QgdHJ1ZSwgaXQgd2lsbCBzZXQgdGhlIGhlaWdodCB0byAxMDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7ISBJZiBpc0JpZyBpcyBub3QgdHJ1ZSwgaXQgd2lsbCBzZXQgdGhlIGhlaWdodCB0byAxMC59fQogICAgPFNvbWVDb21wb25lbnQgQGhlaWdodD17e3VubGVzcyBpc0JpZyAiMTAiICIxMDAifX0gLz4KICAgIGBgYAogIAogICAgb3IKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7c29tZS1jb21wb25lbnQgaGVpZ2h0PSh1bmxlc3MgaXNCaWcgIjEwIiAiMTAwIil9fQogICAgYGBgCiAgCiAgICAjIyBCbG9jayBmb3JtCiAgCiAgICBMaWtlIHRoZSBgaWZgIGhlbHBlciwgYHVubGVzc2AgaGVscGVyIGFsc28gaGFzIGEgYmxvY2sgZm9ybS4KICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7ISBJZiBncmVldGluZ3MgYXJlIGZvdW5kLCB0aGUgdGV4dCBiZWxvdyB3aWxsIG5vdCByZW5kZXIufX0KICAgIHt7I3VubGVzcyBncmVldGluZ3N9fQogICAgICBObyBncmVldGluZ3Mgd2VyZSBmb3VuZC4gV2h5IG5vdCBzZXQgb25lPwogICAge3svdW5sZXNzfX0KICAgIGBgYAogIAogICAgWW91IGNhbiBhbHNvIHVzZSBhbiBgZWxzZWAgaGVscGVyIHdpdGggdGhlIGB1bmxlc3NgIGJsb2NrLiBUaGUKICAgIGBlbHNlYCB3aWxsIGRpc3BsYXkgaWYgdGhlIHZhbHVlIGlzIHRydXRoeS4KICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7ISBJcyB0aGUgdXNlciBsb2dnZWQgaW4/fX0KICAgIHt7I3VubGVzcyB1c2VyRGF0YX19CiAgICAgIFBsZWFzZSBsb2dpbi4KICAgIHt7ZWxzZX19CiAgICAgIFdlbGNvbWUgYmFjayEKICAgIHt7L3VubGVzc319CiAgICBgYGAKICAKICAgIElmIGB1c2VyRGF0YWAgaXMgZmFsc2UsIHVuZGVmaW5lZCwgbnVsbCwgb3IgZW1wdHkgaW4gdGhlIGFib3ZlIGV4YW1wbGUsCiAgICB0aGVuIGl0IHdpbGwgcmVuZGVyOgogIAogICAgYGBgaHRtbAogICAgUGxlYXNlIGxvZ2luLgogICAgYGBgCiAgCiAgICBAbWV0aG9kIHVubGVzcwogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpbmxpbmVVbmxlc3MoX3ZtLCBfcmVmMzApIHsKICAgIHZhciBwb3NpdGlvbmFsID0gX3JlZjMwLnBvc2l0aW9uYWw7CiAgICAoZmFsc2UgJiYgIShwb3NpdGlvbmFsLmxlbmd0aCA9PT0gMyB8fCBwb3NpdGlvbmFsLmxlbmd0aCA9PT0gMikgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgaW5saW5lIGZvcm0gb2YgdGhlIGB1bmxlc3NgIGhlbHBlciBleHBlY3RzIHR3byBvciB0aHJlZSBhcmd1bWVudHMsIGUuZy4gJyArICdge3t1bmxlc3MgaXNGaXJzdExvZ2luICJXZWxjb21lIGJhY2shIn19YC4nLCBwb3NpdGlvbmFsLmxlbmd0aCA9PT0gMyB8fCBwb3NpdGlvbmFsLmxlbmd0aCA9PT0gMikpOwogICAgcmV0dXJuIENvbmRpdGlvbmFsSGVscGVyUmVmZXJlbmNlLmNyZWF0ZShwb3NpdGlvbmFsLmF0KDApLCBwb3NpdGlvbmFsLmF0KDIpLCBwb3NpdGlvbmFsLmF0KDEpKTsKICB9CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgYGxvZ2AgYWxsb3dzIHlvdSB0byBvdXRwdXQgdGhlIHZhbHVlIG9mIHZhcmlhYmxlcyBpbiB0aGUgY3VycmVudCByZW5kZXJpbmcKICAgIGNvbnRleHQuIGBsb2dgIGFsc28gYWNjZXB0cyBwcmltaXRpdmUgdHlwZXMgc3VjaCBhcyBzdHJpbmdzIG9yIG51bWJlcnMuCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e2xvZyAibXlWYXJpYWJsZToiIG15VmFyaWFibGUgfX0KICAgIGBgYAogIAogICAgQG1ldGhvZCBsb2cKICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwYXJhbSB7QXJyYXl9IHBhcmFtcwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBsb2coX3JlZjMxKSB7CiAgICB2YXIgX2NvbnNvbGU7CgogICAgdmFyIHBvc2l0aW9uYWwgPSBfcmVmMzEucG9zaXRpb25hbDsKCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovCiAgICAoX2NvbnNvbGUgPSBjb25zb2xlKS5sb2cuYXBwbHkoX2NvbnNvbGUsIHBvc2l0aW9uYWwudmFsdWUoKSk7CiAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWNvbnNvbGUgKi8KCiAgfQoKICBmdW5jdGlvbiBsb2ckMShfdm0sIGFyZ3MpIHsKICAgIHJldHVybiBuZXcgSW50ZXJuYWxIZWxwZXJSZWZlcmVuY2UobG9nLCBhcmdzLmNhcHR1cmUoKSk7CiAgfQogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIFRoZSBgbXV0YCBoZWxwZXIgbGV0cyB5b3UgX19jbGVhcmx5IHNwZWNpZnlfXyB0aGF0IGEgY2hpbGQgYENvbXBvbmVudGAgY2FuIHVwZGF0ZSB0aGUKICAgIChtdXRhYmxlKSB2YWx1ZSBwYXNzZWQgdG8gaXQsIHdoaWNoIHdpbGwgX19jaGFuZ2UgdGhlIHZhbHVlIG9mIHRoZSBwYXJlbnQgY29tcG9uZW50X18uCiAgCiAgICBUbyBzcGVjaWZ5IHRoYXQgYSBwYXJhbWV0ZXIgaXMgbXV0YWJsZSwgd2hlbiBpbnZva2luZyB0aGUgY2hpbGQgYENvbXBvbmVudGA6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8TXlDaGlsZCBAY2hpbGRDbGlja0NvdW50PXt7Zm4gKG11dCB0b3RhbENsaWNrcyl9fSAvPgogICAgYGBgCiAgCiAgICAgb3IKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7bXktY2hpbGQgY2hpbGRDbGlja0NvdW50PShtdXQgdG90YWxDbGlja3MpfX0KICAgIGBgYAogIAogICAgVGhlIGNoaWxkIGBDb21wb25lbnRgIGNhbiB0aGVuIG1vZGlmeSB0aGUgcGFyZW50J3MgdmFsdWUganVzdCBieSBtb2RpZnlpbmcgaXRzIG93bgogICAgcHJvcGVydHk6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICAvLyBteS1jaGlsZC5qcwogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGNsaWNrKCkgewogICAgICAgIHRoaXMuaW5jcmVtZW50UHJvcGVydHkoJ2NoaWxkQ2xpY2tDb3VudCcpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgTm90ZSB0aGF0IGZvciBjdXJseSBjb21wb25lbnRzIChge3tteS1jb21wb25lbnR9fWApIHRoZSBiaW5kaW5ncyBhcmUgYWxyZWFkeSBtdXRhYmxlLAogICAgbWFraW5nIHRoZSBgbXV0YCB1bm5lY2Vzc2FyeS4KICAKICAgIEFkZGl0aW9uYWxseSwgdGhlIGBtdXRgIGhlbHBlciBjYW4gYmUgY29tYmluZWQgd2l0aCB0aGUgYGZuYCBoZWxwZXIgdG8KICAgIG11dGF0ZSBhIHZhbHVlLiBGb3IgZXhhbXBsZToKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxNeUNoaWxkIEBjaGlsZENsaWNrQ291bnQ9e3t0aGlzLnRvdGFsQ2xpY2tzfX0gQGNsaWNrLWNvdW50LWNoYW5nZT17e2ZuIChtdXQgdG90YWxDbGlja3MpKX19IC8+CiAgICBgYGAKICAKICAgIG9yCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e215LWNoaWxkIGNoaWxkQ2xpY2tDb3VudD10b3RhbENsaWNrcyBjbGljay1jb3VudC1jaGFuZ2U9KGZuIChtdXQgdG90YWxDbGlja3MpKX19CiAgICBgYGAKICAKICAgIFRoZSBjaGlsZCBgQ29tcG9uZW50YCB3b3VsZCBpbnZva2UgdGhlIGZ1bmN0aW9uIHdpdGggdGhlIG5ldyBjbGljayB2YWx1ZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIC8vIG15LWNoaWxkLmpzCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgY2xpY2soKSB7CiAgICAgICAgdGhpcy5nZXQoJ2NsaWNrLWNvdW50LWNoYW5nZScpKHRoaXMuZ2V0KCdjaGlsZENsaWNrQ291bnQnKSArIDEpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgVGhlIGBtdXRgIGhlbHBlciBjaGFuZ2VzIHRoZSBgdG90YWxDbGlja3NgIHZhbHVlIHRvIHdoYXQgd2FzIHByb3ZpZGVkIGFzIHRoZSBgZm5gIGFyZ3VtZW50LgogIAogICAgVGhlIGBtdXRgIGhlbHBlciwgd2hlbiB1c2VkIHdpdGggYGZuYCwgd2lsbCByZXR1cm4gYSBmdW5jdGlvbiB0aGF0CiAgICBzZXRzIHRoZSB2YWx1ZSBwYXNzZWQgdG8gYG11dGAgdG8gaXRzIGZpcnN0IGFyZ3VtZW50LiBBcyBhbiBleGFtcGxlLCB3ZSBjYW4gY3JlYXRlIGEKICAgIGJ1dHRvbiB0aGF0IGluY3JlbWVudHMgYSB2YWx1ZSBwYXNzaW5nIHRoZSB2YWx1ZSBkaXJlY3RseSB0byB0aGUgYGZuYDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7ISBpbmMgaGVscGVyIGlzIG5vdCBwcm92aWRlZCBieSBFbWJlciB9fQogICAgPGJ1dHRvbiBvbmNsaWNrPXt7Zm4gKG11dCBjb3VudCkgKGluYyBjb3VudCl9fT4KICAgICAgSW5jcmVtZW50IGNvdW50CiAgICA8L2J1dHRvbj4KICAgIGBgYAogIAogICAgWW91IGNhbiBhbHNvIHVzZSB0aGUgYHZhbHVlYCBvcHRpb246CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8aW5wdXQgdmFsdWU9e3tuYW1lfX0gb25pbnB1dD17e2ZuIChtdXQgbmFtZSkgdmFsdWU9InRhcmdldC52YWx1ZSJ9fT4KICAgIGBgYAogIAogICAgQG1ldGhvZCBtdXQKICAgIEBwYXJhbSB7T2JqZWN0fSBbYXR0cl0gdGhlICJ0d28td2F5IiBhdHRyaWJ1dGUgdGhhdCBjYW4gYmUgbW9kaWZpZWQuCiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAcHVibGljCiAgKi8KCgogIHZhciBNVVRfUkVGRVJFTkNFID0gKDAsIF91dGlscy5zeW1ib2wpKCdNVVQnKTsKICB2YXIgU09VUkNFID0gKDAsIF91dGlscy5zeW1ib2wpKCdTT1VSQ0UnKTsKCiAgZnVuY3Rpb24gaXNNdXQocmVmKSB7CiAgICByZXR1cm4gcmVmICYmIHJlZltNVVRfUkVGRVJFTkNFXTsKICB9CgogIGZ1bmN0aW9uIHVuTXV0KHJlZikgewogICAgcmV0dXJuIHJlZltTT1VSQ0VdIHx8IHJlZjsKICB9CgogIGZ1bmN0aW9uIG11dChfdm0sIGFyZ3MpIHsKICAgIHZhciByYXdSZWYgPSBhcmdzLnBvc2l0aW9uYWwuYXQoMCk7CgogICAgaWYgKGlzTXV0KHJhd1JlZikpIHsKICAgICAgcmV0dXJuIHJhd1JlZjsKICAgIH0gLy8gVE9ETzogSW1wcm92ZSB0aGlzIGVycm9yIG1lc3NhZ2UuIFRoaXMgY292ZXJzIGF0IGxlYXN0IHR3byBkaXN0aW5jdAogICAgLy8gY2FzZXM6CiAgICAvLwogICAgLy8gMS4gKG11dCAibm90IGEgcGF0aCIpIOKAkyBwYXNzaW5nIGEgbGl0ZXJhbCwgcmVzdWx0IGZyb20gYSBoZWxwZXIKICAgIC8vICAgIGludm9jYXRpb24sIGV0YwogICAgLy8KICAgIC8vIDIuIChtdXQgcmVjZWl2ZWRWYWx1ZSkg4oCTIHBhc3NpbmcgYSB2YWx1ZSByZWNlaXZlZCBmcm9tIHRoZSBjYWxsZXIKICAgIC8vICAgIHRoYXQgd2FzIG9yaWdpbmFsbHkgZGVyaXZlZCBmcm9tIGEgbGl0ZXJhbCwgcmVzdWx0IGZyb20gYSBoZWxwZXIKICAgIC8vICAgIGludm9jYXRpb24sIGV0YwogICAgLy8KICAgIC8vIFRoaXMgbWVzc2FnZSBpcyBhbHJpZ2h0IGZvciB0aGUgZmlyc3QgY2FzZSwgYnV0IGNvdWxkIGJlIHF1aXRlCiAgICAvLyBjb25mdXNpbmcgZm9yIHRoZSBzZWNvbmQgY2FzZS4KCgogICAgKGZhbHNlICYmICEocmF3UmVmW1VQREFURV0pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGNhbiBvbmx5IHBhc3MgYSBwYXRoIHRvIG11dCcsIHJhd1JlZltVUERBVEVdKSk7CiAgICB2YXIgd3JhcHBlZFJlZiA9IE9iamVjdC5jcmVhdGUocmF3UmVmKTsKICAgIHdyYXBwZWRSZWZbU09VUkNFXSA9IHJhd1JlZjsKICAgIHdyYXBwZWRSZWZbSU5WT0tFXSA9IHJhd1JlZltVUERBVEVdOwogICAgd3JhcHBlZFJlZltNVVRfUkVGRVJFTkNFXSA9IHRydWU7CiAgICByZXR1cm4gd3JhcHBlZFJlZjsKICB9CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgVGhpcyBpcyBhIGhlbHBlciB0byBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggdGhlIGxpbmstdG8gaGVscGVyLgogICAgSXQgd2lsbCBzdXBwbHkgdXJsIHF1ZXJ5IHBhcmFtZXRlcnMgdG8gdGhlIHRhcmdldCByb3V0ZS4KICAKICAgIEV4YW1wbGUKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7I2xpbmstdG8gJ3Bvc3RzJyAocXVlcnktcGFyYW1zIGRpcmVjdGlvbj0iYXNjIil9fVNvcnR7ey9saW5rLXRvfX0KICAgIGBgYAogIAogICAgQG1ldGhvZCBxdWVyeS1wYXJhbXMKICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwYXJhbSB7T2JqZWN0fSBoYXNoIHRha2VzIGEgaGFzaCBvZiBxdWVyeSBwYXJhbWV0ZXJzCiAgICBAcmV0dXJuIHtPYmplY3R9IEEgYFF1ZXJ5UGFyYW1zYCBvYmplY3QgZm9yIGB7e2xpbmstdG99fWAKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gcXVlcnlQYXJhbXMoX3JlZjMyKSB7CiAgICB2YXIgcG9zaXRpb25hbCA9IF9yZWYzMi5wb3NpdGlvbmFsLAogICAgICAgIG5hbWVkID0gX3JlZjMyLm5hbWVkOwogICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aAogICAgKGZhbHNlICYmICEocG9zaXRpb25hbC52YWx1ZSgpLmxlbmd0aCA9PT0gMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgYHF1ZXJ5LXBhcmFtc2AgaGVscGVyIG9ubHkgYWNjZXB0cyBoYXNoIHBhcmFtZXRlcnMsIGUuZy4gKHF1ZXJ5LXBhcmFtcyBxdWVyeVBhcmFtUHJvcGVydHlOYW1lPSdmb28nKSBhcyBvcHBvc2VkIHRvIGp1c3QgKHF1ZXJ5LXBhcmFtcyAnZm9vJykiLCBwb3NpdGlvbmFsLnZhbHVlKCkubGVuZ3RoID09PSAwKSk7CiAgICByZXR1cm4gbmV3IF9yb3V0aW5nLlF1ZXJ5UGFyYW1zKCgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIG5hbWVkLnZhbHVlKCkpKTsKICB9CgogIGZ1bmN0aW9uIHF1ZXJ5UGFyYW1zJDEoX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gbmV3IEludGVybmFsSGVscGVyUmVmZXJlbmNlKHF1ZXJ5UGFyYW1zLCBhcmdzLmNhcHR1cmUoKSk7CiAgfQogIC8qKgogICAgVGhlIGByZWFkb25seWAgaGVscGVyIGxldCdzIHlvdSBzcGVjaWZ5IHRoYXQgYSBiaW5kaW5nIGlzIG9uZS13YXkgb25seSwKICAgIGluc3RlYWQgb2YgdHdvLXdheS4KICAgIFdoZW4geW91IHBhc3MgYSBgcmVhZG9ubHlgIGJpbmRpbmcgZnJvbSBhbiBvdXRlciBjb250ZXh0IChlLmcuIHBhcmVudCBjb21wb25lbnQpLAogICAgdG8gdG8gYW4gaW5uZXIgY29udGV4dCAoZS5nLiBjaGlsZCBjb21wb25lbnQpLCB5b3UgYXJlIHNheWluZyB0aGF0IGNoYW5naW5nIHRoYXQKICAgIHByb3BlcnR5IGluIHRoZSBpbm5lciBjb250ZXh0IGRvZXMgbm90IGNoYW5nZSB0aGUgdmFsdWUgaW4gdGhlIG91dGVyIGNvbnRleHQuCiAgCiAgICBUbyBzcGVjaWZ5IHRoYXQgYSBiaW5kaW5nIGlzIHJlYWQtb25seSwgd2hlbiBpbnZva2luZyB0aGUgY2hpbGQgYENvbXBvbmVudGA6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1wYXJlbnQuanMKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICB0b3RhbENsaWNrczogMwogICAgfSk7CiAgICBgYGAKICAKICAgIGBgYGFwcC90ZW1wbGF0ZXMvY29tcG9uZW50cy9teS1wYXJlbnQuaGJzCiAgICB7e2xvZyB0b3RhbENsaWNrc319IC8vIC0+IDMKICAgIDxNeUNoaWxkIEBjaGlsZENsaWNrQ291bnQ9e3tyZWFkb25seSB0b3RhbENsaWNrc319IC8+CiAgICBgYGAKICAgIGBgYAogICAge3tteS1jaGlsZCBjaGlsZENsaWNrQ291bnQ9KHJlYWRvbmx5IHRvdGFsQ2xpY2tzKX19CiAgICBgYGAKICAKICAgIE5vdywgd2hlbiB5b3UgdXBkYXRlIGBjaGlsZENsaWNrQ291bnRgOgogIAogICAgYGBgYXBwL2NvbXBvbmVudHMvbXktY2hpbGQuanMKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGljaygpIHsKICAgICAgICB0aGlzLmluY3JlbWVudFByb3BlcnR5KCdjaGlsZENsaWNrQ291bnQnKTsKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIFRoZSB2YWx1ZSB1cGRhdGVzIGluIHRoZSBjaGlsZCBjb21wb25lbnQsIGJ1dCBub3QgdGhlIHBhcmVudCBjb21wb25lbnQ6CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvbXktY2hpbGQuaGJzCiAgICB7e2xvZyBjaGlsZENsaWNrQ291bnR9fSAvLy0+IDQKICAgIGBgYAogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL215LXBhcmVudC5oYnMKICAgIHt7bG9nIHRvdGFsQ2xpY2tzfX0gLy8tPiAzCiAgICA8TXlDaGlsZCBAY2hpbGRDbGlja0NvdW50PXt7cmVhZG9ubHkgdG90YWxDbGlja3N9fSAvPgogICAgYGBgCiAgICBvcgogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL215LXBhcmVudC5oYnMKICAgIHt7bG9nIHRvdGFsQ2xpY2tzfX0gLy8tPiAzCiAgICB7e215LWNoaWxkIGNoaWxkQ2xpY2tDb3VudD0ocmVhZG9ubHkgdG90YWxDbGlja3MpfX0KICAgIGBgYAogIAogICAgIyMjIE9iamVjdHMgYW5kIEFycmF5cwogIAogICAgV2hlbiBwYXNzaW5nIGEgcHJvcGVydHkgdGhhdCBpcyBhIGNvbXBsZXggb2JqZWN0IChlLmcuIG9iamVjdCwgYXJyYXkpIGluc3RlYWQgb2YgYSBwcmltaXRpdmUgb2JqZWN0IChlLmcuIG51bWJlciwgc3RyaW5nKSwKICAgIG9ubHkgdGhlIHJlZmVyZW5jZSB0byB0aGUgb2JqZWN0IGlzIHByb3RlY3RlZCB1c2luZyB0aGUgcmVhZG9ubHkgaGVscGVyLgogICAgVGhpcyBtZWFucyB0aGF0IHlvdSBjYW4gY2hhbmdlIHByb3BlcnRpZXMgb2YgdGhlIG9iamVjdCBib3RoIG9uIHRoZSBwYXJlbnQgY29tcG9uZW50LCBhcyB3ZWxsIGFzIHRoZSBjaGlsZCBjb21wb25lbnQuCiAgICBUaGUgYHJlYWRvbmx5YCBiaW5kaW5nIGJlaGF2ZXMgc2ltaWxhciB0byB0aGUgYGNvbnN0YCBrZXl3b3JkIGluIEphdmFTY3JpcHQuCiAgCiAgICBMZXQncyBsb29rIGF0IGFuIGV4YW1wbGU6CiAgCiAgICBGaXJzdCBsZXQncyBzZXQgdXAgdGhlIHBhcmVudCBjb21wb25lbnQ6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1wYXJlbnQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgY2xpY2tzOiBudWxsLAogIAogICAgICBpbml0KCkgewogICAgICAgIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cyk7CiAgICAgICAgdGhpcy5zZXQoJ2NsaWNrcycsIHsgdG90YWw6IDMgfSk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvbXktcGFyZW50LmhicwogICAge3tsb2cgY2xpY2tzLnRvdGFsfX0gLy8tPiAzCiAgICA8TXlDaGlsZCBAY2hpbGRDbGlja3M9e3tyZWFkb25seSBjbGlja3N9fSAvPgogICAgYGBgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvbXktcGFyZW50LmhicwogICAge3tsb2cgY2xpY2tzLnRvdGFsfX0gLy8tPiAzCiAgICB7e215LWNoaWxkIGNoaWxkQ2xpY2tzPShyZWFkb25seSBjbGlja3MpfX0KICAgIGBgYAogIAogICAgTm93LCBpZiB5b3UgdXBkYXRlIHRoZSBgdG90YWxgIHByb3BlcnR5IG9mIGBjaGlsZENsaWNrc2A6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jaGlsZC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGljaygpIHsKICAgICAgICB0aGlzLmdldCgnY2xpY2tzJykuaW5jcmVtZW50UHJvcGVydHkoJ3RvdGFsJyk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBZb3Ugd2lsbCBzZWUgdGhlIGZvbGxvd2luZyBoYXBwZW46CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvbXktcGFyZW50LmhicwogICAge3tsb2cgY2xpY2tzLnRvdGFsfX0gLy8tPiA0CiAgICA8TXlDaGlsZCBAY2hpbGRDbGlja3M9e3tyZWFkb25seSBjbGlja3N9fSAvPgogICAgYGBgCiAgICBvcgogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL215LXBhcmVudC5oYnMKICAgIHt7bG9nIGNsaWNrcy50b3RhbH19IC8vLT4gNAogICAge3tteS1jaGlsZCBjaGlsZENsaWNrcz0ocmVhZG9ubHkgY2xpY2tzKX19CiAgICBgYGAKICAKICAgIGBgYGFwcC90ZW1wbGF0ZXMvY29tcG9uZW50cy9teS1jaGlsZC5oYnMKICAgIHt7bG9nIGNoaWxkQ2xpY2tzLnRvdGFsfX0gLy8tPiA0CiAgICBgYGAKICAKICAgIEBtZXRob2QgcmVhZG9ubHkKICAgIEBwYXJhbSB7T2JqZWN0fSBbYXR0cl0gdGhlIHJlYWQtb25seSBhdHRyaWJ1dGUuCiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAcHJpdmF0ZQogICovCgoKICBmdW5jdGlvbiByZWFkb25seShfdm0sIGFyZ3MpIHsKICAgIHZhciByZWYgPSB1bk11dChhcmdzLnBvc2l0aW9uYWwuYXQoMCkpOwogICAgcmV0dXJuIG5ldyBSZWFkb25seVJlZmVyZW5jZShyZWYpOwogIH0KICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBUaGUgYHt7dW5ib3VuZH19YCBoZWxwZXIgZGlzY29ubmVjdHMgdGhlIG9uZS13YXkgYmluZGluZyBvZiBhIHByb3BlcnR5LAogICAgZXNzZW50aWFsbHkgZnJlZXppbmcgaXRzIHZhbHVlIGF0IHRoZSBtb21lbnQgb2YgcmVuZGVyaW5nLiBGb3IgZXhhbXBsZSwKICAgIGluIHRoaXMgZXhhbXBsZSB0aGUgZGlzcGxheSBvZiB0aGUgdmFyaWFibGUgYG5hbWVgIHdpbGwgbm90IGNoYW5nZSBldmVuCiAgICBpZiBpdCBpcyBzZXQgd2l0aCBhIG5ldyB2YWx1ZToKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7dW5ib3VuZCBuYW1lfX0KICAgIGBgYAogIAogICAgTGlrZSBhbnkgaGVscGVyLCB0aGUgYHVuYm91bmRgIGhlbHBlciBjYW4gYWNjZXB0IGEgbmVzdGVkIGhlbHBlciBleHByZXNzaW9uLgogICAgVGhpcyBhbGxvd3MgZm9yIGN1c3RvbSBoZWxwZXJzIHRvIGJlIHJlbmRlcmVkIHVuYm91bmQ6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e3VuYm91bmQgKHNvbWUtY3VzdG9tLWhlbHBlcil9fQogICAge3t1bmJvdW5kIChjYXBpdGFsaXplIG5hbWUpfX0KICAgIHt7ISBZb3UgY2FuIHVzZSBhbnkgaGVscGVyLCBpbmNsdWRpbmcgdW5ib3VuZCwgaW4gYSBuZXN0ZWQgZXhwcmVzc2lvbiB9fQogICAge3tjYXBpdGFsaXplICh1bmJvdW5kIG5hbWUpfX0KICAgIGBgYAogIAogICAgVGhlIGB1bmJvdW5kYCBoZWxwZXIgb25seSBhY2NlcHRzIGEgc2luZ2xlIGFyZ3VtZW50LCBhbmQgaXQgcmV0dXJuIGFuCiAgICB1bmJvdW5kIHZhbHVlLgogIAogICAgQG1ldGhvZCB1bmJvdW5kCiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIHVuYm91bmQoX3ZtLCBhcmdzKSB7CiAgICAoZmFsc2UgJiYgIShhcmdzLnBvc2l0aW9uYWwubGVuZ3RoID09PSAxICYmIGFyZ3MubmFtZWQubGVuZ3RoID09PSAwKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ3VuYm91bmQgaGVscGVyIGNhbm5vdCBiZSBjYWxsZWQgd2l0aCBtdWx0aXBsZSBwYXJhbXMgb3IgaGFzaCBwYXJhbXMnLCBhcmdzLnBvc2l0aW9uYWwubGVuZ3RoID09PSAxICYmIGFyZ3MubmFtZWQubGVuZ3RoID09PSAwKSk7CiAgICByZXR1cm4gVW5ib3VuZFJlZmVyZW5jZS5jcmVhdGUoYXJncy5wb3NpdGlvbmFsLmF0KDApLnZhbHVlKCkpOwogIH0KCiAgdmFyIE1PRElGSUVSUyA9IFsnYWx0JywgJ3NoaWZ0JywgJ21ldGEnLCAnY3RybCddOwogIHZhciBQT0lOVEVSX0VWRU5UX1RZUEVfUkVHRVggPSAvXmNsaWNrfG1vdXNlfHRvdWNoLzsKCiAgZnVuY3Rpb24gaXNBbGxvd2VkRXZlbnQoZXZlbnQsIGFsbG93ZWRLZXlzKSB7CiAgICBpZiAoYWxsb3dlZEtleXMgPT09IG51bGwgfHwgYWxsb3dlZEtleXMgPT09IHVuZGVmaW5lZCkgewogICAgICBpZiAoUE9JTlRFUl9FVkVOVF9UWVBFX1JFR0VYLnRlc3QoZXZlbnQudHlwZSkpIHsKICAgICAgICByZXR1cm4gKDAsIF92aWV3cy5pc1NpbXBsZUNsaWNrKShldmVudCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYWxsb3dlZEtleXMgPSAnJzsKICAgICAgfQogICAgfQoKICAgIGlmIChhbGxvd2VkS2V5cy5pbmRleE9mKCdhbnknKSA+PSAwKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgTU9ESUZJRVJTLmxlbmd0aDsgaSsrKSB7CiAgICAgIGlmIChldmVudFtNT0RJRklFUlNbaV0gKyAnS2V5J10gJiYgYWxsb3dlZEtleXMuaW5kZXhPZihNT0RJRklFUlNbaV0pID09PSAtMSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiB0cnVlOwogIH0KCiAgdmFyIEFjdGlvbkhlbHBlciA9IHsKICAgIC8vIHJlZ2lzdGVyZWRBY3Rpb25zIGlzIHJlLWV4cG9ydGVkIGZvciBjb21wYXRpYmlsaXR5IHdpdGggb2xkZXIgcGx1Z2lucwogICAgLy8gdGhhdCB3ZXJlIHVzaW5nIHRoaXMgdW5kb2N1bWVudGVkIEFQSS4KICAgIHJlZ2lzdGVyZWRBY3Rpb25zOiBfdmlld3MuQWN0aW9uTWFuYWdlci5yZWdpc3RlcmVkQWN0aW9ucywKICAgIHJlZ2lzdGVyQWN0aW9uOiBmdW5jdGlvbiByZWdpc3RlckFjdGlvbihhY3Rpb25TdGF0ZSkgewogICAgICB2YXIgYWN0aW9uSWQgPSBhY3Rpb25TdGF0ZS5hY3Rpb25JZDsKICAgICAgX3ZpZXdzLkFjdGlvbk1hbmFnZXIucmVnaXN0ZXJlZEFjdGlvbnNbYWN0aW9uSWRdID0gYWN0aW9uU3RhdGU7CiAgICAgIHJldHVybiBhY3Rpb25JZDsKICAgIH0sCiAgICB1bnJlZ2lzdGVyQWN0aW9uOiBmdW5jdGlvbiB1bnJlZ2lzdGVyQWN0aW9uKGFjdGlvblN0YXRlKSB7CiAgICAgIHZhciBhY3Rpb25JZCA9IGFjdGlvblN0YXRlLmFjdGlvbklkOwogICAgICBkZWxldGUgX3ZpZXdzLkFjdGlvbk1hbmFnZXIucmVnaXN0ZXJlZEFjdGlvbnNbYWN0aW9uSWRdOwogICAgfQogIH07CgogIHZhciBBY3Rpb25TdGF0ZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEFjdGlvblN0YXRlKGVsZW1lbnQsIGFjdGlvbklkLCBhY3Rpb25OYW1lLCBhY3Rpb25BcmdzLCBuYW1lZEFyZ3MsIHBvc2l0aW9uYWxBcmdzLCBpbXBsaWNpdFRhcmdldCwgZG9tLCB0YWcpIHsKICAgICAgdGhpcy5lbGVtZW50ID0gZWxlbWVudDsKICAgICAgdGhpcy5hY3Rpb25JZCA9IGFjdGlvbklkOwogICAgICB0aGlzLmFjdGlvbk5hbWUgPSBhY3Rpb25OYW1lOwogICAgICB0aGlzLmFjdGlvbkFyZ3MgPSBhY3Rpb25BcmdzOwogICAgICB0aGlzLm5hbWVkQXJncyA9IG5hbWVkQXJnczsKICAgICAgdGhpcy5wb3NpdGlvbmFsID0gcG9zaXRpb25hbEFyZ3M7CiAgICAgIHRoaXMuaW1wbGljaXRUYXJnZXQgPSBpbXBsaWNpdFRhcmdldDsKICAgICAgdGhpcy5kb20gPSBkb207CiAgICAgIHRoaXMuZXZlbnROYW1lID0gdGhpcy5nZXRFdmVudE5hbWUoKTsKICAgICAgdGhpcy50YWcgPSB0YWc7CiAgICB9CgogICAgdmFyIF9wcm90bzU1ID0gQWN0aW9uU3RhdGUucHJvdG90eXBlOwoKICAgIF9wcm90bzU1LmdldEV2ZW50TmFtZSA9IGZ1bmN0aW9uIGdldEV2ZW50TmFtZSgpIHsKICAgICAgcmV0dXJuIHRoaXMubmFtZWRBcmdzLmdldCgnb24nKS52YWx1ZSgpIHx8ICdjbGljayc7CiAgICB9OwoKICAgIF9wcm90bzU1LmdldEFjdGlvbkFyZ3MgPSBmdW5jdGlvbiBnZXRBY3Rpb25BcmdzKCkgewogICAgICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KHRoaXMuYWN0aW9uQXJncy5sZW5ndGgpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmFjdGlvbkFyZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICByZXN1bHRbaV0gPSB0aGlzLmFjdGlvbkFyZ3NbaV0udmFsdWUoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH07CgogICAgX3Byb3RvNTUuZ2V0VGFyZ2V0ID0gZnVuY3Rpb24gZ2V0VGFyZ2V0KCkgewogICAgICB2YXIgaW1wbGljaXRUYXJnZXQgPSB0aGlzLmltcGxpY2l0VGFyZ2V0LAogICAgICAgICAgbmFtZWRBcmdzID0gdGhpcy5uYW1lZEFyZ3M7CiAgICAgIHZhciB0YXJnZXQ7CgogICAgICBpZiAobmFtZWRBcmdzLmhhcygndGFyZ2V0JykpIHsKICAgICAgICB0YXJnZXQgPSBuYW1lZEFyZ3MuZ2V0KCd0YXJnZXQnKS52YWx1ZSgpOwogICAgICB9IGVsc2UgewogICAgICAgIHRhcmdldCA9IGltcGxpY2l0VGFyZ2V0LnZhbHVlKCk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0YXJnZXQ7CiAgICB9OwoKICAgIF9wcm90bzU1LmhhbmRsZXIgPSBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50KSB7CiAgICAgIHZhciBfdGhpczI0ID0gdGhpczsKCiAgICAgIHZhciBhY3Rpb25OYW1lID0gdGhpcy5hY3Rpb25OYW1lLAogICAgICAgICAgbmFtZWRBcmdzID0gdGhpcy5uYW1lZEFyZ3M7CiAgICAgIHZhciBidWJibGVzID0gbmFtZWRBcmdzLmdldCgnYnViYmxlcycpOwogICAgICB2YXIgcHJldmVudERlZmF1bHQgPSBuYW1lZEFyZ3MuZ2V0KCdwcmV2ZW50RGVmYXVsdCcpOwogICAgICB2YXIgYWxsb3dlZEtleXMgPSBuYW1lZEFyZ3MuZ2V0KCdhbGxvd2VkS2V5cycpOwogICAgICB2YXIgdGFyZ2V0ID0gdGhpcy5nZXRUYXJnZXQoKTsKICAgICAgdmFyIHNob3VsZEJ1YmJsZSA9IGJ1YmJsZXMudmFsdWUoKSAhPT0gZmFsc2U7CgogICAgICBpZiAoIWlzQWxsb3dlZEV2ZW50KGV2ZW50LCBhbGxvd2VkS2V5cy52YWx1ZSgpKSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBpZiAocHJldmVudERlZmF1bHQudmFsdWUoKSAhPT0gZmFsc2UpIHsKICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOwogICAgICB9CgogICAgICBpZiAoIXNob3VsZEJ1YmJsZSkgewogICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOwogICAgICB9CgogICAgICAoMCwgX3J1bmxvb3Auam9pbikoZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBhcmdzID0gX3RoaXMyNC5nZXRBY3Rpb25BcmdzKCk7CgogICAgICAgIHZhciBwYXlsb2FkID0gewogICAgICAgICAgYXJnczogYXJncywKICAgICAgICAgIHRhcmdldDogdGFyZ2V0LAogICAgICAgICAgbmFtZTogbnVsbAogICAgICAgIH07CgogICAgICAgIGlmICh0eXBlb2YgYWN0aW9uTmFtZVtJTlZPS0VdID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICAoMCwgX2luc3RydW1lbnRhdGlvbi5mbGFnZ2VkSW5zdHJ1bWVudCkoJ2ludGVyYWN0aW9uLmVtYmVyLWFjdGlvbicsIHBheWxvYWQsIGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgYWN0aW9uTmFtZVtJTlZPS0VdLmFwcGx5KGFjdGlvbk5hbWUsIGFyZ3MpOwogICAgICAgICAgfSk7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAodHlwZW9mIGFjdGlvbk5hbWUgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgICgwLCBfaW5zdHJ1bWVudGF0aW9uLmZsYWdnZWRJbnN0cnVtZW50KSgnaW50ZXJhY3Rpb24uZW1iZXItYWN0aW9uJywgcGF5bG9hZCwgZnVuY3Rpb24gKCkgewogICAgICAgICAgICBhY3Rpb25OYW1lLmFwcGx5KHRhcmdldCwgYXJncyk7CiAgICAgICAgICB9KTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHBheWxvYWQubmFtZSA9IGFjdGlvbk5hbWU7CgogICAgICAgIGlmICh0YXJnZXQuc2VuZCkgewogICAgICAgICAgKDAsIF9pbnN0cnVtZW50YXRpb24uZmxhZ2dlZEluc3RydW1lbnQpKCdpbnRlcmFjdGlvbi5lbWJlci1hY3Rpb24nLCBwYXlsb2FkLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIHRhcmdldC5zZW5kLmFwcGx5KHRhcmdldCwgW2FjdGlvbk5hbWVdLmNvbmNhdChhcmdzKSk7CiAgICAgICAgICB9KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgKGZhbHNlICYmICEodHlwZW9mIHRhcmdldFthY3Rpb25OYW1lXSA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgYWN0aW9uICciICsgYWN0aW9uTmFtZSArICInIGRpZCBub3QgZXhpc3Qgb24gIiArIHRhcmdldCwgdHlwZW9mIHRhcmdldFthY3Rpb25OYW1lXSA9PT0gJ2Z1bmN0aW9uJykpOwogICAgICAgICAgKDAsIF9pbnN0cnVtZW50YXRpb24uZmxhZ2dlZEluc3RydW1lbnQpKCdpbnRlcmFjdGlvbi5lbWJlci1hY3Rpb24nLCBwYXlsb2FkLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIHRhcmdldFthY3Rpb25OYW1lXS5hcHBseSh0YXJnZXQsIGFyZ3MpOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIHNob3VsZEJ1YmJsZTsKICAgIH07CgogICAgX3Byb3RvNTUuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIEFjdGlvbkhlbHBlci51bnJlZ2lzdGVyQWN0aW9uKHRoaXMpOwogICAgfTsKCiAgICByZXR1cm4gQWN0aW9uU3RhdGU7CiAgfSgpOyAvLyBpbXBsZW1lbnRzIE1vZGlmaWVyTWFuYWdlcjxBY3Rpb24+CgoKICB2YXIgQWN0aW9uTW9kaWZpZXJNYW5hZ2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQWN0aW9uTW9kaWZpZXJNYW5hZ2VyKCkge30KCiAgICB2YXIgX3Byb3RvNTYgPSBBY3Rpb25Nb2RpZmllck1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzU2LmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShlbGVtZW50LCBfc3RhdGUsIGFyZ3MsIF9keW5hbWljU2NvcGUsIGRvbSkgewogICAgICB2YXIgX2FyZ3MkY2FwdHVyZSA9IGFyZ3MuY2FwdHVyZSgpLAogICAgICAgICAgbmFtZWQgPSBfYXJncyRjYXB0dXJlLm5hbWVkLAogICAgICAgICAgcG9zaXRpb25hbCA9IF9hcmdzJGNhcHR1cmUucG9zaXRpb25hbCwKICAgICAgICAgIHRhZyA9IF9hcmdzJGNhcHR1cmUudGFnOwoKICAgICAgdmFyIGltcGxpY2l0VGFyZ2V0OwogICAgICB2YXIgYWN0aW9uTmFtZTsKICAgICAgdmFyIGFjdGlvbk5hbWVSZWY7CgogICAgICBpZiAocG9zaXRpb25hbC5sZW5ndGggPiAxKSB7CiAgICAgICAgaW1wbGljaXRUYXJnZXQgPSBwb3NpdGlvbmFsLmF0KDApOwogICAgICAgIGFjdGlvbk5hbWVSZWYgPSBwb3NpdGlvbmFsLmF0KDEpOwoKICAgICAgICBpZiAoYWN0aW9uTmFtZVJlZltJTlZPS0VdKSB7CiAgICAgICAgICBhY3Rpb25OYW1lID0gYWN0aW9uTmFtZVJlZjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFyIGFjdGlvbkxhYmVsID0gYWN0aW9uTmFtZVJlZi5wcm9wZXJ0eUtleTsKICAgICAgICAgIGFjdGlvbk5hbWUgPSBhY3Rpb25OYW1lUmVmLnZhbHVlKCk7CiAgICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGFjdGlvbk5hbWUgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IHNwZWNpZmllZCBhIHF1b3RlbGVzcyBwYXRoLCBgJyArIGFjdGlvbkxhYmVsICsgJ2AsIHRvIHRoZSAnICsgJ3t7YWN0aW9ufX0gaGVscGVyIHdoaWNoIGRpZCBub3QgcmVzb2x2ZSB0byBhbiBhY3Rpb24gbmFtZSAoYSAnICsgJ3N0cmluZykuIFBlcmhhcHMgeW91IG1lYW50IHRvIHVzZSBhIHF1b3RlZCBhY3Rpb25OYW1lPyAoZS5nLiAnICsgJ3t7YWN0aW9uICInICsgYWN0aW9uTGFiZWwgKyAnIn19KS4nLCB0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGFjdGlvbk5hbWUgPT09ICdmdW5jdGlvbicpKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciBhY3Rpb25BcmdzID0gW107IC8vIFRoZSBmaXJzdCB0d28gYXJndW1lbnRzIGFyZSAoMSkgYHRoaXNgIGFuZCAoMikgdGhlIGFjdGlvbiBuYW1lLgogICAgICAvLyBFdmVyeXRoaW5nIGVsc2UgaXMgYSBwYXJhbS4KCiAgICAgIGZvciAodmFyIGkgPSAyOyBpIDwgcG9zaXRpb25hbC5sZW5ndGg7IGkrKykgewogICAgICAgIGFjdGlvbkFyZ3MucHVzaChwb3NpdGlvbmFsLmF0KGkpKTsKICAgICAgfQoKICAgICAgdmFyIGFjdGlvbklkID0gKDAsIF91dGlscy51dWlkKSgpOwogICAgICB2YXIgYWN0aW9uU3RhdGUgPSBuZXcgQWN0aW9uU3RhdGUoZWxlbWVudCwgYWN0aW9uSWQsIGFjdGlvbk5hbWUsIGFjdGlvbkFyZ3MsIG5hbWVkLCBwb3NpdGlvbmFsLCBpbXBsaWNpdFRhcmdldCwgZG9tLCB0YWcpOwogICAgICAoZmFsc2UgJiYgIShhY3Rpb25TdGF0ZS5ldmVudE5hbWUgIT09ICdtb3VzZUVudGVyJyAmJiBhY3Rpb25TdGF0ZS5ldmVudE5hbWUgIT09ICdtb3VzZUxlYXZlJyAmJiBhY3Rpb25TdGF0ZS5ldmVudE5hbWUgIT09ICdtb3VzZU1vdmUnKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIlVzaW5nIHRoZSBge3thY3Rpb259fWAgbW9kaWZpZXIgd2l0aCBgIiArIGFjdGlvblN0YXRlLmV2ZW50TmFtZSArICJgIGV2ZW50cyBoYXMgYmVlbiBkZXByZWNhdGVkLiIsIGFjdGlvblN0YXRlLmV2ZW50TmFtZSAhPT0gJ21vdXNlRW50ZXInICYmIGFjdGlvblN0YXRlLmV2ZW50TmFtZSAhPT0gJ21vdXNlTGVhdmUnICYmIGFjdGlvblN0YXRlLmV2ZW50TmFtZSAhPT0gJ21vdXNlTW92ZScsIHsKICAgICAgICBpZDogJ2VtYmVyLXZpZXdzLmV2ZW50LWRpc3BhdGNoZXIubW91c2VlbnRlci1sZWF2ZS1tb3ZlJywKICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY19hY3Rpb24tbW91c2VlbnRlci1sZWF2ZS1tb3ZlJwogICAgICB9KSk7CiAgICAgIHJldHVybiBhY3Rpb25TdGF0ZTsKICAgIH07CgogICAgX3Byb3RvNTYuaW5zdGFsbCA9IGZ1bmN0aW9uIGluc3RhbGwoYWN0aW9uU3RhdGUpIHsKICAgICAgdmFyIGRvbSA9IGFjdGlvblN0YXRlLmRvbSwKICAgICAgICAgIGVsZW1lbnQgPSBhY3Rpb25TdGF0ZS5lbGVtZW50LAogICAgICAgICAgYWN0aW9uSWQgPSBhY3Rpb25TdGF0ZS5hY3Rpb25JZDsKICAgICAgQWN0aW9uSGVscGVyLnJlZ2lzdGVyQWN0aW9uKGFjdGlvblN0YXRlKTsKICAgICAgZG9tLnNldEF0dHJpYnV0ZShlbGVtZW50LCAnZGF0YS1lbWJlci1hY3Rpb24nLCAnJyk7CiAgICAgIGRvbS5zZXRBdHRyaWJ1dGUoZWxlbWVudCwgImRhdGEtZW1iZXItYWN0aW9uLSIgKyBhY3Rpb25JZCwgYWN0aW9uSWQpOwogICAgfTsKCiAgICBfcHJvdG81Ni51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoYWN0aW9uU3RhdGUpIHsKICAgICAgdmFyIHBvc2l0aW9uYWwgPSBhY3Rpb25TdGF0ZS5wb3NpdGlvbmFsOwogICAgICB2YXIgYWN0aW9uTmFtZVJlZiA9IHBvc2l0aW9uYWwuYXQoMSk7CgogICAgICBpZiAoIWFjdGlvbk5hbWVSZWZbSU5WT0tFXSkgewogICAgICAgIGFjdGlvblN0YXRlLmFjdGlvbk5hbWUgPSBhY3Rpb25OYW1lUmVmLnZhbHVlKCk7CiAgICAgIH0KCiAgICAgIGFjdGlvblN0YXRlLmV2ZW50TmFtZSA9IGFjdGlvblN0YXRlLmdldEV2ZW50TmFtZSgpOwogICAgfTsKCiAgICBfcHJvdG81Ni5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoYWN0aW9uU3RhdGUpIHsKICAgICAgcmV0dXJuIGFjdGlvblN0YXRlLnRhZzsKICAgIH07CgogICAgX3Byb3RvNTYuZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3IobW9kaWZpZXIpIHsKICAgICAgcmV0dXJuIG1vZGlmaWVyOwogICAgfTsKCiAgICByZXR1cm4gQWN0aW9uTW9kaWZpZXJNYW5hZ2VyOwogIH0oKTsKCiAgZnVuY3Rpb24gY2FwYWJpbGl0aWVzJDEobWFuYWdlckFQSSwgb3B0aW9uYWxGZWF0dXJlcykgewogICAgaWYgKG9wdGlvbmFsRmVhdHVyZXMgPT09IHZvaWQgMCkgewogICAgICBvcHRpb25hbEZlYXR1cmVzID0ge307CiAgICB9CgogICAgaWYgKG1hbmFnZXJBUEkgIT09ICczLjEzJykgewogICAgICBtYW5hZ2VyQVBJID0gJzMuMTMnOwogICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdNb2RpZmllciBtYW5hZ2VyIGNhcGFiaWxpdGllcyBub3cgcmVxdWlyZSB5b3UgdG8gcGFzcyBhIHZhbGlkIHZlcnNpb24gd2hlbiBiZWluZyBnZW5lcmF0ZWQuIFZhbGlkIHZlcnNpb25zIGluY2x1ZGU6IDMuMTMnLCBmYWxzZSwgewogICAgICAgIHVudGlsOiAnMy4xNy4wJywKICAgICAgICBpZDogJ2ltcGxpY2l0LW1vZGlmaWVyLW1hbmFnZXItY2FwYWJpbGl0aWVzJwogICAgICB9KSk7CiAgICB9CgogICAgKGZhbHNlICYmICEobWFuYWdlckFQSSA9PT0gJzMuMTMnKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0ludmFsaWQgbW9kaWZpZXIgbWFuYWdlciBjb21wYXRpYmlsaXR5IHNwZWNpZmllZCcsIG1hbmFnZXJBUEkgPT09ICczLjEzJykpOwogICAgcmV0dXJuIHsKICAgICAgZGlzYWJsZUF1dG9UcmFja2luZzogQm9vbGVhbihvcHRpb25hbEZlYXR1cmVzLmRpc2FibGVBdXRvVHJhY2tpbmcpCiAgICB9OwogIH0KCiAgdmFyIEN1c3RvbU1vZGlmaWVyRGVmaW5pdGlvbiA9IGZ1bmN0aW9uIEN1c3RvbU1vZGlmaWVyRGVmaW5pdGlvbihuYW1lLCBNb2RpZmllckNsYXNzLCBkZWxlZ2F0ZSwgaXNJbnRlcmFjdGl2ZSkgewogICAgdGhpcy5uYW1lID0gbmFtZTsKICAgIHRoaXMuTW9kaWZpZXJDbGFzcyA9IE1vZGlmaWVyQ2xhc3M7CiAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7CiAgICB0aGlzLnN0YXRlID0gewogICAgICBNb2RpZmllckNsYXNzOiBNb2RpZmllckNsYXNzLAogICAgICBuYW1lOiBuYW1lLAogICAgICBkZWxlZ2F0ZTogZGVsZWdhdGUKICAgIH07CiAgICB0aGlzLm1hbmFnZXIgPSBpc0ludGVyYWN0aXZlID8gQ1VTVE9NX0lOVEVSQUNUSVZFX01PRElGSUVSX01BTkFHRVIgOiBDVVNUT01fTk9OX0lOVEVSQUNUSVZFX01PRElGSUVSX01BTkFHRVI7CiAgfTsKCiAgdmFyIEN1c3RvbU1vZGlmaWVyU3RhdGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDdXN0b21Nb2RpZmllclN0YXRlKGVsZW1lbnQsIGRlbGVnYXRlLCBtb2RpZmllciwgYXJncykgewogICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50OwogICAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7CiAgICAgIHRoaXMubW9kaWZpZXIgPSBtb2RpZmllcjsKICAgICAgdGhpcy5hcmdzID0gYXJnczsKICAgICAgdGhpcy50YWcgPSAoMCwgX3JlZmVyZW5jZS5jcmVhdGVVcGRhdGFibGVUYWcpKCk7CiAgICB9CgogICAgdmFyIF9wcm90bzU3ID0gQ3VzdG9tTW9kaWZpZXJTdGF0ZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNTcuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHZhciBkZWxlZ2F0ZSA9IHRoaXMuZGVsZWdhdGUsCiAgICAgICAgICBtb2RpZmllciA9IHRoaXMubW9kaWZpZXIsCiAgICAgICAgICBhcmdzID0gdGhpcy5hcmdzOwogICAgICBkZWxlZ2F0ZS5kZXN0cm95TW9kaWZpZXIobW9kaWZpZXIsIGFyZ3MudmFsdWUoKSk7CiAgICB9OwoKICAgIHJldHVybiBDdXN0b21Nb2RpZmllclN0YXRlOwogIH0oKTsKICAvKioKICAgIFRoZSBDdXN0b21Nb2RpZmllck1hbmFnZXIgYWxsb3dzIGFkZG9ucyB0byBwcm92aWRlIGN1c3RvbSBtb2RpZmllcgogICAgaW1wbGVtZW50YXRpb25zIHRoYXQgaW50ZWdyYXRlIHNlYW1sZXNzbHkgaW50byBFbWJlci4gVGhpcyBpcyBhY2NvbXBsaXNoZWQKICAgIHRocm91Z2ggYSBkZWxlZ2F0ZSwgcmVnaXN0ZXJlZCB3aXRoIHRoZSBjdXN0b20gbW9kaWZpZXIgbWFuYWdlciwgd2hpY2gKICAgIGltcGxlbWVudHMgYSBzZXQgb2YgaG9va3MgdGhhdCBkZXRlcm1pbmUgbW9kaWZpZXIgYmVoYXZpb3IuCiAgICBUbyBjcmVhdGUgYSBjdXN0b20gbW9kaWZpZXIgbWFuYWdlciwgaW5zdGFudGlhdGUgYSBuZXcgQ3VzdG9tTW9kaWZpZXJNYW5hZ2VyCiAgICBjbGFzcyBhbmQgcGFzcyB0aGUgZGVsZWdhdGUgYXMgdGhlIGZpcnN0IGFyZ3VtZW50OgogIAogICAgYGBganMKICAgIGxldCBtYW5hZ2VyID0gbmV3IEN1c3RvbU1vZGlmaWVyTWFuYWdlcih7CiAgICAgIC8vIC4uLmRlbGVnYXRlIGltcGxlbWVudGF0aW9uLi4uCiAgICB9KTsKICAgIGBgYAogIAogICAgIyMgRGVsZWdhdGUgSG9va3MKICAKICAgIFRocm91Z2hvdXQgdGhlIGxpZmVjeWNsZSBvZiBhIG1vZGlmaWVyLCB0aGUgbW9kaWZpZXIgbWFuYWdlciB3aWxsIGludm9rZQogICAgZGVsZWdhdGUgaG9va3MgdGhhdCBhcmUgcmVzcG9uc2libGUgZm9yIHN1cmZhY2luZyB0aG9zZSBsaWZlY3ljbGUgY2hhbmdlcyB0bwogICAgdGhlIGVuZCBkZXZlbG9wZXIuCiAgICAqIGBjcmVhdGVNb2RpZmllcigpYCAtIGludm9rZWQgd2hlbiBhIG5ldyBpbnN0YW5jZSBvZiBhIG1vZGlmaWVyIHNob3VsZCBiZSBjcmVhdGVkCiAgICAqIGBpbnN0YWxsTW9kaWZpZXIoKWAgLSBpbnZva2VkIHdoZW4gdGhlIG1vZGlmaWVyIGlzIGluc3RhbGxlZCBvbiB0aGUgZWxlbWVudAogICAgKiBgdXBkYXRlTW9kaWZpZXIoKWAgLSBpbnZva2VkIHdoZW4gdGhlIGFyZ3VtZW50cyBwYXNzZWQgdG8gYSBtb2RpZmllciBjaGFuZ2UKICAgICogYGRlc3Ryb3lNb2RpZmllcigpYCAtIGludm9rZWQgd2hlbiB0aGUgbW9kaWZpZXIgaXMgYWJvdXQgdG8gYmUgZGVzdHJveWVkCiAgKi8KCgogIHZhciBJbnRlcmFjdGl2ZUN1c3RvbU1vZGlmaWVyTWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEludGVyYWN0aXZlQ3VzdG9tTW9kaWZpZXJNYW5hZ2VyKCkge30KCiAgICB2YXIgX3Byb3RvNTggPSBJbnRlcmFjdGl2ZUN1c3RvbU1vZGlmaWVyTWFuYWdlci5wcm90b3R5cGU7CgogICAgX3Byb3RvNTguY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKGVsZW1lbnQsIGRlZmluaXRpb24sIGFyZ3MpIHsKICAgICAgdmFyIGRlbGVnYXRlID0gZGVmaW5pdGlvbi5kZWxlZ2F0ZSwKICAgICAgICAgIE1vZGlmaWVyQ2xhc3MgPSBkZWZpbml0aW9uLk1vZGlmaWVyQ2xhc3M7CiAgICAgIHZhciBjYXB0dXJlZEFyZ3MgPSBhcmdzLmNhcHR1cmUoKTsKICAgICAgdmFyIGluc3RhbmNlID0gZGVmaW5pdGlvbi5kZWxlZ2F0ZS5jcmVhdGVNb2RpZmllcihNb2RpZmllckNsYXNzLCBjYXB0dXJlZEFyZ3MudmFsdWUoKSk7CgogICAgICBpZiAoZGVsZWdhdGUuY2FwYWJpbGl0aWVzID09PSB1bmRlZmluZWQpIHsKICAgICAgICBkZWxlZ2F0ZS5jYXBhYmlsaXRpZXMgPSBjYXBhYmlsaXRpZXMkMSgnMy4xMycpOwogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoJ0N1c3RvbSBtb2RpZmllciBtYW5hZ2VycyBtdXN0IGRlZmluZSB0aGVpciBjYXBhYmlsaXRpZXMgdXNpbmcgdGhlIGNhcGFiaWxpdGllcygpIGhlbHBlciBmdW5jdGlvbicsIGZhbHNlLCB7CiAgICAgICAgICB1bnRpbDogJzMuMTcuMCcsCiAgICAgICAgICBpZDogJ2ltcGxpY2l0LW1vZGlmaWVyLW1hbmFnZXItY2FwYWJpbGl0aWVzJwogICAgICAgIH0pKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5ldyBDdXN0b21Nb2RpZmllclN0YXRlKGVsZW1lbnQsIGRlbGVnYXRlLCBpbnN0YW5jZSwgY2FwdHVyZWRBcmdzKTsKICAgIH07CgogICAgX3Byb3RvNTguZ2V0VGFnID0gZnVuY3Rpb24gZ2V0VGFnKF9yZWYzMykgewogICAgICB2YXIgYXJncyA9IF9yZWYzMy5hcmdzLAogICAgICAgICAgdGFnID0gX3JlZjMzLnRhZzsKICAgICAgcmV0dXJuICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFt0YWcsIGFyZ3MudGFnXSk7CiAgICB9OwoKICAgIF9wcm90bzU4Lmluc3RhbGwgPSBmdW5jdGlvbiBpbnN0YWxsKHN0YXRlKSB7CiAgICAgIHZhciBlbGVtZW50ID0gc3RhdGUuZWxlbWVudCwKICAgICAgICAgIGFyZ3MgPSBzdGF0ZS5hcmdzLAogICAgICAgICAgZGVsZWdhdGUgPSBzdGF0ZS5kZWxlZ2F0ZSwKICAgICAgICAgIG1vZGlmaWVyID0gc3RhdGUubW9kaWZpZXIsCiAgICAgICAgICB0YWcgPSBzdGF0ZS50YWc7CiAgICAgIHZhciBjYXBhYmlsaXRpZXMgPSBkZWxlZ2F0ZS5jYXBhYmlsaXRpZXM7CgogICAgICBpZiAoY2FwYWJpbGl0aWVzLmRpc2FibGVBdXRvVHJhY2tpbmcgPT09IHRydWUpIHsKICAgICAgICAoMCwgX21ldGFsLnVudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBkZWxlZ2F0ZS5pbnN0YWxsTW9kaWZpZXIobW9kaWZpZXIsIGVsZW1lbnQsIGFyZ3MudmFsdWUoKSk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIGNvbWJpbmVkVHJhY2tpbmdUYWcgPSAoMCwgX21ldGFsLnRyYWNrKShmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gZGVsZWdhdGUuaW5zdGFsbE1vZGlmaWVyKG1vZGlmaWVyLCBlbGVtZW50LCBhcmdzLnZhbHVlKCkpOwogICAgICAgIH0pOwogICAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkodGFnLCBjb21iaW5lZFRyYWNraW5nVGFnKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG81OC51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoc3RhdGUpIHsKICAgICAgdmFyIGFyZ3MgPSBzdGF0ZS5hcmdzLAogICAgICAgICAgZGVsZWdhdGUgPSBzdGF0ZS5kZWxlZ2F0ZSwKICAgICAgICAgIG1vZGlmaWVyID0gc3RhdGUubW9kaWZpZXIsCiAgICAgICAgICB0YWcgPSBzdGF0ZS50YWc7CiAgICAgIHZhciBjYXBhYmlsaXRpZXMgPSBkZWxlZ2F0ZS5jYXBhYmlsaXRpZXM7CgogICAgICBpZiAoY2FwYWJpbGl0aWVzLmRpc2FibGVBdXRvVHJhY2tpbmcgPT09IHRydWUpIHsKICAgICAgICAoMCwgX21ldGFsLnVudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBkZWxlZ2F0ZS51cGRhdGVNb2RpZmllcihtb2RpZmllciwgYXJncy52YWx1ZSgpKTsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgY29tYmluZWRUcmFja2luZ1RhZyA9ICgwLCBfbWV0YWwudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBkZWxlZ2F0ZS51cGRhdGVNb2RpZmllcihtb2RpZmllciwgYXJncy52YWx1ZSgpKTsKICAgICAgICB9KTsKICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHRhZywgY29tYmluZWRUcmFja2luZ1RhZyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNTguZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3Ioc3RhdGUpIHsKICAgICAgcmV0dXJuIHN0YXRlOwogICAgfTsKCiAgICByZXR1cm4gSW50ZXJhY3RpdmVDdXN0b21Nb2RpZmllck1hbmFnZXI7CiAgfSgpOwoKICB2YXIgTm9uSW50ZXJhY3RpdmVDdXN0b21Nb2RpZmllck1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBOb25JbnRlcmFjdGl2ZUN1c3RvbU1vZGlmaWVyTWFuYWdlcigpIHt9CgogICAgdmFyIF9wcm90bzU5ID0gTm9uSW50ZXJhY3RpdmVDdXN0b21Nb2RpZmllck1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzU5LmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9OwoKICAgIF9wcm90bzU5LmdldFRhZyA9IGZ1bmN0aW9uIGdldFRhZygpIHsKICAgICAgcmV0dXJuIF9yZWZlcmVuY2UuQ09OU1RBTlRfVEFHOwogICAgfTsKCiAgICBfcHJvdG81OS5pbnN0YWxsID0gZnVuY3Rpb24gaW5zdGFsbCgpIHt9OwoKICAgIF9wcm90bzU5LnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZSgpIHt9OwoKICAgIF9wcm90bzU5LmdldERlc3RydWN0b3IgPSBmdW5jdGlvbiBnZXREZXN0cnVjdG9yKCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH07CgogICAgcmV0dXJuIE5vbkludGVyYWN0aXZlQ3VzdG9tTW9kaWZpZXJNYW5hZ2VyOwogIH0oKTsKCiAgdmFyIENVU1RPTV9JTlRFUkFDVElWRV9NT0RJRklFUl9NQU5BR0VSID0gbmV3IEludGVyYWN0aXZlQ3VzdG9tTW9kaWZpZXJNYW5hZ2VyKCk7CiAgdmFyIENVU1RPTV9OT05fSU5URVJBQ1RJVkVfTU9ESUZJRVJfTUFOQUdFUiA9IG5ldyBOb25JbnRlcmFjdGl2ZUN1c3RvbU1vZGlmaWVyTWFuYWdlcigpOwogIHZhciB1bnRvdWNoYWJsZUNvbnRleHQgPSBidWlsZFVudG91Y2hhYmxlVGhpcygnYG9uYCBtb2RpZmllcicpOwogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKgogICAgSW50ZXJuZXQgRXhwbG9yZXIgMTEgZG9lcyBub3Qgc3VwcG9ydCBgb25jZWAgYW5kIGFsc28gZG9lcyBub3Qgc3VwcG9ydAogICAgcGFzc2luZyBgZXZlbnRPcHRpb25zYC4gSW4gc29tZSBzaXR1YXRpb25zIGl0IHRoZW4gdGhyb3dzIGEgd2VpcmQgc2NyaXB0CiAgICBlcnJvciwgbGlrZToKICAKICAgIGBgYAogICAgQ291bGQgbm90IGNvbXBsZXRlIHRoZSBvcGVyYXRpb24gZHVlIHRvIGVycm9yIDgwMDIwMTAxCiAgICBgYGAKICAKICAgIFRoaXMgZmxhZyBkZXRlcm1pbmVzLCB3aGV0aGVyIGB7IG9uY2U6IHRydWUgfWAgYW5kIHRodXMgYWxzbyBldmVudCBvcHRpb25zIGluCiAgICBnZW5lcmFsIGFyZSBzdXBwb3J0ZWQuCiAgKi8KCiAgdmFyIFNVUFBPUlRTX0VWRU5UX09QVElPTlMgPSBmdW5jdGlvbiAoKSB7CiAgICB0cnkgewogICAgICB2YXIgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIHZhciBjb3VudGVyID0gMDsKICAgICAgZGl2LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBjb3VudGVyKys7CiAgICAgIH0sIHsKICAgICAgICBvbmNlOiB0cnVlCiAgICAgIH0pOwogICAgICB2YXIgZXZlbnQ7CgogICAgICBpZiAodHlwZW9mIEV2ZW50ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgZXZlbnQgPSBuZXcgRXZlbnQoJ2NsaWNrJyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnRXZlbnQnKTsKICAgICAgICBldmVudC5pbml0RXZlbnQoJ2NsaWNrJywgdHJ1ZSwgdHJ1ZSk7CiAgICAgIH0KCiAgICAgIGRpdi5kaXNwYXRjaEV2ZW50KGV2ZW50KTsKICAgICAgZGl2LmRpc3BhdGNoRXZlbnQoZXZlbnQpOwogICAgICByZXR1cm4gY291bnRlciA9PT0gMTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9KCk7CgogIHZhciBPbk1vZGlmaWVyU3RhdGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBPbk1vZGlmaWVyU3RhdGUoZWxlbWVudCwgYXJncykgewogICAgICB0aGlzLnNob3VsZFVwZGF0ZSA9IHRydWU7CiAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7CiAgICAgIHRoaXMuYXJncyA9IGFyZ3M7CiAgICAgIHRoaXMudGFnID0gYXJncy50YWc7CiAgICB9CgogICAgdmFyIF9wcm90bzYwID0gT25Nb2RpZmllclN0YXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG82MC51cGRhdGVGcm9tQXJncyA9IGZ1bmN0aW9uIHVwZGF0ZUZyb21BcmdzKCkgewogICAgICB2YXIgYXJncyA9IHRoaXMuYXJnczsKCiAgICAgIHZhciBfYXJncyRuYW1lZCR2YWx1ZSA9IGFyZ3MubmFtZWQudmFsdWUoKSwKICAgICAgICAgIG9uY2UgPSBfYXJncyRuYW1lZCR2YWx1ZS5vbmNlLAogICAgICAgICAgcGFzc2l2ZSA9IF9hcmdzJG5hbWVkJHZhbHVlLnBhc3NpdmUsCiAgICAgICAgICBjYXB0dXJlID0gX2FyZ3MkbmFtZWQkdmFsdWUuY2FwdHVyZTsKCiAgICAgIGlmIChvbmNlICE9PSB0aGlzLm9uY2UpIHsKICAgICAgICB0aGlzLm9uY2UgPSBvbmNlOwogICAgICAgIHRoaXMuc2hvdWxkVXBkYXRlID0gdHJ1ZTsKICAgICAgfQoKICAgICAgaWYgKHBhc3NpdmUgIT09IHRoaXMucGFzc2l2ZSkgewogICAgICAgIHRoaXMucGFzc2l2ZSA9IHBhc3NpdmU7CiAgICAgICAgdGhpcy5zaG91bGRVcGRhdGUgPSB0cnVlOwogICAgICB9CgogICAgICBpZiAoY2FwdHVyZSAhPT0gdGhpcy5jYXB0dXJlKSB7CiAgICAgICAgdGhpcy5jYXB0dXJlID0gY2FwdHVyZTsKICAgICAgICB0aGlzLnNob3VsZFVwZGF0ZSA9IHRydWU7CiAgICAgIH0KCiAgICAgIHZhciBvcHRpb25zOwoKICAgICAgaWYgKG9uY2UgfHwgcGFzc2l2ZSB8fCBjYXB0dXJlKSB7CiAgICAgICAgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyA9IHsKICAgICAgICAgIG9uY2U6IG9uY2UsCiAgICAgICAgICBwYXNzaXZlOiBwYXNzaXZlLAogICAgICAgICAgY2FwdHVyZTogY2FwdHVyZQogICAgICAgIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5vcHRpb25zID0gdW5kZWZpbmVkOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgIShhcmdzLnBvc2l0aW9uYWwuYXQoMCkgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYXJncy5wb3NpdGlvbmFsLmF0KDApLnZhbHVlKCkgPT09ICdzdHJpbmcnKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBtdXN0IHBhc3MgYSB2YWxpZCBET00gZXZlbnQgbmFtZSBhcyB0aGUgZmlyc3QgYXJndW1lbnQgdG8gdGhlIGBvbmAgbW9kaWZpZXInLCBhcmdzLnBvc2l0aW9uYWwuYXQoMCkgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYXJncy5wb3NpdGlvbmFsLmF0KDApLnZhbHVlKCkgPT09ICdzdHJpbmcnKSk7CiAgICAgIHZhciBldmVudE5hbWUgPSBhcmdzLnBvc2l0aW9uYWwuYXQoMCkudmFsdWUoKTsKCiAgICAgIGlmIChldmVudE5hbWUgIT09IHRoaXMuZXZlbnROYW1lKSB7CiAgICAgICAgdGhpcy5ldmVudE5hbWUgPSBldmVudE5hbWU7CiAgICAgICAgdGhpcy5zaG91bGRVcGRhdGUgPSB0cnVlOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgIShhcmdzLnBvc2l0aW9uYWwuYXQoMSkgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYXJncy5wb3NpdGlvbmFsLmF0KDEpLnZhbHVlKCkgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IG11c3QgcGFzcyBhIGZ1bmN0aW9uIGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgdG8gdGhlIGBvbmAgbW9kaWZpZXInLCBhcmdzLnBvc2l0aW9uYWwuYXQoMSkgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYXJncy5wb3NpdGlvbmFsLmF0KDEpLnZhbHVlKCkgPT09ICdmdW5jdGlvbicpKTsKICAgICAgdmFyIHVzZXJQcm92aWRlZENhbGxiYWNrID0gYXJncy5wb3NpdGlvbmFsLmF0KDEpLnZhbHVlKCk7CgogICAgICBpZiAodXNlclByb3ZpZGVkQ2FsbGJhY2sgIT09IHRoaXMudXNlclByb3ZpZGVkQ2FsbGJhY2spIHsKICAgICAgICB0aGlzLnVzZXJQcm92aWRlZENhbGxiYWNrID0gdXNlclByb3ZpZGVkQ2FsbGJhY2s7CiAgICAgICAgdGhpcy5zaG91bGRVcGRhdGUgPSB0cnVlOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgIShhcmdzLnBvc2l0aW9uYWwubGVuZ3RoID09PSAyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW4gb25seSBwYXNzIHR3byBwb3NpdGlvbmFsIGFyZ3VtZW50cyAoZXZlbnQgbmFtZSBhbmQgY2FsbGJhY2spIHRvIHRoZSBgb25gIG1vZGlmaWVyLCBidXQgeW91IHByb3ZpZGVkICIgKyBhcmdzLnBvc2l0aW9uYWwubGVuZ3RoICsgIi4gQ29uc2lkZXIgdXNpbmcgdGhlIGBmbmAgaGVscGVyIHRvIHByb3ZpZGUgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gdGhlIGBvbmAgY2FsbGJhY2suIiwgYXJncy5wb3NpdGlvbmFsLmxlbmd0aCA9PT0gMikpOwogICAgICB2YXIgbmVlZHNDdXN0b21DYWxsYmFjayA9IFNVUFBPUlRTX0VWRU5UX09QVElPTlMgPT09IGZhbHNlICYmIG9uY2UgfHwKICAgICAgLyogbmVlZHMgbWFudWFsIG9uY2UgaW1wbGVtZW50YXRpb24gKi8KICAgICAgZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgJiYgcGFzc2l2ZQogICAgICAvKiBuZWVkcyBwYXNzaXZlIGVuZm9yY2VtZW50ICovCiAgICAgIDsKCiAgICAgIGlmICh0aGlzLnNob3VsZFVwZGF0ZSkgewogICAgICAgIGlmIChuZWVkc0N1c3RvbUNhbGxiYWNrKSB7CiAgICAgICAgICB2YXIgY2FsbGJhY2sgPSB0aGlzLmNhbGxiYWNrID0gZnVuY3Rpb24gKGV2ZW50KSB7CiAgICAgICAgICAgIGlmIChmYWxzZQogICAgICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICAgICAmJiBwYXNzaXZlKSB7CiAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgbWFya2VkIHRoaXMgbGlzdGVuZXIgYXMgJ3Bhc3NpdmUnLCBtZWFuaW5nIHRoYXQgeW91IG11c3Qgbm90IGNhbGwgJ2V2ZW50LnByZXZlbnREZWZhdWx0KCknOiBcblxuIiArIHVzZXJQcm92aWRlZENhbGxiYWNrKSk7CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaWYgKCFTVVBQT1JUU19FVkVOVF9PUFRJT05TICYmIG9uY2UpIHsKICAgICAgICAgICAgICByZW1vdmVFdmVudExpc3RlbmVyKHRoaXMsIGV2ZW50TmFtZSwgY2FsbGJhY2ssIG9wdGlvbnMpOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gdXNlclByb3ZpZGVkQ2FsbGJhY2suY2FsbCh1bnRvdWNoYWJsZUNvbnRleHQsIGV2ZW50KTsKICAgICAgICAgIH07CiAgICAgICAgfSBlbHNlIGlmIChmYWxzZQogICAgICAgIC8qIERFQlVHICovCiAgICAgICAgKSB7CiAgICAgICAgICAvLyBwcmV2ZW50IHRoZSBjYWxsYmFjayBmcm9tIGJlaW5nIGJvdW5kIHRvIHRoZSBlbGVtZW50CiAgICAgICAgICB0aGlzLmNhbGxiYWNrID0gdXNlclByb3ZpZGVkQ2FsbGJhY2suYmluZCh1bnRvdWNoYWJsZUNvbnRleHQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLmNhbGxiYWNrID0gdXNlclByb3ZpZGVkQ2FsbGJhY2s7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzYwLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICB2YXIgZWxlbWVudCA9IHRoaXMuZWxlbWVudCwKICAgICAgICAgIGV2ZW50TmFtZSA9IHRoaXMuZXZlbnROYW1lLAogICAgICAgICAgY2FsbGJhY2sgPSB0aGlzLmNhbGxiYWNrLAogICAgICAgICAgb3B0aW9ucyA9IHRoaXMub3B0aW9uczsKICAgICAgcmVtb3ZlRXZlbnRMaXN0ZW5lcihlbGVtZW50LCBldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKTsKICAgIH07CgogICAgcmV0dXJuIE9uTW9kaWZpZXJTdGF0ZTsKICB9KCk7CgogIHZhciBhZGRzID0gMDsKICB2YXIgcmVtb3ZlcyA9IDA7CgogIGZ1bmN0aW9uIHJlbW92ZUV2ZW50TGlzdGVuZXIoZWxlbWVudCwgZXZlbnROYW1lLCBjYWxsYmFjaywgb3B0aW9ucykgewogICAgcmVtb3ZlcysrOwoKICAgIGlmIChTVVBQT1JUU19FVkVOVF9PUFRJT05TKSB7CiAgICAgIC8vIHdoZW4gb3B0aW9ucyBhcmUgc3VwcG9ydGVkLCB1c2UgdGhlbSBhY3Jvc3MgdGhlIGJvYXJkCiAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKTsKICAgIH0gZWxzZSBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMuY2FwdHVyZSkgewogICAgICAvLyB1c2VkIG9ubHkgaW4gdGhlIGZvbGxvd2luZyBjYXNlOgogICAgICAvLwogICAgICAvLyBgeyBvbmNlOiB0cnVlIHwgZmFsc2UsIHBhc3NpdmU6IHRydWUgfCBmYWxzZSwgY2FwdHVyZTogdHJ1ZSB9CiAgICAgIC8vCiAgICAgIC8vIGBvbmNlYCBpcyBoYW5kbGVkIHZpYSBhIGN1c3RvbSBjYWxsYmFjayB0aGF0IHJlbW92ZXMgYWZ0ZXIgZmlyc3QKICAgICAgLy8gaW52b2NhdGlvbiBzbyB3ZSBvbmx5IGNhcmUgYWJvdXQgY2FwdHVyZSBoZXJlIGFzIGEgYm9vbGVhbgogICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBjYWxsYmFjaywgdHJ1ZSk7CiAgICB9IGVsc2UgewogICAgICAvLyB1c2VkIG9ubHkgaW4gdGhlIGZvbGxvd2luZyBjYXNlczoKICAgICAgLy8KICAgICAgLy8gKiB3aGVyZSB0aGVyZSBpcyBubyBvcHRpb25zCiAgICAgIC8vICogYHsgb25jZTogdHJ1ZSB8IGZhbHNlLCBwYXNzaXZlOiB0cnVlIHwgZmFsc2UsIGNhcHR1cmU6IGZhbHNlIH0KICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2spOwogICAgfQogIH0KCiAgZnVuY3Rpb24gYWRkRXZlbnRMaXN0ZW5lcihlbGVtZW50LCBldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKSB7CiAgICBhZGRzKys7CgogICAgaWYgKFNVUFBPUlRTX0VWRU5UX09QVElPTlMpIHsKICAgICAgLy8gd2hlbiBvcHRpb25zIGFyZSBzdXBwb3J0ZWQsIHVzZSB0aGVtIGFjcm9zcyB0aGUgYm9hcmQKICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG9wdGlvbnMpOwogICAgfSBlbHNlIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5jYXB0dXJlKSB7CiAgICAgIC8vIHVzZWQgb25seSBpbiB0aGUgZm9sbG93aW5nIGNhc2U6CiAgICAgIC8vCiAgICAgIC8vIGB7IG9uY2U6IHRydWUgfCBmYWxzZSwgcGFzc2l2ZTogdHJ1ZSB8IGZhbHNlLCBjYXB0dXJlOiB0cnVlIH0KICAgICAgLy8KICAgICAgLy8gYG9uY2VgIGlzIGhhbmRsZWQgdmlhIGEgY3VzdG9tIGNhbGxiYWNrIHRoYXQgcmVtb3ZlcyBhZnRlciBmaXJzdAogICAgICAvLyBpbnZvY2F0aW9uIHNvIHdlIG9ubHkgY2FyZSBhYm91dCBjYXB0dXJlIGhlcmUgYXMgYSBib29sZWFuCiAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCB0cnVlKTsKICAgIH0gZWxzZSB7CiAgICAgIC8vIHVzZWQgb25seSBpbiB0aGUgZm9sbG93aW5nIGNhc2VzOgogICAgICAvLwogICAgICAvLyAqIHdoZXJlIHRoZXJlIGlzIG5vIG9wdGlvbnMKICAgICAgLy8gKiBgeyBvbmNlOiB0cnVlIHwgZmFsc2UsIHBhc3NpdmU6IHRydWUgfCBmYWxzZSwgY2FwdHVyZTogZmFsc2UgfQogICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBjYWxsYmFjayk7CiAgICB9CiAgfQogIC8qKgogICAgVGhlIGB7e29ufX1gIG1vZGlmaWVyIGxldHMgeW91IGVhc2lseSBhZGQgZXZlbnQgbGlzdGVuZXJzIChpdCB1c2VzCiAgICBbRXZlbnRUYXJnZXQuYWRkRXZlbnRMaXN0ZW5lcl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0V2ZW50VGFyZ2V0L2FkZEV2ZW50TGlzdGVuZXIpCiAgICBpbnRlcm5hbGx5KS4KICAKICAgIEZvciBleGFtcGxlLCBpZiB5b3UnZCBsaWtlIHRvIHJ1biBhIGZ1bmN0aW9uIG9uIHlvdXIgY29tcG9uZW50IHdoZW4gYSBgPGJ1dHRvbj5gCiAgICBpbiB0aGUgY29tcG9uZW50cyB0ZW1wbGF0ZSBpcyBjbGlja2VkIHlvdSBtaWdodCBkbyBzb21ldGhpbmcgbGlrZToKICAKICAgIGBgYGFwcC90ZW1wbGF0ZXMvY29tcG9uZW50cy9saWtlLXBvc3QuaGJzCiAgICA8YnV0dG9uIHt7b24gJ2NsaWNrJyB0aGlzLnNhdmVMaWtlfX0+TGlrZSB0aGlzIHBvc3QhPC9idXR0b24+CiAgICBgYGAKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL2xpa2UtcG9zdC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZ2xpbW1lci9jb21wb25lbnQnOwogICAgaW1wb3J0IHsgYWN0aW9uIH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBjbGFzcyBMaWtlUG9zdENvbXBvbmVudCBleHRlbmRzIENvbXBvbmVudCB7CiAgICAgIEBhY3Rpb24KICAgICAgc2F2ZUxpa2UoKSB7CiAgICAgICAgLy8gc29tZW9uZSBsaWtlcyB5b3VyIHBvc3QhCiAgICAgICAgLy8gYmV0dGVyIHNlbmQgYSByZXF1ZXN0IG9mZiB0byB5b3VyIHNlcnZlci4uLgogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgICMjIyBBcmd1bWVudHMKICAKICAgIGB7e29ufX1gIGFjY2VwdHMgdHdvIHBvc2l0aW9uYWwgYXJndW1lbnRzLCBhbmQgYSBmZXcgbmFtZWQgYXJndW1lbnRzLgogIAogICAgVGhlIHBvc2l0aW9uYWwgYXJndW1lbnRzIGFyZToKICAKICAgIC0gYGV2ZW50YCAtLSB0aGUgbmFtZSB0byB1c2Ugd2hlbiBjYWxsaW5nIGBhZGRFdmVudExpc3RlbmVyYAogICAgLSBgY2FsbGJhY2tgIC0tIHRoZSBmdW5jdGlvbiB0byBiZSBwYXNzZWQgdG8gYGFkZEV2ZW50TGlzdGVuZXJgCiAgCiAgICBUaGUgbmFtZWQgYXJndW1lbnRzIGFyZToKICAKICAgIC0gY2FwdHVyZSAtLSBhIGB0cnVlYCB2YWx1ZSBpbmRpY2F0ZXMgdGhhdCBldmVudHMgb2YgdGhpcyB0eXBlIHdpbGwgYmUgZGlzcGF0Y2hlZAogICAgICB0byB0aGUgcmVnaXN0ZXJlZCBsaXN0ZW5lciBiZWZvcmUgYmVpbmcgZGlzcGF0Y2hlZCB0byBhbnkgRXZlbnRUYXJnZXQgYmVuZWF0aCBpdAogICAgICBpbiB0aGUgRE9NIHRyZWUuCiAgICAtIG9uY2UgLS0gaW5kaWNhdGVzIHRoYXQgdGhlIGxpc3RlbmVyIHNob3VsZCBiZSBpbnZva2VkIGF0IG1vc3Qgb25jZSBhZnRlciBiZWluZwogICAgICBhZGRlZC4gSWYgdHJ1ZSwgdGhlIGxpc3RlbmVyIHdvdWxkIGJlIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZCB3aGVuIGludm9rZWQuCiAgICAtIHBhc3NpdmUgLS0gaWYgYHRydWVgLCBpbmRpY2F0ZXMgdGhhdCB0aGUgZnVuY3Rpb24gc3BlY2lmaWVkIGJ5IGxpc3RlbmVyIHdpbGwgbmV2ZXIKICAgICAgY2FsbCBwcmV2ZW50RGVmYXVsdCgpLiBJZiBhIHBhc3NpdmUgbGlzdGVuZXIgZG9lcyBjYWxsIHByZXZlbnREZWZhdWx0KCksIHRoZSB1c2VyCiAgICAgIGFnZW50IHdpbGwgZG8gbm90aGluZyBvdGhlciB0aGFuIGdlbmVyYXRlIGEgY29uc29sZSB3YXJuaW5nLiBTZWUKICAgICAgW0ltcHJvdmluZyBzY3JvbGxpbmcgcGVyZm9ybWFuY2Ugd2l0aCBwYXNzaXZlIGxpc3RlbmVyc10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0V2ZW50VGFyZ2V0L2FkZEV2ZW50TGlzdGVuZXIjSW1wcm92aW5nX3Njcm9sbGluZ19wZXJmb3JtYW5jZV93aXRoX3Bhc3NpdmVfbGlzdGVuZXJzKQogICAgICB0byBsZWFybiBtb3JlLgogIAogICAgVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHBhc3NlZCB0byBge3tvbn19YCB3aWxsIHJlY2VpdmUgYW55IGFyZ3VtZW50cyB0aGF0IGFyZSBwYXNzZWQKICAgIHRvIHRoZSBldmVudCBoYW5kbGVyLiBNb3N0IGNvbW1vbmx5IHRoaXMgd291bGQgYmUgdGhlIGBldmVudGAgaXRzZWxmLgogIAogICAgSWYgeW91IHdvdWxkIGxpa2UgdG8gcGFzcyBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byB0aGUgZnVuY3Rpb24geW91IHNob3VsZCB1c2UKICAgIHRoZSBge3tmbn19YCBoZWxwZXIuCiAgCiAgICBGb3IgZXhhbXBsZSwgaW4gb3VyIGV4YW1wbGUgY2FzZSBhYm92ZSBpZiB5b3UnZCBsaWtlIHRvIHBhc3MgaW4gdGhlIHBvc3QgdGhhdAogICAgd2FzIGJlaW5nIGxpa2VkIHdoZW4gdGhlIGJ1dHRvbiBpcyBjbGlja2VkIHlvdSBjb3VsZCBkbyBzb21ldGhpbmcgbGlrZToKICAKICAgIGBgYGFwcC90ZW1wbGF0ZXMvY29tcG9uZW50cy9saWtlLXBvc3QuanMKICAgIDxidXR0b24ge3tvbiAnY2xpY2snIChmbiB0aGlzLnNhdmVMaWtlIEBwb3N0KX19Pkxpa2UgdGhpcyBwb3N0ITwvYnV0dG9uPgogICAgYGBgCiAgCiAgICBJbiB0aGlzIGNhc2UsIHRoZSBgc2F2ZUxpa2VgIGZ1bmN0aW9uIHdpbGwgcmVjZWl2ZSB0d28gYXJndW1lbnRzOiB0aGUgY2xpY2sgZXZlbnQKICAgIGFuZCB0aGUgdmFsdWUgb2YgYEBwb3N0YC4KICAKICAgICMjIyBGdW5jdGlvbiBDb250ZXh0CiAgCiAgICBJbiB0aGUgZXhhbXBsZSBhYm92ZSwgd2UgdXNlZCBgQGFjdGlvbmAgdG8gZW5zdXJlIHRoYXQgYGxpa2VQb3N0YCBpcwogICAgcHJvcGVybHkgYm91bmQgdG8gdGhlIGBpdGVtcy1saXN0YCwgYnV0IGxldCdzIGV4cGxvcmUgd2hhdCBoYXBwZW5zIGlmIHdlCiAgICBsZWZ0IG91dCBgQGFjdGlvbmA6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9saWtlLXBvc3QuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGdsaW1tZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IGNsYXNzIExpa2VQb3N0Q29tcG9uZW50IGV4dGVuZHMgQ29tcG9uZW50IHsKICAgICAgc2F2ZUxpa2UoKSB7CiAgICAgICAgLy8gLi4uc25pcC4uLgogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIEluIHRoaXMgZXhhbXBsZSwgd2hlbiB0aGUgYnV0dG9uIGlzIGNsaWNrZWQgYHNhdmVMaWtlYCB3aWxsIGJlIGludm9rZWQsCiAgICBpdCB3aWxsICoqbm90KiogaGF2ZSBhY2Nlc3MgdG8gdGhlIGNvbXBvbmVudCBpbnN0YW5jZS4gSW4gb3RoZXIKICAgIHdvcmRzLCBpdCB3aWxsIGhhdmUgbm8gYHRoaXNgIGNvbnRleHQsIHNvIHBsZWFzZSBtYWtlIHN1cmUgeW91ciBmdW5jdGlvbnMKICAgIGFyZSBib3VuZCAodmlhIGBAYWN0aW9uYCBvciBvdGhlciBtZWFucykgYmVmb3JlIHBhc3NpbmcgaW50byBgb25gIQogIAogICAgQG1ldGhvZCBvbgogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHB1YmxpYwogICAgQHNpbmNlIDMuMTEuMAogICovCgoKICB2YXIgT25Nb2RpZmllck1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBPbk1vZGlmaWVyTWFuYWdlcihpc0ludGVyYWN0aXZlKSB7CiAgICAgIHRoaXMuU1VQUE9SVFNfRVZFTlRfT1BUSU9OUyA9IFNVUFBPUlRTX0VWRU5UX09QVElPTlM7CiAgICAgIHRoaXMuaXNJbnRlcmFjdGl2ZSA9IGlzSW50ZXJhY3RpdmU7CiAgICB9CgogICAgdmFyIF9wcm90bzYxID0gT25Nb2RpZmllck1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzYxLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShlbGVtZW50LCBfc3RhdGUsIGFyZ3MpIHsKICAgICAgaWYgKCF0aGlzLmlzSW50ZXJhY3RpdmUpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIGNhcHR1cmVkQXJncyA9IGFyZ3MuY2FwdHVyZSgpOwogICAgICByZXR1cm4gbmV3IE9uTW9kaWZpZXJTdGF0ZShlbGVtZW50LCBjYXB0dXJlZEFyZ3MpOwogICAgfTsKCiAgICBfcHJvdG82MS5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoc3RhdGUpIHsKICAgICAgaWYgKHN0YXRlID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIF9yZWZlcmVuY2UuQ09OU1RBTlRfVEFHOwogICAgICB9CgogICAgICByZXR1cm4gc3RhdGUudGFnOwogICAgfTsKCiAgICBfcHJvdG82MS5pbnN0YWxsID0gZnVuY3Rpb24gaW5zdGFsbChzdGF0ZSkgewogICAgICBpZiAoc3RhdGUgPT09IG51bGwpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHN0YXRlLnVwZGF0ZUZyb21BcmdzKCk7CiAgICAgIHZhciBlbGVtZW50ID0gc3RhdGUuZWxlbWVudCwKICAgICAgICAgIGV2ZW50TmFtZSA9IHN0YXRlLmV2ZW50TmFtZSwKICAgICAgICAgIGNhbGxiYWNrID0gc3RhdGUuY2FsbGJhY2ssCiAgICAgICAgICBvcHRpb25zID0gc3RhdGUub3B0aW9uczsKICAgICAgYWRkRXZlbnRMaXN0ZW5lcihlbGVtZW50LCBldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKTsKICAgICAgc3RhdGUuc2hvdWxkVXBkYXRlID0gZmFsc2U7CiAgICB9OwoKICAgIF9wcm90bzYxLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZShzdGF0ZSkgewogICAgICBpZiAoc3RhdGUgPT09IG51bGwpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gLy8gc3Rhc2ggcHJpb3Igc3RhdGUgZm9yIGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIKCgogICAgICB2YXIgZWxlbWVudCA9IHN0YXRlLmVsZW1lbnQsCiAgICAgICAgICBldmVudE5hbWUgPSBzdGF0ZS5ldmVudE5hbWUsCiAgICAgICAgICBjYWxsYmFjayA9IHN0YXRlLmNhbGxiYWNrLAogICAgICAgICAgb3B0aW9ucyA9IHN0YXRlLm9wdGlvbnM7CiAgICAgIHN0YXRlLnVwZGF0ZUZyb21BcmdzKCk7CgogICAgICBpZiAoIXN0YXRlLnNob3VsZFVwZGF0ZSkgewogICAgICAgIHJldHVybjsKICAgICAgfSAvLyB1c2UgcHJpb3Igc3RhdGUgdmFsdWVzIGZvciByZW1vdmFsCgoKICAgICAgcmVtb3ZlRXZlbnRMaXN0ZW5lcihlbGVtZW50LCBldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKTsgLy8gcmVhZCB1cGRhdGVkIHZhbHVlcyBmcm9tIHRoZSBzdGF0ZSBvYmplY3QKCiAgICAgIGFkZEV2ZW50TGlzdGVuZXIoc3RhdGUuZWxlbWVudCwgc3RhdGUuZXZlbnROYW1lLCBzdGF0ZS5jYWxsYmFjaywgc3RhdGUub3B0aW9ucyk7CiAgICAgIHN0YXRlLnNob3VsZFVwZGF0ZSA9IGZhbHNlOwogICAgfTsKCiAgICBfcHJvdG82MS5nZXREZXN0cnVjdG9yID0gZnVuY3Rpb24gZ2V0RGVzdHJ1Y3RvcihzdGF0ZSkgewogICAgICByZXR1cm4gc3RhdGU7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoT25Nb2RpZmllck1hbmFnZXIsIFt7CiAgICAgIGtleTogImNvdW50ZXJzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGFkZHM6IGFkZHMsCiAgICAgICAgICByZW1vdmVzOiByZW1vdmVzCiAgICAgICAgfTsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIE9uTW9kaWZpZXJNYW5hZ2VyOwogIH0oKTsKCiAgZnVuY3Rpb24gaGFzaFRvQXJncyhoYXNoKSB7CiAgICBpZiAoaGFzaCA9PT0gbnVsbCkgcmV0dXJuIG51bGw7CiAgICB2YXIgbmFtZXMgPSBoYXNoWzBdLm1hcChmdW5jdGlvbiAoa2V5KSB7CiAgICAgIHJldHVybiAiQCIgKyBrZXk7CiAgICB9KTsKICAgIHJldHVybiBbbmFtZXMsIGhhc2hbMV1dOwogIH0KICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICAgIFRoZSBgbGV0YCBoZWxwZXIgcmVjZWl2ZXMgb25lIG9yIG1vcmUgcG9zaXRpb25hbCBhcmd1bWVudHMgYW5kIHlpZWxkcwogICAgICB0aGVtIG91dCBhcyBibG9jayBwYXJhbXMuCiAgCiAgICAgIFRoaXMgYWxsb3dzIHRoZSBkZXZlbG9wZXIgdG8gaW50cm9kdWNlIHNob3J0ZXIgbmFtZXMgZm9yIGNlcnRhaW4gY29tcHV0YXRpb25zCiAgICAgIGluIHRoZSB0ZW1wbGF0ZS4KICAKICAgICAgVGhpcyBpcyBlc3BlY2lhbGx5IHVzZWZ1bCBpZiB5b3UgYXJlIHBhc3NpbmcgcHJvcGVydGllcyB0byBhIGNvbXBvbmVudAogICAgICB0aGF0IHJlY2VpdmVzIGEgbG90IG9mIG9wdGlvbnMgYW5kIHlvdSB3YW50IHRvIGNsZWFuIHVwIHRoZSBpbnZvY2F0aW9uLgogIAogICAgICBGb3IgdGhlIGZvbGxvd2luZyBleGFtcGxlLCB0aGUgdGVtcGxhdGUgcmVjZWl2ZXMgYSBgcG9zdGAgb2JqZWN0IHdpdGgKICAgICAgYGNvbnRlbnRgIGFuZCBgdGl0bGVgIHByb3BlcnRpZXMuCiAgCiAgICAgIFdlIGFyZSBnb2luZyB0byBjYWxsIHRoZSBgbXktcG9zdGAgY29tcG9uZW50LCBwYXNzaW5nIGEgdGl0bGUgd2hpY2ggaXMKICAgICAgdGhlIHRpdGxlIG9mIHRoZSBwb3N0IHN1ZmZpeGVkIHdpdGggdGhlIG5hbWUgb2YgdGhlIGJsb2csIHRoZSBjb250ZW50CiAgICAgIG9mIHRoZSBwb3N0LCBhbmQgYSBzZXJpZXMgb2Ygb3B0aW9ucyBkZWZpbmVkIGluLXBsYWNlLgogIAogICAgICBgYGBoYW5kbGViYXJzCiAgICAgIHt7I2xldAogICAgICAgICAgKGNvbmNhdCBwb3N0LnRpdGxlICcgfCBUaGUgRW1iZXIuanMgQmxvZycpCiAgICAgICAgICBwb3N0LmNvbnRlbnQKICAgICAgICAgIChoYXNoCiAgICAgICAgICAgIHRoZW1lPSJoaWdoLWNvbnRyYXN0IgogICAgICAgICAgICBlbmFibGVDb21tZW50cz10cnVlCiAgICAgICAgICApCiAgICAgICAgICBhcyB8dGl0bGUgY29udGVudCBvcHRpb25zfAogICAgICB9fQogICAgICAgIDxNeVBvc3QgQHRpdGxlPXt7dGl0bGV9fSBAY29udGVudD17e2NvbnRlbnR9fSBAb3B0aW9ucz17e29wdGlvbnN9fSAvPgogICAgICB7ey9sZXR9fQogICAgYGBgCiAgIG9yCiAgICBgYGBoYW5kbGViYXJzCiAgICAgIHt7I2xldAogICAgICAgICAgKGNvbmNhdCBwb3N0LnRpdGxlICcgfCBUaGUgRW1iZXIuanMgQmxvZycpCiAgICAgICAgICBwb3N0LmNvbnRlbnQKICAgICAgICAgIChoYXNoCiAgICAgICAgICAgIHRoZW1lPSJoaWdoLWNvbnRyYXN0IgogICAgICAgICAgICBlbmFibGVDb21tZW50cz10cnVlCiAgICAgICAgICApCiAgICAgICAgICBhcyB8dGl0bGUgY29udGVudCBvcHRpb25zfAogICAgICB9fQogICAgICAgIHt7bXktcG9zdCB0aXRsZT10aXRsZSBjb250ZW50PWNvbnRlbnQgb3B0aW9ucz1vcHRpb25zfX0KICAgICAge3svbGV0fX0KICAgIGBgYAogIAogICAgQG1ldGhvZCBsZXQKICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gYmxvY2tMZXRNYWNybyhwYXJhbXMsIF9oYXNoLCB0ZW1wbGF0ZSwgX2ludmVyc2UsIGJ1aWxkZXIpIHsKICAgIGlmICh0ZW1wbGF0ZSAhPT0gbnVsbCkgewogICAgICBpZiAocGFyYW1zICE9PSBudWxsKSB7CiAgICAgICAgYnVpbGRlci5jb21waWxlUGFyYW1zKHBhcmFtcyk7CiAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNCbG9jayh0ZW1wbGF0ZSwgcGFyYW1zLmxlbmd0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWModGVtcGxhdGUpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHRydWU7CiAgfQoKICB2YXIgQ0FQQUJJTElUSUVTJDQgPSB7CiAgICBkeW5hbWljTGF5b3V0OiB0cnVlLAogICAgZHluYW1pY1RhZzogZmFsc2UsCiAgICBwcmVwYXJlQXJnczogZmFsc2UsCiAgICBjcmVhdGVBcmdzOiBmYWxzZSwKICAgIGF0dHJpYnV0ZUhvb2s6IGZhbHNlLAogICAgZWxlbWVudEhvb2s6IGZhbHNlLAogICAgY3JlYXRlQ2FsbGVyOiB0cnVlLAogICAgZHluYW1pY1Njb3BlOiB0cnVlLAogICAgdXBkYXRlSG9vazogdHJ1ZSwKICAgIGNyZWF0ZUluc3RhbmNlOiB0cnVlCiAgfTsKCiAgdmFyIE1vdW50TWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQWJzdHJhY3RNYW5hZ2VyNikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE1vdW50TWFuYWdlciwgX0Fic3RyYWN0TWFuYWdlcjYpOwoKICAgIGZ1bmN0aW9uIE1vdW50TWFuYWdlcigpIHsKICAgICAgcmV0dXJuIF9BYnN0cmFjdE1hbmFnZXI2LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjIgPSBNb3VudE1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzYyLmdldER5bmFtaWNMYXlvdXQgPSBmdW5jdGlvbiBnZXREeW5hbWljTGF5b3V0KHN0YXRlLCBfKSB7CiAgICAgIHZhciB0ZW1wbGF0ZUZhY3RvcnkkJDEgPSBzdGF0ZS5lbmdpbmUubG9va3VwKCd0ZW1wbGF0ZTphcHBsaWNhdGlvbicpOwogICAgICB2YXIgdGVtcGxhdGUgPSB0ZW1wbGF0ZUZhY3RvcnkkJDEoc3RhdGUuZW5naW5lKTsKICAgICAgdmFyIGxheW91dCA9IHRlbXBsYXRlLmFzTGF5b3V0KCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiBsYXlvdXQuY29tcGlsZSgpLAogICAgICAgIHN5bWJvbFRhYmxlOiBsYXlvdXQuc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvNjIuZ2V0Q2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gZ2V0Q2FwYWJpbGl0aWVzKCkgewogICAgICByZXR1cm4gQ0FQQUJJTElUSUVTJDQ7CiAgICB9OwoKICAgIF9wcm90bzYyLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShlbnZpcm9ubWVudCwgc3RhdGUpIHsKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuX3B1c2hFbmdpbmVUb0RlYnVnU3RhY2soImVuZ2luZToiICsgc3RhdGUubmFtZSwgZW52aXJvbm1lbnQpOwogICAgICB9IC8vIFRPRE8KICAgICAgLy8gbW91bnQgaXMgYSBydW50aW1lIGhlbHBlciwgdGhpcyBzaG91bGRuJ3QgdXNlIGR5bmFtaWMgbGF5b3V0CiAgICAgIC8vIHdlIHNob3VsZCByZXNvbHZlIHRoZSBlbmdpbmUgYXBwIHRlbXBsYXRlIGluIHRoZSBoZWxwZXIKICAgICAgLy8gaXQgYWxzbyBzaG91bGQgdXNlIHRoZSBvd25lciB0aGF0IGxvb2tlZCB1cCB0aGUgbW91bnQgaGVscGVyLgoKCiAgICAgIHZhciBlbmdpbmUgPSBlbnZpcm9ubWVudC5vd25lci5idWlsZENoaWxkRW5naW5lSW5zdGFuY2Uoc3RhdGUubmFtZSk7CiAgICAgIGVuZ2luZS5ib290KCk7CiAgICAgIHZhciBhcHBsaWNhdGlvbkZhY3RvcnkgPSBlbmdpbmUuZmFjdG9yeUZvcigiY29udHJvbGxlcjphcHBsaWNhdGlvbiIpOwogICAgICB2YXIgY29udHJvbGxlckZhY3RvcnkgPSBhcHBsaWNhdGlvbkZhY3RvcnkgfHwgKDAsIF9yb3V0aW5nLmdlbmVyYXRlQ29udHJvbGxlckZhY3RvcnkpKGVuZ2luZSwgJ2FwcGxpY2F0aW9uJyk7CiAgICAgIHZhciBjb250cm9sbGVyOwogICAgICB2YXIgc2VsZjsKICAgICAgdmFyIGJ1Y2tldDsKICAgICAgdmFyIHRhZzsKICAgICAgdmFyIG1vZGVsUmVmID0gc3RhdGUubW9kZWxSZWY7CgogICAgICBpZiAobW9kZWxSZWYgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGNvbnRyb2xsZXIgPSBjb250cm9sbGVyRmFjdG9yeS5jcmVhdGUoKTsKICAgICAgICBzZWxmID0gbmV3IFJvb3RSZWZlcmVuY2UoY29udHJvbGxlcik7CiAgICAgICAgdGFnID0gX3JlZmVyZW5jZS5DT05TVEFOVF9UQUc7CiAgICAgICAgYnVja2V0ID0gewogICAgICAgICAgZW5naW5lOiBlbmdpbmUsCiAgICAgICAgICBjb250cm9sbGVyOiBjb250cm9sbGVyLAogICAgICAgICAgc2VsZjogc2VsZiwKICAgICAgICAgIHRhZzogdGFnCiAgICAgICAgfTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgbW9kZWwgPSBtb2RlbFJlZi52YWx1ZSgpOwogICAgICAgIHZhciBtb2RlbFJldiA9ICgwLCBfcmVmZXJlbmNlLnZhbHVlKShtb2RlbFJlZi50YWcpOwogICAgICAgIGNvbnRyb2xsZXIgPSBjb250cm9sbGVyRmFjdG9yeS5jcmVhdGUoewogICAgICAgICAgbW9kZWw6IG1vZGVsCiAgICAgICAgfSk7CiAgICAgICAgc2VsZiA9IG5ldyBSb290UmVmZXJlbmNlKGNvbnRyb2xsZXIpOwogICAgICAgIHRhZyA9IG1vZGVsUmVmLnRhZzsKICAgICAgICBidWNrZXQgPSB7CiAgICAgICAgICBlbmdpbmU6IGVuZ2luZSwKICAgICAgICAgIGNvbnRyb2xsZXI6IGNvbnRyb2xsZXIsCiAgICAgICAgICBzZWxmOiBzZWxmLAogICAgICAgICAgdGFnOiB0YWcsCiAgICAgICAgICBtb2RlbFJlZjogbW9kZWxSZWYsCiAgICAgICAgICBtb2RlbFJldjogbW9kZWxSZXYKICAgICAgICB9OwogICAgICB9CgogICAgICByZXR1cm4gYnVja2V0OwogICAgfTsKCiAgICBfcHJvdG82Mi5nZXRTZWxmID0gZnVuY3Rpb24gZ2V0U2VsZihfcmVmMzQpIHsKICAgICAgdmFyIHNlbGYgPSBfcmVmMzQuc2VsZjsKICAgICAgcmV0dXJuIHNlbGY7CiAgICB9OwoKICAgIF9wcm90bzYyLmdldFRhZyA9IGZ1bmN0aW9uIGdldFRhZyhzdGF0ZSkgewogICAgICByZXR1cm4gc3RhdGUudGFnOwogICAgfTsKCiAgICBfcHJvdG82Mi5nZXREZXN0cnVjdG9yID0gZnVuY3Rpb24gZ2V0RGVzdHJ1Y3RvcihfcmVmMzUpIHsKICAgICAgdmFyIGVuZ2luZSA9IF9yZWYzNS5lbmdpbmU7CiAgICAgIHJldHVybiBlbmdpbmU7CiAgICB9OwoKICAgIF9wcm90bzYyLmRpZFJlbmRlckxheW91dCA9IGZ1bmN0aW9uIGRpZFJlbmRlckxheW91dCgpIHsKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuZGVidWdTdGFjay5wb3AoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG82Mi51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoYnVja2V0KSB7CiAgICAgIHZhciBjb250cm9sbGVyID0gYnVja2V0LmNvbnRyb2xsZXIsCiAgICAgICAgICBtb2RlbFJlZiA9IGJ1Y2tldC5tb2RlbFJlZiwKICAgICAgICAgIG1vZGVsUmV2ID0gYnVja2V0Lm1vZGVsUmV2OwoKICAgICAgaWYgKCEoMCwgX3JlZmVyZW5jZS52YWxpZGF0ZSkobW9kZWxSZWYudGFnLCBtb2RlbFJldikpIHsKICAgICAgICB2YXIgbW9kZWwgPSBtb2RlbFJlZi52YWx1ZSgpOwogICAgICAgIGJ1Y2tldC5tb2RlbFJldiA9ICgwLCBfcmVmZXJlbmNlLnZhbHVlKShtb2RlbFJlZi50YWcpOwogICAgICAgIGNvbnRyb2xsZXIuc2V0KCdtb2RlbCcsIG1vZGVsKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gTW91bnRNYW5hZ2VyOwogIH0oQWJzdHJhY3RNYW5hZ2VyKTsKCiAgdmFyIE1PVU5UX01BTkFHRVIgPSBuZXcgTW91bnRNYW5hZ2VyKCk7CgogIHZhciBNb3VudERlZmluaXRpb24gPSBmdW5jdGlvbiBNb3VudERlZmluaXRpb24obmFtZSwgbW9kZWxSZWYpIHsKICAgIHRoaXMubWFuYWdlciA9IE1PVU5UX01BTkFHRVI7CiAgICB0aGlzLnN0YXRlID0gewogICAgICBuYW1lOiBuYW1lLAogICAgICBtb2RlbFJlZjogbW9kZWxSZWYKICAgIH07CiAgfTsKCiAgZnVuY3Rpb24gbW91bnRIZWxwZXIodm0sIGFyZ3MpIHsKICAgIHZhciBlbnYgPSB2bS5lbnY7CiAgICB2YXIgbmFtZVJlZiA9IGFyZ3MucG9zaXRpb25hbC5hdCgwKTsKICAgIHZhciBtb2RlbFJlZiA9IGFyZ3MubmFtZWQuaGFzKCdtb2RlbCcpID8gYXJncy5uYW1lZC5nZXQoJ21vZGVsJykgOiB1bmRlZmluZWQ7CiAgICByZXR1cm4gbmV3IER5bmFtaWNFbmdpbmVSZWZlcmVuY2UobmFtZVJlZiwgZW52LCBtb2RlbFJlZik7CiAgfQogIC8qKgogICAgVGhlIGB7e21vdW50fX1gIGhlbHBlciBsZXRzIHlvdSBlbWJlZCBhIHJvdXRlbGVzcyBlbmdpbmUgaW4gYSB0ZW1wbGF0ZS4KICAgIE1vdW50aW5nIGFuIGVuZ2luZSB3aWxsIGNhdXNlIGFuIGluc3RhbmNlIHRvIGJlIGJvb3RlZCBhbmQgaXRzIGBhcHBsaWNhdGlvbmAKICAgIHRlbXBsYXRlIHRvIGJlIHJlbmRlcmVkLgogIAogICAgRm9yIGV4YW1wbGUsIHRoZSBmb2xsb3dpbmcgdGVtcGxhdGUgbW91bnRzIHRoZSBgZW1iZXItY2hhdGAgZW5naW5lOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3shIGFwcGxpY2F0aW9uLmhicyB9fQogICAge3ttb3VudCAiZW1iZXItY2hhdCJ9fQogICAgYGBgCiAgCiAgICBBZGRpdGlvbmFsbHksIHlvdSBjYW4gYWxzbyBwYXNzIGluIGEgYG1vZGVsYCBhcmd1bWVudCB0aGF0IHdpbGwgYmUKICAgIHNldCBhcyB0aGUgZW5naW5lcyBtb2RlbC4gVGhpcyBjYW4gYmUgYW4gZXhpc3Rpbmcgb2JqZWN0OgogIAogICAgYGBgCiAgICA8ZGl2PgogICAgICB7e21vdW50ICdhZG1pbicgbW9kZWw9dXNlclNldHRpbmdzfX0KICAgIDwvZGl2PgogICAgYGBgCiAgCiAgICBPciBhbiBpbmxpbmUgYGhhc2hgLCBhbmQgeW91IGNhbiBldmVuIHBhc3MgY29tcG9uZW50czoKICAKICAgIGBgYAogICAgPGRpdj4KICAgICAgPGgxPkFwcGxpY2F0aW9uIHRlbXBsYXRlITwvaDE+CiAgICAgIHt7bW91bnQgJ2FkbWluJyBtb2RlbD0oaGFzaAogICAgICAgICAgdGl0bGU9J1NlY3JldCBBZG1pbicKICAgICAgICAgIHNpZ25JbkJ1dHRvbj0oY29tcG9uZW50ICdzaWduLWluLWJ1dHRvbicpCiAgICAgICl9fQogICAgPC9kaXY+CiAgICBgYGAKICAKICAgIEBtZXRob2QgbW91bnQKICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIGVuZ2luZSB0byBtb3VudC4KICAgIEBwYXJhbSB7T2JqZWN0fSBbbW9kZWxdIE9iamVjdCB0aGF0IHdpbGwgYmUgc2V0IGFzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgbW9kZWwgb2YgdGhlIGVuZ2luZS4KICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbW91bnRNYWNybyhfbmFtZSwgcGFyYW1zLCBoYXNoLCBidWlsZGVyKSB7CiAgICAoZmFsc2UgJiYgIShwYXJhbXMubGVuZ3RoID09PSAxKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW4gb25seSBwYXNzIGEgc2luZ2xlIHBvc2l0aW9uYWwgYXJndW1lbnQgdG8gdGhlIHt7bW91bnR9fSBoZWxwZXIsIGUuZy4ge3ttb3VudCAiY2hhdC1lbmdpbmUifX0uJywgcGFyYW1zLmxlbmd0aCA9PT0gMSkpOwogICAgdmFyIGV4cHIgPSBbX3dpcmVGb3JtYXQuT3BzLkhlbHBlciwgJy1tb3VudCcsIHBhcmFtcyB8fCBbXSwgaGFzaF07CiAgICBidWlsZGVyLmR5bmFtaWNDb21wb25lbnQoZXhwciwgbnVsbCwgW10sIG51bGwsIGZhbHNlLCBudWxsLCBudWxsKTsKICAgIHJldHVybiB0cnVlOwogIH0KCiAgdmFyIER5bmFtaWNFbmdpbmVSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBEeW5hbWljRW5naW5lUmVmZXJlbmNlKG5hbWVSZWYsIGVudiwgbW9kZWxSZWYpIHsKICAgICAgdGhpcy50YWcgPSBuYW1lUmVmLnRhZzsKICAgICAgdGhpcy5uYW1lUmVmID0gbmFtZVJlZjsKICAgICAgdGhpcy5tb2RlbFJlZiA9IG1vZGVsUmVmOwogICAgICB0aGlzLmVudiA9IGVudjsKICAgICAgdGhpcy5fbGFzdE5hbWUgPSBudWxsOwogICAgICB0aGlzLl9sYXN0RGVmID0gbnVsbDsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjMgPSBEeW5hbWljRW5naW5lUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG82My52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICB2YXIgZW52ID0gdGhpcy5lbnYsCiAgICAgICAgICBuYW1lUmVmID0gdGhpcy5uYW1lUmVmLAogICAgICAgICAgbW9kZWxSZWYgPSB0aGlzLm1vZGVsUmVmOwogICAgICB2YXIgbmFtZSA9IG5hbWVSZWYudmFsdWUoKTsKCiAgICAgIGlmICh0eXBlb2YgbmFtZSA9PT0gJ3N0cmluZycpIHsKICAgICAgICBpZiAodGhpcy5fbGFzdE5hbWUgPT09IG5hbWUpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9sYXN0RGVmOwogICAgICAgIH0KCiAgICAgICAgKGZhbHNlICYmICEoZW52Lm93bmVyLmhhc1JlZ2lzdHJhdGlvbigiZW5naW5lOiIgKyBuYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgdXNlZCBge3ttb3VudCAnIiArIG5hbWUgKyAiJ319YCwgYnV0IHRoZSBlbmdpbmUgJyIgKyBuYW1lICsgIicgY2FuIG5vdCBiZSBmb3VuZC4iLCBlbnYub3duZXIuaGFzUmVnaXN0cmF0aW9uKCJlbmdpbmU6IiArIG5hbWUpKSk7CgogICAgICAgIGlmICghZW52Lm93bmVyLmhhc1JlZ2lzdHJhdGlvbigiZW5naW5lOiIgKyBuYW1lKSkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQoKICAgICAgICB0aGlzLl9sYXN0TmFtZSA9IG5hbWU7CiAgICAgICAgdGhpcy5fbGFzdERlZiA9ICgwLCBfcnVudGltZTIuY3VycnkpKG5ldyBNb3VudERlZmluaXRpb24obmFtZSwgbW9kZWxSZWYpKTsKICAgICAgICByZXR1cm4gdGhpcy5fbGFzdERlZjsKICAgICAgfSBlbHNlIHsKICAgICAgICAoZmFsc2UgJiYgIShuYW1lID09PSBudWxsIHx8IG5hbWUgPT09IHVuZGVmaW5lZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJJbnZhbGlkIGVuZ2luZSBuYW1lICciICsgbmFtZSArICInIHNwZWNpZmllZCwgZW5naW5lIG5hbWUgbXVzdCBiZSBlaXRoZXIgYSBzdHJpbmcsIG51bGwgb3IgdW5kZWZpbmVkLiIsIG5hbWUgPT09IG51bGwgfHwgbmFtZSA9PT0gdW5kZWZpbmVkKSk7CiAgICAgICAgdGhpcy5fbGFzdERlZiA9IG51bGw7CiAgICAgICAgdGhpcy5fbGFzdE5hbWUgPSBudWxsOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzYzLmdldCA9IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9ydW50aW1lMi5VTkRFRklORURfUkVGRVJFTkNFOwogICAgfTsKCiAgICByZXR1cm4gRHluYW1pY0VuZ2luZVJlZmVyZW5jZTsKICB9KCk7CiAgLyoqCiAgICogUmVwcmVzZW50cyB0aGUgcm9vdCBvdXRsZXQuCiAgICovCgoKICB2YXIgUm9vdE91dGxldFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJvb3RPdXRsZXRSZWZlcmVuY2Uob3V0bGV0U3RhdGUpIHsKICAgICAgdGhpcy5vdXRsZXRTdGF0ZSA9IG91dGxldFN0YXRlOwogICAgICB0aGlzLnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVRhZykoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjQgPSBSb290T3V0bGV0UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG82NC5nZXQgPSBmdW5jdGlvbiBnZXQoa2V5KSB7CiAgICAgIHJldHVybiBuZXcgUGF0aFJlZmVyZW5jZSh0aGlzLCBrZXkpOwogICAgfTsKCiAgICBfcHJvdG82NC52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICByZXR1cm4gdGhpcy5vdXRsZXRTdGF0ZTsKICAgIH07CgogICAgX3Byb3RvNjQudXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKHN0YXRlKSB7CiAgICAgIHRoaXMub3V0bGV0U3RhdGUub3V0bGV0cy5tYWluID0gc3RhdGU7CiAgICAgICgwLCBfcmVmZXJlbmNlLmRpcnR5KSh0aGlzLnRhZyk7CiAgICB9OwoKICAgIHJldHVybiBSb290T3V0bGV0UmVmZXJlbmNlOwogIH0oKTsKICAvKioKICAgKiBSZXByZXNlbnRzIHRoZSBjb25uZWN0ZWQgb3V0bGV0LgogICAqLwoKCiAgdmFyIE91dGxldFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIE91dGxldFJlZmVyZW5jZShwYXJlbnRTdGF0ZVJlZiwgb3V0bGV0TmFtZVJlZikgewogICAgICB0aGlzLnBhcmVudFN0YXRlUmVmID0gcGFyZW50U3RhdGVSZWY7CiAgICAgIHRoaXMub3V0bGV0TmFtZVJlZiA9IG91dGxldE5hbWVSZWY7CiAgICAgIHRoaXMudGFnID0gKDAsIF9yZWZlcmVuY2UuY29tYmluZSkoW3BhcmVudFN0YXRlUmVmLnRhZywgb3V0bGV0TmFtZVJlZi50YWddKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjUgPSBPdXRsZXRSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzY1LnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHZhciBvdXRsZXRTdGF0ZSA9IHRoaXMucGFyZW50U3RhdGVSZWYudmFsdWUoKTsKICAgICAgdmFyIG91dGxldHMgPSBvdXRsZXRTdGF0ZSA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogb3V0bGV0U3RhdGUub3V0bGV0czsKICAgICAgcmV0dXJuIG91dGxldHMgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IG91dGxldHNbdGhpcy5vdXRsZXROYW1lUmVmLnZhbHVlKCldOwogICAgfTsKCiAgICBfcHJvdG82NS5nZXQgPSBmdW5jdGlvbiBnZXQoa2V5KSB7CiAgICAgIHJldHVybiBuZXcgUGF0aFJlZmVyZW5jZSh0aGlzLCBrZXkpOwogICAgfTsKCiAgICByZXR1cm4gT3V0bGV0UmVmZXJlbmNlOwogIH0oKTsKICAvKioKICAgKiBPdXRsZXQgc3RhdGUgaXMgZGlydGllZCBmcm9tIHJvb3QuCiAgICogVGhpcyBqdXN0IHVzaW5nIHRoZSBwYXJlbnQgdGFnIGZvciBkaXJ0aW5lc3MuCiAgICovCgoKICB2YXIgUGF0aFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFBhdGhSZWZlcmVuY2UocGFyZW50LCBrZXkpIHsKICAgICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7CiAgICAgIHRoaXMua2V5ID0ga2V5OwogICAgICB0aGlzLnRhZyA9IHBhcmVudC50YWc7CiAgICB9CgogICAgdmFyIF9wcm90bzY2ID0gUGF0aFJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNjYuZ2V0ID0gZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICByZXR1cm4gbmV3IFBhdGhSZWZlcmVuY2UodGhpcywga2V5KTsKICAgIH07CgogICAgX3Byb3RvNjYudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgdmFyIHBhcmVudCA9IHRoaXMucGFyZW50LnZhbHVlKCk7CiAgICAgIHJldHVybiBwYXJlbnQgJiYgcGFyZW50W3RoaXMua2V5XTsKICAgIH07CgogICAgcmV0dXJuIFBhdGhSZWZlcmVuY2U7CiAgfSgpOwogIC8qKgogICAgVGhlIGB7e291dGxldH19YCBoZWxwZXIgbGV0cyB5b3Ugc3BlY2lmeSB3aGVyZSBhIGNoaWxkIHJvdXRlIHdpbGwgcmVuZGVyIGluCiAgICB5b3VyIHRlbXBsYXRlLiBBbiBpbXBvcnRhbnQgdXNlIG9mIHRoZSBge3tvdXRsZXR9fWAgaGVscGVyIGlzIGluIHlvdXIKICAgIGFwcGxpY2F0aW9uJ3MgYGFwcGxpY2F0aW9uLmhic2AgZmlsZToKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7ISBhcHAvdGVtcGxhdGVzL2FwcGxpY2F0aW9uLmhicyB9fQogICAgPCEtLSBoZWFkZXIgY29udGVudCBnb2VzIGhlcmUsIGFuZCB3aWxsIGFsd2F5cyBkaXNwbGF5IC0tPgogICAgPE15SGVhZGVyIC8+CiAgICA8ZGl2IGNsYXNzPSJteS1keW5hbWljLWNvbnRlbnQiPgogICAgICA8IS0tIHRoaXMgY29udGVudCB3aWxsIGNoYW5nZSBiYXNlZCBvbiB0aGUgY3VycmVudCByb3V0ZSwgd2hpY2ggZGVwZW5kcyBvbiB0aGUgY3VycmVudCBVUkwgLS0+CiAgICAgIHt7b3V0bGV0fX0KICAgIDwvZGl2PgogICAgPCEtLSBmb290ZXIgY29udGVudCBnb2VzIGhlcmUsIGFuZCB3aWxsIGFsd2F5cyBkaXNwbGF5IC0tPgogICAgPE15Rm9vdGVyIC8+CiAgICBgYGAKICAKICAgIFlvdSBtYXkgYWxzbyBzcGVjaWZ5IGEgbmFtZSBmb3IgdGhlIGB7e291dGxldH19YCwgd2hpY2ggaXMgdXNlZnVsIHdoZW4gdXNpbmcgbW9yZSB0aGFuIG9uZQogICAgYHt7b3V0bGV0fX1gIGluIGEgdGVtcGxhdGU6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e291dGxldCAibWVudSJ9fQogICAge3tvdXRsZXQgInNpZGViYXIifX0KICAgIHt7b3V0bGV0ICJtYWluIn19CiAgICBgYGAKICAKICAgIFlvdXIgcm91dGVzIGNhbiB0aGVuIHJlbmRlciBpbnRvIGEgc3BlY2lmaWMgb25lIG9mIHRoZXNlIGBvdXRsZXRgcyBieSBzcGVjaWZ5aW5nIHRoZSBgb3V0bGV0YAogICAgYXR0cmlidXRlIGluIHlvdXIgYHJlbmRlclRlbXBsYXRlYCBmdW5jdGlvbjoKICAKICAgIGBgYGFwcC9yb3V0ZXMvbWVudS5qcwogICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgIHJlbmRlclRlbXBsYXRlKCkgewogICAgICAgIHRoaXMucmVuZGVyKHsgb3V0bGV0OiAnbWVudScgfSk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBTZWUgdGhlIFtyb3V0aW5nIGd1aWRlXShodHRwczovL2d1aWRlcy5lbWJlcmpzLmNvbS9yZWxlYXNlL3JvdXRpbmcvcmVuZGVyaW5nLWEtdGVtcGxhdGUvKSBmb3IgbW9yZQogICAgaW5mb3JtYXRpb24gb24gaG93IHlvdXIgYHJvdXRlYCBpbnRlcmFjdHMgd2l0aCB0aGUgYHt7b3V0bGV0fX1gIGhlbHBlci4KICAgIE5vdGU6IFlvdXIgY29udGVudCBfX3dpbGwgbm90IHJlbmRlcl9fIGlmIHRoZXJlIGlzbid0IGFuIGB7e291dGxldH19YCBmb3IgaXQuCiAgCiAgICBAbWV0aG9kIG91dGxldAogICAgQHBhcmFtIHtTdHJpbmd9IFtuYW1lXQogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBvdXRsZXRIZWxwZXIodm0sIGFyZ3MpIHsKICAgIHZhciBzY29wZSA9IHZtLmR5bmFtaWNTY29wZSgpOwogICAgdmFyIG5hbWVSZWY7CgogICAgaWYgKGFyZ3MucG9zaXRpb25hbC5sZW5ndGggPT09IDApIHsKICAgICAgbmFtZVJlZiA9IG5ldyBfcmVmZXJlbmNlLkNvbnN0UmVmZXJlbmNlKCdtYWluJyk7CiAgICB9IGVsc2UgewogICAgICBuYW1lUmVmID0gYXJncy5wb3NpdGlvbmFsLmF0KDApOwogICAgfQoKICAgIHJldHVybiBuZXcgT3V0bGV0Q29tcG9uZW50UmVmZXJlbmNlKG5ldyBPdXRsZXRSZWZlcmVuY2Uoc2NvcGUub3V0bGV0U3RhdGUsIG5hbWVSZWYpKTsKICB9CgogIGZ1bmN0aW9uIG91dGxldE1hY3JvKF9uYW1lLCBwYXJhbXMsIGhhc2gsIGJ1aWxkZXIpIHsKICAgIHZhciBleHByID0gW193aXJlRm9ybWF0Lk9wcy5IZWxwZXIsICctb3V0bGV0JywgcGFyYW1zIHx8IFtdLCBoYXNoXTsKICAgIGJ1aWxkZXIuZHluYW1pY0NvbXBvbmVudChleHByLCBudWxsLCBbXSwgbnVsbCwgZmFsc2UsIG51bGwsIG51bGwpOwogICAgcmV0dXJuIHRydWU7CiAgfQoKICB2YXIgT3V0bGV0Q29tcG9uZW50UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gT3V0bGV0Q29tcG9uZW50UmVmZXJlbmNlKG91dGxldFJlZikgewogICAgICB0aGlzLm91dGxldFJlZiA9IG91dGxldFJlZjsKICAgICAgdGhpcy5kZWZpbml0aW9uID0gbnVsbDsKICAgICAgdGhpcy5sYXN0U3RhdGUgPSBudWxsOyAvLyBUaGUgcm91dGVyIGFsd2F5cyBkaXJ0aWVzIHRoZSByb290IHN0YXRlLgoKICAgICAgdGhpcy50YWcgPSBvdXRsZXRSZWYudGFnOwogICAgfQoKICAgIHZhciBfcHJvdG82NyA9IE91dGxldENvbXBvbmVudFJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNjcudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgdmFyIHN0YXRlID0gc3RhdGVGb3IodGhpcy5vdXRsZXRSZWYpOwoKICAgICAgaWYgKHZhbGlkYXRlJDEoc3RhdGUsIHRoaXMubGFzdFN0YXRlKSkgewogICAgICAgIHJldHVybiB0aGlzLmRlZmluaXRpb247CiAgICAgIH0KCiAgICAgIHRoaXMubGFzdFN0YXRlID0gc3RhdGU7CiAgICAgIHZhciBkZWZpbml0aW9uID0gbnVsbDsKCiAgICAgIGlmIChzdGF0ZSAhPT0gbnVsbCkgewogICAgICAgIGRlZmluaXRpb24gPSAoMCwgX3J1bnRpbWUyLmN1cnJ5KShuZXcgT3V0bGV0Q29tcG9uZW50RGVmaW5pdGlvbihzdGF0ZSkpOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5kZWZpbml0aW9uID0gZGVmaW5pdGlvbjsKICAgIH07CgogICAgX3Byb3RvNjcuZ2V0ID0gZnVuY3Rpb24gZ2V0KF9rZXkpIHsKICAgICAgcmV0dXJuIF9ydW50aW1lMi5VTkRFRklORURfUkVGRVJFTkNFOwogICAgfTsKCiAgICByZXR1cm4gT3V0bGV0Q29tcG9uZW50UmVmZXJlbmNlOwogIH0oKTsKCiAgZnVuY3Rpb24gc3RhdGVGb3IocmVmKSB7CiAgICB2YXIgb3V0bGV0ID0gcmVmLnZhbHVlKCk7CiAgICBpZiAob3V0bGV0ID09PSB1bmRlZmluZWQpIHJldHVybiBudWxsOwogICAgdmFyIHJlbmRlciA9IG91dGxldC5yZW5kZXI7CiAgICBpZiAocmVuZGVyID09PSB1bmRlZmluZWQpIHJldHVybiBudWxsOwogICAgdmFyIHRlbXBsYXRlJCQxID0gcmVuZGVyLnRlbXBsYXRlOwogICAgaWYgKHRlbXBsYXRlJCQxID09PSB1bmRlZmluZWQpIHJldHVybiBudWxsOyAvLyB0aGlzIGd1YXJkIGNhbiBiZSByZW1vdmVkIG9uY2UgQGVtYmVyL3Rlc3QtaGVscGVyc0AxLjYuMCBoYXMgImFnZWQgb3V0IgogICAgLy8gYW5kIGlzIG5vIGxvbmdlciBjb25zaWRlcmVkIHN1cHBvcnRlZAoKICAgIGlmIChpc1RlbXBsYXRlRmFjdG9yeSh0ZW1wbGF0ZSQkMSkpIHsKICAgICAgdGVtcGxhdGUkJDEgPSB0ZW1wbGF0ZSQkMShyZW5kZXIub3duZXIpOwogICAgfQoKICAgIHJldHVybiB7CiAgICAgIHJlZjogcmVmLAogICAgICBuYW1lOiByZW5kZXIubmFtZSwKICAgICAgb3V0bGV0OiByZW5kZXIub3V0bGV0LAogICAgICB0ZW1wbGF0ZTogdGVtcGxhdGUkJDEsCiAgICAgIGNvbnRyb2xsZXI6IHJlbmRlci5jb250cm9sbGVyCiAgICB9OwogIH0KCiAgZnVuY3Rpb24gdmFsaWRhdGUkMShzdGF0ZSwgbGFzdFN0YXRlKSB7CiAgICBpZiAoc3RhdGUgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIGxhc3RTdGF0ZSA9PT0gbnVsbDsKICAgIH0KCiAgICBpZiAobGFzdFN0YXRlID09PSBudWxsKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICByZXR1cm4gc3RhdGUudGVtcGxhdGUgPT09IGxhc3RTdGF0ZS50ZW1wbGF0ZSAmJiBzdGF0ZS5jb250cm9sbGVyID09PSBsYXN0U3RhdGUuY29udHJvbGxlcjsKICB9CgogIGZ1bmN0aW9uIHJlZmluZUlubGluZVN5bnRheChuYW1lLCBwYXJhbXMsIGhhc2gsIGJ1aWxkZXIpIHsKICAgIChmYWxzZSAmJiAhKCEoYnVpbGRlci5jb21waWxlclsncmVzb2x2ZXInXVsncmVzb2x2ZXInXVsnYnVpbHRJbkhlbHBlcnMnXVtuYW1lXSAmJiBidWlsZGVyLnJlZmVycmVyLm93bmVyLmhhc1JlZ2lzdHJhdGlvbigiaGVscGVyOiIgKyBuYW1lKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byBvdmVyd3JpdGUgdGhlIGJ1aWx0LWluIGhlbHBlciBcIiIgKyBuYW1lICsgIlwiIHdoaWNoIGlzIG5vdCBhbGxvd2VkLiBQbGVhc2UgcmVuYW1lIHRoZSBoZWxwZXIuIiwgIShidWlsZGVyLmNvbXBpbGVyWydyZXNvbHZlciddWydyZXNvbHZlciddWydidWlsdEluSGVscGVycyddW25hbWVdICYmIGJ1aWxkZXIucmVmZXJyZXIub3duZXIuaGFzUmVnaXN0cmF0aW9uKCJoZWxwZXI6IiArIG5hbWUpKSkpOwogICAgdmFyIGhhbmRsZSA9IGJ1aWxkZXIuY29tcGlsZXJbJ3Jlc29sdmVyJ10ubG9va3VwQ29tcG9uZW50RGVmaW5pdGlvbihuYW1lLCBidWlsZGVyLnJlZmVycmVyKTsKCiAgICBpZiAoaGFuZGxlICE9PSBudWxsKSB7CiAgICAgIGJ1aWxkZXIuY29tcG9uZW50LnN0YXRpYyhoYW5kbGUsIFtwYXJhbXMgPT09IG51bGwgPyBbXSA6IHBhcmFtcywgaGFzaFRvQXJncyhoYXNoKSwgbnVsbCwgbnVsbF0pOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICBmdW5jdGlvbiByZWZpbmVCbG9ja1N5bnRheChuYW1lLCBwYXJhbXMsIGhhc2gsIHRlbXBsYXRlLCBpbnZlcnNlLCBidWlsZGVyKSB7CiAgICB2YXIgaGFuZGxlID0gYnVpbGRlci5jb21waWxlclsncmVzb2x2ZXInXS5sb29rdXBDb21wb25lbnREZWZpbml0aW9uKG5hbWUsIGJ1aWxkZXIucmVmZXJyZXIpOwoKICAgIGlmIChoYW5kbGUgIT09IG51bGwpIHsKICAgICAgd3JhcENvbXBvbmVudENsYXNzQXR0cmlidXRlKGhhc2gpOwogICAgICBidWlsZGVyLmNvbXBvbmVudC5zdGF0aWMoaGFuZGxlLCBbcGFyYW1zLCBoYXNoVG9BcmdzKGhhc2gpLCB0ZW1wbGF0ZSwgaW52ZXJzZV0pOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICAoZmFsc2UgJiYgIShidWlsZGVyLnJlZmVycmVyLm93bmVyLmhhc1JlZ2lzdHJhdGlvbigiaGVscGVyOiIgKyBuYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJBIGNvbXBvbmVudCBvciBoZWxwZXIgbmFtZWQgXCIiICsgbmFtZSArICJcIiBjb3VsZCBub3QgYmUgZm91bmQiLCBidWlsZGVyLnJlZmVycmVyLm93bmVyLmhhc1JlZ2lzdHJhdGlvbigiaGVscGVyOiIgKyBuYW1lKSkpOwogICAgKGZhbHNlICYmICEoIWZ1bmN0aW9uICgpIHsKICAgICAgdmFyIHJlc29sdmVyID0gYnVpbGRlci5jb21waWxlclsncmVzb2x2ZXInXVsncmVzb2x2ZXInXTsKICAgICAgdmFyIF9idWlsZGVyJHJlZmVycmVyID0gYnVpbGRlci5yZWZlcnJlciwKICAgICAgICAgIG93bmVyID0gX2J1aWxkZXIkcmVmZXJyZXIub3duZXIsCiAgICAgICAgICBtb2R1bGVOYW1lID0gX2J1aWxkZXIkcmVmZXJyZXIubW9kdWxlTmFtZTsKCiAgICAgIGlmIChuYW1lID09PSAnY29tcG9uZW50JyB8fCByZXNvbHZlclsnYnVpbHRJbkhlbHBlcnMnXVtuYW1lXSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICB2YXIgb3B0aW9ucyA9IHsKICAgICAgICBzb3VyY2U6ICJ0ZW1wbGF0ZToiICsgbW9kdWxlTmFtZQogICAgICB9OwogICAgICByZXR1cm4gb3duZXIuaGFzUmVnaXN0cmF0aW9uKCJoZWxwZXI6IiArIG5hbWUsIG9wdGlvbnMpIHx8IG93bmVyLmhhc1JlZ2lzdHJhdGlvbigiaGVscGVyOiIgKyBuYW1lKTsKICAgIH0oKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJIZWxwZXJzIG1heSBub3QgYmUgdXNlZCBpbiB0aGUgYmxvY2sgZm9ybSwgZm9yIGV4YW1wbGUge3sjIiArIG5hbWUgKyAifX17ey8iICsgbmFtZSArICJ9fS4gUGxlYXNlIHVzZSBhIGNvbXBvbmVudCwgb3IgYWx0ZXJuYXRpdmVseSB1c2UgdGhlIGhlbHBlciBpbiBjb21iaW5hdGlvbiB3aXRoIGEgYnVpbHQtaW4gRW1iZXIgaGVscGVyLCBmb3IgZXhhbXBsZSB7eyNpZiAoIiArIG5hbWUgKyAiKX19e3svaWZ9fS4iLCAhZnVuY3Rpb24gKCkgewogICAgICB2YXIgcmVzb2x2ZXIgPSBidWlsZGVyLmNvbXBpbGVyWydyZXNvbHZlciddWydyZXNvbHZlciddOwogICAgICB2YXIgX2J1aWxkZXIkcmVmZXJyZXIgPSBidWlsZGVyLnJlZmVycmVyLAogICAgICAgICAgb3duZXIgPSBfYnVpbGRlciRyZWZlcnJlci5vd25lciwKICAgICAgICAgIG1vZHVsZU5hbWUgPSBfYnVpbGRlciRyZWZlcnJlci5tb2R1bGVOYW1lOwoKICAgICAgaWYgKG5hbWUgPT09ICdjb21wb25lbnQnIHx8IHJlc29sdmVyWydidWlsdEluSGVscGVycyddW25hbWVdKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIHZhciBvcHRpb25zID0gewogICAgICAgIHNvdXJjZTogInRlbXBsYXRlOiIgKyBtb2R1bGVOYW1lCiAgICAgIH07CiAgICAgIHJldHVybiBvd25lci5oYXNSZWdpc3RyYXRpb24oImhlbHBlcjoiICsgbmFtZSwgb3B0aW9ucykgfHwgb3duZXIuaGFzUmVnaXN0cmF0aW9uKCJoZWxwZXI6IiArIG5hbWUpOwogICAgfSgpKSk7CiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICB2YXIgZXhwZXJpbWVudGFsTWFjcm9zID0gW107IC8vIFRoaXMgaXMgYSBwcml2YXRlIEFQSSB0byBhbGxvdyBmb3IgZXhwZXJpbWVudGFsIG1hY3JvcwogIC8vIHRvIGJlIGNyZWF0ZWQgaW4gdXNlciBzcGFjZS4gUmVnaXN0ZXJpbmcgYSBtYWNybyBzaG91bGQKICAvLyBzaG91bGQgYmUgZG9uZSBpbiBhbiBpbml0aWFsaXplci4KCiAgX2V4cG9ydHMuX2V4cGVyaW1lbnRhbE1hY3JvcyA9IGV4cGVyaW1lbnRhbE1hY3JvczsKCiAgZnVuY3Rpb24gcmVnaXN0ZXJNYWNyb3MobWFjcm8pIHsKICAgIGV4cGVyaW1lbnRhbE1hY3Jvcy5wdXNoKG1hY3JvKTsKICB9CgogIGZ1bmN0aW9uIHBvcHVsYXRlTWFjcm9zKG1hY3JvcykgewogICAgdmFyIGlubGluZXMgPSBtYWNyb3MuaW5saW5lcywKICAgICAgICBibG9ja3MgPSBtYWNyb3MuYmxvY2tzOwogICAgaW5saW5lcy5hZGQoJ291dGxldCcsIG91dGxldE1hY3JvKTsKICAgIGlubGluZXMuYWRkKCdtb3VudCcsIG1vdW50TWFjcm8pOwogICAgaW5saW5lcy5hZGRNaXNzaW5nKHJlZmluZUlubGluZVN5bnRheCk7CiAgICBibG9ja3MuYWRkKCdsZXQnLCBibG9ja0xldE1hY3JvKTsKICAgIGJsb2Nrcy5hZGRNaXNzaW5nKHJlZmluZUJsb2NrU3ludGF4KTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV4cGVyaW1lbnRhbE1hY3Jvcy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgbWFjcm8gPSBleHBlcmltZW50YWxNYWNyb3NbaV07CiAgICAgIG1hY3JvKGJsb2NrcywgaW5saW5lcyk7CiAgICB9CgogICAgcmV0dXJuIHsKICAgICAgYmxvY2tzOiBibG9ja3MsCiAgICAgIGlubGluZXM6IGlubGluZXMKICAgIH07CiAgfQoKICB2YXIgVEVNUExBVEVTJDEgPSBuZXcgV2Vha01hcCgpOwogIHZhciBnZXRQcm90b3R5cGVPZiQxID0gT2JqZWN0LmdldFByb3RvdHlwZU9mOwoKICBmdW5jdGlvbiBzZXRDb21wb25lbnRUZW1wbGF0ZShmYWN0b3J5LCBvYmopIHsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gbnVsbCAmJiAodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IGNhbGwgYHNldENvbXBvbmVudFRlbXBsYXRlYCBvbiBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKG9iaikgKyAiYCIsIG9iaiAhPT0gbnVsbCAmJiAodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykpKTsKICAgIChmYWxzZSAmJiAhKCFURU1QTEFURVMkMS5oYXMob2JqKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJDYW5ub3QgY2FsbCBgc2V0Q29tcG9uZW50VGVtcGxhdGVgIG11bHRpcGxlIHRpbWVzIG9uIHRoZSBzYW1lIGNsYXNzIChgIiArIG9iaiArICJgKSIsICFURU1QTEFURVMkMS5oYXMob2JqKSkpOwogICAgVEVNUExBVEVTJDEuc2V0KG9iaiwgZmFjdG9yeSk7CiAgICByZXR1cm4gb2JqOwogIH0KCiAgZnVuY3Rpb24gZ2V0Q29tcG9uZW50VGVtcGxhdGUob2JqKSB7CiAgICB2YXIgcG9pbnRlciA9IG9iajsKCiAgICB3aGlsZSAocG9pbnRlciAhPT0gdW5kZWZpbmVkICYmIHBvaW50ZXIgIT09IG51bGwpIHsKICAgICAgdmFyIF90ZW1wbGF0ZSA9IFRFTVBMQVRFUyQxLmdldChwb2ludGVyKTsKCiAgICAgIGlmIChfdGVtcGxhdGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBfdGVtcGxhdGU7CiAgICAgIH0KCiAgICAgIHBvaW50ZXIgPSBnZXRQcm90b3R5cGVPZiQxKHBvaW50ZXIpOwogICAgfQoKICAgIHJldHVybiBudWxsOwogIH0KCiAgZnVuY3Rpb24gc2V0TW9kaWZpZXJNYW5hZ2VyKGZhY3RvcnksIG9iaikgewogICAgcmV0dXJuIHNldE1hbmFnZXIoewogICAgICBmYWN0b3J5OiBmYWN0b3J5LAogICAgICBpbnRlcm5hbDogZmFsc2UsCiAgICAgIHR5cGU6ICdtb2RpZmllcicKICAgIH0sIG9iaik7CiAgfQoKICBmdW5jdGlvbiBnZXRNb2RpZmllck1hbmFnZXIob2JqKSB7CiAgICB2YXIgd3JhcHBlciA9IGdldE1hbmFnZXIob2JqKTsKCiAgICBpZiAod3JhcHBlciAmJiAhd3JhcHBlci5pbnRlcm5hbCAmJiB3cmFwcGVyLnR5cGUgPT09ICdtb2RpZmllcicpIHsKICAgICAgcmV0dXJuIHdyYXBwZXIuZmFjdG9yeTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBpbnN0cnVtZW50YXRpb25QYXlsb2FkJDEobmFtZSkgewogICAgcmV0dXJuIHsKICAgICAgb2JqZWN0OiAiY29tcG9uZW50OiIgKyBuYW1lCiAgICB9OwogIH0KCiAgZnVuY3Rpb24gbWFrZU9wdGlvbnMobW9kdWxlTmFtZSwgbmFtZXNwYWNlKSB7CiAgICByZXR1cm4gewogICAgICBzb3VyY2U6IG1vZHVsZU5hbWUgIT09IHVuZGVmaW5lZCA/ICJ0ZW1wbGF0ZToiICsgbW9kdWxlTmFtZSA6IHVuZGVmaW5lZCwKICAgICAgbmFtZXNwYWNlOiBuYW1lc3BhY2UKICAgIH07CiAgfQoKICBmdW5jdGlvbiBjb21wb25lbnRGb3IobmFtZSwgb3duZXIsIG9wdGlvbnMpIHsKICAgIHZhciBmdWxsTmFtZSA9ICJjb21wb25lbnQ6IiArIG5hbWU7CiAgICByZXR1cm4gb3duZXIuZmFjdG9yeUZvcihmdWxsTmFtZSwgb3B0aW9ucykgfHwgbnVsbDsKICB9CgogIGZ1bmN0aW9uIGxheW91dEZvcihuYW1lLCBvd25lciwgb3B0aW9ucykgewogICAgdmFyIHRlbXBsYXRlRnVsbE5hbWUgPSAidGVtcGxhdGU6Y29tcG9uZW50cy8iICsgbmFtZTsKICAgIHJldHVybiBvd25lci5sb29rdXAodGVtcGxhdGVGdWxsTmFtZSwgb3B0aW9ucykgfHwgbnVsbDsKICB9CgogIGZ1bmN0aW9uIGxvb2t1cENvbXBvbmVudFBhaXIob3duZXIsIG5hbWUsIG9wdGlvbnMpIHsKICAgIHZhciBjb21wb25lbnQgPSBjb21wb25lbnRGb3IobmFtZSwgb3duZXIsIG9wdGlvbnMpOwogICAgewogICAgICBpZiAoY29tcG9uZW50ICE9PSBudWxsICYmIGNvbXBvbmVudC5jbGFzcyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdmFyIF9sYXlvdXQyID0gZ2V0Q29tcG9uZW50VGVtcGxhdGUoY29tcG9uZW50LmNsYXNzKTsKCiAgICAgICAgaWYgKF9sYXlvdXQyICE9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBjb21wb25lbnQ6IGNvbXBvbmVudCwKICAgICAgICAgICAgbGF5b3V0OiBfbGF5b3V0MgogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHZhciBsYXlvdXQgPSBsYXlvdXRGb3IobmFtZSwgb3duZXIsIG9wdGlvbnMpOwoKICAgIGlmIChjb21wb25lbnQgPT09IG51bGwgJiYgbGF5b3V0ID09PSBudWxsKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBjb21wb25lbnQ6IGNvbXBvbmVudCwKICAgICAgICBsYXlvdXQ6IGxheW91dAogICAgICB9OwogICAgfQogIH0KCiAgZnVuY3Rpb24gbG9va3VwQ29tcG9uZW50KG93bmVyLCBuYW1lLCBvcHRpb25zKSB7CiAgICBpZiAob3B0aW9ucy5zb3VyY2UgfHwgb3B0aW9ucy5uYW1lc3BhY2UpIHsKICAgICAgdmFyIHBhaXIgPSBsb29rdXBDb21wb25lbnRQYWlyKG93bmVyLCBuYW1lLCBvcHRpb25zKTsKCiAgICAgIGlmIChwYWlyICE9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIHBhaXI7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gbG9va3VwQ29tcG9uZW50UGFpcihvd25lciwgbmFtZSk7CiAgfQoKICB2YXIgQlVJTFRJTlNfSEVMUEVSUyA9IHsKICAgIGlmOiBpbmxpbmVJZiwKICAgIGFjdGlvbjogYWN0aW9uLAogICAgYXJyYXk6IGFycmF5LAogICAgY29uY2F0OiBjb25jYXQkMSwKICAgIGdldDogZ2V0JDEsCiAgICBoYXNoOiBoYXNoLAogICAgbG9nOiBsb2ckMSwKICAgIG11dDogbXV0LAogICAgJ3F1ZXJ5LXBhcmFtcyc6IHF1ZXJ5UGFyYW1zJDEsCiAgICByZWFkb25seTogcmVhZG9ubHksCiAgICB1bmJvdW5kOiB1bmJvdW5kLAogICAgdW5sZXNzOiBpbmxpbmVVbmxlc3MsCiAgICAnLWNsYXNzJzogY2xhc3NIZWxwZXIkMSwKICAgICctZWFjaC1pbic6IGVhY2hJbiwKICAgICctaW5wdXQtdHlwZSc6IGlucHV0VHlwZUhlbHBlciQxLAogICAgJy1ub3JtYWxpemUtY2xhc3MnOiBub3JtYWxpemVDbGFzc0hlbHBlciwKICAgICctZ2V0LWR5bmFtaWMtdmFyJzogX3J1bnRpbWUyLmdldER5bmFtaWNWYXIsCiAgICAnLW1vdW50JzogbW91bnRIZWxwZXIsCiAgICAnLW91dGxldCc6IG91dGxldEhlbHBlciwKICAgICctYXNzZXJ0LWltcGxpY2l0LWNvbXBvbmVudC1oZWxwZXItYXJndW1lbnQnOiBjb21wb25lbnRBc3NlcnRpb25IZWxwZXIsCiAgICBmbjogdW5kZWZpbmVkCiAgfTsKICB7CiAgICBCVUlMVElOU19IRUxQRVJTLmZuID0gZm47CiAgfQoKICB2YXIgUnVudGltZVJlc29sdmVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUnVudGltZVJlc29sdmVyKGlzSW50ZXJhY3RpdmUpIHsKICAgICAgdGhpcy5oYW5kbGVzID0gW3VuZGVmaW5lZF07CiAgICAgIHRoaXMub2JqVG9IYW5kbGUgPSBuZXcgV2Vha01hcCgpOwogICAgICB0aGlzLmJ1aWx0SW5IZWxwZXJzID0gQlVJTFRJTlNfSEVMUEVSUzsKICAgICAgdGhpcy5jb21wb25lbnREZWZpbml0aW9uQ2FjaGUgPSBuZXcgTWFwKCk7CiAgICAgIHRoaXMuY29tcG9uZW50RGVmaW5pdGlvbkNvdW50ID0gMDsKICAgICAgdGhpcy5oZWxwZXJEZWZpbml0aW9uQ291bnQgPSAwOwogICAgICB2YXIgbWFjcm9zID0gbmV3IF9vcGNvZGVDb21waWxlci5NYWNyb3MoKTsKICAgICAgcG9wdWxhdGVNYWNyb3MobWFjcm9zKTsKICAgICAgdGhpcy5jb21waWxlciA9IG5ldyBfb3Bjb2RlQ29tcGlsZXIuTGF6eUNvbXBpbGVyKG5ldyBDb21waWxlVGltZUxvb2t1cCh0aGlzKSwgdGhpcywgbWFjcm9zKTsKICAgICAgdGhpcy5pc0ludGVyYWN0aXZlID0gaXNJbnRlcmFjdGl2ZTsKICAgICAgdGhpcy5idWlsdEluTW9kaWZpZXJzID0gewogICAgICAgIGFjdGlvbjogewogICAgICAgICAgbWFuYWdlcjogbmV3IEFjdGlvbk1vZGlmaWVyTWFuYWdlcigpLAogICAgICAgICAgc3RhdGU6IG51bGwKICAgICAgICB9LAogICAgICAgIG9uOiB7CiAgICAgICAgICBtYW5hZ2VyOiBuZXcgT25Nb2RpZmllck1hbmFnZXIoaXNJbnRlcmFjdGl2ZSksCiAgICAgICAgICBzdGF0ZTogbnVsbAogICAgICAgIH0KICAgICAgfTsKICAgIH0KICAgIC8qKiogIElSdW50aW1lUmVzb2x2ZXIgKioqLwoKICAgIC8qKgogICAgICogcHVibGljIGNvbXBvbmVudERlZkhhbmRsZUNvdW50ID0gMDsKICAgICAqIENhbGxlZCB3aGlsZSBleGVjdXRpbmcgQXBwZW5kIE9wLlB1c2hEeW5hbWljQ29tcG9uZW50TWFuYWdlciBpZiBzdHJpbmcKICAgICAqLwoKCiAgICB2YXIgX3Byb3RvNjggPSBSdW50aW1lUmVzb2x2ZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzY4Lmxvb2t1cENvbXBvbmVudERlZmluaXRpb24gPSBmdW5jdGlvbiBsb29rdXBDb21wb25lbnREZWZpbml0aW9uKG5hbWUsIG1ldGEpIHsKICAgICAgdmFyIGhhbmRsZSA9IHRoaXMubG9va3VwQ29tcG9uZW50SGFuZGxlKG5hbWUsIG1ldGEpOwoKICAgICAgaWYgKGhhbmRsZSA9PT0gbnVsbCkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkNvdWxkIG5vdCBmaW5kIGNvbXBvbmVudCBuYW1lZCBcIiIgKyBuYW1lICsgIlwiIChubyBjb21wb25lbnQgb3IgdGVtcGxhdGUgd2l0aCB0aGF0IG5hbWUgd2FzIGZvdW5kKSIpKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZShoYW5kbGUpOwogICAgfTsKCiAgICBfcHJvdG82OC5sb29rdXBDb21wb25lbnRIYW5kbGUgPSBmdW5jdGlvbiBsb29rdXBDb21wb25lbnRIYW5kbGUobmFtZSwgbWV0YSkgewogICAgICB2YXIgbmV4dEhhbmRsZSA9IHRoaXMuaGFuZGxlcy5sZW5ndGg7CiAgICAgIHZhciBoYW5kbGUgPSB0aGlzLmhhbmRsZSh0aGlzLl9sb29rdXBDb21wb25lbnREZWZpbml0aW9uKG5hbWUsIG1ldGEpKTsKICAgICAgKGZhbHNlICYmICEoISh0cnVlCiAgICAgIC8qIEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMgKi8KICAgICAgJiYgbmFtZSA9PT0gJ3RleHQtYXJlYScgJiYgaGFuZGxlID09PSBudWxsKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdDb3VsZCBub3QgZmluZCBjb21wb25lbnQgYDxUZXh0QXJlYSAvPmAgKGRpZCB5b3UgbWVhbiBgPFRleHRhcmVhIC8+YD8pJywgISh0cnVlICYmIG5hbWUgPT09ICd0ZXh0LWFyZWEnICYmIGhhbmRsZSA9PT0gbnVsbCkpKTsKCiAgICAgIGlmIChuZXh0SGFuZGxlID09PSBoYW5kbGUpIHsKICAgICAgICB0aGlzLmNvbXBvbmVudERlZmluaXRpb25Db3VudCsrOwogICAgICB9CgogICAgICByZXR1cm4gaGFuZGxlOwogICAgfQogICAgLyoqCiAgICAgKiBDYWxsZWQgYnkgUnVudGltZUNvbnN0YW50cyB0byBsb29rdXAgdW5yZXNvbHZlZCBoYW5kbGVzLgogICAgICovCiAgICA7CgogICAgX3Byb3RvNjgucmVzb2x2ZSA9IGZ1bmN0aW9uIHJlc29sdmUoaGFuZGxlKSB7CiAgICAgIHJldHVybiB0aGlzLmhhbmRsZXNbaGFuZGxlXTsKICAgIH0gLy8gRW5kIElSdW50aW1lUmVzb2x2ZXIKCiAgICAvKioKICAgICAqIENhbGxlZCBieSBDb21waWxlVGltZUxvb2t1cCBjb21waWxpbmcgVW5rbm93biBvciBIZWxwZXIgT3BDb2RlCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG82OC5sb29rdXBIZWxwZXIgPSBmdW5jdGlvbiBsb29rdXBIZWxwZXIobmFtZSwgbWV0YSkgewogICAgICB2YXIgbmV4dEhhbmRsZSA9IHRoaXMuaGFuZGxlcy5sZW5ndGg7CgogICAgICB2YXIgaGVscGVyJCQxID0gdGhpcy5fbG9va3VwSGVscGVyKG5hbWUsIG1ldGEpOwoKICAgICAgaWYgKGhlbHBlciQkMSAhPT0gbnVsbCkgewogICAgICAgIHZhciBoYW5kbGUgPSB0aGlzLmhhbmRsZShoZWxwZXIkJDEpOwoKICAgICAgICBpZiAobmV4dEhhbmRsZSA9PT0gaGFuZGxlKSB7CiAgICAgICAgICB0aGlzLmhlbHBlckRlZmluaXRpb25Db3VudCsrOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGhhbmRsZTsKICAgICAgfQoKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICAvKioKICAgICAqIENhbGxlZCBieSBDb21waWxlVGltZUxvb2t1cCBjb21waWxpbmcgdGhlCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG82OC5sb29rdXBNb2RpZmllciA9IGZ1bmN0aW9uIGxvb2t1cE1vZGlmaWVyKG5hbWUsIG1ldGEpIHsKICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlKHRoaXMuX2xvb2t1cE1vZGlmaWVyKG5hbWUsIG1ldGEpKTsKICAgIH0KICAgIC8qKgogICAgICogQ2FsbGVkIGJ5IENvbXBpbGVUaW1lTG9va3VwIHRvIGxvb2t1cCBwYXJ0aWFsCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG82OC5sb29rdXBQYXJ0aWFsID0gZnVuY3Rpb24gbG9va3VwUGFydGlhbChuYW1lLCBtZXRhKSB7CiAgICAgIHZhciBwYXJ0aWFsID0gdGhpcy5fbG9va3VwUGFydGlhbChuYW1lLCBtZXRhKTsKCiAgICAgIHJldHVybiB0aGlzLmhhbmRsZShwYXJ0aWFsKTsKICAgIH0gLy8gZW5kIENvbXBpbGVUaW1lTG9va3VwCiAgICAvLyBuZWVkZWQgZm9yIGxhenkgY29tcGlsZSB0aW1lIGxvb2t1cAogICAgOwoKICAgIF9wcm90bzY4LmhhbmRsZSA9IGZ1bmN0aW9uIGhhbmRsZShvYmopIHsKICAgICAgaWYgKG9iaiA9PT0gdW5kZWZpbmVkIHx8IG9iaiA9PT0gbnVsbCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgaGFuZGxlID0gdGhpcy5vYmpUb0hhbmRsZS5nZXQob2JqKTsKCiAgICAgIGlmIChoYW5kbGUgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGhhbmRsZSA9IHRoaXMuaGFuZGxlcy5wdXNoKG9iaikgLSAxOwogICAgICAgIHRoaXMub2JqVG9IYW5kbGUuc2V0KG9iaiwgaGFuZGxlKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGhhbmRsZTsKICAgIH07CgogICAgX3Byb3RvNjguX2xvb2t1cEhlbHBlciA9IGZ1bmN0aW9uIF9sb29rdXBIZWxwZXIoX25hbWUsIG1ldGEpIHsKICAgICAgdmFyIGhlbHBlciQkMSA9IHRoaXMuYnVpbHRJbkhlbHBlcnNbX25hbWVdOwoKICAgICAgaWYgKGhlbHBlciQkMSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIGhlbHBlciQkMTsKICAgICAgfQoKICAgICAgdmFyIG93bmVyID0gbWV0YS5vd25lciwKICAgICAgICAgIG1vZHVsZU5hbWUgPSBtZXRhLm1vZHVsZU5hbWU7CiAgICAgIHZhciBuYW1lID0gX25hbWU7CiAgICAgIHZhciBuYW1lc3BhY2UgPSB1bmRlZmluZWQ7CiAgICAgIHZhciBvcHRpb25zID0gbWFrZU9wdGlvbnMobW9kdWxlTmFtZSwgbmFtZXNwYWNlKTsKICAgICAgdmFyIGZhY3RvcnkgPSBvd25lci5mYWN0b3J5Rm9yKCJoZWxwZXI6IiArIG5hbWUsIG9wdGlvbnMpIHx8IG93bmVyLmZhY3RvcnlGb3IoImhlbHBlcjoiICsgbmFtZSk7CgogICAgICBpZiAoIWlzSGVscGVyRmFjdG9yeShmYWN0b3J5KSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICByZXR1cm4gZnVuY3Rpb24gKHZtLCBhcmdzKSB7CiAgICAgICAgdmFyIGhlbHBlciQkMSA9IGZhY3RvcnkuY3JlYXRlKCk7CgogICAgICAgIGlmIChpc1NpbXBsZUhlbHBlcihoZWxwZXIkJDEpKSB7CiAgICAgICAgICByZXR1cm4gU2ltcGxlSGVscGVyUmVmZXJlbmNlLmNyZWF0ZShoZWxwZXIkJDEuY29tcHV0ZSwgYXJncy5jYXB0dXJlKCkpOwogICAgICAgIH0KCiAgICAgICAgdm0ubmV3RGVzdHJveWFibGUoaGVscGVyJCQxKTsKICAgICAgICByZXR1cm4gQ2xhc3NCYXNlZEhlbHBlclJlZmVyZW5jZS5jcmVhdGUoaGVscGVyJCQxLCBhcmdzLmNhcHR1cmUoKSk7CiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzY4Ll9sb29rdXBQYXJ0aWFsID0gZnVuY3Rpb24gX2xvb2t1cFBhcnRpYWwobmFtZSwgbWV0YSkgewogICAgICB2YXIgdGVtcGxhdGVGYWN0b3J5JCQxID0gKDAsIF92aWV3cy5sb29rdXBQYXJ0aWFsKShuYW1lLCBtZXRhLm93bmVyKTsKICAgICAgdmFyIHRlbXBsYXRlID0gdGVtcGxhdGVGYWN0b3J5JCQxKG1ldGEub3duZXIpOwogICAgICByZXR1cm4gbmV3IF9vcGNvZGVDb21waWxlci5QYXJ0aWFsRGVmaW5pdGlvbihuYW1lLCB0ZW1wbGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzY4Ll9sb29rdXBNb2RpZmllciA9IGZ1bmN0aW9uIF9sb29rdXBNb2RpZmllcihuYW1lLCBtZXRhKSB7CiAgICAgIHZhciBidWlsdGluID0gdGhpcy5idWlsdEluTW9kaWZpZXJzW25hbWVdOwoKICAgICAgaWYgKGJ1aWx0aW4gPT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhciBvd25lciA9IG1ldGEub3duZXI7CiAgICAgICAgdmFyIG1vZGlmaWVyID0gb3duZXIuZmFjdG9yeUZvcigibW9kaWZpZXI6IiArIG5hbWUpOwoKICAgICAgICBpZiAobW9kaWZpZXIgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdmFyIG1hbmFnZXJGYWN0b3J5ID0gZ2V0TW9kaWZpZXJNYW5hZ2VyKG1vZGlmaWVyLmNsYXNzKTsKICAgICAgICAgIHZhciBtYW5hZ2VyID0gbWFuYWdlckZhY3Rvcnkob3duZXIpOwogICAgICAgICAgcmV0dXJuIG5ldyBDdXN0b21Nb2RpZmllckRlZmluaXRpb24obmFtZSwgbW9kaWZpZXIsIG1hbmFnZXIsIHRoaXMuaXNJbnRlcmFjdGl2ZSk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gYnVpbHRpbjsKICAgIH07CgogICAgX3Byb3RvNjguX3BhcnNlTmFtZUZvck5hbWVzcGFjZSA9IGZ1bmN0aW9uIF9wYXJzZU5hbWVGb3JOYW1lc3BhY2UoX25hbWUpIHsKICAgICAgdmFyIG5hbWUgPSBfbmFtZTsKICAgICAgdmFyIG5hbWVzcGFjZSA9IHVuZGVmaW5lZDsKCiAgICAgIHZhciBuYW1lc3BhY2VEZWxpbWl0ZXJPZmZzZXQgPSBfbmFtZS5pbmRleE9mKCc6OicpOwoKICAgICAgaWYgKG5hbWVzcGFjZURlbGltaXRlck9mZnNldCAhPT0gLTEpIHsKICAgICAgICBuYW1lID0gX25hbWUuc2xpY2UobmFtZXNwYWNlRGVsaW1pdGVyT2Zmc2V0ICsgMik7CiAgICAgICAgbmFtZXNwYWNlID0gX25hbWUuc2xpY2UoMCwgbmFtZXNwYWNlRGVsaW1pdGVyT2Zmc2V0KTsKICAgICAgfQoKICAgICAgcmV0dXJuIHsKICAgICAgICBuYW1lOiBuYW1lLAogICAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzY4Ll9sb29rdXBDb21wb25lbnREZWZpbml0aW9uID0gZnVuY3Rpb24gX2xvb2t1cENvbXBvbmVudERlZmluaXRpb24oX25hbWUsIF9yZWYzNikgewogICAgICB2YXIgbW9kdWxlTmFtZSA9IF9yZWYzNi5tb2R1bGVOYW1lLAogICAgICAgICAgb3duZXIgPSBfcmVmMzYub3duZXI7CiAgICAgIChmYWxzZSAmJiAhKHRydWUKICAgICAgLyogRU1CRVJfR0xJTU1FUl9BTkdMRV9CUkFDS0VUX0JVSUxUX0lOUyAqLwogICAgICB8fCBfbmFtZSAhPT0gJ3RleHRhcmVhJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdJbnZva2luZyBge3t0ZXh0YXJlYX19YCB1c2luZyBhbmdsZSBicmFja2V0IHN5bnRheCBvciBgY29tcG9uZW50YCBoZWxwZXIgaXMgbm90IHlldCBzdXBwb3J0ZWQuJywgdHJ1ZSB8fCBfbmFtZSAhPT0gJ3RleHRhcmVhJykpOwogICAgICAoZmFsc2UgJiYgISh0cnVlCiAgICAgIC8qIEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMgKi8KICAgICAgfHwgX25hbWUgIT09ICdpbnB1dCcpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnSW52b2tpbmcgYHt7aW5wdXR9fWAgdXNpbmcgYW5nbGUgYnJhY2tldCBzeW50YXggb3IgYGNvbXBvbmVudGAgaGVscGVyIGlzIG5vdCB5ZXQgc3VwcG9ydGVkLicsIHRydWUgfHwgX25hbWUgIT09ICdpbnB1dCcpKTsKICAgICAgdmFyIG5hbWUgPSBfbmFtZTsKICAgICAgdmFyIG5hbWVzcGFjZSA9IHVuZGVmaW5lZDsKICAgICAgdmFyIHBhaXIgPSBsb29rdXBDb21wb25lbnQob3duZXIsIG5hbWUsIG1ha2VPcHRpb25zKG1vZHVsZU5hbWUsIG5hbWVzcGFjZSkpOwoKICAgICAgaWYgKHBhaXIgPT09IG51bGwpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIGxheW91dCA9IG51bGw7CiAgICAgIHZhciBrZXk7CgogICAgICBpZiAocGFpci5jb21wb25lbnQgPT09IG51bGwpIHsKICAgICAgICBrZXkgPSBsYXlvdXQgPSBwYWlyLmxheW91dChvd25lcik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAga2V5ID0gcGFpci5jb21wb25lbnQ7CiAgICAgIH0KCiAgICAgIHZhciBjYWNoZWRDb21wb25lbnREZWZpbml0aW9uID0gdGhpcy5jb21wb25lbnREZWZpbml0aW9uQ2FjaGUuZ2V0KGtleSk7CgogICAgICBpZiAoY2FjaGVkQ29tcG9uZW50RGVmaW5pdGlvbiAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIGNhY2hlZENvbXBvbmVudERlZmluaXRpb247CiAgICAgIH0KCiAgICAgIGlmIChsYXlvdXQgPT09IG51bGwgJiYgcGFpci5sYXlvdXQgIT09IG51bGwpIHsKICAgICAgICBsYXlvdXQgPSBwYWlyLmxheW91dChvd25lcik7CiAgICAgIH0KCiAgICAgIHZhciBmaW5hbGl6ZXIgPSAoMCwgX2luc3RydW1lbnRhdGlvbi5faW5zdHJ1bWVudFN0YXJ0KSgncmVuZGVyLmdldENvbXBvbmVudERlZmluaXRpb24nLCBpbnN0cnVtZW50YXRpb25QYXlsb2FkJDEsIG5hbWUpOwogICAgICB2YXIgZGVmaW5pdGlvbiA9IG51bGw7CgogICAgICBpZiAocGFpci5jb21wb25lbnQgPT09IG51bGwpIHsKICAgICAgICBpZiAoX2Vudmlyb25tZW50Mi5FTlYuX1RFTVBMQVRFX09OTFlfR0xJTU1FUl9DT01QT05FTlRTKSB7CiAgICAgICAgICBkZWZpbml0aW9uID0gbmV3IFRlbXBsYXRlT25seUNvbXBvbmVudERlZmluaXRpb24obGF5b3V0KTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAodHJ1ZQogICAgICAvKiBFTUJFUl9HTElNTUVSX1NFVF9DT01QT05FTlRfVEVNUExBVEUgKi8KICAgICAgJiYgKDAsIF90ZW1wbGF0ZU9ubHkuaXNUZW1wbGF0ZU9ubHlDb21wb25lbnQpKHBhaXIuY29tcG9uZW50LmNsYXNzKSkgewogICAgICAgIGRlZmluaXRpb24gPSBuZXcgVGVtcGxhdGVPbmx5Q29tcG9uZW50RGVmaW5pdGlvbihsYXlvdXQpOwogICAgICB9CgogICAgICBpZiAocGFpci5jb21wb25lbnQgIT09IG51bGwpIHsKICAgICAgICAoZmFsc2UgJiYgIShwYWlyLmNvbXBvbmVudC5jbGFzcyAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIm1pc3NpbmcgY29tcG9uZW50IGNsYXNzICIgKyBuYW1lLCBwYWlyLmNvbXBvbmVudC5jbGFzcyAhPT0gdW5kZWZpbmVkKSk7CiAgICAgICAgdmFyIENvbXBvbmVudENsYXNzID0gcGFpci5jb21wb25lbnQuY2xhc3M7CiAgICAgICAgdmFyIHdyYXBwZXIgPSBnZXRNYW5hZ2VyKENvbXBvbmVudENsYXNzKTsKCiAgICAgICAgaWYgKHdyYXBwZXIgIT09IG51bGwgJiYgd3JhcHBlci50eXBlID09PSAnY29tcG9uZW50JykgewogICAgICAgICAgdmFyIGZhY3RvcnkgPSB3cmFwcGVyLmZhY3Rvcnk7CgogICAgICAgICAgaWYgKHdyYXBwZXIuaW50ZXJuYWwpIHsKICAgICAgICAgICAgKGZhbHNlICYmICEocGFpci5sYXlvdXQgIT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgibWlzc2luZyBsYXlvdXQgZm9yIGludGVybmFsIGNvbXBvbmVudCAiICsgbmFtZSwgcGFpci5sYXlvdXQgIT09IG51bGwpKTsKICAgICAgICAgICAgZGVmaW5pdGlvbiA9IG5ldyBJbnRlcm5hbENvbXBvbmVudERlZmluaXRpb24oZmFjdG9yeShvd25lciksIENvbXBvbmVudENsYXNzLCBsYXlvdXQpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZGVmaW5pdGlvbiA9IG5ldyBDdXN0b21NYW5hZ2VyRGVmaW5pdGlvbihuYW1lLCBwYWlyLmNvbXBvbmVudCwgZmFjdG9yeShvd25lciksIGxheW91dCAhPT0gbnVsbCA/IGxheW91dCA6IG93bmVyLmxvb2t1cCgoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdDMoKSkpKG93bmVyKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoZGVmaW5pdGlvbiA9PT0gbnVsbCkgewogICAgICAgIGRlZmluaXRpb24gPSBuZXcgQ3VybHlDb21wb25lbnREZWZpbml0aW9uKG5hbWUsIHBhaXIuY29tcG9uZW50IHx8IG93bmVyLmZhY3RvcnlGb3IoKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3Q0KCkpKSwgbnVsbCwgbGF5b3V0KTsKICAgICAgfQoKICAgICAgZmluYWxpemVyKCk7CiAgICAgIHRoaXMuY29tcG9uZW50RGVmaW5pdGlvbkNhY2hlLnNldChrZXksIGRlZmluaXRpb24pOwogICAgICByZXR1cm4gZGVmaW5pdGlvbjsKICAgIH07CgogICAgcmV0dXJuIFJ1bnRpbWVSZXNvbHZlcjsKICB9KCk7CgogIHZhciBUZW1wbGF0ZUNvbXBpbGVyID0gewogICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUoX3JlZjM3KSB7CiAgICAgIHZhciBlbnZpcm9ubWVudCA9IF9yZWYzNy5lbnZpcm9ubWVudDsKICAgICAgcmV0dXJuIG5ldyBSdW50aW1lUmVzb2x2ZXIoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkuY29tcGlsZXI7CiAgICB9CiAgfTsKICB2YXIgQ29tcG9uZW50VGVtcGxhdGUgPSB0ZW1wbGF0ZSh7CiAgICAiaWQiOiAiY2hmUWNIODMiLAogICAgImJsb2NrIjogIntcInN5bWJvbHNcIjpbXCImZGVmYXVsdFwiXSxcInN0YXRlbWVudHNcIjpbWzE0LDFdXSxcImhhc0V2YWxcIjpmYWxzZX0iLAogICAgIm1ldGEiOiB7CiAgICAgICJtb2R1bGVOYW1lIjogInBhY2thZ2VzL0BlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIvbGliL3RlbXBsYXRlcy9jb21wb25lbnQuaGJzIgogICAgfQogIH0pOwogIHZhciBJbnB1dFRlbXBsYXRlID0gdGVtcGxhdGUoewogICAgImlkIjogIk5XWnpMU0lJIiwKICAgICJibG9jayI6ICJ7XCJzeW1ib2xzXCI6W1wiQ2hlY2tib3hcIixcIlRleHRGaWVsZFwiLFwiQF9fQVJHU19fXCIsXCImYXR0cnNcIl0sXCJzdGF0ZW1lbnRzXCI6W1s0LFwibGV0XCIsW1syOCxcImNvbXBvbmVudFwiLFtcIi1jaGVja2JveFwiXSxudWxsXSxbMjgsXCJjb21wb25lbnRcIixbXCItdGV4dC1maWVsZFwiXSxudWxsXV0sbnVsbCx7XCJzdGF0ZW1lbnRzXCI6W1s0LFwiaWZcIixbWzIzLDAsW1wiaXNDaGVja2JveFwiXV1dLG51bGwse1wic3RhdGVtZW50c1wiOltbNixbMjMsMSxbXV0sW1sxMyw0XV0sW1tcIkB0YXJnZXRcIixcIkBfX0FSR1NfX1wiXSxbWzIzLDAsW1wiY2FsbGVyXCJdXSxbMjMsMyxbXV1dXV1dLFwicGFyYW1ldGVyc1wiOltdfSx7XCJzdGF0ZW1lbnRzXCI6W1s2LFsyMywyLFtdXSxbWzEzLDRdXSxbW1wiQHRhcmdldFwiLFwiQF9fQVJHU19fXCJdLFtbMjMsMCxbXCJjYWxsZXJcIl1dLFsyMywzLFtdXV1dXV0sXCJwYXJhbWV0ZXJzXCI6W119XV0sXCJwYXJhbWV0ZXJzXCI6WzEsMl19LG51bGxdXSxcImhhc0V2YWxcIjpmYWxzZX0iLAogICAgIm1ldGEiOiB7CiAgICAgICJtb2R1bGVOYW1lIjogInBhY2thZ2VzL0BlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIvbGliL3RlbXBsYXRlcy9pbnB1dC5oYnMiCiAgICB9CiAgfSk7CiAgdmFyIE91dGxldFRlbXBsYXRlID0gdGVtcGxhdGUoewogICAgImlkIjogImZmQUw2SERsIiwKICAgICJibG9jayI6ICJ7XCJzeW1ib2xzXCI6W10sXCJzdGF0ZW1lbnRzXCI6W1sxLFsyMixcIm91dGxldFwiXSxmYWxzZV1dLFwiaGFzRXZhbFwiOmZhbHNlfSIsCiAgICAibWV0YSI6IHsKICAgICAgIm1vZHVsZU5hbWUiOiAicGFja2FnZXMvQGVtYmVyLy1pbnRlcm5hbHMvZ2xpbW1lci9saWIvdGVtcGxhdGVzL291dGxldC5oYnMiCiAgICB9CiAgfSk7CiAgdmFyIFRPUF9MRVZFTF9OQU1FID0gJy10b3AtbGV2ZWwnOwogIHZhciBUT1BfTEVWRUxfT1VUTEVUID0gJ21haW4nOwoKICB2YXIgT3V0bGV0VmlldyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIE91dGxldFZpZXcoX2Vudmlyb25tZW50LCByZW5kZXJlciwgb3duZXIsIHRlbXBsYXRlKSB7CiAgICAgIHRoaXMuX2Vudmlyb25tZW50ID0gX2Vudmlyb25tZW50OwogICAgICB0aGlzLnJlbmRlcmVyID0gcmVuZGVyZXI7CiAgICAgIHRoaXMub3duZXIgPSBvd25lcjsKICAgICAgdGhpcy50ZW1wbGF0ZSA9IHRlbXBsYXRlOwogICAgICB2YXIgcmVmID0gdGhpcy5yZWYgPSBuZXcgUm9vdE91dGxldFJlZmVyZW5jZSh7CiAgICAgICAgb3V0bGV0czogewogICAgICAgICAgbWFpbjogdW5kZWZpbmVkCiAgICAgICAgfSwKICAgICAgICByZW5kZXI6IHsKICAgICAgICAgIG93bmVyOiBvd25lciwKICAgICAgICAgIGludG86IHVuZGVmaW5lZCwKICAgICAgICAgIG91dGxldDogVE9QX0xFVkVMX09VVExFVCwKICAgICAgICAgIG5hbWU6IFRPUF9MRVZFTF9OQU1FLAogICAgICAgICAgY29udHJvbGxlcjogdW5kZWZpbmVkLAogICAgICAgICAgdGVtcGxhdGU6IHRlbXBsYXRlCiAgICAgICAgfQogICAgICB9KTsKICAgICAgdGhpcy5zdGF0ZSA9IHsKICAgICAgICByZWY6IHJlZiwKICAgICAgICBuYW1lOiBUT1BfTEVWRUxfTkFNRSwKICAgICAgICBvdXRsZXQ6IFRPUF9MRVZFTF9PVVRMRVQsCiAgICAgICAgdGVtcGxhdGU6IHRlbXBsYXRlLAogICAgICAgIGNvbnRyb2xsZXI6IHVuZGVmaW5lZAogICAgICB9OwogICAgfQoKICAgIE91dGxldFZpZXcuZXh0ZW5kID0gZnVuY3Rpb24gZXh0ZW5kKGluamVjdGlvbnMpIHsKICAgICAgcmV0dXJuICgKICAgICAgICAvKiNfX1BVUkVfXyovCiAgICAgICAgZnVuY3Rpb24gKF9PdXRsZXRWaWV3KSB7CiAgICAgICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoX2NsYXNzLCBfT3V0bGV0Vmlldyk7CgogICAgICAgICAgZnVuY3Rpb24gX2NsYXNzKCkgewogICAgICAgICAgICByZXR1cm4gX091dGxldFZpZXcuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICAgICAgfQoKICAgICAgICAgIF9jbGFzcy5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUob3B0aW9ucykgewogICAgICAgICAgICBpZiAob3B0aW9ucykgewogICAgICAgICAgICAgIHJldHVybiBfT3V0bGV0Vmlldy5jcmVhdGUuY2FsbCh0aGlzLCAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBpbmplY3Rpb25zLCBvcHRpb25zKSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmV0dXJuIF9PdXRsZXRWaWV3LmNyZWF0ZS5jYWxsKHRoaXMsIGluamVjdGlvbnMpOwogICAgICAgICAgICB9CiAgICAgICAgICB9OwoKICAgICAgICAgIHJldHVybiBfY2xhc3M7CiAgICAgICAgfShPdXRsZXRWaWV3KQogICAgICApOwogICAgfTsKCiAgICBPdXRsZXRWaWV3LnJlb3BlbkNsYXNzID0gZnVuY3Rpb24gcmVvcGVuQ2xhc3MoaW5qZWN0aW9ucykgewogICAgICAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHRoaXMsIGluamVjdGlvbnMpOwogICAgfTsKCiAgICBPdXRsZXRWaWV3LmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShvcHRpb25zKSB7CiAgICAgIHZhciBfZW52aXJvbm1lbnQgPSBvcHRpb25zLl9lbnZpcm9ubWVudCwKICAgICAgICAgIHJlbmRlcmVyID0gb3B0aW9ucy5yZW5kZXJlciwKICAgICAgICAgIHRlbXBsYXRlRmFjdG9yeSQkMSA9IG9wdGlvbnMudGVtcGxhdGU7CiAgICAgIHZhciBvd25lciA9IG9wdGlvbnNbX293bmVyLk9XTkVSXTsKICAgICAgdmFyIHRlbXBsYXRlID0gdGVtcGxhdGVGYWN0b3J5JCQxKG93bmVyKTsKICAgICAgcmV0dXJuIG5ldyBPdXRsZXRWaWV3KF9lbnZpcm9ubWVudCwgcmVuZGVyZXIsIG93bmVyLCB0ZW1wbGF0ZSk7CiAgICB9OwoKICAgIHZhciBfcHJvdG82OSA9IE91dGxldFZpZXcucHJvdG90eXBlOwoKICAgIF9wcm90bzY5LmFwcGVuZFRvID0gZnVuY3Rpb24gYXBwZW5kVG8oc2VsZWN0b3IpIHsKICAgICAgdmFyIHRhcmdldDsKCiAgICAgIGlmICh0aGlzLl9lbnZpcm9ubWVudC5oYXNET00pIHsKICAgICAgICB0YXJnZXQgPSB0eXBlb2Ygc2VsZWN0b3IgPT09ICdzdHJpbmcnID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3RvcikgOiBzZWxlY3RvcjsKICAgICAgfSBlbHNlIHsKICAgICAgICB0YXJnZXQgPSBzZWxlY3RvcjsKICAgICAgfQoKICAgICAgKDAsIF9ydW5sb29wLnNjaGVkdWxlKSgncmVuZGVyJywgdGhpcy5yZW5kZXJlciwgJ2FwcGVuZE91dGxldFZpZXcnLCB0aGlzLCB0YXJnZXQpOwogICAgfTsKCiAgICBfcHJvdG82OS5yZXJlbmRlciA9IGZ1bmN0aW9uIHJlcmVuZGVyKCkgewogICAgICAvKiovCiAgICB9OwoKICAgIF9wcm90bzY5LnNldE91dGxldFN0YXRlID0gZnVuY3Rpb24gc2V0T3V0bGV0U3RhdGUoc3RhdGUpIHsKICAgICAgdGhpcy5yZWYudXBkYXRlKHN0YXRlKTsKICAgIH07CgogICAgX3Byb3RvNjkuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIC8qKi8KICAgIH07CgogICAgcmV0dXJuIE91dGxldFZpZXc7CiAgfSgpOwoKICBfZXhwb3J0cy5PdXRsZXRWaWV3ID0gT3V0bGV0VmlldzsKCiAgZnVuY3Rpb24gc2V0dXBBcHBsaWNhdGlvblJlZ2lzdHJ5KHJlZ2lzdHJ5KSB7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3NlcnZpY2U6LWdsaW1tZXItZW52aXJvbm1lbnQnLCAnYXBwZW5kT3BlcmF0aW9ucycsICdzZXJ2aWNlOi1kb20tdHJlZS1jb25zdHJ1Y3Rpb24nKTsKICAgIHJlZ2lzdHJ5LmluamVjdGlvbigncmVuZGVyZXInLCAnZW52JywgJ3NlcnZpY2U6LWdsaW1tZXItZW52aXJvbm1lbnQnKTsgLy8gYmVjYXVzZSB3ZSBhcmUgdXNpbmcgaW5qZWN0aW9ucyB3ZSBjYW4ndCB1c2UgaW5zdGFudGlhdGUgZmFsc2UKICAgIC8vIHdlIG5lZWQgdG8gdXNlIGJpbmQoKSB0byBjb3B5IHRoZSBmdW5jdGlvbiBzbyBmYWN0b3J5IGZvcgogICAgLy8gYXNzb2NpYXRpb24gd29uJ3QgbGVhawoKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdzZXJ2aWNlOi1kb20tYnVpbGRlcicsIHsKICAgICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUoX3JlZjM4KSB7CiAgICAgICAgdmFyIGJvb3RPcHRpb25zID0gX3JlZjM4LmJvb3RPcHRpb25zOwogICAgICAgIHZhciBfcmVuZGVyTW9kZSA9IGJvb3RPcHRpb25zLl9yZW5kZXJNb2RlOwoKICAgICAgICBzd2l0Y2ggKF9yZW5kZXJNb2RlKSB7CiAgICAgICAgICBjYXNlICdzZXJpYWxpemUnOgogICAgICAgICAgICByZXR1cm4gX25vZGUuc2VyaWFsaXplQnVpbGRlci5iaW5kKG51bGwpOwoKICAgICAgICAgIGNhc2UgJ3JlaHlkcmF0ZSc6CiAgICAgICAgICAgIHJldHVybiBfcnVudGltZTIucmVoeWRyYXRpb25CdWlsZGVyLmJpbmQobnVsbCk7CgogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgcmV0dXJuIF9ydW50aW1lMi5jbGllbnRCdWlsZGVyLmJpbmQobnVsbCk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICAgIHJlZ2lzdHJ5LmluamVjdGlvbignc2VydmljZTotZG9tLWJ1aWxkZXInLCAnYm9vdE9wdGlvbnMnLCAnLWVudmlyb25tZW50Om1haW4nKTsKICAgIHJlZ2lzdHJ5LmluamVjdGlvbigncmVuZGVyZXInLCAnYnVpbGRlcicsICdzZXJ2aWNlOi1kb20tYnVpbGRlcicpOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3Q1KCkpLCBSb290VGVtcGxhdGUpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdyZW5kZXJlcicsICdyb290VGVtcGxhdGUnLCAoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdDYoKSkpOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ3JlbmRlcmVyOi1kb20nLCBJbnRlcmFjdGl2ZVJlbmRlcmVyKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdyZW5kZXJlcjotaW5lcnQnLCBJbmVydFJlbmRlcmVyKTsKCiAgICBpZiAoX2Jyb3dzZXJFbnZpcm9ubWVudC5oYXNET00pIHsKICAgICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdzZXJ2aWNlOi1nbGltbWVyLWVudmlyb25tZW50JywgJ3VwZGF0ZU9wZXJhdGlvbnMnLCAnc2VydmljZTotZG9tLWNoYW5nZXMnKTsKICAgIH0KCiAgICByZWdpc3RyeS5yZWdpc3Rlcignc2VydmljZTotZG9tLWNoYW5nZXMnLCB7CiAgICAgIGNyZWF0ZTogZnVuY3Rpb24gY3JlYXRlKF9yZWYzOSkgewogICAgICAgIHZhciBkb2N1bWVudCA9IF9yZWYzOS5kb2N1bWVudDsKICAgICAgICByZXR1cm4gbmV3IF9ydW50aW1lMi5ET01DaGFuZ2VzKGRvY3VtZW50KTsKICAgICAgfQogICAgfSk7CiAgICByZWdpc3RyeS5yZWdpc3Rlcignc2VydmljZTotZG9tLXRyZWUtY29uc3RydWN0aW9uJywgewogICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShfcmVmNDApIHsKICAgICAgICB2YXIgZG9jdW1lbnQgPSBfcmVmNDAuZG9jdW1lbnQ7CiAgICAgICAgdmFyIEltcGxlbWVudGF0aW9uID0gX2Jyb3dzZXJFbnZpcm9ubWVudC5oYXNET00gPyBfcnVudGltZTIuRE9NVHJlZUNvbnN0cnVjdGlvbiA6IF9ub2RlLk5vZGVET01UcmVlQ29uc3RydWN0aW9uOwogICAgICAgIHJldHVybiBuZXcgSW1wbGVtZW50YXRpb24oZG9jdW1lbnQpOwogICAgICB9CiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHNldHVwRW5naW5lUmVnaXN0cnkocmVnaXN0cnkpIHsKICAgIHJlZ2lzdHJ5Lm9wdGlvbnNGb3JUeXBlKCd0ZW1wbGF0ZScsIHsKICAgICAgaW5zdGFudGlhdGU6IGZhbHNlCiAgICB9KTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCd2aWV3Oi1vdXRsZXQnLCBPdXRsZXRWaWV3KTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCd0ZW1wbGF0ZTotb3V0bGV0JywgT3V0bGV0VGVtcGxhdGUpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCd2aWV3Oi1vdXRsZXQnLCAndGVtcGxhdGUnLCAndGVtcGxhdGU6LW91dGxldCcpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdzZXJ2aWNlOi1kb20tY2hhbmdlcycsICdkb2N1bWVudCcsICdzZXJ2aWNlOi1kb2N1bWVudCcpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdzZXJ2aWNlOi1kb20tdHJlZS1jb25zdHJ1Y3Rpb24nLCAnZG9jdW1lbnQnLCAnc2VydmljZTotZG9jdW1lbnQnKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCgwLCBfY29udGFpbmVyLnByaXZhdGl6ZSkoX3RlbXBsYXRlT2JqZWN0NygpKSwgQ29tcG9uZW50VGVtcGxhdGUpOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ3NlcnZpY2U6LWdsaW1tZXItZW52aXJvbm1lbnQnLCBFbnZpcm9ubWVudCQxKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCgwLCBfY29udGFpbmVyLnByaXZhdGl6ZSkoX3RlbXBsYXRlT2JqZWN0OCgpKSwgVGVtcGxhdGVDb21waWxlcik7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3Q5KCkpLCAnZW52aXJvbm1lbnQnLCAnLWVudmlyb25tZW50Om1haW4nKTsKICAgIHJlZ2lzdHJ5Lm9wdGlvbnNGb3JUeXBlKCdoZWxwZXInLCB7CiAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgfSk7CiAgICByZWdpc3RyeS5yZWdpc3RlcignaGVscGVyOmxvYycsIGxvYyQxKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdjb21wb25lbnQ6LXRleHQtZmllbGQnLCBUZXh0RmllbGQpOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ2NvbXBvbmVudDotY2hlY2tib3gnLCBDaGVja2JveCk7CiAgICByZWdpc3RyeS5yZWdpc3RlcignY29tcG9uZW50OmxpbmstdG8nLCBMaW5rVG9Db21wb25lbnQpOwogICAgewogICAgICByZWdpc3RyeS5yZWdpc3RlcignY29tcG9uZW50OmlucHV0JywgSW5wdXQkMSk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCd0ZW1wbGF0ZTpjb21wb25lbnRzL2lucHV0JywgSW5wdXRUZW1wbGF0ZSk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdjb21wb25lbnQ6dGV4dGFyZWEnLCBUZXh0QXJlYSk7CiAgICB9CgogICAgaWYgKCFfZW52aXJvbm1lbnQyLkVOVi5fVEVNUExBVEVfT05MWV9HTElNTUVSX0NPTVBPTkVOVFMpIHsKICAgICAgcmVnaXN0cnkucmVnaXN0ZXIoKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3QxMCgpKSwgQ29tcG9uZW50KTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHNldENvbXBvbmVudE1hbmFnZXIoc3RyaW5nT3JGdW5jdGlvbiwgb2JqKSB7CiAgICB2YXIgZmFjdG9yeTsKCiAgICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5DT01QT05FTlRfTUFOQUdFUl9TVFJJTkdfTE9PS1VQICYmIHR5cGVvZiBzdHJpbmdPckZ1bmN0aW9uID09PSAnc3RyaW5nJykgewogICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdQYXNzaW5nIHRoZSBuYW1lIG9mIHRoZSBjb21wb25lbnQgbWFuYWdlciB0byAic2V0dXBDb21wb25lbnRNYW5hZ2VyIiBpcyBkZXByZWNhdGVkLiBQbGVhc2UgcGFzcyBhIGZ1bmN0aW9uIHRoYXQgcHJvZHVjZXMgYW4gaW5zdGFuY2Ugb2YgdGhlIG1hbmFnZXIuJywgZmFsc2UsIHsKICAgICAgICBpZDogJ2RlcHJlY2F0ZS1zdHJpbmctYmFzZWQtY29tcG9uZW50LW1hbmFnZXInLAogICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngvI3RvY19jb21wb25lbnQtbWFuYWdlci1zdHJpbmctbG9va3VwJwogICAgICB9KSk7CgogICAgICBmYWN0b3J5ID0gZnVuY3Rpb24gZmFjdG9yeShvd25lcikgewogICAgICAgIHJldHVybiBvd25lci5sb29rdXAoImNvbXBvbmVudC1tYW5hZ2VyOiIgKyBzdHJpbmdPckZ1bmN0aW9uKTsKICAgICAgfTsKICAgIH0gZWxzZSB7CiAgICAgIGZhY3RvcnkgPSBzdHJpbmdPckZ1bmN0aW9uOwogICAgfQoKICAgIHJldHVybiBzZXRNYW5hZ2VyKHsKICAgICAgZmFjdG9yeTogZmFjdG9yeSwKICAgICAgaW50ZXJuYWw6IGZhbHNlLAogICAgICB0eXBlOiAnY29tcG9uZW50JwogICAgfSwgb2JqKTsKICB9CgogIGZ1bmN0aW9uIGdldENvbXBvbmVudE1hbmFnZXIob2JqKSB7CiAgICB2YXIgd3JhcHBlciA9IGdldE1hbmFnZXIob2JqKTsKCiAgICBpZiAod3JhcHBlciAmJiAhd3JhcHBlci5pbnRlcm5hbCAmJiB3cmFwcGVyLnR5cGUgPT09ICdjb21wb25lbnQnKSB7CiAgICAgIHJldHVybiB3cmFwcGVyLmZhY3Rvcnk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogIH0KICAvKioKICAgIFtHbGltbWVyXShodHRwczovL2dpdGh1Yi5jb20vdGlsZGVpby9nbGltbWVyKSBpcyBhIHRlbXBsYXRpbmcgZW5naW5lIHVzZWQgYnkgRW1iZXIuanMgdGhhdCBpcyBjb21wYXRpYmxlIHdpdGggYSBzdWJzZXQgb2YgdGhlIFtIYW5kbGViYXJzXShodHRwOi8vaGFuZGxlYmFyc2pzLmNvbS8pIHN5bnRheC4KICAKICAgICMjIyBTaG93aW5nIGEgcHJvcGVydHkKICAKICAgIFRlbXBsYXRlcyBtYW5hZ2UgdGhlIGZsb3cgb2YgYW4gYXBwbGljYXRpb24ncyBVSSwgYW5kIGRpc3BsYXkgc3RhdGUgKHRocm91Z2gKICAgIHRoZSBET00pIHRvIGEgdXNlci4gRm9yIGV4YW1wbGUsIGdpdmVuIGEgY29tcG9uZW50IHdpdGggdGhlIHByb3BlcnR5ICJuYW1lIiwKICAgIHRoYXQgY29tcG9uZW50J3MgdGVtcGxhdGUgY2FuIHVzZSB0aGUgbmFtZSBpbiBzZXZlcmFsIHdheXM6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9wZXJzb24tcHJvZmlsZS5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBuYW1lOiAnSmlsbCcKICAgIH0pOwogICAgYGBgCiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvcGVyc29uLXByb2ZpbGUuaGJzCiAgICB7e25hbWV9fQogICAgPGRpdj57e25hbWV9fTwvZGl2PgogICAgPHNwYW4gZGF0YS1uYW1lPXt7bmFtZX19Pjwvc3Bhbj4KICAgIGBgYAogIAogICAgQW55IHRpbWUgdGhlICJuYW1lIiBwcm9wZXJ0eSBvbiB0aGUgY29tcG9uZW50IGNoYW5nZXMsIHRoZSBET00gd2lsbCBiZQogICAgdXBkYXRlZC4KICAKICAgIFByb3BlcnRpZXMgY2FuIGJlIGNoYWluZWQgYXMgd2VsbDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7YVVzZXJNb2RlbC5uYW1lfX0KICAgIDxkaXY+e3tsaXN0T2ZVc2Vycy5maXJzdE9iamVjdC5uYW1lfX08L2Rpdj4KICAgIGBgYAogIAogICAgIyMjIFVzaW5nIEVtYmVyIGhlbHBlcnMKICAKICAgIFdoZW4gY29udGVudCBpcyBwYXNzZWQgaW4gbXVzdGFjaGVzIGB7e319YCwgRW1iZXIgd2lsbCBmaXJzdCB0cnkgdG8gZmluZCBhIGhlbHBlcgogICAgb3IgY29tcG9uZW50IHdpdGggdGhhdCBuYW1lLiBGb3IgZXhhbXBsZSwgdGhlIGBpZmAgaGVscGVyOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3tpZiBuYW1lICJJIGhhdmUgYSBuYW1lIiAiSSBoYXZlIG5vIG5hbWUifX0KICAgIDxzcGFuIGRhdGEtaGFzLW5hbWU9e3tpZiBuYW1lIHRydWV9fT48L3NwYW4+CiAgICBgYGAKICAKICAgIFRoZSByZXR1cm5lZCB2YWx1ZSBpcyBwbGFjZWQgd2hlcmUgdGhlIGB7e319YCBpcyBjYWxsZWQuIFRoZSBhYm92ZSBzdHlsZSBpcwogICAgY2FsbGVkICJpbmxpbmUiLiBBIHNlY29uZCBzdHlsZSBvZiBoZWxwZXIgdXNhZ2UgaXMgY2FsbGVkICJibG9jayIuIEZvciBleGFtcGxlOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3sjaWYgbmFtZX19CiAgICBJIGhhdmUgYSBuYW1lCiAgICB7e2Vsc2V9fQogICAgSSBoYXZlIG5vIG5hbWUKICAgIHt7L2lmfX0KICAgIGBgYAogIAogICAgVGhlIGJsb2NrIGZvcm0gb2YgaGVscGVycyBhbGxvd3MgeW91IHRvIGNvbnRyb2wgaG93IHRoZSBVSSBpcyBjcmVhdGVkIGJhc2VkCiAgICBvbiB0aGUgdmFsdWVzIG9mIHByb3BlcnRpZXMuCiAgICBBIHRoaXJkIGZvcm0gb2YgaGVscGVyIGlzIGNhbGxlZCAibmVzdGVkIi4gRm9yIGV4YW1wbGUgaGVyZSB0aGUgY29uY2F0CiAgICBoZWxwZXIgd2lsbCBhZGQgIiBEb2UiIHRvIGEgZGlzcGxheWVkIG5hbWUgaWYgdGhlIHBlcnNvbiBoYXMgbm8gbGFzdCBuYW1lOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPHNwYW4gZGF0YS1uYW1lPXt7Y29uY2F0IGZpcnN0TmFtZSAoCiAgICBpZiBsYXN0TmFtZSAoY29uY2F0ICIgIiBsYXN0TmFtZSkgIkRvZSIKICAgICl9fT48L3NwYW4+CiAgICBgYGAKICAKICAgIEVtYmVyJ3MgYnVpbHQtaW4gaGVscGVycyBhcmUgZGVzY3JpYmVkIHVuZGVyIHRoZSBbRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnNdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMpCiAgICBuYW1lc3BhY2UuIERvY3VtZW50YXRpb24gb24gY3JlYXRpbmcgY3VzdG9tIGhlbHBlcnMgY2FuIGJlIGZvdW5kIHVuZGVyCiAgICBbaGVscGVyXSgvZW1iZXIvcmVsZWFzZS9mdW5jdGlvbnMvQGVtYmVyJTJGY29tcG9uZW50JTJGaGVscGVyL2hlbHBlcikgKG9yCiAgICB1bmRlciBbSGVscGVyXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0hlbHBlcikgaWYgYSBoZWxwZXIgcmVxdWlyZXMgYWNjZXNzIHRvCiAgICBkZXBlbmRlbmN5IGluamVjdGlvbikuCiAgCiAgICAjIyMgSW52b2tpbmcgYSBDb21wb25lbnQKICAKICAgIEVtYmVyIGNvbXBvbmVudHMgcmVwcmVzZW50IHN0YXRlIHRvIHRoZSBVSSBvZiBhbiBhcHBsaWNhdGlvbi4gRnVydGhlcgogICAgcmVhZGluZyBvbiBjb21wb25lbnRzIGNhbiBiZSBmb3VuZCB1bmRlciBbQ29tcG9uZW50XSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0NvbXBvbmVudCkuCiAgCiAgICBAbW9kdWxlIEBlbWJlci9jb21wb25lbnQKICAgIEBtYWluIEBlbWJlci9jb21wb25lbnQKICAgIEBwdWJsaWMKICAgKi8KCn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL21ldGEvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YS9saWIvbWV0YSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJjb3VudGVycyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9tZXRhLmNvdW50ZXJzOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlbGV0ZU1ldGEiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbWV0YS5kZWxldGVNZXRhOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIk1ldGEiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbWV0YS5NZXRhOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIm1ldGEiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbWV0YS5tZXRhOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInBlZWtNZXRhIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX21ldGEucGVla01ldGE7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0TWV0YSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9tZXRhLnNldE1ldGE7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiVU5ERUZJTkVEIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX21ldGEuVU5ERUZJTkVEOwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9tZXRhL2xpYi9tZXRhIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZ2xpbW1lci9yZWZlcmVuY2UiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX3V0aWxzLCBfZGVidWcsIF9yZWZlcmVuY2UpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLnNldE1ldGEgPSBzZXRNZXRhOwogIF9leHBvcnRzLnBlZWtNZXRhID0gcGVla01ldGE7CiAgX2V4cG9ydHMuZGVsZXRlTWV0YSA9IGRlbGV0ZU1ldGE7CiAgX2V4cG9ydHMuY291bnRlcnMgPSBfZXhwb3J0cy5tZXRhID0gX2V4cG9ydHMuTWV0YSA9IF9leHBvcnRzLlVOREVGSU5FRCA9IHZvaWQgMDsKICB2YXIgb2JqZWN0UHJvdG90eXBlID0gT2JqZWN0LnByb3RvdHlwZTsKICB2YXIgY291bnRlcnM7CiAgX2V4cG9ydHMuY291bnRlcnMgPSBjb3VudGVyczsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIF9leHBvcnRzLmNvdW50ZXJzID0gY291bnRlcnMgPSB7CiAgICAgIHBlZWtDYWxsczogMCwKICAgICAgcGVla1Byb3RvdHlwZVdhbGtzOiAwLAogICAgICBzZXRDYWxsczogMCwKICAgICAgZGVsZXRlQ2FsbHM6IDAsCiAgICAgIG1ldGFDYWxsczogMCwKICAgICAgbWV0YUluc3RhbnRpYXRlZDogMCwKICAgICAgbWF0Y2hpbmdMaXN0ZW5lcnNDYWxsczogMCwKICAgICAgb2JzZXJ2ZXJFdmVudHNDYWxsczogMCwKICAgICAgYWRkVG9MaXN0ZW5lcnNDYWxsczogMCwKICAgICAgcmVtb3ZlRnJvbUxpc3RlbmVyc0NhbGxzOiAwLAogICAgICByZW1vdmVBbGxMaXN0ZW5lcnNDYWxsczogMCwKICAgICAgbGlzdGVuZXJzSW5oZXJpdGVkOiAwLAogICAgICBsaXN0ZW5lcnNGbGF0dGVuZWQ6IDAsCiAgICAgIHBhcmVudExpc3RlbmVyc1VzZWQ6IDAsCiAgICAgIGZsYXR0ZW5lZExpc3RlbmVyc0NhbGxzOiAwLAogICAgICByZW9wZW5zQWZ0ZXJGbGF0dGVuOiAwLAogICAgICByZWFkYWJsZUxhenlDaGFpbnNDYWxsczogMCwKICAgICAgd3JpdGFibGVMYXp5Q2hhaW5zQ2FsbHM6IDAKICAgIH07CiAgfQogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKCiAgdmFyIFVOREVGSU5FRCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgndW5kZWZpbmVkJyk7CiAgX2V4cG9ydHMuVU5ERUZJTkVEID0gVU5ERUZJTkVEOwogIHZhciBjdXJyZW50TGlzdGVuZXJWZXJzaW9uID0gMTsKCiAgdmFyIE1ldGEgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBNZXRhKG9iaikgewogICAgICB0aGlzLl9saXN0ZW5lcnNWZXJzaW9uID0gMTsKICAgICAgdGhpcy5faW5oZXJpdGVkRW5kID0gLTE7CiAgICAgIHRoaXMuX2ZsYXR0ZW5lZFZlcnNpb24gPSAwOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGNvdW50ZXJzLm1ldGFJbnN0YW50aWF0ZWQrKzsKICAgICAgICB0aGlzLl92YWx1ZXMgPSB1bmRlZmluZWQ7CiAgICAgIH0KCiAgICAgIHRoaXMuX3BhcmVudCA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5fZGVzY3JpcHRvcnMgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuX3dhdGNoaW5nID0gdW5kZWZpbmVkOwogICAgICB0aGlzLl9taXhpbnMgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuX2RlcHMgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuX2NoYWluV2F0Y2hlcnMgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuX2NoYWlucyA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5fdGFnID0gdW5kZWZpbmVkOwogICAgICB0aGlzLl90YWdzID0gdW5kZWZpbmVkOyAvLyBpbml0aWFsIHZhbHVlIGZvciBhbGwgZmxhZ3MgcmlnaHQgbm93IGlzIGZhbHNlCiAgICAgIC8vIHNlZSBGTEFHUyBjb25zdCBmb3IgZGV0YWlsZWQgbGlzdCBvZiBmbGFncyB1c2VkCgogICAgICB0aGlzLl9mbGFncyA9IDAKICAgICAgLyogTk9ORSAqLwogICAgICA7IC8vIHVzZWQgb25seSBpbnRlcm5hbGx5CgogICAgICB0aGlzLnNvdXJjZSA9IG9iajsKICAgICAgdGhpcy5wcm90byA9IG9iai5jb25zdHJ1Y3RvciA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogb2JqLmNvbnN0cnVjdG9yLnByb3RvdHlwZTsKICAgICAgdGhpcy5fbGlzdGVuZXJzID0gdW5kZWZpbmVkOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBNZXRhLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uc2V0SW5pdGlhbGl6aW5nID0gZnVuY3Rpb24gc2V0SW5pdGlhbGl6aW5nKCkgewogICAgICB0aGlzLl9mbGFncyB8PSA4CiAgICAgIC8qIElOSVRJQUxJWklORyAqLwogICAgICA7CiAgICB9OwoKICAgIF9wcm90by51bnNldEluaXRpYWxpemluZyA9IGZ1bmN0aW9uIHVuc2V0SW5pdGlhbGl6aW5nKCkgewogICAgICB0aGlzLl9mbGFncyBePSA4CiAgICAgIC8qIElOSVRJQUxJWklORyAqLwogICAgICA7CiAgICB9OwoKICAgIF9wcm90by5pc0luaXRpYWxpemluZyA9IGZ1bmN0aW9uIGlzSW5pdGlhbGl6aW5nKCkgewogICAgICByZXR1cm4gdGhpcy5faGFzRmxhZyg4CiAgICAgIC8qIElOSVRJQUxJWklORyAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8uaXNQcm90b3R5cGVNZXRhID0gZnVuY3Rpb24gaXNQcm90b3R5cGVNZXRhKG9iaikgewogICAgICByZXR1cm4gdGhpcy5wcm90byA9PT0gdGhpcy5zb3VyY2UgJiYgdGhpcy5zb3VyY2UgPT09IG9iajsKICAgIH07CgogICAgX3Byb3RvLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICBpZiAodGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5zZXRNZXRhRGVzdHJveWVkKCk7IC8vIHJlbW92ZSBjaGFpbldhdGNoZXJzIHRvIHJlbW92ZSBjaXJjdWxhciByZWZlcmVuY2VzIHRoYXQgd291bGQgcHJldmVudCBHQwoKICAgICAgdmFyIGNoYWlucyA9IHRoaXMucmVhZGFibGVDaGFpbnMoKTsKCiAgICAgIGlmIChjaGFpbnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGNoYWlucy5kZXN0cm95KCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmlzU291cmNlRGVzdHJveWluZyA9IGZ1bmN0aW9uIGlzU291cmNlRGVzdHJveWluZygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2hhc0ZsYWcoMQogICAgICAvKiBTT1VSQ0VfREVTVFJPWUlORyAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8uc2V0U291cmNlRGVzdHJveWluZyA9IGZ1bmN0aW9uIHNldFNvdXJjZURlc3Ryb3lpbmcoKSB7CiAgICAgIHRoaXMuX2ZsYWdzIHw9IDEKICAgICAgLyogU09VUkNFX0RFU1RST1lJTkcgKi8KICAgICAgOwogICAgfTsKCiAgICBfcHJvdG8uaXNTb3VyY2VEZXN0cm95ZWQgPSBmdW5jdGlvbiBpc1NvdXJjZURlc3Ryb3llZCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2hhc0ZsYWcoMgogICAgICAvKiBTT1VSQ0VfREVTVFJPWUVEICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90by5zZXRTb3VyY2VEZXN0cm95ZWQgPSBmdW5jdGlvbiBzZXRTb3VyY2VEZXN0cm95ZWQoKSB7CiAgICAgIHRoaXMuX2ZsYWdzIHw9IDIKICAgICAgLyogU09VUkNFX0RFU1RST1lFRCAqLwogICAgICA7CiAgICB9OwoKICAgIF9wcm90by5pc01ldGFEZXN0cm95ZWQgPSBmdW5jdGlvbiBpc01ldGFEZXN0cm95ZWQoKSB7CiAgICAgIHJldHVybiB0aGlzLl9oYXNGbGFnKDQKICAgICAgLyogTUVUQV9ERVNUUk9ZRUQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvLnNldE1ldGFEZXN0cm95ZWQgPSBmdW5jdGlvbiBzZXRNZXRhRGVzdHJveWVkKCkgewogICAgICB0aGlzLl9mbGFncyB8PSA0CiAgICAgIC8qIE1FVEFfREVTVFJPWUVEICovCiAgICAgIDsKICAgIH07CgogICAgX3Byb3RvLl9oYXNGbGFnID0gZnVuY3Rpb24gX2hhc0ZsYWcoZmxhZykgewogICAgICByZXR1cm4gKHRoaXMuX2ZsYWdzICYgZmxhZykgPT09IGZsYWc7CiAgICB9OwoKICAgIF9wcm90by5fZ2V0T3JDcmVhdGVPd25NYXAgPSBmdW5jdGlvbiBfZ2V0T3JDcmVhdGVPd25NYXAoa2V5KSB7CiAgICAgIHJldHVybiB0aGlzW2tleV0gfHwgKHRoaXNba2V5XSA9IE9iamVjdC5jcmVhdGUobnVsbCkpOwogICAgfTsKCiAgICBfcHJvdG8uX2dldE9yQ3JlYXRlT3duU2V0ID0gZnVuY3Rpb24gX2dldE9yQ3JlYXRlT3duU2V0KGtleSkgewogICAgICByZXR1cm4gdGhpc1trZXldIHx8ICh0aGlzW2tleV0gPSBuZXcgU2V0KCkpOwogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRJbmhlcml0ZWQxID0gZnVuY3Rpb24gX2ZpbmRJbmhlcml0ZWQxKGtleSkgewogICAgICB2YXIgcG9pbnRlciA9IHRoaXM7CgogICAgICB3aGlsZSAocG9pbnRlciAhPT0gbnVsbCkgewogICAgICAgIHZhciBtYXAgPSBwb2ludGVyW2tleV07CgogICAgICAgIGlmIChtYXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcmV0dXJuIG1hcDsKICAgICAgICB9CgogICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRJbmhlcml0ZWQyID0gZnVuY3Rpb24gX2ZpbmRJbmhlcml0ZWQyKGtleSwgc3Via2V5KSB7CiAgICAgIHZhciBwb2ludGVyID0gdGhpczsKCiAgICAgIHdoaWxlIChwb2ludGVyICE9PSBudWxsKSB7CiAgICAgICAgdmFyIG1hcCA9IHBvaW50ZXJba2V5XTsKCiAgICAgICAgaWYgKG1hcCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YXIgdmFsdWUgPSBtYXBbc3Via2V5XTsKCiAgICAgICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwb2ludGVyID0gcG9pbnRlci5wYXJlbnQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9maW5kSW5oZXJpdGVkMyA9IGZ1bmN0aW9uIF9maW5kSW5oZXJpdGVkMyhrZXksIHN1YmtleSwgc3Vic3Via2V5KSB7CiAgICAgIHZhciBwb2ludGVyID0gdGhpczsKCiAgICAgIHdoaWxlIChwb2ludGVyICE9PSBudWxsKSB7CiAgICAgICAgdmFyIG1hcCA9IHBvaW50ZXJba2V5XTsKCiAgICAgICAgaWYgKG1hcCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YXIgc3VibWFwID0gbWFwW3N1YmtleV07CgogICAgICAgICAgaWYgKHN1Ym1hcCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHZhciB2YWx1ZSA9IHN1Ym1hcFtzdWJzdWJrZXldOwoKICAgICAgICAgICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRJbmhlcml0ZWRNYXAgPSBmdW5jdGlvbiBfZmluZEluaGVyaXRlZE1hcChrZXksIHN1YmtleSkgewogICAgICB2YXIgcG9pbnRlciA9IHRoaXM7CgogICAgICB3aGlsZSAocG9pbnRlciAhPT0gbnVsbCkgewogICAgICAgIHZhciBtYXAgPSBwb2ludGVyW2tleV07CgogICAgICAgIGlmIChtYXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdmFyIHZhbHVlID0gbWFwLmdldChzdWJrZXkpOwoKICAgICAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2hhc0luSW5oZXJpdGVkU2V0ID0gZnVuY3Rpb24gX2hhc0luSW5oZXJpdGVkU2V0KGtleSwgdmFsdWUpIHsKICAgICAgdmFyIHBvaW50ZXIgPSB0aGlzOwoKICAgICAgd2hpbGUgKHBvaW50ZXIgIT09IG51bGwpIHsKICAgICAgICB2YXIgc2V0ID0gcG9pbnRlcltrZXldOwoKICAgICAgICBpZiAoc2V0ICE9PSB1bmRlZmluZWQgJiYgc2V0Lmhhcyh2YWx1ZSkpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgcG9pbnRlciA9IHBvaW50ZXIucGFyZW50OwogICAgICB9CgogICAgICByZXR1cm4gZmFsc2U7CiAgICB9IC8vIEltcGxlbWVudHMgYSBtZW1iZXIgdGhhdCBwcm92aWRlcyBhIGxhemlseSBjcmVhdGVkIG1hcCBvZiBtYXBzLAogICAgLy8gd2l0aCBpbmhlcml0YW5jZSBhdCBib3RoIGxldmVscy4KICAgIDsKCiAgICBfcHJvdG8ud3JpdGVEZXBzID0gZnVuY3Rpb24gd3JpdGVEZXBzKHN1YmtleSwgaXRlbWtleSwgY291bnQpIHsKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNNZXRhRGVzdHJveWVkKCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSh0aGlzLmlzTWV0YURlc3Ryb3llZCgpID8gIkNhbm5vdCBtb2RpZnkgZGVwZW5kZW50IGtleXMgZm9yIGAiICsgaXRlbWtleSArICJgIG9uIGAiICsgKDAsIF91dGlscy50b1N0cmluZykodGhpcy5zb3VyY2UpICsgImAgYWZ0ZXIgaXQgaGFzIGJlZW4gZGVzdHJveWVkLiIgOiAnJywgIXRoaXMuaXNNZXRhRGVzdHJveWVkKCkpKTsKCiAgICAgIHZhciBvdXRlck1hcCA9IHRoaXMuX2dldE9yQ3JlYXRlT3duTWFwKCdfZGVwcycpOwoKICAgICAgdmFyIGlubmVyTWFwID0gb3V0ZXJNYXBbc3Via2V5XTsKCiAgICAgIGlmIChpbm5lck1hcCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgaW5uZXJNYXAgPSBvdXRlck1hcFtzdWJrZXldID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgfQoKICAgICAgaW5uZXJNYXBbaXRlbWtleV0gPSBjb3VudDsKICAgIH07CgogICAgX3Byb3RvLnBlZWtEZXBzID0gZnVuY3Rpb24gcGVla0RlcHMoc3Via2V5LCBpdGVta2V5KSB7CiAgICAgIHZhciB2YWwgPSB0aGlzLl9maW5kSW5oZXJpdGVkMygnX2RlcHMnLCBzdWJrZXksIGl0ZW1rZXkpOwoKICAgICAgcmV0dXJuIHZhbCA9PT0gdW5kZWZpbmVkID8gMCA6IHZhbDsKICAgIH07CgogICAgX3Byb3RvLmhhc0RlcHMgPSBmdW5jdGlvbiBoYXNEZXBzKHN1YmtleSkgewogICAgICB2YXIgdmFsID0gdGhpcy5fZmluZEluaGVyaXRlZDIoJ19kZXBzJywgc3Via2V5KTsKCiAgICAgIHJldHVybiB2YWwgIT09IHVuZGVmaW5lZDsKICAgIH07CgogICAgX3Byb3RvLmZvckVhY2hJbkRlcHMgPSBmdW5jdGlvbiBmb3JFYWNoSW5EZXBzKHN1YmtleSwgZm4pIHsKICAgICAgdmFyIHBvaW50ZXIgPSB0aGlzOwogICAgICB2YXIgc2VlbjsKCiAgICAgIHdoaWxlIChwb2ludGVyICE9PSBudWxsKSB7CiAgICAgICAgdmFyIG1hcCA9IHBvaW50ZXIuX2RlcHM7CgogICAgICAgIGlmIChtYXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdmFyIGlubmVyTWFwID0gbWFwW3N1YmtleV07CgogICAgICAgICAgaWYgKGlubmVyTWFwICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgc2VlbiA9IHNlZW4gPT09IHVuZGVmaW5lZCA/IG5ldyBTZXQoKSA6IHNlZW47CgogICAgICAgICAgICBmb3IgKHZhciBpbm5lcktleSBpbiBpbm5lck1hcCkgewogICAgICAgICAgICAgIGlmICghc2Vlbi5oYXMoaW5uZXJLZXkpKSB7CiAgICAgICAgICAgICAgICBzZWVuLmFkZChpbm5lcktleSk7CgogICAgICAgICAgICAgICAgaWYgKGlubmVyTWFwW2lubmVyS2V5XSA+IDApIHsKICAgICAgICAgICAgICAgICAgZm4oaW5uZXJLZXkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcG9pbnRlciA9IHBvaW50ZXIucGFyZW50OwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by53cml0YWJsZVRhZ3MgPSBmdW5jdGlvbiB3cml0YWJsZVRhZ3MoKSB7CiAgICAgIHJldHVybiB0aGlzLl9nZXRPckNyZWF0ZU93bk1hcCgnX3RhZ3MnKTsKICAgIH07CgogICAgX3Byb3RvLnJlYWRhYmxlVGFncyA9IGZ1bmN0aW9uIHJlYWRhYmxlVGFncygpIHsKICAgICAgcmV0dXJuIHRoaXMuX3RhZ3M7CiAgICB9OwoKICAgIF9wcm90by53cml0YWJsZVRhZyA9IGZ1bmN0aW9uIHdyaXRhYmxlVGFnKCkgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMuaXNNZXRhRGVzdHJveWVkKCkgPyAiQ2Fubm90IGNyZWF0ZSBhIG5ldyB0YWcgZm9yIGAiICsgKDAsIF91dGlscy50b1N0cmluZykodGhpcy5zb3VyY2UpICsgImAgYWZ0ZXIgaXQgaGFzIGJlZW4gZGVzdHJveWVkLiIgOiAnJywgIXRoaXMuaXNNZXRhRGVzdHJveWVkKCkpKTsKICAgICAgdmFyIHJldCA9IHRoaXMuX3RhZzsKCiAgICAgIGlmIChyZXQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldCA9IHRoaXMuX3RhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJldDsKICAgIH07CgogICAgX3Byb3RvLnJlYWRhYmxlVGFnID0gZnVuY3Rpb24gcmVhZGFibGVUYWcoKSB7CiAgICAgIHJldHVybiB0aGlzLl90YWc7CiAgICB9OwoKICAgIF9wcm90by53cml0YWJsZUxhenlDaGFpbnNGb3IgPSBmdW5jdGlvbiB3cml0YWJsZUxhenlDaGFpbnNGb3Ioa2V5KSB7CiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICBjb3VudGVycy53cml0YWJsZUxhenlDaGFpbnNDYWxscysrOwogICAgICB9CgogICAgICB2YXIgbGF6eUNoYWlucyA9IHRoaXMuX2dldE9yQ3JlYXRlT3duTWFwKCdfbGF6eUNoYWlucycpOwoKICAgICAgaWYgKCEoa2V5IGluIGxhenlDaGFpbnMpKSB7CiAgICAgICAgbGF6eUNoYWluc1trZXldID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGxhenlDaGFpbnNba2V5XTsKICAgIH07CgogICAgX3Byb3RvLnJlYWRhYmxlTGF6eUNoYWluc0ZvciA9IGZ1bmN0aW9uIHJlYWRhYmxlTGF6eUNoYWluc0ZvcihrZXkpIHsKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGNvdW50ZXJzLnJlYWRhYmxlTGF6eUNoYWluc0NhbGxzKys7CiAgICAgIH0KCiAgICAgIHZhciBsYXp5Q2hhaW5zID0gdGhpcy5fbGF6eUNoYWluczsKCiAgICAgIGlmIChsYXp5Q2hhaW5zICE9PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gbGF6eUNoYWluc1trZXldOwogICAgICB9CgogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfTsKCiAgICBfcHJvdG8ud3JpdGFibGVDaGFpbldhdGNoZXJzID0gZnVuY3Rpb24gd3JpdGFibGVDaGFpbldhdGNoZXJzKGNyZWF0ZSkgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMuaXNNZXRhRGVzdHJveWVkKCkgPyAiQ2Fubm90IGNyZWF0ZSBhIG5ldyBjaGFpbiB3YXRjaGVyIGZvciBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKHRoaXMuc291cmNlKSArICJgIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CiAgICAgIHZhciByZXQgPSB0aGlzLl9jaGFpbldhdGNoZXJzOwoKICAgICAgaWYgKHJldCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0ID0gdGhpcy5fY2hhaW5XYXRjaGVycyA9IGNyZWF0ZSh0aGlzLnNvdXJjZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiByZXQ7CiAgICB9OwoKICAgIF9wcm90by5yZWFkYWJsZUNoYWluV2F0Y2hlcnMgPSBmdW5jdGlvbiByZWFkYWJsZUNoYWluV2F0Y2hlcnMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9jaGFpbldhdGNoZXJzOwogICAgfTsKCiAgICBfcHJvdG8ud3JpdGFibGVDaGFpbnMgPSBmdW5jdGlvbiB3cml0YWJsZUNoYWlucyhjcmVhdGUpIHsKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNNZXRhRGVzdHJveWVkKCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSh0aGlzLmlzTWV0YURlc3Ryb3llZCgpID8gIkNhbm5vdCBjcmVhdGUgYSBuZXcgY2hhaW5zIGZvciBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKHRoaXMuc291cmNlKSArICJgIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CiAgICAgIHZhciByZXQgPSB0aGlzLl9jaGFpbnM7CgogICAgICBpZiAocmV0ID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLl9jaGFpbnMgPSByZXQgPSBjcmVhdGUodGhpcy5zb3VyY2UpOwogICAgICAgIHZhciBwYXJlbnQgPSB0aGlzLnBhcmVudDsKCiAgICAgICAgaWYgKHBhcmVudCAhPT0gbnVsbCkgewogICAgICAgICAgdmFyIHBhcmVudENoYWlucyA9IHBhcmVudC53cml0YWJsZUNoYWlucyhjcmVhdGUpOwogICAgICAgICAgcGFyZW50Q2hhaW5zLmNvcHlUbyhyZXQpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHJldDsKICAgIH07CgogICAgX3Byb3RvLnJlYWRhYmxlQ2hhaW5zID0gZnVuY3Rpb24gcmVhZGFibGVDaGFpbnMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9maW5kSW5oZXJpdGVkMSgnX2NoYWlucycpOwogICAgfTsKCiAgICBfcHJvdG8ud3JpdGVXYXRjaGluZyA9IGZ1bmN0aW9uIHdyaXRlV2F0Y2hpbmcoc3Via2V5LCB2YWx1ZSkgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMuaXNNZXRhRGVzdHJveWVkKCkgPyAiQ2Fubm90IHVwZGF0ZSB3YXRjaGVycyBmb3IgYCIgKyBzdWJrZXkgKyAiYCBvbiBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKHRoaXMuc291cmNlKSArICJgIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CgogICAgICB2YXIgbWFwID0gdGhpcy5fZ2V0T3JDcmVhdGVPd25NYXAoJ193YXRjaGluZycpOwoKICAgICAgbWFwW3N1YmtleV0gPSB2YWx1ZTsKICAgIH07CgogICAgX3Byb3RvLnBlZWtXYXRjaGluZyA9IGZ1bmN0aW9uIHBlZWtXYXRjaGluZyhzdWJrZXkpIHsKICAgICAgdmFyIGNvdW50ID0gdGhpcy5fZmluZEluaGVyaXRlZDIoJ193YXRjaGluZycsIHN1YmtleSk7CgogICAgICByZXR1cm4gY291bnQgPT09IHVuZGVmaW5lZCA/IDAgOiBjb3VudDsKICAgIH07CgogICAgX3Byb3RvLmFkZE1peGluID0gZnVuY3Rpb24gYWRkTWl4aW4obWl4aW4pIHsKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNNZXRhRGVzdHJveWVkKCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSh0aGlzLmlzTWV0YURlc3Ryb3llZCgpID8gIkNhbm5vdCBhZGQgbWl4aW5zIG9mIGAiICsgKDAsIF91dGlscy50b1N0cmluZykobWl4aW4pICsgImAgb24gYCIgKyAoMCwgX3V0aWxzLnRvU3RyaW5nKSh0aGlzLnNvdXJjZSkgKyAiYCBjYWxsIGFkZE1peGluIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CgogICAgICB2YXIgc2V0ID0gdGhpcy5fZ2V0T3JDcmVhdGVPd25TZXQoJ19taXhpbnMnKTsKCiAgICAgIHNldC5hZGQobWl4aW4pOwogICAgfTsKCiAgICBfcHJvdG8uaGFzTWl4aW4gPSBmdW5jdGlvbiBoYXNNaXhpbihtaXhpbikgewogICAgICByZXR1cm4gdGhpcy5faGFzSW5Jbmhlcml0ZWRTZXQoJ19taXhpbnMnLCBtaXhpbik7CiAgICB9OwoKICAgIF9wcm90by5mb3JFYWNoTWl4aW5zID0gZnVuY3Rpb24gZm9yRWFjaE1peGlucyhmbikgewogICAgICB2YXIgcG9pbnRlciA9IHRoaXM7CiAgICAgIHZhciBzZWVuOwoKICAgICAgd2hpbGUgKHBvaW50ZXIgIT09IG51bGwpIHsKICAgICAgICB2YXIgc2V0ID0gcG9pbnRlci5fbWl4aW5zOwoKICAgICAgICBpZiAoc2V0ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHNlZW4gPSBzZWVuID09PSB1bmRlZmluZWQgPyBuZXcgU2V0KCkgOiBzZWVuOyAvLyBUT0RPIGNsZWFudXAgdHlwaW5nIGhlcmUKCiAgICAgICAgICBzZXQuZm9yRWFjaChmdW5jdGlvbiAobWl4aW4pIHsKICAgICAgICAgICAgaWYgKCFzZWVuLmhhcyhtaXhpbikpIHsKICAgICAgICAgICAgICBzZWVuLmFkZChtaXhpbik7CiAgICAgICAgICAgICAgZm4obWl4aW4pOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ud3JpdGVEZXNjcmlwdG9ycyA9IGZ1bmN0aW9uIHdyaXRlRGVzY3JpcHRvcnMoc3Via2V5LCB2YWx1ZSkgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMuaXNNZXRhRGVzdHJveWVkKCkgPyAiQ2Fubm90IHVwZGF0ZSBkZXNjcmlwdG9ycyBmb3IgYCIgKyBzdWJrZXkgKyAiYCBvbiBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKHRoaXMuc291cmNlKSArICJgIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CiAgICAgIHZhciBtYXAgPSB0aGlzLl9kZXNjcmlwdG9ycyB8fCAodGhpcy5fZGVzY3JpcHRvcnMgPSBuZXcgTWFwKCkpOwogICAgICBtYXAuc2V0KHN1YmtleSwgdmFsdWUpOwogICAgfTsKCiAgICBfcHJvdG8ucGVla0Rlc2NyaXB0b3JzID0gZnVuY3Rpb24gcGVla0Rlc2NyaXB0b3JzKHN1YmtleSkgewogICAgICB2YXIgcG9zc2libGVEZXNjID0gdGhpcy5fZmluZEluaGVyaXRlZE1hcCgnX2Rlc2NyaXB0b3JzJywgc3Via2V5KTsKCiAgICAgIHJldHVybiBwb3NzaWJsZURlc2MgPT09IFVOREVGSU5FRCA/IHVuZGVmaW5lZCA6IHBvc3NpYmxlRGVzYzsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZURlc2NyaXB0b3JzID0gZnVuY3Rpb24gcmVtb3ZlRGVzY3JpcHRvcnMoc3Via2V5KSB7CiAgICAgIHRoaXMud3JpdGVEZXNjcmlwdG9ycyhzdWJrZXksIFVOREVGSU5FRCk7CiAgICB9OwoKICAgIF9wcm90by5mb3JFYWNoRGVzY3JpcHRvcnMgPSBmdW5jdGlvbiBmb3JFYWNoRGVzY3JpcHRvcnMoZm4pIHsKICAgICAgdmFyIHBvaW50ZXIgPSB0aGlzOwogICAgICB2YXIgc2VlbjsKCiAgICAgIHdoaWxlIChwb2ludGVyICE9PSBudWxsKSB7CiAgICAgICAgdmFyIG1hcCA9IHBvaW50ZXIuX2Rlc2NyaXB0b3JzOwoKICAgICAgICBpZiAobWFwICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHNlZW4gPSBzZWVuID09PSB1bmRlZmluZWQgPyBuZXcgU2V0KCkgOiBzZWVuOwogICAgICAgICAgbWFwLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHsKICAgICAgICAgICAgaWYgKCFzZWVuLmhhcyhrZXkpKSB7CiAgICAgICAgICAgICAgc2Vlbi5hZGQoa2V5KTsKCiAgICAgICAgICAgICAgaWYgKHZhbHVlICE9PSBVTkRFRklORUQpIHsKICAgICAgICAgICAgICAgIGZuKGtleSwgdmFsdWUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfQoKICAgICAgICBwb2ludGVyID0gcG9pbnRlci5wYXJlbnQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmFkZFRvTGlzdGVuZXJzID0gZnVuY3Rpb24gYWRkVG9MaXN0ZW5lcnMoZXZlbnROYW1lLCB0YXJnZXQsIG1ldGhvZCwgb25jZSwgc3luYykgewogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgY291bnRlcnMuYWRkVG9MaXN0ZW5lcnNDYWxscysrOwogICAgICB9CgogICAgICB0aGlzLnB1c2hMaXN0ZW5lcihldmVudE5hbWUsIHRhcmdldCwgbWV0aG9kLCBvbmNlID8gMQogICAgICAvKiBPTkNFICovCiAgICAgIDogMAogICAgICAvKiBBREQgKi8KICAgICAgLCBzeW5jKTsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUZyb21MaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVGcm9tTGlzdGVuZXJzKGV2ZW50TmFtZSwgdGFyZ2V0LCBtZXRob2QpIHsKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGNvdW50ZXJzLnJlbW92ZUZyb21MaXN0ZW5lcnNDYWxscysrOwogICAgICB9CgogICAgICB0aGlzLnB1c2hMaXN0ZW5lcihldmVudE5hbWUsIHRhcmdldCwgbWV0aG9kLCAyCiAgICAgIC8qIFJFTU9WRSAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8ucHVzaExpc3RlbmVyID0gZnVuY3Rpb24gcHVzaExpc3RlbmVyKGV2ZW50LCB0YXJnZXQsIG1ldGhvZCwga2luZCwgc3luYykgewogICAgICBpZiAoc3luYyA9PT0gdm9pZCAwKSB7CiAgICAgICAgc3luYyA9IGZhbHNlOwogICAgICB9CgogICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy53cml0YWJsZUxpc3RlbmVycygpOwogICAgICB2YXIgaSA9IGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnMsIGV2ZW50LCB0YXJnZXQsIG1ldGhvZCk7IC8vIHJlbW92ZSBpZiBmb3VuZCBsaXN0ZW5lciB3YXMgaW5oZXJpdGVkCgogICAgICBpZiAoaSAhPT0gLTEgJiYgaSA8IHRoaXMuX2luaGVyaXRlZEVuZCkgewogICAgICAgIGxpc3RlbmVycy5zcGxpY2UoaSwgMSk7CiAgICAgICAgdGhpcy5faW5oZXJpdGVkRW5kLS07CiAgICAgICAgaSA9IC0xOwogICAgICB9IC8vIGlmIG5vdCBmb3VuZCwgcHVzaC4gTm90ZSB0aGF0IHdlIG11c3QgYWx3YXlzIHB1c2ggaWYgYSBsaXN0ZW5lciBpcyBub3QKICAgICAgLy8gZm91bmQsIGV2ZW4gaW4gdGhlIGNhc2Ugb2YgYSBmdW5jdGlvbiBsaXN0ZW5lciByZW1vdmUsIGJlY2F1c2Ugd2UgbWF5IGJlCiAgICAgIC8vIGF0dGVtcHRpbmcgdG8gYWRkIG9yIHJlbW92ZSBsaXN0ZW5lcnMgX2JlZm9yZV8gZmxhdHRlbmluZyBoYXMgb2NjdXJlZC4KCgogICAgICBpZiAoaSA9PT0gLTEpIHsKICAgICAgICAoZmFsc2UgJiYgISghKHRoaXMuaXNQcm90b3R5cGVNZXRhKHRoaXMuc291cmNlKSAmJiB0eXBlb2YgbWV0aG9kID09PSAnZnVuY3Rpb24nKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgY2Fubm90IGFkZCBmdW5jdGlvbiBsaXN0ZW5lcnMgdG8gcHJvdG90eXBlcy4gQ29udmVydCB0aGUgbGlzdGVuZXIgdG8gYSBzdHJpbmcgbGlzdGVuZXIsIG9yIGFkZCBpdCB0byB0aGUgaW5zdGFuY2UgaW5zdGVhZC4nLCAhKHRoaXMuaXNQcm90b3R5cGVNZXRhKHRoaXMuc291cmNlKSAmJiB0eXBlb2YgbWV0aG9kID09PSAnZnVuY3Rpb24nKSkpOwogICAgICAgIChmYWxzZSAmJiAhKCEoIXRoaXMuaXNQcm90b3R5cGVNZXRhKHRoaXMuc291cmNlKSAmJiB0eXBlb2YgbWV0aG9kID09PSAnZnVuY3Rpb24nICYmIGtpbmQgPT09IDIKICAgICAgICAvKiBSRU1PVkUgKi8KICAgICAgICApKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gcmVtb3ZlIGEgZnVuY3Rpb24gbGlzdGVuZXIgd2hpY2ggZGlkIG5vdCBleGlzdCBvbiB0aGUgaW5zdGFuY2UsIHdoaWNoIG1lYW5zIHlvdSBtYXkgaGF2ZSBhdHRlbXB0ZWQgdG8gcmVtb3ZlIGl0IGJlZm9yZSBpdCB3YXMgYWRkZWQuJywgISghdGhpcy5pc1Byb3RvdHlwZU1ldGEodGhpcy5zb3VyY2UpICYmIHR5cGVvZiBtZXRob2QgPT09ICdmdW5jdGlvbicgJiYga2luZCA9PT0gMikpKTsKICAgICAgICBsaXN0ZW5lcnMucHVzaCh7CiAgICAgICAgICBldmVudDogZXZlbnQsCiAgICAgICAgICB0YXJnZXQ6IHRhcmdldCwKICAgICAgICAgIG1ldGhvZDogbWV0aG9kLAogICAgICAgICAga2luZDoga2luZCwKICAgICAgICAgIHN5bmM6IHN5bmMKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07IC8vIElmIHRoZSBsaXN0ZW5lciBpcyBvdXIgb3duIGxpc3RlbmVyIGFuZCB3ZSBhcmUgdHJ5aW5nIHRvIHJlbW92ZSBpdCwgd2UKICAgICAgICAvLyB3YW50IHRvIHNwbGljZSBpdCBvdXQgZW50aXJlbHkgc28gd2UgZG9uJ3QgaG9sZCBvbnRvIGEgcmVmZXJlbmNlLgoKICAgICAgICBpZiAoa2luZCA9PT0gMgogICAgICAgIC8qIFJFTU9WRSAqLwogICAgICAgICYmIGxpc3RlbmVyLmtpbmQgIT09IDIKICAgICAgICAvKiBSRU1PVkUgKi8KICAgICAgICApIHsKICAgICAgICAgICAgbGlzdGVuZXJzLnNwbGljZShpLCAxKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAoZmFsc2UgJiYgISghKGxpc3RlbmVyLmtpbmQgPT09IDAKICAgICAgICAgIC8qIEFERCAqLwogICAgICAgICAgJiYga2luZCA9PT0gMAogICAgICAgICAgLyogQUREICovCiAgICAgICAgICAmJiBsaXN0ZW5lci5zeW5jICE9PSBzeW5jKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgYXR0ZW1wdGVkIHRvIGFkZCBhbiBvYnNlcnZlciBmb3IgdGhlIHNhbWUgbWV0aG9kIG9uICciICsgZXZlbnQuc3BsaXQoJzonKVswXSArICInIHR3aWNlIHRvICIgKyB0YXJnZXQgKyAiIGFzIGJvdGggc3luYyBhbmQgYXN5bmMuIE9ic2VydmVycyBtdXN0IGJlIGVpdGhlciBzeW5jIG9yIGFzeW5jLCB0aGV5IGNhbm5vdCBiZSBib3RoLiBUaGlzIGlzIGxpa2VseSBhIG1pc3Rha2UsIHlvdSBzaG91bGQgZWl0aGVyIHJlbW92ZSB0aGUgY29kZSB0aGF0IGFkZGVkIHRoZSBvYnNlcnZlciBhIHNlY29uZCB0aW1lLCBvciB1cGRhdGUgaXQgdG8gYWx3YXlzIGJlIHN5bmMgb3IgYXN5bmMuIFRoZSBtZXRob2Qgd2FzICIgKyBtZXRob2QgKyAiLiIsICEobGlzdGVuZXIua2luZCA9PT0gMCAmJiBraW5kID09PSAwICYmIGxpc3RlbmVyLnN5bmMgIT09IHN5bmMpKSk7IC8vIHVwZGF0ZSBvd24gbGlzdGVuZXIKCiAgICAgICAgICBsaXN0ZW5lci5raW5kID0ga2luZDsKICAgICAgICAgIGxpc3RlbmVyLnN5bmMgPSBzeW5jOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ud3JpdGFibGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiB3cml0YWJsZUxpc3RlbmVycygpIHsKICAgICAgLy8gQ2hlY2sgaWYgd2UgbmVlZCB0byBpbnZhbGlkYXRlIGFuZCByZWZsYXR0ZW4uIFdlIG5lZWQgdG8gZG8gdGhpcyBpZiB3ZQogICAgICAvLyBoYXZlIGFscmVhZHkgZmxhdHRlbmVkIChmbGF0dGVuZWQgdmVyc2lvbiBpcyB0aGUgY3VycmVudCB2ZXJzaW9uKSBhbmQKICAgICAgLy8gd2UgYXJlIGVpdGhlciB3cml0aW5nIHRvIGEgcHJvdG90eXBlIG1ldGEgT1Igd2UgaGF2ZSBuZXZlciBpbmhlcml0ZWQsIGFuZAogICAgICAvLyBtYXkgaGF2ZSBjYWNoZWQgdGhlIHBhcmVudCdzIGxpc3RlbmVycy4KICAgICAgaWYgKHRoaXMuX2ZsYXR0ZW5lZFZlcnNpb24gPT09IGN1cnJlbnRMaXN0ZW5lclZlcnNpb24gJiYgKHRoaXMuc291cmNlID09PSB0aGlzLnByb3RvIHx8IHRoaXMuX2luaGVyaXRlZEVuZCA9PT0gLTEpKSB7CiAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgIGNvdW50ZXJzLnJlb3BlbnNBZnRlckZsYXR0ZW4rKzsKICAgICAgICB9CgogICAgICAgIGN1cnJlbnRMaXN0ZW5lclZlcnNpb24rKzsKICAgICAgfSAvLyBJbmhlcml0ZWQgZW5kIGhhcyBub3QgYmVlbiBzZXQsIHRoZW4gd2UgaGF2ZSBuZXZlciBjcmVhdGVkIG91ciBvd24KICAgICAgLy8gbGlzdGVuZXJzLCBidXQgbWF5IGhhdmUgY2FjaGVkIHRoZSBwYXJlbnQncwoKCiAgICAgIGlmICh0aGlzLl9pbmhlcml0ZWRFbmQgPT09IC0xKSB7CiAgICAgICAgdGhpcy5faW5oZXJpdGVkRW5kID0gMDsKICAgICAgICB0aGlzLl9saXN0ZW5lcnMgPSBbXTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuX2xpc3RlbmVyczsKICAgIH0KICAgIC8qKgogICAgICBGbGF0dGVuaW5nIGlzIGJhc2VkIG9uIGEgZ2xvYmFsIHJldmlzaW9uIGNvdW50ZXIuIElmIHRoZSByZXZpc2lvbiBoYXMKICAgICAgYnVtcGVkIGl0IG1lYW5zIHRoYXQgc29tZXdoZXJlIGluIGEgY2xhc3MgaW5oZXJpdGFuY2UgY2hhaW4gc29tZXRoaW5nIGhhcwogICAgICBjaGFuZ2VkLCBzbyB3ZSBuZWVkIHRvIHJlZmxhdHRlbiBldmVyeXRoaW5nLiBUaGlzIGNhbiBvbmx5IGhhcHBlbiBpZjoKICAgICAgICAgMS4gQSBtZXRhIGhhcyBiZWVuIGZsYXR0ZW5lZCAobGlzdGVuZXIgaGFzIGJlZW4gY2FsbGVkKQogICAgICAyLiBUaGUgbWV0YSBpcyBhIHByb3RvdHlwZSBtZXRhIHdpdGggY2hpbGRyZW4gd2hvIGhhdmUgaW5oZXJpdGVkIGl0cwogICAgICAgICBsaXN0ZW5lcnMKICAgICAgMy4gQSBuZXcgbGlzdGVuZXIgaXMgc3Vic2VxdWVudGx5IGFkZGVkIHRvIHRoZSBtZXRhIChlLmcuIHZpYSBgLnJlb3BlbigpYCkKICAgICAgICAgVGhpcyBpcyBhIHZlcnkgcmFyZSBvY2N1cmVuY2UsIHNvIHdoaWxlIHRoZSBjb3VudGVyIGlzIGdsb2JhbCBpdCBzaG91bGRuJ3QKICAgICAgYmUgdXBkYXRlZCB2ZXJ5IG9mdGVuIGluIHByYWN0aWNlLgogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZmxhdHRlbmVkTGlzdGVuZXJzID0gZnVuY3Rpb24gZmxhdHRlbmVkTGlzdGVuZXJzKCkgewogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgY291bnRlcnMuZmxhdHRlbmVkTGlzdGVuZXJzQ2FsbHMrKzsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuX2ZsYXR0ZW5lZFZlcnNpb24gPCBjdXJyZW50TGlzdGVuZXJWZXJzaW9uKSB7CiAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgIGNvdW50ZXJzLmxpc3RlbmVyc0ZsYXR0ZW5lZCsrOwogICAgICAgIH0KCiAgICAgICAgdmFyIHBhcmVudCA9IHRoaXMucGFyZW50OwoKICAgICAgICBpZiAocGFyZW50ICE9PSBudWxsKSB7CiAgICAgICAgICAvLyBjb21wdXRlCiAgICAgICAgICB2YXIgcGFyZW50TGlzdGVuZXJzID0gcGFyZW50LmZsYXR0ZW5lZExpc3RlbmVycygpOwoKICAgICAgICAgIGlmIChwYXJlbnRMaXN0ZW5lcnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBpZiAodGhpcy5fbGlzdGVuZXJzID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAvLyBJZiB0aGlzIGluc3RhbmNlIGRvZXNuJ3QgaGF2ZSBhbnkgb2YgaXRzIG93biBsaXN0ZW5lcnMgKHdyaXRhYmxlTGlzdGVuZXJzCiAgICAgICAgICAgICAgLy8gaGFzIG5ldmVyIGJlZW4gY2FsbGVkKSB0aGVuIHdlIGRvbid0IG5lZWQgdG8gZG8gYW55IGZsYXR0ZW5pbmcsIHJldHVybgogICAgICAgICAgICAgIC8vIHRoZSBwYXJlbnQncyBsaXN0ZW5lcnMgaW5zdGVhZC4KICAgICAgICAgICAgICBpZiAoZmFsc2UKICAgICAgICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICAgICAgICkgewogICAgICAgICAgICAgICAgY291bnRlcnMucGFyZW50TGlzdGVuZXJzVXNlZCsrOwogICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgdGhpcy5fbGlzdGVuZXJzID0gcGFyZW50TGlzdGVuZXJzOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnM7CgogICAgICAgICAgICAgIGlmICh0aGlzLl9pbmhlcml0ZWRFbmQgPiAwKSB7CiAgICAgICAgICAgICAgICBsaXN0ZW5lcnMuc3BsaWNlKDAsIHRoaXMuX2luaGVyaXRlZEVuZCk7CiAgICAgICAgICAgICAgICB0aGlzLl9pbmhlcml0ZWRFbmQgPSAwOwogICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJlbnRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIHZhciBsaXN0ZW5lciA9IHBhcmVudExpc3RlbmVyc1tpXTsKICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnMsIGxpc3RlbmVyLmV2ZW50LCBsaXN0ZW5lci50YXJnZXQsIGxpc3RlbmVyLm1ldGhvZCk7CgogICAgICAgICAgICAgICAgaWYgKGluZGV4ID09PSAtMSkgewogICAgICAgICAgICAgICAgICBpZiAoZmFsc2UKICAgICAgICAgICAgICAgICAgLyogREVCVUcgKi8KICAgICAgICAgICAgICAgICAgKSB7CiAgICAgICAgICAgICAgICAgICAgY291bnRlcnMubGlzdGVuZXJzSW5oZXJpdGVkKys7CiAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgIGxpc3RlbmVycy51bnNoaWZ0KGxpc3RlbmVyKTsKICAgICAgICAgICAgICAgICAgdGhpcy5faW5oZXJpdGVkRW5kKys7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB0aGlzLl9mbGF0dGVuZWRWZXJzaW9uID0gY3VycmVudExpc3RlbmVyVmVyc2lvbjsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuX2xpc3RlbmVyczsKICAgIH07CgogICAgX3Byb3RvLm1hdGNoaW5nTGlzdGVuZXJzID0gZnVuY3Rpb24gbWF0Y2hpbmdMaXN0ZW5lcnMoZXZlbnROYW1lKSB7CiAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmZsYXR0ZW5lZExpc3RlbmVycygpOwogICAgICB2YXIgcmVzdWx0OwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGNvdW50ZXJzLm1hdGNoaW5nTGlzdGVuZXJzQ2FsbHMrKzsKICAgICAgfQoKICAgICAgaWYgKGxpc3RlbmVycyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxpc3RlbmVycy5sZW5ndGg7IGluZGV4KyspIHsKICAgICAgICAgIHZhciBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpbmRleF07IC8vIFJFTU9WRSBsaXN0ZW5lcnMgYXJlIHBsYWNlaG9sZGVycyB0aGF0IHRlbGwgdXMgbm90IHRvCiAgICAgICAgICAvLyBpbmhlcml0LCBzbyB0aGV5IG5ldmVyIG1hdGNoLiBPbmx5IEFERCBhbmQgT05DRSBjYW4gbWF0Y2guCgogICAgICAgICAgaWYgKGxpc3RlbmVyLmV2ZW50ID09PSBldmVudE5hbWUgJiYgKGxpc3RlbmVyLmtpbmQgPT09IDAKICAgICAgICAgIC8qIEFERCAqLwogICAgICAgICAgfHwgbGlzdGVuZXIua2luZCA9PT0gMQogICAgICAgICAgLyogT05DRSAqLwogICAgICAgICAgKSkgewogICAgICAgICAgICBpZiAocmVzdWx0ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAvLyB3ZSBjcmVhdGUgdGhpcyBhcnJheSBvbmx5IGFmdGVyIHdlJ3ZlIGZvdW5kIGEgbGlzdGVuZXIgdGhhdAogICAgICAgICAgICAgIC8vIG1hdGNoZXMgdG8gYXZvaWQgYWxsb2NhdGlvbnMgd2hlbiBubyBtYXRjaGVzIGFyZSBmb3VuZC4KICAgICAgICAgICAgICByZXN1bHQgPSBbXTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgcmVzdWx0LnB1c2gobGlzdGVuZXIudGFyZ2V0LCBsaXN0ZW5lci5tZXRob2QsIGxpc3RlbmVyLmtpbmQgPT09IDEKICAgICAgICAgICAgLyogT05DRSAqLwogICAgICAgICAgICApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH07CgogICAgX3Byb3RvLm9ic2VydmVyRXZlbnRzID0gZnVuY3Rpb24gb2JzZXJ2ZXJFdmVudHMoKSB7CiAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmZsYXR0ZW5lZExpc3RlbmVycygpOwogICAgICB2YXIgcmVzdWx0OwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGNvdW50ZXJzLm9ic2VydmVyRXZlbnRzQ2FsbHMrKzsKICAgICAgfQoKICAgICAgaWYgKGxpc3RlbmVycyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxpc3RlbmVycy5sZW5ndGg7IGluZGV4KyspIHsKICAgICAgICAgIHZhciBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpbmRleF07IC8vIFJFTU9WRSBsaXN0ZW5lcnMgYXJlIHBsYWNlaG9sZGVycyB0aGF0IHRlbGwgdXMgbm90IHRvCiAgICAgICAgICAvLyBpbmhlcml0LCBzbyB0aGV5IG5ldmVyIG1hdGNoLiBPbmx5IEFERCBhbmQgT05DRSBjYW4gbWF0Y2guCgogICAgICAgICAgaWYgKChsaXN0ZW5lci5raW5kID09PSAwCiAgICAgICAgICAvKiBBREQgKi8KICAgICAgICAgIHx8IGxpc3RlbmVyLmtpbmQgPT09IDEKICAgICAgICAgIC8qIE9OQ0UgKi8KICAgICAgICAgICkgJiYgbGlzdGVuZXIuZXZlbnQuaW5kZXhPZignOmNoYW5nZScpICE9PSAtMSkgewogICAgICAgICAgICBpZiAocmVzdWx0ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAvLyB3ZSBjcmVhdGUgdGhpcyBhcnJheSBvbmx5IGFmdGVyIHdlJ3ZlIGZvdW5kIGEgbGlzdGVuZXIgdGhhdAogICAgICAgICAgICAgIC8vIG1hdGNoZXMgdG8gYXZvaWQgYWxsb2NhdGlvbnMgd2hlbiBubyBtYXRjaGVzIGFyZSBmb3VuZC4KICAgICAgICAgICAgICByZXN1bHQgPSBbXTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgcmVzdWx0LnB1c2gobGlzdGVuZXIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH07CgogICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShNZXRhLCBbewogICAgICBrZXk6ICJwYXJlbnQiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICB2YXIgcGFyZW50ID0gdGhpcy5fcGFyZW50OwoKICAgICAgICBpZiAocGFyZW50ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHZhciBwcm90byA9IGdldFByb3RvdHlwZU9mKHRoaXMuc291cmNlKTsKICAgICAgICAgIHRoaXMuX3BhcmVudCA9IHBhcmVudCA9IHByb3RvID09PSBudWxsIHx8IHByb3RvID09PSBvYmplY3RQcm90b3R5cGUgPyBudWxsIDogbWV0YShwcm90byk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcGFyZW50OwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gTWV0YTsKICB9KCk7CgogIF9leHBvcnRzLk1ldGEgPSBNZXRhOwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgTWV0YS5wcm90b3R5cGUud3JpdGVWYWx1ZXMgPSBmdW5jdGlvbiAoc3Via2V5LCB2YWx1ZSkgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMuaXNNZXRhRGVzdHJveWVkKCkgPyAiQ2Fubm90IHNldCB0aGUgdmFsdWUgb2YgYCIgKyBzdWJrZXkgKyAiYCBvbiBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKHRoaXMuc291cmNlKSArICJgIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CgogICAgICB2YXIgbWFwID0gdGhpcy5fZ2V0T3JDcmVhdGVPd25NYXAoJ192YWx1ZXMnKTsKCiAgICAgIG1hcFtzdWJrZXldID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IFVOREVGSU5FRCA6IHZhbHVlOwogICAgfTsKCiAgICBNZXRhLnByb3RvdHlwZS5wZWVrVmFsdWVzID0gZnVuY3Rpb24gKGtleSkgewogICAgICB2YXIgdmFsID0gdGhpcy5fZmluZEluaGVyaXRlZDIoJ192YWx1ZXMnLCBrZXkpOwoKICAgICAgcmV0dXJuIHZhbCA9PT0gVU5ERUZJTkVEID8gdW5kZWZpbmVkIDogdmFsOwogICAgfTsKCiAgICBNZXRhLnByb3RvdHlwZS5kZWxldGVGcm9tVmFsdWVzID0gZnVuY3Rpb24gKGtleSkgewogICAgICBkZWxldGUgdGhpcy5fZ2V0T3JDcmVhdGVPd25NYXAoJ192YWx1ZXMnKVtrZXldOwogICAgfTsKCiAgICBNZXRhLnByb3RvdHlwZS5yZWFkSW5oZXJpdGVkVmFsdWUgPSBmdW5jdGlvbiAoa2V5KSB7CiAgICAgIHJldHVybiB0aGlzLl9maW5kSW5oZXJpdGVkMignX3ZhbHVlcycsIGtleSk7CiAgICB9OwoKICAgIE1ldGEucHJvdG90eXBlLndyaXRlVmFsdWUgPSBmdW5jdGlvbiAob2JqLCBrZXksIHZhbHVlKSB7CiAgICAgIHZhciBkZXNjcmlwdG9yID0gKDAsIF91dGlscy5sb29rdXBEZXNjcmlwdG9yKShvYmosIGtleSk7CiAgICAgIHZhciBpc01hbmRhdG9yeVNldHRlciA9IGRlc2NyaXB0b3IgIT09IG51bGwgJiYgZGVzY3JpcHRvci5zZXQgJiYgZGVzY3JpcHRvci5zZXQuaXNNYW5kYXRvcnlTZXR0ZXI7CgogICAgICBpZiAoaXNNYW5kYXRvcnlTZXR0ZXIpIHsKICAgICAgICB0aGlzLndyaXRlVmFsdWVzKGtleSwgdmFsdWUpOwogICAgICB9IGVsc2UgewogICAgICAgIG9ialtrZXldID0gdmFsdWU7CiAgICAgIH0KICAgIH07CiAgfQoKICB2YXIgZ2V0UHJvdG90eXBlT2YgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Y7CiAgdmFyIG1ldGFTdG9yZSA9IG5ldyBXZWFrTWFwKCk7CgogIGZ1bmN0aW9uIHNldE1ldGEob2JqLCBtZXRhKSB7CiAgICAoZmFsc2UgJiYgIShvYmogIT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IGNhbGwgYHNldE1ldGFgIG9uIG51bGwnLCBvYmogIT09IG51bGwpKTsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0Nhbm5vdCBjYWxsIGBzZXRNZXRhYCBvbiB1bmRlZmluZWQnLCBvYmogIT09IHVuZGVmaW5lZCkpOwogICAgKGZhbHNlICYmICEodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJDYW5ub3QgY2FsbCBgc2V0TWV0YWAgb24gIiArIHR5cGVvZiBvYmosIHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpKTsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgY291bnRlcnMuc2V0Q2FsbHMrKzsKICAgIH0KCiAgICBtZXRhU3RvcmUuc2V0KG9iaiwgbWV0YSk7CiAgfQoKICBmdW5jdGlvbiBwZWVrTWV0YShvYmopIHsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdDYW5ub3QgY2FsbCBgcGVla01ldGFgIG9uIG51bGwnLCBvYmogIT09IG51bGwpKTsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0Nhbm5vdCBjYWxsIGBwZWVrTWV0YWAgb24gdW5kZWZpbmVkJywgb2JqICE9PSB1bmRlZmluZWQpKTsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IGNhbGwgYHBlZWtNZXRhYCBvbiAiICsgdHlwZW9mIG9iaiwgdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykpOwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBjb3VudGVycy5wZWVrQ2FsbHMrKzsKICAgIH0KCiAgICB2YXIgbWV0YSA9IG1ldGFTdG9yZS5nZXQob2JqKTsKCiAgICBpZiAobWV0YSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBtZXRhOwogICAgfQoKICAgIHZhciBwb2ludGVyID0gZ2V0UHJvdG90eXBlT2Yob2JqKTsKCiAgICB3aGlsZSAocG9pbnRlciAhPT0gbnVsbCkgewogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgY291bnRlcnMucGVla1Byb3RvdHlwZVdhbGtzKys7CiAgICAgIH0KCiAgICAgIG1ldGEgPSBtZXRhU3RvcmUuZ2V0KHBvaW50ZXIpOwoKICAgICAgaWYgKG1ldGEgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGlmIChtZXRhLnByb3RvICE9PSBwb2ludGVyKSB7CiAgICAgICAgICAvLyBUaGUgbWV0YSB3YXMgYSBwcm90b3R5cGUgbWV0YSB3aGljaCB3YXMgbm90IG1hcmtlZCBhcyBpbml0aWFsaXppbmcuCiAgICAgICAgICAvLyBUaGlzIGNhbiBoYXBwZW4gd2hlbiBhIHByb3RvdHlwZSBjaGFpbiB3YXMgY3JlYXRlZCBtYW51YWxseSB2aWEKICAgICAgICAgIC8vIE9iamVjdC5jcmVhdGUoKSBhbmQgdGhlIHNvdXJjZSBvYmplY3QgZG9lcyBub3QgaGF2ZSBhIGNvbnN0cnVjdG9yLgogICAgICAgICAgbWV0YS5wcm90byA9IHBvaW50ZXI7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gbWV0YTsKICAgICAgfQoKICAgICAgcG9pbnRlciA9IGdldFByb3RvdHlwZU9mKHBvaW50ZXIpOwogICAgfQoKICAgIHJldHVybiBudWxsOwogIH0KICAvKioKICAgIFRlYXJzIGRvd24gdGhlIG1ldGEgb24gYW4gb2JqZWN0IHNvIHRoYXQgaXQgY2FuIGJlIGdhcmJhZ2UgY29sbGVjdGVkLgogICAgTXVsdGlwbGUgY2FsbHMgd2lsbCBoYXZlIG5vIGVmZmVjdC4KICAKICAgIEBtZXRob2QgZGVsZXRlTWV0YQogICAgQGZvciBFbWJlcgogICAgQHBhcmFtIHtPYmplY3R9IG9iaiAgdGhlIG9iamVjdCB0byBkZXN0cm95CiAgICBAcmV0dXJuIHt2b2lkfQogICAgQHByaXZhdGUKICAqLwoKCiAgZnVuY3Rpb24gZGVsZXRlTWV0YShvYmopIHsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdDYW5ub3QgY2FsbCBgZGVsZXRlTWV0YWAgb24gbnVsbCcsIG9iaiAhPT0gbnVsbCkpOwogICAgKGZhbHNlICYmICEob2JqICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IGNhbGwgYGRlbGV0ZU1ldGFgIG9uIHVuZGVmaW5lZCcsIG9iaiAhPT0gdW5kZWZpbmVkKSk7CiAgICAoZmFsc2UgJiYgISh0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyB8fCB0eXBlb2Ygb2JqID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkNhbm5vdCBjYWxsIGBkZWxldGVNZXRhYCBvbiAiICsgdHlwZW9mIG9iaiwgdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykpOwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBjb3VudGVycy5kZWxldGVDYWxscysrOwogICAgfQoKICAgIHZhciBtZXRhID0gcGVla01ldGEob2JqKTsKCiAgICBpZiAobWV0YSAhPT0gbnVsbCkgewogICAgICBtZXRhLmRlc3Ryb3koKTsKICAgIH0KICB9CiAgLyoqCiAgICBSZXRyaWV2ZXMgdGhlIG1ldGEgaGFzaCBmb3IgYW4gb2JqZWN0LiBJZiBgd3JpdGFibGVgIGlzIHRydWUgZW5zdXJlcyB0aGUKICAgIGhhc2ggaXMgd3JpdGFibGUgZm9yIHRoaXMgb2JqZWN0IGFzIHdlbGwuCiAgCiAgICBUaGUgbWV0YSBvYmplY3QgY29udGFpbnMgaW5mb3JtYXRpb24gYWJvdXQgY29tcHV0ZWQgcHJvcGVydHkgZGVzY3JpcHRvcnMgYXMKICAgIHdlbGwgYXMgYW55IHdhdGNoZWQgcHJvcGVydGllcyBhbmQgb3RoZXIgaW5mb3JtYXRpb24uIFlvdSBnZW5lcmFsbHkgd2lsbAogICAgbm90IGFjY2VzcyB0aGlzIGluZm9ybWF0aW9uIGRpcmVjdGx5IGJ1dCBpbnN0ZWFkIHdvcmsgd2l0aCBoaWdoZXIgbGV2ZWwKICAgIG1ldGhvZHMgdGhhdCBtYW5pcHVsYXRlIHRoaXMgaGFzaCBpbmRpcmVjdGx5LgogIAogICAgQG1ldGhvZCBtZXRhCiAgICBAZm9yIEVtYmVyCiAgICBAcHJpdmF0ZQogIAogICAgQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIHJldHJpZXZlIG1ldGEgZm9yCiAgICBAcGFyYW0ge0Jvb2xlYW59IFt3cml0YWJsZT10cnVlXSBQYXNzIGBmYWxzZWAgaWYgeW91IGRvIG5vdCBpbnRlbmQgdG8gbW9kaWZ5CiAgICAgIHRoZSBtZXRhIGhhc2gsIGFsbG93aW5nIHRoZSBtZXRob2QgdG8gYXZvaWQgbWFraW5nIGFuIHVubmVjZXNzYXJ5IGNvcHkuCiAgICBAcmV0dXJuIHtPYmplY3R9IHRoZSBtZXRhIGhhc2ggZm9yIGFuIG9iamVjdAogICovCgoKICB2YXIgbWV0YSA9IGZ1bmN0aW9uIG1ldGEob2JqKSB7CiAgICAoZmFsc2UgJiYgIShvYmogIT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IGNhbGwgYG1ldGFgIG9uIG51bGwnLCBvYmogIT09IG51bGwpKTsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0Nhbm5vdCBjYWxsIGBtZXRhYCBvbiB1bmRlZmluZWQnLCBvYmogIT09IHVuZGVmaW5lZCkpOwogICAgKGZhbHNlICYmICEodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJDYW5ub3QgY2FsbCBgbWV0YWAgb24gIiArIHR5cGVvZiBvYmosIHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpKTsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgY291bnRlcnMubWV0YUNhbGxzKys7CiAgICB9CgogICAgdmFyIG1heWJlTWV0YSA9IHBlZWtNZXRhKG9iaik7IC8vIHJlbW92ZSB0aGlzIGNvZGUsIGluLWZhdm9yIG9mIGV4cGxpY2l0IHBhcmVudAoKICAgIGlmIChtYXliZU1ldGEgIT09IG51bGwgJiYgbWF5YmVNZXRhLnNvdXJjZSA9PT0gb2JqKSB7CiAgICAgIHJldHVybiBtYXliZU1ldGE7CiAgICB9CgogICAgdmFyIG5ld01ldGEgPSBuZXcgTWV0YShvYmopOwogICAgc2V0TWV0YShvYmosIG5ld01ldGEpOwogICAgcmV0dXJuIG5ld01ldGE7CiAgfTsKCiAgX2V4cG9ydHMubWV0YSA9IG1ldGE7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICBtZXRhLl9jb3VudGVycyA9IGNvdW50ZXJzOwogIH0KCiAgZnVuY3Rpb24gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVycywgZXZlbnQsIHRhcmdldCwgbWV0aG9kKSB7CiAgICBmb3IgKHZhciBpID0gbGlzdGVuZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgIHZhciBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXTsKCiAgICAgIGlmIChsaXN0ZW5lci5ldmVudCA9PT0gZXZlbnQgJiYgbGlzdGVuZXIudGFyZ2V0ID09PSB0YXJnZXQgJiYgbGlzdGVuZXIubWV0aG9kID09PSBtZXRob2QpIHsKICAgICAgICByZXR1cm4gaTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiAtMTsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL21ldGFsL2luZGV4IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YSIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL3J1bmxvb3AiLCAiQGdsaW1tZXIvcmVmZXJlbmNlIiwgIkBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50IiwgIkBlbWJlci9lcnJvciIsICJlbWJlci92ZXJzaW9uIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2VtYmVyQmFiZWwsIF9wb2x5ZmlsbHMsIF9tZXRhMiwgX3V0aWxzLCBfZGVidWcsIF9ydW5sb29wLCBfcmVmZXJlbmNlLCBfZW52aXJvbm1lbnQsIF9lcnJvciwgX3ZlcnNpb24sIF9kZXByZWNhdGVkRmVhdHVyZXMsIF9vd25lcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuY29tcHV0ZWQgPSBjb21wdXRlZDsKICBfZXhwb3J0cy5pc0NvbXB1dGVkID0gaXNDb21wdXRlZDsKICBfZXhwb3J0cy5nZXRDYWNoZUZvciA9IGdldENhY2hlRm9yOwogIF9leHBvcnRzLmdldENhY2hlZFZhbHVlRm9yID0gZ2V0Q2FjaGVkVmFsdWVGb3I7CiAgX2V4cG9ydHMucGVla0NhY2hlRm9yID0gcGVla0NhY2hlRm9yOwogIF9leHBvcnRzLmFsaWFzID0gYWxpYXM7CiAgX2V4cG9ydHMuZGVwcmVjYXRlUHJvcGVydHkgPSBkZXByZWNhdGVQcm9wZXJ0eTsKICBfZXhwb3J0cy5fZ2V0UGF0aCA9IF9nZXRQYXRoOwogIF9leHBvcnRzLmdldCA9IF9nZXQyOwogIF9leHBvcnRzLmdldFdpdGhEZWZhdWx0ID0gZ2V0V2l0aERlZmF1bHQ7CiAgX2V4cG9ydHMuc2V0ID0gX3NldDI7CiAgX2V4cG9ydHMudHJ5U2V0ID0gdHJ5U2V0OwogIF9leHBvcnRzLm9iamVjdEF0ID0gb2JqZWN0QXQ7CiAgX2V4cG9ydHMucmVwbGFjZSA9IHJlcGxhY2U7CiAgX2V4cG9ydHMucmVwbGFjZUluTmF0aXZlQXJyYXkgPSByZXBsYWNlSW5OYXRpdmVBcnJheTsKICBfZXhwb3J0cy5hZGRBcnJheU9ic2VydmVyID0gYWRkQXJyYXlPYnNlcnZlcjsKICBfZXhwb3J0cy5yZW1vdmVBcnJheU9ic2VydmVyID0gcmVtb3ZlQXJyYXlPYnNlcnZlcjsKICBfZXhwb3J0cy5hcnJheUNvbnRlbnRXaWxsQ2hhbmdlID0gYXJyYXlDb250ZW50V2lsbENoYW5nZTsKICBfZXhwb3J0cy5hcnJheUNvbnRlbnREaWRDaGFuZ2UgPSBhcnJheUNvbnRlbnREaWRDaGFuZ2U7CiAgX2V4cG9ydHMuZWFjaFByb3h5Rm9yID0gZWFjaFByb3h5Rm9yOwogIF9leHBvcnRzLmVhY2hQcm94eUFycmF5V2lsbENoYW5nZSA9IGVhY2hQcm94eUFycmF5V2lsbENoYW5nZTsKICBfZXhwb3J0cy5lYWNoUHJveHlBcnJheURpZENoYW5nZSA9IGVhY2hQcm94eUFycmF5RGlkQ2hhbmdlOwogIF9leHBvcnRzLmFkZExpc3RlbmVyID0gYWRkTGlzdGVuZXI7CiAgX2V4cG9ydHMuaGFzTGlzdGVuZXJzID0gaGFzTGlzdGVuZXJzOwogIF9leHBvcnRzLm9uID0gb247CiAgX2V4cG9ydHMucmVtb3ZlTGlzdGVuZXIgPSByZW1vdmVMaXN0ZW5lcjsKICBfZXhwb3J0cy5zZW5kRXZlbnQgPSBzZW5kRXZlbnQ7CiAgX2V4cG9ydHMuaXNOb25lID0gaXNOb25lOwogIF9leHBvcnRzLmlzRW1wdHkgPSBpc0VtcHR5OwogIF9leHBvcnRzLmlzQmxhbmsgPSBpc0JsYW5rOwogIF9leHBvcnRzLmlzUHJlc2VudCA9IGlzUHJlc2VudDsKICBfZXhwb3J0cy5iZWdpblByb3BlcnR5Q2hhbmdlcyA9IGJlZ2luUHJvcGVydHlDaGFuZ2VzOwogIF9leHBvcnRzLmNoYW5nZVByb3BlcnRpZXMgPSBjaGFuZ2VQcm9wZXJ0aWVzOwogIF9leHBvcnRzLmVuZFByb3BlcnR5Q2hhbmdlcyA9IGVuZFByb3BlcnR5Q2hhbmdlczsKICBfZXhwb3J0cy5ub3RpZnlQcm9wZXJ0eUNoYW5nZSA9IG5vdGlmeVByb3BlcnR5Q2hhbmdlOwogIF9leHBvcnRzLm92ZXJyaWRlQ2hhaW5zID0gb3ZlcnJpZGVDaGFpbnM7CiAgX2V4cG9ydHMuZGVmaW5lUHJvcGVydHkgPSBkZWZpbmVQcm9wZXJ0eTsKICBfZXhwb3J0cy5pc0VsZW1lbnREZXNjcmlwdG9yID0gaXNFbGVtZW50RGVzY3JpcHRvcjsKICBfZXhwb3J0cy5uYXRpdmVEZXNjRGVjb3JhdG9yID0gbmF0aXZlRGVzY0RlY29yYXRvcjsKICBfZXhwb3J0cy5kZXNjcmlwdG9yRm9yRGVjb3JhdG9yID0gZGVzY3JpcHRvckZvckRlY29yYXRvcjsKICBfZXhwb3J0cy5kZXNjcmlwdG9yRm9yUHJvcGVydHkgPSBkZXNjcmlwdG9yRm9yUHJvcGVydHk7CiAgX2V4cG9ydHMuaXNDbGFzc2ljRGVjb3JhdG9yID0gaXNDbGFzc2ljRGVjb3JhdG9yOwogIF9leHBvcnRzLnNldENsYXNzaWNEZWNvcmF0b3IgPSBzZXRDbGFzc2ljRGVjb3JhdG9yOwogIF9leHBvcnRzLndhdGNoS2V5ID0gd2F0Y2hLZXk7CiAgX2V4cG9ydHMudW53YXRjaEtleSA9IHVud2F0Y2hLZXk7CiAgX2V4cG9ydHMuZmluaXNoQ2hhaW5zID0gZmluaXNoQ2hhaW5zOwogIF9leHBvcnRzLnJlbW92ZUNoYWluV2F0Y2hlciA9IHJlbW92ZUNoYWluV2F0Y2hlcjsKICBfZXhwb3J0cy5nZXRDaGFpblRhZ3NGb3JLZXkgPSBnZXRDaGFpblRhZ3NGb3JLZXk7CiAgX2V4cG9ydHMud2F0Y2hQYXRoID0gd2F0Y2hQYXRoOwogIF9leHBvcnRzLnVud2F0Y2hQYXRoID0gdW53YXRjaFBhdGg7CiAgX2V4cG9ydHMuaXNXYXRjaGluZyA9IGlzV2F0Y2hpbmc7CiAgX2V4cG9ydHMudW53YXRjaCA9IHVud2F0Y2g7CiAgX2V4cG9ydHMud2F0Y2ggPSB3YXRjaDsKICBfZXhwb3J0cy53YXRjaGVyQ291bnQgPSB3YXRjaGVyQ291bnQ7CiAgX2V4cG9ydHMuZ2V0UHJvcGVydGllcyA9IGdldFByb3BlcnRpZXM7CiAgX2V4cG9ydHMuc2V0UHJvcGVydGllcyA9IHNldFByb3BlcnRpZXM7CiAgX2V4cG9ydHMuZXhwYW5kUHJvcGVydGllcyA9IGV4cGFuZFByb3BlcnRpZXM7CiAgX2V4cG9ydHMuYWRkT2JzZXJ2ZXIgPSBhZGRPYnNlcnZlcjsKICBfZXhwb3J0cy5hY3RpdmF0ZU9ic2VydmVyID0gYWN0aXZhdGVPYnNlcnZlcjsKICBfZXhwb3J0cy5yZW1vdmVPYnNlcnZlciA9IHJlbW92ZU9ic2VydmVyOwogIF9leHBvcnRzLmZsdXNoQXN5bmNPYnNlcnZlcnMgPSBmbHVzaEFzeW5jT2JzZXJ2ZXJzOwogIF9leHBvcnRzLm1peGluID0gbWl4aW47CiAgX2V4cG9ydHMub2JzZXJ2ZXIgPSBvYnNlcnZlcjsKICBfZXhwb3J0cy5hcHBseU1peGluID0gYXBwbHlNaXhpbjsKICBfZXhwb3J0cy5pbmplY3QgPSBpbmplY3Q7CiAgX2V4cG9ydHMudGFnRm9yUHJvcGVydHkgPSB0YWdGb3JQcm9wZXJ0eTsKICBfZXhwb3J0cy50YWdGb3IgPSB0YWdGb3I7CiAgX2V4cG9ydHMubWFya09iamVjdEFzRGlydHkgPSBtYXJrT2JqZWN0QXNEaXJ0eTsKICBfZXhwb3J0cy5jb25zdW1lID0gY29uc3VtZTsKICBfZXhwb3J0cy50cmFja2VkID0gdHJhY2tlZDsKICBfZXhwb3J0cy50cmFjayA9IHRyYWNrOwogIF9leHBvcnRzLnVudHJhY2sgPSB1bnRyYWNrOwogIF9leHBvcnRzLmlzVHJhY2tpbmcgPSBpc1RyYWNraW5nOwogIF9leHBvcnRzLmFkZE5hbWVzcGFjZSA9IGFkZE5hbWVzcGFjZTsKICBfZXhwb3J0cy5jbGFzc1RvU3RyaW5nID0gY2xhc3NUb1N0cmluZzsKICBfZXhwb3J0cy5maW5kTmFtZXNwYWNlID0gZmluZE5hbWVzcGFjZTsKICBfZXhwb3J0cy5maW5kTmFtZXNwYWNlcyA9IGZpbmROYW1lc3BhY2VzOwogIF9leHBvcnRzLnByb2Nlc3NOYW1lc3BhY2UgPSBwcm9jZXNzTmFtZXNwYWNlOwogIF9leHBvcnRzLnByb2Nlc3NBbGxOYW1lc3BhY2VzID0gcHJvY2Vzc0FsbE5hbWVzcGFjZXM7CiAgX2V4cG9ydHMucmVtb3ZlTmFtZXNwYWNlID0gcmVtb3ZlTmFtZXNwYWNlOwogIF9leHBvcnRzLmlzTmFtZXNwYWNlU2VhcmNoRGlzYWJsZWQgPSBpc1NlYXJjaERpc2FibGVkOwogIF9leHBvcnRzLnNldE5hbWVzcGFjZVNlYXJjaERpc2FibGVkID0gc2V0U2VhcmNoRGlzYWJsZWQ7CiAgX2V4cG9ydHMuTkFNRVNQQUNFU19CWV9JRCA9IF9leHBvcnRzLk5BTUVTUEFDRVMgPSBfZXhwb3J0cy5UcmFja2VyID0gX2V4cG9ydHMuYXNzZXJ0Tm90UmVuZGVyZWQgPSBfZXhwb3J0cy5kaWRSZW5kZXIgPSBfZXhwb3J0cy5ydW5JblRyYW5zYWN0aW9uID0gX2V4cG9ydHMuVU5LTk9XTl9QUk9QRVJUWV9UQUcgPSBfZXhwb3J0cy5ERUJVR19JTkpFQ1RJT05fRlVOQ1RJT05TID0gX2V4cG9ydHMuYWxpYXNNZXRob2QgPSBfZXhwb3J0cy5NaXhpbiA9IF9leHBvcnRzLkxpYnJhcmllcyA9IF9leHBvcnRzLmxpYnJhcmllcyA9IF9leHBvcnRzLkFSR1NfUFJPWFlfVEFHUyA9IF9leHBvcnRzLkNoYWluTm9kZSA9IF9leHBvcnRzLlBST1BFUlRZX0RJRF9DSEFOR0UgPSBfZXhwb3J0cy5QUk9YWV9DT05URU5UID0gX2V4cG9ydHMuQ29tcHV0ZWRQcm9wZXJ0eSA9IF9leHBvcnRzLl9nbG9iYWxzQ29tcHV0ZWQgPSB2b2lkIDA7CiAgdmFyIENPTVBVVEVEX1BST1BFUlRZX0NBQ0hFRF9WQUxVRVMgPSBuZXcgV2Vha01hcCgpOwogIHZhciBDT01QVVRFRF9QUk9QRVJUWV9MQVNUX1JFVklTSU9OID0gbmV3IFdlYWtNYXAoKTsKCiAgZnVuY3Rpb24gZ2V0Q2FjaGVGb3Iob2JqKSB7CiAgICB2YXIgY2FjaGUgPSBDT01QVVRFRF9QUk9QRVJUWV9DQUNIRURfVkFMVUVTLmdldChvYmopOwoKICAgIGlmIChjYWNoZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGNhY2hlID0gbmV3IE1hcCgpOwogICAgICBDT01QVVRFRF9QUk9QRVJUWV9DQUNIRURfVkFMVUVTLnNldChvYmosIGNhY2hlKTsKICAgIH0KCiAgICByZXR1cm4gY2FjaGU7CiAgfQogIC8qKgogICAgUmV0dXJucyB0aGUgY2FjaGVkIHZhbHVlIGZvciBhIHByb3BlcnR5LCBpZiBvbmUgZXhpc3RzLgogICAgVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBwZWVraW5nIGF0IHRoZSB2YWx1ZSBvZiBhIGNvbXB1dGVkCiAgICBwcm9wZXJ0eSB0aGF0IGlzIGdlbmVyYXRlZCBsYXppbHksIHdpdGhvdXQgYWNjaWRlbnRhbGx5IGNhdXNpbmcKICAgIGl0IHRvIGJlIGNyZWF0ZWQuCiAgCiAgICBAbWV0aG9kIGNhY2hlRm9yCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvaW50ZXJuYWxzCiAgICBAcGFyYW0ge09iamVjdH0gb2JqIHRoZSBvYmplY3Qgd2hvc2UgcHJvcGVydHkgeW91IHdhbnQgdG8gY2hlY2sKICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkgdGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHdob3NlIGNhY2hlZCB2YWx1ZSB5b3Ugd2FudAogICAgICB0byByZXR1cm4KICAgIEByZXR1cm4ge09iamVjdH0gdGhlIGNhY2hlZCB2YWx1ZQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBnZXRDYWNoZWRWYWx1ZUZvcihvYmosIGtleSkgewogICAgdmFyIGNhY2hlID0gQ09NUFVURURfUFJPUEVSVFlfQ0FDSEVEX1ZBTFVFUy5nZXQob2JqKTsKCiAgICBpZiAoY2FjaGUgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gY2FjaGUuZ2V0KGtleSk7CiAgICB9CiAgfQoKICB2YXIgc2V0TGFzdFJldmlzaW9uRm9yOwogIHZhciBnZXRMYXN0UmV2aXNpb25Gb3I7CiAgewogICAgc2V0TGFzdFJldmlzaW9uRm9yID0gZnVuY3Rpb24gc2V0TGFzdFJldmlzaW9uRm9yKG9iaiwga2V5LCByZXZpc2lvbikgewogICAgICB2YXIgY2FjaGUgPSBDT01QVVRFRF9QUk9QRVJUWV9MQVNUX1JFVklTSU9OLmdldChvYmopOwoKICAgICAgaWYgKGNhY2hlID09PSB1bmRlZmluZWQpIHsKICAgICAgICBjYWNoZSA9IG5ldyBNYXAoKTsKICAgICAgICBDT01QVVRFRF9QUk9QRVJUWV9MQVNUX1JFVklTSU9OLnNldChvYmosIGNhY2hlKTsKICAgICAgfQoKICAgICAgY2FjaGUuc2V0KGtleSwgcmV2aXNpb24pOwogICAgfTsKCiAgICBnZXRMYXN0UmV2aXNpb25Gb3IgPSBmdW5jdGlvbiBnZXRMYXN0UmV2aXNpb25Gb3Iob2JqLCBrZXkpIHsKICAgICAgdmFyIGNhY2hlID0gQ09NUFVURURfUFJPUEVSVFlfTEFTVF9SRVZJU0lPTi5nZXQob2JqKTsKCiAgICAgIGlmIChjYWNoZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIHJldmlzaW9uID0gY2FjaGUuZ2V0KGtleSk7CiAgICAgICAgcmV0dXJuIHJldmlzaW9uID09PSB1bmRlZmluZWQgPyAwIDogcmV2aXNpb247CiAgICAgIH0KICAgIH07CiAgfQoKICBmdW5jdGlvbiBwZWVrQ2FjaGVGb3Iob2JqKSB7CiAgICByZXR1cm4gQ09NUFVURURfUFJPUEVSVFlfQ0FDSEVEX1ZBTFVFUy5nZXQob2JqKTsKICB9CgogIHZhciBFQUNIX1BST1hJRVMgPSBuZXcgV2Vha01hcCgpOwoKICBmdW5jdGlvbiBlYWNoUHJveHlBcnJheVdpbGxDaGFuZ2UoYXJyYXksIGlkeCwgcmVtb3ZlZENudCwgYWRkZWRDbnQpIHsKICAgIHZhciBlYWNoUHJveHkgPSBFQUNIX1BST1hJRVMuZ2V0KGFycmF5KTsKCiAgICBpZiAoZWFjaFByb3h5ICE9PSB1bmRlZmluZWQpIHsKICAgICAgZWFjaFByb3h5LmFycmF5V2lsbENoYW5nZShhcnJheSwgaWR4LCByZW1vdmVkQ250LCBhZGRlZENudCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBlYWNoUHJveHlBcnJheURpZENoYW5nZShhcnJheSwgaWR4LCByZW1vdmVkQ250LCBhZGRlZENudCkgewogICAgdmFyIGVhY2hQcm94eSA9IEVBQ0hfUFJPWElFUy5nZXQoYXJyYXkpOwoKICAgIGlmIChlYWNoUHJveHkgIT09IHVuZGVmaW5lZCkgewogICAgICBlYWNoUHJveHkuYXJyYXlEaWRDaGFuZ2UoYXJyYXksIGlkeCwgcmVtb3ZlZENudCwgYWRkZWRDbnQpOwogICAgfQogIH0KICAvKioKICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwoKICAvKgogICAgVGhlIGV2ZW50IHN5c3RlbSB1c2VzIGEgc2VyaWVzIG9mIG5lc3RlZCBoYXNoZXMgdG8gc3RvcmUgbGlzdGVuZXJzIG9uIGFuCiAgICBvYmplY3QuIFdoZW4gYSBsaXN0ZW5lciBpcyByZWdpc3RlcmVkLCBvciB3aGVuIGFuIGV2ZW50IGFycml2ZXMsIHRoZXNlCiAgICBoYXNoZXMgYXJlIGNvbnN1bHRlZCB0byBkZXRlcm1pbmUgd2hpY2ggdGFyZ2V0IGFuZCBhY3Rpb24gcGFpciB0byBpbnZva2UuCiAgCiAgICBUaGUgaGFzaGVzIGFyZSBzdG9yZWQgaW4gdGhlIG9iamVjdCdzIG1ldGEgaGFzaCwgYW5kIGxvb2sgbGlrZSB0aGlzOgogIAogICAgICAgIC8vIE9iamVjdCdzIG1ldGEgaGFzaAogICAgICAgIHsKICAgICAgICAgIGxpc3RlbmVyczogeyAgICAgICAvLyB2YXJpYWJsZSBuYW1lOiBgbGlzdGVuZXJTZXRgCiAgICAgICAgICAgICJmb286Y2hhbmdlIjogWyAvLyB2YXJpYWJsZSBuYW1lOiBgYWN0aW9uc2AKICAgICAgICAgICAgICB0YXJnZXQsIG1ldGhvZCwgb25jZQogICAgICAgICAgICBdCiAgICAgICAgICB9CiAgICAgICAgfQogIAogICovCgogIC8qKgogICAgQWRkIGFuIGV2ZW50IGxpc3RlbmVyCiAgCiAgICBAbWV0aG9kIGFkZExpc3RlbmVyCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvZXZlbnRzCiAgICBAcGFyYW0gb2JqCiAgICBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lCiAgICBAcGFyYW0ge09iamVjdHxGdW5jdGlvbn0gdGFyZ2V0IEEgdGFyZ2V0IG9iamVjdCBvciBhIGZ1bmN0aW9uCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIEEgZnVuY3Rpb24gb3IgdGhlIG5hbWUgb2YgYSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgb24gYHRhcmdldGAKICAgIEBwYXJhbSB7Qm9vbGVhbn0gb25jZSBBIGZsYWcgd2hldGhlciBhIGZ1bmN0aW9uIHNob3VsZCBvbmx5IGJlIGNhbGxlZCBvbmNlCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGFkZExpc3RlbmVyKG9iaiwgZXZlbnROYW1lLCB0YXJnZXQsIG1ldGhvZCwgb25jZSwgc3luYykgewogICAgaWYgKHN5bmMgPT09IHZvaWQgMCkgewogICAgICBzeW5jID0gdHJ1ZTsKICAgIH0KCiAgICAoZmFsc2UgJiYgIShCb29sZWFuKG9iaikgJiYgQm9vbGVhbihldmVudE5hbWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBtdXN0IHBhc3MgYXQgbGVhc3QgYW4gb2JqZWN0IGFuZCBldmVudCBuYW1lIHRvIGFkZExpc3RlbmVyJywgQm9vbGVhbihvYmopICYmIEJvb2xlYW4oZXZlbnROYW1lKSkpOwoKICAgIGlmICghbWV0aG9kICYmICdmdW5jdGlvbicgPT09IHR5cGVvZiB0YXJnZXQpIHsKICAgICAgbWV0aG9kID0gdGFyZ2V0OwogICAgICB0YXJnZXQgPSBudWxsOwogICAgfQoKICAgICgwLCBfbWV0YTIubWV0YSkob2JqKS5hZGRUb0xpc3RlbmVycyhldmVudE5hbWUsIHRhcmdldCwgbWV0aG9kLCBvbmNlID09PSB0cnVlLCBzeW5jKTsKICB9CiAgLyoqCiAgICBSZW1vdmUgYW4gZXZlbnQgbGlzdGVuZXIKICAKICAgIEFyZ3VtZW50cyBzaG91bGQgbWF0Y2ggdGhvc2UgcGFzc2VkIHRvIGBhZGRMaXN0ZW5lcmAuCiAgCiAgICBAbWV0aG9kIHJlbW92ZUxpc3RlbmVyCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvZXZlbnRzCiAgICBAcGFyYW0gb2JqCiAgICBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lCiAgICBAcGFyYW0ge09iamVjdHxGdW5jdGlvbn0gdGFyZ2V0IEEgdGFyZ2V0IG9iamVjdCBvciBhIGZ1bmN0aW9uCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIEEgZnVuY3Rpb24gb3IgdGhlIG5hbWUgb2YgYSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgb24gYHRhcmdldGAKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIob2JqLCBldmVudE5hbWUsIHRhcmdldE9yRnVuY3Rpb24sIGZ1bmN0aW9uT3JOYW1lKSB7CiAgICAoZmFsc2UgJiYgIShCb29sZWFuKG9iaikgJiYgQm9vbGVhbihldmVudE5hbWUpICYmICh0eXBlb2YgdGFyZ2V0T3JGdW5jdGlvbiA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgdGFyZ2V0T3JGdW5jdGlvbiA9PT0gJ29iamVjdCcgJiYgQm9vbGVhbihmdW5jdGlvbk9yTmFtZSkpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBtdXN0IHBhc3MgYXQgbGVhc3QgYW4gb2JqZWN0LCBldmVudCBuYW1lLCBhbmQgbWV0aG9kIG9yIHRhcmdldCBhbmQgbWV0aG9kL21ldGhvZCBuYW1lIHRvIHJlbW92ZUxpc3RlbmVyJywgQm9vbGVhbihvYmopICYmIEJvb2xlYW4oZXZlbnROYW1lKSAmJiAodHlwZW9mIHRhcmdldE9yRnVuY3Rpb24gPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIHRhcmdldE9yRnVuY3Rpb24gPT09ICdvYmplY3QnICYmIEJvb2xlYW4oZnVuY3Rpb25Pck5hbWUpKSkpOwogICAgdmFyIHRhcmdldCwgbWV0aG9kOwoKICAgIGlmICh0eXBlb2YgdGFyZ2V0T3JGdW5jdGlvbiA9PT0gJ29iamVjdCcpIHsKICAgICAgdGFyZ2V0ID0gdGFyZ2V0T3JGdW5jdGlvbjsKICAgICAgbWV0aG9kID0gZnVuY3Rpb25Pck5hbWU7CiAgICB9IGVsc2UgewogICAgICB0YXJnZXQgPSBudWxsOwogICAgICBtZXRob2QgPSB0YXJnZXRPckZ1bmN0aW9uOwogICAgfQoKICAgIHZhciBtID0gKDAsIF9tZXRhMi5tZXRhKShvYmopOwogICAgbS5yZW1vdmVGcm9tTGlzdGVuZXJzKGV2ZW50TmFtZSwgdGFyZ2V0LCBtZXRob2QpOwogIH0KICAvKioKICAgIFNlbmQgYW4gZXZlbnQuIFRoZSBleGVjdXRpb24gb2Ygc3VzcGVuZGVkIGxpc3RlbmVycwogICAgaXMgc2tpcHBlZCwgYW5kIG9uY2UgbGlzdGVuZXJzIGFyZSByZW1vdmVkLiBBIGxpc3RlbmVyIHdpdGhvdXQKICAgIGEgdGFyZ2V0IGlzIGV4ZWN1dGVkIG9uIHRoZSBwYXNzZWQgb2JqZWN0LiBJZiBhbiBhcnJheSBvZiBhY3Rpb25zCiAgICBpcyBub3QgcGFzc2VkLCB0aGUgYWN0aW9ucyBzdG9yZWQgb24gdGhlIHBhc3NlZCBvYmplY3QgYXJlIGludm9rZWQuCiAgCiAgICBAbWV0aG9kIHNlbmRFdmVudAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2V2ZW50cwogICAgQHBhcmFtIG9iagogICAgQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZQogICAgQHBhcmFtIHtBcnJheX0gcGFyYW1zIE9wdGlvbmFsIHBhcmFtZXRlcnMgZm9yIGVhY2ggbGlzdGVuZXIuCiAgICBAcmV0dXJuIHtCb29sZWFufSBpZiB0aGUgZXZlbnQgd2FzIGRlbGl2ZXJlZCB0byBvbmUgb3IgbW9yZSBhY3Rpb25zCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIHNlbmRFdmVudChvYmosIGV2ZW50TmFtZSwgcGFyYW1zLCBhY3Rpb25zLCBfbWV0YSkgewogICAgaWYgKGFjdGlvbnMgPT09IHVuZGVmaW5lZCkgewogICAgICB2YXIgbWV0YSQkMSA9IF9tZXRhID09PSB1bmRlZmluZWQgPyAoMCwgX21ldGEyLnBlZWtNZXRhKShvYmopIDogX21ldGE7CiAgICAgIGFjdGlvbnMgPSB0eXBlb2YgbWV0YSQkMSA9PT0gJ29iamVjdCcgJiYgbWV0YSQkMSAhPT0gbnVsbCA/IG1ldGEkJDEubWF0Y2hpbmdMaXN0ZW5lcnMoZXZlbnROYW1lKSA6IHVuZGVmaW5lZDsKICAgIH0KCiAgICBpZiAoYWN0aW9ucyA9PT0gdW5kZWZpbmVkIHx8IGFjdGlvbnMubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICBmb3IgKHZhciBpID0gYWN0aW9ucy5sZW5ndGggLSAzOyBpID49IDA7IGkgLT0gMykgewogICAgICAvLyBsb29waW5nIGluIHJldmVyc2UgZm9yIG9uY2UgbGlzdGVuZXJzCiAgICAgIHZhciB0YXJnZXQgPSBhY3Rpb25zW2ldOwogICAgICB2YXIgbWV0aG9kID0gYWN0aW9uc1tpICsgMV07CiAgICAgIHZhciBvbmNlID0gYWN0aW9uc1tpICsgMl07CgogICAgICBpZiAoIW1ldGhvZCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICBpZiAob25jZSkgewogICAgICAgIHJlbW92ZUxpc3RlbmVyKG9iaiwgZXZlbnROYW1lLCB0YXJnZXQsIG1ldGhvZCk7CiAgICAgIH0KCiAgICAgIGlmICghdGFyZ2V0KSB7CiAgICAgICAgdGFyZ2V0ID0gb2JqOwogICAgICB9CgogICAgICBpZiAoJ3N0cmluZycgPT09IHR5cGVvZiBtZXRob2QpIHsKICAgICAgICBtZXRob2QgPSB0YXJnZXRbbWV0aG9kXTsKICAgICAgfQoKICAgICAgbWV0aG9kLmFwcGx5KHRhcmdldCwgcGFyYW1zKTsKICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCBoYXNMaXN0ZW5lcnMKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9ldmVudHMKICAgIEBwYXJhbSBvYmoKICAgIEBwYXJhbSB7U3RyaW5nfSBldmVudE5hbWUKICAgIEByZXR1cm4ge0Jvb2xlYW59IGlmIGBvYmpgIGhhcyBsaXN0ZW5lcnMgZm9yIGV2ZW50IGBldmVudE5hbWVgCiAgKi8KCgogIGZ1bmN0aW9uIGhhc0xpc3RlbmVycyhvYmosIGV2ZW50TmFtZSkgewogICAgdmFyIG1ldGEkJDEgPSAoMCwgX21ldGEyLnBlZWtNZXRhKShvYmopOwoKICAgIGlmIChtZXRhJCQxID09PSBudWxsKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICB2YXIgbWF0Y2hlZCA9IG1ldGEkJDEubWF0Y2hpbmdMaXN0ZW5lcnMoZXZlbnROYW1lKTsKICAgIHJldHVybiBtYXRjaGVkICE9PSB1bmRlZmluZWQgJiYgbWF0Y2hlZC5sZW5ndGggPiAwOwogIH0KICAvKioKICAgIERlZmluZSBhIHByb3BlcnR5IGFzIGEgZnVuY3Rpb24gdGhhdCBzaG91bGQgYmUgZXhlY3V0ZWQgd2hlbgogICAgYSBzcGVjaWZpZWQgZXZlbnQgb3IgZXZlbnRzIGFyZSB0cmlnZ2VyZWQuCiAgCiAgICBgYGAgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgb24gfSBmcm9tICdAZW1iZXIvb2JqZWN0L2V2ZW50ZWQnOwogICAgaW1wb3J0IHsgc2VuZEV2ZW50IH0gZnJvbSAnQGVtYmVyL29iamVjdC9ldmVudHMnOwogIAogICAgbGV0IEpvYiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGxvZ0NvbXBsZXRlZDogb24oJ2NvbXBsZXRlZCcsIGZ1bmN0aW9uKCkgewogICAgICAgIGNvbnNvbGUubG9nKCdKb2IgY29tcGxldGVkIScpOwogICAgICB9KQogICAgfSk7CiAgCiAgICBsZXQgam9iID0gSm9iLmNyZWF0ZSgpOwogIAogICAgc2VuZEV2ZW50KGpvYiwgJ2NvbXBsZXRlZCcpOyAvLyBMb2dzICdKb2IgY29tcGxldGVkIScKICAgYGBgCiAgCiAgICBAbWV0aG9kIG9uCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvZXZlbnRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZXMqCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jCiAgICBAcmV0dXJuIHtGdW5jdGlvbn0gdGhlIGxpc3RlbmVyIGZ1bmN0aW9uLCBwYXNzZWQgYXMgbGFzdCBhcmd1bWVudCB0byBvbiguLi4pCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIG9uKCkgewogICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkyID0gMDsgX2tleTIgPCBfbGVuOyBfa2V5MisrKSB7CiAgICAgIGFyZ3NbX2tleTJdID0gYXJndW1lbnRzW19rZXkyXTsKICAgIH0KCiAgICB2YXIgZnVuYyA9IGFyZ3MucG9wKCk7CiAgICB2YXIgZXZlbnRzID0gYXJnczsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBmdW5jID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ29uIGV4cGVjdHMgZnVuY3Rpb24gYXMgbGFzdCBhcmd1bWVudCcsIHR5cGVvZiBmdW5jID09PSAnZnVuY3Rpb24nKSk7CiAgICAoZmFsc2UgJiYgIShldmVudHMubGVuZ3RoID4gMCAmJiBldmVudHMuZXZlcnkoZnVuY3Rpb24gKHApIHsKICAgICAgcmV0dXJuIHR5cGVvZiBwID09PSAnc3RyaW5nJyAmJiBwLmxlbmd0aCA+IDA7CiAgICB9KSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdvbiBjYWxsZWQgd2l0aG91dCB2YWxpZCBldmVudCBuYW1lcycsIGV2ZW50cy5sZW5ndGggPiAwICYmIGV2ZW50cy5ldmVyeShmdW5jdGlvbiAocCkgewogICAgICByZXR1cm4gdHlwZW9mIHAgPT09ICdzdHJpbmcnICYmIHAubGVuZ3RoID4gMDsKICAgIH0pKSk7CiAgICAoMCwgX3V0aWxzLnNldExpc3RlbmVycykoZnVuYywgZXZlbnRzKTsKICAgIHJldHVybiBmdW5jOwogIH0KCiAgdmFyIEFGVEVSX09CU0VSVkVSUyA9ICc6Y2hhbmdlJzsKCiAgZnVuY3Rpb24gY2hhbmdlRXZlbnQoa2V5TmFtZSkgewogICAgcmV0dXJuIGtleU5hbWUgKyBBRlRFUl9PQlNFUlZFUlM7CiAgfQoKICB2YXIgREVDT1JBVE9SX0RFU0NSSVBUT1JfTUFQID0gbmV3IFdlYWtNYXAoKTsKICAvKioKICAgIFJldHVybnMgdGhlIENQIGRlc2NyaXB0b3IgYXNzb2NhaXRlZCB3aXRoIGBvYmpgIGFuZCBga2V5TmFtZWAsIGlmIGFueS4KICAKICAgIEBtZXRob2QgZGVzY3JpcHRvckZvclByb3BlcnR5CiAgICBAcGFyYW0ge09iamVjdH0gb2JqIHRoZSBvYmplY3QgdG8gY2hlY2sKICAgIEBwYXJhbSB7U3RyaW5nfSBrZXlOYW1lIHRoZSBrZXkgdG8gY2hlY2sKICAgIEByZXR1cm4ge0Rlc2NyaXB0b3J9CiAgICBAcHJpdmF0ZQogICovCgogIGZ1bmN0aW9uIGRlc2NyaXB0b3JGb3JQcm9wZXJ0eShvYmosIGtleU5hbWUsIF9tZXRhKSB7CiAgICAoZmFsc2UgJiYgIShvYmogIT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IGNhbGwgYGRlc2NyaXB0b3JGb3JQcm9wZXJ0eWAgb24gbnVsbCcsIG9iaiAhPT0gbnVsbCkpOwogICAgKGZhbHNlICYmICEob2JqICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IGNhbGwgYGRlc2NyaXB0b3JGb3JQcm9wZXJ0eWAgb24gdW5kZWZpbmVkJywgb2JqICE9PSB1bmRlZmluZWQpKTsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IGNhbGwgYGRlc2NyaXB0b3JGb3JQcm9wZXJ0eWAgb24gIiArIHR5cGVvZiBvYmosIHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpKTsKICAgIHZhciBtZXRhJCQxID0gX21ldGEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaikgOiBfbWV0YTsKCiAgICBpZiAobWV0YSQkMSAhPT0gbnVsbCkgewogICAgICByZXR1cm4gbWV0YSQkMS5wZWVrRGVzY3JpcHRvcnMoa2V5TmFtZSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKGRlYykgewogICAgcmV0dXJuIERFQ09SQVRPUl9ERVNDUklQVE9SX01BUC5nZXQoZGVjKTsKICB9CiAgLyoqCiAgICBDaGVjayB3aGV0aGVyIGEgdmFsdWUgaXMgYSBkZWNvcmF0b3IKICAKICAgIEBtZXRob2QgaXNDbGFzc2ljRGVjb3JhdG9yCiAgICBAcGFyYW0ge2FueX0gcG9zc2libGVEZXNjIHRoZSB2YWx1ZSB0byBjaGVjawogICAgQHJldHVybiB7Ym9vbGVhbn0KICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIGlzQ2xhc3NpY0RlY29yYXRvcihkZWMpIHsKICAgIHJldHVybiBkZWMgIT09IG51bGwgJiYgZGVjICE9PSB1bmRlZmluZWQgJiYgREVDT1JBVE9SX0RFU0NSSVBUT1JfTUFQLmhhcyhkZWMpOwogIH0KICAvKioKICAgIFNldCBhIHZhbHVlIGFzIGEgZGVjb3JhdG9yCiAgCiAgICBAbWV0aG9kIHNldENsYXNzaWNEZWNvcmF0b3IKICAgIEBwYXJhbSB7ZnVuY3Rpb259IGRlY29yYXRvciB0aGUgdmFsdWUgdG8gbWFyayBhcyBhIGRlY29yYXRvcgogICAgQHByaXZhdGUKICAqLwoKCiAgZnVuY3Rpb24gc2V0Q2xhc3NpY0RlY29yYXRvcihkZWMsIHZhbHVlJCQxKSB7CiAgICBpZiAodmFsdWUkJDEgPT09IHZvaWQgMCkgewogICAgICB2YWx1ZSQkMSA9IHRydWU7CiAgICB9CgogICAgREVDT1JBVE9SX0RFU0NSSVBUT1JfTUFQLnNldChkZWMsIHZhbHVlJCQxKTsKICB9CgogIHZhciBmaXJzdERvdEluZGV4Q2FjaGUgPSBuZXcgX3V0aWxzLkNhY2hlKDEwMDAsIGZ1bmN0aW9uIChrZXkpIHsKICAgIHJldHVybiBrZXkuaW5kZXhPZignLicpOwogIH0pOwoKICBmdW5jdGlvbiBpc1BhdGgocGF0aCkgewogICAgcmV0dXJuIHR5cGVvZiBwYXRoID09PSAnc3RyaW5nJyAmJiBmaXJzdERvdEluZGV4Q2FjaGUuZ2V0KHBhdGgpICE9PSAtMTsKICB9CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KICAvLyBERUZJTklORyBQUk9QRVJUSUVTIEFQSQogIC8vCgoKICBmdW5jdGlvbiBNQU5EQVRPUllfU0VUVEVSX0ZVTkNUSU9OKG5hbWUpIHsKICAgIGZ1bmN0aW9uIFNFVFRFUl9GVU5DVElPTih2YWx1ZSQkMSkgewogICAgICB2YXIgbSA9ICgwLCBfbWV0YTIucGVla01ldGEpKHRoaXMpOwoKICAgICAgaWYgKG0uaXNJbml0aWFsaXppbmcoKSB8fCBtLmlzUHJvdG90eXBlTWV0YSh0aGlzKSkgewogICAgICAgIG0ud3JpdGVWYWx1ZXMobmFtZSwgdmFsdWUkJDEpOwogICAgICB9IGVsc2UgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBtdXN0IHVzZSBzZXQoKSB0byBzZXQgdGhlIGAiICsgbmFtZSArICJgIHByb3BlcnR5IChvZiAiICsgdGhpcyArICIpIHRvIGAiICsgdmFsdWUkJDEgKyAiYC4iLCBmYWxzZSkpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuICgwLCBfcG9seWZpbGxzLmFzc2lnbikoU0VUVEVSX0ZVTkNUSU9OLCB7CiAgICAgIGlzTWFuZGF0b3J5U2V0dGVyOiB0cnVlCiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIERFRkFVTFRfR0VUVEVSX0ZVTkNUSU9OKG5hbWUpIHsKICAgIHJldHVybiBmdW5jdGlvbiBHRVRURVJfRlVOQ1RJT04oKSB7CiAgICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkodGhpcyk7CgogICAgICBpZiAobWV0YSQkMSAhPT0gbnVsbCkgewogICAgICAgIHJldHVybiBtZXRhJCQxLnBlZWtWYWx1ZXMobmFtZSk7CiAgICAgIH0KICAgIH07CiAgfQoKICBmdW5jdGlvbiBJTkhFUklUSU5HX0dFVFRFUl9GVU5DVElPTihuYW1lKSB7CiAgICBmdW5jdGlvbiBJR0VUVEVSX0ZVTkNUSU9OKCkgewogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKHRoaXMpOwogICAgICB2YXIgdmFsOwoKICAgICAgaWYgKG1ldGEkJDEgIT09IG51bGwpIHsKICAgICAgICB2YWwgPSBtZXRhJCQxLnJlYWRJbmhlcml0ZWRWYWx1ZShuYW1lKTsKCiAgICAgICAgaWYgKHZhbCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YXIgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcyk7CiAgICAgICAgICB2YWwgPSBwcm90byA9PT0gbnVsbCA/IHVuZGVmaW5lZCA6IHByb3RvW25hbWVdOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB2YWwgPSB2YWwgPT09IF9tZXRhMi5VTkRFRklORUQgPyB1bmRlZmluZWQgOiB2YWw7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdmFsOwogICAgfQoKICAgIHJldHVybiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKElHRVRURVJfRlVOQ1RJT04sIHsKICAgICAgaXNJbmhlcml0aW5nR2V0dGVyOiB0cnVlCiAgICB9KTsKICB9CiAgLyoqCiAgICBOT1RFOiBUaGlzIGlzIGEgbG93LWxldmVsIG1ldGhvZCB1c2VkIGJ5IG90aGVyIHBhcnRzIG9mIHRoZSBBUEkuIFlvdSBhbG1vc3QKICAgIG5ldmVyIHdhbnQgdG8gY2FsbCB0aGlzIG1ldGhvZCBkaXJlY3RseS4gSW5zdGVhZCB5b3Ugc2hvdWxkIHVzZQogICAgYG1peGluKClgIHRvIGRlZmluZSBuZXcgcHJvcGVydGllcy4KICAKICAgIERlZmluZXMgYSBwcm9wZXJ0eSBvbiBhbiBvYmplY3QuIFRoaXMgbWV0aG9kIHdvcmtzIG11Y2ggbGlrZSB0aGUgRVM1CiAgICBgT2JqZWN0LmRlZmluZVByb3BlcnR5KClgIG1ldGhvZCBleGNlcHQgdGhhdCBpdCBjYW4gYWxzbyBhY2NlcHQgY29tcHV0ZWQKICAgIHByb3BlcnRpZXMgYW5kIG90aGVyIHNwZWNpYWwgZGVzY3JpcHRvcnMuCiAgCiAgICBOb3JtYWxseSB0aGlzIG1ldGhvZCB0YWtlcyBvbmx5IHRocmVlIHBhcmFtZXRlcnMuIEhvd2V2ZXIgaWYgeW91IHBhc3MgYW4KICAgIGluc3RhbmNlIG9mIGBEZXNjcmlwdG9yYCBhcyB0aGUgdGhpcmQgcGFyYW0gdGhlbiB5b3UgY2FuIHBhc3MgYW4KICAgIG9wdGlvbmFsIHZhbHVlIGFzIHRoZSBmb3VydGggcGFyYW1ldGVyLiBUaGlzIGlzIG9mdGVuIG1vcmUgZWZmaWNpZW50IHRoYW4KICAgIGNyZWF0aW5nIG5ldyBkZXNjcmlwdG9yIGhhc2hlcyBmb3IgZWFjaCBwcm9wZXJ0eS4KICAKICAgICMjIEV4YW1wbGVzCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBkZWZpbmVQcm9wZXJ0eSwgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIC8vIEVTNSBjb21wYXRpYmxlIG1vZGUKICAgIGRlZmluZVByb3BlcnR5KGNvbnRhY3QsICdmaXJzdE5hbWUnLCB7CiAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICBjb25maWd1cmFibGU6IGZhbHNlLAogICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICB2YWx1ZTogJ0NoYXJsZXMnCiAgICB9KTsKICAKICAgIC8vIGRlZmluZSBhIHNpbXBsZSBwcm9wZXJ0eQogICAgZGVmaW5lUHJvcGVydHkoY29udGFjdCwgJ2xhc3ROYW1lJywgdW5kZWZpbmVkLCAnSm9sbGV5Jyk7CiAgCiAgICAvLyBkZWZpbmUgYSBjb21wdXRlZCBwcm9wZXJ0eQogICAgZGVmaW5lUHJvcGVydHkoY29udGFjdCwgJ2Z1bGxOYW1lJywgY29tcHV0ZWQoJ2ZpcnN0TmFtZScsICdsYXN0TmFtZScsIGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gdGhpcy5maXJzdE5hbWUrJyAnK3RoaXMubGFzdE5hbWU7CiAgICB9KSk7CiAgICBgYGAKICAKICAgIEBwdWJsaWMKICAgIEBtZXRob2QgZGVmaW5lUHJvcGVydHkKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdAogICAgQHBhcmFtIHtPYmplY3R9IG9iaiB0aGUgb2JqZWN0IHRvIGRlZmluZSB0aGlzIHByb3BlcnR5IG9uLiBUaGlzIG1heSBiZSBhIHByb3RvdHlwZS4KICAgIEBwYXJhbSB7U3RyaW5nfSBrZXlOYW1lIHRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eQogICAgQHBhcmFtIHtEZXNjcmlwdG9yfSBbZGVzY10gYW4gaW5zdGFuY2Ugb2YgYERlc2NyaXB0b3JgICh0eXBpY2FsbHkgYQogICAgICBjb21wdXRlZCBwcm9wZXJ0eSkgb3IgYW4gRVM1IGRlc2NyaXB0b3IuCiAgICAgIFlvdSBtdXN0IHByb3ZpZGUgdGhpcyBvciBgZGF0YWAgYnV0IG5vdCBib3RoLgogICAgQHBhcmFtIHsqfSBbZGF0YV0gc29tZXRoaW5nIG90aGVyIHRoYW4gYSBkZXNjcmlwdG9yLCB0aGF0IHdpbGwKICAgICAgYmVjb21lIHRoZSBleHBsaWNpdCB2YWx1ZSBvZiB0aGlzIHByb3BlcnR5LgogICovCgoKICBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShvYmosIGtleU5hbWUsIGRlc2MsIGRhdGEsIG1ldGEkJDEpIHsKICAgIGlmIChtZXRhJCQxID09PSB1bmRlZmluZWQpIHsKICAgICAgbWV0YSQkMSA9ICgwLCBfbWV0YTIubWV0YSkob2JqKTsKICAgIH0KCiAgICB2YXIgd2F0Y2hpbmcgPSBtZXRhJCQxLnBlZWtXYXRjaGluZyhrZXlOYW1lKSA+IDA7CiAgICB2YXIgcHJldmlvdXNEZXNjID0gZGVzY3JpcHRvckZvclByb3BlcnR5KG9iaiwga2V5TmFtZSwgbWV0YSQkMSk7CiAgICB2YXIgd2FzRGVzY3JpcHRvciA9IHByZXZpb3VzRGVzYyAhPT0gdW5kZWZpbmVkOwoKICAgIGlmICh3YXNEZXNjcmlwdG9yKSB7CiAgICAgIHByZXZpb3VzRGVzYy50ZWFyZG93bihvYmosIGtleU5hbWUsIG1ldGEkJDEpOwogICAgfSAvLyB1c2VkIHRvIHRyYWNrIGlmIHRoZSB0aGUgcHJvcGVydHkgYmVpbmcgZGVmaW5lZCBiZSBlbnVtZXJhYmxlCgoKICAgIHZhciBlbnVtZXJhYmxlID0gdHJ1ZTsgLy8gRW1iZXIuTmF0aXZlQXJyYXkgaXMgYSBub3JtYWwgRW1iZXIuTWl4aW4gdGhhdCB3ZSBtaXggaW50byBgQXJyYXkucHJvdG90eXBlYCB3aGVuIHByb3RvdHlwZSBleHRlbnNpb25zIGFyZSBlbmFibGVkCiAgICAvLyBtdXRhdGluZyBhIG5hdGl2ZSBvYmplY3QgcHJvdG90eXBlIGxpa2UgdGhpcyBzaG91bGQgX25vdF8gcmVzdWx0IGluIGVudW1lcmFibGUgcHJvcGVydGllcyBiZWluZyBhZGRlZCAob3Igd2UgaGF2ZSBzaWduaWZpY2FudAogICAgLy8gaXNzdWVzIHdpdGggdGhpbmdzIGxpa2UgZGVlcCBlcXVhbGl0eSBjaGVja3MgZnJvbSB0ZXN0IGZyYW1ld29ya3MsIG9yIHRoaW5ncyBsaWtlIGpRdWVyeS5leHRlbmQodHJ1ZSwgW10sIFtdKSkuCiAgICAvLwogICAgLy8gdGhpcyBpcyBhIGhhY2ssIGFuZCB3ZSBzaG91bGQgc3RvcCBtdXRhdGluZyB0aGUgYXJyYXkgcHJvdG90eXBlIGJ5IGRlZmF1bHQg8J+YqwoKICAgIGlmIChvYmogPT09IEFycmF5LnByb3RvdHlwZSkgewogICAgICBlbnVtZXJhYmxlID0gZmFsc2U7CiAgICB9CgogICAgdmFyIHZhbHVlJCQxOwoKICAgIGlmIChpc0NsYXNzaWNEZWNvcmF0b3IoZGVzYykpIHsKICAgICAgdmFyIHByb3BlcnR5RGVzYzsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICBwcm9wZXJ0eURlc2MgPSBkZXNjKG9iaiwga2V5TmFtZSwgdW5kZWZpbmVkLCBtZXRhJCQxLCB0cnVlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBwcm9wZXJ0eURlc2MgPSBkZXNjKG9iaiwga2V5TmFtZSwgdW5kZWZpbmVkLCBtZXRhJCQxKTsKICAgICAgfQoKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwga2V5TmFtZSwgcHJvcGVydHlEZXNjKTsgLy8gcGFzcyB0aGUgZGVjb3JhdG9yIGZ1bmN0aW9uIGZvcndhcmQgZm9yIGJhY2t3YXJkcyBjb21wYXQKCiAgICAgIHZhbHVlJCQxID0gZGVzYzsKICAgIH0gZWxzZSBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkIHx8IGRlc2MgPT09IG51bGwpIHsKICAgICAgdmFsdWUkJDEgPSBkYXRhOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICYmIHdhdGNoaW5nKSB7CiAgICAgICAgbWV0YSQkMS53cml0ZVZhbHVlcyhrZXlOYW1lLCBkYXRhKTsKICAgICAgICB2YXIgZGVmYXVsdERlc2NyaXB0b3IgPSB7CiAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgICBlbnVtZXJhYmxlOiBlbnVtZXJhYmxlLAogICAgICAgICAgc2V0OiBNQU5EQVRPUllfU0VUVEVSX0ZVTkNUSU9OKGtleU5hbWUpLAogICAgICAgICAgZ2V0OiBERUZBVUxUX0dFVFRFUl9GVU5DVElPTihrZXlOYW1lKQogICAgICAgIH07CiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwga2V5TmFtZSwgZGVmYXVsdERlc2NyaXB0b3IpOwogICAgICB9IGVsc2UgaWYgKHdhc0Rlc2NyaXB0b3IgfHwgZW51bWVyYWJsZSA9PT0gZmFsc2UpIHsKICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCB7CiAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgICBlbnVtZXJhYmxlOiBlbnVtZXJhYmxlLAogICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICB2YWx1ZTogdmFsdWUkJDEKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAodHJ1ZQogICAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICAgICYmIGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgICgwLCBfdXRpbHMuc2V0V2l0aE1hbmRhdG9yeVNldHRlcikob2JqLCBrZXlOYW1lLCBkYXRhKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb2JqW2tleU5hbWVdID0gZGF0YTsKICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhbHVlJCQxID0gZGVzYzsgLy8gZmFsbGJhY2sgdG8gRVM1CgogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCBkZXNjKTsKICAgIH0gLy8gaWYga2V5IGlzIGJlaW5nIHdhdGNoZWQsIG92ZXJyaWRlIGNoYWlucyB0aGF0CiAgICAvLyB3ZXJlIGluaXRpYWxpemVkIHdpdGggdGhlIHByb3RvdHlwZQoKCiAgICB7CiAgICAgIGlmICghbWV0YSQkMS5pc1Byb3RvdHlwZU1ldGEob2JqKSkgewogICAgICAgIHJldmFsaWRhdGVPYnNlcnZlcnMob2JqKTsKICAgICAgfQogICAgfSAvLyBUaGUgYHZhbHVlYCBwYXNzZWQgdG8gdGhlIGBkaWREZWZpbmVQcm9wZXJ0eWAgaG9vayBpcwogICAgLy8gZWl0aGVyIHRoZSBkZXNjcmlwdG9yIG9yIGRhdGEsIHdoaWNoZXZlciB3YXMgcGFzc2VkLgoKICAgIGlmICh0eXBlb2Ygb2JqLmRpZERlZmluZVByb3BlcnR5ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIG9iai5kaWREZWZpbmVQcm9wZXJ0eShvYmosIGtleU5hbWUsIHZhbHVlJCQxKTsKICAgIH0KICB9CgogIHZhciBoYW5kbGVNYW5kYXRvcnlTZXR0ZXI7CgogIGZ1bmN0aW9uIHdhdGNoS2V5KG9iaiwga2V5TmFtZSwgX21ldGEpIHsKICAgIHZhciBtZXRhJCQxID0gX21ldGEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIubWV0YSkob2JqKSA6IF9tZXRhOwogICAgdmFyIGNvdW50ID0gbWV0YSQkMS5wZWVrV2F0Y2hpbmcoa2V5TmFtZSk7CiAgICBtZXRhJCQxLndyaXRlV2F0Y2hpbmcoa2V5TmFtZSwgY291bnQgKyAxKTsKCiAgICBpZiAoY291bnQgPT09IDApIHsKICAgICAgLy8gYWN0aXZhdGUgd2F0Y2hpbmcgZmlyc3QgdGltZQogICAgICB2YXIgcG9zc2libGVEZXNjID0gZGVzY3JpcHRvckZvclByb3BlcnR5KG9iaiwga2V5TmFtZSwgbWV0YSQkMSk7CgogICAgICBpZiAocG9zc2libGVEZXNjICE9PSB1bmRlZmluZWQgJiYgcG9zc2libGVEZXNjLndpbGxXYXRjaCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcG9zc2libGVEZXNjLndpbGxXYXRjaChvYmosIGtleU5hbWUsIG1ldGEkJDEpOwogICAgICB9CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgLy8gTk9URTogdGhpcyBpcyBkcm9wcGVkIGZvciBwcm9kICsgbWluaWZpZWQgYnVpbGRzCiAgICAgICAgaGFuZGxlTWFuZGF0b3J5U2V0dGVyKG1ldGEkJDEsIG9iaiwga2V5TmFtZSk7CiAgICAgIH0KICAgIH0KICB9CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICB2YXIgX2hhc093blByb3BlcnR5ID0gZnVuY3Rpb24gX2hhc093blByb3BlcnR5KG9iaiwga2V5KSB7CiAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpOwogICAgfTsKCiAgICB2YXIgX3Byb3BlcnR5SXNFbnVtZXJhYmxlID0gZnVuY3Rpb24gX3Byb3BlcnR5SXNFbnVtZXJhYmxlKG9iaiwga2V5KSB7CiAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwob2JqLCBrZXkpOwogICAgfTsgLy8gRnV0dXJlIHRyYXZlbGVyLCBhbHRob3VnaCB0aGlzIGNvZGUgbG9va3Mgc2NhcnkuIEl0IG1lcmVseSBleGlzdHMgaW4KICAgIC8vIGRldmVsb3BtZW50IHRvIGFpZCBpbiBkZXZlbG9wbWVudCBhc2VydGlvbnMuIFByb2R1Y3Rpb24gYnVpbGRzIG9mCiAgICAvLyBlbWJlciBzdHJpcCB0aGlzIGVudGlyZSBibG9jayBvdXQKCgogICAgaGFuZGxlTWFuZGF0b3J5U2V0dGVyID0gZnVuY3Rpb24gaGFuZGxlTWFuZGF0b3J5U2V0dGVyKG0sIG9iaiwga2V5TmFtZSkgewogICAgICB2YXIgZGVzY3JpcHRvciA9ICgwLCBfdXRpbHMubG9va3VwRGVzY3JpcHRvcikob2JqLCBrZXlOYW1lKTsKICAgICAgdmFyIGhhc0Rlc2NyaXB0b3IgPSBkZXNjcmlwdG9yICE9PSBudWxsOwogICAgICB2YXIgcG9zc2libGVEZXNjID0gaGFzRGVzY3JpcHRvciAmJiBkZXNjcmlwdG9yLnZhbHVlOwoKICAgICAgaWYgKGlzQ2xhc3NpY0RlY29yYXRvcihwb3NzaWJsZURlc2MpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgY29uZmlndXJhYmxlID0gaGFzRGVzY3JpcHRvciA/IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlIDogdHJ1ZTsKICAgICAgdmFyIGlzV3JpdGFibGUgPSBoYXNEZXNjcmlwdG9yID8gZGVzY3JpcHRvci53cml0YWJsZSA6IHRydWU7CiAgICAgIHZhciBoYXNWYWx1ZSA9IGhhc0Rlc2NyaXB0b3IgPyAndmFsdWUnIGluIGRlc2NyaXB0b3IgOiB0cnVlOyAvLyB0aGlzIHggaW4gWSBkZW9wdHMsIHNvIGtlZXBpbmcgaXQgaW4gdGhpcyBmdW5jdGlvbiBpcyBiZXR0ZXI7CgogICAgICBpZiAoY29uZmlndXJhYmxlICYmIGlzV3JpdGFibGUgJiYgaGFzVmFsdWUgJiYga2V5TmFtZSBpbiBvYmopIHsKICAgICAgICB2YXIgZGVzYyA9IHsKICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICAgIHNldDogTUFOREFUT1JZX1NFVFRFUl9GVU5DVElPTihrZXlOYW1lKSwKICAgICAgICAgIGVudW1lcmFibGU6IF9wcm9wZXJ0eUlzRW51bWVyYWJsZShvYmosIGtleU5hbWUpLAogICAgICAgICAgZ2V0OiB1bmRlZmluZWQKICAgICAgICB9OwoKICAgICAgICBpZiAoX2hhc093blByb3BlcnR5KG9iaiwga2V5TmFtZSkpIHsKICAgICAgICAgIG0ud3JpdGVWYWx1ZXMoa2V5TmFtZSwgb2JqW2tleU5hbWVdKTsKICAgICAgICAgIGRlc2MuZ2V0ID0gREVGQVVMVF9HRVRURVJfRlVOQ1RJT04oa2V5TmFtZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGRlc2MuZ2V0ID0gSU5IRVJJVElOR19HRVRURVJfRlVOQ1RJT04oa2V5TmFtZSk7CiAgICAgICAgfQoKICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCBkZXNjKTsKICAgICAgfQogICAgfTsKICB9CgogIGZ1bmN0aW9uIHVud2F0Y2hLZXkob2JqLCBrZXlOYW1lLCBfbWV0YSkgewogICAgdmFyIG1ldGEkJDEgPSBfbWV0YSA9PT0gdW5kZWZpbmVkID8gKDAsIF9tZXRhMi5wZWVrTWV0YSkob2JqKSA6IF9tZXRhOyAvLyBkbyBub3RoaW5nIG9mIHRoaXMgb2JqZWN0IGhhcyBhbHJlYWR5IGJlZW4gZGVzdHJveWVkCgogICAgaWYgKG1ldGEkJDEgPT09IG51bGwgfHwgbWV0YSQkMS5pc1NvdXJjZURlc3Ryb3llZCgpKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgY291bnQgPSBtZXRhJCQxLnBlZWtXYXRjaGluZyhrZXlOYW1lKTsKCiAgICBpZiAoY291bnQgPT09IDEpIHsKICAgICAgbWV0YSQkMS53cml0ZVdhdGNoaW5nKGtleU5hbWUsIDApOwogICAgICB2YXIgcG9zc2libGVEZXNjID0gZGVzY3JpcHRvckZvclByb3BlcnR5KG9iaiwga2V5TmFtZSwgbWV0YSQkMSk7CiAgICAgIHZhciBpc0Rlc2NyaXB0b3IgPSBwb3NzaWJsZURlc2MgIT09IHVuZGVmaW5lZDsKCiAgICAgIGlmIChpc0Rlc2NyaXB0b3IgJiYgcG9zc2libGVEZXNjLmRpZFVud2F0Y2ggIT09IHVuZGVmaW5lZCkgewogICAgICAgIHBvc3NpYmxlRGVzYy5kaWRVbndhdGNoKG9iaiwga2V5TmFtZSwgbWV0YSQkMSk7CiAgICAgIH0KCiAgICAgIGlmICh0eXBlb2Ygb2JqLmRpZFVud2F0Y2hQcm9wZXJ0eSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIG9iai5kaWRVbndhdGNoUHJvcGVydHkoa2V5TmFtZSk7CiAgICAgIH0KCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICAvLyBJdCBpcyB0cnVlLCB0aGUgZm9sbG93aW5nIGNvZGUgbG9va3MgcXVpdGUgV0FULiBCdXQgaGF2ZSBubyBmZWFyLCBJdAogICAgICAgIC8vIGV4aXN0cyBwdXJlbHkgdG8gaW1wcm92ZSBkZXZlbG9wbWVudCBlcmdvbm9taWNzIGFuZCBpcyByZW1vdmVkIGZyb20KICAgICAgICAvLyBlbWJlci5taW4uanMgYW5kIGVtYmVyLnByb2QuanMgYnVpbGRzLgogICAgICAgIC8vCiAgICAgICAgLy8gU29tZSBmdXJ0aGVyIGNvbnRleHQ6IE9uY2UgYSBwcm9wZXJ0eSBpcyB3YXRjaGVkIGJ5IGVtYmVyLCBieXBhc3NpbmcgYHNldGAKICAgICAgICAvLyBmb3IgbXV0YXRpb24sIHdpbGwgYnlwYXNzIG9ic2VydmF0aW9uLiBUaGlzIGNvZGUgZXhpc3RzIHRvIGFzc2VydCB3aGVuCiAgICAgICAgLy8gdGhhdCBvY2N1cnMsIGFuZCBhdHRlbXB0IHRvIHByb3ZpZGUgbW9yZSBoZWxwZnVsIGZlZWRiYWNrLiBUaGUgYWx0ZXJuYXRpdmUKICAgICAgICAvLyBpcyB0cmlja3kgdG8gZGVidWcgcGFydGlhbGx5IG9ic2VydmFibGUgcHJvcGVydGllcy4KICAgICAgICBpZiAoIWlzRGVzY3JpcHRvciAmJiBrZXlOYW1lIGluIG9iaikgewogICAgICAgICAgdmFyIG1heWJlTWFuZGF0b3J5RGVzY3JpcHRvciA9ICgwLCBfdXRpbHMubG9va3VwRGVzY3JpcHRvcikob2JqLCBrZXlOYW1lKTsKCiAgICAgICAgICBpZiAobWF5YmVNYW5kYXRvcnlEZXNjcmlwdG9yICYmIG1heWJlTWFuZGF0b3J5RGVzY3JpcHRvci5zZXQgJiYgbWF5YmVNYW5kYXRvcnlEZXNjcmlwdG9yLnNldC5pc01hbmRhdG9yeVNldHRlcikgewogICAgICAgICAgICBpZiAobWF5YmVNYW5kYXRvcnlEZXNjcmlwdG9yLmdldCAmJiBtYXliZU1hbmRhdG9yeURlc2NyaXB0b3IuZ2V0LmlzSW5oZXJpdGluZ0dldHRlcikgewogICAgICAgICAgICAgIHZhciBwb3NzaWJsZVZhbHVlID0gbWV0YSQkMS5yZWFkSW5oZXJpdGVkVmFsdWUoa2V5TmFtZSk7CgogICAgICAgICAgICAgIGlmIChwb3NzaWJsZVZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgIGRlbGV0ZSBvYmpba2V5TmFtZV07CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCB7CiAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgIGVudW1lcmFibGU6IE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChvYmosIGtleU5hbWUpLAogICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgIHZhbHVlOiBtZXRhJCQxLnBlZWtWYWx1ZXMoa2V5TmFtZSkKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIG1ldGEkJDEuZGVsZXRlRnJvbVZhbHVlcyhrZXlOYW1lKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoY291bnQgPiAxKSB7CiAgICAgIG1ldGEkJDEud3JpdGVXYXRjaGluZyhrZXlOYW1lLCBjb3VudCAtIDEpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZWFjaFByb3h5Rm9yKGFycmF5KSB7CiAgICB2YXIgZWFjaFByb3h5ID0gRUFDSF9QUk9YSUVTLmdldChhcnJheSk7CgogICAgaWYgKGVhY2hQcm94eSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGVhY2hQcm94eSA9IG5ldyBFYWNoUHJveHkoYXJyYXkpOwogICAgICBFQUNIX1BST1hJRVMuc2V0KGFycmF5LCBlYWNoUHJveHkpOwogICAgfQoKICAgIHJldHVybiBlYWNoUHJveHk7CiAgfQoKICB2YXIgRWFjaFByb3h5ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRWFjaFByb3h5KGNvbnRlbnQpIHsKICAgICAgdGhpcy5fY29udGVudCA9IGNvbnRlbnQ7CiAgICAgIHRoaXMuX2tleXMgPSB1bmRlZmluZWQ7CiAgICAgICgwLCBfbWV0YTIubWV0YSkodGhpcyk7CiAgICB9IC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KICAgIC8vIEFSUkFZIENIQU5HRVMKICAgIC8vIEludm9rZXMgd2hlbmV2ZXIgdGhlIGNvbnRlbnQgYXJyYXkgaXRzZWxmIGNoYW5nZXMuCgoKICAgIHZhciBfcHJvdG8gPSBFYWNoUHJveHkucHJvdG90eXBlOwoKICAgIF9wcm90by5hcnJheVdpbGxDaGFuZ2UgPSBmdW5jdGlvbiBhcnJheVdpbGxDaGFuZ2UoY29udGVudCwgaWR4LCByZW1vdmVkQ250CiAgICAvKiwgYWRkZWRDbnQgKi8KICAgICkgewogICAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzCiAgICAgIHZhciBrZXlzID0gdGhpcy5fa2V5czsKCiAgICAgIGlmICgha2V5cykgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIGxpbSA9IHJlbW92ZWRDbnQgPiAwID8gaWR4ICsgcmVtb3ZlZENudCA6IC0xOwoKICAgICAgaWYgKGxpbSA+IDApIHsKICAgICAgICBmb3IgKHZhciBrZXkgaW4ga2V5cykgewogICAgICAgICAgcmVtb3ZlT2JzZXJ2ZXJGb3JDb250ZW50S2V5KGNvbnRlbnQsIGtleSwgdGhpcywgaWR4LCBsaW0pOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uYXJyYXlEaWRDaGFuZ2UgPSBmdW5jdGlvbiBhcnJheURpZENoYW5nZShjb250ZW50LCBpZHgsIF9yZW1vdmVkQ250LCBhZGRlZENudCkgewogICAgICB2YXIga2V5cyA9IHRoaXMuX2tleXM7CgogICAgICBpZiAoIWtleXMpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBsaW0gPSBhZGRlZENudCA+IDAgPyBpZHggKyBhZGRlZENudCA6IC0xOwogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKHRoaXMpOwoKICAgICAgZm9yICh2YXIga2V5IGluIGtleXMpIHsKICAgICAgICBpZiAobGltID4gMCkgewogICAgICAgICAgYWRkT2JzZXJ2ZXJGb3JDb250ZW50S2V5KGNvbnRlbnQsIGtleSwgdGhpcywgaWR4LCBsaW0pOwogICAgICAgIH0KCiAgICAgICAgbm90aWZ5UHJvcGVydHlDaGFuZ2UodGhpcywga2V5LCBtZXRhJCQxKTsKICAgICAgfQogICAgfSAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uCiAgICAvLyBMSVNURU4gRk9SIE5FVyBPQlNFUlZFUlMgQU5EIE9USEVSIEVWRU5UIExJU1RFTkVSUwogICAgLy8gU3RhcnQgbW9uaXRvcmluZyBrZXlzIGJhc2VkIG9uIHdobyBpcyBsaXN0ZW5pbmcuLi4KICAgIDsKCiAgICBfcHJvdG8ud2lsbFdhdGNoUHJvcGVydHkgPSBmdW5jdGlvbiB3aWxsV2F0Y2hQcm9wZXJ0eShwcm9wZXJ0eSkgewogICAgICB0aGlzLmJlZ2luT2JzZXJ2aW5nQ29udGVudEtleShwcm9wZXJ0eSk7CiAgICB9OwoKICAgIF9wcm90by5kaWRVbndhdGNoUHJvcGVydHkgPSBmdW5jdGlvbiBkaWRVbndhdGNoUHJvcGVydHkocHJvcGVydHkpIHsKICAgICAgdGhpcy5zdG9wT2JzZXJ2aW5nQ29udGVudEtleShwcm9wZXJ0eSk7CiAgICB9IC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KICAgIC8vIENPTlRFTlQgS0VZIE9CU0VSVklORwogICAgLy8gQWN0dWFsIHdhdGNoIGtleXMgb24gdGhlIHNvdXJjZSBjb250ZW50LgogICAgOwoKICAgIF9wcm90by5iZWdpbk9ic2VydmluZ0NvbnRlbnRLZXkgPSBmdW5jdGlvbiBiZWdpbk9ic2VydmluZ0NvbnRlbnRLZXkoa2V5TmFtZSkgewogICAgICB2YXIga2V5cyA9IHRoaXMuX2tleXM7CgogICAgICBpZiAoa2V5cyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAga2V5cyA9IHRoaXMuX2tleXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB9CgogICAgICBpZiAoIWtleXNba2V5TmFtZV0pIHsKICAgICAgICBrZXlzW2tleU5hbWVdID0gMTsKICAgICAgICB2YXIgY29udGVudCA9IHRoaXMuX2NvbnRlbnQ7CiAgICAgICAgdmFyIGxlbiA9IGNvbnRlbnQubGVuZ3RoOwogICAgICAgIGFkZE9ic2VydmVyRm9yQ29udGVudEtleShjb250ZW50LCBrZXlOYW1lLCB0aGlzLCAwLCBsZW4pOwogICAgICB9IGVsc2UgewogICAgICAgIGtleXNba2V5TmFtZV0rKzsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uc3RvcE9ic2VydmluZ0NvbnRlbnRLZXkgPSBmdW5jdGlvbiBzdG9wT2JzZXJ2aW5nQ29udGVudEtleShrZXlOYW1lKSB7CiAgICAgIHZhciBrZXlzID0gdGhpcy5fa2V5czsKCiAgICAgIGlmIChrZXlzICE9PSB1bmRlZmluZWQgJiYga2V5c1trZXlOYW1lXSA+IDAgJiYgLS1rZXlzW2tleU5hbWVdIDw9IDApIHsKICAgICAgICB2YXIgY29udGVudCA9IHRoaXMuX2NvbnRlbnQ7CiAgICAgICAgdmFyIGxlbiA9IGNvbnRlbnQubGVuZ3RoOwogICAgICAgIHJlbW92ZU9ic2VydmVyRm9yQ29udGVudEtleShjb250ZW50LCBrZXlOYW1lLCB0aGlzLCAwLCBsZW4pOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5jb250ZW50S2V5RGlkQ2hhbmdlID0gZnVuY3Rpb24gY29udGVudEtleURpZENoYW5nZShfb2JqLCBrZXlOYW1lKSB7CiAgICAgIG5vdGlmeVByb3BlcnR5Q2hhbmdlKHRoaXMsIGtleU5hbWUpOwogICAgfTsKCiAgICByZXR1cm4gRWFjaFByb3h5OwogIH0oKTsKCiAgZnVuY3Rpb24gYWRkT2JzZXJ2ZXJGb3JDb250ZW50S2V5KGNvbnRlbnQsIGtleU5hbWUsIHByb3h5LCBpZHgsIGxvYykgewogICAgd2hpbGUgKC0tbG9jID49IGlkeCkgewogICAgICB2YXIgaXRlbSA9IG9iamVjdEF0KGNvbnRlbnQsIGxvYyk7CgogICAgICBpZiAoaXRlbSkgewogICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBpdGVtID09PSAnb2JqZWN0JykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJXaGVuIHVzaW5nIEBlYWNoIHRvIG9ic2VydmUgdGhlIGFycmF5IGAiICsgY29udGVudC50b1N0cmluZygpICsgImAsIHRoZSBhcnJheSBtdXN0IHJldHVybiBhbiBvYmplY3QiLCB0eXBlb2YgaXRlbSA9PT0gJ29iamVjdCcpKTsKICAgICAgICBhZGRPYnNlcnZlcihpdGVtLCBrZXlOYW1lLCBwcm94eSwgJ2NvbnRlbnRLZXlEaWRDaGFuZ2UnKTsKICAgICAgfQogICAgfQogIH0KCiAgZnVuY3Rpb24gcmVtb3ZlT2JzZXJ2ZXJGb3JDb250ZW50S2V5KGNvbnRlbnQsIGtleU5hbWUsIHByb3h5LCBpZHgsIGxvYykgewogICAgd2hpbGUgKC0tbG9jID49IGlkeCkgewogICAgICB2YXIgaXRlbSA9IG9iamVjdEF0KGNvbnRlbnQsIGxvYyk7CgogICAgICBpZiAoaXRlbSkgewogICAgICAgIHJlbW92ZU9ic2VydmVyKGl0ZW0sIGtleU5hbWUsIHByb3h5LCAnY29udGVudEtleURpZENoYW5nZScpOwogICAgICB9CiAgICB9CiAgfQoKICB2YXIgVU5LTk9XTl9QUk9QRVJUWV9UQUcgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ1VOS05PV05fUFJPUEVSVFlfVEFHJyk7CiAgX2V4cG9ydHMuVU5LTk9XTl9QUk9QRVJUWV9UQUcgPSBVTktOT1dOX1BST1BFUlRZX1RBRzsKCiAgZnVuY3Rpb24gdGFnRm9yUHJvcGVydHkob2JqZWN0LCBwcm9wZXJ0eUtleSwgX21ldGEpIHsKICAgIHZhciBvYmplY3RUeXBlID0gdHlwZW9mIG9iamVjdDsKCiAgICBpZiAob2JqZWN0VHlwZSAhPT0gJ2Z1bmN0aW9uJyAmJiAob2JqZWN0VHlwZSAhPT0gJ29iamVjdCcgfHwgb2JqZWN0ID09PSBudWxsKSkgewogICAgICByZXR1cm4gX3JlZmVyZW5jZS5DT05TVEFOVF9UQUc7CiAgICB9CgogICAgdmFyIG1ldGEkJDEgPSBfbWV0YSA9PT0gdW5kZWZpbmVkID8gKDAsIF9tZXRhMi5tZXRhKShvYmplY3QpIDogX21ldGE7CiAgICB7CiAgICAgIGlmICghKHByb3BlcnR5S2V5IGluIG9iamVjdCkgJiYgdHlwZW9mIG9iamVjdFtVTktOT1dOX1BST1BFUlRZX1RBR10gPT09ICdmdW5jdGlvbicpIHsKICAgICAgICByZXR1cm4gb2JqZWN0W1VOS05PV05fUFJPUEVSVFlfVEFHXShwcm9wZXJ0eUtleSk7CiAgICAgIH0KICAgIH0KICAgIHZhciB0YWdzID0gbWV0YSQkMS53cml0YWJsZVRhZ3MoKTsKICAgIHZhciB0YWcgPSB0YWdzW3Byb3BlcnR5S2V5XTsKCiAgICBpZiAodGFnKSB7CiAgICAgIHJldHVybiB0YWc7CiAgICB9CgogICAgewogICAgICB2YXIgbmV3VGFnID0gKDAsIF9yZWZlcmVuY2UuY3JlYXRlVXBkYXRhYmxlVGFnKSgpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHsKICAgICAgICAgICgwLCBfdXRpbHMuc2V0dXBNYW5kYXRvcnlTZXR0ZXIpKG9iamVjdCwgcHJvcGVydHlLZXkpOwogICAgICAgIH0KICAgICAgICBuZXdUYWcuX3Byb3BlcnR5S2V5ID0gcHJvcGVydHlLZXk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0YWdzW3Byb3BlcnR5S2V5XSA9IG5ld1RhZzsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHRhZ0ZvcihvYmplY3QsIF9tZXRhKSB7CiAgICBpZiAodHlwZW9mIG9iamVjdCA9PT0gJ29iamVjdCcgJiYgb2JqZWN0ICE9PSBudWxsKSB7CiAgICAgIHZhciBtZXRhJCQxID0gX21ldGEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIubWV0YSkob2JqZWN0KSA6IF9tZXRhOwoKICAgICAgaWYgKCFtZXRhJCQxLmlzTWV0YURlc3Ryb3llZCgpKSB7CiAgICAgICAgcmV0dXJuIG1ldGEkJDEud3JpdGFibGVUYWcoKTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBfcmVmZXJlbmNlLkNPTlNUQU5UX1RBRzsKICB9CgogIGZ1bmN0aW9uIG1hcmtPYmplY3RBc0RpcnR5KG9iaiwgcHJvcGVydHlLZXksIF9tZXRhKSB7CiAgICB2YXIgbWV0YSQkMSA9IF9tZXRhID09PSB1bmRlZmluZWQgPyAoMCwgX21ldGEyLm1ldGEpKG9iaikgOiBfbWV0YTsKICAgIHZhciBvYmplY3RUYWcgPSBtZXRhJCQxLnJlYWRhYmxlVGFnKCk7CgogICAgaWYgKG9iamVjdFRhZyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICgwLCBfcmVmZXJlbmNlLmRpcnR5KShvYmplY3RUYWcpOwogICAgfQoKICAgIHZhciB0YWdzID0gbWV0YSQkMS5yZWFkYWJsZVRhZ3MoKTsKICAgIHZhciBwcm9wZXJ0eVRhZyA9IHRhZ3MgIT09IHVuZGVmaW5lZCA/IHRhZ3NbcHJvcGVydHlLZXldIDogdW5kZWZpbmVkOwoKICAgIGlmIChwcm9wZXJ0eVRhZyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICgwLCBfcmVmZXJlbmNlLmRpcnR5KShwcm9wZXJ0eVRhZyk7CiAgICB9CgogICAgaWYgKG9iamVjdFRhZyAhPT0gdW5kZWZpbmVkIHx8IHByb3BlcnR5VGFnICE9PSB1bmRlZmluZWQpIHsKICAgICAgZW5zdXJlUnVubG9vcCgpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZW5zdXJlUnVubG9vcCgpIHsKICAgIF9ydW5sb29wLmJhY2tidXJuZXIuZW5zdXJlSW5zdGFuY2UoKTsKICB9CgogIGZ1bmN0aW9uIGlzRWxlbWVudERlc2NyaXB0b3IoYXJncykgewogICAgdmFyIG1heWJlVGFyZ2V0ID0gYXJnc1swXSwKICAgICAgICBtYXliZUtleSA9IGFyZ3NbMV0sCiAgICAgICAgbWF5YmVEZXNjID0gYXJnc1syXTsKICAgIHJldHVybiAoLy8gRW5zdXJlIHdlIGhhdmUgdGhlIHJpZ2h0IG51bWJlciBvZiBhcmdzCiAgICAgIGFyZ3MubGVuZ3RoID09PSAzICYmICggLy8gTWFrZSBzdXJlIHRoZSB0YXJnZXQgaXMgYSBjbGFzcyBvciBvYmplY3QgKHByb3RvdHlwZSkKICAgICAgdHlwZW9mIG1heWJlVGFyZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBtYXliZVRhcmdldCA9PT0gJ29iamVjdCcgJiYgbWF5YmVUYXJnZXQgIT09IG51bGwpICYmIC8vIE1ha2Ugc3VyZSB0aGUga2V5IGlzIGEgc3RyaW5nCiAgICAgIHR5cGVvZiBtYXliZUtleSA9PT0gJ3N0cmluZycgJiYgKCAvLyBNYWtlIHN1cmUgdGhlIGRlc2NyaXB0b3IgaXMgdGhlIHJpZ2h0IHNoYXBlCiAgICAgIHR5cGVvZiBtYXliZURlc2MgPT09ICdvYmplY3QnICYmIG1heWJlRGVzYyAhPT0gbnVsbCAmJiAnZW51bWVyYWJsZScgaW4gbWF5YmVEZXNjICYmICdjb25maWd1cmFibGUnIGluIG1heWJlRGVzYyB8fCAvLyBUUyBjb21wYXRpYmlsaXR5CiAgICAgIG1heWJlRGVzYyA9PT0gdW5kZWZpbmVkKQogICAgKTsKICB9IC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KICAvLyBERVBFTkRFTlQgS0VZUwogIC8vCgoKICBmdW5jdGlvbiBhZGREZXBlbmRlbnRLZXlzKGRlc2MsIG9iaiwga2V5TmFtZSwgbWV0YSQkMSkgewogICAgLy8gdGhlIGRlc2NyaXB0b3IgaGFzIGEgbGlzdCBvZiBkZXBlbmRlbnQga2V5cywgc28KICAgIC8vIGFkZCBhbGwgb2YgaXRzIGRlcGVuZGVudCBrZXlzLgogICAgdmFyIGRlcEtleXMgPSBkZXNjLl9kZXBlbmRlbnRLZXlzOwoKICAgIGlmIChkZXBLZXlzID09PSBudWxsIHx8IGRlcEtleXMgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm47CiAgICB9CgogICAgZm9yICh2YXIgaWR4ID0gMDsgaWR4IDwgZGVwS2V5cy5sZW5ndGg7IGlkeCsrKSB7CiAgICAgIHZhciBkZXBLZXkgPSBkZXBLZXlzW2lkeF07IC8vIEluY3JlbWVudCB0aGUgbnVtYmVyIG9mIHRpbWVzIGRlcEtleSBkZXBlbmRzIG9uIGtleU5hbWUuCgogICAgICBtZXRhJCQxLndyaXRlRGVwcyhkZXBLZXksIGtleU5hbWUsIG1ldGEkJDEucGVla0RlcHMoZGVwS2V5LCBrZXlOYW1lKSArIDEpOyAvLyBXYXRjaCB0aGUgZGVwS2V5CgogICAgICB3YXRjaChvYmosIGRlcEtleSwgbWV0YSQkMSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiByZW1vdmVEZXBlbmRlbnRLZXlzKGRlc2MsIG9iaiwga2V5TmFtZSwgbWV0YSQkMSkgewogICAgLy8gdGhlIGRlc2NyaXB0b3IgaGFzIGEgbGlzdCBvZiBkZXBlbmRlbnQga2V5cywgc28KICAgIC8vIHJlbW92ZSBhbGwgb2YgaXRzIGRlcGVuZGVudCBrZXlzLgogICAgdmFyIGRlcEtleXMgPSBkZXNjLl9kZXBlbmRlbnRLZXlzOwoKICAgIGlmIChkZXBLZXlzID09PSBudWxsIHx8IGRlcEtleXMgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm47CiAgICB9CgogICAgZm9yICh2YXIgaWR4ID0gMDsgaWR4IDwgZGVwS2V5cy5sZW5ndGg7IGlkeCsrKSB7CiAgICAgIHZhciBkZXBLZXkgPSBkZXBLZXlzW2lkeF07IC8vIERlY3JlbWVudCB0aGUgbnVtYmVyIG9mIHRpbWVzIGRlcEtleSBkZXBlbmRzIG9uIGtleU5hbWUuCgogICAgICBtZXRhJCQxLndyaXRlRGVwcyhkZXBLZXksIGtleU5hbWUsIG1ldGEkJDEucGVla0RlcHMoZGVwS2V5LCBrZXlOYW1lKSAtIDEpOyAvLyBVbndhdGNoIHRoZSBkZXBLZXkKCiAgICAgIHVud2F0Y2gob2JqLCBkZXBLZXksIG1ldGEkJDEpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gbmF0aXZlRGVzY0RlY29yYXRvcihwcm9wZXJ0eURlc2MpIHsKICAgIHZhciBkZWNvcmF0b3IgPSBmdW5jdGlvbiBkZWNvcmF0b3IoKSB7CiAgICAgIHJldHVybiBwcm9wZXJ0eURlc2M7CiAgICB9OwoKICAgIHNldENsYXNzaWNEZWNvcmF0b3IoZGVjb3JhdG9yKTsKICAgIHJldHVybiBkZWNvcmF0b3I7CiAgfQogIC8qKgogICAgT2JqZWN0cyBvZiB0aGlzIHR5cGUgY2FuIGltcGxlbWVudCBhbiBpbnRlcmZhY2UgdG8gcmVzcG9uZCB0byByZXF1ZXN0cyB0bwogICAgZ2V0IGFuZCBzZXQuIFRoZSBkZWZhdWx0IGltcGxlbWVudGF0aW9uIGhhbmRsZXMgc2ltcGxlIHByb3BlcnRpZXMuCiAgCiAgICBAY2xhc3MgRGVzY3JpcHRvcgogICAgQHByaXZhdGUKICAqLwoKCiAgdmFyIENvbXB1dGVkRGVzY3JpcHRvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENvbXB1dGVkRGVzY3JpcHRvcigpIHsKICAgICAgdGhpcy5lbnVtZXJhYmxlID0gdHJ1ZTsKICAgICAgdGhpcy5jb25maWd1cmFibGUgPSB0cnVlOwogICAgICB0aGlzLl9kZXBlbmRlbnRLZXlzID0gdW5kZWZpbmVkOwogICAgICB0aGlzLl9tZXRhID0gdW5kZWZpbmVkOwogICAgfQoKICAgIHZhciBfcHJvdG8yID0gQ29tcHV0ZWREZXNjcmlwdG9yLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yLnNldHVwID0gZnVuY3Rpb24gc2V0dXAoX29iaiwga2V5TmFtZSwgX3Byb3BlcnR5RGVzYywgbWV0YSQkMSkgewogICAgICBtZXRhJCQxLndyaXRlRGVzY3JpcHRvcnMoa2V5TmFtZSwgdGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzIudGVhcmRvd24gPSBmdW5jdGlvbiB0ZWFyZG93bihfb2JqLCBrZXlOYW1lLCBtZXRhJCQxKSB7CiAgICAgIG1ldGEkJDEucmVtb3ZlRGVzY3JpcHRvcnMoa2V5TmFtZSk7CiAgICB9OwoKICAgIHJldHVybiBDb21wdXRlZERlc2NyaXB0b3I7CiAgfSgpOwoKICBmdW5jdGlvbiBERVNDUklQVE9SX0dFVFRFUl9GVU5DVElPTihuYW1lLCBkZXNjcmlwdG9yKSB7CiAgICByZXR1cm4gZnVuY3Rpb24gQ1BHRVRURVJfRlVOQ1RJT04oKSB7CiAgICAgIHJldHVybiBkZXNjcmlwdG9yLmdldCh0aGlzLCBuYW1lKTsKICAgIH07CiAgfQoKICBmdW5jdGlvbiBERVNDUklQVE9SX1NFVFRFUl9GVU5DVElPTihuYW1lLCBkZXNjcmlwdG9yKSB7CiAgICB2YXIgZnVuYyA9IGZ1bmN0aW9uIENQU0VUVEVSX0ZVTkNUSU9OKHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiBkZXNjcmlwdG9yLnNldCh0aGlzLCBuYW1lLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIENQX1NFVFRFUl9GVU5DUy5hZGQoZnVuYyk7CiAgICByZXR1cm4gZnVuYzsKICB9CgogIHZhciBDUF9TRVRURVJfRlVOQ1MgPSBuZXcgX3BvbHlmaWxscy5fV2Vha1NldCgpOwoKICBmdW5jdGlvbiBtYWtlQ29tcHV0ZWREZWNvcmF0b3IoZGVzYywgRGVjb3JhdG9yQ2xhc3MpIHsKICAgIHZhciBkZWNvcmF0b3IgPSBmdW5jdGlvbiBDT01QVVRFRF9ERUNPUkFUT1IodGFyZ2V0LCBrZXksIHByb3BlcnR5RGVzYywgbWF5YmVNZXRhLCBpc0NsYXNzaWNEZWNvcmF0b3IkJDEpIHsKICAgICAgKGZhbHNlICYmICEodHJ1ZQogICAgICAvKiBFTUJFUl9OQVRJVkVfREVDT1JBVE9SX1NVUFBPUlQgKi8KICAgICAgfHwgaXNDbGFzc2ljRGVjb3JhdG9yJCQxKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ05hdGl2ZSBkZWNvcmF0b3JzIGFyZSBub3QgZW5hYmxlZCB3aXRob3V0IHRoZSBFTUJFUl9OQVRJVkVfREVDT1JBVE9SX1NVUFBPUlQgZmxhZycsIHRydWUgfHwgaXNDbGFzc2ljRGVjb3JhdG9yJCQxKSk7CiAgICAgIChmYWxzZSAmJiAhKGlzQ2xhc3NpY0RlY29yYXRvciQkMSB8fCAhcHJvcGVydHlEZXNjIHx8ICFwcm9wZXJ0eURlc2MuZ2V0IHx8IHByb3BlcnR5RGVzYy5nZXQudG9TdHJpbmcoKS5pbmRleE9mKCdDUEdFVFRFUl9GVU5DVElPTicpID09PSAtMSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJPbmx5IG9uZSBjb21wdXRlZCBwcm9wZXJ0eSBkZWNvcmF0b3IgY2FuIGJlIGFwcGxpZWQgdG8gYSBjbGFzcyBmaWVsZCBvciBhY2Nlc3NvciwgYnV0ICciICsga2V5ICsgIicgd2FzIGRlY29yYXRlZCB0d2ljZS4gWW91IG1heSBoYXZlIGFkZGVkIHRoZSBkZWNvcmF0b3IgdG8gYm90aCBhIGdldHRlciBhbmQgc2V0dGVyLCB3aGljaCBpcyB1bmVjZXNzYXJ5LiIsIGlzQ2xhc3NpY0RlY29yYXRvciQkMSB8fCAhcHJvcGVydHlEZXNjIHx8ICFwcm9wZXJ0eURlc2MuZ2V0IHx8IHByb3BlcnR5RGVzYy5nZXQudG9TdHJpbmcoKS5pbmRleE9mKCdDUEdFVFRFUl9GVU5DVElPTicpID09PSAtMSkpOwogICAgICB2YXIgbWV0YSQkMSA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDMgPyAoMCwgX21ldGEyLm1ldGEpKHRhcmdldCkgOiBtYXliZU1ldGE7CiAgICAgIGRlc2Muc2V0dXAodGFyZ2V0LCBrZXksIHByb3BlcnR5RGVzYywgbWV0YSQkMSk7CiAgICAgIHZhciBjb21wdXRlZERlc2MgPSB7CiAgICAgICAgZW51bWVyYWJsZTogZGVzYy5lbnVtZXJhYmxlLAogICAgICAgIGNvbmZpZ3VyYWJsZTogZGVzYy5jb25maWd1cmFibGUsCiAgICAgICAgZ2V0OiBERVNDUklQVE9SX0dFVFRFUl9GVU5DVElPTihrZXksIGRlc2MpCiAgICAgIH07CiAgICAgIHsKICAgICAgICBjb21wdXRlZERlc2Muc2V0ID0gREVTQ1JJUFRPUl9TRVRURVJfRlVOQ1RJT04oa2V5LCBkZXNjKTsKICAgICAgfQogICAgICByZXR1cm4gY29tcHV0ZWREZXNjOwogICAgfTsKCiAgICBzZXRDbGFzc2ljRGVjb3JhdG9yKGRlY29yYXRvciwgZGVzYyk7CiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YoZGVjb3JhdG9yLCBEZWNvcmF0b3JDbGFzcy5wcm90b3R5cGUpOwogICAgcmV0dXJuIGRlY29yYXRvcjsKICB9CiAgLyoqCiAgICBBbiBvYmplY3QgdGhhdCB0aGF0IHRyYWNrcyBAdHJhY2tlZCBwcm9wZXJ0aWVzIHRoYXQgd2VyZSBjb25zdW1lZC4KICAKICAgIEBwcml2YXRlCiAgKi8KCgogIHZhciBUcmFja2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gVHJhY2tlcigpIHsKICAgICAgdGhpcy50YWdzID0gbmV3IFNldCgpOwogICAgICB0aGlzLmxhc3QgPSBudWxsOwogICAgfQoKICAgIHZhciBfcHJvdG8zID0gVHJhY2tlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMy5hZGQgPSBmdW5jdGlvbiBhZGQodGFnKSB7CiAgICAgIHRoaXMudGFncy5hZGQodGFnKTsKICAgICAgdGhpcy5sYXN0ID0gdGFnOwogICAgfTsKCiAgICBfcHJvdG8zLmNvbWJpbmUgPSBmdW5jdGlvbiBjb21iaW5lKCkgewogICAgICBpZiAodGhpcy50YWdzLnNpemUgPT09IDApIHsKICAgICAgICByZXR1cm4gX3JlZmVyZW5jZS5DT05TVEFOVF9UQUc7CiAgICAgIH0gZWxzZSBpZiAodGhpcy50YWdzLnNpemUgPT09IDEpIHsKICAgICAgICByZXR1cm4gdGhpcy5sYXN0OwogICAgICB9IGVsc2UgewogICAgICAgIHZhciB0YWdzID0gW107CiAgICAgICAgdGhpcy50YWdzLmZvckVhY2goZnVuY3Rpb24gKHRhZykgewogICAgICAgICAgcmV0dXJuIHRhZ3MucHVzaCh0YWcpOwogICAgICAgIH0pOwogICAgICAgIHJldHVybiAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKSh0YWdzKTsKICAgICAgfQogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKFRyYWNrZXIsIFt7CiAgICAgIGtleTogInNpemUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy50YWdzLnNpemU7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBUcmFja2VyOwogIH0oKTsKCiAgX2V4cG9ydHMuVHJhY2tlciA9IFRyYWNrZXI7CgogIGZ1bmN0aW9uIHRyYWNrZWQoKSB7CiAgICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjIpLCBfa2V5MyA9IDA7IF9rZXkzIDwgX2xlbjI7IF9rZXkzKyspIHsKICAgICAgYXJnc1tfa2V5M10gPSBhcmd1bWVudHNbX2tleTNdOwogICAgfQoKICAgIChmYWxzZSAmJiAhKCEoaXNFbGVtZW50RGVzY3JpcHRvcihhcmdzLnNsaWNlKDAsIDMpKSAmJiBhcmdzLmxlbmd0aCA9PT0gNSAmJiBhcmdzWzRdID09PSB0cnVlKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJAdHJhY2tlZCBjYW4gb25seSBiZSB1c2VkIGRpcmVjdGx5IGFzIGEgbmF0aXZlIGRlY29yYXRvci4gSWYgeW91J3JlIHVzaW5nIHRyYWNrZWQgaW4gY2xhc3NpYyBjbGFzc2VzLCBhZGQgcGFyZW50aGVzaXMgdG8gY2FsbCBpdCBsaWtlIGEgZnVuY3Rpb246IHRyYWNrZWQoKSIsICEoaXNFbGVtZW50RGVzY3JpcHRvcihhcmdzLnNsaWNlKDAsIDMpKSAmJiBhcmdzLmxlbmd0aCA9PT0gNSAmJiBhcmdzWzRdID09PSB0cnVlKSkpOwoKICAgIGlmICghaXNFbGVtZW50RGVzY3JpcHRvcihhcmdzKSkgewogICAgICB2YXIgcHJvcGVydHlEZXNjID0gYXJnc1swXTsKICAgICAgKGZhbHNlICYmICEoYXJncy5sZW5ndGggPT09IDAgfHwgdHlwZW9mIHByb3BlcnR5RGVzYyA9PT0gJ29iamVjdCcgJiYgcHJvcGVydHlEZXNjICE9PSBudWxsKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoInRyYWNrZWQoKSBtYXkgb25seSByZWNlaXZlIGFuIG9wdGlvbnMgb2JqZWN0IGNvbnRhaW5pbmcgJ3ZhbHVlJyBvciAnaW5pdGlhbGl6ZXInLCByZWNlaXZlZCAiICsgcHJvcGVydHlEZXNjLCBhcmdzLmxlbmd0aCA9PT0gMCB8fCB0eXBlb2YgcHJvcGVydHlEZXNjID09PSAnb2JqZWN0JyAmJiBwcm9wZXJ0eURlc2MgIT09IG51bGwpKTsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICAmJiBwcm9wZXJ0eURlc2MpIHsKICAgICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHByb3BlcnR5RGVzYyk7CiAgICAgICAgKGZhbHNlICYmICEoa2V5cy5sZW5ndGggPD0gMSAmJiAoa2V5c1swXSA9PT0gdW5kZWZpbmVkIHx8IGtleXNbMF0gPT09ICd2YWx1ZScgfHwga2V5c1swXSA9PT0gJ2luaXRpYWxpemVyJykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIG9wdGlvbnMgb2JqZWN0IHBhc3NlZCB0byB0cmFja2VkKCkgbWF5IG9ubHkgY29udGFpbiBhICd2YWx1ZScgb3IgJ2luaXRpYWxpemVyJyBwcm9wZXJ0eSwgbm90IGJvdGguIFJlY2VpdmVkOiBbIiArIGtleXMgKyAiXSIsIGtleXMubGVuZ3RoIDw9IDEgJiYgKGtleXNbMF0gPT09IHVuZGVmaW5lZCB8fCBrZXlzWzBdID09PSAndmFsdWUnIHx8IGtleXNbMF0gPT09ICdpbml0aWFsaXplcicpKSk7CiAgICAgICAgKGZhbHNlICYmICEoISgnaW5pdGlhbGl6ZXInIGluIHByb3BlcnR5RGVzYykgfHwgdHlwZW9mIHByb3BlcnR5RGVzYy5pbml0aWFsaXplciA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgaW5pdGlhbGl6ZXIgcGFzc2VkIHRvIHRyYWNrZWQgbXVzdCBiZSBhIGZ1bmN0aW9uLiBSZWNlaXZlZCAiICsgcHJvcGVydHlEZXNjLmluaXRpYWxpemVyLCAhKCdpbml0aWFsaXplcicgaW4gcHJvcGVydHlEZXNjKSB8fCB0eXBlb2YgcHJvcGVydHlEZXNjLmluaXRpYWxpemVyID09PSAnZnVuY3Rpb24nKSk7CiAgICAgIH0KCiAgICAgIHZhciBpbml0aWFsaXplciA9IHByb3BlcnR5RGVzYyA/IHByb3BlcnR5RGVzYy5pbml0aWFsaXplciA6IHVuZGVmaW5lZDsKICAgICAgdmFyIHZhbHVlJCQxID0gcHJvcGVydHlEZXNjID8gcHJvcGVydHlEZXNjLnZhbHVlIDogdW5kZWZpbmVkOwoKICAgICAgdmFyIGRlY29yYXRvciA9IGZ1bmN0aW9uIGRlY29yYXRvcih0YXJnZXQsIGtleSwgX2Rlc2MsIF9tZXRhLCBpc0NsYXNzaWNEZWNvcmF0b3IkJDEpIHsKICAgICAgICAoZmFsc2UgJiYgIShpc0NsYXNzaWNEZWNvcmF0b3IkJDEpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byBzZXQgYSBkZWZhdWx0IHZhbHVlIGZvciAiICsga2V5ICsgIiB3aXRoIHRoZSBAdHJhY2tlZCh7IHZhbHVlOiAnZGVmYXVsdCcgfSkgc3ludGF4LiBZb3UgY2FuIG9ubHkgdXNlIHRoaXMgc3ludGF4IHdpdGggY2xhc3NpYyBjbGFzc2VzLiBGb3IgbmF0aXZlIGNsYXNzZXMsIHlvdSBjYW4gdXNlIGNsYXNzIGluaXRpYWxpemVyczogQHRyYWNrZWQgZmllbGQgPSAnZGVmYXVsdCc7IiwgaXNDbGFzc2ljRGVjb3JhdG9yJCQxKSk7CiAgICAgICAgdmFyIGZpZWxkRGVzYyA9IHsKICAgICAgICAgIGluaXRpYWxpemVyOiBpbml0aWFsaXplciB8fCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIHJldHVybiB2YWx1ZSQkMTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHJldHVybiBkZXNjcmlwdG9yRm9yRmllbGQoW3RhcmdldCwga2V5LCBmaWVsZERlc2NdKTsKICAgICAgfTsKCiAgICAgIHNldENsYXNzaWNEZWNvcmF0b3IoZGVjb3JhdG9yKTsKICAgICAgcmV0dXJuIGRlY29yYXRvcjsKICAgIH0KCiAgICAoZmFsc2UgJiYgIShCb29sZWFuKHRydWUKICAgIC8qIEVNQkVSX05BVElWRV9ERUNPUkFUT1JfU1VQUE9SVCAqLwogICAgKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdOYXRpdmUgZGVjb3JhdG9ycyBhcmUgbm90IGVuYWJsZWQgd2l0aG91dCB0aGUgRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUIGZsYWcnLCBCb29sZWFuKHRydWUpKSk7CiAgICByZXR1cm4gZGVzY3JpcHRvckZvckZpZWxkKGFyZ3MpOwogIH0KCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIC8vIE5vcm1hbGx5IHRoaXMgaXNuJ3QgYSBjbGFzc2ljIGRlY29yYXRvciwgYnV0IHdlIHdhbnQgdG8gdGhyb3cgYSBoZWxwZnVsCiAgICAvLyBlcnJvciBpbiBkZXZlbG9wbWVudCBzbyB3ZSBuZWVkIGl0IHRvIHRyZWF0IGl0IGxpa2Ugb25lCiAgICBzZXRDbGFzc2ljRGVjb3JhdG9yKHRyYWNrZWQpOwogIH0KCiAgZnVuY3Rpb24gZGVzY3JpcHRvckZvckZpZWxkKF9yZWYpIHsKICAgIHZhciBfdGFyZ2V0ID0gX3JlZlswXSwKICAgICAgICBrZXkgPSBfcmVmWzFdLAogICAgICAgIGRlc2MgPSBfcmVmWzJdOwogICAgKGZhbHNlICYmICEoIWRlc2MgfHwgIWRlc2MudmFsdWUgJiYgIWRlc2MuZ2V0ICYmICFkZXNjLnNldCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAdHJhY2tlZCBvbiAiICsga2V5ICsgIiwgYnV0IHRoYXQgZWxlbWVudCBpcyBub3QgYSBjbGFzcyBmaWVsZC4gQHRyYWNrZWQgaXMgb25seSB1c2FibGUgb24gY2xhc3MgZmllbGRzLiBOYXRpdmUgZ2V0dGVycyBhbmQgc2V0dGVycyB3aWxsIGF1dG90cmFjayBhZGQgYW55IHRyYWNrZWQgZmllbGRzIHRoZXkgZW5jb3VudGVyLCBzbyB0aGVyZSBpcyBubyBuZWVkIG1hcmsgZ2V0dGVycyBhbmQgc2V0dGVycyB3aXRoIEB0cmFja2VkLiIsICFkZXNjIHx8ICFkZXNjLnZhbHVlICYmICFkZXNjLmdldCAmJiAhZGVzYy5zZXQpKTsKICAgIHZhciBpbml0aWFsaXplciA9IGRlc2MgPyBkZXNjLmluaXRpYWxpemVyIDogdW5kZWZpbmVkOwogICAgdmFyIHZhbHVlcyA9IG5ldyBXZWFrTWFwKCk7CiAgICB2YXIgaGFzSW5pdGlhbGl6ZXIgPSB0eXBlb2YgaW5pdGlhbGl6ZXIgPT09ICdmdW5jdGlvbic7CiAgICByZXR1cm4gewogICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBwcm9wZXJ0eVRhZyA9IHRhZ0ZvclByb3BlcnR5KHRoaXMsIGtleSk7CiAgICAgICAgaWYgKENVUlJFTlRfVFJBQ0tFUikgQ1VSUkVOVF9UUkFDS0VSLmFkZChwcm9wZXJ0eVRhZyk7CiAgICAgICAgdmFyIHZhbHVlJCQxOyAvLyBJZiB0aGUgZmllbGQgaGFzIG5ldmVyIGJlZW4gaW5pdGlhbGl6ZWQsIHdlIHNob3VsZCBpbml0aWFsaXplIGl0CgogICAgICAgIGlmIChoYXNJbml0aWFsaXplciAmJiAhdmFsdWVzLmhhcyh0aGlzKSkgewogICAgICAgICAgdmFsdWUkJDEgPSBpbml0aWFsaXplci5jYWxsKHRoaXMpOwogICAgICAgICAgdmFsdWVzLnNldCh0aGlzLCB2YWx1ZSQkMSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhbHVlJCQxID0gdmFsdWVzLmdldCh0aGlzKTsKICAgICAgICB9IC8vIEFkZCB0aGUgdGFnIG9mIHRoZSByZXR1cm5lZCB2YWx1ZSBpZiBpdCBpcyBhbiBhcnJheSwgc2luY2UgYXJyYXlzCiAgICAgICAgLy8gc2hvdWxkIGFsd2F5cyBjYXVzZSB1cGRhdGVzIGlmIHRoZXkgYXJlIGNvbnN1bWVkIGFuZCB0aGVuIGNoYW5nZWQKCgogICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlJCQxKSB8fCAoMCwgX3V0aWxzLmlzRW1iZXJBcnJheSkodmFsdWUkJDEpKSB7CiAgICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHByb3BlcnR5VGFnLCB0YWdGb3JQcm9wZXJ0eSh2YWx1ZSQkMSwgJ1tdJykpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHZhbHVlJCQxOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldChuZXdWYWx1ZSkgewogICAgICAgIG1hcmtPYmplY3RBc0RpcnR5KHRoaXMsIGtleSk7CiAgICAgICAgdmFsdWVzLnNldCh0aGlzLCBuZXdWYWx1ZSk7CgogICAgICAgIGlmIChwcm9wZXJ0eURpZENoYW5nZSAhPT0gbnVsbCkgewogICAgICAgICAgcHJvcGVydHlEaWRDaGFuZ2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CiAgfQogIC8qKgogICAgQHByaXZhdGUKICAKICAgIFdoZW5ldmVyIGEgdHJhY2tlZCBjb21wdXRlZCBwcm9wZXJ0eSBpcyBlbnRlcmVkLCB0aGUgY3VycmVudCB0cmFja2VyIGlzCiAgICBzYXZlZCBvZmYgYW5kIGEgbmV3IHRyYWNrZXIgaXMgcmVwbGFjZWQuCiAgCiAgICBBbnkgdHJhY2tlZCBwcm9wZXJ0aWVzIGNvbnN1bWVkIGFyZSBhZGRlZCB0byB0aGUgY3VycmVudCB0cmFja2VyLgogIAogICAgV2hlbiBhIHRyYWNrZWQgY29tcHV0ZWQgcHJvcGVydHkgaXMgZXhpdGVkLCB0aGUgdHJhY2tlcidzIHRhZ3MgYXJlCiAgICBjb21iaW5lZCBhbmQgYWRkZWQgdG8gdGhlIHBhcmVudCB0cmFja2VyLgogIAogICAgVGhlIGNvbnNlcXVlbmNlIGlzIHRoYXQgZWFjaCB0cmFja2VkIGNvbXB1dGVkIHByb3BlcnR5IGhhcyBhIHRhZwogICAgdGhhdCBjb3JyZXNwb25kcyB0byB0aGUgdHJhY2tlZCBwcm9wZXJ0aWVzIGNvbnN1bWVkIGluc2lkZSBvZgogICAgaXRzZWxmLCBpbmNsdWRpbmcgY2hpbGQgdHJhY2tlZCBjb21wdXRlZCBwcm9wZXJ0aWVzLgogICovCgoKICB2YXIgQ1VSUkVOVF9UUkFDS0VSID0gbnVsbDsKCiAgZnVuY3Rpb24gdHJhY2soY2FsbGJhY2spIHsKICAgIHZhciBwYXJlbnQgPSBDVVJSRU5UX1RSQUNLRVI7CiAgICB2YXIgY3VycmVudCA9IG5ldyBUcmFja2VyKCk7CiAgICBDVVJSRU5UX1RSQUNLRVIgPSBjdXJyZW50OwoKICAgIHRyeSB7CiAgICAgIGNhbGxiYWNrKCk7CiAgICB9IGZpbmFsbHkgewogICAgICBDVVJSRU5UX1RSQUNLRVIgPSBwYXJlbnQ7CiAgICB9CgogICAgcmV0dXJuIGN1cnJlbnQuY29tYmluZSgpOwogIH0KCiAgZnVuY3Rpb24gY29uc3VtZSh0YWcpIHsKICAgIGlmIChDVVJSRU5UX1RSQUNLRVIgIT09IG51bGwpIHsKICAgICAgQ1VSUkVOVF9UUkFDS0VSLmFkZCh0YWcpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gaXNUcmFja2luZygpIHsKICAgIHJldHVybiBDVVJSRU5UX1RSQUNLRVIgIT09IG51bGw7CiAgfQoKICBmdW5jdGlvbiB1bnRyYWNrKGNhbGxiYWNrKSB7CiAgICB2YXIgcGFyZW50ID0gQ1VSUkVOVF9UUkFDS0VSOwogICAgQ1VSUkVOVF9UUkFDS0VSID0gbnVsbDsKCiAgICB0cnkgewogICAgICBjYWxsYmFjaygpOwogICAgfSBmaW5hbGx5IHsKICAgICAgQ1VSUkVOVF9UUkFDS0VSID0gcGFyZW50OwogICAgfQogIH0KCiAgdmFyIHByb3BlcnR5RGlkQ2hhbmdlID0gbnVsbDsKICAvKioKICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwoKICB2YXIgUFJPWFlfQ09OVEVOVCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnUFJPWFlfQ09OVEVOVCcpOwogIF9leHBvcnRzLlBST1hZX0NPTlRFTlQgPSBQUk9YWV9DT05URU5UOwogIHZhciBnZXRQb3NzaWJsZU1hbmRhdG9yeVByb3h5VmFsdWU7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgJiYgX3V0aWxzLkhBU19OQVRJVkVfUFJPWFkpIHsKICAgIGdldFBvc3NpYmxlTWFuZGF0b3J5UHJveHlWYWx1ZSA9IGZ1bmN0aW9uIGdldFBvc3NpYmxlTWFuZGF0b3J5UHJveHlWYWx1ZShvYmosIGtleU5hbWUpIHsKICAgICAgdmFyIGNvbnRlbnQgPSBvYmpbUFJPWFlfQ09OVEVOVF07CgogICAgICBpZiAoY29udGVudCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIG9ialtrZXlOYW1lXTsKICAgICAgfSBlbHNlIHsKICAgICAgICAvKiBnbG9iYWwgUmVmbGVjdCAqLwogICAgICAgIHJldHVybiBSZWZsZWN0LmdldChjb250ZW50LCBrZXlOYW1lLCBvYmopOwogICAgICB9CiAgICB9OwogIH0gLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogIC8vIEdFVCBBTkQgU0VUCiAgLy8KICAvLyBJZiB3ZSBhcmUgb24gYSBwbGF0Zm9ybSB0aGF0IHN1cHBvcnRzIGFjY2Vzc29ycyB3ZSBjYW4gdXNlIHRob3NlLgogIC8vIE90aGVyd2lzZSBzaW11bGF0ZSBhY2Nlc3NvcnMgYnkgbG9va2luZyB1cCB0aGUgcHJvcGVydHkgZGlyZWN0bHkgb24gdGhlCiAgLy8gb2JqZWN0LgoKICAvKioKICAgIEdldHMgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgb24gYW4gb2JqZWN0LiBJZiB0aGUgcHJvcGVydHkgaXMgY29tcHV0ZWQsCiAgICB0aGUgZnVuY3Rpb24gd2lsbCBiZSBpbnZva2VkLiBJZiB0aGUgcHJvcGVydHkgaXMgbm90IGRlZmluZWQgYnV0IHRoZQogICAgb2JqZWN0IGltcGxlbWVudHMgdGhlIGB1bmtub3duUHJvcGVydHlgIG1ldGhvZCB0aGVuIHRoYXQgd2lsbCBiZSBpbnZva2VkLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZ2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBnZXQob2JqLCAibmFtZSIpOwogICAgYGBgCiAgCiAgICBJZiB5b3UgcGxhbiB0byBydW4gb24gSUU4IGFuZCBvbGRlciBicm93c2VycyB0aGVuIHlvdSBzaG91bGQgdXNlIHRoaXMKICAgIG1ldGhvZCBhbnl0aW1lIHlvdSB3YW50IHRvIHJldHJpZXZlIGEgcHJvcGVydHkgb24gYW4gb2JqZWN0IHRoYXQgeW91IGRvbid0CiAgICBrbm93IGZvciBzdXJlIGlzIHByaXZhdGUuIChQcm9wZXJ0aWVzIGJlZ2lubmluZyB3aXRoIGFuIHVuZGVyc2NvcmUgJ18nCiAgICBhcmUgY29uc2lkZXJlZCBwcml2YXRlLikKICAKICAgIE9uIGFsbCBuZXdlciBicm93c2VycywgeW91IG9ubHkgbmVlZCB0byB1c2UgdGhpcyBtZXRob2QgdG8gcmV0cmlldmUKICAgIHByb3BlcnRpZXMgaWYgdGhlIHByb3BlcnR5IG1pZ2h0IG5vdCBiZSBkZWZpbmVkIG9uIHRoZSBvYmplY3QgYW5kIHlvdSB3YW50CiAgICB0byByZXNwZWN0IHRoZSBgdW5rbm93blByb3BlcnR5YCBoYW5kbGVyLiBPdGhlcndpc2UgeW91IGNhbiBpZ25vcmUgdGhpcwogICAgbWV0aG9kLgogIAogICAgTm90ZSB0aGF0IGlmIHRoZSBvYmplY3QgaXRzZWxmIGlzIGB1bmRlZmluZWRgLCB0aGlzIG1ldGhvZCB3aWxsIHRocm93CiAgICBhbiBlcnJvci4KICAKICAgIEBtZXRob2QgZ2V0CiAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byByZXRyaWV2ZSBmcm9tLgogICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIHByb3BlcnR5IGtleSB0byByZXRyaWV2ZQogICAgQHJldHVybiB7T2JqZWN0fSB0aGUgcHJvcGVydHkgdmFsdWUgb3IgYG51bGxgLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBfZ2V0MihvYmosIGtleU5hbWUpIHsKICAgIChmYWxzZSAmJiAhKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiR2V0IG11c3QgYmUgY2FsbGVkIHdpdGggdHdvIGFyZ3VtZW50czsgYW4gb2JqZWN0IGFuZCBhIHByb3BlcnR5IGtleSIsIGFyZ3VtZW50cy5sZW5ndGggPT09IDIpKTsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gdW5kZWZpbmVkICYmIG9iaiAhPT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJDYW5ub3QgY2FsbCBnZXQgd2l0aCAnIiArIGtleU5hbWUgKyAiJyBvbiBhbiB1bmRlZmluZWQgb2JqZWN0LiIsIG9iaiAhPT0gdW5kZWZpbmVkICYmIG9iaiAhPT0gbnVsbCkpOwogICAgKGZhbHNlICYmICEodHlwZW9mIGtleU5hbWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBrZXlOYW1lID09PSAnbnVtYmVyJyAmJiAhaXNOYU4oa2V5TmFtZSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIGtleSBwcm92aWRlZCB0byBnZXQgbXVzdCBiZSBhIHN0cmluZyBvciBudW1iZXIsIHlvdSBwYXNzZWQgIiArIGtleU5hbWUsIHR5cGVvZiBrZXlOYW1lID09PSAnc3RyaW5nJyB8fCB0eXBlb2Yga2V5TmFtZSA9PT0gJ251bWJlcicgJiYgIWlzTmFOKGtleU5hbWUpKSk7CiAgICAoZmFsc2UgJiYgISh0eXBlb2Yga2V5TmFtZSAhPT0gJ3N0cmluZycgfHwga2V5TmFtZS5sYXN0SW5kZXhPZigndGhpcy4nLCAwKSAhPT0gMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCIndGhpcycgaW4gcGF0aHMgaXMgbm90IHN1cHBvcnRlZCIsIHR5cGVvZiBrZXlOYW1lICE9PSAnc3RyaW5nJyB8fCBrZXlOYW1lLmxhc3RJbmRleE9mKCd0aGlzLicsIDApICE9PSAwKSk7CiAgICB2YXIgdHlwZSA9IHR5cGVvZiBvYmo7CiAgICB2YXIgaXNPYmplY3QgPSB0eXBlID09PSAnb2JqZWN0JzsKICAgIHZhciBpc0Z1bmN0aW9uID0gdHlwZSA9PT0gJ2Z1bmN0aW9uJzsKICAgIHZhciBpc09iamVjdExpa2UgPSBpc09iamVjdCB8fCBpc0Z1bmN0aW9uOwoKICAgIGlmIChpc1BhdGgoa2V5TmFtZSkpIHsKICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSA/IF9nZXRQYXRoKG9iaiwga2V5TmFtZSkgOiB1bmRlZmluZWQ7CiAgICB9CgogICAgdmFyIHZhbHVlJCQxOwoKICAgIGlmIChpc09iamVjdExpa2UpIHsKICAgICAgdmFyIHRyYWNraW5nID0gaXNUcmFja2luZygpOwogICAgICB7CiAgICAgICAgaWYgKHRyYWNraW5nKSB7CiAgICAgICAgICBjb25zdW1lKHRhZ0ZvclByb3BlcnR5KG9iaiwga2V5TmFtZSkpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICYmIF91dGlscy5IQVNfTkFUSVZFX1BST1hZKSB7CiAgICAgICAgdmFsdWUkJDEgPSBnZXRQb3NzaWJsZU1hbmRhdG9yeVByb3h5VmFsdWUob2JqLCBrZXlOYW1lKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YWx1ZSQkMSA9IG9ialtrZXlOYW1lXTsKICAgICAgfSAvLyBBZGQgdGhlIHRhZyBvZiB0aGUgcmV0dXJuZWQgdmFsdWUgaWYgaXQgaXMgYW4gYXJyYXksIHNpbmNlIGFycmF5cwogICAgICAvLyBzaG91bGQgYWx3YXlzIGNhdXNlIHVwZGF0ZXMgaWYgdGhleSBhcmUgY29uc3VtZWQgYW5kIHRoZW4gY2hhbmdlZAoKCiAgICAgIGlmICh0cnVlCiAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICAmJiB0cmFja2luZyAmJiAoQXJyYXkuaXNBcnJheSh2YWx1ZSQkMSkgfHwgKDAsIF91dGlscy5pc0VtYmVyQXJyYXkpKHZhbHVlJCQxKSkpIHsKICAgICAgICBjb25zdW1lKHRhZ0ZvclByb3BlcnR5KHZhbHVlJCQxLCAnW10nKSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhbHVlJCQxID0gb2JqW2tleU5hbWVdOwogICAgfQoKICAgIGlmICh2YWx1ZSQkMSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmIChpc09iamVjdCAmJiAhKGtleU5hbWUgaW4gb2JqKSAmJiB0eXBlb2Ygb2JqLnVua25vd25Qcm9wZXJ0eSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIHJldHVybiBvYmoudW5rbm93blByb3BlcnR5KGtleU5hbWUpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHZhbHVlJCQxOwogIH0KCiAgZnVuY3Rpb24gX2dldFBhdGgocm9vdCwgcGF0aCkgewogICAgdmFyIG9iaiA9IHJvb3Q7CiAgICB2YXIgcGFydHMgPSB0eXBlb2YgcGF0aCA9PT0gJ3N0cmluZycgPyBwYXRoLnNwbGl0KCcuJykgOiBwYXRoOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHsKICAgICAgaWYgKG9iaiA9PT0gdW5kZWZpbmVkIHx8IG9iaiA9PT0gbnVsbCB8fCBvYmouaXNEZXN0cm95ZWQpIHsKICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgICB9CgogICAgICBvYmogPSBfZ2V0MihvYmosIHBhcnRzW2ldKTsKICAgIH0KCiAgICByZXR1cm4gb2JqOwogIH0KICAvKioKICAgIFJldHJpZXZlcyB0aGUgdmFsdWUgb2YgYSBwcm9wZXJ0eSBmcm9tIGFuIE9iamVjdCwgb3IgYSBkZWZhdWx0IHZhbHVlIGluIHRoZQogICAgY2FzZSB0aGF0IHRoZSBwcm9wZXJ0eSByZXR1cm5zIGB1bmRlZmluZWRgLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZ2V0V2l0aERlZmF1bHQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGdldFdpdGhEZWZhdWx0KHBlcnNvbiwgJ2xhc3ROYW1lJywgJ0RvZScpOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGdldFdpdGhEZWZhdWx0CiAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byByZXRyaWV2ZSBmcm9tLgogICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIHJldHJpZXZlCiAgICBAcGFyYW0ge09iamVjdH0gZGVmYXVsdFZhbHVlIFRoZSB2YWx1ZSB0byByZXR1cm4gaWYgdGhlIHByb3BlcnR5IHZhbHVlIGlzIHVuZGVmaW5lZAogICAgQHJldHVybiB7T2JqZWN0fSBUaGUgcHJvcGVydHkgdmFsdWUgb3IgdGhlIGRlZmF1bHRWYWx1ZS4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZ2V0V2l0aERlZmF1bHQocm9vdCwga2V5LCBkZWZhdWx0VmFsdWUpIHsKICAgIHZhciB2YWx1ZSQkMSA9IF9nZXQyKHJvb3QsIGtleSk7CgogICAgaWYgKHZhbHVlJCQxID09PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKICAgIH0KCiAgICByZXR1cm4gdmFsdWUkJDE7CiAgfQoKICBmdW5jdGlvbiBpc09iamVjdChvYmopIHsKICAgIHJldHVybiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiBvYmogIT09IG51bGw7CiAgfQoKICBmdW5jdGlvbiBpc1ZvbGF0aWxlKG9iaiwga2V5TmFtZSwgbWV0YSQkMSkgewogICAgdmFyIGRlc2MgPSBkZXNjcmlwdG9yRm9yUHJvcGVydHkob2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgIHJldHVybiAhKGRlc2MgIT09IHVuZGVmaW5lZCAmJiBkZXNjLl92b2xhdGlsZSA9PT0gZmFsc2UpOwogIH0KCiAgdmFyIENoYWluV2F0Y2hlcnMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDaGFpbldhdGNoZXJzKCkgewogICAgICAvLyBjaGFpbiBub2RlcyB0aGF0IHJlZmVyZW5jZSBhIGtleSBpbiB0aGlzIG9iaiBieSBrZXkKICAgICAgLy8gd2Ugb25seSBjcmVhdGUgQ2hhaW5XYXRjaGVycyB3aGVuIHdlIGFyZSBnb2luZyB0byBhZGQgdGhlbQogICAgICAvLyBzbyBjcmVhdGUgdGhpcyB1cGZyb250CiAgICAgIHRoaXMuY2hhaW5zID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNCA9IENoYWluV2F0Y2hlcnMucHJvdG90eXBlOwoKICAgIF9wcm90bzQuYWRkID0gZnVuY3Rpb24gYWRkKGtleSwgbm9kZSkgewogICAgICB2YXIgbm9kZXMgPSB0aGlzLmNoYWluc1trZXldOwoKICAgICAgaWYgKG5vZGVzID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLmNoYWluc1trZXldID0gW25vZGVdOwogICAgICB9IGVsc2UgewogICAgICAgIG5vZGVzLnB1c2gobm9kZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNC5yZW1vdmUgPSBmdW5jdGlvbiByZW1vdmUoa2V5LCBub2RlKSB7CiAgICAgIHZhciBub2RlcyA9IHRoaXMuY2hhaW5zW2tleV07CgogICAgICBpZiAobm9kZXMgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGlmIChub2Rlc1tpXSA9PT0gbm9kZSkgewogICAgICAgICAgICBub2Rlcy5zcGxpY2UoaSwgMSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG80LmhhcyA9IGZ1bmN0aW9uIGhhcyhrZXksIG5vZGUpIHsKICAgICAgdmFyIG5vZGVzID0gdGhpcy5jaGFpbnNba2V5XTsKCiAgICAgIGlmIChub2RlcyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgaWYgKG5vZGVzW2ldID09PSBub2RlKSB7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfTsKCiAgICBfcHJvdG80LnJldmFsaWRhdGVBbGwgPSBmdW5jdGlvbiByZXZhbGlkYXRlQWxsKCkgewogICAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5jaGFpbnMpIHsKICAgICAgICB0aGlzLm5vdGlmeShrZXksIHRydWUsIHVuZGVmaW5lZCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNC5yZXZhbGlkYXRlID0gZnVuY3Rpb24gcmV2YWxpZGF0ZShrZXkpIHsKICAgICAgdGhpcy5ub3RpZnkoa2V5LCB0cnVlLCB1bmRlZmluZWQpOwogICAgfSAvLyBrZXk6IHRoZSBzdHJpbmcga2V5IHRoYXQgaXMgcGFydCBvZiBhIHBhdGggY2hhbmdlZAogICAgLy8gcmV2YWxpZGF0ZTogYm9vbGVhbjsgdGhlIGNoYWlucyB0aGF0IGFyZSB3YXRjaGluZyB0aGlzIHZhbHVlIHNob3VsZCByZXZhbGlkYXRlCiAgICAvLyBjYWxsYmFjazogZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGNhbGxlZCB3aXRoIHRoZSBvYmplY3QgYW5kIHBhdGggdGhhdAogICAgLy8gICAgICAgICAgIHdpbGwgYmUvYXJlIGludmFsaWRhdGVkIGJ5IHRoaXMga2V5IGNoYW5nZSwgZGVwZW5kaW5nIG9uCiAgICAvLyAgICAgICAgICAgd2hldGhlciB0aGUgcmV2YWxpZGF0ZSBmbGFnIGlzIHBhc3NlZAogICAgOwoKICAgIF9wcm90bzQubm90aWZ5ID0gZnVuY3Rpb24gbm90aWZ5KGtleSwgcmV2YWxpZGF0ZSwgY2FsbGJhY2spIHsKICAgICAgdmFyIG5vZGVzID0gdGhpcy5jaGFpbnNba2V5XTsKCiAgICAgIGlmIChub2RlcyA9PT0gdW5kZWZpbmVkIHx8IG5vZGVzLmxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIGFmZmVjdGVkID0gdW5kZWZpbmVkOwoKICAgICAgaWYgKGNhbGxiYWNrICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBhZmZlY3RlZCA9IFtdOwogICAgICB9CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgbm9kZXNbaV0ubm90aWZ5KHJldmFsaWRhdGUsIGFmZmVjdGVkKTsKICAgICAgfQoKICAgICAgaWYgKGNhbGxiYWNrID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gLy8gd2UgZ2F0aGVyIGNhbGxiYWNrcyBzbyB3ZSBkb24ndCBub3RpZnkgdGhlbSBkdXJpbmcgcmV2YWxpZGF0aW9uCgoKICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGFmZmVjdGVkLmxlbmd0aDsgX2kgKz0gMikgewogICAgICAgIHZhciBvYmogPSBhZmZlY3RlZFtfaV07CiAgICAgICAgdmFyIHBhdGggPSBhZmZlY3RlZFtfaSArIDFdOwogICAgICAgIGNhbGxiYWNrKG9iaiwgcGF0aCk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIENoYWluV2F0Y2hlcnM7CiAgfSgpOwoKICBmdW5jdGlvbiBtYWtlQ2hhaW5XYXRjaGVyKCkgewogICAgcmV0dXJuIG5ldyBDaGFpbldhdGNoZXJzKCk7CiAgfQoKICBmdW5jdGlvbiBtYWtlQ2hhaW5Ob2RlKG9iaikgewogICAgcmV0dXJuIG5ldyBDaGFpbk5vZGUobnVsbCwgbnVsbCwgb2JqKTsKICB9CgogIGZ1bmN0aW9uIGFkZENoYWluV2F0Y2hlcihvYmosIGtleU5hbWUsIG5vZGUpIHsKICAgIHZhciBtID0gKDAsIF9tZXRhMi5tZXRhKShvYmopOwogICAgbS53cml0YWJsZUNoYWluV2F0Y2hlcnMobWFrZUNoYWluV2F0Y2hlcikuYWRkKGtleU5hbWUsIG5vZGUpOwogICAgd2F0Y2hLZXkob2JqLCBrZXlOYW1lLCBtKTsKICB9CgogIGZ1bmN0aW9uIHJlbW92ZUNoYWluV2F0Y2hlcihvYmosIGtleU5hbWUsIG5vZGUsIF9tZXRhKSB7CiAgICBpZiAoIWlzT2JqZWN0KG9iaikpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBtZXRhJCQxID0gX21ldGEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaikgOiBfbWV0YTsKCiAgICBpZiAobWV0YSQkMSA9PT0gbnVsbCB8fCBtZXRhJCQxLmlzU291cmNlRGVzdHJveWluZygpIHx8IG1ldGEkJDEuaXNNZXRhRGVzdHJveWVkKCkgfHwgbWV0YSQkMS5yZWFkYWJsZUNoYWluV2F0Y2hlcnMoKSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybjsKICAgIH0gLy8gbWFrZSBtZXRhIHdyaXRhYmxlCgoKICAgIG1ldGEkJDEgPSAoMCwgX21ldGEyLm1ldGEpKG9iaik7CiAgICBtZXRhJCQxLnJlYWRhYmxlQ2hhaW5XYXRjaGVycygpLnJlbW92ZShrZXlOYW1lLCBub2RlKTsKICAgIHVud2F0Y2hLZXkob2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICB9CgogIHZhciBOT0RFX1NUQUNLID0gW107CgogIGZ1bmN0aW9uIGRlc3Ryb3lSb290KHJvb3QpIHsKICAgIHB1c2hDaGlsZHJlbihyb290KTsKCiAgICB3aGlsZSAoTk9ERV9TVEFDSy5sZW5ndGggPiAwKSB7CiAgICAgIHZhciBub2RlID0gTk9ERV9TVEFDSy5wb3AoKTsKICAgICAgcHVzaENoaWxkcmVuKG5vZGUpOwogICAgICBkZXN0cm95T25lKG5vZGUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZGVzdHJveU9uZShub2RlKSB7CiAgICBpZiAobm9kZS5pc1dhdGNoaW5nKSB7CiAgICAgIHJlbW92ZUNoYWluV2F0Y2hlcihub2RlLm9iamVjdCwgbm9kZS5rZXksIG5vZGUpOwogICAgICBub2RlLmlzV2F0Y2hpbmcgPSBmYWxzZTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHB1c2hDaGlsZHJlbihub2RlKSB7CiAgICB2YXIgbm9kZXMgPSBub2RlLmNoYWluczsKCiAgICBpZiAobm9kZXMgIT09IHVuZGVmaW5lZCkgewogICAgICBmb3IgKHZhciBrZXkgaW4gbm9kZXMpIHsKICAgICAgICBpZiAobm9kZXNba2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBOT0RFX1NUQUNLLnB1c2gobm9kZXNba2V5XSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfSAvLyBBIENoYWluTm9kZSB3YXRjaGVzIGEgc2luZ2xlIGtleSBvbiBhbiBvYmplY3QuIElmIHlvdSBwcm92aWRlIGEgc3RhcnRpbmcKICAvLyB2YWx1ZSBmb3IgdGhlIGtleSB0aGVuIHRoZSBub2RlIHdvbid0IGFjdHVhbGx5IHdhdGNoIGl0LiBGb3IgYSByb290IG5vZGUKICAvLyBwYXNzIG51bGwgZm9yIHBhcmVudCBhbmQga2V5IGFuZCBvYmplY3QgZm9yIHZhbHVlLgoKCiAgdmFyIENoYWluTm9kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENoYWluTm9kZShwYXJlbnQsIGtleSwgdmFsdWUkJDEpIHsKICAgICAgdGhpcy5wYXRocyA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5pc1dhdGNoaW5nID0gZmFsc2U7CiAgICAgIHRoaXMuY2hhaW5zID0gdW5kZWZpbmVkOwogICAgICB0aGlzLm9iamVjdCA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5jb3VudCA9IDA7CiAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50OwogICAgICB0aGlzLmtleSA9IGtleTsKICAgICAgdGhpcy5jb250ZW50ID0gdmFsdWUkJDE7IC8vIEl0IGlzIGZhbHNlIGZvciB0aGUgcm9vdCBvZiBhIGNoYWluIChiZWNhdXNlIHdlIGhhdmUgbm8gcGFyZW50KQoKICAgICAgdmFyIGlzV2F0Y2hpbmcgPSB0aGlzLmlzV2F0Y2hpbmcgPSBwYXJlbnQgIT09IG51bGw7CgogICAgICBpZiAoaXNXYXRjaGluZykgewogICAgICAgIHZhciBwYXJlbnRWYWx1ZSA9IHBhcmVudC52YWx1ZSgpOwoKICAgICAgICBpZiAoaXNPYmplY3QocGFyZW50VmFsdWUpKSB7CiAgICAgICAgICB0aGlzLm9iamVjdCA9IHBhcmVudFZhbHVlOwogICAgICAgICAgYWRkQ2hhaW5XYXRjaGVyKHBhcmVudFZhbHVlLCBrZXksIHRoaXMpOwogICAgICAgIH0KICAgICAgfQogICAgfQoKICAgIHZhciBfcHJvdG81ID0gQ2hhaW5Ob2RlLnByb3RvdHlwZTsKCiAgICBfcHJvdG81LnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIGlmICh0aGlzLmNvbnRlbnQgPT09IHVuZGVmaW5lZCAmJiB0aGlzLmlzV2F0Y2hpbmcpIHsKICAgICAgICB2YXIgb2JqID0gdGhpcy5wYXJlbnQudmFsdWUoKTsKICAgICAgICB0aGlzLmNvbnRlbnQgPSBsYXp5R2V0KG9iaiwgdGhpcy5rZXkpOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5jb250ZW50OwogICAgfTsKCiAgICBfcHJvdG81LmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICAvLyBjaGVjayBpZiByb290CiAgICAgIGlmICh0aGlzLnBhcmVudCA9PT0gbnVsbCkgewogICAgICAgIGRlc3Ryb3lSb290KHRoaXMpOwogICAgICB9IGVsc2UgewogICAgICAgIGRlc3Ryb3lPbmUodGhpcyk7CiAgICAgIH0KICAgIH0gLy8gY29waWVzIGEgdG9wIGxldmVsIG9iamVjdCBvbmx5CiAgICA7CgogICAgX3Byb3RvNS5jb3B5VG8gPSBmdW5jdGlvbiBjb3B5VG8odGFyZ2V0KSB7CiAgICAgIHZhciBwYXRocyA9IHRoaXMucGF0aHM7CgogICAgICBpZiAocGF0aHMgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhciBwYXRoOwoKICAgICAgICBmb3IgKHBhdGggaW4gcGF0aHMpIHsKICAgICAgICAgIGlmIChwYXRoc1twYXRoXSA+IDApIHsKICAgICAgICAgICAgdGFyZ2V0LmFkZChwYXRoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0gLy8gY2FsbGVkIG9uIHRoZSByb290IG5vZGUgb2YgYSBjaGFpbiB0byBzZXR1cCB3YXRjaGVycyBvbiB0aGUgc3BlY2lmaWVkCiAgICAvLyBwYXRoLgogICAgOwoKICAgIF9wcm90bzUuYWRkID0gZnVuY3Rpb24gYWRkKHBhdGgpIHsKICAgICAgdmFyIHBhdGhzID0gdGhpcy5wYXRocyB8fCAodGhpcy5wYXRocyA9IHt9KTsKICAgICAgcGF0aHNbcGF0aF0gPSAocGF0aHNbcGF0aF0gfHwgMCkgKyAxOwogICAgICB2YXIgdGFpbHMgPSBwYXRoLnNwbGl0KCcuJyk7CiAgICAgIHRoaXMuY2hhaW4odGFpbHMuc2hpZnQoKSwgdGFpbHMpOwogICAgfSAvLyBjYWxsZWQgb24gdGhlIHJvb3Qgbm9kZSBvZiBhIGNoYWluIHRvIHRlYXJkb3duIHdhdGNoZXIgb24gdGhlIHNwZWNpZmllZAogICAgLy8gcGF0aAogICAgOwoKICAgIF9wcm90bzUucmVtb3ZlID0gZnVuY3Rpb24gcmVtb3ZlKHBhdGgpIHsKICAgICAgdmFyIHBhdGhzID0gdGhpcy5wYXRoczsKCiAgICAgIGlmIChwYXRocyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAocGF0aHNbcGF0aF0gPiAwKSB7CiAgICAgICAgcGF0aHNbcGF0aF0tLTsKICAgICAgfQoKICAgICAgdmFyIHRhaWxzID0gcGF0aC5zcGxpdCgnLicpOwogICAgICB0aGlzLnVuY2hhaW4odGFpbHMuc2hpZnQoKSwgdGFpbHMpOwogICAgfTsKCiAgICBfcHJvdG81LmNoYWluID0gZnVuY3Rpb24gY2hhaW4oa2V5LCB0YWlscykgewogICAgICB2YXIgY2hhaW5zID0gdGhpcy5jaGFpbnM7CgogICAgICBpZiAoY2hhaW5zID09PSB1bmRlZmluZWQpIHsKICAgICAgICBjaGFpbnMgPSB0aGlzLmNoYWlucyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIH0KCiAgICAgIHZhciBub2RlID0gY2hhaW5zW2tleV07CgogICAgICBpZiAobm9kZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgbm9kZSA9IGNoYWluc1trZXldID0gbmV3IENoYWluTm9kZSh0aGlzLCBrZXksIHVuZGVmaW5lZCk7CiAgICAgIH0KCiAgICAgIG5vZGUuY291bnQrKzsgLy8gY291bnQgY2hhaW5zLi4uCiAgICAgIC8vIGNoYWluIHJlc3Qgb2YgcGF0aCBpZiB0aGVyZSBpcyBvbmUKCiAgICAgIGlmICh0YWlscy5sZW5ndGggPiAwKSB7CiAgICAgICAgbm9kZS5jaGFpbih0YWlscy5zaGlmdCgpLCB0YWlscyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNS51bmNoYWluID0gZnVuY3Rpb24gdW5jaGFpbihrZXksIHRhaWxzKSB7CiAgICAgIHZhciBjaGFpbnMgPSB0aGlzLmNoYWluczsKICAgICAgdmFyIG5vZGUgPSBjaGFpbnNba2V5XTsgLy8gdW5jaGFpbiByZXN0IG9mIHBhdGggZmlyc3QuLi4KCiAgICAgIGlmICh0YWlscy5sZW5ndGggPiAwKSB7CiAgICAgICAgbm9kZS51bmNoYWluKHRhaWxzLnNoaWZ0KCksIHRhaWxzKTsKICAgICAgfSAvLyBkZWxldGUgbm9kZSBpZiBuZWVkZWQuCgoKICAgICAgbm9kZS5jb3VudC0tOwoKICAgICAgaWYgKG5vZGUuY291bnQgPD0gMCkgewogICAgICAgIGNoYWluc1tub2RlLmtleV0gPSB1bmRlZmluZWQ7CiAgICAgICAgbm9kZS5kZXN0cm95KCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNS5ub3RpZnkgPSBmdW5jdGlvbiBub3RpZnkocmV2YWxpZGF0ZSwgYWZmZWN0ZWQpIHsKICAgICAgaWYgKHJldmFsaWRhdGUgJiYgdGhpcy5pc1dhdGNoaW5nKSB7CiAgICAgICAgdmFyIHBhcmVudFZhbHVlID0gdGhpcy5wYXJlbnQudmFsdWUoKTsKCiAgICAgICAgaWYgKHBhcmVudFZhbHVlICE9PSB0aGlzLm9iamVjdCkgewogICAgICAgICAgcmVtb3ZlQ2hhaW5XYXRjaGVyKHRoaXMub2JqZWN0LCB0aGlzLmtleSwgdGhpcyk7CgogICAgICAgICAgaWYgKGlzT2JqZWN0KHBhcmVudFZhbHVlKSkgewogICAgICAgICAgICB0aGlzLm9iamVjdCA9IHBhcmVudFZhbHVlOwogICAgICAgICAgICBhZGRDaGFpbldhdGNoZXIocGFyZW50VmFsdWUsIHRoaXMua2V5LCB0aGlzKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRoaXMub2JqZWN0ID0gdW5kZWZpbmVkOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgdGhpcy5jb250ZW50ID0gdW5kZWZpbmVkOwogICAgICB9IC8vIHRoZW4gbm90aWZ5IGNoYWlucy4uLgoKCiAgICAgIHZhciBjaGFpbnMgPSB0aGlzLmNoYWluczsKCiAgICAgIGlmIChjaGFpbnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhciBub2RlOwoKICAgICAgICBmb3IgKHZhciBrZXkgaW4gY2hhaW5zKSB7CiAgICAgICAgICBub2RlID0gY2hhaW5zW2tleV07CgogICAgICAgICAgaWYgKG5vZGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBub2RlLm5vdGlmeShyZXZhbGlkYXRlLCBhZmZlY3RlZCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoYWZmZWN0ZWQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLnBhcmVudCAhPT0gbnVsbCkgewogICAgICAgIHRoaXMucGFyZW50LnBvcHVsYXRlQWZmZWN0ZWQodGhpcy5rZXksIDEsIGFmZmVjdGVkKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG81LnBvcHVsYXRlQWZmZWN0ZWQgPSBmdW5jdGlvbiBwb3B1bGF0ZUFmZmVjdGVkKHBhdGgsIGRlcHRoLCBhZmZlY3RlZCkgewogICAgICBpZiAodGhpcy5rZXkpIHsKICAgICAgICBwYXRoID0gdGhpcy5rZXkgKyAiLiIgKyBwYXRoOwogICAgICB9CgogICAgICBpZiAodGhpcy5wYXJlbnQgIT09IG51bGwpIHsKICAgICAgICB0aGlzLnBhcmVudC5wb3B1bGF0ZUFmZmVjdGVkKHBhdGgsIGRlcHRoICsgMSwgYWZmZWN0ZWQpOwogICAgICB9IGVsc2UgaWYgKGRlcHRoID4gMSkgewogICAgICAgIGFmZmVjdGVkLnB1c2godGhpcy52YWx1ZSgpLCBwYXRoKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gQ2hhaW5Ob2RlOwogIH0oKTsKCiAgX2V4cG9ydHMuQ2hhaW5Ob2RlID0gQ2hhaW5Ob2RlOwoKICBmdW5jdGlvbiBsYXp5R2V0KG9iaiwga2V5KSB7CiAgICBpZiAoIWlzT2JqZWN0KG9iaikpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkob2JqKTsgLy8gY2hlY2sgaWYgb2JqZWN0IG1lYW50IG9ubHkgdG8gYmUgYSBwcm90b3R5cGUKCiAgICBpZiAobWV0YSQkMSAhPT0gbnVsbCAmJiBtZXRhJCQxLnByb3RvID09PSBvYmopIHsKICAgICAgcmV0dXJuOwogICAgfSAvLyBVc2UgYGdldGAgaWYgdGhlIHJldHVybiB2YWx1ZSBpcyBhbiBFYWNoUHJveHkgb3IgYW4gdW5jYWNoZWFibGUgdmFsdWUuCgoKICAgIGlmIChrZXkgPT09ICdAZWFjaCcpIHsKICAgICAgcmV0dXJuIGVhY2hQcm94eUZvcihvYmopOwogICAgfSBlbHNlIGlmIChpc1ZvbGF0aWxlKG9iaiwga2V5LCBtZXRhJCQxKSkgewogICAgICByZXR1cm4gX2dldDIob2JqLCBrZXkpOyAvLyBPdGhlcndpc2UgYXR0ZW1wdCB0byBnZXQgdGhlIGNhY2hlZCB2YWx1ZSBvZiB0aGUgY29tcHV0ZWQgcHJvcGVydHkKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBnZXRDYWNoZWRWYWx1ZUZvcihvYmosIGtleSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBmaW5pc2hDaGFpbnMobWV0YSQkMSkgewogICAgLy8gZmluaXNoIGFueSBjdXJyZW50IGNoYWlucyBub2RlIHdhdGNoZXJzIHRoYXQgcmVmZXJlbmNlIG9iagogICAgdmFyIGNoYWluV2F0Y2hlcnMgPSBtZXRhJCQxLnJlYWRhYmxlQ2hhaW5XYXRjaGVycygpOwoKICAgIGlmIChjaGFpbldhdGNoZXJzICE9PSB1bmRlZmluZWQpIHsKICAgICAgY2hhaW5XYXRjaGVycy5yZXZhbGlkYXRlQWxsKCk7CiAgICB9IC8vIGVuc3VyZSB0aGF0IGlmIHdlIGhhdmUgaW5oZXJpdGVkIGFueSBjaGFpbnMgdGhleSBoYXZlIGJlZW4KICAgIC8vIGNvcGllZCBvbnRvIG91ciBvd24gbWV0YS4KCgogICAgaWYgKG1ldGEkJDEucmVhZGFibGVDaGFpbnMoKSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIG1ldGEkJDEud3JpdGFibGVDaGFpbnMobWFrZUNoYWluTm9kZSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiB3YXRjaFBhdGgob2JqLCBrZXlQYXRoLCBtZXRhJCQxKSB7CiAgICB2YXIgbSA9IG1ldGEkJDEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIubWV0YSkob2JqKSA6IG1ldGEkJDE7CiAgICB2YXIgY291bnRlciA9IG0ucGVla1dhdGNoaW5nKGtleVBhdGgpOwogICAgbS53cml0ZVdhdGNoaW5nKGtleVBhdGgsIGNvdW50ZXIgKyAxKTsKCiAgICBpZiAoY291bnRlciA9PT0gMCkgewogICAgICAvLyBhY3RpdmF0ZSB3YXRjaGluZyBmaXJzdCB0aW1lCiAgICAgIG0ud3JpdGFibGVDaGFpbnMobWFrZUNoYWluTm9kZSkuYWRkKGtleVBhdGgpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gdW53YXRjaFBhdGgob2JqLCBrZXlQYXRoLCBtZXRhJCQxKSB7CiAgICB2YXIgbSA9IG1ldGEkJDEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaikgOiBtZXRhJCQxOwoKICAgIGlmIChtID09PSBudWxsKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgY291bnRlciA9IG0ucGVla1dhdGNoaW5nKGtleVBhdGgpOwoKICAgIGlmIChjb3VudGVyID4gMCkgewogICAgICBtLndyaXRlV2F0Y2hpbmcoa2V5UGF0aCwgY291bnRlciAtIDEpOwoKICAgICAgaWYgKGNvdW50ZXIgPT09IDEpIHsKICAgICAgICBtLndyaXRhYmxlQ2hhaW5zKG1ha2VDaGFpbk5vZGUpLnJlbW92ZShrZXlQYXRoKTsKICAgICAgfQogICAgfQogIH0KICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBTdGFydHMgd2F0Y2hpbmcgYSBwcm9wZXJ0eSBvbiBhbiBvYmplY3QuIFdoZW5ldmVyIHRoZSBwcm9wZXJ0eSBjaGFuZ2VzLAogICAgaW52b2tlcyBgRW1iZXIubm90aWZ5UHJvcGVydHlDaGFuZ2VgLiBUaGlzIGlzIHRoZSBwcmltaXRpdmUgdXNlZCBieSBvYnNlcnZlcnMKICAgIGFuZCBkZXBlbmRlbnQga2V5czsgdXN1YWxseSB5b3Ugd2lsbCBuZXZlciBjYWxsIHRoaXMgbWV0aG9kIGRpcmVjdGx5IGJ1dCBpbnN0ZWFkCiAgICB1c2UgaGlnaGVyIGxldmVsIG1ldGhvZHMgbGlrZSBgYWRkT2JzZXJ2ZXIoKWAuCiAgCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCB3YXRjaAogICAgQGZvciBFbWJlcgogICAgQHBhcmFtIG9iagogICAgQHBhcmFtIHtTdHJpbmd9IGtleVBhdGgKICAgIEBwYXJhbSB7T2JqZWN0fSBtZXRhCiAgKi8KCgogIGZ1bmN0aW9uIHdhdGNoKG9iaiwga2V5UGF0aCwgbWV0YSQkMSkgewogICAgaWYgKGlzUGF0aChrZXlQYXRoKSkgewogICAgICB3YXRjaFBhdGgob2JqLCBrZXlQYXRoLCBtZXRhJCQxKTsKICAgIH0gZWxzZSB7CiAgICAgIHdhdGNoS2V5KG9iaiwga2V5UGF0aCwgbWV0YSQkMSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBpc1dhdGNoaW5nKG9iaiwga2V5KSB7CiAgICByZXR1cm4gd2F0Y2hlckNvdW50KG9iaiwga2V5KSA+IDA7CiAgfQoKICBmdW5jdGlvbiB3YXRjaGVyQ291bnQob2JqLCBrZXkpIHsKICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkob2JqKTsKICAgIHJldHVybiBtZXRhJCQxICE9PSBudWxsICYmIG1ldGEkJDEucGVla1dhdGNoaW5nKGtleSkgfHwgMDsKICB9CiAgLyoqCiAgICBTdG9wcyB3YXRjaGluZyBhIHByb3BlcnR5IG9uIGFuIG9iamVjdC4gVXN1YWxseSB5b3Ugd2lsbCBuZXZlciBjYWxsIHRoaXMgbWV0aG9kIGRpcmVjdGx5IGJ1dCBpbnN0ZWFkCiAgICB1c2UgaGlnaGVyIGxldmVsIG1ldGhvZHMgbGlrZSBgcmVtb3ZlT2JzZXJ2ZXIoKWAuCiAgCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCB1bndhdGNoCiAgICBAZm9yIEVtYmVyCiAgICBAcGFyYW0gb2JqCiAgICBAcGFyYW0ge1N0cmluZ30ga2V5UGF0aAogICAgQHBhcmFtIHtPYmplY3R9IG1ldGEKICAqLwoKCiAgZnVuY3Rpb24gdW53YXRjaChvYmosIGtleVBhdGgsIG1ldGEkJDEpIHsKICAgIGlmIChpc1BhdGgoa2V5UGF0aCkpIHsKICAgICAgdW53YXRjaFBhdGgob2JqLCBrZXlQYXRoLCBtZXRhJCQxKTsKICAgIH0gZWxzZSB7CiAgICAgIHVud2F0Y2hLZXkob2JqLCBrZXlQYXRoLCBtZXRhJCQxKTsKICAgIH0KICB9CgogIHZhciBTWU5DX0RFRkFVTFQgPSAhX2Vudmlyb25tZW50LkVOVi5fREVGQVVMVF9BU1lOQ19PQlNFUlZFUlM7CiAgdmFyIFNZTkNfT0JTRVJWRVJTID0gbmV3IE1hcCgpOwogIHZhciBBU1lOQ19PQlNFUlZFUlMgPSBuZXcgTWFwKCk7CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KCiAgLyoqCiAgICBAbWV0aG9kIGFkZE9ic2VydmVyCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3Qvb2JzZXJ2ZXJzCiAgICBAcGFyYW0gb2JqCiAgICBAcGFyYW0ge1N0cmluZ30gcGF0aAogICAgQHBhcmFtIHtPYmplY3R8RnVuY3Rpb259IHRhcmdldAogICAgQHBhcmFtIHtGdW5jdGlvbnxTdHJpbmd9IFttZXRob2RdCiAgICBAcHVibGljCiAgKi8KCiAgZnVuY3Rpb24gYWRkT2JzZXJ2ZXIob2JqLCBwYXRoLCB0YXJnZXQsIG1ldGhvZCwgc3luYykgewogICAgaWYgKHN5bmMgPT09IHZvaWQgMCkgewogICAgICBzeW5jID0gU1lOQ19ERUZBVUxUOwogICAgfQoKICAgIHZhciBldmVudE5hbWUgPSBjaGFuZ2VFdmVudChwYXRoKTsKICAgIGFkZExpc3RlbmVyKG9iaiwgZXZlbnROYW1lLCB0YXJnZXQsIG1ldGhvZCwgZmFsc2UsIHN5bmMpOwogICAgewogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaik7CgogICAgICBpZiAobWV0YSQkMSA9PT0gbnVsbCB8fCAhKG1ldGEkJDEuaXNQcm90b3R5cGVNZXRhKG9iaikgfHwgbWV0YSQkMS5pc0luaXRpYWxpemluZygpKSkgewogICAgICAgIGFjdGl2YXRlT2JzZXJ2ZXIob2JqLCBldmVudE5hbWUsIHN5bmMpOwogICAgICB9CiAgICB9CiAgfQogIC8qKgogICAgQG1ldGhvZCByZW1vdmVPYnNlcnZlcgogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L29ic2VydmVycwogICAgQHBhcmFtIG9iagogICAgQHBhcmFtIHtTdHJpbmd9IHBhdGgKICAgIEBwYXJhbSB7T2JqZWN0fEZ1bmN0aW9ufSB0YXJnZXQKICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBbbWV0aG9kXQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiByZW1vdmVPYnNlcnZlcihvYmosIHBhdGgsIHRhcmdldCwgbWV0aG9kLCBzeW5jKSB7CiAgICBpZiAoc3luYyA9PT0gdm9pZCAwKSB7CiAgICAgIHN5bmMgPSBTWU5DX0RFRkFVTFQ7CiAgICB9CgogICAgdmFyIGV2ZW50TmFtZSA9IGNoYW5nZUV2ZW50KHBhdGgpOwogICAgewogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaik7CgogICAgICBpZiAobWV0YSQkMSA9PT0gbnVsbCB8fCAhKG1ldGEkJDEuaXNQcm90b3R5cGVNZXRhKG9iaikgfHwgbWV0YSQkMS5pc0luaXRpYWxpemluZygpKSkgewogICAgICAgIGRlYWN0aXZhdGVPYnNlcnZlcihvYmosIGV2ZW50TmFtZSwgc3luYyk7CiAgICAgIH0KICAgIH0KICAgIHJlbW92ZUxpc3RlbmVyKG9iaiwgZXZlbnROYW1lLCB0YXJnZXQsIG1ldGhvZCk7CiAgfQoKICBmdW5jdGlvbiBnZXRPckNyZWF0ZUFjdGl2ZU9ic2VydmVyc0Zvcih0YXJnZXQsIHN5bmMpIHsKICAgIHZhciBvYnNlcnZlck1hcCA9IHN5bmMgPT09IHRydWUgPyBTWU5DX09CU0VSVkVSUyA6IEFTWU5DX09CU0VSVkVSUzsKCiAgICBpZiAoIW9ic2VydmVyTWFwLmhhcyh0YXJnZXQpKSB7CiAgICAgIG9ic2VydmVyTWFwLnNldCh0YXJnZXQsIG5ldyBNYXAoKSk7CiAgICB9CgogICAgcmV0dXJuIG9ic2VydmVyTWFwLmdldCh0YXJnZXQpOwogIH0KCiAgZnVuY3Rpb24gYWN0aXZhdGVPYnNlcnZlcih0YXJnZXQsIGV2ZW50TmFtZSwgc3luYykgewogICAgaWYgKHN5bmMgPT09IHZvaWQgMCkgewogICAgICBzeW5jID0gZmFsc2U7CiAgICB9CgogICAgdmFyIGFjdGl2ZU9ic2VydmVycyA9IGdldE9yQ3JlYXRlQWN0aXZlT2JzZXJ2ZXJzRm9yKHRhcmdldCwgc3luYyk7CgogICAgaWYgKGFjdGl2ZU9ic2VydmVycy5oYXMoZXZlbnROYW1lKSkgewogICAgICBhY3RpdmVPYnNlcnZlcnMuZ2V0KGV2ZW50TmFtZSkuY291bnQrKzsKICAgIH0gZWxzZSB7CiAgICAgIHZhciBfZXZlbnROYW1lJHNwbGl0ID0gZXZlbnROYW1lLnNwbGl0KCc6JyksCiAgICAgICAgICBwYXRoID0gX2V2ZW50TmFtZSRzcGxpdFswXTsKCiAgICAgIHZhciB0YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShnZXRDaGFpblRhZ3NGb3JLZXkodGFyZ2V0LCBwYXRoKSk7CiAgICAgIGFjdGl2ZU9ic2VydmVycy5zZXQoZXZlbnROYW1lLCB7CiAgICAgICAgY291bnQ6IDEsCiAgICAgICAgcGF0aDogcGF0aCwKICAgICAgICB0YWc6IHRhZywKICAgICAgICBsYXN0UmV2aXNpb246ICgwLCBfcmVmZXJlbmNlLnZhbHVlKSh0YWcpLAogICAgICAgIHN1c3BlbmRlZDogZmFsc2UKICAgICAgfSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBkZWFjdGl2YXRlT2JzZXJ2ZXIodGFyZ2V0LCBldmVudE5hbWUsIHN5bmMpIHsKICAgIGlmIChzeW5jID09PSB2b2lkIDApIHsKICAgICAgc3luYyA9IGZhbHNlOwogICAgfQoKICAgIHZhciBvYnNlcnZlck1hcCA9IHN5bmMgPT09IHRydWUgPyBTWU5DX09CU0VSVkVSUyA6IEFTWU5DX09CU0VSVkVSUzsKICAgIHZhciBhY3RpdmVPYnNlcnZlcnMgPSBvYnNlcnZlck1hcC5nZXQodGFyZ2V0KTsKCiAgICBpZiAoYWN0aXZlT2JzZXJ2ZXJzICE9PSB1bmRlZmluZWQpIHsKICAgICAgdmFyIF9vYnNlcnZlciA9IGFjdGl2ZU9ic2VydmVycy5nZXQoZXZlbnROYW1lKTsKCiAgICAgIF9vYnNlcnZlci5jb3VudC0tOwoKICAgICAgaWYgKF9vYnNlcnZlci5jb3VudCA9PT0gMCkgewogICAgICAgIGFjdGl2ZU9ic2VydmVycy5kZWxldGUoZXZlbnROYW1lKTsKCiAgICAgICAgaWYgKGFjdGl2ZU9ic2VydmVycy5zaXplID09PSAwKSB7CiAgICAgICAgICBvYnNlcnZlck1hcC5kZWxldGUodGFyZ2V0KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgLyoqCiAgICogUHJpbWFyaWx5IHVzZWQgZm9yIGNhc2VzIHdoZXJlIHdlIGFyZSByZWRlZmluaW5nIGEgY2xhc3MsIGUuZy4gbWl4aW5zL3Jlb3BlbgogICAqIGJlaW5nIGFwcGxpZWQgbGF0ZXIuIFJldmFsaWRhdGVzIGFsbCB0aGUgb2JzZXJ2ZXJzLCByZXNldHRpbmcgdGhlaXIgdGFncy4KICAgKgogICAqIEBwcml2YXRlCiAgICogQHBhcmFtIHRhcmdldAogICAqLwoKCiAgZnVuY3Rpb24gcmV2YWxpZGF0ZU9ic2VydmVycyh0YXJnZXQpIHsKICAgIGlmIChBU1lOQ19PQlNFUlZFUlMuaGFzKHRhcmdldCkpIHsKICAgICAgQVNZTkNfT0JTRVJWRVJTLmdldCh0YXJnZXQpLmZvckVhY2goZnVuY3Rpb24gKG9ic2VydmVyKSB7CiAgICAgICAgb2JzZXJ2ZXIudGFnID0gKDAsIF9yZWZlcmVuY2UuY29tYmluZSkoZ2V0Q2hhaW5UYWdzRm9yS2V5KHRhcmdldCwgb2JzZXJ2ZXIucGF0aCkpOwogICAgICAgIG9ic2VydmVyLmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlLnZhbHVlKShvYnNlcnZlci50YWcpOwogICAgICB9KTsKICAgIH0KCiAgICBpZiAoU1lOQ19PQlNFUlZFUlMuaGFzKHRhcmdldCkpIHsKICAgICAgU1lOQ19PQlNFUlZFUlMuZ2V0KHRhcmdldCkuZm9yRWFjaChmdW5jdGlvbiAob2JzZXJ2ZXIpIHsKICAgICAgICBvYnNlcnZlci50YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShnZXRDaGFpblRhZ3NGb3JLZXkodGFyZ2V0LCBvYnNlcnZlci5wYXRoKSk7CiAgICAgICAgb2JzZXJ2ZXIubGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKG9ic2VydmVyLnRhZyk7CiAgICAgIH0pOwogICAgfQogIH0KCiAgdmFyIGxhc3RLbm93blJldmlzaW9uID0gMDsKCiAgZnVuY3Rpb24gZmx1c2hBc3luY09ic2VydmVycyhzaG91bGRTY2hlZHVsZSkgewogICAgaWYgKHNob3VsZFNjaGVkdWxlID09PSB2b2lkIDApIHsKICAgICAgc2hvdWxkU2NoZWR1bGUgPSB0cnVlOwogICAgfQoKICAgIGlmIChsYXN0S25vd25SZXZpc2lvbiA9PT0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKF9yZWZlcmVuY2UuQ1VSUkVOVF9UQUcpKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBsYXN0S25vd25SZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlLnZhbHVlKShfcmVmZXJlbmNlLkNVUlJFTlRfVEFHKTsKICAgIEFTWU5DX09CU0VSVkVSUy5mb3JFYWNoKGZ1bmN0aW9uIChhY3RpdmVPYnNlcnZlcnMsIHRhcmdldCkgewogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKHRhcmdldCk7CgogICAgICBpZiAobWV0YSQkMSAmJiAobWV0YSQkMS5pc1NvdXJjZURlc3Ryb3lpbmcoKSB8fCBtZXRhJCQxLmlzTWV0YURlc3Ryb3llZCgpKSkgewogICAgICAgIEFTWU5DX09CU0VSVkVSUy5kZWxldGUodGFyZ2V0KTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGFjdGl2ZU9ic2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChvYnNlcnZlciwgZXZlbnROYW1lKSB7CiAgICAgICAgaWYgKCEoMCwgX3JlZmVyZW5jZS52YWxpZGF0ZSkob2JzZXJ2ZXIudGFnLCBvYnNlcnZlci5sYXN0UmV2aXNpb24pKSB7CiAgICAgICAgICB2YXIgc2VuZE9ic2VydmVyID0gZnVuY3Rpb24gc2VuZE9ic2VydmVyKCkgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIHNlbmRFdmVudCh0YXJnZXQsIGV2ZW50TmFtZSwgW3RhcmdldCwgb2JzZXJ2ZXIucGF0aF0pOwogICAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICAgIG9ic2VydmVyLnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKGdldENoYWluVGFnc0ZvcktleSh0YXJnZXQsIG9ic2VydmVyLnBhdGgpKTsKICAgICAgICAgICAgICBvYnNlcnZlci5sYXN0UmV2aXNpb24gPSAoMCwgX3JlZmVyZW5jZS52YWx1ZSkob2JzZXJ2ZXIudGFnKTsKICAgICAgICAgICAgfQogICAgICAgICAgfTsKCiAgICAgICAgICBpZiAoc2hvdWxkU2NoZWR1bGUpIHsKICAgICAgICAgICAgKDAsIF9ydW5sb29wLnNjaGVkdWxlKSgnYWN0aW9ucycsIHNlbmRPYnNlcnZlcik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzZW5kT2JzZXJ2ZXIoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgfSk7CiAgfQoKICBmdW5jdGlvbiBmbHVzaFN5bmNPYnNlcnZlcnMoKSB7CiAgICAvLyBXaGVuIGZsdXNoaW5nIHN5bmNocm9ub3VzIG9ic2VydmVycywgd2Uga25vdyB0aGF0IHNvbWV0aGluZyBoYXMgY2hhbmdlZCAod2UKICAgIC8vIG9ubHkgZG8gdGhpcyBkdXJpbmcgYSBub3RpZnlQcm9wZXJ0eUNoYW5nZSksIHNvIHRoZXJlJ3Mgbm8gcmVhc29uIHRvIGNoZWNrCiAgICAvLyBhIGdsb2JhbCByZXZpc2lvbi4KICAgIFNZTkNfT0JTRVJWRVJTLmZvckVhY2goZnVuY3Rpb24gKGFjdGl2ZU9ic2VydmVycywgdGFyZ2V0KSB7CiAgICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkodGFyZ2V0KTsKCiAgICAgIGlmIChtZXRhJCQxICYmIChtZXRhJCQxLmlzU291cmNlRGVzdHJveWluZygpIHx8IG1ldGEkJDEuaXNNZXRhRGVzdHJveWVkKCkpKSB7CiAgICAgICAgU1lOQ19PQlNFUlZFUlMuZGVsZXRlKHRhcmdldCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBhY3RpdmVPYnNlcnZlcnMuZm9yRWFjaChmdW5jdGlvbiAob2JzZXJ2ZXIsIGV2ZW50TmFtZSkgewogICAgICAgIGlmICghb2JzZXJ2ZXIuc3VzcGVuZGVkICYmICEoMCwgX3JlZmVyZW5jZS52YWxpZGF0ZSkob2JzZXJ2ZXIudGFnLCBvYnNlcnZlci5sYXN0UmV2aXNpb24pKSB7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBvYnNlcnZlci5zdXNwZW5kZWQgPSB0cnVlOwogICAgICAgICAgICBzZW5kRXZlbnQodGFyZ2V0LCBldmVudE5hbWUsIFt0YXJnZXQsIG9ic2VydmVyLnBhdGhdKTsKICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIG9ic2VydmVyLnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKGdldENoYWluVGFnc0ZvcktleSh0YXJnZXQsIG9ic2VydmVyLnBhdGgpKTsKICAgICAgICAgICAgb2JzZXJ2ZXIubGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKG9ic2VydmVyLnRhZyk7CiAgICAgICAgICAgIG9ic2VydmVyLnN1c3BlbmRlZCA9IGZhbHNlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHNldE9ic2VydmVyU3VzcGVuZGVkKHRhcmdldCwgcHJvcGVydHksIHN1c3BlbmRlZCkgewogICAgdmFyIGFjdGl2ZU9ic2VydmVycyA9IFNZTkNfT0JTRVJWRVJTLmdldCh0YXJnZXQpOwoKICAgIGlmICghYWN0aXZlT2JzZXJ2ZXJzKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgb2JzZXJ2ZXIgPSBhY3RpdmVPYnNlcnZlcnMuZ2V0KGNoYW5nZUV2ZW50KHByb3BlcnR5KSk7CgogICAgaWYgKG9ic2VydmVyKSB7CiAgICAgIG9ic2VydmVyLnN1c3BlbmRlZCA9IHN1c3BlbmRlZDsKICAgIH0KICB9CgogIHZhciBydW5JblRyYW5zYWN0aW9uOwogIF9leHBvcnRzLnJ1bkluVHJhbnNhY3Rpb24gPSBydW5JblRyYW5zYWN0aW9uOwogIHZhciBkaWRSZW5kZXI7CiAgX2V4cG9ydHMuZGlkUmVuZGVyID0gZGlkUmVuZGVyOwogIHZhciBhc3NlcnROb3RSZW5kZXJlZDsgLy8gZGV0ZWN0LWJhY2t0cmFja2luZy1yZXJlbmRlciBieSBkZWZhdWx0IGlzIGRlYnVnIGJ1aWxkIG9ubHkKCiAgX2V4cG9ydHMuYXNzZXJ0Tm90UmVuZGVyZWQgPSBhc3NlcnROb3RSZW5kZXJlZDsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIC8vIHRoZXJlIGFyZSAyIHN0YXRlcwogICAgLy8gREVCVUcKICAgIC8vIHRyYWNrcyBsYXN0UmVmIGFuZCBsYXN0UmVuZGVyZWRJbiBwZXIgcmVuZGVyZWQgb2JqZWN0IGFuZCBrZXkgZHVyaW5nIGEgdHJhbnNhY3Rpb24KICAgIC8vIHJlbGVhc2UgZXZlcnl0aGluZyB2aWEgbm9ybWFsIHdlYWttYXAgc2VtYW50aWNzIGJ5IGp1c3QgZGVyZWZlbmNpbmcgdGhlIHdlYWttYXAKICAgIC8vIFJFTEVBU0UKICAgIC8vIHRyYWNrcyB0cmFuc2FjdGlvbklkIHBlciByZW5kZXJlZCBvYmplY3QgYW5kIGtleSBkdXJpbmcgYSB0cmFuc2FjdGlvbgogICAgLy8gcmVsZWFzZSBldmVyeXRoaW5nIHZpYSBub3JtYWwgd2Vha21hcCBzZW1hbnRpY3MgYnkganVzdCBkZXJlZmVuY2luZyB0aGUgd2Vha21hcAogICAgdmFyIFRyYW5zYWN0aW9uUnVubmVyID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uICgpIHsKICAgICAgZnVuY3Rpb24gVHJhbnNhY3Rpb25SdW5uZXIoKSB7CiAgICAgICAgdGhpcy50cmFuc2FjdGlvbklkID0gMDsKICAgICAgICB0aGlzLmluVHJhbnNhY3Rpb24gPSBmYWxzZTsKICAgICAgICB0aGlzLnNob3VsZFJlZmx1c2ggPSBmYWxzZTsKICAgICAgICB0aGlzLndlYWtNYXAgPSBuZXcgV2Vha01hcCgpOwoKICAgICAgICBpZiAoZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICkgewogICAgICAgICAgLy8gdHJhY2sgdGVtcGxhdGVzCiAgICAgICAgICB0aGlzLmRlYnVnU3RhY2sgPSB1bmRlZmluZWQ7CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgX3Byb3RvNiA9IFRyYW5zYWN0aW9uUnVubmVyLnByb3RvdHlwZTsKCiAgICAgIF9wcm90bzYucnVuSW5UcmFuc2FjdGlvbiA9IGZ1bmN0aW9uIHJ1bkluVHJhbnNhY3Rpb24oY29udGV4dCQkMSwgbWV0aG9kTmFtZSkgewogICAgICAgIHRoaXMuYmVmb3JlKGNvbnRleHQkJDEpOwoKICAgICAgICB0cnkgewogICAgICAgICAgY29udGV4dCQkMVttZXRob2ROYW1lXSgpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICB0aGlzLmFmdGVyKCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5zaG91bGRSZWZsdXNoOwogICAgICB9OwoKICAgICAgX3Byb3RvNi5kaWRSZW5kZXIgPSBmdW5jdGlvbiBkaWRSZW5kZXIob2JqZWN0LCBrZXksIHJlZmVyZW5jZSkgewogICAgICAgIGlmICghdGhpcy5pblRyYW5zYWN0aW9uKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAoZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICkgewogICAgICAgICAgdGhpcy5zZXRLZXkob2JqZWN0LCBrZXksIHsKICAgICAgICAgICAgbGFzdFJlZjogcmVmZXJlbmNlLAogICAgICAgICAgICBsYXN0UmVuZGVyZWRJbjogdGhpcy5kZWJ1Z1N0YWNrLnBlZWsoKQogICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuc2V0S2V5KG9iamVjdCwga2V5LCB0aGlzLnRyYW5zYWN0aW9uSWQpOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIF9wcm90bzYuYXNzZXJ0Tm90UmVuZGVyZWQgPSBmdW5jdGlvbiBhc3NlcnROb3RSZW5kZXJlZChvYmplY3QsIGtleSkgewogICAgICAgIGlmICghdGhpcy5pblRyYW5zYWN0aW9uKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAodGhpcy5oYXNSZW5kZXJlZChvYmplY3QsIGtleSkpIHsKICAgICAgICAgIGlmIChmYWxzZQogICAgICAgICAgLyogREVCVUcgKi8KICAgICAgICAgICkgewogICAgICAgICAgICB2YXIgX3RoaXMkZ2V0S2V5ID0gdGhpcy5nZXRLZXkob2JqZWN0LCBrZXkpLAogICAgICAgICAgICAgICAgbGFzdFJlZiA9IF90aGlzJGdldEtleS5sYXN0UmVmLAogICAgICAgICAgICAgICAgbGFzdFJlbmRlcmVkSW4gPSBfdGhpcyRnZXRLZXkubGFzdFJlbmRlcmVkSW47CgogICAgICAgICAgICB2YXIgY3VycmVudGx5SW4gPSB0aGlzLmRlYnVnU3RhY2sucGVlaygpOwogICAgICAgICAgICB2YXIgcGFydHMgPSBbXTsKICAgICAgICAgICAgdmFyIGxhYmVsOwoKICAgICAgICAgICAgaWYgKGxhc3RSZWYgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIHdoaWxlIChsYXN0UmVmICYmIGxhc3RSZWYucHJvcGVydHlLZXkpIHsKICAgICAgICAgICAgICAgIHBhcnRzLnVuc2hpZnQobGFzdFJlZi5wcm9wZXJ0eUtleSk7CiAgICAgICAgICAgICAgICBsYXN0UmVmID0gbGFzdFJlZi5wYXJlbnRSZWZlcmVuY2U7CiAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICBsYWJlbCA9IHBhcnRzLmpvaW4oJy4nKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBsYWJlbCA9ICd0aGUgc2FtZSB2YWx1ZSc7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBtb2RpZmllZCBcIiIgKyBsYWJlbCArICJcIiB0d2ljZSBvbiAiICsgb2JqZWN0ICsgIiBpbiBhIHNpbmdsZSByZW5kZXIuIEl0IHdhcyByZW5kZXJlZCBpbiAiICsgbGFzdFJlbmRlcmVkSW4gKyAiIGFuZCBtb2RpZmllZCBpbiAiICsgY3VycmVudGx5SW4gKyAiLiBUaGlzIHdhcyB1bnJlbGlhYmxlIGFuZCBzbG93IGluIEVtYmVyIDEueCBhbmQgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZC4gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lbWJlcmpzL2VtYmVyLmpzL2lzc3Vlcy8xMzk0OCBmb3IgbW9yZSBkZXRhaWxzLiIsIGZhbHNlKSk7CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5zaG91bGRSZWZsdXNoID0gdHJ1ZTsKICAgICAgICB9CiAgICAgIH07CgogICAgICBfcHJvdG82Lmhhc1JlbmRlcmVkID0gZnVuY3Rpb24gaGFzUmVuZGVyZWQob2JqZWN0LCBrZXkpIHsKICAgICAgICBpZiAoIXRoaXMuaW5UcmFuc2FjdGlvbikgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgIHJldHVybiB0aGlzLmdldEtleShvYmplY3QsIGtleSkgIT09IHVuZGVmaW5lZDsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLmdldEtleShvYmplY3QsIGtleSkgPT09IHRoaXMudHJhbnNhY3Rpb25JZDsKICAgICAgfTsKCiAgICAgIF9wcm90bzYuYmVmb3JlID0gZnVuY3Rpb24gYmVmb3JlKGNvbnRleHQkJDEpIHsKICAgICAgICB0aGlzLmluVHJhbnNhY3Rpb24gPSB0cnVlOwogICAgICAgIHRoaXMuc2hvdWxkUmVmbHVzaCA9IGZhbHNlOwoKICAgICAgICBpZiAoZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICkgewogICAgICAgICAgdGhpcy5kZWJ1Z1N0YWNrID0gY29udGV4dCQkMS5lbnYuZGVidWdTdGFjazsKICAgICAgICB9CiAgICAgIH07CgogICAgICBfcHJvdG82LmFmdGVyID0gZnVuY3Rpb24gYWZ0ZXIoKSB7CiAgICAgICAgdGhpcy50cmFuc2FjdGlvbklkKys7CiAgICAgICAgdGhpcy5pblRyYW5zYWN0aW9uID0gZmFsc2U7CgogICAgICAgIGlmIChmYWxzZQogICAgICAgIC8qIERFQlVHICovCiAgICAgICAgKSB7CiAgICAgICAgICB0aGlzLmRlYnVnU3RhY2sgPSB1bmRlZmluZWQ7CiAgICAgICAgfQoKICAgICAgICB0aGlzLmNsZWFyT2JqZWN0TWFwKCk7CiAgICAgIH07CgogICAgICBfcHJvdG82LmNyZWF0ZU1hcCA9IGZ1bmN0aW9uIGNyZWF0ZU1hcChvYmplY3QpIHsKICAgICAgICB2YXIgbWFwID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICB0aGlzLndlYWtNYXAuc2V0KG9iamVjdCwgbWFwKTsKICAgICAgICByZXR1cm4gbWFwOwogICAgICB9OwoKICAgICAgX3Byb3RvNi5nZXRPckNyZWF0ZU1hcCA9IGZ1bmN0aW9uIGdldE9yQ3JlYXRlTWFwKG9iamVjdCkgewogICAgICAgIHZhciBtYXAgPSB0aGlzLndlYWtNYXAuZ2V0KG9iamVjdCk7CgogICAgICAgIGlmIChtYXAgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgbWFwID0gdGhpcy5jcmVhdGVNYXAob2JqZWN0KTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBtYXA7CiAgICAgIH07CgogICAgICBfcHJvdG82LnNldEtleSA9IGZ1bmN0aW9uIHNldEtleShvYmplY3QsIGtleSwgdmFsdWUkJDEpIHsKICAgICAgICB2YXIgbWFwID0gdGhpcy5nZXRPckNyZWF0ZU1hcChvYmplY3QpOwogICAgICAgIG1hcFtrZXldID0gdmFsdWUkJDE7CiAgICAgIH07CgogICAgICBfcHJvdG82LmdldEtleSA9IGZ1bmN0aW9uIGdldEtleShvYmplY3QsIGtleSkgewogICAgICAgIHZhciBtYXAgPSB0aGlzLndlYWtNYXAuZ2V0KG9iamVjdCk7CgogICAgICAgIGlmIChtYXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcmV0dXJuIG1hcFtrZXldOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIF9wcm90bzYuY2xlYXJPYmplY3RNYXAgPSBmdW5jdGlvbiBjbGVhck9iamVjdE1hcCgpIHsKICAgICAgICB0aGlzLndlYWtNYXAgPSBuZXcgV2Vha01hcCgpOwogICAgICB9OwoKICAgICAgcmV0dXJuIFRyYW5zYWN0aW9uUnVubmVyOwogICAgfSgpOwoKICAgIHZhciBydW5uZXIgPSBuZXcgVHJhbnNhY3Rpb25SdW5uZXIoKTsKCiAgICBfZXhwb3J0cy5ydW5JblRyYW5zYWN0aW9uID0gcnVuSW5UcmFuc2FjdGlvbiA9IGZ1bmN0aW9uIHJ1bkluVHJhbnNhY3Rpb24oKSB7CiAgICAgIHJldHVybiBydW5uZXIucnVuSW5UcmFuc2FjdGlvbi5hcHBseShydW5uZXIsIGFyZ3VtZW50cyk7CiAgICB9OwoKICAgIF9leHBvcnRzLmRpZFJlbmRlciA9IGRpZFJlbmRlciA9IGZ1bmN0aW9uIGRpZFJlbmRlcigpIHsKICAgICAgcmV0dXJuIHJ1bm5lci5kaWRSZW5kZXIuYXBwbHkocnVubmVyLCBhcmd1bWVudHMpOwogICAgfTsKCiAgICBfZXhwb3J0cy5hc3NlcnROb3RSZW5kZXJlZCA9IGFzc2VydE5vdFJlbmRlcmVkID0gZnVuY3Rpb24gYXNzZXJ0Tm90UmVuZGVyZWQoKSB7CiAgICAgIHJldHVybiBydW5uZXIuYXNzZXJ0Tm90UmVuZGVyZWQuYXBwbHkocnVubmVyLCBhcmd1bWVudHMpOwogICAgfTsKICB9IGVsc2UgewogICAgLy8gaW4gcHJvZHVjdGlvbiBkbyBub3RoaW5nIHRvIGRldGVjdCByZWZsdXNoZXMKICAgIF9leHBvcnRzLnJ1bkluVHJhbnNhY3Rpb24gPSBydW5JblRyYW5zYWN0aW9uID0gZnVuY3Rpb24gcnVuSW5UcmFuc2FjdGlvbihjb250ZXh0JCQxLCBtZXRob2ROYW1lKSB7CiAgICAgIGNvbnRleHQkJDFbbWV0aG9kTmFtZV0oKTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfTsKICB9CiAgLyoqCiAgIEBtb2R1bGUgZW1iZXIKICAgQHByaXZhdGUKICAgKi8KCgogIHZhciBQUk9QRVJUWV9ESURfQ0hBTkdFID0gKDAsIF91dGlscy5zeW1ib2wpKCdQUk9QRVJUWV9ESURfQ0hBTkdFJyk7CiAgX2V4cG9ydHMuUFJPUEVSVFlfRElEX0NIQU5HRSA9IFBST1BFUlRZX0RJRF9DSEFOR0U7CiAgdmFyIGRlZmVycmVkID0gMDsKICAvKioKICAgIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGp1c3QgYWZ0ZXIgYW4gb2JqZWN0IHByb3BlcnR5IGhhcyBjaGFuZ2VkLgogICAgSXQgd2lsbCBub3RpZnkgYW55IG9ic2VydmVycyBhbmQgY2xlYXIgY2FjaGVzIGFtb25nIG90aGVyIHRoaW5ncy4KICAKICAgIE5vcm1hbGx5IHlvdSB3aWxsIG5vdCBuZWVkIHRvIGNhbGwgdGhpcyBtZXRob2QgZGlyZWN0bHkgYnV0IGlmIGZvciBzb21lCiAgICByZWFzb24geW91IGNhbid0IGRpcmVjdGx5IHdhdGNoIGEgcHJvcGVydHkgeW91IGNhbiBpbnZva2UgdGhpcyBtZXRob2QKICAgIG1hbnVhbGx5LgogIAogICAgQG1ldGhvZCBub3RpZnlQcm9wZXJ0eUNoYW5nZQogICAgQGZvciBAZW1iZXIvb2JqZWN0CiAgICBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3Qgd2l0aCB0aGUgcHJvcGVydHkgdGhhdCB3aWxsIGNoYW5nZQogICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIHByb3BlcnR5IGtleSAob3IgcGF0aCkgdGhhdCB3aWxsIGNoYW5nZS4KICAgIEBwYXJhbSB7TWV0YX0gbWV0YSBUaGUgb2JqZWN0cyBtZXRhLgogICAgQHJldHVybiB7dm9pZH0KICAgIEBzaW5jZSAzLjEuMAogICAgQHB1YmxpYwogICovCgogIGZ1bmN0aW9uIG5vdGlmeVByb3BlcnR5Q2hhbmdlKG9iaiwga2V5TmFtZSwgX21ldGEpIHsKICAgIHZhciBtZXRhJCQxID0gX21ldGEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaikgOiBfbWV0YTsKCiAgICBpZiAobWV0YSQkMSAhPT0gbnVsbCAmJiAobWV0YSQkMS5pc0luaXRpYWxpemluZygpIHx8IG1ldGEkJDEuaXNQcm90b3R5cGVNZXRhKG9iaikpKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAobWV0YSQkMSAhPT0gbnVsbCkgewogICAgICBtYXJrT2JqZWN0QXNEaXJ0eShvYmosIGtleU5hbWUsIG1ldGEkJDEpOwogICAgfQoKICAgIGlmICh0cnVlCiAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICYmIGRlZmVycmVkIDw9IDApIHsKICAgICAgZmx1c2hTeW5jT2JzZXJ2ZXJzKCk7CiAgICB9CgogICAgaWYgKFBST1BFUlRZX0RJRF9DSEFOR0UgaW4gb2JqKSB7CiAgICAgIG9ialtQUk9QRVJUWV9ESURfQ0hBTkdFXShrZXlOYW1lKTsKICAgIH0KCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgYXNzZXJ0Tm90UmVuZGVyZWQob2JqLCBrZXlOYW1lKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIG92ZXJyaWRlQ2hhaW5zKF9vYmosIGtleU5hbWUsIG1ldGEkJDEpIHsKICAgIHZhciBjaGFpbldhdGNoZXJzID0gbWV0YSQkMS5yZWFkYWJsZUNoYWluV2F0Y2hlcnMoKTsKCiAgICBpZiAoY2hhaW5XYXRjaGVycyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGNoYWluV2F0Y2hlcnMucmV2YWxpZGF0ZShrZXlOYW1lKTsKICAgIH0KICB9CiAgLyoqCiAgICBAbWV0aG9kIGJlZ2luUHJvcGVydHlDaGFuZ2VzCiAgICBAY2hhaW5hYmxlCiAgICBAcHJpdmF0ZQogICovCgoKICBmdW5jdGlvbiBiZWdpblByb3BlcnR5Q2hhbmdlcygpIHsKICAgIGRlZmVycmVkKys7CiAgfQogIC8qKgogICAgQG1ldGhvZCBlbmRQcm9wZXJ0eUNoYW5nZXMKICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIGVuZFByb3BlcnR5Q2hhbmdlcygpIHsKICAgIGRlZmVycmVkLS07CgogICAgaWYgKGRlZmVycmVkIDw9IDApIHsKICAgICAgewogICAgICAgIGZsdXNoU3luY09ic2VydmVycygpOwogICAgICB9CiAgICB9CiAgfQogIC8qKgogICAgTWFrZSBhIHNlcmllcyBvZiBwcm9wZXJ0eSBjaGFuZ2VzIHRvZ2V0aGVyIGluIGFuCiAgICBleGNlcHRpb24tc2FmZSB3YXkuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBFbWJlci5jaGFuZ2VQcm9wZXJ0aWVzKGZ1bmN0aW9uKCkgewogICAgICBvYmoxLnNldCgnZm9vJywgbWF5Qmxvd1VwV2hlblNldCk7CiAgICAgIG9iajIuc2V0KCdiYXInLCBiYXopOwogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgY2hhbmdlUHJvcGVydGllcwogICAgQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sKICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIGNoYW5nZVByb3BlcnRpZXMoY2FsbGJhY2spIHsKICAgIGJlZ2luUHJvcGVydHlDaGFuZ2VzKCk7CgogICAgdHJ5IHsKICAgICAgY2FsbGJhY2soKTsKICAgIH0gZmluYWxseSB7CiAgICAgIGVuZFByb3BlcnR5Q2hhbmdlcygpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gYXJyYXlDb250ZW50V2lsbENoYW5nZShhcnJheSwgc3RhcnRJZHgsIHJlbW92ZUFtdCwgYWRkQW10KSB7CiAgICAvLyBpZiBubyBhcmdzIGFyZSBwYXNzZWQgYXNzdW1lIGV2ZXJ5dGhpbmcgY2hhbmdlcwogICAgaWYgKHN0YXJ0SWR4ID09PSB1bmRlZmluZWQpIHsKICAgICAgc3RhcnRJZHggPSAwOwogICAgICByZW1vdmVBbXQgPSBhZGRBbXQgPSAtMTsKICAgIH0gZWxzZSB7CiAgICAgIGlmIChyZW1vdmVBbXQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJlbW92ZUFtdCA9IC0xOwogICAgICB9CgogICAgICBpZiAoYWRkQW10ID09PSB1bmRlZmluZWQpIHsKICAgICAgICBhZGRBbXQgPSAtMTsKICAgICAgfQogICAgfQoKICAgIHNlbmRFdmVudChhcnJheSwgJ0BhcnJheTpiZWZvcmUnLCBbYXJyYXksIHN0YXJ0SWR4LCByZW1vdmVBbXQsIGFkZEFtdF0pOwogICAgcmV0dXJuIGFycmF5OwogIH0KCiAgZnVuY3Rpb24gYXJyYXlDb250ZW50RGlkQ2hhbmdlKGFycmF5LCBzdGFydElkeCwgcmVtb3ZlQW10LCBhZGRBbXQpIHsKICAgIC8vIGlmIG5vIGFyZ3MgYXJlIHBhc3NlZCBhc3N1bWUgZXZlcnl0aGluZyBjaGFuZ2VzCiAgICBpZiAoc3RhcnRJZHggPT09IHVuZGVmaW5lZCkgewogICAgICBzdGFydElkeCA9IDA7CiAgICAgIHJlbW92ZUFtdCA9IGFkZEFtdCA9IC0xOwogICAgfSBlbHNlIHsKICAgICAgaWYgKHJlbW92ZUFtdCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmVtb3ZlQW10ID0gLTE7CiAgICAgIH0KCiAgICAgIGlmIChhZGRBbXQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGFkZEFtdCA9IC0xOwogICAgICB9CiAgICB9CgogICAgdmFyIG1ldGEkJDEgPSAoMCwgX21ldGEyLnBlZWtNZXRhKShhcnJheSk7CgogICAgaWYgKGFkZEFtdCA8IDAgfHwgcmVtb3ZlQW10IDwgMCB8fCBhZGRBbXQgLSByZW1vdmVBbXQgIT09IDApIHsKICAgICAgbm90aWZ5UHJvcGVydHlDaGFuZ2UoYXJyYXksICdsZW5ndGgnLCBtZXRhJCQxKTsKICAgIH0KCiAgICBub3RpZnlQcm9wZXJ0eUNoYW5nZShhcnJheSwgJ1tdJywgbWV0YSQkMSk7CiAgICBzZW5kRXZlbnQoYXJyYXksICdAYXJyYXk6Y2hhbmdlJywgW2FycmF5LCBzdGFydElkeCwgcmVtb3ZlQW10LCBhZGRBbXRdKTsKICAgIHZhciBjYWNoZSA9IHBlZWtDYWNoZUZvcihhcnJheSk7CgogICAgaWYgKGNhY2hlICE9PSB1bmRlZmluZWQpIHsKICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDsKICAgICAgdmFyIGFkZGVkQW1vdW50ID0gYWRkQW10ID09PSAtMSA/IDAgOiBhZGRBbXQ7CiAgICAgIHZhciByZW1vdmVkQW1vdW50ID0gcmVtb3ZlQW10ID09PSAtMSA/IDAgOiByZW1vdmVBbXQ7CiAgICAgIHZhciBkZWx0YSA9IGFkZGVkQW1vdW50IC0gcmVtb3ZlZEFtb3VudDsKICAgICAgdmFyIHByZXZpb3VzTGVuZ3RoID0gbGVuZ3RoIC0gZGVsdGE7CiAgICAgIHZhciBub3JtYWxTdGFydElkeCA9IHN0YXJ0SWR4IDwgMCA/IHByZXZpb3VzTGVuZ3RoICsgc3RhcnRJZHggOiBzdGFydElkeDsKCiAgICAgIGlmIChjYWNoZS5oYXMoJ2ZpcnN0T2JqZWN0JykgJiYgbm9ybWFsU3RhcnRJZHggPT09IDApIHsKICAgICAgICBub3RpZnlQcm9wZXJ0eUNoYW5nZShhcnJheSwgJ2ZpcnN0T2JqZWN0JywgbWV0YSQkMSk7CiAgICAgIH0KCiAgICAgIGlmIChjYWNoZS5oYXMoJ2xhc3RPYmplY3QnKSkgewogICAgICAgIHZhciBwcmV2aW91c0xhc3RJbmRleCA9IHByZXZpb3VzTGVuZ3RoIC0gMTsKICAgICAgICB2YXIgbGFzdEFmZmVjdGVkSW5kZXggPSBub3JtYWxTdGFydElkeCArIHJlbW92ZWRBbW91bnQ7CgogICAgICAgIGlmIChwcmV2aW91c0xhc3RJbmRleCA8IGxhc3RBZmZlY3RlZEluZGV4KSB7CiAgICAgICAgICBub3RpZnlQcm9wZXJ0eUNoYW5nZShhcnJheSwgJ2xhc3RPYmplY3QnLCBtZXRhJCQxKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gYXJyYXk7CiAgfQoKICB2YXIgRU1QVFlfQVJSQVkgPSBPYmplY3QuZnJlZXplKFtdKTsKCiAgZnVuY3Rpb24gb2JqZWN0QXQoYXJyYXksIGluZGV4KSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheShhcnJheSkpIHsKICAgICAgcmV0dXJuIGFycmF5W2luZGV4XTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBhcnJheS5vYmplY3RBdChpbmRleCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiByZXBsYWNlKGFycmF5LCBzdGFydCwgZGVsZXRlQ291bnQsIGl0ZW1zKSB7CiAgICBpZiAoaXRlbXMgPT09IHZvaWQgMCkgewogICAgICBpdGVtcyA9IEVNUFRZX0FSUkFZOwogICAgfQoKICAgIGlmIChBcnJheS5pc0FycmF5KGFycmF5KSkgewogICAgICByZXBsYWNlSW5OYXRpdmVBcnJheShhcnJheSwgc3RhcnQsIGRlbGV0ZUNvdW50LCBpdGVtcyk7CiAgICB9IGVsc2UgewogICAgICBhcnJheS5yZXBsYWNlKHN0YXJ0LCBkZWxldGVDb3VudCwgaXRlbXMpOwogICAgfQogIH0KCiAgdmFyIENIVU5LX1NJWkUgPSA2MDAwMDsgLy8gVG8gYXZvaWQgb3ZlcmZsb3dpbmcgdGhlIHN0YWNrLCB3ZSBzcGxpY2UgdXAgdG8gQ0hVTktfU0laRSBpdGVtcyBhdCBhIHRpbWUuCiAgLy8gU2VlIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD01NjU4OCBmb3IgbW9yZSBkZXRhaWxzLgoKICBmdW5jdGlvbiByZXBsYWNlSW5OYXRpdmVBcnJheShhcnJheSwgc3RhcnQsIGRlbGV0ZUNvdW50LCBpdGVtcykgewogICAgYXJyYXlDb250ZW50V2lsbENoYW5nZShhcnJheSwgc3RhcnQsIGRlbGV0ZUNvdW50LCBpdGVtcy5sZW5ndGgpOwoKICAgIGlmIChpdGVtcy5sZW5ndGggPD0gQ0hVTktfU0laRSkgewogICAgICBhcnJheS5zcGxpY2UuYXBwbHkoYXJyYXksIFtzdGFydCwgZGVsZXRlQ291bnRdLmNvbmNhdChpdGVtcykpOwogICAgfSBlbHNlIHsKICAgICAgYXJyYXkuc3BsaWNlKHN0YXJ0LCBkZWxldGVDb3VudCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgaSArPSBDSFVOS19TSVpFKSB7CiAgICAgICAgdmFyIGNodW5rID0gaXRlbXMuc2xpY2UoaSwgaSArIENIVU5LX1NJWkUpOwogICAgICAgIGFycmF5LnNwbGljZS5hcHBseShhcnJheSwgW3N0YXJ0ICsgaSwgMF0uY29uY2F0KGNodW5rKSk7CiAgICAgIH0KICAgIH0KCiAgICBhcnJheUNvbnRlbnREaWRDaGFuZ2UoYXJyYXksIHN0YXJ0LCBkZWxldGVDb3VudCwgaXRlbXMubGVuZ3RoKTsKICB9CgogIGZ1bmN0aW9uIGFycmF5T2JzZXJ2ZXJzSGVscGVyKG9iaiwgdGFyZ2V0LCBvcHRzLCBvcGVyYXRpb24sIG5vdGlmeSkgewogICAgdmFyIHdpbGxDaGFuZ2UgPSBvcHRzICYmIG9wdHMud2lsbENoYW5nZSB8fCAnYXJyYXlXaWxsQ2hhbmdlJzsKICAgIHZhciBkaWRDaGFuZ2UgPSBvcHRzICYmIG9wdHMuZGlkQ2hhbmdlIHx8ICdhcnJheURpZENoYW5nZSc7CgogICAgdmFyIGhhc09ic2VydmVycyA9IF9nZXQyKG9iaiwgJ2hhc0FycmF5T2JzZXJ2ZXJzJyk7CgogICAgb3BlcmF0aW9uKG9iaiwgJ0BhcnJheTpiZWZvcmUnLCB0YXJnZXQsIHdpbGxDaGFuZ2UpOwogICAgb3BlcmF0aW9uKG9iaiwgJ0BhcnJheTpjaGFuZ2UnLCB0YXJnZXQsIGRpZENoYW5nZSk7CgogICAgaWYgKGhhc09ic2VydmVycyA9PT0gbm90aWZ5KSB7CiAgICAgIG5vdGlmeVByb3BlcnR5Q2hhbmdlKG9iaiwgJ2hhc0FycmF5T2JzZXJ2ZXJzJyk7CiAgICB9CgogICAgcmV0dXJuIG9iajsKICB9CgogIGZ1bmN0aW9uIGFkZEFycmF5T2JzZXJ2ZXIoYXJyYXksIHRhcmdldCwgb3B0cykgewogICAgcmV0dXJuIGFycmF5T2JzZXJ2ZXJzSGVscGVyKGFycmF5LCB0YXJnZXQsIG9wdHMsIGFkZExpc3RlbmVyLCBmYWxzZSk7CiAgfQoKICBmdW5jdGlvbiByZW1vdmVBcnJheU9ic2VydmVyKGFycmF5LCB0YXJnZXQsIG9wdHMpIHsKICAgIHJldHVybiBhcnJheU9ic2VydmVyc0hlbHBlcihhcnJheSwgdGFyZ2V0LCBvcHRzLCByZW1vdmVMaXN0ZW5lciwgdHJ1ZSk7CiAgfQoKICB2YXIgQVJHU19QUk9YWV9UQUdTID0gbmV3IFdlYWtNYXAoKTsKICBfZXhwb3J0cy5BUkdTX1BST1hZX1RBR1MgPSBBUkdTX1BST1hZX1RBR1M7CgogIGZ1bmN0aW9uIGZpbmlzaExhenlDaGFpbnMob2JqLCBrZXksIHZhbHVlJCQxKSB7CiAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaik7CiAgICB2YXIgbGF6eVRhZ3MgPSBtZXRhJCQxICE9PSBudWxsID8gbWV0YSQkMS5yZWFkYWJsZUxhenlDaGFpbnNGb3Ioa2V5KSA6IHVuZGVmaW5lZDsKCiAgICBpZiAobGF6eVRhZ3MgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKHZhbHVlJCQxID09PSBudWxsIHx8IHR5cGVvZiB2YWx1ZSQkMSAhPT0gJ29iamVjdCcgJiYgdHlwZW9mIHZhbHVlJCQxICE9PSAnZnVuY3Rpb24nKSB7CiAgICAgIGZvciAodmFyIHBhdGggaW4gbGF6eVRhZ3MpIHsKICAgICAgICBkZWxldGUgbGF6eVRhZ3NbcGF0aF07CiAgICAgIH0KCiAgICAgIHJldHVybjsKICAgIH0KCiAgICBmb3IgKHZhciBfcGF0aCBpbiBsYXp5VGFncykgewogICAgICB2YXIgdGFnID0gbGF6eVRhZ3NbX3BhdGhdOwogICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHRhZywgKDAsIF9yZWZlcmVuY2UuY29tYmluZSkoZ2V0Q2hhaW5UYWdzRm9yS2V5KHZhbHVlJCQxLCBfcGF0aCkpKTsKICAgICAgZGVsZXRlIGxhenlUYWdzW19wYXRoXTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGdldENoYWluVGFnc0ZvcktleXMob2JqLCBrZXlzKSB7CiAgICB2YXIgY2hhaW5UYWdzID0gW107CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgIGNoYWluVGFncy5wdXNoLmFwcGx5KGNoYWluVGFncywgZ2V0Q2hhaW5UYWdzRm9yS2V5KG9iaiwga2V5c1tpXSkpOwogICAgfQoKICAgIHJldHVybiBjaGFpblRhZ3M7CiAgfQoKICBmdW5jdGlvbiBnZXRDaGFpblRhZ3NGb3JLZXkob2JqLCBwYXRoKSB7CiAgICB2YXIgY2hhaW5UYWdzID0gW107CiAgICB2YXIgY3VycmVudCA9IG9iajsKICAgIHZhciBwYXRoTGVuZ3RoID0gcGF0aC5sZW5ndGg7CiAgICB2YXIgc2VnbWVudEVuZCA9IC0xOyAvLyBwcmV2ZW50IGNsb3N1cmVzCgogICAgdmFyIHNlZ21lbnQsIGRlc2NyaXB0b3I7IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zdGFudC1jb25kaXRpb24KCiAgICB3aGlsZSAodHJ1ZSkgewogICAgICB2YXIgY3VycmVudFR5cGUgPSB0eXBlb2YgY3VycmVudDsKCiAgICAgIGlmIChjdXJyZW50ID09PSBudWxsIHx8IGN1cnJlbnRUeXBlICE9PSAnb2JqZWN0JyAmJiBjdXJyZW50VHlwZSAhPT0gJ2Z1bmN0aW9uJykgewogICAgICAgIC8vIHdlJ3ZlIGhpdCB0aGUgZW5kIG9mIHRoZSBjaGFpbiBmb3Igbm93LCBicmVhayBvdXQKICAgICAgICBicmVhazsKICAgICAgfQoKICAgICAgdmFyIGxhc3RTZWdtZW50RW5kID0gc2VnbWVudEVuZCArIDE7CiAgICAgIHNlZ21lbnRFbmQgPSBwYXRoLmluZGV4T2YoJy4nLCBsYXN0U2VnbWVudEVuZCk7CgogICAgICBpZiAoc2VnbWVudEVuZCA9PT0gLTEpIHsKICAgICAgICBzZWdtZW50RW5kID0gcGF0aExlbmd0aDsKICAgICAgfQoKICAgICAgc2VnbWVudCA9IHBhdGguc2xpY2UobGFzdFNlZ21lbnRFbmQsIHNlZ21lbnRFbmQpOyAvLyBJZiB0aGUgc2VnbWVudCBpcyBhbiBAZWFjaCwgd2UgY2FuIHByb2Nlc3MgaXQgYW5kIHRoZW4gYnJlYWsKCiAgICAgIGlmIChzZWdtZW50ID09PSAnQGVhY2gnICYmIHNlZ21lbnRFbmQgIT09IHBhdGhMZW5ndGgpIHsKICAgICAgICBsYXN0U2VnbWVudEVuZCA9IHNlZ21lbnRFbmQgKyAxOwogICAgICAgIHNlZ21lbnRFbmQgPSBwYXRoLmluZGV4T2YoJy4nLCBsYXN0U2VnbWVudEVuZCk7IC8vIFRoZXJlIHNob3VsZCBiZSBleGFjdGx5IG9uZSBzZWdtZW50IGFmdGVyIGFuIGBAZWFjaGAgKGkuZS4gYEBlYWNoLmZvb2AsIG5vdCBgQGVhY2guZm9vLmJhcmApCgogICAgICAgIChmYWxzZSAmJiAhKHNlZ21lbnRFbmQgPT09IC0xKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIldoZW4gdXNpbmcgQGVhY2ggaW4gYSBkZXBlbmRlbnQta2V5IG9yIGFuIG9ic2VydmVyLCAiICsgInlvdSBjYW4gb25seSBjaGFpbiBvbmUgcHJvcGVydHkgbGV2ZWwgZGVlcCBhZnRlciAiICsgKCJ0aGUgQGVhY2guIFRoYXQgaXMsIGAiICsgcGF0aC5zbGljZSgwLCBzZWdtZW50RW5kKSArICJgICIpICsgKCJpcyBhbGxvd2VkIGJ1dCBgIiArIHBhdGggKyAiYCAod2hpY2ggaXMgd2hhdCB5b3UgcGFzc2VkKSAiKSArICJpcyBub3QuXG5cbiIgKyAiVGhpcyB3YXMgbmV2ZXIgc3VwcG9ydGVkLiBDdXJyZW50bHksIHRoZSBleHRyYSBzZWdtZW50cyAiICsgKCJhcmUgc2lsZW50bHkgaWdub3JlZCwgaS5lLiBgIiArIHBhdGggKyAiYCBiZWhhdmVzIGV4YWN0bHkgIikgKyAoInRoZSBzYW1lIGFzIGAiICsgcGF0aC5zbGljZSgwLCBzZWdtZW50RW5kKSArICJgLiAiKSArICJJbiB0aGUgZnV0dXJlLCB0aGlzIHdpbGwgdGhyb3cgYW4gZXJyb3IuXG5cbiIgKyAiSWYgdGhlIGN1cnJlbnQgYmVoYXZpb3IgaXMgYWNjZXB0YWJsZSBmb3IgeW91ciB1c2UgY2FzZSwgIiArICJwbGVhc2UgcmVtb3ZlIHRoZSBleHRyYW5lb3VzIHNlZ21lbnRzIGJ5IGNoYW5naW5nIHlvdXIgIiArICgia2V5IHRvIGAiICsgcGF0aC5zbGljZSgwLCBzZWdtZW50RW5kKSArICJgLiAiKSArICJPdGhlcndpc2UsIHBsZWFzZSBjcmVhdGUgYW4gaW50ZXJtZWRpYXJ5IGNvbXB1dGVkIHByb3BlcnR5ICIgKyAib3Igc3dpdGNoIHRvIHVzaW5nIHRyYWNrZWQgcHJvcGVydGllcy4iLCBzZWdtZW50RW5kID09PSAtMSwgewogICAgICAgICAgdW50aWw6ICczLjE3LjAnLAogICAgICAgICAgaWQ6ICdlbWJlci1tZXRhbC5jb21wdXRlZC1kZWVwLWVhY2gnCiAgICAgICAgfSkpOwogICAgICAgIHZhciBhcnJMZW5ndGggPSBjdXJyZW50Lmxlbmd0aDsKCiAgICAgICAgaWYgKHR5cGVvZiBhcnJMZW5ndGggIT09ICdudW1iZXInIHx8IC8vIFRPRE86IHNob3VsZCB0aGUgc2Vjb25kIHRlc3QgYmUgYGlzRW1iZXJBcnJheWAgaW5zdGVhZD8KICAgICAgICAhKEFycmF5LmlzQXJyYXkoY3VycmVudCkgfHwgJ29iamVjdEF0JyBpbiBjdXJyZW50KSkgewogICAgICAgICAgLy8gSWYgdGhlIGN1cnJlbnQgb2JqZWN0IGlzbid0IGFuIGFycmF5LCB0aGVyZSdzIG5vdGhpbmcgZWxzZSB0byBkbywKICAgICAgICAgIC8vIHdlIGRvbid0IHdhdGNoIGluZGl2aWR1YWwgcHJvcGVydGllcy4gQnJlYWsgb3V0IG9mIHRoZSBsb29wLgogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSBlbHNlIGlmIChhcnJMZW5ndGggPT09IDApIHsKICAgICAgICAgIC8vIEZhc3QgcGF0aCBmb3IgZW1wdHkgYXJyYXlzCiAgICAgICAgICBjaGFpblRhZ3MucHVzaCh0YWdGb3JQcm9wZXJ0eShjdXJyZW50LCAnW10nKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIGlmIChzZWdtZW50RW5kID09PSAtMSkgewogICAgICAgICAgc2VnbWVudCA9IHBhdGguc2xpY2UobGFzdFNlZ21lbnRFbmQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBEZXByZWNhdGVkLCByZW1vdmUgb25jZSB3ZSB0dXJuIHRoZSBkZXByZWNhdGlvbiBpbnRvIGFuIGFzc2VydGlvbgogICAgICAgICAgc2VnbWVudCA9IHBhdGguc2xpY2UobGFzdFNlZ21lbnRFbmQsIHNlZ21lbnRFbmQpOwogICAgICAgIH0gLy8gUHVzaCB0aGUgdGFncyBmb3IgZWFjaCBpdGVtJ3MgcHJvcGVydHkKCgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyTGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHZhciBpdGVtID0gb2JqZWN0QXQoY3VycmVudCwgaSk7CiAgICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgaXRlbSA9PT0gJ29iamVjdCcpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiV2hlbiB1c2luZyBAZWFjaCB0byBvYnNlcnZlIHRoZSBhcnJheSBgIiArIGN1cnJlbnQudG9TdHJpbmcoKSArICJgLCB0aGUgaXRlbXMgaW4gdGhlIGFycmF5IG11c3QgYmUgb2JqZWN0cyIsIHR5cGVvZiBpdGVtID09PSAnb2JqZWN0JykpOwogICAgICAgICAgY2hhaW5UYWdzLnB1c2godGFnRm9yUHJvcGVydHkoaXRlbSwgc2VnbWVudCkpOwogICAgICAgIH0gLy8gUHVzaCB0aGUgdGFnIGZvciB0aGUgYXJyYXkgbGVuZ3RoIGl0c2VsZgoKCiAgICAgICAgY2hhaW5UYWdzLnB1c2godGFnRm9yUHJvcGVydHkoY3VycmVudCwgJ1tdJykpOwogICAgICAgIGJyZWFrOwogICAgICB9IC8vIElmIHRoZSBzZWdtZW50IGlzIGxpbmtpbmcgdG8gYW4gYXJncyBwcm94eSwgd2UgbmVlZCB0byBtYW51YWxseSBhY2Nlc3MKICAgICAgLy8gdGhlIHRhZ3MgZm9yIHRoZSBhcmdzLCBzaW5jZSB0aGV5IGFyZSBkaXJlY3QgcmVmZXJlbmNlcyBhbmQgZG9uJ3QgaGF2ZSBhCiAgICAgIC8vIHRhZ0ZvclByb3BlcnR5LiBXZSB0aGVuIGNvbnRpbnVlIGNoYWluaW5nIGxpa2Ugbm9ybWFsIGFmdGVyIGl0LCBzaW5jZQogICAgICAvLyB5b3UgY291bGQgY2hhaW4gb2ZmIGFuIGFyZyBpZiBpdCB3ZXJlIGFuIG9iamVjdCwgZm9yIGluc3RhbmNlLgoKCiAgICAgIGlmIChzZWdtZW50ID09PSAnYXJncycgJiYgQVJHU19QUk9YWV9UQUdTLmhhcyhjdXJyZW50LmFyZ3MpKSB7CiAgICAgICAgKGZhbHNlICYmICEoc2VnbWVudEVuZCAhPT0gcGF0aExlbmd0aCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJXaGVuIHdhdGNoaW5nIHRoZSAnYXJncycgb24gYSBHbGltbWVyQ29tcG9uZW50LCB5b3UgbXVzdCB3YXRjaCBhIHZhbHVlIG9uIHRoZSBhcmdzLiBZb3UgY2Fubm90IHdhdGNoIHRoZSBvYmplY3QgaXRzZWxmLCBhcyBpdCBuZXZlciBjaGFuZ2VzLiIsIHNlZ21lbnRFbmQgIT09IHBhdGhMZW5ndGgpKTsKICAgICAgICBsYXN0U2VnbWVudEVuZCA9IHNlZ21lbnRFbmQgKyAxOwogICAgICAgIHNlZ21lbnRFbmQgPSBwYXRoLmluZGV4T2YoJy4nLCBsYXN0U2VnbWVudEVuZCk7CgogICAgICAgIGlmIChzZWdtZW50RW5kID09PSAtMSkgewogICAgICAgICAgc2VnbWVudEVuZCA9IHBhdGhMZW5ndGg7CiAgICAgICAgfQoKICAgICAgICBzZWdtZW50ID0gcGF0aC5zbGljZShsYXN0U2VnbWVudEVuZCwgc2VnbWVudEVuZCk7CiAgICAgICAgdmFyIG5hbWVkQXJncyA9IEFSR1NfUFJPWFlfVEFHUy5nZXQoY3VycmVudC5hcmdzKTsKICAgICAgICB2YXIgcmVmID0gbmFtZWRBcmdzLmdldChzZWdtZW50KTsKICAgICAgICBjaGFpblRhZ3MucHVzaChyZWYudGFnKTsgLy8gV2Ugc3RpbGwgbmVlZCB0byBicmVhayBpZiB3ZSdyZSBhdCB0aGUgZW5kIG9mIHRoZSBwYXRoLgoKICAgICAgICBpZiAoc2VnbWVudEVuZCA9PT0gcGF0aExlbmd0aCkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSAvLyBPdGhlcndpc2UsIHNldCB0aGUgY3VycmVudCB2YWx1ZSBhbmQgdGhlbiBjb250aW51ZSB0byB0aGUgbmV4dCBzZWdtZW50CgoKICAgICAgICBjdXJyZW50ID0gcmVmLnZhbHVlKCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0gLy8gVE9ETzogQXNzZXJ0IHRoYXQgY3VycmVudFtzZWdtZW50XSBpc24ndCBhbiB1bmRlY29yYXRlZCwgbm9uLU1BTkRBVE9SWV9TRVRURVIvZGVwZW5kZW50S2V5Q29tcGF0IGdldHRlcgoKCiAgICAgIHZhciBwcm9wZXJ0eVRhZyA9IHRhZ0ZvclByb3BlcnR5KGN1cnJlbnQsIHNlZ21lbnQpOwogICAgICBkZXNjcmlwdG9yID0gZGVzY3JpcHRvckZvclByb3BlcnR5KGN1cnJlbnQsIHNlZ21lbnQpOwogICAgICBjaGFpblRhZ3MucHVzaChwcm9wZXJ0eVRhZyk7IC8vIElmIHRoZSBrZXkgd2FzIGFuIGFsaWFzLCB3ZSBzaG91bGQgYWx3YXlzIGdldCB0aGUgbmV4dCB2YWx1ZSBpbiBvcmRlciB0bwogICAgICAvLyBib290c3RyYXAgdGhlIGFsaWFzLiBUaGlzIGlzIGJlY2F1c2UgYWxpYXNlcywgdW5saWtlIG90aGVyIENQcywgc2hvdWxkCiAgICAgIC8vIGFsd2F5cyBiZSBpbiBzeW5jIHdpdGggdGhlIGFsaWFzZWQgdmFsdWUuCgogICAgICBpZiAoZGVzY3JpcHRvciAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBkZXNjcmlwdG9yLmFsdEtleSA9PT0gJ3N0cmluZycpIHsKICAgICAgICBjdXJyZW50ID0gY3VycmVudFtzZWdtZW50XTsgLy8gV2Ugc3RpbGwgbmVlZCB0byBicmVhayBpZiB3ZSdyZSBhdCB0aGUgZW5kIG9mIHRoZSBwYXRoLgoKICAgICAgICBpZiAoc2VnbWVudEVuZCA9PT0gcGF0aExlbmd0aCkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSAvLyBPdGhlcndpc2UsIGNvbnRpbnVlIHRvIHByb2Nlc3MgdGhlIG5leHQgc2VnbWVudAoKCiAgICAgICAgY29udGludWU7CiAgICAgIH0gLy8gSWYgd2UncmUgYXQgdGhlIGVuZCBvZiB0aGUgcGF0aCwgcHJvY2Vzc2luZyB0aGUgbGFzdCBzZWdtZW50LCBhbmQgaXQncwogICAgICAvLyBub3QgYW4gYWxpYXMsIHdlIHNob3VsZCBfbm90XyBnZXQgdGhlIGxhc3QgdmFsdWUsIHNpbmNlIHdlIGFscmVhZHkgaGF2ZQogICAgICAvLyBpdHMgdGFnLiBUaGVyZSdzIG5vIHJlYXNvbiB0byBhY2Nlc3MgaXQgYW5kIGRvIG1vcmUgd29yay4KCgogICAgICBpZiAoc2VnbWVudEVuZCA9PT0gcGF0aExlbmd0aCkgewogICAgICAgIGJyZWFrOwogICAgICB9CgogICAgICBpZiAoZGVzY3JpcHRvciA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgLy8gSWYgdGhlIGRlc2NyaXB0b3IgaXMgdW5kZWZpbmVkLCB0aGVuIGl0cyBhIG5vcm1hbCBwcm9wZXJ0eSwgc28gd2Ugc2hvdWxkCiAgICAgICAgLy8gbG9va3VwIHRoZSB2YWx1ZSB0byBjaGFpbiBvZmYgb2YgbGlrZSBub3JtYWwuCiAgICAgICAgaWYgKCEoc2VnbWVudCBpbiBjdXJyZW50KSAmJiB0eXBlb2YgY3VycmVudC51bmtub3duUHJvcGVydHkgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIGN1cnJlbnQgPSBjdXJyZW50LnVua25vd25Qcm9wZXJ0eShzZWdtZW50KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY3VycmVudCA9IGN1cnJlbnRbc2VnbWVudF07CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIC8vIElmIHRoZSBkZXNjcmlwdG9yIGlzIGRlZmluZWQsIHRoZW4gaXRzIGEgbm9ybWFsIENQIChub3QgYW4gYWxpYXMsIHdoaWNoCiAgICAgICAgLy8gd291bGQgaGF2ZSBiZWVuIGhhbmRsZWQgZWFybGllcikuIFdlIGdldCB0aGUgbGFzdCByZXZpc2lvbiB0byBjaGVjayBpZgogICAgICAgIC8vIHRoZSBDUCBpcyBzdGlsbCB2YWxpZCwgYW5kIGlmIHNvIHdlIHVzZSB0aGUgY2FjaGVkIHZhbHVlLiBJZiBub3QsIHRoZW4KICAgICAgICAvLyB3ZSBjcmVhdGUgYSBsYXp5IGNoYWluIGxvb2t1cCwgYW5kIHRoZSBuZXh0IHRpbWUgdGhlIENQIGlzIGNhbHVjdWxhdGVkLAogICAgICAgIC8vIGl0IHdpbGwgdXBkYXRlIHRoYXQgbGF6eSBjaGFpbi4KICAgICAgICB2YXIgbGFzdFJldmlzaW9uID0gZ2V0TGFzdFJldmlzaW9uRm9yKGN1cnJlbnQsIHNlZ21lbnQpOwoKICAgICAgICBpZiAoKDAsIF9yZWZlcmVuY2UudmFsaWRhdGUpKHByb3BlcnR5VGFnLCBsYXN0UmV2aXNpb24pKSB7CiAgICAgICAgICBjdXJyZW50ID0gcGVla0NhY2hlRm9yKGN1cnJlbnQpLmdldChzZWdtZW50KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFyIGxhenlDaGFpbnMgPSAoMCwgX21ldGEyLm1ldGEpKGN1cnJlbnQpLndyaXRhYmxlTGF6eUNoYWluc0ZvcihzZWdtZW50KTsKICAgICAgICAgIHZhciByZXN0ID0gcGF0aC5zdWJzdHIoc2VnbWVudEVuZCArIDEpOwogICAgICAgICAgdmFyIHBsYWNlaG9sZGVyVGFnID0gbGF6eUNoYWluc1tyZXN0XTsKCiAgICAgICAgICBpZiAocGxhY2Vob2xkZXJUYWcgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBwbGFjZWhvbGRlclRhZyA9IGxhenlDaGFpbnNbcmVzdF0gPSAoMCwgX3JlZmVyZW5jZS5jcmVhdGVVcGRhdGFibGVUYWcpKCk7CiAgICAgICAgICB9CgogICAgICAgICAgY2hhaW5UYWdzLnB1c2gocGxhY2Vob2xkZXJUYWcpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGNoYWluVGFnczsKICB9CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KCgogIHZhciBFTkRfV0lUSF9FQUNIX1JFR0VYID0gL1wuQGVhY2gkLzsKICAvKioKICAgIEV4cGFuZHMgYHBhdHRlcm5gLCBpbnZva2luZyBgY2FsbGJhY2tgIGZvciBlYWNoIGV4cGFuc2lvbi4KICAKICAgIFRoZSBvbmx5IHBhdHRlcm4gc3VwcG9ydGVkIGlzIGJyYWNlLWV4cGFuc2lvbiwgYW55dGhpbmcgZWxzZSB3aWxsIGJlIHBhc3NlZAogICAgb25jZSB0byBgY2FsbGJhY2tgIGRpcmVjdGx5LgogIAogICAgRXhhbXBsZQogIAogICAgYGBganMKICAgIGltcG9ydCB7IGV4cGFuZFByb3BlcnRpZXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGZ1bmN0aW9uIGVjaG8oYXJnKXsgY29uc29sZS5sb2coYXJnKTsgfQogIAogICAgZXhwYW5kUHJvcGVydGllcygnZm9vLmJhcicsIGVjaG8pOyAgICAgICAgICAgICAgLy89PiAnZm9vLmJhcicKICAgIGV4cGFuZFByb3BlcnRpZXMoJ3tmb28sYmFyfScsIGVjaG8pOyAgICAgICAgICAgIC8vPT4gJ2ZvbycsICdiYXInCiAgICBleHBhbmRQcm9wZXJ0aWVzKCdmb28ue2JhcixiYXp9JywgZWNobyk7ICAgICAgICAvLz0+ICdmb28uYmFyJywgJ2Zvby5iYXonCiAgICBleHBhbmRQcm9wZXJ0aWVzKCd7Zm9vLGJhcn0uYmF6JywgZWNobyk7ICAgICAgICAvLz0+ICdmb28uYmF6JywgJ2Jhci5iYXonCiAgICBleHBhbmRQcm9wZXJ0aWVzKCdmb28ue2JhcixiYXp9LltdJywgZWNobykgICAgICAvLz0+ICdmb28uYmFyLltdJywgJ2Zvby5iYXouW10nCiAgICBleHBhbmRQcm9wZXJ0aWVzKCd7Zm9vLGJhcn0ue3NwYW0sZWdnc30nLCBlY2hvKSAvLz0+ICdmb28uc3BhbScsICdmb28uZWdncycsICdiYXIuc3BhbScsICdiYXIuZWdncycKICAgIGV4cGFuZFByb3BlcnRpZXMoJ3tmb299LmJhci57YmF6fScpICAgICAgICAgICAgIC8vPT4gJ2Zvby5iYXIuYmF6JwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGV4cGFuZFByb3BlcnRpZXMKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHB1YmxpYwogICAgQHBhcmFtIHtTdHJpbmd9IHBhdHRlcm4gVGhlIHByb3BlcnR5IHBhdHRlcm4gdG8gZXhwYW5kLgogICAgQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGNhbGxiYWNrIHRvIGludm9rZS4gIEl0IGlzIGludm9rZWQgb25jZSBwZXIKICAgIGV4cGFuc2lvbiwgYW5kIGlzIHBhc3NlZCB0aGUgZXhwYW5zaW9uLgogICovCgogIGZ1bmN0aW9uIGV4cGFuZFByb3BlcnRpZXMocGF0dGVybiwgY2FsbGJhY2spIHsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBwYXR0ZXJuID09PSAnc3RyaW5nJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJBIGNvbXB1dGVkIHByb3BlcnR5IGtleSBtdXN0IGJlIGEgc3RyaW5nLCB5b3UgcGFzc2VkICIgKyB0eXBlb2YgcGF0dGVybiArICIgIiArIHBhdHRlcm4sIHR5cGVvZiBwYXR0ZXJuID09PSAnc3RyaW5nJykpOwogICAgKGZhbHNlICYmICEocGF0dGVybi5pbmRleE9mKCcgJykgPT09IC0xKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0JyYWNlIGV4cGFuZGVkIHByb3BlcnRpZXMgY2Fubm90IGNvbnRhaW4gc3BhY2VzLCBlLmcuICJ1c2VyLntmaXJzdE5hbWUsIGxhc3ROYW1lfSIgc2hvdWxkIGJlICJ1c2VyLntmaXJzdE5hbWUsbGFzdE5hbWV9IicsIHBhdHRlcm4uaW5kZXhPZignICcpID09PSAtMSkpOyAvLyByZWdleCB0byBsb29rIGZvciBkb3VibGUgb3BlbiwgZG91YmxlIGNsb3NlLCBvciB1bmNsb3NlZCBicmFjZXMKCiAgICAoZmFsc2UgJiYgIShwYXR0ZXJuLm1hdGNoKC9ce1tefXtdKlx7fFx9W159e10qXH18XHtbXn1dKiQvZykgPT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQnJhY2UgZXhwYW5kZWQgcHJvcGVydGllcyBoYXZlIHRvIGJlIGJhbGFuY2VkIGFuZCBjYW5ub3QgYmUgbmVzdGVkLCBwYXR0ZXJuOiAiICsgcGF0dGVybiwgcGF0dGVybi5tYXRjaCgvXHtbXn17XSpce3xcfVtefXtdKlx9fFx7W159XSokL2cpID09PSBudWxsKSk7CiAgICB2YXIgc3RhcnQgPSBwYXR0ZXJuLmluZGV4T2YoJ3snKTsKCiAgICBpZiAoc3RhcnQgPCAwKSB7CiAgICAgIGNhbGxiYWNrKHBhdHRlcm4ucmVwbGFjZShFTkRfV0lUSF9FQUNIX1JFR0VYLCAnLltdJykpOwogICAgfSBlbHNlIHsKICAgICAgZGl2ZSgnJywgcGF0dGVybiwgc3RhcnQsIGNhbGxiYWNrKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGRpdmUocHJlZml4LCBwYXR0ZXJuLCBzdGFydCwgY2FsbGJhY2spIHsKICAgIHZhciBlbmQgPSBwYXR0ZXJuLmluZGV4T2YoJ30nKSwKICAgICAgICBpID0gMCwKICAgICAgICBuZXdTdGFydCwKICAgICAgICBhcnJheUxlbmd0aDsKICAgIHZhciB0ZW1wQXJyID0gcGF0dGVybi5zdWJzdHJpbmcoc3RhcnQgKyAxLCBlbmQpLnNwbGl0KCcsJyk7CiAgICB2YXIgYWZ0ZXIgPSBwYXR0ZXJuLnN1YnN0cmluZyhlbmQgKyAxKTsKICAgIHByZWZpeCA9IHByZWZpeCArIHBhdHRlcm4uc3Vic3RyaW5nKDAsIHN0YXJ0KTsKICAgIGFycmF5TGVuZ3RoID0gdGVtcEFyci5sZW5ndGg7CgogICAgd2hpbGUgKGkgPCBhcnJheUxlbmd0aCkgewogICAgICBuZXdTdGFydCA9IGFmdGVyLmluZGV4T2YoJ3snKTsKCiAgICAgIGlmIChuZXdTdGFydCA8IDApIHsKICAgICAgICBjYWxsYmFjaygocHJlZml4ICsgdGVtcEFycltpKytdICsgYWZ0ZXIpLnJlcGxhY2UoRU5EX1dJVEhfRUFDSF9SRUdFWCwgJy5bXScpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBkaXZlKHByZWZpeCArIHRlbXBBcnJbaSsrXSwgYWZ0ZXIsIG5ld1N0YXJ0LCBjYWxsYmFjayk7CiAgICAgIH0KICAgIH0KICB9CiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL29iamVjdAogICovCgogIC8qKgogICAgU2V0cyB0aGUgdmFsdWUgb2YgYSBwcm9wZXJ0eSBvbiBhbiBvYmplY3QsIHJlc3BlY3RpbmcgY29tcHV0ZWQgcHJvcGVydGllcwogICAgYW5kIG5vdGlmeWluZyBvYnNlcnZlcnMgYW5kIG90aGVyIGxpc3RlbmVycyBvZiB0aGUgY2hhbmdlLgogICAgSWYgdGhlIHNwZWNpZmllZCBwcm9wZXJ0eSBpcyBub3QgZGVmaW5lZCBvbiB0aGUgb2JqZWN0IGFuZCB0aGUgb2JqZWN0CiAgICBpbXBsZW1lbnRzIHRoZSBgc2V0VW5rbm93blByb3BlcnR5YCBtZXRob2QsIHRoZW4gaW5zdGVhZCBvZiBzZXR0aW5nIHRoZQogICAgdmFsdWUgb2YgdGhlIHByb3BlcnR5IG9uIHRoZSBvYmplY3QsIGl0cyBgc2V0VW5rbm93blByb3BlcnR5YCBoYW5kbGVyCiAgICB3aWxsIGJlIGludm9rZWQgd2l0aCB0aGUgdHdvIHBhcmFtZXRlcnMgYGtleU5hbWVgIGFuZCBgdmFsdWVgLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBzZXQob2JqLCAibmFtZSIsIHZhbHVlKTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBzZXQKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdAogICAgQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIG1vZGlmeS4KICAgIEBwYXJhbSB7U3RyaW5nfSBrZXlOYW1lIFRoZSBwcm9wZXJ0eSBrZXkgdG8gc2V0CiAgICBAcGFyYW0ge09iamVjdH0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldAogICAgQHJldHVybiB7T2JqZWN0fSB0aGUgcGFzc2VkIHZhbHVlLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBfc2V0MihvYmosIGtleU5hbWUsIHZhbHVlJCQxLCB0b2xlcmFudCkgewogICAgKGZhbHNlICYmICEoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyB8fCBhcmd1bWVudHMubGVuZ3RoID09PSA0KSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIlNldCBtdXN0IGJlIGNhbGxlZCB3aXRoIHRocmVlIG9yIGZvdXIgYXJndW1lbnRzOyBhbiBvYmplY3QsIGEgcHJvcGVydHkga2V5LCBhIHZhbHVlIGFuZCB0b2xlcmFudCB0cnVlL2ZhbHNlIiwgYXJndW1lbnRzLmxlbmd0aCA9PT0gMyB8fCBhcmd1bWVudHMubGVuZ3RoID09PSA0KSk7CiAgICAoZmFsc2UgJiYgIShvYmogJiYgdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJDYW5ub3QgY2FsbCBzZXQgd2l0aCAnIiArIGtleU5hbWUgKyAiJyBvbiBhbiB1bmRlZmluZWQgb2JqZWN0LiIsIG9iaiAmJiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyB8fCB0eXBlb2Ygb2JqID09PSAnZnVuY3Rpb24nKSk7CiAgICAoZmFsc2UgJiYgISh0eXBlb2Yga2V5TmFtZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGtleU5hbWUgPT09ICdudW1iZXInICYmICFpc05hTihrZXlOYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUga2V5IHByb3ZpZGVkIHRvIHNldCBtdXN0IGJlIGEgc3RyaW5nIG9yIG51bWJlciwgeW91IHBhc3NlZCAiICsga2V5TmFtZSwgdHlwZW9mIGtleU5hbWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBrZXlOYW1lID09PSAnbnVtYmVyJyAmJiAhaXNOYU4oa2V5TmFtZSkpKTsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBrZXlOYW1lICE9PSAnc3RyaW5nJyB8fCBrZXlOYW1lLmxhc3RJbmRleE9mKCd0aGlzLicsIDApICE9PSAwKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIid0aGlzJyBpbiBwYXRocyBpcyBub3Qgc3VwcG9ydGVkIiwgdHlwZW9mIGtleU5hbWUgIT09ICdzdHJpbmcnIHx8IGtleU5hbWUubGFzdEluZGV4T2YoJ3RoaXMuJywgMCkgIT09IDApKTsKCiAgICBpZiAob2JqLmlzRGVzdHJveWVkKSB7CiAgICAgIChmYWxzZSAmJiAhKHRvbGVyYW50KSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoImNhbGxpbmcgc2V0IG9uIGRlc3Ryb3llZCBvYmplY3Q6ICIgKyAoMCwgX3V0aWxzLnRvU3RyaW5nKShvYmopICsgIi4iICsga2V5TmFtZSArICIgPSAiICsgKDAsIF91dGlscy50b1N0cmluZykodmFsdWUkJDEpLCB0b2xlcmFudCkpOwogICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKGlzUGF0aChrZXlOYW1lKSkgewogICAgICByZXR1cm4gc2V0UGF0aChvYmosIGtleU5hbWUsIHZhbHVlJCQxLCB0b2xlcmFudCk7CiAgICB9CgogICAgdmFyIG1ldGEkJDEgPSAoMCwgX21ldGEyLnBlZWtNZXRhKShvYmopOwogICAgewogICAgICB2YXIgZGVzY3JpcHRvciA9ICgwLCBfdXRpbHMubG9va3VwRGVzY3JpcHRvcikob2JqLCBrZXlOYW1lKTsKICAgICAgdmFyIHNldHRlciA9IGRlc2NyaXB0b3IgPT09IG51bGwgPyB1bmRlZmluZWQgOiBkZXNjcmlwdG9yLnNldDsKCiAgICAgIGlmIChzZXR0ZXIgIT09IHVuZGVmaW5lZCAmJiBDUF9TRVRURVJfRlVOQ1MuaGFzKHNldHRlcikpIHsKICAgICAgICBvYmpba2V5TmFtZV0gPSB2YWx1ZSQkMTsKICAgICAgICByZXR1cm4gdmFsdWUkJDE7CiAgICAgIH0KICAgIH0KICAgIHZhciBjdXJyZW50VmFsdWU7CgogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgJiYgX3V0aWxzLkhBU19OQVRJVkVfUFJPWFkpIHsKICAgICAgY3VycmVudFZhbHVlID0gZ2V0UG9zc2libGVNYW5kYXRvcnlQcm94eVZhbHVlKG9iaiwga2V5TmFtZSk7CiAgICB9IGVsc2UgewogICAgICBjdXJyZW50VmFsdWUgPSBvYmpba2V5TmFtZV07CiAgICB9CgogICAgaWYgKGN1cnJlbnRWYWx1ZSA9PT0gdW5kZWZpbmVkICYmICdvYmplY3QnID09PSB0eXBlb2Ygb2JqICYmICEoa2V5TmFtZSBpbiBvYmopICYmIHR5cGVvZiBvYmouc2V0VW5rbm93blByb3BlcnR5ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIC8qIHVua25vd24gcHJvcGVydHkgKi8KICAgICAgb2JqLnNldFVua25vd25Qcm9wZXJ0eShrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgICB9IGVsc2UgewogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgewogICAgICAgICAgKDAsIF91dGlscy5zZXRXaXRoTWFuZGF0b3J5U2V0dGVyKShvYmosIGtleU5hbWUsIHZhbHVlJCQxKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgb2JqW2tleU5hbWVdID0gdmFsdWUkJDE7CiAgICAgIH0KCiAgICAgIGlmIChjdXJyZW50VmFsdWUgIT09IHZhbHVlJCQxKSB7CiAgICAgICAgbm90aWZ5UHJvcGVydHlDaGFuZ2Uob2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiB2YWx1ZSQkMTsKICB9CgogIGZ1bmN0aW9uIHNldFBhdGgocm9vdCwgcGF0aCwgdmFsdWUkJDEsIHRvbGVyYW50KSB7CiAgICB2YXIgcGFydHMgPSBwYXRoLnNwbGl0KCcuJyk7CiAgICB2YXIga2V5TmFtZSA9IHBhcnRzLnBvcCgpOwogICAgKGZhbHNlICYmICEoa2V5TmFtZS50cmltKCkubGVuZ3RoID4gMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdQcm9wZXJ0eSBzZXQgZmFpbGVkOiBZb3UgcGFzc2VkIGFuIGVtcHR5IHBhdGgnLCBrZXlOYW1lLnRyaW0oKS5sZW5ndGggPiAwKSk7CgogICAgdmFyIG5ld1Jvb3QgPSBfZ2V0UGF0aChyb290LCBwYXJ0cyk7CgogICAgaWYgKG5ld1Jvb3QgIT09IG51bGwgJiYgbmV3Um9vdCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBfc2V0MihuZXdSb290LCBrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgICB9IGVsc2UgaWYgKCF0b2xlcmFudCkgewogICAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIlByb3BlcnR5IHNldCBmYWlsZWQ6IG9iamVjdCBpbiBwYXRoIFwiIiArIHBhcnRzLmpvaW4oJy4nKSArICJcIiBjb3VsZCBub3QgYmUgZm91bmQuIik7CiAgICB9CiAgfQogIC8qKgogICAgRXJyb3ItdG9sZXJhbnQgZm9ybSBvZiBgc2V0YC4gV2lsbCBub3QgYmxvdyB1cCBpZiBhbnkgcGFydCBvZiB0aGUKICAgIGNoYWluIGlzIGB1bmRlZmluZWRgLCBgbnVsbGAsIG9yIGRlc3Ryb3llZC4KICAKICAgIFRoaXMgaXMgcHJpbWFyaWx5IHVzZWQgd2hlbiBzeW5jaW5nIGJpbmRpbmdzLCB3aGljaCBtYXkgdHJ5IHRvIHVwZGF0ZSBhZnRlcgogICAgYW4gb2JqZWN0IGhhcyBiZWVuIGRlc3Ryb3llZC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHRyeVNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgbGV0IG9iaiA9IHsgbmFtZTogIlpvZXkiIH07CiAgICB0cnlTZXQob2JqLCAiY29udGFjdHMudHdpdHRlciIsICJAZW1iZXJqcyIpOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHRyeVNldAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0CiAgICBAcGFyYW0ge09iamVjdH0gcm9vdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS4KICAgIEBwYXJhbSB7U3RyaW5nfSBwYXRoIFRoZSBwcm9wZXJ0eSBwYXRoIHRvIHNldAogICAgQHBhcmFtIHtPYmplY3R9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gdHJ5U2V0KHJvb3QsIHBhdGgsIHZhbHVlJCQxKSB7CiAgICByZXR1cm4gX3NldDIocm9vdCwgcGF0aCwgdmFsdWUkJDEsIHRydWUpOwogIH0KICAvKioKICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwoKCiAgdmFyIERFRVBfRUFDSF9SRUdFWCA9IC9cLkBlYWNoXC5bXi5dK1wuLzsKCiAgZnVuY3Rpb24gbm9vcCgpIHt9CiAgLyoqCiAgICBgQGNvbXB1dGVkYCBpcyBhIGRlY29yYXRvciB0aGF0IHR1cm5zIGEgSmF2YVNjcmlwdCBnZXR0ZXIgYW5kIHNldHRlciBpbnRvIGEKICAgIGNvbXB1dGVkIHByb3BlcnR5LCB3aGljaCBpcyBhIF9jYWNoZWQsIHRyYWNrYWJsZSB2YWx1ZV8uIEJ5IGRlZmF1bHQgdGhlIGdldHRlcgogICAgd2lsbCBvbmx5IGJlIGNhbGxlZCBvbmNlIGFuZCB0aGUgcmVzdWx0IHdpbGwgYmUgY2FjaGVkLiBZb3UgY2FuIHNwZWNpZnkKICAgIHZhcmlvdXMgcHJvcGVydGllcyB0aGF0IHlvdXIgY29tcHV0ZWQgcHJvcGVydHkgZGVwZW5kcyBvbi4gVGhpcyB3aWxsIGZvcmNlIHRoZQogICAgY2FjaGVkIHJlc3VsdCB0byBiZSBjbGVhcmVkIGlmIHRoZSBkZXBlbmRlbmNpZXMgYXJlIG1vZGlmaWVkLCBhbmQgbGF6aWx5IHJlY29tcHV0ZWQgdGhlIG5leHQgdGltZSBzb21ldGhpbmcgYXNrcyBmb3IgaXQuCiAgCiAgICBJbiB0aGUgZm9sbG93aW5nIGV4YW1wbGUgd2UgZGVjb3JhdGUgYSBnZXR0ZXIgLSBgZnVsbE5hbWVgIC0gIGJ5IGNhbGxpbmcKICAgIGBjb21wdXRlZGAgd2l0aCB0aGUgcHJvcGVydHkgZGVwZW5kZW5jaWVzIChgZmlyc3ROYW1lYCBhbmQgYGxhc3ROYW1lYCkgYXMKICAgIGFyZ3VtZW50cy4gVGhlIGBmdWxsTmFtZWAgZ2V0dGVyIHdpbGwgYmUgY2FsbGVkIG9uY2UgKHJlZ2FyZGxlc3Mgb2YgaG93IG1hbnkKICAgIHRpbWVzIGl0IGlzIGFjY2Vzc2VkKSBhcyBsb25nIGFzIGl0cyBkZXBlbmRlbmNpZXMgZG8gbm90IGNoYW5nZS4gT25jZQogICAgYGZpcnN0TmFtZWAgb3IgYGxhc3ROYW1lYCBhcmUgdXBkYXRlZCBhbnkgZnV0dXJlIGNhbGxzIHRvIGBmdWxsTmFtZWAgd2lsbAogICAgaW5jb3Jwb3JhdGUgdGhlIG5ldyB2YWx1ZXMsIGFuZCBhbnkgd2F0Y2hlcnMgb2YgdGhlIHZhbHVlIHN1Y2ggYXMgdGVtcGxhdGVzCiAgICB3aWxsIGJlIHVwZGF0ZWQ6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBjb21wdXRlZCwgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgCiAgICBjbGFzcyBQZXJzb24gewogICAgICBjb25zdHJ1Y3RvcihmaXJzdE5hbWUsIGxhc3ROYW1lKSB7CiAgICAgICAgc2V0KHRoaXMsICdmaXJzdE5hbWUnLCBmaXJzdE5hbWUpOwogICAgICAgIHNldCh0aGlzLCAnbGFzdE5hbWUnLCBsYXN0TmFtZSk7CiAgICAgIH0KICAKICAgICAgQGNvbXB1dGVkKCdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnKQogICAgICBnZXQgZnVsbE5hbWUoKSB7CiAgICAgICAgcmV0dXJuIGAke3RoaXMuZmlyc3ROYW1lfSAke3RoaXMubGFzdE5hbWV9YDsKICAgICAgfQogICAgfSk7CiAgCiAgICBsZXQgdG9tID0gbmV3IFBlcnNvbignVG9tJywgJ0RhbGUnKTsKICAKICAgIHRvbS5mdWxsTmFtZTsgLy8gJ1RvbSBEYWxlJwogICAgYGBgCiAgCiAgICBZb3UgY2FuIGFsc28gcHJvdmlkZSBhIHNldHRlciwgd2hpY2ggd2lsbCBiZSB1c2VkIHdoZW4gdXBkYXRpbmcgdGhlIGNvbXB1dGVkCiAgICBwcm9wZXJ0eS4gRW1iZXIncyBgc2V0YCBmdW5jdGlvbiBtdXN0IGJlIHVzZWQgdG8gdXBkYXRlIHRoZSBwcm9wZXJ0eQogICAgc2luY2UgaXQgd2lsbCBhbHNvIG5vdGlmeSBvYnNlcnZlcnMgb2YgdGhlIHByb3BlcnR5OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgY29tcHV0ZWQsIHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgY2xhc3MgUGVyc29uIHsKICAgICAgY29uc3RydWN0b3IoZmlyc3ROYW1lLCBsYXN0TmFtZSkgewogICAgICAgIHNldCh0aGlzLCAnZmlyc3ROYW1lJywgZmlyc3ROYW1lKTsKICAgICAgICBzZXQodGhpcywgJ2xhc3ROYW1lJywgbGFzdE5hbWUpOwogICAgICB9CiAgCiAgICAgIEBjb21wdXRlZCgnZmlyc3ROYW1lJywgJ2xhc3ROYW1lJykKICAgICAgZ2V0IGZ1bGxOYW1lKCkgewogICAgICAgIHJldHVybiBgJHt0aGlzLmZpcnN0TmFtZX0gJHt0aGlzLmxhc3ROYW1lfWA7CiAgICAgIH0KICAKICAgICAgc2V0IGZ1bGxOYW1lKHZhbHVlKSB7CiAgICAgICAgbGV0IFtmaXJzdE5hbWUsIGxhc3ROYW1lXSA9IHZhbHVlLnNwbGl0KCcgJyk7CiAgCiAgICAgICAgc2V0KHRoaXMsICdmaXJzdE5hbWUnLCBmaXJzdE5hbWUpOwogICAgICAgIHNldCh0aGlzLCAnbGFzdE5hbWUnLCBsYXN0TmFtZSk7CiAgICAgIH0KICAgIH0pOwogIAogICAgbGV0IHBlcnNvbiA9IG5ldyBQZXJzb24oKTsKICAKICAgIHNldChwZXJzb24sICdmdWxsTmFtZScsICdQZXRlciBXYWdlbmV0Jyk7CiAgICBwZXJzb24uZmlyc3ROYW1lOyAvLyAnUGV0ZXInCiAgICBwZXJzb24ubGFzdE5hbWU7ICAvLyAnV2FnZW5ldCcKICAgIGBgYAogIAogICAgWW91IGNhbiBhbHNvIHBhc3MgYSBnZXR0ZXIgZnVuY3Rpb24gb3Igb2JqZWN0IHdpdGggYGdldGAgYW5kIGBzZXRgIGZ1bmN0aW9ucwogICAgYXMgdGhlIGxhc3QgYXJndW1lbnQgdG8gdGhlIGNvbXB1dGVkIGRlY29yYXRvci4gVGhpcyBhbGxvd3MgeW91IHRvIGRlZmluZQogICAgY29tcHV0ZWQgcHJvcGVydHkgX21hY3Jvc186CiAgCiAgICBgYGBqcwogICAgaW1wb3J0IHsgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGZ1bmN0aW9uIGpvaW4oLi4ua2V5cykgewogICAgICByZXR1cm4gY29tcHV0ZWQoLi4ua2V5cywgZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIGtleXMubWFwKGtleSA9PiB0aGlzW2tleV0pLmpvaW4oJyAnKTsKICAgICAgfSk7CiAgICB9CiAgCiAgICBjbGFzcyBQZXJzb24gewogICAgICBAam9pbignZmlyc3ROYW1lJywgJ2xhc3ROYW1lJykKICAgICAgZnVsbE5hbWU7CiAgICB9CiAgICBgYGAKICAKICAgIE5vdGUgdGhhdCB3aGVuIGRlZmluZWQgdGhpcyB3YXksIGdldHRlcnMgYW5kIHNldHRlcnMgcmVjZWl2ZSB0aGUgX2tleV8gb2YgdGhlCiAgICBwcm9wZXJ0eSB0aGV5IGFyZSBkZWNvcmF0aW5nIGFzIHRoZSBmaXJzdCBhcmd1bWVudC4gU2V0dGVycyByZWNlaXZlIHRoZSB2YWx1ZQogICAgdGhleSBhcmUgc2V0dGluZyB0byBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IGluc3RlYWQuIEFkZGl0aW9uYWxseSwgc2V0dGVycyBtdXN0CiAgICBfcmV0dXJuXyB0aGUgdmFsdWUgdGhhdCBzaG91bGQgYmUgY2FjaGVkOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgY29tcHV0ZWQsIHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZnVuY3Rpb24gZnVsbE5hbWVNYWNybyhmaXJzdE5hbWVLZXksIGxhc3ROYW1lS2V5KSB7CiAgICAgIHJldHVybiBjb21wdXRlZChmaXJzdE5hbWVLZXksIGxhc3ROYW1lS2V5LCB7CiAgICAgICAgZ2V0KCkgewogICAgICAgICAgcmV0dXJuIGAke3RoaXNbZmlyc3ROYW1lS2V5XX0gJHt0aGlzW2xhc3ROYW1lS2V5XX1gOwogICAgICAgIH0KICAKICAgICAgICBzZXQoa2V5LCB2YWx1ZSkgewogICAgICAgICAgbGV0IFtmaXJzdE5hbWUsIGxhc3ROYW1lXSA9IHZhbHVlLnNwbGl0KCcgJyk7CiAgCiAgICAgICAgICBzZXQodGhpcywgZmlyc3ROYW1lS2V5LCBmaXJzdE5hbWUpOwogICAgICAgICAgc2V0KHRoaXMsIGxhc3ROYW1lS2V5LCBsYXN0TmFtZSk7CiAgCiAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICAKICAgIGNsYXNzIFBlcnNvbiB7CiAgICAgIGNvbnN0cnVjdG9yKGZpcnN0TmFtZSwgbGFzdE5hbWUpIHsKICAgICAgICBzZXQodGhpcywgJ2ZpcnN0TmFtZScsIGZpcnN0TmFtZSk7CiAgICAgICAgc2V0KHRoaXMsICdsYXN0TmFtZScsIGxhc3ROYW1lKTsKICAgICAgfQogIAogICAgICBAZnVsbE5hbWVNYWNybyBmdWxsTmFtZTsKICAgIH0pOwogIAogICAgbGV0IHBlcnNvbiA9IG5ldyBQZXJzb24oKTsKICAKICAgIHNldChwZXJzb24sICdmdWxsTmFtZScsICdQZXRlciBXYWdlbmV0Jyk7CiAgICBwZXJzb24uZmlyc3ROYW1lOyAvLyAnUGV0ZXInCiAgICBwZXJzb24ubGFzdE5hbWU7ICAvLyAnV2FnZW5ldCcKICAgIGBgYAogIAogICAgQ29tcHV0ZWQgcHJvcGVydGllcyBjYW4gYWxzbyBiZSB1c2VkIGluIGNsYXNzaWMgY2xhc3Nlcy4gVG8gZG8gdGhpcywgd2UKICAgIHByb3ZpZGUgdGhlIGdldHRlciBhbmQgc2V0dGVyIGFzIHRoZSBsYXN0IGFyZ3VtZW50IGxpa2Ugd2Ugd291bGQgZm9yIGEgbWFjcm8sCiAgICBhbmQgd2UgYXNzaWduIGl0IHRvIGEgcHJvcGVydHkgb24gdGhlIGNsYXNzIGRlZmluaXRpb24uIFRoaXMgaXMgYW4gX2Fub255bW91c18KICAgIGNvbXB1dGVkIG1hY3JvOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IGNvbXB1dGVkLCBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGxldCBQZXJzb24gPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAvLyB0aGVzZSB3aWxsIGJlIHN1cHBsaWVkIGJ5IGBjcmVhdGVgCiAgICAgIGZpcnN0TmFtZTogbnVsbCwKICAgICAgbGFzdE5hbWU6IG51bGwsCiAgCiAgICAgIGZ1bGxOYW1lOiBjb21wdXRlZCgnZmlyc3ROYW1lJywgJ2xhc3ROYW1lJywgewogICAgICAgIGdldCgpIHsKICAgICAgICAgIHJldHVybiBgJHt0aGlzLmZpcnN0TmFtZX0gJHt0aGlzLmxhc3ROYW1lfWA7CiAgICAgICAgfQogIAogICAgICAgIHNldChrZXksIHZhbHVlKSB7CiAgICAgICAgICBsZXQgW2ZpcnN0TmFtZSwgbGFzdE5hbWVdID0gdmFsdWUuc3BsaXQoJyAnKTsKICAKICAgICAgICAgIHNldCh0aGlzLCAnZmlyc3ROYW1lJywgZmlyc3ROYW1lKTsKICAgICAgICAgIHNldCh0aGlzLCAnbGFzdE5hbWUnLCBsYXN0TmFtZSk7CiAgCiAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgfQogICAgICB9KQogICAgfSk7CiAgCiAgICBsZXQgdG9tID0gUGVyc29uLmNyZWF0ZSh7CiAgICAgIGZpcnN0TmFtZTogJ1RvbScsCiAgICAgIGxhc3ROYW1lOiAnRGFsZScKICAgIH0pOwogIAogICAgdG9tLmdldCgnZnVsbE5hbWUnKSAvLyAnVG9tIERhbGUnCiAgICBgYGAKICAKICAgIFlvdSBjYW4gb3ZlcndyaXRlIGNvbXB1dGVkIHByb3BlcnR5IHdpdGhvdXQgc2V0dGVycyB3aXRoIGEgbm9ybWFsIHByb3BlcnR5IChubwogICAgbG9uZ2VyIGNvbXB1dGVkKSB0aGF0IHdvbid0IGNoYW5nZSBpZiBkZXBlbmRlbmNpZXMgY2hhbmdlLiBZb3UgY2FuIGFsc28gbWFyawogICAgY29tcHV0ZWQgcHJvcGVydHkgYXMgYC5yZWFkT25seSgpYCBhbmQgYmxvY2sgYWxsIGF0dGVtcHRzIHRvIHNldCBpdC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGNvbXB1dGVkLCBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGNsYXNzIFBlcnNvbiB7CiAgICAgIGNvbnN0cnVjdG9yKGZpcnN0TmFtZSwgbGFzdE5hbWUpIHsKICAgICAgICBzZXQodGhpcywgJ2ZpcnN0TmFtZScsIGZpcnN0TmFtZSk7CiAgICAgICAgc2V0KHRoaXMsICdsYXN0TmFtZScsIGxhc3ROYW1lKTsKICAgICAgfQogIAogICAgICBAY29tcHV0ZWQoJ2ZpcnN0TmFtZScsICdsYXN0TmFtZScpLnJlYWRPbmx5KCkKICAgICAgZ2V0IGZ1bGxOYW1lKCkgewogICAgICAgIHJldHVybiBgJHt0aGlzLmZpcnN0TmFtZX0gJHt0aGlzLmxhc3ROYW1lfWA7CiAgICAgIH0KICAgIH0pOwogIAogICAgbGV0IHBlcnNvbiA9IG5ldyBQZXJzb24oKTsKICAgIHBlcnNvbi5zZXQoJ2Z1bGxOYW1lJywgJ1BldGVyIFdhZ2VuZXQnKTsgLy8gVW5jYXVnaHQgRXJyb3I6IENhbm5vdCBzZXQgcmVhZC1vbmx5IHByb3BlcnR5ICJmdWxsTmFtZSIgb24gb2JqZWN0OiA8KC4uLik6ZW1iZXJYWFg+CiAgICBgYGAKICAKICAgIEFkZGl0aW9uYWwgcmVzb3VyY2VzOgogICAgLSBbRGVjb3JhdG9ycyBSRkNdKGh0dHBzOi8vZ2l0aHViLmNvbS9lbWJlcmpzL3JmY3MvYmxvYi9tYXN0ZXIvdGV4dC8wNDA4LWRlY29yYXRvcnMubWQpCiAgICAtIFtOZXcgQ1Agc3ludGF4IFJGQ10oaHR0cHM6Ly9naXRodWIuY29tL2VtYmVyanMvcmZjcy9ibG9iL21hc3Rlci90ZXh0LzAwMTEtaW1wcm92ZWQtY3Atc3ludGF4Lm1kKQogICAgLSBbTmV3IGNvbXB1dGVkIHN5bnRheCBleHBsYWluZWQgaW4gIkVtYmVyIDEuMTIgcmVsZWFzZWQiIF0oaHR0cHM6Ly9lbWJlcmpzLmNvbS9ibG9nLzIwMTUvMDUvMTMvZW1iZXItMS0xMi1yZWxlYXNlZC5odG1sI3RvY19uZXctY29tcHV0ZWQtc3ludGF4KQogIAogICAgQGNsYXNzIENvbXB1dGVkUHJvcGVydHkKICAgIEBwdWJsaWMKICAqLwoKCiAgdmFyIENvbXB1dGVkUHJvcGVydHkgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NvbXB1dGVkRGVzY3JpcHRvcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKENvbXB1dGVkUHJvcGVydHksIF9Db21wdXRlZERlc2NyaXB0b3IpOwoKICAgIGZ1bmN0aW9uIENvbXB1dGVkUHJvcGVydHkoYXJncykgewogICAgICB2YXIgX3RoaXM7CgogICAgICBfdGhpcyA9IF9Db21wdXRlZERlc2NyaXB0b3IuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpcy5fdm9sYXRpbGUgPSBmYWxzZTsKICAgICAgX3RoaXMuX3JlYWRPbmx5ID0gZmFsc2U7CiAgICAgIF90aGlzLl9zdXNwZW5kZWQgPSB1bmRlZmluZWQ7CiAgICAgIF90aGlzLl9oYXNDb25maWcgPSBmYWxzZTsKICAgICAgX3RoaXMuX2dldHRlciA9IHVuZGVmaW5lZDsKICAgICAgX3RoaXMuX3NldHRlciA9IHVuZGVmaW5lZDsKICAgICAgdmFyIG1heWJlQ29uZmlnID0gYXJnc1thcmdzLmxlbmd0aCAtIDFdOwoKICAgICAgaWYgKHR5cGVvZiBtYXliZUNvbmZpZyA9PT0gJ2Z1bmN0aW9uJyB8fCBtYXliZUNvbmZpZyAhPT0gbnVsbCAmJiB0eXBlb2YgbWF5YmVDb25maWcgPT09ICdvYmplY3QnKSB7CiAgICAgICAgX3RoaXMuX2hhc0NvbmZpZyA9IHRydWU7CiAgICAgICAgdmFyIGNvbmZpZyA9IGFyZ3MucG9wKCk7CgogICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICAoZmFsc2UgJiYgISghaXNDbGFzc2ljRGVjb3JhdG9yKGNvbmZpZykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byBwYXNzIGEgY29tcHV0ZWQgcHJvcGVydHkgaW5zdGFuY2UgdG8gY29tcHV0ZWQoKS4gQ29tcHV0ZWQgcHJvcGVydHkgaW5zdGFuY2VzIGFyZSBkZWNvcmF0b3IgZnVuY3Rpb25zLCBhbmQgY2Fubm90IGJlIHBhc3NlZCB0byBjb21wdXRlZCgpIGJlY2F1c2UgdGhleSBjYW5ub3QgYmUgdHVybmVkIGludG8gZGVjb3JhdG9ycyB0d2ljZSIsICFpc0NsYXNzaWNEZWNvcmF0b3IoY29uZmlnKSkpOwogICAgICAgICAgX3RoaXMuX2dldHRlciA9IGNvbmZpZzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFyIG9iamVjdENvbmZpZyA9IGNvbmZpZzsKICAgICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBvYmplY3RDb25maWcgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KG9iamVjdENvbmZpZykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnY29tcHV0ZWQgZXhwZWN0cyBhIGZ1bmN0aW9uIG9yIGFuIG9iamVjdCBhcyBsYXN0IGFyZ3VtZW50LicsIHR5cGVvZiBvYmplY3RDb25maWcgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KG9iamVjdENvbmZpZykpKTsKICAgICAgICAgIChmYWxzZSAmJiAhKE9iamVjdC5rZXlzKG9iamVjdENvbmZpZykuZXZlcnkoZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgICByZXR1cm4ga2V5ID09PSAnZ2V0JyB8fCBrZXkgPT09ICdzZXQnOwogICAgICAgICAgfSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ29uZmlnIG9iamVjdCBwYXNzZWQgdG8gY29tcHV0ZWQgY2FuIG9ubHkgY29udGFpbiBgZ2V0YCBhbmQgYHNldGAga2V5cy4nLCBPYmplY3Qua2V5cyhvYmplY3RDb25maWcpLmV2ZXJ5KGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgICAgcmV0dXJuIGtleSA9PT0gJ2dldCcgfHwga2V5ID09PSAnc2V0JzsKICAgICAgICAgIH0pKSk7CiAgICAgICAgICAoZmFsc2UgJiYgIShCb29sZWFuKG9iamVjdENvbmZpZy5nZXQpIHx8IEJvb2xlYW4ob2JqZWN0Q29uZmlnLnNldCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ29tcHV0ZWQgcHJvcGVydGllcyBtdXN0IHJlY2VpdmUgYSBnZXR0ZXIgb3IgYSBzZXR0ZXIsIHlvdSBwYXNzZWQgbm9uZS4nLCBCb29sZWFuKG9iamVjdENvbmZpZy5nZXQpIHx8IEJvb2xlYW4ob2JqZWN0Q29uZmlnLnNldCkpKTsKICAgICAgICAgIF90aGlzLl9nZXR0ZXIgPSBvYmplY3RDb25maWcuZ2V0IHx8IG5vb3A7CiAgICAgICAgICBfdGhpcy5fc2V0dGVyID0gb2JqZWN0Q29uZmlnLnNldDsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChhcmdzLmxlbmd0aCA+IDApIHsKICAgICAgICB2YXIgX3RoaXMyOwoKICAgICAgICAoX3RoaXMyID0gX3RoaXMpLl9wcm9wZXJ0eS5hcHBseShfdGhpczIsIGFyZ3MpOwogICAgICB9CgogICAgICByZXR1cm4gX3RoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzcgPSBDb21wdXRlZFByb3BlcnR5LnByb3RvdHlwZTsKCiAgICBfcHJvdG83LnNldHVwID0gZnVuY3Rpb24gc2V0dXAob2JqLCBrZXlOYW1lLCBwcm9wZXJ0eURlc2MsIG1ldGEkJDEpIHsKICAgICAgX0NvbXB1dGVkRGVzY3JpcHRvci5wcm90b3R5cGUuc2V0dXAuY2FsbCh0aGlzLCBvYmosIGtleU5hbWUsIHByb3BlcnR5RGVzYywgbWV0YSQkMSk7CgogICAgICAoZmFsc2UgJiYgISghKHByb3BlcnR5RGVzYyAmJiB0eXBlb2YgcHJvcGVydHlEZXNjLnZhbHVlID09PSAnZnVuY3Rpb24nKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJAY29tcHV0ZWQgY2FuIG9ubHkgYmUgdXNlZCBvbiBhY2Nlc3NvcnMgb3IgZmllbGRzLCBhdHRlbXB0ZWQgdG8gdXNlIGl0IHdpdGggIiArIGtleU5hbWUgKyAiIGJ1dCB0aGF0IHdhcyBhIG1ldGhvZC4gVHJ5IGNvbnZlcnRpbmcgaXQgdG8gYSBnZXR0ZXIgKGUuZy4gYGdldCAiICsga2V5TmFtZSArICIoKSB7fWApIiwgIShwcm9wZXJ0eURlc2MgJiYgdHlwZW9mIHByb3BlcnR5RGVzYy52YWx1ZSA9PT0gJ2Z1bmN0aW9uJykpKTsKICAgICAgKGZhbHNlICYmICEoIXByb3BlcnR5RGVzYyB8fCAhcHJvcGVydHlEZXNjLmluaXRpYWxpemVyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkBjb21wdXRlZCBjYW4gb25seSBiZSB1c2VkIG9uIGVtcHR5IGZpZWxkcy4gIiArIGtleU5hbWUgKyAiIGhhcyBhbiBpbml0aWFsIHZhbHVlIChlLmcuIGAiICsga2V5TmFtZSArICIgPSBzb21lVmFsdWVgKSIsICFwcm9wZXJ0eURlc2MgfHwgIXByb3BlcnR5RGVzYy5pbml0aWFsaXplcikpOwogICAgICAoZmFsc2UgJiYgISghKHRoaXMuX2hhc0NvbmZpZyAmJiBwcm9wZXJ0eURlc2MgJiYgKHR5cGVvZiBwcm9wZXJ0eURlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBwcm9wZXJ0eURlc2Muc2V0ID09PSAnZnVuY3Rpb24nKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQXR0ZW1wdGVkIHRvIGFwcGx5IGEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCBhbHJlYWR5IGhhcyBhIGdldHRlci9zZXR0ZXIgdG8gYSAiICsga2V5TmFtZSArICIsIGJ1dCBpdCBpcyBhIG1ldGhvZCBvciBhbiBhY2Nlc3Nvci4gSWYgeW91IHBhc3NlZCBAY29tcHV0ZWQgYSBmdW5jdGlvbiBvciBnZXR0ZXIvc2V0dGVyIChlLmcuIGBAY29tcHV0ZWQoeyBnZXQoKSB7IC4uLiB9IH0pYCksIHRoZW4gaXQgbXVzdCBiZSBhcHBsaWVkIHRvIGEgZmllbGQiLCAhKHRoaXMuX2hhc0NvbmZpZyAmJiBwcm9wZXJ0eURlc2MgJiYgKHR5cGVvZiBwcm9wZXJ0eURlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBwcm9wZXJ0eURlc2Muc2V0ID09PSAnZnVuY3Rpb24nKSkpKTsKCiAgICAgIGlmICh0aGlzLl9oYXNDb25maWcgPT09IGZhbHNlKSB7CiAgICAgICAgKGZhbHNlICYmICEocHJvcGVydHlEZXNjICYmICh0eXBlb2YgcHJvcGVydHlEZXNjLmdldCA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgcHJvcGVydHlEZXNjLnNldCA9PT0gJ2Z1bmN0aW9uJykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQXR0ZW1wdGVkIHRvIHVzZSBAY29tcHV0ZWQgb24gIiArIGtleU5hbWUgKyAiLCBidXQgaXQgZGlkIG5vdCBoYXZlIGEgZ2V0dGVyIG9yIGEgc2V0dGVyLiBZb3UgbXVzdCBlaXRoZXIgcGFzcyBhIGdldCBhIGZ1bmN0aW9uIG9yIGdldHRlci9zZXR0ZXIgdG8gQGNvbXB1dGVkIGRpcmVjdGx5IChlLmcuIGBAY29tcHV0ZWQoeyBnZXQoKSB7IC4uLiB9IH0pYCkgb3IgYXBwbHkgQGNvbXB1dGVkIGRpcmVjdGx5IHRvIGEgZ2V0dGVyL3NldHRlciIsIHByb3BlcnR5RGVzYyAmJiAodHlwZW9mIHByb3BlcnR5RGVzYy5nZXQgPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIHByb3BlcnR5RGVzYy5zZXQgPT09ICdmdW5jdGlvbicpKSk7CiAgICAgICAgdmFyIF9nZXQgPSBwcm9wZXJ0eURlc2MuZ2V0LAogICAgICAgICAgICBzZXQkJDEgPSBwcm9wZXJ0eURlc2Muc2V0OwoKICAgICAgICBpZiAoX2dldCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB0aGlzLl9nZXR0ZXIgPSBfZ2V0OwogICAgICAgIH0KCiAgICAgICAgaWYgKHNldCQkMSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB0aGlzLl9zZXR0ZXIgPSBmdW5jdGlvbiBzZXR0ZXJXcmFwcGVyKF9rZXksIHZhbHVlJCQxKSB7CiAgICAgICAgICAgIHZhciByZXQgPSBzZXQkJDEuY2FsbCh0aGlzLCB2YWx1ZSQkMSk7CgogICAgICAgICAgICBpZiAoX2dldCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiByZXQgPT09ICd1bmRlZmluZWQnID8gX2dldC5jYWxsKHRoaXMpIDogcmV0OwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBDYWxsIG9uIGEgY29tcHV0ZWQgcHJvcGVydHkgdG8gc2V0IGl0IGludG8gbm9uLWNhY2hlZCBtb2RlLiBXaGVuIGluIHRoaXMKICAgICAgbW9kZSB0aGUgY29tcHV0ZWQgcHJvcGVydHkgd2lsbCBub3QgYXV0b21hdGljYWxseSBjYWNoZSB0aGUgcmV0dXJuIHZhbHVlLgogICAgICBJdCBhbHNvIGRvZXMgbm90IGF1dG9tYXRpY2FsbHkgZmlyZSBhbnkgY2hhbmdlIGV2ZW50cy4gWW91IG11c3QgbWFudWFsbHkgbm90aWZ5CiAgICAgIGFueSBjaGFuZ2VzIGlmIHlvdSB3YW50IHRvIG9ic2VydmUgdGhpcyBwcm9wZXJ0eS4KICAgICAgRGVwZW5kZW5jeSBrZXlzIGhhdmUgbm8gZWZmZWN0IG9uIHZvbGF0aWxlIHByb3BlcnRpZXMgYXMgdGhleSBhcmUgZm9yIGNhY2hlCiAgICAgIGludmFsaWRhdGlvbiBhbmQgbm90aWZpY2F0aW9uIHdoZW4gY2FjaGVkIHZhbHVlIGlzIGludmFsaWRhdGVkLgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICBsZXQgb3V0c2lkZVNlcnZpY2UgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAgIHZhbHVlOiBjb21wdXRlZChmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiBPdXRzaWRlU2VydmljZS5nZXRWYWx1ZSgpOwogICAgICAgIH0pLnZvbGF0aWxlKCkKICAgICAgfSkuY3JlYXRlKCk7CiAgICAgIGBgYAogICAgICBAbWV0aG9kIHZvbGF0aWxlCiAgICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IHRoaXMKICAgICAgQGNoYWluYWJsZQogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90bzcudm9sYXRpbGUgPSBmdW5jdGlvbiB2b2xhdGlsZSgpIHsKICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgnU2V0dGluZyBhIGNvbXB1dGVkIHByb3BlcnR5IGFzIHZvbGF0aWxlIGhhcyBiZWVuIGRlcHJlY2F0ZWQuIEluc3RlYWQsIGNvbnNpZGVyIHVzaW5nIGEgbmF0aXZlIGdldHRlciB3aXRoIG5hdGl2ZSBjbGFzcyBzeW50YXguJywgZmFsc2UsIHsKICAgICAgICBpZDogJ2NvbXB1dGVkLXByb3BlcnR5LnZvbGF0aWxlJywKICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY19jb21wdXRlZC1wcm9wZXJ0eS12b2xhdGlsZScKICAgICAgfSkpOwogICAgICB0aGlzLl92b2xhdGlsZSA9IHRydWU7CiAgICB9CiAgICAvKioKICAgICAgQ2FsbCBvbiBhIGNvbXB1dGVkIHByb3BlcnR5IHRvIHNldCBpdCBpbnRvIHJlYWQtb25seSBtb2RlLiBXaGVuIGluIHRoaXMKICAgICAgbW9kZSB0aGUgY29tcHV0ZWQgcHJvcGVydHkgd2lsbCB0aHJvdyBhbiBlcnJvciB3aGVuIHNldC4KICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgRW1iZXJPYmplY3QsIHsgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgbGV0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgICAgZ3VpZDogY29tcHV0ZWQoZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gJ2d1aWQtZ3VpZC1ndWlkJzsKICAgICAgICB9KS5yZWFkT25seSgpCiAgICAgIH0pOwogICAgICBsZXQgcGVyc29uID0gUGVyc29uLmNyZWF0ZSgpOwogICAgICBwZXJzb24uc2V0KCdndWlkJywgJ25ldy1ndWlkJyk7IC8vIHdpbGwgdGhyb3cgYW4gZXhjZXB0aW9uCiAgICAgIGBgYAogICAgICBAbWV0aG9kIHJlYWRPbmx5CiAgICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IHRoaXMKICAgICAgQGNoYWluYWJsZQogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90bzcucmVhZE9ubHkgPSBmdW5jdGlvbiByZWFkT25seSgpIHsKICAgICAgdGhpcy5fcmVhZE9ubHkgPSB0cnVlOwogICAgICAoZmFsc2UgJiYgISghKHRoaXMuX3JlYWRPbmx5ICYmIHRoaXMuX3NldHRlciAmJiB0aGlzLl9zZXR0ZXIgIT09IHRoaXMuX2dldHRlcikpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ29tcHV0ZWQgcHJvcGVydGllcyB0aGF0IGRlZmluZSBhIHNldHRlciB1c2luZyB0aGUgbmV3IHN5bnRheCBjYW5ub3QgYmUgcmVhZC1vbmx5JywgISh0aGlzLl9yZWFkT25seSAmJiB0aGlzLl9zZXR0ZXIgJiYgdGhpcy5fc2V0dGVyICE9PSB0aGlzLl9nZXR0ZXIpKSk7CiAgICB9CiAgICAvKioKICAgICAgU2V0cyB0aGUgZGVwZW5kZW50IGtleXMgb24gdGhpcyBjb21wdXRlZCBwcm9wZXJ0eS4gUGFzcyBhbnkgbnVtYmVyIG9mCiAgICAgIGFyZ3VtZW50cyBjb250YWluaW5nIGtleSBwYXRocyB0aGF0IHRoaXMgY29tcHV0ZWQgcHJvcGVydHkgZGVwZW5kcyBvbi4KICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgRW1iZXJPYmplY3QsIHsgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgbGV0IFByZXNpZGVudCA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgICAgZnVsbE5hbWU6IGNvbXB1dGVkKCdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnLCBmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiB0aGlzLmdldCgnZmlyc3ROYW1lJykgKyAnICcgKyB0aGlzLmdldCgnbGFzdE5hbWUnKTsKICAgICAgICAgIC8vIFRlbGwgRW1iZXIgdGhhdCB0aGlzIGNvbXB1dGVkIHByb3BlcnR5IGRlcGVuZHMgb24gZmlyc3ROYW1lCiAgICAgICAgICAvLyBhbmQgbGFzdE5hbWUKICAgICAgICB9KQogICAgICB9KTsKICAgICAgbGV0IHByZXNpZGVudCA9IFByZXNpZGVudC5jcmVhdGUoewogICAgICAgIGZpcnN0TmFtZTogJ0JhcmFjaycsCiAgICAgICAgbGFzdE5hbWU6ICdPYmFtYScKICAgICAgfSk7CiAgICAgIHByZXNpZGVudC5nZXQoJ2Z1bGxOYW1lJyk7IC8vICdCYXJhY2sgT2JhbWEnCiAgICAgIGBgYAogICAgICBAbWV0aG9kIHByb3BlcnR5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBwYXRoKiB6ZXJvIG9yIG1vcmUgcHJvcGVydHkgcGF0aHMKICAgICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gdGhpcwogICAgICBAY2hhaW5hYmxlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvNy5wcm9wZXJ0eSA9IGZ1bmN0aW9uIHByb3BlcnR5KCkgewogICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdTZXR0aW5nIGRlcGVuZGVuY3kga2V5cyB1c2luZyB0aGUgYC5wcm9wZXJ0eSgpYCBtb2RpZmllciBoYXMgYmVlbiBkZXByZWNhdGVkLiBQYXNzIHRoZSBkZXBlbmRlbmN5IGtleXMgZGlyZWN0bHkgdG8gY29tcHV0ZWQgYXMgYXJndW1lbnRzIGluc3RlYWQuIElmIHlvdSBhcmUgdXNpbmcgYC5wcm9wZXJ0eSgpYCBvbiBhIGNvbXB1dGVkIHByb3BlcnR5IG1hY3JvLCBjb25zaWRlciByZWZhY3RvcmluZyB5b3VyIG1hY3JvIHRvIHJlY2VpdmUgYWRkaXRpb25hbCBkZXBlbmRlbnQga2V5cyBpbiBpdHMgaW5pdGlhbCBkZWNsYXJhdGlvbi4nLCBmYWxzZSwgewogICAgICAgIGlkOiAnY29tcHV0ZWQtcHJvcGVydHkucHJvcGVydHknLAogICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2NvbXB1dGVkLXByb3BlcnR5LXByb3BlcnR5JwogICAgICB9KSk7CgogICAgICB0aGlzLl9wcm9wZXJ0eS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfTsKCiAgICBfcHJvdG83Ll9wcm9wZXJ0eSA9IGZ1bmN0aW9uIF9wcm9wZXJ0eSgpIHsKICAgICAgdmFyIGFyZ3MgPSBbXTsKCiAgICAgIGZ1bmN0aW9uIGFkZEFyZyhwcm9wZXJ0eSkgewogICAgICAgIChmYWxzZSAmJiAoMCwgX2RlYnVnLndhcm4pKCJEZXBlbmRlbnQga2V5cyBjb250YWluaW5nIEBlYWNoIG9ubHkgd29yayBvbmUgbGV2ZWwgZGVlcC4gIiArICgiWW91IHVzZWQgdGhlIGtleSBcIiIgKyBwcm9wZXJ0eSArICJcIiB3aGljaCBpcyBpbnZhbGlkLiAiKSArICJQbGVhc2UgY3JlYXRlIGFuIGludGVybWVkaWFyeSBjb21wdXRlZCBwcm9wZXJ0eS4iLCBERUVQX0VBQ0hfUkVHRVgudGVzdChwcm9wZXJ0eSkgPT09IGZhbHNlLCB7CiAgICAgICAgICBpZDogJ2VtYmVyLW1ldGFsLmNvbXB1dGVkLWRlZXAtZWFjaCcKICAgICAgICB9KSk7CiAgICAgICAgYXJncy5wdXNoKHByb3BlcnR5KTsKICAgICAgfQoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsKICAgICAgICBleHBhbmRQcm9wZXJ0aWVzKGkgPCAwIHx8IGFyZ3VtZW50cy5sZW5ndGggPD0gaSA/IHVuZGVmaW5lZCA6IGFyZ3VtZW50c1tpXSwgYWRkQXJnKTsKICAgICAgfQoKICAgICAgdGhpcy5fZGVwZW5kZW50S2V5cyA9IGFyZ3M7CiAgICB9CiAgICAvKioKICAgICAgSW4gc29tZSBjYXNlcywgeW91IG1heSB3YW50IHRvIGFubm90YXRlIGNvbXB1dGVkIHByb3BlcnRpZXMgd2l0aCBhZGRpdGlvbmFsCiAgICAgIG1ldGFkYXRhIGFib3V0IGhvdyB0aGV5IGZ1bmN0aW9uIG9yIHdoYXQgdmFsdWVzIHRoZXkgb3BlcmF0ZSBvbi4gRm9yIGV4YW1wbGUsCiAgICAgIGNvbXB1dGVkIHByb3BlcnR5IGZ1bmN0aW9ucyBtYXkgY2xvc2Ugb3ZlciB2YXJpYWJsZXMgdGhhdCBhcmUgdGhlbiBubyBsb25nZXIKICAgICAgYXZhaWxhYmxlIGZvciBpbnRyb3NwZWN0aW9uLgogICAgICBZb3UgY2FuIHBhc3MgYSBoYXNoIG9mIHRoZXNlIHZhbHVlcyB0byBhIGNvbXB1dGVkIHByb3BlcnR5IGxpa2UgdGhpczoKICAgICAgYGBgCiAgICAgIGltcG9ydCB7IGNvbXB1dGVkIH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgIGltcG9ydCBQZXJzb24gZnJvbSAnbXktYXBwL3V0aWxzL3BlcnNvbic7CiAgICAgIHBlcnNvbjogY29tcHV0ZWQoZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IHBlcnNvbklkID0gdGhpcy5nZXQoJ3BlcnNvbklkJyk7CiAgICAgICAgcmV0dXJuIFBlcnNvbi5jcmVhdGUoeyBpZDogcGVyc29uSWQgfSk7CiAgICAgIH0pLm1ldGEoeyB0eXBlOiBQZXJzb24gfSkKICAgICAgYGBgCiAgICAgIFRoZSBoYXNoIHRoYXQgeW91IHBhc3MgdG8gdGhlIGBtZXRhKClgIGZ1bmN0aW9uIHdpbGwgYmUgc2F2ZWQgb24gdGhlCiAgICAgIGNvbXB1dGVkIHByb3BlcnR5IGRlc2NyaXB0b3IgdW5kZXIgdGhlIGBfbWV0YWAga2V5LiBFbWJlciBydW50aW1lCiAgICAgIGV4cG9zZXMgYSBwdWJsaWMgQVBJIGZvciByZXRyaWV2aW5nIHRoZXNlIHZhbHVlcyBmcm9tIGNsYXNzZXMsCiAgICAgIHZpYSB0aGUgYG1ldGFGb3JQcm9wZXJ0eSgpYCBmdW5jdGlvbi4KICAgICAgQG1ldGhvZCBtZXRhCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBtZXRhCiAgICAgIEBjaGFpbmFibGUKICAgICAgQHB1YmxpYwogICAgKi8KICAgIC8vIGludmFsaWRhdGUgY2FjaGUgd2hlbiBDUCBrZXkgY2hhbmdlcwogICAgOwoKICAgIF9wcm90bzcuZGlkQ2hhbmdlID0gZnVuY3Rpb24gZGlkQ2hhbmdlKG9iaiwga2V5TmFtZSkgewogICAgICAvLyBfc3VzcGVuZGVkIGlzIHNldCB2aWEgYSBDUC5zZXQgdG8gZW5zdXJlIHdlIGRvbid0IGNsZWFyCiAgICAgIC8vIHRoZSBjYWNoZWQgdmFsdWUgc2V0IGJ5IHRoZSBzZXR0ZXIKICAgICAgaWYgKHRoaXMuX3ZvbGF0aWxlIHx8IHRoaXMuX3N1c3BlbmRlZCA9PT0gb2JqKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIGRvbid0IGNyZWF0ZSBvYmplY3RzIGp1c3QgdG8gaW52YWxpZGF0ZQoKCiAgICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkob2JqKTsKCiAgICAgIGlmIChtZXRhJCQxID09PSBudWxsIHx8IG1ldGEkJDEuc291cmNlICE9PSBvYmopIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBjYWNoZSA9IHBlZWtDYWNoZUZvcihvYmopOwoKICAgICAgaWYgKGNhY2hlICE9PSB1bmRlZmluZWQgJiYgY2FjaGUuZGVsZXRlKGtleU5hbWUpKSB7CiAgICAgICAgcmVtb3ZlRGVwZW5kZW50S2V5cyh0aGlzLCBvYmosIGtleU5hbWUsIG1ldGEkJDEpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzcuZ2V0ID0gZnVuY3Rpb24gZ2V0KG9iaiwga2V5TmFtZSkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIGlmICh0aGlzLl92b2xhdGlsZSkgewogICAgICAgIHJldHVybiB0aGlzLl9nZXR0ZXIuY2FsbChvYmosIGtleU5hbWUpOwogICAgICB9CgogICAgICB2YXIgY2FjaGUgPSBnZXRDYWNoZUZvcihvYmopOwogICAgICB7CiAgICAgICAgdmFyIHByb3BlcnR5VGFnID0gdGFnRm9yUHJvcGVydHkob2JqLCBrZXlOYW1lKTsKICAgICAgICB2YXIgcmV0OwoKICAgICAgICBpZiAoY2FjaGUuaGFzKGtleU5hbWUpICYmICgwLCBfcmVmZXJlbmNlLnZhbGlkYXRlKShwcm9wZXJ0eVRhZywgZ2V0TGFzdFJldmlzaW9uRm9yKG9iaiwga2V5TmFtZSkpKSB7CiAgICAgICAgICByZXQgPSBjYWNoZS5nZXQoa2V5TmFtZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vIEZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSwgd2Ugb25seSB0aHJvdyBpZiB0aGUgQ1AgaGFzIGFueSBkZXBlbmRlbmNpZXMuIENQcyB3aXRob3V0IGRlcGVuZGVuY2llcwogICAgICAgICAgLy8gc2hvdWxkIGJlIGFsbG93ZWQsIGV2ZW4gYWZ0ZXIgdGhlIG9iamVjdCBoYXMgYmVlbiBkZXN0cm95ZWQsIHdoaWNoIGlzIHdoeSB3ZSBjaGVjayBfZGVwZW5kZW50S2V5cy4KICAgICAgICAgIChmYWxzZSAmJiAhKHRoaXMuX2RlcGVuZGVudEtleXMgPT09IHVuZGVmaW5lZCB8fCAhKDAsIF9tZXRhMi5tZXRhKShvYmopLmlzTWV0YURlc3Ryb3llZCgpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF0dGVtcHRlZCB0byBhY2Nlc3MgdGhlIGNvbXB1dGVkICIgKyBvYmogKyAiLiIgKyBrZXlOYW1lICsgIiBvbiBhIGRlc3Ryb3llZCBvYmplY3QsIHdoaWNoIGlzIG5vdCBhbGxvd2VkIiwgdGhpcy5fZGVwZW5kZW50S2V5cyA9PT0gdW5kZWZpbmVkIHx8ICEoMCwgX21ldGEyLm1ldGEpKG9iaikuaXNNZXRhRGVzdHJveWVkKCkpKTsKICAgICAgICAgIHZhciB1cHN0cmVhbVRhZyA9IHVuZGVmaW5lZDsKCiAgICAgICAgICBpZiAodGhpcy5fYXV0byA9PT0gdHJ1ZSkgewogICAgICAgICAgICB1cHN0cmVhbVRhZyA9IHRyYWNrKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICByZXQgPSBfdGhpczMuX2dldHRlci5jYWxsKG9iaiwga2V5TmFtZSk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgLy8gQ3JlYXRlIGEgdHJhY2tlciB0aGF0IGFic29yYnMgYW55IHRyYWNrYWJsZSBhY3Rpb25zIGluc2lkZSB0aGUgQ1AKICAgICAgICAgICAgdW50cmFjayhmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgcmV0ID0gX3RoaXMzLl9nZXR0ZXIuY2FsbChvYmosIGtleU5hbWUpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAodGhpcy5fZGVwZW5kZW50S2V5cyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHZhciB0YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShnZXRDaGFpblRhZ3NGb3JLZXlzKG9iaiwgdGhpcy5fZGVwZW5kZW50S2V5cykpOwogICAgICAgICAgICB1cHN0cmVhbVRhZyA9IHVwc3RyZWFtVGFnID09PSB1bmRlZmluZWQgPyB0YWcgOiAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShbdXBzdHJlYW1UYWcsIHRhZ10pOwogICAgICAgICAgfQoKICAgICAgICAgIGlmICh1cHN0cmVhbVRhZyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkocHJvcGVydHlUYWcsIHVwc3RyZWFtVGFnKTsKICAgICAgICAgIH0KCiAgICAgICAgICBzZXRMYXN0UmV2aXNpb25Gb3Iob2JqLCBrZXlOYW1lLCAoMCwgX3JlZmVyZW5jZS52YWx1ZSkocHJvcGVydHlUYWcpKTsKICAgICAgICAgIGNhY2hlLnNldChrZXlOYW1lLCByZXQpOwogICAgICAgICAgZmluaXNoTGF6eUNoYWlucyhvYmosIGtleU5hbWUsIHJldCk7CiAgICAgICAgfQoKICAgICAgICBjb25zdW1lKHByb3BlcnR5VGFnKTsgLy8gQWRkIHRoZSB0YWcgb2YgdGhlIHJldHVybmVkIHZhbHVlIGlmIGl0IGlzIGFuIGFycmF5LCBzaW5jZSBhcnJheXMKICAgICAgICAvLyBzaG91bGQgYWx3YXlzIGNhdXNlIHVwZGF0ZXMgaWYgdGhleSBhcmUgY29uc3VtZWQgYW5kIHRoZW4gY2hhbmdlZAoKICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShyZXQpIHx8ICgwLCBfdXRpbHMuaXNFbWJlckFycmF5KShyZXQpKSB7CiAgICAgICAgICBjb25zdW1lKHRhZ0ZvclByb3BlcnR5KHJldCwgJ1tdJykpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG83LnNldCA9IGZ1bmN0aW9uIHNldChvYmosIGtleU5hbWUsIHZhbHVlJCQxKSB7CiAgICAgIGlmICh0aGlzLl9yZWFkT25seSkgewogICAgICAgIHRoaXMuX3Rocm93UmVhZE9ubHlFcnJvcihvYmosIGtleU5hbWUpOwogICAgICB9CgogICAgICBpZiAoIXRoaXMuX3NldHRlcikgewogICAgICAgIHJldHVybiB0aGlzLmNsb2JiZXJTZXQob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLl92b2xhdGlsZSkgewogICAgICAgIHJldHVybiB0aGlzLnZvbGF0aWxlU2V0KG9iaiwga2V5TmFtZSwgdmFsdWUkJDEpOwogICAgICB9CgogICAgICB7CiAgICAgICAgdmFyIHJldDsKCiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJlZ2luUHJvcGVydHlDaGFuZ2VzKCk7CiAgICAgICAgICByZXQgPSB0aGlzLl9zZXQob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgICAgICAgICBmaW5pc2hMYXp5Q2hhaW5zKG9iaiwga2V5TmFtZSwgcmV0KTsKICAgICAgICAgIHZhciBwcm9wZXJ0eVRhZyA9IHRhZ0ZvclByb3BlcnR5KG9iaiwga2V5TmFtZSk7CgogICAgICAgICAgaWYgKHRoaXMuX2RlcGVuZGVudEtleXMgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHByb3BlcnR5VGFnLCAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShnZXRDaGFpblRhZ3NGb3JLZXlzKG9iaiwgdGhpcy5fZGVwZW5kZW50S2V5cykpKTsKICAgICAgICAgIH0KCiAgICAgICAgICBzZXRMYXN0UmV2aXNpb25Gb3Iob2JqLCBrZXlOYW1lLCAoMCwgX3JlZmVyZW5jZS52YWx1ZSkocHJvcGVydHlUYWcpKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgZW5kUHJvcGVydHlDaGFuZ2VzKCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzcuX3Rocm93UmVhZE9ubHlFcnJvciA9IGZ1bmN0aW9uIF90aHJvd1JlYWRPbmx5RXJyb3Iob2JqLCBrZXlOYW1lKSB7CiAgICAgIHRocm93IG5ldyBfZXJyb3IuZGVmYXVsdCgiQ2Fubm90IHNldCByZWFkLW9ubHkgcHJvcGVydHkgXCIiICsga2V5TmFtZSArICJcIiBvbiBvYmplY3Q6ICIgKyAoMCwgX3V0aWxzLmluc3BlY3QpKG9iaikpOwogICAgfTsKCiAgICBfcHJvdG83LmNsb2JiZXJTZXQgPSBmdW5jdGlvbiBjbG9iYmVyU2V0KG9iaiwga2V5TmFtZSwgdmFsdWUkJDEpIHsKICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgiVGhlICIgKyAoMCwgX3V0aWxzLnRvU3RyaW5nKShvYmopICsgIiMiICsga2V5TmFtZSArICIgY29tcHV0ZWQgcHJvcGVydHkgd2FzIGp1c3Qgb3ZlcnJpZGVuLiBUaGlzIHJlbW92ZXMgdGhlIGNvbXB1dGVkIHByb3BlcnR5IGFuZCByZXBsYWNlcyBpdCB3aXRoIGEgcGxhaW4gdmFsdWUsIGFuZCBoYXMgYmVlbiBkZXByZWNhdGVkLiBJZiB5b3Ugd2FudCB0aGlzIGJlaGF2aW9yLCBjb25zaWRlciBkZWZpbmluZyBhIHNldHRlciB3aGljaCBkb2VzIGl0IG1hbnVhbGx5LiIsIGZhbHNlLCB7CiAgICAgICAgaWQ6ICdjb21wdXRlZC1wcm9wZXJ0eS5vdmVycmlkZScsCiAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfY29tcHV0ZWQtcHJvcGVydHktb3ZlcnJpZGUnCiAgICAgIH0pKTsKICAgICAgdmFyIGNhY2hlZFZhbHVlID0gZ2V0Q2FjaGVkVmFsdWVGb3Iob2JqLCBrZXlOYW1lKTsKICAgICAgZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCBudWxsLCBjYWNoZWRWYWx1ZSk7CgogICAgICBfc2V0MihvYmosIGtleU5hbWUsIHZhbHVlJCQxKTsKCiAgICAgIHJldHVybiB2YWx1ZSQkMTsKICAgIH07CgogICAgX3Byb3RvNy52b2xhdGlsZVNldCA9IGZ1bmN0aW9uIHZvbGF0aWxlU2V0KG9iaiwga2V5TmFtZSwgdmFsdWUkJDEpIHsKICAgICAgcmV0dXJuIHRoaXMuX3NldHRlci5jYWxsKG9iaiwga2V5TmFtZSwgdmFsdWUkJDEpOwogICAgfTsKCiAgICBfcHJvdG83LnNldFdpdGhTdXNwZW5kID0gZnVuY3Rpb24gc2V0V2l0aFN1c3BlbmQob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSkgewogICAgICB2YXIgb2xkU3VzcGVuZGVkID0gdGhpcy5fc3VzcGVuZGVkOwogICAgICB0aGlzLl9zdXNwZW5kZWQgPSBvYmo7CgogICAgICB0cnkgewogICAgICAgIHJldHVybiB0aGlzLl9zZXQob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgICAgIH0gZmluYWxseSB7CiAgICAgICAgdGhpcy5fc3VzcGVuZGVkID0gb2xkU3VzcGVuZGVkOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzcuX3NldCA9IGZ1bmN0aW9uIF9zZXQob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSkgewogICAgICB2YXIgY2FjaGUgPSBnZXRDYWNoZUZvcihvYmopOwogICAgICB2YXIgaGFkQ2FjaGVkVmFsdWUgPSBjYWNoZS5oYXMoa2V5TmFtZSk7CiAgICAgIHZhciBjYWNoZWRWYWx1ZSA9IGNhY2hlLmdldChrZXlOYW1lKTsKICAgICAgdmFyIHJldDsKICAgICAgewogICAgICAgIHNldE9ic2VydmVyU3VzcGVuZGVkKG9iaiwga2V5TmFtZSwgdHJ1ZSk7CgogICAgICAgIHRyeSB7CiAgICAgICAgICByZXQgPSB0aGlzLl9zZXR0ZXIuY2FsbChvYmosIGtleU5hbWUsIHZhbHVlJCQxLCBjYWNoZWRWYWx1ZSk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIHNldE9ic2VydmVyU3VzcGVuZGVkKG9iaiwga2V5TmFtZSwgZmFsc2UpOwogICAgICAgIH0KICAgICAgfSAvLyBhbGxvd3Mgc2V0dGVyIHRvIHJldHVybiB0aGUgc2FtZSB2YWx1ZSB0aGF0IGlzIGNhY2hlZCBhbHJlYWR5CgogICAgICBpZiAoaGFkQ2FjaGVkVmFsdWUgJiYgY2FjaGVkVmFsdWUgPT09IHJldCkgewogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0KCiAgICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5tZXRhKShvYmopOwogICAgICBjYWNoZS5zZXQoa2V5TmFtZSwgcmV0KTsKICAgICAgbm90aWZ5UHJvcGVydHlDaGFuZ2Uob2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgICAgcmV0dXJuIHJldDsKICAgIH0KICAgIC8qIGNhbGxlZCBiZWZvcmUgcHJvcGVydHkgaXMgb3ZlcnJpZGRlbiAqLwogICAgOwoKICAgIF9wcm90bzcudGVhcmRvd24gPSBmdW5jdGlvbiB0ZWFyZG93bihvYmosIGtleU5hbWUsIG1ldGEkJDEpIHsKICAgICAgaWYgKCF0aGlzLl92b2xhdGlsZSkgewogICAgICAgIHZhciBjYWNoZSA9IHBlZWtDYWNoZUZvcihvYmopOwoKICAgICAgICBpZiAoY2FjaGUgIT09IHVuZGVmaW5lZCAmJiBjYWNoZS5kZWxldGUoa2V5TmFtZSkpIHsKICAgICAgICAgIHJlbW92ZURlcGVuZGVudEtleXModGhpcywgb2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIF9Db21wdXRlZERlc2NyaXB0b3IucHJvdG90eXBlLnRlYXJkb3duLmNhbGwodGhpcywgb2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgIH07CgogICAgcmV0dXJuIENvbXB1dGVkUHJvcGVydHk7CiAgfShDb21wdXRlZERlc2NyaXB0b3IpOwoKICBfZXhwb3J0cy5Db21wdXRlZFByb3BlcnR5ID0gQ29tcHV0ZWRQcm9wZXJ0eTsKICB7CiAgICBDb21wdXRlZFByb3BlcnR5LnByb3RvdHlwZS5hdXRvID0gZnVuY3Rpb24gKCkgewogICAgICB0aGlzLl9hdXRvID0gdHJ1ZTsKICAgIH07CiAgfSAvLyBUT0RPOiBUaGlzIGNsYXNzIGNhbiBiZSBzdmVsdGVkIG9uY2UgYG1ldGFgIGhhcyBiZWVuIGRlcHJlY2F0ZWQKCiAgdmFyIENvbXB1dGVkRGVjb3JhdG9ySW1wbCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRnVuY3Rpb24pIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDb21wdXRlZERlY29yYXRvckltcGwsIF9GdW5jdGlvbik7CgogICAgZnVuY3Rpb24gQ29tcHV0ZWREZWNvcmF0b3JJbXBsKCkgewogICAgICByZXR1cm4gX0Z1bmN0aW9uLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvOCA9IENvbXB1dGVkRGVjb3JhdG9ySW1wbC5wcm90b3R5cGU7CgogICAgX3Byb3RvOC5yZWFkT25seSA9IGZ1bmN0aW9uIHJlYWRPbmx5KCkgewogICAgICBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKHRoaXMpLnJlYWRPbmx5KCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICBfcHJvdG84LnZvbGF0aWxlID0gZnVuY3Rpb24gdm9sYXRpbGUoKSB7CiAgICAgIGRlc2NyaXB0b3JGb3JEZWNvcmF0b3IodGhpcykudm9sYXRpbGUoKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9OwoKICAgIF9wcm90bzgucHJvcGVydHkgPSBmdW5jdGlvbiBwcm9wZXJ0eSgpIHsKICAgICAgdmFyIF9kZXNjcmlwdG9yRm9yRGVjb3JhdDsKCiAgICAgIChfZGVzY3JpcHRvckZvckRlY29yYXQgPSBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKHRoaXMpKS5wcm9wZXJ0eS5hcHBseShfZGVzY3JpcHRvckZvckRlY29yYXQsIGFyZ3VtZW50cyk7CgogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgX3Byb3RvOC5tZXRhID0gZnVuY3Rpb24gbWV0YShtZXRhJCQxKSB7CiAgICAgIHZhciBwcm9wID0gZGVzY3JpcHRvckZvckRlY29yYXRvcih0aGlzKTsKCiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIHByb3AuX21ldGEgfHwge307CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcHJvcC5fbWV0YSA9IG1ldGEkJDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgIH0gLy8gVE9ETzogUmVtb3ZlIHRoaXMgd2hlbiB3ZSBjYW4gcHJvdmlkZSBhbHRlcm5hdGl2ZXMgaW4gdGhlIGVjb3N5c3RlbSB0bwogICAgLy8gYWRkb25zIHN1Y2ggYXMgZW1iZXItbWFjcm8taGVscGVycyB0aGF0IHVzZSBpdC4KICAgIDsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKENvbXB1dGVkRGVjb3JhdG9ySW1wbCwgW3sKICAgICAga2V5OiAiX2dldHRlciIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKHRoaXMpLl9nZXR0ZXI7CiAgICAgIH0gLy8gVE9ETzogUmVmYWN0b3IgdGhpcywgdGhpcyBpcyBhbiBpbnRlcm5hbCBBUEkgb25seQoKICAgIH0sIHsKICAgICAga2V5OiAiZW51bWVyYWJsZSIsCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHZhbHVlJCQxKSB7CiAgICAgICAgZGVzY3JpcHRvckZvckRlY29yYXRvcih0aGlzKS5lbnVtZXJhYmxlID0gdmFsdWUkJDE7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBDb21wdXRlZERlY29yYXRvckltcGw7CiAgfSgoMCwgX2VtYmVyQmFiZWwud3JhcE5hdGl2ZVN1cGVyKShGdW5jdGlvbikpOwoKICBmdW5jdGlvbiBjb21wdXRlZCgpIHsKICAgIGZvciAodmFyIF9sZW4zID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuMyksIF9rZXk0ID0gMDsgX2tleTQgPCBfbGVuMzsgX2tleTQrKykgewogICAgICBhcmdzW19rZXk0XSA9IGFyZ3VtZW50c1tfa2V5NF07CiAgICB9CgogICAgKGZhbHNlICYmICEoIShpc0VsZW1lbnREZXNjcmlwdG9yKGFyZ3Muc2xpY2UoMCwgMykpICYmIGFyZ3MubGVuZ3RoID09PSA1ICYmIGFyZ3NbNF0gPT09IHRydWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkBjb21wdXRlZCBjYW4gb25seSBiZSB1c2VkIGRpcmVjdGx5IGFzIGEgbmF0aXZlIGRlY29yYXRvci4gSWYgeW91J3JlIHVzaW5nIHRyYWNrZWQgaW4gY2xhc3NpYyBjbGFzc2VzLCBhZGQgcGFyZW50aGVzaXMgdG8gY2FsbCBpdCBsaWtlIGEgZnVuY3Rpb246IGNvbXB1dGVkKCkiLCAhKGlzRWxlbWVudERlc2NyaXB0b3IoYXJncy5zbGljZSgwLCAzKSkgJiYgYXJncy5sZW5ndGggPT09IDUgJiYgYXJnc1s0XSA9PT0gdHJ1ZSkpKTsKCiAgICBpZiAoaXNFbGVtZW50RGVzY3JpcHRvcihhcmdzKSkgewogICAgICAoZmFsc2UgJiYgIShCb29sZWFuKHRydWUKICAgICAgLyogRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUICovCiAgICAgICkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnTmF0aXZlIGRlY29yYXRvcnMgYXJlIG5vdCBlbmFibGVkIHdpdGhvdXQgdGhlIEVNQkVSX05BVElWRV9ERUNPUkFUT1JfU1VQUE9SVCBmbGFnLiBJZiB5b3UgYXJlIHVzaW5nIGNvbXB1dGVkIGluIGEgY2xhc3NpYyBjbGFzcywgYWRkIHBhcmVudGhlc2lzIHRvIGl0OiBjb21wdXRlZCgpJywgQm9vbGVhbih0cnVlKSkpOwogICAgICB2YXIgZGVjb3JhdG9yID0gbWFrZUNvbXB1dGVkRGVjb3JhdG9yKG5ldyBDb21wdXRlZFByb3BlcnR5KFtdKSwgQ29tcHV0ZWREZWNvcmF0b3JJbXBsKTsKICAgICAgcmV0dXJuIGRlY29yYXRvcihhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdKTsKICAgIH0KCiAgICByZXR1cm4gbWFrZUNvbXB1dGVkRGVjb3JhdG9yKG5ldyBDb21wdXRlZFByb3BlcnR5KGFyZ3MpLCBDb21wdXRlZERlY29yYXRvckltcGwpOwogIH0KICAvKioKICAgIEFsbG93cyBjaGVja2luZyBpZiBhIGdpdmVuIHByb3BlcnR5IG9uIGFuIG9iamVjdCBpcyBhIGNvbXB1dGVkIHByb3BlcnR5LiBGb3IgdGhlIG1vc3QgcGFydCwKICAgIHRoaXMgZG9lc24ndCBtYXR0ZXIgKHlvdSB3b3VsZCBub3JtYWxseSBqdXN0IGFjY2VzcyB0aGUgcHJvcGVydHkgZGlyZWN0bHkgYW5kIHVzZSBpdHMgdmFsdWUpLAogICAgYnV0IGZvciBzb21lIHRvb2xpbmcgc3BlY2lmaWMgc2NlbmFyaW9zIChlLmcuIHRoZSBlbWJlci1pbnNwZWN0b3IpIGl0IGlzIGltcG9ydGFudCB0bwogICAgZGlmZmVyZW50aWF0ZSBpZiBhIHByb3BlcnR5IGlzIGEgY29tcHV0ZWQgcHJvcGVydHkgb3IgYSAibm9ybWFsIiBwcm9wZXJ0eS4KICAKICAgIFRoaXMgd2lsbCB3b3JrIG9uIGVpdGhlciBhIGNsYXNzJ3MgcHJvdG90eXBlIG9yIGFuIGluc3RhbmNlIGl0c2VsZi4KICAKICAgIEBzdGF0aWMKICAgIEBtZXRob2QgaXNDb21wdXRlZAogICAgQGZvciBAZW1iZXIvZGVidWcKICAgIEBwcml2YXRlCiAgICovCgoKICBmdW5jdGlvbiBpc0NvbXB1dGVkKG9iaiwga2V5KSB7CiAgICByZXR1cm4gQm9vbGVhbihkZXNjcmlwdG9yRm9yUHJvcGVydHkob2JqLCBrZXkpKTsKICB9CgogIHZhciBfZ2xvYmFsc0NvbXB1dGVkID0gY29tcHV0ZWQuYmluZChudWxsKTsKCiAgX2V4cG9ydHMuX2dsb2JhbHNDb21wdXRlZCA9IF9nbG9iYWxzQ29tcHV0ZWQ7CiAgdmFyIENPTlNVTUVEID0gT2JqZWN0LmZyZWV6ZSh7fSk7CgogIGZ1bmN0aW9uIGFsaWFzKGFsdEtleSkgewogICAgKGZhbHNlICYmICEoIWlzRWxlbWVudERlc2NyaXB0b3IoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGFsaWFzIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgYWx0S2V5YCBwYXJhbWV0ZXInLCAhaXNFbGVtZW50RGVzY3JpcHRvcihBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIG1ha2VDb21wdXRlZERlY29yYXRvcihuZXcgQWxpYXNlZFByb3BlcnR5KGFsdEtleSksIEFsaWFzRGVjb3JhdG9ySW1wbCk7CiAgfSAvLyBUT0RPOiBUaGlzIGNsYXNzIGNhbiBiZSBzdmVsdGVkIG9uY2UgYG1ldGFgIGhhcyBiZWVuIGRlcHJlY2F0ZWQKCgogIHZhciBBbGlhc0RlY29yYXRvckltcGwgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Z1bmN0aW9uMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEFsaWFzRGVjb3JhdG9ySW1wbCwgX0Z1bmN0aW9uMik7CgogICAgZnVuY3Rpb24gQWxpYXNEZWNvcmF0b3JJbXBsKCkgewogICAgICByZXR1cm4gX0Z1bmN0aW9uMi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzkgPSBBbGlhc0RlY29yYXRvckltcGwucHJvdG90eXBlOwoKICAgIF9wcm90bzkucmVhZE9ubHkgPSBmdW5jdGlvbiByZWFkT25seSgpIHsKICAgICAgZGVzY3JpcHRvckZvckRlY29yYXRvcih0aGlzKS5yZWFkT25seSgpOwogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgX3Byb3RvOS5vbmVXYXkgPSBmdW5jdGlvbiBvbmVXYXkoKSB7CiAgICAgIGRlc2NyaXB0b3JGb3JEZWNvcmF0b3IodGhpcykub25lV2F5KCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICBfcHJvdG85Lm1ldGEgPSBmdW5jdGlvbiBtZXRhKG1ldGEkJDEpIHsKICAgICAgdmFyIHByb3AgPSBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKHRoaXMpOwoKICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gcHJvcC5fbWV0YSB8fCB7fTsKICAgICAgfSBlbHNlIHsKICAgICAgICBwcm9wLl9tZXRhID0gbWV0YSQkMTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gQWxpYXNEZWNvcmF0b3JJbXBsOwogIH0oKDAsIF9lbWJlckJhYmVsLndyYXBOYXRpdmVTdXBlcikoRnVuY3Rpb24pKTsKCiAgdmFyIEFsaWFzZWRQcm9wZXJ0eSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ29tcHV0ZWREZXNjcmlwdG9yMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEFsaWFzZWRQcm9wZXJ0eSwgX0NvbXB1dGVkRGVzY3JpcHRvcjIpOwoKICAgIGZ1bmN0aW9uIEFsaWFzZWRQcm9wZXJ0eShhbHRLZXkpIHsKICAgICAgdmFyIF90aGlzNDsKCiAgICAgIF90aGlzNCA9IF9Db21wdXRlZERlc2NyaXB0b3IyLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXM0LmFsdEtleSA9IGFsdEtleTsKICAgICAgcmV0dXJuIF90aGlzNDsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTAgPSBBbGlhc2VkUHJvcGVydHkucHJvdG90eXBlOwoKICAgIF9wcm90bzEwLnNldHVwID0gZnVuY3Rpb24gc2V0dXAob2JqLCBrZXlOYW1lLCBwcm9wZXJ0eURlc2MsIG1ldGEkJDEpIHsKICAgICAgKGZhbHNlICYmICEodGhpcy5hbHRLZXkgIT09IGtleU5hbWUpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiU2V0dGluZyBhbGlhcyAnIiArIGtleU5hbWUgKyAiJyBvbiBzZWxmIiwgdGhpcy5hbHRLZXkgIT09IGtleU5hbWUpKTsKCiAgICAgIF9Db21wdXRlZERlc2NyaXB0b3IyLnByb3RvdHlwZS5zZXR1cC5jYWxsKHRoaXMsIG9iaiwga2V5TmFtZSwgcHJvcGVydHlEZXNjLCBtZXRhJCQxKTsKICAgIH07CgogICAgX3Byb3RvMTAudGVhcmRvd24gPSBmdW5jdGlvbiB0ZWFyZG93bihvYmosIGtleU5hbWUsIG1ldGEkJDEpIHsKICAgICAgX0NvbXB1dGVkRGVzY3JpcHRvcjIucHJvdG90eXBlLnRlYXJkb3duLmNhbGwodGhpcywgb2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgIH07CgogICAgX3Byb3RvMTAud2lsbFdhdGNoID0gZnVuY3Rpb24gd2lsbFdhdGNoKG9iaiwga2V5TmFtZSwgbWV0YSQkMSkge307CgogICAgX3Byb3RvMTAuZ2V0ID0gZnVuY3Rpb24gZ2V0KG9iaiwga2V5TmFtZSkgewogICAgICB2YXIgX3RoaXM1ID0gdGhpczsKCiAgICAgIHZhciByZXQ7CiAgICAgIHsKICAgICAgICB2YXIgcHJvcGVydHlUYWcgPSB0YWdGb3JQcm9wZXJ0eShvYmosIGtleU5hbWUpOyAvLyBXZSBkb24ndCB1c2UgdGhlIHRhZyBzaW5jZSBDUHMgYXJlIG5vdCBhdXRvbWF0aWMsIHdlIGp1c3Qgd2FudCB0byBhdm9pZAogICAgICAgIC8vIGFueXRoaW5nIHRyYWNraW5nIHdoaWxlIHdlIGdldCB0aGUgYWx0S2V5CgogICAgICAgIHVudHJhY2soZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0ID0gX2dldDIob2JqLCBfdGhpczUuYWx0S2V5KTsKICAgICAgICB9KTsKICAgICAgICB2YXIgbGFzdFJldmlzaW9uID0gZ2V0TGFzdFJldmlzaW9uRm9yKG9iaiwga2V5TmFtZSk7CgogICAgICAgIGlmICghKDAsIF9yZWZlcmVuY2UudmFsaWRhdGUpKHByb3BlcnR5VGFnLCBsYXN0UmV2aXNpb24pKSB7CiAgICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHByb3BlcnR5VGFnLCAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShnZXRDaGFpblRhZ3NGb3JLZXkob2JqLCB0aGlzLmFsdEtleSkpKTsKICAgICAgICAgIHNldExhc3RSZXZpc2lvbkZvcihvYmosIGtleU5hbWUsICgwLCBfcmVmZXJlbmNlLnZhbHVlKShwcm9wZXJ0eVRhZykpOwogICAgICAgICAgZmluaXNoTGF6eUNoYWlucyhvYmosIGtleU5hbWUsIHJldCk7CiAgICAgICAgfQoKICAgICAgICBjb25zdW1lKHByb3BlcnR5VGFnKTsKICAgICAgfQogICAgICByZXR1cm4gcmV0OwogICAgfTsKCiAgICBfcHJvdG8xMC51bmNvbnN1bWUgPSBmdW5jdGlvbiB1bmNvbnN1bWUob2JqLCBrZXlOYW1lLCBtZXRhJCQxKSB7CiAgICAgIHZhciB3YXNDb25zdW1lZCA9IGdldENhY2hlZFZhbHVlRm9yKG9iaiwga2V5TmFtZSkgPT09IENPTlNVTUVEOwoKICAgICAgaWYgKHdhc0NvbnN1bWVkIHx8IG1ldGEkJDEucGVla1dhdGNoaW5nKGtleU5hbWUpID4gMCkgewogICAgICAgIHJlbW92ZURlcGVuZGVudEtleXModGhpcywgb2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgICAgfQoKICAgICAgaWYgKHdhc0NvbnN1bWVkKSB7CiAgICAgICAgZ2V0Q2FjaGVGb3Iob2JqKS5kZWxldGUoa2V5TmFtZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTAuY29uc3VtZSA9IGZ1bmN0aW9uIGNvbnN1bWUob2JqLCBrZXlOYW1lLCBtZXRhJCQxKSB7CiAgICAgIHZhciBjYWNoZSA9IGdldENhY2hlRm9yKG9iaik7CgogICAgICBpZiAoY2FjaGUuZ2V0KGtleU5hbWUpICE9PSBDT05TVU1FRCkgewogICAgICAgIGNhY2hlLnNldChrZXlOYW1lLCBDT05TVU1FRCk7CiAgICAgICAgYWRkRGVwZW5kZW50S2V5cyh0aGlzLCBvYmosIGtleU5hbWUsIG1ldGEkJDEpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzEwLnNldCA9IGZ1bmN0aW9uIHNldChvYmosIF9rZXlOYW1lLCB2YWx1ZSQkMSkgewogICAgICByZXR1cm4gX3NldDIob2JqLCB0aGlzLmFsdEtleSwgdmFsdWUkJDEpOwogICAgfTsKCiAgICBfcHJvdG8xMC5yZWFkT25seSA9IGZ1bmN0aW9uIHJlYWRPbmx5KCkgewogICAgICB0aGlzLnNldCA9IEFsaWFzZWRQcm9wZXJ0eV9yZWFkT25seVNldDsKICAgIH07CgogICAgX3Byb3RvMTAub25lV2F5ID0gZnVuY3Rpb24gb25lV2F5KCkgewogICAgICB0aGlzLnNldCA9IEFsaWFzZWRQcm9wZXJ0eV9vbmVXYXlTZXQ7CiAgICB9OwoKICAgIHJldHVybiBBbGlhc2VkUHJvcGVydHk7CiAgfShDb21wdXRlZERlc2NyaXB0b3IpOwoKICBmdW5jdGlvbiBBbGlhc2VkUHJvcGVydHlfcmVhZE9ubHlTZXQob2JqLCBrZXlOYW1lKSB7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzCiAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIkNhbm5vdCBzZXQgcmVhZC1vbmx5IHByb3BlcnR5ICciICsga2V5TmFtZSArICInIG9uIG9iamVjdDogIiArICgwLCBfdXRpbHMuaW5zcGVjdCkob2JqKSk7CiAgfQoKICBmdW5jdGlvbiBBbGlhc2VkUHJvcGVydHlfb25lV2F5U2V0KG9iaiwga2V5TmFtZSwgdmFsdWUkJDEpIHsKICAgIGRlZmluZVByb3BlcnR5KG9iaiwga2V5TmFtZSwgbnVsbCk7CiAgICByZXR1cm4gX3NldDIob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgfQogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIFVzZWQgaW50ZXJuYWxseSB0byBhbGxvdyBjaGFuZ2luZyBwcm9wZXJ0aWVzIGluIGEgYmFja3dhcmRzIGNvbXBhdGlibGUgd2F5LCBhbmQgcHJpbnQgYSBoZWxwZnVsCiAgICBkZXByZWNhdGlvbiB3YXJuaW5nLgogIAogICAgQG1ldGhvZCBkZXByZWNhdGVQcm9wZXJ0eQogICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGFkZCB0aGUgZGVwcmVjYXRlZCBwcm9wZXJ0eSB0by4KICAgIEBwYXJhbSB7U3RyaW5nfSBkZXByZWNhdGVkS2V5IFRoZSBwcm9wZXJ0eSB0byBhZGQgKGFuZCBwcmludCBkZXByZWNhdGlvbiB3YXJuaW5ncyB1cG9uIGFjY2Vzc2luZykuCiAgICBAcGFyYW0ge1N0cmluZ30gbmV3S2V5IFRoZSBwcm9wZXJ0eSB0aGF0IHdpbGwgYmUgYWxpYXNlZC4KICAgIEBwcml2YXRlCiAgICBAc2luY2UgMS43LjAKICAqLwoKCiAgZnVuY3Rpb24gZGVwcmVjYXRlUHJvcGVydHkob2JqZWN0LCBkZXByZWNhdGVkS2V5LCBuZXdLZXksIG9wdGlvbnMpIHsKICAgIGZ1bmN0aW9uIF9kZXByZWNhdGUoKSB7CiAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIlVzYWdlIG9mIGAiICsgZGVwcmVjYXRlZEtleSArICJgIGlzIGRlcHJlY2F0ZWQsIHVzZSBgIiArIG5ld0tleSArICJgIGluc3RlYWQuIiwgZmFsc2UsIG9wdGlvbnMpKTsKICAgIH0KCiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqZWN0LCBkZXByZWNhdGVkS2V5LCB7CiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgZW51bWVyYWJsZTogZmFsc2UsCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHZhbHVlJCQxKSB7CiAgICAgICAgX2RlcHJlY2F0ZSgpOwoKICAgICAgICBfc2V0Mih0aGlzLCBuZXdLZXksIHZhbHVlJCQxKTsKICAgICAgfSwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgX2RlcHJlY2F0ZSgpOwoKICAgICAgICByZXR1cm4gX2dldDIodGhpcywgbmV3S2V5KTsKICAgICAgfQogICAgfSk7CiAgfQogIC8qKgogICBAbW9kdWxlIEBlbWJlci91dGlscwogICovCgogIC8qKgogICAgUmV0dXJucyB0cnVlIGlmIHRoZSBwYXNzZWQgdmFsdWUgaXMgbnVsbCBvciB1bmRlZmluZWQuIFRoaXMgYXZvaWRzIGVycm9ycwogICAgZnJvbSBKU0xpbnQgY29tcGxhaW5pbmcgYWJvdXQgdXNlIG9mID09LCB3aGljaCBjYW4gYmUgdGVjaG5pY2FsbHkKICAgIGNvbmZ1c2luZy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGlzTm9uZSgpOyAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNOb25lKG51bGwpOyAgICAgICAgICAvLyB0cnVlCiAgICBpc05vbmUodW5kZWZpbmVkKTsgICAgIC8vIHRydWUKICAgIGlzTm9uZSgnJyk7ICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzTm9uZShbXSk7ICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzTm9uZShmdW5jdGlvbigpIHt9KTsgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQG1ldGhvZCBpc05vbmUKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL3V0aWxzCiAgICBAcGFyYW0ge09iamVjdH0gb2JqIFZhbHVlIHRvIHRlc3QKICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGlzTm9uZShvYmopIHsKICAgIHJldHVybiBvYmogPT09IG51bGwgfHwgb2JqID09PSB1bmRlZmluZWQ7CiAgfQogIC8qKgogICBAbW9kdWxlIEBlbWJlci91dGlscwogICovCgogIC8qKgogICAgVmVyaWZpZXMgdGhhdCBhIHZhbHVlIGlzIGBudWxsYCBvciBgdW5kZWZpbmVkYCwgYW4gZW1wdHkgc3RyaW5nLCBvciBhbiBlbXB0eQogICAgYXJyYXkuCiAgCiAgICBDb25zdHJhaW5zIHRoZSBydWxlcyBvbiBgaXNOb25lYCBieSByZXR1cm5pbmcgdHJ1ZSBmb3IgZW1wdHkgc3RyaW5ncyBhbmQKICAgIGVtcHR5IGFycmF5cy4KICAKICAgIElmIHRoZSB2YWx1ZSBpcyBhbiBvYmplY3Qgd2l0aCBhIGBzaXplYCBwcm9wZXJ0eSBvZiB0eXBlIG51bWJlciwgaXQgaXMgdXNlZAogICAgdG8gY2hlY2sgZW1wdGluZXNzLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaXNFbXB0eSgpOyAgICAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eShudWxsKTsgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eSh1bmRlZmluZWQpOyAgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eSgnJyk7ICAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eShbXSk7ICAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eSh7IHNpemU6IDB9KTsgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eSh7fSk7ICAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzRW1wdHkoJ0FkYW0gSGF3a2lucycpOyAgIC8vIGZhbHNlCiAgICBpc0VtcHR5KFswLDEsMl0pOyAgICAgICAgICAvLyBmYWxzZQogICAgaXNFbXB0eSgnXG5cdCcpOyAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzRW1wdHkoJyAgJyk7ICAgICAgICAgICAgIC8vIGZhbHNlCiAgICBpc0VtcHR5KHsgc2l6ZTogMSB9KSAgICAgICAvLyBmYWxzZQogICAgaXNFbXB0eSh7IHNpemU6ICgpID0+IDAgfSkgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQG1ldGhvZCBpc0VtcHR5CiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci91dGlscwogICAgQHBhcmFtIHtPYmplY3R9IG9iaiBWYWx1ZSB0byB0ZXN0CiAgICBAcmV0dXJuIHtCb29sZWFufQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpc0VtcHR5KG9iaikgewogICAgdmFyIG5vbmUgPSBvYmogPT09IG51bGwgfHwgb2JqID09PSB1bmRlZmluZWQ7CgogICAgaWYgKG5vbmUpIHsKICAgICAgcmV0dXJuIG5vbmU7CiAgICB9CgogICAgaWYgKHR5cGVvZiBvYmouc2l6ZSA9PT0gJ251bWJlcicpIHsKICAgICAgcmV0dXJuICFvYmouc2l6ZTsKICAgIH0KCiAgICB2YXIgb2JqZWN0VHlwZSA9IHR5cGVvZiBvYmo7CgogICAgaWYgKG9iamVjdFR5cGUgPT09ICdvYmplY3QnKSB7CiAgICAgIHZhciBzaXplID0gX2dldDIob2JqLCAnc2l6ZScpOwoKICAgICAgaWYgKHR5cGVvZiBzaXplID09PSAnbnVtYmVyJykgewogICAgICAgIHJldHVybiAhc2l6ZTsKICAgICAgfQogICAgfQoKICAgIGlmICh0eXBlb2Ygb2JqLmxlbmd0aCA9PT0gJ251bWJlcicgJiYgb2JqZWN0VHlwZSAhPT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gIW9iai5sZW5ndGg7CiAgICB9CgogICAgaWYgKG9iamVjdFR5cGUgPT09ICdvYmplY3QnKSB7CiAgICAgIHZhciBsZW5ndGggPSBfZ2V0MihvYmosICdsZW5ndGgnKTsKCiAgICAgIGlmICh0eXBlb2YgbGVuZ3RoID09PSAnbnVtYmVyJykgewogICAgICAgIHJldHVybiAhbGVuZ3RoOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGZhbHNlOwogIH0KICAvKioKICAgQG1vZHVsZSBAZW1iZXIvdXRpbHMKICAqLwoKICAvKioKICAgIEEgdmFsdWUgaXMgYmxhbmsgaWYgaXQgaXMgZW1wdHkgb3IgYSB3aGl0ZXNwYWNlIHN0cmluZy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGlzQmxhbmsgfSBmcm9tICdAZW1iZXIvdXRpbHMnOwogIAogICAgaXNCbGFuaygpOyAgICAgICAgICAgICAgICAvLyB0cnVlCiAgICBpc0JsYW5rKG51bGwpOyAgICAgICAgICAgIC8vIHRydWUKICAgIGlzQmxhbmsodW5kZWZpbmVkKTsgICAgICAgLy8gdHJ1ZQogICAgaXNCbGFuaygnJyk7ICAgICAgICAgICAgICAvLyB0cnVlCiAgICBpc0JsYW5rKFtdKTsgICAgICAgICAgICAgIC8vIHRydWUKICAgIGlzQmxhbmsoJ1xuXHQnKTsgICAgICAgICAgLy8gdHJ1ZQogICAgaXNCbGFuaygnICAnKTsgICAgICAgICAgICAvLyB0cnVlCiAgICBpc0JsYW5rKHt9KTsgICAgICAgICAgICAgIC8vIGZhbHNlCiAgICBpc0JsYW5rKCdcblx0IEhlbGxvJyk7ICAgIC8vIGZhbHNlCiAgICBpc0JsYW5rKCdIZWxsbyB3b3JsZCcpOyAgIC8vIGZhbHNlCiAgICBpc0JsYW5rKFsxLDIsM10pOyAgICAgICAgIC8vIGZhbHNlCiAgICBgYGAKICAKICAgIEBtZXRob2QgaXNCbGFuawogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvdXRpbHMKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVmFsdWUgdG8gdGVzdAogICAgQHJldHVybiB7Qm9vbGVhbn0KICAgIEBzaW5jZSAxLjUuMAogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpc0JsYW5rKG9iaikgewogICAgcmV0dXJuIGlzRW1wdHkob2JqKSB8fCB0eXBlb2Ygb2JqID09PSAnc3RyaW5nJyAmJiAvXFMvLnRlc3Qob2JqKSA9PT0gZmFsc2U7CiAgfQogIC8qKgogICBAbW9kdWxlIEBlbWJlci91dGlscwogICovCgogIC8qKgogICAgQSB2YWx1ZSBpcyBwcmVzZW50IGlmIGl0IG5vdCBgaXNCbGFua2AuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpc1ByZXNlbnQoKTsgICAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzUHJlc2VudChudWxsKTsgICAgICAgICAgICAvLyBmYWxzZQogICAgaXNQcmVzZW50KHVuZGVmaW5lZCk7ICAgICAgIC8vIGZhbHNlCiAgICBpc1ByZXNlbnQoJycpOyAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzUHJlc2VudCgnICAnKTsgICAgICAgICAgICAvLyBmYWxzZQogICAgaXNQcmVzZW50KCdcblx0Jyk7ICAgICAgICAgIC8vIGZhbHNlCiAgICBpc1ByZXNlbnQoW10pOyAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzUHJlc2VudCh7IGxlbmd0aDogMCB9KTsgICAvLyBmYWxzZQogICAgaXNQcmVzZW50KGZhbHNlKTsgICAgICAgICAgIC8vIHRydWUKICAgIGlzUHJlc2VudCh0cnVlKTsgICAgICAgICAgICAvLyB0cnVlCiAgICBpc1ByZXNlbnQoJ3N0cmluZycpOyAgICAgICAgLy8gdHJ1ZQogICAgaXNQcmVzZW50KDApOyAgICAgICAgICAgICAgIC8vIHRydWUKICAgIGlzUHJlc2VudChmdW5jdGlvbigpIHt9KTsgICAvLyB0cnVlCiAgICBpc1ByZXNlbnQoe30pOyAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNQcmVzZW50KCdcblx0IEhlbGxvJyk7ICAgIC8vIHRydWUKICAgIGlzUHJlc2VudChbMSwgMiwgM10pOyAgICAgICAvLyB0cnVlCiAgICBgYGAKICAKICAgIEBtZXRob2QgaXNQcmVzZW50CiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci91dGlscwogICAgQHBhcmFtIHtPYmplY3R9IG9iaiBWYWx1ZSB0byB0ZXN0CiAgICBAcmV0dXJuIHtCb29sZWFufQogICAgQHNpbmNlIDEuOC4wCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGlzUHJlc2VudChvYmopIHsKICAgIHJldHVybiAhaXNCbGFuayhvYmopOwogIH0KICAvKioKICAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgSGVscGVyIGNsYXNzIHRoYXQgYWxsb3dzIHlvdSB0byByZWdpc3RlciB5b3VyIGxpYnJhcnkgd2l0aCBFbWJlci4KICAKICAgIFNpbmdsZXRvbiBjcmVhdGVkIGF0IGBFbWJlci5saWJyYXJpZXNgLgogIAogICAgQGNsYXNzIExpYnJhcmllcwogICAgQGNvbnN0cnVjdG9yCiAgICBAcHJpdmF0ZQogICovCgoKICB2YXIgTGlicmFyaWVzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gTGlicmFyaWVzKCkgewogICAgICB0aGlzLl9yZWdpc3RyeSA9IFtdOwogICAgICB0aGlzLl9jb3JlTGliSW5kZXggPSAwOwogICAgfQoKICAgIHZhciBfcHJvdG8xMSA9IExpYnJhcmllcy5wcm90b3R5cGU7CgogICAgX3Byb3RvMTEuX2dldExpYnJhcnlCeU5hbWUgPSBmdW5jdGlvbiBfZ2V0TGlicmFyeUJ5TmFtZShuYW1lKSB7CiAgICAgIHZhciBsaWJzID0gdGhpcy5fcmVnaXN0cnk7CiAgICAgIHZhciBjb3VudCA9IGxpYnMubGVuZ3RoOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgICAgaWYgKGxpYnNbaV0ubmFtZSA9PT0gbmFtZSkgewogICAgICAgICAgcmV0dXJuIGxpYnNbaV07CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfTsKCiAgICBfcHJvdG8xMS5yZWdpc3RlciA9IGZ1bmN0aW9uIHJlZ2lzdGVyKG5hbWUsIHZlcnNpb24sIGlzQ29yZUxpYnJhcnkpIHsKICAgICAgdmFyIGluZGV4ID0gdGhpcy5fcmVnaXN0cnkubGVuZ3RoOwoKICAgICAgaWYgKCF0aGlzLl9nZXRMaWJyYXJ5QnlOYW1lKG5hbWUpKSB7CiAgICAgICAgaWYgKGlzQ29yZUxpYnJhcnkpIHsKICAgICAgICAgIGluZGV4ID0gdGhpcy5fY29yZUxpYkluZGV4Kys7CiAgICAgICAgfQoKICAgICAgICB0aGlzLl9yZWdpc3RyeS5zcGxpY2UoaW5kZXgsIDAsIHsKICAgICAgICAgIG5hbWU6IG5hbWUsCiAgICAgICAgICB2ZXJzaW9uOiB2ZXJzaW9uCiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgKGZhbHNlICYmICgwLCBfZGVidWcud2FybikoIkxpYnJhcnkgXCIiICsgbmFtZSArICJcIiBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgd2l0aCBFbWJlci4iLCBmYWxzZSwgewogICAgICAgICAgaWQ6ICdlbWJlci1tZXRhbC5saWJyYXJpZXMtcmVnaXN0ZXInCiAgICAgICAgfSkpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzExLnJlZ2lzdGVyQ29yZUxpYnJhcnkgPSBmdW5jdGlvbiByZWdpc3RlckNvcmVMaWJyYXJ5KG5hbWUsIHZlcnNpb24pIHsKICAgICAgdGhpcy5yZWdpc3RlcihuYW1lLCB2ZXJzaW9uLCB0cnVlKTsKICAgIH07CgogICAgX3Byb3RvMTEuZGVSZWdpc3RlciA9IGZ1bmN0aW9uIGRlUmVnaXN0ZXIobmFtZSkgewogICAgICB2YXIgbGliID0gdGhpcy5fZ2V0TGlicmFyeUJ5TmFtZShuYW1lKTsKCiAgICAgIHZhciBpbmRleDsKCiAgICAgIGlmIChsaWIpIHsKICAgICAgICBpbmRleCA9IHRoaXMuX3JlZ2lzdHJ5LmluZGV4T2YobGliKTsKCiAgICAgICAgdGhpcy5fcmVnaXN0cnkuc3BsaWNlKGluZGV4LCAxKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gTGlicmFyaWVzOwogIH0oKTsKCiAgX2V4cG9ydHMuTGlicmFyaWVzID0gTGlicmFyaWVzOwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgTGlicmFyaWVzLnByb3RvdHlwZS5sb2dWZXJzaW9ucyA9IGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGxpYnMgPSB0aGlzLl9yZWdpc3RyeTsKICAgICAgdmFyIG5hbWVMZW5ndGhzID0gbGlicy5tYXAoZnVuY3Rpb24gKGl0ZW0pIHsKICAgICAgICByZXR1cm4gX2dldDIoaXRlbSwgJ25hbWUubGVuZ3RoJyk7CiAgICAgIH0pOwogICAgICB2YXIgbWF4TmFtZUxlbmd0aCA9IE1hdGgubWF4LmFwcGx5KG51bGwsIG5hbWVMZW5ndGhzKTsKICAgICAgKDAsIF9kZWJ1Zy5kZWJ1ZykoJy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0nKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGlicy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBsaWIgPSBsaWJzW2ldOwogICAgICAgIHZhciBzcGFjZXMgPSBuZXcgQXJyYXkobWF4TmFtZUxlbmd0aCAtIGxpYi5uYW1lLmxlbmd0aCArIDEpLmpvaW4oJyAnKTsKICAgICAgICAoMCwgX2RlYnVnLmRlYnVnKShbbGliLm5hbWUsIHNwYWNlcywgJyA6ICcsIGxpYi52ZXJzaW9uXS5qb2luKCcnKSk7CiAgICAgIH0KCiAgICAgICgwLCBfZGVidWcuZGVidWcpKCctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJyk7CiAgICB9OwogIH0KCiAgdmFyIExJQlJBUklFUyA9IG5ldyBMaWJyYXJpZXMoKTsKICBfZXhwb3J0cy5saWJyYXJpZXMgPSBMSUJSQVJJRVM7CiAgTElCUkFSSUVTLnJlZ2lzdGVyQ29yZUxpYnJhcnkoJ0VtYmVyJywgX3ZlcnNpb24uZGVmYXVsdCk7CiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL29iamVjdAogICovCgogIC8qKgogICAgVG8gZ2V0IG11bHRpcGxlIHByb3BlcnRpZXMgYXQgb25jZSwgY2FsbCBgZ2V0UHJvcGVydGllc2AKICAgIHdpdGggYW4gb2JqZWN0IGZvbGxvd2VkIGJ5IGEgbGlzdCBvZiBzdHJpbmdzIG9yIGFuIGFycmF5OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZ2V0UHJvcGVydGllcyB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZ2V0UHJvcGVydGllcyhyZWNvcmQsICdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnLCAnemlwQ29kZScpOwogICAgLy8geyBmaXJzdE5hbWU6ICdKb2huJywgbGFzdE5hbWU6ICdEb2UnLCB6aXBDb2RlOiAnMTAwMTEnIH0KICAgIGBgYAogIAogICAgaXMgZXF1aXZhbGVudCB0bzoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGdldFByb3BlcnRpZXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGdldFByb3BlcnRpZXMocmVjb3JkLCBbJ2ZpcnN0TmFtZScsICdsYXN0TmFtZScsICd6aXBDb2RlJ10pOwogICAgLy8geyBmaXJzdE5hbWU6ICdKb2huJywgbGFzdE5hbWU6ICdEb2UnLCB6aXBDb2RlOiAnMTAwMTEnIH0KICAgIGBgYAogIAogICAgQG1ldGhvZCBnZXRQcm9wZXJ0aWVzCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmoKICAgIEBwYXJhbSB7U3RyaW5nLi4ufEFycmF5fSBsaXN0IG9mIGtleXMgdG8gZ2V0CiAgICBAcmV0dXJuIHtPYmplY3R9CiAgICBAcHVibGljCiAgKi8KCiAgZnVuY3Rpb24gZ2V0UHJvcGVydGllcyhvYmosIGtleXMpIHsKICAgIHZhciByZXQgPSB7fTsKICAgIHZhciBwcm9wZXJ0eU5hbWVzID0gYXJndW1lbnRzOwogICAgdmFyIGkgPSAxOwoKICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmIEFycmF5LmlzQXJyYXkoa2V5cykpIHsKICAgICAgaSA9IDA7CiAgICAgIHByb3BlcnR5TmFtZXMgPSBhcmd1bWVudHNbMV07CiAgICB9CgogICAgZm9yICg7IGkgPCBwcm9wZXJ0eU5hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHJldFtwcm9wZXJ0eU5hbWVzW2ldXSA9IF9nZXQyKG9iaiwgcHJvcGVydHlOYW1lc1tpXSk7CiAgICB9CgogICAgcmV0dXJuIHJldDsKICB9CiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL29iamVjdAogICovCgogIC8qKgogICAgU2V0IGEgbGlzdCBvZiBwcm9wZXJ0aWVzIG9uIGFuIG9iamVjdC4gVGhlc2UgcHJvcGVydGllcyBhcmUgc2V0IGluc2lkZQogICAgYSBzaW5nbGUgYGJlZ2luUHJvcGVydHlDaGFuZ2VzYCBhbmQgYGVuZFByb3BlcnR5Q2hhbmdlc2AgYmF0Y2gsIHNvCiAgICBvYnNlcnZlcnMgd2lsbCBiZSBidWZmZXJlZC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGxldCBhbk9iamVjdCA9IEVtYmVyT2JqZWN0LmNyZWF0ZSgpOwogIAogICAgYW5PYmplY3Quc2V0UHJvcGVydGllcyh7CiAgICAgIGZpcnN0TmFtZTogJ1N0YW5sZXknLAogICAgICBsYXN0TmFtZTogJ1N0dWFydCcsCiAgICAgIGFnZTogMjEKICAgIH0pOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHNldFByb3BlcnRpZXMKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdAogICAgQHBhcmFtIG9iagogICAgQHBhcmFtIHtPYmplY3R9IHByb3BlcnRpZXMKICAgIEByZXR1cm4gcHJvcGVydGllcwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBzZXRQcm9wZXJ0aWVzKG9iaiwgcHJvcGVydGllcykgewogICAgaWYgKHByb3BlcnRpZXMgPT09IG51bGwgfHwgdHlwZW9mIHByb3BlcnRpZXMgIT09ICdvYmplY3QnKSB7CiAgICAgIHJldHVybiBwcm9wZXJ0aWVzOwogICAgfQoKICAgIGNoYW5nZVByb3BlcnRpZXMoZnVuY3Rpb24gKCkgewogICAgICB2YXIgcHJvcHMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKTsKICAgICAgdmFyIHByb3BlcnR5TmFtZTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsKICAgICAgICBwcm9wZXJ0eU5hbWUgPSBwcm9wc1tpXTsKCiAgICAgICAgX3NldDIob2JqLCBwcm9wZXJ0eU5hbWUsIHByb3BlcnRpZXNbcHJvcGVydHlOYW1lXSk7CiAgICAgIH0KICAgIH0pOwogICAgcmV0dXJuIHByb3BlcnRpZXM7CiAgfSAvLyBtb3ZlIGludG8gaXRzIG93biBwYWNrYWdlCiAgLy8gaXQgaXMgbmVlZGVkIGJ5IE1peGluIGZvciBjbGFzc1RvU3RyaW5nCiAgLy8gbWF5YmUgbW92ZSBpdCBpbnRvIGVudmlyb25tZW50CgoKICB2YXIgaGFzT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5OwogIHZhciBzZWFyY2hEaXNhYmxlZCA9IGZhbHNlOwogIHZhciBmbGFncyA9IHsKICAgIF9zZXQ6IDAsCiAgICBfdW5wcm9jZXNzZWROYW1lc3BhY2VzOiBmYWxzZSwKCiAgICBnZXQgdW5wcm9jZXNzZWROYW1lc3BhY2VzKCkgewogICAgICByZXR1cm4gdGhpcy5fdW5wcm9jZXNzZWROYW1lc3BhY2VzOwogICAgfSwKCiAgICBzZXQgdW5wcm9jZXNzZWROYW1lc3BhY2VzKHYpIHsKICAgICAgdGhpcy5fc2V0Kys7CiAgICAgIHRoaXMuX3VucHJvY2Vzc2VkTmFtZXNwYWNlcyA9IHY7CiAgICB9CgogIH07CiAgdmFyIHVucHJvY2Vzc2VkTWl4aW5zID0gZmFsc2U7CiAgdmFyIE5BTUVTUEFDRVMgPSBbXTsKICBfZXhwb3J0cy5OQU1FU1BBQ0VTID0gTkFNRVNQQUNFUzsKICB2YXIgTkFNRVNQQUNFU19CWV9JRCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgX2V4cG9ydHMuTkFNRVNQQUNFU19CWV9JRCA9IE5BTUVTUEFDRVNfQllfSUQ7CgogIGZ1bmN0aW9uIGFkZE5hbWVzcGFjZShuYW1lc3BhY2UpIHsKICAgIGZsYWdzLnVucHJvY2Vzc2VkTmFtZXNwYWNlcyA9IHRydWU7CiAgICBOQU1FU1BBQ0VTLnB1c2gobmFtZXNwYWNlKTsKICB9CgogIGZ1bmN0aW9uIHJlbW92ZU5hbWVzcGFjZShuYW1lc3BhY2UpIHsKICAgIHZhciBuYW1lID0gKDAsIF91dGlscy5nZXROYW1lKShuYW1lc3BhY2UpOwogICAgZGVsZXRlIE5BTUVTUEFDRVNfQllfSURbbmFtZV07CiAgICBOQU1FU1BBQ0VTLnNwbGljZShOQU1FU1BBQ0VTLmluZGV4T2YobmFtZXNwYWNlKSwgMSk7CgogICAgaWYgKG5hbWUgaW4gX2Vudmlyb25tZW50LmNvbnRleHQubG9va3VwICYmIG5hbWVzcGFjZSA9PT0gX2Vudmlyb25tZW50LmNvbnRleHQubG9va3VwW25hbWVdKSB7CiAgICAgIF9lbnZpcm9ubWVudC5jb250ZXh0Lmxvb2t1cFtuYW1lXSA9IHVuZGVmaW5lZDsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGZpbmROYW1lc3BhY2VzKCkgewogICAgaWYgKCFmbGFncy51bnByb2Nlc3NlZE5hbWVzcGFjZXMpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBsb29rdXAgPSBfZW52aXJvbm1lbnQuY29udGV4dC5sb29rdXA7CiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGxvb2t1cCk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBrZXkgPSBrZXlzW2ldOyAvLyBPbmx5IHByb2Nlc3MgZW50aXRpZXMgdGhhdCBzdGFydCB3aXRoIHVwcGVyY2FzZSBBLVoKCiAgICAgIGlmICghaXNVcHBlcmNhc2Uoa2V5LmNoYXJDb2RlQXQoMCkpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIHZhciBvYmogPSB0cnlJc05hbWVzcGFjZShsb29rdXAsIGtleSk7CgogICAgICBpZiAob2JqKSB7CiAgICAgICAgKDAsIF91dGlscy5zZXROYW1lKShvYmosIGtleSk7CiAgICAgIH0KICAgIH0KICB9CgogIGZ1bmN0aW9uIGZpbmROYW1lc3BhY2UobmFtZSkgewogICAgaWYgKCFzZWFyY2hEaXNhYmxlZCkgewogICAgICBwcm9jZXNzQWxsTmFtZXNwYWNlcygpOwogICAgfQoKICAgIHJldHVybiBOQU1FU1BBQ0VTX0JZX0lEW25hbWVdOwogIH0KCiAgZnVuY3Rpb24gcHJvY2Vzc05hbWVzcGFjZShuYW1lc3BhY2UpIHsKICAgIF9wcm9jZXNzTmFtZXNwYWNlKFtuYW1lc3BhY2UudG9TdHJpbmcoKV0sIG5hbWVzcGFjZSwgbmV3IFNldCgpKTsKICB9CgogIGZ1bmN0aW9uIHByb2Nlc3NBbGxOYW1lc3BhY2VzKCkgewogICAgdmFyIHVucHJvY2Vzc2VkTmFtZXNwYWNlcyA9IGZsYWdzLnVucHJvY2Vzc2VkTmFtZXNwYWNlczsKCiAgICBpZiAodW5wcm9jZXNzZWROYW1lc3BhY2VzKSB7CiAgICAgIGZpbmROYW1lc3BhY2VzKCk7CiAgICAgIGZsYWdzLnVucHJvY2Vzc2VkTmFtZXNwYWNlcyA9IGZhbHNlOwogICAgfQoKICAgIGlmICh1bnByb2Nlc3NlZE5hbWVzcGFjZXMgfHwgdW5wcm9jZXNzZWRNaXhpbnMpIHsKICAgICAgdmFyIG5hbWVzcGFjZXMgPSBOQU1FU1BBQ0VTOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lc3BhY2VzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgcHJvY2Vzc05hbWVzcGFjZShuYW1lc3BhY2VzW2ldKTsKICAgICAgfQoKICAgICAgdW5wcm9jZXNzZWRNaXhpbnMgPSBmYWxzZTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGNsYXNzVG9TdHJpbmcoKSB7CiAgICB2YXIgbmFtZSA9ICgwLCBfdXRpbHMuZ2V0TmFtZSkodGhpcyk7CgogICAgaWYgKG5hbWUgIT09IHZvaWQgMCkgewogICAgICByZXR1cm4gbmFtZTsKICAgIH0KCiAgICBuYW1lID0gY2FsY3VsYXRlVG9TdHJpbmcodGhpcyk7CiAgICAoMCwgX3V0aWxzLnNldE5hbWUpKHRoaXMsIG5hbWUpOwogICAgcmV0dXJuIG5hbWU7CiAgfQoKICBmdW5jdGlvbiBpc1NlYXJjaERpc2FibGVkKCkgewogICAgcmV0dXJuIHNlYXJjaERpc2FibGVkOwogIH0KCiAgZnVuY3Rpb24gc2V0U2VhcmNoRGlzYWJsZWQoZmxhZykgewogICAgc2VhcmNoRGlzYWJsZWQgPSBCb29sZWFuKGZsYWcpOwogIH0KCiAgZnVuY3Rpb24gc2V0VW5wcm9jZXNzZWRNaXhpbnMoKSB7CiAgICB1bnByb2Nlc3NlZE1peGlucyA9IHRydWU7CiAgfQoKICBmdW5jdGlvbiBfcHJvY2Vzc05hbWVzcGFjZShwYXRocywgcm9vdCwgc2VlbikgewogICAgdmFyIGlkeCA9IHBhdGhzLmxlbmd0aDsKICAgIHZhciBpZCA9IHBhdGhzLmpvaW4oJy4nKTsKICAgIE5BTUVTUEFDRVNfQllfSURbaWRdID0gcm9vdDsKICAgICgwLCBfdXRpbHMuc2V0TmFtZSkocm9vdCwgaWQpOyAvLyBMb29wIG92ZXIgYWxsIG9mIHRoZSBrZXlzIGluIHRoZSBuYW1lc3BhY2UsIGxvb2tpbmcgZm9yIGNsYXNzZXMKCiAgICBmb3IgKHZhciBrZXkgaW4gcm9vdCkgewogICAgICBpZiAoIWhhc093blByb3BlcnR5LmNhbGwocm9vdCwga2V5KSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICB2YXIgb2JqID0gcm9vdFtrZXldOyAvLyBJZiB3ZSBhcmUgcHJvY2Vzc2luZyB0aGUgYEVtYmVyYCBuYW1lc3BhY2UsIGZvciBleGFtcGxlLCB0aGUKICAgICAgLy8gYHBhdGhzYCB3aWxsIHN0YXJ0IHdpdGggYFsiRW1iZXIiXWAuIEV2ZXJ5IGl0ZXJhdGlvbiB0aHJvdWdoCiAgICAgIC8vIHRoZSBsb29wIHdpbGwgdXBkYXRlIHRoZSAqKnNlY29uZCoqIGVsZW1lbnQgb2YgdGhpcyBsaXN0IHdpdGgKICAgICAgLy8gdGhlIGtleSwgc28gcHJvY2Vzc2luZyBgRW1iZXIuVmlld2Agd2lsbCBtYWtlIHRoZSBBcnJheQogICAgICAvLyBgWydFbWJlcicsICdWaWV3J11gLgoKICAgICAgcGF0aHNbaWR4XSA9IGtleTsgLy8gSWYgd2UgaGF2ZSBmb3VuZCBhbiB1bnByb2Nlc3NlZCBjbGFzcwoKICAgICAgaWYgKG9iaiAmJiBvYmoudG9TdHJpbmcgPT09IGNsYXNzVG9TdHJpbmcgJiYgKDAsIF91dGlscy5nZXROYW1lKShvYmopID09PSB2b2lkIDApIHsKICAgICAgICAvLyBSZXBsYWNlIHRoZSBjbGFzcycgYHRvU3RyaW5nYCB3aXRoIHRoZSBkb3Qtc2VwYXJhdGVkIHBhdGgKICAgICAgICAoMCwgX3V0aWxzLnNldE5hbWUpKG9iaiwgcGF0aHMuam9pbignLicpKTsgLy8gU3VwcG9ydCBuZXN0ZWQgbmFtZXNwYWNlcwogICAgICB9IGVsc2UgaWYgKG9iaiAmJiBvYmouaXNOYW1lc3BhY2UpIHsKICAgICAgICAvLyBTa2lwIGFsaWFzZWQgbmFtZXNwYWNlcwogICAgICAgIGlmIChzZWVuLmhhcyhvYmopKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIHNlZW4uYWRkKG9iaik7IC8vIFByb2Nlc3MgdGhlIGNoaWxkIG5hbWVzcGFjZQoKICAgICAgICBfcHJvY2Vzc05hbWVzcGFjZShwYXRocywgb2JqLCBzZWVuKTsKICAgICAgfQogICAgfQoKICAgIHBhdGhzLmxlbmd0aCA9IGlkeDsgLy8gY3V0IG91dCBsYXN0IGl0ZW0KICB9CgogIGZ1bmN0aW9uIGlzVXBwZXJjYXNlKGNvZGUpIHsKICAgIHJldHVybiBjb2RlID49IDY1ICYmIGNvZGUgPD0gOTAgLy8gQQogICAgOyAvLyBaCiAgfQoKICBmdW5jdGlvbiB0cnlJc05hbWVzcGFjZShsb29rdXAsIHByb3ApIHsKICAgIHRyeSB7CiAgICAgIHZhciBvYmogPSBsb29rdXBbcHJvcF07CiAgICAgIHJldHVybiAob2JqICE9PSBudWxsICYmIHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpICYmIG9iai5pc05hbWVzcGFjZSAmJiBvYmo7CiAgICB9IGNhdGNoIChlKSB7Ly8gY29udGludWUKICAgIH0KICB9CgogIGZ1bmN0aW9uIGNhbGN1bGF0ZVRvU3RyaW5nKHRhcmdldCkgewogICAgdmFyIHN0cjsKCiAgICBpZiAoIXNlYXJjaERpc2FibGVkKSB7CiAgICAgIHByb2Nlc3NBbGxOYW1lc3BhY2VzKCk7CiAgICAgIHN0ciA9ICgwLCBfdXRpbHMuZ2V0TmFtZSkodGFyZ2V0KTsKCiAgICAgIGlmIChzdHIgIT09IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzdHI7CiAgICAgIH0KCiAgICAgIHZhciBzdXBlcmNsYXNzID0gdGFyZ2V0OwoKICAgICAgZG8gewogICAgICAgIHN1cGVyY2xhc3MgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yoc3VwZXJjbGFzcyk7CgogICAgICAgIGlmIChzdXBlcmNsYXNzID09PSBGdW5jdGlvbi5wcm90b3R5cGUgfHwgc3VwZXJjbGFzcyA9PT0gT2JqZWN0LnByb3RvdHlwZSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICBzdHIgPSAoMCwgX3V0aWxzLmdldE5hbWUpKHRhcmdldCk7CgogICAgICAgIGlmIChzdHIgIT09IHZvaWQgMCkgewogICAgICAgICAgc3RyID0gIihzdWJjbGFzcyBvZiAiICsgc3RyICsgIikiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9IHdoaWxlIChzdHIgPT09IHZvaWQgMCk7CiAgICB9CgogICAgcmV0dXJuIHN0ciB8fCAnKHVua25vd24pJzsKICB9CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KCgogIHZhciBhX2NvbmNhdCA9IEFycmF5LnByb3RvdHlwZS5jb25jYXQ7CiAgdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5OwoKICBmdW5jdGlvbiBpc01ldGhvZChvYmopIHsKICAgIHJldHVybiAnZnVuY3Rpb24nID09PSB0eXBlb2Ygb2JqICYmIG9iai5pc01ldGhvZCAhPT0gZmFsc2UgJiYgb2JqICE9PSBCb29sZWFuICYmIG9iaiAhPT0gT2JqZWN0ICYmIG9iaiAhPT0gTnVtYmVyICYmIG9iaiAhPT0gQXJyYXkgJiYgb2JqICE9PSBEYXRlICYmIG9iaiAhPT0gU3RyaW5nOwogIH0KCiAgZnVuY3Rpb24gaXNBY2Nlc3NvcihkZXNjKSB7CiAgICByZXR1cm4gdHlwZW9mIGRlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBkZXNjLnNldCA9PT0gJ2Z1bmN0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGV4dHJhY3RBY2Nlc3NvcnMocHJvcGVydGllcykgewogICAgaWYgKHByb3BlcnRpZXMgIT09IHVuZGVmaW5lZCkgewogICAgICB2YXIgZGVzY3JpcHRvcnMgPSAoMCwgX3V0aWxzLmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMpKHByb3BlcnRpZXMpOwogICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGRlc2NyaXB0b3JzKTsKICAgICAgdmFyIGhhc0FjY2Vzc29ycyA9IGtleXMuc29tZShmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgcmV0dXJuIGlzQWNjZXNzb3IoZGVzY3JpcHRvcnNba2V5XSk7CiAgICAgIH0pOwoKICAgICAgaWYgKGhhc0FjY2Vzc29ycykgewogICAgICAgIHZhciBleHRyYWN0ZWQgPSB7fTsKICAgICAgICBrZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgdmFyIGRlc2NyaXB0b3IgPSBkZXNjcmlwdG9yc1trZXldOwoKICAgICAgICAgIGlmIChpc0FjY2Vzc29yKGRlc2NyaXB0b3IpKSB7CiAgICAgICAgICAgIGV4dHJhY3RlZFtrZXldID0gbmF0aXZlRGVzY0RlY29yYXRvcihkZXNjcmlwdG9yKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dHJhY3RlZFtrZXldID0gcHJvcGVydGllc1trZXldOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBleHRyYWN0ZWQ7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcHJvcGVydGllczsKICB9CgogIHZhciBDT05USU5VRSA9IHt9OwoKICBmdW5jdGlvbiBtaXhpblByb3BlcnRpZXMobWl4aW5zTWV0YSwgbWl4aW4pIHsKICAgIGlmIChtaXhpbiBpbnN0YW5jZW9mIE1peGluKSB7CiAgICAgIGlmIChtaXhpbnNNZXRhLmhhc01peGluKG1peGluKSkgewogICAgICAgIHJldHVybiBDT05USU5VRTsKICAgICAgfQoKICAgICAgbWl4aW5zTWV0YS5hZGRNaXhpbihtaXhpbik7CiAgICAgIHJldHVybiBtaXhpbi5wcm9wZXJ0aWVzOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG1peGluOyAvLyBhcHBseSBhbm9ueW1vdXMgbWl4aW4gcHJvcGVydGllcwogICAgfQogIH0KCiAgZnVuY3Rpb24gY29uY2F0ZW5hdGVkTWl4aW5Qcm9wZXJ0aWVzKGNvbmNhdFByb3AsIHByb3BzLCB2YWx1ZXMsIGJhc2UpIHsKICAgIC8vIHJlc2V0IGJlZm9yZSBhZGRpbmcgZWFjaCBuZXcgbWl4aW4gdG8gcGlja3VwIGNvbmNhdHMgZnJvbSBwcmV2aW91cwogICAgdmFyIGNvbmNhdHMgPSB2YWx1ZXNbY29uY2F0UHJvcF0gfHwgYmFzZVtjb25jYXRQcm9wXTsKCiAgICBpZiAocHJvcHNbY29uY2F0UHJvcF0pIHsKICAgICAgY29uY2F0cyA9IGNvbmNhdHMgPyBhX2NvbmNhdC5jYWxsKGNvbmNhdHMsIHByb3BzW2NvbmNhdFByb3BdKSA6IHByb3BzW2NvbmNhdFByb3BdOwogICAgfQoKICAgIHJldHVybiBjb25jYXRzOwogIH0KCiAgZnVuY3Rpb24gZ2l2ZURlY29yYXRvclN1cGVyKG1ldGEkJDEsIGtleSwgZGVjb3JhdG9yLCB2YWx1ZXMsIGRlc2NzLCBiYXNlKSB7CiAgICB2YXIgcHJvcGVydHkgPSBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKGRlY29yYXRvcik7CiAgICB2YXIgc3VwZXJQcm9wZXJ0eTsKCiAgICBpZiAoIShwcm9wZXJ0eSBpbnN0YW5jZW9mIENvbXB1dGVkUHJvcGVydHkpIHx8IHByb3BlcnR5Ll9nZXR0ZXIgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gZGVjb3JhdG9yOwogICAgfSAvLyBDb21wdXRlZCBwcm9wZXJ0aWVzIG92ZXJyaWRlIG1ldGhvZHMsIGFuZCBkbyBub3QgY2FsbCBzdXBlciB0byB0aGVtCgoKICAgIGlmICh2YWx1ZXNba2V5XSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIC8vIEZpbmQgdGhlIG9yaWdpbmFsIGRlc2NyaXB0b3IgaW4gYSBwYXJlbnQgbWl4aW4KICAgICAgc3VwZXJQcm9wZXJ0eSA9IGRlc2NyaXB0b3JGb3JEZWNvcmF0b3IoZGVzY3Nba2V5XSk7CiAgICB9IC8vIElmIHdlIGRpZG4ndCBmaW5kIHRoZSBvcmlnaW5hbCBkZXNjcmlwdG9yIGluIGEgcGFyZW50IG1peGluLCBmaW5kCiAgICAvLyBpdCBvbiB0aGUgb3JpZ2luYWwgb2JqZWN0LgoKCiAgICBpZiAoIXN1cGVyUHJvcGVydHkpIHsKICAgICAgc3VwZXJQcm9wZXJ0eSA9IGRlc2NyaXB0b3JGb3JQcm9wZXJ0eShiYXNlLCBrZXksIG1ldGEkJDEpOwogICAgfQoKICAgIGlmIChzdXBlclByb3BlcnR5ID09PSB1bmRlZmluZWQgfHwgIShzdXBlclByb3BlcnR5IGluc3RhbmNlb2YgQ29tcHV0ZWRQcm9wZXJ0eSkpIHsKICAgICAgcmV0dXJuIGRlY29yYXRvcjsKICAgIH0KCiAgICB2YXIgZ2V0ID0gKDAsIF91dGlscy53cmFwKShwcm9wZXJ0eS5fZ2V0dGVyLCBzdXBlclByb3BlcnR5Ll9nZXR0ZXIpOwogICAgdmFyIHNldDsKCiAgICBpZiAoc3VwZXJQcm9wZXJ0eS5fc2V0dGVyKSB7CiAgICAgIGlmIChwcm9wZXJ0eS5fc2V0dGVyKSB7CiAgICAgICAgc2V0ID0gKDAsIF91dGlscy53cmFwKShwcm9wZXJ0eS5fc2V0dGVyLCBzdXBlclByb3BlcnR5Ll9zZXR0ZXIpOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIElmIHRoZSBzdXBlciBwcm9wZXJ0eSBoYXMgYSBzZXR0ZXIsIHdlIGRlZmF1bHQgdG8gdXNpbmcgaXQgbm8gbWF0dGVyIHdoYXQuCiAgICAgICAgLy8gVGhpcyBpcyBjbGVhcmx5IHZlcnkgYnJva2VuIGFuZCB3ZWlyZCwgYnV0IGl0J3Mgd2hhdCB3YXMgaGVyZSBzbyB3ZSBoYXZlCiAgICAgICAgLy8gdG8ga2VlcCBpdCB1bnRpbCB0aGUgbmV4dCBtYWpvciBhdCBsZWFzdC4KICAgICAgICAvLwogICAgICAgIC8vIFRPRE86IEFkZCBhIGRlcHJlY2F0aW9uIGhlcmUuCiAgICAgICAgc2V0ID0gc3VwZXJQcm9wZXJ0eS5fc2V0dGVyOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBzZXQgPSBwcm9wZXJ0eS5fc2V0dGVyOwogICAgfSAvLyBvbmx5IGNyZWF0ZSBhIG5ldyBDUCBpZiB3ZSBtdXN0CgoKICAgIGlmIChnZXQgIT09IHByb3BlcnR5Ll9nZXR0ZXIgfHwgc2V0ICE9PSBwcm9wZXJ0eS5fc2V0dGVyKSB7CiAgICAgIC8vIFNpbmNlIG11bHRpcGxlIG1peGlucyBtYXkgaW5oZXJpdCBmcm9tIHRoZSBzYW1lIHBhcmVudCwgd2UgbmVlZAogICAgICAvLyB0byBjbG9uZSB0aGUgY29tcHV0ZWQgcHJvcGVydHkgc28gdGhhdCBvdGhlciBtaXhpbnMgZG8gbm90IHJlY2VpdmUKICAgICAgLy8gdGhlIHdyYXBwZWQgdmVyc2lvbi4KICAgICAgdmFyIG5ld1Byb3BlcnR5ID0gT2JqZWN0LmNyZWF0ZShwcm9wZXJ0eSk7CiAgICAgIG5ld1Byb3BlcnR5Ll9nZXR0ZXIgPSBnZXQ7CiAgICAgIG5ld1Byb3BlcnR5Ll9zZXR0ZXIgPSBzZXQ7CiAgICAgIHJldHVybiBtYWtlQ29tcHV0ZWREZWNvcmF0b3IobmV3UHJvcGVydHksIENvbXB1dGVkUHJvcGVydHkpOwogICAgfQoKICAgIHJldHVybiBkZWNvcmF0b3I7CiAgfQoKICBmdW5jdGlvbiBnaXZlTWV0aG9kU3VwZXIob2JqLCBrZXksIG1ldGhvZCwgdmFsdWVzLCBkZXNjcykgewogICAgLy8gTWV0aG9kcyBvdmVyd3JpdGUgY29tcHV0ZWQgcHJvcGVydGllcywgYW5kIGRvIG5vdCBjYWxsIHN1cGVyIHRvIHRoZW0uCiAgICBpZiAoZGVzY3Nba2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBtZXRob2Q7CiAgICB9IC8vIEZpbmQgdGhlIG9yaWdpbmFsIG1ldGhvZCBpbiBhIHBhcmVudCBtaXhpbgoKCiAgICB2YXIgc3VwZXJNZXRob2QgPSB2YWx1ZXNba2V5XTsgLy8gSWYgd2UgZGlkbid0IGZpbmQgdGhlIG9yaWdpbmFsIHZhbHVlIGluIGEgcGFyZW50IG1peGluLCBmaW5kIGl0IGluCiAgICAvLyB0aGUgb3JpZ2luYWwgb2JqZWN0CgogICAgaWYgKHN1cGVyTWV0aG9kID09PSB1bmRlZmluZWQgJiYgZGVzY3JpcHRvckZvclByb3BlcnR5KG9iaiwga2V5KSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHN1cGVyTWV0aG9kID0gb2JqW2tleV07CiAgICB9IC8vIE9ubHkgd3JhcCB0aGUgbmV3IG1ldGhvZCBpZiB0aGUgb3JpZ2luYWwgbWV0aG9kIHdhcyBhIGZ1bmN0aW9uCgoKICAgIGlmICh0eXBlb2Ygc3VwZXJNZXRob2QgPT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuICgwLCBfdXRpbHMud3JhcCkobWV0aG9kLCBzdXBlck1ldGhvZCk7CiAgICB9CgogICAgcmV0dXJuIG1ldGhvZDsKICB9CgogIGZ1bmN0aW9uIGFwcGx5Q29uY2F0ZW5hdGVkUHJvcGVydGllcyhvYmosIGtleSwgdmFsdWUkJDEsIHZhbHVlcykgewogICAgdmFyIGJhc2VWYWx1ZSA9IHZhbHVlc1trZXldIHx8IG9ialtrZXldOwogICAgdmFyIHJldCA9ICgwLCBfdXRpbHMubWFrZUFycmF5KShiYXNlVmFsdWUpLmNvbmNhdCgoMCwgX3V0aWxzLm1ha2VBcnJheSkodmFsdWUkJDEpKTsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgLy8gaXQgaXMgcG9zc2libGUgdG8gdXNlIGNvbmNhdGVuYXRlZFByb3BlcnRpZXMgd2l0aCBzdHJpbmdzICh3aGljaCBjYW5ub3QgYmUgZnJvemVuKQogICAgICAvLyBvbmx5IGZyZWV6ZSBvYmplY3RzLi4uCiAgICAgIGlmICh0eXBlb2YgcmV0ID09PSAnb2JqZWN0JyAmJiByZXQgIT09IG51bGwpIHsKICAgICAgICAvLyBwcmV2ZW50IG11dGF0aW5nIGBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzYCBhcnJheSBhZnRlciBpdCBpcyBhcHBsaWVkCiAgICAgICAgT2JqZWN0LmZyZWV6ZShyZXQpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJldDsKICB9CgogIGZ1bmN0aW9uIGFwcGx5TWVyZ2VkUHJvcGVydGllcyhvYmosIGtleSwgdmFsdWUkJDEsIHZhbHVlcykgewogICAgdmFyIGJhc2VWYWx1ZSA9IHZhbHVlc1trZXldIHx8IG9ialtrZXldOwogICAgKGZhbHNlICYmICEoIWlzQXJyYXkodmFsdWUkJDEpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBwYXNzZWQgaW4gYCIgKyBKU09OLnN0cmluZ2lmeSh2YWx1ZSQkMSkgKyAiYCBhcyB0aGUgdmFsdWUgZm9yIGAiICsga2V5ICsgImAgYnV0IGAiICsga2V5ICsgImAgY2Fubm90IGJlIGFuIEFycmF5IiwgIWlzQXJyYXkodmFsdWUkJDEpKSk7CgogICAgaWYgKCFiYXNlVmFsdWUpIHsKICAgICAgcmV0dXJuIHZhbHVlJCQxOwogICAgfQoKICAgIHZhciBuZXdCYXNlID0gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgYmFzZVZhbHVlKTsKICAgIHZhciBoYXNGdW5jdGlvbiA9IGZhbHNlOwoKICAgIGZvciAodmFyIHByb3AgaW4gdmFsdWUkJDEpIHsKICAgICAgaWYgKCF2YWx1ZSQkMS5oYXNPd25Qcm9wZXJ0eShwcm9wKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICB2YXIgcHJvcFZhbHVlID0gdmFsdWUkJDFbcHJvcF07CgogICAgICBpZiAoaXNNZXRob2QocHJvcFZhbHVlKSkgewogICAgICAgIC8vIFRPRE86IHN1cHBvcnQgZm9yIENvbXB1dGVkIFByb3BlcnRpZXMsIGV0Yz8KICAgICAgICBoYXNGdW5jdGlvbiA9IHRydWU7CiAgICAgICAgbmV3QmFzZVtwcm9wXSA9IGdpdmVNZXRob2RTdXBlcihvYmosIHByb3AsIHByb3BWYWx1ZSwgYmFzZVZhbHVlLCB7fSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmV3QmFzZVtwcm9wXSA9IHByb3BWYWx1ZTsKICAgICAgfQogICAgfQoKICAgIGlmIChoYXNGdW5jdGlvbikgewogICAgICBuZXdCYXNlLl9zdXBlciA9IF91dGlscy5ST09UOwogICAgfQoKICAgIHJldHVybiBuZXdCYXNlOwogIH0KCiAgZnVuY3Rpb24gYWRkTm9ybWFsaXplZFByb3BlcnR5KGJhc2UsIGtleSwgdmFsdWUkJDEsIG1ldGEkJDEsIGRlc2NzLCB2YWx1ZXMsIGNvbmNhdHMsIG1lcmdpbmdzKSB7CiAgICBpZiAoaXNDbGFzc2ljRGVjb3JhdG9yKHZhbHVlJCQxKSkgewogICAgICAvLyBXcmFwIGRlc2NyaXB0b3IgZnVuY3Rpb24gdG8gaW1wbGVtZW50IF9zdXBlcigpIGlmIG5lZWRlZAogICAgICBkZXNjc1trZXldID0gZ2l2ZURlY29yYXRvclN1cGVyKG1ldGEkJDEsIGtleSwgdmFsdWUkJDEsIHZhbHVlcywgZGVzY3MsIGJhc2UpOwogICAgICB2YWx1ZXNba2V5XSA9IHVuZGVmaW5lZDsKICAgIH0gZWxzZSB7CiAgICAgIGlmIChjb25jYXRzICYmIGNvbmNhdHMuaW5kZXhPZihrZXkpID49IDAgfHwga2V5ID09PSAnY29uY2F0ZW5hdGVkUHJvcGVydGllcycgfHwga2V5ID09PSAnbWVyZ2VkUHJvcGVydGllcycpIHsKICAgICAgICB2YWx1ZSQkMSA9IGFwcGx5Q29uY2F0ZW5hdGVkUHJvcGVydGllcyhiYXNlLCBrZXksIHZhbHVlJCQxLCB2YWx1ZXMpOwogICAgICB9IGVsc2UgaWYgKG1lcmdpbmdzICYmIG1lcmdpbmdzLmluZGV4T2Yoa2V5KSA+IC0xKSB7CiAgICAgICAgdmFsdWUkJDEgPSBhcHBseU1lcmdlZFByb3BlcnRpZXMoYmFzZSwga2V5LCB2YWx1ZSQkMSwgdmFsdWVzKTsKICAgICAgfSBlbHNlIGlmIChpc01ldGhvZCh2YWx1ZSQkMSkpIHsKICAgICAgICB2YWx1ZSQkMSA9IGdpdmVNZXRob2RTdXBlcihiYXNlLCBrZXksIHZhbHVlJCQxLCB2YWx1ZXMsIGRlc2NzKTsKICAgICAgfQoKICAgICAgZGVzY3Nba2V5XSA9IHVuZGVmaW5lZDsKICAgICAgdmFsdWVzW2tleV0gPSB2YWx1ZSQkMTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIG1lcmdlTWl4aW5zKG1peGlucywgbWV0YSQkMSwgZGVzY3MsIHZhbHVlcywgYmFzZSwga2V5cykgewogICAgdmFyIGN1cnJlbnRNaXhpbiwgcHJvcHMsIGtleSwgY29uY2F0cywgbWVyZ2luZ3M7CgogICAgZnVuY3Rpb24gcmVtb3ZlS2V5cyhrZXlOYW1lKSB7CiAgICAgIGRlbGV0ZSBkZXNjc1trZXlOYW1lXTsKICAgICAgZGVsZXRlIHZhbHVlc1trZXlOYW1lXTsKICAgIH0KCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1peGlucy5sZW5ndGg7IGkrKykgewogICAgICBjdXJyZW50TWl4aW4gPSBtaXhpbnNbaV07CiAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBjdXJyZW50TWl4aW4gPT09ICdvYmplY3QnICYmIGN1cnJlbnRNaXhpbiAhPT0gbnVsbCAmJiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoY3VycmVudE1peGluKSAhPT0gJ1tvYmplY3QgQXJyYXldJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJFeHBlY3RlZCBoYXNoIG9yIE1peGluIGluc3RhbmNlLCBnb3QgIiArIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChjdXJyZW50TWl4aW4pLCB0eXBlb2YgY3VycmVudE1peGluID09PSAnb2JqZWN0JyAmJiBjdXJyZW50TWl4aW4gIT09IG51bGwgJiYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGN1cnJlbnRNaXhpbikgIT09ICdbb2JqZWN0IEFycmF5XScpKTsKICAgICAgcHJvcHMgPSBtaXhpblByb3BlcnRpZXMobWV0YSQkMSwgY3VycmVudE1peGluKTsKCiAgICAgIGlmIChwcm9wcyA9PT0gQ09OVElOVUUpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQoKICAgICAgaWYgKHByb3BzKSB7CiAgICAgICAgLy8gcmVtb3ZlIHdpbGxNZXJnZU1peGluIGFmdGVyIDMuNCBhcyBpdCB3YXMgdXNlZCBmb3IgX2FjdGlvbnMKICAgICAgICBpZiAoYmFzZS53aWxsTWVyZ2VNaXhpbikgewogICAgICAgICAgYmFzZS53aWxsTWVyZ2VNaXhpbihwcm9wcyk7CiAgICAgICAgfQoKICAgICAgICBjb25jYXRzID0gY29uY2F0ZW5hdGVkTWl4aW5Qcm9wZXJ0aWVzKCdjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzJywgcHJvcHMsIHZhbHVlcywgYmFzZSk7CiAgICAgICAgbWVyZ2luZ3MgPSBjb25jYXRlbmF0ZWRNaXhpblByb3BlcnRpZXMoJ21lcmdlZFByb3BlcnRpZXMnLCBwcm9wcywgdmFsdWVzLCBiYXNlKTsKCiAgICAgICAgZm9yIChrZXkgaW4gcHJvcHMpIHsKICAgICAgICAgIGlmICghcHJvcHMuaGFzT3duUHJvcGVydHkoa2V5KSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KCiAgICAgICAgICBrZXlzLnB1c2goa2V5KTsKICAgICAgICAgIGFkZE5vcm1hbGl6ZWRQcm9wZXJ0eShiYXNlLCBrZXksIHByb3BzW2tleV0sIG1ldGEkJDEsIGRlc2NzLCB2YWx1ZXMsIGNvbmNhdHMsIG1lcmdpbmdzKTsKICAgICAgICB9IC8vIG1hbnVhbGx5IGNvcHkgdG9TdHJpbmcoKSBiZWNhdXNlIHNvbWUgSlMgZW5naW5lcyBkbyBub3QgZW51bWVyYXRlIGl0CgoKICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoJ3RvU3RyaW5nJykpIHsKICAgICAgICAgIGJhc2UudG9TdHJpbmcgPSBwcm9wcy50b1N0cmluZzsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY3VycmVudE1peGluLm1peGlucykgewogICAgICAgIG1lcmdlTWl4aW5zKGN1cnJlbnRNaXhpbi5taXhpbnMsIG1ldGEkJDEsIGRlc2NzLCB2YWx1ZXMsIGJhc2UsIGtleXMpOwoKICAgICAgICBpZiAoY3VycmVudE1peGluLl93aXRob3V0KSB7CiAgICAgICAgICBjdXJyZW50TWl4aW4uX3dpdGhvdXQuZm9yRWFjaChyZW1vdmVLZXlzKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CgogIHZhciBmb2xsb3dNZXRob2RBbGlhczsKCiAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuQUxJQVNfTUVUSE9EKSB7CiAgICBmb2xsb3dNZXRob2RBbGlhcyA9IGZ1bmN0aW9uIGZvbGxvd01ldGhvZEFsaWFzKG9iaiwgYWxpYXMsIGRlc2NzLCB2YWx1ZXMpIHsKICAgICAgdmFyIGFsdEtleSA9IGFsaWFzLm1ldGhvZE5hbWU7CiAgICAgIHZhciBwb3NzaWJsZURlc2M7CiAgICAgIHZhciBkZXNjID0gZGVzY3NbYWx0S2V5XTsKICAgICAgdmFyIHZhbHVlJCQxID0gdmFsdWVzW2FsdEtleV07CgogICAgICBpZiAoZGVzYyAhPT0gdW5kZWZpbmVkIHx8IHZhbHVlJCQxICE9PSB1bmRlZmluZWQpIHsvLyBkbyBub3RoaW5nCiAgICAgIH0gZWxzZSBpZiAoKHBvc3NpYmxlRGVzYyA9IGRlc2NyaXB0b3JGb3JQcm9wZXJ0eShvYmosIGFsdEtleSkpICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBkZXNjID0gcG9zc2libGVEZXNjOwogICAgICAgIHZhbHVlJCQxID0gdW5kZWZpbmVkOwogICAgICB9IGVsc2UgewogICAgICAgIGRlc2MgPSB1bmRlZmluZWQ7CiAgICAgICAgdmFsdWUkJDEgPSBvYmpbYWx0S2V5XTsKICAgICAgfQoKICAgICAgcmV0dXJuIHsKICAgICAgICBkZXNjOiBkZXNjLAogICAgICAgIHZhbHVlOiB2YWx1ZSQkMQogICAgICB9OwogICAgfTsKICB9CgogIGZ1bmN0aW9uIHVwZGF0ZU9ic2VydmVyc0FuZExpc3RlbmVycyhvYmosIGtleSwgZm4sIGFkZCkgewogICAgdmFyIG9ic2VydmVycyA9ICgwLCBfdXRpbHMuZ2V0T2JzZXJ2ZXJzKShmbik7CiAgICB2YXIgbGlzdGVuZXJzID0gKDAsIF91dGlscy5nZXRMaXN0ZW5lcnMpKGZuKTsKCiAgICBpZiAob2JzZXJ2ZXJzICE9PSB1bmRlZmluZWQpIHsKICAgICAgdmFyIHVwZGF0ZU9ic2VydmVyID0gYWRkID8gYWRkT2JzZXJ2ZXIgOiByZW1vdmVPYnNlcnZlcjsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JzZXJ2ZXJzLnBhdGhzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdXBkYXRlT2JzZXJ2ZXIob2JqLCBvYnNlcnZlcnMucGF0aHNbaV0sIG51bGwsIGtleSwgb2JzZXJ2ZXJzLnN5bmMpOwogICAgICB9CiAgICB9CgogICAgaWYgKGxpc3RlbmVycyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHZhciB1cGRhdGVMaXN0ZW5lciA9IGFkZCA/IGFkZExpc3RlbmVyIDogcmVtb3ZlTGlzdGVuZXI7CgogICAgICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBsaXN0ZW5lcnMubGVuZ3RoOyBfaTIrKykgewogICAgICAgIHVwZGF0ZUxpc3RlbmVyKG9iaiwgbGlzdGVuZXJzW19pMl0sIG51bGwsIGtleSk7CiAgICAgIH0KICAgIH0KICB9CgogIGZ1bmN0aW9uIHJlcGxhY2VPYnNlcnZlcnNBbmRMaXN0ZW5lcnMob2JqLCBrZXksIHByZXYsIG5leHQpIHsKICAgIGlmICh0eXBlb2YgcHJldiA9PT0gJ2Z1bmN0aW9uJykgewogICAgICB1cGRhdGVPYnNlcnZlcnNBbmRMaXN0ZW5lcnMob2JqLCBrZXksIHByZXYsIGZhbHNlKTsKICAgIH0KCiAgICBpZiAodHlwZW9mIG5leHQgPT09ICdmdW5jdGlvbicpIHsKICAgICAgdXBkYXRlT2JzZXJ2ZXJzQW5kTGlzdGVuZXJzKG9iaiwga2V5LCBuZXh0LCB0cnVlKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGFwcGx5TWl4aW4ob2JqLCBtaXhpbnMpIHsKICAgIHZhciBkZXNjcyA9IHt9OwogICAgdmFyIHZhbHVlcyA9IHt9OwogICAgdmFyIG1ldGEkJDEgPSAoMCwgX21ldGEyLm1ldGEpKG9iaik7CiAgICB2YXIga2V5cyA9IFtdOwogICAgdmFyIGtleSwgdmFsdWUkJDEsIGRlc2M7CiAgICBvYmouX3N1cGVyID0gX3V0aWxzLlJPT1Q7IC8vIEdvIHRocm91Z2ggYWxsIG1peGlucyBhbmQgaGFzaGVzIHBhc3NlZCBpbiwgYW5kOgogICAgLy8KICAgIC8vICogSGFuZGxlIGNvbmNhdGVuYXRlZCBwcm9wZXJ0aWVzCiAgICAvLyAqIEhhbmRsZSBtZXJnZWQgcHJvcGVydGllcwogICAgLy8gKiBTZXQgdXAgX3N1cGVyIHdyYXBwaW5nIGlmIG5lY2Vzc2FyeQogICAgLy8gKiBTZXQgdXAgY29tcHV0ZWQgcHJvcGVydHkgZGVzY3JpcHRvcnMKICAgIC8vICogQ29weWluZyBgdG9TdHJpbmdgIGluIGJyb2tlbiBicm93c2VycwoKICAgIG1lcmdlTWl4aW5zKG1peGlucywgbWV0YSQkMSwgZGVzY3MsIHZhbHVlcywgb2JqLCBrZXlzKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgICAga2V5ID0ga2V5c1tpXTsKCiAgICAgIGlmIChrZXkgPT09ICdjb25zdHJ1Y3RvcicgfHwgIXZhbHVlcy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIGRlc2MgPSBkZXNjc1trZXldOwogICAgICB2YWx1ZSQkMSA9IHZhbHVlc1trZXldOwoKICAgICAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuQUxJQVNfTUVUSE9EKSB7CiAgICAgICAgd2hpbGUgKHZhbHVlJCQxICYmIHZhbHVlJCQxIGluc3RhbmNlb2YgQWxpYXNJbXBsKSB7CiAgICAgICAgICB2YXIgZm9sbG93ZWQgPSBmb2xsb3dNZXRob2RBbGlhcyhvYmosIHZhbHVlJCQxLCBkZXNjcywgdmFsdWVzKTsKICAgICAgICAgIGRlc2MgPSBmb2xsb3dlZC5kZXNjOwogICAgICAgICAgdmFsdWUkJDEgPSBmb2xsb3dlZC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChkZXNjID09PSB1bmRlZmluZWQgJiYgdmFsdWUkJDEgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICBpZiAoZGVzY3JpcHRvckZvclByb3BlcnR5KG9iaiwga2V5KSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmVwbGFjZU9ic2VydmVyc0FuZExpc3RlbmVycyhvYmosIGtleSwgbnVsbCwgdmFsdWUkJDEpOwogICAgICB9IGVsc2UgewogICAgICAgIHJlcGxhY2VPYnNlcnZlcnNBbmRMaXN0ZW5lcnMob2JqLCBrZXksIG9ialtrZXldLCB2YWx1ZSQkMSk7CiAgICAgIH0KCiAgICAgIGRlZmluZVByb3BlcnR5KG9iaiwga2V5LCBkZXNjLCB2YWx1ZSQkMSwgbWV0YSQkMSk7CiAgICB9CgogICAgcmV0dXJuIG9iajsKICB9CiAgLyoqCiAgICBAbWV0aG9kIG1peGluCiAgICBAcGFyYW0gb2JqCiAgICBAcGFyYW0gbWl4aW5zKgogICAgQHJldHVybiBvYmoKICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIG1peGluKG9iaikgewogICAgZm9yICh2YXIgX2xlbjQgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW40ID4gMSA/IF9sZW40IC0gMSA6IDApLCBfa2V5NSA9IDE7IF9rZXk1IDwgX2xlbjQ7IF9rZXk1KyspIHsKICAgICAgYXJnc1tfa2V5NSAtIDFdID0gYXJndW1lbnRzW19rZXk1XTsKICAgIH0KCiAgICBhcHBseU1peGluKG9iaiwgYXJncyk7CiAgICByZXR1cm4gb2JqOwogIH0KICAvKioKICAgIFRoZSBgTWl4aW5gIGNsYXNzIGFsbG93cyB5b3UgdG8gY3JlYXRlIG1peGlucywgd2hvc2UgcHJvcGVydGllcyBjYW4gYmUKICAgIGFkZGVkIHRvIG90aGVyIGNsYXNzZXMuIEZvciBpbnN0YW5jZSwKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBNaXhpbiBmcm9tICdAZW1iZXIvb2JqZWN0L21peGluJzsKICAKICAgIGNvbnN0IEVkaXRhYmxlTWl4aW4gPSBNaXhpbi5jcmVhdGUoewogICAgICBlZGl0KCkgewogICAgICAgIGNvbnNvbGUubG9nKCdzdGFydGluZyB0byBlZGl0Jyk7CiAgICAgICAgdGhpcy5zZXQoJ2lzRWRpdGluZycsIHRydWUpOwogICAgICB9LAogICAgICBpc0VkaXRpbmc6IGZhbHNlCiAgICB9KTsKICAgIGBgYAogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IEVkaXRhYmxlTWl4aW4gZnJvbSAnLi4vbWl4aW5zL2VkaXRhYmxlJzsKICAKICAgIC8vIE1peCBtaXhpbnMgaW50byBjbGFzc2VzIGJ5IHBhc3NpbmcgdGhlbSBhcyB0aGUgZmlyc3QgYXJndW1lbnRzIHRvCiAgICAvLyBgLmV4dGVuZC5gCiAgICBjb25zdCBDb21tZW50ID0gRW1iZXJPYmplY3QuZXh0ZW5kKEVkaXRhYmxlTWl4aW4sIHsKICAgICAgcG9zdDogbnVsbAogICAgfSk7CiAgCiAgICBsZXQgY29tbWVudCA9IENvbW1lbnQuY3JlYXRlKHsKICAgICAgcG9zdDogc29tZVBvc3QKICAgIH0pOwogIAogICAgY29tbWVudC5lZGl0KCk7IC8vIG91dHB1dHMgJ3N0YXJ0aW5nIHRvIGVkaXQnCiAgICBgYGAKICAKICAgIE5vdGUgdGhhdCBNaXhpbnMgYXJlIGNyZWF0ZWQgd2l0aCBgTWl4aW4uY3JlYXRlYCwgbm90CiAgICBgTWl4aW4uZXh0ZW5kYC4KICAKICAgIE5vdGUgdGhhdCBtaXhpbnMgZXh0ZW5kIGEgY29uc3RydWN0b3IncyBwcm90b3R5cGUgc28gYXJyYXlzIGFuZCBvYmplY3QgbGl0ZXJhbHMKICAgIGRlZmluZWQgYXMgcHJvcGVydGllcyB3aWxsIGJlIHNoYXJlZCBhbW9uZ3N0IG9iamVjdHMgdGhhdCBpbXBsZW1lbnQgdGhlIG1peGluLgogICAgSWYgeW91IHdhbnQgdG8gZGVmaW5lIGEgcHJvcGVydHkgaW4gYSBtaXhpbiB0aGF0IGlzIG5vdCBzaGFyZWQsIHlvdSBjYW4gZGVmaW5lCiAgICBpdCBlaXRoZXIgYXMgYSBjb21wdXRlZCBwcm9wZXJ0eSBvciBoYXZlIGl0IGJlIGNyZWF0ZWQgb24gaW5pdGlhbGl6YXRpb24gb2YgdGhlIG9iamVjdC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIC8vIGZpbHRlcnMgYXJyYXkgd2lsbCBiZSBzaGFyZWQgYW1vbmdzdCBhbnkgb2JqZWN0IGltcGxlbWVudGluZyBtaXhpbgogICAgaW1wb3J0IE1peGluIGZyb20gJ0BlbWJlci9vYmplY3QvbWl4aW4nOwogICAgaW1wb3J0IHsgQSB9IGZyb20gJ0BlbWJlci9hcnJheSc7CiAgCiAgICBjb25zdCBGaWx0ZXJhYmxlTWl4aW4gPSBNaXhpbi5jcmVhdGUoewogICAgICBmaWx0ZXJzOiBBKCkKICAgIH0pOwogICAgYGBgCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgTWl4aW4gZnJvbSAnQGVtYmVyL29iamVjdC9taXhpbic7CiAgICBpbXBvcnQgeyBBIH0gZnJvbSAnQGVtYmVyL2FycmF5JzsKICAgIGltcG9ydCB7IGNvbXB1dGVkIH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgCiAgICAvLyBmaWx0ZXJzIHdpbGwgYmUgYSBzZXBhcmF0ZSBhcnJheSBmb3IgZXZlcnkgb2JqZWN0IGltcGxlbWVudGluZyB0aGUgbWl4aW4KICAgIGNvbnN0IEZpbHRlcmFibGVNaXhpbiA9IE1peGluLmNyZWF0ZSh7CiAgICAgIGZpbHRlcnM6IGNvbXB1dGVkKGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBBKCk7CiAgICAgIH0pCiAgICB9KTsKICAgIGBgYAogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IE1peGluIGZyb20gJ0BlbWJlci9vYmplY3QvbWl4aW4nOwogICAgaW1wb3J0IHsgQSB9IGZyb20gJ0BlbWJlci9hcnJheSc7CiAgCiAgICAvLyBmaWx0ZXJzIHdpbGwgYmUgY3JlYXRlZCBhcyBhIHNlcGFyYXRlIGFycmF5IGR1cmluZyB0aGUgb2JqZWN0J3MgaW5pdGlhbGl6YXRpb24KICAgIGNvbnN0IEZpbHRlcmFibGUgPSBNaXhpbi5jcmVhdGUoewogICAgICBmaWx0ZXJzOiBudWxsLAogIAogICAgICBpbml0KCkgewogICAgICAgIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cyk7CiAgICAgICAgdGhpcy5zZXQoImZpbHRlcnMiLCBBKCkpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQGNsYXNzIE1peGluCiAgICBAcHVibGljCiAgKi8KCgogIHZhciBNaXhpbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIE1peGluKG1peGlucywgcHJvcGVydGllcykgewogICAgICB0aGlzLnByb3BlcnRpZXMgPSBleHRyYWN0QWNjZXNzb3JzKHByb3BlcnRpZXMpOwogICAgICB0aGlzLm1peGlucyA9IGJ1aWxkTWl4aW5zQXJyYXkobWl4aW5zKTsKICAgICAgdGhpcy5vd25lckNvbnN0cnVjdG9yID0gdW5kZWZpbmVkOwogICAgICB0aGlzLl93aXRob3V0ID0gdW5kZWZpbmVkOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIC8qCiAgICAgICAgICBJbiBkZWJ1ZyBidWlsZHMsIHdlIHNlYWwgbWl4aW5zIHRvIGhlbHAgYXZvaWQgcGVyZm9ybWFuY2UgcGl0ZmFsbHMuCiAgICAgICAgICAgICAgICAgSW4gSUUxMSB0aGVyZSBpcyBhIHF1aXJrIHRoYXQgcHJldmVudHMgc2VhbGVkIG9iamVjdHMgZnJvbSBiZWluZyBhZGRlZAogICAgICAgICAgdG8gYSBXZWFrTWFwLiBVbmZvcnR1bmF0ZWx5LCB0aGUgbWl4aW4gc3lzdGVtIGN1cnJlbnRseSByZWxpZXMgb24KICAgICAgICAgIHdlYWsgbWFwcyBpbiBgZ3VpZEZvcmAsIHNvIHdlIG5lZWQgdG8gcHJpbWUgdGhlIGd1aWQgY2FjaGUgd2VhayBtYXAuCiAgICAgICAgKi8KICAgICAgICAoMCwgX3V0aWxzLmd1aWRGb3IpKHRoaXMpOwogICAgICAgIE9iamVjdC5zZWFsKHRoaXMpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgQG1ldGhvZCBjcmVhdGUKICAgICAgQGZvciBAZW1iZXIvb2JqZWN0L21peGluCiAgICAgIEBzdGF0aWMKICAgICAgQHBhcmFtIGFyZ3VtZW50cyoKICAgICAgQHB1YmxpYwogICAgKi8KCgogICAgTWl4aW4uY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKCkgewogICAgICAvLyBFUzZUT0RPOiB0aGlzIHJlbGllcyBvbiBhIGdsb2JhbCBzdGF0ZT8KICAgICAgc2V0VW5wcm9jZXNzZWRNaXhpbnMoKTsKICAgICAgdmFyIE0gPSB0aGlzOwoKICAgICAgZm9yICh2YXIgX2xlbjUgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW41KSwgX2tleTYgPSAwOyBfa2V5NiA8IF9sZW41OyBfa2V5NisrKSB7CiAgICAgICAgYXJnc1tfa2V5Nl0gPSBhcmd1bWVudHNbX2tleTZdOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IE0oYXJncywgdW5kZWZpbmVkKTsKICAgIH0gLy8gcmV0dXJucyB0aGUgbWl4aW5zIGN1cnJlbnRseSBhcHBsaWVkIHRvIHRoZSBzcGVjaWZpZWQgb2JqZWN0CiAgICAvLyBUT0RPOiBNYWtlIGBtaXhpbmAKICAgIDsKCiAgICBNaXhpbi5taXhpbnMgPSBmdW5jdGlvbiBtaXhpbnMob2JqKSB7CiAgICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkob2JqKTsKICAgICAgdmFyIHJldCA9IFtdOwoKICAgICAgaWYgKG1ldGEkJDEgPT09IG51bGwpIHsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9CgogICAgICBtZXRhJCQxLmZvckVhY2hNaXhpbnMoZnVuY3Rpb24gKGN1cnJlbnRNaXhpbikgewogICAgICAgIC8vIHNraXAgcHJpbWl0aXZlIG1peGlucyBzaW5jZSB0aGVzZSBhcmUgYWx3YXlzIGFub255bW91cwogICAgICAgIGlmICghY3VycmVudE1peGluLnByb3BlcnRpZXMpIHsKICAgICAgICAgIHJldC5wdXNoKGN1cnJlbnRNaXhpbik7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIHJldDsKICAgIH0KICAgIC8qKgogICAgICBAbWV0aG9kIHJlb3BlbgogICAgICBAcGFyYW0gYXJndW1lbnRzKgogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICB2YXIgX3Byb3RvMTIgPSBNaXhpbi5wcm90b3R5cGU7CgogICAgX3Byb3RvMTIucmVvcGVuID0gZnVuY3Rpb24gcmVvcGVuKCkgewogICAgICBmb3IgKHZhciBfbGVuNiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjYpLCBfa2V5NyA9IDA7IF9rZXk3IDwgX2xlbjY7IF9rZXk3KyspIHsKICAgICAgICBhcmdzW19rZXk3XSA9IGFyZ3VtZW50c1tfa2V5N107CiAgICAgIH0KCiAgICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgaWYgKHRoaXMucHJvcGVydGllcykgewogICAgICAgIHZhciBjdXJyZW50TWl4aW4gPSBuZXcgTWl4aW4odW5kZWZpbmVkLCB0aGlzLnByb3BlcnRpZXMpOwogICAgICAgIHRoaXMucHJvcGVydGllcyA9IHVuZGVmaW5lZDsKICAgICAgICB0aGlzLm1peGlucyA9IFtjdXJyZW50TWl4aW5dOwogICAgICB9IGVsc2UgaWYgKCF0aGlzLm1peGlucykgewogICAgICAgIHRoaXMubWl4aW5zID0gW107CiAgICAgIH0KCiAgICAgIHRoaXMubWl4aW5zID0gdGhpcy5taXhpbnMuY29uY2F0KGJ1aWxkTWl4aW5zQXJyYXkoYXJncykpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0KICAgIC8qKgogICAgICBAbWV0aG9kIGFwcGx5CiAgICAgIEBwYXJhbSBvYmoKICAgICAgQHJldHVybiBhcHBsaWVkIG9iamVjdAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8xMi5hcHBseSA9IGZ1bmN0aW9uIGFwcGx5KG9iaikgewogICAgICByZXR1cm4gYXBwbHlNaXhpbihvYmosIFt0aGlzXSk7CiAgICB9OwoKICAgIF9wcm90bzEyLmFwcGx5UGFydGlhbCA9IGZ1bmN0aW9uIGFwcGx5UGFydGlhbChvYmopIHsKICAgICAgcmV0dXJuIGFwcGx5TWl4aW4ob2JqLCBbdGhpc10pOwogICAgfQogICAgLyoqCiAgICAgIEBtZXRob2QgZGV0ZWN0CiAgICAgIEBwYXJhbSBvYmoKICAgICAgQHJldHVybiB7Qm9vbGVhbn0KICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvMTIuZGV0ZWN0ID0gZnVuY3Rpb24gZGV0ZWN0KG9iaikgewogICAgICBpZiAodHlwZW9mIG9iaiAhPT0gJ29iamVjdCcgfHwgb2JqID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CgogICAgICBpZiAob2JqIGluc3RhbmNlb2YgTWl4aW4pIHsKICAgICAgICByZXR1cm4gX2RldGVjdChvYmosIHRoaXMpOwogICAgICB9CgogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaik7CgogICAgICBpZiAobWV0YSQkMSA9PT0gbnVsbCkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgcmV0dXJuIG1ldGEkJDEuaGFzTWl4aW4odGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzEyLndpdGhvdXQgPSBmdW5jdGlvbiB3aXRob3V0KCkgewogICAgICB2YXIgcmV0ID0gbmV3IE1peGluKFt0aGlzXSk7CgogICAgICBmb3IgKHZhciBfbGVuNyA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjcpLCBfa2V5OCA9IDA7IF9rZXk4IDwgX2xlbjc7IF9rZXk4KyspIHsKICAgICAgICBhcmdzW19rZXk4XSA9IGFyZ3VtZW50c1tfa2V5OF07CiAgICAgIH0KCiAgICAgIHJldC5fd2l0aG91dCA9IGFyZ3M7CiAgICAgIHJldHVybiByZXQ7CiAgICB9OwoKICAgIF9wcm90bzEyLmtleXMgPSBmdW5jdGlvbiBrZXlzKCkgewogICAgICByZXR1cm4gX2tleXModGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzEyLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiAnKHVua25vd24gbWl4aW4pJzsKICAgIH07CgogICAgcmV0dXJuIE1peGluOwogIH0oKTsKCiAgX2V4cG9ydHMuTWl4aW4gPSBNaXhpbjsKCiAgZnVuY3Rpb24gYnVpbGRNaXhpbnNBcnJheShtaXhpbnMpIHsKICAgIHZhciBsZW5ndGggPSBtaXhpbnMgJiYgbWl4aW5zLmxlbmd0aCB8fCAwOwogICAgdmFyIG0gPSB1bmRlZmluZWQ7CgogICAgaWYgKGxlbmd0aCA+IDApIHsKICAgICAgbSA9IG5ldyBBcnJheShsZW5ndGgpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgIHZhciB4ID0gbWl4aW5zW2ldOwogICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiB4ID09PSAnb2JqZWN0JyAmJiB4ICE9PSBudWxsICYmIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KSAhPT0gJ1tvYmplY3QgQXJyYXldJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJFeHBlY3RlZCBoYXNoIG9yIE1peGluIGluc3RhbmNlLCBnb3QgIiArIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KSwgdHlwZW9mIHggPT09ICdvYmplY3QnICYmIHggIT09IG51bGwgJiYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHgpICE9PSAnW29iamVjdCBBcnJheV0nKSk7CgogICAgICAgIGlmICh4IGluc3RhbmNlb2YgTWl4aW4pIHsKICAgICAgICAgIG1baV0gPSB4OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBtW2ldID0gbmV3IE1peGluKHVuZGVmaW5lZCwgeCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgcmV0dXJuIG07CiAgfQoKICBNaXhpbi5wcm90b3R5cGUudG9TdHJpbmcgPSBjbGFzc1RvU3RyaW5nOwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgT2JqZWN0LnNlYWwoTWl4aW4ucHJvdG90eXBlKTsKICB9CgogIGZ1bmN0aW9uIF9kZXRlY3QoY3VyTWl4aW4sIHRhcmdldE1peGluLCBzZWVuKSB7CiAgICBpZiAoc2VlbiA9PT0gdm9pZCAwKSB7CiAgICAgIHNlZW4gPSBuZXcgU2V0KCk7CiAgICB9CgogICAgaWYgKHNlZW4uaGFzKGN1ck1peGluKSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgc2Vlbi5hZGQoY3VyTWl4aW4pOwoKICAgIGlmIChjdXJNaXhpbiA9PT0gdGFyZ2V0TWl4aW4pIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgdmFyIG1peGlucyA9IGN1ck1peGluLm1peGluczsKCiAgICBpZiAobWl4aW5zKSB7CiAgICAgIHJldHVybiBtaXhpbnMuc29tZShmdW5jdGlvbiAobWl4aW4pIHsKICAgICAgICByZXR1cm4gX2RldGVjdChtaXhpbiwgdGFyZ2V0TWl4aW4sIHNlZW4pOwogICAgICB9KTsKICAgIH0KCiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICBmdW5jdGlvbiBfa2V5cyhtaXhpbiwgcmV0LCBzZWVuKSB7CiAgICBpZiAocmV0ID09PSB2b2lkIDApIHsKICAgICAgcmV0ID0gbmV3IFNldCgpOwogICAgfQoKICAgIGlmIChzZWVuID09PSB2b2lkIDApIHsKICAgICAgc2VlbiA9IG5ldyBTZXQoKTsKICAgIH0KCiAgICBpZiAoc2Vlbi5oYXMobWl4aW4pKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBzZWVuLmFkZChtaXhpbik7CgogICAgaWYgKG1peGluLnByb3BlcnRpZXMpIHsKICAgICAgdmFyIHByb3BzID0gT2JqZWN0LmtleXMobWl4aW4ucHJvcGVydGllcyk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgcmV0LmFkZChwcm9wc1tpXSk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAobWl4aW4ubWl4aW5zKSB7CiAgICAgIG1peGluLm1peGlucy5mb3JFYWNoKGZ1bmN0aW9uICh4KSB7CiAgICAgICAgcmV0dXJuIF9rZXlzKHgsIHJldCwgc2Vlbik7CiAgICAgIH0pOwogICAgfQoKICAgIHJldHVybiByZXQ7CiAgfQoKICB2YXIgQWxpYXNJbXBsOwoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5BTElBU19NRVRIT0QpIHsKICAgIEFsaWFzSW1wbCA9IGZ1bmN0aW9uIEFsaWFzSW1wbChtZXRob2ROYW1lKSB7CiAgICAgIHRoaXMubWV0aG9kTmFtZSA9IG1ldGhvZE5hbWU7CiAgICB9OwogIH0KICAvKioKICAgIE1ha2VzIGEgbWV0aG9kIGF2YWlsYWJsZSB2aWEgYW4gYWRkaXRpb25hbCBuYW1lLgogIAogICAgYGBgYXBwL3V0aWxzL3BlcnNvbi5qcwogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7CiAgICAgIGFsaWFzTWV0aG9kCiAgICB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgbmFtZSgpIHsKICAgICAgICByZXR1cm4gJ1RvbWh1ZGEgS2F0emRhbGUnOwogICAgICB9LAogICAgICBtb25pa2VyOiBhbGlhc01ldGhvZCgnbmFtZScpCiAgICB9KTsKICAgIGBgYAogIAogICAgYGBgamF2YXNjcmlwdAogICAgbGV0IGdvb2RHdXkgPSBQZXJzb24uY3JlYXRlKCk7CiAgCiAgICBnb29kR3V5Lm5hbWUoKTsgICAgLy8gJ1RvbWh1ZGEgS2F0emRhbGUnCiAgICBnb29kR3V5Lm1vbmlrZXIoKTsgLy8gJ1RvbWh1ZGEgS2F0emRhbGUnCiAgICBgYGAKICAKICAgIEBtZXRob2QgYWxpYXNNZXRob2QKICAgIEBzdGF0aWMKICAgIEBkZXByZWNhdGVkIFVzZSBhIHNoYXJlZCB1dGlsaXR5IG1ldGhvZCBpbnN0ZWFkCiAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgIEBwYXJhbSB7U3RyaW5nfSBtZXRob2ROYW1lIG5hbWUgb2YgdGhlIG1ldGhvZCB0byBhbGlhcwogICAgQHB1YmxpYwogICovCgoKICB2YXIgYWxpYXNNZXRob2Q7CiAgX2V4cG9ydHMuYWxpYXNNZXRob2QgPSBhbGlhc01ldGhvZDsKCiAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuQUxJQVNfTUVUSE9EKSB7CiAgICBfZXhwb3J0cy5hbGlhc01ldGhvZCA9IGFsaWFzTWV0aG9kID0gZnVuY3Rpb24gYWxpYXNNZXRob2QobWV0aG9kTmFtZSkgewogICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCJZb3UgYXR0ZW1wdGVkIHRvIGFsaWFzICciICsgbWV0aG9kTmFtZSArICIsIGJ1dCBhbGlhc01ldGhvZCBoYXMgYmVlbiBkZXByZWNhdGVkLiBDb25zaWRlciBleHRyYWN0aW5nIHRoZSBtZXRob2QgaW50byBhIHNoYXJlZCB1dGlsaXR5IGZ1bmN0aW9uLiIsIGZhbHNlLCB7CiAgICAgICAgaWQ6ICdvYmplY3QuYWxpYXMtbWV0aG9kJywKICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY19vYmplY3QtYWxpYXMtbWV0aG9kJwogICAgICB9KSk7CiAgICAgIHJldHVybiBuZXcgQWxpYXNJbXBsKG1ldGhvZE5hbWUpOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIG9ic2VydmVyKCkgewogICAgZm9yICh2YXIgX2xlbjggPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW44KSwgX2tleTkgPSAwOyBfa2V5OSA8IF9sZW44OyBfa2V5OSsrKSB7CiAgICAgIGFyZ3NbX2tleTldID0gYXJndW1lbnRzW19rZXk5XTsKICAgIH0KCiAgICB2YXIgZnVuY09yRGVmID0gYXJncy5wb3AoKTsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBmdW5jT3JEZWYgPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIGZ1bmNPckRlZiA9PT0gJ29iamVjdCcgJiYgZnVuY09yRGVmICE9PSBudWxsKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ29ic2VydmVyIG11c3QgYmUgcHJvdmlkZWQgYSBmdW5jdGlvbiBvciBhbiBvYnNlcnZlciBkZWZpbml0aW9uJywgdHlwZW9mIGZ1bmNPckRlZiA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgZnVuY09yRGVmID09PSAnb2JqZWN0JyAmJiBmdW5jT3JEZWYgIT09IG51bGwpKTsKICAgIHZhciBmdW5jLCBkZXBlbmRlbnRLZXlzLCBzeW5jOwoKICAgIGlmICh0eXBlb2YgZnVuY09yRGVmID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIGZ1bmMgPSBmdW5jT3JEZWY7CiAgICAgIGRlcGVuZGVudEtleXMgPSBhcmdzOwogICAgICBzeW5jID0gIV9lbnZpcm9ubWVudC5FTlYuX0RFRkFVTFRfQVNZTkNfT0JTRVJWRVJTOwogICAgfSBlbHNlIHsKICAgICAgZnVuYyA9IGZ1bmNPckRlZi5mbjsKICAgICAgZGVwZW5kZW50S2V5cyA9IGZ1bmNPckRlZi5kZXBlbmRlbnRLZXlzOwogICAgICBzeW5jID0gZnVuY09yRGVmLnN5bmM7CiAgICB9CgogICAgKGZhbHNlICYmICEodHlwZW9mIGZ1bmMgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnb2JzZXJ2ZXIgY2FsbGVkIHdpdGhvdXQgYSBmdW5jdGlvbicsIHR5cGVvZiBmdW5jID09PSAnZnVuY3Rpb24nKSk7CiAgICAoZmFsc2UgJiYgIShBcnJheS5pc0FycmF5KGRlcGVuZGVudEtleXMpICYmIGRlcGVuZGVudEtleXMubGVuZ3RoID4gMCAmJiBkZXBlbmRlbnRLZXlzLmV2ZXJ5KGZ1bmN0aW9uIChwKSB7CiAgICAgIHJldHVybiB0eXBlb2YgcCA9PT0gJ3N0cmluZycgJiYgQm9vbGVhbihwLmxlbmd0aCk7CiAgICB9KSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdvYnNlcnZlciBjYWxsZWQgd2l0aG91dCB2YWxpZCBwYXRoJywgQXJyYXkuaXNBcnJheShkZXBlbmRlbnRLZXlzKSAmJiBkZXBlbmRlbnRLZXlzLmxlbmd0aCA+IDAgJiYgZGVwZW5kZW50S2V5cy5ldmVyeShmdW5jdGlvbiAocCkgewogICAgICByZXR1cm4gdHlwZW9mIHAgPT09ICdzdHJpbmcnICYmIEJvb2xlYW4ocC5sZW5ndGgpOwogICAgfSkpKTsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBzeW5jID09PSAnYm9vbGVhbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnb2JzZXJ2ZXIgY2FsbGVkIHdpdGhvdXQgc3luYycsIHR5cGVvZiBzeW5jID09PSAnYm9vbGVhbicpKTsKICAgIHZhciBwYXRocyA9IFtdOwoKICAgIHZhciBhZGRXYXRjaGVkUHJvcGVydHkgPSBmdW5jdGlvbiBhZGRXYXRjaGVkUHJvcGVydHkocGF0aCkgewogICAgICByZXR1cm4gcGF0aHMucHVzaChwYXRoKTsKICAgIH07CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkZXBlbmRlbnRLZXlzLmxlbmd0aDsgKytpKSB7CiAgICAgIGV4cGFuZFByb3BlcnRpZXMoZGVwZW5kZW50S2V5c1tpXSwgYWRkV2F0Y2hlZFByb3BlcnR5KTsKICAgIH0KCiAgICAoMCwgX3V0aWxzLnNldE9ic2VydmVycykoZnVuYywgewogICAgICBwYXRoczogcGF0aHMsCiAgICAgIHN5bmM6IHN5bmMKICAgIH0pOwogICAgcmV0dXJuIGZ1bmM7CiAgfQoKICB2YXIgREVCVUdfSU5KRUNUSU9OX0ZVTkNUSU9OUzsKICBfZXhwb3J0cy5ERUJVR19JTkpFQ1RJT05fRlVOQ1RJT05TID0gREVCVUdfSU5KRUNUSU9OX0ZVTkNUSU9OUzsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIF9leHBvcnRzLkRFQlVHX0lOSkVDVElPTl9GVU5DVElPTlMgPSBERUJVR19JTkpFQ1RJT05fRlVOQ1RJT05TID0gbmV3IFdlYWtNYXAoKTsKICB9CgogIGZ1bmN0aW9uIGluamVjdCh0eXBlKSB7CiAgICAoZmFsc2UgJiYgISh0eXBlb2YgdHlwZSA9PT0gJ3N0cmluZycpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYSBzdHJpbmcgdHlwZSBtdXN0IGJlIHByb3ZpZGVkIHRvIGluamVjdCcsIHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJykpOwoKICAgIGZvciAodmFyIF9sZW45ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuOSA+IDEgPyBfbGVuOSAtIDEgOiAwKSwgX2tleTEwID0gMTsgX2tleTEwIDwgX2xlbjk7IF9rZXkxMCsrKSB7CiAgICAgIGFyZ3NbX2tleTEwIC0gMV0gPSBhcmd1bWVudHNbX2tleTEwXTsKICAgIH0KCiAgICB2YXIgY2FsbGVkQXNEZWNvcmF0b3IgPSBpc0VsZW1lbnREZXNjcmlwdG9yKGFyZ3MpOwogICAgdmFyIHNvdXJjZSwgbmFtZXNwYWNlOwogICAgdmFyIG5hbWUgPSBjYWxsZWRBc0RlY29yYXRvciA/IHVuZGVmaW5lZCA6IGFyZ3NbMF07CiAgICB2YXIgb3B0aW9ucyA9IGNhbGxlZEFzRGVjb3JhdG9yID8gdW5kZWZpbmVkIDogYXJnc1sxXTsKCiAgICB2YXIgZ2V0SW5qZWN0aW9uID0gZnVuY3Rpb24gZ2V0SW5qZWN0aW9uKHByb3BlcnR5TmFtZSkgewogICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKSB8fCB0aGlzLmNvbnRhaW5lcjsgLy8gZmFsbGJhY2sgdG8gYGNvbnRhaW5lcmAgZm9yIGJhY2t3YXJkcyBjb21wYXQKCiAgICAgIChmYWxzZSAmJiAhKEJvb2xlYW4ob3duZXIpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF0dGVtcHRpbmcgdG8gbG9va3VwIGFuIGluamVjdGVkIHByb3BlcnR5IG9uIGFuIG9iamVjdCB3aXRob3V0IGEgY29udGFpbmVyLCBlbnN1cmUgdGhhdCB0aGUgb2JqZWN0IHdhcyBpbnN0YW50aWF0ZWQgdmlhIGEgY29udGFpbmVyLiIsIEJvb2xlYW4ob3duZXIpKSk7CiAgICAgIHJldHVybiBvd25lci5sb29rdXAodHlwZSArICI6IiArIChuYW1lIHx8IHByb3BlcnR5TmFtZSksIHsKICAgICAgICBzb3VyY2U6IHNvdXJjZSwKICAgICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZQogICAgICB9KTsKICAgIH07CgogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgKSB7CiAgICAgIERFQlVHX0lOSkVDVElPTl9GVU5DVElPTlMuc2V0KGdldEluamVjdGlvbiwgewogICAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlLAogICAgICAgIHNvdXJjZTogc291cmNlLAogICAgICAgIHR5cGU6IHR5cGUsCiAgICAgICAgbmFtZTogbmFtZQogICAgICB9KTsKICAgIH0KCiAgICB2YXIgZGVjb3JhdG9yID0gY29tcHV0ZWQoewogICAgICBnZXQ6IGdldEluamVjdGlvbiwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5TmFtZSwgdmFsdWUkJDEpIHsKICAgICAgICBkZWZpbmVQcm9wZXJ0eSh0aGlzLCBrZXlOYW1lLCBudWxsLCB2YWx1ZSQkMSk7CiAgICAgIH0KICAgIH0pOwoKICAgIGlmIChjYWxsZWRBc0RlY29yYXRvcikgewogICAgICAoZmFsc2UgJiYgIShCb29sZWFuKHRydWUKICAgICAgLyogRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUICovCiAgICAgICkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnTmF0aXZlIGRlY29yYXRvcnMgYXJlIG5vdCBlbmFibGVkIHdpdGhvdXQgdGhlIEVNQkVSX05BVElWRV9ERUNPUkFUT1JfU1VQUE9SVCBmbGFnLiBJZiB5b3UgYXJlIHVzaW5nIGluamVjdCBpbiBhIGNsYXNzaWMgY2xhc3MsIGFkZCBwYXJlbnRoZXNpcyB0byBpdDogaW5qZWN0KCknLCBCb29sZWFuKHRydWUpKSk7CiAgICAgIHJldHVybiBkZWNvcmF0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gZGVjb3JhdG9yOwogICAgfQogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvb3duZXIvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdXRpbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmdldE93bmVyID0gZ2V0T3duZXI7CiAgX2V4cG9ydHMuc2V0T3duZXIgPSBzZXRPd25lcjsKICBfZXhwb3J0cy5PV05FUiA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvYXBwbGljYXRpb24KICAqLwogIHZhciBPV05FUiA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnT1dORVInKTsKICAvKioKICAgIEZyYW1ld29yayBvYmplY3RzIGluIGFuIEVtYmVyIGFwcGxpY2F0aW9uIChjb21wb25lbnRzLCBzZXJ2aWNlcywgcm91dGVzLCBldGMuKQogICAgYXJlIGNyZWF0ZWQgdmlhIGEgZmFjdG9yeSBhbmQgZGVwZW5kZW5jeSBpbmplY3Rpb24gc3lzdGVtLiBFYWNoIG9mIHRoZXNlCiAgICBvYmplY3RzIGlzIHRoZSByZXNwb25zaWJpbGl0eSBvZiBhbiAib3duZXIiLCB3aGljaCBoYW5kbGVkIGl0cwogICAgaW5zdGFudGlhdGlvbiBhbmQgbWFuYWdlcyBpdHMgbGlmZXRpbWUuCiAgCiAgICBgZ2V0T3duZXJgIGZldGNoZXMgdGhlIG93bmVyIG9iamVjdCByZXNwb25zaWJsZSBmb3IgYW4gaW5zdGFuY2UuIFRoaXMgY2FuCiAgICBiZSB1c2VkIHRvIGxvb2t1cCBvciByZXNvbHZlIG90aGVyIGNsYXNzIGluc3RhbmNlcywgb3IgcmVnaXN0ZXIgbmV3IGZhY3RvcmllcwogICAgaW50byB0aGUgb3duZXIuCiAgCiAgICBGb3IgZXhhbXBsZSwgdGhpcyBjb21wb25lbnQgZHluYW1pY2FsbHkgbG9va3MgdXAgYSBzZXJ2aWNlIGJhc2VkIG9uIHRoZQogICAgYGF1ZGlvVHlwZWAgcGFzc2VkIGFzIGFuIGF0dHJpYnV0ZToKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL3BsYXktYXVkaW8uanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgZ2V0T3duZXIgfSBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogIAogICAgLy8gVXNhZ2U6CiAgICAvLwogICAgLy8gICB7e3BsYXktYXVkaW8gYXVkaW9UeXBlPW1vZGVsLmF1ZGlvVHlwZSBhdWRpb0ZpbGU9bW9kZWwuZmlsZX19CiAgICAvLwogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGF1ZGlvU2VydmljZTogY29tcHV0ZWQoJ2F1ZGlvVHlwZScsIGZ1bmN0aW9uKCkgewogICAgICAgIGxldCBvd25lciA9IGdldE93bmVyKHRoaXMpOwogICAgICAgIHJldHVybiBvd25lci5sb29rdXAoYHNlcnZpY2U6JHt0aGlzLmdldCgnYXVkaW9UeXBlJyl9YCk7CiAgICAgIH0pLAogIAogICAgICBjbGljaygpIHsKICAgICAgICBsZXQgcGxheWVyID0gdGhpcy5nZXQoJ2F1ZGlvU2VydmljZScpOwogICAgICAgIHBsYXllci5wbGF5KHRoaXMuZ2V0KCdhdWRpb0ZpbGUnKSk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGdldE93bmVyCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9hcHBsaWNhdGlvbgogICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdCBBbiBvYmplY3Qgd2l0aCBhbiBvd25lci4KICAgIEByZXR1cm4ge09iamVjdH0gQW4gb3duZXIgb2JqZWN0LgogICAgQHNpbmNlIDIuMy4wCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMuT1dORVIgPSBPV05FUjsKCiAgZnVuY3Rpb24gZ2V0T3duZXIob2JqZWN0KSB7CiAgICByZXR1cm4gb2JqZWN0W09XTkVSXTsKICB9CiAgLyoqCiAgICBgc2V0T3duZXJgIGZvcmNlcyBhIG5ldyBvd25lciBvbiBhIGdpdmVuIG9iamVjdCBpbnN0YW5jZS4gVGhpcyBpcyBwcmltYXJpbHkKICAgIHVzZWZ1bCBpbiBzb21lIHRlc3RpbmcgY2FzZXMuCiAgCiAgICBAbWV0aG9kIHNldE93bmVyCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9hcHBsaWNhdGlvbgogICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdCBBbiBvYmplY3QgaW5zdGFuY2UuCiAgICBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBuZXcgb3duZXIgb2JqZWN0IG9mIHRoZSBvYmplY3QgaW5zdGFuY2UuCiAgICBAc2luY2UgMi4zLjAKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gc2V0T3duZXIob2JqZWN0LCBvd25lcikgewogICAgb2JqZWN0W09XTkVSXSA9IG93bmVyOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9leHQvY29udHJvbGxlciIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9sb2NhdGlvbi9hcGkiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vbm9uZV9sb2NhdGlvbiIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9sb2NhdGlvbi9oYXNoX2xvY2F0aW9uIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL2hpc3RvcnlfbG9jYXRpb24iLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vYXV0b19sb2NhdGlvbiIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vZ2VuZXJhdGVfY29udHJvbGxlciIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vY29udHJvbGxlcl9mb3IiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL2RzbCIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vcm91dGVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3N5c3RlbS9yb3V0ZSIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vcXVlcnlfcGFyYW1zIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3NlcnZpY2VzL3JvdXRpbmciLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc2VydmljZXMvcm91dGVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3N5c3RlbS9jYWNoZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9jb250cm9sbGVyLCBfYXBpLCBfbm9uZV9sb2NhdGlvbiwgX2hhc2hfbG9jYXRpb24sIF9oaXN0b3J5X2xvY2F0aW9uLCBfYXV0b19sb2NhdGlvbiwgX2dlbmVyYXRlX2NvbnRyb2xsZXIsIF9jb250cm9sbGVyX2ZvciwgX2RzbCwgX3JvdXRlciwgX3JvdXRlLCBfcXVlcnlfcGFyYW1zLCBfcm91dGluZywgX3JvdXRlcjIsIF9jYWNoZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiTG9jYXRpb24iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXBpLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiTm9uZUxvY2F0aW9uIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX25vbmVfbG9jYXRpb24uZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJIYXNoTG9jYXRpb24iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfaGFzaF9sb2NhdGlvbi5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkhpc3RvcnlMb2NhdGlvbiIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9oaXN0b3J5X2xvY2F0aW9uLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQXV0b0xvY2F0aW9uIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2F1dG9fbG9jYXRpb24uZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZW5lcmF0ZUNvbnRyb2xsZXIiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZ2VuZXJhdGVfY29udHJvbGxlci5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImdlbmVyYXRlQ29udHJvbGxlckZhY3RvcnkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZ2VuZXJhdGVfY29udHJvbGxlci5nZW5lcmF0ZUNvbnRyb2xsZXJGYWN0b3J5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImNvbnRyb2xsZXJGb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29udHJvbGxlcl9mb3IuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJSb3V0ZXJEU0wiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZHNsLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiUm91dGVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JvdXRlci5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIlJvdXRlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JvdXRlLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiUXVlcnlQYXJhbXMiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcXVlcnlfcGFyYW1zLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiUm91dGluZ1NlcnZpY2UiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcm91dGluZy5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIlJvdXRlclNlcnZpY2UiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcm91dGVyMi5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkJ1Y2tldENhY2hlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NhY2hlLmRlZmF1bHQ7CiAgICB9CiAgfSk7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2V4dC9jb250cm9sbGVyIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci9jb250cm9sbGVyL2xpYi9jb250cm9sbGVyX21peGluIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3V0aWxzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21ldGFsLCBfY29udHJvbGxlcl9taXhpbiwgX3V0aWxzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KICBfY29udHJvbGxlcl9taXhpbi5kZWZhdWx0LnJlb3Blbih7CiAgICBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzOiBbJ3F1ZXJ5UGFyYW1zJ10sCgogICAgLyoqCiAgICAgIERlZmluZXMgd2hpY2ggcXVlcnkgcGFyYW1ldGVycyB0aGUgY29udHJvbGxlciBhY2NlcHRzLgogICAgICBJZiB5b3UgZ2l2ZSB0aGUgbmFtZXMgYFsnY2F0ZWdvcnknLCdwYWdlJ11gIGl0IHdpbGwgYmluZAogICAgICB0aGUgdmFsdWVzIG9mIHRoZXNlIHF1ZXJ5IHBhcmFtZXRlcnMgdG8gdGhlIHZhcmlhYmxlcwogICAgICBgdGhpcy5jYXRlZ29yeWAgYW5kIGB0aGlzLnBhZ2VgLgogICAgICBCeSBkZWZhdWx0LCBFbWJlciBjb2VyY2VzIHF1ZXJ5IHBhcmFtZXRlciB2YWx1ZXMgdXNpbmcgYHRvZ2dsZVByb3BlcnR5YC4KICAgICAgVGhpcyBiZWhhdmlvciBtYXkgbGVhZCB0byB1bmV4cGVjdGVkIHJlc3VsdHMuCiAgICAgIEF2YWlsYWJsZSBxdWVyeVBhcmFtIHR5cGVzOiBgYm9vbGVhbmAsIGBudW1iZXJgLCBgYXJyYXlgLgogICAgICBJZiBxdWVyeSBwYXJhbSB0eXBlIG5vdCBzcGVjaWZpZWQsIGl0IHdpbGwgYmUgYHN0cmluZ2AuCiAgICAgIFRvIGV4cGxpY2l0bHkgY29uZmlndXJlIGEgcXVlcnkgcGFyYW1ldGVyIHByb3BlcnR5IHNvIGl0IGNvZXJjZXMgYXMgZXhwZWN0ZWQsIHlvdSBtdXN0IGRlZmluZSBhIHR5cGUgcHJvcGVydHk6CiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgICBxdWVyeVBhcmFtczogW3sKICAgICAgICAgIGNhdGVnb3J5OiB7CiAgICAgICAgICAgIHR5cGU6ICdib29sZWFuJwogICAgICAgICAgfQogICAgICAgIH1dCiAgICAgIGBgYAogICAgICBAZm9yIEVtYmVyLkNvbnRyb2xsZXJNaXhpbgogICAgICBAcHJvcGVydHkgcXVlcnlQYXJhbXMKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHF1ZXJ5UGFyYW1zOiBudWxsLAoKICAgIC8qKgogICAgIFRoaXMgcHJvcGVydHkgaXMgdXBkYXRlZCB0byB2YXJpb3VzIGRpZmZlcmVudCBjYWxsYmFjayBmdW5jdGlvbnMgZGVwZW5kaW5nIG9uCiAgICAgdGhlIGN1cnJlbnQgInN0YXRlIiBvZiB0aGUgYmFja2luZyByb3V0ZS4gSXQgaXMgdXNlZCBieQogICAgIGBDb250cm9sbGVyLnByb3RvdHlwZS5fcXBDaGFuZ2VkYC4KICAgICAgICBUaGUgbWV0aG9kcyBiYWNraW5nIGVhY2ggc3RhdGUgY2FuIGJlIGZvdW5kIGluIHRoZSBgUm91dGUucHJvdG90eXBlLl9xcGAgY29tcHV0ZWQKICAgICBwcm9wZXJ0eSByZXR1cm4gdmFsdWUgKHRoZSBgLnN0YXRlc2AgcHJvcGVydHkpLiBUaGUgY3VycmVudCB2YWx1ZXMgYXJlIGxpc3RlZCBoZXJlIGZvcgogICAgIHRoZSBzYW5pdHkgb2YgZnV0dXJlIHRyYXZlbGVyczoKICAgICAgICAqIGBpbmFjdGl2ZWAgLSBUaGlzIHN0YXRlIGlzIHVzZWQgd2hlbiB0aGlzIGNvbnRyb2xsZXIgaW5zdGFuY2UgaXMgbm90IHBhcnQgb2YgdGhlIGFjdGl2ZQogICAgICAgcm91dGUgaGllcmFyY2h5LiBTZXQgaW4gYFJvdXRlLnByb3RvdHlwZS5fcmVzZXRgIChhIGByb3V0ZXIuanNgIG1pY3JvbGliIGhvb2spIGFuZAogICAgICAgYFJvdXRlLnByb3RvdHlwZS5hY3Rpb25zLmZpbmFsaXplUXVlcnlQYXJhbUNoYW5nZWAuCiAgICAgKiBgYWN0aXZlYCAtIFRoaXMgc3RhdGUgaXMgdXNlZCB3aGVuIHRoaXMgY29udHJvbGxlciBpbnN0YW5jZSBpcyBwYXJ0IG9mIHRoZSBhY3RpdmUKICAgICAgIHJvdXRlIGhpZXJhcmNoeS4gU2V0IGluIGBSb3V0ZS5wcm90b3R5cGUuYWN0aW9ucy5maW5hbGl6ZVF1ZXJ5UGFyYW1DaGFuZ2VgLgogICAgICogYGFsbG93T3ZlcnJpZGVzYCAtIFRoaXMgc3RhdGUgaXMgdXNlZCBpbiBgUm91dGUucHJvdG90eXBlLnNldHVwYCAoYHJvdXRlLmpzYCBtaWNyb2xpYiBob29rKS4KICAgICAgICAgQG1ldGhvZCBfcXBEZWxlZ2F0ZQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9xcERlbGVnYXRlOiBudWxsLAoKICAgIC8qKgogICAgIER1cmluZyBgUm91dGUjc2V0dXBgIG9ic2VydmVycyBhcmUgY3JlYXRlZCB0byBpbnZva2UgdGhpcyBtZXRob2QKICAgICB3aGVuIGFueSBvZiB0aGUgcXVlcnkgcGFyYW1zIGRlY2xhcmVkIGluIGBDb250cm9sbGVyI3F1ZXJ5UGFyYW1zYCBwcm9wZXJ0eQogICAgIGFyZSBjaGFuZ2VkLgogICAgICAgIFdoZW4gaW52b2tlZCB0aGlzIG1ldGhvZCB1c2VzIHRoZSBjdXJyZW50bHkgYWN0aXZlIHF1ZXJ5IHBhcmFtIHVwZGF0ZSBkZWxlZ2F0ZQogICAgIChzZWUgYENvbnRyb2xsZXIucHJvdG90eXBlLl9xcERlbGVnYXRlYCBmb3IgZGV0YWlscykgYW5kIGludm9rZXMgaXQgd2l0aAogICAgIHRoZSBRUCBrZXkvdmFsdWUgYmVpbmcgY2hhbmdlZC4KICAgICAgICAgQG1ldGhvZCBfcXBDaGFuZ2VkCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX3FwQ2hhbmdlZDogZnVuY3Rpb24gX3FwQ2hhbmdlZChjb250cm9sbGVyLCBfcHJvcCkgewogICAgICB2YXIgZG90SW5kZXggPSBfcHJvcC5pbmRleE9mKCcuW10nKTsKCiAgICAgIHZhciBwcm9wID0gZG90SW5kZXggPT09IC0xID8gX3Byb3AgOiBfcHJvcC5zbGljZSgwLCBkb3RJbmRleCk7CiAgICAgIHZhciBkZWxlZ2F0ZSA9IGNvbnRyb2xsZXIuX3FwRGVsZWdhdGU7CiAgICAgIHZhciB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KShjb250cm9sbGVyLCBwcm9wKTsKICAgICAgZGVsZWdhdGUocHJvcCwgdmFsdWUpOwogICAgfSwKCiAgICAvKioKICAgICAgVHJhbnNpdGlvbiB0aGUgYXBwbGljYXRpb24gaW50byBhbm90aGVyIHJvdXRlLiBUaGUgcm91dGUgbWF5CiAgICAgIGJlIGVpdGhlciBhIHNpbmdsZSByb3V0ZSBvciByb3V0ZSBwYXRoOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGFDb250cm9sbGVyLnRyYW5zaXRpb25Ub1JvdXRlKCdibG9nUG9zdHMnKTsKICAgICAgYUNvbnRyb2xsZXIudHJhbnNpdGlvblRvUm91dGUoJ2Jsb2dQb3N0cy5yZWNlbnRFbnRyaWVzJyk7CiAgICAgIGBgYAogICAgICAgICBPcHRpb25hbGx5IHN1cHBseSBhIG1vZGVsIGZvciB0aGUgcm91dGUgaW4gcXVlc3Rpb24uIFRoZSBtb2RlbAogICAgICB3aWxsIGJlIHNlcmlhbGl6ZWQgaW50byB0aGUgVVJMIHVzaW5nIHRoZSBgc2VyaWFsaXplYCBob29rIG9mCiAgICAgIHRoZSByb3V0ZToKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBhQ29udHJvbGxlci50cmFuc2l0aW9uVG9Sb3V0ZSgnYmxvZ1Bvc3QnLCBhUG9zdCk7CiAgICAgIGBgYAogICAgICAgICBJZiBhIGxpdGVyYWwgaXMgcGFzc2VkIChzdWNoIGFzIGEgbnVtYmVyIG9yIGEgc3RyaW5nKSwgaXQgd2lsbAogICAgICBiZSB0cmVhdGVkIGFzIGFuIGlkZW50aWZpZXIgaW5zdGVhZC4gSW4gdGhpcyBjYXNlLCB0aGUgYG1vZGVsYAogICAgICBob29rIG9mIHRoZSByb3V0ZSB3aWxsIGJlIHRyaWdnZXJlZDoKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBhQ29udHJvbGxlci50cmFuc2l0aW9uVG9Sb3V0ZSgnYmxvZ1Bvc3QnLCAxKTsKICAgICAgYGBgCiAgICAgICAgIE11bHRpcGxlIG1vZGVscyB3aWxsIGJlIGFwcGxpZWQgbGFzdCB0byBmaXJzdCByZWN1cnNpdmVseSB1cCB0aGUKICAgICAgcm91dGUgdHJlZS4KICAgICAgICAgYGBgYXBwL3JvdXRlci5qcwogICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoJ2Jsb2dQb3N0JywgeyBwYXRoOiAnOmJsb2dQb3N0SWQnIH0sIGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhpcy5yb3V0ZSgnYmxvZ0NvbW1lbnQnLCB7IHBhdGg6ICc6YmxvZ0NvbW1lbnRJZCcsIHJlc2V0TmFtZXNwYWNlOiB0cnVlIH0pOwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgYUNvbnRyb2xsZXIudHJhbnNpdGlvblRvUm91dGUoJ2Jsb2dDb21tZW50JywgYVBvc3QsIGFDb21tZW50KTsKICAgICAgYUNvbnRyb2xsZXIudHJhbnNpdGlvblRvUm91dGUoJ2Jsb2dDb21tZW50JywgMSwgMTMpOwogICAgICBgYGAKICAgICAgICAgSXQgaXMgYWxzbyBwb3NzaWJsZSB0byBwYXNzIGEgVVJMIChhIHN0cmluZyB0aGF0IHN0YXJ0cyB3aXRoIGEKICAgICAgYC9gKS4KICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBhQ29udHJvbGxlci50cmFuc2l0aW9uVG9Sb3V0ZSgnLycpOwogICAgICBhQ29udHJvbGxlci50cmFuc2l0aW9uVG9Sb3V0ZSgnL2Jsb2cvcG9zdC8xL2NvbW1lbnQvMTMnKTsKICAgICAgYUNvbnRyb2xsZXIudHJhbnNpdGlvblRvUm91dGUoJy9ibG9nL3Bvc3RzP3NvcnQ9dGl0bGUnKTsKICAgICAgYGBgCiAgICAgICAgIEFuIG9wdGlvbnMgaGFzaCB3aXRoIGEgYHF1ZXJ5UGFyYW1zYCBwcm9wZXJ0eSBtYXkgYmUgcHJvdmlkZWQgYXMKICAgICAgdGhlIGZpbmFsIGFyZ3VtZW50IHRvIGFkZCBxdWVyeSBwYXJhbWV0ZXJzIHRvIHRoZSBkZXN0aW5hdGlvbiBVUkwuCiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgYUNvbnRyb2xsZXIudHJhbnNpdGlvblRvUm91dGUoJ2Jsb2dQb3N0JywgMSwgewogICAgICAgIHF1ZXJ5UGFyYW1zOiB7IHNob3dDb21tZW50czogJ3RydWUnIH0KICAgICAgfSk7CiAgICAgICAgIC8vIGlmIHlvdSBqdXN0IHdhbnQgdG8gdHJhbnNpdGlvbiB0aGUgcXVlcnkgcGFyYW1ldGVycyB3aXRob3V0IGNoYW5naW5nIHRoZSByb3V0ZQogICAgICBhQ29udHJvbGxlci50cmFuc2l0aW9uVG9Sb3V0ZSh7IHF1ZXJ5UGFyYW1zOiB7IHNvcnQ6ICdkYXRlJyB9IH0pOwogICAgICBgYGAKICAgICAgICAgU2VlIGFsc28gW3JlcGxhY2VSb3V0ZV0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9FbWJlci5Db250cm9sbGVyTWl4aW4vbWV0aG9kcy9yZXBsYWNlUm91dGU/YW5jaG9yPXJlcGxhY2VSb3V0ZSkuCiAgICAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZSBvciBhIFVSTAogICAgICBAcGFyYW0gey4uLk9iamVjdH0gbW9kZWxzIHRoZSBtb2RlbChzKSBvciBpZGVudGlmaWVyKHMpIHRvIGJlIHVzZWQKICAgICAgICB3aGlsZSB0cmFuc2l0aW9uaW5nIHRvIHRoZSByb3V0ZS4KICAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBvcHRpb25hbCBoYXNoIHdpdGggYSBxdWVyeVBhcmFtcyBwcm9wZXJ0eQogICAgICAgIGNvbnRhaW5pbmcgYSBtYXBwaW5nIG9mIHF1ZXJ5IHBhcmFtZXRlcnMKICAgICAgQGZvciBFbWJlci5Db250cm9sbGVyTWl4aW4KICAgICAgQG1ldGhvZCB0cmFuc2l0aW9uVG9Sb3V0ZQogICAgICBAcHVibGljCiAgICAqLwogICAgdHJhbnNpdGlvblRvUm91dGU6IGZ1bmN0aW9uIHRyYW5zaXRpb25Ub1JvdXRlKCkgewogICAgICAvLyB0YXJnZXQgbWF5IGJlIGVpdGhlciBhbm90aGVyIGNvbnRyb2xsZXIgb3IgYSByb3V0ZXIKICAgICAgdmFyIHRhcmdldCA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAndGFyZ2V0Jyk7CiAgICAgIHZhciBtZXRob2QgPSB0YXJnZXQudHJhbnNpdGlvblRvUm91dGUgfHwgdGFyZ2V0LnRyYW5zaXRpb25UbzsKCiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgIHJldHVybiBtZXRob2QuYXBwbHkodGFyZ2V0LCAoMCwgX3V0aWxzLnByZWZpeFJvdXRlTmFtZUFyZykodGhpcywgYXJncykpOwogICAgfSwKCiAgICAvKioKICAgICAgVHJhbnNpdGlvbiBpbnRvIGFub3RoZXIgcm91dGUgd2hpbGUgcmVwbGFjaW5nIHRoZSBjdXJyZW50IFVSTCwgaWYgcG9zc2libGUuCiAgICAgIFRoaXMgd2lsbCByZXBsYWNlIHRoZSBjdXJyZW50IGhpc3RvcnkgZW50cnkgaW5zdGVhZCBvZiBhZGRpbmcgYSBuZXcgb25lLgogICAgICBCZXNpZGUgdGhhdCwgaXQgaXMgaWRlbnRpY2FsIHRvIGB0cmFuc2l0aW9uVG9Sb3V0ZWAgaW4gYWxsIG90aGVyIHJlc3BlY3RzLgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGFDb250cm9sbGVyLnJlcGxhY2VSb3V0ZSgnYmxvZ1Bvc3RzJyk7CiAgICAgIGFDb250cm9sbGVyLnJlcGxhY2VSb3V0ZSgnYmxvZ1Bvc3RzLnJlY2VudEVudHJpZXMnKTsKICAgICAgYGBgCiAgICAgICAgIE9wdGlvbmFsbHkgc3VwcGx5IGEgbW9kZWwgZm9yIHRoZSByb3V0ZSBpbiBxdWVzdGlvbi4gVGhlIG1vZGVsCiAgICAgIHdpbGwgYmUgc2VyaWFsaXplZCBpbnRvIHRoZSBVUkwgdXNpbmcgdGhlIGBzZXJpYWxpemVgIGhvb2sgb2YKICAgICAgdGhlIHJvdXRlOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGFDb250cm9sbGVyLnJlcGxhY2VSb3V0ZSgnYmxvZ1Bvc3QnLCBhUG9zdCk7CiAgICAgIGBgYAogICAgICAgICBJZiBhIGxpdGVyYWwgaXMgcGFzc2VkIChzdWNoIGFzIGEgbnVtYmVyIG9yIGEgc3RyaW5nKSwgaXQgd2lsbAogICAgICBiZSB0cmVhdGVkIGFzIGFuIGlkZW50aWZpZXIgaW5zdGVhZC4gSW4gdGhpcyBjYXNlLCB0aGUgYG1vZGVsYAogICAgICBob29rIG9mIHRoZSByb3V0ZSB3aWxsIGJlIHRyaWdnZXJlZDoKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBhQ29udHJvbGxlci5yZXBsYWNlUm91dGUoJ2Jsb2dQb3N0JywgMSk7CiAgICAgIGBgYAogICAgICAgICBNdWx0aXBsZSBtb2RlbHMgd2lsbCBiZSBhcHBsaWVkIGxhc3QgdG8gZmlyc3QgcmVjdXJzaXZlbHkgdXAgdGhlCiAgICAgIHJvdXRlIHRyZWUuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdibG9nUG9zdCcsIHsgcGF0aDogJzpibG9nUG9zdElkJyB9LCBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMucm91dGUoJ2Jsb2dDb21tZW50JywgeyBwYXRoOiAnOmJsb2dDb21tZW50SWQnLCByZXNldE5hbWVzcGFjZTogdHJ1ZSB9KTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBgYGAKICAgICAgYUNvbnRyb2xsZXIucmVwbGFjZVJvdXRlKCdibG9nQ29tbWVudCcsIGFQb3N0LCBhQ29tbWVudCk7CiAgICAgIGFDb250cm9sbGVyLnJlcGxhY2VSb3V0ZSgnYmxvZ0NvbW1lbnQnLCAxLCAxMyk7CiAgICAgIGBgYAogICAgICAgICBJdCBpcyBhbHNvIHBvc3NpYmxlIHRvIHBhc3MgYSBVUkwgKGEgc3RyaW5nIHRoYXQgc3RhcnRzIHdpdGggYQogICAgICBgL2ApLgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGFDb250cm9sbGVyLnJlcGxhY2VSb3V0ZSgnLycpOwogICAgICBhQ29udHJvbGxlci5yZXBsYWNlUm91dGUoJy9ibG9nL3Bvc3QvMS9jb21tZW50LzEzJyk7CiAgICAgIGBgYAogICAgICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSB0aGUgbmFtZSBvZiB0aGUgcm91dGUgb3IgYSBVUkwKICAgICAgQHBhcmFtIHsuLi5PYmplY3R9IG1vZGVscyB0aGUgbW9kZWwocykgb3IgaWRlbnRpZmllcihzKSB0byBiZSB1c2VkCiAgICAgIHdoaWxlIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICBAZm9yIEVtYmVyLkNvbnRyb2xsZXJNaXhpbgogICAgICBAbWV0aG9kIHJlcGxhY2VSb3V0ZQogICAgICBAcHVibGljCiAgICAqLwogICAgcmVwbGFjZVJvdXRlOiBmdW5jdGlvbiByZXBsYWNlUm91dGUoKSB7CiAgICAgIC8vIHRhcmdldCBtYXkgYmUgZWl0aGVyIGFub3RoZXIgY29udHJvbGxlciBvciBhIHJvdXRlcgogICAgICB2YXIgdGFyZ2V0ID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICd0YXJnZXQnKTsKICAgICAgdmFyIG1ldGhvZCA9IHRhcmdldC5yZXBsYWNlUm91dGUgfHwgdGFyZ2V0LnJlcGxhY2VXaXRoOwoKICAgICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4yKSwgX2tleTIgPSAwOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7CiAgICAgICAgYXJnc1tfa2V5Ml0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICB9CgogICAgICByZXR1cm4gbWV0aG9kLmFwcGx5KHRhcmdldCwgKDAsIF91dGlscy5wcmVmaXhSb3V0ZU5hbWVBcmcpKHRoaXMsIGFyZ3MpKTsKICAgIH0KICB9KTsKCiAgdmFyIF9kZWZhdWx0ID0gX2NvbnRyb2xsZXJfbWl4aW4uZGVmYXVsdDsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL2FwaSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZGVidWciXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVidWcpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgQGVtYmVyL3JvdXRpbmcKICAqLwoKICAvKioKICAgIExvY2F0aW9uIHJldHVybnMgYW4gaW5zdGFuY2Ugb2YgdGhlIGNvcnJlY3QgaW1wbGVtZW50YXRpb24gb2YKICAgIHRoZSBgbG9jYXRpb25gIEFQSS4KICAKICAgICMjIEltcGxlbWVudGF0aW9ucwogIAogICAgWW91IGNhbiBwYXNzIGFuIGltcGxlbWVudGF0aW9uIG5hbWUgKGBoYXNoYCwgYGhpc3RvcnlgLCBgbm9uZWAsIGBhdXRvYCkgdG8gZm9yY2UgYQogICAgcGFydGljdWxhciBpbXBsZW1lbnRhdGlvbiB0byBiZSB1c2VkIGluIHlvdXIgYXBwbGljYXRpb24uCiAgCiAgICBTZWUgW0hhc2hMb2NhdGlvbl0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9IYXNoTG9jYXRpb24pLgogICAgU2VlIFtIaXN0b3J5TG9jYXRpb25dKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvSGlzdG9yeUxvY2F0aW9uKS4KICAgIFNlZSBbTm9uZUxvY2F0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL05vbmVMb2NhdGlvbikuCiAgICBTZWUgW0F1dG9Mb2NhdGlvbl0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9BdXRvTG9jYXRpb24pLgogIAogICAgIyMgTG9jYXRpb24gQVBJCiAgCiAgICBFYWNoIGxvY2F0aW9uIGltcGxlbWVudGF0aW9uIG11c3QgcHJvdmlkZSB0aGUgZm9sbG93aW5nIG1ldGhvZHM6CiAgCiAgICAqIGltcGxlbWVudGF0aW9uOiByZXR1cm5zIHRoZSBzdHJpbmcgbmFtZSB1c2VkIHRvIHJlZmVyZW5jZSB0aGUgaW1wbGVtZW50YXRpb24uCiAgICAqIGdldFVSTDogcmV0dXJucyB0aGUgY3VycmVudCBVUkwuCiAgICAqIHNldFVSTChwYXRoKTogc2V0cyB0aGUgY3VycmVudCBVUkwuCiAgICAqIHJlcGxhY2VVUkwocGF0aCk6IHJlcGxhY2UgdGhlIGN1cnJlbnQgVVJMIChvcHRpb25hbCkuCiAgICAqIG9uVXBkYXRlVVJMKGNhbGxiYWNrKTogdHJpZ2dlcnMgdGhlIGNhbGxiYWNrIHdoZW4gdGhlIFVSTCBjaGFuZ2VzLgogICAgKiBmb3JtYXRVUkwodXJsKTogZm9ybWF0cyBgdXJsYCB0byBiZSBwbGFjZWQgaW50byBgaHJlZmAgYXR0cmlidXRlLgogICAgKiBkZXRlY3QoKSAob3B0aW9uYWwpOiBpbnN0cnVjdHMgdGhlIGxvY2F0aW9uIHRvIGRvIGFueSBmZWF0dXJlIGRldGVjdGlvbgogICAgICAgIG5lY2Vzc2FyeS4gSWYgdGhlIGxvY2F0aW9uIG5lZWRzIHRvIHJlZGlyZWN0IHRvIGEgZGlmZmVyZW50IFVSTCwgaXQKICAgICAgICBjYW4gY2FuY2VsIHJvdXRpbmcgYnkgc2V0dGluZyB0aGUgYGNhbmNlbFJvdXRlclNldHVwYCBwcm9wZXJ0eSBvbiBpdHNlbGYKICAgICAgICB0byBgZmFsc2VgLgogIAogICAgQ2FsbGluZyBzZXRVUkwgb3IgcmVwbGFjZVVSTCB3aWxsIG5vdCB0cmlnZ2VyIG9uVXBkYXRlVVJMIGNhbGxiYWNrcy4KICAKICAgICMjIEN1c3RvbSBpbXBsZW1lbnRhdGlvbgogIAogICAgRW1iZXIgc2NhbnMgYGFwcC9sb2NhdGlvbnMvKmAgZm9yIGV4dGVuZGluZyB0aGUgTG9jYXRpb24gQVBJLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBIaXN0b3J5TG9jYXRpb24gZnJvbSAnQGVtYmVyL3JvdXRpbmcvaGlzdG9yeS1sb2NhdGlvbic7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBjbGFzcyBNeUhpc3RvcnkgewogICAgICBpbXBsZW1lbnRhdGlvbjogJ215LWN1c3RvbS1oaXN0b3J5JywKICAgICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgdGhpcy5faGlzdG9yeSA9IEhpc3RvcnlMb2NhdGlvbi5jcmVhdGUoLi4uYXJndW1lbnRzKTsKICAgICAgfQogICAgICBjcmVhdGUoKSB7CiAgICAgICAgcmV0dXJuIG5ldyB0aGlzKC4uLmFyZ3VtZW50cyk7CiAgICAgIH0KICAgICAgcHVzaFN0YXRlKHBhdGgpIHsKICAgICAgICAgdGhpcy5faGlzdG9yeS5wdXNoU3RhdGUocGF0aCk7CiAgICAgIH0KICAgIH0KICAgIGBgYAogIAogICAgQGNsYXNzIExvY2F0aW9uCiAgICBAcHJpdmF0ZQogICovCiAgdmFyIF9kZWZhdWx0ID0gewogICAgLyoqCiAgICAgVGhpcyBpcyBkZXByZWNhdGVkIGluIGZhdm9yIG9mIHVzaW5nIHRoZSBjb250YWluZXIgdG8gbG9va3VwIHRoZSBsb2NhdGlvbgogICAgIGltcGxlbWVudGF0aW9uIGFzIGRlc2lyZWQuCiAgICAgICAgRm9yIGV4YW1wbGU6CiAgICAgICAgYGBgamF2YXNjcmlwdAogICAgIC8vIEdpdmVuIGEgbG9jYXRpb24gcmVnaXN0ZXJlZCBhcyBmb2xsb3dzOgogICAgIGNvbnRhaW5lci5yZWdpc3RlcignbG9jYXRpb246aGlzdG9yeS10ZXN0JywgSGlzdG9yeVRlc3RMb2NhdGlvbik7CiAgICAgICAgLy8gWW91IGNvdWxkIGNyZWF0ZSBhIG5ldyBpbnN0YW5jZSB2aWE6CiAgICAgY29udGFpbmVyLmxvb2t1cCgnbG9jYXRpb246aGlzdG9yeS10ZXN0Jyk7CiAgICAgYGBgCiAgICAgICAgIEBtZXRob2QgY3JlYXRlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgIEByZXR1cm4ge09iamVjdH0gYW4gaW5zdGFuY2Ugb2YgYW4gaW1wbGVtZW50YXRpb24gb2YgdGhlIGBsb2NhdGlvbmAgQVBJCiAgICAgIEBkZXByZWNhdGVkIFVzZSB0aGUgY29udGFpbmVyIHRvIGxvb2t1cCB0aGUgbG9jYXRpb24gaW1wbGVtZW50YXRpb24gdGhhdCB5b3UKICAgICAgbmVlZC4KICAgICAgQHByaXZhdGUKICAgICovCiAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShvcHRpb25zKSB7CiAgICAgIHZhciBpbXBsZW1lbnRhdGlvbiA9IG9wdGlvbnMgJiYgb3B0aW9ucy5pbXBsZW1lbnRhdGlvbjsKICAgICAgKGZhbHNlICYmICEoQm9vbGVhbihpbXBsZW1lbnRhdGlvbikpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiTG9jYXRpb24uY3JlYXRlOiB5b3UgbXVzdCBzcGVjaWZ5IGEgJ2ltcGxlbWVudGF0aW9uJyBvcHRpb24iLCBCb29sZWFuKGltcGxlbWVudGF0aW9uKSkpOwogICAgICB2YXIgaW1wbGVtZW50YXRpb25DbGFzcyA9IHRoaXMuaW1wbGVtZW50YXRpb25zW2ltcGxlbWVudGF0aW9uXTsKICAgICAgKGZhbHNlICYmICEoQm9vbGVhbihpbXBsZW1lbnRhdGlvbkNsYXNzKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJMb2NhdGlvbi5jcmVhdGU6ICIgKyBpbXBsZW1lbnRhdGlvbiArICIgaXMgbm90IGEgdmFsaWQgaW1wbGVtZW50YXRpb24iLCBCb29sZWFuKGltcGxlbWVudGF0aW9uQ2xhc3MpKSk7CiAgICAgIHJldHVybiBpbXBsZW1lbnRhdGlvbkNsYXNzLmNyZWF0ZS5hcHBseShpbXBsZW1lbnRhdGlvbkNsYXNzLCBhcmd1bWVudHMpOwogICAgfSwKICAgIGltcGxlbWVudGF0aW9uczoge30KICB9OwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vYXV0b19sb2NhdGlvbiIsIFsiZXhwb3J0cyIsICJlbWJlci1iYWJlbCIsICJAZW1iZXIvLWludGVybmFscy9icm93c2VyLWVudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL3V0aWwiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX2Jyb3dzZXJFbnZpcm9ubWVudCwgX21ldGFsLCBfb3duZXIsIF9ydW50aW1lLCBfdXRpbHMsIF9kZWJ1ZywgX3V0aWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmdldEhpc3RvcnlQYXRoID0gZ2V0SGlzdG9yeVBhdGg7CiAgX2V4cG9ydHMuZ2V0SGFzaFBhdGggPSBnZXRIYXNoUGF0aDsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIEBlbWJlci9yb3V0aW5nCiAgKi8KCiAgLyoqCiAgICBBdXRvTG9jYXRpb24gd2lsbCBzZWxlY3QgdGhlIGJlc3QgbG9jYXRpb24gb3B0aW9uIGJhc2VkIG9mZiBicm93c2VyCiAgICBzdXBwb3J0IHdpdGggdGhlIHByaW9yaXR5IG9yZGVyOiBoaXN0b3J5LCBoYXNoLCBub25lLgogIAogICAgQ2xlYW4gcHVzaFN0YXRlIHBhdGhzIGFjY2Vzc2VkIGJ5IGhhc2hjaGFuZ2Utb25seSBicm93c2VycyB3aWxsIGJlIHJlZGlyZWN0ZWQKICAgIHRvIHRoZSBoYXNoLWVxdWl2YWxlbnQgYW5kIHZpY2UgdmVyc2Egc28gZnV0dXJlIHRyYW5zaXRpb25zIGFyZSBjb25zaXN0ZW50LgogIAogICAgS2VlcCBpbiBtaW5kIHRoYXQgc2luY2Ugc29tZSBvZiB5b3VyIHVzZXJzIHdpbGwgdXNlIGBIaXN0b3J5TG9jYXRpb25gLCB5b3VyCiAgICBzZXJ2ZXIgbXVzdCBzZXJ2ZSB0aGUgRW1iZXIgYXBwIGF0IGFsbCB0aGUgcm91dGVzIHlvdSBkZWZpbmUuCiAgCiAgICBCcm93c2VycyB0aGF0IHN1cHBvcnQgdGhlIGBoaXN0b3J5YCBBUEkgd2lsbCB1c2UgYEhpc3RvcnlMb2NhdGlvbmAsIHRob3NlIHRoYXQKICAgIGRvIG5vdCwgYnV0IHN0aWxsIHN1cHBvcnQgdGhlIGBoYXNoY2hhbmdlYCBldmVudCB3aWxsIHVzZSBgSGFzaExvY2F0aW9uYCwgYW5kCiAgICBpbiB0aGUgcmFyZSBjYXNlIG5laXRoZXIgaXMgc3VwcG9ydGVkIHdpbGwgdXNlIGBOb25lTG9jYXRpb25gLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgIHRoaXMucm91dGUoJ3Bvc3RzJywgZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgnbmV3Jyk7CiAgICAgIH0pOwogICAgfSk7CiAgCiAgICBSb3V0ZXIucmVvcGVuKHsKICAgICAgbG9jYXRpb246ICdhdXRvJwogICAgfSk7CiAgICBgYGAKICAKICAgIFRoaXMgd2lsbCByZXN1bHQgaW4gYSBwb3N0cy5uZXcgdXJsIG9mIGAvcG9zdHMvbmV3YCBmb3IgbW9kZXJuIGJyb3dzZXJzIHRoYXQKICAgIHN1cHBvcnQgdGhlIGBoaXN0b3J5YCBhcGkgb3IgYC8jL3Bvc3RzL25ld2AgZm9yIG9sZGVyIG9uZXMsIGxpa2UgSW50ZXJuZXQKICAgIEV4cGxvcmVyIDkgYW5kIGJlbG93LgogIAogICAgV2hlbiBhIHVzZXIgdmlzaXRzIGEgbGluayB0byB5b3VyIGFwcGxpY2F0aW9uLCB0aGV5IHdpbGwgYmUgYXV0b21hdGljYWxseQogICAgdXBncmFkZWQgb3IgZG93bmdyYWRlZCB0byB0aGUgYXBwcm9wcmlhdGUgYExvY2F0aW9uYCBjbGFzcywgd2l0aCB0aGUgVVJMCiAgICB0cmFuc2Zvcm1lZCBhY2NvcmRpbmdseSwgaWYgbmVlZGVkLgogIAogICAgS2VlcCBpbiBtaW5kIHRoYXQgc2luY2Ugc29tZSBvZiB5b3VyIHVzZXJzIHdpbGwgdXNlIGBIaXN0b3J5TG9jYXRpb25gLCB5b3VyCiAgICBzZXJ2ZXIgbXVzdCBzZXJ2ZSB0aGUgRW1iZXIgYXBwIGF0IGFsbCB0aGUgcm91dGVzIHlvdSBkZWZpbmUuCiAgCiAgICBAY2xhc3MgQXV0b0xvY2F0aW9uCiAgICBAc3RhdGljCiAgICBAcHJvdGVjdGVkCiAgKi8KICB2YXIgQXV0b0xvY2F0aW9uID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9FbWJlck9iamVjdCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEF1dG9Mb2NhdGlvbiwgX0VtYmVyT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBBdXRvTG9jYXRpb24oKSB7CiAgICAgIHZhciBfdGhpczsKCiAgICAgIF90aGlzID0gX0VtYmVyT2JqZWN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgICAgX3RoaXMuaW1wbGVtZW50YXRpb24gPSAnYXV0byc7CiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KICAgIC8qKgogICAgIENhbGxlZCBieSB0aGUgcm91dGVyIHRvIGluc3RydWN0IHRoZSBsb2NhdGlvbiB0byBkbyBhbnkgZmVhdHVyZSBkZXRlY3Rpb24KICAgICBuZWNlc3NhcnkuIEluIHRoZSBjYXNlIG9mIEF1dG9Mb2NhdGlvbiwgd2UgZGV0ZWN0IHdoZXRoZXIgdG8gdXNlIGhpc3RvcnkKICAgICBvciBoYXNoIGNvbmNyZXRlIGltcGxlbWVudGF0aW9ucy4KICAgICAgICBAcHJpdmF0ZQogICAgKi8KCgogICAgdmFyIF9wcm90byA9IEF1dG9Mb2NhdGlvbi5wcm90b3R5cGU7CgogICAgX3Byb3RvLmRldGVjdCA9IGZ1bmN0aW9uIGRldGVjdCgpIHsKICAgICAgdmFyIHJvb3RVUkwgPSB0aGlzLnJvb3RVUkw7CiAgICAgIChmYWxzZSAmJiAhKHJvb3RVUkwuY2hhckF0KHJvb3RVUkwubGVuZ3RoIC0gMSkgPT09ICcvJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdyb290VVJMIG11c3QgZW5kIHdpdGggYSB0cmFpbGluZyBmb3J3YXJkIHNsYXNoIGUuZy4gIi9hcHAvIicsIHJvb3RVUkwuY2hhckF0KHJvb3RVUkwubGVuZ3RoIC0gMSkgPT09ICcvJykpOwogICAgICB2YXIgaW1wbGVtZW50YXRpb24gPSBkZXRlY3RJbXBsZW1lbnRhdGlvbih7CiAgICAgICAgbG9jYXRpb246IHRoaXMubG9jYXRpb24sCiAgICAgICAgaGlzdG9yeTogdGhpcy5oaXN0b3J5LAogICAgICAgIHVzZXJBZ2VudDogdGhpcy51c2VyQWdlbnQsCiAgICAgICAgcm9vdFVSTDogcm9vdFVSTCwKICAgICAgICBkb2N1bWVudE1vZGU6IHRoaXMuZG9jdW1lbnRNb2RlLAogICAgICAgIGdsb2JhbDogdGhpcy5nbG9iYWwKICAgICAgfSk7CgogICAgICBpZiAoaW1wbGVtZW50YXRpb24gPT09IGZhbHNlKSB7CiAgICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdjYW5jZWxSb3V0ZXJTZXR1cCcsIHRydWUpOwogICAgICAgIGltcGxlbWVudGF0aW9uID0gJ25vbmUnOwogICAgICB9CgogICAgICB2YXIgY29uY3JldGUgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKS5sb29rdXAoImxvY2F0aW9uOiIgKyBpbXBsZW1lbnRhdGlvbik7CiAgICAgIChmYWxzZSAmJiAhKGNvbmNyZXRlICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ291bGQgbm90IGZpbmQgbG9jYXRpb24gJyIgKyBpbXBsZW1lbnRhdGlvbiArICInLiIsIGNvbmNyZXRlICE9PSB1bmRlZmluZWQpKTsKICAgICAgKDAsIF9tZXRhbC5zZXQpKGNvbmNyZXRlLCAncm9vdFVSTCcsIHJvb3RVUkwpOwogICAgICAoMCwgX21ldGFsLnNldCkodGhpcywgJ2NvbmNyZXRlSW1wbGVtZW50YXRpb24nLCBjb25jcmV0ZSk7CiAgICB9OwoKICAgIF9wcm90by53aWxsRGVzdHJveSA9IGZ1bmN0aW9uIHdpbGxEZXN0cm95KCkgewogICAgICB2YXIgY29uY3JldGVJbXBsZW1lbnRhdGlvbiA9IHRoaXMuY29uY3JldGVJbXBsZW1lbnRhdGlvbjsKCiAgICAgIGlmIChjb25jcmV0ZUltcGxlbWVudGF0aW9uKSB7CiAgICAgICAgY29uY3JldGVJbXBsZW1lbnRhdGlvbi5kZXN0cm95KCk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEF1dG9Mb2NhdGlvbjsKICB9KF9ydW50aW1lLk9iamVjdCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBBdXRvTG9jYXRpb247CiAgQXV0b0xvY2F0aW9uLnJlb3Blbih7CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgV2lsbCBiZSBwcmUtcGVuZGVkIHRvIHBhdGggdXBvbiBzdGF0ZSBjaGFuZ2UuCiAgICAgICAgIEBzaW5jZSAxLjUuMQogICAgICBAcHJvcGVydHkgcm9vdFVSTAogICAgICBAZGVmYXVsdCAnLycKICAgICovCiAgICByb290VVJMOiAnLycsCiAgICBpbml0U3RhdGU6IGRlbGVnYXRlVG9Db25jcmV0ZUltcGxlbWVudGF0aW9uKCdpbml0U3RhdGUnKSwKICAgIGdldFVSTDogZGVsZWdhdGVUb0NvbmNyZXRlSW1wbGVtZW50YXRpb24oJ2dldFVSTCcpLAogICAgc2V0VVJMOiBkZWxlZ2F0ZVRvQ29uY3JldGVJbXBsZW1lbnRhdGlvbignc2V0VVJMJyksCiAgICByZXBsYWNlVVJMOiBkZWxlZ2F0ZVRvQ29uY3JldGVJbXBsZW1lbnRhdGlvbigncmVwbGFjZVVSTCcpLAogICAgb25VcGRhdGVVUkw6IGRlbGVnYXRlVG9Db25jcmV0ZUltcGxlbWVudGF0aW9uKCdvblVwZGF0ZVVSTCcpLAogICAgZm9ybWF0VVJMOiBkZWxlZ2F0ZVRvQ29uY3JldGVJbXBsZW1lbnRhdGlvbignZm9ybWF0VVJMJyksCgogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgICAgIFRoZSBicm93c2VyJ3MgYGxvY2F0aW9uYCBvYmplY3QuIFRoaXMgaXMgdHlwaWNhbGx5IGVxdWl2YWxlbnQgdG8KICAgICAgYHdpbmRvdy5sb2NhdGlvbmAsIGJ1dCBtYXkgYmUgb3ZlcnJpZGRlbiBmb3IgdGVzdGluZy4KICAgICAgICAgQHByb3BlcnR5IGxvY2F0aW9uCiAgICAgIEBkZWZhdWx0IGVudmlyb25tZW50LmxvY2F0aW9uCiAgICAqLwogICAgbG9jYXRpb246IF9icm93c2VyRW52aXJvbm1lbnQubG9jYXRpb24sCgogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgICAgIFRoZSBicm93c2VyJ3MgYGhpc3RvcnlgIG9iamVjdC4gVGhpcyBpcyB0eXBpY2FsbHkgZXF1aXZhbGVudCB0bwogICAgICBgd2luZG93Lmhpc3RvcnlgLCBidXQgbWF5IGJlIG92ZXJyaWRkZW4gZm9yIHRlc3RpbmcuCiAgICAgICAgIEBzaW5jZSAxLjUuMQogICAgICBAcHJvcGVydHkgaGlzdG9yeQogICAgICBAZGVmYXVsdCBlbnZpcm9ubWVudC5oaXN0b3J5CiAgICAqLwogICAgaGlzdG9yeTogX2Jyb3dzZXJFbnZpcm9ubWVudC5oaXN0b3J5LAoKICAgIC8qKgogICAgIEBwcml2YXRlCiAgICAgICAgVGhlIHVzZXIgYWdlbnQncyBnbG9iYWwgdmFyaWFibGUuIEluIGJyb3dzZXJzLCB0aGlzIHdpbGwgYmUgYHdpbmRvd2AuCiAgICAgICAgQHNpbmNlIDEuMTEKICAgICBAcHJvcGVydHkgZ2xvYmFsCiAgICAgQGRlZmF1bHQgd2luZG93CiAgICAqLwogICAgZ2xvYmFsOiBfYnJvd3NlckVudmlyb25tZW50LndpbmRvdywKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgVGhlIGJyb3dzZXIncyBgdXNlckFnZW50YC4gVGhpcyBpcyB0eXBpY2FsbHkgZXF1aXZhbGVudCB0bwogICAgICBgbmF2aWdhdG9yLnVzZXJBZ2VudGAsIGJ1dCBtYXkgYmUgb3ZlcnJpZGRlbiBmb3IgdGVzdGluZy4KICAgICAgICAgQHNpbmNlIDEuNS4xCiAgICAgIEBwcm9wZXJ0eSB1c2VyQWdlbnQKICAgICAgQGRlZmF1bHQgZW52aXJvbm1lbnQuaGlzdG9yeQogICAgKi8KICAgIHVzZXJBZ2VudDogX2Jyb3dzZXJFbnZpcm9ubWVudC51c2VyQWdlbnQsCgogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgICAgIFRoaXMgcHJvcGVydHkgaXMgdXNlZCBieSB0aGUgcm91dGVyIHRvIGtub3cgd2hldGhlciB0byBjYW5jZWwgdGhlIHJvdXRpbmcKICAgICAgc2V0dXAgcHJvY2Vzcywgd2hpY2ggaXMgbmVlZGVkIHdoaWxlIHdlIHJlZGlyZWN0IHRoZSBicm93c2VyLgogICAgICAgICBAc2luY2UgMS41LjEKICAgICAgQHByb3BlcnR5IGNhbmNlbFJvdXRlclNldHVwCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAqLwogICAgY2FuY2VsUm91dGVyU2V0dXA6IGZhbHNlCiAgfSk7CgogIGZ1bmN0aW9uIGRlbGVnYXRlVG9Db25jcmV0ZUltcGxlbWVudGF0aW9uKG1ldGhvZE5hbWUpIHsKICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBjb25jcmV0ZUltcGxlbWVudGF0aW9uID0gdGhpcy5jb25jcmV0ZUltcGxlbWVudGF0aW9uOwogICAgICAoZmFsc2UgJiYgIShCb29sZWFuKGNvbmNyZXRlSW1wbGVtZW50YXRpb24pKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF1dG9Mb2NhdGlvbidzIGRldGVjdCgpIG1ldGhvZCBzaG91bGQgYmUgY2FsbGVkIGJlZm9yZSBjYWxsaW5nIGFueSBvdGhlciBob29rcy4iLCBCb29sZWFuKGNvbmNyZXRlSW1wbGVtZW50YXRpb24pKSk7CgogICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICByZXR1cm4gKDAsIF91dGlscy50cnlJbnZva2UpKGNvbmNyZXRlSW1wbGVtZW50YXRpb24sIG1ldGhvZE5hbWUsIGFyZ3MpOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIGRldGVjdEltcGxlbWVudGF0aW9uKG9wdGlvbnMpIHsKICAgIHZhciBsb2NhdGlvbiA9IG9wdGlvbnMubG9jYXRpb24sCiAgICAgICAgdXNlckFnZW50ID0gb3B0aW9ucy51c2VyQWdlbnQsCiAgICAgICAgaGlzdG9yeSA9IG9wdGlvbnMuaGlzdG9yeSwKICAgICAgICBkb2N1bWVudE1vZGUgPSBvcHRpb25zLmRvY3VtZW50TW9kZSwKICAgICAgICBnbG9iYWwgPSBvcHRpb25zLmdsb2JhbCwKICAgICAgICByb290VVJMID0gb3B0aW9ucy5yb290VVJMOwogICAgdmFyIGltcGxlbWVudGF0aW9uID0gJ25vbmUnOwogICAgdmFyIGNhbmNlbFJvdXRlclNldHVwID0gZmFsc2U7CiAgICB2YXIgY3VycmVudFBhdGggPSAoMCwgX3V0aWwuZ2V0RnVsbFBhdGgpKGxvY2F0aW9uKTsKCiAgICBpZiAoKDAsIF91dGlsLnN1cHBvcnRzSGlzdG9yeSkodXNlckFnZW50LCBoaXN0b3J5KSkgewogICAgICB2YXIgaGlzdG9yeVBhdGggPSBnZXRIaXN0b3J5UGF0aChyb290VVJMLCBsb2NhdGlvbik7IC8vIElmIHRoZSBicm93c2VyIHN1cHBvcnRzIGhpc3RvcnkgYW5kIHdlIGhhdmUgYSBoaXN0b3J5IHBhdGgsIHdlIGNhbiB1c2UKICAgICAgLy8gdGhlIGhpc3RvcnkgbG9jYXRpb24gd2l0aCBubyByZWRpcmVjdHMuCgogICAgICBpZiAoY3VycmVudFBhdGggPT09IGhpc3RvcnlQYXRoKSB7CiAgICAgICAgaW1wbGVtZW50YXRpb24gPSAnaGlzdG9yeSc7CiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFBhdGguc3Vic3RyKDAsIDIpID09PSAnLyMnKSB7CiAgICAgICAgaGlzdG9yeS5yZXBsYWNlU3RhdGUoewogICAgICAgICAgcGF0aDogaGlzdG9yeVBhdGgKICAgICAgICB9LCAnJywgaGlzdG9yeVBhdGgpOwogICAgICAgIGltcGxlbWVudGF0aW9uID0gJ2hpc3RvcnknOwogICAgICB9IGVsc2UgewogICAgICAgIGNhbmNlbFJvdXRlclNldHVwID0gdHJ1ZTsKICAgICAgICAoMCwgX3V0aWwucmVwbGFjZVBhdGgpKGxvY2F0aW9uLCBoaXN0b3J5UGF0aCk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoKDAsIF91dGlsLnN1cHBvcnRzSGFzaENoYW5nZSkoZG9jdW1lbnRNb2RlLCBnbG9iYWwpKSB7CiAgICAgIHZhciBoYXNoUGF0aCA9IGdldEhhc2hQYXRoKHJvb3RVUkwsIGxvY2F0aW9uKTsgLy8gQmUgc3VyZSB3ZSdyZSB1c2luZyBhIGhhc2hlZCBwYXRoLCBvdGhlcndpc2UgbGV0J3Mgc3dpdGNoIG92ZXIgaXQgdG8gc28KICAgICAgLy8gd2Ugc3RhcnQgb2ZmIGNsZWFuIGFuZCBjb25zaXN0ZW50LiBXZSdsbCBjb3VudCBhbiBpbmRleCBwYXRoIHdpdGggbm8KICAgICAgLy8gaGFzaCBhcyAiZ29vZCBlbm91Z2giIGFzIHdlbGwuCgogICAgICBpZiAoY3VycmVudFBhdGggPT09IGhhc2hQYXRoIHx8IGN1cnJlbnRQYXRoID09PSAnLycgJiYgaGFzaFBhdGggPT09ICcvIy8nKSB7CiAgICAgICAgaW1wbGVtZW50YXRpb24gPSAnaGFzaCc7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gT3VyIFVSTCBpc24ndCBpbiB0aGUgZXhwZWN0ZWQgaGFzaC1zdXBwb3J0ZWQgZm9ybWF0LCBzbyB3ZSB3YW50IHRvCiAgICAgICAgLy8gY2FuY2VsIHRoZSByb3V0ZXIgc2V0dXAgYW5kIHJlcGxhY2UgdGhlIFVSTCB0byBzdGFydCBvZmYgY2xlYW4KICAgICAgICBjYW5jZWxSb3V0ZXJTZXR1cCA9IHRydWU7CiAgICAgICAgKDAsIF91dGlsLnJlcGxhY2VQYXRoKShsb2NhdGlvbiwgaGFzaFBhdGgpOwogICAgICB9CiAgICB9CgogICAgaWYgKGNhbmNlbFJvdXRlclNldHVwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICByZXR1cm4gaW1wbGVtZW50YXRpb247CiAgfQogIC8qKgogICAgQHByaXZhdGUKICAKICAgIFJldHVybnMgdGhlIGN1cnJlbnQgcGF0aCBhcyBpdCBzaG91bGQgYXBwZWFyIGZvciBIaXN0b3J5TG9jYXRpb24gc3VwcG9ydGVkCiAgICBicm93c2Vycy4gVGhpcyBtYXkgdmVyeSB3ZWxsIGRpZmZlciBmcm9tIHRoZSByZWFsIGN1cnJlbnQgcGF0aCAoZS5nLiBpZiBpdAogICAgc3RhcnRzIG9mZiBhcyBhIGhhc2hlZCBVUkwpCiAgKi8KCgogIGZ1bmN0aW9uIGdldEhpc3RvcnlQYXRoKHJvb3RVUkwsIGxvY2F0aW9uKSB7CiAgICB2YXIgcGF0aCA9ICgwLCBfdXRpbC5nZXRQYXRoKShsb2NhdGlvbik7CiAgICB2YXIgaGFzaCA9ICgwLCBfdXRpbC5nZXRIYXNoKShsb2NhdGlvbik7CiAgICB2YXIgcXVlcnkgPSAoMCwgX3V0aWwuZ2V0UXVlcnkpKGxvY2F0aW9uKTsKICAgIHZhciByb290VVJMSW5kZXggPSBwYXRoLmluZGV4T2Yocm9vdFVSTCk7CiAgICB2YXIgcm91dGVIYXNoLCBoYXNoUGFydHM7CiAgICAoZmFsc2UgJiYgIShyb290VVJMSW5kZXggPT09IDApICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiUGF0aCAiICsgcGF0aCArICIgZG9lcyBub3Qgc3RhcnQgd2l0aCB0aGUgcHJvdmlkZWQgcm9vdFVSTCAiICsgcm9vdFVSTCwgcm9vdFVSTEluZGV4ID09PSAwKSk7IC8vIEJ5IGNvbnZlbnRpb24sIEVtYmVyLmpzIHJvdXRlcyB1c2luZyBIYXNoTG9jYXRpb24gYXJlIHJlcXVpcmVkIHRvIHN0YXJ0CiAgICAvLyB3aXRoIGAjL2AuIEFueXRoaW5nIGVsc2Ugc2hvdWxkIE5PVCBiZSBjb25zaWRlcmVkIGEgcm91dGUgYW5kIHNob3VsZAogICAgLy8gYmUgcGFzc2VkIHN0cmFpZ2h0IHRocm91Z2gsIHdpdGhvdXQgdHJhbnNmb3JtYXRpb24uCgogICAgaWYgKGhhc2guc3Vic3RyKDAsIDIpID09PSAnIy8nKSB7CiAgICAgIC8vIFRoZXJlIGNvdWxkIGJlIGV4dHJhIGhhc2ggc2VnbWVudHMgYWZ0ZXIgdGhlIHJvdXRlCiAgICAgIGhhc2hQYXJ0cyA9IGhhc2guc3Vic3RyKDEpLnNwbGl0KCcjJyk7IC8vIFRoZSBmaXJzdCBvbmUgaXMgYWx3YXlzIHRoZSByb3V0ZSB1cmwKCiAgICAgIHJvdXRlSGFzaCA9IGhhc2hQYXJ0cy5zaGlmdCgpOyAvLyBJZiB0aGUgcGF0aCBhbHJlYWR5IGhhcyBhIHRyYWlsaW5nIHNsYXNoLCByZW1vdmUgdGhlIG9uZQogICAgICAvLyBmcm9tIHRoZSBoYXNoZWQgcm91dGUgc28gd2UgZG9uJ3QgZG91YmxlIHVwLgoKICAgICAgaWYgKHBhdGguY2hhckF0KHBhdGgubGVuZ3RoIC0gMSkgPT09ICcvJykgewogICAgICAgIHJvdXRlSGFzaCA9IHJvdXRlSGFzaC5zdWJzdHIoMSk7CiAgICAgIH0gLy8gVGhpcyBpcyB0aGUgImV4cGVjdGVkIiBmaW5hbCBvcmRlcgoKCiAgICAgIHBhdGggKz0gcm91dGVIYXNoICsgcXVlcnk7CgogICAgICBpZiAoaGFzaFBhcnRzLmxlbmd0aCkgewogICAgICAgIHBhdGggKz0gIiMiICsgaGFzaFBhcnRzLmpvaW4oJyMnKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgcGF0aCArPSBxdWVyeSArIGhhc2g7CiAgICB9CgogICAgcmV0dXJuIHBhdGg7CiAgfQogIC8qKgogICAgQHByaXZhdGUKICAKICAgIFJldHVybnMgdGhlIGN1cnJlbnQgcGF0aCBhcyBpdCBzaG91bGQgYXBwZWFyIGZvciBIYXNoTG9jYXRpb24gc3VwcG9ydGVkCiAgICBicm93c2Vycy4gVGhpcyBtYXkgdmVyeSB3ZWxsIGRpZmZlciBmcm9tIHRoZSByZWFsIGN1cnJlbnQgcGF0aC4KICAKICAgIEBtZXRob2QgX2dldEhhc2hQYXRoCiAgKi8KCgogIGZ1bmN0aW9uIGdldEhhc2hQYXRoKHJvb3RVUkwsIGxvY2F0aW9uKSB7CiAgICB2YXIgcGF0aCA9IHJvb3RVUkw7CiAgICB2YXIgaGlzdG9yeVBhdGggPSBnZXRIaXN0b3J5UGF0aChyb290VVJMLCBsb2NhdGlvbik7CiAgICB2YXIgcm91dGVQYXRoID0gaGlzdG9yeVBhdGguc3Vic3RyKHJvb3RVUkwubGVuZ3RoKTsKCiAgICBpZiAocm91dGVQYXRoICE9PSAnJykgewogICAgICBpZiAocm91dGVQYXRoWzBdICE9PSAnLycpIHsKICAgICAgICByb3V0ZVBhdGggPSAiLyIgKyByb3V0ZVBhdGg7CiAgICAgIH0KCiAgICAgIHBhdGggKz0gIiMiICsgcm91dGVQYXRoOwogICAgfQoKICAgIHJldHVybiBwYXRoOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vaGFzaF9sb2NhdGlvbiIsIFsiZXhwb3J0cyIsICJlbWJlci1iYWJlbCIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIiwgIkBlbWJlci9ydW5sb29wIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL3V0aWwiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX21ldGFsLCBfcnVudGltZSwgX3J1bmxvb3AsIF91dGlsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIEBlbWJlci9yb3V0aW5nCiAgKi8KCiAgLyoqCiAgICBgSGFzaExvY2F0aW9uYCBpbXBsZW1lbnRzIHRoZSBsb2NhdGlvbiBBUEkgdXNpbmcgdGhlIGJyb3dzZXIncwogICAgaGFzaC4gQXQgcHJlc2VudCwgaXQgcmVsaWVzIG9uIGEgYGhhc2hjaGFuZ2VgIGV2ZW50IGV4aXN0aW5nIGluIHRoZQogICAgYnJvd3Nlci4KICAKICAgIFVzaW5nIGBIYXNoTG9jYXRpb25gIHJlc3VsdHMgaW4gVVJMcyB3aXRoIGEgYCNgIChoYXNoIHNpZ24pIHNlcGFyYXRpbmcgdGhlCiAgICBzZXJ2ZXIgc2lkZSBVUkwgcG9ydGlvbiBvZiB0aGUgVVJMIGZyb20gdGhlIHBvcnRpb24gdGhhdCBpcyB1c2VkIGJ5IEVtYmVyLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgIHRoaXMucm91dGUoJ3Bvc3RzJywgZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgnbmV3Jyk7CiAgICAgIH0pOwogICAgfSk7CiAgCiAgICBSb3V0ZXIucmVvcGVuKHsKICAgICAgbG9jYXRpb246ICdoYXNoJwogICAgfSk7CiAgICBgYGAKICAKICAgIFRoaXMgd2lsbCByZXN1bHQgaW4gYSBwb3N0cy5uZXcgdXJsIG9mIGAvIy9wb3N0cy9uZXdgLgogIAogICAgQGNsYXNzIEhhc2hMb2NhdGlvbgogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAgIEBwcm90ZWN0ZWQKICAqLwogIHZhciBIYXNoTG9jYXRpb24gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0VtYmVyT2JqZWN0KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoSGFzaExvY2F0aW9uLCBfRW1iZXJPYmplY3QpOwoKICAgIGZ1bmN0aW9uIEhhc2hMb2NhdGlvbigpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfRW1iZXJPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpcy5pbXBsZW1lbnRhdGlvbiA9ICdoYXNoJzsKICAgICAgcmV0dXJuIF90aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBIYXNoTG9jYXRpb24ucHJvdG90eXBlOwoKICAgIF9wcm90by5pbml0ID0gZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdsb2NhdGlvbicsIHRoaXMuX2xvY2F0aW9uIHx8IHdpbmRvdy5sb2NhdGlvbik7CiAgICAgIHRoaXMuX2hhc2hjaGFuZ2VIYW5kbGVyID0gdW5kZWZpbmVkOwogICAgfQogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgICAgIFJldHVybnMgbm9ybWFsaXplZCBsb2NhdGlvbi5oYXNoCiAgICAgICAgIEBzaW5jZSAxLjUuMQogICAgICBAbWV0aG9kIGdldEhhc2gKICAgICovCiAgICA7CgogICAgX3Byb3RvLmdldEhhc2ggPSBmdW5jdGlvbiBnZXRIYXNoKCkgewogICAgICByZXR1cm4gKDAsIF91dGlsLmdldEhhc2gpKHRoaXMubG9jYXRpb24pOwogICAgfQogICAgLyoqCiAgICAgIFJldHVybnMgdGhlIG5vcm1hbGl6ZWQgVVJMLCBjb25zdHJ1Y3RlZCBmcm9tIGBsb2NhdGlvbi5oYXNoYC4KICAgICAgICAgZS5nLiBgIy9mb29gID0+IGAvZm9vYCBhcyB3ZWxsIGFzIGAjL2ZvbyNiYXJgID0+IGAvZm9vI2JhcmAuCiAgICAgICAgIEJ5IGNvbnZlbnRpb24sIGhhc2hlZCBwYXRocyBtdXN0IGJlZ2luIHdpdGggYSBmb3J3YXJkIHNsYXNoLCBvdGhlcndpc2UgdGhleQogICAgICBhcmUgbm90IHRyZWF0ZWQgYXMgYSBwYXRoIHNvIHdlIGNhbiBkaXN0aW5ndWlzaCBpbnRlbnQuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZ2V0VVJMCiAgICAqLwogICAgOwoKICAgIF9wcm90by5nZXRVUkwgPSBmdW5jdGlvbiBnZXRVUkwoKSB7CiAgICAgIHZhciBvcmlnaW5hbFBhdGggPSB0aGlzLmdldEhhc2goKS5zdWJzdHIoMSk7CiAgICAgIHZhciBvdXRQYXRoID0gb3JpZ2luYWxQYXRoOwoKICAgICAgaWYgKG91dFBhdGhbMF0gIT09ICcvJykgewogICAgICAgIG91dFBhdGggPSAnLyc7IC8vIE9ubHkgYWRkIHRoZSAjIGlmIHRoZSBwYXRoIGlzbid0IGVtcHR5LgogICAgICAgIC8vIFdlIGRvIE5PVCB3YW50IGAvI2Agc2luY2UgdGhlIGFtcGVyc2FuZAogICAgICAgIC8vIGlzIG9ubHkgaW5jbHVkZWQgKGNvbnZlbnRpb25hbGx5KSB3aGVuCiAgICAgICAgLy8gdGhlIGxvY2F0aW9uLmhhc2ggaGFzIGEgdmFsdWUKCiAgICAgICAgaWYgKG9yaWdpbmFsUGF0aCkgewogICAgICAgICAgb3V0UGF0aCArPSAiIyIgKyBvcmlnaW5hbFBhdGg7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gb3V0UGF0aDsKICAgIH0KICAgIC8qKgogICAgICBTZXQgdGhlIGBsb2NhdGlvbi5oYXNoYCBhbmQgcmVtZW1iZXJzIHdoYXQgd2FzIHNldC4gVGhpcyBwcmV2ZW50cwogICAgICBgb25VcGRhdGVVUkxgIGNhbGxiYWNrcyBmcm9tIHRyaWdnZXJpbmcgd2hlbiB0aGUgaGFzaCB3YXMgc2V0IGJ5CiAgICAgIGBIYXNoTG9jYXRpb25gLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHNldFVSTAogICAgICBAcGFyYW0gcGF0aCB7U3RyaW5nfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uc2V0VVJMID0gZnVuY3Rpb24gc2V0VVJMKHBhdGgpIHsKICAgICAgdGhpcy5sb2NhdGlvbi5oYXNoID0gcGF0aDsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdsYXN0U2V0VVJMJywgcGF0aCk7CiAgICB9CiAgICAvKioKICAgICAgVXNlcyBsb2NhdGlvbi5yZXBsYWNlIHRvIHVwZGF0ZSB0aGUgdXJsIHdpdGhvdXQgYSBwYWdlIHJlbG9hZAogICAgICBvciBoaXN0b3J5IG1vZGlmaWNhdGlvbi4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCByZXBsYWNlVVJMCiAgICAgIEBwYXJhbSBwYXRoIHtTdHJpbmd9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5yZXBsYWNlVVJMID0gZnVuY3Rpb24gcmVwbGFjZVVSTChwYXRoKSB7CiAgICAgIHRoaXMubG9jYXRpb24ucmVwbGFjZSgiIyIgKyBwYXRoKTsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdsYXN0U2V0VVJMJywgcGF0aCk7CiAgICB9CiAgICAvKioKICAgICAgUmVnaXN0ZXIgYSBjYWxsYmFjayB0byBiZSBpbnZva2VkIHdoZW4gdGhlIGhhc2ggY2hhbmdlcy4gVGhlc2UKICAgICAgY2FsbGJhY2tzIHdpbGwgZXhlY3V0ZSB3aGVuIHRoZSB1c2VyIHByZXNzZXMgdGhlIGJhY2sgb3IgZm9yd2FyZAogICAgICBidXR0b24sIGJ1dCBub3QgYWZ0ZXIgYHNldFVSTGAgaXMgaW52b2tlZC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBvblVwZGF0ZVVSTAogICAgICBAcGFyYW0gY2FsbGJhY2sge0Z1bmN0aW9ufQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ub25VcGRhdGVVUkwgPSBmdW5jdGlvbiBvblVwZGF0ZVVSTChjYWxsYmFjaykgewogICAgICB0aGlzLl9yZW1vdmVFdmVudExpc3RlbmVyKCk7CgogICAgICB0aGlzLl9oYXNoY2hhbmdlSGFuZGxlciA9ICgwLCBfcnVubG9vcC5iaW5kKSh0aGlzLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIHBhdGggPSB0aGlzLmdldFVSTCgpOwoKICAgICAgICBpZiAodGhpcy5sYXN0U2V0VVJMID09PSBwYXRoKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICAoMCwgX21ldGFsLnNldCkodGhpcywgJ2xhc3RTZXRVUkwnLCBudWxsKTsKICAgICAgICBjYWxsYmFjayhwYXRoKTsKICAgICAgfSk7CiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdoYXNoY2hhbmdlJywgdGhpcy5faGFzaGNoYW5nZUhhbmRsZXIpOwogICAgfQogICAgLyoqCiAgICAgIEdpdmVuIGEgVVJMLCBmb3JtYXRzIGl0IHRvIGJlIHBsYWNlZCBpbnRvIHRoZSBwYWdlIGFzIHBhcnQKICAgICAgb2YgYW4gZWxlbWVudCdzIGBocmVmYCBhdHRyaWJ1dGUuCiAgICAgICAgIFRoaXMgaXMgdXNlZCwgZm9yIGV4YW1wbGUsIHdoZW4gdXNpbmcgdGhlIHt7YWN0aW9ufX0gaGVscGVyCiAgICAgIHRvIGdlbmVyYXRlIGEgVVJMIGJhc2VkIG9uIGFuIGV2ZW50LgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGZvcm1hdFVSTAogICAgICBAcGFyYW0gdXJsIHtTdHJpbmd9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5mb3JtYXRVUkwgPSBmdW5jdGlvbiBmb3JtYXRVUkwodXJsKSB7CiAgICAgIHJldHVybiAiIyIgKyB1cmw7CiAgICB9CiAgICAvKioKICAgICAgQ2xlYW5zIHVwIHRoZSBIYXNoTG9jYXRpb24gZXZlbnQgbGlzdGVuZXIuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2Qgd2lsbERlc3Ryb3kKICAgICovCiAgICA7CgogICAgX3Byb3RvLndpbGxEZXN0cm95ID0gZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3JlbW92ZUV2ZW50TGlzdGVuZXIoKTsKICAgIH07CgogICAgX3Byb3RvLl9yZW1vdmVFdmVudExpc3RlbmVyID0gZnVuY3Rpb24gX3JlbW92ZUV2ZW50TGlzdGVuZXIoKSB7CiAgICAgIGlmICh0aGlzLl9oYXNoY2hhbmdlSGFuZGxlcikgewogICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdoYXNoY2hhbmdlJywgdGhpcy5faGFzaGNoYW5nZUhhbmRsZXIpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBIYXNoTG9jYXRpb247CiAgfShfcnVudGltZS5PYmplY3QpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gSGFzaExvY2F0aW9uOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9sb2NhdGlvbi9oaXN0b3J5X2xvY2F0aW9uIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vdXRpbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfbWV0YWwsIF9ydW50aW1lLCBfdXRpbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvcm91dGluZwogICovCiAgdmFyIHBvcHN0YXRlRmlyZWQgPSBmYWxzZTsKCiAgZnVuY3Rpb24gX3V1aWQoKSB7CiAgICByZXR1cm4gJ3h4eHh4eHh4LXh4eHgtNHh4eC15eHh4LXh4eHh4eHh4eHh4eCcucmVwbGFjZSgvW3h5XS9nLCBmdW5jdGlvbiAoYykgewogICAgICB2YXIgciwgdjsKICAgICAgciA9IE1hdGgucmFuZG9tKCkgKiAxNiB8IDA7CiAgICAgIHYgPSBjID09PSAneCcgPyByIDogciAmIDMgfCA4OwogICAgICByZXR1cm4gdi50b1N0cmluZygxNik7CiAgICB9KTsKICB9CiAgLyoqCiAgICBIaXN0b3J5TG9jYXRpb24gaW1wbGVtZW50cyB0aGUgbG9jYXRpb24gQVBJIHVzaW5nIHRoZSBicm93c2VyJ3MKICAgIGhpc3RvcnkucHVzaFN0YXRlIEFQSS4KICAKICAgIFVzaW5nIGBIaXN0b3J5TG9jYXRpb25gIHJlc3VsdHMgaW4gVVJMcyB0aGF0IGFyZSBpbmRpc3Rpbmd1aXNoYWJsZSBmcm9tIGEKICAgIHN0YW5kYXJkIFVSTC4gVGhpcyByZWxpZXMgdXBvbiB0aGUgYnJvd3NlcidzIGBoaXN0b3J5YCBBUEkuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgYXBwL3JvdXRlci5qcwogICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgdGhpcy5yb3V0ZSgncG9zdHMnLCBmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCduZXcnKTsKICAgICAgfSk7CiAgICB9KTsKICAKICAgIFJvdXRlci5yZW9wZW4oewogICAgICBsb2NhdGlvbjogJ2hpc3RvcnknCiAgICB9KTsKICAgIGBgYAogIAogICAgVGhpcyB3aWxsIHJlc3VsdCBpbiBhIHBvc3RzLm5ldyB1cmwgb2YgYC9wb3N0cy9uZXdgLgogIAogICAgS2VlcCBpbiBtaW5kIHRoYXQgeW91ciBzZXJ2ZXIgbXVzdCBzZXJ2ZSB0aGUgRW1iZXIgYXBwIGF0IGFsbCB0aGUgcm91dGVzIHlvdQogICAgZGVmaW5lLgogIAogICAgQGNsYXNzIEhpc3RvcnlMb2NhdGlvbgogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAgIEBwcm90ZWN0ZWQKICAqLwoKCiAgdmFyIEhpc3RvcnlMb2NhdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW1iZXJPYmplY3QpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShIaXN0b3J5TG9jYXRpb24sIF9FbWJlck9iamVjdCk7CgogICAgZnVuY3Rpb24gSGlzdG9yeUxvY2F0aW9uKCkgewogICAgICB2YXIgX3RoaXM7CgogICAgICBfdGhpcyA9IF9FbWJlck9iamVjdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICAgIF90aGlzLmltcGxlbWVudGF0aW9uID0gJ2hpc3RvcnknOwogICAgICAvKioKICAgICAgICBXaWxsIGJlIHByZS1wZW5kZWQgdG8gcGF0aCB1cG9uIHN0YXRlIGNoYW5nZQogICAgICAgICAgICAgICBAcHJvcGVydHkgcm9vdFVSTAogICAgICAgIEBkZWZhdWx0ICcvJwogICAgICAgIEBwcml2YXRlCiAgICAgICovCgogICAgICBfdGhpcy5yb290VVJMID0gJy8nOwogICAgICByZXR1cm4gX3RoaXM7CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgUmV0dXJucyBub3JtYWxpemVkIGxvY2F0aW9uLmhhc2gKICAgICAgICAgQG1ldGhvZCBnZXRIYXNoCiAgICAqLwoKCiAgICB2YXIgX3Byb3RvID0gSGlzdG9yeUxvY2F0aW9uLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uZ2V0SGFzaCA9IGZ1bmN0aW9uIGdldEhhc2goKSB7CiAgICAgIHJldHVybiAoMCwgX3V0aWwuZ2V0SGFzaCkodGhpcy5sb2NhdGlvbik7CiAgICB9OwoKICAgIF9wcm90by5pbml0ID0gZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIHZhciBiYXNlID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignYmFzZScpOwogICAgICB2YXIgYmFzZVVSTCA9ICcnOwoKICAgICAgaWYgKGJhc2UpIHsKICAgICAgICBiYXNlVVJMID0gYmFzZS5nZXRBdHRyaWJ1dGUoJ2hyZWYnKTsKICAgICAgfQoKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdiYXNlVVJMJywgYmFzZVVSTCk7CiAgICAgICgwLCBfbWV0YWwuc2V0KSh0aGlzLCAnbG9jYXRpb24nLCB0aGlzLmxvY2F0aW9uIHx8IHdpbmRvdy5sb2NhdGlvbik7CiAgICAgIHRoaXMuX3BvcHN0YXRlSGFuZGxlciA9IHVuZGVmaW5lZDsKICAgIH0KICAgIC8qKgogICAgICBVc2VkIHRvIHNldCBzdGF0ZSBvbiBmaXJzdCBjYWxsIHRvIHNldFVSTAogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGluaXRTdGF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uaW5pdFN0YXRlID0gZnVuY3Rpb24gaW5pdFN0YXRlKCkgewogICAgICB2YXIgaGlzdG9yeSA9IHRoaXMuaGlzdG9yeSB8fCB3aW5kb3cuaGlzdG9yeTsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdoaXN0b3J5JywgaGlzdG9yeSk7CgogICAgICBpZiAoaGlzdG9yeSAmJiAnc3RhdGUnIGluIGhpc3RvcnkpIHsKICAgICAgICB0aGlzLnN1cHBvcnRzSGlzdG9yeSA9IHRydWU7CiAgICAgIH0KCiAgICAgIHZhciBzdGF0ZSA9IHRoaXMuZ2V0U3RhdGUoKTsKICAgICAgdmFyIHBhdGggPSB0aGlzLmZvcm1hdFVSTCh0aGlzLmdldFVSTCgpKTsKCiAgICAgIGlmIChzdGF0ZSAmJiBzdGF0ZS5wYXRoID09PSBwYXRoKSB7CiAgICAgICAgLy8gcHJlc2VydmUgZXhpc3Rpbmcgc3RhdGUKICAgICAgICAvLyB1c2VkIGZvciB3ZWJraXQgd29ya2Fyb3VuZCwgc2luY2UgdGhlcmUgd2lsbCBiZSBubyBpbml0aWFsIHBvcHN0YXRlIGV2ZW50CiAgICAgICAgdGhpcy5fcHJldmlvdXNVUkwgPSB0aGlzLmdldFVSTCgpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMucmVwbGFjZVN0YXRlKHBhdGgpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgUmV0dXJucyB0aGUgY3VycmVudCBgbG9jYXRpb24ucGF0aG5hbWVgIHdpdGhvdXQgYHJvb3RVUkxgIG9yIGBiYXNlVVJMYAogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGdldFVSTAogICAgICBAcmV0dXJuIHVybCB7U3RyaW5nfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZ2V0VVJMID0gZnVuY3Rpb24gZ2V0VVJMKCkgewogICAgICB2YXIgbG9jYXRpb24gPSB0aGlzLmxvY2F0aW9uLAogICAgICAgICAgcm9vdFVSTCA9IHRoaXMucm9vdFVSTCwKICAgICAgICAgIGJhc2VVUkwgPSB0aGlzLmJhc2VVUkw7CiAgICAgIHZhciBwYXRoID0gbG9jYXRpb24ucGF0aG5hbWU7IC8vIHJlbW92ZSB0cmFpbGluZyBzbGFzaGVzIGlmIHRoZXkgZXhpc3RzCgogICAgICByb290VVJMID0gcm9vdFVSTC5yZXBsYWNlKC9cLyQvLCAnJyk7CiAgICAgIGJhc2VVUkwgPSBiYXNlVVJMLnJlcGxhY2UoL1wvJC8sICcnKTsgLy8gcmVtb3ZlIGJhc2VVUkwgYW5kIHJvb3RVUkwgZnJvbSBzdGFydCBvZiBwYXRoCgogICAgICB2YXIgdXJsID0gcGF0aC5yZXBsYWNlKG5ldyBSZWdFeHAoIl4iICsgYmFzZVVSTCArICIoPz0vfCQpIiksICcnKS5yZXBsYWNlKG5ldyBSZWdFeHAoIl4iICsgcm9vdFVSTCArICIoPz0vfCQpIiksICcnKS5yZXBsYWNlKC9cL1wvL2csICcvJyk7IC8vIHJlbW92ZSBleHRyYSBzbGFzaGVzCgogICAgICB2YXIgc2VhcmNoID0gbG9jYXRpb24uc2VhcmNoIHx8ICcnOwogICAgICB1cmwgKz0gc2VhcmNoICsgdGhpcy5nZXRIYXNoKCk7CiAgICAgIHJldHVybiB1cmw7CiAgICB9CiAgICAvKioKICAgICAgVXNlcyBgaGlzdG9yeS5wdXNoU3RhdGVgIHRvIHVwZGF0ZSB0aGUgdXJsIHdpdGhvdXQgYSBwYWdlIHJlbG9hZC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBzZXRVUkwKICAgICAgQHBhcmFtIHBhdGgge1N0cmluZ30KICAgICovCiAgICA7CgogICAgX3Byb3RvLnNldFVSTCA9IGZ1bmN0aW9uIHNldFVSTChwYXRoKSB7CiAgICAgIHZhciBzdGF0ZSA9IHRoaXMuZ2V0U3RhdGUoKTsKICAgICAgcGF0aCA9IHRoaXMuZm9ybWF0VVJMKHBhdGgpOwoKICAgICAgaWYgKCFzdGF0ZSB8fCBzdGF0ZS5wYXRoICE9PSBwYXRoKSB7CiAgICAgICAgdGhpcy5wdXNoU3RhdGUocGF0aCk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBVc2VzIGBoaXN0b3J5LnJlcGxhY2VTdGF0ZWAgdG8gdXBkYXRlIHRoZSB1cmwgd2l0aG91dCBhIHBhZ2UgcmVsb2FkCiAgICAgIG9yIGhpc3RvcnkgbW9kaWZpY2F0aW9uLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHJlcGxhY2VVUkwKICAgICAgQHBhcmFtIHBhdGgge1N0cmluZ30KICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlcGxhY2VVUkwgPSBmdW5jdGlvbiByZXBsYWNlVVJMKHBhdGgpIHsKICAgICAgdmFyIHN0YXRlID0gdGhpcy5nZXRTdGF0ZSgpOwogICAgICBwYXRoID0gdGhpcy5mb3JtYXRVUkwocGF0aCk7CgogICAgICBpZiAoIXN0YXRlIHx8IHN0YXRlLnBhdGggIT09IHBhdGgpIHsKICAgICAgICB0aGlzLnJlcGxhY2VTdGF0ZShwYXRoKTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgIEdldCB0aGUgY3VycmVudCBgaGlzdG9yeS5zdGF0ZWAuIENoZWNrcyBmb3IgaWYgYSBwb2x5ZmlsbCBpcwogICAgICByZXF1aXJlZCBhbmQgaWYgc28gZmV0Y2hlcyB0aGlzLl9oaXN0b3J5U3RhdGUuIFRoZSBzdGF0ZSByZXR1cm5lZAogICAgICBmcm9tIGdldFN0YXRlIG1heSBiZSBudWxsIGlmIGFuIGlmcmFtZSBoYXMgY2hhbmdlZCBhIHdpbmRvdydzCiAgICAgIGhpc3RvcnkuCiAgICAgICAgIFRoZSBvYmplY3QgcmV0dXJuZWQgd2lsbCBjb250YWluIGEgYHBhdGhgIGZvciB0aGUgZ2l2ZW4gc3RhdGUgYXMgd2VsbAogICAgICBhcyBhIHVuaXF1ZSBzdGF0ZSBgaWRgLiBUaGUgc3RhdGUgaW5kZXggd2lsbCBhbGxvdyB0aGUgYXBwIHRvIGRpc3Rpbmd1aXNoCiAgICAgIGJldHdlZW4gdHdvIHN0YXRlcyB3aXRoIHNpbWlsYXIgcGF0aHMgYnV0IHNob3VsZCBiZSB1bmlxdWUgZnJvbSBvbmUgYW5vdGhlci4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBnZXRTdGF0ZQogICAgICBAcmV0dXJuIHN0YXRlIHtPYmplY3R9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5nZXRTdGF0ZSA9IGZ1bmN0aW9uIGdldFN0YXRlKCkgewogICAgICBpZiAodGhpcy5zdXBwb3J0c0hpc3RvcnkpIHsKICAgICAgICByZXR1cm4gdGhpcy5oaXN0b3J5LnN0YXRlOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5faGlzdG9yeVN0YXRlOwogICAgfQogICAgLyoqCiAgICAgUHVzaGVzIGEgbmV3IHN0YXRlLgogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBwdXNoU3RhdGUKICAgICBAcGFyYW0gcGF0aCB7U3RyaW5nfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucHVzaFN0YXRlID0gZnVuY3Rpb24gcHVzaFN0YXRlKHBhdGgpIHsKICAgICAgdmFyIHN0YXRlID0gewogICAgICAgIHBhdGg6IHBhdGgsCiAgICAgICAgdXVpZDogX3V1aWQoKQogICAgICB9OwogICAgICB0aGlzLmhpc3RvcnkucHVzaFN0YXRlKHN0YXRlLCBudWxsLCBwYXRoKTsKICAgICAgdGhpcy5faGlzdG9yeVN0YXRlID0gc3RhdGU7IC8vIHVzZWQgZm9yIHdlYmtpdCB3b3JrYXJvdW5kCgogICAgICB0aGlzLl9wcmV2aW91c1VSTCA9IHRoaXMuZ2V0VVJMKCk7CiAgICB9CiAgICAvKioKICAgICBSZXBsYWNlcyB0aGUgY3VycmVudCBzdGF0ZS4KICAgICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2QgcmVwbGFjZVN0YXRlCiAgICAgQHBhcmFtIHBhdGgge1N0cmluZ30KICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlcGxhY2VTdGF0ZSA9IGZ1bmN0aW9uIHJlcGxhY2VTdGF0ZShwYXRoKSB7CiAgICAgIHZhciBzdGF0ZSA9IHsKICAgICAgICBwYXRoOiBwYXRoLAogICAgICAgIHV1aWQ6IF91dWlkKCkKICAgICAgfTsKICAgICAgdGhpcy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShzdGF0ZSwgbnVsbCwgcGF0aCk7CiAgICAgIHRoaXMuX2hpc3RvcnlTdGF0ZSA9IHN0YXRlOyAvLyB1c2VkIGZvciB3ZWJraXQgd29ya2Fyb3VuZAoKICAgICAgdGhpcy5fcHJldmlvdXNVUkwgPSB0aGlzLmdldFVSTCgpOwogICAgfQogICAgLyoqCiAgICAgIFJlZ2lzdGVyIGEgY2FsbGJhY2sgdG8gYmUgaW52b2tlZCB3aGVuZXZlciB0aGUgYnJvd3NlcgogICAgICBoaXN0b3J5IGNoYW5nZXMsIGluY2x1ZGluZyB1c2luZyBmb3J3YXJkIGFuZCBiYWNrIGJ1dHRvbnMuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2Qgb25VcGRhdGVVUkwKICAgICAgQHBhcmFtIGNhbGxiYWNrIHtGdW5jdGlvbn0KICAgICovCiAgICA7CgogICAgX3Byb3RvLm9uVXBkYXRlVVJMID0gZnVuY3Rpb24gb25VcGRhdGVVUkwoY2FsbGJhY2spIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICB0aGlzLl9yZW1vdmVFdmVudExpc3RlbmVyKCk7CgogICAgICB0aGlzLl9wb3BzdGF0ZUhhbmRsZXIgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgLy8gSWdub3JlIGluaXRpYWwgcGFnZSBsb2FkIHBvcHN0YXRlIGV2ZW50IGluIENocm9tZQogICAgICAgIGlmICghcG9wc3RhdGVGaXJlZCkgewogICAgICAgICAgcG9wc3RhdGVGaXJlZCA9IHRydWU7CgogICAgICAgICAgaWYgKF90aGlzMi5nZXRVUkwoKSA9PT0gX3RoaXMyLl9wcmV2aW91c1VSTCkgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBjYWxsYmFjayhfdGhpczIuZ2V0VVJMKCkpOwogICAgICB9OwoKICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgdGhpcy5fcG9wc3RhdGVIYW5kbGVyKTsKICAgIH0KICAgIC8qKgogICAgICBVc2VkIHdoZW4gdXNpbmcgYHt7YWN0aW9ufX1gIGhlbHBlci4gIFRoZSB1cmwgaXMgYWx3YXlzIGFwcGVuZGVkIHRvIHRoZSByb290VVJMLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGZvcm1hdFVSTAogICAgICBAcGFyYW0gdXJsIHtTdHJpbmd9CiAgICAgIEByZXR1cm4gZm9ybWF0dGVkIHVybCB7U3RyaW5nfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZm9ybWF0VVJMID0gZnVuY3Rpb24gZm9ybWF0VVJMKHVybCkgewogICAgICB2YXIgcm9vdFVSTCA9IHRoaXMucm9vdFVSTCwKICAgICAgICAgIGJhc2VVUkwgPSB0aGlzLmJhc2VVUkw7CgogICAgICBpZiAodXJsICE9PSAnJykgewogICAgICAgIC8vIHJlbW92ZSB0cmFpbGluZyBzbGFzaGVzIGlmIHRoZXkgZXhpc3RzCiAgICAgICAgcm9vdFVSTCA9IHJvb3RVUkwucmVwbGFjZSgvXC8kLywgJycpOwogICAgICAgIGJhc2VVUkwgPSBiYXNlVVJMLnJlcGxhY2UoL1wvJC8sICcnKTsKICAgICAgfSBlbHNlIGlmIChiYXNlVVJMWzBdID09PSAnLycgJiYgcm9vdFVSTFswXSA9PT0gJy8nKSB7CiAgICAgICAgLy8gaWYgYmFzZVVSTCBhbmQgcm9vdFVSTCBib3RoIHN0YXJ0IHdpdGggYSBzbGFzaAogICAgICAgIC8vIC4uLiByZW1vdmUgdHJhaWxpbmcgc2xhc2ggZnJvbSBiYXNlVVJMIGlmIGl0IGV4aXN0cwogICAgICAgIGJhc2VVUkwgPSBiYXNlVVJMLnJlcGxhY2UoL1wvJC8sICcnKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGJhc2VVUkwgKyByb290VVJMICsgdXJsOwogICAgfQogICAgLyoqCiAgICAgIENsZWFucyB1cCB0aGUgSGlzdG9yeUxvY2F0aW9uIGV2ZW50IGxpc3RlbmVyLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHdpbGxEZXN0cm95CiAgICAqLwogICAgOwoKICAgIF9wcm90by53aWxsRGVzdHJveSA9IGZ1bmN0aW9uIHdpbGxEZXN0cm95KCkgewogICAgICB0aGlzLl9yZW1vdmVFdmVudExpc3RlbmVyKCk7CiAgICB9OwoKICAgIF9wcm90by5fcmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIF9yZW1vdmVFdmVudExpc3RlbmVyKCkgewogICAgICBpZiAodGhpcy5fcG9wc3RhdGVIYW5kbGVyKSB7CiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgdGhpcy5fcG9wc3RhdGVIYW5kbGVyKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gSGlzdG9yeUxvY2F0aW9uOwogIH0oX3J1bnRpbWUuT2JqZWN0KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IEhpc3RvcnlMb2NhdGlvbjsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vbm9uZV9sb2NhdGlvbiIsIFsiZXhwb3J0cyIsICJlbWJlci1iYWJlbCIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIiwgIkBlbWJlci9kZWJ1ZyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfbWV0YWwsIF9ydW50aW1lLCBfZGVidWcpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgQGVtYmVyL3JvdXRpbmcKICAqLwoKICAvKioKICAgIE5vbmVMb2NhdGlvbiBkb2VzIG5vdCBpbnRlcmFjdCB3aXRoIHRoZSBicm93c2VyLiBJdCBpcyB1c2VmdWwgZm9yCiAgICB0ZXN0aW5nLCBvciB3aGVuIHlvdSBuZWVkIHRvIG1hbmFnZSBzdGF0ZSB3aXRoIHlvdXIgUm91dGVyLCBidXQgdGVtcG9yYXJpbHkKICAgIGRvbid0IHdhbnQgaXQgdG8gbXVjayB3aXRoIHRoZSBVUkwgKGZvciBleGFtcGxlIHdoZW4geW91IGVtYmVkIHlvdXIKICAgIGFwcGxpY2F0aW9uIGluIGEgbGFyZ2VyIHBhZ2UpLgogIAogICAgVXNpbmcgYE5vbmVMb2NhdGlvbmAgY2F1c2VzIEVtYmVyIHRvIG5vdCBzdG9yZSB0aGUgYXBwbGljYXRpb25zIFVSTCBzdGF0ZQogICAgaW4gdGhlIGFjdHVhbCBVUkwuIFRoaXMgaXMgZ2VuZXJhbGx5IHVzZWQgZm9yIHRlc3RpbmcgcHVycG9zZXMsIGFuZCBpcyBvbmUKICAgIG9mIHRoZSBjaGFuZ2VzIG1hZGUgd2hlbiBjYWxsaW5nIGBBcHAuc2V0dXBGb3JUZXN0aW5nKClgLgogIAogICAgQGNsYXNzIE5vbmVMb2NhdGlvbgogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAgIEBwcm90ZWN0ZWQKICAqLwogIHZhciBOb25lTG9jYXRpb24gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0VtYmVyT2JqZWN0KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTm9uZUxvY2F0aW9uLCBfRW1iZXJPYmplY3QpOwoKICAgIGZ1bmN0aW9uIE5vbmVMb2NhdGlvbigpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfRW1iZXJPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpcy5pbXBsZW1lbnRhdGlvbiA9ICdub25lJzsKICAgICAgcmV0dXJuIF90aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBOb25lTG9jYXRpb24ucHJvdG90eXBlOwoKICAgIF9wcm90by5kZXRlY3QgPSBmdW5jdGlvbiBkZXRlY3QoKSB7CiAgICAgIHZhciByb290VVJMID0gdGhpcy5yb290VVJMOwogICAgICAoZmFsc2UgJiYgIShyb290VVJMLmNoYXJBdChyb290VVJMLmxlbmd0aCAtIDEpID09PSAnLycpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgncm9vdFVSTCBtdXN0IGVuZCB3aXRoIGEgdHJhaWxpbmcgZm9yd2FyZCBzbGFzaCBlLmcuICIvYXBwLyInLCByb290VVJMLmNoYXJBdChyb290VVJMLmxlbmd0aCAtIDEpID09PSAnLycpKTsKICAgIH0KICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSBjdXJyZW50IHBhdGggd2l0aG91dCBgcm9vdFVSTGAuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZ2V0VVJMCiAgICAgIEByZXR1cm4ge1N0cmluZ30gcGF0aAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZ2V0VVJMID0gZnVuY3Rpb24gZ2V0VVJMKCkgewogICAgICB2YXIgcGF0aCA9IHRoaXMucGF0aCwKICAgICAgICAgIHJvb3RVUkwgPSB0aGlzLnJvb3RVUkw7IC8vIHJlbW92ZSB0cmFpbGluZyBzbGFzaGVzIGlmIHRoZXkgZXhpc3RzCgogICAgICByb290VVJMID0gcm9vdFVSTC5yZXBsYWNlKC9cLyQvLCAnJyk7IC8vIHJlbW92ZSByb290VVJMIGZyb20gdXJsCgogICAgICByZXR1cm4gcGF0aC5yZXBsYWNlKG5ldyBSZWdFeHAoIl4iICsgcm9vdFVSTCArICIoPz0vfCQpIiksICcnKTsKICAgIH0KICAgIC8qKgogICAgICBTZXQgdGhlIHBhdGggYW5kIHJlbWVtYmVycyB3aGF0IHdhcyBzZXQuIFVzaW5nIHRoaXMgbWV0aG9kCiAgICAgIHRvIGNoYW5nZSB0aGUgcGF0aCB3aWxsIG5vdCBpbnZva2UgdGhlIGB1cGRhdGVVUkxgIGNhbGxiYWNrLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHNldFVSTAogICAgICBAcGFyYW0gcGF0aCB7U3RyaW5nfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uc2V0VVJMID0gZnVuY3Rpb24gc2V0VVJMKHBhdGgpIHsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdwYXRoJywgcGF0aCk7CiAgICB9CiAgICAvKioKICAgICAgUmVnaXN0ZXIgYSBjYWxsYmFjayB0byBiZSBpbnZva2VkIHdoZW4gdGhlIHBhdGggY2hhbmdlcy4gVGhlc2UKICAgICAgY2FsbGJhY2tzIHdpbGwgZXhlY3V0ZSB3aGVuIHRoZSB1c2VyIHByZXNzZXMgdGhlIGJhY2sgb3IgZm9yd2FyZAogICAgICBidXR0b24sIGJ1dCBub3QgYWZ0ZXIgYHNldFVSTGAgaXMgaW52b2tlZC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBvblVwZGF0ZVVSTAogICAgICBAcGFyYW0gY2FsbGJhY2sge0Z1bmN0aW9ufQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ub25VcGRhdGVVUkwgPSBmdW5jdGlvbiBvblVwZGF0ZVVSTChjYWxsYmFjaykgewogICAgICB0aGlzLnVwZGF0ZUNhbGxiYWNrID0gY2FsbGJhY2s7CiAgICB9CiAgICAvKioKICAgICAgU2V0cyB0aGUgcGF0aCBhbmQgY2FsbHMgdGhlIGB1cGRhdGVVUkxgIGNhbGxiYWNrLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGhhbmRsZVVSTAogICAgICBAcGFyYW0gdXJsIHtTdHJpbmd9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5oYW5kbGVVUkwgPSBmdW5jdGlvbiBoYW5kbGVVUkwodXJsKSB7CiAgICAgICgwLCBfbWV0YWwuc2V0KSh0aGlzLCAncGF0aCcsIHVybCk7CiAgICAgIHRoaXMudXBkYXRlQ2FsbGJhY2sodXJsKTsKICAgIH0KICAgIC8qKgogICAgICBHaXZlbiBhIFVSTCwgZm9ybWF0cyBpdCB0byBiZSBwbGFjZWQgaW50byB0aGUgcGFnZSBhcyBwYXJ0CiAgICAgIG9mIGFuIGVsZW1lbnQncyBgaHJlZmAgYXR0cmlidXRlLgogICAgICAgICBUaGlzIGlzIHVzZWQsIGZvciBleGFtcGxlLCB3aGVuIHVzaW5nIHRoZSB7e2FjdGlvbn19IGhlbHBlcgogICAgICB0byBnZW5lcmF0ZSBhIFVSTCBiYXNlZCBvbiBhbiBldmVudC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBmb3JtYXRVUkwKICAgICAgQHBhcmFtIHVybCB7U3RyaW5nfQogICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZm9ybWF0VVJMID0gZnVuY3Rpb24gZm9ybWF0VVJMKHVybCkgewogICAgICB2YXIgcm9vdFVSTCA9IHRoaXMucm9vdFVSTDsKCiAgICAgIGlmICh1cmwgIT09ICcnKSB7CiAgICAgICAgLy8gcmVtb3ZlIHRyYWlsaW5nIHNsYXNoZXMgaWYgdGhleSBleGlzdHMKICAgICAgICByb290VVJMID0gcm9vdFVSTC5yZXBsYWNlKC9cLyQvLCAnJyk7CiAgICAgIH0KCiAgICAgIHJldHVybiByb290VVJMICsgdXJsOwogICAgfTsKCiAgICByZXR1cm4gTm9uZUxvY2F0aW9uOwogIH0oX3J1bnRpbWUuT2JqZWN0KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IE5vbmVMb2NhdGlvbjsKICBOb25lTG9jYXRpb24ucmVvcGVuKHsKICAgIHBhdGg6ICcnLAoKICAgIC8qKgogICAgICBXaWxsIGJlIHByZS1wZW5kZWQgdG8gcGF0aC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQHByb3BlcnR5IHJvb3RVUkwKICAgICAgQGRlZmF1bHQgJy8nCiAgICAqLwogICAgcm9vdFVSTDogJy8nCiAgfSk7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL3V0aWwiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5nZXRQYXRoID0gZ2V0UGF0aDsKICBfZXhwb3J0cy5nZXRRdWVyeSA9IGdldFF1ZXJ5OwogIF9leHBvcnRzLmdldEhhc2ggPSBnZXRIYXNoOwogIF9leHBvcnRzLmdldEZ1bGxQYXRoID0gZ2V0RnVsbFBhdGg7CiAgX2V4cG9ydHMuZ2V0T3JpZ2luID0gZ2V0T3JpZ2luOwogIF9leHBvcnRzLnN1cHBvcnRzSGFzaENoYW5nZSA9IHN1cHBvcnRzSGFzaENoYW5nZTsKICBfZXhwb3J0cy5zdXBwb3J0c0hpc3RvcnkgPSBzdXBwb3J0c0hpc3Rvcnk7CiAgX2V4cG9ydHMucmVwbGFjZVBhdGggPSByZXBsYWNlUGF0aDsKCiAgLyoqCiAgICBAcHJpdmF0ZQogIAogICAgUmV0dXJucyB0aGUgY3VycmVudCBgbG9jYXRpb24ucGF0aG5hbWVgLCBub3JtYWxpemVkIGZvciBJRSBpbmNvbnNpc3RlbmNpZXMuCiAgKi8KICBmdW5jdGlvbiBnZXRQYXRoKGxvY2F0aW9uKSB7CiAgICB2YXIgcGF0aG5hbWUgPSBsb2NhdGlvbi5wYXRobmFtZTsgLy8gVmFyaW91cyB2ZXJzaW9ucyBvZiBJRS9PcGVyYSBkb24ndCBhbHdheXMgcmV0dXJuIGEgbGVhZGluZyBzbGFzaAoKICAgIGlmIChwYXRobmFtZVswXSAhPT0gJy8nKSB7CiAgICAgIHBhdGhuYW1lID0gIi8iICsgcGF0aG5hbWU7CiAgICB9CgogICAgcmV0dXJuIHBhdGhuYW1lOwogIH0KICAvKioKICAgIEBwcml2YXRlCiAgCiAgICBSZXR1cm5zIHRoZSBjdXJyZW50IGBsb2NhdGlvbi5zZWFyY2hgLgogICovCgoKICBmdW5jdGlvbiBnZXRRdWVyeShsb2NhdGlvbikgewogICAgcmV0dXJuIGxvY2F0aW9uLnNlYXJjaDsKICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogIAogICAgUmV0dXJucyB0aGUgaGFzaCBvciBlbXB0eSBzdHJpbmcKICAqLwoKCiAgZnVuY3Rpb24gZ2V0SGFzaChsb2NhdGlvbikgewogICAgaWYgKGxvY2F0aW9uLmhhc2ggIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gbG9jYXRpb24uaGFzaC5zdWJzdHIoMCk7CiAgICB9CgogICAgcmV0dXJuICcnOwogIH0KCiAgZnVuY3Rpb24gZ2V0RnVsbFBhdGgobG9jYXRpb24pIHsKICAgIHJldHVybiBnZXRQYXRoKGxvY2F0aW9uKSArIGdldFF1ZXJ5KGxvY2F0aW9uKSArIGdldEhhc2gobG9jYXRpb24pOwogIH0KCiAgZnVuY3Rpb24gZ2V0T3JpZ2luKGxvY2F0aW9uKSB7CiAgICB2YXIgb3JpZ2luID0gbG9jYXRpb24ub3JpZ2luOyAvLyBPbGRlciBicm93c2VycywgZXNwZWNpYWxseSBJRSwgZG9uJ3QgaGF2ZSBvcmlnaW4KCiAgICBpZiAoIW9yaWdpbikgewogICAgICBvcmlnaW4gPSBsb2NhdGlvbi5wcm90b2NvbCArICIvLyIgKyBsb2NhdGlvbi5ob3N0bmFtZTsKCiAgICAgIGlmIChsb2NhdGlvbi5wb3J0KSB7CiAgICAgICAgb3JpZ2luICs9ICI6IiArIGxvY2F0aW9uLnBvcnQ7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gb3JpZ2luOwogIH0KICAvKgogICAgYGRvY3VtZW50TW9kZWAgb25seSBleGlzdCBpbiBJbnRlcm5ldCBFeHBsb3JlciwgYW5kIGl0J3MgdGVzdGVkIGJlY2F1c2UgSUU4IHJ1bm5pbmcgaW4KICAgIElFNyBjb21wYXRpYmlsaXR5IG1vZGUgY2xhaW1zIHRvIHN1cHBvcnQgYG9uaGFzaGNoYW5nZWAgYnV0IGFjdHVhbGx5IGRvZXMgbm90LgogIAogICAgYGdsb2JhbGAgaXMgYW4gb2JqZWN0IHRoYXQgbWF5IGhhdmUgYW4gYG9uaGFzaGNoYW5nZWAgcHJvcGVydHkuCiAgCiAgICBAcHJpdmF0ZQogICAgQGZ1bmN0aW9uIHN1cHBvcnRzSGFzaENoYW5nZQogICovCgoKICBmdW5jdGlvbiBzdXBwb3J0c0hhc2hDaGFuZ2UoZG9jdW1lbnRNb2RlLCBnbG9iYWwpIHsKICAgIHJldHVybiBnbG9iYWwgJiYgJ29uaGFzaGNoYW5nZScgaW4gZ2xvYmFsICYmIChkb2N1bWVudE1vZGUgPT09IHVuZGVmaW5lZCB8fCBkb2N1bWVudE1vZGUgPiA3KTsKICB9CiAgLyoKICAgIGB1c2VyQWdlbnRgIGlzIGEgdXNlciBhZ2VudCBzdHJpbmcuIFdlIHVzZSB1c2VyIGFnZW50IHRlc3RpbmcgaGVyZSwgYmVjYXVzZQogICAgdGhlIHN0b2NrIEFuZHJvaWQgYnJvd3NlciBpcyBrbm93biB0byBoYXZlIGJ1Z2d5IHZlcnNpb25zIG9mIHRoZSBIaXN0b3J5IEFQSSwKICAgIGluIHNvbWUgQW5kcm9pZCB2ZXJzaW9ucy4KICAKICAgIEBwcml2YXRlCiAgICBAZnVuY3Rpb24gc3VwcG9ydHNIaXN0b3J5CiAgKi8KCgogIGZ1bmN0aW9uIHN1cHBvcnRzSGlzdG9yeSh1c2VyQWdlbnQsIGhpc3RvcnkpIHsKICAgIC8vIEJvb3N0ZWQgZnJvbSBNb2Rlcm5penI6IGh0dHBzOi8vZ2l0aHViLmNvbS9Nb2Rlcm5penIvTW9kZXJuaXpyL2Jsb2IvbWFzdGVyL2ZlYXR1cmUtZGV0ZWN0cy9oaXN0b3J5LmpzCiAgICAvLyBUaGUgc3RvY2sgYnJvd3NlciBvbiBBbmRyb2lkIDIuMiAmIDIuMywgYW5kIDQuMC54IHJldHVybnMgcG9zaXRpdmUgb24gaGlzdG9yeSBzdXBwb3J0CiAgICAvLyBVbmZvcnR1bmF0ZWx5IHN1cHBvcnQgaXMgcmVhbGx5IGJ1Z2d5IGFuZCB0aGVyZSBpcyBubyBjbGVhbiB3YXkgdG8gZGV0ZWN0CiAgICAvLyB0aGVzZSBidWdzLCBzbyB3ZSBmYWxsIGJhY2sgdG8gYSB1c2VyIGFnZW50IHNuaWZmIDooCiAgICAvLyBXZSBvbmx5IHdhbnQgQW5kcm9pZCAyIGFuZCA0LjAsIHN0b2NrIGJyb3dzZXIsIGFuZCBub3QgQ2hyb21lIHdoaWNoIGlkZW50aWZpZXMKICAgIC8vIGl0c2VsZiBhcyAnTW9iaWxlIFNhZmFyaScgYXMgd2VsbCwgbm9yIFdpbmRvd3MgUGhvbmUuCiAgICBpZiAoKHVzZXJBZ2VudC5pbmRleE9mKCdBbmRyb2lkIDIuJykgIT09IC0xIHx8IHVzZXJBZ2VudC5pbmRleE9mKCdBbmRyb2lkIDQuMCcpICE9PSAtMSkgJiYgdXNlckFnZW50LmluZGV4T2YoJ01vYmlsZSBTYWZhcmknKSAhPT0gLTEgJiYgdXNlckFnZW50LmluZGV4T2YoJ0Nocm9tZScpID09PSAtMSAmJiB1c2VyQWdlbnQuaW5kZXhPZignV2luZG93cyBQaG9uZScpID09PSAtMSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgcmV0dXJuIEJvb2xlYW4oaGlzdG9yeSAmJiAncHVzaFN0YXRlJyBpbiBoaXN0b3J5KTsKICB9CiAgLyoqCiAgICBSZXBsYWNlcyB0aGUgY3VycmVudCBsb2NhdGlvbiwgbWFraW5nIHN1cmUgd2UgZXhwbGljaXRseSBpbmNsdWRlIHRoZSBvcmlnaW4KICAgIHRvIHByZXZlbnQgcmVkaXJlY3RpbmcgdG8gYSBkaWZmZXJlbnQgb3JpZ2luLgogIAogICAgQHByaXZhdGUKICAqLwoKCiAgZnVuY3Rpb24gcmVwbGFjZVBhdGgobG9jYXRpb24sIHBhdGgpIHsKICAgIGxvY2F0aW9uLnJlcGxhY2UoZ2V0T3JpZ2luKGxvY2F0aW9uKSArIHBhdGgpOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc2VydmljZXMvcm91dGVyIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci9vYmplY3QvY29tcHV0ZWQiLCAiQGVtYmVyL3NlcnZpY2UiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvdXRpbHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX3J1bnRpbWUsIF9kZWJ1ZywgX2NvbXB1dGVkLCBfc2VydmljZSwgX3V0aWxzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwogIHZhciBmcmVlemVSb3V0ZUluZm87CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICBmcmVlemVSb3V0ZUluZm8gPSBmdW5jdGlvbiBmcmVlemVSb3V0ZUluZm8odHJhbnNpdGlvbikgewogICAgICBpZiAodHJhbnNpdGlvbi5mcm9tICE9PSBudWxsICYmICFPYmplY3QuaXNGcm96ZW4odHJhbnNpdGlvbi5mcm9tKSkgewogICAgICAgIE9iamVjdC5mcmVlemUodHJhbnNpdGlvbi5mcm9tKTsKICAgICAgfQoKICAgICAgaWYgKHRyYW5zaXRpb24udG8gIT09IG51bGwgJiYgIU9iamVjdC5pc0Zyb3plbih0cmFuc2l0aW9uLnRvKSkgewogICAgICAgIE9iamVjdC5mcmVlemUodHJhbnNpdGlvbi50byk7CiAgICAgIH0KICAgIH07CiAgfQoKICBmdW5jdGlvbiBjbGVhblVSTCh1cmwsIHJvb3RVUkwpIHsKICAgIGlmIChyb290VVJMID09PSAnLycpIHsKICAgICAgcmV0dXJuIHVybDsKICAgIH0KCiAgICByZXR1cm4gdXJsLnN1YnN0cihyb290VVJMLmxlbmd0aCwgdXJsLmxlbmd0aCk7CiAgfQogIC8qKgogICAgIFRoZSBSb3V0ZXIgc2VydmljZSBpcyB0aGUgcHVibGljIEFQSSB0aGF0IHByb3ZpZGVzIGFjY2VzcyB0byB0aGUgcm91dGVyLgogIAogICAgIFRoZSBpbW1lZGlhdGUgYmVuZWZpdCBvZiB0aGUgUm91dGVyIHNlcnZpY2UgaXMgdGhhdCB5b3UgY2FuIGluamVjdCBpdCBpbnRvIGNvbXBvbmVudHMsCiAgICAgZ2l2aW5nIHRoZW0gYSBmcmllbmRseSB3YXkgdG8gaW5pdGlhdGUgdHJhbnNpdGlvbnMgYW5kIGFzayBxdWVzdGlvbnMgYWJvdXQgdGhlIGN1cnJlbnQKICAgICBnbG9iYWwgcm91dGVyIHN0YXRlLgogIAogICAgIEluIHRoaXMgZXhhbXBsZSwgdGhlIFJvdXRlciBzZXJ2aWNlIGlzIGluamVjdGVkIGludG8gYSBjb21wb25lbnQgdG8gaW5pdGlhdGUgYSB0cmFuc2l0aW9uCiAgICAgdG8gYSBkZWRpY2F0ZWQgcm91dGU6CiAgICAgYGBgamF2YXNjcmlwdAogICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgaW1wb3J0IHsgaW5qZWN0IGFzIHNlcnZpY2UgfSBmcm9tICdAZW1iZXIvc2VydmljZSc7CiAgCiAgICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICByb3V0ZXI6IHNlcnZpY2UoKSwKICAKICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgbmV4dCgpIHsKICAgICAgICAgICB0aGlzLnJvdXRlci50cmFuc2l0aW9uVG8oJ290aGVyLnJvdXRlJyk7CiAgICAgICAgIH0KICAgICAgIH0KICAgICB9KTsKICAgICBgYGAKICAKICAgICBMaWtlIGFueSBzZXJ2aWNlLCBpdCBjYW4gYWxzbyBiZSBpbmplY3RlZCBpbnRvIGhlbHBlcnMsIHJvdXRlcywgZXRjLgogIAogICAgIEBwdWJsaWMKICAgICBAZXh0ZW5kcyBTZXJ2aWNlCiAgICAgQGNsYXNzIFJvdXRlclNlcnZpY2UKICAgKi8KCgogIHZhciBSb3V0ZXJTZXJ2aWNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9TZXJ2aWNlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUm91dGVyU2VydmljZSwgX1NlcnZpY2UpOwoKICAgIGZ1bmN0aW9uIFJvdXRlclNlcnZpY2UoKSB7CiAgICAgIHJldHVybiBfU2VydmljZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90byA9IFJvdXRlclNlcnZpY2UucHJvdG90eXBlOwoKICAgIF9wcm90by5pbml0ID0gZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIF9TZXJ2aWNlLnByb3RvdHlwZS5pbml0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzLl9yb3V0ZXIub24oJ3JvdXRlV2lsbENoYW5nZScsIGZ1bmN0aW9uICh0cmFuc2l0aW9uKSB7CiAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgIGZyZWV6ZVJvdXRlSW5mbyh0cmFuc2l0aW9uKTsKICAgICAgICB9CgogICAgICAgIF90aGlzLnRyaWdnZXIoJ3JvdXRlV2lsbENoYW5nZScsIHRyYW5zaXRpb24pOwogICAgICB9KTsKCiAgICAgIHRoaXMuX3JvdXRlci5vbigncm91dGVEaWRDaGFuZ2UnLCBmdW5jdGlvbiAodHJhbnNpdGlvbikgewogICAgICAgIGlmIChmYWxzZQogICAgICAgIC8qIERFQlVHICovCiAgICAgICAgKSB7CiAgICAgICAgICBmcmVlemVSb3V0ZUluZm8odHJhbnNpdGlvbik7CiAgICAgICAgfQoKICAgICAgICBfdGhpcy50cmlnZ2VyKCdyb3V0ZURpZENoYW5nZScsIHRyYW5zaXRpb24pOwogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICAgVHJhbnNpdGlvbiB0aGUgYXBwbGljYXRpb24gaW50byBhbm90aGVyIHJvdXRlLiBUaGUgcm91dGUgbWF5CiAgICAgICBiZSBlaXRoZXIgYSBzaW5nbGUgcm91dGUgb3Igcm91dGUgcGF0aDoKICAgICAgICAgIFNlZSBbdHJhbnNpdGlvblRvXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1JvdXRlL21ldGhvZHMvdHJhbnNpdGlvblRvP2FuY2hvcj10cmFuc2l0aW9uVG8pIGZvciBtb3JlIGluZm8uCiAgICAgICAgICBDYWxsaW5nIGB0cmFuc2l0aW9uVG9gIGZyb20gdGhlIFJvdXRlciBzZXJ2aWNlIHdpbGwgY2F1c2UgZGVmYXVsdCBxdWVyeSBwYXJhbWV0ZXIgdmFsdWVzIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBVUkwuCiAgICAgICBUaGlzIGJlaGF2aW9yIGlzIGRpZmZlcmVudCBmcm9tIGNhbGxpbmcgYHRyYW5zaXRpb25Ub2Agb24gYSByb3V0ZSBvciBgdHJhbnNpdGlvblRvUm91dGVgIG9uIGEgY29udHJvbGxlci4KICAgICAgIFNlZSB0aGUgW1JvdXRlciBTZXJ2aWNlIFJGQ10oaHR0cHM6Ly9naXRodWIuY29tL2VtYmVyanMvcmZjcy9ibG9iL21hc3Rlci90ZXh0LzAwOTUtcm91dGVyLXNlcnZpY2UubWQjcXVlcnktcGFyYW1ldGVyLXNlbWFudGljcykgZm9yIG1vcmUgaW5mby4KICAgICAgICAgIEluIHRoZSBmb2xsb3dpbmcgZXhhbXBsZSB3ZSB1c2UgdGhlIFJvdXRlciBzZXJ2aWNlIHRvIG5hdmlnYXRlIHRvIGEgcm91dGUgd2l0aCBhCiAgICAgICBzcGVjaWZpYyBtb2RlbCBmcm9tIGEgQ29tcG9uZW50LgogICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgIGltcG9ydCB7IGluamVjdCBhcyBzZXJ2aWNlIH0gZnJvbSAnQGVtYmVyL3NlcnZpY2UnOwogICAgICAgICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgIHJvdXRlcjogc2VydmljZSgpLAogICAgICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICAgZ29Ub0NvbW1lbnRzKHBvc3QpIHsKICAgICAgICAgICAgIHRoaXMucm91dGVyLnRyYW5zaXRpb25UbygnY29tbWVudHMnLCBwb3N0KTsKICAgICAgICAgICB9CiAgICAgICAgIH0KICAgICAgIH0pOwogICAgICAgYGBgCiAgICAgICAgICBAbWV0aG9kIHRyYW5zaXRpb25UbwogICAgICAgQHBhcmFtIHtTdHJpbmd9IHJvdXRlTmFtZU9yVXJsIHRoZSBuYW1lIG9mIHRoZSByb3V0ZSBvciBhIFVSTAogICAgICAgQHBhcmFtIHsuLi5PYmplY3R9IG1vZGVscyB0aGUgbW9kZWwocykgb3IgaWRlbnRpZmllcihzKSB0byBiZSB1c2VkIHdoaWxlCiAgICAgICAgIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBvcHRpb25hbCBoYXNoIHdpdGggYSBxdWVyeVBhcmFtcyBwcm9wZXJ0eQogICAgICAgICBjb250YWluaW5nIGEgbWFwcGluZyBvZiBxdWVyeSBwYXJhbWV0ZXJzCiAgICAgICBAcmV0dXJuIHtUcmFuc2l0aW9ufSB0aGUgdHJhbnNpdGlvbiBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoaXMKICAgICAgICAgYXR0ZW1wdGVkIHRyYW5zaXRpb24KICAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by50cmFuc2l0aW9uVG8gPSBmdW5jdGlvbiB0cmFuc2l0aW9uVG8oKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgIGlmICgoMCwgX3V0aWxzLnJlc2VtYmxlc1VSTCkoYXJnc1swXSkpIHsKICAgICAgICByZXR1cm4gdGhpcy5fcm91dGVyLl9kb1VSTFRyYW5zaXRpb24oJ3RyYW5zaXRpb25UbycsIGFyZ3NbMF0pOwogICAgICB9CgogICAgICB2YXIgX2V4dHJhY3RSb3V0ZUFyZ3MgPSAoMCwgX3V0aWxzLmV4dHJhY3RSb3V0ZUFyZ3MpKGFyZ3MpLAogICAgICAgICAgcm91dGVOYW1lID0gX2V4dHJhY3RSb3V0ZUFyZ3Mucm91dGVOYW1lLAogICAgICAgICAgbW9kZWxzID0gX2V4dHJhY3RSb3V0ZUFyZ3MubW9kZWxzLAogICAgICAgICAgcXVlcnlQYXJhbXMgPSBfZXh0cmFjdFJvdXRlQXJncy5xdWVyeVBhcmFtczsKCiAgICAgIHZhciB0cmFuc2l0aW9uID0gdGhpcy5fcm91dGVyLl9kb1RyYW5zaXRpb24ocm91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zLCB0cnVlKTsKCiAgICAgIHRyYW5zaXRpb25bJ19rZWVwRGVmYXVsdFF1ZXJ5UGFyYW1WYWx1ZXMnXSA9IHRydWU7CiAgICAgIHJldHVybiB0cmFuc2l0aW9uOwogICAgfQogICAgLyoqCiAgICAgICBUcmFuc2l0aW9uIGludG8gYW5vdGhlciByb3V0ZSB3aGlsZSByZXBsYWNpbmcgdGhlIGN1cnJlbnQgVVJMLCBpZiBwb3NzaWJsZS4KICAgICAgIFRoZSByb3V0ZSBtYXkgYmUgZWl0aGVyIGEgc2luZ2xlIHJvdXRlIG9yIHJvdXRlIHBhdGg6CiAgICAgICAgICBTZWUgW3JlcGxhY2VXaXRoXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1JvdXRlL21ldGhvZHMvcmVwbGFjZVdpdGg/YW5jaG9yPXJlcGxhY2VXaXRoKSBmb3IgbW9yZSBpbmZvLgogICAgICAgICAgQ2FsbGluZyBgcmVwbGFjZVdpdGhgIGZyb20gdGhlIFJvdXRlciBzZXJ2aWNlIHdpbGwgY2F1c2UgZGVmYXVsdCBxdWVyeSBwYXJhbWV0ZXIgdmFsdWVzIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBVUkwuCiAgICAgICBUaGlzIGJlaGF2aW9yIGlzIGRpZmZlcmVudCBmcm9tIGNhbGxpbmcgYHJlcGxhY2VXaXRoYCBvbiBhIHJvdXRlLgogICAgICAgU2VlIHRoZSBbUm91dGVyIFNlcnZpY2UgUkZDXShodHRwczovL2dpdGh1Yi5jb20vZW1iZXJqcy9yZmNzL2Jsb2IvbWFzdGVyL3RleHQvMDA5NS1yb3V0ZXItc2VydmljZS5tZCNxdWVyeS1wYXJhbWV0ZXItc2VtYW50aWNzKSBmb3IgbW9yZSBpbmZvLgogICAgICAgICAgVXNhZ2UgZXhhbXBsZToKICAgICAgICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgICBiZWZvcmVNb2RlbCgpIHsKICAgICAgICAgICBpZiAoIWF1dGhvcml6ZWQoKSl7CiAgICAgICAgICAgICB0aGlzLnJlcGxhY2VXaXRoKCd1bmF1dGhvcml6ZWQnKTsKICAgICAgICAgICB9CiAgICAgICAgIH0KICAgICAgIH0pOwogICAgICAgYGBgCiAgICAgICAgICBAbWV0aG9kIHJlcGxhY2VXaXRoCiAgICAgICBAcGFyYW0ge1N0cmluZ30gcm91dGVOYW1lT3JVcmwgdGhlIG5hbWUgb2YgdGhlIHJvdXRlIG9yIGEgVVJMCiAgICAgICBAcGFyYW0gey4uLk9iamVjdH0gbW9kZWxzIHRoZSBtb2RlbChzKSBvciBpZGVudGlmaWVyKHMpIHRvIGJlIHVzZWQgd2hpbGUKICAgICAgICAgdHJhbnNpdGlvbmluZyB0byB0aGUgcm91dGUuCiAgICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIG9wdGlvbmFsIGhhc2ggd2l0aCBhIHF1ZXJ5UGFyYW1zIHByb3BlcnR5CiAgICAgICAgIGNvbnRhaW5pbmcgYSBtYXBwaW5nIG9mIHF1ZXJ5IHBhcmFtZXRlcnMKICAgICAgIEByZXR1cm4ge1RyYW5zaXRpb259IHRoZSB0cmFuc2l0aW9uIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhpcwogICAgICAgICBhdHRlbXB0ZWQgdHJhbnNpdGlvbgogICAgICAgQHB1YmxpYwogICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlcGxhY2VXaXRoID0gZnVuY3Rpb24gcmVwbGFjZVdpdGgoKQogICAgLyogcm91dGVOYW1lT3JVcmwsIC4uLm1vZGVscywgb3B0aW9ucyAqLwogICAgewogICAgICByZXR1cm4gdGhpcy50cmFuc2l0aW9uVG8uYXBwbHkodGhpcywgYXJndW1lbnRzKS5tZXRob2QoJ3JlcGxhY2UnKTsKICAgIH0KICAgIC8qKgogICAgICBHZW5lcmF0ZSBhIFVSTCBiYXNlZCBvbiB0aGUgc3VwcGxpZWQgcm91dGUgbmFtZSBhbmQgb3B0aW9uYWxseSBhIG1vZGVsLiBUaGUKICAgICAgVVJMIGlzIHJldHVybmVkIGFzIGEgc3RyaW5nIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGFueSBwdXJwb3NlLgogICAgICAgICBJbiB0aGlzIGV4YW1wbGUsIHRoZSBVUkwgZm9yIHRoZSBgYXV0aG9yLmJvb2tzYCByb3V0ZSBmb3IgYSBnaXZlbiBhdXRob3IKICAgICAgaXMgY29waWVkIHRvIHRoZSBjbGlwYm9hcmQuCiAgICAgICAgIGBgYGFwcC9jb21wb25lbnRzL2NvcHktbGluay5qcwogICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICBpbXBvcnQge2luamVjdCBhcyBzZXJ2aWNlfSBmcm9tICdAZW1iZXIvc2VydmljZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICAgIHJvdXRlcjogc2VydmljZSgncm91dGVyJyksCiAgICAgICAgY2xpcGJvYXJkOiBzZXJ2aWNlKCdjbGlwYm9hcmQnKQogICAgICAgICAgIC8vIFByb3ZpZGVkIGluIHRoZSB0ZW1wbGF0ZQogICAgICAgIC8vIHsgaWQ6ICd0b21zdGVyJywgbmFtZTogJ1RvbXN0ZXInIH0KICAgICAgICBhdXRob3I6IG51bGwsCiAgICAgICAgICAgY29weUJvb2tzVVJMKCkgewogICAgICAgICAgaWYgKHRoaXMuYXV0aG9yKSB7CiAgICAgICAgICAgIGNvbnN0IHVybCA9IHRoaXMucm91dGVyLnVybEZvcignYXV0aG9yLmJvb2tzJywgdGhpcy5hdXRob3IpOwogICAgICAgICAgICB0aGlzLmNsaXBib2FyZC5zZXQodXJsKTsKICAgICAgICAgICAgLy8gQ2xpcGJvYXJkIG5vdyBoYXMgL2F1dGhvci90b21zdGVyL2Jvb2tzCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIEp1c3QgbGlrZSB3aXRoIGB0cmFuc2l0aW9uVG9gIGFuZCBgcmVwbGFjZVdpdGhgLCBgdXJsRm9yYCBjYW4gYWxzbyBoYW5kbGUKICAgICAgcXVlcnkgcGFyYW1ldGVycy4KICAgICAgICAgYGBgYXBwL2NvbXBvbmVudHMvY29weS1saW5rLmpzCiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIGltcG9ydCB7aW5qZWN0IGFzIHNlcnZpY2V9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgcm91dGVyOiBzZXJ2aWNlKCdyb3V0ZXInKSwKICAgICAgICBjbGlwYm9hcmQ6IHNlcnZpY2UoJ2NsaXBib2FyZCcpCiAgICAgICAgICAgLy8gUHJvdmlkZWQgaW4gdGhlIHRlbXBsYXRlCiAgICAgICAgLy8geyBpZDogJ3RvbXN0ZXInLCBuYW1lOiAnVG9tc3RlcicgfQogICAgICAgIGF1dGhvcjogbnVsbCwKICAgICAgICAgICBjb3B5T25seUVtYmVyQm9va3NVUkwoKSB7CiAgICAgICAgICBpZiAodGhpcy5hdXRob3IpIHsKICAgICAgICAgICAgY29uc3QgdXJsID0gdGhpcy5yb3V0ZXIudXJsRm9yKCdhdXRob3IuYm9va3MnLCB0aGlzLmF1dGhvciwgewogICAgICAgICAgICAgIHF1ZXJ5UGFyYW1zOiB7IGZpbHRlcjogJ2VtYmVyanMnIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHRoaXMuY2xpcGJvYXJkLnNldCh1cmwpOwogICAgICAgICAgICAvLyBDbGlwYm9hcmQgbm93IGhhcyAvYXV0aG9yL3RvbXN0ZXIvYm9va3M/ZmlsdGVyPWVtYmVyanMKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgIEBtZXRob2QgdXJsRm9yCiAgICAgICBAcGFyYW0ge1N0cmluZ30gcm91dGVOYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZQogICAgICAgQHBhcmFtIHsuLi5PYmplY3R9IG1vZGVscyB0aGUgbW9kZWwocykgb3IgaWRlbnRpZmllcihzKSB0byBiZSB1c2VkIHdoaWxlCiAgICAgICAgIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBvcHRpb25hbCBoYXNoIHdpdGggYSBxdWVyeVBhcmFtcyBwcm9wZXJ0eQogICAgICAgICBjb250YWluaW5nIGEgbWFwcGluZyBvZiBxdWVyeSBwYXJhbWV0ZXJzCiAgICAgICBAcmV0dXJuIHtTdHJpbmd9IHRoZSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBnZW5lcmF0ZWQgVVJMCiAgICAgICBAcHVibGljCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8udXJsRm9yID0gZnVuY3Rpb24gdXJsRm9yKHJvdXRlTmFtZSkgewogICAgICB2YXIgX3RoaXMkX3JvdXRlcjsKCiAgICAgIGZvciAodmFyIF9sZW4yID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuMiA+IDEgPyBfbGVuMiAtIDEgOiAwKSwgX2tleTIgPSAxOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7CiAgICAgICAgYXJnc1tfa2V5MiAtIDFdID0gYXJndW1lbnRzW19rZXkyXTsKICAgICAgfQoKICAgICAgcmV0dXJuIChfdGhpcyRfcm91dGVyID0gdGhpcy5fcm91dGVyKS5nZW5lcmF0ZS5hcHBseShfdGhpcyRfcm91dGVyLCBbcm91dGVOYW1lXS5jb25jYXQoYXJncykpOwogICAgfQogICAgLyoqCiAgICAgICBEZXRlcm1pbmVzIHdoZXRoZXIgYSByb3V0ZSBpcyBhY3RpdmUuCiAgICAgICAgICBAbWV0aG9kIGlzQWN0aXZlCiAgICAgICBAcGFyYW0ge1N0cmluZ30gcm91dGVOYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZQogICAgICAgQHBhcmFtIHsuLi5PYmplY3R9IG1vZGVscyB0aGUgbW9kZWwocykgb3IgaWRlbnRpZmllcihzKSB0byBiZSB1c2VkIHdoaWxlCiAgICAgICAgIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBvcHRpb25hbCBoYXNoIHdpdGggYSBxdWVyeVBhcmFtcyBwcm9wZXJ0eQogICAgICAgICBjb250YWluaW5nIGEgbWFwcGluZyBvZiBxdWVyeSBwYXJhbWV0ZXJzCiAgICAgICBAcmV0dXJuIHtib29sZWFufSB0cnVlIGlmIHRoZSBwcm92aWRlZCByb3V0ZU5hbWUvbW9kZWxzL3F1ZXJ5UGFyYW1zIGFyZSBhY3RpdmUKICAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by5pc0FjdGl2ZSA9IGZ1bmN0aW9uIGlzQWN0aXZlKCkgewogICAgICBmb3IgKHZhciBfbGVuMyA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjMpLCBfa2V5MyA9IDA7IF9rZXkzIDwgX2xlbjM7IF9rZXkzKyspIHsKICAgICAgICBhcmdzW19rZXkzXSA9IGFyZ3VtZW50c1tfa2V5M107CiAgICAgIH0KCiAgICAgIHZhciBfZXh0cmFjdFJvdXRlQXJnczIgPSAoMCwgX3V0aWxzLmV4dHJhY3RSb3V0ZUFyZ3MpKGFyZ3MpLAogICAgICAgICAgcm91dGVOYW1lID0gX2V4dHJhY3RSb3V0ZUFyZ3MyLnJvdXRlTmFtZSwKICAgICAgICAgIG1vZGVscyA9IF9leHRyYWN0Um91dGVBcmdzMi5tb2RlbHMsCiAgICAgICAgICBxdWVyeVBhcmFtcyA9IF9leHRyYWN0Um91dGVBcmdzMi5xdWVyeVBhcmFtczsKCiAgICAgIHZhciByb3V0ZXJNaWNyb2xpYiA9IHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWI7CgogICAgICBpZiAoIXJvdXRlck1pY3JvbGliLmlzQWN0aXZlSW50ZW50KHJvdXRlTmFtZSwgbW9kZWxzKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgdmFyIGhhc1F1ZXJ5UGFyYW1zID0gT2JqZWN0LmtleXMocXVlcnlQYXJhbXMpLmxlbmd0aCA+IDA7CgogICAgICBpZiAoaGFzUXVlcnlQYXJhbXMpIHsKICAgICAgICB0aGlzLl9yb3V0ZXIuX3ByZXBhcmVRdWVyeVBhcmFtcyhyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMsIHRydWUKICAgICAgICAvKiBmcm9tUm91dGVyU2VydmljZSAqLwogICAgICAgICk7CgogICAgICAgIHJldHVybiAoMCwgX3V0aWxzLnNoYWxsb3dFcXVhbCkocXVlcnlQYXJhbXMsIHJvdXRlck1pY3JvbGliLnN0YXRlLnF1ZXJ5UGFyYW1zKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICAvKioKICAgICAgIFRha2VzIGEgc3RyaW5nIFVSTCBhbmQgcmV0dXJucyBhIGBSb3V0ZUluZm9gIGZvciB0aGUgbGVhZm1vc3Qgcm91dGUgcmVwcmVzZW50ZWQKICAgICAgIGJ5IHRoZSBVUkwuIFJldHVybnMgYG51bGxgIGlmIHRoZSBVUkwgaXMgbm90IHJlY29nbml6ZWQuIFRoaXMgbWV0aG9kIGV4cGVjdHMgdG8KICAgICAgIHJlY2VpdmUgdGhlIGFjdHVhbCBVUkwgYXMgc2VlbiBieSB0aGUgYnJvd3NlciBpbmNsdWRpbmcgdGhlIGFwcCdzIGByb290VVJMYC4KICAgICAgICAgIFNlZSBbUm91dGVJbmZvXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1JvdXRlSW5mbykgZm9yIG1vcmUgaW5mby4KICAgICAgICAgIEluIHRoZSBmb2xsb3dpbmcgZXhhbXBsZSBgcmVjb2duaXplYCBpcyB1c2VkIHRvIHZlcmlmeSBpZiBhIHBhdGggYmVsb25ncyB0byBvdXIKICAgICAgIGFwcGxpY2F0aW9uIGJlZm9yZSB0cmFuc2l0aW9uaW5nIHRvIGl0LgogICAgICAgICAgYGBgCiAgICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICAgaW1wb3J0IHsgaW5qZWN0IGFzIHNlcnZpY2UgfSBmcm9tICdAZW1iZXIvc2VydmljZSc7CiAgICAgICAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICAgcm91dGVyOiBzZXJ2aWNlKCksCiAgICAgICAgIHBhdGg6ICcvJywKICAgICAgICAgICAgY2xpY2soKSB7CiAgICAgICAgICAgaWYodGhpcy5yb3V0ZXIucmVjb2duaXplKHRoaXMucGF0aCkpIHsKICAgICAgICAgICAgIHRoaXMucm91dGVyLnRyYW5zaXRpb25Ubyh0aGlzLnBhdGgpOwogICAgICAgICAgIH0KICAgICAgICAgfQogICAgICAgfSk7CiAgICAgICBgYGAKICAgICAgICAgICBAbWV0aG9kIHJlY29nbml6ZQogICAgICAgIEBwYXJhbSB7U3RyaW5nfSB1cmwKICAgICAgICBAcHVibGljCiAgICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlY29nbml6ZSA9IGZ1bmN0aW9uIHJlY29nbml6ZSh1cmwpIHsKICAgICAgKGZhbHNlICYmICEodXJsLmluZGV4T2YodGhpcy5yb290VVJMKSA9PT0gMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgbXVzdCBwYXNzIGEgdXJsIHRoYXQgYmVnaW5zIHdpdGggdGhlIGFwcGxpY2F0aW9uJ3Mgcm9vdFVSTCBcIiIgKyB0aGlzLnJvb3RVUkwgKyAiXCIiLCB1cmwuaW5kZXhPZih0aGlzLnJvb3RVUkwpID09PSAwKSk7CiAgICAgIHZhciBpbnRlcm5hbFVSTCA9IGNsZWFuVVJMKHVybCwgdGhpcy5yb290VVJMKTsKICAgICAgcmV0dXJuIHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWIucmVjb2duaXplKGludGVybmFsVVJMKTsKICAgIH0KICAgIC8qKgogICAgICBUYWtlcyBhIHN0cmluZyBVUkwgYW5kIHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYQogICAgICBgUm91dGVJbmZvV2l0aEF0dHJpYnV0ZXNgIGZvciB0aGUgbGVhZm1vc3Qgcm91dGUgcmVwcmVzZW50ZWQgYnkgdGhlIFVSTC4KICAgICAgVGhlIHByb21pc2UgcmVqZWN0cyBpZiB0aGUgVVJMIGlzIG5vdCByZWNvZ25pemVkIG9yIGFuIHVuaGFuZGxlZCBleGNlcHRpb24KICAgICAgaXMgZW5jb3VudGVyZWQuIFRoaXMgbWV0aG9kIGV4cGVjdHMgdG8gcmVjZWl2ZSB0aGUgYWN0dWFsIFVSTCBhcyBzZWVuIGJ5CiAgICAgIHRoZSBicm93c2VyIGluY2x1ZGluZyB0aGUgYXBwJ3MgYHJvb3RVUkxgLgogICAgICAgICAgIEBtZXRob2QgcmVjb2duaXplQW5kTG9hZAogICAgICAgIEBwYXJhbSB7U3RyaW5nfSB1cmwKICAgICAgICBAcHVibGljCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVjb2duaXplQW5kTG9hZCA9IGZ1bmN0aW9uIHJlY29nbml6ZUFuZExvYWQodXJsKSB7CiAgICAgIChmYWxzZSAmJiAhKHVybC5pbmRleE9mKHRoaXMucm9vdFVSTCkgPT09IDApICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IG11c3QgcGFzcyBhIHVybCB0aGF0IGJlZ2lucyB3aXRoIHRoZSBhcHBsaWNhdGlvbidzIHJvb3RVUkwgXCIiICsgdGhpcy5yb290VVJMICsgIlwiIiwgdXJsLmluZGV4T2YodGhpcy5yb290VVJMKSA9PT0gMCkpOwogICAgICB2YXIgaW50ZXJuYWxVUkwgPSBjbGVhblVSTCh1cmwsIHRoaXMucm9vdFVSTCk7CiAgICAgIHJldHVybiB0aGlzLl9yb3V0ZXIuX3JvdXRlck1pY3JvbGliLnJlY29nbml6ZUFuZExvYWQoaW50ZXJuYWxVUkwpOwogICAgfTsKCiAgICByZXR1cm4gUm91dGVyU2VydmljZTsKICB9KF9zZXJ2aWNlLmRlZmF1bHQpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gUm91dGVyU2VydmljZTsKICBSb3V0ZXJTZXJ2aWNlLnJlb3BlbihfcnVudGltZS5FdmVudGVkLCB7CiAgICAvKioKICAgICAgIE5hbWUgb2YgdGhlIGN1cnJlbnQgcm91dGUuCiAgICAgICAgICBUaGlzIHByb3BlcnR5IHJlcHJlc2VudHMgdGhlIGxvZ2ljYWwgbmFtZSBvZiB0aGUgcm91dGUsCiAgICAgICB3aGljaCBpcyBjb21tYSBzZXBhcmF0ZWQuCiAgICAgICBGb3IgdGhlIGZvbGxvd2luZyByb3V0ZXI6CiAgICAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgICB0aGlzLnJvdXRlKCdhYm91dCcpOwogICAgICAgICB0aGlzLnJvdXRlKCdibG9nJywgZnVuY3Rpb24gKCkgewogICAgICAgICAgIHRoaXMucm91dGUoJ3Bvc3QnLCB7IHBhdGg6ICc6cG9zdF9pZCcgfSk7CiAgICAgICAgIH0pOwogICAgICAgfSk7CiAgICAgICBgYGAKICAgICAgICAgIEl0IHdpbGwgcmV0dXJuOgogICAgICAgICAgKiBgaW5kZXhgIHdoZW4geW91IHZpc2l0IGAvYAogICAgICAgKiBgYWJvdXRgIHdoZW4geW91IHZpc2l0IGAvYWJvdXRgCiAgICAgICAqIGBibG9nLmluZGV4YCB3aGVuIHlvdSB2aXNpdCBgL2Jsb2dgCiAgICAgICAqIGBibG9nLnBvc3RgIHdoZW4geW91IHZpc2l0IGAvYmxvZy9zb21lLXBvc3QtaWRgCiAgICAgICAgICBAcHJvcGVydHkgY3VycmVudFJvdXRlTmFtZQogICAgICAgQHR5cGUgU3RyaW5nCiAgICAgICBAcHVibGljCiAgICAgKi8KICAgIGN1cnJlbnRSb3V0ZU5hbWU6ICgwLCBfY29tcHV0ZWQucmVhZE9ubHkpKCdfcm91dGVyLmN1cnJlbnRSb3V0ZU5hbWUnKSwKCiAgICAvKioKICAgICAgIEN1cnJlbnQgVVJMIGZvciB0aGUgYXBwbGljYXRpb24uCiAgICAgICAgIFRoaXMgcHJvcGVydHkgcmVwcmVzZW50cyB0aGUgVVJMIHBhdGggZm9yIHRoaXMgcm91dGUuCiAgICAgIEZvciB0aGUgZm9sbG93aW5nIHJvdXRlcjoKICAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgIHRoaXMucm91dGUoJ2Fib3V0Jyk7CiAgICAgICAgIHRoaXMucm91dGUoJ2Jsb2cnLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgdGhpcy5yb3V0ZSgncG9zdCcsIHsgcGF0aDogJzpwb3N0X2lkJyB9KTsKICAgICAgICAgfSk7CiAgICAgICB9KTsKICAgICAgIGBgYAogICAgICAgICAgSXQgd2lsbCByZXR1cm46CiAgICAgICAgICAqIGAvYCB3aGVuIHlvdSB2aXNpdCBgL2AKICAgICAgICogYC9hYm91dGAgd2hlbiB5b3UgdmlzaXQgYC9hYm91dGAKICAgICAgICogYC9ibG9nYCB3aGVuIHlvdSB2aXNpdCBgL2Jsb2dgCiAgICAgICAqIGAvYmxvZy9zb21lLXBvc3QtaWRgIHdoZW4geW91IHZpc2l0IGAvYmxvZy9zb21lLXBvc3QtaWRgCiAgICAgICAgICBAcHJvcGVydHkgY3VycmVudFVSTAogICAgICAgQHR5cGUgU3RyaW5nCiAgICAgICBAcHVibGljCiAgICAgKi8KICAgIGN1cnJlbnRVUkw6ICgwLCBfY29tcHV0ZWQucmVhZE9ubHkpKCdfcm91dGVyLmN1cnJlbnRVUkwnKSwKCiAgICAvKioKICAgICAgVGhlIGBsb2NhdGlvbmAgcHJvcGVydHkgcmV0dXJucyB3aGF0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBgbG9jYXRpb25gIEFQSQogICAgICB5b3VyIGFwcGxpY2F0aW9uIGlzIHVzaW5nLCB3aGljaCBkZXRlcm1pbmVzIHdoYXQgdHlwZSBvZiBVUkwgaXMgYmVpbmcgdXNlZC4KICAgICAgICAgU2VlIFtMb2NhdGlvbl0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9Mb2NhdGlvbikgZm9yIG1vcmUgaW5mb3JtYXRpb24uCiAgICAgICAgIFRvIGZvcmNlIGEgcGFydGljdWxhciBgbG9jYXRpb25gIEFQSSBpbXBsZW1lbnRhdGlvbiB0byBiZSB1c2VkIGluIHlvdXIKICAgICAgYXBwbGljYXRpb24geW91IGNhbiBzZXQgYSBsb2NhdGlvbiB0eXBlIG9uIHlvdXIgYGNvbmZpZy9lbnZpcm9ubWVudGAuCiAgICAgIEZvciBleGFtcGxlLCB0byBzZXQgdGhlIGBoaXN0b3J5YCB0eXBlOgogICAgICAgICBgYGBjb25maWcvZW52aXJvbm1lbnQuanMKICAgICAgJ3VzZSBzdHJpY3QnOwogICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGVudmlyb25tZW50KSB7CiAgICAgICAgbGV0IEVOViA9IHsKICAgICAgICAgIG1vZHVsZVByZWZpeDogJ3JvdXRlci1zZXJ2aWNlJywKICAgICAgICAgIGVudmlyb25tZW50LAogICAgICAgICAgcm9vdFVSTDogJy8nLAogICAgICAgICAgbG9jYXRpb25UeXBlOiAnaGlzdG9yeScsCiAgICAgICAgICAuLi4KICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICAgIFRoZSBmb2xsb3dpbmcgbG9jYXRpb24gdHlwZXMgYXJlIGF2YWlsYWJsZSBieSBkZWZhdWx0OgogICAgICBgYXV0b2AsIGBoYXNoYCwgYGhpc3RvcnlgLCBgbm9uZWAuCiAgICAgICAgIFNlZSBbSGFzaExvY2F0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0hhc2hMb2NhdGlvbikuCiAgICAgIFNlZSBbSGlzdG9yeUxvY2F0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0hpc3RvcnlMb2NhdGlvbikuCiAgICAgIFNlZSBbTm9uZUxvY2F0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL05vbmVMb2NhdGlvbikuCiAgICAgIFNlZSBbQXV0b0xvY2F0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0F1dG9Mb2NhdGlvbikuCiAgICAgICAgIEBwcm9wZXJ0eSBsb2NhdGlvbgogICAgICBAZGVmYXVsdCAnaGFzaCcKICAgICAgQHNlZSB7TG9jYXRpb259CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBsb2NhdGlvbjogKDAsIF9jb21wdXRlZC5yZWFkT25seSkoJ19yb3V0ZXIubG9jYXRpb24nKSwKCiAgICAvKioKICAgICAgVGhlIGByb290VVJMYCBwcm9wZXJ0eSByZXByZXNlbnRzIHRoZSBVUkwgb2YgdGhlIHJvb3Qgb2YKICAgICAgdGhlIGFwcGxpY2F0aW9uLCAnLycgYnkgZGVmYXVsdC4KICAgICAgVGhpcyBwcmVmaXggaXMgYXNzdW1lZCBvbiBhbGwgcm91dGVzIGRlZmluZWQgb24gdGhpcyBhcHAuCiAgICAgICAgIElmIHlvdSBjaGFuZ2UgdGhlIGByb290VVJMYCBpbiB5b3VyIGVudmlyb25tZW50IGNvbmZpZ3VyYXRpb24KICAgICAgbGlrZSBzbzoKICAgICAgICAgYGBgY29uZmlnL2Vudmlyb25tZW50LmpzCiAgICAgICd1c2Ugc3RyaWN0JzsKICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihlbnZpcm9ubWVudCkgewogICAgICAgIGxldCBFTlYgPSB7CiAgICAgICAgICBtb2R1bGVQcmVmaXg6ICdyb3V0ZXItc2VydmljZScsCiAgICAgICAgICBlbnZpcm9ubWVudCwKICAgICAgICAgIHJvb3RVUkw6ICcvbXktcm9vdCcsCiAgICAgICAg4oCmCiAgICAgICAgfQogICAgICBdCiAgICAgIGBgYAogICAgICAgICBUaGlzIHByb3BlcnR5IHdpbGwgcmV0dXJuIGAvbXktcm9vdGAuCiAgICAgICAgIEBwcm9wZXJ0eSByb290VVJMCiAgICAgIEBkZWZhdWx0ICcvJwogICAgICBAcHVibGljCiAgICAqLwogICAgcm9vdFVSTDogKDAsIF9jb21wdXRlZC5yZWFkT25seSkoJ19yb3V0ZXIucm9vdFVSTCcpLAoKICAgIC8qKgogICAgICBUaGUgYGN1cnJlbnRSb3V0ZWAgcHJvcGVydHkgY29udGFpbnMgbWV0YWRhdGEgYWJvdXQgdGhlIGN1cnJlbnQgbGVhZiByb3V0ZS4KICAgICAgSXQgcmV0dXJucyBhIGBSb3V0ZUluZm9gIG9iamVjdCB0aGF0IGhhcyBpbmZvcm1hdGlvbiBsaWtlIHRoZSByb3V0ZSBuYW1lLAogICAgICBwYXJhbXMsIHF1ZXJ5IHBhcmFtcyBhbmQgbW9yZS4KICAgICAgICAgU2VlIFtSb3V0ZUluZm9dKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvUm91dGVJbmZvKSBmb3IgbW9yZSBpbmZvLgogICAgICAgICBUaGlzIHByb3BlcnR5IGlzIGd1YXJhbnRlZWQgdG8gY2hhbmdlIHdoZW5ldmVyIGEgcm91dGUgdHJhbnNpdGlvbgogICAgICBoYXBwZW5zIChldmVuIHdoZW4gdGhhdCB0cmFuc2l0aW9uIG9ubHkgY2hhbmdlcyBwYXJhbWV0ZXJzCiAgICAgIGFuZCBkb2Vzbid0IGNoYW5nZSB0aGUgYWN0aXZlIHJvdXRlKS4KICAgICAgICAgVXNhZ2UgZXhhbXBsZToKICAgICAgYGBgYXBwL2NvbXBvbmVudHMvaGVhZGVyLmpzCiAgICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAgICAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICAgICAgcm91dGVyOiBzZXJ2aWNlKCksCiAgICAgICAgICAgICBpc0NoaWxkUm91dGU6IGNvbXB1dGVkLm5vdEVtcHR5KCdyb3V0ZXIuY3VycmVudFJvdXRlLmNoaWxkJykKICAgICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgICBAcHJvcGVydHkgY3VycmVudFJvdXRlCiAgICAgICBAdHlwZSBSb3V0ZUluZm8KICAgICAgIEBwdWJsaWMKICAgICAqLwogICAgY3VycmVudFJvdXRlOiAoMCwgX2NvbXB1dGVkLnJlYWRPbmx5KSgnX3JvdXRlci5jdXJyZW50Um91dGUnKQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zZXJ2aWNlcy9yb3V0aW5nIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci9vYmplY3QvY29tcHV0ZWQiLCAiQGVtYmVyL3BvbHlmaWxscyIsICJAZW1iZXIvc2VydmljZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfY29tcHV0ZWQsIF9wb2x5ZmlsbHMsIF9zZXJ2aWNlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBUaGUgUm91dGluZyBzZXJ2aWNlIGlzIHVzZWQgYnkgTGlua0NvbXBvbmVudCwgYW5kIHByb3ZpZGVzIGZhY2lsaXRpZXMgZm9yCiAgICB0aGUgY29tcG9uZW50L3ZpZXcgbGF5ZXIgdG8gaW50ZXJhY3Qgd2l0aCB0aGUgcm91dGVyLgogIAogICAgVGhpcyBpcyBhIHByaXZhdGUgc2VydmljZSBmb3IgaW50ZXJuYWwgdXNhZ2Ugb25seS4gRm9yIHB1YmxpYyB1c2FnZSwKICAgIHJlZmVyIHRvIHRoZSBgUm91dGVyYCBzZXJ2aWNlLgogIAogICAgQHByaXZhdGUKICAgIEBjbGFzcyBSb3V0aW5nU2VydmljZQogICovCiAgdmFyIFJvdXRpbmdTZXJ2aWNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9TZXJ2aWNlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUm91dGluZ1NlcnZpY2UsIF9TZXJ2aWNlKTsKCiAgICBmdW5jdGlvbiBSb3V0aW5nU2VydmljZSgpIHsKICAgICAgcmV0dXJuIF9TZXJ2aWNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gUm91dGluZ1NlcnZpY2UucHJvdG90eXBlOwoKICAgIF9wcm90by5oYXNSb3V0ZSA9IGZ1bmN0aW9uIGhhc1JvdXRlKHJvdXRlTmFtZSkgewogICAgICByZXR1cm4gdGhpcy5yb3V0ZXIuaGFzUm91dGUocm91dGVOYW1lKTsKICAgIH07CgogICAgX3Byb3RvLnRyYW5zaXRpb25UbyA9IGZ1bmN0aW9uIHRyYW5zaXRpb25Ubyhyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMsIHNob3VsZFJlcGxhY2UpIHsKICAgICAgdmFyIHRyYW5zaXRpb24gPSB0aGlzLnJvdXRlci5fZG9UcmFuc2l0aW9uKHJvdXRlTmFtZSwgbW9kZWxzLCBxdWVyeVBhcmFtcyk7CgogICAgICBpZiAoc2hvdWxkUmVwbGFjZSkgewogICAgICAgIHRyYW5zaXRpb24ubWV0aG9kKCdyZXBsYWNlJyk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0cmFuc2l0aW9uOwogICAgfTsKCiAgICBfcHJvdG8ubm9ybWFsaXplUXVlcnlQYXJhbXMgPSBmdW5jdGlvbiBub3JtYWxpemVRdWVyeVBhcmFtcyhyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMpIHsKICAgICAgdGhpcy5yb3V0ZXIuX3ByZXBhcmVRdWVyeVBhcmFtcyhyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMpOwogICAgfTsKCiAgICBfcHJvdG8uZ2VuZXJhdGVVUkwgPSBmdW5jdGlvbiBnZW5lcmF0ZVVSTChyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMpIHsKICAgICAgdmFyIHJvdXRlciA9IHRoaXMucm91dGVyOyAvLyByZXR1cm4gZWFybHkgd2hlbiB0aGUgcm91dGVyIG1pY3JvbGliIGlzIG5vdCBwcmVzZW50LCB3aGljaCBpcyB0aGUgY2FzZSBmb3Ige3tsaW5rLXRvfX0gaW4gaW50ZWdyYXRpb24gdGVzdHMKCiAgICAgIGlmICghcm91dGVyLl9yb3V0ZXJNaWNyb2xpYikgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIHZpc2libGVRdWVyeVBhcmFtcyA9IHt9OwoKICAgICAgaWYgKHF1ZXJ5UGFyYW1zKSB7CiAgICAgICAgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh2aXNpYmxlUXVlcnlQYXJhbXMsIHF1ZXJ5UGFyYW1zKTsKICAgICAgICB0aGlzLm5vcm1hbGl6ZVF1ZXJ5UGFyYW1zKHJvdXRlTmFtZSwgbW9kZWxzLCB2aXNpYmxlUXVlcnlQYXJhbXMpOwogICAgICB9CgogICAgICByZXR1cm4gcm91dGVyLmdlbmVyYXRlLmFwcGx5KHJvdXRlciwgW3JvdXRlTmFtZV0uY29uY2F0KG1vZGVscywgW3sKICAgICAgICBxdWVyeVBhcmFtczogdmlzaWJsZVF1ZXJ5UGFyYW1zCiAgICAgIH1dKSk7CiAgICB9OwoKICAgIF9wcm90by5pc0FjdGl2ZUZvclJvdXRlID0gZnVuY3Rpb24gaXNBY3RpdmVGb3JSb3V0ZShjb250ZXh0cywgcXVlcnlQYXJhbXMsIHJvdXRlTmFtZSwgcm91dGVyU3RhdGUsIGlzQ3VycmVudFdoZW5TcGVjaWZpZWQpIHsKICAgICAgdmFyIGhhbmRsZXJzID0gdGhpcy5yb3V0ZXIuX3JvdXRlck1pY3JvbGliLnJlY29nbml6ZXIuaGFuZGxlcnNGb3Iocm91dGVOYW1lKTsKCiAgICAgIHZhciBsZWFmTmFtZSA9IGhhbmRsZXJzW2hhbmRsZXJzLmxlbmd0aCAtIDFdLmhhbmRsZXI7CiAgICAgIHZhciBtYXhpbXVtQ29udGV4dHMgPSBudW1iZXJPZkNvbnRleHRzQWNjZXB0ZWRCeUhhbmRsZXIocm91dGVOYW1lLCBoYW5kbGVycyk7IC8vIE5PVEU6IGFueSB1Z2xpbmVzcyBpbiB0aGUgY2FsY3VsYXRpb24gb2YgYWN0aXZlbmVzcyBpcyBsYXJnZWx5CiAgICAgIC8vIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHdlIHN1cHBvcnQgYXV0b21hdGljIG5vcm1hbGl6aW5nIG9mCiAgICAgIC8vIGByZXNvdXJjZWAgLT4gYHJlc291cmNlLmluZGV4YCwgZXZlbiB0aG91Z2ggdGhlcmUgbWlnaHQgYmUKICAgICAgLy8gZHluYW1pYyBzZWdtZW50cyAvIHF1ZXJ5IHBhcmFtcyBkZWZpbmVkIG9uIGByZXNvdXJjZS5pbmRleGAKICAgICAgLy8gd2hpY2ggY29tcGxpY2F0ZXMgKGFuZCBtYWtlcyBzb21ld2hhdCBhbWJpZ3VvdXMpIHRoZSBjYWxjdWxhdGlvbgogICAgICAvLyBvZiBhY3RpdmVuZXNzIGZvciBsaW5rcyB0aGF0IGxpbmsgdG8gYHJlc291cmNlYCBpbnN0ZWFkIG9mCiAgICAgIC8vIGRpcmVjdGx5IHRvIGByZXNvdXJjZS5pbmRleGAuCiAgICAgIC8vIGlmIHdlIGRvbid0IGhhdmUgZW5vdWdoIGNvbnRleHRzIHJldmVydCBiYWNrIHRvIGZ1bGwgcm91dGUgbmFtZQogICAgICAvLyB0aGlzIGlzIGJlY2F1c2UgdGhlIGxlYWYgcm91dGUgd2lsbCB1c2Ugb25lIG9mIHRoZSBjb250ZXh0cwoKICAgICAgaWYgKGNvbnRleHRzLmxlbmd0aCA+IG1heGltdW1Db250ZXh0cykgewogICAgICAgIHJvdXRlTmFtZSA9IGxlYWZOYW1lOwogICAgICB9CgogICAgICByZXR1cm4gcm91dGVyU3RhdGUuaXNBY3RpdmVJbnRlbnQocm91dGVOYW1lLCBjb250ZXh0cywgcXVlcnlQYXJhbXMsICFpc0N1cnJlbnRXaGVuU3BlY2lmaWVkKTsKICAgIH07CgogICAgcmV0dXJuIFJvdXRpbmdTZXJ2aWNlOwogIH0oX3NlcnZpY2UuZGVmYXVsdCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBSb3V0aW5nU2VydmljZTsKICBSb3V0aW5nU2VydmljZS5yZW9wZW4oewogICAgdGFyZ2V0U3RhdGU6ICgwLCBfY29tcHV0ZWQucmVhZE9ubHkpKCdyb3V0ZXIudGFyZ2V0U3RhdGUnKSwKICAgIGN1cnJlbnRTdGF0ZTogKDAsIF9jb21wdXRlZC5yZWFkT25seSkoJ3JvdXRlci5jdXJyZW50U3RhdGUnKSwKICAgIGN1cnJlbnRSb3V0ZU5hbWU6ICgwLCBfY29tcHV0ZWQucmVhZE9ubHkpKCdyb3V0ZXIuY3VycmVudFJvdXRlTmFtZScpLAogICAgY3VycmVudFBhdGg6ICgwLCBfY29tcHV0ZWQucmVhZE9ubHkpKCdyb3V0ZXIuY3VycmVudFBhdGgnKQogIH0pOwoKICBmdW5jdGlvbiBudW1iZXJPZkNvbnRleHRzQWNjZXB0ZWRCeUhhbmRsZXIoaGFuZGxlck5hbWUsIGhhbmRsZXJJbmZvcykgewogICAgdmFyIHJlcSA9IDA7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYW5kbGVySW5mb3MubGVuZ3RoOyBpKyspIHsKICAgICAgcmVxICs9IGhhbmRsZXJJbmZvc1tpXS5uYW1lcy5sZW5ndGg7CgogICAgICBpZiAoaGFuZGxlckluZm9zW2ldLmhhbmRsZXIgPT09IGhhbmRsZXJOYW1lKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcmVxOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL2NhY2hlIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgICBBIHR3by10aWVyZWQgY2FjaGUgd2l0aCBzdXBwb3J0IGZvciBmYWxsYmFjayB2YWx1ZXMgd2hlbiBkb2luZyBsb29rdXBzLgogICAgVXNlcyAiYnVja2V0cyIgYW5kIHRoZW4gImtleXMiIHRvIGNhY2hlIHZhbHVlcy4KICAKICAgIEBwcml2YXRlCiAgICBAY2xhc3MgQnVja2V0Q2FjaGUKICAqLwogIHZhciBCdWNrZXRDYWNoZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEJ1Y2tldENhY2hlKCkgewogICAgICB0aGlzLmNhY2hlID0gbmV3IE1hcCgpOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBCdWNrZXRDYWNoZS5wcm90b3R5cGU7CgogICAgX3Byb3RvLmhhcyA9IGZ1bmN0aW9uIGhhcyhidWNrZXRLZXkpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuaGFzKGJ1Y2tldEtleSk7CiAgICB9OwoKICAgIF9wcm90by5zdGFzaCA9IGZ1bmN0aW9uIHN0YXNoKGJ1Y2tldEtleSwga2V5LCB2YWx1ZSkgewogICAgICB2YXIgYnVja2V0ID0gdGhpcy5jYWNoZS5nZXQoYnVja2V0S2V5KTsKCiAgICAgIGlmIChidWNrZXQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGJ1Y2tldCA9IG5ldyBNYXAoKTsKICAgICAgICB0aGlzLmNhY2hlLnNldChidWNrZXRLZXksIGJ1Y2tldCk7CiAgICAgIH0KCiAgICAgIGJ1Y2tldC5zZXQoa2V5LCB2YWx1ZSk7CiAgICB9OwoKICAgIF9wcm90by5sb29rdXAgPSBmdW5jdGlvbiBsb29rdXAoYnVja2V0S2V5LCBwcm9wLCBkZWZhdWx0VmFsdWUpIHsKICAgICAgaWYgKCF0aGlzLmhhcyhidWNrZXRLZXkpKSB7CiAgICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKICAgICAgfQoKICAgICAgdmFyIGJ1Y2tldCA9IHRoaXMuY2FjaGUuZ2V0KGJ1Y2tldEtleSk7CgogICAgICBpZiAoYnVja2V0Lmhhcyhwcm9wKSkgewogICAgICAgIHJldHVybiBidWNrZXQuZ2V0KHByb3ApOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEJ1Y2tldENhY2hlOwogIH0oKTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IEJ1Y2tldENhY2hlOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vY29udHJvbGxlcl9mb3IiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gY29udHJvbGxlckZvcjsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgRmluZHMgYSBjb250cm9sbGVyIGluc3RhbmNlLgogIAogICAgQGZvciBFbWJlcgogICAgQG1ldGhvZCBjb250cm9sbGVyRm9yCiAgICBAcHJpdmF0ZQogICovCiAgZnVuY3Rpb24gY29udHJvbGxlckZvcihjb250YWluZXIsIGNvbnRyb2xsZXJOYW1lLCBsb29rdXBPcHRpb25zKSB7CiAgICByZXR1cm4gY29udGFpbmVyLmxvb2t1cCgiY29udHJvbGxlcjoiICsgY29udHJvbGxlck5hbWUsIGxvb2t1cE9wdGlvbnMpOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL2RzbCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL3BvbHlmaWxscyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9kZWJ1ZywgX3BvbHlmaWxscykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKICB2YXIgdXVpZCA9IDA7CgogIGZ1bmN0aW9uIGlzQ2FsbGJhY2sodmFsdWUpIHsKICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbic7CiAgfQoKICBmdW5jdGlvbiBpc09wdGlvbnModmFsdWUpIHsKICAgIHJldHVybiB2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnOwogIH0KCiAgdmFyIERTTEltcGwgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBEU0xJbXBsKG5hbWUsIG9wdGlvbnMpIHsKICAgICAgaWYgKG5hbWUgPT09IHZvaWQgMCkgewogICAgICAgIG5hbWUgPSBudWxsOwogICAgICB9CgogICAgICB0aGlzLmV4cGxpY2l0SW5kZXggPSBmYWxzZTsKICAgICAgdGhpcy5wYXJlbnQgPSBuYW1lOwogICAgICB0aGlzLmVuYWJsZUxvYWRpbmdTdWJzdGF0ZXMgPSBCb29sZWFuKG9wdGlvbnMgJiYgb3B0aW9ucy5lbmFibGVMb2FkaW5nU3Vic3RhdGVzKTsKICAgICAgdGhpcy5tYXRjaGVzID0gW107CiAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7CiAgICB9CgogICAgdmFyIF9wcm90byA9IERTTEltcGwucHJvdG90eXBlOwoKICAgIF9wcm90by5yb3V0ZSA9IGZ1bmN0aW9uIHJvdXRlKG5hbWUsIF9vcHRpb25zLCBfY2FsbGJhY2spIHsKICAgICAgdmFyIG9wdGlvbnM7CiAgICAgIHZhciBjYWxsYmFjayA9IG51bGw7CiAgICAgIHZhciBkdW1teUVycm9yUm91dGUgPSAiL191bnVzZWRfZHVtbXlfZXJyb3JfcGF0aF9yb3V0ZV8iICsgbmFtZSArICIvOmVycm9yIjsKCiAgICAgIGlmIChpc0NhbGxiYWNrKF9vcHRpb25zKSkgewogICAgICAgIChmYWxzZSAmJiAhKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnVW5leHBlY3RlZCBhcmd1bWVudHMnLCBhcmd1bWVudHMubGVuZ3RoID09PSAyKSk7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICAgIGNhbGxiYWNrID0gX29wdGlvbnM7CiAgICAgIH0gZWxzZSBpZiAoaXNDYWxsYmFjayhfY2FsbGJhY2spKSB7CiAgICAgICAgKGZhbHNlICYmICEoYXJndW1lbnRzLmxlbmd0aCA9PT0gMykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdVbmV4cGVjdGVkIGFyZ3VtZW50cycsIGFyZ3VtZW50cy5sZW5ndGggPT09IDMpKTsKICAgICAgICAoZmFsc2UgJiYgIShpc09wdGlvbnMoX29wdGlvbnMpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1VuZXhwZWN0ZWQgYXJndW1lbnRzJywgaXNPcHRpb25zKF9vcHRpb25zKSkpOwogICAgICAgIG9wdGlvbnMgPSBfb3B0aW9uczsKICAgICAgICBjYWxsYmFjayA9IF9jYWxsYmFjazsKICAgICAgfSBlbHNlIHsKICAgICAgICBvcHRpb25zID0gX29wdGlvbnMgfHwge307CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKGZ1bmN0aW9uICgpIHsKICAgICAgICBpZiAob3B0aW9ucy5vdmVycmlkZU5hbWVBc3NlcnRpb24gPT09IHRydWUpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIFsnYmFzaWMnLCAnYXBwbGljYXRpb24nXS5pbmRleE9mKG5hbWUpID09PSAtMTsKICAgICAgfSgpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIiciICsgbmFtZSArICInIGNhbm5vdCBiZSB1c2VkIGFzIGEgcm91dGUgbmFtZS4iLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgaWYgKG9wdGlvbnMub3ZlcnJpZGVOYW1lQXNzZXJ0aW9uID09PSB0cnVlKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBbJ2Jhc2ljJywgJ2FwcGxpY2F0aW9uJ10uaW5kZXhPZihuYW1lKSA9PT0gLTE7CiAgICAgIH0oKSkpOwogICAgICAoZmFsc2UgJiYgIShuYW1lLmluZGV4T2YoJzonKSA9PT0gLTEpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiJyIgKyBuYW1lICsgIicgaXMgbm90IGEgdmFsaWQgcm91dGUgbmFtZS4gSXQgY2Fubm90IGNvbnRhaW4gYSAnOicuIFlvdSBtYXkgd2FudCB0byB1c2UgdGhlICdwYXRoJyBvcHRpb24gaW5zdGVhZC4iLCBuYW1lLmluZGV4T2YoJzonKSA9PT0gLTEpKTsKCiAgICAgIGlmICh0aGlzLmVuYWJsZUxvYWRpbmdTdWJzdGF0ZXMpIHsKICAgICAgICBjcmVhdGVSb3V0ZSh0aGlzLCBuYW1lICsgIl9sb2FkaW5nIiwgewogICAgICAgICAgcmVzZXROYW1lc3BhY2U6IG9wdGlvbnMucmVzZXROYW1lc3BhY2UKICAgICAgICB9KTsKICAgICAgICBjcmVhdGVSb3V0ZSh0aGlzLCBuYW1lICsgIl9lcnJvciIsIHsKICAgICAgICAgIHJlc2V0TmFtZXNwYWNlOiBvcHRpb25zLnJlc2V0TmFtZXNwYWNlLAogICAgICAgICAgcGF0aDogZHVtbXlFcnJvclJvdXRlCiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIGlmIChjYWxsYmFjaykgewogICAgICAgIHZhciBmdWxsTmFtZSA9IGdldEZ1bGxOYW1lKHRoaXMsIG5hbWUsIG9wdGlvbnMucmVzZXROYW1lc3BhY2UpOwogICAgICAgIHZhciBkc2wgPSBuZXcgRFNMSW1wbChmdWxsTmFtZSwgdGhpcy5vcHRpb25zKTsKICAgICAgICBjcmVhdGVSb3V0ZShkc2wsICdsb2FkaW5nJyk7CiAgICAgICAgY3JlYXRlUm91dGUoZHNsLCAnZXJyb3InLCB7CiAgICAgICAgICBwYXRoOiBkdW1teUVycm9yUm91dGUKICAgICAgICB9KTsKICAgICAgICBjYWxsYmFjay5jYWxsKGRzbCk7CiAgICAgICAgY3JlYXRlUm91dGUodGhpcywgbmFtZSwgb3B0aW9ucywgZHNsLmdlbmVyYXRlKCkpOwogICAgICB9IGVsc2UgewogICAgICAgIGNyZWF0ZVJvdXRlKHRoaXMsIG5hbWUsIG9wdGlvbnMpOwogICAgICB9CiAgICB9CiAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWR1cGUtY2xhc3MtbWVtYmVycyAqLwogICAgOwoKICAgIF9wcm90by5wdXNoID0gZnVuY3Rpb24gcHVzaCh1cmwsIG5hbWUsIGNhbGxiYWNrLCBzZXJpYWxpemUpIHsKICAgICAgdmFyIHBhcnRzID0gbmFtZS5zcGxpdCgnLicpOwoKICAgICAgaWYgKHRoaXMub3B0aW9ucy5lbmdpbmVJbmZvKSB7CiAgICAgICAgdmFyIGxvY2FsRnVsbE5hbWUgPSBuYW1lLnNsaWNlKHRoaXMub3B0aW9ucy5lbmdpbmVJbmZvLmZ1bGxOYW1lLmxlbmd0aCArIDEpOwogICAgICAgIHZhciByb3V0ZUluZm8gPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHsKICAgICAgICAgIGxvY2FsRnVsbE5hbWU6IGxvY2FsRnVsbE5hbWUKICAgICAgICB9LCB0aGlzLm9wdGlvbnMuZW5naW5lSW5mbyk7CgogICAgICAgIGlmIChzZXJpYWxpemUpIHsKICAgICAgICAgIHJvdXRlSW5mby5zZXJpYWxpemVNZXRob2QgPSBzZXJpYWxpemU7CiAgICAgICAgfQoKICAgICAgICB0aGlzLm9wdGlvbnMuYWRkUm91dGVGb3JFbmdpbmUobmFtZSwgcm91dGVJbmZvKTsKICAgICAgfSBlbHNlIGlmIChzZXJpYWxpemUpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkRlZmluaW5nIGEgcm91dGUgc2VyaWFsaXplciBvbiByb3V0ZSAnIiArIG5hbWUgKyAiJyBvdXRzaWRlIGFuIEVuZ2luZSBpcyBub3QgYWxsb3dlZC4iKTsKICAgICAgfQoKICAgICAgaWYgKHVybCA9PT0gJycgfHwgdXJsID09PSAnLycgfHwgcGFydHNbcGFydHMubGVuZ3RoIC0gMV0gPT09ICdpbmRleCcpIHsKICAgICAgICB0aGlzLmV4cGxpY2l0SW5kZXggPSB0cnVlOwogICAgICB9CgogICAgICB0aGlzLm1hdGNoZXMucHVzaCh1cmwsIG5hbWUsIGNhbGxiYWNrKTsKICAgIH07CgogICAgX3Byb3RvLmdlbmVyYXRlID0gZnVuY3Rpb24gZ2VuZXJhdGUoKSB7CiAgICAgIHZhciBkc2xNYXRjaGVzID0gdGhpcy5tYXRjaGVzOwoKICAgICAgaWYgKCF0aGlzLmV4cGxpY2l0SW5kZXgpIHsKICAgICAgICB0aGlzLnJvdXRlKCdpbmRleCcsIHsKICAgICAgICAgIHBhdGg6ICcvJwogICAgICAgIH0pOwogICAgICB9CgogICAgICByZXR1cm4gZnVuY3Rpb24gKG1hdGNoKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkc2xNYXRjaGVzLmxlbmd0aDsgaSArPSAzKSB7CiAgICAgICAgICBtYXRjaChkc2xNYXRjaGVzW2ldKS50byhkc2xNYXRjaGVzW2kgKyAxXSwgZHNsTWF0Y2hlc1tpICsgMl0pOwogICAgICAgIH0KICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvLm1vdW50ID0gZnVuY3Rpb24gbW91bnQoX25hbWUsIG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgfQoKICAgICAgdmFyIGVuZ2luZVJvdXRlTWFwID0gdGhpcy5vcHRpb25zLnJlc29sdmVSb3V0ZU1hcChfbmFtZSk7CiAgICAgIHZhciBuYW1lID0gX25hbWU7CgogICAgICBpZiAob3B0aW9ucy5hcykgewogICAgICAgIG5hbWUgPSBvcHRpb25zLmFzOwogICAgICB9CgogICAgICB2YXIgZnVsbE5hbWUgPSBnZXRGdWxsTmFtZSh0aGlzLCBuYW1lLCBvcHRpb25zLnJlc2V0TmFtZXNwYWNlKTsKICAgICAgdmFyIGVuZ2luZUluZm8gPSB7CiAgICAgICAgbmFtZTogX25hbWUsCiAgICAgICAgaW5zdGFuY2VJZDogdXVpZCsrLAogICAgICAgIG1vdW50UG9pbnQ6IGZ1bGxOYW1lLAogICAgICAgIGZ1bGxOYW1lOiBmdWxsTmFtZQogICAgICB9OwogICAgICB2YXIgcGF0aCA9IG9wdGlvbnMucGF0aDsKCiAgICAgIGlmICh0eXBlb2YgcGF0aCAhPT0gJ3N0cmluZycpIHsKICAgICAgICBwYXRoID0gIi8iICsgbmFtZTsKICAgICAgfQoKICAgICAgdmFyIGNhbGxiYWNrOwogICAgICB2YXIgZHVtbXlFcnJvclJvdXRlID0gIi9fdW51c2VkX2R1bW15X2Vycm9yX3BhdGhfcm91dGVfIiArIG5hbWUgKyAiLzplcnJvciI7CgogICAgICBpZiAoZW5naW5lUm91dGVNYXApIHsKICAgICAgICB2YXIgc2hvdWxkUmVzZXRFbmdpbmVJbmZvID0gZmFsc2U7CiAgICAgICAgdmFyIG9sZEVuZ2luZUluZm8gPSB0aGlzLm9wdGlvbnMuZW5naW5lSW5mbzsKCiAgICAgICAgaWYgKG9sZEVuZ2luZUluZm8pIHsKICAgICAgICAgIHNob3VsZFJlc2V0RW5naW5lSW5mbyA9IHRydWU7CiAgICAgICAgICB0aGlzLm9wdGlvbnMuZW5naW5lSW5mbyA9IGVuZ2luZUluZm87CiAgICAgICAgfQoKICAgICAgICB2YXIgb3B0aW9uc0ZvckNoaWxkID0gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7CiAgICAgICAgICBlbmdpbmVJbmZvOiBlbmdpbmVJbmZvCiAgICAgICAgfSwgdGhpcy5vcHRpb25zKTsKICAgICAgICB2YXIgY2hpbGREU0wgPSBuZXcgRFNMSW1wbChmdWxsTmFtZSwgb3B0aW9uc0ZvckNoaWxkKTsKICAgICAgICBjcmVhdGVSb3V0ZShjaGlsZERTTCwgJ2xvYWRpbmcnKTsKICAgICAgICBjcmVhdGVSb3V0ZShjaGlsZERTTCwgJ2Vycm9yJywgewogICAgICAgICAgcGF0aDogZHVtbXlFcnJvclJvdXRlCiAgICAgICAgfSk7CiAgICAgICAgZW5naW5lUm91dGVNYXAuY2xhc3MuY2FsbChjaGlsZERTTCk7CiAgICAgICAgY2FsbGJhY2sgPSBjaGlsZERTTC5nZW5lcmF0ZSgpOwoKICAgICAgICBpZiAoc2hvdWxkUmVzZXRFbmdpbmVJbmZvKSB7CiAgICAgICAgICB0aGlzLm9wdGlvbnMuZW5naW5lSW5mbyA9IG9sZEVuZ2luZUluZm87CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgbG9jYWxGdWxsTmFtZSA9ICdhcHBsaWNhdGlvbic7CiAgICAgIHZhciByb3V0ZUluZm8gPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHsKICAgICAgICBsb2NhbEZ1bGxOYW1lOiBsb2NhbEZ1bGxOYW1lCiAgICAgIH0sIGVuZ2luZUluZm8pOwoKICAgICAgaWYgKHRoaXMuZW5hYmxlTG9hZGluZ1N1YnN0YXRlcykgewogICAgICAgIC8vIFRoZXNlIHZhbHVlcyBhcmUgaW1wb3J0YW50IHRvIHJlZ2lzdGVyIHRoZSBsb2FkaW5nIHJvdXRlcyB1bmRlciB0aGVpcgogICAgICAgIC8vIHByb3BlciBuYW1lcyBmb3IgdGhlIFJvdXRlciBhbmQgd2l0aGluIHRoZSBFbmdpbmUncyByZWdpc3RyeS4KICAgICAgICB2YXIgc3Vic3RhdGVOYW1lID0gbmFtZSArICJfbG9hZGluZyI7CiAgICAgICAgdmFyIF9sb2NhbEZ1bGxOYW1lID0gImFwcGxpY2F0aW9uX2xvYWRpbmciOwoKICAgICAgICB2YXIgX3JvdXRlSW5mbyA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoewogICAgICAgICAgbG9jYWxGdWxsTmFtZTogX2xvY2FsRnVsbE5hbWUKICAgICAgICB9LCBlbmdpbmVJbmZvKTsKCiAgICAgICAgY3JlYXRlUm91dGUodGhpcywgc3Vic3RhdGVOYW1lLCB7CiAgICAgICAgICByZXNldE5hbWVzcGFjZTogb3B0aW9ucy5yZXNldE5hbWVzcGFjZQogICAgICAgIH0pOwogICAgICAgIHRoaXMub3B0aW9ucy5hZGRSb3V0ZUZvckVuZ2luZShzdWJzdGF0ZU5hbWUsIF9yb3V0ZUluZm8pOwogICAgICAgIHN1YnN0YXRlTmFtZSA9IG5hbWUgKyAiX2Vycm9yIjsKICAgICAgICBfbG9jYWxGdWxsTmFtZSA9ICJhcHBsaWNhdGlvbl9lcnJvciI7CiAgICAgICAgX3JvdXRlSW5mbyA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoewogICAgICAgICAgbG9jYWxGdWxsTmFtZTogX2xvY2FsRnVsbE5hbWUKICAgICAgICB9LCBlbmdpbmVJbmZvKTsKICAgICAgICBjcmVhdGVSb3V0ZSh0aGlzLCBzdWJzdGF0ZU5hbWUsIHsKICAgICAgICAgIHJlc2V0TmFtZXNwYWNlOiBvcHRpb25zLnJlc2V0TmFtZXNwYWNlLAogICAgICAgICAgcGF0aDogZHVtbXlFcnJvclJvdXRlCiAgICAgICAgfSk7CiAgICAgICAgdGhpcy5vcHRpb25zLmFkZFJvdXRlRm9yRW5naW5lKHN1YnN0YXRlTmFtZSwgX3JvdXRlSW5mbyk7CiAgICAgIH0KCiAgICAgIHRoaXMub3B0aW9ucy5hZGRSb3V0ZUZvckVuZ2luZShmdWxsTmFtZSwgcm91dGVJbmZvKTsKICAgICAgdGhpcy5wdXNoKHBhdGgsIGZ1bGxOYW1lLCBjYWxsYmFjayk7CiAgICB9OwoKICAgIHJldHVybiBEU0xJbXBsOwogIH0oKTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IERTTEltcGw7CgogIGZ1bmN0aW9uIGNhbk5lc3QoZHNsKSB7CiAgICByZXR1cm4gZHNsLnBhcmVudCAhPT0gJ2FwcGxpY2F0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGdldEZ1bGxOYW1lKGRzbCwgbmFtZSwgcmVzZXROYW1lc3BhY2UpIHsKICAgIGlmIChjYW5OZXN0KGRzbCkgJiYgcmVzZXROYW1lc3BhY2UgIT09IHRydWUpIHsKICAgICAgcmV0dXJuIGRzbC5wYXJlbnQgKyAiLiIgKyBuYW1lOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG5hbWU7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBjcmVhdGVSb3V0ZShkc2wsIG5hbWUsIG9wdGlvbnMsIGNhbGxiYWNrKSB7CiAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgIG9wdGlvbnMgPSB7fTsKICAgIH0KCiAgICB2YXIgZnVsbE5hbWUgPSBnZXRGdWxsTmFtZShkc2wsIG5hbWUsIG9wdGlvbnMucmVzZXROYW1lc3BhY2UpOwoKICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5wYXRoICE9PSAnc3RyaW5nJykgewogICAgICBvcHRpb25zLnBhdGggPSAiLyIgKyBuYW1lOwogICAgfQoKICAgIGRzbC5wdXNoKG9wdGlvbnMucGF0aCwgZnVsbE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zLnNlcmlhbGl6ZSk7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vZW5naW5lcyIsIFtdLCBmdW5jdGlvbiAoKSB7CiAgInVzZSBzdHJpY3QiOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vZ2VuZXJhdGVfY29udHJvbGxlciIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwsIF9kZWJ1ZykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZ2VuZXJhdGVDb250cm9sbGVyRmFjdG9yeSA9IGdlbmVyYXRlQ29udHJvbGxlckZhY3Rvcnk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IGdlbmVyYXRlQ29udHJvbGxlcjsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgR2VuZXJhdGVzIGEgY29udHJvbGxlciBmYWN0b3J5CiAgCiAgICBAZm9yIEVtYmVyCiAgICBAbWV0aG9kIGdlbmVyYXRlQ29udHJvbGxlckZhY3RvcnkKICAgIEBwcml2YXRlCiAgKi8KICBmdW5jdGlvbiBnZW5lcmF0ZUNvbnRyb2xsZXJGYWN0b3J5KG93bmVyLCBjb250cm9sbGVyTmFtZSkgewogICAgdmFyIEZhY3RvcnkgPSBvd25lci5mYWN0b3J5Rm9yKCdjb250cm9sbGVyOmJhc2ljJykuY2xhc3M7CiAgICBGYWN0b3J5ID0gRmFjdG9yeS5leHRlbmQoewogICAgICB0b1N0cmluZzogZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgICAgcmV0dXJuICIoZ2VuZXJhdGVkICIgKyBjb250cm9sbGVyTmFtZSArICIgY29udHJvbGxlcikiOwogICAgICB9CiAgICB9KTsKICAgIHZhciBmdWxsTmFtZSA9ICJjb250cm9sbGVyOiIgKyBjb250cm9sbGVyTmFtZTsKICAgIG93bmVyLnJlZ2lzdGVyKGZ1bGxOYW1lLCBGYWN0b3J5KTsKICAgIHJldHVybiBvd25lci5mYWN0b3J5Rm9yKGZ1bGxOYW1lKTsKICB9CiAgLyoqCiAgICBHZW5lcmF0ZXMgYW5kIGluc3RhbnRpYXRlcyBhIGNvbnRyb2xsZXIgZXh0ZW5kaW5nIGZyb20gYGNvbnRyb2xsZXI6YmFzaWNgCiAgICBpZiBwcmVzZW50LCBvciBgQ29udHJvbGxlcmAgaWYgbm90LgogIAogICAgQGZvciBFbWJlcgogICAgQG1ldGhvZCBnZW5lcmF0ZUNvbnRyb2xsZXIKICAgIEBwcml2YXRlCiAgICBAc2luY2UgMS4zLjAKICAqLwoKCiAgZnVuY3Rpb24gZ2VuZXJhdGVDb250cm9sbGVyKG93bmVyLCBjb250cm9sbGVyTmFtZSkgewogICAgZ2VuZXJhdGVDb250cm9sbGVyRmFjdG9yeShvd25lciwgY29udHJvbGxlck5hbWUpOwogICAgdmFyIGZ1bGxOYW1lID0gImNvbnRyb2xsZXI6IiArIGNvbnRyb2xsZXJOYW1lOwogICAgdmFyIGluc3RhbmNlID0gb3duZXIubG9va3VwKGZ1bGxOYW1lKTsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgaWYgKCgwLCBfbWV0YWwuZ2V0KShpbnN0YW5jZSwgJ25hbWVzcGFjZS5MT0dfQUNUSVZFX0dFTkVSQVRJT04nKSkgewogICAgICAgICgwLCBfZGVidWcuaW5mbykoImdlbmVyYXRlZCAtPiAiICsgZnVsbE5hbWUsIHsKICAgICAgICAgIGZ1bGxOYW1lOiBmdWxsTmFtZQogICAgICAgIH0pOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGluc3RhbmNlOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL3F1ZXJ5X3BhcmFtcyIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIHZhciBRdWVyeVBhcmFtcyA9IGZ1bmN0aW9uIFF1ZXJ5UGFyYW1zKHZhbHVlcykgewogICAgaWYgKHZhbHVlcyA9PT0gdm9pZCAwKSB7CiAgICAgIHZhbHVlcyA9IG51bGw7CiAgICB9CgogICAgdGhpcy5pc1F1ZXJ5UGFyYW1zID0gdHJ1ZTsKICAgIHRoaXMudmFsdWVzID0gdmFsdWVzOwogIH07CgogIF9leHBvcnRzLmRlZmF1bHQgPSBRdWVyeVBhcmFtczsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL3JvdXRlLWluZm8iLCBbXSwgZnVuY3Rpb24gKCkgewogICJ1c2Ugc3RyaWN0IjsKICAvKioKICAgIEEgYFJvdXRlSW5mb1dpdGhBdHRyaWJ1dGVzYCBpcyBhbiBvYmplY3QgdGhhdCBjb250YWlucwogICAgbWV0YWRhdGEsIGluY2x1ZGluZyB0aGUgcmVzb2x2ZWQgdmFsdWUgZnJvbSB0aGUgcm91dGVzCiAgICBgbW9kZWxgIGhvb2suIExpa2UgYFJvdXRlSW5mb2AsIGEgYFJvdXRlSW5mb1dpdGhBdHRyaWJ1dGVzYAogICAgcmVwcmVzZW50cyBhIHNwZWNpZmljIHJvdXRlIHdpdGhpbiBhIFRyYW5zaXRpb24uCiAgICBJdCBpcyByZWFkLW9ubHkgYW5kIGludGVybmFsbHkgaW1tdXRhYmxlLiBJdCBpcyBhbHNvIG5vdAogICAgb2JzZXJ2YWJsZSwgYmVjYXVzZSBhIFRyYW5zaXRpb24gaW5zdGFuY2UgaXMgbmV2ZXIKICAgIGNoYW5nZWQgYWZ0ZXIgY3JlYXRpb24uCiAgCiAgICBAY2xhc3MgUm91dGVJbmZvV2l0aEF0dHJpYnV0ZXMKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSBkb3Qtc2VwYXJhdGVkLCBmdWxseS1xdWFsaWZpZWQgbmFtZSBvZiB0aGUKICAgIHJvdXRlLCBsaWtlICJwZW9wbGUuaW5kZXgiLgogICAgQHByb3BlcnR5IHtTdHJpbmd9IG5hbWUKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSBmaW5hbCBzZWdtZW50IG9mIHRoZSBmdWxseS1xdWFsaWZpZWQgbmFtZSBvZgogICAgdGhlIHJvdXRlLCBsaWtlICJpbmRleCIKICAgIEBwcm9wZXJ0eSB7U3RyaW5nfSBsb2NhbE5hbWUKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSB2YWx1ZXMgb2YgdGhlIHJvdXRlJ3MgcGFyYW1ldGVycy4gVGhlc2UgYXJlIHRoZQogICAgc2FtZSBwYXJhbXMgdGhhdCBhcmUgcmVjZWl2ZWQgYXMgYXJndW1lbnRzIHRvIHRoZQogICAgcm91dGUncyBtb2RlbCBob29rLiBDb250YWlucyBvbmx5IHRoZSBwYXJhbWV0ZXJzCiAgICB2YWxpZCBmb3IgdGhpcyByb3V0ZSwgaWYgYW55IChwYXJhbXMgZm9yIHBhcmVudCBvcgogICAgY2hpbGQgcm91dGVzIGFyZSBub3QgbWVyZ2VkKS4KICAgIEBwcm9wZXJ0eSB7T2JqZWN0fSBwYXJhbXMKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSBvcmRlcmVkIGxpc3Qgb2YgdGhlIG5hbWVzIG9mIHRoZSBwYXJhbXMKICAgIHJlcXVpcmVkIGZvciB0aGlzIHJvdXRlLiBJdCB3aWxsIGNvbnRhaW4gdGhlIHNhbWUKICAgIHN0cmluZ3MgYXMgYE9iamVjdC5rZXlzKHBhcmFtcylgLCBidXQgaGVyZSB0aGUgb3JkZXIKICAgIGlzIHNpZ25pZmljYW50LiBUaGlzIGFsbG93cyB1c2VycyB0byBjb3JyZWN0bHkgcGFzcwogICAgcGFyYW1zIGludG8gcm91dGVzIHByb2dyYW1tYXRpY2FsbHkuCiAgICBAcHJvcGVydHkge0FycmF5fSBwYXJhbU5hbWVzCiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBUaGUgdmFsdWVzIG9mIGFueSBxdWVyeVBhcmFtcyBvbiB0aGlzIHJvdXRlLgogICAgQHByb3BlcnR5IHtPYmplY3R9IHF1ZXJ5UGFyYW1zCiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBUaGlzIGlzIHRoZSByZXNvbHZlZCByZXR1cm4gdmFsdWUgZnJvbSB0aGUKICAgIHJvdXRlJ3MgbW9kZWwgaG9vay4KICAgIEBwcm9wZXJ0eSB7T2JqZWN0fEFycmF5fFN0cmluZ30gYXR0cmlidXRlcwogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgV2lsbCBjb250YWluIHRoZSByZXN1bHQgYFJvdXRlI2J1aWxkUm91dGVJbmZvTWV0YWRhdGFgCiAgICBmb3IgdGhlIGNvcnJlc3BvbmRpbmcgUm91dGUuCiAgICBAcHJvcGVydHkge0FueX0gbWV0YWRhdGEKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIEEgcmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgcm91dGUncyBSb3V0ZUluZm8uCiAgICBUaGlzIGNhbiBiZSB1c2VkIHRvIHRyYXZlcnNlIHVwd2FyZCB0byB0aGUgdG9wbW9zdAogICAgYFJvdXRlSW5mb2AuCiAgICBAcHJvcGVydHkge1JvdXRlSW5mb3xudWxsfSBwYXJlbnQKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIEEgcmVmZXJlbmNlIHRvIHRoZSBjaGlsZCByb3V0ZSdzIFJvdXRlSW5mby4KICAgIFRoaXMgY2FuIGJlIHVzZWQgdG8gdHJhdmVyc2UgZG93bndhcmQgdG8gdGhlCiAgICBsZWFmbW9zdCBgUm91dGVJbmZvYC4KICAgIEBwcm9wZXJ0eSB7Um91dGVJbmZvfG51bGx9IGNoaWxkCiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBBbGxvd3MgeW91IHRvIHRyYXZlcnNlIHRocm91Z2ggdGhlIGxpbmtlZCBsaXN0CiAgICBvZiBgUm91dGVJbmZvYHMgZnJvbSB0aGUgdG9wbW9zdCB0byBsZWFmbW9zdC4KICAgIFJldHVybnMgdGhlIGZpcnN0IGBSb3V0ZUluZm9gIGluIHRoZSBsaW5rZWQgbGlzdAogICAgZm9yIHdoaWNoIHRoZSBjYWxsYmFjayByZXR1cm5zIHRydWUuCiAgCiAgICAgIFRoaXMgbWV0aG9kIGlzIHNpbWlsYXIgdG8gdGhlIGBmaW5kKClgIG1ldGhvZAogICAgICBkZWZpbmVkIGluIEVDTUFTY3JpcHQgMjAxNS4KICAKICAgICAgVGhlIGNhbGxiYWNrIG1ldGhvZCB5b3UgcHJvdmlkZSBzaG91bGQgaGF2ZSB0aGUKICAgICAgZm9sbG93aW5nIHNpZ25hdHVyZSAoYWxsIHBhcmFtZXRlcnMgYXJlIG9wdGlvbmFsKToKICAKICAgICAgYGBgamF2YXNjcmlwdAogICAgICBmdW5jdGlvbihpdGVtLCBpbmRleCwgYXJyYXkpOwogICAgICBgYGAKICAKICAgICAgLSBgaXRlbWAgaXMgdGhlIGN1cnJlbnQgaXRlbSBpbiB0aGUgaXRlcmF0aW9uLgogICAgICAtIGBpbmRleGAgaXMgdGhlIGN1cnJlbnQgaW5kZXggaW4gdGhlIGl0ZXJhdGlvbi4KICAgICAgLSBgYXJyYXlgIGlzIHRoZSBhcnJheSBpdHNlbGYuCiAgCiAgICAgIEl0IHNob3VsZCByZXR1cm4gdGhlIGB0cnVlYCB0byBpbmNsdWRlIHRoZSBpdGVtIGluCiAgICAgIHRoZSByZXN1bHRzLCBgZmFsc2VgIG90aGVyd2lzZS4KICAKICAgICAgTm90ZSB0aGF0IGluIGFkZGl0aW9uIHRvIGEgY2FsbGJhY2ssIHlvdSBjYW4gYWxzbwogICAgICBwYXNzIGFuIG9wdGlvbmFsIHRhcmdldCBvYmplY3QgdGhhdCB3aWxsIGJlIHNldCBhcwogICAgICBgdGhpc2Agb24gdGhlIGNvbnRleHQuCiAgCiAgICBAbWV0aG9kIGZpbmQKICAgIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIHRoZSBjYWxsYmFjayB0byBleGVjdXRlCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldCpdIG9wdGlvbmFsIHRhcmdldCB0byB1c2UKICAgIEByZXR1cm5zIHtPYmplY3R9IEZvdW5kIGl0ZW0gb3IgdW5kZWZpbmVkCiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBBIFJvdXRlSW5mbyBpcyBhbiBvYmplY3QgdGhhdCBjb250YWlucyBtZXRhZGF0YQogICAgYWJvdXQgYSBzcGVjaWZpYyByb3V0ZSB3aXRoaW4gYSBUcmFuc2l0aW9uLiBJdCBpcwogICAgcmVhZC1vbmx5IGFuZCBpbnRlcm5hbGx5IGltbXV0YWJsZS4gSXQgaXMgYWxzbyBub3QKICAgIG9ic2VydmFibGUsIGJlY2F1c2UgYSBUcmFuc2l0aW9uIGluc3RhbmNlIGlzIG5ldmVyCiAgICBjaGFuZ2VkIGFmdGVyIGNyZWF0aW9uLgogIAogICAgQGNsYXNzIFJvdXRlSW5mbwogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgVGhlIGRvdC1zZXBhcmF0ZWQsIGZ1bGx5LXF1YWxpZmllZCBuYW1lIG9mIHRoZQogICAgcm91dGUsIGxpa2UgInBlb3BsZS5pbmRleCIuCiAgICBAcHJvcGVydHkge1N0cmluZ30gbmFtZQogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgVGhlIGZpbmFsIHNlZ21lbnQgb2YgdGhlIGZ1bGx5LXF1YWxpZmllZCBuYW1lIG9mCiAgICB0aGUgcm91dGUsIGxpa2UgImluZGV4IgogICAgQHByb3BlcnR5IHtTdHJpbmd9IGxvY2FsTmFtZQogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgVGhlIHZhbHVlcyBvZiB0aGUgcm91dGUncyBwYXJhbWV0ZXJzLiBUaGVzZSBhcmUgdGhlCiAgICBzYW1lIHBhcmFtcyB0aGF0IGFyZSByZWNlaXZlZCBhcyBhcmd1bWVudHMgdG8gdGhlCiAgICByb3V0ZSdzIGBtb2RlbGAgaG9vay4gQ29udGFpbnMgb25seSB0aGUgcGFyYW1ldGVycwogICAgdmFsaWQgZm9yIHRoaXMgcm91dGUsIGlmIGFueSAocGFyYW1zIGZvciBwYXJlbnQgb3IKICAgIGNoaWxkIHJvdXRlcyBhcmUgbm90IG1lcmdlZCkuCiAgICBAcHJvcGVydHkge09iamVjdH0gcGFyYW1zCiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBUaGUgb3JkZXJlZCBsaXN0IG9mIHRoZSBuYW1lcyBvZiB0aGUgcGFyYW1zCiAgICByZXF1aXJlZCBmb3IgdGhpcyByb3V0ZS4gSXQgd2lsbCBjb250YWluIHRoZSBzYW1lCiAgICBzdHJpbmdzIGFzIE9iamVjdC5rZXlzKHBhcmFtcyksIGJ1dCBoZXJlIHRoZSBvcmRlcgogICAgaXMgc2lnbmlmaWNhbnQuIFRoaXMgYWxsb3dzIHVzZXJzIHRvIGNvcnJlY3RseSBwYXNzCiAgICBwYXJhbXMgaW50byByb3V0ZXMgcHJvZ3JhbW1hdGljYWxseS4KICAgIEBwcm9wZXJ0eSB7QXJyYXl9IHBhcmFtTmFtZXMKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSB2YWx1ZXMgb2YgYW55IHF1ZXJ5UGFyYW1zIG9uIHRoaXMgcm91dGUuCiAgICBAcHJvcGVydHkge09iamVjdH0gcXVlcnlQYXJhbXMKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIEEgcmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgcm91dGUncyBgUm91dGVJbmZvYC4KICAgIFRoaXMgY2FuIGJlIHVzZWQgdG8gdHJhdmVyc2UgdXB3YXJkIHRvIHRoZSB0b3Btb3N0CiAgICBgUm91dGVJbmZvYC4KICAgIEBwcm9wZXJ0eSB7Um91dGVJbmZvfG51bGx9IHBhcmVudAogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgQSByZWZlcmVuY2UgdG8gdGhlIGNoaWxkIHJvdXRlJ3MgYFJvdXRlSW5mb2AuCiAgICBUaGlzIGNhbiBiZSB1c2VkIHRvIHRyYXZlcnNlIGRvd253YXJkIHRvIHRoZQogICAgbGVhZm1vc3QgYFJvdXRlSW5mb2AuCiAgICBAcHJvcGVydHkge1JvdXRlSW5mb3xudWxsfSBjaGlsZAogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgQWxsb3dzIHlvdSB0byB0cmF2ZXJzZSB0aHJvdWdoIHRoZSBsaW5rZWQgbGlzdAogICAgb2YgYFJvdXRlSW5mb2BzIGZyb20gdGhlIHRvcG1vc3QgdG8gbGVhZm1vc3QuCiAgICBSZXR1cm5zIHRoZSBmaXJzdCBgUm91dGVJbmZvYCBpbiB0aGUgbGlua2VkIGxpc3QKICAgIGZvciB3aGljaCB0aGUgY2FsbGJhY2sgcmV0dXJucyB0cnVlLgogIAogICAgICBUaGlzIG1ldGhvZCBpcyBzaW1pbGFyIHRvIHRoZSBgZmluZCgpYCBtZXRob2QKICAgICAgZGVmaW5lZCBpbiBFQ01BU2NyaXB0IDIwMTUuCiAgCiAgICAgIFRoZSBjYWxsYmFjayBtZXRob2QgeW91IHByb3ZpZGUgc2hvdWxkIGhhdmUgdGhlCiAgICAgIGZvbGxvd2luZyBzaWduYXR1cmUgKGFsbCBwYXJhbWV0ZXJzIGFyZSBvcHRpb25hbCk6CiAgCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgZnVuY3Rpb24oaXRlbSwgaW5kZXgsIGFycmF5KTsKICAgICAgYGBgCiAgCiAgICAgIC0gYGl0ZW1gIGlzIHRoZSBjdXJyZW50IGl0ZW0gaW4gdGhlIGl0ZXJhdGlvbi4KICAgICAgLSBgaW5kZXhgIGlzIHRoZSBjdXJyZW50IGluZGV4IGluIHRoZSBpdGVyYXRpb24uCiAgICAgIC0gYGFycmF5YCBpcyB0aGUgYXJyYXkgaXRzZWxmLgogIAogICAgICBJdCBzaG91bGQgcmV0dXJuIHRoZSBgdHJ1ZWAgdG8gaW5jbHVkZSB0aGUgaXRlbSBpbgogICAgICB0aGUgcmVzdWx0cywgYGZhbHNlYCBvdGhlcndpc2UuCiAgCiAgICAgIE5vdGUgdGhhdCBpbiBhZGRpdGlvbiB0byBhIGNhbGxiYWNrLCB5b3UgY2FuIGFsc28KICAgICAgcGFzcyBhbiBvcHRpb25hbCB0YXJnZXQgb2JqZWN0IHRoYXQgd2lsbCBiZSBzZXQgYXMKICAgICAgYHRoaXNgIG9uIHRoZSBjb250ZXh0LgogIAogICAgQG1ldGhvZCBmaW5kCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayB0aGUgY2FsbGJhY2sgdG8gZXhlY3V0ZQogICAgQHBhcmFtIHtPYmplY3R9IFt0YXJnZXQqXSBvcHRpb25hbCB0YXJnZXQgdG8gdXNlCiAgICBAcmV0dXJucyB7T2JqZWN0fSBGb3VuZCBpdGVtIG9yIHVuZGVmaW5lZAogICAgQHB1YmxpYwogICovCn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3N5c3RlbS9yb3V0ZSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvcG9seWZpbGxzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIiwgIkBlbWJlci9vYmplY3QvY29tcGF0IiwgIkBlbWJlci9ydW5sb29wIiwgIkBlbWJlci9zdHJpbmciLCAicm91dGVyX2pzIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3V0aWxzIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3N5c3RlbS9nZW5lcmF0ZV9jb250cm9sbGVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3BvbHlmaWxscywgX2VtYmVyQmFiZWwsIF9tZXRhbCwgX293bmVyLCBfcnVudGltZSwgX3V0aWxzLCBfZGVidWcsIF9kZXByZWNhdGVkRmVhdHVyZXMsIF9jb21wYXQsIF9ydW5sb29wLCBfc3RyaW5nLCBfcm91dGVyX2pzLCBfdXRpbHMyLCBfZ2VuZXJhdGVfY29udHJvbGxlcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdFNlcmlhbGl6ZSA9IGRlZmF1bHRTZXJpYWxpemU7CiAgX2V4cG9ydHMuaGFzRGVmYXVsdFNlcmlhbGl6ZSA9IGhhc0RlZmF1bHRTZXJpYWxpemU7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9leHBvcnRzLlJPVVRFUl9FVkVOVF9ERVBSRUNBVElPTlMgPSBfZXhwb3J0cy5ST1VURV9DT05ORUNUSU9OUyA9IHZvaWQgMDsKICB2YXIgUk9VVEVfQ09OTkVDVElPTlMgPSBuZXcgV2Vha01hcCgpOwogIF9leHBvcnRzLlJPVVRFX0NPTk5FQ1RJT05TID0gUk9VVEVfQ09OTkVDVElPTlM7CgogIGZ1bmN0aW9uIGRlZmF1bHRTZXJpYWxpemUobW9kZWwsIHBhcmFtcykgewogICAgaWYgKHBhcmFtcy5sZW5ndGggPCAxIHx8ICFtb2RlbCkgewogICAgICByZXR1cm47CiAgICB9CgogICAgdmFyIG9iamVjdCA9IHt9OwoKICAgIGlmIChwYXJhbXMubGVuZ3RoID09PSAxKSB7CiAgICAgIHZhciBuYW1lID0gcGFyYW1zWzBdOwoKICAgICAgaWYgKG5hbWUgaW4gbW9kZWwpIHsKICAgICAgICBvYmplY3RbbmFtZV0gPSAoMCwgX21ldGFsLmdldCkobW9kZWwsIG5hbWUpOwogICAgICB9IGVsc2UgaWYgKC9faWQkLy50ZXN0KG5hbWUpKSB7CiAgICAgICAgb2JqZWN0W25hbWVdID0gKDAsIF9tZXRhbC5nZXQpKG1vZGVsLCAnaWQnKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgb2JqZWN0ID0gKDAsIF9tZXRhbC5nZXRQcm9wZXJ0aWVzKShtb2RlbCwgcGFyYW1zKTsKICAgIH0KCiAgICByZXR1cm4gb2JqZWN0OwogIH0KCiAgZnVuY3Rpb24gaGFzRGVmYXVsdFNlcmlhbGl6ZShyb3V0ZSkgewogICAgcmV0dXJuIHJvdXRlLnNlcmlhbGl6ZSA9PT0gZGVmYXVsdFNlcmlhbGl6ZTsKICB9CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvcm91dGluZwogICovCgogIC8qKgogICAgVGhlIGBSb3V0ZWAgY2xhc3MgaXMgdXNlZCB0byBkZWZpbmUgaW5kaXZpZHVhbCByb3V0ZXMuIFJlZmVyIHRvCiAgICB0aGUgW3JvdXRpbmcgZ3VpZGVdKGh0dHBzOi8vZ3VpZGVzLmVtYmVyanMuY29tL3JlbGVhc2Uvcm91dGluZy8pIGZvciBkb2N1bWVudGF0aW9uLgogIAogICAgQGNsYXNzIFJvdXRlCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHVzZXMgQWN0aW9uSGFuZGxlcgogICAgQHVzZXMgRXZlbnRlZAogICAgQHNpbmNlIDEuMC4wCiAgICBAcHVibGljCiAgKi8KCgogIHZhciBSb3V0ZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW1iZXJPYmplY3QpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShSb3V0ZSwgX0VtYmVyT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBSb3V0ZSgpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfRW1iZXJPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpcy5jb250ZXh0ID0ge307CiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KICAgIC8qKgogICAgICBUaGUgbmFtZSBvZiB0aGUgcm91dGUsIGRvdC1kZWxpbWl0ZWQuCiAgICAgICAgIEZvciBleGFtcGxlLCBhIHJvdXRlIGZvdW5kIGF0IGBhcHAvcm91dGVzL3Bvc3RzL3Bvc3QuanNgIHdpbGwgaGF2ZQogICAgICBhIGByb3V0ZU5hbWVgIG9mIGBwb3N0cy5wb3N0YC4KICAgICAgICAgQHByb3BlcnR5IHJvdXRlTmFtZQogICAgICBAZm9yIFJvdXRlCiAgICAgIEB0eXBlIFN0cmluZwogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgVGhlIG5hbWUgb2YgdGhlIHJvdXRlLCBkb3QtZGVsaW1pdGVkLCBpbmNsdWRpbmcgdGhlIGVuZ2luZSBwcmVmaXgKICAgICAgaWYgYXBwbGljYWJsZS4KICAgICAgICAgRm9yIGV4YW1wbGUsIGEgcm91dGUgZm91bmQgYXQgYGFkZG9uL3JvdXRlcy9wb3N0cy9wb3N0LmpzYCB3aXRoaW4gYW4KICAgICAgZW5naW5lIG5hbWVkIGBhZG1pbmAgd2lsbCBoYXZlIGEgYGZ1bGxSb3V0ZU5hbWVgIG9mIGBhZG1pbi5wb3N0cy5wb3N0YC4KICAgICAgICAgQHByb3BlcnR5IGZ1bGxSb3V0ZU5hbWUKICAgICAgQGZvciBSb3V0ZQogICAgICBAdHlwZSBTdHJpbmcKICAgICAgQHNpbmNlIDIuMTAuMAogICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBTZXRzIHRoZSBuYW1lIGZvciB0aGlzIHJvdXRlLCBpbmNsdWRpbmcgYSBmdWxseSByZXNvbHZlZCBuYW1lIGZvciByb3V0ZXMKICAgICAgaW5zaWRlIGVuZ2luZXMuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX3NldFJvdXRlTmFtZQogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZQogICAgKi8KCgogICAgdmFyIF9wcm90byA9IFJvdXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uX3NldFJvdXRlTmFtZSA9IGZ1bmN0aW9uIF9zZXRSb3V0ZU5hbWUobmFtZSkgewogICAgICB0aGlzLnJvdXRlTmFtZSA9IG5hbWU7CiAgICAgIHRoaXMuZnVsbFJvdXRlTmFtZSA9IGdldEVuZ2luZVJvdXRlTmFtZSgoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKSwgbmFtZSk7CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgQG1ldGhvZCBfc3Rhc2hOYW1lcwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3N0YXNoTmFtZXMgPSBmdW5jdGlvbiBfc3Rhc2hOYW1lcyhyb3V0ZUluZm8sIGR5bmFtaWNQYXJlbnQpIHsKICAgICAgaWYgKHRoaXMuX25hbWVzKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgbmFtZXMgPSB0aGlzLl9uYW1lcyA9IHJvdXRlSW5mb1snX25hbWVzJ107CgogICAgICBpZiAoIW5hbWVzLmxlbmd0aCkgewogICAgICAgIHJvdXRlSW5mbyA9IGR5bmFtaWNQYXJlbnQ7CiAgICAgICAgbmFtZXMgPSByb3V0ZUluZm8gJiYgcm91dGVJbmZvWydfbmFtZXMnXSB8fCBbXTsKICAgICAgfQoKICAgICAgdmFyIHFwcyA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnX3FwLnFwcycpOwogICAgICB2YXIgbmFtZVBhdGhzID0gbmV3IEFycmF5KG5hbWVzLmxlbmd0aCk7CgogICAgICBmb3IgKHZhciBhID0gMDsgYSA8IG5hbWVzLmxlbmd0aDsgKythKSB7CiAgICAgICAgbmFtZVBhdGhzW2FdID0gcm91dGVJbmZvLm5hbWUgKyAiLiIgKyBuYW1lc1thXTsKICAgICAgfQoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBxcHMubGVuZ3RoOyArK2kpIHsKICAgICAgICB2YXIgcXAgPSBxcHNbaV07CgogICAgICAgIGlmIChxcC5zY29wZSA9PT0gJ21vZGVsJykgewogICAgICAgICAgcXAucGFydHMgPSBuYW1lUGF0aHM7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgQHByb3BlcnR5IF9hY3RpdmVRUENoYW5nZWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9hY3RpdmVRUENoYW5nZWQgPSBmdW5jdGlvbiBfYWN0aXZlUVBDaGFuZ2VkKHFwLCB2YWx1ZSkgewogICAgICB0aGlzLl9yb3V0ZXIuX2FjdGl2ZVFQQ2hhbmdlZChxcC5zY29wZWRQcm9wZXJ0eU5hbWUsIHZhbHVlKTsKICAgIH0KICAgIC8qKgogICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF91cGRhdGluZ1FQQ2hhbmdlZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3VwZGF0aW5nUVBDaGFuZ2VkID0gZnVuY3Rpb24gX3VwZGF0aW5nUVBDaGFuZ2VkKHFwKSB7CiAgICAgIHRoaXMuX3JvdXRlci5fdXBkYXRpbmdRUENoYW5nZWQocXAudXJsS2V5KTsKICAgIH0KICAgIC8qKgogICAgICBSZXR1cm5zIGEgaGFzaCBjb250YWluaW5nIHRoZSBwYXJhbWV0ZXJzIG9mIGFuIGFuY2VzdG9yIHJvdXRlLgogICAgICAgICBZb3UgbWF5IG5vdGljZSB0aGF0IGB0aGlzLnBhcmFtc0ZvcmAgc29tZXRpbWVzIHdvcmtzIHdoZW4gcmVmZXJyaW5nIHRvIGEKICAgICAgY2hpbGQgcm91dGUsIGJ1dCB0aGlzIGJlaGF2aW9yIHNob3VsZCBub3QgYmUgcmVsaWVkIHVwb24gYXMgb25seSBhbmNlc3RvcgogICAgICByb3V0ZXMgYXJlIGNlcnRhaW4gdG8gYmUgbG9hZGVkIGluIHRpbWUuCiAgICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlci5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdtZW1iZXInLCB7IHBhdGg6ICc6bmFtZScgfSwgZnVuY3Rpb24oKSB7CiAgICAgICAgICB0aGlzLnJvdXRlKCdpbnRlcmVzdCcsIHsgcGF0aDogJzppbnRlcmVzdCcgfSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9tZW1iZXIuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBxdWVyeVBhcmFtczogewogICAgICAgICAgbWVtYmVyUXA6IHsgcmVmcmVzaE1vZGVsOiB0cnVlIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9tZW1iZXIvaW50ZXJlc3QuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBxdWVyeVBhcmFtczogewogICAgICAgICAgaW50ZXJlc3RRcDogeyByZWZyZXNoTW9kZWw6IHRydWUgfQogICAgICAgIH0sCiAgICAgICAgICAgbW9kZWwoKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5wYXJhbXNGb3IoJ21lbWJlcicpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBJZiB3ZSB2aXNpdCBgL3R1cmluZy9tYXRocz9tZW1iZXJRcD1tZW1iZXImaW50ZXJlc3RRcD1pbnRlcmVzdGAgdGhlIG1vZGVsIGZvcgogICAgICB0aGUgYG1lbWJlci5pbnRlcmVzdGAgcm91dGUgaXMgYSBoYXNoIHdpdGg6CiAgICAgICAgICogYG5hbWVgOiBgdHVyaW5nYAogICAgICAqIGBtZW1iZXJRcGA6IGBtZW1iZXJgCiAgICAgICAgIEBtZXRob2QgcGFyYW1zRm9yCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lCiAgICAgIEByZXR1cm4ge09iamVjdH0gaGFzaCBjb250YWluaW5nIHRoZSBwYXJhbWV0ZXJzIG9mIHRoZSByb3V0ZSBgbmFtZWAKICAgICAgQHNpbmNlIDEuNC4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLnBhcmFtc0ZvciA9IGZ1bmN0aW9uIHBhcmFtc0ZvcihuYW1lKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgdmFyIHJvdXRlID0gKDAsIF9vd25lci5nZXRPd25lcikodGhpcykubG9va3VwKCJyb3V0ZToiICsgbmFtZSk7CgogICAgICBpZiAocm91dGUgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiB7fTsKICAgICAgfQoKICAgICAgdmFyIHRyYW5zaXRpb24gPSB0aGlzLl9yb3V0ZXIuX3JvdXRlck1pY3JvbGliLmFjdGl2ZVRyYW5zaXRpb247CiAgICAgIHZhciBzdGF0ZSA9IHRyYW5zaXRpb24gPyB0cmFuc2l0aW9uW19yb3V0ZXJfanMuU1RBVEVfU1lNQk9MXSA6IHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWIuc3RhdGU7CiAgICAgIHZhciBmdWxsTmFtZSA9IHJvdXRlLmZ1bGxSb3V0ZU5hbWU7CiAgICAgIHZhciBwYXJhbXMgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBzdGF0ZS5wYXJhbXNbZnVsbE5hbWVdKTsKICAgICAgdmFyIHF1ZXJ5UGFyYW1zID0gZ2V0UXVlcnlQYXJhbXNGb3Iocm91dGUsIHN0YXRlKTsKICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHF1ZXJ5UGFyYW1zKS5yZWR1Y2UoZnVuY3Rpb24gKHBhcmFtcywga2V5KSB7CiAgICAgICAgKGZhbHNlICYmICEoIXBhcmFtc1trZXldKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIlRoZSByb3V0ZSAnIiArIF90aGlzMi5yb3V0ZU5hbWUgKyAiJyBoYXMgYm90aCBhIGR5bmFtaWMgc2VnbWVudCBhbmQgcXVlcnkgcGFyYW0gd2l0aCBuYW1lICciICsga2V5ICsgIicuIFBsZWFzZSByZW5hbWUgb25lIHRvIGF2b2lkIGNvbGxpc2lvbnMuIiwgIXBhcmFtc1trZXldKSk7CiAgICAgICAgcGFyYW1zW2tleV0gPSBxdWVyeVBhcmFtc1trZXldOwogICAgICAgIHJldHVybiBwYXJhbXM7CiAgICAgIH0sIHBhcmFtcyk7CiAgICB9CiAgICAvKioKICAgICAgU2VyaWFsaXplcyB0aGUgcXVlcnkgcGFyYW1ldGVyIGtleQogICAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZVF1ZXJ5UGFyYW1LZXkKICAgICAgQHBhcmFtIHtTdHJpbmd9IGNvbnRyb2xsZXJQcm9wZXJ0eU5hbWUKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLnNlcmlhbGl6ZVF1ZXJ5UGFyYW1LZXkgPSBmdW5jdGlvbiBzZXJpYWxpemVRdWVyeVBhcmFtS2V5KGNvbnRyb2xsZXJQcm9wZXJ0eU5hbWUpIHsKICAgICAgcmV0dXJuIGNvbnRyb2xsZXJQcm9wZXJ0eU5hbWU7CiAgICB9CiAgICAvKioKICAgICAgU2VyaWFsaXplcyB2YWx1ZSBvZiB0aGUgcXVlcnkgcGFyYW1ldGVyIGJhc2VkIG9uIGRlZmF1bHRWYWx1ZVR5cGUKICAgICAgICAgQG1ldGhvZCBzZXJpYWxpemVRdWVyeVBhcmFtCiAgICAgIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZQogICAgICBAcGFyYW0ge1N0cmluZ30gdXJsS2V5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBkZWZhdWx0VmFsdWVUeXBlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5zZXJpYWxpemVRdWVyeVBhcmFtID0gZnVuY3Rpb24gc2VyaWFsaXplUXVlcnlQYXJhbSh2YWx1ZSwgX3VybEtleSwgZGVmYXVsdFZhbHVlVHlwZSkgewogICAgICAvLyB1cmxLZXkgaXNuJ3QgdXNlZCBoZXJlLCBidXQgYW55b25lIG92ZXJyaWRpbmcKICAgICAgLy8gY2FuIHVzZSBpdCB0byBwcm92aWRlIHNlcmlhbGl6YXRpb24gc3BlY2lmaWMKICAgICAgLy8gdG8gYSBjZXJ0YWluIHF1ZXJ5IHBhcmFtLgogICAgICByZXR1cm4gdGhpcy5fcm91dGVyLl9zZXJpYWxpemVRdWVyeVBhcmFtKHZhbHVlLCBkZWZhdWx0VmFsdWVUeXBlKTsKICAgIH0KICAgIC8qKgogICAgICBEZXNlcmlhbGl6ZXMgdmFsdWUgb2YgdGhlIHF1ZXJ5IHBhcmFtZXRlciBiYXNlZCBvbiBkZWZhdWx0VmFsdWVUeXBlCiAgICAgICAgIEBtZXRob2QgZGVzZXJpYWxpemVRdWVyeVBhcmFtCiAgICAgIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZQogICAgICBAcGFyYW0ge1N0cmluZ30gdXJsS2V5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBkZWZhdWx0VmFsdWVUeXBlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5kZXNlcmlhbGl6ZVF1ZXJ5UGFyYW0gPSBmdW5jdGlvbiBkZXNlcmlhbGl6ZVF1ZXJ5UGFyYW0odmFsdWUsIF91cmxLZXksIGRlZmF1bHRWYWx1ZVR5cGUpIHsKICAgICAgLy8gdXJsS2V5IGlzbid0IHVzZWQgaGVyZSwgYnV0IGFueW9uZSBvdmVycmlkaW5nCiAgICAgIC8vIGNhbiB1c2UgaXQgdG8gcHJvdmlkZSBkZXNlcmlhbGl6YXRpb24gc3BlY2lmaWMKICAgICAgLy8gdG8gYSBjZXJ0YWluIHF1ZXJ5IHBhcmFtLgogICAgICByZXR1cm4gdGhpcy5fcm91dGVyLl9kZXNlcmlhbGl6ZVF1ZXJ5UGFyYW0odmFsdWUsIGRlZmF1bHRWYWx1ZVR5cGUpOwogICAgfQogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgICAgIEBwcm9wZXJ0eSBfb3B0aW9uc0ZvclF1ZXJ5UGFyYW0KICAgICovCiAgICA7CgogICAgX3Byb3RvLl9vcHRpb25zRm9yUXVlcnlQYXJhbSA9IGZ1bmN0aW9uIF9vcHRpb25zRm9yUXVlcnlQYXJhbShxcCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICJxdWVyeVBhcmFtcy4iICsgcXAudXJsS2V5KSB8fCAoMCwgX21ldGFsLmdldCkodGhpcywgInF1ZXJ5UGFyYW1zLiIgKyBxcC5wcm9wKSB8fCB7fTsKICAgIH0KICAgIC8qKgogICAgICBBIGhvb2sgeW91IGNhbiB1c2UgdG8gcmVzZXQgY29udHJvbGxlciB2YWx1ZXMgZWl0aGVyIHdoZW4gdGhlIG1vZGVsCiAgICAgIGNoYW5nZXMgb3IgdGhlIHJvdXRlIGlzIGV4aXRpbmcuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvYXJ0aWNsZXMuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICByZXNldENvbnRyb2xsZXIoY29udHJvbGxlciwgaXNFeGl0aW5nLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICBpZiAoaXNFeGl0aW5nICYmIHRyYW5zaXRpb24udGFyZ2V0TmFtZSAhPT0gJ2Vycm9yJykgewogICAgICAgICAgICBjb250cm9sbGVyLnNldCgncGFnZScsIDEpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHJlc2V0Q29udHJvbGxlcgogICAgICBAcGFyYW0ge0NvbnRyb2xsZXJ9IGNvbnRyb2xsZXIgaW5zdGFuY2UKICAgICAgQHBhcmFtIHtCb29sZWFufSBpc0V4aXRpbmcKICAgICAgQHBhcmFtIHtPYmplY3R9IHRyYW5zaXRpb24KICAgICAgQHNpbmNlIDEuNy4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc2V0Q29udHJvbGxlciA9IGZ1bmN0aW9uIHJlc2V0Q29udHJvbGxlcihfY29udHJvbGxlciwgX2lzRXhpdGluZywgX3RyYW5zaXRpb24pIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgQG1ldGhvZCBleGl0CiAgICAqLwogICAgOwoKICAgIF9wcm90by5leGl0ID0gZnVuY3Rpb24gZXhpdCgpIHsKICAgICAgdGhpcy5kZWFjdGl2YXRlKCk7CiAgICAgIHRoaXMudHJpZ2dlcignZGVhY3RpdmF0ZScpOwogICAgICB0aGlzLnRlYXJkb3duVmlld3MoKTsKICAgIH0KICAgIC8qKgogICAgICBAcHJpdmF0ZQogICAgICAgICBAbWV0aG9kIF9pbnRlcm5hbFJlc2V0CiAgICAgIEBzaW5jZSAzLjYuMAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX2ludGVybmFsUmVzZXQgPSBmdW5jdGlvbiBfaW50ZXJuYWxSZXNldChpc0V4aXRpbmcsIHRyYW5zaXRpb24pIHsKICAgICAgdmFyIGNvbnRyb2xsZXIgPSB0aGlzLmNvbnRyb2xsZXI7CiAgICAgIGNvbnRyb2xsZXIuX3FwRGVsZWdhdGUgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ19xcC5zdGF0ZXMuaW5hY3RpdmUnKTsKICAgICAgdGhpcy5yZXNldENvbnRyb2xsZXIoY29udHJvbGxlciwgaXNFeGl0aW5nLCB0cmFuc2l0aW9uKTsKICAgIH0KICAgIC8qKgogICAgICBAcHJpdmF0ZQogICAgICAgICBAbWV0aG9kIGVudGVyCiAgICAqLwogICAgOwoKICAgIF9wcm90by5lbnRlciA9IGZ1bmN0aW9uIGVudGVyKCkgewogICAgICBST1VURV9DT05ORUNUSU9OUy5zZXQodGhpcywgW10pOwogICAgICB0aGlzLmFjdGl2YXRlKCk7CiAgICAgIHRoaXMudHJpZ2dlcignYWN0aXZhdGUnKTsKICAgIH0KICAgIC8qKgogICAgICBUaGUgYHdpbGxUcmFuc2l0aW9uYCBhY3Rpb24gaXMgZmlyZWQgYXQgdGhlIGJlZ2lubmluZyBvZiBhbnkKICAgICAgYXR0ZW1wdGVkIHRyYW5zaXRpb24gd2l0aCBhIGBUcmFuc2l0aW9uYCBvYmplY3QgYXMgdGhlIHNvbGUKICAgICAgYXJndW1lbnQuIFRoaXMgYWN0aW9uIGNhbiBiZSB1c2VkIGZvciBhYm9ydGluZywgcmVkaXJlY3RpbmcsCiAgICAgIG9yIGRlY29yYXRpbmcgdGhlIHRyYW5zaXRpb24gZnJvbSB0aGUgY3VycmVudGx5IGFjdGl2ZSByb3V0ZXMuCiAgICAgICAgIEEgZ29vZCBleGFtcGxlIGlzIHByZXZlbnRpbmcgbmF2aWdhdGlvbiB3aGVuIGEgZm9ybSBpcwogICAgICBoYWxmLWZpbGxlZCBvdXQ6CiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvY29udGFjdC1mb3JtLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgd2lsbFRyYW5zaXRpb24odHJhbnNpdGlvbikgewogICAgICAgICAgICBpZiAodGhpcy5jb250cm9sbGVyLmdldCgndXNlckhhc0VudGVyZWREYXRhJykpIHsKICAgICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZGlzcGxheU5hdmlnYXRpb25Db25maXJtKCk7CiAgICAgICAgICAgICAgdHJhbnNpdGlvbi5hYm9ydCgpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIFlvdSBjYW4gYWxzbyByZWRpcmVjdCBlbHNld2hlcmUgYnkgY2FsbGluZwogICAgICBgdGhpcy50cmFuc2l0aW9uVG8oJ2Vsc2V3aGVyZScpYCBmcm9tIHdpdGhpbiBgd2lsbFRyYW5zaXRpb25gLgogICAgICBOb3RlIHRoYXQgYHdpbGxUcmFuc2l0aW9uYCB3aWxsIG5vdCBiZSBmaXJlZCBmb3IgdGhlCiAgICAgIHJlZGlyZWN0aW5nIGB0cmFuc2l0aW9uVG9gLCBzaW5jZSBgd2lsbFRyYW5zaXRpb25gIGRvZXNuJ3QKICAgICAgZmlyZSB3aGVuIHRoZXJlIGlzIGFscmVhZHkgYSB0cmFuc2l0aW9uIHVuZGVyd2F5LiBJZiB5b3Ugd2FudAogICAgICBzdWJzZXF1ZW50IGB3aWxsVHJhbnNpdGlvbmAgYWN0aW9ucyB0byBmaXJlIGZvciB0aGUgcmVkaXJlY3RpbmcKICAgICAgdHJhbnNpdGlvbiwgeW91IG11c3QgZmlyc3QgZXhwbGljaXRseSBjYWxsCiAgICAgIGB0cmFuc2l0aW9uLmFib3J0KClgLgogICAgICAgICBUbyBhbGxvdyB0aGUgYHdpbGxUcmFuc2l0aW9uYCBldmVudCB0byBjb250aW51ZSBidWJibGluZyB0byB0aGUgcGFyZW50CiAgICAgIHJvdXRlLCB1c2UgYHJldHVybiB0cnVlO2AuIFdoZW4gdGhlIGB3aWxsVHJhbnNpdGlvbmAgbWV0aG9kIGhhcyBhCiAgICAgIHJldHVybiB2YWx1ZSBvZiBgdHJ1ZWAgdGhlbiB0aGUgcGFyZW50IHJvdXRlJ3MgYHdpbGxUcmFuc2l0aW9uYCBtZXRob2QKICAgICAgd2lsbCBiZSBmaXJlZCwgZW5hYmxpbmcgImJ1YmJsaW5nIiBiZWhhdmlvciBmb3IgdGhlIGV2ZW50LgogICAgICAgICBAZXZlbnQgd2lsbFRyYW5zaXRpb24KICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBUaGUgYGRpZFRyYW5zaXRpb25gIGFjdGlvbiBpcyBmaXJlZCBhZnRlciBhIHRyYW5zaXRpb24gaGFzCiAgICAgIHN1Y2Nlc3NmdWxseSBiZWVuIGNvbXBsZXRlZC4gVGhpcyBvY2N1cnMgYWZ0ZXIgdGhlIG5vcm1hbCBtb2RlbAogICAgICBob29rcyAoYGJlZm9yZU1vZGVsYCwgYG1vZGVsYCwgYGFmdGVyTW9kZWxgLCBgc2V0dXBDb250cm9sbGVyYCkKICAgICAgaGF2ZSByZXNvbHZlZC4gVGhlIGBkaWRUcmFuc2l0aW9uYCBhY3Rpb24gaGFzIG5vIGFyZ3VtZW50cywKICAgICAgaG93ZXZlciwgaXQgY2FuIGJlIHVzZWZ1bCBmb3IgdHJhY2tpbmcgcGFnZSB2aWV3cyBvciByZXNldHRpbmcKICAgICAgc3RhdGUgb24gdGhlIGNvbnRyb2xsZXIuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvbG9naW4uanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBkaWRUcmFuc2l0aW9uKCkgewogICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZ2V0KCdlcnJvcnMuYmFzZScpLmNsZWFyKCk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOyAvLyBCdWJibGUgdGhlIGRpZFRyYW5zaXRpb24gZXZlbnQKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQGV2ZW50IGRpZFRyYW5zaXRpb24KICAgICAgQHNpbmNlIDEuMi4wCiAgICAgIEBwdWJsaWMKICAgICovCgogICAgLyoqCiAgICAgIFRoZSBgbG9hZGluZ2AgYWN0aW9uIGlzIGZpcmVkIG9uIHRoZSByb3V0ZSB3aGVuIGEgcm91dGUncyBgbW9kZWxgCiAgICAgIGhvb2sgcmV0dXJucyBhIHByb21pc2UgdGhhdCBpcyBub3QgYWxyZWFkeSByZXNvbHZlZC4gVGhlIGN1cnJlbnQKICAgICAgYFRyYW5zaXRpb25gIG9iamVjdCBpcyB0aGUgZmlyc3QgcGFyYW1ldGVyIGFuZCB0aGUgcm91dGUgdGhhdAogICAgICB0cmlnZ2VyZWQgdGhlIGxvYWRpbmcgZXZlbnQgaXMgdGhlIHNlY29uZCBwYXJhbWV0ZXIuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBsb2FkaW5nKHRyYW5zaXRpb24sIHJvdXRlKSB7CiAgICAgICAgICAgIGxldCBjb250cm9sbGVyID0gdGhpcy5jb250cm9sbGVyRm9yKCdmb28nKTsKICAgICAgICAgICAgY29udHJvbGxlci5zZXQoJ2N1cnJlbnRseUxvYWRpbmcnLCB0cnVlKTsKICAgICAgICAgICAgICAgdHJhbnNpdGlvbi5maW5hbGx5KGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIGNvbnRyb2xsZXIuc2V0KCdjdXJyZW50bHlMb2FkaW5nJywgZmFsc2UpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQGV2ZW50IGxvYWRpbmcKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEBwYXJhbSB7Um91dGV9IHJvdXRlIFRoZSByb3V0ZSB0aGF0IHRyaWdnZXJlZCB0aGUgbG9hZGluZyBldmVudAogICAgICBAc2luY2UgMS4yLjAKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgV2hlbiBhdHRlbXB0aW5nIHRvIHRyYW5zaXRpb24gaW50byBhIHJvdXRlLCBhbnkgb2YgdGhlIGhvb2tzCiAgICAgIG1heSByZXR1cm4gYSBwcm9taXNlIHRoYXQgcmVqZWN0cywgYXQgd2hpY2ggcG9pbnQgYW4gYGVycm9yYAogICAgICBhY3Rpb24gd2lsbCBiZSBmaXJlZCBvbiB0aGUgcGFydGlhbGx5LWVudGVyZWQgcm91dGVzLCBhbGxvd2luZwogICAgICBmb3IgcGVyLXJvdXRlIGVycm9yIGhhbmRsaW5nIGxvZ2ljLCBvciBzaGFyZWQgZXJyb3IgaGFuZGxpbmcKICAgICAgbG9naWMgZGVmaW5lZCBvbiBhIHBhcmVudCByb3V0ZS4KICAgICAgICAgSGVyZSBpcyBhbiBleGFtcGxlIG9mIGFuIGVycm9yIGhhbmRsZXIgdGhhdCB3aWxsIGJlIGludm9rZWQKICAgICAgZm9yIHJlamVjdGVkIHByb21pc2VzIGZyb20gdGhlIHZhcmlvdXMgaG9va3Mgb24gdGhlIHJvdXRlLAogICAgICBhcyB3ZWxsIGFzIGFueSB1bmhhbmRsZWQgZXJyb3JzIGZyb20gY2hpbGQgcm91dGVzOgogICAgICAgICBgYGBhcHAvcm91dGVzL2FkbWluLmpzCiAgICAgIGltcG9ydCB7IHJlamVjdCB9IGZyb20gJ3JzdnAnOwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGJlZm9yZU1vZGVsKCkgewogICAgICAgICAgcmV0dXJuIHJlamVjdCgnYmFkIHRoaW5ncyEnKTsKICAgICAgICB9LAogICAgICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIGVycm9yKGVycm9yLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICAgIC8vIEFzc3VtaW5nIHdlIGdvdCBoZXJlIGR1ZSB0byB0aGUgZXJyb3IgaW4gYGJlZm9yZU1vZGVsYCwKICAgICAgICAgICAgLy8gd2UgY2FuIGV4cGVjdCB0aGF0IGVycm9yID09PSAiYmFkIHRoaW5ncyEiLAogICAgICAgICAgICAvLyBidXQgYSBwcm9taXNlIG1vZGVsIHJlamVjdGluZyB3b3VsZCBhbHNvCiAgICAgICAgICAgIC8vIGNhbGwgdGhpcyBob29rLCBhcyB3b3VsZCBhbnkgZXJyb3JzIGVuY291bnRlcmVkCiAgICAgICAgICAgIC8vIGluIGBhZnRlck1vZGVsYC4KICAgICAgICAgICAgICAgLy8gVGhlIGBlcnJvcmAgaG9vayBpcyBhbHNvIHByb3ZpZGVkIHRoZSBmYWlsZWQKICAgICAgICAgICAgLy8gYHRyYW5zaXRpb25gLCB3aGljaCBjYW4gYmUgc3RvcmVkIGFuZCBsYXRlcgogICAgICAgICAgICAvLyBgLnJldHJ5KClgZCBpZiBkZXNpcmVkLgogICAgICAgICAgICAgICB0aGlzLnRyYW5zaXRpb25UbygnbG9naW4nKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgYGVycm9yYCBhY3Rpb25zIHRoYXQgYnViYmxlIHVwIGFsbCB0aGUgd2F5IHRvIGBBcHBsaWNhdGlvblJvdXRlYAogICAgICB3aWxsIGZpcmUgYSBkZWZhdWx0IGVycm9yIGhhbmRsZXIgdGhhdCBsb2dzIHRoZSBlcnJvci4gWW91IGNhbgogICAgICBzcGVjaWZ5IHlvdXIgb3duIGdsb2JhbCBkZWZhdWx0IGVycm9yIGhhbmRsZXIgYnkgb3ZlcnJpZGluZyB0aGUKICAgICAgYGVycm9yYCBoYW5kbGVyIG9uIGBBcHBsaWNhdGlvblJvdXRlYDoKICAgICAgICAgYGBgYXBwL3JvdXRlcy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIGVycm9yKGVycm9yLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICAgIHRoaXMuY29udHJvbGxlckZvcignYmFubmVyJykuZGlzcGxheUVycm9yKGVycm9yLm1lc3NhZ2UpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICBAZXZlbnQgZXJyb3IKICAgICAgQHBhcmFtIHtFcnJvcn0gZXJyb3IKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBUaGlzIGV2ZW50IGlzIHRyaWdnZXJlZCB3aGVuIHRoZSByb3V0ZXIgZW50ZXJzIHRoZSByb3V0ZS4gSXQgaXMKICAgICAgbm90IGV4ZWN1dGVkIHdoZW4gdGhlIG1vZGVsIGZvciB0aGUgcm91dGUgY2hhbmdlcy4KICAgICAgICAgYGBgYXBwL3JvdXRlcy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgeyBvbiB9IGZyb20gJ0BlbWJlci9vYmplY3QvZXZlbnRlZCc7CiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgY29sbGVjdEFuYWx5dGljczogb24oJ2FjdGl2YXRlJywgZnVuY3Rpb24oKXsKICAgICAgICAgIGNvbGxlY3RBbmFseXRpY3MoKTsKICAgICAgICB9KQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIEBldmVudCBhY3RpdmF0ZQogICAgICBAc2luY2UgMS45LjAKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgVGhpcyBldmVudCBpcyB0cmlnZ2VyZWQgd2hlbiB0aGUgcm91dGVyIGNvbXBsZXRlbHkgZXhpdHMgdGhpcwogICAgICByb3V0ZS4gSXQgaXMgbm90IGV4ZWN1dGVkIHdoZW4gdGhlIG1vZGVsIGZvciB0aGUgcm91dGUgY2hhbmdlcy4KICAgICAgICAgYGBgYXBwL3JvdXRlcy9pbmRleC5qcwogICAgICBpbXBvcnQgeyBvbiB9IGZyb20gJ0BlbWJlci9vYmplY3QvZXZlbnRlZCc7CiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgdHJhY2tQYWdlTGVhdmVBbmFseXRpY3M6IG9uKCdkZWFjdGl2YXRlJywgZnVuY3Rpb24oKXsKICAgICAgICAgIHRyYWNrUGFnZUxlYXZlQW5hbHl0aWNzKCk7CiAgICAgICAgfSkKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAZXZlbnQgZGVhY3RpdmF0ZQogICAgICBAc2luY2UgMS45LjAKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgVGhpcyBob29rIGlzIGV4ZWN1dGVkIHdoZW4gdGhlIHJvdXRlciBjb21wbGV0ZWx5IGV4aXRzIHRoaXMgcm91dGUuIEl0IGlzCiAgICAgIG5vdCBleGVjdXRlZCB3aGVuIHRoZSBtb2RlbCBmb3IgdGhlIHJvdXRlIGNoYW5nZXMuCiAgICAgICAgIEBtZXRob2QgZGVhY3RpdmF0ZQogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZGVhY3RpdmF0ZSA9IGZ1bmN0aW9uIGRlYWN0aXZhdGUoKSB7fQogICAgLyoqCiAgICAgIFRoaXMgaG9vayBpcyBleGVjdXRlZCB3aGVuIHRoZSByb3V0ZXIgZW50ZXJzIHRoZSByb3V0ZS4gSXQgaXMgbm90IGV4ZWN1dGVkCiAgICAgIHdoZW4gdGhlIG1vZGVsIGZvciB0aGUgcm91dGUgY2hhbmdlcy4KICAgICAgICAgQG1ldGhvZCBhY3RpdmF0ZQogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uYWN0aXZhdGUgPSBmdW5jdGlvbiBhY3RpdmF0ZSgpIHt9CiAgICAvKioKICAgICAgVHJhbnNpdGlvbiB0aGUgYXBwbGljYXRpb24gaW50byBhbm90aGVyIHJvdXRlLiBUaGUgcm91dGUgbWF5CiAgICAgIGJlIGVpdGhlciBhIHNpbmdsZSByb3V0ZSBvciByb3V0ZSBwYXRoOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCdibG9nUG9zdHMnKTsKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ2Jsb2dQb3N0cy5yZWNlbnRFbnRyaWVzJyk7CiAgICAgIGBgYAogICAgICAgICBPcHRpb25hbGx5IHN1cHBseSBhIG1vZGVsIGZvciB0aGUgcm91dGUgaW4gcXVlc3Rpb24uIFRoZSBtb2RlbAogICAgICB3aWxsIGJlIHNlcmlhbGl6ZWQgaW50byB0aGUgVVJMIHVzaW5nIHRoZSBgc2VyaWFsaXplYCBob29rIG9mCiAgICAgIHRoZSByb3V0ZToKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICB0aGlzLnRyYW5zaXRpb25UbygnYmxvZ1Bvc3QnLCBhUG9zdCk7CiAgICAgIGBgYAogICAgICAgICBJZiBhIGxpdGVyYWwgaXMgcGFzc2VkIChzdWNoIGFzIGEgbnVtYmVyIG9yIGEgc3RyaW5nKSwgaXQgd2lsbAogICAgICBiZSB0cmVhdGVkIGFzIGFuIGlkZW50aWZpZXIgaW5zdGVhZC4gSW4gdGhpcyBjYXNlLCB0aGUgYG1vZGVsYAogICAgICBob29rIG9mIHRoZSByb3V0ZSB3aWxsIGJlIHRyaWdnZXJlZDoKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICB0aGlzLnRyYW5zaXRpb25UbygnYmxvZ1Bvc3QnLCAxKTsKICAgICAgYGBgCiAgICAgICAgIE11bHRpcGxlIG1vZGVscyB3aWxsIGJlIGFwcGxpZWQgbGFzdCB0byBmaXJzdCByZWN1cnNpdmVseSB1cCB0aGUKICAgICAgcm91dGUgdHJlZS4KICAgICAgICAgYGBgYXBwL3JvdXRlcy5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdibG9nUG9zdCcsIHsgcGF0aDonOmJsb2dQb3N0SWQnIH0sIGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhpcy5yb3V0ZSgnYmxvZ0NvbW1lbnQnLCB7IHBhdGg6ICc6YmxvZ0NvbW1lbnRJZCcgfSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCdibG9nQ29tbWVudCcsIGFQb3N0LCBhQ29tbWVudCk7CiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCdibG9nQ29tbWVudCcsIDEsIDEzKTsKICAgICAgYGBgCiAgICAgICAgIEl0IGlzIGFsc28gcG9zc2libGUgdG8gcGFzcyBhIFVSTCAoYSBzdHJpbmcgdGhhdCBzdGFydHMgd2l0aCBhCiAgICAgIGAvYCkuCiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJy8nKTsKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJy9ibG9nL3Bvc3QvMS9jb21tZW50LzEzJyk7CiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCcvYmxvZy9wb3N0cz9zb3J0PXRpdGxlJyk7CiAgICAgIGBgYAogICAgICAgICBBbiBvcHRpb25zIGhhc2ggd2l0aCBhIGBxdWVyeVBhcmFtc2AgcHJvcGVydHkgbWF5IGJlIHByb3ZpZGVkIGFzCiAgICAgIHRoZSBmaW5hbCBhcmd1bWVudCB0byBhZGQgcXVlcnkgcGFyYW1ldGVycyB0byB0aGUgZGVzdGluYXRpb24gVVJMLgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCdibG9nUG9zdCcsIDEsIHsKICAgICAgICBxdWVyeVBhcmFtczogeyBzaG93Q29tbWVudHM6ICd0cnVlJyB9CiAgICAgIH0pOwogICAgICAgICAvLyBpZiB5b3UganVzdCB3YW50IHRvIHRyYW5zaXRpb24gdGhlIHF1ZXJ5IHBhcmFtZXRlcnMgd2l0aG91dCBjaGFuZ2luZyB0aGUgcm91dGUKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oeyBxdWVyeVBhcmFtczogeyBzb3J0OiAnZGF0ZScgfSB9KTsKICAgICAgYGBgCiAgICAgICAgIFNlZSBhbHNvIFtyZXBsYWNlV2l0aF0oI21ldGhvZF9yZXBsYWNlV2l0aCkuCiAgICAgICAgIFNpbXBsZSBUcmFuc2l0aW9uIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlcy5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdpbmRleCcpOwogICAgICAgIHRoaXMucm91dGUoJ3NlY3JldCcpOwogICAgICAgIHRoaXMucm91dGUoJ2ZvdXJPaEZvdXInLCB7IHBhdGg6ICcqOicgfSk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL2luZGV4LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIG1vdmVUb1NlY3JldChjb250ZXh0KSB7CiAgICAgICAgICAgIGlmIChhdXRob3JpemVkKCkpIHsKICAgICAgICAgICAgICB0aGlzLnRyYW5zaXRpb25Ubygnc2VjcmV0JywgY29udGV4dCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ2ZvdXJPaEZvdXInKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBUcmFuc2l0aW9uIHRvIGEgbmVzdGVkIHJvdXRlCiAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgLy8gLi4uCiAgICAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgnYXJ0aWNsZXMnLCB7IHBhdGg6ICcvYXJ0aWNsZXMnIH0sIGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhpcy5yb3V0ZSgnbmV3Jyk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL2luZGV4LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgdHJhbnNpdGlvblRvTmV3QXJ0aWNsZSgpIHsKICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ2FydGljbGVzLm5ldycpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBNdWx0aXBsZSBNb2RlbHMgRXhhbXBsZQogICAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgIC8vIC4uLgogICAgICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoJ2luZGV4Jyk7CiAgICAgICAgICAgdGhpcy5yb3V0ZSgnYnJlYWtmYXN0JywgeyBwYXRoOiAnOmJyZWFrZmFzdElkJyB9LCBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMucm91dGUoJ2NlcmVhbCcsIHsgcGF0aDogJzpjZXJlYWxJZCcgfSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL2luZGV4LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgbW92ZVRvQ2hvY29sYXRlQ2VyZWFsKCkgewogICAgICAgICAgICBsZXQgY2VyZWFsID0geyBjZXJlYWxJZDogJ0Nob2NvbGF0ZVl1bW1pbmVzcycgfTsKICAgICAgICAgICAgbGV0IGJyZWFrZmFzdCA9IHsgYnJlYWtmYXN0SWQ6ICdDZXJlYWxBbmRNaWxrJyB9OwogICAgICAgICAgICAgICB0aGlzLnRyYW5zaXRpb25UbygnYnJlYWtmYXN0LmNlcmVhbCcsIGJyZWFrZmFzdCwgY2VyZWFsKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgTmVzdGVkIFJvdXRlIHdpdGggUXVlcnkgU3RyaW5nIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlcy5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdmcnVpdHMnLCBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMucm91dGUoJ2FwcGxlcycpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9pbmRleC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHRyYW5zaXRpb25Ub0FwcGxlcygpIHsKICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ2ZydWl0cy5hcHBsZXMnLCB7IHF1ZXJ5UGFyYW1zOiB7IGNvbG9yOiAncmVkJyB9IH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHRyYW5zaXRpb25UbwogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSB0aGUgbmFtZSBvZiB0aGUgcm91dGUgb3IgYSBVUkwKICAgICAgQHBhcmFtIHsuLi5PYmplY3R9IG1vZGVscyB0aGUgbW9kZWwocykgb3IgaWRlbnRpZmllcihzKSB0byBiZSB1c2VkIHdoaWxlCiAgICAgICAgdHJhbnNpdGlvbmluZyB0byB0aGUgcm91dGUuCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gb3B0aW9uYWwgaGFzaCB3aXRoIGEgcXVlcnlQYXJhbXMgcHJvcGVydHkKICAgICAgICBjb250YWluaW5nIGEgbWFwcGluZyBvZiBxdWVyeSBwYXJhbWV0ZXJzCiAgICAgIEByZXR1cm4ge1RyYW5zaXRpb259IHRoZSB0cmFuc2l0aW9uIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhpcwogICAgICAgIGF0dGVtcHRlZCB0cmFuc2l0aW9uCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by50cmFuc2l0aW9uVG8gPSBmdW5jdGlvbiB0cmFuc2l0aW9uVG8oKSB7CiAgICAgIHZhciBfdGhpcyRfcm91dGVyOwoKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgICAgfQoKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFycwogICAgICByZXR1cm4gKF90aGlzJF9yb3V0ZXIgPSB0aGlzLl9yb3V0ZXIpLnRyYW5zaXRpb25Uby5hcHBseShfdGhpcyRfcm91dGVyLCAoMCwgX3V0aWxzMi5wcmVmaXhSb3V0ZU5hbWVBcmcpKHRoaXMsIGFyZ3MpKTsKICAgIH0KICAgIC8qKgogICAgICBQZXJmb3JtIGEgc3luY2hyb25vdXMgdHJhbnNpdGlvbiBpbnRvIGFub3RoZXIgcm91dGUgd2l0aG91dCBhdHRlbXB0aW5nCiAgICAgIHRvIHJlc29sdmUgcHJvbWlzZXMsIHVwZGF0ZSB0aGUgVVJMLCBvciBhYm9ydCBhbnkgY3VycmVudGx5IGFjdGl2ZQogICAgICBhc3luY2hyb25vdXMgdHJhbnNpdGlvbnMgKGkuZS4gcmVndWxhciB0cmFuc2l0aW9ucyBjYXVzZWQgYnkKICAgICAgYHRyYW5zaXRpb25Ub2Agb3IgVVJMIGNoYW5nZXMpLgogICAgICAgICBUaGlzIG1ldGhvZCBpcyBoYW5keSBmb3IgcGVyZm9ybWluZyBpbnRlcm1lZGlhdGUgdHJhbnNpdGlvbnMgb24gdGhlCiAgICAgIHdheSB0byBhIGZpbmFsIGRlc3RpbmF0aW9uIHJvdXRlLCBhbmQgaXMgY2FsbGVkIGludGVybmFsbHkgYnkgdGhlCiAgICAgIGRlZmF1bHQgaW1wbGVtZW50YXRpb25zIG9mIHRoZSBgZXJyb3JgIGFuZCBgbG9hZGluZ2AgaGFuZGxlcnMuCiAgICAgICAgIEBtZXRob2QgaW50ZXJtZWRpYXRlVHJhbnNpdGlvblRvCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZQogICAgICBAcGFyYW0gey4uLk9iamVjdH0gbW9kZWxzIHRoZSBtb2RlbChzKSB0byBiZSB1c2VkIHdoaWxlIHRyYW5zaXRpb25pbmcKICAgICAgdG8gdGhlIHJvdXRlLgogICAgICBAc2luY2UgMS4yLjAKICAgICAgQHB1YmxpYwogICAgICovCiAgICA7CgogICAgX3Byb3RvLmludGVybWVkaWF0ZVRyYW5zaXRpb25UbyA9IGZ1bmN0aW9uIGludGVybWVkaWF0ZVRyYW5zaXRpb25UbygpIHsKICAgICAgdmFyIF90aGlzJF9yb3V0ZXIyOwoKICAgICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4yKSwgX2tleTIgPSAwOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7CiAgICAgICAgYXJnc1tfa2V5Ml0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICB9CgogICAgICB2YXIgX3ByZWZpeFJvdXRlTmFtZUFyZyA9ICgwLCBfdXRpbHMyLnByZWZpeFJvdXRlTmFtZUFyZykodGhpcywgYXJncyksCiAgICAgICAgICBuYW1lID0gX3ByZWZpeFJvdXRlTmFtZUFyZ1swXSwKICAgICAgICAgIHByZXBhcmVkQXJncyA9IF9wcmVmaXhSb3V0ZU5hbWVBcmcuc2xpY2UoMSk7CgogICAgICAoX3RoaXMkX3JvdXRlcjIgPSB0aGlzLl9yb3V0ZXIpLmludGVybWVkaWF0ZVRyYW5zaXRpb25Uby5hcHBseShfdGhpcyRfcm91dGVyMiwgW25hbWVdLmNvbmNhdChwcmVwYXJlZEFyZ3MpKTsKICAgIH0KICAgIC8qKgogICAgICBSZWZyZXNoIHRoZSBtb2RlbCBvbiB0aGlzIHJvdXRlIGFuZCBhbnkgY2hpbGQgcm91dGVzLCBmaXJpbmcgdGhlCiAgICAgIGBiZWZvcmVNb2RlbGAsIGBtb2RlbGAsIGFuZCBgYWZ0ZXJNb2RlbGAgaG9va3MgaW4gYSBzaW1pbGFyIGZhc2hpb24KICAgICAgdG8gaG93IHJvdXRlcyBhcmUgZW50ZXJlZCB3aGVuIHRyYW5zaXRpb25pbmcgaW4gZnJvbSBvdGhlciByb3V0ZS4KICAgICAgVGhlIGN1cnJlbnQgcm91dGUgcGFyYW1zIChlLmcuIGBhcnRpY2xlX2lkYCkgd2lsbCBiZSBwYXNzZWQgaW4KICAgICAgdG8gdGhlIHJlc3BlY3RpdmUgbW9kZWwgaG9va3MsIGFuZCBpZiBhIGRpZmZlcmVudCBtb2RlbCBpcyByZXR1cm5lZCwKICAgICAgYHNldHVwQ29udHJvbGxlcmAgYW5kIGFzc29jaWF0ZWQgcm91dGUgaG9va3Mgd2lsbCByZS1maXJlIGFzIHdlbGwuCiAgICAgICAgIEFuIGV4YW1wbGUgdXNhZ2Ugb2YgdGhpcyBtZXRob2QgaXMgcmUtcXVlcnlpbmcgdGhlIHNlcnZlciBmb3IgdGhlCiAgICAgIGxhdGVzdCBpbmZvcm1hdGlvbiB1c2luZyB0aGUgc2FtZSBwYXJhbWV0ZXJzIGFzIHdoZW4gdGhlIHJvdXRlCiAgICAgIHdhcyBmaXJzdCBlbnRlcmVkLgogICAgICAgICBOb3RlIHRoYXQgdGhpcyB3aWxsIGNhdXNlIGBtb2RlbGAgaG9va3MgdG8gZmlyZSBldmVuIG9uIHJvdXRlcwogICAgICB0aGF0IHdlcmUgcHJvdmlkZWQgYSBtb2RlbCBvYmplY3Qgd2hlbiB0aGUgcm91dGUgd2FzIGluaXRpYWxseQogICAgICBlbnRlcmVkLgogICAgICAgICBAbWV0aG9kIHJlZnJlc2gKICAgICAgQHJldHVybiB7VHJhbnNpdGlvbn0gdGhlIHRyYW5zaXRpb24gb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGlzCiAgICAgICAgYXR0ZW1wdGVkIHRyYW5zaXRpb24KICAgICAgQHNpbmNlIDEuNC4wCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by5yZWZyZXNoID0gZnVuY3Rpb24gcmVmcmVzaCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWIucmVmcmVzaCh0aGlzKTsKICAgIH0KICAgIC8qKgogICAgICBUcmFuc2l0aW9uIGludG8gYW5vdGhlciByb3V0ZSB3aGlsZSByZXBsYWNpbmcgdGhlIGN1cnJlbnQgVVJMLCBpZiBwb3NzaWJsZS4KICAgICAgVGhpcyB3aWxsIHJlcGxhY2UgdGhlIGN1cnJlbnQgaGlzdG9yeSBlbnRyeSBpbnN0ZWFkIG9mIGFkZGluZyBhIG5ldyBvbmUuCiAgICAgIEJlc2lkZSB0aGF0LCBpdCBpcyBpZGVudGljYWwgdG8gYHRyYW5zaXRpb25Ub2AgaW4gYWxsIG90aGVyIHJlc3BlY3RzLiBTZWUKICAgICAgJ3RyYW5zaXRpb25UbycgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIG11bHRpcGxlIG1vZGVscy4KICAgICAgICAgRXhhbXBsZQogICAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgIC8vIC4uLgogICAgICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoJ2luZGV4Jyk7CiAgICAgICAgdGhpcy5yb3V0ZSgnc2VjcmV0Jyk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL3NlY3JldC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFmdGVyTW9kZWwoKSB7CiAgICAgICAgICBpZiAoIWF1dGhvcml6ZWQoKSl7CiAgICAgICAgICAgIHRoaXMucmVwbGFjZVdpdGgoJ2luZGV4Jyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIEBtZXRob2QgcmVwbGFjZVdpdGgKICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIHJvdXRlIG9yIGEgVVJMCiAgICAgIEBwYXJhbSB7Li4uT2JqZWN0fSBtb2RlbHMgdGhlIG1vZGVsKHMpIG9yIGlkZW50aWZpZXIocykgdG8gYmUgdXNlZCB3aGlsZQogICAgICAgIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIG9wdGlvbmFsIGhhc2ggd2l0aCBhIHF1ZXJ5UGFyYW1zIHByb3BlcnR5CiAgICAgICAgY29udGFpbmluZyBhIG1hcHBpbmcgb2YgcXVlcnkgcGFyYW1ldGVycwogICAgICBAcmV0dXJuIHtUcmFuc2l0aW9ufSB0aGUgdHJhbnNpdGlvbiBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoaXMKICAgICAgICBhdHRlbXB0ZWQgdHJhbnNpdGlvbgogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVwbGFjZVdpdGggPSBmdW5jdGlvbiByZXBsYWNlV2l0aCgpIHsKICAgICAgdmFyIF90aGlzJF9yb3V0ZXIzOwoKICAgICAgZm9yICh2YXIgX2xlbjMgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4zKSwgX2tleTMgPSAwOyBfa2V5MyA8IF9sZW4zOyBfa2V5MysrKSB7CiAgICAgICAgYXJnc1tfa2V5M10gPSBhcmd1bWVudHNbX2tleTNdOwogICAgICB9CgogICAgICByZXR1cm4gKF90aGlzJF9yb3V0ZXIzID0gdGhpcy5fcm91dGVyKS5yZXBsYWNlV2l0aC5hcHBseShfdGhpcyRfcm91dGVyMywgKDAsIF91dGlsczIucHJlZml4Um91dGVOYW1lQXJnKSh0aGlzLCBhcmdzKSk7CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBob29rIGlzIHRoZSBlbnRyeSBwb2ludCBmb3Igcm91dGVyLmpzCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2Qgc2V0dXAKICAgICovCiAgICA7CgogICAgX3Byb3RvLnNldHVwID0gZnVuY3Rpb24gc2V0dXAoY29udGV4dCwgdHJhbnNpdGlvbikgewogICAgICB2YXIgY29udHJvbGxlck5hbWUgPSB0aGlzLmNvbnRyb2xsZXJOYW1lIHx8IHRoaXMucm91dGVOYW1lOwogICAgICB2YXIgZGVmaW5lZENvbnRyb2xsZXIgPSB0aGlzLmNvbnRyb2xsZXJGb3IoY29udHJvbGxlck5hbWUsIHRydWUpOwogICAgICB2YXIgY29udHJvbGxlcjsKCiAgICAgIGlmIChkZWZpbmVkQ29udHJvbGxlcikgewogICAgICAgIGNvbnRyb2xsZXIgPSBkZWZpbmVkQ29udHJvbGxlcjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb250cm9sbGVyID0gdGhpcy5nZW5lcmF0ZUNvbnRyb2xsZXIoY29udHJvbGxlck5hbWUpOwogICAgICB9IC8vIEFzc2lnbiB0aGUgcm91dGUncyBjb250cm9sbGVyIHNvIHRoYXQgaXQgY2FuIG1vcmUgZWFzaWx5IGJlCiAgICAgIC8vIHJlZmVyZW5jZWQgaW4gYWN0aW9uIGhhbmRsZXJzLiBTaWRlIGVmZmVjdHMuIFNpZGUgZWZmZWN0cyBldmVyeXdoZXJlLgoKCiAgICAgIGlmICghdGhpcy5jb250cm9sbGVyKSB7CiAgICAgICAgdmFyIHFwID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdfcXAnKTsKICAgICAgICB2YXIgcHJvcE5hbWVzID0gcXAgIT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YWwuZ2V0KShxcCwgJ3Byb3BlcnR5TmFtZXMnKSA6IFtdOwogICAgICAgIGFkZFF1ZXJ5UGFyYW1zT2JzZXJ2ZXJzKGNvbnRyb2xsZXIsIHByb3BOYW1lcyk7CiAgICAgICAgdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjsKICAgICAgfQoKICAgICAgdmFyIHF1ZXJ5UGFyYW1zID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdfcXAnKTsKICAgICAgdmFyIHN0YXRlcyA9IHF1ZXJ5UGFyYW1zLnN0YXRlczsKICAgICAgY29udHJvbGxlci5fcXBEZWxlZ2F0ZSA9IHN0YXRlcy5hbGxvd092ZXJyaWRlczsKCiAgICAgIGlmICh0cmFuc2l0aW9uKSB7CiAgICAgICAgLy8gVXBkYXRlIHRoZSBtb2RlbCBkZXAgdmFsdWVzIHVzZWQgdG8gY2FsY3VsYXRlIGNhY2hlIGtleXMuCiAgICAgICAgKDAsIF91dGlsczIuc3Rhc2hQYXJhbU5hbWVzKSh0aGlzLl9yb3V0ZXIsIHRyYW5zaXRpb25bX3JvdXRlcl9qcy5TVEFURV9TWU1CT0xdLnJvdXRlSW5mb3MpOwogICAgICAgIHZhciBjYWNoZSA9IHRoaXMuX2J1Y2tldENhY2hlOwogICAgICAgIHZhciBwYXJhbXMgPSB0cmFuc2l0aW9uW19yb3V0ZXJfanMuUEFSQU1TX1NZTUJPTF07CiAgICAgICAgdmFyIGFsbFBhcmFtcyA9IHF1ZXJ5UGFyYW1zLnByb3BlcnR5TmFtZXM7CiAgICAgICAgYWxsUGFyYW1zLmZvckVhY2goZnVuY3Rpb24gKHByb3ApIHsKICAgICAgICAgIHZhciBhUXAgPSBxdWVyeVBhcmFtcy5tYXBbcHJvcF07CiAgICAgICAgICBhUXAudmFsdWVzID0gcGFyYW1zOwogICAgICAgICAgdmFyIGNhY2hlS2V5ID0gKDAsIF91dGlsczIuY2FsY3VsYXRlQ2FjaGVLZXkpKGFRcC5yb3V0ZS5mdWxsUm91dGVOYW1lLCBhUXAucGFydHMsIGFRcC52YWx1ZXMpOwogICAgICAgICAgdmFyIHZhbHVlID0gY2FjaGUubG9va3VwKGNhY2hlS2V5LCBwcm9wLCBhUXAudW5kZWNvcmF0ZWREZWZhdWx0VmFsdWUpOwogICAgICAgICAgKDAsIF9tZXRhbC5zZXQpKGNvbnRyb2xsZXIsIHByb3AsIHZhbHVlKTsKICAgICAgICB9KTsKICAgICAgICB2YXIgcXBWYWx1ZXMgPSBnZXRRdWVyeVBhcmFtc0Zvcih0aGlzLCB0cmFuc2l0aW9uW19yb3V0ZXJfanMuU1RBVEVfU1lNQk9MXSk7CiAgICAgICAgKDAsIF9tZXRhbC5zZXRQcm9wZXJ0aWVzKShjb250cm9sbGVyLCBxcFZhbHVlcyk7CiAgICAgIH0KCiAgICAgIHRoaXMuc2V0dXBDb250cm9sbGVyKGNvbnRyb2xsZXIsIGNvbnRleHQsIHRyYW5zaXRpb24pOwoKICAgICAgaWYgKHRoaXMuX2Vudmlyb25tZW50Lm9wdGlvbnMuc2hvdWxkUmVuZGVyKSB7CiAgICAgICAgdGhpcy5yZW5kZXJUZW1wbGF0ZShjb250cm9sbGVyLCBjb250ZXh0KTsKICAgICAgfSAvLyBTZXR1cCBjYW4gY2F1c2UgY2hhbmdlcyB0byBRUHMgd2hpY2ggbmVlZCB0byBiZSBwcm9wb2dhdGVkIGltbWVkaWF0ZWx5IGluCiAgICAgIC8vIHNvbWUgc2l0dWF0aW9ucy4gRXZlbnR1YWxseSwgd2Ugc2hvdWxkIHdvcmsgb24gbWFraW5nIHRoZXNlIGFzeW5jIHNvbWVob3cuCgoKICAgICAgaWYgKHRydWUKICAgICAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgICAgICkgewogICAgICAgICAgKDAsIF9tZXRhbC5mbHVzaEFzeW5jT2JzZXJ2ZXJzKShmYWxzZSk7CiAgICAgICAgfQogICAgfQogICAgLyoKICAgICAgQ2FsbGVkIHdoZW4gYSBxdWVyeSBwYXJhbWV0ZXIgZm9yIHRoaXMgcm91dGUgY2hhbmdlcywgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIHRoZSByb3V0ZQogICAgICBpcyBjdXJyZW50bHkgcGFydCBvZiB0aGUgYWN0aXZlIHJvdXRlIGhpZXJhcmNoeS4gVGhpcyB3aWxsIHVwZGF0ZSB0aGUgcXVlcnkgcGFyYW1ldGVyJ3MKICAgICAgdmFsdWUgaW4gdGhlIGNhY2hlIHNvIGlmIHRoaXMgcm91dGUgYmVjb21lcyBhY3RpdmUsIHRoZSBjYWNoZSB2YWx1ZSBoYXMgYmVlbiB1cGRhdGVkLgogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3FwQ2hhbmdlZCA9IGZ1bmN0aW9uIF9xcENoYW5nZWQocHJvcCwgdmFsdWUsIHFwKSB7CiAgICAgIGlmICghcXApIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gLy8gVXBkYXRlIG1vZGVsLWRlcCBjYWNoZQoKCiAgICAgIHZhciBjYWNoZSA9IHRoaXMuX2J1Y2tldENhY2hlOwogICAgICB2YXIgY2FjaGVLZXkgPSAoMCwgX3V0aWxzMi5jYWxjdWxhdGVDYWNoZUtleSkocXAucm91dGUuZnVsbFJvdXRlTmFtZSwgcXAucGFydHMsIHFwLnZhbHVlcyk7CiAgICAgIGNhY2hlLnN0YXNoKGNhY2hlS2V5LCBwcm9wLCB2YWx1ZSk7CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBob29rIGlzIHRoZSBmaXJzdCBvZiB0aGUgcm91dGUgZW50cnkgdmFsaWRhdGlvbiBob29rcwogICAgICBjYWxsZWQgd2hlbiBhbiBhdHRlbXB0IGlzIG1hZGUgdG8gdHJhbnNpdGlvbiBpbnRvIGEgcm91dGUKICAgICAgb3Igb25lIG9mIGl0cyBjaGlsZHJlbi4gSXQgaXMgY2FsbGVkIGJlZm9yZSBgbW9kZWxgIGFuZAogICAgICBgYWZ0ZXJNb2RlbGAsIGFuZCBpcyBhcHByb3ByaWF0ZSBmb3IgY2FzZXMgd2hlbjoKICAgICAgICAgMSkgQSBkZWNpc2lvbiBjYW4gYmUgbWFkZSB0byByZWRpcmVjdCBlbHNld2hlcmUgd2l0aG91dAogICAgICAgICBuZWVkaW5nIHRvIHJlc29sdmUgdGhlIG1vZGVsIGZpcnN0LgogICAgICAyKSBBbnkgYXN5bmMgb3BlcmF0aW9ucyBuZWVkIHRvIG9jY3VyIGZpcnN0IGJlZm9yZSB0aGUKICAgICAgICAgbW9kZWwgaXMgYXR0ZW1wdGVkIHRvIGJlIHJlc29sdmVkLgogICAgICAgICBUaGlzIGhvb2sgaXMgcHJvdmlkZWQgdGhlIGN1cnJlbnQgYHRyYW5zaXRpb25gIGF0dGVtcHQKICAgICAgYXMgYSBwYXJhbWV0ZXIsIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGAuYWJvcnQoKWAgdGhlIHRyYW5zaXRpb24sCiAgICAgIHNhdmUgaXQgZm9yIGEgbGF0ZXIgYC5yZXRyeSgpYCwgb3IgcmV0cmlldmUgdmFsdWVzIHNldAogICAgICBvbiBpdCBmcm9tIGEgcHJldmlvdXMgaG9vay4gWW91IGNhbiBhbHNvIGp1c3QgY2FsbAogICAgICBgdGhpcy50cmFuc2l0aW9uVG9gIHRvIGFub3RoZXIgcm91dGUgdG8gaW1wbGljaXRseQogICAgICBhYm9ydCB0aGUgYHRyYW5zaXRpb25gLgogICAgICAgICBZb3UgY2FuIHJldHVybiBhIHByb21pc2UgZnJvbSB0aGlzIGhvb2sgdG8gcGF1c2UgdGhlCiAgICAgIHRyYW5zaXRpb24gdW50aWwgdGhlIHByb21pc2UgcmVzb2x2ZXMgKG9yIHJlamVjdHMpLiBUaGlzIGNvdWxkCiAgICAgIGJlIHVzZWZ1bCwgZm9yIGluc3RhbmNlLCBmb3IgcmV0cmlldmluZyBhc3luYyBjb2RlIGZyb20KICAgICAgdGhlIHNlcnZlciB0aGF0IGlzIHJlcXVpcmVkIHRvIGVudGVyIGEgcm91dGUuCiAgICAgICAgIEBtZXRob2QgYmVmb3JlTW9kZWwKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEByZXR1cm4ge2FueSB8IFByb21pc2U8YW55Pn0gaWYgdGhlIHZhbHVlIHJldHVybmVkIGZyb20gdGhpcyBob29rIGlzCiAgICAgICAgYSBwcm9taXNlLCB0aGUgdHJhbnNpdGlvbiB3aWxsIHBhdXNlIHVudGlsIHRoZSB0cmFuc2l0aW9uCiAgICAgICAgcmVzb2x2ZXMuIE90aGVyd2lzZSwgbm9uLXByb21pc2UgcmV0dXJuIHZhbHVlcyBhcmUgbm90CiAgICAgICAgdXRpbGl6ZWQgaW4gYW55IHdheS4KICAgICAgQHNpbmNlIDEuMC4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLmJlZm9yZU1vZGVsID0gZnVuY3Rpb24gYmVmb3JlTW9kZWwoKSB7fQogICAgLyoqCiAgICAgIFRoaXMgaG9vayBpcyBjYWxsZWQgYWZ0ZXIgdGhpcyByb3V0ZSdzIG1vZGVsIGhhcyByZXNvbHZlZC4KICAgICAgSXQgZm9sbG93cyBpZGVudGljYWwgYXN5bmMvcHJvbWlzZSBzZW1hbnRpY3MgdG8gYGJlZm9yZU1vZGVsYAogICAgICBidXQgaXMgcHJvdmlkZWQgdGhlIHJvdXRlJ3MgcmVzb2x2ZWQgbW9kZWwgaW4gYWRkaXRpb24gdG8KICAgICAgdGhlIGB0cmFuc2l0aW9uYCwgYW5kIGlzIHRoZXJlZm9yZSBzdWl0ZWQgdG8gcGVyZm9ybWluZwogICAgICBsb2dpYyB0aGF0IGNhbiBvbmx5IHRha2UgcGxhY2UgYWZ0ZXIgdGhlIG1vZGVsIGhhcyBhbHJlYWR5CiAgICAgIHJlc29sdmVkLgogICAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3RzLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWZ0ZXJNb2RlbChwb3N0cywgdHJhbnNpdGlvbikgewogICAgICAgICAgaWYgKHBvc3RzLmdldCgnbGVuZ3RoJykgPT09IDEpIHsKICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ3Bvc3Quc2hvdycsIHBvc3RzLmdldCgnZmlyc3RPYmplY3QnKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIFJlZmVyIHRvIGRvY3VtZW50YXRpb24gZm9yIGBiZWZvcmVNb2RlbGAgZm9yIGEgZGVzY3JpcHRpb24KICAgICAgb2YgdHJhbnNpdGlvbi1wYXVzaW5nIHNlbWFudGljcyB3aGVuIGEgcHJvbWlzZSBpcyByZXR1cm5lZAogICAgICBmcm9tIHRoaXMgaG9vay4KICAgICAgICAgQG1ldGhvZCBhZnRlck1vZGVsCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZXNvbHZlZE1vZGVsIHRoZSB2YWx1ZSByZXR1cm5lZCBmcm9tIGBtb2RlbGAsCiAgICAgICAgb3IgaXRzIHJlc29sdmVkIHZhbHVlIGlmIGl0IHdhcyBhIHByb21pc2UKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEByZXR1cm4ge2FueSB8IFByb21pc2U8YW55Pn0gaWYgdGhlIHZhbHVlIHJldHVybmVkIGZyb20gdGhpcyBob29rIGlzCiAgICAgICAgYSBwcm9taXNlLCB0aGUgdHJhbnNpdGlvbiB3aWxsIHBhdXNlIHVudGlsIHRoZSB0cmFuc2l0aW9uCiAgICAgICAgcmVzb2x2ZXMuIE90aGVyd2lzZSwgbm9uLXByb21pc2UgcmV0dXJuIHZhbHVlcyBhcmUgbm90CiAgICAgICAgdXRpbGl6ZWQgaW4gYW55IHdheS4KICAgICAgQHNpbmNlIDEuMC4wCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by5hZnRlck1vZGVsID0gZnVuY3Rpb24gYWZ0ZXJNb2RlbCgpIHt9CiAgICAvKioKICAgICAgQSBob29rIHlvdSBjYW4gaW1wbGVtZW50IHRvIG9wdGlvbmFsbHkgcmVkaXJlY3QgdG8gYW5vdGhlciByb3V0ZS4KICAgICAgICAgSWYgeW91IGNhbGwgYHRoaXMudHJhbnNpdGlvblRvYCBmcm9tIGluc2lkZSBvZiB0aGlzIGhvb2ssIHRoaXMgcm91dGUKICAgICAgd2lsbCBub3QgYmUgZW50ZXJlZCBpbiBmYXZvciBvZiB0aGUgb3RoZXIgaG9vay4KICAgICAgICAgYHJlZGlyZWN0YCBhbmQgYGFmdGVyTW9kZWxgIGJlaGF2ZSB2ZXJ5IHNpbWlsYXJseSBhbmQgYXJlCiAgICAgIGNhbGxlZCBhbG1vc3QgYXQgdGhlIHNhbWUgdGltZSwgYnV0IHRoZXkgaGF2ZSBhbiBpbXBvcnRhbnQKICAgICAgZGlzdGluY3Rpb24gaW4gdGhlIGNhc2UgdGhhdCwgZnJvbSBvbmUgb2YgdGhlc2UgaG9va3MsIGEKICAgICAgcmVkaXJlY3QgaW50byBhIGNoaWxkIHJvdXRlIG9mIHRoaXMgcm91dGUgb2NjdXJzOiByZWRpcmVjdHMKICAgICAgZnJvbSBgYWZ0ZXJNb2RlbGAgZXNzZW50aWFsbHkgaW52YWxpZGF0ZSB0aGUgY3VycmVudCBhdHRlbXB0CiAgICAgIHRvIGVudGVyIHRoaXMgcm91dGUsIGFuZCB3aWxsIHJlc3VsdCBpbiB0aGlzIHJvdXRlJ3MgYGJlZm9yZU1vZGVsYCwKICAgICAgYG1vZGVsYCwgYW5kIGBhZnRlck1vZGVsYCBob29rcyBiZWluZyBmaXJlZCBhZ2FpbiB3aXRoaW4KICAgICAgdGhlIG5ldywgcmVkaXJlY3RpbmcgdHJhbnNpdGlvbi4gUmVkaXJlY3RzIHRoYXQgb2NjdXIgd2l0aGluCiAgICAgIHRoZSBgcmVkaXJlY3RgIGhvb2ssIG9uIHRoZSBvdGhlciBoYW5kLCB3aWxsIF9ub3RfIGNhdXNlCiAgICAgIHRoZXNlIGhvb2tzIHRvIGJlIGZpcmVkIGFnYWluIHRoZSBzZWNvbmQgdGltZSBhcm91bmQ7IGluCiAgICAgIG90aGVyIHdvcmRzLCBieSB0aGUgdGltZSB0aGUgYHJlZGlyZWN0YCBob29rIGhhcyBiZWVuIGNhbGxlZCwKICAgICAgYm90aCB0aGUgcmVzb2x2ZWQgbW9kZWwgYW5kIGF0dGVtcHRlZCBlbnRyeSBpbnRvIHRoaXMgcm91dGUKICAgICAgYXJlIGNvbnNpZGVyZWQgdG8gYmUgZnVsbHkgdmFsaWRhdGVkLgogICAgICAgICBAbWV0aG9kIHJlZGlyZWN0CiAgICAgIEBwYXJhbSB7T2JqZWN0fSBtb2RlbCB0aGUgbW9kZWwgZm9yIHRoaXMgcm91dGUKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uIHRoZSB0cmFuc2l0aW9uIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIGN1cnJlbnQgdHJhbnNpdGlvbgogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVkaXJlY3QgPSBmdW5jdGlvbiByZWRpcmVjdCgpIHt9CiAgICAvKioKICAgICAgQ2FsbGVkIHdoZW4gdGhlIGNvbnRleHQgaXMgY2hhbmdlZCBieSByb3V0ZXIuanMuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgY29udGV4dERpZENoYW5nZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uY29udGV4dERpZENoYW5nZSA9IGZ1bmN0aW9uIGNvbnRleHREaWRDaGFuZ2UoKSB7CiAgICAgIHRoaXMuY3VycmVudE1vZGVsID0gdGhpcy5jb250ZXh0OwogICAgfQogICAgLyoqCiAgICAgIEEgaG9vayB5b3UgY2FuIGltcGxlbWVudCB0byBjb252ZXJ0IHRoZSBVUkwgaW50byB0aGUgbW9kZWwgZm9yCiAgICAgIHRoaXMgcm91dGUuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgLy8gLi4uCiAgICAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgncG9zdCcsIHsgcGF0aDogJy9wb3N0cy86cG9zdF9pZCcgfSk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBUaGUgbW9kZWwgZm9yIHRoZSBgcG9zdGAgcm91dGUgaXMgYHN0b3JlLmZpbmRSZWNvcmQoJ3Bvc3QnLCBwYXJhbXMucG9zdF9pZClgLgogICAgICAgICBCeSBkZWZhdWx0LCBpZiB5b3VyIHJvdXRlIGhhcyBhIGR5bmFtaWMgc2VnbWVudCBlbmRpbmcgaW4gYF9pZGA6CiAgICAgICAgICogVGhlIG1vZGVsIGNsYXNzIGlzIGRldGVybWluZWQgZnJvbSB0aGUgc2VnbWVudCAoYHBvc3RfaWRgJ3MKICAgICAgICBjbGFzcyBpcyBgQXBwLlBvc3RgKQogICAgICAqIFRoZSBmaW5kIG1ldGhvZCBpcyBjYWxsZWQgb24gdGhlIG1vZGVsIGNsYXNzIHdpdGggdGhlIHZhbHVlIG9mCiAgICAgICAgdGhlIGR5bmFtaWMgc2VnbWVudC4KICAgICAgICAgTm90ZSB0aGF0IGZvciByb3V0ZXMgd2l0aCBkeW5hbWljIHNlZ21lbnRzLCB0aGlzIGhvb2sgaXMgbm90IGFsd2F5cwogICAgICBleGVjdXRlZC4gSWYgdGhlIHJvdXRlIGlzIGVudGVyZWQgdGhyb3VnaCBhIHRyYW5zaXRpb24gKGUuZy4gd2hlbgogICAgICB1c2luZyB0aGUgYGxpbmstdG9gIEhhbmRsZWJhcnMgaGVscGVyIG9yIHRoZSBgdHJhbnNpdGlvblRvYCBtZXRob2QKICAgICAgb2Ygcm91dGVzKSwgYW5kIGEgbW9kZWwgY29udGV4dCBpcyBhbHJlYWR5IHByb3ZpZGVkIHRoaXMgaG9vawogICAgICBpcyBub3QgY2FsbGVkLgogICAgICAgICBBIG1vZGVsIGNvbnRleHQgZG9lcyBub3QgaW5jbHVkZSBhIHByaW1pdGl2ZSBzdHJpbmcgb3IgbnVtYmVyLAogICAgICB3aGljaCBkb2VzIGNhdXNlIHRoZSBtb2RlbCBob29rIHRvIGJlIGNhbGxlZC4KICAgICAgICAgUm91dGVzIHdpdGhvdXQgZHluYW1pYyBzZWdtZW50cyB3aWxsIGFsd2F5cyBleGVjdXRlIHRoZSBtb2RlbCBob29rLgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIC8vIG5vIGR5bmFtaWMgc2VnbWVudCwgbW9kZWwgaG9vayBhbHdheXMgY2FsbGVkCiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCdwb3N0cycpOwogICAgICAgICAvLyBtb2RlbCBwYXNzZWQgaW4sIHNvIG1vZGVsIGhvb2sgbm90IGNhbGxlZAogICAgICB0aGVQb3N0ID0gc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIDEpOwogICAgICB0aGlzLnRyYW5zaXRpb25UbygncG9zdCcsIHRoZVBvc3QpOwogICAgICAgICAvLyBpbnRlZ2VyIHBhc3NlZCBpbiwgbW9kZWwgaG9vayBpcyBjYWxsZWQKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ3Bvc3QnLCAxKTsKICAgICAgICAgLy8gbW9kZWwgaWQgcGFzc2VkIGluLCBtb2RlbCBob29rIGlzIGNhbGxlZAogICAgICAvLyB1c2VmdWwgZm9yIGZvcmNpbmcgdGhlIGhvb2sgdG8gZXhlY3V0ZQogICAgICB0aGVQb3N0ID0gc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIDEpOwogICAgICB0aGlzLnRyYW5zaXRpb25UbygncG9zdCcsIHRoZVBvc3QuaWQpOwogICAgICBgYGAKICAgICAgICAgVGhpcyBob29rIGZvbGxvd3MgdGhlIGFzeW5jaHJvbm91cy9wcm9taXNlIHNlbWFudGljcwogICAgICBkZXNjcmliZWQgaW4gdGhlIGRvY3VtZW50YXRpb24gZm9yIGBiZWZvcmVNb2RlbGAuIEluIHBhcnRpY3VsYXIsCiAgICAgIGlmIGEgcHJvbWlzZSByZXR1cm5lZCBmcm9tIGBtb2RlbGAgZmFpbHMsIHRoZSBlcnJvciB3aWxsIGJlCiAgICAgIGhhbmRsZWQgYnkgdGhlIGBlcnJvcmAgaG9vayBvbiBgUm91dGVgLgogICAgICAgICBFeGFtcGxlCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIG1vZGVsKHBhcmFtcykgewogICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIHBhcmFtcy5wb3N0X2lkKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBtb2RlbAogICAgICBAcGFyYW0ge09iamVjdH0gcGFyYW1zIHRoZSBwYXJhbWV0ZXJzIGV4dHJhY3RlZCBmcm9tIHRoZSBVUkwKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEByZXR1cm4ge2FueSB8IFByb21pc2U8YW55Pn0gdGhlIG1vZGVsIGZvciB0aGlzIHJvdXRlLiBJZgogICAgICAgIGEgcHJvbWlzZSBpcyByZXR1cm5lZCwgdGhlIHRyYW5zaXRpb24gd2lsbCBwYXVzZSB1bnRpbAogICAgICAgIHRoZSBwcm9taXNlIHJlc29sdmVzLCBhbmQgdGhlIHJlc29sdmVkIHZhbHVlIG9mIHRoZSBwcm9taXNlCiAgICAgICAgd2lsbCBiZSB1c2VkIGFzIHRoZSBtb2RlbCBmb3IgdGhpcyByb3V0ZS4KICAgICAgQHNpbmNlIDEuMC4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLm1vZGVsID0gZnVuY3Rpb24gbW9kZWwocGFyYW1zLCB0cmFuc2l0aW9uKSB7CiAgICAgIHZhciBuYW1lLCBzYXdQYXJhbXMsIHZhbHVlOwogICAgICB2YXIgcXVlcnlQYXJhbXMgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ19xcC5tYXAnKTsKCiAgICAgIGZvciAodmFyIHByb3AgaW4gcGFyYW1zKSB7CiAgICAgICAgaWYgKHByb3AgPT09ICdxdWVyeVBhcmFtcycgfHwgcXVlcnlQYXJhbXMgJiYgcHJvcCBpbiBxdWVyeVBhcmFtcykgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICB2YXIgbWF0Y2ggPSBwcm9wLm1hdGNoKC9eKC4qKV9pZCQvKTsKCiAgICAgICAgaWYgKG1hdGNoICE9PSBudWxsKSB7CiAgICAgICAgICBuYW1lID0gbWF0Y2hbMV07CiAgICAgICAgICB2YWx1ZSA9IHBhcmFtc1twcm9wXTsKICAgICAgICB9CgogICAgICAgIHNhd1BhcmFtcyA9IHRydWU7CiAgICAgIH0KCiAgICAgIGlmICghbmFtZSkgewogICAgICAgIGlmIChzYXdQYXJhbXMpIHsKICAgICAgICAgIHJldHVybiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBwYXJhbXMpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAodHJhbnNpdGlvbi5yZXNvbHZlSW5kZXggPCAxKSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KCiAgICAgICAgICByZXR1cm4gdHJhbnNpdGlvbltfcm91dGVyX2pzLlNUQVRFX1NZTUJPTF0ucm91dGVJbmZvc1t0cmFuc2l0aW9uLnJlc29sdmVJbmRleCAtIDFdLmNvbnRleHQ7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5maW5kTW9kZWwobmFtZSwgdmFsdWUpOwogICAgfQogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZGVzZXJpYWxpemUKICAgICAgQHBhcmFtIHtPYmplY3R9IHBhcmFtcyB0aGUgcGFyYW1ldGVycyBleHRyYWN0ZWQgZnJvbSB0aGUgVVJMCiAgICAgIEBwYXJhbSB7VHJhbnNpdGlvbn0gdHJhbnNpdGlvbgogICAgICBAcmV0dXJuIHthbnkgfCBQcm9taXNlPGFueT59IHRoZSBtb2RlbCBmb3IgdGhpcyByb3V0ZS4KICAgICAgICAgUm91dGVyLmpzIGhvb2suCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZGVzZXJpYWxpemUgPSBmdW5jdGlvbiBkZXNlcmlhbGl6ZShfcGFyYW1zLCB0cmFuc2l0aW9uKSB7CiAgICAgIHJldHVybiB0aGlzLm1vZGVsKHRoaXMuX3BhcmFtc0Zvcih0aGlzLnJvdXRlTmFtZSwgX3BhcmFtcyksIHRyYW5zaXRpb24pOwogICAgfQogICAgLyoqCiAgICAgICAgIEBtZXRob2QgZmluZE1vZGVsCiAgICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlIHRoZSBtb2RlbCB0eXBlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZSB0aGUgdmFsdWUgcGFzc2VkIHRvIGZpbmQKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmZpbmRNb2RlbCA9IGZ1bmN0aW9uIGZpbmRNb2RlbCgpIHsKICAgICAgdmFyIF9nZXQ7CgogICAgICByZXR1cm4gKF9nZXQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ3N0b3JlJykpLmZpbmQuYXBwbHkoX2dldCwgYXJndW1lbnRzKTsKICAgIH0KICAgIC8qKgogICAgICBBIGhvb2sgeW91IGNhbiB1c2UgdG8gc2V0dXAgdGhlIGNvbnRyb2xsZXIgZm9yIHRoZSBjdXJyZW50IHJvdXRlLgogICAgICAgICBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgd2l0aCB0aGUgY29udHJvbGxlciBmb3IgdGhlIGN1cnJlbnQgcm91dGUgYW5kIHRoZQogICAgICBtb2RlbCBzdXBwbGllZCBieSB0aGUgYG1vZGVsYCBob29rLgogICAgICAgICBCeSBkZWZhdWx0LCB0aGUgYHNldHVwQ29udHJvbGxlcmAgaG9vayBzZXRzIHRoZSBgbW9kZWxgIHByb3BlcnR5IG9mCiAgICAgIHRoZSBjb250cm9sbGVyIHRvIHRoZSBzcGVjaWZpZWQgYG1vZGVsYCB3aGVuIGl0IGlzIG5vdCBgdW5kZWZpbmVkYC4KICAgICAgICAgSWYgeW91IGltcGxlbWVudCB0aGUgYHNldHVwQ29udHJvbGxlcmAgaG9vayBpbiB5b3VyIFJvdXRlLCBpdCB3aWxsCiAgICAgIHByZXZlbnQgdGhpcyBkZWZhdWx0IGJlaGF2aW9yLiBJZiB5b3Ugd2FudCB0byBwcmVzZXJ2ZSB0aGF0IGJlaGF2aW9yCiAgICAgIHdoZW4gaW1wbGVtZW50aW5nIHlvdXIgYHNldHVwQ29udHJvbGxlcmAgZnVuY3Rpb24sIG1ha2Ugc3VyZSB0byBjYWxsCiAgICAgIGBfc3VwZXJgOgogICAgICAgICBgYGBhcHAvcm91dGVzL3Bob3Rvcy5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIG1vZGVsKCkgewogICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZmluZEFsbCgncGhvdG8nKTsKICAgICAgICB9LAogICAgICAgICAgIHNldHVwQ29udHJvbGxlcihjb250cm9sbGVyLCBtb2RlbCkgewogICAgICAgICAgLy8gQ2FsbCBfc3VwZXIgZm9yIGRlZmF1bHQgYmVoYXZpb3IKICAgICAgICAgIHRoaXMuX3N1cGVyKGNvbnRyb2xsZXIsIG1vZGVsKTsKICAgICAgICAgIC8vIEltcGxlbWVudCB5b3VyIGN1c3RvbSBzZXR1cCBhZnRlcgogICAgICAgICAgdGhpcy5jb250cm9sbGVyRm9yKCdhcHBsaWNhdGlvbicpLnNldCgnc2hvd2luZ1Bob3RvcycsIHRydWUpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBUaGUgcHJvdmlkZWQgY29udHJvbGxlciB3aWxsIGJlIG9uZSByZXNvbHZlZCBiYXNlZCBvbiB0aGUgbmFtZQogICAgICBvZiB0aGlzIHJvdXRlLgogICAgICAgICBJZiBubyBleHBsaWNpdCBjb250cm9sbGVyIGlzIGRlZmluZWQsIEVtYmVyIHdpbGwgYXV0b21hdGljYWxseSBjcmVhdGUgb25lLgogICAgICAgICBBcyBhbiBleGFtcGxlLCBjb25zaWRlciB0aGUgcm91dGVyOgogICAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgIC8vIC4uLgogICAgICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoJ3Bvc3QnLCB7IHBhdGg6ICcvcG9zdHMvOnBvc3RfaWQnIH0pOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgRm9yIHRoZSBgcG9zdGAgcm91dGUsIGEgY29udHJvbGxlciBuYW1lZCBgQXBwLlBvc3RDb250cm9sbGVyYCB3b3VsZAogICAgICBiZSB1c2VkIGlmIGl0IGlzIGRlZmluZWQuIElmIGl0IGlzIG5vdCBkZWZpbmVkLCBhIGJhc2ljIGBDb250cm9sbGVyYAogICAgICBpbnN0YW5jZSB3b3VsZCBiZSB1c2VkLgogICAgICAgICBFeGFtcGxlCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIHNldHVwQ29udHJvbGxlcihjb250cm9sbGVyLCBtb2RlbCkgewogICAgICAgICAgY29udHJvbGxlci5zZXQoJ21vZGVsJywgbW9kZWwpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHNldHVwQ29udHJvbGxlcgogICAgICBAcGFyYW0ge0NvbnRyb2xsZXJ9IGNvbnRyb2xsZXIgaW5zdGFuY2UKICAgICAgQHBhcmFtIHtPYmplY3R9IG1vZGVsCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5zZXR1cENvbnRyb2xsZXIgPSBmdW5jdGlvbiBzZXR1cENvbnRyb2xsZXIoY29udHJvbGxlciwgY29udGV4dCwgX3RyYW5zaXRpb24pIHsKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFycwogICAgICBpZiAoY29udHJvbGxlciAmJiBjb250ZXh0ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAoMCwgX21ldGFsLnNldCkoY29udHJvbGxlciwgJ21vZGVsJywgY29udGV4dCk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSBjb250cm9sbGVyIG9mIHRoZSBjdXJyZW50IHJvdXRlLCBvciBhIHBhcmVudCAob3IgYW55IGFuY2VzdG9yKQogICAgICByb3V0ZSBpbiBhIHJvdXRlIGhpZXJhcmNoeS4KICAgICAgICAgVGhlIGNvbnRyb2xsZXIgaW5zdGFuY2UgbXVzdCBhbHJlYWR5IGhhdmUgYmVlbiBjcmVhdGVkLCBlaXRoZXIgdGhyb3VnaCBlbnRlcmluZyB0aGUKICAgICAgYXNzb2NpYXRlZCByb3V0ZSBvciB1c2luZyBgZ2VuZXJhdGVDb250cm9sbGVyYC4KICAgICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgc2V0dXBDb250cm9sbGVyKGNvbnRyb2xsZXIsIHBvc3QpIHsKICAgICAgICAgIHRoaXMuX3N1cGVyKGNvbnRyb2xsZXIsIHBvc3QpOwogICAgICAgICAgdGhpcy5jb250cm9sbGVyRm9yKCdwb3N0cycpLnNldCgnY3VycmVudFBvc3QnLCBwb3N0KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBjb250cm9sbGVyRm9yCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZSBvciBjb250cm9sbGVyCiAgICAgIEByZXR1cm4ge0NvbnRyb2xsZXJ9CiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5jb250cm9sbGVyRm9yID0gZnVuY3Rpb24gY29udHJvbGxlckZvcihuYW1lLCBfc2tpcEFzc2VydCkgewogICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKTsKICAgICAgdmFyIHJvdXRlID0gb3duZXIubG9va3VwKCJyb3V0ZToiICsgbmFtZSk7CgogICAgICBpZiAocm91dGUgJiYgcm91dGUuY29udHJvbGxlck5hbWUpIHsKICAgICAgICBuYW1lID0gcm91dGUuY29udHJvbGxlck5hbWU7CiAgICAgIH0KCiAgICAgIHZhciBjb250cm9sbGVyID0gb3duZXIubG9va3VwKCJjb250cm9sbGVyOiIgKyBuYW1lKTsgLy8gTk9URTogV2UncmUgc3BlY2lmaWNhbGx5IGNoZWNraW5nIHRoYXQgc2tpcEFzc2VydCBpcyB0cnVlLCBiZWNhdXNlIGFjY29yZGluZwogICAgICAvLyAgIHRvIHRoZSBvbGQgQVBJIHRoZSBzZWNvbmQgcGFyYW1ldGVyIHdhcyBtb2RlbC4gV2UgZG8gbm90IHdhbnQgcGVvcGxlIHdobwogICAgICAvLyAgIHBhc3NlZCBhIG1vZGVsIHRvIHNraXAgdGhlIGFzc2VydGlvbi4KCiAgICAgIChmYWxzZSAmJiAhKGNvbnRyb2xsZXIgIT09IHVuZGVmaW5lZCB8fCBfc2tpcEFzc2VydCA9PT0gdHJ1ZSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgY29udHJvbGxlciBuYW1lZCAnIiArIG5hbWUgKyAiJyBjb3VsZCBub3QgYmUgZm91bmQuIE1ha2Ugc3VyZSB0aGF0IHRoaXMgcm91dGUgZXhpc3RzIGFuZCBoYXMgYWxyZWFkeSBiZWVuIGVudGVyZWQgYXQgbGVhc3Qgb25jZS4gSWYgeW91IGFyZSBhY2Nlc3NpbmcgYSBjb250cm9sbGVyIG5vdCBhc3NvY2lhdGVkIHdpdGggYSByb3V0ZSwgbWFrZSBzdXJlIHRoZSBjb250cm9sbGVyIGNsYXNzIGlzIGV4cGxpY2l0bHkgZGVmaW5lZC4iLCBjb250cm9sbGVyICE9PSB1bmRlZmluZWQgfHwgX3NraXBBc3NlcnQgPT09IHRydWUpKTsKICAgICAgcmV0dXJuIGNvbnRyb2xsZXI7CiAgICB9CiAgICAvKioKICAgICAgR2VuZXJhdGVzIGEgY29udHJvbGxlciBmb3IgYSByb3V0ZS4KICAgICAgICAgRXhhbXBsZQogICAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3QuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBzZXR1cENvbnRyb2xsZXIoY29udHJvbGxlciwgcG9zdCkgewogICAgICAgICAgdGhpcy5fc3VwZXIoY29udHJvbGxlciwgcG9zdCk7CiAgICAgICAgICB0aGlzLmdlbmVyYXRlQ29udHJvbGxlcigncG9zdHMnKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBnZW5lcmF0ZUNvbnRyb2xsZXIKICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIGNvbnRyb2xsZXIKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmdlbmVyYXRlQ29udHJvbGxlciA9IGZ1bmN0aW9uIGdlbmVyYXRlQ29udHJvbGxlcihuYW1lKSB7CiAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICByZXR1cm4gKDAsIF9nZW5lcmF0ZV9jb250cm9sbGVyLmRlZmF1bHQpKG93bmVyLCBuYW1lKTsKICAgIH0KICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSByZXNvbHZlZCBtb2RlbCBvZiBhIHBhcmVudCAob3IgYW55IGFuY2VzdG9yKSByb3V0ZQogICAgICBpbiBhIHJvdXRlIGhpZXJhcmNoeS4gIER1cmluZyBhIHRyYW5zaXRpb24sIGFsbCByb3V0ZXMKICAgICAgbXVzdCByZXNvbHZlIGEgbW9kZWwgb2JqZWN0LCBhbmQgaWYgYSByb3V0ZQogICAgICBuZWVkcyBhY2Nlc3MgdG8gYSBwYXJlbnQgcm91dGUncyBtb2RlbCBpbiBvcmRlciB0bwogICAgICByZXNvbHZlIGEgbW9kZWwgKG9yIGp1c3QgcmV1c2UgdGhlIG1vZGVsIGZyb20gYSBwYXJlbnQpLAogICAgICBpdCBjYW4gY2FsbCBgdGhpcy5tb2RlbEZvcih0aGVOYW1lT2ZQYXJlbnRSb3V0ZSlgIHRvCiAgICAgIHJldHJpZXZlIGl0LiBJZiB0aGUgYW5jZXN0b3Igcm91dGUncyBtb2RlbCB3YXMgYSBwcm9taXNlLAogICAgICBpdHMgcmVzb2x2ZWQgcmVzdWx0IGlzIHJldHVybmVkLgogICAgICAgICBFeGFtcGxlCiAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgLy8gLi4uCiAgICAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgncG9zdCcsIHsgcGF0aDogJy9wb3N0cy86cG9zdF9pZCcgfSwgZnVuY3Rpb24oKSB7CiAgICAgICAgICB0aGlzLnJvdXRlKCdjb21tZW50cycpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0L2NvbW1lbnRzLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgbW9kZWwoKSB7CiAgICAgICAgICBsZXQgcG9zdCA9IHRoaXMubW9kZWxGb3IoJ3Bvc3QnKTsKICAgICAgICAgIHJldHVybiBwb3N0LmdldCgnY29tbWVudHMnKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBtb2RlbEZvcgogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSB0aGUgbmFtZSBvZiB0aGUgcm91dGUKICAgICAgQHJldHVybiB7T2JqZWN0fSB0aGUgbW9kZWwgb2JqZWN0CiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5tb2RlbEZvciA9IGZ1bmN0aW9uIG1vZGVsRm9yKF9uYW1lKSB7CiAgICAgIHZhciBuYW1lOwogICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKTsKICAgICAgdmFyIHRyYW5zaXRpb24gPSB0aGlzLl9yb3V0ZXIgJiYgdGhpcy5fcm91dGVyLl9yb3V0ZXJNaWNyb2xpYiA/IHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWIuYWN0aXZlVHJhbnNpdGlvbiA6IHVuZGVmaW5lZDsgLy8gT25seSBjaGFuZ2UgdGhlIHJvdXRlIG5hbWUgd2hlbiB0aGVyZSBpcyBhbiBhY3RpdmUgdHJhbnNpdGlvbi4KICAgICAgLy8gT3RoZXJ3aXNlLCB1c2UgdGhlIHBhc3NlZCBpbiByb3V0ZSBuYW1lLgoKICAgICAgaWYgKG93bmVyLnJvdXRhYmxlICYmIHRyYW5zaXRpb24gIT09IHVuZGVmaW5lZCkgewogICAgICAgIG5hbWUgPSBnZXRFbmdpbmVSb3V0ZU5hbWUob3duZXIsIF9uYW1lKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBuYW1lID0gX25hbWU7CiAgICAgIH0KCiAgICAgIHZhciByb3V0ZSA9IG93bmVyLmxvb2t1cCgicm91dGU6IiArIG5hbWUpOyAvLyBJZiB3ZSBhcmUgbWlkLXRyYW5zaXRpb24sIHdlIHdhbnQgdG8gdHJ5IGFuZCBsb29rIHVwCiAgICAgIC8vIHJlc29sdmVkIHBhcmVudCBjb250ZXh0cyBvbiB0aGUgY3VycmVudCB0cmFuc2l0aW9uRXZlbnQuCgogICAgICBpZiAodHJhbnNpdGlvbiAhPT0gdW5kZWZpbmVkICYmIHRyYW5zaXRpb24gIT09IG51bGwpIHsKICAgICAgICB2YXIgbW9kZWxMb29rdXBOYW1lID0gcm91dGUgJiYgcm91dGUucm91dGVOYW1lIHx8IG5hbWU7CgogICAgICAgIGlmICh0cmFuc2l0aW9uLnJlc29sdmVkTW9kZWxzLmhhc093blByb3BlcnR5KG1vZGVsTG9va3VwTmFtZSkpIHsKICAgICAgICAgIHJldHVybiB0cmFuc2l0aW9uLnJlc29sdmVkTW9kZWxzW21vZGVsTG9va3VwTmFtZV07CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gcm91dGUgJiYgcm91dGUuY3VycmVudE1vZGVsOwogICAgfQogICAgLyoqCiAgICAgIEEgaG9vayB5b3UgY2FuIHVzZSB0byByZW5kZXIgdGhlIHRlbXBsYXRlIGZvciB0aGUgY3VycmVudCByb3V0ZS4KICAgICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIHdpdGggdGhlIGNvbnRyb2xsZXIgZm9yIHRoZSBjdXJyZW50IHJvdXRlIGFuZCB0aGUKICAgICAgbW9kZWwgc3VwcGxpZWQgYnkgdGhlIGBtb2RlbGAgaG9vay4gQnkgZGVmYXVsdCwgaXQgcmVuZGVycyB0aGUgcm91dGUncwogICAgICB0ZW1wbGF0ZSwgY29uZmlndXJlZCB3aXRoIHRoZSBjb250cm9sbGVyIGZvciB0aGUgcm91dGUuCiAgICAgICAgIFRoaXMgbWV0aG9kIGNhbiBiZSBvdmVycmlkZGVuIHRvIHNldCB1cCBhbmQgcmVuZGVyIGFkZGl0aW9uYWwgb3IKICAgICAgYWx0ZXJuYXRpdmUgdGVtcGxhdGVzLgogICAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3RzLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgcmVuZGVyVGVtcGxhdGUoY29udHJvbGxlciwgbW9kZWwpIHsKICAgICAgICAgIGxldCBmYXZDb250cm9sbGVyID0gdGhpcy5jb250cm9sbGVyRm9yKCdmYXZvcml0ZVBvc3QnKTsKICAgICAgICAgICAgIC8vIFJlbmRlciB0aGUgYGZhdm9yaXRlUG9zdGAgdGVtcGxhdGUgaW50bwogICAgICAgICAgLy8gdGhlIG91dGxldCBgcG9zdHNgLCBhbmQgZGlzcGxheSB0aGUgYGZhdm9yaXRlUG9zdGAKICAgICAgICAgIC8vIGNvbnRyb2xsZXIuCiAgICAgICAgICB0aGlzLnJlbmRlcignZmF2b3JpdGVQb3N0JywgewogICAgICAgICAgICBvdXRsZXQ6ICdwb3N0cycsCiAgICAgICAgICAgIGNvbnRyb2xsZXI6IGZhdkNvbnRyb2xsZXIKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHJlbmRlclRlbXBsYXRlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBjb250cm9sbGVyIHRoZSByb3V0ZSdzIGNvbnRyb2xsZXIKICAgICAgQHBhcmFtIHtPYmplY3R9IG1vZGVsIHRoZSByb3V0ZSdzIG1vZGVsCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5yZW5kZXJUZW1wbGF0ZSA9IGZ1bmN0aW9uIHJlbmRlclRlbXBsYXRlKF9jb250cm9sbGVyLCBfbW9kZWwpIHsKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFycwogICAgICB0aGlzLnJlbmRlcigpOwogICAgfQogICAgLyoqCiAgICAgIGByZW5kZXJgIGlzIHVzZWQgdG8gcmVuZGVyIGEgdGVtcGxhdGUgaW50byBhIHJlZ2lvbiBvZiBhbm90aGVyIHRlbXBsYXRlCiAgICAgIChpbmRpY2F0ZWQgYnkgYW4gYHt7b3V0bGV0fX1gKS4gYHJlbmRlcmAgaXMgdXNlZCBib3RoIGR1cmluZyB0aGUgZW50cnkKICAgICAgcGhhc2Ugb2Ygcm91dGluZyAodmlhIHRoZSBgcmVuZGVyVGVtcGxhdGVgIGhvb2spIGFuZCBsYXRlciBpbiByZXNwb25zZSB0bwogICAgICB1c2VyIGludGVyYWN0aW9uLgogICAgICAgICBGb3IgZXhhbXBsZSwgZ2l2ZW4gdGhlIGZvbGxvd2luZyBtaW5pbWFsIHJvdXRlciBhbmQgdGVtcGxhdGVzOgogICAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgIC8vIC4uLgogICAgICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoJ3Bob3RvcycpOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgYGBgaGFuZGxlYmFycwogICAgICA8IS0tIGFwcGxpY2F0aW9uLmhicyAtLT4KICAgICAgPGRpdiBjbGFzcz0nc29tZXRoaW5nLWluLXRoZS1hcHAtaGJzJz4KICAgICAgICB7e291dGxldCAiYW5PdXRsZXROYW1lIn19CiAgICAgIDwvZGl2PgogICAgICBgYGAKICAgICAgICAgYGBgaGFuZGxlYmFycwogICAgICA8IS0tIHBob3Rvcy5oYnMgLS0+CiAgICAgIDxoMT5QaG90b3M8L2gxPgogICAgICBgYGAKICAgICAgICAgWW91IGNhbiByZW5kZXIgYHBob3Rvcy5oYnNgIGludG8gdGhlIGAiYW5PdXRsZXROYW1lImAgb3V0bGV0IG9mCiAgICAgIGBhcHBsaWNhdGlvbi5oYnNgIGJ5IGNhbGxpbmcgYHJlbmRlcmA6CiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIHJlbmRlclRlbXBsYXRlKCkgewogICAgICAgICAgdGhpcy5yZW5kZXIoJ3Bob3RvcycsIHsKICAgICAgICAgICAgaW50bzogJ2FwcGxpY2F0aW9uJywKICAgICAgICAgICAgb3V0bGV0OiAnYW5PdXRsZXROYW1lJwogICAgICAgICAgfSkKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgYHJlbmRlcmAgYWRkaXRpb25hbGx5IGFsbG93cyB5b3UgdG8gc3VwcGx5IHdoaWNoIGBjb250cm9sbGVyYCBhbmQKICAgICAgYG1vZGVsYCBvYmplY3RzIHNob3VsZCBiZSBsb2FkZWQgYW5kIGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVuZGVyZWQgdGVtcGxhdGUuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdHMuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICByZW5kZXJUZW1wbGF0ZShjb250cm9sbGVyLCBtb2RlbCl7CiAgICAgICAgICB0aGlzLnJlbmRlcigncG9zdHMnLCB7ICAgIC8vIHRoZSB0ZW1wbGF0ZSB0byByZW5kZXIsIHJlZmVyZW5jZWQgYnkgbmFtZQogICAgICAgICAgICBpbnRvOiAnYXBwbGljYXRpb24nLCAgICAvLyB0aGUgdGVtcGxhdGUgdG8gcmVuZGVyIGludG8sIHJlZmVyZW5jZWQgYnkgbmFtZQogICAgICAgICAgICBvdXRsZXQ6ICdhbk91dGxldE5hbWUnLCAvLyB0aGUgb3V0bGV0IGluc2lkZSBgb3B0aW9ucy5pbnRvYCB0byByZW5kZXIgaW50by4KICAgICAgICAgICAgY29udHJvbGxlcjogJ3NvbWVDb250cm9sbGVyTmFtZScsIC8vIHRoZSBjb250cm9sbGVyIHRvIHVzZSBmb3IgdGhpcyB0ZW1wbGF0ZSwgcmVmZXJlbmNlZCBieSBuYW1lCiAgICAgICAgICAgIG1vZGVsOiBtb2RlbCAgICAgICAgICAgIC8vIHRoZSBtb2RlbCB0byBzZXQgb24gYG9wdGlvbnMuY29udHJvbGxlcmAuCiAgICAgICAgICB9KQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBUaGUgc3RyaW5nIHZhbHVlcyBwcm92aWRlZCBmb3IgdGhlIHRlbXBsYXRlIG5hbWUsIGFuZCBjb250cm9sbGVyCiAgICAgIHdpbGwgZXZlbnR1YWxseSBwYXNzIHRocm91Z2ggdG8gdGhlIHJlc29sdmVyIGZvciBsb29rdXAuIFNlZQogICAgICBSZXNvbHZlciBmb3IgaG93IHRoZXNlIGFyZSBtYXBwZWQgdG8gSmF2YVNjcmlwdCBvYmplY3RzIGluIHlvdXIKICAgICAgYXBwbGljYXRpb24uIFRoZSB0ZW1wbGF0ZSB0byByZW5kZXIgaW50byBuZWVkcyB0byBiZSByZWxhdGVkIHRvICBlaXRoZXIgdGhlCiAgICAgIGN1cnJlbnQgcm91dGUgb3Igb25lIG9mIGl0cyBhbmNlc3RvcnMuCiAgICAgICAgIE5vdCBhbGwgb3B0aW9ucyBuZWVkIHRvIGJlIHBhc3NlZCB0byBgcmVuZGVyYC4gRGVmYXVsdCB2YWx1ZXMgd2lsbCBiZSB1c2VkCiAgICAgIGJhc2VkIG9uIHRoZSBuYW1lIG9mIHRoZSByb3V0ZSBzcGVjaWZpZWQgaW4gdGhlIHJvdXRlciBvciB0aGUgUm91dGUncwogICAgICBgY29udHJvbGxlck5hbWVgIGFuZCBgdGVtcGxhdGVOYW1lYCBwcm9wZXJ0aWVzLgogICAgICAgICBGb3IgZXhhbXBsZToKICAgICAgICAgYGBgYXBwL3JvdXRlci5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdpbmRleCcpOwogICAgICAgIHRoaXMucm91dGUoJ3Bvc3QnLCB7IHBhdGg6ICcvcG9zdHMvOnBvc3RfaWQnIH0pOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgcmVuZGVyVGVtcGxhdGUoKSB7CiAgICAgICAgICB0aGlzLnJlbmRlcigpOyAvLyBhbGwgZGVmYXVsdHMgYXBwbHkKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgVGhlIG5hbWUgb2YgdGhlIHJvdXRlLCBkZWZpbmVkIGJ5IHRoZSByb3V0ZXIsIGlzIGBwb3N0YC4KICAgICAgICAgVGhlIGZvbGxvd2luZyBlcXVpdmFsZW50IGRlZmF1bHQgb3B0aW9ucyB3aWxsIGJlIGFwcGxpZWQgd2hlbgogICAgICB0aGUgUm91dGUgY2FsbHMgYHJlbmRlcmA6CiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgdGhpcy5yZW5kZXIoJ3Bvc3QnLCB7ICAvLyB0aGUgdGVtcGxhdGUgbmFtZSBhc3NvY2lhdGVkIHdpdGggJ3Bvc3QnIFJvdXRlCiAgICAgICAgaW50bzogJ2FwcGxpY2F0aW9uJywgLy8gdGhlIHBhcmVudCByb3V0ZSB0byAncG9zdCcgUm91dGUKICAgICAgICBvdXRsZXQ6ICdtYWluJywgICAgICAvLyB7e291dGxldH19IGFuZCB7e291dGxldCAnbWFpbid9fSBhcmUgc3lub255bW91cywKICAgICAgICBjb250cm9sbGVyOiAncG9zdCcsICAvLyB0aGUgY29udHJvbGxlciBhc3NvY2lhdGVkIHdpdGggdGhlICdwb3N0JyBSb3V0ZQogICAgICB9KQogICAgICBgYGAKICAgICAgICAgQnkgZGVmYXVsdCB0aGUgY29udHJvbGxlcidzIGBtb2RlbGAgd2lsbCBiZSB0aGUgcm91dGUncyBtb2RlbCwgc28gaXQgZG9lcyBub3QKICAgICAgbmVlZCB0byBiZSBwYXNzZWQgdW5sZXNzIHlvdSB3aXNoIHRvIGNoYW5nZSB3aGljaCBtb2RlbCBpcyBiZWluZyB1c2VkLgogICAgICAgICBAbWV0aG9kIHJlbmRlcgogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSB0aGUgbmFtZSBvZiB0aGUgdGVtcGxhdGUgdG8gcmVuZGVyCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gdGhlIG9wdGlvbnMKICAgICAgQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmludG9dIHRoZSB0ZW1wbGF0ZSB0byByZW5kZXIgaW50bywKICAgICAgICAgICAgICAgICAgICAgIHJlZmVyZW5jZWQgYnkgbmFtZS4gRGVmYXVsdHMgdG8gdGhlIHBhcmVudCB0ZW1wbGF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMub3V0bGV0XSB0aGUgb3V0bGV0IGluc2lkZSBgb3B0aW9ucy5pbnRvYCB0byByZW5kZXIgaW50by4KICAgICAgICAgICAgICAgICAgICAgIERlZmF1bHRzIHRvICdtYWluJwogICAgICBAcGFyYW0ge1N0cmluZ3xPYmplY3R9IFtvcHRpb25zLmNvbnRyb2xsZXJdIHRoZSBjb250cm9sbGVyIHRvIHVzZSBmb3IgdGhpcyB0ZW1wbGF0ZSwKICAgICAgICAgICAgICAgICAgICAgIHJlZmVyZW5jZWQgYnkgbmFtZSBvciBhcyBhIGNvbnRyb2xsZXIgaW5zdGFuY2UuIERlZmF1bHRzIHRvIHRoZSBSb3V0ZSdzIHBhaXJlZCBjb250cm9sbGVyCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5tb2RlbF0gdGhlIG1vZGVsIG9iamVjdCB0byBzZXQgb24gYG9wdGlvbnMuY29udHJvbGxlcmAuCiAgICAgICAgICAgICAgICAgICAgICBEZWZhdWx0cyB0byB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBSb3V0ZSdzIG1vZGVsIGhvb2sKICAgICAgQHNpbmNlIDEuMC4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlbmRlciA9IGZ1bmN0aW9uIHJlbmRlcihfbmFtZSwgb3B0aW9ucykgewogICAgICB2YXIgbmFtZTsKICAgICAgdmFyIGlzRGVmYXVsdFJlbmRlciA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDA7CgogICAgICBpZiAoIWlzRGVmYXVsdFJlbmRlcikgewogICAgICAgIGlmICh0eXBlb2YgX25hbWUgPT09ICdvYmplY3QnICYmICFvcHRpb25zKSB7CiAgICAgICAgICBuYW1lID0gdGhpcy50ZW1wbGF0ZU5hbWUgfHwgdGhpcy5yb3V0ZU5hbWU7CiAgICAgICAgICBvcHRpb25zID0gX25hbWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRW1wdHkpKF9uYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgbmFtZSBpbiB0aGUgZ2l2ZW4gYXJndW1lbnRzIGlzIHVuZGVmaW5lZCBvciBlbXB0eSBzdHJpbmcnLCAhKDAsIF9tZXRhbC5pc0VtcHR5KShfbmFtZSkpKTsKICAgICAgICAgIG5hbWUgPSBfbmFtZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciByZW5kZXJPcHRpb25zID0gYnVpbGRSZW5kZXJPcHRpb25zKHRoaXMsIGlzRGVmYXVsdFJlbmRlciwgbmFtZSwgb3B0aW9ucyk7CiAgICAgIFJPVVRFX0NPTk5FQ1RJT05TLmdldCh0aGlzKS5wdXNoKHJlbmRlck9wdGlvbnMpOwogICAgICAoMCwgX3J1bmxvb3Aub25jZSkodGhpcy5fcm91dGVyLCAnX3NldE91dGxldHMnKTsKICAgIH0KICAgIC8qKgogICAgICBEaXNjb25uZWN0cyBhIHZpZXcgdGhhdCBoYXMgYmVlbiByZW5kZXJlZCBpbnRvIGFuIG91dGxldC4KICAgICAgICAgWW91IG1heSBwYXNzIGFueSBvciBhbGwgb2YgdGhlIGZvbGxvd2luZyBvcHRpb25zIHRvIGBkaXNjb25uZWN0T3V0bGV0YDoKICAgICAgICAgKiBgb3V0bGV0YDogdGhlIG5hbWUgb2YgdGhlIG91dGxldCB0byBjbGVhciAoZGVmYXVsdDogJ21haW4nKQogICAgICAqIGBwYXJlbnRWaWV3YDogdGhlIG5hbWUgb2YgdGhlIHZpZXcgY29udGFpbmluZyB0aGUgb3V0bGV0IHRvIGNsZWFyCiAgICAgICAgIChkZWZhdWx0OiB0aGUgdmlldyByZW5kZXJlZCBieSB0aGUgcGFyZW50IHJvdXRlKQogICAgICAgICBFeGFtcGxlOgogICAgICAgICBgYGBhcHAvcm91dGVzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgc2hvd01vZGFsKGV2dCkgewogICAgICAgICAgICB0aGlzLnJlbmRlcihldnQubW9kYWxOYW1lLCB7CiAgICAgICAgICAgICAgb3V0bGV0OiAnbW9kYWwnLAogICAgICAgICAgICAgIGludG86ICdhcHBsaWNhdGlvbicKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9LAogICAgICAgICAgICAgaGlkZU1vZGFsKGV2dCkgewogICAgICAgICAgICB0aGlzLmRpc2Nvbm5lY3RPdXRsZXQoewogICAgICAgICAgICAgIG91dGxldDogJ21vZGFsJywKICAgICAgICAgICAgICBwYXJlbnRWaWV3OiAnYXBwbGljYXRpb24nCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBBbHRlcm5hdGl2ZWx5LCB5b3UgY2FuIHBhc3MgdGhlIGBvdXRsZXRgIG5hbWUgZGlyZWN0bHkgYXMgYSBzdHJpbmcuCiAgICAgICAgIEV4YW1wbGU6CiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBzaG93TW9kYWwoZXZ0KSB7CiAgICAgICAgICAgIC8vIC4uLgogICAgICAgICAgfSwKICAgICAgICAgIGhpZGVNb2RhbChldnQpIHsKICAgICAgICAgICAgdGhpcy5kaXNjb25uZWN0T3V0bGV0KCdtb2RhbCcpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBkaXNjb25uZWN0T3V0bGV0CiAgICAgIEBwYXJhbSB7T2JqZWN0fFN0cmluZ30gb3B0aW9ucyB0aGUgb3B0aW9ucyBoYXNoIG9yIG91dGxldCBuYW1lCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5kaXNjb25uZWN0T3V0bGV0ID0gZnVuY3Rpb24gZGlzY29ubmVjdE91dGxldChvcHRpb25zKSB7CiAgICAgIHZhciBvdXRsZXROYW1lOwogICAgICB2YXIgcGFyZW50VmlldzsKCiAgICAgIGlmIChvcHRpb25zKSB7CiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnc3RyaW5nJykgewogICAgICAgICAgb3V0bGV0TmFtZSA9IG9wdGlvbnM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG91dGxldE5hbWUgPSBvcHRpb25zLm91dGxldDsKICAgICAgICAgIHBhcmVudFZpZXcgPSBvcHRpb25zLnBhcmVudFZpZXcgPyBvcHRpb25zLnBhcmVudFZpZXcucmVwbGFjZSgvXC8vZywgJy4nKSA6IHVuZGVmaW5lZDsKICAgICAgICAgIChmYWxzZSAmJiAhKCEoJ291dGxldCcgaW4gb3B0aW9ucyAmJiBvcHRpb25zLm91dGxldCA9PT0gdW5kZWZpbmVkKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgcGFzc2VkIHVuZGVmaW5lZCBhcyB0aGUgb3V0bGV0IG5hbWUuJywgISgnb3V0bGV0JyBpbiBvcHRpb25zICYmIG9wdGlvbnMub3V0bGV0ID09PSB1bmRlZmluZWQpKSk7CiAgICAgICAgfQogICAgICB9CgogICAgICBvdXRsZXROYW1lID0gb3V0bGV0TmFtZSB8fCAnbWFpbic7CgogICAgICB0aGlzLl9kaXNjb25uZWN0T3V0bGV0KG91dGxldE5hbWUsIHBhcmVudFZpZXcpOwoKICAgICAgdmFyIHJvdXRlSW5mb3MgPSB0aGlzLl9yb3V0ZXIuX3JvdXRlck1pY3JvbGliLmN1cnJlbnRSb3V0ZUluZm9zOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3V0ZUluZm9zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgLy8gVGhpcyBub24tbG9jYWwgc3RhdGUgbXVuZ2luZyBpcyBzYWRseSBuZWNlc3NhcnkgdG8gbWFpbnRhaW4KICAgICAgICAvLyBiYWNrd2FyZCBjb21wYXRpYmlsaXR5IHdpdGggb3VyIGV4aXN0aW5nIHNlbWFudGljcywgd2hpY2ggYWxsb3cKICAgICAgICAvLyBhbnkgcm91dGUgdG8gZGlzY29ubmVjdE91dGxldCB0aGluZ3Mgb3JpZ2luYWxseSByZW5kZXJlZCBieSBhbnkKICAgICAgICAvLyBvdGhlciByb3V0ZS4gVGhpcyBzaG91bGQgYWxsIGdldCBjdXQgaW4gMi4wLgogICAgICAgIHJvdXRlSW5mb3NbaV0ucm91dGUuX2Rpc2Nvbm5lY3RPdXRsZXQob3V0bGV0TmFtZSwgcGFyZW50Vmlldyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9kaXNjb25uZWN0T3V0bGV0ID0gZnVuY3Rpb24gX2Rpc2Nvbm5lY3RPdXRsZXQob3V0bGV0TmFtZSwgcGFyZW50VmlldykgewogICAgICB2YXIgcGFyZW50ID0gcGFyZW50Um91dGUodGhpcyk7CgogICAgICBpZiAocGFyZW50ICYmIHBhcmVudFZpZXcgPT09IHBhcmVudC5yb3V0ZU5hbWUpIHsKICAgICAgICBwYXJlbnRWaWV3ID0gdW5kZWZpbmVkOwogICAgICB9CgogICAgICB2YXIgY29ubmVjdGlvbnMgPSBST1VURV9DT05ORUNUSU9OUy5nZXQodGhpcyk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbm5lY3Rpb25zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGNvbm5lY3Rpb24gPSBjb25uZWN0aW9uc1tpXTsKCiAgICAgICAgaWYgKGNvbm5lY3Rpb24ub3V0bGV0ID09PSBvdXRsZXROYW1lICYmIGNvbm5lY3Rpb24uaW50byA9PT0gcGFyZW50VmlldykgewogICAgICAgICAgLy8gVGhpcyBuZXV0ZXJzIHRoZSBkaXNjb25uZWN0ZWQgb3V0bGV0IHN1Y2ggdGhhdCBpdCBkb2Vzbid0CiAgICAgICAgICAvLyByZW5kZXIgYW55dGhpbmcsIGJ1dCBpdCBsZWF2ZXMgYW4gZW50cnkgaW4gdGhlIG91dGxldAogICAgICAgICAgLy8gaGllcmFyY2h5IHNvIHRoYXQgYW55IGV4aXN0aW5nIG90aGVyIHJlbmRlcnMgdGhhdCB0YXJnZXQgaXQKICAgICAgICAgIC8vIGRvbid0IHN1ZGRlbmx5IGJsb3cgdXAuIFRoZXkgd2lsbCBzdGlsbCBzdGljayB0aGVtc2VsdmVzCiAgICAgICAgICAvLyBpbnRvIGl0cyBvdXRsZXRzLCB3aGljaCB3b24ndCByZW5kZXIgYW55d2hlcmUuIEFsbCBvZiB0aGlzCiAgICAgICAgICAvLyBzdGF0ZWZ1bG5lc3Mgc2hvdWxkIGdldCB0aGUgbWFjaGV0ZSBpbiAyLjAuCiAgICAgICAgICBjb25uZWN0aW9uc1tpXSA9IHsKICAgICAgICAgICAgb3duZXI6IGNvbm5lY3Rpb24ub3duZXIsCiAgICAgICAgICAgIGludG86IGNvbm5lY3Rpb24uaW50bywKICAgICAgICAgICAgb3V0bGV0OiBjb25uZWN0aW9uLm91dGxldCwKICAgICAgICAgICAgbmFtZTogY29ubmVjdGlvbi5uYW1lLAogICAgICAgICAgICBjb250cm9sbGVyOiB1bmRlZmluZWQsCiAgICAgICAgICAgIHRlbXBsYXRlOiB1bmRlZmluZWQKICAgICAgICAgIH07CiAgICAgICAgICAoMCwgX3J1bmxvb3Aub25jZSkodGhpcy5fcm91dGVyLCAnX3NldE91dGxldHMnKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIFJPVVRFX0NPTk5FQ1RJT05TLnNldCh0aGlzLCBjb25uZWN0aW9ucyk7CiAgICB9OwoKICAgIF9wcm90by53aWxsRGVzdHJveSA9IGZ1bmN0aW9uIHdpbGxEZXN0cm95KCkgewogICAgICB0aGlzLnRlYXJkb3duVmlld3MoKTsKICAgIH0KICAgIC8qKgogICAgICBAcHJpdmF0ZQogICAgICAgICBAbWV0aG9kIHRlYXJkb3duVmlld3MKICAgICovCiAgICA7CgogICAgX3Byb3RvLnRlYXJkb3duVmlld3MgPSBmdW5jdGlvbiB0ZWFyZG93blZpZXdzKCkgewogICAgICB2YXIgY29ubmVjdGlvbnMgPSBST1VURV9DT05ORUNUSU9OUy5nZXQodGhpcyk7CgogICAgICBpZiAoY29ubmVjdGlvbnMgIT09IHVuZGVmaW5lZCAmJiBjb25uZWN0aW9ucy5sZW5ndGggPiAwKSB7CiAgICAgICAgUk9VVEVfQ09OTkVDVElPTlMuc2V0KHRoaXMsIFtdKTsKICAgICAgICAoMCwgX3J1bmxvb3Aub25jZSkodGhpcy5fcm91dGVyLCAnX3NldE91dGxldHMnKTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgIEFsbG93cyB5b3UgdG8gcHJvZHVjZSBjdXN0b20gbWV0YWRhdGEgZm9yIHRoZSByb3V0ZS4KICAgICAgVGhlIHJldHVybiB2YWx1ZSBvZiB0aGlzIG1ldGhvZCB3aWxsIGJlIGF0dGF0Y2hlZCB0bwogICAgICBpdHMgY29ycmVzcG9uZGluZyBSb3V0ZUluZm9XaXRoQXR0cmlidXRlcyBvYmVqY3QuCiAgICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0cy9pbmRleC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGJ1aWxkUm91dGVJbmZvTWV0YWRhdGEoKSB7CiAgICAgICAgICByZXR1cm4geyB0aXRsZTogJ1Bvc3RzIFBhZ2UnIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgYGBgYXBwL3JvdXRlcy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICByb3V0ZXI6IHNlcnZpY2UoJ3JvdXRlcicpLAogICAgICAgIGluaXQoKSB7CiAgICAgICAgICB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogICAgICAgICAgdGhpcy5yb3V0ZXIub24oJ3JvdXRlRGlkQ2hhbmdlJywgdHJhbnNpdGlvbiA9PiB7CiAgICAgICAgICAgIGRvY3VtZW50LnRpdGxlID0gdHJhbnNpdGlvbi50by5tZXRhZGF0YS50aXRsZTsKICAgICAgICAgICAgLy8gd291bGQgdXBkYXRlIGRvY3VtZW50J3MgdGl0bGUgdG8gIlBvc3RzIFBhZ2UiCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQHJldHVybiBhbnkKICAgICAqLwogICAgOwoKICAgIF9wcm90by5idWlsZFJvdXRlSW5mb01ldGFkYXRhID0gZnVuY3Rpb24gYnVpbGRSb3V0ZUluZm9NZXRhZGF0YSgpIHt9OwoKICAgIHJldHVybiBSb3V0ZTsKICB9KF9ydW50aW1lLk9iamVjdCk7CgogIFJvdXRlLnJlb3BlbkNsYXNzKHsKICAgIGlzUm91dGVGYWN0b3J5OiB0cnVlCiAgfSk7CgogIGZ1bmN0aW9uIHBhcmVudFJvdXRlKHJvdXRlKSB7CiAgICB2YXIgcm91dGVJbmZvID0gcm91dGVJbmZvRm9yKHJvdXRlLCByb3V0ZS5fcm91dGVyLl9yb3V0ZXJNaWNyb2xpYi5zdGF0ZS5yb3V0ZUluZm9zLCAtMSk7CiAgICByZXR1cm4gcm91dGVJbmZvICYmIHJvdXRlSW5mby5yb3V0ZTsKICB9CgogIGZ1bmN0aW9uIHJvdXRlSW5mb0Zvcihyb3V0ZSwgcm91dGVJbmZvcywgb2Zmc2V0KSB7CiAgICBpZiAob2Zmc2V0ID09PSB2b2lkIDApIHsKICAgICAgb2Zmc2V0ID0gMDsKICAgIH0KCiAgICBpZiAoIXJvdXRlSW5mb3MpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBjdXJyZW50OwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm91dGVJbmZvcy5sZW5ndGg7IGkrKykgewogICAgICBjdXJyZW50ID0gcm91dGVJbmZvc1tpXS5yb3V0ZTsKCiAgICAgIGlmIChjdXJyZW50ID09PSByb3V0ZSkgewogICAgICAgIHJldHVybiByb3V0ZUluZm9zW2kgKyBvZmZzZXRdOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuOwogIH0KCiAgZnVuY3Rpb24gYnVpbGRSZW5kZXJPcHRpb25zKHJvdXRlLCBpc0RlZmF1bHRSZW5kZXIsIF9uYW1lLCBvcHRpb25zKSB7CiAgICAoZmFsc2UgJiYgIShpc0RlZmF1bHRSZW5kZXIgfHwgIShvcHRpb25zICYmICdvdXRsZXQnIGluIG9wdGlvbnMgJiYgb3B0aW9ucy5vdXRsZXQgPT09IHVuZGVmaW5lZCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IHBhc3NlZCB1bmRlZmluZWQgYXMgdGhlIG91dGxldCBuYW1lLicsIGlzRGVmYXVsdFJlbmRlciB8fCAhKG9wdGlvbnMgJiYgJ291dGxldCcgaW4gb3B0aW9ucyAmJiBvcHRpb25zLm91dGxldCA9PT0gdW5kZWZpbmVkKSkpOwogICAgdmFyIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikocm91dGUpOwogICAgdmFyIG5hbWUsIHRlbXBsYXRlTmFtZSwgaW50bywgb3V0bGV0LCBtb2RlbDsKICAgIHZhciBjb250cm9sbGVyID0gdW5kZWZpbmVkOwoKICAgIGlmIChvcHRpb25zKSB7CiAgICAgIGludG8gPSBvcHRpb25zLmludG8gJiYgb3B0aW9ucy5pbnRvLnJlcGxhY2UoL1wvL2csICcuJyk7CiAgICAgIG91dGxldCA9IG9wdGlvbnMub3V0bGV0OwogICAgICBjb250cm9sbGVyID0gb3B0aW9ucy5jb250cm9sbGVyOwogICAgICBtb2RlbCA9IG9wdGlvbnMubW9kZWw7CiAgICB9CgogICAgb3V0bGV0ID0gb3V0bGV0IHx8ICdtYWluJzsKCiAgICBpZiAoaXNEZWZhdWx0UmVuZGVyKSB7CiAgICAgIG5hbWUgPSByb3V0ZS5yb3V0ZU5hbWU7CiAgICAgIHRlbXBsYXRlTmFtZSA9IHJvdXRlLnRlbXBsYXRlTmFtZSB8fCBuYW1lOwogICAgfSBlbHNlIHsKICAgICAgbmFtZSA9IF9uYW1lLnJlcGxhY2UoL1wvL2csICcuJyk7CiAgICAgIHRlbXBsYXRlTmFtZSA9IG5hbWU7CiAgICB9CgogICAgaWYgKGNvbnRyb2xsZXIgPT09IHVuZGVmaW5lZCkgewogICAgICBpZiAoaXNEZWZhdWx0UmVuZGVyKSB7CiAgICAgICAgY29udHJvbGxlciA9IHJvdXRlLmNvbnRyb2xsZXJOYW1lIHx8IG93bmVyLmxvb2t1cCgiY29udHJvbGxlcjoiICsgbmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29udHJvbGxlciA9IG93bmVyLmxvb2t1cCgiY29udHJvbGxlcjoiICsgbmFtZSkgfHwgcm91dGUuY29udHJvbGxlck5hbWUgfHwgcm91dGUucm91dGVOYW1lOwogICAgICB9CiAgICB9CgogICAgaWYgKHR5cGVvZiBjb250cm9sbGVyID09PSAnc3RyaW5nJykgewogICAgICB2YXIgY29udHJvbGxlck5hbWUgPSBjb250cm9sbGVyOwogICAgICBjb250cm9sbGVyID0gb3duZXIubG9va3VwKCJjb250cm9sbGVyOiIgKyBjb250cm9sbGVyTmFtZSk7CiAgICAgIChmYWxzZSAmJiAhKGlzRGVmYXVsdFJlbmRlciB8fCBjb250cm9sbGVyICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IHBhc3NlZCBgY29udHJvbGxlcjogJyIgKyBjb250cm9sbGVyTmFtZSArICInYCBpbnRvIHRoZSBgcmVuZGVyYCBtZXRob2QsIGJ1dCBubyBzdWNoIGNvbnRyb2xsZXIgY291bGQgYmUgZm91bmQuIiwgaXNEZWZhdWx0UmVuZGVyIHx8IGNvbnRyb2xsZXIgIT09IHVuZGVmaW5lZCkpOwogICAgfQoKICAgIGlmIChtb2RlbCkgewogICAgICBjb250cm9sbGVyLnNldCgnbW9kZWwnLCBtb2RlbCk7CiAgICB9CgogICAgdmFyIHRlbXBsYXRlID0gb3duZXIubG9va3VwKCJ0ZW1wbGF0ZToiICsgdGVtcGxhdGVOYW1lKTsKICAgIChmYWxzZSAmJiAhKGlzRGVmYXVsdFJlbmRlciB8fCB0ZW1wbGF0ZSAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkNvdWxkIG5vdCBmaW5kIFwiIiArIHRlbXBsYXRlTmFtZSArICJcIiB0ZW1wbGF0ZSwgdmlldywgb3IgY29tcG9uZW50LiIsIGlzRGVmYXVsdFJlbmRlciB8fCB0ZW1wbGF0ZSAhPT0gdW5kZWZpbmVkKSk7CiAgICB2YXIgcGFyZW50OwoKICAgIGlmIChpbnRvICYmIChwYXJlbnQgPSBwYXJlbnRSb3V0ZShyb3V0ZSkpICYmIGludG8gPT09IHBhcmVudC5yb3V0ZU5hbWUpIHsKICAgICAgaW50byA9IHVuZGVmaW5lZDsKICAgIH0KCiAgICB2YXIgcmVuZGVyT3B0aW9ucyA9IHsKICAgICAgb3duZXI6IG93bmVyLAogICAgICBpbnRvOiBpbnRvLAogICAgICBvdXRsZXQ6IG91dGxldCwKICAgICAgbmFtZTogbmFtZSwKICAgICAgY29udHJvbGxlcjogY29udHJvbGxlciwKICAgICAgdGVtcGxhdGU6IHRlbXBsYXRlICE9PSB1bmRlZmluZWQgPyB0ZW1wbGF0ZShvd25lcikgOiByb3V0ZS5fdG9wTGV2ZWxWaWV3VGVtcGxhdGUob3duZXIpCiAgICB9OwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICB2YXIgTE9HX1ZJRVdfTE9PS1VQUyA9ICgwLCBfbWV0YWwuZ2V0KShyb3V0ZS5fcm91dGVyLCAnbmFtZXNwYWNlLkxPR19WSUVXX0xPT0tVUFMnKTsKCiAgICAgIGlmIChMT0dfVklFV19MT09LVVBTICYmICF0ZW1wbGF0ZSkgewogICAgICAgICgwLCBfZGVidWcuaW5mbykoIkNvdWxkIG5vdCBmaW5kIFwiIiArIG5hbWUgKyAiXCIgdGVtcGxhdGUuIE5vdGhpbmcgd2lsbCBiZSByZW5kZXJlZCIsIHsKICAgICAgICAgIGZ1bGxOYW1lOiAidGVtcGxhdGU6IiArIG5hbWUKICAgICAgICB9KTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiByZW5kZXJPcHRpb25zOwogIH0KCiAgZnVuY3Rpb24gZ2V0RnVsbFF1ZXJ5UGFyYW1zKHJvdXRlciwgc3RhdGUpIHsKICAgIGlmIChzdGF0ZVsnZnVsbFF1ZXJ5UGFyYW1zJ10pIHsKICAgICAgcmV0dXJuIHN0YXRlWydmdWxsUXVlcnlQYXJhbXMnXTsKICAgIH0KCiAgICBzdGF0ZVsnZnVsbFF1ZXJ5UGFyYW1zJ10gPSB7fTsKICAgICgwLCBfcG9seWZpbGxzLmFzc2lnbikoc3RhdGVbJ2Z1bGxRdWVyeVBhcmFtcyddLCBzdGF0ZS5xdWVyeVBhcmFtcyk7CgogICAgcm91dGVyLl9kZXNlcmlhbGl6ZVF1ZXJ5UGFyYW1zKHN0YXRlLnJvdXRlSW5mb3MsIHN0YXRlWydmdWxsUXVlcnlQYXJhbXMnXSk7CgogICAgcmV0dXJuIHN0YXRlWydmdWxsUXVlcnlQYXJhbXMnXTsKICB9CgogIGZ1bmN0aW9uIGdldFF1ZXJ5UGFyYW1zRm9yKHJvdXRlLCBzdGF0ZSkgewogICAgc3RhdGVbJ3F1ZXJ5UGFyYW1zRm9yJ10gPSBzdGF0ZVsncXVlcnlQYXJhbXNGb3InXSB8fCB7fTsKICAgIHZhciBuYW1lID0gcm91dGUuZnVsbFJvdXRlTmFtZTsKCiAgICBpZiAoc3RhdGVbJ3F1ZXJ5UGFyYW1zRm9yJ11bbmFtZV0pIHsKICAgICAgcmV0dXJuIHN0YXRlWydxdWVyeVBhcmFtc0ZvciddW25hbWVdOwogICAgfQoKICAgIHZhciBmdWxsUXVlcnlQYXJhbXMgPSBnZXRGdWxsUXVlcnlQYXJhbXMocm91dGUuX3JvdXRlciwgc3RhdGUpOwogICAgdmFyIHBhcmFtcyA9IHN0YXRlWydxdWVyeVBhcmFtc0ZvciddW25hbWVdID0ge307IC8vIENvcHkgb3ZlciBhbGwgdGhlIHF1ZXJ5IHBhcmFtcyBmb3IgdGhpcyByb3V0ZS9jb250cm9sbGVyIGludG8gcGFyYW1zIGhhc2guCgogICAgdmFyIHFwcyA9ICgwLCBfbWV0YWwuZ2V0KShyb3V0ZSwgJ19xcC5xcHMnKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHFwcy5sZW5ndGg7ICsraSkgewogICAgICAvLyBQdXQgZGVzZXJpYWxpemVkIHFwIG9uIHBhcmFtcyBoYXNoLgogICAgICB2YXIgcXAgPSBxcHNbaV07CiAgICAgIHZhciBxcFZhbHVlV2FzUGFzc2VkSW4gPSBxcC5wcm9wIGluIGZ1bGxRdWVyeVBhcmFtczsKICAgICAgcGFyYW1zW3FwLnByb3BdID0gcXBWYWx1ZVdhc1Bhc3NlZEluID8gZnVsbFF1ZXJ5UGFyYW1zW3FwLnByb3BdIDogY29weURlZmF1bHRWYWx1ZShxcC5kZWZhdWx0VmFsdWUpOwogICAgfQoKICAgIHJldHVybiBwYXJhbXM7CiAgfQoKICBmdW5jdGlvbiBjb3B5RGVmYXVsdFZhbHVlKHZhbHVlKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5BKSh2YWx1ZS5zbGljZSgpKTsKICAgIH0KCiAgICByZXR1cm4gdmFsdWU7CiAgfQogIC8qCiAgICBNZXJnZXMgYWxsIHF1ZXJ5IHBhcmFtZXRlcnMgZnJvbSBhIGNvbnRyb2xsZXIgd2l0aCB0aG9zZSBmcm9tCiAgICBhIHJvdXRlLCByZXR1cm5pbmcgYSBuZXcgb2JqZWN0IGFuZCBhdm9pZGluZyBhbnkgbXV0YXRpb25zIHRvCiAgICB0aGUgZXhpc3Rpbmcgb2JqZWN0cy4KICAqLwoKCiAgZnVuY3Rpb24gbWVyZ2VFYWNoUXVlcnlQYXJhbXMoY29udHJvbGxlclFQLCByb3V0ZVFQKSB7CiAgICB2YXIgcXBzID0ge307CiAgICB2YXIga2V5c0FscmVhZHlNZXJnZWRPclNraXBwYWJsZSA9IHsKICAgICAgZGVmYXVsdFZhbHVlOiB0cnVlLAogICAgICB0eXBlOiB0cnVlLAogICAgICBzY29wZTogdHJ1ZSwKICAgICAgYXM6IHRydWUKICAgIH07IC8vIGZpcnN0IGxvb3Agb3ZlciBhbGwgY29udHJvbGxlciBxcHMsIG1lcmdpbmcgdGhlbSB3aXRoIGFueSBtYXRjaGluZyByb3V0ZSBxcHMKICAgIC8vIGludG8gYSBuZXcgZW1wdHkgb2JqZWN0IHRvIGF2b2lkIG11dGF0aW5nLgoKICAgIGZvciAodmFyIGNxcE5hbWUgaW4gY29udHJvbGxlclFQKSB7CiAgICAgIGlmICghY29udHJvbGxlclFQLmhhc093blByb3BlcnR5KGNxcE5hbWUpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIHZhciBuZXdDb250cm9sbGVyUGFyYW1ldGVyQ29uZmlndXJhdGlvbiA9IHt9OwogICAgICAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKG5ld0NvbnRyb2xsZXJQYXJhbWV0ZXJDb25maWd1cmF0aW9uLCBjb250cm9sbGVyUVBbY3FwTmFtZV0sIHJvdXRlUVBbY3FwTmFtZV0pOwogICAgICBxcHNbY3FwTmFtZV0gPSBuZXdDb250cm9sbGVyUGFyYW1ldGVyQ29uZmlndXJhdGlvbjsgLy8gYWxsb3dzIHVzIHRvIHNraXAgdGhpcyBRUCB3aGVuIHdlIGNoZWNrIHJvdXRlIFFQcy4KCiAgICAgIGtleXNBbHJlYWR5TWVyZ2VkT3JTa2lwcGFibGVbY3FwTmFtZV0gPSB0cnVlOwogICAgfSAvLyBsb29wIG92ZXIgYWxsIHJvdXRlIHFwcywgc2tpcHBpbmcgdGhvc2UgdGhhdCB3ZXJlIG1lcmdlZCBpbiB0aGUgZmlyc3QgcGFzcwogICAgLy8gYmVjYXVzZSB0aGV5IGFsc28gYXBwZWFyIGluIGNvbnRyb2xsZXIgcXBzCgoKICAgIGZvciAodmFyIHJxcE5hbWUgaW4gcm91dGVRUCkgewogICAgICBpZiAoIXJvdXRlUVAuaGFzT3duUHJvcGVydHkocnFwTmFtZSkgfHwga2V5c0FscmVhZHlNZXJnZWRPclNraXBwYWJsZVtycXBOYW1lXSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICB2YXIgbmV3Um91dGVQYXJhbWV0ZXJDb25maWd1cmF0aW9uID0ge307CiAgICAgICgwLCBfcG9seWZpbGxzLmFzc2lnbikobmV3Um91dGVQYXJhbWV0ZXJDb25maWd1cmF0aW9uLCByb3V0ZVFQW3JxcE5hbWVdLCBjb250cm9sbGVyUVBbcnFwTmFtZV0pOwogICAgICBxcHNbcnFwTmFtZV0gPSBuZXdSb3V0ZVBhcmFtZXRlckNvbmZpZ3VyYXRpb247CiAgICB9CgogICAgcmV0dXJuIHFwczsKICB9CgogIGZ1bmN0aW9uIGFkZFF1ZXJ5UGFyYW1zT2JzZXJ2ZXJzKGNvbnRyb2xsZXIsIHByb3BOYW1lcykgewogICAgcHJvcE5hbWVzLmZvckVhY2goZnVuY3Rpb24gKHByb3ApIHsKICAgICAgaWYgKCgwLCBfbWV0YWwuZGVzY3JpcHRvckZvclByb3BlcnR5KShjb250cm9sbGVyLCBwcm9wKSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdmFyIGRlc2MgPSAoMCwgX3V0aWxzLmxvb2t1cERlc2NyaXB0b3IpKGNvbnRyb2xsZXIsIHByb3ApOwoKICAgICAgICBpZiAoZGVzYyAhPT0gbnVsbCAmJiAodHlwZW9mIGRlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBkZXNjLnNldCA9PT0gJ2Z1bmN0aW9uJykpIHsKICAgICAgICAgICgwLCBfbWV0YWwuZGVmaW5lUHJvcGVydHkpKGNvbnRyb2xsZXIsIHByb3AsICgwLCBfY29tcGF0LmRlcGVuZGVudEtleUNvbXBhdCkoewogICAgICAgICAgICBnZXQ6IGRlc2MuZ2V0LAogICAgICAgICAgICBzZXQ6IGRlc2Muc2V0CiAgICAgICAgICB9KSk7CiAgICAgICAgfQogICAgICB9CgogICAgICAoMCwgX21ldGFsLmFkZE9ic2VydmVyKShjb250cm9sbGVyLCBwcm9wICsgIi5bXSIsIGNvbnRyb2xsZXIsIGNvbnRyb2xsZXIuX3FwQ2hhbmdlZCwgZmFsc2UpOwogICAgfSk7CiAgfQoKICBmdW5jdGlvbiBnZXRFbmdpbmVSb3V0ZU5hbWUoZW5naW5lLCByb3V0ZU5hbWUpIHsKICAgIGlmIChlbmdpbmUucm91dGFibGUpIHsKICAgICAgdmFyIHByZWZpeCA9IGVuZ2luZS5tb3VudFBvaW50OwoKICAgICAgaWYgKHJvdXRlTmFtZSA9PT0gJ2FwcGxpY2F0aW9uJykgewogICAgICAgIHJldHVybiBwcmVmaXg7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHByZWZpeCArICIuIiArIHJvdXRlTmFtZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiByb3V0ZU5hbWU7CiAgfQogIC8qKgogICAgICBBIGhvb2sgeW91IGNhbiBpbXBsZW1lbnQgdG8gY29udmVydCB0aGUgcm91dGUncyBtb2RlbCBpbnRvIHBhcmFtZXRlcnMKICAgICAgZm9yIHRoZSBVUkwuCiAgCiAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgLy8gLi4uCiAgCiAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgncG9zdCcsIHsgcGF0aDogJy9wb3N0cy86cG9zdF9pZCcgfSk7CiAgICAgIH0pOwogIAogICAgICBgYGAKICAKICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0LmpzCiAgICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeSc7CiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgCiAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgbW9kZWwocGFyYW1zKSB7CiAgICAgICAgICAvLyB0aGUgc2VydmVyIHJldHVybnMgYHsgaWQ6IDEyIH1gCiAgICAgICAgICByZXR1cm4gJC5nZXRKU09OKCcvcG9zdHMvJyArIHBhcmFtcy5wb3N0X2lkKTsKICAgICAgICB9LAogIAogICAgICAgIHNlcmlhbGl6ZShtb2RlbCkgewogICAgICAgICAgLy8gdGhpcyB3aWxsIG1ha2UgdGhlIFVSTCBgL3Bvc3RzLzEyYAogICAgICAgICAgcmV0dXJuIHsgcG9zdF9pZDogbW9kZWwuaWQgfTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAKICAgICAgVGhlIGRlZmF1bHQgYHNlcmlhbGl6ZWAgbWV0aG9kIHdpbGwgaW5zZXJ0IHRoZSBtb2RlbCdzIGBpZGAgaW50byB0aGUKICAgICAgcm91dGUncyBkeW5hbWljIHNlZ21lbnQgKGluIHRoaXMgY2FzZSwgYDpwb3N0X2lkYCkgaWYgdGhlIHNlZ21lbnQgY29udGFpbnMgJ19pZCcuCiAgICAgIElmIHRoZSByb3V0ZSBoYXMgbXVsdGlwbGUgZHluYW1pYyBzZWdtZW50cyBvciBkb2VzIG5vdCBjb250YWluICdfaWQnLCBgc2VyaWFsaXplYAogICAgICB3aWxsIHJldHVybiBgZ2V0UHJvcGVydGllcyhtb2RlbCwgcGFyYW1zKWAKICAKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIHdoZW4gYHRyYW5zaXRpb25Ub2AgaXMgY2FsbGVkIHdpdGggYSBjb250ZXh0CiAgICAgIGluIG9yZGVyIHRvIHBvcHVsYXRlIHRoZSBVUkwuCiAgCiAgICAgIEBtZXRob2Qgc2VyaWFsaXplCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBtb2RlbCB0aGUgcm91dGVzIG1vZGVsCiAgICAgIEBwYXJhbSB7QXJyYXl9IHBhcmFtcyBhbiBBcnJheSBvZiBwYXJhbWV0ZXIgbmFtZXMgZm9yIHRoZSBjdXJyZW50CiAgICAgICAgcm91dGUgKGluIHRoZSBleGFtcGxlLCBgWydwb3N0X2lkJ11gLgogICAgICBAcmV0dXJuIHtPYmplY3R9IHRoZSBzZXJpYWxpemVkIHBhcmFtZXRlcnMKICAgICAgQHNpbmNlIDEuMC4wCiAgICAgIEBwdWJsaWMKICAgICovCgoKICBSb3V0ZS5wcm90b3R5cGUuc2VyaWFsaXplID0gZGVmYXVsdFNlcmlhbGl6ZTsKICBSb3V0ZS5yZW9wZW4oX3J1bnRpbWUuQWN0aW9uSGFuZGxlciwgX3J1bnRpbWUuRXZlbnRlZCwgewogICAgbWVyZ2VkUHJvcGVydGllczogWydxdWVyeVBhcmFtcyddLAoKICAgIC8qKgogICAgICBDb25maWd1cmF0aW9uIGhhc2ggZm9yIHRoaXMgcm91dGUncyBxdWVyeVBhcmFtcy4gVGhlIHBvc3NpYmxlCiAgICAgIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBhbmQgdGhlaXIgZGVmYXVsdHMgYXJlIGFzIGZvbGxvd3MKICAgICAgKGFzc3VtaW5nIGEgcXVlcnkgcGFyYW0gd2hvc2UgY29udHJvbGxlciBwcm9wZXJ0eSBpcyBgcGFnZWApOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHF1ZXJ5UGFyYW1zOiB7CiAgICAgICAgcGFnZTogewogICAgICAgICAgLy8gQnkgZGVmYXVsdCwgY29udHJvbGxlciBxdWVyeSBwYXJhbSBwcm9wZXJ0aWVzIGRvbid0CiAgICAgICAgICAvLyBjYXVzZSBhIGZ1bGwgdHJhbnNpdGlvbiB3aGVuIHRoZXkgYXJlIGNoYW5nZWQsIGJ1dAogICAgICAgICAgLy8gcmF0aGVyIG9ubHkgY2F1c2UgdGhlIFVSTCB0byB1cGRhdGUuIFNldHRpbmcKICAgICAgICAgIC8vIGByZWZyZXNoTW9kZWxgIHRvIHRydWUgd2lsbCBjYXVzZSBhbiAiaW4tcGxhY2UiCiAgICAgICAgICAvLyB0cmFuc2l0aW9uIHRvIG9jY3VyLCB3aGVyZWJ5IHRoZSBtb2RlbCBob29rcyBmb3IKICAgICAgICAgIC8vIHRoaXMgcm91dGUgKGFuZCBhbnkgY2hpbGQgcm91dGVzKSB3aWxsIHJlLWZpcmUsIGFsbG93aW5nCiAgICAgICAgICAvLyB5b3UgdG8gcmVsb2FkIG1vZGVscyAoZS5nLiwgZnJvbSB0aGUgc2VydmVyKSB1c2luZyB0aGUKICAgICAgICAgIC8vIHVwZGF0ZWQgcXVlcnkgcGFyYW0gdmFsdWVzLgogICAgICAgICAgcmVmcmVzaE1vZGVsOiBmYWxzZSwKICAgICAgICAgICAgIC8vIEJ5IGRlZmF1bHQsIGNoYW5nZXMgdG8gY29udHJvbGxlciBxdWVyeSBwYXJhbSBwcm9wZXJ0aWVzCiAgICAgICAgICAvLyBjYXVzZSB0aGUgVVJMIHRvIHVwZGF0ZSB2aWEgYHB1c2hTdGF0ZWAsIHdoaWNoIG1lYW5zIGFuCiAgICAgICAgICAvLyBpdGVtIHdpbGwgYmUgYWRkZWQgdG8gdGhlIGJyb3dzZXIncyBoaXN0b3J5LCBhbGxvd2luZwogICAgICAgICAgLy8geW91IHRvIHVzZSB0aGUgYmFjayBidXR0b24gdG8gcmVzdG9yZSB0aGUgYXBwIHRvIHRoZQogICAgICAgICAgLy8gcHJldmlvdXMgc3RhdGUgYmVmb3JlIHRoZSBxdWVyeSBwYXJhbSBwcm9wZXJ0eSB3YXMgY2hhbmdlZC4KICAgICAgICAgIC8vIFNldHRpbmcgYHJlcGxhY2VgIHRvIHRydWUgd2lsbCB1c2UgYHJlcGxhY2VTdGF0ZWAgKG9yIGl0cwogICAgICAgICAgLy8gaGFzaCBsb2NhdGlvbiBlcXVpdmFsZW50KSwgd2hpY2ggY2F1c2VzIG5vIGJyb3dzZXIgaGlzdG9yeQogICAgICAgICAgLy8gaXRlbSB0byBiZSBhZGRlZC4gVGhpcyBvcHRpb25zIG5hbWUgYW5kIGRlZmF1bHQgdmFsdWUgYXJlCiAgICAgICAgICAvLyB0aGUgc2FtZSBhcyB0aGUgYGxpbmstdG9gIGhlbHBlcidzIGByZXBsYWNlYCBvcHRpb24uCiAgICAgICAgICByZXBsYWNlOiBmYWxzZSwKICAgICAgICAgICAgIC8vIEJ5IGRlZmF1bHQsIHRoZSBxdWVyeSBwYXJhbSBVUkwga2V5IGlzIHRoZSBzYW1lIG5hbWUgYXMKICAgICAgICAgIC8vIHRoZSBjb250cm9sbGVyIHByb3BlcnR5IG5hbWUuIFVzZSBgYXNgIHRvIHNwZWNpZnkgYQogICAgICAgICAgLy8gZGlmZmVyZW50IFVSTCBrZXkuCiAgICAgICAgICBhczogJ3BhZ2UnCiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgICBAcHJvcGVydHkgcXVlcnlQYXJhbXMKICAgICAgQGZvciBSb3V0ZQogICAgICBAdHlwZSBPYmplY3QKICAgICAgQHNpbmNlIDEuNi4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBxdWVyeVBhcmFtczoge30sCgogICAgLyoqCiAgICAgIFRoZSBuYW1lIG9mIHRoZSB0ZW1wbGF0ZSB0byB1c2UgYnkgZGVmYXVsdCB3aGVuIHJlbmRlcmluZyB0aGlzIHJvdXRlcwogICAgICB0ZW1wbGF0ZS4KICAgICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0cy9saXN0LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgdGVtcGxhdGVOYW1lOiAncG9zdHMvbGlzdCcKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3RzL2luZGV4LmpzCiAgICAgIGltcG9ydCBQb3N0c0xpc3QgZnJvbSAnLi4vcG9zdHMvbGlzdCc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFBvc3RzTGlzdC5leHRlbmQoKTsKICAgICAgYGBgCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdHMvYXJjaGl2ZWQuanMKICAgICAgaW1wb3J0IFBvc3RzTGlzdCBmcm9tICcuLi9wb3N0cy9saXN0JzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUG9zdHNMaXN0LmV4dGVuZCgpOwogICAgICBgYGAKICAgICAgICAgQHByb3BlcnR5IHRlbXBsYXRlTmFtZQogICAgICBAdHlwZSBTdHJpbmcKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAc2luY2UgMS40LjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHRlbXBsYXRlTmFtZTogbnVsbCwKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgQHByb3BlcnR5IF9uYW1lcwogICAgKi8KICAgIF9uYW1lczogbnVsbCwKCiAgICAvKioKICAgICAgVGhlIG5hbWUgb2YgdGhlIGNvbnRyb2xsZXIgdG8gYXNzb2NpYXRlIHdpdGggdGhpcyByb3V0ZS4KICAgICAgICAgQnkgZGVmYXVsdCwgRW1iZXIgd2lsbCBsb29rdXAgYSByb3V0ZSdzIGNvbnRyb2xsZXIgdGhhdCBtYXRjaGVzIHRoZSBuYW1lCiAgICAgIG9mIHRoZSByb3V0ZSAoaS5lLiBgcG9zdHMubmV3YCkuIEhvd2V2ZXIsCiAgICAgIGlmIHlvdSB3b3VsZCBsaWtlIHRvIGRlZmluZSBhIHNwZWNpZmljIGNvbnRyb2xsZXIgdG8gdXNlLCB5b3UgY2FuIGRvIHNvCiAgICAgIHVzaW5nIHRoaXMgcHJvcGVydHkuCiAgICAgICAgIFRoaXMgaXMgdXNlZnVsIGluIG1hbnkgd2F5cywgYXMgdGhlIGNvbnRyb2xsZXIgc3BlY2lmaWVkIHdpbGwgYmU6CiAgICAgICAgICogcGFzc2VkIHRvIHRoZSBgc2V0dXBDb250cm9sbGVyYCBtZXRob2QuCiAgICAgICogdXNlZCBhcyB0aGUgY29udHJvbGxlciBmb3IgdGhlIHRlbXBsYXRlIGJlaW5nIHJlbmRlcmVkIGJ5IHRoZSByb3V0ZS4KICAgICAgKiByZXR1cm5lZCBmcm9tIGEgY2FsbCB0byBgY29udHJvbGxlckZvcmAgZm9yIHRoZSByb3V0ZS4KICAgICAgICAgQHByb3BlcnR5IGNvbnRyb2xsZXJOYW1lCiAgICAgIEB0eXBlIFN0cmluZwogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBzaW5jZSAxLjQuMAogICAgICBAcHVibGljCiAgICAqLwogICAgY29udHJvbGxlck5hbWU6IG51bGwsCgogICAgLyoqCiAgICAgIFN0b3JlIHByb3BlcnR5IHByb3ZpZGVzIGEgaG9vayBmb3IgZGF0YSBwZXJzaXN0ZW5jZSBsaWJyYXJpZXMgdG8gaW5qZWN0IHRoZW1zZWx2ZXMuCiAgICAgICAgIEJ5IGRlZmF1bHQsIHRoaXMgc3RvcmUgcHJvcGVydHkgcHJvdmlkZXMgdGhlIGV4YWN0IHNhbWUgZnVuY3Rpb25hbGl0eSBwcmV2aW91c2x5CiAgICAgIGluIHRoZSBtb2RlbCBob29rLgogICAgICAgICBDdXJyZW50bHksIHRoZSByZXF1aXJlZCBpbnRlcmZhY2UgaXM6CiAgICAgICAgIGBzdG9yZS5maW5kKG1vZGVsTmFtZSwgZmluZEFyZ3VtZW50cylgCiAgICAgICAgIEBwcm9wZXJ0eSBzdG9yZQogICAgICBAdHlwZSB7T2JqZWN0fQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIHN0b3JlOiAoMCwgX21ldGFsLmNvbXB1dGVkKSh7CiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICAgIHZhciByb3V0ZU5hbWUgPSB0aGlzLnJvdXRlTmFtZTsKICAgICAgICB2YXIgbmFtZXNwYWNlID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdfcm91dGVyLm5hbWVzcGFjZScpOwogICAgICAgIHJldHVybiB7CiAgICAgICAgICBmaW5kOiBmdW5jdGlvbiBmaW5kKG5hbWUsIHZhbHVlKSB7CiAgICAgICAgICAgIHZhciBtb2RlbENsYXNzID0gb3duZXIuZmFjdG9yeUZvcigibW9kZWw6IiArIG5hbWUpOwogICAgICAgICAgICAoZmFsc2UgJiYgIShCb29sZWFuKG1vZGVsQ2xhc3MpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSB1c2VkIHRoZSBkeW5hbWljIHNlZ21lbnQgIiArIG5hbWUgKyAiX2lkIGluIHlvdXIgcm91dGUgIiArIHJvdXRlTmFtZSArICIsIGJ1dCAiICsgbmFtZXNwYWNlICsgIi4iICsgKDAsIF9zdHJpbmcuY2xhc3NpZnkpKG5hbWUpICsgIiBkaWQgbm90IGV4aXN0IGFuZCB5b3UgZGlkIG5vdCBvdmVycmlkZSB5b3VyIHJvdXRlJ3MgYG1vZGVsYCBob29rLiIsIEJvb2xlYW4obW9kZWxDbGFzcykpKTsKCiAgICAgICAgICAgIGlmICghbW9kZWxDbGFzcykgewogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbW9kZWxDbGFzcyA9IG1vZGVsQ2xhc3MuY2xhc3M7CiAgICAgICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBtb2RlbENsYXNzLmZpbmQgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgoMCwgX3N0cmluZy5jbGFzc2lmeSkobmFtZSkgKyAiIGhhcyBubyBtZXRob2QgYGZpbmRgLiIsIHR5cGVvZiBtb2RlbENsYXNzLmZpbmQgPT09ICdmdW5jdGlvbicpKTsKICAgICAgICAgICAgcmV0dXJuIG1vZGVsQ2xhc3MuZmluZCh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5LCB2YWx1ZSkgewogICAgICAgICgwLCBfbWV0YWwuZGVmaW5lUHJvcGVydHkpKHRoaXMsIGtleSwgbnVsbCwgdmFsdWUpOwogICAgICB9CiAgICB9KSwKCiAgICAvKioKICAgICAgICBAcHJpdmF0ZQogICAgICAgICAgIEBwcm9wZXJ0eSBfcXAKICAgICAgKi8KICAgIF9xcDogKDAsIF9tZXRhbC5jb21wdXRlZCkoZnVuY3Rpb24gKCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHZhciBjb21iaW5lZFF1ZXJ5UGFyYW1ldGVyQ29uZmlndXJhdGlvbjsKICAgICAgdmFyIGNvbnRyb2xsZXJOYW1lID0gdGhpcy5jb250cm9sbGVyTmFtZSB8fCB0aGlzLnJvdXRlTmFtZTsKICAgICAgdmFyIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikodGhpcyk7CiAgICAgIHZhciBjb250cm9sbGVyID0gb3duZXIubG9va3VwKCJjb250cm9sbGVyOiIgKyBjb250cm9sbGVyTmFtZSk7CiAgICAgIHZhciBxdWVyeVBhcmFtZXRlckNvbmZpZ3VyYXRvbiA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAncXVlcnlQYXJhbXMnKTsKICAgICAgdmFyIGhhc1JvdXRlckRlZmluZWRRdWVyeVBhcmFtcyA9IE9iamVjdC5rZXlzKHF1ZXJ5UGFyYW1ldGVyQ29uZmlndXJhdG9uKS5sZW5ndGggPiAwOwoKICAgICAgaWYgKGNvbnRyb2xsZXIpIHsKICAgICAgICAvLyB0aGUgZGV2ZWxvcGVyIGhhcyBhdXRob3JlZCBhIGNvbnRyb2xsZXIgY2xhc3MgaW4gdGhlaXIgYXBwbGljYXRpb24gZm9yCiAgICAgICAgLy8gdGhpcyByb3V0ZSBmaW5kIGl0cyBxdWVyeSBwYXJhbXMgYW5kIG5vcm1hbGl6ZSB0aGVpciBvYmplY3Qgc2hhcGUgdGhlbQogICAgICAgIC8vIG1lcmdlIGluIHRoZSBxdWVyeSBwYXJhbXMgZm9yIHRoZSByb3V0ZS4gQXMgYSBtZXJnZWRQcm9wZXJ0eSwKICAgICAgICAvLyBSb3V0ZSNxdWVyeVBhcmFtcyBpcyBhbHdheXMgYXQgbGVhc3QgYHt9YAogICAgICAgIHZhciBjb250cm9sbGVyRGVmaW5lZFF1ZXJ5UGFyYW1ldGVyQ29uZmlndXJhdGlvbiA9ICgwLCBfbWV0YWwuZ2V0KShjb250cm9sbGVyLCAncXVlcnlQYXJhbXMnKSB8fCB7fTsKICAgICAgICB2YXIgbm9ybWFsaXplZENvbnRyb2xsZXJRdWVyeVBhcmFtZXRlckNvbmZpZ3VyYXRpb24gPSAoMCwgX3V0aWxzMi5ub3JtYWxpemVDb250cm9sbGVyUXVlcnlQYXJhbXMpKGNvbnRyb2xsZXJEZWZpbmVkUXVlcnlQYXJhbWV0ZXJDb25maWd1cmF0aW9uKTsKICAgICAgICBjb21iaW5lZFF1ZXJ5UGFyYW1ldGVyQ29uZmlndXJhdGlvbiA9IG1lcmdlRWFjaFF1ZXJ5UGFyYW1zKG5vcm1hbGl6ZWRDb250cm9sbGVyUXVlcnlQYXJhbWV0ZXJDb25maWd1cmF0aW9uLCBxdWVyeVBhcmFtZXRlckNvbmZpZ3VyYXRvbik7CiAgICAgIH0gZWxzZSBpZiAoaGFzUm91dGVyRGVmaW5lZFF1ZXJ5UGFyYW1zKSB7CiAgICAgICAgLy8gdGhlIGRldmVsb3BlciBoYXMgbm90IGRlZmluZWQgYSBjb250cm9sbGVyIGJ1dCAqaGFzKiBzdXBwbGllZCByb3V0ZSBxdWVyeSBwYXJhbXMuCiAgICAgICAgLy8gR2VuZXJhdGUgYSBjbGFzcyBmb3IgdGhlbSBzbyB3ZSBjYW4gbGF0ZXIgaW5zZXJ0IGRlZmF1bHQgdmFsdWVzCiAgICAgICAgY29udHJvbGxlciA9ICgwLCBfZ2VuZXJhdGVfY29udHJvbGxlci5kZWZhdWx0KShvd25lciwgY29udHJvbGxlck5hbWUpOwogICAgICAgIGNvbWJpbmVkUXVlcnlQYXJhbWV0ZXJDb25maWd1cmF0aW9uID0gcXVlcnlQYXJhbWV0ZXJDb25maWd1cmF0b247CiAgICAgIH0KCiAgICAgIHZhciBxcHMgPSBbXTsKICAgICAgdmFyIG1hcCA9IHt9OwogICAgICB2YXIgcHJvcGVydHlOYW1lcyA9IFtdOwoKICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gY29tYmluZWRRdWVyeVBhcmFtZXRlckNvbmZpZ3VyYXRpb24pIHsKICAgICAgICBpZiAoIWNvbWJpbmVkUXVlcnlQYXJhbWV0ZXJDb25maWd1cmF0aW9uLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfSAvLyB0byBzdXBwb3J0IHRoZSBkdWJpb3VzIGZlYXR1cmUgb2YgdXNpbmcgdW5rbm93blByb3BlcnR5CiAgICAgICAgLy8gb24gcXVlcnlQYXJhbXMgY29uZmlndXJhdGlvbgoKCiAgICAgICAgaWYgKHByb3BOYW1lID09PSAndW5rbm93blByb3BlcnR5JyB8fCBwcm9wTmFtZSA9PT0gJ19zdXBlcicpIHsKICAgICAgICAgIC8vIHBvc3NpYmxlIHRvZG86IGlzc3VlIGRlcHJlY2F0aW9uIHdhcm5pbmc/CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIHZhciBkZXNjID0gY29tYmluZWRRdWVyeVBhcmFtZXRlckNvbmZpZ3VyYXRpb25bcHJvcE5hbWVdOwogICAgICAgIHZhciBzY29wZSA9IGRlc2Muc2NvcGUgfHwgJ21vZGVsJzsKICAgICAgICB2YXIgcGFydHMgPSB2b2lkIDA7CgogICAgICAgIGlmIChzY29wZSA9PT0gJ2NvbnRyb2xsZXInKSB7CiAgICAgICAgICBwYXJ0cyA9IFtdOwogICAgICAgIH0KCiAgICAgICAgdmFyIHVybEtleSA9IGRlc2MuYXMgfHwgdGhpcy5zZXJpYWxpemVRdWVyeVBhcmFtS2V5KHByb3BOYW1lKTsKICAgICAgICB2YXIgZGVmYXVsdFZhbHVlID0gKDAsIF9tZXRhbC5nZXQpKGNvbnRyb2xsZXIsIHByb3BOYW1lKTsKICAgICAgICBkZWZhdWx0VmFsdWUgPSBjb3B5RGVmYXVsdFZhbHVlKGRlZmF1bHRWYWx1ZSk7CiAgICAgICAgdmFyIHR5cGUgPSBkZXNjLnR5cGUgfHwgKDAsIF9ydW50aW1lLnR5cGVPZikoZGVmYXVsdFZhbHVlKTsKICAgICAgICB2YXIgZGVmYXVsdFZhbHVlU2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplUXVlcnlQYXJhbShkZWZhdWx0VmFsdWUsIHVybEtleSwgdHlwZSk7CiAgICAgICAgdmFyIHNjb3BlZFByb3BlcnR5TmFtZSA9IGNvbnRyb2xsZXJOYW1lICsgIjoiICsgcHJvcE5hbWU7CiAgICAgICAgdmFyIHFwID0gewogICAgICAgICAgdW5kZWNvcmF0ZWREZWZhdWx0VmFsdWU6ICgwLCBfbWV0YWwuZ2V0KShjb250cm9sbGVyLCBwcm9wTmFtZSksCiAgICAgICAgICBkZWZhdWx0VmFsdWU6IGRlZmF1bHRWYWx1ZSwKICAgICAgICAgIHNlcmlhbGl6ZWREZWZhdWx0VmFsdWU6IGRlZmF1bHRWYWx1ZVNlcmlhbGl6ZWQsCiAgICAgICAgICBzZXJpYWxpemVkVmFsdWU6IGRlZmF1bHRWYWx1ZVNlcmlhbGl6ZWQsCiAgICAgICAgICB0eXBlOiB0eXBlLAogICAgICAgICAgdXJsS2V5OiB1cmxLZXksCiAgICAgICAgICBwcm9wOiBwcm9wTmFtZSwKICAgICAgICAgIHNjb3BlZFByb3BlcnR5TmFtZTogc2NvcGVkUHJvcGVydHlOYW1lLAogICAgICAgICAgY29udHJvbGxlck5hbWU6IGNvbnRyb2xsZXJOYW1lLAogICAgICAgICAgcm91dGU6IHRoaXMsCiAgICAgICAgICBwYXJ0czogcGFydHMsCiAgICAgICAgICB2YWx1ZXM6IG51bGwsCiAgICAgICAgICBzY29wZTogc2NvcGUKICAgICAgICB9OwogICAgICAgIG1hcFtwcm9wTmFtZV0gPSBtYXBbdXJsS2V5XSA9IG1hcFtzY29wZWRQcm9wZXJ0eU5hbWVdID0gcXA7CiAgICAgICAgcXBzLnB1c2gocXApOwogICAgICAgIHByb3BlcnR5TmFtZXMucHVzaChwcm9wTmFtZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB7CiAgICAgICAgcXBzOiBxcHMsCiAgICAgICAgbWFwOiBtYXAsCiAgICAgICAgcHJvcGVydHlOYW1lczogcHJvcGVydHlOYW1lcywKICAgICAgICBzdGF0ZXM6IHsKICAgICAgICAgIC8qCiAgICAgICAgICAgIENhbGxlZCB3aGVuIGEgcXVlcnkgcGFyYW1ldGVyIGNoYW5nZXMgaW4gdGhlIFVSTCwgdGhpcyByb3V0ZSBjYXJlcwogICAgICAgICAgICBhYm91dCB0aGF0IHF1ZXJ5IHBhcmFtZXRlciwgYnV0IHRoZSByb3V0ZSBpcyBub3QgY3VycmVudGx5CiAgICAgICAgICAgIGluIHRoZSBhY3RpdmUgcm91dGUgaGllcmFyY2h5LgogICAgICAgICAgKi8KICAgICAgICAgIGluYWN0aXZlOiBmdW5jdGlvbiBpbmFjdGl2ZShwcm9wLCB2YWx1ZSkgewogICAgICAgICAgICB2YXIgcXAgPSBtYXBbcHJvcF07CgogICAgICAgICAgICBfdGhpczMuX3FwQ2hhbmdlZChwcm9wLCB2YWx1ZSwgcXApOwogICAgICAgICAgfSwKCiAgICAgICAgICAvKgogICAgICAgICAgICBDYWxsZWQgd2hlbiBhIHF1ZXJ5IHBhcmFtZXRlciBjaGFuZ2VzIGluIHRoZSBVUkwsIHRoaXMgcm91dGUgY2FyZXMKICAgICAgICAgICAgYWJvdXQgdGhhdCBxdWVyeSBwYXJhbWV0ZXIsIGFuZCB0aGUgcm91dGUgaXMgY3VycmVudGx5CiAgICAgICAgICAgIGluIHRoZSBhY3RpdmUgcm91dGUgaGllcmFyY2h5LgogICAgICAgICAgKi8KICAgICAgICAgIGFjdGl2ZTogZnVuY3Rpb24gYWN0aXZlKHByb3AsIHZhbHVlKSB7CiAgICAgICAgICAgIHZhciBxcCA9IG1hcFtwcm9wXTsKCiAgICAgICAgICAgIF90aGlzMy5fcXBDaGFuZ2VkKHByb3AsIHZhbHVlLCBxcCk7CgogICAgICAgICAgICByZXR1cm4gX3RoaXMzLl9hY3RpdmVRUENoYW5nZWQocXAsIHZhbHVlKTsKICAgICAgICAgIH0sCgogICAgICAgICAgLyoKICAgICAgICAgICAgQ2FsbGVkIHdoZW4gYSB2YWx1ZSBvZiBhIHF1ZXJ5IHBhcmFtZXRlciB0aGlzIHJvdXRlIGhhbmRsZXMgY2hhbmdlcyBpbiBhIGNvbnRyb2xsZXIKICAgICAgICAgICAgYW5kIHRoZSByb3V0ZSBpcyBjdXJyZW50bHkgaW4gdGhlIGFjdGl2ZSByb3V0ZSBoaWVyYXJjaHkuCiAgICAgICAgICAqLwogICAgICAgICAgYWxsb3dPdmVycmlkZXM6IGZ1bmN0aW9uIGFsbG93T3ZlcnJpZGVzKHByb3AsIHZhbHVlKSB7CiAgICAgICAgICAgIHZhciBxcCA9IG1hcFtwcm9wXTsKCiAgICAgICAgICAgIF90aGlzMy5fcXBDaGFuZ2VkKHByb3AsIHZhbHVlLCBxcCk7CgogICAgICAgICAgICByZXR1cm4gX3RoaXMzLl91cGRhdGluZ1FQQ2hhbmdlZChxcCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9OwogICAgfSksCgogICAgLyoqCiAgICAgIFNlbmRzIGFuIGFjdGlvbiB0byB0aGUgcm91dGVyLCB3aGljaCB3aWxsIGRlbGVnYXRlIGl0IHRvIHRoZSBjdXJyZW50bHkKICAgICAgYWN0aXZlIHJvdXRlIGhpZXJhcmNoeSBwZXIgdGhlIGJ1YmJsaW5nIHJ1bGVzIGV4cGxhaW5lZCB1bmRlciBgYWN0aW9uc2AuCiAgICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlci5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdpbmRleCcpOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHRyYWNrKGFyZykgewogICAgICAgICAgICBjb25zb2xlLmxvZyhhcmcsICd3YXMgY2xpY2tlZCcpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL2luZGV4LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgdHJhY2tJZkRlYnVnKGFyZykgewogICAgICAgICAgICBpZiAoZGVidWcpIHsKICAgICAgICAgICAgICB0aGlzLnNlbmQoJ3RyYWNrJywgYXJnKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHNlbmQKICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIGFjdGlvbiB0byB0cmlnZ2VyCiAgICAgIEBwYXJhbSB7Li4uKn0gYXJncwogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHNlbmQ6IGZ1bmN0aW9uIHNlbmQoKSB7CiAgICAgIGZvciAodmFyIF9sZW40ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuNCksIF9rZXk0ID0gMDsgX2tleTQgPCBfbGVuNDsgX2tleTQrKykgewogICAgICAgIGFyZ3NbX2tleTRdID0gYXJndW1lbnRzW19rZXk0XTsKICAgICAgfQoKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF0dGVtcHRlZCB0byBjYWxsIC5zZW5kKCkgd2l0aCB0aGUgYWN0aW9uICciICsgYXJnc1swXSArICInIG9uIHRoZSBkZXN0cm95ZWQgcm91dGUgJyIgKyB0aGlzLnJvdXRlTmFtZSArICInLiIsICF0aGlzLmlzRGVzdHJveWluZyAmJiAhdGhpcy5pc0Rlc3Ryb3llZCkpOwoKICAgICAgaWYgKHRoaXMuX3JvdXRlciAmJiB0aGlzLl9yb3V0ZXIuX3JvdXRlck1pY3JvbGliIHx8ICEoMCwgX2RlYnVnLmlzVGVzdGluZykoKSkgewogICAgICAgIHZhciBfdGhpcyRfcm91dGVyNDsKCiAgICAgICAgKF90aGlzJF9yb3V0ZXI0ID0gdGhpcy5fcm91dGVyKS5zZW5kLmFwcGx5KF90aGlzJF9yb3V0ZXI0LCBhcmdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgbmFtZSA9IGFyZ3Muc2hpZnQoKTsKICAgICAgICB2YXIgYWN0aW9uID0gdGhpcy5hY3Rpb25zW25hbWVdOwoKICAgICAgICBpZiAoYWN0aW9uKSB7CiAgICAgICAgICByZXR1cm4gYWN0aW9uLmFwcGx5KHRoaXMsIGFyZ3MpOwogICAgICAgIH0KICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgVGhlIGNvbnRyb2xsZXIgYXNzb2NpYXRlZCB3aXRoIHRoaXMgcm91dGUuCiAgICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlcy9mb3JtLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgd2lsbFRyYW5zaXRpb24odHJhbnNpdGlvbikgewogICAgICAgICAgICBpZiAodGhpcy5jb250cm9sbGVyLmdldCgndXNlckhhc0VudGVyZWREYXRhJykgJiYKICAgICAgICAgICAgICAgICFjb25maXJtKCdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gYWJhbmRvbiBwcm9ncmVzcz8nKSkgewogICAgICAgICAgICAgIHRyYW5zaXRpb24uYWJvcnQoKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAvLyBCdWJibGUgdGhlIGB3aWxsVHJhbnNpdGlvbmAgYWN0aW9uIHNvIHRoYXQKICAgICAgICAgICAgICAvLyBwYXJlbnQgcm91dGVzIGNhbiBkZWNpZGUgd2hldGhlciBvciBub3QgdG8gYWJvcnQuCiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQHByb3BlcnR5IGNvbnRyb2xsZXIKICAgICAgQHR5cGUgQ29udHJvbGxlcgogICAgICBAc2luY2UgMS42LjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIGFjdGlvbnM6IHsKICAgICAgLyoqCiAgICAgIFRoaXMgYWN0aW9uIGlzIGNhbGxlZCB3aGVuIG9uZSBvciBtb3JlIHF1ZXJ5IHBhcmFtcyBoYXZlIGNoYW5nZWQuIEJ1YmJsZXMuCiAgICAgICAgICAgQG1ldGhvZCBxdWVyeVBhcmFtc0RpZENoYW5nZQogICAgICBAcGFyYW0gY2hhbmdlZCB7T2JqZWN0fSBLZXlzIGFyZSBuYW1lcyBvZiBxdWVyeSBwYXJhbXMgdGhhdCBoYXZlIGNoYW5nZWQuCiAgICAgIEBwYXJhbSB0b3RhbFByZXNlbnQge09iamVjdH0gS2V5cyBhcmUgbmFtZXMgb2YgcXVlcnkgcGFyYW1zIHRoYXQgYXJlIGN1cnJlbnRseSBzZXQuCiAgICAgIEBwYXJhbSByZW1vdmVkIHtPYmplY3R9IEtleXMgYXJlIG5hbWVzIG9mIHF1ZXJ5IHBhcmFtcyB0aGF0IGhhdmUgYmVlbiByZW1vdmVkLgogICAgICBAcmV0dXJucyB7Ym9vbGVhbn0KICAgICAgQHByaXZhdGUKICAgICAgKi8KICAgICAgcXVlcnlQYXJhbXNEaWRDaGFuZ2U6IGZ1bmN0aW9uIHF1ZXJ5UGFyYW1zRGlkQ2hhbmdlKGNoYW5nZWQsIF90b3RhbFByZXNlbnQsIHJlbW92ZWQpIHsKICAgICAgICB2YXIgcXBNYXAgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ19xcCcpLm1hcDsKICAgICAgICB2YXIgdG90YWxDaGFuZ2VkID0gT2JqZWN0LmtleXMoY2hhbmdlZCkuY29uY2F0KE9iamVjdC5rZXlzKHJlbW92ZWQpKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0b3RhbENoYW5nZWQubGVuZ3RoOyArK2kpIHsKICAgICAgICAgIHZhciBxcCA9IHFwTWFwW3RvdGFsQ2hhbmdlZFtpXV07CgogICAgICAgICAgaWYgKHFwICYmICgwLCBfbWV0YWwuZ2V0KSh0aGlzLl9vcHRpb25zRm9yUXVlcnlQYXJhbShxcCksICdyZWZyZXNoTW9kZWwnKSAmJiB0aGlzLl9yb3V0ZXIuY3VycmVudFN0YXRlKSB7CiAgICAgICAgICAgIHRoaXMucmVmcmVzaCgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9LAogICAgICBmaW5hbGl6ZVF1ZXJ5UGFyYW1DaGFuZ2U6IGZ1bmN0aW9uIGZpbmFsaXplUXVlcnlQYXJhbUNoYW5nZShwYXJhbXMsIGZpbmFsUGFyYW1zLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgaWYgKHRoaXMuZnVsbFJvdXRlTmFtZSAhPT0gJ2FwcGxpY2F0aW9uJykgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfSAvLyBUcmFuc2l0aW9uIG9iamVjdCBpcyBhYnNlbnQgZm9yIGludGVybWVkaWF0ZSB0cmFuc2l0aW9ucy4KCgogICAgICAgIGlmICghdHJhbnNpdGlvbikgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgdmFyIHJvdXRlSW5mb3MgPSB0cmFuc2l0aW9uW19yb3V0ZXJfanMuU1RBVEVfU1lNQk9MXS5yb3V0ZUluZm9zOwogICAgICAgIHZhciByb3V0ZXIgPSB0aGlzLl9yb3V0ZXI7CgogICAgICAgIHZhciBxcE1ldGEgPSByb3V0ZXIuX3F1ZXJ5UGFyYW1zRm9yKHJvdXRlSW5mb3MpOwoKICAgICAgICB2YXIgY2hhbmdlcyA9IHJvdXRlci5fcXBVcGRhdGVzOwogICAgICAgIHZhciBxcFVwZGF0ZWQgPSBmYWxzZTsKICAgICAgICB2YXIgcmVwbGFjZVVybDsKICAgICAgICAoMCwgX3V0aWxzMi5zdGFzaFBhcmFtTmFtZXMpKHJvdXRlciwgcm91dGVJbmZvcyk7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcXBNZXRhLnFwcy5sZW5ndGg7ICsraSkgewogICAgICAgICAgdmFyIHFwID0gcXBNZXRhLnFwc1tpXTsKICAgICAgICAgIHZhciByb3V0ZSA9IHFwLnJvdXRlOwogICAgICAgICAgdmFyIGNvbnRyb2xsZXIgPSByb3V0ZS5jb250cm9sbGVyOwogICAgICAgICAgdmFyIHByZXNlbnRLZXkgPSBxcC51cmxLZXkgaW4gcGFyYW1zICYmIHFwLnVybEtleTsgLy8gRG8gYSByZXZlcnNlIGxvb2t1cCB0byBzZWUgaWYgdGhlIGNoYW5nZWQgcXVlcnkKICAgICAgICAgIC8vIHBhcmFtIFVSTCBrZXkgY29ycmVzcG9uZHMgdG8gYSBRUCBwcm9wZXJ0eSBvbgogICAgICAgICAgLy8gdGhpcyBjb250cm9sbGVyLgoKICAgICAgICAgIHZhciB2YWx1ZSA9IHZvaWQgMCwKICAgICAgICAgICAgICBzdmFsdWUgPSB2b2lkIDA7CgogICAgICAgICAgaWYgKGNoYW5nZXMuaGFzKHFwLnVybEtleSkpIHsKICAgICAgICAgICAgLy8gVmFsdWUgdXBkYXRlZCBpbi9iZWZvcmUgc2V0dXBDb250cm9sbGVyCiAgICAgICAgICAgIHZhbHVlID0gKDAsIF9tZXRhbC5nZXQpKGNvbnRyb2xsZXIsIHFwLnByb3ApOwogICAgICAgICAgICBzdmFsdWUgPSByb3V0ZS5zZXJpYWxpemVRdWVyeVBhcmFtKHZhbHVlLCBxcC51cmxLZXksIHFwLnR5cGUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKHByZXNlbnRLZXkpIHsKICAgICAgICAgICAgICBzdmFsdWUgPSBwYXJhbXNbcHJlc2VudEtleV07CgogICAgICAgICAgICAgIGlmIChzdmFsdWUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgdmFsdWUgPSByb3V0ZS5kZXNlcmlhbGl6ZVF1ZXJ5UGFyYW0oc3ZhbHVlLCBxcC51cmxLZXksIHFwLnR5cGUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAvLyBObyBRUCBwcm92aWRlZDsgdXNlIGRlZmF1bHQgdmFsdWUuCiAgICAgICAgICAgICAgc3ZhbHVlID0gcXAuc2VyaWFsaXplZERlZmF1bHRWYWx1ZTsKICAgICAgICAgICAgICB2YWx1ZSA9IGNvcHlEZWZhdWx0VmFsdWUocXAuZGVmYXVsdFZhbHVlKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQoKICAgICAgICAgIGNvbnRyb2xsZXIuX3FwRGVsZWdhdGUgPSAoMCwgX21ldGFsLmdldCkocm91dGUsICdfcXAuc3RhdGVzLmluYWN0aXZlJyk7CiAgICAgICAgICB2YXIgdGhpc1F1ZXJ5UGFyYW1DaGFuZ2VkID0gc3ZhbHVlICE9PSBxcC5zZXJpYWxpemVkVmFsdWU7CgogICAgICAgICAgaWYgKHRoaXNRdWVyeVBhcmFtQ2hhbmdlZCkgewogICAgICAgICAgICBpZiAodHJhbnNpdGlvbi5xdWVyeVBhcmFtc09ubHkgJiYgcmVwbGFjZVVybCAhPT0gZmFsc2UpIHsKICAgICAgICAgICAgICB2YXIgb3B0aW9ucyA9IHJvdXRlLl9vcHRpb25zRm9yUXVlcnlQYXJhbShxcCk7CgogICAgICAgICAgICAgIHZhciByZXBsYWNlQ29uZmlnVmFsdWUgPSAoMCwgX21ldGFsLmdldCkob3B0aW9ucywgJ3JlcGxhY2UnKTsKCiAgICAgICAgICAgICAgaWYgKHJlcGxhY2VDb25maWdWYWx1ZSkgewogICAgICAgICAgICAgICAgcmVwbGFjZVVybCA9IHRydWU7CiAgICAgICAgICAgICAgfSBlbHNlIGlmIChyZXBsYWNlQ29uZmlnVmFsdWUgPT09IGZhbHNlKSB7CiAgICAgICAgICAgICAgICAvLyBFeHBsaWNpdCBwdXNoU3RhdGUgd2lucyBvdmVyIGFueSBvdGhlciByZXBsYWNlU3RhdGVzLgogICAgICAgICAgICAgICAgcmVwbGFjZVVybCA9IGZhbHNlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgKDAsIF9tZXRhbC5zZXQpKGNvbnRyb2xsZXIsIHFwLnByb3AsIHZhbHVlKTsKICAgICAgICAgICAgcXBVcGRhdGVkID0gdHJ1ZTsKICAgICAgICAgIH0gLy8gU3Rhc2ggY3VycmVudCBzZXJpYWxpemVkIHZhbHVlIG9mIGNvbnRyb2xsZXIuCgoKICAgICAgICAgIHFwLnNlcmlhbGl6ZWRWYWx1ZSA9IHN2YWx1ZTsKICAgICAgICAgIHZhciB0aGlzUXVlcnlQYXJhbUhhc0RlZmF1bHRWYWx1ZSA9IHFwLnNlcmlhbGl6ZWREZWZhdWx0VmFsdWUgPT09IHN2YWx1ZTsKCiAgICAgICAgICBpZiAoIXRoaXNRdWVyeVBhcmFtSGFzRGVmYXVsdFZhbHVlIHx8IHRyYW5zaXRpb24uX2tlZXBEZWZhdWx0UXVlcnlQYXJhbVZhbHVlcykgewogICAgICAgICAgICBmaW5hbFBhcmFtcy5wdXNoKHsKICAgICAgICAgICAgICB2YWx1ZTogc3ZhbHVlLAogICAgICAgICAgICAgIHZpc2libGU6IHRydWUsCiAgICAgICAgICAgICAga2V5OiBwcmVzZW50S2V5IHx8IHFwLnVybEtleQogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9IC8vIFNvbWUgUVBzIGhhdmUgYmVlbiB1cGRhdGVkLCBhbmQgdGhvc2UgY2hhbmdlcyBuZWVkIHRvIGJlIHByb3BvZ2F0ZWQKICAgICAgICAvLyBpbW1lZGlhdGVseS4gRXZlbnR1YWxseSwgd2Ugc2hvdWxkIHdvcmsgb24gbWFraW5nIHRoaXMgYXN5bmMgc29tZWhvdy4KCgogICAgICAgIGlmICh0cnVlCiAgICAgICAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgICAgICAgJiYgcXBVcGRhdGVkID09PSB0cnVlKSB7CiAgICAgICAgICAoMCwgX21ldGFsLmZsdXNoQXN5bmNPYnNlcnZlcnMpKGZhbHNlKTsKICAgICAgICB9CgogICAgICAgIGlmIChyZXBsYWNlVXJsKSB7CiAgICAgICAgICB0cmFuc2l0aW9uLm1ldGhvZCgncmVwbGFjZScpOwogICAgICAgIH0KCiAgICAgICAgcXBNZXRhLnFwcy5mb3JFYWNoKGZ1bmN0aW9uIChxcCkgewogICAgICAgICAgdmFyIHJvdXRlUXBNZXRhID0gKDAsIF9tZXRhbC5nZXQpKHFwLnJvdXRlLCAnX3FwJyk7CiAgICAgICAgICB2YXIgZmluYWxpemVkQ29udHJvbGxlciA9IHFwLnJvdXRlLmNvbnRyb2xsZXI7CiAgICAgICAgICBmaW5hbGl6ZWRDb250cm9sbGVyLl9xcERlbGVnYXRlID0gKDAsIF9tZXRhbC5nZXQpKHJvdXRlUXBNZXRhLCAnc3RhdGVzLmFjdGl2ZScpOwogICAgICAgIH0pOwoKICAgICAgICByb3V0ZXIuX3FwVXBkYXRlcy5jbGVhcigpOwoKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgIH0KICB9KTsKICB2YXIgUk9VVEVSX0VWRU5UX0RFUFJFQ0FUSU9OUzsKICBfZXhwb3J0cy5ST1VURVJfRVZFTlRfREVQUkVDQVRJT05TID0gUk9VVEVSX0VWRU5UX0RFUFJFQ0FUSU9OUzsKCiAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuUk9VVEVSX0VWRU5UUykgewogICAgX2V4cG9ydHMuUk9VVEVSX0VWRU5UX0RFUFJFQ0FUSU9OUyA9IFJPVVRFUl9FVkVOVF9ERVBSRUNBVElPTlMgPSB7CiAgICAgIG9uOiBmdW5jdGlvbiBvbihuYW1lKSB7CiAgICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgICAgdmFyIGhhc0RpZFRyYW5zaXRpb24gPSBuYW1lID09PSAnZGlkVHJhbnNpdGlvbic7CiAgICAgICAgdmFyIGhhc1dpbGxUcmFuc2l0aW9uID0gbmFtZSA9PT0gJ3dpbGxUcmFuc2l0aW9uJzsKCiAgICAgICAgaWYgKGhhc0RpZFRyYW5zaXRpb24pIHsKICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoJ1lvdSBhdHRlbXB0ZWQgdG8gbGlzdGVuIHRvIHRoZSAiZGlkVHJhbnNpdGlvbiIgZXZlbnQgd2hpY2ggaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGluamVjdCB0aGUgcm91dGVyIHNlcnZpY2UgYW5kIGxpc3RlbiB0byB0aGUgInJvdXRlRGlkQ2hhbmdlIiBldmVudC4nLCBmYWxzZSwgewogICAgICAgICAgICBpZDogJ2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJywKICAgICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJwogICAgICAgICAgfSkpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGhhc1dpbGxUcmFuc2l0aW9uKSB7CiAgICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdZb3UgYXR0ZW1wdGVkIHRvIGxpc3RlbiB0byB0aGUgIndpbGxUcmFuc2l0aW9uIiBldmVudCB3aGljaCBpcyBkZXByZWNhdGVkLiBQbGVhc2UgaW5qZWN0IHRoZSByb3V0ZXIgc2VydmljZSBhbmQgbGlzdGVuIHRvIHRoZSAicm91dGVXaWxsQ2hhbmdlIiBldmVudC4nLCBmYWxzZSwgewogICAgICAgICAgICBpZDogJ2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJywKICAgICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJwogICAgICAgICAgfSkpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKICAgIFJvdXRlLnJlb3BlbihST1VURVJfRVZFTlRfREVQUkVDQVRJT05TLCB7CiAgICAgIF9wYXJhbXNGb3I6IGZ1bmN0aW9uIF9wYXJhbXNGb3Iocm91dGVOYW1lLCBwYXJhbXMpIHsKICAgICAgICB2YXIgdHJhbnNpdGlvbiA9IHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWIuYWN0aXZlVHJhbnNpdGlvbjsKCiAgICAgICAgaWYgKHRyYW5zaXRpb24gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcmV0dXJuIHRoaXMucGFyYW1zRm9yKHJvdXRlTmFtZSk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcGFyYW1zOwogICAgICB9CiAgICB9KTsKICB9CgogIGlmICh0cnVlCiAgLyogRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCAqLwogICkgewogICAgICAoMCwgX3J1bnRpbWUuc2V0RnJhbWV3b3JrQ2xhc3MpKFJvdXRlKTsKICAgIH0KCiAgdmFyIF9kZWZhdWx0ID0gUm91dGU7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vcm91dGVyIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIiwgIkBlbWJlci9lcnJvciIsICJAZW1iZXIvcG9seWZpbGxzIiwgIkBlbWJlci9ydW5sb29wIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL2FwaSIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi91dGlscyIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vZHNsIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3N5c3RlbS9yb3V0ZSIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vcm91dGVyX3N0YXRlIiwgInJvdXRlcl9qcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfbWV0YWwsIF9vd25lciwgX3J1bnRpbWUsIF9kZWJ1ZywgX2RlcHJlY2F0ZWRGZWF0dXJlcywgX2Vycm9yMywgX3BvbHlmaWxscywgX3J1bmxvb3AsIF9hcGksIF91dGlscywgX2RzbCwgX3JvdXRlLCBfcm91dGVyX3N0YXRlLCBfcm91dGVyX2pzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy50cmlnZ2VyRXZlbnQgPSBfdHJpZ2dlckV2ZW50OwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIGZ1bmN0aW9uIGRlZmF1bHREaWRUcmFuc2l0aW9uKGluZm9zKSB7CiAgICB1cGRhdGVQYXRocyh0aGlzKTsKCiAgICB0aGlzLl9jYW5jZWxTbG93VHJhbnNpdGlvblRpbWVyKCk7CgogICAgdGhpcy5ub3RpZnlQcm9wZXJ0eUNoYW5nZSgndXJsJyk7CiAgICB0aGlzLnNldCgnY3VycmVudFN0YXRlJywgdGhpcy50YXJnZXRTdGF0ZSk7IC8vIFB1dCB0aGlzIGluIHRoZSBydW5sb29wIHNvIHVybCB3aWxsIGJlIGFjY3VyYXRlLiBTZWVtcwogICAgLy8gbGVzcyBzdXJwcmlzaW5nIHRoYW4gZGlkVHJhbnNpdGlvbiBiZWluZyBvdXQgb2Ygc3luYy4KCiAgICAoMCwgX3J1bmxvb3Aub25jZSkodGhpcywgdGhpcy50cmlnZ2VyLCAnZGlkVHJhbnNpdGlvbicpOwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBpZiAoKDAsIF9tZXRhbC5nZXQpKHRoaXMsICduYW1lc3BhY2UnKS5MT0dfVFJBTlNJVElPTlMpIHsKICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZQogICAgICAgIGNvbnNvbGUubG9nKCJUcmFuc2l0aW9uZWQgaW50byAnIiArIEVtYmVyUm91dGVyLl9yb3V0ZVBhdGgoaW5mb3MpICsgIiciKTsKICAgICAgfQogICAgfQogIH0KCiAgZnVuY3Rpb24gZGVmYXVsdFdpbGxUcmFuc2l0aW9uKG9sZEluZm9zLCBuZXdJbmZvcywgdHJhbnNpdGlvbikgewogICAgKDAsIF9ydW5sb29wLm9uY2UpKHRoaXMsIHRoaXMudHJpZ2dlciwgJ3dpbGxUcmFuc2l0aW9uJywgdHJhbnNpdGlvbik7CgogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgKSB7CiAgICAgIGlmICgoMCwgX21ldGFsLmdldCkodGhpcywgJ25hbWVzcGFjZScpLkxPR19UUkFOU0lUSU9OUykgewogICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlCiAgICAgICAgY29uc29sZS5sb2coIlByZXBhcmluZyB0byB0cmFuc2l0aW9uIGZyb20gJyIgKyBFbWJlclJvdXRlci5fcm91dGVQYXRoKG9sZEluZm9zKSArICInIHRvICciICsgRW1iZXJSb3V0ZXIuX3JvdXRlUGF0aChuZXdJbmZvcykgKyAiJyIpOwogICAgICB9CiAgICB9CiAgfQoKICBmdW5jdGlvbiBLKCkgewogICAgcmV0dXJuIHRoaXM7CiAgfQoKICB2YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7CiAgLyoqCiAgICBUaGUgYEVtYmVyUm91dGVyYCBjbGFzcyBtYW5hZ2VzIHRoZSBhcHBsaWNhdGlvbiBzdGF0ZSBhbmQgVVJMcy4gUmVmZXIgdG8KICAgIHRoZSBbcm91dGluZyBndWlkZV0oaHR0cHM6Ly9ndWlkZXMuZW1iZXJqcy5jb20vcmVsZWFzZS9yb3V0aW5nLykgZm9yIGRvY3VtZW50YXRpb24uCiAgCiAgICBAY2xhc3MgRW1iZXJSb3V0ZXIKICAgIEBleHRlbmRzIEVtYmVyT2JqZWN0CiAgICBAdXNlcyBFdmVudGVkCiAgICBAcHVibGljCiAgKi8KCiAgdmFyIEVtYmVyUm91dGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9FbWJlck9iamVjdCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEVtYmVyUm91dGVyLCBfRW1iZXJPYmplY3QpOwoKICAgIGZ1bmN0aW9uIEVtYmVyUm91dGVyKCkgewogICAgICB2YXIgX3RoaXM7CgogICAgICBfdGhpcyA9IF9FbWJlck9iamVjdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICAgIF90aGlzLmN1cnJlbnRVUkwgPSBudWxsOwogICAgICBfdGhpcy5jdXJyZW50Um91dGVOYW1lID0gbnVsbDsKICAgICAgX3RoaXMuY3VycmVudFBhdGggPSBudWxsOwogICAgICBfdGhpcy5jdXJyZW50Um91dGUgPSBudWxsOwogICAgICBfdGhpcy5fcXBDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIF90aGlzLl9xcFVwZGF0ZXMgPSBuZXcgU2V0KCk7CiAgICAgIF90aGlzLl9oYW5kbGVkRXJyb3JzID0gbmV3IFNldCgpOwogICAgICBfdGhpcy5fZW5naW5lSW5zdGFuY2VzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgX3RoaXMuX2VuZ2luZUluZm9CeVJvdXRlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgX3RoaXMuY3VycmVudFN0YXRlID0gbnVsbDsKICAgICAgX3RoaXMudGFyZ2V0U3RhdGUgPSBudWxsOwoKICAgICAgX3RoaXMuX3Jlc2V0UXVldWVkUXVlcnlQYXJhbWV0ZXJDaGFuZ2VzKCk7CgogICAgICByZXR1cm4gX3RoaXM7CiAgICB9CgogICAgdmFyIF9wcm90byA9IEVtYmVyUm91dGVyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uX2luaXRSb3V0ZXJKcyA9IGZ1bmN0aW9uIF9pbml0Um91dGVySnMoKSB7CiAgICAgIHZhciBsb2NhdGlvbiA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnbG9jYXRpb24nKTsKICAgICAgdmFyIHJvdXRlciA9IHRoaXM7CiAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICB2YXIgc2VlbiA9IE9iamVjdC5jcmVhdGUobnVsbCk7CgogICAgICB2YXIgUHJpdmF0ZVJvdXRlciA9CiAgICAgIC8qI19fUFVSRV9fKi8KICAgICAgZnVuY3Rpb24gKF9Sb3V0ZXIpIHsKICAgICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUHJpdmF0ZVJvdXRlciwgX1JvdXRlcik7CgogICAgICAgIGZ1bmN0aW9uIFByaXZhdGVSb3V0ZXIoKSB7CiAgICAgICAgICByZXR1cm4gX1JvdXRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICAgICAgfQoKICAgICAgICB2YXIgX3Byb3RvMiA9IFByaXZhdGVSb3V0ZXIucHJvdG90eXBlOwoKICAgICAgICBfcHJvdG8yLmdldFJvdXRlID0gZnVuY3Rpb24gZ2V0Um91dGUobmFtZSkgewogICAgICAgICAgdmFyIHJvdXRlTmFtZSA9IG5hbWU7CiAgICAgICAgICB2YXIgcm91dGVPd25lciA9IG93bmVyOwogICAgICAgICAgdmFyIGVuZ2luZUluZm8gPSByb3V0ZXIuX2VuZ2luZUluZm9CeVJvdXRlW3JvdXRlTmFtZV07CgogICAgICAgICAgaWYgKGVuZ2luZUluZm8pIHsKICAgICAgICAgICAgdmFyIGVuZ2luZUluc3RhbmNlID0gcm91dGVyLl9nZXRFbmdpbmVJbnN0YW5jZShlbmdpbmVJbmZvKTsKCiAgICAgICAgICAgIHJvdXRlT3duZXIgPSBlbmdpbmVJbnN0YW5jZTsKICAgICAgICAgICAgcm91dGVOYW1lID0gZW5naW5lSW5mby5sb2NhbEZ1bGxOYW1lOwogICAgICAgICAgfQoKICAgICAgICAgIHZhciBmdWxsUm91dGVOYW1lID0gInJvdXRlOiIgKyByb3V0ZU5hbWU7CiAgICAgICAgICB2YXIgcm91dGUgPSByb3V0ZU93bmVyLmxvb2t1cChmdWxsUm91dGVOYW1lKTsKCiAgICAgICAgICBpZiAoc2VlbltuYW1lXSkgewogICAgICAgICAgICByZXR1cm4gcm91dGU7CiAgICAgICAgICB9CgogICAgICAgICAgc2VlbltuYW1lXSA9IHRydWU7CgogICAgICAgICAgaWYgKCFyb3V0ZSkgewogICAgICAgICAgICB2YXIgRGVmYXVsdFJvdXRlID0gcm91dGVPd25lci5mYWN0b3J5Rm9yKCdyb3V0ZTpiYXNpYycpLmNsYXNzOwogICAgICAgICAgICByb3V0ZU93bmVyLnJlZ2lzdGVyKGZ1bGxSb3V0ZU5hbWUsIERlZmF1bHRSb3V0ZS5leHRlbmQoKSk7CiAgICAgICAgICAgIHJvdXRlID0gcm91dGVPd25lci5sb29rdXAoZnVsbFJvdXRlTmFtZSk7CgogICAgICAgICAgICBpZiAoZmFsc2UKICAgICAgICAgICAgLyogREVCVUcgKi8KICAgICAgICAgICAgKSB7CiAgICAgICAgICAgICAgaWYgKCgwLCBfbWV0YWwuZ2V0KShyb3V0ZXIsICduYW1lc3BhY2UuTE9HX0FDVElWRV9HRU5FUkFUSU9OJykpIHsKICAgICAgICAgICAgICAgICgwLCBfZGVidWcuaW5mbykoImdlbmVyYXRlZCAtPiAiICsgZnVsbFJvdXRlTmFtZSwgewogICAgICAgICAgICAgICAgICBmdWxsTmFtZTogZnVsbFJvdXRlTmFtZQogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgcm91dGUuX3NldFJvdXRlTmFtZShyb3V0ZU5hbWUpOwoKICAgICAgICAgIGlmIChlbmdpbmVJbmZvICYmICEoMCwgX3JvdXRlLmhhc0RlZmF1bHRTZXJpYWxpemUpKHJvdXRlKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RlZmluaW5nIGEgY3VzdG9tIHNlcmlhbGl6ZSBtZXRob2Qgb24gYW4gRW5naW5lIHJvdXRlIGlzIG5vdCBzdXBwb3J0ZWQuJyk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIHJvdXRlOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzIuZ2V0U2VyaWFsaXplciA9IGZ1bmN0aW9uIGdldFNlcmlhbGl6ZXIobmFtZSkgewogICAgICAgICAgdmFyIGVuZ2luZUluZm8gPSByb3V0ZXIuX2VuZ2luZUluZm9CeVJvdXRlW25hbWVdOyAvLyBJZiB0aGlzIGlzIG5vdCBhbiBFbmdpbmUgcm91dGUsIHdlIGZhbGwgYmFjayB0byB0aGUgaGFuZGxlciBmb3Igc2VyaWFsaXphdGlvbgoKICAgICAgICAgIGlmICghZW5naW5lSW5mbykgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIGVuZ2luZUluZm8uc2VyaWFsaXplTWV0aG9kIHx8IF9yb3V0ZS5kZWZhdWx0U2VyaWFsaXplOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzIudXBkYXRlVVJMID0gZnVuY3Rpb24gdXBkYXRlVVJMKHBhdGgpIHsKICAgICAgICAgICgwLCBfcnVubG9vcC5vbmNlKShmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIGxvY2F0aW9uLnNldFVSTChwYXRoKTsKICAgICAgICAgICAgKDAsIF9tZXRhbC5zZXQpKHJvdXRlciwgJ2N1cnJlbnRVUkwnLCBwYXRoKTsKICAgICAgICAgIH0pOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzIuZGlkVHJhbnNpdGlvbiA9IGZ1bmN0aW9uIGRpZFRyYW5zaXRpb24oaW5mb3MpIHsKICAgICAgICAgIGlmIChfZGVwcmVjYXRlZEZlYXR1cmVzLlJPVVRFUl9FVkVOVFMpIHsKICAgICAgICAgICAgaWYgKHJvdXRlci5kaWRUcmFuc2l0aW9uICE9PSBkZWZhdWx0RGlkVHJhbnNpdGlvbikgewogICAgICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoJ1lvdSBhdHRlbXB0ZWQgdG8gb3ZlcnJpZGUgdGhlICJkaWRUcmFuc2l0aW9uIiBtZXRob2Qgd2hpY2ggaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGluamVjdCB0aGUgcm91dGVyIHNlcnZpY2UgYW5kIGxpc3RlbiB0byB0aGUgInJvdXRlRGlkQ2hhbmdlIiBldmVudC4nLCBmYWxzZSwgewogICAgICAgICAgICAgICAgaWQ6ICdkZXByZWNhdGUtcm91dGVyLWV2ZW50cycsCiAgICAgICAgICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJwogICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQoKICAgICAgICAgIHJvdXRlci5kaWRUcmFuc2l0aW9uKGluZm9zKTsKICAgICAgICB9OwoKICAgICAgICBfcHJvdG8yLndpbGxUcmFuc2l0aW9uID0gZnVuY3Rpb24gd2lsbFRyYW5zaXRpb24ob2xkSW5mb3MsIG5ld0luZm9zLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5ST1VURVJfRVZFTlRTKSB7CiAgICAgICAgICAgIGlmIChyb3V0ZXIud2lsbFRyYW5zaXRpb24gIT09IGRlZmF1bHRXaWxsVHJhbnNpdGlvbikgewogICAgICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoJ1lvdSBhdHRlbXB0ZWQgdG8gb3ZlcnJpZGUgdGhlICJ3aWxsVHJhbnNpdGlvbiIgbWV0aG9kIHdoaWNoIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSBpbmplY3QgdGhlIHJvdXRlciBzZXJ2aWNlIGFuZCBsaXN0ZW4gdG8gdGhlICJyb3V0ZVdpbGxDaGFuZ2UiIGV2ZW50LicsIGZhbHNlLCB7CiAgICAgICAgICAgICAgICBpZDogJ2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJywKICAgICAgICAgICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfZGVwcmVjYXRlLXJvdXRlci1ldmVudHMnCiAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgcm91dGVyLndpbGxUcmFuc2l0aW9uKG9sZEluZm9zLCBuZXdJbmZvcywgdHJhbnNpdGlvbik7CiAgICAgICAgfTsKCiAgICAgICAgX3Byb3RvMi50cmlnZ2VyRXZlbnQgPSBmdW5jdGlvbiB0cmlnZ2VyRXZlbnQocm91dGVJbmZvcywgaWdub3JlRmFpbHVyZSwgbmFtZSwgYXJncykgewogICAgICAgICAgcmV0dXJuIF90cmlnZ2VyRXZlbnQuYmluZChyb3V0ZXIpKHJvdXRlSW5mb3MsIGlnbm9yZUZhaWx1cmUsIG5hbWUsIGFyZ3MpOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzIucm91dGVXaWxsQ2hhbmdlID0gZnVuY3Rpb24gcm91dGVXaWxsQ2hhbmdlKHRyYW5zaXRpb24pIHsKICAgICAgICAgIHJvdXRlci50cmlnZ2VyKCdyb3V0ZVdpbGxDaGFuZ2UnLCB0cmFuc2l0aW9uKTsKICAgICAgICB9OwoKICAgICAgICBfcHJvdG8yLnJvdXRlRGlkQ2hhbmdlID0gZnVuY3Rpb24gcm91dGVEaWRDaGFuZ2UodHJhbnNpdGlvbikgewogICAgICAgICAgcm91dGVyLnNldCgnY3VycmVudFJvdXRlJywgdHJhbnNpdGlvbi50byk7CiAgICAgICAgICAoMCwgX3J1bmxvb3Aub25jZSkoZnVuY3Rpb24gKCkgewogICAgICAgICAgICByb3V0ZXIudHJpZ2dlcigncm91dGVEaWRDaGFuZ2UnLCB0cmFuc2l0aW9uKTsKICAgICAgICAgIH0pOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzIudHJhbnNpdGlvbkRpZEVycm9yID0gZnVuY3Rpb24gdHJhbnNpdGlvbkRpZEVycm9yKGVycm9yLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICBpZiAoZXJyb3Iud2FzQWJvcnRlZCB8fCB0cmFuc2l0aW9uLmlzQWJvcnRlZCkgewogICAgICAgICAgICAvLyBJZiB0aGUgZXJyb3Igd2FzIGEgdHJhbnNpdGlvbiBlcm9yciBvciB0aGUgdHJhbnNpdGlvbiBhYm9ydGVkCiAgICAgICAgICAgIC8vIGxvZyB0aGUgYWJvcnQuCiAgICAgICAgICAgIHJldHVybiAoMCwgX3JvdXRlcl9qcy5sb2dBYm9ydCkodHJhbnNpdGlvbik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvLyBPdGhlcndpc2UgdHJpZ2dlciB0aGUgImVycm9yIiBldmVudCB0byBhdHRlbXB0IGFuIGludGVybWVkaWF0ZQogICAgICAgICAgICAvLyB0cmFuc2l0aW9uIGludG8gYW4gZXJyb3Igc3Vic3RhdGUKICAgICAgICAgICAgdHJhbnNpdGlvbi50cmlnZ2VyKGZhbHNlLCAnZXJyb3InLCBlcnJvci5lcnJvciwgdHJhbnNpdGlvbiwgZXJyb3Iucm91dGUpOwoKICAgICAgICAgICAgaWYgKHJvdXRlci5faXNFcnJvckhhbmRsZWQoZXJyb3IuZXJyb3IpKSB7CiAgICAgICAgICAgICAgLy8gSWYgd2UgaGFuZGxlZCB0aGUgZXJyb3Igd2l0aCBhIHN1YnN0YXRlIGp1c3Qgcm9sbCB0aGUgc3RhdGUgYmFjayBvbgogICAgICAgICAgICAgIC8vIHRoZSB0cmFuc2l0aW9uIGFuZCBzZW5kIHRoZSAicm91dGVEaWRDaGFuZ2UiIGV2ZW50IGZvciBsYW5kaW5nIG9uCiAgICAgICAgICAgICAgLy8gdGhlIGVycm9yIHN1YnN0YXRlIGFuZCByZXR1cm4gdGhlIGVycm9yLgogICAgICAgICAgICAgIHRyYW5zaXRpb24ucm9sbGJhY2soKTsKICAgICAgICAgICAgICB0aGlzLnJvdXRlRGlkQ2hhbmdlKHRyYW5zaXRpb24pOwogICAgICAgICAgICAgIHJldHVybiBlcnJvci5lcnJvcjsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAvLyBJZiBpdCB3YXMgbm90IGhhbmRsZWQsIGFib3J0IHRoZSB0cmFuc2l0aW9uIGNvbXBsZXRlbHkgYW5kIHJldHVybgogICAgICAgICAgICAgIC8vIHRoZSBlcnJvci4KICAgICAgICAgICAgICB0cmFuc2l0aW9uLmFib3J0KCk7CiAgICAgICAgICAgICAgcmV0dXJuIGVycm9yLmVycm9yOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfTsKCiAgICAgICAgX3Byb3RvMi5fdHJpZ2dlcldpbGxDaGFuZ2VDb250ZXh0ID0gZnVuY3Rpb24gX3RyaWdnZXJXaWxsQ2hhbmdlQ29udGV4dCgpIHsKICAgICAgICAgIHJldHVybiByb3V0ZXI7CiAgICAgICAgfTsKCiAgICAgICAgX3Byb3RvMi5fdHJpZ2dlcldpbGxMZWF2ZSA9IGZ1bmN0aW9uIF90cmlnZ2VyV2lsbExlYXZlKCkgewogICAgICAgICAgcmV0dXJuIHJvdXRlcjsKICAgICAgICB9OwoKICAgICAgICBfcHJvdG8yLnJlcGxhY2VVUkwgPSBmdW5jdGlvbiByZXBsYWNlVVJMKHVybCkgewogICAgICAgICAgaWYgKGxvY2F0aW9uLnJlcGxhY2VVUkwpIHsKICAgICAgICAgICAgdmFyIGRvUmVwbGFjZVVSTCA9IGZ1bmN0aW9uIGRvUmVwbGFjZVVSTCgpIHsKICAgICAgICAgICAgICBsb2NhdGlvbi5yZXBsYWNlVVJMKHVybCk7CiAgICAgICAgICAgICAgKDAsIF9tZXRhbC5zZXQpKHJvdXRlciwgJ2N1cnJlbnRVUkwnLCB1cmwpOwogICAgICAgICAgICB9OwoKICAgICAgICAgICAgKDAsIF9ydW5sb29wLm9uY2UpKGRvUmVwbGFjZVVSTCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aGlzLnVwZGF0ZVVSTCh1cmwpOwogICAgICAgICAgfQogICAgICAgIH07CgogICAgICAgIHJldHVybiBQcml2YXRlUm91dGVyOwogICAgICB9KF9yb3V0ZXJfanMuZGVmYXVsdCk7CgogICAgICB2YXIgcm91dGVyTWljcm9saWIgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYiA9IG5ldyBQcml2YXRlUm91dGVyKCk7CiAgICAgIHZhciBkc2xDYWxsYmFja3MgPSB0aGlzLmNvbnN0cnVjdG9yLmRzbENhbGxiYWNrcyB8fCBbS107CgogICAgICB2YXIgZHNsID0gdGhpcy5fYnVpbGREU0woKTsKCiAgICAgIGRzbC5yb3V0ZSgnYXBwbGljYXRpb24nLCB7CiAgICAgICAgcGF0aDogJy8nLAogICAgICAgIHJlc2V0TmFtZXNwYWNlOiB0cnVlLAogICAgICAgIG92ZXJyaWRlTmFtZUFzc2VydGlvbjogdHJ1ZQogICAgICB9LCBmdW5jdGlvbiAoKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkc2xDYWxsYmFja3MubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGRzbENhbGxiYWNrc1tpXS5jYWxsKHRoaXMpOwogICAgICAgIH0KICAgICAgfSk7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgaWYgKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnbmFtZXNwYWNlLkxPR19UUkFOU0lUSU9OU19JTlRFUk5BTCcpKSB7CiAgICAgICAgICByb3V0ZXJNaWNyb2xpYi5sb2cgPSBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGUKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJvdXRlck1pY3JvbGliLm1hcChkc2wuZ2VuZXJhdGUoKSk7CiAgICB9OwoKICAgIF9wcm90by5fYnVpbGREU0wgPSBmdW5jdGlvbiBfYnVpbGREU0woKSB7CiAgICAgIHZhciBlbmFibGVMb2FkaW5nU3Vic3RhdGVzID0gdGhpcy5faGFzTW9kdWxlQmFzZWRSZXNvbHZlcigpOwoKICAgICAgdmFyIHJvdXRlciA9IHRoaXM7CiAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICB2YXIgb3B0aW9ucyA9IHsKICAgICAgICBlbmFibGVMb2FkaW5nU3Vic3RhdGVzOiBlbmFibGVMb2FkaW5nU3Vic3RhdGVzLAogICAgICAgIHJlc29sdmVSb3V0ZU1hcDogZnVuY3Rpb24gcmVzb2x2ZVJvdXRlTWFwKG5hbWUpIHsKICAgICAgICAgIHJldHVybiBvd25lci5mYWN0b3J5Rm9yKCJyb3V0ZS1tYXA6IiArIG5hbWUpOwogICAgICAgIH0sCiAgICAgICAgYWRkUm91dGVGb3JFbmdpbmU6IGZ1bmN0aW9uIGFkZFJvdXRlRm9yRW5naW5lKG5hbWUsIGVuZ2luZUluZm8pIHsKICAgICAgICAgIGlmICghcm91dGVyLl9lbmdpbmVJbmZvQnlSb3V0ZVtuYW1lXSkgewogICAgICAgICAgICByb3V0ZXIuX2VuZ2luZUluZm9CeVJvdXRlW25hbWVdID0gZW5naW5lSW5mbzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH07CiAgICAgIHJldHVybiBuZXcgX2RzbC5kZWZhdWx0KG51bGwsIG9wdGlvbnMpOwogICAgfQogICAgLyoKICAgICAgUmVzZXRzIGFsbCBwZW5kaW5nIHF1ZXJ5IHBhcmFtZXRlciBjaGFuZ2VzLgogICAgICBDYWxsZWQgYWZ0ZXIgdHJhbnNpdGlvbmluZyB0byBhIG5ldyByb3V0ZQogICAgICBiYXNlZCBvbiBxdWVyeSBwYXJhbWV0ZXIgY2hhbmdlcy4KICAgICovCiAgICA7CgogICAgX3Byb3RvLl9yZXNldFF1ZXVlZFF1ZXJ5UGFyYW1ldGVyQ2hhbmdlcyA9IGZ1bmN0aW9uIF9yZXNldFF1ZXVlZFF1ZXJ5UGFyYW1ldGVyQ2hhbmdlcygpIHsKICAgICAgdGhpcy5fcXVldWVkUVBDaGFuZ2VzID0ge307CiAgICB9OwoKICAgIF9wcm90by5faGFzTW9kdWxlQmFzZWRSZXNvbHZlciA9IGZ1bmN0aW9uIF9oYXNNb2R1bGVCYXNlZFJlc29sdmVyKCkgewogICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKTsKCiAgICAgIGlmICghb3duZXIpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIHZhciByZXNvbHZlciA9ICgwLCBfbWV0YWwuZ2V0KShvd25lciwgJ2FwcGxpY2F0aW9uLl9fcmVnaXN0cnlfXy5yZXNvbHZlci5tb2R1bGVCYXNlZFJlc29sdmVyJyk7CiAgICAgIHJldHVybiBCb29sZWFuKHJlc29sdmVyKTsKICAgIH0KICAgIC8qKgogICAgICBJbml0aWFsaXplcyB0aGUgY3VycmVudCByb3V0ZXIgaW5zdGFuY2UgYW5kIHNldHMgdXAgdGhlIGNoYW5nZSBoYW5kbGluZwogICAgICBldmVudCBsaXN0ZW5lcnMgdXNlZCBieSB0aGUgaW5zdGFuY2VzIGBsb2NhdGlvbmAgaW1wbGVtZW50YXRpb24uCiAgICAgICAgIEEgcHJvcGVydHkgbmFtZWQgYGluaXRpYWxVUkxgIHdpbGwgYmUgdXNlZCB0byBkZXRlcm1pbmUgdGhlIGluaXRpYWwgVVJMLgogICAgICBJZiBubyB2YWx1ZSBpcyBmb3VuZCBgL2Agd2lsbCBiZSB1c2VkLgogICAgICAgICBAbWV0aG9kIHN0YXJ0Um91dGluZwogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uc3RhcnRSb3V0aW5nID0gZnVuY3Rpb24gc3RhcnRSb3V0aW5nKCkgewogICAgICB2YXIgaW5pdGlhbFVSTCA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnaW5pdGlhbFVSTCcpOwoKICAgICAgaWYgKHRoaXMuc2V0dXBSb3V0ZXIoKSkgewogICAgICAgIGlmIChpbml0aWFsVVJMID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGluaXRpYWxVUkwgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2xvY2F0aW9uJykuZ2V0VVJMKCk7CiAgICAgICAgfQoKICAgICAgICB2YXIgaW5pdGlhbFRyYW5zaXRpb24gPSB0aGlzLmhhbmRsZVVSTChpbml0aWFsVVJMKTsKCiAgICAgICAgaWYgKGluaXRpYWxUcmFuc2l0aW9uICYmIGluaXRpYWxUcmFuc2l0aW9uLmVycm9yKSB7CiAgICAgICAgICB0aHJvdyBpbml0aWFsVHJhbnNpdGlvbi5lcnJvcjsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnNldHVwUm91dGVyID0gZnVuY3Rpb24gc2V0dXBSb3V0ZXIoKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgdGhpcy5fc2V0dXBMb2NhdGlvbigpOwoKICAgICAgdmFyIGxvY2F0aW9uID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdsb2NhdGlvbicpOyAvLyBBbGxvdyB0aGUgTG9jYXRpb24gY2xhc3MgdG8gY2FuY2VsIHRoZSByb3V0ZXIgc2V0dXAgd2hpbGUgaXQgcmVmcmVzaGVzCiAgICAgIC8vIHRoZSBwYWdlCgogICAgICBpZiAoKDAsIF9tZXRhbC5nZXQpKGxvY2F0aW9uLCAnY2FuY2VsUm91dGVyU2V0dXAnKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgdGhpcy5faW5pdFJvdXRlckpzKCk7CgogICAgICBsb2NhdGlvbi5vblVwZGF0ZVVSTChmdW5jdGlvbiAodXJsKSB7CiAgICAgICAgX3RoaXMyLmhhbmRsZVVSTCh1cmwpOwogICAgICB9KTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9OwoKICAgIF9wcm90by5fc2V0T3V0bGV0cyA9IGZ1bmN0aW9uIF9zZXRPdXRsZXRzKCkgewogICAgICAvLyBUaGlzIGlzIHRyaWdnZXJlZCBhc3luYyBkdXJpbmcgUm91dGUjd2lsbERlc3Ryb3kuCiAgICAgIC8vIElmIHRoZSByb3V0ZXIgaXMgYWxzbyBiZWluZyBkZXN0cm95ZWQgd2UgZG8gbm90IHdhbnQgdG8KICAgICAgLy8gdG8gY3JlYXRlIGFub3RoZXIgdGhpcy5fdG9wbGV2ZWxWaWV3IChhbmQgbGVhayB0aGUgcmVuZGVyZXIpCiAgICAgIGlmICh0aGlzLmlzRGVzdHJveWluZyB8fCB0aGlzLmlzRGVzdHJveWVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgcm91dGVJbmZvcyA9IHRoaXMuX3JvdXRlck1pY3JvbGliLmN1cnJlbnRSb3V0ZUluZm9zOwogICAgICB2YXIgcm91dGU7CiAgICAgIHZhciBkZWZhdWx0UGFyZW50U3RhdGU7CiAgICAgIHZhciBsaXZlUm91dGVzID0gbnVsbDsKCiAgICAgIGlmICghcm91dGVJbmZvcykgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3V0ZUluZm9zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgcm91dGUgPSByb3V0ZUluZm9zW2ldLnJvdXRlOwoKICAgICAgICB2YXIgY29ubmVjdGlvbnMgPSBfcm91dGUuUk9VVEVfQ09OTkVDVElPTlMuZ2V0KHJvdXRlKTsKCiAgICAgICAgdmFyIG93blN0YXRlID0gdm9pZCAwOwoKICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGNvbm5lY3Rpb25zLmxlbmd0aDsgaisrKSB7CiAgICAgICAgICB2YXIgYXBwZW5kZWQgPSBhcHBlbmRMaXZlUm91dGUobGl2ZVJvdXRlcywgZGVmYXVsdFBhcmVudFN0YXRlLCBjb25uZWN0aW9uc1tqXSk7CiAgICAgICAgICBsaXZlUm91dGVzID0gYXBwZW5kZWQubGl2ZVJvdXRlczsKCiAgICAgICAgICBpZiAoYXBwZW5kZWQub3duU3RhdGUucmVuZGVyLm5hbWUgPT09IHJvdXRlLnJvdXRlTmFtZSB8fCBhcHBlbmRlZC5vd25TdGF0ZS5yZW5kZXIub3V0bGV0ID09PSAnbWFpbicpIHsKICAgICAgICAgICAgb3duU3RhdGUgPSBhcHBlbmRlZC5vd25TdGF0ZTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmIChjb25uZWN0aW9ucy5sZW5ndGggPT09IDApIHsKICAgICAgICAgIG93blN0YXRlID0gcmVwcmVzZW50RW1wdHlSb3V0ZShsaXZlUm91dGVzLCBkZWZhdWx0UGFyZW50U3RhdGUsIHJvdXRlKTsKICAgICAgICB9CgogICAgICAgIGRlZmF1bHRQYXJlbnRTdGF0ZSA9IG93blN0YXRlOwogICAgICB9IC8vIHdoZW4gYSB0cmFuc2l0aW9uVG8gaGFwcGVucyBhZnRlciB0aGUgdmFsaWRhdGlvbiBwaGFzZQogICAgICAvLyBkdXJpbmcgdGhlIGluaXRpYWwgdHJhbnNpdGlvbiBfc2V0T3V0bGV0cyBpcyBjYWxsZWQKICAgICAgLy8gd2hlbiBubyByb3V0ZXMgYXJlIGFjdGl2ZS4gSG93ZXZlciwgaXQgd2lsbCBnZXQgY2FsbGVkCiAgICAgIC8vIGFnYWluIHdpdGggdGhlIGNvcnJlY3QgdmFsdWVzIGR1cmluZyB0aGUgbmV4dCB0dXJuIG9mCiAgICAgIC8vIHRoZSBydW5sb29wCgoKICAgICAgaWYgKCFsaXZlUm91dGVzKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAoIXRoaXMuX3RvcGxldmVsVmlldykgewogICAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICAgIHZhciBPdXRsZXRWaWV3ID0gb3duZXIuZmFjdG9yeUZvcigndmlldzotb3V0bGV0Jyk7CiAgICAgICAgdGhpcy5fdG9wbGV2ZWxWaWV3ID0gT3V0bGV0Vmlldy5jcmVhdGUoKTsKCiAgICAgICAgdGhpcy5fdG9wbGV2ZWxWaWV3LnNldE91dGxldFN0YXRlKGxpdmVSb3V0ZXMpOwoKICAgICAgICB2YXIgaW5zdGFuY2UgPSBvd25lci5sb29rdXAoJy1hcHBsaWNhdGlvbi1pbnN0YW5jZTptYWluJyk7CiAgICAgICAgaW5zdGFuY2UuZGlkQ3JlYXRlUm9vdFZpZXcodGhpcy5fdG9wbGV2ZWxWaWV3KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLl90b3BsZXZlbFZpZXcuc2V0T3V0bGV0U3RhdGUobGl2ZVJvdXRlcyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmhhbmRsZVVSTCA9IGZ1bmN0aW9uIGhhbmRsZVVSTCh1cmwpIHsKICAgICAgLy8gVW50aWwgd2UgaGF2ZSBhbiBlbWJlci1pZGlvbWF0aWMgd2F5IG9mIGFjY2Vzc2luZyAjaGFzaGVzLCB3ZSBuZWVkIHRvCiAgICAgIC8vIHJlbW92ZSBpdCBiZWNhdXNlIHJvdXRlci5qcyBkb2Vzbid0IGtub3cgaG93IHRvIGhhbmRsZSBpdC4KICAgICAgdmFyIF91cmwgPSB1cmwuc3BsaXQoLyMoLispPy8pWzBdOwogICAgICByZXR1cm4gdGhpcy5fZG9VUkxUcmFuc2l0aW9uKCdoYW5kbGVVUkwnLCBfdXJsKTsKICAgIH07CgogICAgX3Byb3RvLl9kb1VSTFRyYW5zaXRpb24gPSBmdW5jdGlvbiBfZG9VUkxUcmFuc2l0aW9uKHJvdXRlckpzTWV0aG9kLCB1cmwpIHsKICAgICAgdmFyIHRyYW5zaXRpb24gPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYltyb3V0ZXJKc01ldGhvZF0odXJsIHx8ICcvJyk7CgogICAgICBkaWRCZWdpblRyYW5zaXRpb24odHJhbnNpdGlvbiwgdGhpcyk7CiAgICAgIHJldHVybiB0cmFuc2l0aW9uOwogICAgfQogICAgLyoqCiAgICAgIFRyYW5zaXRpb24gdGhlIGFwcGxpY2F0aW9uIGludG8gYW5vdGhlciByb3V0ZS4gVGhlIHJvdXRlIG1heQogICAgICBiZSBlaXRoZXIgYSBzaW5nbGUgcm91dGUgb3Igcm91dGUgcGF0aDoKICAgICAgICAgU2VlIFt0cmFuc2l0aW9uVG9dKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvUm91dGUvbWV0aG9kcy90cmFuc2l0aW9uVG8/YW5jaG9yPXRyYW5zaXRpb25UbykgZm9yIG1vcmUgaW5mby4KICAgICAgICAgQG1ldGhvZCB0cmFuc2l0aW9uVG8KICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIHJvdXRlIG9yIGEgVVJMCiAgICAgIEBwYXJhbSB7Li4uT2JqZWN0fSBtb2RlbHMgdGhlIG1vZGVsKHMpIG9yIGlkZW50aWZpZXIocykgdG8gYmUgdXNlZCB3aGlsZQogICAgICAgIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIG9wdGlvbmFsIGhhc2ggd2l0aCBhIHF1ZXJ5UGFyYW1zIHByb3BlcnR5CiAgICAgICAgY29udGFpbmluZyBhIG1hcHBpbmcgb2YgcXVlcnkgcGFyYW1ldGVycwogICAgICBAcmV0dXJuIHtUcmFuc2l0aW9ufSB0aGUgdHJhbnNpdGlvbiBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoaXMKICAgICAgICBhdHRlbXB0ZWQgdHJhbnNpdGlvbgogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by50cmFuc2l0aW9uVG8gPSBmdW5jdGlvbiB0cmFuc2l0aW9uVG8oKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgIGlmICgoMCwgX3V0aWxzLnJlc2VtYmxlc1VSTCkoYXJnc1swXSkpIHsKICAgICAgICAoZmFsc2UgJiYgISghdGhpcy5pc0Rlc3Ryb3lpbmcgJiYgIXRoaXMuaXNEZXN0cm95ZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQSB0cmFuc2l0aW9uIHdhcyBhdHRlbXB0ZWQgZnJvbSAnIiArIHRoaXMuY3VycmVudFJvdXRlTmFtZSArICInIHRvICciICsgYXJnc1swXSArICInIGJ1dCB0aGUgYXBwbGljYXRpb24gaW5zdGFuY2UgaGFzIGFscmVhZHkgYmVlbiBkZXN0cm95ZWQuIiwgIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgICAgcmV0dXJuIHRoaXMuX2RvVVJMVHJhbnNpdGlvbigndHJhbnNpdGlvblRvJywgYXJnc1swXSk7CiAgICAgIH0KCiAgICAgIHZhciBfZXh0cmFjdFJvdXRlQXJncyA9ICgwLCBfdXRpbHMuZXh0cmFjdFJvdXRlQXJncykoYXJncyksCiAgICAgICAgICByb3V0ZU5hbWUgPSBfZXh0cmFjdFJvdXRlQXJncy5yb3V0ZU5hbWUsCiAgICAgICAgICBtb2RlbHMgPSBfZXh0cmFjdFJvdXRlQXJncy5tb2RlbHMsCiAgICAgICAgICBxdWVyeVBhcmFtcyA9IF9leHRyYWN0Um91dGVBcmdzLnF1ZXJ5UGFyYW1zOwoKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkEgdHJhbnNpdGlvbiB3YXMgYXR0ZW1wdGVkIGZyb20gJyIgKyB0aGlzLmN1cnJlbnRSb3V0ZU5hbWUgKyAiJyB0byAnIiArIHJvdXRlTmFtZSArICInIGJ1dCB0aGUgYXBwbGljYXRpb24gaW5zdGFuY2UgaGFzIGFscmVhZHkgYmVlbiBkZXN0cm95ZWQuIiwgIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgIHJldHVybiB0aGlzLl9kb1RyYW5zaXRpb24ocm91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zKTsKICAgIH07CgogICAgX3Byb3RvLmludGVybWVkaWF0ZVRyYW5zaXRpb25UbyA9IGZ1bmN0aW9uIGludGVybWVkaWF0ZVRyYW5zaXRpb25UbyhuYW1lKSB7CiAgICAgIHZhciBfdGhpcyRfcm91dGVyTWljcm9saWI7CgogICAgICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjIgPiAxID8gX2xlbjIgLSAxIDogMCksIF9rZXkyID0gMTsgX2tleTIgPCBfbGVuMjsgX2tleTIrKykgewogICAgICAgIGFyZ3NbX2tleTIgLSAxXSA9IGFyZ3VtZW50c1tfa2V5Ml07CiAgICAgIH0KCiAgICAgIChfdGhpcyRfcm91dGVyTWljcm9saWIgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYikuaW50ZXJtZWRpYXRlVHJhbnNpdGlvblRvLmFwcGx5KF90aGlzJF9yb3V0ZXJNaWNyb2xpYiwgW25hbWVdLmNvbmNhdChhcmdzKSk7CgogICAgICB1cGRhdGVQYXRocyh0aGlzKTsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICB2YXIgaW5mb3MgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYi5jdXJyZW50Um91dGVJbmZvczsKCiAgICAgICAgaWYgKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnbmFtZXNwYWNlJykuTE9HX1RSQU5TSVRJT05TKSB7CiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZQogICAgICAgICAgY29uc29sZS5sb2coIkludGVybWVkaWF0ZS10cmFuc2l0aW9uZWQgaW50byAnIiArIEVtYmVyUm91dGVyLl9yb3V0ZVBhdGgoaW5mb3MpICsgIiciKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnJlcGxhY2VXaXRoID0gZnVuY3Rpb24gcmVwbGFjZVdpdGgoKSB7CiAgICAgIHJldHVybiB0aGlzLnRyYW5zaXRpb25Uby5hcHBseSh0aGlzLCBhcmd1bWVudHMpLm1ldGhvZCgncmVwbGFjZScpOwogICAgfTsKCiAgICBfcHJvdG8uZ2VuZXJhdGUgPSBmdW5jdGlvbiBnZW5lcmF0ZShuYW1lKSB7CiAgICAgIHZhciBfdGhpcyRfcm91dGVyTWljcm9saWIyOwoKICAgICAgZm9yICh2YXIgX2xlbjMgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4zID4gMSA/IF9sZW4zIC0gMSA6IDApLCBfa2V5MyA9IDE7IF9rZXkzIDwgX2xlbjM7IF9rZXkzKyspIHsKICAgICAgICBhcmdzW19rZXkzIC0gMV0gPSBhcmd1bWVudHNbX2tleTNdOwogICAgICB9CgogICAgICB2YXIgdXJsID0gKF90aGlzJF9yb3V0ZXJNaWNyb2xpYjIgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYikuZ2VuZXJhdGUuYXBwbHkoX3RoaXMkX3JvdXRlck1pY3JvbGliMiwgW25hbWVdLmNvbmNhdChhcmdzKSk7CgogICAgICByZXR1cm4gdGhpcy5sb2NhdGlvbi5mb3JtYXRVUkwodXJsKTsKICAgIH0KICAgIC8qKgogICAgICBEZXRlcm1pbmVzIGlmIHRoZSBzdXBwbGllZCByb3V0ZSBpcyBjdXJyZW50bHkgYWN0aXZlLgogICAgICAgICBAbWV0aG9kIGlzQWN0aXZlCiAgICAgIEBwYXJhbSByb3V0ZU5hbWUKICAgICAgQHJldHVybiB7Qm9vbGVhbn0KICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmlzQWN0aXZlID0gZnVuY3Rpb24gaXNBY3RpdmUocm91dGVOYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLl9yb3V0ZXJNaWNyb2xpYi5pc0FjdGl2ZShyb3V0ZU5hbWUpOwogICAgfQogICAgLyoqCiAgICAgIEFuIGFsdGVybmF0aXZlIGZvcm0gb2YgYGlzQWN0aXZlYCB0aGF0IGRvZXNuJ3QgcmVxdWlyZQogICAgICBtYW51YWwgY29uY2F0ZW5hdGlvbiBvZiB0aGUgYXJndW1lbnRzIGludG8gYSBzaW5nbGUKICAgICAgYXJyYXkuCiAgICAgICAgIEBtZXRob2QgaXNBY3RpdmVJbnRlbnQKICAgICAgQHBhcmFtIHJvdXRlTmFtZQogICAgICBAcGFyYW0gbW9kZWxzCiAgICAgIEBwYXJhbSBxdWVyeVBhcmFtcwogICAgICBAcmV0dXJuIHtCb29sZWFufQogICAgICBAcHJpdmF0ZQogICAgICBAc2luY2UgMS43LjAKICAgICovCiAgICA7CgogICAgX3Byb3RvLmlzQWN0aXZlSW50ZW50ID0gZnVuY3Rpb24gaXNBY3RpdmVJbnRlbnQocm91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zKSB7CiAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5pc0FjdGl2ZUludGVudChyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMpOwogICAgfTsKCiAgICBfcHJvdG8uc2VuZCA9IGZ1bmN0aW9uIHNlbmQobmFtZSkgewogICAgICB2YXIgX3RoaXMkX3JvdXRlck1pY3JvbGliMzsKCiAgICAgIGZvciAodmFyIF9sZW40ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuNCA+IDEgPyBfbGVuNCAtIDEgOiAwKSwgX2tleTQgPSAxOyBfa2V5NCA8IF9sZW40OyBfa2V5NCsrKSB7CiAgICAgICAgYXJnc1tfa2V5NCAtIDFdID0gYXJndW1lbnRzW19rZXk0XTsKICAgICAgfQoKICAgICAgLypuYW1lLCBjb250ZXh0Ki8KICAgICAgKF90aGlzJF9yb3V0ZXJNaWNyb2xpYjMgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYikudHJpZ2dlci5hcHBseShfdGhpcyRfcm91dGVyTWljcm9saWIzLCBbbmFtZV0uY29uY2F0KGFyZ3MpKTsKICAgIH0KICAgIC8qKgogICAgICBEb2VzIHRoaXMgcm91dGVyIGluc3RhbmNlIGhhdmUgdGhlIGdpdmVuIHJvdXRlLgogICAgICAgICBAbWV0aG9kIGhhc1JvdXRlCiAgICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5oYXNSb3V0ZSA9IGZ1bmN0aW9uIGhhc1JvdXRlKHJvdXRlKSB7CiAgICAgIHJldHVybiB0aGlzLl9yb3V0ZXJNaWNyb2xpYi5oYXNSb3V0ZShyb3V0ZSk7CiAgICB9CiAgICAvKioKICAgICAgUmVzZXRzIHRoZSBzdGF0ZSBvZiB0aGUgcm91dGVyIGJ5IGNsZWFyaW5nIHRoZSBjdXJyZW50IHJvdXRlCiAgICAgIGhhbmRsZXJzIGFuZCBkZWFjdGl2YXRpbmcgdGhlbS4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCByZXNldAogICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoKSB7CiAgICAgIGlmICh0aGlzLl9yb3V0ZXJNaWNyb2xpYikgewogICAgICAgIHRoaXMuX3JvdXRlck1pY3JvbGliLnJlc2V0KCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLndpbGxEZXN0cm95ID0gZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIGlmICh0aGlzLl90b3BsZXZlbFZpZXcpIHsKICAgICAgICB0aGlzLl90b3BsZXZlbFZpZXcuZGVzdHJveSgpOwoKICAgICAgICB0aGlzLl90b3BsZXZlbFZpZXcgPSBudWxsOwogICAgICB9CgogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgdGhpcy5yZXNldCgpOwogICAgICB2YXIgaW5zdGFuY2VzID0gdGhpcy5fZW5naW5lSW5zdGFuY2VzOwoKICAgICAgZm9yICh2YXIgbmFtZSBpbiBpbnN0YW5jZXMpIHsKICAgICAgICBmb3IgKHZhciBpZCBpbiBpbnN0YW5jZXNbbmFtZV0pIHsKICAgICAgICAgICgwLCBfcnVubG9vcC5ydW4pKGluc3RhbmNlc1tuYW1lXVtpZF0sICdkZXN0cm95Jyk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKgogICAgICBDYWxsZWQgd2hlbiBhbiBhY3RpdmUgcm91dGUncyBxdWVyeSBwYXJhbWV0ZXIgaGFzIGNoYW5nZWQuCiAgICAgIFRoZXNlIGNoYW5nZXMgYXJlIGJhdGNoZWQgaW50byBhIHJ1bmxvb3AgcnVuIGFuZCB0cmlnZ2VyCiAgICAgIGEgc2luZ2xlIHRyYW5zaXRpb24uCiAgICAqLwogICAgOwoKICAgIF9wcm90by5fYWN0aXZlUVBDaGFuZ2VkID0gZnVuY3Rpb24gX2FjdGl2ZVFQQ2hhbmdlZChxdWVyeVBhcmFtZXRlck5hbWUsIG5ld1ZhbHVlKSB7CiAgICAgIHRoaXMuX3F1ZXVlZFFQQ2hhbmdlc1txdWVyeVBhcmFtZXRlck5hbWVdID0gbmV3VmFsdWU7CiAgICAgICgwLCBfcnVubG9vcC5vbmNlKSh0aGlzLCB0aGlzLl9maXJlUXVlcnlQYXJhbVRyYW5zaXRpb24pOwogICAgfTsKCiAgICBfcHJvdG8uX3VwZGF0aW5nUVBDaGFuZ2VkID0gZnVuY3Rpb24gX3VwZGF0aW5nUVBDaGFuZ2VkKHF1ZXJ5UGFyYW1ldGVyTmFtZSkgewogICAgICB0aGlzLl9xcFVwZGF0ZXMuYWRkKHF1ZXJ5UGFyYW1ldGVyTmFtZSk7CiAgICB9CiAgICAvKgogICAgICBUcmlnZ2VycyBhIHRyYW5zaXRpb24gdG8gYSByb3V0ZSBiYXNlZCBvbiBxdWVyeSBwYXJhbWV0ZXIgY2hhbmdlcy4KICAgICAgVGhpcyBpcyBjYWxsZWQgb25jZSBwZXIgcnVubG9vcCwgdG8gYmF0Y2ggY2hhbmdlcy4KICAgICAgICAgZS5nLgogICAgICAgICBpZiB0aGVzZSBtZXRob2RzIGFyZSBjYWxsZWQgaW4gc3VjY2Vzc2lvbjoKICAgICAgdGhpcy5fYWN0aXZlUVBDaGFuZ2VkKCdmb28nLCAnMTAnKTsKICAgICAgICAvLyByZXN1bHRzIGluIF9xdWV1ZWRRUENoYW5nZXMgPSB7IGZvbzogJzEwJyB9CiAgICAgIHRoaXMuX2FjdGl2ZVFQQ2hhbmdlZCgnYmFyJywgZmFsc2UpOwogICAgICAgIC8vIHJlc3VsdHMgaW4gX3F1ZXVlZFFQQ2hhbmdlcyA9IHsgZm9vOiAnMTAnLCBiYXI6IGZhbHNlIH0KICAgICAgICAgX3F1ZXVlZFFQQ2hhbmdlcyB3aWxsIHJlcHJlc2VudCBib3RoIG9mIHRoZXNlIGNoYW5nZXMKICAgICAgYW5kIHRoZSB0cmFuc2l0aW9uIHVzaW5nIGB0cmFuc2l0aW9uVG9gIHdpbGwgYmUgdHJpZ2dlcmVkCiAgICAgIG9uY2UuCiAgICAqLwogICAgOwoKICAgIF9wcm90by5fZmlyZVF1ZXJ5UGFyYW1UcmFuc2l0aW9uID0gZnVuY3Rpb24gX2ZpcmVRdWVyeVBhcmFtVHJhbnNpdGlvbigpIHsKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oewogICAgICAgIHF1ZXJ5UGFyYW1zOiB0aGlzLl9xdWV1ZWRRUENoYW5nZXMKICAgICAgfSk7CgogICAgICB0aGlzLl9yZXNldFF1ZXVlZFF1ZXJ5UGFyYW1ldGVyQ2hhbmdlcygpOwogICAgfTsKCiAgICBfcHJvdG8uX3NldHVwTG9jYXRpb24gPSBmdW5jdGlvbiBfc2V0dXBMb2NhdGlvbigpIHsKICAgICAgdmFyIGxvY2F0aW9uID0gdGhpcy5sb2NhdGlvbjsKICAgICAgdmFyIHJvb3RVUkwgPSB0aGlzLnJvb3RVUkw7CiAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwoKICAgICAgaWYgKCdzdHJpbmcnID09PSB0eXBlb2YgbG9jYXRpb24gJiYgb3duZXIpIHsKICAgICAgICB2YXIgcmVzb2x2ZWRMb2NhdGlvbiA9IG93bmVyLmxvb2t1cCgibG9jYXRpb246IiArIGxvY2F0aW9uKTsKCiAgICAgICAgaWYgKHJlc29sdmVkTG9jYXRpb24gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgbG9jYXRpb24gPSAoMCwgX21ldGFsLnNldCkodGhpcywgJ2xvY2F0aW9uJywgcmVzb2x2ZWRMb2NhdGlvbik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vIEFsbG93IGZvciBkZXByZWNhdGVkIHJlZ2lzdHJhdGlvbiBvZiBjdXN0b20gbG9jYXRpb24gQVBJJ3MKICAgICAgICAgIHZhciBvcHRpb25zID0gewogICAgICAgICAgICBpbXBsZW1lbnRhdGlvbjogbG9jYXRpb24KICAgICAgICAgIH07CiAgICAgICAgICBsb2NhdGlvbiA9ICgwLCBfbWV0YWwuc2V0KSh0aGlzLCAnbG9jYXRpb24nLCBfYXBpLmRlZmF1bHQuY3JlYXRlKG9wdGlvbnMpKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChsb2NhdGlvbiAhPT0gbnVsbCAmJiB0eXBlb2YgbG9jYXRpb24gPT09ICdvYmplY3QnKSB7CiAgICAgICAgaWYgKHJvb3RVUkwpIHsKICAgICAgICAgICgwLCBfbWV0YWwuc2V0KShsb2NhdGlvbiwgJ3Jvb3RVUkwnLCByb290VVJMKTsKICAgICAgICB9IC8vIEFsbG93IHRoZSBsb2NhdGlvbiB0byBkbyBhbnkgZmVhdHVyZSBkZXRlY3Rpb24sIHN1Y2ggYXMgQXV0b0xvY2F0aW9uCiAgICAgICAgLy8gZGV0ZWN0aW5nIGhpc3Rvcnkgc3VwcG9ydC4gVGhpcyBnaXZlcyBpdCBhIGNoYW5jZSB0byBzZXQgaXRzCiAgICAgICAgLy8gYGNhbmNlbFJvdXRlclNldHVwYCBwcm9wZXJ0eSB3aGljaCBhYm9ydHMgcm91dGluZy4KCgogICAgICAgIGlmICh0eXBlb2YgbG9jYXRpb24uZGV0ZWN0ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICBsb2NhdGlvbi5kZXRlY3QoKTsKICAgICAgICB9IC8vIGVuc3VyZSB0aGF0IGluaXRTdGF0ZSBpcyBjYWxsZWQgQUZURVIgdGhlIHJvb3RVUkwgaXMgc2V0IG9uCiAgICAgICAgLy8gdGhlIGxvY2F0aW9uIGluc3RhbmNlCgoKICAgICAgICBpZiAodHlwZW9mIGxvY2F0aW9uLmluaXRTdGF0ZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgICAgbG9jYXRpb24uaW5pdFN0YXRlKCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgU2VyaWFsaXplcyB0aGUgZ2l2ZW4gcXVlcnkgcGFyYW1zIGFjY29yZGluZyB0byB0aGVpciBRUCBtZXRhIGluZm9ybWF0aW9uLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9zZXJpYWxpemVRdWVyeVBhcmFtcwogICAgICBAcGFyYW0ge0FycnJheTxSb3V0ZUluZm8+fSByb3V0ZUluZm9zCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeVBhcmFtcwogICAgICBAcmV0dXJuIHtWb2lkfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3NlcmlhbGl6ZVF1ZXJ5UGFyYW1zID0gZnVuY3Rpb24gX3NlcmlhbGl6ZVF1ZXJ5UGFyYW1zKHJvdXRlSW5mb3MsIHF1ZXJ5UGFyYW1zKSB7CiAgICAgIHZhciBfdGhpczMgPSB0aGlzOwoKICAgICAgZm9yRWFjaFF1ZXJ5UGFyYW0odGhpcywgcm91dGVJbmZvcywgcXVlcnlQYXJhbXMsIGZ1bmN0aW9uIChrZXksIHZhbHVlLCBxcCkgewogICAgICAgIGlmIChxcCkgewogICAgICAgICAgZGVsZXRlIHF1ZXJ5UGFyYW1zW2tleV07CiAgICAgICAgICBxdWVyeVBhcmFtc1txcC51cmxLZXldID0gcXAucm91dGUuc2VyaWFsaXplUXVlcnlQYXJhbSh2YWx1ZSwgcXAudXJsS2V5LCBxcC50eXBlKTsKICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJldHVybjsgLy8gV2UgZG9uJ3Qgc2VyaWFsaXplIHVuZGVmaW5lZCB2YWx1ZXMKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcXVlcnlQYXJhbXNba2V5XSA9IF90aGlzMy5fc2VyaWFsaXplUXVlcnlQYXJhbSh2YWx1ZSwgKDAsIF9ydW50aW1lLnR5cGVPZikodmFsdWUpKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogICAgLyoqCiAgICAgIFNlcmlhbGl6ZXMgdGhlIHZhbHVlIG9mIGEgcXVlcnkgcGFyYW1ldGVyIGJhc2VkIG9uIGEgdHlwZQogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9zZXJpYWxpemVRdWVyeVBhcmFtCiAgICAgIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZQogICAgICBAcGFyYW0ge1N0cmluZ30gdHlwZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3NlcmlhbGl6ZVF1ZXJ5UGFyYW0gPSBmdW5jdGlvbiBfc2VyaWFsaXplUXVlcnlQYXJhbSh2YWx1ZSwgdHlwZSkgewogICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnYXJyYXknKSB7CiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlKTsKICAgICAgfQoKICAgICAgcmV0dXJuICIiICsgdmFsdWU7CiAgICB9CiAgICAvKioKICAgICAgRGVzZXJpYWxpemVzIHRoZSBnaXZlbiBxdWVyeSBwYXJhbXMgYWNjb3JkaW5nIHRvIHRoZWlyIFFQIG1ldGEgaW5mb3JtYXRpb24uCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX2Rlc2VyaWFsaXplUXVlcnlQYXJhbXMKICAgICAgQHBhcmFtIHtBcnJheTxSb3V0ZUluZm8+fSByb3V0ZUluZm9zCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeVBhcmFtcwogICAgICBAcmV0dXJuIHtWb2lkfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX2Rlc2VyaWFsaXplUXVlcnlQYXJhbXMgPSBmdW5jdGlvbiBfZGVzZXJpYWxpemVRdWVyeVBhcmFtcyhyb3V0ZUluZm9zLCBxdWVyeVBhcmFtcykgewogICAgICBmb3JFYWNoUXVlcnlQYXJhbSh0aGlzLCByb3V0ZUluZm9zLCBxdWVyeVBhcmFtcywgZnVuY3Rpb24gKGtleSwgdmFsdWUsIHFwKSB7CiAgICAgICAgLy8gSWYgd2UgZG9uJ3QgaGF2ZSBRUCBtZXRhIGluZm8gZm9yIGEgZ2l2ZW4ga2V5LCB0aGVuIHdlIGRvIG5vdGhpbmcKICAgICAgICAvLyBiZWNhdXNlIGFsbCB2YWx1ZXMgd2lsbCBiZSB0cmVhdGVkIGFzIHN0cmluZ3MKICAgICAgICBpZiAocXApIHsKICAgICAgICAgIGRlbGV0ZSBxdWVyeVBhcmFtc1trZXldOwogICAgICAgICAgcXVlcnlQYXJhbXNbcXAucHJvcF0gPSBxcC5yb3V0ZS5kZXNlcmlhbGl6ZVF1ZXJ5UGFyYW0odmFsdWUsIHFwLnVybEtleSwgcXAudHlwZSk7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICBEZXNlcmlhbGl6ZXMgdGhlIHZhbHVlIG9mIGEgcXVlcnkgcGFyYW1ldGVyIGJhc2VkIG9uIGEgZGVmYXVsdCB0eXBlCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX2Rlc2VyaWFsaXplUXVlcnlQYXJhbQogICAgICBAcGFyYW0ge09iamVjdH0gdmFsdWUKICAgICAgQHBhcmFtIHtTdHJpbmd9IGRlZmF1bHRUeXBlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5fZGVzZXJpYWxpemVRdWVyeVBhcmFtID0gZnVuY3Rpb24gX2Rlc2VyaWFsaXplUXVlcnlQYXJhbSh2YWx1ZSwgZGVmYXVsdFR5cGUpIHsKICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0gZWxzZSBpZiAoZGVmYXVsdFR5cGUgPT09ICdib29sZWFuJykgewogICAgICAgIHJldHVybiB2YWx1ZSA9PT0gJ3RydWUnOwogICAgICB9IGVsc2UgaWYgKGRlZmF1bHRUeXBlID09PSAnbnVtYmVyJykgewogICAgICAgIHJldHVybiBOdW1iZXIodmFsdWUpLnZhbHVlT2YoKTsKICAgICAgfSBlbHNlIGlmIChkZWZhdWx0VHlwZSA9PT0gJ2FycmF5JykgewogICAgICAgIHJldHVybiAoMCwgX3J1bnRpbWUuQSkoSlNPTi5wYXJzZSh2YWx1ZSkpOwogICAgICB9CgogICAgICByZXR1cm4gdmFsdWU7CiAgICB9CiAgICAvKioKICAgICAgUmVtb3ZlcyAocHJ1bmVzKSBhbnkgcXVlcnkgcGFyYW1zIHdpdGggZGVmYXVsdCB2YWx1ZXMgZnJvbSB0aGUgZ2l2ZW4gUVAKICAgICAgb2JqZWN0LiBEZWZhdWx0IHZhbHVlcyBhcmUgZGV0ZXJtaW5lZCBmcm9tIHRoZSBRUCBtZXRhIGluZm9ybWF0aW9uIHBlciBrZXkuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX3BydW5lRGVmYXVsdFF1ZXJ5UGFyYW1WYWx1ZXMKICAgICAgQHBhcmFtIHtBcnJheTxSb3V0ZUluZm8+fSByb3V0ZUluZm9zCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeVBhcmFtcwogICAgICBAcmV0dXJuIHtWb2lkfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3BydW5lRGVmYXVsdFF1ZXJ5UGFyYW1WYWx1ZXMgPSBmdW5jdGlvbiBfcHJ1bmVEZWZhdWx0UXVlcnlQYXJhbVZhbHVlcyhyb3V0ZUluZm9zLCBxdWVyeVBhcmFtcykgewogICAgICB2YXIgcXBzID0gdGhpcy5fcXVlcnlQYXJhbXNGb3Iocm91dGVJbmZvcyk7CgogICAgICBmb3IgKHZhciBrZXkgaW4gcXVlcnlQYXJhbXMpIHsKICAgICAgICB2YXIgcXAgPSBxcHMubWFwW2tleV07CgogICAgICAgIGlmIChxcCAmJiBxcC5zZXJpYWxpemVkRGVmYXVsdFZhbHVlID09PSBxdWVyeVBhcmFtc1trZXldKSB7CiAgICAgICAgICBkZWxldGUgcXVlcnlQYXJhbXNba2V5XTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9kb1RyYW5zaXRpb24gPSBmdW5jdGlvbiBfZG9UcmFuc2l0aW9uKF90YXJnZXRSb3V0ZU5hbWUsIG1vZGVscywgX3F1ZXJ5UGFyYW1zLCBfa2VlcERlZmF1bHRRdWVyeVBhcmFtVmFsdWVzKSB7CiAgICAgIHZhciBfdGhpcyRfcm91dGVyTWljcm9saWI0OwoKICAgICAgdmFyIHRhcmdldFJvdXRlTmFtZSA9IF90YXJnZXRSb3V0ZU5hbWUgfHwgKDAsIF91dGlscy5nZXRBY3RpdmVUYXJnZXROYW1lKSh0aGlzLl9yb3V0ZXJNaWNyb2xpYik7CgogICAgICAoZmFsc2UgJiYgIShCb29sZWFuKHRhcmdldFJvdXRlTmFtZSkgJiYgdGhpcy5fcm91dGVyTWljcm9saWIuaGFzUm91dGUodGFyZ2V0Um91dGVOYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgcm91dGUgIiArIHRhcmdldFJvdXRlTmFtZSArICIgd2FzIG5vdCBmb3VuZCIsIEJvb2xlYW4odGFyZ2V0Um91dGVOYW1lKSAmJiB0aGlzLl9yb3V0ZXJNaWNyb2xpYi5oYXNSb3V0ZSh0YXJnZXRSb3V0ZU5hbWUpKSk7CiAgICAgIHZhciBxdWVyeVBhcmFtcyA9IHt9OwoKICAgICAgdGhpcy5fcHJvY2Vzc0FjdGl2ZVRyYW5zaXRpb25RdWVyeVBhcmFtcyh0YXJnZXRSb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMsIF9xdWVyeVBhcmFtcyk7CgogICAgICAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHF1ZXJ5UGFyYW1zLCBfcXVlcnlQYXJhbXMpOwoKICAgICAgdGhpcy5fcHJlcGFyZVF1ZXJ5UGFyYW1zKHRhcmdldFJvdXRlTmFtZSwgbW9kZWxzLCBxdWVyeVBhcmFtcywgQm9vbGVhbihfa2VlcERlZmF1bHRRdWVyeVBhcmFtVmFsdWVzKSk7CgogICAgICB2YXIgdHJhbnNpdGlvbiA9IChfdGhpcyRfcm91dGVyTWljcm9saWI0ID0gdGhpcy5fcm91dGVyTWljcm9saWIpLnRyYW5zaXRpb25Uby5hcHBseShfdGhpcyRfcm91dGVyTWljcm9saWI0LCBbdGFyZ2V0Um91dGVOYW1lXS5jb25jYXQobW9kZWxzLCBbewogICAgICAgIHF1ZXJ5UGFyYW1zOiBxdWVyeVBhcmFtcwogICAgICB9XSkpOwoKICAgICAgZGlkQmVnaW5UcmFuc2l0aW9uKHRyYW5zaXRpb24sIHRoaXMpOwogICAgICByZXR1cm4gdHJhbnNpdGlvbjsKICAgIH07CgogICAgX3Byb3RvLl9wcm9jZXNzQWN0aXZlVHJhbnNpdGlvblF1ZXJ5UGFyYW1zID0gZnVuY3Rpb24gX3Byb2Nlc3NBY3RpdmVUcmFuc2l0aW9uUXVlcnlQYXJhbXModGFyZ2V0Um91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zLCBfcXVlcnlQYXJhbXMpIHsKICAgICAgLy8gbWVyZ2UgaW4gYW55IHF1ZXJ5UGFyYW1zIGZyb20gdGhlIGFjdGl2ZSB0cmFuc2l0aW9uIHdoaWNoIGNvdWxkIGluY2x1ZGUKICAgICAgLy8gcXVlcnlQYXJhbXMgZnJvbSB0aGUgdXJsIG9uIGluaXRpYWwgbG9hZC4KICAgICAgaWYgKCF0aGlzLl9yb3V0ZXJNaWNyb2xpYi5hY3RpdmVUcmFuc2l0aW9uKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgdW5jaGFuZ2VkUVBzID0ge307CiAgICAgIHZhciBxcFVwZGF0ZXMgPSB0aGlzLl9xcFVwZGF0ZXM7CiAgICAgIHZhciBwYXJhbXMgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYi5hY3RpdmVUcmFuc2l0aW9uW19yb3V0ZXJfanMuUVVFUllfUEFSQU1TX1NZTUJPTF07CgogICAgICBmb3IgKHZhciBrZXkgaW4gcGFyYW1zKSB7CiAgICAgICAgaWYgKCFxcFVwZGF0ZXMuaGFzKGtleSkpIHsKICAgICAgICAgIHVuY2hhbmdlZFFQc1trZXldID0gcGFyYW1zW2tleV07CiAgICAgICAgfQogICAgICB9IC8vIFdlIG5lZWQgdG8gZnVsbHkgc2NvcGUgcXVlcnlQYXJhbXMgc28gdGhhdCB3ZSBjYW4gY3JlYXRlIG9uZSBvYmplY3QKICAgICAgLy8gdGhhdCByZXByZXNlbnRzIGJvdGggcGFzc2VkLWluIHF1ZXJ5UGFyYW1zIGFuZCBvbmVzIHRoYXQgYXJlbid0IGNoYW5nZWQKICAgICAgLy8gZnJvbSB0aGUgYWN0aXZlIHRyYW5zaXRpb24uCgoKICAgICAgdGhpcy5fZnVsbHlTY29wZVF1ZXJ5UGFyYW1zKHRhcmdldFJvdXRlTmFtZSwgbW9kZWxzLCBfcXVlcnlQYXJhbXMpOwoKICAgICAgdGhpcy5fZnVsbHlTY29wZVF1ZXJ5UGFyYW1zKHRhcmdldFJvdXRlTmFtZSwgbW9kZWxzLCB1bmNoYW5nZWRRUHMpOwoKICAgICAgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKShxdWVyeVBhcmFtcywgdW5jaGFuZ2VkUVBzKTsKICAgIH0KICAgIC8qKgogICAgICBQcmVwYXJlcyB0aGUgcXVlcnkgcGFyYW1zIGZvciBhIFVSTCBvciBUcmFuc2l0aW9uLiBSZXN0b3JlcyBhbnkgdW5kZWZpbmVkIFFQCiAgICAgIGtleXMvdmFsdWVzLCBzZXJpYWxpemVzIGFsbCB2YWx1ZXMsIGFuZCB0aGVuIHBydW5lcyBhbnkgZGVmYXVsdCB2YWx1ZXMuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX3ByZXBhcmVRdWVyeVBhcmFtcwogICAgICBAcGFyYW0ge1N0cmluZ30gdGFyZ2V0Um91dGVOYW1lCiAgICAgIEBwYXJhbSB7QXJyYXk8T2JqZWN0Pn0gbW9kZWxzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeVBhcmFtcwogICAgICBAcGFyYW0ge2Jvb2xlYW59IGtlZXBEZWZhdWx0UXVlcnlQYXJhbVZhbHVlcwogICAgICBAcmV0dXJuIHtWb2lkfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3ByZXBhcmVRdWVyeVBhcmFtcyA9IGZ1bmN0aW9uIF9wcmVwYXJlUXVlcnlQYXJhbXModGFyZ2V0Um91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zLCBfZnJvbVJvdXRlclNlcnZpY2UpIHsKICAgICAgdmFyIHN0YXRlID0gY2FsY3VsYXRlUG9zdFRyYW5zaXRpb25TdGF0ZSh0aGlzLCB0YXJnZXRSb3V0ZU5hbWUsIG1vZGVscyk7CgogICAgICB0aGlzLl9oeWRyYXRlVW5zdXBwbGllZFF1ZXJ5UGFyYW1zKHN0YXRlLCBxdWVyeVBhcmFtcywgQm9vbGVhbihfZnJvbVJvdXRlclNlcnZpY2UpKTsKCiAgICAgIHRoaXMuX3NlcmlhbGl6ZVF1ZXJ5UGFyYW1zKHN0YXRlLnJvdXRlSW5mb3MsIHF1ZXJ5UGFyYW1zKTsKCiAgICAgIGlmICghX2Zyb21Sb3V0ZXJTZXJ2aWNlKSB7CiAgICAgICAgdGhpcy5fcHJ1bmVEZWZhdWx0UXVlcnlQYXJhbVZhbHVlcyhzdGF0ZS5yb3V0ZUluZm9zLCBxdWVyeVBhcmFtcyk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSBtZXRhIGluZm9ybWF0aW9uIGZvciB0aGUgcXVlcnkgcGFyYW1zIG9mIGEgZ2l2ZW4gcm91dGUuIFRoaXMKICAgICAgd2lsbCBiZSBvdmVycmlkZGVuIHRvIGFsbG93IHN1cHBvcnQgZm9yIGxhenkgcm91dGVzLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9nZXRRUE1ldGEKICAgICAgQHBhcmFtIHtSb3V0ZUluZm99IHJvdXRlSW5mbwogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5fZ2V0UVBNZXRhID0gZnVuY3Rpb24gX2dldFFQTWV0YShyb3V0ZUluZm8pIHsKICAgICAgdmFyIHJvdXRlID0gcm91dGVJbmZvLnJvdXRlOwogICAgICByZXR1cm4gcm91dGUgJiYgKDAsIF9tZXRhbC5nZXQpKHJvdXRlLCAnX3FwJyk7CiAgICB9CiAgICAvKioKICAgICAgUmV0dXJucyBhIG1lcmdlZCBxdWVyeSBwYXJhbXMgbWV0YSBvYmplY3QgZm9yIGEgZ2l2ZW4gc2V0IG9mIHJvdXRlSW5mb3MuCiAgICAgIFVzZWZ1bCBmb3Iga25vd2luZyB3aGF0IHF1ZXJ5IHBhcmFtcyBhcmUgYXZhaWxhYmxlIGZvciBhIGdpdmVuIHJvdXRlIGhpZXJhcmNoeS4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBfcXVlcnlQYXJhbXNGb3IKICAgICAgQHBhcmFtIHtBcnJheTxSb3V0ZUluZm8+fSByb3V0ZUluZm9zCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICAqLwogICAgOwoKICAgIF9wcm90by5fcXVlcnlQYXJhbXNGb3IgPSBmdW5jdGlvbiBfcXVlcnlQYXJhbXNGb3Iocm91dGVJbmZvcykgewogICAgICB2YXIgcm91dGVJbmZvTGVuZ3RoID0gcm91dGVJbmZvcy5sZW5ndGg7CiAgICAgIHZhciBsZWFmUm91dGVOYW1lID0gcm91dGVJbmZvc1tyb3V0ZUluZm9MZW5ndGggLSAxXS5uYW1lOwogICAgICB2YXIgY2FjaGVkID0gdGhpcy5fcXBDYWNoZVtsZWFmUm91dGVOYW1lXTsKCiAgICAgIGlmIChjYWNoZWQgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBjYWNoZWQ7CiAgICAgIH0KCiAgICAgIHZhciBzaG91bGRDYWNoZSA9IHRydWU7CiAgICAgIHZhciBtYXAgPSB7fTsKICAgICAgdmFyIHFwcyA9IFtdOwogICAgICB2YXIgcXBzQnlVcmxLZXkgPSBmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICA/IHt9IDogbnVsbDsKICAgICAgdmFyIHFwTWV0YTsKICAgICAgdmFyIHFwOwogICAgICB2YXIgdXJsS2V5OwogICAgICB2YXIgcXBPdGhlcjsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm91dGVJbmZvTGVuZ3RoOyArK2kpIHsKICAgICAgICBxcE1ldGEgPSB0aGlzLl9nZXRRUE1ldGEocm91dGVJbmZvc1tpXSk7CgogICAgICAgIGlmICghcXBNZXRhKSB7CiAgICAgICAgICBzaG91bGRDYWNoZSA9IGZhbHNlOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfSAvLyBMb29wIG92ZXIgZWFjaCBRUCB0byBtYWtlIHN1cmUgd2UgZG9uJ3QgaGF2ZSBhbnkgY29sbGlzaW9ucyBieSB1cmxLZXkKCgogICAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBxcE1ldGEucXBzLmxlbmd0aDsgX2krKykgewogICAgICAgICAgcXAgPSBxcE1ldGEucXBzW19pXTsKCiAgICAgICAgICBpZiAoZmFsc2UKICAgICAgICAgIC8qIERFQlVHICovCiAgICAgICAgICApIHsKICAgICAgICAgICAgdXJsS2V5ID0gcXAudXJsS2V5OwogICAgICAgICAgICBxcE90aGVyID0gcXBzQnlVcmxLZXlbdXJsS2V5XTsKCiAgICAgICAgICAgIGlmIChxcE90aGVyICYmIHFwT3RoZXIuY29udHJvbGxlck5hbWUgIT09IHFwLmNvbnRyb2xsZXJOYW1lKSB7CiAgICAgICAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91J3JlIG5vdCBhbGxvd2VkIHRvIGhhdmUgbW9yZSB0aGFuIG9uZSBjb250cm9sbGVyIHByb3BlcnR5IG1hcCB0byB0aGUgc2FtZSBxdWVyeSBwYXJhbSBrZXksIGJ1dCBib3RoIGAiICsgcXBPdGhlci5zY29wZWRQcm9wZXJ0eU5hbWUgKyAiYCBhbmQgYCIgKyBxcC5zY29wZWRQcm9wZXJ0eU5hbWUgKyAiYCBtYXAgdG8gYCIgKyB1cmxLZXkgKyAiYC4gWW91IGNhbiBmaXggdGhpcyBieSBtYXBwaW5nIG9uZSBvZiB0aGUgY29udHJvbGxlciBwcm9wZXJ0aWVzIHRvIGEgZGlmZmVyZW50IHF1ZXJ5IHBhcmFtIGtleSB2aWEgdGhlIGBhc2AgY29uZmlnIG9wdGlvbiwgZS5nLiBgIiArIHFwT3RoZXIucHJvcCArICI6IHsgYXM6ICdvdGhlci0iICsgcXBPdGhlci5wcm9wICsgIicgfWAiLCBmYWxzZSkpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBxcHNCeVVybEtleVt1cmxLZXldID0gcXA7CiAgICAgICAgICB9CgogICAgICAgICAgcXBzLnB1c2gocXApOwogICAgICAgIH0KCiAgICAgICAgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKShtYXAsIHFwTWV0YS5tYXApOwogICAgICB9CgogICAgICB2YXIgZmluYWxRUE1ldGEgPSB7CiAgICAgICAgcXBzOiBxcHMsCiAgICAgICAgbWFwOiBtYXAKICAgICAgfTsKCiAgICAgIGlmIChzaG91bGRDYWNoZSkgewogICAgICAgIHRoaXMuX3FwQ2FjaGVbbGVhZlJvdXRlTmFtZV0gPSBmaW5hbFFQTWV0YTsKICAgICAgfQoKICAgICAgcmV0dXJuIGZpbmFsUVBNZXRhOwogICAgfQogICAgLyoqCiAgICAgIE1hcHMgYWxsIHF1ZXJ5IHBhcmFtIGtleXMgdG8gdGhlaXIgZnVsbHkgc2NvcGVkIHByb3BlcnR5IG5hbWUgb2YgdGhlIGZvcm0KICAgICAgYGNvbnRyb2xsZXJOYW1lOnByb3BOYW1lYC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBfZnVsbHlTY29wZVF1ZXJ5UGFyYW1zCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBsZWFmUm91dGVOYW1lCiAgICAgIEBwYXJhbSB7QXJyYXk8T2JqZWN0Pn0gY29udGV4dHMKICAgICAgQHBhcmFtIHtPYmplY3R9IHF1ZXJ5UGFyYW1zCiAgICAgIEByZXR1cm4ge1ZvaWR9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5fZnVsbHlTY29wZVF1ZXJ5UGFyYW1zID0gZnVuY3Rpb24gX2Z1bGx5U2NvcGVRdWVyeVBhcmFtcyhsZWFmUm91dGVOYW1lLCBjb250ZXh0cywgcXVlcnlQYXJhbXMpIHsKICAgICAgdmFyIHN0YXRlID0gY2FsY3VsYXRlUG9zdFRyYW5zaXRpb25TdGF0ZSh0aGlzLCBsZWFmUm91dGVOYW1lLCBjb250ZXh0cyk7CiAgICAgIHZhciByb3V0ZUluZm9zID0gc3RhdGUucm91dGVJbmZvczsKICAgICAgdmFyIHFwTWV0YTsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSByb3V0ZUluZm9zLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgICAgcXBNZXRhID0gdGhpcy5fZ2V0UVBNZXRhKHJvdXRlSW5mb3NbaV0pOwoKICAgICAgICBpZiAoIXFwTWV0YSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICB2YXIgcXAgPSB2b2lkIDA7CiAgICAgICAgdmFyIHByZXNlbnRQcm9wID0gdm9pZCAwOwoKICAgICAgICBmb3IgKHZhciBqID0gMCwgcXBMZW4gPSBxcE1ldGEucXBzLmxlbmd0aDsgaiA8IHFwTGVuOyArK2opIHsKICAgICAgICAgIHFwID0gcXBNZXRhLnFwc1tqXTsKICAgICAgICAgIHByZXNlbnRQcm9wID0gcXAucHJvcCBpbiBxdWVyeVBhcmFtcyAmJiBxcC5wcm9wIHx8IHFwLnNjb3BlZFByb3BlcnR5TmFtZSBpbiBxdWVyeVBhcmFtcyAmJiBxcC5zY29wZWRQcm9wZXJ0eU5hbWUgfHwgcXAudXJsS2V5IGluIHF1ZXJ5UGFyYW1zICYmIHFwLnVybEtleTsKCiAgICAgICAgICBpZiAocHJlc2VudFByb3ApIHsKICAgICAgICAgICAgaWYgKHByZXNlbnRQcm9wICE9PSBxcC5zY29wZWRQcm9wZXJ0eU5hbWUpIHsKICAgICAgICAgICAgICBxdWVyeVBhcmFtc1txcC5zY29wZWRQcm9wZXJ0eU5hbWVdID0gcXVlcnlQYXJhbXNbcHJlc2VudFByb3BdOwogICAgICAgICAgICAgIGRlbGV0ZSBxdWVyeVBhcmFtc1twcmVzZW50UHJvcF07CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBIeWRyYXRlcyAoYWRkcy9yZXN0b3JlcykgYW55IHF1ZXJ5IHBhcmFtcyB0aGF0IGhhdmUgcHJlLWV4aXN0aW5nIHZhbHVlcyBpbnRvCiAgICAgIHRoZSBnaXZlbiBxdWVyeVBhcmFtcyBoYXNoLiBUaGlzIGlzIHdoYXQgYWxsb3dzIHF1ZXJ5IHBhcmFtcyB0byBiZSAic3RpY2t5IgogICAgICBhbmQgcmVzdG9yZSB0aGVpciBsYXN0IGtub3duIHZhbHVlcyBmb3IgdGhlaXIgc2NvcGUuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX2h5ZHJhdGVVbnN1cHBsaWVkUXVlcnlQYXJhbXMKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9uU3RhdGV9IHN0YXRlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeVBhcmFtcwogICAgICBAcmV0dXJuIHtWb2lkfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX2h5ZHJhdGVVbnN1cHBsaWVkUXVlcnlQYXJhbXMgPSBmdW5jdGlvbiBfaHlkcmF0ZVVuc3VwcGxpZWRRdWVyeVBhcmFtcyhzdGF0ZSwgcXVlcnlQYXJhbXMsIF9mcm9tUm91dGVyU2VydmljZSkgewogICAgICB2YXIgcm91dGVJbmZvcyA9IHN0YXRlLnJvdXRlSW5mb3M7CiAgICAgIHZhciBhcHBDYWNoZSA9IHRoaXMuX2J1Y2tldENhY2hlOwogICAgICB2YXIgcXBNZXRhOwogICAgICB2YXIgcXA7CiAgICAgIHZhciBwcmVzZW50UHJvcDsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm91dGVJbmZvcy5sZW5ndGg7ICsraSkgewogICAgICAgIHFwTWV0YSA9IHRoaXMuX2dldFFQTWV0YShyb3V0ZUluZm9zW2ldKTsKCiAgICAgICAgaWYgKCFxcE1ldGEpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KCiAgICAgICAgZm9yICh2YXIgaiA9IDAsIHFwTGVuID0gcXBNZXRhLnFwcy5sZW5ndGg7IGogPCBxcExlbjsgKytqKSB7CiAgICAgICAgICBxcCA9IHFwTWV0YS5xcHNbal07CiAgICAgICAgICBwcmVzZW50UHJvcCA9IHFwLnByb3AgaW4gcXVlcnlQYXJhbXMgJiYgcXAucHJvcCB8fCBxcC5zY29wZWRQcm9wZXJ0eU5hbWUgaW4gcXVlcnlQYXJhbXMgJiYgcXAuc2NvcGVkUHJvcGVydHlOYW1lIHx8IHFwLnVybEtleSBpbiBxdWVyeVBhcmFtcyAmJiBxcC51cmxLZXk7CiAgICAgICAgICAoZmFsc2UgJiYgIShmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIGlmIChxcC51cmxLZXkgPT09IHByZXNlbnRQcm9wKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChfZnJvbVJvdXRlclNlcnZpY2UgJiYgcHJlc2VudFByb3AgIT09IGZhbHNlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgIH0oKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgcGFzc2VkIHRoZSBgIiArIHByZXNlbnRQcm9wICsgImAgcXVlcnkgcGFyYW1ldGVyIGR1cmluZyBhIHRyYW5zaXRpb24gaW50byAiICsgcXAucm91dGUucm91dGVOYW1lICsgIiwgcGxlYXNlIHVwZGF0ZSB0byAiICsgcXAudXJsS2V5LCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIGlmIChxcC51cmxLZXkgPT09IHByZXNlbnRQcm9wKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChfZnJvbVJvdXRlclNlcnZpY2UgJiYgcHJlc2VudFByb3AgIT09IGZhbHNlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgIH0oKSkpOwoKICAgICAgICAgIGlmIChwcmVzZW50UHJvcCkgewogICAgICAgICAgICBpZiAocHJlc2VudFByb3AgIT09IHFwLnNjb3BlZFByb3BlcnR5TmFtZSkgewogICAgICAgICAgICAgIHF1ZXJ5UGFyYW1zW3FwLnNjb3BlZFByb3BlcnR5TmFtZV0gPSBxdWVyeVBhcmFtc1twcmVzZW50UHJvcF07CiAgICAgICAgICAgICAgZGVsZXRlIHF1ZXJ5UGFyYW1zW3ByZXNlbnRQcm9wXTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdmFyIGNhY2hlS2V5ID0gKDAsIF91dGlscy5jYWxjdWxhdGVDYWNoZUtleSkocXAucm91dGUuZnVsbFJvdXRlTmFtZSwgcXAucGFydHMsIHN0YXRlLnBhcmFtcyk7CiAgICAgICAgICAgIHF1ZXJ5UGFyYW1zW3FwLnNjb3BlZFByb3BlcnR5TmFtZV0gPSBhcHBDYWNoZS5sb29rdXAoY2FjaGVLZXksIHFwLnByb3AsIHFwLmRlZmF1bHRWYWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fc2NoZWR1bGVMb2FkaW5nRXZlbnQgPSBmdW5jdGlvbiBfc2NoZWR1bGVMb2FkaW5nRXZlbnQodHJhbnNpdGlvbiwgb3JpZ2luUm91dGUpIHsKICAgICAgdGhpcy5fY2FuY2VsU2xvd1RyYW5zaXRpb25UaW1lcigpOwoKICAgICAgdGhpcy5fc2xvd1RyYW5zaXRpb25UaW1lciA9ICgwLCBfcnVubG9vcC5zY2hlZHVsZU9uY2UpKCdyb3V0ZXJUcmFuc2l0aW9ucycsIHRoaXMsICdfaGFuZGxlU2xvd1RyYW5zaXRpb24nLCB0cmFuc2l0aW9uLCBvcmlnaW5Sb3V0ZSk7CiAgICB9OwoKICAgIF9wcm90by5faGFuZGxlU2xvd1RyYW5zaXRpb24gPSBmdW5jdGlvbiBfaGFuZGxlU2xvd1RyYW5zaXRpb24odHJhbnNpdGlvbiwgb3JpZ2luUm91dGUpIHsKICAgICAgaWYgKCF0aGlzLl9yb3V0ZXJNaWNyb2xpYi5hY3RpdmVUcmFuc2l0aW9uKSB7CiAgICAgICAgLy8gRG9uJ3QgZmlyZSBhbiBldmVudCBpZiB3ZSd2ZSBzaW5jZSBtb3ZlZCBvbiBmcm9tCiAgICAgICAgLy8gdGhlIHRyYW5zaXRpb24gdGhhdCBwdXQgdXMgaW4gYSBsb2FkaW5nIHN0YXRlLgogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIHRhcmdldFN0YXRlID0gbmV3IF9yb3V0ZXJfc3RhdGUuZGVmYXVsdCh0aGlzLCB0aGlzLl9yb3V0ZXJNaWNyb2xpYiwgdGhpcy5fcm91dGVyTWljcm9saWIuYWN0aXZlVHJhbnNpdGlvbltfcm91dGVyX2pzLlNUQVRFX1NZTUJPTF0pOwogICAgICB0aGlzLnNldCgndGFyZ2V0U3RhdGUnLCB0YXJnZXRTdGF0ZSk7CiAgICAgIHRyYW5zaXRpb24udHJpZ2dlcih0cnVlLCAnbG9hZGluZycsIHRyYW5zaXRpb24sIG9yaWdpblJvdXRlKTsKICAgIH07CgogICAgX3Byb3RvLl9jYW5jZWxTbG93VHJhbnNpdGlvblRpbWVyID0gZnVuY3Rpb24gX2NhbmNlbFNsb3dUcmFuc2l0aW9uVGltZXIoKSB7CiAgICAgIGlmICh0aGlzLl9zbG93VHJhbnNpdGlvblRpbWVyKSB7CiAgICAgICAgKDAsIF9ydW5sb29wLmNhbmNlbCkodGhpcy5fc2xvd1RyYW5zaXRpb25UaW1lcik7CiAgICAgIH0KCiAgICAgIHRoaXMuX3Nsb3dUcmFuc2l0aW9uVGltZXIgPSBudWxsOwogICAgfSAvLyBUaGVzZSB0aHJlZSBoZWxwZXIgZnVuY3Rpb25zIGFyZSB1c2VkIHRvIGVuc3VyZSBlcnJvcnMgYXJlbid0CiAgICAvLyByZS1yYWlzZWQgaWYgdGhleSdyZSBoYW5kbGVkIGluIGEgcm91dGUncyBlcnJvciBhY3Rpb24uCiAgICA7CgogICAgX3Byb3RvLl9tYXJrRXJyb3JBc0hhbmRsZWQgPSBmdW5jdGlvbiBfbWFya0Vycm9yQXNIYW5kbGVkKGVycm9yKSB7CiAgICAgIHRoaXMuX2hhbmRsZWRFcnJvcnMuYWRkKGVycm9yKTsKICAgIH07CgogICAgX3Byb3RvLl9pc0Vycm9ySGFuZGxlZCA9IGZ1bmN0aW9uIF9pc0Vycm9ySGFuZGxlZChlcnJvcikgewogICAgICByZXR1cm4gdGhpcy5faGFuZGxlZEVycm9ycy5oYXMoZXJyb3IpOwogICAgfTsKCiAgICBfcHJvdG8uX2NsZWFySGFuZGxlZEVycm9yID0gZnVuY3Rpb24gX2NsZWFySGFuZGxlZEVycm9yKGVycm9yKSB7CiAgICAgIHRoaXMuX2hhbmRsZWRFcnJvcnMuZGVsZXRlKGVycm9yKTsKICAgIH07CgogICAgX3Byb3RvLl9nZXRFbmdpbmVJbnN0YW5jZSA9IGZ1bmN0aW9uIF9nZXRFbmdpbmVJbnN0YW5jZShfcmVmKSB7CiAgICAgIHZhciBuYW1lID0gX3JlZi5uYW1lLAogICAgICAgICAgaW5zdGFuY2VJZCA9IF9yZWYuaW5zdGFuY2VJZCwKICAgICAgICAgIG1vdW50UG9pbnQgPSBfcmVmLm1vdW50UG9pbnQ7CiAgICAgIHZhciBlbmdpbmVJbnN0YW5jZXMgPSB0aGlzLl9lbmdpbmVJbnN0YW5jZXM7CgogICAgICBpZiAoIWVuZ2luZUluc3RhbmNlc1tuYW1lXSkgewogICAgICAgIGVuZ2luZUluc3RhbmNlc1tuYW1lXSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIH0KCiAgICAgIHZhciBlbmdpbmVJbnN0YW5jZSA9IGVuZ2luZUluc3RhbmNlc1tuYW1lXVtpbnN0YW5jZUlkXTsKCiAgICAgIGlmICghZW5naW5lSW5zdGFuY2UpIHsKICAgICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKTsKICAgICAgICAoZmFsc2UgJiYgIShvd25lci5oYXNSZWdpc3RyYXRpb24oImVuZ2luZToiICsgbmFtZSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byBtb3VudCB0aGUgZW5naW5lICciICsgbmFtZSArICInIGluIHlvdXIgcm91dGVyIG1hcCwgYnV0IHRoZSBlbmdpbmUgY2FuIG5vdCBiZSBmb3VuZC4iLCBvd25lci5oYXNSZWdpc3RyYXRpb24oImVuZ2luZToiICsgbmFtZSkpKTsKICAgICAgICBlbmdpbmVJbnN0YW5jZSA9IG93bmVyLmJ1aWxkQ2hpbGRFbmdpbmVJbnN0YW5jZShuYW1lLCB7CiAgICAgICAgICByb3V0YWJsZTogdHJ1ZSwKICAgICAgICAgIG1vdW50UG9pbnQ6IG1vdW50UG9pbnQKICAgICAgICB9KTsKICAgICAgICBlbmdpbmVJbnN0YW5jZS5ib290KCk7CiAgICAgICAgZW5naW5lSW5zdGFuY2VzW25hbWVdW2luc3RhbmNlSWRdID0gZW5naW5lSW5zdGFuY2U7CiAgICAgIH0KCiAgICAgIHJldHVybiBlbmdpbmVJbnN0YW5jZTsKICAgIH07CgogICAgcmV0dXJuIEVtYmVyUm91dGVyOwogIH0oX3J1bnRpbWUuT2JqZWN0KTsKICAvKgogICAgSGVscGVyIGZ1bmN0aW9uIGZvciBpdGVyYXRpbmcgb3ZlciByb3V0ZXMgaW4gYSBzZXQgb2Ygcm91dGVJbmZvcyB0aGF0IGFyZQogICAgYXQgb3IgYWJvdmUgdGhlIGdpdmVuIG9yaWdpbiByb3V0ZS4gRXhhbXBsZTogaWYgYG9yaWdpblJvdXRlYCA9PT0gJ2Zvby5iYXInCiAgICBhbmQgdGhlIHJvdXRlSW5mb3MgZ2l2ZW4gd2VyZSBmb3IgJ2Zvby5iYXIuYmF6JywgdGhlbiB0aGUgZ2l2ZW4gY2FsbGJhY2sKICAgIHdpbGwgYmUgaW52b2tlZCB3aXRoIHRoZSByb3V0ZXMgZm9yICdmb28uYmFyJywgJ2ZvbycsIGFuZCAnYXBwbGljYXRpb24nCiAgICBpbmRpdmlkdWFsbHkuCiAgCiAgICBJZiB0aGUgY2FsbGJhY2sgcmV0dXJucyBhbnl0aGluZyBvdGhlciB0aGFuIGB0cnVlYCwgdGhlbiBpdGVyYXRpb24gd2lsbCBzdG9wLgogIAogICAgQHByaXZhdGUKICAgIEBwYXJhbSB7Um91dGV9IG9yaWdpblJvdXRlCiAgICBAcGFyYW0ge0FycmF5PFJvdXRlSW5mbz59IHJvdXRlSW5mb3MKICAgIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrCiAgICBAcmV0dXJuIHtWb2lkfQogICAqLwoKCiAgZnVuY3Rpb24gZm9yRWFjaFJvdXRlQWJvdmUocm91dGVJbmZvcywgY2FsbGJhY2spIHsKICAgIGZvciAodmFyIGkgPSByb3V0ZUluZm9zLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgIHZhciByb3V0ZUluZm8gPSByb3V0ZUluZm9zW2ldOwogICAgICB2YXIgcm91dGUgPSByb3V0ZUluZm8ucm91dGU7IC8vIHJvdXRlSW5mby5oYW5kbGVyIGJlaW5nIGB1bmRlZmluZWRgIGdlbmVyYWxseSBtZWFucyBlaXRoZXI6CiAgICAgIC8vCiAgICAgIC8vIDEuIGFuIGVycm9yIG9jY3VycmVkIGR1cmluZyBjcmVhdGlvbiBvZiB0aGUgcm91dGUgaW4gcXVlc3Rpb24KICAgICAgLy8gMi4gdGhlIHJvdXRlIGlzIGFjcm9zcyBhbiBhc3luYyBib3VuZGFyeSAoZS5nLiB3aXRoaW4gYW4gZW5naW5lKQogICAgICAvLwogICAgICAvLyBJbiBib3RoIG9mIHRoZXNlIGNhc2VzLCB3ZSBjYW5ub3QgaW52b2tlIHRoZSBjYWxsYmFjayBvbiB0aGF0IHNwZWNpZmljCiAgICAgIC8vIHJvdXRlLCBiZWNhdXNlIGl0IGp1c3QgZG9lc24ndCBleGlzdC4uLgoKICAgICAgaWYgKHJvdXRlID09PSB1bmRlZmluZWQpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQoKICAgICAgaWYgKGNhbGxiYWNrKHJvdXRlLCByb3V0ZUluZm8pICE9PSB0cnVlKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICB9CiAgfSAvLyBUaGVzZSBnZXQgaW52b2tlZCB3aGVuIGFuIGFjdGlvbiBidWJibGVzIGFib3ZlIEFwcGxpY2F0aW9uUm91dGUKICAvLyBhbmQgYXJlIG5vdCBtZWFudCB0byBiZSBvdmVycmlkYWJsZS4KCgogIHZhciBkZWZhdWx0QWN0aW9uSGFuZGxlcnMgPSB7CiAgICB3aWxsUmVzb2x2ZU1vZGVsOiBmdW5jdGlvbiB3aWxsUmVzb2x2ZU1vZGVsKF9yb3V0ZUluZm9zLCB0cmFuc2l0aW9uLCBvcmlnaW5Sb3V0ZSkgewogICAgICB0aGlzLl9zY2hlZHVsZUxvYWRpbmdFdmVudCh0cmFuc2l0aW9uLCBvcmlnaW5Sb3V0ZSk7CiAgICB9LAogICAgLy8gQXR0ZW1wdCB0byBmaW5kIGFuIGFwcHJvcHJpYXRlIGVycm9yIHJvdXRlIG9yIHN1YnN0YXRlIHRvIGVudGVyLgogICAgZXJyb3I6IGZ1bmN0aW9uIGVycm9yKHJvdXRlSW5mb3MsIF9lcnJvcjIsIHRyYW5zaXRpb24pIHsKICAgICAgdmFyIHJvdXRlciA9IHRoaXM7CiAgICAgIHZhciByb3V0ZUluZm9XaXRoRXJyb3IgPSByb3V0ZUluZm9zW3JvdXRlSW5mb3MubGVuZ3RoIC0gMV07CiAgICAgIGZvckVhY2hSb3V0ZUFib3ZlKHJvdXRlSW5mb3MsIGZ1bmN0aW9uIChyb3V0ZSwgcm91dGVJbmZvKSB7CiAgICAgICAgLy8gV2UgZG9uJ3QgY2hlY2sgdGhlIGxlYWYgbW9zdCByb3V0ZUluZm8gc2luY2UgdGhhdCB3b3VsZAogICAgICAgIC8vIHRlY2huaWNhbGx5IGJlIGJlbG93IHdoZXJlIHdlJ3JlIGF0IGluIHRoZSByb3V0ZSBoaWVyYXJjaHkuCiAgICAgICAgaWYgKHJvdXRlSW5mbyAhPT0gcm91dGVJbmZvV2l0aEVycm9yKSB7CiAgICAgICAgICAvLyBDaGVjayBmb3IgdGhlIGV4aXN0ZW5jZSBvZiBhbiAnZXJyb3InIHJvdXRlLgogICAgICAgICAgdmFyIGVycm9yUm91dGVOYW1lID0gZmluZFJvdXRlU3RhdGVOYW1lKHJvdXRlLCAnZXJyb3InKTsKCiAgICAgICAgICBpZiAoZXJyb3JSb3V0ZU5hbWUpIHsKICAgICAgICAgICAgcm91dGVyLl9tYXJrRXJyb3JBc0hhbmRsZWQoX2Vycm9yMik7CgogICAgICAgICAgICByb3V0ZXIuaW50ZXJtZWRpYXRlVHJhbnNpdGlvblRvKGVycm9yUm91dGVOYW1lLCBfZXJyb3IyKTsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgIH0gLy8gQ2hlY2sgZm9yIGFuICdlcnJvcicgc3Vic3RhdGUgcm91dGUKCgogICAgICAgIHZhciBlcnJvclN1YnN0YXRlTmFtZSA9IGZpbmRSb3V0ZVN1YnN0YXRlTmFtZShyb3V0ZSwgJ2Vycm9yJyk7CgogICAgICAgIGlmIChlcnJvclN1YnN0YXRlTmFtZSkgewogICAgICAgICAgcm91dGVyLl9tYXJrRXJyb3JBc0hhbmRsZWQoX2Vycm9yMik7CgogICAgICAgICAgcm91dGVyLmludGVybWVkaWF0ZVRyYW5zaXRpb25UbyhlcnJvclN1YnN0YXRlTmFtZSwgX2Vycm9yMik7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfSk7CiAgICAgIGxvZ0Vycm9yKF9lcnJvcjIsICJFcnJvciB3aGlsZSBwcm9jZXNzaW5nIHJvdXRlOiAiICsgdHJhbnNpdGlvbi50YXJnZXROYW1lKTsKICAgIH0sCiAgICAvLyBBdHRlbXB0IHRvIGZpbmQgYW4gYXBwcm9wcmlhdGUgbG9hZGluZyByb3V0ZSBvciBzdWJzdGF0ZSB0byBlbnRlci4KICAgIGxvYWRpbmc6IGZ1bmN0aW9uIGxvYWRpbmcocm91dGVJbmZvcywgdHJhbnNpdGlvbikgewogICAgICB2YXIgcm91dGVyID0gdGhpczsKICAgICAgdmFyIHJvdXRlSW5mb1dpdGhTbG93TG9hZGluZyA9IHJvdXRlSW5mb3Nbcm91dGVJbmZvcy5sZW5ndGggLSAxXTsKICAgICAgZm9yRWFjaFJvdXRlQWJvdmUocm91dGVJbmZvcywgZnVuY3Rpb24gKHJvdXRlLCByb3V0ZUluZm8pIHsKICAgICAgICAvLyBXZSBkb24ndCBjaGVjayB0aGUgbGVhZiBtb3N0IHJvdXRlSW5mb3Mgc2luY2UgdGhhdCB3b3VsZAogICAgICAgIC8vIHRlY2huaWNhbGx5IGJlIGJlbG93IHdoZXJlIHdlJ3JlIGF0IGluIHRoZSByb3V0ZSBoaWVyYXJjaHkuCiAgICAgICAgaWYgKHJvdXRlSW5mbyAhPT0gcm91dGVJbmZvV2l0aFNsb3dMb2FkaW5nKSB7CiAgICAgICAgICAvLyBDaGVjayBmb3IgdGhlIGV4aXN0ZW5jZSBvZiBhICdsb2FkaW5nJyByb3V0ZS4KICAgICAgICAgIHZhciBsb2FkaW5nUm91dGVOYW1lID0gZmluZFJvdXRlU3RhdGVOYW1lKHJvdXRlLCAnbG9hZGluZycpOwoKICAgICAgICAgIGlmIChsb2FkaW5nUm91dGVOYW1lKSB7CiAgICAgICAgICAgIHJvdXRlci5pbnRlcm1lZGlhdGVUcmFuc2l0aW9uVG8obG9hZGluZ1JvdXRlTmFtZSk7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICB9IC8vIENoZWNrIGZvciBsb2FkaW5nIHN1YnN0YXRlCgoKICAgICAgICB2YXIgbG9hZGluZ1N1YnN0YXRlTmFtZSA9IGZpbmRSb3V0ZVN1YnN0YXRlTmFtZShyb3V0ZSwgJ2xvYWRpbmcnKTsKCiAgICAgICAgaWYgKGxvYWRpbmdTdWJzdGF0ZU5hbWUpIHsKICAgICAgICAgIHJvdXRlci5pbnRlcm1lZGlhdGVUcmFuc2l0aW9uVG8obG9hZGluZ1N1YnN0YXRlTmFtZSk7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfSAvLyBEb24ndCBidWJibGUgYWJvdmUgcGl2b3Qgcm91dGUuCgoKICAgICAgICByZXR1cm4gdHJhbnNpdGlvbi5waXZvdEhhbmRsZXIgIT09IHJvdXRlOwogICAgICB9KTsKICAgIH0KICB9OwoKICBmdW5jdGlvbiBsb2dFcnJvcihfZXJyb3IsIGluaXRpYWxNZXNzYWdlKSB7CiAgICB2YXIgX2NvbnNvbGU7CgogICAgdmFyIGVycm9yQXJncyA9IFtdOwogICAgdmFyIGVycm9yOwoKICAgIGlmIChfZXJyb3IgJiYgdHlwZW9mIF9lcnJvciA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIF9lcnJvci5lcnJvclRocm93biA9PT0gJ29iamVjdCcpIHsKICAgICAgZXJyb3IgPSBfZXJyb3IuZXJyb3JUaHJvd247CiAgICB9IGVsc2UgewogICAgICBlcnJvciA9IF9lcnJvcjsKICAgIH0KCiAgICBpZiAoaW5pdGlhbE1lc3NhZ2UpIHsKICAgICAgZXJyb3JBcmdzLnB1c2goaW5pdGlhbE1lc3NhZ2UpOwogICAgfQoKICAgIGlmIChlcnJvcikgewogICAgICBpZiAoZXJyb3IubWVzc2FnZSkgewogICAgICAgIGVycm9yQXJncy5wdXNoKGVycm9yLm1lc3NhZ2UpOwogICAgICB9CgogICAgICBpZiAoZXJyb3Iuc3RhY2spIHsKICAgICAgICBlcnJvckFyZ3MucHVzaChlcnJvci5zdGFjayk7CiAgICAgIH0KCiAgICAgIGlmICh0eXBlb2YgZXJyb3IgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgZXJyb3JBcmdzLnB1c2goZXJyb3IpOwogICAgICB9CiAgICB9CgogICAgKF9jb25zb2xlID0gY29uc29sZSkuZXJyb3IuYXBwbHkoX2NvbnNvbGUsIGVycm9yQXJncyk7IC8vZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlCgogIH0KICAvKioKICAgIEZpbmRzIHRoZSBuYW1lIG9mIHRoZSBzdWJzdGF0ZSByb3V0ZSBpZiBpdCBleGlzdHMgZm9yIHRoZSBnaXZlbiByb3V0ZS4gQQogICAgc3Vic3RhdGUgcm91dGUgaXMgb2YgdGhlIGZvcm0gYHJvdXRlX3N0YXRlYCwgc3VjaCBhcyBgZm9vX2xvYWRpbmdgLgogIAogICAgQHByaXZhdGUKICAgIEBwYXJhbSB7Um91dGV9IHJvdXRlCiAgICBAcGFyYW0ge1N0cmluZ30gc3RhdGUKICAgIEByZXR1cm4ge1N0cmluZ30KICAqLwoKCiAgZnVuY3Rpb24gZmluZFJvdXRlU3Vic3RhdGVOYW1lKHJvdXRlLCBzdGF0ZSkgewogICAgdmFyIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikocm91dGUpOwogICAgdmFyIHJvdXRlTmFtZSA9IHJvdXRlLnJvdXRlTmFtZSwKICAgICAgICBmdWxsUm91dGVOYW1lID0gcm91dGUuZnVsbFJvdXRlTmFtZSwKICAgICAgICByb3V0ZXIgPSByb3V0ZS5fcm91dGVyOwogICAgdmFyIHN1YnN0YXRlTmFtZSA9IHJvdXRlTmFtZSArICJfIiArIHN0YXRlOwogICAgdmFyIHN1YnN0YXRlTmFtZUZ1bGwgPSBmdWxsUm91dGVOYW1lICsgIl8iICsgc3RhdGU7CiAgICByZXR1cm4gcm91dGVIYXNCZWVuRGVmaW5lZChvd25lciwgcm91dGVyLCBzdWJzdGF0ZU5hbWUsIHN1YnN0YXRlTmFtZUZ1bGwpID8gc3Vic3RhdGVOYW1lRnVsbCA6ICcnOwogIH0KICAvKioKICAgIEZpbmRzIHRoZSBuYW1lIG9mIHRoZSBzdGF0ZSByb3V0ZSBpZiBpdCBleGlzdHMgZm9yIHRoZSBnaXZlbiByb3V0ZS4gQSBzdGF0ZQogICAgcm91dGUgaXMgb2YgdGhlIGZvcm0gYHJvdXRlLnN0YXRlYCwgc3VjaCBhcyBgZm9vLmxvYWRpbmdgLiBQcm9wZXJseSBIYW5kbGVzCiAgICBgYXBwbGljYXRpb25gIG5hbWVkIHJvdXRlcy4KICAKICAgIEBwcml2YXRlCiAgICBAcGFyYW0ge1JvdXRlfSByb3V0ZQogICAgQHBhcmFtIHtTdHJpbmd9IHN0YXRlCiAgICBAcmV0dXJuIHtTdHJpbmd9CiAgKi8KCgogIGZ1bmN0aW9uIGZpbmRSb3V0ZVN0YXRlTmFtZShyb3V0ZSwgc3RhdGUpIHsKICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHJvdXRlKTsKICAgIHZhciByb3V0ZU5hbWUgPSByb3V0ZS5yb3V0ZU5hbWUsCiAgICAgICAgZnVsbFJvdXRlTmFtZSA9IHJvdXRlLmZ1bGxSb3V0ZU5hbWUsCiAgICAgICAgcm91dGVyID0gcm91dGUuX3JvdXRlcjsKICAgIHZhciBzdGF0ZU5hbWUgPSByb3V0ZU5hbWUgPT09ICdhcHBsaWNhdGlvbicgPyBzdGF0ZSA6IHJvdXRlTmFtZSArICIuIiArIHN0YXRlOwogICAgdmFyIHN0YXRlTmFtZUZ1bGwgPSBmdWxsUm91dGVOYW1lID09PSAnYXBwbGljYXRpb24nID8gc3RhdGUgOiBmdWxsUm91dGVOYW1lICsgIi4iICsgc3RhdGU7CiAgICByZXR1cm4gcm91dGVIYXNCZWVuRGVmaW5lZChvd25lciwgcm91dGVyLCBzdGF0ZU5hbWUsIHN0YXRlTmFtZUZ1bGwpID8gc3RhdGVOYW1lRnVsbCA6ICcnOwogIH0KICAvKioKICAgIERldGVybWluZXMgd2hldGhlciBvciBub3QgYSByb3V0ZSBoYXMgYmVlbiBkZWZpbmVkIGJ5IGNoZWNraW5nIHRoYXQgdGhlIHJvdXRlCiAgICBpcyBpbiB0aGUgUm91dGVyJ3MgbWFwIGFuZCB0aGUgb3duZXIgaGFzIGEgcmVnaXN0cmF0aW9uIGZvciB0aGF0IHJvdXRlLgogIAogICAgQHByaXZhdGUKICAgIEBwYXJhbSB7T3duZXJ9IG93bmVyCiAgICBAcGFyYW0ge1JvdXRlcn0gcm91dGVyCiAgICBAcGFyYW0ge1N0cmluZ30gbG9jYWxOYW1lCiAgICBAcGFyYW0ge1N0cmluZ30gZnVsbE5hbWUKICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgKi8KCgogIGZ1bmN0aW9uIHJvdXRlSGFzQmVlbkRlZmluZWQob3duZXIsIHJvdXRlciwgbG9jYWxOYW1lLCBmdWxsTmFtZSkgewogICAgdmFyIHJvdXRlckhhc1JvdXRlID0gcm91dGVyLmhhc1JvdXRlKGZ1bGxOYW1lKTsKICAgIHZhciBvd25lckhhc1JvdXRlID0gb3duZXIuaGFzUmVnaXN0cmF0aW9uKCJ0ZW1wbGF0ZToiICsgbG9jYWxOYW1lKSB8fCBvd25lci5oYXNSZWdpc3RyYXRpb24oInJvdXRlOiIgKyBsb2NhbE5hbWUpOwogICAgcmV0dXJuIHJvdXRlckhhc1JvdXRlICYmIG93bmVySGFzUm91dGU7CiAgfQoKICBmdW5jdGlvbiBfdHJpZ2dlckV2ZW50KHJvdXRlSW5mb3MsIGlnbm9yZUZhaWx1cmUsIG5hbWUsIGFyZ3MpIHsKICAgIGlmICghcm91dGVJbmZvcykgewogICAgICBpZiAoaWdub3JlRmFpbHVyZSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhyb3cgbmV3IF9lcnJvcjMuZGVmYXVsdCgiQ2FuJ3QgdHJpZ2dlciBhY3Rpb24gJyIgKyBuYW1lICsgIicgYmVjYXVzZSB5b3VyIGFwcCBoYXNuJ3QgZmluaXNoZWQgdHJhbnNpdGlvbmluZyBpbnRvIGl0cyBmaXJzdCByb3V0ZS4gVG8gdHJpZ2dlciBhbiBhY3Rpb24gb24gZGVzdGluYXRpb24gcm91dGVzIGR1cmluZyBhIHRyYW5zaXRpb24sIHlvdSBjYW4gY2FsbCBgLnNlbmQoKWAgb24gdGhlIGBUcmFuc2l0aW9uYCBvYmplY3QgcGFzc2VkIHRvIHRoZSBgbW9kZWwvYmVmb3JlTW9kZWwvYWZ0ZXJNb2RlbGAgaG9va3MuIik7CiAgICB9CgogICAgdmFyIGV2ZW50V2FzSGFuZGxlZCA9IGZhbHNlOwogICAgdmFyIHJvdXRlSW5mbywgaGFuZGxlciwgYWN0aW9uSGFuZGxlcjsKCiAgICBmb3IgKHZhciBpID0gcm91dGVJbmZvcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICByb3V0ZUluZm8gPSByb3V0ZUluZm9zW2ldOwogICAgICBoYW5kbGVyID0gcm91dGVJbmZvLnJvdXRlOwogICAgICBhY3Rpb25IYW5kbGVyID0gaGFuZGxlciAmJiBoYW5kbGVyLmFjdGlvbnMgJiYgaGFuZGxlci5hY3Rpb25zW25hbWVdOwoKICAgICAgaWYgKGFjdGlvbkhhbmRsZXIpIHsKICAgICAgICBpZiAoYWN0aW9uSGFuZGxlci5hcHBseShoYW5kbGVyLCBhcmdzKSA9PT0gdHJ1ZSkgewogICAgICAgICAgZXZlbnRXYXNIYW5kbGVkID0gdHJ1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgLy8gU2hvdWxkIG9ubHkgaGl0IGhlcmUgaWYgYSBub24tYnViYmxpbmcgZXJyb3IgYWN0aW9uIGlzIHRyaWdnZXJlZCBvbiBhIHJvdXRlLgogICAgICAgICAgaWYgKG5hbWUgPT09ICdlcnJvcicpIHsKICAgICAgICAgICAgaGFuZGxlci5fcm91dGVyLl9tYXJrRXJyb3JBc0hhbmRsZWQoYXJnc1swXSk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgfQogICAgfQoKICAgIHZhciBkZWZhdWx0SGFuZGxlciA9IGRlZmF1bHRBY3Rpb25IYW5kbGVyc1tuYW1lXTsKCiAgICBpZiAoZGVmYXVsdEhhbmRsZXIpIHsKICAgICAgZGVmYXVsdEhhbmRsZXIuYXBwbHkodGhpcywgW3JvdXRlSW5mb3NdLmNvbmNhdChhcmdzKSk7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoIWV2ZW50V2FzSGFuZGxlZCAmJiAhaWdub3JlRmFpbHVyZSkgewogICAgICB0aHJvdyBuZXcgX2Vycm9yMy5kZWZhdWx0KCJOb3RoaW5nIGhhbmRsZWQgdGhlIGFjdGlvbiAnIiArIG5hbWUgKyAiJy4gSWYgeW91IGRpZCBoYW5kbGUgdGhlIGFjdGlvbiwgdGhpcyBlcnJvciBjYW4gYmUgY2F1c2VkIGJ5IHJldHVybmluZyB0cnVlIGZyb20gYW4gYWN0aW9uIGhhbmRsZXIgaW4gYSBjb250cm9sbGVyLCBjYXVzaW5nIHRoZSBhY3Rpb24gdG8gYnViYmxlLiIpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gY2FsY3VsYXRlUG9zdFRyYW5zaXRpb25TdGF0ZShlbWJlclJvdXRlciwgbGVhZlJvdXRlTmFtZSwgY29udGV4dHMpIHsKICAgIHZhciBzdGF0ZSA9IGVtYmVyUm91dGVyLl9yb3V0ZXJNaWNyb2xpYi5hcHBseUludGVudChsZWFmUm91dGVOYW1lLCBjb250ZXh0cyk7CgogICAgdmFyIHJvdXRlSW5mb3MgPSBzdGF0ZS5yb3V0ZUluZm9zLAogICAgICAgIHBhcmFtcyA9IHN0YXRlLnBhcmFtczsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvdXRlSW5mb3MubGVuZ3RoOyArK2kpIHsKICAgICAgdmFyIHJvdXRlSW5mbyA9IHJvdXRlSW5mb3NbaV07IC8vIElmIHRoZSByb3V0ZUluZm8gaXMgbm90IHJlc29sdmVkLCB3ZSBzZXJpYWxpemUgdGhlIGNvbnRleHQgaW50byBwYXJhbXMKCiAgICAgIGlmICghcm91dGVJbmZvLmlzUmVzb2x2ZWQpIHsKICAgICAgICBwYXJhbXNbcm91dGVJbmZvLm5hbWVdID0gcm91dGVJbmZvLnNlcmlhbGl6ZShyb3V0ZUluZm8uY29udGV4dCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcGFyYW1zW3JvdXRlSW5mby5uYW1lXSA9IHJvdXRlSW5mby5wYXJhbXM7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gc3RhdGU7CiAgfQoKICBmdW5jdGlvbiB1cGRhdGVQYXRocyhyb3V0ZXIpIHsKICAgIHZhciBpbmZvcyA9IHJvdXRlci5fcm91dGVyTWljcm9saWIuY3VycmVudFJvdXRlSW5mb3M7CgogICAgaWYgKGluZm9zLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm47CiAgICB9CgogICAgdmFyIHBhdGggPSBFbWJlclJvdXRlci5fcm91dGVQYXRoKGluZm9zKTsKCiAgICB2YXIgY3VycmVudFJvdXRlTmFtZSA9IGluZm9zW2luZm9zLmxlbmd0aCAtIDFdLm5hbWU7CiAgICB2YXIgY3VycmVudFVSTCA9IHJvdXRlci5nZXQoJ2xvY2F0aW9uJykuZ2V0VVJMKCk7CiAgICAoMCwgX21ldGFsLnNldCkocm91dGVyLCAnY3VycmVudFBhdGgnLCBwYXRoKTsKICAgICgwLCBfbWV0YWwuc2V0KShyb3V0ZXIsICdjdXJyZW50Um91dGVOYW1lJywgY3VycmVudFJvdXRlTmFtZSk7CiAgICAoMCwgX21ldGFsLnNldCkocm91dGVyLCAnY3VycmVudFVSTCcsIGN1cnJlbnRVUkwpOwogICAgdmFyIGFwcENvbnRyb2xsZXIgPSAoMCwgX293bmVyLmdldE93bmVyKShyb3V0ZXIpLmxvb2t1cCgnY29udHJvbGxlcjphcHBsaWNhdGlvbicpOwoKICAgIGlmICghYXBwQ29udHJvbGxlcikgewogICAgICAvLyBhcHBDb250cm9sbGVyIG1pZ2h0IG5vdCBleGlzdCB3aGVuIHRvcC1sZXZlbCBsb2FkaW5nL2Vycm9yCiAgICAgIC8vIHN1YnN0YXRlcyBoYXZlIGJlZW4gZW50ZXJlZCBzaW5jZSBBcHBsaWNhdGlvblJvdXRlIGhhc24ndAogICAgICAvLyBhY3R1YWxseSBiZWVuIGVudGVyZWQgYXQgdGhhdCBwb2ludC4KICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmIChfZGVwcmVjYXRlZEZlYXR1cmVzLkFQUF9DVFJMX1JPVVRFUl9QUk9QUykgewogICAgICBpZiAoISgnY3VycmVudFBhdGgnIGluIGFwcENvbnRyb2xsZXIpKSB7CiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGFwcENvbnRyb2xsZXIsICdjdXJyZW50UGF0aCcsIHsKICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdBY2Nlc3NpbmcgYGN1cnJlbnRQYXRoYCBvbiBgY29udHJvbGxlcjphcHBsaWNhdGlvbmAgaXMgZGVwcmVjYXRlZCwgdXNlIHRoZSBgY3VycmVudFBhdGhgIHByb3BlcnR5IG9uIGBzZXJ2aWNlOnJvdXRlcmAgaW5zdGVhZC4nLCBmYWxzZSwgewogICAgICAgICAgICAgIGlkOiAnYXBwbGljYXRpb24tY29udHJvbGxlci5yb3V0ZXItcHJvcGVydGllcycsCiAgICAgICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfYXBwbGljYXRpb24tY29udHJvbGxlci1yb3V0ZXItcHJvcGVydGllcycKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHJvdXRlciwgJ2N1cnJlbnRQYXRoJyk7CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgICgwLCBfbWV0YWwubm90aWZ5UHJvcGVydHlDaGFuZ2UpKGFwcENvbnRyb2xsZXIsICdjdXJyZW50UGF0aCcpOwoKICAgICAgaWYgKCEoJ2N1cnJlbnRSb3V0ZU5hbWUnIGluIGFwcENvbnRyb2xsZXIpKSB7CiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGFwcENvbnRyb2xsZXIsICdjdXJyZW50Um91dGVOYW1lJywgewogICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoJ0FjY2Vzc2luZyBgY3VycmVudFJvdXRlTmFtZWAgb24gYGNvbnRyb2xsZXI6YXBwbGljYXRpb25gIGlzIGRlcHJlY2F0ZWQsIHVzZSB0aGUgYGN1cnJlbnRSb3V0ZU5hbWVgIHByb3BlcnR5IG9uIGBzZXJ2aWNlOnJvdXRlcmAgaW5zdGVhZC4nLCBmYWxzZSwgewogICAgICAgICAgICAgIGlkOiAnYXBwbGljYXRpb24tY29udHJvbGxlci5yb3V0ZXItcHJvcGVydGllcycsCiAgICAgICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfYXBwbGljYXRpb24tY29udHJvbGxlci1yb3V0ZXItcHJvcGVydGllcycKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHJvdXRlciwgJ2N1cnJlbnRSb3V0ZU5hbWUnKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQoKICAgICAgKDAsIF9tZXRhbC5ub3RpZnlQcm9wZXJ0eUNoYW5nZSkoYXBwQ29udHJvbGxlciwgJ2N1cnJlbnRSb3V0ZU5hbWUnKTsKICAgIH0KICB9CgogIEVtYmVyUm91dGVyLnJlb3BlbkNsYXNzKHsKICAgIC8qKgogICAgICBUaGUgYFJvdXRlci5tYXBgIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gZGVmaW5lIG1hcHBpbmdzIGZyb20gVVJMcyB0byByb3V0ZXMKICAgICAgaW4geW91ciBhcHBsaWNhdGlvbi4gVGhlc2UgbWFwcGluZ3MgYXJlIGRlZmluZWQgd2l0aGluIHRoZQogICAgICBzdXBwbGllZCBjYWxsYmFjayBmdW5jdGlvbiB1c2luZyBgdGhpcy5yb3V0ZWAuCiAgICAgICAgIFRoZSBmaXJzdCBwYXJhbWV0ZXIgaXMgdGhlIG5hbWUgb2YgdGhlIHJvdXRlIHdoaWNoIGlzIHVzZWQgYnkgZGVmYXVsdCBhcyB0aGUKICAgICAgcGF0aCBuYW1lIGFzIHdlbGwuCiAgICAgICAgIFRoZSBzZWNvbmQgcGFyYW1ldGVyIGlzIHRoZSBvcHRpb25hbCBvcHRpb25zIGhhc2guIEF2YWlsYWJsZSBvcHRpb25zIGFyZToKICAgICAgICAgICAqIGBwYXRoYDogYWxsb3dzIHlvdSB0byBwcm92aWRlIHlvdXIgb3duIHBhdGggYXMgd2VsbCBhcyBtYXJrIGR5bmFtaWMKICAgICAgICAgIHNlZ21lbnRzLgogICAgICAgICogYHJlc2V0TmFtZXNwYWNlYDogZmFsc2UgYnkgZGVmYXVsdDsgd2hlbiBuZXN0aW5nIHJvdXRlcywgZW1iZXIgd2lsbAogICAgICAgICAgY29tYmluZSB0aGUgcm91dGUgbmFtZXMgdG8gZm9ybSB0aGUgZnVsbHktcXVhbGlmaWVkIHJvdXRlIG5hbWUsIHdoaWNoIGlzCiAgICAgICAgICB1c2VkIHdpdGggYHt7bGluay10b319YCBvciBtYW51YWxseSB0cmFuc2l0aW9uaW5nIHRvIHJvdXRlcy4gU2V0dGluZwogICAgICAgICAgYHJlc2V0TmFtZXNwYWNlOiB0cnVlYCB3aWxsIGNhdXNlIHRoZSByb3V0ZSBub3QgdG8gaW5oZXJpdCBmcm9tIGl0cwogICAgICAgICAgcGFyZW50IHJvdXRlJ3MgbmFtZXMuIFRoaXMgaXMgaGFuZHkgZm9yIHByZXZlbnRpbmcgZXh0cmVtZWx5IGxvbmcgcm91dGUgbmFtZXMuCiAgICAgICAgICBLZWVwIGluIG1pbmQgdGhhdCB0aGUgYWN0dWFsIFVSTCBwYXRoIGJlaGF2aW9yIGlzIHN0aWxsIHJldGFpbmVkLgogICAgICAgICBUaGUgdGhpcmQgcGFyYW1ldGVyIGlzIGEgZnVuY3Rpb24sIHdoaWNoIGNhbiBiZSB1c2VkIHRvIG5lc3Qgcm91dGVzLgogICAgICBOZXN0ZWQgcm91dGVzLCBieSBkZWZhdWx0LCB3aWxsIGhhdmUgdGhlIHBhcmVudCByb3V0ZSB0cmVlJ3Mgcm91dGUgbmFtZSBhbmQKICAgICAgcGF0aCBwcmVwZW5kZWQgdG8gaXQncyBvd24uCiAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpewogICAgICAgIHRoaXMucm91dGUoJ3Bvc3QnLCB7IHBhdGg6ICcvcG9zdC86cG9zdF9pZCcgfSwgZnVuY3Rpb24oKSB7CiAgICAgICAgICB0aGlzLnJvdXRlKCdlZGl0Jyk7CiAgICAgICAgICB0aGlzLnJvdXRlKCdjb21tZW50cycsIHsgcmVzZXROYW1lc3BhY2U6IHRydWUgfSwgZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHRoaXMucm91dGUoJ25ldycpOwogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBtYXAKICAgICAgQHBhcmFtIGNhbGxiYWNrCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBtYXA6IGZ1bmN0aW9uIG1hcChjYWxsYmFjaykgewogICAgICBpZiAoIXRoaXMuZHNsQ2FsbGJhY2tzKSB7CiAgICAgICAgdGhpcy5kc2xDYWxsYmFja3MgPSBbXTsKICAgICAgICB0aGlzLnJlb3BlbkNsYXNzKHsKICAgICAgICAgIGRzbENhbGxiYWNrczogdGhpcy5kc2xDYWxsYmFja3MKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgdGhpcy5kc2xDYWxsYmFja3MucHVzaChjYWxsYmFjayk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKICAgIF9yb3V0ZVBhdGg6IGZ1bmN0aW9uIF9yb3V0ZVBhdGgocm91dGVJbmZvcykgewogICAgICB2YXIgcGF0aCA9IFtdOyAvLyBXZSBoYXZlIHRvIGhhbmRsZSBjb2FsZXNjaW5nIHJlc291cmNlIG5hbWVzIHRoYXQKICAgICAgLy8gYXJlIHByZWZpeGVkIHdpdGggdGhlaXIgcGFyZW50J3MgbmFtZXMsIGUuZy4KICAgICAgLy8gWydmb28nLCAnZm9vLmJhci5iYXonXSA9PiAnZm9vLmJhci5iYXonLCBub3QgJ2Zvby5mb28uYmFyLmJheicKCiAgICAgIGZ1bmN0aW9uIGludGVyc2VjdGlvbk1hdGNoZXMoYTEsIGEyKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhMS5sZW5ndGg7ICsraSkgewogICAgICAgICAgaWYgKGExW2ldICE9PSBhMltpXSkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgdmFyIG5hbWUsIG5hbWVQYXJ0cywgb2xkTmFtZVBhcnRzOwoKICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCByb3V0ZUluZm9zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgbmFtZSA9IHJvdXRlSW5mb3NbaV0ubmFtZTsKICAgICAgICBuYW1lUGFydHMgPSBuYW1lLnNwbGl0KCcuJyk7CiAgICAgICAgb2xkTmFtZVBhcnRzID0gc2xpY2UuY2FsbChwYXRoKTsKCiAgICAgICAgd2hpbGUgKG9sZE5hbWVQYXJ0cy5sZW5ndGgpIHsKICAgICAgICAgIGlmIChpbnRlcnNlY3Rpb25NYXRjaGVzKG9sZE5hbWVQYXJ0cywgbmFtZVBhcnRzKSkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KCiAgICAgICAgICBvbGROYW1lUGFydHMuc2hpZnQoKTsKICAgICAgICB9CgogICAgICAgIHBhdGgucHVzaC5hcHBseShwYXRoLCBuYW1lUGFydHMuc2xpY2Uob2xkTmFtZVBhcnRzLmxlbmd0aCkpOwogICAgICB9CgogICAgICByZXR1cm4gcGF0aC5qb2luKCcuJyk7CiAgICB9CiAgfSk7CgogIGZ1bmN0aW9uIGRpZEJlZ2luVHJhbnNpdGlvbih0cmFuc2l0aW9uLCByb3V0ZXIpIHsKICAgIHZhciByb3V0ZXJTdGF0ZSA9IG5ldyBfcm91dGVyX3N0YXRlLmRlZmF1bHQocm91dGVyLCByb3V0ZXIuX3JvdXRlck1pY3JvbGliLCB0cmFuc2l0aW9uW19yb3V0ZXJfanMuU1RBVEVfU1lNQk9MXSk7CgogICAgaWYgKCFyb3V0ZXIuY3VycmVudFN0YXRlKSB7CiAgICAgIHJvdXRlci5zZXQoJ2N1cnJlbnRTdGF0ZScsIHJvdXRlclN0YXRlKTsKICAgIH0KCiAgICByb3V0ZXIuc2V0KCd0YXJnZXRTdGF0ZScsIHJvdXRlclN0YXRlKTsKICAgIHRyYW5zaXRpb24ucHJvbWlzZSA9IHRyYW5zaXRpb24uY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7CiAgICAgIGlmIChyb3V0ZXIuX2lzRXJyb3JIYW5kbGVkKGVycm9yKSkgewogICAgICAgIHJvdXRlci5fY2xlYXJIYW5kbGVkRXJyb3IoZXJyb3IpOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IGVycm9yOwogICAgICB9CiAgICB9LCAnVHJhbnNpdGlvbiBFcnJvcicpOwogIH0KCiAgZnVuY3Rpb24gZm9yRWFjaFF1ZXJ5UGFyYW0ocm91dGVyLCByb3V0ZUluZm9zLCBxdWVyeVBhcmFtcywgY2FsbGJhY2spIHsKICAgIHZhciBxcENhY2hlID0gcm91dGVyLl9xdWVyeVBhcmFtc0Zvcihyb3V0ZUluZm9zKTsKCiAgICBmb3IgKHZhciBrZXkgaW4gcXVlcnlQYXJhbXMpIHsKICAgICAgaWYgKCFxdWVyeVBhcmFtcy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIHZhciB2YWx1ZSA9IHF1ZXJ5UGFyYW1zW2tleV07CiAgICAgIHZhciBxcCA9IHFwQ2FjaGUubWFwW2tleV07CiAgICAgIGNhbGxiYWNrKGtleSwgdmFsdWUsIHFwKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGZpbmRMaXZlUm91dGUobGl2ZVJvdXRlcywgbmFtZSkgewogICAgaWYgKCFsaXZlUm91dGVzKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgc3RhY2sgPSBbbGl2ZVJvdXRlc107CgogICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgdmFyIHRlc3QgPSBzdGFjay5zaGlmdCgpOwoKICAgICAgaWYgKHRlc3QucmVuZGVyLm5hbWUgPT09IG5hbWUpIHsKICAgICAgICByZXR1cm4gdGVzdDsKICAgICAgfQoKICAgICAgdmFyIG91dGxldHMgPSB0ZXN0Lm91dGxldHM7CgogICAgICBmb3IgKHZhciBvdXRsZXROYW1lIGluIG91dGxldHMpIHsKICAgICAgICBzdGFjay5wdXNoKG91dGxldHNbb3V0bGV0TmFtZV0pOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuOwogIH0KCiAgZnVuY3Rpb24gYXBwZW5kTGl2ZVJvdXRlKGxpdmVSb3V0ZXMsIGRlZmF1bHRQYXJlbnRTdGF0ZSwgcmVuZGVyT3B0aW9ucykgewogICAgdmFyIHRhcmdldDsKICAgIHZhciBteVN0YXRlID0gewogICAgICByZW5kZXI6IHJlbmRlck9wdGlvbnMsCiAgICAgIG91dGxldHM6IE9iamVjdC5jcmVhdGUobnVsbCksCiAgICAgIHdhc1VzZWQ6IGZhbHNlCiAgICB9OwoKICAgIGlmIChyZW5kZXJPcHRpb25zLmludG8pIHsKICAgICAgdGFyZ2V0ID0gZmluZExpdmVSb3V0ZShsaXZlUm91dGVzLCByZW5kZXJPcHRpb25zLmludG8pOwogICAgfSBlbHNlIHsKICAgICAgdGFyZ2V0ID0gZGVmYXVsdFBhcmVudFN0YXRlOwogICAgfQoKICAgIGlmICh0YXJnZXQpIHsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRhcmdldC5vdXRsZXRzLCByZW5kZXJPcHRpb25zLm91dGxldCwgbXlTdGF0ZSk7CiAgICB9IGVsc2UgewogICAgICBsaXZlUm91dGVzID0gbXlTdGF0ZTsKICAgIH0KCiAgICByZXR1cm4gewogICAgICBsaXZlUm91dGVzOiBsaXZlUm91dGVzLAogICAgICBvd25TdGF0ZTogbXlTdGF0ZQogICAgfTsKICB9CgogIGZ1bmN0aW9uIHJlcHJlc2VudEVtcHR5Um91dGUobGl2ZVJvdXRlcywgZGVmYXVsdFBhcmVudFN0YXRlLCByb3V0ZSkgewogICAgLy8gdGhlIHJvdXRlIGRpZG4ndCByZW5kZXIgYW55dGhpbmcKICAgIHZhciBhbHJlYWR5QXBwZW5kZWQgPSBmaW5kTGl2ZVJvdXRlKGxpdmVSb3V0ZXMsIHJvdXRlLnJvdXRlTmFtZSk7CgogICAgaWYgKGFscmVhZHlBcHBlbmRlZCkgewogICAgICAvLyBCdXQgc29tZSBvdGhlciByb3V0ZSBoYXMgYWxyZWFkeSByZW5kZXJlZCBvdXIgZGVmYXVsdAogICAgICAvLyB0ZW1wbGF0ZSwgc28gdGhhdCBiZWNvbWVzIHRoZSBkZWZhdWx0IHRhcmdldCBmb3IgYW55CiAgICAgIC8vIGNoaWxkcmVuIHdlIG1heSBoYXZlLgogICAgICByZXR1cm4gYWxyZWFkeUFwcGVuZGVkOwogICAgfSBlbHNlIHsKICAgICAgLy8gQ3JlYXRlIGFuIGVudHJ5IHRvIHJlcHJlc2VudCBvdXIgZGVmYXVsdCB0ZW1wbGF0ZSBuYW1lLAogICAgICAvLyBqdXN0IHNvIG90aGVyIHJvdXRlcyBjYW4gdGFyZ2V0IGl0IGFuZCBpbmhlcml0IGl0cyBwbGFjZQogICAgICAvLyBpbiB0aGUgb3V0bGV0IGhpZXJhcmNoeS4KICAgICAgZGVmYXVsdFBhcmVudFN0YXRlLm91dGxldHMubWFpbiA9IHsKICAgICAgICByZW5kZXI6IHsKICAgICAgICAgIG5hbWU6IHJvdXRlLnJvdXRlTmFtZSwKICAgICAgICAgIG91dGxldDogJ21haW4nCiAgICAgICAgfSwKICAgICAgICBvdXRsZXRzOiB7fQogICAgICB9OwogICAgICByZXR1cm4gZGVmYXVsdFBhcmVudFN0YXRlOwogICAgfQogIH0KCiAgRW1iZXJSb3V0ZXIucmVvcGVuKF9ydW50aW1lLkV2ZW50ZWQsIHsKICAgIC8qKgogICAgICBIYW5kbGVzIHVwZGF0aW5nIHRoZSBwYXRocyBhbmQgbm90aWZ5aW5nIGFueSBsaXN0ZW5lcnMgb2YgdGhlIFVSTAogICAgICBjaGFuZ2UuCiAgICAgICAgIFRyaWdnZXJzIHRoZSByb3V0ZXIgbGV2ZWwgYGRpZFRyYW5zaXRpb25gIGhvb2suCiAgICAgICAgIEZvciBleGFtcGxlLCB0byBub3RpZnkgZ29vZ2xlIGFuYWx5dGljcyB3aGVuIHRoZSByb3V0ZSBjaGFuZ2VzLAogICAgICB5b3UgY291bGQgdXNlIHRoaXMgaG9vay4gIChOb3RlOiByZXF1aXJlcyBhbHNvIGluY2x1ZGluZyBHQSBzY3JpcHRzLCBldGMuKQogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBjb25maWcgZnJvbSAnLi9jb25maWcvZW52aXJvbm1lbnQnOwogICAgICBpbXBvcnQgRW1iZXJSb3V0ZXIgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGVyJzsKICAgICAgaW1wb3J0IHsgaW5qZWN0IGFzIHNlcnZpY2UgfSBmcm9tICdAZW1iZXIvc2VydmljZSc7CiAgICAgICAgIGxldCBSb3V0ZXIgPSBFbWJlclJvdXRlci5leHRlbmQoewogICAgICAgIGxvY2F0aW9uOiBjb25maWcubG9jYXRpb25UeXBlLAogICAgICAgICAgIHJvdXRlcjogc2VydmljZSgpLAogICAgICAgICAgIGRpZFRyYW5zaXRpb246IGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICAgICAgIGdhKCdzZW5kJywgJ3BhZ2V2aWV3JywgewogICAgICAgICAgICBwYWdlOiB0aGlzLnJvdXRlci5jdXJyZW50VVJMLAogICAgICAgICAgICB0aXRsZTogdGhpcy5yb3V0ZXIuY3VycmVudFJvdXRlTmFtZSwKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIGRpZFRyYW5zaXRpb24KICAgICAgQHB1YmxpYwogICAgICBAc2luY2UgMS4yLjAKICAgICovCiAgICBkaWRUcmFuc2l0aW9uOiBkZWZhdWx0RGlkVHJhbnNpdGlvbiwKCiAgICAvKioKICAgICAgSGFuZGxlcyBub3RpZnlpbmcgYW55IGxpc3RlbmVycyBvZiBhbiBpbXBlbmRpbmcgVVJMCiAgICAgIGNoYW5nZS4KICAgICAgICAgVHJpZ2dlcnMgdGhlIHJvdXRlciBsZXZlbCBgd2lsbFRyYW5zaXRpb25gIGhvb2suCiAgICAgICAgIEBtZXRob2Qgd2lsbFRyYW5zaXRpb24KICAgICAgQHB1YmxpYwogICAgICBAc2luY2UgMS4xMS4wCiAgICAqLwogICAgd2lsbFRyYW5zaXRpb246IGRlZmF1bHRXaWxsVHJhbnNpdGlvbiwKCiAgICAvKioKICAgICBSZXByZXNlbnRzIHRoZSBVUkwgb2YgdGhlIHJvb3Qgb2YgdGhlIGFwcGxpY2F0aW9uLCBvZnRlbiAnLycuIFRoaXMgcHJlZml4IGlzCiAgICAgYXNzdW1lZCBvbiBhbGwgcm91dGVzIGRlZmluZWQgb24gdGhpcyByb3V0ZXIuCiAgICAgICAgQHByb3BlcnR5IHJvb3RVUkwKICAgICBAZGVmYXVsdCAnLycKICAgICBAcHVibGljCiAgICAqLwogICAgcm9vdFVSTDogJy8nLAoKICAgIC8qKgogICAgIFRoZSBgbG9jYXRpb25gIHByb3BlcnR5IGRldGVybWluZXMgdGhlIHR5cGUgb2YgVVJMJ3MgdGhhdCB5b3VyCiAgICAgYXBwbGljYXRpb24gd2lsbCB1c2UuCiAgICAgICAgVGhlIGZvbGxvd2luZyBsb2NhdGlvbiB0eXBlcyBhcmUgY3VycmVudGx5IGF2YWlsYWJsZToKICAgICAgICAqIGBoaXN0b3J5YCAtIHVzZSB0aGUgYnJvd3NlcidzIGhpc3RvcnkgQVBJIHRvIG1ha2UgdGhlIFVSTHMgbG9vayBqdXN0IGxpa2UgYW55IHN0YW5kYXJkIFVSTAogICAgICogYGhhc2hgIC0gdXNlIGAjYCB0byBzZXBhcmF0ZSB0aGUgc2VydmVyIHBhcnQgb2YgdGhlIFVSTCBmcm9tIHRoZSBFbWJlciBwYXJ0OiBgL2Jsb2cvIy9wb3N0cy9uZXdgCiAgICAgKiBgbm9uZWAgLSBkbyBub3Qgc3RvcmUgdGhlIEVtYmVyIFVSTCBpbiB0aGUgYWN0dWFsIGJyb3dzZXIgVVJMIChtYWlubHkgdXNlZCBmb3IgdGVzdGluZykKICAgICAqIGBhdXRvYCAtIHVzZSB0aGUgYmVzdCBvcHRpb24gYmFzZWQgb24gYnJvd3NlciBjYXBhYmlsaXRpZXM6IGBoaXN0b3J5YCBpZiBwb3NzaWJsZSwgdGhlbiBgaGFzaGAgaWYgcG9zc2libGUsIG90aGVyd2lzZSBgbm9uZWAKICAgICAgICBUaGlzIHZhbHVlIGlzIGRlZmF1bHRlZCB0byBgYXV0b2AgYnkgdGhlIGBsb2NhdGlvblR5cGVgIHNldHRpbmcgb2YgYC9jb25maWcvZW52aXJvbm1lbnQuanNgCiAgICAgICAgQHByb3BlcnR5IGxvY2F0aW9uCiAgICAgQGRlZmF1bHQgJ2hhc2gnCiAgICAgQHNlZSB7TG9jYXRpb259CiAgICAgQHB1YmxpYwogICAgKi8KICAgIGxvY2F0aW9uOiAnaGFzaCcsCgogICAgLyoqCiAgICAgUmVwcmVzZW50cyB0aGUgY3VycmVudCBVUkwuCiAgICAgICAgQHByb3BlcnR5IHVybAogICAgIEB0eXBlIHtTdHJpbmd9CiAgICAgQHByaXZhdGUKICAgICovCiAgICB1cmw6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGxvY2F0aW9uID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdsb2NhdGlvbicpOwoKICAgICAgaWYgKHR5cGVvZiBsb2NhdGlvbiA9PT0gJ3N0cmluZycpIHsKICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgICB9CgogICAgICByZXR1cm4gbG9jYXRpb24uZ2V0VVJMKCk7CiAgICB9KQogIH0pOwoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5ST1VURVJfRVZFTlRTKSB7CiAgICBFbWJlclJvdXRlci5yZW9wZW4oX3JvdXRlLlJPVVRFUl9FVkVOVF9ERVBSRUNBVElPTlMpOwogIH0KCiAgdmFyIF9kZWZhdWx0ID0gRW1iZXJSb3V0ZXI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vcm91dGVyX3N0YXRlIiwgWyJleHBvcnRzIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvdXRpbHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfcG9seWZpbGxzLCBfdXRpbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIHZhciBSb3V0ZXJTdGF0ZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJvdXRlclN0YXRlKGVtYmVyUm91dGVyLCByb3V0ZXIsIHJvdXRlckpzU3RhdGUpIHsKICAgICAgdGhpcy5lbWJlclJvdXRlciA9IGVtYmVyUm91dGVyOwogICAgICB0aGlzLnJvdXRlciA9IHJvdXRlcjsKICAgICAgdGhpcy5yb3V0ZXJKc1N0YXRlID0gcm91dGVySnNTdGF0ZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gUm91dGVyU3RhdGUucHJvdG90eXBlOwoKICAgIF9wcm90by5pc0FjdGl2ZUludGVudCA9IGZ1bmN0aW9uIGlzQWN0aXZlSW50ZW50KHJvdXRlTmFtZSwgbW9kZWxzLCBxdWVyeVBhcmFtcywgcXVlcnlQYXJhbXNNdXN0TWF0Y2gpIHsKICAgICAgdmFyIHN0YXRlID0gdGhpcy5yb3V0ZXJKc1N0YXRlOwoKICAgICAgaWYgKCF0aGlzLnJvdXRlci5pc0FjdGl2ZUludGVudChyb3V0ZU5hbWUsIG1vZGVscywgdW5kZWZpbmVkLCBzdGF0ZSkpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIGlmIChxdWVyeVBhcmFtc011c3RNYXRjaCAmJiBPYmplY3Qua2V5cyhxdWVyeVBhcmFtcykubGVuZ3RoID4gMCkgewogICAgICAgIHZhciB2aXNpYmxlUXVlcnlQYXJhbXMgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBxdWVyeVBhcmFtcyk7CgogICAgICAgIHRoaXMuZW1iZXJSb3V0ZXIuX3ByZXBhcmVRdWVyeVBhcmFtcyhyb3V0ZU5hbWUsIG1vZGVscywgdmlzaWJsZVF1ZXJ5UGFyYW1zKTsKCiAgICAgICAgcmV0dXJuICgwLCBfdXRpbHMuc2hhbGxvd0VxdWFsKSh2aXNpYmxlUXVlcnlQYXJhbXMsIHN0YXRlLnF1ZXJ5UGFyYW1zKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRydWU7CiAgICB9OwoKICAgIHJldHVybiBSb3V0ZXJTdGF0ZTsKICB9KCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBSb3V0ZXJTdGF0ZTsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL3RyYW5zaXRpb24iLCBbXSwgZnVuY3Rpb24gKCkgewogICJ1c2Ugc3RyaWN0IjsKICAvKioKICAgIEEgVHJhbnNpdGlvbiBpcyBhIHRoZW5uYWJsZSAoYSBwcm9taXNlLWxpa2Ugb2JqZWN0KSB0aGF0IHJlcHJlc2VudHMKICAgIGFuIGF0dGVtcHQgdG8gdHJhbnNpdGlvbiB0byBhbm90aGVyIHJvdXRlLiBJdCBjYW4gYmUgYWJvcnRlZCwgZWl0aGVyCiAgICBleHBsaWNpdGx5IHZpYSBgYWJvcnRgIG9yIGJ5IGF0dGVtcHRpbmcgYW5vdGhlciB0cmFuc2l0aW9uIHdoaWxlIGEKICAgIHByZXZpb3VzIG9uZSBpcyBzdGlsbCB1bmRlcndheS4gQW4gYWJvcnRlZCB0cmFuc2l0aW9uIGNhbiBhbHNvCiAgICBiZSBgcmV0cnkoKWBkIGxhdGVyLgogIAogICAgQGNsYXNzIFRyYW5zaXRpb24KICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSBUcmFuc2l0aW9uJ3MgaW50ZXJuYWwgcHJvbWlzZS4gQ2FsbGluZyBgLnRoZW5gIG9uIHRoaXMgcHJvcGVydHkKICAgIGlzIHRoYXQgc2FtZSBhcyBjYWxsaW5nIGAudGhlbmAgb24gdGhlIFRyYW5zaXRpb24gb2JqZWN0IGl0c2VsZiwgYnV0CiAgICB0aGlzIHByb3BlcnR5IGlzIGV4cG9zZWQgZm9yIHdoZW4geW91IHdhbnQgdG8gcGFzcyBhcm91bmQgYQogICAgVHJhbnNpdGlvbidzIHByb21pc2UsIGJ1dCBub3QgdGhlIFRyYW5zaXRpb24gb2JqZWN0IGl0c2VsZiwgc2luY2UKICAgIFRyYW5zaXRpb24gb2JqZWN0IGNhbiBiZSBleHRlcm5hbGx5IGBhYm9ydGBlZCwgd2hpbGUgdGhlIHByb21pc2UKICAgIGNhbm5vdC4KICAKICAgIEBwcm9wZXJ0eSBwcm9taXNlCiAgICBAdHlwZSB7T2JqZWN0fQogICAgQHB1YmxpYwogICAgKi8KCiAgLyoqCiAgICBDdXN0b20gc3RhdGUgY2FuIGJlIHN0b3JlZCBvbiBhIFRyYW5zaXRpb24ncyBgZGF0YWAgb2JqZWN0LgogICAgVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBkZWNvcmF0aW5nIGEgVHJhbnNpdGlvbiB3aXRoaW4gYW4gZWFybGllcgogICAgaG9vayBhbmQgc2hhcmVkIHdpdGggYSBsYXRlciBob29rLiBQcm9wZXJ0aWVzIHNldCBvbiBgZGF0YWAgd2lsbAogICAgYmUgY29waWVkIHRvIG5ldyB0cmFuc2l0aW9ucyBnZW5lcmF0ZWQgYnkgY2FsbGluZyBgcmV0cnlgIG9uIHRoaXMKICAgIHRyYW5zaXRpb24uCiAgCiAgICBAcHJvcGVydHkgZGF0YQogICAgQHR5cGUge09iamVjdH0KICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIEEgc3RhbmRhcmQgcHJvbWlzZSBob29rIHRoYXQgcmVzb2x2ZXMgaWYgdGhlIHRyYW5zaXRpb24KICAgIHN1Y2NlZWRzIGFuZCByZWplY3RzIGlmIGl0IGZhaWxzL3JlZGlyZWN0cy9hYm9ydHMuCiAgCiAgICBGb3J3YXJkcyB0byB0aGUgaW50ZXJuYWwgYHByb21pc2VgIHByb3BlcnR5IHdoaWNoIHlvdSBjYW4KICAgIHVzZSBpbiBzaXR1YXRpb25zIHdoZXJlIHlvdSB3YW50IHRvIHBhc3MgYXJvdW5kIGEgdGhlbm5hYmxlLAogICAgYnV0IG5vdCB0aGUgVHJhbnNpdGlvbiBpdHNlbGYuCiAgCiAgICBAbWV0aG9kIHRoZW4KICAgIEBwYXJhbSB7RnVuY3Rpb259IG9uRnVsZmlsbGVkCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGVkCiAgICBAcGFyYW0ge1N0cmluZ30gbGFiZWwgb3B0aW9uYWwgc3RyaW5nIGZvciBsYWJlbGluZyB0aGUgcHJvbWlzZS4KICAgIFVzZWZ1bCBmb3IgdG9vbGluZy4KICAgIEByZXR1cm4ge1Byb21pc2V9CiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgCiAgICBGb3J3YXJkcyB0byB0aGUgaW50ZXJuYWwgYHByb21pc2VgIHByb3BlcnR5IHdoaWNoIHlvdSBjYW4KICAgIHVzZSBpbiBzaXR1YXRpb25zIHdoZXJlIHlvdSB3YW50IHRvIHBhc3MgYXJvdW5kIGEgdGhlbm5hYmxlLAogICAgYnV0IG5vdCB0aGUgVHJhbnNpdGlvbiBpdHNlbGYuCiAgCiAgICBAbWV0aG9kIGNhdGNoCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGlvbgogICAgQHBhcmFtIHtTdHJpbmd9IGxhYmVsIG9wdGlvbmFsIHN0cmluZyBmb3IgbGFiZWxpbmcgdGhlIHByb21pc2UuCiAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICBAcmV0dXJuIHtQcm9taXNlfQogICAgQHB1YmxpYwogICovCgogIC8qKgogIAogICAgRm9yd2FyZHMgdG8gdGhlIGludGVybmFsIGBwcm9taXNlYCBwcm9wZXJ0eSB3aGljaCB5b3UgY2FuCiAgICB1c2UgaW4gc2l0dWF0aW9ucyB3aGVyZSB5b3Ugd2FudCB0byBwYXNzIGFyb3VuZCBhIHRoZW5uYWJsZSwKICAgIGJ1dCBub3QgdGhlIFRyYW5zaXRpb24gaXRzZWxmLgogIAogICAgQG1ldGhvZCBmaW5hbGx5CiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgQHBhcmFtIHtTdHJpbmd9IGxhYmVsIG9wdGlvbmFsIHN0cmluZyBmb3IgbGFiZWxpbmcgdGhlIHByb21pc2UuCiAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICBAcmV0dXJuIHtQcm9taXNlfQogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgQWJvcnRzIHRoZSBUcmFuc2l0aW9uLiBOb3RlIHlvdSBjYW4gYWxzbyBpbXBsaWNpdGx5IGFib3J0IGEgdHJhbnNpdGlvbgogICAgYnkgaW5pdGlhdGluZyBhbm90aGVyIHRyYW5zaXRpb24gd2hpbGUgYSBwcmV2aW91cyBvbmUgaXMgdW5kZXJ3YXkuCiAgCiAgICBAbWV0aG9kIGFib3J0CiAgICBAcmV0dXJuIHtUcmFuc2l0aW9ufSB0aGlzIHRyYW5zaXRpb24KICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAKICAgIFJldHJpZXMgYSBwcmV2aW91c2x5LWFib3J0ZWQgdHJhbnNpdGlvbiAobWFraW5nIHN1cmUgdG8gYWJvcnQgdGhlCiAgICB0cmFuc2l0aW9uIGlmIGl0J3Mgc3RpbGwgYWN0aXZlKS4gUmV0dXJucyBhIG5ldyB0cmFuc2l0aW9uIHRoYXQKICAgIHJlcHJlc2VudHMgdGhlIG5ldyBhdHRlbXB0IHRvIHRyYW5zaXRpb24uCiAgCiAgICBAbWV0aG9kIHJldHJ5CiAgICBAcmV0dXJuIHtUcmFuc2l0aW9ufSBuZXcgdHJhbnNpdGlvbgogICAgQHB1YmxpYwogICAgKi8KCiAgLyoqCiAgCiAgICBTZXRzIHRoZSBVUkwtY2hhbmdpbmcgbWV0aG9kIHRvIGJlIGVtcGxveWVkIGF0IHRoZSBlbmQgb2YgYQogICAgc3VjY2Vzc2Z1bCB0cmFuc2l0aW9uLiBCeSBkZWZhdWx0LCBhIG5ldyBUcmFuc2l0aW9uIHdpbGwganVzdAogICAgdXNlIGB1cGRhdGVVUkxgLCBidXQgcGFzc2luZyAncmVwbGFjZScgdG8gdGhpcyBtZXRob2Qgd2lsbAogICAgY2F1c2UgdGhlIFVSTCB0byB1cGRhdGUgdXNpbmcgJ3JlcGxhY2VXaXRoJyBpbnN0ZWFkLiBPbWl0dGluZwogICAgYSBwYXJhbWV0ZXIgd2lsbCBkaXNhYmxlIHRoZSBVUkwgY2hhbmdlLCBhbGxvd2luZyBmb3IgdHJhbnNpdGlvbnMKICAgIHRoYXQgZG9uJ3QgdXBkYXRlIHRoZSBVUkwgYXQgY29tcGxldGlvbiAodGhpcyBpcyBhbHNvIHVzZWQgZm9yCiAgICBoYW5kbGVVUkwsIHNpbmNlIHRoZSBVUkwgaGFzIGFscmVhZHkgY2hhbmdlZCBiZWZvcmUgdGhlCiAgICB0cmFuc2l0aW9uIHRvb2sgcGxhY2UpLgogIAogICAgQG1ldGhvZCBtZXRob2QKICAgIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgdGhlIHR5cGUgb2YgVVJMLWNoYW5naW5nIG1ldGhvZCB0byB1c2UKICAgICAgYXQgdGhlIGVuZCBvZiBhIHRyYW5zaXRpb24uIEFjY2VwdGVkIHZhbHVlcyBhcmUgJ3JlcGxhY2UnLAogICAgICBmYWxzeSB2YWx1ZXMsIG9yIGFueSBvdGhlciBub24tZmFsc3kgdmFsdWUgKHdoaWNoIGlzCiAgICAgIGludGVycHJldGVkIGFzIGFuIHVwZGF0ZVVSTCB0cmFuc2l0aW9uKS4KICAKICAgIEByZXR1cm4ge1RyYW5zaXRpb259IHRoaXMgdHJhbnNpdGlvbgogICAgQHB1YmxpYwogICovCgogIC8qKgogIAogICAgRmlyZXMgYW4gZXZlbnQgb24gdGhlIGN1cnJlbnQgbGlzdCBvZiByZXNvbHZlZC9yZXNvbHZpbmcKICAgIGhhbmRsZXJzIHdpdGhpbiB0aGlzIHRyYW5zaXRpb24uIFVzZWZ1bCBmb3IgZmlyaW5nIGV2ZW50cwogICAgb24gcm91dGUgaGllcmFyY2hpZXMgdGhhdCBoYXZlbid0IGZ1bGx5IGJlZW4gZW50ZXJlZCB5ZXQuCiAgCiAgICBOb3RlOiBUaGlzIG1ldGhvZCBpcyBhbHNvIGFsaWFzZWQgYXMgYHNlbmRgCiAgCiAgICBAbWV0aG9kIHRyaWdnZXIKICAgIEBwYXJhbSB7Qm9vbGVhbn0gW2lnbm9yZUZhaWx1cmU9ZmFsc2VdIGEgYm9vbGVhbiBzcGVjaWZ5aW5nIHdoZXRoZXIgdW5oYW5kbGVkIGV2ZW50cyB0aHJvdyBhbiBlcnJvcgogICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGZpcmUKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgKiBUaGlzIHByb3BlcnR5IGlzIGEgYFJvdXRlSW5mb2Agb2JqZWN0IHRoYXQgcmVwcmVzZW50cwogICAqIHdoZXJlIHRoZSByb3V0ZXIgaXMgdHJhbnNpdGlvbmluZyB0by4gSXQncyBpbXBvcnRhbnQKICAgKiB0byBub3RlIHRoYXQgYSBgUm91dGVJbmZvYCBpcyBhIGxpbmtlZCBsaXN0IGFuZCB0aGlzCiAgICogcHJvcGVydHkgcmVwcmVzZW50cyB0aGUgbGVhZm1vc3Qgcm91dGUuCiAgICogQHByb3BlcnR5IHtSb3V0ZUluZm98Um91dGVJbmZvV2l0aEF0dHJpYnV0ZXN9IHRvCiAgICogQHB1YmxpYwogICAqLwoKICAvKioKICAgKiBUaGlzIHByb3BlcnR5IGlzIGEgYFJvdXRlSW5mb2Agb2JqZWN0IHRoYXQgcmVwcmVzZW50cwogICAqIHdoZXJlIHRyYW5zaXRpb24gb3JpZ2luYXRlZCBmcm9tLiBJdCdzIGltcG9ydGFudAogICAqIHRvIG5vdGUgdGhhdCBhIGBSb3V0ZUluZm9gIGlzIGEgbGlua2VkIGxpc3QgYW5kIHRoaXMKICAgKiBwcm9wZXJ0eSByZXByZXNlbnRzIHRoZSBoZWFkIG5vZGUgb2YgdGhlIGxpc3QuCiAgICogSW4gdGhlIGNhc2Ugb2YgYW4gaW5pdGlhbCByZW5kZXIsIGBmcm9tYCB3aWxsIGJlIHNldCB0bwogICAqIGBudWxsYC4KICAgKiBAcHJvcGVydHkge1JvdXRlSW5mb1dpdGhBdHRyaWJ1dGVzfSBmcm9tCiAgICogQHB1YmxpYwogICAqLwoKICAvKioKICAgIFRyYW5zaXRpb25zIGFyZSBhYm9ydGVkIGFuZCB0aGVpciBwcm9taXNlcyByZWplY3RlZAogICAgd2hlbiByZWRpcmVjdHMgb2NjdXI7IHRoaXMgbWV0aG9kIHJldHVybnMgYSBwcm9taXNlCiAgICB0aGF0IHdpbGwgZm9sbG93IGFueSByZWRpcmVjdHMgdGhhdCBvY2N1ciBhbmQgZnVsZmlsbAogICAgd2l0aCB0aGUgdmFsdWUgZnVsZmlsbGVkIGJ5IGFueSByZWRpcmVjdGluZyB0cmFuc2l0aW9ucwogICAgdGhhdCBvY2N1ci4KICAKICAgIEBtZXRob2QgZm9sbG93UmVkaXJlY3RzCiAgICBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCBmdWxmaWxscyB3aXRoIHRoZSBzYW1lCiAgICAgIHZhbHVlIHRoYXQgdGhlIGZpbmFsIHJlZGlyZWN0aW5nIHRyYW5zaXRpb24gZnVsZmlsbHMgd2l0aAogICAgQHB1YmxpYwogICovCn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3V0aWxzIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci9lcnJvciIsICJAZW1iZXIvcG9seWZpbGxzIiwgInJvdXRlcl9qcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX293bmVyLCBfZXJyb3IsIF9wb2x5ZmlsbHMsIF9yb3V0ZXJfanMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmV4dHJhY3RSb3V0ZUFyZ3MgPSBleHRyYWN0Um91dGVBcmdzOwogIF9leHBvcnRzLmdldEFjdGl2ZVRhcmdldE5hbWUgPSBnZXRBY3RpdmVUYXJnZXROYW1lOwogIF9leHBvcnRzLnN0YXNoUGFyYW1OYW1lcyA9IHN0YXNoUGFyYW1OYW1lczsKICBfZXhwb3J0cy5jYWxjdWxhdGVDYWNoZUtleSA9IGNhbGN1bGF0ZUNhY2hlS2V5OwogIF9leHBvcnRzLm5vcm1hbGl6ZUNvbnRyb2xsZXJRdWVyeVBhcmFtcyA9IG5vcm1hbGl6ZUNvbnRyb2xsZXJRdWVyeVBhcmFtczsKICBfZXhwb3J0cy5yZXNlbWJsZXNVUkwgPSByZXNlbWJsZXNVUkw7CiAgX2V4cG9ydHMucHJlZml4Um91dGVOYW1lQXJnID0gcHJlZml4Um91dGVOYW1lQXJnOwogIF9leHBvcnRzLnNoYWxsb3dFcXVhbCA9IHNoYWxsb3dFcXVhbDsKICB2YXIgQUxMX1BFUklPRFNfUkVHRVggPSAvXC4vZzsKCiAgZnVuY3Rpb24gZXh0cmFjdFJvdXRlQXJncyhhcmdzKSB7CiAgICBhcmdzID0gYXJncy5zbGljZSgpOwogICAgdmFyIHBvc3NpYmxlUXVlcnlQYXJhbXMgPSBhcmdzW2FyZ3MubGVuZ3RoIC0gMV07CiAgICB2YXIgcXVlcnlQYXJhbXM7CgogICAgaWYgKHBvc3NpYmxlUXVlcnlQYXJhbXMgJiYgcG9zc2libGVRdWVyeVBhcmFtcy5oYXNPd25Qcm9wZXJ0eSgncXVlcnlQYXJhbXMnKSkgewogICAgICBxdWVyeVBhcmFtcyA9IGFyZ3MucG9wKCkucXVlcnlQYXJhbXM7CiAgICB9IGVsc2UgewogICAgICBxdWVyeVBhcmFtcyA9IHt9OwogICAgfQoKICAgIHZhciByb3V0ZU5hbWUgPSBhcmdzLnNoaWZ0KCk7CiAgICByZXR1cm4gewogICAgICByb3V0ZU5hbWU6IHJvdXRlTmFtZSwKICAgICAgbW9kZWxzOiBhcmdzLAogICAgICBxdWVyeVBhcmFtczogcXVlcnlQYXJhbXMKICAgIH07CiAgfQoKICBmdW5jdGlvbiBnZXRBY3RpdmVUYXJnZXROYW1lKHJvdXRlcikgewogICAgdmFyIHJvdXRlSW5mb3MgPSByb3V0ZXIuYWN0aXZlVHJhbnNpdGlvbiA/IHJvdXRlci5hY3RpdmVUcmFuc2l0aW9uW19yb3V0ZXJfanMuU1RBVEVfU1lNQk9MXS5yb3V0ZUluZm9zIDogcm91dGVyLnN0YXRlLnJvdXRlSW5mb3M7CiAgICByZXR1cm4gcm91dGVJbmZvc1tyb3V0ZUluZm9zLmxlbmd0aCAtIDFdLm5hbWU7CiAgfQoKICBmdW5jdGlvbiBzdGFzaFBhcmFtTmFtZXMocm91dGVyLCByb3V0ZUluZm9zKSB7CiAgICBpZiAocm91dGVJbmZvc1snX25hbWVzU3Rhc2hlZCddKSB7CiAgICAgIHJldHVybjsKICAgIH0gLy8gVGhpcyBoZWxwZXIgZXhpc3RzIGJlY2F1c2Ugcm91dGVyLmpzL3JvdXRlLXJlY29nbml6ZXIuanMgYXdrd2FyZGx5CiAgICAvLyBrZWVwcyBzZXBhcmF0ZSBhIHJvdXRlSW5mbydzIGxpc3Qgb2YgcGFyYW1ldGVyIG5hbWVzIGRlcGVuZGluZwogICAgLy8gb24gd2hldGhlciBhIFVSTCB0cmFuc2l0aW9uIG9yIG5hbWVkIHRyYW5zaXRpb24gaXMgaGFwcGVuaW5nLgogICAgLy8gSG9wZWZ1bGx5IHdlIGNhbiByZW1vdmUgdGhpcyBpbiB0aGUgZnV0dXJlLgoKCiAgICB2YXIgdGFyZ2V0Um91dGVOYW1lID0gcm91dGVJbmZvc1tyb3V0ZUluZm9zLmxlbmd0aCAtIDFdLm5hbWU7CgogICAgdmFyIHJlY29nSGFuZGxlcnMgPSByb3V0ZXIuX3JvdXRlck1pY3JvbGliLnJlY29nbml6ZXIuaGFuZGxlcnNGb3IodGFyZ2V0Um91dGVOYW1lKTsKCiAgICB2YXIgZHluYW1pY1BhcmVudDsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvdXRlSW5mb3MubGVuZ3RoOyArK2kpIHsKICAgICAgdmFyIHJvdXRlSW5mbyA9IHJvdXRlSW5mb3NbaV07CiAgICAgIHZhciBuYW1lcyA9IHJlY29nSGFuZGxlcnNbaV0ubmFtZXM7CgogICAgICBpZiAobmFtZXMubGVuZ3RoKSB7CiAgICAgICAgZHluYW1pY1BhcmVudCA9IHJvdXRlSW5mbzsKICAgICAgfQoKICAgICAgcm91dGVJbmZvWydfbmFtZXMnXSA9IG5hbWVzOwogICAgICB2YXIgcm91dGUgPSByb3V0ZUluZm8ucm91dGU7CgogICAgICByb3V0ZS5fc3Rhc2hOYW1lcyhyb3V0ZUluZm8sIGR5bmFtaWNQYXJlbnQpOwogICAgfQoKICAgIHJvdXRlSW5mb3NbJ19uYW1lc1N0YXNoZWQnXSA9IHRydWU7CiAgfQoKICBmdW5jdGlvbiBfY2FsY3VsYXRlQ2FjaGVWYWx1ZVByZWZpeChwcmVmaXgsIHBhcnQpIHsKICAgIC8vIGNhbGN1bGF0ZXMgdGhlIGRvdCBzZXBhcmF0ZWQgc2VjdGlvbnMgZnJvbSBwcmVmaXggdGhhdCBhcmUgYWxzbwogICAgLy8gYXQgdGhlIHN0YXJ0IG9mIHBhcnQgLSB3aGljaCBnaXZlcyB1cyB0aGUgcm91dGUgbmFtZQogICAgLy8gZ2l2ZW4gOiBwcmVmaXggPSBzaXRlLmFydGljbGUuY29tbWVudHMsIHBhcnQgPSBzaXRlLmFydGljbGUuaWQKICAgIC8vICAgICAgLSByZXR1cm5zOiBzaXRlLmFydGljbGUgKHVzZSBnZXQodmFsdWVzW3NpdGUuYXJ0aWNsZV0sICdpZCcpIHRvIGdldCB0aGUgZHluYW1pYyBwYXJ0IC0gdXNlZCBiZWxvdykKICAgIC8vIGdpdmVuIDogcHJlZml4ID0gc2l0ZS5hcnRpY2xlLCBwYXJ0ID0gc2l0ZS5hcnRpY2xlLmlkCiAgICAvLyAgICAgIC0gcmV0dXJuczogc2l0ZS5hcnRpY2xlLiAodXNlIGdldCh2YWx1ZXNbc2l0ZS5hcnRpY2xlXSwgJ2lkJykgdG8gZ2V0IHRoZSBkeW5hbWljIHBhcnQgLSB1c2VkIGJlbG93KQogICAgdmFyIHByZWZpeFBhcnRzID0gcHJlZml4LnNwbGl0KCcuJyk7CiAgICB2YXIgY3VyclByZWZpeCA9ICcnOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJlZml4UGFydHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGN1cnJQYXJ0ID0gcHJlZml4UGFydHMuc2xpY2UoMCwgaSArIDEpLmpvaW4oJy4nKTsKCiAgICAgIGlmIChwYXJ0LmluZGV4T2YoY3VyclBhcnQpICE9PSAwKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KCiAgICAgIGN1cnJQcmVmaXggPSBjdXJyUGFydDsKICAgIH0KCiAgICByZXR1cm4gY3VyclByZWZpeDsKICB9CiAgLyoKICAgIFN0b2xlbiBmcm9tIENvbnRyb2xsZXIKICAqLwoKCiAgZnVuY3Rpb24gY2FsY3VsYXRlQ2FjaGVLZXkocHJlZml4LCBwYXJ0cywgdmFsdWVzKSB7CiAgICBpZiAocGFydHMgPT09IHZvaWQgMCkgewogICAgICBwYXJ0cyA9IFtdOwogICAgfQoKICAgIHZhciBzdWZmaXhlcyA9ICcnOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyArK2kpIHsKICAgICAgdmFyIHBhcnQgPSBwYXJ0c1tpXTsKCiAgICAgIHZhciBjYWNoZVZhbHVlUHJlZml4ID0gX2NhbGN1bGF0ZUNhY2hlVmFsdWVQcmVmaXgocHJlZml4LCBwYXJ0KTsKCiAgICAgIHZhciB2YWx1ZSA9IHZvaWQgMDsKCiAgICAgIGlmICh2YWx1ZXMpIHsKICAgICAgICBpZiAoY2FjaGVWYWx1ZVByZWZpeCAmJiBjYWNoZVZhbHVlUHJlZml4IGluIHZhbHVlcykgewogICAgICAgICAgdmFyIHBhcnRSZW1vdmVkUHJlZml4ID0gcGFydC5pbmRleE9mKGNhY2hlVmFsdWVQcmVmaXgpID09PSAwID8gcGFydC5zdWJzdHIoY2FjaGVWYWx1ZVByZWZpeC5sZW5ndGggKyAxKSA6IHBhcnQ7CiAgICAgICAgICB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KSh2YWx1ZXNbY2FjaGVWYWx1ZVByZWZpeF0sIHBhcnRSZW1vdmVkUHJlZml4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFsdWUgPSAoMCwgX21ldGFsLmdldCkodmFsdWVzLCBwYXJ0KTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHN1ZmZpeGVzICs9ICI6OiIgKyBwYXJ0ICsgIjoiICsgdmFsdWU7CiAgICB9CgogICAgcmV0dXJuIHByZWZpeCArIHN1ZmZpeGVzLnJlcGxhY2UoQUxMX1BFUklPRFNfUkVHRVgsICctJyk7CiAgfQogIC8qCiAgICBDb250cm9sbGVyLWRlZmluZWQgcXVlcnkgcGFyYW1ldGVycyBjYW4gY29tZSBpbiB0aHJlZSBzaGFwZXM6CiAgCiAgICBBcnJheQogICAgICBxdWVyeVBhcmFtczogWydmb28nLCAnYmFyJ10KICAgIEFycmF5IG9mIHNpbXBsZSBvYmplY3RzIHdoZXJlIHZhbHVlIGlzIGFuIGFsaWFzCiAgICAgIHF1ZXJ5UGFyYW1zOiBbCiAgICAgICAgewogICAgICAgICAgJ2Zvbyc6ICdyZW5hbWVfZm9vX3RvX3RoaXMnCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAnYmFyJzogJ2NhbGxfYmFyX3RoaXNfaW5zdGVhZCcKICAgICAgICB9CiAgICAgIF0KICAgIEFycmF5IG9mIGZ1bGx5IGRlZmluZWQgb2JqZWN0cwogICAgICBxdWVyeVBhcmFtczogWwogICAgICAgIHsKICAgICAgICAgICdmb28nOiB7CiAgICAgICAgICAgIGFzOiAncmVuYW1lX2Zvb190b190aGlzJwogICAgICAgICAgfSwKICAgICAgICB9CiAgICAgICAgewogICAgICAgICAgJ2Jhcic6IHsKICAgICAgICAgICAgYXM6ICdjYWxsX2Jhcl90aGlzX2luc3RlYWQnLAogICAgICAgICAgICBzY29wZTogJ2NvbnRyb2xsZXInCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICBdCiAgCiAgICBUaGlzIGhlbHBlciBub3JtYWxpemVzIGFsbCB0aHJlZSBwb3NzaWJsZSBzdHlsZXMgaW50byB0aGUKICAgICdBcnJheSBvZiBmdWxseSBkZWZpbmVkIG9iamVjdHMnIHN0eWxlLgogICovCgoKICBmdW5jdGlvbiBub3JtYWxpemVDb250cm9sbGVyUXVlcnlQYXJhbXMocXVlcnlQYXJhbXMpIHsKICAgIHZhciBxcE1hcCA9IHt9OwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcXVlcnlQYXJhbXMubGVuZ3RoOyArK2kpIHsKICAgICAgYWNjdW11bGF0ZVF1ZXJ5UGFyYW1EZXNjcmlwdG9ycyhxdWVyeVBhcmFtc1tpXSwgcXBNYXApOwogICAgfQoKICAgIHJldHVybiBxcE1hcDsKICB9CgogIGZ1bmN0aW9uIGFjY3VtdWxhdGVRdWVyeVBhcmFtRGVzY3JpcHRvcnMoX2Rlc2MsIGFjY3VtKSB7CiAgICB2YXIgZGVzYyA9IF9kZXNjOwogICAgdmFyIHRtcDsKCiAgICBpZiAodHlwZW9mIGRlc2MgPT09ICdzdHJpbmcnKSB7CiAgICAgIHRtcCA9IHt9OwogICAgICB0bXBbZGVzY10gPSB7CiAgICAgICAgYXM6IG51bGwKICAgICAgfTsKICAgICAgZGVzYyA9IHRtcDsKICAgIH0KCiAgICBmb3IgKHZhciBrZXkgaW4gZGVzYykgewogICAgICBpZiAoIWRlc2MuaGFzT3duUHJvcGVydHkoa2V5KSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIHNpbmdsZURlc2MgPSBkZXNjW2tleV07CgogICAgICBpZiAodHlwZW9mIHNpbmdsZURlc2MgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgc2luZ2xlRGVzYyA9IHsKICAgICAgICAgIGFzOiBzaW5nbGVEZXNjCiAgICAgICAgfTsKICAgICAgfQoKICAgICAgdG1wID0gYWNjdW1ba2V5XSB8fCB7CiAgICAgICAgYXM6IG51bGwsCiAgICAgICAgc2NvcGU6ICdtb2RlbCcKICAgICAgfTsKICAgICAgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh0bXAsIHNpbmdsZURlc2MpOwogICAgICBhY2N1bVtrZXldID0gdG1wOwogICAgfQogIH0KICAvKgogICAgQ2hlY2sgaWYgYSByb3V0ZU5hbWUgcmVzZW1ibGVzIGEgdXJsIGluc3RlYWQKICAKICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIHJlc2VtYmxlc1VSTChzdHIpIHsKICAgIHJldHVybiB0eXBlb2Ygc3RyID09PSAnc3RyaW5nJyAmJiAoc3RyID09PSAnJyB8fCBzdHJbMF0gPT09ICcvJyk7CiAgfQogIC8qCiAgICBSZXR1cm5zIGFuIGFyZ3VtZW50cyBhcnJheSB3aGVyZSB0aGUgcm91dGUgbmFtZSBhcmcgaXMgcHJlZml4ZWQgYmFzZWQgb24gdGhlIG1vdW50IHBvaW50CiAgCiAgICBAcHJpdmF0ZQogICovCgoKICBmdW5jdGlvbiBwcmVmaXhSb3V0ZU5hbWVBcmcocm91dGUsIGFyZ3MpIHsKICAgIHZhciByb3V0ZU5hbWUgPSBhcmdzWzBdOwogICAgdmFyIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikocm91dGUpOwogICAgdmFyIHByZWZpeCA9IG93bmVyLm1vdW50UG9pbnQ7IC8vIG9ubHkgYWx0ZXIgdGhlIHJvdXRlTmFtZSBpZiBpdCdzIGFjdHVhbGx5IHJlZmVyZW5jaW5nIGEgcm91dGUuCgogICAgaWYgKG93bmVyLnJvdXRhYmxlICYmIHR5cGVvZiByb3V0ZU5hbWUgPT09ICdzdHJpbmcnKSB7CiAgICAgIGlmIChyZXNlbWJsZXNVUkwocm91dGVOYW1lKSkgewogICAgICAgIHRocm93IG5ldyBfZXJyb3IuZGVmYXVsdCgnUHJvZ3JhbW1hdGljIHRyYW5zaXRpb25zIGJ5IFVSTCBjYW5ub3QgYmUgdXNlZCB3aXRoaW4gYW4gRW5naW5lLiBQbGVhc2UgdXNlIHRoZSByb3V0ZSBuYW1lIGluc3RlYWQuJyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcm91dGVOYW1lID0gcHJlZml4ICsgIi4iICsgcm91dGVOYW1lOwogICAgICAgIGFyZ3NbMF0gPSByb3V0ZU5hbWU7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gYXJnczsKICB9CgogIGZ1bmN0aW9uIHNoYWxsb3dFcXVhbChhLCBiKSB7CiAgICB2YXIgazsKICAgIHZhciBhQ291bnQgPSAwOwogICAgdmFyIGJDb3VudCA9IDA7CgogICAgZm9yIChrIGluIGEpIHsKICAgICAgaWYgKGEuaGFzT3duUHJvcGVydHkoaykpIHsKICAgICAgICBpZiAoYVtrXSAhPT0gYltrXSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgYUNvdW50Kys7CiAgICAgIH0KICAgIH0KCiAgICBmb3IgKGsgaW4gYikgewogICAgICBpZiAoYi5oYXNPd25Qcm9wZXJ0eShrKSkgewogICAgICAgIGJDb3VudCsrOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGFDb3VudCA9PT0gYkNvdW50OwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vb2JqZWN0IiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9yZWdpc3RyeV9wcm94eSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvY29udGFpbmVyX3Byb3h5IiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL2NvcHkiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvY29tcGFyZSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9pcy1lcXVhbCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvYXJyYXkiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2NvbXBhcmFibGUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL25hbWVzcGFjZSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vYXJyYXlfcHJveHkiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL29iamVjdF9wcm94eSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vY29yZV9vYmplY3QiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2FjdGlvbl9oYW5kbGVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9jb3B5YWJsZSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvZW51bWVyYWJsZSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvLXByb3h5IiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9vYnNlcnZhYmxlIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9tdXRhYmxlX2VudW1lcmFibGUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL3RhcmdldF9hY3Rpb25fc3VwcG9ydCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvZXZlbnRlZCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvcHJvbWlzZV9wcm94eSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9leHQvcnN2cCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi90eXBlLW9mIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL2V4dC9mdW5jdGlvbiJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9vYmplY3QsIF9yZWdpc3RyeV9wcm94eSwgX2NvbnRhaW5lcl9wcm94eSwgX2NvcHksIF9jb21wYXJlLCBfaXNFcXVhbCwgX2FycmF5LCBfY29tcGFyYWJsZSwgX25hbWVzcGFjZSwgX2FycmF5X3Byb3h5LCBfb2JqZWN0X3Byb3h5LCBfY29yZV9vYmplY3QsIF9hY3Rpb25faGFuZGxlciwgX2NvcHlhYmxlLCBfZW51bWVyYWJsZSwgX3Byb3h5LCBfb2JzZXJ2YWJsZSwgX211dGFibGVfZW51bWVyYWJsZSwgX3RhcmdldF9hY3Rpb25fc3VwcG9ydCwgX2V2ZW50ZWQsIF9wcm9taXNlX3Byb3h5LCBfcnN2cCwgX3R5cGVPZiwgX2Z1bmN0aW9uKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJPYmplY3QiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfb2JqZWN0LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiRnJhbWV3b3JrT2JqZWN0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX29iamVjdC5GcmFtZXdvcmtPYmplY3Q7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiUmVnaXN0cnlQcm94eU1peGluIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZ2lzdHJ5X3Byb3h5LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQ29udGFpbmVyUHJveHlNaXhpbiIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb250YWluZXJfcHJveHkuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJjb3B5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvcHkuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJjb21wYXJlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXBhcmUuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJpc0VxdWFsIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2lzRXF1YWwuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJBcnJheSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9hcnJheS5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIk5hdGl2ZUFycmF5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2FycmF5Lk5hdGl2ZUFycmF5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkEiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXJyYXkuQTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJNdXRhYmxlQXJyYXkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXJyYXkuTXV0YWJsZUFycmF5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInJlbW92ZUF0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2FycmF5LnJlbW92ZUF0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInVuaXFCeSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9hcnJheS51bmlxQnk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiaXNBcnJheSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9hcnJheS5pc0FycmF5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkNvbXBhcmFibGUiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcGFyYWJsZS5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIk5hbWVzcGFjZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9uYW1lc3BhY2UuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJBcnJheVByb3h5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2FycmF5X3Byb3h5LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiT2JqZWN0UHJveHkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfb2JqZWN0X3Byb3h5LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQ29yZU9iamVjdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb3JlX29iamVjdC5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInNldEZyYW1ld29ya0NsYXNzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvcmVfb2JqZWN0LnNldEZyYW1ld29ya0NsYXNzOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkFjdGlvbkhhbmRsZXIiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYWN0aW9uX2hhbmRsZXIuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJDb3B5YWJsZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb3B5YWJsZS5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkVudW1lcmFibGUiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZW51bWVyYWJsZS5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9Qcm94eU1peGluIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3Byb3h5LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX2NvbnRlbnRGb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJveHkuY29udGVudEZvcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJPYnNlcnZhYmxlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX29ic2VydmFibGUuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJNdXRhYmxlRW51bWVyYWJsZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9tdXRhYmxlX2VudW1lcmFibGUuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJUYXJnZXRBY3Rpb25TdXBwb3J0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3RhcmdldF9hY3Rpb25fc3VwcG9ydC5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkV2ZW50ZWQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZXZlbnRlZC5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIlByb21pc2VQcm94eU1peGluIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3Byb21pc2VfcHJveHkuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJSU1ZQIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JzdnAuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJvbmVycm9yRGVmYXVsdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9yc3ZwLm9uZXJyb3JEZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInR5cGVPZiIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF90eXBlT2YudHlwZU9mOwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9jb21wYXJlIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL3R5cGUtb2YiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2NvbXBhcmFibGUiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdHlwZU9mLCBfY29tcGFyYWJsZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IGNvbXBhcmU7CiAgdmFyIFRZUEVfT1JERVIgPSB7CiAgICB1bmRlZmluZWQ6IDAsCiAgICBudWxsOiAxLAogICAgYm9vbGVhbjogMiwKICAgIG51bWJlcjogMywKICAgIHN0cmluZzogNCwKICAgIGFycmF5OiA1LAogICAgb2JqZWN0OiA2LAogICAgaW5zdGFuY2U6IDcsCiAgICBmdW5jdGlvbjogOCwKICAgIGNsYXNzOiA5LAogICAgZGF0ZTogMTAKICB9OyAvLwogIC8vIHRoZSBzcGFjZXNoaXAgb3BlcmF0b3IKICAvLwogIC8vICAgICAgICAgICAgICAgICAgICAgIGAuIF9fXwogIC8vICAgICAgICAgICAgICAgICAgICAgX18sJyBfX2AuICAgICAgICAgICAgICAgIF8uLi0tLS0uLi4uX19fXwogIC8vICAgICAgICAgX18uLi4tLS4nYGA7LiAgICwuICAgO2BgLS0uLl9fICAgICAuJyAgICAsLS5fICAgIF8uLScKICAvLyAgIF8uLi0nJy0tLS0tLS0nICAgYCcgICBgJyAgIGAnICAgICBPIGBgLScnLl8gICAoLDsnKSBfLCcKICAvLyAsJ19fX19fX19fX19fX19fX18gICAgICAgICAgICAgICAgICAgICAgICAgIFxgLS5fYC0nLCcKICAvLyAgYC5fICAgICAgICAgICAgICBgYGBgYGBgYGBgYC0tLS0tLS4uLl9fXyAgICctLi5fJy06CiAgLy8gICAgIGBgYC0tLi5fICAgICAgLC4gICAgICAgICAgICAgICAgICAgICBgYGBgLS0uLi5fX1wtLgogIC8vICAgICAgICAgICAgIGAuLS0uIGAtYCAiSU5GSU5JVFkgSVMgTEVTUyAgICAgX19fXyAgICB8ICB8YAogIC8vICAgICAgICAgICAgICAgYC4gYC4gICBUSEFOIEJFWU9ORCIgICAgICAgICwnYGBgYGAuICA7ICA7YAogIC8vICAgICAgICAgICAgICAgICBgLl9gLiAgICAgICAgX19fX19fX19fXyAgIGAuICAgICAgXCdfXy9gCiAgLy8gICAgICAgICAgICAgICAgICAgIGAtOi5fX19fXy9fX19fX18vX19fL19fX19gLiAgICAgXCAgYAogIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgIGAuXyAgICBgLiAgICBcCiAgLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGAuX19fX19fX19fYC0uICAgYC4gICBgLl9fXwogIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNTdCAgYC0tLS0tLSdgCgogIGZ1bmN0aW9uIHNwYWNlc2hpcChhLCBiKSB7CiAgICB2YXIgZGlmZiA9IGEgLSBiOwogICAgcmV0dXJuIChkaWZmID4gMCkgLSAoZGlmZiA8IDApOwogIH0KICAvKioKICAgQG1vZHVsZSBAZW1iZXIvdXRpbHMKICAqLwoKICAvKioKICAgQ29tcGFyZXMgdHdvIGphdmFzY3JpcHQgdmFsdWVzIGFuZCByZXR1cm5zOgogIAogICAgLSAtMSBpZiB0aGUgZmlyc3QgaXMgc21hbGxlciB0aGFuIHRoZSBzZWNvbmQsCiAgICAtIDAgaWYgYm90aCBhcmUgZXF1YWwsCiAgICAtIDEgaWYgdGhlIGZpcnN0IGlzIGdyZWF0ZXIgdGhhbiB0aGUgc2Vjb25kLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgY29tcGFyZSB9IGZyb20gJ0BlbWJlci91dGlscyc7CiAgCiAgICBjb21wYXJlKCdoZWxsbycsICdoZWxsbycpOyAgLy8gMAogICAgY29tcGFyZSgnYWJjJywgJ2RmZycpOyAgICAgIC8vIC0xCiAgICBjb21wYXJlKDIsIDEpOyAgICAgICAgICAgICAgLy8gMQogICAgYGBgCiAgCiAgIElmIHRoZSB0eXBlcyBvZiB0aGUgdHdvIG9iamVjdHMgYXJlIGRpZmZlcmVudCBwcmVjZWRlbmNlIG9jY3VycyBpbiB0aGUKICAgZm9sbG93aW5nIG9yZGVyLCB3aXRoIHR5cGVzIGVhcmxpZXIgaW4gdGhlIGxpc3QgY29uc2lkZXJlZCBgPGAgdHlwZXMKICAgbGF0ZXIgaW4gdGhlIGxpc3Q6CiAgCiAgICAtIHVuZGVmaW5lZAogICAgLSBudWxsCiAgICAtIGJvb2xlYW4KICAgIC0gbnVtYmVyCiAgICAtIHN0cmluZwogICAgLSBhcnJheQogICAgLSBvYmplY3QKICAgIC0gaW5zdGFuY2UKICAgIC0gZnVuY3Rpb24KICAgIC0gY2xhc3MKICAgIC0gZGF0ZQogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgY29tcGFyZSB9IGZyb20gJ0BlbWJlci91dGlscyc7CiAgCiAgICBjb21wYXJlKCdoZWxsbycsIDUwKTsgICAgICAgLy8gMQogICAgY29tcGFyZSg1MCwgJ2hlbGxvJyk7ICAgICAgIC8vIC0xCiAgICBgYGAKICAKICAgQG1ldGhvZCBjb21wYXJlCiAgIEBmb3IgQGVtYmVyL3V0aWxzCiAgIEBzdGF0aWMKICAgQHBhcmFtIHtPYmplY3R9IHYgRmlyc3QgdmFsdWUgdG8gY29tcGFyZQogICBAcGFyYW0ge09iamVjdH0gdyBTZWNvbmQgdmFsdWUgdG8gY29tcGFyZQogICBAcmV0dXJuIHtOdW1iZXJ9IC0xIGlmIHYgPCB3LCAwIGlmIHYgPSB3IGFuZCAxIGlmIHYgPiB3LgogICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGNvbXBhcmUodiwgdykgewogICAgaWYgKHYgPT09IHcpIHsKICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgdmFyIHR5cGUxID0gKDAsIF90eXBlT2YudHlwZU9mKSh2KTsKICAgIHZhciB0eXBlMiA9ICgwLCBfdHlwZU9mLnR5cGVPZikodyk7CgogICAgaWYgKHR5cGUxID09PSAnaW5zdGFuY2UnICYmIF9jb21wYXJhYmxlLmRlZmF1bHQuZGV0ZWN0KHYpICYmIHYuY29uc3RydWN0b3IuY29tcGFyZSkgewogICAgICByZXR1cm4gdi5jb25zdHJ1Y3Rvci5jb21wYXJlKHYsIHcpOwogICAgfQoKICAgIGlmICh0eXBlMiA9PT0gJ2luc3RhbmNlJyAmJiBfY29tcGFyYWJsZS5kZWZhdWx0LmRldGVjdCh3KSAmJiB3LmNvbnN0cnVjdG9yLmNvbXBhcmUpIHsKICAgICAgcmV0dXJuIHcuY29uc3RydWN0b3IuY29tcGFyZSh3LCB2KSAqIC0xOwogICAgfQoKICAgIHZhciByZXMgPSBzcGFjZXNoaXAoVFlQRV9PUkRFUlt0eXBlMV0sIFRZUEVfT1JERVJbdHlwZTJdKTsKCiAgICBpZiAocmVzICE9PSAwKSB7CiAgICAgIHJldHVybiByZXM7CiAgICB9IC8vIHR5cGVzIGFyZSBlcXVhbCAtIHNvIHdlIGhhdmUgdG8gY2hlY2sgdmFsdWVzIG5vdwoKCiAgICBzd2l0Y2ggKHR5cGUxKSB7CiAgICAgIGNhc2UgJ2Jvb2xlYW4nOgogICAgICBjYXNlICdudW1iZXInOgogICAgICAgIHJldHVybiBzcGFjZXNoaXAodiwgdyk7CgogICAgICBjYXNlICdzdHJpbmcnOgogICAgICAgIHJldHVybiBzcGFjZXNoaXAodi5sb2NhbGVDb21wYXJlKHcpLCAwKTsKCiAgICAgIGNhc2UgJ2FycmF5JzoKICAgICAgICB7CiAgICAgICAgICB2YXIgdkxlbiA9IHYubGVuZ3RoOwogICAgICAgICAgdmFyIHdMZW4gPSB3Lmxlbmd0aDsKICAgICAgICAgIHZhciBsZW4gPSBNYXRoLm1pbih2TGVuLCB3TGVuKTsKCiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgICAgICAgIHZhciByID0gY29tcGFyZSh2W2ldLCB3W2ldKTsKCiAgICAgICAgICAgIGlmIChyICE9PSAwKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHI7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gLy8gYWxsIGVsZW1lbnRzIGFyZSBlcXVhbCBub3cKICAgICAgICAgIC8vIHNob3J0ZXIgYXJyYXkgc2hvdWxkIGJlIG9yZGVyZWQgZmlyc3QKCgogICAgICAgICAgcmV0dXJuIHNwYWNlc2hpcCh2TGVuLCB3TGVuKTsKICAgICAgICB9CgogICAgICBjYXNlICdpbnN0YW5jZSc6CiAgICAgICAgaWYgKF9jb21wYXJhYmxlLmRlZmF1bHQuZGV0ZWN0KHYpKSB7CiAgICAgICAgICByZXR1cm4gdi5jb21wYXJlKHYsIHcpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIDA7CgogICAgICBjYXNlICdkYXRlJzoKICAgICAgICByZXR1cm4gc3BhY2VzaGlwKHYuZ2V0VGltZSgpLCB3LmdldFRpbWUoKSk7CgogICAgICBkZWZhdWx0OgogICAgICAgIHJldHVybiAwOwogICAgfQogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvY29weSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL29iamVjdCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvY29weWFibGUiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVidWcsIF9vYmplY3QsIF9jb3B5YWJsZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IGNvcHk7CgogIC8qKgogICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwogIGZ1bmN0aW9uIF9jb3B5KG9iaiwgZGVlcCwgc2VlbiwgY29waWVzKSB7CiAgICAvLyBwcmltaXRpdmUgZGF0YSB0eXBlcyBhcmUgaW1tdXRhYmxlLCBqdXN0IHJldHVybiB0aGVtLgogICAgaWYgKHR5cGVvZiBvYmogIT09ICdvYmplY3QnIHx8IG9iaiA9PT0gbnVsbCkgewogICAgICByZXR1cm4gb2JqOwogICAgfQoKICAgIHZhciByZXQsIGxvYzsgLy8gYXZvaWQgY3ljbGljYWwgbG9vcHMKCiAgICBpZiAoZGVlcCAmJiAobG9jID0gc2Vlbi5pbmRleE9mKG9iaikpID49IDApIHsKICAgICAgcmV0dXJuIGNvcGllc1tsb2NdOwogICAgfQoKICAgIGlmIChkZWVwKSB7CiAgICAgIHNlZW4ucHVzaChvYmopOwogICAgfSAvLyBJTVBPUlRBTlQ6IHRoaXMgc3BlY2lmaWMgdGVzdCB3aWxsIGRldGVjdCBhIG5hdGl2ZSBhcnJheSBvbmx5LiBBbnkgb3RoZXIKICAgIC8vIG9iamVjdCB3aWxsIG5lZWQgdG8gaW1wbGVtZW50IENvcHlhYmxlLgoKCiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7CiAgICAgIHJldCA9IG9iai5zbGljZSgpOwoKICAgICAgaWYgKGRlZXApIHsKICAgICAgICBjb3BpZXMucHVzaChyZXQpOwogICAgICAgIGxvYyA9IHJldC5sZW5ndGg7CgogICAgICAgIHdoaWxlICgtLWxvYyA+PSAwKSB7CiAgICAgICAgICByZXRbbG9jXSA9IF9jb3B5KHJldFtsb2NdLCBkZWVwLCBzZWVuLCBjb3BpZXMpOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIGlmIChfY29weWFibGUuZGVmYXVsdC5kZXRlY3Qob2JqKSkgewogICAgICByZXQgPSBvYmouY29weShkZWVwLCBzZWVuLCBjb3BpZXMpOwoKICAgICAgaWYgKGRlZXApIHsKICAgICAgICBjb3BpZXMucHVzaChyZXQpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKG9iaiBpbnN0YW5jZW9mIERhdGUpIHsKICAgICAgcmV0ID0gbmV3IERhdGUob2JqLmdldFRpbWUoKSk7CgogICAgICBpZiAoZGVlcCkgewogICAgICAgIGNvcGllcy5wdXNoKHJldCk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIChmYWxzZSAmJiAhKCEob2JqIGluc3RhbmNlb2YgX29iamVjdC5kZWZhdWx0KSB8fCBfY29weWFibGUuZGVmYXVsdC5kZXRlY3Qob2JqKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdDYW5ub3QgY2xvbmUgYW4gRW1iZXJPYmplY3QgdGhhdCBkb2VzIG5vdCBpbXBsZW1lbnQgQ29weWFibGUnLCAhKG9iaiBpbnN0YW5jZW9mIF9vYmplY3QuZGVmYXVsdCkgfHwgX2NvcHlhYmxlLmRlZmF1bHQuZGV0ZWN0KG9iaikpKTsKICAgICAgcmV0ID0ge307CgogICAgICBpZiAoZGVlcCkgewogICAgICAgIGNvcGllcy5wdXNoKHJldCk7CiAgICAgIH0KCiAgICAgIHZhciBrZXk7CgogICAgICBmb3IgKGtleSBpbiBvYmopIHsKICAgICAgICAvLyBzdXBwb3J0IE51bGwgcHJvdG90eXBlCiAgICAgICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9IC8vIFByZXZlbnRzIGJyb3dzZXJzIHRoYXQgZG9uJ3QgcmVzcGVjdCBub24tZW51bWVyYWJpbGl0eSBmcm9tCiAgICAgICAgLy8gY29weWluZyBpbnRlcm5hbCBFbWJlciBwcm9wZXJ0aWVzCgoKICAgICAgICBpZiAoa2V5LnN1YnN0cmluZygwLCAyKSA9PT0gJ19fJykgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICByZXRba2V5XSA9IGRlZXAgPyBfY29weShvYmpba2V5XSwgZGVlcCwgc2VlbiwgY29waWVzKSA6IG9ialtrZXldOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJldDsKICB9CiAgLyoqCiAgICBDcmVhdGVzIGEgc2hhbGxvdyBjb3B5IG9mIHRoZSBwYXNzZWQgb2JqZWN0LiBBIGRlZXAgY29weSBvZiB0aGUgb2JqZWN0IGlzCiAgICByZXR1cm5lZCBpZiB0aGUgb3B0aW9uYWwgYGRlZXBgIGFyZ3VtZW50IGlzIGB0cnVlYC4KICAKICAgIElmIHRoZSBwYXNzZWQgb2JqZWN0IGltcGxlbWVudHMgdGhlIGBDb3B5YWJsZWAgaW50ZXJmYWNlLCB0aGVuIHRoaXMKICAgIGZ1bmN0aW9uIHdpbGwgZGVsZWdhdGUgdG8gdGhlIG9iamVjdCdzIGBjb3B5KClgIG1ldGhvZCBhbmQgcmV0dXJuIHRoZQogICAgcmVzdWx0LiBTZWUgYENvcHlhYmxlYCBmb3IgZnVydGhlciBkZXRhaWxzLgogIAogICAgRm9yIHByaW1pdGl2ZSB2YWx1ZXMgKHdoaWNoIGFyZSBpbW11dGFibGUgaW4gSmF2YVNjcmlwdCksIHRoZSBwYXNzZWQgb2JqZWN0CiAgICBpcyBzaW1wbHkgcmV0dXJuZWQuCiAgCiAgICBAbWV0aG9kIGNvcHkKICAgIEBkZXByZWNhdGVkIFVzZSAnZW1iZXItY29weScgYWRkb24gaW5zdGVhZAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2ludGVybmFscwogICAgQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIGNsb25lCiAgICBAcGFyYW0ge0Jvb2xlYW59IFtkZWVwPWZhbHNlXSBJZiB0cnVlLCBhIGRlZXAgY29weSBvZiB0aGUgb2JqZWN0IGlzIG1hZGUuCiAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSBjb3BpZWQgb2JqZWN0CiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGNvcHkob2JqLCBkZWVwKSB7CiAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdVc2UgZW1iZXItY29weSBhZGRvbiBpbnN0ZWFkIG9mIGNvcHkgbWV0aG9kIGFuZCBDb3B5YWJsZSBtaXhpbi4nLCBmYWxzZSwgewogICAgICBpZDogJ2VtYmVyLXJ1bnRpbWUuZGVwcmVjYXRlLWNvcHktY29weWFibGUnLAogICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueC8jdG9jX2VtYmVyLXJ1bnRpbWUtZGVwcmVjYXRlLWNvcHktY29weWFibGUnCiAgICB9KSk7IC8vIGZhc3QgcGF0aHMKCiAgICBpZiAoJ29iamVjdCcgIT09IHR5cGVvZiBvYmogfHwgb2JqID09PSBudWxsKSB7CiAgICAgIHJldHVybiBvYmo7IC8vIGNhbid0IGNvcHkgcHJpbWl0aXZlcwogICAgfQoKICAgIGlmICghQXJyYXkuaXNBcnJheShvYmopICYmIF9jb3B5YWJsZS5kZWZhdWx0LmRldGVjdChvYmopKSB7CiAgICAgIHJldHVybiBvYmouY29weShkZWVwKTsKICAgIH0KCiAgICByZXR1cm4gX2NvcHkob2JqLCBkZWVwLCBkZWVwID8gW10gOiBudWxsLCBkZWVwID8gW10gOiBudWxsKTsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL2V4dC9mdW5jdGlvbiIsIFsiQGVtYmVyLy1pbnRlcm5hbHMvZW52aXJvbm1lbnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIl0sIGZ1bmN0aW9uIChfZW52aXJvbm1lbnQsIF9tZXRhbCwgX2RlYnVnLCBfZGVwcmVjYXRlZEZlYXR1cmVzKSB7CiAgInVzZSBzdHJpY3QiOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5GVU5DVElPTl9QUk9UT1RZUEVfRVhURU5TSU9OUyAmJiBfZW52aXJvbm1lbnQuRU5WLkVYVEVORF9QUk9UT1RZUEVTLkZ1bmN0aW9uKSB7CiAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhGdW5jdGlvbi5wcm90b3R5cGUsIHsKICAgICAgLyoqCiAgICAgICAgVGhlIGBwcm9wZXJ0eWAgZXh0ZW5zaW9uIG9mIEphdmFzY3JpcHQncyBGdW5jdGlvbiBwcm90b3R5cGUgaXMgYXZhaWxhYmxlCiAgICAgICAgd2hlbiBgRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVNgIG9yIGBFbWJlckVOVi5FWFRFTkRfUFJPVE9UWVBFUy5GdW5jdGlvbmAgaXMKICAgICAgICBgdHJ1ZWAsIHdoaWNoIGlzIHRoZSBkZWZhdWx0LgogICAgICAgICBDb21wdXRlZCBwcm9wZXJ0aWVzIGFsbG93IHlvdSB0byB0cmVhdCBhIGZ1bmN0aW9uIGxpa2UgYSBwcm9wZXJ0eToKICAgICAgICAgYGBgYXBwL3V0aWxzL3ByZXNpZGVudC5qcwogICAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICAgIGZpcnN0TmFtZTogJycsCiAgICAgICAgICBsYXN0TmFtZTogICcnLAogICAgICAgICAgIGZ1bGxOYW1lOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KCdmaXJzdE5hbWUnKSArICcgJyArIHRoaXMuZ2V0KCdsYXN0TmFtZScpOwogICAgICAgICAgfS5wcm9wZXJ0eSgpIC8vIENhbGwgdGhpcyBmbGFnIHRvIG1hcmsgdGhlIGZ1bmN0aW9uIGFzIGEgcHJvcGVydHkKICAgICAgICB9KTsKICAgICAgICBgYGAKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICAgIGxldCBwcmVzaWRlbnQgPSBQcmVzaWRlbnQuY3JlYXRlKHsKICAgICAgICAgIGZpcnN0TmFtZTogJ0JhcmFjaycsCiAgICAgICAgICBsYXN0TmFtZTogJ09iYW1hJwogICAgICAgIH0pOwogICAgICAgICBwcmVzaWRlbnQuZ2V0KCdmdWxsTmFtZScpOyAvLyAnQmFyYWNrIE9iYW1hJwogICAgICAgIGBgYAogICAgICAgICBUcmVhdGluZyBhIGZ1bmN0aW9uIGxpa2UgYSBwcm9wZXJ0eSBpcyB1c2VmdWwgYmVjYXVzZSB0aGV5IGNhbiB3b3JrIHdpdGgKICAgICAgICBiaW5kaW5ncywganVzdCBsaWtlIGFueSBvdGhlciBwcm9wZXJ0eS4KICAgICAgICAgTWFueSBjb21wdXRlZCBwcm9wZXJ0aWVzIGhhdmUgZGVwZW5kZW5jaWVzIG9uIG90aGVyIHByb3BlcnRpZXMuIEZvcgogICAgICAgIGV4YW1wbGUsIGluIHRoZSBhYm92ZSBleGFtcGxlLCB0aGUgYGZ1bGxOYW1lYCBwcm9wZXJ0eSBkZXBlbmRzIG9uCiAgICAgICAgYGZpcnN0TmFtZWAgYW5kIGBsYXN0TmFtZWAgdG8gZGV0ZXJtaW5lIGl0cyB2YWx1ZS4gWW91IGNhbiB0ZWxsIEVtYmVyCiAgICAgICAgYWJvdXQgdGhlc2UgZGVwZW5kZW5jaWVzIGxpa2UgdGhpczoKICAgICAgICAgYGBgYXBwL3V0aWxzL3ByZXNpZGVudC5qcwogICAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICAgIGZpcnN0TmFtZTogJycsCiAgICAgICAgICBsYXN0TmFtZTogICcnLAogICAgICAgICAgIGZ1bGxOYW1lOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KCdmaXJzdE5hbWUnKSArICcgJyArIHRoaXMuZ2V0KCdsYXN0TmFtZScpOwogICAgICAgICAgICAgLy8gVGVsbCBFbWJlci5qcyB0aGF0IHRoaXMgY29tcHV0ZWQgcHJvcGVydHkgZGVwZW5kcyBvbiBmaXJzdE5hbWUKICAgICAgICAgICAgLy8gYW5kIGxhc3ROYW1lCiAgICAgICAgICB9LnByb3BlcnR5KCdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnKQogICAgICAgIH0pOwogICAgICAgIGBgYAogICAgICAgICBNYWtlIHN1cmUgeW91IGxpc3QgdGhlc2UgZGVwZW5kZW5jaWVzIHNvIEVtYmVyIGtub3dzIHdoZW4gdG8gdXBkYXRlCiAgICAgICAgYmluZGluZ3MgdGhhdCBjb25uZWN0IHRvIGEgY29tcHV0ZWQgcHJvcGVydHkuIENoYW5naW5nIGEgZGVwZW5kZW5jeQogICAgICAgIHdpbGwgbm90IGltbWVkaWF0ZWx5IHRyaWdnZXIgYW4gdXBkYXRlIG9mIHRoZSBjb21wdXRlZCBwcm9wZXJ0eSwgYnV0CiAgICAgICAgd2lsbCBpbnN0ZWFkIGNsZWFyIHRoZSBjYWNoZSBzbyB0aGF0IGl0IGlzIHVwZGF0ZWQgd2hlbiB0aGUgbmV4dCBgZ2V0YAogICAgICAgIGlzIGNhbGxlZCBvbiB0aGUgcHJvcGVydHkuCiAgICAgICAgIFNlZSBbQ29tcHV0ZWRQcm9wZXJ0eV0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9Db21wdXRlZFByb3BlcnR5KSwgW0BlbWJlci9vYmplY3QvY29tcHV0ZWRdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvQGVtYmVyJTJGb2JqZWN0JTJGY29tcHV0ZWQpLgogICAgICAgICBAbWV0aG9kIHByb3BlcnR5CiAgICAgICAgQGZvciBGdW5jdGlvbgogICAgICAgIEBwdWJsaWMKICAgICAgKi8KICAgICAgcHJvcGVydHk6IHsKICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsCiAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgiRnVuY3Rpb24gcHJvdG90eXBlIGV4dGVuc2lvbnMgaGF2ZSBiZWVuIGRlcHJlY2F0ZWQsIHBsZWFzZSBtaWdyYXRlIGZyb20gZnVuY3Rpb24oKXt9LnByb3BlcnR5KCdiYXInKSB0byBjb21wdXRlZCgnYmFyJywgZnVuY3Rpb24oKSB7fSkuIiwgZmFsc2UsIHsKICAgICAgICAgICAgaWQ6ICdmdW5jdGlvbi1wcm90b3R5cGUtZXh0ZW5zaW9ucy5wcm9wZXJ0eScsCiAgICAgICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgICAgICB1cmw6ICdodHRwczovL2RlcHJlY2F0aW9ucy5lbWJlcmpzLmNvbS92My54I3RvY19mdW5jdGlvbi1wcm90b3R5cGUtZXh0ZW5zaW9ucy1wcm9wZXJ0eScKICAgICAgICAgIH0pKTsKICAgICAgICAgIHJldHVybiBfbWV0YWwuY29tcHV0ZWQuYXBwbHkodm9pZCAwLCBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpLmNvbmNhdChbdGhpc10pKTsKICAgICAgICB9CiAgICAgIH0sCgogICAgICAvKioKICAgICAgICBUaGUgYG9ic2VydmVzYCBleHRlbnNpb24gb2YgSmF2YXNjcmlwdCdzIEZ1bmN0aW9uIHByb3RvdHlwZSBpcyBhdmFpbGFibGUKICAgICAgICB3aGVuIGBFbWJlckVOVi5FWFRFTkRfUFJPVE9UWVBFU2Agb3IgYEVtYmVyRU5WLkVYVEVORF9QUk9UT1RZUEVTLkZ1bmN0aW9uYCBpcwogICAgICAgIHRydWUsIHdoaWNoIGlzIHRoZSBkZWZhdWx0LgogICAgICAgICBZb3UgY2FuIG9ic2VydmUgcHJvcGVydHkgY2hhbmdlcyBzaW1wbHkgYnkgYWRkaW5nIHRoZSBgb2JzZXJ2ZXNgCiAgICAgICAgY2FsbCB0byB0aGUgZW5kIG9mIHlvdXIgbWV0aG9kIGRlY2xhcmF0aW9ucyBpbiBjbGFzc2VzIHRoYXQgeW91IHdyaXRlLgogICAgICAgIEZvciBleGFtcGxlOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgICBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAgICAgdmFsdWVPYnNlcnZlcjogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIC8vIEV4ZWN1dGVzIHdoZW5ldmVyIHRoZSAidmFsdWUiIHByb3BlcnR5IGNoYW5nZXMKICAgICAgICAgIH0ub2JzZXJ2ZXMoJ3ZhbHVlJykKICAgICAgICB9KTsKICAgICAgICBgYGAKICAgICAgICAgSW4gdGhlIGZ1dHVyZSB0aGlzIG1ldGhvZCBtYXkgYmVjb21lIGFzeW5jaHJvbm91cy4KICAgICAgICAgU2VlIGBvYnNlcnZlcmAuCiAgICAgICAgIEBtZXRob2Qgb2JzZXJ2ZXMKICAgICAgICBAZm9yIEZ1bmN0aW9uCiAgICAgICAgQHB1YmxpYwogICAgICAqLwogICAgICBvYnNlcnZlczogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCJGdW5jdGlvbiBwcm90b3R5cGUgZXh0ZW5zaW9ucyBoYXZlIGJlZW4gZGVwcmVjYXRlZCwgcGxlYXNlIG1pZ3JhdGUgZnJvbSBmdW5jdGlvbigpe30ub2JzZXJ2ZXMoJ2ZvbycpIHRvIG9ic2VydmVyKCdmb28nLCBmdW5jdGlvbigpIHt9KS4iLCBmYWxzZSwgewogICAgICAgICAgICBpZDogJ2Z1bmN0aW9uLXByb3RvdHlwZS1leHRlbnNpb25zLm9ic2VydmVzJywKICAgICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vZGVwcmVjYXRpb25zLmVtYmVyanMuY29tL3YzLngjdG9jX2Z1bmN0aW9uLXByb3RvdHlwZS1leHRlbnNpb25zLW9ic2VydmVzJwogICAgICAgICAgfSkpOwogICAgICAgICAgcmV0dXJuIF9tZXRhbC5vYnNlcnZlci5hcHBseSh2b2lkIDAsIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykuY29uY2F0KFt0aGlzXSkpOwogICAgICAgIH0KICAgICAgfSwKCiAgICAgIC8qKgogICAgICAgIFRoZSBgb25gIGV4dGVuc2lvbiBvZiBKYXZhc2NyaXB0J3MgRnVuY3Rpb24gcHJvdG90eXBlIGlzIGF2YWlsYWJsZQogICAgICAgIHdoZW4gYEVtYmVyRU5WLkVYVEVORF9QUk9UT1RZUEVTYCBvciBgRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVMuRnVuY3Rpb25gIGlzCiAgICAgICAgdHJ1ZSwgd2hpY2ggaXMgdGhlIGRlZmF1bHQuCiAgICAgICAgIFlvdSBjYW4gbGlzdGVuIGZvciBldmVudHMgc2ltcGx5IGJ5IGFkZGluZyB0aGUgYG9uYCBjYWxsIHRvIHRoZSBlbmQgb2YKICAgICAgICB5b3VyIG1ldGhvZCBkZWNsYXJhdGlvbnMgaW4gY2xhc3NlcyBvciBtaXhpbnMgdGhhdCB5b3Ugd3JpdGUuIEZvciBleGFtcGxlOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgICAgaW1wb3J0IE1peGluIGZyb20gJ0BlbWJlci9taXhpbic7CiAgICAgICAgIE1peGluLmNyZWF0ZSh7CiAgICAgICAgICBkb1NvbWV0aGluZ1dpdGhFbGVtZW50OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgLy8gRXhlY3V0ZXMgd2hlbmV2ZXIgdGhlICJkaWRJbnNlcnRFbGVtZW50IiBldmVudCBmaXJlcwogICAgICAgICAgfS5vbignZGlkSW5zZXJ0RWxlbWVudCcpCiAgICAgICAgfSk7CiAgICAgICAgYGBgCiAgICAgICAgIFNlZSBgQGVtYmVyL29iamVjdC9ldmVudGVkL29uYC4KICAgICAgICAgQG1ldGhvZCBvbgogICAgICAgIEBmb3IgRnVuY3Rpb24KICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgIG9uOiB7CiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgIGVudW1lcmFibGU6IGZhbHNlLAogICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgIHZhbHVlOiBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIkZ1bmN0aW9uIHByb3RvdHlwZSBleHRlbnNpb25zIGhhdmUgYmVlbiBkZXByZWNhdGVkLCBwbGVhc2UgbWlncmF0ZSBmcm9tIGZ1bmN0aW9uKCl7fS5vbignZm9vJykgdG8gb24oJ2ZvbycsIGZ1bmN0aW9uKCkge30pLiIsIGZhbHNlLCB7CiAgICAgICAgICAgIGlkOiAnZnVuY3Rpb24tcHJvdG90eXBlLWV4dGVuc2lvbnMub24nLAogICAgICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9kZXByZWNhdGlvbnMuZW1iZXJqcy5jb20vdjMueCN0b2NfZnVuY3Rpb24tcHJvdG90eXBlLWV4dGVuc2lvbnMtb24nCiAgICAgICAgICB9KSk7CiAgICAgICAgICByZXR1cm4gX21ldGFsLm9uLmFwcGx5KHZvaWQgMCwgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKS5jb25jYXQoW3RoaXNdKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL2V4dC9yc3ZwIiwgWyJleHBvcnRzIiwgInJzdnAiLCAiQGVtYmVyL3J1bmxvb3AiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZXJyb3ItaGFuZGxpbmciLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgUlNWUCwgX3J1bmxvb3AsIF9lcnJvckhhbmRsaW5nLCBfZGVidWcpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLm9uZXJyb3JEZWZhdWx0ID0gb25lcnJvckRlZmF1bHQ7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKICBSU1ZQLmNvbmZpZ3VyZSgnYXN5bmMnLCBmdW5jdGlvbiAoY2FsbGJhY2ssIHByb21pc2UpIHsKICAgIF9ydW5sb29wLmJhY2tidXJuZXIuc2NoZWR1bGUoJ2FjdGlvbnMnLCBudWxsLCBjYWxsYmFjaywgcHJvbWlzZSk7CiAgfSk7CiAgUlNWUC5jb25maWd1cmUoJ2FmdGVyJywgZnVuY3Rpb24gKGNiKSB7CiAgICBfcnVubG9vcC5iYWNrYnVybmVyLnNjaGVkdWxlKF9ydW5sb29wLl9yc3ZwRXJyb3JRdWV1ZSwgbnVsbCwgY2IpOwogIH0pOwogIFJTVlAub24oJ2Vycm9yJywgb25lcnJvckRlZmF1bHQpOwoKICBmdW5jdGlvbiBvbmVycm9yRGVmYXVsdChyZWFzb24pIHsKICAgIHZhciBlcnJvciA9IGVycm9yRm9yKHJlYXNvbik7CgogICAgaWYgKGVycm9yKSB7CiAgICAgIHZhciBvdmVycmlkZURpc3BhdGNoID0gKDAsIF9lcnJvckhhbmRsaW5nLmdldERpc3BhdGNoT3ZlcnJpZGUpKCk7CgogICAgICBpZiAob3ZlcnJpZGVEaXNwYXRjaCkgewogICAgICAgIG92ZXJyaWRlRGlzcGF0Y2goZXJyb3IpOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IGVycm9yOwogICAgICB9CiAgICB9CiAgfQoKICBmdW5jdGlvbiBlcnJvckZvcihyZWFzb24pIHsKICAgIGlmICghcmVhc29uKSByZXR1cm47CgogICAgaWYgKHJlYXNvbi5lcnJvclRocm93bikgewogICAgICByZXR1cm4gdW53cmFwRXJyb3JUaHJvd24ocmVhc29uKTsKICAgIH0KCiAgICBpZiAocmVhc29uLm5hbWUgPT09ICdVbnJlY29nbml6ZWRVUkxFcnJvcicpIHsKICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIFVSTCAnIiArIHJlYXNvbi5tZXNzYWdlICsgIicgZGlkIG5vdCBtYXRjaCBhbnkgcm91dGVzIGluIHlvdXIgYXBwbGljYXRpb24iLCBmYWxzZSkpOwogICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKHJlYXNvbi5uYW1lID09PSAnVHJhbnNpdGlvbkFib3J0ZWQnKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICByZXR1cm4gcmVhc29uOwogIH0KCiAgZnVuY3Rpb24gdW53cmFwRXJyb3JUaHJvd24ocmVhc29uKSB7CiAgICB2YXIgZXJyb3IgPSByZWFzb24uZXJyb3JUaHJvd247CgogICAgaWYgKHR5cGVvZiBlcnJvciA9PT0gJ3N0cmluZycpIHsKICAgICAgZXJyb3IgPSBuZXcgRXJyb3IoZXJyb3IpOwogICAgfQoKICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlcnJvciwgJ19fcmVhc29uX3dpdGhfZXJyb3JfdGhyb3duX18nLCB7CiAgICAgIHZhbHVlOiByZWFzb24sCiAgICAgIGVudW1lcmFibGU6IGZhbHNlCiAgICB9KTsKICAgIHJldHVybiBlcnJvcjsKICB9CgogIHZhciBfZGVmYXVsdCA9IFJTVlA7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9pcy1lcXVhbCIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSBpc0VxdWFsOwoKICAvKioKICAgQG1vZHVsZSBAZW1iZXIvdXRpbHMKICAqLwoKICAvKioKICAgIENvbXBhcmVzIHR3byBvYmplY3RzLCByZXR1cm5pbmcgdHJ1ZSBpZiB0aGV5IGFyZSBlcXVhbC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGlzRXF1YWwgfSBmcm9tICdAZW1iZXIvdXRpbHMnOwogIAogICAgaXNFcXVhbCgnaGVsbG8nLCAnaGVsbG8nKTsgICAgICAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNFcXVhbCgxLCAyKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGBgYAogIAogICAgYGlzRXF1YWxgIGlzIGEgbW9yZSBzcGVjaWZpYyBjb21wYXJpc29uIHRoYW4gYSB0cmlwbGUgZXF1YWwgY29tcGFyaXNvbi4KICAgIEl0IHdpbGwgY2FsbCB0aGUgYGlzRXF1YWxgIGluc3RhbmNlIG1ldGhvZCBvbiB0aGUgb2JqZWN0cyBiZWluZwogICAgY29tcGFyZWQsIGFsbG93aW5nIGZpbmVyIGNvbnRyb2wgb3ZlciB3aGVuIG9iamVjdHMgc2hvdWxkIGJlIGNvbnNpZGVyZWQKICAgIGVxdWFsIHRvIGVhY2ggb3RoZXIuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBpc0VxdWFsIH0gZnJvbSAnQGVtYmVyL3V0aWxzJzsKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGxldCBQZXJzb24gPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBpc0VxdWFsKG90aGVyKSB7IHJldHVybiB0aGlzLnNzbiA9PSBvdGhlci5zc247IH0KICAgIH0pOwogIAogICAgbGV0IHBlcnNvbkEgPSBQZXJzb24uY3JlYXRlKHtuYW1lOiAnTXVoYW1tYWQgQWxpJywgc3NuOiAnMTIzLTQ1LTY3ODknfSk7CiAgICBsZXQgcGVyc29uQiA9IFBlcnNvbi5jcmVhdGUoe25hbWU6ICdDYXNzaXVzIENsYXknLCBzc246ICcxMjMtNDUtNjc4OSd9KTsKICAKICAgIGlzRXF1YWwocGVyc29uQSwgcGVyc29uQik7IC8vIHRydWUKICAgIGBgYAogIAogICAgRHVlIHRvIHRoZSBleHBlbnNlIG9mIGFycmF5IGNvbXBhcmlzb25zLCBjb2xsZWN0aW9ucyB3aWxsIG5ldmVyIGJlIGVxdWFsIHRvCiAgICBlYWNoIG90aGVyIGV2ZW4gaWYgZWFjaCBvZiB0aGVpciBpdGVtcyBhcmUgZXF1YWwgdG8gZWFjaCBvdGhlci4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGlzRXF1YWwgfSBmcm9tICdAZW1iZXIvdXRpbHMnOwogIAogICAgaXNFcXVhbChbNCwgMl0sIFs0LCAyXSk7ICAgICAgICAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQG1ldGhvZCBpc0VxdWFsCiAgICBAZm9yIEBlbWJlci91dGlscwogICAgQHN0YXRpYwogICAgQHBhcmFtIHtPYmplY3R9IGEgZmlyc3Qgb2JqZWN0IHRvIGNvbXBhcmUKICAgIEBwYXJhbSB7T2JqZWN0fSBiIHNlY29uZCBvYmplY3QgdG8gY29tcGFyZQogICAgQHJldHVybiB7Qm9vbGVhbn0KICAgIEBwdWJsaWMKICAqLwogIGZ1bmN0aW9uIGlzRXF1YWwoYSwgYikgewogICAgaWYgKGEgJiYgdHlwZW9mIGEuaXNFcXVhbCA9PT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gYS5pc0VxdWFsKGIpOwogICAgfQoKICAgIGlmIChhIGluc3RhbmNlb2YgRGF0ZSAmJiBiIGluc3RhbmNlb2YgRGF0ZSkgewogICAgICByZXR1cm4gYS5nZXRUaW1lKCkgPT09IGIuZ2V0VGltZSgpOwogICAgfQoKICAgIHJldHVybiBhID09PSBiOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zLy1wcm94eSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZ2xpbW1lci9yZWZlcmVuY2UiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YSwgX21ldGFsLCBfdXRpbHMsIF9kZWJ1ZywgX3JlZmVyZW5jZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuY29udGVudEZvciA9IGNvbnRlbnRGb3I7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgdmFyIF9NaXhpbiRjcmVhdGU7CgogIGZ1bmN0aW9uIGNvbnRlbnRGb3IocHJveHksIG0pIHsKICAgIHZhciBjb250ZW50ID0gKDAsIF9tZXRhbC5nZXQpKHByb3h5LCAnY29udGVudCcpOwogICAgdmFyIHRhZyA9IChtID09PSB1bmRlZmluZWQgPyAoMCwgX21ldGEubWV0YSkocHJveHkpIDogbSkucmVhZGFibGVUYWcoKTsKCiAgICBpZiAodGFnICE9PSB1bmRlZmluZWQpIHsKICAgICAgKDAsIF9yZWZlcmVuY2UudXBkYXRlKSh0YWcsICgwLCBfbWV0YWwudGFnRm9yKShjb250ZW50KSk7CiAgICB9CgogICAgcmV0dXJuIGNvbnRlbnQ7CiAgfQogIC8qKgogICAgYEVtYmVyLlByb3h5TWl4aW5gIGZvcndhcmRzIGFsbCBwcm9wZXJ0aWVzIG5vdCBkZWZpbmVkIGJ5IHRoZSBwcm94eSBpdHNlbGYKICAgIHRvIGEgcHJveGllZCBgY29udGVudGAgb2JqZWN0LiAgU2VlIE9iamVjdFByb3h5IGZvciBtb3JlIGRldGFpbHMuCiAgCiAgICBAY2xhc3MgUHJveHlNaXhpbgogICAgQG5hbWVzcGFjZSBFbWJlcgogICAgQHByaXZhdGUKICAqLwoKCiAgdmFyIF9kZWZhdWx0ID0gX21ldGFsLk1peGluLmNyZWF0ZSgoX01peGluJGNyZWF0ZSA9IHsKICAgIC8qKgogICAgICBUaGUgb2JqZWN0IHdob3NlIHByb3BlcnRpZXMgd2lsbCBiZSBmb3J3YXJkZWQuCiAgICAgICBAcHJvcGVydHkgY29udGVudAogICAgICBAdHlwZSB7dW5rbm93bn0KICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwogICAgY29udGVudDogbnVsbCwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAoMCwgX3V0aWxzLnNldFByb3h5KSh0aGlzKTsKICAgICAgdmFyIG0gPSAoMCwgX21ldGEubWV0YSkodGhpcyk7CiAgICAgIG0ud3JpdGFibGVUYWcoKTsKICAgIH0sCiAgICB3aWxsRGVzdHJveTogZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIHRoaXMuc2V0KCdjb250ZW50JywgbnVsbCk7CgogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfSwKICAgIGlzVHJ1dGh5OiAoMCwgX21ldGFsLmNvbXB1dGVkKSgnY29udGVudCcsIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIEJvb2xlYW4oKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdjb250ZW50JykpOwogICAgfSksCiAgICB3aWxsV2F0Y2hQcm9wZXJ0eTogZnVuY3Rpb24gd2lsbFdhdGNoUHJvcGVydHkoa2V5KSB7CiAgICAgIGlmICghdHJ1ZQogICAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICAgKSB7CiAgICAgICAgICB2YXIgY29udGVudEtleSA9ICJjb250ZW50LiIgKyBrZXk7CiAgICAgICAgICAoMCwgX21ldGFsLmFkZE9ic2VydmVyKSh0aGlzLCBjb250ZW50S2V5LCBudWxsLCAnX2NvbnRlbnRQcm9wZXJ0eURpZENoYW5nZScpOwogICAgICAgIH0KICAgIH0sCiAgICBkaWRVbndhdGNoUHJvcGVydHk6IGZ1bmN0aW9uIGRpZFVud2F0Y2hQcm9wZXJ0eShrZXkpIHsKICAgICAgaWYgKCF0cnVlCiAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICApIHsKICAgICAgICAgIHZhciBjb250ZW50S2V5ID0gImNvbnRlbnQuIiArIGtleTsKICAgICAgICAgICgwLCBfbWV0YWwucmVtb3ZlT2JzZXJ2ZXIpKHRoaXMsIGNvbnRlbnRLZXksIG51bGwsICdfY29udGVudFByb3BlcnR5RGlkQ2hhbmdlJyk7CiAgICAgICAgfQogICAgfSwKICAgIF9jb250ZW50UHJvcGVydHlEaWRDaGFuZ2U6IGZ1bmN0aW9uIF9jb250ZW50UHJvcGVydHlEaWRDaGFuZ2UoY29udGVudCwgY29udGVudEtleSkgewogICAgICB2YXIga2V5ID0gY29udGVudEtleS5zbGljZSg4KTsgLy8gcmVtb3ZlICJjb250ZW50LiIKCiAgICAgIGlmIChrZXkgaW4gdGhpcykgewogICAgICAgIHJldHVybjsKICAgICAgfSAvLyBpZiBzaGFkb3dlZCBpbiBwcm94eQoKCiAgICAgICgwLCBfbWV0YWwubm90aWZ5UHJvcGVydHlDaGFuZ2UpKHRoaXMsIGtleSk7CiAgICB9CiAgfSwgX01peGluJGNyZWF0ZVtfbWV0YWwuVU5LTk9XTl9QUk9QRVJUWV9UQUddID0gZnVuY3Rpb24gKGtleSkgewogICAgcmV0dXJuICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKCgwLCBfbWV0YWwuZ2V0Q2hhaW5UYWdzRm9yS2V5KSh0aGlzLCAiY29udGVudC4iICsga2V5KSk7CiAgfSwgX01peGluJGNyZWF0ZS51bmtub3duUHJvcGVydHkgPSBmdW5jdGlvbiB1bmtub3duUHJvcGVydHkoa2V5KSB7CiAgICB2YXIgY29udGVudCA9IGNvbnRlbnRGb3IodGhpcyk7CgogICAgaWYgKGNvbnRlbnQpIHsKICAgICAgcmV0dXJuICgwLCBfbWV0YWwuZ2V0KShjb250ZW50LCBrZXkpOwogICAgfQogIH0sIF9NaXhpbiRjcmVhdGUuc2V0VW5rbm93blByb3BlcnR5ID0gZnVuY3Rpb24gc2V0VW5rbm93blByb3BlcnR5KGtleSwgdmFsdWUpIHsKICAgIHZhciBtID0gKDAsIF9tZXRhLm1ldGEpKHRoaXMpOwoKICAgIGlmIChtLmlzSW5pdGlhbGl6aW5nKCkgfHwgbS5pc1Byb3RvdHlwZU1ldGEodGhpcykpIHsKICAgICAgLy8gaWYgbWFya2VkIGFzIHByb3RvdHlwZSBvciBvYmplY3QgaXMgaW5pdGlhbGl6aW5nIHRoZW4ganVzdAogICAgICAvLyBkZWZpbmVQcm9wZXJ0eSByYXRoZXIgdGhhbiBkZWxlZ2F0ZQogICAgICAoMCwgX21ldGFsLmRlZmluZVByb3BlcnR5KSh0aGlzLCBrZXksIG51bGwsIHZhbHVlKTsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQoKICAgIHZhciBjb250ZW50ID0gY29udGVudEZvcih0aGlzLCBtKTsKICAgIChmYWxzZSAmJiAhKGNvbnRlbnQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IGRlbGVnYXRlIHNldCgnIiArIGtleSArICInLCAiICsgdmFsdWUgKyAiKSB0byB0aGUgJ2NvbnRlbnQnIHByb3BlcnR5IG9mIG9iamVjdCBwcm94eSAiICsgdGhpcyArICI6IGl0cyAnY29udGVudCcgaXMgdW5kZWZpbmVkLiIsIGNvbnRlbnQpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLnNldCkoY29udGVudCwga2V5LCB2YWx1ZSk7CiAgfSwgX01peGluJGNyZWF0ZSkpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9hY3Rpb25faGFuZGxlciIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwsIF9kZWJ1ZykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgYEVtYmVyLkFjdGlvbkhhbmRsZXJgIGlzIGF2YWlsYWJsZSBvbiBzb21lIGZhbWlsaWFyIGNsYXNzZXMgaW5jbHVkaW5nCiAgICBgUm91dGVgLCBgQ29tcG9uZW50YCwgYW5kIGBDb250cm9sbGVyYC4KICAgIChJbnRlcm5hbGx5IHRoZSBtaXhpbiBpcyB1c2VkIGJ5IGBFbWJlci5Db3JlVmlld2AsIGBFbWJlci5Db250cm9sbGVyTWl4aW5gLAogICAgYW5kIGBSb3V0ZWAgYW5kIGF2YWlsYWJsZSB0byB0aGUgYWJvdmUgY2xhc3NlcyB0aHJvdWdoCiAgICBpbmhlcml0YW5jZS4pCiAgCiAgICBAY2xhc3MgQWN0aW9uSGFuZGxlcgogICAgQG5hbWVzcGFjZSBFbWJlcgogICAgQHByaXZhdGUKICAqLwogIHZhciBBY3Rpb25IYW5kbGVyID0gX21ldGFsLk1peGluLmNyZWF0ZSh7CiAgICBtZXJnZWRQcm9wZXJ0aWVzOiBbJ2FjdGlvbnMnXSwKCiAgICAvKioKICAgICAgVGhlIGNvbGxlY3Rpb24gb2YgZnVuY3Rpb25zLCBrZXllZCBieSBuYW1lLCBhdmFpbGFibGUgb24gdGhpcwogICAgICBgQWN0aW9uSGFuZGxlcmAgYXMgYWN0aW9uIHRhcmdldHMuCiAgICAgICBUaGVzZSBmdW5jdGlvbnMgd2lsbCBiZSBpbnZva2VkIHdoZW4gYSBtYXRjaGluZyBge3thY3Rpb259fWAgaXMgdHJpZ2dlcmVkCiAgICAgIGZyb20gd2l0aGluIGEgdGVtcGxhdGUgYW5kIHRoZSBhcHBsaWNhdGlvbidzIGN1cnJlbnQgcm91dGUgaXMgdGhpcyByb3V0ZS4KICAgICAgIEFjdGlvbnMgY2FuIGFsc28gYmUgaW52b2tlZCBmcm9tIG90aGVyIHBhcnRzIG9mIHlvdXIgYXBwbGljYXRpb24KICAgICAgdmlhIGBBY3Rpb25IYW5kbGVyI3NlbmRgLgogICAgICAgVGhlIGBhY3Rpb25zYCBoYXNoIHdpbGwgaW5oZXJpdCBhY3Rpb24gaGFuZGxlcnMgZnJvbQogICAgICB0aGUgYGFjdGlvbnNgIGhhc2ggZGVmaW5lZCBvbiBleHRlbmRlZCBwYXJlbnQgY2xhc3NlcwogICAgICBvciBtaXhpbnMgcmF0aGVyIHRoYW4ganVzdCByZXBsYWNlIHRoZSBlbnRpcmUgaGFzaCwgZS5nLjoKICAgICAgIGBgYGFwcC9taXhpbnMvY2FuLWRpc3BsYXktYmFubmVyLmpzCiAgICAgIGltcG9ydCBNaXhpbiBmcm9tICdAZW1iZXIvbWl4aW4nOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTWl4aW4uY3JlYXRlKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBkaXNwbGF5QmFubmVyKG1zZykgewogICAgICAgICAgICAvLyAuLi4KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIGBgYGFwcC9yb3V0ZXMvd2VsY29tZS5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICBpbXBvcnQgQ2FuRGlzcGxheUJhbm5lciBmcm9tICcuLi9taXhpbnMvY2FuLWRpc3BsYXktYmFubmVyJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZChDYW5EaXNwbGF5QmFubmVyLCB7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgcGxheU11c2ljKCkgewogICAgICAgICAgICAvLyAuLi4KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICAgLy8gYFdlbGNvbWVSb3V0ZWAsIHdoZW4gYWN0aXZlLCB3aWxsIGJlIGFibGUgdG8gcmVzcG9uZAogICAgICAvLyB0byBib3RoIGFjdGlvbnMsIHNpbmNlIHRoZSBhY3Rpb25zIGhhc2ggaXMgbWVyZ2VkIHJhdGhlcgogICAgICAvLyB0aGVuIHJlcGxhY2VkIHdoZW4gZXh0ZW5kaW5nIG1peGlucyAvIHBhcmVudCBjbGFzc2VzLgogICAgICB0aGlzLnNlbmQoJ2Rpc3BsYXlCYW5uZXInKTsKICAgICAgdGhpcy5zZW5kKCdwbGF5TXVzaWMnKTsKICAgICAgYGBgCiAgICAgICBXaXRoaW4gYSBDb250cm9sbGVyLCBSb3V0ZSBvciBDb21wb25lbnQncyBhY3Rpb24gaGFuZGxlciwKICAgICAgdGhlIHZhbHVlIG9mIHRoZSBgdGhpc2AgY29udGV4dCBpcyB0aGUgQ29udHJvbGxlciwgUm91dGUgb3IKICAgICAgQ29tcG9uZW50IG9iamVjdDoKICAgICAgIGBgYGFwcC9yb3V0ZXMvc29uZy5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBteUFjdGlvbigpIHsKICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyRm9yKCJzb25nIik7CiAgICAgICAgICAgIHRoaXMudHJhbnNpdGlvblRvKCJvdGhlci5yb3V0ZSIpOwogICAgICAgICAgICAuLi4KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEl0IGlzIGFsc28gcG9zc2libGUgdG8gY2FsbCBgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKWAgZnJvbSB3aXRoaW4gYW4KICAgICAgYWN0aW9uIGhhbmRsZXIgaWYgaXQgb3ZlcnJpZGVzIGEgaGFuZGxlciBkZWZpbmVkIG9uIGEgcGFyZW50CiAgICAgIGNsYXNzIG9yIG1peGluOgogICAgICAgVGFrZSBmb3IgZXhhbXBsZSB0aGUgZm9sbG93aW5nIHJvdXRlczoKICAgICAgIGBgYGFwcC9taXhpbnMvZGVidWctcm91dGUuanMKICAgICAgaW1wb3J0IE1peGluIGZyb20gJ0BlbWJlci9taXhpbic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBNaXhpbi5jcmVhdGUoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIGRlYnVnUm91dGVJbmZvcm1hdGlvbigpIHsKICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygiSXQncyBhLW1lLCBjb25zb2xlLmRlYnVnISIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgYXBwL3JvdXRlcy9hbm5veWluZy1kZWJ1Zy5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICBpbXBvcnQgRGVidWdSb3V0ZSBmcm9tICcuLi9taXhpbnMvZGVidWctcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKERlYnVnUm91dGUsIHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBkZWJ1Z1JvdXRlSW5mb3JtYXRpb24oKSB7CiAgICAgICAgICAgIC8vIGFsc28gY2FsbCB0aGUgZGVidWdSb3V0ZUluZm9ybWF0aW9uIG9mIG1peGVkIGluIERlYnVnUm91dGUKICAgICAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICAgICAgIC8vIHNob3cgYWRkaXRpb25hbCBhbm5veWFuY2UKICAgICAgICAgICAgd2luZG93LmFsZXJ0KC4uLik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAjIyBCdWJibGluZwogICAgICAgQnkgZGVmYXVsdCwgYW4gYWN0aW9uIHdpbGwgc3RvcCBidWJibGluZyBvbmNlIGEgaGFuZGxlciBkZWZpbmVkCiAgICAgIG9uIHRoZSBgYWN0aW9uc2AgaGFzaCBoYW5kbGVzIGl0LiBUbyBjb250aW51ZSBidWJibGluZyB0aGUgYWN0aW9uLAogICAgICB5b3UgbXVzdCByZXR1cm4gYHRydWVgIGZyb20gdGhlIGhhbmRsZXI6CiAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgiYWxidW0iLCBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMucm91dGUoInNvbmciKTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgYXBwL3JvdXRlcy9hbGJ1bS5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBzdGFydFBsYXlpbmc6IGZ1bmN0aW9uKCkgewogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgYXBwL3JvdXRlcy9hbGJ1bS1zb25nLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHN0YXJ0UGxheWluZygpIHsKICAgICAgICAgICAgLy8gLi4uCiAgICAgICAgICAgICBpZiAoYWN0aW9uU2hvdWxkQWxzb0JlVHJpZ2dlcmVkT25QYXJlbnRSb3V0ZSkgewogICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAcHJvcGVydHkgYWN0aW9ucwogICAgICBAdHlwZSBPYmplY3QKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBUcmlnZ2VycyBhIG5hbWVkIGFjdGlvbiBvbiB0aGUgYEFjdGlvbkhhbmRsZXJgLiBBbnkgcGFyYW1ldGVycwogICAgICBzdXBwbGllZCBhZnRlciB0aGUgYGFjdGlvbk5hbWVgIHN0cmluZyB3aWxsIGJlIHBhc3NlZCBhcyBhcmd1bWVudHMKICAgICAgdG8gdGhlIGFjdGlvbiB0YXJnZXQgZnVuY3Rpb24uCiAgICAgICBJZiB0aGUgYEFjdGlvbkhhbmRsZXJgIGhhcyBpdHMgYHRhcmdldGAgcHJvcGVydHkgc2V0LCBhY3Rpb25zIG1heQogICAgICBidWJibGUgdG8gdGhlIGB0YXJnZXRgLiBCdWJibGluZyBoYXBwZW5zIHdoZW4gYW4gYGFjdGlvbk5hbWVgIGNhbgogICAgICBub3QgYmUgZm91bmQgaW4gdGhlIGBBY3Rpb25IYW5kbGVyYCdzIGBhY3Rpb25zYCBoYXNoIG9yIGlmIHRoZQogICAgICBhY3Rpb24gdGFyZ2V0IGZ1bmN0aW9uIHJldHVybnMgYHRydWVgLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3JvdXRlcy93ZWxjb21lLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHBsYXlUaGVtZSgpIHsKICAgICAgICAgICAgdGhpcy5zZW5kKCdwbGF5TXVzaWMnLCAndGhlbWUubXAzJyk7CiAgICAgICAgICB9LAogICAgICAgICAgcGxheU11c2ljKHRyYWNrKSB7CiAgICAgICAgICAgIC8vIC4uLgogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZW5kCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBhY3Rpb25OYW1lIFRoZSBhY3Rpb24gdG8gdHJpZ2dlcgogICAgICBAcGFyYW0geyp9IGNvbnRleHQgYSBjb250ZXh0IHRvIHNlbmQgd2l0aCB0aGUgYWN0aW9uCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBzZW5kOiBmdW5jdGlvbiBzZW5kKGFjdGlvbk5hbWUpIHsKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5ID0gMTsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleSAtIDFdID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc0Rlc3Ryb3lpbmcgJiYgIXRoaXMuaXNEZXN0cm95ZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQXR0ZW1wdGVkIHRvIGNhbGwgLnNlbmQoKSB3aXRoIHRoZSBhY3Rpb24gJyIgKyBhY3Rpb25OYW1lICsgIicgb24gdGhlIGRlc3Ryb3llZCBvYmplY3QgJyIgKyB0aGlzICsgIicuIiwgIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSk7CgogICAgICBpZiAodGhpcy5hY3Rpb25zICYmIHRoaXMuYWN0aW9uc1thY3Rpb25OYW1lXSkgewogICAgICAgIHZhciBzaG91bGRCdWJibGUgPSB0aGlzLmFjdGlvbnNbYWN0aW9uTmFtZV0uYXBwbHkodGhpcywgYXJncykgPT09IHRydWU7CgogICAgICAgIGlmICghc2hvdWxkQnViYmxlKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgdGFyZ2V0ID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICd0YXJnZXQnKTsKCiAgICAgIGlmICh0YXJnZXQpIHsKICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgdGFyZ2V0LnNlbmQgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIGB0YXJnZXRgIGZvciAiICsgdGhpcyArICIgKCIgKyB0YXJnZXQgKyAiKSBkb2VzIG5vdCBoYXZlIGEgYHNlbmRgIG1ldGhvZCIsIHR5cGVvZiB0YXJnZXQuc2VuZCA9PT0gJ2Z1bmN0aW9uJykpOwogICAgICAgIHRhcmdldC5zZW5kLmFwcGx5KHRhcmdldCwgYXJndW1lbnRzKTsKICAgICAgfQogICAgfQogIH0pOwoKICB2YXIgX2RlZmF1bHQgPSBBY3Rpb25IYW5kbGVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2FycmF5IiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvZW51bWVyYWJsZSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9jb21wYXJlIiwgIkBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9vYnNlcnZhYmxlIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9tdXRhYmxlX2VudW1lcmFibGUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvdHlwZS1vZiJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX3V0aWxzLCBfZGVidWcsIF9lbnVtZXJhYmxlLCBfY29tcGFyZSwgX2Vudmlyb25tZW50LCBfb2JzZXJ2YWJsZSwgX211dGFibGVfZW51bWVyYWJsZSwgX3R5cGVPZikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMudW5pcUJ5ID0gX3VuaXFCeTsKICBfZXhwb3J0cy5yZW1vdmVBdCA9IF9yZW1vdmVBdDsKICBfZXhwb3J0cy5pc0FycmF5ID0gaXNBcnJheTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2V4cG9ydHMuTXV0YWJsZUFycmF5ID0gX2V4cG9ydHMuTmF0aXZlQXJyYXkgPSBfZXhwb3J0cy5BID0gdm9pZCAwOwoKICB2YXIgX01peGluJGNyZWF0ZSwgX05hdGl2ZUFycmF5OwoKICB2YXIgRU1QVFlfQVJSQVkgPSBPYmplY3QuZnJlZXplKFtdKTsKCiAgdmFyIGlkZW50aXR5RnVuY3Rpb24gPSBmdW5jdGlvbiBpZGVudGl0eUZ1bmN0aW9uKGl0ZW0pIHsKICAgIHJldHVybiBpdGVtOwogIH07CgogIGZ1bmN0aW9uIF91bmlxQnkoYXJyYXksIGtleSkgewogICAgaWYgKGtleSA9PT0gdm9pZCAwKSB7CiAgICAgIGtleSA9IGlkZW50aXR5RnVuY3Rpb247CiAgICB9CgogICAgKGZhbHNlICYmICEoaXNBcnJheShhcnJheSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiZmlyc3QgYXJndW1lbnQgcGFzc2VkIHRvIGB1bmlxQnlgIHNob3VsZCBiZSBhcnJheSIsIGlzQXJyYXkoYXJyYXkpKSk7CgogICAgdmFyIHJldCA9IF9BMigpOwoKICAgIHZhciBzZWVuID0gbmV3IFNldCgpOwogICAgdmFyIGdldHRlciA9IHR5cGVvZiBrZXkgPT09ICdmdW5jdGlvbicgPyBrZXkgOiBmdW5jdGlvbiAoaXRlbSkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKGl0ZW0sIGtleSk7CiAgICB9OwogICAgYXJyYXkuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkgewogICAgICB2YXIgdmFsID0gZ2V0dGVyKGl0ZW0pOwoKICAgICAgaWYgKCFzZWVuLmhhcyh2YWwpKSB7CiAgICAgICAgc2Vlbi5hZGQodmFsKTsKICAgICAgICByZXQucHVzaChpdGVtKTsKICAgICAgfQogICAgfSk7CiAgICByZXR1cm4gcmV0OwogIH0KCiAgZnVuY3Rpb24gaXRlcihrZXksIHZhbHVlKSB7CiAgICB2YXIgdmFsdWVQcm92aWRlZCA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDI7CiAgICByZXR1cm4gdmFsdWVQcm92aWRlZCA/IGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgIHJldHVybiB2YWx1ZSA9PT0gKDAsIF9tZXRhbC5nZXQpKGl0ZW0sIGtleSk7CiAgICB9IDogZnVuY3Rpb24gKGl0ZW0pIHsKICAgICAgcmV0dXJuIEJvb2xlYW4oKDAsIF9tZXRhbC5nZXQpKGl0ZW0sIGtleSkpOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIGZpbmRJbmRleChhcnJheSwgcHJlZGljYXRlLCBzdGFydEF0KSB7CiAgICB2YXIgbGVuID0gYXJyYXkubGVuZ3RoOwoKICAgIGZvciAodmFyIGluZGV4ID0gc3RhcnRBdDsgaW5kZXggPCBsZW47IGluZGV4KyspIHsKICAgICAgdmFyIGl0ZW0gPSAoMCwgX21ldGFsLm9iamVjdEF0KShhcnJheSwgaW5kZXgpOwoKICAgICAgaWYgKHByZWRpY2F0ZShpdGVtLCBpbmRleCwgYXJyYXkpKSB7CiAgICAgICAgcmV0dXJuIGluZGV4OwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIC0xOwogIH0KCiAgZnVuY3Rpb24gX2ZpbmQoYXJyYXksIGNhbGxiYWNrLCB0YXJnZXQpIHsKICAgIHZhciBwcmVkaWNhdGUgPSBjYWxsYmFjay5iaW5kKHRhcmdldCk7CiAgICB2YXIgaW5kZXggPSBmaW5kSW5kZXgoYXJyYXksIHByZWRpY2F0ZSwgMCk7CiAgICByZXR1cm4gaW5kZXggPT09IC0xID8gdW5kZWZpbmVkIDogKDAsIF9tZXRhbC5vYmplY3RBdCkoYXJyYXksIGluZGV4KTsKICB9CgogIGZ1bmN0aW9uIF9hbnkoYXJyYXksIGNhbGxiYWNrLCB0YXJnZXQpIHsKICAgIHZhciBwcmVkaWNhdGUgPSBjYWxsYmFjay5iaW5kKHRhcmdldCk7CiAgICByZXR1cm4gZmluZEluZGV4KGFycmF5LCBwcmVkaWNhdGUsIDApICE9PSAtMTsKICB9CgogIGZ1bmN0aW9uIF9ldmVyeShhcnJheSwgY2FsbGJhY2ssIHRhcmdldCkgewogICAgdmFyIGNiID0gY2FsbGJhY2suYmluZCh0YXJnZXQpOwoKICAgIHZhciBwcmVkaWNhdGUgPSBmdW5jdGlvbiBwcmVkaWNhdGUoaXRlbSwgaW5kZXgsIGFycmF5KSB7CiAgICAgIHJldHVybiAhY2IoaXRlbSwgaW5kZXgsIGFycmF5KTsKICAgIH07CgogICAgcmV0dXJuIGZpbmRJbmRleChhcnJheSwgcHJlZGljYXRlLCAwKSA9PT0gLTE7CiAgfQoKICBmdW5jdGlvbiBfaW5kZXhPZihhcnJheSwgdmFsLCBzdGFydEF0LCB3aXRoTmFOQ2hlY2spIHsKICAgIGlmIChzdGFydEF0ID09PSB2b2lkIDApIHsKICAgICAgc3RhcnRBdCA9IDA7CiAgICB9CgogICAgdmFyIGxlbiA9IGFycmF5Lmxlbmd0aDsKCiAgICBpZiAoc3RhcnRBdCA8IDApIHsKICAgICAgc3RhcnRBdCArPSBsZW47CiAgICB9IC8vIFNhbWVWYWx1ZVplcm8gY29tcGFyaXNvbiAoTmFOICE9PSBOYU4pCgoKICAgIHZhciBwcmVkaWNhdGUgPSB3aXRoTmFOQ2hlY2sgJiYgdmFsICE9PSB2YWwgPyBmdW5jdGlvbiAoaXRlbSkgewogICAgICByZXR1cm4gaXRlbSAhPT0gaXRlbTsKICAgIH0gOiBmdW5jdGlvbiAoaXRlbSkgewogICAgICByZXR1cm4gaXRlbSA9PT0gdmFsOwogICAgfTsKICAgIHJldHVybiBmaW5kSW5kZXgoYXJyYXksIHByZWRpY2F0ZSwgc3RhcnRBdCk7CiAgfQoKICBmdW5jdGlvbiBfcmVtb3ZlQXQoYXJyYXksIGluZGV4LCBsZW4pIHsKICAgIGlmIChsZW4gPT09IHZvaWQgMCkgewogICAgICBsZW4gPSAxOwogICAgfQoKICAgIChmYWxzZSAmJiAhKGluZGV4ID4gLTEgJiYgaW5kZXggPCBhcnJheS5sZW5ndGgpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiYHJlbW92ZUF0YCBpbmRleCBwcm92aWRlZCBpcyBvdXQgb2YgcmFuZ2UiLCBpbmRleCA+IC0xICYmIGluZGV4IDwgYXJyYXkubGVuZ3RoKSk7CiAgICAoMCwgX21ldGFsLnJlcGxhY2UpKGFycmF5LCBpbmRleCwgbGVuLCBFTVBUWV9BUlJBWSk7CiAgICByZXR1cm4gYXJyYXk7CiAgfQoKICBmdW5jdGlvbiBfaW5zZXJ0QXQoYXJyYXksIGluZGV4LCBpdGVtKSB7CiAgICAoZmFsc2UgJiYgIShpbmRleCA+IC0xICYmIGluZGV4IDw9IGFycmF5Lmxlbmd0aCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJgaW5zZXJ0QXRgIGluZGV4IHByb3ZpZGVkIGlzIG91dCBvZiByYW5nZSIsIGluZGV4ID4gLTEgJiYgaW5kZXggPD0gYXJyYXkubGVuZ3RoKSk7CiAgICAoMCwgX21ldGFsLnJlcGxhY2UpKGFycmF5LCBpbmRleCwgMCwgW2l0ZW1dKTsKICAgIHJldHVybiBpdGVtOwogIH0KICAvKioKICAgIFJldHVybnMgdHJ1ZSBpZiB0aGUgcGFzc2VkIG9iamVjdCBpcyBhbiBhcnJheSBvciBBcnJheS1saWtlLgogIAogICAgT2JqZWN0cyBhcmUgY29uc2lkZXJlZCBBcnJheS1saWtlIGlmIGFueSBvZiB0aGUgZm9sbG93aW5nIGFyZSB0cnVlOgogIAogICAgICAtIHRoZSBvYmplY3QgaXMgYSBuYXRpdmUgQXJyYXkKICAgICAgLSB0aGUgb2JqZWN0IGhhcyBhbiBvYmplY3RBdCBwcm9wZXJ0eQogICAgICAtIHRoZSBvYmplY3QgaXMgYW4gT2JqZWN0LCBhbmQgaGFzIGEgbGVuZ3RoIHByb3BlcnR5CiAgCiAgICBVbmxpa2UgYHR5cGVPZmAgdGhpcyBtZXRob2QgcmV0dXJucyB0cnVlIGV2ZW4gaWYgdGhlIHBhc3NlZCBvYmplY3QgaXMKICAgIG5vdCBmb3JtYWxseSBhbiBhcnJheSBidXQgYXBwZWFycyB0byBiZSBhcnJheS1saWtlIChpLmUuIGltcGxlbWVudHMgYEFycmF5YCkKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGlzQXJyYXkgfSBmcm9tICdAZW1iZXIvYXJyYXknOwogICAgaW1wb3J0IEFycmF5UHJveHkgZnJvbSAnQGVtYmVyL2FycmF5L3Byb3h5JzsKICAKICAgIGlzQXJyYXkoKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZhbHNlCiAgICBpc0FycmF5KFtdKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0cnVlCiAgICBpc0FycmF5KEFycmF5UHJveHkuY3JlYXRlKHsgY29udGVudDogW10gfSkpOyAgICAvLyB0cnVlCiAgICBgYGAKICAKICAgIEBtZXRob2QgaXNBcnJheQogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvYXJyYXkKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byB0ZXN0CiAgICBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHRoZSBwYXNzZWQgb2JqZWN0IGlzIGFuIGFycmF5IG9yIEFycmF5LWxpa2UKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gaXNBcnJheShfb2JqKSB7CiAgICB2YXIgb2JqID0gX29iajsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICAmJiBfdXRpbHMuSEFTX05BVElWRV9QUk9YWSAmJiB0eXBlb2YgX29iaiA9PT0gJ29iamVjdCcgJiYgX29iaiAhPT0gbnVsbCkgewogICAgICB2YXIgcG9zc2libGVQcm94eUNvbnRlbnQgPSBfb2JqW19tZXRhbC5QUk9YWV9DT05URU5UXTsKCiAgICAgIGlmIChwb3NzaWJsZVByb3h5Q29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgb2JqID0gcG9zc2libGVQcm94eUNvbnRlbnQ7CiAgICAgIH0KICAgIH0KCiAgICBpZiAoIW9iaiB8fCBvYmouc2V0SW50ZXJ2YWwpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikgfHwgQXJyYXlNaXhpbi5kZXRlY3Qob2JqKSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICB2YXIgdHlwZSA9ICgwLCBfdHlwZU9mLnR5cGVPZikob2JqKTsKCiAgICBpZiAoJ2FycmF5JyA9PT0gdHlwZSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICB2YXIgbGVuZ3RoID0gb2JqLmxlbmd0aDsKCiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PT0gJ251bWJlcicgJiYgbGVuZ3RoID09PSBsZW5ndGggJiYgJ29iamVjdCcgPT09IHR5cGUpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgcmV0dXJuIGZhbHNlOwogIH0KICAvKgogICAgVGhpcyBhbGxvd3MgdXMgdG8gZGVmaW5lIGNvbXB1dGVkIHByb3BlcnRpZXMgdGhhdCBhcmUgbm90IGVudW1lcmFibGUuCiAgICBUaGUgcHJpbWFyeSByZWFzb24gdGhpcyBpcyBpbXBvcnRhbnQgaXMgdGhhdCB3aGVuIGBOYXRpdmVBcnJheWAgaXMKICAgIGFwcGxpZWQgdG8gYEFycmF5LnByb3RvdHlwZWAgd2UgbmVlZCB0byBlbnN1cmUgdGhhdCB3ZSBkbyBub3QgYWRkIF9hbnlfCiAgICBuZXcgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLgogICovCgoKICBmdW5jdGlvbiBub25FbnVtZXJhYmxlQ29tcHV0ZWQoKSB7CiAgICB2YXIgcHJvcGVydHkgPSBfbWV0YWwuY29tcHV0ZWQuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpOwoKICAgIHByb3BlcnR5LmVudW1lcmFibGUgPSBmYWxzZTsKICAgIHJldHVybiBwcm9wZXJ0eTsKICB9CgogIGZ1bmN0aW9uIG1hcEJ5KGtleSkgewogICAgcmV0dXJuIHRoaXMubWFwKGZ1bmN0aW9uIChuZXh0KSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkobmV4dCwga2V5KTsKICAgIH0pOwogIH0gLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogIC8vIEFSUkFZCiAgLy8KCiAgLyoqCiAgICBUaGlzIG1peGluIGltcGxlbWVudHMgT2JzZXJ2ZXItZnJpZW5kbHkgQXJyYXktbGlrZSBiZWhhdmlvci4gSXQgaXMgbm90IGEKICAgIGNvbmNyZXRlIGltcGxlbWVudGF0aW9uLCBidXQgaXQgY2FuIGJlIHVzZWQgdXAgYnkgb3RoZXIgY2xhc3NlcyB0aGF0IHdhbnQKICAgIHRvIGFwcGVhciBsaWtlIGFycmF5cy4KICAKICAgIEZvciBleGFtcGxlLCBBcnJheVByb3h5IGlzIGEgY29uY3JldGUgY2xhc3NlcyB0aGF0IGNhbgogICAgYmUgaW5zdGFudGlhdGVkIHRvIGltcGxlbWVudCBhcnJheS1saWtlIGJlaGF2aW9yLiBCb3RoIG9mIHRoZXNlIGNsYXNzZXMgdXNlCiAgICB0aGUgQXJyYXkgTWl4aW4gYnkgd2F5IG9mIHRoZSBNdXRhYmxlQXJyYXkgbWl4aW4sIHdoaWNoIGFsbG93cyBvYnNlcnZhYmxlCiAgICBjaGFuZ2VzIHRvIGJlIG1hZGUgdG8gdGhlIHVuZGVybHlpbmcgYXJyYXkuCiAgCiAgICBUaGlzIG1peGluIGRlZmluZXMgbWV0aG9kcyBzcGVjaWZpY2FsbHkgZm9yIGNvbGxlY3Rpb25zIHRoYXQgcHJvdmlkZQogICAgaW5kZXgtb3JkZXJlZCBhY2Nlc3MgdG8gdGhlaXIgY29udGVudHMuIFdoZW4geW91IGFyZSBkZXNpZ25pbmcgY29kZSB0aGF0CiAgICBuZWVkcyB0byBhY2NlcHQgYW55IGtpbmQgb2YgQXJyYXktbGlrZSBvYmplY3QsIHlvdSBzaG91bGQgdXNlIHRoZXNlIG1ldGhvZHMKICAgIGluc3RlYWQgb2YgQXJyYXkgcHJpbWl0aXZlcyBiZWNhdXNlIHRoZXNlIHdpbGwgcHJvcGVybHkgbm90aWZ5IG9ic2VydmVycyBvZgogICAgY2hhbmdlcyB0byB0aGUgYXJyYXkuCiAgCiAgICBBbHRob3VnaCB0aGVzZSBtZXRob2RzIGFyZSBlZmZpY2llbnQsIHRoZXkgZG8gYWRkIGEgbGF5ZXIgb2YgaW5kaXJlY3Rpb24gdG8KICAgIHlvdXIgYXBwbGljYXRpb24gc28gaXQgaXMgYSBnb29kIGlkZWEgdG8gdXNlIHRoZW0gb25seSB3aGVuIHlvdSBuZWVkIHRoZQogICAgZmxleGliaWxpdHkgb2YgdXNpbmcgYm90aCB0cnVlIEphdmFTY3JpcHQgYXJyYXlzIGFuZCAidmlydHVhbCIgYXJyYXlzIHN1Y2gKICAgIGFzIGNvbnRyb2xsZXJzIGFuZCBjb2xsZWN0aW9ucy4KICAKICAgIFlvdSBjYW4gdXNlIHRoZSBtZXRob2RzIGRlZmluZWQgaW4gdGhpcyBtb2R1bGUgdG8gYWNjZXNzIGFuZCBtb2RpZnkgYXJyYXkKICAgIGNvbnRlbnRzIGluIGEgS1ZPLWZyaWVuZGx5IHdheS4gWW91IGNhbiBhbHNvIGJlIG5vdGlmaWVkIHdoZW5ldmVyIHRoZQogICAgbWVtYmVyc2hpcCBvZiBhbiBhcnJheSBjaGFuZ2VzIGJ5IHVzaW5nIGAub2JzZXJ2ZXMoJ215QXJyYXkuW10nKWAuCiAgCiAgICBUbyBzdXBwb3J0IGBFbWJlckFycmF5YCBpbiB5b3VyIG93biBjbGFzcywgeW91IG11c3Qgb3ZlcnJpZGUgdHdvCiAgICBwcmltaXRpdmVzIHRvIHVzZSBpdDogYGxlbmd0aCgpYCBhbmQgYG9iamVjdEF0KClgLgogIAogICAgQGNsYXNzIEVtYmVyQXJyYXkKICAgIEB1c2VzIEVudW1lcmFibGUKICAgIEBzaW5jZSBFbWJlciAwLjkuMAogICAgQHB1YmxpYwogICovCgoKICB2YXIgQXJyYXlNaXhpbiA9IF9tZXRhbC5NaXhpbi5jcmVhdGUoX2VudW1lcmFibGUuZGVmYXVsdCwgKF9NaXhpbiRjcmVhdGUgPSB7fSwgX01peGluJGNyZWF0ZVtfdXRpbHMuRU1CRVJfQVJSQVldID0gdHJ1ZSwgX01peGluJGNyZWF0ZS5vYmplY3RzQXQgPSBmdW5jdGlvbiBvYmplY3RzQXQoaW5kZXhlcykgewogICAgdmFyIF90aGlzID0gdGhpczsKCiAgICByZXR1cm4gaW5kZXhlcy5tYXAoZnVuY3Rpb24gKGlkeCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5vYmplY3RBdCkoX3RoaXMsIGlkeCk7CiAgICB9KTsKICB9LCBfTWl4aW4kY3JlYXRlWydbXSddID0gbm9uRW51bWVyYWJsZUNvbXB1dGVkKHsKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH0sCiAgICBzZXQ6IGZ1bmN0aW9uIHNldChrZXksIHZhbHVlKSB7CiAgICAgIHRoaXMucmVwbGFjZSgwLCB0aGlzLmxlbmd0aCwgdmFsdWUpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0KICB9KSwgX01peGluJGNyZWF0ZS5maXJzdE9iamVjdCA9IG5vbkVudW1lcmFibGVDb21wdXRlZChmdW5jdGlvbiAoKSB7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5vYmplY3RBdCkodGhpcywgMCk7CiAgfSkucmVhZE9ubHkoKSwgX01peGluJGNyZWF0ZS5sYXN0T2JqZWN0ID0gbm9uRW51bWVyYWJsZUNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgIHJldHVybiAoMCwgX21ldGFsLm9iamVjdEF0KSh0aGlzLCB0aGlzLmxlbmd0aCAtIDEpOwogIH0pLnJlYWRPbmx5KCksIF9NaXhpbiRjcmVhdGUuc2xpY2UgPSBmdW5jdGlvbiBzbGljZShiZWdpbkluZGV4LCBlbmRJbmRleCkgewogICAgaWYgKGJlZ2luSW5kZXggPT09IHZvaWQgMCkgewogICAgICBiZWdpbkluZGV4ID0gMDsKICAgIH0KCiAgICB2YXIgcmV0ID0gX0EyKCk7CgogICAgdmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoOwoKICAgIGlmIChiZWdpbkluZGV4IDwgMCkgewogICAgICBiZWdpbkluZGV4ID0gbGVuZ3RoICsgYmVnaW5JbmRleDsKICAgIH0KCiAgICBpZiAoZW5kSW5kZXggPT09IHVuZGVmaW5lZCB8fCBlbmRJbmRleCA+IGxlbmd0aCkgewogICAgICBlbmRJbmRleCA9IGxlbmd0aDsKICAgIH0gZWxzZSBpZiAoZW5kSW5kZXggPCAwKSB7CiAgICAgIGVuZEluZGV4ID0gbGVuZ3RoICsgZW5kSW5kZXg7CiAgICB9CgogICAgd2hpbGUgKGJlZ2luSW5kZXggPCBlbmRJbmRleCkgewogICAgICByZXRbcmV0Lmxlbmd0aF0gPSAoMCwgX21ldGFsLm9iamVjdEF0KSh0aGlzLCBiZWdpbkluZGV4KyspOwogICAgfQoKICAgIHJldHVybiByZXQ7CiAgfSwgX01peGluJGNyZWF0ZS5pbmRleE9mID0gZnVuY3Rpb24gaW5kZXhPZihvYmplY3QsIHN0YXJ0QXQpIHsKICAgIHJldHVybiBfaW5kZXhPZih0aGlzLCBvYmplY3QsIHN0YXJ0QXQsIGZhbHNlKTsKICB9LCBfTWl4aW4kY3JlYXRlLmxhc3RJbmRleE9mID0gZnVuY3Rpb24gbGFzdEluZGV4T2Yob2JqZWN0LCBzdGFydEF0KSB7CiAgICB2YXIgbGVuID0gdGhpcy5sZW5ndGg7CgogICAgaWYgKHN0YXJ0QXQgPT09IHVuZGVmaW5lZCB8fCBzdGFydEF0ID49IGxlbikgewogICAgICBzdGFydEF0ID0gbGVuIC0gMTsKICAgIH0KCiAgICBpZiAoc3RhcnRBdCA8IDApIHsKICAgICAgc3RhcnRBdCArPSBsZW47CiAgICB9CgogICAgZm9yICh2YXIgaWR4ID0gc3RhcnRBdDsgaWR4ID49IDA7IGlkeC0tKSB7CiAgICAgIGlmICgoMCwgX21ldGFsLm9iamVjdEF0KSh0aGlzLCBpZHgpID09PSBvYmplY3QpIHsKICAgICAgICByZXR1cm4gaWR4OwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIC0xOwogIH0sIF9NaXhpbiRjcmVhdGUuYWRkQXJyYXlPYnNlcnZlciA9IGZ1bmN0aW9uIGFkZEFycmF5T2JzZXJ2ZXIodGFyZ2V0LCBvcHRzKSB7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5hZGRBcnJheU9ic2VydmVyKSh0aGlzLCB0YXJnZXQsIG9wdHMpOwogIH0sIF9NaXhpbiRjcmVhdGUucmVtb3ZlQXJyYXlPYnNlcnZlciA9IGZ1bmN0aW9uIHJlbW92ZUFycmF5T2JzZXJ2ZXIodGFyZ2V0LCBvcHRzKSB7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5yZW1vdmVBcnJheU9ic2VydmVyKSh0aGlzLCB0YXJnZXQsIG9wdHMpOwogIH0sIF9NaXhpbiRjcmVhdGUuaGFzQXJyYXlPYnNlcnZlcnMgPSBub25FbnVtZXJhYmxlQ29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgcmV0dXJuICgwLCBfbWV0YWwuaGFzTGlzdGVuZXJzKSh0aGlzLCAnQGFycmF5OmNoYW5nZScpIHx8ICgwLCBfbWV0YWwuaGFzTGlzdGVuZXJzKSh0aGlzLCAnQGFycmF5OmJlZm9yZScpOwogIH0pLCBfTWl4aW4kY3JlYXRlLmFycmF5Q29udGVudFdpbGxDaGFuZ2UgPSBmdW5jdGlvbiBhcnJheUNvbnRlbnRXaWxsQ2hhbmdlKHN0YXJ0SWR4LCByZW1vdmVBbXQsIGFkZEFtdCkgewogICAgcmV0dXJuICgwLCBfbWV0YWwuYXJyYXlDb250ZW50V2lsbENoYW5nZSkodGhpcywgc3RhcnRJZHgsIHJlbW92ZUFtdCwgYWRkQW10KTsKICB9LCBfTWl4aW4kY3JlYXRlLmFycmF5Q29udGVudERpZENoYW5nZSA9IGZ1bmN0aW9uIGFycmF5Q29udGVudERpZENoYW5nZShzdGFydElkeCwgcmVtb3ZlQW10LCBhZGRBbXQpIHsKICAgIHJldHVybiAoMCwgX21ldGFsLmFycmF5Q29udGVudERpZENoYW5nZSkodGhpcywgc3RhcnRJZHgsIHJlbW92ZUFtdCwgYWRkQW10KTsKICB9LCBfTWl4aW4kY3JlYXRlLmZvckVhY2ggPSBmdW5jdGlvbiBmb3JFYWNoKGNhbGxiYWNrLCB0YXJnZXQpIHsKICAgIGlmICh0YXJnZXQgPT09IHZvaWQgMCkgewogICAgICB0YXJnZXQgPSBudWxsOwogICAgfQoKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdgZm9yRWFjaGAgZXhwZWN0cyBhIGZ1bmN0aW9uIGFzIGZpcnN0IGFyZ3VtZW50LicsIHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykpOwogICAgdmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoOwoKICAgIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHsKICAgICAgdmFyIGl0ZW0gPSB0aGlzLm9iamVjdEF0KGluZGV4KTsKICAgICAgY2FsbGJhY2suY2FsbCh0YXJnZXQsIGl0ZW0sIGluZGV4LCB0aGlzKTsKICAgIH0KCiAgICByZXR1cm4gdGhpczsKICB9LCBfTWl4aW4kY3JlYXRlLmdldEVhY2ggPSBtYXBCeSwgX01peGluJGNyZWF0ZS5zZXRFYWNoID0gZnVuY3Rpb24gc2V0RWFjaChrZXksIHZhbHVlKSB7CiAgICByZXR1cm4gdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLnNldCkoaXRlbSwga2V5LCB2YWx1ZSk7CiAgICB9KTsKICB9LCBfTWl4aW4kY3JlYXRlLm1hcCA9IGZ1bmN0aW9uIG1hcChjYWxsYmFjaywgdGFyZ2V0KSB7CiAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgdGFyZ2V0ID0gbnVsbDsKICAgIH0KCiAgICAoZmFsc2UgJiYgISh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYG1hcGAgZXhwZWN0cyBhIGZ1bmN0aW9uIGFzIGZpcnN0IGFyZ3VtZW50LicsIHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykpOwoKICAgIHZhciByZXQgPSBfQTIoKTsKCiAgICB0aGlzLmZvckVhY2goZnVuY3Rpb24gKHgsIGlkeCwgaSkgewogICAgICByZXR1cm4gcmV0W2lkeF0gPSBjYWxsYmFjay5jYWxsKHRhcmdldCwgeCwgaWR4LCBpKTsKICAgIH0pOwogICAgcmV0dXJuIHJldDsKICB9LCBfTWl4aW4kY3JlYXRlLm1hcEJ5ID0gbWFwQnksIF9NaXhpbiRjcmVhdGUuZmlsdGVyID0gZnVuY3Rpb24gZmlsdGVyKGNhbGxiYWNrLCB0YXJnZXQpIHsKICAgIGlmICh0YXJnZXQgPT09IHZvaWQgMCkgewogICAgICB0YXJnZXQgPSBudWxsOwogICAgfQoKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdgZmlsdGVyYCBleHBlY3RzIGEgZnVuY3Rpb24gYXMgZmlyc3QgYXJndW1lbnQuJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CgogICAgdmFyIHJldCA9IF9BMigpOwoKICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbiAoeCwgaWR4LCBpKSB7CiAgICAgIGlmIChjYWxsYmFjay5jYWxsKHRhcmdldCwgeCwgaWR4LCBpKSkgewogICAgICAgIHJldC5wdXNoKHgpOwogICAgICB9CiAgICB9KTsKICAgIHJldHVybiByZXQ7CiAgfSwgX01peGluJGNyZWF0ZS5yZWplY3QgPSBmdW5jdGlvbiByZWplY3QoY2FsbGJhY2ssIHRhcmdldCkgewogICAgaWYgKHRhcmdldCA9PT0gdm9pZCAwKSB7CiAgICAgIHRhcmdldCA9IG51bGw7CiAgICB9CgogICAgKGZhbHNlICYmICEodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2ByZWplY3RgIGV4cGVjdHMgYSBmdW5jdGlvbiBhcyBmaXJzdCBhcmd1bWVudC4nLCB0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpKTsKICAgIHJldHVybiB0aGlzLmZpbHRlcihmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAhY2FsbGJhY2suYXBwbHkodGFyZ2V0LCBhcmd1bWVudHMpOwogICAgfSk7CiAgfSwgX01peGluJGNyZWF0ZS5maWx0ZXJCeSA9IGZ1bmN0aW9uIGZpbHRlckJ5KCkgewogICAgcmV0dXJuIHRoaXMuZmlsdGVyKGl0ZXIuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpKTsKICB9LCBfTWl4aW4kY3JlYXRlLnJlamVjdEJ5ID0gZnVuY3Rpb24gcmVqZWN0QnkoKSB7CiAgICByZXR1cm4gdGhpcy5yZWplY3QoaXRlci5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cykpOwogIH0sIF9NaXhpbiRjcmVhdGUuZmluZCA9IGZ1bmN0aW9uIGZpbmQoY2FsbGJhY2ssIHRhcmdldCkgewogICAgaWYgKHRhcmdldCA9PT0gdm9pZCAwKSB7CiAgICAgIHRhcmdldCA9IG51bGw7CiAgICB9CgogICAgKGZhbHNlICYmICEodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2BmaW5kYCBleHBlY3RzIGEgZnVuY3Rpb24gYXMgZmlyc3QgYXJndW1lbnQuJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICByZXR1cm4gX2ZpbmQodGhpcywgY2FsbGJhY2ssIHRhcmdldCk7CiAgfSwgX01peGluJGNyZWF0ZS5maW5kQnkgPSBmdW5jdGlvbiBmaW5kQnkoKSB7CiAgICByZXR1cm4gX2ZpbmQodGhpcywgaXRlci5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cykpOwogIH0sIF9NaXhpbiRjcmVhdGUuZXZlcnkgPSBmdW5jdGlvbiBldmVyeShjYWxsYmFjaywgdGFyZ2V0KSB7CiAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgdGFyZ2V0ID0gbnVsbDsKICAgIH0KCiAgICAoZmFsc2UgJiYgISh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYGV2ZXJ5YCBleHBlY3RzIGEgZnVuY3Rpb24gYXMgZmlyc3QgYXJndW1lbnQuJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICByZXR1cm4gX2V2ZXJ5KHRoaXMsIGNhbGxiYWNrLCB0YXJnZXQpOwogIH0sIF9NaXhpbiRjcmVhdGUuaXNFdmVyeSA9IGZ1bmN0aW9uIGlzRXZlcnkoKSB7CiAgICByZXR1cm4gX2V2ZXJ5KHRoaXMsIGl0ZXIuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpKTsKICB9LCBfTWl4aW4kY3JlYXRlLmFueSA9IGZ1bmN0aW9uIGFueShjYWxsYmFjaywgdGFyZ2V0KSB7CiAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgdGFyZ2V0ID0gbnVsbDsKICAgIH0KCiAgICAoZmFsc2UgJiYgISh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYGFueWAgZXhwZWN0cyBhIGZ1bmN0aW9uIGFzIGZpcnN0IGFyZ3VtZW50LicsIHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykpOwogICAgcmV0dXJuIF9hbnkodGhpcywgY2FsbGJhY2ssIHRhcmdldCk7CiAgfSwgX01peGluJGNyZWF0ZS5pc0FueSA9IGZ1bmN0aW9uIGlzQW55KCkgewogICAgcmV0dXJuIF9hbnkodGhpcywgaXRlci5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cykpOwogIH0sIF9NaXhpbiRjcmVhdGUucmVkdWNlID0gZnVuY3Rpb24gcmVkdWNlKGNhbGxiYWNrLCBpbml0aWFsVmFsdWUpIHsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdgcmVkdWNlYCBleHBlY3RzIGEgZnVuY3Rpb24gYXMgZmlyc3QgYXJndW1lbnQuJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICB2YXIgcmV0ID0gaW5pdGlhbFZhbHVlOwogICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtLCBpKSB7CiAgICAgIHJldCA9IGNhbGxiYWNrKHJldCwgaXRlbSwgaSwgdGhpcyk7CiAgICB9LCB0aGlzKTsKICAgIHJldHVybiByZXQ7CiAgfSwgX01peGluJGNyZWF0ZS5pbnZva2UgPSBmdW5jdGlvbiBpbnZva2UobWV0aG9kTmFtZSkgewogICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5ID0gMTsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICBhcmdzW19rZXkgLSAxXSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgIH0KCiAgICB2YXIgcmV0ID0gX0EyKCk7CgogICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgIHJldHVybiByZXQucHVzaCgoMCwgX3V0aWxzLnRyeUludm9rZSkoaXRlbSwgbWV0aG9kTmFtZSwgYXJncykpOwogICAgfSk7CiAgICByZXR1cm4gcmV0OwogIH0sIF9NaXhpbiRjcmVhdGUudG9BcnJheSA9IGZ1bmN0aW9uIHRvQXJyYXkoKSB7CiAgICByZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24gKGl0ZW0pIHsKICAgICAgcmV0dXJuIGl0ZW07CiAgICB9KTsKICB9LCBfTWl4aW4kY3JlYXRlLmNvbXBhY3QgPSBmdW5jdGlvbiBjb21wYWN0KCkgewogICAgcmV0dXJuIHRoaXMuZmlsdGVyKGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICByZXR1cm4gdmFsdWUgIT0gbnVsbDsKICAgIH0pOwogIH0sIF9NaXhpbiRjcmVhdGUuaW5jbHVkZXMgPSBmdW5jdGlvbiBpbmNsdWRlcyhvYmplY3QsIHN0YXJ0QXQpIHsKICAgIHJldHVybiBfaW5kZXhPZih0aGlzLCBvYmplY3QsIHN0YXJ0QXQsIHRydWUpICE9PSAtMTsKICB9LCBfTWl4aW4kY3JlYXRlLnNvcnRCeSA9IGZ1bmN0aW9uIHNvcnRCeSgpIHsKICAgIHZhciBzb3J0S2V5cyA9IGFyZ3VtZW50czsKICAgIHJldHVybiB0aGlzLnRvQXJyYXkoKS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc29ydEtleXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIga2V5ID0gc29ydEtleXNbaV07CiAgICAgICAgdmFyIHByb3BBID0gKDAsIF9tZXRhbC5nZXQpKGEsIGtleSk7CiAgICAgICAgdmFyIHByb3BCID0gKDAsIF9tZXRhbC5nZXQpKGIsIGtleSk7IC8vIHJldHVybiAxIG9yIC0xIGVsc2UgY29udGludWUgdG8gdGhlIG5leHQgc29ydEtleQoKICAgICAgICB2YXIgY29tcGFyZVZhbHVlID0gKDAsIF9jb21wYXJlLmRlZmF1bHQpKHByb3BBLCBwcm9wQik7CgogICAgICAgIGlmIChjb21wYXJlVmFsdWUpIHsKICAgICAgICAgIHJldHVybiBjb21wYXJlVmFsdWU7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gMDsKICAgIH0pOwogIH0sIF9NaXhpbiRjcmVhdGUudW5pcSA9IGZ1bmN0aW9uIHVuaXEoKSB7CiAgICByZXR1cm4gX3VuaXFCeSh0aGlzKTsKICB9LCBfTWl4aW4kY3JlYXRlLnVuaXFCeSA9IGZ1bmN0aW9uIHVuaXFCeShrZXkpIHsKICAgIHJldHVybiBfdW5pcUJ5KHRoaXMsIGtleSk7CiAgfSwgX01peGluJGNyZWF0ZS53aXRob3V0ID0gZnVuY3Rpb24gd2l0aG91dCh2YWx1ZSkgewogICAgaWYgKCF0aGlzLmluY2x1ZGVzKHZhbHVlKSkgewogICAgICByZXR1cm4gdGhpczsgLy8gbm90aGluZyB0byBkbwogICAgfSAvLyBTYW1lVmFsdWVaZXJvIGNvbXBhcmlzb24gKE5hTiAhPT0gTmFOKQoKCiAgICB2YXIgcHJlZGljYXRlID0gdmFsdWUgPT09IHZhbHVlID8gZnVuY3Rpb24gKGl0ZW0pIHsKICAgICAgcmV0dXJuIGl0ZW0gIT09IHZhbHVlOwogICAgfSA6IGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgIHJldHVybiBpdGVtID09PSBpdGVtOwogICAgfTsKICAgIHJldHVybiB0aGlzLmZpbHRlcihwcmVkaWNhdGUpOwogIH0sIF9NaXhpbiRjcmVhdGUpKTsKICAvKioKICAgIFRoaXMgbWl4aW4gZGVmaW5lcyB0aGUgQVBJIGZvciBtb2RpZnlpbmcgYXJyYXktbGlrZSBvYmplY3RzLiBUaGVzZSBtZXRob2RzCiAgICBjYW4gYmUgYXBwbGllZCBvbmx5IHRvIGEgY29sbGVjdGlvbiB0aGF0IGtlZXBzIGl0cyBpdGVtcyBpbiBhbiBvcmRlcmVkIHNldC4KICAgIEl0IGJ1aWxkcyB1cG9uIHRoZSBBcnJheSBtaXhpbiBhbmQgYWRkcyBtZXRob2RzIHRvIG1vZGlmeSB0aGUgYXJyYXkuCiAgICBPbmUgY29uY3JldGUgaW1wbGVtZW50YXRpb25zIG9mIHRoaXMgY2xhc3MgaW5jbHVkZSBBcnJheVByb3h5LgogIAogICAgSXQgaXMgaW1wb3J0YW50IHRvIHVzZSB0aGUgbWV0aG9kcyBpbiB0aGlzIGNsYXNzIHRvIG1vZGlmeSBhcnJheXMgc28gdGhhdAogICAgY2hhbmdlcyBhcmUgb2JzZXJ2YWJsZS4gVGhpcyBhbGxvd3MgdGhlIGJpbmRpbmcgc3lzdGVtIGluIEVtYmVyIHRvIGZ1bmN0aW9uCiAgICBjb3JyZWN0bHkuCiAgCiAgCiAgICBOb3RlIHRoYXQgYW4gQXJyYXkgY2FuIGNoYW5nZSBldmVuIGlmIGl0IGRvZXMgbm90IGltcGxlbWVudCB0aGlzIG1peGluLgogICAgRm9yIGV4YW1wbGUsIG9uZSBtaWdodCBpbXBsZW1lbnQgYSBTcGFyc2VBcnJheSB0aGF0IGNhbm5vdCBiZSBkaXJlY3RseQogICAgbW9kaWZpZWQsIGJ1dCBpZiBpdHMgdW5kZXJseWluZyBlbnVtZXJhYmxlIGNoYW5nZXMsIGl0IHdpbGwgY2hhbmdlIGFsc28uCiAgCiAgICBAY2xhc3MgTXV0YWJsZUFycmF5CiAgICBAdXNlcyBFbWJlckFycmF5CiAgICBAdXNlcyBNdXRhYmxlRW51bWVyYWJsZQogICAgQHB1YmxpYwogICovCgoKICB2YXIgTXV0YWJsZUFycmF5ID0gX21ldGFsLk1peGluLmNyZWF0ZShBcnJheU1peGluLCBfbXV0YWJsZV9lbnVtZXJhYmxlLmRlZmF1bHQsIHsKICAgIC8qKgogICAgICBfX1JlcXVpcmVkLl9fIFlvdSBtdXN0IGltcGxlbWVudCB0aGlzIG1ldGhvZCB0byBhcHBseSB0aGlzIG1peGluLgogICAgICAgVGhpcyBpcyBvbmUgb2YgdGhlIHByaW1pdGl2ZXMgeW91IG11c3QgaW1wbGVtZW50IHRvIHN1cHBvcnQgYEFycmF5YC4KICAgICAgWW91IHNob3VsZCByZXBsYWNlIGFtdCBvYmplY3RzIHN0YXJ0ZWQgYXQgaWR4IHdpdGggdGhlIG9iamVjdHMgaW4gdGhlCiAgICAgIHBhc3NlZCBhcnJheS4gWW91IHNob3VsZCBhbHNvIGNhbGwgYHRoaXMuYXJyYXlDb250ZW50RGlkQ2hhbmdlKClgCiAgICAgICBOb3RlIHRoYXQgdGhpcyBtZXRob2QgaXMgZXhwZWN0ZWQgdG8gdmFsaWRhdGUgdGhlIHR5cGUocykgb2Ygb2JqZWN0cyB0aGF0IGl0IGV4cGVjdHMuCiAgICAgICBAbWV0aG9kIHJlcGxhY2UKICAgICAgQHBhcmFtIHtOdW1iZXJ9IGlkeCBTdGFydGluZyBpbmRleCBpbiB0aGUgYXJyYXkgdG8gcmVwbGFjZS4gSWYKICAgICAgICBpZHggPj0gbGVuZ3RoLCB0aGVuIGFwcGVuZCB0byB0aGUgZW5kIG9mIHRoZSBhcnJheS4KICAgICAgQHBhcmFtIHtOdW1iZXJ9IGFtdCBOdW1iZXIgb2YgZWxlbWVudHMgdGhhdCBzaG91bGQgYmUgcmVtb3ZlZCBmcm9tCiAgICAgICAgdGhlIGFycmF5LCBzdGFydGluZyBhdCAqaWR4Ki4KICAgICAgQHBhcmFtIHtFbWJlckFycmF5fSBvYmplY3RzIEFuIGFycmF5IG9mIHplcm8gb3IgbW9yZSBvYmplY3RzIHRoYXQgc2hvdWxkIGJlCiAgICAgICAgaW5zZXJ0ZWQgaW50byB0aGUgYXJyYXkgYXQgKmlkeCoKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgUmVtb3ZlIGFsbCBlbGVtZW50cyBmcm9tIHRoZSBhcnJheS4gVGhpcyBpcyB1c2VmdWwgaWYgeW91CiAgICAgIHdhbnQgdG8gcmV1c2UgYW4gZXhpc3RpbmcgYXJyYXkgd2l0aG91dCBoYXZpbmcgdG8gcmVjcmVhdGUgaXQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjb2xvcnMgPSBbJ3JlZCcsICdncmVlbicsICdibHVlJ107CiAgICAgICBjb2xvcnMubGVuZ3RoOyAgLy8gMwogICAgICBjb2xvcnMuY2xlYXIoKTsgLy8gW10KICAgICAgY29sb3JzLmxlbmd0aDsgIC8vIDAKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGNsZWFyCiAgICAgIEByZXR1cm4ge0FycmF5fSBBbiBlbXB0eSBBcnJheS4KICAgICAgQHB1YmxpYwogICAgKi8KICAgIGNsZWFyOiBmdW5jdGlvbiBjbGVhcigpIHsKICAgICAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoOwoKICAgICAgaWYgKGxlbiA9PT0gMCkgewogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICB0aGlzLnJlcGxhY2UoMCwgbGVuLCBFTVBUWV9BUlJBWSk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgVGhpcyB3aWxsIHVzZSB0aGUgcHJpbWl0aXZlIGByZXBsYWNlKClgIG1ldGhvZCB0byBpbnNlcnQgYW4gb2JqZWN0IGF0IHRoZQogICAgICBzcGVjaWZpZWQgaW5kZXguCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjb2xvcnMgPSBbJ3JlZCcsICdncmVlbicsICdibHVlJ107CiAgICAgICBjb2xvcnMuaW5zZXJ0QXQoMiwgJ3llbGxvdycpOyAgLy8gWydyZWQnLCAnZ3JlZW4nLCAneWVsbG93JywgJ2JsdWUnXQogICAgICBjb2xvcnMuaW5zZXJ0QXQoNSwgJ29yYW5nZScpOyAgLy8gRXJyb3I6IEluZGV4IG91dCBvZiByYW5nZQogICAgICBgYGAKICAgICAgIEBtZXRob2QgaW5zZXJ0QXQKICAgICAgQHBhcmFtIHtOdW1iZXJ9IGlkeCBpbmRleCBvZiBpbnNlcnQgdGhlIG9iamVjdCBhdC4KICAgICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdCBvYmplY3QgdG8gaW5zZXJ0CiAgICAgIEByZXR1cm4ge0VtYmVyQXJyYXl9IHJlY2VpdmVyCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBpbnNlcnRBdDogZnVuY3Rpb24gaW5zZXJ0QXQoaWR4LCBvYmplY3QpIHsKICAgICAgX2luc2VydEF0KHRoaXMsIGlkeCwgb2JqZWN0KTsKCiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgUmVtb3ZlIGFuIG9iamVjdCBhdCB0aGUgc3BlY2lmaWVkIGluZGV4IHVzaW5nIHRoZSBgcmVwbGFjZSgpYCBwcmltaXRpdmUKICAgICAgbWV0aG9kLiBZb3UgY2FuIHBhc3MgZWl0aGVyIGEgc2luZ2xlIGluZGV4LCBvciBhIHN0YXJ0IGFuZCBhIGxlbmd0aC4KICAgICAgIElmIHlvdSBwYXNzIGEgc3RhcnQgYW5kIGxlbmd0aCB0aGF0IGlzIGJleW9uZCB0aGUKICAgICAgbGVuZ3RoIHRoaXMgbWV0aG9kIHdpbGwgdGhyb3cgYW4gYXNzZXJ0aW9uLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgY29sb3JzID0gWydyZWQnLCAnZ3JlZW4nLCAnYmx1ZScsICd5ZWxsb3cnLCAnb3JhbmdlJ107CiAgICAgICBjb2xvcnMucmVtb3ZlQXQoMCk7ICAgICAvLyBbJ2dyZWVuJywgJ2JsdWUnLCAneWVsbG93JywgJ29yYW5nZSddCiAgICAgIGNvbG9ycy5yZW1vdmVBdCgyLCAyKTsgIC8vIFsnZ3JlZW4nLCAnYmx1ZSddCiAgICAgIGNvbG9ycy5yZW1vdmVBdCg0LCAyKTsgIC8vIEVycm9yOiBJbmRleCBvdXQgb2YgcmFuZ2UKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHJlbW92ZUF0CiAgICAgIEBwYXJhbSB7TnVtYmVyfSBzdGFydCBpbmRleCwgc3RhcnQgb2YgcmFuZ2UKICAgICAgQHBhcmFtIHtOdW1iZXJ9IGxlbiBsZW5ndGggb2YgcGFzc2luZyByYW5nZQogICAgICBAcmV0dXJuIHtFbWJlckFycmF5fSByZWNlaXZlcgogICAgICBAcHVibGljCiAgICAqLwogICAgcmVtb3ZlQXQ6IGZ1bmN0aW9uIHJlbW92ZUF0KHN0YXJ0LCBsZW4pIHsKICAgICAgcmV0dXJuIF9yZW1vdmVBdCh0aGlzLCBzdGFydCwgbGVuKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFB1c2ggdGhlIG9iamVjdCBvbnRvIHRoZSBlbmQgb2YgdGhlIGFycmF5LiBXb3JrcyBqdXN0IGxpa2UgYHB1c2goKWAgYnV0IGl0CiAgICAgIGlzIEtWTy1jb21wbGlhbnQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjb2xvcnMgPSBbJ3JlZCcsICdncmVlbiddOwogICAgICAgY29sb3JzLnB1c2hPYmplY3QoJ2JsYWNrJyk7ICAgICAvLyBbJ3JlZCcsICdncmVlbicsICdibGFjayddCiAgICAgIGNvbG9ycy5wdXNoT2JqZWN0KFsneWVsbG93J10pOyAgLy8gWydyZWQnLCAnZ3JlZW4nLCBbJ3llbGxvdyddXQogICAgICBgYGAKICAgICAgIEBtZXRob2QgcHVzaE9iamVjdAogICAgICBAcGFyYW0geyp9IG9iaiBvYmplY3QgdG8gcHVzaAogICAgICBAcmV0dXJuIG9iamVjdCBzYW1lIG9iamVjdCBwYXNzZWQgYXMgYSBwYXJhbQogICAgICBAcHVibGljCiAgICAqLwogICAgcHVzaE9iamVjdDogZnVuY3Rpb24gcHVzaE9iamVjdChvYmopIHsKICAgICAgcmV0dXJuIF9pbnNlcnRBdCh0aGlzLCB0aGlzLmxlbmd0aCwgb2JqKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEFkZCB0aGUgb2JqZWN0cyBpbiB0aGUgcGFzc2VkIGFycmF5IHRvIHRoZSBlbmQgb2YgdGhlIGFycmF5LiBEZWZlcnMKICAgICAgbm90aWZ5aW5nIG9ic2VydmVycyBvZiB0aGUgY2hhbmdlIHVudGlsIGFsbCBvYmplY3RzIGFyZSBhZGRlZC4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IGNvbG9ycyA9IFsncmVkJ107CiAgICAgICBjb2xvcnMucHVzaE9iamVjdHMoWyd5ZWxsb3cnLCAnb3JhbmdlJ10pOyAgLy8gWydyZWQnLCAneWVsbG93JywgJ29yYW5nZSddCiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBwdXNoT2JqZWN0cwogICAgICBAcGFyYW0ge0VtYmVyQXJyYXl9IG9iamVjdHMgdGhlIG9iamVjdHMgdG8gYWRkCiAgICAgIEByZXR1cm4ge0VtYmVyQXJyYXl9IHJlY2VpdmVyCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBwdXNoT2JqZWN0czogZnVuY3Rpb24gcHVzaE9iamVjdHMob2JqZWN0cykgewogICAgICB0aGlzLnJlcGxhY2UodGhpcy5sZW5ndGgsIDAsIG9iamVjdHMpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCgogICAgLyoqCiAgICAgIFBvcCBvYmplY3QgZnJvbSBhcnJheSBvciBuaWwgaWYgbm9uZSBhcmUgbGVmdC4gV29ya3MganVzdCBsaWtlIGBwb3AoKWAgYnV0CiAgICAgIGl0IGlzIEtWTy1jb21wbGlhbnQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjb2xvcnMgPSBbJ3JlZCcsICdncmVlbicsICdibHVlJ107CiAgICAgICBjb2xvcnMucG9wT2JqZWN0KCk7ICAgLy8gJ2JsdWUnCiAgICAgIGNvbnNvbGUubG9nKGNvbG9ycyk7ICAvLyBbJ3JlZCcsICdncmVlbiddCiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBwb3BPYmplY3QKICAgICAgQHJldHVybiBvYmplY3QKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHBvcE9iamVjdDogZnVuY3Rpb24gcG9wT2JqZWN0KCkgewogICAgICB2YXIgbGVuID0gdGhpcy5sZW5ndGg7CgogICAgICBpZiAobGVuID09PSAwKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KCiAgICAgIHZhciByZXQgPSAoMCwgX21ldGFsLm9iamVjdEF0KSh0aGlzLCBsZW4gLSAxKTsKICAgICAgdGhpcy5yZW1vdmVBdChsZW4gLSAxLCAxKTsKICAgICAgcmV0dXJuIHJldDsKICAgIH0sCgogICAgLyoqCiAgICAgIFNoaWZ0IGFuIG9iamVjdCBmcm9tIHN0YXJ0IG9mIGFycmF5IG9yIG5pbCBpZiBub25lIGFyZSBsZWZ0LiBXb3JrcyBqdXN0CiAgICAgIGxpa2UgYHNoaWZ0KClgIGJ1dCBpdCBpcyBLVk8tY29tcGxpYW50LgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgY29sb3JzID0gWydyZWQnLCAnZ3JlZW4nLCAnYmx1ZSddOwogICAgICAgY29sb3JzLnNoaWZ0T2JqZWN0KCk7ICAvLyAncmVkJwogICAgICBjb25zb2xlLmxvZyhjb2xvcnMpOyAgIC8vIFsnZ3JlZW4nLCAnYmx1ZSddCiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzaGlmdE9iamVjdAogICAgICBAcmV0dXJuIG9iamVjdAogICAgICBAcHVibGljCiAgICAqLwogICAgc2hpZnRPYmplY3Q6IGZ1bmN0aW9uIHNoaWZ0T2JqZWN0KCkgewogICAgICBpZiAodGhpcy5sZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIHJldCA9ICgwLCBfbWV0YWwub2JqZWN0QXQpKHRoaXMsIDApOwogICAgICB0aGlzLnJlbW92ZUF0KDApOwogICAgICByZXR1cm4gcmV0OwogICAgfSwKCiAgICAvKioKICAgICAgVW5zaGlmdCBhbiBvYmplY3QgdG8gc3RhcnQgb2YgYXJyYXkuIFdvcmtzIGp1c3QgbGlrZSBgdW5zaGlmdCgpYCBidXQgaXQgaXMKICAgICAgS1ZPLWNvbXBsaWFudC4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IGNvbG9ycyA9IFsncmVkJ107CiAgICAgICBjb2xvcnMudW5zaGlmdE9iamVjdCgneWVsbG93Jyk7ICAgIC8vIFsneWVsbG93JywgJ3JlZCddCiAgICAgIGNvbG9ycy51bnNoaWZ0T2JqZWN0KFsnYmxhY2snXSk7ICAgLy8gW1snYmxhY2snXSwgJ3llbGxvdycsICdyZWQnXQogICAgICBgYGAKICAgICAgIEBtZXRob2QgdW5zaGlmdE9iamVjdAogICAgICBAcGFyYW0geyp9IG9iaiBvYmplY3QgdG8gdW5zaGlmdAogICAgICBAcmV0dXJuIG9iamVjdCBzYW1lIG9iamVjdCBwYXNzZWQgYXMgYSBwYXJhbQogICAgICBAcHVibGljCiAgICAqLwogICAgdW5zaGlmdE9iamVjdDogZnVuY3Rpb24gdW5zaGlmdE9iamVjdChvYmopIHsKICAgICAgcmV0dXJuIF9pbnNlcnRBdCh0aGlzLCAwLCBvYmopOwogICAgfSwKCiAgICAvKioKICAgICAgQWRkcyB0aGUgbmFtZWQgb2JqZWN0cyB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBhcnJheS4gRGVmZXJzIG5vdGlmeWluZwogICAgICBvYnNlcnZlcnMgdW50aWwgYWxsIG9iamVjdHMgaGF2ZSBiZWVuIGFkZGVkLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgY29sb3JzID0gWydyZWQnXTsKICAgICAgIGNvbG9ycy51bnNoaWZ0T2JqZWN0cyhbJ2JsYWNrJywgJ3doaXRlJ10pOyAgIC8vIFsnYmxhY2snLCAnd2hpdGUnLCAncmVkJ10KICAgICAgY29sb3JzLnVuc2hpZnRPYmplY3RzKCd5ZWxsb3cnKTsgLy8gVHlwZSBFcnJvcjogJ3VuZGVmaW5lZCcgaXMgbm90IGEgZnVuY3Rpb24KICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHVuc2hpZnRPYmplY3RzCiAgICAgIEBwYXJhbSB7RW51bWJlcmFibGV9IG9iamVjdHMgdGhlIG9iamVjdHMgdG8gYWRkCiAgICAgIEByZXR1cm4ge0VtYmVyQXJyYXl9IHJlY2VpdmVyCiAgICAgIEBwdWJsaWMKICAgICovCiAgICB1bnNoaWZ0T2JqZWN0czogZnVuY3Rpb24gdW5zaGlmdE9iamVjdHMob2JqZWN0cykgewogICAgICB0aGlzLnJlcGxhY2UoMCwgMCwgb2JqZWN0cyk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgUmV2ZXJzZSBvYmplY3RzIGluIHRoZSBhcnJheS4gV29ya3MganVzdCBsaWtlIGByZXZlcnNlKClgIGJ1dCBpdCBpcwogICAgICBLVk8tY29tcGxpYW50LgogICAgICAgQG1ldGhvZCByZXZlcnNlT2JqZWN0cwogICAgICBAcmV0dXJuIHtFbWJlckFycmF5fSByZWNlaXZlcgogICAgICAgQHB1YmxpYwogICAgKi8KICAgIHJldmVyc2VPYmplY3RzOiBmdW5jdGlvbiByZXZlcnNlT2JqZWN0cygpIHsKICAgICAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoOwoKICAgICAgaWYgKGxlbiA9PT0gMCkgewogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICB2YXIgb2JqZWN0cyA9IHRoaXMudG9BcnJheSgpLnJldmVyc2UoKTsKICAgICAgdGhpcy5yZXBsYWNlKDAsIGxlbiwgb2JqZWN0cyk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgUmVwbGFjZSBhbGwgdGhlIHJlY2VpdmVyJ3MgY29udGVudCB3aXRoIGNvbnRlbnQgb2YgdGhlIGFyZ3VtZW50LgogICAgICBJZiBhcmd1bWVudCBpcyBhbiBlbXB0eSBhcnJheSByZWNlaXZlciB3aWxsIGJlIGNsZWFyZWQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjb2xvcnMgPSBbJ3JlZCcsICdncmVlbicsICdibHVlJ107CiAgICAgICBjb2xvcnMuc2V0T2JqZWN0cyhbJ2JsYWNrJywgJ3doaXRlJ10pOyAgLy8gWydibGFjaycsICd3aGl0ZSddCiAgICAgIGNvbG9ycy5zZXRPYmplY3RzKFtdKTsgICAgICAgICAgICAgICAgICAvLyBbXQogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc2V0T2JqZWN0cwogICAgICBAcGFyYW0ge0VtYmVyQXJyYXl9IG9iamVjdHMgYXJyYXkgd2hvc2UgY29udGVudCB3aWxsIGJlIHVzZWQgZm9yIHJlcGxhY2luZwogICAgICAgICAgdGhlIGNvbnRlbnQgb2YgdGhlIHJlY2VpdmVyCiAgICAgIEByZXR1cm4ge0VtYmVyQXJyYXl9IHJlY2VpdmVyIHdpdGggdGhlIG5ldyBjb250ZW50CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBzZXRPYmplY3RzOiBmdW5jdGlvbiBzZXRPYmplY3RzKG9iamVjdHMpIHsKICAgICAgaWYgKG9iamVjdHMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuY2xlYXIoKTsKICAgICAgfQoKICAgICAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoOwogICAgICB0aGlzLnJlcGxhY2UoMCwgbGVuLCBvYmplY3RzKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgICBSZW1vdmUgYWxsIG9jY3VycmVuY2VzIG9mIGFuIG9iamVjdCBpbiB0aGUgYXJyYXkuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjaXRpZXMgPSBbJ0NoaWNhZ28nLCAnQmVybGluJywgJ0xpbWEnLCAnQ2hpY2FnbyddOwogICAgICAgY2l0aWVzLnJlbW92ZU9iamVjdCgnQ2hpY2FnbycpOyAgLy8gWydCZXJsaW4nLCAnTGltYSddCiAgICAgIGNpdGllcy5yZW1vdmVPYmplY3QoJ0xpbWEnKTsgICAgIC8vIFsnQmVybGluJ10KICAgICAgY2l0aWVzLnJlbW92ZU9iamVjdCgnVG9reW8nKSAgICAgLy8gWydCZXJsaW4nXQogICAgICBgYGAKICAgICAgIEBtZXRob2QgcmVtb3ZlT2JqZWN0CiAgICAgIEBwYXJhbSB7Kn0gb2JqIG9iamVjdCB0byByZW1vdmUKICAgICAgQHJldHVybiB7RW1iZXJBcnJheX0gcmVjZWl2ZXIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHJlbW92ZU9iamVjdDogZnVuY3Rpb24gcmVtb3ZlT2JqZWN0KG9iaikgewogICAgICB2YXIgbG9jID0gdGhpcy5sZW5ndGggfHwgMDsKCiAgICAgIHdoaWxlICgtLWxvYyA+PSAwKSB7CiAgICAgICAgdmFyIGN1ck9iamVjdCA9ICgwLCBfbWV0YWwub2JqZWN0QXQpKHRoaXMsIGxvYyk7CgogICAgICAgIGlmIChjdXJPYmplY3QgPT09IG9iaikgewogICAgICAgICAgdGhpcy5yZW1vdmVBdChsb2MpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgICBSZW1vdmVzIGVhY2ggb2JqZWN0IGluIHRoZSBwYXNzZWQgYXJyYXkgZnJvbSB0aGUgcmVjZWl2ZXIuCiAgICAgICBAbWV0aG9kIHJlbW92ZU9iamVjdHMKICAgICAgQHBhcmFtIHtFbWJlckFycmF5fSBvYmplY3RzIHRoZSBvYmplY3RzIHRvIHJlbW92ZQogICAgICBAcmV0dXJuIHtFbWJlckFycmF5fSByZWNlaXZlcgogICAgICBAcHVibGljCiAgICAqLwogICAgcmVtb3ZlT2JqZWN0czogZnVuY3Rpb24gcmVtb3ZlT2JqZWN0cyhvYmplY3RzKSB7CiAgICAgICgwLCBfbWV0YWwuYmVnaW5Qcm9wZXJ0eUNoYW5nZXMpKCk7CgogICAgICBmb3IgKHZhciBpID0gb2JqZWN0cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICAgIHRoaXMucmVtb3ZlT2JqZWN0KG9iamVjdHNbaV0pOwogICAgICB9CgogICAgICAoMCwgX21ldGFsLmVuZFByb3BlcnR5Q2hhbmdlcykoKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgICBQdXNoIHRoZSBvYmplY3Qgb250byB0aGUgZW5kIG9mIHRoZSBhcnJheSBpZiBpdCBpcyBub3QgYWxyZWFkeQogICAgICBwcmVzZW50IGluIHRoZSBhcnJheS4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IGNpdGllcyA9IFsnQ2hpY2FnbycsICdCZXJsaW4nXTsKICAgICAgIGNpdGllcy5hZGRPYmplY3QoJ0xpbWEnKTsgICAgLy8gWydDaGljYWdvJywgJ0JlcmxpbicsICdMaW1hJ10KICAgICAgY2l0aWVzLmFkZE9iamVjdCgnQmVybGluJyk7ICAvLyBbJ0NoaWNhZ28nLCAnQmVybGluJywgJ0xpbWEnXQogICAgICBgYGAKICAgICAgIEBtZXRob2QgYWRkT2JqZWN0CiAgICAgIEBwYXJhbSB7Kn0gb2JqIG9iamVjdCB0byBhZGQsIGlmIG5vdCBhbHJlYWR5IHByZXNlbnQKICAgICAgQHJldHVybiB7RW1iZXJBcnJheX0gcmVjZWl2ZXIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIGFkZE9iamVjdDogZnVuY3Rpb24gYWRkT2JqZWN0KG9iaikgewogICAgICB2YXIgaW5jbHVkZWQgPSB0aGlzLmluY2x1ZGVzKG9iaik7CgogICAgICBpZiAoIWluY2x1ZGVkKSB7CiAgICAgICAgdGhpcy5wdXNoT2JqZWN0KG9iaik7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgQWRkcyBlYWNoIG9iamVjdCBpbiB0aGUgcGFzc2VkIGFycmF5IHRvIHRoZSByZWNlaXZlci4KICAgICAgIEBtZXRob2QgYWRkT2JqZWN0cwogICAgICBAcGFyYW0ge0VtYmVyQXJyYXl9IG9iamVjdHMgdGhlIG9iamVjdHMgdG8gYWRkLgogICAgICBAcmV0dXJuIHtFbWJlckFycmF5fSByZWNlaXZlcgogICAgICBAcHVibGljCiAgICAqLwogICAgYWRkT2JqZWN0czogZnVuY3Rpb24gYWRkT2JqZWN0cyhvYmplY3RzKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgKDAsIF9tZXRhbC5iZWdpblByb3BlcnR5Q2hhbmdlcykoKTsKICAgICAgb2JqZWN0cy5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHsKICAgICAgICByZXR1cm4gX3RoaXMyLmFkZE9iamVjdChvYmopOwogICAgICB9KTsKICAgICAgKDAsIF9tZXRhbC5lbmRQcm9wZXJ0eUNoYW5nZXMpKCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfQogIH0pOwogIC8qKgogICAgQ3JlYXRlcyBhbiBgRW1iZXIuTmF0aXZlQXJyYXlgIGZyb20gYW4gQXJyYXktbGlrZSBvYmplY3QuCiAgICBEb2VzIG5vdCBtb2RpZnkgdGhlIG9yaWdpbmFsIG9iamVjdCdzIGNvbnRlbnRzLiBgQSgpYCBpcyBub3QgbmVlZGVkIGlmCiAgICBgRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVNgIGlzIGB0cnVlYCAodGhlIGRlZmF1bHQgdmFsdWUpLiBIb3dldmVyLAogICAgaXQgaXMgcmVjb21tZW5kZWQgdGhhdCB5b3UgdXNlIGBBKClgIHdoZW4gY3JlYXRpbmcgYWRkb25zIGZvcgogICAgZW1iZXIgb3Igd2hlbiB5b3UgY2FuIG5vdCBndWFyYW50ZWUgdGhhdCBgRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVNgCiAgICB3aWxsIGJlIGB0cnVlYC4KICAKICAgIEV4YW1wbGUKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LWNvbXBvbmVudC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgIGltcG9ydCB7IEEgfSBmcm9tICdAZW1iZXIvYXJyYXknOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIHRhZ05hbWU6ICd1bCcsCiAgICAgIGNsYXNzTmFtZXM6IFsncGFnaW5hdGlvbiddLAogIAogICAgICBpbml0KCkgewogICAgICAgIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cyk7CiAgCiAgICAgICAgaWYgKCF0aGlzLmdldCgnY29udGVudCcpKSB7CiAgICAgICAgICB0aGlzLnNldCgnY29udGVudCcsIEEoKSk7CiAgICAgICAgICB0aGlzLnNldCgnb3RoZXJDb250ZW50JywgQShbMSwyLDNdKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBBCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9hcnJheQogICAgQHJldHVybiB7RW1iZXIuTmF0aXZlQXJyYXl9CiAgICBAcHVibGljCiAgKi8KICAvLyBBZGQgRW1iZXIuQXJyYXkgdG8gQXJyYXkucHJvdG90eXBlLiBSZW1vdmUgbWV0aG9kcyB3aXRoIG5hdGl2ZQogIC8vIGltcGxlbWVudGF0aW9ucyBhbmQgc3VwcGx5IHNvbWUgbW9yZSBvcHRpbWl6ZWQgdmVyc2lvbnMgb2YgZ2VuZXJpYyBtZXRob2RzCiAgLy8gYmVjYXVzZSB0aGV5IGFyZSBzbyBjb21tb24uCgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIFRoZSBOYXRpdmVBcnJheSBtaXhpbiBjb250YWlucyB0aGUgcHJvcGVydGllcyBuZWVkZWQgdG8gbWFrZSB0aGUgbmF0aXZlCiAgICBBcnJheSBzdXBwb3J0IE11dGFibGVBcnJheSBhbmQgYWxsIG9mIGl0cyBkZXBlbmRlbnQgQVBJcy4gVW5sZXNzIHlvdQogICAgaGF2ZSBgRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVNgIG9yIGBFbWJlckVOVi5FWFRFTkRfUFJPVE9UWVBFUy5BcnJheWAgc2V0IHRvCiAgICBmYWxzZSwgdGhpcyB3aWxsIGJlIGFwcGxpZWQgYXV0b21hdGljYWxseS4gT3RoZXJ3aXNlIHlvdSBjYW4gYXBwbHkgdGhlIG1peGluCiAgICBhdCBhbnl0aW1lIGJ5IGNhbGxpbmcgYEVtYmVyLk5hdGl2ZUFycmF5LmFwcGx5KEFycmF5LnByb3RvdHlwZSlgLgogIAogICAgQGNsYXNzIEVtYmVyLk5hdGl2ZUFycmF5CiAgICBAdXNlcyBNdXRhYmxlQXJyYXkKICAgIEB1c2VzIE9ic2VydmFibGUKICAgIEBwdWJsaWMKICAqLwoKCiAgX2V4cG9ydHMuTXV0YWJsZUFycmF5ID0gTXV0YWJsZUFycmF5OwoKICB2YXIgTmF0aXZlQXJyYXkgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKE11dGFibGVBcnJheSwgX29ic2VydmFibGUuZGVmYXVsdCwgewogICAgb2JqZWN0QXQ6IGZ1bmN0aW9uIG9iamVjdEF0KGlkeCkgewogICAgICByZXR1cm4gdGhpc1tpZHhdOwogICAgfSwKICAgIC8vIHByaW1pdGl2ZSBmb3IgYXJyYXkgc3VwcG9ydC4KICAgIHJlcGxhY2U6IGZ1bmN0aW9uIHJlcGxhY2Uoc3RhcnQsIGRlbGV0ZUNvdW50LCBpdGVtcykgewogICAgICBpZiAoaXRlbXMgPT09IHZvaWQgMCkgewogICAgICAgIGl0ZW1zID0gRU1QVFlfQVJSQVk7CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKEFycmF5LmlzQXJyYXkoaXRlbXMpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSB0aGlyZCBhcmd1bWVudCB0byByZXBsYWNlIG5lZWRzIHRvIGJlIGFuIGFycmF5LicsIEFycmF5LmlzQXJyYXkoaXRlbXMpKSk7CiAgICAgICgwLCBfbWV0YWwucmVwbGFjZUluTmF0aXZlQXJyYXkpKHRoaXMsIHN0YXJ0LCBkZWxldGVDb3VudCwgaXRlbXMpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0KICB9KTsgLy8gUmVtb3ZlIGFueSBtZXRob2RzIGltcGxlbWVudGVkIG5hdGl2ZWx5IHNvIHdlIGRvbid0IG92ZXJyaWRlIHRoZW0KCgogIF9leHBvcnRzLk5hdGl2ZUFycmF5ID0gTmF0aXZlQXJyYXk7CiAgdmFyIGlnbm9yZSA9IFsnbGVuZ3RoJ107CiAgTmF0aXZlQXJyYXkua2V5cygpLmZvckVhY2goZnVuY3Rpb24gKG1ldGhvZE5hbWUpIHsKICAgIGlmIChBcnJheS5wcm90b3R5cGVbbWV0aG9kTmFtZV0pIHsKICAgICAgaWdub3JlLnB1c2gobWV0aG9kTmFtZSk7CiAgICB9CiAgfSk7CiAgX2V4cG9ydHMuTmF0aXZlQXJyYXkgPSBOYXRpdmVBcnJheSA9IChfTmF0aXZlQXJyYXkgPSBOYXRpdmVBcnJheSkud2l0aG91dC5hcHBseShfTmF0aXZlQXJyYXksIGlnbm9yZSk7CgogIHZhciBfQTI7CgogIF9leHBvcnRzLkEgPSBfQTI7CgogIGlmIChfZW52aXJvbm1lbnQuRU5WLkVYVEVORF9QUk9UT1RZUEVTLkFycmF5KSB7CiAgICBOYXRpdmVBcnJheS5hcHBseShBcnJheS5wcm90b3R5cGUpOwoKICAgIF9leHBvcnRzLkEgPSBfQTIgPSBmdW5jdGlvbiBBKGFycikgewogICAgICAoZmFsc2UgJiYgISghKHRoaXMgaW5zdGFuY2VvZiBfQTIpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW5ub3QgY3JlYXRlIGFuIEVtYmVyIEFycmF5IHdpdGggYG5ldyBBKClgLCBwbGVhc2UgdXBkYXRlIHRvIGNhbGxpbmcgQSBhcyBhIGZ1bmN0aW9uOiBgQSgpYCcsICEodGhpcyBpbnN0YW5jZW9mIF9BMikpKTsKICAgICAgcmV0dXJuIGFyciB8fCBbXTsKICAgIH07CiAgfSBlbHNlIHsKICAgIF9leHBvcnRzLkEgPSBfQTIgPSBmdW5jdGlvbiBfQShhcnIpIHsKICAgICAgKGZhbHNlICYmICEoISh0aGlzIGluc3RhbmNlb2YgX0EyKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgY2Fubm90IGNyZWF0ZSBhbiBFbWJlciBBcnJheSB3aXRoIGBuZXcgQSgpYCwgcGxlYXNlIHVwZGF0ZSB0byBjYWxsaW5nIEEgYXMgYSBmdW5jdGlvbjogYEEoKWAnLCAhKHRoaXMgaW5zdGFuY2VvZiBfQTIpKSk7CgogICAgICBpZiAoIWFycikgewogICAgICAgIGFyciA9IFtdOwogICAgICB9CgogICAgICByZXR1cm4gQXJyYXlNaXhpbi5kZXRlY3QoYXJyKSA/IGFyciA6IE5hdGl2ZUFycmF5LmFwcGx5KGFycik7CiAgICB9OwogIH0KCiAgdmFyIF9kZWZhdWx0ID0gQXJyYXlNaXhpbjsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9jb21wYXJhYmxlIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21ldGFsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBJbXBsZW1lbnRzIHNvbWUgc3RhbmRhcmQgbWV0aG9kcyBmb3IgY29tcGFyaW5nIG9iamVjdHMuIEFkZCB0aGlzIG1peGluIHRvCiAgICBhbnkgY2xhc3MgeW91IGNyZWF0ZSB0aGF0IGNhbiBjb21wYXJlIGl0cyBpbnN0YW5jZXMuCiAgCiAgICBZb3Ugc2hvdWxkIGltcGxlbWVudCB0aGUgYGNvbXBhcmUoKWAgbWV0aG9kLgogIAogICAgQGNsYXNzIENvbXBhcmFibGUKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEBzaW5jZSBFbWJlciAwLjkKICAgIEBwcml2YXRlCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIC8qKgogICAgICBfX1JlcXVpcmVkLl9fIFlvdSBtdXN0IGltcGxlbWVudCB0aGlzIG1ldGhvZCB0byBhcHBseSB0aGlzIG1peGluLgogICAgICAgT3ZlcnJpZGUgdG8gcmV0dXJuIHRoZSByZXN1bHQgb2YgdGhlIGNvbXBhcmlzb24gb2YgdGhlIHR3byBwYXJhbWV0ZXJzLiBUaGUKICAgICAgY29tcGFyZSBtZXRob2Qgc2hvdWxkIHJldHVybjoKICAgICAgIC0gYC0xYCBpZiBgYSA8IGJgCiAgICAgIC0gYDBgIGlmIGBhID09IGJgCiAgICAgIC0gYDFgIGlmIGBhID4gYmAKICAgICAgIERlZmF1bHQgaW1wbGVtZW50YXRpb24gcmFpc2VzIGFuIGV4Y2VwdGlvbi4KICAgICAgIEBtZXRob2QgY29tcGFyZQogICAgICBAcGFyYW0gYSB7T2JqZWN0fSB0aGUgZmlyc3Qgb2JqZWN0IHRvIGNvbXBhcmUKICAgICAgQHBhcmFtIGIge09iamVjdH0gdGhlIHNlY29uZCBvYmplY3QgdG8gY29tcGFyZQogICAgICBAcmV0dXJuIHtOdW1iZXJ9IHRoZSByZXN1bHQgb2YgdGhlIGNvbXBhcmlzb24KICAgICAgQHByaXZhdGUKICAgICovCiAgICBjb21wYXJlOiBudWxsCiAgfSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2NvbnRhaW5lcl9wcm94eSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvcnVubG9vcCIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9ydW5sb29wLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIENvbnRhaW5lclByb3h5TWl4aW4gaXMgdXNlZCB0byBwcm92aWRlIHB1YmxpYyBhY2Nlc3MgdG8gc3BlY2lmaWMKICAgIGNvbnRhaW5lciBmdW5jdGlvbmFsaXR5LgogIAogICAgQGNsYXNzIENvbnRhaW5lclByb3h5TWl4aW4KICAgIEBwcml2YXRlCiAgKi8KICB2YXIgY29udGFpbmVyUHJveHlNaXhpbiA9IHsKICAgIC8qKgogICAgIFRoZSBjb250YWluZXIgc3RvcmVzIHN0YXRlLgogICAgICBAcHJpdmF0ZQogICAgIEBwcm9wZXJ0eSB7RW1iZXIuQ29udGFpbmVyfSBfX2NvbnRhaW5lcl9fCiAgICAgKi8KICAgIF9fY29udGFpbmVyX186IG51bGwsCgogICAgLyoqCiAgICAgUmV0dXJucyBhbiBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCB0byBwcm92aWRlIGFuIG93bmVyIHRvIGEKICAgICBtYW51YWxseSBjcmVhdGVkIGluc3RhbmNlLgogICAgICBFeGFtcGxlOgogICAgICBgYGAKICAgICBpbXBvcnQgeyBnZXRPd25lciB9IGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgIGxldCBvd25lciA9IGdldE93bmVyKHRoaXMpOwogICAgICBVc2VyLmNyZWF0ZSgKICAgICAgIG93bmVyLm93bmVySW5qZWN0aW9uKCksCiAgICAgICB7IHVzZXJuYW1lOiAncndqYmx1ZScgfQogICAgICkKICAgICBgYGAKICAgICAgQHB1YmxpYwogICAgIEBtZXRob2Qgb3duZXJJbmplY3Rpb24KICAgICBAc2luY2UgMi4zLjAKICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgb3duZXJJbmplY3Rpb246IGZ1bmN0aW9uIG93bmVySW5qZWN0aW9uKCkgewogICAgICByZXR1cm4gdGhpcy5fX2NvbnRhaW5lcl9fLm93bmVySW5qZWN0aW9uKCk7CiAgICB9LAoKICAgIC8qKgogICAgIEdpdmVuIGEgZnVsbE5hbWUgcmV0dXJuIGEgY29ycmVzcG9uZGluZyBpbnN0YW5jZS4KICAgICAgVGhlIGRlZmF1bHQgYmVoYXZpb3IgaXMgZm9yIGxvb2t1cCB0byByZXR1cm4gYSBzaW5nbGV0b24gaW5zdGFuY2UuCiAgICAgVGhlIHNpbmdsZXRvbiBpcyBzY29wZWQgdG8gdGhlIGNvbnRhaW5lciwgYWxsb3dpbmcgbXVsdGlwbGUgY29udGFpbmVycwogICAgIHRvIGFsbCBoYXZlIHRoZWlyIG93biBsb2NhbGx5IHNjb3BlZCBzaW5nbGV0b25zLgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgbGV0IGNvbnRhaW5lciA9IHJlZ2lzdHJ5LmNvbnRhaW5lcigpOwogICAgICByZWdpc3RyeS5yZWdpc3RlcignYXBpOnR3aXR0ZXInLCBUd2l0dGVyKTsKICAgICAgbGV0IHR3aXR0ZXIgPSBjb250YWluZXIubG9va3VwKCdhcGk6dHdpdHRlcicpOwogICAgICB0d2l0dGVyIGluc3RhbmNlb2YgVHdpdHRlcjsgLy8gPT4gdHJ1ZQogICAgICAvLyBieSBkZWZhdWx0IHRoZSBjb250YWluZXIgd2lsbCByZXR1cm4gc2luZ2xldG9ucwogICAgIGxldCB0d2l0dGVyMiA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJyk7CiAgICAgdHdpdHRlcjIgaW5zdGFuY2VvZiBUd2l0dGVyOyAvLyA9PiB0cnVlCiAgICAgIHR3aXR0ZXIgPT09IHR3aXR0ZXIyOyAvLz0+IHRydWUKICAgICBgYGAKICAgICAgSWYgc2luZ2xldG9ucyBhcmUgbm90IHdhbnRlZCBhbiBvcHRpb25hbCBmbGFnIGNhbiBiZSBwcm92aWRlZCBhdCBsb29rdXAuCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoKTsKICAgICBsZXQgY29udGFpbmVyID0gcmVnaXN0cnkuY29udGFpbmVyKCk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdhcGk6dHdpdHRlcicsIFR3aXR0ZXIpOwogICAgICBsZXQgdHdpdHRlciA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJywgeyBzaW5nbGV0b246IGZhbHNlIH0pOwogICAgIGxldCB0d2l0dGVyMiA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJywgeyBzaW5nbGV0b246IGZhbHNlIH0pOwogICAgICB0d2l0dGVyID09PSB0d2l0dGVyMjsgLy89PiBmYWxzZQogICAgIGBgYAogICAgICBAcHVibGljCiAgICAgQG1ldGhvZCBsb29rdXAKICAgICBAcGFyYW0ge1N0cmluZ30gZnVsbE5hbWUKICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgIEByZXR1cm4ge2FueX0KICAgICAqLwogICAgbG9va3VwOiBmdW5jdGlvbiBsb29rdXAoZnVsbE5hbWUsIG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMuX19jb250YWluZXJfXy5sb29rdXAoZnVsbE5hbWUsIG9wdGlvbnMpOwogICAgfSwKICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHZhciBjb250YWluZXIgPSB0aGlzLl9fY29udGFpbmVyX187CgogICAgICBpZiAoY29udGFpbmVyKSB7CiAgICAgICAgKDAsIF9ydW5sb29wLmpvaW4pKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIGNvbnRhaW5lci5kZXN0cm95KCk7CiAgICAgICAgICAoMCwgX3J1bmxvb3Auc2NoZWR1bGUpKCdkZXN0cm95JywgY29udGFpbmVyLCAnZmluYWxpemVEZXN0cm95Jyk7CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHRoaXMuX3N1cGVyKCk7CiAgICB9LAoKICAgIC8qKgogICAgR2l2ZW4gYSBmdWxsTmFtZSByZXR1cm4gYSBmYWN0b3J5IG1hbmFnZXIuCiAgICAgVGhpcyBtZXRob2QgcmV0dXJucyBhIG1hbmFnZXIgd2hpY2ggY2FuIGJlIHVzZWQgZm9yIGludHJvc3BlY3Rpb24gb2YgdGhlCiAgICBmYWN0b3J5J3MgY2xhc3Mgb3IgZm9yIHRoZSBjcmVhdGlvbiBvZiBmYWN0b3J5IGluc3RhbmNlcyB3aXRoIGluaXRpYWwKICAgIHByb3BlcnRpZXMuIFRoZSBtYW5hZ2VyIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllczoKICAgICAqIGBjbGFzc2AgLSBUaGUgcmVnaXN0ZXJlZCBvciByZXNvbHZlZCBjbGFzcy4KICAgICogYGNyZWF0ZWAgLSBBIGZ1bmN0aW9uIHRoYXQgd2lsbCBjcmVhdGUgYW4gaW5zdGFuY2Ugb2YgdGhlIGNsYXNzIHdpdGgKICAgICAgYW55IGRlcGVuZGVuY2llcyBpbmplY3RlZC4KICAgICBGb3IgZXhhbXBsZToKICAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBnZXRPd25lciB9IGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgbGV0IG93bmVyID0gZ2V0T3duZXIob3RoZXJJbnN0YW5jZSk7CiAgICAvLyB0aGUgb3duZXIgaXMgY29tbW9ubHkgdGhlIGBhcHBsaWNhdGlvbkluc3RhbmNlYCwgYW5kIGNhbiBiZSBhY2Nlc3NlZCB2aWEKICAgIC8vIGFuIGluc3RhbmNlIGluaXRpYWxpemVyLgogICAgIGxldCBmYWN0b3J5ID0gb3duZXIuZmFjdG9yeUZvcignc2VydmljZTpiZXNwb2tlJyk7CiAgICAgZmFjdG9yeS5jbGFzczsKICAgIC8vIFRoZSByZWdpc3RlcmVkIG9yIHJlc29sdmVkIGNsYXNzLiBGb3IgZXhhbXBsZSB3aGVuIHVzZWQgd2l0aCBhbiBFbWJlci1DTEkKICAgIC8vIGFwcCwgdGhpcyB3b3VsZCBiZSB0aGUgZGVmYXVsdCBleHBvcnQgZnJvbSBgYXBwL3NlcnZpY2VzL2Jlc3Bva2UuanNgLgogICAgIGxldCBpbnN0YW5jZSA9IGZhY3RvcnkuY3JlYXRlKHsKICAgICAgc29tZVByb3BlcnR5OiAnYW4gaW5pdGlhbCBwcm9wZXJ0eSB2YWx1ZScKICAgIH0pOwogICAgLy8gQ3JlYXRlIGFuIGluc3RhbmNlIHdpdGggYW55IGluamVjdGlvbnMgYW5kIHRoZSBwYXNzZWQgb3B0aW9ucyBhcwogICAgLy8gaW5pdGlhbCBwcm9wZXJ0aWVzLgogICAgYGBgCiAgICAgQW55IGluc3RhbmNlcyBjcmVhdGVkIHZpYSB0aGUgZmFjdG9yeSdzIGAuY3JlYXRlKClgIG1ldGhvZCAqbXVzdCogYmUgZGVzdHJveWVkCiAgICBtYW51YWxseSBieSB0aGUgY2FsbGVyIG9mIGAuY3JlYXRlKClgLiBUeXBpY2FsbHksIHRoaXMgaXMgZG9uZSBkdXJpbmcgdGhlIGNyZWF0aW5nCiAgICBvYmplY3RzIG93biBgZGVzdHJveWAgb3IgYHdpbGxEZXN0cm95YCBtZXRob2RzLgogICAgIEBwdWJsaWMKICAgIEBtZXRob2QgZmFjdG9yeUZvcgogICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgQHJldHVybiB7RmFjdG9yeU1hbmFnZXJ9CiAgICAqLwogICAgZmFjdG9yeUZvcjogZnVuY3Rpb24gZmFjdG9yeUZvcihmdWxsTmFtZSwgb3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fX2NvbnRhaW5lcl9fLmZhY3RvcnlGb3IoZnVsbE5hbWUsIG9wdGlvbnMpOwogICAgfQogIH07CgogIHZhciBfZGVmYXVsdCA9IF9tZXRhbC5NaXhpbi5jcmVhdGUoY29udGFpbmVyUHJveHlNaXhpbik7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2NvcHlhYmxlIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21ldGFsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBJbXBsZW1lbnRzIHNvbWUgc3RhbmRhcmQgbWV0aG9kcyBmb3IgY29weWluZyBhbiBvYmplY3QuIEFkZCB0aGlzIG1peGluIHRvCiAgICBhbnkgb2JqZWN0IHlvdSBjcmVhdGUgdGhhdCBjYW4gY3JlYXRlIGEgY29weSBvZiBpdHNlbGYuIFRoaXMgbWl4aW4gaXMKICAgIGFkZGVkIGF1dG9tYXRpY2FsbHkgdG8gdGhlIGJ1aWx0LWluIGFycmF5LgogIAogICAgWW91IHNob3VsZCBnZW5lcmFsbHkgaW1wbGVtZW50IHRoZSBgY29weSgpYCBtZXRob2QgdG8gcmV0dXJuIGEgY29weSBvZiB0aGUKICAgIHJlY2VpdmVyLgogIAogICAgQGNsYXNzIENvcHlhYmxlCiAgICBAbmFtZXNwYWNlIEVtYmVyCiAgICBAc2luY2UgRW1iZXIgMC45CiAgICBAZGVwcmVjYXRlZCBVc2UgJ2VtYmVyLWNvcHknIGFkZG9uIGluc3RlYWQKICAgIEBwcml2YXRlCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIC8qKgogICAgICBfX1JlcXVpcmVkLl9fIFlvdSBtdXN0IGltcGxlbWVudCB0aGlzIG1ldGhvZCB0byBhcHBseSB0aGlzIG1peGluLgogICAgICAgT3ZlcnJpZGUgdG8gcmV0dXJuIGEgY29weSBvZiB0aGUgcmVjZWl2ZXIuIERlZmF1bHQgaW1wbGVtZW50YXRpb24gcmFpc2VzCiAgICAgIGFuIGV4Y2VwdGlvbi4KICAgICAgIEBtZXRob2QgY29weQogICAgICBAcGFyYW0ge0Jvb2xlYW59IGRlZXAgaWYgYHRydWVgLCBhIGRlZXAgY29weSBvZiB0aGUgb2JqZWN0IHNob3VsZCBiZSBtYWRlCiAgICAgIEByZXR1cm4ge09iamVjdH0gY29weSBvZiByZWNlaXZlcgogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGNvcHk6IG51bGwKICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvZW51bWVyYWJsZSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvZW51bWVyYWJsZQogIEBwcml2YXRlCiAgKi8KCiAgLyoqCiAgICBUaGUgbWV0aG9kcyBpbiB0aGlzIG1peGluIGhhdmUgYmVlbiBtb3ZlZCB0byBbTXV0YWJsZUFycmF5XSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL011dGFibGVBcnJheSkuIFRoaXMgbWl4aW4gaGFzCiAgICBiZWVuIGludGVudGlvbmFsbHkgcHJlc2VydmVkIHRvIGF2b2lkIGJyZWFraW5nIEVudW1lcmFibGUuZGV0ZWN0IGNoZWNrcwogICAgdW50aWwgdGhlIGNvbW11bml0eSBtaWdyYXRlcyBhd2F5IGZyb20gdGhlbS4KICAKICAgIEBjbGFzcyBFbnVtZXJhYmxlCiAgICBAcHJpdmF0ZQogICovCiAgdmFyIF9kZWZhdWx0ID0gX21ldGFsLk1peGluLmNyZWF0ZSgpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9ldmVudGVkIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21ldGFsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwoKICAvKioKICAgIFRoaXMgbWl4aW4gYWxsb3dzIGZvciBFbWJlciBvYmplY3RzIHRvIHN1YnNjcmliZSB0byBhbmQgZW1pdCBldmVudHMuCiAgCiAgICBgYGBhcHAvdXRpbHMvcGVyc29uLmpzCiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgRXZlbnRlZCBmcm9tICdAZW1iZXIvb2JqZWN0L2V2ZW50ZWQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgRW1iZXJPYmplY3QuZXh0ZW5kKEV2ZW50ZWQsIHsKICAgICAgZ3JlZXQoKSB7CiAgICAgICAgLy8gLi4uCiAgICAgICAgdGhpcy50cmlnZ2VyKCdncmVldCcpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgYGBgamF2YXNjcmlwdAogICAgdmFyIHBlcnNvbiA9IFBlcnNvbi5jcmVhdGUoKTsKICAKICAgIHBlcnNvbi5vbignZ3JlZXQnLCBmdW5jdGlvbigpIHsKICAgICAgY29uc29sZS5sb2coJ091ciBwZXJzb24gaGFzIGdyZWV0ZWQnKTsKICAgIH0pOwogIAogICAgcGVyc29uLmdyZWV0KCk7CiAgCiAgICAvLyBvdXRwdXRzOiAnT3VyIHBlcnNvbiBoYXMgZ3JlZXRlZCcKICAgIGBgYAogIAogICAgWW91IGNhbiBhbHNvIGNoYWluIG11bHRpcGxlIGV2ZW50IHN1YnNjcmlwdGlvbnM6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBwZXJzb24ub24oJ2dyZWV0JywgZnVuY3Rpb24oKSB7CiAgICAgIGNvbnNvbGUubG9nKCdPdXIgcGVyc29uIGhhcyBncmVldGVkJyk7CiAgICB9KS5vbmUoJ2dyZWV0JywgZnVuY3Rpb24oKSB7CiAgICAgIGNvbnNvbGUubG9nKCdPZmZlciBvbmUtdGltZSBzcGVjaWFsJyk7CiAgICB9KS5vZmYoJ2V2ZW50JywgdGhpcywgZm9yZ2V0VGhpcyk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBFdmVudGVkCiAgICBAcHVibGljCiAgICovCiAgdmFyIF9kZWZhdWx0ID0gX21ldGFsLk1peGluLmNyZWF0ZSh7CiAgICAvKioKICAgICAgU3Vic2NyaWJlcyB0byBhIG5hbWVkIGV2ZW50IHdpdGggZ2l2ZW4gZnVuY3Rpb24uCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHBlcnNvbi5vbignZGlkTG9hZCcsIGZ1bmN0aW9uKCkgewogICAgICAgIC8vIGZpcmVkIG9uY2UgdGhlIHBlcnNvbiBoYXMgbG9hZGVkCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEFuIG9wdGlvbmFsIHRhcmdldCBjYW4gYmUgcGFzc2VkIGluIGFzIHRoZSAybmQgYXJndW1lbnQgdGhhdCB3aWxsCiAgICAgIGJlIHNldCBhcyB0aGUgInRoaXMiIGZvciB0aGUgY2FsbGJhY2suIFRoaXMgaXMgYSBnb29kIHdheSB0byBnaXZlIHlvdXIKICAgICAgZnVuY3Rpb24gYWNjZXNzIHRvIHRoZSBvYmplY3QgdHJpZ2dlcmluZyB0aGUgZXZlbnQuIFdoZW4gdGhlIHRhcmdldAogICAgICBwYXJhbWV0ZXIgaXMgdXNlZCB0aGUgY2FsbGJhY2sgbWV0aG9kIGJlY29tZXMgdGhlIHRoaXJkIGFyZ3VtZW50LgogICAgICAgQG1ldGhvZCBvbgogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQKICAgICAgQHBhcmFtIHtPYmplY3R9IFt0YXJnZXRdIFRoZSAidGhpcyIgYmluZGluZyBmb3IgdGhlIGNhbGxiYWNrCiAgICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBtZXRob2QgQSBmdW5jdGlvbiBvciB0aGUgbmFtZSBvZiBhIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBvbiBgdGFyZ2V0YAogICAgICBAcmV0dXJuIHRoaXMKICAgICAgQHB1YmxpYwogICAgKi8KICAgIG9uOiBmdW5jdGlvbiBvbihuYW1lLCB0YXJnZXQsIG1ldGhvZCkgewogICAgICAoMCwgX21ldGFsLmFkZExpc3RlbmVyKSh0aGlzLCBuYW1lLCB0YXJnZXQsIG1ldGhvZCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgU3Vic2NyaWJlcyBhIGZ1bmN0aW9uIHRvIGEgbmFtZWQgZXZlbnQgYW5kIHRoZW4gY2FuY2VscyB0aGUgc3Vic2NyaXB0aW9uCiAgICAgIGFmdGVyIHRoZSBmaXJzdCB0aW1lIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuIEl0IGlzIGdvb2QgdG8gdXNlIGBgb25lYGAgd2hlbgogICAgICB5b3Ugb25seSBjYXJlIGFib3V0IHRoZSBmaXJzdCB0aW1lIGFuIGV2ZW50IGhhcyB0YWtlbiBwbGFjZS4KICAgICAgIFRoaXMgZnVuY3Rpb24gdGFrZXMgYW4gb3B0aW9uYWwgMm5kIGFyZ3VtZW50IHRoYXQgd2lsbCBiZWNvbWUgdGhlICJ0aGlzIgogICAgICB2YWx1ZSBmb3IgdGhlIGNhbGxiYWNrLiBXaGVuIHRoZSB0YXJnZXQgcGFyYW1ldGVyIGlzIHVzZWQgdGhlIGNhbGxiYWNrIG1ldGhvZAogICAgICBiZWNvbWVzIHRoZSB0aGlyZCBhcmd1bWVudC4KICAgICAgIEBtZXRob2Qgb25lCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudAogICAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gVGhlICJ0aGlzIiBiaW5kaW5nIGZvciB0aGUgY2FsbGJhY2sKICAgICAgQHBhcmFtIHtGdW5jdGlvbnxTdHJpbmd9IG1ldGhvZCBBIGZ1bmN0aW9uIG9yIHRoZSBuYW1lIG9mIGEgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIG9uIGB0YXJnZXRgCiAgICAgIEByZXR1cm4gdGhpcwogICAgICBAcHVibGljCiAgICAqLwogICAgb25lOiBmdW5jdGlvbiBvbmUobmFtZSwgdGFyZ2V0LCBtZXRob2QpIHsKICAgICAgKDAsIF9tZXRhbC5hZGRMaXN0ZW5lcikodGhpcywgbmFtZSwgdGFyZ2V0LCBtZXRob2QsIHRydWUpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCgogICAgLyoqCiAgICAgIFRyaWdnZXJzIGEgbmFtZWQgZXZlbnQgZm9yIHRoZSBvYmplY3QuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cwogICAgICB3aWxsIGJlIHBhc3NlZCBhcyBwYXJhbWV0ZXJzIHRvIHRoZSBmdW5jdGlvbnMgdGhhdCBhcmUgc3Vic2NyaWJlZCB0byB0aGUKICAgICAgZXZlbnQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHBlcnNvbi5vbignZGlkRWF0JywgZnVuY3Rpb24oZm9vZCkgewogICAgICAgIGNvbnNvbGUubG9nKCdwZXJzb24gYXRlIHNvbWUgJyArIGZvb2QpOwogICAgICB9KTsKICAgICAgIHBlcnNvbi50cmlnZ2VyKCdkaWRFYXQnLCAnYnJvY2NvbGknKTsKICAgICAgIC8vIG91dHB1dHM6IHBlcnNvbiBhdGUgc29tZSBicm9jY29saQogICAgICBgYGAKICAgICAgQG1ldGhvZCB0cmlnZ2VyCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudAogICAgICBAcGFyYW0ge09iamVjdC4uLn0gYXJncyBPcHRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyBvbgogICAgICBAcHVibGljCiAgICAqLwogICAgdHJpZ2dlcjogZnVuY3Rpb24gdHJpZ2dlcihuYW1lKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4gPiAxID8gX2xlbiAtIDEgOiAwKSwgX2tleSA9IDE7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgICBhcmdzW19rZXkgLSAxXSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgICAgfQoKICAgICAgKDAsIF9tZXRhbC5zZW5kRXZlbnQpKHRoaXMsIG5hbWUsIGFyZ3MpOwogICAgfSwKCiAgICAvKioKICAgICAgQ2FuY2VscyBzdWJzY3JpcHRpb24gZm9yIGdpdmVuIG5hbWUsIHRhcmdldCwgYW5kIG1ldGhvZC4KICAgICAgIEBtZXRob2Qgb2ZmCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudAogICAgICBAcGFyYW0ge09iamVjdH0gdGFyZ2V0IFRoZSB0YXJnZXQgb2YgdGhlIHN1YnNjcmlwdGlvbgogICAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIFRoZSBmdW5jdGlvbiBvciB0aGUgbmFtZSBvZiBhIGZ1bmN0aW9uIG9mIHRoZSBzdWJzY3JpcHRpb24KICAgICAgQHJldHVybiB0aGlzCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBvZmY6IGZ1bmN0aW9uIG9mZihuYW1lLCB0YXJnZXQsIG1ldGhvZCkgewogICAgICAoMCwgX21ldGFsLnJlbW92ZUxpc3RlbmVyKSh0aGlzLCBuYW1lLCB0YXJnZXQsIG1ldGhvZCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgQ2hlY2tzIHRvIHNlZSBpZiBvYmplY3QgaGFzIGFueSBzdWJzY3JpcHRpb25zIGZvciBuYW1lZCBldmVudC4KICAgICAgIEBtZXRob2QgaGFzCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudAogICAgICBAcmV0dXJuIHtCb29sZWFufSBkb2VzIHRoZSBvYmplY3QgaGF2ZSBhIHN1YnNjcmlwdGlvbiBmb3IgZXZlbnQKICAgICAgQHB1YmxpYwogICAgICovCiAgICBoYXM6IGZ1bmN0aW9uIGhhcyhuYW1lKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmhhc0xpc3RlbmVycykodGhpcywgbmFtZSk7CiAgICB9CiAgfSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL211dGFibGVfZW51bWVyYWJsZSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvZW51bWVyYWJsZSIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbnVtZXJhYmxlLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIFRoZSBtZXRob2RzIGluIHRoaXMgbWl4aW4gaGF2ZSBiZWVuIG1vdmVkIHRvIE11dGFibGVBcnJheS4gVGhpcyBtaXhpbiBoYXMKICAgIGJlZW4gaW50ZW50aW9uYWxseSBwcmVzZXJ2ZWQgdG8gYXZvaWQgYnJlYWtpbmcgTXV0YWJsZUVudW1lcmFibGUuZGV0ZWN0CiAgICBjaGVja3MgdW50aWwgdGhlIGNvbW11bml0eSBtaWdyYXRlcyBhd2F5IGZyb20gdGhlbS4KICAKICAgIEBjbGFzcyBNdXRhYmxlRW51bWVyYWJsZQogICAgQG5hbWVzcGFjZSBFbWJlcgogICAgQHVzZXMgRW51bWVyYWJsZQogICAgQHByaXZhdGUKICAqLwogIHZhciBfZGVmYXVsdCA9IF9tZXRhbC5NaXhpbi5jcmVhdGUoX2VudW1lcmFibGUuZGVmYXVsdCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL29ic2VydmFibGUiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21ldGFsLCBfZGVidWcpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgQGVtYmVyL29iamVjdAogICovCgogIC8qKgogICAgIyMgT3ZlcnZpZXcKICAKICAgIFRoaXMgbWl4aW4gcHJvdmlkZXMgcHJvcGVydGllcyBhbmQgcHJvcGVydHkgb2JzZXJ2aW5nIGZ1bmN0aW9uYWxpdHksIGNvcmUKICAgIGZlYXR1cmVzIG9mIHRoZSBFbWJlciBvYmplY3QgbW9kZWwuCiAgCiAgICBQcm9wZXJ0aWVzIGFuZCBvYnNlcnZlcnMgYWxsb3cgb25lIG9iamVjdCB0byBvYnNlcnZlIGNoYW5nZXMgdG8gYQogICAgcHJvcGVydHkgb24gYW5vdGhlciBvYmplY3QuIFRoaXMgaXMgb25lIG9mIHRoZSBmdW5kYW1lbnRhbCB3YXlzIHRoYXQKICAgIG1vZGVscywgY29udHJvbGxlcnMgYW5kIHZpZXdzIGNvbW11bmljYXRlIHdpdGggZWFjaCBvdGhlciBpbiBhbiBFbWJlcgogICAgYXBwbGljYXRpb24uCiAgCiAgICBBbnkgb2JqZWN0IHRoYXQgaGFzIHRoaXMgbWl4aW4gYXBwbGllZCBjYW4gYmUgdXNlZCBpbiBvYnNlcnZlcgogICAgb3BlcmF0aW9ucy4gVGhhdCBpbmNsdWRlcyBgRW1iZXJPYmplY3RgIGFuZCBtb3N0IG9iamVjdHMgeW91IHdpbGwKICAgIGludGVyYWN0IHdpdGggYXMgeW91IHdyaXRlIHlvdXIgRW1iZXIgYXBwbGljYXRpb24uCiAgCiAgICBOb3RlIHRoYXQgeW91IHdpbGwgbm90IGdlbmVyYWxseSBhcHBseSB0aGlzIG1peGluIHRvIGNsYXNzZXMgeW91cnNlbGYsCiAgICBidXQgeW91IHdpbGwgdXNlIHRoZSBmZWF0dXJlcyBwcm92aWRlZCBieSB0aGlzIG1vZHVsZSBmcmVxdWVudGx5LCBzbyBpdAogICAgaXMgaW1wb3J0YW50IHRvIHVuZGVyc3RhbmQgaG93IHRvIHVzZSBpdC4KICAKICAgICMjIFVzaW5nIGBnZXQoKWAgYW5kIGBzZXQoKWAKICAKICAgIEJlY2F1c2Ugb2YgRW1iZXIncyBzdXBwb3J0IGZvciBiaW5kaW5ncyBhbmQgb2JzZXJ2ZXJzLCB5b3Ugd2lsbCBhbHdheXMKICAgIGFjY2VzcyBwcm9wZXJ0aWVzIHVzaW5nIHRoZSBnZXQgbWV0aG9kLCBhbmQgc2V0IHByb3BlcnRpZXMgdXNpbmcgdGhlCiAgICBzZXQgbWV0aG9kLiBUaGlzIGFsbG93cyB0aGUgb2JzZXJ2aW5nIG9iamVjdHMgdG8gYmUgbm90aWZpZWQgYW5kCiAgICBjb21wdXRlZCBwcm9wZXJ0aWVzIHRvIGJlIGhhbmRsZWQgcHJvcGVybHkuCiAgCiAgICBNb3JlIGRvY3VtZW50YXRpb24gYWJvdXQgYGdldGAgYW5kIGBzZXRgIGFyZSBiZWxvdy4KICAKICAgICMjIE9ic2VydmluZyBQcm9wZXJ0eSBDaGFuZ2VzCiAgCiAgICBZb3UgdHlwaWNhbGx5IG9ic2VydmUgcHJvcGVydHkgY2hhbmdlcyBzaW1wbHkgYnkgdXNpbmcgdGhlIGBvYnNlcnZlcmAKICAgIGZ1bmN0aW9uIGluIGNsYXNzZXMgdGhhdCB5b3Ugd3JpdGUuCiAgCiAgICBGb3IgZXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IG9ic2VydmVyIH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgCiAgICBFbWJlck9iamVjdC5leHRlbmQoewogICAgICB2YWx1ZU9ic2VydmVyOiBvYnNlcnZlcigndmFsdWUnLCBmdW5jdGlvbihzZW5kZXIsIGtleSwgdmFsdWUsIHJldikgewogICAgICAgIC8vIEV4ZWN1dGVzIHdoZW5ldmVyIHRoZSAidmFsdWUiIHByb3BlcnR5IGNoYW5nZXMKICAgICAgICAvLyBTZWUgdGhlIGFkZE9ic2VydmVyIG1ldGhvZCBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY2FsbGJhY2sgYXJndW1lbnRzCiAgICAgIH0pCiAgICB9KTsKICAgIGBgYAogIAogICAgQWx0aG91Z2ggdGhpcyBpcyB0aGUgbW9zdCBjb21tb24gd2F5IHRvIGFkZCBhbiBvYnNlcnZlciwgdGhpcyBjYXBhYmlsaXR5CiAgICBpcyBhY3R1YWxseSBidWlsdCBpbnRvIHRoZSBgRW1iZXJPYmplY3RgIGNsYXNzIG9uIHRvcCBvZiB0d28gbWV0aG9kcwogICAgZGVmaW5lZCBpbiB0aGlzIG1peGluOiBgYWRkT2JzZXJ2ZXJgIGFuZCBgcmVtb3ZlT2JzZXJ2ZXJgLiBZb3UgY2FuIHVzZQogICAgdGhlc2UgdHdvIG1ldGhvZHMgdG8gYWRkIGFuZCByZW1vdmUgb2JzZXJ2ZXJzIHlvdXJzZWxmIGlmIHlvdSBuZWVkIHRvCiAgICBkbyBzbyBhdCBydW50aW1lLgogIAogICAgVG8gYWRkIGFuIG9ic2VydmVyIGZvciBhIHByb3BlcnR5LCBjYWxsOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgb2JqZWN0LmFkZE9ic2VydmVyKCdwcm9wZXJ0eUtleScsIHRhcmdldE9iamVjdCwgdGFyZ2V0QWN0aW9uKQogICAgYGBgCiAgCiAgICBUaGlzIHdpbGwgY2FsbCB0aGUgYHRhcmdldEFjdGlvbmAgbWV0aG9kIG9uIHRoZSBgdGFyZ2V0T2JqZWN0YCB3aGVuZXZlcgogICAgdGhlIHZhbHVlIG9mIHRoZSBgcHJvcGVydHlLZXlgIGNoYW5nZXMuCiAgCiAgICBOb3RlIHRoYXQgaWYgYHByb3BlcnR5S2V5YCBpcyBhIGNvbXB1dGVkIHByb3BlcnR5LCB0aGUgb2JzZXJ2ZXIgd2lsbCBiZQogICAgY2FsbGVkIHdoZW4gYW55IG9mIHRoZSBwcm9wZXJ0eSBkZXBlbmRlbmNpZXMgYXJlIGNoYW5nZWQsIGV2ZW4gaWYgdGhlCiAgICByZXN1bHRpbmcgdmFsdWUgb2YgdGhlIGNvbXB1dGVkIHByb3BlcnR5IGlzIHVuY2hhbmdlZC4gVGhpcyBpcyBuZWNlc3NhcnkKICAgIGJlY2F1c2UgY29tcHV0ZWQgcHJvcGVydGllcyBhcmUgbm90IGNvbXB1dGVkIHVudGlsIGBnZXRgIGlzIGNhbGxlZC4KICAKICAgIEBjbGFzcyBPYnNlcnZhYmxlCiAgICBAcHVibGljCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIC8qKgogICAgICBSZXRyaWV2ZXMgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgZnJvbSB0aGUgb2JqZWN0LgogICAgICAgVGhpcyBtZXRob2QgaXMgdXN1YWxseSBzaW1pbGFyIHRvIHVzaW5nIGBvYmplY3Rba2V5TmFtZV1gIG9yIGBvYmplY3Qua2V5TmFtZWAsCiAgICAgIGhvd2V2ZXIgaXQgc3VwcG9ydHMgYm90aCBjb21wdXRlZCBwcm9wZXJ0aWVzIGFuZCB0aGUgdW5rbm93blByb3BlcnR5CiAgICAgIGhhbmRsZXIuCiAgICAgICBCZWNhdXNlIGBnZXRgIHVuaWZpZXMgdGhlIHN5bnRheCBmb3IgYWNjZXNzaW5nIGFsbCB0aGVzZSBraW5kcwogICAgICBvZiBwcm9wZXJ0aWVzLCBpdCBjYW4gbWFrZSBtYW55IHJlZmFjdG9yaW5ncyBlYXNpZXIsIHN1Y2ggYXMgcmVwbGFjaW5nIGEKICAgICAgc2ltcGxlIHByb3BlcnR5IHdpdGggYSBjb21wdXRlZCBwcm9wZXJ0eSwgb3IgdmljZSB2ZXJzYS4KICAgICAgICMjIyBDb21wdXRlZCBQcm9wZXJ0aWVzCiAgICAgICBDb21wdXRlZCBwcm9wZXJ0aWVzIGFyZSBtZXRob2RzIGRlZmluZWQgd2l0aCB0aGUgYHByb3BlcnR5YCBtb2RpZmllcgogICAgICBkZWNsYXJlZCBhdCB0aGUgZW5kLCBzdWNoIGFzOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgZnVsbE5hbWU6IGNvbXB1dGVkKCdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnLCBmdW5jdGlvbigpIHsKICAgICAgICByZXR1cm4gdGhpcy5nZXQoJ2ZpcnN0TmFtZScpICsgJyAnICsgdGhpcy5nZXQoJ2xhc3ROYW1lJyk7CiAgICAgIH0pCiAgICAgIGBgYAogICAgICAgV2hlbiB5b3UgY2FsbCBgZ2V0YCBvbiBhIGNvbXB1dGVkIHByb3BlcnR5LCB0aGUgZnVuY3Rpb24gd2lsbCBiZQogICAgICBjYWxsZWQgYW5kIHRoZSByZXR1cm4gdmFsdWUgd2lsbCBiZSByZXR1cm5lZCBpbnN0ZWFkIG9mIHRoZSBmdW5jdGlvbgogICAgICBpdHNlbGYuCiAgICAgICAjIyMgVW5rbm93biBQcm9wZXJ0aWVzCiAgICAgICBMaWtld2lzZSwgaWYgeW91IHRyeSB0byBjYWxsIGBnZXRgIG9uIGEgcHJvcGVydHkgd2hvc2UgdmFsdWUgaXMKICAgICAgYHVuZGVmaW5lZGAsIHRoZSBgdW5rbm93blByb3BlcnR5KClgIG1ldGhvZCB3aWxsIGJlIGNhbGxlZCBvbiB0aGUgb2JqZWN0LgogICAgICBJZiB0aGlzIG1ldGhvZCByZXR1cm5zIGFueSB2YWx1ZSBvdGhlciB0aGFuIGB1bmRlZmluZWRgLCBpdCB3aWxsIGJlIHJldHVybmVkCiAgICAgIGluc3RlYWQuIFRoaXMgYWxsb3dzIHlvdSB0byBpbXBsZW1lbnQgInZpcnR1YWwiIHByb3BlcnRpZXMgdGhhdCBhcmUKICAgICAgbm90IGRlZmluZWQgdXBmcm9udC4KICAgICAgIEBtZXRob2QgZ2V0CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBrZXlOYW1lIFRoZSBwcm9wZXJ0eSB0byByZXRyaWV2ZQogICAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSBwcm9wZXJ0eSB2YWx1ZSBvciB1bmRlZmluZWQuCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBnZXQ6IGZ1bmN0aW9uIGdldChrZXlOYW1lKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkodGhpcywga2V5TmFtZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBUbyBnZXQgdGhlIHZhbHVlcyBvZiBtdWx0aXBsZSBwcm9wZXJ0aWVzIGF0IG9uY2UsIGNhbGwgYGdldFByb3BlcnRpZXNgCiAgICAgIHdpdGggYSBsaXN0IG9mIHN0cmluZ3Mgb3IgYW4gYXJyYXk6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHJlY29yZC5nZXRQcm9wZXJ0aWVzKCdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnLCAnemlwQ29kZScpOwogICAgICAvLyB7IGZpcnN0TmFtZTogJ0pvaG4nLCBsYXN0TmFtZTogJ0RvZScsIHppcENvZGU6ICcxMDAxMScgfQogICAgICBgYGAKICAgICAgIGlzIGVxdWl2YWxlbnQgdG86CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHJlY29yZC5nZXRQcm9wZXJ0aWVzKFsnZmlyc3ROYW1lJywgJ2xhc3ROYW1lJywgJ3ppcENvZGUnXSk7CiAgICAgIC8vIHsgZmlyc3ROYW1lOiAnSm9obicsIGxhc3ROYW1lOiAnRG9lJywgemlwQ29kZTogJzEwMDExJyB9CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBnZXRQcm9wZXJ0aWVzCiAgICAgIEBwYXJhbSB7U3RyaW5nLi4ufEFycmF5fSBsaXN0IG9mIGtleXMgdG8gZ2V0CiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICAgQHB1YmxpYwogICAgKi8KICAgIGdldFByb3BlcnRpZXM6IGZ1bmN0aW9uIGdldFByb3BlcnRpZXMoKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgIHJldHVybiBfbWV0YWwuZ2V0UHJvcGVydGllcy5hcHBseSh2b2lkIDAsIFt0aGlzXS5jb25jYXQoYXJncykpOwogICAgfSwKCiAgICAvKioKICAgICAgU2V0cyB0aGUgcHJvdmlkZWQga2V5IG9yIHBhdGggdG8gdGhlIHZhbHVlLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICByZWNvcmQuc2V0KCJrZXkiLCB2YWx1ZSk7CiAgICAgIGBgYAogICAgICAgVGhpcyBtZXRob2QgaXMgZ2VuZXJhbGx5IHZlcnkgc2ltaWxhciB0byBjYWxsaW5nIGBvYmplY3RbImtleSJdID0gdmFsdWVgIG9yCiAgICAgIGBvYmplY3Qua2V5ID0gdmFsdWVgLCBleGNlcHQgdGhhdCBpdCBwcm92aWRlcyBzdXBwb3J0IGZvciBjb21wdXRlZAogICAgICBwcm9wZXJ0aWVzLCB0aGUgYHNldFVua25vd25Qcm9wZXJ0eSgpYCBtZXRob2QgYW5kIHByb3BlcnR5IG9ic2VydmVycy4KICAgICAgICMjIyBDb21wdXRlZCBQcm9wZXJ0aWVzCiAgICAgICBJZiB5b3UgdHJ5IHRvIHNldCBhIHZhbHVlIG9uIGEga2V5IHRoYXQgaGFzIGEgY29tcHV0ZWQgcHJvcGVydHkgaGFuZGxlcgogICAgICBkZWZpbmVkIChzZWUgdGhlIGBnZXQoKWAgbWV0aG9kIGZvciBhbiBleGFtcGxlKSwgdGhlbiBgc2V0KClgIHdpbGwgY2FsbAogICAgICB0aGF0IG1ldGhvZCwgcGFzc2luZyBib3RoIHRoZSB2YWx1ZSBhbmQga2V5IGluc3RlYWQgb2Ygc2ltcGx5IGNoYW5naW5nCiAgICAgIHRoZSB2YWx1ZSBpdHNlbGYuIFRoaXMgaXMgdXNlZnVsIGZvciB0aG9zZSB0aW1lcyB3aGVuIHlvdSBuZWVkIHRvCiAgICAgIGltcGxlbWVudCBhIHByb3BlcnR5IHRoYXQgaXMgY29tcG9zZWQgb2Ygb25lIG9yIG1vcmUgbWVtYmVyCiAgICAgIHByb3BlcnRpZXMuCiAgICAgICAjIyMgVW5rbm93biBQcm9wZXJ0aWVzCiAgICAgICBJZiB5b3UgdHJ5IHRvIHNldCBhIHZhbHVlIG9uIGEga2V5IHRoYXQgaXMgdW5kZWZpbmVkIGluIHRoZSB0YXJnZXQKICAgICAgb2JqZWN0LCB0aGVuIHRoZSBgc2V0VW5rbm93blByb3BlcnR5KClgIGhhbmRsZXIgd2lsbCBiZSBjYWxsZWQgaW5zdGVhZC4gVGhpcwogICAgICBnaXZlcyB5b3UgYW4gb3Bwb3J0dW5pdHkgdG8gaW1wbGVtZW50IGNvbXBsZXggInZpcnR1YWwiIHByb3BlcnRpZXMgdGhhdAogICAgICBhcmUgbm90IHByZWRlZmluZWQgb24gdGhlIG9iamVjdC4gSWYgYHNldFVua25vd25Qcm9wZXJ0eSgpYCByZXR1cm5zCiAgICAgIHVuZGVmaW5lZCwgdGhlbiBgc2V0KClgIHdpbGwgc2ltcGx5IHNldCB0aGUgdmFsdWUgb24gdGhlIG9iamVjdC4KICAgICAgICMjIyBQcm9wZXJ0eSBPYnNlcnZlcnMKICAgICAgIEluIGFkZGl0aW9uIHRvIGNoYW5naW5nIHRoZSBwcm9wZXJ0eSwgYHNldCgpYCB3aWxsIGFsc28gcmVnaXN0ZXIgYSBwcm9wZXJ0eQogICAgICBjaGFuZ2Ugd2l0aCB0aGUgb2JqZWN0LiBVbmxlc3MgeW91IGhhdmUgcGxhY2VkIHRoaXMgY2FsbCBpbnNpZGUgb2YgYQogICAgICBgYmVnaW5Qcm9wZXJ0eUNoYW5nZXMoKWAgYW5kIGBlbmRQcm9wZXJ0eUNoYW5nZXMoKSxgIGFueSAibG9jYWwiIG9ic2VydmVycwogICAgICAoaS5lLiBvYnNlcnZlciBtZXRob2RzIGRlY2xhcmVkIG9uIHRoZSBzYW1lIG9iamVjdCksIHdpbGwgYmUgY2FsbGVkCiAgICAgIGltbWVkaWF0ZWx5LiBBbnkgInJlbW90ZSIgb2JzZXJ2ZXJzIChpLmUuIG9ic2VydmVyIG1ldGhvZHMgZGVjbGFyZWQgb24KICAgICAgYW5vdGhlciBvYmplY3QpIHdpbGwgYmUgcGxhY2VkIGluIGEgcXVldWUgYW5kIGNhbGxlZCBhdCBhIGxhdGVyIHRpbWUgaW4gYQogICAgICBjb2FsZXNjZWQgbWFubmVyLgogICAgICAgQG1ldGhvZCBzZXQKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIHByb3BlcnR5IHRvIHNldAogICAgICBAcGFyYW0ge09iamVjdH0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldCBvciBgbnVsbGAuCiAgICAgIEByZXR1cm4ge09iamVjdH0gVGhlIHBhc3NlZCB2YWx1ZQogICAgICBAcHVibGljCiAgICAqLwogICAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5TmFtZSwgdmFsdWUpIHsKICAgICAgcmV0dXJuICgwLCBfbWV0YWwuc2V0KSh0aGlzLCBrZXlOYW1lLCB2YWx1ZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBTZXRzIGEgbGlzdCBvZiBwcm9wZXJ0aWVzIGF0IG9uY2UuIFRoZXNlIHByb3BlcnRpZXMgYXJlIHNldCBpbnNpZGUKICAgICAgYSBzaW5nbGUgYGJlZ2luUHJvcGVydHlDaGFuZ2VzYCBhbmQgYGVuZFByb3BlcnR5Q2hhbmdlc2AgYmF0Y2gsIHNvCiAgICAgIG9ic2VydmVycyB3aWxsIGJlIGJ1ZmZlcmVkLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICByZWNvcmQuc2V0UHJvcGVydGllcyh7IGZpcnN0TmFtZTogJ0NoYXJsZXMnLCBsYXN0TmFtZTogJ0pvbGxleScgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXRQcm9wZXJ0aWVzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBoYXNoIHRoZSBoYXNoIG9mIGtleXMgYW5kIHZhbHVlcyB0byBzZXQKICAgICAgQHJldHVybiB7T2JqZWN0fSBUaGUgcGFzc2VkIGluIGhhc2gKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHNldFByb3BlcnRpZXM6IGZ1bmN0aW9uIHNldFByb3BlcnRpZXMoaGFzaCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5zZXRQcm9wZXJ0aWVzKSh0aGlzLCBoYXNoKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEJlZ2lucyBhIGdyb3VwaW5nIG9mIHByb3BlcnR5IGNoYW5nZXMuCiAgICAgICBZb3UgY2FuIHVzZSB0aGlzIG1ldGhvZCB0byBncm91cCBwcm9wZXJ0eSBjaGFuZ2VzIHNvIHRoYXQgbm90aWZpY2F0aW9ucwogICAgICB3aWxsIG5vdCBiZSBzZW50IHVudGlsIHRoZSBjaGFuZ2VzIGFyZSBmaW5pc2hlZC4gSWYgeW91IHBsYW4gdG8gbWFrZSBhCiAgICAgIGxhcmdlIG51bWJlciBvZiBjaGFuZ2VzIHRvIGFuIG9iamVjdCBhdCBvbmUgdGltZSwgeW91IHNob3VsZCBjYWxsIHRoaXMKICAgICAgbWV0aG9kIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGNoYW5nZXMgdG8gYmVnaW4gZGVmZXJyaW5nIGNoYW5nZQogICAgICBub3RpZmljYXRpb25zLiBXaGVuIHlvdSBhcmUgZG9uZSBtYWtpbmcgY2hhbmdlcywgY2FsbAogICAgICBgZW5kUHJvcGVydHlDaGFuZ2VzKClgIHRvIGRlbGl2ZXIgdGhlIGRlZmVycmVkIGNoYW5nZSBub3RpZmljYXRpb25zIGFuZCBlbmQKICAgICAgZGVmZXJyaW5nLgogICAgICAgQG1ldGhvZCBiZWdpblByb3BlcnR5Q2hhbmdlcwogICAgICBAcmV0dXJuIHtPYnNlcnZhYmxlfQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGJlZ2luUHJvcGVydHlDaGFuZ2VzOiBmdW5jdGlvbiBiZWdpblByb3BlcnR5Q2hhbmdlcygpIHsKICAgICAgKDAsIF9tZXRhbC5iZWdpblByb3BlcnR5Q2hhbmdlcykoKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgICBFbmRzIGEgZ3JvdXBpbmcgb2YgcHJvcGVydHkgY2hhbmdlcy4KICAgICAgIFlvdSBjYW4gdXNlIHRoaXMgbWV0aG9kIHRvIGdyb3VwIHByb3BlcnR5IGNoYW5nZXMgc28gdGhhdCBub3RpZmljYXRpb25zCiAgICAgIHdpbGwgbm90IGJlIHNlbnQgdW50aWwgdGhlIGNoYW5nZXMgYXJlIGZpbmlzaGVkLiBJZiB5b3UgcGxhbiB0byBtYWtlIGEKICAgICAgbGFyZ2UgbnVtYmVyIG9mIGNoYW5nZXMgdG8gYW4gb2JqZWN0IGF0IG9uZSB0aW1lLCB5b3Ugc2hvdWxkIGNhbGwKICAgICAgYGJlZ2luUHJvcGVydHlDaGFuZ2VzKClgIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGNoYW5nZXMgdG8gZGVmZXIgY2hhbmdlCiAgICAgIG5vdGlmaWNhdGlvbnMuIFdoZW4geW91IGFyZSBkb25lIG1ha2luZyBjaGFuZ2VzLCBjYWxsIHRoaXMgbWV0aG9kIHRvCiAgICAgIGRlbGl2ZXIgdGhlIGRlZmVycmVkIGNoYW5nZSBub3RpZmljYXRpb25zIGFuZCBlbmQgZGVmZXJyaW5nLgogICAgICAgQG1ldGhvZCBlbmRQcm9wZXJ0eUNoYW5nZXMKICAgICAgQHJldHVybiB7T2JzZXJ2YWJsZX0KICAgICAgQHByaXZhdGUKICAgICovCiAgICBlbmRQcm9wZXJ0eUNoYW5nZXM6IGZ1bmN0aW9uIGVuZFByb3BlcnR5Q2hhbmdlcygpIHsKICAgICAgKDAsIF9tZXRhbC5lbmRQcm9wZXJ0eUNoYW5nZXMpKCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgTm90aWZ5IHRoZSBvYnNlcnZlciBzeXN0ZW0gdGhhdCBhIHByb3BlcnR5IGhhcyBqdXN0IGNoYW5nZWQuCiAgICAgICBTb21ldGltZXMgeW91IG5lZWQgdG8gY2hhbmdlIGEgdmFsdWUgZGlyZWN0bHkgb3IgaW5kaXJlY3RseSB3aXRob3V0CiAgICAgIGFjdHVhbGx5IGNhbGxpbmcgYGdldCgpYCBvciBgc2V0KClgIG9uIGl0LiBJbiB0aGlzIGNhc2UsIHlvdSBjYW4gdXNlIHRoaXMKICAgICAgbWV0aG9kIGluc3RlYWQuIENhbGxpbmcgdGhpcyBtZXRob2Qgd2lsbCBub3RpZnkgYWxsIG9ic2VydmVycyB0aGF0IHRoZQogICAgICBwcm9wZXJ0eSBoYXMgcG90ZW50aWFsbHkgY2hhbmdlZCB2YWx1ZS4KICAgICAgIEBtZXRob2Qgbm90aWZ5UHJvcGVydHlDaGFuZ2UKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIHByb3BlcnR5IGtleSB0byBiZSBub3RpZmllZCBhYm91dC4KICAgICAgQHJldHVybiB7T2JzZXJ2YWJsZX0KICAgICAgQHB1YmxpYwogICAgKi8KICAgIG5vdGlmeVByb3BlcnR5Q2hhbmdlOiBmdW5jdGlvbiBub3RpZnlQcm9wZXJ0eUNoYW5nZShrZXlOYW1lKSB7CiAgICAgICgwLCBfbWV0YWwubm90aWZ5UHJvcGVydHlDaGFuZ2UpKHRoaXMsIGtleU5hbWUpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCgogICAgLyoqCiAgICAgIEFkZHMgYW4gb2JzZXJ2ZXIgb24gYSBwcm9wZXJ0eS4KICAgICAgIFRoaXMgaXMgdGhlIGNvcmUgbWV0aG9kIHVzZWQgdG8gcmVnaXN0ZXIgYW4gb2JzZXJ2ZXIgZm9yIGEgcHJvcGVydHkuCiAgICAgICBPbmNlIHlvdSBjYWxsIHRoaXMgbWV0aG9kLCBhbnkgdGltZSB0aGUga2V5J3MgdmFsdWUgaXMgc2V0LCB5b3VyIG9ic2VydmVyCiAgICAgIHdpbGwgYmUgbm90aWZpZWQuIE5vdGUgdGhhdCB0aGUgb2JzZXJ2ZXJzIGFyZSB0cmlnZ2VyZWQgYW55IHRpbWUgdGhlCiAgICAgIHZhbHVlIGlzIHNldCwgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIGl0IGhhcyBhY3R1YWxseSBjaGFuZ2VkLiBZb3VyCiAgICAgIG9ic2VydmVyIHNob3VsZCBiZSBwcmVwYXJlZCB0byBoYW5kbGUgdGhhdC4KICAgICAgIFRoZXJlIGFyZSB0d28gY29tbW9uIGludm9jYXRpb24gcGF0dGVybnMgZm9yIGAuYWRkT2JzZXJ2ZXIoKWA6CiAgICAgICAtIFBhc3NpbmcgdHdvIGFyZ3VtZW50czoKICAgICAgICAtIHRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBvYnNlcnZlIChhcyBhIHN0cmluZykKICAgICAgICAtIHRoZSBmdW5jdGlvbiB0byBpbnZva2UgKGFuIGFjdHVhbCBmdW5jdGlvbikKICAgICAgLSBQYXNzaW5nIHRocmVlIGFyZ3VtZW50czoKICAgICAgICAtIHRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBvYnNlcnZlIChhcyBhIHN0cmluZykKICAgICAgICAtIHRoZSB0YXJnZXQgb2JqZWN0ICh3aWxsIGJlIHVzZWQgdG8gbG9vayB1cCBhbmQgaW52b2tlIGEKICAgICAgICAgIGZ1bmN0aW9uIG9uKQogICAgICAgIC0gdGhlIG5hbWUgb2YgdGhlIGZ1bmN0aW9uIHRvIGludm9rZSBvbiB0aGUgdGFyZ2V0IG9iamVjdAogICAgICAgICAgKGFzIGEgc3RyaW5nKS4KICAgICAgIGBgYGFwcC9jb21wb25lbnRzL215LWNvbXBvbmVudC5qcwogICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgaW5pdCgpIHsKICAgICAgICAgIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cyk7CiAgICAgICAgICAgLy8gdGhlIGZvbGxvd2luZyBhcmUgZXF1aXZhbGVudDoKICAgICAgICAgICAvLyB1c2luZyB0aHJlZSBhcmd1bWVudHMKICAgICAgICAgIHRoaXMuYWRkT2JzZXJ2ZXIoJ2ZvbycsIHRoaXMsICdmb29EaWRDaGFuZ2UnKTsKICAgICAgICAgICAvLyB1c2luZyB0d28gYXJndW1lbnRzCiAgICAgICAgICB0aGlzLmFkZE9ic2VydmVyKCdmb28nLCAoLi4uYXJncykgPT4gewogICAgICAgICAgICB0aGlzLmZvb0RpZENoYW5nZSguLi5hcmdzKTsKICAgICAgICAgIH0pOwogICAgICAgIH0sCiAgICAgICAgIGZvb0RpZENoYW5nZSgpIHsKICAgICAgICAgIC8vIHlvdXIgY3VzdG9tIGxvZ2ljIGNvZGUKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICMjIyBPYnNlcnZlciBNZXRob2RzCiAgICAgICBPYnNlcnZlciBtZXRob2RzIGhhdmUgdGhlIGZvbGxvd2luZyBzaWduYXR1cmU6CiAgICAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICAgIGluaXQoKSB7CiAgICAgICAgICB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogICAgICAgICAgdGhpcy5hZGRPYnNlcnZlcignZm9vJywgdGhpcywgJ2Zvb0RpZENoYW5nZScpOwogICAgICAgIH0sCiAgICAgICAgIGZvb0RpZENoYW5nZShzZW5kZXIsIGtleSwgdmFsdWUsIHJldikgewogICAgICAgICAgLy8geW91ciBjb2RlCiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBUaGUgYHNlbmRlcmAgaXMgdGhlIG9iamVjdCB0aGF0IGNoYW5nZWQuIFRoZSBga2V5YCBpcyB0aGUgcHJvcGVydHkgdGhhdAogICAgICBjaGFuZ2VzLiBUaGUgYHZhbHVlYCBwcm9wZXJ0eSBpcyBjdXJyZW50bHkgcmVzZXJ2ZWQgYW5kIHVudXNlZC4gVGhlIGByZXZgCiAgICAgIGlzIHRoZSBsYXN0IHByb3BlcnR5IHJldmlzaW9uIG9mIHRoZSBvYmplY3Qgd2hlbiBpdCBjaGFuZ2VkLCB3aGljaCB5b3UgY2FuCiAgICAgIHVzZSB0byBkZXRlY3QgaWYgdGhlIGtleSB2YWx1ZSBoYXMgcmVhbGx5IGNoYW5nZWQgb3Igbm90LgogICAgICAgVXN1YWxseSB5b3Ugd2lsbCBub3QgbmVlZCB0aGUgdmFsdWUgb3IgcmV2aXNpb24gcGFyYW1ldGVycyBhdAogICAgICB0aGUgZW5kLiBJbiB0aGlzIGNhc2UsIGl0IGlzIGNvbW1vbiB0byB3cml0ZSBvYnNlcnZlciBtZXRob2RzIHRoYXQgdGFrZQogICAgICBvbmx5IGEgc2VuZGVyIGFuZCBrZXkgdmFsdWUgYXMgcGFyYW1ldGVycyBvciwgaWYgeW91IGFyZW4ndCBpbnRlcmVzdGVkIGluCiAgICAgIGFueSBvZiB0aGVzZSB2YWx1ZXMsIHRvIHdyaXRlIGFuIG9ic2VydmVyIHRoYXQgaGFzIG5vIHBhcmFtZXRlcnMgYXQgYWxsLgogICAgICAgQG1ldGhvZCBhZGRPYnNlcnZlcgogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5IFRoZSBrZXkgdG8gb2JzZXJ2ZQogICAgICBAcGFyYW0ge09iamVjdH0gdGFyZ2V0IFRoZSB0YXJnZXQgb2JqZWN0IHRvIGludm9rZQogICAgICBAcGFyYW0ge1N0cmluZ3xGdW5jdGlvbn0gbWV0aG9kIFRoZSBtZXRob2QgdG8gaW52b2tlCiAgICAgIEBwYXJhbSB7Qm9vbGVhbn0gYXN5bmMgV2hldGhlciB0aGUgb2JzZXJ2ZXIgaXMgYXN5bmMgb3Igbm90CiAgICAgIEByZXR1cm4ge09ic2VydmFibGV9CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBhZGRPYnNlcnZlcjogZnVuY3Rpb24gYWRkT2JzZXJ2ZXIoa2V5LCB0YXJnZXQsIG1ldGhvZCwgYXN5bmMpIHsKICAgICAgKDAsIF9tZXRhbC5hZGRPYnNlcnZlcikodGhpcywga2V5LCB0YXJnZXQsIG1ldGhvZCwgYXN5bmMpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCgogICAgLyoqCiAgICAgIFJlbW92ZSBhbiBvYnNlcnZlciB5b3UgaGF2ZSBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgb24gdGhpcyBvYmplY3QuIFBhc3MKICAgICAgdGhlIHNhbWUga2V5LCB0YXJnZXQsIGFuZCBtZXRob2QgeW91IHBhc3NlZCB0byBgYWRkT2JzZXJ2ZXIoKWAgYW5kIHlvdXIKICAgICAgdGFyZ2V0IHdpbGwgbm8gbG9uZ2VyIHJlY2VpdmUgbm90aWZpY2F0aW9ucy4KICAgICAgIEBtZXRob2QgcmVtb3ZlT2JzZXJ2ZXIKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleSBUaGUga2V5IHRvIG9ic2VydmUKICAgICAgQHBhcmFtIHtPYmplY3R9IHRhcmdldCBUaGUgdGFyZ2V0IG9iamVjdCB0byBpbnZva2UKICAgICAgQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IG1ldGhvZCBUaGUgbWV0aG9kIHRvIGludm9rZQogICAgICBAcGFyYW0ge0Jvb2xlYW59IGFzeW5jIFdoZXRoZXIgdGhlIG9ic2VydmVyIGlzIGFzeW5jIG9yIG5vdAogICAgICBAcmV0dXJuIHtPYnNlcnZhYmxlfQogICAgICBAcHVibGljCiAgICAqLwogICAgcmVtb3ZlT2JzZXJ2ZXI6IGZ1bmN0aW9uIHJlbW92ZU9ic2VydmVyKGtleSwgdGFyZ2V0LCBtZXRob2QsIGFzeW5jKSB7CiAgICAgICgwLCBfbWV0YWwucmVtb3ZlT2JzZXJ2ZXIpKHRoaXMsIGtleSwgdGFyZ2V0LCBtZXRob2QsIGFzeW5jKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0IGN1cnJlbnRseSBoYXMgb2JzZXJ2ZXJzIHJlZ2lzdGVyZWQgZm9yIGEKICAgICAgcGFydGljdWxhciBrZXkuIFlvdSBjYW4gdXNlIHRoaXMgbWV0aG9kIHRvIHBvdGVudGlhbGx5IGRlZmVyIHBlcmZvcm1pbmcKICAgICAgYW4gZXhwZW5zaXZlIGFjdGlvbiB1bnRpbCBzb21lb25lIGJlZ2lucyBvYnNlcnZpbmcgYSBwYXJ0aWN1bGFyIHByb3BlcnR5CiAgICAgIG9uIHRoZSBvYmplY3QuCiAgICAgICBAbWV0aG9kIGhhc09ic2VydmVyRm9yCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkgS2V5IHRvIGNoZWNrCiAgICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgaGFzT2JzZXJ2ZXJGb3I6IGZ1bmN0aW9uIGhhc09ic2VydmVyRm9yKGtleSkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5oYXNMaXN0ZW5lcnMpKHRoaXMsIGtleSArICI6Y2hhbmdlIik7CiAgICB9LAoKICAgIC8qKgogICAgICBSZXRyaWV2ZXMgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHksIG9yIGEgZGVmYXVsdCB2YWx1ZSBpbiB0aGUgY2FzZSB0aGF0IHRoZQogICAgICBwcm9wZXJ0eSByZXR1cm5zIGB1bmRlZmluZWRgLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBwZXJzb24uZ2V0V2l0aERlZmF1bHQoJ2xhc3ROYW1lJywgJ0RvZScpOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZ2V0V2l0aERlZmF1bHQKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIHJldHJpZXZlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBkZWZhdWx0VmFsdWUgVGhlIHZhbHVlIHRvIHJldHVybiBpZiB0aGUgcHJvcGVydHkgdmFsdWUgaXMgdW5kZWZpbmVkCiAgICAgIEByZXR1cm4ge09iamVjdH0gVGhlIHByb3BlcnR5IHZhbHVlIG9yIHRoZSBkZWZhdWx0VmFsdWUuCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBnZXRXaXRoRGVmYXVsdDogZnVuY3Rpb24gZ2V0V2l0aERlZmF1bHQoa2V5TmFtZSwgZGVmYXVsdFZhbHVlKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldFdpdGhEZWZhdWx0KSh0aGlzLCBrZXlOYW1lLCBkZWZhdWx0VmFsdWUpOwogICAgfSwKCiAgICAvKioKICAgICAgU2V0IHRoZSB2YWx1ZSBvZiBhIHByb3BlcnR5IHRvIHRoZSBjdXJyZW50IHZhbHVlIHBsdXMgc29tZSBhbW91bnQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHBlcnNvbi5pbmNyZW1lbnRQcm9wZXJ0eSgnYWdlJyk7CiAgICAgIHRlYW0uaW5jcmVtZW50UHJvcGVydHkoJ3Njb3JlJywgMik7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBpbmNyZW1lbnRQcm9wZXJ0eQogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5TmFtZSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdG8gaW5jcmVtZW50CiAgICAgIEBwYXJhbSB7TnVtYmVyfSBpbmNyZW1lbnQgVGhlIGFtb3VudCB0byBpbmNyZW1lbnQgYnkuIERlZmF1bHRzIHRvIDEKICAgICAgQHJldHVybiB7TnVtYmVyfSBUaGUgbmV3IHByb3BlcnR5IHZhbHVlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBpbmNyZW1lbnRQcm9wZXJ0eTogZnVuY3Rpb24gaW5jcmVtZW50UHJvcGVydHkoa2V5TmFtZSwgaW5jcmVtZW50KSB7CiAgICAgIGlmIChpbmNyZW1lbnQgPT09IHZvaWQgMCkgewogICAgICAgIGluY3JlbWVudCA9IDE7CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKCFpc05hTihwYXJzZUZsb2F0KGluY3JlbWVudCkpICYmIGlzRmluaXRlKGluY3JlbWVudCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnTXVzdCBwYXNzIGEgbnVtZXJpYyB2YWx1ZSB0byBpbmNyZW1lbnRQcm9wZXJ0eScsICFpc05hTihwYXJzZUZsb2F0KGluY3JlbWVudCkpICYmIGlzRmluaXRlKGluY3JlbWVudCkpKTsKICAgICAgcmV0dXJuICgwLCBfbWV0YWwuc2V0KSh0aGlzLCBrZXlOYW1lLCAocGFyc2VGbG9hdCgoMCwgX21ldGFsLmdldCkodGhpcywga2V5TmFtZSkpIHx8IDApICsgaW5jcmVtZW50KTsKICAgIH0sCgogICAgLyoqCiAgICAgIFNldCB0aGUgdmFsdWUgb2YgYSBwcm9wZXJ0eSB0byB0aGUgY3VycmVudCB2YWx1ZSBtaW51cyBzb21lIGFtb3VudC4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgcGxheWVyLmRlY3JlbWVudFByb3BlcnR5KCdsaXZlcycpOwogICAgICBvcmMuZGVjcmVtZW50UHJvcGVydHkoJ2hlYWx0aCcsIDUpOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZGVjcmVtZW50UHJvcGVydHkKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIGRlY3JlbWVudAogICAgICBAcGFyYW0ge051bWJlcn0gZGVjcmVtZW50IFRoZSBhbW91bnQgdG8gZGVjcmVtZW50IGJ5LiBEZWZhdWx0cyB0byAxCiAgICAgIEByZXR1cm4ge051bWJlcn0gVGhlIG5ldyBwcm9wZXJ0eSB2YWx1ZQogICAgICBAcHVibGljCiAgICAqLwogICAgZGVjcmVtZW50UHJvcGVydHk6IGZ1bmN0aW9uIGRlY3JlbWVudFByb3BlcnR5KGtleU5hbWUsIGRlY3JlbWVudCkgewogICAgICBpZiAoZGVjcmVtZW50ID09PSB2b2lkIDApIHsKICAgICAgICBkZWNyZW1lbnQgPSAxOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISghaXNOYU4ocGFyc2VGbG9hdChkZWNyZW1lbnQpKSAmJiBpc0Zpbml0ZShkZWNyZW1lbnQpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ011c3QgcGFzcyBhIG51bWVyaWMgdmFsdWUgdG8gZGVjcmVtZW50UHJvcGVydHknLCAhaXNOYU4ocGFyc2VGbG9hdChkZWNyZW1lbnQpKSAmJiBpc0Zpbml0ZShkZWNyZW1lbnQpKSk7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLnNldCkodGhpcywga2V5TmFtZSwgKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBrZXlOYW1lKSB8fCAwKSAtIGRlY3JlbWVudCk7CiAgICB9LAoKICAgIC8qKgogICAgICBTZXQgdGhlIHZhbHVlIG9mIGEgYm9vbGVhbiBwcm9wZXJ0eSB0byB0aGUgb3Bwb3NpdGUgb2YgaXRzCiAgICAgIGN1cnJlbnQgdmFsdWUuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0YXJzaGlwLnRvZ2dsZVByb3BlcnR5KCd3YXJwRHJpdmVFbmdhZ2VkJyk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCB0b2dnbGVQcm9wZXJ0eQogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5TmFtZSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdG8gdG9nZ2xlCiAgICAgIEByZXR1cm4ge0Jvb2xlYW59IFRoZSBuZXcgcHJvcGVydHkgdmFsdWUKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHRvZ2dsZVByb3BlcnR5OiBmdW5jdGlvbiB0b2dnbGVQcm9wZXJ0eShrZXlOYW1lKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLnNldCkodGhpcywga2V5TmFtZSwgISgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBrZXlOYW1lKSk7CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSBjYWNoZWQgdmFsdWUgb2YgYSBjb21wdXRlZCBwcm9wZXJ0eSwgaWYgaXQgZXhpc3RzLgogICAgICBUaGlzIGFsbG93cyB5b3UgdG8gaW5zcGVjdCB0aGUgdmFsdWUgb2YgYSBjb21wdXRlZCBwcm9wZXJ0eQogICAgICB3aXRob3V0IGFjY2lkZW50YWxseSBpbnZva2luZyBpdCBpZiBpdCBpcyBpbnRlbmRlZCB0byBiZQogICAgICBnZW5lcmF0ZWQgbGF6aWx5LgogICAgICAgQG1ldGhvZCBjYWNoZUZvcgogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5TmFtZQogICAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSBjYWNoZWQgdmFsdWUgb2YgdGhlIGNvbXB1dGVkIHByb3BlcnR5LCBpZiBhbnkKICAgICAgQHB1YmxpYwogICAgKi8KICAgIGNhY2hlRm9yOiBmdW5jdGlvbiBjYWNoZUZvcihrZXlOYW1lKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldENhY2hlZFZhbHVlRm9yKSh0aGlzLCBrZXlOYW1lKTsKICAgIH0KICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvcHJvbWlzZV9wcm94eSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZXJyb3IiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwsIF9lcnJvcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwogIGZ1bmN0aW9uIHRhcChwcm94eSwgcHJvbWlzZSkgewogICAgKDAsIF9tZXRhbC5zZXRQcm9wZXJ0aWVzKShwcm94eSwgewogICAgICBpc0Z1bGZpbGxlZDogZmFsc2UsCiAgICAgIGlzUmVqZWN0ZWQ6IGZhbHNlCiAgICB9KTsKICAgIHJldHVybiBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgIGlmICghcHJveHkuaXNEZXN0cm95ZWQgJiYgIXByb3h5LmlzRGVzdHJveWluZykgewogICAgICAgICgwLCBfbWV0YWwuc2V0UHJvcGVydGllcykocHJveHksIHsKICAgICAgICAgIGNvbnRlbnQ6IHZhbHVlLAogICAgICAgICAgaXNGdWxmaWxsZWQ6IHRydWUKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICBpZiAoIXByb3h5LmlzRGVzdHJveWVkICYmICFwcm94eS5pc0Rlc3Ryb3lpbmcpIHsKICAgICAgICAoMCwgX21ldGFsLnNldFByb3BlcnRpZXMpKHByb3h5LCB7CiAgICAgICAgICByZWFzb246IHJlYXNvbiwKICAgICAgICAgIGlzUmVqZWN0ZWQ6IHRydWUKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgdGhyb3cgcmVhc29uOwogICAgfSwgJ0VtYmVyOiBQcm9taXNlUHJveHknKTsKICB9CiAgLyoqCiAgICBBIGxvdyBsZXZlbCBtaXhpbiBtYWtpbmcgT2JqZWN0UHJveHkgcHJvbWlzZS1hd2FyZS4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHJlc29sdmUgfSBmcm9tICdyc3ZwJzsKICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeSc7CiAgICBpbXBvcnQgT2JqZWN0UHJveHkgZnJvbSAnQGVtYmVyL29iamVjdC9wcm94eSc7CiAgICBpbXBvcnQgUHJvbWlzZVByb3h5TWl4aW4gZnJvbSAnQGVtYmVyL29iamVjdC9wcm9taXNlLXByb3h5LW1peGluJzsKICAKICAgIGxldCBPYmplY3RQcm9taXNlUHJveHkgPSBPYmplY3RQcm94eS5leHRlbmQoUHJvbWlzZVByb3h5TWl4aW4pOwogIAogICAgbGV0IHByb3h5ID0gT2JqZWN0UHJvbWlzZVByb3h5LmNyZWF0ZSh7CiAgICAgIHByb21pc2U6IHJlc29sdmUoJC5nZXRKU09OKCcvc29tZS9yZW1vdGUvZGF0YS5qc29uJykpCiAgICB9KTsKICAKICAgIHByb3h5LnRoZW4oZnVuY3Rpb24oanNvbil7CiAgICAgICAvLyB0aGUganNvbgogICAgfSwgZnVuY3Rpb24ocmVhc29uKSB7CiAgICAgICAvLyB0aGUgcmVhc29uIHdoeSB5b3UgaGF2ZSBubyBqc29uCiAgICB9KTsKICAgIGBgYAogIAogICAgdGhlIHByb3h5IGhhcyBiaW5kYWJsZSBhdHRyaWJ1dGVzIHdoaWNoCiAgICB0cmFjayB0aGUgcHJvbWlzZXMgbGlmZSBjeWNsZQogIAogICAgYGBgamF2YXNjcmlwdAogICAgcHJveHkuZ2V0KCdpc1BlbmRpbmcnKSAgIC8vPT4gdHJ1ZQogICAgcHJveHkuZ2V0KCdpc1NldHRsZWQnKSAgLy89PiBmYWxzZQogICAgcHJveHkuZ2V0KCdpc1JlamVjdGVkJykgIC8vPT4gZmFsc2UKICAgIHByb3h5LmdldCgnaXNGdWxmaWxsZWQnKSAvLz0+IGZhbHNlCiAgICBgYGAKICAKICAgIFdoZW4gdGhlICQuZ2V0SlNPTiBjb21wbGV0ZXMsIGFuZCB0aGUgcHJvbWlzZSBpcyBmdWxmaWxsZWQKICAgIHdpdGgganNvbiwgdGhlIGxpZmUgY3ljbGUgYXR0cmlidXRlcyB3aWxsIHVwZGF0ZSBhY2NvcmRpbmdseS4KICAgIE5vdGUgdGhhdCAkLmdldEpTT04gZG9lc24ndCByZXR1cm4gYW4gRUNNQSBzcGVjaWZpZWQgcHJvbWlzZSwKICAgIGl0IGlzIHVzZWZ1bCB0byB3cmFwIHRoaXMgd2l0aCBhbiBgUlNWUC5yZXNvbHZlYCBzbyB0aGF0IGl0IGJlaGF2ZXMKICAgIGFzIGEgc3BlYyBjb21wbGlhbnQgcHJvbWlzZS4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIHByb3h5LmdldCgnaXNQZW5kaW5nJykgICAvLz0+IGZhbHNlCiAgICBwcm94eS5nZXQoJ2lzU2V0dGxlZCcpICAgLy89PiB0cnVlCiAgICBwcm94eS5nZXQoJ2lzUmVqZWN0ZWQnKSAgLy89PiBmYWxzZQogICAgcHJveHkuZ2V0KCdpc0Z1bGZpbGxlZCcpIC8vPT4gdHJ1ZQogICAgYGBgCiAgCiAgICBBcyB0aGUgcHJveHkgaXMgYW4gT2JqZWN0UHJveHksIGFuZCB0aGUganNvbiBub3cgaXRzIGNvbnRlbnQsCiAgICBhbGwgdGhlIGpzb24gcHJvcGVydGllcyB3aWxsIGJlIGF2YWlsYWJsZSBkaXJlY3RseSBmcm9tIHRoZSBwcm94eS4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIC8vIEFzc3VtaW5nIHRoZSBmb2xsb3dpbmcganNvbjoKICAgIHsKICAgICAgZmlyc3ROYW1lOiAnU3RlZmFuJywKICAgICAgbGFzdE5hbWU6ICdQZW5uZXInCiAgICB9CiAgCiAgICAvLyBib3RoIHByb3BlcnRpZXMgd2lsbCBhY2Nlc3NpYmxlIG9uIHRoZSBwcm94eQogICAgcHJveHkuZ2V0KCdmaXJzdE5hbWUnKSAvLz0+ICdTdGVmYW4nCiAgICBwcm94eS5nZXQoJ2xhc3ROYW1lJykgIC8vPT4gJ1Blbm5lcicKICAgIGBgYAogIAogICAgQGNsYXNzIFByb21pc2VQcm94eU1peGluCiAgICBAcHVibGljCiAgKi8KCgogIHZhciBfZGVmYXVsdCA9IF9tZXRhbC5NaXhpbi5jcmVhdGUoewogICAgLyoqCiAgICAgIElmIHRoZSBwcm94aWVkIHByb21pc2UgaXMgcmVqZWN0ZWQgdGhpcyB3aWxsIGNvbnRhaW4gdGhlIHJlYXNvbgogICAgICBwcm92aWRlZC4KICAgICAgIEBwcm9wZXJ0eSByZWFzb24KICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwogICAgcmVhc29uOiBudWxsLAoKICAgIC8qKgogICAgICBPbmNlIHRoZSBwcm94aWVkIHByb21pc2UgaGFzIHNldHRsZWQgdGhpcyB3aWxsIGJlY29tZSBgZmFsc2VgLgogICAgICAgQHByb3BlcnR5IGlzUGVuZGluZwogICAgICBAZGVmYXVsdCB0cnVlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBpc1BlbmRpbmc6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKCdpc1NldHRsZWQnLCBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAhKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdpc1NldHRsZWQnKTsKICAgIH0pLnJlYWRPbmx5KCksCgogICAgLyoqCiAgICAgIE9uY2UgdGhlIHByb3hpZWQgcHJvbWlzZSBoYXMgc2V0dGxlZCB0aGlzIHdpbGwgYmVjb21lIGB0cnVlYC4KICAgICAgIEBwcm9wZXJ0eSBpc1NldHRsZWQKICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgQHB1YmxpYwogICAgKi8KICAgIGlzU2V0dGxlZDogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ2lzUmVqZWN0ZWQnLCAnaXNGdWxmaWxsZWQnLCBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkodGhpcywgJ2lzUmVqZWN0ZWQnKSB8fCAoMCwgX21ldGFsLmdldCkodGhpcywgJ2lzRnVsZmlsbGVkJyk7CiAgICB9KS5yZWFkT25seSgpLAoKICAgIC8qKgogICAgICBXaWxsIGJlY29tZSBgdHJ1ZWAgaWYgdGhlIHByb3hpZWQgcHJvbWlzZSBpcyByZWplY3RlZC4KICAgICAgIEBwcm9wZXJ0eSBpc1JlamVjdGVkCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBpc1JlamVjdGVkOiBmYWxzZSwKCiAgICAvKioKICAgICAgV2lsbCBiZWNvbWUgYHRydWVgIGlmIHRoZSBwcm94aWVkIHByb21pc2UgaXMgZnVsZmlsbGVkLgogICAgICAgQHByb3BlcnR5IGlzRnVsZmlsbGVkCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBpc0Z1bGZpbGxlZDogZmFsc2UsCgogICAgLyoqCiAgICAgIFRoZSBwcm9taXNlIHdob3NlIGZ1bGZpbGxtZW50IHZhbHVlIGlzIGJlaW5nIHByb3hpZWQgYnkgdGhpcyBvYmplY3QuCiAgICAgICBUaGlzIHByb3BlcnR5IG11c3QgYmUgc3BlY2lmaWVkIHVwb24gY3JlYXRpb24sIGFuZCBzaG91bGQgbm90IGJlCiAgICAgIGNoYW5nZWQgb25jZSBjcmVhdGVkLgogICAgICAgRXhhbXBsZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IE9iamVjdFByb3h5IGZyb20gJ0BlbWJlci9vYmplY3QvcHJveHknOwogICAgICBpbXBvcnQgUHJvbWlzZVByb3h5TWl4aW4gZnJvbSAnQGVtYmVyL29iamVjdC9wcm9taXNlLXByb3h5LW1peGluJzsKICAgICAgIE9iamVjdFByb3h5LmV4dGVuZChQcm9taXNlUHJveHlNaXhpbikuY3JlYXRlKHsKICAgICAgICBwcm9taXNlOiA8dGhlbmFibGU+CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBwcm9taXNlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBwcm9taXNlOiAoMCwgX21ldGFsLmNvbXB1dGVkKSh7CiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHRocm93IG5ldyBfZXJyb3IuZGVmYXVsdCgiUHJvbWlzZVByb3h5J3MgcHJvbWlzZSBtdXN0IGJlIHNldCIpOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldChrZXksIHByb21pc2UpIHsKICAgICAgICByZXR1cm4gdGFwKHRoaXMsIHByb21pc2UpOwogICAgICB9CiAgICB9KSwKCiAgICAvKioKICAgICAgQW4gYWxpYXMgdG8gdGhlIHByb3hpZWQgcHJvbWlzZSdzIGB0aGVuYC4KICAgICAgIFNlZSBSU1ZQLlByb21pc2UudGhlbi4KICAgICAgIEBtZXRob2QgdGhlbgogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgICBAcmV0dXJuIHtSU1ZQLlByb21pc2V9CiAgICAgIEBwdWJsaWMKICAgICovCiAgICB0aGVuOiBwcm9taXNlQWxpYXMoJ3RoZW4nKSwKCiAgICAvKioKICAgICAgQW4gYWxpYXMgdG8gdGhlIHByb3hpZWQgcHJvbWlzZSdzIGBjYXRjaGAuCiAgICAgICBTZWUgUlNWUC5Qcm9taXNlLmNhdGNoLgogICAgICAgQG1ldGhvZCBjYXRjaAogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgICBAcmV0dXJuIHtSU1ZQLlByb21pc2V9CiAgICAgIEBzaW5jZSAxLjMuMAogICAgICBAcHVibGljCiAgICAqLwogICAgY2F0Y2g6IHByb21pc2VBbGlhcygnY2F0Y2gnKSwKCiAgICAvKioKICAgICAgQW4gYWxpYXMgdG8gdGhlIHByb3hpZWQgcHJvbWlzZSdzIGBmaW5hbGx5YC4KICAgICAgIFNlZSBSU1ZQLlByb21pc2UuZmluYWxseS4KICAgICAgIEBtZXRob2QgZmluYWxseQogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgICBAcmV0dXJuIHtSU1ZQLlByb21pc2V9CiAgICAgIEBzaW5jZSAxLjMuMAogICAgICBAcHVibGljCiAgICAqLwogICAgZmluYWxseTogcHJvbWlzZUFsaWFzKCdmaW5hbGx5JykKICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OwoKICBmdW5jdGlvbiBwcm9taXNlQWxpYXMobmFtZSkgewogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIHByb21pc2UgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ3Byb21pc2UnKTsKICAgICAgcmV0dXJuIHByb21pc2VbbmFtZV0uYXBwbHkocHJvbWlzZSwgYXJndW1lbnRzKTsKICAgIH07CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvcmVnaXN0cnlfcHJveHkiLCBbImV4cG9ydHMiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlYnVnLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIFJlZ2lzdHJ5UHJveHlNaXhpbiBpcyB1c2VkIHRvIHByb3ZpZGUgcHVibGljIGFjY2VzcyB0byBzcGVjaWZpYwogICAgcmVnaXN0cnkgZnVuY3Rpb25hbGl0eS4KICAKICAgIEBjbGFzcyBSZWdpc3RyeVByb3h5TWl4aW4KICAgIEBwcml2YXRlCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIF9fcmVnaXN0cnlfXzogbnVsbCwKCiAgICAvKioKICAgICBHaXZlbiBhIGZ1bGxOYW1lIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyBmYWN0b3J5LgogICAgICBAcHVibGljCiAgICAgQG1ldGhvZCByZXNvbHZlUmVnaXN0cmF0aW9uCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHJldHVybiB7RnVuY3Rpb259IGZ1bGxOYW1lJ3MgZmFjdG9yeQogICAgICovCiAgICByZXNvbHZlUmVnaXN0cmF0aW9uOiBmdW5jdGlvbiByZXNvbHZlUmVnaXN0cmF0aW9uKGZ1bGxOYW1lLCBvcHRpb25zKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMuX19yZWdpc3RyeV9fLmlzVmFsaWRGdWxsTmFtZShmdWxsTmFtZSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnZnVsbE5hbWUgbXVzdCBiZSBhIHByb3BlciBmdWxsIG5hbWUnLCB0aGlzLl9fcmVnaXN0cnlfXy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSk7CiAgICAgIHJldHVybiB0aGlzLl9fcmVnaXN0cnlfXy5yZXNvbHZlKGZ1bGxOYW1lLCBvcHRpb25zKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFJlZ2lzdGVycyBhIGZhY3RvcnkgdGhhdCBjYW4gYmUgdXNlZCBmb3IgZGVwZW5kZW5jeSBpbmplY3Rpb24gKHdpdGgKICAgICAgYGluamVjdGApIG9yIGZvciBzZXJ2aWNlIGxvb2t1cC4gRWFjaCBmYWN0b3J5IGlzIHJlZ2lzdGVyZWQgd2l0aAogICAgICBhIGZ1bGwgbmFtZSBpbmNsdWRpbmcgdHdvIHBhcnRzOiBgdHlwZTpuYW1lYC4KICAgICAgIEEgc2ltcGxlIGV4YW1wbGU6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgICBsZXQgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKCk7CiAgICAgICBBcHAuT3JhbmdlID0gRW1iZXJPYmplY3QuZXh0ZW5kKCk7CiAgICAgIEFwcC5yZWdpc3RlcignZnJ1aXQ6ZmF2b3JpdGUnLCBBcHAuT3JhbmdlKTsKICAgICAgYGBgCiAgICAgICBFbWJlciB3aWxsIHJlc29sdmUgZmFjdG9yaWVzIGZyb20gdGhlIGBBcHBgIG5hbWVzcGFjZSBhdXRvbWF0aWNhbGx5LgogICAgICBGb3IgZXhhbXBsZSBgQXBwLkNhcnNDb250cm9sbGVyYCB3aWxsIGJlIGRpc2NvdmVyZWQgYW5kIHJldHVybmVkIGlmCiAgICAgIGFuIGFwcGxpY2F0aW9uIHJlcXVlc3RzIGBjb250cm9sbGVyOmNhcnNgLgogICAgICAgQW4gZXhhbXBsZSBvZiByZWdpc3RlcmluZyBhIGNvbnRyb2xsZXIgd2l0aCBhIG5vbi1zdGFuZGFyZCBuYW1lOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAgICAgaW1wb3J0IENvbnRyb2xsZXIgZnJvbSAnQGVtYmVyL2NvbnRyb2xsZXInOwogICAgICAgbGV0IEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSgpOwogICAgICBsZXQgU2Vzc2lvbiA9IENvbnRyb2xsZXIuZXh0ZW5kKCk7CiAgICAgICBBcHAucmVnaXN0ZXIoJ2NvbnRyb2xsZXI6c2Vzc2lvbicsIFNlc3Npb24pOwogICAgICAgLy8gVGhlIFNlc3Npb24gY29udHJvbGxlciBjYW4gbm93IGJlIHRyZWF0ZWQgbGlrZSBhIG5vcm1hbCBjb250cm9sbGVyLAogICAgICAvLyBkZXNwaXRlIGl0cyBub24tc3RhbmRhcmQgbmFtZS4KICAgICAgQXBwLkFwcGxpY2F0aW9uQ29udHJvbGxlciA9IENvbnRyb2xsZXIuZXh0ZW5kKHsKICAgICAgICBuZWVkczogWydzZXNzaW9uJ10KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgUmVnaXN0ZXJlZCBmYWN0b3JpZXMgYXJlICoqaW5zdGFudGlhdGVkKiogYnkgaGF2aW5nIGBjcmVhdGVgCiAgICAgIGNhbGxlZCBvbiB0aGVtLiBBZGRpdGlvbmFsbHkgdGhleSBhcmUgKipzaW5nbGV0b25zKiosIGVhY2ggdGltZQogICAgICB0aGV5IGFyZSBsb29rZWQgdXAgdGhleSByZXR1cm4gdGhlIHNhbWUgaW5zdGFuY2UuCiAgICAgICBTb21lIGV4YW1wbGVzIG1vZGlmeWluZyB0aGF0IGRlZmF1bHQgYmVoYXZpb3I6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgICBsZXQgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKCk7CiAgICAgICBBcHAuUGVyc29uID0gRW1iZXJPYmplY3QuZXh0ZW5kKCk7CiAgICAgIEFwcC5PcmFuZ2UgPSBFbWJlck9iamVjdC5leHRlbmQoKTsKICAgICAgQXBwLkVtYWlsID0gRW1iZXJPYmplY3QuZXh0ZW5kKCk7CiAgICAgIEFwcC5zZXNzaW9uID0gRW1iZXJPYmplY3QuY3JlYXRlKCk7CiAgICAgICBBcHAucmVnaXN0ZXIoJ21vZGVsOnVzZXInLCBBcHAuUGVyc29uLCB7IHNpbmdsZXRvbjogZmFsc2UgfSk7CiAgICAgIEFwcC5yZWdpc3RlcignZnJ1aXQ6ZmF2b3JpdGUnLCBBcHAuT3JhbmdlKTsKICAgICAgQXBwLnJlZ2lzdGVyKCdjb21tdW5pY2F0aW9uOm1haW4nLCBBcHAuRW1haWwsIHsgc2luZ2xldG9uOiBmYWxzZSB9KTsKICAgICAgQXBwLnJlZ2lzdGVyKCdzZXNzaW9uJywgQXBwLnNlc3Npb24sIHsgaW5zdGFudGlhdGU6IGZhbHNlIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgcmVnaXN0ZXIKICAgICAgQHBhcmFtICBmdWxsTmFtZSB7U3RyaW5nfSB0eXBlOm5hbWUgKGUuZy4sICdtb2RlbDp1c2VyJykKICAgICAgQHBhcmFtICBmYWN0b3J5IHthbnl9IChlLmcuLCBBcHAuUGVyc29uKQogICAgICBAcGFyYW0gIG9wdGlvbnMge09iamVjdH0gKG9wdGlvbmFsKSBkaXNhYmxlIGluc3RhbnRpYXRpb24gb3Igc2luZ2xldG9uIHVzYWdlCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgcmVnaXN0ZXI6IHJlZ2lzdHJ5QWxpYXMoJ3JlZ2lzdGVyJyksCgogICAgLyoqCiAgICAgVW5yZWdpc3RlciBhIGZhY3RvcnkuCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoKTsKICAgICBsZXQgVXNlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCgpOwogICAgIEFwcC5yZWdpc3RlcignbW9kZWw6dXNlcicsIFVzZXIpOwogICAgICBBcHAucmVzb2x2ZVJlZ2lzdHJhdGlvbignbW9kZWw6dXNlcicpLmNyZWF0ZSgpIGluc3RhbmNlb2YgVXNlciAvLz0+IHRydWUKICAgICAgQXBwLnVucmVnaXN0ZXIoJ21vZGVsOnVzZXInKQogICAgIEFwcC5yZXNvbHZlUmVnaXN0cmF0aW9uKCdtb2RlbDp1c2VyJykgPT09IHVuZGVmaW5lZCAvLz0+IHRydWUKICAgICBgYGAKICAgICAgQHB1YmxpYwogICAgIEBtZXRob2QgdW5yZWdpc3RlcgogICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZQogICAgICovCiAgICB1bnJlZ2lzdGVyOiByZWdpc3RyeUFsaWFzKCd1bnJlZ2lzdGVyJyksCgogICAgLyoqCiAgICAgQ2hlY2sgaWYgYSBmYWN0b3J5IGlzIHJlZ2lzdGVyZWQuCiAgICAgIEBwdWJsaWMKICAgICBAbWV0aG9kIGhhc1JlZ2lzdHJhdGlvbgogICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZQogICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICAgKi8KICAgIGhhc1JlZ2lzdHJhdGlvbjogcmVnaXN0cnlBbGlhcygnaGFzJyksCgogICAgLyoqCiAgICAgUmV0dXJuIGEgc3BlY2lmaWMgcmVnaXN0ZXJlZCBvcHRpb24gZm9yIGEgcGFydGljdWxhciBmYWN0b3J5LgogICAgICBAcHVibGljCiAgICAgQG1ldGhvZCByZWdpc3RlcmVkT3B0aW9uCiAgICAgQHBhcmFtICB7U3RyaW5nfSBmdWxsTmFtZQogICAgIEBwYXJhbSAge1N0cmluZ30gb3B0aW9uTmFtZQogICAgIEByZXR1cm4ge09iamVjdH0gb3B0aW9ucwogICAgICovCiAgICByZWdpc3RlcmVkT3B0aW9uOiByZWdpc3RyeUFsaWFzKCdnZXRPcHRpb24nKSwKCiAgICAvKioKICAgICBSZWdpc3RlciBvcHRpb25zIGZvciBhIHBhcnRpY3VsYXIgZmFjdG9yeS4KICAgICAgQHB1YmxpYwogICAgIEBtZXRob2QgcmVnaXN0ZXJPcHRpb25zCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAqLwogICAgcmVnaXN0ZXJPcHRpb25zOiByZWdpc3RyeUFsaWFzKCdvcHRpb25zJyksCgogICAgLyoqCiAgICAgUmV0dXJuIHJlZ2lzdGVyZWQgb3B0aW9ucyBmb3IgYSBwYXJ0aWN1bGFyIGZhY3RvcnkuCiAgICAgIEBwdWJsaWMKICAgICBAbWV0aG9kIHJlZ2lzdGVyZWRPcHRpb25zCiAgICAgQHBhcmFtICB7U3RyaW5nfSBmdWxsTmFtZQogICAgIEByZXR1cm4ge09iamVjdH0gb3B0aW9ucwogICAgICovCiAgICByZWdpc3RlcmVkT3B0aW9uczogcmVnaXN0cnlBbGlhcygnZ2V0T3B0aW9ucycpLAoKICAgIC8qKgogICAgIEFsbG93IHJlZ2lzdGVyaW5nIG9wdGlvbnMgZm9yIGFsbCBmYWN0b3JpZXMgb2YgYSB0eXBlLgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoKTsKICAgICBsZXQgYXBwSW5zdGFuY2UgPSBBcHAuYnVpbGRJbnN0YW5jZSgpOwogICAgICAvLyBpZiBhbGwgb2YgdHlwZSBgY29ubmVjdGlvbmAgbXVzdCBub3QgYmUgc2luZ2xldG9ucwogICAgIGFwcEluc3RhbmNlLnJlZ2lzdGVyT3B0aW9uc0ZvclR5cGUoJ2Nvbm5lY3Rpb24nLCB7IHNpbmdsZXRvbjogZmFsc2UgfSk7CiAgICAgIGFwcEluc3RhbmNlLnJlZ2lzdGVyKCdjb25uZWN0aW9uOnR3aXR0ZXInLCBUd2l0dGVyQ29ubmVjdGlvbik7CiAgICAgYXBwSW5zdGFuY2UucmVnaXN0ZXIoJ2Nvbm5lY3Rpb246ZmFjZWJvb2snLCBGYWNlYm9va0Nvbm5lY3Rpb24pOwogICAgICBsZXQgdHdpdHRlciA9IGFwcEluc3RhbmNlLmxvb2t1cCgnY29ubmVjdGlvbjp0d2l0dGVyJyk7CiAgICAgbGV0IHR3aXR0ZXIyID0gYXBwSW5zdGFuY2UubG9va3VwKCdjb25uZWN0aW9uOnR3aXR0ZXInKTsKICAgICAgdHdpdHRlciA9PT0gdHdpdHRlcjI7IC8vID0+IGZhbHNlCiAgICAgIGxldCBmYWNlYm9vayA9IGFwcEluc3RhbmNlLmxvb2t1cCgnY29ubmVjdGlvbjpmYWNlYm9vaycpOwogICAgIGxldCBmYWNlYm9vazIgPSBhcHBJbnN0YW5jZS5sb29rdXAoJ2Nvbm5lY3Rpb246ZmFjZWJvb2snKTsKICAgICAgZmFjZWJvb2sgPT09IGZhY2Vib29rMjsgLy8gPT4gZmFsc2UKICAgICBgYGAKICAgICAgQHB1YmxpYwogICAgIEBtZXRob2QgcmVnaXN0ZXJPcHRpb25zRm9yVHlwZQogICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAqLwogICAgcmVnaXN0ZXJPcHRpb25zRm9yVHlwZTogcmVnaXN0cnlBbGlhcygnb3B0aW9uc0ZvclR5cGUnKSwKCiAgICAvKioKICAgICBSZXR1cm4gdGhlIHJlZ2lzdGVyZWQgb3B0aW9ucyBmb3IgYWxsIGZhY3RvcmllcyBvZiBhIHR5cGUuCiAgICAgIEBwdWJsaWMKICAgICBAbWV0aG9kIHJlZ2lzdGVyZWRPcHRpb25zRm9yVHlwZQogICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlCiAgICAgQHJldHVybiB7T2JqZWN0fSBvcHRpb25zCiAgICAgKi8KICAgIHJlZ2lzdGVyZWRPcHRpb25zRm9yVHlwZTogcmVnaXN0cnlBbGlhcygnZ2V0T3B0aW9uc0ZvclR5cGUnKSwKCiAgICAvKioKICAgICAgRGVmaW5lIGEgZGVwZW5kZW5jeSBpbmplY3Rpb24gb250byBhIHNwZWNpZmljIGZhY3Rvcnkgb3IgYWxsIGZhY3RvcmllcwogICAgICBvZiBhIHR5cGUuCiAgICAgICBXaGVuIEVtYmVyIGluc3RhbnRpYXRlcyBhIGNvbnRyb2xsZXIsIHZpZXcsIG9yIG90aGVyIGZyYW1ld29yayBjb21wb25lbnQKICAgICAgaXQgY2FuIGF0dGFjaCBhIGRlcGVuZGVuY3kgdG8gdGhhdCBjb21wb25lbnQuIFRoaXMgaXMgb2Z0ZW4gdXNlZCB0bwogICAgICBwcm92aWRlIHNlcnZpY2VzIHRvIGEgc2V0IG9mIGZyYW1ld29yayBjb21wb25lbnRzLgogICAgICAgQW4gZXhhbXBsZSBvZiBwcm92aWRpbmcgYSBzZXNzaW9uIG9iamVjdCB0byBhbGwgY29udHJvbGxlcnM6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCB7IGFsaWFzIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICBpbXBvcnQgQ29udHJvbGxlciBmcm9tICdAZW1iZXIvY29udHJvbGxlcic7CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoKTsKICAgICAgbGV0IFNlc3Npb24gPSBFbWJlck9iamVjdC5leHRlbmQoeyBpc0F1dGhlbnRpY2F0ZWQ6IGZhbHNlIH0pOwogICAgICAgLy8gQSBmYWN0b3J5IG11c3QgYmUgcmVnaXN0ZXJlZCBiZWZvcmUgaXQgY2FuIGJlIGluamVjdGVkCiAgICAgIEFwcC5yZWdpc3Rlcignc2Vzc2lvbjptYWluJywgU2Vzc2lvbik7CiAgICAgICAvLyBJbmplY3QgJ3Nlc3Npb246bWFpbicgb250byBhbGwgZmFjdG9yaWVzIG9mIHRoZSB0eXBlICdjb250cm9sbGVyJwogICAgICAvLyB3aXRoIHRoZSBuYW1lICdzZXNzaW9uJwogICAgICBBcHAuaW5qZWN0KCdjb250cm9sbGVyJywgJ3Nlc3Npb24nLCAnc2Vzc2lvbjptYWluJyk7CiAgICAgICBBcHAuSW5kZXhDb250cm9sbGVyID0gQ29udHJvbGxlci5leHRlbmQoewogICAgICAgIGlzTG9nZ2VkSW46IGFsaWFzKCdzZXNzaW9uLmlzQXV0aGVudGljYXRlZCcpCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEluamVjdGlvbnMgY2FuIGFsc28gYmUgcGVyZm9ybWVkIG9uIHNwZWNpZmljIGZhY3Rvcmllcy4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgQXBwLmluamVjdCg8ZnVsbF9uYW1lIG9yIHR5cGU+LCA8cHJvcGVydHkgbmFtZT4sIDxmdWxsX25hbWU+KQogICAgICBBcHAuaW5qZWN0KCdyb3V0ZScsICdzb3VyY2UnLCAnc291cmNlOm1haW4nKQogICAgICBBcHAuaW5qZWN0KCdyb3V0ZTphcHBsaWNhdGlvbicsICdlbWFpbCcsICdtb2RlbDplbWFpbCcpCiAgICAgIGBgYAogICAgICAgSXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCBpbmplY3Rpb25zIGNhbiBvbmx5IGJlIHBlcmZvcm1lZCBvbgogICAgICBjbGFzc2VzIHRoYXQgYXJlIGluc3RhbnRpYXRlZCBieSBFbWJlciBpdHNlbGYuIEluc3RhbnRpYXRpbmcgYSBjbGFzcwogICAgICBkaXJlY3RseSAodmlhIGBjcmVhdGVgIG9yIGBuZXdgKSBieXBhc3NlcyB0aGUgZGVwZW5kZW5jeSBpbmplY3Rpb24KICAgICAgc3lzdGVtLgogICAgICAgQHB1YmxpYwogICAgICBAbWV0aG9kIGluamVjdAogICAgICBAcGFyYW0gIGZhY3RvcnlOYW1lT3JUeXBlIHtTdHJpbmd9CiAgICAgIEBwYXJhbSAgcHJvcGVydHkge1N0cmluZ30KICAgICAgQHBhcmFtICBpbmplY3Rpb25OYW1lIHtTdHJpbmd9CiAgICAqKi8KICAgIGluamVjdDogcmVnaXN0cnlBbGlhcygnaW5qZWN0aW9uJykKICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OwoKICBmdW5jdGlvbiByZWdpc3RyeUFsaWFzKG5hbWUpIHsKICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBfdGhpcyRfX3JlZ2lzdHJ5X187CgogICAgICByZXR1cm4gKF90aGlzJF9fcmVnaXN0cnlfXyA9IHRoaXMuX19yZWdpc3RyeV9fKVtuYW1lXS5hcHBseShfdGhpcyRfX3JlZ2lzdHJ5X18sIGFyZ3VtZW50cyk7CiAgICB9OwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL3RhcmdldF9hY3Rpb25fc3VwcG9ydCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW52aXJvbm1lbnQsIF9tZXRhbCwgX2RlYnVnKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgYEVtYmVyLlRhcmdldEFjdGlvblN1cHBvcnRgIGlzIGEgbWl4aW4gdGhhdCBjYW4gYmUgaW5jbHVkZWQgaW4gYSBjbGFzcwogIHRvIGFkZCBhIGB0cmlnZ2VyQWN0aW9uYCBtZXRob2Qgd2l0aCBzZW1hbnRpY3Mgc2ltaWxhciB0byB0aGUgSGFuZGxlYmFycwogIGB7e2FjdGlvbn19YCBoZWxwZXIuIEluIG5vcm1hbCBFbWJlciB1c2FnZSwgdGhlIGB7e2FjdGlvbn19YCBoZWxwZXIgaXMKICB1c3VhbGx5IHRoZSBiZXN0IGNob2ljZS4gVGhpcyBtaXhpbiBpcyBtb3N0IG9mdGVuIHVzZWZ1bCB3aGVuIHlvdSBhcmUKICBkb2luZyBtb3JlIGNvbXBsZXggZXZlbnQgaGFuZGxpbmcgaW4gQ29tcG9uZW50cy4KICAKICBAY2xhc3MgVGFyZ2V0QWN0aW9uU3VwcG9ydAogIEBuYW1lc3BhY2UgRW1iZXIKICBAZXh0ZW5kcyBNaXhpbgogIEBwcml2YXRlCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIHRhcmdldDogbnVsbCwKICAgIGFjdGlvbjogbnVsbCwKICAgIGFjdGlvbkNvbnRleHQ6IG51bGwsCiAgICBhY3Rpb25Db250ZXh0T2JqZWN0OiAoMCwgX21ldGFsLmNvbXB1dGVkKSgnYWN0aW9uQ29udGV4dCcsIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGFjdGlvbkNvbnRleHQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FjdGlvbkNvbnRleHQnKTsKCiAgICAgIGlmICh0eXBlb2YgYWN0aW9uQ29udGV4dCA9PT0gJ3N0cmluZycpIHsKICAgICAgICB2YXIgdmFsdWUgPSAoMCwgX21ldGFsLmdldCkodGhpcywgYWN0aW9uQ29udGV4dCk7CgogICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KShfZW52aXJvbm1lbnQuY29udGV4dC5sb29rdXAsIGFjdGlvbkNvbnRleHQpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBhY3Rpb25Db250ZXh0OwogICAgICB9CiAgICB9KSwKCiAgICAvKioKICAgIFNlbmQgYW4gYGFjdGlvbmAgd2l0aCBhbiBgYWN0aW9uQ29udGV4dGAgdG8gYSBgdGFyZ2V0YC4gVGhlIGFjdGlvbiwgYWN0aW9uQ29udGV4dAogICAgYW5kIHRhcmdldCB3aWxsIGJlIHJldHJpZXZlZCBmcm9tIHByb3BlcnRpZXMgb2YgdGhlIG9iamVjdC4gRm9yIGV4YW1wbGU6CiAgICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgYWxpYXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAgICBBcHAuU2F2ZUJ1dHRvblZpZXcgPSBFbWJlci5WaWV3LmV4dGVuZChFbWJlci5UYXJnZXRBY3Rpb25TdXBwb3J0LCB7CiAgICAgIHRhcmdldDogYWxpYXMoJ2NvbnRyb2xsZXInKSwKICAgICAgYWN0aW9uOiAnc2F2ZScsCiAgICAgIGFjdGlvbkNvbnRleHQ6IGFsaWFzKCdjb250ZXh0JyksCiAgICAgIGNsaWNrKCkgewogICAgICAgIHRoaXMudHJpZ2dlckFjdGlvbigpOyAvLyBTZW5kcyB0aGUgYHNhdmVgIGFjdGlvbiwgYWxvbmcgd2l0aCB0aGUgY3VycmVudCBjb250ZXh0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvIHRoZSBjdXJyZW50IGNvbnRyb2xsZXIKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAgICBUaGUgYHRhcmdldGAsIGBhY3Rpb25gLCBhbmQgYGFjdGlvbkNvbnRleHRgIGNhbiBiZSBwcm92aWRlZCBhcyBwcm9wZXJ0aWVzIG9mCiAgICBhbiBvcHRpb25hbCBvYmplY3QgYXJndW1lbnQgdG8gYHRyaWdnZXJBY3Rpb25gIGFzIHdlbGwuCiAgICAgYGBgamF2YXNjcmlwdAogICAgQXBwLlNhdmVCdXR0b25WaWV3ID0gRW1iZXIuVmlldy5leHRlbmQoRW1iZXIuVGFyZ2V0QWN0aW9uU3VwcG9ydCwgewogICAgICBjbGljaygpIHsKICAgICAgICB0aGlzLnRyaWdnZXJBY3Rpb24oewogICAgICAgICAgYWN0aW9uOiAnc2F2ZScsCiAgICAgICAgICB0YXJnZXQ6IHRoaXMuZ2V0KCdjb250cm9sbGVyJyksCiAgICAgICAgICBhY3Rpb25Db250ZXh0OiB0aGlzLmdldCgnY29udGV4dCcpCiAgICAgICAgfSk7IC8vIFNlbmRzIHRoZSBgc2F2ZWAgYWN0aW9uLCBhbG9uZyB3aXRoIHRoZSBjdXJyZW50IGNvbnRleHQKICAgICAgICAgICAgLy8gdG8gdGhlIGN1cnJlbnQgY29udHJvbGxlcgogICAgICB9CiAgICB9KTsKICAgIGBgYAogICAgIFRoZSBgYWN0aW9uQ29udGV4dGAgZGVmYXVsdHMgdG8gdGhlIG9iamVjdCB5b3UgYXJlIG1peGluZyBgVGFyZ2V0QWN0aW9uU3VwcG9ydGAgaW50by4KICAgIEJ1dCBgdGFyZ2V0YCBhbmQgYGFjdGlvbmAgbXVzdCBiZSBzcGVjaWZpZWQgZWl0aGVyIGFzIHByb3BlcnRpZXMgb3Igd2l0aCB0aGUgYXJndW1lbnQKICAgIHRvIGB0cmlnZ2VyQWN0aW9uYCwgb3IgYSBjb21iaW5hdGlvbjoKICAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBhbGlhcyB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogICAgIEFwcC5TYXZlQnV0dG9uVmlldyA9IEVtYmVyLlZpZXcuZXh0ZW5kKEVtYmVyLlRhcmdldEFjdGlvblN1cHBvcnQsIHsKICAgICAgdGFyZ2V0OiBhbGlhcygnY29udHJvbGxlcicpLAogICAgICBjbGljaygpIHsKICAgICAgICB0aGlzLnRyaWdnZXJBY3Rpb24oewogICAgICAgICAgYWN0aW9uOiAnc2F2ZScKICAgICAgICB9KTsgLy8gU2VuZHMgdGhlIGBzYXZlYCBhY3Rpb24sIGFsb25nIHdpdGggYSByZWZlcmVuY2UgdG8gYHRoaXNgLAogICAgICAgICAgICAvLyB0byB0aGUgY3VycmVudCBjb250cm9sbGVyCiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgICAgQG1ldGhvZCB0cmlnZ2VyQWN0aW9uCiAgICBAcGFyYW0gb3B0cyB7T2JqZWN0fSAob3B0aW9uYWwsIHdpdGggdGhlIG9wdGlvbmFsIGtleXMgYWN0aW9uLCB0YXJnZXQgYW5kL29yIGFjdGlvbkNvbnRleHQpCiAgICBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHRoZSBhY3Rpb24gd2FzIHNlbnQgc3VjY2Vzc2Z1bGx5IGFuZCBkaWQgbm90IHJldHVybiBmYWxzZQogICAgQHByaXZhdGUKICAgICovCiAgICB0cmlnZ2VyQWN0aW9uOiBmdW5jdGlvbiB0cmlnZ2VyQWN0aW9uKG9wdHMpIHsKICAgICAgaWYgKG9wdHMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdHMgPSB7fTsKICAgICAgfQoKICAgICAgdmFyIF9vcHRzID0gb3B0cywKICAgICAgICAgIGFjdGlvbiA9IF9vcHRzLmFjdGlvbiwKICAgICAgICAgIHRhcmdldCA9IF9vcHRzLnRhcmdldCwKICAgICAgICAgIGFjdGlvbkNvbnRleHQgPSBfb3B0cy5hY3Rpb25Db250ZXh0OwogICAgICBhY3Rpb24gPSBhY3Rpb24gfHwgKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdhY3Rpb24nKTsKICAgICAgdGFyZ2V0ID0gdGFyZ2V0IHx8IGdldFRhcmdldCh0aGlzKTsKCiAgICAgIGlmIChhY3Rpb25Db250ZXh0ID09PSB1bmRlZmluZWQpIHsKICAgICAgICBhY3Rpb25Db250ZXh0ID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdhY3Rpb25Db250ZXh0T2JqZWN0JykgfHwgdGhpczsKICAgICAgfQoKICAgICAgaWYgKHRhcmdldCAmJiBhY3Rpb24pIHsKICAgICAgICB2YXIgcmV0OwoKICAgICAgICBpZiAodGFyZ2V0LnNlbmQpIHsKICAgICAgICAgIHZhciBfdGFyZ2V0OwoKICAgICAgICAgIHJldCA9IChfdGFyZ2V0ID0gdGFyZ2V0KS5zZW5kLmFwcGx5KF90YXJnZXQsIFthY3Rpb25dLmNvbmNhdChhY3Rpb25Db250ZXh0KSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBfdGFyZ2V0MjsKCiAgICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgdGFyZ2V0W2FjdGlvbl0gPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIGFjdGlvbiAnIiArIGFjdGlvbiArICInIGRpZCBub3QgZXhpc3Qgb24gIiArIHRhcmdldCwgdHlwZW9mIHRhcmdldFthY3Rpb25dID09PSAnZnVuY3Rpb24nKSk7CiAgICAgICAgICByZXQgPSAoX3RhcmdldDIgPSB0YXJnZXQpW2FjdGlvbl0uYXBwbHkoX3RhcmdldDIsIFtdLmNvbmNhdChhY3Rpb25Db250ZXh0KSk7CiAgICAgICAgfQoKICAgICAgICBpZiAocmV0ICE9PSBmYWxzZSkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgfSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKCiAgZnVuY3Rpb24gZ2V0VGFyZ2V0KGluc3RhbmNlKSB7CiAgICB2YXIgdGFyZ2V0ID0gKDAsIF9tZXRhbC5nZXQpKGluc3RhbmNlLCAndGFyZ2V0Jyk7CgogICAgaWYgKHRhcmdldCkgewogICAgICBpZiAodHlwZW9mIHRhcmdldCA9PT0gJ3N0cmluZycpIHsKICAgICAgICB2YXIgdmFsdWUgPSAoMCwgX21ldGFsLmdldCkoaW5zdGFuY2UsIHRhcmdldCk7CgogICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KShfZW52aXJvbm1lbnQuY29udGV4dC5sb29rdXAsIHRhcmdldCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHRhcmdldDsKICAgICAgfQogICAgfQoKICAgIGlmIChpbnN0YW5jZS5fdGFyZ2V0KSB7CiAgICAgIHJldHVybiBpbnN0YW5jZS5fdGFyZ2V0OwogICAgfQoKICAgIHJldHVybiBudWxsOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL2FycmF5X3Byb3h5IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL3N5c3RlbS9vYmplY3QiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2FycmF5IiwgIkBlbWJlci9kZWJ1ZyIsICJAZ2xpbW1lci9yZWZlcmVuY2UiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX21ldGFsLCBfb2JqZWN0LCBfYXJyYXksIF9kZWJ1ZywgX3JlZmVyZW5jZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvYXJyYXkKICAqLwogIHZhciBBUlJBWV9PQlNFUlZFUl9NQVBQSU5HID0gewogICAgd2lsbENoYW5nZTogJ19hcnJhbmdlZENvbnRlbnRBcnJheVdpbGxDaGFuZ2UnLAogICAgZGlkQ2hhbmdlOiAnX2FycmFuZ2VkQ29udGVudEFycmF5RGlkQ2hhbmdlJwogIH07CiAgLyoqCiAgICBBbiBBcnJheVByb3h5IHdyYXBzIGFueSBvdGhlciBvYmplY3QgdGhhdCBpbXBsZW1lbnRzIGBBcnJheWAgYW5kL29yCiAgICBgTXV0YWJsZUFycmF5LGAgZm9yd2FyZGluZyBhbGwgcmVxdWVzdHMuIFRoaXMgbWFrZXMgaXQgdmVyeSB1c2VmdWwgZm9yCiAgICBhIG51bWJlciBvZiBiaW5kaW5nIHVzZSBjYXNlcyBvciBvdGhlciBjYXNlcyB3aGVyZSBiZWluZyBhYmxlIHRvIHN3YXAKICAgIG91dCB0aGUgdW5kZXJseWluZyBhcnJheSBpcyB1c2VmdWwuCiAgCiAgICBBIHNpbXBsZSBleGFtcGxlIG9mIHVzYWdlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgQSB9IGZyb20gJ0BlbWJlci9hcnJheSc7CiAgICBpbXBvcnQgQXJyYXlQcm94eSBmcm9tICdAZW1iZXIvYXJyYXkvcHJveHknOwogIAogICAgbGV0IHBldHMgPSBbJ2RvZycsICdjYXQnLCAnZmlzaCddOwogICAgbGV0IGFwID0gQXJyYXlQcm94eS5jcmVhdGUoeyBjb250ZW50OiBBKHBldHMpIH0pOwogIAogICAgYXAuZ2V0KCdmaXJzdE9iamVjdCcpOyAgICAgICAgICAgICAgICAgICAgICAgIC8vICdkb2cnCiAgICBhcC5zZXQoJ2NvbnRlbnQnLCBbJ2Ftb2ViYScsICdwYXJhbWVjaXVtJ10pOwogICAgYXAuZ2V0KCdmaXJzdE9iamVjdCcpOyAgICAgICAgICAgICAgICAgICAgICAgIC8vICdhbW9lYmEnCiAgICBgYGAKICAKICAgIFRoaXMgY2xhc3MgY2FuIGFsc28gYmUgdXNlZnVsIGFzIGEgbGF5ZXIgdG8gdHJhbnNmb3JtIHRoZSBjb250ZW50cyBvZgogICAgYW4gYXJyYXksIGFzIHRoZXkgYXJlIGFjY2Vzc2VkLiBUaGlzIGNhbiBiZSBkb25lIGJ5IG92ZXJyaWRpbmcKICAgIGBvYmplY3RBdENvbnRlbnRgOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgQSB9IGZyb20gJ0BlbWJlci9hcnJheSc7CiAgICBpbXBvcnQgQXJyYXlQcm94eSBmcm9tICdAZW1iZXIvYXJyYXkvcHJveHknOwogIAogICAgbGV0IHBldHMgPSBbJ2RvZycsICdjYXQnLCAnZmlzaCddOwogICAgbGV0IGFwID0gQXJyYXlQcm94eS5jcmVhdGUoewogICAgICAgIGNvbnRlbnQ6IEEocGV0cyksCiAgICAgICAgb2JqZWN0QXRDb250ZW50OiBmdW5jdGlvbihpZHgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KCdjb250ZW50Jykub2JqZWN0QXQoaWR4KS50b1VwcGVyQ2FzZSgpOwogICAgICAgIH0KICAgIH0pOwogIAogICAgYXAuZ2V0KCdmaXJzdE9iamVjdCcpOyAvLyAuICdET0cnCiAgICBgYGAKICAKICAgIFdoZW4gb3ZlcnJpZGluZyB0aGlzIGNsYXNzLCBpdCBpcyBpbXBvcnRhbnQgdG8gcGxhY2UgdGhlIGNhbGwgdG8KICAgIGBfc3VwZXJgICphZnRlciogc2V0dGluZyBgY29udGVudGAgc28gdGhlIGludGVybmFsIG9ic2VydmVycyBoYXZlCiAgICBhIGNoYW5jZSB0byBmaXJlIHByb3Blcmx5OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgQSB9IGZyb20gJ0BlbWJlci9hcnJheSc7CiAgICBpbXBvcnQgQXJyYXlQcm94eSBmcm9tICdAZW1iZXIvYXJyYXkvcHJveHknOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQXJyYXlQcm94eS5leHRlbmQoewogICAgICBpbml0KCkgewogICAgICAgIHRoaXMuc2V0KCdjb250ZW50JywgQShbJ2RvZycsICdjYXQnLCAnZmlzaCddKSk7CiAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBBcnJheVByb3h5CiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHVzZXMgTXV0YWJsZUFycmF5CiAgICBAcHVibGljCiAgKi8KCiAgdmFyIEFycmF5UHJveHkgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0VtYmVyT2JqZWN0KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoQXJyYXlQcm94eSwgX0VtYmVyT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBBcnJheVByb3h5KCkgewogICAgICByZXR1cm4gX0VtYmVyT2JqZWN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gQXJyYXlQcm94eS5wcm90b3R5cGU7CgogICAgX3Byb3RvLmluaXQgPSBmdW5jdGlvbiBpbml0KCkgewogICAgICBfRW1iZXJPYmplY3QucHJvdG90eXBlLmluaXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgICAgLyoKICAgICAgICBgdGhpcy5fb2JqZWN0c0RpcnR5SW5kZXhgIGRldGVybWluZXMgd2hpY2ggaW5kZXhlcyBpbiB0aGUgYHRoaXMuX29iamVjdHNgCiAgICAgICAgY2FjaGUgYXJlIGRpcnR5LgogICAgICAgICBJZiBgdGhpcy5fb2JqZWN0c0RpcnR5SW5kZXggPT09IC0xYCB0aGVuIG5vIGluZGV4ZXMgYXJlIGRpcnR5LgogICAgICAgIE90aGVyd2lzZSwgYW4gaW5kZXggYGlgIGlzIGRpcnR5IGlmIGBpID49IHRoaXMuX29iamVjdHNEaXJ0eUluZGV4YC4KICAgICAgICAgQ2FsbGluZyBgb2JqZWN0QXRgIHdpdGggYSBkaXJ0eSBpbmRleCB3aWxsIGNhdXNlIHRoZSBgdGhpcy5fb2JqZWN0c2AKICAgICAgICBjYWNoZSB0byBiZSByZWNvbXB1dGVkLgogICAgICAqLwoKCiAgICAgIHRoaXMuX29iamVjdHNEaXJ0eUluZGV4ID0gMDsKICAgICAgdGhpcy5fb2JqZWN0cyA9IG51bGw7CiAgICAgIHRoaXMuX2xlbmd0aERpcnR5ID0gdHJ1ZTsKICAgICAgdGhpcy5fbGVuZ3RoID0gMDsKICAgICAgdGhpcy5fYXJyYW5nZWRDb250ZW50ID0gbnVsbDsKCiAgICAgIGlmICh0cnVlCiAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICApIHsKICAgICAgICAgIHRoaXMuX2FycmFuZ2VkQ29udGVudElzVXBkYXRpbmcgPSBmYWxzZTsKICAgICAgICAgIHRoaXMuX2FycmFuZ2VkQ29udGVudFRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKCgwLCBfbWV0YWwuZ2V0Q2hhaW5UYWdzRm9yS2V5KSh0aGlzLCAnYXJyYW5nZWRDb250ZW50JykpOwogICAgICAgICAgdGhpcy5fYXJyYW5nZWRDb250ZW50UmV2aXNpb24gPSAoMCwgX3JlZmVyZW5jZS52YWx1ZSkodGhpcy5fYXJyYW5nZWRDb250ZW50VGFnKTsKICAgICAgICB9CgogICAgICB0aGlzLl9hZGRBcnJhbmdlZENvbnRlbnRBcnJheU9ic2V2ZXIoKTsKICAgIH07CgogICAgX3Byb3RvLndpbGxEZXN0cm95ID0gZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3JlbW92ZUFycmFuZ2VkQ29udGVudEFycmF5T2JzZXZlcigpOwogICAgfQogICAgLyoqCiAgICAgIFRoZSBjb250ZW50IGFycmF5LiBNdXN0IGJlIGFuIG9iamVjdCB0aGF0IGltcGxlbWVudHMgYEFycmF5YCBhbmQvb3IKICAgICAgYE11dGFibGVBcnJheS5gCiAgICAgICBAcHJvcGVydHkgY29udGVudAogICAgICBAdHlwZSBFbWJlckFycmF5CiAgICAgIEBwdWJsaWMKICAgICovCgogICAgLyoqCiAgICAgIFNob3VsZCBhY3R1YWxseSByZXRyaWV2ZSB0aGUgb2JqZWN0IGF0IHRoZSBzcGVjaWZpZWQgaW5kZXggZnJvbSB0aGUKICAgICAgY29udGVudC4gWW91IGNhbiBvdmVycmlkZSB0aGlzIG1ldGhvZCBpbiBzdWJjbGFzc2VzIHRvIHRyYW5zZm9ybSB0aGUKICAgICAgY29udGVudCBpdGVtIHRvIHNvbWV0aGluZyBuZXcuCiAgICAgICBUaGlzIG1ldGhvZCB3aWxsIG9ubHkgYmUgY2FsbGVkIGlmIGNvbnRlbnQgaXMgbm9uLWBudWxsYC4KICAgICAgIEBtZXRob2Qgb2JqZWN0QXRDb250ZW50CiAgICAgIEBwYXJhbSB7TnVtYmVyfSBpZHggVGhlIGluZGV4IHRvIHJldHJpZXZlLgogICAgICBAcmV0dXJuIHtPYmplY3R9IHRoZSB2YWx1ZSBvciB1bmRlZmluZWQgaWYgbm9uZSBmb3VuZAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5vYmplY3RBdENvbnRlbnQgPSBmdW5jdGlvbiBvYmplY3RBdENvbnRlbnQoaWR4KSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLm9iamVjdEF0KSgoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpLCBpZHgpOwogICAgfSAvLyBTZWUgYWRkaXRpb25hbCBkb2NzIGZvciBgcmVwbGFjZWAgZnJvbSBgTXV0YWJsZUFycmF5YDoKICAgIC8vIGh0dHBzOi8vYXBpLmVtYmVyanMuY29tL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9NdXRhYmxlQXJyYXkvbWV0aG9kcy9yZXBsYWNlP2FuY2hvcj1yZXBsYWNlCiAgICA7CgogICAgX3Byb3RvLnJlcGxhY2UgPSBmdW5jdGlvbiByZXBsYWNlKGlkeCwgYW10LCBvYmplY3RzKSB7CiAgICAgIChmYWxzZSAmJiAhKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnYXJyYW5nZWRDb250ZW50JykgPT09ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnY29udGVudCcpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ011dGF0aW5nIGFuIGFycmFuZ2VkIEFycmF5UHJveHkgaXMgbm90IGFsbG93ZWQnLCAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpID09PSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2NvbnRlbnQnKSkpOwogICAgICB0aGlzLnJlcGxhY2VDb250ZW50KGlkeCwgYW10LCBvYmplY3RzKTsKICAgIH0KICAgIC8qKgogICAgICBTaG91bGQgYWN0dWFsbHkgcmVwbGFjZSB0aGUgc3BlY2lmaWVkIG9iamVjdHMgb24gdGhlIGNvbnRlbnQgYXJyYXkuCiAgICAgIFlvdSBjYW4gb3ZlcnJpZGUgdGhpcyBtZXRob2QgaW4gc3ViY2xhc3NlcyB0byB0cmFuc2Zvcm0gdGhlIGNvbnRlbnQgaXRlbQogICAgICBpbnRvIHNvbWV0aGluZyBuZXcuCiAgICAgICBUaGlzIG1ldGhvZCB3aWxsIG9ubHkgYmUgY2FsbGVkIGlmIGNvbnRlbnQgaXMgbm9uLWBudWxsYC4KICAgICAgIEBtZXRob2QgcmVwbGFjZUNvbnRlbnQKICAgICAgQHBhcmFtIHtOdW1iZXJ9IGlkeCBUaGUgc3RhcnRpbmcgaW5kZXgKICAgICAgQHBhcmFtIHtOdW1iZXJ9IGFtdCBUaGUgbnVtYmVyIG9mIGl0ZW1zIHRvIHJlbW92ZSBmcm9tIHRoZSBjb250ZW50LgogICAgICBAcGFyYW0ge0VtYmVyQXJyYXl9IG9iamVjdHMgT3B0aW9uYWwgYXJyYXkgb2Ygb2JqZWN0cyB0byBpbnNlcnQgb3IgbnVsbCBpZiBubwogICAgICAgIG9iamVjdHMuCiAgICAgIEByZXR1cm4ge3ZvaWR9CiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlcGxhY2VDb250ZW50ID0gZnVuY3Rpb24gcmVwbGFjZUNvbnRlbnQoaWR4LCBhbXQsIG9iamVjdHMpIHsKICAgICAgKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdjb250ZW50JykucmVwbGFjZShpZHgsIGFtdCwgb2JqZWN0cyk7CiAgICB9IC8vIE92ZXJyaWRpbmcgb2JqZWN0QXQgaXMgbm90IHN1cHBvcnRlZC4KICAgIDsKCiAgICBfcHJvdG8ub2JqZWN0QXQgPSBmdW5jdGlvbiBvYmplY3RBdChpZHgpIHsKICAgICAgaWYgKHRydWUKICAgICAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgICAgICkgewogICAgICAgICAgdGhpcy5fcmV2YWxpZGF0ZSgpOwogICAgICAgIH0KCiAgICAgIGlmICh0aGlzLl9vYmplY3RzID09PSBudWxsKSB7CiAgICAgICAgdGhpcy5fb2JqZWN0cyA9IFtdOwogICAgICB9CgogICAgICBpZiAodGhpcy5fb2JqZWN0c0RpcnR5SW5kZXggIT09IC0xICYmIGlkeCA+PSB0aGlzLl9vYmplY3RzRGlydHlJbmRleCkgewogICAgICAgIHZhciBhcnJhbmdlZENvbnRlbnQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpOwoKICAgICAgICBpZiAoYXJyYW5nZWRDb250ZW50KSB7CiAgICAgICAgICB2YXIgbGVuZ3RoID0gdGhpcy5fb2JqZWN0cy5sZW5ndGggPSAoMCwgX21ldGFsLmdldCkoYXJyYW5nZWRDb250ZW50LCAnbGVuZ3RoJyk7CgogICAgICAgICAgZm9yICh2YXIgaSA9IHRoaXMuX29iamVjdHNEaXJ0eUluZGV4OyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgdGhpcy5fb2JqZWN0c1tpXSA9IHRoaXMub2JqZWN0QXRDb250ZW50KGkpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9vYmplY3RzLmxlbmd0aCA9IDA7CiAgICAgICAgfQoKICAgICAgICB0aGlzLl9vYmplY3RzRGlydHlJbmRleCA9IC0xOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fb2JqZWN0c1tpZHhdOwogICAgfSAvLyBPdmVycmlkaW5nIGxlbmd0aCBpcyBub3Qgc3VwcG9ydGVkLgogICAgOwoKICAgIF9wcm90b1tfbWV0YWwuUFJPUEVSVFlfRElEX0NIQU5HRV0gPSBmdW5jdGlvbiAoa2V5KSB7CiAgICAgIGlmICh0cnVlCiAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICApIHsKICAgICAgICAgIHRoaXMuX3JldmFsaWRhdGUoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgIGlmIChrZXkgPT09ICdhcnJhbmdlZENvbnRlbnQnKSB7CiAgICAgICAgICB0aGlzLl91cGRhdGVBcnJhbmdlZENvbnRlbnRBcnJheSgpOwogICAgICAgIH0gZWxzZSBpZiAoa2V5ID09PSAnY29udGVudCcpIHsKICAgICAgICAgIHRoaXMuX2ludmFsaWRhdGUoKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl91cGRhdGVBcnJhbmdlZENvbnRlbnRBcnJheSA9IGZ1bmN0aW9uIF91cGRhdGVBcnJhbmdlZENvbnRlbnRBcnJheSgpIHsKICAgICAgdmFyIG9sZExlbmd0aCA9IHRoaXMuX29iamVjdHMgPT09IG51bGwgPyAwIDogdGhpcy5fb2JqZWN0cy5sZW5ndGg7CiAgICAgIHZhciBhcnJhbmdlZENvbnRlbnQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpOwogICAgICB2YXIgbmV3TGVuZ3RoID0gYXJyYW5nZWRDb250ZW50ID8gKDAsIF9tZXRhbC5nZXQpKGFycmFuZ2VkQ29udGVudCwgJ2xlbmd0aCcpIDogMDsKCiAgICAgIHRoaXMuX3JlbW92ZUFycmFuZ2VkQ29udGVudEFycmF5T2JzZXZlcigpOwoKICAgICAgdGhpcy5hcnJheUNvbnRlbnRXaWxsQ2hhbmdlKDAsIG9sZExlbmd0aCwgbmV3TGVuZ3RoKTsKCiAgICAgIHRoaXMuX2ludmFsaWRhdGUoKTsKCiAgICAgIHRoaXMuYXJyYXlDb250ZW50RGlkQ2hhbmdlKDAsIG9sZExlbmd0aCwgbmV3TGVuZ3RoKTsKCiAgICAgIHRoaXMuX2FkZEFycmFuZ2VkQ29udGVudEFycmF5T2JzZXZlcigpOwogICAgfTsKCiAgICBfcHJvdG8uX2FkZEFycmFuZ2VkQ29udGVudEFycmF5T2JzZXZlciA9IGZ1bmN0aW9uIF9hZGRBcnJhbmdlZENvbnRlbnRBcnJheU9ic2V2ZXIoKSB7CiAgICAgIHZhciBhcnJhbmdlZENvbnRlbnQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpOwoKICAgICAgaWYgKGFycmFuZ2VkQ29udGVudCAmJiAhYXJyYW5nZWRDb250ZW50LmlzRGVzdHJveWVkKSB7CiAgICAgICAgKGZhbHNlICYmICEoYXJyYW5nZWRDb250ZW50ICE9PSB0aGlzKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkNhbid0IHNldCBBcnJheVByb3h5J3MgY29udGVudCB0byBpdHNlbGYiLCBhcnJhbmdlZENvbnRlbnQgIT09IHRoaXMpKTsKICAgICAgICAoZmFsc2UgJiYgISgoMCwgX2FycmF5LmlzQXJyYXkpKGFycmFuZ2VkQ29udGVudCkgfHwgYXJyYW5nZWRDb250ZW50LmlzRGVzdHJveWVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkFycmF5UHJveHkgZXhwZWN0cyBhbiBBcnJheSBvciBBcnJheVByb3h5LCBidXQgeW91IHBhc3NlZCAiICsgdHlwZW9mIGFycmFuZ2VkQ29udGVudCwgKDAsIF9hcnJheS5pc0FycmF5KShhcnJhbmdlZENvbnRlbnQpIHx8IGFycmFuZ2VkQ29udGVudC5pc0Rlc3Ryb3llZCkpOwogICAgICAgICgwLCBfbWV0YWwuYWRkQXJyYXlPYnNlcnZlcikoYXJyYW5nZWRDb250ZW50LCB0aGlzLCBBUlJBWV9PQlNFUlZFUl9NQVBQSU5HKTsKICAgICAgICB0aGlzLl9hcnJhbmdlZENvbnRlbnQgPSBhcnJhbmdlZENvbnRlbnQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9yZW1vdmVBcnJhbmdlZENvbnRlbnRBcnJheU9ic2V2ZXIgPSBmdW5jdGlvbiBfcmVtb3ZlQXJyYW5nZWRDb250ZW50QXJyYXlPYnNldmVyKCkgewogICAgICBpZiAodGhpcy5fYXJyYW5nZWRDb250ZW50KSB7CiAgICAgICAgKDAsIF9tZXRhbC5yZW1vdmVBcnJheU9ic2VydmVyKSh0aGlzLl9hcnJhbmdlZENvbnRlbnQsIHRoaXMsIEFSUkFZX09CU0VSVkVSX01BUFBJTkcpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fYXJyYW5nZWRDb250ZW50QXJyYXlXaWxsQ2hhbmdlID0gZnVuY3Rpb24gX2FycmFuZ2VkQ29udGVudEFycmF5V2lsbENoYW5nZSgpIHt9OwoKICAgIF9wcm90by5fYXJyYW5nZWRDb250ZW50QXJyYXlEaWRDaGFuZ2UgPSBmdW5jdGlvbiBfYXJyYW5nZWRDb250ZW50QXJyYXlEaWRDaGFuZ2UocHJveHksIGlkeCwgcmVtb3ZlZENudCwgYWRkZWRDbnQpIHsKICAgICAgdGhpcy5hcnJheUNvbnRlbnRXaWxsQ2hhbmdlKGlkeCwgcmVtb3ZlZENudCwgYWRkZWRDbnQpOwogICAgICB2YXIgZGlydHlJbmRleCA9IGlkeDsKCiAgICAgIGlmIChkaXJ0eUluZGV4IDwgMCkgewogICAgICAgIHZhciBsZW5ndGggPSAoMCwgX21ldGFsLmdldCkodGhpcy5fYXJyYW5nZWRDb250ZW50LCAnbGVuZ3RoJyk7CiAgICAgICAgZGlydHlJbmRleCArPSBsZW5ndGggKyByZW1vdmVkQ250IC0gYWRkZWRDbnQ7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLl9vYmplY3RzRGlydHlJbmRleCA9PT0gLTEgfHwgdGhpcy5fb2JqZWN0c0RpcnR5SW5kZXggPiBkaXJ0eUluZGV4KSB7CiAgICAgICAgdGhpcy5fb2JqZWN0c0RpcnR5SW5kZXggPSBkaXJ0eUluZGV4OwogICAgICB9CgogICAgICB0aGlzLl9sZW5ndGhEaXJ0eSA9IHRydWU7CiAgICAgIHRoaXMuYXJyYXlDb250ZW50RGlkQ2hhbmdlKGlkeCwgcmVtb3ZlZENudCwgYWRkZWRDbnQpOwogICAgfTsKCiAgICBfcHJvdG8uX2ludmFsaWRhdGUgPSBmdW5jdGlvbiBfaW52YWxpZGF0ZSgpIHsKICAgICAgdGhpcy5fb2JqZWN0c0RpcnR5SW5kZXggPSAwOwogICAgICB0aGlzLl9sZW5ndGhEaXJ0eSA9IHRydWU7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoQXJyYXlQcm94eSwgW3sKICAgICAga2V5OiAibGVuZ3RoIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRydWUKICAgICAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICAgICApIHsKICAgICAgICAgICAgdGhpcy5fcmV2YWxpZGF0ZSgpOwogICAgICAgICAgfQoKICAgICAgICBpZiAodGhpcy5fbGVuZ3RoRGlydHkpIHsKICAgICAgICAgIHZhciBhcnJhbmdlZENvbnRlbnQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpOwogICAgICAgICAgdGhpcy5fbGVuZ3RoID0gYXJyYW5nZWRDb250ZW50ID8gKDAsIF9tZXRhbC5nZXQpKGFycmFuZ2VkQ29udGVudCwgJ2xlbmd0aCcpIDogMDsKICAgICAgICAgIHRoaXMuX2xlbmd0aERpcnR5ID0gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fbGVuZ3RoOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSkgewogICAgICAgIHZhciBsZW5ndGggPSB0aGlzLmxlbmd0aDsKICAgICAgICB2YXIgcmVtb3ZlZENvdW50ID0gbGVuZ3RoIC0gdmFsdWU7CiAgICAgICAgdmFyIGFkZGVkOwoKICAgICAgICBpZiAocmVtb3ZlZENvdW50ID09PSAwKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfSBlbHNlIGlmIChyZW1vdmVkQ291bnQgPCAwKSB7CiAgICAgICAgICBhZGRlZCA9IG5ldyBBcnJheSgtcmVtb3ZlZENvdW50KTsKICAgICAgICAgIHJlbW92ZWRDb3VudCA9IDA7CiAgICAgICAgfQoKICAgICAgICB2YXIgY29udGVudCA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnY29udGVudCcpOwoKICAgICAgICBpZiAoY29udGVudCkgewogICAgICAgICAgKDAsIF9tZXRhbC5yZXBsYWNlKShjb250ZW50LCB2YWx1ZSwgcmVtb3ZlZENvdW50LCBhZGRlZCk7CgogICAgICAgICAgdGhpcy5faW52YWxpZGF0ZSgpOwogICAgICAgIH0KICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIEFycmF5UHJveHk7CiAgfShfb2JqZWN0LmRlZmF1bHQpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gQXJyYXlQcm94eTsKCiAgdmFyIF9yZXZhbGlkYXRlOwoKICBpZiAodHJ1ZQogIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICkgewogICAgICBfcmV2YWxpZGF0ZSA9IGZ1bmN0aW9uIF9yZXZhbGlkYXRlKCkgewogICAgICAgIGlmICghdGhpcy5fYXJyYW5nZWRDb250ZW50SXNVcGRhdGluZyAmJiAhKDAsIF9yZWZlcmVuY2UudmFsaWRhdGUpKHRoaXMuX2FycmFuZ2VkQ29udGVudFRhZywgdGhpcy5fYXJyYW5nZWRDb250ZW50UmV2aXNpb24pKSB7CiAgICAgICAgICB0aGlzLl9hcnJhbmdlZENvbnRlbnRJc1VwZGF0aW5nID0gdHJ1ZTsKCiAgICAgICAgICB0aGlzLl91cGRhdGVBcnJhbmdlZENvbnRlbnRBcnJheSgpOwoKICAgICAgICAgIHRoaXMuX2FycmFuZ2VkQ29udGVudElzVXBkYXRpbmcgPSBmYWxzZTsKICAgICAgICAgIHRoaXMuX2FycmFuZ2VkQ29udGVudFRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKCgwLCBfbWV0YWwuZ2V0Q2hhaW5UYWdzRm9yS2V5KSh0aGlzLCAnYXJyYW5nZWRDb250ZW50JykpOwogICAgICAgICAgdGhpcy5fYXJyYW5nZWRDb250ZW50UmV2aXNpb24gPSAoMCwgX3JlZmVyZW5jZS52YWx1ZSkodGhpcy5fYXJyYW5nZWRDb250ZW50VGFnKTsKICAgICAgICB9CiAgICAgIH07CiAgICB9CgogIEFycmF5UHJveHkucmVvcGVuKF9hcnJheS5NdXRhYmxlQXJyYXksIHsKICAgIC8qKgogICAgICBUaGUgYXJyYXkgdGhhdCB0aGUgcHJveHkgcHJldGVuZHMgdG8gYmUuIEluIHRoZSBkZWZhdWx0IGBBcnJheVByb3h5YAogICAgICBpbXBsZW1lbnRhdGlvbiwgdGhpcyBhbmQgYGNvbnRlbnRgIGFyZSB0aGUgc2FtZS4gU3ViY2xhc3NlcyBvZiBgQXJyYXlQcm94eWAKICAgICAgY2FuIG92ZXJyaWRlIHRoaXMgcHJvcGVydHkgdG8gcHJvdmlkZSB0aGluZ3MgbGlrZSBzb3J0aW5nIGFuZCBmaWx0ZXJpbmcuCiAgICAgICBAcHJvcGVydHkgYXJyYW5nZWRDb250ZW50CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBhcnJhbmdlZENvbnRlbnQ6ICgwLCBfbWV0YWwuYWxpYXMpKCdjb250ZW50JyksCiAgICBfcmV2YWxpZGF0ZTogX3JldmFsaWRhdGUKICB9KTsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL2NvcmVfb2JqZWN0IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL2NvbnRhaW5lciIsICJAZW1iZXIvLWludGVybmFscy9vd25lciIsICJAZW1iZXIvcG9seWZpbGxzIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9ydW5sb29wIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGEiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2FjdGlvbl9oYW5kbGVyIiwgIkBlbWJlci9kZWJ1ZyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfY29udGFpbmVyLCBfb3duZXIsIF9wb2x5ZmlsbHMsIF91dGlscywgX3J1bmxvb3AsIF9tZXRhMiwgX21ldGFsLCBfYWN0aW9uX2hhbmRsZXIsIF9kZWJ1ZykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuc2V0RnJhbWV3b3JrQ2xhc3MgPSBzZXRGcmFtZXdvcmtDbGFzczsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyL29iamVjdAogICovCiAgdmFyIF9yZW9wZW4gPSBfbWV0YWwuTWl4aW4ucHJvdG90eXBlLnJlb3BlbjsKICB2YXIgd2FzQXBwbGllZCA9IG5ldyBfcG9seWZpbGxzLl9XZWFrU2V0KCk7CiAgdmFyIGZhY3RvcnlNYXAgPSBuZXcgV2Vha01hcCgpOwogIHZhciBwcm90b3R5cGVNaXhpbk1hcCA9IG5ldyBXZWFrTWFwKCk7CiAgdmFyIGluaXRDYWxsZWQgPSBmYWxzZQogIC8qIERFQlVHICovCiAgPyBuZXcgX3BvbHlmaWxscy5fV2Vha1NldCgpIDogdW5kZWZpbmVkOyAvLyBvbmx5IHVzZWQgaW4gZGVidWcgYnVpbGRzIHRvIGVuYWJsZSB0aGUgcHJveHkgdHJhcAoKICB2YXIgUEFTU0VEX0ZST01fQ1JFQVRFID0gZmFsc2UKICAvKiBERUJVRyAqLwogID8gKDAsIF91dGlscy5zeW1ib2wpKCdQQVNTRURfRlJPTV9DUkVBVEUnKSA6IHVuZGVmaW5lZDsKICB2YXIgRlJBTUVXT1JLX0NMQVNTRVMgPSB0cnVlCiAgLyogRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCAqLwogID8gKDAsIF91dGlscy5zeW1ib2wpKCdGUkFNRVdPUktfQ0xBU1MnKSA6IHVuZGVmaW5lZDsKCiAgZnVuY3Rpb24gc2V0RnJhbWV3b3JrQ2xhc3Moa2xhc3MpIHsKICAgIGtsYXNzW0ZSQU1FV09SS19DTEFTU0VTXSA9IHRydWU7CiAgfQoKICBmdW5jdGlvbiBpbml0aWFsaXplKG9iaiwgcHJvcGVydGllcykgewogICAgdmFyIG0gPSAoMCwgX21ldGEyLm1ldGEpKG9iaik7CgogICAgaWYgKHByb3BlcnRpZXMgIT09IHVuZGVmaW5lZCkgewogICAgICAoZmFsc2UgJiYgISh0eXBlb2YgcHJvcGVydGllcyA9PT0gJ29iamVjdCcgJiYgcHJvcGVydGllcyAhPT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdFbWJlck9iamVjdC5jcmVhdGUgb25seSBhY2NlcHRzIG9iamVjdHMuJywgdHlwZW9mIHByb3BlcnRpZXMgPT09ICdvYmplY3QnICYmIHByb3BlcnRpZXMgIT09IG51bGwpKTsKICAgICAgKGZhbHNlICYmICEoIShwcm9wZXJ0aWVzIGluc3RhbmNlb2YgX21ldGFsLk1peGluKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdFbWJlck9iamVjdC5jcmVhdGUgbm8gbG9uZ2VyIHN1cHBvcnRzIG1peGluZyBpbiBvdGhlciAnICsgJ2RlZmluaXRpb25zLCB1c2UgLmV4dGVuZCAmIC5jcmVhdGUgc2VwYXJhdGVseSBpbnN0ZWFkLicsICEocHJvcGVydGllcyBpbnN0YW5jZW9mIF9tZXRhbC5NaXhpbikpKTsKICAgICAgdmFyIGNvbmNhdGVuYXRlZFByb3BlcnRpZXMgPSBvYmouY29uY2F0ZW5hdGVkUHJvcGVydGllczsKICAgICAgdmFyIG1lcmdlZFByb3BlcnRpZXMgPSBvYmoubWVyZ2VkUHJvcGVydGllczsKICAgICAgdmFyIGhhc0NvbmNhdGVuYXRlZFByb3BzID0gY29uY2F0ZW5hdGVkUHJvcGVydGllcyAhPT0gdW5kZWZpbmVkICYmIGNvbmNhdGVuYXRlZFByb3BlcnRpZXMubGVuZ3RoID4gMDsKICAgICAgdmFyIGhhc01lcmdlZFByb3BzID0gbWVyZ2VkUHJvcGVydGllcyAhPT0gdW5kZWZpbmVkICYmIG1lcmdlZFByb3BlcnRpZXMubGVuZ3RoID4gMDsKICAgICAgdmFyIGtleU5hbWVzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleU5hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGtleU5hbWUgPSBrZXlOYW1lc1tpXTsKICAgICAgICB2YXIgdmFsdWUgPSBwcm9wZXJ0aWVzW2tleU5hbWVdOwogICAgICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzQ2xhc3NpY0RlY29yYXRvcikodmFsdWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0VtYmVyT2JqZWN0LmNyZWF0ZSBubyBsb25nZXIgc3VwcG9ydHMgZGVmaW5pbmcgY29tcHV0ZWQgJyArICdwcm9wZXJ0aWVzLiBEZWZpbmUgY29tcHV0ZWQgcHJvcGVydGllcyB1c2luZyBleHRlbmQoKSBvciByZW9wZW4oKSAnICsgJ2JlZm9yZSBjYWxsaW5nIGNyZWF0ZSgpLicsICEoMCwgX21ldGFsLmlzQ2xhc3NpY0RlY29yYXRvcikodmFsdWUpKSk7CiAgICAgICAgKGZhbHNlICYmICEoISh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicgJiYgdmFsdWUudG9TdHJpbmcoKS5pbmRleE9mKCcuX3N1cGVyJykgIT09IC0xKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdFbWJlck9iamVjdC5jcmVhdGUgbm8gbG9uZ2VyIHN1cHBvcnRzIGRlZmluaW5nIG1ldGhvZHMgdGhhdCBjYWxsIF9zdXBlci4nLCAhKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJyAmJiB2YWx1ZS50b1N0cmluZygpLmluZGV4T2YoJy5fc3VwZXInKSAhPT0gLTEpKSk7CiAgICAgICAgKGZhbHNlICYmICEoIShrZXlOYW1lID09PSAnYWN0aW9ucycgJiYgX2FjdGlvbl9oYW5kbGVyLmRlZmF1bHQuZGV0ZWN0KG9iaikpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2BhY3Rpb25zYCBtdXN0IGJlIHByb3ZpZGVkIGF0IGV4dGVuZCB0aW1lLCBub3QgYXQgY3JlYXRlIHRpbWUsICcgKyAnd2hlbiBFbWJlci5BY3Rpb25IYW5kbGVyIGlzIHVzZWQgKGkuZS4gdmlld3MsIGNvbnRyb2xsZXJzICYgcm91dGVzKS4nLCAhKGtleU5hbWUgPT09ICdhY3Rpb25zJyAmJiBfYWN0aW9uX2hhbmRsZXIuZGVmYXVsdC5kZXRlY3Qob2JqKSkpKTsKICAgICAgICB2YXIgcG9zc2libGVEZXNjID0gKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKG9iaiwga2V5TmFtZSwgbSk7CiAgICAgICAgdmFyIGlzRGVzY3JpcHRvciA9IHBvc3NpYmxlRGVzYyAhPT0gdW5kZWZpbmVkOwoKICAgICAgICBpZiAoIWlzRGVzY3JpcHRvcikgewogICAgICAgICAgdmFyIGJhc2VWYWx1ZSA9IG9ialtrZXlOYW1lXTsKCiAgICAgICAgICBpZiAoaGFzQ29uY2F0ZW5hdGVkUHJvcHMgJiYgY29uY2F0ZW5hdGVkUHJvcGVydGllcy5pbmRleE9mKGtleU5hbWUpID4gLTEpIHsKICAgICAgICAgICAgaWYgKGJhc2VWYWx1ZSkgewogICAgICAgICAgICAgIHZhbHVlID0gKDAsIF91dGlscy5tYWtlQXJyYXkpKGJhc2VWYWx1ZSkuY29uY2F0KHZhbHVlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB2YWx1ZSA9ICgwLCBfdXRpbHMubWFrZUFycmF5KSh2YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoaGFzTWVyZ2VkUHJvcHMgJiYgbWVyZ2VkUHJvcGVydGllcy5pbmRleE9mKGtleU5hbWUpID4gLTEpIHsKICAgICAgICAgICAgdmFsdWUgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBiYXNlVmFsdWUsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmIChpc0Rlc2NyaXB0b3IpIHsKICAgICAgICAgIHBvc3NpYmxlRGVzYy5zZXQob2JqLCBrZXlOYW1lLCB2YWx1ZSk7CiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb2JqLnNldFVua25vd25Qcm9wZXJ0eSA9PT0gJ2Z1bmN0aW9uJyAmJiAhKGtleU5hbWUgaW4gb2JqKSkgewogICAgICAgICAgb2JqLnNldFVua25vd25Qcm9wZXJ0eShrZXlOYW1lLCB2YWx1ZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChmYWxzZQogICAgICAgICAgLyogREVCVUcgKi8KICAgICAgICAgICkgewogICAgICAgICAgICAoMCwgX21ldGFsLmRlZmluZVByb3BlcnR5KShvYmosIGtleU5hbWUsIG51bGwsIHZhbHVlLCBtKTsgLy8gc2V0dXAgbWFuZGF0b3J5IHNldHRlcgogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb2JqW2tleU5hbWVdID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9IC8vIHVzaW5nIERFQlVHIGhlcmUgdG8gYXZvaWQgdGhlIGV4dHJhbmVvdXMgdmFyaWFibGUgd2hlbiBub3QgbmVlZGVkCgoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBpbml0Q2FsbGVkLmFkZChvYmopOwogICAgfQoKICAgIG9iai5pbml0KHByb3BlcnRpZXMpOwogICAgbS51bnNldEluaXRpYWxpemluZygpOwoKICAgIGlmICh0cnVlCiAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICkgewogICAgICAgIHZhciBvYnNlcnZlckV2ZW50cyA9IG0ub2JzZXJ2ZXJFdmVudHMoKTsKCiAgICAgICAgaWYgKG9ic2VydmVyRXZlbnRzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBvYnNlcnZlckV2ZW50cy5sZW5ndGg7IF9pKyspIHsKICAgICAgICAgICAgKDAsIF9tZXRhbC5hY3RpdmF0ZU9ic2VydmVyKShvYmosIG9ic2VydmVyRXZlbnRzW19pXS5ldmVudCwgb2JzZXJ2ZXJFdmVudHNbX2ldLnN5bmMpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgLy8gcmUtZW5hYmxlIGNoYWlucwogICAgICAoMCwgX21ldGFsLmZpbmlzaENoYWlucykobSk7CiAgICB9CgogICAgKDAsIF9tZXRhbC5zZW5kRXZlbnQpKG9iaiwgJ2luaXQnLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBtKTsKICB9CiAgLyoqCiAgICBgQ29yZU9iamVjdGAgaXMgdGhlIGJhc2UgY2xhc3MgZm9yIGFsbCBFbWJlciBjb25zdHJ1Y3RzLiBJdCBlc3RhYmxpc2hlcyBhCiAgICBjbGFzcyBzeXN0ZW0gYmFzZWQgb24gRW1iZXIncyBNaXhpbiBzeXN0ZW0sIGFuZCBwcm92aWRlcyB0aGUgYmFzaXMgZm9yIHRoZQogICAgRW1iZXIgT2JqZWN0IE1vZGVsLiBgQ29yZU9iamVjdGAgc2hvdWxkIGdlbmVyYWxseSBub3QgYmUgdXNlZCBkaXJlY3RseSwKICAgIGluc3RlYWQgeW91IHNob3VsZCB1c2UgYEVtYmVyT2JqZWN0YC4KICAKICAgICMjIFVzYWdlCiAgCiAgICBZb3UgY2FuIGRlZmluZSBhIGNsYXNzIGJ5IGV4dGVuZGluZyBmcm9tIGBDb3JlT2JqZWN0YCB1c2luZyB0aGUgYGV4dGVuZGAKICAgIG1ldGhvZDoKICAKICAgIGBgYGpzCiAgICBjb25zdCBQZXJzb24gPSBDb3JlT2JqZWN0LmV4dGVuZCh7CiAgICAgIG5hbWU6ICdUb21zdGVyJywKICAgIH0pOwogICAgYGBgCiAgCiAgICBGb3IgZGV0YWlsZWQgdXNhZ2UsIHNlZSB0aGUgW09iamVjdCBNb2RlbF0oaHR0cHM6Ly9ndWlkZXMuZW1iZXJqcy5jb20vcmVsZWFzZS9vYmplY3QtbW9kZWwvKQogICAgc2VjdGlvbiBvZiB0aGUgZ3VpZGVzLgogIAogICAgIyMgVXNhZ2Ugd2l0aCBOYXRpdmUgQ2xhc3NlcwogIAogICAgTmF0aXZlIEphdmFTY3JpcHQgYGNsYXNzYCBzeW50YXggY2FuIGJlIHVzZWQgdG8gZXh0ZW5kIGZyb20gYW55IGBDb3JlT2JqZWN0YAogICAgYmFzZWQgY2xhc3M6CiAgCiAgICBgYGBqcwogICAgY2xhc3MgUGVyc29uIGV4dGVuZHMgQ29yZU9iamVjdCB7CiAgICAgIGluaXQoKSB7CiAgICAgICAgc3VwZXIuaW5pdCguLi5hcmd1bWVudHMpOwogICAgICAgIHRoaXMubmFtZSA9ICdUb21zdGVyJzsKICAgICAgfQogICAgfQogICAgYGBgCiAgCiAgICBTb21lIG5vdGVzIGFib3V0IGBjbGFzc2AgdXNhZ2U6CiAgCiAgICAqIGBuZXdgIHN5bnRheCBpcyBub3QgY3VycmVudGx5IHN1cHBvcnRlZCB3aXRoIGNsYXNzZXMgdGhhdCBleHRlbmQgZnJvbQogICAgICBgRW1iZXJPYmplY3RgIG9yIGBDb3JlT2JqZWN0YC4gWW91IG11c3QgY29udGludWUgdG8gdXNlIHRoZSBgY3JlYXRlYCBtZXRob2QKICAgICAgd2hlbiBtYWtpbmcgbmV3IGluc3RhbmNlcyBvZiBjbGFzc2VzLCBldmVuIGlmIHRoZXkgYXJlIGRlZmluZWQgdXNpbmcgbmF0aXZlCiAgICAgIGNsYXNzIHN5bnRheC4gSWYgeW91IHdhbnQgdG8gdXNlIGBuZXdgIHN5bnRheCwgY29uc2lkZXIgY3JlYXRpbmcgY2xhc3NlcwogICAgICB3aGljaCBkbyBfbm90XyBleHRlbmQgZnJvbSBgRW1iZXJPYmplY3RgIG9yIGBDb3JlT2JqZWN0YC4gRW1iZXIgZmVhdHVyZXMsCiAgICAgIHN1Y2ggYXMgY29tcHV0ZWQgcHJvcGVydGllcyBhbmQgZGVjb3JhdG9ycywgd2lsbCBzdGlsbCB3b3JrIHdpdGggYmFzZS1sZXNzCiAgICAgIGNsYXNzZXMuCiAgICAqIEluc3RlYWQgb2YgdXNpbmcgYHRoaXMuX3N1cGVyKClgLCB5b3UgbXVzdCB1c2Ugc3RhbmRhcmQgYHN1cGVyYCBzeW50YXggaW4KICAgICAgbmF0aXZlIGNsYXNzZXMuIFNlZSB0aGUgW01ETiBkb2NzIG9uIGNsYXNzZXNdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0NsYXNzZXMjU3VwZXJfY2xhc3NfY2FsbHNfd2l0aF9zdXBlcikKICAgICAgZm9yIG1vcmUgZGV0YWlscy4KICAgICogTmF0aXZlIGNsYXNzZXMgc3VwcG9ydCB1c2luZyBbY29uc3RydWN0b3JzXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9DbGFzc2VzI0NvbnN0cnVjdG9yKQogICAgICB0byBzZXQgdXAgbmV3bHktY3JlYXRlZCBpbnN0YW5jZXMuIEVtYmVyIHVzZXMgdGhlc2UgdG8sIGFtb25nIG90aGVyIHRoaW5ncywKICAgICAgc3VwcG9ydCBmZWF0dXJlcyB0aGF0IG5lZWQgdG8gcmV0cmlldmUgb3RoZXIgZW50aXRpZXMgYnkgbmFtZSwgbGlrZSBTZXJ2aWNlCiAgICAgIGluamVjdGlvbiBhbmQgYGdldE93bmVyYC4gVG8gZW5zdXJlIHlvdXIgY3VzdG9tIGluc3RhbmNlIHNldHVwIGxvZ2ljIHRha2VzCiAgICAgIHBsYWNlIGFmdGVyIHRoaXMgaW1wb3J0YW50IHdvcmsgaXMgZG9uZSwgYXZvaWQgdXNpbmcgdGhlIGBjb25zdHJ1Y3RvcmAgaW4KICAgICAgZmF2b3Igb2YgYGluaXRgLgogICAgKiBQcm9wZXJ0aWVzIHBhc3NlZCB0byBgY3JlYXRlYCB3aWxsIGJlIGF2YWlsYWJsZSBvbiB0aGUgaW5zdGFuY2UgYnkgdGhlIHRpbWUKICAgICAgYGluaXRgIHJ1bnMsIHNvIGFueSBjb2RlIHRoYXQgcmVxdWlyZXMgdGhlc2UgdmFsdWVzIHNob3VsZCB3b3JrIGF0IHRoYXQKICAgICAgdGltZS4KICAgICogVXNpbmcgbmF0aXZlIGNsYXNzZXMsIGFuZCBzd2l0Y2hpbmcgYmFjayB0byB0aGUgb2xkIEVtYmVyIE9iamVjdCBtb2RlbCBpcwogICAgICBmdWxseSBzdXBwb3J0ZWQuCiAgCiAgICBAY2xhc3MgQ29yZU9iamVjdAogICAgQHB1YmxpYwogICovCgoKICB2YXIgQ29yZU9iamVjdCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIENvcmVPYmplY3QuX2luaXRGYWN0b3J5ID0gZnVuY3Rpb24gX2luaXRGYWN0b3J5KGZhY3RvcnkpIHsKICAgICAgZmFjdG9yeU1hcC5zZXQodGhpcywgZmFjdG9yeSk7CiAgICB9OwoKICAgIGZ1bmN0aW9uIENvcmVPYmplY3QocGFzc2VkRnJvbUNyZWF0ZSkgewogICAgICAvLyBwbHVjayBvZmYgZmFjdG9yeQogICAgICB2YXIgaW5pdEZhY3RvcnkgPSBmYWN0b3J5TWFwLmdldCh0aGlzLmNvbnN0cnVjdG9yKTsKCiAgICAgIGlmIChpbml0RmFjdG9yeSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZmFjdG9yeU1hcC5kZWxldGUodGhpcy5jb25zdHJ1Y3Rvcik7CgogICAgICAgIF9jb250YWluZXIuRkFDVE9SWV9GT1Iuc2V0KHRoaXMsIGluaXRGYWN0b3J5KTsKICAgICAgfSAvLyBwcmVwYXJlIHByb3RvdHlwZS4uLgoKCiAgICAgIHRoaXMuY29uc3RydWN0b3IucHJvdG8oKTsKICAgICAgdmFyIHNlbGYgPSB0aGlzOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICYmIF91dGlscy5IQVNfTkFUSVZFX1BST1hZICYmIHR5cGVvZiBzZWxmLnVua25vd25Qcm9wZXJ0eSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIHZhciBtZXNzYWdlRm9yID0gZnVuY3Rpb24gbWVzc2FnZUZvcihvYmosIHByb3BlcnR5KSB7CiAgICAgICAgICByZXR1cm4gIllvdSBhdHRlbXB0ZWQgdG8gYWNjZXNzIHRoZSBgIiArIFN0cmluZyhwcm9wZXJ0eSkgKyAiYCBwcm9wZXJ0eSAob2YgIiArIG9iaiArICIpLlxuIiArICJTaW5jZSBFbWJlciAzLjEsIHRoaXMgaXMgdXN1YWxseSBmaW5lIGFzIHlvdSBubyBsb25nZXIgbmVlZCB0byB1c2UgYC5nZXQoKWBcbiIgKyAidG8gYWNjZXNzIGNvbXB1dGVkIHByb3BlcnRpZXMuIEhvd2V2ZXIsIGluIHRoaXMgY2FzZSwgdGhlIG9iamVjdCBpbiBxdWVzdGlvblxuIiArICJpcyBhIHNwZWNpYWwga2luZCBvZiBFbWJlciBvYmplY3QgKGEgcHJveHkpLiBUaGVyZWZvcmUsIGl0IGlzIHN0aWxsIG5lY2Vzc2FyeVxuIiArICgidG8gdXNlIGAuZ2V0KCciICsgU3RyaW5nKHByb3BlcnR5KSArICInKWAgaW4gdGhpcyBjYXNlLlxuXG4iKSArICJJZiB5b3UgZW5jb3VudGVyZWQgdGhpcyBlcnJvciBiZWNhdXNlIG9mIHRoaXJkLXBhcnR5IGNvZGUgdGhhdCB5b3UgZG9uJ3QgY29udHJvbCxcbiIgKyAidGhlcmUgaXMgbW9yZSBpbmZvcm1hdGlvbiBhdCBodHRwczovL2dpdGh1Yi5jb20vZW1iZXJqcy9lbWJlci5qcy9pc3N1ZXMvMTYxNDgsIGFuZFxuIiArICJ5b3UgY2FuIGhlbHAgdXMgaW1wcm92ZSB0aGlzIGVycm9yIG1lc3NhZ2UgYnkgdGVsbGluZyB1cyBtb3JlIGFib3V0IHdoYXQgaGFwcGVuZWQgaW5cbiIgKyAidGhpcyBzaXR1YXRpb24uIjsKICAgICAgICB9OwogICAgICAgIC8qIGdsb2JhbHMgUHJveHkgUmVmbGVjdCAqLwoKCiAgICAgICAgc2VsZiA9IG5ldyBQcm94eSh0aGlzLCB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCh0YXJnZXQsIHByb3BlcnR5LCByZWNlaXZlcikgewogICAgICAgICAgICBpZiAocHJvcGVydHkgPT09IF9tZXRhbC5QUk9YWV9DT05URU5UKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRhcmdldDsKICAgICAgICAgICAgfSBlbHNlIGlmICggLy8gaW5pdCBjYWxsZWQgd2lsbCBiZSBzZXQgb24gdGhlIHByb3h5LCBub3QgdGhlIHRhcmdldCwgc28gZ2V0IHdpdGggdGhlIHJlY2VpdmVyCiAgICAgICAgICAgICFpbml0Q2FsbGVkLmhhcyhyZWNlaXZlcikgfHwgdHlwZW9mIHByb3BlcnR5ID09PSAnc3ltYm9sJyB8fCAoMCwgX3V0aWxzLmlzSW50ZXJuYWxTeW1ib2wpKHByb3BlcnR5KSB8fCBwcm9wZXJ0eSA9PT0gJ3RvSlNPTicgfHwgcHJvcGVydHkgPT09ICd0b1N0cmluZycgfHwgcHJvcGVydHkgPT09ICd0b1N0cmluZ0V4dGVuc2lvbicgfHwgcHJvcGVydHkgPT09ICdkaWREZWZpbmVQcm9wZXJ0eScgfHwgcHJvcGVydHkgPT09ICd3aWxsV2F0Y2hQcm9wZXJ0eScgfHwgcHJvcGVydHkgPT09ICdkaWRVbndhdGNoUHJvcGVydHknIHx8IHByb3BlcnR5ID09PSAnZGlkQWRkTGlzdGVuZXInIHx8IHByb3BlcnR5ID09PSAnZGlkUmVtb3ZlTGlzdGVuZXInIHx8IHByb3BlcnR5ID09PSAnaXNEZXNjcmlwdG9yJyB8fCBwcm9wZXJ0eSA9PT0gJ19vbkxvb2t1cCcgfHwgcHJvcGVydHkgaW4gdGFyZ2V0KSB7CiAgICAgICAgICAgICAgcmV0dXJuIFJlZmxlY3QuZ2V0KHRhcmdldCwgcHJvcGVydHksIHJlY2VpdmVyKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdmFyIHZhbHVlID0gdGFyZ2V0LnVua25vd25Qcm9wZXJ0eS5jYWxsKHJlY2VpdmVyLCBwcm9wZXJ0eSk7CgogICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICAgICAgKGZhbHNlICYmICEodmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKG1lc3NhZ2VGb3IocmVjZWl2ZXIsIHByb3BlcnR5KSwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gbnVsbCkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSk7CgogICAgICAgIF9jb250YWluZXIuRkFDVE9SWV9GT1Iuc2V0KHNlbGYsIGluaXRGYWN0b3J5KTsKICAgICAgfSAvLyBkaXNhYmxlIGNoYWlucwoKCiAgICAgIHZhciBtID0gKDAsIF9tZXRhMi5tZXRhKShzZWxmKTsKICAgICAgbS5zZXRJbml0aWFsaXppbmcoKTsKICAgICAgKGZhbHNlICYmICEoZnVuY3Rpb24gKCkgewogICAgICAgIGlmIChwYXNzZWRGcm9tQ3JlYXRlID09PSBQQVNTRURfRlJPTV9DUkVBVEUpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgaWYgKCF0cnVlCiAgICAgICAgLyogRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCAqLwogICAgICAgICkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CgogICAgICAgIGlmIChpbml0RmFjdG9yeSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICBpZiAocGFzc2VkRnJvbUNyZWF0ZSA9PT0gaW5pdEZhY3Rvcnkub3duZXIpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9KCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQW4gRW1iZXJPYmplY3QgYmFzZWQgY2xhc3MsICIgKyB0aGlzLmNvbnN0cnVjdG9yICsgIiwgd2FzIG5vdCBpbnN0YW50aWF0ZWQgY29ycmVjdGx5LiBZb3UgbWF5IGhhdmUgZWl0aGVyIHVzZWQgYG5ld2AgaW5zdGVhZCBvZiBgLmNyZWF0ZSgpYCwgb3Igbm90IHBhc3NlZCBhcmd1bWVudHMgdG8geW91ciBjYWxsIHRvIHN1cGVyIGluIHRoZSBjb25zdHJ1Y3RvcjogYHN1cGVyKC4uLmFyZ3VtZW50cylgLiBJZiB5b3UgYXJlIHRyeWluZyB0byB1c2UgYG5ld2AsIGNvbnNpZGVyIHVzaW5nIG5hdGl2ZSBjbGFzc2VzIHdpdGhvdXQgZXh0ZW5kaW5nIGZyb20gRW1iZXJPYmplY3QuIiwgZnVuY3Rpb24gKCkgewogICAgICAgIGlmIChwYXNzZWRGcm9tQ3JlYXRlID09PSBQQVNTRURfRlJPTV9DUkVBVEUpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgaWYgKCF0cnVlKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KCiAgICAgICAgaWYgKGluaXRGYWN0b3J5ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CgogICAgICAgIGlmIChwYXNzZWRGcm9tQ3JlYXRlID09PSBpbml0RmFjdG9yeS5vd25lcikgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0oKSkpOyAvLyBvbmx5IHJldHVybiB3aGVuIGluIGRlYnVnIGJ1aWxkcyBhbmQgYHNlbGZgIGlzIHRoZSBwcm94eSBjcmVhdGVkIGFib3ZlCgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgJiYgc2VsZiAhPT0gdGhpcykgewogICAgICAgIHJldHVybiBzZWxmOwogICAgICB9CiAgICB9CgogICAgdmFyIF9wcm90byA9IENvcmVPYmplY3QucHJvdG90eXBlOwoKICAgIF9wcm90by5yZW9wZW4gPSBmdW5jdGlvbiByZW9wZW4oKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgICgwLCBfbWV0YWwuYXBwbHlNaXhpbikodGhpcywgYXJncyk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfQogICAgLyoqCiAgICAgIEFuIG92ZXJyaWRhYmxlIG1ldGhvZCBjYWxsZWQgd2hlbiBvYmplY3RzIGFyZSBpbnN0YW50aWF0ZWQuIEJ5IGRlZmF1bHQsCiAgICAgIGRvZXMgbm90aGluZyB1bmxlc3MgaXQgaXMgb3ZlcnJpZGRlbiBkdXJpbmcgY2xhc3MgZGVmaW5pdGlvbi4KICAgICAgIEV4YW1wbGU6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgIGNvbnN0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgICAgaW5pdCgpIHsKICAgICAgICAgIGFsZXJ0KGBOYW1lIGlzICR7dGhpcy5nZXQoJ25hbWUnKX1gKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgbGV0IHN0ZXZlID0gUGVyc29uLmNyZWF0ZSh7CiAgICAgICAgbmFtZTogJ1N0ZXZlJwogICAgICB9KTsKICAgICAgIC8vIGFsZXJ0cyAnTmFtZSBpcyBTdGV2ZScuCiAgICAgIGBgYAogICAgICAgTk9URTogSWYgeW91IGRvIG92ZXJyaWRlIGBpbml0YCBmb3IgYSBmcmFtZXdvcmsgY2xhc3MgbGlrZSBgRW1iZXIuVmlld2AsCiAgICAgIGJlIHN1cmUgdG8gY2FsbCBgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKWAgaW4geW91cgogICAgICBgaW5pdGAgZGVjbGFyYXRpb24hIElmIHlvdSBkb24ndCwgRW1iZXIgbWF5IG5vdCBoYXZlIGFuIG9wcG9ydHVuaXR5IHRvCiAgICAgIGRvIGltcG9ydGFudCBzZXR1cCB3b3JrLCBhbmQgeW91J2xsIHNlZSBzdHJhbmdlIGJlaGF2aW9yIGluIHlvdXIKICAgICAgYXBwbGljYXRpb24uCiAgICAgICBAbWV0aG9kIGluaXQKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uaW5pdCA9IGZ1bmN0aW9uIGluaXQoKSB7fQogICAgLyoqCiAgICAgIERlZmluZXMgdGhlIHByb3BlcnRpZXMgdGhhdCB3aWxsIGJlIGNvbmNhdGVuYXRlZCBmcm9tIHRoZSBzdXBlcmNsYXNzCiAgICAgIChpbnN0ZWFkIG9mIG92ZXJyaWRkZW4pLgogICAgICAgQnkgZGVmYXVsdCwgd2hlbiB5b3UgZXh0ZW5kIGFuIEVtYmVyIGNsYXNzIGEgcHJvcGVydHkgZGVmaW5lZCBpbgogICAgICB0aGUgc3ViY2xhc3Mgb3ZlcnJpZGVzIGEgcHJvcGVydHkgd2l0aCB0aGUgc2FtZSBuYW1lIHRoYXQgaXMgZGVmaW5lZAogICAgICBpbiB0aGUgc3VwZXJjbGFzcy4gSG93ZXZlciwgdGhlcmUgYXJlIHNvbWUgY2FzZXMgd2hlcmUgaXQgaXMgcHJlZmVyYWJsZQogICAgICB0byBidWlsZCB1cCBhIHByb3BlcnR5J3MgdmFsdWUgYnkgY29tYmluaW5nIHRoZSBzdXBlcmNsYXNzJyBwcm9wZXJ0eQogICAgICB2YWx1ZSB3aXRoIHRoZSBzdWJjbGFzcycgdmFsdWUuIEFuIGV4YW1wbGUgb2YgdGhpcyBpbiB1c2Ugd2l0aGluIEVtYmVyCiAgICAgIGlzIHRoZSBgY2xhc3NOYW1lc2AgcHJvcGVydHkgb2YgYEVtYmVyLlZpZXdgLgogICAgICAgSGVyZSBpcyBzb21lIHNhbXBsZSBjb2RlIHNob3dpbmcgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBhIGNvbmNhdGVuYXRlZAogICAgICBwcm9wZXJ0eSBhbmQgYSBub3JtYWwgb25lOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgICBjb25zdCBCYXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAgIC8vIENvbmZpZ3VyZSB3aGljaCBwcm9wZXJ0aWVzIHRvIGNvbmNhdGVuYXRlCiAgICAgICAgY29uY2F0ZW5hdGVkUHJvcGVydGllczogWydjb25jYXRlbmF0ZWRQcm9wZXJ0eSddLAogICAgICAgICBzb21lTm9uQ29uY2F0ZW5hdGVkUHJvcGVydHk6IFsnYmFyJ10sCiAgICAgICAgY29uY2F0ZW5hdGVkUHJvcGVydHk6IFsnYmFyJ10KICAgICAgfSk7CiAgICAgICBjb25zdCBGb29CYXIgPSBCYXIuZXh0ZW5kKHsKICAgICAgICBzb21lTm9uQ29uY2F0ZW5hdGVkUHJvcGVydHk6IFsnZm9vJ10sCiAgICAgICAgY29uY2F0ZW5hdGVkUHJvcGVydHk6IFsnZm9vJ10KICAgICAgfSk7CiAgICAgICBsZXQgZm9vQmFyID0gRm9vQmFyLmNyZWF0ZSgpOwogICAgICBmb29CYXIuZ2V0KCdzb21lTm9uQ29uY2F0ZW5hdGVkUHJvcGVydHknKTsgLy8gWydmb28nXQogICAgICBmb29CYXIuZ2V0KCdjb25jYXRlbmF0ZWRQcm9wZXJ0eScpOyAvLyBbJ2JhcicsICdmb28nXQogICAgICBgYGAKICAgICAgIFRoaXMgYmVoYXZpb3IgZXh0ZW5kcyB0byBvYmplY3QgY3JlYXRpb24gYXMgd2VsbC4gQ29udGludWluZyB0aGUKICAgICAgYWJvdmUgZXhhbXBsZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IGZvb0JhciA9IEZvb0Jhci5jcmVhdGUoewogICAgICAgIHNvbWVOb25Db25jYXRlbmF0ZWRQcm9wZXJ0eTogWydiYXonXSwKICAgICAgICBjb25jYXRlbmF0ZWRQcm9wZXJ0eTogWydiYXonXQogICAgICB9KQogICAgICBmb29CYXIuZ2V0KCdzb21lTm9uQ29uY2F0ZW5hdGVkUHJvcGVydHknKTsgLy8gWydiYXonXQogICAgICBmb29CYXIuZ2V0KCdjb25jYXRlbmF0ZWRQcm9wZXJ0eScpOyAvLyBbJ2JhcicsICdmb28nLCAnYmF6J10KICAgICAgYGBgCiAgICAgICBBZGRpbmcgYSBzaW5nbGUgcHJvcGVydHkgdGhhdCBpcyBub3QgYW4gYXJyYXkgd2lsbCBqdXN0IGFkZCBpdCBpbiB0aGUgYXJyYXk6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBmb29CYXIgPSBGb29CYXIuY3JlYXRlKHsKICAgICAgICBjb25jYXRlbmF0ZWRQcm9wZXJ0eTogJ2JheicKICAgICAgfSkKICAgICAgdmlldy5nZXQoJ2NvbmNhdGVuYXRlZFByb3BlcnR5Jyk7IC8vIFsnYmFyJywgJ2ZvbycsICdiYXonXQogICAgICBgYGAKICAgICAgIFVzaW5nIHRoZSBgY29uY2F0ZW5hdGVkUHJvcGVydGllc2AgcHJvcGVydHksIHdlIGNhbiB0ZWxsIEVtYmVyIHRvIG1peCB0aGUKICAgICAgY29udGVudCBvZiB0aGUgcHJvcGVydGllcy4KICAgICAgIEluIGBDb21wb25lbnRgIHRoZSBgY2xhc3NOYW1lc2AsIGBjbGFzc05hbWVCaW5kaW5nc2AgYW5kCiAgICAgIGBhdHRyaWJ1dGVCaW5kaW5nc2AgcHJvcGVydGllcyBhcmUgY29uY2F0ZW5hdGVkLgogICAgICAgVGhpcyBmZWF0dXJlIGlzIGF2YWlsYWJsZSBmb3IgeW91IHRvIHVzZSB0aHJvdWdob3V0IHRoZSBFbWJlciBvYmplY3QgbW9kZWwsCiAgICAgIGFsdGhvdWdoIHR5cGljYWwgYXBwIGRldmVsb3BlcnMgYXJlIGxpa2VseSB0byB1c2UgaXQgaW5mcmVxdWVudGx5LiBTaW5jZQogICAgICBpdCBjaGFuZ2VzIGV4cGVjdGF0aW9ucyBhYm91dCBiZWhhdmlvciBvZiBwcm9wZXJ0aWVzLCB5b3Ugc2hvdWxkIHByb3Blcmx5CiAgICAgIGRvY3VtZW50IGl0cyB1c2FnZSBpbiBlYWNoIGluZGl2aWR1YWwgY29uY2F0ZW5hdGVkIHByb3BlcnR5ICh0byBub3QKICAgICAgbWlzbGVhZCB5b3VyIHVzZXJzIHRvIHRoaW5rIHRoZXkgY2FuIG92ZXJyaWRlIHRoZSBwcm9wZXJ0eSBpbiBhIHN1YmNsYXNzKS4KICAgICAgIEBwcm9wZXJ0eSBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzCiAgICAgIEB0eXBlIEFycmF5CiAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgRGVmaW5lcyB0aGUgcHJvcGVydGllcyB0aGF0IHdpbGwgYmUgbWVyZ2VkIGZyb20gdGhlIHN1cGVyY2xhc3MKICAgICAgKGluc3RlYWQgb2Ygb3ZlcnJpZGRlbikuCiAgICAgICBCeSBkZWZhdWx0LCB3aGVuIHlvdSBleHRlbmQgYW4gRW1iZXIgY2xhc3MgYSBwcm9wZXJ0eSBkZWZpbmVkIGluCiAgICAgIHRoZSBzdWJjbGFzcyBvdmVycmlkZXMgYSBwcm9wZXJ0eSB3aXRoIHRoZSBzYW1lIG5hbWUgdGhhdCBpcyBkZWZpbmVkCiAgICAgIGluIHRoZSBzdXBlcmNsYXNzLiBIb3dldmVyLCB0aGVyZSBhcmUgc29tZSBjYXNlcyB3aGVyZSBpdCBpcyBwcmVmZXJhYmxlCiAgICAgIHRvIGJ1aWxkIHVwIGEgcHJvcGVydHkncyB2YWx1ZSBieSBtZXJnaW5nIHRoZSBzdXBlcmNsYXNzIHByb3BlcnR5IHZhbHVlCiAgICAgIHdpdGggdGhlIHN1YmNsYXNzIHByb3BlcnR5J3MgdmFsdWUuIEFuIGV4YW1wbGUgb2YgdGhpcyBpbiB1c2Ugd2l0aGluIEVtYmVyCiAgICAgIGlzIHRoZSBgcXVlcnlQYXJhbXNgIHByb3BlcnR5IG9mIHJvdXRlcy4KICAgICAgIEhlcmUgaXMgc29tZSBzYW1wbGUgY29kZSBzaG93aW5nIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gYSBtZXJnZWQKICAgICAgcHJvcGVydHkgYW5kIGEgbm9ybWFsIG9uZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgY29uc3QgQmFyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICAvLyBDb25maWd1cmUgd2hpY2ggcHJvcGVydGllcyBhcmUgdG8gYmUgbWVyZ2VkCiAgICAgICAgbWVyZ2VkUHJvcGVydGllczogWydtZXJnZWRQcm9wZXJ0eSddLAogICAgICAgICBzb21lTm9uTWVyZ2VkUHJvcGVydHk6IHsKICAgICAgICAgIG5vbk1lcmdlZDogJ3N1cGVyY2xhc3MgdmFsdWUgb2Ygbm9uTWVyZ2VkJwogICAgICAgIH0sCiAgICAgICAgbWVyZ2VkUHJvcGVydHk6IHsKICAgICAgICAgIHBhZ2U6IHsgcmVwbGFjZTogZmFsc2UgfSwKICAgICAgICAgIGxpbWl0OiB7IHJlcGxhY2U6IHRydWUgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBjb25zdCBGb29CYXIgPSBCYXIuZXh0ZW5kKHsKICAgICAgICBzb21lTm9uTWVyZ2VkUHJvcGVydHk6IHsKICAgICAgICAgIGNvbXBsZXRlbHlOb25NZXJnZWQ6ICdzdWJjbGFzcyB2YWx1ZSBvZiBub25NZXJnZWQnCiAgICAgICAgfSwKICAgICAgICBtZXJnZWRQcm9wZXJ0eTogewogICAgICAgICAgbGltaXQ6IHsgcmVwbGFjZTogZmFsc2UgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBsZXQgZm9vQmFyID0gRm9vQmFyLmNyZWF0ZSgpOwogICAgICAgZm9vQmFyLmdldCgnc29tZU5vbk1lcmdlZFByb3BlcnR5Jyk7CiAgICAgIC8vID0+IHsgY29tcGxldGVseU5vbk1lcmdlZDogJ3N1YmNsYXNzIHZhbHVlIG9mIG5vbk1lcmdlZCcgfQogICAgICAvLwogICAgICAvLyBOb3RlIHRoZSBlbnRpcmUgb2JqZWN0LCBpbmNsdWRpbmcgdGhlIG5vbk1lcmdlZCBwcm9wZXJ0eSBvZgogICAgICAvLyB0aGUgc3VwZXJjbGFzcyBvYmplY3QsIGhhcyBiZWVuIHJlcGxhY2VkCiAgICAgICBmb29CYXIuZ2V0KCdtZXJnZWRQcm9wZXJ0eScpOwogICAgICAvLyA9PiB7CiAgICAgIC8vICAgcGFnZToge3JlcGxhY2U6IGZhbHNlfSwKICAgICAgLy8gICBsaW1pdDoge3JlcGxhY2U6IGZhbHNlfQogICAgICAvLyB9CiAgICAgIC8vCiAgICAgIC8vIE5vdGUgdGhlIHBhZ2UgcmVtYWlucyBmcm9tIHRoZSBzdXBlcmNsYXNzLCBhbmQgdGhlCiAgICAgIC8vIGBsaW1pdGAgcHJvcGVydHkncyB2YWx1ZSBvZiBgZmFsc2VgIGhhcyBiZWVuIG1lcmdlZCBmcm9tCiAgICAgIC8vIHRoZSBzdWJjbGFzcy4KICAgICAgYGBgCiAgICAgICBUaGlzIGJlaGF2aW9yIGlzIG5vdCBhdmFpbGFibGUgZHVyaW5nIG9iamVjdCBgY3JlYXRlYCBjYWxscy4gSXQgaXMgb25seQogICAgICBhdmFpbGFibGUgYXQgYGV4dGVuZGAgdGltZS4KICAgICAgIEluIGBSb3V0ZWAgdGhlIGBxdWVyeVBhcmFtc2AgcHJvcGVydHkgaXMgbWVyZ2VkLgogICAgICAgVGhpcyBmZWF0dXJlIGlzIGF2YWlsYWJsZSBmb3IgeW91IHRvIHVzZSB0aHJvdWdob3V0IHRoZSBFbWJlciBvYmplY3QgbW9kZWwsCiAgICAgIGFsdGhvdWdoIHR5cGljYWwgYXBwIGRldmVsb3BlcnMgYXJlIGxpa2VseSB0byB1c2UgaXQgaW5mcmVxdWVudGx5LiBTaW5jZQogICAgICBpdCBjaGFuZ2VzIGV4cGVjdGF0aW9ucyBhYm91dCBiZWhhdmlvciBvZiBwcm9wZXJ0aWVzLCB5b3Ugc2hvdWxkIHByb3Blcmx5CiAgICAgIGRvY3VtZW50IGl0cyB1c2FnZSBpbiBlYWNoIGluZGl2aWR1YWwgbWVyZ2VkIHByb3BlcnR5ICh0byBub3QKICAgICAgbWlzbGVhZCB5b3VyIHVzZXJzIHRvIHRoaW5rIHRoZXkgY2FuIG92ZXJyaWRlIHRoZSBwcm9wZXJ0eSBpbiBhIHN1YmNsYXNzKS4KICAgICAgIEBwcm9wZXJ0eSBtZXJnZWRQcm9wZXJ0aWVzCiAgICAgIEB0eXBlIEFycmF5CiAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgRGVzdHJveWVkIG9iamVjdCBwcm9wZXJ0eSBmbGFnLgogICAgICAgaWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAgdGhlIG9ic2VydmVycyBhbmQgYmluZGluZ3Mgd2VyZSBhbHJlYWR5CiAgICAgIHJlbW92ZWQgYnkgdGhlIGVmZmVjdCBvZiBjYWxsaW5nIHRoZSBgZGVzdHJveSgpYCBtZXRob2QuCiAgICAgICBAcHJvcGVydHkgaXNEZXN0cm95ZWQKICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICAvKioKICAgICAgRGVzdHJveXMgYW4gb2JqZWN0IGJ5IHNldHRpbmcgdGhlIGBpc0Rlc3Ryb3llZGAgZmxhZyBhbmQgcmVtb3ZpbmcgaXRzCiAgICAgIG1ldGFkYXRhLCB3aGljaCBlZmZlY3RpdmVseSBkZXN0cm95cyBvYnNlcnZlcnMgYW5kIGJpbmRpbmdzLgogICAgICAgSWYgeW91IHRyeSB0byBzZXQgYSBwcm9wZXJ0eSBvbiBhIGRlc3Ryb3llZCBvYmplY3QsIGFuIGV4Y2VwdGlvbiB3aWxsIGJlCiAgICAgIHJhaXNlZC4KICAgICAgIE5vdGUgdGhhdCBkZXN0cnVjdGlvbiBpcyBzY2hlZHVsZWQgZm9yIHRoZSBlbmQgb2YgdGhlIHJ1biBsb29wIGFuZCBkb2VzIG5vdAogICAgICBoYXBwZW4gaW1tZWRpYXRlbHkuICBJdCB3aWxsIHNldCBhbiBpc0Rlc3Ryb3lpbmcgZmxhZyBpbW1lZGlhdGVseS4KICAgICAgIEBtZXRob2QgZGVzdHJveQogICAgICBAcmV0dXJuIHtFbWJlck9iamVjdH0gcmVjZWl2ZXIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIF9wcm90by5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdmFyIG0gPSAoMCwgX21ldGEyLnBlZWtNZXRhKSh0aGlzKTsKCiAgICAgIGlmIChtLmlzU291cmNlRGVzdHJveWluZygpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBtLnNldFNvdXJjZURlc3Ryb3lpbmcoKTsKICAgICAgKDAsIF9ydW5sb29wLnNjaGVkdWxlKSgnYWN0aW9ucycsIHRoaXMsIHRoaXMud2lsbERlc3Ryb3kpOwogICAgICAoMCwgX3J1bmxvb3Auc2NoZWR1bGUpKCdkZXN0cm95JywgdGhpcywgdGhpcy5fc2NoZWR1bGVkRGVzdHJveSwgbSk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfQogICAgLyoqCiAgICAgIE92ZXJyaWRlIHRvIGltcGxlbWVudCB0ZWFyZG93bi4KICAgICAgIEBtZXRob2Qgd2lsbERlc3Ryb3kKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ud2lsbERlc3Ryb3kgPSBmdW5jdGlvbiB3aWxsRGVzdHJveSgpIHt9CiAgICAvKioKICAgICAgSW52b2tlZCBieSB0aGUgcnVuIGxvb3AgdG8gYWN0dWFsbHkgZGVzdHJveSB0aGUgb2JqZWN0LiBUaGlzIGlzCiAgICAgIHNjaGVkdWxlZCBmb3IgZXhlY3V0aW9uIGJ5IHRoZSBgZGVzdHJveWAgbWV0aG9kLgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBfc2NoZWR1bGVkRGVzdHJveQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3NjaGVkdWxlZERlc3Ryb3kgPSBmdW5jdGlvbiBfc2NoZWR1bGVkRGVzdHJveShtKSB7CiAgICAgIGlmIChtLmlzU291cmNlRGVzdHJveWVkKCkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgICgwLCBfbWV0YTIuZGVsZXRlTWV0YSkodGhpcyk7CiAgICAgIG0uc2V0U291cmNlRGVzdHJveWVkKCk7CiAgICB9CiAgICAvKioKICAgICAgUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiB3aGljaCBhdHRlbXB0cyB0byBwcm92aWRlIG1vcmUgaW5mb3JtYXRpb24KICAgICAgdGhhbiBKYXZhc2NyaXB0J3MgYHRvU3RyaW5nYCB0eXBpY2FsbHkgZG9lcywgaW4gYSBnZW5lcmljIHdheSBmb3IgYWxsIEVtYmVyCiAgICAgIG9iamVjdHMuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgIGNvbnN0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCgpOwogICAgICBwZXJzb24gPSBQZXJzb24uY3JlYXRlKCk7CiAgICAgIHBlcnNvbi50b1N0cmluZygpOyAvLz0+ICI8UGVyc29uOmVtYmVyMTAyND4iCiAgICAgIGBgYAogICAgICAgSWYgdGhlIG9iamVjdCdzIGNsYXNzIGlzIG5vdCBkZWZpbmVkIG9uIGFuIEVtYmVyIG5hbWVzcGFjZSwgaXQgd2lsbAogICAgICBpbmRpY2F0ZSBpdCBpcyBhIHN1YmNsYXNzIG9mIHRoZSByZWdpc3RlcmVkIHN1cGVyY2xhc3M6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGNvbnN0IFN0dWRlbnQgPSBQZXJzb24uZXh0ZW5kKCk7CiAgICAgIGxldCBzdHVkZW50ID0gU3R1ZGVudC5jcmVhdGUoKTsKICAgICAgc3R1ZGVudC50b1N0cmluZygpOyAvLz0+ICI8KHN1YmNsYXNzIG9mIFBlcnNvbik6ZW1iZXIxMDI1PiIKICAgICAgYGBgCiAgICAgICBJZiB0aGUgbWV0aG9kIGB0b1N0cmluZ0V4dGVuc2lvbmAgaXMgZGVmaW5lZCwgaXRzIHJldHVybiB2YWx1ZSB3aWxsIGJlCiAgICAgIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGNvbnN0IFRlYWNoZXIgPSBQZXJzb24uZXh0ZW5kKHsKICAgICAgICB0b1N0cmluZ0V4dGVuc2lvbigpIHsKICAgICAgICAgIHJldHVybiB0aGlzLmdldCgnZnVsbE5hbWUnKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICB0ZWFjaGVyID0gVGVhY2hlci5jcmVhdGUoKTsKICAgICAgdGVhY2hlci50b1N0cmluZygpOyAvLz0+ICI8VGVhY2hlcjplbWJlcjEwMjY6VG9tIERhbGU+IgogICAgICBgYGAKICAgICAgIEBtZXRob2QgdG9TdHJpbmcKICAgICAgQHJldHVybiB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24KICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8udG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgdmFyIGhhc1RvU3RyaW5nRXh0ZW5zaW9uID0gdHlwZW9mIHRoaXMudG9TdHJpbmdFeHRlbnNpb24gPT09ICdmdW5jdGlvbic7CiAgICAgIHZhciBleHRlbnNpb24gPSBoYXNUb1N0cmluZ0V4dGVuc2lvbiA/ICI6IiArIHRoaXMudG9TdHJpbmdFeHRlbnNpb24oKSA6ICcnOwogICAgICB2YXIgcmV0ID0gIjwiICsgKCgwLCBfdXRpbHMuZ2V0TmFtZSkodGhpcykgfHwgX2NvbnRhaW5lci5GQUNUT1JZX0ZPUi5nZXQodGhpcykgfHwgdGhpcy5jb25zdHJ1Y3Rvci50b1N0cmluZygpKSArICI6IiArICgwLCBfdXRpbHMuZ3VpZEZvcikodGhpcykgKyBleHRlbnNpb24gKyAiPiI7CiAgICAgIHJldHVybiByZXQ7CiAgICB9CiAgICAvKioKICAgICAgQ3JlYXRlcyBhIG5ldyBzdWJjbGFzcy4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgY29uc3QgUGVyc29uID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICBzYXkodGhpbmcpIHsKICAgICAgICAgIGFsZXJ0KHRoaW5nKTsKICAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBUaGlzIGRlZmluZXMgYSBuZXcgc3ViY2xhc3Mgb2YgRW1iZXJPYmplY3Q6IGBQZXJzb25gLiBJdCBjb250YWlucyBvbmUgbWV0aG9kOiBgc2F5KClgLgogICAgICAgWW91IGNhbiBhbHNvIGNyZWF0ZSBhIHN1YmNsYXNzIGZyb20gYW55IGV4aXN0aW5nIGNsYXNzIGJ5IGNhbGxpbmcgaXRzIGBleHRlbmQoKWAgbWV0aG9kLgogICAgICBGb3IgZXhhbXBsZSwgeW91IG1pZ2h0IHdhbnQgdG8gY3JlYXRlIGEgc3ViY2xhc3Mgb2YgRW1iZXIncyBidWlsdC1pbiBgQ29tcG9uZW50YCBjbGFzczoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgIGNvbnN0IFBlcnNvbkNvbXBvbmVudCA9IENvbXBvbmVudC5leHRlbmQoewogICAgICAgIHRhZ05hbWU6ICdsaScsCiAgICAgICAgY2xhc3NOYW1lQmluZGluZ3M6IFsnaXNBZG1pbmlzdHJhdG9yJ10KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgV2hlbiBkZWZpbmluZyBhIHN1YmNsYXNzLCB5b3UgY2FuIG92ZXJyaWRlIG1ldGhvZHMgYnV0IHN0aWxsIGFjY2VzcyB0aGUKICAgICAgaW1wbGVtZW50YXRpb24gb2YgeW91ciBwYXJlbnQgY2xhc3MgYnkgY2FsbGluZyB0aGUgc3BlY2lhbCBgX3N1cGVyKClgIG1ldGhvZDoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgY29uc3QgUGVyc29uID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICBzYXkodGhpbmcpIHsKICAgICAgICAgIGxldCBuYW1lID0gdGhpcy5nZXQoJ25hbWUnKTsKICAgICAgICAgIGFsZXJ0KGAke25hbWV9IHNheXM6ICR7dGhpbmd9YCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGNvbnN0IFNvbGRpZXIgPSBQZXJzb24uZXh0ZW5kKHsKICAgICAgICBzYXkodGhpbmcpIHsKICAgICAgICAgIHRoaXMuX3N1cGVyKGAke3RoaW5nfSwgc2lyIWApOwogICAgICAgIH0sCiAgICAgICAgbWFyY2gobnVtYmVyT2ZIb3VycykgewogICAgICAgICAgYWxlcnQoYCR7dGhpcy5nZXQoJ25hbWUnKX0gbWFyY2hlcyBmb3IgJHtudW1iZXJPZkhvdXJzfSBob3Vycy5gKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgbGV0IHllaHVkYSA9IFNvbGRpZXIuY3JlYXRlKHsKICAgICAgICBuYW1lOiAnWWVodWRhIEthdHonCiAgICAgIH0pOwogICAgICAgeWVodWRhLnNheSgnWWVzJyk7ICAvLyBhbGVydHMgIlllaHVkYSBLYXR6IHNheXM6IFllcywgc2lyISIKICAgICAgYGBgCiAgICAgICBUaGUgYGNyZWF0ZSgpYCBvbiBsaW5lICMxNyBjcmVhdGVzIGFuICppbnN0YW5jZSogb2YgdGhlIGBTb2xkaWVyYCBjbGFzcy4KICAgICAgVGhlIGBleHRlbmQoKWAgb24gbGluZSAjOCBjcmVhdGVzIGEgKnN1YmNsYXNzKiBvZiBgUGVyc29uYC4gQW55IGluc3RhbmNlCiAgICAgIG9mIHRoZSBgUGVyc29uYCBjbGFzcyB3aWxsICpub3QqIGhhdmUgdGhlIGBtYXJjaCgpYCBtZXRob2QuCiAgICAgICBZb3UgY2FuIGFsc28gcGFzcyBgTWl4aW5gIGNsYXNzZXMgdG8gYWRkIGFkZGl0aW9uYWwgcHJvcGVydGllcyB0byB0aGUgc3ViY2xhc3MuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgaW1wb3J0IE1peGluIGZyb20gJ0BlbWJlci9vYmplY3QvbWl4aW4nOwogICAgICAgY29uc3QgUGVyc29uID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICBzYXkodGhpbmcpIHsKICAgICAgICAgIGFsZXJ0KGAke3RoaXMuZ2V0KCduYW1lJyl9IHNheXM6ICR7dGhpbmd9YCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGNvbnN0IFNpbmdpbmdNaXhpbiA9IE1peGluLmNyZWF0ZSh7CiAgICAgICAgc2luZyh0aGluZykgewogICAgICAgICAgYWxlcnQoYCR7dGhpcy5nZXQoJ25hbWUnKX0gc2luZ3M6IGxhIGxhIGxhICR7dGhpbmd9YCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGNvbnN0IEJyb2Fkd2F5U3RhciA9IFBlcnNvbi5leHRlbmQoU2luZ2luZ01peGluLCB7CiAgICAgICAgZGFuY2UoKSB7CiAgICAgICAgICBhbGVydChgJHt0aGlzLmdldCgnbmFtZScpfSBkYW5jZXM6IHRhcCB0YXAgdGFwIHRhcCBgKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRoZSBgQnJvYWR3YXlTdGFyYCBjbGFzcyBjb250YWlucyB0aHJlZSBtZXRob2RzOiBgc2F5KClgLCBgc2luZygpYCwgYW5kIGBkYW5jZSgpYC4KICAgICAgIEBtZXRob2QgZXh0ZW5kCiAgICAgIEBzdGF0aWMKICAgICAgQGZvciBAZW1iZXIvb2JqZWN0CiAgICAgIEBwYXJhbSB7TWl4aW59IFttaXhpbnNdKiBPbmUgb3IgbW9yZSBNaXhpbiBjbGFzc2VzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBbYXJndW1lbnRzXSogT2JqZWN0IGNvbnRhaW5pbmcgdmFsdWVzIHRvIHVzZSB3aXRoaW4gdGhlIG5ldyBjbGFzcwogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIENvcmVPYmplY3QuZXh0ZW5kID0gZnVuY3Rpb24gZXh0ZW5kKCkgewogICAgICB2YXIgQ2xhc3MgPQogICAgICAvKiNfX1BVUkVfXyovCiAgICAgIGZ1bmN0aW9uIChfdGhpcykgewogICAgICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDbGFzcywgX3RoaXMpOwoKICAgICAgICBmdW5jdGlvbiBDbGFzcygpIHsKICAgICAgICAgIHJldHVybiBfdGhpcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gQ2xhc3M7CiAgICAgIH0odGhpcyk7CgogICAgICBfcmVvcGVuLmFwcGx5KENsYXNzLlByb3RvdHlwZU1peGluLCBhcmd1bWVudHMpOwoKICAgICAgcmV0dXJuIENsYXNzOwogICAgfQogICAgLyoqCiAgICAgIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgYSBjbGFzcy4gQWNjZXB0cyBlaXRoZXIgbm8gYXJndW1lbnRzLCBvciBhbiBvYmplY3QKICAgICAgY29udGFpbmluZyB2YWx1ZXMgdG8gaW5pdGlhbGl6ZSB0aGUgbmV3bHkgaW5zdGFudGlhdGVkIG9iamVjdCB3aXRoLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgICBjb25zdCBQZXJzb24gPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAgIGhlbGxvV29ybGQoKSB7CiAgICAgICAgICBhbGVydChgSGksIG15IG5hbWUgaXMgJHt0aGlzLmdldCgnbmFtZScpfWApOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBsZXQgdG9tID0gUGVyc29uLmNyZWF0ZSh7CiAgICAgICAgbmFtZTogJ1RvbSBEYWxlJwogICAgICB9KTsKICAgICAgIHRvbS5oZWxsb1dvcmxkKCk7IC8vIGFsZXJ0cyAiSGksIG15IG5hbWUgaXMgVG9tIERhbGUiLgogICAgICBgYGAKICAgICAgIGBjcmVhdGVgIHdpbGwgY2FsbCB0aGUgYGluaXRgIGZ1bmN0aW9uIGlmIGRlZmluZWQgZHVyaW5nCiAgICAgIGBBbnlPYmplY3QuZXh0ZW5kYAogICAgICAgSWYgbm8gYXJndW1lbnRzIGFyZSBwYXNzZWQgdG8gYGNyZWF0ZWAsIGl0IHdpbGwgbm90IHNldCB2YWx1ZXMgdG8gdGhlIG5ldwogICAgICBpbnN0YW5jZSBkdXJpbmcgaW5pdGlhbGl6YXRpb246CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBub05hbWUgPSBQZXJzb24uY3JlYXRlKCk7CiAgICAgIG5vTmFtZS5oZWxsb1dvcmxkKCk7IC8vIGFsZXJ0cyB1bmRlZmluZWQKICAgICAgYGBgCiAgICAgICBOT1RFOiBGb3IgcGVyZm9ybWFuY2UgcmVhc29ucywgeW91IGNhbm5vdCBkZWNsYXJlIG1ldGhvZHMgb3IgY29tcHV0ZWQKICAgICAgcHJvcGVydGllcyBkdXJpbmcgYGNyZWF0ZWAuIFlvdSBzaG91bGQgaW5zdGVhZCBkZWNsYXJlIG1ldGhvZHMgYW5kIGNvbXB1dGVkCiAgICAgIHByb3BlcnRpZXMgd2hlbiB1c2luZyBgZXh0ZW5kYC4KICAgICAgIEBtZXRob2QgY3JlYXRlCiAgICAgIEBmb3IgQGVtYmVyL29iamVjdAogICAgICBAc3RhdGljCiAgICAgIEBwYXJhbSBbYXJndW1lbnRzXSoKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBDb3JlT2JqZWN0LmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wcywgZXh0cmEpIHsKICAgICAgdmFyIEMgPSB0aGlzOwogICAgICB2YXIgaW5zdGFuY2U7CgogICAgICBpZiAodHJ1ZQogICAgICAvKiBFTUJFUl9GUkFNRVdPUktfT0JKRUNUX09XTkVSX0FSR1VNRU5UICovCiAgICAgICYmIHRoaXNbRlJBTUVXT1JLX0NMQVNTRVNdKSB7CiAgICAgICAgdmFyIGluaXRGYWN0b3J5ID0gZmFjdG9yeU1hcC5nZXQodGhpcyk7CiAgICAgICAgdmFyIG93bmVyOwoKICAgICAgICBpZiAoaW5pdEZhY3RvcnkgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgb3duZXIgPSBpbml0RmFjdG9yeS5vd25lcjsKICAgICAgICB9IGVsc2UgaWYgKHByb3BzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikocHJvcHMpOwogICAgICAgIH0KCiAgICAgICAgaWYgKG93bmVyID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIC8vIGZhbGxiYWNrIHRvIHBhc3NpbmcgdGhlIHNwZWNpYWwgUEFTU0VEX0ZST01fQ1JFQVRFIHN5bWJvbAogICAgICAgICAgLy8gdG8gYXZvaWQgYW4gZXJyb3Igd2hlbiBmb2xrcyBjYWxsIHRoaW5ncyBsaWtlIENvbnRyb2xsZXIuZXh0ZW5kKCkuY3JlYXRlKCkKICAgICAgICAgIC8vIHdlIHNob3VsZCBkbyBhIHN1YnNlcXVlbnQgZGVwcmVjYXRpb24gcGFzcyB0byBlbnN1cmUgdGhpcyBpc24ndCBhbGxvd2VkCiAgICAgICAgICBvd25lciA9IFBBU1NFRF9GUk9NX0NSRUFURTsKICAgICAgICB9CgogICAgICAgIGluc3RhbmNlID0gbmV3IEMob3duZXIpOwogICAgICB9IGVsc2UgewogICAgICAgIGluc3RhbmNlID0gZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgID8gbmV3IEMoUEFTU0VEX0ZST01fQ1JFQVRFKSA6IG5ldyBDKCk7CiAgICAgIH0KCiAgICAgIGlmIChleHRyYSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgaW5pdGlhbGl6ZShpbnN0YW5jZSwgcHJvcHMpOwogICAgICB9IGVsc2UgewogICAgICAgIGluaXRpYWxpemUoaW5zdGFuY2UsIGZsYXR0ZW5Qcm9wcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGluc3RhbmNlOwogICAgfQogICAgLyoqCiAgICAgIEF1Z21lbnRzIGEgY29uc3RydWN0b3IncyBwcm90b3R5cGUgd2l0aCBhZGRpdGlvbmFsCiAgICAgIHByb3BlcnRpZXMgYW5kIGZ1bmN0aW9uczoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgY29uc3QgTXlPYmplY3QgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAgIG5hbWU6ICdhbiBvYmplY3QnCiAgICAgIH0pOwogICAgICAgbyA9IE15T2JqZWN0LmNyZWF0ZSgpOwogICAgICBvLmdldCgnbmFtZScpOyAvLyAnYW4gb2JqZWN0JwogICAgICAgTXlPYmplY3QucmVvcGVuKHsKICAgICAgICBzYXkobXNnKSB7CiAgICAgICAgICBjb25zb2xlLmxvZyhtc2cpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBvMiA9IE15T2JqZWN0LmNyZWF0ZSgpOwogICAgICBvMi5zYXkoJ2hlbGxvJyk7IC8vIGxvZ3MgImhlbGxvIgogICAgICAgby5zYXkoJ2dvb2RieWUnKTsgLy8gbG9ncyAiZ29vZGJ5ZSIKICAgICAgYGBgCiAgICAgICBUbyBhZGQgZnVuY3Rpb25zIGFuZCBwcm9wZXJ0aWVzIHRvIHRoZSBjb25zdHJ1Y3RvciBpdHNlbGYsCiAgICAgIHNlZSBgcmVvcGVuQ2xhc3NgCiAgICAgICBAbWV0aG9kIHJlb3BlbgogICAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgICAgQHN0YXRpYwogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIENvcmVPYmplY3QucmVvcGVuID0gZnVuY3Rpb24gcmVvcGVuKCkgewogICAgICB0aGlzLndpbGxSZW9wZW4oKTsKCiAgICAgIF9yZW9wZW4uYXBwbHkodGhpcy5Qcm90b3R5cGVNaXhpbiwgYXJndW1lbnRzKTsKCiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICBDb3JlT2JqZWN0LndpbGxSZW9wZW4gPSBmdW5jdGlvbiB3aWxsUmVvcGVuKCkgewogICAgICB2YXIgcCA9IHRoaXMucHJvdG90eXBlOwoKICAgICAgaWYgKHdhc0FwcGxpZWQuaGFzKHApKSB7CiAgICAgICAgd2FzQXBwbGllZC5kZWxldGUocCk7IC8vIElmIHRoZSBiYXNlIG1peGluIGFscmVhZHkgZXhpc3RzIGFuZCB3YXMgYXBwbGllZCwgY3JlYXRlIGEgbmV3IG1peGluIHRvCiAgICAgICAgLy8gbWFrZSBzdXJlIHRoYXQgaXQgZ2V0cyBwcm9wZXJseSBhcHBsaWVkLiBSZXVzaW5nIHRoZSBzYW1lIG1peGluIGFmdGVyCiAgICAgICAgLy8gdGhlIGZpcnN0IGBwcm90b2AgY2FsbCB3aWxsIGNhdXNlIGl0IHRvIGdldCBza2lwcGVkLgoKICAgICAgICBpZiAocHJvdG90eXBlTWl4aW5NYXAuaGFzKHRoaXMpKSB7CiAgICAgICAgICBwcm90b3R5cGVNaXhpbk1hcC5zZXQodGhpcywgX21ldGFsLk1peGluLmNyZWF0ZSh0aGlzLlByb3RvdHlwZU1peGluKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgQXVnbWVudHMgYSBjb25zdHJ1Y3RvcidzIG93biBwcm9wZXJ0aWVzIGFuZCBmdW5jdGlvbnM6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgIGNvbnN0IE15T2JqZWN0ID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICBuYW1lOiAnYW4gb2JqZWN0JwogICAgICB9KTsKICAgICAgIE15T2JqZWN0LnJlb3BlbkNsYXNzKHsKICAgICAgICBjYW5CdWlsZDogZmFsc2UKICAgICAgfSk7CiAgICAgICBNeU9iamVjdC5jYW5CdWlsZDsgLy8gZmFsc2UKICAgICAgbyA9IE15T2JqZWN0LmNyZWF0ZSgpOwogICAgICBgYGAKICAgICAgIEluIG90aGVyIHdvcmRzLCB0aGlzIGNyZWF0ZXMgc3RhdGljIHByb3BlcnRpZXMgYW5kIGZ1bmN0aW9ucyBmb3IgdGhlIGNsYXNzLgogICAgICBUaGVzZSBhcmUgb25seSBhdmFpbGFibGUgb24gdGhlIGNsYXNzIGFuZCBub3Qgb24gYW55IGluc3RhbmNlIG9mIHRoYXQgY2xhc3MuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgIGNvbnN0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgICAgbmFtZTogJycsCiAgICAgICAgc2F5SGVsbG8oKSB7CiAgICAgICAgICBhbGVydChgSGVsbG8uIE15IG5hbWUgaXMgJHt0aGlzLmdldCgnbmFtZScpfWApOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBQZXJzb24ucmVvcGVuQ2xhc3MoewogICAgICAgIHNwZWNpZXM6ICdIb21vIHNhcGllbnMnLAogICAgICAgICBjcmVhdGVQZXJzb24obmFtZSkgewogICAgICAgICAgcmV0dXJuIFBlcnNvbi5jcmVhdGUoeyBuYW1lIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBsZXQgdG9tID0gUGVyc29uLmNyZWF0ZSh7CiAgICAgICAgbmFtZTogJ1RvbSBEYWxlJwogICAgICB9KTsKICAgICAgbGV0IHllaHVkYSA9IFBlcnNvbi5jcmVhdGVQZXJzb24oJ1llaHVkYSBLYXR6Jyk7CiAgICAgICB0b20uc2F5SGVsbG8oKTsgLy8gIkhlbGxvLiBNeSBuYW1lIGlzIFRvbSBEYWxlIgogICAgICB5ZWh1ZGEuc2F5SGVsbG8oKTsgLy8gIkhlbGxvLiBNeSBuYW1lIGlzIFllaHVkYSBLYXR6IgogICAgICBhbGVydChQZXJzb24uc3BlY2llcyk7IC8vICJIb21vIHNhcGllbnMiCiAgICAgIGBgYAogICAgICAgTm90ZSB0aGF0IGBzcGVjaWVzYCBhbmQgYGNyZWF0ZVBlcnNvbmAgYXJlICpub3QqIHZhbGlkIG9uIHRoZSBgdG9tYCBhbmQgYHllaHVkYWAKICAgICAgdmFyaWFibGVzLiBUaGV5IGFyZSBvbmx5IHZhbGlkIG9uIGBQZXJzb25gLgogICAgICAgVG8gYWRkIGZ1bmN0aW9ucyBhbmQgcHJvcGVydGllcyB0byBpbnN0YW5jZXMgb2YKICAgICAgYSBjb25zdHJ1Y3RvciBieSBleHRlbmRpbmcgdGhlIGNvbnN0cnVjdG9yJ3MgcHJvdG90eXBlCiAgICAgIHNlZSBgcmVvcGVuYAogICAgICAgQG1ldGhvZCByZW9wZW5DbGFzcwogICAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgICAgQHN0YXRpYwogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIENvcmVPYmplY3QucmVvcGVuQ2xhc3MgPSBmdW5jdGlvbiByZW9wZW5DbGFzcygpIHsKICAgICAgKDAsIF9tZXRhbC5hcHBseU1peGluKSh0aGlzLCBhcmd1bWVudHMpOwogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgQ29yZU9iamVjdC5kZXRlY3QgPSBmdW5jdGlvbiBkZXRlY3Qob2JqKSB7CiAgICAgIGlmICgnZnVuY3Rpb24nICE9PSB0eXBlb2Ygb2JqKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CgogICAgICB3aGlsZSAob2JqKSB7CiAgICAgICAgaWYgKG9iaiA9PT0gdGhpcykgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBvYmogPSBvYmouc3VwZXJjbGFzczsKICAgICAgfQoKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfTsKCiAgICBDb3JlT2JqZWN0LmRldGVjdEluc3RhbmNlID0gZnVuY3Rpb24gZGV0ZWN0SW5zdGFuY2Uob2JqKSB7CiAgICAgIHJldHVybiBvYmogaW5zdGFuY2VvZiB0aGlzOwogICAgfQogICAgLyoqCiAgICAgIEluIHNvbWUgY2FzZXMsIHlvdSBtYXkgd2FudCB0byBhbm5vdGF0ZSBjb21wdXRlZCBwcm9wZXJ0aWVzIHdpdGggYWRkaXRpb25hbAogICAgICBtZXRhZGF0YSBhYm91dCBob3cgdGhleSBmdW5jdGlvbiBvciB3aGF0IHZhbHVlcyB0aGV5IG9wZXJhdGUgb24uIEZvcgogICAgICBleGFtcGxlLCBjb21wdXRlZCBwcm9wZXJ0eSBmdW5jdGlvbnMgbWF5IGNsb3NlIG92ZXIgdmFyaWFibGVzIHRoYXQgYXJlIHRoZW4KICAgICAgbm8gbG9uZ2VyIGF2YWlsYWJsZSBmb3IgaW50cm9zcGVjdGlvbi4KICAgICAgIFlvdSBjYW4gcGFzcyBhIGhhc2ggb2YgdGhlc2UgdmFsdWVzIHRvIGEgY29tcHV0ZWQgcHJvcGVydHkgbGlrZSB0aGlzOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgcGVyc29uOiBjb21wdXRlZChmdW5jdGlvbigpIHsKICAgICAgICBsZXQgcGVyc29uSWQgPSB0aGlzLmdldCgncGVyc29uSWQnKTsKICAgICAgICByZXR1cm4gUGVyc29uLmNyZWF0ZSh7IGlkOiBwZXJzb25JZCB9KTsKICAgICAgfSkubWV0YSh7IHR5cGU6IFBlcnNvbiB9KQogICAgICBgYGAKICAgICAgIE9uY2UgeW91J3ZlIGRvbmUgdGhpcywgeW91IGNhbiByZXRyaWV2ZSB0aGUgdmFsdWVzIHNhdmVkIHRvIHRoZSBjb21wdXRlZAogICAgICBwcm9wZXJ0eSBmcm9tIHlvdXIgY2xhc3MgbGlrZSB0aGlzOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBNeUNsYXNzLm1ldGFGb3JQcm9wZXJ0eSgncGVyc29uJyk7CiAgICAgIGBgYAogICAgICAgVGhpcyB3aWxsIHJldHVybiB0aGUgb3JpZ2luYWwgaGFzaCB0aGF0IHdhcyBwYXNzZWQgdG8gYG1ldGEoKWAuCiAgICAgICBAc3RhdGljCiAgICAgIEBtZXRob2QgbWV0YUZvclByb3BlcnR5CiAgICAgIEBwYXJhbSBrZXkge1N0cmluZ30gcHJvcGVydHkgbmFtZQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBDb3JlT2JqZWN0Lm1ldGFGb3JQcm9wZXJ0eSA9IGZ1bmN0aW9uIG1ldGFGb3JQcm9wZXJ0eShrZXkpIHsKICAgICAgdmFyIHByb3RvID0gdGhpcy5wcm90bygpOyAvLyBlbnN1cmUgcHJvdG90eXBlIGlzIGluaXRpYWxpemVkCgogICAgICB2YXIgcG9zc2libGVEZXNjID0gKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKHByb3RvLCBrZXkpOwogICAgICAoZmFsc2UgJiYgIShwb3NzaWJsZURlc2MgIT09IHVuZGVmaW5lZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJtZXRhRm9yUHJvcGVydHkoKSBjb3VsZCBub3QgZmluZCBhIGNvbXB1dGVkIHByb3BlcnR5IHdpdGgga2V5ICciICsga2V5ICsgIicuIiwgcG9zc2libGVEZXNjICE9PSB1bmRlZmluZWQpKTsKICAgICAgcmV0dXJuIHBvc3NpYmxlRGVzYy5fbWV0YSB8fCB7fTsKICAgIH0KICAgIC8qKgogICAgICBJdGVyYXRlIG92ZXIgZWFjaCBjb21wdXRlZCBwcm9wZXJ0eSBmb3IgdGhlIGNsYXNzLCBwYXNzaW5nIGl0cyBuYW1lCiAgICAgIGFuZCBhbnkgYXNzb2NpYXRlZCBtZXRhZGF0YSAoc2VlIGBtZXRhRm9yUHJvcGVydHlgKSB0byB0aGUgY2FsbGJhY2suCiAgICAgICBAc3RhdGljCiAgICAgIEBtZXRob2QgZWFjaENvbXB1dGVkUHJvcGVydHkKICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sKICAgICAgQHBhcmFtIHtPYmplY3R9IGJpbmRpbmcKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgQ29yZU9iamVjdC5lYWNoQ29tcHV0ZWRQcm9wZXJ0eSA9IGZ1bmN0aW9uIGVhY2hDb21wdXRlZFByb3BlcnR5KGNhbGxiYWNrLCBiaW5kaW5nKSB7CiAgICAgIGlmIChiaW5kaW5nID09PSB2b2lkIDApIHsKICAgICAgICBiaW5kaW5nID0gdGhpczsKICAgICAgfQoKICAgICAgdGhpcy5wcm90bygpOyAvLyBlbnN1cmUgcHJvdG90eXBlIGlzIGluaXRpYWxpemVkCgogICAgICB2YXIgZW1wdHkgPSB7fTsKICAgICAgKDAsIF9tZXRhMi5tZXRhKSh0aGlzLnByb3RvdHlwZSkuZm9yRWFjaERlc2NyaXB0b3JzKGZ1bmN0aW9uIChuYW1lLCBkZXNjcmlwdG9yKSB7CiAgICAgICAgaWYgKGRlc2NyaXB0b3IuZW51bWVyYWJsZSkgewogICAgICAgICAgdmFyIF9tZXRhID0gZGVzY3JpcHRvci5fbWV0YSB8fCBlbXB0eTsKCiAgICAgICAgICBjYWxsYmFjay5jYWxsKGJpbmRpbmcsIG5hbWUsIF9tZXRhKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfTsKCiAgICBDb3JlT2JqZWN0LnByb3RvID0gZnVuY3Rpb24gcHJvdG8oKSB7CiAgICAgIHZhciBwID0gdGhpcy5wcm90b3R5cGU7CgogICAgICBpZiAoIXdhc0FwcGxpZWQuaGFzKHApKSB7CiAgICAgICAgd2FzQXBwbGllZC5hZGQocCk7CiAgICAgICAgdmFyIHBhcmVudCA9IHRoaXMuc3VwZXJjbGFzczsKCiAgICAgICAgaWYgKHBhcmVudCkgewogICAgICAgICAgcGFyZW50LnByb3RvKCk7CiAgICAgICAgfSAvLyBJZiB0aGUgcHJvdG90eXBlIG1peGluIGV4aXN0cywgYXBwbHkgaXQuIEluIHRoZSBjYXNlIG9mIG5hdGl2ZSBjbGFzc2VzLAogICAgICAgIC8vIGl0IHdpbGwgbm90IGV4aXN0ICh1bmxlc3MgdGhlIGNsYXNzIGhhcyBiZWVuIHJlb3BlbmVkKS4KCgogICAgICAgIGlmIChwcm90b3R5cGVNaXhpbk1hcC5oYXModGhpcykpIHsKICAgICAgICAgIHRoaXMuUHJvdG90eXBlTWl4aW4uYXBwbHkocCk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gcDsKICAgIH07CgogICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShDb3JlT2JqZWN0LCBbewogICAgICBrZXk6ICJpc0Rlc3Ryb3llZCIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiAoMCwgX21ldGEyLnBlZWtNZXRhKSh0aGlzKS5pc1NvdXJjZURlc3Ryb3llZCgpOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3Qgc2V0IGAiICsgdGhpcyArICIuaXNEZXN0cm95ZWRgIGRpcmVjdGx5LCBwbGVhc2UgdXNlIGAuZGVzdHJveSgpYC4iLCBmYWxzZSkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgIERlc3RydWN0aW9uIHNjaGVkdWxlZCBmbGFnLiBUaGUgYGRlc3Ryb3koKWAgbWV0aG9kIGhhcyBiZWVuIGNhbGxlZC4KICAgICAgICAgVGhlIG9iamVjdCBzdGF5cyBpbnRhY3QgdW50aWwgdGhlIGVuZCBvZiB0aGUgcnVuIGxvb3AgYXQgd2hpY2ggcG9pbnQKICAgICAgICB0aGUgYGlzRGVzdHJveWVkYCBmbGFnIGlzIHNldC4KICAgICAgICAgQHByb3BlcnR5IGlzRGVzdHJveWluZwogICAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgICAgQHB1YmxpYwogICAgICAqLwoKICAgIH0sIHsKICAgICAga2V5OiAiaXNEZXN0cm95aW5nIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuICgwLCBfbWV0YTIucGVla01ldGEpKHRoaXMpLmlzU291cmNlRGVzdHJveWluZygpOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3Qgc2V0IGAiICsgdGhpcyArICIuaXNEZXN0cm95aW5nYCBkaXJlY3RseSwgcGxlYXNlIHVzZSBgLmRlc3Ryb3koKWAuIiwgZmFsc2UpKTsKICAgICAgfQogICAgfV0sIFt7CiAgICAgIGtleTogIlByb3RvdHlwZU1peGluIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIHByb3RvdHlwZU1peGluID0gcHJvdG90eXBlTWl4aW5NYXAuZ2V0KHRoaXMpOwoKICAgICAgICBpZiAocHJvdG90eXBlTWl4aW4gPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcHJvdG90eXBlTWl4aW4gPSBfbWV0YWwuTWl4aW4uY3JlYXRlKCk7CiAgICAgICAgICBwcm90b3R5cGVNaXhpbi5vd25lckNvbnN0cnVjdG9yID0gdGhpczsKICAgICAgICAgIHByb3RvdHlwZU1peGluTWFwLnNldCh0aGlzLCBwcm90b3R5cGVNaXhpbik7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcHJvdG90eXBlTWl4aW47CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAic3VwZXJjbGFzcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBjID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHRoaXMpOwogICAgICAgIHJldHVybiBjICE9PSBGdW5jdGlvbi5wcm90b3R5cGUgPyBjIDogdW5kZWZpbmVkOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gQ29yZU9iamVjdDsKICB9KCk7CgogIENvcmVPYmplY3QudG9TdHJpbmcgPSBfbWV0YWwuY2xhc3NUb1N0cmluZzsKICAoMCwgX3V0aWxzLnNldE5hbWUpKENvcmVPYmplY3QsICdFbWJlci5Db3JlT2JqZWN0Jyk7CiAgQ29yZU9iamVjdC5pc0NsYXNzID0gdHJ1ZTsKICBDb3JlT2JqZWN0LmlzTWV0aG9kID0gZmFsc2U7CgogIGZ1bmN0aW9uIGZsYXR0ZW5Qcm9wcygpIHsKICAgIHZhciBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzID0gdGhpcy5jb25jYXRlbmF0ZWRQcm9wZXJ0aWVzLAogICAgICAgIG1lcmdlZFByb3BlcnRpZXMgPSB0aGlzLm1lcmdlZFByb3BlcnRpZXM7CiAgICB2YXIgaGFzQ29uY2F0ZW5hdGVkUHJvcHMgPSBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzICE9PSB1bmRlZmluZWQgJiYgY29uY2F0ZW5hdGVkUHJvcGVydGllcy5sZW5ndGggPiAwOwogICAgdmFyIGhhc01lcmdlZFByb3BzID0gbWVyZ2VkUHJvcGVydGllcyAhPT0gdW5kZWZpbmVkICYmIG1lcmdlZFByb3BlcnRpZXMubGVuZ3RoID4gMDsKICAgIHZhciBpbml0UHJvcGVydGllcyA9IHt9OwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBwcm9wZXJ0aWVzID0gaSA8IDAgfHwgYXJndW1lbnRzLmxlbmd0aCA8PSBpID8gdW5kZWZpbmVkIDogYXJndW1lbnRzW2ldOwogICAgICAoZmFsc2UgJiYgISghKHByb3BlcnRpZXMgaW5zdGFuY2VvZiBfbWV0YWwuTWl4aW4pKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0VtYmVyT2JqZWN0LmNyZWF0ZSBubyBsb25nZXIgc3VwcG9ydHMgbWl4aW5nIGluIG90aGVyICcgKyAnZGVmaW5pdGlvbnMsIHVzZSAuZXh0ZW5kICYgLmNyZWF0ZSBzZXBhcmF0ZWx5IGluc3RlYWQuJywgIShwcm9wZXJ0aWVzIGluc3RhbmNlb2YgX21ldGFsLk1peGluKSkpOwogICAgICB2YXIga2V5TmFtZXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKTsKCiAgICAgIGZvciAodmFyIGogPSAwLCBrID0ga2V5TmFtZXMubGVuZ3RoOyBqIDwgazsgaisrKSB7CiAgICAgICAgdmFyIGtleU5hbWUgPSBrZXlOYW1lc1tqXTsKICAgICAgICB2YXIgdmFsdWUgPSBwcm9wZXJ0aWVzW2tleU5hbWVdOwoKICAgICAgICBpZiAoaGFzQ29uY2F0ZW5hdGVkUHJvcHMgJiYgY29uY2F0ZW5hdGVkUHJvcGVydGllcy5pbmRleE9mKGtleU5hbWUpID4gLTEpIHsKICAgICAgICAgIHZhciBiYXNlVmFsdWUgPSBpbml0UHJvcGVydGllc1trZXlOYW1lXTsKCiAgICAgICAgICBpZiAoYmFzZVZhbHVlKSB7CiAgICAgICAgICAgIHZhbHVlID0gKDAsIF91dGlscy5tYWtlQXJyYXkpKGJhc2VWYWx1ZSkuY29uY2F0KHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHZhbHVlID0gKDAsIF91dGlscy5tYWtlQXJyYXkpKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmIChoYXNNZXJnZWRQcm9wcyAmJiBtZXJnZWRQcm9wZXJ0aWVzLmluZGV4T2Yoa2V5TmFtZSkgPiAtMSkgewogICAgICAgICAgdmFyIF9iYXNlVmFsdWUgPSBpbml0UHJvcGVydGllc1trZXlOYW1lXTsKICAgICAgICAgIHZhbHVlID0gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgX2Jhc2VWYWx1ZSwgdmFsdWUpOwogICAgICAgIH0KCiAgICAgICAgaW5pdFByb3BlcnRpZXNba2V5TmFtZV0gPSB2YWx1ZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBpbml0UHJvcGVydGllczsKICB9CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICAvKioKICAgICAgUHJvdmlkZXMgbG9va3VwLXRpbWUgdHlwZSB2YWxpZGF0aW9uIGZvciBpbmplY3RlZCBwcm9wZXJ0aWVzLgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBfb25Mb29rdXAKICAgICovCiAgICBDb3JlT2JqZWN0Ll9vbkxvb2t1cCA9IGZ1bmN0aW9uIGluamVjdGVkUHJvcGVydHlBc3NlcnRpb24oZGVidWdDb250YWluZXJLZXkpIHsKICAgICAgdmFyIF9kZWJ1Z0NvbnRhaW5lcktleSRzcCA9IGRlYnVnQ29udGFpbmVyS2V5LnNwbGl0KCc6JyksCiAgICAgICAgICB0eXBlID0gX2RlYnVnQ29udGFpbmVyS2V5JHNwWzBdOwoKICAgICAgdmFyIHByb3RvID0gdGhpcy5wcm90bygpOwoKICAgICAgZm9yICh2YXIga2V5IGluIHByb3RvKSB7CiAgICAgICAgdmFyIGRlc2MgPSAoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JQcm9wZXJ0eSkocHJvdG8sIGtleSk7CgogICAgICAgIGlmIChkZXNjICYmIF9tZXRhbC5ERUJVR19JTkpFQ1RJT05fRlVOQ1RJT05TLmhhcyhkZXNjLl9nZXR0ZXIpKSB7CiAgICAgICAgICAoZmFsc2UgJiYgISh0eXBlID09PSAnY29udHJvbGxlcicgfHwgX21ldGFsLkRFQlVHX0lOSkVDVElPTl9GVU5DVElPTlMuZ2V0KGRlc2MuX2dldHRlcikudHlwZSAhPT0gJ2NvbnRyb2xsZXInKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkRlZmluaW5nIGAiICsga2V5ICsgImAgYXMgYW4gaW5qZWN0ZWQgY29udHJvbGxlciBwcm9wZXJ0eSBvbiBhIG5vbi1jb250cm9sbGVyIChgIiArIGRlYnVnQ29udGFpbmVyS2V5ICsgImApIGlzIG5vdCBhbGxvd2VkLiIsIHR5cGUgPT09ICdjb250cm9sbGVyJyB8fCBfbWV0YWwuREVCVUdfSU5KRUNUSU9OX0ZVTkNUSU9OUy5nZXQoZGVzYy5fZ2V0dGVyKS50eXBlICE9PSAnY29udHJvbGxlcicpKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CiAgICAvKioKICAgICAgUmV0dXJucyBhIGhhc2ggb2YgcHJvcGVydHkgbmFtZXMgYW5kIGNvbnRhaW5lciBuYW1lcyB0aGF0IGluamVjdGVkCiAgICAgIHByb3BlcnRpZXMgd2lsbCBsb29rdXAgb24gdGhlIGNvbnRhaW5lciBsYXppbHkuCiAgICAgICBAbWV0aG9kIF9sYXp5SW5qZWN0aW9ucwogICAgICBAcmV0dXJuIHtPYmplY3R9IEhhc2ggb2YgYWxsIGxhenkgaW5qZWN0ZWQgcHJvcGVydHkga2V5cyB0byBjb250YWluZXIgbmFtZXMKICAgICAgQHByaXZhdGUKICAgICovCgoKICAgIENvcmVPYmplY3QuX2xhenlJbmplY3Rpb25zID0gZnVuY3Rpb24gKCkgewogICAgICB2YXIgaW5qZWN0aW9ucyA9IHt9OwogICAgICB2YXIgcHJvdG8gPSB0aGlzLnByb3RvKCk7CiAgICAgIHZhciBrZXk7CiAgICAgIHZhciBkZXNjOwoKICAgICAgZm9yIChrZXkgaW4gcHJvdG8pIHsKICAgICAgICBkZXNjID0gKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKHByb3RvLCBrZXkpOwoKICAgICAgICBpZiAoZGVzYyAmJiBfbWV0YWwuREVCVUdfSU5KRUNUSU9OX0ZVTkNUSU9OUy5oYXMoZGVzYy5fZ2V0dGVyKSkgewogICAgICAgICAgdmFyIF9ERUJVR19JTkpFQ1RJT05fRlVOQyA9IF9tZXRhbC5ERUJVR19JTkpFQ1RJT05fRlVOQ1RJT05TLmdldChkZXNjLl9nZXR0ZXIpLAogICAgICAgICAgICAgIG5hbWVzcGFjZSA9IF9ERUJVR19JTkpFQ1RJT05fRlVOQy5uYW1lc3BhY2UsCiAgICAgICAgICAgICAgc291cmNlID0gX0RFQlVHX0lOSkVDVElPTl9GVU5DLnNvdXJjZSwKICAgICAgICAgICAgICB0eXBlID0gX0RFQlVHX0lOSkVDVElPTl9GVU5DLnR5cGUsCiAgICAgICAgICAgICAgbmFtZSA9IF9ERUJVR19JTkpFQ1RJT05fRlVOQy5uYW1lOwoKICAgICAgICAgIGluamVjdGlvbnNba2V5XSA9IHsKICAgICAgICAgICAgbmFtZXNwYWNlOiBuYW1lc3BhY2UsCiAgICAgICAgICAgIHNvdXJjZTogc291cmNlLAogICAgICAgICAgICBzcGVjaWZpZXI6IHR5cGUgKyAiOiIgKyAobmFtZSB8fCBrZXkpCiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGluamVjdGlvbnM7CiAgICB9OwogIH0KCiAgdmFyIF9kZWZhdWx0ID0gQ29yZU9iamVjdDsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL3N5c3RlbS9uYW1lc3BhY2UiLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL29iamVjdCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfbWV0YWwsIF91dGlscywgX29iamVjdCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCiAgLy8gUHJlbG9hZGVkIGludG8gbmFtZXNwYWNlcwoKICAvKioKICAgIEEgTmFtZXNwYWNlIGlzIGFuIG9iamVjdCB1c3VhbGx5IHVzZWQgdG8gY29udGFpbiBvdGhlciBvYmplY3RzIG9yIG1ldGhvZHMKICAgIHN1Y2ggYXMgYW4gYXBwbGljYXRpb24gb3IgZnJhbWV3b3JrLiBDcmVhdGUgYSBuYW1lc3BhY2UgYW55dGltZSB5b3Ugd2FudAogICAgdG8gZGVmaW5lIG9uZSBvZiB0aGVzZSBuZXcgY29udGFpbmVycy4KICAKICAgICMgRXhhbXBsZSBVc2FnZQogIAogICAgYGBgamF2YXNjcmlwdAogICAgTXlGcmFtZXdvcmsgPSBFbWJlci5OYW1lc3BhY2UuY3JlYXRlKHsKICAgICAgVkVSU0lPTjogJzEuMC4wJwogICAgfSk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBOYW1lc3BhY2UKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEBleHRlbmRzIEVtYmVyT2JqZWN0CiAgICBAcHVibGljCiAgKi8KICB2YXIgTmFtZXNwYWNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9FbWJlck9iamVjdCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE5hbWVzcGFjZSwgX0VtYmVyT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBOYW1lc3BhY2UoKSB7CiAgICAgIHJldHVybiBfRW1iZXJPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBOYW1lc3BhY2UucHJvdG90eXBlOwoKICAgIF9wcm90by5pbml0ID0gZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgKDAsIF9tZXRhbC5hZGROYW1lc3BhY2UpKHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG8udG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgdmFyIG5hbWUgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ25hbWUnKSB8fCAoMCwgX21ldGFsLmdldCkodGhpcywgJ21vZHVsZVByZWZpeCcpOwoKICAgICAgaWYgKG5hbWUpIHsKICAgICAgICByZXR1cm4gbmFtZTsKICAgICAgfQoKICAgICAgKDAsIF9tZXRhbC5maW5kTmFtZXNwYWNlcykoKTsKICAgICAgbmFtZSA9ICgwLCBfdXRpbHMuZ2V0TmFtZSkodGhpcyk7CgogICAgICBpZiAobmFtZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgbmFtZSA9ICgwLCBfdXRpbHMuZ3VpZEZvcikodGhpcyk7CiAgICAgICAgKDAsIF91dGlscy5zZXROYW1lKSh0aGlzLCBuYW1lKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5hbWU7CiAgICB9OwoKICAgIF9wcm90by5uYW1lQ2xhc3NlcyA9IGZ1bmN0aW9uIG5hbWVDbGFzc2VzKCkgewogICAgICAoMCwgX21ldGFsLnByb2Nlc3NOYW1lc3BhY2UpKHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG8uZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgICgwLCBfbWV0YWwucmVtb3ZlTmFtZXNwYWNlKSh0aGlzKTsKCiAgICAgIF9FbWJlck9iamVjdC5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpOwogICAgfTsKCiAgICByZXR1cm4gTmFtZXNwYWNlOwogIH0oX29iamVjdC5kZWZhdWx0KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IE5hbWVzcGFjZTsKICBOYW1lc3BhY2UucHJvdG90eXBlLmlzTmFtZXNwYWNlID0gdHJ1ZTsKICBOYW1lc3BhY2UuTkFNRVNQQUNFUyA9IF9tZXRhbC5OQU1FU1BBQ0VTOwogIE5hbWVzcGFjZS5OQU1FU1BBQ0VTX0JZX0lEID0gX21ldGFsLk5BTUVTUEFDRVNfQllfSUQ7CiAgTmFtZXNwYWNlLnByb2Nlc3NBbGwgPSBfbWV0YWwucHJvY2Vzc0FsbE5hbWVzcGFjZXM7CiAgTmFtZXNwYWNlLmJ5TmFtZSA9IF9tZXRhbC5maW5kTmFtZXNwYWNlOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vb2JqZWN0IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL2NvbnRhaW5lciIsICJAZW1iZXIvLWludGVybmFscy9vd25lciIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vY29yZV9vYmplY3QiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL29ic2VydmFibGUiLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2VtYmVyQmFiZWwsIF9jb250YWluZXIsIF9vd25lciwgX3V0aWxzLCBfbWV0YWwsIF9jb3JlX29iamVjdCwgX29ic2VydmFibGUsIF9kZWJ1ZykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuRnJhbWV3b3JrT2JqZWN0ID0gX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KICB2YXIgaW5zdGFuY2VPd25lciA9IG5ldyBXZWFrTWFwKCk7CiAgLyoqCiAgICBgRW1iZXJPYmplY3RgIGlzIHRoZSBtYWluIGJhc2UgY2xhc3MgZm9yIGFsbCBFbWJlciBvYmplY3RzLiBJdCBpcyBhIHN1YmNsYXNzCiAgICBvZiBgQ29yZU9iamVjdGAgd2l0aCB0aGUgYE9ic2VydmFibGVgIG1peGluIGFwcGxpZWQuIEZvciBkZXRhaWxzLAogICAgc2VlIHRoZSBkb2N1bWVudGF0aW9uIGZvciBlYWNoIG9mIHRoZXNlLgogIAogICAgQGNsYXNzIEVtYmVyT2JqZWN0CiAgICBAZXh0ZW5kcyBDb3JlT2JqZWN0CiAgICBAdXNlcyBPYnNlcnZhYmxlCiAgICBAcHVibGljCiAgKi8KCiAgdmFyIEVtYmVyT2JqZWN0ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Db3JlT2JqZWN0KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRW1iZXJPYmplY3QsIF9Db3JlT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBFbWJlck9iamVjdCgpIHsKICAgICAgcmV0dXJuIF9Db3JlT2JqZWN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKEVtYmVyT2JqZWN0LCBbewogICAgICBrZXk6ICJfZGVidWdDb250YWluZXJLZXkiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICB2YXIgZmFjdG9yeSA9IF9jb250YWluZXIuRkFDVE9SWV9GT1IuZ2V0KHRoaXMpOwoKICAgICAgICByZXR1cm4gZmFjdG9yeSAhPT0gdW5kZWZpbmVkICYmIGZhY3RvcnkuZnVsbE5hbWU7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiBfb3duZXIuT1dORVIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBvd25lciA9IGluc3RhbmNlT3duZXIuZ2V0KHRoaXMpOwoKICAgICAgICBpZiAob3duZXIgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcmV0dXJuIG93bmVyOwogICAgICAgIH0KCiAgICAgICAgdmFyIGZhY3RvcnkgPSBfY29udGFpbmVyLkZBQ1RPUllfRk9SLmdldCh0aGlzKTsKCiAgICAgICAgcmV0dXJuIGZhY3RvcnkgIT09IHVuZGVmaW5lZCAmJiBmYWN0b3J5Lm93bmVyOwogICAgICB9IC8vIHdlIG5lZWQgYSBzZXR0ZXIgaGVyZSBsYXJnZWx5IHRvIHN1cHBvcnQKICAgICAgLy8gZm9sa3MgY2FsbGluZyBgb3duZXIub3duZXJJbmplY3Rpb24oKWAgQVBJCiAgICAgICwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQodmFsdWUpIHsKICAgICAgICBpbnN0YW5jZU93bmVyLnNldCh0aGlzLCB2YWx1ZSk7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBFbWJlck9iamVjdDsKICB9KF9jb3JlX29iamVjdC5kZWZhdWx0KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IEVtYmVyT2JqZWN0OwogICgwLCBfdXRpbHMuc2V0TmFtZSkoRW1iZXJPYmplY3QsICdFbWJlci5PYmplY3QnKTsKCiAgX29ic2VydmFibGUuZGVmYXVsdC5hcHBseShFbWJlck9iamVjdC5wcm90b3R5cGUpOwoKICB2YXIgRnJhbWV3b3JrT2JqZWN0OwogIF9leHBvcnRzLkZyYW1ld29ya09iamVjdCA9IEZyYW1ld29ya09iamVjdDsKCiAgaWYgKHRydWUKICAvKiBFTUJFUl9GUkFNRVdPUktfT0JKRUNUX09XTkVSX0FSR1VNRU5UICovCiAgKSB7CiAgICAgIF9leHBvcnRzLkZyYW1ld29ya09iamVjdCA9IEZyYW1ld29ya09iamVjdCA9CiAgICAgIC8qI19fUFVSRV9fKi8KICAgICAgZnVuY3Rpb24gKF9Db3JlT2JqZWN0MikgewogICAgICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShGcmFtZXdvcmtPYmplY3QsIF9Db3JlT2JqZWN0Mik7CiAgICAgICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShGcmFtZXdvcmtPYmplY3QsIFt7CiAgICAgICAgICBrZXk6ICJfZGVidWdDb250YWluZXJLZXkiLAogICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgICAgIHZhciBmYWN0b3J5ID0gX2NvbnRhaW5lci5GQUNUT1JZX0ZPUi5nZXQodGhpcyk7CgogICAgICAgICAgICByZXR1cm4gZmFjdG9yeSAhPT0gdW5kZWZpbmVkICYmIGZhY3RvcnkuZnVsbE5hbWU7CiAgICAgICAgICB9CiAgICAgICAgfV0pOwoKICAgICAgICBmdW5jdGlvbiBGcmFtZXdvcmtPYmplY3Qob3duZXIpIHsKICAgICAgICAgIHZhciBfdGhpczsKCiAgICAgICAgICBfdGhpcyA9IF9Db3JlT2JqZWN0Mi5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgICAgICAoMCwgX293bmVyLnNldE93bmVyKSgoMCwgX2VtYmVyQmFiZWwuYXNzZXJ0VGhpc0luaXRpYWxpemVkKShfdGhpcyksIG93bmVyKTsKICAgICAgICAgIHJldHVybiBfdGhpczsKICAgICAgICB9CgogICAgICAgIHJldHVybiBGcmFtZXdvcmtPYmplY3Q7CiAgICAgIH0oX2NvcmVfb2JqZWN0LmRlZmF1bHQpOwoKICAgICAgX29ic2VydmFibGUuZGVmYXVsdC5hcHBseShGcmFtZXdvcmtPYmplY3QucHJvdG90eXBlKTsKICAgIH0gZWxzZSB7CiAgICBfZXhwb3J0cy5GcmFtZXdvcmtPYmplY3QgPSBGcmFtZXdvcmtPYmplY3QgPQogICAgLyojX19QVVJFX18qLwogICAgZnVuY3Rpb24gKF9FbWJlck9iamVjdCkgewogICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRnJhbWV3b3JrT2JqZWN0LCBfRW1iZXJPYmplY3QpOwoKICAgICAgZnVuY3Rpb24gRnJhbWV3b3JrT2JqZWN0KCkgewogICAgICAgIHJldHVybiBfRW1iZXJPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICB9CgogICAgICByZXR1cm4gRnJhbWV3b3JrT2JqZWN0OwogICAgfShFbWJlck9iamVjdCk7CiAgfQoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgdmFyIElOSVRfV0FTX0NBTExFRCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnSU5JVF9XQVNfQ0FMTEVEJyk7CiAgICB2YXIgQVNTRVJUX0lOSVRfV0FTX0NBTExFRCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnQVNTRVJUX0lOSVRfV0FTX0NBTExFRCcpOwoKICAgIF9leHBvcnRzLkZyYW1ld29ya09iamVjdCA9IEZyYW1ld29ya09iamVjdCA9CiAgICAvKiNfX1BVUkVfXyovCiAgICBmdW5jdGlvbiAoX0VtYmVyT2JqZWN0MikgewogICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRGVidWdGcmFtZXdvcmtPYmplY3QsIF9FbWJlck9iamVjdDIpOwoKICAgICAgZnVuY3Rpb24gRGVidWdGcmFtZXdvcmtPYmplY3QoKSB7CiAgICAgICAgcmV0dXJuIF9FbWJlck9iamVjdDIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICB9CgogICAgICB2YXIgX3Byb3RvID0gRGVidWdGcmFtZXdvcmtPYmplY3QucHJvdG90eXBlOwoKICAgICAgX3Byb3RvLmluaXQgPSBmdW5jdGlvbiBpbml0KCkgewogICAgICAgIF9FbWJlck9iamVjdDIucHJvdG90eXBlLmluaXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgICAgdGhpc1tJTklUX1dBU19DQUxMRURdID0gdHJ1ZTsKICAgICAgfTsKCiAgICAgIF9wcm90b1tBU1NFUlRfSU5JVF9XQVNfQ0FMTEVEXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAoZmFsc2UgJiYgISh0aGlzW0lOSVRfV0FTX0NBTExFRF0pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IG11c3QgY2FsbCBgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTtgIHdoZW4gb3ZlcnJpZGluZyBgaW5pdGAgb24gYSBmcmFtZXdvcmsgb2JqZWN0LiBQbGVhc2UgdXBkYXRlICIgKyB0aGlzICsgIiB0byBjYWxsIGB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpO2AgZnJvbSBgaW5pdGAuIiwgdGhpc1tJTklUX1dBU19DQUxMRURdKSk7CiAgICAgIH07CgogICAgICByZXR1cm4gRGVidWdGcmFtZXdvcmtPYmplY3Q7CiAgICB9KEVtYmVyT2JqZWN0KTsKCiAgICAoMCwgX21ldGFsLmFkZExpc3RlbmVyKShGcmFtZXdvcmtPYmplY3QucHJvdG90eXBlLCAnaW5pdCcsIG51bGwsIEFTU0VSVF9JTklUX1dBU19DQUxMRUQpOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL29iamVjdF9wcm94eSIsIFsiZXhwb3J0cyIsICJlbWJlci1iYWJlbCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vb2JqZWN0IiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy8tcHJveHkiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX29iamVjdCwgX3Byb3h5KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgIGBPYmplY3RQcm94eWAgZm9yd2FyZHMgYWxsIHByb3BlcnRpZXMgbm90IGRlZmluZWQgYnkgdGhlIHByb3h5IGl0c2VsZgogICAgdG8gYSBwcm94aWVkIGBjb250ZW50YCBvYmplY3QuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgT2JqZWN0UHJveHkgZnJvbSAnQGVtYmVyL29iamVjdC9wcm94eSc7CiAgCiAgICBvYmplY3QgPSBFbWJlck9iamVjdC5jcmVhdGUoewogICAgICBuYW1lOiAnRm9vJwogICAgfSk7CiAgCiAgICBwcm94eSA9IE9iamVjdFByb3h5LmNyZWF0ZSh7CiAgICAgIGNvbnRlbnQ6IG9iamVjdAogICAgfSk7CiAgCiAgICAvLyBBY2Nlc3MgYW5kIGNoYW5nZSBleGlzdGluZyBwcm9wZXJ0aWVzCiAgICBwcm94eS5nZXQoJ25hbWUnKSAgICAgICAgICAvLyAnRm9vJwogICAgcHJveHkuc2V0KCduYW1lJywgJ0JhcicpOwogICAgb2JqZWN0LmdldCgnbmFtZScpICAgICAgICAgLy8gJ0JhcicKICAKICAgIC8vIENyZWF0ZSBuZXcgJ2Rlc2NyaXB0aW9uJyBwcm9wZXJ0eSBvbiBgb2JqZWN0YAogICAgcHJveHkuc2V0KCdkZXNjcmlwdGlvbicsICdGb28gaXMgYSB3aGl6Ym9vIGJheicpOwogICAgb2JqZWN0LmdldCgnZGVzY3JpcHRpb24nKSAgLy8gJ0ZvbyBpcyBhIHdoaXpib28gYmF6JwogICAgYGBgCiAgCiAgICBXaGlsZSBgY29udGVudGAgaXMgdW5zZXQsIHNldHRpbmcgYSBwcm9wZXJ0eSB0byBiZSBkZWxlZ2F0ZWQgd2lsbCB0aHJvdyBhbgogICAgRXJyb3IuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgT2JqZWN0UHJveHkgZnJvbSAnQGVtYmVyL29iamVjdC9wcm94eSc7CiAgCiAgICBwcm94eSA9IE9iamVjdFByb3h5LmNyZWF0ZSh7CiAgICAgIGNvbnRlbnQ6IG51bGwsCiAgICAgIGZsYWc6IG51bGwKICAgIH0pOwogICAgcHJveHkuc2V0KCdmbGFnJywgdHJ1ZSk7CiAgICBwcm94eS5nZXQoJ2ZsYWcnKTsgICAgICAgICAvLyB0cnVlCiAgICBwcm94eS5nZXQoJ2ZvbycpOyAgICAgICAgICAvLyB1bmRlZmluZWQKICAgIHByb3h5LnNldCgnZm9vJywgJ2RhdGEnKTsgIC8vIHRocm93cyBFcnJvcgogICAgYGBgCiAgCiAgICBEZWxlZ2F0ZWQgcHJvcGVydGllcyBjYW4gYmUgYm91bmQgdG8gYW5kIHdpbGwgY2hhbmdlIHdoZW4gY29udGVudCBpcyB1cGRhdGVkLgogIAogICAgQ29tcHV0ZWQgcHJvcGVydGllcyBvbiB0aGUgcHJveHkgaXRzZWxmIGNhbiBkZXBlbmQgb24gZGVsZWdhdGVkIHByb3BlcnRpZXMuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IE9iamVjdFByb3h5IGZyb20gJ0BlbWJlci9vYmplY3QvcHJveHknOwogIAogICAgUHJveHlXaXRoQ29tcHV0ZWRQcm9wZXJ0eSA9IE9iamVjdFByb3h5LmV4dGVuZCh7CiAgICAgIGZ1bGxOYW1lOiBjb21wdXRlZCgnZmlyc3ROYW1lJywgJ2xhc3ROYW1lJywgZnVuY3Rpb24oKSB7CiAgICAgICAgdmFyIGZpcnN0TmFtZSA9IHRoaXMuZ2V0KCdmaXJzdE5hbWUnKSwKICAgICAgICAgICAgbGFzdE5hbWUgPSB0aGlzLmdldCgnbGFzdE5hbWUnKTsKICAgICAgICBpZiAoZmlyc3ROYW1lICYmIGxhc3ROYW1lKSB7CiAgICAgICAgICByZXR1cm4gZmlyc3ROYW1lICsgJyAnICsgbGFzdE5hbWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmaXJzdE5hbWUgfHwgbGFzdE5hbWU7CiAgICAgIH0pCiAgICB9KTsKICAKICAgIHByb3h5ID0gUHJveHlXaXRoQ29tcHV0ZWRQcm9wZXJ0eS5jcmVhdGUoKTsKICAKICAgIHByb3h5LmdldCgnZnVsbE5hbWUnKTsgIC8vIHVuZGVmaW5lZAogICAgcHJveHkuc2V0KCdjb250ZW50JywgewogICAgICBmaXJzdE5hbWU6ICdUb20nLCBsYXN0TmFtZTogJ0RhbGUnCiAgICB9KTsgLy8gdHJpZ2dlcnMgcHJvcGVydHkgY2hhbmdlIGZvciBmdWxsTmFtZSBvbiBwcm94eQogIAogICAgcHJveHkuZ2V0KCdmdWxsTmFtZScpOyAgLy8gJ1RvbSBEYWxlJwogICAgYGBgCiAgCiAgICBAY2xhc3MgT2JqZWN0UHJveHkKICAgIEBleHRlbmRzIEVtYmVyT2JqZWN0CiAgICBAdXNlcyBFbWJlci5Qcm94eU1peGluCiAgICBAcHVibGljCiAgKi8KICB2YXIgT2JqZWN0UHJveHkgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0ZyYW1ld29ya09iamVjdCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE9iamVjdFByb3h5LCBfRnJhbWV3b3JrT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBPYmplY3RQcm94eSgpIHsKICAgICAgcmV0dXJuIF9GcmFtZXdvcmtPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHJldHVybiBPYmplY3RQcm94eTsKICB9KF9vYmplY3QuZGVmYXVsdCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBPYmplY3RQcm94eTsKICBPYmplY3RQcm94eS5Qcm90b3R5cGVNaXhpbi5yZW9wZW4oX3Byb3h5LmRlZmF1bHQpOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi90eXBlLW9mIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL3N5c3RlbS9jb3JlX29iamVjdCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9jb3JlX29iamVjdCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMudHlwZU9mID0gdHlwZU9mOwogIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KICAvLyBUWVBJTkcgJiBBUlJBWSBNRVNTQUdJTkcKICAvLwogIHZhciBUWVBFX01BUCA9IHsKICAgICdbb2JqZWN0IEJvb2xlYW5dJzogJ2Jvb2xlYW4nLAogICAgJ1tvYmplY3QgTnVtYmVyXSc6ICdudW1iZXInLAogICAgJ1tvYmplY3QgU3RyaW5nXSc6ICdzdHJpbmcnLAogICAgJ1tvYmplY3QgRnVuY3Rpb25dJzogJ2Z1bmN0aW9uJywKICAgICdbb2JqZWN0IEFycmF5XSc6ICdhcnJheScsCiAgICAnW29iamVjdCBEYXRlXSc6ICdkYXRlJywKICAgICdbb2JqZWN0IFJlZ0V4cF0nOiAncmVnZXhwJywKICAgICdbb2JqZWN0IE9iamVjdF0nOiAnb2JqZWN0JywKICAgICdbb2JqZWN0IEZpbGVMaXN0XSc6ICdmaWxlbGlzdCcKICB9OwogIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7CiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL3V0aWxzCiAgKi8KCiAgLyoqCiAgICBSZXR1cm5zIGEgY29uc2lzdGVudCB0eXBlIGZvciB0aGUgcGFzc2VkIG9iamVjdC4KICAKICAgIFVzZSB0aGlzIGluc3RlYWQgb2YgdGhlIGJ1aWx0LWluIGB0eXBlb2ZgIHRvIGdldCB0aGUgdHlwZSBvZiBhbiBpdGVtLgogICAgSXQgd2lsbCByZXR1cm4gdGhlIHNhbWUgcmVzdWx0IGFjcm9zcyBhbGwgYnJvd3NlcnMgYW5kIGluY2x1ZGVzIGEgYml0CiAgICBtb3JlIGRldGFpbC4gSGVyZSBpcyB3aGF0IHdpbGwgYmUgcmV0dXJuZWQ6CiAgCiAgICAgICAgfCBSZXR1cm4gVmFsdWUgIHwgTWVhbmluZyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfC0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18CiAgICAgICAgfCAnc3RyaW5nJyAgICAgIHwgU3RyaW5nIHByaW1pdGl2ZSBvciBTdHJpbmcgb2JqZWN0LiAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnbnVtYmVyJyAgICAgIHwgTnVtYmVyIHByaW1pdGl2ZSBvciBOdW1iZXIgb2JqZWN0LiAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnYm9vbGVhbicgICAgIHwgQm9vbGVhbiBwcmltaXRpdmUgb3IgQm9vbGVhbiBvYmplY3QuICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnbnVsbCcgICAgICAgIHwgTnVsbCB2YWx1ZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAndW5kZWZpbmVkJyAgIHwgVW5kZWZpbmVkIHZhbHVlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnZnVuY3Rpb24nICAgIHwgQSBmdW5jdGlvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnYXJyYXknICAgICAgIHwgQW4gaW5zdGFuY2Ugb2YgQXJyYXkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAncmVnZXhwJyAgICAgIHwgQW4gaW5zdGFuY2Ugb2YgUmVnRXhwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnZGF0ZScgICAgICAgIHwgQW4gaW5zdGFuY2Ugb2YgRGF0ZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnZmlsZWxpc3QnICAgIHwgQW4gaW5zdGFuY2Ugb2YgRmlsZUxpc3QgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnY2xhc3MnICAgICAgIHwgQW4gRW1iZXIgY2xhc3MgKGNyZWF0ZWQgdXNpbmcgRW1iZXJPYmplY3QuZXh0ZW5kKCkpICB8CiAgICAgICAgfCAnaW5zdGFuY2UnICAgIHwgQW4gRW1iZXIgb2JqZWN0IGluc3RhbmNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnZXJyb3InICAgICAgIHwgQW4gaW5zdGFuY2Ugb2YgdGhlIEVycm9yIG9iamVjdCAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnb2JqZWN0JyAgICAgIHwgQSBKYXZhU2NyaXB0IG9iamVjdCBub3QgaW5oZXJpdGluZyBmcm9tIEVtYmVyT2JqZWN0ICB8CiAgCiAgICBFeGFtcGxlczoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IEEgfSBmcm9tICdAZW1iZXIvYXJyYXknOwogICAgaW1wb3J0IHsgdHlwZU9mIH0gZnJvbSAnQGVtYmVyL3V0aWxzJzsKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIHR5cGVPZigpOyAgICAgICAgICAgICAgICAgICAgICAgLy8gJ3VuZGVmaW5lZCcKICAgIHR5cGVPZihudWxsKTsgICAgICAgICAgICAgICAgICAgLy8gJ251bGwnCiAgICB0eXBlT2YodW5kZWZpbmVkKTsgICAgICAgICAgICAgIC8vICd1bmRlZmluZWQnCiAgICB0eXBlT2YoJ21pY2hhZWwnKTsgICAgICAgICAgICAgIC8vICdzdHJpbmcnCiAgICB0eXBlT2YobmV3IFN0cmluZygnbWljaGFlbCcpKTsgIC8vICdzdHJpbmcnCiAgICB0eXBlT2YoMTAxKTsgICAgICAgICAgICAgICAgICAgIC8vICdudW1iZXInCiAgICB0eXBlT2YobmV3IE51bWJlcigxMDEpKTsgICAgICAgIC8vICdudW1iZXInCiAgICB0eXBlT2YodHJ1ZSk7ICAgICAgICAgICAgICAgICAgIC8vICdib29sZWFuJwogICAgdHlwZU9mKG5ldyBCb29sZWFuKHRydWUpKTsgICAgICAvLyAnYm9vbGVhbicKICAgIHR5cGVPZihBKTsgICAgICAgICAgICAgICAgICAgICAgLy8gJ2Z1bmN0aW9uJwogICAgdHlwZU9mKFsxLCAyLCA5MF0pOyAgICAgICAgICAgICAvLyAnYXJyYXknCiAgICB0eXBlT2YoL2FiYy8pOyAgICAgICAgICAgICAgICAgIC8vICdyZWdleHAnCiAgICB0eXBlT2YobmV3IERhdGUoKSk7ICAgICAgICAgICAgIC8vICdkYXRlJwogICAgdHlwZU9mKGV2ZW50LnRhcmdldC5maWxlcyk7ICAgICAvLyAnZmlsZWxpc3QnCiAgICB0eXBlT2YoRW1iZXJPYmplY3QuZXh0ZW5kKCkpOyAgIC8vICdjbGFzcycKICAgIHR5cGVPZihFbWJlck9iamVjdC5jcmVhdGUoKSk7ICAgLy8gJ2luc3RhbmNlJwogICAgdHlwZU9mKG5ldyBFcnJvcigndGVhbW9jaWwnKSk7ICAvLyAnZXJyb3InCiAgCiAgICAvLyAnbm9ybWFsJyBKYXZhU2NyaXB0IG9iamVjdAogICAgdHlwZU9mKHsgYTogJ2InIH0pOyAgICAgICAgICAgICAvLyAnb2JqZWN0JwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHR5cGVPZgogICAgQGZvciBAZW1iZXIvdXRpbHMKICAgIEBwYXJhbSB7T2JqZWN0fSBpdGVtIHRoZSBpdGVtIHRvIGNoZWNrCiAgICBAcmV0dXJuIHtTdHJpbmd9IHRoZSB0eXBlCiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgKi8KCiAgZnVuY3Rpb24gdHlwZU9mKGl0ZW0pIHsKICAgIGlmIChpdGVtID09PSBudWxsKSB7CiAgICAgIHJldHVybiAnbnVsbCc7CiAgICB9CgogICAgaWYgKGl0ZW0gPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gJ3VuZGVmaW5lZCc7CiAgICB9CgogICAgdmFyIHJldCA9IFRZUEVfTUFQW3RvU3RyaW5nLmNhbGwoaXRlbSldIHx8ICdvYmplY3QnOwoKICAgIGlmIChyZXQgPT09ICdmdW5jdGlvbicpIHsKICAgICAgaWYgKF9jb3JlX29iamVjdC5kZWZhdWx0LmRldGVjdChpdGVtKSkgewogICAgICAgIHJldCA9ICdjbGFzcyc7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAocmV0ID09PSAnb2JqZWN0JykgewogICAgICBpZiAoaXRlbSBpbnN0YW5jZW9mIEVycm9yKSB7CiAgICAgICAgcmV0ID0gJ2Vycm9yJzsKICAgICAgfSBlbHNlIGlmIChpdGVtIGluc3RhbmNlb2YgX2NvcmVfb2JqZWN0LmRlZmF1bHQpIHsKICAgICAgICByZXQgPSAnaW5zdGFuY2UnOwogICAgICB9IGVsc2UgaWYgKGl0ZW0gaW5zdGFuY2VvZiBEYXRlKSB7CiAgICAgICAgcmV0ID0gJ2RhdGUnOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJldDsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzL2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3BvbHlmaWxscywgX2RlYnVnKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5zeW1ib2wgPSBzeW1ib2w7CiAgX2V4cG9ydHMuaXNJbnRlcm5hbFN5bWJvbCA9IGlzSW50ZXJuYWxTeW1ib2w7CiAgX2V4cG9ydHMuZGljdGlvbmFyeSA9IG1ha2VEaWN0aW9uYXJ5OwogIF9leHBvcnRzLnV1aWQgPSB1dWlkOwogIF9leHBvcnRzLmdlbmVyYXRlR3VpZCA9IGdlbmVyYXRlR3VpZDsKICBfZXhwb3J0cy5ndWlkRm9yID0gZ3VpZEZvcjsKICBfZXhwb3J0cy5pbnRlcm4gPSBpbnRlcm47CiAgX2V4cG9ydHMud3JhcCA9IHdyYXA7CiAgX2V4cG9ydHMuZ2V0T2JzZXJ2ZXJzID0gZ2V0T2JzZXJ2ZXJzOwogIF9leHBvcnRzLmdldExpc3RlbmVycyA9IGdldExpc3RlbmVyczsKICBfZXhwb3J0cy5zZXRPYnNlcnZlcnMgPSBzZXRPYnNlcnZlcnM7CiAgX2V4cG9ydHMuc2V0TGlzdGVuZXJzID0gc2V0TGlzdGVuZXJzOwogIF9leHBvcnRzLmluc3BlY3QgPSBpbnNwZWN0OwogIF9leHBvcnRzLmxvb2t1cERlc2NyaXB0b3IgPSBsb29rdXBEZXNjcmlwdG9yOwogIF9leHBvcnRzLmNhbkludm9rZSA9IGNhbkludm9rZTsKICBfZXhwb3J0cy50cnlJbnZva2UgPSB0cnlJbnZva2U7CiAgX2V4cG9ydHMubWFrZUFycmF5ID0gbWFrZUFycmF5OwogIF9leHBvcnRzLmdldE5hbWUgPSBnZXROYW1lOwogIF9leHBvcnRzLnNldE5hbWUgPSBzZXROYW1lOwogIF9leHBvcnRzLnRvU3RyaW5nID0gdG9TdHJpbmc7CiAgX2V4cG9ydHMuaXNQcm94eSA9IGlzUHJveHk7CiAgX2V4cG9ydHMuc2V0UHJveHkgPSBzZXRQcm94eTsKICBfZXhwb3J0cy5pc0VtYmVyQXJyYXkgPSBpc0VtYmVyQXJyYXk7CiAgX2V4cG9ydHMuc2V0V2l0aE1hbmRhdG9yeVNldHRlciA9IF9leHBvcnRzLnRlYXJkb3duTWFuZGF0b3J5U2V0dGVyID0gX2V4cG9ydHMuc2V0dXBNYW5kYXRvcnlTZXR0ZXIgPSBfZXhwb3J0cy5FTUJFUl9BUlJBWSA9IF9leHBvcnRzLkNhY2hlID0gX2V4cG9ydHMuSEFTX05BVElWRV9QUk9YWSA9IF9leHBvcnRzLkhBU19OQVRJVkVfU1lNQk9MID0gX2V4cG9ydHMuUk9PVCA9IF9leHBvcnRzLmNoZWNrSGFzU3VwZXIgPSBfZXhwb3J0cy5HVUlEX0tFWSA9IF9leHBvcnRzLmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMgPSB2b2lkIDA7CgogIC8qKgogICAgU3Ryb25nbHkgaGludCBydW50aW1lcyB0byBpbnRlcm4gdGhlIHByb3ZpZGVkIHN0cmluZy4KICAKICAgIFdoZW4gZG8gSSBuZWVkIHRvIHVzZSB0aGlzIGZ1bmN0aW9uPwogIAogICAgRm9yIHRoZSBtb3N0IHBhcnQsIG5ldmVyLiBQcmUtbWF0dXJlIG9wdGltaXphdGlvbiBpcyBiYWQsIGFuZCBvZnRlbiB0aGUKICAgIHJ1bnRpbWUgZG9lcyBleGFjdGx5IHdoYXQgeW91IG5lZWQgaXQgdG8sIGFuZCBtb3JlIG9mdGVuIHRoZSB0cmFkZS1vZmYgaXNuJ3QKICAgIHdvcnRoIGl0LgogIAogICAgV2h5PwogIAogICAgUnVudGltZXMgc3RvcmUgc3RyaW5ncyBpbiBhdCBsZWFzdCAyIGRpZmZlcmVudCByZXByZXNlbnRhdGlvbnM6CiAgICBSb3BlcyBhbmQgU3ltYm9scyAoaW50ZXJuZWQgc3RyaW5ncykuIFRoZSBSb3BlIHByb3ZpZGVzIGEgbWVtb3J5IGVmZmljaWVudAogICAgZGF0YS1zdHJ1Y3R1cmUgZm9yIHN0cmluZ3MgY3JlYXRlZCBmcm9tIGNvbmNhdGVuYXRpb24gb3Igc29tZSBvdGhlciBzdHJpbmcKICAgIG1hbmlwdWxhdGlvbiBsaWtlIHNwbGl0dGluZy4KICAKICAgIFVuZm9ydHVuYXRlbHkgY2hlY2tpbmcgZXF1YWxpdHkgb2YgZGlmZmVyZW50IHJvcGVzIGNhbiBiZSBxdWl0ZSBjb3N0bHkgYXMKICAgIHJ1bnRpbWVzIG11c3QgcmVzb3J0IHRvIGNsZXZlciBzdHJpbmcgY29tcGFyaXNvbiBhbGdvcml0aG1zLiBUaGVzZQogICAgYWxnb3JpdGhtcyB0eXBpY2FsbHkgY29zdCBpbiBwcm9wb3J0aW9uIHRvIHRoZSBsZW5ndGggb2YgdGhlIHN0cmluZy4KICAgIEx1Y2tpbHksIHRoaXMgaXMgd2hlcmUgdGhlIFN5bWJvbHMgKGludGVybmVkIHN0cmluZ3MpIHNoaW5lLiBBcyBTeW1ib2xzIGFyZQogICAgdW5pcXVlIGJ5IHRoZWlyIHN0cmluZyBjb250ZW50LCBlcXVhbGl0eSBjaGVja3MgY2FuIGJlIGRvbmUgYnkgcG9pbnRlcgogICAgY29tcGFyaXNvbi4KICAKICAgIEhvdyBkbyBJIGtub3cgaWYgbXkgc3RyaW5nIGlzIGEgcm9wZSBvciBzeW1ib2w/CiAgCiAgICBUeXBpY2FsbHkgKHdhcm5pbmcgZ2VuZXJhbCBzd2VlcGluZyBzdGF0ZW1lbnQsIGJ1dCB0cnV0aHkgaW4gcnVudGltZXMgYXQKICAgIHByZXNlbnQpIHN0YXRpYyBzdHJpbmdzIGNyZWF0ZWQgYXMgcGFydCBvZiB0aGUgSlMgc291cmNlIGFyZSBpbnRlcm5lZC4KICAgIFN0cmluZ3Mgb2Z0ZW4gdXNlZCBmb3IgY29tcGFyaXNvbnMgY2FuIGJlIGludGVybmVkIGF0IHJ1bnRpbWUgaWYgc29tZQogICAgY3JpdGVyaWEgYXJlIG1ldC4gIE9uZSBvZiB0aGVzZSBjcml0ZXJpYSBjYW4gYmUgdGhlIHNpemUgb2YgdGhlIGVudGlyZSByb3BlLgogICAgRm9yIGV4YW1wbGUsIGluIGNocm9tZSAzOCBhIHJvcGUgbG9uZ2VyIHRoZW4gMTIgY2hhcmFjdGVycyB3aWxsIG5vdAogICAgaW50ZXJuLCBub3Igd2lsbCBzZWdtZW50cyBvZiB0aGF0IHJvcGUuCiAgCiAgICBTb21lIG51bWJlcnM6IGh0dHA6Ly9qc3BlcmYuY29tL2V2YWwtdnMta2V5cy84CiAgCiAgICBLbm93biBUcmlja+KEogogIAogICAgQHByaXZhdGUKICAgIEByZXR1cm4ge1N0cmluZ30gaW50ZXJuZWQgdmVyc2lvbiBvZiB0aGUgcHJvdmlkZWQgc3RyaW5nCiAgKi8KICBmdW5jdGlvbiBpbnRlcm4oc3RyKSB7CiAgICB2YXIgb2JqID0ge307CiAgICBvYmpbc3RyXSA9IDE7CgogICAgZm9yICh2YXIga2V5IGluIG9iaikgewogICAgICBpZiAoa2V5ID09PSBzdHIpIHsKICAgICAgICByZXR1cm4ga2V5OwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHN0cjsKICB9CiAgLyoqCiAgICBSZXR1cm5zIHdoZXRoZXIgVHlwZSh2YWx1ZSkgaXMgT2JqZWN0LgogIAogICAgVXNlZnVsIGZvciBjaGVja2luZyB3aGV0aGVyIGEgdmFsdWUgaXMgYSB2YWxpZCBXZWFrTWFwIGtleS4KICAKICAgIFJlZnM6IGh0dHBzOi8vdGMzOS5naXRodWIuaW8vZWNtYTI2Mi8jc2VjLXR5cGVvZi1vcGVyYXRvci1ydW50aW1lLXNlbWFudGljcy1ldmFsdWF0aW9uCiAgICAgICAgICBodHRwczovL3RjMzkuZ2l0aHViLmlvL2VjbWEyNjIvI3NlYy13ZWFrbWFwLnByb3RvdHlwZS5zZXQKICAKICAgIEBwcml2YXRlCiAgICBAZnVuY3Rpb24gaXNPYmplY3QKICAqLwoKCiAgZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHsKICAgIHJldHVybiB2YWx1ZSAhPT0gbnVsbCAmJiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyB8fCB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpOwogIH0KICAvKioKICAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KCiAgLyoqCiAgIFByZXZpb3VzbHkgd2UgdXNlZCBgRW1iZXIuJC51dWlkYCwgaG93ZXZlciBgJC51dWlkYCBoYXMgYmVlbiByZW1vdmVkIGZyb20KICAgalF1ZXJ5IG1hc3Rlci4gV2UnbGwganVzdCBib290c3RyYXAgb3VyIG93biB1dWlkIG5vdy4KICAKICAgQHByaXZhdGUKICAgQHJldHVybiB7TnVtYmVyfSB0aGUgdXVpZAogICAqLwoKCiAgdmFyIF91dWlkID0gMDsKICAvKioKICAgR2VuZXJhdGVzIGEgdW5pdmVyc2FsbHkgdW5pcXVlIGlkZW50aWZpZXIuIFRoaXMgbWV0aG9kCiAgIGlzIHVzZWQgaW50ZXJuYWxseSBieSBFbWJlciBmb3IgYXNzaXN0aW5nIHdpdGgKICAgdGhlIGdlbmVyYXRpb24gb2YgR1VJRCdzIGFuZCBvdGhlciB1bmlxdWUgaWRlbnRpZmllcnMuCiAgCiAgIEBwdWJsaWMKICAgQHJldHVybiB7TnVtYmVyfSBbZGVzY3JpcHRpb25dCiAgICovCgogIGZ1bmN0aW9uIHV1aWQoKSB7CiAgICByZXR1cm4gKytfdXVpZDsKICB9CiAgLyoqCiAgIFByZWZpeCB1c2VkIGZvciBndWlkcyB0aHJvdWdoIG91dCBFbWJlci4KICAgQHByaXZhdGUKICAgQHByb3BlcnR5IEdVSURfUFJFRklYCiAgIEBmb3IgRW1iZXIKICAgQHR5cGUgU3RyaW5nCiAgIEBmaW5hbAogICAqLwoKCiAgdmFyIEdVSURfUFJFRklYID0gJ2VtYmVyJzsgLy8gVXNlZCBmb3IgZ3VpZCBnZW5lcmF0aW9uLi4uCgogIHZhciBPQkpFQ1RfR1VJRFMgPSBuZXcgV2Vha01hcCgpOwogIHZhciBOT05fT0JKRUNUX0dVSURTID0gbmV3IE1hcCgpOwogIC8qKgogICAgQSB1bmlxdWUga2V5IHVzZWQgdG8gYXNzaWduIGd1aWRzIGFuZCBvdGhlciBwcml2YXRlIG1ldGFkYXRhIHRvIG9iamVjdHMuCiAgICBJZiB5b3UgaW5zcGVjdCBhbiBvYmplY3QgaW4geW91ciBicm93c2VyIGRlYnVnZ2VyIHlvdSB3aWxsIG9mdGVuIHNlZSB0aGVzZS4KICAgIFRoZXkgY2FuIGJlIHNhZmVseSBpZ25vcmVkLgogIAogICAgT24gYnJvd3NlcnMgdGhhdCBzdXBwb3J0IGl0LCB0aGVzZSBwcm9wZXJ0aWVzIGFyZSBhZGRlZCB3aXRoIGVudW1lcmF0aW9uCiAgICBkaXNhYmxlZCBzbyB0aGV5IHdvbid0IHNob3cgdXAgd2hlbiB5b3UgaXRlcmF0ZSBvdmVyIHlvdXIgcHJvcGVydGllcy4KICAKICAgIEBwcml2YXRlCiAgICBAcHJvcGVydHkgR1VJRF9LRVkKICAgIEBmb3IgRW1iZXIKICAgIEB0eXBlIFN0cmluZwogICAgQGZpbmFsCiAgKi8KCiAgdmFyIEdVSURfS0VZID0gaW50ZXJuKCJfX2VtYmVyIiArIERhdGUubm93KCkpOwogIC8qKgogICAgR2VuZXJhdGVzIGEgbmV3IGd1aWQsIG9wdGlvbmFsbHkgc2F2aW5nIHRoZSBndWlkIHRvIHRoZSBvYmplY3QgdGhhdCB5b3UKICAgIHBhc3MgaW4uIFlvdSB3aWxsIHJhcmVseSBuZWVkIHRvIHVzZSB0aGlzIG1ldGhvZC4gSW5zdGVhZCB5b3Ugc2hvdWxkCiAgICBjYWxsIGBndWlkRm9yKG9iailgLCB3aGljaCByZXR1cm4gYW4gZXhpc3RpbmcgZ3VpZCBpZiBhdmFpbGFibGUuCiAgCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCBnZW5lcmF0ZUd1aWQKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9pbnRlcm5hbHMKICAgIEBwYXJhbSB7T2JqZWN0fSBbb2JqXSBPYmplY3QgdGhlIGd1aWQgd2lsbCBiZSB1c2VkIGZvci4gSWYgcGFzc2VkIGluLCB0aGUgZ3VpZCB3aWxsCiAgICAgIGJlIHNhdmVkIG9uIHRoZSBvYmplY3QgYW5kIHJldXNlZCB3aGVuZXZlciB5b3UgcGFzcyB0aGUgc2FtZSBvYmplY3QKICAgICAgYWdhaW4uCiAgCiAgICAgIElmIG5vIG9iamVjdCBpcyBwYXNzZWQsIGp1c3QgZ2VuZXJhdGUgYSBuZXcgZ3VpZC4KICAgIEBwYXJhbSB7U3RyaW5nfSBbcHJlZml4XSBQcmVmaXggdG8gcGxhY2UgaW4gZnJvbnQgb2YgdGhlIGd1aWQuIFVzZWZ1bCB3aGVuIHlvdSB3YW50IHRvCiAgICAgIHNlcGFyYXRlIHRoZSBndWlkIGludG8gc2VwYXJhdGUgbmFtZXNwYWNlcy4KICAgIEByZXR1cm4ge1N0cmluZ30gdGhlIGd1aWQKICAqLwoKICBfZXhwb3J0cy5HVUlEX0tFWSA9IEdVSURfS0VZOwoKICBmdW5jdGlvbiBnZW5lcmF0ZUd1aWQob2JqLCBwcmVmaXgpIHsKICAgIGlmIChwcmVmaXggPT09IHZvaWQgMCkgewogICAgICBwcmVmaXggPSBHVUlEX1BSRUZJWDsKICAgIH0KCiAgICB2YXIgZ3VpZCA9IHByZWZpeCArIHV1aWQoKTsKCiAgICBpZiAoaXNPYmplY3Qob2JqKSkgewogICAgICBPQkpFQ1RfR1VJRFMuc2V0KG9iaiwgZ3VpZCk7CiAgICB9CgogICAgcmV0dXJuIGd1aWQ7CiAgfQogIC8qKgogICAgUmV0dXJucyBhIHVuaXF1ZSBpZCBmb3IgdGhlIG9iamVjdC4gSWYgdGhlIG9iamVjdCBkb2VzIG5vdCB5ZXQgaGF2ZSBhIGd1aWQsCiAgICBvbmUgd2lsbCBiZSBhc3NpZ25lZCB0byBpdC4gWW91IGNhbiBjYWxsIHRoaXMgb24gYW55IG9iamVjdCwKICAgIGBFbWJlck9iamVjdGAtYmFzZWQgb3Igbm90LgogIAogICAgWW91IGNhbiBhbHNvIHVzZSB0aGlzIG1ldGhvZCBvbiBET00gRWxlbWVudCBvYmplY3RzLgogIAogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQG1ldGhvZCBndWlkRm9yCiAgICBAZm9yIEBlbWJlci9vYmplY3QvaW50ZXJuYWxzCiAgICBAcGFyYW0ge09iamVjdH0gb2JqIGFueSBvYmplY3QsIHN0cmluZywgbnVtYmVyLCBFbGVtZW50LCBvciBwcmltaXRpdmUKICAgIEByZXR1cm4ge1N0cmluZ30gdGhlIHVuaXF1ZSBndWlkIGZvciB0aGlzIGluc3RhbmNlLgogICovCgoKICBmdW5jdGlvbiBndWlkRm9yKHZhbHVlKSB7CiAgICB2YXIgZ3VpZDsKCiAgICBpZiAoaXNPYmplY3QodmFsdWUpKSB7CiAgICAgIGd1aWQgPSBPQkpFQ1RfR1VJRFMuZ2V0KHZhbHVlKTsKCiAgICAgIGlmIChndWlkID09PSB1bmRlZmluZWQpIHsKICAgICAgICBndWlkID0gR1VJRF9QUkVGSVggKyB1dWlkKCk7CiAgICAgICAgT0JKRUNUX0dVSURTLnNldCh2YWx1ZSwgZ3VpZCk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGd1aWQgPSBOT05fT0JKRUNUX0dVSURTLmdldCh2YWx1ZSk7CgogICAgICBpZiAoZ3VpZCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7CgogICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykgewogICAgICAgICAgZ3VpZCA9ICdzdCcgKyB1dWlkKCk7CiAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJykgewogICAgICAgICAgZ3VpZCA9ICdudScgKyB1dWlkKCk7CiAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnc3ltYm9sJykgewogICAgICAgICAgZ3VpZCA9ICdzeScgKyB1dWlkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGd1aWQgPSAnKCcgKyB2YWx1ZSArICcpJzsKICAgICAgICB9CgogICAgICAgIE5PTl9PQkpFQ1RfR1VJRFMuc2V0KHZhbHVlLCBndWlkKTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBndWlkOwogIH0KCiAgdmFyIEdFTkVSQVRFRF9TWU1CT0xTID0gW107CgogIGZ1bmN0aW9uIGlzSW50ZXJuYWxTeW1ib2wocG9zc2libGVTeW1ib2wpIHsKICAgIHJldHVybiBHRU5FUkFURURfU1lNQk9MUy5pbmRleE9mKHBvc3NpYmxlU3ltYm9sKSAhPT0gLTE7CiAgfQoKICBmdW5jdGlvbiBzeW1ib2woZGVidWdOYW1lKSB7CiAgICAvLyBUT0RPOiBJbnZlc3RpZ2F0ZSB1c2luZyBwbGF0Zm9ybSBzeW1ib2xzLCBidXQgd2UgZG8gbm90CiAgICAvLyB3YW50IHRvIHJlcXVpcmUgbm9uLWVudW1lcmFiaWxpdHkgZm9yIHRoaXMgQVBJLCB3aGljaAogICAgLy8gd291bGQgaW50cm9kdWNlIGEgbGFyZ2UgY29zdC4KICAgIHZhciBpZCA9IEdVSURfS0VZICsgTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogRGF0ZS5ub3coKSk7CiAgICB2YXIgc3ltYm9sID0gaW50ZXJuKCJfXyIgKyBkZWJ1Z05hbWUgKyBpZCArICJfXyIpOwogICAgR0VORVJBVEVEX1NZTUJPTFMucHVzaChzeW1ib2wpOwogICAgcmV0dXJuIHN5bWJvbDsKICB9IC8vIHRoZSBkZWxldGUgaXMgbWVhbnQgdG8gaGludCBhdCBydW50aW1lcyB0aGF0IHRoaXMgb2JqZWN0IHNob3VsZCByZW1haW4gaW4KICAvLyBkaWN0aW9uYXJ5IG1vZGUuIFRoaXMgaXMgY2xlYXJseSBhIHJ1bnRpbWUgc3BlY2lmaWMgaGFjaywgYnV0IGN1cnJlbnRseSBpdAogIC8vIGFwcGVhcnMgd29ydGh3aGlsZSBpbiBzb21lIHVzZWNhc2VzLiBQbGVhc2Ugbm90ZSwgdGhlc2UgZGVsZXRlcyBkbyBpbmNyZWFzZQogIC8vIHRoZSBjb3N0IG9mIGNyZWF0aW9uIGRyYW1hdGljYWxseSBvdmVyIGEgcGxhaW4gT2JqZWN0LmNyZWF0ZS4gQW5kIGFzIHRoaXMKICAvLyBvbmx5IG1ha2VzIHNlbnNlIGZvciBsb25nLWxpdmVkIGRpY3Rpb25hcmllcyB0aGF0IGFyZW4ndCBpbnN0YW50aWF0ZWQgb2Z0ZW4uCgoKICBmdW5jdGlvbiBtYWtlRGljdGlvbmFyeShwYXJlbnQpIHsKICAgIHZhciBkaWN0ID0gT2JqZWN0LmNyZWF0ZShwYXJlbnQpOwogICAgZGljdFsnX2RpY3QnXSA9IG51bGw7CiAgICBkZWxldGUgZGljdFsnX2RpY3QnXTsKICAgIHJldHVybiBkaWN0OwogIH0KCiAgdmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvcnM7CgogIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyAhPT0gdW5kZWZpbmVkKSB7CiAgICBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnM7CiAgfSBlbHNlIHsKICAgIGdldE93blByb3BlcnR5RGVzY3JpcHRvcnMgPSBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKG9iaikgewogICAgICB2YXIgZGVzY3JpcHRvcnMgPSB7fTsKICAgICAgT2JqZWN0LmtleXMob2JqKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICBkZXNjcmlwdG9yc1trZXldID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmosIGtleSk7CiAgICAgIH0pOwogICAgICByZXR1cm4gZGVzY3JpcHRvcnM7CiAgICB9OwogIH0KCiAgdmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvcnMkMSA9IGdldE93blByb3BlcnR5RGVzY3JpcHRvcnM7CiAgX2V4cG9ydHMuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyA9IGdldE93blByb3BlcnR5RGVzY3JpcHRvcnMkMTsKICB2YXIgSEFTX1NVUEVSX1BBVFRFUk4gPSAvXC4oX3N1cGVyfGNhbGxcKHRoaXN8YXBwbHlcKHRoaXMpLzsKICB2YXIgZm5Ub1N0cmluZyA9IEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZzsKCiAgdmFyIGNoZWNrSGFzU3VwZXIgPSBmdW5jdGlvbiAoKSB7CiAgICB2YXIgc291cmNlQXZhaWxhYmxlID0gZm5Ub1N0cmluZy5jYWxsKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9KS5pbmRleE9mKCdyZXR1cm4gdGhpcycpID4gLTE7CgogICAgaWYgKHNvdXJjZUF2YWlsYWJsZSkgewogICAgICByZXR1cm4gZnVuY3Rpb24gY2hlY2tIYXNTdXBlcihmdW5jKSB7CiAgICAgICAgcmV0dXJuIEhBU19TVVBFUl9QQVRURVJOLnRlc3QoZm5Ub1N0cmluZy5jYWxsKGZ1bmMpKTsKICAgICAgfTsKICAgIH0KCiAgICByZXR1cm4gZnVuY3Rpb24gY2hlY2tIYXNTdXBlcigpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9OwogIH0oKTsKCiAgX2V4cG9ydHMuY2hlY2tIYXNTdXBlciA9IGNoZWNrSGFzU3VwZXI7CiAgdmFyIEhBU19TVVBFUl9NQVAgPSBuZXcgV2Vha01hcCgpOwogIHZhciBST09UID0gT2JqZWN0LmZyZWV6ZShmdW5jdGlvbiAoKSB7fSk7CiAgX2V4cG9ydHMuUk9PVCA9IFJPT1Q7CiAgSEFTX1NVUEVSX01BUC5zZXQoUk9PVCwgZmFsc2UpOwoKICBmdW5jdGlvbiBoYXNTdXBlcihmdW5jKSB7CiAgICB2YXIgaGFzU3VwZXIgPSBIQVNfU1VQRVJfTUFQLmdldChmdW5jKTsKCiAgICBpZiAoaGFzU3VwZXIgPT09IHVuZGVmaW5lZCkgewogICAgICBoYXNTdXBlciA9IGNoZWNrSGFzU3VwZXIoZnVuYyk7CiAgICAgIEhBU19TVVBFUl9NQVAuc2V0KGZ1bmMsIGhhc1N1cGVyKTsKICAgIH0KCiAgICByZXR1cm4gaGFzU3VwZXI7CiAgfQoKICB2YXIgT0JTRVJWRVJTX01BUCA9IG5ldyBXZWFrTWFwKCk7CgogIGZ1bmN0aW9uIHNldE9ic2VydmVycyhmdW5jLCBvYnNlcnZlcnMpIHsKICAgIE9CU0VSVkVSU19NQVAuc2V0KGZ1bmMsIG9ic2VydmVycyk7CiAgfQoKICBmdW5jdGlvbiBnZXRPYnNlcnZlcnMoZnVuYykgewogICAgcmV0dXJuIE9CU0VSVkVSU19NQVAuZ2V0KGZ1bmMpOwogIH0KCiAgdmFyIExJU1RFTkVSU19NQVAgPSBuZXcgV2Vha01hcCgpOwoKICBmdW5jdGlvbiBzZXRMaXN0ZW5lcnMoZnVuYywgbGlzdGVuZXJzKSB7CiAgICBpZiAobGlzdGVuZXJzKSB7CiAgICAgIExJU1RFTkVSU19NQVAuc2V0KGZ1bmMsIGxpc3RlbmVycyk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBnZXRMaXN0ZW5lcnMoZnVuYykgewogICAgcmV0dXJuIExJU1RFTkVSU19NQVAuZ2V0KGZ1bmMpOwogIH0KCiAgdmFyIElTX1dSQVBQRURfRlVOQ1RJT05fU0VUID0gbmV3IF9wb2x5ZmlsbHMuX1dlYWtTZXQoKTsKICAvKioKICAgIFdyYXBzIHRoZSBwYXNzZWQgZnVuY3Rpb24gc28gdGhhdCBgdGhpcy5fc3VwZXJgIHdpbGwgcG9pbnQgdG8gdGhlIHN1cGVyRnVuYwogICAgd2hlbiB0aGUgZnVuY3Rpb24gaXMgaW52b2tlZC4gVGhpcyBpcyB0aGUgcHJpbWl0aXZlIHdlIHVzZSB0byBpbXBsZW1lbnQKICAgIGNhbGxzIHRvIHN1cGVyLgogIAogICAgQHByaXZhdGUKICAgIEBtZXRob2Qgd3JhcAogICAgQGZvciBFbWJlcgogICAgQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gY2FsbAogICAgQHBhcmFtIHtGdW5jdGlvbn0gc3VwZXJGdW5jIFRoZSBzdXBlciBmdW5jdGlvbi4KICAgIEByZXR1cm4ge0Z1bmN0aW9ufSB3cmFwcGVkIGZ1bmN0aW9uLgogICovCgogIGZ1bmN0aW9uIHdyYXAoZnVuYywgc3VwZXJGdW5jKSB7CiAgICBpZiAoIWhhc1N1cGVyKGZ1bmMpKSB7CiAgICAgIHJldHVybiBmdW5jOwogICAgfSAvLyBlbnN1cmUgYW4gdW53cmFwcGVkIHN1cGVyIHRoYXQgY2FsbHMgX3N1cGVyIGlzIHdyYXBwZWQgd2l0aCBhIHRlcm1pbmFsIF9zdXBlcgoKCiAgICBpZiAoIUlTX1dSQVBQRURfRlVOQ1RJT05fU0VULmhhcyhzdXBlckZ1bmMpICYmIGhhc1N1cGVyKHN1cGVyRnVuYykpIHsKICAgICAgcmV0dXJuIF93cmFwKGZ1bmMsIF93cmFwKHN1cGVyRnVuYywgUk9PVCkpOwogICAgfQoKICAgIHJldHVybiBfd3JhcChmdW5jLCBzdXBlckZ1bmMpOwogIH0KCiAgZnVuY3Rpb24gX3dyYXAoZnVuYywgc3VwZXJGdW5jKSB7CiAgICBmdW5jdGlvbiBzdXBlcldyYXBwZXIoKSB7CiAgICAgIHZhciBvcmlnID0gdGhpcy5fc3VwZXI7CiAgICAgIHRoaXMuX3N1cGVyID0gc3VwZXJGdW5jOwogICAgICB2YXIgcmV0ID0gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgICB0aGlzLl9zdXBlciA9IG9yaWc7CiAgICAgIHJldHVybiByZXQ7CiAgICB9CgogICAgSVNfV1JBUFBFRF9GVU5DVElPTl9TRVQuYWRkKHN1cGVyV3JhcHBlcik7CiAgICBzZXRPYnNlcnZlcnMoc3VwZXJXcmFwcGVyLCBnZXRPYnNlcnZlcnMoZnVuYykpOwogICAgc2V0TGlzdGVuZXJzKHN1cGVyV3JhcHBlciwgZ2V0TGlzdGVuZXJzKGZ1bmMpKTsKICAgIHJldHVybiBzdXBlcldyYXBwZXI7CiAgfQoKICB2YXIgb2JqZWN0VG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nOwogIHZhciBmdW5jdGlvblRvU3RyaW5nID0gRnVuY3Rpb24ucHJvdG90eXBlLnRvU3RyaW5nOwogIHZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheTsKICB2YXIgb2JqZWN0S2V5cyA9IE9iamVjdC5rZXlzOwogIHZhciBzdHJpbmdpZnkgPSBKU09OLnN0cmluZ2lmeTsKICB2YXIgTElTVF9MSU1JVCA9IDEwMDsKICB2YXIgREVQVEhfTElNSVQgPSA0OwogIHZhciBTQUZFX0tFWSA9IC9eW1x3JF0rJC87CiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL2RlYnVnCiAgKi8KCiAgLyoqCiAgICBDb252ZW5pZW5jZSBtZXRob2QgdG8gaW5zcGVjdCBhbiBvYmplY3QuIFRoaXMgbWV0aG9kIHdpbGwgYXR0ZW1wdCB0bwogICAgY29udmVydCB0aGUgb2JqZWN0IGludG8gYSB1c2VmdWwgc3RyaW5nIGRlc2NyaXB0aW9uLgogIAogICAgSXQgaXMgYSBwcmV0dHkgc2ltcGxlIGltcGxlbWVudGF0aW9uLiBJZiB5b3Ugd2FudCBzb21ldGhpbmcgbW9yZSByb2J1c3QsCiAgICB1c2Ugc29tZXRoaW5nIGxpa2UgSlNEdW1wOiBodHRwczovL2dpdGh1Yi5jb20vTlYvanNEdW1wCiAgCiAgICBAbWV0aG9kIGluc3BlY3QKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB5b3Ugd2FudCB0byBpbnNwZWN0LgogICAgQHJldHVybiB7U3RyaW5nfSBBIGRlc2NyaXB0aW9uIG9mIHRoZSBvYmplY3QKICAgIEBzaW5jZSAxLjQuMAogICAgQHByaXZhdGUKICAqLwoKICBmdW5jdGlvbiBpbnNwZWN0KG9iaikgewogICAgLy8gZGV0ZWN0IE5vZGUgdXRpbC5pbnNwZWN0IGNhbGwgaW5zcGVjdChkZXB0aDogbnVtYmVyLCBvcHRzOiBvYmplY3QpCiAgICBpZiAodHlwZW9mIG9iaiA9PT0gJ251bWJlcicgJiYgYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgewogICAgICByZXR1cm4gdGhpczsKICAgIH0KCiAgICByZXR1cm4gaW5zcGVjdFZhbHVlKG9iaiwgMCk7CiAgfQoKICBmdW5jdGlvbiBpbnNwZWN0VmFsdWUodmFsdWUsIGRlcHRoLCBzZWVuKSB7CiAgICB2YXIgdmFsdWVJc0FycmF5ID0gZmFsc2U7CgogICAgc3dpdGNoICh0eXBlb2YgdmFsdWUpIHsKICAgICAgY2FzZSAndW5kZWZpbmVkJzoKICAgICAgICByZXR1cm4gJ3VuZGVmaW5lZCc7CgogICAgICBjYXNlICdvYmplY3QnOgogICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkgcmV0dXJuICdudWxsJzsKCiAgICAgICAgaWYgKGlzQXJyYXkodmFsdWUpKSB7CiAgICAgICAgICB2YWx1ZUlzQXJyYXkgPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSAvLyBpcyB0b1N0cmluZyBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nIG9yIHVuZGVmaW5lZCB0aGVuIHRyYXZlcnNlCgoKICAgICAgICBpZiAodmFsdWUudG9TdHJpbmcgPT09IG9iamVjdFRvU3RyaW5nIHx8IHZhbHVlLnRvU3RyaW5nID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0gLy8gY3VzdG9tIHRvU3RyaW5nCgoKICAgICAgICByZXR1cm4gdmFsdWUudG9TdHJpbmcoKTsKCiAgICAgIGNhc2UgJ2Z1bmN0aW9uJzoKICAgICAgICByZXR1cm4gdmFsdWUudG9TdHJpbmcgPT09IGZ1bmN0aW9uVG9TdHJpbmcgPyB2YWx1ZS5uYW1lID8gIltGdW5jdGlvbjoiICsgdmFsdWUubmFtZSArICJdIiA6ICJbRnVuY3Rpb25dIiA6IHZhbHVlLnRvU3RyaW5nKCk7CgogICAgICBjYXNlICdzdHJpbmcnOgogICAgICAgIHJldHVybiBzdHJpbmdpZnkodmFsdWUpOwoKICAgICAgY2FzZSAnc3ltYm9sJzoKICAgICAgY2FzZSAnYm9vbGVhbic6CiAgICAgIGNhc2UgJ251bWJlcic6CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCk7CiAgICB9CgogICAgaWYgKHNlZW4gPT09IHVuZGVmaW5lZCkgewogICAgICBzZWVuID0gbmV3IF9wb2x5ZmlsbHMuX1dlYWtTZXQoKTsKICAgIH0gZWxzZSB7CiAgICAgIGlmIChzZWVuLmhhcyh2YWx1ZSkpIHJldHVybiAiW0NpcmN1bGFyXSI7CiAgICB9CgogICAgc2Vlbi5hZGQodmFsdWUpOwogICAgcmV0dXJuIHZhbHVlSXNBcnJheSA/IGluc3BlY3RBcnJheSh2YWx1ZSwgZGVwdGggKyAxLCBzZWVuKSA6IGluc3BlY3RPYmplY3QodmFsdWUsIGRlcHRoICsgMSwgc2Vlbik7CiAgfQoKICBmdW5jdGlvbiBpbnNwZWN0S2V5KGtleSkgewogICAgcmV0dXJuIFNBRkVfS0VZLnRlc3Qoa2V5KSA/IGtleSA6IHN0cmluZ2lmeShrZXkpOwogIH0KCiAgZnVuY3Rpb24gaW5zcGVjdE9iamVjdChvYmosIGRlcHRoLCBzZWVuKSB7CiAgICBpZiAoZGVwdGggPiBERVBUSF9MSU1JVCkgewogICAgICByZXR1cm4gJ1tPYmplY3RdJzsKICAgIH0KCiAgICB2YXIgcyA9ICd7JzsKICAgIHZhciBrZXlzID0gb2JqZWN0S2V5cyhvYmopOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgICBzICs9IGkgPT09IDAgPyAnICcgOiAnLCAnOwoKICAgICAgaWYgKGkgPj0gTElTVF9MSU1JVCkgewogICAgICAgIHMgKz0gIi4uLiAiICsgKGtleXMubGVuZ3RoIC0gTElTVF9MSU1JVCkgKyAiIG1vcmUga2V5cyI7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KCiAgICAgIHZhciBrZXkgPSBrZXlzW2ldOwogICAgICBzICs9IGluc3BlY3RLZXkoa2V5KSArICc6ICcgKyBpbnNwZWN0VmFsdWUob2JqW2tleV0sIGRlcHRoLCBzZWVuKTsKICAgIH0KCiAgICBzICs9ICcgfSc7CiAgICByZXR1cm4gczsKICB9CgogIGZ1bmN0aW9uIGluc3BlY3RBcnJheShhcnIsIGRlcHRoLCBzZWVuKSB7CiAgICBpZiAoZGVwdGggPiBERVBUSF9MSU1JVCkgewogICAgICByZXR1cm4gJ1tBcnJheV0nOwogICAgfQoKICAgIHZhciBzID0gJ1snOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7CiAgICAgIHMgKz0gaSA9PT0gMCA/ICcgJyA6ICcsICc7CgogICAgICBpZiAoaSA+PSBMSVNUX0xJTUlUKSB7CiAgICAgICAgcyArPSAiLi4uICIgKyAoYXJyLmxlbmd0aCAtIExJU1RfTElNSVQpICsgIiBtb3JlIGl0ZW1zIjsKICAgICAgICBicmVhazsKICAgICAgfQoKICAgICAgcyArPSBpbnNwZWN0VmFsdWUoYXJyW2ldLCBkZXB0aCwgc2Vlbik7CiAgICB9CgogICAgcyArPSAnIF0nOwogICAgcmV0dXJuIHM7CiAgfQoKICBmdW5jdGlvbiBsb29rdXBEZXNjcmlwdG9yKG9iaiwga2V5TmFtZSkgewogICAgdmFyIGN1cnJlbnQgPSBvYmo7CgogICAgZG8gewogICAgICB2YXIgZGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoY3VycmVudCwga2V5TmFtZSk7CgogICAgICBpZiAoZGVzY3JpcHRvciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIGRlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIGN1cnJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoY3VycmVudCk7CiAgICB9IHdoaWxlIChjdXJyZW50ICE9PSBudWxsKTsKCiAgICByZXR1cm4gbnVsbDsKICB9CiAgLyoqCiAgICBDaGVja3MgdG8gc2VlIGlmIHRoZSBgbWV0aG9kTmFtZWAgZXhpc3RzIG9uIHRoZSBgb2JqYC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCBmb28gPSB7IGJhcjogZnVuY3Rpb24oKSB7IHJldHVybiAnYmFyJzsgfSwgYmF6OiBudWxsIH07CiAgCiAgICBFbWJlci5jYW5JbnZva2UoZm9vLCAnYmFyJyk7IC8vIHRydWUKICAgIEVtYmVyLmNhbkludm9rZShmb28sICdiYXonKTsgLy8gZmFsc2UKICAgIEVtYmVyLmNhbkludm9rZShmb28sICdiYXQnKTsgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQG1ldGhvZCBjYW5JbnZva2UKICAgIEBmb3IgRW1iZXIKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBjaGVjayBmb3IgdGhlIG1ldGhvZAogICAgQHBhcmFtIHtTdHJpbmd9IG1ldGhvZE5hbWUgVGhlIG1ldGhvZCBuYW1lIHRvIGNoZWNrIGZvcgogICAgQHJldHVybiB7Qm9vbGVhbn0KICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIGNhbkludm9rZShvYmosIG1ldGhvZE5hbWUpIHsKICAgIHJldHVybiBvYmogIT09IG51bGwgJiYgb2JqICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG9ialttZXRob2ROYW1lXSA9PT0gJ2Z1bmN0aW9uJzsKICB9CiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci91dGlscwogICovCgogIC8qKgogICAgQ2hlY2tzIHRvIHNlZSBpZiB0aGUgYG1ldGhvZE5hbWVgIGV4aXN0cyBvbiB0aGUgYG9iamAsCiAgICBhbmQgaWYgaXQgZG9lcywgaW52b2tlcyBpdCB3aXRoIHRoZSBhcmd1bWVudHMgcGFzc2VkLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgdHJ5SW52b2tlIH0gZnJvbSAnQGVtYmVyL3V0aWxzJzsKICAKICAgIGxldCBkID0gbmV3IERhdGUoJzAzLzE1LzIwMTMnKTsKICAKICAgIHRyeUludm9rZShkLCAnZ2V0VGltZScpOyAgICAgICAgICAgICAgLy8gMTM2MzMyMDAwMDAwMAogICAgdHJ5SW52b2tlKGQsICdzZXRGdWxsWWVhcicsIFsyMDE0XSk7ICAvLyAxMzk0ODU2MDAwMDAwCiAgICB0cnlJbnZva2UoZCwgJ25vU3VjaE1ldGhvZCcsIFsyMDE0XSk7IC8vIHVuZGVmaW5lZAogICAgYGBgCiAgCiAgICBAbWV0aG9kIHRyeUludm9rZQogICAgQGZvciBAZW1iZXIvdXRpbHMKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBjaGVjayBmb3IgdGhlIG1ldGhvZAogICAgQHBhcmFtIHtTdHJpbmd9IG1ldGhvZE5hbWUgVGhlIG1ldGhvZCBuYW1lIHRvIGNoZWNrIGZvcgogICAgQHBhcmFtIHtBcnJheX0gW2FyZ3NdIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kCiAgICBAcmV0dXJuIHsqfSB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBpbnZva2VkIG1ldGhvZCBvciB1bmRlZmluZWQgaWYgaXQgY2Fubm90IGJlIGludm9rZWQKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gdHJ5SW52b2tlKG9iaiwgbWV0aG9kTmFtZSwgYXJncykgewogICAgaWYgKGNhbkludm9rZShvYmosIG1ldGhvZE5hbWUpKSB7CiAgICAgIHZhciBtZXRob2QgPSBvYmpbbWV0aG9kTmFtZV07CiAgICAgIHJldHVybiBtZXRob2QuYXBwbHkob2JqLCBhcmdzKTsKICAgIH0KICB9CgogIHZhciBpc0FycmF5JDEgPSBBcnJheS5pc0FycmF5OwoKICBmdW5jdGlvbiBtYWtlQXJyYXkob2JqKSB7CiAgICBpZiAob2JqID09PSBudWxsIHx8IG9iaiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBbXTsKICAgIH0KCiAgICByZXR1cm4gaXNBcnJheSQxKG9iaikgPyBvYmogOiBbb2JqXTsKICB9CgogIHZhciBOQU1FUyA9IG5ldyBXZWFrTWFwKCk7CgogIGZ1bmN0aW9uIHNldE5hbWUob2JqLCBuYW1lKSB7CiAgICBpZiAoaXNPYmplY3Qob2JqKSkgTkFNRVMuc2V0KG9iaiwgbmFtZSk7CiAgfQoKICBmdW5jdGlvbiBnZXROYW1lKG9iaikgewogICAgcmV0dXJuIE5BTUVTLmdldChvYmopOwogIH0KCiAgdmFyIG9iamVjdFRvU3RyaW5nJDEgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nOwoKICBmdW5jdGlvbiBpc05vbmUob2JqKSB7CiAgICByZXR1cm4gb2JqID09PSBudWxsIHx8IG9iaiA9PT0gdW5kZWZpbmVkOwogIH0KICAvKgogICBBIGB0b1N0cmluZ2AgdXRpbCBmdW5jdGlvbiB0aGF0IHN1cHBvcnRzIG9iamVjdHMgd2l0aG91dCBhIGB0b1N0cmluZ2AKICAgbWV0aG9kLCBlLmcuIGFuIG9iamVjdCBjcmVhdGVkIHdpdGggYE9iamVjdC5jcmVhdGUobnVsbClgLgogICovCgoKICBmdW5jdGlvbiB0b1N0cmluZyhvYmopIHsKICAgIGlmICh0eXBlb2Ygb2JqID09PSAnc3RyaW5nJykgewogICAgICByZXR1cm4gb2JqOwogICAgfQoKICAgIGlmIChudWxsID09PSBvYmopIHJldHVybiAnbnVsbCc7CiAgICBpZiAodW5kZWZpbmVkID09PSBvYmopIHJldHVybiAndW5kZWZpbmVkJzsKCiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7CiAgICAgIC8vIFJlaW1wbGVtZW50IEFycmF5LnByb3RvdHlwZS5qb2luIGFjY29yZGluZyB0byBzcGVjICgyMi4xLjMuMTMpCiAgICAgIC8vIENoYW5naW5nIFRvU3RyaW5nKGVsZW1lbnQpIHdpdGggdGhpcyBzYWZlIHZlcnNpb24gb2YgVG9TdHJpbmcuCiAgICAgIHZhciByID0gJyc7CgogICAgICBmb3IgKHZhciBrID0gMDsgayA8IG9iai5sZW5ndGg7IGsrKykgewogICAgICAgIGlmIChrID4gMCkgewogICAgICAgICAgciArPSAnLCc7CiAgICAgICAgfQoKICAgICAgICBpZiAoIWlzTm9uZShvYmpba10pKSB7CiAgICAgICAgICByICs9IHRvU3RyaW5nKG9ialtrXSk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gcjsKICAgIH0KCiAgICBpZiAodHlwZW9mIG9iai50b1N0cmluZyA9PT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gb2JqLnRvU3RyaW5nKCk7CiAgICB9CgogICAgcmV0dXJuIG9iamVjdFRvU3RyaW5nJDEuY2FsbChvYmopOwogIH0KCiAgdmFyIEhBU19OQVRJVkVfU1lNQk9MID0gZnVuY3Rpb24gKCkgewogICAgaWYgKHR5cGVvZiBTeW1ib2wgIT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIHJldHVybiB0eXBlb2YgU3ltYm9sKCkgPT09ICdzeW1ib2wnOwogIH0oKTsKCiAgX2V4cG9ydHMuSEFTX05BVElWRV9TWU1CT0wgPSBIQVNfTkFUSVZFX1NZTUJPTDsKICB2YXIgSEFTX05BVElWRV9QUk9YWSA9IHR5cGVvZiBQcm94eSA9PT0gJ2Z1bmN0aW9uJzsKICBfZXhwb3J0cy5IQVNfTkFUSVZFX1BST1hZID0gSEFTX05BVElWRV9QUk9YWTsKICB2YXIgUFJPWElFUyA9IG5ldyBfcG9seWZpbGxzLl9XZWFrU2V0KCk7CgogIGZ1bmN0aW9uIGlzUHJveHkodmFsdWUpIHsKICAgIGlmIChpc09iamVjdCh2YWx1ZSkpIHsKICAgICAgcmV0dXJuIFBST1hJRVMuaGFzKHZhbHVlKTsKICAgIH0KCiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICBmdW5jdGlvbiBzZXRQcm94eShvYmplY3QpIHsKICAgIGlmIChpc09iamVjdChvYmplY3QpKSB7CiAgICAgIFBST1hJRVMuYWRkKG9iamVjdCk7CiAgICB9CiAgfQoKICB2YXIgQ2FjaGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDYWNoZShsaW1pdCwgZnVuYywgc3RvcmUpIHsKICAgICAgdGhpcy5saW1pdCA9IGxpbWl0OwogICAgICB0aGlzLmZ1bmMgPSBmdW5jOwogICAgICB0aGlzLnN0b3JlID0gc3RvcmU7CiAgICAgIHRoaXMuc2l6ZSA9IDA7CiAgICAgIHRoaXMubWlzc2VzID0gMDsKICAgICAgdGhpcy5oaXRzID0gMDsKICAgICAgdGhpcy5zdG9yZSA9IHN0b3JlIHx8IG5ldyBNYXAoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gQ2FjaGUucHJvdG90eXBlOwoKICAgIF9wcm90by5nZXQgPSBmdW5jdGlvbiBnZXQoa2V5KSB7CiAgICAgIGlmICh0aGlzLnN0b3JlLmhhcyhrZXkpKSB7CiAgICAgICAgdGhpcy5oaXRzKys7CiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZ2V0KGtleSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5taXNzZXMrKzsKICAgICAgICByZXR1cm4gdGhpcy5zZXQoa2V5LCB0aGlzLmZ1bmMoa2V5KSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnNldCA9IGZ1bmN0aW9uIHNldChrZXksIHZhbHVlKSB7CiAgICAgIGlmICh0aGlzLmxpbWl0ID4gdGhpcy5zaXplKSB7CiAgICAgICAgdGhpcy5zaXplKys7CiAgICAgICAgdGhpcy5zdG9yZS5zZXQoa2V5LCB2YWx1ZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH07CgogICAgX3Byb3RvLnB1cmdlID0gZnVuY3Rpb24gcHVyZ2UoKSB7CiAgICAgIHRoaXMuc3RvcmUuY2xlYXIoKTsKICAgICAgdGhpcy5zaXplID0gMDsKICAgICAgdGhpcy5oaXRzID0gMDsKICAgICAgdGhpcy5taXNzZXMgPSAwOwogICAgfTsKCiAgICByZXR1cm4gQ2FjaGU7CiAgfSgpOwoKICBfZXhwb3J0cy5DYWNoZSA9IENhY2hlOwogIHZhciBFTUJFUl9BUlJBWSA9IHN5bWJvbCgnRU1CRVJfQVJSQVknKTsKICBfZXhwb3J0cy5FTUJFUl9BUlJBWSA9IEVNQkVSX0FSUkFZOwoKICBmdW5jdGlvbiBpc0VtYmVyQXJyYXkob2JqKSB7CiAgICByZXR1cm4gb2JqICYmIG9ialtFTUJFUl9BUlJBWV07CiAgfQoKICB2YXIgc2V0dXBNYW5kYXRvcnlTZXR0ZXI7CiAgX2V4cG9ydHMuc2V0dXBNYW5kYXRvcnlTZXR0ZXIgPSBzZXR1cE1hbmRhdG9yeVNldHRlcjsKICB2YXIgdGVhcmRvd25NYW5kYXRvcnlTZXR0ZXI7CiAgX2V4cG9ydHMudGVhcmRvd25NYW5kYXRvcnlTZXR0ZXIgPSB0ZWFyZG93bk1hbmRhdG9yeVNldHRlcjsKICB2YXIgc2V0V2l0aE1hbmRhdG9yeVNldHRlcjsKICBfZXhwb3J0cy5zZXRXaXRoTWFuZGF0b3J5U2V0dGVyID0gc2V0V2l0aE1hbmRhdG9yeVNldHRlcjsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICAmJiB0cnVlCiAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgKSB7CiAgICAgIHZhciBNQU5EQVRPUllfU0VUVEVSUyA9IG5ldyBXZWFrTWFwKCk7CgogICAgICB2YXIgX3Byb3BlcnR5SXNFbnVtZXJhYmxlID0gZnVuY3Rpb24gX3Byb3BlcnR5SXNFbnVtZXJhYmxlKG9iaiwga2V5KSB7CiAgICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChvYmosIGtleSk7CiAgICAgIH07CgogICAgICBfZXhwb3J0cy5zZXR1cE1hbmRhdG9yeVNldHRlciA9IHNldHVwTWFuZGF0b3J5U2V0dGVyID0gZnVuY3Rpb24gc2V0dXBNYW5kYXRvcnlTZXR0ZXIob2JqLCBrZXlOYW1lKSB7CiAgICAgICAgdmFyIGRlc2MgPSBsb29rdXBEZXNjcmlwdG9yKG9iaiwga2V5TmFtZSkgfHwge307CgogICAgICAgIGlmIChkZXNjLmdldCB8fCBkZXNjLnNldCkgewogICAgICAgICAgLy8gaWYgaXQgaGFzIGEgZ2V0dGVyIG9yIHNldHRlciwgd2UgY2FuJ3QgaW5zdGFsbCB0aGUgbWFuZGF0b3J5IHNldHRlci4KICAgICAgICAgIC8vIG5hdGl2ZSBzZXR0ZXJzIGFyZSBhbGxvd2VkLCB3ZSBoYXZlIHRvIGFzc3VtZSB0aGF0IHRoZXkgd2lsbCByZXNvbHZlCiAgICAgICAgICAvLyB0byB0cmFja2VkIHByb3BlcnRpZXMuCiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAoZGVzYyAmJiAoIWRlc2MuY29uZmlndXJhYmxlIHx8ICFkZXNjLndyaXRhYmxlKSkgewogICAgICAgICAgLy8gaWYgaXQgaXNuJ3Qgd3JpdGFibGUgYW55d2F5cywgc28gd2Ugc2hvdWxkbid0IHByb3ZpZGUgdGhlIHNldHRlci4KICAgICAgICAgIC8vIGlmIGl0IGlzbid0IGNvbmZpZ3VyYWJsZSwgd2UgY2FuJ3Qgb3ZlcndyaXRlIGl0IGFueXdheXMuCiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICB2YXIgc2V0dGVycyA9IE1BTkRBVE9SWV9TRVRURVJTLmdldChvYmopOwoKICAgICAgICBpZiAoc2V0dGVycyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBzZXR0ZXJzID0ge307CiAgICAgICAgICBNQU5EQVRPUllfU0VUVEVSUy5zZXQob2JqLCBzZXR0ZXJzKTsKICAgICAgICB9CgogICAgICAgIGRlc2MuaGFkT3duUHJvcGVydHkgPSBPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleU5hbWUpOwogICAgICAgIHNldHRlcnNba2V5TmFtZV0gPSBkZXNjOwogICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleU5hbWUsIHsKICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICAgIGVudW1lcmFibGU6IF9wcm9wZXJ0eUlzRW51bWVyYWJsZShvYmosIGtleU5hbWUpLAogICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgICAgIGlmIChkZXNjLmdldCkgewogICAgICAgICAgICAgIHJldHVybiBkZXNjLmdldC5jYWxsKHRoaXMpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJldHVybiBkZXNjLnZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9LAogICAgICAgICAgc2V0OiBmdW5jdGlvbiBzZXQodmFsdWUpIHsKICAgICAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byB1cGRhdGUgIiArIHRoaXMgKyAiLiIgKyBTdHJpbmcoa2V5TmFtZSkgKyAiIHRvIFwiIiArIFN0cmluZyh2YWx1ZSkgKyAiXCIsIGJ1dCBpdCBpcyBiZWluZyB0cmFja2VkIGJ5IGEgdHJhY2tpbmcgY29udGV4dCwgc3VjaCBhcyBhIHRlbXBsYXRlLCBjb21wdXRlZCBwcm9wZXJ0eSwgb3Igb2JzZXJ2ZXIuIEluIG9yZGVyIHRvIG1ha2Ugc3VyZSB0aGUgY29udGV4dCB1cGRhdGVzIHByb3Blcmx5LCB5b3UgbXVzdCBpbnZhbGlkYXRlIHRoZSBwcm9wZXJ0eSB3aGVuIHVwZGF0aW5nIGl0LiBZb3UgY2FuIG1hcmsgdGhlIHByb3BlcnR5IGFzIGBAdHJhY2tlZGAsIG9yIHVzZSBgQGVtYmVyL29iamVjdCNzZXRgIHRvIGRvIHRoaXMuIikpOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9OwoKICAgICAgX2V4cG9ydHMudGVhcmRvd25NYW5kYXRvcnlTZXR0ZXIgPSB0ZWFyZG93bk1hbmRhdG9yeVNldHRlciA9IGZ1bmN0aW9uIHRlYXJkb3duTWFuZGF0b3J5U2V0dGVyKG9iaiwga2V5TmFtZSkgewogICAgICAgIHZhciBzZXR0ZXJzID0gTUFOREFUT1JZX1NFVFRFUlMuZ2V0KG9iaik7CgogICAgICAgIGlmIChzZXR0ZXJzICE9PSB1bmRlZmluZWQgJiYgc2V0dGVyc1trZXlOYW1lXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCBzZXR0ZXJzW2tleU5hbWVdKTsKICAgICAgICAgIHNldHRlcnNba2V5TmFtZV0gPSB1bmRlZmluZWQ7CiAgICAgICAgfQogICAgICB9OwoKICAgICAgX2V4cG9ydHMuc2V0V2l0aE1hbmRhdG9yeVNldHRlciA9IHNldFdpdGhNYW5kYXRvcnlTZXR0ZXIgPSBmdW5jdGlvbiBzZXRXaXRoTWFuZGF0b3J5U2V0dGVyKG9iaiwga2V5TmFtZSwgdmFsdWUpIHsKICAgICAgICB2YXIgc2V0dGVycyA9IE1BTkRBVE9SWV9TRVRURVJTLmdldChvYmopOwoKICAgICAgICBpZiAoc2V0dGVycyAhPT0gdW5kZWZpbmVkICYmIHNldHRlcnNba2V5TmFtZV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdmFyIHNldHRlciA9IHNldHRlcnNba2V5TmFtZV07CgogICAgICAgICAgaWYgKHNldHRlci5zZXQpIHsKICAgICAgICAgICAgc2V0dGVyLnNldC5jYWxsKG9iaiwgdmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc2V0dGVyLnZhbHVlID0gdmFsdWU7IC8vIElmIHRoZSBvYmplY3QgZGlkbid0IGhhdmUgb3duIHByb3BlcnR5IGJlZm9yZSwgaXQgd291bGQgaGF2ZSBjaGFuZ2VkCiAgICAgICAgICAgIC8vIHRoZSBlbnVtZXJhYmlsaXR5IGFmdGVyIHNldHRpbmcgdGhlIHZhbHVlIHRoZSBmaXJzdCB0aW1lLgoKICAgICAgICAgICAgaWYgKCFzZXR0ZXIuaGFkT3duUHJvcGVydHkpIHsKICAgICAgICAgICAgICB2YXIgZGVzYyA9IGxvb2t1cERlc2NyaXB0b3Iob2JqLCBrZXlOYW1lKTsKICAgICAgICAgICAgICBkZXNjLmVudW1lcmFibGUgPSB0cnVlOwogICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleU5hbWUsIGRlc2MpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9ialtrZXlOYW1lXSA9IHZhbHVlOwogICAgICAgIH0KICAgICAgfTsKICAgIH0KICAvKgogICBUaGlzIHBhY2thZ2Ugd2lsbCBiZSBlYWdlcmx5IHBhcnNlZCBhbmQgc2hvdWxkIGhhdmUgbm8gZGVwZW5kZW5jaWVzIG9uIGV4dGVybmFsCiAgIHBhY2thZ2VzLgogIAogICBJdCBpcyBpbnRlbmRlZCB0byBiZSB1c2VkIHRvIHNoYXJlIHV0aWxpdHkgbWV0aG9kcyB0aGF0IHdpbGwgYmUgbmVlZGVkCiAgIGJ5IGV2ZXJ5IEVtYmVyIGFwcGxpY2F0aW9uIChhbmQgaXMgKipub3QqKiBhIGR1bXBpbmcgZ3JvdW5kIG9mIHVzZWZ1bCB1dGlsaXRpZXMpLgogIAogICBVdGlsaXR5IG1ldGhvZHMgdGhhdCBhcmUgbmVlZGVkIGluIDwgODAlIG9mIGNhc2VzIHNob3VsZCBiZSBwbGFjZWQKICAgZWxzZXdoZXJlIChzbyB0aGV5IGNhbiBiZSBsYXppbHkgZXZhbHVhdGVkIC8gcGFyc2VkKS4KICAqLwoKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3N5c3RlbS9qcXVlcnkiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3N5c3RlbS91dGlscyIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2V2ZW50X2Rpc3BhdGNoZXIiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL2NvbXBvbmVudF9sb29rdXAiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL21peGlucy90ZXh0X3N1cHBvcnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL2NvcmVfdmlldyIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvbWl4aW5zL2NsYXNzX25hbWVzX3N1cHBvcnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL21peGlucy9jaGlsZF92aWV3c19zdXBwb3J0IiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9taXhpbnMvdmlld19zdGF0ZV9zdXBwb3J0IiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9taXhpbnMvdmlld19zdXBwb3J0IiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9taXhpbnMvYWN0aW9uX3N1cHBvcnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL2NvbXBhdC9hdHRycyIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2xvb2t1cF9wYXJ0aWFsIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vYWN0aW9uX21hbmFnZXIiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfanF1ZXJ5LCBfdXRpbHMsIF9ldmVudF9kaXNwYXRjaGVyLCBfY29tcG9uZW50X2xvb2t1cCwgX3RleHRfc3VwcG9ydCwgX2NvcmVfdmlldywgX2NsYXNzX25hbWVzX3N1cHBvcnQsIF9jaGlsZF92aWV3c19zdXBwb3J0LCBfdmlld19zdGF0ZV9zdXBwb3J0LCBfdmlld19zdXBwb3J0LCBfYWN0aW9uX3N1cHBvcnQsIF9hdHRycywgX2xvb2t1cF9wYXJ0aWFsLCBfYWN0aW9uX21hbmFnZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImpRdWVyeSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9qcXVlcnkualF1ZXJ5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImpRdWVyeURpc2FibGVkIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2pxdWVyeS5qUXVlcnlEaXNhYmxlZDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJhZGRDaGlsZFZpZXciLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfdXRpbHMuYWRkQ2hpbGRWaWV3OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImlzU2ltcGxlQ2xpY2siLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfdXRpbHMuaXNTaW1wbGVDbGljazsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRWaWV3Qm91bmRzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldFZpZXdCb3VuZHM7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ2V0Vmlld0NsaWVudFJlY3RzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldFZpZXdDbGllbnRSZWN0czsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRWaWV3Qm91bmRpbmdDbGllbnRSZWN0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldFZpZXdCb3VuZGluZ0NsaWVudFJlY3Q7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ2V0Um9vdFZpZXdzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldFJvb3RWaWV3czsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRDaGlsZFZpZXdzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldENoaWxkVmlld3M7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ2V0Vmlld0lkIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldFZpZXdJZDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRFbGVtZW50VmlldyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF91dGlscy5nZXRFbGVtZW50VmlldzsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRWaWV3RWxlbWVudCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF91dGlscy5nZXRWaWV3RWxlbWVudDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJzZXRFbGVtZW50VmlldyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF91dGlscy5zZXRFbGVtZW50VmlldzsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJzZXRWaWV3RWxlbWVudCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF91dGlscy5zZXRWaWV3RWxlbWVudDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJjbGVhckVsZW1lbnRWaWV3IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmNsZWFyRWxlbWVudFZpZXc7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiY2xlYXJWaWV3RWxlbWVudCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF91dGlscy5jbGVhclZpZXdFbGVtZW50OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImNvbnN0cnVjdFN0eWxlRGVwcmVjYXRpb25NZXNzYWdlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmNvbnN0cnVjdFN0eWxlRGVwcmVjYXRpb25NZXNzYWdlOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkV2ZW50RGlzcGF0Y2hlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9ldmVudF9kaXNwYXRjaGVyLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQ29tcG9uZW50TG9va3VwIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXBvbmVudF9sb29rdXAuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJUZXh0U3VwcG9ydCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF90ZXh0X3N1cHBvcnQuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJDb3JlVmlldyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb3JlX3ZpZXcuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJDbGFzc05hbWVzU3VwcG9ydCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jbGFzc19uYW1lc19zdXBwb3J0LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQ2hpbGRWaWV3c1N1cHBvcnQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY2hpbGRfdmlld3Nfc3VwcG9ydC5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIlZpZXdTdGF0ZVN1cHBvcnQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfdmlld19zdGF0ZV9zdXBwb3J0LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiVmlld01peGluIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ZpZXdfc3VwcG9ydC5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkFjdGlvblN1cHBvcnQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYWN0aW9uX3N1cHBvcnQuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJNVVRBQkxFX0NFTEwiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXR0cnMuTVVUQUJMRV9DRUxMOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImxvb2t1cFBhcnRpYWwiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbG9va3VwX3BhcnRpYWwuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJoYXNQYXJ0aWFsIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2xvb2t1cF9wYXJ0aWFsLmhhc1BhcnRpYWw7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQWN0aW9uTWFuYWdlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9hY3Rpb25fbWFuYWdlci5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvY29tcGF0L2F0dHJzIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3V0aWxzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5NVVRBQkxFX0NFTEwgPSB2b2lkIDA7CiAgdmFyIE1VVEFCTEVfQ0VMTCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnTVVUQUJMRV9DRUxMJyk7CiAgX2V4cG9ydHMuTVVUQUJMRV9DRUxMID0gTVVUQUJMRV9DRUxMOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvY29tcGF0L2ZhbGxiYWNrLXZpZXctcmVnaXN0cnkiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdXRpbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIHZhciBfZGVmYXVsdCA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL2NvbXBvbmVudF9sb29rdXAiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9ydW50aW1lKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICB2YXIgX2RlZmF1bHQgPSBfcnVudGltZS5PYmplY3QuZXh0ZW5kKHsKICAgIGNvbXBvbmVudEZvcjogZnVuY3Rpb24gY29tcG9uZW50Rm9yKG5hbWUsIG93bmVyLCBvcHRpb25zKSB7CiAgICAgIHZhciBmdWxsTmFtZSA9ICJjb21wb25lbnQ6IiArIG5hbWU7CiAgICAgIHJldHVybiBvd25lci5mYWN0b3J5Rm9yKGZ1bGxOYW1lLCBvcHRpb25zKTsKICAgIH0sCiAgICBsYXlvdXRGb3I6IGZ1bmN0aW9uIGxheW91dEZvcihuYW1lLCBvd25lciwgb3B0aW9ucykgewogICAgICB2YXIgdGVtcGxhdGVGdWxsTmFtZSA9ICJ0ZW1wbGF0ZTpjb21wb25lbnRzLyIgKyBuYW1lOwogICAgICByZXR1cm4gb3duZXIubG9va3VwKHRlbXBsYXRlRnVsbE5hbWUsIG9wdGlvbnMpOwogICAgfQogIH0pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9taXhpbnMvYWN0aW9uX3N1cHBvcnQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9jb21wYXQvYXR0cnMiLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdXRpbHMsIF9tZXRhbCwgX2RlYnVnLCBfYXR0cnMsIF9kZXByZWNhdGVkRmVhdHVyZXMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICBAbW9kdWxlIGVtYmVyCiAgKi8KICB2YXIgbWl4aW5PYmogPSB7CiAgICBzZW5kOiBmdW5jdGlvbiBzZW5kKGFjdGlvbk5hbWUpIHsKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5ID0gMTsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleSAtIDFdID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc0Rlc3Ryb3lpbmcgJiYgIXRoaXMuaXNEZXN0cm95ZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQXR0ZW1wdGVkIHRvIGNhbGwgLnNlbmQoKSB3aXRoIHRoZSBhY3Rpb24gJyIgKyBhY3Rpb25OYW1lICsgIicgb24gdGhlIGRlc3Ryb3llZCBvYmplY3QgJyIgKyB0aGlzICsgIicuIiwgIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgIHZhciBhY3Rpb24gPSB0aGlzLmFjdGlvbnMgJiYgdGhpcy5hY3Rpb25zW2FjdGlvbk5hbWVdOwoKICAgICAgaWYgKGFjdGlvbikgewogICAgICAgIHZhciBzaG91bGRCdWJibGUgPSBhY3Rpb24uYXBwbHkodGhpcywgYXJncykgPT09IHRydWU7CgogICAgICAgIGlmICghc2hvdWxkQnViYmxlKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgdGFyZ2V0ID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICd0YXJnZXQnKTsKCiAgICAgIGlmICh0YXJnZXQpIHsKICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgdGFyZ2V0LnNlbmQgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIGB0YXJnZXRgIGZvciAiICsgdGhpcyArICIgKCIgKyB0YXJnZXQgKyAiKSBkb2VzIG5vdCBoYXZlIGEgYHNlbmRgIG1ldGhvZCIsIHR5cGVvZiB0YXJnZXQuc2VuZCA9PT0gJ2Z1bmN0aW9uJykpOwogICAgICAgIHRhcmdldC5zZW5kLmFwcGx5KHRhcmdldCwgYXJndW1lbnRzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAoZmFsc2UgJiYgIShhY3Rpb24pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgoMCwgX3V0aWxzLmluc3BlY3QpKHRoaXMpICsgIiBoYWQgbm8gYWN0aW9uIGhhbmRsZXIgZm9yOiAiICsgYWN0aW9uTmFtZSwgYWN0aW9uKSk7CiAgICAgIH0KICAgIH0KICB9OwoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5TRU5EX0FDVElPTikgewogICAgLyoqCiAgICAgIENhbGxzIGFuIGFjdGlvbiBwYXNzZWQgdG8gYSBjb21wb25lbnQuCiAgICAgICBGb3IgZXhhbXBsZSBhIGNvbXBvbmVudCBmb3IgcGxheWluZyBvciBwYXVzaW5nIG11c2ljIG1heSB0cmFuc2xhdGUgY2xpY2sgZXZlbnRzCiAgICAgIGludG8gYWN0aW9uIG5vdGlmaWNhdGlvbnMgb2YgInBsYXkiIG9yICJzdG9wIiBkZXBlbmRpbmcgb24gc29tZSBpbnRlcm5hbCBzdGF0ZQogICAgICBvZiB0aGUgY29tcG9uZW50OgogICAgICAgYGBgYXBwL2NvbXBvbmVudHMvcGxheS1idXR0b24uanMKICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICAgIGNsaWNrKCkgewogICAgICAgICAgaWYgKHRoaXMuZ2V0KCdpc1BsYXlpbmcnKSkgewogICAgICAgICAgICB0aGlzLnNlbmRBY3Rpb24oJ3BsYXknKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRoaXMuc2VuZEFjdGlvbignc3RvcCcpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVGhlIGFjdGlvbnMgInBsYXkiIGFuZCAic3RvcCIgbXVzdCBiZSBwYXNzZWQgdG8gdGhpcyBgcGxheS1idXR0b25gIGNvbXBvbmVudDoKICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAge3shIGFwcC90ZW1wbGF0ZXMvYXBwbGljYXRpb24uaGJzIH19CiAgICAgIHt7cGxheS1idXR0b24gcGxheT0oYWN0aW9uICJtdXNpY1N0YXJ0ZWQiKSBzdG9wPShhY3Rpb24gIm11c2ljU3RvcHBlZCIpfX0KICAgICAgYGBgCiAgICAgICBXaGVuIHRoZSBjb21wb25lbnQgcmVjZWl2ZXMgYSBicm93c2VyIGBjbGlja2AgZXZlbnQgaXQgdHJhbnNsYXRlIHRoaXMKICAgICAgaW50ZXJhY3Rpb24gaW50byBhcHBsaWNhdGlvbi1zcGVjaWZpYyBzZW1hbnRpY3MgKCJwbGF5IiBvciAic3RvcCIpIGFuZAogICAgICBjYWxscyB0aGUgc3BlY2lmaWVkIGFjdGlvbi4KICAgICAgIGBgYGFwcC9jb250cm9sbGVyL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBDb250cm9sbGVyIGZyb20gJ0BlbWJlci9jb250cm9sbGVyJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IENvbnRyb2xsZXIuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBtdXNpY1N0YXJ0ZWQoKSB7CiAgICAgICAgICAgIC8vIGNhbGxlZCB3aGVuIHRoZSBwbGF5IGJ1dHRvbiBpcyBjbGlja2VkCiAgICAgICAgICAgIC8vIGFuZCB0aGUgbXVzaWMgc3RhcnRlZCBwbGF5aW5nCiAgICAgICAgICB9LAogICAgICAgICAgbXVzaWNTdG9wcGVkKCkgewogICAgICAgICAgICAvLyBjYWxsZWQgd2hlbiB0aGUgcGxheSBidXR0b24gaXMgY2xpY2tlZAogICAgICAgICAgICAvLyBhbmQgdGhlIG11c2ljIHN0b3BwZWQgcGxheWluZwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgSWYgbm8gYWN0aW9uIGlzIHBhc3NlZCB0byBgc2VuZEFjdGlvbmAgYSBkZWZhdWx0IG5hbWUgb2YgImFjdGlvbiIKICAgICAgaXMgYXNzdW1lZC4KICAgICAgIGBgYGFwcC9jb21wb25lbnRzL25leHQtYnV0dG9uLmpzCiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICBjbGljaygpIHsKICAgICAgICAgIHRoaXMuc2VuZEFjdGlvbigpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgaGFuZGxlYmFycwogICAgICB7eyEgYXBwL3RlbXBsYXRlcy9hcHBsaWNhdGlvbi5oYnMgfX0KICAgICAge3tuZXh0LWJ1dHRvbiBhY3Rpb249KGFjdGlvbiAicGxheU5leHRTb25nSW5BbGJ1bSIpfX0KICAgICAgYGBgCiAgICAgICBgYGBhcHAvY29udHJvbGxlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IENvbnRyb2xsZXIgZnJvbSAnQGVtYmVyL2NvbnRyb2xsZXInOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQ29udHJvbGxlci5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHBsYXlOZXh0U29uZ0luQWxidW0oKSB7CiAgICAgICAgICAgIC4uLgogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZW5kQWN0aW9uCiAgICAgIEBwYXJhbSBbYWN0aW9uXSB7U3RyaW5nfSB0aGUgYWN0aW9uIHRvIGNhbGwKICAgICAgQHBhcmFtIFtwYXJhbXNdIHsqfSBhcmd1bWVudHMgZm9yIHRoZSBhY3Rpb24KICAgICAgQHB1YmxpYwogICAgICBAZGVwcmVjYXRlZAogICAgKi8KICAgIHZhciBzZW5kQWN0aW9uID0gZnVuY3Rpb24gc2VuZEFjdGlvbihhY3Rpb24pIHsKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF0dGVtcHRlZCB0byBjYWxsIC5zZW5kQWN0aW9uKCkgd2l0aCB0aGUgYWN0aW9uICciICsgYWN0aW9uICsgIicgb24gdGhlIGRlc3Ryb3llZCBvYmplY3QgJyIgKyB0aGlzICsgIicuIiwgIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIllvdSBjYWxsZWQgIiArICgwLCBfdXRpbHMuaW5zcGVjdCkodGhpcykgKyAiLnNlbmRBY3Rpb24oIiArICh0eXBlb2YgYWN0aW9uID09PSAnc3RyaW5nJyA/ICJcIiIgKyBhY3Rpb24gKyAiXCIiIDogJycpICsgIikgYnV0IENvbXBvbmVudCNzZW5kQWN0aW9uIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgY2xvc3VyZSBhY3Rpb25zIGluc3RlYWQuIiwgZmFsc2UsIHsKICAgICAgICBpZDogJ2VtYmVyLWNvbXBvbmVudC5zZW5kLWFjdGlvbicsCiAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfZW1iZXItY29tcG9uZW50LXNlbmQtYWN0aW9uJwogICAgICB9KSk7CiAgICAgIHZhciBhY3Rpb25OYW1lOyAvLyBTZW5kIHRoZSBkZWZhdWx0IGFjdGlvbgoKICAgICAgaWYgKGFjdGlvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgYWN0aW9uID0gJ2FjdGlvbic7CiAgICAgIH0KCiAgICAgIGFjdGlvbk5hbWUgPSAoMCwgX21ldGFsLmdldCkodGhpcywgImF0dHJzLiIgKyBhY3Rpb24pIHx8ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBhY3Rpb24pOwogICAgICBhY3Rpb25OYW1lID0gdmFsaWRhdGVBY3Rpb24odGhpcywgYWN0aW9uTmFtZSk7IC8vIElmIG5vIGFjdGlvbiBuYW1lIGZvciB0aGF0IGFjdGlvbiBjb3VsZCBiZSBmb3VuZCwganVzdCBhYm9ydC4KCiAgICAgIGlmIChhY3Rpb25OYW1lID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGZvciAodmFyIF9sZW4yID0gYXJndW1lbnRzLmxlbmd0aCwgY29udGV4dHMgPSBuZXcgQXJyYXkoX2xlbjIgPiAxID8gX2xlbjIgLSAxIDogMCksIF9rZXkyID0gMTsgX2tleTIgPCBfbGVuMjsgX2tleTIrKykgewogICAgICAgIGNvbnRleHRzW19rZXkyIC0gMV0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICB9CgogICAgICBpZiAodHlwZW9mIGFjdGlvbk5hbWUgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICBhY3Rpb25OYW1lLmFwcGx5KHZvaWQgMCwgY29udGV4dHMpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMudHJpZ2dlckFjdGlvbih7CiAgICAgICAgICBhY3Rpb246IGFjdGlvbk5hbWUsCiAgICAgICAgICBhY3Rpb25Db250ZXh0OiBjb250ZXh0cwogICAgICAgIH0pOwogICAgICB9CiAgICB9OwoKICAgIHZhciB2YWxpZGF0ZUFjdGlvbiA9IGZ1bmN0aW9uIHZhbGlkYXRlQWN0aW9uKGNvbXBvbmVudCwgYWN0aW9uTmFtZSkgewogICAgICBpZiAoYWN0aW9uTmFtZSAmJiBhY3Rpb25OYW1lW19hdHRycy5NVVRBQkxFX0NFTExdKSB7CiAgICAgICAgYWN0aW9uTmFtZSA9IGFjdGlvbk5hbWUudmFsdWU7CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKGFjdGlvbk5hbWUgPT09IG51bGwgfHwgYWN0aW9uTmFtZSA9PT0gdW5kZWZpbmVkIHx8IHR5cGVvZiBhY3Rpb25OYW1lID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgZGVmYXVsdCBhY3Rpb24gd2FzIHRyaWdnZXJlZCBvbiB0aGUgY29tcG9uZW50ICIgKyBjb21wb25lbnQudG9TdHJpbmcoKSArICIsIGJ1dCB0aGUgYWN0aW9uIG5hbWUgKCIgKyBhY3Rpb25OYW1lICsgIikgd2FzIG5vdCBhIHN0cmluZy4iLCBhY3Rpb25OYW1lID09PSBudWxsIHx8IGFjdGlvbk5hbWUgPT09IHVuZGVmaW5lZCB8fCB0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGFjdGlvbk5hbWUgPT09ICdmdW5jdGlvbicpKTsKICAgICAgcmV0dXJuIGFjdGlvbk5hbWU7CiAgICB9OwoKICAgIG1peGluT2JqLnNlbmRBY3Rpb24gPSBzZW5kQWN0aW9uOwogIH0KICAvKioKICAgQGNsYXNzIEFjdGlvblN1cHBvcnQKICAgQG5hbWVzcGFjZSBFbWJlcgogICBAcHJpdmF0ZQogICovCgoKICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKG1peGluT2JqKTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvbWl4aW5zL2NoaWxkX3ZpZXdzX3N1cHBvcnQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3N5c3RlbS91dGlscyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX3V0aWxzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIC8qKgogICAgICBBcnJheSBvZiBjaGlsZCB2aWV3cy4gWW91IHNob3VsZCBuZXZlciBlZGl0IHRoaXMgYXJyYXkgZGlyZWN0bHkuCiAgICAgICBAcHJvcGVydHkgY2hpbGRWaWV3cwogICAgICBAdHlwZSBBcnJheQogICAgICBAZGVmYXVsdCBbXQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGNoaWxkVmlld3M6ICgwLCBfbWV0YWwubmF0aXZlRGVzY0RlY29yYXRvcikoewogICAgICBjb25maWd1cmFibGU6IGZhbHNlLAogICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuICgwLCBfdXRpbHMuZ2V0Q2hpbGRWaWV3cykodGhpcyk7CiAgICAgIH0KICAgIH0pLAogICAgYXBwZW5kQ2hpbGQ6IGZ1bmN0aW9uIGFwcGVuZENoaWxkKHZpZXcpIHsKICAgICAgKDAsIF91dGlscy5hZGRDaGlsZFZpZXcpKHRoaXMsIHZpZXcpOwogICAgfQogIH0pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9taXhpbnMvY2xhc3NfbmFtZXNfc3VwcG9ydCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwsIF9kZWJ1ZykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCiAgdmFyIEVNUFRZX0FSUkFZID0gT2JqZWN0LmZyZWV6ZShbXSk7CiAgLyoqCiAgICBAY2xhc3MgQ2xhc3NOYW1lc1N1cHBvcnQKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEBwcml2YXRlCiAgKi8KCiAgdmFyIF9kZWZhdWx0ID0gX21ldGFsLk1peGluLmNyZWF0ZSh7CiAgICBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzOiBbJ2NsYXNzTmFtZXMnLCAnY2xhc3NOYW1lQmluZGluZ3MnXSwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAoZmFsc2UgJiYgISgoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JQcm9wZXJ0eSkodGhpcywgJ2NsYXNzTmFtZUJpbmRpbmdzJykgPT09IHVuZGVmaW5lZCAmJiBBcnJheS5pc0FycmF5KHRoaXMuY2xhc3NOYW1lQmluZGluZ3MpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIk9ubHkgYXJyYXlzIGFyZSBhbGxvd2VkIGZvciAnY2xhc3NOYW1lQmluZGluZ3MnIiwgKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKHRoaXMsICdjbGFzc05hbWVCaW5kaW5ncycpID09PSB1bmRlZmluZWQgJiYgQXJyYXkuaXNBcnJheSh0aGlzLmNsYXNzTmFtZUJpbmRpbmdzKSkpOwogICAgICAoZmFsc2UgJiYgISgoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JQcm9wZXJ0eSkodGhpcywgJ2NsYXNzTmFtZXMnKSA9PT0gdW5kZWZpbmVkICYmIEFycmF5LmlzQXJyYXkodGhpcy5jbGFzc05hbWVzKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJPbmx5IGFycmF5cyBvZiBzdGF0aWMgY2xhc3Mgc3RyaW5ncyBhcmUgYWxsb3dlZCBmb3IgJ2NsYXNzTmFtZXMnLiBGb3IgZHluYW1pYyBjbGFzc2VzLCB1c2UgJ2NsYXNzTmFtZUJpbmRpbmdzJy4iLCAoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JQcm9wZXJ0eSkodGhpcywgJ2NsYXNzTmFtZXMnKSA9PT0gdW5kZWZpbmVkICYmIEFycmF5LmlzQXJyYXkodGhpcy5jbGFzc05hbWVzKSkpOwogICAgfSwKCiAgICAvKioKICAgICAgU3RhbmRhcmQgQ1NTIGNsYXNzIG5hbWVzIHRvIGFwcGx5IHRvIHRoZSB2aWV3J3Mgb3V0ZXIgZWxlbWVudC4gVGhpcwogICAgICBwcm9wZXJ0eSBhdXRvbWF0aWNhbGx5IGluaGVyaXRzIGFueSBjbGFzcyBuYW1lcyBkZWZpbmVkIGJ5IHRoZSB2aWV3J3MKICAgICAgc3VwZXJjbGFzc2VzIGFzIHdlbGwuCiAgICAgICBAcHJvcGVydHkgY2xhc3NOYW1lcwogICAgICBAdHlwZSBBcnJheQogICAgICBAZGVmYXVsdCBbJ2VtYmVyLXZpZXcnXQogICAgICBAcHVibGljCiAgICAqLwogICAgY2xhc3NOYW1lczogRU1QVFlfQVJSQVksCgogICAgLyoqCiAgICAgIEEgbGlzdCBvZiBwcm9wZXJ0aWVzIG9mIHRoZSB2aWV3IHRvIGFwcGx5IGFzIGNsYXNzIG5hbWVzLiBJZiB0aGUgcHJvcGVydHkKICAgICAgaXMgYSBzdHJpbmcgdmFsdWUsIHRoZSB2YWx1ZSBvZiB0aGF0IHN0cmluZyB3aWxsIGJlIGFwcGxpZWQgYXMgYSBjbGFzcwogICAgICBuYW1lLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICAvLyBBcHBsaWVzIHRoZSAnaGlnaCcgY2xhc3MgdG8gdGhlIHZpZXcgZWxlbWVudAogICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICBjbGFzc05hbWVCaW5kaW5nczogWydwcmlvcml0eSddLAogICAgICAgIHByaW9yaXR5OiAnaGlnaCcKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgSWYgdGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSBpcyBhIEJvb2xlYW4sIHRoZSBuYW1lIG9mIHRoYXQgcHJvcGVydHkgaXMKICAgICAgYWRkZWQgYXMgYSBkYXNoZXJpemVkIGNsYXNzIG5hbWUuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIC8vIEFwcGxpZXMgdGhlICdpcy11cmdlbnQnIGNsYXNzIHRvIHRoZSB2aWV3IGVsZW1lbnQKICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgY2xhc3NOYW1lQmluZGluZ3M6IFsnaXNVcmdlbnQnXSwKICAgICAgICBpc1VyZ2VudDogdHJ1ZQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBJZiB5b3Ugd291bGQgcHJlZmVyIHRvIHVzZSBhIGN1c3RvbSB2YWx1ZSBpbnN0ZWFkIG9mIHRoZSBkYXNoZXJpemVkCiAgICAgIHByb3BlcnR5IG5hbWUsIHlvdSBjYW4gcGFzcyBhIGJpbmRpbmcgbGlrZSB0aGlzOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICAvLyBBcHBsaWVzIHRoZSAndXJnZW50JyBjbGFzcyB0byB0aGUgdmlldyBlbGVtZW50CiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIENvbXBvbmVudC5leHRlbmQoewogICAgICAgIGNsYXNzTmFtZUJpbmRpbmdzOiBbJ2lzVXJnZW50OnVyZ2VudCddLAogICAgICAgIGlzVXJnZW50OiB0cnVlCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIElmIHlvdSB3b3VsZCBsaWtlIHRvIHNwZWNpZnkgYSBjbGFzcyB0aGF0IHNob3VsZCBvbmx5IGJlIGFkZGVkIHdoZW4gdGhlCiAgICAgIHByb3BlcnR5IGlzIGZhbHNlLCB5b3UgY2FuIGRlY2xhcmUgYSBiaW5kaW5nIGxpa2UgdGhpczoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgLy8gQXBwbGllcyB0aGUgJ2Rpc2FibGVkJyBjbGFzcyB0byB0aGUgdmlldyBlbGVtZW50CiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIENvbXBvbmVudC5leHRlbmQoewogICAgICAgIGNsYXNzTmFtZUJpbmRpbmdzOiBbJ2lzRW5hYmxlZDo6ZGlzYWJsZWQnXSwKICAgICAgICBpc0VuYWJsZWQ6IGZhbHNlCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRoaXMgbGlzdCBvZiBwcm9wZXJ0aWVzIGlzIGluaGVyaXRlZCBmcm9tIHRoZSBjb21wb25lbnQncyBzdXBlcmNsYXNzZXMgYXMgd2VsbC4KICAgICAgIEBwcm9wZXJ0eSBjbGFzc05hbWVCaW5kaW5ncwogICAgICBAdHlwZSBBcnJheQogICAgICBAZGVmYXVsdCBbXQogICAgICBAcHVibGljCiAgICAqLwogICAgY2xhc3NOYW1lQmluZGluZ3M6IEVNUFRZX0FSUkFZCiAgfSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL21peGlucy90ZXh0X3N1cHBvcnQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwsIF9ydW50aW1lLCBfZGVidWcsIF9kZXByZWNhdGVkRmVhdHVyZXMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwogIHZhciBLRVlfRVZFTlRTID0gewogICAgMTM6ICdpbnNlcnROZXdsaW5lJywKICAgIDI3OiAnY2FuY2VsJwogIH07CiAgLyoqCiAgICBgVGV4dFN1cHBvcnRgIGlzIGEgc2hhcmVkIG1peGluIHVzZWQgYnkgYm90aCBgVGV4dEZpZWxkYCBhbmQKICAgIGBUZXh0QXJlYWAuIGBUZXh0U3VwcG9ydGAgYWRkcyBhIG51bWJlciBvZiBtZXRob2RzIHRoYXQgYWxsb3cgeW91IHRvCiAgICBzcGVjaWZ5IGEgY29udHJvbGxlciBhY3Rpb24gdG8gaW52b2tlIHdoZW4gYSBjZXJ0YWluIGV2ZW50IGlzIGZpcmVkIG9uIHlvdXIKICAgIHRleHQgZmllbGQgb3IgdGV4dGFyZWEuIFRoZSBzcGVjaWZpZWQgY29udHJvbGxlciBhY3Rpb24gd291bGQgZ2V0IHRoZSBjdXJyZW50CiAgICB2YWx1ZSBvZiB0aGUgZmllbGQgcGFzc2VkIGluIGFzIHRoZSBvbmx5IGFyZ3VtZW50IHVubGVzcyB0aGUgdmFsdWUgb2YKICAgIHRoZSBmaWVsZCBpcyBlbXB0eS4gSW4gdGhhdCBjYXNlLCB0aGUgaW5zdGFuY2Ugb2YgdGhlIGZpZWxkIGl0c2VsZiBpcyBwYXNzZWQKICAgIGluIGFzIHRoZSBvbmx5IGFyZ3VtZW50LgogIAogICAgTGV0J3MgdXNlIHRoZSBwcmVzc2luZyBvZiB0aGUgZXNjYXBlIGtleSBhcyBhbiBleGFtcGxlLiBJZiB5b3Ugd2FudGVkIHRvCiAgICBpbnZva2UgYSBjb250cm9sbGVyIGFjdGlvbiB3aGVuIGEgdXNlciBwcmVzc2VzIHRoZSBlc2NhcGUga2V5IHdoaWxlIG9uIHlvdXIKICAgIGZpZWxkLCB5b3Ugd291bGQgdXNlIHRoZSBgZXNjYXBlLXByZXNzYCBhdHRyaWJ1dGUgb24geW91ciBmaWVsZCBsaWtlIHNvOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgICB7eyEgYXBwbGljYXRpb24uaGJzfX0KICAKICAgICAge3tpbnB1dCBlc2NhcGUtcHJlc3M9J2FsZXJ0VXNlcid9fQogICAgYGBgCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICAgICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgICAgaW1wb3J0IENvbnRyb2xsZXIgZnJvbSAnQGVtYmVyL2NvbnRyb2xsZXInOwogICAgICAgIEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSgpOwogIAogICAgICAgIEFwcC5BcHBsaWNhdGlvbkNvbnRyb2xsZXIgPSBDb250cm9sbGVyLmV4dGVuZCh7CiAgICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICAgIGFsZXJ0VXNlcjogZnVuY3Rpb24gKCBjdXJyZW50VmFsdWUgKSB7CiAgICAgICAgICAgICAgYWxlcnQoICdlc2NhcGUgcHJlc3NlZCwgY3VycmVudCB2YWx1ZTogJyArIGN1cnJlbnRWYWx1ZSApOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICBgYGAKICAKICAgIFRoZSBmb2xsb3dpbmcgY2hhcnQgaXMgYSB2aXN1YWwgcmVwcmVzZW50YXRpb24gb2Ygd2hhdCB0YWtlcyBwbGFjZSB3aGVuIHRoZQogICAgZXNjYXBlIGtleSBpcyBwcmVzc2VkIGluIHRoaXMgc2NlbmFyaW86CiAgCiAgICBgYGAKICAgIFRoZSBUZW1wbGF0ZQogICAgKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICB8IGVzY2FwZS1wcmVzcz0nYWxlcnRVc2VyJyAgfAogICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgVGV4dFN1cHBvcnQgTWl4aW4KICAgICstLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rICAgICAgICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKwogICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBjYW5jZWwgbWV0aG9kICAgICAgICAgICAgICAgICB8CiAgICAgICAgIHwgICAgICBlc2NhcGUgYnV0dG9uIHByZXNzZWQgICAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKICAgICAgICAgKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+IHwgY2hlY2tzIGZvciB0aGUgYGVzY2FwZS1wcmVzc2AgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBhdHRyaWJ1dGUgYW5kIHB1bGxzIG91dCB0aGUgICB8CiAgICAgICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKyB8IGBhbGVydFVzZXJgIHZhbHVlICAgICAgICAgICAgIHwKICAgICAgICAgfCAgICAgYWN0aW9uIG5hbWUgJ2FsZXJ0VXNlcicgICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKwogICAgICAgICB8ICAgICBzZW50IHRvIGNvbnRyb2xsZXIKICAgICAgICAgdgogICAgQ29udHJvbGxlcgogICAgKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSArCiAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKICAgIHwgIGFjdGlvbnM6IHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAogICAgfCAgICAgYWxlcnRVc2VyOiBmdW5jdGlvbiggY3VycmVudFZhbHVlICl7ICB8CiAgICB8ICAgICAgIGFsZXJ0KCAndGhlIGVzYyBrZXkgd2FzIHByZXNzZWQhJyApIHwKICAgIHwgICAgIH0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAogICAgfCAgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKwogICAgYGBgCiAgCiAgICBIZXJlIGFyZSB0aGUgZXZlbnRzIHRoYXQgd2UgY3VycmVudGx5IHN1cHBvcnQgYWxvbmcgd2l0aCB0aGUgbmFtZSBvZiB0aGUKICAgIGF0dHJpYnV0ZSB5b3Ugd291bGQgbmVlZCB0byB1c2Ugb24geW91ciBmaWVsZC4gVG8gcmVpdGVyYXRlLCB5b3Ugd291bGQgdXNlIHRoZQogICAgYXR0cmlidXRlIG5hbWUgbGlrZSBzbzoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgICAge3tpbnB1dCBhdHRyaWJ1dGUtbmFtZT0nY29udHJvbGxlckFjdGlvbid9fQogICAgYGBgCiAgCiAgICBgYGAKICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tKwogICAgfCAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICB8CiAgICB8IGV2ZW50ICAgICAgICAgICAgICB8IGF0dHJpYnV0ZSBuYW1lIHwKICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tKwogICAgfCBuZXcgbGluZSBpbnNlcnRlZCAgfCBpbnNlcnQtbmV3bGluZSB8CiAgICB8ICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgIHwKICAgIHwgZW50ZXIga2V5IHByZXNzZWQgIHwgZW50ZXIgICAgICAgICAgfAogICAgfCAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICB8CiAgICB8IGNhbmNlbCBrZXkgcHJlc3NlZCB8IGVzY2FwZS1wcmVzcyAgIHwKICAgIHwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgfAogICAgfCBmb2N1c2luICAgICAgICAgICAgfCBmb2N1cy1pbiAgICAgICB8CiAgICB8ICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgIHwKICAgIHwgZm9jdXNvdXQgICAgICAgICAgIHwgZm9jdXMtb3V0ICAgICAgfAogICAgfCAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICB8CiAgICB8IGtleXByZXNzICAgICAgICAgICB8IGtleS1wcmVzcyAgICAgIHwKICAgIHwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgfAogICAgfCBrZXl1cCAgICAgICAgICAgICAgfCBrZXktdXAgICAgICAgICB8CiAgICB8ICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgIHwKICAgIHwga2V5ZG93biAgICAgICAgICAgIHwga2V5LWRvd24gICAgICAgfAogICAgKy0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0rCiAgICBgYGAKICAKICAgIEBjbGFzcyBUZXh0U3VwcG9ydAogICAgQG5hbWVzcGFjZSBFbWJlcgogICAgQHVzZXMgRW1iZXIuVGFyZ2V0QWN0aW9uU3VwcG9ydAogICAgQGV4dGVuZHMgTWl4aW4KICAgIEBwcml2YXRlCiAgKi8KCiAgdmFyIF9kZWZhdWx0ID0gX21ldGFsLk1peGluLmNyZWF0ZShfcnVudGltZS5UYXJnZXRBY3Rpb25TdXBwb3J0LCB7CiAgICB2YWx1ZTogJycsCiAgICBhdHRyaWJ1dGVCaW5kaW5nczogWydhdXRvY2FwaXRhbGl6ZScsICdhdXRvY29ycmVjdCcsICdhdXRvZm9jdXMnLCAnZGlzYWJsZWQnLCAnZm9ybScsICdtYXhsZW5ndGgnLCAnbWlubGVuZ3RoJywgJ3BsYWNlaG9sZGVyJywgJ3JlYWRvbmx5JywgJ3JlcXVpcmVkJywgJ3NlbGVjdGlvbkRpcmVjdGlvbicsICdzcGVsbGNoZWNrJywgJ3RhYmluZGV4JywgJ3RpdGxlJ10sCiAgICBwbGFjZWhvbGRlcjogbnVsbCwKICAgIGRpc2FibGVkOiBmYWxzZSwKICAgIG1heGxlbmd0aDogbnVsbCwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzLm9uKCdwYXN0ZScsIHRoaXMsIHRoaXMuX2VsZW1lbnRWYWx1ZURpZENoYW5nZSk7CiAgICAgIHRoaXMub24oJ2N1dCcsIHRoaXMsIHRoaXMuX2VsZW1lbnRWYWx1ZURpZENoYW5nZSk7CiAgICAgIHRoaXMub24oJ2lucHV0JywgdGhpcywgdGhpcy5fZWxlbWVudFZhbHVlRGlkQ2hhbmdlKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFdoZXRoZXIgdGhlIGBrZXlVcGAgZXZlbnQgdGhhdCB0cmlnZ2VycyBhbiBgYWN0aW9uYCB0byBiZSBzZW50IGNvbnRpbnVlcwogICAgICBwcm9wYWdhdGluZyB0byBvdGhlciB2aWV3cy4KICAgICAgIEJ5IGRlZmF1bHQsIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyB0aGUgcmV0dXJuIGtleSBvbiB0aGVpciBrZXlib2FyZCBhbmQKICAgICAgdGhlIHRleHQgZmllbGQgaGFzIGFuIGBhY3Rpb25gIHNldCwgdGhlIGFjdGlvbiB3aWxsIGJlIHNlbnQgdG8gdGhlIHZpZXcncwogICAgICBjb250cm9sbGVyIGFuZCB0aGUga2V5IGV2ZW50IHdpbGwgc3RvcCBwcm9wYWdhdGluZy4KICAgICAgIElmIHlvdSB3b3VsZCBsaWtlIHBhcmVudCB2aWV3cyB0byByZWNlaXZlIHRoZSBga2V5VXBgIGV2ZW50IGV2ZW4gYWZ0ZXIgYW4KICAgICAgYWN0aW9uIGhhcyBiZWVuIGRpc3BhdGNoZWQsIHNldCBgYnViYmxlc2AgdG8gdHJ1ZS4KICAgICAgIEBwcm9wZXJ0eSBidWJibGVzCiAgICAgIEB0eXBlIEJvb2xlYW4KICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgQHByaXZhdGUKICAgICovCiAgICBidWJibGVzOiBmYWxzZSwKICAgIGludGVycHJldEtleUV2ZW50czogZnVuY3Rpb24gaW50ZXJwcmV0S2V5RXZlbnRzKGV2ZW50KSB7CiAgICAgIHZhciBtYXAgPSBLRVlfRVZFTlRTOwogICAgICB2YXIgbWV0aG9kID0gbWFwW2V2ZW50LmtleUNvZGVdOwoKICAgICAgdGhpcy5fZWxlbWVudFZhbHVlRGlkQ2hhbmdlKCk7CgogICAgICBpZiAobWV0aG9kKSB7CiAgICAgICAgcmV0dXJuIHRoaXNbbWV0aG9kXShldmVudCk7CiAgICAgIH0KICAgIH0sCiAgICBfZWxlbWVudFZhbHVlRGlkQ2hhbmdlOiBmdW5jdGlvbiBfZWxlbWVudFZhbHVlRGlkQ2hhbmdlKCkgewogICAgICAoMCwgX21ldGFsLnNldCkodGhpcywgJ3ZhbHVlJywgdGhpcy5lbGVtZW50LnZhbHVlKTsKICAgIH0sCiAgICBjaGFuZ2U6IGZ1bmN0aW9uIGNoYW5nZShldmVudCkgewogICAgICB0aGlzLl9lbGVtZW50VmFsdWVEaWRDaGFuZ2UoZXZlbnQpOwogICAgfSwKCiAgICAvKioKICAgICAgQWxsb3dzIHlvdSB0byBzcGVjaWZ5IGEgY29udHJvbGxlciBhY3Rpb24gdG8gaW52b2tlIHdoZW4gZWl0aGVyIHRoZSBgZW50ZXJgCiAgICAgIGtleSBpcyBwcmVzc2VkIG9yLCBpbiB0aGUgY2FzZSBvZiB0aGUgZmllbGQgYmVpbmcgYSB0ZXh0YXJlYSwgd2hlbiBhIG5ld2xpbmUKICAgICAgaXMgaW5zZXJ0ZWQuIFRvIHVzZSB0aGlzIG1ldGhvZCwgZ2l2ZSB5b3VyIGZpZWxkIGFuIGBpbnNlcnQtbmV3bGluZWAKICAgICAgYXR0cmlidXRlLiBUaGUgdmFsdWUgb2YgdGhhdCBhdHRyaWJ1dGUgc2hvdWxkIGJlIHRoZSBuYW1lIG9mIHRoZSBhY3Rpb24KICAgICAgaW4geW91ciBjb250cm9sbGVyIHRoYXQgeW91IHdpc2ggdG8gaW52b2tlLgogICAgICAgRm9yIGFuIGV4YW1wbGUgb24gaG93IHRvIHVzZSB0aGUgYGluc2VydC1uZXdsaW5lYCBhdHRyaWJ1dGUsIHBsZWFzZQogICAgICByZWZlcmVuY2UgdGhlIGV4YW1wbGUgbmVhciB0aGUgdG9wIG9mIHRoaXMgZmlsZS4KICAgICAgIEBtZXRob2QgaW5zZXJ0TmV3bGluZQogICAgICBAcGFyYW0ge0V2ZW50fSBldmVudAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGluc2VydE5ld2xpbmU6IGZ1bmN0aW9uIGluc2VydE5ld2xpbmUoZXZlbnQpIHsKICAgICAgc2VuZEFjdGlvbignZW50ZXInLCB0aGlzLCBldmVudCk7CiAgICAgIHNlbmRBY3Rpb24oJ2luc2VydC1uZXdsaW5lJywgdGhpcywgZXZlbnQpOwogICAgfSwKCiAgICAvKioKICAgICAgQWxsb3dzIHlvdSB0byBzcGVjaWZ5IGEgY29udHJvbGxlciBhY3Rpb24gdG8gaW52b2tlIHdoZW4gdGhlIGVzY2FwZSBidXR0b24KICAgICAgaXMgcHJlc3NlZC4gVG8gdXNlIHRoaXMgbWV0aG9kLCBnaXZlIHlvdXIgZmllbGQgYW4gYGVzY2FwZS1wcmVzc2AKICAgICAgYXR0cmlidXRlLiBUaGUgdmFsdWUgb2YgdGhhdCBhdHRyaWJ1dGUgc2hvdWxkIGJlIHRoZSBuYW1lIG9mIHRoZSBhY3Rpb24KICAgICAgaW4geW91ciBjb250cm9sbGVyIHRoYXQgeW91IHdpc2ggdG8gaW52b2tlLgogICAgICAgRm9yIGFuIGV4YW1wbGUgb24gaG93IHRvIHVzZSB0aGUgYGVzY2FwZS1wcmVzc2AgYXR0cmlidXRlLCBwbGVhc2UgcmVmZXJlbmNlCiAgICAgIHRoZSBleGFtcGxlIG5lYXIgdGhlIHRvcCBvZiB0aGlzIGZpbGUuCiAgICAgICBAbWV0aG9kIGNhbmNlbAogICAgICBAcGFyYW0ge0V2ZW50fSBldmVudAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGNhbmNlbDogZnVuY3Rpb24gY2FuY2VsKGV2ZW50KSB7CiAgICAgIHNlbmRBY3Rpb24oJ2VzY2FwZS1wcmVzcycsIHRoaXMsIGV2ZW50KTsKICAgIH0sCgogICAgLyoqCiAgICAgIEFsbG93cyB5b3UgdG8gc3BlY2lmeSBhIGNvbnRyb2xsZXIgYWN0aW9uIHRvIGludm9rZSB3aGVuIGEgZmllbGQgcmVjZWl2ZXMKICAgICAgZm9jdXMuIFRvIHVzZSB0aGlzIG1ldGhvZCwgZ2l2ZSB5b3VyIGZpZWxkIGEgYGZvY3VzLWluYCBhdHRyaWJ1dGUuIFRoZSB2YWx1ZQogICAgICBvZiB0aGF0IGF0dHJpYnV0ZSBzaG91bGQgYmUgdGhlIG5hbWUgb2YgdGhlIGFjdGlvbiBpbiB5b3VyIGNvbnRyb2xsZXIKICAgICAgdGhhdCB5b3Ugd2lzaCB0byBpbnZva2UuCiAgICAgICBGb3IgYW4gZXhhbXBsZSBvbiBob3cgdG8gdXNlIHRoZSBgZm9jdXMtaW5gIGF0dHJpYnV0ZSwgcGxlYXNlIHJlZmVyZW5jZSB0aGUKICAgICAgZXhhbXBsZSBuZWFyIHRoZSB0b3Agb2YgdGhpcyBmaWxlLgogICAgICAgQG1ldGhvZCBmb2N1c0luCiAgICAgIEBwYXJhbSB7RXZlbnR9IGV2ZW50CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgZm9jdXNJbjogZnVuY3Rpb24gZm9jdXNJbihldmVudCkgewogICAgICBzZW5kQWN0aW9uKCdmb2N1cy1pbicsIHRoaXMsIGV2ZW50KTsKICAgIH0sCgogICAgLyoqCiAgICAgIEFsbG93cyB5b3UgdG8gc3BlY2lmeSBhIGNvbnRyb2xsZXIgYWN0aW9uIHRvIGludm9rZSB3aGVuIGEgZmllbGQgbG9zZXMKICAgICAgZm9jdXMuIFRvIHVzZSB0aGlzIG1ldGhvZCwgZ2l2ZSB5b3VyIGZpZWxkIGEgYGZvY3VzLW91dGAgYXR0cmlidXRlLiBUaGUgdmFsdWUKICAgICAgb2YgdGhhdCBhdHRyaWJ1dGUgc2hvdWxkIGJlIHRoZSBuYW1lIG9mIHRoZSBhY3Rpb24gaW4geW91ciBjb250cm9sbGVyCiAgICAgIHRoYXQgeW91IHdpc2ggdG8gaW52b2tlLgogICAgICAgRm9yIGFuIGV4YW1wbGUgb24gaG93IHRvIHVzZSB0aGUgYGZvY3VzLW91dGAgYXR0cmlidXRlLCBwbGVhc2UgcmVmZXJlbmNlIHRoZQogICAgICBleGFtcGxlIG5lYXIgdGhlIHRvcCBvZiB0aGlzIGZpbGUuCiAgICAgICBAbWV0aG9kIGZvY3VzT3V0CiAgICAgIEBwYXJhbSB7RXZlbnR9IGV2ZW50CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgZm9jdXNPdXQ6IGZ1bmN0aW9uIGZvY3VzT3V0KGV2ZW50KSB7CiAgICAgIHRoaXMuX2VsZW1lbnRWYWx1ZURpZENoYW5nZShldmVudCk7CgogICAgICBzZW5kQWN0aW9uKCdmb2N1cy1vdXQnLCB0aGlzLCBldmVudCk7CiAgICB9LAoKICAgIC8qKgogICAgICBBbGxvd3MgeW91IHRvIHNwZWNpZnkgYSBjb250cm9sbGVyIGFjdGlvbiB0byBpbnZva2Ugd2hlbiBhIGtleSBpcyBwcmVzc2VkLgogICAgICBUbyB1c2UgdGhpcyBtZXRob2QsIGdpdmUgeW91ciBmaWVsZCBhIGBrZXktcHJlc3NgIGF0dHJpYnV0ZS4gVGhlIHZhbHVlIG9mCiAgICAgIHRoYXQgYXR0cmlidXRlIHNob3VsZCBiZSB0aGUgbmFtZSBvZiB0aGUgYWN0aW9uIGluIHlvdXIgY29udHJvbGxlciB5b3UKICAgICAgdGhhdCB3aXNoIHRvIGludm9rZS4KICAgICAgIEZvciBhbiBleGFtcGxlIG9uIGhvdyB0byB1c2UgdGhlIGBrZXktcHJlc3NgIGF0dHJpYnV0ZSwgcGxlYXNlIHJlZmVyZW5jZSB0aGUKICAgICAgZXhhbXBsZSBuZWFyIHRoZSB0b3Agb2YgdGhpcyBmaWxlLgogICAgICAgQG1ldGhvZCBrZXlQcmVzcwogICAgICBAcGFyYW0ge0V2ZW50fSBldmVudAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGtleVByZXNzOiBmdW5jdGlvbiBrZXlQcmVzcyhldmVudCkgewogICAgICBzZW5kQWN0aW9uKCdrZXktcHJlc3MnLCB0aGlzLCBldmVudCk7CiAgICB9LAoKICAgIC8qKgogICAgICBBbGxvd3MgeW91IHRvIHNwZWNpZnkgYSBjb250cm9sbGVyIGFjdGlvbiB0byBpbnZva2Ugd2hlbiBhIGtleS11cCBldmVudCBpcwogICAgICBmaXJlZC4gVG8gdXNlIHRoaXMgbWV0aG9kLCBnaXZlIHlvdXIgZmllbGQgYSBga2V5LXVwYCBhdHRyaWJ1dGUuIFRoZSB2YWx1ZQogICAgICBvZiB0aGF0IGF0dHJpYnV0ZSBzaG91bGQgYmUgdGhlIG5hbWUgb2YgdGhlIGFjdGlvbiBpbiB5b3VyIGNvbnRyb2xsZXIKICAgICAgdGhhdCB5b3Ugd2lzaCB0byBpbnZva2UuCiAgICAgICBGb3IgYW4gZXhhbXBsZSBvbiBob3cgdG8gdXNlIHRoZSBga2V5LXVwYCBhdHRyaWJ1dGUsIHBsZWFzZSByZWZlcmVuY2UgdGhlCiAgICAgIGV4YW1wbGUgbmVhciB0aGUgdG9wIG9mIHRoaXMgZmlsZS4KICAgICAgIEBtZXRob2Qga2V5VXAKICAgICAgQHBhcmFtIHtFdmVudH0gZXZlbnQKICAgICAgQHByaXZhdGUKICAgICovCiAgICBrZXlVcDogZnVuY3Rpb24ga2V5VXAoZXZlbnQpIHsKICAgICAgdGhpcy5pbnRlcnByZXRLZXlFdmVudHMoZXZlbnQpOwogICAgICBzZW5kQWN0aW9uKCdrZXktdXAnLCB0aGlzLCBldmVudCk7CiAgICB9LAoKICAgIC8qKgogICAgICBBbGxvd3MgeW91IHRvIHNwZWNpZnkgYSBjb250cm9sbGVyIGFjdGlvbiB0byBpbnZva2Ugd2hlbiBhIGtleS1kb3duIGV2ZW50IGlzCiAgICAgIGZpcmVkLiBUbyB1c2UgdGhpcyBtZXRob2QsIGdpdmUgeW91ciBmaWVsZCBhIGBrZXktZG93bmAgYXR0cmlidXRlLiBUaGUgdmFsdWUKICAgICAgb2YgdGhhdCBhdHRyaWJ1dGUgc2hvdWxkIGJlIHRoZSBuYW1lIG9mIHRoZSBhY3Rpb24gaW4geW91ciBjb250cm9sbGVyIHRoYXQKICAgICAgeW91IHdpc2ggdG8gaW52b2tlLgogICAgICAgRm9yIGFuIGV4YW1wbGUgb24gaG93IHRvIHVzZSB0aGUgYGtleS1kb3duYCBhdHRyaWJ1dGUsIHBsZWFzZSByZWZlcmVuY2UgdGhlCiAgICAgIGV4YW1wbGUgbmVhciB0aGUgdG9wIG9mIHRoaXMgZmlsZS4KICAgICAgIEBtZXRob2Qga2V5RG93bgogICAgICBAcGFyYW0ge0V2ZW50fSBldmVudAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGtleURvd246IGZ1bmN0aW9uIGtleURvd24oZXZlbnQpIHsKICAgICAgc2VuZEFjdGlvbigna2V5LWRvd24nLCB0aGlzLCBldmVudCk7CiAgICB9CiAgfSk7IC8vIEluIHByaW5jaXBsZSwgdGhpcyBzaG91bGRuJ3QgYmUgbmVjZXNzYXJ5LCBidXQgdGhlIGxlZ2FjeQogIC8vIHNlbmRBY3Rpb24gc2VtYW50aWNzIGZvciBUZXh0RmllbGQgYXJlIGRpZmZlcmVudCBmcm9tCiAgLy8gdGhlIGNvbXBvbmVudCBzZW1hbnRpY3Mgc28gdGhpcyBtZXRob2Qgbm9ybWFsaXplcyB0aGVtLgoKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OwoKICBmdW5jdGlvbiBzZW5kQWN0aW9uKGV2ZW50TmFtZSwgdmlldywgZXZlbnQpIHsKICAgIHZhciBhY3Rpb25OYW1lID0gKDAsIF9tZXRhbC5nZXQpKHZpZXcsICJhdHRycy4iICsgZXZlbnROYW1lKSB8fCAoMCwgX21ldGFsLmdldCkodmlldywgZXZlbnROYW1lKTsKICAgIHZhciB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KSh2aWV3LCAndmFsdWUnKTsKCiAgICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5TRU5EX0FDVElPTiAmJiB0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ3N0cmluZycpIHsKICAgICAgdmFyIG1lc3NhZ2UgPSB0cnVlCiAgICAgIC8qIEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMgKi8KICAgICAgPyAiUGFzc2luZyBhY3Rpb25zIHRvIGNvbXBvbmVudHMgYXMgc3RyaW5ncyAobGlrZSBgPElucHV0IEAiICsgZXZlbnROYW1lICsgIj1cIiIgKyBhY3Rpb25OYW1lICsgIlwiIC8+YCkgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBjbG9zdXJlIGFjdGlvbnMgaW5zdGVhZCAoYDxJbnB1dCBAIiArIGV2ZW50TmFtZSArICI9e3thY3Rpb24gXCIiICsgYWN0aW9uTmFtZSArICJcIn19IC8+YCkuIiA6ICJQYXNzaW5nIGFjdGlvbnMgdG8gY29tcG9uZW50cyBhcyBzdHJpbmdzIChsaWtlIGB7e2lucHV0ICIgKyBldmVudE5hbWUgKyAiPVwiIiArIGFjdGlvbk5hbWUgKyAiXCJ9fWApIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgY2xvc3VyZSBhY3Rpb25zIGluc3RlYWQgKGB7e2lucHV0ICIgKyBldmVudE5hbWUgKyAiPShhY3Rpb24gXCIiICsgYWN0aW9uTmFtZSArICJcIil9fWApLiI7CiAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkobWVzc2FnZSwgZmFsc2UsIHsKICAgICAgICBpZDogJ2VtYmVyLWNvbXBvbmVudC5zZW5kLWFjdGlvbicsCiAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfZW1iZXItY29tcG9uZW50LXNlbmQtYWN0aW9uJwogICAgICB9KSk7CiAgICAgIHZpZXcudHJpZ2dlckFjdGlvbih7CiAgICAgICAgYWN0aW9uOiBhY3Rpb25OYW1lLAogICAgICAgIGFjdGlvbkNvbnRleHQ6IFt2YWx1ZSwgZXZlbnRdCiAgICAgIH0pOwogICAgfSBlbHNlIGlmICh0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICBhY3Rpb25OYW1lKHZhbHVlLCBldmVudCk7CiAgICB9CgogICAgaWYgKGFjdGlvbk5hbWUgJiYgISgwLCBfbWV0YWwuZ2V0KSh2aWV3LCAnYnViYmxlcycpKSB7CiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOwogICAgfQogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL21peGlucy92aWV3X3N0YXRlX3N1cHBvcnQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwogIHZhciBfZGVmYXVsdCA9IF9tZXRhbC5NaXhpbi5jcmVhdGUoewogICAgX3RyYW5zaXRpb25UbzogZnVuY3Rpb24gX3RyYW5zaXRpb25UbyhzdGF0ZSkgewogICAgICB2YXIgcHJpb3JTdGF0ZSA9IHRoaXMuX2N1cnJlbnRTdGF0ZTsKICAgICAgdmFyIGN1cnJlbnRTdGF0ZSA9IHRoaXMuX2N1cnJlbnRTdGF0ZSA9IHRoaXMuX3N0YXRlc1tzdGF0ZV07CiAgICAgIHRoaXMuX3N0YXRlID0gc3RhdGU7CgogICAgICBpZiAocHJpb3JTdGF0ZSAmJiBwcmlvclN0YXRlLmV4aXQpIHsKICAgICAgICBwcmlvclN0YXRlLmV4aXQodGhpcyk7CiAgICAgIH0KCiAgICAgIGlmIChjdXJyZW50U3RhdGUuZW50ZXIpIHsKICAgICAgICBjdXJyZW50U3RhdGUuZW50ZXIodGhpcyk7CiAgICAgIH0KICAgIH0KICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvbWl4aW5zL3ZpZXdfc3VwcG9ydCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyLy1pbnRlcm5hbHMvYnJvd3Nlci1lbnZpcm9ubWVudCIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL3V0aWxzIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vanF1ZXJ5IiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3V0aWxzLCBfbWV0YWwsIF9kZWJ1ZywgX2Jyb3dzZXJFbnZpcm9ubWVudCwgX3V0aWxzMiwgX2pxdWVyeSwgX2RlcHJlY2F0ZWRGZWF0dXJlcykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgZnVuY3Rpb24gSygpIHsKICAgIHJldHVybiB0aGlzOwogIH0KCiAgdmFyIG1peGluID0gewogICAgLyoqCiAgICAgQSBsaXN0IG9mIHByb3BlcnRpZXMgb2YgdGhlIHZpZXcgdG8gYXBwbHkgYXMgYXR0cmlidXRlcy4gSWYgdGhlIHByb3BlcnR5CiAgICAgaXMgYSBzdHJpbmcgdmFsdWUsIHRoZSB2YWx1ZSBvZiB0aGF0IHN0cmluZyB3aWxsIGJlIGFwcGxpZWQgYXMgdGhlIHZhbHVlCiAgICAgZm9yIGFuIGF0dHJpYnV0ZSBvZiB0aGUgcHJvcGVydHkncyBuYW1lLgogICAgICBUaGUgZm9sbG93aW5nIGV4YW1wbGUgY3JlYXRlcyBhIHRhZyBsaWtlIGA8ZGl2IHByaW9yaXR5PSJoaWdoIiAvPmAuCiAgICAgIGBgYGFwcC9jb21wb25lbnRzL215LWNvbXBvbmVudC5qcwogICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ3ByaW9yaXR5J10sCiAgICAgICAgcHJpb3JpdHk6ICdoaWdoJwogICAgICB9KTsKICAgICBgYGAKICAgICAgSWYgdGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSBpcyBhIEJvb2xlYW4sIHRoZSBhdHRyaWJ1dGUgaXMgdHJlYXRlZCBhcwogICAgIGFuIEhUTUwgQm9vbGVhbiBhdHRyaWJ1dGUuIEl0IHdpbGwgYmUgcHJlc2VudCBpZiB0aGUgcHJvcGVydHkgaXMgYHRydWVgCiAgICAgYW5kIG9taXR0ZWQgaWYgdGhlIHByb3BlcnR5IGlzIGBmYWxzZWAuCiAgICAgIFRoZSBmb2xsb3dpbmcgZXhhbXBsZSBjcmVhdGVzIG1hcmt1cCBsaWtlIGA8ZGl2IHZpc2libGUgLz5gLgogICAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICBhdHRyaWJ1dGVCaW5kaW5nczogWyd2aXNpYmxlJ10sCiAgICAgICAgdmlzaWJsZTogdHJ1ZQogICAgICB9KTsKICAgICBgYGAKICAgICAgSWYgeW91IHdvdWxkIHByZWZlciB0byB1c2UgYSBjdXN0b20gdmFsdWUgaW5zdGVhZCBvZiB0aGUgcHJvcGVydHkgbmFtZSwKICAgICB5b3UgY2FuIGNyZWF0ZSB0aGUgc2FtZSBtYXJrdXAgYXMgdGhlIGxhc3QgZXhhbXBsZSB3aXRoIGEgYmluZGluZyBsaWtlCiAgICAgdGhpczoKICAgICAgYGBgYXBwL2NvbXBvbmVudHMvbXktY29tcG9uZW50LmpzCiAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgYXR0cmlidXRlQmluZGluZ3M6IFsnaXNWaXNpYmxlOnZpc2libGUnXSwKICAgICAgICBpc1Zpc2libGU6IHRydWUKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIFRoaXMgbGlzdCBvZiBhdHRyaWJ1dGVzIGlzIGluaGVyaXRlZCBmcm9tIHRoZSBjb21wb25lbnQncyBzdXBlcmNsYXNzZXMsCiAgICAgYXMgd2VsbC4KICAgICAgQHByb3BlcnR5IGF0dHJpYnV0ZUJpbmRpbmdzCiAgICAgQHR5cGUgQXJyYXkKICAgICBAZGVmYXVsdCBbXQogICAgIEBwdWJsaWMKICAgICAqLwogICAgY29uY2F0ZW5hdGVkUHJvcGVydGllczogWydhdHRyaWJ1dGVCaW5kaW5ncyddLAogICAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogICAgLy8gVEVNUExBVEUgU1VQUE9SVAogICAgLy8KCiAgICAvKioKICAgICBSZXR1cm4gdGhlIG5lYXJlc3QgYW5jZXN0b3IgdGhhdCBpcyBhbiBpbnN0YW5jZSBvZiB0aGUgcHJvdmlkZWQKICAgICBjbGFzcyBvciBtaXhpbi4KICAgICAgQG1ldGhvZCBuZWFyZXN0T2ZUeXBlCiAgICAgQHBhcmFtIHtDbGFzcyxNaXhpbn0ga2xhc3MgU3ViY2xhc3Mgb2YgRW1iZXIuVmlldyAob3IgRW1iZXIuVmlldyBpdHNlbGYpLAogICAgIG9yIGFuIGluc3RhbmNlIG9mIE1peGluLgogICAgIEByZXR1cm4gRW1iZXIuVmlldwogICAgIEBkZXByZWNhdGVkIHVzZSBgeWllbGRgIGFuZCBjb250ZXh0dWFsIGNvbXBvbmVudHMgZm9yIGNvbXBvc2l0aW9uIGluc3RlYWQuCiAgICAgQHByaXZhdGUKICAgICAqLwogICAgbmVhcmVzdE9mVHlwZTogZnVuY3Rpb24gbmVhcmVzdE9mVHlwZShrbGFzcykgewogICAgICB2YXIgdmlldyA9IHRoaXMucGFyZW50VmlldzsKICAgICAgdmFyIGlzT2ZUeXBlID0ga2xhc3MgaW5zdGFuY2VvZiBfbWV0YWwuTWl4aW4gPyBmdW5jdGlvbiAodmlldykgewogICAgICAgIHJldHVybiBrbGFzcy5kZXRlY3Qodmlldyk7CiAgICAgIH0gOiBmdW5jdGlvbiAodmlldykgewogICAgICAgIHJldHVybiBrbGFzcy5kZXRlY3Qodmlldy5jb25zdHJ1Y3Rvcik7CiAgICAgIH07CgogICAgICB3aGlsZSAodmlldykgewogICAgICAgIGlmIChpc09mVHlwZSh2aWV3KSkgewogICAgICAgICAgcmV0dXJuIHZpZXc7CiAgICAgICAgfQoKICAgICAgICB2aWV3ID0gdmlldy5wYXJlbnRWaWV3OwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgIFJldHVybiB0aGUgbmVhcmVzdCBhbmNlc3RvciB0aGF0IGhhcyBhIGdpdmVuIHByb3BlcnR5LgogICAgICBAbWV0aG9kIG5lYXJlc3RXaXRoUHJvcGVydHkKICAgICBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHkgQSBwcm9wZXJ0eSBuYW1lCiAgICAgQHJldHVybiBFbWJlci5WaWV3CiAgICAgQGRlcHJlY2F0ZWQgdXNlIGB5aWVsZGAgYW5kIGNvbnRleHR1YWwgY29tcG9uZW50cyBmb3IgY29tcG9zaXRpb24gaW5zdGVhZC4KICAgICBAcHJpdmF0ZQogICAgICovCiAgICBuZWFyZXN0V2l0aFByb3BlcnR5OiBmdW5jdGlvbiBuZWFyZXN0V2l0aFByb3BlcnR5KHByb3BlcnR5KSB7CiAgICAgIHZhciB2aWV3ID0gdGhpcy5wYXJlbnRWaWV3OwoKICAgICAgd2hpbGUgKHZpZXcpIHsKICAgICAgICBpZiAocHJvcGVydHkgaW4gdmlldykgewogICAgICAgICAgcmV0dXJuIHZpZXc7CiAgICAgICAgfQoKICAgICAgICB2aWV3ID0gdmlldy5wYXJlbnRWaWV3OwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgIFJlbmRlcnMgdGhlIHZpZXcgYWdhaW4uIFRoaXMgd2lsbCB3b3JrIHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGUKICAgICB2aWV3IGlzIGFscmVhZHkgaW4gdGhlIERPTSBvciBub3QuIElmIHRoZSB2aWV3IGlzIGluIHRoZSBET00sIHRoZQogICAgIHJlbmRlcmluZyBwcm9jZXNzIHdpbGwgYmUgZGVmZXJyZWQgdG8gZ2l2ZSBiaW5kaW5ncyBhIGNoYW5jZQogICAgIHRvIHN5bmNocm9uaXplLgogICAgICBJZiBjaGlsZHJlbiB3ZXJlIGFkZGVkIGR1cmluZyB0aGUgcmVuZGVyaW5nIHByb2Nlc3MgdXNpbmcgYGFwcGVuZENoaWxkYCwKICAgICBgcmVyZW5kZXJgIHdpbGwgcmVtb3ZlIHRoZW0sIGJlY2F1c2UgdGhleSB3aWxsIGJlIGFkZGVkIGFnYWluCiAgICAgaWYgbmVlZGVkIGJ5IHRoZSBuZXh0IGByZW5kZXJgLgogICAgICBJbiBnZW5lcmFsLCBpZiB0aGUgZGlzcGxheSBvZiB5b3VyIHZpZXcgY2hhbmdlcywgeW91IHNob3VsZCBtb2RpZnkKICAgICB0aGUgRE9NIGVsZW1lbnQgZGlyZWN0bHkgaW5zdGVhZCBvZiBtYW51YWxseSBjYWxsaW5nIGByZXJlbmRlcmAsIHdoaWNoIGNhbgogICAgIGJlIHNsb3cuCiAgICAgIEBtZXRob2QgcmVyZW5kZXIKICAgICBAcHVibGljCiAgICAgKi8KICAgIHJlcmVuZGVyOiBmdW5jdGlvbiByZXJlbmRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRTdGF0ZS5yZXJlbmRlcih0aGlzKTsKICAgIH0sCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uCiAgICAvLyBFTEVNRU5UIFNVUFBPUlQKICAgIC8vCgogICAgLyoqCiAgICAgUmV0dXJucyB0aGUgY3VycmVudCBET00gZWxlbWVudCBmb3IgdGhlIHZpZXcuCiAgICAgICBAcHJvcGVydHkgZWxlbWVudAogICAgICBAdHlwZSBET01FbGVtZW50CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBlbGVtZW50OiAoMCwgX21ldGFsLm5hdGl2ZURlc2NEZWNvcmF0b3IpKHsKICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSwKICAgICAgZW51bWVyYWJsZTogZmFsc2UsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLnJlbmRlcmVyLmdldEVsZW1lbnQodGhpcyk7CiAgICAgIH0KICAgIH0pLAoKICAgIC8qKgogICAgIEFwcGVuZHMgdGhlIHZpZXcncyBlbGVtZW50IHRvIHRoZSBzcGVjaWZpZWQgcGFyZW50IGVsZW1lbnQuCiAgICAgIE5vdGUgdGhhdCB0aGlzIG1ldGhvZCBqdXN0IHNjaGVkdWxlcyB0aGUgdmlldyB0byBiZSBhcHBlbmRlZDsgdGhlIERPTQogICAgIGVsZW1lbnQgd2lsbCBub3QgYmUgYXBwZW5kZWQgdG8gdGhlIGdpdmVuIGVsZW1lbnQgdW50aWwgYWxsIGJpbmRpbmdzIGhhdmUKICAgICBmaW5pc2hlZCBzeW5jaHJvbml6aW5nLgogICAgICBUaGlzIGlzIG5vdCB0eXBpY2FsbHkgYSBmdW5jdGlvbiB0aGF0IHlvdSB3aWxsIG5lZWQgdG8gY2FsbCBkaXJlY3RseSB3aGVuCiAgICAgYnVpbGRpbmcgeW91ciBhcHBsaWNhdGlvbi4gSWYgeW91IGRvIG5lZWQgdG8gdXNlIGBhcHBlbmRUb2AsIGJlIHN1cmUgdGhhdAogICAgIHRoZSB0YXJnZXQgZWxlbWVudCB5b3UgYXJlIHByb3ZpZGluZyBpcyBhc3NvY2lhdGVkIHdpdGggYW4gYEFwcGxpY2F0aW9uYAogICAgIGFuZCBkb2VzIG5vdCBoYXZlIGFuIGFuY2VzdG9yIGVsZW1lbnQgdGhhdCBpcyBhc3NvY2lhdGVkIHdpdGggYW4gRW1iZXIgdmlldy4KICAgICAgQG1ldGhvZCBhcHBlbmRUbwogICAgIEBwYXJhbSB7U3RyaW5nfERPTUVsZW1lbnR8alF1ZXJ5fSBBIHNlbGVjdG9yLCBlbGVtZW50LCBIVE1MIHN0cmluZywgb3IgalF1ZXJ5IG9iamVjdAogICAgIEByZXR1cm4ge0VtYmVyLlZpZXd9IHJlY2VpdmVyCiAgICAgQHByaXZhdGUKICAgICAqLwogICAgYXBwZW5kVG86IGZ1bmN0aW9uIGFwcGVuZFRvKHNlbGVjdG9yKSB7CiAgICAgIHZhciB0YXJnZXQ7CgogICAgICBpZiAoX2Jyb3dzZXJFbnZpcm9ubWVudC5oYXNET00pIHsKICAgICAgICB0YXJnZXQgPSB0eXBlb2Ygc2VsZWN0b3IgPT09ICdzdHJpbmcnID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3RvcikgOiBzZWxlY3RvcjsKICAgICAgICAoZmFsc2UgJiYgISh0YXJnZXQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IHRyaWVkIHRvIGFwcGVuZCB0byAoIiArIHNlbGVjdG9yICsgIikgYnV0IHRoYXQgaXNuJ3QgaW4gdGhlIERPTSIsIHRhcmdldCkpOwogICAgICAgIChmYWxzZSAmJiAhKCEoMCwgX3V0aWxzMi5tYXRjaGVzKSh0YXJnZXQsICcuZW1iZXItdmlldycpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW5ub3QgYXBwZW5kIHRvIGFuIGV4aXN0aW5nIEVtYmVyLlZpZXcuJywgISgwLCBfdXRpbHMyLm1hdGNoZXMpKHRhcmdldCwgJy5lbWJlci12aWV3JykpKTsKICAgICAgICAoZmFsc2UgJiYgIShmdW5jdGlvbiAoKSB7CiAgICAgICAgICB2YXIgbm9kZSA9IHRhcmdldC5wYXJlbnROb2RlOwoKICAgICAgICAgIHdoaWxlIChub2RlKSB7CiAgICAgICAgICAgIGlmIChub2RlLm5vZGVUeXBlICE9PSA5ICYmICgwLCBfdXRpbHMyLm1hdGNoZXMpKG5vZGUsICcuZW1iZXItdmlldycpKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0oKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgY2Fubm90IGFwcGVuZCB0byBhbiBleGlzdGluZyBFbWJlci5WaWV3LicsIGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHZhciBub2RlID0gdGFyZ2V0LnBhcmVudE5vZGU7CgogICAgICAgICAgd2hpbGUgKG5vZGUpIHsKICAgICAgICAgICAgaWYgKG5vZGUubm9kZVR5cGUgIT09IDkgJiYgKDAsIF91dGlsczIubWF0Y2hlcykobm9kZSwgJy5lbWJlci12aWV3JykpIHsKICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIG5vZGUgPSBub2RlLnBhcmVudE5vZGU7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfSgpKSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGFyZ2V0ID0gc2VsZWN0b3I7CiAgICAgICAgKGZhbHNlICYmICEodHlwZW9mIHRhcmdldCAhPT0gJ3N0cmluZycpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IHRyaWVkIHRvIGFwcGVuZCB0byBhIHNlbGVjdG9yIHN0cmluZyAoIiArIHNlbGVjdG9yICsgIikgaW4gYW4gZW52aXJvbm1lbnQgd2l0aG91dCBqUXVlcnkiLCB0eXBlb2YgdGFyZ2V0ICE9PSAnc3RyaW5nJykpOwogICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBzZWxlY3Rvci5hcHBlbmRDaGlsZCA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgdHJpZWQgdG8gYXBwZW5kIHRvIGEgbm9uLUVsZW1lbnQgKCIgKyBzZWxlY3RvciArICIpIGluIGFuIGVudmlyb25tZW50IHdpdGhvdXQgalF1ZXJ5IiwgdHlwZW9mIHNlbGVjdG9yLmFwcGVuZENoaWxkID09PSAnZnVuY3Rpb24nKSk7CiAgICAgIH0KCiAgICAgIHRoaXMucmVuZGVyZXIuYXBwZW5kVG8odGhpcywgdGFyZ2V0KTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgIEFwcGVuZHMgdGhlIHZpZXcncyBlbGVtZW50IHRvIHRoZSBkb2N1bWVudCBib2R5LiBJZiB0aGUgdmlldyBkb2VzCiAgICAgbm90IGhhdmUgYW4gSFRNTCByZXByZXNlbnRhdGlvbiB5ZXQKICAgICB0aGUgZWxlbWVudCB3aWxsIGJlIGdlbmVyYXRlZCBhdXRvbWF0aWNhbGx5LgogICAgICBJZiB5b3VyIGFwcGxpY2F0aW9uIHVzZXMgdGhlIGByb290RWxlbWVudGAgcHJvcGVydHksIHlvdSBtdXN0IGFwcGVuZAogICAgIHRoZSB2aWV3IHdpdGhpbiB0aGF0IGVsZW1lbnQuIFJlbmRlcmluZyB2aWV3cyBvdXRzaWRlIG9mIHRoZSBgcm9vdEVsZW1lbnRgCiAgICAgaXMgbm90IHN1cHBvcnRlZC4KICAgICAgTm90ZSB0aGF0IHRoaXMgbWV0aG9kIGp1c3Qgc2NoZWR1bGVzIHRoZSB2aWV3IHRvIGJlIGFwcGVuZGVkOyB0aGUgRE9NCiAgICAgZWxlbWVudCB3aWxsIG5vdCBiZSBhcHBlbmRlZCB0byB0aGUgZG9jdW1lbnQgYm9keSB1bnRpbCBhbGwgYmluZGluZ3MgaGF2ZQogICAgIGZpbmlzaGVkIHN5bmNocm9uaXppbmcuCiAgICAgIEBtZXRob2QgYXBwZW5kCiAgICAgQHJldHVybiB7RW1iZXIuVmlld30gcmVjZWl2ZXIKICAgICBAcHJpdmF0ZQogICAgICovCiAgICBhcHBlbmQ6IGZ1bmN0aW9uIGFwcGVuZCgpIHsKICAgICAgcmV0dXJuIHRoaXMuYXBwZW5kVG8oZG9jdW1lbnQuYm9keSk7CiAgICB9LAoKICAgIC8qKgogICAgIFRoZSBIVE1MIGBpZGAgb2YgdGhlIHZpZXcncyBlbGVtZW50IGluIHRoZSBET00uIFlvdSBjYW4gcHJvdmlkZSB0aGlzCiAgICAgdmFsdWUgeW91cnNlbGYgYnV0IGl0IG11c3QgYmUgdW5pcXVlIChqdXN0IGFzIGluIEhUTUwpOgogICAgICBgYGBoYW5kbGViYXJzCiAgICAge3tteS1jb21wb25lbnQgZWxlbWVudElkPSJhLXJlYWxseS1jb29sLWlkIn19CiAgICAgYGBgCiAgICAgIElmIG5vdCBtYW51YWxseSBzZXQgYSBkZWZhdWx0IHZhbHVlIHdpbGwgYmUgcHJvdmlkZWQgYnkgdGhlIGZyYW1ld29yay4KICAgICAgT25jZSByZW5kZXJlZCBhbiBlbGVtZW50J3MgYGVsZW1lbnRJZGAgaXMgY29uc2lkZXJlZCBpbW11dGFibGUgYW5kIHlvdQogICAgIHNob3VsZCBuZXZlciBjaGFuZ2UgaXQuIElmIHlvdSBuZWVkIHRvIGNvbXB1dGUgYSBkeW5hbWljIHZhbHVlIGZvciB0aGUKICAgICBgZWxlbWVudElkYCwgeW91IHNob3VsZCBkbyB0aGlzIHdoZW4gdGhlIGNvbXBvbmVudCBvciBlbGVtZW50IGlzIGJlaW5nCiAgICAgaW5zdGFudGlhdGVkOgogICAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICBpbml0KCkgewogICAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICAgIGxldCBpbmRleCA9IHRoaXMuZ2V0KCdpbmRleCcpOwogICAgICAgICAgdGhpcy5zZXQoJ2VsZW1lbnRJZCcsICdjb21wb25lbnQtaWQnICsgaW5kZXgpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgYGBgCiAgICAgIEBwcm9wZXJ0eSBlbGVtZW50SWQKICAgICBAdHlwZSBTdHJpbmcKICAgICBAcHVibGljCiAgICAgKi8KICAgIGVsZW1lbnRJZDogbnVsbCwKCiAgICAvKioKICAgICBDYWxsZWQgd2hlbiBhIHZpZXcgaXMgZ29pbmcgdG8gaW5zZXJ0IGFuIGVsZW1lbnQgaW50byB0aGUgRE9NLgogICAgICBAZXZlbnQgd2lsbEluc2VydEVsZW1lbnQKICAgICBAcHVibGljCiAgICAgKi8KICAgIHdpbGxJbnNlcnRFbGVtZW50OiBLLAoKICAgIC8qKgogICAgIENhbGxlZCB3aGVuIHRoZSBlbGVtZW50IG9mIHRoZSB2aWV3IGhhcyBiZWVuIGluc2VydGVkIGludG8gdGhlIERPTS4KICAgICBPdmVycmlkZSB0aGlzIGZ1bmN0aW9uIHRvIGRvIGFueSBzZXQgdXAgdGhhdCByZXF1aXJlcyBhbiBlbGVtZW50CiAgICAgaW4gdGhlIGRvY3VtZW50IGJvZHkuCiAgICAgIFdoZW4gYSB2aWV3IGhhcyBjaGlsZHJlbiwgZGlkSW5zZXJ0RWxlbWVudCB3aWxsIGJlIGNhbGxlZCBvbiB0aGUKICAgICBjaGlsZCB2aWV3KHMpIGZpcnN0IGFuZCBvbiBpdHNlbGYgYWZ0ZXJ3YXJkcy4KICAgICAgQGV2ZW50IGRpZEluc2VydEVsZW1lbnQKICAgICBAcHVibGljCiAgICAgKi8KICAgIGRpZEluc2VydEVsZW1lbnQ6IEssCgogICAgLyoqCiAgICAgQ2FsbGVkIHdoZW4gdGhlIHZpZXcgaXMgYWJvdXQgdG8gcmVyZW5kZXIsIGJ1dCBiZWZvcmUgYW55dGhpbmcgaGFzCiAgICAgYmVlbiB0b3JuIGRvd24uIFRoaXMgaXMgYSBnb29kIG9wcG9ydHVuaXR5IHRvIHRlYXIgZG93biBhbnkgbWFudWFsCiAgICAgb2JzZXJ2ZXJzIHlvdSBoYXZlIGluc3RhbGxlZCBiYXNlZCBvbiB0aGUgRE9NIHN0YXRlCiAgICAgIEBldmVudCB3aWxsQ2xlYXJSZW5kZXIKICAgICBAcHVibGljCiAgICAgKi8KICAgIHdpbGxDbGVhclJlbmRlcjogSywKCiAgICAvKioKICAgICBZb3UgbXVzdCBjYWxsIGBkZXN0cm95YCBvbiBhIHZpZXcgdG8gZGVzdHJveSB0aGUgdmlldyAoYW5kIGFsbCBvZiBpdHMKICAgICBjaGlsZCB2aWV3cykuIFRoaXMgd2lsbCByZW1vdmUgdGhlIHZpZXcgZnJvbSBhbnkgcGFyZW50IG5vZGUsIHRoZW4gbWFrZQogICAgIHN1cmUgdGhhdCB0aGUgRE9NIGVsZW1lbnQgbWFuYWdlZCBieSB0aGUgdmlldyBjYW4gYmUgcmVsZWFzZWQgYnkgdGhlCiAgICAgbWVtb3J5IG1hbmFnZXIuCiAgICAgIEBtZXRob2QgZGVzdHJveQogICAgIEBwcml2YXRlCiAgICAgKi8KICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzLl9jdXJyZW50U3RhdGUuZGVzdHJveSh0aGlzKTsKICAgIH0sCgogICAgLyoqCiAgICAgQ2FsbGVkIHdoZW4gdGhlIGVsZW1lbnQgb2YgdGhlIHZpZXcgaXMgZ29pbmcgdG8gYmUgZGVzdHJveWVkLiBPdmVycmlkZQogICAgIHRoaXMgZnVuY3Rpb24gdG8gZG8gYW55IHRlYXJkb3duIHRoYXQgcmVxdWlyZXMgYW4gZWxlbWVudCwgbGlrZSByZW1vdmluZwogICAgIGV2ZW50IGxpc3RlbmVycy4KICAgICAgUGxlYXNlIG5vdGU6IGFueSBwcm9wZXJ0eSBjaGFuZ2VzIG1hZGUgZHVyaW5nIHRoaXMgZXZlbnQgd2lsbCBoYXZlIG5vCiAgICAgZWZmZWN0IG9uIG9iamVjdCBvYnNlcnZlcnMuCiAgICAgIEBldmVudCB3aWxsRGVzdHJveUVsZW1lbnQKICAgICBAcHVibGljCiAgICAgKi8KICAgIHdpbGxEZXN0cm95RWxlbWVudDogSywKCiAgICAvKioKICAgICBDYWxsZWQgYWZ0ZXIgdGhlIGVsZW1lbnQgb2YgdGhlIHZpZXcgaXMgZGVzdHJveWVkLgogICAgICBAZXZlbnQgd2lsbERlc3Ryb3lFbGVtZW50CiAgICAgQHB1YmxpYwogICAgICovCiAgICBkaWREZXN0cm95RWxlbWVudDogSywKCiAgICAvKioKICAgICBDYWxsZWQgd2hlbiB0aGUgcGFyZW50VmlldyBwcm9wZXJ0eSBoYXMgY2hhbmdlZC4KICAgICAgQGV2ZW50IHBhcmVudFZpZXdEaWRDaGFuZ2UKICAgICBAcHJpdmF0ZQogICAgICovCiAgICBwYXJlbnRWaWV3RGlkQ2hhbmdlOiBLLAogICAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogICAgLy8gU1RBTkRBUkQgUkVOREVSIFBST1BFUlRJRVMKICAgIC8vCgogICAgLyoqCiAgICAgVGFnIG5hbWUgZm9yIHRoZSB2aWV3J3Mgb3V0ZXIgZWxlbWVudC4gVGhlIHRhZyBuYW1lIGlzIG9ubHkgdXNlZCB3aGVuIGFuCiAgICAgZWxlbWVudCBpcyBmaXJzdCBjcmVhdGVkLiBJZiB5b3UgY2hhbmdlIHRoZSBgdGFnTmFtZWAgZm9yIGFuIGVsZW1lbnQsIHlvdQogICAgIG11c3QgZGVzdHJveSBhbmQgcmVjcmVhdGUgdGhlIHZpZXcgZWxlbWVudC4KICAgICAgQnkgZGVmYXVsdCwgdGhlIHJlbmRlciBidWZmZXIgd2lsbCB1c2UgYSBgPGRpdj5gIHRhZyBmb3Igdmlld3MuCiAgICAgIElmIHRoZSB0YWdOYW1lIGlzIGAnJ2AsIHRoZSB2aWV3IHdpbGwgYmUgdGFnbGVzcywgd2l0aCBubyBvdXRlciBlbGVtZW50LgogICAgIENvbXBvbmVudCBwcm9wZXJ0aWVzIHRoYXQgZGVwZW5kIG9uIHRoZSBwcmVzZW5jZSBvZiBhbiBvdXRlciBlbGVtZW50LCBzdWNoCiAgICAgYXMgYGNsYXNzTmFtZUJpbmRpbmdzYCBhbmQgYGF0dHJpYnV0ZUJpbmRpbmdzYCwgZG8gbm90IHdvcmsgd2l0aCB0YWdsZXNzCiAgICAgY29tcG9uZW50cy4gVGFnbGVzcyBjb21wb25lbnRzIGNhbm5vdCBpbXBsZW1lbnQgbWV0aG9kcyB0byBoYW5kbGUgZXZlbnRzLAogICAgIGFuZCBoYXZlIG5vIGFzc29jaWF0ZWQgalF1ZXJ5IG9iamVjdCB0byByZXR1cm4gd2l0aCBgJCgpYC4KICAgICAgQHByb3BlcnR5IHRhZ05hbWUKICAgICBAdHlwZSBTdHJpbmcKICAgICBAZGVmYXVsdCBudWxsCiAgICAgQHB1YmxpYwogICAgICovCiAgICAvLyBXZSBsZWF2ZSB0aGlzIG51bGwgYnkgZGVmYXVsdCBzbyB3ZSBjYW4gdGVsbCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuCiAgICAvLyB0aGUgZGVmYXVsdCBjYXNlIGFuZCBhIHVzZXItc3BlY2lmaWVkIHRhZy4KICAgIHRhZ05hbWU6IG51bGwsCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uCiAgICAvLyBDT1JFIERJU1BMQVkgTUVUSE9EUwogICAgLy8KCiAgICAvKioKICAgICBTZXR1cCBhIHZpZXcsIGJ1dCBkbyBub3QgZmluaXNoIHdha2luZyBpdCB1cC4KICAgICAgKiBjb25maWd1cmUgYGNoaWxkVmlld3NgCiAgICAgKiByZWdpc3RlciB0aGUgdmlldyB3aXRoIHRoZSBnbG9iYWwgdmlld3MgaGFzaCwgd2hpY2ggaXMgdXNlZCBmb3IgZXZlbnQKICAgICBkaXNwYXRjaAogICAgICBAbWV0aG9kIGluaXQKICAgICBAcHJpdmF0ZQogICAgICovCiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOyAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoCgoKICAgICAgKGZhbHNlICYmICEoKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKHRoaXMsICdlbGVtZW50SWQnKSA9PT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3QgdXNlIGEgY29tcHV0ZWQgcHJvcGVydHkgZm9yIHRoZSBjb21wb25lbnQncyBgZWxlbWVudElkYCAoIiArIHRoaXMgKyAiKS4iLCAoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JQcm9wZXJ0eSkodGhpcywgJ2VsZW1lbnRJZCcpID09PSB1bmRlZmluZWQpKTsgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aAoKICAgICAgKGZhbHNlICYmICEoKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKHRoaXMsICd0YWdOYW1lJykgPT09IHVuZGVmaW5lZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgY2Fubm90IHVzZSBhIGNvbXB1dGVkIHByb3BlcnR5IGZvciB0aGUgY29tcG9uZW50J3MgYHRhZ05hbWVgICgiICsgdGhpcyArICIpLiIsICgwLCBfbWV0YWwuZGVzY3JpcHRvckZvclByb3BlcnR5KSh0aGlzLCAndGFnTmFtZScpID09PSB1bmRlZmluZWQpKTsKCiAgICAgIGlmICghdGhpcy5lbGVtZW50SWQgJiYgdGhpcy50YWdOYW1lICE9PSAnJykgewogICAgICAgIHRoaXMuZWxlbWVudElkID0gKDAsIF91dGlscy5ndWlkRm9yKSh0aGlzKTsKICAgICAgfQoKICAgICAgKGZhbHNlICYmICEoIXRoaXMucmVuZGVyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1VzaW5nIGEgY3VzdG9tIGAucmVuZGVyYCBmdW5jdGlvbiBpcyBubyBsb25nZXIgc3VwcG9ydGVkLicsICF0aGlzLnJlbmRlcikpOwogICAgfSwKICAgIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KICAgIC8vIEVWRU5UIEhBTkRMSU5HCiAgICAvLwoKICAgIC8qKgogICAgIEhhbmRsZSBldmVudHMgZnJvbSBgRXZlbnREaXNwYXRjaGVyYAogICAgICBAbWV0aG9kIGhhbmRsZUV2ZW50CiAgICAgQHBhcmFtIGV2ZW50TmFtZSB7U3RyaW5nfQogICAgIEBwYXJhbSBldnQge0V2ZW50fQogICAgIEBwcml2YXRlCiAgICAgKi8KICAgIGhhbmRsZUV2ZW50OiBmdW5jdGlvbiBoYW5kbGVFdmVudChldmVudE5hbWUsIGV2dCkgewogICAgICByZXR1cm4gdGhpcy5fY3VycmVudFN0YXRlLmhhbmRsZUV2ZW50KHRoaXMsIGV2ZW50TmFtZSwgZXZ0KTsKICAgIH0KICB9OwoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5KUVVFUllfSU5URUdSQVRJT04pIHsKICAgIC8qKgogICAgIFJldHVybnMgYSBqUXVlcnkgb2JqZWN0IGZvciB0aGlzIHZpZXcncyBlbGVtZW50LiBJZiB5b3UgcGFzcyBpbiBhIHNlbGVjdG9yCiAgICAgc3RyaW5nLCB0aGlzIG1ldGhvZCB3aWxsIHJldHVybiBhIGpRdWVyeSBvYmplY3QsIHVzaW5nIHRoZSBjdXJyZW50IGVsZW1lbnQKICAgICBhcyBpdHMgYnVmZmVyLgogICAgICBGb3IgZXhhbXBsZSwgY2FsbGluZyBgdmlldy4kKCdsaScpYCB3aWxsIHJldHVybiBhIGpRdWVyeSBvYmplY3QgY29udGFpbmluZwogICAgIGFsbCBvZiB0aGUgYGxpYCBlbGVtZW50cyBpbnNpZGUgdGhlIERPTSBlbGVtZW50IG9mIHRoaXMgdmlldy4KICAgICAgQG1ldGhvZCAkCiAgICAgQHBhcmFtIHtTdHJpbmd9IFtzZWxlY3Rvcl0gYSBqUXVlcnktY29tcGF0aWJsZSBzZWxlY3RvciBzdHJpbmcKICAgICBAcmV0dXJuIHtqUXVlcnl9IHRoZSBqUXVlcnkgb2JqZWN0IGZvciB0aGUgRE9NIG5vZGUKICAgICBAcHVibGljCiAgICAgQGRlcHJlY2F0ZWQKICAgICAqLwogICAgbWl4aW4uJCA9IGZ1bmN0aW9uICQoc2VsKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMudGFnTmFtZSAhPT0gJycpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGNhbm5vdCBhY2Nlc3MgdGhpcy4kKCkgb24gYSBjb21wb25lbnQgd2l0aCBgdGFnTmFtZTogJydgIHNwZWNpZmllZC4iLCB0aGlzLnRhZ05hbWUgIT09ICcnKSk7CiAgICAgIChmYWxzZSAmJiAhKCFfanF1ZXJ5LmpRdWVyeURpc2FibGVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW5ub3QgYWNjZXNzIHRoaXMuJCgpIHdpdGggYGpRdWVyeWAgZGlzYWJsZWQuJywgIV9qcXVlcnkualF1ZXJ5RGlzYWJsZWQpKTsKICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgnVXNpbmcgdGhpcy4kKCkgaW4gYSBjb21wb25lbnQgaGFzIGJlZW4gZGVwcmVjYXRlZCwgY29uc2lkZXIgdXNpbmcgdGhpcy5lbGVtZW50JywgZmFsc2UsIHsKICAgICAgICBpZDogJ2VtYmVyLXZpZXdzLmN1cmx5LWNvbXBvbmVudHMuanF1ZXJ5LWVsZW1lbnQnLAogICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2pxdWVyeS1hcGlzJwogICAgICB9KSk7CgogICAgICBpZiAodGhpcy5lbGVtZW50KSB7CiAgICAgICAgcmV0dXJuIHNlbCA/ICgwLCBfanF1ZXJ5LmpRdWVyeSkoc2VsLCB0aGlzLmVsZW1lbnQpIDogKDAsIF9qcXVlcnkualF1ZXJ5KSh0aGlzLmVsZW1lbnQpOwogICAgICB9CiAgICB9OwogIH0KICAvKioKICAgQGNsYXNzIFZpZXdNaXhpbgogICBAbmFtZXNwYWNlIEVtYmVyCiAgIEBwcml2YXRlCiAgKi8KCgogIHZhciBfZGVmYXVsdCA9IF9tZXRhbC5NaXhpbi5jcmVhdGUobWl4aW4pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vYWN0aW9uX21hbmFnZXIiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gQWN0aW9uTWFuYWdlcjsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCiAgZnVuY3Rpb24gQWN0aW9uTWFuYWdlcigpIHt9CiAgLyoqCiAgICBHbG9iYWwgYWN0aW9uIGlkIGhhc2guCiAgCiAgICBAcHJpdmF0ZQogICAgQHByb3BlcnR5IHJlZ2lzdGVyZWRBY3Rpb25zCiAgICBAdHlwZSBPYmplY3QKICAqLwoKCiAgQWN0aW9uTWFuYWdlci5yZWdpc3RlcmVkQWN0aW9ucyA9IHt9Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2V2ZW50X2Rpc3BhdGNoZXIiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvb3duZXIiLCAiQGVtYmVyL3BvbHlmaWxscyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSIsICJAZW1iZXIvLWludGVybmFscy92aWV3cyIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2pxdWVyeSIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2FjdGlvbl9tYW5hZ2VyIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vanF1ZXJ5X2V2ZW50X2RlcHJlY2F0aW9uIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vdXRpbHMiLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfb3duZXIsIF9wb2x5ZmlsbHMsIF9kZWJ1ZywgX21ldGFsLCBfcnVudGltZSwgX3ZpZXdzLCBfanF1ZXJ5LCBfYWN0aW9uX21hbmFnZXIsIF9qcXVlcnlfZXZlbnRfZGVwcmVjYXRpb24sIF91dGlscywgX2RlcHJlY2F0ZWRGZWF0dXJlcykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCiAgdmFyIFJPT1RfRUxFTUVOVF9DTEFTUyA9ICdlbWJlci1hcHBsaWNhdGlvbic7CiAgdmFyIFJPT1RfRUxFTUVOVF9TRUxFQ1RPUiA9ICIuIiArIFJPT1RfRUxFTUVOVF9DTEFTUzsKICB2YXIgRVZFTlRfTUFQID0gewogICAgbW91c2VlbnRlcjogJ21vdXNlb3ZlcicsCiAgICBtb3VzZWxlYXZlOiAnbW91c2VvdXQnCiAgfTsKICAvKioKICAgIGBFbWJlci5FdmVudERpc3BhdGNoZXJgIGhhbmRsZXMgZGVsZWdhdGluZyBicm93c2VyIGV2ZW50cyB0byB0aGVpcgogICAgY29ycmVzcG9uZGluZyBgRW1iZXIuVmlld3MuYCBGb3IgZXhhbXBsZSwgd2hlbiB5b3UgY2xpY2sgb24gYSB2aWV3LAogICAgYEVtYmVyLkV2ZW50RGlzcGF0Y2hlcmAgZW5zdXJlcyB0aGF0IHRoYXQgdmlldydzIGBtb3VzZURvd25gIG1ldGhvZCBnZXRzCiAgICBjYWxsZWQuCiAgCiAgICBAY2xhc3MgRXZlbnREaXNwYXRjaGVyCiAgICBAbmFtZXNwYWNlIEVtYmVyCiAgICBAcHJpdmF0ZQogICAgQGV4dGVuZHMgRW1iZXIuT2JqZWN0CiAgKi8KCiAgdmFyIF9kZWZhdWx0ID0gX3J1bnRpbWUuT2JqZWN0LmV4dGVuZCh7CiAgICAvKioKICAgICAgVGhlIHNldCBvZiBldmVudHMgbmFtZXMgKGFuZCBhc3NvY2lhdGVkIGhhbmRsZXIgZnVuY3Rpb24gbmFtZXMpIHRvIGJlIHNldHVwCiAgICAgIGFuZCBkaXNwYXRjaGVkIGJ5IHRoZSBgRXZlbnREaXNwYXRjaGVyYC4gTW9kaWZpY2F0aW9ucyB0byB0aGlzIGxpc3QgY2FuIGJlIGRvbmUKICAgICAgYXQgc2V0dXAgdGltZSwgZ2VuZXJhbGx5IHZpYSB0aGUgYEFwcGxpY2F0aW9uLmN1c3RvbUV2ZW50c2AgaGFzaC4KICAgICAgIFRvIGFkZCBuZXcgZXZlbnRzIHRvIGJlIGxpc3RlbmVkIHRvOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAgICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoewogICAgICAgIGN1c3RvbUV2ZW50czogewogICAgICAgICAgcGFzdGU6ICdwYXN0ZScKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRvIHByZXZlbnQgZGVmYXVsdCBldmVudHMgZnJvbSBiZWluZyBsaXN0ZW5lZCB0bzoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgICBsZXQgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKHsKICAgICAgICBjdXN0b21FdmVudHM6IHsKICAgICAgICAgIG1vdXNlZW50ZXI6IG51bGwsCiAgICAgICAgICBtb3VzZWxlYXZlOiBudWxsCiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgIEBwcm9wZXJ0eSBldmVudHMKICAgICAgQHR5cGUgT2JqZWN0CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgZXZlbnRzOiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHsKICAgICAgdG91Y2hzdGFydDogJ3RvdWNoU3RhcnQnLAogICAgICB0b3VjaG1vdmU6ICd0b3VjaE1vdmUnLAogICAgICB0b3VjaGVuZDogJ3RvdWNoRW5kJywKICAgICAgdG91Y2hjYW5jZWw6ICd0b3VjaENhbmNlbCcsCiAgICAgIGtleWRvd246ICdrZXlEb3duJywKICAgICAga2V5dXA6ICdrZXlVcCcsCiAgICAgIGtleXByZXNzOiAna2V5UHJlc3MnLAogICAgICBtb3VzZWRvd246ICdtb3VzZURvd24nLAogICAgICBtb3VzZXVwOiAnbW91c2VVcCcsCiAgICAgIGNvbnRleHRtZW51OiAnY29udGV4dE1lbnUnLAogICAgICBjbGljazogJ2NsaWNrJywKICAgICAgZGJsY2xpY2s6ICdkb3VibGVDbGljaycsCiAgICAgIGZvY3VzaW46ICdmb2N1c0luJywKICAgICAgZm9jdXNvdXQ6ICdmb2N1c091dCcsCiAgICAgIHN1Ym1pdDogJ3N1Ym1pdCcsCiAgICAgIGlucHV0OiAnaW5wdXQnLAogICAgICBjaGFuZ2U6ICdjaGFuZ2UnLAogICAgICBkcmFnc3RhcnQ6ICdkcmFnU3RhcnQnLAogICAgICBkcmFnOiAnZHJhZycsCiAgICAgIGRyYWdlbnRlcjogJ2RyYWdFbnRlcicsCiAgICAgIGRyYWdsZWF2ZTogJ2RyYWdMZWF2ZScsCiAgICAgIGRyYWdvdmVyOiAnZHJhZ092ZXInLAogICAgICBkcm9wOiAnZHJvcCcsCiAgICAgIGRyYWdlbmQ6ICdkcmFnRW5kJwogICAgfSwgX2RlcHJlY2F0ZWRGZWF0dXJlcy5NT1VTRV9FTlRFUl9MRUFWRV9NT1ZFX0VWRU5UUyA/IHsKICAgICAgbW91c2VlbnRlcjogJ21vdXNlRW50ZXInLAogICAgICBtb3VzZWxlYXZlOiAnbW91c2VMZWF2ZScsCiAgICAgIG1vdXNlbW92ZTogJ21vdXNlTW92ZScKICAgIH0gOiB7fSksCgogICAgLyoqCiAgICAgIFRoZSByb290IERPTSBlbGVtZW50IHRvIHdoaWNoIGV2ZW50IGxpc3RlbmVycyBzaG91bGQgYmUgYXR0YWNoZWQuIEV2ZW50CiAgICAgIGxpc3RlbmVycyB3aWxsIGJlIGF0dGFjaGVkIHRvIHRoZSBkb2N1bWVudCB1bmxlc3MgdGhpcyBpcyBvdmVycmlkZGVuLgogICAgICAgQ2FuIGJlIHNwZWNpZmllZCBhcyBhIERPTUVsZW1lbnQgb3IgYSBzZWxlY3RvciBzdHJpbmcuCiAgICAgICBUaGUgZGVmYXVsdCBib2R5IGlzIGEgc3RyaW5nIHNpbmNlIHRoaXMgbWF5IGJlIGV2YWx1YXRlZCBiZWZvcmUgZG9jdW1lbnQuYm9keQogICAgICBleGlzdHMgaW4gdGhlIERPTS4KICAgICAgIEBwcml2YXRlCiAgICAgIEBwcm9wZXJ0eSByb290RWxlbWVudAogICAgICBAdHlwZSBET01FbGVtZW50CiAgICAgIEBkZWZhdWx0ICdib2R5JwogICAgKi8KICAgIHJvb3RFbGVtZW50OiAnYm9keScsCiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgdGhpcy5fc3VwZXIoKTsKCiAgICAgIChmYWxzZSAmJiAhKGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKShfdGhpcyk7CiAgICAgICAgdmFyIGVudmlyb25tZW50ID0gb3duZXIubG9va3VwKCctZW52aXJvbm1lbnQ6bWFpbicpOwogICAgICAgIHJldHVybiBlbnZpcm9ubWVudC5pc0ludGVyYWN0aXZlOwogICAgICB9KCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnRXZlbnREaXNwYXRjaGVyIHNob3VsZCBuZXZlciBiZSBpbnN0YW50aWF0ZWQgaW4gZmFzdGJvb3QgbW9kZS4gUGxlYXNlIHJlcG9ydCB0aGlzIGFzIGFuIEVtYmVyIGJ1Zy4nLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikoX3RoaXMpOwogICAgICAgIHZhciBlbnZpcm9ubWVudCA9IG93bmVyLmxvb2t1cCgnLWVudmlyb25tZW50Om1haW4nKTsKICAgICAgICByZXR1cm4gZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZTsKICAgICAgfSgpKSk7CiAgICAgIHRoaXMuX2V2ZW50SGFuZGxlcnMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgfSwKCiAgICAvKioKICAgICAgU2V0cyB1cCBldmVudCBsaXN0ZW5lcnMgZm9yIHN0YW5kYXJkIGJyb3dzZXIgZXZlbnRzLgogICAgICAgVGhpcyB3aWxsIGJlIGNhbGxlZCBhZnRlciB0aGUgYnJvd3NlciBzZW5kcyBhIGBET01Db250ZW50UmVhZHlgIGV2ZW50LiBCeQogICAgICBkZWZhdWx0LCBpdCB3aWxsIHNldCB1cCBhbGwgb2YgdGhlIGxpc3RlbmVycyBvbiB0aGUgZG9jdW1lbnQgYm9keS4gSWYgeW91CiAgICAgIHdvdWxkIGxpa2UgdG8gcmVnaXN0ZXIgdGhlIGxpc3RlbmVycyBvbiBhIGRpZmZlcmVudCBlbGVtZW50LCBzZXQgdGhlIGV2ZW50CiAgICAgIGRpc3BhdGNoZXIncyBgcm9vdGAgcHJvcGVydHkuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHNldHVwCiAgICAgIEBwYXJhbSBhZGRlZEV2ZW50cyB7T2JqZWN0fQogICAgKi8KICAgIHNldHVwOiBmdW5jdGlvbiBzZXR1cChhZGRlZEV2ZW50cywgX3Jvb3RFbGVtZW50KSB7CiAgICAgIHZhciBldmVudHMgPSB0aGlzLl9maW5hbEV2ZW50cyA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnZXZlbnRzJyksIGFkZGVkRXZlbnRzKTsKCiAgICAgIGlmIChfcm9vdEVsZW1lbnQgIT09IHVuZGVmaW5lZCAmJiBfcm9vdEVsZW1lbnQgIT09IG51bGwpIHsKICAgICAgICAoMCwgX21ldGFsLnNldCkodGhpcywgJ3Jvb3RFbGVtZW50JywgX3Jvb3RFbGVtZW50KTsKICAgICAgfQoKICAgICAgdmFyIHJvb3RFbGVtZW50U2VsZWN0b3IgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ3Jvb3RFbGVtZW50Jyk7CiAgICAgIHZhciByb290RWxlbWVudDsKCiAgICAgIGlmICghX2RlcHJlY2F0ZWRGZWF0dXJlcy5KUVVFUllfSU5URUdSQVRJT04gfHwgX2pxdWVyeS5qUXVlcnlEaXNhYmxlZCkgewogICAgICAgIGlmICh0eXBlb2Ygcm9vdEVsZW1lbnRTZWxlY3RvciAhPT0gJ3N0cmluZycpIHsKICAgICAgICAgIHJvb3RFbGVtZW50ID0gcm9vdEVsZW1lbnRTZWxlY3RvcjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcm9vdEVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHJvb3RFbGVtZW50U2VsZWN0b3IpOwogICAgICAgIH0KCiAgICAgICAgKGZhbHNlICYmICEoIXJvb3RFbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhST09UX0VMRU1FTlRfQ0xBU1MpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3QgdXNlIHRoZSBzYW1lIHJvb3QgZWxlbWVudCAoIiArICgoMCwgX21ldGFsLmdldCkodGhpcywgJ3Jvb3RFbGVtZW50JykgfHwgcm9vdEVsZW1lbnQudGFnTmFtZSkgKyAiKSBtdWx0aXBsZSB0aW1lcyBpbiBhbiBFbWJlci5BcHBsaWNhdGlvbiIsICFyb290RWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoUk9PVF9FTEVNRU5UX0NMQVNTKSkpOwogICAgICAgIChmYWxzZSAmJiAhKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHZhciB0YXJnZXQgPSByb290RWxlbWVudC5wYXJlbnROb2RlOwoKICAgICAgICAgIGRvIHsKICAgICAgICAgICAgaWYgKHRhcmdldC5jbGFzc0xpc3QuY29udGFpbnMoUk9PVF9FTEVNRU5UX0NMQVNTKSkgewogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdGFyZ2V0ID0gdGFyZ2V0LnBhcmVudE5vZGU7CiAgICAgICAgICB9IHdoaWxlICh0YXJnZXQgJiYgdGFyZ2V0Lm5vZGVUeXBlID09PSAxKTsKCiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9KCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGNhbm5vdCBtYWtlIGEgbmV3IEVtYmVyLkFwcGxpY2F0aW9uIHVzaW5nIGEgcm9vdCBlbGVtZW50IHRoYXQgaXMgYSBkZXNjZW5kZW50IG9mIGFuIGV4aXN0aW5nIEVtYmVyLkFwcGxpY2F0aW9uJywgZnVuY3Rpb24gKCkgewogICAgICAgICAgdmFyIHRhcmdldCA9IHJvb3RFbGVtZW50LnBhcmVudE5vZGU7CgogICAgICAgICAgZG8gewogICAgICAgICAgICBpZiAodGFyZ2V0LmNsYXNzTGlzdC5jb250YWlucyhST09UX0VMRU1FTlRfQ0xBU1MpKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICB0YXJnZXQgPSB0YXJnZXQucGFyZW50Tm9kZTsKICAgICAgICAgIH0gd2hpbGUgKHRhcmdldCAmJiB0YXJnZXQubm9kZVR5cGUgPT09IDEpOwoKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0oKSkpOwogICAgICAgIChmYWxzZSAmJiAhKCFyb290RWxlbWVudC5xdWVyeVNlbGVjdG9yKFJPT1RfRUxFTUVOVF9TRUxFQ1RPUikpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGNhbm5vdCBtYWtlIGEgbmV3IEVtYmVyLkFwcGxpY2F0aW9uIHVzaW5nIGEgcm9vdCBlbGVtZW50IHRoYXQgaXMgYW4gYW5jZXN0b3Igb2YgYW4gZXhpc3RpbmcgRW1iZXIuQXBwbGljYXRpb24nLCAhcm9vdEVsZW1lbnQucXVlcnlTZWxlY3RvcihST09UX0VMRU1FTlRfU0VMRUNUT1IpKSk7CiAgICAgICAgcm9vdEVsZW1lbnQuY2xhc3NMaXN0LmFkZChST09UX0VMRU1FTlRfQ0xBU1MpOwogICAgICAgIChmYWxzZSAmJiAhKHJvb3RFbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhST09UX0VMRU1FTlRfQ0xBU1MpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIlVuYWJsZSB0byBhZGQgJyIgKyBST09UX0VMRU1FTlRfQ0xBU1MgKyAiJyBjbGFzcyB0byByb290IGVsZW1lbnQgKCIgKyAoKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdyb290RWxlbWVudCcpIHx8IHJvb3RFbGVtZW50LnRhZ05hbWUpICsgIikuIE1ha2Ugc3VyZSB5b3Ugc2V0IHJvb3RFbGVtZW50IHRvIHRoZSBib2R5IG9yIGFuIGVsZW1lbnQgaW4gdGhlIGJvZHkuIiwgcm9vdEVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKFJPT1RfRUxFTUVOVF9DTEFTUykpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByb290RWxlbWVudCA9ICgwLCBfanF1ZXJ5LmpRdWVyeSkocm9vdEVsZW1lbnRTZWxlY3Rvcik7CiAgICAgICAgKGZhbHNlICYmICEoIXJvb3RFbGVtZW50LmlzKFJPT1RfRUxFTUVOVF9TRUxFQ1RPUikpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGNhbm5vdCB1c2UgdGhlIHNhbWUgcm9vdCBlbGVtZW50ICgiICsgKHJvb3RFbGVtZW50LnNlbGVjdG9yIHx8IHJvb3RFbGVtZW50WzBdLnRhZ05hbWUpICsgIikgbXVsdGlwbGUgdGltZXMgaW4gYW4gRW1iZXIuQXBwbGljYXRpb24iLCAhcm9vdEVsZW1lbnQuaXMoUk9PVF9FTEVNRU5UX1NFTEVDVE9SKSkpOwogICAgICAgIChmYWxzZSAmJiAhKCFyb290RWxlbWVudC5jbG9zZXN0KFJPT1RfRUxFTUVOVF9TRUxFQ1RPUikubGVuZ3RoKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW5ub3QgbWFrZSBhIG5ldyBFbWJlci5BcHBsaWNhdGlvbiB1c2luZyBhIHJvb3QgZWxlbWVudCB0aGF0IGlzIGEgZGVzY2VuZGVudCBvZiBhbiBleGlzdGluZyBFbWJlci5BcHBsaWNhdGlvbicsICFyb290RWxlbWVudC5jbG9zZXN0KFJPT1RfRUxFTUVOVF9TRUxFQ1RPUikubGVuZ3RoKSk7CiAgICAgICAgKGZhbHNlICYmICEoIXJvb3RFbGVtZW50LmZpbmQoUk9PVF9FTEVNRU5UX1NFTEVDVE9SKS5sZW5ndGgpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGNhbm5vdCBtYWtlIGEgbmV3IEVtYmVyLkFwcGxpY2F0aW9uIHVzaW5nIGEgcm9vdCBlbGVtZW50IHRoYXQgaXMgYW4gYW5jZXN0b3Igb2YgYW4gZXhpc3RpbmcgRW1iZXIuQXBwbGljYXRpb24nLCAhcm9vdEVsZW1lbnQuZmluZChST09UX0VMRU1FTlRfU0VMRUNUT1IpLmxlbmd0aCkpOwogICAgICAgIHJvb3RFbGVtZW50LmFkZENsYXNzKFJPT1RfRUxFTUVOVF9DTEFTUyk7CgogICAgICAgIGlmICghcm9vdEVsZW1lbnQuaXMoUk9PVF9FTEVNRU5UX1NFTEVDVE9SKSkgewogICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiVW5hYmxlIHRvIGFkZCAnIiArIFJPT1RfRUxFTUVOVF9DTEFTUyArICInIGNsYXNzIHRvIHJvb3QgZWxlbWVudCAoIiArIChyb290RWxlbWVudC5zZWxlY3RvciB8fCByb290RWxlbWVudFswXS50YWdOYW1lKSArICIpLiBNYWtlIHN1cmUgeW91IHNldCByb290RWxlbWVudCB0byB0aGUgYm9keSBvciBhbiBlbGVtZW50IGluIHRoZSBib2R5LiIpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgZm9yICh2YXIgZXZlbnQgaW4gZXZlbnRzKSB7CiAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShldmVudCkpIHsKICAgICAgICAgIHRoaXMuc2V0dXBIYW5kbGVyKHJvb3RFbGVtZW50LCBldmVudCwgZXZlbnRzW2V2ZW50XSk7CiAgICAgICAgfQogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgb24gdGhlIHJvb3RFbGVtZW50LiBJZiB0aGUgZ2l2ZW4gZXZlbnQgaXMKICAgICAgdHJpZ2dlcmVkLCB0aGUgcHJvdmlkZWQgZXZlbnQgaGFuZGxlciB3aWxsIGJlIHRyaWdnZXJlZCBvbiB0aGUgdGFyZ2V0IHZpZXcuCiAgICAgICBJZiB0aGUgdGFyZ2V0IHZpZXcgZG9lcyBub3QgaW1wbGVtZW50IHRoZSBldmVudCBoYW5kbGVyLCBvciBpZiB0aGUgaGFuZGxlcgogICAgICByZXR1cm5zIGBmYWxzZWAsIHRoZSBwYXJlbnQgdmlldyB3aWxsIGJlIGNhbGxlZC4gVGhlIGV2ZW50IHdpbGwgY29udGludWUgdG8KICAgICAgYnViYmxlIHRvIGVhY2ggc3VjY2Vzc2l2ZSBwYXJlbnQgdmlldyB1bnRpbCBpdCByZWFjaGVzIHRoZSB0b3AuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHNldHVwSGFuZGxlcgogICAgICBAcGFyYW0ge0VsZW1lbnR9IHJvb3RFbGVtZW50CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBldmVudCB0aGUgYnJvd3Nlci1vcmlnaW5hdGVkIGV2ZW50IHRvIGxpc3RlbiB0bwogICAgICBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lIHRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbCBvbiB0aGUgdmlldwogICAgKi8KICAgIHNldHVwSGFuZGxlcjogZnVuY3Rpb24gc2V0dXBIYW5kbGVyKHJvb3RFbGVtZW50LCBldmVudCwgZXZlbnROYW1lKSB7CiAgICAgIGlmIChldmVudE5hbWUgPT09IG51bGwpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGlmICghX2RlcHJlY2F0ZWRGZWF0dXJlcy5KUVVFUllfSU5URUdSQVRJT04gfHwgX2pxdWVyeS5qUXVlcnlEaXNhYmxlZCkgewogICAgICAgIHZhciB2aWV3SGFuZGxlciA9IGZ1bmN0aW9uIHZpZXdIYW5kbGVyKHRhcmdldCwgZXZlbnQpIHsKICAgICAgICAgIHZhciB2aWV3ID0gKDAsIF92aWV3cy5nZXRFbGVtZW50VmlldykodGFyZ2V0KTsKICAgICAgICAgIHZhciByZXN1bHQgPSB0cnVlOwoKICAgICAgICAgIGlmICh2aWV3KSB7CiAgICAgICAgICAgIHJlc3VsdCA9IHZpZXcuaGFuZGxlRXZlbnQoZXZlbnROYW1lLCBldmVudCk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9OwoKICAgICAgICB2YXIgYWN0aW9uSGFuZGxlciA9IGZ1bmN0aW9uIGFjdGlvbkhhbmRsZXIodGFyZ2V0LCBldmVudCkgewogICAgICAgICAgdmFyIGFjdGlvbklkID0gdGFyZ2V0LmdldEF0dHJpYnV0ZSgnZGF0YS1lbWJlci1hY3Rpb24nKTsKICAgICAgICAgIHZhciBhY3Rpb25zID0gX2FjdGlvbl9tYW5hZ2VyLmRlZmF1bHQucmVnaXN0ZXJlZEFjdGlvbnNbYWN0aW9uSWRdOyAvLyBJbiBHbGltbWVyMiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYW4gZW1wdHkgc3RyaW5nIGFuZCBhbiBhZGRpdGlvbmFsCiAgICAgICAgICAvLyBhdHRyaWJ1dGUgaXQgc2V0IGZvciBlYWNoIGFjdGlvbiBvbiBhIGdpdmVuIGVsZW1lbnQuIEluIHRoaXMgY2FzZSwgdGhlCiAgICAgICAgICAvLyBhdHRyaWJ1dGVzIG5lZWQgdG8gYmUgcmVhZCBzbyB0aGF0IGEgcHJvcGVyIHNldCBvZiBhY3Rpb24gaGFuZGxlcnMgY2FuCiAgICAgICAgICAvLyBiZSBjb2FsZXNjZWQuCgogICAgICAgICAgaWYgKGFjdGlvbklkID09PSAnJykgewogICAgICAgICAgICB2YXIgYXR0cmlidXRlcyA9IHRhcmdldC5hdHRyaWJ1dGVzOwogICAgICAgICAgICB2YXIgYXR0cmlidXRlQ291bnQgPSBhdHRyaWJ1dGVzLmxlbmd0aDsKICAgICAgICAgICAgYWN0aW9ucyA9IFtdOwoKICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhdHRyaWJ1dGVDb3VudDsgaSsrKSB7CiAgICAgICAgICAgICAgdmFyIGF0dHIgPSBhdHRyaWJ1dGVzLml0ZW0oaSk7CiAgICAgICAgICAgICAgdmFyIGF0dHJOYW1lID0gYXR0ci5uYW1lOwoKICAgICAgICAgICAgICBpZiAoYXR0ck5hbWUuaW5kZXhPZignZGF0YS1lbWJlci1hY3Rpb24tJykgPT09IDApIHsKICAgICAgICAgICAgICAgIGFjdGlvbnMgPSBhY3Rpb25zLmNvbmNhdChfYWN0aW9uX21hbmFnZXIuZGVmYXVsdC5yZWdpc3RlcmVkQWN0aW9uc1thdHRyLnZhbHVlXSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9IC8vIFdlIGhhdmUgdG8gY2hlY2sgZm9yIGFjdGlvbnMgaGVyZSBzaW5jZSBpbiBzb21lIGNhc2VzLCBqUXVlcnkgd2lsbCB0cmlnZ2VyCiAgICAgICAgICAvLyBhbiBldmVudCBvbiBgcmVtb3ZlQ2hpbGRgIChpLmUuIGZvY3Vzb3V0KSBhZnRlciB3ZSd2ZSBhbHJlYWR5IHRvcm4gZG93biB0aGUKICAgICAgICAgIC8vIGFjdGlvbiBoYW5kbGVycyBmb3IgdGhlIHZpZXcuCgoKICAgICAgICAgIGlmICghYWN0aW9ucykgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CgogICAgICAgICAgdmFyIHJlc3VsdCA9IHRydWU7CgogICAgICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGFjdGlvbnMubGVuZ3RoOyBpbmRleCsrKSB7CiAgICAgICAgICAgIHZhciBhY3Rpb24gPSBhY3Rpb25zW2luZGV4XTsKCiAgICAgICAgICAgIGlmIChhY3Rpb24gJiYgYWN0aW9uLmV2ZW50TmFtZSA9PT0gZXZlbnROYW1lKSB7CiAgICAgICAgICAgICAgLy8gcmV0dXJuIGZhbHNlIGlmIGFueSBvZiB0aGUgYWN0aW9uIGhhbmRsZXJzIHJldHVybnMgZmFsc2UKICAgICAgICAgICAgICByZXN1bHQgPSBhY3Rpb24uaGFuZGxlcihldmVudCkgJiYgcmVzdWx0OwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9OyAvLyBTcGVjaWFsIGhhbmRsaW5nIG9mIGV2ZW50cyB0aGF0IGRvbid0IGJ1YmJsZSAoZXZlbnQgZGVsZWdhdGlvbiBkb2VzIG5vdCB3b3JrKS4KICAgICAgICAvLyBNaW1pY3MgdGhlIHdheSB0aGlzIGlzIGhhbmRsZWQgaW4galF1ZXJ5LAogICAgICAgIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vanF1ZXJ5L2pxdWVyeS9ibG9iLzg5OWM1NmY2YWRhMjY4MjFlOGFmMTJkOWYzNWZhMDM5MTAwZTgzOGUvc3JjL2V2ZW50LmpzI0w2NjYtTDcwMAoKCiAgICAgICAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuTU9VU0VfRU5URVJfTEVBVkVfTU9WRV9FVkVOVFMgJiYgRVZFTlRfTUFQW2V2ZW50XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YXIgbWFwcGVkRXZlbnRUeXBlID0gRVZFTlRfTUFQW2V2ZW50XTsKICAgICAgICAgIHZhciBvcmlnRXZlbnRUeXBlID0gZXZlbnQ7CgogICAgICAgICAgdmFyIGNyZWF0ZUZha2VFdmVudCA9IGZ1bmN0aW9uIGNyZWF0ZUZha2VFdmVudChldmVudFR5cGUsIGV2ZW50KSB7CiAgICAgICAgICAgIHZhciBmYWtlRXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnTW91c2VFdmVudCcpOwogICAgICAgICAgICBmYWtlRXZlbnQuaW5pdE1vdXNlRXZlbnQoZXZlbnRUeXBlLCBmYWxzZSwgZmFsc2UsIGV2ZW50LnZpZXcsIGV2ZW50LmRldGFpbCwgZXZlbnQuc2NyZWVuWCwgZXZlbnQuc2NyZWVuWSwgZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSwgZXZlbnQuY3RybEtleSwgZXZlbnQuYWx0S2V5LCBldmVudC5zaGlmdEtleSwgZXZlbnQubWV0YUtleSwgZXZlbnQuYnV0dG9uLCBldmVudC5yZWxhdGVkVGFyZ2V0KTsgLy8gZmFrZSBldmVudC50YXJnZXQgYXMgd2UgZG9uJ3QgZGlzcGF0Y2ggdGhlIGV2ZW50CgogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZmFrZUV2ZW50LCAndGFyZ2V0JywgewogICAgICAgICAgICAgIHZhbHVlOiBldmVudC50YXJnZXQsCiAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgcmV0dXJuIGZha2VFdmVudDsKICAgICAgICAgIH07CgogICAgICAgICAgdmFyIGhhbmRsZU1hcHBlZEV2ZW50ID0gdGhpcy5fZXZlbnRIYW5kbGVyc1ttYXBwZWRFdmVudFR5cGVdID0gZnVuY3Rpb24gKGV2ZW50KSB7CiAgICAgICAgICAgIHZhciB0YXJnZXQgPSBldmVudC50YXJnZXQ7CiAgICAgICAgICAgIHZhciByZWxhdGVkID0gZXZlbnQucmVsYXRlZFRhcmdldDsKCiAgICAgICAgICAgIHdoaWxlICh0YXJnZXQgJiYgdGFyZ2V0Lm5vZGVUeXBlID09PSAxICYmIChyZWxhdGVkID09PSBudWxsIHx8IHJlbGF0ZWQgIT09IHRhcmdldCAmJiAhKDAsIF91dGlscy5jb250YWlucykodGFyZ2V0LCByZWxhdGVkKSkpIHsKICAgICAgICAgICAgICAvLyBtb3VzZUVudGVyL0xlYXZlIGRvbid0IGJ1YmJsZSwgc28gdGhlcmUgaXMgbm8gbG9naWMgdG8gcHJldmVudCBpdCBhcyB3aXRoIG90aGVyIGV2ZW50cwogICAgICAgICAgICAgIGlmICgoMCwgX3ZpZXdzLmdldEVsZW1lbnRWaWV3KSh0YXJnZXQpKSB7CiAgICAgICAgICAgICAgICB2aWV3SGFuZGxlcih0YXJnZXQsIGNyZWF0ZUZha2VFdmVudChvcmlnRXZlbnRUeXBlLCBldmVudCkpOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0Lmhhc0F0dHJpYnV0ZSgnZGF0YS1lbWJlci1hY3Rpb24nKSkgewogICAgICAgICAgICAgICAgYWN0aW9uSGFuZGxlcih0YXJnZXQsIGNyZWF0ZUZha2VFdmVudChvcmlnRXZlbnRUeXBlLCBldmVudCkpOwogICAgICAgICAgICAgIH0gLy8gc2VwYXJhdGUgbW91c2VFbnRlci9MZWF2ZSBldmVudHMgYXJlIGRpc3BhdGNoZWQgZm9yIGVhY2ggbGlzdGVuaW5nIGVsZW1lbnQKICAgICAgICAgICAgICAvLyB1bnRpbCB0aGUgZWxlbWVudCAocmVsYXRlZCkgaGFzIGJlZW4gcmVhY2hlZCB0aGF0IHRoZSBwb2ludGluZyBkZXZpY2UgZXhpdGVkIGZyb20vdG8KCgogICAgICAgICAgICAgIHRhcmdldCA9IHRhcmdldC5wYXJlbnROb2RlOwogICAgICAgICAgICB9CiAgICAgICAgICB9OwoKICAgICAgICAgIHJvb3RFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIobWFwcGVkRXZlbnRUeXBlLCBoYW5kbGVNYXBwZWRFdmVudCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBoYW5kbGVFdmVudCA9IHRoaXMuX2V2ZW50SGFuZGxlcnNbZXZlbnRdID0gZnVuY3Rpb24gKGV2ZW50KSB7CiAgICAgICAgICAgIHZhciB0YXJnZXQgPSBldmVudC50YXJnZXQ7CgogICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgaWYgKCgwLCBfdmlld3MuZ2V0RWxlbWVudFZpZXcpKHRhcmdldCkpIHsKICAgICAgICAgICAgICAgIGlmICh2aWV3SGFuZGxlcih0YXJnZXQsIGV2ZW50KSA9PT0gZmFsc2UpIHsKICAgICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsKICAgICAgICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChldmVudC5jYW5jZWxCdWJibGUgPT09IHRydWUpIHsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGFyZ2V0Lmhhc0F0dHJpYnV0ZSA9PT0gJ2Z1bmN0aW9uJyAmJiB0YXJnZXQuaGFzQXR0cmlidXRlKCdkYXRhLWVtYmVyLWFjdGlvbicpKSB7CiAgICAgICAgICAgICAgICBpZiAoYWN0aW9uSGFuZGxlcih0YXJnZXQsIGV2ZW50KSA9PT0gZmFsc2UpIHsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICB0YXJnZXQgPSB0YXJnZXQucGFyZW50Tm9kZTsKICAgICAgICAgICAgfSB3aGlsZSAodGFyZ2V0ICYmIHRhcmdldC5ub2RlVHlwZSA9PT0gMSk7CiAgICAgICAgICB9OwoKICAgICAgICAgIHJvb3RFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGhhbmRsZUV2ZW50KTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcm9vdEVsZW1lbnQub24oZXZlbnQgKyAiLmVtYmVyIiwgJy5lbWJlci12aWV3JywgZnVuY3Rpb24gKGV2dCkgewogICAgICAgICAgdmFyIHZpZXcgPSAoMCwgX3ZpZXdzLmdldEVsZW1lbnRWaWV3KSh0aGlzKTsKICAgICAgICAgIHZhciByZXN1bHQgPSB0cnVlOwoKICAgICAgICAgIGlmICh2aWV3KSB7CiAgICAgICAgICAgIHJlc3VsdCA9IHZpZXcuaGFuZGxlRXZlbnQoZXZlbnROYW1lLCAoMCwgX2pxdWVyeV9ldmVudF9kZXByZWNhdGlvbi5kZWZhdWx0KShldnQpKTsKICAgICAgICAgIH0KCiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0pOwogICAgICAgIHJvb3RFbGVtZW50Lm9uKGV2ZW50ICsgIi5lbWJlciIsICdbZGF0YS1lbWJlci1hY3Rpb25dJywgZnVuY3Rpb24gKGV2dCkgewogICAgICAgICAgdmFyIGF0dHJpYnV0ZXMgPSBldnQuY3VycmVudFRhcmdldC5hdHRyaWJ1dGVzOwogICAgICAgICAgdmFyIGhhbmRsZWRBY3Rpb25zID0gW107CiAgICAgICAgICBldnQgPSAoMCwgX2pxdWVyeV9ldmVudF9kZXByZWNhdGlvbi5kZWZhdWx0KShldnQpOwoKICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXR0cmlidXRlcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICB2YXIgYXR0ciA9IGF0dHJpYnV0ZXMuaXRlbShpKTsKICAgICAgICAgICAgdmFyIGF0dHJOYW1lID0gYXR0ci5uYW1lOwoKICAgICAgICAgICAgaWYgKGF0dHJOYW1lLmxhc3RJbmRleE9mKCdkYXRhLWVtYmVyLWFjdGlvbi0nLCAwKSAhPT0gLTEpIHsKICAgICAgICAgICAgICB2YXIgYWN0aW9uID0gX2FjdGlvbl9tYW5hZ2VyLmRlZmF1bHQucmVnaXN0ZXJlZEFjdGlvbnNbYXR0ci52YWx1ZV07IC8vIFdlIGhhdmUgdG8gY2hlY2sgZm9yIGFjdGlvbiBoZXJlIHNpbmNlIGluIHNvbWUgY2FzZXMsIGpRdWVyeSB3aWxsIHRyaWdnZXIKICAgICAgICAgICAgICAvLyBhbiBldmVudCBvbiBgcmVtb3ZlQ2hpbGRgIChpLmUuIGZvY3Vzb3V0KSBhZnRlciB3ZSd2ZSBhbHJlYWR5IHRvcm4gZG93biB0aGUKICAgICAgICAgICAgICAvLyBhY3Rpb24gaGFuZGxlcnMgZm9yIHRoZSB2aWV3LgoKICAgICAgICAgICAgICBpZiAoYWN0aW9uICYmIGFjdGlvbi5ldmVudE5hbWUgPT09IGV2ZW50TmFtZSAmJiBoYW5kbGVkQWN0aW9ucy5pbmRleE9mKGFjdGlvbikgPT09IC0xKSB7CiAgICAgICAgICAgICAgICBhY3Rpb24uaGFuZGxlcihldnQpOyAvLyBBY3Rpb24gaGFuZGxlcnMgY2FuIG11dGF0ZSBzdGF0ZSB3aGljaCBpbiB0dXJuIGNyZWF0ZXMgbmV3IGF0dHJpYnV0ZXMgb24gdGhlIGVsZW1lbnQuCiAgICAgICAgICAgICAgICAvLyBUaGlzIGVmZmVjdCBjb3VsZCBjYXVzZSB0aGUgYGRhdGEtZW1iZXItYWN0aW9uYCBhdHRyaWJ1dGUgdG8gc2hpZnQgZG93biBhbmQgYmUgaW52b2tlZCB0d2ljZS4KICAgICAgICAgICAgICAgIC8vIFRvIGF2b2lkIHRoaXMsIHdlIGtlZXAgdHJhY2sgb2Ygd2hpY2ggYWN0aW9ucyBoYXZlIGJlZW4gaGFuZGxlZC4KCiAgICAgICAgICAgICAgICBoYW5kbGVkQWN0aW9ucy5wdXNoKGFjdGlvbik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0sCiAgICBkZXN0cm95OiBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICB2YXIgcm9vdEVsZW1lbnRTZWxlY3RvciA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAncm9vdEVsZW1lbnQnKTsKICAgICAgdmFyIHJvb3RFbGVtZW50OwoKICAgICAgaWYgKHJvb3RFbGVtZW50U2VsZWN0b3Iubm9kZVR5cGUpIHsKICAgICAgICByb290RWxlbWVudCA9IHJvb3RFbGVtZW50U2VsZWN0b3I7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcm9vdEVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHJvb3RFbGVtZW50U2VsZWN0b3IpOwogICAgICB9CgogICAgICBpZiAoIXJvb3RFbGVtZW50KSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAoIV9kZXByZWNhdGVkRmVhdHVyZXMuSlFVRVJZX0lOVEVHUkFUSU9OIHx8IF9qcXVlcnkualF1ZXJ5RGlzYWJsZWQpIHsKICAgICAgICBmb3IgKHZhciBldmVudCBpbiB0aGlzLl9ldmVudEhhbmRsZXJzKSB7CiAgICAgICAgICByb290RWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCB0aGlzLl9ldmVudEhhbmRsZXJzW2V2ZW50XSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgICgwLCBfanF1ZXJ5LmpRdWVyeSkocm9vdEVsZW1lbnRTZWxlY3Rvcikub2ZmKCcuZW1iZXInLCAnKionKTsKICAgICAgfQoKICAgICAgcm9vdEVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShST09UX0VMRU1FTlRfQ0xBU1MpOwogICAgICByZXR1cm4gdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0sCiAgICB0b1N0cmluZzogZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiAnKEV2ZW50RGlzcGF0Y2hlciknOwogICAgfQogIH0pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vanF1ZXJ5IiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL2Jyb3dzZXItZW52aXJvbm1lbnQiLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW52aXJvbm1lbnQsIF9icm93c2VyRW52aXJvbm1lbnQsIF9kZXByZWNhdGVkRmVhdHVyZXMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmpRdWVyeURpc2FibGVkID0gX2V4cG9ydHMualF1ZXJ5ID0gdm9pZCAwOwogIHZhciBqUXVlcnk7CiAgX2V4cG9ydHMualF1ZXJ5ID0galF1ZXJ5OwogIHZhciBqUXVlcnlEaXNhYmxlZCA9ICFfZGVwcmVjYXRlZEZlYXR1cmVzLkpRVUVSWV9JTlRFR1JBVElPTiB8fCBfZW52aXJvbm1lbnQuRU5WLl9KUVVFUllfSU5URUdSQVRJT04gPT09IGZhbHNlOwogIF9leHBvcnRzLmpRdWVyeURpc2FibGVkID0galF1ZXJ5RGlzYWJsZWQ7CgogIGlmIChfZGVwcmVjYXRlZEZlYXR1cmVzLkpRVUVSWV9JTlRFR1JBVElPTiAmJiBfYnJvd3NlckVudmlyb25tZW50Lmhhc0RPTSkgewogICAgX2V4cG9ydHMualF1ZXJ5ID0galF1ZXJ5ID0gX2Vudmlyb25tZW50LmNvbnRleHQuaW1wb3J0cy5qUXVlcnk7CgogICAgaWYgKCFqUXVlcnlEaXNhYmxlZCAmJiBqUXVlcnkpIHsKICAgICAgaWYgKGpRdWVyeS5ldmVudC5hZGRQcm9wKSB7CiAgICAgICAgalF1ZXJ5LmV2ZW50LmFkZFByb3AoJ2RhdGFUcmFuc2ZlcicpOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIGh0dHA6Ly93d3cud2hhdHdnLm9yZy9zcGVjcy93ZWItYXBwcy9jdXJyZW50LXdvcmsvbXVsdGlwYWdlL2RuZC5odG1sI2RuZGV2ZW50cwogICAgICAgIFsnZHJhZ3N0YXJ0JywgJ2RyYWcnLCAnZHJhZ2VudGVyJywgJ2RyYWdsZWF2ZScsICdkcmFnb3ZlcicsICdkcm9wJywgJ2RyYWdlbmQnXS5mb3JFYWNoKGZ1bmN0aW9uIChldmVudE5hbWUpIHsKICAgICAgICAgIGpRdWVyeS5ldmVudC5maXhIb29rc1tldmVudE5hbWVdID0gewogICAgICAgICAgICBwcm9wczogWydkYXRhVHJhbnNmZXInXQogICAgICAgICAgfTsKICAgICAgICB9KTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgX2V4cG9ydHMualF1ZXJ5ID0galF1ZXJ5ID0gdW5kZWZpbmVkOwogICAgICBfZXhwb3J0cy5qUXVlcnlEaXNhYmxlZCA9IGpRdWVyeURpc2FibGVkID0gdHJ1ZTsKICAgIH0KICB9Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vanF1ZXJ5X2V2ZW50X2RlcHJlY2F0aW9uIiwgWyJleHBvcnRzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvZGVwcmVjYXRlZC1mZWF0dXJlcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9kZWJ1ZywgX2Vudmlyb25tZW50LCBfdXRpbHMsIF9kZXByZWNhdGVkRmVhdHVyZXMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSBhZGRKUXVlcnlFdmVudERlcHJlY2F0aW9uOwoKICAvKiBnbG9iYWwgUHJveHkgKi8KICBmdW5jdGlvbiBhZGRKUXVlcnlFdmVudERlcHJlY2F0aW9uKGpxRXZlbnQpIHsKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICYmIF9kZXByZWNhdGVkRmVhdHVyZXMuSlFVRVJZX0lOVEVHUkFUSU9OICYmIF91dGlscy5IQVNfTkFUSVZFX1BST1hZKSB7CiAgICAgIHZhciBib3VuZEZ1bmN0aW9ucyA9IG5ldyBNYXAoKTsgLy8gd3JhcCB0aGUgalF1ZXJ5IGV2ZW50IGluIGEgUHJveHkgdG8gYWRkIHRoZSBkZXByZWNhdGlvbiBtZXNzYWdlIGZvciBvcmlnaW5hbEV2ZW50LCBhY2NvcmRpbmcgdG8gUkZDIzI5NAogICAgICAvLyB3ZSBuZWVkIGEgbmF0aXZlIFByb3h5IGhlcmUsIHNvIHdlIGNhbiBtYWtlIHN1cmUgdGhhdCB0aGUgaW50ZXJuYWwgdXNlIG9mIG9yaWdpbmFsRXZlbnQgaW4galF1ZXJ5IGl0c2VsZiBkb2VzCiAgICAgIC8vIG5vdCB0cmlnZ2VyIGEgZGVwcmVjYXRpb24KCiAgICAgIHJldHVybiBuZXcgUHJveHkoanFFdmVudCwgewogICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KHRhcmdldCwgbmFtZSkgewogICAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICAgIGNhc2UgJ29yaWdpbmFsRXZlbnQnOgogICAgICAgICAgICAgIChmYWxzZSAmJiAhKGZ1bmN0aW9uIChFbWJlckVOVikgewogICAgICAgICAgICAgICAgLy8gdGhpcyBkZXByZWNhdGlvbiBpcyBpbnRlbnRpb25hbGx5IGNoZWNraW5nIGBnbG9iYWwuRW1iZXJFTlZgIC8KICAgICAgICAgICAgICAgIC8vIGBnbG9iYWwuRU5WYCBzbyB0aGF0IHdlIGNhbiBlbnN1cmUgd2UgX29ubHlfIGRlcHJlY2F0ZSBpbiB0aGUKICAgICAgICAgICAgICAgIC8vIGNhc2Ugd2hlcmUgalF1ZXJ5IGludGVncmF0aW9uIGlzIGVuYWJsZWQgaW1wbGljaXRseSAoZS5nLgogICAgICAgICAgICAgICAgLy8gImRlZmF1bHRlZCIgdG8gZW5hYmxlZCkgYXMgb3Bwb3NlZCB0byB3aGVuIHRoZSB1c2VyIGV4cGxpY2l0bHkKICAgICAgICAgICAgICAgIC8vIG9wdHMgaW4gdG8gdXNpbmcgalF1ZXJ5CiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIEVtYmVyRU5WICE9PSAnb2JqZWN0JyB8fCBFbWJlckVOViA9PT0gbnVsbCkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgcmV0dXJuIEVtYmVyRU5WLl9KUVVFUllfSU5URUdSQVRJT04gPT09IHRydWU7CiAgICAgICAgICAgICAgfShfZW52aXJvbm1lbnQuZ2xvYmFsLkVtYmVyRU5WIHx8IF9lbnZpcm9ubWVudC5nbG9iYWwuRU5WKSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdBY2Nlc3NpbmcgalF1ZXJ5LkV2ZW50IHNwZWNpZmljIHByb3BlcnRpZXMgaXMgZGVwcmVjYXRlZC4gRWl0aGVyIHVzZSB0aGUgZW1iZXItanF1ZXJ5LWxlZ2FjeSBhZGRvbiB0byBub3JtYWxpemUgZXZlbnRzIHRvIG5hdGl2ZSBldmVudHMsIG9yIGV4cGxpY2l0bHkgb3B0IGludG8galF1ZXJ5IGludGVncmF0aW9uIHVzaW5nIEBlbWJlci9vcHRpb25hbC1mZWF0dXJlcy4nLCBmdW5jdGlvbiAoRW1iZXJFTlYpIHsKICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgRW1iZXJFTlYgIT09ICdvYmplY3QnIHx8IEVtYmVyRU5WID09PSBudWxsKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICByZXR1cm4gRW1iZXJFTlYuX0pRVUVSWV9JTlRFR1JBVElPTiA9PT0gdHJ1ZTsKICAgICAgICAgICAgICB9KF9lbnZpcm9ubWVudC5nbG9iYWwuRW1iZXJFTlYgfHwgX2Vudmlyb25tZW50Lmdsb2JhbC5FTlYpLCB7CiAgICAgICAgICAgICAgICBpZDogJ2VtYmVyLXZpZXdzLmV2ZW50LWRpc3BhdGNoZXIuanF1ZXJ5LWV2ZW50JywKICAgICAgICAgICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfanF1ZXJ5LWV2ZW50JwogICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICByZXR1cm4gdGFyZ2V0W25hbWVdOwogICAgICAgICAgICAvLyBwcm92aWRlIGFuIGVzY2FwZSBoYXRjaCBmb3IgZW1iZXItanF1ZXJ5LWxlZ2FjeSB0byBhY2Nlc3Mgb3JpZ2luYWxFdmVudCB3aXRob3V0IGEgZGVwcmVjYXRpb24KCiAgICAgICAgICAgIGNhc2UgJ19fb3JpZ2luYWxFdmVudCc6CiAgICAgICAgICAgICAgcmV0dXJuIHRhcmdldC5vcmlnaW5hbEV2ZW50OwoKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldFtuYW1lXSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgICAgICAgICAgLy8gY2FjaGUgZnVuY3Rpb25zIGZvciByZXVzZQogICAgICAgICAgICAgICAgaWYgKCFib3VuZEZ1bmN0aW9ucy5oYXMobmFtZSkpIHsKICAgICAgICAgICAgICAgICAgLy8gZm9yIGpRdWVyeS5FdmVudCBtZXRob2RzIGNhbGwgdGhlbSB3aXRoIGB0YXJnZXRgIGFzIHRoZSBgdGhpc2AgY29udGV4dCwgc28gdGhleSB3aWxsIGFjY2VzcwogICAgICAgICAgICAgICAgICAvLyBgb3JpZ2luYWxFdmVudGAgZnJvbSB0aGUgb3JpZ2luYWwgalF1ZXJ5IGV2ZW50LCBub3Qgb3VyIHByb3h5LCB0aHVzIG5vdCB0cmlnZ2VyIHRoZSBkZXByZWNhdGlvbgogICAgICAgICAgICAgICAgICBib3VuZEZ1bmN0aW9ucy5zZXQobmFtZSwgdGFyZ2V0W25hbWVdLmJpbmQodGFyZ2V0KSk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgcmV0dXJuIGJvdW5kRnVuY3Rpb25zLmdldChuYW1lKTsKICAgICAgICAgICAgICB9IC8vIHNhbWUgZm9yIGpRdWVyeSdzIGdldHRlciBmdW5jdGlvbnMgZm9yIHNpbXBsZSBwcm9wZXJ0aWVzCgoKICAgICAgICAgICAgICByZXR1cm4gdGFyZ2V0W25hbWVdOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICB9CgogICAgcmV0dXJuIGpxRXZlbnQ7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2xvb2t1cF9wYXJ0aWFsIiwgWyJleHBvcnRzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvZXJyb3IiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVidWcsIF9lcnJvcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IGxvb2t1cFBhcnRpYWw7CiAgX2V4cG9ydHMuaGFzUGFydGlhbCA9IGhhc1BhcnRpYWw7CgogIGZ1bmN0aW9uIHBhcnNlVW5kZXJzY29yZWROYW1lKHRlbXBsYXRlTmFtZSkgewogICAgdmFyIG5hbWVQYXJ0cyA9IHRlbXBsYXRlTmFtZS5zcGxpdCgnLycpOwogICAgdmFyIGxhc3RQYXJ0ID0gbmFtZVBhcnRzW25hbWVQYXJ0cy5sZW5ndGggLSAxXTsKICAgIG5hbWVQYXJ0c1tuYW1lUGFydHMubGVuZ3RoIC0gMV0gPSAiXyIgKyBsYXN0UGFydDsKICAgIHJldHVybiBuYW1lUGFydHMuam9pbignLycpOwogIH0KCiAgZnVuY3Rpb24gbG9va3VwUGFydGlhbCh0ZW1wbGF0ZU5hbWUsIG93bmVyKSB7CiAgICBpZiAodGVtcGxhdGVOYW1lID09IG51bGwpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciB0ZW1wbGF0ZSA9IHRlbXBsYXRlRm9yKG93bmVyLCBwYXJzZVVuZGVyc2NvcmVkTmFtZSh0ZW1wbGF0ZU5hbWUpLCB0ZW1wbGF0ZU5hbWUpOwogICAgKGZhbHNlICYmICEoQm9vbGVhbih0ZW1wbGF0ZSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVW5hYmxlIHRvIGZpbmQgcGFydGlhbCB3aXRoIG5hbWUgXCIiICsgdGVtcGxhdGVOYW1lICsgIlwiIiwgQm9vbGVhbih0ZW1wbGF0ZSkpKTsKICAgIHJldHVybiB0ZW1wbGF0ZTsKICB9CgogIGZ1bmN0aW9uIGhhc1BhcnRpYWwobmFtZSwgb3duZXIpIHsKICAgIGlmICghb3duZXIpIHsKICAgICAgdGhyb3cgbmV3IF9lcnJvci5kZWZhdWx0KCdDb250YWluZXIgd2FzIG5vdCBmb3VuZCB3aGVuIGxvb2tpbmcgdXAgYSB2aWV3cyB0ZW1wbGF0ZS4gJyArICdUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBtYW51YWxseSBpbnN0YW50aWF0aW5nIGFuIEVtYmVyLlZpZXcuICcgKyAnU2VlOiBodHRwOi8vZ2l0LmlvL0VLUHBuQScpOwogICAgfQoKICAgIHJldHVybiBvd25lci5oYXNSZWdpc3RyYXRpb24oInRlbXBsYXRlOiIgKyBwYXJzZVVuZGVyc2NvcmVkTmFtZShuYW1lKSkgfHwgb3duZXIuaGFzUmVnaXN0cmF0aW9uKCJ0ZW1wbGF0ZToiICsgbmFtZSk7CiAgfQoKICBmdW5jdGlvbiB0ZW1wbGF0ZUZvcihvd25lciwgdW5kZXJzY29yZWQsIG5hbWUpIHsKICAgIGlmICghbmFtZSkgewogICAgICByZXR1cm47CiAgICB9CgogICAgKGZhbHNlICYmICEobmFtZS5pbmRleE9mKCcuJykgPT09IC0xKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoInRlbXBsYXRlTmFtZXMgYXJlIG5vdCBhbGxvd2VkIHRvIGNvbnRhaW4gcGVyaW9kczogIiArIG5hbWUsIG5hbWUuaW5kZXhPZignLicpID09PSAtMSkpOwoKICAgIGlmICghb3duZXIpIHsKICAgICAgdGhyb3cgbmV3IF9lcnJvci5kZWZhdWx0KCdDb250YWluZXIgd2FzIG5vdCBmb3VuZCB3aGVuIGxvb2tpbmcgdXAgYSB2aWV3cyB0ZW1wbGF0ZS4gJyArICdUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBtYW51YWxseSBpbnN0YW50aWF0aW5nIGFuIEVtYmVyLlZpZXcuICcgKyAnU2VlOiBodHRwOi8vZ2l0LmlvL0VLUHBuQScpOwogICAgfQoKICAgIHJldHVybiBvd25lci5sb29rdXAoInRlbXBsYXRlOiIgKyB1bmRlcnNjb3JlZCkgfHwgb3duZXIubG9va3VwKCJ0ZW1wbGF0ZToiICsgbmFtZSk7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL3V0aWxzIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX293bmVyLCBfdXRpbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmlzU2ltcGxlQ2xpY2sgPSBpc1NpbXBsZUNsaWNrOwogIF9leHBvcnRzLmNvbnN0cnVjdFN0eWxlRGVwcmVjYXRpb25NZXNzYWdlID0gY29uc3RydWN0U3R5bGVEZXByZWNhdGlvbk1lc3NhZ2U7CiAgX2V4cG9ydHMuZ2V0Um9vdFZpZXdzID0gZ2V0Um9vdFZpZXdzOwogIF9leHBvcnRzLmdldFZpZXdJZCA9IGdldFZpZXdJZDsKICBfZXhwb3J0cy5nZXRFbGVtZW50VmlldyA9IGdldEVsZW1lbnRWaWV3OwogIF9leHBvcnRzLmdldFZpZXdFbGVtZW50ID0gZ2V0Vmlld0VsZW1lbnQ7CiAgX2V4cG9ydHMuc2V0RWxlbWVudFZpZXcgPSBzZXRFbGVtZW50VmlldzsKICBfZXhwb3J0cy5zZXRWaWV3RWxlbWVudCA9IHNldFZpZXdFbGVtZW50OwogIF9leHBvcnRzLmNsZWFyRWxlbWVudFZpZXcgPSBjbGVhckVsZW1lbnRWaWV3OwogIF9leHBvcnRzLmNsZWFyVmlld0VsZW1lbnQgPSBjbGVhclZpZXdFbGVtZW50OwogIF9leHBvcnRzLmdldENoaWxkVmlld3MgPSBnZXRDaGlsZFZpZXdzOwogIF9leHBvcnRzLmluaXRDaGlsZFZpZXdzID0gaW5pdENoaWxkVmlld3M7CiAgX2V4cG9ydHMuYWRkQ2hpbGRWaWV3ID0gYWRkQ2hpbGRWaWV3OwogIF9leHBvcnRzLmNvbGxlY3RDaGlsZFZpZXdzID0gY29sbGVjdENoaWxkVmlld3M7CiAgX2V4cG9ydHMuZ2V0Vmlld0JvdW5kcyA9IGdldFZpZXdCb3VuZHM7CiAgX2V4cG9ydHMuZ2V0Vmlld1JhbmdlID0gZ2V0Vmlld1JhbmdlOwogIF9leHBvcnRzLmdldFZpZXdDbGllbnRSZWN0cyA9IGdldFZpZXdDbGllbnRSZWN0czsKICBfZXhwb3J0cy5nZXRWaWV3Qm91bmRpbmdDbGllbnRSZWN0ID0gZ2V0Vmlld0JvdW5kaW5nQ2xpZW50UmVjdDsKICBfZXhwb3J0cy5tYXRjaGVzID0gbWF0Y2hlczsKICBfZXhwb3J0cy5jb250YWlucyA9IGNvbnRhaW5zOwogIF9leHBvcnRzLmVsTWF0Y2hlcyA9IHZvaWQgMDsKCiAgLyogZ2xvYmFscyBFbGVtZW50ICovCgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwogIGZ1bmN0aW9uIGlzU2ltcGxlQ2xpY2soZXZlbnQpIHsKICAgIHZhciBtb2RpZmllciA9IGV2ZW50LnNoaWZ0S2V5IHx8IGV2ZW50Lm1ldGFLZXkgfHwgZXZlbnQuYWx0S2V5IHx8IGV2ZW50LmN0cmxLZXk7CiAgICB2YXIgc2Vjb25kYXJ5Q2xpY2sgPSBldmVudC53aGljaCA+IDE7IC8vIElFOSBtYXkgcmV0dXJuIHVuZGVmaW5lZAoKICAgIHJldHVybiAhbW9kaWZpZXIgJiYgIXNlY29uZGFyeUNsaWNrOwogIH0KCiAgZnVuY3Rpb24gY29uc3RydWN0U3R5bGVEZXByZWNhdGlvbk1lc3NhZ2UoYWZmZWN0ZWRTdHlsZSkgewogICAgcmV0dXJuICcnICsgJ0JpbmRpbmcgc3R5bGUgYXR0cmlidXRlcyBtYXkgaW50cm9kdWNlIGNyb3NzLXNpdGUgc2NyaXB0aW5nIHZ1bG5lcmFiaWxpdGllczsgJyArICdwbGVhc2UgZW5zdXJlIHRoYXQgdmFsdWVzIGJlaW5nIGJvdW5kIGFyZSBwcm9wZXJseSBlc2NhcGVkLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgJyArICdpbmNsdWRpbmcgaG93IHRvIGRpc2FibGUgdGhpcyB3YXJuaW5nLCBzZWUgJyArICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92MS54LyN0b2NfYmluZGluZy1zdHlsZS1hdHRyaWJ1dGVzLiAnICsgJ1N0eWxlIGFmZmVjdGVkOiAiJyArIGFmZmVjdGVkU3R5bGUgKyAnIic7CiAgfQogIC8qKgogICAgQHByaXZhdGUKICAgIEBtZXRob2QgZ2V0Um9vdFZpZXdzCiAgICBAcGFyYW0ge09iamVjdH0gb3duZXIKICAqLwoKCiAgZnVuY3Rpb24gZ2V0Um9vdFZpZXdzKG93bmVyKSB7CiAgICB2YXIgcmVnaXN0cnkgPSBvd25lci5sb29rdXAoJy12aWV3LXJlZ2lzdHJ5Om1haW4nKTsKICAgIHZhciByb290Vmlld3MgPSBbXTsKICAgIE9iamVjdC5rZXlzKHJlZ2lzdHJ5KS5mb3JFYWNoKGZ1bmN0aW9uIChpZCkgewogICAgICB2YXIgdmlldyA9IHJlZ2lzdHJ5W2lkXTsKCiAgICAgIGlmICh2aWV3LnBhcmVudFZpZXcgPT09IG51bGwpIHsKICAgICAgICByb290Vmlld3MucHVzaCh2aWV3KTsKICAgICAgfQogICAgfSk7CiAgICByZXR1cm4gcm9vdFZpZXdzOwogIH0KICAvKioKICAgIEBwcml2YXRlCiAgICBAbWV0aG9kIGdldFZpZXdJZAogICAgQHBhcmFtIHtFbWJlci5WaWV3fSB2aWV3CiAgICovCgoKICBmdW5jdGlvbiBnZXRWaWV3SWQodmlldykgewogICAgaWYgKHZpZXcudGFnTmFtZSAhPT0gJycgJiYgdmlldy5lbGVtZW50SWQpIHsKICAgICAgcmV0dXJuIHZpZXcuZWxlbWVudElkOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuICgwLCBfdXRpbHMuZ3VpZEZvcikodmlldyk7CiAgICB9CiAgfQoKICB2YXIgRUxFTUVOVF9WSUVXID0gbmV3IFdlYWtNYXAoKTsKICB2YXIgVklFV19FTEVNRU5UID0gbmV3IFdlYWtNYXAoKTsKCiAgZnVuY3Rpb24gZ2V0RWxlbWVudFZpZXcoZWxlbWVudCkgewogICAgcmV0dXJuIEVMRU1FTlRfVklFVy5nZXQoZWxlbWVudCkgfHwgbnVsbDsKICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCBnZXRWaWV3RWxlbWVudAogICAgQHBhcmFtIHtFbWJlci5WaWV3fSB2aWV3CiAgICovCgoKICBmdW5jdGlvbiBnZXRWaWV3RWxlbWVudCh2aWV3KSB7CiAgICByZXR1cm4gVklFV19FTEVNRU5ULmdldCh2aWV3KSB8fCBudWxsOwogIH0KCiAgZnVuY3Rpb24gc2V0RWxlbWVudFZpZXcoZWxlbWVudCwgdmlldykgewogICAgRUxFTUVOVF9WSUVXLnNldChlbGVtZW50LCB2aWV3KTsKICB9CgogIGZ1bmN0aW9uIHNldFZpZXdFbGVtZW50KHZpZXcsIGVsZW1lbnQpIHsKICAgIFZJRVdfRUxFTUVOVC5zZXQodmlldywgZWxlbWVudCk7CiAgfSAvLyBUaGVzZSBhcmUgbm90IG5lZWRlZCBmb3IgR0MsIGJ1dCBmb3IgY29ycmVjdG5lc3MuIFdlIHdhbnQgdG8gYmUgYWJsZSB0bwogIC8vIG51bGwtb3V0IHRoZXNlIGxpbmtzIHdoaWxlIHRoZSBvYmplY3RzIGFyZSBzdGlsbCBsaXZlLiBTcGVjaWZpY2FsbHksIGluCiAgLy8gdGhpcyBjYXNlLCB3ZSB3YW50IHRvIHByZXZlbnQgYWNjZXNzIHRvIHRoZSBlbGVtZW50IChhbmQgdmljZSB2ZXJzZSkgZHVyaW5nCiAgLy8gZGVzdHJ1Y3Rpb24uCgoKICBmdW5jdGlvbiBjbGVhckVsZW1lbnRWaWV3KGVsZW1lbnQpIHsKICAgIEVMRU1FTlRfVklFVy5kZWxldGUoZWxlbWVudCk7CiAgfQoKICBmdW5jdGlvbiBjbGVhclZpZXdFbGVtZW50KHZpZXcpIHsKICAgIFZJRVdfRUxFTUVOVC5kZWxldGUodmlldyk7CiAgfQoKICB2YXIgQ0hJTERfVklFV19JRFMgPSBuZXcgV2Vha01hcCgpOwogIC8qKgogICAgQHByaXZhdGUKICAgIEBtZXRob2QgZ2V0Q2hpbGRWaWV3cwogICAgQHBhcmFtIHtFbWJlci5WaWV3fSB2aWV3CiAgKi8KCiAgZnVuY3Rpb24gZ2V0Q2hpbGRWaWV3cyh2aWV3KSB7CiAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh2aWV3KTsKICAgIHZhciByZWdpc3RyeSA9IG93bmVyLmxvb2t1cCgnLXZpZXctcmVnaXN0cnk6bWFpbicpOwogICAgcmV0dXJuIGNvbGxlY3RDaGlsZFZpZXdzKHZpZXcsIHJlZ2lzdHJ5KTsKICB9CgogIGZ1bmN0aW9uIGluaXRDaGlsZFZpZXdzKHZpZXcpIHsKICAgIHZhciBjaGlsZFZpZXdzID0gbmV3IFNldCgpOwogICAgQ0hJTERfVklFV19JRFMuc2V0KHZpZXcsIGNoaWxkVmlld3MpOwogICAgcmV0dXJuIGNoaWxkVmlld3M7CiAgfQoKICBmdW5jdGlvbiBhZGRDaGlsZFZpZXcocGFyZW50LCBjaGlsZCkgewogICAgdmFyIGNoaWxkVmlld3MgPSBDSElMRF9WSUVXX0lEUy5nZXQocGFyZW50KTsKCiAgICBpZiAoY2hpbGRWaWV3cyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGNoaWxkVmlld3MgPSBpbml0Q2hpbGRWaWV3cyhwYXJlbnQpOwogICAgfQoKICAgIGNoaWxkVmlld3MuYWRkKGdldFZpZXdJZChjaGlsZCkpOwogIH0KCiAgZnVuY3Rpb24gY29sbGVjdENoaWxkVmlld3ModmlldywgcmVnaXN0cnkpIHsKICAgIHZhciB2aWV3cyA9IFtdOwogICAgdmFyIGNoaWxkVmlld3MgPSBDSElMRF9WSUVXX0lEUy5nZXQodmlldyk7CgogICAgaWYgKGNoaWxkVmlld3MgIT09IHVuZGVmaW5lZCkgewogICAgICBjaGlsZFZpZXdzLmZvckVhY2goZnVuY3Rpb24gKGlkKSB7CiAgICAgICAgdmFyIHZpZXcgPSByZWdpc3RyeVtpZF07CgogICAgICAgIGlmICh2aWV3ICYmICF2aWV3LmlzRGVzdHJveWluZyAmJiAhdmlldy5pc0Rlc3Ryb3llZCkgewogICAgICAgICAgdmlld3MucHVzaCh2aWV3KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQoKICAgIHJldHVybiB2aWV3czsKICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCBnZXRWaWV3Qm91bmRzCiAgICBAcGFyYW0ge0VtYmVyLlZpZXd9IHZpZXcKICAqLwoKCiAgZnVuY3Rpb24gZ2V0Vmlld0JvdW5kcyh2aWV3KSB7CiAgICByZXR1cm4gdmlldy5yZW5kZXJlci5nZXRCb3VuZHModmlldyk7CiAgfQogIC8qKgogICAgQHByaXZhdGUKICAgIEBtZXRob2QgZ2V0Vmlld1JhbmdlCiAgICBAcGFyYW0ge0VtYmVyLlZpZXd9IHZpZXcKICAqLwoKCiAgZnVuY3Rpb24gZ2V0Vmlld1JhbmdlKHZpZXcpIHsKICAgIHZhciBib3VuZHMgPSBnZXRWaWV3Qm91bmRzKHZpZXcpOwogICAgdmFyIHJhbmdlID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTsKICAgIHJhbmdlLnNldFN0YXJ0QmVmb3JlKGJvdW5kcy5maXJzdE5vZGUpOwogICAgcmFuZ2Uuc2V0RW5kQWZ0ZXIoYm91bmRzLmxhc3ROb2RlKTsKICAgIHJldHVybiByYW5nZTsKICB9CiAgLyoqCiAgICBgZ2V0Vmlld0NsaWVudFJlY3RzYCBwcm92aWRlcyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcG9zaXRpb24gb2YgdGhlIGJvcmRlcgogICAgYm94IGVkZ2VzIG9mIGEgdmlldyByZWxhdGl2ZSB0byB0aGUgdmlld3BvcnQuCiAgCiAgICBJdCBpcyBvbmx5IGludGVuZGVkIHRvIGJlIHVzZWQgYnkgZGV2ZWxvcG1lbnQgdG9vbHMgbGlrZSB0aGUgRW1iZXIgSW5zcGVjdG9yCiAgICBhbmQgbWF5IG5vdCB3b3JrIG9uIG9sZGVyIGJyb3dzZXJzLgogIAogICAgQHByaXZhdGUKICAgIEBtZXRob2QgZ2V0Vmlld0NsaWVudFJlY3RzCiAgICBAcGFyYW0ge0VtYmVyLlZpZXd9IHZpZXcKICAqLwoKCiAgZnVuY3Rpb24gZ2V0Vmlld0NsaWVudFJlY3RzKHZpZXcpIHsKICAgIHZhciByYW5nZSA9IGdldFZpZXdSYW5nZSh2aWV3KTsKICAgIHJldHVybiByYW5nZS5nZXRDbGllbnRSZWN0cygpOwogIH0KICAvKioKICAgIGBnZXRWaWV3Qm91bmRpbmdDbGllbnRSZWN0YCBwcm92aWRlcyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcG9zaXRpb24gb2YgdGhlCiAgICBib3VuZGluZyBib3JkZXIgYm94IGVkZ2VzIG9mIGEgdmlldyByZWxhdGl2ZSB0byB0aGUgdmlld3BvcnQuCiAgCiAgICBJdCBpcyBvbmx5IGludGVuZGVkIHRvIGJlIHVzZWQgYnkgZGV2ZWxvcG1lbnQgdG9vbHMgbGlrZSB0aGUgRW1iZXIgSW5zcGVjdG9yCiAgICBhbmQgbWF5IG5vdCB3b3JrIG9uIG9sZGVyIGJyb3dzZXJzLgogIAogICAgQHByaXZhdGUKICAgIEBtZXRob2QgZ2V0Vmlld0JvdW5kaW5nQ2xpZW50UmVjdAogICAgQHBhcmFtIHtFbWJlci5WaWV3fSB2aWV3CiAgKi8KCgogIGZ1bmN0aW9uIGdldFZpZXdCb3VuZGluZ0NsaWVudFJlY3QodmlldykgewogICAgdmFyIHJhbmdlID0gZ2V0Vmlld1JhbmdlKHZpZXcpOwogICAgcmV0dXJuIHJhbmdlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOwogIH0KICAvKioKICAgIERldGVybWluZXMgaWYgdGhlIGVsZW1lbnQgbWF0Y2hlcyB0aGUgc3BlY2lmaWVkIHNlbGVjdG9yLgogIAogICAgQHByaXZhdGUKICAgIEBtZXRob2QgbWF0Y2hlcwogICAgQHBhcmFtIHtET01FbGVtZW50fSBlbAogICAgQHBhcmFtIHtTdHJpbmd9IHNlbGVjdG9yCiAgKi8KCgogIHZhciBlbE1hdGNoZXMgPSB0eXBlb2YgRWxlbWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgKEVsZW1lbnQucHJvdG90eXBlLm1hdGNoZXMgfHwgRWxlbWVudC5wcm90b3R5cGUubWF0Y2hlc1NlbGVjdG9yIHx8IEVsZW1lbnQucHJvdG90eXBlLm1vek1hdGNoZXNTZWxlY3RvciB8fCBFbGVtZW50LnByb3RvdHlwZS5tc01hdGNoZXNTZWxlY3RvciB8fCBFbGVtZW50LnByb3RvdHlwZS5vTWF0Y2hlc1NlbGVjdG9yIHx8IEVsZW1lbnQucHJvdG90eXBlLndlYmtpdE1hdGNoZXNTZWxlY3Rvcik7CiAgX2V4cG9ydHMuZWxNYXRjaGVzID0gZWxNYXRjaGVzOwoKICBmdW5jdGlvbiBtYXRjaGVzKGVsLCBzZWxlY3RvcikgewogICAgcmV0dXJuIGVsTWF0Y2hlcy5jYWxsKGVsLCBzZWxlY3Rvcik7CiAgfQoKICBmdW5jdGlvbiBjb250YWlucyhhLCBiKSB7CiAgICBpZiAoYS5jb250YWlucyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBhLmNvbnRhaW5zKGIpOwogICAgfQoKICAgIHdoaWxlIChiID0gYi5wYXJlbnROb2RlKSB7CiAgICAgIGlmIChiID09PSBhKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gZmFsc2U7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvdmlld3MvY29yZV92aWV3IiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9ydW50aW1lLCBfc3RhdGVzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgIGBFbWJlci5Db3JlVmlld2AgaXMgYW4gYWJzdHJhY3QgY2xhc3MgdGhhdCBleGlzdHMgdG8gZ2l2ZSB2aWV3LWxpa2UgYmVoYXZpb3IKICAgIHRvIGJvdGggRW1iZXIncyBtYWluIHZpZXcgY2xhc3MgYENvbXBvbmVudGAgYW5kIG90aGVyIGNsYXNzZXMgdGhhdCBkb24ndCBuZWVkCiAgICB0aGUgZnVsbCBmdW5jdGlvbmFsaXR5IG9mIGBDb21wb25lbnRgLgogIAogICAgVW5sZXNzIHlvdSBoYXZlIHNwZWNpZmljIG5lZWRzIGZvciBgQ29yZVZpZXdgLCB5b3Ugd2lsbCB1c2UgYENvbXBvbmVudGAKICAgIGluIHlvdXIgYXBwbGljYXRpb25zLgogIAogICAgQGNsYXNzIENvcmVWaWV3CiAgICBAbmFtZXNwYWNlIEVtYmVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQGRlcHJlY2F0ZWQgVXNlIGBDb21wb25lbnRgIGluc3RlYWQuCiAgICBAdXNlcyBFdmVudGVkCiAgICBAdXNlcyBFbWJlci5BY3Rpb25IYW5kbGVyCiAgICBAcHJpdmF0ZQogICovCiAgdmFyIENvcmVWaWV3ID0gX3J1bnRpbWUuRnJhbWV3b3JrT2JqZWN0LmV4dGVuZChfcnVudGltZS5FdmVudGVkLCBfcnVudGltZS5BY3Rpb25IYW5kbGVyLCB7CiAgICBpc1ZpZXc6IHRydWUsCiAgICBfc3RhdGVzOiBfc3RhdGVzLmRlZmF1bHQsCiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgdGhpcy5fc3RhdGUgPSAncHJlUmVuZGVyJzsKICAgICAgdGhpcy5fY3VycmVudFN0YXRlID0gdGhpcy5fc3RhdGVzLnByZVJlbmRlcjsKCiAgICAgIGlmICghdGhpcy5yZW5kZXJlcikgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiQ2Fubm90IGluc3RhbnRpYXRlIGEgY29tcG9uZW50IHdpdGhvdXQgYSByZW5kZXJlci4gUGxlYXNlIGVuc3VyZSB0aGF0IHlvdSBhcmUgY3JlYXRpbmcgIiArIHRoaXMgKyAiIHdpdGggYSBwcm9wZXIgY29udGFpbmVyL3JlZ2lzdHJ5LiIpOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBJZiB0aGUgdmlldyBpcyBjdXJyZW50bHkgaW5zZXJ0ZWQgaW50byB0aGUgRE9NIG9mIGEgcGFyZW50IHZpZXcsIHRoaXMKICAgICAgcHJvcGVydHkgd2lsbCBwb2ludCB0byB0aGUgcGFyZW50IG9mIHRoZSB2aWV3LgogICAgICAgQHByb3BlcnR5IHBhcmVudFZpZXcKICAgICAgQHR5cGUgRW1iZXIuVmlldwogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgcGFyZW50VmlldzogbnVsbCwKICAgIGluc3RydW1lbnREZXRhaWxzOiBmdW5jdGlvbiBpbnN0cnVtZW50RGV0YWlscyhoYXNoKSB7CiAgICAgIGhhc2gub2JqZWN0ID0gdGhpcy50b1N0cmluZygpOwogICAgICBoYXNoLmNvbnRhaW5lcktleSA9IHRoaXMuX2RlYnVnQ29udGFpbmVyS2V5OwogICAgICBoYXNoLnZpZXcgPSB0aGlzOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0sCgogICAgLyoqCiAgICAgIE92ZXJyaWRlIHRoZSBkZWZhdWx0IGV2ZW50IGZpcmluZyBmcm9tIGBFdmVudGVkYCB0bwogICAgICBhbHNvIGNhbGwgbWV0aG9kcyB3aXRoIHRoZSBnaXZlbiBuYW1lLgogICAgICAgQG1ldGhvZCB0cmlnZ2VyCiAgICAgIEBwYXJhbSBuYW1lIHtTdHJpbmd9CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgdHJpZ2dlcjogZnVuY3Rpb24gdHJpZ2dlcihuYW1lKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4gPiAxID8gX2xlbiAtIDEgOiAwKSwgX2tleSA9IDE7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgICBhcmdzW19rZXkgLSAxXSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgICAgfQoKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIHZhciBtZXRob2QgPSB0aGlzW25hbWVdOwoKICAgICAgaWYgKHR5cGVvZiBtZXRob2QgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICByZXR1cm4gbWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3MpOwogICAgICB9CiAgICB9LAogICAgaGFzOiBmdW5jdGlvbiBoYXMobmFtZSkgewogICAgICByZXR1cm4gdHlwZW9mIHRoaXNbbmFtZV0gPT09ICdmdW5jdGlvbicgfHwgdGhpcy5fc3VwZXIobmFtZSk7CiAgICB9CiAgfSk7CgogIENvcmVWaWV3LnJlb3BlbkNsYXNzKHsKICAgIGlzVmlld0ZhY3Rvcnk6IHRydWUKICB9KTsKICB2YXIgX2RlZmF1bHQgPSBDb3JlVmlldzsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9wcmVfcmVuZGVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvaGFzX2VsZW1lbnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9pbl9kb20iLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9kZXN0cm95aW5nIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3ByZV9yZW5kZXIsIF9oYXNfZWxlbWVudCwgX2luX2RvbSwgX2Rlc3Ryb3lpbmcpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qCiAgICBEZXNjcmliZSBob3cgdGhlIHNwZWNpZmllZCBhY3Rpb25zIHNob3VsZCBiZWhhdmUgaW4gdGhlIHZhcmlvdXMKICAgIHN0YXRlcyB0aGF0IGEgdmlldyBjYW4gZXhpc3QgaW4uIFBvc3NpYmxlIHN0YXRlczoKICAKICAgICogcHJlUmVuZGVyOiB3aGVuIGEgdmlldyBpcyBmaXJzdCBpbnN0YW50aWF0ZWQsIGFuZCBhZnRlciBpdHMKICAgICAgZWxlbWVudCB3YXMgZGVzdHJveWVkLCBpdCBpcyBpbiB0aGUgcHJlUmVuZGVyIHN0YXRlCiAgICAqIGhhc0VsZW1lbnQ6IHRoZSBET00gcmVwcmVzZW50YXRpb24gb2YgdGhlIHZpZXcgaXMgY3JlYXRlZCwKICAgICAgYW5kIGlzIHJlYWR5IHRvIGJlIGluc2VydGVkCiAgICAqIGluRE9NOiBvbmNlIGEgdmlldyBoYXMgYmVlbiBpbnNlcnRlZCBpbnRvIHRoZSBET00gaXQgaXMgaW4KICAgICAgdGhlIGluRE9NIHN0YXRlLiBBIHZpZXcgc3BlbmRzIHRoZSB2YXN0IG1ham9yaXR5IG9mIGl0cwogICAgICBleGlzdGVuY2UgaW4gdGhpcyBzdGF0ZS4KICAgICogZGVzdHJveWVkOiBvbmNlIGEgdmlldyBoYXMgYmVlbiBkZXN0cm95ZWQgKHVzaW5nIHRoZSBkZXN0cm95CiAgICAgIG1ldGhvZCksIGl0IGlzIGluIHRoaXMgc3RhdGUuIE5vIGZ1cnRoZXIgYWN0aW9ucyBjYW4gYmUgaW52b2tlZAogICAgICBvbiBhIGRlc3Ryb3llZCB2aWV3LgogICovCiAgdmFyIHN0YXRlcyA9IE9iamVjdC5mcmVlemUoewogICAgcHJlUmVuZGVyOiBfcHJlX3JlbmRlci5kZWZhdWx0LAogICAgaW5ET006IF9pbl9kb20uZGVmYXVsdCwKICAgIGhhc0VsZW1lbnQ6IF9oYXNfZWxlbWVudC5kZWZhdWx0LAogICAgZGVzdHJveWluZzogX2Rlc3Ryb3lpbmcuZGVmYXVsdAogIH0pOwogIHZhciBfZGVmYXVsdCA9IHN0YXRlczsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvZGVmYXVsdCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZXJyb3IiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZXJyb3IpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CiAgdmFyIF9kZWZhdWx0ID0gewogICAgLy8gYXBwZW5kQ2hpbGQgaXMgb25seSBsZWdhbCB3aGlsZSByZW5kZXJpbmcgdGhlIGJ1ZmZlci4KICAgIGFwcGVuZENoaWxkOiBmdW5jdGlvbiBhcHBlbmRDaGlsZCgpIHsKICAgICAgdGhyb3cgbmV3IF9lcnJvci5kZWZhdWx0KCJZb3UgY2FuJ3QgdXNlIGFwcGVuZENoaWxkIG91dHNpZGUgb2YgdGhlIHJlbmRlcmluZyBwcm9jZXNzIik7CiAgICB9LAogICAgLy8gSGFuZGxlIGV2ZW50cyBmcm9tIGBFbWJlci5FdmVudERpc3BhdGNoZXJgCiAgICBoYW5kbGVFdmVudDogZnVuY3Rpb24gaGFuZGxlRXZlbnQoKSB7CiAgICAgIHJldHVybiB0cnVlOyAvLyBjb250aW51ZSBldmVudCBwcm9wYWdhdGlvbgogICAgfSwKICAgIHJlcmVuZGVyOiBmdW5jdGlvbiByZXJlbmRlcigpIHt9LAogICAgZGVzdHJveTogZnVuY3Rpb24gZGVzdHJveSgpIHt9CiAgfTsKCiAgdmFyIF9kZWZhdWx0MiA9IE9iamVjdC5mcmVlemUoX2RlZmF1bHQpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQyOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvdmlld3Mvc3RhdGVzL2Rlc3Ryb3lpbmciLCBbImV4cG9ydHMiLCAiQGVtYmVyL3BvbHlmaWxscyIsICJAZW1iZXIvZXJyb3IiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9kZWZhdWx0Il0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3BvbHlmaWxscywgX2Vycm9yLCBfZGVmYXVsdDMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CiAgdmFyIGRlc3Ryb3lpbmcgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBfZGVmYXVsdDMuZGVmYXVsdCwgewogICAgYXBwZW5kQ2hpbGQ6IGZ1bmN0aW9uIGFwcGVuZENoaWxkKCkgewogICAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIllvdSBjYW4ndCBjYWxsIGFwcGVuZENoaWxkIG9uIGEgdmlldyBiZWluZyBkZXN0cm95ZWQiKTsKICAgIH0sCiAgICByZXJlbmRlcjogZnVuY3Rpb24gcmVyZW5kZXIoKSB7CiAgICAgIHRocm93IG5ldyBfZXJyb3IuZGVmYXVsdCgiWW91IGNhbid0IGNhbGwgcmVyZW5kZXIgb24gYSB2aWV3IGJlaW5nIGRlc3Ryb3llZCIpOwogICAgfQogIH0pOwoKICB2YXIgX2RlZmF1bHQyID0gT2JqZWN0LmZyZWV6ZShkZXN0cm95aW5nKTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0MjsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9oYXNfZWxlbWVudCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvcG9seWZpbGxzIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvZGVmYXVsdCIsICJAZW1iZXIvcnVubG9vcCIsICJAZW1iZXIvaW5zdHJ1bWVudGF0aW9uIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3BvbHlmaWxscywgX2RlZmF1bHQzLCBfcnVubG9vcCwgX2luc3RydW1lbnRhdGlvbikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKICB2YXIgaGFzRWxlbWVudCA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIF9kZWZhdWx0My5kZWZhdWx0LCB7CiAgICByZXJlbmRlcjogZnVuY3Rpb24gcmVyZW5kZXIodmlldykgewogICAgICB2aWV3LnJlbmRlcmVyLnJlcmVuZGVyKHZpZXcpOwogICAgfSwKICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3kodmlldykgewogICAgICB2aWV3LnJlbmRlcmVyLnJlbW92ZSh2aWV3KTsKICAgIH0sCiAgICAvLyBIYW5kbGUgZXZlbnRzIGZyb20gYEVtYmVyLkV2ZW50RGlzcGF0Y2hlcmAKICAgIGhhbmRsZUV2ZW50OiBmdW5jdGlvbiBoYW5kbGVFdmVudCh2aWV3LCBldmVudE5hbWUsIGV2ZW50KSB7CiAgICAgIGlmICh2aWV3LmhhcyhldmVudE5hbWUpKSB7CiAgICAgICAgLy8gSGFuZGxlciBzaG91bGQgYmUgYWJsZSB0byByZS1kaXNwYXRjaCBldmVudHMsIHNvIHdlIGRvbid0CiAgICAgICAgLy8gcHJldmVudERlZmF1bHQgb3Igc3RvcFByb3BhZ2F0aW9uLgogICAgICAgIHJldHVybiAoMCwgX2luc3RydW1lbnRhdGlvbi5mbGFnZ2VkSW5zdHJ1bWVudCkoImludGVyYWN0aW9uLiIgKyBldmVudE5hbWUsIHsKICAgICAgICAgIGV2ZW50OiBldmVudCwKICAgICAgICAgIHZpZXc6IHZpZXcKICAgICAgICB9LCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gKDAsIF9ydW5sb29wLmpvaW4pKHZpZXcsIHZpZXcudHJpZ2dlciwgZXZlbnROYW1lLCBldmVudCk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHRydWU7IC8vIGNvbnRpbnVlIGV2ZW50IHByb3BhZ2F0aW9uCiAgICAgIH0KICAgIH0KICB9KTsKCiAgdmFyIF9kZWZhdWx0MiA9IE9iamVjdC5mcmVlemUoaGFzRWxlbWVudCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDI7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvaW5fZG9tIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiQGVtYmVyL2Vycm9yIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvaGFzX2VsZW1lbnQiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdXRpbHMsIF9wb2x5ZmlsbHMsIF9lcnJvciwgX2hhc19lbGVtZW50KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwogIHZhciBpbkRPTSA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIF9oYXNfZWxlbWVudC5kZWZhdWx0LCB7CiAgICBlbnRlcjogZnVuY3Rpb24gZW50ZXIodmlldykgewogICAgICAvLyBSZWdpc3RlciB0aGUgdmlldyBmb3IgZXZlbnQgaGFuZGxpbmcuIFRoaXMgaGFzaCBpcyB1c2VkIGJ5CiAgICAgIC8vIEVtYmVyLkV2ZW50RGlzcGF0Y2hlciB0byBkaXNwYXRjaCBpbmNvbWluZyBldmVudHMuCiAgICAgIHZpZXcucmVuZGVyZXIucmVnaXN0ZXIodmlldyk7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgdmFyIGVsZW1lbnRJZCA9IHZpZXcuZWxlbWVudElkOwoKICAgICAgICBpZiAodHJ1ZQogICAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICAgICkgewogICAgICAgICAgICAoMCwgX3V0aWxzLnRlYXJkb3duTWFuZGF0b3J5U2V0dGVyKSh2aWV3LCAnZWxlbWVudElkJyk7CiAgICAgICAgICB9CgogICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh2aWV3LCAnZWxlbWVudElkJywgewogICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgICAgICByZXR1cm4gZWxlbWVudElkOwogICAgICAgICAgfSwKICAgICAgICAgIHNldDogZnVuY3Rpb24gc2V0KCkgewogICAgICAgICAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIkNoYW5naW5nIGEgdmlldydzIGVsZW1lbnRJZCBhZnRlciBjcmVhdGlvbiBpcyBub3QgYWxsb3dlZCIpOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CiAgICB9LAogICAgZXhpdDogZnVuY3Rpb24gZXhpdCh2aWV3KSB7CiAgICAgIHZpZXcucmVuZGVyZXIudW5yZWdpc3Rlcih2aWV3KTsKICAgIH0KICB9KTsKCiAgdmFyIF9kZWZhdWx0ID0gT2JqZWN0LmZyZWV6ZShpbkRPTSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9wcmVfcmVuZGVyIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvZGVmYXVsdCIsICJAZW1iZXIvcG9seWZpbGxzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlZmF1bHQzLCBfcG9seWZpbGxzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwogIHZhciBwcmVSZW5kZXIgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBfZGVmYXVsdDMuZGVmYXVsdCk7CgogIHZhciBfZGVmYXVsdDIgPSBPYmplY3QuZnJlZXplKHByZVJlbmRlcik7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDI7Cn0pOwpkZWZpbmUoIkBlbWJlci9hcHBsaWNhdGlvbi9nbG9iYWxzLXJlc29sdmVyIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvc3RyaW5nIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyL2FwcGxpY2F0aW9uL2xpYi92YWxpZGF0ZS10eXBlIiwgIkBlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX3V0aWxzLCBfbWV0YWwsIF9kZWJ1ZywgX3N0cmluZywgX3J1bnRpbWUsIF92YWxpZGF0ZVR5cGUsIF9nbGltbWVyKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIEBlbWJlci9hcHBsaWNhdGlvbgogICovCgogIC8qKgogICAgVGhlIERlZmF1bHRSZXNvbHZlciBkZWZpbmVzIHRoZSBkZWZhdWx0IGxvb2t1cCBydWxlcyB0byByZXNvbHZlCiAgICBjb250YWluZXIgbG9va3VwcyBiZWZvcmUgY29uc3VsdGluZyB0aGUgY29udGFpbmVyIGZvciByZWdpc3RlcmVkCiAgICBpdGVtczoKICAKICAgICogdGVtcGxhdGVzIGFyZSBsb29rZWQgdXAgb24gYEVtYmVyLlRFTVBMQVRFU2AKICAgICogb3RoZXIgbmFtZXMgYXJlIGxvb2tlZCB1cCBvbiB0aGUgYXBwbGljYXRpb24gYWZ0ZXIgY29udmVydGluZwogICAgICB0aGUgbmFtZS4gRm9yIGV4YW1wbGUsIGBjb250cm9sbGVyOnBvc3RgIGxvb2tzIHVwCiAgICAgIGBBcHAuUG9zdENvbnRyb2xsZXJgIGJ5IGRlZmF1bHQuCiAgICAqIHRoZXJlIGFyZSBzb21lIG51YW5jZXMgKHNlZSBleGFtcGxlcyBiZWxvdykKICAKICAgICMjIyBIb3cgUmVzb2x2aW5nIFdvcmtzCiAgCiAgICBUaGUgY29udGFpbmVyIGNhbGxzIHRoaXMgb2JqZWN0J3MgYHJlc29sdmVgIG1ldGhvZCB3aXRoIHRoZQogICAgYGZ1bGxOYW1lYCBhcmd1bWVudC4KICAKICAgIEl0IGZpcnN0IHBhcnNlcyB0aGUgZnVsbE5hbWUgaW50byBhbiBvYmplY3QgdXNpbmcgYHBhcnNlTmFtZWAuCiAgCiAgICBUaGVuIGl0IGNoZWNrcyBmb3IgdGhlIHByZXNlbmNlIG9mIGEgdHlwZS1zcGVjaWZpYyBpbnN0YW5jZQogICAgbWV0aG9kIG9mIHRoZSBmb3JtIGByZXNvbHZlW1R5cGVdYCBhbmQgY2FsbHMgaXQgaWYgaXQgZXhpc3RzLgogICAgRm9yIGV4YW1wbGUgaWYgaXQgd2FzIHJlc29sdmluZyAndGVtcGxhdGU6cG9zdCcsIGl0IHdvdWxkIGNhbGwKICAgIHRoZSBgcmVzb2x2ZVRlbXBsYXRlYCBtZXRob2QuCiAgCiAgICBJdHMgbGFzdCByZXNvcnQgaXMgdG8gY2FsbCB0aGUgYHJlc29sdmVPdGhlcmAgbWV0aG9kLgogIAogICAgVGhlIG1ldGhvZHMgb2YgdGhpcyBvYmplY3QgYXJlIGRlc2lnbmVkIHRvIGJlIGVhc3kgdG8gb3ZlcnJpZGUKICAgIGluIGEgc3ViY2xhc3MuIEZvciBleGFtcGxlLCB5b3UgY291bGQgZW5oYW5jZSBob3cgYSB0ZW1wbGF0ZQogICAgaXMgcmVzb2x2ZWQgbGlrZSBzbzoKICAKICAgIGBgYGFwcC9hcHAuanMKICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgaW1wb3J0IEdsb2JhbHNSZXNvbHZlciBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24vZ2xvYmFscy1yZXNvbHZlcic7CiAgCiAgICBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoewogICAgICBSZXNvbHZlcjogR2xvYmFsc1Jlc29sdmVyLmV4dGVuZCh7CiAgICAgICAgcmVzb2x2ZVRlbXBsYXRlKHBhcnNlZE5hbWUpIHsKICAgICAgICAgIGxldCByZXNvbHZlZFRlbXBsYXRlID0gdGhpcy5fc3VwZXIocGFyc2VkTmFtZSk7CiAgICAgICAgICBpZiAocmVzb2x2ZWRUZW1wbGF0ZSkgeyByZXR1cm4gcmVzb2x2ZWRUZW1wbGF0ZTsgfQogIAogICAgICAgICAgcmV0dXJuIEVtYmVyLlRFTVBMQVRFU1snbm90X2ZvdW5kJ107CiAgICAgICAgfQogICAgICB9KQogICAgfSk7CiAgICBgYGAKICAKICAgIFNvbWUgZXhhbXBsZXMgb2YgaG93IG5hbWVzIGFyZSByZXNvbHZlZDoKICAKICAgIGBgYHRleHQKICAgICd0ZW1wbGF0ZTpwb3N0JyAgICAgICAgICAgLy89PiBFbWJlci5URU1QTEFURVNbJ3Bvc3QnXQogICAgJ3RlbXBsYXRlOnBvc3RzL2J5bGluZScgICAvLz0+IEVtYmVyLlRFTVBMQVRFU1sncG9zdHMvYnlsaW5lJ10KICAgICd0ZW1wbGF0ZTpwb3N0cy5ieWxpbmUnICAgLy89PiBFbWJlci5URU1QTEFURVNbJ3Bvc3RzL2J5bGluZSddCiAgICAndGVtcGxhdGU6YmxvZ1Bvc3QnICAgICAgIC8vPT4gRW1iZXIuVEVNUExBVEVTWydibG9nLXBvc3QnXQogICAgJ2NvbnRyb2xsZXI6cG9zdCcgICAgICAgICAvLz0+IEFwcC5Qb3N0Q29udHJvbGxlcgogICAgJ2NvbnRyb2xsZXI6cG9zdHMuaW5kZXgnICAvLz0+IEFwcC5Qb3N0c0luZGV4Q29udHJvbGxlcgogICAgJ2NvbnRyb2xsZXI6YmxvZy9wb3N0JyAgICAvLz0+IEJsb2cuUG9zdENvbnRyb2xsZXIKICAgICdjb250cm9sbGVyOmJhc2ljJyAgICAgICAgLy89PiBDb250cm9sbGVyCiAgICAncm91dGU6cG9zdCcgICAgICAgICAgICAgIC8vPT4gQXBwLlBvc3RSb3V0ZQogICAgJ3JvdXRlOnBvc3RzLmluZGV4JyAgICAgICAvLz0+IEFwcC5Qb3N0c0luZGV4Um91dGUKICAgICdyb3V0ZTpibG9nL3Bvc3QnICAgICAgICAgLy89PiBCbG9nLlBvc3RSb3V0ZQogICAgJ3JvdXRlOmJhc2ljJyAgICAgICAgICAgICAvLz0+IFJvdXRlCiAgICAnZm9vOnBvc3QnICAgICAgICAgICAgICAgIC8vPT4gQXBwLlBvc3RGb28KICAgICdtb2RlbDpwb3N0JyAgICAgICAgICAgICAgLy89PiBBcHAuUG9zdAogICAgYGBgCiAgCiAgICBAY2xhc3MgR2xvYmFsc1Jlc29sdmVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHB1YmxpYwogICovCiAgdmFyIERlZmF1bHRSZXNvbHZlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW1iZXJPYmplY3QpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShEZWZhdWx0UmVzb2x2ZXIsIF9FbWJlck9iamVjdCk7CgogICAgZnVuY3Rpb24gRGVmYXVsdFJlc29sdmVyKCkgewogICAgICByZXR1cm4gX0VtYmVyT2JqZWN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICBEZWZhdWx0UmVzb2x2ZXIuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BzKSB7CiAgICAgIC8vIERPIE5PVCBSRU1PVkUgZXZlbiB0aG91Z2ggdGhpcyBkb2Vzbid0IGRvIGFueXRoaW5nCiAgICAgIC8vIFRoaXMgaXMgcmVxdWlyZWQgZm9yIGEgRmlyZUZveCA2MCsgSklUIGJ1ZyB3aXRoIG91ciB0ZXN0cy4KICAgICAgLy8gd2l0aG91dCBpdCwgY3JlYXRlKHByb3BzKSBpbiBvdXIgdGVzdHMgd291bGQgbG9zZSBwcm9wcyBvbiBhIGRlb3B0LgogICAgICByZXR1cm4gX0VtYmVyT2JqZWN0LmNyZWF0ZS5jYWxsKHRoaXMsIHByb3BzKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIHdpbGwgYmUgc2V0IHRvIHRoZSBBcHBsaWNhdGlvbiBpbnN0YW5jZSB3aGVuIGl0IGlzCiAgICAgIGNyZWF0ZWQuCiAgICAgICBAcHJvcGVydHkgbmFtZXNwYWNlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgdmFyIF9wcm90byA9IERlZmF1bHRSZXNvbHZlci5wcm90b3R5cGU7CgogICAgX3Byb3RvLmluaXQgPSBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9wYXJzZU5hbWVDYWNoZSA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CiAgICB9OwoKICAgIF9wcm90by5ub3JtYWxpemUgPSBmdW5jdGlvbiBub3JtYWxpemUoZnVsbE5hbWUpIHsKICAgICAgdmFyIF9mdWxsTmFtZSRzcGxpdCA9IGZ1bGxOYW1lLnNwbGl0KCc6JyksCiAgICAgICAgICB0eXBlID0gX2Z1bGxOYW1lJHNwbGl0WzBdLAogICAgICAgICAgbmFtZSA9IF9mdWxsTmFtZSRzcGxpdFsxXTsKCiAgICAgIChmYWxzZSAmJiAhKGZ1bGxOYW1lLnNwbGl0KCc6JykubGVuZ3RoID09PSAyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RyaWVkIHRvIG5vcm1hbGl6ZSBhIGNvbnRhaW5lciBuYW1lIHdpdGhvdXQgYSBjb2xvbiAoOikgaW4gaXQuICcgKyAnWW91IHByb2JhYmx5IHRyaWVkIHRvIGxvb2t1cCBhIG5hbWUgdGhhdCBkaWQgbm90IGNvbnRhaW4gYSB0eXBlLCAnICsgJ2EgY29sb24sIGFuZCBhIG5hbWUuIEEgcHJvcGVyIGxvb2t1cCBuYW1lIHdvdWxkIGJlIGB2aWV3OnBvc3RgLicsIGZ1bGxOYW1lLnNwbGl0KCc6JykubGVuZ3RoID09PSAyKSk7CgogICAgICBpZiAodHlwZSAhPT0gJ3RlbXBsYXRlJykgewogICAgICAgIHZhciByZXN1bHQgPSBuYW1lLnJlcGxhY2UoLyhcLnxffC0pLi9nLCBmdW5jdGlvbiAobSkgewogICAgICAgICAgcmV0dXJuIG0uY2hhckF0KDEpLnRvVXBwZXJDYXNlKCk7CiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIHR5cGUgKyAiOiIgKyByZXN1bHQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGZ1bGxOYW1lOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIHZpYSB0aGUgY29udGFpbmVyJ3MgcmVzb2x2ZXIgbWV0aG9kLgogICAgICBJdCBwYXJzZXMgdGhlIHByb3ZpZGVkIGBmdWxsTmFtZWAgYW5kIHRoZW4gbG9va3MgdXAgYW5kCiAgICAgIHJldHVybnMgdGhlIGFwcHJvcHJpYXRlIHRlbXBsYXRlIG9yIGNsYXNzLgogICAgICAgQG1ldGhvZCByZXNvbHZlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZSB0aGUgbG9va3VwIHN0cmluZwogICAgICBAcmV0dXJuIHtPYmplY3R9IHRoZSByZXNvbHZlZCBmYWN0b3J5CiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc29sdmUgPSBmdW5jdGlvbiByZXNvbHZlKGZ1bGxOYW1lKSB7CiAgICAgIHZhciBwYXJzZWROYW1lID0gdGhpcy5wYXJzZU5hbWUoZnVsbE5hbWUpOwogICAgICB2YXIgcmVzb2x2ZU1ldGhvZE5hbWUgPSBwYXJzZWROYW1lLnJlc29sdmVNZXRob2ROYW1lOwogICAgICB2YXIgcmVzb2x2ZWQ7CgogICAgICBpZiAodGhpc1tyZXNvbHZlTWV0aG9kTmFtZV0pIHsKICAgICAgICByZXNvbHZlZCA9IHRoaXNbcmVzb2x2ZU1ldGhvZE5hbWVdKHBhcnNlZE5hbWUpOwogICAgICB9CgogICAgICByZXNvbHZlZCA9IHJlc29sdmVkIHx8IHRoaXMucmVzb2x2ZU90aGVyKHBhcnNlZE5hbWUpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGlmIChwYXJzZWROYW1lLnJvb3QgJiYgcGFyc2VkTmFtZS5yb290LkxPR19SRVNPTFZFUikgewogICAgICAgICAgdGhpcy5fbG9nTG9va3VwKHJlc29sdmVkLCBwYXJzZWROYW1lKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChyZXNvbHZlZCkgewogICAgICAgICgwLCBfdmFsaWRhdGVUeXBlLmRlZmF1bHQpKHJlc29sdmVkLCBwYXJzZWROYW1lKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlc29sdmVkOwogICAgfQogICAgLyoqCiAgICAgIENvbnZlcnQgdGhlIHN0cmluZyBuYW1lIG9mIHRoZSBmb3JtICd0eXBlOm5hbWUnIHRvCiAgICAgIGEgSmF2YXNjcmlwdCBvYmplY3Qgd2l0aCB0aGUgcGFyc2VkIGFzcGVjdHMgb2YgdGhlIG5hbWUKICAgICAgYnJva2VuIG91dC4KICAgICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZSB0aGUgbG9va3VwIHN0cmluZwogICAgICBAbWV0aG9kIHBhcnNlTmFtZQogICAgICBAcHJvdGVjdGVkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5wYXJzZU5hbWUgPSBmdW5jdGlvbiBwYXJzZU5hbWUoZnVsbE5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXMuX3BhcnNlTmFtZUNhY2hlW2Z1bGxOYW1lXSB8fCAodGhpcy5fcGFyc2VOYW1lQ2FjaGVbZnVsbE5hbWVdID0gdGhpcy5fcGFyc2VOYW1lKGZ1bGxOYW1lKSk7CiAgICB9OwoKICAgIF9wcm90by5fcGFyc2VOYW1lID0gZnVuY3Rpb24gX3BhcnNlTmFtZShmdWxsTmFtZSkgewogICAgICB2YXIgX2Z1bGxOYW1lJHNwbGl0MiA9IGZ1bGxOYW1lLnNwbGl0KCc6JyksCiAgICAgICAgICB0eXBlID0gX2Z1bGxOYW1lJHNwbGl0MlswXSwKICAgICAgICAgIGZ1bGxOYW1lV2l0aG91dFR5cGUgPSBfZnVsbE5hbWUkc3BsaXQyWzFdOwoKICAgICAgdmFyIG5hbWUgPSBmdWxsTmFtZVdpdGhvdXRUeXBlOwogICAgICB2YXIgbmFtZXNwYWNlID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICduYW1lc3BhY2UnKTsKICAgICAgdmFyIHJvb3QgPSBuYW1lc3BhY2U7CiAgICAgIHZhciBsYXN0U2xhc2hJbmRleCA9IG5hbWUubGFzdEluZGV4T2YoJy8nKTsKICAgICAgdmFyIGRpcm5hbWUgPSBsYXN0U2xhc2hJbmRleCAhPT0gLTEgPyBuYW1lLnNsaWNlKDAsIGxhc3RTbGFzaEluZGV4KSA6IG51bGw7CgogICAgICBpZiAodHlwZSAhPT0gJ3RlbXBsYXRlJyAmJiBsYXN0U2xhc2hJbmRleCAhPT0gLTEpIHsKICAgICAgICB2YXIgcGFydHMgPSBuYW1lLnNwbGl0KCcvJyk7CiAgICAgICAgbmFtZSA9IHBhcnRzW3BhcnRzLmxlbmd0aCAtIDFdOwogICAgICAgIHZhciBuYW1lc3BhY2VOYW1lID0gKDAsIF9zdHJpbmcuY2FwaXRhbGl6ZSkocGFydHMuc2xpY2UoMCwgLTEpLmpvaW4oJy4nKSk7CiAgICAgICAgcm9vdCA9ICgwLCBfbWV0YWwuZmluZE5hbWVzcGFjZSkobmFtZXNwYWNlTmFtZSk7CiAgICAgICAgKGZhbHNlICYmICEocm9vdCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgYXJlIGxvb2tpbmcgZm9yIGEgIiArIG5hbWUgKyAiICIgKyB0eXBlICsgIiBpbiB0aGUgIiArIG5hbWVzcGFjZU5hbWUgKyAiIG5hbWVzcGFjZSwgYnV0IHRoZSBuYW1lc3BhY2UgY291bGQgbm90IGJlIGZvdW5kIiwgcm9vdCkpOwogICAgICB9CgogICAgICB2YXIgcmVzb2x2ZU1ldGhvZE5hbWUgPSBmdWxsTmFtZVdpdGhvdXRUeXBlID09PSAnbWFpbicgPyAnTWFpbicgOiAoMCwgX3N0cmluZy5jbGFzc2lmeSkodHlwZSk7CgogICAgICBpZiAoIShuYW1lICYmIHR5cGUpKSB7CiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiSW52YWxpZCBmdWxsTmFtZTogYCIgKyBmdWxsTmFtZSArICJgLCBtdXN0IGJlIG9mIHRoZSBmb3JtIGB0eXBlOm5hbWVgICIpOwogICAgICB9CgogICAgICByZXR1cm4gewogICAgICAgIGZ1bGxOYW1lOiBmdWxsTmFtZSwKICAgICAgICB0eXBlOiB0eXBlLAogICAgICAgIGZ1bGxOYW1lV2l0aG91dFR5cGU6IGZ1bGxOYW1lV2l0aG91dFR5cGUsCiAgICAgICAgZGlybmFtZTogZGlybmFtZSwKICAgICAgICBuYW1lOiBuYW1lLAogICAgICAgIHJvb3Q6IHJvb3QsCiAgICAgICAgcmVzb2x2ZU1ldGhvZE5hbWU6ICJyZXNvbHZlIiArIHJlc29sdmVNZXRob2ROYW1lCiAgICAgIH07CiAgICB9CiAgICAvKioKICAgICAgUmV0dXJucyBhIGh1bWFuLXJlYWRhYmxlIGRlc2NyaXB0aW9uIGZvciBhIGZ1bGxOYW1lLiBVc2VkIGJ5IHRoZQogICAgICBBcHBsaWNhdGlvbiBuYW1lc3BhY2UgaW4gYXNzZXJ0aW9ucyB0byBkZXNjcmliZSB0aGUKICAgICAgcHJlY2lzZSBuYW1lIG9mIHRoZSBjbGFzcyB0aGF0IEVtYmVyIGlzIGxvb2tpbmcgZm9yLCByYXRoZXIgdGhhbgogICAgICBjb250YWluZXIga2V5cy4KICAgICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZSB0aGUgbG9va3VwIHN0cmluZwogICAgICBAbWV0aG9kIGxvb2t1cERlc2NyaXB0aW9uCiAgICAgIEBwcm90ZWN0ZWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLmxvb2t1cERlc2NyaXB0aW9uID0gZnVuY3Rpb24gbG9va3VwRGVzY3JpcHRpb24oZnVsbE5hbWUpIHsKICAgICAgdmFyIHBhcnNlZE5hbWUgPSB0aGlzLnBhcnNlTmFtZShmdWxsTmFtZSk7CiAgICAgIHZhciBkZXNjcmlwdGlvbjsKCiAgICAgIGlmIChwYXJzZWROYW1lLnR5cGUgPT09ICd0ZW1wbGF0ZScpIHsKICAgICAgICByZXR1cm4gInRlbXBsYXRlIGF0ICIgKyBwYXJzZWROYW1lLmZ1bGxOYW1lV2l0aG91dFR5cGUucmVwbGFjZSgvXC4vZywgJy8nKTsKICAgICAgfQoKICAgICAgZGVzY3JpcHRpb24gPSBwYXJzZWROYW1lLnJvb3QgKyAiLiIgKyAoMCwgX3N0cmluZy5jbGFzc2lmeSkocGFyc2VkTmFtZS5uYW1lKS5yZXBsYWNlKC9cLi9nLCAnJyk7CgogICAgICBpZiAocGFyc2VkTmFtZS50eXBlICE9PSAnbW9kZWwnKSB7CiAgICAgICAgZGVzY3JpcHRpb24gKz0gKDAsIF9zdHJpbmcuY2xhc3NpZnkpKHBhcnNlZE5hbWUudHlwZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBkZXNjcmlwdGlvbjsKICAgIH07CgogICAgX3Byb3RvLm1ha2VUb1N0cmluZyA9IGZ1bmN0aW9uIG1ha2VUb1N0cmluZyhmYWN0b3J5KSB7CiAgICAgIHJldHVybiBmYWN0b3J5LnRvU3RyaW5nKCk7CiAgICB9CiAgICAvKioKICAgICAgR2l2ZW4gYSBwYXJzZU5hbWUgb2JqZWN0IChvdXRwdXQgZnJvbSBgcGFyc2VOYW1lYCksIGFwcGx5CiAgICAgIHRoZSBjb252ZW50aW9ucyBleHBlY3RlZCBieSBgUm91dGVyYAogICAgICAgQHBhcmFtIHtPYmplY3R9IHBhcnNlZE5hbWUgYSBwYXJzZU5hbWUgb2JqZWN0IHdpdGggdGhlIHBhcnNlZAogICAgICAgIGZ1bGxOYW1lIGxvb2t1cCBzdHJpbmcKICAgICAgQG1ldGhvZCB1c2VSb3V0ZXJOYW1pbmcKICAgICAgQHByb3RlY3RlZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8udXNlUm91dGVyTmFtaW5nID0gZnVuY3Rpb24gdXNlUm91dGVyTmFtaW5nKHBhcnNlZE5hbWUpIHsKICAgICAgaWYgKHBhcnNlZE5hbWUubmFtZSA9PT0gJ2Jhc2ljJykgewogICAgICAgIHBhcnNlZE5hbWUubmFtZSA9ICcnOwogICAgICB9IGVsc2UgewogICAgICAgIHBhcnNlZE5hbWUubmFtZSA9IHBhcnNlZE5hbWUubmFtZS5yZXBsYWNlKC9cLi9nLCAnXycpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgTG9vayB1cCB0aGUgdGVtcGxhdGUgaW4gRW1iZXIuVEVNUExBVEVTCiAgICAgICBAcGFyYW0ge09iamVjdH0gcGFyc2VkTmFtZSBhIHBhcnNlTmFtZSBvYmplY3Qgd2l0aCB0aGUgcGFyc2VkCiAgICAgICAgZnVsbE5hbWUgbG9va3VwIHN0cmluZwogICAgICBAbWV0aG9kIHJlc29sdmVUZW1wbGF0ZQogICAgICBAcHJvdGVjdGVkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5yZXNvbHZlVGVtcGxhdGUgPSBmdW5jdGlvbiByZXNvbHZlVGVtcGxhdGUocGFyc2VkTmFtZSkgewogICAgICB2YXIgdGVtcGxhdGVOYW1lID0gcGFyc2VkTmFtZS5mdWxsTmFtZVdpdGhvdXRUeXBlLnJlcGxhY2UoL1wuL2csICcvJyk7CiAgICAgIHJldHVybiAoMCwgX2dsaW1tZXIuZ2V0VGVtcGxhdGUpKHRlbXBsYXRlTmFtZSkgfHwgKDAsIF9nbGltbWVyLmdldFRlbXBsYXRlKSgoMCwgX3N0cmluZy5kZWNhbWVsaXplKSh0ZW1wbGF0ZU5hbWUpKTsKICAgIH0KICAgIC8qKgogICAgICBMb29rdXAgdGhlIHZpZXcgdXNpbmcgYHJlc29sdmVPdGhlcmAKICAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXJzZWROYW1lIGEgcGFyc2VOYW1lIG9iamVjdCB3aXRoIHRoZSBwYXJzZWQKICAgICAgICBmdWxsTmFtZSBsb29rdXAgc3RyaW5nCiAgICAgIEBtZXRob2QgcmVzb2x2ZVZpZXcKICAgICAgQHByb3RlY3RlZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVzb2x2ZVZpZXcgPSBmdW5jdGlvbiByZXNvbHZlVmlldyhwYXJzZWROYW1lKSB7CiAgICAgIHRoaXMudXNlUm91dGVyTmFtaW5nKHBhcnNlZE5hbWUpOwogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlT3RoZXIocGFyc2VkTmFtZSk7CiAgICB9CiAgICAvKioKICAgICAgTG9va3VwIHRoZSBjb250cm9sbGVyIHVzaW5nIGByZXNvbHZlT3RoZXJgCiAgICAgICBAcGFyYW0ge09iamVjdH0gcGFyc2VkTmFtZSBhIHBhcnNlTmFtZSBvYmplY3Qgd2l0aCB0aGUgcGFyc2VkCiAgICAgICAgZnVsbE5hbWUgbG9va3VwIHN0cmluZwogICAgICBAbWV0aG9kIHJlc29sdmVDb250cm9sbGVyCiAgICAgIEBwcm90ZWN0ZWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc29sdmVDb250cm9sbGVyID0gZnVuY3Rpb24gcmVzb2x2ZUNvbnRyb2xsZXIocGFyc2VkTmFtZSkgewogICAgICB0aGlzLnVzZVJvdXRlck5hbWluZyhwYXJzZWROYW1lKTsKICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZU90aGVyKHBhcnNlZE5hbWUpOwogICAgfQogICAgLyoqCiAgICAgIExvb2t1cCB0aGUgcm91dGUgdXNpbmcgYHJlc29sdmVPdGhlcmAKICAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXJzZWROYW1lIGEgcGFyc2VOYW1lIG9iamVjdCB3aXRoIHRoZSBwYXJzZWQKICAgICAgICBmdWxsTmFtZSBsb29rdXAgc3RyaW5nCiAgICAgIEBtZXRob2QgcmVzb2x2ZVJvdXRlCiAgICAgIEBwcm90ZWN0ZWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc29sdmVSb3V0ZSA9IGZ1bmN0aW9uIHJlc29sdmVSb3V0ZShwYXJzZWROYW1lKSB7CiAgICAgIHRoaXMudXNlUm91dGVyTmFtaW5nKHBhcnNlZE5hbWUpOwogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlT3RoZXIocGFyc2VkTmFtZSk7CiAgICB9CiAgICAvKioKICAgICAgTG9va3VwIHRoZSBtb2RlbCBvbiB0aGUgQXBwbGljYXRpb24gbmFtZXNwYWNlCiAgICAgICBAcGFyYW0ge09iamVjdH0gcGFyc2VkTmFtZSBhIHBhcnNlTmFtZSBvYmplY3Qgd2l0aCB0aGUgcGFyc2VkCiAgICAgICAgZnVsbE5hbWUgbG9va3VwIHN0cmluZwogICAgICBAbWV0aG9kIHJlc29sdmVNb2RlbAogICAgICBAcHJvdGVjdGVkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5yZXNvbHZlTW9kZWwgPSBmdW5jdGlvbiByZXNvbHZlTW9kZWwocGFyc2VkTmFtZSkgewogICAgICB2YXIgY2xhc3NOYW1lID0gKDAsIF9zdHJpbmcuY2xhc3NpZnkpKHBhcnNlZE5hbWUubmFtZSk7CiAgICAgIHZhciBmYWN0b3J5ID0gKDAsIF9tZXRhbC5nZXQpKHBhcnNlZE5hbWUucm9vdCwgY2xhc3NOYW1lKTsKICAgICAgcmV0dXJuIGZhY3Rvcnk7CiAgICB9CiAgICAvKioKICAgICAgTG9vayB1cCB0aGUgc3BlY2lmaWVkIG9iamVjdCAoZnJvbSBwYXJzZWROYW1lKSBvbiB0aGUgYXBwcm9wcmlhdGUKICAgICAgbmFtZXNwYWNlICh1c3VhbGx5IG9uIHRoZSBBcHBsaWNhdGlvbikKICAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXJzZWROYW1lIGEgcGFyc2VOYW1lIG9iamVjdCB3aXRoIHRoZSBwYXJzZWQKICAgICAgICBmdWxsTmFtZSBsb29rdXAgc3RyaW5nCiAgICAgIEBtZXRob2QgcmVzb2x2ZUhlbHBlcgogICAgICBAcHJvdGVjdGVkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5yZXNvbHZlSGVscGVyID0gZnVuY3Rpb24gcmVzb2x2ZUhlbHBlcihwYXJzZWROYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLnJlc29sdmVPdGhlcihwYXJzZWROYW1lKTsKICAgIH0KICAgIC8qKgogICAgICBMb29rIHVwIHRoZSBzcGVjaWZpZWQgb2JqZWN0IChmcm9tIHBhcnNlZE5hbWUpIG9uIHRoZSBhcHByb3ByaWF0ZQogICAgICBuYW1lc3BhY2UgKHVzdWFsbHkgb24gdGhlIEFwcGxpY2F0aW9uKQogICAgICAgQHBhcmFtIHtPYmplY3R9IHBhcnNlZE5hbWUgYSBwYXJzZU5hbWUgb2JqZWN0IHdpdGggdGhlIHBhcnNlZAogICAgICAgIGZ1bGxOYW1lIGxvb2t1cCBzdHJpbmcKICAgICAgQG1ldGhvZCByZXNvbHZlT3RoZXIKICAgICAgQHByb3RlY3RlZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVzb2x2ZU90aGVyID0gZnVuY3Rpb24gcmVzb2x2ZU90aGVyKHBhcnNlZE5hbWUpIHsKICAgICAgdmFyIGNsYXNzTmFtZSA9ICgwLCBfc3RyaW5nLmNsYXNzaWZ5KShwYXJzZWROYW1lLm5hbWUpICsgKDAsIF9zdHJpbmcuY2xhc3NpZnkpKHBhcnNlZE5hbWUudHlwZSk7CiAgICAgIHZhciBmYWN0b3J5ID0gKDAsIF9tZXRhbC5nZXQpKHBhcnNlZE5hbWUucm9vdCwgY2xhc3NOYW1lKTsKICAgICAgcmV0dXJuIGZhY3Rvcnk7CiAgICB9OwoKICAgIF9wcm90by5yZXNvbHZlTWFpbiA9IGZ1bmN0aW9uIHJlc29sdmVNYWluKHBhcnNlZE5hbWUpIHsKICAgICAgdmFyIGNsYXNzTmFtZSA9ICgwLCBfc3RyaW5nLmNsYXNzaWZ5KShwYXJzZWROYW1lLnR5cGUpOwogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHBhcnNlZE5hbWUucm9vdCwgY2xhc3NOYW1lKTsKICAgIH0KICAgIC8qKgogICAgICBVc2VkIHRvIGl0ZXJhdGUgYWxsIGl0ZW1zIG9mIGEgZ2l2ZW4gdHlwZS4KICAgICAgIEBtZXRob2Qga25vd25Gb3JUeXBlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlIHRoZSB0eXBlIHRvIHNlYXJjaCBmb3IKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmtub3duRm9yVHlwZSA9IGZ1bmN0aW9uIGtub3duRm9yVHlwZSh0eXBlKSB7CiAgICAgIHZhciBuYW1lc3BhY2UgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ25hbWVzcGFjZScpOwogICAgICB2YXIgc3VmZml4ID0gKDAsIF9zdHJpbmcuY2xhc3NpZnkpKHR5cGUpOwogICAgICB2YXIgdHlwZVJlZ2V4cCA9IG5ldyBSZWdFeHAoc3VmZml4ICsgIiQiKTsKICAgICAgdmFyIGtub3duID0gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgICAgdmFyIGtub3duS2V5cyA9IE9iamVjdC5rZXlzKG5hbWVzcGFjZSk7CgogICAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwga25vd25LZXlzLmxlbmd0aDsgaW5kZXgrKykgewogICAgICAgIHZhciBuYW1lID0ga25vd25LZXlzW2luZGV4XTsKCiAgICAgICAgaWYgKHR5cGVSZWdleHAudGVzdChuYW1lKSkgewogICAgICAgICAgdmFyIGNvbnRhaW5lck5hbWUgPSB0aGlzLnRyYW5zbGF0ZVRvQ29udGFpbmVyRnVsbG5hbWUodHlwZSwgbmFtZSk7CiAgICAgICAgICBrbm93bltjb250YWluZXJOYW1lXSA9IHRydWU7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4ga25vd247CiAgICB9CiAgICAvKioKICAgICAgQ29udmVydHMgcHJvdmlkZWQgbmFtZSBmcm9tIHRoZSBiYWNraW5nIG5hbWVzcGFjZSBpbnRvIGEgY29udGFpbmVyIGxvb2t1cCBuYW1lLgogICAgICAgRXhhbXBsZXM6CiAgICAgICAqIEFwcC5Gb29CYXJIZWxwZXIgLT4gaGVscGVyOmZvby1iYXIKICAgICAgKiBBcHAuVEhlbHBlciAtPiBoZWxwZXI6dAogICAgICAgQG1ldGhvZCB0cmFuc2xhdGVUb0NvbnRhaW5lckZ1bGxuYW1lCiAgICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by50cmFuc2xhdGVUb0NvbnRhaW5lckZ1bGxuYW1lID0gZnVuY3Rpb24gdHJhbnNsYXRlVG9Db250YWluZXJGdWxsbmFtZSh0eXBlLCBuYW1lKSB7CiAgICAgIHZhciBzdWZmaXggPSAoMCwgX3N0cmluZy5jbGFzc2lmeSkodHlwZSk7CiAgICAgIHZhciBuYW1lUHJlZml4ID0gbmFtZS5zbGljZSgwLCBzdWZmaXgubGVuZ3RoICogLTEpOwogICAgICB2YXIgZGFzaGVyaXplZE5hbWUgPSAoMCwgX3N0cmluZy5kYXNoZXJpemUpKG5hbWVQcmVmaXgpOwogICAgICByZXR1cm4gdHlwZSArICI6IiArIGRhc2hlcml6ZWROYW1lOwogICAgfTsKCiAgICByZXR1cm4gRGVmYXVsdFJlc29sdmVyOwogIH0oX3J1bnRpbWUuT2JqZWN0KTsKCiAgdmFyIF9kZWZhdWx0ID0gRGVmYXVsdFJlc29sdmVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIC8qKgogICAgICAgIEBtZXRob2QgX2xvZ0xvb2t1cAogICAgICAgIEBwYXJhbSB7Qm9vbGVhbn0gZm91bmQKICAgICAgICBAcGFyYW0ge09iamVjdH0gcGFyc2VkTmFtZQogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICBEZWZhdWx0UmVzb2x2ZXIucHJvdG90eXBlLl9sb2dMb29rdXAgPSBmdW5jdGlvbiAoZm91bmQsIHBhcnNlZE5hbWUpIHsKICAgICAgdmFyIHN5bWJvbCA9IGZvdW5kID8gJ1vinJNdJyA6ICdbIF0nOwogICAgICB2YXIgcGFkZGluZzsKCiAgICAgIGlmIChwYXJzZWROYW1lLmZ1bGxOYW1lLmxlbmd0aCA+IDYwKSB7CiAgICAgICAgcGFkZGluZyA9ICcuJzsKICAgICAgfSBlbHNlIHsKICAgICAgICBwYWRkaW5nID0gbmV3IEFycmF5KDYwIC0gcGFyc2VkTmFtZS5mdWxsTmFtZS5sZW5ndGgpLmpvaW4oJy4nKTsKICAgICAgfQoKICAgICAgKDAsIF9kZWJ1Zy5pbmZvKShzeW1ib2wsIHBhcnNlZE5hbWUuZnVsbE5hbWUsIHBhZGRpbmcsIHRoaXMubG9va3VwRGVzY3JpcHRpb24ocGFyc2VkTmFtZS5mdWxsTmFtZSkpOwogICAgfTsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci9hcHBsaWNhdGlvbi9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9vd25lciIsICJAZW1iZXIvYXBwbGljYXRpb24vbGliL2xhenlfbG9hZCIsICJAZW1iZXIvYXBwbGljYXRpb24vbGliL2FwcGxpY2F0aW9uIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX293bmVyLCBfbGF6eV9sb2FkLCBfYXBwbGljYXRpb24pIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImdldE93bmVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX293bmVyLmdldE93bmVyOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInNldE93bmVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX293bmVyLnNldE93bmVyOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIm9uTG9hZCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9sYXp5X2xvYWQub25Mb2FkOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInJ1bkxvYWRIb29rcyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9sYXp5X2xvYWQucnVuTG9hZEhvb2tzOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9sb2FkZWQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbGF6eV9sb2FkLl9sb2FkZWQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZGVmYXVsdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9hcHBsaWNhdGlvbi5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvYXBwbGljYXRpb24vaW5zdGFuY2UiLCBbImV4cG9ydHMiLCAiQGVtYmVyL3BvbHlmaWxscyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvLWludGVybmFscy9icm93c2VyLWVudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzIiwgIkBlbWJlci9lbmdpbmUvaW5zdGFuY2UiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZ2xpbW1lciJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9wb2x5ZmlsbHMsIF9tZXRhbCwgZW52aXJvbm1lbnQsIF92aWV3cywgX2luc3RhbmNlLCBfZ2xpbW1lcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvYXBwbGljYXRpb24KICAqLwoKICAvKioKICAgIFRoZSBgQXBwbGljYXRpb25JbnN0YW5jZWAgZW5jYXBzdWxhdGVzIGFsbCBvZiB0aGUgc3RhdGVmdWwgYXNwZWN0cyBvZiBhCiAgICBydW5uaW5nIGBBcHBsaWNhdGlvbmAuCiAgCiAgICBBdCBhIGhpZ2gtbGV2ZWwsIHdlIGJyZWFrIGFwcGxpY2F0aW9uIGJvb3QgaW50byB0d28gZGlzdGluY3QgcGhhc2VzOgogIAogICAgKiBEZWZpbml0aW9uIHRpbWUsIHdoZXJlIGFsbCBvZiB0aGUgY2xhc3NlcywgdGVtcGxhdGVzLCBhbmQgb3RoZXIKICAgICAgZGVwZW5kZW5jaWVzIGFyZSBsb2FkZWQgKHR5cGljYWxseSBpbiB0aGUgYnJvd3NlcikuCiAgICAqIFJ1biB0aW1lLCB3aGVyZSB3ZSBiZWdpbiBleGVjdXRpbmcgdGhlIGFwcGxpY2F0aW9uIG9uY2UgZXZlcnl0aGluZwogICAgICBoYXMgbG9hZGVkLgogIAogICAgRGVmaW5pdGlvbiB0aW1lIGNhbiBiZSBleHBlbnNpdmUgYW5kIG9ubHkgbmVlZHMgdG8gaGFwcGVuIG9uY2Ugc2luY2UgaXQgaXMKICAgIGFuIGlkZW1wb3RlbnQgb3BlcmF0aW9uLiBGb3IgZXhhbXBsZSwgYmV0d2VlbiB0ZXN0IHJ1bnMgYW5kIEZhc3RCb290CiAgICByZXF1ZXN0cywgdGhlIGFwcGxpY2F0aW9uIHN0YXlzIHRoZSBzYW1lLiBJdCBpcyBvbmx5IHRoZSBzdGF0ZSB0aGF0IHdlIHdhbnQKICAgIHRvIHJlc2V0LgogIAogICAgVGhhdCBzdGF0ZSBpcyB3aGF0IHRoZSBgQXBwbGljYXRpb25JbnN0YW5jZWAgbWFuYWdlczogaXQgaXMgcmVzcG9uc2libGUgZm9yCiAgICBjcmVhdGluZyB0aGUgY29udGFpbmVyIHRoYXQgY29udGFpbnMgYWxsIGFwcGxpY2F0aW9uIHN0YXRlLCBhbmQgZGlzcG9zaW5nIG9mCiAgICBpdCBvbmNlIHRoZSBwYXJ0aWN1bGFyIHRlc3QgcnVuIG9yIEZhc3RCb290IHJlcXVlc3QgaGFzIGZpbmlzaGVkLgogIAogICAgQHB1YmxpYwogICAgQGNsYXNzIEFwcGxpY2F0aW9uSW5zdGFuY2UKICAgIEBleHRlbmRzIEVuZ2luZUluc3RhbmNlCiAgKi8KICB2YXIgQXBwbGljYXRpb25JbnN0YW5jZSA9IF9pbnN0YW5jZS5kZWZhdWx0LmV4dGVuZCh7CiAgICAvKioKICAgICAgVGhlIGBBcHBsaWNhdGlvbmAgZm9yIHdoaWNoIHRoaXMgaXMgYW4gaW5zdGFuY2UuCiAgICAgICBAcHJvcGVydHkge0FwcGxpY2F0aW9ufSBhcHBsaWNhdGlvbgogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGFwcGxpY2F0aW9uOiBudWxsLAoKICAgIC8qKgogICAgICBUaGUgRE9NIGV2ZW50cyBmb3Igd2hpY2ggdGhlIGV2ZW50IGRpc3BhdGNoZXIgc2hvdWxkIGxpc3Rlbi4KICAgICAgIEJ5IGRlZmF1bHQsIHRoZSBhcHBsaWNhdGlvbidzIGBFbWJlci5FdmVudERpc3BhdGNoZXJgIGxpc3RlbnMKICAgICAgZm9yIGEgc2V0IG9mIHN0YW5kYXJkIERPTSBldmVudHMsIHN1Y2ggYXMgYG1vdXNlZG93bmAgYW5kCiAgICAgIGBrZXl1cGAsIGFuZCBkZWxlZ2F0ZXMgdGhlbSB0byB5b3VyIGFwcGxpY2F0aW9uJ3MgYEVtYmVyLlZpZXdgCiAgICAgIGluc3RhbmNlcy4KICAgICAgIEBwcml2YXRlCiAgICAgIEBwcm9wZXJ0eSB7T2JqZWN0fSBjdXN0b21FdmVudHMKICAgICovCiAgICBjdXN0b21FdmVudHM6IG51bGwsCgogICAgLyoqCiAgICAgIFRoZSByb290IERPTSBlbGVtZW50IG9mIHRoZSBBcHBsaWNhdGlvbiBhcyBhbiBlbGVtZW50IG9yIGEKICAgICAgW2pRdWVyeS1jb21wYXRpYmxlIHNlbGVjdG9yCiAgICAgIHN0cmluZ10oaHR0cDovL2FwaS5qcXVlcnkuY29tL2NhdGVnb3J5L3NlbGVjdG9ycy8pLgogICAgICAgQHByaXZhdGUKICAgICAgQHByb3BlcnR5IHtTdHJpbmd8RE9NRWxlbWVudH0gcm9vdEVsZW1lbnQKICAgICovCiAgICByb290RWxlbWVudDogbnVsbCwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzLmFwcGxpY2F0aW9uLl93YXRjaEluc3RhbmNlKHRoaXMpOyAvLyBSZWdpc3RlciB0aGlzIGluc3RhbmNlIGluIHRoZSBwZXItaW5zdGFuY2UgcmVnaXN0cnkuCiAgICAgIC8vCiAgICAgIC8vIFdoeSBkbyB3ZSBuZWVkIHRvIHJlZ2lzdGVyIHRoZSBpbnN0YW5jZSBpbiB0aGUgZmlyc3QgcGxhY2U/CiAgICAgIC8vIEJlY2F1c2Ugd2UgbmVlZCBhIGdvb2Qgd2F5IGZvciB0aGUgcm9vdCByb3V0ZSAoYS5rLmEgQXBwbGljYXRpb25Sb3V0ZSkKICAgICAgLy8gdG8gbm90aWZ5IHVzIHdoZW4gaXQgaGFzIGNyZWF0ZWQgdGhlIHJvb3QtbW9zdCB2aWV3LiBUaGF0IHZpZXcgaXMgdGhlbgogICAgICAvLyBhcHBlbmRlZCB0byB0aGUgcm9vdEVsZW1lbnQsIGluIHRoZSBjYXNlIG9mIGFwcHMsIHRvIHRoZSBmaXh0dXJlIGhhcm5lc3MKICAgICAgLy8gaW4gdGVzdHMsIG9yIHJlbmRlcmVkIHRvIGEgc3RyaW5nIGluIHRoZSBjYXNlIG9mIEZhc3RCb290LgoKCiAgICAgIHRoaXMucmVnaXN0ZXIoJy1hcHBsaWNhdGlvbi1pbnN0YW5jZTptYWluJywgdGhpcywgewogICAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIE92ZXJyaWRlcyB0aGUgYmFzZSBgRW5naW5lSW5zdGFuY2UuX2Jvb3RTeW5jYCBtZXRob2Qgd2l0aCBjb25jZXJucyByZWxldmFudAogICAgICB0byBib290aW5nIGFwcGxpY2F0aW9uIChpbnN0ZWFkIG9mIGVuZ2luZSkgaW5zdGFuY2VzLgogICAgICAgVGhpcyBtZXRob2Qgc2hvdWxkIG9ubHkgY29udGFpbiBzeW5jaHJvbm91cyBib290IGNvbmNlcm5zLiBBc3luY2hyb25vdXMKICAgICAgYm9vdCBjb25jZXJucyBzaG91bGQgZXZlbnR1YWxseSBiZSBtb3ZlZCB0byB0aGUgYGJvb3RgIG1ldGhvZCwgd2hpY2gKICAgICAgcmV0dXJucyBhIHByb21pc2UuCiAgICAgICBVbnRpbCBhbGwgYm9vdCBjb2RlIGhhcyBiZWVuIG1hZGUgYXN5bmNocm9ub3VzLCB3ZSBuZWVkIHRvIGNvbnRpbnVlIHRvCiAgICAgIGV4cG9zZSB0aGlzIG1ldGhvZCBmb3IgdXNlICppbnRlcm5hbGx5KiBpbiBwbGFjZXMgd2hlcmUgd2UgbmVlZCB0byBib290IGFuCiAgICAgIGluc3RhbmNlIHN5bmNocm9ub3VzbHkuCiAgICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ib290U3luYzogZnVuY3Rpb24gX2Jvb3RTeW5jKG9wdGlvbnMpIHsKICAgICAgaWYgKHRoaXMuX2Jvb3RlZCkgewogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBvcHRpb25zID0gbmV3IEJvb3RPcHRpb25zKG9wdGlvbnMpOwogICAgICB0aGlzLnNldHVwUmVnaXN0cnkob3B0aW9ucyk7CgogICAgICBpZiAob3B0aW9ucy5yb290RWxlbWVudCkgewogICAgICAgIHRoaXMucm9vdEVsZW1lbnQgPSBvcHRpb25zLnJvb3RFbGVtZW50OwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMucm9vdEVsZW1lbnQgPSB0aGlzLmFwcGxpY2F0aW9uLnJvb3RFbGVtZW50OwogICAgICB9CgogICAgICBpZiAob3B0aW9ucy5sb2NhdGlvbikgewogICAgICAgICgwLCBfbWV0YWwuc2V0KSh0aGlzLnJvdXRlciwgJ2xvY2F0aW9uJywgb3B0aW9ucy5sb2NhdGlvbik7CiAgICAgIH0KCiAgICAgIHRoaXMuYXBwbGljYXRpb24ucnVuSW5zdGFuY2VJbml0aWFsaXplcnModGhpcyk7CgogICAgICBpZiAob3B0aW9ucy5pc0ludGVyYWN0aXZlKSB7CiAgICAgICAgdGhpcy5zZXR1cEV2ZW50RGlzcGF0Y2hlcigpOwogICAgICB9CgogICAgICB0aGlzLl9ib290ZWQgPSB0cnVlOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCiAgICBzZXR1cFJlZ2lzdHJ5OiBmdW5jdGlvbiBzZXR1cFJlZ2lzdHJ5KG9wdGlvbnMpIHsKICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5zZXR1cFJlZ2lzdHJ5KHRoaXMuX19yZWdpc3RyeV9fLCBvcHRpb25zKTsKICAgIH0sCiAgICByb3V0ZXI6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIHRoaXMubG9va3VwKCdyb3V0ZXI6bWFpbicpOwogICAgfSkucmVhZE9ubHkoKSwKCiAgICAvKioKICAgICAgVGhpcyBob29rIGlzIGNhbGxlZCBieSB0aGUgcm9vdC1tb3N0IFJvdXRlIChhLmsuYS4gdGhlIEFwcGxpY2F0aW9uUm91dGUpCiAgICAgIHdoZW4gaXQgaGFzIGZpbmlzaGVkIGNyZWF0aW5nIHRoZSByb290IFZpZXcuIEJ5IGRlZmF1bHQsIHdlIHNpbXBseSB0YWtlIHRoZQogICAgICB2aWV3IGFuZCBhcHBlbmQgaXQgdG8gdGhlIGByb290RWxlbWVudGAgc3BlY2lmaWVkIG9uIHRoZSBBcHBsaWNhdGlvbi4KICAgICAgIEluIGNhc2VzIGxpa2UgRmFzdEJvb3QgYW5kIHRlc3RpbmcsIHdlIGNhbiBvdmVycmlkZSB0aGlzIGhvb2sgYW5kIGltcGxlbWVudAogICAgICBjdXN0b20gYmVoYXZpb3IsIHN1Y2ggYXMgc2VyaWFsaXppbmcgdG8gYSBzdHJpbmcgYW5kIHNlbmRpbmcgb3ZlciBhbiBIVFRQCiAgICAgIHNvY2tldCByYXRoZXIgdGhhbiBhcHBlbmRpbmcgdG8gRE9NLgogICAgICAgQHBhcmFtIHZpZXcge0VtYmVyLlZpZXd9IHRoZSByb290LW1vc3QgdmlldwogICAgICBAZGVwcmVjYXRlZAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGRpZENyZWF0ZVJvb3RWaWV3OiBmdW5jdGlvbiBkaWRDcmVhdGVSb290Vmlldyh2aWV3KSB7CiAgICAgIHZpZXcuYXBwZW5kVG8odGhpcy5yb290RWxlbWVudCk7CiAgICB9LAoKICAgIC8qKgogICAgICBUZWxscyB0aGUgcm91dGVyIHRvIHN0YXJ0IHJvdXRpbmcuIFRoZSByb3V0ZXIgd2lsbCBhc2sgdGhlIGxvY2F0aW9uIGZvciB0aGUKICAgICAgY3VycmVudCBVUkwgb2YgdGhlIHBhZ2UgdG8gZGV0ZXJtaW5lIHRoZSBpbml0aWFsIFVSTCB0byBzdGFydCByb3V0aW5nIHRvLgogICAgICBUbyBzdGFydCB0aGUgYXBwIGF0IGEgc3BlY2lmaWMgVVJMLCBjYWxsIGBoYW5kbGVVUkxgIGluc3RlYWQuCiAgICAgICBAcHJpdmF0ZQogICAgKi8KICAgIHN0YXJ0Um91dGluZzogZnVuY3Rpb24gc3RhcnRSb3V0aW5nKCkgewogICAgICB0aGlzLnJvdXRlci5zdGFydFJvdXRpbmcoKTsKICAgICAgdGhpcy5fZGlkU2V0dXBSb3V0ZXIgPSB0cnVlOwogICAgfSwKCiAgICAvKioKICAgICAgU2V0cyB1cCB0aGUgcm91dGVyLCBpbml0aWFsaXppbmcgdGhlIGNoaWxkIHJvdXRlciBhbmQgY29uZmlndXJpbmcgdGhlCiAgICAgIGxvY2F0aW9uIGJlZm9yZSByb3V0aW5nIGJlZ2lucy4KICAgICAgIEJlY2F1c2Ugc2V0dXAgc2hvdWxkIG9ubHkgb2NjdXIgb25jZSwgbXVsdGlwbGUgY2FsbHMgdG8gYHNldHVwUm91dGVyYAogICAgICBiZXlvbmQgdGhlIGZpcnN0IGNhbGwgaGF2ZSBubyBlZmZlY3QuCiAgICAgIAogICAgICBUaGlzIGlzIGNvbW1vbmx5IHVzZWQgaW4gb3JkZXIgdG8gY29uZmlybSB0aGluZ3MgdGhhdCByZWx5IG9uIHRoZSByb3V0ZXIKICAgICAgYXJlIGZ1bmN0aW9uaW5nIHByb3Blcmx5IGZyb20gdGVzdHMgdGhhdCBhcmUgcHJpbWFyaWx5IHJlbmRlcmluZyByZWxhdGVkLgogICAgICAKICAgICAgRm9yIGV4YW1wbGUsIGZyb20gd2l0aGluIFtlbWJlci1xdW5pdF0oaHR0cHM6Ly9naXRodWIuY29tL2VtYmVyanMvZW1iZXItcXVuaXQpJ3MKICAgICAgYHNldHVwUmVuZGVyaW5nVGVzdGAgY2FsbGluZyBgdGhpcy5vd25lci5zZXR1cFJvdXRlcigpYCB3b3VsZCBhbGxvdyB0aGF0CiAgICAgIHJlbmRlcmluZyB0ZXN0IHRvIGNvbmZpcm0gdGhhdCBhbnkgYDxMaW5rVG8+PC9MaW5rVG8+YCdzIHRoYXQgYXJlIHJlbmRlcmVkCiAgICAgIGhhdmUgdGhlIGNvcnJlY3QgVVJMLgogICAgICAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHNldHVwUm91dGVyOiBmdW5jdGlvbiBzZXR1cFJvdXRlcigpIHsKICAgICAgaWYgKHRoaXMuX2RpZFNldHVwUm91dGVyKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9kaWRTZXR1cFJvdXRlciA9IHRydWU7CiAgICAgIHRoaXMucm91dGVyLnNldHVwUm91dGVyKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBEaXJlY3RzIHRoZSByb3V0ZXIgdG8gcm91dGUgdG8gYSBwYXJ0aWN1bGFyIFVSTC4gVGhpcyBpcyB1c2VmdWwgaW4gdGVzdHMsCiAgICAgIGZvciBleGFtcGxlLCB0byB0ZWxsIHRoZSBhcHAgdG8gc3RhcnQgYXQgYSBwYXJ0aWN1bGFyIFVSTC4KICAgICAgIEBwYXJhbSB1cmwge1N0cmluZ30gdGhlIFVSTCB0aGUgcm91dGVyIHNob3VsZCByb3V0ZSB0bwogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGhhbmRsZVVSTDogZnVuY3Rpb24gaGFuZGxlVVJMKHVybCkgewogICAgICB0aGlzLnNldHVwUm91dGVyKCk7CiAgICAgIHJldHVybiB0aGlzLnJvdXRlci5oYW5kbGVVUkwodXJsKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgc2V0dXBFdmVudERpc3BhdGNoZXI6IGZ1bmN0aW9uIHNldHVwRXZlbnREaXNwYXRjaGVyKCkgewogICAgICB2YXIgZGlzcGF0Y2hlciA9IHRoaXMubG9va3VwKCdldmVudF9kaXNwYXRjaGVyOm1haW4nKTsKICAgICAgdmFyIGFwcGxpY2F0aW9uQ3VzdG9tRXZlbnRzID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMuYXBwbGljYXRpb24sICdjdXN0b21FdmVudHMnKTsKICAgICAgdmFyIGluc3RhbmNlQ3VzdG9tRXZlbnRzID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdjdXN0b21FdmVudHMnKTsKICAgICAgdmFyIGN1c3RvbUV2ZW50cyA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIGFwcGxpY2F0aW9uQ3VzdG9tRXZlbnRzLCBpbnN0YW5jZUN1c3RvbUV2ZW50cyk7CiAgICAgIGRpc3BhdGNoZXIuc2V0dXAoY3VzdG9tRXZlbnRzLCB0aGlzLnJvb3RFbGVtZW50KTsKICAgICAgcmV0dXJuIGRpc3BhdGNoZXI7CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSBjdXJyZW50IFVSTCBvZiB0aGUgYXBwIGluc3RhbmNlLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdXIKICAgICAgYXBwIGRvZXMgbm90IHVwZGF0ZSB0aGUgYnJvd3NlcnMgVVJMIGJhciAoaS5lLiBpdCB1c2VzIHRoZSBgJ25vbmUnYAogICAgICBsb2NhdGlvbiBhZGFwdGVyKS4KICAgICAgIEBwdWJsaWMKICAgICAgQHJldHVybiB7U3RyaW5nfSB0aGUgY3VycmVudCBVUkwKICAgICovCiAgICBnZXRVUkw6IGZ1bmN0aW9uIGdldFVSTCgpIHsKICAgICAgcmV0dXJuIHRoaXMucm91dGVyLnVybDsKICAgIH0sCiAgICAvLyBgaW5zdGFuY2UudmlzaXQodXJsKWAgc2hvdWxkIGV2ZW50dWFsbHkgcmVwbGFjZSBgaW5zdGFuY2UuaGFuZGxlVVJMKClgOwogICAgLy8gdGhlIHRlc3QgaGVscGVycyBjYW4gcHJvYmFibHkgYmUgc3dpdGNoZWQgdG8gdXNlIHRoaXMgaW1wbGVtZW50YXRpb24gdG9vCgogICAgLyoqCiAgICAgIE5hdmlnYXRlIHRoZSBpbnN0YW5jZSB0byBhIHBhcnRpY3VsYXIgVVJMLiBUaGlzIGlzIHVzZWZ1bCBpbiB0ZXN0cywgZm9yCiAgICAgIGV4YW1wbGUsIG9yIHRvIHRlbGwgdGhlIGFwcCB0byBzdGFydCBhdCBhIHBhcnRpY3VsYXIgVVJMLiBUaGlzIG1ldGhvZAogICAgICByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGFwcCBpbnN0YW5jZSB3aGVuIHRoZSB0cmFuc2l0aW9uCiAgICAgIGlzIGNvbXBsZXRlLCBvciByZWplY3RzIGlmIHRoZSB0cmFuc2lvbiB3YXMgYWJvcnRlZCBkdWUgdG8gYW4gZXJyb3IuCiAgICAgICBAcHVibGljCiAgICAgIEBwYXJhbSB1cmwge1N0cmluZ30gdGhlIGRlc3RpbmF0aW9uIFVSTAogICAgICBAcmV0dXJuIHtQcm9taXNlPEFwcGxpY2F0aW9uSW5zdGFuY2U+fQogICAgKi8KICAgIHZpc2l0OiBmdW5jdGlvbiB2aXNpdCh1cmwpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHRoaXMuc2V0dXBSb3V0ZXIoKTsKCiAgICAgIHZhciBib290T3B0aW9ucyA9IHRoaXMuX19jb250YWluZXJfXy5sb29rdXAoJy1lbnZpcm9ubWVudDptYWluJyk7CgogICAgICB2YXIgcm91dGVyID0gdGhpcy5yb3V0ZXI7CgogICAgICB2YXIgaGFuZGxlVHJhbnNpdGlvblJlc29sdmUgPSBmdW5jdGlvbiBoYW5kbGVUcmFuc2l0aW9uUmVzb2x2ZSgpIHsKICAgICAgICBpZiAoIWJvb3RPcHRpb25zLm9wdGlvbnMuc2hvdWxkUmVuZGVyKSB7CiAgICAgICAgICAvLyBObyByZW5kZXJpbmcgaXMgbmVlZGVkLCBhbmQgcm91dGluZyBoYXMgY29tcGxldGVkLCBzaW1wbHkgcmV0dXJuLgogICAgICAgICAgcmV0dXJuIF90aGlzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBFbnN1cmUgdGhhdCB0aGUgdmlzaXQgcHJvbWlzZSByZXNvbHZlcyB3aGVuIGFsbCByZW5kZXJpbmcgaGFzIGNvbXBsZXRlZAogICAgICAgICAgcmV0dXJuICgwLCBfZ2xpbW1lci5yZW5kZXJTZXR0bGVkKSgpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgICByZXR1cm4gX3RoaXM7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH07CgogICAgICB2YXIgaGFuZGxlVHJhbnNpdGlvblJlamVjdCA9IGZ1bmN0aW9uIGhhbmRsZVRyYW5zaXRpb25SZWplY3QoZXJyb3IpIHsKICAgICAgICBpZiAoZXJyb3IuZXJyb3IpIHsKICAgICAgICAgIHRocm93IGVycm9yLmVycm9yOwogICAgICAgIH0gZWxzZSBpZiAoZXJyb3IubmFtZSA9PT0gJ1RyYW5zaXRpb25BYm9ydGVkJyAmJiByb3V0ZXIuX3JvdXRlck1pY3JvbGliLmFjdGl2ZVRyYW5zaXRpb24pIHsKICAgICAgICAgIHJldHVybiByb3V0ZXIuX3JvdXRlck1pY3JvbGliLmFjdGl2ZVRyYW5zaXRpb24udGhlbihoYW5kbGVUcmFuc2l0aW9uUmVzb2x2ZSwgaGFuZGxlVHJhbnNpdGlvblJlamVjdCk7CiAgICAgICAgfSBlbHNlIGlmIChlcnJvci5uYW1lID09PSAnVHJhbnNpdGlvbkFib3J0ZWQnKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IubWVzc2FnZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIHZhciBsb2NhdGlvbiA9ICgwLCBfbWV0YWwuZ2V0KShyb3V0ZXIsICdsb2NhdGlvbicpOyAvLyBLZWVwcyB0aGUgbG9jYXRpb24gYWRhcHRlcidzIGludGVybmFsIFVSTCBpbi1zeW5jCgogICAgICBsb2NhdGlvbi5zZXRVUkwodXJsKTsgLy8gZ2V0VVJMIHJldHVybnMgdGhlIHNldCB1cmwgd2l0aCB0aGUgcm9vdFVSTCBzdHJpcHBlZCBvZmYKCiAgICAgIHJldHVybiByb3V0ZXIuaGFuZGxlVVJMKGxvY2F0aW9uLmdldFVSTCgpKS50aGVuKGhhbmRsZVRyYW5zaXRpb25SZXNvbHZlLCBoYW5kbGVUcmFuc2l0aW9uUmVqZWN0KTsKICAgIH0sCiAgICB3aWxsRGVzdHJveTogZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzLmFwcGxpY2F0aW9uLl91bndhdGNoSW5zdGFuY2UodGhpcyk7CiAgICB9CiAgfSk7CgogIEFwcGxpY2F0aW9uSW5zdGFuY2UucmVvcGVuQ2xhc3MoewogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIHNldHVwUmVnaXN0cnkKICAgICBAcGFyYW0ge1JlZ2lzdHJ5fSByZWdpc3RyeQogICAgIEBwYXJhbSB7Qm9vdE9wdGlvbnN9IG9wdGlvbnMKICAgICovCiAgICBzZXR1cFJlZ2lzdHJ5OiBmdW5jdGlvbiBzZXR1cFJlZ2lzdHJ5KHJlZ2lzdHJ5LCBvcHRpb25zKSB7CiAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsKICAgICAgICBvcHRpb25zID0ge307CiAgICAgIH0KCiAgICAgIGlmICghb3B0aW9ucy50b0Vudmlyb25tZW50KSB7CiAgICAgICAgb3B0aW9ucyA9IG5ldyBCb290T3B0aW9ucyhvcHRpb25zKTsKICAgICAgfQoKICAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJy1lbnZpcm9ubWVudDptYWluJywgb3B0aW9ucy50b0Vudmlyb25tZW50KCksIHsKICAgICAgICBpbnN0YW50aWF0ZTogZmFsc2UKICAgICAgfSk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdzZXJ2aWNlOi1kb2N1bWVudCcsIG9wdGlvbnMuZG9jdW1lbnQsIHsKICAgICAgICBpbnN0YW50aWF0ZTogZmFsc2UKICAgICAgfSk7CgogICAgICB0aGlzLl9zdXBlcihyZWdpc3RyeSwgb3B0aW9ucyk7CiAgICB9CiAgfSk7CiAgLyoqCiAgICBBIGxpc3Qgb2YgYm9vdC10aW1lIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgY3VzdG9taXppbmcgdGhlIGJlaGF2aW9yIG9mCiAgICBhbiBgQXBwbGljYXRpb25JbnN0YW5jZWAuCiAgCiAgICBUaGlzIGlzIGFuIGludGVyZmFjZSBjbGFzcyB0aGF0IGV4aXN0cyBwdXJlbHkgdG8gZG9jdW1lbnQgdGhlIGF2YWlsYWJsZQogICAgb3B0aW9uczsgeW91IGRvIG5vdCBuZWVkIHRvIGNvbnN0cnVjdCBpdCBtYW51YWxseS4gU2ltcGx5IHBhc3MgYSByZWd1bGFyCiAgICBKYXZhU2NyaXB0IG9iamVjdCBjb250YWluaW5nIHRoZSBkZXNpcmVkIG9wdGlvbnMgaW50byBtZXRob2RzIHRoYXQgcmVxdWlyZQogICAgb25lIG9mIHRoZXNlIG9wdGlvbnMgb2JqZWN0OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgTXlBcHAudmlzaXQoIi8iLCB7IGxvY2F0aW9uOiAibm9uZSIsIHJvb3RFbGVtZW50OiAiI2NvbnRhaW5lciIgfSk7CiAgICBgYGAKICAKICAgIE5vdCBhbGwgY29tYmluYXRpb25zIG9mIHRoZSBzdXBwb3J0ZWQgb3B0aW9ucyBhcmUgdmFsaWQuIFNlZSB0aGUgZG9jdW1lbnRhdGlvbgogICAgb24gYEFwcGxpY2F0aW9uI3Zpc2l0YCBmb3IgdGhlIHN1cHBvcnRlZCBjb25maWd1cmF0aW9ucy4KICAKICAgIEludGVybmFsLCBleHBlcmltZW50YWwgb3Igb3RoZXJ3aXNlIHVuc3RhYmxlIGZsYWdzIGFyZSBtYXJrZWQgYXMgcHJpdmF0ZS4KICAKICAgIEBjbGFzcyBCb290T3B0aW9ucwogICAgQG5hbWVzcGFjZSBBcHBsaWNhdGlvbkluc3RhbmNlCiAgICBAcHVibGljCiAgKi8KCiAgdmFyIEJvb3RPcHRpb25zID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQm9vdE9wdGlvbnMob3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICAvKioKICAgICAgICBQcm92aWRlIGEgc3BlY2lmaWMgaW5zdGFuY2Ugb2YgalF1ZXJ5LiBUaGlzIGlzIHVzZWZ1bCBpbiBjb25qdW5jdGlvbiB3aXRoCiAgICAgICAgdGhlIGBkb2N1bWVudGAgb3B0aW9uLCBhcyBpdCBhbGxvd3MgeW91IHRvIHVzZSBhIGNvcHkgb2YgYGpRdWVyeWAgdGhhdCBpcwogICAgICAgIGFwcHJvcHJpYXRlbHkgYm91bmQgdG8gdGhlIGZvcmVpZ24gYGRvY3VtZW50YCAoZS5nLiBhIGpzZG9tKS4KICAgICAgICAgVGhpcyBpcyBoaWdobHkgZXhwZXJpbWVudGFsIGFuZCBzdXBwb3J0IHZlcnkgaW5jb21wbGV0ZSBhdCB0aGUgbW9tZW50LgogICAgICAgICBAcHJvcGVydHkgalF1ZXJ5CiAgICAgICAgQHR5cGUgT2JqZWN0CiAgICAgICAgQGRlZmF1bHQgYXV0by1kZXRlY3RlZAogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIHRoaXMualF1ZXJ5ID0gX3ZpZXdzLmpRdWVyeTsgLy8gVGhpcyBkZWZhdWx0IGlzIG92ZXJyaWRhYmxlIGJlbG93CgogICAgICAvKioKICAgICAgICBJbnRlcmFjdGl2ZSBtb2RlOiB3aGV0aGVyIHdlIG5lZWQgdG8gc2V0IHVwIGV2ZW50IGRlbGVnYXRpb24gYW5kIGludm9rZQogICAgICAgIGxpZmVjeWNsZSBjYWxsYmFja3Mgb24gQ29tcG9uZW50cy4KICAgICAgICAgQHByb3BlcnR5IGlzSW50ZXJhY3RpdmUKICAgICAgICBAdHlwZSBib29sZWFuCiAgICAgICAgQGRlZmF1bHQgYXV0by1kZXRlY3RlZAogICAgICAgIEBwcml2YXRlCiAgICAgICovCgogICAgICB0aGlzLmlzSW50ZXJhY3RpdmUgPSBlbnZpcm9ubWVudC5oYXNET007IC8vIFRoaXMgZGVmYXVsdCBpcyBvdmVycmlkYWJsZSBiZWxvdwoKICAgICAgLyoqCiAgICAgICAgQHByb3BlcnR5IF9yZW5kZXJNb2RlCiAgICAgICAgQHR5cGUgc3RyaW5nCiAgICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwoKICAgICAgdGhpcy5fcmVuZGVyTW9kZSA9IG9wdGlvbnMuX3JlbmRlck1vZGU7CiAgICAgIC8qKgogICAgICAgIFJ1biBpbiBhIGZ1bGwgYnJvd3NlciBlbnZpcm9ubWVudC4KICAgICAgICAgV2hlbiB0aGlzIGZsYWcgaXMgc2V0IHRvIGBmYWxzZWAsIGl0IHdpbGwgZGlzYWJsZSBtb3N0IGJyb3dzZXItc3BlY2lmaWMKICAgICAgICBhbmQgaW50ZXJhY3RpdmUgZmVhdHVyZXMuIFNwZWNpZmljYWxseToKICAgICAgICAgKiBJdCBkb2VzIG5vdCB1c2UgYGpRdWVyeWAgdG8gYXBwZW5kIHRoZSByb290IHZpZXc7IHRoZSBgcm9vdEVsZW1lbnRgCiAgICAgICAgICAoZWl0aGVyIHNwZWNpZmllZCBhcyBhIHN1YnNlcXVlbnQgb3B0aW9uIG9yIG9uIHRoZSBhcHBsaWNhdGlvbiBpdHNlbGYpCiAgICAgICAgICBtdXN0IGFscmVhZHkgYmUgYW4gYEVsZW1lbnRgIGluIHRoZSBnaXZlbiBgZG9jdW1lbnRgIChhcyBvcHBvc2VkIHRvIGEKICAgICAgICAgIHN0cmluZyBzZWxlY3RvcikuCiAgICAgICAgICogSXQgZG9lcyBub3Qgc2V0IHVwIGFuIGBFdmVudERpc3BhdGNoZXJgLgogICAgICAgICAqIEl0IGRvZXMgbm90IHJ1biBhbnkgYENvbXBvbmVudGAgbGlmZWN5Y2xlIGhvb2tzIChzdWNoIGFzIGBkaWRJbnNlcnRFbGVtZW50YCkuCiAgICAgICAgICogSXQgc2V0cyB0aGUgYGxvY2F0aW9uYCBvcHRpb24gdG8gYCJub25lImAuIChJZiB5b3Ugd291bGQgbGlrZSB0byB1c2UKICAgICAgICAgIHRoZSBsb2NhdGlvbiBhZGFwdGVyIHNwZWNpZmllZCBpbiB0aGUgYXBwJ3Mgcm91dGVyIGluc3RlYWQsIHlvdSBjYW4gYWxzbwogICAgICAgICAgc3BlY2lmeSBgeyBsb2NhdGlvbjogbnVsbCB9YCB0byBzcGVjaWZpY2FsbHkgb3B0LW91dC4pCiAgICAgICAgIEBwcm9wZXJ0eSBpc0Jyb3dzZXIKICAgICAgICBAdHlwZSBib29sZWFuCiAgICAgICAgQGRlZmF1bHQgYXV0by1kZXRlY3RlZAogICAgICAgIEBwdWJsaWMKICAgICAgKi8KCiAgICAgIGlmIChvcHRpb25zLmlzQnJvd3NlciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdGhpcy5pc0Jyb3dzZXIgPSBCb29sZWFuKG9wdGlvbnMuaXNCcm93c2VyKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLmlzQnJvd3NlciA9IGVudmlyb25tZW50Lmhhc0RPTTsKICAgICAgfQoKICAgICAgaWYgKCF0aGlzLmlzQnJvd3NlcikgewogICAgICAgIHRoaXMualF1ZXJ5ID0gbnVsbDsKICAgICAgICB0aGlzLmlzSW50ZXJhY3RpdmUgPSBmYWxzZTsKICAgICAgICB0aGlzLmxvY2F0aW9uID0gJ25vbmUnOwogICAgICB9CiAgICAgIC8qKgogICAgICAgIERpc2FibGUgcmVuZGVyaW5nIGNvbXBsZXRlbHkuCiAgICAgICAgIFdoZW4gdGhpcyBmbGFnIGlzIHNldCB0byBgZmFsc2VgLCBpdCB3aWxsIGRpc2FibGUgdGhlIGVudGlyZSByZW5kZXJpbmcKICAgICAgICBwaXBlbGluZS4gRXNzZW50aWFsbHksIHRoaXMgcHV0cyB0aGUgYXBwIGludG8gInJvdXRpbmctb25seSIgbW9kZS4gTm8KICAgICAgICB0ZW1wbGF0ZXMgd2lsbCBiZSByZW5kZXJlZCwgYW5kIG5vIENvbXBvbmVudHMgd2lsbCBiZSBjcmVhdGVkLgogICAgICAgICBAcHJvcGVydHkgc2hvdWxkUmVuZGVyCiAgICAgICAgQHR5cGUgYm9vbGVhbgogICAgICAgIEBkZWZhdWx0IHRydWUKICAgICAgICBAcHVibGljCiAgICAgICovCgoKICAgICAgaWYgKG9wdGlvbnMuc2hvdWxkUmVuZGVyICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLnNob3VsZFJlbmRlciA9IEJvb2xlYW4ob3B0aW9ucy5zaG91bGRSZW5kZXIpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuc2hvdWxkUmVuZGVyID0gdHJ1ZTsKICAgICAgfQoKICAgICAgaWYgKCF0aGlzLnNob3VsZFJlbmRlcikgewogICAgICAgIHRoaXMualF1ZXJ5ID0gbnVsbDsKICAgICAgICB0aGlzLmlzSW50ZXJhY3RpdmUgPSBmYWxzZTsKICAgICAgfQogICAgICAvKioKICAgICAgICBJZiBwcmVzZW50LCByZW5kZXIgaW50byB0aGUgZ2l2ZW4gYERvY3VtZW50YCBvYmplY3QgaW5zdGVhZCBvZiB0aGUKICAgICAgICBnbG9iYWwgYHdpbmRvdy5kb2N1bWVudGAgb2JqZWN0LgogICAgICAgICBJbiBwcmFjdGljZSwgdGhpcyBpcyBvbmx5IHVzZWZ1bCBpbiBub24tYnJvd3NlciBlbnZpcm9ubWVudCBvciBpbgogICAgICAgIG5vbi1pbnRlcmFjdGl2ZSBtb2RlLCBiZWNhdXNlIEVtYmVyJ3MgYGpRdWVyeWAgZGVwZW5kZW5jeSBpcwogICAgICAgIGltcGxpY2l0bHkgYm91bmQgdG8gdGhlIGN1cnJlbnQgZG9jdW1lbnQsIGNhdXNpbmcgZXZlbnQgZGVsZWdhdGlvbgogICAgICAgIHRvIG5vdCB3b3JrIHByb3Blcmx5IHdoZW4gdGhlIGFwcCBpcyByZW5kZXJlZCBpbnRvIGEgZm9yZWlnbgogICAgICAgIGRvY3VtZW50IG9iamVjdCAoc3VjaCBhcyBhbiBpZnJhbWUncyBgY29udGVudERvY3VtZW50YCkuCiAgICAgICAgIEluIG5vbi1icm93c2VyIG1vZGUsIHRoaXMgY291bGQgYmUgYSAiYERvY3VtZW50YC1saWtlIiBvYmplY3QgYXMKICAgICAgICBFbWJlciBvbmx5IGludGVyYWN0IHdpdGggYSBzbWFsbCBzdWJzZXQgb2YgdGhlIERPTSBBUEkgaW4gbm9uLQogICAgICAgIGludGVyYWN0aXZlIG1vZGUuIFdoaWxlIHRoZSBleGFjdCByZXF1aXJlbWVudHMgaGF2ZSBub3QgeWV0IGJlZW4KICAgICAgICBmb3JtYWxpemVkLCB0aGUgYFNpbXBsZURPTWAgbGlicmFyeSdzIGltcGxlbWVudGF0aW9uIGlzIGtub3duIHRvCiAgICAgICAgd29yay4KICAgICAgICAgQHByb3BlcnR5IGRvY3VtZW50CiAgICAgICAgQHR5cGUgRG9jdW1lbnQKICAgICAgICBAZGVmYXVsdCB0aGUgZ2xvYmFsIGBkb2N1bWVudGAgb2JqZWN0CiAgICAgICAgQHB1YmxpYwogICAgICAqLwoKCiAgICAgIGlmIChvcHRpb25zLmRvY3VtZW50KSB7CiAgICAgICAgdGhpcy5kb2N1bWVudCA9IG9wdGlvbnMuZG9jdW1lbnQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5kb2N1bWVudCA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgPyBkb2N1bWVudCA6IG51bGw7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAgSWYgcHJlc2VudCwgb3ZlcnJpZGVzIHRoZSBhcHBsaWNhdGlvbidzIGByb290RWxlbWVudGAgcHJvcGVydHkgb24KICAgICAgICB0aGUgaW5zdGFuY2UuIFRoaXMgaXMgdXNlZnVsIGZvciB0ZXN0aW5nIGVudmlyb25tZW50LCB3aGVyZSB5b3UKICAgICAgICBtaWdodCB3YW50IHRvIGFwcGVuZCB0aGUgcm9vdCB2aWV3IHRvIGEgZml4dHVyZSBhcmVhLgogICAgICAgICBJbiBub24tYnJvd3NlciBtb2RlLCBiZWNhdXNlIEVtYmVyIGRvZXMgbm90IGhhdmUgYWNjZXNzIHRvIGpRdWVyeSwKICAgICAgICB0aGlzIG9wdGlvbnMgbXVzdCBiZSBzcGVjaWZpZWQgYXMgYSBET00gYEVsZW1lbnRgIG9iamVjdCBpbnN0ZWFkIG9mCiAgICAgICAgYSBzZWxlY3RvciBzdHJpbmcuCiAgICAgICAgIFNlZSB0aGUgZG9jdW1lbnRhdGlvbiBvbiBgQXBwbGljYXRpb25gJ3MgYHJvb3RFbGVtZW50YCBmb3IKICAgICAgICBkZXRhaWxzLgogICAgICAgICBAcHJvcGVydHkgcm9vdEVsZW1lbnQKICAgICAgICBAdHlwZSBTdHJpbmd8RWxlbWVudAogICAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgICBAcHVibGljCiAgICAgICAqLwoKCiAgICAgIGlmIChvcHRpb25zLnJvb3RFbGVtZW50KSB7CiAgICAgICAgdGhpcy5yb290RWxlbWVudCA9IG9wdGlvbnMucm9vdEVsZW1lbnQ7CiAgICAgIH0gLy8gU2V0IHRoZXNlIG9wdGlvbnMgbGFzdCB0byBnaXZlIHRoZSB1c2VyIGEgY2hhbmNlIHRvIG92ZXJyaWRlIHRoZQogICAgICAvLyBkZWZhdWx0cyBmcm9tIHRoZSAiY29tYm8iIG9wdGlvbnMgbGlrZSBgaXNCcm93c2VyYCAoYWx0aG91Z2ggaW4KICAgICAgLy8gcHJhY3RpY2UsIHRoZSByZXN1bHRpbmcgY29tYmluYXRpb24gaXMgcHJvYmFibHkgaW52YWxpZCkKCiAgICAgIC8qKgogICAgICAgIElmIHByZXNlbnQsIG92ZXJyaWRlcyB0aGUgcm91dGVyJ3MgYGxvY2F0aW9uYCBwcm9wZXJ0eSB3aXRoIHRoaXMKICAgICAgICB2YWx1ZS4gVGhpcyBpcyB1c2VmdWwgZm9yIGVudmlyb25tZW50cyB3aGVyZSB0cnlpbmcgdG8gbW9kaWZ5IHRoZQogICAgICAgIFVSTCB3b3VsZCBiZSBpbmFwcHJvcHJpYXRlLgogICAgICAgICBAcHJvcGVydHkgbG9jYXRpb24KICAgICAgICBAdHlwZSBzdHJpbmcKICAgICAgICBAZGVmYXVsdCBudWxsCiAgICAgICAgQHB1YmxpYwogICAgICAqLwoKCiAgICAgIGlmIChvcHRpb25zLmxvY2F0aW9uICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLmxvY2F0aW9uID0gb3B0aW9ucy5sb2NhdGlvbjsKICAgICAgfQoKICAgICAgaWYgKG9wdGlvbnMualF1ZXJ5ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLmpRdWVyeSA9IG9wdGlvbnMualF1ZXJ5OwogICAgICB9CgogICAgICBpZiAob3B0aW9ucy5pc0ludGVyYWN0aXZlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLmlzSW50ZXJhY3RpdmUgPSBCb29sZWFuKG9wdGlvbnMuaXNJbnRlcmFjdGl2ZSk7CiAgICAgIH0KICAgIH0KCiAgICB2YXIgX3Byb3RvID0gQm9vdE9wdGlvbnMucHJvdG90eXBlOwoKICAgIF9wcm90by50b0Vudmlyb25tZW50ID0gZnVuY3Rpb24gdG9FbnZpcm9ubWVudCgpIHsKICAgICAgLy8gRG8gd2UgcmVhbGx5IHdhbnQgdG8gYXNzaWduIGFsbCBvZiB0aGlzIT8KICAgICAgdmFyIGVudiA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIGVudmlyb25tZW50KTsgLy8gRm9yIGNvbXBhdGliaWxpdHkgd2l0aCBleGlzdGluZyBjb2RlCgogICAgICBlbnYuaGFzRE9NID0gdGhpcy5pc0Jyb3dzZXI7CiAgICAgIGVudi5pc0ludGVyYWN0aXZlID0gdGhpcy5pc0ludGVyYWN0aXZlOwogICAgICBlbnYuX3JlbmRlck1vZGUgPSB0aGlzLl9yZW5kZXJNb2RlOwogICAgICBlbnYub3B0aW9ucyA9IHRoaXM7CiAgICAgIHJldHVybiBlbnY7CiAgICB9OwoKICAgIHJldHVybiBCb290T3B0aW9uczsKICB9KCk7CgogIHZhciBfZGVmYXVsdCA9IEFwcGxpY2F0aW9uSW5zdGFuY2U7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvYXBwbGljYXRpb24vbGliL2FwcGxpY2F0aW9uIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL2Jyb3dzZXItZW52aXJvbm1lbnQiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci9ydW5sb29wIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci9hcHBsaWNhdGlvbi9saWIvbGF6eV9sb2FkIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZyIsICJAZW1iZXIvYXBwbGljYXRpb24vaW5zdGFuY2UiLCAiQGVtYmVyL2VuZ2luZSIsICJAZW1iZXIvLWludGVybmFscy9jb250YWluZXIiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZ2xpbW1lciIsICJAZW1iZXIvZGVwcmVjYXRlZC1mZWF0dXJlcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfdXRpbHMsIF9lbnZpcm9ubWVudCwgX2Jyb3dzZXJFbnZpcm9ubWVudCwgX2RlYnVnLCBfcnVubG9vcCwgX21ldGFsLCBfbGF6eV9sb2FkLCBfcnVudGltZSwgX3ZpZXdzLCBfcm91dGluZywgX2luc3RhbmNlLCBfZW5naW5lLCBfY29udGFpbmVyLCBfZ2xpbW1lciwgX2RlcHJlY2F0ZWRGZWF0dXJlcykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0KCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsiLWJ1Y2tldC1jYWNoZTptYWluIl0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdCgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgdmFyIGxpYnJhcmllc1JlZ2lzdGVyZWQgPSBmYWxzZTsKICAvKioKICAgIEFuIGluc3RhbmNlIG9mIGBBcHBsaWNhdGlvbmAgaXMgdGhlIHN0YXJ0aW5nIHBvaW50IGZvciBldmVyeSBFbWJlcgogICAgYXBwbGljYXRpb24uIEl0IGhlbHBzIHRvIGluc3RhbnRpYXRlLCBpbml0aWFsaXplIGFuZCBjb29yZGluYXRlIHRoZSBtYW55CiAgICBvYmplY3RzIHRoYXQgbWFrZSB1cCB5b3VyIGFwcC4KICAKICAgIEVhY2ggRW1iZXIgYXBwIGhhcyBvbmUgYW5kIG9ubHkgb25lIGBBcHBsaWNhdGlvbmAgb2JqZWN0LiBJbiBmYWN0LCB0aGUKICAgIHZlcnkgZmlyc3QgdGhpbmcgeW91IHNob3VsZCBkbyBpbiB5b3VyIGFwcGxpY2F0aW9uIGlzIGNyZWF0ZSB0aGUgaW5zdGFuY2U6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAKICAgIHdpbmRvdy5BcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoKTsKICAgIGBgYAogIAogICAgVHlwaWNhbGx5LCB0aGUgYXBwbGljYXRpb24gb2JqZWN0IGlzIHRoZSBvbmx5IGdsb2JhbCB2YXJpYWJsZS4gQWxsIG90aGVyCiAgICBjbGFzc2VzIGluIHlvdXIgYXBwIHNob3VsZCBiZSBwcm9wZXJ0aWVzIG9uIHRoZSBgQXBwbGljYXRpb25gIGluc3RhbmNlLAogICAgd2hpY2ggaGlnaGxpZ2h0cyBpdHMgZmlyc3Qgcm9sZTogYSBnbG9iYWwgbmFtZXNwYWNlLgogIAogICAgRm9yIGV4YW1wbGUsIGlmIHlvdSBkZWZpbmUgYSB2aWV3IGNsYXNzLCBpdCBtaWdodCBsb29rIGxpa2UgdGhpczoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogIAogICAgQXBwLk15VmlldyA9IEVtYmVyLlZpZXcuZXh0ZW5kKCk7CiAgICBgYGAKICAKICAgIEJ5IGRlZmF1bHQsIGNhbGxpbmcgYEFwcGxpY2F0aW9uLmNyZWF0ZSgpYCB3aWxsIGF1dG9tYXRpY2FsbHkgaW5pdGlhbGl6ZQogICAgeW91ciBhcHBsaWNhdGlvbiBieSBjYWxsaW5nIHRoZSBgQXBwbGljYXRpb24uaW5pdGlhbGl6ZSgpYCBtZXRob2QuIElmCiAgICB5b3UgbmVlZCB0byBkZWxheSBpbml0aWFsaXphdGlvbiwgeW91IGNhbiBjYWxsIHlvdXIgYXBwJ3MgYGRlZmVyUmVhZGluZXNzKClgCiAgICBtZXRob2QuIFdoZW4geW91IGFyZSByZWFkeSBmb3IgeW91ciBhcHAgdG8gYmUgaW5pdGlhbGl6ZWQsIGNhbGwgaXRzCiAgICBgYWR2YW5jZVJlYWRpbmVzcygpYCBtZXRob2QuCiAgCiAgICBZb3UgY2FuIGRlZmluZSBhIGByZWFkeWAgbWV0aG9kIG9uIHRoZSBgQXBwbGljYXRpb25gIGluc3RhbmNlLCB3aGljaAogICAgd2lsbCBiZSBydW4gYnkgRW1iZXIgd2hlbiB0aGUgYXBwbGljYXRpb24gaXMgaW5pdGlhbGl6ZWQuCiAgCiAgICBCZWNhdXNlIGBBcHBsaWNhdGlvbmAgaW5oZXJpdHMgZnJvbSBgRW1iZXIuTmFtZXNwYWNlYCwgYW55IGNsYXNzZXMKICAgIHlvdSBjcmVhdGUgd2lsbCBoYXZlIHVzZWZ1bCBzdHJpbmcgcmVwcmVzZW50YXRpb25zIHdoZW4gY2FsbGluZyBgdG9TdHJpbmcoKWAuCiAgICBTZWUgdGhlIGBFbWJlci5OYW1lc3BhY2VgIGRvY3VtZW50YXRpb24gZm9yIG1vcmUgaW5mb3JtYXRpb24uCiAgCiAgICBXaGlsZSB5b3UgY2FuIHRoaW5rIG9mIHlvdXIgYEFwcGxpY2F0aW9uYCBhcyBhIGNvbnRhaW5lciB0aGF0IGhvbGRzIHRoZQogICAgb3RoZXIgY2xhc3NlcyBpbiB5b3VyIGFwcGxpY2F0aW9uLCB0aGVyZSBhcmUgc2V2ZXJhbCBvdGhlciByZXNwb25zaWJpbGl0aWVzCiAgICBnb2luZyBvbiB1bmRlci10aGUtaG9vZCB0aGF0IHlvdSBtYXkgd2FudCB0byB1bmRlcnN0YW5kLgogIAogICAgIyMjIEV2ZW50IERlbGVnYXRpb24KICAKICAgIEVtYmVyIHVzZXMgYSB0ZWNobmlxdWUgY2FsbGVkIF9ldmVudCBkZWxlZ2F0aW9uXy4gVGhpcyBhbGxvd3MgdGhlIGZyYW1ld29yawogICAgdG8gc2V0IHVwIGEgZ2xvYmFsLCBzaGFyZWQgZXZlbnQgbGlzdGVuZXIgaW5zdGVhZCBvZiByZXF1aXJpbmcgZWFjaCB2aWV3IHRvCiAgICBkbyBpdCBtYW51YWxseS4gRm9yIGV4YW1wbGUsIGluc3RlYWQgb2YgZWFjaCB2aWV3IHJlZ2lzdGVyaW5nIGl0cyBvd24KICAgIGBtb3VzZWRvd25gIGxpc3RlbmVyIG9uIGl0cyBhc3NvY2lhdGVkIGVsZW1lbnQsIEVtYmVyIHNldHMgdXAgYSBgbW91c2Vkb3duYAogICAgbGlzdGVuZXIgb24gdGhlIGBib2R5YC4KICAKICAgIElmIGEgYG1vdXNlZG93bmAgZXZlbnQgb2NjdXJzLCBFbWJlciB3aWxsIGxvb2sgYXQgdGhlIHRhcmdldCBvZiB0aGUgZXZlbnQgYW5kCiAgICBzdGFydCB3YWxraW5nIHVwIHRoZSBET00gbm9kZSB0cmVlLCBmaW5kaW5nIGNvcnJlc3BvbmRpbmcgdmlld3MgYW5kIGludm9raW5nCiAgICB0aGVpciBgbW91c2VEb3duYCBtZXRob2QgYXMgaXQgZ29lcy4KICAKICAgIGBBcHBsaWNhdGlvbmAgaGFzIGEgbnVtYmVyIG9mIGRlZmF1bHQgZXZlbnRzIHRoYXQgaXQgbGlzdGVucyBmb3IsIGFzCiAgICB3ZWxsIGFzIGEgbWFwcGluZyBmcm9tIGxvd2VyY2FzZSBldmVudHMgdG8gY2FtZWwtY2FzZWQgdmlldyBtZXRob2QgbmFtZXMuIEZvcgogICAgZXhhbXBsZSwgdGhlIGBrZXlwcmVzc2AgZXZlbnQgY2F1c2VzIHRoZSBga2V5UHJlc3NgIG1ldGhvZCBvbiB0aGUgdmlldyB0byBiZQogICAgY2FsbGVkLCB0aGUgYGRibGNsaWNrYCBldmVudCBjYXVzZXMgYGRvdWJsZUNsaWNrYCB0byBiZSBjYWxsZWQsIGFuZCBzbyBvbi4KICAKICAgIElmIHRoZXJlIGlzIGEgYnViYmxpbmcgYnJvd3NlciBldmVudCB0aGF0IEVtYmVyIGRvZXMgbm90IGxpc3RlbiBmb3IgYnkKICAgIGRlZmF1bHQsIHlvdSBjYW4gc3BlY2lmeSBjdXN0b20gZXZlbnRzIGFuZCB0aGVpciBjb3JyZXNwb25kaW5nIHZpZXcgbWV0aG9kCiAgICBuYW1lcyBieSBzZXR0aW5nIHRoZSBhcHBsaWNhdGlvbidzIGBjdXN0b21FdmVudHNgIHByb3BlcnR5OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgCiAgICBsZXQgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKHsKICAgICAgY3VzdG9tRXZlbnRzOiB7CiAgICAgICAgLy8gYWRkIHN1cHBvcnQgZm9yIHRoZSBwYXN0ZSBldmVudAogICAgICAgIHBhc3RlOiAncGFzdGUnCiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBUbyBwcmV2ZW50IEVtYmVyIGZyb20gc2V0dGluZyB1cCBhIGxpc3RlbmVyIGZvciBhIGRlZmF1bHQgZXZlbnQsCiAgICBzcGVjaWZ5IHRoZSBldmVudCBuYW1lIHdpdGggYSBgbnVsbGAgdmFsdWUgaW4gdGhlIGBjdXN0b21FdmVudHNgCiAgICBwcm9wZXJ0eToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogIAogICAgbGV0IEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSh7CiAgICAgIGN1c3RvbUV2ZW50czogewogICAgICAgIC8vIHByZXZlbnQgbGlzdGVuZXJzIGZvciBtb3VzZWVudGVyL21vdXNlbGVhdmUgZXZlbnRzCiAgICAgICAgbW91c2VlbnRlcjogbnVsbCwKICAgICAgICBtb3VzZWxlYXZlOiBudWxsCiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBCeSBkZWZhdWx0LCB0aGUgYXBwbGljYXRpb24gc2V0cyB1cCB0aGVzZSBldmVudCBsaXN0ZW5lcnMgb24gdGhlIGRvY3VtZW50CiAgICBib2R5LiBIb3dldmVyLCBpbiBjYXNlcyB3aGVyZSB5b3UgYXJlIGVtYmVkZGluZyBhbiBFbWJlciBhcHBsaWNhdGlvbiBpbnNpZGUKICAgIGFuIGV4aXN0aW5nIHBhZ2UsIHlvdSBtYXkgd2FudCBpdCB0byBzZXQgdXAgdGhlIGxpc3RlbmVycyBvbiBhbiBlbGVtZW50CiAgICBpbnNpZGUgdGhlIGJvZHkuCiAgCiAgICBGb3IgZXhhbXBsZSwgaWYgb25seSBldmVudHMgaW5zaWRlIGEgRE9NIGVsZW1lbnQgd2l0aCB0aGUgSUQgb2YgYGVtYmVyLWFwcGAKICAgIHNob3VsZCBiZSBkZWxlZ2F0ZWQsIHNldCB5b3VyIGFwcGxpY2F0aW9uJ3MgYHJvb3RFbGVtZW50YCBwcm9wZXJ0eToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogIAogICAgbGV0IEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSh7CiAgICAgIHJvb3RFbGVtZW50OiAnI2VtYmVyLWFwcCcKICAgIH0pOwogICAgYGBgCiAgCiAgICBUaGUgYHJvb3RFbGVtZW50YCBjYW4gYmUgZWl0aGVyIGEgRE9NIGVsZW1lbnQgb3IgYSBqUXVlcnktY29tcGF0aWJsZSBzZWxlY3RvcgogICAgc3RyaW5nLiBOb3RlIHRoYXQgKnZpZXdzIGFwcGVuZGVkIHRvIHRoZSBET00gb3V0c2lkZSB0aGUgcm9vdCBlbGVtZW50IHdpbGwKICAgIG5vdCByZWNlaXZlIGV2ZW50cy4qIElmIHlvdSBzcGVjaWZ5IGEgY3VzdG9tIHJvb3QgZWxlbWVudCwgbWFrZSBzdXJlIHlvdSBvbmx5CiAgICBhcHBlbmQgdmlld3MgaW5zaWRlIGl0IQogIAogICAgVG8gbGVhcm4gbW9yZSBhYm91dCB0aGUgZXZlbnRzIEVtYmVyIGNvbXBvbmVudHMgdXNlLCBzZWUKICAKICAgIFtjb21wb25lbnRzL2hhbmRsaW5nLWV2ZW50c10oaHR0cHM6Ly9ndWlkZXMuZW1iZXJqcy5jb20vcmVsZWFzZS9jb21wb25lbnRzL2hhbmRsaW5nLWV2ZW50cy8jdG9jX2V2ZW50LW5hbWVzKS4KICAKICAgICMjIyBJbml0aWFsaXplcnMKICAKICAgIExpYnJhcmllcyBvbiB0b3Agb2YgRW1iZXIgY2FuIGFkZCBpbml0aWFsaXplcnMsIGxpa2Ugc286CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAKICAgIEFwcGxpY2F0aW9uLmluaXRpYWxpemVyKHsKICAgICAgbmFtZTogJ2FwaS1hZGFwdGVyJywKICAKICAgICAgaW5pdGlhbGl6ZTogZnVuY3Rpb24oYXBwbGljYXRpb24pIHsKICAgICAgICBhcHBsaWNhdGlvbi5yZWdpc3RlcignYXBpLWFkYXB0ZXI6bWFpbicsIEFwaUFkYXB0ZXIpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgSW5pdGlhbGl6ZXJzIHByb3ZpZGUgYW4gb3Bwb3J0dW5pdHkgdG8gYWNjZXNzIHRoZSBpbnRlcm5hbCByZWdpc3RyeSwgd2hpY2gKICAgIG9yZ2FuaXplcyB0aGUgZGlmZmVyZW50IGNvbXBvbmVudHMgb2YgYW4gRW1iZXIgYXBwbGljYXRpb24uIEFkZGl0aW9uYWxseQogICAgdGhleSBwcm92aWRlIGEgY2hhbmNlIHRvIGFjY2VzcyB0aGUgaW5zdGFudGlhdGVkIGFwcGxpY2F0aW9uLiBCZXlvbmQKICAgIGJlaW5nIHVzZWQgZm9yIGxpYnJhcmllcywgaW5pdGlhbGl6ZXJzIGFyZSBhbHNvIGEgZ3JlYXQgd2F5IHRvIG9yZ2FuaXplCiAgICBkZXBlbmRlbmN5IGluamVjdGlvbiBvciBzZXR1cCBpbiB5b3VyIG93biBhcHBsaWNhdGlvbi4KICAKICAgICMjIyBSb3V0aW5nCiAgCiAgICBJbiBhZGRpdGlvbiB0byBjcmVhdGluZyB5b3VyIGFwcGxpY2F0aW9uJ3Mgcm91dGVyLCBgQXBwbGljYXRpb25gIGlzCiAgICBhbHNvIHJlc3BvbnNpYmxlIGZvciB0ZWxsaW5nIHRoZSByb3V0ZXIgd2hlbiB0byBzdGFydCByb3V0aW5nLiBUcmFuc2l0aW9ucwogICAgYmV0d2VlbiByb3V0ZXMgY2FuIGJlIGxvZ2dlZCB3aXRoIHRoZSBgTE9HX1RSQU5TSVRJT05TYCBmbGFnLCBhbmQgbW9yZQogICAgZGV0YWlsZWQgaW50cmEtdHJhbnNpdGlvbiBsb2dnaW5nIGNhbiBiZSBsb2dnZWQgd2l0aAogICAgdGhlIGBMT0dfVFJBTlNJVElPTlNfSU5URVJOQUxgIGZsYWc6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAKICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoewogICAgICBMT0dfVFJBTlNJVElPTlM6IHRydWUsIC8vIGJhc2ljIGxvZ2dpbmcgb2Ygc3VjY2Vzc2Z1bCB0cmFuc2l0aW9ucwogICAgICBMT0dfVFJBTlNJVElPTlNfSU5URVJOQUw6IHRydWUgLy8gZGV0YWlsZWQgbG9nZ2luZyBvZiBhbGwgcm91dGluZyBzdGVwcwogICAgfSk7CiAgICBgYGAKICAKICAgIEJ5IGRlZmF1bHQsIHRoZSByb3V0ZXIgd2lsbCBiZWdpbiB0cnlpbmcgdG8gdHJhbnNsYXRlIHRoZSBjdXJyZW50IFVSTCBpbnRvCiAgICBhcHBsaWNhdGlvbiBzdGF0ZSBvbmNlIHRoZSBicm93c2VyIGVtaXRzIHRoZSBgRE9NQ29udGVudFJlYWR5YCBldmVudC4gSWYgeW91CiAgICBuZWVkIHRvIGRlZmVyIHJvdXRpbmcsIHlvdSBjYW4gY2FsbCB0aGUgYXBwbGljYXRpb24ncyBgZGVmZXJSZWFkaW5lc3MoKWAKICAgIG1ldGhvZC4gT25jZSByb3V0aW5nIGNhbiBiZWdpbiwgY2FsbCB0aGUgYGFkdmFuY2VSZWFkaW5lc3MoKWAgbWV0aG9kLgogIAogICAgSWYgdGhlcmUgaXMgYW55IHNldHVwIHJlcXVpcmVkIGJlZm9yZSByb3V0aW5nIGJlZ2lucywgeW91IGNhbiBpbXBsZW1lbnQgYQogICAgYHJlYWR5KClgIG1ldGhvZCBvbiB5b3VyIGFwcCB0aGF0IHdpbGwgYmUgaW52b2tlZCBpbW1lZGlhdGVseSBiZWZvcmUgcm91dGluZwogICAgYmVnaW5zLgogIAogICAgQGNsYXNzIEFwcGxpY2F0aW9uCiAgICBAZXh0ZW5kcyBFbmdpbmUKICAgIEB1c2VzIFJlZ2lzdHJ5UHJveHlNaXhpbgogICAgQHB1YmxpYwogICovCgogIHZhciBBcHBsaWNhdGlvbiA9IF9lbmdpbmUuZGVmYXVsdC5leHRlbmQoewogICAgLyoqCiAgICAgIFRoZSByb290IERPTSBlbGVtZW50IG9mIHRoZSBBcHBsaWNhdGlvbi4gVGhpcyBjYW4gYmUgc3BlY2lmaWVkIGFzIGFuCiAgICAgIGVsZW1lbnQgb3IgYQogICAgICBbalF1ZXJ5LWNvbXBhdGlibGUgc2VsZWN0b3Igc3RyaW5nXShodHRwOi8vYXBpLmpxdWVyeS5jb20vY2F0ZWdvcnkvc2VsZWN0b3JzLykuCiAgICAgICBUaGlzIGlzIHRoZSBlbGVtZW50IHRoYXQgd2lsbCBiZSBwYXNzZWQgdG8gdGhlIEFwcGxpY2F0aW9uJ3MsCiAgICAgIGBldmVudERpc3BhdGNoZXJgLCB3aGljaCBzZXRzIHVwIHRoZSBsaXN0ZW5lcnMgZm9yIGV2ZW50IGRlbGVnYXRpb24uIEV2ZXJ5CiAgICAgIHZpZXcgaW4geW91ciBhcHBsaWNhdGlvbiBzaG91bGQgYmUgYSBjaGlsZCBvZiB0aGUgZWxlbWVudCB5b3Ugc3BlY2lmeSBoZXJlLgogICAgICAgQHByb3BlcnR5IHJvb3RFbGVtZW50CiAgICAgIEB0eXBlIERPTUVsZW1lbnQKICAgICAgQGRlZmF1bHQgJ2JvZHknCiAgICAgIEBwdWJsaWMKICAgICovCiAgICByb290RWxlbWVudDogJ2JvZHknLAoKICAgIC8qKgogICAgICBUaGUgYEVtYmVyLkV2ZW50RGlzcGF0Y2hlcmAgcmVzcG9uc2libGUgZm9yIGRlbGVnYXRpbmcgZXZlbnRzIHRvIHRoaXMKICAgICAgYXBwbGljYXRpb24ncyB2aWV3cy4KICAgICAgIFRoZSBldmVudCBkaXNwYXRjaGVyIGlzIGNyZWF0ZWQgYnkgdGhlIGFwcGxpY2F0aW9uIGF0IGluaXRpYWxpemF0aW9uIHRpbWUKICAgICAgYW5kIHNldHMgdXAgZXZlbnQgbGlzdGVuZXJzIG9uIHRoZSBET00gZWxlbWVudCBkZXNjcmliZWQgYnkgdGhlCiAgICAgIGFwcGxpY2F0aW9uJ3MgYHJvb3RFbGVtZW50YCBwcm9wZXJ0eS4KICAgICAgIFNlZSB0aGUgZG9jdW1lbnRhdGlvbiBmb3IgYEVtYmVyLkV2ZW50RGlzcGF0Y2hlcmAgZm9yIG1vcmUgaW5mb3JtYXRpb24uCiAgICAgICBAcHJvcGVydHkgZXZlbnREaXNwYXRjaGVyCiAgICAgIEB0eXBlIEVtYmVyLkV2ZW50RGlzcGF0Y2hlcgogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBldmVudERpc3BhdGNoZXI6IG51bGwsCgogICAgLyoqCiAgICAgIFRoZSBET00gZXZlbnRzIGZvciB3aGljaCB0aGUgZXZlbnQgZGlzcGF0Y2hlciBzaG91bGQgbGlzdGVuLgogICAgICAgQnkgZGVmYXVsdCwgdGhlIGFwcGxpY2F0aW9uJ3MgYEVtYmVyLkV2ZW50RGlzcGF0Y2hlcmAgbGlzdGVucwogICAgICBmb3IgYSBzZXQgb2Ygc3RhbmRhcmQgRE9NIGV2ZW50cywgc3VjaCBhcyBgbW91c2Vkb3duYCBhbmQKICAgICAgYGtleXVwYCwgYW5kIGRlbGVnYXRlcyB0aGVtIHRvIHlvdXIgYXBwbGljYXRpb24ncyBgRW1iZXIuVmlld2AKICAgICAgaW5zdGFuY2VzLgogICAgICAgSWYgeW91IHdvdWxkIGxpa2UgYWRkaXRpb25hbCBidWJibGluZyBldmVudHMgdG8gYmUgZGVsZWdhdGVkIHRvIHlvdXIKICAgICAgdmlld3MsIHNldCB5b3VyIGBBcHBsaWNhdGlvbmAncyBgY3VzdG9tRXZlbnRzYCBwcm9wZXJ0eQogICAgICB0byBhIGhhc2ggY29udGFpbmluZyB0aGUgRE9NIGV2ZW50IG5hbWUgYXMgdGhlIGtleSBhbmQgdGhlCiAgICAgIGNvcnJlc3BvbmRpbmcgdmlldyBtZXRob2QgbmFtZSBhcyB0aGUgdmFsdWUuIFNldHRpbmcgYW4gZXZlbnQgdG8KICAgICAgYSB2YWx1ZSBvZiBgbnVsbGAgd2lsbCBwcmV2ZW50IGEgZGVmYXVsdCBldmVudCBsaXN0ZW5lciBmcm9tIGJlaW5nCiAgICAgIGFkZGVkIGZvciB0aGF0IGV2ZW50LgogICAgICAgVG8gYWRkIG5ldyBldmVudHMgdG8gYmUgbGlzdGVuZWQgdG86CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICAgbGV0IEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSh7CiAgICAgICAgY3VzdG9tRXZlbnRzOiB7CiAgICAgICAgICAvLyBhZGQgc3VwcG9ydCBmb3IgdGhlIHBhc3RlIGV2ZW50CiAgICAgICAgICBwYXN0ZTogJ3Bhc3RlJwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVG8gcHJldmVudCBkZWZhdWx0IGV2ZW50cyBmcm9tIGJlaW5nIGxpc3RlbmVkIHRvOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAgICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoewogICAgICAgIGN1c3RvbUV2ZW50czogewogICAgICAgICAgLy8gcmVtb3ZlIHN1cHBvcnQgZm9yIG1vdXNlZW50ZXIgLyBtb3VzZWxlYXZlIGV2ZW50cwogICAgICAgICAgbW91c2VlbnRlcjogbnVsbCwKICAgICAgICAgIG1vdXNlbGVhdmU6IG51bGwKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgQHByb3BlcnR5IGN1c3RvbUV2ZW50cwogICAgICBAdHlwZSBPYmplY3QKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwogICAgY3VzdG9tRXZlbnRzOiBudWxsLAoKICAgIC8qKgogICAgICBXaGV0aGVyIHRoZSBhcHBsaWNhdGlvbiBzaG91bGQgYXV0b21hdGljYWxseSBzdGFydCByb3V0aW5nIGFuZCByZW5kZXIKICAgICAgdGVtcGxhdGVzIHRvIHRoZSBgcm9vdEVsZW1lbnRgIG9uIERPTSByZWFkeS4gV2hpbGUgZGVmYXVsdCBieSB0cnVlLAogICAgICBvdGhlciBlbnZpcm9ubWVudHMgc3VjaCBhcyBGYXN0Qm9vdCBvciBhIHRlc3RpbmcgaGFybmVzcyBjYW4gc2V0IHRoaXMKICAgICAgcHJvcGVydHkgdG8gYGZhbHNlYCBhbmQgY29udHJvbCB0aGUgcHJlY2lzZSB0aW1pbmcgYW5kIGJlaGF2aW9yIG9mIHRoZSBib290CiAgICAgIHByb2Nlc3MuCiAgICAgICBAcHJvcGVydHkgYXV0b2Jvb3QKICAgICAgQHR5cGUgQm9vbGVhbgogICAgICBAZGVmYXVsdCB0cnVlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgYXV0b2Jvb3Q6IHRydWUsCgogICAgLyoqCiAgICAgIFdoZXRoZXIgdGhlIGFwcGxpY2F0aW9uIHNob3VsZCBiZSBjb25maWd1cmVkIGZvciB0aGUgbGVnYWN5ICJnbG9iYWxzIG1vZGUiLgogICAgICBVbmRlciB0aGlzIG1vZGUsIHRoZSBBcHBsaWNhdGlvbiBvYmplY3Qgc2VydmVzIGFzIGEgZ2xvYmFsIG5hbWVzcGFjZSBmb3IgYWxsCiAgICAgIGNsYXNzZXMuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICAgbGV0IEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSh7CiAgICAgICAgLi4uCiAgICAgIH0pOwogICAgICAgQXBwLlJvdXRlci5yZW9wZW4oewogICAgICAgIGxvY2F0aW9uOiAnbm9uZScKICAgICAgfSk7CiAgICAgICBBcHAuUm91dGVyLm1hcCh7CiAgICAgICAgLi4uCiAgICAgIH0pOwogICAgICAgQXBwLk15Q29tcG9uZW50ID0gQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgLi4uCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRoaXMgZmxhZyBhbHNvIGV4cG9zZXMgb3RoZXIgaW50ZXJuYWwgQVBJcyB0aGF0IGFzc3VtZXMgdGhlIGV4aXN0ZW5jZSBvZgogICAgICBhIHNwZWNpYWwgImRlZmF1bHQgaW5zdGFuY2UiLCBsaWtlIGBBcHAuX19jb250YWluZXJfXy5sb29rdXAoLi4uKWAuCiAgICAgICBUaGlzIG9wdGlvbiBpcyBjdXJyZW50bHkgbm90IGNvbmZpZ3VyYWJsZSwgaXRzIHZhbHVlIGlzIGRlcml2ZWQgZnJvbQogICAgICB0aGUgYGF1dG9ib290YCBmbGFnIOKAkyBkaXNhYmxpbmcgYGF1dG9ib290YCBhbHNvIGltcGxpZXMgb3B0aW5nLW91dCBvZgogICAgICBnbG9iYWxzIG1vZGUgc3VwcG9ydCwgYWx0aG91Z2ggdGhleSBhcmUgdWx0aW1hdGVseSBvcnRob2dvbmFsIGNvbmNlcm5zLgogICAgICAgU29tZSBvZiB0aGUgZ2xvYmFsIG1vZGVzIGZlYXR1cmVzIGFyZSBhbHJlYWR5IGRlcHJlY2F0ZWQgaW4gMS54LiBUaGUKICAgICAgZXhpc3RlbmNlIG9mIHRoaXMgZmxhZyBpcyB0byB1bnRhbmdsZSB0aGUgZ2xvYmFscyBtb2RlIGNvZGUgcGF0aHMgZnJvbQogICAgICB0aGUgYXV0b2Jvb3QgY29kZSBwYXRocywgc28gdGhhdCB0aGVzZSBsZWdhY3kgZmVhdHVyZXMgY2FuIGJlIHJldmlld2VkCiAgICAgIGZvciBkZXByZWNhdGlvbi9yZW1vdmFsIHNlcGFyYXRlbHkuCiAgICAgICBGb3JjaW5nIHRoZSAoYXV0b2Jvb3Q9dHJ1ZSwgX2dsb2JhbHNNb2RlPWZhbHNlKSBoZXJlIGFuZCBydW5uaW5nIHRoZSB0ZXN0cwogICAgICB3b3VsZCByZXZlYWwgYWxsIHRoZSBwbGFjZXMgd2hlcmUgd2UgYXJlIHN0aWxsIHJlbHlpbmcgb24gdGhlc2UgbGVnYWN5CiAgICAgIGJlaGF2aW9yIGludGVybmFsbHkgKG1vc3RseSBqdXN0IHRlc3RzKS4KICAgICAgIEBwcm9wZXJ0eSBfZ2xvYmFsc01vZGUKICAgICAgQHR5cGUgQm9vbGVhbgogICAgICBAZGVmYXVsdCB0cnVlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX2dsb2JhbHNNb2RlOiB0cnVlLAoKICAgIC8qKgogICAgICBBbiBhcnJheSBvZiBhcHBsaWNhdGlvbiBpbnN0YW5jZXMgY3JlYXRlZCBieSBgYnVpbGRJbnN0YW5jZSgpYC4gVXNlZAogICAgICBpbnRlcm5hbGx5IHRvIGVuc3VyZSB0aGF0IGFsbCBpbnN0YW5jZXMgZ2V0IGRlc3Ryb3llZC4KICAgICAgIEBwcm9wZXJ0eSBfYXBwbGljYXRpb25JbnN0YW5jZXMKICAgICAgQHR5cGUgQXJyYXkKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9hcHBsaWNhdGlvbkluc3RhbmNlczogbnVsbCwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnMKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIGlmICghdGhpcy4kKSB7CiAgICAgICAgdGhpcy4kID0gX3ZpZXdzLmpRdWVyeTsKICAgICAgfQoKICAgICAgcmVnaXN0ZXJMaWJyYXJpZXMoKTsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICBpZiAoX2Vudmlyb25tZW50LkVOVi5MT0dfVkVSU0lPTikgewogICAgICAgICAgLy8gd2Ugb25seSBuZWVkIHRvIHNlZSB0aGlzIG9uY2UgcGVyIEFwcGxpY2F0aW9uI2luaXQKICAgICAgICAgIF9lbnZpcm9ubWVudC5FTlYuTE9HX1ZFUlNJT04gPSBmYWxzZTsKCiAgICAgICAgICBfbWV0YWwubGlicmFyaWVzLmxvZ1ZlcnNpb25zKCk7CiAgICAgICAgfQogICAgICB9IC8vIFN0YXJ0IG9mZiB0aGUgbnVtYmVyIG9mIGRlZmVycmFscyBhdCAxLiBUaGlzIHdpbGwgYmUgZGVjcmVtZW50ZWQgYnkKICAgICAgLy8gdGhlIEFwcGxpY2F0aW9uJ3Mgb3duIGBib290YCBtZXRob2QuCgoKICAgICAgdGhpcy5fcmVhZGluZXNzRGVmZXJyYWxzID0gMTsKICAgICAgdGhpcy5fYm9vdGVkID0gZmFsc2U7CiAgICAgIHRoaXMuX2FwcGxpY2F0aW9uSW5zdGFuY2VzID0gbmV3IFNldCgpOwogICAgICB0aGlzLmF1dG9ib290ID0gdGhpcy5fZ2xvYmFsc01vZGUgPSBCb29sZWFuKHRoaXMuYXV0b2Jvb3QpOwoKICAgICAgaWYgKHRoaXMuX2dsb2JhbHNNb2RlKSB7CiAgICAgICAgdGhpcy5fcHJlcGFyZUZvckdsb2JhbHNNb2RlKCk7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmF1dG9ib290KSB7CiAgICAgICAgdGhpcy53YWl0Rm9yRE9NUmVhZHkoKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgQ3JlYXRlIGFuIEFwcGxpY2F0aW9uSW5zdGFuY2UgZm9yIHRoaXMgYXBwbGljYXRpb24uCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgYnVpbGRJbnN0YW5jZQogICAgICBAcmV0dXJuIHtBcHBsaWNhdGlvbkluc3RhbmNlfSB0aGUgYXBwbGljYXRpb24gaW5zdGFuY2UKICAgICovCiAgICBidWlsZEluc3RhbmNlOiBmdW5jdGlvbiBidWlsZEluc3RhbmNlKG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgfQoKICAgICAgb3B0aW9ucy5iYXNlID0gdGhpczsKICAgICAgb3B0aW9ucy5hcHBsaWNhdGlvbiA9IHRoaXM7CiAgICAgIHJldHVybiBfaW5zdGFuY2UuZGVmYXVsdC5jcmVhdGUob3B0aW9ucyk7CiAgICB9LAoKICAgIC8qKgogICAgICBTdGFydCB0cmFja2luZyBhbiBBcHBsaWNhdGlvbkluc3RhbmNlIGZvciB0aGlzIGFwcGxpY2F0aW9uLgogICAgICBVc2VkIHdoZW4gdGhlIEFwcGxpY2F0aW9uSW5zdGFuY2UgaXMgY3JlYXRlZC4KICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX3dhdGNoSW5zdGFuY2UKICAgICovCiAgICBfd2F0Y2hJbnN0YW5jZTogZnVuY3Rpb24gX3dhdGNoSW5zdGFuY2UoaW5zdGFuY2UpIHsKICAgICAgdGhpcy5fYXBwbGljYXRpb25JbnN0YW5jZXMuYWRkKGluc3RhbmNlKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFN0b3AgdHJhY2tpbmcgYW4gQXBwbGljYXRpb25JbnN0YW5jZSBmb3IgdGhpcyBhcHBsaWNhdGlvbi4KICAgICAgVXNlZCB3aGVuIHRoZSBBcHBsaWNhdGlvbkluc3RhbmNlIGlzIGFib3V0IHRvIGJlIGRlc3Ryb3llZC4KICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX3Vud2F0Y2hJbnN0YW5jZQogICAgKi8KICAgIF91bndhdGNoSW5zdGFuY2U6IGZ1bmN0aW9uIF91bndhdGNoSW5zdGFuY2UoaW5zdGFuY2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FwcGxpY2F0aW9uSW5zdGFuY2VzLmRlbGV0ZShpbnN0YW5jZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBFbmFibGUgdGhlIGxlZ2FjeSBnbG9iYWxzIG1vZGUgYnkgYWxsb3dpbmcgdGhpcyBhcHBsaWNhdGlvbiB0byBhY3QKICAgICAgYXMgYSBnbG9iYWwgbmFtZXNwYWNlLiBTZWUgdGhlIGRvY3Mgb24gdGhlIGBfZ2xvYmFsc01vZGVgIHByb3BlcnR5CiAgICAgIGZvciBkZXRhaWxzLgogICAgICAgTW9zdCBvZiB0aGVzZSBmZWF0dXJlcyBhcmUgYWxyZWFkeSBkZXByZWNhdGVkIGluIDEueCwgc28gd2UgY2FuCiAgICAgIHN0b3AgdXNpbmcgdGhlbSBpbnRlcm5hbGx5IGFuZCB0cnkgdG8gcmVtb3ZlIHRoZW0uCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9wcmVwYXJlRm9yR2xvYmFsc01vZGUKICAgICovCiAgICBfcHJlcGFyZUZvckdsb2JhbHNNb2RlOiBmdW5jdGlvbiBfcHJlcGFyZUZvckdsb2JhbHNNb2RlKCkgewogICAgICAvLyBDcmVhdGUgc3ViY2xhc3Mgb2YgUm91dGVyIGZvciB0aGlzIEFwcGxpY2F0aW9uIGluc3RhbmNlLgogICAgICAvLyBUaGlzIGlzIHRvIGVuc3VyZSB0aGF0IHNvbWVvbmUgcmVvcGVuaW5nIGBBcHAuUm91dGVyYCBkb2VzIG5vdAogICAgICAvLyB0YW1wZXIgd2l0aCB0aGUgZGVmYXVsdCBgUm91dGVyYC4KICAgICAgdGhpcy5Sb3V0ZXIgPSAodGhpcy5Sb3V0ZXIgfHwgX3JvdXRpbmcuUm91dGVyKS5leHRlbmQoKTsKCiAgICAgIHRoaXMuX2J1aWxkRGVwcmVjYXRlZEluc3RhbmNlKCk7CiAgICB9LAoKICAgIC8qCiAgICAgIEJ1aWxkIHRoZSBkZXByZWNhdGVkIGluc3RhbmNlIGZvciBsZWdhY3kgZ2xvYmFscyBtb2RlIHN1cHBvcnQuCiAgICAgIENhbGxlZCB3aGVuIGNyZWF0aW5nIGFuZCByZXNldHRpbmcgdGhlIGFwcGxpY2F0aW9uLgogICAgICAgVGhpcyBpcyBvcnRob2dvbmFsIHRvIGF1dG9ib290OiB0aGUgZGVwcmVjYXRlZCBpbnN0YW5jZSBuZWVkcyB0bwogICAgICBiZSBjcmVhdGVkIGF0IEFwcGxpY2F0aW9uIGNvbnN0cnVjdGlvbiAobm90IGJvb3QpIHRpbWUgdG8gZXhwb3NlCiAgICAgIEFwcC5fX2NvbnRhaW5lcl9fLiBJZiBhdXRvYm9vdCBzZWVzIHRoYXQgdGhpcyBpbnN0YW5jZSBleGlzdHMsCiAgICAgIGl0IHdpbGwgY29udGludWUgYm9vdGluZyBpdCB0byBhdm9pZCBkb2luZyB1bm5jZXNzYXJ5IHdvcmsgKGFzCiAgICAgIG9wcG9zZWQgdG8gYnVpbGRpbmcgYSBuZXcgaW5zdGFuY2UgYXQgYm9vdCB0aW1lKSwgYnV0IHRoZXkgYXJlCiAgICAgIG90aGVyd2lzZSB1bnJlbGF0ZWQuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9idWlsZERlcHJlY2F0ZWRJbnN0YW5jZQogICAgKi8KICAgIF9idWlsZERlcHJlY2F0ZWRJbnN0YW5jZTogZnVuY3Rpb24gX2J1aWxkRGVwcmVjYXRlZEluc3RhbmNlKCkgewogICAgICAvLyBCdWlsZCBhIGRlZmF1bHQgaW5zdGFuY2UKICAgICAgdmFyIGluc3RhbmNlID0gdGhpcy5idWlsZEluc3RhbmNlKCk7IC8vIExlZ2FjeSBzdXBwb3J0IGZvciBBcHAuX19jb250YWluZXJfXyBhbmQgb3RoZXIgZ2xvYmFsIG1ldGhvZHMKICAgICAgLy8gb24gQXBwIHRoYXQgcmVseSBvbiBhIHNpbmdsZSwgZGVmYXVsdCBpbnN0YW5jZS4KCiAgICAgIHRoaXMuX19kZXByZWNhdGVkSW5zdGFuY2VfXyA9IGluc3RhbmNlOwogICAgICB0aGlzLl9fY29udGFpbmVyX18gPSBpbnN0YW5jZS5fX2NvbnRhaW5lcl9fOwogICAgfSwKCiAgICAvKioKICAgICAgQXV0b21hdGljYWxseSBraWNrLW9mZiB0aGUgYm9vdCBwcm9jZXNzIGZvciB0aGUgYXBwbGljYXRpb24gb25jZSB0aGUKICAgICAgRE9NIGhhcyBiZWNvbWUgcmVhZHkuCiAgICAgICBUaGUgaW5pdGlhbGl6YXRpb24gaXRzZWxmIGlzIHNjaGVkdWxlZCBvbiB0aGUgYWN0aW9ucyBxdWV1ZSB3aGljaAogICAgICBlbnN1cmVzIHRoYXQgY29kZS1sb2FkaW5nIGZpbmlzaGVzIGJlZm9yZSBib290aW5nLgogICAgICAgSWYgeW91IGFyZSBhc3luY2hyb25vdXNseSBsb2FkaW5nIGNvZGUsIHlvdSBzaG91bGQgY2FsbCBgZGVmZXJSZWFkaW5lc3MoKWAKICAgICAgdG8gZGVmZXIgYm9vdGluZywgYW5kIHRoZW4gY2FsbCBgYWR2YW5jZVJlYWRpbmVzcygpYCBvbmNlIGFsbCBvZiB5b3VyIGNvZGUKICAgICAgaGFzIGZpbmlzaGVkIGxvYWRpbmcuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHdhaXRGb3JET01SZWFkeQogICAgKi8KICAgIHdhaXRGb3JET01SZWFkeTogZnVuY3Rpb24gd2FpdEZvckRPTVJlYWR5KCkgewogICAgICBpZiAoIXRoaXMuJCB8fCB0aGlzLiQuaXNSZWFkeSkgewogICAgICAgICgwLCBfcnVubG9vcC5zY2hlZHVsZSkoJ2FjdGlvbnMnLCB0aGlzLCAnZG9tUmVhZHknKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLiQoKS5yZWFkeSgoMCwgX3J1bmxvb3AuYmluZCkodGhpcywgJ2RvbVJlYWR5JykpOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBUaGlzIGlzIHRoZSBhdXRvYm9vdCBmbG93OgogICAgICAgMS4gQm9vdCB0aGUgYXBwIGJ5IGNhbGxpbmcgYHRoaXMuYm9vdCgpYAogICAgICAyLiBDcmVhdGUgYW4gaW5zdGFuY2UgKG9yIHVzZSB0aGUgYF9fZGVwcmVjYXRlZEluc3RhbmNlX19gIGluIGdsb2JhbHMgbW9kZSkKICAgICAgMy4gQm9vdCB0aGUgaW5zdGFuY2UgYnkgY2FsbGluZyBgaW5zdGFuY2UuYm9vdCgpYAogICAgICA0LiBJbnZva2UgdGhlIGBBcHAucmVhZHkoKWAgY2FsbGJhY2sKICAgICAgNS4gS2ljay1vZmYgcm91dGluZyBvbiB0aGUgaW5zdGFuY2UKICAgICAgIElkZWFsbHksIHRoaXMgaXMgYWxsIHdlIHdvdWxkIG5lZWQgdG8gZG86CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIF9hdXRvQm9vdCgpIHsKICAgICAgICB0aGlzLmJvb3QoKS50aGVuKCgpID0+IHsKICAgICAgICAgIGxldCBpbnN0YW5jZSA9ICh0aGlzLl9nbG9iYWxzTW9kZSkgPyB0aGlzLl9fZGVwcmVjYXRlZEluc3RhbmNlX18gOiB0aGlzLmJ1aWxkSW5zdGFuY2UoKTsKICAgICAgICAgIHJldHVybiBpbnN0YW5jZS5ib290KCk7CiAgICAgICAgfSkudGhlbigoaW5zdGFuY2UpID0+IHsKICAgICAgICAgIEFwcC5yZWFkeSgpOwogICAgICAgICAgaW5zdGFuY2Uuc3RhcnRSb3V0aW5nKCk7CiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBVbmZvcnR1bmF0ZWx5LCB3ZSBjYW5ub3QgYWN0dWFsbHkgd3JpdGUgdGhpcyBiZWNhdXNlIHdlIG5lZWQgdG8gcGFydGljaXBhdGUKICAgICAgaW4gdGhlICJzeW5jaHJvbm91cyIgYm9vdCBwcm9jZXNzLiBXaGlsZSB0aGUgY29kZSBhYm92ZSB3b3VsZCB3b3JrIGZpbmUgb24KICAgICAgdGhlIGluaXRpYWwgYm9vdCAoaS5lLiBET00gcmVhZHkpLCB3aGVuIGBBcHAucmVzZXQoKWAgaXMgY2FsbGVkLCB3ZSBuZWVkIHRvCiAgICAgIGJvb3QgYSBuZXcgaW5zdGFuY2Ugc3luY2hyb25vdXNseSAoc2VlIHRoZSBkb2N1bWVudGF0aW9uIG9uIGBfYm9vdFN5bmMoKWAKICAgICAgZm9yIGRldGFpbHMpLgogICAgICAgQmVjYXVzZSBvZiB0aGlzIHJlc3RyaWN0aW9uLCB0aGUgYWN0dWFsIGxvZ2ljIG9mIHRoaXMgbWV0aG9kIGlzIGxvY2F0ZWQKICAgICAgaW5zaWRlIGBkaWRCZWNvbWVSZWFkeSgpYC4KICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZG9tUmVhZHkKICAgICovCiAgICBkb21SZWFkeTogZnVuY3Rpb24gZG9tUmVhZHkoKSB7CiAgICAgIGlmICh0aGlzLmlzRGVzdHJveWVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9ib290U3luYygpOyAvLyBDb250aW51ZXMgdG8gYGRpZEJlY29tZVJlYWR5YAoKICAgIH0sCgogICAgLyoqCiAgICAgIFVzZSB0aGlzIHRvIGRlZmVyIHJlYWRpbmVzcyB1bnRpbCBzb21lIGNvbmRpdGlvbiBpcyB0cnVlLgogICAgICAgRXhhbXBsZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgICBsZXQgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKCk7CiAgICAgICBBcHAuZGVmZXJSZWFkaW5lc3MoKTsKICAgICAgIC8vICQgaXMgYSByZWZlcmVuY2UgdG8gdGhlIGpRdWVyeSBvYmplY3QvZnVuY3Rpb24KICAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5OwogICAgICAgJC5nZXRKU09OKCcvYXV0aC10b2tlbicsIGZ1bmN0aW9uKHRva2VuKSB7CiAgICAgICAgQXBwLnRva2VuID0gdG9rZW47CiAgICAgICAgQXBwLmFkdmFuY2VSZWFkaW5lc3MoKTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVGhpcyBhbGxvd3MgeW91IHRvIHBlcmZvcm0gYXN5bmNocm9ub3VzIHNldHVwIGxvZ2ljIGFuZCBkZWZlcgogICAgICBib290aW5nIHlvdXIgYXBwbGljYXRpb24gdW50aWwgdGhlIHNldHVwIGhhcyBmaW5pc2hlZC4KICAgICAgIEhvd2V2ZXIsIGlmIHRoZSBzZXR1cCByZXF1aXJlcyBhIGxvYWRpbmcgVUksIGl0IG1pZ2h0IGJlIGJldHRlcgogICAgICB0byB1c2UgdGhlIHJvdXRlciBmb3IgdGhpcyBwdXJwb3NlLgogICAgICAgQG1ldGhvZCBkZWZlclJlYWRpbmVzcwogICAgICBAcHVibGljCiAgICAqLwogICAgZGVmZXJSZWFkaW5lc3M6IGZ1bmN0aW9uIGRlZmVyUmVhZGluZXNzKCkgewogICAgICAoZmFsc2UgJiYgISh0aGlzIGluc3RhbmNlb2YgQXBwbGljYXRpb24pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IG11c3QgY2FsbCBkZWZlclJlYWRpbmVzcyBvbiBhbiBpbnN0YW5jZSBvZiBBcHBsaWNhdGlvbicsIHRoaXMgaW5zdGFuY2VvZiBBcHBsaWNhdGlvbikpOwogICAgICAoZmFsc2UgJiYgISh0aGlzLl9yZWFkaW5lc3NEZWZlcnJhbHMgPiAwKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW5ub3QgZGVmZXIgcmVhZGluZXNzIHNpbmNlIHRoZSBgcmVhZHkoKWAgaG9vayBoYXMgYWxyZWFkeSBiZWVuIGNhbGxlZC4nLCB0aGlzLl9yZWFkaW5lc3NEZWZlcnJhbHMgPiAwKSk7CiAgICAgIHRoaXMuX3JlYWRpbmVzc0RlZmVycmFscysrOwogICAgfSwKCiAgICAvKioKICAgICAgQ2FsbCBgYWR2YW5jZVJlYWRpbmVzc2AgYWZ0ZXIgYW55IGFzeW5jaHJvbm91cyBzZXR1cCBsb2dpYyBoYXMgY29tcGxldGVkLgogICAgICBFYWNoIGNhbGwgdG8gYGRlZmVyUmVhZGluZXNzYCBtdXN0IGJlIG1hdGNoZWQgYnkgYSBjYWxsIHRvIGBhZHZhbmNlUmVhZGluZXNzYAogICAgICBvciB0aGUgYXBwbGljYXRpb24gd2lsbCBuZXZlciBiZWNvbWUgcmVhZHkgYW5kIHJvdXRpbmcgd2lsbCBub3QgYmVnaW4uCiAgICAgICBAbWV0aG9kIGFkdmFuY2VSZWFkaW5lc3MKICAgICAgQHNlZSB7QXBwbGljYXRpb24jZGVmZXJSZWFkaW5lc3N9CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBhZHZhbmNlUmVhZGluZXNzOiBmdW5jdGlvbiBhZHZhbmNlUmVhZGluZXNzKCkgewogICAgICAoZmFsc2UgJiYgISh0aGlzIGluc3RhbmNlb2YgQXBwbGljYXRpb24pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IG11c3QgY2FsbCBhZHZhbmNlUmVhZGluZXNzIG9uIGFuIGluc3RhbmNlIG9mIEFwcGxpY2F0aW9uJywgdGhpcyBpbnN0YW5jZW9mIEFwcGxpY2F0aW9uKSk7CiAgICAgIHRoaXMuX3JlYWRpbmVzc0RlZmVycmFscy0tOwoKICAgICAgaWYgKHRoaXMuX3JlYWRpbmVzc0RlZmVycmFscyA9PT0gMCkgewogICAgICAgICgwLCBfcnVubG9vcC5vbmNlKSh0aGlzLCB0aGlzLmRpZEJlY29tZVJlYWR5KTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgSW5pdGlhbGl6ZSB0aGUgYXBwbGljYXRpb24gYW5kIHJldHVybiBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBgQXBwbGljYXRpb25gCiAgICAgIG9iamVjdCB3aGVuIHRoZSBib290IHByb2Nlc3MgaXMgY29tcGxldGUuCiAgICAgICBSdW4gYW55IGFwcGxpY2F0aW9uIGluaXRpYWxpemVycyBhbmQgcnVuIHRoZSBhcHBsaWNhdGlvbiBsb2FkIGhvb2suIFRoZXNlIGhvb2tzIG1heQogICAgICBjaG9vc2UgdG8gZGVmZXIgcmVhZGluZXNzLiBGb3IgZXhhbXBsZSwgYW4gYXV0aGVudGljYXRpb24gaG9vayBtaWdodCB3YW50IHRvIGRlZmVyCiAgICAgIHJlYWRpbmVzcyB1bnRpbCB0aGUgYXV0aCB0b2tlbiBoYXMgYmVlbiByZXRyaWV2ZWQuCiAgICAgICBCeSBkZWZhdWx0LCB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgYXV0b21hdGljYWxseSBvbiAiRE9NIHJlYWR5IjsgaG93ZXZlciwgaWYgYXV0b2Jvb3QKICAgICAgaXMgZGlzYWJsZWQsIHRoaXMgaXMgYXV0b21hdGljYWxseSBjYWxsZWQgd2hlbiB0aGUgZmlyc3QgYXBwbGljYXRpb24gaW5zdGFuY2UgaXMKICAgICAgY3JlYXRlZCB2aWEgYHZpc2l0YC4KICAgICAgIEBwdWJsaWMKICAgICAgQG1ldGhvZCBib290CiAgICAgIEByZXR1cm4ge1Byb21pc2U8QXBwbGljYXRpb24sRXJyb3I+fQogICAgKi8KICAgIGJvb3Q6IGZ1bmN0aW9uIGJvb3QoKSB7CiAgICAgIGlmICh0aGlzLl9ib290UHJvbWlzZSkgewogICAgICAgIHJldHVybiB0aGlzLl9ib290UHJvbWlzZTsKICAgICAgfQoKICAgICAgdHJ5IHsKICAgICAgICB0aGlzLl9ib290U3luYygpOwogICAgICB9IGNhdGNoIChfKSB7Ly8gSWdub3JlIHRoZSBlcnJvcjogaW4gdGhlIGFzeW5jaHJvbm91cyBib290IHBhdGgsIHRoZSBlcnJvciBpcyBhbHJlYWR5IHJlZmxlY3RlZAogICAgICAgIC8vIGluIHRoZSBwcm9taXNlIHJlamVjdGlvbgogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fYm9vdFByb21pc2U7CiAgICB9LAoKICAgIC8qKgogICAgICBVbmZvcnR1bmF0ZWx5LCBhIGxvdCBvZiBleGlzdGluZyBjb2RlIGFzc3VtZXMgdGhlIGJvb3RpbmcgcHJvY2VzcyBpcwogICAgICAic3luY2hyb25vdXMiLiBTcGVjaWZpY2FsbHksIGEgbG90IG9mIHRlc3RzIGFzc3VtZXMgdGhlIGxhc3QgY2FsbCB0bwogICAgICBgYXBwLmFkdmFuY2VSZWFkaW5lc3MoKWAgb3IgYGFwcC5yZXNldCgpYCB3aWxsIHJlc3VsdCBpbiB0aGUgYXBwIGJlaW5nCiAgICAgIGZ1bGx5LWJvb3RlZCB3aGVuIHRoZSBjdXJyZW50IHJ1bmxvb3AgY29tcGxldGVzLgogICAgICAgV2Ugd291bGQgbGlrZSBuZXcgY29kZSAobGlrZSB0aGUgYHZpc2l0YCBBUEkpIHRvIHN0b3AgbWFraW5nIHRoaXMgYXNzdW1wdGlvbiwKICAgICAgc28gd2UgY3JlYXRlZCB0aGUgYXN5bmNocm9ub3VzIHZlcnNpb24gYWJvdmUgdGhhdCByZXR1cm5zIGEgcHJvbWlzZS4gQnV0IHVudGlsCiAgICAgIHdlIGhhdmUgbWlncmF0ZWQgYWxsIHRoZSBjb2RlLCB3ZSB3b3VsZCBoYXZlIHRvIGV4cG9zZSB0aGlzIG1ldGhvZCBmb3IgdXNlCiAgICAgICppbnRlcm5hbGx5KiBpbiBwbGFjZXMgd2hlcmUgd2UgbmVlZCB0byBib290IGFuIGFwcCAic3luY2hyb25vdXNseSIuCiAgICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ib290U3luYzogZnVuY3Rpb24gX2Jvb3RTeW5jKCkgewogICAgICBpZiAodGhpcy5fYm9vdGVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIEV2ZW4gdGhvdWdoIHRoaXMgcmV0dXJucyBzeW5jaHJvbm91c2x5LCB3ZSBzdGlsbCBuZWVkIHRvIG1ha2Ugc3VyZSB0aGUKICAgICAgLy8gYm9vdCBwcm9taXNlIGV4aXN0cyBmb3IgYm9vay1rZWVwaW5nIHB1cnBvc2VzOiBpZiBhbnl0aGluZyB3ZW50IHdyb25nIGluCiAgICAgIC8vIHRoZSBib290IHByb2Nlc3MsIHdlIG5lZWQgdG8gc3RvcmUgdGhlIGVycm9yIGFzIGEgcmVqZWN0aW9uIG9uIHRoZSBib290CiAgICAgIC8vIHByb21pc2Ugc28gdGhhdCBhIGZ1dHVyZSBjYWxsZXIgb2YgYGJvb3QoKWAgY2FuIHRlbGwgd2hhdCBmYWlsZWQuCgoKICAgICAgdmFyIGRlZmVyID0gdGhpcy5fYm9vdFJlc29sdmVyID0gX3J1bnRpbWUuUlNWUC5kZWZlcigpOwoKICAgICAgdGhpcy5fYm9vdFByb21pc2UgPSBkZWZlci5wcm9taXNlOwoKICAgICAgdHJ5IHsKICAgICAgICB0aGlzLnJ1bkluaXRpYWxpemVycygpOwogICAgICAgICgwLCBfbGF6eV9sb2FkLnJ1bkxvYWRIb29rcykoJ2FwcGxpY2F0aW9uJywgdGhpcyk7CiAgICAgICAgdGhpcy5hZHZhbmNlUmVhZGluZXNzKCk7IC8vIENvbnRpbnVlcyB0byBgZGlkQmVjb21lUmVhZHlgCiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgLy8gRm9yIHRoZSBhc3luY2hyb25vdXMgYm9vdCBwYXRoCiAgICAgICAgZGVmZXIucmVqZWN0KGVycm9yKTsgLy8gRm9yIHRoZSBzeW5jaHJvbm91cyBib290IHBhdGgKCiAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIFJlc2V0IHRoZSBhcHBsaWNhdGlvbi4gVGhpcyBpcyB0eXBpY2FsbHkgdXNlZCBvbmx5IGluIHRlc3RzLiBJdCBjbGVhbnMgdXAKICAgICAgdGhlIGFwcGxpY2F0aW9uIGluIHRoZSBmb2xsb3dpbmcgb3JkZXI6CiAgICAgICAxLiBEZWFjdGl2YXRlIGV4aXN0aW5nIHJvdXRlcwogICAgICAyLiBEZXN0cm95IGFsbCBvYmplY3RzIGluIHRoZSBjb250YWluZXIKICAgICAgMy4gQ3JlYXRlIGEgbmV3IGFwcGxpY2F0aW9uIGNvbnRhaW5lcgogICAgICA0LiBSZS1yb3V0ZSB0byB0aGUgZXhpc3RpbmcgdXJsCiAgICAgICBUeXBpY2FsIEV4YW1wbGU6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICBsZXQgQXBwOwogICAgICAgcnVuKGZ1bmN0aW9uKCkgewogICAgICAgIEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSgpOwogICAgICB9KTsKICAgICAgIG1vZHVsZSgnYWNjZXB0YW5jZSB0ZXN0JywgewogICAgICAgIHNldHVwOiBmdW5jdGlvbigpIHsKICAgICAgICAgIEFwcC5yZXNldCgpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICB0ZXN0KCdmaXJzdCB0ZXN0JywgZnVuY3Rpb24oKSB7CiAgICAgICAgLy8gQXBwIGlzIGZyZXNobHkgcmVzZXQKICAgICAgfSk7CiAgICAgICB0ZXN0KCdzZWNvbmQgdGVzdCcsIGZ1bmN0aW9uKCkgewogICAgICAgIC8vIEFwcCBpcyBhZ2FpbiBmcmVzaGx5IHJlc2V0CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEFkdmFuY2VkIEV4YW1wbGU6CiAgICAgICBPY2Nhc2lvbmFsbHkgeW91IG1heSB3YW50IHRvIHByZXZlbnQgdGhlIGFwcCBmcm9tIGluaXRpYWxpemluZyBkdXJpbmcKICAgICAgc2V0dXAuIFRoaXMgY291bGQgZW5hYmxlIGV4dHJhIGNvbmZpZ3VyYXRpb24sIG9yIGVuYWJsZSBhc3NlcnRpbmcgcHJpb3IKICAgICAgdG8gdGhlIGFwcCBiZWNvbWluZyByZWFkeS4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgIGxldCBBcHA7CiAgICAgICBydW4oZnVuY3Rpb24oKSB7CiAgICAgICAgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKCk7CiAgICAgIH0pOwogICAgICAgbW9kdWxlKCdhY2NlcHRhbmNlIHRlc3QnLCB7CiAgICAgICAgc2V0dXA6IGZ1bmN0aW9uKCkgewogICAgICAgICAgcnVuKGZ1bmN0aW9uKCkgewogICAgICAgICAgICBBcHAucmVzZXQoKTsKICAgICAgICAgICAgQXBwLmRlZmVyUmVhZGluZXNzKCk7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgdGVzdCgnZmlyc3QgdGVzdCcsIGZ1bmN0aW9uKCkgewogICAgICAgIG9rKHRydWUsICdzb21ldGhpbmcgYmVmb3JlIGFwcCBpcyBpbml0aWFsaXplZCcpOwogICAgICAgICBydW4oZnVuY3Rpb24oKSB7CiAgICAgICAgICBBcHAuYWR2YW5jZVJlYWRpbmVzcygpOwogICAgICAgIH0pOwogICAgICAgICBvayh0cnVlLCAnc29tZXRoaW5nIGFmdGVyIGFwcCBpcyBpbml0aWFsaXplZCcpOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHJlc2V0CiAgICAgIEBwdWJsaWMKICAgICovCiAgICByZXNldDogZnVuY3Rpb24gcmVzZXQoKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMuX2dsb2JhbHNNb2RlICYmIHRoaXMuYXV0b2Jvb3QpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2FsbGluZyByZXNldCgpIG9uIGluc3RhbmNlcyBvZiBgQXBwbGljYXRpb25gIGlzIG5vdFxuICAgICAgICAgICAgc3VwcG9ydGVkIHdoZW4gZ2xvYmFscyBtb2RlIGlzIGRpc2FibGVkOyBjYWxsIGB2aXNpdCgpYCB0b1xuICAgICAgICAgICAgY3JlYXRlIG5ldyBgQXBwbGljYXRpb25JbnN0YW5jZWBzIGFuZCBkaXNwb3NlIHRoZW1cbiAgICAgICAgICAgIHZpYSB0aGVpciBgZGVzdHJveSgpYCBtZXRob2QgaW5zdGVhZC4iLCB0aGlzLl9nbG9iYWxzTW9kZSAmJiB0aGlzLmF1dG9ib290KSk7CiAgICAgIHZhciBpbnN0YW5jZSA9IHRoaXMuX19kZXByZWNhdGVkSW5zdGFuY2VfXzsKICAgICAgdGhpcy5fcmVhZGluZXNzRGVmZXJyYWxzID0gMTsKICAgICAgdGhpcy5fYm9vdFByb21pc2UgPSBudWxsOwogICAgICB0aGlzLl9ib290UmVzb2x2ZXIgPSBudWxsOwogICAgICB0aGlzLl9ib290ZWQgPSBmYWxzZTsKCiAgICAgIGZ1bmN0aW9uIGhhbmRsZVJlc2V0KCkgewogICAgICAgICgwLCBfcnVubG9vcC5ydW4pKGluc3RhbmNlLCAnZGVzdHJveScpOwoKICAgICAgICB0aGlzLl9idWlsZERlcHJlY2F0ZWRJbnN0YW5jZSgpOwoKICAgICAgICAoMCwgX3J1bmxvb3Auc2NoZWR1bGUpKCdhY3Rpb25zJywgdGhpcywgJ19ib290U3luYycpOwogICAgICB9CgogICAgICAoMCwgX3J1bmxvb3Auam9pbikodGhpcywgaGFuZGxlUmVzZXQpOwogICAgfSwKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBkaWRCZWNvbWVSZWFkeQogICAgKi8KICAgIGRpZEJlY29tZVJlYWR5OiBmdW5jdGlvbiBkaWRCZWNvbWVSZWFkeSgpIHsKICAgICAgdHJ5IHsKICAgICAgICAvLyBUT0RPOiBJcyB0aGlzIHN0aWxsIG5lZWRlZCBmb3IgX2dsb2JhbHNNb2RlID0gZmFsc2U/CiAgICAgICAgaWYgKCEoMCwgX2RlYnVnLmlzVGVzdGluZykoKSkgewogICAgICAgICAgLy8gRWFnZXJseSBuYW1lIGFsbCBjbGFzc2VzIHRoYXQgYXJlIGFscmVhZHkgbG9hZGVkCiAgICAgICAgICAoMCwgX21ldGFsLnByb2Nlc3NBbGxOYW1lc3BhY2VzKSgpOwogICAgICAgICAgKDAsIF9tZXRhbC5zZXROYW1lc3BhY2VTZWFyY2hEaXNhYmxlZCkodHJ1ZSk7CiAgICAgICAgfSAvLyBTZWUgZG9jdW1lbnRhdGlvbiBvbiBgX2F1dG9ib290KClgIGZvciBkZXRhaWxzCgoKICAgICAgICBpZiAodGhpcy5hdXRvYm9vdCkgewogICAgICAgICAgdmFyIGluc3RhbmNlOwoKICAgICAgICAgIGlmICh0aGlzLl9nbG9iYWxzTW9kZSkgewogICAgICAgICAgICAvLyBJZiB3ZSBhbHJlYWR5IGhhdmUgdGhlIF9fZGVwcmVjYXRlZEluc3RhbmNlX18gbHlpbmcgYXJvdW5kLCBib290IGl0IHRvCiAgICAgICAgICAgIC8vIGF2b2lkIHVubmVjZXNzYXJ5IHdvcmsKICAgICAgICAgICAgaW5zdGFuY2UgPSB0aGlzLl9fZGVwcmVjYXRlZEluc3RhbmNlX187CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvLyBPdGhlcndpc2UsIGJ1aWxkIGFuIGluc3RhbmNlIGFuZCBib290IGl0LiBUaGlzIGlzIGN1cnJlbnRseSB1bnJlYWNoYWJsZSwKICAgICAgICAgICAgLy8gYmVjYXVzZSB3ZSBmb3JjZWQgX2dsb2JhbHNNb2RlIHRvID09PSBhdXRvYm9vdDsgYnV0IGhhdmluZyB0aGlzIGJyYW5jaAogICAgICAgICAgICAvLyBhbGxvd3MgdXMgdG8gbG9jYWxseSB0b2dnbGUgdGhhdCBmbGFnIGZvciB3ZWVkaW5nIG91dCBsZWdhY3kgZ2xvYmFscyBtb2RlCiAgICAgICAgICAgIC8vIGRlcGVuZGVuY2llcyBpbmRlcGVuZGVudGx5CiAgICAgICAgICAgIGluc3RhbmNlID0gdGhpcy5idWlsZEluc3RhbmNlKCk7CiAgICAgICAgICB9CgogICAgICAgICAgaW5zdGFuY2UuX2Jvb3RTeW5jKCk7IC8vIFRPRE86IEFwcC5yZWFkeSgpIGlzIG5vdCBjYWxsZWQgd2hlbiBhdXRvYm9vdCBpcyBkaXNhYmxlZCwgaXMgdGhpcyBjb3JyZWN0PwoKCiAgICAgICAgICB0aGlzLnJlYWR5KCk7CiAgICAgICAgICBpbnN0YW5jZS5zdGFydFJvdXRpbmcoKTsKICAgICAgICB9IC8vIEZvciB0aGUgYXN5bmNocm9ub3VzIGJvb3QgcGF0aAoKCiAgICAgICAgdGhpcy5fYm9vdFJlc29sdmVyLnJlc29sdmUodGhpcyk7IC8vIEZvciB0aGUgc3luY2hyb25vdXMgYm9vdCBwYXRoCgoKICAgICAgICB0aGlzLl9ib290ZWQgPSB0cnVlOwogICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgIC8vIEZvciB0aGUgYXN5bmNocm9ub3VzIGJvb3QgcGF0aAogICAgICAgIHRoaXMuX2Jvb3RSZXNvbHZlci5yZWplY3QoZXJyb3IpOyAvLyBGb3IgdGhlIHN5bmNocm9ub3VzIGJvb3QgcGF0aAoKCiAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIENhbGxlZCB3aGVuIHRoZSBBcHBsaWNhdGlvbiBoYXMgYmVjb21lIHJlYWR5LCBpbW1lZGlhdGVseSBiZWZvcmUgcm91dGluZwogICAgICBiZWdpbnMuIFRoZSBjYWxsIHdpbGwgYmUgZGVsYXllZCB1bnRpbCB0aGUgRE9NIGhhcyBiZWNvbWUgcmVhZHkuCiAgICAgICBAZXZlbnQgcmVhZHkKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHJlYWR5OiBmdW5jdGlvbiByZWFkeSgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAogICAgLy8gVGhpcyBtZXRob2QgbXVzdCBiZSBtb3ZlZCB0byB0aGUgYXBwbGljYXRpb24gaW5zdGFuY2Ugb2JqZWN0CiAgICB3aWxsRGVzdHJveTogZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAoMCwgX21ldGFsLnNldE5hbWVzcGFjZVNlYXJjaERpc2FibGVkKShmYWxzZSk7CiAgICAgIHRoaXMuX2Jvb3RlZCA9IGZhbHNlOwogICAgICB0aGlzLl9ib290UHJvbWlzZSA9IG51bGw7CiAgICAgIHRoaXMuX2Jvb3RSZXNvbHZlciA9IG51bGw7CgogICAgICBpZiAoX2xhenlfbG9hZC5fbG9hZGVkLmFwcGxpY2F0aW9uID09PSB0aGlzKSB7CiAgICAgICAgX2xhenlfbG9hZC5fbG9hZGVkLmFwcGxpY2F0aW9uID0gdW5kZWZpbmVkOwogICAgICB9CgogICAgICBpZiAodGhpcy5fYXBwbGljYXRpb25JbnN0YW5jZXMuc2l6ZSkgewogICAgICAgIHRoaXMuX2FwcGxpY2F0aW9uSW5zdGFuY2VzLmZvckVhY2goZnVuY3Rpb24gKGkpIHsKICAgICAgICAgIHJldHVybiBpLmRlc3Ryb3koKTsKICAgICAgICB9KTsKCiAgICAgICAgdGhpcy5fYXBwbGljYXRpb25JbnN0YW5jZXMuY2xlYXIoKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgQm9vdCBhIG5ldyBpbnN0YW5jZSBvZiBgQXBwbGljYXRpb25JbnN0YW5jZWAgZm9yIHRoZSBjdXJyZW50CiAgICAgIGFwcGxpY2F0aW9uIGFuZCBuYXZpZ2F0ZSBpdCB0byB0aGUgZ2l2ZW4gYHVybGAuIFJldHVybnMgYSBgUHJvbWlzZWAgdGhhdAogICAgICByZXNvbHZlcyB3aXRoIHRoZSBpbnN0YW5jZSB3aGVuIHRoZSBpbml0aWFsIHJvdXRpbmcgYW5kIHJlbmRlcmluZyBpcwogICAgICBjb21wbGV0ZSwgb3IgcmVqZWN0cyB3aXRoIGFueSBlcnJvciB0aGF0IG9jY3VycmVkIGR1cmluZyB0aGUgYm9vdCBwcm9jZXNzLgogICAgICAgV2hlbiBgYXV0b2Jvb3RgIGlzIGRpc2FibGVkLCBjYWxsaW5nIGB2aXNpdGAgd291bGQgZmlyc3QgY2F1c2UgdGhlCiAgICAgIGFwcGxpY2F0aW9uIHRvIGJvb3QsIHdoaWNoIHJ1bnMgdGhlIGFwcGxpY2F0aW9uIGluaXRpYWxpemVycy4KICAgICAgIFRoaXMgbWV0aG9kIGFsc28gdGFrZXMgYSBoYXNoIG9mIGJvb3QtdGltZSBjb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yCiAgICAgIGN1c3RvbWl6aW5nIHRoZSBpbnN0YW5jZSdzIGJlaGF2aW9yLiBTZWUgdGhlIGRvY3VtZW50YXRpb24gb24KICAgICAgYEFwcGxpY2F0aW9uSW5zdGFuY2UuQm9vdE9wdGlvbnNgIGZvciBkZXRhaWxzLgogICAgICAgYEFwcGxpY2F0aW9uSW5zdGFuY2UuQm9vdE9wdGlvbnNgIGlzIGFuIGludGVyZmFjZSBjbGFzcyB0aGF0IGV4aXN0cwogICAgICBwdXJlbHkgdG8gZG9jdW1lbnQgdGhlIGF2YWlsYWJsZSBvcHRpb25zOyB5b3UgZG8gbm90IG5lZWQgdG8gY29uc3RydWN0IGl0CiAgICAgIG1hbnVhbGx5LiBTaW1wbHkgcGFzcyBhIHJlZ3VsYXIgSmF2YVNjcmlwdCBvYmplY3QgY29udGFpbmluZyBvZiB0aGUKICAgICAgZGVzaXJlZCBvcHRpb25zOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBNeUFwcC52aXNpdCgiLyIsIHsgbG9jYXRpb246ICJub25lIiwgcm9vdEVsZW1lbnQ6ICIjY29udGFpbmVyIiB9KTsKICAgICAgYGBgCiAgICAgICAjIyMgU3VwcG9ydGVkIFNjZW5hcmlvcwogICAgICAgV2hpbGUgdGhlIGBCb290T3B0aW9uc2AgY2xhc3MgZXhwb3NlcyBhIGxhcmdlIG51bWJlciBvZiBrbm9icywgbm90IGFsbAogICAgICBjb21iaW5hdGlvbnMgb2YgdGhlbSBhcmUgdmFsaWQ7IGNlcnRhaW4gaW5jb21wYXRpYmxlIGNvbWJpbmF0aW9ucyBtaWdodAogICAgICByZXN1bHQgaW4gdW5leHBlY3RlZCBiZWhhdmlvci4KICAgICAgIEZvciBleGFtcGxlLCBib290aW5nIHRoZSBpbnN0YW5jZSBpbiB0aGUgZnVsbCBicm93c2VyIGVudmlyb25tZW50CiAgICAgIHdoaWxlIHNwZWNpZnlpbmcgYSBmb3JlaWduIGBkb2N1bWVudGAgb2JqZWN0IChlLmcuIGB7IGlzQnJvd3NlcjogdHJ1ZSwKICAgICAgZG9jdW1lbnQ6IGlmcmFtZS5jb250ZW50RG9jdW1lbnQgfWApIGRvZXMgbm90IHdvcmsgY29ycmVjdGx5IHRvZGF5LAogICAgICBsYXJnZWx5IGR1ZSB0byBFbWJlcidzIGpRdWVyeSBkZXBlbmRlbmN5LgogICAgICAgQ3VycmVudGx5LCB0aGVyZSBhcmUgdGhyZWUgb2ZmaWNpYWxseSBzdXBwb3J0ZWQgc2NlbmFyaW9zL2NvbmZpZ3VyYXRpb25zLgogICAgICBVc2FnZXMgb3V0c2lkZSBvZiB0aGVzZSBzY2VuYXJpb3MgYXJlIG5vdCBndWFyYW50ZWVkIHRvIHdvcmssIGJ1dCBwbGVhc2UKICAgICAgZmVlbCBmcmVlIHRvIGZpbGUgYnVnIHJlcG9ydHMgZG9jdW1lbnRpbmcgeW91ciBleHBlcmllbmNlIGFuZCBhbnkgaXNzdWVzCiAgICAgIHlvdSBlbmNvdW50ZXJlZCB0byBoZWxwIGV4cGFuZCBzdXBwb3J0LgogICAgICAgIyMjIyBCcm93c2VyIEFwcGxpY2F0aW9ucyAoTWFudWFsIEJvb3QpCiAgICAgICBUaGUgc2V0dXAgaXMgbGFyZ2VseSBzaW1pbGFyIHRvIGhvdyBFbWJlciB3b3JrcyBvdXQtb2YtdGhlLWJveC4gTm9ybWFsbHksCiAgICAgIEVtYmVyIHdpbGwgYm9vdCBhIGRlZmF1bHQgaW5zdGFuY2UgZm9yIHlvdXIgQXBwbGljYXRpb24gb24gIkRPTSByZWFkeSIuCiAgICAgIEhvd2V2ZXIsIHlvdSBjYW4gY3VzdG9taXplIHRoaXMgYmVoYXZpb3IgYnkgZGlzYWJsaW5nIGBhdXRvYm9vdGAuCiAgICAgICBGb3IgZXhhbXBsZSwgdGhpcyBhbGxvd3MgeW91IHRvIHJlbmRlciBhIG1pbml0dXJlIGRlbW8gb2YgeW91ciBhcHBsaWNhdGlvbgogICAgICBpbnRvIGEgc3BlY2lmaWMgYXJlYSBvbiB5b3VyIG1hcmtldGluZyB3ZWJzaXRlOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgTXlBcHAgZnJvbSAnbXktYXBwJzsKICAgICAgICQoZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IEFwcCA9IE15QXBwLmNyZWF0ZSh7IGF1dG9ib290OiBmYWxzZSB9KTsKICAgICAgICAgbGV0IG9wdGlvbnMgPSB7CiAgICAgICAgICAvLyBPdmVycmlkZSB0aGUgcm91dGVyJ3MgbG9jYXRpb24gYWRhcHRlciB0byBwcmV2ZW50IGl0IGZyb20gdXBkYXRpbmcKICAgICAgICAgIC8vIHRoZSBVUkwgaW4gdGhlIGFkZHJlc3MgYmFyCiAgICAgICAgICBsb2NhdGlvbjogJ25vbmUnLAogICAgICAgICAgIC8vIE92ZXJyaWRlIHRoZSBkZWZhdWx0IGByb290RWxlbWVudGAgb24gdGhlIGFwcCB0byByZW5kZXIgaW50byBhCiAgICAgICAgICAvLyBzcGVjaWZpYyBgZGl2YCBvbiB0aGUgcGFnZQogICAgICAgICAgcm9vdEVsZW1lbnQ6ICcjZGVtbycKICAgICAgICB9OwogICAgICAgICAvLyBTdGFydCB0aGUgYXBwIGF0IHRoZSBzcGVjaWFsIGRlbW8gVVJMCiAgICAgICAgQXBwLnZpc2l0KCcvZGVtbycsIG9wdGlvbnMpOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBPciBwZXJoYXBzIHlvdSBtaWdodCB3YW50IHRvIGJvb3QgdHdvIGluc3RhbmNlcyBvZiB5b3VyIGFwcCBvbiB0aGUgc2FtZQogICAgICBwYWdlIGZvciBhIHNwbGl0LXNjcmVlbiBtdWx0aXBsYXllciBleHBlcmllbmNlOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgTXlBcHAgZnJvbSAnbXktYXBwJzsKICAgICAgICQoZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IEFwcCA9IE15QXBwLmNyZWF0ZSh7IGF1dG9ib290OiBmYWxzZSB9KTsKICAgICAgICAgbGV0IHNlc3Npb25JZCA9IE15QXBwLmdlbmVyYXRlU2Vzc2lvbklEKCk7CiAgICAgICAgIGxldCBwbGF5ZXIxID0gQXBwLnZpc2l0KGAvbWF0Y2hlcy9qb2luP25hbWU9UGxheWVyKzEmc2Vzc2lvbj0ke3Nlc3Npb25JZH1gLCB7IHJvb3RFbGVtZW50OiAnI2xlZnQnLCBsb2NhdGlvbjogJ25vbmUnIH0pOwogICAgICAgIGxldCBwbGF5ZXIyID0gQXBwLnZpc2l0KGAvbWF0Y2hlcy9qb2luP25hbWU9UGxheWVyKzImc2Vzc2lvbj0ke3Nlc3Npb25JZH1gLCB7IHJvb3RFbGVtZW50OiAnI3JpZ2h0JywgbG9jYXRpb246ICdub25lJyB9KTsKICAgICAgICAgUHJvbWlzZS5hbGwoW3BsYXllcjEsIHBsYXllcjJdKS50aGVuKCgpID0+IHsKICAgICAgICAgIC8vIEJvdGggYXBwcyBoYXZlIGNvbXBsZXRlZCB0aGUgaW5pdGlhbCByZW5kZXIKICAgICAgICAgICQoJyNsb2FkaW5nJykuZmFkZU91dCgpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBEbyBub3RlIHRoYXQgZWFjaCBhcHAgaW5zdGFuY2UgbWFpbnRhaW5zIHRoZWlyIG93biByZWdpc3RyeS9jb250YWluZXIsIHNvCiAgICAgIHRoZXkgd2lsbCBydW4gaW4gY29tcGxldGUgaXNvbGF0aW9uIGJ5IGRlZmF1bHQuCiAgICAgICAjIyMjIFNlcnZlci1TaWRlIFJlbmRlcmluZyAoYWxzbyBrbm93biBhcyBGYXN0Qm9vdCkKICAgICAgIFRoaXMgc2V0dXAgYWxsb3dzIHlvdSB0byBydW4geW91ciBFbWJlciBhcHAgaW4gYSBzZXJ2ZXIgZW52aXJvbm1lbnQgdXNpbmcKICAgICAgTm9kZS5qcyBhbmQgcmVuZGVyIGl0cyBjb250ZW50IGludG8gc3RhdGljIEhUTUwgZm9yIFNFTyBwdXJwb3Nlcy4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgY29uc3QgSFRNTFNlcmlhbGl6ZXIgPSBuZXcgU2ltcGxlRE9NLkhUTUxTZXJpYWxpemVyKFNpbXBsZURPTS52b2lkTWFwKTsKICAgICAgIGZ1bmN0aW9uIHJlbmRlclVSTCh1cmwpIHsKICAgICAgICBsZXQgZG9tID0gbmV3IFNpbXBsZURPTS5Eb2N1bWVudCgpOwogICAgICAgIGxldCByb290RWxlbWVudCA9IGRvbS5ib2R5OwogICAgICAgIGxldCBvcHRpb25zID0geyBpc0Jyb3dzZXI6IGZhbHNlLCBkb2N1bWVudDogZG9tLCByb290RWxlbWVudDogcm9vdEVsZW1lbnQgfTsKICAgICAgICAgcmV0dXJuIE15QXBwLnZpc2l0KG9wdGlvbnMpLnRoZW4oaW5zdGFuY2UgPT4gewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcmV0dXJuIEhUTUxTZXJpYWxpemVyLnNlcmlhbGl6ZShyb290RWxlbWVudC5maXJzdENoaWxkKTsKICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIGluc3RhbmNlLmRlc3Ryb3koKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQogICAgICBgYGAKICAgICAgIEluIHRoaXMgc2NlbmFyaW8sIGJlY2F1c2UgRW1iZXIgZG9lcyBub3QgaGF2ZSBhY2Nlc3MgdG8gYSBnbG9iYWwgYGRvY3VtZW50YAogICAgICBvYmplY3QgaW4gdGhlIE5vZGUuanMgZW52aXJvbm1lbnQsIHlvdSBtdXN0IHByb3ZpZGUgb25lIGV4cGxpY2l0bHkuIEluIHByYWN0aWNlLAogICAgICBpbiB0aGUgbm9uLWJyb3dzZXIgZW52aXJvbm1lbnQsIHRoZSBzdGFuZC1pbiBgZG9jdW1lbnRgIG9iamVjdCBvbmx5IG5lZWRzIHRvCiAgICAgIGltcGxlbWVudCBhIGxpbWl0ZWQgc3Vic2V0IG9mIHRoZSBmdWxsIERPTSBBUEkuIFRoZSBgU2ltcGxlRE9NYCBsaWJyYXJ5IGlzIGtub3duCiAgICAgIHRvIHdvcmsuCiAgICAgICBTaW5jZSB0aGVyZSBpcyBubyBhY2Nlc3MgdG8galF1ZXJ5IGluIHRoZSBub24tYnJvd3NlciBlbnZpcm9ubWVudCwgeW91IG11c3QgYWxzbwogICAgICBzcGVjaWZ5IGEgRE9NIGBFbGVtZW50YCBvYmplY3QgaW4gdGhlIHNhbWUgYGRvY3VtZW50YCBmb3IgdGhlIGByb290RWxlbWVudGAgb3B0aW9uCiAgICAgIChhcyBvcHBvc2VkIHRvIGEgc2VsZWN0b3Igc3RyaW5nIGxpa2UgYCJib2R5ImApLgogICAgICAgU2VlIHRoZSBkb2N1bWVudGF0aW9uIG9uIHRoZSBgaXNCcm93c2VyYCwgYGRvY3VtZW50YCBhbmQgYHJvb3RFbGVtZW50YCBwcm9wZXJ0aWVzCiAgICAgIG9uIGBBcHBsaWNhdGlvbkluc3RhbmNlLkJvb3RPcHRpb25zYCBmb3IgZGV0YWlscy4KICAgICAgICMjIyMgU2VydmVyLVNpZGUgUmVzb3VyY2UgRGlzY292ZXJ5CiAgICAgICBUaGlzIHNldHVwIGFsbG93cyB5b3UgdG8gcnVuIHRoZSByb3V0aW5nIGxheWVyIG9mIHlvdXIgRW1iZXIgYXBwIGluIGEgc2VydmVyCiAgICAgIGVudmlyb25tZW50IHVzaW5nIE5vZGUuanMgYW5kIGNvbXBsZXRlbHkgZGlzYWJsZSByZW5kZXJpbmcuIFRoaXMgYWxsb3dzIHlvdQogICAgICB0byBzaW11bGF0ZSBhbmQgZGlzY292ZXIgdGhlIHJlc291cmNlcyAoaS5lLiBBSkFYIHJlcXVlc3RzKSBuZWVkZWQgdG8gZnVsZmlsbAogICAgICBhIGdpdmVuIHJlcXVlc3QgYW5kIGVhZ2VybHkgInB1c2giIHRoZXNlIHJlc291cmNlcyB0byB0aGUgY2xpZW50LgogICAgICAgYGBgYXBwL2luaXRpYWxpemVycy9uZXR3b3JrLXNlcnZpY2UuanMKICAgICAgaW1wb3J0IEJyb3dzZXJOZXR3b3JrU2VydmljZSBmcm9tICdhcHAvc2VydmljZXMvbmV0d29yay9icm93c2VyJzsKICAgICAgaW1wb3J0IE5vZGVOZXR3b3JrU2VydmljZSBmcm9tICdhcHAvc2VydmljZXMvbmV0d29yay9ub2RlJzsKICAgICAgIC8vIEluamVjdCBhIChoeXBvdGhldGljYWwpIHNlcnZpY2UgZm9yIGFic3RyYWN0aW5nIGFsbCBBSkFYIGNhbGxzIGFuZCB1c2UKICAgICAgLy8gdGhlIGFwcHJvcHJpYXRlIGltcGxlbWVudGF0aW9uIG9uIHRoZSBjbGllbnQvc2VydmVyLiBUaGlzIGFsc28gYWxsb3dzIHRoZQogICAgICAvLyBzZXJ2ZXIgdG8gbG9nIGFsbCB0aGUgQUpBWCBjYWxscyBtYWRlIGR1cmluZyBhIHBhcnRpY3VsYXIgcmVxdWVzdCBhbmQgdXNlCiAgICAgIC8vIHRoYXQgZm9yIHJlc291cmNlLWRpc2NvdmVyeSBwdXJwb3NlLgogICAgICAgZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemUoYXBwbGljYXRpb24pIHsKICAgICAgICBpZiAod2luZG93KSB7IC8vIGJyb3dzZXIKICAgICAgICAgIGFwcGxpY2F0aW9uLnJlZ2lzdGVyKCdzZXJ2aWNlOm5ldHdvcmsnLCBCcm93c2VyTmV0d29ya1NlcnZpY2UpOwogICAgICAgIH0gZWxzZSB7IC8vIG5vZGUKICAgICAgICAgIGFwcGxpY2F0aW9uLnJlZ2lzdGVyKCdzZXJ2aWNlOm5ldHdvcmsnLCBOb2RlTmV0d29ya1NlcnZpY2UpOwogICAgICAgIH0KICAgICAgICAgYXBwbGljYXRpb24uaW5qZWN0KCdyb3V0ZScsICduZXR3b3JrJywgJ3NlcnZpY2U6bmV0d29yaycpOwogICAgICB9OwogICAgICAgZXhwb3J0IGRlZmF1bHQgewogICAgICAgIG5hbWU6ICduZXR3b3JrLXNlcnZpY2UnLAogICAgICAgIGluaXRpYWxpemU6IGluaXRpYWxpemUKICAgICAgfTsKICAgICAgYGBgCiAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3QuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgIC8vIEFuIGV4YW1wbGUgb2YgaG93IHRoZSAoaHlwb3RoZXRpY2FsKSBzZXJ2aWNlIGlzIHVzZWQgaW4gcm91dGVzLgogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBtb2RlbChwYXJhbXMpIHsKICAgICAgICAgIHJldHVybiB0aGlzLm5ldHdvcmsuZmV0Y2goYC9hcGkvcG9zdHMvJHtwYXJhbXMucG9zdF9pZH0uanNvbmApOwogICAgICAgIH0sCiAgICAgICAgIGFmdGVyTW9kZWwocG9zdCkgewogICAgICAgICAgaWYgKHBvc3QuaXNFeHRlcm5hbENvbnRlbnQpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMubmV0d29yay5mZXRjaChgL2FwaS9leHRlcm5hbC8/dXJsPSR7cG9zdC5leHRlcm5hbFVSTH1gKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBwb3N0OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgamF2YXNjcmlwdAogICAgICAvLyBGaW5hbGx5LCBwdXQgYWxsIHRoZSBwaWVjZXMgdG9nZXRoZXIKICAgICAgIGZ1bmN0aW9uIGRpc2NvdmVyUmVzb3VyY2VzRm9yKHVybCkgewogICAgICAgIHJldHVybiBNeUFwcC52aXNpdCh1cmwsIHsgaXNCcm93c2VyOiBmYWxzZSwgc2hvdWxkUmVuZGVyOiBmYWxzZSB9KS50aGVuKGluc3RhbmNlID0+IHsKICAgICAgICAgIGxldCBuZXR3b3JrU2VydmljZSA9IGluc3RhbmNlLmxvb2t1cCgnc2VydmljZTpuZXR3b3JrJyk7CiAgICAgICAgICByZXR1cm4gbmV0d29ya1NlcnZpY2UucmVxdWVzdHM7IC8vID0+IHsgIi9hcGkvcG9zdHMvMTIzLmpzb24iOiAiLi4uIiB9CiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgdmlzaXQKICAgICAgQHBhcmFtIHVybCB7U3RyaW5nfSBUaGUgaW5pdGlhbCBVUkwgdG8gbmF2aWdhdGUgdG8KICAgICAgQHBhcmFtIG9wdGlvbnMge0FwcGxpY2F0aW9uSW5zdGFuY2UuQm9vdE9wdGlvbnN9CiAgICAgIEByZXR1cm4ge1Byb21pc2U8QXBwbGljYXRpb25JbnN0YW5jZSwgRXJyb3I+fQogICAgKi8KICAgIHZpc2l0OiBmdW5jdGlvbiB2aXNpdCh1cmwsIG9wdGlvbnMpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHJldHVybiB0aGlzLmJvb3QoKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgaW5zdGFuY2UgPSBfdGhpcy5idWlsZEluc3RhbmNlKCk7CgogICAgICAgIHJldHVybiBpbnN0YW5jZS5ib290KG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuIGluc3RhbmNlLnZpc2l0KHVybCk7CiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7CiAgICAgICAgICAoMCwgX3J1bmxvb3AucnVuKShpbnN0YW5jZSwgJ2Rlc3Ryb3knKTsKICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0KICB9KTsKCiAgQXBwbGljYXRpb24ucmVvcGVuQ2xhc3MoewogICAgLyoqCiAgICAgIFRoaXMgY3JlYXRlcyBhIHJlZ2lzdHJ5IHdpdGggdGhlIGRlZmF1bHQgRW1iZXIgbmFtaW5nIGNvbnZlbnRpb25zLgogICAgICAgSXQgYWxzbyBjb25maWd1cmVzIHRoZSByZWdpc3RyeToKICAgICAgICogcmVnaXN0ZXJlZCB2aWV3cyBhcmUgY3JlYXRlZCBldmVyeSB0aW1lIHRoZXkgYXJlIGxvb2tlZCB1cCAodGhleSBhcmUKICAgICAgICBub3Qgc2luZ2xldG9ucykKICAgICAgKiByZWdpc3RlcmVkIHRlbXBsYXRlcyBhcmUgbm90IGZhY3RvcmllczsgdGhlIHJlZ2lzdGVyZWQgdmFsdWUgaXMKICAgICAgICByZXR1cm5lZCBkaXJlY3RseS4KICAgICAgKiB0aGUgcm91dGVyIHJlY2VpdmVzIHRoZSBhcHBsaWNhdGlvbiBhcyBpdHMgYG5hbWVzcGFjZWAgcHJvcGVydHkKICAgICAgKiBhbGwgY29udHJvbGxlcnMgcmVjZWl2ZSB0aGUgcm91dGVyIGFzIHRoZWlyIGB0YXJnZXRgIGFuZCBgY29udHJvbGxlcnNgCiAgICAgICAgcHJvcGVydGllcwogICAgICAqIGFsbCBjb250cm9sbGVycyByZWNlaXZlIHRoZSBhcHBsaWNhdGlvbiBhcyB0aGVpciBgbmFtZXNwYWNlYCBwcm9wZXJ0eQogICAgICAqIHRoZSBhcHBsaWNhdGlvbiB2aWV3IHJlY2VpdmVzIHRoZSBhcHBsaWNhdGlvbiBjb250cm9sbGVyIGFzIGl0cwogICAgICAgIGBjb250cm9sbGVyYCBwcm9wZXJ0eQogICAgICAqIHRoZSBhcHBsaWNhdGlvbiB2aWV3IHJlY2VpdmVzIHRoZSBhcHBsaWNhdGlvbiB0ZW1wbGF0ZSBhcyBpdHMKICAgICAgICBgZGVmYXVsdFRlbXBsYXRlYCBwcm9wZXJ0eQogICAgICAgQG1ldGhvZCBidWlsZFJlZ2lzdHJ5CiAgICAgIEBzdGF0aWMKICAgICAgQHBhcmFtIHtBcHBsaWNhdGlvbn0gbmFtZXNwYWNlIHRoZSBhcHBsaWNhdGlvbiBmb3Igd2hpY2ggdG8KICAgICAgICBidWlsZCB0aGUgcmVnaXN0cnkKICAgICAgQHJldHVybiB7RW1iZXIuUmVnaXN0cnl9IHRoZSBidWlsdCByZWdpc3RyeQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGJ1aWxkUmVnaXN0cnk6IGZ1bmN0aW9uIGJ1aWxkUmVnaXN0cnkoKSB7CiAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnMKICAgICAgdmFyIHJlZ2lzdHJ5ID0gdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIGNvbW1vblNldHVwUmVnaXN0cnkocmVnaXN0cnkpOwogICAgICAoMCwgX2dsaW1tZXIuc2V0dXBBcHBsaWNhdGlvblJlZ2lzdHJ5KShyZWdpc3RyeSk7CiAgICAgIHJldHVybiByZWdpc3RyeTsKICAgIH0KICB9KTsKCiAgZnVuY3Rpb24gY29tbW9uU2V0dXBSZWdpc3RyeShyZWdpc3RyeSkgewogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ3JvdXRlcjptYWluJywgX3JvdXRpbmcuUm91dGVyLmV4dGVuZCgpKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCctdmlldy1yZWdpc3RyeTptYWluJywgewogICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgICByZXR1cm4gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgICAgfQogICAgfSk7CiAgICByZWdpc3RyeS5yZWdpc3Rlcigncm91dGU6YmFzaWMnLCBfcm91dGluZy5Sb3V0ZSk7CiAgICByZWdpc3RyeS5yZWdpc3RlcignZXZlbnRfZGlzcGF0Y2hlcjptYWluJywgX3ZpZXdzLkV2ZW50RGlzcGF0Y2hlcik7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3JvdXRlcjptYWluJywgJ25hbWVzcGFjZScsICdhcHBsaWNhdGlvbjptYWluJyk7CiAgICByZWdpc3RyeS5yZWdpc3RlcignbG9jYXRpb246YXV0bycsIF9yb3V0aW5nLkF1dG9Mb2NhdGlvbik7CiAgICByZWdpc3RyeS5yZWdpc3RlcignbG9jYXRpb246aGFzaCcsIF9yb3V0aW5nLkhhc2hMb2NhdGlvbik7CiAgICByZWdpc3RyeS5yZWdpc3RlcignbG9jYXRpb246aGlzdG9yeScsIF9yb3V0aW5nLkhpc3RvcnlMb2NhdGlvbik7CiAgICByZWdpc3RyeS5yZWdpc3RlcignbG9jYXRpb246bm9uZScsIF9yb3V0aW5nLk5vbmVMb2NhdGlvbik7CiAgICByZWdpc3RyeS5yZWdpc3RlcigoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdCgpKSwgewogICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgICByZXR1cm4gbmV3IF9yb3V0aW5nLkJ1Y2tldENhY2hlKCk7CiAgICAgIH0KICAgIH0pOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ3NlcnZpY2U6cm91dGVyJywgX3JvdXRpbmcuUm91dGVyU2VydmljZSk7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3NlcnZpY2U6cm91dGVyJywgJ19yb3V0ZXInLCAncm91dGVyOm1haW4nKTsKICB9CgogIGZ1bmN0aW9uIHJlZ2lzdGVyTGlicmFyaWVzKCkgewogICAgaWYgKCFsaWJyYXJpZXNSZWdpc3RlcmVkKSB7CiAgICAgIGxpYnJhcmllc1JlZ2lzdGVyZWQgPSB0cnVlOwoKICAgICAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuSlFVRVJZX0lOVEVHUkFUSU9OICYmIF9icm93c2VyRW52aXJvbm1lbnQuaGFzRE9NICYmICFfdmlld3MualF1ZXJ5RGlzYWJsZWQpIHsKICAgICAgICBfbWV0YWwubGlicmFyaWVzLnJlZ2lzdGVyQ29yZUxpYnJhcnkoJ2pRdWVyeScsICgwLCBfdmlld3MualF1ZXJ5KSgpLmpxdWVyeSk7CiAgICAgIH0KICAgIH0KICB9CgogIHZhciBfZGVmYXVsdCA9IEFwcGxpY2F0aW9uOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2FwcGxpY2F0aW9uL2xpYi9sYXp5X2xvYWQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZW52aXJvbm1lbnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvYnJvd3Nlci1lbnZpcm9ubWVudCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbnZpcm9ubWVudCwgX2Jyb3dzZXJFbnZpcm9ubWVudCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMub25Mb2FkID0gb25Mb2FkOwogIF9leHBvcnRzLnJ1bkxvYWRIb29rcyA9IHJ1bkxvYWRIb29rczsKICBfZXhwb3J0cy5fbG9hZGVkID0gdm9pZCAwOwoKICAvKmdsb2JhbHMgQ3VzdG9tRXZlbnQgKi8KCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci9hcHBsaWNhdGlvbgogICovCiAgdmFyIGxvYWRIb29rcyA9IF9lbnZpcm9ubWVudC5FTlYuRU1CRVJfTE9BRF9IT09LUyB8fCB7fTsKICB2YXIgbG9hZGVkID0ge307CiAgdmFyIF9sb2FkZWQgPSBsb2FkZWQ7CiAgLyoqCiAgICBEZXRlY3RzIHdoZW4gYSBzcGVjaWZpYyBwYWNrYWdlIG9mIEVtYmVyIChlLmcuICdBcHBsaWNhdGlvbicpCiAgICBoYXMgZnVsbHkgbG9hZGVkIGFuZCBpcyBhdmFpbGFibGUgZm9yIGV4dGVuc2lvbi4KICAKICAgIFRoZSBwcm92aWRlZCBgY2FsbGJhY2tgIHdpbGwgYmUgY2FsbGVkIHdpdGggdGhlIGBuYW1lYCBwYXNzZWQKICAgIHJlc29sdmVkIGZyb20gYSBzdHJpbmcgaW50byB0aGUgb2JqZWN0OgogIAogICAgYGBgIGphdmFzY3JpcHQKICAgIGltcG9ydCB7IG9uTG9hZCB9IGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgCiAgICBvbkxvYWQoJ0VtYmVyLkFwcGxpY2F0aW9uJyBmdW5jdGlvbihoYmFycykgewogICAgICBoYmFycy5yZWdpc3RlckhlbHBlciguLi4pOwogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2Qgb25Mb2FkCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9hcHBsaWNhdGlvbgogICAgQHBhcmFtIG5hbWUge1N0cmluZ30gbmFtZSBvZiBob29rCiAgICBAcGFyYW0gY2FsbGJhY2sge0Z1bmN0aW9ufSBjYWxsYmFjayB0byBiZSBjYWxsZWQKICAgIEBwcml2YXRlCiAgKi8KCiAgX2V4cG9ydHMuX2xvYWRlZCA9IF9sb2FkZWQ7CgogIGZ1bmN0aW9uIG9uTG9hZChuYW1lLCBjYWxsYmFjaykgewogICAgdmFyIG9iamVjdCA9IGxvYWRlZFtuYW1lXTsKICAgIGxvYWRIb29rc1tuYW1lXSA9IGxvYWRIb29rc1tuYW1lXSB8fCBbXTsKICAgIGxvYWRIb29rc1tuYW1lXS5wdXNoKGNhbGxiYWNrKTsKCiAgICBpZiAob2JqZWN0KSB7CiAgICAgIGNhbGxiYWNrKG9iamVjdCk7CiAgICB9CiAgfQogIC8qKgogICAgQ2FsbGVkIHdoZW4gYW4gRW1iZXIuanMgcGFja2FnZSAoZS5nIEFwcGxpY2F0aW9uKSBoYXMgZmluaXNoZWQKICAgIGxvYWRpbmcuIFRyaWdnZXJzIGFueSBjYWxsYmFja3MgcmVnaXN0ZXJlZCBmb3IgdGhpcyBldmVudC4KICAKICAgIEBtZXRob2QgcnVuTG9hZEhvb2tzCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9hcHBsaWNhdGlvbgogICAgQHBhcmFtIG5hbWUge1N0cmluZ30gbmFtZSBvZiBob29rCiAgICBAcGFyYW0gb2JqZWN0IHtPYmplY3R9IG9iamVjdCB0byBwYXNzIHRvIGNhbGxiYWNrcwogICAgQHByaXZhdGUKICAqLwoKCiAgZnVuY3Rpb24gcnVuTG9hZEhvb2tzKG5hbWUsIG9iamVjdCkgewogICAgbG9hZGVkW25hbWVdID0gb2JqZWN0OwoKICAgIGlmIChfYnJvd3NlckVudmlyb25tZW50LndpbmRvdyAmJiB0eXBlb2YgQ3VzdG9tRXZlbnQgPT09ICdmdW5jdGlvbicpIHsKICAgICAgdmFyIGV2ZW50ID0gbmV3IEN1c3RvbUV2ZW50KG5hbWUsIHsKICAgICAgICBkZXRhaWw6IG9iamVjdCwKICAgICAgICBuYW1lOiBuYW1lCiAgICAgIH0pOwoKICAgICAgX2Jyb3dzZXJFbnZpcm9ubWVudC53aW5kb3cuZGlzcGF0Y2hFdmVudChldmVudCk7CiAgICB9CgogICAgaWYgKGxvYWRIb29rc1tuYW1lXSkgewogICAgICBsb2FkSG9va3NbbmFtZV0uZm9yRWFjaChmdW5jdGlvbiAoY2FsbGJhY2spIHsKICAgICAgICByZXR1cm4gY2FsbGJhY2sob2JqZWN0KTsKICAgICAgfSk7CiAgICB9CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvYXBwbGljYXRpb24vbGliL3ZhbGlkYXRlLXR5cGUiLCBbImV4cG9ydHMiLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlYnVnKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdmFsaWRhdGVUeXBlOwogIHZhciBWQUxJREFURURfVFlQRVMgPSB7CiAgICByb3V0ZTogWydhc3NlcnQnLCAnaXNSb3V0ZUZhY3RvcnknLCAnRW1iZXIuUm91dGUnXSwKICAgIGNvbXBvbmVudDogWydkZXByZWNhdGUnLCAnaXNDb21wb25lbnRGYWN0b3J5JywgJ0VtYmVyLkNvbXBvbmVudCddLAogICAgdmlldzogWydkZXByZWNhdGUnLCAnaXNWaWV3RmFjdG9yeScsICdFbWJlci5WaWV3J10sCiAgICBzZXJ2aWNlOiBbJ2RlcHJlY2F0ZScsICdpc1NlcnZpY2VGYWN0b3J5JywgJ0VtYmVyLlNlcnZpY2UnXQogIH07CgogIGZ1bmN0aW9uIHZhbGlkYXRlVHlwZShyZXNvbHZlZFR5cGUsIHBhcnNlZE5hbWUpIHsKICAgIHZhciB2YWxpZGF0aW9uQXR0cmlidXRlcyA9IFZBTElEQVRFRF9UWVBFU1twYXJzZWROYW1lLnR5cGVdOwoKICAgIGlmICghdmFsaWRhdGlvbkF0dHJpYnV0ZXMpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBmYWN0b3J5RmxhZyA9IHZhbGlkYXRpb25BdHRyaWJ1dGVzWzFdLAogICAgICAgIGV4cGVjdGVkVHlwZSA9IHZhbGlkYXRpb25BdHRyaWJ1dGVzWzJdOwogICAgKGZhbHNlICYmICEoQm9vbGVhbihyZXNvbHZlZFR5cGVbZmFjdG9yeUZsYWddKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJFeHBlY3RlZCAiICsgcGFyc2VkTmFtZS5mdWxsTmFtZSArICIgdG8gcmVzb2x2ZSB0byBhbiAiICsgZXhwZWN0ZWRUeXBlICsgIiBidXQgIiArICgiaW5zdGVhZCBpdCB3YXMgIiArIHJlc29sdmVkVHlwZSArICIuIiksIEJvb2xlYW4ocmVzb2x2ZWRUeXBlW2ZhY3RvcnlGbGFnXSkpKTsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci9jYW5hcnktZmVhdHVyZXMvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZW52aXJvbm1lbnQiLCAiQGVtYmVyL3BvbHlmaWxscyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbnZpcm9ubWVudCwgX3BvbHlmaWxscykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuaXNFbmFibGVkID0gaXNFbmFibGVkOwogIF9leHBvcnRzLkVNQkVSX0dMSU1NRVJfU0VUX0NPTVBPTkVOVF9URU1QTEFURSA9IF9leHBvcnRzLkVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQgPSBfZXhwb3J0cy5FTUJFUl9DVVNUT01fQ09NUE9ORU5UX0FSR19QUk9YWSA9IF9leHBvcnRzLkVNQkVSX0dMSU1NRVJfRk5fSEVMUEVSID0gX2V4cG9ydHMuRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUID0gX2V4cG9ydHMuRU1CRVJfR0xJTU1FUl9BTkdMRV9CUkFDS0VUX0JVSUxUX0lOUyA9IF9leHBvcnRzLkVNQkVSX0dMSU1NRVJfRk9SV0FSRF9NT0RJRklFUlNfV0lUSF9TUExBVFRSSUJVVEVTID0gX2V4cG9ydHMuRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTID0gX2V4cG9ydHMuRU1CRVJfTU9EVUxFX1VOSUZJQ0FUSU9OID0gX2V4cG9ydHMuRU1CRVJfSU1QUk9WRURfSU5TVFJVTUVOVEFUSU9OID0gX2V4cG9ydHMuRU1CRVJfTElCUkFSSUVTX0lTUkVHSVNURVJFRCA9IF9leHBvcnRzLkZFQVRVUkVTID0gX2V4cG9ydHMuREVGQVVMVF9GRUFUVVJFUyA9IHZvaWQgMDsKCiAgLyoqCiAgICBTZXQgYEVtYmVyRU5WLkZFQVRVUkVTYCBpbiB5b3VyIGFwcGxpY2F0aW9uJ3MgYGNvbmZpZy9lbnZpcm9ubWVudC5qc2AgZmlsZQogICAgdG8gZW5hYmxlIGNhbmFyeSBmZWF0dXJlcyBpbiB5b3VyIGFwcGxpY2F0aW9uLgogIAogICAgU2VlIHRoZSBbZmVhdHVyZSBmbGFnIGd1aWRlXShodHRwczovL2d1aWRlcy5lbWJlcmpzLmNvbS9yZWxlYXNlL2NvbmZpZ3VyaW5nLWVtYmVyL2ZlYXR1cmUtZmxhZ3MvKQogICAgZm9yIG1vcmUgZGV0YWlscy4KICAKICAgIEBtb2R1bGUgQGVtYmVyL2NhbmFyeS1mZWF0dXJlcwogICAgQHB1YmxpYwogICovCiAgdmFyIERFRkFVTFRfRkVBVFVSRVMgPSB7CiAgICBFTUJFUl9MSUJSQVJJRVNfSVNSRUdJU1RFUkVEOiBmYWxzZSwKICAgIEVNQkVSX0lNUFJPVkVEX0lOU1RSVU1FTlRBVElPTjogZmFsc2UsCiAgICBFTUJFUl9NT0RVTEVfVU5JRklDQVRJT046IGZhbHNlLAogICAgRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTOiB0cnVlLAogICAgRU1CRVJfR0xJTU1FUl9GT1JXQVJEX01PRElGSUVSU19XSVRIX1NQTEFUVFJJQlVURVM6IHRydWUsCiAgICBFTUJFUl9HTElNTUVSX0FOR0xFX0JSQUNLRVRfQlVJTFRfSU5TOiB0cnVlLAogICAgRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUOiB0cnVlLAogICAgRU1CRVJfR0xJTU1FUl9GTl9IRUxQRVI6IHRydWUsCiAgICBFTUJFUl9DVVNUT01fQ09NUE9ORU5UX0FSR19QUk9YWTogdHJ1ZSwKICAgIEVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQ6IHRydWUsCiAgICBFTUJFUl9HTElNTUVSX1NFVF9DT01QT05FTlRfVEVNUExBVEU6IHRydWUKICB9OwogIC8qKgogICAgVGhlIGhhc2ggb2YgZW5hYmxlZCBDYW5hcnkgZmVhdHVyZXMuIEFkZCB0byB0aGlzLCBhbnkgY2FuYXJ5IGZlYXR1cmVzCiAgICBiZWZvcmUgY3JlYXRpbmcgeW91ciBhcHBsaWNhdGlvbi4KICAKICAgIEBjbGFzcyBGRUFUVVJFUwogICAgQHN0YXRpYwogICAgQHNpbmNlIDEuMS4wCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMuREVGQVVMVF9GRUFUVVJFUyA9IERFRkFVTFRfRkVBVFVSRVM7CiAgdmFyIEZFQVRVUkVTID0gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKShERUZBVUxUX0ZFQVRVUkVTLCBfZW52aXJvbm1lbnQuRU5WLkZFQVRVUkVTKTsKICAvKioKICAgIERldGVybWluZSB3aGV0aGVyIHRoZSBzcGVjaWZpZWQgYGZlYXR1cmVgIGlzIGVuYWJsZWQuIFVzZWQgYnkgRW1iZXIncwogICAgYnVpbGQgdG9vbHMgdG8gZXhjbHVkZSBleHBlcmltZW50YWwgZmVhdHVyZXMgZnJvbSBiZXRhL3N0YWJsZSBidWlsZHMuCiAgCiAgICBZb3UgY2FuIGRlZmluZSB0aGUgZm9sbG93aW5nIGNvbmZpZ3VyYXRpb24gb3B0aW9uczoKICAKICAgICogYEVtYmVyRU5WLkVOQUJMRV9PUFRJT05BTF9GRUFUVVJFU2AgLSBlbmFibGUgYW55IGZlYXR1cmVzIHRoYXQgaGF2ZSBub3QgYmVlbiBleHBsaWNpdGx5CiAgICAgIGVuYWJsZWQvZGlzYWJsZWQuCiAgCiAgICBAbWV0aG9kIGlzRW5hYmxlZAogICAgQHBhcmFtIHtTdHJpbmd9IGZlYXR1cmUgVGhlIGZlYXR1cmUgdG8gY2hlY2sKICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICBAc2luY2UgMS4xLjAKICAgIEBwdWJsaWMKICAqLwoKICBfZXhwb3J0cy5GRUFUVVJFUyA9IEZFQVRVUkVTOwoKICBmdW5jdGlvbiBpc0VuYWJsZWQoZmVhdHVyZSkgewogICAgdmFyIGZlYXR1cmVWYWx1ZSA9IEZFQVRVUkVTW2ZlYXR1cmVdOwoKICAgIGlmIChmZWF0dXJlVmFsdWUgPT09IHRydWUgfHwgZmVhdHVyZVZhbHVlID09PSBmYWxzZSkgewogICAgICByZXR1cm4gZmVhdHVyZVZhbHVlOwogICAgfSBlbHNlIGlmIChfZW52aXJvbm1lbnQuRU5WLkVOQUJMRV9PUFRJT05BTF9GRUFUVVJFUykgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGZlYXR1cmVWYWx1ZSh2YWx1ZSkgewogICAgaWYgKF9lbnZpcm9ubWVudC5FTlYuRU5BQkxFX09QVElPTkFMX0ZFQVRVUkVTICYmIHZhbHVlID09PSBudWxsKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIHJldHVybiB2YWx1ZTsKICB9CgogIHZhciBFTUJFUl9MSUJSQVJJRVNfSVNSRUdJU1RFUkVEID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLkVNQkVSX0xJQlJBUklFU19JU1JFR0lTVEVSRUQpOwogIF9leHBvcnRzLkVNQkVSX0xJQlJBUklFU19JU1JFR0lTVEVSRUQgPSBFTUJFUl9MSUJSQVJJRVNfSVNSRUdJU1RFUkVEOwogIHZhciBFTUJFUl9JTVBST1ZFRF9JTlNUUlVNRU5UQVRJT04gPSBmZWF0dXJlVmFsdWUoRkVBVFVSRVMuRU1CRVJfSU1QUk9WRURfSU5TVFJVTUVOVEFUSU9OKTsKICBfZXhwb3J0cy5FTUJFUl9JTVBST1ZFRF9JTlNUUlVNRU5UQVRJT04gPSBFTUJFUl9JTVBST1ZFRF9JTlNUUlVNRU5UQVRJT047CiAgdmFyIEVNQkVSX01PRFVMRV9VTklGSUNBVElPTiA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5FTUJFUl9NT0RVTEVfVU5JRklDQVRJT04pOwogIF9leHBvcnRzLkVNQkVSX01PRFVMRV9VTklGSUNBVElPTiA9IEVNQkVSX01PRFVMRV9VTklGSUNBVElPTjsKICB2YXIgRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLkVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyk7CiAgX2V4cG9ydHMuRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTID0gRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTOwogIHZhciBFTUJFUl9HTElNTUVSX0ZPUldBUkRfTU9ESUZJRVJTX1dJVEhfU1BMQVRUUklCVVRFUyA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5FTUJFUl9HTElNTUVSX0ZPUldBUkRfTU9ESUZJRVJTX1dJVEhfU1BMQVRUUklCVVRFUyk7CiAgX2V4cG9ydHMuRU1CRVJfR0xJTU1FUl9GT1JXQVJEX01PRElGSUVSU19XSVRIX1NQTEFUVFJJQlVURVMgPSBFTUJFUl9HTElNTUVSX0ZPUldBUkRfTU9ESUZJRVJTX1dJVEhfU1BMQVRUUklCVVRFUzsKICB2YXIgRU1CRVJfR0xJTU1FUl9BTkdMRV9CUkFDS0VUX0JVSUxUX0lOUyA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5FTUJFUl9HTElNTUVSX0FOR0xFX0JSQUNLRVRfQlVJTFRfSU5TKTsKICBfZXhwb3J0cy5FTUJFUl9HTElNTUVSX0FOR0xFX0JSQUNLRVRfQlVJTFRfSU5TID0gRU1CRVJfR0xJTU1FUl9BTkdMRV9CUkFDS0VUX0JVSUxUX0lOUzsKICB2YXIgRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLkVNQkVSX05BVElWRV9ERUNPUkFUT1JfU1VQUE9SVCk7CiAgX2V4cG9ydHMuRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUID0gRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUOwogIHZhciBFTUJFUl9HTElNTUVSX0ZOX0hFTFBFUiA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5FTUJFUl9HTElNTUVSX0ZOX0hFTFBFUik7CiAgX2V4cG9ydHMuRU1CRVJfR0xJTU1FUl9GTl9IRUxQRVIgPSBFTUJFUl9HTElNTUVSX0ZOX0hFTFBFUjsKICB2YXIgRU1CRVJfQ1VTVE9NX0NPTVBPTkVOVF9BUkdfUFJPWFkgPSBmZWF0dXJlVmFsdWUoRkVBVFVSRVMuRU1CRVJfQ1VTVE9NX0NPTVBPTkVOVF9BUkdfUFJPWFkpOwogIF9leHBvcnRzLkVNQkVSX0NVU1RPTV9DT01QT05FTlRfQVJHX1BST1hZID0gRU1CRVJfQ1VTVE9NX0NPTVBPTkVOVF9BUkdfUFJPWFk7CiAgdmFyIEVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQgPSBmZWF0dXJlVmFsdWUoRkVBVFVSRVMuRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCk7CiAgX2V4cG9ydHMuRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCA9IEVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQ7CiAgdmFyIEVNQkVSX0dMSU1NRVJfU0VUX0NPTVBPTkVOVF9URU1QTEFURSA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5FTUJFUl9HTElNTUVSX1NFVF9DT01QT05FTlRfVEVNUExBVEUpOwogIF9leHBvcnRzLkVNQkVSX0dMSU1NRVJfU0VUX0NPTVBPTkVOVF9URU1QTEFURSA9IEVNQkVSX0dMSU1NRVJfU0VUX0NPTVBPTkVOVF9URU1QTEFURTsKfSk7CmRlZmluZSgiQGVtYmVyL2NvbXBvbmVudC9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9nbGltbWVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2dsaW1tZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkNvbXBvbmVudCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9nbGltbWVyLkNvbXBvbmVudDsKICAgIH0KICB9KTsKfSk7CmRlZmluZSgiQGVtYmVyL2NvbXBvbmVudC90ZW1wbGF0ZS1vbmx5IiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHRlbXBsYXRlT25seUNvbXBvbmVudDsKICBfZXhwb3J0cy5pc1RlbXBsYXRlT25seUNvbXBvbmVudCA9IGlzVGVtcGxhdGVPbmx5Q29tcG9uZW50OwogIF9leHBvcnRzLlRlbXBsYXRlT25seUNvbXBvbmVudCA9IHZvaWQgMDsKCiAgLy8gVGhpcyBpcyBvbmx5IGV4cG9ydGVkIGZvciB0eXBlcywgZG9uJ3QgdXNlIHRoaXMgY2xhc3MgZGlyZWN0bHkKICB2YXIgVGVtcGxhdGVPbmx5Q29tcG9uZW50ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gVGVtcGxhdGVPbmx5Q29tcG9uZW50KG1vZHVsZU5hbWUpIHsKICAgICAgaWYgKG1vZHVsZU5hbWUgPT09IHZvaWQgMCkgewogICAgICAgIG1vZHVsZU5hbWUgPSAnQGVtYmVyL2NvbXBvbmVudC90ZW1wbGF0ZS1vbmx5JzsKICAgICAgfQoKICAgICAgdGhpcy5tb2R1bGVOYW1lID0gbW9kdWxlTmFtZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gVGVtcGxhdGVPbmx5Q29tcG9uZW50LnByb3RvdHlwZTsKCiAgICBfcHJvdG8udG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMubW9kdWxlTmFtZTsKICAgIH07CgogICAgcmV0dXJuIFRlbXBsYXRlT25seUNvbXBvbmVudDsKICB9KCk7CiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci9jb21wb25lbnQvdGVtcGxhdGUtb25seQogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgVGhpcyB1dGlsaXR5IGZ1bmN0aW9uIGlzIHVzZWQgdG8gZGVjbGFyZSBhIGdpdmVuIGNvbXBvbmVudCBoYXMgbm8gYmFja2luZyBjbGFzcy4gV2hlbiB0aGUgcmVuZGVyaW5nIGVuZ2luZSBkZXRlY3RzIHRoaXMgaXQKICAgIGlzIGFibGUgdG8gcGVyZm9ybSBhIG51bWJlciBvZiBvcHRpbWl6YXRpb25zLiBUZW1wbGF0ZXMgdGhhdCBhcmUgYXNzb2NpYXRlZCB3aXRoIGB0ZW1wbGF0ZU9ubHkoKWAgd2lsbCBiZSByZW5kZXJlZCBfYXMgaXNfCiAgICB3aXRob3V0IGFkZGluZyBhIHdyYXBwaW5nIGA8ZGl2PmAgKG9yIGFueSBvZiB0aGUgb3RoZXIgZWxlbWVudCBjdXN0b21pemF0aW9uIGJlaGF2aW9ycyBvZiBbQGVtYmVyL2NvbXBvbmVudF0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9Db21wb25lbnQpKS4KICAgIFNwZWNpZmljYWxseSwgdGhpcyBtZWFucyB0aGF0IHRoZSB0ZW1wbGF0ZSB3aWxsIGJlIHJlbmRlcmVkIGFzICJvdXRlciBIVE1MIi4KICAKICAgIEluIGdlbmVyYWwsIHRoaXMgbWV0aG9kIHdpbGwgYmUgdXNlZCBieSBidWlsZCB0aW1lIHRvb2xpbmcgYW5kIHdvdWxkIG5vdCBiZSBkaXJlY3RseSB3cml0dGVuIGluIGFuIGFwcGxpY2F0aW9uLiBIb3dldmVyLAogICAgYXQgdGltZXMgaXQgbWF5IGJlIHVzZWZ1bCB0byB1c2UgZGlyZWN0bHkgdG8gbGV2ZXJhZ2UgdGhlICJvdXRlciBIVE1MIiBzZW1hbnRpY3MgbWVudGlvbmVkIGFib3ZlLiBGb3IgZXhhbXBsZSwgaWYgYW4gYWRkb24gd291bGQgbGlrZQogICAgdG8gdXNlIHRoZXNlIHNlbWFudGljcyBmb3IgaXRzIHRlbXBsYXRlcyBidXQgY2Fubm90IGJlIGNlcnRhaW4gaXQgd2lsbCBvbmx5IGJlIGNvbnN1bWVkIGJ5IGFwcGxpY2F0aW9ucyB0aGF0IGhhdmUgZW5hYmxlZCB0aGUKICAgIGB0ZW1wbGF0ZS1vbmx5LWdsaW1tZXItY29tcG9uZW50c2Agb3B0aW9uYWwgZmVhdHVyZS4KICAKICAgIEBleGFtcGxlCiAgCiAgICBgYGBqcwogICAgaW1wb3J0IHRlbXBsYXRlT25seSBmcm9tICdAZW1iZXIvY29tcG9uZW50L3RlbXBsYXRlLW9ubHknOwogIAogICAgZXhwb3J0IGRlZmF1bHQgdGVtcGxhdGVPbmx5KCk7CiAgICBgYGAKICAKICAgIEBwdWJsaWMKICAgIEBtZXRob2QgdGVtcGxhdGVPbmx5CiAgICBAcGFyYW0ge1N0cmluZ30gbW9kdWxlTmFtZSB0aGUgbW9kdWxlIG5hbWUgdGhhdCB0aGUgdGVtcGxhdGUgb25seSBjb21wb25lbnQgcmVwcmVzZW50cywgdGhpcyB3aWxsIGJlIHVzZWQgZm9yIGRlYnVnZ2luZyBwdXJwb3NlcwogICAgQGNhdGVnb3J5IEVNQkVSX0dMSU1NRVJfU0VUX0NPTVBPTkVOVF9URU1QTEFURQogICovCgoKICBfZXhwb3J0cy5UZW1wbGF0ZU9ubHlDb21wb25lbnQgPSBUZW1wbGF0ZU9ubHlDb21wb25lbnQ7CgogIGZ1bmN0aW9uIHRlbXBsYXRlT25seUNvbXBvbmVudChtb2R1bGVOYW1lKSB7CiAgICByZXR1cm4gbmV3IFRlbXBsYXRlT25seUNvbXBvbmVudChtb2R1bGVOYW1lKTsKICB9CgogIGZ1bmN0aW9uIGlzVGVtcGxhdGVPbmx5Q29tcG9uZW50KGNvbXBvbmVudCkgewogICAgcmV0dXJuIGNvbXBvbmVudCBpbnN0YW5jZW9mIFRlbXBsYXRlT25seUNvbXBvbmVudDsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci9jb250cm9sbGVyL2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2NvbnRyb2xsZXIvbGliL2NvbnRyb2xsZXJfbWl4aW4iXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfcnVudGltZSwgX21ldGFsLCBfY29udHJvbGxlcl9taXhpbikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuaW5qZWN0ID0gaW5qZWN0OwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgQGVtYmVyL2NvbnRyb2xsZXIKICAqLwoKICAvKioKICAgIEBjbGFzcyBDb250cm9sbGVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHVzZXMgRW1iZXIuQ29udHJvbGxlck1peGluCiAgICBAcHVibGljCiAgKi8KICB2YXIgQ29udHJvbGxlciA9IF9ydW50aW1lLkZyYW1ld29ya09iamVjdC5leHRlbmQoX2NvbnRyb2xsZXJfbWl4aW4uZGVmYXVsdCk7CgogIGlmICh0cnVlCiAgLyogRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCAqLwogICkgewogICAgICAoMCwgX3J1bnRpbWUuc2V0RnJhbWV3b3JrQ2xhc3MpKENvbnRyb2xsZXIpOwogICAgfQogIC8qKgogICAgQ3JlYXRlcyBhIHByb3BlcnR5IHRoYXQgbGF6aWx5IGxvb2tzIHVwIGFub3RoZXIgY29udHJvbGxlciBpbiB0aGUgY29udGFpbmVyLgogICAgQ2FuIG9ubHkgYmUgdXNlZCB3aGVuIGRlZmluaW5nIGFub3RoZXIgY29udHJvbGxlci4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBhcHAvY29udHJvbGxlcnMvcG9zdC5qcwogICAgaW1wb3J0IENvbnRyb2xsZXIsIHsKICAgICAgaW5qZWN0IGFzIGNvbnRyb2xsZXIKICAgIH0gZnJvbSAnQGVtYmVyL2NvbnRyb2xsZXInOwogIAogICAgZXhwb3J0IGRlZmF1bHQgY2xhc3MgUG9zdENvbnRyb2xsZXIgZXh0ZW5kcyBDb250cm9sbGVyIHsKICAgICAgQGNvbnRyb2xsZXIgcG9zdHM7CiAgICB9CiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGFwcC9jb250cm9sbGVycy9wb3N0LmpzCiAgICBpbXBvcnQgQ29udHJvbGxlciwgewogICAgICBpbmplY3QgYXMgY29udHJvbGxlcgogICAgfSBmcm9tICdAZW1iZXIvY29udHJvbGxlcic7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb250cm9sbGVyLmV4dGVuZCh7CiAgICAgIHBvc3RzOiBjb250cm9sbGVyKCkKICAgIH0pOwogICAgYGBgCiAgCiAgICBUaGlzIGV4YW1wbGUgd2lsbCBjcmVhdGUgYSBgcG9zdHNgIHByb3BlcnR5IG9uIHRoZSBgcG9zdGAgY29udHJvbGxlciB0aGF0CiAgICBsb29rcyB1cCB0aGUgYHBvc3RzYCBjb250cm9sbGVyIGluIHRoZSBjb250YWluZXIsIG1ha2luZyBpdCBlYXN5IHRvIHJlZmVyZW5jZQogICAgb3RoZXIgY29udHJvbGxlcnMuCiAgCiAgICBAbWV0aG9kIGluamVjdAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvY29udHJvbGxlcgogICAgQHNpbmNlIDEuMTAuMAogICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgKG9wdGlvbmFsKSBuYW1lIG9mIHRoZSBjb250cm9sbGVyIHRvIGluamVjdCwgZGVmYXVsdHMgdG8KICAgICAgICAgICB0aGUgcHJvcGVydHkncyBuYW1lCiAgICBAcmV0dXJuIHtDb21wdXRlZERlY29yYXRvcn0gaW5qZWN0aW9uIGRlY29yYXRvciBpbnN0YW5jZQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpbmplY3QoKSB7CiAgICByZXR1cm4gX21ldGFsLmluamVjdC5hcHBseSh2b2lkIDAsIFsnY29udHJvbGxlciddLmNvbmNhdChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7CiAgfQoKICB2YXIgX2RlZmF1bHQgPSBDb250cm9sbGVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2NvbnRyb2xsZXIvbGliL2NvbnRyb2xsZXJfbWl4aW4iLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX3J1bnRpbWUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIEBjbGFzcyBDb250cm9sbGVyTWl4aW4KICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEB1c2VzIEVtYmVyLkFjdGlvbkhhbmRsZXIKICAgIEBwcml2YXRlCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKF9ydW50aW1lLkFjdGlvbkhhbmRsZXIsIHsKICAgIC8qIGR1Y2t0eXBlIGFzIGEgY29udHJvbGxlciAqLwogICAgaXNDb250cm9sbGVyOiB0cnVlLAoKICAgIC8qKgogICAgICBUaGUgb2JqZWN0IHRvIHdoaWNoIGFjdGlvbnMgZnJvbSB0aGUgdmlldyBzaG91bGQgYmUgc2VudC4KICAgICAgIEZvciBleGFtcGxlLCB3aGVuIGEgSGFuZGxlYmFycyB0ZW1wbGF0ZSB1c2VzIHRoZSBge3thY3Rpb259fWAgaGVscGVyLAogICAgICBpdCB3aWxsIGF0dGVtcHQgdG8gc2VuZCB0aGUgYWN0aW9uIHRvIHRoZSB2aWV3J3MgY29udHJvbGxlcidzIGB0YXJnZXRgLgogICAgICAgQnkgZGVmYXVsdCwgdGhlIHZhbHVlIG9mIHRoZSB0YXJnZXQgcHJvcGVydHkgaXMgc2V0IHRvIHRoZSByb3V0ZXIsIGFuZAogICAgICBpcyBpbmplY3RlZCB3aGVuIGEgY29udHJvbGxlciBpcyBpbnN0YW50aWF0ZWQuIFRoaXMgaW5qZWN0aW9uIGlzIGFwcGxpZWQKICAgICAgYXMgcGFydCBvZiB0aGUgYXBwbGljYXRpb24ncyBpbml0aWFsaXphdGlvbiBwcm9jZXNzLiBJbiBtb3N0IGNhc2VzIHRoZQogICAgICBgdGFyZ2V0YCBwcm9wZXJ0eSB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgc2V0IHRvIHRoZSBsb2dpY2FsIGNvbnN1bWVyIG9mCiAgICAgIGFjdGlvbnMgZm9yIHRoZSBjb250cm9sbGVyLgogICAgICAgQHByb3BlcnR5IHRhcmdldAogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBwdWJsaWMKICAgICovCiAgICB0YXJnZXQ6IG51bGwsCiAgICBzdG9yZTogbnVsbCwKCiAgICAvKioKICAgICAgVGhlIGNvbnRyb2xsZXIncyBjdXJyZW50IG1vZGVsLiBXaGVuIHJldHJpZXZpbmcgb3IgbW9kaWZ5aW5nIGEgY29udHJvbGxlcidzCiAgICAgIG1vZGVsLCB0aGlzIHByb3BlcnR5IHNob3VsZCBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGBjb250ZW50YCBwcm9wZXJ0eS4KICAgICAgIEBwcm9wZXJ0eSBtb2RlbAogICAgICBAcHVibGljCiAgICAqLwogICAgbW9kZWw6IHRydWUKICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgPyAoMCwgX21ldGFsLnRyYWNrZWQpKCkgOiBudWxsCiAgfSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2RlYnVnL2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL2Jyb3dzZXItZW52aXJvbm1lbnQiLCAiQGVtYmVyL2Vycm9yIiwgIkBlbWJlci9kZWJ1Zy9saWIvZGVwcmVjYXRlIiwgIkBlbWJlci9kZWJ1Zy9saWIvdGVzdGluZyIsICJAZW1iZXIvZGVidWcvbGliL3dhcm4iXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfYnJvd3NlckVudmlyb25tZW50LCBfZXJyb3IsIF9kZXByZWNhdGUyLCBfdGVzdGluZywgX3dhcm4yKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJyZWdpc3RlckRlcHJlY2F0aW9uSGFuZGxlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9kZXByZWNhdGUyLnJlZ2lzdGVySGFuZGxlcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJpc1Rlc3RpbmciLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfdGVzdGluZy5pc1Rlc3Rpbmc7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0VGVzdGluZyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF90ZXN0aW5nLnNldFRlc3Rpbmc7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAicmVnaXN0ZXJXYXJuSGFuZGxlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF93YXJuMi5yZWdpc3RlckhhbmRsZXI7CiAgICB9CiAgfSk7CiAgX2V4cG9ydHMuX3dhcm5JZlVzaW5nU3RyaXBwZWRGZWF0dXJlRmxhZ3MgPSBfZXhwb3J0cy5nZXREZWJ1Z0Z1bmN0aW9uID0gX2V4cG9ydHMuc2V0RGVidWdGdW5jdGlvbiA9IF9leHBvcnRzLmRlcHJlY2F0ZUZ1bmMgPSBfZXhwb3J0cy5ydW5JbkRlYnVnID0gX2V4cG9ydHMuZGVidWdGcmVlemUgPSBfZXhwb3J0cy5kZWJ1Z1NlYWwgPSBfZXhwb3J0cy5kZXByZWNhdGUgPSBfZXhwb3J0cy5kZWJ1ZyA9IF9leHBvcnRzLndhcm4gPSBfZXhwb3J0cy5pbmZvID0gX2V4cG9ydHMuYXNzZXJ0ID0gdm9pZCAwOwoKICAvLyBUaGVzZSBhcmUgdGhlIGRlZmF1bHQgcHJvZHVjdGlvbiBidWlsZCB2ZXJzaW9uczoKICB2YXIgbm9vcCA9IGZ1bmN0aW9uIG5vb3AoKSB7fTsKCiAgdmFyIGFzc2VydCA9IG5vb3A7CiAgX2V4cG9ydHMuYXNzZXJ0ID0gYXNzZXJ0OwogIHZhciBpbmZvID0gbm9vcDsKICBfZXhwb3J0cy5pbmZvID0gaW5mbzsKICB2YXIgd2FybiA9IG5vb3A7CiAgX2V4cG9ydHMud2FybiA9IHdhcm47CiAgdmFyIGRlYnVnID0gbm9vcDsKICBfZXhwb3J0cy5kZWJ1ZyA9IGRlYnVnOwogIHZhciBkZXByZWNhdGUgPSBub29wOwogIF9leHBvcnRzLmRlcHJlY2F0ZSA9IGRlcHJlY2F0ZTsKICB2YXIgZGVidWdTZWFsID0gbm9vcDsKICBfZXhwb3J0cy5kZWJ1Z1NlYWwgPSBkZWJ1Z1NlYWw7CiAgdmFyIGRlYnVnRnJlZXplID0gbm9vcDsKICBfZXhwb3J0cy5kZWJ1Z0ZyZWV6ZSA9IGRlYnVnRnJlZXplOwogIHZhciBydW5JbkRlYnVnID0gbm9vcDsKICBfZXhwb3J0cy5ydW5JbkRlYnVnID0gcnVuSW5EZWJ1ZzsKICB2YXIgc2V0RGVidWdGdW5jdGlvbiA9IG5vb3A7CiAgX2V4cG9ydHMuc2V0RGVidWdGdW5jdGlvbiA9IHNldERlYnVnRnVuY3Rpb247CiAgdmFyIGdldERlYnVnRnVuY3Rpb24gPSBub29wOwogIF9leHBvcnRzLmdldERlYnVnRnVuY3Rpb24gPSBnZXREZWJ1Z0Z1bmN0aW9uOwoKICB2YXIgZGVwcmVjYXRlRnVuYyA9IGZ1bmN0aW9uIGRlcHJlY2F0ZUZ1bmMoKSB7CiAgICByZXR1cm4gYXJndW1lbnRzW2FyZ3VtZW50cy5sZW5ndGggLSAxXTsKICB9OwoKICBfZXhwb3J0cy5kZXByZWNhdGVGdW5jID0gZGVwcmVjYXRlRnVuYzsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIF9leHBvcnRzLnNldERlYnVnRnVuY3Rpb24gPSBzZXREZWJ1Z0Z1bmN0aW9uID0gZnVuY3Rpb24gc2V0RGVidWdGdW5jdGlvbih0eXBlLCBjYWxsYmFjaykgewogICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICBjYXNlICdhc3NlcnQnOgogICAgICAgICAgcmV0dXJuIF9leHBvcnRzLmFzc2VydCA9IGFzc2VydCA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdpbmZvJzoKICAgICAgICAgIHJldHVybiBfZXhwb3J0cy5pbmZvID0gaW5mbyA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICd3YXJuJzoKICAgICAgICAgIHJldHVybiBfZXhwb3J0cy53YXJuID0gd2FybiA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdkZWJ1Zyc6CiAgICAgICAgICByZXR1cm4gX2V4cG9ydHMuZGVidWcgPSBkZWJ1ZyA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdkZXByZWNhdGUnOgogICAgICAgICAgcmV0dXJuIF9leHBvcnRzLmRlcHJlY2F0ZSA9IGRlcHJlY2F0ZSA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdkZWJ1Z1NlYWwnOgogICAgICAgICAgcmV0dXJuIF9leHBvcnRzLmRlYnVnU2VhbCA9IGRlYnVnU2VhbCA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdkZWJ1Z0ZyZWV6ZSc6CiAgICAgICAgICByZXR1cm4gX2V4cG9ydHMuZGVidWdGcmVlemUgPSBkZWJ1Z0ZyZWV6ZSA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdydW5JbkRlYnVnJzoKICAgICAgICAgIHJldHVybiBfZXhwb3J0cy5ydW5JbkRlYnVnID0gcnVuSW5EZWJ1ZyA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdkZXByZWNhdGVGdW5jJzoKICAgICAgICAgIHJldHVybiBfZXhwb3J0cy5kZXByZWNhdGVGdW5jID0gZGVwcmVjYXRlRnVuYyA9IGNhbGxiYWNrOwogICAgICB9CiAgICB9OwoKICAgIF9leHBvcnRzLmdldERlYnVnRnVuY3Rpb24gPSBnZXREZWJ1Z0Z1bmN0aW9uID0gZnVuY3Rpb24gZ2V0RGVidWdGdW5jdGlvbih0eXBlKSB7CiAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgIGNhc2UgJ2Fzc2VydCc6CiAgICAgICAgICByZXR1cm4gYXNzZXJ0OwoKICAgICAgICBjYXNlICdpbmZvJzoKICAgICAgICAgIHJldHVybiBpbmZvOwoKICAgICAgICBjYXNlICd3YXJuJzoKICAgICAgICAgIHJldHVybiB3YXJuOwoKICAgICAgICBjYXNlICdkZWJ1Zyc6CiAgICAgICAgICByZXR1cm4gZGVidWc7CgogICAgICAgIGNhc2UgJ2RlcHJlY2F0ZSc6CiAgICAgICAgICByZXR1cm4gZGVwcmVjYXRlOwoKICAgICAgICBjYXNlICdkZWJ1Z1NlYWwnOgogICAgICAgICAgcmV0dXJuIGRlYnVnU2VhbDsKCiAgICAgICAgY2FzZSAnZGVidWdGcmVlemUnOgogICAgICAgICAgcmV0dXJuIGRlYnVnRnJlZXplOwoKICAgICAgICBjYXNlICdydW5JbkRlYnVnJzoKICAgICAgICAgIHJldHVybiBydW5JbkRlYnVnOwoKICAgICAgICBjYXNlICdkZXByZWNhdGVGdW5jJzoKICAgICAgICAgIHJldHVybiBkZXByZWNhdGVGdW5jOwogICAgICB9CiAgICB9OwogIH0KICAvKioKICBAbW9kdWxlIEBlbWJlci9kZWJ1ZwogICovCgoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgLyoqCiAgICAgIFZlcmlmeSB0aGF0IGEgY2VydGFpbiBleHBlY3RhdGlvbiBpcyBtZXQsIG9yIHRocm93IGEgZXhjZXB0aW9uIG90aGVyd2lzZS4KICAgICAgICAgVGhpcyBpcyB1c2VmdWwgZm9yIGNvbW11bmljYXRpbmcgYXNzdW1wdGlvbnMgaW4gdGhlIGNvZGUgdG8gb3RoZXIgaHVtYW4KICAgICAgcmVhZGVycyBhcyB3ZWxsIGFzIGNhdGNoaW5nIGJ1Z3MgdGhhdCBhY2NpZGVudGFsbHkgdmlvbGF0ZXMgdGhlc2UKICAgICAgZXhwZWN0YXRpb25zLgogICAgICAgICBBc3NlcnRpb25zIGFyZSByZW1vdmVkIGZyb20gcHJvZHVjdGlvbiBidWlsZHMsIHNvIHRoZXkgY2FuIGJlIGZyZWVseSBhZGRlZAogICAgICBmb3IgZG9jdW1lbnRhdGlvbiBhbmQgZGVidWdnaW5nIHB1cnBvc2VzIHdpdGhvdXQgd29ycmllcyBvZiBpbmN1cmluZyBhbnkKICAgICAgcGVyZm9ybWFuY2UgcGVuYWx0eS4gSG93ZXZlciwgYmVjYXVzZSBvZiB0aGF0LCB0aGV5IHNob3VsZCBub3QgYmUgdXNlZCBmb3IKICAgICAgY2hlY2tzIHRoYXQgY291bGQgcmVhc29uYWJseSBmYWlsIGR1cmluZyBub3JtYWwgdXNhZ2UuIEZ1cnRoZXJtb3JlLCBjYXJlCiAgICAgIHNob3VsZCBiZSB0YWtlbiB0byBhdm9pZCBhY2NpZGVudGFsbHkgcmVseWluZyBvbiBzaWRlLWVmZmVjdHMgcHJvZHVjZWQgZnJvbQogICAgICBldmFsdWF0aW5nIHRoZSBjb25kaXRpb24gaXRzZWxmLCBzaW5jZSB0aGUgY29kZSB3aWxsIG5vdCBydW4gaW4gcHJvZHVjdGlvbi4KICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgeyBhc3NlcnQgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgICAvLyBUZXN0IGZvciB0cnV0aGluZXNzCiAgICAgIGFzc2VydCgnTXVzdCBwYXNzIGEgc3RyaW5nJywgdHlwZW9mIHN0ciA9PT0gJ3N0cmluZycpOwogICAgICAgICAvLyBGYWlsIHVuY29uZGl0aW9uYWxseQogICAgICBhc3NlcnQoJ1RoaXMgY29kZSBwYXRoIHNob3VsZCBuZXZlciBiZSBydW4nKTsKICAgICAgYGBgCiAgICAgICAgIEBtZXRob2QgYXNzZXJ0CiAgICAgIEBzdGF0aWMKICAgICAgQGZvciBAZW1iZXIvZGVidWcKICAgICAgQHBhcmFtIHtTdHJpbmd9IGRlc2NyaXB0aW9uIERlc2NyaWJlcyB0aGUgZXhwZWN0YXRpb24uIFRoaXMgd2lsbCBiZWNvbWUgdGhlCiAgICAgICAgdGV4dCBvZiB0aGUgRXJyb3IgdGhyb3duIGlmIHRoZSBhc3NlcnRpb24gZmFpbHMuCiAgICAgIEBwYXJhbSB7Qm9vbGVhbn0gY29uZGl0aW9uIE11c3QgYmUgdHJ1dGh5IGZvciB0aGUgYXNzZXJ0aW9uIHRvIHBhc3MuIElmCiAgICAgICAgZmFsc3ksIGFuIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93bi4KICAgICAgQHB1YmxpYwogICAgICBAc2luY2UgMS4wLjAKICAgICovCiAgICBzZXREZWJ1Z0Z1bmN0aW9uKCdhc3NlcnQnLCBmdW5jdGlvbiBhc3NlcnQoZGVzYywgdGVzdCkgewogICAgICBpZiAoIXRlc3QpIHsKICAgICAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIkFzc2VydGlvbiBGYWlsZWQ6ICIgKyBkZXNjKTsKICAgICAgfQogICAgfSk7CiAgICAvKioKICAgICAgRGlzcGxheSBhIGRlYnVnIG5vdGljZS4KICAgICAgICAgQ2FsbHMgdG8gdGhpcyBmdW5jdGlvbiBhcmUgcmVtb3ZlZCBmcm9tIHByb2R1Y3Rpb24gYnVpbGRzLCBzbyB0aGV5IGNhbiBiZQogICAgICBmcmVlbHkgYWRkZWQgZm9yIGRvY3VtZW50YXRpb24gYW5kIGRlYnVnZ2luZyBwdXJwb3NlcyB3aXRob3V0IHdvcnJpZXMgb2YKICAgICAgaW5jdXJpbmcgYW55IHBlcmZvcm1hbmNlIHBlbmFsdHkuCiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IHsgZGVidWcgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgICBkZWJ1ZygnSVwnbSBhIGRlYnVnIG5vdGljZSEnKTsKICAgICAgYGBgCiAgICAgICAgIEBtZXRob2QgZGVidWcKICAgICAgQGZvciBAZW1iZXIvZGVidWcKICAgICAgQHN0YXRpYwogICAgICBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBBIGRlYnVnIG1lc3NhZ2UgdG8gZGlzcGxheS4KICAgICAgQHB1YmxpYwogICAgKi8KCiAgICBzZXREZWJ1Z0Z1bmN0aW9uKCdkZWJ1ZycsIGZ1bmN0aW9uIGRlYnVnKG1lc3NhZ2UpIHsKICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqLwogICAgICBpZiAoY29uc29sZS5kZWJ1ZykgewogICAgICAgIGNvbnNvbGUuZGVidWcoIkRFQlVHOiAiICsgbWVzc2FnZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc29sZS5sb2coIkRFQlVHOiAiICsgbWVzc2FnZSk7CiAgICAgIH0KICAgICAgLyogZXNsaW50LWVuc2FibGUgbm8tY29uc29sZSAqLwoKICAgIH0pOwogICAgLyoqCiAgICAgIERpc3BsYXkgYW4gaW5mbyBub3RpY2UuCiAgICAgICAgIENhbGxzIHRvIHRoaXMgZnVuY3Rpb24gYXJlIHJlbW92ZWQgZnJvbSBwcm9kdWN0aW9uIGJ1aWxkcywgc28gdGhleSBjYW4gYmUKICAgICAgZnJlZWx5IGFkZGVkIGZvciBkb2N1bWVudGF0aW9uIGFuZCBkZWJ1Z2dpbmcgcHVycG9zZXMgd2l0aG91dCB3b3JyaWVzIG9mCiAgICAgIGluY3VyaW5nIGFueSBwZXJmb3JtYW5jZSBwZW5hbHR5LgogICAgICAgICBAbWV0aG9kIGluZm8KICAgICAgQHByaXZhdGUKICAgICovCgogICAgc2V0RGVidWdGdW5jdGlvbignaW5mbycsIGZ1bmN0aW9uIGluZm8oKSB7CiAgICAgIHZhciBfY29uc29sZTsKCiAgICAgIChfY29uc29sZSA9IGNvbnNvbGUpLmluZm8uYXBwbHkoX2NvbnNvbGUsIGFyZ3VtZW50cyk7CiAgICAgIC8qIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tY29uc29sZSAqLwoKICAgIH0pOwogICAgLyoqCiAgICAgQG1vZHVsZSBAZW1iZXIvZGVidWcKICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBBbGlhcyBhbiBvbGQsIGRlcHJlY2F0ZWQgbWV0aG9kIHdpdGggaXRzIG5ldyBjb3VudGVycGFydC4KICAgICAgICAgRGlzcGxheSBhIGRlcHJlY2F0aW9uIHdhcm5pbmcgd2l0aCB0aGUgcHJvdmlkZWQgbWVzc2FnZSBhbmQgYSBzdGFjayB0cmFjZQogICAgICAoQ2hyb21lIGFuZCBGaXJlZm94IG9ubHkpIHdoZW4gdGhlIGFzc2lnbmVkIG1ldGhvZCBpcyBjYWxsZWQuCiAgICAgICAgIENhbGxzIHRvIHRoaXMgZnVuY3Rpb24gYXJlIHJlbW92ZWQgZnJvbSBwcm9kdWN0aW9uIGJ1aWxkcywgc28gdGhleSBjYW4gYmUKICAgICAgZnJlZWx5IGFkZGVkIGZvciBkb2N1bWVudGF0aW9uIGFuZCBkZWJ1Z2dpbmcgcHVycG9zZXMgd2l0aG91dCB3b3JyaWVzIG9mCiAgICAgIGluY3VyaW5nIGFueSBwZXJmb3JtYW5jZSBwZW5hbHR5LgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCB7IGRlcHJlY2F0ZUZ1bmMgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgICBFbWJlci5vbGRNZXRob2QgPSBkZXByZWNhdGVGdW5jKCdQbGVhc2UgdXNlIHRoZSBuZXcsIHVwZGF0ZWQgbWV0aG9kJywgb3B0aW9ucywgRW1iZXIubmV3TWV0aG9kKTsKICAgICAgYGBgCiAgICAgICAgIEBtZXRob2QgZGVwcmVjYXRlRnVuYwogICAgICBAc3RhdGljCiAgICAgIEBmb3IgQGVtYmVyL2RlYnVnCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIEEgZGVzY3JpcHRpb24gb2YgdGhlIGRlcHJlY2F0aW9uLgogICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIFRoZSBvcHRpb25zIG9iamVjdCBmb3IgYGRlcHJlY2F0ZWAuCiAgICAgIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIG5ldyBmdW5jdGlvbiBjYWxsZWQgdG8gcmVwbGFjZSBpdHMgZGVwcmVjYXRlZCBjb3VudGVycGFydC4KICAgICAgQHJldHVybiB7RnVuY3Rpb259IEEgbmV3IGZ1bmN0aW9uIHRoYXQgd3JhcHMgdGhlIG9yaWdpbmFsIGZ1bmN0aW9uIHdpdGggYSBkZXByZWNhdGlvbiB3YXJuaW5nCiAgICAgIEBwcml2YXRlCiAgICAqLwoKICAgIHNldERlYnVnRnVuY3Rpb24oJ2RlcHJlY2F0ZUZ1bmMnLCBmdW5jdGlvbiBkZXByZWNhdGVGdW5jKCkgewogICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHsKICAgICAgICB2YXIgbWVzc2FnZSA9IGFyZ3NbMF0sCiAgICAgICAgICAgIG9wdGlvbnMgPSBhcmdzWzFdLAogICAgICAgICAgICBmdW5jID0gYXJnc1syXTsKICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgICAgZGVwcmVjYXRlKG1lc3NhZ2UsIGZhbHNlLCBvcHRpb25zKTsKCiAgICAgICAgICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjIpLCBfa2V5MiA9IDA7IF9rZXkyIDwgX2xlbjI7IF9rZXkyKyspIHsKICAgICAgICAgICAgYXJnc1tfa2V5Ml0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3MpOwogICAgICAgIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIF9tZXNzYWdlID0gYXJnc1swXSwKICAgICAgICAgICAgX2Z1bmMgPSBhcmdzWzFdOwogICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBkZXByZWNhdGUoX21lc3NhZ2UpOwogICAgICAgICAgcmV0dXJuIF9mdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICAgICAgfTsKICAgICAgfQogICAgfSk7CiAgICAvKioKICAgICBAbW9kdWxlIEBlbWJlci9kZWJ1ZwogICAgIEBwdWJsaWMKICAgICovCgogICAgLyoqCiAgICAgIFJ1biBhIGZ1bmN0aW9uIG1lYW50IGZvciBkZWJ1Z2dpbmcuCiAgICAgICAgIENhbGxzIHRvIHRoaXMgZnVuY3Rpb24gYXJlIHJlbW92ZWQgZnJvbSBwcm9kdWN0aW9uIGJ1aWxkcywgc28gdGhleSBjYW4gYmUKICAgICAgZnJlZWx5IGFkZGVkIGZvciBkb2N1bWVudGF0aW9uIGFuZCBkZWJ1Z2dpbmcgcHVycG9zZXMgd2l0aG91dCB3b3JyaWVzIG9mCiAgICAgIGluY3VyaW5nIGFueSBwZXJmb3JtYW5jZSBwZW5hbHR5LgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIGltcG9ydCB7IHJ1bkluRGVidWcgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgICBydW5JbkRlYnVnKCgpID0+IHsKICAgICAgICBDb21wb25lbnQucmVvcGVuKHsKICAgICAgICAgIGRpZEluc2VydEVsZW1lbnQoKSB7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKCJJJ20gaGFwcHkiKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHJ1bkluRGVidWcKICAgICAgQGZvciBAZW1iZXIvZGVidWcKICAgICAgQHN0YXRpYwogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZC4KICAgICAgQHNpbmNlIDEuNS4wCiAgICAgIEBwdWJsaWMKICAgICovCgogICAgc2V0RGVidWdGdW5jdGlvbigncnVuSW5EZWJ1ZycsIGZ1bmN0aW9uIHJ1bkluRGVidWcoZnVuYykgewogICAgICBmdW5jKCk7CiAgICB9KTsKICAgIHNldERlYnVnRnVuY3Rpb24oJ2RlYnVnU2VhbCcsIGZ1bmN0aW9uIGRlYnVnU2VhbChvYmopIHsKICAgICAgT2JqZWN0LnNlYWwob2JqKTsKICAgIH0pOwogICAgc2V0RGVidWdGdW5jdGlvbignZGVidWdGcmVlemUnLCBmdW5jdGlvbiBkZWJ1Z0ZyZWV6ZShvYmopIHsKICAgICAgLy8gcmUtZnJlZXppbmcgYW4gYWxyZWFkeSBmcm96ZW4gb2JqZWN0IGludHJvZHVjZXMgYSBzaWduaWZpY2FudAogICAgICAvLyBwZXJmb3JtYW5jZSBwZW5hbHR5IG9uIENocm9tZSAodGVzdGVkIHRocm91Z2ggNTkpLgogICAgICAvLwogICAgICAvLyBTZWU6IGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTY0NTAKICAgICAgaWYgKCFPYmplY3QuaXNGcm96ZW4ob2JqKSkgewogICAgICAgIE9iamVjdC5mcmVlemUob2JqKTsKICAgICAgfQogICAgfSk7CiAgICBzZXREZWJ1Z0Z1bmN0aW9uKCdkZXByZWNhdGUnLCBfZGVwcmVjYXRlMi5kZWZhdWx0KTsKICAgIHNldERlYnVnRnVuY3Rpb24oJ3dhcm4nLCBfd2FybjIuZGVmYXVsdCk7CiAgfQoKICB2YXIgX3dhcm5JZlVzaW5nU3RyaXBwZWRGZWF0dXJlRmxhZ3M7CgogIF9leHBvcnRzLl93YXJuSWZVc2luZ1N0cmlwcGVkRmVhdHVyZUZsYWdzID0gX3dhcm5JZlVzaW5nU3RyaXBwZWRGZWF0dXJlRmxhZ3M7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgJiYgISgwLCBfdGVzdGluZy5pc1Rlc3RpbmcpKCkpIHsKICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiAoX2Jyb3dzZXJFbnZpcm9ubWVudC5pc0ZpcmVmb3ggfHwgX2Jyb3dzZXJFbnZpcm9ubWVudC5pc0Nocm9tZSkgJiYgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIpIHsKICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgaWYgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZGF0YXNldCAmJiAhZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmRhdGFzZXQuZW1iZXJFeHRlbnNpb24pIHsKICAgICAgICAgIHZhciBkb3dubG9hZFVSTDsKCiAgICAgICAgICBpZiAoX2Jyb3dzZXJFbnZpcm9ubWVudC5pc0Nocm9tZSkgewogICAgICAgICAgICBkb3dubG9hZFVSTCA9ICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9lbWJlci1pbnNwZWN0b3IvYm1kYmxuY2Vna2Vua2FjaWVpaGZocGpmcHBvY29uaGknOwogICAgICAgICAgfSBlbHNlIGlmIChfYnJvd3NlckVudmlyb25tZW50LmlzRmlyZWZveCkgewogICAgICAgICAgICBkb3dubG9hZFVSTCA9ICdodHRwczovL2FkZG9ucy5tb3ppbGxhLm9yZy9lbi1VUy9maXJlZm94L2FkZG9uL2VtYmVyLWluc3BlY3Rvci8nOwogICAgICAgICAgfQoKICAgICAgICAgIGRlYnVnKCJGb3IgbW9yZSBhZHZhbmNlZCBkZWJ1Z2dpbmcsIGluc3RhbGwgdGhlIEVtYmVyIEluc3BlY3RvciBmcm9tICIgKyBkb3dubG9hZFVSTCk7CiAgICAgICAgfQogICAgICB9LCBmYWxzZSk7CiAgICB9CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvZGVidWcvbGliL2RlcHJlY2F0ZSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCIsICJAZW1iZXIvZGVidWcvaW5kZXgiLCAiQGVtYmVyL2RlYnVnL2xpYi9oYW5kbGVycyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbnZpcm9ubWVudCwgX2luZGV4LCBfaGFuZGxlcnMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zVW50aWxEZXByZWNhdGlvbiA9IF9leHBvcnRzLm1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9IF9leHBvcnRzLm1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb24gPSBfZXhwb3J0cy5yZWdpc3RlckhhbmRsZXIgPSBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgQG1vZHVsZSBAZW1iZXIvZGVidWcKICAgQHB1YmxpYwogICovCgogIC8qKgogICAgQWxsb3dzIGZvciBydW50aW1lIHJlZ2lzdHJhdGlvbiBvZiBoYW5kbGVyIGZ1bmN0aW9ucyB0aGF0IG92ZXJyaWRlIHRoZSBkZWZhdWx0IGRlcHJlY2F0aW9uIGJlaGF2aW9yLgogICAgRGVwcmVjYXRpb25zIGFyZSBpbnZva2VkIGJ5IGNhbGxzIHRvIFtAZW1iZXIvZGVidWcvZGVwcmVjYXRlXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0BlbWJlciUyRmRlYnVnL21ldGhvZHMvZGVwcmVjYXRlP2FuY2hvcj1kZXByZWNhdGUpLgogICAgVGhlIGZvbGxvd2luZyBleGFtcGxlIGRlbW9uc3RyYXRlcyBpdHMgdXNhZ2UgYnkgcmVnaXN0ZXJpbmcgYSBoYW5kbGVyIHRoYXQgdGhyb3dzIGFuIGVycm9yIGlmIHRoZQogICAgbWVzc2FnZSBjb250YWlucyB0aGUgd29yZCAic2hvdWxkIiwgb3RoZXJ3aXNlIGRlZmVycyB0byB0aGUgZGVmYXVsdCBoYW5kbGVyLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgcmVnaXN0ZXJEZXByZWNhdGlvbkhhbmRsZXIgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogIAogICAgcmVnaXN0ZXJEZXByZWNhdGlvbkhhbmRsZXIoKG1lc3NhZ2UsIG9wdGlvbnMsIG5leHQpID0+IHsKICAgICAgaWYgKG1lc3NhZ2UuaW5kZXhPZignc2hvdWxkJykgIT09IC0xKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBEZXByZWNhdGlvbiBtZXNzYWdlIHdpdGggc2hvdWxkOiAke21lc3NhZ2V9YCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gZGVmZXIgdG8gd2hhdGV2ZXIgaGFuZGxlciB3YXMgcmVnaXN0ZXJlZCBiZWZvcmUgdGhpcyBvbmUKICAgICAgICBuZXh0KG1lc3NhZ2UsIG9wdGlvbnMpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgVGhlIGhhbmRsZXIgZnVuY3Rpb24gdGFrZXMgdGhlIGZvbGxvd2luZyBhcmd1bWVudHM6CiAgCiAgICA8dWw+CiAgICAgIDxsaT4gPGNvZGU+bWVzc2FnZTwvY29kZT4gLSBUaGUgbWVzc2FnZSByZWNlaXZlZCBmcm9tIHRoZSBkZXByZWNhdGlvbiBjYWxsLjwvbGk+CiAgICAgIDxsaT4gPGNvZGU+b3B0aW9uczwvY29kZT4gLSBBbiBvYmplY3QgcGFzc2VkIGluIHdpdGggdGhlIGRlcHJlY2F0aW9uIGNhbGwgY29udGFpbmluZyBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIGluY2x1ZGluZzo8L2xpPgogICAgICAgIDx1bD4KICAgICAgICAgIDxsaT4gPGNvZGU+aWQ8L2NvZGU+IC0gQW4gaWQgb2YgdGhlIGRlcHJlY2F0aW9uIGluIHRoZSBmb3JtIG9mIDxjb2RlPnBhY2thZ2UtbmFtZS5zcGVjaWZpYy1kZXByZWNhdGlvbjwvY29kZT4uPC9saT4KICAgICAgICAgIDxsaT4gPGNvZGU+dW50aWw8L2NvZGU+IC0gVGhlIEVtYmVyIHZlcnNpb24gbnVtYmVyIHRoZSBmZWF0dXJlIGFuZCBkZXByZWNhdGlvbiB3aWxsIGJlIHJlbW92ZWQgaW4uPC9saT4KICAgICAgICA8L3VsPgogICAgICA8bGk+IDxjb2RlPm5leHQ8L2NvZGU+IC0gQSBmdW5jdGlvbiB0aGF0IGNhbGxzIGludG8gdGhlIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCBoYW5kbGVyLjwvbGk+CiAgICA8L3VsPgogIAogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQG1ldGhvZCByZWdpc3RlckRlcHJlY2F0aW9uSGFuZGxlcgogICAgQGZvciBAZW1iZXIvZGVidWcKICAgIEBwYXJhbSBoYW5kbGVyIHtGdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBoYW5kbGUgZGVwcmVjYXRpb24gY2FsbHMuCiAgICBAc2luY2UgMi4xLjAKICAqLwogIHZhciByZWdpc3RlckhhbmRsZXIgPSBmdW5jdGlvbiByZWdpc3RlckhhbmRsZXIoKSB7fTsKCiAgX2V4cG9ydHMucmVnaXN0ZXJIYW5kbGVyID0gcmVnaXN0ZXJIYW5kbGVyOwogIHZhciBtaXNzaW5nT3B0aW9uc0RlcHJlY2F0aW9uOwogIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb24gPSBtaXNzaW5nT3B0aW9uc0RlcHJlY2F0aW9uOwogIHZhciBtaXNzaW5nT3B0aW9uc0lkRGVwcmVjYXRpb247CiAgX2V4cG9ydHMubWlzc2luZ09wdGlvbnNJZERlcHJlY2F0aW9uID0gbWlzc2luZ09wdGlvbnNJZERlcHJlY2F0aW9uOwogIHZhciBtaXNzaW5nT3B0aW9uc1VudGlsRGVwcmVjYXRpb247CiAgX2V4cG9ydHMubWlzc2luZ09wdGlvbnNVbnRpbERlcHJlY2F0aW9uID0gbWlzc2luZ09wdGlvbnNVbnRpbERlcHJlY2F0aW9uOwoKICB2YXIgZGVwcmVjYXRlID0gZnVuY3Rpb24gZGVwcmVjYXRlKCkge307CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICBfZXhwb3J0cy5yZWdpc3RlckhhbmRsZXIgPSByZWdpc3RlckhhbmRsZXIgPSBmdW5jdGlvbiByZWdpc3RlckhhbmRsZXIoaGFuZGxlcikgewogICAgICAoMCwgX2hhbmRsZXJzLnJlZ2lzdGVySGFuZGxlcikoJ2RlcHJlY2F0ZScsIGhhbmRsZXIpOwogICAgfTsKCiAgICB2YXIgZm9ybWF0TWVzc2FnZSA9IGZ1bmN0aW9uIGZvcm1hdE1lc3NhZ2UoX21lc3NhZ2UsIG9wdGlvbnMpIHsKICAgICAgdmFyIG1lc3NhZ2UgPSBfbWVzc2FnZTsKCiAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuaWQpIHsKICAgICAgICBtZXNzYWdlID0gbWVzc2FnZSArICgiIFtkZXByZWNhdGlvbiBpZDogIiArIG9wdGlvbnMuaWQgKyAiXSIpOwogICAgICB9CgogICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnVybCkgewogICAgICAgIG1lc3NhZ2UgKz0gIiBTZWUgIiArIG9wdGlvbnMudXJsICsgIiBmb3IgbW9yZSBkZXRhaWxzLiI7CiAgICAgIH0KCiAgICAgIHJldHVybiBtZXNzYWdlOwogICAgfTsKCiAgICByZWdpc3RlckhhbmRsZXIoZnVuY3Rpb24gbG9nRGVwcmVjYXRpb25Ub0NvbnNvbGUobWVzc2FnZSwgb3B0aW9ucykgewogICAgICB2YXIgdXBkYXRlZE1lc3NhZ2UgPSBmb3JtYXRNZXNzYWdlKG1lc3NhZ2UsIG9wdGlvbnMpOwogICAgICBjb25zb2xlLndhcm4oIkRFUFJFQ0FUSU9OOiAiICsgdXBkYXRlZE1lc3NhZ2UpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGUKICAgIH0pOwogICAgdmFyIGNhcHR1cmVFcnJvckZvclN0YWNrOwoKICAgIGlmIChuZXcgRXJyb3IoKS5zdGFjaykgewogICAgICBjYXB0dXJlRXJyb3JGb3JTdGFjayA9IGZ1bmN0aW9uIGNhcHR1cmVFcnJvckZvclN0YWNrKCkgewogICAgICAgIHJldHVybiBuZXcgRXJyb3IoKTsKICAgICAgfTsKICAgIH0gZWxzZSB7CiAgICAgIGNhcHR1cmVFcnJvckZvclN0YWNrID0gZnVuY3Rpb24gY2FwdHVyZUVycm9yRm9yU3RhY2soKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIF9fZmFpbF9fLmZhaWwoKTsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICByZXR1cm4gZTsKICAgICAgICB9CiAgICAgIH07CiAgICB9CgogICAgcmVnaXN0ZXJIYW5kbGVyKGZ1bmN0aW9uIGxvZ0RlcHJlY2F0aW9uU3RhY2tUcmFjZShtZXNzYWdlLCBvcHRpb25zLCBuZXh0KSB7CiAgICAgIGlmIChfZW52aXJvbm1lbnQuRU5WLkxPR19TVEFDS1RSQUNFX09OX0RFUFJFQ0FUSU9OKSB7CiAgICAgICAgdmFyIHN0YWNrU3RyID0gJyc7CiAgICAgICAgdmFyIGVycm9yID0gY2FwdHVyZUVycm9yRm9yU3RhY2soKTsKICAgICAgICB2YXIgc3RhY2s7CgogICAgICAgIGlmIChlcnJvci5zdGFjaykgewogICAgICAgICAgaWYgKGVycm9yWydhcmd1bWVudHMnXSkgewogICAgICAgICAgICAvLyBDaHJvbWUKICAgICAgICAgICAgc3RhY2sgPSBlcnJvci5zdGFjay5yZXBsYWNlKC9eXHMrYXRccysvZ20sICcnKS5yZXBsYWNlKC9eKFteXChdKz8pKFtcbiRdKS9nbSwgJ3thbm9ueW1vdXN9KCQxKSQyJykucmVwbGFjZSgvXk9iamVjdC48YW5vbnltb3VzPlxzKlwoKFteXCldKylcKS9nbSwgJ3thbm9ueW1vdXN9KCQxKScpLnNwbGl0KCdcbicpOwogICAgICAgICAgICBzdGFjay5zaGlmdCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgLy8gRmlyZWZveAogICAgICAgICAgICBzdGFjayA9IGVycm9yLnN0YWNrLnJlcGxhY2UoLyg/OlxuQDowKT9ccyskL20sICcnKS5yZXBsYWNlKC9eXCgvZ20sICd7YW5vbnltb3VzfSgnKS5zcGxpdCgnXG4nKTsKICAgICAgICAgIH0KCiAgICAgICAgICBzdGFja1N0ciA9ICJcbiAgICAiICsgc3RhY2suc2xpY2UoMikuam9pbignXG4gICAgJyk7CiAgICAgICAgfQoKICAgICAgICB2YXIgdXBkYXRlZE1lc3NhZ2UgPSBmb3JtYXRNZXNzYWdlKG1lc3NhZ2UsIG9wdGlvbnMpOwogICAgICAgIGNvbnNvbGUud2FybigiREVQUkVDQVRJT046ICIgKyB1cGRhdGVkTWVzc2FnZSArIHN0YWNrU3RyKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlCiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmV4dChtZXNzYWdlLCBvcHRpb25zKTsKICAgICAgfQogICAgfSk7CiAgICByZWdpc3RlckhhbmRsZXIoZnVuY3Rpb24gcmFpc2VPbkRlcHJlY2F0aW9uKG1lc3NhZ2UsIG9wdGlvbnMsIG5leHQpIHsKICAgICAgaWYgKF9lbnZpcm9ubWVudC5FTlYuUkFJU0VfT05fREVQUkVDQVRJT04pIHsKICAgICAgICB2YXIgdXBkYXRlZE1lc3NhZ2UgPSBmb3JtYXRNZXNzYWdlKG1lc3NhZ2UpOwogICAgICAgIHRocm93IG5ldyBFcnJvcih1cGRhdGVkTWVzc2FnZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmV4dChtZXNzYWdlLCBvcHRpb25zKTsKICAgICAgfQogICAgfSk7CiAgICBfZXhwb3J0cy5taXNzaW5nT3B0aW9uc0RlcHJlY2F0aW9uID0gbWlzc2luZ09wdGlvbnNEZXByZWNhdGlvbiA9ICdXaGVuIGNhbGxpbmcgYGRlcHJlY2F0ZWAgeW91ICcgKyAnbXVzdCBwcm92aWRlIGFuIGBvcHRpb25zYCBoYXNoIGFzIHRoZSB0aGlyZCBwYXJhbWV0ZXIuICAnICsgJ2BvcHRpb25zYCBzaG91bGQgaW5jbHVkZSBgaWRgIGFuZCBgdW50aWxgIHByb3BlcnRpZXMuJzsKICAgIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9ICdXaGVuIGNhbGxpbmcgYGRlcHJlY2F0ZWAgeW91IG11c3QgcHJvdmlkZSBgaWRgIGluIG9wdGlvbnMuJzsKICAgIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zVW50aWxEZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zVW50aWxEZXByZWNhdGlvbiA9ICdXaGVuIGNhbGxpbmcgYGRlcHJlY2F0ZWAgeW91IG11c3QgcHJvdmlkZSBgdW50aWxgIGluIG9wdGlvbnMuJzsKICAgIC8qKgogICAgIEBtb2R1bGUgQGVtYmVyL2RlYnVnCiAgICAgQHB1YmxpYwogICAgICovCgogICAgLyoqCiAgICAgIERpc3BsYXkgYSBkZXByZWNhdGlvbiB3YXJuaW5nIHdpdGggdGhlIHByb3ZpZGVkIG1lc3NhZ2UgYW5kIGEgc3RhY2sgdHJhY2UKICAgICAgKENocm9tZSBhbmQgRmlyZWZveCBvbmx5KS4KICAgICAgICAgKiBJbiBhIHByb2R1Y3Rpb24gYnVpbGQsIHRoaXMgbWV0aG9kIGlzIGRlZmluZWQgYXMgYW4gZW1wdHkgZnVuY3Rpb24gKE5PUCkuCiAgICAgIFVzZXMgb2YgdGhpcyBtZXRob2QgaW4gRW1iZXIgaXRzZWxmIGFyZSBzdHJpcHBlZCBmcm9tIHRoZSBlbWJlci5wcm9kLmpzIGJ1aWxkLgogICAgICAgICBAbWV0aG9kIGRlcHJlY2F0ZQogICAgICBAZm9yIEBlbWJlci9kZWJ1ZwogICAgICBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBBIGRlc2NyaXB0aW9uIG9mIHRoZSBkZXByZWNhdGlvbi4KICAgICAgQHBhcmFtIHtCb29sZWFufSB0ZXN0IEEgYm9vbGVhbi4gSWYgZmFsc3ksIHRoZSBkZXByZWNhdGlvbiB3aWxsIGJlIGRpc3BsYXllZC4KICAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAgQHBhcmFtIHtTdHJpbmd9IG9wdGlvbnMuaWQgQSB1bmlxdWUgaWQgZm9yIHRoaXMgZGVwcmVjYXRpb24uIFRoZSBpZCBjYW4gYmUKICAgICAgICB1c2VkIGJ5IEVtYmVyIGRlYnVnZ2luZyB0b29scyB0byBjaGFuZ2UgdGhlIGJlaGF2aW9yIChyYWlzZSwgbG9nIG9yIHNpbGVuY2UpCiAgICAgICAgZm9yIHRoYXQgc3BlY2lmaWMgZGVwcmVjYXRpb24uIFRoZSBpZCBzaG91bGQgYmUgbmFtZXNwYWNlZCBieSBkb3RzLCBlLmcuCiAgICAgICAgInZpZXcuaGVscGVyLnNlbGVjdCIuCiAgICAgIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLnVudGlsIFRoZSB2ZXJzaW9uIG9mIEVtYmVyIHdoZW4gdGhpcyBkZXByZWNhdGlvbgogICAgICAgIHdhcm5pbmcgd2lsbCBiZSByZW1vdmVkLgogICAgICBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMudXJsXSBBbiBvcHRpb25hbCB1cmwgdG8gdGhlIHRyYW5zaXRpb24gZ3VpZGUgb24gdGhlCiAgICAgICAgZW1iZXJqcy5jb20gd2Vic2l0ZS4KICAgICAgQHN0YXRpYwogICAgICBAcHVibGljCiAgICAgIEBzaW5jZSAxLjAuMAogICAgKi8KCiAgICBkZXByZWNhdGUgPSBmdW5jdGlvbiBkZXByZWNhdGUobWVzc2FnZSwgdGVzdCwgb3B0aW9ucykgewogICAgICAoMCwgX2luZGV4LmFzc2VydCkobWlzc2luZ09wdGlvbnNEZXByZWNhdGlvbiwgQm9vbGVhbihvcHRpb25zICYmIChvcHRpb25zLmlkIHx8IG9wdGlvbnMudW50aWwpKSk7CiAgICAgICgwLCBfaW5kZXguYXNzZXJ0KShtaXNzaW5nT3B0aW9uc0lkRGVwcmVjYXRpb24sIEJvb2xlYW4ob3B0aW9ucy5pZCkpOwogICAgICAoMCwgX2luZGV4LmFzc2VydCkobWlzc2luZ09wdGlvbnNVbnRpbERlcHJlY2F0aW9uLCBCb29sZWFuKG9wdGlvbnMudW50aWwpKTsKICAgICAgKDAsIF9oYW5kbGVycy5pbnZva2UpKCdkZXByZWNhdGUnLCBtZXNzYWdlLCB0ZXN0LCBvcHRpb25zKTsKICAgIH07CiAgfQoKICB2YXIgX2RlZmF1bHQgPSBkZXByZWNhdGU7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvZGVidWcvbGliL2hhbmRsZXJzIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuaW52b2tlID0gX2V4cG9ydHMucmVnaXN0ZXJIYW5kbGVyID0gX2V4cG9ydHMuSEFORExFUlMgPSB2b2lkIDA7CiAgdmFyIEhBTkRMRVJTID0ge307CiAgX2V4cG9ydHMuSEFORExFUlMgPSBIQU5ETEVSUzsKCiAgdmFyIHJlZ2lzdGVySGFuZGxlciA9IGZ1bmN0aW9uIHJlZ2lzdGVySGFuZGxlcigpIHt9OwoKICBfZXhwb3J0cy5yZWdpc3RlckhhbmRsZXIgPSByZWdpc3RlckhhbmRsZXI7CgogIHZhciBpbnZva2UgPSBmdW5jdGlvbiBpbnZva2UoKSB7fTsKCiAgX2V4cG9ydHMuaW52b2tlID0gaW52b2tlOwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgX2V4cG9ydHMucmVnaXN0ZXJIYW5kbGVyID0gcmVnaXN0ZXJIYW5kbGVyID0gZnVuY3Rpb24gcmVnaXN0ZXJIYW5kbGVyKHR5cGUsIGNhbGxiYWNrKSB7CiAgICAgIHZhciBuZXh0SGFuZGxlciA9IEhBTkRMRVJTW3R5cGVdIHx8IGZ1bmN0aW9uICgpIHt9OwoKICAgICAgSEFORExFUlNbdHlwZV0gPSBmdW5jdGlvbiAobWVzc2FnZSwgb3B0aW9ucykgewogICAgICAgIGNhbGxiYWNrKG1lc3NhZ2UsIG9wdGlvbnMsIG5leHRIYW5kbGVyKTsKICAgICAgfTsKICAgIH07CgogICAgX2V4cG9ydHMuaW52b2tlID0gaW52b2tlID0gZnVuY3Rpb24gaW52b2tlKHR5cGUsIG1lc3NhZ2UsIHRlc3QsIG9wdGlvbnMpIHsKICAgICAgaWYgKHRlc3QpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBoYW5kbGVyRm9yVHlwZSA9IEhBTkRMRVJTW3R5cGVdOwoKICAgICAgaWYgKGhhbmRsZXJGb3JUeXBlKSB7CiAgICAgICAgaGFuZGxlckZvclR5cGUobWVzc2FnZSwgb3B0aW9ucyk7CiAgICAgIH0KICAgIH07CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvZGVidWcvbGliL3Rlc3RpbmciLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5pc1Rlc3RpbmcgPSBpc1Rlc3Rpbmc7CiAgX2V4cG9ydHMuc2V0VGVzdGluZyA9IHNldFRlc3Rpbmc7CiAgdmFyIHRlc3RpbmcgPSBmYWxzZTsKCiAgZnVuY3Rpb24gaXNUZXN0aW5nKCkgewogICAgcmV0dXJuIHRlc3Rpbmc7CiAgfQoKICBmdW5jdGlvbiBzZXRUZXN0aW5nKHZhbHVlKSB7CiAgICB0ZXN0aW5nID0gQm9vbGVhbih2YWx1ZSk7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvZGVidWcvbGliL3dhcm4iLCBbImV4cG9ydHMiLCAiQGVtYmVyL2RlYnVnL2luZGV4IiwgIkBlbWJlci9kZWJ1Zy9saWIvaGFuZGxlcnMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfaW5kZXgsIF9oYW5kbGVycykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMubWlzc2luZ09wdGlvbnNEZXByZWNhdGlvbiA9IF9leHBvcnRzLm1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9IF9leHBvcnRzLnJlZ2lzdGVySGFuZGxlciA9IF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIHZhciByZWdpc3RlckhhbmRsZXIgPSBmdW5jdGlvbiByZWdpc3RlckhhbmRsZXIoKSB7fTsKCiAgX2V4cG9ydHMucmVnaXN0ZXJIYW5kbGVyID0gcmVnaXN0ZXJIYW5kbGVyOwoKICB2YXIgd2FybiA9IGZ1bmN0aW9uIHdhcm4oKSB7fTsKCiAgdmFyIG1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb247CiAgX2V4cG9ydHMubWlzc2luZ09wdGlvbnNEZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb247CiAgdmFyIG1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbjsKICAvKioKICBAbW9kdWxlIEBlbWJlci9kZWJ1ZwogICovCgogIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbjsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIC8qKgogICAgICBBbGxvd3MgZm9yIHJ1bnRpbWUgcmVnaXN0cmF0aW9uIG9mIGhhbmRsZXIgZnVuY3Rpb25zIHRoYXQgb3ZlcnJpZGUgdGhlIGRlZmF1bHQgd2FybmluZyBiZWhhdmlvci4KICAgICAgV2FybmluZ3MgYXJlIGludm9rZWQgYnkgY2FsbHMgbWFkZSB0byBbQGVtYmVyL2RlYnVnL3dhcm5dKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvQGVtYmVyJTJGZGVidWcvbWV0aG9kcy93YXJuP2FuY2hvcj13YXJuKS4KICAgICAgVGhlIGZvbGxvd2luZyBleGFtcGxlIGRlbW9uc3RyYXRlcyBpdHMgdXNhZ2UgYnkgcmVnaXN0ZXJpbmcgYSBoYW5kbGVyIHRoYXQgZG9lcyBub3RoaW5nIG92ZXJyaWRpbmcgRW1iZXIncwogICAgICBkZWZhdWx0IHdhcm5pbmcgYmVoYXZpb3IuCiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IHsgcmVnaXN0ZXJXYXJuSGFuZGxlciB9IGZyb20gJ0BlbWJlci9kZWJ1Zyc7CiAgICAgICAgIC8vIG5leHQgaXMgbm90IGNhbGxlZCwgc28gbm8gd2FybmluZ3MgZ2V0IHRoZSBkZWZhdWx0IGJlaGF2aW9yCiAgICAgIHJlZ2lzdGVyV2FybkhhbmRsZXIoKCkgPT4ge30pOwogICAgICBgYGAKICAgICAgICAgVGhlIGhhbmRsZXIgZnVuY3Rpb24gdGFrZXMgdGhlIGZvbGxvd2luZyBhcmd1bWVudHM6CiAgICAgICAgIDx1bD4KICAgICAgICA8bGk+IDxjb2RlPm1lc3NhZ2U8L2NvZGU+IC0gVGhlIG1lc3NhZ2UgcmVjZWl2ZWQgZnJvbSB0aGUgd2FybiBjYWxsLiA8L2xpPgogICAgICAgIDxsaT4gPGNvZGU+b3B0aW9uczwvY29kZT4gLSBBbiBvYmplY3QgcGFzc2VkIGluIHdpdGggdGhlIHdhcm4gY2FsbCBjb250YWluaW5nIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gaW5jbHVkaW5nOjwvbGk+CiAgICAgICAgICA8dWw+CiAgICAgICAgICAgIDxsaT4gPGNvZGU+aWQ8L2NvZGU+IC0gQW4gaWQgb2YgdGhlIHdhcm5pbmcgaW4gdGhlIGZvcm0gb2YgPGNvZGU+cGFja2FnZS1uYW1lLnNwZWNpZmljLXdhcm5pbmc8L2NvZGU+LjwvbGk+CiAgICAgICAgICA8L3VsPgogICAgICAgIDxsaT4gPGNvZGU+bmV4dDwvY29kZT4gLSBBIGZ1bmN0aW9uIHRoYXQgY2FsbHMgaW50byB0aGUgcHJldmlvdXNseSByZWdpc3RlcmVkIGhhbmRsZXIuPC9saT4KICAgICAgPC91bD4KICAgICAgICAgQHB1YmxpYwogICAgICBAc3RhdGljCiAgICAgIEBtZXRob2QgcmVnaXN0ZXJXYXJuSGFuZGxlcgogICAgICBAZm9yIEBlbWJlci9kZWJ1ZwogICAgICBAcGFyYW0gaGFuZGxlciB7RnVuY3Rpb259IEEgZnVuY3Rpb24gdG8gaGFuZGxlIHdhcm5pbmdzLgogICAgICBAc2luY2UgMi4xLjAKICAgICovCiAgICBfZXhwb3J0cy5yZWdpc3RlckhhbmRsZXIgPSByZWdpc3RlckhhbmRsZXIgPSBmdW5jdGlvbiByZWdpc3RlckhhbmRsZXIoaGFuZGxlcikgewogICAgICAoMCwgX2hhbmRsZXJzLnJlZ2lzdGVySGFuZGxlcikoJ3dhcm4nLCBoYW5kbGVyKTsKICAgIH07CgogICAgcmVnaXN0ZXJIYW5kbGVyKGZ1bmN0aW9uIGxvZ1dhcm5pbmcobWVzc2FnZSkgewogICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovCiAgICAgIGNvbnNvbGUud2FybigiV0FSTklORzogIiArIG1lc3NhZ2UpOwogICAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWNvbnNvbGUgKi8KICAgIH0pOwogICAgX2V4cG9ydHMubWlzc2luZ09wdGlvbnNEZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb24gPSAnV2hlbiBjYWxsaW5nIGB3YXJuYCB5b3UgJyArICdtdXN0IHByb3ZpZGUgYW4gYG9wdGlvbnNgIGhhc2ggYXMgdGhlIHRoaXJkIHBhcmFtZXRlci4gICcgKyAnYG9wdGlvbnNgIHNob3VsZCBpbmNsdWRlIGFuIGBpZGAgcHJvcGVydHkuJzsKICAgIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9ICdXaGVuIGNhbGxpbmcgYHdhcm5gIHlvdSBtdXN0IHByb3ZpZGUgYGlkYCBpbiBvcHRpb25zLic7CiAgICAvKioKICAgICAgRGlzcGxheSBhIHdhcm5pbmcgd2l0aCB0aGUgcHJvdmlkZWQgbWVzc2FnZS4KICAgICAgICAgKiBJbiBhIHByb2R1Y3Rpb24gYnVpbGQsIHRoaXMgbWV0aG9kIGlzIGRlZmluZWQgYXMgYW4gZW1wdHkgZnVuY3Rpb24gKE5PUCkuCiAgICAgIFVzZXMgb2YgdGhpcyBtZXRob2QgaW4gRW1iZXIgaXRzZWxmIGFyZSBzdHJpcHBlZCBmcm9tIHRoZSBlbWJlci5wcm9kLmpzIGJ1aWxkLgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCB7IHdhcm4gfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICBpbXBvcnQgdG9tc3RlckNvdW50IGZyb20gJy4vdG9tc3Rlci1jb3VudGVyJzsgLy8gYSBtb2R1bGUgaW4gbXkgcHJvamVjdAogICAgICAgICAvLyBMb2cgYSB3YXJuaW5nIGlmIHdlIGhhdmUgbW9yZSB0aGFuIDMgdG9tc3RlcnMKICAgICAgd2FybignVG9vIG1hbnkgdG9tc3RlcnMhJywgdG9tc3RlckNvdW50IDw9IDMsIHsKICAgICAgICBpZDogJ2VtYmVyLWRlYnVnLnRvby1tYW55LXRvbXN0ZXJzJwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIEBtZXRob2Qgd2FybgogICAgICBAZm9yIEBlbWJlci9kZWJ1ZwogICAgICBAc3RhdGljCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIEEgd2FybmluZyB0byBkaXNwbGF5LgogICAgICBAcGFyYW0ge0Jvb2xlYW59IHRlc3QgQW4gb3B0aW9uYWwgYm9vbGVhbi4gSWYgZmFsc3ksIHRoZSB3YXJuaW5nCiAgICAgICAgd2lsbCBiZSBkaXNwbGF5ZWQuCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIEFuIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIHBhc3MgYSB1bmlxdWUKICAgICAgICBgaWRgIGZvciB0aGlzIHdhcm5pbmcuICBUaGUgYGlkYCBjYW4gYmUgdXNlZCBieSBFbWJlciBkZWJ1Z2dpbmcgdG9vbHMKICAgICAgICB0byBjaGFuZ2UgdGhlIGJlaGF2aW9yIChyYWlzZSwgbG9nLCBvciBzaWxlbmNlKSBmb3IgdGhhdCBzcGVjaWZpYyB3YXJuaW5nLgogICAgICAgIFRoZSBgaWRgIHNob3VsZCBiZSBuYW1lc3BhY2VkIGJ5IGRvdHMsIGUuZy4gImVtYmVyLWRlYnVnLmZlYXR1cmUtZmxhZy13aXRoLWZlYXR1cmVzLXN0cmlwcGVkIgogICAgICBAcHVibGljCiAgICAgIEBzaW5jZSAxLjAuMAogICAgKi8KCiAgICB3YXJuID0gZnVuY3Rpb24gd2FybihtZXNzYWdlLCB0ZXN0LCBvcHRpb25zKSB7CiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmIHR5cGVvZiB0ZXN0ID09PSAnb2JqZWN0JykgewogICAgICAgIG9wdGlvbnMgPSB0ZXN0OwogICAgICAgIHRlc3QgPSBmYWxzZTsKICAgICAgfQoKICAgICAgKDAsIF9pbmRleC5hc3NlcnQpKG1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb24sIEJvb2xlYW4ob3B0aW9ucykpOwogICAgICAoMCwgX2luZGV4LmFzc2VydCkobWlzc2luZ09wdGlvbnNJZERlcHJlY2F0aW9uLCBCb29sZWFuKG9wdGlvbnMgJiYgb3B0aW9ucy5pZCkpOwogICAgICAoMCwgX2hhbmRsZXJzLmludm9rZSkoJ3dhcm4nLCBtZXNzYWdlLCB0ZXN0LCBvcHRpb25zKTsKICAgIH07CiAgfQoKICB2YXIgX2RlZmF1bHQgPSB3YXJuOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMvaW5kZXgiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5NT1VTRV9FTlRFUl9MRUFWRV9NT1ZFX0VWRU5UUyA9IF9leHBvcnRzLkZVTkNUSU9OX1BST1RPVFlQRV9FWFRFTlNJT05TID0gX2V4cG9ydHMuQVBQX0NUUkxfUk9VVEVSX1BST1BTID0gX2V4cG9ydHMuQUxJQVNfTUVUSE9EID0gX2V4cG9ydHMuSlFVRVJZX0lOVEVHUkFUSU9OID0gX2V4cG9ydHMuQ09NUE9ORU5UX01BTkFHRVJfU1RSSU5HX0xPT0tVUCA9IF9leHBvcnRzLlJPVVRFUl9FVkVOVFMgPSBfZXhwb3J0cy5NRVJHRSA9IF9leHBvcnRzLkxPR0dFUiA9IF9leHBvcnRzLkVNQkVSX0VYVEVORF9QUk9UT1RZUEVTID0gX2V4cG9ydHMuU0VORF9BQ1RJT04gPSB2b2lkIDA7CgogIC8qIGVzbGludC1kaXNhYmxlIG5vLWltcGxpY2l0LWNvZXJjaW9uICovCiAgLy8gVGhlc2UgdmVyc2lvbnMgc2hvdWxkIGJlIHRoZSB2ZXJzaW9uIHRoYXQgdGhlIGRlcHJlY2F0aW9uIHdhcyBfaW50cm9kdWNlZF8sCiAgLy8gbm90IHRoZSB2ZXJzaW9uIHRoYXQgdGhlIGZlYXR1cmUgd2lsbCBiZSByZW1vdmVkLgogIHZhciBTRU5EX0FDVElPTiA9ICEhJzMuNC4wJzsKICBfZXhwb3J0cy5TRU5EX0FDVElPTiA9IFNFTkRfQUNUSU9OOwogIHZhciBFTUJFUl9FWFRFTkRfUFJPVE9UWVBFUyA9ICEhJzMuMi4wLWJldGEuNSc7CiAgX2V4cG9ydHMuRU1CRVJfRVhURU5EX1BST1RPVFlQRVMgPSBFTUJFUl9FWFRFTkRfUFJPVE9UWVBFUzsKICB2YXIgTE9HR0VSID0gISEnMy4yLjAtYmV0YS4xJzsKICBfZXhwb3J0cy5MT0dHRVIgPSBMT0dHRVI7CiAgdmFyIE1FUkdFID0gISEnMy42LjAtYmV0YS4xJzsKICBfZXhwb3J0cy5NRVJHRSA9IE1FUkdFOwogIHZhciBST1VURVJfRVZFTlRTID0gISEnNC4wLjAnOwogIF9leHBvcnRzLlJPVVRFUl9FVkVOVFMgPSBST1VURVJfRVZFTlRTOwogIHZhciBDT01QT05FTlRfTUFOQUdFUl9TVFJJTkdfTE9PS1VQID0gISEnMy44LjAnOwogIF9leHBvcnRzLkNPTVBPTkVOVF9NQU5BR0VSX1NUUklOR19MT09LVVAgPSBDT01QT05FTlRfTUFOQUdFUl9TVFJJTkdfTE9PS1VQOwogIHZhciBKUVVFUllfSU5URUdSQVRJT04gPSAhISczLjkuMCc7CiAgX2V4cG9ydHMuSlFVRVJZX0lOVEVHUkFUSU9OID0gSlFVRVJZX0lOVEVHUkFUSU9OOwogIHZhciBBTElBU19NRVRIT0QgPSAhISczLjkuMCc7CiAgX2V4cG9ydHMuQUxJQVNfTUVUSE9EID0gQUxJQVNfTUVUSE9EOwogIHZhciBBUFBfQ1RSTF9ST1VURVJfUFJPUFMgPSAhISczLjEwLjAtYmV0YS4xJzsKICBfZXhwb3J0cy5BUFBfQ1RSTF9ST1VURVJfUFJPUFMgPSBBUFBfQ1RSTF9ST1VURVJfUFJPUFM7CiAgdmFyIEZVTkNUSU9OX1BST1RPVFlQRV9FWFRFTlNJT05TID0gISEnMy4xMS4wLWJldGEuMSc7CiAgX2V4cG9ydHMuRlVOQ1RJT05fUFJPVE9UWVBFX0VYVEVOU0lPTlMgPSBGVU5DVElPTl9QUk9UT1RZUEVfRVhURU5TSU9OUzsKICB2YXIgTU9VU0VfRU5URVJfTEVBVkVfTU9WRV9FVkVOVFMgPSAhISczLjEzLjAtYmV0YS4xJzsKICBfZXhwb3J0cy5NT1VTRV9FTlRFUl9MRUFWRV9NT1ZFX0VWRU5UUyA9IE1PVVNFX0VOVEVSX0xFQVZFX01PVkVfRVZFTlRTOwp9KTsKZGVmaW5lKCJAZW1iZXIvZW5naW5lL2luZGV4IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci9lbmdpbmUvbGliL2VuZ2luZS1wYXJlbnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyL2NvbnRyb2xsZXIiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSIsICJAZW1iZXIvLWludGVybmFscy9jb250YWluZXIiLCAiZGFnLW1hcCIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2FwcGxpY2F0aW9uL2dsb2JhbHMtcmVzb2x2ZXIiLCAiQGVtYmVyL2VuZ2luZS9pbnN0YW5jZSIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nIiwgIkBlbWJlci8taW50ZXJuYWxzL2V4dGVuc2lvbi1zdXBwb3J0IiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzIiwgIkBlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX2VuZ2luZVBhcmVudCwgX3V0aWxzLCBfY29udHJvbGxlciwgX3J1bnRpbWUsIF9jb250YWluZXIsIF9kYWdNYXAsIF9kZWJ1ZywgX21ldGFsLCBfZ2xvYmFsc1Jlc29sdmVyLCBfaW5zdGFuY2UsIF9yb3V0aW5nLCBfZXh0ZW5zaW9uU3VwcG9ydCwgX3ZpZXdzLCBfZ2xpbW1lcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ2V0RW5naW5lUGFyZW50IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2VuZ2luZVBhcmVudC5nZXRFbmdpbmVQYXJlbnQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0RW5naW5lUGFyZW50IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2VuZ2luZVBhcmVudC5zZXRFbmdpbmVQYXJlbnQ7CiAgICB9CiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0MigpIHsKICAgIHZhciBkYXRhID0gKDAsIF9lbWJlckJhYmVsLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlKShbIi1idWNrZXQtY2FjaGU6bWFpbiJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3QyID0gZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0MigpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0KCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsiLWJ1Y2tldC1jYWNoZTptYWluIl0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdCgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gcHJvcHMob2JqKSB7CiAgICB2YXIgcHJvcGVydGllcyA9IFtdOwoKICAgIGZvciAodmFyIGtleSBpbiBvYmopIHsKICAgICAgcHJvcGVydGllcy5wdXNoKGtleSk7CiAgICB9CgogICAgcmV0dXJuIHByb3BlcnRpZXM7CiAgfQogIC8qKgogIEBtb2R1bGUgQGVtYmVyL2VuZ2luZQogICovCgogIC8qKgogICAgVGhlIGBFbmdpbmVgIGNsYXNzIGNvbnRhaW5zIGNvcmUgZnVuY3Rpb25hbGl0eSBmb3IgYm90aCBhcHBsaWNhdGlvbnMgYW5kCiAgICBlbmdpbmVzLgogIAogICAgRWFjaCBlbmdpbmUgbWFuYWdlcyBhIHJlZ2lzdHJ5IHRoYXQncyB1c2VkIGZvciBkZXBlbmRlbmN5IGluamVjdGlvbiBhbmQKICAgIGV4cG9zZWQgdGhyb3VnaCBgUmVnaXN0cnlQcm94eWAuCiAgCiAgICBFbmdpbmVzIGFsc28gbWFuYWdlIGluaXRpYWxpemVycyBhbmQgaW5zdGFuY2UgaW5pdGlhbGl6ZXJzLgogIAogICAgRW5naW5lcyBjYW4gc3Bhd24gYEVuZ2luZUluc3RhbmNlYCBpbnN0YW5jZXMgdmlhIGBidWlsZEluc3RhbmNlKClgLgogIAogICAgQGNsYXNzIEVuZ2luZQogICAgQGV4dGVuZHMgRW1iZXIuTmFtZXNwYWNlCiAgICBAdXNlcyBSZWdpc3RyeVByb3h5CiAgICBAcHVibGljCiAgKi8KCgogIHZhciBFbmdpbmUgPSBfcnVudGltZS5OYW1lc3BhY2UuZXh0ZW5kKF9ydW50aW1lLlJlZ2lzdHJ5UHJveHlNaXhpbiwgewogICAgaW5pdDogZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIHRoaXMuYnVpbGRSZWdpc3RyeSgpOwogICAgfSwKCiAgICAvKioKICAgICAgQSBwcml2YXRlIGZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIGFuIGVuZ2luZSdzIGluaXRpYWxpemVycyBoYXZlIHJ1biB5ZXQuCiAgICAgICBAcHJpdmF0ZQogICAgICBAcHJvcGVydHkgX2luaXRpYWxpemVyc1JhbgogICAgKi8KICAgIF9pbml0aWFsaXplcnNSYW46IGZhbHNlLAoKICAgIC8qKgogICAgICBFbnN1cmUgdGhhdCBpbml0aWFsaXplcnMgYXJlIHJ1biBvbmNlLCBhbmQgb25seSBvbmNlLCBwZXIgZW5naW5lLgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBlbnN1cmVJbml0aWFsaXplcnMKICAgICovCiAgICBlbnN1cmVJbml0aWFsaXplcnM6IGZ1bmN0aW9uIGVuc3VyZUluaXRpYWxpemVycygpIHsKICAgICAgaWYgKCF0aGlzLl9pbml0aWFsaXplcnNSYW4pIHsKICAgICAgICB0aGlzLnJ1bkluaXRpYWxpemVycygpOwogICAgICAgIHRoaXMuX2luaXRpYWxpemVyc1JhbiA9IHRydWU7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIENyZWF0ZSBhbiBFbmdpbmVJbnN0YW5jZSBmb3IgdGhpcyBlbmdpbmUuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgYnVpbGRJbnN0YW5jZQogICAgICBAcmV0dXJuIHtFbmdpbmVJbnN0YW5jZX0gdGhlIGVuZ2luZSBpbnN0YW5jZQogICAgKi8KICAgIGJ1aWxkSW5zdGFuY2U6IGZ1bmN0aW9uIGJ1aWxkSW5zdGFuY2Uob3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICB0aGlzLmVuc3VyZUluaXRpYWxpemVycygpOwogICAgICBvcHRpb25zLmJhc2UgPSB0aGlzOwogICAgICByZXR1cm4gX2luc3RhbmNlLmRlZmF1bHQuY3JlYXRlKG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICAgQnVpbGQgYW5kIGNvbmZpZ3VyZSB0aGUgcmVnaXN0cnkgZm9yIHRoZSBjdXJyZW50IGVuZ2luZS4KICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgYnVpbGRSZWdpc3RyeQogICAgICBAcmV0dXJuIHtFbWJlci5SZWdpc3RyeX0gdGhlIGNvbmZpZ3VyZWQgcmVnaXN0cnkKICAgICovCiAgICBidWlsZFJlZ2lzdHJ5OiBmdW5jdGlvbiBidWlsZFJlZ2lzdHJ5KCkgewogICAgICB2YXIgcmVnaXN0cnkgPSB0aGlzLl9fcmVnaXN0cnlfXyA9IHRoaXMuY29uc3RydWN0b3IuYnVpbGRSZWdpc3RyeSh0aGlzKTsKICAgICAgcmV0dXJuIHJlZ2lzdHJ5OwogICAgfSwKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBpbml0aWFsaXplcgogICAgKi8KICAgIGluaXRpYWxpemVyOiBmdW5jdGlvbiBpbml0aWFsaXplcihvcHRpb25zKSB7CiAgICAgIHRoaXMuY29uc3RydWN0b3IuaW5pdGlhbGl6ZXIob3B0aW9ucyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGluc3RhbmNlSW5pdGlhbGl6ZXIKICAgICovCiAgICBpbnN0YW5jZUluaXRpYWxpemVyOiBmdW5jdGlvbiBpbnN0YW5jZUluaXRpYWxpemVyKG9wdGlvbnMpIHsKICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5pbnN0YW5jZUluaXRpYWxpemVyKG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBydW5Jbml0aWFsaXplcnMKICAgICovCiAgICBydW5Jbml0aWFsaXplcnM6IGZ1bmN0aW9uIHJ1bkluaXRpYWxpemVycygpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHRoaXMuX3J1bkluaXRpYWxpemVyKCdpbml0aWFsaXplcnMnLCBmdW5jdGlvbiAobmFtZSwgaW5pdGlhbGl6ZXIpIHsKICAgICAgICAoZmFsc2UgJiYgIShCb29sZWFuKGluaXRpYWxpemVyKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJObyBhcHBsaWNhdGlvbiBpbml0aWFsaXplciBuYW1lZCAnIiArIG5hbWUgKyAiJyIsIEJvb2xlYW4oaW5pdGlhbGl6ZXIpKSk7CiAgICAgICAgaW5pdGlhbGl6ZXIuaW5pdGlhbGl6ZShfdGhpcyk7CiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgQHNpbmNlIDEuMTIuMAogICAgICBAbWV0aG9kIHJ1bkluc3RhbmNlSW5pdGlhbGl6ZXJzCiAgICAqLwogICAgcnVuSW5zdGFuY2VJbml0aWFsaXplcnM6IGZ1bmN0aW9uIHJ1bkluc3RhbmNlSW5pdGlhbGl6ZXJzKGluc3RhbmNlKSB7CiAgICAgIHRoaXMuX3J1bkluaXRpYWxpemVyKCdpbnN0YW5jZUluaXRpYWxpemVycycsIGZ1bmN0aW9uIChuYW1lLCBpbml0aWFsaXplcikgewogICAgICAgIChmYWxzZSAmJiAhKEJvb2xlYW4oaW5pdGlhbGl6ZXIpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIk5vIGluc3RhbmNlIGluaXRpYWxpemVyIG5hbWVkICciICsgbmFtZSArICInIiwgQm9vbGVhbihpbml0aWFsaXplcikpKTsKICAgICAgICBpbml0aWFsaXplci5pbml0aWFsaXplKGluc3RhbmNlKTsKICAgICAgfSk7CiAgICB9LAogICAgX3J1bkluaXRpYWxpemVyOiBmdW5jdGlvbiBfcnVuSW5pdGlhbGl6ZXIoYnVja2V0TmFtZSwgY2IpIHsKICAgICAgdmFyIGluaXRpYWxpemVyc0J5TmFtZSA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLmNvbnN0cnVjdG9yLCBidWNrZXROYW1lKTsKICAgICAgdmFyIGluaXRpYWxpemVycyA9IHByb3BzKGluaXRpYWxpemVyc0J5TmFtZSk7CiAgICAgIHZhciBncmFwaCA9IG5ldyBfZGFnTWFwLmRlZmF1bHQoKTsKICAgICAgdmFyIGluaXRpYWxpemVyOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbml0aWFsaXplcnMubGVuZ3RoOyBpKyspIHsKICAgICAgICBpbml0aWFsaXplciA9IGluaXRpYWxpemVyc0J5TmFtZVtpbml0aWFsaXplcnNbaV1dOwogICAgICAgIGdyYXBoLmFkZChpbml0aWFsaXplci5uYW1lLCBpbml0aWFsaXplciwgaW5pdGlhbGl6ZXIuYmVmb3JlLCBpbml0aWFsaXplci5hZnRlcik7CiAgICAgIH0KCiAgICAgIGdyYXBoLnRvcHNvcnQoY2IpOwogICAgfQogIH0pOwoKICBFbmdpbmUucmVvcGVuQ2xhc3MoewogICAgaW5pdGlhbGl6ZXJzOiBPYmplY3QuY3JlYXRlKG51bGwpLAogICAgaW5zdGFuY2VJbml0aWFsaXplcnM6IE9iamVjdC5jcmVhdGUobnVsbCksCgogICAgLyoqCiAgICAgIFRoZSBnb2FsIG9mIGluaXRpYWxpemVycyBzaG91bGQgYmUgdG8gcmVnaXN0ZXIgZGVwZW5kZW5jaWVzIGFuZCBpbmplY3Rpb25zLgogICAgICBUaGlzIHBoYXNlIHJ1bnMgb25jZS4gQmVjYXVzZSB0aGVzZSBpbml0aWFsaXplcnMgbWF5IGxvYWQgY29kZSwgdGhleSBhcmUKICAgICAgYWxsb3dlZCB0byBkZWZlciBhcHBsaWNhdGlvbiByZWFkaW5lc3MgYW5kIGFkdmFuY2UgaXQuIElmIHlvdSBuZWVkIHRvIGFjY2VzcwogICAgICB0aGUgY29udGFpbmVyIG9yIHN0b3JlIHlvdSBzaG91bGQgdXNlIGFuIEluc3RhbmNlSW5pdGlhbGl6ZXIgdGhhdCB3aWxsIGJlIHJ1bgogICAgICBhZnRlciBhbGwgaW5pdGlhbGl6ZXJzIGFuZCB0aGVyZWZvcmUgYWZ0ZXIgYWxsIGNvZGUgaXMgbG9hZGVkIGFuZCB0aGUgYXBwIGlzCiAgICAgIHJlYWR5LgogICAgICAgSW5pdGlhbGl6ZXIgcmVjZWl2ZXMgYW4gb2JqZWN0IHdoaWNoIGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXM6CiAgICAgIGBuYW1lYCwgYGJlZm9yZWAsIGBhZnRlcmAsIGBpbml0aWFsaXplYC4gVGhlIG9ubHkgcmVxdWlyZWQgYXR0cmlidXRlIGlzCiAgICAgIGBpbml0aWFsaXplYCwgYWxsIG90aGVycyBhcmUgb3B0aW9uYWwuCiAgICAgICAqIGBuYW1lYCBhbGxvd3MgeW91IHRvIHNwZWNpZnkgdW5kZXIgd2hpY2ggbmFtZSB0aGUgaW5pdGlhbGl6ZXIgaXMgcmVnaXN0ZXJlZC4KICAgICAgVGhpcyBtdXN0IGJlIGEgdW5pcXVlIG5hbWUsIGFzIHRyeWluZyB0byByZWdpc3RlciB0d28gaW5pdGlhbGl6ZXJzIHdpdGggdGhlCiAgICAgIHNhbWUgbmFtZSB3aWxsIHJlc3VsdCBpbiBhbiBlcnJvci4KICAgICAgIGBgYGFwcC9pbml0aWFsaXplci9uYW1lZC1pbml0aWFsaXplci5qcwogICAgICBpbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJ0BlbWJlci9kZWJ1Zyc7CiAgICAgICBleHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHsKICAgICAgICBkZWJ1ZygnUnVubmluZyBuYW1lZEluaXRpYWxpemVyIScpOwogICAgICB9CiAgICAgICBleHBvcnQgZGVmYXVsdCB7CiAgICAgICAgbmFtZTogJ25hbWVkLWluaXRpYWxpemVyJywKICAgICAgICBpbml0aWFsaXplCiAgICAgIH07CiAgICAgIGBgYAogICAgICAgKiBgYmVmb3JlYCBhbmQgYGFmdGVyYCBhcmUgdXNlZCB0byBlbnN1cmUgdGhhdCB0aGlzIGluaXRpYWxpemVyIGlzIHJhbiBwcmlvcgogICAgICBvciBhZnRlciB0aGUgb25lIGlkZW50aWZpZWQgYnkgdGhlIHZhbHVlLiBUaGlzIHZhbHVlIGNhbiBiZSBhIHNpbmdsZSBzdHJpbmcKICAgICAgb3IgYW4gYXJyYXkgb2Ygc3RyaW5ncywgcmVmZXJlbmNpbmcgdGhlIGBuYW1lYCBvZiBvdGhlciBpbml0aWFsaXplcnMuCiAgICAgICBBbiBleGFtcGxlIG9mIG9yZGVyaW5nIGluaXRpYWxpemVycywgd2UgY3JlYXRlIGFuIGluaXRpYWxpemVyIG5hbWVkIGBmaXJzdGA6CiAgICAgICBgYGBhcHAvaW5pdGlhbGl6ZXIvZmlyc3QuanMKICAgICAgaW1wb3J0IHsgZGVidWcgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7CiAgICAgICAgZGVidWcoJ0ZpcnN0IGluaXRpYWxpemVyIScpOwogICAgICB9CiAgICAgICBleHBvcnQgZGVmYXVsdCB7CiAgICAgICAgbmFtZTogJ2ZpcnN0JywKICAgICAgICBpbml0aWFsaXplCiAgICAgIH07CiAgICAgIGBgYAogICAgICAgYGBgYmFzaAogICAgICAvLyBERUJVRzogRmlyc3QgaW5pdGlhbGl6ZXIhCiAgICAgIGBgYAogICAgICAgV2UgYWRkIGFub3RoZXIgaW5pdGlhbGl6ZXIgbmFtZWQgYHNlY29uZGAsIHNwZWNpZnlpbmcgdGhhdCBpdCBzaG91bGQgcnVuCiAgICAgIGFmdGVyIHRoZSBpbml0aWFsaXplciBuYW1lZCBgZmlyc3RgOgogICAgICAgYGBgYXBwL2luaXRpYWxpemVyL3NlY29uZC5qcwogICAgICBpbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJ0BlbWJlci9kZWJ1Zyc7CiAgICAgICBleHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHsKICAgICAgICBkZWJ1ZygnU2Vjb25kIGluaXRpYWxpemVyIScpOwogICAgICB9CiAgICAgICBleHBvcnQgZGVmYXVsdCB7CiAgICAgICAgbmFtZTogJ3NlY29uZCcsCiAgICAgICAgYWZ0ZXI6ICdmaXJzdCcsCiAgICAgICAgaW5pdGlhbGl6ZQogICAgICB9OwogICAgICBgYGAKICAgICAgIGBgYAogICAgICAvLyBERUJVRzogRmlyc3QgaW5pdGlhbGl6ZXIhCiAgICAgIC8vIERFQlVHOiBTZWNvbmQgaW5pdGlhbGl6ZXIhCiAgICAgIGBgYAogICAgICAgQWZ0ZXJ3YXJkcyB3ZSBhZGQgYSBmdXJ0aGVyIGluaXRpYWxpemVyIG5hbWVkIGBwcmVgLCB0aGlzIHRpbWUgc3BlY2lmeWluZwogICAgICB0aGF0IGl0IHNob3VsZCBydW4gYmVmb3JlIHRoZSBpbml0aWFsaXplciBuYW1lZCBgZmlyc3RgOgogICAgICAgYGBgYXBwL2luaXRpYWxpemVyL3ByZS5qcwogICAgICBpbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJ0BlbWJlci9kZWJ1Zyc7CiAgICAgICBleHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHsKICAgICAgICBkZWJ1ZygnUHJlIGluaXRpYWxpemVyIScpOwogICAgICB9CiAgICAgICBleHBvcnQgZGVmYXVsdCB7CiAgICAgICAgbmFtZTogJ3ByZScsCiAgICAgICAgYmVmb3JlOiAnZmlyc3QnLAogICAgICAgIGluaXRpYWxpemUKICAgICAgfTsKICAgICAgYGBgCiAgICAgICBgYGBiYXNoCiAgICAgIC8vIERFQlVHOiBQcmUgaW5pdGlhbGl6ZXIhCiAgICAgIC8vIERFQlVHOiBGaXJzdCBpbml0aWFsaXplciEKICAgICAgLy8gREVCVUc6IFNlY29uZCBpbml0aWFsaXplciEKICAgICAgYGBgCiAgICAgICBGaW5hbGx5IHdlIGFkZCBhbiBpbml0aWFsaXplciBuYW1lZCBgcG9zdGAsIHNwZWNpZnlpbmcgaXQgc2hvdWxkIHJ1biBhZnRlcgogICAgICBib3RoIHRoZSBgZmlyc3RgIGFuZCB0aGUgYHNlY29uZGAgaW5pdGlhbGl6ZXJzOgogICAgICAgYGBgYXBwL2luaXRpYWxpemVyL3Bvc3QuanMKICAgICAgaW1wb3J0IHsgZGVidWcgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7CiAgICAgICAgZGVidWcoJ1Bvc3QgaW5pdGlhbGl6ZXIhJyk7CiAgICAgIH0KICAgICAgIGV4cG9ydCBkZWZhdWx0IHsKICAgICAgICBuYW1lOiAncG9zdCcsCiAgICAgICAgYWZ0ZXI6IFsnZmlyc3QnLCAnc2Vjb25kJ10sCiAgICAgICAgaW5pdGlhbGl6ZQogICAgICB9OwogICAgICBgYGAKICAgICAgIGBgYGJhc2gKICAgICAgLy8gREVCVUc6IFByZSBpbml0aWFsaXplciEKICAgICAgLy8gREVCVUc6IEZpcnN0IGluaXRpYWxpemVyIQogICAgICAvLyBERUJVRzogU2Vjb25kIGluaXRpYWxpemVyIQogICAgICAvLyBERUJVRzogUG9zdCBpbml0aWFsaXplciEKICAgICAgYGBgCiAgICAgICAqIGBpbml0aWFsaXplYCBpcyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgcmVjZWl2ZXMgb25lIGFyZ3VtZW50LAogICAgICAgIGBhcHBsaWNhdGlvbmAsIG9uIHdoaWNoIHlvdSBjYW4gb3BlcmF0ZS4KICAgICAgIEV4YW1wbGUgb2YgdXNpbmcgYGFwcGxpY2F0aW9uYCB0byByZWdpc3RlciBhbiBhZGFwdGVyOgogICAgICAgYGBgYXBwL2luaXRpYWxpemVyL2FwaS1hZGFwdGVyLmpzCiAgICAgIGltcG9ydCBBcGlBZGFwdGVyIGZyb20gJy4uL3V0aWxzL2FwaS1hZGFwdGVyJzsKICAgICAgIGV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplKGFwcGxpY2F0aW9uKSB7CiAgICAgICAgYXBwbGljYXRpb24ucmVnaXN0ZXIoJ2FwaS1hZGFwdGVyOm1haW4nLCBBcGlBZGFwdGVyKTsKICAgICAgfQogICAgICAgZXhwb3J0IGRlZmF1bHQgewogICAgICAgIG5hbWU6ICdwb3N0JywKICAgICAgICBhZnRlcjogWydmaXJzdCcsICdzZWNvbmQnXSwKICAgICAgICBpbml0aWFsaXplCiAgICAgIH07CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBpbml0aWFsaXplcgogICAgICBAcGFyYW0gaW5pdGlhbGl6ZXIge09iamVjdH0KICAgICAgQHB1YmxpYwogICAgKi8KICAgIGluaXRpYWxpemVyOiBidWlsZEluaXRpYWxpemVyTWV0aG9kKCdpbml0aWFsaXplcnMnLCAnaW5pdGlhbGl6ZXInKSwKCiAgICAvKioKICAgICAgSW5zdGFuY2UgaW5pdGlhbGl6ZXJzIHJ1biBhZnRlciBhbGwgaW5pdGlhbGl6ZXJzIGhhdmUgcnVuLiBCZWNhdXNlCiAgICAgIGluc3RhbmNlIGluaXRpYWxpemVycyBydW4gYWZ0ZXIgdGhlIGFwcCBpcyBmdWxseSBzZXQgdXAuIFdlIGhhdmUgYWNjZXNzCiAgICAgIHRvIHRoZSBzdG9yZSwgY29udGFpbmVyLCBhbmQgb3RoZXIgaXRlbXMuIEhvd2V2ZXIsIHRoZXNlIGluaXRpYWxpemVycyBydW4KICAgICAgYWZ0ZXIgY29kZSBoYXMgbG9hZGVkIGFuZCBhcmUgbm90IGFsbG93ZWQgdG8gZGVmZXIgcmVhZGluZXNzLgogICAgICAgSW5zdGFuY2UgaW5pdGlhbGl6ZXIgcmVjZWl2ZXMgYW4gb2JqZWN0IHdoaWNoIGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXM6CiAgICAgIGBuYW1lYCwgYGJlZm9yZWAsIGBhZnRlcmAsIGBpbml0aWFsaXplYC4gVGhlIG9ubHkgcmVxdWlyZWQgYXR0cmlidXRlIGlzCiAgICAgIGBpbml0aWFsaXplYCwgYWxsIG90aGVycyBhcmUgb3B0aW9uYWwuCiAgICAgICAqIGBuYW1lYCBhbGxvd3MgeW91IHRvIHNwZWNpZnkgdW5kZXIgd2hpY2ggbmFtZSB0aGUgaW5zdGFuY2VJbml0aWFsaXplciBpcwogICAgICByZWdpc3RlcmVkLiBUaGlzIG11c3QgYmUgYSB1bmlxdWUgbmFtZSwgYXMgdHJ5aW5nIHRvIHJlZ2lzdGVyIHR3bwogICAgICBpbnN0YW5jZUluaXRpYWxpemVyIHdpdGggdGhlIHNhbWUgbmFtZSB3aWxsIHJlc3VsdCBpbiBhbiBlcnJvci4KICAgICAgIGBgYGFwcC9pbml0aWFsaXplci9uYW1lZC1pbnN0YW5jZS1pbml0aWFsaXplci5qcwogICAgICBpbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJ0BlbWJlci9kZWJ1Zyc7CiAgICAgICBleHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHsKICAgICAgICBkZWJ1ZygnUnVubmluZyBuYW1lZC1pbnN0YW5jZS1pbml0aWFsaXplciEnKTsKICAgICAgfQogICAgICAgZXhwb3J0IGRlZmF1bHQgewogICAgICAgIG5hbWU6ICduYW1lZC1pbnN0YW5jZS1pbml0aWFsaXplcicsCiAgICAgICAgaW5pdGlhbGl6ZQogICAgICB9OwogICAgICBgYGAKICAgICAgICogYGJlZm9yZWAgYW5kIGBhZnRlcmAgYXJlIHVzZWQgdG8gZW5zdXJlIHRoYXQgdGhpcyBpbml0aWFsaXplciBpcyByYW4gcHJpb3IKICAgICAgb3IgYWZ0ZXIgdGhlIG9uZSBpZGVudGlmaWVkIGJ5IHRoZSB2YWx1ZS4gVGhpcyB2YWx1ZSBjYW4gYmUgYSBzaW5nbGUgc3RyaW5nCiAgICAgIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MsIHJlZmVyZW5jaW5nIHRoZSBgbmFtZWAgb2Ygb3RoZXIgaW5pdGlhbGl6ZXJzLgogICAgICAgKiBTZWUgQXBwbGljYXRpb24uaW5pdGlhbGl6ZXIgZm9yIGRpc2N1c3Npb24gb24gdGhlIHVzYWdlIG9mIGJlZm9yZQogICAgICBhbmQgYWZ0ZXIuCiAgICAgICBFeGFtcGxlIGluc3RhbmNlSW5pdGlhbGl6ZXIgdG8gcHJlbG9hZCBkYXRhIGludG8gdGhlIHN0b3JlLgogICAgICAgYGBgYXBwL2luaXRpYWxpemVyL3ByZWxvYWQtZGF0YS5qcwogICAgICBpbXBvcnQgJCBmcm9tICdqcXVlcnknOwogICAgICAgZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemUoYXBwbGljYXRpb24pIHsKICAgICAgICAgIHZhciB1c2VyQ29uZmlnLCB1c2VyQ29uZmlnRW5jb2RlZCwgc3RvcmU7CiAgICAgICAgICAvLyBXZSBoYXZlIGEgSFRNTCBlc2NhcGVkIEpTT04gcmVwcmVzZW50YXRpb24gb2YgdGhlIHVzZXIncyBiYXNpYwogICAgICAgICAgLy8gY29uZmlndXJhdGlvbiBnZW5lcmF0ZWQgc2VydmVyIHNpZGUgYW5kIHN0b3JlZCBpbiB0aGUgRE9NIG9mIHRoZSBtYWluCiAgICAgICAgICAvLyBpbmRleC5odG1sIGZpbGUuIFRoaXMgYWxsb3dzIHRoZSBhcHAgdG8gaGF2ZSBhY2Nlc3MgdG8gYSBzZXQgb2YgZGF0YQogICAgICAgICAgLy8gd2l0aG91dCBtYWtpbmcgYW55IGFkZGl0aW9uYWwgcmVtb3RlIGNhbGxzLiBHb29kIGZvciBiYXNpYyBkYXRhIHRoYXQgaXMKICAgICAgICAgIC8vIG5lZWRlZCBmb3IgaW1tZWRpYXRlIHJlbmRlcmluZyBvZiB0aGUgcGFnZS4gS2VlcCBpbiBtaW5kLCB0aGlzIGRhdGEsCiAgICAgICAgICAvLyBsaWtlIGFsbCBsb2NhbCBtb2RlbHMgYW5kIGRhdGEgY2FuIGJlIG1hbmlwdWxhdGVkIGJ5IHRoZSB1c2VyLCBzbyBpdAogICAgICAgICAgLy8gc2hvdWxkIG5vdCBiZSByZWxpZWQgdXBvbiBmb3Igc2VjdXJpdHkgb3IgYXV0aG9yaXphdGlvbi4KICAgICAgICAgICAvLyBHcmFiIHRoZSBlbmNvZGVkIGRhdGEgZnJvbSB0aGUgbWV0YSB0YWcKICAgICAgICAgIHVzZXJDb25maWdFbmNvZGVkID0gJCgnaGVhZCBtZXRhW25hbWU9YXBwLXVzZXItY29uZmlnXScpLmF0dHIoJ2NvbnRlbnQnKTsKICAgICAgICAgICAvLyBVbmVzY2FwZSB0aGUgdGV4dCwgdGhlbiBwYXJzZSB0aGUgcmVzdWx0aW5nIEpTT04gaW50byBhIHJlYWwgb2JqZWN0CiAgICAgICAgICB1c2VyQ29uZmlnID0gSlNPTi5wYXJzZSh1bmVzY2FwZSh1c2VyQ29uZmlnRW5jb2RlZCkpOwogICAgICAgICAgIC8vIExvb2t1cCB0aGUgc3RvcmUKICAgICAgICAgIHN0b3JlID0gYXBwbGljYXRpb24ubG9va3VwKCdzZXJ2aWNlOnN0b3JlJyk7CiAgICAgICAgICAgLy8gUHVzaCB0aGUgZW5jb2RlZCBKU09OIGludG8gdGhlIHN0b3JlCiAgICAgICAgICBzdG9yZS5wdXNoUGF5bG9hZCh1c2VyQ29uZmlnKTsKICAgICAgfQogICAgICAgZXhwb3J0IGRlZmF1bHQgewogICAgICAgIG5hbWU6ICduYW1lZC1pbnN0YW5jZS1pbml0aWFsaXplcicsCiAgICAgICAgaW5pdGlhbGl6ZQogICAgICB9OwogICAgICBgYGAKICAgICAgIEBtZXRob2QgaW5zdGFuY2VJbml0aWFsaXplcgogICAgICBAcGFyYW0gaW5zdGFuY2VJbml0aWFsaXplcgogICAgICBAcHVibGljCiAgICAqLwogICAgaW5zdGFuY2VJbml0aWFsaXplcjogYnVpbGRJbml0aWFsaXplck1ldGhvZCgnaW5zdGFuY2VJbml0aWFsaXplcnMnLCAnaW5zdGFuY2UgaW5pdGlhbGl6ZXInKSwKCiAgICAvKioKICAgICAgVGhpcyBjcmVhdGVzIGEgcmVnaXN0cnkgd2l0aCB0aGUgZGVmYXVsdCBFbWJlciBuYW1pbmcgY29udmVudGlvbnMuCiAgICAgICBJdCBhbHNvIGNvbmZpZ3VyZXMgdGhlIHJlZ2lzdHJ5OgogICAgICAgKiByZWdpc3RlcmVkIHZpZXdzIGFyZSBjcmVhdGVkIGV2ZXJ5IHRpbWUgdGhleSBhcmUgbG9va2VkIHVwICh0aGV5IGFyZQogICAgICAgIG5vdCBzaW5nbGV0b25zKQogICAgICAqIHJlZ2lzdGVyZWQgdGVtcGxhdGVzIGFyZSBub3QgZmFjdG9yaWVzOyB0aGUgcmVnaXN0ZXJlZCB2YWx1ZSBpcwogICAgICAgIHJldHVybmVkIGRpcmVjdGx5LgogICAgICAqIHRoZSByb3V0ZXIgcmVjZWl2ZXMgdGhlIGFwcGxpY2F0aW9uIGFzIGl0cyBgbmFtZXNwYWNlYCBwcm9wZXJ0eQogICAgICAqIGFsbCBjb250cm9sbGVycyByZWNlaXZlIHRoZSByb3V0ZXIgYXMgdGhlaXIgYHRhcmdldGAgYW5kIGBjb250cm9sbGVyc2AKICAgICAgICBwcm9wZXJ0aWVzCiAgICAgICogYWxsIGNvbnRyb2xsZXJzIHJlY2VpdmUgdGhlIGFwcGxpY2F0aW9uIGFzIHRoZWlyIGBuYW1lc3BhY2VgIHByb3BlcnR5CiAgICAgICogdGhlIGFwcGxpY2F0aW9uIHZpZXcgcmVjZWl2ZXMgdGhlIGFwcGxpY2F0aW9uIGNvbnRyb2xsZXIgYXMgaXRzCiAgICAgICAgYGNvbnRyb2xsZXJgIHByb3BlcnR5CiAgICAgICogdGhlIGFwcGxpY2F0aW9uIHZpZXcgcmVjZWl2ZXMgdGhlIGFwcGxpY2F0aW9uIHRlbXBsYXRlIGFzIGl0cwogICAgICAgIGBkZWZhdWx0VGVtcGxhdGVgIHByb3BlcnR5CiAgICAgICBAbWV0aG9kIGJ1aWxkUmVnaXN0cnkKICAgICAgQHN0YXRpYwogICAgICBAcGFyYW0ge0FwcGxpY2F0aW9ufSBuYW1lc3BhY2UgdGhlIGFwcGxpY2F0aW9uIGZvciB3aGljaCB0bwogICAgICAgIGJ1aWxkIHRoZSByZWdpc3RyeQogICAgICBAcmV0dXJuIHtFbWJlci5SZWdpc3RyeX0gdGhlIGJ1aWx0IHJlZ2lzdHJ5CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgYnVpbGRSZWdpc3RyeTogZnVuY3Rpb24gYnVpbGRSZWdpc3RyeShuYW1lc3BhY2UpIHsKICAgICAgdmFyIHJlZ2lzdHJ5ID0gbmV3IF9jb250YWluZXIuUmVnaXN0cnkoewogICAgICAgIHJlc29sdmVyOiByZXNvbHZlckZvcihuYW1lc3BhY2UpCiAgICAgIH0pOwogICAgICByZWdpc3RyeS5zZXQgPSBfbWV0YWwuc2V0OwogICAgICByZWdpc3RyeS5yZWdpc3RlcignYXBwbGljYXRpb246bWFpbicsIG5hbWVzcGFjZSwgewogICAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgICB9KTsKICAgICAgY29tbW9uU2V0dXBSZWdpc3RyeShyZWdpc3RyeSk7CiAgICAgICgwLCBfZ2xpbW1lci5zZXR1cEVuZ2luZVJlZ2lzdHJ5KShyZWdpc3RyeSk7CiAgICAgIHJldHVybiByZWdpc3RyeTsKICAgIH0sCgogICAgLyoqCiAgICAgIFNldCB0aGlzIHRvIHByb3ZpZGUgYW4gYWx0ZXJuYXRlIGNsYXNzIHRvIGBEZWZhdWx0UmVzb2x2ZXJgCiAgICAgICBAZGVwcmVjYXRlZCBVc2UgJ1Jlc29sdmVyJyBpbnN0ZWFkCiAgICAgIEBwcm9wZXJ0eSByZXNvbHZlcgogICAgICBAcHVibGljCiAgICAqLwogICAgcmVzb2x2ZXI6IG51bGwsCgogICAgLyoqCiAgICAgIFNldCB0aGlzIHRvIHByb3ZpZGUgYW4gYWx0ZXJuYXRlIGNsYXNzIHRvIGBEZWZhdWx0UmVzb2x2ZXJgCiAgICAgICBAcHJvcGVydHkgcmVzb2x2ZXIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIFJlc29sdmVyOiBudWxsCiAgfSk7CiAgLyoqCiAgICBUaGlzIGZ1bmN0aW9uIGRlZmluZXMgdGhlIGRlZmF1bHQgbG9va3VwIHJ1bGVzIGZvciBjb250YWluZXIgbG9va3VwczoKICAKICAgICogdGVtcGxhdGVzIGFyZSBsb29rZWQgdXAgb24gYEVtYmVyLlRFTVBMQVRFU2AKICAgICogb3RoZXIgbmFtZXMgYXJlIGxvb2tlZCB1cCBvbiB0aGUgYXBwbGljYXRpb24gYWZ0ZXIgY2xhc3NpZnlpbmcgdGhlIG5hbWUuCiAgICAgIEZvciBleGFtcGxlLCBgY29udHJvbGxlcjpwb3N0YCBsb29rcyB1cCBgQXBwLlBvc3RDb250cm9sbGVyYCBieSBkZWZhdWx0LgogICAgKiBpZiB0aGUgZGVmYXVsdCBsb29rdXAgZmFpbHMsIGxvb2sgZm9yIHJlZ2lzdGVyZWQgY2xhc3NlcyBvbiB0aGUgY29udGFpbmVyCiAgCiAgICBUaGlzIGFsbG93cyB0aGUgYXBwbGljYXRpb24gdG8gcmVnaXN0ZXIgZGVmYXVsdCBpbmplY3Rpb25zIGluIHRoZSBjb250YWluZXIKICAgIHRoYXQgY291bGQgYmUgb3ZlcnJpZGRlbiBieSB0aGUgbm9ybWFsIG5hbWluZyBjb252ZW50aW9uLgogIAogICAgQHByaXZhdGUKICAgIEBtZXRob2QgcmVzb2x2ZXJGb3IKICAgIEBwYXJhbSB7RW1iZXIuTmFtZXNwYWNlfSBuYW1lc3BhY2UgdGhlIG5hbWVzcGFjZSB0byBsb29rIGZvciBjbGFzc2VzCiAgICBAcmV0dXJuIHsqfSB0aGUgcmVzb2x2ZWQgdmFsdWUgZm9yIGEgZ2l2ZW4gbG9va3VwCiAgKi8KCiAgZnVuY3Rpb24gcmVzb2x2ZXJGb3IobmFtZXNwYWNlKSB7CiAgICB2YXIgUmVzb2x2ZXJDbGFzcyA9ICgwLCBfbWV0YWwuZ2V0KShuYW1lc3BhY2UsICdSZXNvbHZlcicpIHx8IF9nbG9iYWxzUmVzb2x2ZXIuZGVmYXVsdDsKCiAgICB2YXIgcHJvcHMgPSB7CiAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlCiAgICB9OwogICAgcmV0dXJuIFJlc29sdmVyQ2xhc3MuY3JlYXRlKHByb3BzKTsKICB9CgogIGZ1bmN0aW9uIGJ1aWxkSW5pdGlhbGl6ZXJNZXRob2QoYnVja2V0TmFtZSwgaHVtYW5OYW1lKSB7CiAgICByZXR1cm4gZnVuY3Rpb24gKGluaXRpYWxpemVyKSB7CiAgICAgIC8vIElmIHRoaXMgaXMgdGhlIGZpcnN0IGluaXRpYWxpemVyIGJlaW5nIGFkZGVkIHRvIGEgc3ViY2xhc3MsIHdlIGFyZSBnb2luZyB0byByZW9wZW4gdGhlIGNsYXNzCiAgICAgIC8vIHRvIG1ha2Ugc3VyZSB3ZSBoYXZlIGEgbmV3IGBpbml0aWFsaXplcnNgIG9iamVjdCwgd2hpY2ggZXh0ZW5kcyBmcm9tIHRoZSBwYXJlbnQgY2xhc3MnIHVzaW5nCiAgICAgIC8vIHByb3RvdHlwYWwgaW5oZXJpdGFuY2UuIFdpdGhvdXQgdGhpcywgYXR0ZW1wdGluZyB0byBhZGQgaW5pdGlhbGl6ZXJzIHRvIHRoZSBzdWJjbGFzcyB3b3VsZAogICAgICAvLyBwb2xsdXRlIHRoZSBwYXJlbnQgY2xhc3MgYXMgd2VsbCBhcyBvdGhlciBzdWJjbGFzc2VzLgogICAgICBpZiAodGhpcy5zdXBlcmNsYXNzW2J1Y2tldE5hbWVdICE9PSB1bmRlZmluZWQgJiYgdGhpcy5zdXBlcmNsYXNzW2J1Y2tldE5hbWVdID09PSB0aGlzW2J1Y2tldE5hbWVdKSB7CiAgICAgICAgdmFyIGF0dHJzID0ge307CiAgICAgICAgYXR0cnNbYnVja2V0TmFtZV0gPSBPYmplY3QuY3JlYXRlKHRoaXNbYnVja2V0TmFtZV0pOwogICAgICAgIHRoaXMucmVvcGVuQ2xhc3MoYXR0cnMpOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISghdGhpc1tidWNrZXROYW1lXVtpbml0aWFsaXplci5uYW1lXSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgIiArIGh1bWFuTmFtZSArICIgJyIgKyBpbml0aWFsaXplci5uYW1lICsgIicgaGFzIGFscmVhZHkgYmVlbiByZWdpc3RlcmVkIiwgIXRoaXNbYnVja2V0TmFtZV1baW5pdGlhbGl6ZXIubmFtZV0pKTsKICAgICAgKGZhbHNlICYmICEoKDAsIF91dGlscy5jYW5JbnZva2UpKGluaXRpYWxpemVyLCAnaW5pdGlhbGl6ZScpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkFuICIgKyBodW1hbk5hbWUgKyAiIGNhbm5vdCBiZSByZWdpc3RlcmVkIHdpdGhvdXQgYW4gaW5pdGlhbGl6ZSBmdW5jdGlvbiIsICgwLCBfdXRpbHMuY2FuSW52b2tlKShpbml0aWFsaXplciwgJ2luaXRpYWxpemUnKSkpOwogICAgICAoZmFsc2UgJiYgIShpbml0aWFsaXplci5uYW1lICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQW4gIiArIGh1bWFuTmFtZSArICIgY2Fubm90IGJlIHJlZ2lzdGVyZWQgd2l0aG91dCBhIG5hbWUgcHJvcGVydHkiLCBpbml0aWFsaXplci5uYW1lICE9PSB1bmRlZmluZWQpKTsKICAgICAgdGhpc1tidWNrZXROYW1lXVtpbml0aWFsaXplci5uYW1lXSA9IGluaXRpYWxpemVyOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIGNvbW1vblNldHVwUmVnaXN0cnkocmVnaXN0cnkpIHsKICAgIHJlZ2lzdHJ5Lm9wdGlvbnNGb3JUeXBlKCdjb21wb25lbnQnLCB7CiAgICAgIHNpbmdsZXRvbjogZmFsc2UKICAgIH0pOwogICAgcmVnaXN0cnkub3B0aW9uc0ZvclR5cGUoJ3ZpZXcnLCB7CiAgICAgIHNpbmdsZXRvbjogZmFsc2UKICAgIH0pOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ2NvbnRyb2xsZXI6YmFzaWMnLCBfY29udHJvbGxlci5kZWZhdWx0LCB7CiAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgfSk7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3ZpZXcnLCAnX3ZpZXdSZWdpc3RyeScsICctdmlldy1yZWdpc3RyeTptYWluJyk7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3JlbmRlcmVyJywgJ192aWV3UmVnaXN0cnknLCAnLXZpZXctcmVnaXN0cnk6bWFpbicpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdyb3V0ZScsICdfdG9wTGV2ZWxWaWV3VGVtcGxhdGUnLCAndGVtcGxhdGU6LW91dGxldCcpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCd2aWV3Oi1vdXRsZXQnLCAnbmFtZXNwYWNlJywgJ2FwcGxpY2F0aW9uOm1haW4nKTsKICAgIHJlZ2lzdHJ5LmluamVjdGlvbignY29udHJvbGxlcicsICd0YXJnZXQnLCAncm91dGVyOm1haW4nKTsKICAgIHJlZ2lzdHJ5LmluamVjdGlvbignY29udHJvbGxlcicsICduYW1lc3BhY2UnLCAnYXBwbGljYXRpb246bWFpbicpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdyb3V0ZXInLCAnX2J1Y2tldENhY2hlJywgKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3QoKSkpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdyb3V0ZScsICdfYnVja2V0Q2FjaGUnLCAoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdDIoKSkpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdyb3V0ZScsICdfcm91dGVyJywgJ3JvdXRlcjptYWluJyk7IC8vIFJlZ2lzdGVyIHRoZSByb3V0aW5nIHNlcnZpY2UuLi4KCiAgICByZWdpc3RyeS5yZWdpc3Rlcignc2VydmljZTotcm91dGluZycsIF9yb3V0aW5nLlJvdXRpbmdTZXJ2aWNlKTsgLy8gVGhlbiBpbmplY3QgdGhlIGFwcCByb3V0ZXIgaW50byBpdAoKICAgIHJlZ2lzdHJ5LmluamVjdGlvbignc2VydmljZTotcm91dGluZycsICdyb3V0ZXInLCAncm91dGVyOm1haW4nKTsgLy8gREVCVUdHSU5HCgogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ3Jlc29sdmVyLWZvci1kZWJ1Z2dpbmc6bWFpbicsIHJlZ2lzdHJ5LnJlc29sdmVyLCB7CiAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgfSk7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ2NvbnRhaW5lci1kZWJ1Zy1hZGFwdGVyOm1haW4nLCAncmVzb2x2ZXInLCAncmVzb2x2ZXItZm9yLWRlYnVnZ2luZzptYWluJyk7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ2RhdGEtYWRhcHRlcjptYWluJywgJ2NvbnRhaW5lckRlYnVnQWRhcHRlcicsICdjb250YWluZXItZGVidWctYWRhcHRlcjptYWluJyk7IC8vIEN1c3RvbSByZXNvbHZlciBhdXRob3JzIG1heSB3YW50IHRvIHJlZ2lzdGVyIHRoZWlyIG93biBDb250YWluZXJEZWJ1Z0FkYXB0ZXIgd2l0aCB0aGlzIGtleQoKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdjb250YWluZXItZGVidWctYWRhcHRlcjptYWluJywgX2V4dGVuc2lvblN1cHBvcnQuQ29udGFpbmVyRGVidWdBZGFwdGVyKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdjb21wb25lbnQtbG9va3VwOm1haW4nLCBfdmlld3MuQ29tcG9uZW50TG9va3VwKTsKICB9CgogIHZhciBfZGVmYXVsdCA9IEVuZ2luZTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci9lbmdpbmUvaW5zdGFuY2UiLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL2Vycm9yIiwgIkBlbWJlci8taW50ZXJuYWxzL2NvbnRhaW5lciIsICJAZW1iZXIvZW5naW5lL2xpYi9lbmdpbmUtcGFyZW50Il0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2VtYmVyQmFiZWwsIF91dGlscywgX3J1bnRpbWUsIF9kZWJ1ZywgX2Vycm9yLCBfY29udGFpbmVyLCBfZW5naW5lUGFyZW50KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3QyKCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsidGVtcGxhdGUtY29tcGlsZXI6bWFpbiJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3QyID0gZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0MigpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0KCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsiLWJ1Y2tldC1jYWNoZTptYWluIl0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdCgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgLyoqCiAgICBUaGUgYEVuZ2luZUluc3RhbmNlYCBlbmNhcHN1bGF0ZXMgYWxsIG9mIHRoZSBzdGF0ZWZ1bCBhc3BlY3RzIG9mIGEKICAgIHJ1bm5pbmcgYEVuZ2luZWAuCiAgCiAgICBAcHVibGljCiAgICBAY2xhc3MgRW5naW5lSW5zdGFuY2UKICAgIEBleHRlbmRzIEVtYmVyT2JqZWN0CiAgICBAdXNlcyBSZWdpc3RyeVByb3h5TWl4aW4KICAgIEB1c2VzIENvbnRhaW5lclByb3h5TWl4aW4KICAqLwogIHZhciBFbmdpbmVJbnN0YW5jZSA9IF9ydW50aW1lLk9iamVjdC5leHRlbmQoX3J1bnRpbWUuUmVnaXN0cnlQcm94eU1peGluLCBfcnVudGltZS5Db250YWluZXJQcm94eU1peGluLCB7CiAgICAvKioKICAgICAgVGhlIGJhc2UgYEVuZ2luZWAgZm9yIHdoaWNoIHRoaXMgaXMgYW4gaW5zdGFuY2UuCiAgICAgICBAcHJvcGVydHkge0VuZ2luZX0gZW5naW5lCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgYmFzZTogbnVsbCwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAoMCwgX3V0aWxzLmd1aWRGb3IpKHRoaXMpOwogICAgICB2YXIgYmFzZSA9IHRoaXMuYmFzZTsKCiAgICAgIGlmICghYmFzZSkgewogICAgICAgIGJhc2UgPSB0aGlzLmFwcGxpY2F0aW9uOwogICAgICAgIHRoaXMuYmFzZSA9IGJhc2U7CiAgICAgIH0gLy8gQ3JlYXRlIGEgcGVyLWluc3RhbmNlIHJlZ2lzdHJ5IHRoYXQgd2lsbCB1c2UgdGhlIGFwcGxpY2F0aW9uJ3MgcmVnaXN0cnkKICAgICAgLy8gYXMgYSBmYWxsYmFjayBmb3IgcmVzb2x2aW5nIHJlZ2lzdHJhdGlvbnMuCgoKICAgICAgdmFyIHJlZ2lzdHJ5ID0gdGhpcy5fX3JlZ2lzdHJ5X18gPSBuZXcgX2NvbnRhaW5lci5SZWdpc3RyeSh7CiAgICAgICAgZmFsbGJhY2s6IGJhc2UuX19yZWdpc3RyeV9fCiAgICAgIH0pOyAvLyBDcmVhdGUgYSBwZXItaW5zdGFuY2UgY29udGFpbmVyIGZyb20gdGhlIGluc3RhbmNlJ3MgcmVnaXN0cnkKCiAgICAgIHRoaXMuX19jb250YWluZXJfXyA9IHJlZ2lzdHJ5LmNvbnRhaW5lcih7CiAgICAgICAgb3duZXI6IHRoaXMKICAgICAgfSk7CiAgICAgIHRoaXMuX2Jvb3RlZCA9IGZhbHNlOwogICAgfSwKCiAgICAvKioKICAgICAgSW5pdGlhbGl6ZSB0aGUgYEVuZ2luZUluc3RhbmNlYCBhbmQgcmV0dXJuIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzCiAgICAgIHdpdGggdGhlIGluc3RhbmNlIGl0c2VsZiB3aGVuIHRoZSBib290IHByb2Nlc3MgaXMgY29tcGxldGUuCiAgICAgICBUaGUgcHJpbWFyeSB0YXNrIGhlcmUgaXMgdG8gcnVuIGFueSByZWdpc3RlcmVkIGluc3RhbmNlIGluaXRpYWxpemVycy4KICAgICAgIFNlZSB0aGUgZG9jdW1lbnRhdGlvbiBvbiBgQm9vdE9wdGlvbnNgIGZvciB0aGUgb3B0aW9ucyBpdCB0YWtlcy4KICAgICAgIEBwdWJsaWMKICAgICAgQG1ldGhvZCBib290CiAgICAgIEBwYXJhbSBvcHRpb25zIHtPYmplY3R9CiAgICAgIEByZXR1cm4ge1Byb21pc2U8RW5naW5lSW5zdGFuY2UsRXJyb3I+fQogICAgKi8KICAgIGJvb3Q6IGZ1bmN0aW9uIGJvb3Qob3B0aW9ucykgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgaWYgKHRoaXMuX2Jvb3RQcm9taXNlKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2Jvb3RQcm9taXNlOwogICAgICB9CgogICAgICB0aGlzLl9ib290UHJvbWlzZSA9IG5ldyBfcnVudGltZS5SU1ZQLlByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUpIHsKICAgICAgICByZXR1cm4gcmVzb2x2ZShfdGhpcy5fYm9vdFN5bmMob3B0aW9ucykpOwogICAgICB9KTsKICAgICAgcmV0dXJuIHRoaXMuX2Jvb3RQcm9taXNlOwogICAgfSwKCiAgICAvKioKICAgICAgVW5mb3J0dW5hdGVseSwgYSBsb3Qgb2YgZXhpc3RpbmcgY29kZSBhc3N1bWVzIGJvb3RpbmcgYW4gaW5zdGFuY2UgaXMKICAgICAgc3luY2hyb25vdXMg4oCTIHNwZWNpZmljYWxseSwgYSBsb3Qgb2YgdGVzdHMgYXNzdW1lIHRoZSBsYXN0IGNhbGwgdG8KICAgICAgYGFwcC5hZHZhbmNlUmVhZGluZXNzKClgIG9yIGBhcHAucmVzZXQoKWAgd2lsbCByZXN1bHQgaW4gYSBuZXcgaW5zdGFuY2UKICAgICAgYmVpbmcgZnVsbHktYm9vdGVkIHdoZW4gdGhlIGN1cnJlbnQgcnVubG9vcCBjb21wbGV0ZXMuCiAgICAgICBXZSB3b3VsZCBsaWtlIG5ldyBjb2RlIChsaWtlIHRoZSBgdmlzaXRgIEFQSSkgdG8gc3RvcCBtYWtpbmcgdGhpcwogICAgICBhc3N1bXB0aW9uLCBzbyB3ZSBjcmVhdGVkIHRoZSBhc3luY2hyb25vdXMgdmVyc2lvbiBhYm92ZSB0aGF0IHJldHVybnMgYQogICAgICBwcm9taXNlLiBCdXQgdW50aWwgd2UgaGF2ZSBtaWdyYXRlZCBhbGwgdGhlIGNvZGUsIHdlIHdvdWxkIGhhdmUgdG8gZXhwb3NlCiAgICAgIHRoaXMgbWV0aG9kIGZvciB1c2UgKmludGVybmFsbHkqIGluIHBsYWNlcyB3aGVyZSB3ZSBuZWVkIHRvIGJvb3QgYW4gaW5zdGFuY2UKICAgICAgc3luY2hyb25vdXNseS4KICAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX2Jvb3RTeW5jOiBmdW5jdGlvbiBfYm9vdFN5bmMob3B0aW9ucykgewogICAgICBpZiAodGhpcy5fYm9vdGVkKSB7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKCgwLCBfZW5naW5lUGFyZW50LmdldEVuZ2luZVBhcmVudCkodGhpcykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQW4gZW5naW5lIGluc3RhbmNlJ3MgcGFyZW50IG11c3QgYmUgc2V0IHZpYSBgc2V0RW5naW5lUGFyZW50KGVuZ2luZSwgcGFyZW50KWAgcHJpb3IgdG8gY2FsbGluZyBgZW5naW5lLmJvb3QoKWAuIiwgKDAsIF9lbmdpbmVQYXJlbnQuZ2V0RW5naW5lUGFyZW50KSh0aGlzKSkpOwogICAgICB0aGlzLmNsb25lUGFyZW50RGVwZW5kZW5jaWVzKCk7CiAgICAgIHRoaXMuc2V0dXBSZWdpc3RyeShvcHRpb25zKTsKICAgICAgdGhpcy5iYXNlLnJ1bkluc3RhbmNlSW5pdGlhbGl6ZXJzKHRoaXMpOwogICAgICB0aGlzLl9ib290ZWQgPSB0cnVlOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCiAgICBzZXR1cFJlZ2lzdHJ5OiBmdW5jdGlvbiBzZXR1cFJlZ2lzdHJ5KG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB0aGlzLl9fY29udGFpbmVyX18ubG9va3VwKCctZW52aXJvbm1lbnQ6bWFpbicpOwogICAgICB9CgogICAgICB0aGlzLmNvbnN0cnVjdG9yLnNldHVwUmVnaXN0cnkodGhpcy5fX3JlZ2lzdHJ5X18sIG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICBVbnJlZ2lzdGVyIGEgZmFjdG9yeS4KICAgICAgT3ZlcnJpZGVzIGBSZWdpc3RyeVByb3h5I3VucmVnaXN0ZXJgIGluIG9yZGVyIHRvIGNsZWFyIGFueSBjYWNoZWQgaW5zdGFuY2VzCiAgICAgb2YgdGhlIHVucmVnaXN0ZXJlZCBmYWN0b3J5LgogICAgICBAcHVibGljCiAgICAgQG1ldGhvZCB1bnJlZ2lzdGVyCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgKi8KICAgIHVucmVnaXN0ZXI6IGZ1bmN0aW9uIHVucmVnaXN0ZXIoZnVsbE5hbWUpIHsKICAgICAgdGhpcy5fX2NvbnRhaW5lcl9fLnJlc2V0KGZ1bGxOYW1lKTsKCiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qKgogICAgICBCdWlsZCBhIG5ldyBgRW5naW5lSW5zdGFuY2VgIHRoYXQncyBhIGNoaWxkIG9mIHRoaXMgaW5zdGFuY2UuCiAgICAgICBFbmdpbmVzIG11c3QgYmUgcmVnaXN0ZXJlZCBieSBuYW1lIHdpdGggdGhlaXIgcGFyZW50IGVuZ2luZQogICAgICAob3IgYXBwbGljYXRpb24pLgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBidWlsZENoaWxkRW5naW5lSW5zdGFuY2UKICAgICAgQHBhcmFtIG5hbWUge1N0cmluZ30gdGhlIHJlZ2lzdGVyZWQgbmFtZSBvZiB0aGUgZW5naW5lLgogICAgICBAcGFyYW0gb3B0aW9ucyB7T2JqZWN0fSBvcHRpb25zIHByb3ZpZGVkIHRvIHRoZSBlbmdpbmUgaW5zdGFuY2UuCiAgICAgIEByZXR1cm4ge0VuZ2luZUluc3RhbmNlLEVycm9yfQogICAgKi8KICAgIGJ1aWxkQ2hpbGRFbmdpbmVJbnN0YW5jZTogZnVuY3Rpb24gYnVpbGRDaGlsZEVuZ2luZUluc3RhbmNlKG5hbWUsIG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgfQoKICAgICAgdmFyIEVuZ2luZSA9IHRoaXMubG9va3VwKCJlbmdpbmU6IiArIG5hbWUpOwoKICAgICAgaWYgKCFFbmdpbmUpIHsKICAgICAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIllvdSBhdHRlbXB0ZWQgdG8gbW91bnQgdGhlIGVuZ2luZSAnIiArIG5hbWUgKyAiJywgYnV0IGl0IGlzIG5vdCByZWdpc3RlcmVkIHdpdGggaXRzIHBhcmVudC4iKTsKICAgICAgfQoKICAgICAgdmFyIGVuZ2luZUluc3RhbmNlID0gRW5naW5lLmJ1aWxkSW5zdGFuY2Uob3B0aW9ucyk7CiAgICAgICgwLCBfZW5naW5lUGFyZW50LnNldEVuZ2luZVBhcmVudCkoZW5naW5lSW5zdGFuY2UsIHRoaXMpOwogICAgICByZXR1cm4gZW5naW5lSW5zdGFuY2U7CiAgICB9LAoKICAgIC8qKgogICAgICBDbG9uZSBkZXBlbmRlbmNpZXMgc2hhcmVkIGJldHdlZW4gYW4gZW5naW5lIGluc3RhbmNlIGFuZCBpdHMgcGFyZW50LgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBjbG9uZVBhcmVudERlcGVuZGVuY2llcwogICAgKi8KICAgIGNsb25lUGFyZW50RGVwZW5kZW5jaWVzOiBmdW5jdGlvbiBjbG9uZVBhcmVudERlcGVuZGVuY2llcygpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICB2YXIgcGFyZW50ID0gKDAsIF9lbmdpbmVQYXJlbnQuZ2V0RW5naW5lUGFyZW50KSh0aGlzKTsKICAgICAgdmFyIHJlZ2lzdHJhdGlvbnMgPSBbJ3JvdXRlOmJhc2ljJywgJ3NlcnZpY2U6LXJvdXRpbmcnLCAnc2VydmljZTotZ2xpbW1lci1lbnZpcm9ubWVudCddOwogICAgICByZWdpc3RyYXRpb25zLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgIHJldHVybiBfdGhpczIucmVnaXN0ZXIoa2V5LCBwYXJlbnQucmVzb2x2ZVJlZ2lzdHJhdGlvbihrZXkpKTsKICAgICAgfSk7CiAgICAgIHZhciBlbnYgPSBwYXJlbnQubG9va3VwKCctZW52aXJvbm1lbnQ6bWFpbicpOwogICAgICB0aGlzLnJlZ2lzdGVyKCctZW52aXJvbm1lbnQ6bWFpbicsIGVudiwgewogICAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgICB9KTsKICAgICAgdmFyIHNpbmdsZXRvbnMgPSBbJ3JvdXRlcjptYWluJywgKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3QoKSksICctdmlldy1yZWdpc3RyeTptYWluJywgInJlbmRlcmVyOi0iICsgKGVudi5pc0ludGVyYWN0aXZlID8gJ2RvbScgOiAnaW5lcnQnKSwgJ3NlcnZpY2U6LWRvY3VtZW50JywgKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3QyKCkpXTsKCiAgICAgIGlmIChlbnYuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIHNpbmdsZXRvbnMucHVzaCgnZXZlbnRfZGlzcGF0Y2hlcjptYWluJyk7CiAgICAgIH0KCiAgICAgIHNpbmdsZXRvbnMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgcmV0dXJuIF90aGlzMi5yZWdpc3RlcihrZXksIHBhcmVudC5sb29rdXAoa2V5KSwgewogICAgICAgICAgaW5zdGFudGlhdGU6IGZhbHNlCiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICB0aGlzLmluamVjdCgndmlldycsICdfZW52aXJvbm1lbnQnLCAnLWVudmlyb25tZW50Om1haW4nKTsKICAgICAgdGhpcy5pbmplY3QoJ3JvdXRlJywgJ19lbnZpcm9ubWVudCcsICctZW52aXJvbm1lbnQ6bWFpbicpOwogICAgfQogIH0pOwoKICBFbmdpbmVJbnN0YW5jZS5yZW9wZW5DbGFzcyh7CiAgICAvKioKICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2Qgc2V0dXBSZWdpc3RyeQogICAgIEBwYXJhbSB7UmVnaXN0cnl9IHJlZ2lzdHJ5CiAgICAgQHBhcmFtIHtCb290T3B0aW9uc30gb3B0aW9ucwogICAgICovCiAgICBzZXR1cFJlZ2lzdHJ5OiBmdW5jdGlvbiBzZXR1cFJlZ2lzdHJ5KHJlZ2lzdHJ5LCBvcHRpb25zKSB7CiAgICAgIC8vIHdoZW4gbm8gb3B0aW9ucy9lbnZpcm9ubWVudCBpcyBwcmVzZW50LCBkbyBub3RoaW5nCiAgICAgIGlmICghb3B0aW9ucykgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgcmVnaXN0cnkuaW5qZWN0aW9uKCd2aWV3JywgJ19lbnZpcm9ubWVudCcsICctZW52aXJvbm1lbnQ6bWFpbicpOwogICAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3JvdXRlJywgJ19lbnZpcm9ubWVudCcsICctZW52aXJvbm1lbnQ6bWFpbicpOwoKICAgICAgaWYgKG9wdGlvbnMuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIHJlZ2lzdHJ5LmluamVjdGlvbigndmlldycsICdyZW5kZXJlcicsICdyZW5kZXJlcjotZG9tJyk7CiAgICAgICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdjb21wb25lbnQnLCAncmVuZGVyZXInLCAncmVuZGVyZXI6LWRvbScpOwogICAgICB9IGVsc2UgewogICAgICAgIHJlZ2lzdHJ5LmluamVjdGlvbigndmlldycsICdyZW5kZXJlcicsICdyZW5kZXJlcjotaW5lcnQnKTsKICAgICAgICByZWdpc3RyeS5pbmplY3Rpb24oJ2NvbXBvbmVudCcsICdyZW5kZXJlcicsICdyZW5kZXJlcjotaW5lcnQnKTsKICAgICAgfQogICAgfQogIH0pOwogIHZhciBfZGVmYXVsdCA9IEVuZ2luZUluc3RhbmNlOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2VuZ2luZS9saWIvZW5naW5lLXBhcmVudCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy91dGlscyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF91dGlscykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZ2V0RW5naW5lUGFyZW50ID0gZ2V0RW5naW5lUGFyZW50OwogIF9leHBvcnRzLnNldEVuZ2luZVBhcmVudCA9IHNldEVuZ2luZVBhcmVudDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvZW5naW5lCiAgKi8KICB2YXIgRU5HSU5FX1BBUkVOVCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnRU5HSU5FX1BBUkVOVCcpOwogIC8qKgogICAgYGdldEVuZ2luZVBhcmVudGAgcmV0cmlldmVzIGFuIGVuZ2luZSBpbnN0YW5jZSdzIHBhcmVudCBpbnN0YW5jZS4KICAKICAgIEBtZXRob2QgZ2V0RW5naW5lUGFyZW50CiAgICBAcGFyYW0ge0VuZ2luZUluc3RhbmNlfSBlbmdpbmUgQW4gZW5naW5lIGluc3RhbmNlLgogICAgQHJldHVybiB7RW5naW5lSW5zdGFuY2V9IFRoZSBwYXJlbnQgZW5naW5lIGluc3RhbmNlLgogICAgQGZvciBAZW1iZXIvZW5naW5lCiAgICBAc3RhdGljCiAgICBAcHJpdmF0ZQogICovCgogIGZ1bmN0aW9uIGdldEVuZ2luZVBhcmVudChlbmdpbmUpIHsKICAgIHJldHVybiBlbmdpbmVbRU5HSU5FX1BBUkVOVF07CiAgfQogIC8qKgogICAgYHNldEVuZ2luZVBhcmVudGAgc2V0cyBhbiBlbmdpbmUgaW5zdGFuY2UncyBwYXJlbnQgaW5zdGFuY2UuCiAgCiAgICBAbWV0aG9kIHNldEVuZ2luZVBhcmVudAogICAgQHBhcmFtIHtFbmdpbmVJbnN0YW5jZX0gZW5naW5lIEFuIGVuZ2luZSBpbnN0YW5jZS4KICAgIEBwYXJhbSB7RW5naW5lSW5zdGFuY2V9IHBhcmVudCBUaGUgcGFyZW50IGVuZ2luZSBpbnN0YW5jZS4KICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIHNldEVuZ2luZVBhcmVudChlbmdpbmUsIHBhcmVudCkgewogICAgZW5naW5lW0VOR0lORV9QQVJFTlRdID0gcGFyZW50OwogIH0KfSk7CmRlZmluZSgiQGVtYmVyL2Vycm9yL2luZGV4IiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL2Vycm9yCiAgKi8KCiAgLyoqCiAgICBUaGUgSmF2YVNjcmlwdCBFcnJvciBvYmplY3QgdXNlZCBieSBFbWJlci5hc3NlcnQuCiAgCiAgICBAY2xhc3MgRXJyb3IKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEBleHRlbmRzIEVycm9yCiAgICBAY29uc3RydWN0b3IKICAgIEBwdWJsaWMKICAqLwogIHZhciBfZGVmYXVsdCA9IEVycm9yOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2luc3RydW1lbnRhdGlvbi9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbnZpcm9ubWVudCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuaW5zdHJ1bWVudCA9IGluc3RydW1lbnQ7CiAgX2V4cG9ydHMuX2luc3RydW1lbnRTdGFydCA9IF9pbnN0cnVtZW50U3RhcnQ7CiAgX2V4cG9ydHMuc3Vic2NyaWJlID0gc3Vic2NyaWJlOwogIF9leHBvcnRzLnVuc3Vic2NyaWJlID0gdW5zdWJzY3JpYmU7CiAgX2V4cG9ydHMucmVzZXQgPSByZXNldDsKICBfZXhwb3J0cy5mbGFnZ2VkSW5zdHJ1bWVudCA9IF9leHBvcnRzLnN1YnNjcmliZXJzID0gdm9pZCAwOwoKICAvKiBlc2xpbnQgbm8tY29uc29sZTpvZmYgKi8KCiAgLyogZ2xvYmFsIGNvbnNvbGUgKi8KCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvaW5zdHJ1bWVudGF0aW9uCiAgQHByaXZhdGUKICAqLwoKICAvKioKICAgIFRoZSBwdXJwb3NlIG9mIHRoZSBFbWJlciBJbnN0cnVtZW50YXRpb24gbW9kdWxlIGlzCiAgICB0byBwcm92aWRlIGVmZmljaWVudCwgZ2VuZXJhbC1wdXJwb3NlIGluc3RydW1lbnRhdGlvbgogICAgZm9yIEVtYmVyLgogIAogICAgU3Vic2NyaWJlIHRvIGEgbGlzdGVuZXIgYnkgdXNpbmcgYHN1YnNjcmliZWA6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzdWJzY3JpYmUgfSBmcm9tICdAZW1iZXIvaW5zdHJ1bWVudGF0aW9uJzsKICAKICAgIHN1YnNjcmliZSgicmVuZGVyIiwgewogICAgICBiZWZvcmUobmFtZSwgdGltZXN0YW1wLCBwYXlsb2FkKSB7CiAgCiAgICAgIH0sCiAgCiAgICAgIGFmdGVyKG5hbWUsIHRpbWVzdGFtcCwgcGF5bG9hZCkgewogIAogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgeW91IHJldHVybiBhIHZhbHVlIGZyb20gdGhlIGBiZWZvcmVgIGNhbGxiYWNrLCB0aGF0IHNhbWUKICAgIHZhbHVlIHdpbGwgYmUgcGFzc2VkIGFzIGEgZm91cnRoIHBhcmFtZXRlciB0byB0aGUgYGFmdGVyYAogICAgY2FsbGJhY2suCiAgCiAgICBJbnN0cnVtZW50IGEgYmxvY2sgb2YgY29kZSBieSB1c2luZyBgaW5zdHJ1bWVudGA6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBpbnN0cnVtZW50IH0gZnJvbSAnQGVtYmVyL2luc3RydW1lbnRhdGlvbic7CiAgCiAgICBpbnN0cnVtZW50KCJyZW5kZXIuaGFuZGxlYmFycyIsIHBheWxvYWQsIGZ1bmN0aW9uKCkgewogICAgICAvLyByZW5kZXJpbmcgbG9naWMKICAgIH0sIGJpbmRpbmcpOwogICAgYGBgCiAgCiAgICBFdmVudCBuYW1lcyBwYXNzZWQgdG8gYGluc3RydW1lbnRgIGFyZSBuYW1lc3BhY2VkCiAgICBieSBwZXJpb2RzLCBmcm9tIG1vcmUgZ2VuZXJhbCB0byBtb3JlIHNwZWNpZmljLiBTdWJzY3JpYmVycwogICAgY2FuIGxpc3RlbiBmb3IgZXZlbnRzIGJ5IHdoYXRldmVyIGxldmVsIG9mIGdyYW51bGFyaXR5IHRoZXkKICAgIGFyZSBpbnRlcmVzdGVkIGluLgogIAogICAgSW4gdGhlIGFib3ZlIGV4YW1wbGUsIHRoZSBldmVudCBpcyBgcmVuZGVyLmhhbmRsZWJhcnNgLAogICAgYW5kIHRoZSBzdWJzY3JpYmVyIGxpc3RlbmVkIGZvciBhbGwgZXZlbnRzIGJlZ2lubmluZyB3aXRoCiAgICBgcmVuZGVyYC4gSXQgd291bGQgcmVjZWl2ZSBjYWxsYmFja3MgZm9yIGV2ZW50cyBuYW1lZAogICAgYHJlbmRlcmAsIGByZW5kZXIuaGFuZGxlYmFyc2AsIGByZW5kZXIuY29udGFpbmVyYCwgb3IKICAgIGV2ZW4gYHJlbmRlci5oYW5kbGViYXJzLmxheW91dGAuCiAgCiAgICBAY2xhc3MgSW5zdHJ1bWVudGF0aW9uCiAgICBAc3RhdGljCiAgICBAcHJpdmF0ZQogICovCiAgdmFyIHN1YnNjcmliZXJzID0gW107CiAgX2V4cG9ydHMuc3Vic2NyaWJlcnMgPSBzdWJzY3JpYmVyczsKICB2YXIgY2FjaGUgPSB7fTsKCiAgZnVuY3Rpb24gcG9wdWxhdGVMaXN0ZW5lcnMobmFtZSkgewogICAgdmFyIGxpc3RlbmVycyA9IFtdOwogICAgdmFyIHN1YnNjcmliZXI7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdWJzY3JpYmVycy5sZW5ndGg7IGkrKykgewogICAgICBzdWJzY3JpYmVyID0gc3Vic2NyaWJlcnNbaV07CgogICAgICBpZiAoc3Vic2NyaWJlci5yZWdleC50ZXN0KG5hbWUpKSB7CiAgICAgICAgbGlzdGVuZXJzLnB1c2goc3Vic2NyaWJlci5vYmplY3QpOwogICAgICB9CiAgICB9CgogICAgY2FjaGVbbmFtZV0gPSBsaXN0ZW5lcnM7CiAgICByZXR1cm4gbGlzdGVuZXJzOwogIH0KCiAgdmFyIHRpbWUgPSBmdW5jdGlvbiAoKSB7CiAgICB2YXIgcGVyZiA9ICd1bmRlZmluZWQnICE9PSB0eXBlb2Ygd2luZG93ID8gd2luZG93LnBlcmZvcm1hbmNlIHx8IHt9IDoge307CiAgICB2YXIgZm4gPSBwZXJmLm5vdyB8fCBwZXJmLm1vek5vdyB8fCBwZXJmLndlYmtpdE5vdyB8fCBwZXJmLm1zTm93IHx8IHBlcmYub05vdzsKICAgIHJldHVybiBmbiA/IGZuLmJpbmQocGVyZikgOiBEYXRlLm5vdzsKICB9KCk7CgogIGZ1bmN0aW9uIGlzQ2FsbGJhY2sodmFsdWUpIHsKICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbic7CiAgfQoKICBmdW5jdGlvbiBpbnN0cnVtZW50KG5hbWUsIHAxLCBwMiwgcDMpIHsKICAgIHZhciBfcGF5bG9hZDsKCiAgICB2YXIgY2FsbGJhY2s7CiAgICB2YXIgYmluZGluZzsKCiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8PSAzICYmIGlzQ2FsbGJhY2socDEpKSB7CiAgICAgIGNhbGxiYWNrID0gcDE7CiAgICAgIGJpbmRpbmcgPSBwMjsKICAgIH0gZWxzZSB7CiAgICAgIF9wYXlsb2FkID0gcDE7CiAgICAgIGNhbGxiYWNrID0gcDI7CiAgICAgIGJpbmRpbmcgPSBwMzsKICAgIH0gLy8gZmFzdCBwYXRoCgoKICAgIGlmIChzdWJzY3JpYmVycy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIGNhbGxiYWNrLmNhbGwoYmluZGluZyk7CiAgICB9IC8vIGF2b2lkIGFsbG9jYXRpbmcgdGhlIHBheWxvYWQgaW4gZmFzdCBwYXRoCgoKICAgIHZhciBwYXlsb2FkID0gX3BheWxvYWQgfHwge307CgogICAgdmFyIGZpbmFsaXplciA9IF9pbnN0cnVtZW50U3RhcnQobmFtZSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gcGF5bG9hZDsKICAgIH0pOwoKICAgIGlmIChmaW5hbGl6ZXIgPT09IE5PT1ApIHsKICAgICAgcmV0dXJuIGNhbGxiYWNrLmNhbGwoYmluZGluZyk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gd2l0aEZpbmFsaXplcihjYWxsYmFjaywgZmluYWxpemVyLCBwYXlsb2FkLCBiaW5kaW5nKTsKICAgIH0KICB9CgogIHZhciBmbGFnZ2VkSW5zdHJ1bWVudDsKICBfZXhwb3J0cy5mbGFnZ2VkSW5zdHJ1bWVudCA9IGZsYWdnZWRJbnN0cnVtZW50OwoKICBpZiAoZmFsc2UKICAvKiBFTUJFUl9JTVBST1ZFRF9JTlNUUlVNRU5UQVRJT04gKi8KICApIHsKICAgICAgX2V4cG9ydHMuZmxhZ2dlZEluc3RydW1lbnQgPSBmbGFnZ2VkSW5zdHJ1bWVudCA9IGluc3RydW1lbnQ7CiAgICB9IGVsc2UgewogICAgX2V4cG9ydHMuZmxhZ2dlZEluc3RydW1lbnQgPSBmbGFnZ2VkSW5zdHJ1bWVudCA9IGZ1bmN0aW9uIGluc3RydW1lbnQoX25hbWUsIF9wYXlsb2FkLCBjYWxsYmFjaykgewogICAgICByZXR1cm4gY2FsbGJhY2soKTsKICAgIH07CiAgfQoKICBmdW5jdGlvbiB3aXRoRmluYWxpemVyKGNhbGxiYWNrLCBmaW5hbGl6ZXIsIHBheWxvYWQsIGJpbmRpbmcpIHsKICAgIHRyeSB7CiAgICAgIHJldHVybiBjYWxsYmFjay5jYWxsKGJpbmRpbmcpOwogICAgfSBjYXRjaCAoZSkgewogICAgICBwYXlsb2FkLmV4Y2VwdGlvbiA9IGU7CiAgICAgIHRocm93IGU7CiAgICB9IGZpbmFsbHkgewogICAgICBmaW5hbGl6ZXIoKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIE5PT1AoKSB7fQoKICBmdW5jdGlvbiBfaW5zdHJ1bWVudFN0YXJ0KG5hbWUsIHBheWxvYWRGdW5jLCBwYXlsb2FkQXJnKSB7CiAgICBpZiAoc3Vic2NyaWJlcnMubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBOT09QOwogICAgfQoKICAgIHZhciBsaXN0ZW5lcnMgPSBjYWNoZVtuYW1lXTsKCiAgICBpZiAoIWxpc3RlbmVycykgewogICAgICBsaXN0ZW5lcnMgPSBwb3B1bGF0ZUxpc3RlbmVycyhuYW1lKTsKICAgIH0KCiAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gTk9PUDsKICAgIH0KCiAgICB2YXIgcGF5bG9hZCA9IHBheWxvYWRGdW5jKHBheWxvYWRBcmcpOwogICAgdmFyIFNUUlVDVFVSRURfUFJPRklMRSA9IF9lbnZpcm9ubWVudC5FTlYuU1RSVUNUVVJFRF9QUk9GSUxFOwogICAgdmFyIHRpbWVOYW1lOwoKICAgIGlmIChTVFJVQ1RVUkVEX1BST0ZJTEUpIHsKICAgICAgdGltZU5hbWUgPSBuYW1lICsgIjogIiArIHBheWxvYWQub2JqZWN0OwogICAgICBjb25zb2xlLnRpbWUodGltZU5hbWUpOwogICAgfQoKICAgIHZhciBiZWZvcmVWYWx1ZXMgPSBbXTsKICAgIHZhciB0aW1lc3RhbXAgPSB0aW1lKCk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldOwogICAgICBiZWZvcmVWYWx1ZXMucHVzaChsaXN0ZW5lci5iZWZvcmUobmFtZSwgdGltZXN0YW1wLCBwYXlsb2FkKSk7CiAgICB9CgogICAgcmV0dXJuIGZ1bmN0aW9uIF9pbnN0cnVtZW50RW5kKCkgewogICAgICB2YXIgdGltZXN0YW1wID0gdGltZSgpOwoKICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGxpc3RlbmVycy5sZW5ndGg7IF9pKyspIHsKICAgICAgICB2YXIgX2xpc3RlbmVyID0gbGlzdGVuZXJzW19pXTsKCiAgICAgICAgaWYgKHR5cGVvZiBfbGlzdGVuZXIuYWZ0ZXIgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIF9saXN0ZW5lci5hZnRlcihuYW1lLCB0aW1lc3RhbXAsIHBheWxvYWQsIGJlZm9yZVZhbHVlc1tfaV0pOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKFNUUlVDVFVSRURfUFJPRklMRSkgewogICAgICAgIGNvbnNvbGUudGltZUVuZCh0aW1lTmFtZSk7CiAgICAgIH0KICAgIH07CiAgfQogIC8qKgogICAgU3Vic2NyaWJlcyB0byBhIHBhcnRpY3VsYXIgZXZlbnQgb3IgaW5zdHJ1bWVudGVkIGJsb2NrIG9mIGNvZGUuCiAgCiAgICBAbWV0aG9kIHN1YnNjcmliZQogICAgQGZvciBAZW1iZXIvaW5zdHJ1bWVudGF0aW9uCiAgICBAc3RhdGljCiAgCiAgICBAcGFyYW0ge1N0cmluZ30gW3BhdHRlcm5dIE5hbWVzcGFjZWQgZXZlbnQgbmFtZS4KICAgIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBCZWZvcmUgYW5kIEFmdGVyIGhvb2tzLgogIAogICAgQHJldHVybiB7U3Vic2NyaWJlcn0KICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIHN1YnNjcmliZShwYXR0ZXJuLCBvYmplY3QpIHsKICAgIHZhciBwYXRocyA9IHBhdHRlcm4uc3BsaXQoJy4nKTsKICAgIHZhciBwYXRoOwogICAgdmFyIHJlZ2V4ZXMgPSBbXTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGhzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHBhdGggPSBwYXRoc1tpXTsKCiAgICAgIGlmIChwYXRoID09PSAnKicpIHsKICAgICAgICByZWdleGVzLnB1c2goJ1teXFwuXSonKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZWdleGVzLnB1c2gocGF0aCk7CiAgICAgIH0KICAgIH0KCiAgICB2YXIgcmVnZXggPSByZWdleGVzLmpvaW4oJ1xcLicpOwogICAgcmVnZXggPSByZWdleCArICIoXFwuLiopPyI7CiAgICB2YXIgc3Vic2NyaWJlciA9IHsKICAgICAgcGF0dGVybjogcGF0dGVybiwKICAgICAgcmVnZXg6IG5ldyBSZWdFeHAoIl4iICsgcmVnZXggKyAiJCIpLAogICAgICBvYmplY3Q6IG9iamVjdAogICAgfTsKICAgIHN1YnNjcmliZXJzLnB1c2goc3Vic2NyaWJlcik7CiAgICBjYWNoZSA9IHt9OwogICAgcmV0dXJuIHN1YnNjcmliZXI7CiAgfQogIC8qKgogICAgVW5zdWJzY3JpYmVzIGZyb20gYSBwYXJ0aWN1bGFyIGV2ZW50IG9yIGluc3RydW1lbnRlZCBibG9jayBvZiBjb2RlLgogIAogICAgQG1ldGhvZCB1bnN1YnNjcmliZQogICAgQGZvciBAZW1iZXIvaW5zdHJ1bWVudGF0aW9uCiAgICBAc3RhdGljCiAgCiAgICBAcGFyYW0ge09iamVjdH0gW3N1YnNjcmliZXJdCiAgICBAcHJpdmF0ZQogICovCgoKICBmdW5jdGlvbiB1bnN1YnNjcmliZShzdWJzY3JpYmVyKSB7CiAgICB2YXIgaW5kZXggPSAwOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3Vic2NyaWJlcnMubGVuZ3RoOyBpKyspIHsKICAgICAgaWYgKHN1YnNjcmliZXJzW2ldID09PSBzdWJzY3JpYmVyKSB7CiAgICAgICAgaW5kZXggPSBpOwogICAgICB9CiAgICB9CgogICAgc3Vic2NyaWJlcnMuc3BsaWNlKGluZGV4LCAxKTsKICAgIGNhY2hlID0ge307CiAgfQogIC8qKgogICAgUmVzZXRzIGBJbnN0cnVtZW50YXRpb25gIGJ5IGZsdXNoaW5nIGxpc3Qgb2Ygc3Vic2NyaWJlcnMuCiAgCiAgICBAbWV0aG9kIHJlc2V0CiAgICBAZm9yIEBlbWJlci9pbnN0cnVtZW50YXRpb24KICAgIEBzdGF0aWMKICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIHJlc2V0KCkgewogICAgc3Vic2NyaWJlcnMubGVuZ3RoID0gMDsKICAgIGNhY2hlID0ge307CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvbW9kaWZpZXIvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZ2xpbW1lciJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9nbGltbWVyKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJzZXRNb2RpZmllck1hbmFnZXIiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZ2xpbW1lci5zZXRNb2RpZmllck1hbmFnZXI7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiY2FwYWJpbHRpZXMiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZ2xpbW1lci5tb2RpZmllckNhcGFiaWxpdGllczsKICAgIH0KICB9KTsKfSk7CmRlZmluZSgiQGVtYmVyL29iamVjdC9jb21wYXQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2RlYnVnIiwgIkBnbGltbWVyL3JlZmVyZW5jZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX2RlYnVnLCBfcmVmZXJlbmNlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZXBlbmRlbnRLZXlDb21wYXQgPSBkZXBlbmRlbnRLZXlDb21wYXQ7CgogIHZhciB3cmFwR2V0dGVyU2V0dGVyID0gZnVuY3Rpb24gd3JhcEdldHRlclNldHRlcihfdGFyZ2V0LCBrZXksIGRlc2MpIHsKICAgIHZhciBvcmlnaW5hbEdldCA9IGRlc2MuZ2V0OwoKICAgIGlmIChvcmlnaW5hbEdldCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGRlc2MuZ2V0ID0gZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICAgIHZhciBwcm9wZXJ0eVRhZyA9ICgwLCBfbWV0YWwudGFnRm9yUHJvcGVydHkpKHRoaXMsIGtleSk7CiAgICAgICAgdmFyIHJldDsKICAgICAgICB2YXIgdGFnID0gKDAsIF9tZXRhbC50cmFjaykoZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0ID0gb3JpZ2luYWxHZXQuY2FsbChfdGhpcyk7CiAgICAgICAgfSk7CiAgICAgICAgKDAsIF9yZWZlcmVuY2UudXBkYXRlKShwcm9wZXJ0eVRhZywgdGFnKTsKICAgICAgICAoMCwgX21ldGFsLmNvbnN1bWUpKHRhZyk7CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfTsKICAgIH0KCiAgICByZXR1cm4gZGVzYzsKICB9OwoKICBmdW5jdGlvbiBkZXBlbmRlbnRLZXlDb21wYXQodGFyZ2V0LCBrZXksIGRlc2MpIHsKICAgIChmYWxzZSAmJiAhKEJvb2xlYW4odHJ1ZQogICAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgICApKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBkZXBlbmRlbnRLZXlDb21wYXQgZGVjb3JhdG9yIGNhbiBvbmx5IGJlIHVzZWQgaWYgdGhlIHRyYWNrZWQgcHJvcGVydGllcyBmZWF0dXJlIGlzIGVuYWJsZWQnLCBCb29sZWFuKHRydWUpKSk7CgogICAgaWYgKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKFt0YXJnZXQsIGtleSwgZGVzY10pKSB7CiAgICAgIGRlc2MgPSB0YXJnZXQ7CgogICAgICB2YXIgZGVjb3JhdG9yID0gZnVuY3Rpb24gZGVjb3JhdG9yKHRhcmdldCwga2V5LCBfZGVzYywgX21ldGEsIGlzQ2xhc3NpY0RlY29yYXRvcikgewogICAgICAgIChmYWxzZSAmJiAhKGlzQ2xhc3NpY0RlY29yYXRvcikgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgQGRlcGVuZGVudEtleUNvbXBhdCBkZWNvcmF0b3IgbWF5IG9ubHkgYmUgcGFzc2VkIGEgbWV0aG9kIHdoZW4gdXNlZCBpbiBjbGFzc2ljIGNsYXNzZXMuIFlvdSBzaG91bGQgZGVjb3JhdGUgZ2V0dGVycy9zZXR0ZXJzIGRpcmVjdGx5IGluIG5hdGl2ZSBjbGFzc2VzJywgaXNDbGFzc2ljRGVjb3JhdG9yKSk7CiAgICAgICAgKGZhbHNlICYmICEoZGVzYyAhPT0gbnVsbCAmJiB0eXBlb2YgZGVzYyA9PT0gJ29iamVjdCcgJiYgKHR5cGVvZiBkZXNjLmdldCA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgZGVzYy5zZXQgPT09ICdmdW5jdGlvbicpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBkZXBlbmRlbnRLZXlDb21wYXQoKSBkZWNvcmF0b3IgbXVzdCBiZSBwYXNzZWQgYSBnZXR0ZXIgb3Igc2V0dGVyIHdoZW4gdXNlZCBpbiBjbGFzc2ljIGNsYXNzZXMnLCBkZXNjICE9PSBudWxsICYmIHR5cGVvZiBkZXNjID09PSAnb2JqZWN0JyAmJiAodHlwZW9mIGRlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBkZXNjLnNldCA9PT0gJ2Z1bmN0aW9uJykpKTsKICAgICAgICByZXR1cm4gd3JhcEdldHRlclNldHRlcih0YXJnZXQsIGtleSwgZGVzYyk7CiAgICAgIH07CgogICAgICAoMCwgX21ldGFsLnNldENsYXNzaWNEZWNvcmF0b3IpKGRlY29yYXRvcik7CiAgICAgIHJldHVybiBkZWNvcmF0b3I7CiAgICB9CgogICAgKGZhbHNlICYmICEoZGVzYyAhPT0gbnVsbCAmJiB0eXBlb2YgZGVzYy5nZXQgPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIGRlc2Muc2V0ID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBAZGVwZW5kZW50S2V5Q29tcGF0IGRlY29yYXRvciBtdXN0IGJlIGFwcGxpZWQgdG8gZ2V0dGVycy9zZXR0ZXJzIHdoZW4gdXNlZCBpbiBuYXRpdmUgY2xhc3NlcycsIGRlc2MgIT09IG51bGwgJiYgdHlwZW9mIGRlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBkZXNjLnNldCA9PT0gJ2Z1bmN0aW9uJykpOwogICAgcmV0dXJuIHdyYXBHZXR0ZXJTZXR0ZXIodGFyZ2V0LCBrZXksIGRlc2MpOwogIH0KCiAgKDAsIF9tZXRhbC5zZXRDbGFzc2ljRGVjb3JhdG9yKShkZXBlbmRlbnRLZXlDb21wYXQpOwp9KTsKZGVmaW5lKCJAZW1iZXIvb2JqZWN0L2NvbXB1dGVkIiwgWyJleHBvcnRzIiwgIkBlbWJlci9vYmplY3QvbGliL2NvbXB1dGVkL2NvbXB1dGVkX21hY3JvcyIsICJAZW1iZXIvb2JqZWN0L2xpYi9jb21wdXRlZC9yZWR1Y2VfY29tcHV0ZWRfbWFjcm9zIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2NvbXB1dGVkX21hY3JvcywgX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImVtcHR5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXB1dGVkX21hY3Jvcy5lbXB0eTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJub3RFbXB0eSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3Mubm90RW1wdHk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAibm9uZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3Mubm9uZTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJub3QiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcHV0ZWRfbWFjcm9zLm5vdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJib29sIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXB1dGVkX21hY3Jvcy5ib29sOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIm1hdGNoIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXB1dGVkX21hY3Jvcy5tYXRjaDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJlcXVhbCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3MuZXF1YWw7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ3QiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcHV0ZWRfbWFjcm9zLmd0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImd0ZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3MuZ3RlOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImx0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXB1dGVkX21hY3Jvcy5sdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJsdGUiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcHV0ZWRfbWFjcm9zLmx0ZTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJvbmVXYXkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcHV0ZWRfbWFjcm9zLm9uZVdheTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJyZWFkT25seSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3MucmVhZE9ubHk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZGVwcmVjYXRpbmdBbGlhcyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3MuZGVwcmVjYXRpbmdBbGlhczsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJhbmQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcHV0ZWRfbWFjcm9zLmFuZDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJvciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3Mub3I7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic3VtIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3Muc3VtOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIm1pbiIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9yZWR1Y2VfY29tcHV0ZWRfbWFjcm9zLm1pbjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJtYXgiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcmVkdWNlX2NvbXB1dGVkX21hY3Jvcy5tYXg7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAibWFwIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MubWFwOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInNvcnQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcmVkdWNlX2NvbXB1dGVkX21hY3Jvcy5zb3J0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInNldERpZmYiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcmVkdWNlX2NvbXB1dGVkX21hY3Jvcy5zZXREaWZmOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIm1hcEJ5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MubWFwQnk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZmlsdGVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MuZmlsdGVyOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImZpbHRlckJ5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MuZmlsdGVyQnk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAidW5pcSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9yZWR1Y2VfY29tcHV0ZWRfbWFjcm9zLnVuaXE7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAidW5pcUJ5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MudW5pcUJ5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInVuaW9uIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MudW5pb247CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiaW50ZXJzZWN0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MuaW50ZXJzZWN0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImNvbGxlY3QiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcmVkdWNlX2NvbXB1dGVkX21hY3Jvcy5jb2xsZWN0OwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvb2JqZWN0L2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvcG9seWZpbGxzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlYnVnLCBfcG9seWZpbGxzLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmFjdGlvbiA9IHZvaWQgMDsKCiAgLyoqCiAgICBEZWNvcmF0b3IgdGhhdCB0dXJucyB0aGUgdGFyZ2V0IGZ1bmN0aW9uIGludG8gYW4gQWN0aW9uIHdoaWNoIGNhbiBiZSBhY2Nlc3NlZAogICAgZGlyZWN0bHkgYnkgcmVmZXJlbmNlLgogIAogICAgYGBganMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBhY3Rpb24sIHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgY2xhc3MgVG9vbHRpcCBleHRlbmRzIENvbXBvbmVudCB7CiAgICAgIEBhY3Rpb24KICAgICAgdG9nZ2xlU2hvd2luZygpIHsKICAgICAgICBzZXQodGhpcywgJ2lzU2hvd2luZycsICF0aGlzLmlzU2hvd2luZyk7CiAgICAgIH0KICAgIH0KICAgIGBgYAogICAgYGBgaGJzCiAgICA8IS0tIHRlbXBsYXRlLmhicyAtLT4KICAgIDxidXR0b24ge3thY3Rpb24gdGhpcy50b2dnbGVTaG93aW5nfX0+U2hvdyB0b29sdGlwPC9idXR0b24+CiAgCiAgICB7eyNpZiBpc1Nob3dpbmd9fQogICAgICA8ZGl2IGNsYXNzPSJ0b29sdGlwIj4KICAgICAgICBJJ20gYSB0b29sdGlwIQogICAgICA8L2Rpdj4KICAgIHt7L2lmfX0KICAgIGBgYAogIAogICAgRGVjb3JhdGVkIGFjdGlvbnMgYWxzbyBpbnRlcm9wIHdpdGggdGhlIHN0cmluZyBzdHlsZSB0ZW1wbGF0ZSBhY3Rpb25zOgogIAogICAgYGBgaGJzCiAgICA8IS0tIHRlbXBsYXRlLmhicyAtLT4KICAgIDxidXR0b24ge3thY3Rpb24gInRvZ2dsZVNob3dpbmcifX0+U2hvdyB0b29sdGlwPC9idXR0b24+CiAgCiAgICB7eyNpZiBpc1Nob3dpbmd9fQogICAgICA8ZGl2IGNsYXNzPSJ0b29sdGlwIj4KICAgICAgICBJJ20gYSB0b29sdGlwIQogICAgICA8L2Rpdj4KICAgIHt7L2lmfX0KICAgIGBgYAogIAogICAgSXQgYWxzbyBiaW5kcyB0aGUgZnVuY3Rpb24gZGlyZWN0bHkgdG8gdGhlIGluc3RhbmNlLCBzbyBpdCBjYW4gYmUgdXNlZCBpbiBhbnkKICAgIGNvbnRleHQgYW5kIHdpbGwgY29ycmVjdGx5IHJlZmVyIHRvIHRoZSBjbGFzcyBpdCBjYW1lIGZyb206CiAgCiAgICBgYGBoYnMKICAgIDwhLS0gdGVtcGxhdGUuaGJzIC0tPgogICAgPGJ1dHRvbgogICAgICB7e2RpZC1pbnNlcnQgdGhpcy50b2dnbGVTaG93aW5nfX0KICAgICAge3tvbiAiY2xpY2siIHRoaXMudG9nZ2xlU2hvd2luZ319CiAgICA+CiAgICAgIFNob3cgdG9vbHRpcAogICAgPC9idXR0b24+CiAgCiAgICB7eyNpZiBpc1Nob3dpbmd9fQogICAgICA8ZGl2IGNsYXNzPSJ0b29sdGlwIj4KICAgICAgICBJJ20gYSB0b29sdGlwIQogICAgICA8L2Rpdj4KICAgIHt7L2lmfX0KICAgIGBgYAogIAogICAgVGhpcyBjYW4gYWxzbyBiZSB1c2VkIGluIEphdmFTY3JpcHQgY29kZSBkaXJlY3RseToKICAKICAgIGBgYGpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgaW1wb3J0IHsgYWN0aW9uLCBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IGNsYXNzIFRvb2x0aXAgZXh0ZW5kcyBDb21wb25lbnQgewogICAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogIAogICAgICAgIC8vIHRoaXMudG9nZ2xlU2hvd2luZyBpcyBzdGlsbCBib3VuZCBjb3JyZWN0bHkgd2hlbiBhZGRlZCB0bwogICAgICAgIC8vIHRoZSBldmVudCBsaXN0ZW5lcgogICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy50b2dnbGVTaG93aW5nKTsKICAgICAgfQogIAogICAgICBAYWN0aW9uCiAgICAgIHRvZ2dsZVNob3dpbmcoKSB7CiAgICAgICAgc2V0KHRoaXMsICdpc1Nob3dpbmcnLCAhdGhpcy5pc1Nob3dpbmcpOwogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIFRoaXMgaXMgY29uc2lkZXJlZCBiZXN0IHByYWN0aWNlLCBzaW5jZSBpdCBtZWFucyB0aGF0IG1ldGhvZHMgd2lsbCBiZSBib3VuZAogICAgY29ycmVjdGx5IG5vIG1hdHRlciB3aGVyZSB0aGV5IGFyZSB1c2VkLiBCeSBjb250cmFzdCwgdGhlIGB7e2FjdGlvbn19YCBoZWxwZXIKICAgIGFuZCBtb2RpZmllciBjYW4gYWxzbyBiZSB1c2VkIHRvIGJpbmQgY29udGV4dCwgYnV0IGl0IHdpbGwgYmUgcmVxdWlyZWQgZm9yCiAgICBldmVyeSB1c2FnZSBvZiB0aGUgbWV0aG9kOgogIAogICAgYGBgaGJzCiAgICA8IS0tIHRlbXBsYXRlLmhicyAtLT4KICAgIDxidXR0b24KICAgICAge3tkaWQtaW5zZXJ0IChhY3Rpb24gdGhpcy50b2dnbGVTaG93aW5nKX19CiAgICAgIHt7b24gImNsaWNrIiAoYWN0aW9uIHRoaXMudG9nZ2xlU2hvd2luZyl9fQogICAgPgogICAgICBTaG93IHRvb2x0aXAKICAgIDwvYnV0dG9uPgogIAogICAge3sjaWYgaXNTaG93aW5nfX0KICAgICAgPGRpdiBjbGFzcz0idG9vbHRpcCI+CiAgICAgICAgSSdtIGEgdG9vbHRpcCEKICAgICAgPC9kaXY+CiAgICB7ey9pZn19CiAgICBgYGAKICAKICAgIFRoZXkgYWxzbyBkbyBub3QgaGF2ZSBlcXVpdmFsZW50cyBpbiBKYXZhU2NyaXB0IGRpcmVjdGx5LCBzbyB0aGV5IGNhbm5vdCBiZQogICAgdXNlZCBmb3Igb3RoZXIgc2l0dWF0aW9ucyB3aGVyZSBiaW5kaW5nIHdvdWxkIGJlIHVzZWZ1bC4KICAKICAgIEBwdWJsaWMKICAgIEBtZXRob2QgYWN0aW9uCiAgICBAY2F0ZWdvcnkgRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUCiAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7RnVuY3Rpb258dW5kZWZpbmVkfSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gdHVybiBpbnRvIGFuIGFjdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGVuIHVzZWQgaW4gY2xhc3NpYyBjbGFzc2VzCiAgICBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gcHJvcGVydHkgZGVjb3JhdG9yIGluc3RhbmNlCiAgKi8KICB2YXIgYWN0aW9uOwogIF9leHBvcnRzLmFjdGlvbiA9IGFjdGlvbjsKCiAgaWYgKHRydWUKICAvKiBFTUJFUl9OQVRJVkVfREVDT1JBVE9SX1NVUFBPUlQgKi8KICApIHsKICAgICAgdmFyIEJJTkRJTkdTX01BUCA9IG5ldyBXZWFrTWFwKCk7CgogICAgICB2YXIgc2V0dXBBY3Rpb24gPSBmdW5jdGlvbiBzZXR1cEFjdGlvbih0YXJnZXQsIGtleSwgYWN0aW9uRm4pIHsKICAgICAgICBpZiAodGFyZ2V0LmNvbnN0cnVjdG9yICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIHRhcmdldC5jb25zdHJ1Y3Rvci5wcm90byA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgICAgdGFyZ2V0LmNvbnN0cnVjdG9yLnByb3RvKCk7CiAgICAgICAgfQoKICAgICAgICBpZiAoIXRhcmdldC5oYXNPd25Qcm9wZXJ0eSgnYWN0aW9ucycpKSB7CiAgICAgICAgICB2YXIgcGFyZW50QWN0aW9ucyA9IHRhcmdldC5hY3Rpb25zOyAvLyB3ZSBuZWVkIHRvIGFzc2lnbiBiZWNhdXNlIG9mIHRoZSB3YXkgbWl4aW5zIGNvcHkgYWN0aW9ucyBkb3duIHdoZW4gaW5oZXJpdGluZwoKICAgICAgICAgIHRhcmdldC5hY3Rpb25zID0gcGFyZW50QWN0aW9ucyA/ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIHBhcmVudEFjdGlvbnMpIDoge307CiAgICAgICAgfQoKICAgICAgICB0YXJnZXQuYWN0aW9uc1trZXldID0gYWN0aW9uRm47CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgICAgICB2YXIgYmluZGluZ3MgPSBCSU5ESU5HU19NQVAuZ2V0KHRoaXMpOwoKICAgICAgICAgICAgaWYgKGJpbmRpbmdzID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICBiaW5kaW5ncyA9IG5ldyBNYXAoKTsKICAgICAgICAgICAgICBCSU5ESU5HU19NQVAuc2V0KHRoaXMsIGJpbmRpbmdzKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdmFyIGZuID0gYmluZGluZ3MuZ2V0KGFjdGlvbkZuKTsKCiAgICAgICAgICAgIGlmIChmbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgZm4gPSBhY3Rpb25Gbi5iaW5kKHRoaXMpOwogICAgICAgICAgICAgIGJpbmRpbmdzLnNldChhY3Rpb25GbiwgZm4pOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gZm47CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgfTsKCiAgICAgIF9leHBvcnRzLmFjdGlvbiA9IGFjdGlvbiA9IGZ1bmN0aW9uIGFjdGlvbih0YXJnZXQsIGtleSwgZGVzYykgewogICAgICAgIHZhciBhY3Rpb25GbjsKCiAgICAgICAgaWYgKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKFt0YXJnZXQsIGtleSwgZGVzY10pKSB7CiAgICAgICAgICBhY3Rpb25GbiA9IHRhcmdldDsKCiAgICAgICAgICB2YXIgZGVjb3JhdG9yID0gZnVuY3Rpb24gZGVjb3JhdG9yKHRhcmdldCwga2V5LCBkZXNjLCBtZXRhLCBpc0NsYXNzaWNEZWNvcmF0b3IpIHsKICAgICAgICAgICAgKGZhbHNlICYmICEoaXNDbGFzc2ljRGVjb3JhdG9yKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBAYWN0aW9uIGRlY29yYXRvciBtYXkgb25seSBiZSBwYXNzZWQgYSBtZXRob2Qgd2hlbiB1c2VkIGluIGNsYXNzaWMgY2xhc3Nlcy4gWW91IHNob3VsZCBkZWNvcmF0ZSBtZXRob2RzIGRpcmVjdGx5IGluIG5hdGl2ZSBjbGFzc2VzJywgaXNDbGFzc2ljRGVjb3JhdG9yKSk7CiAgICAgICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBhY3Rpb25GbiA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgYWN0aW9uKCkgZGVjb3JhdG9yIG11c3QgYmUgcGFzc2VkIGEgbWV0aG9kIHdoZW4gdXNlZCBpbiBjbGFzc2ljIGNsYXNzZXMnLCB0eXBlb2YgYWN0aW9uRm4gPT09ICdmdW5jdGlvbicpKTsKICAgICAgICAgICAgcmV0dXJuIHNldHVwQWN0aW9uKHRhcmdldCwga2V5LCBhY3Rpb25Gbik7CiAgICAgICAgICB9OwoKICAgICAgICAgICgwLCBfbWV0YWwuc2V0Q2xhc3NpY0RlY29yYXRvcikoZGVjb3JhdG9yKTsKICAgICAgICAgIHJldHVybiBkZWNvcmF0b3I7CiAgICAgICAgfQoKICAgICAgICBhY3Rpb25GbiA9IGRlc2MudmFsdWU7CiAgICAgICAgKGZhbHNlICYmICEodHlwZW9mIGFjdGlvbkZuID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBAYWN0aW9uIGRlY29yYXRvciBtdXN0IGJlIGFwcGxpZWQgdG8gbWV0aG9kcyB3aGVuIHVzZWQgaW4gbmF0aXZlIGNsYXNzZXMnLCB0eXBlb2YgYWN0aW9uRm4gPT09ICdmdW5jdGlvbicpKTsKICAgICAgICByZXR1cm4gc2V0dXBBY3Rpb24odGFyZ2V0LCBrZXksIGFjdGlvbkZuKTsKICAgICAgfTsKCiAgICAgICgwLCBfbWV0YWwuc2V0Q2xhc3NpY0RlY29yYXRvcikoYWN0aW9uKTsKICAgIH0KfSk7CmRlZmluZSgiQGVtYmVyL29iamVjdC9saWIvY29tcHV0ZWQvY29tcHV0ZWRfbWFjcm9zIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci9kZWJ1ZyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX2RlYnVnKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5lbXB0eSA9IGVtcHR5OwogIF9leHBvcnRzLm5vdEVtcHR5ID0gbm90RW1wdHk7CiAgX2V4cG9ydHMubm9uZSA9IG5vbmU7CiAgX2V4cG9ydHMubm90ID0gbm90OwogIF9leHBvcnRzLmJvb2wgPSBib29sOwogIF9leHBvcnRzLm1hdGNoID0gbWF0Y2g7CiAgX2V4cG9ydHMuZXF1YWwgPSBlcXVhbDsKICBfZXhwb3J0cy5ndCA9IGd0OwogIF9leHBvcnRzLmd0ZSA9IGd0ZTsKICBfZXhwb3J0cy5sdCA9IGx0OwogIF9leHBvcnRzLmx0ZSA9IGx0ZTsKICBfZXhwb3J0cy5vbmVXYXkgPSBvbmVXYXk7CiAgX2V4cG9ydHMucmVhZE9ubHkgPSByZWFkT25seTsKICBfZXhwb3J0cy5kZXByZWNhdGluZ0FsaWFzID0gZGVwcmVjYXRpbmdBbGlhczsKICBfZXhwb3J0cy5vciA9IF9leHBvcnRzLmFuZCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KICBmdW5jdGlvbiBleHBhbmRQcm9wZXJ0aWVzVG9BcnJheShwcmVkaWNhdGVOYW1lLCBwcm9wZXJ0aWVzKSB7CiAgICB2YXIgZXhwYW5kZWRQcm9wZXJ0aWVzID0gW107CgogICAgZnVuY3Rpb24gZXh0cmFjdFByb3BlcnR5KGVudHJ5KSB7CiAgICAgIGV4cGFuZGVkUHJvcGVydGllcy5wdXNoKGVudHJ5KTsKICAgIH0KCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BlcnRpZXMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1tpXTsKICAgICAgKGZhbHNlICYmICEocHJvcGVydHkuaW5kZXhPZignICcpIDwgMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJEZXBlbmRlbnQga2V5cyBwYXNzZWQgdG8gY29tcHV0ZWQuIiArIHByZWRpY2F0ZU5hbWUgKyAiKCkgY2FuJ3QgaGF2ZSBzcGFjZXMuIiwgcHJvcGVydHkuaW5kZXhPZignICcpIDwgMCkpOwogICAgICAoMCwgX21ldGFsLmV4cGFuZFByb3BlcnRpZXMpKHByb3BlcnR5LCBleHRyYWN0UHJvcGVydHkpOwogICAgfQoKICAgIHJldHVybiBleHBhbmRlZFByb3BlcnRpZXM7CiAgfQoKICBmdW5jdGlvbiBnZW5lcmF0ZUNvbXB1dGVkV2l0aFByZWRpY2F0ZShuYW1lLCBwcmVkaWNhdGUpIHsKICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBwcm9wZXJ0aWVzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIHByb3BlcnRpZXNbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKHByb3BlcnRpZXMpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBhdHRlbXB0ZWQgdG8gdXNlIEAiICsgbmFtZSArICIgYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBhdCBsZWFzdCBvbmUgZGVwZW5kZW50IGtleSBwYXJhbWV0ZXIiLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShwcm9wZXJ0aWVzKSkpOwogICAgICB2YXIgZGVwZW5kZW50S2V5cyA9IGV4cGFuZFByb3BlcnRpZXNUb0FycmF5KG5hbWUsIHByb3BlcnRpZXMpOwoKICAgICAgdmFyIGNvbXB1dGVkRnVuYyA9IF9tZXRhbC5jb21wdXRlZC5hcHBseSh2b2lkIDAsIGRlcGVuZGVudEtleXMuY29uY2F0KFtmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIGxhc3RJZHggPSBkZXBlbmRlbnRLZXlzLmxlbmd0aCAtIDE7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGFzdElkeDsgaSsrKSB7CiAgICAgICAgICB2YXIgdmFsdWUgPSAoMCwgX21ldGFsLmdldCkodGhpcywgZGVwZW5kZW50S2V5c1tpXSk7CgogICAgICAgICAgaWYgKCFwcmVkaWNhdGUodmFsdWUpKSB7CiAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkodGhpcywgZGVwZW5kZW50S2V5c1tsYXN0SWR4XSk7CiAgICAgIH1dKSk7CgogICAgICByZXR1cm4gY29tcHV0ZWRGdW5jOwogICAgfTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IG1hY3JvIHRoYXQgcmV0dXJucyB0cnVlIGlmIHRoZSB2YWx1ZSBvZiB0aGUgZGVwZW5kZW50CiAgICBwcm9wZXJ0eSBpcyBudWxsLCBhbiBlbXB0eSBzdHJpbmcsIGVtcHR5IGFycmF5LCBvciBlbXB0eSBmdW5jdGlvbi4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGVtcHR5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBUb0RvTGlzdCB7CiAgICAgIGNvbnN0cnVjdG9yKHRvZG9zKSB7CiAgICAgICAgc2V0KHRoaXMsICd0b2RvcycsIHRvZG9zKTsKICAgICAgfQogIAogICAgICBAZW1wdHkoJ3RvZG9zJykgaXNEb25lOwogICAgfQogIAogICAgbGV0IHRvZG9MaXN0ID0gbmV3IFRvRG9MaXN0KAogICAgICBbJ1VuaXQgVGVzdCcsICdEb2N1bWVudGF0aW9uJywgJ1JlbGVhc2UnXQogICAgKTsKICAKICAgIHRvZG9MaXN0LmlzRG9uZTsgLy8gZmFsc2UKICAgIHNldCh0b2RvTGlzdCwgJ3RvZG9zJywgW10pOwogICAgdG9kb0xpc3QuaXNEb25lOyAvLyB0cnVlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGVtcHR5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgVG9Eb0xpc3QgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBpc0RvbmU6IGVtcHR5KCd0b2RvcycpCiAgICB9KTsKICAKICAgIGxldCB0b2RvTGlzdCA9IFRvRG9MaXN0LmNyZWF0ZSh7CiAgICAgIHRvZG9zOiBbJ1VuaXQgVGVzdCcsICdEb2N1bWVudGF0aW9uJywgJ1JlbGVhc2UnXQogICAgfSk7CiAgCiAgICB0b2RvTGlzdC5pc0RvbmU7IC8vIGZhbHNlCiAgICBzZXQodG9kb0xpc3QsICd0b2RvcycsIFtdKTsKICAgIHRvZG9MaXN0LmlzRG9uZTsgLy8gdHJ1ZQogICAgYGBgCiAgCiAgICBAc2luY2UgMS42LjAKICAgIEBtZXRob2QgZW1wdHkKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggcmV0dXJucyB0cnVlIGlmIHRoZSB2YWx1ZQogICAgb2YgdGhlIGRlcGVuZGVudCBwcm9wZXJ0eSBpcyBudWxsLCBhbiBlbXB0eSBzdHJpbmcsIGVtcHR5IGFycmF5LCBvciBlbXB0eQogICAgZnVuY3Rpb24gYW5kIGZhbHNlIGlmIHRoZSB1bmRlcmx5aW5nIHZhbHVlIGlzIG5vdCBlbXB0eS4KICAKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZW1wdHkoZGVwZW5kZW50S2V5KSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAZW1wdHkgYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBhIGBkZXBlbmRlbnRLZXlgIHBhcmFtZXRlcicsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoZGVwZW5kZW50S2V5ICsgIi5sZW5ndGgiLCBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmlzRW1wdHkpKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpKTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRydWUgaWYgdGhlIHZhbHVlIG9mIHRoZSBkZXBlbmRlbnQgcHJvcGVydHkKICAgIGlzIE5PVCBudWxsLCBhbiBlbXB0eSBzdHJpbmcsIGVtcHR5IGFycmF5LCBvciBlbXB0eSBmdW5jdGlvbi4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG5vdEVtcHR5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgY29uc3RydWN0b3IoYmFja3BhY2spIHsKICAgICAgICBzZXQodGhpcywgJ2JhY2twYWNrJywgYmFja3BhY2spOwogICAgICB9CiAgCiAgICAgIEBub3RFbXB0eSgnYmFja3BhY2snKSBoYXNTdHVmZgogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigKICAgICAgWydGb29kJywgJ1NsZWVwaW5nIEJhZycsICdUZW50J10KICAgICk7CiAgCiAgICBoYW1zdGVyLmhhc1N0dWZmOyAvLyB0cnVlCiAgICBzZXQoaGFtc3RlciwgJ2JhY2twYWNrJywgW10pOwogICAgaGFtc3Rlci5oYXNTdHVmZjsgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbm90RW1wdHkgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgaGFzU3R1ZmY6IG5vdEVtcHR5KCdiYWNrcGFjaycpCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoewogICAgICBiYWNrcGFjazogWydGb29kJywgJ1NsZWVwaW5nIEJhZycsICdUZW50J10KICAgIH0pOwogIAogICAgaGFtc3Rlci5oYXNTdHVmZjsgLy8gdHJ1ZQogICAgc2V0KGhhbXN0ZXIsICdiYWNrcGFjaycsIFtdKTsKICAgIGhhbXN0ZXIuaGFzU3R1ZmY7IC8vIGZhbHNlCiAgICBgYGAKICAKICAgIEBtZXRob2Qgbm90RW1wdHkKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggcmV0dXJucyB0cnVlIGlmIG9yaWdpbmFsCiAgICB2YWx1ZSBmb3IgcHJvcGVydHkgaXMgbm90IGVtcHR5LgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBub3RFbXB0eShkZXBlbmRlbnRLZXkpIHsKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBub3RFbXB0eSBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGEgYGRlcGVuZGVudEtleWAgcGFyYW1ldGVyJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmNvbXB1dGVkKShkZXBlbmRlbnRLZXkgKyAiLmxlbmd0aCIsIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuICEoMCwgX21ldGFsLmlzRW1wdHkpKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpKTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRydWUgaWYgdGhlIHZhbHVlIG9mIHRoZSBkZXBlbmRlbnQgcHJvcGVydHkKICAgIGlzIG51bGwgb3IgdW5kZWZpbmVkLiBUaGlzIGF2b2lkcyBlcnJvcnMgZnJvbSBKU0xpbnQgY29tcGxhaW5pbmcgYWJvdXQgdXNlIG9mCiAgICA9PSwgd2hpY2ggY2FuIGJlIHRlY2huaWNhbGx5IGNvbmZ1c2luZy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbm9uZSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBub25lKCdmb29kJykgaXNIdW5ncnk7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKCk7CiAgCiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyB0cnVlCiAgCiAgICBzZXQoaGFtc3RlciwgJ2Zvb2QnLCAnQmFuYW5hJyk7CiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdmb29kJywgbnVsbCk7CiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyB0cnVlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG5vbmUgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgaXNIdW5ncnk6IG5vbmUoJ2Zvb2QnKQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyB0cnVlCiAgCiAgICBzZXQoaGFtc3RlciwgJ2Zvb2QnLCAnQmFuYW5hJyk7CiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdmb29kJywgbnVsbCk7CiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyB0cnVlCiAgICBgYGAKICAKICAgIEBtZXRob2Qgbm9uZQogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIHRydWUgaWYgb3JpZ2luYWwKICAgIHZhbHVlIGZvciBwcm9wZXJ0eSBpcyBudWxsIG9yIHVuZGVmaW5lZC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbm9uZShkZXBlbmRlbnRLZXkpIHsKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBub25lIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgZGVwZW5kZW50S2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuY29tcHV0ZWQpKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5pc05vbmUpKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpKTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRoZSBpbnZlcnNlIGJvb2xlYW4gdmFsdWUgb2YgdGhlIG9yaWdpbmFsCiAgICB2YWx1ZSBmb3IgdGhlIGRlcGVuZGVudCBwcm9wZXJ0eS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG5vdCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgVXNlciB7CiAgICAgIGxvZ2dlZEluID0gZmFsc2U7CiAgCiAgICAgIEBub3QoJ2xvZ2dlZEluJykgaXNBbm9ueW1vdXM7CiAgICB9CiAgCiAgICBsZXQgdXNlciA9IG5ldyBVc2VyKCk7CiAgCiAgICB1c2VyLmlzQW5vbnltb3VzOyAvLyB0cnVlCiAgICBzZXQodXNlciwgJ2xvZ2dlZEluJywgdHJ1ZSk7CiAgICB1c2VyLmlzQW5vbnltb3VzOyAvLyBmYWxzZQogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QsIHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBub3QgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBVc2VyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgbG9nZ2VkSW46IGZhbHNlLAogIAogICAgICBpc0Fub255bW91czogbm90KCdsb2dnZWRJbicpCiAgICB9KTsKICAKICAgIGxldCB1c2VyID0gVXNlci5jcmVhdGUoKTsKICAKICAgIHVzZXIuaXNBbm9ueW1vdXM7IC8vIHRydWUKICAgIHNldCh1c2VyLCAnbG9nZ2VkSW4nLCB0cnVlKTsKICAgIHVzZXIuaXNBbm9ueW1vdXM7IC8vIGZhbHNlCiAgICBgYGAKICAKICAgIEBtZXRob2Qgbm90CiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBwYXJhbSB7U3RyaW5nfSBkZXBlbmRlbnRLZXkKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgaW52ZXJzZSBvZiB0aGUKICAgIG9yaWdpbmFsIHZhbHVlIGZvciBwcm9wZXJ0eQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBub3QoZGVwZW5kZW50S2V5KSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAbm90IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgZGVwZW5kZW50S2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuY29tcHV0ZWQpKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gISgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpOwogICAgfSk7CiAgfQogIC8qKgogICAgQSBjb21wdXRlZCBwcm9wZXJ0eSB0aGF0IGNvbnZlcnRzIHRoZSBwcm92aWRlZCBkZXBlbmRlbnQgcHJvcGVydHkgaW50byBhCiAgICBib29sZWFuIHZhbHVlLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgYm9vbCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBib29sKCdudW1CYW5hbmFzJykgaGFzQmFuYW5hcwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgaGFtc3Rlci5oYXNCYW5hbmFzOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgMCk7CiAgICBoYW1zdGVyLmhhc0JhbmFuYXM7IC8vIGZhbHNlCiAgCiAgICBzZXQoaGFtc3RlciwgJ251bUJhbmFuYXMnLCAxKTsKICAgIGhhbXN0ZXIuaGFzQmFuYW5hczsgLy8gdHJ1ZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgbnVsbCk7CiAgICBoYW1zdGVyLmhhc0JhbmFuYXM7IC8vIGZhbHNlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGJvb2wgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgaGFzQmFuYW5hczogYm9vbCgnbnVtQmFuYW5hcycpCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoKTsKICAKICAgIGhhbXN0ZXIuaGFzQmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDApOwogICAgaGFtc3Rlci5oYXNCYW5hbmFzOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgMSk7CiAgICBoYW1zdGVyLmhhc0JhbmFuYXM7IC8vIHRydWUKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIG51bGwpOwogICAgaGFtc3Rlci5oYXNCYW5hbmFzOyAvLyBmYWxzZQogICAgYGBgCiAgCiAgICBAbWV0aG9kIGJvb2wKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggY29udmVydHMgdG8gYm9vbGVhbiB0aGUKICAgIG9yaWdpbmFsIHZhbHVlIGZvciBwcm9wZXJ0eQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBib29sKGRlcGVuZGVudEtleSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGJvb2wgYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBhIGBkZXBlbmRlbnRLZXlgIHBhcmFtZXRlcicsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoZGVwZW5kZW50S2V5LCBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBCb29sZWFuKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpKTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggbWF0Y2hlcyB0aGUgb3JpZ2luYWwgdmFsdWUgZm9yIHRoZSBkZXBlbmRlbnQKICAgIHByb3BlcnR5IGFnYWluc3QgYSBnaXZlbiBSZWdFeHAsIHJldHVybmluZyBgdHJ1ZWAgaWYgdGhlIHZhbHVlIG1hdGNoZXMgdGhlCiAgICBSZWdFeHAgYW5kIGBmYWxzZWAgaWYgaXQgZG9lcyBub3QuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBtYXRjaCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgVXNlciB7CiAgICAgIEBtYXRjaCgnZW1haWwnLCAvXi4rQC4rXC4uKyQvKSBoYXNWYWxpZEVtYWlsOwogICAgfQogIAogICAgbGV0IHVzZXIgPSBuZXcgVXNlcigpOwogIAogICAgdXNlci5oYXNWYWxpZEVtYWlsOyAvLyBmYWxzZQogIAogICAgc2V0KHVzZXIsICdlbWFpbCcsICcnKTsKICAgIHVzZXIuaGFzVmFsaWRFbWFpbDsgLy8gZmFsc2UKICAKICAgIHNldCh1c2VyLCAnZW1haWwnLCAnZW1iZXJfaGFtc3RlckBleGFtcGxlLmNvbScpOwogICAgdXNlci5oYXNWYWxpZEVtYWlsOyAvLyB0cnVlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG1hdGNoIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgVXNlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGhhc1ZhbGlkRW1haWw6IG1hdGNoKCdlbWFpbCcsIC9eLitALitcLi4rJC8pCiAgICB9KTsKICAKICAgIGxldCB1c2VyID0gVXNlci5jcmVhdGUoKTsKICAKICAgIHVzZXIuaGFzVmFsaWRFbWFpbDsgLy8gZmFsc2UKICAKICAgIHNldCh1c2VyLCAnZW1haWwnLCAnJyk7CiAgICB1c2VyLmhhc1ZhbGlkRW1haWw7IC8vIGZhbHNlCiAgCiAgICBzZXQodXNlciwgJ2VtYWlsJywgJ2VtYmVyX2hhbXN0ZXJAZXhhbXBsZS5jb20nKTsKICAgIHVzZXIuaGFzVmFsaWRFbWFpbDsgLy8gdHJ1ZQogICAgYGBgCiAgCiAgICBAbWV0aG9kIG1hdGNoCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBwYXJhbSB7U3RyaW5nfSBkZXBlbmRlbnRLZXkKICAgIEBwYXJhbSB7UmVnRXhwfSByZWdleHAKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIG1hdGNoIHRoZSBvcmlnaW5hbCB2YWx1ZQogICAgZm9yIHByb3BlcnR5IGFnYWluc3QgYSBnaXZlbiBSZWdFeHAKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbWF0Y2goZGVwZW5kZW50S2V5LCByZWdleHApIHsKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBtYXRjaCBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGBkZXBlbmRlbnRLZXlgIGFuZCBgcmVnZXhwYCBwYXJhbWV0ZXJzJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmNvbXB1dGVkKShkZXBlbmRlbnRLZXksIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIHZhbHVlID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIGRlcGVuZGVudEtleSk7CiAgICAgIHJldHVybiByZWdleHAudGVzdCh2YWx1ZSk7CiAgICB9KTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgcmV0dXJucyB0cnVlIGlmIHRoZSBwcm92aWRlZCBkZXBlbmRlbnQgcHJvcGVydHkgaXMKICAgIGVxdWFsIHRvIHRoZSBnaXZlbiB2YWx1ZS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGVxdWFsIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgQGVxdWFsKCdwZXJjZW50Q2Fycm90c0VhdGVuJywgMTAwKSBzYXRpc2ZpZWQ7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKCk7CiAgCiAgICBoYW1zdGVyLnNhdGlzZmllZDsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAncGVyY2VudENhcnJvdHNFYXRlbicsIDEwMCk7CiAgICBoYW1zdGVyLnNhdGlzZmllZDsgLy8gdHJ1ZQogIAogICAgc2V0KGhhbXN0ZXIsICdwZXJjZW50Q2Fycm90c0VhdGVuJywgNTApOwogICAgaGFtc3Rlci5zYXRpc2ZpZWQ7IC8vIGZhbHNlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGVxdWFsIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgSGFtc3RlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIHNhdGlzZmllZDogZXF1YWwoJ3BlcmNlbnRDYXJyb3RzRWF0ZW4nLCAxMDApCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoKTsKICAKICAgIGhhbXN0ZXIuc2F0aXNmaWVkOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdwZXJjZW50Q2Fycm90c0VhdGVuJywgMTAwKTsKICAgIGhhbXN0ZXIuc2F0aXNmaWVkOyAvLyB0cnVlCiAgCiAgICBzZXQoaGFtc3RlciwgJ3BlcmNlbnRDYXJyb3RzRWF0ZW4nLCA1MCk7CiAgICBoYW1zdGVyLnNhdGlzZmllZDsgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQG1ldGhvZCBlcXVhbAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ8T2JqZWN0fSB2YWx1ZQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggcmV0dXJucyB0cnVlIGlmIHRoZQogICAgb3JpZ2luYWwgdmFsdWUgZm9yIHByb3BlcnR5IGlzIGVxdWFsIHRvIHRoZSBnaXZlbiB2YWx1ZS4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZXF1YWwoZGVwZW5kZW50S2V5LCB2YWx1ZSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGVxdWFsIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYGRlcGVuZGVudEtleWAgYW5kIGB2YWx1ZWAgcGFyYW1ldGVyJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmNvbXB1dGVkKShkZXBlbmRlbnRLZXksIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpID09PSB2YWx1ZTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRydWUgaWYgdGhlIHByb3ZpZGVkIGRlcGVuZGVudCBwcm9wZXJ0eSBpcwogICAgZ3JlYXRlciB0aGFuIHRoZSBwcm92aWRlZCB2YWx1ZS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGd0IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgQGd0KCdudW1CYW5hbmFzJywgMTApIGhhc1Rvb01hbnlCYW5hbmFzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDExKTsKICAgIGhhbXN0ZXIuaGFzVG9vTWFueUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgZ3QgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgaGFzVG9vTWFueUJhbmFuYXM6IGd0KCdudW1CYW5hbmFzJywgMTApCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoKTsKICAKICAgIGhhbXN0ZXIuaGFzVG9vTWFueUJhbmFuYXM7IC8vIGZhbHNlCiAgCiAgICBzZXQoaGFtc3RlciwgJ251bUJhbmFuYXMnLCAzKTsKICAgIGhhbXN0ZXIuaGFzVG9vTWFueUJhbmFuYXM7IC8vIGZhbHNlCiAgCiAgICBzZXQoaGFtc3RlciwgJ251bUJhbmFuYXMnLCAxMSk7CiAgICBoYW1zdGVyLmhhc1Rvb01hbnlCYW5hbmFzOyAvLyB0cnVlCiAgICBgYGAKICAKICAgIEBtZXRob2QgZ3QKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHBhcmFtIHtOdW1iZXJ9IHZhbHVlCiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIHRydWUgaWYgdGhlCiAgICBvcmlnaW5hbCB2YWx1ZSBmb3IgcHJvcGVydHkgaXMgZ3JlYXRlciB0aGFuIGdpdmVuIHZhbHVlLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBndChkZXBlbmRlbnRLZXksIHZhbHVlKSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAZ3QgYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBgZGVwZW5kZW50S2V5YCBhbmQgYHZhbHVlYCBwYXJhbWV0ZXJzJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmNvbXB1dGVkKShkZXBlbmRlbnRLZXksIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpID4gdmFsdWU7CiAgICB9KTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgcmV0dXJucyB0cnVlIGlmIHRoZSBwcm92aWRlZCBkZXBlbmRlbnQgcHJvcGVydHkgaXMKICAgIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byB0aGUgcHJvdmlkZWQgdmFsdWUuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBndGUgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGNsYXNzIEhhbXN0ZXIgewogICAgICBAZ3RlKCdudW1CYW5hbmFzJywgMTApIGhhc1Rvb01hbnlCYW5hbmFzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDEwKTsKICAgIGhhbXN0ZXIuaGFzVG9vTWFueUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgZ3RlIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgSGFtc3RlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGhhc1Rvb01hbnlCYW5hbmFzOiBndGUoJ251bUJhbmFuYXMnLCAxMCkKICAgIH0pOwogIAogICAgbGV0IGhhbXN0ZXIgPSBIYW1zdGVyLmNyZWF0ZSgpOwogIAogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDEwKTsKICAgIGhhbXN0ZXIuaGFzVG9vTWFueUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQG1ldGhvZCBndGUKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHBhcmFtIHtOdW1iZXJ9IHZhbHVlCiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIHRydWUgaWYgdGhlCiAgICBvcmlnaW5hbCB2YWx1ZSBmb3IgcHJvcGVydHkgaXMgZ3JlYXRlciBvciBlcXVhbCB0aGVuIGdpdmVuIHZhbHVlLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBndGUoZGVwZW5kZW50S2V5LCB2YWx1ZSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGd0ZSBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGBkZXBlbmRlbnRLZXlgIGFuZCBgdmFsdWVgIHBhcmFtZXRlcnMnLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuY29tcHV0ZWQpKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIGRlcGVuZGVudEtleSkgPj0gdmFsdWU7CiAgICB9KTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgcmV0dXJucyB0cnVlIGlmIHRoZSBwcm92aWRlZCBkZXBlbmRlbnQgcHJvcGVydHkgaXMKICAgIGxlc3MgdGhhbiB0aGUgcHJvdmlkZWQgdmFsdWUuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBsdCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBsdCgnbnVtQmFuYW5hcycsIDMpIG5lZWRzTW9yZUJhbmFuYXM7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKCk7CiAgCiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5uZWVkc01vcmVCYW5hbmFzOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgMik7CiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbHQgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgbmVlZHNNb3JlQmFuYW5hczogbHQoJ251bUJhbmFuYXMnLCAzKQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5uZWVkc01vcmVCYW5hbmFzOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgMik7CiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQG1ldGhvZCBsdAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge051bWJlcn0gdmFsdWUKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgdHJ1ZSBpZiB0aGUKICAgIG9yaWdpbmFsIHZhbHVlIGZvciBwcm9wZXJ0eSBpcyBsZXNzIHRoZW4gZ2l2ZW4gdmFsdWUuCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGx0KGRlcGVuZGVudEtleSwgdmFsdWUpIHsKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBsdCBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGBkZXBlbmRlbnRLZXlgIGFuZCBgdmFsdWVgIHBhcmFtZXRlcnMnLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuY29tcHV0ZWQpKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIGRlcGVuZGVudEtleSkgPCB2YWx1ZTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRydWUgaWYgdGhlIHByb3ZpZGVkIGRlcGVuZGVudCBwcm9wZXJ0eSBpcwogICAgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHRoZSBwcm92aWRlZCB2YWx1ZS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGx0ZSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBsdGUoJ251bUJhbmFuYXMnLCAzKSBuZWVkc01vcmVCYW5hbmFzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgaGFtc3Rlci5uZWVkc01vcmVCYW5hbmFzOyAvLyB0cnVlCiAgCiAgICBzZXQoaGFtc3RlciwgJ251bUJhbmFuYXMnLCA1KTsKICAgIGhhbXN0ZXIubmVlZHNNb3JlQmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5uZWVkc01vcmVCYW5hbmFzOyAvLyB0cnVlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGx0ZSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBuZWVkc01vcmVCYW5hbmFzOiBsdGUoJ251bUJhbmFuYXMnLCAzKQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDUpOwogICAgaGFtc3Rlci5uZWVkc01vcmVCYW5hbmFzOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgMyk7CiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQG1ldGhvZCBsdGUKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHBhcmFtIHtOdW1iZXJ9IHZhbHVlCiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIHRydWUgaWYgdGhlCiAgICBvcmlnaW5hbCB2YWx1ZSBmb3IgcHJvcGVydHkgaXMgbGVzcyBvciBlcXVhbCB0aGFuIGdpdmVuIHZhbHVlLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBsdGUoZGVwZW5kZW50S2V5LCB2YWx1ZSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGx0ZSBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGBkZXBlbmRlbnRLZXlgIGFuZCBgdmFsdWVgIHBhcmFtZXRlcnMnLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuY29tcHV0ZWQpKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIGRlcGVuZGVudEtleSkgPD0gdmFsdWU7CiAgICB9KTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgcGVyZm9ybXMgYSBsb2dpY2FsIGBhbmRgIG9uIHRoZSBvcmlnaW5hbCB2YWx1ZXMgZm9yCiAgICB0aGUgcHJvdmlkZWQgZGVwZW5kZW50IHByb3BlcnRpZXMuCiAgCiAgICBZb3UgbWF5IHBhc3MgaW4gbW9yZSB0aGFuIHR3byBwcm9wZXJ0aWVzIGFuZCBldmVuIHVzZSBwcm9wZXJ0eSBicmFjZQogICAgZXhwYW5zaW9uLiAgVGhlIGNvbXB1dGVkIHByb3BlcnR5IHdpbGwgcmV0dXJuIHRoZSBmaXJzdCBmYWxzeSB2YWx1ZSBvciBsYXN0CiAgICB0cnV0aHkgdmFsdWUganVzdCBsaWtlIEphdmFTY3JpcHQncyBgJiZgIG9wZXJhdG9yLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgYW5kIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgQGFuZCgnaGFzVGVudCcsICdoYXNCYWNrcGFjaycpIHJlYWR5Rm9yQ2FtcDsKICAgICAgQGFuZCgnaGFzV2Fsa2luZ1N0aWNrJywgJ2hhc0JhY2twYWNrJykgcmVhZHlGb3JIaWtlOwogICAgfQogIAogICAgbGV0IHRvbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgdG9tc3Rlci5yZWFkeUZvckNhbXA7IC8vIGZhbHNlCiAgCiAgICBzZXQodG9tc3RlciwgJ2hhc1RlbnQnLCB0cnVlKTsKICAgIHRvbXN0ZXIucmVhZHlGb3JDYW1wOyAvLyBmYWxzZQogIAogICAgc2V0KHRvbXN0ZXIsICdoYXNCYWNrcGFjaycsIHRydWUpOwogICAgdG9tc3Rlci5yZWFkeUZvckNhbXA7IC8vIHRydWUKICAKICAgIHNldCh0b21zdGVyLCAnaGFzQmFja3BhY2snLCAnWWVzJyk7CiAgICB0b21zdGVyLnJlYWR5Rm9yQ2FtcDsgLy8gJ1llcycKICAKICAgIHNldCh0b21zdGVyLCAnaGFzV2Fsa2luZ1N0aWNrJywgbnVsbCk7CiAgICB0b21zdGVyLnJlYWR5Rm9ySGlrZTsgLy8gbnVsbAogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QsIHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBhbmQgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgcmVhZHlGb3JDYW1wOiBhbmQoJ2hhc1RlbnQnLCAnaGFzQmFja3BhY2snKSwKICAgICAgcmVhZHlGb3JIaWtlOiBhbmQoJ2hhc1dhbGtpbmdTdGljaycsICdoYXNCYWNrcGFjaycpCiAgICB9KTsKICAKICAgIGxldCB0b21zdGVyID0gSGFtc3Rlci5jcmVhdGUoKTsKICAKICAgIHRvbXN0ZXIucmVhZHlGb3JDYW1wOyAvLyBmYWxzZQogIAogICAgc2V0KHRvbXN0ZXIsICdoYXNUZW50JywgdHJ1ZSk7CiAgICB0b21zdGVyLnJlYWR5Rm9yQ2FtcDsgLy8gZmFsc2UKICAKICAgIHNldCh0b21zdGVyLCAnaGFzQmFja3BhY2snLCB0cnVlKTsKICAgIHRvbXN0ZXIucmVhZHlGb3JDYW1wOyAvLyB0cnVlCiAgCiAgICBzZXQodG9tc3RlciwgJ2hhc0JhY2twYWNrJywgJ1llcycpOwogICAgdG9tc3Rlci5yZWFkeUZvckNhbXA7IC8vICdZZXMnCiAgCiAgICBzZXQodG9tc3RlciwgJ2hhc1dhbGtpbmdTdGljaycsIG51bGwpOwogICAgdG9tc3Rlci5yZWFkeUZvckhpa2U7IC8vIG51bGwKICAgIGBgYAogIAogICAgQG1ldGhvZCBhbmQKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleSoKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHBlcmZvcm1zIGEgbG9naWNhbCBgYW5kYCBvbgogICAgdGhlIHZhbHVlcyBvZiBhbGwgdGhlIG9yaWdpbmFsIHZhbHVlcyBmb3IgcHJvcGVydGllcy4KICAgIEBwdWJsaWMKICAqLwoKCiAgdmFyIGFuZCA9IGdlbmVyYXRlQ29tcHV0ZWRXaXRoUHJlZGljYXRlKCdhbmQnLCBmdW5jdGlvbiAodmFsdWUpIHsKICAgIHJldHVybiB2YWx1ZTsKICB9KTsKICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggcGVyZm9ybXMgYSBsb2dpY2FsIGBvcmAgb24gdGhlIG9yaWdpbmFsIHZhbHVlcyBmb3IKICAgIHRoZSBwcm92aWRlZCBkZXBlbmRlbnQgcHJvcGVydGllcy4KICAKICAgIFlvdSBtYXkgcGFzcyBpbiBtb3JlIHRoYW4gdHdvIHByb3BlcnRpZXMgYW5kIGV2ZW4gdXNlIHByb3BlcnR5IGJyYWNlCiAgICBleHBhbnNpb24uICBUaGUgY29tcHV0ZWQgcHJvcGVydHkgd2lsbCByZXR1cm4gdGhlIGZpcnN0IHRydXRoeSB2YWx1ZSBvciBsYXN0CiAgICBmYWxzeSB2YWx1ZSBqdXN0IGxpa2UgSmF2YVNjcmlwdCdzIGB8fGAgb3BlcmF0b3IuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBvciB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBvcignaGFzSmFja2V0JywgJ2hhc1VtYnJlbGxhJykgcmVhZHlGb3JSYWluOwogICAgICBAb3IoJ2hhc1N1bnNjcmVlbicsICdoYXNVbWJyZWxsYScpIHJlYWR5Rm9yQmVhY2g7CiAgICB9CiAgCiAgICBsZXQgdG9tc3RlciA9IG5ldyBIYW1zdGVyKCk7CiAgCiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gdW5kZWZpbmVkCiAgCiAgICBzZXQodG9tc3RlciwgJ2hhc1VtYnJlbGxhJywgdHJ1ZSk7CiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gdHJ1ZQogIAogICAgc2V0KHRvbXN0ZXIsICdoYXNKYWNrZXQnLCAnWWVzJyk7CiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gJ1llcycKICAKICAgIHNldCh0b21zdGVyLCAnaGFzU3Vuc2NyZWVuJywgJ0NoZWNrJyk7CiAgICB0b21zdGVyLnJlYWR5Rm9yQmVhY2g7IC8vICdDaGVjaycKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgb3IgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgcmVhZHlGb3JSYWluOiBvcignaGFzSmFja2V0JywgJ2hhc1VtYnJlbGxhJyksCiAgICAgIHJlYWR5Rm9yQmVhY2g6IG9yKCdoYXNTdW5zY3JlZW4nLCAnaGFzVW1icmVsbGEnKQogICAgfSk7CiAgCiAgICBsZXQgdG9tc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gdW5kZWZpbmVkCiAgCiAgICBzZXQodG9tc3RlciwgJ2hhc1VtYnJlbGxhJywgdHJ1ZSk7CiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gdHJ1ZQogIAogICAgc2V0KHRvbXN0ZXIsICdoYXNKYWNrZXQnLCAnWWVzJyk7CiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gJ1llcycKICAKICAgIHNldCh0b21zdGVyLCAnaGFzU3Vuc2NyZWVuJywgJ0NoZWNrJyk7CiAgICB0b21zdGVyLnJlYWR5Rm9yQmVhY2g7IC8vICdDaGVjaycKICAgIGBgYAogIAogICAgQG1ldGhvZCBvcgogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5KgogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggcGVyZm9ybXMgYSBsb2dpY2FsIGBvcmAgb24KICAgIHRoZSB2YWx1ZXMgb2YgYWxsIHRoZSBvcmlnaW5hbCB2YWx1ZXMgZm9yIHByb3BlcnRpZXMuCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMuYW5kID0gYW5kOwogIHZhciBvciA9IGdlbmVyYXRlQ29tcHV0ZWRXaXRoUHJlZGljYXRlKCdvcicsIGZ1bmN0aW9uICh2YWx1ZSkgewogICAgcmV0dXJuICF2YWx1ZTsKICB9KTsKICAvKioKICAgIENyZWF0ZXMgYSBuZXcgcHJvcGVydHkgdGhhdCBpcyBhbiBhbGlhcyBmb3IgYW5vdGhlciBwcm9wZXJ0eSBvbiBhbiBvYmplY3QuCiAgICBDYWxscyB0byBgZ2V0YCBvciBgc2V0YCB0aGlzIHByb3BlcnR5IGJlaGF2ZSBhcyB0aG91Z2ggdGhleSB3ZXJlIGNhbGxlZCBvbiB0aGUKICAgIG9yaWdpbmFsIHByb3BlcnR5LgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgYWxpYXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGNsYXNzIFBlcnNvbiB7CiAgICAgIG5hbWUgPSAnQWxleCBNYXRjaG5lZXInOwogIAogICAgICBAYWxpYXMoJ25hbWUnKSBub21lbjsKICAgIH0KICAKICAgIGxldCBhbGV4ID0gbmV3IFBlcnNvbigpOwogIAogICAgYWxleC5ub21lbjsgLy8gJ0FsZXggTWF0Y2huZWVyJwogICAgYWxleC5uYW1lOyAgLy8gJ0FsZXggTWF0Y2huZWVyJwogIAogICAgc2V0KGFsZXgsICdub21lbicsICdAbWFjaHR5Jyk7CiAgICBhbGV4Lm5hbWU7ICAvLyAnQG1hY2h0eScKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgYWxpYXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBQZXJzb24gPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBuYW1lOiAnQWxleCBNYXRjaG5lZXInLAogIAogICAgICBub21lbjogYWxpYXMoJ25hbWUnKQogICAgfSk7CiAgCiAgICBsZXQgYWxleCA9IFBlcnNvbi5jcmVhdGUoKTsKICAKICAgIGFsZXgubm9tZW47IC8vICdBbGV4IE1hdGNobmVlcicKICAgIGFsZXgubmFtZTsgIC8vICdBbGV4IE1hdGNobmVlcicKICAKICAgIHNldChhbGV4LCAnbm9tZW4nLCAnQG1hY2h0eScpOwogICAgYWxleC5uYW1lOyAgLy8gJ0BtYWNodHknCiAgICBgYGAKICAKICAgIEBtZXRob2QgYWxpYXMKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggY3JlYXRlcyBhbiBhbGlhcyB0byB0aGUKICAgIG9yaWdpbmFsIHZhbHVlIGZvciBwcm9wZXJ0eS4KICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFdoZXJlIGBjb21wdXRlZC5hbGlhc2AgYWxpYXNlcyBgZ2V0YCBhbmQgYHNldGAsIGFuZCBhbGxvd3MgZm9yIGJpZGlyZWN0aW9uYWwKICAgIGRhdGEgZmxvdywgYGNvbXB1dGVkLm9uZVdheWAgb25seSBwcm92aWRlcyBhbiBhbGlhc2VkIGBnZXRgLiBUaGUgYHNldGAgd2lsbAogICAgbm90IG11dGF0ZSB0aGUgdXBzdHJlYW0gcHJvcGVydHksIHJhdGhlciBjYXVzZXMgdGhlIGN1cnJlbnQgcHJvcGVydHkgdG8gYmVjb21lCiAgICB0aGUgdmFsdWUgc2V0LiBUaGlzIGNhdXNlcyB0aGUgZG93bnN0cmVhbSBwcm9wZXJ0eSB0byBwZXJtYW5lbnRseSBkaXZlcmdlIGZyb20KICAgIHRoZSB1cHN0cmVhbSBwcm9wZXJ0eS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG9uZVdheSB9ZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBVc2VyIHsKICAgICAgY29uc3RydWN0b3IoZmlyc3ROYW1lLCBsYXN0TmFtZSkgewogICAgICAgIHNldCh0aGlzLCAnZmlyc3ROYW1lJywgZmlyc3ROYW1lKTsKICAgICAgICBzZXQodGhpcywgJ2xhc3ROYW1lJywgbGFzdE5hbWUpOwogICAgICB9CiAgCiAgICAgIEBvbmVXYXkoJ2ZpcnN0TmFtZScpIG5pY2tOYW1lOwogICAgfQogIAogICAgbGV0IHRlZGR5ID0gbmV3IFVzZXIoJ1RlZGR5JywgJ1plZW5ueScpOwogIAogICAgdGVkZHkubmlja05hbWU7IC8vICdUZWRkeScKICAKICAgIHNldCh0ZWRkeSwgJ25pY2tOYW1lJywgJ1RlZGR5QmVhcicpOwogICAgdGVkZHkuZmlyc3ROYW1lOyAvLyAnVGVkZHknCiAgICB0ZWRkeS5uaWNrTmFtZTsgLy8gJ1RlZGR5QmVhcicKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgb25lV2F5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgVXNlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGZpcnN0TmFtZTogbnVsbCwKICAgICAgbGFzdE5hbWU6IG51bGwsCiAgCiAgICAgIG5pY2tOYW1lOiBvbmVXYXkoJ2ZpcnN0TmFtZScpCiAgICB9KTsKICAKICAgIGxldCB0ZWRkeSA9IFVzZXIuY3JlYXRlKHsKICAgICAgZmlyc3ROYW1lOiAnVGVkZHknLAogICAgICBsYXN0TmFtZTogJ1plZW5ueScKICAgIH0pOwogIAogICAgdGVkZHkubmlja05hbWU7IC8vICdUZWRkeScKICAKICAgIHNldCh0ZWRkeSwgJ25pY2tOYW1lJywgJ1RlZGR5QmVhcicpOyAvLyAnVGVkZHlCZWFyJwogICAgdGVkZHkuZmlyc3ROYW1lOyAvLyAnVGVkZHknCiAgICB0ZWRkeS5uaWNrTmFtZTsgLy8gJ1RlZGR5QmVhcicKICAgIGBgYAogIAogICAgQG1ldGhvZCBvbmVXYXkKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggY3JlYXRlcyBhIG9uZSB3YXkgY29tcHV0ZWQKICAgIHByb3BlcnR5IHRvIHRoZSBvcmlnaW5hbCB2YWx1ZSBmb3IgcHJvcGVydHkuCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMub3IgPSBvcjsKCiAgZnVuY3Rpb24gb25lV2F5KGRlcGVuZGVudEtleSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQG9uZVdheSBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGEgYGRlcGVuZGVudEtleWAgcGFyYW1ldGVyJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmFsaWFzKShkZXBlbmRlbnRLZXkpLm9uZVdheSgpOwogIH0KICAvKioKICAgIFRoaXMgaXMgYSBtb3JlIHNlbWFudGljYWxseSBtZWFuaW5nZnVsIGFsaWFzIG9mIGBjb21wdXRlZC5vbmVXYXlgLCB3aG9zZSBuYW1lCiAgICBpcyBzb21ld2hhdCBhbWJpZ3VvdXMgYXMgdG8gd2hpY2ggZGlyZWN0aW9uIHRoZSBkYXRhIGZsb3dzLgogIAogICAgQG1ldGhvZCByZWFkcwogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCBjcmVhdGVzIGEgb25lIHdheSBjb21wdXRlZAogICAgICBwcm9wZXJ0eSB0byB0aGUgb3JpZ2luYWwgdmFsdWUgZm9yIHByb3BlcnR5LgogICAgQHB1YmxpYwogICAqLwoKICAvKioKICAgIFdoZXJlIGBjb21wdXRlZC5vbmVXYXlgIHByb3ZpZGVzIG9uZVdheSBiaW5kaW5ncywgYGNvbXB1dGVkLnJlYWRPbmx5YCBwcm92aWRlcwogICAgYSByZWFkT25seSBvbmUgd2F5IGJpbmRpbmcuIFZlcnkgb2Z0ZW4gd2hlbiB1c2luZyBgY29tcHV0ZWQub25lV2F5YCBvbmUgZG9lcwogICAgbm90IGFsc28gd2FudCBjaGFuZ2VzIHRvIHByb3BhZ2F0ZSBiYWNrIHVwLCBhcyB0aGV5IHdpbGwgcmVwbGFjZSB0aGUgdmFsdWUuCiAgCiAgICBUaGlzIHByZXZlbnRzIHRoZSByZXZlcnNlIGZsb3csIGFuZCBhbHNvIHRocm93cyBhbiBleGNlcHRpb24gd2hlbiBpdCBvY2N1cnMuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyByZWFkT25seSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgVXNlciB7CiAgICAgIGNvbnN0cnVjdG9yKGZpcnN0TmFtZSwgbGFzdE5hbWUpIHsKICAgICAgICBzZXQodGhpcywgJ2ZpcnN0TmFtZScsIGZpcnN0TmFtZSk7CiAgICAgICAgc2V0KHRoaXMsICdsYXN0TmFtZScsIGxhc3ROYW1lKTsKICAgICAgfQogIAogICAgICBAcmVhZE9ubHkoJ2ZpcnN0TmFtZScpIG5pY2tOYW1lOwogICAgfSk7CiAgCiAgICBsZXQgdGVkZHkgPSBuZXcgVXNlcignVGVkZHknLCAnWmVlbm55Jyk7CiAgCiAgICB0ZWRkeS5uaWNrTmFtZTsgLy8gJ1RlZGR5JwogIAogICAgc2V0KHRlZGR5LCAnbmlja05hbWUnLCAnVGVkZHlCZWFyJyk7IC8vIHRocm93cyBFeGNlcHRpb24KICAgIC8vIHRocm93IG5ldyBFbWJlckVycm9yKCdDYW5ub3QgU2V0OiBuaWNrTmFtZSBvbjogPFVzZXI6ZW1iZXIyNzI4OD4nICk7YAogIAogICAgdGVkZHkuZmlyc3ROYW1lOyAvLyAnVGVkZHknCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IHJlYWRPbmx5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgVXNlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGZpcnN0TmFtZTogbnVsbCwKICAgICAgbGFzdE5hbWU6IG51bGwsCiAgCiAgICAgIG5pY2tOYW1lOiByZWFkT25seSgnZmlyc3ROYW1lJykKICAgIH0pOwogIAogICAgbGV0IHRlZGR5ID0gVXNlci5jcmVhdGUoewogICAgICBmaXJzdE5hbWU6ICdUZWRkeScsCiAgICAgIGxhc3ROYW1lOiAgJ1plZW5ueScKICAgIH0pOwogIAogICAgdGVkZHkubmlja05hbWU7IC8vICdUZWRkeScKICAKICAgIHNldCh0ZWRkeSwgJ25pY2tOYW1lJywgJ1RlZGR5QmVhcicpOyAvLyB0aHJvd3MgRXhjZXB0aW9uCiAgICAvLyB0aHJvdyBuZXcgRW1iZXJFcnJvcignQ2Fubm90IFNldDogbmlja05hbWUgb246IDxVc2VyOmVtYmVyMjcyODg+JyApO2AKICAKICAgIHRlZGR5LmZpcnN0TmFtZTsgLy8gJ1RlZGR5JwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHJlYWRPbmx5CiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBwYXJhbSB7U3RyaW5nfSBkZXBlbmRlbnRLZXkKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIGNyZWF0ZXMgYSBvbmUgd2F5IGNvbXB1dGVkCiAgICBwcm9wZXJ0eSB0byB0aGUgb3JpZ2luYWwgdmFsdWUgZm9yIHByb3BlcnR5LgogICAgQHNpbmNlIDEuNS4wCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIHJlYWRPbmx5KGRlcGVuZGVudEtleSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQHJlYWRPbmx5IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgZGVwZW5kZW50S2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuYWxpYXMpKGRlcGVuZGVudEtleSkucmVhZE9ubHkoKTsKICB9CiAgLyoqCiAgICBDcmVhdGVzIGEgbmV3IHByb3BlcnR5IHRoYXQgaXMgYW4gYWxpYXMgZm9yIGFub3RoZXIgcHJvcGVydHkgb24gYW4gb2JqZWN0LgogICAgQ2FsbHMgdG8gYGdldGAgb3IgYHNldGAgdGhpcyBwcm9wZXJ0eSBiZWhhdmUgYXMgdGhvdWdoIHRoZXkgd2VyZSBjYWxsZWQgb24gdGhlCiAgICBvcmlnaW5hbCBwcm9wZXJ0eSwgYnV0IGFsc28gcHJpbnQgYSBkZXByZWNhdGlvbiB3YXJuaW5nLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgZGVwcmVjYXRpbmdBbGlhcyB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBkZXByZWNhdGluZ0FsaWFzKCdjYXZlbmRpc2hDb3VudCcsIHsKICAgICAgICBpZDogJ2hhbXN0ZXIuZGVwcmVjYXRlLWJhbmFuYScsCiAgICAgICAgdW50aWw6ICczLjAuMCcKICAgICAgfSkKICAgICAgYmFuYW5hQ291bnQ7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKCk7CiAgCiAgICBzZXQoaGFtc3RlciwgJ2JhbmFuYUNvdW50JywgNSk7IC8vIFByaW50cyBhIGRlcHJlY2F0aW9uIHdhcm5pbmcuCiAgICBoYW1zdGVyLmNhdmVuZGlzaENvdW50OyAvLyA1CiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGRlcHJlY2F0aW5nQWxpYXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgYmFuYW5hQ291bnQ6IGRlcHJlY2F0aW5nQWxpYXMoJ2NhdmVuZGlzaENvdW50JywgewogICAgICAgIGlkOiAnaGFtc3Rlci5kZXByZWNhdGUtYmFuYW5hJywKICAgICAgICB1bnRpbDogJzMuMC4wJwogICAgICB9KQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICBzZXQoaGFtc3RlciwgJ2JhbmFuYUNvdW50JywgNSk7IC8vIFByaW50cyBhIGRlcHJlY2F0aW9uIHdhcm5pbmcuCiAgICBoYW1zdGVyLmNhdmVuZGlzaENvdW50OyAvLyA1CiAgICBgYGAKICAKICAgIEBtZXRob2QgZGVwcmVjYXRpbmdBbGlhcwogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBPcHRpb25zIGZvciBgZGVwcmVjYXRlYC4KICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIGNyZWF0ZXMgYW4gYWxpYXMgd2l0aCBhCiAgICBkZXByZWNhdGlvbiB0byB0aGUgb3JpZ2luYWwgdmFsdWUgZm9yIHByb3BlcnR5LgogICAgQHNpbmNlIDEuNy4wCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGRlcHJlY2F0aW5nQWxpYXMoZGVwZW5kZW50S2V5LCBvcHRpb25zKSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAZGVwcmVjYXRpbmdBbGlhcyBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGBkZXBlbmRlbnRLZXlgIGFuZCBgb3B0aW9uc2AgcGFyYW1ldGVycycsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoZGVwZW5kZW50S2V5LCB7CiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIlVzYWdlIG9mIGAiICsga2V5ICsgImAgaXMgZGVwcmVjYXRlZCwgdXNlIGAiICsgZGVwZW5kZW50S2V5ICsgImAgaW5zdGVhZC4iLCBmYWxzZSwgb3B0aW9ucykpOwogICAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkodGhpcywgZGVwZW5kZW50S2V5KTsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5LCB2YWx1ZSkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIlVzYWdlIG9mIGAiICsga2V5ICsgImAgaXMgZGVwcmVjYXRlZCwgdXNlIGAiICsgZGVwZW5kZW50S2V5ICsgImAgaW5zdGVhZC4iLCBmYWxzZSwgb3B0aW9ucykpOwogICAgICAgICgwLCBfbWV0YWwuc2V0KSh0aGlzLCBkZXBlbmRlbnRLZXksIHZhbHVlKTsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0KICAgIH0pOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyL29iamVjdC9saWIvY29tcHV0ZWQvcmVkdWNlX2NvbXB1dGVkX21hY3JvcyIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9kZWJ1ZywgX21ldGFsLCBfcnVudGltZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuc3VtID0gc3VtOwogIF9leHBvcnRzLm1heCA9IG1heDsKICBfZXhwb3J0cy5taW4gPSBtaW47CiAgX2V4cG9ydHMubWFwID0gbWFwOwogIF9leHBvcnRzLm1hcEJ5ID0gbWFwQnk7CiAgX2V4cG9ydHMuZmlsdGVyID0gZmlsdGVyOwogIF9leHBvcnRzLmZpbHRlckJ5ID0gZmlsdGVyQnk7CiAgX2V4cG9ydHMudW5pcSA9IHVuaXE7CiAgX2V4cG9ydHMudW5pcUJ5ID0gdW5pcUJ5OwogIF9leHBvcnRzLmludGVyc2VjdCA9IGludGVyc2VjdDsKICBfZXhwb3J0cy5zZXREaWZmID0gc2V0RGlmZjsKICBfZXhwb3J0cy5jb2xsZWN0ID0gY29sbGVjdDsKICBfZXhwb3J0cy5zb3J0ID0gc29ydDsKICBfZXhwb3J0cy51bmlvbiA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KICBmdW5jdGlvbiByZWR1Y2VNYWNybyhkZXBlbmRlbnRLZXksIGNhbGxiYWNrLCBpbml0aWFsVmFsdWUsIG5hbWUpIHsKICAgIChmYWxzZSAmJiAhKCEvW1xbXF1ce1x9XS9nLnRlc3QoZGVwZW5kZW50S2V5KSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJEZXBlbmRlbnQga2V5IHBhc3NlZCB0byBgY29tcHV0ZWQuIiArIG5hbWUgKyAiYCBzaG91bGRuJ3QgY29udGFpbiBicmFjZSBleHBhbmRpbmcgcGF0dGVybi4iLCAhL1tcW1xdXHtcfV0vZy50ZXN0KGRlcGVuZGVudEtleSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmNvbXB1dGVkKShkZXBlbmRlbnRLZXkgKyAiLltdIiwgZnVuY3Rpb24gKCkgewogICAgICB2YXIgYXJyID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIGRlcGVuZGVudEtleSk7CgogICAgICBpZiAoYXJyID09PSBudWxsIHx8IHR5cGVvZiBhcnIgIT09ICdvYmplY3QnKSB7CiAgICAgICAgcmV0dXJuIGluaXRpYWxWYWx1ZTsKICAgICAgfQoKICAgICAgcmV0dXJuIGFyci5yZWR1Y2UoY2FsbGJhY2ssIGluaXRpYWxWYWx1ZSwgdGhpcyk7CiAgICB9KS5yZWFkT25seSgpOwogIH0KCiAgZnVuY3Rpb24gYXJyYXlNYWNybyhkZXBlbmRlbnRLZXksIGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzLCBjYWxsYmFjaykgewogICAgLy8gVGhpcyBpcyBhIGJpdCB1Z2x5CiAgICB2YXIgcHJvcGVydHlOYW1lOwoKICAgIGlmICgvQGVhY2gvLnRlc3QoZGVwZW5kZW50S2V5KSkgewogICAgICBwcm9wZXJ0eU5hbWUgPSBkZXBlbmRlbnRLZXkucmVwbGFjZSgvXC5AZWFjaC4qJC8sICcnKTsKICAgIH0gZWxzZSB7CiAgICAgIHByb3BlcnR5TmFtZSA9IGRlcGVuZGVudEtleTsKICAgICAgZGVwZW5kZW50S2V5ICs9ICcuW10nOwogICAgfQoKICAgIHJldHVybiBfbWV0YWwuY29tcHV0ZWQuYXBwbHkodm9pZCAwLCBbZGVwZW5kZW50S2V5XS5jb25jYXQoYWRkaXRpb25hbERlcGVuZGVudEtleXMsIFtmdW5jdGlvbiAoKSB7CiAgICAgIHZhciB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBwcm9wZXJ0eU5hbWUpOwoKICAgICAgaWYgKCgwLCBfcnVudGltZS5pc0FycmF5KSh2YWx1ZSkpIHsKICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKGNhbGxiYWNrLmNhbGwodGhpcywgdmFsdWUpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICAgIH0KICAgIH1dKSkucmVhZE9ubHkoKTsKICB9CgogIGZ1bmN0aW9uIG11bHRpQXJyYXlNYWNybyhfZGVwZW5kZW50S2V5cywgY2FsbGJhY2ssIG5hbWUpIHsKICAgIChmYWxzZSAmJiAhKF9kZXBlbmRlbnRLZXlzLmV2ZXJ5KGZ1bmN0aW9uIChkZXBlbmRlbnRLZXkpIHsKICAgICAgcmV0dXJuICEvW1xbXF1ce1x9XS9nLnRlc3QoZGVwZW5kZW50S2V5KTsKICAgIH0pKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkRlcGVuZGVudCBrZXlzIHBhc3NlZCB0byBgY29tcHV0ZWQuIiArIG5hbWUgKyAiYCBzaG91bGRuJ3QgY29udGFpbiBicmFjZSBleHBhbmRpbmcgcGF0dGVybi4iLCBfZGVwZW5kZW50S2V5cy5ldmVyeShmdW5jdGlvbiAoZGVwZW5kZW50S2V5KSB7CiAgICAgIHJldHVybiAhL1tcW1xdXHtcfV0vZy50ZXN0KGRlcGVuZGVudEtleSk7CiAgICB9KSkpOwoKICAgIHZhciBkZXBlbmRlbnRLZXlzID0gX2RlcGVuZGVudEtleXMubWFwKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgcmV0dXJuIGtleSArICIuW10iOwogICAgfSk7CgogICAgcmV0dXJuIF9tZXRhbC5jb21wdXRlZC5hcHBseSh2b2lkIDAsIGRlcGVuZGVudEtleXMuY29uY2F0KFtmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAoMCwgX3J1bnRpbWUuQSkoY2FsbGJhY2suY2FsbCh0aGlzLCBfZGVwZW5kZW50S2V5cykpOwogICAgfV0pKS5yZWFkT25seSgpOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRoZSBzdW0gb2YgdGhlIHZhbHVlcyBpbiB0aGUgZGVwZW5kZW50IGFycmF5LgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHN1bSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSW52b2ljZSB7CiAgICAgIGxpbmVJdGVtcyA9IFsxLjAwLCAyLjUwLCA5Ljk5XTsKICAKICAgICAgQHN1bSgnbGluZUl0ZW1zJykgdG90YWw7CiAgICB9CiAgCiAgICBsZXQgaW52b2ljZSA9IG5ldyBJbnZvaWNlKCk7CiAgCiAgICBpbnZvaWNlLnRvdGFsOyAvLyAxMy40OQogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBzdW0gfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBJbnZvaWNlID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgbGluZUl0ZW1zOiBbMS4wMCwgMi41MCwgOS45OV0sCiAgCiAgICAgIHRvdGFsOiBzdW0oJ2xpbmVJdGVtcycpCiAgICB9KQogIAogICAgbGV0IGludm9pY2UgPSBJbnZvaWNlLmNyZWF0ZSgpOwogIAogICAgaW52b2ljZS50b3RhbDsgLy8gMTMuNDkKICAgIGBgYAogIAogICAgQG1ldGhvZCBzdW0KICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHN0YXRpYwogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZXMgdGhlIHN1bSBvZiBhbGwgdmFsdWVzIGluIHRoZQogICAgZGVwZW5kZW50S2V5J3MgYXJyYXkKICAgIEBzaW5jZSAxLjQuMAogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBzdW0oZGVwZW5kZW50S2V5KSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAc3VtIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgZGVwZW5kZW50S2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIHJlZHVjZU1hY3JvKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKHN1bSwgaXRlbSkgewogICAgICByZXR1cm4gc3VtICsgaXRlbTsKICAgIH0sIDAsICdzdW0nKTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgY2FsY3VsYXRlcyB0aGUgbWF4aW11bSB2YWx1ZSBpbiB0aGUgZGVwZW5kZW50IGFycmF5LgogICAgVGhpcyB3aWxsIHJldHVybiBgLUluZmluaXR5YCB3aGVuIHRoZSBkZXBlbmRlbnQgYXJyYXkgaXMgZW1wdHkuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBtYXBCeSwgbWF4IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBQZXJzb24gewogICAgICBjaGlsZHJlbiA9IFtdOwogIAogICAgICBAbWFwQnkoJ2NoaWxkcmVuJywgJ2FnZScpIGNoaWxkQWdlczsKICAgICAgQG1heCgnY2hpbGRBZ2VzJykgbWF4Q2hpbGRBZ2U7CiAgICB9CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gbmV3IFBlcnNvbigpOwogIAogICAgbG9yZEJ5cm9uLm1heENoaWxkQWdlOyAvLyAtSW5maW5pdHkKICAKICAgIHNldChsb3JkQnlyb24sICdjaGlsZHJlbicsIFsKICAgICAgewogICAgICAgIG5hbWU6ICdBdWd1c3RhIEFkYSBCeXJvbicsCiAgICAgICAgYWdlOiA3CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLm1heENoaWxkQWdlOyAvLyA3CiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIC4uLmxvcmRCeXJvbi5jaGlsZHJlbiwKICAgICAgewogICAgICAgIG5hbWU6ICdBbGxlZ3JhIEJ5cm9uJywKICAgICAgICBhZ2U6IDUKICAgICAgfSwgewogICAgICAgIG5hbWU6ICdFbGl6YWJldGggTWVkb3JhIExlaWdoJywKICAgICAgICBhZ2U6IDgKICAgICAgfQogICAgXSk7CiAgICBsb3JkQnlyb24ubWF4Q2hpbGRBZ2U7IC8vIDgKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbWFwQnksIG1heCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGNoaWxkQWdlczogbWFwQnkoJ2NoaWxkcmVuJywgJ2FnZScpLAogICAgICBtYXhDaGlsZEFnZTogbWF4KCdjaGlsZEFnZXMnKQogICAgfSk7CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gUGVyc29uLmNyZWF0ZSh7IGNoaWxkcmVuOiBbXSB9KTsKICAKICAgIGxvcmRCeXJvbi5tYXhDaGlsZEFnZTsgLy8gLUluZmluaXR5CiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIHsKICAgICAgICBuYW1lOiAnQXVndXN0YSBBZGEgQnlyb24nLAogICAgICAgIGFnZTogNwogICAgICB9CiAgICBdKTsKICAgIGxvcmRCeXJvbi5tYXhDaGlsZEFnZTsgLy8gNwogIAogICAgc2V0KGxvcmRCeXJvbiwgJ2NoaWxkcmVuJywgWwogICAgICAuLi5sb3JkQnlyb24uY2hpbGRyZW4sCiAgICAgIHsKICAgICAgICBuYW1lOiAnQWxsZWdyYSBCeXJvbicsCiAgICAgICAgYWdlOiA1CiAgICAgIH0sIHsKICAgICAgICBuYW1lOiAnRWxpemFiZXRoIE1lZG9yYSBMZWlnaCcsCiAgICAgICAgYWdlOiA4CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLm1heENoaWxkQWdlOyAvLyA4CiAgICBgYGAKICAKICAgIElmIHRoZSB0eXBlcyBvZiB0aGUgYXJndW1lbnRzIGFyZSBub3QgbnVtYmVycywgdGhleSB3aWxsIGJlIGNvbnZlcnRlZCB0bwogICAgbnVtYmVycyBhbmQgdGhlIHR5cGUgb2YgdGhlIHJldHVybiB2YWx1ZSB3aWxsIGFsd2F5cyBiZSBgTnVtYmVyYC4gRm9yIGV4YW1wbGUsCiAgICB0aGUgbWF4IG9mIGEgbGlzdCBvZiBEYXRlIG9iamVjdHMgd2lsbCBiZSB0aGUgaGlnaGVzdCB0aW1lc3RhbXAgYXMgYSBgTnVtYmVyYC4KICAgIFRoaXMgYmVoYXZpb3IgaXMgY29uc2lzdGVudCB3aXRoIGBNYXRoLm1heGAuCiAgCiAgICBAbWV0aG9kIG1heAogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlcyB0aGUgbGFyZ2VzdCB2YWx1ZSBpbiB0aGUgZGVwZW5kZW50S2V5J3MKICAgIGFycmF5CiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIG1heChkZXBlbmRlbnRLZXkpIHsKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBtYXggYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBhIGBkZXBlbmRlbnRLZXlgIHBhcmFtZXRlcicsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICByZXR1cm4gcmVkdWNlTWFjcm8oZGVwZW5kZW50S2V5LCBmdW5jdGlvbiAobWF4LCBpdGVtKSB7CiAgICAgIHJldHVybiBNYXRoLm1heChtYXgsIGl0ZW0pOwogICAgfSwgLUluZmluaXR5LCAnbWF4Jyk7CiAgfQogIC8qKgogICAgQSBjb21wdXRlZCBwcm9wZXJ0eSB0aGF0IGNhbGN1bGF0ZXMgdGhlIG1pbmltdW0gdmFsdWUgaW4gdGhlIGRlcGVuZGVudCBhcnJheS4KICAgIFRoaXMgd2lsbCByZXR1cm4gYEluZmluaXR5YCB3aGVuIHRoZSBkZXBlbmRlbnQgYXJyYXkgaXMgZW1wdHkuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBtYXBCeSwgbWluIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBQZXJzb24gewogICAgICBjaGlsZHJlbiA9IFtdOwogIAogICAgICBAbWFwQnkoJ2NoaWxkcmVuJywgJ2FnZScpIGNoaWxkQWdlczsKICAgICAgQG1pbignY2hpbGRBZ2VzJykgbWluQ2hpbGRBZ2U7CiAgICB9CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gUGVyc29uLmNyZWF0ZSh7IGNoaWxkcmVuOiBbXSB9KTsKICAKICAgIGxvcmRCeXJvbi5taW5DaGlsZEFnZTsgLy8gSW5maW5pdHkKICAKICAgIHNldChsb3JkQnlyb24sICdjaGlsZHJlbicsIFsKICAgICAgewogICAgICAgIG5hbWU6ICdBdWd1c3RhIEFkYSBCeXJvbicsCiAgICAgICAgYWdlOiA3CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLm1pbkNoaWxkQWdlOyAvLyA3CiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIC4uLmxvcmRCeXJvbi5jaGlsZHJlbiwKICAgICAgewogICAgICAgIG5hbWU6ICdBbGxlZ3JhIEJ5cm9uJywKICAgICAgICBhZ2U6IDUKICAgICAgfSwgewogICAgICAgIG5hbWU6ICdFbGl6YWJldGggTWVkb3JhIExlaWdoJywKICAgICAgICBhZ2U6IDgKICAgICAgfQogICAgXSk7CiAgICBsb3JkQnlyb24ubWluQ2hpbGRBZ2U7IC8vIDUKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbWFwQnksIG1pbiB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGNoaWxkQWdlczogbWFwQnkoJ2NoaWxkcmVuJywgJ2FnZScpLAogICAgICBtaW5DaGlsZEFnZTogbWluKCdjaGlsZEFnZXMnKQogICAgfSk7CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gUGVyc29uLmNyZWF0ZSh7IGNoaWxkcmVuOiBbXSB9KTsKICAKICAgIGxvcmRCeXJvbi5taW5DaGlsZEFnZTsgLy8gSW5maW5pdHkKICAKICAgIHNldChsb3JkQnlyb24sICdjaGlsZHJlbicsIFsKICAgICAgewogICAgICAgIG5hbWU6ICdBdWd1c3RhIEFkYSBCeXJvbicsCiAgICAgICAgYWdlOiA3CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLm1pbkNoaWxkQWdlOyAvLyA3CiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIC4uLmxvcmRCeXJvbi5jaGlsZHJlbiwKICAgICAgewogICAgICAgIG5hbWU6ICdBbGxlZ3JhIEJ5cm9uJywKICAgICAgICBhZ2U6IDUKICAgICAgfSwgewogICAgICAgIG5hbWU6ICdFbGl6YWJldGggTWVkb3JhIExlaWdoJywKICAgICAgICBhZ2U6IDgKICAgICAgfQogICAgXSk7CiAgICBsb3JkQnlyb24ubWluQ2hpbGRBZ2U7IC8vIDUKICAgIGBgYAogIAogICAgSWYgdGhlIHR5cGVzIG9mIHRoZSBhcmd1bWVudHMgYXJlIG5vdCBudW1iZXJzLCB0aGV5IHdpbGwgYmUgY29udmVydGVkIHRvCiAgICBudW1iZXJzIGFuZCB0aGUgdHlwZSBvZiB0aGUgcmV0dXJuIHZhbHVlIHdpbGwgYWx3YXlzIGJlIGBOdW1iZXJgLiBGb3IgZXhhbXBsZSwKICAgIHRoZSBtaW4gb2YgYSBsaXN0IG9mIERhdGUgb2JqZWN0cyB3aWxsIGJlIHRoZSBsb3dlc3QgdGltZXN0YW1wIGFzIGEgYE51bWJlcmAuCiAgICBUaGlzIGJlaGF2aW9yIGlzIGNvbnNpc3RlbnQgd2l0aCBgTWF0aC5taW5gLgogIAogICAgQG1ldGhvZCBtaW4KICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHN0YXRpYwogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZXMgdGhlIHNtYWxsZXN0IHZhbHVlIGluIHRoZSBkZXBlbmRlbnRLZXkncyBhcnJheQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBtaW4oZGVwZW5kZW50S2V5KSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAbWluIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgZGVwZW5kZW50S2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIHJlZHVjZU1hY3JvKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKG1pbiwgaXRlbSkgewogICAgICByZXR1cm4gTWF0aC5taW4obWluLCBpdGVtKTsKICAgIH0sIEluZmluaXR5LCAnbWluJyk7CiAgfQogIC8qKgogICAgUmV0dXJucyBhbiBhcnJheSBtYXBwZWQgdmlhIHRoZSBjYWxsYmFjawogIAogICAgVGhlIGNhbGxiYWNrIG1ldGhvZCB5b3UgcHJvdmlkZSBzaG91bGQgaGF2ZSB0aGUgZm9sbG93aW5nIHNpZ25hdHVyZToKICAgIC0gYGl0ZW1gIGlzIHRoZSBjdXJyZW50IGl0ZW0gaW4gdGhlIGl0ZXJhdGlvbi4KICAgIC0gYGluZGV4YCBpcyB0aGUgaW50ZWdlciBpbmRleCBvZiB0aGUgY3VycmVudCBpdGVtIGluIHRoZSBpdGVyYXRpb24uCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBmdW5jdGlvbiBtYXBDYWxsYmFjayhpdGVtLCBpbmRleCk7CiAgICBgYGAKICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG1hcCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIGNvbnN0cnVjdG9yKGNob3JlcykgewogICAgICAgIHNldCh0aGlzLCAnY2hvcmVzJywgY2hvcmVzKTsKICAgICAgfQogIAogICAgICBAbWFwKCdjaG9yZXMnLCBmdW5jdGlvbihjaG9yZSwgaW5kZXgpIHsKICAgICAgICByZXR1cm4gYCR7Y2hvcmUudG9VcHBlckNhc2UoKX0hYDsKICAgICAgfSkKICAgICAgZXhjaXRpbmdDaG9yZXM7CiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gbmV3IEhhbXN0ZXIoWydjbGVhbicsICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnXSk7CiAgCiAgICBoYW1zdGVyLmV4Y2l0aW5nQ2hvcmVzOyAvLyBbJ0NMRUFOIScsICdXUklURSBNT1JFIFVOSVQgVEVTVFMhJ10KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbWFwIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgSGFtc3RlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGV4Y2l0aW5nQ2hvcmVzOiBtYXAoJ2Nob3JlcycsIGZ1bmN0aW9uKGNob3JlLCBpbmRleCkgewogICAgICAgIHJldHVybiBgJHtjaG9yZS50b1VwcGVyQ2FzZSgpfSFgOwogICAgICB9KQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKHsKICAgICAgY2hvcmVzOiBbJ2NsZWFuJywgJ3dyaXRlIG1vcmUgdW5pdCB0ZXN0cyddCiAgICB9KTsKICAKICAgIGhhbXN0ZXIuZXhjaXRpbmdDaG9yZXM7IC8vIFsnQ0xFQU4hJywgJ1dSSVRFIE1PUkUgVU5JVCBURVNUUyEnXQogICAgYGBgCiAgCiAgICBZb3UgY2FuIG9wdGlvbmFsbHkgcGFzcyBhbiBhcnJheSBvZiBhZGRpdGlvbmFsIGRlcGVuZGVudCBrZXlzIGFzIHRoZSBzZWNvbmQKICAgIHBhcmFtZXRlciB0byB0aGUgbWFjcm8sIGlmIHlvdXIgbWFwIGZ1bmN0aW9uIHJlbGllcyBvbiBhbnkgZXh0ZXJuYWwgdmFsdWVzOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBtYXAgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGNsYXNzIEhhbXN0ZXIgewogICAgICBzaG91bGRVcHBlckNhc2UgPSBmYWxzZTsKICAKICAgICAgY29uc3RydWN0b3IoY2hvcmVzKSB7CiAgICAgICAgc2V0KHRoaXMsICdjaG9yZXMnLCBjaG9yZXMpOwogICAgICB9CiAgCiAgICAgIEBtYXAoJ2Nob3JlcycsIFsnc2hvdWxkVXBwZXJDYXNlJ10sIGZ1bmN0aW9uKGNob3JlLCBpbmRleCkgewogICAgICAgIGlmICh0aGlzLnNob3VsZFVwcGVyQ2FzZSkgewogICAgICAgICAgcmV0dXJuIGAke2Nob3JlLnRvVXBwZXJDYXNlKCl9IWA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBgJHtjaG9yZX0hYDsKICAgICAgICB9CiAgICAgIH0pCiAgICAgIGV4Y2l0aW5nQ2hvcmVzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcihbJ2NsZWFuJywgJ3dyaXRlIG1vcmUgdW5pdCB0ZXN0cyddKTsKICAKICAgIGhhbXN0ZXIuZXhjaXRpbmdDaG9yZXM7IC8vIFsnY2xlYW4hJywgJ3dyaXRlIG1vcmUgdW5pdCB0ZXN0cyEnXQogIAogICAgc2V0KGhhbXN0ZXIsICdzaG91bGRVcHBlckNhc2UnLCB0cnVlKTsKICAgIGhhbXN0ZXIuZXhjaXRpbmdDaG9yZXM7IC8vIFsnQ0xFQU4hJywgJ1dSSVRFIE1PUkUgVU5JVCBURVNUUyEnXQogICAgYGBgCiAgCiAgICBAbWV0aG9kIG1hcAogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge0FycmF5fSBbYWRkaXRpb25hbERlcGVuZGVudEtleXNdIG9wdGlvbmFsIGFycmF5IG9mIGFkZGl0aW9uYWwKICAgIGRlcGVuZGVudCBrZXlzCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gYW4gYXJyYXkgbWFwcGVkIHZpYSB0aGUgY2FsbGJhY2sKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbWFwKGRlcGVuZGVudEtleSwgYWRkaXRpb25hbERlcGVuZGVudEtleXMsIGNhbGxiYWNrKSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAbWFwIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBgZGVwZW5kZW50S2V5YCBhbmQgYGNhbGxiYWNrYCBwYXJhbWV0ZXJzJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKCiAgICBpZiAoY2FsbGJhY2sgPT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYWRkaXRpb25hbERlcGVuZGVudEtleXMgPT09ICdmdW5jdGlvbicpIHsKICAgICAgY2FsbGJhY2sgPSBhZGRpdGlvbmFsRGVwZW5kZW50S2V5czsKICAgICAgYWRkaXRpb25hbERlcGVuZGVudEtleXMgPSBbXTsKICAgIH0KCiAgICAoZmFsc2UgJiYgISh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnVGhlIGZpbmFsIHBhcmFtZXRlciBwcm92aWRlZCB0byBtYXAgbXVzdCBiZSBhIGNhbGxiYWNrIGZ1bmN0aW9uJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICAoZmFsc2UgJiYgIShBcnJheS5pc0FycmF5KGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgc2Vjb25kIHBhcmFtZXRlciBwcm92aWRlZCB0byBtYXAgbXVzdCBlaXRoZXIgYmUgdGhlIGNhbGxiYWNrIG9yIGFuIGFycmF5IG9mIGFkZGl0aW9uYWwgZGVwZW5kZW50IGtleXMnLCBBcnJheS5pc0FycmF5KGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzKSkpOwogICAgcmV0dXJuIGFycmF5TWFjcm8oZGVwZW5kZW50S2V5LCBhZGRpdGlvbmFsRGVwZW5kZW50S2V5cywgZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgIHJldHVybiB2YWx1ZS5tYXAoY2FsbGJhY2ssIHRoaXMpOwogICAgfSk7CiAgfQogIC8qKgogICAgUmV0dXJucyBhbiBhcnJheSBtYXBwZWQgdG8gdGhlIHNwZWNpZmllZCBrZXkuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBtYXBCeSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgUGVyc29uIHsKICAgICAgY2hpbGRyZW4gPSBbXTsKICAKICAgICAgQG1hcEJ5KCdjaGlsZHJlbicsICdhZ2UnKSBjaGlsZEFnZXM7CiAgICB9CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gbmV3IFBlcnNvbigpOwogIAogICAgbG9yZEJ5cm9uLmNoaWxkQWdlczsgLy8gW10KICAKICAgIHNldChsb3JkQnlyb24sICdjaGlsZHJlbicsIFsKICAgICAgewogICAgICAgIG5hbWU6ICdBdWd1c3RhIEFkYSBCeXJvbicsCiAgICAgICAgYWdlOiA3CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLmNoaWxkQWdlczsgLy8gWzddCiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIC4uLmxvcmRCeXJvbi5jaGlsZHJlbiwKICAgICAgewogICAgICAgIG5hbWU6ICdBbGxlZ3JhIEJ5cm9uJywKICAgICAgICBhZ2U6IDUKICAgICAgfSwgewogICAgICAgIG5hbWU6ICdFbGl6YWJldGggTWVkb3JhIExlaWdoJywKICAgICAgICBhZ2U6IDgKICAgICAgfQogICAgXSk7CiAgICBsb3JkQnlyb24uY2hpbGRBZ2VzOyAvLyBbNywgNSwgOF0KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbWFwQnkgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBQZXJzb24gPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBjaGlsZEFnZXM6IG1hcEJ5KCdjaGlsZHJlbicsICdhZ2UnKQogICAgfSk7CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gUGVyc29uLmNyZWF0ZSh7IGNoaWxkcmVuOiBbXSB9KTsKICAKICAgIGxvcmRCeXJvbi5jaGlsZEFnZXM7IC8vIFtdCiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIHsKICAgICAgICBuYW1lOiAnQXVndXN0YSBBZGEgQnlyb24nLAogICAgICAgIGFnZTogNwogICAgICB9CiAgICBdKTsKICAgIGxvcmRCeXJvbi5jaGlsZEFnZXM7IC8vIFs3XQogIAogICAgc2V0KGxvcmRCeXJvbiwgJ2NoaWxkcmVuJywgWwogICAgICAuLi5sb3JkQnlyb24uY2hpbGRyZW4sCiAgICAgIHsKICAgICAgICBuYW1lOiAnQWxsZWdyYSBCeXJvbicsCiAgICAgICAgYWdlOiA1CiAgICAgIH0sIHsKICAgICAgICBuYW1lOiAnRWxpemFiZXRoIE1lZG9yYSBMZWlnaCcsCiAgICAgICAgYWdlOiA4CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLmNoaWxkQWdlczsgLy8gWzcsIDUsIDhdCiAgICBgYGAKICAKICAgIEBtZXRob2QgbWFwQnkKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHN0YXRpYwogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5S2V5CiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBhbiBhcnJheSBtYXBwZWQgdG8gdGhlIHNwZWNpZmllZCBrZXkKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbWFwQnkoZGVwZW5kZW50S2V5LCBwcm9wZXJ0eUtleSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQG1hcEJ5IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYGRlcGVuZGVudEtleWAgYW5kIGBwcm9wZXJ0eUtleWAgcGFyYW1ldGVycycsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICAoZmFsc2UgJiYgISh0eXBlb2YgcHJvcGVydHlLZXkgPT09ICdzdHJpbmcnKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2Bjb21wdXRlZC5tYXBCeWAgZXhwZWN0cyBhIHByb3BlcnR5IHN0cmluZyBmb3IgaXRzIHNlY29uZCBhcmd1bWVudCwgJyArICdwZXJoYXBzIHlvdSBtZWFudCB0byB1c2UgIm1hcCInLCB0eXBlb2YgcHJvcGVydHlLZXkgPT09ICdzdHJpbmcnKSk7CiAgICAoZmFsc2UgJiYgISghL1tcW1xdXHtcfV0vZy50ZXN0KGRlcGVuZGVudEtleSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiRGVwZW5kZW50IGtleSBwYXNzZWQgdG8gYGNvbXB1dGVkLm1hcEJ5YCBzaG91bGRuJ3QgY29udGFpbiBicmFjZSBleHBhbmRpbmcgcGF0dGVybi4iLCAhL1tcW1xdXHtcfV0vZy50ZXN0KGRlcGVuZGVudEtleSkpKTsKICAgIHJldHVybiBtYXAoZGVwZW5kZW50S2V5ICsgIi5AZWFjaC4iICsgcHJvcGVydHlLZXksIGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkoaXRlbSwgcHJvcGVydHlLZXkpOwogICAgfSk7CiAgfQogIC8qKgogICAgRmlsdGVycyB0aGUgYXJyYXkgYnkgdGhlIGNhbGxiYWNrLgogIAogICAgVGhlIGNhbGxiYWNrIG1ldGhvZCB5b3UgcHJvdmlkZSBzaG91bGQgaGF2ZSB0aGUgZm9sbG93aW5nIHNpZ25hdHVyZToKICAgIC0gYGl0ZW1gIGlzIHRoZSBjdXJyZW50IGl0ZW0gaW4gdGhlIGl0ZXJhdGlvbi4KICAgIC0gYGluZGV4YCBpcyB0aGUgaW50ZWdlciBpbmRleCBvZiB0aGUgY3VycmVudCBpdGVtIGluIHRoZSBpdGVyYXRpb24uCiAgICAtIGBhcnJheWAgaXMgdGhlIGRlcGVuZGFudCBhcnJheSBpdHNlbGYuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBmdW5jdGlvbiBmaWx0ZXJDYWxsYmFjayhpdGVtLCBpbmRleCwgYXJyYXkpOwogICAgYGBgCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBmaWx0ZXIgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGNsYXNzIEhhbXN0ZXIgewogICAgICBjb25zdHJ1Y3RvcihjaG9yZXMpIHsKICAgICAgICBzZXQodGhpcywgJ2Nob3JlcycsIGNob3Jlcyk7CiAgICAgIH0KICAKICAgICAgQGZpbHRlcignY2hvcmVzJywgZnVuY3Rpb24oY2hvcmUsIGluZGV4LCBhcnJheSkgewogICAgICAgIHJldHVybiAhY2hvcmUuZG9uZTsKICAgICAgfSkKICAgICAgcmVtYWluaW5nQ2hvcmVzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBIYW1zdGVyLmNyZWF0ZShbCiAgICAgIHsgbmFtZTogJ2Nvb2snLCBkb25lOiB0cnVlIH0sCiAgICAgIHsgbmFtZTogJ2NsZWFuJywgZG9uZTogdHJ1ZSB9LAogICAgICB7IG5hbWU6ICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnLCBkb25lOiBmYWxzZSB9CiAgICBdKTsKICAKICAgIGhhbXN0ZXIucmVtYWluaW5nQ2hvcmVzOyAvLyBbe25hbWU6ICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnLCBkb25lOiBmYWxzZX1dCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGZpbHRlciB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICByZW1haW5pbmdDaG9yZXM6IGZpbHRlcignY2hvcmVzJywgZnVuY3Rpb24oY2hvcmUsIGluZGV4LCBhcnJheSkgewogICAgICAgIHJldHVybiAhY2hvcmUuZG9uZTsKICAgICAgfSkKICAgIH0pOwogIAogICAgbGV0IGhhbXN0ZXIgPSBIYW1zdGVyLmNyZWF0ZSh7CiAgICAgIGNob3JlczogWwogICAgICAgIHsgbmFtZTogJ2Nvb2snLCBkb25lOiB0cnVlIH0sCiAgICAgICAgeyBuYW1lOiAnY2xlYW4nLCBkb25lOiB0cnVlIH0sCiAgICAgICAgeyBuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2UgfQogICAgICBdCiAgICB9KTsKICAKICAgIGhhbXN0ZXIucmVtYWluaW5nQ2hvcmVzOyAvLyBbe25hbWU6ICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnLCBkb25lOiBmYWxzZX1dCiAgICBgYGAKICAKICAgIFlvdSBjYW4gYWxzbyB1c2UgYEBlYWNoLnByb3BlcnR5YCBpbiB5b3VyIGRlcGVuZGVudCBrZXksIHRoZSBjYWxsYmFjayB3aWxsCiAgICBzdGlsbCB1c2UgdGhlIHVuZGVybHlpbmcgYXJyYXk6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGZpbHRlciB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIGNvbnN0cnVjdG9yKGNob3JlcykgewogICAgICAgIHNldCh0aGlzLCAnY2hvcmVzJywgY2hvcmVzKTsKICAgICAgfQogIAogICAgICBAZmlsdGVyKCdjaG9yZXMuQGVhY2guZG9uZScsIGZ1bmN0aW9uKGNob3JlLCBpbmRleCwgYXJyYXkpIHsKICAgICAgICByZXR1cm4gIWNob3JlLmRvbmU7CiAgICAgIH0pCiAgICAgIHJlbWFpbmluZ0Nob3JlczsKICAgIH0KICAKICAgIGxldCBoYW1zdGVyID0gbmV3IEhhbXN0ZXIoWwogICAgICB7IG5hbWU6ICdjb29rJywgZG9uZTogdHJ1ZSB9LAogICAgICB7IG5hbWU6ICdjbGVhbicsIGRvbmU6IHRydWUgfSwKICAgICAgeyBuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2UgfQogICAgXSk7CiAgICBoYW1zdGVyLnJlbWFpbmluZ0Nob3JlczsgLy8gW3tuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2V9XQogIAogICAgc2V0KGhhbXN0ZXIuY2hvcmVzWzJdLCAnZG9uZScsIHRydWUpOwogICAgaGFtc3Rlci5yZW1haW5pbmdDaG9yZXM7IC8vIFtdCiAgICBgYGAKICAKICAgIEZpbmFsbHksIHlvdSBjYW4gb3B0aW9uYWxseSBwYXNzIGFuIGFycmF5IG9mIGFkZGl0aW9uYWwgZGVwZW5kZW50IGtleXMgYXMgdGhlCiAgICBzZWNvbmQgcGFyYW1ldGVyIHRvIHRoZSBtYWNybywgaWYgeW91ciBmaWx0ZXIgZnVuY3Rpb24gcmVsaWVzIG9uIGFueSBleHRlcm5hbAogICAgdmFsdWVzOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZmlsdGVyIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgY29uc3RydWN0b3IoY2hvcmVzKSB7CiAgICAgICAgc2V0KHRoaXMsICdjaG9yZXMnLCBjaG9yZXMpOwogICAgICB9CiAgCiAgICAgIGRvbmVLZXkgPSAnZmluaXNoZWQnOwogIAogICAgICBAZmlsdGVyKCdjaG9yZXMnLCBbJ2RvbmVLZXknXSwgZnVuY3Rpb24oY2hvcmUsIGluZGV4LCBhcnJheSkgewogICAgICAgIHJldHVybiAhY2hvcmVbdGhpcy5kb25lS2V5XTsKICAgICAgfSkKICAgICAgcmVtYWluaW5nQ2hvcmVzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcihbCiAgICAgIHsgbmFtZTogJ2Nvb2snLCBmaW5pc2hlZDogdHJ1ZSB9LAogICAgICB7IG5hbWU6ICdjbGVhbicsIGZpbmlzaGVkOiB0cnVlIH0sCiAgICAgIHsgbmFtZTogJ3dyaXRlIG1vcmUgdW5pdCB0ZXN0cycsIGZpbmlzaGVkOiBmYWxzZSB9CiAgICBdKTsKICAKICAgIGhhbXN0ZXIucmVtYWluaW5nQ2hvcmVzOyAvLyBbe25hbWU6ICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnLCBmaW5pc2hlZDogZmFsc2V9XQogICAgYGBgCiAgCiAgICBAbWV0aG9kIGZpbHRlcgogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge0FycmF5fSBbYWRkaXRpb25hbERlcGVuZGVudEtleXNdIG9wdGlvbmFsIGFycmF5IG9mIGFkZGl0aW9uYWwgZGVwZW5kZW50IGtleXMKICAgIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrCiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSB0aGUgZmlsdGVyZWQgYXJyYXkKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZmlsdGVyKGRlcGVuZGVudEtleSwgYWRkaXRpb25hbERlcGVuZGVudEtleXMsIGNhbGxiYWNrKSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAZmlsdGVyIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBgZGVwZW5kZW50S2V5YCBhbmQgYGNhbGxiYWNrYCBwYXJhbWV0ZXJzJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKCiAgICBpZiAoY2FsbGJhY2sgPT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYWRkaXRpb25hbERlcGVuZGVudEtleXMgPT09ICdmdW5jdGlvbicpIHsKICAgICAgY2FsbGJhY2sgPSBhZGRpdGlvbmFsRGVwZW5kZW50S2V5czsKICAgICAgYWRkaXRpb25hbERlcGVuZGVudEtleXMgPSBbXTsKICAgIH0KCiAgICAoZmFsc2UgJiYgISh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnVGhlIGZpbmFsIHBhcmFtZXRlciBwcm92aWRlZCB0byBmaWx0ZXIgbXVzdCBiZSBhIGNhbGxiYWNrIGZ1bmN0aW9uJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICAoZmFsc2UgJiYgIShBcnJheS5pc0FycmF5KGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgc2Vjb25kIHBhcmFtZXRlciBwcm92aWRlZCB0byBmaWx0ZXIgbXVzdCBlaXRoZXIgYmUgdGhlIGNhbGxiYWNrIG9yIGFuIGFycmF5IG9mIGFkZGl0aW9uYWwgZGVwZW5kZW50IGtleXMnLCBBcnJheS5pc0FycmF5KGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzKSkpOwogICAgcmV0dXJuIGFycmF5TWFjcm8oZGVwZW5kZW50S2V5LCBhZGRpdGlvbmFsRGVwZW5kZW50S2V5cywgZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgIHJldHVybiB2YWx1ZS5maWx0ZXIoY2FsbGJhY2ssIHRoaXMpOwogICAgfSk7CiAgfQogIC8qKgogICAgRmlsdGVycyB0aGUgYXJyYXkgYnkgdGhlIHByb3BlcnR5IGFuZCB2YWx1ZS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGZpbHRlckJ5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgY29uc3RydWN0b3IoY2hvcmVzKSB7CiAgICAgICAgc2V0KHRoaXMsICdjaG9yZXMnLCBjaG9yZXMpOwogICAgICB9CiAgCiAgICAgIEBmaWx0ZXJCeSgnY2hvcmVzJywgJ2RvbmUnLCBmYWxzZSkgcmVtYWluaW5nQ2hvcmVzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcihbCiAgICAgIHsgbmFtZTogJ2Nvb2snLCBkb25lOiB0cnVlIH0sCiAgICAgIHsgbmFtZTogJ2NsZWFuJywgZG9uZTogdHJ1ZSB9LAogICAgICB7IG5hbWU6ICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnLCBkb25lOiBmYWxzZSB9CiAgICBdKTsKICAKICAgIGhhbXN0ZXIucmVtYWluaW5nQ2hvcmVzOyAvLyBbeyBuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2UgfV0KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgZmlsdGVyQnkgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgcmVtYWluaW5nQ2hvcmVzOiBmaWx0ZXJCeSgnY2hvcmVzJywgJ2RvbmUnLCBmYWxzZSkKICAgIH0pOwogIAogICAgbGV0IGhhbXN0ZXIgPSBIYW1zdGVyLmNyZWF0ZSh7CiAgICAgIGNob3JlczogWwogICAgICAgIHsgbmFtZTogJ2Nvb2snLCBkb25lOiB0cnVlIH0sCiAgICAgICAgeyBuYW1lOiAnY2xlYW4nLCBkb25lOiB0cnVlIH0sCiAgICAgICAgeyBuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2UgfQogICAgICBdCiAgICB9KTsKICAKICAgIGhhbXN0ZXIucmVtYWluaW5nQ2hvcmVzOyAvLyBbeyBuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2UgfV0KICAgIGBgYAogIAogICAgQG1ldGhvZCBmaWx0ZXJCeQogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlLZXkKICAgIEBwYXJhbSB7Kn0gdmFsdWUKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IHRoZSBmaWx0ZXJlZCBhcnJheQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBmaWx0ZXJCeShkZXBlbmRlbnRLZXksIHByb3BlcnR5S2V5LCB2YWx1ZSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGZpbHRlckJ5IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBgZGVwZW5kZW50S2V5YCBhbmQgYHByb3BlcnR5S2V5YCBwYXJhbWV0ZXJzJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIChmYWxzZSAmJiAhKCEvW1xbXF1ce1x9XS9nLnRlc3QoZGVwZW5kZW50S2V5KSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJEZXBlbmRlbnQga2V5IHBhc3NlZCB0byBgY29tcHV0ZWQuZmlsdGVyQnlgIHNob3VsZG4ndCBjb250YWluIGJyYWNlIGV4cGFuZGluZyBwYXR0ZXJuLiIsICEvW1xbXF1ce1x9XS9nLnRlc3QoZGVwZW5kZW50S2V5KSkpOwogICAgdmFyIGNhbGxiYWNrOwoKICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyKSB7CiAgICAgIGNhbGxiYWNrID0gZnVuY3Rpb24gY2FsbGJhY2soaXRlbSkgewogICAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkoaXRlbSwgcHJvcGVydHlLZXkpOwogICAgICB9OwogICAgfSBlbHNlIHsKICAgICAgY2FsbGJhY2sgPSBmdW5jdGlvbiBjYWxsYmFjayhpdGVtKSB7CiAgICAgICAgcmV0dXJuICgwLCBfbWV0YWwuZ2V0KShpdGVtLCBwcm9wZXJ0eUtleSkgPT09IHZhbHVlOwogICAgICB9OwogICAgfQoKICAgIHJldHVybiBmaWx0ZXIoZGVwZW5kZW50S2V5ICsgIi5AZWFjaC4iICsgcHJvcGVydHlLZXksIGNhbGxiYWNrKTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgYSBuZXcgYXJyYXkgd2l0aCBhbGwgdGhlIHVuaXF1ZSBlbGVtZW50cwogICAgZnJvbSBvbmUgb3IgbW9yZSBkZXBlbmRlbnQgYXJyYXlzLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgdW5pcSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIGNvbnN0cnVjdG9yKGZydWl0cykgewogICAgICAgIHNldCh0aGlzLCAnZnJ1aXRzJywgZnJ1aXRzKTsKICAgICAgfQogIAogICAgICBAdW5pcSgnZnJ1aXRzJykgdW5pcXVlRnJ1aXRzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcihbCiAgICAgICdiYW5hbmEnLAogICAgICAnZ3JhcGUnLAogICAgICAna2FsZScsCiAgICAgICdiYW5hbmEnCiAgICBdKTsKICAKICAgIGhhbXN0ZXIudW5pcXVlRnJ1aXRzOyAvLyBbJ2JhbmFuYScsICdncmFwZScsICdrYWxlJ10KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgdW5pcSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICB1bmlxdWVGcnVpdHM6IHVuaXEoJ2ZydWl0cycpCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoewogICAgICBmcnVpdHM6IFsKICAgICAgICAnYmFuYW5hJywKICAgICAgICAnZ3JhcGUnLAogICAgICAgICdrYWxlJywKICAgICAgICAnYmFuYW5hJwogICAgICBdCiAgICB9KTsKICAKICAgIGhhbXN0ZXIudW5pcXVlRnJ1aXRzOyAvLyBbJ2JhbmFuYScsICdncmFwZScsICdrYWxlJ10KICAgIGBgYAogIAogICAgQG1ldGhvZCB1bmlxCiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eUtleSoKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVzIGEgbmV3IGFycmF5IHdpdGggYWxsIHRoZQogICAgdW5pcXVlIGVsZW1lbnRzIGZyb20gdGhlIGRlcGVuZGVudCBhcnJheQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiB1bmlxKCkgewogICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICB9CgogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQHVuaXEvQHVuaW9uIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBvbmUgZGVwZW5kZW50IGtleSBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIG11bHRpQXJyYXlNYWNybyhhcmdzLCBmdW5jdGlvbiAoZGVwZW5kZW50S2V5cykgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgdmFyIHVuaXEgPSAoMCwgX3J1bnRpbWUuQSkoKTsKICAgICAgdmFyIHNlZW4gPSBuZXcgU2V0KCk7CiAgICAgIGRlcGVuZGVudEtleXMuZm9yRWFjaChmdW5jdGlvbiAoZGVwZW5kZW50S2V5KSB7CiAgICAgICAgdmFyIHZhbHVlID0gKDAsIF9tZXRhbC5nZXQpKF90aGlzLCBkZXBlbmRlbnRLZXkpOwoKICAgICAgICBpZiAoKDAsIF9ydW50aW1lLmlzQXJyYXkpKHZhbHVlKSkgewogICAgICAgICAgdmFsdWUuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkgewogICAgICAgICAgICBpZiAoIXNlZW4uaGFzKGl0ZW0pKSB7CiAgICAgICAgICAgICAgc2Vlbi5hZGQoaXRlbSk7CiAgICAgICAgICAgICAgdW5pcS5wdXNoKGl0ZW0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gdW5pcTsKICAgIH0sICd1bmlxJyk7CiAgfQogIC8qKgogICAgQSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIGEgbmV3IGFycmF5IHdpdGggYWxsIHRoZSB1bmlxdWUgZWxlbWVudHMKICAgIGZyb20gYW4gYXJyYXksIHdpdGggdW5pcXVlbmVzcyBkZXRlcm1pbmVkIGJ5IHNwZWNpZmljIGtleS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IHVuaXFCeSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIGNvbnN0cnVjdG9yKGZydWl0cykgewogICAgICAgIHNldCh0aGlzLCAnZnJ1aXRzJywgZnJ1aXRzKTsKICAgICAgfQogIAogICAgICBAdW5pcUJ5KCdmcnVpdHMnLCAnaWQnKSB1bmlxdWVGcnVpdHM7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKFsKICAgICAgeyBpZDogMSwgJ2JhbmFuYScgfSwKICAgICAgeyBpZDogMiwgJ2dyYXBlJyB9LAogICAgICB7IGlkOiAzLCAncGVhY2gnIH0sCiAgICAgIHsgaWQ6IDEsICdiYW5hbmEnIH0KICAgIF0pOwogIAogICAgaGFtc3Rlci51bmlxdWVGcnVpdHM7IC8vIFsgeyBpZDogMSwgJ2JhbmFuYScgfSwgeyBpZDogMiwgJ2dyYXBlJyB9LCB7IGlkOiAzLCAncGVhY2gnIH1dCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IHVuaXFCeSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICB1bmlxdWVGcnVpdHM6IHVuaXFCeSgnZnJ1aXRzJywgJ2lkJykKICAgIH0pOwogIAogICAgbGV0IGhhbXN0ZXIgPSBIYW1zdGVyLmNyZWF0ZSh7CiAgICAgIGZydWl0czogWwogICAgICAgIHsgaWQ6IDEsICdiYW5hbmEnIH0sCiAgICAgICAgeyBpZDogMiwgJ2dyYXBlJyB9LAogICAgICAgIHsgaWQ6IDMsICdwZWFjaCcgfSwKICAgICAgICB7IGlkOiAxLCAnYmFuYW5hJyB9CiAgICAgIF0KICAgIH0pOwogIAogICAgaGFtc3Rlci51bmlxdWVGcnVpdHM7IC8vIFsgeyBpZDogMSwgJ2JhbmFuYScgfSwgeyBpZDogMiwgJ2dyYXBlJyB9LCB7IGlkOiAzLCAncGVhY2gnIH1dCiAgICBgYGAKICAKICAgIEBtZXRob2QgdW5pcUJ5CiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7U3RyaW5nfSBkZXBlbmRlbnRLZXkKICAgIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eUtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZXMgYSBuZXcgYXJyYXkgd2l0aCBhbGwgdGhlCiAgICB1bmlxdWUgZWxlbWVudHMgZnJvbSB0aGUgZGVwZW5kZW50IGFycmF5CiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIHVuaXFCeShkZXBlbmRlbnRLZXksIHByb3BlcnR5S2V5KSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAdW5pcUJ5IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYGRlcGVuZGVudEtleWAgYW5kIGBwcm9wZXJ0eUtleWAgcGFyYW1ldGVycycsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICAoZmFsc2UgJiYgISghL1tcW1xdXHtcfV0vZy50ZXN0KGRlcGVuZGVudEtleSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiRGVwZW5kZW50IGtleSBwYXNzZWQgdG8gYGNvbXB1dGVkLnVuaXFCeWAgc2hvdWxkbid0IGNvbnRhaW4gYnJhY2UgZXhwYW5kaW5nIHBhdHRlcm4uIiwgIS9bXFtcXVx7XH1dL2cudGVzdChkZXBlbmRlbnRLZXkpKSk7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoZGVwZW5kZW50S2V5ICsgIi5bXSIsIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGxpc3QgPSAoMCwgX21ldGFsLmdldCkodGhpcywgZGVwZW5kZW50S2V5KTsKICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5pc0FycmF5KShsaXN0KSA/ICgwLCBfcnVudGltZS51bmlxQnkpKGxpc3QsIHByb3BlcnR5S2V5KSA6ICgwLCBfcnVudGltZS5BKSgpOwogICAgfSkucmVhZE9ubHkoKTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgYSBuZXcgYXJyYXkgd2l0aCBhbGwgdGhlIHVuaXF1ZSBlbGVtZW50cwogICAgZnJvbSBvbmUgb3IgbW9yZSBkZXBlbmRlbnQgYXJyYXlzLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgdW5pb24gfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGNsYXNzIEhhbXN0ZXIgewogICAgICBjb25zdHJ1Y3RvcihmcnVpdHMsIHZlZ2V0YWJsZXMpIHsKICAgICAgICBzZXQodGhpcywgJ2ZydWl0cycsIGZydWl0cyk7CiAgICAgICAgc2V0KHRoaXMsICd2ZWdldGFibGVzJywgdmVnZXRhYmxlcyk7CiAgICAgIH0KICAKICAgICAgQHVuaW9uKCdmcnVpdHMnLCAndmVnZXRhYmxlcycpIGVkaWJsZVBsYW50czsKICAgIH0pOwogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcsIEhhbXN0ZXIoCiAgICAgIFsKICAgICAgICAnYmFuYW5hJywKICAgICAgICAnZ3JhcGUnLAogICAgICAgICdrYWxlJywKICAgICAgICAnYmFuYW5hJywKICAgICAgICAndG9tYXRvJwogICAgICBdLAogICAgICBbCiAgICAgICAgJ3RvbWF0bycsCiAgICAgICAgJ2NhcnJvdCcsCiAgICAgICAgJ2xldHR1Y2UnCiAgICAgIF0KICAgICk7CiAgCiAgICBoYW1zdGVyLnVuaXF1ZUZydWl0czsgLy8gWydiYW5hbmEnLCAnZ3JhcGUnLCAna2FsZScsICd0b21hdG8nLCAnY2Fycm90JywgJ2xldHR1Y2UnXQogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyB1bmlvbiB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICB1bmlxdWVGcnVpdHM6IHVuaW9uKCdmcnVpdHMnLCAndmVnZXRhYmxlcycpCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoewogICAgICBmcnVpdHM6IFsKICAgICAgICAnYmFuYW5hJywKICAgICAgICAnZ3JhcGUnLAogICAgICAgICdrYWxlJywKICAgICAgICAnYmFuYW5hJywKICAgICAgICAndG9tYXRvJwogICAgICBdLAogICAgICB2ZWdldGFibGVzOiBbCiAgICAgICAgJ3RvbWF0bycsCiAgICAgICAgJ2NhcnJvdCcsCiAgICAgICAgJ2xldHR1Y2UnCiAgICAgIF0KICAgIH0pOwogIAogICAgaGFtc3Rlci51bmlxdWVGcnVpdHM7IC8vIFsnYmFuYW5hJywgJ2dyYXBlJywgJ2thbGUnLCAndG9tYXRvJywgJ2NhcnJvdCcsICdsZXR0dWNlJ10KICAgIGBgYAogIAogICAgQG1ldGhvZCB1bmlvbgogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlLZXkqCiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlcyBhIG5ldyBhcnJheSB3aXRoIGFsbCB0aGUgdW5pcXVlIGVsZW1lbnRzCiAgICBmcm9tIG9uZSBvciBtb3JlIGRlcGVuZGVudCBhcnJheXMuCiAgICBAcHVibGljCiAgKi8KCgogIHZhciB1bmlvbiA9IHVuaXE7CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgYSBuZXcgYXJyYXkgd2l0aCBhbGwgdGhlIGVsZW1lbnRzCiAgICB0d28gb3IgbW9yZSBkZXBlbmRlbnQgYXJyYXlzIGhhdmUgaW4gY29tbW9uLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgaW50ZXJzZWN0IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBGcmllbmRHcm91cHMgewogICAgICBjb25zdHJ1Y3RvcihhZGFGcmllbmRzLCBjaGFybGVzRnJpZW5kcykgewogICAgICAgIHNldCh0aGlzLCAnYWRhRnJpZW5kcycsIGFkYUZyaWVuZHMpOwogICAgICAgIHNldCh0aGlzLCAnY2hhcmxlc0ZyaWVuZHMnLCBjaGFybGVzRnJpZW5kcyk7CiAgICAgIH0KICAKICAgICAgQGludGVyc2VjdCgnYWRhRnJpZW5kcycsICdjaGFybGVzRnJpZW5kcycpIGZyaWVuZHNJbkNvbW1vbjsKICAgIH0KICAKICAgIGxldCBncm91cHMgPSBuZXcgRnJpZW5kR3JvdXBzKAogICAgICBbJ0NoYXJsZXMgQmFiYmFnZScsICdKb2huIEhvYmhvdXNlJywgJ1dpbGxpYW0gS2luZycsICdNYXJ5IFNvbWVydmlsbGUnXSwKICAgICAgWydXaWxsaWFtIEtpbmcnLCAnTWFyeSBTb21lcnZpbGxlJywgJ0FkYSBMb3ZlbGFjZScsICdHZW9yZ2UgUGVhY29jayddCiAgICApOwogIAogICAgZ3JvdXBzLmZyaWVuZHNJbkNvbW1vbjsgLy8gWydXaWxsaWFtIEtpbmcnLCAnTWFyeSBTb21lcnZpbGxlJ10KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgaW50ZXJzZWN0IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgRnJpZW5kR3JvdXBzID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgZnJpZW5kc0luQ29tbW9uOiBpbnRlcnNlY3QoJ2FkYUZyaWVuZHMnLCAnY2hhcmxlc0ZyaWVuZHMnKQogICAgfSk7CiAgCiAgICBsZXQgZ3JvdXBzID0gRnJpZW5kR3JvdXBzLmNyZWF0ZSh7CiAgICAgIGFkYUZyaWVuZHM6IFsnQ2hhcmxlcyBCYWJiYWdlJywgJ0pvaG4gSG9iaG91c2UnLCAnV2lsbGlhbSBLaW5nJywgJ01hcnkgU29tZXJ2aWxsZSddLAogICAgICBjaGFybGVzRnJpZW5kczogWydXaWxsaWFtIEtpbmcnLCAnTWFyeSBTb21lcnZpbGxlJywgJ0FkYSBMb3ZlbGFjZScsICdHZW9yZ2UgUGVhY29jayddCiAgICB9KTsKICAKICAgIGdyb3Vwcy5mcmllbmRzSW5Db21tb247IC8vIFsnV2lsbGlhbSBLaW5nJywgJ01hcnkgU29tZXJ2aWxsZSddCiAgICBgYGAKICAKICAgIEBtZXRob2QgaW50ZXJzZWN0CiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eUtleSoKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVzIGEgbmV3IGFycmF5IHdpdGggYWxsIHRoZSBkdXBsaWNhdGVkCiAgICBlbGVtZW50cyBmcm9tIHRoZSBkZXBlbmRlbnQgYXJyYXlzCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMudW5pb24gPSB1bmlvbjsKCiAgZnVuY3Rpb24gaW50ZXJzZWN0KCkgewogICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4yKSwgX2tleTIgPSAwOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7CiAgICAgIGFyZ3NbX2tleTJdID0gYXJndW1lbnRzW19rZXkyXTsKICAgIH0KCiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAaW50ZXJzZWN0IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBvbmUgZGVwZW5kZW50IGtleSBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIG11bHRpQXJyYXlNYWNybyhhcmdzLCBmdW5jdGlvbiAoZGVwZW5kZW50S2V5cykgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIHZhciBhcnJheXMgPSBkZXBlbmRlbnRLZXlzLm1hcChmdW5jdGlvbiAoZGVwZW5kZW50S2V5KSB7CiAgICAgICAgdmFyIGFycmF5ID0gKDAsIF9tZXRhbC5nZXQpKF90aGlzMiwgZGVwZW5kZW50S2V5KTsKICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLmlzQXJyYXkpKGFycmF5KSA/IGFycmF5IDogW107CiAgICAgIH0pOwogICAgICB2YXIgcmVzdWx0cyA9IGFycmF5cy5wb3AoKS5maWx0ZXIoZnVuY3Rpb24gKGNhbmRpZGF0ZSkgewogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICB2YXIgZm91bmQgPSBmYWxzZTsKICAgICAgICAgIHZhciBhcnJheSA9IGFycmF5c1tpXTsKCiAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGFycmF5Lmxlbmd0aDsgaisrKSB7CiAgICAgICAgICAgIGlmIChhcnJheVtqXSA9PT0gY2FuZGlkYXRlKSB7CiAgICAgICAgICAgICAgZm91bmQgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKGZvdW5kID09PSBmYWxzZSkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfSk7CiAgICAgIHJldHVybiAoMCwgX3J1bnRpbWUuQSkocmVzdWx0cyk7CiAgICB9LCAnaW50ZXJzZWN0Jyk7CiAgfQogIC8qKgogICAgQSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIGEgbmV3IGFycmF5IHdpdGggYWxsIHRoZSBwcm9wZXJ0aWVzIGZyb20gdGhlCiAgICBmaXJzdCBkZXBlbmRlbnQgYXJyYXkgdGhhdCBhcmUgbm90IGluIHRoZSBzZWNvbmQgZGVwZW5kZW50IGFycmF5LgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgc2V0RGlmZiB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIGNvbnN0cnVjdG9yKGxpa2VzLCBmcnVpdHMpIHsKICAgICAgICBzZXQodGhpcywgJ2xpa2VzJywgbGlrZXMpOwogICAgICAgIHNldCh0aGlzLCAnZnJ1aXRzJywgZnJ1aXRzKTsKICAgICAgfQogIAogICAgICBAc2V0RGlmZignbGlrZXMnLCAnZnJ1aXRzJykgd2FudHM7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKAogICAgICBbCiAgICAgICAgJ2JhbmFuYScsCiAgICAgICAgJ2dyYXBlJywKICAgICAgICAna2FsZScKICAgICAgXSwKICAgICAgWwogICAgICAgICdncmFwZScsCiAgICAgICAgJ2thbGUnLAogICAgICBdCiAgICApOwogIAogICAgaGFtc3Rlci53YW50czsgLy8gWydiYW5hbmEnXQogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBzZXREaWZmIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgSGFtc3RlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIHdhbnRzOiBzZXREaWZmKCdsaWtlcycsICdmcnVpdHMnKQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKHsKICAgICAgbGlrZXM6IFsKICAgICAgICAnYmFuYW5hJywKICAgICAgICAnZ3JhcGUnLAogICAgICAgICdrYWxlJwogICAgICBdLAogICAgICBmcnVpdHM6IFsKICAgICAgICAnZ3JhcGUnLAogICAgICAgICdrYWxlJywKICAgICAgXQogICAgfSk7CiAgCiAgICBoYW1zdGVyLndhbnRzOyAvLyBbJ2JhbmFuYSddCiAgICBgYGAKICAKICAgIEBtZXRob2Qgc2V0RGlmZgogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gc2V0QVByb3BlcnR5CiAgICBAcGFyYW0ge1N0cmluZ30gc2V0QlByb3BlcnR5CiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlcyBhIG5ldyBhcnJheSB3aXRoIGFsbCB0aGUgaXRlbXMgZnJvbSB0aGUKICAgIGZpcnN0IGRlcGVuZGVudCBhcnJheSB0aGF0IGFyZSBub3QgaW4gdGhlIHNlY29uZCBkZXBlbmRlbnQgYXJyYXkKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gc2V0RGlmZihzZXRBUHJvcGVydHksIHNldEJQcm9wZXJ0eSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQHNldERpZmYgYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBhdGxlYXN0IG9uZSBkZXBlbmRlbnQga2V5IHBhcmFtZXRlcicsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICAoZmFsc2UgJiYgIShhcmd1bWVudHMubGVuZ3RoID09PSAyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2Bjb21wdXRlZC5zZXREaWZmYCByZXF1aXJlcyBleGFjdGx5IHR3byBkZXBlbmRlbnQgYXJyYXlzLicsIGFyZ3VtZW50cy5sZW5ndGggPT09IDIpKTsKICAgIChmYWxzZSAmJiAhKCEvW1xbXF1ce1x9XS9nLnRlc3Qoc2V0QVByb3BlcnR5KSAmJiAhL1tcW1xdXHtcfV0vZy50ZXN0KHNldEJQcm9wZXJ0eSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiRGVwZW5kZW50IGtleXMgcGFzc2VkIHRvIGBjb21wdXRlZC5zZXREaWZmYCBzaG91bGRuJ3QgY29udGFpbiBicmFjZSBleHBhbmRpbmcgcGF0dGVybi4iLCAhL1tcW1xdXHtcfV0vZy50ZXN0KHNldEFQcm9wZXJ0eSkgJiYgIS9bXFtcXVx7XH1dL2cudGVzdChzZXRCUHJvcGVydHkpKSk7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoc2V0QVByb3BlcnR5ICsgIi5bXSIsIHNldEJQcm9wZXJ0eSArICIuW10iLCBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBzZXRBID0gdGhpcy5nZXQoc2V0QVByb3BlcnR5KTsKICAgICAgdmFyIHNldEIgPSB0aGlzLmdldChzZXRCUHJvcGVydHkpOwoKICAgICAgaWYgKCEoMCwgX3J1bnRpbWUuaXNBcnJheSkoc2V0QSkpIHsKICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICAgIH0KCiAgICAgIGlmICghKDAsIF9ydW50aW1lLmlzQXJyYXkpKHNldEIpKSB7CiAgICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5BKShzZXRBKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHNldEEuZmlsdGVyKGZ1bmN0aW9uICh4KSB7CiAgICAgICAgcmV0dXJuIHNldEIuaW5kZXhPZih4KSA9PT0gLTE7CiAgICAgIH0pOwogICAgfSkucmVhZE9ubHkoKTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgcmV0dXJucyB0aGUgYXJyYXkgb2YgdmFsdWVzIGZvciB0aGUgcHJvdmlkZWQKICAgIGRlcGVuZGVudCBwcm9wZXJ0aWVzLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgY29sbGVjdCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBjb2xsZWN0KCdoYXQnLCAnc2hpcnQnKSBjbG90aGVzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgaGFtc3Rlci5jbG90aGVzOyAvLyBbbnVsbCwgbnVsbF0KICAKICAgIHNldChoYW1zdGVyLCAnaGF0JywgJ0NhbXAgSGF0Jyk7CiAgICBzZXQoaGFtc3RlciwgJ3NoaXJ0JywgJ0NhbXAgU2hpcnQnKTsKICAgIGhhbXN0ZXIuY2xvdGhlczsgLy8gWydDYW1wIEhhdCcsICdDYW1wIFNoaXJ0J10KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgY29sbGVjdCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBjbG90aGVzOiBjb2xsZWN0KCdoYXQnLCAnc2hpcnQnKQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICBoYW1zdGVyLmNsb3RoZXM7IC8vIFtudWxsLCBudWxsXQogIAogICAgc2V0KGhhbXN0ZXIsICdoYXQnLCAnQ2FtcCBIYXQnKTsKICAgIHNldChoYW1zdGVyLCAnc2hpcnQnLCAnQ2FtcCBTaGlydCcpOwogICAgaGFtc3Rlci5jbG90aGVzOyAvLyBbJ0NhbXAgSGF0JywgJ0NhbXAgU2hpcnQnXQogICAgYGBgCiAgCiAgICBAbWV0aG9kIGNvbGxlY3QKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHN0YXRpYwogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleSoKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIG1hcHMgdmFsdWVzIG9mIGFsbCBwYXNzZWQKICAgIGluIHByb3BlcnRpZXMgdG8gYW4gYXJyYXkuCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGNvbGxlY3QoKSB7CiAgICBmb3IgKHZhciBfbGVuMyA9IGFyZ3VtZW50cy5sZW5ndGgsIGRlcGVuZGVudEtleXMgPSBuZXcgQXJyYXkoX2xlbjMpLCBfa2V5MyA9IDA7IF9rZXkzIDwgX2xlbjM7IF9rZXkzKyspIHsKICAgICAgZGVwZW5kZW50S2V5c1tfa2V5M10gPSBhcmd1bWVudHNbX2tleTNdOwogICAgfQoKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBjb2xsZWN0IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBvbmUgZGVwZW5kZW50IGtleSBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIG11bHRpQXJyYXlNYWNybyhkZXBlbmRlbnRLZXlzLCBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBfdGhpczMgPSB0aGlzOwoKICAgICAgdmFyIHJlcyA9IGRlcGVuZGVudEtleXMubWFwKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICB2YXIgdmFsID0gKDAsIF9tZXRhbC5nZXQpKF90aGlzMywga2V5KTsKICAgICAgICByZXR1cm4gdmFsID09PSB1bmRlZmluZWQgPyBudWxsIDogdmFsOwogICAgICB9KTsKICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5BKShyZXMpOwogICAgfSwgJ2NvbGxlY3QnKTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgYSBuZXcgYXJyYXkgd2l0aCBhbGwgdGhlIHByb3BlcnRpZXMgZnJvbSB0aGUKICAgIGZpcnN0IGRlcGVuZGVudCBhcnJheSBzb3J0ZWQgYmFzZWQgb24gYSBwcm9wZXJ0eSBvciBzb3J0IGZ1bmN0aW9uLiBUaGUgc29ydAogICAgbWFjcm8gY2FuIGJlIHVzZWQgaW4gdHdvIGRpZmZlcmVudCB3YXlzOgogIAogICAgMS4gQnkgcHJvdmlkaW5nIGEgc29ydCBjYWxsYmFjayBmdW5jdGlvbgogICAgMi4gQnkgcHJvdmlkaW5nIGFuIGFycmF5IG9mIGtleXMgdG8gc29ydCB0aGUgYXJyYXkKICAKICAgIEluIHRoZSBmaXJzdCBmb3JtLCB0aGUgY2FsbGJhY2sgbWV0aG9kIHlvdSBwcm92aWRlIHNob3VsZCBoYXZlIHRoZSBmb2xsb3dpbmcKICAgIHNpZ25hdHVyZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGZ1bmN0aW9uIHNvcnRDYWxsYmFjayhpdGVtQSwgaXRlbUIpOwogICAgYGBgCiAgCiAgICAtIGBpdGVtQWAgdGhlIGZpcnN0IGl0ZW0gdG8gY29tcGFyZS4KICAgIC0gYGl0ZW1CYCB0aGUgc2Vjb25kIGl0ZW0gdG8gY29tcGFyZS4KICAKICAgIFRoaXMgZnVuY3Rpb24gc2hvdWxkIHJldHVybiBuZWdhdGl2ZSBudW1iZXIgKGUuZy4gYC0xYCkgd2hlbiBgaXRlbUFgIHNob3VsZAogICAgY29tZSBiZWZvcmUgYGl0ZW1CYC4gSXQgc2hvdWxkIHJldHVybiBwb3NpdGl2ZSBudW1iZXIgKGUuZy4gYDFgKSB3aGVuIGBpdGVtQWAKICAgIHNob3VsZCBjb21lIGFmdGVyIGBpdGVtQmAuIElmIHRoZSBgaXRlbUFgIGFuZCBgaXRlbUJgIGFyZSBlcXVhbCB0aGlzIGZ1bmN0aW9uCiAgICBzaG91bGQgcmV0dXJuIGAwYC4KICAKICAgIFRoZXJlZm9yZSwgaWYgdGhpcyBmdW5jdGlvbiBpcyBjb21wYXJpbmcgc29tZSBudW1lcmljIHZhbHVlcywgc2ltcGxlIGBpdGVtQSAtCiAgICBpdGVtQmAgb3IgYGl0ZW1BLmdldCggJ2ZvbycgKSAtIGl0ZW1CLmdldCggJ2ZvbycgKWAgY2FuIGJlIHVzZWQgaW5zdGVhZCBvZgogICAgc2VyaWVzIG9mIGBpZmAuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBzb3J0IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBUb0RvTGlzdCB7CiAgICAgIGNvbnN0cnVjdG9yKHRvZG9zKSB7CiAgICAgICAgc2V0KHRoaXMsICd0b2RvcycsIHRvZG9zKTsKICAgICAgfQogIAogICAgICAvLyB1c2luZyBhIGN1c3RvbSBzb3J0IGZ1bmN0aW9uCiAgICAgIEBzb3J0KCd0b2RvcycsIGZ1bmN0aW9uKGEsIGIpewogICAgICAgIGlmIChhLnByaW9yaXR5ID4gYi5wcmlvcml0eSkgewogICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfSBlbHNlIGlmIChhLnByaW9yaXR5IDwgYi5wcmlvcml0eSkgewogICAgICAgICAgcmV0dXJuIC0xOwogICAgICAgIH0KICAKICAgICAgICByZXR1cm4gMDsKICAgICAgfSkKICAgICAgcHJpb3JpdHlUb2RvczsKICAgIH0KICAKICAgIGxldCB0b2RvTGlzdCA9IG5ldyBUb0RvTGlzdChbCiAgICAgIHsgbmFtZTogJ1VuaXQgVGVzdCcsIHByaW9yaXR5OiAyIH0sCiAgICAgIHsgbmFtZTogJ0RvY3VtZW50YXRpb24nLCBwcmlvcml0eTogMyB9LAogICAgICB7IG5hbWU6ICdSZWxlYXNlJywgcHJpb3JpdHk6IDEgfQogICAgXSk7CiAgCiAgICB0b2RvTGlzdC5wcmlvcml0eVRvZG9zOyAvLyBbeyBuYW1lOidSZWxlYXNlJywgcHJpb3JpdHk6MSB9LCB7IG5hbWU6J1VuaXQgVGVzdCcsIHByaW9yaXR5OjIgfSwgeyBuYW1lOidEb2N1bWVudGF0aW9uJywgcHJpb3JpdHk6MyB9XQogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBzb3J0IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgVG9Eb0xpc3QgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAvLyB1c2luZyBhIGN1c3RvbSBzb3J0IGZ1bmN0aW9uCiAgICAgIHByaW9yaXR5VG9kb3M6IHNvcnQoJ3RvZG9zJywgZnVuY3Rpb24oYSwgYil7CiAgICAgICAgaWYgKGEucHJpb3JpdHkgPiBiLnByaW9yaXR5KSB7CiAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9IGVsc2UgaWYgKGEucHJpb3JpdHkgPCBiLnByaW9yaXR5KSB7CiAgICAgICAgICByZXR1cm4gLTE7CiAgICAgICAgfQogIAogICAgICAgIHJldHVybiAwOwogICAgICB9KQogICAgfSk7CiAgCiAgICBsZXQgdG9kb0xpc3QgPSBUb0RvTGlzdC5jcmVhdGUoewogICAgICB0b2RvczogWwogICAgICAgIHsgbmFtZTogJ1VuaXQgVGVzdCcsIHByaW9yaXR5OiAyIH0sCiAgICAgICAgeyBuYW1lOiAnRG9jdW1lbnRhdGlvbicsIHByaW9yaXR5OiAzIH0sCiAgICAgICAgeyBuYW1lOiAnUmVsZWFzZScsIHByaW9yaXR5OiAxIH0KICAgICAgXQogICAgfSk7CiAgCiAgICB0b2RvTGlzdC5wcmlvcml0eVRvZG9zOyAvLyBbeyBuYW1lOidSZWxlYXNlJywgcHJpb3JpdHk6MSB9LCB7IG5hbWU6J1VuaXQgVGVzdCcsIHByaW9yaXR5OjIgfSwgeyBuYW1lOidEb2N1bWVudGF0aW9uJywgcHJpb3JpdHk6MyB9XQogICAgYGBgCiAgCiAgICBZb3UgY2FuIGFsc28gb3B0aW9uYWxseSBwYXNzIGFuIGFycmF5IG9mIGFkZGl0aW9uYWwgZGVwZW5kZW50IGtleXMgYXMgdGhlCiAgICBzZWNvbmQgcGFyYW1ldGVyLCBpZiB5b3VyIHNvcnQgZnVuY3Rpb24gaXMgZGVwZW5kZW50IG9uIGFkZGl0aW9uYWwgdmFsdWVzIHRoYXQKICAgIGNvdWxkIGNoYW5nZXM6CiAgCiAgICBgYGBqcwogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgc29ydCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgVG9Eb0xpc3QgewogICAgICBzb3J0S2V5ID0gJ3ByaW9yaXR5JzsKICAKICAgICAgY29uc3RydWN0b3IodG9kb3MpIHsKICAgICAgICBzZXQodGhpcywgJ3RvZG9zJywgdG9kb3MpOwogICAgICB9CiAgCiAgICAgIC8vIHVzaW5nIGEgY3VzdG9tIHNvcnQgZnVuY3Rpb24KICAgICAgQHNvcnQoJ3RvZG9zJywgWydzb3J0S2V5J10sIGZ1bmN0aW9uKGEsIGIpewogICAgICAgIGlmIChhW3RoaXMuc29ydEtleV0gPiBiW3RoaXMuc29ydEtleV0pIHsKICAgICAgICAgIHJldHVybiAxOwogICAgICAgIH0gZWxzZSBpZiAoYVt0aGlzLnNvcnRLZXldIDwgYlt0aGlzLnNvcnRLZXldKSB7CiAgICAgICAgICByZXR1cm4gLTE7CiAgICAgICAgfQogIAogICAgICAgIHJldHVybiAwOwogICAgICB9KQogICAgICBzb3J0ZWRUb2RvczsKICAgIH0pOwogIAogICAgbGV0IHRvZG9MaXN0ID0gbmV3IFRvRG9MaXN0KFsKICAgICAgeyBuYW1lOiAnVW5pdCBUZXN0JywgcHJpb3JpdHk6IDIgfSwKICAgICAgeyBuYW1lOiAnRG9jdW1lbnRhdGlvbicsIHByaW9yaXR5OiAzIH0sCiAgICAgIHsgbmFtZTogJ1JlbGVhc2UnLCBwcmlvcml0eTogMSB9CiAgICBdKTsKICAKICAgIHRvZG9MaXN0LnByaW9yaXR5VG9kb3M7IC8vIFt7IG5hbWU6J1JlbGVhc2UnLCBwcmlvcml0eToxIH0sIHsgbmFtZTonVW5pdCBUZXN0JywgcHJpb3JpdHk6MiB9LCB7IG5hbWU6J0RvY3VtZW50YXRpb24nLCBwcmlvcml0eTozIH1dCiAgICBgYGAKICAKICAgIEluIHRoZSBzZWNvbmQgZm9ybSwgeW91IHNob3VsZCBwcm92aWRlIHRoZSBrZXkgb2YgdGhlIGFycmF5IG9mIHNvcnQgdmFsdWVzIGFzCiAgICB0aGUgc2Vjb25kIHBhcmFtZXRlcjoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgc29ydCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgVG9Eb0xpc3QgewogICAgICBjb25zdHJ1Y3Rvcih0b2RvcykgewogICAgICAgIHNldCh0aGlzLCAndG9kb3MnLCB0b2Rvcyk7CiAgICAgIH0KICAKICAgICAgLy8gdXNpbmcgc3RhbmRhcmQgYXNjZW5kaW5nIHNvcnQKICAgICAgdG9kb3NTb3J0aW5nID0gWyduYW1lJ107CiAgICAgIEBzb3J0KCd0b2RvcycsICd0b2Rvc1NvcnRpbmcnKSBzb3J0ZWRUb2RvczsKICAKICAgICAgLy8gdXNpbmcgZGVzY2VuZGluZyBzb3J0CiAgICAgIHRvZG9zU29ydGluZ0Rlc2MgPSBbJ25hbWU6ZGVzYyddOwogICAgICBAc29ydCgndG9kb3MnLCAndG9kb3NTb3J0aW5nRGVzYycpIHNvcnRlZFRvZG9zRGVzYzsKICAgIH0KICAKICAgIGxldCB0b2RvTGlzdCA9IG5ldyBUb0RvTGlzdChbCiAgICAgIHsgbmFtZTogJ1VuaXQgVGVzdCcsIHByaW9yaXR5OiAyIH0sCiAgICAgIHsgbmFtZTogJ0RvY3VtZW50YXRpb24nLCBwcmlvcml0eTogMyB9LAogICAgICB7IG5hbWU6ICdSZWxlYXNlJywgcHJpb3JpdHk6IDEgfQogICAgXSk7CiAgCiAgICB0b2RvTGlzdC5zb3J0ZWRUb2RvczsgLy8gW3sgbmFtZTonRG9jdW1lbnRhdGlvbicsIHByaW9yaXR5OjMgfSwgeyBuYW1lOidSZWxlYXNlJywgcHJpb3JpdHk6MSB9LCB7IG5hbWU6J1VuaXQgVGVzdCcsIHByaW9yaXR5OjIgfV0KICAgIHRvZG9MaXN0LnNvcnRlZFRvZG9zRGVzYzsgLy8gW3sgbmFtZTonVW5pdCBUZXN0JywgcHJpb3JpdHk6MiB9LCB7IG5hbWU6J1JlbGVhc2UnLCBwcmlvcml0eToxIH0sIHsgbmFtZTonRG9jdW1lbnRhdGlvbicsIHByaW9yaXR5OjMgfV0KICAgIGBgYAogIAogICAgQG1ldGhvZCBzb3J0CiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7U3RyaW5nfSBpdGVtc0tleQogICAgQHBhcmFtIHtBcnJheX0gW2FkZGl0aW9uYWxEZXBlbmRlbnRLZXlzXSBvcHRpb25hbCBhcnJheSBvZiBhZGRpdGlvbmFsCiAgICBkZXBlbmRlbnQga2V5cwogICAgQHBhcmFtIHtTdHJpbmcgb3IgRnVuY3Rpb259IHNvcnREZWZpbml0aW9uIGEgZGVwZW5kZW50IGtleSB0byBhbiBhcnJheSBvZiBzb3J0CiAgICBwcm9wZXJ0aWVzIChhZGQgYDpkZXNjYCB0byB0aGUgYXJyYXlzIHNvcnQgcHJvcGVydGllcyB0byBzb3J0IGRlc2NlbmRpbmcpIG9yIGEKICAgIGZ1bmN0aW9uIHRvIHVzZSB3aGVuIHNvcnRpbmcKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVzIGEgbmV3IHNvcnRlZCBhcnJheSBiYXNlZCBvbiB0aGUgc29ydAogICAgcHJvcGVydHkgYXJyYXkgb3IgY2FsbGJhY2sgZnVuY3Rpb24KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gc29ydChpdGVtc0tleSwgYWRkaXRpb25hbERlcGVuZGVudEtleXMsIHNvcnREZWZpbml0aW9uKSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAc29ydCBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGF0bGVhc3QgYW4gYGl0ZW1zS2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICB2YXIgYXJndW1lbnRzVmFsaWQgPSBmYWxzZTsKCiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyKSB7CiAgICAgICAgYXJndW1lbnRzVmFsaWQgPSB0eXBlb2YgaXRlbXNLZXkgPT09ICdzdHJpbmcnICYmICh0eXBlb2YgYWRkaXRpb25hbERlcGVuZGVudEtleXMgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBhZGRpdGlvbmFsRGVwZW5kZW50S2V5cyA9PT0gJ2Z1bmN0aW9uJyk7CiAgICAgIH0KCiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAzKSB7CiAgICAgICAgYXJndW1lbnRzVmFsaWQgPSB0eXBlb2YgaXRlbXNLZXkgPT09ICdzdHJpbmcnICYmIEFycmF5LmlzQXJyYXkoYWRkaXRpb25hbERlcGVuZGVudEtleXMpICYmIHR5cGVvZiBzb3J0RGVmaW5pdGlvbiA9PT0gJ2Z1bmN0aW9uJzsKICAgICAgfQoKICAgICAgKGZhbHNlICYmICEoYXJndW1lbnRzVmFsaWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYGNvbXB1dGVkLnNvcnRgIGNhbiBlaXRoZXIgYmUgdXNlZCB3aXRoIGFuIGFycmF5IG9mIHNvcnQgcHJvcGVydGllcyBvciB3aXRoIGEgc29ydCBmdW5jdGlvbi4gSWYgdXNlZCB3aXRoIGFuIGFycmF5IG9mIHNvcnQgcHJvcGVydGllcywgaXQgbXVzdCByZWNlaXZlIGV4YWN0bHkgdHdvIGFyZ3VtZW50czogdGhlIGtleSBvZiB0aGUgYXJyYXkgdG8gc29ydCwgYW5kIHRoZSBrZXkgb2YgdGhlIGFycmF5IG9mIHNvcnQgcHJvcGVydGllcy4gSWYgdXNlZCB3aXRoIGEgc29ydCBmdW5jdGlvbiwgaXQgbWF5IHJlY2lldmUgdXAgdG8gdGhyZWUgYXJndW1lbnRzOiB0aGUga2V5IG9mIHRoZSBhcnJheSB0byBzb3J0LCBhbiBvcHRpb25hbCBhZGRpdGlvbmFsIGFycmF5IG9mIGRlcGVuZGVudCBrZXlzIGZvciB0aGUgY29tcHV0ZWQgcHJvcGVydHksIGFuZCB0aGUgc29ydCBmdW5jdGlvbi4nLCBhcmd1bWVudHNWYWxpZCkpOwogICAgfQoKICAgIGlmIChzb3J0RGVmaW5pdGlvbiA9PT0gdW5kZWZpbmVkICYmICFBcnJheS5pc0FycmF5KGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzKSkgewogICAgICBzb3J0RGVmaW5pdGlvbiA9IGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzOwogICAgICBhZGRpdGlvbmFsRGVwZW5kZW50S2V5cyA9IFtdOwogICAgfQoKICAgIGlmICh0eXBlb2Ygc29ydERlZmluaXRpb24gPT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuIGN1c3RvbVNvcnQoaXRlbXNLZXksIGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzLCBzb3J0RGVmaW5pdGlvbik7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gcHJvcGVydHlTb3J0KGl0ZW1zS2V5LCBzb3J0RGVmaW5pdGlvbik7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBjdXN0b21Tb3J0KGl0ZW1zS2V5LCBhZGRpdGlvbmFsRGVwZW5kZW50S2V5cywgY29tcGFyYXRvcikgewogICAgcmV0dXJuIGFycmF5TWFjcm8oaXRlbXNLZXksIGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzLCBmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgdmFyIF90aGlzNCA9IHRoaXM7CgogICAgICByZXR1cm4gdmFsdWUuc2xpY2UoKS5zb3J0KGZ1bmN0aW9uICh4LCB5KSB7CiAgICAgICAgcmV0dXJuIGNvbXBhcmF0b3IuY2FsbChfdGhpczQsIHgsIHkpOwogICAgICB9KTsKICAgIH0pOwogIH0gLy8gVGhpcyBvbmUgbmVlZHMgdG8gZHluYW1pY2FsbHkgc2V0IHVwIGFuZCB0ZWFyIGRvd24gb2JzZXJ2ZXJzIG9uIHRoZSBpdGVtc0tleQogIC8vIGRlcGVuZGluZyBvbiB0aGUgc29ydFByb3BlcnRpZXMKCgogIGZ1bmN0aW9uIHByb3BlcnR5U29ydChpdGVtc0tleSwgc29ydFByb3BlcnRpZXNLZXkpIHsKICAgIHZhciBhY3RpdmVPYnNlcnZlcnNNYXAgPSBuZXcgV2Vha01hcCgpOwogICAgdmFyIHNvcnRQcm9wZXJ0eURpZENoYW5nZU1hcCA9IG5ldyBXZWFrTWFwKCk7CgogICAgaWYgKHRydWUKICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgKSB7CiAgICAgICAgdmFyIGNwID0gKDAsIF9tZXRhbC5jb21wdXRlZCkoaXRlbXNLZXkgKyAiLltdIiwgc29ydFByb3BlcnRpZXNLZXkgKyAiLltdIiwgZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgdmFyIHNvcnRQcm9wZXJ0aWVzID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIHNvcnRQcm9wZXJ0aWVzS2V5KTsKICAgICAgICAgIChmYWxzZSAmJiAhKCgwLCBfcnVudGltZS5pc0FycmF5KShzb3J0UHJvcGVydGllcykgJiYgc29ydFByb3BlcnRpZXMuZXZlcnkoZnVuY3Rpb24gKHMpIHsKICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBzID09PSAnc3RyaW5nJzsKICAgICAgICAgIH0pKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIlRoZSBzb3J0IGRlZmluaXRpb24gZm9yICciICsga2V5ICsgIicgb24gIiArIHRoaXMgKyAiIG11c3QgYmUgYSBmdW5jdGlvbiBvciBhbiBhcnJheSBvZiBzdHJpbmdzIiwgKDAsIF9ydW50aW1lLmlzQXJyYXkpKHNvcnRQcm9wZXJ0aWVzKSAmJiBzb3J0UHJvcGVydGllcy5ldmVyeShmdW5jdGlvbiAocykgewogICAgICAgICAgICByZXR1cm4gdHlwZW9mIHMgPT09ICdzdHJpbmcnOwogICAgICAgICAgfSkpKTsKICAgICAgICAgIHZhciBpdGVtc0tleUlzQXRUaGlzID0gaXRlbXNLZXkgPT09ICdAdGhpcyc7CiAgICAgICAgICB2YXIgbm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzID0gbm9ybWFsaXplU29ydFByb3BlcnRpZXMoc29ydFByb3BlcnRpZXMpOwogICAgICAgICAgdmFyIGl0ZW1zID0gaXRlbXNLZXlJc0F0VGhpcyA/IHRoaXMgOiAoMCwgX21ldGFsLmdldCkodGhpcywgaXRlbXNLZXkpOwoKICAgICAgICAgIGlmICghKDAsIF9ydW50aW1lLmlzQXJyYXkpKGl0ZW1zKSkgewogICAgICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKG5vcm1hbGl6ZWRTb3J0UHJvcGVydGllcy5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5BKShpdGVtcy5zbGljZSgpKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBzb3J0QnlOb3JtYWxpemVkU29ydFByb3BlcnRpZXMoaXRlbXMsIG5vcm1hbGl6ZWRTb3J0UHJvcGVydGllcyk7CiAgICAgICAgICB9CiAgICAgICAgfSkucmVhZE9ubHkoKTsKICAgICAgICAoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JEZWNvcmF0b3IpKGNwKS5hdXRvKCk7CiAgICAgICAgcmV0dXJuIGNwOwogICAgICB9IGVsc2UgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoc29ydFByb3BlcnRpZXNLZXkgKyAiLltdIiwgZnVuY3Rpb24gKGtleSkgewogICAgICAgIHZhciBfdGhpczUgPSB0aGlzOwoKICAgICAgICB2YXIgc29ydFByb3BlcnRpZXMgPSAoMCwgX21ldGFsLmdldCkodGhpcywgc29ydFByb3BlcnRpZXNLZXkpOwogICAgICAgIChmYWxzZSAmJiAhKCgwLCBfcnVudGltZS5pc0FycmF5KShzb3J0UHJvcGVydGllcykgJiYgc29ydFByb3BlcnRpZXMuZXZlcnkoZnVuY3Rpb24gKHMpIHsKICAgICAgICAgIHJldHVybiB0eXBlb2YgcyA9PT0gJ3N0cmluZyc7CiAgICAgICAgfSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIHNvcnQgZGVmaW5pdGlvbiBmb3IgJyIgKyBrZXkgKyAiJyBvbiAiICsgdGhpcyArICIgbXVzdCBiZSBhIGZ1bmN0aW9uIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MiLCAoMCwgX3J1bnRpbWUuaXNBcnJheSkoc29ydFByb3BlcnRpZXMpICYmIHNvcnRQcm9wZXJ0aWVzLmV2ZXJ5KGZ1bmN0aW9uIChzKSB7CiAgICAgICAgICByZXR1cm4gdHlwZW9mIHMgPT09ICdzdHJpbmcnOwogICAgICAgIH0pKSk7IC8vIEFkZC9yZW1vdmUgcHJvcGVydHkgb2JzZXJ2ZXJzIGFzIHJlcXVpcmVkLgoKICAgICAgICB2YXIgYWN0aXZlT2JzZXJ2ZXJzID0gYWN0aXZlT2JzZXJ2ZXJzTWFwLmdldCh0aGlzKTsKCiAgICAgICAgaWYgKCFzb3J0UHJvcGVydHlEaWRDaGFuZ2VNYXAuaGFzKHRoaXMpKSB7CiAgICAgICAgICBzb3J0UHJvcGVydHlEaWRDaGFuZ2VNYXAuc2V0KHRoaXMsIGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgKDAsIF9tZXRhbC5ub3RpZnlQcm9wZXJ0eUNoYW5nZSkodGhpcywga2V5KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgdmFyIHNvcnRQcm9wZXJ0eURpZENoYW5nZSA9IHNvcnRQcm9wZXJ0eURpZENoYW5nZU1hcC5nZXQodGhpcyk7CgogICAgICAgIGlmIChhY3RpdmVPYnNlcnZlcnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgYWN0aXZlT2JzZXJ2ZXJzLmZvckVhY2goZnVuY3Rpb24gKHBhdGgpIHsKICAgICAgICAgICAgcmV0dXJuICgwLCBfbWV0YWwucmVtb3ZlT2JzZXJ2ZXIpKF90aGlzNSwgcGF0aCwgc29ydFByb3BlcnR5RGlkQ2hhbmdlKTsKICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgdmFyIGl0ZW1zS2V5SXNBdFRoaXMgPSBpdGVtc0tleSA9PT0gJ0B0aGlzJzsKICAgICAgICB2YXIgbm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzID0gbm9ybWFsaXplU29ydFByb3BlcnRpZXMoc29ydFByb3BlcnRpZXMpOwoKICAgICAgICBpZiAobm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgdmFyIHBhdGggPSBpdGVtc0tleUlzQXRUaGlzID8gIltdIiA6IGl0ZW1zS2V5ICsgIi5bXSI7CiAgICAgICAgICAoMCwgX21ldGFsLmFkZE9ic2VydmVyKSh0aGlzLCBwYXRoLCBzb3J0UHJvcGVydHlEaWRDaGFuZ2UpOwogICAgICAgICAgYWN0aXZlT2JzZXJ2ZXJzID0gW3BhdGhdOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBhY3RpdmVPYnNlcnZlcnMgPSBub3JtYWxpemVkU29ydFByb3BlcnRpZXMubWFwKGZ1bmN0aW9uIChfcmVmKSB7CiAgICAgICAgICAgIHZhciBwcm9wID0gX3JlZlswXTsKICAgICAgICAgICAgdmFyIHBhdGggPSBpdGVtc0tleUlzQXRUaGlzID8gIkBlYWNoLiIgKyBwcm9wIDogaXRlbXNLZXkgKyAiLkBlYWNoLiIgKyBwcm9wOwogICAgICAgICAgICAoMCwgX21ldGFsLmFkZE9ic2VydmVyKShfdGhpczUsIHBhdGgsIHNvcnRQcm9wZXJ0eURpZENoYW5nZSk7CiAgICAgICAgICAgIHJldHVybiBwYXRoOwogICAgICAgICAgfSk7CiAgICAgICAgfQoKICAgICAgICBhY3RpdmVPYnNlcnZlcnNNYXAuc2V0KHRoaXMsIGFjdGl2ZU9ic2VydmVycyk7CiAgICAgICAgdmFyIGl0ZW1zID0gaXRlbXNLZXlJc0F0VGhpcyA/IHRoaXMgOiAoMCwgX21ldGFsLmdldCkodGhpcywgaXRlbXNLZXkpOwoKICAgICAgICBpZiAoISgwLCBfcnVudGltZS5pc0FycmF5KShpdGVtcykpIHsKICAgICAgICAgIHJldHVybiAoMCwgX3J1bnRpbWUuQSkoKTsKICAgICAgICB9CgogICAgICAgIGlmIChub3JtYWxpemVkU29ydFByb3BlcnRpZXMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKGl0ZW1zLnNsaWNlKCkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gc29ydEJ5Tm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzKGl0ZW1zLCBub3JtYWxpemVkU29ydFByb3BlcnRpZXMpOwogICAgICAgIH0KICAgICAgfSkucmVhZE9ubHkoKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIG5vcm1hbGl6ZVNvcnRQcm9wZXJ0aWVzKHNvcnRQcm9wZXJ0aWVzKSB7CiAgICByZXR1cm4gc29ydFByb3BlcnRpZXMubWFwKGZ1bmN0aW9uIChwKSB7CiAgICAgIHZhciBfcCRzcGxpdCA9IHAuc3BsaXQoJzonKSwKICAgICAgICAgIHByb3AgPSBfcCRzcGxpdFswXSwKICAgICAgICAgIGRpcmVjdGlvbiA9IF9wJHNwbGl0WzFdOwoKICAgICAgZGlyZWN0aW9uID0gZGlyZWN0aW9uIHx8ICdhc2MnOwogICAgICByZXR1cm4gW3Byb3AsIGRpcmVjdGlvbl07CiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHNvcnRCeU5vcm1hbGl6ZWRTb3J0UHJvcGVydGllcyhpdGVtcywgbm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzKSB7CiAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKGl0ZW1zLnNsaWNlKCkuc29ydChmdW5jdGlvbiAoaXRlbUEsIGl0ZW1CKSB7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIF9ub3JtYWxpemVkU29ydFByb3BlciA9IG5vcm1hbGl6ZWRTb3J0UHJvcGVydGllc1tpXSwKICAgICAgICAgICAgcHJvcCA9IF9ub3JtYWxpemVkU29ydFByb3BlclswXSwKICAgICAgICAgICAgZGlyZWN0aW9uID0gX25vcm1hbGl6ZWRTb3J0UHJvcGVyWzFdOwogICAgICAgIHZhciByZXN1bHQgPSAoMCwgX3J1bnRpbWUuY29tcGFyZSkoKDAsIF9tZXRhbC5nZXQpKGl0ZW1BLCBwcm9wKSwgKDAsIF9tZXRhbC5nZXQpKGl0ZW1CLCBwcm9wKSk7CgogICAgICAgIGlmIChyZXN1bHQgIT09IDApIHsKICAgICAgICAgIHJldHVybiBkaXJlY3Rpb24gPT09ICdkZXNjJyA/IC0xICogcmVzdWx0IDogcmVzdWx0OwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIDA7CiAgICB9KSk7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvcG9seWZpbGxzL2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIiwgIkBlbWJlci9wb2x5ZmlsbHMvbGliL21lcmdlIiwgIkBlbWJlci9wb2x5ZmlsbHMvbGliL2Fzc2lnbiIsICJAZW1iZXIvcG9seWZpbGxzL2xpYi93ZWFrX3NldCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9kZXByZWNhdGVkRmVhdHVyZXMsIF9tZXJnZSwgX2Fzc2lnbiwgX3dlYWtfc2V0KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJhc3NpZ24iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXNzaWduLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiYXNzaWduUG9seWZpbGwiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXNzaWduLmFzc2lnbjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfV2Vha1NldCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF93ZWFrX3NldC5kZWZhdWx0OwogICAgfQogIH0pOwogIF9leHBvcnRzLm1lcmdlID0gdm9pZCAwOwogIHZhciBtZXJnZSA9IF9kZXByZWNhdGVkRmVhdHVyZXMuTUVSR0UgPyBfbWVyZ2UuZGVmYXVsdCA6IHVuZGVmaW5lZDsgLy8gRXhwb3J0IGBhc3NpZ25Qb2x5ZmlsbGAgZm9yIHRlc3RpbmcKCiAgX2V4cG9ydHMubWVyZ2UgPSBtZXJnZTsKfSk7CmRlZmluZSgiQGVtYmVyL3BvbHlmaWxscy9saWIvYXNzaWduIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuYXNzaWduID0gYXNzaWduOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICBAbW9kdWxlIEBlbWJlci9wb2x5ZmlsbHMKICAqLwoKICAvKioKICAgIENvcHkgcHJvcGVydGllcyBmcm9tIGEgc291cmNlIG9iamVjdCB0byBhIHRhcmdldCBvYmplY3QuIFNvdXJjZSBhcmd1bWVudHMgcmVtYWluIHVuY2hhbmdlZC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGFzc2lnbiB9IGZyb20gJ0BlbWJlci9wb2x5ZmlsbHMnOwogIAogICAgdmFyIGEgPSB7IGZpcnN0OiAnWWVodWRhJyB9OwogICAgdmFyIGIgPSB7IGxhc3Q6ICdLYXR6JyB9OwogICAgdmFyIGMgPSB7IGNvbXBhbnk6ICdPdGhlciBDb21wYW55JyB9OwogICAgdmFyIGQgPSB7IGNvbXBhbnk6ICdUaWxkZSBJbmMuJyB9OwogICAgYXNzaWduKGEsIGIsIGMsIGQpOyAvLyBhID09PSB7IGZpcnN0OiAnWWVodWRhJywgbGFzdDogJ0thdHonLCBjb21wYW55OiAnVGlsZGUgSW5jLicgfTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBhc3NpZ24KICAgIEBmb3IgQGVtYmVyL3BvbHlmaWxscwogICAgQHBhcmFtIHtPYmplY3R9IHRhcmdldCBUaGUgb2JqZWN0IHRvIGFzc2lnbiBpbnRvCiAgICBAcGFyYW0ge09iamVjdH0gLi4uYXJncyBUaGUgb2JqZWN0cyB0byBjb3B5IHByb3BlcnRpZXMgZnJvbQogICAgQHJldHVybiB7T2JqZWN0fQogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICovCiAgZnVuY3Rpb24gYXNzaWduKHRhcmdldCkgewogICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGFyZyA9IGFyZ3VtZW50c1tpXTsKCiAgICAgIGlmICghYXJnKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIHZhciB1cGRhdGVzID0gT2JqZWN0LmtleXMoYXJnKTsKCiAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCB1cGRhdGVzLmxlbmd0aDsgX2krKykgewogICAgICAgIHZhciBwcm9wID0gdXBkYXRlc1tfaV07CiAgICAgICAgdGFyZ2V0W3Byb3BdID0gYXJnW3Byb3BdOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHRhcmdldDsKICB9IC8vIE5vdGU6IFdlIHVzZSB0aGUgYnJhY2tldCBub3RhdGlvbiBzbwogIC8vICAgICAgIHRoYXQgdGhlIGJhYmVsIHBsdWdpbiBkb2VzIG5vdAogIC8vICAgICAgIHRyYW5zZm9ybSBpdC4KICAvLyBodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9iYWJlbC1wbHVnaW4tdHJhbnNmb3JtLW9iamVjdC1hc3NpZ24KCgogIHZhciBfYXNzaWduID0gT2JqZWN0LmFzc2lnbjsKCiAgdmFyIF9kZWZhdWx0ID0gX2Fzc2lnbiB8fCBhc3NpZ247CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL3BvbHlmaWxscy9saWIvbWVyZ2UiLCBbImV4cG9ydHMiLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlYnVnKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gbWVyZ2U7CgogIC8qKgogICAgTWVyZ2UgdGhlIGNvbnRlbnRzIG9mIHR3byBvYmplY3RzIHRvZ2V0aGVyIGludG8gdGhlIGZpcnN0IG9iamVjdC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IG1lcmdlIH0gZnJvbSAnQGVtYmVyL3BvbHlmaWxscyc7CiAgCiAgICBtZXJnZSh7IGZpcnN0OiAnVG9tJyB9LCB7IGxhc3Q6ICdEYWxlJyB9KTsgLy8geyBmaXJzdDogJ1RvbScsIGxhc3Q6ICdEYWxlJyB9CiAgICB2YXIgYSA9IHsgZmlyc3Q6ICdZZWh1ZGEnIH07CiAgICB2YXIgYiA9IHsgbGFzdDogJ0thdHonIH07CiAgICBtZXJnZShhLCBiKTsgLy8gYSA9PSB7IGZpcnN0OiAnWWVodWRhJywgbGFzdDogJ0thdHonIH0sIGIgPT0geyBsYXN0OiAnS2F0eicgfQogICAgYGBgCiAgCiAgICBAbWV0aG9kIG1lcmdlCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9wb2x5ZmlsbHMKICAgIEBwYXJhbSB7T2JqZWN0fSBvcmlnaW5hbCBUaGUgb2JqZWN0IHRvIG1lcmdlIGludG8KICAgIEBwYXJhbSB7T2JqZWN0fSB1cGRhdGVzIFRoZSBvYmplY3QgdG8gY29weSBwcm9wZXJ0aWVzIGZyb20KICAgIEByZXR1cm4ge09iamVjdH0KICAgIEBkZXByZWNhdGVkCiAgICBAcHVibGljCiAgKi8KICBmdW5jdGlvbiBtZXJnZShvcmlnaW5hbCwgdXBkYXRlcykgewogICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgnVXNlIG9mIGBtZXJnZWAgaGFzIGJlZW4gZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBgYXNzaWduYCBpbnN0ZWFkLicsIGZhbHNlLCB7CiAgICAgIGlkOiAnZW1iZXItcG9seWZpbGxzLmRlcHJlY2F0ZS1tZXJnZScsCiAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54LyN0b2NfZW1iZXItcG9seWZpbGxzLWRlcHJlY2F0ZS1tZXJnZScKICAgIH0pKTsKCiAgICBpZiAodXBkYXRlcyA9PT0gbnVsbCB8fCB0eXBlb2YgdXBkYXRlcyAhPT0gJ29iamVjdCcpIHsKICAgICAgcmV0dXJuIG9yaWdpbmFsOwogICAgfQoKICAgIHZhciBwcm9wcyA9IE9iamVjdC5rZXlzKHVwZGF0ZXMpOwogICAgdmFyIHByb3A7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgewogICAgICBwcm9wID0gcHJvcHNbaV07CiAgICAgIG9yaWdpbmFsW3Byb3BdID0gdXBkYXRlc1twcm9wXTsKICAgIH0KCiAgICByZXR1cm4gb3JpZ2luYWw7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvcG9seWZpbGxzL2xpYi93ZWFrX3NldCIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qIGdsb2JhbHMgV2Vha1NldCAqLwogIHZhciBfZGVmYXVsdCA9IHR5cGVvZiBXZWFrU2V0ID09PSAnZnVuY3Rpb24nID8gV2Vha1NldCA6CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFdlYWtTZXRQb2x5RmlsbCgpIHsKICAgICAgdGhpcy5fbWFwID0gbmV3IFdlYWtNYXAoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gV2Vha1NldFBvbHlGaWxsLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uYWRkID0gZnVuY3Rpb24gYWRkKHZhbCkgewogICAgICB0aGlzLl9tYXAuc2V0KHZhbCwgdHJ1ZSk7CgogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgX3Byb3RvLmRlbGV0ZSA9IGZ1bmN0aW9uIF9kZWxldGUodmFsKSB7CiAgICAgIHJldHVybiB0aGlzLl9tYXAuZGVsZXRlKHZhbCk7CiAgICB9OwoKICAgIF9wcm90by5oYXMgPSBmdW5jdGlvbiBoYXModmFsKSB7CiAgICAgIHJldHVybiB0aGlzLl9tYXAuaGFzKHZhbCk7CiAgICB9OwoKICAgIHJldHVybiBXZWFrU2V0UG9seUZpbGw7CiAgfSgpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci9ydW5sb29wL2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvLWludGVybmFscy9lcnJvci1oYW5kbGluZyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJiYWNrYnVybmVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlYnVnLCBfZXJyb3JIYW5kbGluZywgX21ldGFsLCBfYmFja2J1cm5lcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZ2V0Q3VycmVudFJ1bkxvb3AgPSBnZXRDdXJyZW50UnVuTG9vcDsKICBfZXhwb3J0cy5ydW4gPSBydW47CiAgX2V4cG9ydHMuam9pbiA9IGpvaW47CiAgX2V4cG9ydHMuYmVnaW4gPSBiZWdpbjsKICBfZXhwb3J0cy5lbmQgPSBlbmQ7CiAgX2V4cG9ydHMuc2NoZWR1bGUgPSBzY2hlZHVsZTsKICBfZXhwb3J0cy5oYXNTY2hlZHVsZWRUaW1lcnMgPSBoYXNTY2hlZHVsZWRUaW1lcnM7CiAgX2V4cG9ydHMuY2FuY2VsVGltZXJzID0gY2FuY2VsVGltZXJzOwogIF9leHBvcnRzLmxhdGVyID0gbGF0ZXI7CiAgX2V4cG9ydHMub25jZSA9IG9uY2U7CiAgX2V4cG9ydHMuc2NoZWR1bGVPbmNlID0gc2NoZWR1bGVPbmNlOwogIF9leHBvcnRzLm5leHQgPSBuZXh0OwogIF9leHBvcnRzLmNhbmNlbCA9IGNhbmNlbDsKICBfZXhwb3J0cy5kZWJvdW5jZSA9IGRlYm91bmNlOwogIF9leHBvcnRzLnRocm90dGxlID0gdGhyb3R0bGU7CiAgX2V4cG9ydHMuYmluZCA9IF9leHBvcnRzLl9nbG9iYWxzUnVuID0gX2V4cG9ydHMuYmFja2J1cm5lciA9IF9leHBvcnRzLnF1ZXVlcyA9IF9leHBvcnRzLl9yc3ZwRXJyb3JRdWV1ZSA9IHZvaWQgMDsKICB2YXIgY3VycmVudFJ1bkxvb3AgPSBudWxsOwoKICBmdW5jdGlvbiBnZXRDdXJyZW50UnVuTG9vcCgpIHsKICAgIHJldHVybiBjdXJyZW50UnVuTG9vcDsKICB9CgogIGZ1bmN0aW9uIG9uQmVnaW4oY3VycmVudCkgewogICAgY3VycmVudFJ1bkxvb3AgPSBjdXJyZW50OwogIH0KCiAgZnVuY3Rpb24gb25FbmQoY3VycmVudCwgbmV4dCkgewogICAgY3VycmVudFJ1bkxvb3AgPSBuZXh0OwoKICAgIGlmICh0cnVlCiAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICkgewogICAgICAgICgwLCBfbWV0YWwuZmx1c2hBc3luY09ic2VydmVycykoKTsKICAgICAgfQogIH0KCiAgdmFyIGZsdXNoOwoKICBpZiAodHJ1ZQogIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICkgewogICAgICBmbHVzaCA9IGZ1bmN0aW9uIGZsdXNoKHF1ZXVlTmFtZSwgbmV4dCkgewogICAgICAgIGlmIChxdWV1ZU5hbWUgPT09ICdyZW5kZXInIHx8IHF1ZXVlTmFtZSA9PT0gX3JzdnBFcnJvclF1ZXVlKSB7CiAgICAgICAgICAoMCwgX21ldGFsLmZsdXNoQXN5bmNPYnNlcnZlcnMpKCk7CiAgICAgICAgfQoKICAgICAgICBuZXh0KCk7CiAgICAgIH07CiAgICB9CgogIHZhciBfcnN2cEVycm9yUXVldWUgPSAoIiIgKyBNYXRoLnJhbmRvbSgpICsgRGF0ZS5ub3coKSkucmVwbGFjZSgnLicsICcnKTsKICAvKioKICAgIEFycmF5IG9mIG5hbWVkIHF1ZXVlcy4gVGhpcyBhcnJheSBkZXRlcm1pbmVzIHRoZSBvcmRlciBpbiB3aGljaCBxdWV1ZXMKICAgIGFyZSBmbHVzaGVkIGF0IHRoZSBlbmQgb2YgdGhlIFJ1bkxvb3AuIFlvdSBjYW4gZGVmaW5lIHlvdXIgb3duIHF1ZXVlcyBieQogICAgc2ltcGx5IGFkZGluZyB0aGUgcXVldWUgbmFtZSB0byB0aGlzIGFycmF5LiBOb3JtYWxseSB5b3Ugc2hvdWxkIG5vdCBuZWVkCiAgICB0byBpbnNwZWN0IG9yIG1vZGlmeSB0aGlzIHByb3BlcnR5LgogIAogICAgQHByb3BlcnR5IHF1ZXVlcwogICAgQHR5cGUgQXJyYXkKICAgIEBkZWZhdWx0IFsnYWN0aW9ucycsICdkZXN0cm95J10KICAgIEBwcml2YXRlCiAgKi8KCgogIF9leHBvcnRzLl9yc3ZwRXJyb3JRdWV1ZSA9IF9yc3ZwRXJyb3JRdWV1ZTsKICB2YXIgcXVldWVzID0gWydhY3Rpb25zJywgLy8gdXNlZCBpbiByb3V0ZXIgdHJhbnNpdGlvbnMgdG8gcHJldmVudCB1bm5lY2Vzc2FyeSBsb2FkaW5nIHN0YXRlIGVudHJ5CiAgLy8gaWYgYWxsIGNvbnRleHQgcHJvbWlzZXMgcmVzb2x2ZSBvbiB0aGUgJ2FjdGlvbnMnIHF1ZXVlIGZpcnN0CiAgJ3JvdXRlclRyYW5zaXRpb25zJywgJ3JlbmRlcicsICdhZnRlclJlbmRlcicsICdkZXN0cm95JywgLy8gdXNlZCB0byByZS10aHJvdyB1bmhhbmRsZWQgUlNWUCByZWplY3Rpb24gZXJyb3JzIHNwZWNpZmljYWxseSBpbiB0aGlzCiAgLy8gcG9zaXRpb24gdG8gYXZvaWQgYnJlYWtpbmcgYW55dGhpbmcgcmVuZGVyZWQgaW4gdGhlIG90aGVyIHNlY3Rpb25zCiAgX3JzdnBFcnJvclF1ZXVlXTsKICBfZXhwb3J0cy5xdWV1ZXMgPSBxdWV1ZXM7CiAgdmFyIGJhY2tidXJuZXIgPSBuZXcgX2JhY2tidXJuZXIuZGVmYXVsdChxdWV1ZXMsIHsKICAgIGRlZmF1bHRRdWV1ZTogJ2FjdGlvbnMnLAogICAgb25CZWdpbjogb25CZWdpbiwKICAgIG9uRW5kOiBvbkVuZCwKICAgIG9uRXJyb3JUYXJnZXQ6IF9lcnJvckhhbmRsaW5nLm9uRXJyb3JUYXJnZXQsCiAgICBvbkVycm9yTWV0aG9kOiAnb25lcnJvcicsCiAgICBmbHVzaDogZmx1c2gKICB9KTsKICAvKioKICAgQG1vZHVsZSBAZW1iZXIvcnVubG9vcAogICovCiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogIC8vIHJ1biAtIHRoaXMgaXMgaWRlYWxseSB0aGUgb25seSBwdWJsaWMgQVBJIHRoZSBkZXYgc2VlcwogIC8vCgogIC8qKgogICAgUnVucyB0aGUgcGFzc2VkIHRhcmdldCBhbmQgbWV0aG9kIGluc2lkZSBvZiBhIFJ1bkxvb3AsIGVuc3VyaW5nIGFueQogICAgZGVmZXJyZWQgYWN0aW9ucyBpbmNsdWRpbmcgYmluZGluZ3MgYW5kIHZpZXdzIHVwZGF0ZXMgYXJlIGZsdXNoZWQgYXQgdGhlCiAgICBlbmQuCiAgCiAgICBOb3JtYWxseSB5b3Ugc2hvdWxkIG5vdCBuZWVkIHRvIGludm9rZSB0aGlzIG1ldGhvZCB5b3Vyc2VsZi4gSG93ZXZlciBpZgogICAgeW91IGFyZSBpbXBsZW1lbnRpbmcgcmF3IGV2ZW50IGhhbmRsZXJzIHdoZW4gaW50ZXJmYWNpbmcgd2l0aCBvdGhlcgogICAgbGlicmFyaWVzIG9yIHBsdWdpbnMsIHlvdSBzaG91bGQgcHJvYmFibHkgd3JhcCBhbGwgb2YgeW91ciBjb2RlIGluc2lkZSB0aGlzCiAgICBjYWxsLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgcnVuIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogIAogICAgcnVuKGZ1bmN0aW9uKCkgewogICAgICAvLyBjb2RlIHRvIGJlIGV4ZWN1dGVkIHdpdGhpbiBhIFJ1bkxvb3AKICAgIH0pOwogICAgYGBgCiAgICBAbWV0aG9kIHJ1bgogICAgQGZvciBAZW1iZXIvcnVubG9vcAogICAgQHN0YXRpYwogICAgQHBhcmFtIHtPYmplY3R9IFt0YXJnZXRdIHRhcmdldCBvZiBtZXRob2QgdG8gY2FsbAogICAgQHBhcmFtIHtGdW5jdGlvbnxTdHJpbmd9IG1ldGhvZCBNZXRob2QgdG8gaW52b2tlLgogICAgICBNYXkgYmUgYSBmdW5jdGlvbiBvciBhIHN0cmluZy4gSWYgeW91IHBhc3MgYSBzdHJpbmcKICAgICAgdGhlbiBpdCB3aWxsIGJlIGxvb2tlZCB1cCBvbiB0aGUgcGFzc2VkIHRhcmdldC4KICAgIEBwYXJhbSB7T2JqZWN0fSBbYXJncypdIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyB5b3Ugd2lzaCB0byBwYXNzIHRvIHRoZSBtZXRob2QuCiAgICBAcmV0dXJuIHtPYmplY3R9IHJldHVybiB2YWx1ZSBmcm9tIGludm9raW5nIHRoZSBwYXNzZWQgZnVuY3Rpb24uCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMuYmFja2J1cm5lciA9IGJhY2tidXJuZXI7CgogIGZ1bmN0aW9uIHJ1bigpIHsKICAgIHJldHVybiBiYWNrYnVybmVyLnJ1bi5hcHBseShiYWNrYnVybmVyLCBhcmd1bWVudHMpOwogIH0gLy8gdXNlZCBmb3IgdGhlIEVtYmVyLnJ1biBnbG9iYWwgb25seQoKCiAgdmFyIF9nbG9iYWxzUnVuID0gcnVuLmJpbmQobnVsbCk7CiAgLyoqCiAgICBJZiBubyBydW4tbG9vcCBpcyBwcmVzZW50LCBpdCBjcmVhdGVzIGEgbmV3IG9uZS4gSWYgYSBydW4gbG9vcCBpcwogICAgcHJlc2VudCBpdCB3aWxsIHF1ZXVlIGl0c2VsZiB0byBydW4gb24gdGhlIGV4aXN0aW5nIHJ1bi1sb29wcyBhY3Rpb24KICAgIHF1ZXVlLgogIAogICAgUGxlYXNlIG5vdGU6IFRoaXMgaXMgbm90IGZvciBub3JtYWwgdXNhZ2UsIGFuZCBzaG91bGQgYmUgdXNlZCBzcGFyaW5nbHkuCiAgCiAgICBJZiBpbnZva2VkIHdoZW4gbm90IHdpdGhpbiBhIHJ1biBsb29wOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgam9pbiB9IGZyb20gJ0BlbWJlci9ydW5sb29wJzsKICAKICAgIGpvaW4oZnVuY3Rpb24oKSB7CiAgICAgIC8vIGNyZWF0ZXMgYSBuZXcgcnVuLWxvb3AKICAgIH0pOwogICAgYGBgCiAgCiAgICBBbHRlcm5hdGl2ZWx5LCBpZiBjYWxsZWQgd2l0aGluIGFuIGV4aXN0aW5nIHJ1biBsb29wOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgcnVuLCBqb2luIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogIAogICAgcnVuKGZ1bmN0aW9uKCkgewogICAgICAvLyBjcmVhdGVzIGEgbmV3IHJ1bi1sb29wCiAgCiAgICAgIGpvaW4oZnVuY3Rpb24oKSB7CiAgICAgICAgLy8gam9pbnMgd2l0aCB0aGUgZXhpc3RpbmcgcnVuLWxvb3AsIGFuZCBxdWV1ZXMgZm9yIGludm9jYXRpb24gb24KICAgICAgICAvLyB0aGUgZXhpc3RpbmcgcnVuLWxvb3BzIGFjdGlvbiBxdWV1ZS4KICAgICAgfSk7CiAgICB9KTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBqb2luCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9ydW5sb29wCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gdGFyZ2V0IG9mIG1ldGhvZCB0byBjYWxsCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIE1ldGhvZCB0byBpbnZva2UuCiAgICAgIE1heSBiZSBhIGZ1bmN0aW9uIG9yIGEgc3RyaW5nLiBJZiB5b3UgcGFzcyBhIHN0cmluZwogICAgICB0aGVuIGl0IHdpbGwgYmUgbG9va2VkIHVwIG9uIHRoZSBwYXNzZWQgdGFyZ2V0LgogICAgQHBhcmFtIHtPYmplY3R9IFthcmdzKl0gQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIHlvdSB3aXNoIHRvIHBhc3MgdG8gdGhlIG1ldGhvZC4KICAgIEByZXR1cm4ge09iamVjdH0gUmV0dXJuIHZhbHVlIGZyb20gaW52b2tpbmcgdGhlIHBhc3NlZCBmdW5jdGlvbi4gUGxlYXNlIG5vdGUsCiAgICB3aGVuIGNhbGxlZCB3aXRoaW4gYW4gZXhpc3RpbmcgbG9vcCwgbm8gcmV0dXJuIHZhbHVlIGlzIHBvc3NpYmxlLgogICAgQHB1YmxpYwogICovCgoKICBfZXhwb3J0cy5fZ2xvYmFsc1J1biA9IF9nbG9iYWxzUnVuOwoKICBmdW5jdGlvbiBqb2luKCkgewogICAgcmV0dXJuIGJhY2tidXJuZXIuam9pbi5hcHBseShiYWNrYnVybmVyLCBhcmd1bWVudHMpOwogIH0KICAvKioKICAgIEFsbG93cyB5b3UgdG8gc3BlY2lmeSB3aGljaCBjb250ZXh0IHRvIGNhbGwgdGhlIHNwZWNpZmllZCBmdW5jdGlvbiBpbiB3aGlsZQogICAgYWRkaW5nIHRoZSBleGVjdXRpb24gb2YgdGhhdCBmdW5jdGlvbiB0byB0aGUgRW1iZXIgcnVuIGxvb3AuIFRoaXMgYWJpbGl0eQogICAgbWFrZXMgdGhpcyBtZXRob2QgYSBncmVhdCB3YXkgdG8gYXN5bmNocm9ub3VzbHkgaW50ZWdyYXRlIHRoaXJkLXBhcnR5IGxpYnJhcmllcwogICAgaW50byB5b3VyIEVtYmVyIGFwcGxpY2F0aW9uLgogIAogICAgYGJpbmRgIHRha2VzIHR3byBtYWluIGFyZ3VtZW50cywgdGhlIGRlc2lyZWQgY29udGV4dCBhbmQgdGhlIGZ1bmN0aW9uIHRvCiAgICBpbnZva2UgaW4gdGhhdCBjb250ZXh0LiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgd2lsbCBiZSBzdXBwbGllZCBhcyBhcmd1bWVudHMKICAgIHRvIHRoZSBmdW5jdGlvbiB0aGF0IGlzIHBhc3NlZCBpbi4KICAKICAgIExldCdzIHVzZSB0aGUgY3JlYXRpb24gb2YgYSBUaW55TUNFIGNvbXBvbmVudCBhcyBhbiBleGFtcGxlLiBDdXJyZW50bHksCiAgICBUaW55TUNFIHByb3ZpZGVzIGEgc2V0dXAgY29uZmlndXJhdGlvbiBvcHRpb24gd2UgY2FuIHVzZSB0byBkbyBzb21lIHByb2Nlc3NpbmcKICAgIGFmdGVyIHRoZSBUaW55TUNFIGluc3RhbmNlIGlzIGluaXRpYWxpemVkIGJ1dCBiZWZvcmUgaXQgaXMgYWN0dWFsbHkgcmVuZGVyZWQuCiAgICBXZSBjYW4gdXNlIHRoYXQgc2V0dXAgb3B0aW9uIHRvIGRvIHNvbWUgYWRkaXRpb25hbCBzZXR1cCBmb3Igb3VyIGNvbXBvbmVudC4KICAgIFRoZSBjb21wb25lbnQgaXRzZWxmIGNvdWxkIGxvb2sgc29tZXRoaW5nIGxpa2UgdGhlIGZvbGxvd2luZzoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL3JpY2gtdGV4dC1lZGl0b3IuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBvbiB9IGZyb20gJ0BlbWJlci9vYmplY3QvZXZlbnRlZCc7CiAgICBpbXBvcnQgeyBiaW5kIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGluaXRpYWxpemVUaW55TUNFOiBvbignZGlkSW5zZXJ0RWxlbWVudCcsIGZ1bmN0aW9uKCkgewogICAgICAgIHRpbnltY2UuaW5pdCh7CiAgICAgICAgICBzZWxlY3RvcjogJyMnICsgdGhpcy4kKCkucHJvcCgnaWQnKSwKICAgICAgICAgIHNldHVwOiBiaW5kKHRoaXMsIHRoaXMuc2V0dXBFZGl0b3IpCiAgICAgICAgfSk7CiAgICAgIH0pLAogIAogICAgICBkaWRJbnNlcnRFbGVtZW50KCkgewogICAgICAgIHRpbnltY2UuaW5pdCh7CiAgICAgICAgICBzZWxlY3RvcjogJyMnICsgdGhpcy4kKCkucHJvcCgnaWQnKSwKICAgICAgICAgIHNldHVwOiBiaW5kKHRoaXMsIHRoaXMuc2V0dXBFZGl0b3IpCiAgICAgICAgfSk7CiAgICAgIH0KICAKICAgICAgc2V0dXBFZGl0b3IoZWRpdG9yKSB7CiAgICAgICAgdGhpcy5zZXQoJ2VkaXRvcicsIGVkaXRvcik7CiAgCiAgICAgICAgZWRpdG9yLm9uKCdjaGFuZ2UnLCBmdW5jdGlvbigpIHsKICAgICAgICAgIGNvbnNvbGUubG9nKCdjb250ZW50IGNoYW5nZWQhJyk7CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBJbiB0aGlzIGV4YW1wbGUsIHdlIHVzZSBgYmluZGAgdG8gYmluZCB0aGUgc2V0dXBFZGl0b3IgbWV0aG9kIHRvIHRoZQogICAgY29udGV4dCBvZiB0aGUgUmljaFRleHRFZGl0b3IgY29tcG9uZW50IGFuZCB0byBoYXZlIHRoZSBpbnZvY2F0aW9uIG9mIHRoYXQKICAgIG1ldGhvZCBiZSBzYWZlbHkgaGFuZGxlZCBhbmQgZXhlY3V0ZWQgYnkgdGhlIEVtYmVyIHJ1biBsb29wLgogIAogICAgQG1ldGhvZCBiaW5kCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9ydW5sb29wCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gdGFyZ2V0IG9mIG1ldGhvZCB0byBjYWxsCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIE1ldGhvZCB0byBpbnZva2UuCiAgICAgIE1heSBiZSBhIGZ1bmN0aW9uIG9yIGEgc3RyaW5nLiBJZiB5b3UgcGFzcyBhIHN0cmluZwogICAgICB0aGVuIGl0IHdpbGwgYmUgbG9va2VkIHVwIG9uIHRoZSBwYXNzZWQgdGFyZ2V0LgogICAgQHBhcmFtIHtPYmplY3R9IFthcmdzKl0gQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIHlvdSB3aXNoIHRvIHBhc3MgdG8gdGhlIG1ldGhvZC4KICAgIEByZXR1cm4ge0Z1bmN0aW9ufSByZXR1cm5zIGEgbmV3IGZ1bmN0aW9uIHRoYXQgd2lsbCBhbHdheXMgaGF2ZSBhIHBhcnRpY3VsYXIgY29udGV4dAogICAgQHNpbmNlIDEuNC4wCiAgICBAcHVibGljCiAgKi8KCgogIHZhciBiaW5kID0gZnVuY3Rpb24gYmluZCgpIHsKICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBjdXJyaWVkID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICBjdXJyaWVkW19rZXldID0gYXJndW1lbnRzW19rZXldOwogICAgfQoKICAgIChmYWxzZSAmJiAhKGZ1bmN0aW9uIChtZXRob2RPclRhcmdldCwgbWV0aG9kT3JBcmcpIHsKICAgICAgLy8gQXBwbGllcyB0aGUgc2FtZSBsb2dpYyBhcyBiYWNrYnVybmVyIHBhcnNlQXJncyBmb3IgZGV0ZWN0aW5nIGlmIGEgbWV0aG9kCiAgICAgIC8vIGlzIGFjdHVhbGx5IGJlaW5nIHBhc3NlZC4KICAgICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7CgogICAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gMSkgewogICAgICAgIHJldHVybiB0eXBlb2YgbWV0aG9kT3JUYXJnZXQgPT09ICdmdW5jdGlvbic7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgbWV0aG9kT3JBcmc7CiAgICAgICAgcmV0dXJuIHR5cGUgPT09ICdmdW5jdGlvbicgfHwgLy8gc2Vjb25kIGFyZ3VtZW50IGlzIGEgZnVuY3Rpb24KICAgICAgICBtZXRob2RPclRhcmdldCAhPT0gbnVsbCAmJiB0eXBlID09PSAnc3RyaW5nJyAmJiBtZXRob2RPckFyZyBpbiBtZXRob2RPclRhcmdldCB8fCAvLyBzZWNvbmQgYXJndW1lbnQgaXMgdGhlIG5hbWUgb2YgYSBtZXRob2QgaW4gZmlyc3QgYXJndW1lbnQKICAgICAgICB0eXBlb2YgbWV0aG9kT3JUYXJnZXQgPT09ICdmdW5jdGlvbicgLy9maXJzdCBhcmd1bWVudCBpcyBhIGZ1bmN0aW9uCiAgICAgICAgOwogICAgICB9CiAgICB9LmFwcGx5KHZvaWQgMCwgY3VycmllZCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnY291bGQgbm90IGZpbmQgYSBzdWl0YWJsZSBtZXRob2QgdG8gYmluZCcsIGZ1bmN0aW9uIChtZXRob2RPclRhcmdldCwgbWV0aG9kT3JBcmcpIHsKICAgICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7CgogICAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gMSkgewogICAgICAgIHJldHVybiB0eXBlb2YgbWV0aG9kT3JUYXJnZXQgPT09ICdmdW5jdGlvbic7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgbWV0aG9kT3JBcmc7CiAgICAgICAgcmV0dXJuIHR5cGUgPT09ICdmdW5jdGlvbicgfHwgbWV0aG9kT3JUYXJnZXQgIT09IG51bGwgJiYgdHlwZSA9PT0gJ3N0cmluZycgJiYgbWV0aG9kT3JBcmcgaW4gbWV0aG9kT3JUYXJnZXQgfHwgdHlwZW9mIG1ldGhvZE9yVGFyZ2V0ID09PSAnZnVuY3Rpb24nOwogICAgICB9CiAgICB9LmFwcGx5KHZvaWQgMCwgY3VycmllZCkpKTsKICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgIGZvciAodmFyIF9sZW4yID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuMiksIF9rZXkyID0gMDsgX2tleTIgPCBfbGVuMjsgX2tleTIrKykgewogICAgICAgIGFyZ3NbX2tleTJdID0gYXJndW1lbnRzW19rZXkyXTsKICAgICAgfQoKICAgICAgcmV0dXJuIGpvaW4uYXBwbHkodm9pZCAwLCBjdXJyaWVkLmNvbmNhdChhcmdzKSk7CiAgICB9OwogIH07CiAgLyoqCiAgICBCZWdpbnMgYSBuZXcgUnVuTG9vcC4gQW55IGRlZmVycmVkIGFjdGlvbnMgaW52b2tlZCBhZnRlciB0aGUgYmVnaW4gd2lsbAogICAgYmUgYnVmZmVyZWQgdW50aWwgeW91IGludm9rZSBhIG1hdGNoaW5nIGNhbGwgdG8gYGVuZCgpYC4gVGhpcyBpcwogICAgYSBsb3dlci1sZXZlbCB3YXkgdG8gdXNlIGEgUnVuTG9vcCBpbnN0ZWFkIG9mIHVzaW5nIGBydW4oKWAuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBiZWdpbiwgZW5kIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogIAogICAgYmVnaW4oKTsKICAgIC8vIGNvZGUgdG8gYmUgZXhlY3V0ZWQgd2l0aGluIGEgUnVuTG9vcAogICAgZW5kKCk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgYmVnaW4KICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL3J1bmxvb3AKICAgIEByZXR1cm4ge3ZvaWR9CiAgICBAcHVibGljCiAgKi8KCgogIF9leHBvcnRzLmJpbmQgPSBiaW5kOwoKICBmdW5jdGlvbiBiZWdpbigpIHsKICAgIGJhY2tidXJuZXIuYmVnaW4oKTsKICB9CiAgLyoqCiAgICBFbmRzIGEgUnVuTG9vcC4gVGhpcyBtdXN0IGJlIGNhbGxlZCBzb21ldGltZSBhZnRlciB5b3UgY2FsbAogICAgYGJlZ2luKClgIHRvIGZsdXNoIGFueSBkZWZlcnJlZCBhY3Rpb25zLiBUaGlzIGlzIGEgbG93ZXItbGV2ZWwgd2F5CiAgICB0byB1c2UgYSBSdW5Mb29wIGluc3RlYWQgb2YgdXNpbmcgYHJ1bigpYC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGJlZ2luLCBlbmQgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBiZWdpbigpOwogICAgLy8gY29kZSB0byBiZSBleGVjdXRlZCB3aXRoaW4gYSBSdW5Mb29wCiAgICBlbmQoKTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBlbmQKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL3J1bmxvb3AKICAgIEByZXR1cm4ge3ZvaWR9CiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGVuZCgpIHsKICAgIGJhY2tidXJuZXIuZW5kKCk7CiAgfQogIC8qKgogICAgQWRkcyB0aGUgcGFzc2VkIHRhcmdldC9tZXRob2QgYW5kIGFueSBvcHRpb25hbCBhcmd1bWVudHMgdG8gdGhlIG5hbWVkCiAgICBxdWV1ZSB0byBiZSBleGVjdXRlZCBhdCB0aGUgZW5kIG9mIHRoZSBSdW5Mb29wLiBJZiB5b3UgaGF2ZSBub3QgYWxyZWFkeQogICAgc3RhcnRlZCBhIFJ1bkxvb3Agd2hlbiBjYWxsaW5nIHRoaXMgbWV0aG9kIG9uZSB3aWxsIGJlIHN0YXJ0ZWQgZm9yIHlvdQogICAgYXV0b21hdGljYWxseS4KICAKICAgIEF0IHRoZSBlbmQgb2YgYSBSdW5Mb29wLCBhbnkgbWV0aG9kcyBzY2hlZHVsZWQgaW4gdGhpcyB3YXkgd2lsbCBiZSBpbnZva2VkLgogICAgTWV0aG9kcyB3aWxsIGJlIGludm9rZWQgaW4gYW4gb3JkZXIgbWF0Y2hpbmcgdGhlIG5hbWVkIHF1ZXVlcyBkZWZpbmVkIGluCiAgICB0aGUgYHF1ZXVlc2AgcHJvcGVydHkuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzY2hlZHVsZSB9IGZyb20gJ0BlbWJlci9ydW5sb29wJzsKICAKICAgIHNjaGVkdWxlKCdhZnRlclJlbmRlcicsIHRoaXMsIGZ1bmN0aW9uKCkgewogICAgICAvLyB0aGlzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlICdhZnRlclJlbmRlcicgcXVldWUKICAgICAgY29uc29sZS5sb2coJ3NjaGVkdWxlZCBvbiBhZnRlclJlbmRlciBxdWV1ZScpOwogICAgfSk7CiAgCiAgICBzY2hlZHVsZSgnYWN0aW9ucycsIHRoaXMsIGZ1bmN0aW9uKCkgewogICAgICAvLyB0aGlzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlICdhY3Rpb25zJyBxdWV1ZQogICAgICBjb25zb2xlLmxvZygnc2NoZWR1bGVkIG9uIGFjdGlvbnMgcXVldWUnKTsKICAgIH0pOwogIAogICAgLy8gTm90ZSB0aGUgZnVuY3Rpb25zIHdpbGwgYmUgcnVuIGluIG9yZGVyIGJhc2VkIG9uIHRoZSBydW4gcXVldWVzIG9yZGVyLgogICAgLy8gT3V0cHV0IHdvdWxkIGJlOgogICAgLy8gICBzY2hlZHVsZWQgb24gYWN0aW9ucyBxdWV1ZQogICAgLy8gICBzY2hlZHVsZWQgb24gYWZ0ZXJSZW5kZXIgcXVldWUKICAgIGBgYAogIAogICAgQG1ldGhvZCBzY2hlZHVsZQogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvcnVubG9vcAogICAgQHBhcmFtIHtTdHJpbmd9IHF1ZXVlIFRoZSBuYW1lIG9mIHRoZSBxdWV1ZSB0byBzY2hlZHVsZSBhZ2FpbnN0LiBEZWZhdWx0IHF1ZXVlcyBpcyAnYWN0aW9ucycKICAgIEBwYXJhbSB7T2JqZWN0fSBbdGFyZ2V0XSB0YXJnZXQgb2JqZWN0IHRvIHVzZSBhcyB0aGUgY29udGV4dCB3aGVuIGludm9raW5nIGEgbWV0aG9kLgogICAgQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IG1ldGhvZCBUaGUgbWV0aG9kIHRvIGludm9rZS4gSWYgeW91IHBhc3MgYSBzdHJpbmcgaXQKICAgICAgd2lsbCBiZSByZXNvbHZlZCBvbiB0aGUgdGFyZ2V0IG9iamVjdCBhdCB0aGUgdGltZSB0aGUgc2NoZWR1bGVkIGl0ZW0gaXMKICAgICAgaW52b2tlZCBhbGxvd2luZyB5b3UgdG8gY2hhbmdlIHRoZSB0YXJnZXQgZnVuY3Rpb24uCiAgICBAcGFyYW0ge09iamVjdH0gW2FyZ3VtZW50cypdIE9wdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gdGhlIHF1ZXVlZCBtZXRob2QuCiAgICBAcmV0dXJuIHsqfSBUaW1lciBpbmZvcm1hdGlvbiBmb3IgdXNlIGluIGNhbmNlbGluZywgc2VlIGBjYW5jZWxgLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBzY2hlZHVsZSgpCiAgLyogcXVldWUsIHRhcmdldCwgbWV0aG9kICovCiAgewogICAgcmV0dXJuIGJhY2tidXJuZXIuc2NoZWR1bGUuYXBwbHkoYmFja2J1cm5lciwgYXJndW1lbnRzKTsKICB9IC8vIFVzZWQgYnkgZ2xvYmFsIHRlc3QgdGVhcmRvd24KCgogIGZ1bmN0aW9uIGhhc1NjaGVkdWxlZFRpbWVycygpIHsKICAgIHJldHVybiBiYWNrYnVybmVyLmhhc1RpbWVycygpOwogIH0gLy8gVXNlZCBieSBnbG9iYWwgdGVzdCB0ZWFyZG93bgoKCiAgZnVuY3Rpb24gY2FuY2VsVGltZXJzKCkgewogICAgYmFja2J1cm5lci5jYW5jZWxUaW1lcnMoKTsKICB9CiAgLyoqCiAgICBJbnZva2VzIHRoZSBwYXNzZWQgdGFyZ2V0L21ldGhvZCBhbmQgb3B0aW9uYWwgYXJndW1lbnRzIGFmdGVyIGEgc3BlY2lmaWVkCiAgICBwZXJpb2Qgb2YgdGltZS4gVGhlIGxhc3QgcGFyYW1ldGVyIG9mIHRoaXMgbWV0aG9kIG11c3QgYWx3YXlzIGJlIGEgbnVtYmVyCiAgICBvZiBtaWxsaXNlY29uZHMuCiAgCiAgICBZb3Ugc2hvdWxkIHVzZSB0aGlzIG1ldGhvZCB3aGVuZXZlciB5b3UgbmVlZCB0byBydW4gc29tZSBhY3Rpb24gYWZ0ZXIgYQogICAgcGVyaW9kIG9mIHRpbWUgaW5zdGVhZCBvZiB1c2luZyBgc2V0VGltZW91dCgpYC4gVGhpcyBtZXRob2Qgd2lsbCBlbnN1cmUgdGhhdAogICAgaXRlbXMgdGhhdCBleHBpcmUgZHVyaW5nIHRoZSBzYW1lIHNjcmlwdCBleGVjdXRpb24gY3ljbGUgYWxsIGV4ZWN1dGUKICAgIHRvZ2V0aGVyLCB3aGljaCBpcyBvZnRlbiBtb3JlIGVmZmljaWVudCB0aGFuIHVzaW5nIGEgcmVhbCBzZXRUaW1lb3V0LgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgbGF0ZXIgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBsYXRlcihteUNvbnRleHQsIGZ1bmN0aW9uKCkgewogICAgICAvLyBjb2RlIGhlcmUgd2lsbCBleGVjdXRlIHdpdGhpbiBhIFJ1bkxvb3AgaW4gYWJvdXQgNTAwbXMgd2l0aCB0aGlzID09IG15Q29udGV4dAogICAgfSwgNTAwKTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBsYXRlcgogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvcnVubG9vcAogICAgQHBhcmFtIHtPYmplY3R9IFt0YXJnZXRdIHRhcmdldCBvZiBtZXRob2QgdG8gaW52b2tlCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIFRoZSBtZXRob2QgdG8gaW52b2tlLgogICAgICBJZiB5b3UgcGFzcyBhIHN0cmluZyBpdCB3aWxsIGJlIHJlc29sdmVkIG9uIHRoZQogICAgICB0YXJnZXQgYXQgdGhlIHRpbWUgdGhlIG1ldGhvZCBpcyBpbnZva2VkLgogICAgQHBhcmFtIHtPYmplY3R9IFthcmdzKl0gT3B0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIHRpbWVvdXQuCiAgICBAcGFyYW0ge051bWJlcn0gd2FpdCBOdW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIHdhaXQuCiAgICBAcmV0dXJuIHsqfSBUaW1lciBpbmZvcm1hdGlvbiBmb3IgdXNlIGluIGNhbmNlbGluZywgc2VlIGBjYW5jZWxgLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBsYXRlcigpCiAgLyp0YXJnZXQsIG1ldGhvZCovCiAgewogICAgcmV0dXJuIGJhY2tidXJuZXIubGF0ZXIuYXBwbHkoYmFja2J1cm5lciwgYXJndW1lbnRzKTsKICB9CiAgLyoqCiAgIFNjaGVkdWxlIGEgZnVuY3Rpb24gdG8gcnVuIG9uZSB0aW1lIGR1cmluZyB0aGUgY3VycmVudCBSdW5Mb29wLiBUaGlzIGlzIGVxdWl2YWxlbnQKICAgIHRvIGNhbGxpbmcgYHNjaGVkdWxlT25jZWAgd2l0aCB0aGUgImFjdGlvbnMiIHF1ZXVlLgogIAogICAgQG1ldGhvZCBvbmNlCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9ydW5sb29wCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gVGhlIHRhcmdldCBvZiB0aGUgbWV0aG9kIHRvIGludm9rZS4KICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBtZXRob2QgVGhlIG1ldGhvZCB0byBpbnZva2UuCiAgICAgIElmIHlvdSBwYXNzIGEgc3RyaW5nIGl0IHdpbGwgYmUgcmVzb2x2ZWQgb24gdGhlCiAgICAgIHRhcmdldCBhdCB0aGUgdGltZSB0aGUgbWV0aG9kIGlzIGludm9rZWQuCiAgICBAcGFyYW0ge09iamVjdH0gW2FyZ3MqXSBPcHRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgdGltZW91dC4KICAgIEByZXR1cm4ge09iamVjdH0gVGltZXIgaW5mb3JtYXRpb24gZm9yIHVzZSBpbiBjYW5jZWxpbmcsIHNlZSBgY2FuY2VsYC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gb25jZSgpIHsKICAgIGZvciAodmFyIF9sZW4zID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuMyksIF9rZXkzID0gMDsgX2tleTMgPCBfbGVuMzsgX2tleTMrKykgewogICAgICBhcmdzW19rZXkzXSA9IGFyZ3VtZW50c1tfa2V5M107CiAgICB9CgogICAgYXJncy51bnNoaWZ0KCdhY3Rpb25zJyk7CiAgICByZXR1cm4gYmFja2J1cm5lci5zY2hlZHVsZU9uY2UuYXBwbHkoYmFja2J1cm5lciwgYXJncyk7CiAgfQogIC8qKgogICAgU2NoZWR1bGVzIGEgZnVuY3Rpb24gdG8gcnVuIG9uZSB0aW1lIGluIGEgZ2l2ZW4gcXVldWUgb2YgdGhlIGN1cnJlbnQgUnVuTG9vcC4KICAgIENhbGxpbmcgdGhpcyBtZXRob2Qgd2l0aCB0aGUgc2FtZSBxdWV1ZS90YXJnZXQvbWV0aG9kIGNvbWJpbmF0aW9uIHdpbGwgaGF2ZQogICAgbm8gZWZmZWN0IChwYXN0IHRoZSBpbml0aWFsIGNhbGwpLgogIAogICAgTm90ZSB0aGF0IGFsdGhvdWdoIHlvdSBjYW4gcGFzcyBvcHRpb25hbCBhcmd1bWVudHMgdGhlc2Ugd2lsbCBub3QgYmUKICAgIGNvbnNpZGVyZWQgd2hlbiBsb29raW5nIGZvciBkdXBsaWNhdGVzLiBOZXcgYXJndW1lbnRzIHdpbGwgcmVwbGFjZSBwcmV2aW91cwogICAgY2FsbHMuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBydW4sIHNjaGVkdWxlT25jZSB9IGZyb20gJ0BlbWJlci9ydW5sb29wJzsKICAKICAgIGZ1bmN0aW9uIHNheUhpKCkgewogICAgICBjb25zb2xlLmxvZygnaGknKTsKICAgIH0KICAKICAgIHJ1bihmdW5jdGlvbigpIHsKICAgICAgc2NoZWR1bGVPbmNlKCdhZnRlclJlbmRlcicsIG15Q29udGV4dCwgc2F5SGkpOwogICAgICBzY2hlZHVsZU9uY2UoJ2FmdGVyUmVuZGVyJywgbXlDb250ZXh0LCBzYXlIaSk7CiAgICAgIC8vIHNheUhpIHdpbGwgb25seSBiZSBleGVjdXRlZCBvbmNlLCBpbiB0aGUgYWZ0ZXJSZW5kZXIgcXVldWUgb2YgdGhlIFJ1bkxvb3AKICAgIH0pOwogICAgYGBgCiAgCiAgICBBbHNvIG5vdGUgdGhhdCBmb3IgYHNjaGVkdWxlT25jZWAgdG8gcHJldmVudCBhZGRpdGlvbmFsIGNhbGxzLCB5b3UgbmVlZCB0bwogICAgcGFzcyB0aGUgc2FtZSBmdW5jdGlvbiBpbnN0YW5jZS4gVGhlIGZvbGxvd2luZyBjYXNlIHdvcmtzIGFzIGV4cGVjdGVkOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgZnVuY3Rpb24gbG9nKCkgewogICAgICBjb25zb2xlLmxvZygnTG9nZ2luZyBvbmx5IG9uY2UnKTsKICAgIH0KICAKICAgIGZ1bmN0aW9uIHNjaGVkdWxlSXQoKSB7CiAgICAgIHNjaGVkdWxlT25jZSgnYWN0aW9ucycsIG15Q29udGV4dCwgbG9nKTsKICAgIH0KICAKICAgIHNjaGVkdWxlSXQoKTsKICAgIHNjaGVkdWxlSXQoKTsKICAgIGBgYAogIAogICAgQnV0IHRoaXMgb3RoZXIgY2FzZSB3aWxsIHNjaGVkdWxlIHRoZSBmdW5jdGlvbiBtdWx0aXBsZSB0aW1lczoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNjaGVkdWxlT25jZSB9IGZyb20gJ0BlbWJlci9ydW5sb29wJzsKICAKICAgIGZ1bmN0aW9uIHNjaGVkdWxlSXQoKSB7CiAgICAgIHNjaGVkdWxlT25jZSgnYWN0aW9ucycsIG15Q29udGV4dCwgZnVuY3Rpb24oKSB7CiAgICAgICAgY29uc29sZS5sb2coJ0Nsb3N1cmUnKTsKICAgICAgfSk7CiAgICB9CiAgCiAgICBzY2hlZHVsZUl0KCk7CiAgICBzY2hlZHVsZUl0KCk7CiAgCiAgICAvLyAiQ2xvc3VyZSIgd2lsbCBwcmludCB0d2ljZSwgZXZlbiB0aG91Z2ggd2UncmUgdXNpbmcgYHNjaGVkdWxlT25jZWAsCiAgICAvLyBiZWNhdXNlIHRoZSBmdW5jdGlvbiB3ZSBwYXNzIHRvIGl0IHdvbid0IG1hdGNoIHRoZQogICAgLy8gcHJldmlvdXNseSBzY2hlZHVsZWQgb3BlcmF0aW9uLgogICAgYGBgCiAgCiAgICBBdmFpbGFibGUgcXVldWVzLCBhbmQgdGhlaXIgb3JkZXIsIGNhbiBiZSBmb3VuZCBhdCBgcXVldWVzYAogIAogICAgQG1ldGhvZCBzY2hlZHVsZU9uY2UKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL3J1bmxvb3AKICAgIEBwYXJhbSB7U3RyaW5nfSBbcXVldWVdIFRoZSBuYW1lIG9mIHRoZSBxdWV1ZSB0byBzY2hlZHVsZSBhZ2FpbnN0LiBEZWZhdWx0IHF1ZXVlcyBpcyAnYWN0aW9ucycuCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gVGhlIHRhcmdldCBvZiB0aGUgbWV0aG9kIHRvIGludm9rZS4KICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBtZXRob2QgVGhlIG1ldGhvZCB0byBpbnZva2UuCiAgICAgIElmIHlvdSBwYXNzIGEgc3RyaW5nIGl0IHdpbGwgYmUgcmVzb2x2ZWQgb24gdGhlCiAgICAgIHRhcmdldCBhdCB0aGUgdGltZSB0aGUgbWV0aG9kIGlzIGludm9rZWQuCiAgICBAcGFyYW0ge09iamVjdH0gW2FyZ3MqXSBPcHRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgdGltZW91dC4KICAgIEByZXR1cm4ge09iamVjdH0gVGltZXIgaW5mb3JtYXRpb24gZm9yIHVzZSBpbiBjYW5jZWxpbmcsIHNlZSBgY2FuY2VsYC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gc2NoZWR1bGVPbmNlKCkKICAvKiBxdWV1ZSwgdGFyZ2V0LCBtZXRob2QqLwogIHsKICAgIHJldHVybiBiYWNrYnVybmVyLnNjaGVkdWxlT25jZS5hcHBseShiYWNrYnVybmVyLCBhcmd1bWVudHMpOwogIH0KICAvKioKICAgIFNjaGVkdWxlcyBhbiBpdGVtIHRvIHJ1biBmcm9tIHdpdGhpbiBhIHNlcGFyYXRlIHJ1biBsb29wLCBhZnRlcgogICAgY29udHJvbCBoYXMgYmVlbiByZXR1cm5lZCB0byB0aGUgc3lzdGVtLiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gY2FsbGluZwogICAgYGxhdGVyYCB3aXRoIGEgd2FpdCB0aW1lIG9mIDFtcy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IG5leHQgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBuZXh0KG15Q29udGV4dCwgZnVuY3Rpb24oKSB7CiAgICAgIC8vIGNvZGUgdG8gYmUgZXhlY3V0ZWQgaW4gdGhlIG5leHQgcnVuIGxvb3AsCiAgICAgIC8vIHdoaWNoIHdpbGwgYmUgc2NoZWR1bGVkIGFmdGVyIHRoZSBjdXJyZW50IG9uZQogICAgfSk7CiAgICBgYGAKICAKICAgIE11bHRpcGxlIG9wZXJhdGlvbnMgc2NoZWR1bGVkIHdpdGggYG5leHRgIHdpbGwgY29hbGVzY2UKICAgIGludG8gdGhlIHNhbWUgbGF0ZXIgcnVuIGxvb3AsIGFsb25nIHdpdGggYW55IG90aGVyIG9wZXJhdGlvbnMKICAgIHNjaGVkdWxlZCBieSBgbGF0ZXJgIHRoYXQgZXhwaXJlIHJpZ2h0IGFyb3VuZCB0aGUgc2FtZQogICAgdGltZSB0aGF0IGBuZXh0YCBvcGVyYXRpb25zIHdpbGwgZmlyZS4KICAKICAgIE5vdGUgdGhhdCB0aGVyZSBhcmUgb2Z0ZW4gYWx0ZXJuYXRpdmVzIHRvIHVzaW5nIGBuZXh0YC4KICAgIEZvciBpbnN0YW5jZSwgaWYgeW91J2QgbGlrZSB0byBzY2hlZHVsZSBhbiBvcGVyYXRpb24gdG8gaGFwcGVuCiAgICBhZnRlciBhbGwgRE9NIGVsZW1lbnQgb3BlcmF0aW9ucyBoYXZlIGNvbXBsZXRlZCB3aXRoaW4gdGhlIGN1cnJlbnQKICAgIHJ1biBsb29wLCB5b3UgY2FuIG1ha2UgdXNlIG9mIHRoZSBgYWZ0ZXJSZW5kZXJgIHJ1biBsb29wIHF1ZXVlIChhZGRlZAogICAgYnkgdGhlIGBlbWJlci12aWV3c2AgcGFja2FnZSwgYWxvbmcgd2l0aCB0aGUgcHJlY2VkaW5nIGByZW5kZXJgIHF1ZXVlCiAgICB3aGVyZSBhbGwgdGhlIERPTSBlbGVtZW50IG9wZXJhdGlvbnMgaGFwcGVuKS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBzY2hlZHVsZU9uY2UgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBleHBvcnQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGRpZEluc2VydEVsZW1lbnQoKSB7CiAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICBzY2hlZHVsZU9uY2UoJ2FmdGVyUmVuZGVyJywgdGhpcywgJ3Byb2Nlc3NDaGlsZEVsZW1lbnRzJyk7CiAgICAgIH0sCiAgCiAgICAgIHByb2Nlc3NDaGlsZEVsZW1lbnRzKCkgewogICAgICAgIC8vIC4uLiBkbyBzb21ldGhpbmcgd2l0aCBjb21wb25lbnQncyBjaGlsZCBjb21wb25lbnQKICAgICAgICAvLyBlbGVtZW50cyBhZnRlciB0aGV5J3ZlIGZpbmlzaGVkIHJlbmRlcmluZywgd2hpY2gKICAgICAgICAvLyBjYW4ndCBiZSBkb25lIHdpdGhpbiB0aGlzIGNvbXBvbmVudCdzCiAgICAgICAgLy8gYGRpZEluc2VydEVsZW1lbnRgIGhvb2sgYmVjYXVzZSB0aGF0IGdldHMgcnVuCiAgICAgICAgLy8gYmVmb3JlIHRoZSBjaGlsZCBlbGVtZW50cyBoYXZlIGJlZW4gYWRkZWQgdG8gdGhlIERPTS4KICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIE9uZSBiZW5lZml0IG9mIHRoZSBhYm92ZSBhcHByb2FjaCBjb21wYXJlZCB0byB1c2luZyBgbmV4dGAgaXMKICAgIHRoYXQgeW91IHdpbGwgYmUgYWJsZSB0byBwZXJmb3JtIERPTS9DU1Mgb3BlcmF0aW9ucyBiZWZvcmUgdW5wcm9jZXNzZWQKICAgIGVsZW1lbnRzIGFyZSByZW5kZXJlZCB0byB0aGUgc2NyZWVuLCB3aGljaCBtYXkgcHJldmVudCBmbGlja2VyaW5nIG9yCiAgICBvdGhlciBhcnRpZmFjdHMgY2F1c2VkIGJ5IGRlbGF5aW5nIHByb2Nlc3NpbmcgdW50aWwgYWZ0ZXIgcmVuZGVyaW5nLgogIAogICAgVGhlIG90aGVyIG1ham9yIGJlbmVmaXQgdG8gdGhlIGFib3ZlIGFwcHJvYWNoIGlzIHRoYXQgYG5leHRgCiAgICBpbnRyb2R1Y2VzIGFuIGVsZW1lbnQgb2Ygbm9uLWRldGVybWluaXNtLCB3aGljaCBjYW4gbWFrZSB0aGluZ3MgbXVjaAogICAgaGFyZGVyIHRvIHRlc3QsIGR1ZSB0byBpdHMgcmVsaWFuY2Ugb24gYHNldFRpbWVvdXRgOyBpdCdzIG11Y2ggaGFyZGVyCiAgICB0byBndWFyYW50ZWUgdGhlIG9yZGVyIG9mIHNjaGVkdWxlZCBvcGVyYXRpb25zIHdoZW4gdGhleSBhcmUgc2NoZWR1bGVkCiAgICBvdXRzaWRlIG9mIHRoZSBjdXJyZW50IHJ1biBsb29wLCBpLmUuIHdpdGggYG5leHRgLgogIAogICAgQG1ldGhvZCBuZXh0CiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9ydW5sb29wCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gdGFyZ2V0IG9mIG1ldGhvZCB0byBpbnZva2UKICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBtZXRob2QgVGhlIG1ldGhvZCB0byBpbnZva2UuCiAgICAgIElmIHlvdSBwYXNzIGEgc3RyaW5nIGl0IHdpbGwgYmUgcmVzb2x2ZWQgb24gdGhlCiAgICAgIHRhcmdldCBhdCB0aGUgdGltZSB0aGUgbWV0aG9kIGlzIGludm9rZWQuCiAgICBAcGFyYW0ge09iamVjdH0gW2FyZ3MqXSBPcHRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgdGltZW91dC4KICAgIEByZXR1cm4ge09iamVjdH0gVGltZXIgaW5mb3JtYXRpb24gZm9yIHVzZSBpbiBjYW5jZWxpbmcsIHNlZSBgY2FuY2VsYC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbmV4dCgpIHsKICAgIGZvciAodmFyIF9sZW40ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuNCksIF9rZXk0ID0gMDsgX2tleTQgPCBfbGVuNDsgX2tleTQrKykgewogICAgICBhcmdzW19rZXk0XSA9IGFyZ3VtZW50c1tfa2V5NF07CiAgICB9CgogICAgYXJncy5wdXNoKDEpOwogICAgcmV0dXJuIGJhY2tidXJuZXIubGF0ZXIuYXBwbHkoYmFja2J1cm5lciwgYXJncyk7CiAgfQogIC8qKgogICAgQ2FuY2VscyBhIHNjaGVkdWxlZCBpdGVtLiBNdXN0IGJlIGEgdmFsdWUgcmV0dXJuZWQgYnkgYGxhdGVyKClgLAogICAgYG9uY2UoKWAsIGBzY2hlZHVsZU9uY2UoKWAsIGBuZXh0KClgLCBgZGVib3VuY2UoKWAsIG9yCiAgICBgdGhyb3R0bGUoKWAuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgewogICAgICBuZXh0LAogICAgICBjYW5jZWwsCiAgICAgIGxhdGVyLAogICAgICBzY2hlZHVsZU9uY2UsCiAgICAgIG9uY2UsCiAgICAgIHRocm90dGxlLAogICAgICBkZWJvdW5jZQogICAgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBsZXQgcnVuTmV4dCA9IG5leHQobXlDb250ZXh0LCBmdW5jdGlvbigpIHsKICAgICAgLy8gd2lsbCBub3QgYmUgZXhlY3V0ZWQKICAgIH0pOwogIAogICAgY2FuY2VsKHJ1bk5leHQpOwogIAogICAgbGV0IHJ1bkxhdGVyID0gbGF0ZXIobXlDb250ZXh0LCBmdW5jdGlvbigpIHsKICAgICAgLy8gd2lsbCBub3QgYmUgZXhlY3V0ZWQKICAgIH0sIDUwMCk7CiAgCiAgICBjYW5jZWwocnVuTGF0ZXIpOwogIAogICAgbGV0IHJ1blNjaGVkdWxlT25jZSA9IHNjaGVkdWxlT25jZSgnYWZ0ZXJSZW5kZXInLCBteUNvbnRleHQsIGZ1bmN0aW9uKCkgewogICAgICAvLyB3aWxsIG5vdCBiZSBleGVjdXRlZAogICAgfSk7CiAgCiAgICBjYW5jZWwocnVuU2NoZWR1bGVPbmNlKTsKICAKICAgIGxldCBydW5PbmNlID0gb25jZShteUNvbnRleHQsIGZ1bmN0aW9uKCkgewogICAgICAvLyB3aWxsIG5vdCBiZSBleGVjdXRlZAogICAgfSk7CiAgCiAgICBjYW5jZWwocnVuT25jZSk7CiAgCiAgICBsZXQgdGhyb3R0bGUgPSB0aHJvdHRsZShteUNvbnRleHQsIGZ1bmN0aW9uKCkgewogICAgICAvLyB3aWxsIG5vdCBiZSBleGVjdXRlZAogICAgfSwgMSwgZmFsc2UpOwogIAogICAgY2FuY2VsKHRocm90dGxlKTsKICAKICAgIGxldCBkZWJvdW5jZSA9IGRlYm91bmNlKG15Q29udGV4dCwgZnVuY3Rpb24oKSB7CiAgICAgIC8vIHdpbGwgbm90IGJlIGV4ZWN1dGVkCiAgICB9LCAxKTsKICAKICAgIGNhbmNlbChkZWJvdW5jZSk7CiAgCiAgICBsZXQgZGVib3VuY2VJbW1lZGlhdGUgPSBkZWJvdW5jZShteUNvbnRleHQsIGZ1bmN0aW9uKCkgewogICAgICAvLyB3aWxsIGJlIGV4ZWN1dGVkIHNpbmNlIHdlIHBhc3NlZCBpbiB0cnVlIChpbW1lZGlhdGUpCiAgICB9LCAxMDAsIHRydWUpOwogIAogICAgLy8gdGhlIDEwMG1zIGRlbGF5IHVudGlsIHRoaXMgbWV0aG9kIGNhbiBiZSBjYWxsZWQgYWdhaW4gd2lsbCBiZSBjYW5jZWxlZAogICAgY2FuY2VsKGRlYm91bmNlSW1tZWRpYXRlKTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBjYW5jZWwKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL3J1bmxvb3AKICAgIEBwYXJhbSB7T2JqZWN0fSB0aW1lciBUaW1lciBvYmplY3QgdG8gY2FuY2VsCiAgICBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIGNhbmNlbGVkIG9yIGZhbHNlL3VuZGVmaW5lZCBpZiBpdCB3YXNuJ3QgZm91bmQKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gY2FuY2VsKHRpbWVyKSB7CiAgICByZXR1cm4gYmFja2J1cm5lci5jYW5jZWwodGltZXIpOwogIH0KICAvKioKICAgIERlbGF5IGNhbGxpbmcgdGhlIHRhcmdldCBtZXRob2QgdW50aWwgdGhlIGRlYm91bmNlIHBlcmlvZCBoYXMgZWxhcHNlZAogICAgd2l0aCBubyBhZGRpdGlvbmFsIGRlYm91bmNlIGNhbGxzLiBJZiBgZGVib3VuY2VgIGlzIGNhbGxlZCBhZ2FpbiBiZWZvcmUKICAgIHRoZSBzcGVjaWZpZWQgdGltZSBoYXMgZWxhcHNlZCwgdGhlIHRpbWVyIGlzIHJlc2V0IGFuZCB0aGUgZW50aXJlIHBlcmlvZAogICAgbXVzdCBwYXNzIGFnYWluIGJlZm9yZSB0aGUgdGFyZ2V0IG1ldGhvZCBpcyBjYWxsZWQuCiAgCiAgICBUaGlzIG1ldGhvZCBzaG91bGQgYmUgdXNlZCB3aGVuIGFuIGV2ZW50IG1heSBiZSBjYWxsZWQgbXVsdGlwbGUgdGltZXMKICAgIGJ1dCB0aGUgYWN0aW9uIHNob3VsZCBvbmx5IGJlIGNhbGxlZCBvbmNlIHdoZW4gdGhlIGV2ZW50IGlzIGRvbmUgZmlyaW5nLgogICAgQSBjb21tb24gZXhhbXBsZSBpcyBmb3Igc2Nyb2xsIGV2ZW50cyB3aGVyZSB5b3Ugb25seSB3YW50IHVwZGF0ZXMgdG8KICAgIGhhcHBlbiBvbmNlIHNjcm9sbGluZyBoYXMgY2Vhc2VkLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZGVib3VuY2UgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBmdW5jdGlvbiB3aG9SYW4oKSB7CiAgICAgIGNvbnNvbGUubG9nKHRoaXMubmFtZSArICcgcmFuLicpOwogICAgfQogIAogICAgbGV0IG15Q29udGV4dCA9IHsgbmFtZTogJ2RlYm91bmNlJyB9OwogIAogICAgZGVib3VuY2UobXlDb250ZXh0LCB3aG9SYW4sIDE1MCk7CiAgCiAgICAvLyBsZXNzIHRoYW4gMTUwbXMgcGFzc2VzCiAgICBkZWJvdW5jZShteUNvbnRleHQsIHdob1JhbiwgMTUwKTsKICAKICAgIC8vIDE1MG1zIHBhc3NlcwogICAgLy8gd2hvUmFuIGlzIGludm9rZWQgd2l0aCBjb250ZXh0IG15Q29udGV4dAogICAgLy8gY29uc29sZSBsb2dzICdkZWJvdW5jZSByYW4uJyBvbmUgdGltZS4KICAgIGBgYAogIAogICAgSW1tZWRpYXRlIGFsbG93cyB5b3UgdG8gcnVuIHRoZSBmdW5jdGlvbiBpbW1lZGlhdGVseSwgYnV0IGRlYm91bmNlCiAgICBvdGhlciBjYWxscyBmb3IgdGhpcyBmdW5jdGlvbiB1bnRpbCB0aGUgd2FpdCB0aW1lIGhhcyBlbGFwc2VkLiBJZgogICAgYGRlYm91bmNlYCBpcyBjYWxsZWQgYWdhaW4gYmVmb3JlIHRoZSBzcGVjaWZpZWQgdGltZSBoYXMgZWxhcHNlZCwKICAgIHRoZSB0aW1lciBpcyByZXNldCBhbmQgdGhlIGVudGlyZSBwZXJpb2QgbXVzdCBwYXNzIGFnYWluIGJlZm9yZQogICAgdGhlIG1ldGhvZCBjYW4gYmUgY2FsbGVkIGFnYWluLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZGVib3VuY2UgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBmdW5jdGlvbiB3aG9SYW4oKSB7CiAgICAgIGNvbnNvbGUubG9nKHRoaXMubmFtZSArICcgcmFuLicpOwogICAgfQogIAogICAgbGV0IG15Q29udGV4dCA9IHsgbmFtZTogJ2RlYm91bmNlJyB9OwogIAogICAgZGVib3VuY2UobXlDb250ZXh0LCB3aG9SYW4sIDE1MCwgdHJ1ZSk7CiAgCiAgICAvLyBjb25zb2xlIGxvZ3MgJ2RlYm91bmNlIHJhbi4nIG9uZSB0aW1lIGltbWVkaWF0ZWx5LgogICAgLy8gMTAwbXMgcGFzc2VzCiAgICBkZWJvdW5jZShteUNvbnRleHQsIHdob1JhbiwgMTUwLCB0cnVlKTsKICAKICAgIC8vIDE1MG1zIHBhc3NlcyBhbmQgbm90aGluZyBlbHNlIGlzIGxvZ2dlZCB0byB0aGUgY29uc29sZSBhbmQKICAgIC8vIHRoZSBkZWJvdW5jZWUgaXMgbm8gbG9uZ2VyIGJlaW5nIHdhdGNoZWQKICAgIGRlYm91bmNlKG15Q29udGV4dCwgd2hvUmFuLCAxNTAsIHRydWUpOwogIAogICAgLy8gY29uc29sZSBsb2dzICdkZWJvdW5jZSByYW4uJyBvbmUgdGltZSBpbW1lZGlhdGVseS4KICAgIC8vIDE1MG1zIHBhc3NlcyBhbmQgbm90aGluZyBlbHNlIGlzIGxvZ2dlZCB0byB0aGUgY29uc29sZSBhbmQKICAgIC8vIHRoZSBkZWJvdW5jZWUgaXMgbm8gbG9uZ2VyIGJlaW5nIHdhdGNoZWQKICAgIGBgYAogIAogICAgQG1ldGhvZCBkZWJvdW5jZQogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvcnVubG9vcAogICAgQHBhcmFtIHtPYmplY3R9IFt0YXJnZXRdIHRhcmdldCBvZiBtZXRob2QgdG8gaW52b2tlCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIFRoZSBtZXRob2QgdG8gaW52b2tlLgogICAgICBNYXkgYmUgYSBmdW5jdGlvbiBvciBhIHN0cmluZy4gSWYgeW91IHBhc3MgYSBzdHJpbmcKICAgICAgdGhlbiBpdCB3aWxsIGJlIGxvb2tlZCB1cCBvbiB0aGUgcGFzc2VkIHRhcmdldC4KICAgIEBwYXJhbSB7T2JqZWN0fSBbYXJncypdIE9wdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSB0aW1lb3V0LgogICAgQHBhcmFtIHtOdW1iZXJ9IHdhaXQgTnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byB3YWl0LgogICAgQHBhcmFtIHtCb29sZWFufSBpbW1lZGlhdGUgVHJpZ2dlciB0aGUgZnVuY3Rpb24gb24gdGhlIGxlYWRpbmcgaW5zdGVhZAogICAgICBvZiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgd2FpdCBpbnRlcnZhbC4gRGVmYXVsdHMgdG8gZmFsc2UuCiAgICBAcmV0dXJuIHtBcnJheX0gVGltZXIgaW5mb3JtYXRpb24gZm9yIHVzZSBpbiBjYW5jZWxpbmcsIHNlZSBgY2FuY2VsYC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZGVib3VuY2UoKSB7CiAgICByZXR1cm4gYmFja2J1cm5lci5kZWJvdW5jZS5hcHBseShiYWNrYnVybmVyLCBhcmd1bWVudHMpOwogIH0KICAvKioKICAgIEVuc3VyZSB0aGF0IHRoZSB0YXJnZXQgbWV0aG9kIGlzIG5ldmVyIGNhbGxlZCBtb3JlIGZyZXF1ZW50bHkgdGhhbgogICAgdGhlIHNwZWNpZmllZCBzcGFjaW5nIHBlcmlvZC4gVGhlIHRhcmdldCBtZXRob2QgaXMgY2FsbGVkIGltbWVkaWF0ZWx5LgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgdGhyb3R0bGUgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBmdW5jdGlvbiB3aG9SYW4oKSB7CiAgICAgIGNvbnNvbGUubG9nKHRoaXMubmFtZSArICcgcmFuLicpOwogICAgfQogIAogICAgbGV0IG15Q29udGV4dCA9IHsgbmFtZTogJ3Rocm90dGxlJyB9OwogIAogICAgdGhyb3R0bGUobXlDb250ZXh0LCB3aG9SYW4sIDE1MCk7CiAgICAvLyB3aG9SYW4gaXMgaW52b2tlZCB3aXRoIGNvbnRleHQgbXlDb250ZXh0CiAgICAvLyBjb25zb2xlIGxvZ3MgJ3Rocm90dGxlIHJhbi4nCiAgCiAgICAvLyA1MG1zIHBhc3NlcwogICAgdGhyb3R0bGUobXlDb250ZXh0LCB3aG9SYW4sIDE1MCk7CiAgCiAgICAvLyA1MG1zIHBhc3NlcwogICAgdGhyb3R0bGUobXlDb250ZXh0LCB3aG9SYW4sIDE1MCk7CiAgCiAgICAvLyAxNTBtcyBwYXNzZXMKICAgIHRocm90dGxlKG15Q29udGV4dCwgd2hvUmFuLCAxNTApOwogICAgLy8gd2hvUmFuIGlzIGludm9rZWQgd2l0aCBjb250ZXh0IG15Q29udGV4dAogICAgLy8gY29uc29sZSBsb2dzICd0aHJvdHRsZSByYW4uJwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHRocm90dGxlCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9ydW5sb29wCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gdGFyZ2V0IG9mIG1ldGhvZCB0byBpbnZva2UKICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBtZXRob2QgVGhlIG1ldGhvZCB0byBpbnZva2UuCiAgICAgIE1heSBiZSBhIGZ1bmN0aW9uIG9yIGEgc3RyaW5nLiBJZiB5b3UgcGFzcyBhIHN0cmluZwogICAgICB0aGVuIGl0IHdpbGwgYmUgbG9va2VkIHVwIG9uIHRoZSBwYXNzZWQgdGFyZ2V0LgogICAgQHBhcmFtIHtPYmplY3R9IFthcmdzKl0gT3B0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIHRpbWVvdXQuCiAgICBAcGFyYW0ge051bWJlcn0gc3BhY2luZyBOdW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIHNwYWNlIG91dCByZXF1ZXN0cy4KICAgIEBwYXJhbSB7Qm9vbGVhbn0gaW1tZWRpYXRlIFRyaWdnZXIgdGhlIGZ1bmN0aW9uIG9uIHRoZSBsZWFkaW5nIGluc3RlYWQKICAgICAgb2YgdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHdhaXQgaW50ZXJ2YWwuIERlZmF1bHRzIHRvIHRydWUuCiAgICBAcmV0dXJuIHtBcnJheX0gVGltZXIgaW5mb3JtYXRpb24gZm9yIHVzZSBpbiBjYW5jZWxpbmcsIHNlZSBgY2FuY2VsYC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gdGhyb3R0bGUoKSB7CiAgICByZXR1cm4gYmFja2J1cm5lci50aHJvdHRsZS5hcHBseShiYWNrYnVybmVyLCBhcmd1bWVudHMpOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyL3NlcnZpY2UvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9ydW50aW1lLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmluamVjdCA9IGluamVjdDsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgQG1vZHVsZSBAZW1iZXIvc2VydmljZQogICBAcHVibGljCiAgICovCgogIC8qKgogICAgQ3JlYXRlcyBhIHByb3BlcnR5IHRoYXQgbGF6aWx5IGxvb2tzIHVwIGEgc2VydmljZSBpbiB0aGUgY29udGFpbmVyLiBUaGVyZSBhcmUKICAgIG5vIHJlc3RyaWN0aW9ucyBhcyB0byB3aGF0IG9iamVjdHMgYSBzZXJ2aWNlIGNhbiBiZSBpbmplY3RlZCBpbnRvLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IGNsYXNzIEFwcGxpY2F0aW9uUm91dGUgZXh0ZW5kcyBSb3V0ZSB7CiAgICAgIEBzZXJ2aWNlKCdhdXRoJykgYXV0aE1hbmFnZXI7CiAgCiAgICAgIG1vZGVsKCkgewogICAgICAgIHJldHVybiB0aGlzLmF1dGhNYW5hZ2VyLmZpbmRDdXJyZW50VXNlcigpOwogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgIGF1dGhNYW5hZ2VyOiBzZXJ2aWNlKCdhdXRoJyksCiAgCiAgICAgIG1vZGVsKCkgewogICAgICAgIHJldHVybiB0aGlzLmdldCgnYXV0aE1hbmFnZXInKS5maW5kQ3VycmVudFVzZXIoKTsKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIFRoaXMgZXhhbXBsZSB3aWxsIGNyZWF0ZSBhbiBgYXV0aE1hbmFnZXJgIHByb3BlcnR5IG9uIHRoZSBhcHBsaWNhdGlvbiByb3V0ZQogICAgdGhhdCBsb29rcyB1cCB0aGUgYGF1dGhgIHNlcnZpY2UgaW4gdGhlIGNvbnRhaW5lciwgbWFraW5nIGl0IGVhc2lseSBhY2Nlc3NpYmxlCiAgICBpbiB0aGUgYG1vZGVsYCBob29rLgogIAogICAgQG1ldGhvZCBpbmplY3QKICAgIEBzdGF0aWMKICAgIEBzaW5jZSAxLjEwLjAKICAgIEBmb3IgQGVtYmVyL3NlcnZpY2UKICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIChvcHRpb25hbCkgbmFtZSBvZiB0aGUgc2VydmljZSB0byBpbmplY3QsIGRlZmF1bHRzIHRvCiAgICAgICAgICAgdGhlIHByb3BlcnR5J3MgbmFtZQogICAgQHJldHVybiB7Q29tcHV0ZWREZWNvcmF0b3J9IGluamVjdGlvbiBkZWNvcmF0b3IgaW5zdGFuY2UKICAgIEBwdWJsaWMKICAqLwogIGZ1bmN0aW9uIGluamVjdCgpIHsKICAgIHJldHVybiBfbWV0YWwuaW5qZWN0LmFwcGx5KHZvaWQgMCwgWydzZXJ2aWNlJ10uY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTsKICB9CiAgLyoqCiAgICBAY2xhc3MgU2VydmljZQogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAgIEBzaW5jZSAxLjEwLjAKICAgIEBwdWJsaWMKICAqLwoKCiAgdmFyIFNlcnZpY2UgPSBfcnVudGltZS5GcmFtZXdvcmtPYmplY3QuZXh0ZW5kKCk7CgogIFNlcnZpY2UucmVvcGVuQ2xhc3MoewogICAgaXNTZXJ2aWNlRmFjdG9yeTogdHJ1ZQogIH0pOwoKICBpZiAodHJ1ZQogIC8qIEVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQgKi8KICApIHsKICAgICAgKDAsIF9ydW50aW1lLnNldEZyYW1ld29ya0NsYXNzKShTZXJ2aWNlKTsKICAgIH0KCiAgdmFyIF9kZWZhdWx0ID0gU2VydmljZTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci9zdHJpbmcvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyL3N0cmluZy9saWIvc3RyaW5nX3JlZ2lzdHJ5IiwgIkBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3N0cmluZ19yZWdpc3RyeSwgX2Vudmlyb25tZW50LCBfdXRpbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmxvYyA9IGxvYzsKICBfZXhwb3J0cy53ID0gdzsKICBfZXhwb3J0cy5kZWNhbWVsaXplID0gZGVjYW1lbGl6ZTsKICBfZXhwb3J0cy5kYXNoZXJpemUgPSBkYXNoZXJpemU7CiAgX2V4cG9ydHMuY2FtZWxpemUgPSBjYW1lbGl6ZTsKICBfZXhwb3J0cy5jbGFzc2lmeSA9IGNsYXNzaWZ5OwogIF9leHBvcnRzLnVuZGVyc2NvcmUgPSB1bmRlcnNjb3JlOwogIF9leHBvcnRzLmNhcGl0YWxpemUgPSBjYXBpdGFsaXplOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9nZXRTdHJpbmdzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3N0cmluZ19yZWdpc3RyeS5nZXRTdHJpbmdzOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9zZXRTdHJpbmdzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3N0cmluZ19yZWdpc3RyeS5zZXRTdHJpbmdzOwogICAgfQogIH0pOwoKICAvKioKICBAbW9kdWxlIEBlbWJlci9zdHJpbmcKICAqLwogIHZhciBTVFJJTkdfREFTSEVSSVpFX1JFR0VYUCA9IC9bIF9dL2c7CiAgdmFyIFNUUklOR19EQVNIRVJJWkVfQ0FDSEUgPSBuZXcgX3V0aWxzLkNhY2hlKDEwMDAsIGZ1bmN0aW9uIChrZXkpIHsKICAgIHJldHVybiBkZWNhbWVsaXplKGtleSkucmVwbGFjZShTVFJJTkdfREFTSEVSSVpFX1JFR0VYUCwgJy0nKTsKICB9KTsKICB2YXIgU1RSSU5HX0NBTUVMSVpFX1JFR0VYUF8xID0gLyhcLXxcX3xcLnxccykrKC4pPy9nOwogIHZhciBTVFJJTkdfQ0FNRUxJWkVfUkVHRVhQXzIgPSAvKF58XC8pKFtBLVpdKS9nOwogIHZhciBDQU1FTElaRV9DQUNIRSA9IG5ldyBfdXRpbHMuQ2FjaGUoMTAwMCwgZnVuY3Rpb24gKGtleSkgewogICAgcmV0dXJuIGtleS5yZXBsYWNlKFNUUklOR19DQU1FTElaRV9SRUdFWFBfMSwgZnVuY3Rpb24gKF9tYXRjaCwgX3NlcGFyYXRvciwgY2hyKSB7CiAgICAgIHJldHVybiBjaHIgPyBjaHIudG9VcHBlckNhc2UoKSA6ICcnOwogICAgfSkucmVwbGFjZShTVFJJTkdfQ0FNRUxJWkVfUkVHRVhQXzIsIGZ1bmN0aW9uIChtYXRjaAogICAgLyosIHNlcGFyYXRvciwgY2hyICovCiAgICApIHsKICAgICAgcmV0dXJuIG1hdGNoLnRvTG93ZXJDYXNlKCk7CiAgICB9KTsKICB9KTsKICB2YXIgU1RSSU5HX0NMQVNTSUZZX1JFR0VYUF8xID0gL14oXC18XykrKC4pPy87CiAgdmFyIFNUUklOR19DTEFTU0lGWV9SRUdFWFBfMiA9IC8oLikoXC18XF98XC58XHMpKyguKT8vZzsKICB2YXIgU1RSSU5HX0NMQVNTSUZZX1JFR0VYUF8zID0gLyhefFwvfFwuKShbYS16XSkvZzsKICB2YXIgQ0xBU1NJRllfQ0FDSEUgPSBuZXcgX3V0aWxzLkNhY2hlKDEwMDAsIGZ1bmN0aW9uIChzdHIpIHsKICAgIHZhciByZXBsYWNlMSA9IGZ1bmN0aW9uIHJlcGxhY2UxKF9tYXRjaCwgX3NlcGFyYXRvciwgY2hyKSB7CiAgICAgIHJldHVybiBjaHIgPyAiXyIgKyBjaHIudG9VcHBlckNhc2UoKSA6ICcnOwogICAgfTsKCiAgICB2YXIgcmVwbGFjZTIgPSBmdW5jdGlvbiByZXBsYWNlMihfbWF0Y2gsIGluaXRpYWxDaGFyLCBfc2VwYXJhdG9yLCBjaHIpIHsKICAgICAgcmV0dXJuIGluaXRpYWxDaGFyICsgKGNociA/IGNoci50b1VwcGVyQ2FzZSgpIDogJycpOwogICAgfTsKCiAgICB2YXIgcGFydHMgPSBzdHIuc3BsaXQoJy8nKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHBhcnRzW2ldID0gcGFydHNbaV0ucmVwbGFjZShTVFJJTkdfQ0xBU1NJRllfUkVHRVhQXzEsIHJlcGxhY2UxKS5yZXBsYWNlKFNUUklOR19DTEFTU0lGWV9SRUdFWFBfMiwgcmVwbGFjZTIpOwogICAgfQoKICAgIHJldHVybiBwYXJ0cy5qb2luKCcvJykucmVwbGFjZShTVFJJTkdfQ0xBU1NJRllfUkVHRVhQXzMsIGZ1bmN0aW9uIChtYXRjaAogICAgLyosIHNlcGFyYXRvciwgY2hyICovCiAgICApIHsKICAgICAgcmV0dXJuIG1hdGNoLnRvVXBwZXJDYXNlKCk7CiAgICB9KTsKICB9KTsKICB2YXIgU1RSSU5HX1VOREVSU0NPUkVfUkVHRVhQXzEgPSAvKFthLXpcZF0pKFtBLVpdKykvZzsKICB2YXIgU1RSSU5HX1VOREVSU0NPUkVfUkVHRVhQXzIgPSAvXC18XHMrL2c7CiAgdmFyIFVOREVSU0NPUkVfQ0FDSEUgPSBuZXcgX3V0aWxzLkNhY2hlKDEwMDAsIGZ1bmN0aW9uIChzdHIpIHsKICAgIHJldHVybiBzdHIucmVwbGFjZShTVFJJTkdfVU5ERVJTQ09SRV9SRUdFWFBfMSwgJyQxXyQyJykucmVwbGFjZShTVFJJTkdfVU5ERVJTQ09SRV9SRUdFWFBfMiwgJ18nKS50b0xvd2VyQ2FzZSgpOwogIH0pOwogIHZhciBTVFJJTkdfQ0FQSVRBTElaRV9SRUdFWFAgPSAvKF58XC8pKFthLXpcdTAwQzAtXHUwMjRGXSkvZzsKICB2YXIgQ0FQSVRBTElaRV9DQUNIRSA9IG5ldyBfdXRpbHMuQ2FjaGUoMTAwMCwgZnVuY3Rpb24gKHN0cikgewogICAgcmV0dXJuIHN0ci5yZXBsYWNlKFNUUklOR19DQVBJVEFMSVpFX1JFR0VYUCwgZnVuY3Rpb24gKG1hdGNoCiAgICAvKiwgc2VwYXJhdG9yLCBjaHIgKi8KICAgICkgewogICAgICByZXR1cm4gbWF0Y2gudG9VcHBlckNhc2UoKTsKICAgIH0pOwogIH0pOwogIHZhciBTVFJJTkdfREVDQU1FTElaRV9SRUdFWFAgPSAvKFthLXpcZF0pKFtBLVpdKS9nOwogIHZhciBERUNBTUVMSVpFX0NBQ0hFID0gbmV3IF91dGlscy5DYWNoZSgxMDAwLCBmdW5jdGlvbiAoc3RyKSB7CiAgICByZXR1cm4gc3RyLnJlcGxhY2UoU1RSSU5HX0RFQ0FNRUxJWkVfUkVHRVhQLCAnJDFfJDInKS50b0xvd2VyQ2FzZSgpOwogIH0pOwogIC8qKgogICAgRGVmaW5lcyBzdHJpbmcgaGVscGVyIG1ldGhvZHMgaW5jbHVkaW5nIHN0cmluZyBmb3JtYXR0aW5nIGFuZCBsb2NhbGl6YXRpb24uCiAgICBVbmxlc3MgYEVtYmVyRU5WLkVYVEVORF9QUk9UT1RZUEVTLlN0cmluZ2AgaXMgYGZhbHNlYCB0aGVzZSBtZXRob2RzIHdpbGwgYWxzbyBiZQogICAgYWRkZWQgdG8gdGhlIGBTdHJpbmcucHJvdG90eXBlYCBhcyB3ZWxsLgogIAogICAgQGNsYXNzIFN0cmluZwogICAgQHB1YmxpYwogICovCgogIGZ1bmN0aW9uIF9mbXQoc3RyLCBmb3JtYXRzKSB7CiAgICAvLyBmaXJzdCwgcmVwbGFjZSBhbnkgT1JERVJFRCByZXBsYWNlbWVudHMuCiAgICB2YXIgaWR4ID0gMDsgLy8gdGhlIGN1cnJlbnQgaW5kZXggZm9yIG5vbi1udW1lcmljYWwgcmVwbGFjZW1lbnRzCgogICAgcmV0dXJuIHN0ci5yZXBsYWNlKC8lQChbMC05XSspPy9nLCBmdW5jdGlvbiAoX3MsIGFyZ0luZGV4KSB7CiAgICAgIHZhciBpID0gYXJnSW5kZXggPyBwYXJzZUludChhcmdJbmRleCwgMTApIC0gMSA6IGlkeCsrOwogICAgICB2YXIgciA9IGkgPCBmb3JtYXRzLmxlbmd0aCA/IGZvcm1hdHNbaV0gOiB1bmRlZmluZWQ7CiAgICAgIHJldHVybiB0eXBlb2YgciA9PT0gJ3N0cmluZycgPyByIDogciA9PT0gbnVsbCA/ICcobnVsbCknIDogciA9PT0gdW5kZWZpbmVkID8gJycgOiBTdHJpbmcocik7CiAgICB9KTsKICB9CiAgLyoqCiAgICBGb3JtYXRzIHRoZSBwYXNzZWQgc3RyaW5nLCBidXQgZmlyc3QgbG9va3MgdXAgdGhlIHN0cmluZyBpbiB0aGUgbG9jYWxpemVkCiAgICBzdHJpbmdzIGhhc2guIFRoaXMgaXMgYSBjb252ZW5pZW50IHdheSB0byBsb2NhbGl6ZSB0ZXh0LgogIAogICAgTm90ZSB0aGF0IGl0IGlzIHRyYWRpdGlvbmFsIGJ1dCBub3QgcmVxdWlyZWQgdG8gcHJlZml4IGxvY2FsaXplZCBzdHJpbmcKICAgIGtleXMgd2l0aCBhbiB1bmRlcnNjb3JlIG9yIG90aGVyIGNoYXJhY3RlciBzbyB5b3UgY2FuIGVhc2lseSBpZGVudGlmeQogICAgbG9jYWxpemVkIHN0cmluZ3MuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBsb2MgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAKICAgIEVtYmVyLlNUUklOR1MgPSB7CiAgICAgICdfSGVsbG8gV29ybGQnOiAnQm9uam91ciBsZSBtb25kZScsCiAgICAgICdfSGVsbG8gJUAgJUAnOiAnQm9uam91ciAlQCAlQCcKICAgIH07CiAgCiAgICBsb2MoIl9IZWxsbyBXb3JsZCIpOyAgLy8gJ0JvbmpvdXIgbGUgbW9uZGUnOwogICAgbG9jKCJfSGVsbG8gJUAgJUAiLCBbIkpvaG4iLCAiU21pdGgiXSk7ICAvLyAiQm9uam91ciBKb2huIFNtaXRoIjsKICAgIGBgYAogIAogICAgQG1ldGhvZCBsb2MKICAgIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byBmb3JtYXQKICAgIEBwYXJhbSB7QXJyYXl9IGZvcm1hdHMgT3B0aW9uYWwgYXJyYXkgb2YgcGFyYW1ldGVycyB0byBpbnRlcnBvbGF0ZSBpbnRvIHN0cmluZy4KICAgIEByZXR1cm4ge1N0cmluZ30gZm9ybWF0dGVkIHN0cmluZwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBsb2Moc3RyLCBmb3JtYXRzKSB7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZm9ybWF0cykgfHwgYXJndW1lbnRzLmxlbmd0aCA+IDIpIHsKICAgICAgZm9ybWF0cyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7CiAgICB9CgogICAgc3RyID0gKDAsIF9zdHJpbmdfcmVnaXN0cnkuZ2V0U3RyaW5nKShzdHIpIHx8IHN0cjsKICAgIHJldHVybiBfZm10KHN0ciwgZm9ybWF0cyk7CiAgfQogIC8qKgogICAgU3BsaXRzIGEgc3RyaW5nIGludG8gc2VwYXJhdGUgdW5pdHMgc2VwYXJhdGVkIGJ5IHNwYWNlcywgZWxpbWluYXRpbmcgYW55CiAgICBlbXB0eSBzdHJpbmdzIGluIHRoZSBwcm9jZXNzLiBUaGlzIGlzIGEgY29udmVuaWVuY2UgbWV0aG9kIGZvciBzcGxpdCB0aGF0CiAgICBpcyBtb3N0bHkgdXNlZnVsIHdoZW4gYXBwbGllZCB0byB0aGUgYFN0cmluZy5wcm90b3R5cGVgLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgdyB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogIAogICAgdygiYWxwaGEgYmV0YSBnYW1tYSIpLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7CiAgICAgIGNvbnNvbGUubG9nKGtleSk7CiAgICB9KTsKICAKICAgIC8vID4gYWxwaGEKICAgIC8vID4gYmV0YQogICAgLy8gPiBnYW1tYQogICAgYGBgCiAgCiAgICBAbWV0aG9kIHcKICAgIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byBzcGxpdAogICAgQHJldHVybiB7QXJyYXl9IGFycmF5IGNvbnRhaW5pbmcgdGhlIHNwbGl0IHN0cmluZ3MKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gdyhzdHIpIHsKICAgIHJldHVybiBzdHIuc3BsaXQoL1xzKy8pOwogIH0KICAvKioKICAgIENvbnZlcnRzIGEgY2FtZWxpemVkIHN0cmluZyBpbnRvIGFsbCBsb3dlciBjYXNlIHNlcGFyYXRlZCBieSB1bmRlcnNjb3Jlcy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGRlY2FtZWxpemUgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAKICAgIGRlY2FtZWxpemUoJ2lubmVySFRNTCcpOyAgICAgICAgICAvLyAnaW5uZXJfaHRtbCcKICAgIGRlY2FtZWxpemUoJ2FjdGlvbl9uYW1lJyk7ICAgICAgICAvLyAnYWN0aW9uX25hbWUnCiAgICBkZWNhbWVsaXplKCdjc3MtY2xhc3MtbmFtZScpOyAgICAgLy8gJ2Nzcy1jbGFzcy1uYW1lJwogICAgZGVjYW1lbGl6ZSgnbXkgZmF2b3JpdGUgaXRlbXMnKTsgIC8vICdteSBmYXZvcml0ZSBpdGVtcycKICAgIGBgYAogIAogICAgQG1ldGhvZCBkZWNhbWVsaXplCiAgICBAcGFyYW0ge1N0cmluZ30gc3RyIFRoZSBzdHJpbmcgdG8gZGVjYW1lbGl6ZS4KICAgIEByZXR1cm4ge1N0cmluZ30gdGhlIGRlY2FtZWxpemVkIHN0cmluZy4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZGVjYW1lbGl6ZShzdHIpIHsKICAgIHJldHVybiBERUNBTUVMSVpFX0NBQ0hFLmdldChzdHIpOwogIH0KICAvKioKICAgIFJlcGxhY2VzIHVuZGVyc2NvcmVzLCBzcGFjZXMsIG9yIGNhbWVsQ2FzZSB3aXRoIGRhc2hlcy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGRhc2hlcml6ZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogIAogICAgZGFzaGVyaXplKCdpbm5lckhUTUwnKTsgICAgICAgICAgICAgICAgLy8gJ2lubmVyLWh0bWwnCiAgICBkYXNoZXJpemUoJ2FjdGlvbl9uYW1lJyk7ICAgICAgICAgICAgICAvLyAnYWN0aW9uLW5hbWUnCiAgICBkYXNoZXJpemUoJ2Nzcy1jbGFzcy1uYW1lJyk7ICAgICAgICAgICAvLyAnY3NzLWNsYXNzLW5hbWUnCiAgICBkYXNoZXJpemUoJ215IGZhdm9yaXRlIGl0ZW1zJyk7ICAgICAgICAvLyAnbXktZmF2b3JpdGUtaXRlbXMnCiAgICBkYXNoZXJpemUoJ3ByaXZhdGVEb2NzL293bmVySW52b2ljZSc7ICAvLyAncHJpdmF0ZS1kb2NzL293bmVyLWludm9pY2UnCiAgICBgYGAKICAKICAgIEBtZXRob2QgZGFzaGVyaXplCiAgICBAcGFyYW0ge1N0cmluZ30gc3RyIFRoZSBzdHJpbmcgdG8gZGFzaGVyaXplLgogICAgQHJldHVybiB7U3RyaW5nfSB0aGUgZGFzaGVyaXplZCBzdHJpbmcuCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGRhc2hlcml6ZShzdHIpIHsKICAgIHJldHVybiBTVFJJTkdfREFTSEVSSVpFX0NBQ0hFLmdldChzdHIpOwogIH0KICAvKioKICAgIFJldHVybnMgdGhlIGxvd2VyQ2FtZWxDYXNlIGZvcm0gb2YgYSBzdHJpbmcuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBjYW1lbGl6ZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogIAogICAgY2FtZWxpemUoJ2lubmVySFRNTCcpOyAgICAgICAgICAgICAgICAgICAvLyAnaW5uZXJIVE1MJwogICAgY2FtZWxpemUoJ2FjdGlvbl9uYW1lJyk7ICAgICAgICAgICAgICAgICAvLyAnYWN0aW9uTmFtZScKICAgIGNhbWVsaXplKCdjc3MtY2xhc3MtbmFtZScpOyAgICAgICAgICAgICAgLy8gJ2Nzc0NsYXNzTmFtZScKICAgIGNhbWVsaXplKCdteSBmYXZvcml0ZSBpdGVtcycpOyAgICAgICAgICAgLy8gJ215RmF2b3JpdGVJdGVtcycKICAgIGNhbWVsaXplKCdNeSBGYXZvcml0ZSBJdGVtcycpOyAgICAgICAgICAgLy8gJ215RmF2b3JpdGVJdGVtcycKICAgIGNhbWVsaXplKCdwcml2YXRlLWRvY3Mvb3duZXItaW52b2ljZScpOyAgLy8gJ3ByaXZhdGVEb2NzL293bmVySW52b2ljZScKICAgIGBgYAogIAogICAgQG1ldGhvZCBjYW1lbGl6ZQogICAgQHBhcmFtIHtTdHJpbmd9IHN0ciBUaGUgc3RyaW5nIHRvIGNhbWVsaXplLgogICAgQHJldHVybiB7U3RyaW5nfSB0aGUgY2FtZWxpemVkIHN0cmluZy4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gY2FtZWxpemUoc3RyKSB7CiAgICByZXR1cm4gQ0FNRUxJWkVfQ0FDSEUuZ2V0KHN0cik7CiAgfQogIC8qKgogICAgUmV0dXJucyB0aGUgVXBwZXJDYW1lbENhc2UgZm9ybSBvZiBhIHN0cmluZy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGNsYXNzaWZ5IH0gZnJvbSAnQGVtYmVyL3N0cmluZyc7CiAgCiAgICBjbGFzc2lmeSgnaW5uZXJIVE1MJyk7ICAgICAgICAgICAgICAgICAgIC8vICdJbm5lckhUTUwnCiAgICBjbGFzc2lmeSgnYWN0aW9uX25hbWUnKTsgICAgICAgICAgICAgICAgIC8vICdBY3Rpb25OYW1lJwogICAgY2xhc3NpZnkoJ2Nzcy1jbGFzcy1uYW1lJyk7ICAgICAgICAgICAgICAvLyAnQ3NzQ2xhc3NOYW1lJwogICAgY2xhc3NpZnkoJ215IGZhdm9yaXRlIGl0ZW1zJyk7ICAgICAgICAgICAvLyAnTXlGYXZvcml0ZUl0ZW1zJwogICAgY2xhc3NpZnkoJ3ByaXZhdGUtZG9jcy9vd25lci1pbnZvaWNlJyk7ICAvLyAnUHJpdmF0ZURvY3MvT3duZXJJbnZvaWNlJwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGNsYXNzaWZ5CiAgICBAcGFyYW0ge1N0cmluZ30gc3RyIHRoZSBzdHJpbmcgdG8gY2xhc3NpZnkKICAgIEByZXR1cm4ge1N0cmluZ30gdGhlIGNsYXNzaWZpZWQgc3RyaW5nCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGNsYXNzaWZ5KHN0cikgewogICAgcmV0dXJuIENMQVNTSUZZX0NBQ0hFLmdldChzdHIpOwogIH0KICAvKioKICAgIE1vcmUgZ2VuZXJhbCB0aGFuIGRlY2FtZWxpemUuIFJldHVybnMgdGhlIGxvd2VyXF9jYXNlXF9hbmRcX3VuZGVyc2NvcmVkCiAgICBmb3JtIG9mIGEgc3RyaW5nLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgdW5kZXJzY29yZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogIAogICAgdW5kZXJzY29yZSgnaW5uZXJIVE1MJyk7ICAgICAgICAgICAgICAgICAvLyAnaW5uZXJfaHRtbCcKICAgIHVuZGVyc2NvcmUoJ2FjdGlvbl9uYW1lJyk7ICAgICAgICAgICAgICAgLy8gJ2FjdGlvbl9uYW1lJwogICAgdW5kZXJzY29yZSgnY3NzLWNsYXNzLW5hbWUnKTsgICAgICAgICAgICAvLyAnY3NzX2NsYXNzX25hbWUnCiAgICB1bmRlcnNjb3JlKCdteSBmYXZvcml0ZSBpdGVtcycpOyAgICAgICAgIC8vICdteV9mYXZvcml0ZV9pdGVtcycKICAgIHVuZGVyc2NvcmUoJ3ByaXZhdGVEb2NzL293bmVySW52b2ljZScpOyAgLy8gJ3ByaXZhdGVfZG9jcy9vd25lcl9pbnZvaWNlJwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHVuZGVyc2NvcmUKICAgIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byB1bmRlcnNjb3JlLgogICAgQHJldHVybiB7U3RyaW5nfSB0aGUgdW5kZXJzY29yZWQgc3RyaW5nLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiB1bmRlcnNjb3JlKHN0cikgewogICAgcmV0dXJuIFVOREVSU0NPUkVfQ0FDSEUuZ2V0KHN0cik7CiAgfQogIC8qKgogICAgUmV0dXJucyB0aGUgQ2FwaXRhbGl6ZWQgZm9ybSBvZiBhIHN0cmluZwogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgY2FwaXRhbGl6ZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogIAogICAgY2FwaXRhbGl6ZSgnaW5uZXJIVE1MJykgICAgICAgICAgICAgICAgIC8vICdJbm5lckhUTUwnCiAgICBjYXBpdGFsaXplKCdhY3Rpb25fbmFtZScpICAgICAgICAgICAgICAgLy8gJ0FjdGlvbl9uYW1lJwogICAgY2FwaXRhbGl6ZSgnY3NzLWNsYXNzLW5hbWUnKSAgICAgICAgICAgIC8vICdDc3MtY2xhc3MtbmFtZScKICAgIGNhcGl0YWxpemUoJ215IGZhdm9yaXRlIGl0ZW1zJykgICAgICAgICAvLyAnTXkgZmF2b3JpdGUgaXRlbXMnCiAgICBjYXBpdGFsaXplKCdwcml2YXRlRG9jcy9vd25lckludm9pY2UnKTsgLy8gJ1ByaXZhdGVEb2NzL293bmVySW52b2ljZScKICAgIGBgYAogIAogICAgQG1ldGhvZCBjYXBpdGFsaXplCiAgICBAcGFyYW0ge1N0cmluZ30gc3RyIFRoZSBzdHJpbmcgdG8gY2FwaXRhbGl6ZS4KICAgIEByZXR1cm4ge1N0cmluZ30gVGhlIGNhcGl0YWxpemVkIHN0cmluZy4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHIpIHsKICAgIHJldHVybiBDQVBJVEFMSVpFX0NBQ0hFLmdldChzdHIpOwogIH0KCiAgaWYgKF9lbnZpcm9ubWVudC5FTlYuRVhURU5EX1BST1RPVFlQRVMuU3RyaW5nKSB7CiAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhTdHJpbmcucHJvdG90eXBlLCB7CiAgICAgIC8qKgogICAgICAgIFNlZSBbU3RyaW5nLnddKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvU3RyaW5nL21ldGhvZHMvdz9hbmNob3I9dykuCiAgICAgICAgICAgICBAbWV0aG9kIHcKICAgICAgICBAZm9yIEBlbWJlci9zdHJpbmcKICAgICAgICBAc3RhdGljCiAgICAgICAgQHByaXZhdGUKICAgICAgKi8KICAgICAgdzogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0ZWFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgcmV0dXJuIHcodGhpcyk7CiAgICAgICAgfQogICAgICB9LAoKICAgICAgLyoqCiAgICAgICAgU2VlIFtTdHJpbmcubG9jXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1N0cmluZy9tZXRob2RzL2xvYz9hbmNob3I9bG9jKS4KICAgICAgICAgICAgIEBtZXRob2QgbG9jCiAgICAgICAgQGZvciBAZW1iZXIvc3RyaW5nCiAgICAgICAgQHN0YXRpYwogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIGxvYzogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0ZWFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIGxvYyh0aGlzLCBhcmdzKTsKICAgICAgICB9CiAgICAgIH0sCgogICAgICAvKioKICAgICAgICBTZWUgW1N0cmluZy5jYW1lbGl6ZV0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9TdHJpbmcvbWV0aG9kcy9jYW1lbGl6ZT9hbmNob3I9Y2FtZWxpemUpLgogICAgICAgICAgICAgQG1ldGhvZCBjYW1lbGl6ZQogICAgICAgIEBmb3IgQGVtYmVyL3N0cmluZwogICAgICAgIEBzdGF0aWMKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBjYW1lbGl6ZTogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0ZWFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgcmV0dXJuIGNhbWVsaXplKHRoaXMpOwogICAgICAgIH0KICAgICAgfSwKCiAgICAgIC8qKgogICAgICAgIFNlZSBbU3RyaW5nLmRlY2FtZWxpemVdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvU3RyaW5nL21ldGhvZHMvZGVjYW1lbGl6ZT9hbmNob3I9ZGVjYW1lbGl6ZSkuCiAgICAgICAgICAgICBAbWV0aG9kIGRlY2FtZWxpemUKICAgICAgICBAZm9yIEBlbWJlci9zdHJpbmcKICAgICAgICBAc3RhdGljCiAgICAgICAgQHByaXZhdGUKICAgICAgKi8KICAgICAgZGVjYW1lbGl6ZTogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0ZWFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgcmV0dXJuIGRlY2FtZWxpemUodGhpcyk7CiAgICAgICAgfQogICAgICB9LAoKICAgICAgLyoqCiAgICAgICAgU2VlIFtTdHJpbmcuZGFzaGVyaXplXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1N0cmluZy9tZXRob2RzL2Rhc2hlcml6ZT9hbmNob3I9ZGFzaGVyaXplKS4KICAgICAgICAgICAgIEBtZXRob2QgZGFzaGVyaXplCiAgICAgICAgQGZvciBAZW1iZXIvc3RyaW5nCiAgICAgICAgQHN0YXRpYwogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIGRhc2hlcml6ZTogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0ZWFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgcmV0dXJuIGRhc2hlcml6ZSh0aGlzKTsKICAgICAgICB9CiAgICAgIH0sCgogICAgICAvKioKICAgICAgICBTZWUgW1N0cmluZy51bmRlcnNjb3JlXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1N0cmluZy9tZXRob2RzL3VuZGVyc2NvcmU/YW5jaG9yPXVuZGVyc2NvcmUpLgogICAgICAgICAgICAgQG1ldGhvZCB1bmRlcnNjb3JlCiAgICAgICAgQGZvciBAZW1iZXIvc3RyaW5nCiAgICAgICAgQHN0YXRpYwogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIHVuZGVyc2NvcmU6IHsKICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsCiAgICAgICAgd3JpdGVhYmxlOiB0cnVlLAogICAgICAgIHZhbHVlOiBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgICAgIHJldHVybiB1bmRlcnNjb3JlKHRoaXMpOwogICAgICAgIH0KICAgICAgfSwKCiAgICAgIC8qKgogICAgICAgIFNlZSBbU3RyaW5nLmNsYXNzaWZ5XSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1N0cmluZy9tZXRob2RzL2NsYXNzaWZ5P2FuY2hvcj1jbGFzc2lmeSkuCiAgICAgICAgICAgICBAbWV0aG9kIGNsYXNzaWZ5CiAgICAgICAgQGZvciBAZW1iZXIvc3RyaW5nCiAgICAgICAgQHN0YXRpYwogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIGNsYXNzaWZ5OiB7CiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgIGVudW1lcmFibGU6IGZhbHNlLAogICAgICAgIHdyaXRlYWJsZTogdHJ1ZSwKICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgICAgICByZXR1cm4gY2xhc3NpZnkodGhpcyk7CiAgICAgICAgfQogICAgICB9LAoKICAgICAgLyoqCiAgICAgICAgU2VlIFtTdHJpbmcuY2FwaXRhbGl6ZV0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9TdHJpbmcvbWV0aG9kcy9jYXBpdGFsaXplP2FuY2hvcj1jYXBpdGFsaXplKS4KICAgICAgICAgICAgIEBtZXRob2QgY2FwaXRhbGl6ZQogICAgICAgIEBmb3IgQGVtYmVyL3N0cmluZwogICAgICAgIEBzdGF0aWMKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBjYXBpdGFsaXplOiB7CiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgIGVudW1lcmFibGU6IGZhbHNlLAogICAgICAgIHdyaXRlYWJsZTogdHJ1ZSwKICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgICAgICByZXR1cm4gY2FwaXRhbGl6ZSh0aGlzKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0pOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyL3N0cmluZy9saWIvc3RyaW5nX3JlZ2lzdHJ5IiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuc2V0U3RyaW5ncyA9IHNldFN0cmluZ3M7CiAgX2V4cG9ydHMuZ2V0U3RyaW5ncyA9IGdldFN0cmluZ3M7CiAgX2V4cG9ydHMuZ2V0U3RyaW5nID0gZ2V0U3RyaW5nOwogIC8vIFNUQVRFIHdpdGhpbiBhIG1vZHVsZSBpcyBmcm93bmVkIHVwb24sIHRoaXMgZXhpc3RzCiAgLy8gdG8gc3VwcG9ydCBFbWJlci5TVFJJTkdTIGJ1dCBzaGllbGQgZW1iZXIgaW50ZXJuYWxzIGZyb20gdGhpcyBsZWdhY3kgZ2xvYmFsCiAgLy8gQVBJLgogIHZhciBTVFJJTkdTID0ge307CgogIGZ1bmN0aW9uIHNldFN0cmluZ3Moc3RyaW5ncykgewogICAgU1RSSU5HUyA9IHN0cmluZ3M7CiAgfQoKICBmdW5jdGlvbiBnZXRTdHJpbmdzKCkgewogICAgcmV0dXJuIFNUUklOR1M7CiAgfQoKICBmdW5jdGlvbiBnZXRTdHJpbmcobmFtZSkgewogICAgcmV0dXJuIFNUUklOR1NbbmFtZV07CiAgfQp9KTsKZGVmaW5lKCJAZ2xpbW1lci9lbmNvZGVyIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuSW5zdHJ1Y3Rpb25FbmNvZGVyID0gdm9pZCAwOwoKICB2YXIgSW5zdHJ1Y3Rpb25FbmNvZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSW5zdHJ1Y3Rpb25FbmNvZGVyKGJ1ZmZlcikgewogICAgICB0aGlzLmJ1ZmZlciA9IGJ1ZmZlcjsKICAgICAgdGhpcy50eXBlUG9zID0gMDsKICAgICAgdGhpcy5zaXplID0gMDsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gSW5zdHJ1Y3Rpb25FbmNvZGVyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKHR5cGUsIG1hY2hpbmUpIHsKICAgICAgaWYgKHR5cGUgPiAyNTUKICAgICAgLyogVFlQRV9TSVpFICovCiAgICAgICkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJPcGNvZGUgdHlwZSBvdmVyIDgtYml0cy4gR290ICIgKyB0eXBlICsgIi4iKTsKICAgICAgICB9CgogICAgICB0aGlzLmJ1ZmZlci5wdXNoKHR5cGUgfCBtYWNoaW5lIHwgYXJndW1lbnRzLmxlbmd0aCAtIDIgPDwgOAogICAgICAvKiBBUkdfU0hJRlQgKi8KICAgICAgKTsKICAgICAgdGhpcy50eXBlUG9zID0gdGhpcy5idWZmZXIubGVuZ3RoIC0gMTsKCiAgICAgIGZvciAodmFyIGkgPSAyOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIG9wID0gYXJndW1lbnRzW2ldOwoKICAgICAgICBpZiAodHlwZW9mIG9wID09PSAnbnVtYmVyJyAmJiBvcCA+IDQyOTQ5NjcyOTUKICAgICAgICAvKiBNQVhfU0laRSAqLwogICAgICAgICkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIk9wZXJhbmQgb3ZlciAzMi1iaXRzLiBHb3QgIiArIG9wICsgIi4iKTsKICAgICAgICAgIH0KCiAgICAgICAgdGhpcy5idWZmZXIucHVzaChvcCk7CiAgICAgIH0KCiAgICAgIHRoaXMuc2l6ZSA9IHRoaXMuYnVmZmVyLmxlbmd0aDsKICAgIH07CgogICAgX3Byb3RvLnBhdGNoID0gZnVuY3Rpb24gcGF0Y2gocG9zaXRpb24sIHRhcmdldCkgewogICAgICBpZiAodGhpcy5idWZmZXJbcG9zaXRpb24gKyAxXSA9PT0gLTEpIHsKICAgICAgICB0aGlzLmJ1ZmZlcltwb3NpdGlvbiArIDFdID0gdGFyZ2V0OwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcignVHJ5aW5nIHRvIHBhdGNoIG9wZXJhbmQgaW4gcG9wdWxhdGVkIHNsb3QgaW5zdGVhZCBvZiBhIHJlc2VydmVkIHNsb3QuJyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnBhdGNoV2l0aCA9IGZ1bmN0aW9uIHBhdGNoV2l0aChwb3NpdGlvbiwgdGFyZ2V0LCBvcGVyYW5kKSB7CiAgICAgIGlmICh0aGlzLmJ1ZmZlcltwb3NpdGlvbiArIDFdID09PSAtMSkgewogICAgICAgIHRoaXMuYnVmZmVyW3Bvc2l0aW9uICsgMV0gPSB0YXJnZXQ7CiAgICAgICAgdGhpcy5idWZmZXJbcG9zaXRpb24gKyAyXSA9IG9wZXJhbmQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUcnlpbmcgdG8gcGF0Y2ggb3BlcmFuZCBpbiBwb3B1bGF0ZWQgc2xvdCBpbnN0ZWFkIG9mIGEgcmVzZXJ2ZWQgc2xvdC4nKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gSW5zdHJ1Y3Rpb25FbmNvZGVyOwogIH0oKTsKCiAgX2V4cG9ydHMuSW5zdHJ1Y3Rpb25FbmNvZGVyID0gSW5zdHJ1Y3Rpb25FbmNvZGVyOwp9KTsKZGVmaW5lKCJAZ2xpbW1lci9sb3ctbGV2ZWwiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5TdGFjayA9IF9leHBvcnRzLlN0b3JhZ2UgPSB2b2lkIDA7CgogIHZhciBTdG9yYWdlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gU3RvcmFnZSgpIHsKICAgICAgdGhpcy5hcnJheSA9IFtdOwogICAgICB0aGlzLm5leHQgPSAwOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBTdG9yYWdlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uYWRkID0gZnVuY3Rpb24gYWRkKGVsZW1lbnQpIHsKICAgICAgdmFyIHNsb3QgPSB0aGlzLm5leHQsCiAgICAgICAgICBhcnJheSA9IHRoaXMuYXJyYXk7CgogICAgICBpZiAoc2xvdCA9PT0gYXJyYXkubGVuZ3RoKSB7CiAgICAgICAgdGhpcy5uZXh0Kys7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIHByZXYgPSBhcnJheVtzbG90XTsKICAgICAgICB0aGlzLm5leHQgPSBwcmV2OwogICAgICB9CgogICAgICB0aGlzLmFycmF5W3Nsb3RdID0gZWxlbWVudDsKICAgICAgcmV0dXJuIHNsb3Q7CiAgICB9OwoKICAgIF9wcm90by5kZXJlZiA9IGZ1bmN0aW9uIGRlcmVmKHBvaW50ZXIpIHsKICAgICAgcmV0dXJuIHRoaXMuYXJyYXlbcG9pbnRlcl07CiAgICB9OwoKICAgIF9wcm90by5kcm9wID0gZnVuY3Rpb24gZHJvcChwb2ludGVyKSB7CiAgICAgIHRoaXMuYXJyYXlbcG9pbnRlcl0gPSB0aGlzLm5leHQ7CiAgICAgIHRoaXMubmV4dCA9IHBvaW50ZXI7CiAgICB9OwoKICAgIHJldHVybiBTdG9yYWdlOwogIH0oKTsKCiAgX2V4cG9ydHMuU3RvcmFnZSA9IFN0b3JhZ2U7CgogIHZhciBTdGFjayA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFN0YWNrKHZlYykgewogICAgICBpZiAodmVjID09PSB2b2lkIDApIHsKICAgICAgICB2ZWMgPSBbXTsKICAgICAgfQoKICAgICAgdGhpcy52ZWMgPSB2ZWM7CiAgICB9CgogICAgdmFyIF9wcm90bzIgPSBTdGFjay5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5jbG9uZSA9IGZ1bmN0aW9uIGNsb25lKCkgewogICAgICByZXR1cm4gbmV3IFN0YWNrKHRoaXMudmVjLnNsaWNlKCkpOwogICAgfTsKCiAgICBfcHJvdG8yLnNsaWNlRnJvbSA9IGZ1bmN0aW9uIHNsaWNlRnJvbShzdGFydCkgewogICAgICByZXR1cm4gbmV3IFN0YWNrKHRoaXMudmVjLnNsaWNlKHN0YXJ0KSk7CiAgICB9OwoKICAgIF9wcm90bzIuc2xpY2UgPSBmdW5jdGlvbiBzbGljZShzdGFydCwgZW5kKSB7CiAgICAgIHJldHVybiBuZXcgU3RhY2sodGhpcy52ZWMuc2xpY2Uoc3RhcnQsIGVuZCkpOwogICAgfTsKCiAgICBfcHJvdG8yLmNvcHkgPSBmdW5jdGlvbiBjb3B5KGZyb20sIHRvKSB7CiAgICAgIHRoaXMudmVjW3RvXSA9IHRoaXMudmVjW2Zyb21dOwogICAgfSAvLyBUT0RPOiBob3cgdG8gbW9kZWwgdTY0IGFyZ3VtZW50PwogICAgOwoKICAgIF9wcm90bzIud3JpdGVSYXcgPSBmdW5jdGlvbiB3cml0ZVJhdyhwb3MsIHZhbHVlKSB7CiAgICAgIC8vIFRPRE86IEdyb3c/CiAgICAgIHRoaXMudmVjW3Bvc10gPSB2YWx1ZTsKICAgIH0gLy8gVE9ETzogcGFydGlhbGx5IGRlY29kZWQgZW51bT8KICAgIDsKCiAgICBfcHJvdG8yLmdldFJhdyA9IGZ1bmN0aW9uIGdldFJhdyhwb3MpIHsKICAgICAgcmV0dXJuIHRoaXMudmVjW3Bvc107CiAgICB9OwoKICAgIF9wcm90bzIucmVzZXQgPSBmdW5jdGlvbiByZXNldCgpIHsKICAgICAgdGhpcy52ZWMubGVuZ3RoID0gMDsKICAgIH07CgogICAgX3Byb3RvMi5sZW4gPSBmdW5jdGlvbiBsZW4oKSB7CiAgICAgIHJldHVybiB0aGlzLnZlYy5sZW5ndGg7CiAgICB9OwoKICAgIHJldHVybiBTdGFjazsKICB9KCk7CgogIF9leHBvcnRzLlN0YWNrID0gU3RhY2s7Cn0pOwpkZWZpbmUoIkBnbGltbWVyL25vZGUiLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiLCAiQGdsaW1tZXIvcnVudGltZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfcnVudGltZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuc2VyaWFsaXplQnVpbGRlciA9IHNlcmlhbGl6ZUJ1aWxkZXI7CiAgX2V4cG9ydHMuTm9kZURPTVRyZWVDb25zdHJ1Y3Rpb24gPSB2b2lkIDA7CgogIHZhciBOb2RlRE9NVHJlZUNvbnN0cnVjdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRE9NVHJlZUNvbnN0cnVjdGlvbikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE5vZGVET01UcmVlQ29uc3RydWN0aW9uLCBfRE9NVHJlZUNvbnN0cnVjdGlvbik7CgogICAgZnVuY3Rpb24gTm9kZURPTVRyZWVDb25zdHJ1Y3Rpb24oZG9jKSB7CiAgICAgIHJldHVybiBfRE9NVHJlZUNvbnN0cnVjdGlvbi5jYWxsKHRoaXMsIGRvYykgfHwgdGhpczsKICAgIH0gLy8gb3ZlcnJpZGUgdG8gcHJldmVudCB1c2FnZSBvZiBgdGhpcy5kb2N1bWVudGAgdW50aWwgYWZ0ZXIgdGhlIGNvbnN0cnVjdG9yCgoKICAgIHZhciBfcHJvdG8gPSBOb2RlRE9NVHJlZUNvbnN0cnVjdGlvbi5wcm90b3R5cGU7CgogICAgX3Byb3RvLnNldHVwVXNlbGVzc0VsZW1lbnQgPSBmdW5jdGlvbiBzZXR1cFVzZWxlc3NFbGVtZW50KCkge30gLy8gb3ZlcnJpZGUgdG8gYXZvaWQgU1ZHIGRldGVjdGlvbi93b3JrIHdoZW4gaW4gbm9kZSAodGhpcyBpcyBub3QgbmVlZGVkIGluIFNTUikKICAgIDsKCiAgICBfcHJvdG8uY3JlYXRlRWxlbWVudCA9IGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodGFnKSB7CiAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTsKICAgIH0gLy8gb3ZlcnJpZGUgdG8gYXZvaWQgbmFtZXNwYWNlIHNoZW5hbmlnYW5zIHdoZW4gaW4gbm9kZSAodGhpcyBpcyBub3QgbmVlZGVkIGluIFNTUikKICAgIDsKCiAgICBfcHJvdG8uc2V0QXR0cmlidXRlID0gZnVuY3Rpb24gc2V0QXR0cmlidXRlKGVsZW1lbnQsIG5hbWUsIHZhbHVlKSB7CiAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlKTsKICAgIH07CgogICAgcmV0dXJuIE5vZGVET01UcmVlQ29uc3RydWN0aW9uOwogIH0oX3J1bnRpbWUuRE9NVHJlZUNvbnN0cnVjdGlvbik7CgogIF9leHBvcnRzLk5vZGVET01UcmVlQ29uc3RydWN0aW9uID0gTm9kZURPTVRyZWVDb25zdHJ1Y3Rpb247CiAgdmFyIFRFWFRfTk9ERSA9IDM7CgogIGZ1bmN0aW9uIGN1cnJlbnROb2RlKGN1cnNvcikgewogICAgdmFyIGVsZW1lbnQgPSBjdXJzb3IuZWxlbWVudCwKICAgICAgICBuZXh0U2libGluZyA9IGN1cnNvci5uZXh0U2libGluZzsKCiAgICBpZiAobmV4dFNpYmxpbmcgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIGVsZW1lbnQubGFzdENoaWxkOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG5leHRTaWJsaW5nLnByZXZpb3VzU2libGluZzsKICAgIH0KICB9CgogIHZhciBTZXJpYWxpemVCdWlsZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9OZXdFbGVtZW50QnVpbGRlcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFNlcmlhbGl6ZUJ1aWxkZXIsIF9OZXdFbGVtZW50QnVpbGRlcik7CgogICAgZnVuY3Rpb24gU2VyaWFsaXplQnVpbGRlcigpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfTmV3RWxlbWVudEJ1aWxkZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpcy5zZXJpYWxpemVCbG9ja0RlcHRoID0gMDsKICAgICAgcmV0dXJuIF90aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8yID0gU2VyaWFsaXplQnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5fX29wZW5CbG9jayA9IGZ1bmN0aW9uIF9fb3BlbkJsb2NrKCkgewogICAgICB2YXIgdGFnTmFtZSA9IHRoaXMuZWxlbWVudC50YWdOYW1lOwoKICAgICAgaWYgKHRhZ05hbWUgIT09ICdUSVRMRScgJiYgdGFnTmFtZSAhPT0gJ1NDUklQVCcgJiYgdGFnTmFtZSAhPT0gJ1NUWUxFJykgewogICAgICAgIHZhciBkZXB0aCA9IHRoaXMuc2VyaWFsaXplQmxvY2tEZXB0aCsrOwoKICAgICAgICB0aGlzLl9fYXBwZW5kQ29tbWVudCgiJStiOiIgKyBkZXB0aCArICIlIik7CiAgICAgIH0KCiAgICAgIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuX19vcGVuQmxvY2suY2FsbCh0aGlzKTsKICAgIH07CgogICAgX3Byb3RvMi5fX2Nsb3NlQmxvY2sgPSBmdW5jdGlvbiBfX2Nsb3NlQmxvY2soKSB7CiAgICAgIHZhciB0YWdOYW1lID0gdGhpcy5lbGVtZW50LnRhZ05hbWU7CgogICAgICBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fY2xvc2VCbG9jay5jYWxsKHRoaXMpOwoKICAgICAgaWYgKHRhZ05hbWUgIT09ICdUSVRMRScgJiYgdGFnTmFtZSAhPT0gJ1NDUklQVCcgJiYgdGFnTmFtZSAhPT0gJ1NUWUxFJykgewogICAgICAgIHZhciBkZXB0aCA9IC0tdGhpcy5zZXJpYWxpemVCbG9ja0RlcHRoOwoKICAgICAgICB0aGlzLl9fYXBwZW5kQ29tbWVudCgiJS1iOiIgKyBkZXB0aCArICIlIik7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMi5fX2FwcGVuZEhUTUwgPSBmdW5jdGlvbiBfX2FwcGVuZEhUTUwoaHRtbCkgewogICAgICB2YXIgdGFnTmFtZSA9IHRoaXMuZWxlbWVudC50YWdOYW1lOwoKICAgICAgaWYgKHRhZ05hbWUgPT09ICdUSVRMRScgfHwgdGFnTmFtZSA9PT0gJ1NDUklQVCcgfHwgdGFnTmFtZSA9PT0gJ1NUWUxFJykgewogICAgICAgIHJldHVybiBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fYXBwZW5kSFRNTC5jYWxsKHRoaXMsIGh0bWwpOwogICAgICB9IC8vIERvIHdlIG5lZWQgdG8gcnVuIHRoZSBodG1sIHRva2VuaXplciBoZXJlPwoKCiAgICAgIHZhciBmaXJzdCA9IHRoaXMuX19hcHBlbmRDb21tZW50KCclZ2xtciUnKTsKCiAgICAgIGlmICh0YWdOYW1lID09PSAnVEFCTEUnKSB7CiAgICAgICAgdmFyIG9wZW5JbmRleCA9IGh0bWwuaW5kZXhPZignPCcpOwoKICAgICAgICBpZiAob3BlbkluZGV4ID4gLTEpIHsKICAgICAgICAgIHZhciB0ciA9IGh0bWwuc2xpY2Uob3BlbkluZGV4ICsgMSwgb3BlbkluZGV4ICsgMyk7CgogICAgICAgICAgaWYgKHRyID09PSAndHInKSB7CiAgICAgICAgICAgIGh0bWwgPSAiPHRib2R5PiIgKyBodG1sICsgIjwvdGJvZHk+IjsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChodG1sID09PSAnJykgewogICAgICAgIHRoaXMuX19hcHBlbmRDb21tZW50KCclICUnKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fYXBwZW5kSFRNTC5jYWxsKHRoaXMsIGh0bWwpOwogICAgICB9CgogICAgICB2YXIgbGFzdCA9IHRoaXMuX19hcHBlbmRDb21tZW50KCclZ2xtciUnKTsKCiAgICAgIHJldHVybiBuZXcgX3J1bnRpbWUuQ29uY3JldGVCb3VuZHModGhpcy5lbGVtZW50LCBmaXJzdCwgbGFzdCk7CiAgICB9OwoKICAgIF9wcm90bzIuX19hcHBlbmRUZXh0ID0gZnVuY3Rpb24gX19hcHBlbmRUZXh0KHN0cmluZykgewogICAgICB2YXIgdGFnTmFtZSA9IHRoaXMuZWxlbWVudC50YWdOYW1lOwogICAgICB2YXIgY3VycmVudCA9IGN1cnJlbnROb2RlKHRoaXMpOwoKICAgICAgaWYgKHRhZ05hbWUgPT09ICdUSVRMRScgfHwgdGFnTmFtZSA9PT0gJ1NDUklQVCcgfHwgdGFnTmFtZSA9PT0gJ1NUWUxFJykgewogICAgICAgIHJldHVybiBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fYXBwZW5kVGV4dC5jYWxsKHRoaXMsIHN0cmluZyk7CiAgICAgIH0gZWxzZSBpZiAoc3RyaW5nID09PSAnJykgewogICAgICAgIHJldHVybiB0aGlzLl9fYXBwZW5kQ29tbWVudCgnJSAlJyk7CiAgICAgIH0gZWxzZSBpZiAoY3VycmVudCAmJiBjdXJyZW50Lm5vZGVUeXBlID09PSBURVhUX05PREUpIHsKICAgICAgICB0aGlzLl9fYXBwZW5kQ29tbWVudCgnJXwlJyk7CiAgICAgIH0KCiAgICAgIHJldHVybiBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fYXBwZW5kVGV4dC5jYWxsKHRoaXMsIHN0cmluZyk7CiAgICB9OwoKICAgIF9wcm90bzIuY2xvc2VFbGVtZW50ID0gZnVuY3Rpb24gY2xvc2VFbGVtZW50KCkgewogICAgICBpZiAodGhpcy5lbGVtZW50WyduZWVkc0V4dHJhQ2xvc2UnXSA9PT0gdHJ1ZSkgewogICAgICAgIHRoaXMuZWxlbWVudFsnbmVlZHNFeHRyYUNsb3NlJ10gPSBmYWxzZTsKCiAgICAgICAgX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS5jbG9zZUVsZW1lbnQuY2FsbCh0aGlzKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuY2xvc2VFbGVtZW50LmNhbGwodGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzIub3BlbkVsZW1lbnQgPSBmdW5jdGlvbiBvcGVuRWxlbWVudCh0YWcpIHsKICAgICAgaWYgKHRhZyA9PT0gJ3RyJykgewogICAgICAgIGlmICh0aGlzLmVsZW1lbnQudGFnTmFtZSAhPT0gJ1RCT0RZJyAmJiB0aGlzLmVsZW1lbnQudGFnTmFtZSAhPT0gJ1RIRUFEJyAmJiB0aGlzLmVsZW1lbnQudGFnTmFtZSAhPT0gJ1RGT09UJykgewogICAgICAgICAgdGhpcy5vcGVuRWxlbWVudCgndGJvZHknKTsgLy8gVGhpcyBwcmV2ZW50cyB0aGUgY2xvc2VCbG9jayBjb21tZW50IGZyb20gYmVpbmcgcmUtcGFyZW50ZWQKICAgICAgICAgIC8vIHVuZGVyIHRoZSBhdXRvIGluc2VydGVkIHRib2R5LiBSZWh5ZHJhdGlvbiBidWlsZGVyIG5lZWRzIHRvCiAgICAgICAgICAvLyBhY2NvdW50IGZvciB0aGUgaW5zZXJ0aW9uIHNpbmNlIGl0IGlzIGluamVjdGVkIGhlcmUgYW5kIG5vdAogICAgICAgICAgLy8gcmVhbGx5IGluIHRoZSB0ZW1wbGF0ZS4KCiAgICAgICAgICB0aGlzLmNvbnN0cnVjdGluZ1snbmVlZHNFeHRyYUNsb3NlJ10gPSB0cnVlOwogICAgICAgICAgdGhpcy5mbHVzaEVsZW1lbnQobnVsbCk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS5vcGVuRWxlbWVudC5jYWxsKHRoaXMsIHRhZyk7CiAgICB9OwoKICAgIF9wcm90bzIucHVzaFJlbW90ZUVsZW1lbnQgPSBmdW5jdGlvbiBwdXNoUmVtb3RlRWxlbWVudChlbGVtZW50LCBjdXJzb3JJZCwgbmV4dFNpYmxpbmcpIHsKICAgICAgaWYgKG5leHRTaWJsaW5nID09PSB2b2lkIDApIHsKICAgICAgICBuZXh0U2libGluZyA9IG51bGw7CiAgICAgIH0KCiAgICAgIHZhciBkb20gPSB0aGlzLmRvbTsKICAgICAgdmFyIHNjcmlwdCA9IGRvbS5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTsKICAgICAgc2NyaXB0LnNldEF0dHJpYnV0ZSgnZ2xtcicsIGN1cnNvcklkKTsKICAgICAgZG9tLmluc2VydEJlZm9yZShlbGVtZW50LCBzY3JpcHQsIG5leHRTaWJsaW5nKTsKCiAgICAgIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUucHVzaFJlbW90ZUVsZW1lbnQuY2FsbCh0aGlzLCBlbGVtZW50LCBjdXJzb3JJZCwgbmV4dFNpYmxpbmcpOwogICAgfTsKCiAgICByZXR1cm4gU2VyaWFsaXplQnVpbGRlcjsKICB9KF9ydW50aW1lLk5ld0VsZW1lbnRCdWlsZGVyKTsKCiAgZnVuY3Rpb24gc2VyaWFsaXplQnVpbGRlcihlbnYsIGN1cnNvcikgewogICAgcmV0dXJuIFNlcmlhbGl6ZUJ1aWxkZXIuZm9ySW5pdGlhbFJlbmRlcihlbnYsIGN1cnNvcik7CiAgfQp9KTsKZGVmaW5lKCJAZ2xpbW1lci9vcGNvZGUtY29tcGlsZXIiLCBbImV4cG9ydHMiLCAiQGVtYmVyL3BvbHlmaWxscyIsICJlbWJlci1iYWJlbCIsICJAZ2xpbW1lci91dGlsIiwgIkBnbGltbWVyL3ZtIiwgIkBnbGltbWVyL3dpcmUtZm9ybWF0IiwgIkBnbGltbWVyL2VuY29kZXIiLCAiQGdsaW1tZXIvcHJvZ3JhbSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9wb2x5ZmlsbHMsIF9lbWJlckJhYmVsLCBfdXRpbCwgX3ZtLCBfd2lyZUZvcm1hdCwgX2VuY29kZXIsIF9wcm9ncmFtKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5jb21waWxlID0gY29tcGlsZTsKICBfZXhwb3J0cy50ZW1wbGF0ZUZhY3RvcnkgPSB0ZW1wbGF0ZUZhY3Rvcnk7CiAgX2V4cG9ydHMuZGVidWcgPSBkZWJ1ZzsKICBfZXhwb3J0cy5kZWJ1Z1NsaWNlID0gZGVidWdTbGljZTsKICBfZXhwb3J0cy5sb2dPcGNvZGUgPSBsb2dPcGNvZGU7CiAgX2V4cG9ydHMuUExBQ0VIT0xERVJfSEFORExFID0gX2V4cG9ydHMuV3JhcHBlZEJ1aWxkZXIgPSBfZXhwb3J0cy5QYXJ0aWFsRGVmaW5pdGlvbiA9IF9leHBvcnRzLlN0ZE9wY29kZUJ1aWxkZXIgPSBfZXhwb3J0cy5PcGNvZGVCdWlsZGVyID0gX2V4cG9ydHMuRWFnZXJPcGNvZGVCdWlsZGVyID0gX2V4cG9ydHMuTGF6eU9wY29kZUJ1aWxkZXIgPSBfZXhwb3J0cy5Db21waWxhYmxlUHJvZ3JhbSA9IF9leHBvcnRzLkNvbXBpbGFibGVCbG9jayA9IF9leHBvcnRzLmRlYnVnQ29tcGlsZXIgPSBfZXhwb3J0cy5BYnN0cmFjdENvbXBpbGVyID0gX2V4cG9ydHMuTGF6eUNvbXBpbGVyID0gX2V4cG9ydHMuTWFjcm9zID0gX2V4cG9ydHMuQVRUUlNfQkxPQ0sgPSB2b2lkIDA7CiAgdmFyIFBMQUNFSE9MREVSX0hBTkRMRSA9IC0xOwogIF9leHBvcnRzLlBMQUNFSE9MREVSX0hBTkRMRSA9IFBMQUNFSE9MREVSX0hBTkRMRTsKICB2YXIgT3BzJDE7CgogIChmdW5jdGlvbiAoT3BzJCQxKSB7CiAgICBPcHMkJDFbT3BzJCQxWyJPcGVuQ29tcG9uZW50RWxlbWVudCJdID0gMF0gPSAiT3BlbkNvbXBvbmVudEVsZW1lbnQiOwogICAgT3BzJCQxW09wcyQkMVsiRGlkQ3JlYXRlRWxlbWVudCJdID0gMV0gPSAiRGlkQ3JlYXRlRWxlbWVudCI7CiAgICBPcHMkJDFbT3BzJCQxWyJEaWRSZW5kZXJMYXlvdXQiXSA9IDJdID0gIkRpZFJlbmRlckxheW91dCI7CiAgICBPcHMkJDFbT3BzJCQxWyJEZWJ1Z2dlciJdID0gM10gPSAiRGVidWdnZXIiOwogIH0pKE9wcyQxIHx8IChPcHMkMSA9IHt9KSk7CgogIHZhciBPcHMkMiA9IF93aXJlRm9ybWF0Lk9wczsKICB2YXIgQVRUUlNfQkxPQ0sgPSAnJmF0dHJzJzsKICBfZXhwb3J0cy5BVFRSU19CTE9DSyA9IEFUVFJTX0JMT0NLOwoKICB2YXIgQ29tcGlsZXJzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ29tcGlsZXJzKG9mZnNldCkgewogICAgICBpZiAob2Zmc2V0ID09PSB2b2lkIDApIHsKICAgICAgICBvZmZzZXQgPSAwOwogICAgICB9CgogICAgICB0aGlzLm9mZnNldCA9IG9mZnNldDsKICAgICAgdGhpcy5uYW1lcyA9ICgwLCBfdXRpbC5kaWN0KSgpOwogICAgICB0aGlzLmZ1bmNzID0gW107CiAgICB9CgogICAgdmFyIF9wcm90byA9IENvbXBpbGVycy5wcm90b3R5cGU7CgogICAgX3Byb3RvLmFkZCA9IGZ1bmN0aW9uIGFkZChuYW1lLCBmdW5jKSB7CiAgICAgIHRoaXMuZnVuY3MucHVzaChmdW5jKTsKICAgICAgdGhpcy5uYW1lc1tuYW1lXSA9IHRoaXMuZnVuY3MubGVuZ3RoIC0gMTsKICAgIH07CgogICAgX3Byb3RvLmNvbXBpbGUgPSBmdW5jdGlvbiBjb21waWxlKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIG5hbWUgPSBzZXhwW3RoaXMub2Zmc2V0XTsKICAgICAgdmFyIGluZGV4ID0gdGhpcy5uYW1lc1tuYW1lXTsKICAgICAgdmFyIGZ1bmMgPSB0aGlzLmZ1bmNzW2luZGV4XTsKICAgICAgZnVuYyhzZXhwLCBidWlsZGVyKTsKICAgIH07CgogICAgcmV0dXJuIENvbXBpbGVyczsKICB9KCk7CgogIHZhciBfc3RhdGVtZW50Q29tcGlsZXI7CgogIGZ1bmN0aW9uIHN0YXRlbWVudENvbXBpbGVyKCkgewogICAgaWYgKF9zdGF0ZW1lbnRDb21waWxlcikgewogICAgICByZXR1cm4gX3N0YXRlbWVudENvbXBpbGVyOwogICAgfQoKICAgIHZhciBTVEFURU1FTlRTID0gX3N0YXRlbWVudENvbXBpbGVyID0gbmV3IENvbXBpbGVycygpOwogICAgU1RBVEVNRU5UUy5hZGQoT3BzJDIuVGV4dCwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgYnVpbGRlci50ZXh0KHNleHBbMV0pOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5Db21tZW50LCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICBidWlsZGVyLmNvbW1lbnQoc2V4cFsxXSk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkNsb3NlRWxlbWVudCwgZnVuY3Rpb24gKF9zZXhwLCBidWlsZGVyKSB7CiAgICAgIGJ1aWxkZXIuY2xvc2VFbGVtZW50KCk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkZsdXNoRWxlbWVudCwgZnVuY3Rpb24gKF9zZXhwLCBidWlsZGVyKSB7CiAgICAgIGJ1aWxkZXIuZmx1c2hFbGVtZW50KCk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLk1vZGlmaWVyLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgcmVmZXJyZXIgPSBidWlsZGVyLnJlZmVycmVyOwogICAgICB2YXIgbmFtZSA9IHNleHBbMV0sCiAgICAgICAgICBwYXJhbXMgPSBzZXhwWzJdLAogICAgICAgICAgaGFzaCA9IHNleHBbM107CiAgICAgIHZhciBoYW5kbGUgPSBidWlsZGVyLmNvbXBpbGVyLnJlc29sdmVNb2RpZmllcihuYW1lLCByZWZlcnJlcik7CgogICAgICBpZiAoaGFuZGxlICE9PSBudWxsKSB7CiAgICAgICAgYnVpbGRlci5tb2RpZmllcihoYW5kbGUsIHBhcmFtcywgaGFzaCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDb21waWxlIEVycm9yICIgKyBuYW1lICsgIiBpcyBub3QgYSBtb2RpZmllcjogSGVscGVycyBtYXkgbm90IGJlIHVzZWQgaW4gdGhlIGVsZW1lbnQgZm9ybS4iKTsKICAgICAgfQogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5TdGF0aWNBdHRyLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgbmFtZSA9IHNleHBbMV0sCiAgICAgICAgICB2YWx1ZSA9IHNleHBbMl0sCiAgICAgICAgICBuYW1lc3BhY2UgPSBzZXhwWzNdOwogICAgICBidWlsZGVyLnN0YXRpY0F0dHIobmFtZSwgbmFtZXNwYWNlLCB2YWx1ZSk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkR5bmFtaWNBdHRyLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICBkeW5hbWljQXR0cihzZXhwLCBmYWxzZSwgYnVpbGRlcik7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkNvbXBvbmVudEF0dHIsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIGNvbXBvbmVudEF0dHIoc2V4cCwgZmFsc2UsIGJ1aWxkZXIpOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5UcnVzdGluZ0F0dHIsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIGR5bmFtaWNBdHRyKHNleHAsIHRydWUsIGJ1aWxkZXIpOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5UcnVzdGluZ0NvbXBvbmVudEF0dHIsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIGNvbXBvbmVudEF0dHIoc2V4cCwgdHJ1ZSwgYnVpbGRlcik7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLk9wZW5FbGVtZW50LCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgdGFnID0gc2V4cFsxXSwKICAgICAgICAgIHNpbXBsZSA9IHNleHBbMl07CgogICAgICBpZiAoIXNpbXBsZSkgewogICAgICAgIGJ1aWxkZXIucHV0Q29tcG9uZW50T3BlcmF0aW9ucygpOwogICAgICB9CgogICAgICBidWlsZGVyLm9wZW5QcmltaXRpdmVFbGVtZW50KHRhZyk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkR5bmFtaWNDb21wb25lbnQsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciBkZWZpbml0aW9uID0gc2V4cFsxXSwKICAgICAgICAgIGF0dHJzID0gc2V4cFsyXSwKICAgICAgICAgIGFyZ3MgPSBzZXhwWzNdLAogICAgICAgICAgdGVtcGxhdGUgPSBzZXhwWzRdOwogICAgICB2YXIgYmxvY2sgPSBidWlsZGVyLnRlbXBsYXRlKHRlbXBsYXRlKTsKICAgICAgdmFyIGF0dHJzQmxvY2sgPSBudWxsOwoKICAgICAgaWYgKGF0dHJzLmxlbmd0aCA+IDApIHsKICAgICAgICBhdHRyc0Jsb2NrID0gYnVpbGRlci5pbmxpbmVCbG9jayh7CiAgICAgICAgICBzdGF0ZW1lbnRzOiBhdHRycywKICAgICAgICAgIHBhcmFtZXRlcnM6IF91dGlsLkVNUFRZX0FSUkFZCiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIGJ1aWxkZXIuZHluYW1pY0NvbXBvbmVudChkZWZpbml0aW9uLCBhdHRyc0Jsb2NrLCBudWxsLCBhcmdzLCBmYWxzZSwgYmxvY2ssIG51bGwpOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5Db21wb25lbnQsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciB0YWcgPSBzZXhwWzFdLAogICAgICAgICAgYXR0cnMgPSBzZXhwWzJdLAogICAgICAgICAgYXJncyA9IHNleHBbM10sCiAgICAgICAgICBibG9jayA9IHNleHBbNF07CiAgICAgIHZhciByZWZlcnJlciA9IGJ1aWxkZXIucmVmZXJyZXI7CgogICAgICB2YXIgX2J1aWxkZXIkY29tcGlsZXIkcmVzID0gYnVpbGRlci5jb21waWxlci5yZXNvbHZlTGF5b3V0Rm9yVGFnKHRhZywgcmVmZXJyZXIpLAogICAgICAgICAgaGFuZGxlID0gX2J1aWxkZXIkY29tcGlsZXIkcmVzLmhhbmRsZSwKICAgICAgICAgIGNhcGFiaWxpdGllcyA9IF9idWlsZGVyJGNvbXBpbGVyJHJlcy5jYXBhYmlsaXRpZXMsCiAgICAgICAgICBjb21waWxhYmxlID0gX2J1aWxkZXIkY29tcGlsZXIkcmVzLmNvbXBpbGFibGU7CgogICAgICBpZiAoaGFuZGxlICE9PSBudWxsICYmIGNhcGFiaWxpdGllcyAhPT0gbnVsbCkgewogICAgICAgIHZhciBhdHRyc0Jsb2NrID0gbnVsbDsKCiAgICAgICAgaWYgKGF0dHJzLmxlbmd0aCA+IDApIHsKICAgICAgICAgIGF0dHJzQmxvY2sgPSBidWlsZGVyLmlubGluZUJsb2NrKHsKICAgICAgICAgICAgc3RhdGVtZW50czogYXR0cnMsCiAgICAgICAgICAgIHBhcmFtZXRlcnM6IF91dGlsLkVNUFRZX0FSUkFZCiAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIHZhciBjaGlsZCA9IGJ1aWxkZXIudGVtcGxhdGUoYmxvY2spOwoKICAgICAgICBpZiAoY29tcGlsYWJsZSkgewogICAgICAgICAgYnVpbGRlci5wdXNoQ29tcG9uZW50RGVmaW5pdGlvbihoYW5kbGUpOwogICAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNDb21wb25lbnQoY2FwYWJpbGl0aWVzLCBjb21waWxhYmxlLCBhdHRyc0Jsb2NrLCBudWxsLCBhcmdzLCBmYWxzZSwgY2hpbGQgJiYgY2hpbGQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBidWlsZGVyLnB1c2hDb21wb25lbnREZWZpbml0aW9uKGhhbmRsZSk7CiAgICAgICAgICBidWlsZGVyLmludm9rZUNvbXBvbmVudChjYXBhYmlsaXRpZXMsIGF0dHJzQmxvY2ssIG51bGwsIGFyZ3MsIGZhbHNlLCBjaGlsZCAmJiBjaGlsZCk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiQ29tcGlsZSBFcnJvcjogQ2Fubm90IGZpbmQgY29tcG9uZW50ICIgKyB0YWcpOwogICAgICB9CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLlBhcnRpYWwsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciBuYW1lID0gc2V4cFsxXSwKICAgICAgICAgIGV2YWxJbmZvID0gc2V4cFsyXTsKICAgICAgdmFyIHJlZmVycmVyID0gYnVpbGRlci5yZWZlcnJlcjsKICAgICAgYnVpbGRlci5yZXBsYXlhYmxlSWYoewogICAgICAgIGFyZ3M6IGZ1bmN0aW9uIGFyZ3MoKSB7CiAgICAgICAgICBidWlsZGVyLmV4cHIobmFtZSk7CiAgICAgICAgICBidWlsZGVyLmR1cCgpOwogICAgICAgICAgcmV0dXJuIDI7CiAgICAgICAgfSwKICAgICAgICBpZlRydWU6IGZ1bmN0aW9uIGlmVHJ1ZSgpIHsKICAgICAgICAgIGJ1aWxkZXIuaW52b2tlUGFydGlhbChyZWZlcnJlciwgYnVpbGRlci5ldmFsU3ltYm9scygpLCBldmFsSW5mbyk7CiAgICAgICAgICBidWlsZGVyLnBvcFNjb3BlKCk7CiAgICAgICAgICBidWlsZGVyLnBvcEZyYW1lKCk7IC8vIEZJWE1FOiBXQVQKICAgICAgICB9CiAgICAgIH0pOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5ZaWVsZCwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIHRvID0gc2V4cFsxXSwKICAgICAgICAgIHBhcmFtcyA9IHNleHBbMl07CiAgICAgIGJ1aWxkZXIueWllbGQodG8sIHBhcmFtcyk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkF0dHJTcGxhdCwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIHRvID0gc2V4cFsxXTsKICAgICAgYnVpbGRlci55aWVsZCh0bywgW10pOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5EZWJ1Z2dlciwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIGV2YWxJbmZvID0gc2V4cFsxXTsKICAgICAgYnVpbGRlci5kZWJ1Z2dlcihidWlsZGVyLmV2YWxTeW1ib2xzKCksIGV2YWxJbmZvKTsKICAgIH0pOwogICAgU1RBVEVNRU5UUy5hZGQoT3BzJDIuQ2xpZW50U2lkZVN0YXRlbWVudCwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgQ0xJRU5UX1NJREUuY29tcGlsZShzZXhwLCBidWlsZGVyKTsKICAgIH0pOwogICAgU1RBVEVNRU5UUy5hZGQoT3BzJDIuQXBwZW5kLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgdmFsdWUgPSBzZXhwWzFdLAogICAgICAgICAgdHJ1c3RpbmcgPSBzZXhwWzJdOwogICAgICB2YXIgcmV0dXJuZWQgPSBidWlsZGVyLmNvbXBpbGVJbmxpbmUoc2V4cCkgfHwgdmFsdWU7CiAgICAgIGlmIChyZXR1cm5lZCA9PT0gdHJ1ZSkgcmV0dXJuOwogICAgICBidWlsZGVyLmd1YXJkZWRBcHBlbmQodmFsdWUsIHRydXN0aW5nKTsKICAgIH0pOwogICAgU1RBVEVNRU5UUy5hZGQoT3BzJDIuQmxvY2ssIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciBuYW1lID0gc2V4cFsxXSwKICAgICAgICAgIHBhcmFtcyA9IHNleHBbMl0sCiAgICAgICAgICBoYXNoID0gc2V4cFszXSwKICAgICAgICAgIF90ZW1wbGF0ZSA9IHNleHBbNF0sCiAgICAgICAgICBfaW52ZXJzZSA9IHNleHBbNV07CiAgICAgIHZhciB0ZW1wbGF0ZSA9IGJ1aWxkZXIudGVtcGxhdGUoX3RlbXBsYXRlKTsKICAgICAgdmFyIGludmVyc2UgPSBidWlsZGVyLnRlbXBsYXRlKF9pbnZlcnNlKTsKICAgICAgdmFyIHRlbXBsYXRlQmxvY2sgPSB0ZW1wbGF0ZSAmJiB0ZW1wbGF0ZTsKICAgICAgdmFyIGludmVyc2VCbG9jayA9IGludmVyc2UgJiYgaW52ZXJzZTsKICAgICAgYnVpbGRlci5jb21waWxlQmxvY2sobmFtZSwgcGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZUJsb2NrLCBpbnZlcnNlQmxvY2spOwogICAgfSk7CiAgICB2YXIgQ0xJRU5UX1NJREUgPSBuZXcgQ29tcGlsZXJzKDEpOwogICAgQ0xJRU5UX1NJREUuYWRkKE9wcyQxLk9wZW5Db21wb25lbnRFbGVtZW50LCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICBidWlsZGVyLnB1dENvbXBvbmVudE9wZXJhdGlvbnMoKTsKICAgICAgYnVpbGRlci5vcGVuUHJpbWl0aXZlRWxlbWVudChzZXhwWzJdKTsKICAgIH0pOwogICAgQ0xJRU5UX1NJREUuYWRkKE9wcyQxLkRpZENyZWF0ZUVsZW1lbnQsIGZ1bmN0aW9uIChfc2V4cCwgYnVpbGRlcikgewogICAgICBidWlsZGVyLmRpZENyZWF0ZUVsZW1lbnQoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgIH0pOwogICAgQ0xJRU5UX1NJREUuYWRkKE9wcyQxLkRlYnVnZ2VyLCBmdW5jdGlvbiAoKSB7CiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1kZWJ1Z2dlcgogICAgICBkZWJ1Z2dlcjsKICAgIH0pOwogICAgQ0xJRU5UX1NJREUuYWRkKE9wcyQxLkRpZFJlbmRlckxheW91dCwgZnVuY3Rpb24gKF9zZXhwLCBidWlsZGVyKSB7CiAgICAgIGJ1aWxkZXIuZGlkUmVuZGVyTGF5b3V0KF92bS5SZWdpc3Rlci5zMCk7CiAgICB9KTsKICAgIHJldHVybiBTVEFURU1FTlRTOwogIH0KCiAgZnVuY3Rpb24gY29tcG9uZW50QXR0cihzZXhwLCB0cnVzdGluZywgYnVpbGRlcikgewogICAgdmFyIG5hbWUgPSBzZXhwWzFdLAogICAgICAgIHZhbHVlID0gc2V4cFsyXSwKICAgICAgICBuYW1lc3BhY2UgPSBzZXhwWzNdOwogICAgYnVpbGRlci5leHByKHZhbHVlKTsKCiAgICBpZiAobmFtZXNwYWNlKSB7CiAgICAgIGJ1aWxkZXIuY29tcG9uZW50QXR0cihuYW1lLCBuYW1lc3BhY2UsIHRydXN0aW5nKTsKICAgIH0gZWxzZSB7CiAgICAgIGJ1aWxkZXIuY29tcG9uZW50QXR0cihuYW1lLCBudWxsLCB0cnVzdGluZyk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBkeW5hbWljQXR0cihzZXhwLCB0cnVzdGluZywgYnVpbGRlcikgewogICAgdmFyIG5hbWUgPSBzZXhwWzFdLAogICAgICAgIHZhbHVlID0gc2V4cFsyXSwKICAgICAgICBuYW1lc3BhY2UgPSBzZXhwWzNdOwogICAgYnVpbGRlci5leHByKHZhbHVlKTsKCiAgICBpZiAobmFtZXNwYWNlKSB7CiAgICAgIGJ1aWxkZXIuZHluYW1pY0F0dHIobmFtZSwgbmFtZXNwYWNlLCB0cnVzdGluZyk7CiAgICB9IGVsc2UgewogICAgICBidWlsZGVyLmR5bmFtaWNBdHRyKG5hbWUsIG51bGwsIHRydXN0aW5nKTsKICAgIH0KICB9CgogIHZhciBfZXhwcmVzc2lvbkNvbXBpbGVyOwoKICBmdW5jdGlvbiBleHByZXNzaW9uQ29tcGlsZXIoKSB7CiAgICBpZiAoX2V4cHJlc3Npb25Db21waWxlcikgewogICAgICByZXR1cm4gX2V4cHJlc3Npb25Db21waWxlcjsKICAgIH0KCiAgICB2YXIgRVhQUkVTU0lPTlMgPSBfZXhwcmVzc2lvbkNvbXBpbGVyID0gbmV3IENvbXBpbGVycygpOwogICAgRVhQUkVTU0lPTlMuYWRkKE9wcyQyLlVua25vd24sIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciBjb21waWxlciA9IGJ1aWxkZXIuY29tcGlsZXIsCiAgICAgICAgICByZWZlcnJlciA9IGJ1aWxkZXIucmVmZXJyZXIsCiAgICAgICAgICBhc1BhcnRpYWwgPSBidWlsZGVyLmNvbnRhaW5pbmdMYXlvdXQuYXNQYXJ0aWFsOwogICAgICB2YXIgbmFtZSA9IHNleHBbMV07CiAgICAgIHZhciBoYW5kbGUgPSBjb21waWxlci5yZXNvbHZlSGVscGVyKG5hbWUsIHJlZmVycmVyKTsKCiAgICAgIGlmIChoYW5kbGUgIT09IG51bGwpIHsKICAgICAgICBidWlsZGVyLmhlbHBlcihoYW5kbGUsIG51bGwsIG51bGwpOwogICAgICB9IGVsc2UgaWYgKGFzUGFydGlhbCkgewogICAgICAgIGJ1aWxkZXIucmVzb2x2ZU1heWJlTG9jYWwobmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnVpbGRlci5nZXRWYXJpYWJsZSgwKTsKICAgICAgICBidWlsZGVyLmdldFByb3BlcnR5KG5hbWUpOwogICAgICB9CiAgICB9KTsKICAgIEVYUFJFU1NJT05TLmFkZChPcHMkMi5Db25jYXQsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciBwYXJ0cyA9IHNleHBbMV07CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgYnVpbGRlci5leHByKHBhcnRzW2ldKTsKICAgICAgfQoKICAgICAgYnVpbGRlci5jb25jYXQocGFydHMubGVuZ3RoKTsKICAgIH0pOwogICAgRVhQUkVTU0lPTlMuYWRkKE9wcyQyLkhlbHBlciwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIGNvbXBpbGVyID0gYnVpbGRlci5jb21waWxlciwKICAgICAgICAgIHJlZmVycmVyID0gYnVpbGRlci5yZWZlcnJlcjsKICAgICAgdmFyIG5hbWUgPSBzZXhwWzFdLAogICAgICAgICAgcGFyYW1zID0gc2V4cFsyXSwKICAgICAgICAgIGhhc2ggPSBzZXhwWzNdOyAvLyBUT0RPOiB0cmlhZ2UgdGhpcyBpbiB0aGUgV0YgY29tcGlsZXIKCiAgICAgIGlmIChuYW1lID09PSAnY29tcG9uZW50JykgewogICAgICAgIHZhciBkZWZpbml0aW9uID0gcGFyYW1zWzBdLAogICAgICAgICAgICByZXN0QXJncyA9IHBhcmFtcy5zbGljZSgxKTsKICAgICAgICBidWlsZGVyLmN1cnJ5Q29tcG9uZW50KGRlZmluaXRpb24sIHJlc3RBcmdzLCBoYXNoLCB0cnVlKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBoYW5kbGUgPSBjb21waWxlci5yZXNvbHZlSGVscGVyKG5hbWUsIHJlZmVycmVyKTsKCiAgICAgIGlmIChoYW5kbGUgIT09IG51bGwpIHsKICAgICAgICBidWlsZGVyLmhlbHBlcihoYW5kbGUsIHBhcmFtcywgaGFzaCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDb21waWxlIEVycm9yOiAiICsgbmFtZSArICIgaXMgbm90IGEgaGVscGVyIik7CiAgICAgIH0KICAgIH0pOwogICAgRVhQUkVTU0lPTlMuYWRkKE9wcyQyLkdldCwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIGhlYWQgPSBzZXhwWzFdLAogICAgICAgICAgcGF0aCA9IHNleHBbMl07CiAgICAgIGJ1aWxkZXIuZ2V0VmFyaWFibGUoaGVhZCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGgubGVuZ3RoOyBpKyspIHsKICAgICAgICBidWlsZGVyLmdldFByb3BlcnR5KHBhdGhbaV0pOwogICAgICB9CiAgICB9KTsKICAgIEVYUFJFU1NJT05TLmFkZChPcHMkMi5NYXliZUxvY2FsLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgcGF0aCA9IHNleHBbMV07CgogICAgICBpZiAoYnVpbGRlci5jb250YWluaW5nTGF5b3V0LmFzUGFydGlhbCkgewogICAgICAgIHZhciBoZWFkID0gcGF0aFswXTsKICAgICAgICBwYXRoID0gcGF0aC5zbGljZSgxKTsKICAgICAgICBidWlsZGVyLnJlc29sdmVNYXliZUxvY2FsKGhlYWQpOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1aWxkZXIuZ2V0VmFyaWFibGUoMCk7CiAgICAgIH0KCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0aC5sZW5ndGg7IGkrKykgewogICAgICAgIGJ1aWxkZXIuZ2V0UHJvcGVydHkocGF0aFtpXSk7CiAgICAgIH0KICAgIH0pOwogICAgRVhQUkVTU0lPTlMuYWRkKE9wcyQyLlVuZGVmaW5lZCwgZnVuY3Rpb24gKF9zZXhwLCBidWlsZGVyKSB7CiAgICAgIHJldHVybiBidWlsZGVyLnB1c2hQcmltaXRpdmVSZWZlcmVuY2UodW5kZWZpbmVkKTsKICAgIH0pOwogICAgRVhQUkVTU0lPTlMuYWRkKE9wcyQyLkhhc0Jsb2NrLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICBidWlsZGVyLmhhc0Jsb2NrKHNleHBbMV0pOwogICAgfSk7CiAgICBFWFBSRVNTSU9OUy5hZGQoT3BzJDIuSGFzQmxvY2tQYXJhbXMsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIGJ1aWxkZXIuaGFzQmxvY2tQYXJhbXMoc2V4cFsxXSk7CiAgICB9KTsKICAgIHJldHVybiBFWFBSRVNTSU9OUzsKICB9CgogIHZhciBNYWNyb3MgPSBmdW5jdGlvbiBNYWNyb3MoKSB7CiAgICB2YXIgX3BvcHVsYXRlQnVpbHRpbnMgPSBwb3B1bGF0ZUJ1aWx0aW5zKCksCiAgICAgICAgYmxvY2tzID0gX3BvcHVsYXRlQnVpbHRpbnMuYmxvY2tzLAogICAgICAgIGlubGluZXMgPSBfcG9wdWxhdGVCdWlsdGlucy5pbmxpbmVzOwoKICAgIHRoaXMuYmxvY2tzID0gYmxvY2tzOwogICAgdGhpcy5pbmxpbmVzID0gaW5saW5lczsKICB9OwoKICBfZXhwb3J0cy5NYWNyb3MgPSBNYWNyb3M7CgogIHZhciBCbG9ja3MgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBCbG9ja3MoKSB7CiAgICAgIHRoaXMubmFtZXMgPSAoMCwgX3V0aWwuZGljdCkoKTsKICAgICAgdGhpcy5mdW5jcyA9IFtdOwogICAgfQoKICAgIHZhciBfcHJvdG8yID0gQmxvY2tzLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yLmFkZCA9IGZ1bmN0aW9uIGFkZChuYW1lLCBmdW5jKSB7CiAgICAgIHRoaXMuZnVuY3MucHVzaChmdW5jKTsKICAgICAgdGhpcy5uYW1lc1tuYW1lXSA9IHRoaXMuZnVuY3MubGVuZ3RoIC0gMTsKICAgIH07CgogICAgX3Byb3RvMi5hZGRNaXNzaW5nID0gZnVuY3Rpb24gYWRkTWlzc2luZyhmdW5jKSB7CiAgICAgIHRoaXMubWlzc2luZyA9IGZ1bmM7CiAgICB9OwoKICAgIF9wcm90bzIuY29tcGlsZSA9IGZ1bmN0aW9uIGNvbXBpbGUobmFtZSwgcGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZSwgaW52ZXJzZSwgYnVpbGRlcikgewogICAgICB2YXIgaW5kZXggPSB0aGlzLm5hbWVzW25hbWVdOwoKICAgICAgaWYgKGluZGV4ID09PSB1bmRlZmluZWQpIHsKICAgICAgICB2YXIgZnVuYyA9IHRoaXMubWlzc2luZzsKICAgICAgICB2YXIgaGFuZGxlZCA9IGZ1bmMobmFtZSwgcGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZSwgaW52ZXJzZSwgYnVpbGRlcik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIF9mdW5jID0gdGhpcy5mdW5jc1tpbmRleF07CgogICAgICAgIF9mdW5jKHBhcmFtcywgaGFzaCwgdGVtcGxhdGUsIGludmVyc2UsIGJ1aWxkZXIpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBCbG9ja3M7CiAgfSgpOwoKICB2YXIgSW5saW5lcyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIElubGluZXMoKSB7CiAgICAgIHRoaXMubmFtZXMgPSAoMCwgX3V0aWwuZGljdCkoKTsKICAgICAgdGhpcy5mdW5jcyA9IFtdOwogICAgfQoKICAgIHZhciBfcHJvdG8zID0gSW5saW5lcy5wcm90b3R5cGU7CgogICAgX3Byb3RvMy5hZGQgPSBmdW5jdGlvbiBhZGQobmFtZSwgZnVuYykgewogICAgICB0aGlzLmZ1bmNzLnB1c2goZnVuYyk7CiAgICAgIHRoaXMubmFtZXNbbmFtZV0gPSB0aGlzLmZ1bmNzLmxlbmd0aCAtIDE7CiAgICB9OwoKICAgIF9wcm90bzMuYWRkTWlzc2luZyA9IGZ1bmN0aW9uIGFkZE1pc3NpbmcoZnVuYykgewogICAgICB0aGlzLm1pc3NpbmcgPSBmdW5jOwogICAgfTsKCiAgICBfcHJvdG8zLmNvbXBpbGUgPSBmdW5jdGlvbiBjb21waWxlKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIHZhbHVlID0gc2V4cFsxXTsgLy8gVE9ETzogRml4IHRoaXMgc28gdGhhdCBleHByZXNzaW9uIG1hY3JvcyBjYW4gcmV0dXJuCiAgICAgIC8vIHRoaW5ncyBsaWtlIGNvbXBvbmVudHMsIHNvIHRoYXQge3tjb21wb25lbnQgZm9vfX0KICAgICAgLy8gaXMgdGhlIHNhbWUgYXMge3soY29tcG9uZW50IGZvbyl9fQoKICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSkgcmV0dXJuIFsnZXhwcicsIHZhbHVlXTsKICAgICAgdmFyIG5hbWU7CiAgICAgIHZhciBwYXJhbXM7CiAgICAgIHZhciBoYXNoOwoKICAgICAgaWYgKHZhbHVlWzBdID09PSBPcHMkMi5IZWxwZXIpIHsKICAgICAgICBuYW1lID0gdmFsdWVbMV07CiAgICAgICAgcGFyYW1zID0gdmFsdWVbMl07CiAgICAgICAgaGFzaCA9IHZhbHVlWzNdOwogICAgICB9IGVsc2UgaWYgKHZhbHVlWzBdID09PSBPcHMkMi5Vbmtub3duKSB7CiAgICAgICAgbmFtZSA9IHZhbHVlWzFdOwogICAgICAgIHBhcmFtcyA9IGhhc2ggPSBudWxsOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBbJ2V4cHInLCB2YWx1ZV07CiAgICAgIH0KCiAgICAgIHZhciBpbmRleCA9IHRoaXMubmFtZXNbbmFtZV07CgogICAgICBpZiAoaW5kZXggPT09IHVuZGVmaW5lZCAmJiB0aGlzLm1pc3NpbmcpIHsKICAgICAgICB2YXIgZnVuYyA9IHRoaXMubWlzc2luZzsKICAgICAgICB2YXIgcmV0dXJuZWQgPSBmdW5jKG5hbWUsIHBhcmFtcywgaGFzaCwgYnVpbGRlcik7CiAgICAgICAgcmV0dXJuIHJldHVybmVkID09PSBmYWxzZSA/IFsnZXhwcicsIHZhbHVlXSA6IHJldHVybmVkOwogICAgICB9IGVsc2UgaWYgKGluZGV4ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB2YXIgX2Z1bmMyID0gdGhpcy5mdW5jc1tpbmRleF07CgogICAgICAgIHZhciBfcmV0dXJuZWQgPSBfZnVuYzIobmFtZSwgcGFyYW1zLCBoYXNoLCBidWlsZGVyKTsKCiAgICAgICAgcmV0dXJuIF9yZXR1cm5lZCA9PT0gZmFsc2UgPyBbJ2V4cHInLCB2YWx1ZV0gOiBfcmV0dXJuZWQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIFsnZXhwcicsIHZhbHVlXTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gSW5saW5lczsKICB9KCk7CgogIGZ1bmN0aW9uIHBvcHVsYXRlQnVpbHRpbnMoYmxvY2tzLCBpbmxpbmVzKSB7CiAgICBpZiAoYmxvY2tzID09PSB2b2lkIDApIHsKICAgICAgYmxvY2tzID0gbmV3IEJsb2NrcygpOwogICAgfQoKICAgIGlmIChpbmxpbmVzID09PSB2b2lkIDApIHsKICAgICAgaW5saW5lcyA9IG5ldyBJbmxpbmVzKCk7CiAgICB9CgogICAgYmxvY2tzLmFkZCgnaWYnLCBmdW5jdGlvbiAocGFyYW1zLCBfaGFzaCwgdGVtcGxhdGUsIGludmVyc2UsIGJ1aWxkZXIpIHsKICAgICAgLy8gICAgICAgIFB1dEFyZ3MKICAgICAgLy8gICAgICAgIFRlc3QoRW52aXJvbm1lbnQpCiAgICAgIC8vICAgICAgICBFbnRlcihCRUdJTiwgRU5EKQogICAgICAvLyBCRUdJTjogTm9vcAogICAgICAvLyAgICAgICAgSnVtcFVubGVzcyhFTFNFKQogICAgICAvLyAgICAgICAgRXZhbHVhdGUoZGVmYXVsdCkKICAgICAgLy8gICAgICAgIEp1bXAoRU5EKQogICAgICAvLyBFTFNFOiAgTm9vcAogICAgICAvLyAgICAgICAgRXZhbHVsYXRlKGludmVyc2UpCiAgICAgIC8vIEVORDogICBOb29wCiAgICAgIC8vICAgICAgICBFeGl0CiAgICAgIGlmICghcGFyYW1zIHx8IHBhcmFtcy5sZW5ndGggIT09IDEpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlNZTlRBWCBFUlJPUjogI2lmIHJlcXVpcmVzIGEgc2luZ2xlIGFyZ3VtZW50Iik7CiAgICAgIH0KCiAgICAgIGJ1aWxkZXIucmVwbGF5YWJsZUlmKHsKICAgICAgICBhcmdzOiBmdW5jdGlvbiBhcmdzKCkgewogICAgICAgICAgYnVpbGRlci5leHByKHBhcmFtc1swXSk7CiAgICAgICAgICBidWlsZGVyLnRvQm9vbGVhbigpOwogICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfSwKICAgICAgICBpZlRydWU6IGZ1bmN0aW9uIGlmVHJ1ZSgpIHsKICAgICAgICAgIGJ1aWxkZXIuaW52b2tlU3RhdGljQmxvY2sodGVtcGxhdGUpOwogICAgICAgIH0sCiAgICAgICAgaWZGYWxzZTogZnVuY3Rpb24gaWZGYWxzZSgpIHsKICAgICAgICAgIGlmIChpbnZlcnNlKSB7CiAgICAgICAgICAgIGJ1aWxkZXIuaW52b2tlU3RhdGljQmxvY2soaW52ZXJzZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgIH0pOwogICAgYmxvY2tzLmFkZCgndW5sZXNzJywgZnVuY3Rpb24gKHBhcmFtcywgX2hhc2gsIHRlbXBsYXRlLCBpbnZlcnNlLCBidWlsZGVyKSB7CiAgICAgIC8vICAgICAgICBQdXRBcmdzCiAgICAgIC8vICAgICAgICBUZXN0KEVudmlyb25tZW50KQogICAgICAvLyAgICAgICAgRW50ZXIoQkVHSU4sIEVORCkKICAgICAgLy8gQkVHSU46IE5vb3AKICAgICAgLy8gICAgICAgIEp1bXBVbmxlc3MoRUxTRSkKICAgICAgLy8gICAgICAgIEV2YWx1YXRlKGRlZmF1bHQpCiAgICAgIC8vICAgICAgICBKdW1wKEVORCkKICAgICAgLy8gRUxTRTogIE5vb3AKICAgICAgLy8gICAgICAgIEV2YWx1bGF0ZShpbnZlcnNlKQogICAgICAvLyBFTkQ6ICAgTm9vcAogICAgICAvLyAgICAgICAgRXhpdAogICAgICBpZiAoIXBhcmFtcyB8fCBwYXJhbXMubGVuZ3RoICE9PSAxKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJTWU5UQVggRVJST1I6ICN1bmxlc3MgcmVxdWlyZXMgYSBzaW5nbGUgYXJndW1lbnQiKTsKICAgICAgfQoKICAgICAgYnVpbGRlci5yZXBsYXlhYmxlSWYoewogICAgICAgIGFyZ3M6IGZ1bmN0aW9uIGFyZ3MoKSB7CiAgICAgICAgICBidWlsZGVyLmV4cHIocGFyYW1zWzBdKTsKICAgICAgICAgIGJ1aWxkZXIudG9Cb29sZWFuKCk7CiAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9LAogICAgICAgIGlmVHJ1ZTogZnVuY3Rpb24gaWZUcnVlKCkgewogICAgICAgICAgaWYgKGludmVyc2UpIHsKICAgICAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNCbG9jayhpbnZlcnNlKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGlmRmFsc2U6IGZ1bmN0aW9uIGlmRmFsc2UoKSB7CiAgICAgICAgICBidWlsZGVyLmludm9rZVN0YXRpY0Jsb2NrKHRlbXBsYXRlKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfSk7CiAgICBibG9ja3MuYWRkKCd3aXRoJywgZnVuY3Rpb24gKHBhcmFtcywgX2hhc2gsIHRlbXBsYXRlLCBpbnZlcnNlLCBidWlsZGVyKSB7CiAgICAgIC8vICAgICAgICBQdXRBcmdzCiAgICAgIC8vICAgICAgICBUZXN0KEVudmlyb25tZW50KQogICAgICAvLyAgICAgICAgRW50ZXIoQkVHSU4sIEVORCkKICAgICAgLy8gQkVHSU46IE5vb3AKICAgICAgLy8gICAgICAgIEp1bXBVbmxlc3MoRUxTRSkKICAgICAgLy8gICAgICAgIEV2YWx1YXRlKGRlZmF1bHQpCiAgICAgIC8vICAgICAgICBKdW1wKEVORCkKICAgICAgLy8gRUxTRTogIE5vb3AKICAgICAgLy8gICAgICAgIEV2YWx1bGF0ZShpbnZlcnNlKQogICAgICAvLyBFTkQ6ICAgTm9vcAogICAgICAvLyAgICAgICAgRXhpdAogICAgICBpZiAoIXBhcmFtcyB8fCBwYXJhbXMubGVuZ3RoICE9PSAxKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJTWU5UQVggRVJST1I6ICN3aXRoIHJlcXVpcmVzIGEgc2luZ2xlIGFyZ3VtZW50Iik7CiAgICAgIH0KCiAgICAgIGJ1aWxkZXIucmVwbGF5YWJsZUlmKHsKICAgICAgICBhcmdzOiBmdW5jdGlvbiBhcmdzKCkgewogICAgICAgICAgYnVpbGRlci5leHByKHBhcmFtc1swXSk7CiAgICAgICAgICBidWlsZGVyLmR1cCgpOwogICAgICAgICAgYnVpbGRlci50b0Jvb2xlYW4oKTsKICAgICAgICAgIHJldHVybiAyOwogICAgICAgIH0sCiAgICAgICAgaWZUcnVlOiBmdW5jdGlvbiBpZlRydWUoKSB7CiAgICAgICAgICBidWlsZGVyLmludm9rZVN0YXRpY0Jsb2NrKHRlbXBsYXRlLCAxKTsKICAgICAgICB9LAogICAgICAgIGlmRmFsc2U6IGZ1bmN0aW9uIGlmRmFsc2UoKSB7CiAgICAgICAgICBpZiAoaW52ZXJzZSkgewogICAgICAgICAgICBidWlsZGVyLmludm9rZVN0YXRpY0Jsb2NrKGludmVyc2UpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICB9KTsKICAgIGJsb2Nrcy5hZGQoJ2VhY2gnLCBmdW5jdGlvbiAocGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZSwgaW52ZXJzZSwgYnVpbGRlcikgewogICAgICAvLyAgICAgICAgIEVudGVyKEJFR0lOLCBFTkQpCiAgICAgIC8vIEJFR0lOOiAgTm9vcAogICAgICAvLyAgICAgICAgIFB1dEFyZ3MKICAgICAgLy8gICAgICAgICBQdXRJdGVyYWJsZQogICAgICAvLyAgICAgICAgIEp1bXBVbmxlc3MoRUxTRSkKICAgICAgLy8gICAgICAgICBFbnRlckxpc3QoQkVHSU4yLCBFTkQyKQogICAgICAvLyBJVEVSOiAgIE5vb3AKICAgICAgLy8gICAgICAgICBOZXh0SXRlcihCUkVBSykKICAgICAgLy8gQkVHSU4yOiBOb29wCiAgICAgIC8vICAgICAgICAgUHVzaENoaWxkU2NvcGUKICAgICAgLy8gICAgICAgICBFdmFsdWF0ZShkZWZhdWx0KQogICAgICAvLyAgICAgICAgIFBvcFNjb3BlCiAgICAgIC8vIEVORDI6ICAgTm9vcAogICAgICAvLyAgICAgICAgIEV4aXQKICAgICAgLy8gICAgICAgICBKdW1wKElURVIpCiAgICAgIC8vIEJSRUFLOiAgTm9vcAogICAgICAvLyAgICAgICAgIEV4aXRMaXN0CiAgICAgIC8vICAgICAgICAgSnVtcChFTkQpCiAgICAgIC8vIEVMU0U6ICAgTm9vcAogICAgICAvLyAgICAgICAgIEV2YWx1bGF0ZShpbnZlcnNlKQogICAgICAvLyBFTkQ6ICAgIE5vb3AKICAgICAgLy8gICAgICAgICBFeGl0CiAgICAgIGJ1aWxkZXIucmVwbGF5YWJsZSh7CiAgICAgICAgYXJnczogZnVuY3Rpb24gYXJncygpIHsKICAgICAgICAgIGlmIChoYXNoICYmIGhhc2hbMF1bMF0gPT09ICdrZXknKSB7CiAgICAgICAgICAgIGJ1aWxkZXIuZXhwcihoYXNoWzFdWzBdKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGJ1aWxkZXIucHVzaFByaW1pdGl2ZVJlZmVyZW5jZShudWxsKTsKICAgICAgICAgIH0KCiAgICAgICAgICBidWlsZGVyLmV4cHIocGFyYW1zWzBdKTsKICAgICAgICAgIHJldHVybiAyOwogICAgICAgIH0sCiAgICAgICAgYm9keTogZnVuY3Rpb24gYm9keSgpIHsKICAgICAgICAgIGJ1aWxkZXIucHV0SXRlcmF0b3IoKTsKICAgICAgICAgIGJ1aWxkZXIuanVtcFVubGVzcygnRUxTRScpOwogICAgICAgICAgYnVpbGRlci5wdXNoRnJhbWUoKTsKICAgICAgICAgIGJ1aWxkZXIuZHVwKF92bS5SZWdpc3Rlci5mcCwgMSk7CiAgICAgICAgICBidWlsZGVyLnJldHVyblRvKCdJVEVSJyk7CiAgICAgICAgICBidWlsZGVyLmVudGVyTGlzdCgnQk9EWScpOwogICAgICAgICAgYnVpbGRlci5sYWJlbCgnSVRFUicpOwogICAgICAgICAgYnVpbGRlci5pdGVyYXRlKCdCUkVBSycpOwogICAgICAgICAgYnVpbGRlci5sYWJlbCgnQk9EWScpOwogICAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNCbG9jayh0ZW1wbGF0ZSwgMik7CiAgICAgICAgICBidWlsZGVyLnBvcCgyKTsKICAgICAgICAgIGJ1aWxkZXIuanVtcCgnRklOQUxMWScpOwogICAgICAgICAgYnVpbGRlci5sYWJlbCgnQlJFQUsnKTsKICAgICAgICAgIGJ1aWxkZXIuZXhpdExpc3QoKTsKICAgICAgICAgIGJ1aWxkZXIucG9wRnJhbWUoKTsKICAgICAgICAgIGJ1aWxkZXIuanVtcCgnRklOQUxMWScpOwogICAgICAgICAgYnVpbGRlci5sYWJlbCgnRUxTRScpOwoKICAgICAgICAgIGlmIChpbnZlcnNlKSB7CiAgICAgICAgICAgIGJ1aWxkZXIuaW52b2tlU3RhdGljQmxvY2soaW52ZXJzZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgIH0pOwogICAgYmxvY2tzLmFkZCgnaW4tZWxlbWVudCcsIGZ1bmN0aW9uIChwYXJhbXMsIGhhc2gsIHRlbXBsYXRlLCBfaW52ZXJzZSwgYnVpbGRlcikgewogICAgICBpZiAoIXBhcmFtcyB8fCBwYXJhbXMubGVuZ3RoICE9PSAxKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJTWU5UQVggRVJST1I6ICNpbi1lbGVtZW50IHJlcXVpcmVzIGEgc2luZ2xlIGFyZ3VtZW50Iik7CiAgICAgIH0KCiAgICAgIGJ1aWxkZXIucmVwbGF5YWJsZUlmKHsKICAgICAgICBhcmdzOiBmdW5jdGlvbiBhcmdzKCkgewogICAgICAgICAgdmFyIGtleXMgPSBoYXNoWzBdLAogICAgICAgICAgICAgIHZhbHVlcyA9IGhhc2hbMV07CgogICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHZhciBrZXkgPSBrZXlzW2ldOwoKICAgICAgICAgICAgaWYgKGtleSA9PT0gJ25leHRTaWJsaW5nJyB8fCBrZXkgPT09ICdndWlkJykgewogICAgICAgICAgICAgIGJ1aWxkZXIuZXhwcih2YWx1ZXNbaV0pOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiU1lOVEFYIEVSUk9SOiAjaW4tZWxlbWVudCBkb2VzIG5vdCB0YWtlIGEgYCIgKyBrZXlzWzBdICsgImAgb3B0aW9uIik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICBidWlsZGVyLmV4cHIocGFyYW1zWzBdKTsKICAgICAgICAgIGJ1aWxkZXIuZHVwKCk7CiAgICAgICAgICByZXR1cm4gNDsKICAgICAgICB9LAogICAgICAgIGlmVHJ1ZTogZnVuY3Rpb24gaWZUcnVlKCkgewogICAgICAgICAgYnVpbGRlci5wdXNoUmVtb3RlRWxlbWVudCgpOwogICAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNCbG9jayh0ZW1wbGF0ZSk7CiAgICAgICAgICBidWlsZGVyLnBvcFJlbW90ZUVsZW1lbnQoKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfSk7CiAgICBibG9ja3MuYWRkKCctd2l0aC1keW5hbWljLXZhcnMnLCBmdW5jdGlvbiAoX3BhcmFtcywgaGFzaCwgdGVtcGxhdGUsIF9pbnZlcnNlLCBidWlsZGVyKSB7CiAgICAgIGlmIChoYXNoKSB7CiAgICAgICAgdmFyIG5hbWVzID0gaGFzaFswXSwKICAgICAgICAgICAgZXhwcmVzc2lvbnMgPSBoYXNoWzFdOwogICAgICAgIGJ1aWxkZXIuY29tcGlsZVBhcmFtcyhleHByZXNzaW9ucyk7CiAgICAgICAgYnVpbGRlci5wdXNoRHluYW1pY1Njb3BlKCk7CiAgICAgICAgYnVpbGRlci5iaW5kRHluYW1pY1Njb3BlKG5hbWVzKTsKICAgICAgICBidWlsZGVyLmludm9rZVN0YXRpY0Jsb2NrKHRlbXBsYXRlKTsKICAgICAgICBidWlsZGVyLnBvcER5bmFtaWNTY29wZSgpOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1aWxkZXIuaW52b2tlU3RhdGljQmxvY2sodGVtcGxhdGUpOwogICAgICB9CiAgICB9KTsKICAgIGJsb2Nrcy5hZGQoJ2NvbXBvbmVudCcsIGZ1bmN0aW9uIChfcGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZSwgaW52ZXJzZSwgYnVpbGRlcikgewogICAgICB2YXIgdGFnID0gX3BhcmFtc1swXTsKCiAgICAgIGlmICh0eXBlb2YgdGFnID09PSAnc3RyaW5nJykgewogICAgICAgIHZhciByZXR1cm5lZCA9IGJ1aWxkZXIuc3RhdGljQ29tcG9uZW50SGVscGVyKF9wYXJhbXNbMF0sIGhhc2gsIHRlbXBsYXRlKTsKICAgICAgICBpZiAocmV0dXJuZWQpIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIGRlZmluaXRpb24gPSBfcGFyYW1zWzBdLAogICAgICAgICAgcGFyYW1zID0gX3BhcmFtcy5zbGljZSgxKTsKCiAgICAgIGJ1aWxkZXIuZHluYW1pY0NvbXBvbmVudChkZWZpbml0aW9uLCBudWxsLCBwYXJhbXMsIGhhc2gsIHRydWUsIHRlbXBsYXRlLCBpbnZlcnNlKTsKICAgIH0pOwogICAgaW5saW5lcy5hZGQoJ2NvbXBvbmVudCcsIGZ1bmN0aW9uIChfbmFtZSwgX3BhcmFtcywgaGFzaCwgYnVpbGRlcikgewogICAgICB2YXIgdGFnID0gX3BhcmFtcyAmJiBfcGFyYW1zWzBdOwoKICAgICAgaWYgKHR5cGVvZiB0YWcgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgdmFyIHJldHVybmVkID0gYnVpbGRlci5zdGF0aWNDb21wb25lbnRIZWxwZXIodGFnLCBoYXNoLCBudWxsKTsKICAgICAgICBpZiAocmV0dXJuZWQpIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICB2YXIgZGVmaW5pdGlvbiA9IF9wYXJhbXNbMF0sCiAgICAgICAgICBwYXJhbXMgPSBfcGFyYW1zLnNsaWNlKDEpOwoKICAgICAgYnVpbGRlci5keW5hbWljQ29tcG9uZW50KGRlZmluaXRpb24sIG51bGwsIHBhcmFtcywgaGFzaCwgdHJ1ZSwgbnVsbCwgbnVsbCk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSk7CiAgICByZXR1cm4gewogICAgICBibG9ja3M6IGJsb2NrcywKICAgICAgaW5saW5lczogaW5saW5lcwogICAgfTsKICB9CgogIHZhciBQTEFDRUhPTERFUl9IQU5ETEUkMSA9IC0xOwoKICB2YXIgQ29tcGlsYWJsZVByb2dyYW0gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDb21waWxhYmxlUHJvZ3JhbShjb21waWxlciwgbGF5b3V0KSB7CiAgICAgIHRoaXMuY29tcGlsZXIgPSBjb21waWxlcjsKICAgICAgdGhpcy5sYXlvdXQgPSBsYXlvdXQ7CiAgICAgIHRoaXMuY29tcGlsZWQgPSBudWxsOwogICAgfQoKICAgIHZhciBfcHJvdG80ID0gQ29tcGlsYWJsZVByb2dyYW0ucHJvdG90eXBlOwoKICAgIF9wcm90bzQuY29tcGlsZSA9IGZ1bmN0aW9uIGNvbXBpbGUoKSB7CiAgICAgIGlmICh0aGlzLmNvbXBpbGVkICE9PSBudWxsKSByZXR1cm4gdGhpcy5jb21waWxlZDsKICAgICAgdGhpcy5jb21waWxlZCA9IFBMQUNFSE9MREVSX0hBTkRMRSQxOwogICAgICB2YXIgc3RhdGVtZW50cyA9IHRoaXMubGF5b3V0LmJsb2NrLnN0YXRlbWVudHM7CiAgICAgIHJldHVybiB0aGlzLmNvbXBpbGVkID0gdGhpcy5jb21waWxlci5hZGQoc3RhdGVtZW50cywgdGhpcy5sYXlvdXQpOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKENvbXBpbGFibGVQcm9ncmFtLCBbewogICAgICBrZXk6ICJzeW1ib2xUYWJsZSIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmxheW91dC5ibG9jazsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIENvbXBpbGFibGVQcm9ncmFtOwogIH0oKTsKCiAgX2V4cG9ydHMuQ29tcGlsYWJsZVByb2dyYW0gPSBDb21waWxhYmxlUHJvZ3JhbTsKCiAgdmFyIENvbXBpbGFibGVCbG9jayA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENvbXBpbGFibGVCbG9jayhjb21waWxlciwgcGFyc2VkKSB7CiAgICAgIHRoaXMuY29tcGlsZXIgPSBjb21waWxlcjsKICAgICAgdGhpcy5wYXJzZWQgPSBwYXJzZWQ7CiAgICAgIHRoaXMuY29tcGlsZWQgPSBudWxsOwogICAgfQoKICAgIHZhciBfcHJvdG81ID0gQ29tcGlsYWJsZUJsb2NrLnByb3RvdHlwZTsKCiAgICBfcHJvdG81LmNvbXBpbGUgPSBmdW5jdGlvbiBjb21waWxlKCkgewogICAgICBpZiAodGhpcy5jb21waWxlZCAhPT0gbnVsbCkgcmV0dXJuIHRoaXMuY29tcGlsZWQ7IC8vIFRyYWNrIHRoYXQgY29tcGlsYXRpb24gaGFzIHN0YXJ0ZWQgYnV0IG5vdCB5ZXQgZmluaXNoZWQgYnkgdGVtcG9yYXJpbHkKICAgICAgLy8gdXNpbmcgYSBwbGFjZWhvbGRlciBoYW5kbGUuIEluIGVhZ2VyIGNvbXBpbGF0aW9uIG1vZGUsIHdoZXJlIGNvbXBpbGUoKQogICAgICAvLyBtYXkgYmUgY2FsbGVkIHJlY3Vyc2l2ZWx5LCB3ZSB1c2UgdGhpcyBhcyBhIHNpZ25hbCB0aGF0IHRoZSBoYW5kbGUgY2Fubm90CiAgICAgIC8vIGJlIGtub3duIHN5bmNocm9ub3VzbHkgYW5kIG11c3QgYmUgbGlua2VkIGxhemlseS4KCiAgICAgIHRoaXMuY29tcGlsZWQgPSBQTEFDRUhPTERFUl9IQU5ETEUkMTsKICAgICAgdmFyIF90aGlzJHBhcnNlZCA9IHRoaXMucGFyc2VkLAogICAgICAgICAgc3RhdGVtZW50cyA9IF90aGlzJHBhcnNlZC5ibG9jay5zdGF0ZW1lbnRzLAogICAgICAgICAgY29udGFpbmluZ0xheW91dCA9IF90aGlzJHBhcnNlZC5jb250YWluaW5nTGF5b3V0OwogICAgICByZXR1cm4gdGhpcy5jb21waWxlZCA9IHRoaXMuY29tcGlsZXIuYWRkKHN0YXRlbWVudHMsIGNvbnRhaW5pbmdMYXlvdXQpOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKENvbXBpbGFibGVCbG9jaywgW3sKICAgICAga2V5OiAic3ltYm9sVGFibGUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5wYXJzZWQuYmxvY2s7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBDb21waWxhYmxlQmxvY2s7CiAgfSgpOwoKICBfZXhwb3J0cy5Db21waWxhYmxlQmxvY2sgPSBDb21waWxhYmxlQmxvY2s7CgogIGZ1bmN0aW9uIGNvbXBpbGUoc3RhdGVtZW50cywgYnVpbGRlciwgY29tcGlsZXIpIHsKICAgIHZhciBzQ29tcGlsZXIgPSBzdGF0ZW1lbnRDb21waWxlcigpOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RhdGVtZW50cy5sZW5ndGg7IGkrKykgewogICAgICBzQ29tcGlsZXIuY29tcGlsZShzdGF0ZW1lbnRzW2ldLCBidWlsZGVyKTsKICAgIH0KCiAgICB2YXIgaGFuZGxlID0gYnVpbGRlci5jb21taXQoKTsKICAgIHJldHVybiBoYW5kbGU7CiAgfQoKICBmdW5jdGlvbiBkZWJ1Z1NsaWNlKHByb2dyYW0sIHN0YXJ0LCBlbmQpIHt9CgogIGZ1bmN0aW9uIGxvZ09wY29kZSh0eXBlLCBwYXJhbXMpIHsKICAgIHZhciBvdXQgPSB0eXBlOwoKICAgIGlmIChwYXJhbXMpIHsKICAgICAgdmFyIGFyZ3MgPSBPYmplY3Qua2V5cyhwYXJhbXMpLm1hcChmdW5jdGlvbiAocCkgewogICAgICAgIHJldHVybiAiICIgKyBwICsgIj0iICsganNvbihwYXJhbXNbcF0pOwogICAgICB9KS5qb2luKCcnKTsKICAgICAgb3V0ICs9IGFyZ3M7CiAgICB9CgogICAgcmV0dXJuICIoIiArIG91dCArICIpIjsKICB9CgogIGZ1bmN0aW9uIGpzb24ocGFyYW0pIHt9CgogIGZ1bmN0aW9uIGRlYnVnKHBvcywgYywgb3ApIHsKICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBvcGVyYW5kcyA9IG5ldyBBcnJheShfbGVuID4gMyA/IF9sZW4gLSAzIDogMCksIF9rZXkgPSAzOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgIG9wZXJhbmRzW19rZXkgLSAzXSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgIH0KCiAgICB2YXIgbWV0YWRhdGEgPSBudWxsOwoKICAgIGlmICghbWV0YWRhdGEpIHsKICAgICAgdGhyb3cgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiTWlzc2luZyBPcGNvZGUgTWV0YWRhdGEgZm9yICIgKyBvcCk7CiAgICB9CgogICAgdmFyIG91dCA9ICgwLCBfdXRpbC5kaWN0KSgpOwogICAgbWV0YWRhdGEub3BzLmZvckVhY2goZnVuY3Rpb24gKG9wZXJhbmQsIGluZGV4KSB7CiAgICAgIHZhciBvcCA9IG9wZXJhbmRzW2luZGV4XTsKCiAgICAgIHN3aXRjaCAob3BlcmFuZC50eXBlKSB7CiAgICAgICAgY2FzZSAndG8nOgogICAgICAgICAgb3V0W29wZXJhbmQubmFtZV0gPSBwb3MgKyBvcDsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICdpMzInOgogICAgICAgIGNhc2UgJ3N5bWJvbCc6CiAgICAgICAgY2FzZSAnYmxvY2snOgogICAgICAgICAgb3V0W29wZXJhbmQubmFtZV0gPSBvcDsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICdoYW5kbGUnOgogICAgICAgICAgb3V0W29wZXJhbmQubmFtZV0gPSBjLnJlc29sdmVIYW5kbGUob3ApOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ3N0cic6CiAgICAgICAgICBvdXRbb3BlcmFuZC5uYW1lXSA9IGMuZ2V0U3RyaW5nKG9wKTsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICdvcHRpb24tc3RyJzoKICAgICAgICAgIG91dFtvcGVyYW5kLm5hbWVdID0gb3AgPyBjLmdldFN0cmluZyhvcCkgOiBudWxsOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ3N0ci1hcnJheSc6CiAgICAgICAgICBvdXRbb3BlcmFuZC5uYW1lXSA9IGMuZ2V0U3RyaW5nQXJyYXkob3ApOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ2FycmF5JzoKICAgICAgICAgIG91dFtvcGVyYW5kLm5hbWVdID0gYy5nZXRBcnJheShvcCk7CiAgICAgICAgICBicmVhazsKCiAgICAgICAgY2FzZSAnYm9vbCc6CiAgICAgICAgICBvdXRbb3BlcmFuZC5uYW1lXSA9ICEhb3A7CiAgICAgICAgICBicmVhazsKCiAgICAgICAgY2FzZSAncHJpbWl0aXZlJzoKICAgICAgICAgIG91dFtvcGVyYW5kLm5hbWVdID0gZGVjb2RlUHJpbWl0aXZlKG9wLCBjKTsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICdyZWdpc3Rlcic6CiAgICAgICAgICBvdXRbb3BlcmFuZC5uYW1lXSA9IF92bS5SZWdpc3RlcltvcF07CiAgICAgICAgICBicmVhazsKCiAgICAgICAgY2FzZSAnc2VyaWFsaXphYmxlJzoKICAgICAgICAgIG91dFtvcGVyYW5kLm5hbWVdID0gYy5nZXRTZXJpYWxpemFibGUob3ApOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ2xhenktY29uc3RhbnQnOgogICAgICAgICAgb3V0W29wZXJhbmQubmFtZV0gPSBjLmdldE90aGVyKG9wKTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9KTsKICAgIHJldHVybiBbbWV0YWRhdGEubmFtZSwgb3V0XTsKICB9CgogIGZ1bmN0aW9uIGRlY29kZVByaW1pdGl2ZShwcmltaXRpdmUsIGNvbnN0YW50cykgewogICAgdmFyIGZsYWcgPSBwcmltaXRpdmUgJiA3OyAvLyAxMTEKCiAgICB2YXIgdmFsdWUgPSBwcmltaXRpdmUgPj4gMzsKCiAgICBzd2l0Y2ggKGZsYWcpIHsKICAgICAgY2FzZSAwCiAgICAgIC8qIE5VTUJFUiAqLwogICAgICA6CiAgICAgICAgcmV0dXJuIHZhbHVlOwoKICAgICAgY2FzZSAxCiAgICAgIC8qIEZMT0FUICovCiAgICAgIDoKICAgICAgICByZXR1cm4gY29uc3RhbnRzLmdldE51bWJlcih2YWx1ZSk7CgogICAgICBjYXNlIDIKICAgICAgLyogU1RSSU5HICovCiAgICAgIDoKICAgICAgICByZXR1cm4gY29uc3RhbnRzLmdldFN0cmluZyh2YWx1ZSk7CgogICAgICBjYXNlIDMKICAgICAgLyogQk9PTEVBTl9PUl9WT0lEICovCiAgICAgIDoKICAgICAgICBzd2l0Y2ggKHZhbHVlKSB7CiAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKCiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHJldHVybiB0cnVlOwoKICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgcmV0dXJuIG51bGw7CgogICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgICAgIH0KCiAgICAgIGNhc2UgNAogICAgICAvKiBORUdBVElWRSAqLwogICAgICA6CiAgICAgIGNhc2UgNQogICAgICAvKiBCSUdfTlVNICovCiAgICAgIDoKICAgICAgICByZXR1cm4gY29uc3RhbnRzLmdldE51bWJlcih2YWx1ZSk7CgogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoKTsKICAgIH0KICB9CgogIHZhciBTdGRMaWIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBTdGRMaWIobWFpbiwgdHJ1c3RpbmdHdWFyZGVkQXBwZW5kLCBjYXV0aW91c0d1YXJkZWRBcHBlbmQpIHsKICAgICAgdGhpcy5tYWluID0gbWFpbjsKICAgICAgdGhpcy50cnVzdGluZ0d1YXJkZWRBcHBlbmQgPSB0cnVzdGluZ0d1YXJkZWRBcHBlbmQ7CiAgICAgIHRoaXMuY2F1dGlvdXNHdWFyZGVkQXBwZW5kID0gY2F1dGlvdXNHdWFyZGVkQXBwZW5kOwogICAgfQoKICAgIFN0ZExpYi5jb21waWxlID0gZnVuY3Rpb24gY29tcGlsZShjb21waWxlcikgewogICAgICB2YXIgbWFpbiA9IHRoaXMuc3RkKGNvbXBpbGVyLCBmdW5jdGlvbiAoYikgewogICAgICAgIHJldHVybiBiLm1haW4oKTsKICAgICAgfSk7CiAgICAgIHZhciB0cnVzdGluZ0d1YXJkZWRBcHBlbmQgPSB0aGlzLnN0ZChjb21waWxlciwgZnVuY3Rpb24gKGIpIHsKICAgICAgICByZXR1cm4gYi5zdGRBcHBlbmQodHJ1ZSk7CiAgICAgIH0pOwogICAgICB2YXIgY2F1dGlvdXNHdWFyZGVkQXBwZW5kID0gdGhpcy5zdGQoY29tcGlsZXIsIGZ1bmN0aW9uIChiKSB7CiAgICAgICAgcmV0dXJuIGIuc3RkQXBwZW5kKGZhbHNlKTsKICAgICAgfSk7CiAgICAgIHJldHVybiBuZXcgU3RkTGliKG1haW4sIHRydXN0aW5nR3VhcmRlZEFwcGVuZCwgY2F1dGlvdXNHdWFyZGVkQXBwZW5kKTsKICAgIH07CgogICAgU3RkTGliLnN0ZCA9IGZ1bmN0aW9uIHN0ZChjb21waWxlciwgY2FsbGJhY2spIHsKICAgICAgcmV0dXJuIFN0ZE9wY29kZUJ1aWxkZXIuYnVpbGQoY29tcGlsZXIsIGNhbGxiYWNrKTsKICAgIH07CgogICAgdmFyIF9wcm90bzYgPSBTdGRMaWIucHJvdG90eXBlOwoKICAgIF9wcm90bzYuZ2V0QXBwZW5kID0gZnVuY3Rpb24gZ2V0QXBwZW5kKHRydXN0aW5nKSB7CiAgICAgIHJldHVybiB0cnVzdGluZyA/IHRoaXMudHJ1c3RpbmdHdWFyZGVkQXBwZW5kIDogdGhpcy5jYXV0aW91c0d1YXJkZWRBcHBlbmQ7CiAgICB9OwoKICAgIHJldHVybiBTdGRMaWI7CiAgfSgpOwoKICB2YXIgQWJzdHJhY3RDb21waWxlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEFic3RyYWN0Q29tcGlsZXIobWFjcm9zLCBwcm9ncmFtLCByZXNvbHZlcikgewogICAgICB0aGlzLm1hY3JvcyA9IG1hY3JvczsKICAgICAgdGhpcy5wcm9ncmFtID0gcHJvZ3JhbTsKICAgICAgdGhpcy5yZXNvbHZlciA9IHJlc29sdmVyOwogICAgICB0aGlzLmluaXRpYWxpemUoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNyA9IEFic3RyYWN0Q29tcGlsZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzcuaW5pdGlhbGl6ZSA9IGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7CiAgICAgIHRoaXMuc3RkTGliID0gU3RkTGliLmNvbXBpbGUodGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzcuY29tcGlsZUlubGluZSA9IGZ1bmN0aW9uIGNvbXBpbGVJbmxpbmUoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgaW5saW5lcyA9IHRoaXMubWFjcm9zLmlubGluZXM7CiAgICAgIHJldHVybiBpbmxpbmVzLmNvbXBpbGUoc2V4cCwgYnVpbGRlcik7CiAgICB9OwoKICAgIF9wcm90bzcuY29tcGlsZUJsb2NrID0gZnVuY3Rpb24gY29tcGlsZUJsb2NrKG5hbWUsIHBhcmFtcywgaGFzaCwgdGVtcGxhdGUsIGludmVyc2UsIGJ1aWxkZXIpIHsKICAgICAgdmFyIGJsb2NrcyA9IHRoaXMubWFjcm9zLmJsb2NrczsKICAgICAgYmxvY2tzLmNvbXBpbGUobmFtZSwgcGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZSwgaW52ZXJzZSwgYnVpbGRlcik7CiAgICB9OwoKICAgIF9wcm90bzcuYWRkID0gZnVuY3Rpb24gYWRkKHN0YXRlbWVudHMsIGNvbnRhaW5pbmdMYXlvdXQpIHsKICAgICAgcmV0dXJuIGNvbXBpbGUoc3RhdGVtZW50cywgdGhpcy5idWlsZGVyRm9yKGNvbnRhaW5pbmdMYXlvdXQpLCB0aGlzKTsKICAgIH07CgogICAgX3Byb3RvNy5jb21taXQgPSBmdW5jdGlvbiBjb21taXQoc2NvcGVTaXplLCBidWZmZXIpIHsKICAgICAgdmFyIGhlYXAgPSB0aGlzLnByb2dyYW0uaGVhcDsgLy8gVE9ETzogY2hhbmdlIHRoZSB3aG9sZSBtYWxsb2MgQVBJIGFuZCBkbyBzb21ldGhpbmcgbW9yZSBlZmZpY2llbnQKCiAgICAgIHZhciBoYW5kbGUgPSBoZWFwLm1hbGxvYygpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBidWZmZXIubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgdmFsdWUgPSBidWZmZXJbaV07CgogICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIGhlYXAucHVzaFBsYWNlaG9sZGVyKHZhbHVlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaGVhcC5wdXNoKHZhbHVlKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGhlYXAuZmluaXNoTWFsbG9jKGhhbmRsZSwgc2NvcGVTaXplKTsKICAgICAgcmV0dXJuIGhhbmRsZTsKICAgIH07CgogICAgX3Byb3RvNy5yZXNvbHZlTGF5b3V0Rm9yVGFnID0gZnVuY3Rpb24gcmVzb2x2ZUxheW91dEZvclRhZyh0YWcsIHJlZmVycmVyKSB7CiAgICAgIHZhciByZXNvbHZlciA9IHRoaXMucmVzb2x2ZXI7CiAgICAgIHZhciBoYW5kbGUgPSByZXNvbHZlci5sb29rdXBDb21wb25lbnREZWZpbml0aW9uKHRhZywgcmVmZXJyZXIpOwogICAgICBpZiAoaGFuZGxlID09PSBudWxsKSByZXR1cm4gewogICAgICAgIGhhbmRsZTogbnVsbCwKICAgICAgICBjYXBhYmlsaXRpZXM6IG51bGwsCiAgICAgICAgY29tcGlsYWJsZTogbnVsbAogICAgICB9OwogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlTGF5b3V0Rm9ySGFuZGxlKGhhbmRsZSk7CiAgICB9OwoKICAgIF9wcm90bzcucmVzb2x2ZUxheW91dEZvckhhbmRsZSA9IGZ1bmN0aW9uIHJlc29sdmVMYXlvdXRGb3JIYW5kbGUoaGFuZGxlKSB7CiAgICAgIHZhciByZXNvbHZlciA9IHRoaXMucmVzb2x2ZXI7CiAgICAgIHZhciBjYXBhYmlsaXRpZXMgPSByZXNvbHZlci5nZXRDYXBhYmlsaXRpZXMoaGFuZGxlKTsKICAgICAgdmFyIGNvbXBpbGFibGUgPSBudWxsOwoKICAgICAgaWYgKCFjYXBhYmlsaXRpZXMuZHluYW1pY0xheW91dCkgewogICAgICAgIGNvbXBpbGFibGUgPSByZXNvbHZlci5nZXRMYXlvdXQoaGFuZGxlKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHsKICAgICAgICBoYW5kbGU6IGhhbmRsZSwKICAgICAgICBjYXBhYmlsaXRpZXM6IGNhcGFiaWxpdGllcywKICAgICAgICBjb21waWxhYmxlOiBjb21waWxhYmxlCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzcucmVzb2x2ZU1vZGlmaWVyID0gZnVuY3Rpb24gcmVzb2x2ZU1vZGlmaWVyKG5hbWUsIHJlZmVycmVyKSB7CiAgICAgIHJldHVybiB0aGlzLnJlc29sdmVyLmxvb2t1cE1vZGlmaWVyKG5hbWUsIHJlZmVycmVyKTsKICAgIH07CgogICAgX3Byb3RvNy5yZXNvbHZlSGVscGVyID0gZnVuY3Rpb24gcmVzb2x2ZUhlbHBlcihuYW1lLCByZWZlcnJlcikgewogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlci5sb29rdXBIZWxwZXIobmFtZSwgcmVmZXJyZXIpOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKEFic3RyYWN0Q29tcGlsZXIsIFt7CiAgICAgIGtleTogImNvbnN0YW50cyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLnByb2dyYW0uY29uc3RhbnRzOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gQWJzdHJhY3RDb21waWxlcjsKICB9KCk7CgogIF9leHBvcnRzLkFic3RyYWN0Q29tcGlsZXIgPSBBYnN0cmFjdENvbXBpbGVyOwogIHZhciBkZWJ1Z0NvbXBpbGVyOwogIF9leHBvcnRzLmRlYnVnQ29tcGlsZXIgPSBkZWJ1Z0NvbXBpbGVyOwoKICB2YXIgV3JhcHBlZEJ1aWxkZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBXcmFwcGVkQnVpbGRlcihjb21waWxlciwgbGF5b3V0KSB7CiAgICAgIHRoaXMuY29tcGlsZXIgPSBjb21waWxlcjsKICAgICAgdGhpcy5sYXlvdXQgPSBsYXlvdXQ7CiAgICAgIHRoaXMuY29tcGlsZWQgPSBudWxsOwogICAgICB2YXIgYmxvY2sgPSBsYXlvdXQuYmxvY2s7CiAgICAgIHZhciBzeW1ib2xzID0gYmxvY2suc3ltYm9scy5zbGljZSgpOyAvLyBlbnN1cmUgQVRUUlNfQkxPQ0sgaXMgYWx3YXlzIGluY2x1ZGVkIChvbmx5IG9uY2UpIGluIHRoZSBsaXN0IG9mIHN5bWJvbHMKCiAgICAgIHZhciBhdHRyc0Jsb2NrSW5kZXggPSBzeW1ib2xzLmluZGV4T2YoQVRUUlNfQkxPQ0spOwoKICAgICAgaWYgKGF0dHJzQmxvY2tJbmRleCA9PT0gLTEpIHsKICAgICAgICB0aGlzLmF0dHJzQmxvY2tOdW1iZXIgPSBzeW1ib2xzLnB1c2goQVRUUlNfQkxPQ0spOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuYXR0cnNCbG9ja051bWJlciA9IGF0dHJzQmxvY2tJbmRleCArIDE7CiAgICAgIH0KCiAgICAgIHRoaXMuc3ltYm9sVGFibGUgPSB7CiAgICAgICAgaGFzRXZhbDogYmxvY2suaGFzRXZhbCwKICAgICAgICBzeW1ib2xzOiBzeW1ib2xzCiAgICAgIH07CiAgICB9CgogICAgdmFyIF9wcm90bzggPSBXcmFwcGVkQnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvOC5jb21waWxlID0gZnVuY3Rpb24gY29tcGlsZSgpIHsKICAgICAgaWYgKHRoaXMuY29tcGlsZWQgIT09IG51bGwpIHJldHVybiB0aGlzLmNvbXBpbGVkOyAvLz09PT09PT09RFlOQU1JQwogICAgICAvLyAgICAgICAgUHV0VmFsdWUoVGFnRXhwcikKICAgICAgLy8gICAgICAgIFRlc3QKICAgICAgLy8gICAgICAgIEp1bXBVbmxlc3MoQk9EWSkKICAgICAgLy8gICAgICAgIFB1dENvbXBvbmVudE9wZXJhdGlvbnMKICAgICAgLy8gICAgICAgIE9wZW5EeW5hbWljUHJpbWl0aXZlRWxlbWVudAogICAgICAvLyAgICAgICAgRGlkQ3JlYXRlRWxlbWVudAogICAgICAvLyAgICAgICAgLi4uYXR0ciBzdGF0ZW1lbnRzLi4uCiAgICAgIC8vICAgICAgICBGbHVzaEVsZW1lbnQKICAgICAgLy8gQk9EWTogIE5vb3AKICAgICAgLy8gICAgICAgIC4uLmJvZHkgc3RhdGVtZW50cy4uLgogICAgICAvLyAgICAgICAgUHV0VmFsdWUoVGFnRXhwcikKICAgICAgLy8gICAgICAgIFRlc3QKICAgICAgLy8gICAgICAgIEp1bXBVbmxlc3MoRU5EKQogICAgICAvLyAgICAgICAgQ2xvc2VFbGVtZW50CiAgICAgIC8vIEVORDogICBOb29wCiAgICAgIC8vICAgICAgICBEaWRSZW5kZXJMYXlvdXQKICAgICAgLy8gICAgICAgIEV4aXQKICAgICAgLy8KICAgICAgLy89PT09PT09PVNUQVRJQwogICAgICAvLyAgICAgICAgT3BlblByaW1pdGl2ZUVsZW1lbnRPcGNvZGUKICAgICAgLy8gICAgICAgIERpZENyZWF0ZUVsZW1lbnQKICAgICAgLy8gICAgICAgIC4uLmF0dHIgc3RhdGVtZW50cy4uLgogICAgICAvLyAgICAgICAgRmx1c2hFbGVtZW50CiAgICAgIC8vICAgICAgICAuLi5ib2R5IHN0YXRlbWVudHMuLi4KICAgICAgLy8gICAgICAgIENsb3NlRWxlbWVudAogICAgICAvLyAgICAgICAgRGlkUmVuZGVyTGF5b3V0CiAgICAgIC8vICAgICAgICBFeGl0CgogICAgICB2YXIgY29tcGlsZXIgPSB0aGlzLmNvbXBpbGVyLAogICAgICAgICAgbGF5b3V0ID0gdGhpcy5sYXlvdXQ7CiAgICAgIHZhciBiID0gY29tcGlsZXIuYnVpbGRlckZvcihsYXlvdXQpOwogICAgICBiLnN0YXJ0TGFiZWxzKCk7CiAgICAgIGIuZmV0Y2goX3ZtLlJlZ2lzdGVyLnMxKTsKICAgICAgYi5nZXRDb21wb25lbnRUYWdOYW1lKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIGIucHJpbWl0aXZlUmVmZXJlbmNlKCk7CiAgICAgIGIuZHVwKCk7CiAgICAgIGIubG9hZChfdm0uUmVnaXN0ZXIuczEpOwogICAgICBiLmp1bXBVbmxlc3MoJ0JPRFknKTsKICAgICAgYi5mZXRjaChfdm0uUmVnaXN0ZXIuczEpOwogICAgICBiLnB1dENvbXBvbmVudE9wZXJhdGlvbnMoKTsKICAgICAgYi5vcGVuRHluYW1pY0VsZW1lbnQoKTsKICAgICAgYi5kaWRDcmVhdGVFbGVtZW50KF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIGIueWllbGQodGhpcy5hdHRyc0Jsb2NrTnVtYmVyLCBbXSk7CiAgICAgIGIuZmx1c2hFbGVtZW50KCk7CiAgICAgIGIubGFiZWwoJ0JPRFknKTsKICAgICAgYi5pbnZva2VTdGF0aWNCbG9jayhibG9ja0ZvcihsYXlvdXQsIGNvbXBpbGVyKSk7CiAgICAgIGIuZmV0Y2goX3ZtLlJlZ2lzdGVyLnMxKTsKICAgICAgYi5qdW1wVW5sZXNzKCdFTkQnKTsKICAgICAgYi5jbG9zZUVsZW1lbnQoKTsKICAgICAgYi5sYWJlbCgnRU5EJyk7CiAgICAgIGIubG9hZChfdm0uUmVnaXN0ZXIuczEpOwogICAgICBiLnN0b3BMYWJlbHMoKTsKICAgICAgdmFyIGhhbmRsZSA9IGIuY29tbWl0KCk7CiAgICAgIHJldHVybiB0aGlzLmNvbXBpbGVkID0gaGFuZGxlOwogICAgfTsKCiAgICByZXR1cm4gV3JhcHBlZEJ1aWxkZXI7CiAgfSgpOwoKICBfZXhwb3J0cy5XcmFwcGVkQnVpbGRlciA9IFdyYXBwZWRCdWlsZGVyOwoKICBmdW5jdGlvbiBibG9ja0ZvcihsYXlvdXQsIGNvbXBpbGVyKSB7CiAgICByZXR1cm4gbmV3IENvbXBpbGFibGVCbG9jayhjb21waWxlciwgewogICAgICBibG9jazogewogICAgICAgIHN0YXRlbWVudHM6IGxheW91dC5ibG9jay5zdGF0ZW1lbnRzLAogICAgICAgIHBhcmFtZXRlcnM6IF91dGlsLkVNUFRZX0FSUkFZCiAgICAgIH0sCiAgICAgIGNvbnRhaW5pbmdMYXlvdXQ6IGxheW91dAogICAgfSk7CiAgfQoKICB2YXIgQ29tcG9uZW50QnVpbGRlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENvbXBvbmVudEJ1aWxkZXIoYnVpbGRlcikgewogICAgICB0aGlzLmJ1aWxkZXIgPSBidWlsZGVyOwogICAgfQoKICAgIHZhciBfcHJvdG85ID0gQ29tcG9uZW50QnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvOS5zdGF0aWMgPSBmdW5jdGlvbiBfc3RhdGljKGhhbmRsZSwgYXJncykgewogICAgICB2YXIgcGFyYW1zID0gYXJnc1swXSwKICAgICAgICAgIGhhc2ggPSBhcmdzWzFdLAogICAgICAgICAgX2RlZmF1bHQgPSBhcmdzWzJdLAogICAgICAgICAgaW52ZXJzZSA9IGFyZ3NbM107CiAgICAgIHZhciBidWlsZGVyID0gdGhpcy5idWlsZGVyOwoKICAgICAgaWYgKGhhbmRsZSAhPT0gbnVsbCkgewogICAgICAgIHZhciBfYnVpbGRlciRjb21waWxlciRyZXMyID0gYnVpbGRlci5jb21waWxlci5yZXNvbHZlTGF5b3V0Rm9ySGFuZGxlKGhhbmRsZSksCiAgICAgICAgICAgIGNhcGFiaWxpdGllcyA9IF9idWlsZGVyJGNvbXBpbGVyJHJlczIuY2FwYWJpbGl0aWVzLAogICAgICAgICAgICBjb21waWxhYmxlID0gX2J1aWxkZXIkY29tcGlsZXIkcmVzMi5jb21waWxhYmxlOwoKICAgICAgICBpZiAoY29tcGlsYWJsZSkgewogICAgICAgICAgYnVpbGRlci5wdXNoQ29tcG9uZW50RGVmaW5pdGlvbihoYW5kbGUpOwogICAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNDb21wb25lbnQoY2FwYWJpbGl0aWVzLCBjb21waWxhYmxlLCBudWxsLCBwYXJhbXMsIGhhc2gsIGZhbHNlLCBfZGVmYXVsdCwgaW52ZXJzZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGJ1aWxkZXIucHVzaENvbXBvbmVudERlZmluaXRpb24oaGFuZGxlKTsKICAgICAgICAgIGJ1aWxkZXIuaW52b2tlQ29tcG9uZW50KGNhcGFiaWxpdGllcywgbnVsbCwgcGFyYW1zLCBoYXNoLCBmYWxzZSwgX2RlZmF1bHQsIGludmVyc2UpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gQ29tcG9uZW50QnVpbGRlcjsKICB9KCk7CgogIHZhciBMYWJlbHMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBMYWJlbHMoKSB7CiAgICAgIHRoaXMubGFiZWxzID0gKDAsIF91dGlsLmRpY3QpKCk7CiAgICAgIHRoaXMudGFyZ2V0cyA9IFtdOwogICAgfQoKICAgIHZhciBfcHJvdG8xMCA9IExhYmVscy5wcm90b3R5cGU7CgogICAgX3Byb3RvMTAubGFiZWwgPSBmdW5jdGlvbiBsYWJlbChuYW1lLCBpbmRleCkgewogICAgICB0aGlzLmxhYmVsc1tuYW1lXSA9IGluZGV4OwogICAgfTsKCiAgICBfcHJvdG8xMC50YXJnZXQgPSBmdW5jdGlvbiB0YXJnZXQoYXQsIF90YXJnZXQpIHsKICAgICAgdGhpcy50YXJnZXRzLnB1c2goewogICAgICAgIGF0OiBhdCwKICAgICAgICB0YXJnZXQ6IF90YXJnZXQKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90bzEwLnBhdGNoID0gZnVuY3Rpb24gcGF0Y2goZW5jb2RlcikgewogICAgICB2YXIgdGFyZ2V0cyA9IHRoaXMudGFyZ2V0cywKICAgICAgICAgIGxhYmVscyA9IHRoaXMubGFiZWxzOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0YXJnZXRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIF90YXJnZXRzJGkgPSB0YXJnZXRzW2ldLAogICAgICAgICAgICBhdCA9IF90YXJnZXRzJGkuYXQsCiAgICAgICAgICAgIHRhcmdldCA9IF90YXJnZXRzJGkudGFyZ2V0OwogICAgICAgIHZhciBhZGRyZXNzID0gbGFiZWxzW3RhcmdldF0gLSBhdDsKICAgICAgICBlbmNvZGVyLnBhdGNoKGF0LCBhZGRyZXNzKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gTGFiZWxzOwogIH0oKTsKCiAgdmFyIFN0ZE9wY29kZUJ1aWxkZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBTdGRPcGNvZGVCdWlsZGVyKGNvbXBpbGVyLCBzaXplKSB7CiAgICAgIGlmIChzaXplID09PSB2b2lkIDApIHsKICAgICAgICBzaXplID0gMDsKICAgICAgfQoKICAgICAgdGhpcy5zaXplID0gc2l6ZTsKICAgICAgdGhpcy5lbmNvZGVyID0gbmV3IF9lbmNvZGVyLkluc3RydWN0aW9uRW5jb2RlcihbXSk7CiAgICAgIHRoaXMubGFiZWxzU3RhY2sgPSBuZXcgX3V0aWwuU3RhY2soKTsKICAgICAgdGhpcy5jb21waWxlciA9IGNvbXBpbGVyOwogICAgfQoKICAgIFN0ZE9wY29kZUJ1aWxkZXIuYnVpbGQgPSBmdW5jdGlvbiBidWlsZChjb21waWxlciwgY2FsbGJhY2spIHsKICAgICAgdmFyIGJ1aWxkZXIgPSBuZXcgU3RkT3Bjb2RlQnVpbGRlcihjb21waWxlcik7CiAgICAgIGNhbGxiYWNrKGJ1aWxkZXIpOwogICAgICByZXR1cm4gYnVpbGRlci5jb21taXQoKTsKICAgIH07CgogICAgdmFyIF9wcm90bzExID0gU3RkT3Bjb2RlQnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMTEucHVzaCA9IGZ1bmN0aW9uIHB1c2gobmFtZSkgewogICAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGVyLmVuY29kZShuYW1lLCAwKTsKCiAgICAgICAgY2FzZSAyOgogICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2Rlci5lbmNvZGUobmFtZSwgMCwgYXJndW1lbnRzWzFdKTsKCiAgICAgICAgY2FzZSAzOgogICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2Rlci5lbmNvZGUobmFtZSwgMCwgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0pOwoKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2Rlci5lbmNvZGUobmFtZSwgMCwgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTEucHVzaE1hY2hpbmUgPSBmdW5jdGlvbiBwdXNoTWFjaGluZShuYW1lKSB7CiAgICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkgewogICAgICAgIGNhc2UgMToKICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZXIuZW5jb2RlKG5hbWUsIDEwMjQKICAgICAgICAgIC8qIE1BQ0hJTkVfTUFTSyAqLwogICAgICAgICAgKTsKCiAgICAgICAgY2FzZSAyOgogICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2Rlci5lbmNvZGUobmFtZSwgMTAyNAogICAgICAgICAgLyogTUFDSElORV9NQVNLICovCiAgICAgICAgICAsIGFyZ3VtZW50c1sxXSk7CgogICAgICAgIGNhc2UgMzoKICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZXIuZW5jb2RlKG5hbWUsIDEwMjQKICAgICAgICAgIC8qIE1BQ0hJTkVfTUFTSyAqLwogICAgICAgICAgLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSk7CgogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGVyLmVuY29kZShuYW1lLCAxMDI0CiAgICAgICAgICAvKiBNQUNISU5FX01BU0sgKi8KICAgICAgICAgICwgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTEuY29tbWl0ID0gZnVuY3Rpb24gY29tbWl0KCkgewogICAgICB0aGlzLnB1c2hNYWNoaW5lKDI0CiAgICAgIC8qIFJldHVybiAqLwogICAgICApOwogICAgICByZXR1cm4gdGhpcy5jb21waWxlci5jb21taXQodGhpcy5zaXplLCB0aGlzLmVuY29kZXIuYnVmZmVyKTsKICAgIH07CgogICAgX3Byb3RvMTEucmVzZXJ2ZSA9IGZ1bmN0aW9uIHJlc2VydmUobmFtZSkgewogICAgICB0aGlzLmVuY29kZXIuZW5jb2RlKG5hbWUsIDAsIC0xKTsKICAgIH07CgogICAgX3Byb3RvMTEucmVzZXJ2ZVdpdGhPcGVyYW5kID0gZnVuY3Rpb24gcmVzZXJ2ZVdpdGhPcGVyYW5kKG5hbWUsIG9wZXJhbmQpIHsKICAgICAgdGhpcy5lbmNvZGVyLmVuY29kZShuYW1lLCAwLCAtMSwgb3BlcmFuZCk7CiAgICB9OwoKICAgIF9wcm90bzExLnJlc2VydmVNYWNoaW5lID0gZnVuY3Rpb24gcmVzZXJ2ZU1hY2hpbmUobmFtZSkgewogICAgICB0aGlzLmVuY29kZXIuZW5jb2RlKG5hbWUsIDEwMjQKICAgICAgLyogTUFDSElORV9NQVNLICovCiAgICAgICwgLTEpOwogICAgfSAvLy8KICAgIDsKCiAgICBfcHJvdG8xMS5tYWluID0gZnVuY3Rpb24gbWFpbigpIHsKICAgICAgdGhpcy5wdXNoKDY4CiAgICAgIC8qIE1haW4gKi8KICAgICAgLCBfdm0uUmVnaXN0ZXIuczApOwogICAgICB0aGlzLmludm9rZVByZXBhcmVkQ29tcG9uZW50KGZhbHNlLCBmYWxzZSwgdHJ1ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLmFwcGVuZEhUTUwgPSBmdW5jdGlvbiBhcHBlbmRIVE1MKCkgewogICAgICB0aGlzLnB1c2goMjgKICAgICAgLyogQXBwZW5kSFRNTCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5hcHBlbmRTYWZlSFRNTCA9IGZ1bmN0aW9uIGFwcGVuZFNhZmVIVE1MKCkgewogICAgICB0aGlzLnB1c2goMjkKICAgICAgLyogQXBwZW5kU2FmZUhUTUwgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuYXBwZW5kRG9jdW1lbnRGcmFnbWVudCA9IGZ1bmN0aW9uIGFwcGVuZERvY3VtZW50RnJhZ21lbnQoKSB7CiAgICAgIHRoaXMucHVzaCgzMAogICAgICAvKiBBcHBlbmREb2N1bWVudEZyYWdtZW50ICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLmFwcGVuZE5vZGUgPSBmdW5jdGlvbiBhcHBlbmROb2RlKCkgewogICAgICB0aGlzLnB1c2goMzEKICAgICAgLyogQXBwZW5kTm9kZSAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5hcHBlbmRUZXh0ID0gZnVuY3Rpb24gYXBwZW5kVGV4dCgpIHsKICAgICAgdGhpcy5wdXNoKDMyCiAgICAgIC8qIEFwcGVuZFRleHQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuYmVnaW5Db21wb25lbnRUcmFuc2FjdGlvbiA9IGZ1bmN0aW9uIGJlZ2luQ29tcG9uZW50VHJhbnNhY3Rpb24oKSB7CiAgICAgIHRoaXMucHVzaCg5MQogICAgICAvKiBCZWdpbkNvbXBvbmVudFRyYW5zYWN0aW9uICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLmNvbW1pdENvbXBvbmVudFRyYW5zYWN0aW9uID0gZnVuY3Rpb24gY29tbWl0Q29tcG9uZW50VHJhbnNhY3Rpb24oKSB7CiAgICAgIHRoaXMucHVzaCg5MgogICAgICAvKiBDb21taXRDb21wb25lbnRUcmFuc2FjdGlvbiAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5wdXNoRHluYW1pY1Njb3BlID0gZnVuY3Rpb24gcHVzaER5bmFtaWNTY29wZSgpIHsKICAgICAgdGhpcy5wdXNoKDQ0CiAgICAgIC8qIFB1c2hEeW5hbWljU2NvcGUgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEucG9wRHluYW1pY1Njb3BlID0gZnVuY3Rpb24gcG9wRHluYW1pY1Njb3BlKCkgewogICAgICB0aGlzLnB1c2goNDUKICAgICAgLyogUG9wRHluYW1pY1Njb3BlICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLnB1c2hSZW1vdGVFbGVtZW50ID0gZnVuY3Rpb24gcHVzaFJlbW90ZUVsZW1lbnQoKSB7CiAgICAgIHRoaXMucHVzaCg0MQogICAgICAvKiBQdXNoUmVtb3RlRWxlbWVudCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5wb3BSZW1vdGVFbGVtZW50ID0gZnVuY3Rpb24gcG9wUmVtb3RlRWxlbWVudCgpIHsKICAgICAgdGhpcy5wdXNoKDQyCiAgICAgIC8qIFBvcFJlbW90ZUVsZW1lbnQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEucHVzaFJvb3RTY29wZSA9IGZ1bmN0aW9uIHB1c2hSb290U2NvcGUoc3ltYm9scywgYmluZENhbGxlclNjb3BlKSB7CiAgICAgIHRoaXMucHVzaCgyMAogICAgICAvKiBSb290U2NvcGUgKi8KICAgICAgLCBzeW1ib2xzLCBiaW5kQ2FsbGVyU2NvcGUgPyAxIDogMCk7CiAgICB9OwoKICAgIF9wcm90bzExLnB1c2hWaXJ0dWFsUm9vdFNjb3BlID0gZnVuY3Rpb24gcHVzaFZpcnR1YWxSb290U2NvcGUocmVnaXN0ZXIpIHsKICAgICAgdGhpcy5wdXNoKDIxCiAgICAgIC8qIFZpcnR1YWxSb290U2NvcGUgKi8KICAgICAgLCByZWdpc3Rlcik7CiAgICB9OwoKICAgIF9wcm90bzExLnB1c2hDaGlsZFNjb3BlID0gZnVuY3Rpb24gcHVzaENoaWxkU2NvcGUoKSB7CiAgICAgIHRoaXMucHVzaCgyMgogICAgICAvKiBDaGlsZFNjb3BlICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLnBvcFNjb3BlID0gZnVuY3Rpb24gcG9wU2NvcGUoKSB7CiAgICAgIHRoaXMucHVzaCgyMwogICAgICAvKiBQb3BTY29wZSAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5wcmVwYXJlQXJncyA9IGZ1bmN0aW9uIHByZXBhcmVBcmdzKHN0YXRlKSB7CiAgICAgIHRoaXMucHVzaCg3OQogICAgICAvKiBQcmVwYXJlQXJncyAqLwogICAgICAsIHN0YXRlKTsKICAgIH07CgogICAgX3Byb3RvMTEuY3JlYXRlQ29tcG9uZW50ID0gZnVuY3Rpb24gY3JlYXRlQ29tcG9uZW50KHN0YXRlLCBoYXNEZWZhdWx0KSB7CiAgICAgIHZhciBmbGFnID0gaGFzRGVmYXVsdCB8IDA7CiAgICAgIHRoaXMucHVzaCg4MQogICAgICAvKiBDcmVhdGVDb21wb25lbnQgKi8KICAgICAgLCBmbGFnLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLnJlZ2lzdGVyQ29tcG9uZW50RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIHJlZ2lzdGVyQ29tcG9uZW50RGVzdHJ1Y3RvcihzdGF0ZSkgewogICAgICB0aGlzLnB1c2goODIKICAgICAgLyogUmVnaXN0ZXJDb21wb25lbnREZXN0cnVjdG9yICovCiAgICAgICwgc3RhdGUpOwogICAgfTsKCiAgICBfcHJvdG8xMS5wdXRDb21wb25lbnRPcGVyYXRpb25zID0gZnVuY3Rpb24gcHV0Q29tcG9uZW50T3BlcmF0aW9ucygpIHsKICAgICAgdGhpcy5wdXNoKDgzCiAgICAgIC8qIFB1dENvbXBvbmVudE9wZXJhdGlvbnMgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuZ2V0Q29tcG9uZW50U2VsZiA9IGZ1bmN0aW9uIGdldENvbXBvbmVudFNlbGYoc3RhdGUpIHsKICAgICAgdGhpcy5wdXNoKDg0CiAgICAgIC8qIEdldENvbXBvbmVudFNlbGYgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLmdldENvbXBvbmVudFRhZ05hbWUgPSBmdW5jdGlvbiBnZXRDb21wb25lbnRUYWdOYW1lKHN0YXRlKSB7CiAgICAgIHRoaXMucHVzaCg4NQogICAgICAvKiBHZXRDb21wb25lbnRUYWdOYW1lICovCiAgICAgICwgc3RhdGUpOwogICAgfTsKCiAgICBfcHJvdG8xMS5nZXRDb21wb25lbnRMYXlvdXQgPSBmdW5jdGlvbiBnZXRDb21wb25lbnRMYXlvdXQoc3RhdGUpIHsKICAgICAgdGhpcy5wdXNoKDg2CiAgICAgIC8qIEdldENvbXBvbmVudExheW91dCAqLwogICAgICAsIHN0YXRlKTsKICAgIH07CgogICAgX3Byb3RvMTEuc2V0dXBGb3JFdmFsID0gZnVuY3Rpb24gc2V0dXBGb3JFdmFsKHN0YXRlKSB7CiAgICAgIHRoaXMucHVzaCg4NwogICAgICAvKiBTZXR1cEZvckV2YWwgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLmludm9rZUNvbXBvbmVudExheW91dCA9IGZ1bmN0aW9uIGludm9rZUNvbXBvbmVudExheW91dChzdGF0ZSkgewogICAgICB0aGlzLnB1c2goOTAKICAgICAgLyogSW52b2tlQ29tcG9uZW50TGF5b3V0ICovCiAgICAgICwgc3RhdGUpOwogICAgfTsKCiAgICBfcHJvdG8xMS5kaWRDcmVhdGVFbGVtZW50ID0gZnVuY3Rpb24gZGlkQ3JlYXRlRWxlbWVudChzdGF0ZSkgewogICAgICB0aGlzLnB1c2goOTMKICAgICAgLyogRGlkQ3JlYXRlRWxlbWVudCAqLwogICAgICAsIHN0YXRlKTsKICAgIH07CgogICAgX3Byb3RvMTEuZGlkUmVuZGVyTGF5b3V0ID0gZnVuY3Rpb24gZGlkUmVuZGVyTGF5b3V0KHN0YXRlKSB7CiAgICAgIHRoaXMucHVzaCg5NAogICAgICAvKiBEaWRSZW5kZXJMYXlvdXQgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLnB1c2hGcmFtZSA9IGZ1bmN0aW9uIHB1c2hGcmFtZSgpIHsKICAgICAgdGhpcy5wdXNoTWFjaGluZSg1NwogICAgICAvKiBQdXNoRnJhbWUgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEucG9wRnJhbWUgPSBmdW5jdGlvbiBwb3BGcmFtZSgpIHsKICAgICAgdGhpcy5wdXNoTWFjaGluZSg1OAogICAgICAvKiBQb3BGcmFtZSAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5wdXNoU21hbGxGcmFtZSA9IGZ1bmN0aW9uIHB1c2hTbWFsbEZyYW1lKCkgewogICAgICB0aGlzLnB1c2hNYWNoaW5lKDU5CiAgICAgIC8qIFB1c2hTbWFsbEZyYW1lICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLnBvcFNtYWxsRnJhbWUgPSBmdW5jdGlvbiBwb3BTbWFsbEZyYW1lKCkgewogICAgICB0aGlzLnB1c2hNYWNoaW5lKDYwCiAgICAgIC8qIFBvcFNtYWxsRnJhbWUgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuaW52b2tlVmlydHVhbCA9IGZ1bmN0aW9uIGludm9rZVZpcnR1YWwoKSB7CiAgICAgIHRoaXMucHVzaE1hY2hpbmUoNDkKICAgICAgLyogSW52b2tlVmlydHVhbCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5pbnZva2VZaWVsZCA9IGZ1bmN0aW9uIGludm9rZVlpZWxkKCkgewogICAgICB0aGlzLnB1c2goNTEKICAgICAgLyogSW52b2tlWWllbGQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEudG9Cb29sZWFuID0gZnVuY3Rpb24gdG9Cb29sZWFuKCkgewogICAgICB0aGlzLnB1c2goNjMKICAgICAgLyogVG9Cb29sZWFuICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLmludm9rZVByZXBhcmVkQ29tcG9uZW50ID0gZnVuY3Rpb24gaW52b2tlUHJlcGFyZWRDb21wb25lbnQoaGFzQmxvY2ssIGJpbmRhYmxlQmxvY2tzLCBiaW5kYWJsZUF0TmFtZXMsIHBvcHVsYXRlTGF5b3V0KSB7CiAgICAgIGlmIChwb3B1bGF0ZUxheW91dCA9PT0gdm9pZCAwKSB7CiAgICAgICAgcG9wdWxhdGVMYXlvdXQgPSBudWxsOwogICAgICB9CgogICAgICB0aGlzLmJlZ2luQ29tcG9uZW50VHJhbnNhY3Rpb24oKTsKICAgICAgdGhpcy5wdXNoRHluYW1pY1Njb3BlKCk7CiAgICAgIHRoaXMuY3JlYXRlQ29tcG9uZW50KF92bS5SZWdpc3Rlci5zMCwgaGFzQmxvY2spOyAvLyB0aGlzIGhhcyB0byBydW4gYWZ0ZXIgY3JlYXRlQ29tcG9uZW50IHRvIGFsbG93CiAgICAgIC8vIGZvciBsYXRlLWJvdW5kIGxheW91dHMsIGJ1dCBhIGNhbGxlciBpcyBmcmVlCiAgICAgIC8vIHRvIHBvcHVsYXRlIHRoZSBsYXlvdXQgZWFybGllciBpZiBpdCB3YW50cyB0bwogICAgICAvLyBhbmQgZG8gbm90aGluZyBoZXJlLgoKICAgICAgaWYgKHBvcHVsYXRlTGF5b3V0KSBwb3B1bGF0ZUxheW91dCgpOwogICAgICB0aGlzLnJlZ2lzdGVyQ29tcG9uZW50RGVzdHJ1Y3Rvcihfdm0uUmVnaXN0ZXIuczApOwogICAgICB0aGlzLmdldENvbXBvbmVudFNlbGYoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5wdXNoVmlydHVhbFJvb3RTY29wZShfdm0uUmVnaXN0ZXIuczApOwogICAgICB0aGlzLnNldFZhcmlhYmxlKDApOwogICAgICB0aGlzLnNldHVwRm9yRXZhbChfdm0uUmVnaXN0ZXIuczApOwogICAgICBpZiAoYmluZGFibGVBdE5hbWVzKSB0aGlzLnNldE5hbWVkVmFyaWFibGVzKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIGlmIChiaW5kYWJsZUJsb2NrcykgdGhpcy5zZXRCbG9ja3MoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5wb3AoKTsKICAgICAgdGhpcy5pbnZva2VDb21wb25lbnRMYXlvdXQoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5kaWRSZW5kZXJMYXlvdXQoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5wb3BGcmFtZSgpOwogICAgICB0aGlzLnBvcFNjb3BlKCk7CiAgICAgIHRoaXMucG9wRHluYW1pY1Njb3BlKCk7CiAgICAgIHRoaXMuY29tbWl0Q29tcG9uZW50VHJhbnNhY3Rpb24oKTsKICAgIH07CgogICAgLy8vCiAgICBfcHJvdG8xMS5jb21waWxlSW5saW5lID0gZnVuY3Rpb24gY29tcGlsZUlubGluZShzZXhwKSB7CiAgICAgIHJldHVybiB0aGlzLmNvbXBpbGVyLmNvbXBpbGVJbmxpbmUoc2V4cCwgdGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzExLmNvbXBpbGVCbG9jayA9IGZ1bmN0aW9uIGNvbXBpbGVCbG9jayhuYW1lLCBwYXJhbXMsIGhhc2gsIHRlbXBsYXRlLCBpbnZlcnNlKSB7CiAgICAgIHRoaXMuY29tcGlsZXIuY29tcGlsZUJsb2NrKG5hbWUsIHBhcmFtcywgaGFzaCwgdGVtcGxhdGUsIGludmVyc2UsIHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG8xMS5sYWJlbCA9IGZ1bmN0aW9uIGxhYmVsKG5hbWUpIHsKICAgICAgdGhpcy5sYWJlbHMubGFiZWwobmFtZSwgdGhpcy5uZXh0UG9zKTsKICAgIH0gLy8gaGVscGVycwogICAgOwoKICAgIF9wcm90bzExLnN0YXJ0TGFiZWxzID0gZnVuY3Rpb24gc3RhcnRMYWJlbHMoKSB7CiAgICAgIHRoaXMubGFiZWxzU3RhY2sucHVzaChuZXcgTGFiZWxzKCkpOwogICAgfTsKCiAgICBfcHJvdG8xMS5zdG9wTGFiZWxzID0gZnVuY3Rpb24gc3RvcExhYmVscygpIHsKICAgICAgdmFyIGxhYmVsID0gdGhpcy5sYWJlbHNTdGFjay5wb3AoKTsKICAgICAgbGFiZWwucGF0Y2godGhpcy5lbmNvZGVyKTsKICAgIH0gLy8gY29tcG9uZW50cwogICAgOwoKICAgIF9wcm90bzExLnB1c2hDdXJyaWVkQ29tcG9uZW50ID0gZnVuY3Rpb24gcHVzaEN1cnJpZWRDb21wb25lbnQoKSB7CiAgICAgIHRoaXMucHVzaCg3NAogICAgICAvKiBQdXNoQ3VycmllZENvbXBvbmVudCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5wdXNoRHluYW1pY0NvbXBvbmVudEluc3RhbmNlID0gZnVuY3Rpb24gcHVzaER5bmFtaWNDb21wb25lbnRJbnN0YW5jZSgpIHsKICAgICAgdGhpcy5wdXNoKDczCiAgICAgIC8qIFB1c2hEeW5hbWljQ29tcG9uZW50SW5zdGFuY2UgKi8KICAgICAgKTsKICAgIH0gLy8gZG9tCiAgICA7CgogICAgX3Byb3RvMTEub3BlbkR5bmFtaWNFbGVtZW50ID0gZnVuY3Rpb24gb3BlbkR5bmFtaWNFbGVtZW50KCkgewogICAgICB0aGlzLnB1c2goMzQKICAgICAgLyogT3BlbkR5bmFtaWNFbGVtZW50ICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLmZsdXNoRWxlbWVudCA9IGZ1bmN0aW9uIGZsdXNoRWxlbWVudCgpIHsKICAgICAgdGhpcy5wdXNoKDM4CiAgICAgIC8qIEZsdXNoRWxlbWVudCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5jbG9zZUVsZW1lbnQgPSBmdW5jdGlvbiBjbG9zZUVsZW1lbnQoKSB7CiAgICAgIHRoaXMucHVzaCgzOQogICAgICAvKiBDbG9zZUVsZW1lbnQgKi8KICAgICAgKTsKICAgIH0gLy8gbGlzdHMKICAgIDsKCiAgICBfcHJvdG8xMS5wdXRJdGVyYXRvciA9IGZ1bmN0aW9uIHB1dEl0ZXJhdG9yKCkgewogICAgICB0aGlzLnB1c2goNjYKICAgICAgLyogUHV0SXRlcmF0b3IgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuZW50ZXJMaXN0ID0gZnVuY3Rpb24gZW50ZXJMaXN0KHN0YXJ0KSB7CiAgICAgIHRoaXMucmVzZXJ2ZSg2NAogICAgICAvKiBFbnRlckxpc3QgKi8KICAgICAgKTsKICAgICAgdGhpcy5sYWJlbHMudGFyZ2V0KHRoaXMucG9zLCBzdGFydCk7CiAgICB9OwoKICAgIF9wcm90bzExLmV4aXRMaXN0ID0gZnVuY3Rpb24gZXhpdExpc3QoKSB7CiAgICAgIHRoaXMucHVzaCg2NQogICAgICAvKiBFeGl0TGlzdCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5pdGVyYXRlID0gZnVuY3Rpb24gaXRlcmF0ZShicmVha3MpIHsKICAgICAgdGhpcy5yZXNlcnZlKDY3CiAgICAgIC8qIEl0ZXJhdGUgKi8KICAgICAgKTsKICAgICAgdGhpcy5sYWJlbHMudGFyZ2V0KHRoaXMucG9zLCBicmVha3MpOwogICAgfSAvLyBleHByZXNzaW9ucwogICAgOwoKICAgIF9wcm90bzExLnNldE5hbWVkVmFyaWFibGVzID0gZnVuY3Rpb24gc2V0TmFtZWRWYXJpYWJsZXMoc3RhdGUpIHsKICAgICAgdGhpcy5wdXNoKDIKICAgICAgLyogU2V0TmFtZWRWYXJpYWJsZXMgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLnNldEJsb2NrcyA9IGZ1bmN0aW9uIHNldEJsb2NrcyhzdGF0ZSkgewogICAgICB0aGlzLnB1c2goMwogICAgICAvKiBTZXRCbG9ja3MgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLnNldFZhcmlhYmxlID0gZnVuY3Rpb24gc2V0VmFyaWFibGUoc3ltYm9sKSB7CiAgICAgIHRoaXMucHVzaCg0CiAgICAgIC8qIFNldFZhcmlhYmxlICovCiAgICAgICwgc3ltYm9sKTsKICAgIH07CgogICAgX3Byb3RvMTEuc2V0QmxvY2sgPSBmdW5jdGlvbiBzZXRCbG9jayhzeW1ib2wpIHsKICAgICAgdGhpcy5wdXNoKDUKICAgICAgLyogU2V0QmxvY2sgKi8KICAgICAgLCBzeW1ib2wpOwogICAgfTsKCiAgICBfcHJvdG8xMS5nZXRWYXJpYWJsZSA9IGZ1bmN0aW9uIGdldFZhcmlhYmxlKHN5bWJvbCkgewogICAgICB0aGlzLnB1c2goNgogICAgICAvKiBHZXRWYXJpYWJsZSAqLwogICAgICAsIHN5bWJvbCk7CiAgICB9OwoKICAgIF9wcm90bzExLmdldEJsb2NrID0gZnVuY3Rpb24gZ2V0QmxvY2soc3ltYm9sKSB7CiAgICAgIHRoaXMucHVzaCg4CiAgICAgIC8qIEdldEJsb2NrICovCiAgICAgICwgc3ltYm9sKTsKICAgIH07CgogICAgX3Byb3RvMTEuaGFzQmxvY2sgPSBmdW5jdGlvbiBoYXNCbG9jayhzeW1ib2wpIHsKICAgICAgdGhpcy5wdXNoKDkKICAgICAgLyogSGFzQmxvY2sgKi8KICAgICAgLCBzeW1ib2wpOwogICAgfTsKCiAgICBfcHJvdG8xMS5jb25jYXQgPSBmdW5jdGlvbiBjb25jYXQoc2l6ZSkgewogICAgICB0aGlzLnB1c2goMTEKICAgICAgLyogQ29uY2F0ICovCiAgICAgICwgc2l6ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLmxvYWQgPSBmdW5jdGlvbiBsb2FkKHJlZ2lzdGVyKSB7CiAgICAgIHRoaXMucHVzaCgxOAogICAgICAvKiBMb2FkICovCiAgICAgICwgcmVnaXN0ZXIpOwogICAgfTsKCiAgICBfcHJvdG8xMS5mZXRjaCA9IGZ1bmN0aW9uIGZldGNoKHJlZ2lzdGVyKSB7CiAgICAgIHRoaXMucHVzaCgxOQogICAgICAvKiBGZXRjaCAqLwogICAgICAsIHJlZ2lzdGVyKTsKICAgIH07CgogICAgX3Byb3RvMTEuZHVwID0gZnVuY3Rpb24gZHVwKHJlZ2lzdGVyLCBvZmZzZXQpIHsKICAgICAgaWYgKHJlZ2lzdGVyID09PSB2b2lkIDApIHsKICAgICAgICByZWdpc3RlciA9IF92bS5SZWdpc3Rlci5zcDsKICAgICAgfQoKICAgICAgaWYgKG9mZnNldCA9PT0gdm9pZCAwKSB7CiAgICAgICAgb2Zmc2V0ID0gMDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMucHVzaCgxNgogICAgICAvKiBEdXAgKi8KICAgICAgLCByZWdpc3Rlciwgb2Zmc2V0KTsKICAgIH07CgogICAgX3Byb3RvMTEucG9wID0gZnVuY3Rpb24gcG9wKGNvdW50KSB7CiAgICAgIGlmIChjb3VudCA9PT0gdm9pZCAwKSB7CiAgICAgICAgY291bnQgPSAxOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5wdXNoKDE3CiAgICAgIC8qIFBvcCAqLwogICAgICAsIGNvdW50KTsKICAgIH0gLy8gdm0KICAgIDsKCiAgICBfcHJvdG8xMS5yZXR1cm5UbyA9IGZ1bmN0aW9uIHJldHVyblRvKGxhYmVsKSB7CiAgICAgIHRoaXMucmVzZXJ2ZU1hY2hpbmUoMjUKICAgICAgLyogUmV0dXJuVG8gKi8KICAgICAgKTsKICAgICAgdGhpcy5sYWJlbHMudGFyZ2V0KHRoaXMucG9zLCBsYWJlbCk7CiAgICB9OwoKICAgIF9wcm90bzExLnByaW1pdGl2ZVJlZmVyZW5jZSA9IGZ1bmN0aW9uIHByaW1pdGl2ZVJlZmVyZW5jZSgpIHsKICAgICAgdGhpcy5wdXNoKDE0CiAgICAgIC8qIFByaW1pdGl2ZVJlZmVyZW5jZSAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5yZWlmeVUzMiA9IGZ1bmN0aW9uIHJlaWZ5VTMyKCkgewogICAgICB0aGlzLnB1c2goMTUKICAgICAgLyogUmVpZnlVMzIgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuZW50ZXIgPSBmdW5jdGlvbiBlbnRlcihhcmdzKSB7CiAgICAgIHRoaXMucHVzaCg2MQogICAgICAvKiBFbnRlciAqLwogICAgICAsIGFyZ3MpOwogICAgfTsKCiAgICBfcHJvdG8xMS5leGl0ID0gZnVuY3Rpb24gZXhpdCgpIHsKICAgICAgdGhpcy5wdXNoKDYyCiAgICAgIC8qIEV4aXQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEucmV0dXJuID0gZnVuY3Rpb24gX3JldHVybigpIHsKICAgICAgdGhpcy5wdXNoTWFjaGluZSgyNAogICAgICAvKiBSZXR1cm4gKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuanVtcCA9IGZ1bmN0aW9uIGp1bXAodGFyZ2V0KSB7CiAgICAgIHRoaXMucmVzZXJ2ZU1hY2hpbmUoNTIKICAgICAgLyogSnVtcCAqLwogICAgICApOwogICAgICB0aGlzLmxhYmVscy50YXJnZXQodGhpcy5wb3MsIHRhcmdldCk7CiAgICB9OwoKICAgIF9wcm90bzExLmp1bXBJZiA9IGZ1bmN0aW9uIGp1bXBJZih0YXJnZXQpIHsKICAgICAgdGhpcy5yZXNlcnZlKDUzCiAgICAgIC8qIEp1bXBJZiAqLwogICAgICApOwogICAgICB0aGlzLmxhYmVscy50YXJnZXQodGhpcy5wb3MsIHRhcmdldCk7CiAgICB9OwoKICAgIF9wcm90bzExLmp1bXBVbmxlc3MgPSBmdW5jdGlvbiBqdW1wVW5sZXNzKHRhcmdldCkgewogICAgICB0aGlzLnJlc2VydmUoNTQKICAgICAgLyogSnVtcFVubGVzcyAqLwogICAgICApOwogICAgICB0aGlzLmxhYmVscy50YXJnZXQodGhpcy5wb3MsIHRhcmdldCk7CiAgICB9OwoKICAgIF9wcm90bzExLmp1bXBFcSA9IGZ1bmN0aW9uIGp1bXBFcSh2YWx1ZSwgdGFyZ2V0KSB7CiAgICAgIHRoaXMucmVzZXJ2ZVdpdGhPcGVyYW5kKDU1CiAgICAgIC8qIEp1bXBFcSAqLwogICAgICAsIHZhbHVlKTsKICAgICAgdGhpcy5sYWJlbHMudGFyZ2V0KHRoaXMucG9zLCB0YXJnZXQpOwogICAgfTsKCiAgICBfcHJvdG8xMS5hc3NlcnRTYW1lID0gZnVuY3Rpb24gYXNzZXJ0U2FtZSgpIHsKICAgICAgdGhpcy5wdXNoKDU2CiAgICAgIC8qIEFzc2VydFNhbWUgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEucHVzaEVtcHR5QXJncyA9IGZ1bmN0aW9uIHB1c2hFbXB0eUFyZ3MoKSB7CiAgICAgIHRoaXMucHVzaCg3NwogICAgICAvKiBQdXNoRW1wdHlBcmdzICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLnN3aXRjaCA9IGZ1bmN0aW9uIF9zd2l0Y2goX29wY29kZSwgY2FsbGJhY2spIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIC8vIFNldHVwIHRoZSBzd2l0Y2ggRFNMCiAgICAgIHZhciBjbGF1c2VzID0gW107CiAgICAgIHZhciBjb3VudCA9IDA7CgogICAgICBmdW5jdGlvbiB3aGVuKG1hdGNoLCBjYWxsYmFjaykgewogICAgICAgIGNsYXVzZXMucHVzaCh7CiAgICAgICAgICBtYXRjaDogbWF0Y2gsCiAgICAgICAgICBjYWxsYmFjazogY2FsbGJhY2ssCiAgICAgICAgICBsYWJlbDogIkNMQVVTRSIgKyBjb3VudCsrCiAgICAgICAgfSk7CiAgICAgIH0gLy8gQ2FsbCB0aGUgY2FsbGJhY2sKCgogICAgICBjYWxsYmFjayh3aGVuKTsgLy8gRW1pdCB0aGUgb3Bjb2RlcyBmb3IgdGhlIHN3aXRjaAoKICAgICAgdGhpcy5lbnRlcigyKTsKICAgICAgdGhpcy5hc3NlcnRTYW1lKCk7CiAgICAgIHRoaXMucmVpZnlVMzIoKTsKICAgICAgdGhpcy5zdGFydExhYmVscygpOyAvLyBGaXJzdCwgZW1pdCB0aGUganVtcCBvcGNvZGVzLiBXZSBkb24ndCBuZWVkIGEganVtcCBmb3IgdGhlIGxhc3QKICAgICAgLy8gb3Bjb2RlLCBzaW5jZSBpdCBibGVlZHMgZGlyZWN0bHkgaW50byBpdHMgY2xhdXNlLgoKICAgICAgY2xhdXNlcy5zbGljZSgwLCAtMSkuZm9yRWFjaChmdW5jdGlvbiAoY2xhdXNlKSB7CiAgICAgICAgcmV0dXJuIF90aGlzLmp1bXBFcShjbGF1c2UubWF0Y2gsIGNsYXVzZS5sYWJlbCk7CiAgICAgIH0pOyAvLyBFbnVtZXJhdGUgdGhlIGNsYXVzZXMgaW4gcmV2ZXJzZSBvcmRlci4gRWFybGllciBtYXRjaGVzIHdpbGwKICAgICAgLy8gcmVxdWlyZSBmZXdlciBjaGVja3MuCgogICAgICBmb3IgKHZhciBpID0gY2xhdXNlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICAgIHZhciBjbGF1c2UgPSBjbGF1c2VzW2ldOwogICAgICAgIHRoaXMubGFiZWwoY2xhdXNlLmxhYmVsKTsKICAgICAgICB0aGlzLnBvcCgyKTsKICAgICAgICBjbGF1c2UuY2FsbGJhY2soKTsgLy8gVGhlIGZpcnN0IG1hdGNoIGlzIHNwZWNpYWw6IGl0IGlzIHBsYWNlZCBkaXJlY3RseSBiZWZvcmUgdGhlIEVORAogICAgICAgIC8vIGxhYmVsLCBzbyBubyBhZGRpdGlvbmFsIGp1bXAgaXMgbmVlZGVkIGF0IHRoZSBlbmQgb2YgaXQuCgogICAgICAgIGlmIChpICE9PSAwKSB7CiAgICAgICAgICB0aGlzLmp1bXAoJ0VORCcpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdGhpcy5sYWJlbCgnRU5EJyk7CiAgICAgIHRoaXMuc3RvcExhYmVscygpOwogICAgICB0aGlzLmV4aXQoKTsKICAgIH07CgogICAgX3Byb3RvMTEuc3RkQXBwZW5kID0gZnVuY3Rpb24gc3RkQXBwZW5kKHRydXN0aW5nKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgdGhpcy5zd2l0Y2godGhpcy5jb250ZW50VHlwZSgpLCBmdW5jdGlvbiAod2hlbikgewogICAgICAgIHdoZW4oMQogICAgICAgIC8qIFN0cmluZyAqLwogICAgICAgICwgZnVuY3Rpb24gKCkgewogICAgICAgICAgaWYgKHRydXN0aW5nKSB7CiAgICAgICAgICAgIF90aGlzMi5hc3NlcnRTYW1lKCk7CgogICAgICAgICAgICBfdGhpczIuYXBwZW5kSFRNTCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgX3RoaXMyLmFwcGVuZFRleHQoKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgICB3aGVuKDAKICAgICAgICAvKiBDb21wb25lbnQgKi8KICAgICAgICAsIGZ1bmN0aW9uICgpIHsKICAgICAgICAgIF90aGlzMi5wdXNoQ3VycmllZENvbXBvbmVudCgpOwoKICAgICAgICAgIF90aGlzMi5wdXNoRHluYW1pY0NvbXBvbmVudEluc3RhbmNlKCk7CgogICAgICAgICAgX3RoaXMyLmludm9rZUJhcmVDb21wb25lbnQoKTsKICAgICAgICB9KTsKICAgICAgICB3aGVuKDMKICAgICAgICAvKiBTYWZlU3RyaW5nICovCiAgICAgICAgLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBfdGhpczIuYXNzZXJ0U2FtZSgpOwoKICAgICAgICAgIF90aGlzMi5hcHBlbmRTYWZlSFRNTCgpOwogICAgICAgIH0pOwogICAgICAgIHdoZW4oNAogICAgICAgIC8qIEZyYWdtZW50ICovCiAgICAgICAgLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBfdGhpczIuYXNzZXJ0U2FtZSgpOwoKICAgICAgICAgIF90aGlzMi5hcHBlbmREb2N1bWVudEZyYWdtZW50KCk7CiAgICAgICAgfSk7CiAgICAgICAgd2hlbig1CiAgICAgICAgLyogTm9kZSAqLwogICAgICAgICwgZnVuY3Rpb24gKCkgewogICAgICAgICAgX3RoaXMyLmFzc2VydFNhbWUoKTsKCiAgICAgICAgICBfdGhpczIuYXBwZW5kTm9kZSgpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvMTEucG9wdWxhdGVMYXlvdXQgPSBmdW5jdGlvbiBwb3B1bGF0ZUxheW91dChzdGF0ZSkgewogICAgICB0aGlzLnB1c2goODkKICAgICAgLyogUG9wdWxhdGVMYXlvdXQgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLmludm9rZUJhcmVDb21wb25lbnQgPSBmdW5jdGlvbiBpbnZva2VCYXJlQ29tcG9uZW50KCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHRoaXMuZmV0Y2goX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5kdXAoX3ZtLlJlZ2lzdGVyLnNwLCAxKTsKICAgICAgdGhpcy5sb2FkKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHRoaXMucHVzaEZyYW1lKCk7CiAgICAgIHRoaXMucHVzaEVtcHR5QXJncygpOwogICAgICB0aGlzLnByZXBhcmVBcmdzKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHRoaXMuaW52b2tlUHJlcGFyZWRDb21wb25lbnQoZmFsc2UsIGZhbHNlLCB0cnVlLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgX3RoaXMzLmdldENvbXBvbmVudExheW91dChfdm0uUmVnaXN0ZXIuczApOwoKICAgICAgICBfdGhpczMucG9wdWxhdGVMYXlvdXQoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgfSk7CiAgICAgIHRoaXMubG9hZChfdm0uUmVnaXN0ZXIuczApOwogICAgfTsKCiAgICBfcHJvdG8xMS5pc0NvbXBvbmVudCA9IGZ1bmN0aW9uIGlzQ29tcG9uZW50KCkgewogICAgICB0aGlzLnB1c2goNjkKICAgICAgLyogSXNDb21wb25lbnQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuY29udGVudFR5cGUgPSBmdW5jdGlvbiBjb250ZW50VHlwZSgpIHsKICAgICAgdGhpcy5wdXNoKDcwCiAgICAgIC8qIENvbnRlbnRUeXBlICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLnB1c2hCbG9ja1Njb3BlID0gZnVuY3Rpb24gcHVzaEJsb2NrU2NvcGUoKSB7CiAgICAgIHRoaXMucHVzaCg0NwogICAgICAvKiBQdXNoQmxvY2tTY29wZSAqLwogICAgICApOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKFN0ZE9wY29kZUJ1aWxkZXIsIFt7CiAgICAgIGtleTogInBvcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmVuY29kZXIudHlwZVBvczsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJuZXh0UG9zIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2Rlci5zaXplOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImxhYmVscyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmxhYmVsc1N0YWNrLmN1cnJlbnQ7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBTdGRPcGNvZGVCdWlsZGVyOwogIH0oKTsKCiAgX2V4cG9ydHMuU3RkT3Bjb2RlQnVpbGRlciA9IFN0ZE9wY29kZUJ1aWxkZXI7CgogIHZhciBPcGNvZGVCdWlsZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9TdGRPcGNvZGVCdWlsZGVyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoT3Bjb2RlQnVpbGRlciwgX1N0ZE9wY29kZUJ1aWxkZXIpOwoKICAgIGZ1bmN0aW9uIE9wY29kZUJ1aWxkZXIoY29tcGlsZXIsIGNvbnRhaW5pbmdMYXlvdXQpIHsKICAgICAgdmFyIF90aGlzNDsKCiAgICAgIF90aGlzNCA9IF9TdGRPcGNvZGVCdWlsZGVyLmNhbGwodGhpcywgY29tcGlsZXIsIGNvbnRhaW5pbmdMYXlvdXQgPyBjb250YWluaW5nTGF5b3V0LmJsb2NrLnN5bWJvbHMubGVuZ3RoIDogMCkgfHwgdGhpczsKICAgICAgX3RoaXM0LmNvbnRhaW5pbmdMYXlvdXQgPSBjb250YWluaW5nTGF5b3V0OwogICAgICBfdGhpczQuY29tcG9uZW50ID0gbmV3IENvbXBvbmVudEJ1aWxkZXIoKDAsIF9lbWJlckJhYmVsLmFzc2VydFRoaXNJbml0aWFsaXplZCkoX3RoaXM0KSk7CiAgICAgIF90aGlzNC5leHByZXNzaW9uQ29tcGlsZXIgPSBleHByZXNzaW9uQ29tcGlsZXIoKTsKICAgICAgX3RoaXM0LmNvbnN0YW50cyA9IGNvbXBpbGVyLmNvbnN0YW50czsKICAgICAgX3RoaXM0LnN0ZExpYiA9IGNvbXBpbGVyLnN0ZExpYjsKICAgICAgcmV0dXJuIF90aGlzNDsKICAgIH0gLy8vIE1FQ0hBTklDUwoKCiAgICB2YXIgX3Byb3RvMTIgPSBPcGNvZGVCdWlsZGVyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xMi5leHByID0gZnVuY3Rpb24gZXhwcihleHByZXNzaW9uKSB7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KGV4cHJlc3Npb24pKSB7CiAgICAgICAgdGhpcy5leHByZXNzaW9uQ29tcGlsZXIuY29tcGlsZShleHByZXNzaW9uLCB0aGlzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnB1c2hQcmltaXRpdmVSZWZlcmVuY2UoZXhwcmVzc2lvbik7CiAgICAgIH0KICAgIH0gLy8vCiAgICAvLyBhcmdzCiAgICA7CgogICAgX3Byb3RvMTIucHVzaEFyZ3MgPSBmdW5jdGlvbiBwdXNoQXJncyhuYW1lcywgZmxhZ3MpIHsKICAgICAgdmFyIHNlcmlhbGl6ZWQgPSB0aGlzLmNvbnN0YW50cy5zdHJpbmdBcnJheShuYW1lcyk7CiAgICAgIHRoaXMucHVzaCg3NgogICAgICAvKiBQdXNoQXJncyAqLwogICAgICAsIHNlcmlhbGl6ZWQsIGZsYWdzKTsKICAgIH07CgogICAgX3Byb3RvMTIucHVzaFlpZWxkYWJsZUJsb2NrID0gZnVuY3Rpb24gcHVzaFlpZWxkYWJsZUJsb2NrKGJsb2NrKSB7CiAgICAgIHRoaXMucHVzaFN5bWJvbFRhYmxlKGJsb2NrICYmIGJsb2NrLnN5bWJvbFRhYmxlKTsKICAgICAgdGhpcy5wdXNoQmxvY2tTY29wZSgpOwogICAgICB0aGlzLnB1c2hCbG9jayhibG9jayk7CiAgICB9OwoKICAgIF9wcm90bzEyLmN1cnJ5Q29tcG9uZW50ID0gZnVuY3Rpb24gY3VycnlDb21wb25lbnQoZGVmaW5pdGlvbiwKICAgIC8qIFRPRE86IGF0dHJzOiBPcHRpb248UmF3SW5saW5lQmxvY2s+LCAqLwogICAgcGFyYW1zLCBoYXNoLCBzeW50aGV0aWMpIHsKICAgICAgdmFyIHJlZmVycmVyID0gdGhpcy5jb250YWluaW5nTGF5b3V0LnJlZmVycmVyOwogICAgICB0aGlzLnB1c2hGcmFtZSgpOwogICAgICB0aGlzLmNvbXBpbGVBcmdzKHBhcmFtcywgaGFzaCwgbnVsbCwgc3ludGhldGljKTsKICAgICAgdGhpcy5wdXNoKDgwCiAgICAgIC8qIENhcHR1cmVBcmdzICovCiAgICAgICk7CiAgICAgIHRoaXMuZXhwcihkZWZpbml0aW9uKTsKICAgICAgdGhpcy5wdXNoKDcxCiAgICAgIC8qIEN1cnJ5Q29tcG9uZW50ICovCiAgICAgICwgdGhpcy5jb25zdGFudHMuc2VyaWFsaXphYmxlKHJlZmVycmVyKSk7CiAgICAgIHRoaXMucG9wRnJhbWUoKTsKICAgICAgdGhpcy5mZXRjaChfdm0uUmVnaXN0ZXIudjApOwogICAgfTsKCiAgICBfcHJvdG8xMi5wdXNoU3ltYm9sVGFibGUgPSBmdW5jdGlvbiBwdXNoU3ltYm9sVGFibGUodGFibGUpIHsKICAgICAgaWYgKHRhYmxlKSB7CiAgICAgICAgdmFyIGNvbnN0YW50ID0gdGhpcy5jb25zdGFudHMuc2VyaWFsaXphYmxlKHRhYmxlKTsKICAgICAgICB0aGlzLnB1c2goNDgKICAgICAgICAvKiBQdXNoU3ltYm9sVGFibGUgKi8KICAgICAgICAsIGNvbnN0YW50KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnByaW1pdGl2ZShudWxsKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8xMi5pbnZva2VDb21wb25lbnQgPSBmdW5jdGlvbiBpbnZva2VDb21wb25lbnQoY2FwYWJpbGl0aWVzLCBhdHRycywgcGFyYW1zLCBoYXNoLCBzeW50aGV0aWMsIGJsb2NrLCBpbnZlcnNlLCBsYXlvdXQpIHsKICAgICAgdmFyIF90aGlzNSA9IHRoaXM7CgogICAgICBpZiAoaW52ZXJzZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgaW52ZXJzZSA9IG51bGw7CiAgICAgIH0KCiAgICAgIHRoaXMuZmV0Y2goX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5kdXAoX3ZtLlJlZ2lzdGVyLnNwLCAxKTsKICAgICAgdGhpcy5sb2FkKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHRoaXMucHVzaEZyYW1lKCk7CiAgICAgIHZhciBiaW5kYWJsZUJsb2NrcyA9ICEhKGJsb2NrIHx8IGludmVyc2UgfHwgYXR0cnMpOwogICAgICB2YXIgYmluZGFibGVBdE5hbWVzID0gY2FwYWJpbGl0aWVzID09PSB0cnVlIHx8IGNhcGFiaWxpdGllcy5wcmVwYXJlQXJncyB8fCAhIShoYXNoICYmIGhhc2hbMF0ubGVuZ3RoICE9PSAwKTsKICAgICAgdmFyIGJsb2NrcyA9IHsKICAgICAgICBtYWluOiBibG9jaywKICAgICAgICBlbHNlOiBpbnZlcnNlLAogICAgICAgIGF0dHJzOiBhdHRycwogICAgICB9OwogICAgICB0aGlzLmNvbXBpbGVBcmdzKHBhcmFtcywgaGFzaCwgYmxvY2tzLCBzeW50aGV0aWMpOwogICAgICB0aGlzLnByZXBhcmVBcmdzKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHRoaXMuaW52b2tlUHJlcGFyZWRDb21wb25lbnQoYmxvY2sgIT09IG51bGwsIGJpbmRhYmxlQmxvY2tzLCBiaW5kYWJsZUF0TmFtZXMsIGZ1bmN0aW9uICgpIHsKICAgICAgICBpZiAobGF5b3V0KSB7CiAgICAgICAgICBfdGhpczUucHVzaFN5bWJvbFRhYmxlKGxheW91dC5zeW1ib2xUYWJsZSk7CgogICAgICAgICAgX3RoaXM1LnB1c2hMYXlvdXQobGF5b3V0KTsKCiAgICAgICAgICBfdGhpczUucmVzb2x2ZUxheW91dCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBfdGhpczUuZ2V0Q29tcG9uZW50TGF5b3V0KF92bS5SZWdpc3Rlci5zMCk7CiAgICAgICAgfQoKICAgICAgICBfdGhpczUucG9wdWxhdGVMYXlvdXQoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgfSk7CiAgICAgIHRoaXMubG9hZChfdm0uUmVnaXN0ZXIuczApOwogICAgfTsKCiAgICBfcHJvdG8xMi5pbnZva2VTdGF0aWNDb21wb25lbnQgPSBmdW5jdGlvbiBpbnZva2VTdGF0aWNDb21wb25lbnQoY2FwYWJpbGl0aWVzLCBsYXlvdXQsIGF0dHJzLCBwYXJhbXMsIGhhc2gsIHN5bnRoZXRpYywgYmxvY2ssIGludmVyc2UpIHsKICAgICAgaWYgKGludmVyc2UgPT09IHZvaWQgMCkgewogICAgICAgIGludmVyc2UgPSBudWxsOwogICAgICB9CgogICAgICB2YXIgc3ltYm9sVGFibGUgPSBsYXlvdXQuc3ltYm9sVGFibGU7CiAgICAgIHZhciBiYWlsT3V0ID0gc3ltYm9sVGFibGUuaGFzRXZhbCB8fCBjYXBhYmlsaXRpZXMucHJlcGFyZUFyZ3M7CgogICAgICBpZiAoYmFpbE91dCkgewogICAgICAgIHRoaXMuaW52b2tlQ29tcG9uZW50KGNhcGFiaWxpdGllcywgYXR0cnMsIHBhcmFtcywgaGFzaCwgc3ludGhldGljLCBibG9jaywgaW52ZXJzZSwgbGF5b3V0KTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuZmV0Y2goX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5kdXAoX3ZtLlJlZ2lzdGVyLnNwLCAxKTsKICAgICAgdGhpcy5sb2FkKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHZhciBzeW1ib2xzID0gc3ltYm9sVGFibGUuc3ltYm9sczsKCiAgICAgIGlmIChjYXBhYmlsaXRpZXMuY3JlYXRlQXJncykgewogICAgICAgIHRoaXMucHVzaEZyYW1lKCk7CiAgICAgICAgdGhpcy5jb21waWxlQXJncyhwYXJhbXMsIGhhc2gsIG51bGwsIHN5bnRoZXRpYyk7CiAgICAgIH0KCiAgICAgIHRoaXMuYmVnaW5Db21wb25lbnRUcmFuc2FjdGlvbigpOwoKICAgICAgaWYgKGNhcGFiaWxpdGllcy5keW5hbWljU2NvcGUpIHsKICAgICAgICB0aGlzLnB1c2hEeW5hbWljU2NvcGUoKTsKICAgICAgfQoKICAgICAgaWYgKGNhcGFiaWxpdGllcy5jcmVhdGVJbnN0YW5jZSkgewogICAgICAgIHRoaXMuY3JlYXRlQ29tcG9uZW50KF92bS5SZWdpc3Rlci5zMCwgYmxvY2sgIT09IG51bGwpOwogICAgICB9CgogICAgICBpZiAoY2FwYWJpbGl0aWVzLmNyZWF0ZUFyZ3MpIHsKICAgICAgICB0aGlzLnBvcEZyYW1lKCk7CiAgICAgIH0KCiAgICAgIHRoaXMucHVzaEZyYW1lKCk7CiAgICAgIHRoaXMucmVnaXN0ZXJDb21wb25lbnREZXN0cnVjdG9yKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHZhciBiaW5kaW5ncyA9IFtdOwogICAgICB0aGlzLmdldENvbXBvbmVudFNlbGYoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgYmluZGluZ3MucHVzaCh7CiAgICAgICAgc3ltYm9sOiAwLAogICAgICAgIGlzQmxvY2s6IGZhbHNlCiAgICAgIH0pOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzeW1ib2xzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIHN5bWJvbCA9IHN5bWJvbHNbaV07CgogICAgICAgIHN3aXRjaCAoc3ltYm9sLmNoYXJBdCgwKSkgewogICAgICAgICAgY2FzZSAnJic6CiAgICAgICAgICAgIHZhciBjYWxsZXJCbG9jayA9IG51bGw7CgogICAgICAgICAgICBpZiAoc3ltYm9sID09PSAnJmRlZmF1bHQnKSB7CiAgICAgICAgICAgICAgY2FsbGVyQmxvY2sgPSBibG9jazsKICAgICAgICAgICAgfSBlbHNlIGlmIChzeW1ib2wgPT09ICcmaW52ZXJzZScpIHsKICAgICAgICAgICAgICBjYWxsZXJCbG9jayA9IGludmVyc2U7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoc3ltYm9sID09PSBBVFRSU19CTE9DSykgewogICAgICAgICAgICAgIGNhbGxlckJsb2NrID0gYXR0cnM7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdGhyb3cgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAoY2FsbGVyQmxvY2spIHsKICAgICAgICAgICAgICB0aGlzLnB1c2hZaWVsZGFibGVCbG9jayhjYWxsZXJCbG9jayk7CiAgICAgICAgICAgICAgYmluZGluZ3MucHVzaCh7CiAgICAgICAgICAgICAgICBzeW1ib2w6IGkgKyAxLAogICAgICAgICAgICAgICAgaXNCbG9jazogdHJ1ZQogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRoaXMucHVzaFlpZWxkYWJsZUJsb2NrKG51bGwpOwogICAgICAgICAgICAgIGJpbmRpbmdzLnB1c2goewogICAgICAgICAgICAgICAgc3ltYm9sOiBpICsgMSwKICAgICAgICAgICAgICAgIGlzQmxvY2s6IHRydWUKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgY2FzZSAnQCc6CiAgICAgICAgICAgIGlmICghaGFzaCkgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CgogICAgICAgICAgICB2YXIga2V5cyA9IGhhc2hbMF0sCiAgICAgICAgICAgICAgICB2YWx1ZXMgPSBoYXNoWzFdOwogICAgICAgICAgICB2YXIgbG9va3VwTmFtZSA9IHN5bWJvbDsKCiAgICAgICAgICAgIGlmIChzeW50aGV0aWMpIHsKICAgICAgICAgICAgICBsb29rdXBOYW1lID0gc3ltYm9sLnNsaWNlKDEpOwogICAgICAgICAgICB9CgogICAgICAgICAgICB2YXIgaW5kZXggPSBrZXlzLmluZGV4T2YobG9va3VwTmFtZSk7CgogICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7CiAgICAgICAgICAgICAgdGhpcy5leHByKHZhbHVlc1tpbmRleF0pOwogICAgICAgICAgICAgIGJpbmRpbmdzLnB1c2goewogICAgICAgICAgICAgICAgc3ltYm9sOiBpICsgMSwKICAgICAgICAgICAgICAgIGlzQmxvY2s6IGZhbHNlCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdGhpcy5wdXNoUm9vdFNjb3BlKHN5bWJvbHMubGVuZ3RoICsgMSwgISEoYmxvY2sgfHwgaW52ZXJzZSB8fCBhdHRycykpOwoKICAgICAgZm9yICh2YXIgX2kgPSBiaW5kaW5ncy5sZW5ndGggLSAxOyBfaSA+PSAwOyBfaS0tKSB7CiAgICAgICAgdmFyIF9iaW5kaW5ncyRfaSA9IGJpbmRpbmdzW19pXSwKICAgICAgICAgICAgX3N5bWJvbCA9IF9iaW5kaW5ncyRfaS5zeW1ib2wsCiAgICAgICAgICAgIGlzQmxvY2sgPSBfYmluZGluZ3MkX2kuaXNCbG9jazsKCiAgICAgICAgaWYgKGlzQmxvY2spIHsKICAgICAgICAgIHRoaXMuc2V0QmxvY2soX3N5bWJvbCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuc2V0VmFyaWFibGUoX3N5bWJvbCk7CiAgICAgICAgfQogICAgICB9CgogICAgICB0aGlzLmludm9rZVN0YXRpYyhsYXlvdXQpOwoKICAgICAgaWYgKGNhcGFiaWxpdGllcy5jcmVhdGVJbnN0YW5jZSkgewogICAgICAgIHRoaXMuZGlkUmVuZGVyTGF5b3V0KF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIH0KCiAgICAgIHRoaXMucG9wRnJhbWUoKTsKICAgICAgdGhpcy5wb3BTY29wZSgpOwoKICAgICAgaWYgKGNhcGFiaWxpdGllcy5keW5hbWljU2NvcGUpIHsKICAgICAgICB0aGlzLnBvcER5bmFtaWNTY29wZSgpOwogICAgICB9CgogICAgICB0aGlzLmNvbW1pdENvbXBvbmVudFRyYW5zYWN0aW9uKCk7CiAgICAgIHRoaXMubG9hZChfdm0uUmVnaXN0ZXIuczApOwogICAgfTsKCiAgICBfcHJvdG8xMi5keW5hbWljQ29tcG9uZW50ID0gZnVuY3Rpb24gZHluYW1pY0NvbXBvbmVudChkZWZpbml0aW9uLCBhdHRycywgcGFyYW1zLCBoYXNoLCBzeW50aGV0aWMsIGJsb2NrLCBpbnZlcnNlKSB7CiAgICAgIHZhciBfdGhpczYgPSB0aGlzOwoKICAgICAgaWYgKGludmVyc2UgPT09IHZvaWQgMCkgewogICAgICAgIGludmVyc2UgPSBudWxsOwogICAgICB9CgogICAgICB0aGlzLnJlcGxheWFibGUoewogICAgICAgIGFyZ3M6IGZ1bmN0aW9uIGFyZ3MoKSB7CiAgICAgICAgICBfdGhpczYuZXhwcihkZWZpbml0aW9uKTsKCiAgICAgICAgICBfdGhpczYuZHVwKCk7CgogICAgICAgICAgcmV0dXJuIDI7CiAgICAgICAgfSwKICAgICAgICBib2R5OiBmdW5jdGlvbiBib2R5KCkgewogICAgICAgICAgX3RoaXM2Lmp1bXBVbmxlc3MoJ0VMU0UnKTsKCiAgICAgICAgICBfdGhpczYucmVzb2x2ZUR5bmFtaWNDb21wb25lbnQoX3RoaXM2LmNvbnRhaW5pbmdMYXlvdXQucmVmZXJyZXIpOwoKICAgICAgICAgIF90aGlzNi5wdXNoRHluYW1pY0NvbXBvbmVudEluc3RhbmNlKCk7CgogICAgICAgICAgX3RoaXM2Lmludm9rZUNvbXBvbmVudCh0cnVlLCBhdHRycywgcGFyYW1zLCBoYXNoLCBzeW50aGV0aWMsIGJsb2NrLCBpbnZlcnNlKTsKCiAgICAgICAgICBfdGhpczYubGFiZWwoJ0VMU0UnKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8xMi55aWVsZCA9IGZ1bmN0aW9uIF95aWVsZCh0bywgcGFyYW1zKSB7CiAgICAgIHRoaXMuY29tcGlsZUFyZ3MocGFyYW1zLCBudWxsLCBudWxsLCBmYWxzZSk7CiAgICAgIHRoaXMuZ2V0QmxvY2sodG8pOwogICAgICB0aGlzLnJlc29sdmVCbG9jaygpOwogICAgICB0aGlzLmludm9rZVlpZWxkKCk7CiAgICAgIHRoaXMucG9wU2NvcGUoKTsKICAgICAgdGhpcy5wb3BGcmFtZSgpOwogICAgfTsKCiAgICBfcHJvdG8xMi5ndWFyZGVkQXBwZW5kID0gZnVuY3Rpb24gZ3VhcmRlZEFwcGVuZChleHByZXNzaW9uLCB0cnVzdGluZykgewogICAgICB0aGlzLnB1c2hGcmFtZSgpOwogICAgICB0aGlzLmV4cHIoZXhwcmVzc2lvbik7CiAgICAgIHRoaXMucHVzaE1hY2hpbmUoNTAKICAgICAgLyogSW52b2tlU3RhdGljICovCiAgICAgICwgdGhpcy5zdGRMaWIuZ2V0QXBwZW5kKHRydXN0aW5nKSk7CiAgICAgIHRoaXMucG9wRnJhbWUoKTsKICAgIH07CgogICAgX3Byb3RvMTIuaW52b2tlU3RhdGljQmxvY2sgPSBmdW5jdGlvbiBpbnZva2VTdGF0aWNCbG9jayhibG9jaywgY2FsbGVyQ291bnQpIHsKICAgICAgaWYgKGNhbGxlckNvdW50ID09PSB2b2lkIDApIHsKICAgICAgICBjYWxsZXJDb3VudCA9IDA7CiAgICAgIH0KCiAgICAgIHZhciBwYXJhbWV0ZXJzID0gYmxvY2suc3ltYm9sVGFibGUucGFyYW1ldGVyczsKICAgICAgdmFyIGNhbGxlZUNvdW50ID0gcGFyYW1ldGVycy5sZW5ndGg7CiAgICAgIHZhciBjb3VudCA9IE1hdGgubWluKGNhbGxlckNvdW50LCBjYWxsZWVDb3VudCk7CiAgICAgIHRoaXMucHVzaEZyYW1lKCk7CgogICAgICBpZiAoY291bnQpIHsKICAgICAgICB0aGlzLnB1c2hDaGlsZFNjb3BlKCk7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewogICAgICAgICAgdGhpcy5kdXAoX3ZtLlJlZ2lzdGVyLmZwLCBjYWxsZXJDb3VudCAtIGkpOwogICAgICAgICAgdGhpcy5zZXRWYXJpYWJsZShwYXJhbWV0ZXJzW2ldKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHRoaXMucHVzaEJsb2NrKGJsb2NrKTsKICAgICAgdGhpcy5yZXNvbHZlQmxvY2soKTsKICAgICAgdGhpcy5pbnZva2VWaXJ0dWFsKCk7CgogICAgICBpZiAoY291bnQpIHsKICAgICAgICB0aGlzLnBvcFNjb3BlKCk7CiAgICAgIH0KCiAgICAgIHRoaXMucG9wRnJhbWUoKTsKICAgIH0gLy8vIENPTlZFTklFTkNFCiAgICAvLyBpbnRlcm5hbCBoZWxwZXJzCiAgICA7CgogICAgX3Byb3RvMTIuc3RyaW5nID0gZnVuY3Rpb24gc3RyaW5nKF9zdHJpbmcpIHsKICAgICAgcmV0dXJuIHRoaXMuY29uc3RhbnRzLnN0cmluZyhfc3RyaW5nKTsKICAgIH07CgogICAgX3Byb3RvMTIubmFtZXMgPSBmdW5jdGlvbiBuYW1lcyhfbmFtZXMpIHsKICAgICAgdmFyIG5hbWVzID0gW107CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IF9uYW1lcy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBuID0gX25hbWVzW2ldOwogICAgICAgIG5hbWVzW2ldID0gdGhpcy5jb25zdGFudHMuc3RyaW5nKG4pOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5jb25zdGFudHMuYXJyYXkobmFtZXMpOwogICAgfTsKCiAgICBfcHJvdG8xMi5zeW1ib2xzID0gZnVuY3Rpb24gc3ltYm9scyhfc3ltYm9sczIpIHsKICAgICAgcmV0dXJuIHRoaXMuY29uc3RhbnRzLmFycmF5KF9zeW1ib2xzMik7CiAgICB9IC8vIHZtCiAgICA7CgogICAgX3Byb3RvMTIucHJpbWl0aXZlID0gZnVuY3Rpb24gcHJpbWl0aXZlKF9wcmltaXRpdmUpIHsKICAgICAgdmFyIHR5cGUgPSAwCiAgICAgIC8qIE5VTUJFUiAqLwogICAgICA7CiAgICAgIHZhciBwcmltaXRpdmU7CgogICAgICBzd2l0Y2ggKHR5cGVvZiBfcHJpbWl0aXZlKSB7CiAgICAgICAgY2FzZSAnbnVtYmVyJzoKICAgICAgICAgIGlmIChfcHJpbWl0aXZlICUgMSA9PT0gMCkgewogICAgICAgICAgICBpZiAoX3ByaW1pdGl2ZSA+IC0xKSB7CiAgICAgICAgICAgICAgcHJpbWl0aXZlID0gX3ByaW1pdGl2ZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBwcmltaXRpdmUgPSB0aGlzLmNvbnN0YW50cy5udW1iZXIoX3ByaW1pdGl2ZSk7CiAgICAgICAgICAgICAgdHlwZSA9IDQKICAgICAgICAgICAgICAvKiBORUdBVElWRSAqLwogICAgICAgICAgICAgIDsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcHJpbWl0aXZlID0gdGhpcy5jb25zdGFudHMubnVtYmVyKF9wcmltaXRpdmUpOwogICAgICAgICAgICB0eXBlID0gMQogICAgICAgICAgICAvKiBGTE9BVCAqLwogICAgICAgICAgICA7CiAgICAgICAgICB9CgogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ3N0cmluZyc6CiAgICAgICAgICBwcmltaXRpdmUgPSB0aGlzLnN0cmluZyhfcHJpbWl0aXZlKTsKICAgICAgICAgIHR5cGUgPSAyCiAgICAgICAgICAvKiBTVFJJTkcgKi8KICAgICAgICAgIDsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICdib29sZWFuJzoKICAgICAgICAgIHByaW1pdGl2ZSA9IF9wcmltaXRpdmUgfCAwOwogICAgICAgICAgdHlwZSA9IDMKICAgICAgICAgIC8qIEJPT0xFQU5fT1JfVk9JRCAqLwogICAgICAgICAgOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ29iamVjdCc6CiAgICAgICAgICAvLyBhc3N1bWUgbnVsbAogICAgICAgICAgcHJpbWl0aXZlID0gMjsKICAgICAgICAgIHR5cGUgPSAzCiAgICAgICAgICAvKiBCT09MRUFOX09SX1ZPSUQgKi8KICAgICAgICAgIDsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICd1bmRlZmluZWQnOgogICAgICAgICAgcHJpbWl0aXZlID0gMzsKICAgICAgICAgIHR5cGUgPSAzCiAgICAgICAgICAvKiBCT09MRUFOX09SX1ZPSUQgKi8KICAgICAgICAgIDsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHByaW1pdGl2ZSBwYXNzZWQgdG8gcHVzaFByaW1pdGl2ZScpOwogICAgICB9CgogICAgICB2YXIgaW1tZWRpYXRlID0gdGhpcy5zaXplSW1tZWRpYXRlKHByaW1pdGl2ZSA8PCAzIHwgdHlwZSwgcHJpbWl0aXZlKTsKICAgICAgdGhpcy5wdXNoKDEzCiAgICAgIC8qIFByaW1pdGl2ZSAqLwogICAgICAsIGltbWVkaWF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzEyLnNpemVJbW1lZGlhdGUgPSBmdW5jdGlvbiBzaXplSW1tZWRpYXRlKHNoaWZ0ZWQsIHByaW1pdGl2ZSkgewogICAgICBpZiAoc2hpZnRlZCA+PSA0Mjk0OTY3Mjk1CiAgICAgIC8qIE1BWF9TSVpFICovCiAgICAgIHx8IHNoaWZ0ZWQgPCAwKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RhbnRzLm51bWJlcihwcmltaXRpdmUpIDw8IDMgfCA1CiAgICAgICAgLyogQklHX05VTSAqLwogICAgICAgIDsKICAgICAgfQoKICAgICAgcmV0dXJuIHNoaWZ0ZWQ7CiAgICB9OwoKICAgIF9wcm90bzEyLnB1c2hQcmltaXRpdmVSZWZlcmVuY2UgPSBmdW5jdGlvbiBwdXNoUHJpbWl0aXZlUmVmZXJlbmNlKHByaW1pdGl2ZSkgewogICAgICB0aGlzLnByaW1pdGl2ZShwcmltaXRpdmUpOwogICAgICB0aGlzLnByaW1pdGl2ZVJlZmVyZW5jZSgpOwogICAgfSAvLyBjb21wb25lbnRzCiAgICA7CgogICAgX3Byb3RvMTIucHVzaENvbXBvbmVudERlZmluaXRpb24gPSBmdW5jdGlvbiBwdXNoQ29tcG9uZW50RGVmaW5pdGlvbihoYW5kbGUpIHsKICAgICAgdGhpcy5wdXNoKDcyCiAgICAgIC8qIFB1c2hDb21wb25lbnREZWZpbml0aW9uICovCiAgICAgICwgdGhpcy5jb25zdGFudHMuaGFuZGxlKGhhbmRsZSkpOwogICAgfTsKCiAgICBfcHJvdG8xMi5yZXNvbHZlRHluYW1pY0NvbXBvbmVudCA9IGZ1bmN0aW9uIHJlc29sdmVEeW5hbWljQ29tcG9uZW50KHJlZmVycmVyKSB7CiAgICAgIHRoaXMucHVzaCg3NQogICAgICAvKiBSZXNvbHZlRHluYW1pY0NvbXBvbmVudCAqLwogICAgICAsIHRoaXMuY29uc3RhbnRzLnNlcmlhbGl6YWJsZShyZWZlcnJlcikpOwogICAgfTsKCiAgICBfcHJvdG8xMi5zdGF0aWNDb21wb25lbnRIZWxwZXIgPSBmdW5jdGlvbiBzdGF0aWNDb21wb25lbnRIZWxwZXIodGFnLCBoYXNoLCB0ZW1wbGF0ZSkgewogICAgICB2YXIgX3RoaXMkY29tcGlsZXIkcmVzb2x2ID0gdGhpcy5jb21waWxlci5yZXNvbHZlTGF5b3V0Rm9yVGFnKHRhZywgdGhpcy5yZWZlcnJlciksCiAgICAgICAgICBoYW5kbGUgPSBfdGhpcyRjb21waWxlciRyZXNvbHYuaGFuZGxlLAogICAgICAgICAgY2FwYWJpbGl0aWVzID0gX3RoaXMkY29tcGlsZXIkcmVzb2x2LmNhcGFiaWxpdGllcywKICAgICAgICAgIGNvbXBpbGFibGUgPSBfdGhpcyRjb21waWxlciRyZXNvbHYuY29tcGlsYWJsZTsKCiAgICAgIGlmIChoYW5kbGUgIT09IG51bGwgJiYgY2FwYWJpbGl0aWVzICE9PSBudWxsKSB7CiAgICAgICAgaWYgKGNvbXBpbGFibGUpIHsKICAgICAgICAgIGlmIChoYXNoKSB7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGFzaC5sZW5ndGg7IGkgPSBpICsgMikgewogICAgICAgICAgICAgIGhhc2hbaV1bMF0gPSAiQCIgKyBoYXNoW2ldWzBdOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5wdXNoQ29tcG9uZW50RGVmaW5pdGlvbihoYW5kbGUpOwogICAgICAgICAgdGhpcy5pbnZva2VTdGF0aWNDb21wb25lbnQoY2FwYWJpbGl0aWVzLCBjb21waWxhYmxlLCBudWxsLCBudWxsLCBoYXNoLCBmYWxzZSwgdGVtcGxhdGUgJiYgdGVtcGxhdGUpOwogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gZmFsc2U7CiAgICB9IC8vIHBhcnRpYWwKICAgIDsKCiAgICBfcHJvdG8xMi5pbnZva2VQYXJ0aWFsID0gZnVuY3Rpb24gaW52b2tlUGFydGlhbChyZWZlcnJlciwgc3ltYm9scywgZXZhbEluZm8pIHsKICAgICAgdmFyIF9tZXRhID0gdGhpcy5jb25zdGFudHMuc2VyaWFsaXphYmxlKHJlZmVycmVyKTsKCiAgICAgIHZhciBfc3ltYm9scyA9IHRoaXMuY29uc3RhbnRzLnN0cmluZ0FycmF5KHN5bWJvbHMpOwoKICAgICAgdmFyIF9ldmFsSW5mbyA9IHRoaXMuY29uc3RhbnRzLmFycmF5KGV2YWxJbmZvKTsKCiAgICAgIHRoaXMucHVzaCg5NQogICAgICAvKiBJbnZva2VQYXJ0aWFsICovCiAgICAgICwgX21ldGEsIF9zeW1ib2xzLCBfZXZhbEluZm8pOwogICAgfTsKCiAgICBfcHJvdG8xMi5yZXNvbHZlTWF5YmVMb2NhbCA9IGZ1bmN0aW9uIHJlc29sdmVNYXliZUxvY2FsKG5hbWUpIHsKICAgICAgdGhpcy5wdXNoKDk2CiAgICAgIC8qIFJlc29sdmVNYXliZUxvY2FsICovCiAgICAgICwgdGhpcy5zdHJpbmcobmFtZSkpOwogICAgfSAvLyBkZWJ1Z2dlcgogICAgOwoKICAgIF9wcm90bzEyLmRlYnVnZ2VyID0gZnVuY3Rpb24gX2RlYnVnZ2VyKHN5bWJvbHMsIGV2YWxJbmZvKSB7CiAgICAgIHRoaXMucHVzaCg5NwogICAgICAvKiBEZWJ1Z2dlciAqLwogICAgICAsIHRoaXMuY29uc3RhbnRzLnN0cmluZ0FycmF5KHN5bWJvbHMpLCB0aGlzLmNvbnN0YW50cy5hcnJheShldmFsSW5mbykpOwogICAgfSAvLyBkb20KICAgIDsKCiAgICBfcHJvdG8xMi50ZXh0ID0gZnVuY3Rpb24gdGV4dChfdGV4dCkgewogICAgICB0aGlzLnB1c2goMjYKICAgICAgLyogVGV4dCAqLwogICAgICAsIHRoaXMuY29uc3RhbnRzLnN0cmluZyhfdGV4dCkpOwogICAgfTsKCiAgICBfcHJvdG8xMi5vcGVuUHJpbWl0aXZlRWxlbWVudCA9IGZ1bmN0aW9uIG9wZW5QcmltaXRpdmVFbGVtZW50KHRhZykgewogICAgICB0aGlzLnB1c2goMzMKICAgICAgLyogT3BlbkVsZW1lbnQgKi8KICAgICAgLCB0aGlzLmNvbnN0YW50cy5zdHJpbmcodGFnKSk7CiAgICB9OwoKICAgIF9wcm90bzEyLm1vZGlmaWVyID0gZnVuY3Rpb24gbW9kaWZpZXIobG9jYXRvciwgcGFyYW1zLCBoYXNoKSB7CiAgICAgIHRoaXMucHVzaEZyYW1lKCk7CiAgICAgIHRoaXMuY29tcGlsZUFyZ3MocGFyYW1zLCBoYXNoLCBudWxsLCB0cnVlKTsKICAgICAgdGhpcy5wdXNoKDQwCiAgICAgIC8qIE1vZGlmaWVyICovCiAgICAgICwgdGhpcy5jb25zdGFudHMuaGFuZGxlKGxvY2F0b3IpKTsKICAgICAgdGhpcy5wb3BGcmFtZSgpOwogICAgfTsKCiAgICBfcHJvdG8xMi5jb21tZW50ID0gZnVuY3Rpb24gY29tbWVudChfY29tbWVudCkgewogICAgICB2YXIgY29tbWVudCA9IHRoaXMuY29uc3RhbnRzLnN0cmluZyhfY29tbWVudCk7CiAgICAgIHRoaXMucHVzaCgyNwogICAgICAvKiBDb21tZW50ICovCiAgICAgICwgY29tbWVudCk7CiAgICB9OwoKICAgIF9wcm90bzEyLmR5bmFtaWNBdHRyID0gZnVuY3Rpb24gZHluYW1pY0F0dHIoX25hbWUsIF9uYW1lc3BhY2UsIHRydXN0aW5nKSB7CiAgICAgIHZhciBuYW1lID0gdGhpcy5jb25zdGFudHMuc3RyaW5nKF9uYW1lKTsKICAgICAgdmFyIG5hbWVzcGFjZSA9IF9uYW1lc3BhY2UgPyB0aGlzLmNvbnN0YW50cy5zdHJpbmcoX25hbWVzcGFjZSkgOiAwOwogICAgICB0aGlzLnB1c2goMzYKICAgICAgLyogRHluYW1pY0F0dHIgKi8KICAgICAgLCBuYW1lLCB0cnVzdGluZyA9PT0gdHJ1ZSA/IDEgOiAwLCBuYW1lc3BhY2UpOwogICAgfTsKCiAgICBfcHJvdG8xMi5jb21wb25lbnRBdHRyID0gZnVuY3Rpb24gY29tcG9uZW50QXR0cihfbmFtZSwgX25hbWVzcGFjZSwgdHJ1c3RpbmcpIHsKICAgICAgdmFyIG5hbWUgPSB0aGlzLmNvbnN0YW50cy5zdHJpbmcoX25hbWUpOwogICAgICB2YXIgbmFtZXNwYWNlID0gX25hbWVzcGFjZSA/IHRoaXMuY29uc3RhbnRzLnN0cmluZyhfbmFtZXNwYWNlKSA6IDA7CiAgICAgIHRoaXMucHVzaCgzNwogICAgICAvKiBDb21wb25lbnRBdHRyICovCiAgICAgICwgbmFtZSwgdHJ1c3RpbmcgPT09IHRydWUgPyAxIDogMCwgbmFtZXNwYWNlKTsKICAgIH07CgogICAgX3Byb3RvMTIuc3RhdGljQXR0ciA9IGZ1bmN0aW9uIHN0YXRpY0F0dHIoX25hbWUsIF9uYW1lc3BhY2UsIF92YWx1ZSkgewogICAgICB2YXIgbmFtZSA9IHRoaXMuY29uc3RhbnRzLnN0cmluZyhfbmFtZSk7CiAgICAgIHZhciBuYW1lc3BhY2UgPSBfbmFtZXNwYWNlID8gdGhpcy5jb25zdGFudHMuc3RyaW5nKF9uYW1lc3BhY2UpIDogMDsKICAgICAgdmFyIHZhbHVlID0gdGhpcy5jb25zdGFudHMuc3RyaW5nKF92YWx1ZSk7CiAgICAgIHRoaXMucHVzaCgzNQogICAgICAvKiBTdGF0aWNBdHRyICovCiAgICAgICwgbmFtZSwgdmFsdWUsIG5hbWVzcGFjZSk7CiAgICB9IC8vIGV4cHJlc3Npb25zCiAgICA7CgogICAgX3Byb3RvMTIuaGFzQmxvY2tQYXJhbXMgPSBmdW5jdGlvbiBoYXNCbG9ja1BhcmFtcyh0bykgewogICAgICB0aGlzLmdldEJsb2NrKHRvKTsKICAgICAgdGhpcy5yZXNvbHZlQmxvY2soKTsKICAgICAgdGhpcy5wdXNoKDEwCiAgICAgIC8qIEhhc0Jsb2NrUGFyYW1zICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzEyLmdldFByb3BlcnR5ID0gZnVuY3Rpb24gZ2V0UHJvcGVydHkoa2V5KSB7CiAgICAgIHRoaXMucHVzaCg3CiAgICAgIC8qIEdldFByb3BlcnR5ICovCiAgICAgICwgdGhpcy5zdHJpbmcoa2V5KSk7CiAgICB9OwoKICAgIF9wcm90bzEyLmhlbHBlciA9IGZ1bmN0aW9uIGhlbHBlcihfaGVscGVyLCBwYXJhbXMsIGhhc2gpIHsKICAgICAgdGhpcy5wdXNoRnJhbWUoKTsKICAgICAgdGhpcy5jb21waWxlQXJncyhwYXJhbXMsIGhhc2gsIG51bGwsIHRydWUpOwogICAgICB0aGlzLnB1c2goMQogICAgICAvKiBIZWxwZXIgKi8KICAgICAgLCB0aGlzLmNvbnN0YW50cy5oYW5kbGUoX2hlbHBlcikpOwogICAgICB0aGlzLnBvcEZyYW1lKCk7CiAgICAgIHRoaXMuZmV0Y2goX3ZtLlJlZ2lzdGVyLnYwKTsKICAgIH07CgogICAgX3Byb3RvMTIuYmluZER5bmFtaWNTY29wZSA9IGZ1bmN0aW9uIGJpbmREeW5hbWljU2NvcGUoX25hbWVzKSB7CiAgICAgIHRoaXMucHVzaCg0MwogICAgICAvKiBCaW5kRHluYW1pY1Njb3BlICovCiAgICAgICwgdGhpcy5uYW1lcyhfbmFtZXMpKTsKICAgIH0gLy8gY29udmVuaWVuY2UgbWV0aG9kcwoKICAgIC8qKgogICAgICogQSBjb252ZW5pZW5jZSBmb3IgcHVzaGluZyBzb21lIGFyZ3VtZW50cyBvbiB0aGUgc3RhY2sgYW5kCiAgICAgKiBydW5uaW5nIHNvbWUgY29kZSBpZiB0aGUgY29kZSBuZWVkcyB0byBiZSByZS1leGVjdXRlZCBkdXJpbmcKICAgICAqIHVwZGF0aW5nIGV4ZWN1dGlvbiBpZiBzb21lIG9mIHRoZSBhcmd1bWVudHMgaGF2ZSBjaGFuZ2VkLgogICAgICoKICAgICAqICMgSW5pdGlhbCBFeGVjdXRpb24KICAgICAqCiAgICAgKiBUaGUgYGFyZ3NgIGZ1bmN0aW9uIHNob3VsZCBwdXNoIHplcm8gb3IgbW9yZSBhcmd1bWVudHMgb250bwogICAgICogdGhlIHN0YWNrIGFuZCByZXR1cm4gdGhlIG51bWJlciBvZiBhcmd1bWVudHMgcHVzaGVkLgogICAgICoKICAgICAqIFRoZSBgYm9keWAgZnVuY3Rpb24gcHJvdmlkZXMgdGhlIGluc3RydWN0aW9ucyB0byBleGVjdXRlIGJvdGgKICAgICAqIGR1cmluZyBpbml0aWFsIGV4ZWN1dGlvbiBhbmQgZHVyaW5nIHVwZGF0aW5nIGV4ZWN1dGlvbi4KICAgICAqCiAgICAgKiBJbnRlcm5hbGx5LCB0aGlzIGZ1bmN0aW9uIHN0YXJ0cyBieSBwdXNoaW5nIGEgbmV3IGZyYW1lLCBzbwogICAgICogdGhhdCB0aGUgYm9keSBjYW4gcmV0dXJuIGFuZCBzZXRzIHRoZSByZXR1cm4gcG9pbnQgKCRyYSkgdG8KICAgICAqIHRoZSBFTkRJTklUSUFMIGxhYmVsLgogICAgICoKICAgICAqIEl0IHRoZW4gZXhlY3V0ZXMgdGhlIGBhcmdzYCBmdW5jdGlvbiwgd2hpY2ggYWRkcyBpbnN0cnVjdGlvbnMKICAgICAqIHJlc3BvbnNpYmxlIGZvciBwdXNoaW5nIHRoZSBhcmd1bWVudHMgZm9yIHRoZSBibG9jayB0byB0aGUKICAgICAqIHN0YWNrLiBUaGVzZSBhcmd1bWVudHMgd2lsbCBiZSByZXN0b3JlZCB0byB0aGUgc3RhY2sgYmVmb3JlCiAgICAgKiB1cGRhdGluZyBleGVjdXRpb24uCiAgICAgKgogICAgICogTmV4dCwgaXQgYWRkcyB0aGUgRW50ZXIgb3Bjb2RlLCB3aGljaCBtYXJrcyB0aGUgY3VycmVudCBwb3NpdGlvbgogICAgICogaW4gdGhlIERPTSwgYW5kIHJlbWVtYmVycyB0aGUgY3VycmVudCAkcGMgKHRoZSBuZXh0IGluc3RydWN0aW9uKQogICAgICogYXMgdGhlIGZpcnN0IGluc3RydWN0aW9uIHRvIGV4ZWN1dGUgZHVyaW5nIHVwZGF0aW5nIGV4ZWN1dGlvbi4KICAgICAqCiAgICAgKiBOZXh0LCBpdCBydW5zIGBib2R5YCwgd2hpY2ggYWRkcyB0aGUgb3Bjb2RlcyB0aGF0IHNob3VsZAogICAgICogZXhlY3V0ZSBib3RoIGR1cmluZyBpbml0aWFsIGV4ZWN1dGlvbiBhbmQgZHVyaW5nIHVwZGF0aW5nIGV4ZWN1dGlvbi4KICAgICAqIElmIHRoZSBgYm9keWAgd2lzaGVzIHRvIGZpbmlzaCBlYXJseSwgaXQgc2hvdWxkIEp1bXAgdG8gdGhlCiAgICAgKiBgRklOQUxMWWAgbGFiZWwuCiAgICAgKgogICAgICogTmV4dCwgaXQgYWRkcyB0aGUgRklOQUxMWSBsYWJlbCwgZm9sbG93ZWQgYnk6CiAgICAgKgogICAgICogLSB0aGUgRXhpdCBvcGNvZGUsIHdoaWNoIGZpbmFsaXplcyB0aGUgbWFya2VkIERPTSBzdGFydGVkIGJ5IHRoZQogICAgICogICBFbnRlciBvcGNvZGUuCiAgICAgKiAtIHRoZSBSZXR1cm4gb3Bjb2RlLCB3aGljaCByZXR1cm5zIHRvIHRoZSBjdXJyZW50IHJldHVybiBwb2ludAogICAgICogICAoJHJhKS4KICAgICAqCiAgICAgKiBGaW5hbGx5LCBpdCBhZGRzIHRoZSBFTkRJTklUSUFMIGxhYmVsIGZvbGxvd2VkIGJ5IHRoZSBQb3BGcmFtZQogICAgICogaW5zdHJ1Y3Rpb24sIHdoaWNoIHJlc3RvcmVzICRmcCwgJHNwIGFuZCAkcmEuCiAgICAgKgogICAgICogIyBVcGRhdGluZyBFeGVjdXRpb24KICAgICAqCiAgICAgKiBVcGRhdGluZyBleGVjdXRpb24gZm9yIHRoaXMgYHJlcGxheWFibGVgIG9jY3VycyBpZiB0aGUgYGJvZHlgIGFkZGVkIGFuCiAgICAgKiBhc3NlcnRpb24sIHZpYSBvbmUgb2YgdGhlIGBKdW1wSWZgLCBgSnVtcFVubGVzc2Agb3IgYEFzc2VydFNhbWVgIG9wY29kZXMuCiAgICAgKgogICAgICogSWYsIGR1cmluZyB1cGRhdGluZyBleGVjdXRvbiwgdGhlIGFzc2VydGlvbiBmYWlscywgdGhlIGluaXRpYWwgVk0gaXMKICAgICAqIHJlc3RvcmVkLCBhbmQgdGhlIHN0b3JlZCBhcmd1bWVudHMgYXJlIHB1c2hlZCBvbnRvIHRoZSBzdGFjay4gVGhlIERPTQogICAgICogYmV0d2VlbiB0aGUgc3RhcnRpbmcgYW5kIGVuZGluZyBtYXJrZXJzIGlzIGNsZWFyZWQsIGFuZCB0aGUgVk0ncyBjdXJzb3IKICAgICAqIGlzIHNldCB0byB0aGUgYXJlYSBqdXN0IGNsZWFyZWQuCiAgICAgKgogICAgICogVGhlIHJldHVybiBwb2ludCAoJHJhKSBpcyBzZXQgdG8gLTEsIHRoZSBleGl0IGluc3RydWN0aW9uLgogICAgICoKICAgICAqIEZpbmFsbHksIHRoZSAkcGMgaXMgc2V0IHRvIHRvIHRoZSBpbnN0cnVjdGlvbiBzYXZlZCBvZmYgYnkgdGhlCiAgICAgKiBFbnRlciBvcGNvZGUgZHVyaW5nIGluaXRpYWwgZXhlY3V0aW9uLCBhbmQgZXhlY3V0aW9uIHByb2NlZWRzIGFzCiAgICAgKiB1c3VhbC4KICAgICAqCiAgICAgKiBUaGUgb25seSBkaWZmZXJlbmNlIGlzIHRoYXQgd2hlbiBhIGBSZXR1cm5gIGluc3RydWN0aW9uIGlzCiAgICAgKiBlbmNvdW50ZXJlZCwgdGhlIHByb2dyYW0ganVtcHMgdG8gLTEgcmF0aGVyIHRoYW4gdGhlIEVORCBsYWJlbCwKICAgICAqIGFuZCB0aGUgUG9wRnJhbWUgb3Bjb2RlIGlzIG5vdCBuZWVkZWQuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8xMi5yZXBsYXlhYmxlID0gZnVuY3Rpb24gcmVwbGF5YWJsZShfcmVmKSB7CiAgICAgIHZhciBhcmdzID0gX3JlZi5hcmdzLAogICAgICAgICAgYm9keSA9IF9yZWYuYm9keTsKICAgICAgLy8gU3RhcnQgYSBuZXcgbGFiZWwgZnJhbWUsIHRvIGdpdmUgRU5EIGFuZCBSRVRVUk4KICAgICAgLy8gYSB1bmlxdWUgbWVhbmluZy4KICAgICAgdGhpcy5zdGFydExhYmVscygpOwogICAgICB0aGlzLnB1c2hGcmFtZSgpOyAvLyBJZiB0aGUgYm9keSBpbnZva2VzIGEgYmxvY2ssIGl0cyByZXR1cm4gd2lsbCByZXR1cm4gdG8KICAgICAgLy8gRU5ELiBPdGhlcndpc2UsIHRoZSByZXR1cm4gaW4gUkVUVVJOIHdpbGwgcmV0dXJuIHRvIEVORC4KCiAgICAgIHRoaXMucmV0dXJuVG8oJ0VORElOSVRJQUwnKTsgLy8gUHVzaCB0aGUgYXJndW1lbnRzIG9udG8gdGhlIHN0YWNrLiBUaGUgYXJncygpIGZ1bmN0aW9uCiAgICAgIC8vIHRlbGxzIHVzIGhvdyBtYW55IHN0YWNrIGVsZW1lbnRzIHRvIHJldGFpbiBmb3IgcmUtZXhlY3V0aW9uCiAgICAgIC8vIHdoZW4gdXBkYXRpbmcuCgogICAgICB2YXIgY291bnQgPSBhcmdzKCk7IC8vIFN0YXJ0IGEgbmV3IHVwZGF0aW5nIGNsb3N1cmUsIHJlbWVtYmVyaW5nIGBjb3VudGAgZWxlbWVudHMKICAgICAgLy8gZnJvbSB0aGUgc3RhY2suIEV2ZXJ5dGhpbmcgYWZ0ZXIgdGhpcyBwb2ludCwgYW5kIGJlZm9yZSBFTkQsCiAgICAgIC8vIHdpbGwgZXhlY3V0ZSBib3RoIGluaXRpYWxseSBhbmQgdG8gdXBkYXRlIHRoZSBibG9jay4KICAgICAgLy8KICAgICAgLy8gVGhlIGVudGVyIGFuZCBleGl0IG9wY29kZXMgYWxzbyB0cmFjayB0aGUgYXJlYSBvZiB0aGUgRE9NCiAgICAgIC8vIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGJsb2NrLiBJZiBhbiBhc3NlcnRpb24gaW5zaWRlIHRoZSBibG9jawogICAgICAvLyBmYWlscyAoZm9yIGV4YW1wbGUsIHRoZSB0ZXN0IHZhbHVlIGNoYW5nZXMgZnJvbSB0cnVlIHRvIGZhbHNlCiAgICAgIC8vIGluIGFuICNpZiksIHRoZSBET00gaXMgY2xlYXJlZCBhbmQgdGhlIHByb2dyYW0gaXMgcmUtZXhlY3V0ZWQsCiAgICAgIC8vIHJlc3RvcmluZyBgY291bnRgIGVsZW1lbnRzIHRvIHRoZSBzdGFjayBhbmQgZXhlY3V0aW5nIHRoZQogICAgICAvLyBpbnN0cnVjdGlvbnMgYmV0d2VlbiB0aGUgZW50ZXIgYW5kIGV4aXQuCgogICAgICB0aGlzLmVudGVyKGNvdW50KTsgLy8gRXZhbHVhdGUgdGhlIGJvZHkgb2YgdGhlIGJsb2NrLiBUaGUgYm9keSBvZiB0aGUgYmxvY2sgbWF5CiAgICAgIC8vIHJldHVybiwgd2hpY2ggd2lsbCBqdW1wIGV4ZWN1dGlvbiB0byBFTkQgZHVyaW5nIGluaXRpYWwKICAgICAgLy8gZXhlY3V0aW9uLCBhbmQgZXhpdCB0aGUgdXBkYXRpbmcgcm91dGluZS4KCiAgICAgIGJvZHkoKTsgLy8gQWxsIGV4ZWN1dGlvbiBwYXRocyBpbiB0aGUgYm9keSBzaG91bGQgcnVuIHRoZSBGSU5BTExZIG9uY2UKICAgICAgLy8gdGhleSBhcmUgZG9uZS4gSXQgaXMgZXhlY3V0ZWQgYm90aCBkdXJpbmcgaW5pdGlhbCBleGVjdXRpb24KICAgICAgLy8gYW5kIGR1cmluZyB1cGRhdGluZyBleGVjdXRpb24uCgogICAgICB0aGlzLmxhYmVsKCdGSU5BTExZJyk7IC8vIEZpbmFsaXplIHRoZSBET00uCgogICAgICB0aGlzLmV4aXQoKTsgLy8gSW4gaW5pdGlhbCBleGVjdXRpb24sIHRoaXMgaXMgYSBub29wOiBpdCByZXR1cm5zIHRvIHRoZQogICAgICAvLyBpbW1lZGlhdGVseSBmb2xsb3dpbmcgb3Bjb2RlLiBJbiB1cGRhdGluZyBleGVjdXRpb24sIHRoaXMKICAgICAgLy8gZXhpdHMgdGhlIHVwZGF0aW5nIHJvdXRpbmUuCgogICAgICB0aGlzLnJldHVybigpOyAvLyBDbGVhbnVwIGNvZGUgZm9yIHRoZSBibG9jay4gUnVucyBvbiBpbml0aWFsIGV4ZWN1dGlvbgogICAgICAvLyBidXQgbm90IG9uIHVwZGF0aW5nLgoKICAgICAgdGhpcy5sYWJlbCgnRU5ESU5JVElBTCcpOwogICAgICB0aGlzLnBvcEZyYW1lKCk7CiAgICAgIHRoaXMuc3RvcExhYmVscygpOwogICAgfQogICAgLyoqCiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgdGhlIGByZXBsYXlhYmxlYCBjb252ZW5pZW5jZSB0aGF0IGFsbG93cyB0aGUKICAgICAqIGNhbGxlciB0byBwcm92aWRlIGRpZmZlcmVudCBjb2RlIGJhc2VkIHVwb24gd2hldGhlciB0aGUgaXRlbSBhdAogICAgICogdGhlIHRvcCBvZiB0aGUgc3RhY2sgaXMgdHJ1ZSBvciBmYWxzZS4KICAgICAqCiAgICAgKiBBcyBpbiBgcmVwbGF5YWJsZWAsIHRoZSBgaWZUcnVlYCBhbmQgYGlmRmFsc2VgIGNvZGUgY2FuIGludm9rZSBgcmV0dXJuYC4KICAgICAqCiAgICAgKiBEdXJpbmcgdGhlIGluaXRpYWwgZXhlY3V0aW9uLCBhIGByZXR1cm5gIHdpbGwgY29udGludWUgZXhlY3V0aW9uCiAgICAgKiBpbiB0aGUgY2xlYW51cCBjb2RlLCB3aGljaCBmaW5hbGl6ZXMgdGhlIGN1cnJlbnQgRE9NIGJsb2NrIGFuZCBwb3BzCiAgICAgKiB0aGUgY3VycmVudCBmcmFtZS4KICAgICAqCiAgICAgKiBEdXJpbmcgdGhlIHVwZGF0aW5nIGV4ZWN1dGlvbiwgYSBgcmV0dXJuYCB3aWxsIGV4aXQgdGhlIHVwZGF0aW5nCiAgICAgKiByb3V0aW5lLCBhcyBpdCBjYW4gcmV1c2UgdGhlIERPTSBibG9jayBhbmQgaXMgYWx3YXlzIG9ubHkgYSBzaW5nbGUKICAgICAqIGZyYW1lIGRlZXAuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8xMi5yZXBsYXlhYmxlSWYgPSBmdW5jdGlvbiByZXBsYXlhYmxlSWYoX3JlZjIpIHsKICAgICAgdmFyIF90aGlzNyA9IHRoaXM7CgogICAgICB2YXIgYXJncyA9IF9yZWYyLmFyZ3MsCiAgICAgICAgICBpZlRydWUgPSBfcmVmMi5pZlRydWUsCiAgICAgICAgICBpZkZhbHNlID0gX3JlZjIuaWZGYWxzZTsKICAgICAgdGhpcy5yZXBsYXlhYmxlKHsKICAgICAgICBhcmdzOiBhcmdzLAogICAgICAgIGJvZHk6IGZ1bmN0aW9uIGJvZHkoKSB7CiAgICAgICAgICAvLyBJZiB0aGUgY29uZGl0aW9uYWwgaXMgZmFsc2UsIGp1bXAgdG8gdGhlIEVMU0UgbGFiZWwuCiAgICAgICAgICBfdGhpczcuanVtcFVubGVzcygnRUxTRScpOyAvLyBPdGhlcndpc2UsIGV4ZWN1dGUgdGhlIGNvZGUgYXNzb2NpYXRlZCB3aXRoIHRoZSB0cnVlIGJyYW5jaC4KCgogICAgICAgICAgaWZUcnVlKCk7IC8vIFdlJ3JlIGRvbmUsIHNvIHJldHVybi4gSW4gdGhlIGluaXRpYWwgZXhlY3V0aW9uLCB0aGlzIHJ1bnMKICAgICAgICAgIC8vIHRoZSBjbGVhbnVwIGNvZGUuIEluIHRoZSB1cGRhdGluZyBWTSwgaXQgZXhpdHMgdGhlIHVwZGF0aW5nCiAgICAgICAgICAvLyByb3V0aW5lLgoKICAgICAgICAgIF90aGlzNy5qdW1wKCdGSU5BTExZJyk7CgogICAgICAgICAgX3RoaXM3LmxhYmVsKCdFTFNFJyk7IC8vIElmIHRoZSBjb25kaXRpb25hbCBpcyBmYWxzZSwgYW5kIGNvZGUgYXNzb2NpYXRpZWQgaXRoIHRoZQogICAgICAgICAgLy8gZmFsc2UgYnJhbmNoIHdhcyBwcm92aWRlZCwgZXhlY3V0ZSBpdC4gSWYgdGhlcmUgd2FzIG5vIGNvZGUKICAgICAgICAgIC8vIGFzc29jaWF0ZWQgd2l0aCB0aGUgZmFsc2UgYnJhbmNoLCBqdW1waW5nIHRvIHRoZSBlbHNlIHN0YXRlbWVudAogICAgICAgICAgLy8gaGFzIG5vIG90aGVyIGJlaGF2aW9yLgoKCiAgICAgICAgICBpZiAoaWZGYWxzZSkgewogICAgICAgICAgICBpZkZhbHNlKCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvMTIuaW5saW5lQmxvY2sgPSBmdW5jdGlvbiBpbmxpbmVCbG9jayhibG9jaykgewogICAgICByZXR1cm4gbmV3IENvbXBpbGFibGVCbG9jayh0aGlzLmNvbXBpbGVyLCB7CiAgICAgICAgYmxvY2s6IGJsb2NrLAogICAgICAgIGNvbnRhaW5pbmdMYXlvdXQ6IHRoaXMuY29udGFpbmluZ0xheW91dAogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvMTIuZXZhbFN5bWJvbHMgPSBmdW5jdGlvbiBldmFsU3ltYm9scygpIHsKICAgICAgdmFyIGJsb2NrID0gdGhpcy5jb250YWluaW5nTGF5b3V0LmJsb2NrOwogICAgICByZXR1cm4gYmxvY2suaGFzRXZhbCA/IGJsb2NrLnN5bWJvbHMgOiBudWxsOwogICAgfTsKCiAgICBfcHJvdG8xMi5jb21waWxlUGFyYW1zID0gZnVuY3Rpb24gY29tcGlsZVBhcmFtcyhwYXJhbXMpIHsKICAgICAgaWYgKCFwYXJhbXMpIHJldHVybiAwOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJhbXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB0aGlzLmV4cHIocGFyYW1zW2ldKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHBhcmFtcy5sZW5ndGg7CiAgICB9OwoKICAgIF9wcm90bzEyLmNvbXBpbGVBcmdzID0gZnVuY3Rpb24gY29tcGlsZUFyZ3MocGFyYW1zLCBoYXNoLCBibG9ja3MsIHN5bnRoZXRpYykgewogICAgICBpZiAoYmxvY2tzKSB7CiAgICAgICAgdGhpcy5wdXNoWWllbGRhYmxlQmxvY2soYmxvY2tzLm1haW4pOwogICAgICAgIHRoaXMucHVzaFlpZWxkYWJsZUJsb2NrKGJsb2Nrcy5lbHNlKTsKICAgICAgICB0aGlzLnB1c2hZaWVsZGFibGVCbG9jayhibG9ja3MuYXR0cnMpOwogICAgICB9CgogICAgICB2YXIgY291bnQgPSB0aGlzLmNvbXBpbGVQYXJhbXMocGFyYW1zKTsKICAgICAgdmFyIGZsYWdzID0gY291bnQgPDwgNDsKICAgICAgaWYgKHN5bnRoZXRpYykgZmxhZ3MgfD0gODsKCiAgICAgIGlmIChibG9ja3MpIHsKICAgICAgICBmbGFncyB8PSA3OwogICAgICB9CgogICAgICB2YXIgbmFtZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKCiAgICAgIGlmIChoYXNoKSB7CiAgICAgICAgbmFtZXMgPSBoYXNoWzBdOwogICAgICAgIHZhciB2YWwgPSBoYXNoWzFdOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZhbC5sZW5ndGg7IGkrKykgewogICAgICAgICAgdGhpcy5leHByKHZhbFtpXSk7CiAgICAgICAgfQogICAgICB9CgogICAgICB0aGlzLnB1c2hBcmdzKG5hbWVzLCBmbGFncyk7CiAgICB9OwoKICAgIF9wcm90bzEyLnRlbXBsYXRlID0gZnVuY3Rpb24gdGVtcGxhdGUoYmxvY2spIHsKICAgICAgaWYgKCFibG9jaykgcmV0dXJuIG51bGw7CiAgICAgIHJldHVybiB0aGlzLmlubGluZUJsb2NrKGJsb2NrKTsKICAgIH07CgogICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShPcGNvZGVCdWlsZGVyLCBbewogICAgICBrZXk6ICJyZWZlcnJlciIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5pbmdMYXlvdXQgJiYgdGhpcy5jb250YWluaW5nTGF5b3V0LnJlZmVycmVyOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gT3Bjb2RlQnVpbGRlcjsKICB9KFN0ZE9wY29kZUJ1aWxkZXIpOwoKICBfZXhwb3J0cy5PcGNvZGVCdWlsZGVyID0gT3Bjb2RlQnVpbGRlcjsKCiAgdmFyIExhenlPcGNvZGVCdWlsZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9PcGNvZGVCdWlsZGVyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTGF6eU9wY29kZUJ1aWxkZXIsIF9PcGNvZGVCdWlsZGVyKTsKCiAgICBmdW5jdGlvbiBMYXp5T3Bjb2RlQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIF9PcGNvZGVCdWlsZGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTMgPSBMYXp5T3Bjb2RlQnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMTMucHVzaEJsb2NrID0gZnVuY3Rpb24gcHVzaEJsb2NrKGJsb2NrKSB7CiAgICAgIGlmIChibG9jaykgewogICAgICAgIHRoaXMucHVzaE90aGVyKGJsb2NrKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnByaW1pdGl2ZShudWxsKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8xMy5yZXNvbHZlQmxvY2sgPSBmdW5jdGlvbiByZXNvbHZlQmxvY2soKSB7CiAgICAgIHRoaXMucHVzaCg0NgogICAgICAvKiBDb21waWxlQmxvY2sgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTMucHVzaExheW91dCA9IGZ1bmN0aW9uIHB1c2hMYXlvdXQobGF5b3V0KSB7CiAgICAgIGlmIChsYXlvdXQpIHsKICAgICAgICB0aGlzLnB1c2hPdGhlcihsYXlvdXQpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMucHJpbWl0aXZlKG51bGwpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzEzLnJlc29sdmVMYXlvdXQgPSBmdW5jdGlvbiByZXNvbHZlTGF5b3V0KCkgewogICAgICB0aGlzLnB1c2goNDYKICAgICAgLyogQ29tcGlsZUJsb2NrICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzEzLmludm9rZVN0YXRpYyA9IGZ1bmN0aW9uIGludm9rZVN0YXRpYyhjb21waWxhYmxlKSB7CiAgICAgIHRoaXMucHVzaE90aGVyKGNvbXBpbGFibGUpOwogICAgICB0aGlzLnB1c2goNDYKICAgICAgLyogQ29tcGlsZUJsb2NrICovCiAgICAgICk7CiAgICAgIHRoaXMucHVzaE1hY2hpbmUoNDkKICAgICAgLyogSW52b2tlVmlydHVhbCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMy5wdXNoT3RoZXIgPSBmdW5jdGlvbiBwdXNoT3RoZXIodmFsdWUpIHsKICAgICAgdGhpcy5wdXNoKDEyCiAgICAgIC8qIENvbnN0YW50ICovCiAgICAgICwgdGhpcy5vdGhlcih2YWx1ZSkpOwogICAgfTsKCiAgICBfcHJvdG8xMy5vdGhlciA9IGZ1bmN0aW9uIG90aGVyKHZhbHVlKSB7CiAgICAgIHJldHVybiB0aGlzLmNvbnN0YW50cy5vdGhlcih2YWx1ZSk7CiAgICB9OwoKICAgIHJldHVybiBMYXp5T3Bjb2RlQnVpbGRlcjsKICB9KE9wY29kZUJ1aWxkZXIpOwoKICBfZXhwb3J0cy5MYXp5T3Bjb2RlQnVpbGRlciA9IExhenlPcGNvZGVCdWlsZGVyOwoKICB2YXIgRWFnZXJPcGNvZGVCdWlsZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9PcGNvZGVCdWlsZGVyMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEVhZ2VyT3Bjb2RlQnVpbGRlciwgX09wY29kZUJ1aWxkZXIyKTsKCiAgICBmdW5jdGlvbiBFYWdlck9wY29kZUJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBfT3Bjb2RlQnVpbGRlcjIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8xNCA9IEVhZ2VyT3Bjb2RlQnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMTQucHVzaEJsb2NrID0gZnVuY3Rpb24gcHVzaEJsb2NrKGJsb2NrKSB7CiAgICAgIHZhciBoYW5kbGUgPSBibG9jayA/IGJsb2NrLmNvbXBpbGUoKSA6IG51bGw7CiAgICAgIHRoaXMucHJpbWl0aXZlKGhhbmRsZSk7CiAgICB9OwoKICAgIF9wcm90bzE0LnJlc29sdmVCbG9jayA9IGZ1bmN0aW9uIHJlc29sdmVCbG9jaygpIHsKICAgICAgcmV0dXJuOwogICAgfTsKCiAgICBfcHJvdG8xNC5wdXNoTGF5b3V0ID0gZnVuY3Rpb24gcHVzaExheW91dChsYXlvdXQpIHsKICAgICAgaWYgKGxheW91dCkgewogICAgICAgIHRoaXMucHJpbWl0aXZlKGxheW91dC5jb21waWxlKCkpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMucHJpbWl0aXZlKG51bGwpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzE0LnJlc29sdmVMYXlvdXQgPSBmdW5jdGlvbiByZXNvbHZlTGF5b3V0KCkge307CgogICAgX3Byb3RvMTQuaW52b2tlU3RhdGljID0gZnVuY3Rpb24gaW52b2tlU3RhdGljKGNvbXBpbGFibGUpIHsKICAgICAgdmFyIGhhbmRsZSA9IGNvbXBpbGFibGUuY29tcGlsZSgpOyAvLyBJZiB0aGUgaGFuZGxlIGZvciB0aGUgaW52b2tlZCBjb21wb25lbnQgaXMgbm90IHlldCBrbm93biAoZm9yIGV4YW1wbGUsCiAgICAgIC8vIGJlY2F1c2UgdGhpcyBpcyBhIHJlY3Vyc2l2ZSBpbnZvY2F0aW9uIGFuZCB3ZSdyZSBzdGlsbCBjb21waWxpbmcpLCBwdXNoIGEKICAgICAgLy8gZnVuY3Rpb24gdGhhdCB3aWxsIHByb2R1Y2UgdGhlIGNvcnJlY3QgaGFuZGxlIHdoZW4gdGhlIGhlYXAgaXMKICAgICAgLy8gc2VyaWFsaXplZC4KCiAgICAgIGlmIChoYW5kbGUgPT09IFBMQUNFSE9MREVSX0hBTkRMRSQxKSB7CiAgICAgICAgdGhpcy5wdXNoTWFjaGluZSg1MAogICAgICAgIC8qIEludm9rZVN0YXRpYyAqLwogICAgICAgICwgZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuIGNvbXBpbGFibGUuY29tcGlsZSgpOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMucHVzaE1hY2hpbmUoNTAKICAgICAgICAvKiBJbnZva2VTdGF0aWMgKi8KICAgICAgICAsIGhhbmRsZSk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEVhZ2VyT3Bjb2RlQnVpbGRlcjsKICB9KE9wY29kZUJ1aWxkZXIpOwoKICBfZXhwb3J0cy5FYWdlck9wY29kZUJ1aWxkZXIgPSBFYWdlck9wY29kZUJ1aWxkZXI7CgogIHZhciBMYXp5Q29tcGlsZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Fic3RyYWN0Q29tcGlsZXIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShMYXp5Q29tcGlsZXIsIF9BYnN0cmFjdENvbXBpbGVyKTsKCiAgICAvLyBGSVhNRTogdHVybiB0byBzdGF0aWMgbWV0aG9kCiAgICBmdW5jdGlvbiBMYXp5Q29tcGlsZXIobG9va3VwLCByZXNvbHZlciwgbWFjcm9zKSB7CiAgICAgIHZhciBjb25zdGFudHMgPSBuZXcgX3Byb2dyYW0uTGF6eUNvbnN0YW50cyhyZXNvbHZlcik7CiAgICAgIHZhciBwcm9ncmFtID0gbmV3IF9wcm9ncmFtLlByb2dyYW0oY29uc3RhbnRzKTsKICAgICAgcmV0dXJuIF9BYnN0cmFjdENvbXBpbGVyLmNhbGwodGhpcywgbWFjcm9zLCBwcm9ncmFtLCBsb29rdXApIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzE1ID0gTGF6eUNvbXBpbGVyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xNS5idWlsZGVyRm9yID0gZnVuY3Rpb24gYnVpbGRlckZvcihjb250YWluaW5nTGF5b3V0KSB7CiAgICAgIHJldHVybiBuZXcgTGF6eU9wY29kZUJ1aWxkZXIodGhpcywgY29udGFpbmluZ0xheW91dCk7CiAgICB9OwoKICAgIHJldHVybiBMYXp5Q29tcGlsZXI7CiAgfShBYnN0cmFjdENvbXBpbGVyKTsKCiAgX2V4cG9ydHMuTGF6eUNvbXBpbGVyID0gTGF6eUNvbXBpbGVyOwoKICB2YXIgUGFydGlhbERlZmluaXRpb24gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBQYXJ0aWFsRGVmaW5pdGlvbihuYW1lLCAvLyBmb3IgZGVidWdnaW5nCiAgICB0ZW1wbGF0ZSkgewogICAgICB0aGlzLm5hbWUgPSBuYW1lOwogICAgICB0aGlzLnRlbXBsYXRlID0gdGVtcGxhdGU7CiAgICB9CgogICAgdmFyIF9wcm90bzE2ID0gUGFydGlhbERlZmluaXRpb24ucHJvdG90eXBlOwoKICAgIF9wcm90bzE2LmdldFBhcnRpYWwgPSBmdW5jdGlvbiBnZXRQYXJ0aWFsKCkgewogICAgICB2YXIgcGFydGlhbCA9IHRoaXMudGVtcGxhdGUuYXNQYXJ0aWFsKCk7CiAgICAgIHZhciBoYW5kbGUgPSBwYXJ0aWFsLmNvbXBpbGUoKTsKICAgICAgcmV0dXJuIHsKICAgICAgICBzeW1ib2xUYWJsZTogcGFydGlhbC5zeW1ib2xUYWJsZSwKICAgICAgICBoYW5kbGU6IGhhbmRsZQogICAgICB9OwogICAgfTsKCiAgICByZXR1cm4gUGFydGlhbERlZmluaXRpb247CiAgfSgpOwoKICBfZXhwb3J0cy5QYXJ0aWFsRGVmaW5pdGlvbiA9IFBhcnRpYWxEZWZpbml0aW9uOwogIHZhciBjbGllbnRJZCA9IDA7CgogIGZ1bmN0aW9uIHRlbXBsYXRlRmFjdG9yeShfcmVmMykgewogICAgdmFyIHRlbXBsYXRlSWQgPSBfcmVmMy5pZCwKICAgICAgICBtZXRhID0gX3JlZjMubWV0YSwKICAgICAgICBibG9jayA9IF9yZWYzLmJsb2NrOwogICAgdmFyIHBhcnNlZEJsb2NrOwogICAgdmFyIGlkID0gdGVtcGxhdGVJZCB8fCAiY2xpZW50LSIgKyBjbGllbnRJZCsrOwoKICAgIHZhciBjcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoY29tcGlsZXIsIGVudk1ldGEpIHsKICAgICAgdmFyIG5ld01ldGEgPSBlbnZNZXRhID8gKDAsIF91dGlsLmFzc2lnbikoe30sIGVudk1ldGEsIG1ldGEpIDogbWV0YTsKCiAgICAgIGlmICghcGFyc2VkQmxvY2spIHsKICAgICAgICBwYXJzZWRCbG9jayA9IEpTT04ucGFyc2UoYmxvY2spOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IFRlbXBsYXRlSW1wbChjb21waWxlciwgewogICAgICAgIGlkOiBpZCwKICAgICAgICBibG9jazogcGFyc2VkQmxvY2ssCiAgICAgICAgcmVmZXJyZXI6IG5ld01ldGEKICAgICAgfSk7CiAgICB9OwoKICAgIHJldHVybiB7CiAgICAgIGlkOiBpZCwKICAgICAgbWV0YTogbWV0YSwKICAgICAgY3JlYXRlOiBjcmVhdGUKICAgIH07CiAgfQoKICB2YXIgVGVtcGxhdGVJbXBsID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gVGVtcGxhdGVJbXBsKGNvbXBpbGVyLCBwYXJzZWRMYXlvdXQpIHsKICAgICAgdGhpcy5jb21waWxlciA9IGNvbXBpbGVyOwogICAgICB0aGlzLnBhcnNlZExheW91dCA9IHBhcnNlZExheW91dDsKICAgICAgdGhpcy5sYXlvdXQgPSBudWxsOwogICAgICB0aGlzLnBhcnRpYWwgPSBudWxsOwogICAgICB0aGlzLndyYXBwZWRMYXlvdXQgPSBudWxsOwogICAgICB2YXIgYmxvY2sgPSBwYXJzZWRMYXlvdXQuYmxvY2s7CiAgICAgIHRoaXMuc3ltYm9scyA9IGJsb2NrLnN5bWJvbHM7CiAgICAgIHRoaXMuaGFzRXZhbCA9IGJsb2NrLmhhc0V2YWw7CiAgICAgIHRoaXMucmVmZXJyZXIgPSBwYXJzZWRMYXlvdXQucmVmZXJyZXI7CiAgICAgIHRoaXMuaWQgPSBwYXJzZWRMYXlvdXQuaWQgfHwgImNsaWVudC0iICsgY2xpZW50SWQrKzsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTcgPSBUZW1wbGF0ZUltcGwucHJvdG90eXBlOwoKICAgIF9wcm90bzE3LmFzTGF5b3V0ID0gZnVuY3Rpb24gYXNMYXlvdXQoKSB7CiAgICAgIGlmICh0aGlzLmxheW91dCkgcmV0dXJuIHRoaXMubGF5b3V0OwogICAgICByZXR1cm4gdGhpcy5sYXlvdXQgPSBuZXcgQ29tcGlsYWJsZVByb2dyYW0odGhpcy5jb21waWxlciwgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgdGhpcy5wYXJzZWRMYXlvdXQsIHsKICAgICAgICBhc1BhcnRpYWw6IGZhbHNlCiAgICAgIH0pKTsKICAgIH07CgogICAgX3Byb3RvMTcuYXNQYXJ0aWFsID0gZnVuY3Rpb24gYXNQYXJ0aWFsKCkgewogICAgICBpZiAodGhpcy5wYXJ0aWFsKSByZXR1cm4gdGhpcy5wYXJ0aWFsOwogICAgICByZXR1cm4gdGhpcy5sYXlvdXQgPSBuZXcgQ29tcGlsYWJsZVByb2dyYW0odGhpcy5jb21waWxlciwgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgdGhpcy5wYXJzZWRMYXlvdXQsIHsKICAgICAgICBhc1BhcnRpYWw6IHRydWUKICAgICAgfSkpOwogICAgfTsKCiAgICBfcHJvdG8xNy5hc1dyYXBwZWRMYXlvdXQgPSBmdW5jdGlvbiBhc1dyYXBwZWRMYXlvdXQoKSB7CiAgICAgIGlmICh0aGlzLndyYXBwZWRMYXlvdXQpIHJldHVybiB0aGlzLndyYXBwZWRMYXlvdXQ7CiAgICAgIHJldHVybiB0aGlzLndyYXBwZWRMYXlvdXQgPSBuZXcgV3JhcHBlZEJ1aWxkZXIodGhpcy5jb21waWxlciwgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgdGhpcy5wYXJzZWRMYXlvdXQsIHsKICAgICAgICBhc1BhcnRpYWw6IGZhbHNlCiAgICAgIH0pKTsKICAgIH07CgogICAgcmV0dXJuIFRlbXBsYXRlSW1wbDsKICB9KCk7Cn0pOwpkZWZpbmUoIkBnbGltbWVyL3Byb2dyYW0iLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiLCAiQGdsaW1tZXIvdXRpbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfdXRpbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuT3Bjb2RlID0gX2V4cG9ydHMuUHJvZ3JhbSA9IF9leHBvcnRzLlJ1bnRpbWVQcm9ncmFtID0gX2V4cG9ydHMuV3JpdGVPbmx5UHJvZ3JhbSA9IF9leHBvcnRzLkhlYXAgPSBfZXhwb3J0cy5MYXp5Q29uc3RhbnRzID0gX2V4cG9ydHMuQ29uc3RhbnRzID0gX2V4cG9ydHMuUnVudGltZUNvbnN0YW50cyA9IF9leHBvcnRzLldyaXRlT25seUNvbnN0YW50cyA9IF9leHBvcnRzLldFTExfS05PV05fRU1QVFlfQVJSQVlfUE9TSVRJT04gPSB2b2lkIDA7CiAgdmFyIFVOUkVTT0xWRUQgPSB7fTsKICB2YXIgV0VMTF9LTk9XTl9FTVBUWV9BUlJBWV9QT1NJVElPTiA9IDA7CiAgX2V4cG9ydHMuV0VMTF9LTk9XTl9FTVBUWV9BUlJBWV9QT1NJVElPTiA9IFdFTExfS05PV05fRU1QVFlfQVJSQVlfUE9TSVRJT047CiAgdmFyIFdFTExfS05PV19FTVBUWV9BUlJBWSA9IE9iamVjdC5mcmVlemUoW10pOwoKICB2YXIgV3JpdGVPbmx5Q29uc3RhbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gV3JpdGVPbmx5Q29uc3RhbnRzKCkgewogICAgICAvLyBgMGAgbWVhbnMgTlVMTAogICAgICB0aGlzLnN0cmluZ3MgPSBbXTsKICAgICAgdGhpcy5hcnJheXMgPSBbV0VMTF9LTk9XX0VNUFRZX0FSUkFZXTsKICAgICAgdGhpcy50YWJsZXMgPSBbXTsKICAgICAgdGhpcy5oYW5kbGVzID0gW107CiAgICAgIHRoaXMucmVzb2x2ZWQgPSBbXTsKICAgICAgdGhpcy5udW1iZXJzID0gW107CiAgICB9CgogICAgdmFyIF9wcm90byA9IFdyaXRlT25seUNvbnN0YW50cy5wcm90b3R5cGU7CgogICAgX3Byb3RvLnN0cmluZyA9IGZ1bmN0aW9uIHN0cmluZyh2YWx1ZSkgewogICAgICB2YXIgaW5kZXggPSB0aGlzLnN0cmluZ3MuaW5kZXhPZih2YWx1ZSk7CgogICAgICBpZiAoaW5kZXggPiAtMSkgewogICAgICAgIHJldHVybiBpbmRleDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuc3RyaW5ncy5wdXNoKHZhbHVlKSAtIDE7CiAgICB9OwoKICAgIF9wcm90by5zdHJpbmdBcnJheSA9IGZ1bmN0aW9uIHN0cmluZ0FycmF5KHN0cmluZ3MpIHsKICAgICAgdmFyIF9zdHJpbmdzID0gbmV3IEFycmF5KHN0cmluZ3MubGVuZ3RoKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyaW5ncy5sZW5ndGg7IGkrKykgewogICAgICAgIF9zdHJpbmdzW2ldID0gdGhpcy5zdHJpbmcoc3RyaW5nc1tpXSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLmFycmF5KF9zdHJpbmdzKTsKICAgIH07CgogICAgX3Byb3RvLmFycmF5ID0gZnVuY3Rpb24gYXJyYXkodmFsdWVzKSB7CiAgICAgIGlmICh2YWx1ZXMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIFdFTExfS05PV05fRU1QVFlfQVJSQVlfUE9TSVRJT047CiAgICAgIH0KCiAgICAgIHZhciBpbmRleCA9IHRoaXMuYXJyYXlzLmluZGV4T2YodmFsdWVzKTsKCiAgICAgIGlmIChpbmRleCA+IC0xKSB7CiAgICAgICAgcmV0dXJuIGluZGV4OwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5hcnJheXMucHVzaCh2YWx1ZXMpIC0gMTsKICAgIH07CgogICAgX3Byb3RvLmhhbmRsZSA9IGZ1bmN0aW9uIGhhbmRsZShfaGFuZGxlKSB7CiAgICAgIHZhciBpbmRleCA9IHRoaXMuaGFuZGxlcy5pbmRleE9mKF9oYW5kbGUpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICByZXR1cm4gaW5kZXg7CiAgICAgIH0KCiAgICAgIHRoaXMucmVzb2x2ZWQucHVzaChVTlJFU09MVkVEKTsKICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlcy5wdXNoKF9oYW5kbGUpIC0gMTsKICAgIH07CgogICAgX3Byb3RvLnNlcmlhbGl6YWJsZSA9IGZ1bmN0aW9uIHNlcmlhbGl6YWJsZSh2YWx1ZSkgewogICAgICB2YXIgc3RyID0gSlNPTi5zdHJpbmdpZnkodmFsdWUpOwogICAgICB2YXIgaW5kZXggPSB0aGlzLnN0cmluZ3MuaW5kZXhPZihzdHIpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICByZXR1cm4gaW5kZXg7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLnN0cmluZ3MucHVzaChzdHIpIC0gMTsKICAgIH07CgogICAgX3Byb3RvLm51bWJlciA9IGZ1bmN0aW9uIG51bWJlcihfbnVtYmVyKSB7CiAgICAgIHZhciBpbmRleCA9IHRoaXMubnVtYmVycy5pbmRleE9mKF9udW1iZXIpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICByZXR1cm4gaW5kZXg7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLm51bWJlcnMucHVzaChfbnVtYmVyKSAtIDE7CiAgICB9OwoKICAgIF9wcm90by50b1Bvb2wgPSBmdW5jdGlvbiB0b1Bvb2woKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgc3RyaW5nczogdGhpcy5zdHJpbmdzLAogICAgICAgIGFycmF5czogdGhpcy5hcnJheXMsCiAgICAgICAgaGFuZGxlczogdGhpcy5oYW5kbGVzLAogICAgICAgIG51bWJlcnM6IHRoaXMubnVtYmVycwogICAgICB9OwogICAgfTsKCiAgICByZXR1cm4gV3JpdGVPbmx5Q29uc3RhbnRzOwogIH0oKTsKCiAgX2V4cG9ydHMuV3JpdGVPbmx5Q29uc3RhbnRzID0gV3JpdGVPbmx5Q29uc3RhbnRzOwoKICB2YXIgUnVudGltZUNvbnN0YW50cyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJ1bnRpbWVDb25zdGFudHMocmVzb2x2ZXIsIHBvb2wpIHsKICAgICAgdGhpcy5yZXNvbHZlciA9IHJlc29sdmVyOwogICAgICB0aGlzLnN0cmluZ3MgPSBwb29sLnN0cmluZ3M7CiAgICAgIHRoaXMuYXJyYXlzID0gcG9vbC5hcnJheXM7CiAgICAgIHRoaXMuaGFuZGxlcyA9IHBvb2wuaGFuZGxlczsKICAgICAgdGhpcy5yZXNvbHZlZCA9IHRoaXMuaGFuZGxlcy5tYXAoZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBVTlJFU09MVkVEOwogICAgICB9KTsKICAgICAgdGhpcy5udW1iZXJzID0gcG9vbC5udW1iZXJzOwogICAgfQoKICAgIHZhciBfcHJvdG8yID0gUnVudGltZUNvbnN0YW50cy5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5nZXRTdHJpbmcgPSBmdW5jdGlvbiBnZXRTdHJpbmcodmFsdWUpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RyaW5nc1t2YWx1ZV07CiAgICB9OwoKICAgIF9wcm90bzIuZ2V0TnVtYmVyID0gZnVuY3Rpb24gZ2V0TnVtYmVyKHZhbHVlKSB7CiAgICAgIHJldHVybiB0aGlzLm51bWJlcnNbdmFsdWVdOwogICAgfTsKCiAgICBfcHJvdG8yLmdldFN0cmluZ0FycmF5ID0gZnVuY3Rpb24gZ2V0U3RyaW5nQXJyYXkodmFsdWUpIHsKICAgICAgdmFyIG5hbWVzID0gdGhpcy5nZXRBcnJheSh2YWx1ZSk7CgogICAgICB2YXIgX25hbWVzID0gbmV3IEFycmF5KG5hbWVzLmxlbmd0aCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIG4gPSBuYW1lc1tpXTsKICAgICAgICBfbmFtZXNbaV0gPSB0aGlzLmdldFN0cmluZyhuKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9uYW1lczsKICAgIH07CgogICAgX3Byb3RvMi5nZXRBcnJheSA9IGZ1bmN0aW9uIGdldEFycmF5KHZhbHVlKSB7CiAgICAgIHJldHVybiB0aGlzLmFycmF5c1t2YWx1ZV07CiAgICB9OwoKICAgIF9wcm90bzIucmVzb2x2ZUhhbmRsZSA9IGZ1bmN0aW9uIHJlc29sdmVIYW5kbGUoaW5kZXgpIHsKICAgICAgdmFyIHJlc29sdmVkID0gdGhpcy5yZXNvbHZlZFtpbmRleF07CgogICAgICBpZiAocmVzb2x2ZWQgPT09IFVOUkVTT0xWRUQpIHsKICAgICAgICB2YXIgaGFuZGxlID0gdGhpcy5oYW5kbGVzW2luZGV4XTsKICAgICAgICByZXNvbHZlZCA9IHRoaXMucmVzb2x2ZWRbaW5kZXhdID0gdGhpcy5yZXNvbHZlci5yZXNvbHZlKGhhbmRsZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiByZXNvbHZlZDsKICAgIH07CgogICAgX3Byb3RvMi5nZXRTZXJpYWxpemFibGUgPSBmdW5jdGlvbiBnZXRTZXJpYWxpemFibGUocykgewogICAgICByZXR1cm4gSlNPTi5wYXJzZSh0aGlzLnN0cmluZ3Nbc10pOwogICAgfTsKCiAgICByZXR1cm4gUnVudGltZUNvbnN0YW50czsKICB9KCk7CgogIF9leHBvcnRzLlJ1bnRpbWVDb25zdGFudHMgPSBSdW50aW1lQ29uc3RhbnRzOwoKICB2YXIgQ29uc3RhbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Xcml0ZU9ubHlDb25zdGFudHMpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDb25zdGFudHMsIF9Xcml0ZU9ubHlDb25zdGFudHMpOwoKICAgIGZ1bmN0aW9uIENvbnN0YW50cyhyZXNvbHZlciwgcG9vbCkgewogICAgICB2YXIgX3RoaXM7CgogICAgICBfdGhpcyA9IF9Xcml0ZU9ubHlDb25zdGFudHMuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpcy5yZXNvbHZlciA9IHJlc29sdmVyOwoKICAgICAgaWYgKHBvb2wpIHsKICAgICAgICBfdGhpcy5zdHJpbmdzID0gcG9vbC5zdHJpbmdzOwogICAgICAgIF90aGlzLmFycmF5cyA9IHBvb2wuYXJyYXlzOwogICAgICAgIF90aGlzLmhhbmRsZXMgPSBwb29sLmhhbmRsZXM7CiAgICAgICAgX3RoaXMucmVzb2x2ZWQgPSBfdGhpcy5oYW5kbGVzLm1hcChmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gVU5SRVNPTFZFRDsKICAgICAgICB9KTsKICAgICAgICBfdGhpcy5udW1iZXJzID0gcG9vbC5udW1iZXJzOwogICAgICB9CgogICAgICByZXR1cm4gX3RoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzMgPSBDb25zdGFudHMucHJvdG90eXBlOwoKICAgIF9wcm90bzMuZ2V0TnVtYmVyID0gZnVuY3Rpb24gZ2V0TnVtYmVyKHZhbHVlKSB7CiAgICAgIHJldHVybiB0aGlzLm51bWJlcnNbdmFsdWVdOwogICAgfTsKCiAgICBfcHJvdG8zLmdldFN0cmluZyA9IGZ1bmN0aW9uIGdldFN0cmluZyh2YWx1ZSkgewogICAgICByZXR1cm4gdGhpcy5zdHJpbmdzW3ZhbHVlXTsKICAgIH07CgogICAgX3Byb3RvMy5nZXRTdHJpbmdBcnJheSA9IGZ1bmN0aW9uIGdldFN0cmluZ0FycmF5KHZhbHVlKSB7CiAgICAgIHZhciBuYW1lcyA9IHRoaXMuZ2V0QXJyYXkodmFsdWUpOwoKICAgICAgdmFyIF9uYW1lcyA9IG5ldyBBcnJheShuYW1lcy5sZW5ndGgpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBuID0gbmFtZXNbaV07CiAgICAgICAgX25hbWVzW2ldID0gdGhpcy5nZXRTdHJpbmcobik7CiAgICAgIH0KCiAgICAgIHJldHVybiBfbmFtZXM7CiAgICB9OwoKICAgIF9wcm90bzMuZ2V0QXJyYXkgPSBmdW5jdGlvbiBnZXRBcnJheSh2YWx1ZSkgewogICAgICByZXR1cm4gdGhpcy5hcnJheXNbdmFsdWVdOwogICAgfTsKCiAgICBfcHJvdG8zLnJlc29sdmVIYW5kbGUgPSBmdW5jdGlvbiByZXNvbHZlSGFuZGxlKGluZGV4KSB7CiAgICAgIHZhciByZXNvbHZlZCA9IHRoaXMucmVzb2x2ZWRbaW5kZXhdOwoKICAgICAgaWYgKHJlc29sdmVkID09PSBVTlJFU09MVkVEKSB7CiAgICAgICAgdmFyIGhhbmRsZSA9IHRoaXMuaGFuZGxlc1tpbmRleF07CiAgICAgICAgcmVzb2x2ZWQgPSB0aGlzLnJlc29sdmVkW2luZGV4XSA9IHRoaXMucmVzb2x2ZXIucmVzb2x2ZShoYW5kbGUpOwogICAgICB9CgogICAgICByZXR1cm4gcmVzb2x2ZWQ7CiAgICB9OwoKICAgIF9wcm90bzMuZ2V0U2VyaWFsaXphYmxlID0gZnVuY3Rpb24gZ2V0U2VyaWFsaXphYmxlKHMpIHsKICAgICAgcmV0dXJuIEpTT04ucGFyc2UodGhpcy5zdHJpbmdzW3NdKTsKICAgIH07CgogICAgcmV0dXJuIENvbnN0YW50czsKICB9KFdyaXRlT25seUNvbnN0YW50cyk7CgogIF9leHBvcnRzLkNvbnN0YW50cyA9IENvbnN0YW50czsKCiAgdmFyIExhenlDb25zdGFudHMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NvbnN0YW50cykgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKExhenlDb25zdGFudHMsIF9Db25zdGFudHMpOwoKICAgIGZ1bmN0aW9uIExhenlDb25zdGFudHMoKSB7CiAgICAgIHZhciBfdGhpczI7CgogICAgICBfdGhpczIgPSBfQ29uc3RhbnRzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgICAgX3RoaXMyLm90aGVycyA9IFtdOwogICAgICBfdGhpczIuc2VyaWFsaXphYmxlcyA9IFtdOwogICAgICByZXR1cm4gX3RoaXMyOwogICAgfQoKICAgIHZhciBfcHJvdG80ID0gTGF6eUNvbnN0YW50cy5wcm90b3R5cGU7CgogICAgX3Byb3RvNC5zZXJpYWxpemFibGUgPSBmdW5jdGlvbiBzZXJpYWxpemFibGUodmFsdWUpIHsKICAgICAgdmFyIGluZGV4ID0gdGhpcy5zZXJpYWxpemFibGVzLmluZGV4T2YodmFsdWUpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICByZXR1cm4gaW5kZXg7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLnNlcmlhbGl6YWJsZXMucHVzaCh2YWx1ZSkgLSAxOwogICAgfTsKCiAgICBfcHJvdG80LmdldFNlcmlhbGl6YWJsZSA9IGZ1bmN0aW9uIGdldFNlcmlhbGl6YWJsZShzKSB7CiAgICAgIHJldHVybiB0aGlzLnNlcmlhbGl6YWJsZXNbc107CiAgICB9OwoKICAgIF9wcm90bzQuZ2V0T3RoZXIgPSBmdW5jdGlvbiBnZXRPdGhlcih2YWx1ZSkgewogICAgICByZXR1cm4gdGhpcy5vdGhlcnNbdmFsdWUgLSAxXTsKICAgIH07CgogICAgX3Byb3RvNC5vdGhlciA9IGZ1bmN0aW9uIG90aGVyKF9vdGhlcikgewogICAgICByZXR1cm4gdGhpcy5vdGhlcnMucHVzaChfb3RoZXIpOwogICAgfTsKCiAgICByZXR1cm4gTGF6eUNvbnN0YW50czsKICB9KENvbnN0YW50cyk7CgogIF9leHBvcnRzLkxhenlDb25zdGFudHMgPSBMYXp5Q29uc3RhbnRzOwoKICB2YXIgT3Bjb2RlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gT3Bjb2RlKGhlYXApIHsKICAgICAgdGhpcy5oZWFwID0gaGVhcDsKICAgICAgdGhpcy5vZmZzZXQgPSAwOwogICAgfQoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoT3Bjb2RlLCBbewogICAgICBrZXk6ICJzaXplIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIHJhd1R5cGUgPSB0aGlzLmhlYXAuZ2V0YnlhZGRyKHRoaXMub2Zmc2V0KTsKICAgICAgICByZXR1cm4gKChyYXdUeXBlICYgNzY4CiAgICAgICAgLyogT1BFUkFORF9MRU5fTUFTSyAqLwogICAgICAgICkgPj4gOAogICAgICAgIC8qIEFSR19TSElGVCAqLwogICAgICAgICkgKyAxOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImlzTWFjaGluZSIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciByYXdUeXBlID0gdGhpcy5oZWFwLmdldGJ5YWRkcih0aGlzLm9mZnNldCk7CiAgICAgICAgcmV0dXJuIHJhd1R5cGUgJiAxMDI0CiAgICAgICAgLyogTUFDSElORV9NQVNLICovCiAgICAgICAgOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInR5cGUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5oZWFwLmdldGJ5YWRkcih0aGlzLm9mZnNldCkgJiAyNTUKICAgICAgICAvKiBUWVBFX01BU0sgKi8KICAgICAgICA7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAib3AxIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaGVhcC5nZXRieWFkZHIodGhpcy5vZmZzZXQgKyAxKTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJvcDIiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5oZWFwLmdldGJ5YWRkcih0aGlzLm9mZnNldCArIDIpOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogIm9wMyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmhlYXAuZ2V0YnlhZGRyKHRoaXMub2Zmc2V0ICsgMyk7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBPcGNvZGU7CiAgfSgpOwoKICBfZXhwb3J0cy5PcGNvZGUgPSBPcGNvZGU7CgogIGZ1bmN0aW9uIGVuY29kZVRhYmxlSW5mbyhzY29wZVNpemUsIHN0YXRlKSB7CiAgICByZXR1cm4gc3RhdGUgfCBzY29wZVNpemUgPDwgMjsKICB9CgogIGZ1bmN0aW9uIGNoYW5nZVN0YXRlKGluZm8sIG5ld1N0YXRlKSB7CiAgICByZXR1cm4gaW5mbyB8IG5ld1N0YXRlIDw8IDMwOwogIH0KCiAgdmFyIFBBR0VfU0laRSA9IDB4MTAwMDAwOwogIC8qKgogICAqIFRoZSBIZWFwIGlzIHJlc3BvbnNpYmxlIGZvciBkeW5hbWljYWxseSBhbGxvY2F0aW5nCiAgICogbWVtb3J5IGluIHdoaWNoIHdlIHJlYWQvd3JpdGUgdGhlIFZNJ3MgaW5zdHJ1Y3Rpb25zCiAgICogZnJvbS90by4gV2hlbiB3ZSBtYWxsb2Mgd2UgcGFzcyBvdXQgYSBWTUhhbmRsZSwgd2hpY2gKICAgKiBpcyB1c2VkIGFzIGFuIGluZGlyZWN0IHdheSBvZiBhY2Nlc3NpbmcgdGhlIG1lbW9yeSBkdXJpbmcKICAgKiBleGVjdXRpb24gb2YgdGhlIFZNLiBJbnRlcm5hbGx5IHdlIHRyYWNrIHRoZSBkaWZmZXJlbnQKICAgKiByZWdpb25zIG9mIHRoZSBtZW1vcnkgaW4gYW4gaW50IGFycmF5IGtub3duIGFzIHRoZSB0YWJsZS4KICAgKgogICAqIFRoZSB0YWJsZSAzMi1iaXQgYWxpZ25lZCBhbmQgaGFzIHRoZSBmb2xsb3dpbmcgbGF5b3V0OgogICAqCiAgICogfCAuLi4gfCBocCAodTMyKSB8ICAgICAgIGluZm8gKHUzMikgICB8IHNpemUgKHUzMikgfAogICAqIHwgLi4uIHwgIEhhbmRsZSAgfCBTY29wZSBTaXplIHwgU3RhdGUgfCBTaXplICAgICAgIHwKICAgKiB8IC4uLiB8IDMyYml0cyAgIHwgMzBiaXRzICAgICB8IDJiaXRzIHwgMzJiaXQgICAgICB8CiAgICoKICAgKiBXaXRoIHRoaXMgaW5mb3JtYXRpb24gd2UgZWZmZWN0aXZlbHkgaGF2ZSB0aGUgYWJpbGl0eSB0bwogICAqIGNvbnRyb2wgd2hlbiB3ZSB3YW50IHRvIGZyZWUgbWVtb3J5LiBUaGF0IGJlaW5nIHNhaWQgeW91CiAgICogY2FuIG5vdCBmcmVlIGR1cmluZyBleGVjdXRpb24gYXMgcmF3IGFkZHJlc3MgYXJlIG9ubHkKICAgKiB2YWxpZCBkdXJpbmcgdGhlIGV4ZWN1dGlvbi4gVGhpcyBtZWFucyB5b3UgY2Fubm90IGNsb3NlCiAgICogb3ZlciB0aGVtIGFzIHlvdSB3aWxsIGhhdmUgYSBiYWQgbWVtb3J5IGFjY2VzcyBleGNlcHRpb24uCiAgICovCgogIHZhciBIZWFwID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSGVhcChzZXJpYWxpemVkSGVhcCkgewogICAgICB0aGlzLnBsYWNlaG9sZGVycyA9IFtdOwogICAgICB0aGlzLm9mZnNldCA9IDA7CiAgICAgIHRoaXMuaGFuZGxlID0gMDsKICAgICAgdGhpcy5jYXBhY2l0eSA9IFBBR0VfU0laRTsKCiAgICAgIGlmIChzZXJpYWxpemVkSGVhcCkgewogICAgICAgIHZhciBidWZmZXIgPSBzZXJpYWxpemVkSGVhcC5idWZmZXIsCiAgICAgICAgICAgIHRhYmxlID0gc2VyaWFsaXplZEhlYXAudGFibGUsCiAgICAgICAgICAgIGhhbmRsZSA9IHNlcmlhbGl6ZWRIZWFwLmhhbmRsZTsKICAgICAgICB0aGlzLmhlYXAgPSBuZXcgVWludDMyQXJyYXkoYnVmZmVyKTsKICAgICAgICB0aGlzLnRhYmxlID0gdGFibGU7CiAgICAgICAgdGhpcy5vZmZzZXQgPSB0aGlzLmhlYXAubGVuZ3RoOwogICAgICAgIHRoaXMuaGFuZGxlID0gaGFuZGxlOwogICAgICAgIHRoaXMuY2FwYWNpdHkgPSAwOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuaGVhcCA9IG5ldyBVaW50MzJBcnJheShQQUdFX1NJWkUpOwogICAgICAgIHRoaXMudGFibGUgPSBbXTsKICAgICAgfQogICAgfQoKICAgIHZhciBfcHJvdG81ID0gSGVhcC5wcm90b3R5cGU7CgogICAgX3Byb3RvNS5wdXNoID0gZnVuY3Rpb24gcHVzaChpdGVtKSB7CiAgICAgIHRoaXMuc2l6ZUNoZWNrKCk7CiAgICAgIHRoaXMuaGVhcFt0aGlzLm9mZnNldCsrXSA9IGl0ZW07CiAgICB9OwoKICAgIF9wcm90bzUuc2l6ZUNoZWNrID0gZnVuY3Rpb24gc2l6ZUNoZWNrKCkgewogICAgICBpZiAodGhpcy5jYXBhY2l0eSA9PT0gMCkgewogICAgICAgIHZhciBoZWFwID0gc2xpY2UodGhpcy5oZWFwLCAwLCB0aGlzLm9mZnNldCk7CiAgICAgICAgdGhpcy5oZWFwID0gbmV3IFVpbnQzMkFycmF5KGhlYXAubGVuZ3RoICsgUEFHRV9TSVpFKTsKICAgICAgICB0aGlzLmhlYXAuc2V0KGhlYXAsIDApOwogICAgICAgIHRoaXMuY2FwYWNpdHkgPSBQQUdFX1NJWkU7CiAgICAgIH0KCiAgICAgIHRoaXMuY2FwYWNpdHktLTsKICAgIH07CgogICAgX3Byb3RvNS5nZXRieWFkZHIgPSBmdW5jdGlvbiBnZXRieWFkZHIoYWRkcmVzcykgewogICAgICByZXR1cm4gdGhpcy5oZWFwW2FkZHJlc3NdOwogICAgfTsKCiAgICBfcHJvdG81LnNldGJ5YWRkciA9IGZ1bmN0aW9uIHNldGJ5YWRkcihhZGRyZXNzLCB2YWx1ZSkgewogICAgICB0aGlzLmhlYXBbYWRkcmVzc10gPSB2YWx1ZTsKICAgIH07CgogICAgX3Byb3RvNS5tYWxsb2MgPSBmdW5jdGlvbiBtYWxsb2MoKSB7CiAgICAgIC8vIHB1c2ggb2Zmc2V0LCBpbmZvLCBzaXplCiAgICAgIHRoaXMudGFibGUucHVzaCh0aGlzLm9mZnNldCwgMCwgMCk7CiAgICAgIHZhciBoYW5kbGUgPSB0aGlzLmhhbmRsZTsKICAgICAgdGhpcy5oYW5kbGUgKz0gMwogICAgICAvKiBFTlRSWV9TSVpFICovCiAgICAgIDsKICAgICAgcmV0dXJuIGhhbmRsZTsKICAgIH07CgogICAgX3Byb3RvNS5maW5pc2hNYWxsb2MgPSBmdW5jdGlvbiBmaW5pc2hNYWxsb2MoaGFuZGxlLCBzY29wZVNpemUpIHsKICAgICAgdGhpcy50YWJsZVtoYW5kbGUgKyAxCiAgICAgIC8qIElORk9fT0ZGU0VUICovCiAgICAgIF0gPSBlbmNvZGVUYWJsZUluZm8oc2NvcGVTaXplLCAwCiAgICAgIC8qIEFsbG9jYXRlZCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG81LnNpemUgPSBmdW5jdGlvbiBzaXplKCkgewogICAgICByZXR1cm4gdGhpcy5vZmZzZXQ7CiAgICB9IC8vIEl0IGlzIGlsbGVnYWwgdG8gY2xvc2Ugb3ZlciB0aGlzIGFkZHJlc3MsIGFzIGNvbXBhY3Rpb24KICAgIC8vIG1heSBtb3ZlIGl0LiBIb3dldmVyLCBpdCBpcyBsZWdhbCB0byB1c2UgdGhpcyBhZGRyZXNzCiAgICAvLyBtdWx0aXBsZSB0aW1lcyBiZXR3ZWVuIGNvbXBhY3Rpb25zLgogICAgOwoKICAgIF9wcm90bzUuZ2V0YWRkciA9IGZ1bmN0aW9uIGdldGFkZHIoaGFuZGxlKSB7CiAgICAgIHJldHVybiB0aGlzLnRhYmxlW2hhbmRsZV07CiAgICB9OwoKICAgIF9wcm90bzUuZ2V0aGFuZGxlID0gZnVuY3Rpb24gZ2V0aGFuZGxlKGFkZHJlc3MpIHsKICAgICAgdGhpcy50YWJsZS5wdXNoKGFkZHJlc3MsIGVuY29kZVRhYmxlSW5mbygwLCAzCiAgICAgIC8qIFBvaW50ZXIgKi8KICAgICAgKSwgMCk7CiAgICAgIHZhciBoYW5kbGUgPSB0aGlzLmhhbmRsZTsKICAgICAgdGhpcy5oYW5kbGUgKz0gMwogICAgICAvKiBFTlRSWV9TSVpFICovCiAgICAgIDsKICAgICAgcmV0dXJuIGhhbmRsZTsKICAgIH07CgogICAgX3Byb3RvNS5zaXplb2YgPSBmdW5jdGlvbiBzaXplb2YoaGFuZGxlKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH07CgogICAgX3Byb3RvNS5zY29wZXNpemVvZiA9IGZ1bmN0aW9uIHNjb3Blc2l6ZW9mKGhhbmRsZSkgewogICAgICB2YXIgaW5mbyA9IHRoaXMudGFibGVbaGFuZGxlICsgMQogICAgICAvKiBJTkZPX09GRlNFVCAqLwogICAgICBdOwogICAgICByZXR1cm4gaW5mbyA+PiAyOwogICAgfTsKCiAgICBfcHJvdG81LmZyZWUgPSBmdW5jdGlvbiBmcmVlKGhhbmRsZSkgewogICAgICB2YXIgaW5mbyA9IHRoaXMudGFibGVbaGFuZGxlICsgMQogICAgICAvKiBJTkZPX09GRlNFVCAqLwogICAgICBdOwogICAgICB0aGlzLnRhYmxlW2hhbmRsZSArIDEKICAgICAgLyogSU5GT19PRkZTRVQgKi8KICAgICAgXSA9IGNoYW5nZVN0YXRlKGluZm8sIDEKICAgICAgLyogRnJlZWQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvNS5wdXNoUGxhY2Vob2xkZXIgPSBmdW5jdGlvbiBwdXNoUGxhY2Vob2xkZXIodmFsdWVGdW5jKSB7CiAgICAgIHRoaXMuc2l6ZUNoZWNrKCk7CiAgICAgIHZhciBhZGRyZXNzID0gdGhpcy5vZmZzZXQrKzsKICAgICAgdGhpcy5oZWFwW2FkZHJlc3NdID0gMjE0NzQ4MzY0NwogICAgICAvKiBNQVhfU0laRSAqLwogICAgICA7CiAgICAgIHRoaXMucGxhY2Vob2xkZXJzLnB1c2goW2FkZHJlc3MsIHZhbHVlRnVuY10pOwogICAgfTsKCiAgICBfcHJvdG81LnBhdGNoUGxhY2Vob2xkZXJzID0gZnVuY3Rpb24gcGF0Y2hQbGFjZWhvbGRlcnMoKSB7CiAgICAgIHZhciBwbGFjZWhvbGRlcnMgPSB0aGlzLnBsYWNlaG9sZGVyczsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGxhY2Vob2xkZXJzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIF9wbGFjZWhvbGRlcnMkaSA9IHBsYWNlaG9sZGVyc1tpXSwKICAgICAgICAgICAgYWRkcmVzcyA9IF9wbGFjZWhvbGRlcnMkaVswXSwKICAgICAgICAgICAgZ2V0VmFsdWUgPSBfcGxhY2Vob2xkZXJzJGlbMV07CiAgICAgICAgdGhpcy5zZXRieWFkZHIoYWRkcmVzcywgZ2V0VmFsdWUoKSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNS5jYXB0dXJlID0gZnVuY3Rpb24gY2FwdHVyZShvZmZzZXQpIHsKICAgICAgaWYgKG9mZnNldCA9PT0gdm9pZCAwKSB7CiAgICAgICAgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7CiAgICAgIH0KCiAgICAgIHRoaXMucGF0Y2hQbGFjZWhvbGRlcnMoKTsgLy8gT25seSBjYWxsZWQgaW4gZWFnZXIgbW9kZQoKICAgICAgdmFyIGJ1ZmZlciA9IHNsaWNlKHRoaXMuaGVhcCwgMCwgb2Zmc2V0KS5idWZmZXI7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiB0aGlzLmhhbmRsZSwKICAgICAgICB0YWJsZTogdGhpcy50YWJsZSwKICAgICAgICBidWZmZXI6IGJ1ZmZlcgogICAgICB9OwogICAgfTsKCiAgICByZXR1cm4gSGVhcDsKICB9KCk7CgogIF9leHBvcnRzLkhlYXAgPSBIZWFwOwoKICB2YXIgV3JpdGVPbmx5UHJvZ3JhbSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFdyaXRlT25seVByb2dyYW0oY29uc3RhbnRzLCBoZWFwKSB7CiAgICAgIGlmIChjb25zdGFudHMgPT09IHZvaWQgMCkgewogICAgICAgIGNvbnN0YW50cyA9IG5ldyBXcml0ZU9ubHlDb25zdGFudHMoKTsKICAgICAgfQoKICAgICAgaWYgKGhlYXAgPT09IHZvaWQgMCkgewogICAgICAgIGhlYXAgPSBuZXcgSGVhcCgpOwogICAgICB9CgogICAgICB0aGlzLmNvbnN0YW50cyA9IGNvbnN0YW50czsKICAgICAgdGhpcy5oZWFwID0gaGVhcDsKICAgICAgdGhpcy5fb3Bjb2RlID0gbmV3IE9wY29kZSh0aGlzLmhlYXApOwogICAgfQoKICAgIHZhciBfcHJvdG82ID0gV3JpdGVPbmx5UHJvZ3JhbS5wcm90b3R5cGU7CgogICAgX3Byb3RvNi5vcGNvZGUgPSBmdW5jdGlvbiBvcGNvZGUob2Zmc2V0KSB7CiAgICAgIHRoaXMuX29wY29kZS5vZmZzZXQgPSBvZmZzZXQ7CiAgICAgIHJldHVybiB0aGlzLl9vcGNvZGU7CiAgICB9OwoKICAgIHJldHVybiBXcml0ZU9ubHlQcm9ncmFtOwogIH0oKTsKCiAgX2V4cG9ydHMuV3JpdGVPbmx5UHJvZ3JhbSA9IFdyaXRlT25seVByb2dyYW07CgogIHZhciBSdW50aW1lUHJvZ3JhbSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJ1bnRpbWVQcm9ncmFtKGNvbnN0YW50cywgaGVhcCkgewogICAgICB0aGlzLmNvbnN0YW50cyA9IGNvbnN0YW50czsKICAgICAgdGhpcy5oZWFwID0gaGVhcDsKICAgICAgdGhpcy5fb3Bjb2RlID0gbmV3IE9wY29kZSh0aGlzLmhlYXApOwogICAgfQoKICAgIFJ1bnRpbWVQcm9ncmFtLmh5ZHJhdGUgPSBmdW5jdGlvbiBoeWRyYXRlKHJhd0hlYXAsIHBvb2wsIHJlc29sdmVyKSB7CiAgICAgIHZhciBoZWFwID0gbmV3IEhlYXAocmF3SGVhcCk7CiAgICAgIHZhciBjb25zdGFudHMgPSBuZXcgUnVudGltZUNvbnN0YW50cyhyZXNvbHZlciwgcG9vbCk7CiAgICAgIHJldHVybiBuZXcgUnVudGltZVByb2dyYW0oY29uc3RhbnRzLCBoZWFwKTsKICAgIH07CgogICAgdmFyIF9wcm90bzcgPSBSdW50aW1lUHJvZ3JhbS5wcm90b3R5cGU7CgogICAgX3Byb3RvNy5vcGNvZGUgPSBmdW5jdGlvbiBvcGNvZGUob2Zmc2V0KSB7CiAgICAgIHRoaXMuX29wY29kZS5vZmZzZXQgPSBvZmZzZXQ7CiAgICAgIHJldHVybiB0aGlzLl9vcGNvZGU7CiAgICB9OwoKICAgIHJldHVybiBSdW50aW1lUHJvZ3JhbTsKICB9KCk7CgogIF9leHBvcnRzLlJ1bnRpbWVQcm9ncmFtID0gUnVudGltZVByb2dyYW07CgogIHZhciBQcm9ncmFtID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Xcml0ZU9ubHlQcm9ncmFtKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUHJvZ3JhbSwgX1dyaXRlT25seVByb2dyYW0pOwoKICAgIGZ1bmN0aW9uIFByb2dyYW0oKSB7CiAgICAgIHJldHVybiBfV3JpdGVPbmx5UHJvZ3JhbS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgcmV0dXJuIFByb2dyYW07CiAgfShXcml0ZU9ubHlQcm9ncmFtKTsKCiAgX2V4cG9ydHMuUHJvZ3JhbSA9IFByb2dyYW07CgogIGZ1bmN0aW9uIHNsaWNlKGFyciwgc3RhcnQsIGVuZCkgewogICAgaWYgKGFyci5zbGljZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBhcnIuc2xpY2Uoc3RhcnQsIGVuZCk7CiAgICB9CgogICAgdmFyIHJldCA9IG5ldyBVaW50MzJBcnJheShlbmQpOwoKICAgIGZvciAoOyBzdGFydCA8IGVuZDsgc3RhcnQrKykgewogICAgICByZXRbc3RhcnRdID0gYXJyW3N0YXJ0XTsKICAgIH0KCiAgICByZXR1cm4gcmV0OwogIH0KfSk7CmRlZmluZSgiQGdsaW1tZXIvcmVmZXJlbmNlIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBnbGltbWVyL3V0aWwiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX3V0aWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLm1hcCA9IG1hcDsKICBfZXhwb3J0cy5pc01vZGlmaWVkID0gaXNNb2RpZmllZDsKICBfZXhwb3J0cy5idW1wID0gYnVtcDsKICBfZXhwb3J0cy52YWx1ZSA9IF92YWx1ZTI7CiAgX2V4cG9ydHMudmFsaWRhdGUgPSB2YWxpZGF0ZTsKICBfZXhwb3J0cy5jcmVhdGVUYWcgPSBjcmVhdGVUYWc7CiAgX2V4cG9ydHMuY3JlYXRlVXBkYXRhYmxlVGFnID0gY3JlYXRlVXBkYXRhYmxlVGFnOwogIF9leHBvcnRzLmlzQ29uc3QgPSBpc0NvbnN0OwogIF9leHBvcnRzLmlzQ29uc3RUYWcgPSBpc0NvbnN0VGFnOwogIF9leHBvcnRzLmNvbWJpbmVUYWdnZWQgPSBjb21iaW5lVGFnZ2VkOwogIF9leHBvcnRzLmNvbWJpbmVTbGljZSA9IGNvbWJpbmVTbGljZTsKICBfZXhwb3J0cy5jb21iaW5lID0gY29tYmluZTsKICBfZXhwb3J0cy5DVVJSRU5UX1RBRyA9IF9leHBvcnRzLlZPTEFUSUxFX1RBRyA9IF9leHBvcnRzLkNPTlNUQU5UX1RBRyA9IF9leHBvcnRzLnVwZGF0ZSA9IF9leHBvcnRzLmRpcnR5ID0gX2V4cG9ydHMuTW9ub21vcnBoaWNUYWdJbXBsID0gX2V4cG9ydHMuQUxMT1dfQ1lDTEVTID0gX2V4cG9ydHMuQ09NUFVURSA9IF9leHBvcnRzLlZPTEFUSUxFID0gX2V4cG9ydHMuSU5JVElBTCA9IF9leHBvcnRzLkNPTlNUQU5UID0gX2V4cG9ydHMuSXRlcmF0b3JTeW5jaHJvbml6ZXIgPSBfZXhwb3J0cy5SZWZlcmVuY2VJdGVyYXRvciA9IF9leHBvcnRzLkl0ZXJhdGlvbkFydGlmYWN0cyA9IF9leHBvcnRzLkxpc3RJdGVtID0gX2V4cG9ydHMuQ29uc3RSZWZlcmVuY2UgPSBfZXhwb3J0cy5SZWZlcmVuY2VDYWNoZSA9IF9leHBvcnRzLkNhY2hlZFJlZmVyZW5jZSA9IHZvaWQgMDsKICB2YXIgc3ltYm9sID0gdHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgPyBTeW1ib2wgOiBmdW5jdGlvbiAoa2V5KSB7CiAgICByZXR1cm4gIl9fIiArIGtleSArIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIERhdGUubm93KCkpICsgIl9fIjsKICB9OwogIHZhciBDT05TVEFOVCA9IDA7CiAgX2V4cG9ydHMuQ09OU1RBTlQgPSBDT05TVEFOVDsKICB2YXIgSU5JVElBTCA9IDE7CiAgX2V4cG9ydHMuSU5JVElBTCA9IElOSVRJQUw7CiAgdmFyIFZPTEFUSUxFID0gOTAwNzE5OTI1NDc0MDk5MTsgLy8gTUFYX0lOVAoKICBfZXhwb3J0cy5WT0xBVElMRSA9IFZPTEFUSUxFOwogIHZhciAkUkVWSVNJT04gPSBJTklUSUFMOwoKICBmdW5jdGlvbiBidW1wKCkgewogICAgJFJFVklTSU9OKys7CiAgfSAvLy8vLy8vLy8vCgoKICB2YXIgQ09NUFVURSA9IHN5bWJvbCgnVEFHX0NPTVBVVEUnKTsgLy8vLy8vLy8vLwoKICAvKioKICAgKiBgdmFsdWVgIHJlY2VpdmVzIGEgdGFnIGFuZCByZXR1cm5zIGFuIG9wYXF1ZSBSZXZpc2lvbiBiYXNlZCBvbiB0aGF0IHRhZy4gVGhpcwogICAqIHNuYXBzaG90IGNhbiB0aGVuIGxhdGVyIGJlIHBhc3NlZCB0byBgdmFsaWRhdGVgIHdpdGggdGhlIHNhbWUgdGFnIHRvCiAgICogZGV0ZXJtaW5lIGlmIHRoZSB0YWcgaGFzIGNoYW5nZWQgYXQgYWxsIHNpbmNlIHRoZSB0aW1lIHRoYXQgYHZhbHVlYCB3YXMKICAgKiBjYWxsZWQuCiAgICoKICAgKiBUaGUgY3VycmVudCBpbXBsZW1lbnRhdGlvbiByZXR1cm5zIHRoZSBnbG9iYWwgcmV2aXNpb24gY291bnQgZGlyZWN0bHkgZm9yCiAgICogcGVyZm9ybWFuY2UgcmVhc29ucy4gVGhpcyBpcyBhbiBpbXBsZW1lbnRhdGlvbiBkZXRhaWwsIGFuZCBzaG91bGQgbm90IGJlCiAgICogcmVsaWVkIG9uIGRpcmVjdGx5IGJ5IHVzZXJzIG9mIHRoZXNlIEFQSXMuIEluc3RlYWQsIFJldmlzaW9ucyBzaG91bGQgYmUKICAgKiB0cmVhdGVkIGFzIGlmIHRoZXkgYXJlIG9wYXF1ZS91bmtub3duLCBhbmQgc2hvdWxkIG9ubHkgYmUgaW50ZXJhY3RlZCB3aXRoIHZpYQogICAqIHRoZSBgdmFsdWVgL2B2YWxpZGF0ZWAgQVBJLgogICAqCiAgICogQHBhcmFtIHRhZwogICAqLwoKICBfZXhwb3J0cy5DT01QVVRFID0gQ09NUFVURTsKCiAgZnVuY3Rpb24gX3ZhbHVlMihfdGFnKSB7CiAgICByZXR1cm4gJFJFVklTSU9OOwogIH0KICAvKioKICAgKiBgdmFsaWRhdGVgIHJlY2VpdmVzIGEgdGFnIGFuZCBhIHNuYXBzaG90IGZyb20gYSBwcmV2aW91cyBjYWxsIHRvIGB2YWx1ZWAgd2l0aAogICAqIHRoZSBzYW1lIHRhZywgYW5kIGRldGVybWluZXMgaWYgdGhlIHRhZyBpcyBzdGlsbCB2YWxpZCBjb21wYXJlZCB0byB0aGUKICAgKiBzbmFwc2hvdC4gSWYgdGhlIHRhZydzIHN0YXRlIGhhcyBjaGFuZ2VkIGF0IGFsbCBzaW5jZSB0aGVuLCBgdmFsaWRhdGVgIHdpbGwKICAgKiByZXR1cm4gZmFsc2UsIG90aGVyd2lzZSBpdCB3aWxsIHJldHVybiB0cnVlLiBUaGlzIGlzIHVzZWQgdG8gZGV0ZXJtaW5lIGlmIGEKICAgKiBjYWxjdWxhdGlvbiByZWxhdGVkIHRvIHRoZSB0YWdzIHNob3VsZCBiZSByZXJ1bi4KICAgKgogICAqIEBwYXJhbSB0YWcKICAgKiBAcGFyYW0gc25hcHNob3QKICAgKi8KCgogIGZ1bmN0aW9uIHZhbGlkYXRlKHRhZywgc25hcHNob3QpIHsKICAgIHJldHVybiBzbmFwc2hvdCA+PSB0YWdbQ09NUFVURV0oKTsKICB9CgogIHZhciBUWVBFID0gc3ltYm9sKCdUQUdfVFlQRScpOwogIHZhciBBTExPV19DWUNMRVM7CiAgX2V4cG9ydHMuQUxMT1dfQ1lDTEVTID0gQUxMT1dfQ1lDTEVTOwoKICB2YXIgTW9ub21vcnBoaWNUYWdJbXBsID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gTW9ub21vcnBoaWNUYWdJbXBsKHR5cGUpIHsKICAgICAgdGhpcy5yZXZpc2lvbiA9IElOSVRJQUw7CiAgICAgIHRoaXMubGFzdENoZWNrZWQgPSBJTklUSUFMOwogICAgICB0aGlzLmxhc3RWYWx1ZSA9IElOSVRJQUw7CiAgICAgIHRoaXMuaXNVcGRhdGluZyA9IGZhbHNlOwogICAgICB0aGlzLnN1YnRhZyA9IG51bGw7CiAgICAgIHRoaXMuc3VidGFncyA9IG51bGw7CiAgICAgIHRoaXNbVFlQRV0gPSB0eXBlOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBNb25vbW9ycGhpY1RhZ0ltcGwucHJvdG90eXBlOwoKICAgIF9wcm90b1tDT01QVVRFXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGxhc3RDaGVja2VkID0gdGhpcy5sYXN0Q2hlY2tlZDsKCiAgICAgIGlmIChsYXN0Q2hlY2tlZCAhPT0gJFJFVklTSU9OKSB7CiAgICAgICAgdGhpcy5pc1VwZGF0aW5nID0gdHJ1ZTsKICAgICAgICB0aGlzLmxhc3RDaGVja2VkID0gJFJFVklTSU9OOwoKICAgICAgICB0cnkgewogICAgICAgICAgdmFyIHN1YnRhZ3MgPSB0aGlzLnN1YnRhZ3MsCiAgICAgICAgICAgICAgc3VidGFnID0gdGhpcy5zdWJ0YWcsCiAgICAgICAgICAgICAgcmV2aXNpb24gPSB0aGlzLnJldmlzaW9uOwoKICAgICAgICAgIGlmIChzdWJ0YWcgIT09IG51bGwpIHsKICAgICAgICAgICAgcmV2aXNpb24gPSBNYXRoLm1heChyZXZpc2lvbiwgc3VidGFnW0NPTVBVVEVdKCkpOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChzdWJ0YWdzICE9PSBudWxsKSB7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3VidGFncy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgIHZhciBfdmFsdWUgPSBzdWJ0YWdzW2ldW0NPTVBVVEVdKCk7CgogICAgICAgICAgICAgIHJldmlzaW9uID0gTWF0aC5tYXgoX3ZhbHVlLCByZXZpc2lvbik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICB0aGlzLmxhc3RWYWx1ZSA9IHJldmlzaW9uOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICB0aGlzLmlzVXBkYXRpbmcgPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmlzVXBkYXRpbmcgPT09IHRydWUpIHsKICAgICAgICB0aGlzLmxhc3RDaGVja2VkID0gKyskUkVWSVNJT047CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLmxhc3RWYWx1ZTsKICAgIH07CgogICAgTW9ub21vcnBoaWNUYWdJbXBsLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZShfdGFnLCBzdWJ0YWcpIHsKICAgICAgLy8gVE9ETzogVFMgMy43IHNob3VsZCBhbGxvdyB1cyB0byBkbyB0aGlzIHZpYSBhc3NlcnRpb24KICAgICAgdmFyIHRhZyA9IF90YWc7CgogICAgICBpZiAoc3VidGFnID09PSBDT05TVEFOVF9UQUcpIHsKICAgICAgICB0YWcuc3VidGFnID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0YWcuc3VidGFnID0gc3VidGFnOyAvLyBzdWJ0YWcgY291bGQgYmUgYW5vdGhlciB0eXBlIG9mIHRhZywgZS5nLiBDVVJSRU5UX1RBRyBvciBWT0xBVElMRV9UQUcuCiAgICAgICAgLy8gSWYgc28sIGxhc3RDaGVja2VkL2xhc3RWYWx1ZSB3aWxsIGJlIHVuZGVmaW5lZCwgcmVzdWx0IGluIHRoZXNlIGJlaW5nCiAgICAgICAgLy8gTmFOLiBUaGlzIGlzIGZpbmUsIGl0IHdpbGwgZm9yY2UgdGhlIHN5c3RlbSB0byByZWNvbXB1dGUuCgogICAgICAgIHRhZy5sYXN0Q2hlY2tlZCA9IE1hdGgubWluKHRhZy5sYXN0Q2hlY2tlZCwgc3VidGFnLmxhc3RDaGVja2VkKTsKICAgICAgICB0YWcubGFzdFZhbHVlID0gTWF0aC5tYXgodGFnLmxhc3RWYWx1ZSwgc3VidGFnLmxhc3RWYWx1ZSk7CiAgICAgIH0KICAgIH07CgogICAgTW9ub21vcnBoaWNUYWdJbXBsLmRpcnR5ID0gZnVuY3Rpb24gZGlydHkodGFnKSB7CiAgICAgIHRhZy5yZXZpc2lvbiA9ICsrJFJFVklTSU9OOwogICAgfTsKCiAgICByZXR1cm4gTW9ub21vcnBoaWNUYWdJbXBsOwogIH0oKTsKCiAgX2V4cG9ydHMuTW9ub21vcnBoaWNUYWdJbXBsID0gTW9ub21vcnBoaWNUYWdJbXBsOwogIHZhciBkaXJ0eSA9IE1vbm9tb3JwaGljVGFnSW1wbC5kaXJ0eTsKICBfZXhwb3J0cy5kaXJ0eSA9IGRpcnR5OwogIHZhciB1cGRhdGUgPSBNb25vbW9ycGhpY1RhZ0ltcGwudXBkYXRlOyAvLy8vLy8vLy8vCgogIF9leHBvcnRzLnVwZGF0ZSA9IHVwZGF0ZTsKCiAgZnVuY3Rpb24gY3JlYXRlVGFnKCkgewogICAgcmV0dXJuIG5ldyBNb25vbW9ycGhpY1RhZ0ltcGwoMAogICAgLyogRGlydHlhYmxlICovCiAgICApOwogIH0KCiAgZnVuY3Rpb24gY3JlYXRlVXBkYXRhYmxlVGFnKCkgewogICAgcmV0dXJuIG5ldyBNb25vbW9ycGhpY1RhZ0ltcGwoMQogICAgLyogVXBkYXRhYmxlICovCiAgICApOwogIH0gLy8vLy8vLy8vLwoKCiAgdmFyIENPTlNUQU5UX1RBRyA9IG5ldyBNb25vbW9ycGhpY1RhZ0ltcGwoMwogIC8qIENvbnN0YW50ICovCiAgKTsKICBfZXhwb3J0cy5DT05TVEFOVF9UQUcgPSBDT05TVEFOVF9UQUc7CgogIGZ1bmN0aW9uIGlzQ29uc3QoX3JlZikgewogICAgdmFyIHRhZyA9IF9yZWYudGFnOwogICAgcmV0dXJuIHRhZyA9PT0gQ09OU1RBTlRfVEFHOwogIH0KCiAgZnVuY3Rpb24gaXNDb25zdFRhZyh0YWcpIHsKICAgIHJldHVybiB0YWcgPT09IENPTlNUQU5UX1RBRzsKICB9IC8vLy8vLy8vLy8KCgogIHZhciBWb2xhdGlsZVRhZyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFZvbGF0aWxlVGFnKCkge30KCiAgICB2YXIgX3Byb3RvMiA9IFZvbGF0aWxlVGFnLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yW0NPTVBVVEVdID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gVk9MQVRJTEU7CiAgICB9OwoKICAgIHJldHVybiBWb2xhdGlsZVRhZzsKICB9KCk7CgogIHZhciBWT0xBVElMRV9UQUcgPSBuZXcgVm9sYXRpbGVUYWcoKTsgLy8vLy8vLy8vLwoKICBfZXhwb3J0cy5WT0xBVElMRV9UQUcgPSBWT0xBVElMRV9UQUc7CgogIHZhciBDdXJyZW50VGFnID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ3VycmVudFRhZygpIHt9CgogICAgdmFyIF9wcm90bzMgPSBDdXJyZW50VGFnLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zW0NPTVBVVEVdID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gJFJFVklTSU9OOwogICAgfTsKCiAgICByZXR1cm4gQ3VycmVudFRhZzsKICB9KCk7CgogIHZhciBDVVJSRU5UX1RBRyA9IG5ldyBDdXJyZW50VGFnKCk7IC8vLy8vLy8vLy8KCiAgX2V4cG9ydHMuQ1VSUkVOVF9UQUcgPSBDVVJSRU5UX1RBRzsKCiAgZnVuY3Rpb24gY29tYmluZVRhZ2dlZCh0YWdnZWQpIHsKICAgIHZhciBvcHRpbWl6ZWQgPSBbXTsKCiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRhZ2dlZC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgdmFyIHRhZyA9IHRhZ2dlZFtpXS50YWc7CiAgICAgIGlmICh0YWcgPT09IENPTlNUQU5UX1RBRykgY29udGludWU7CiAgICAgIG9wdGltaXplZC5wdXNoKHRhZyk7CiAgICB9CgogICAgcmV0dXJuIF9jb21iaW5lKG9wdGltaXplZCk7CiAgfQoKICBmdW5jdGlvbiBjb21iaW5lU2xpY2Uoc2xpY2UpIHsKICAgIHZhciBvcHRpbWl6ZWQgPSBbXTsKICAgIHZhciBub2RlID0gc2xpY2UuaGVhZCgpOwoKICAgIHdoaWxlIChub2RlICE9PSBudWxsKSB7CiAgICAgIHZhciB0YWcgPSBub2RlLnRhZzsKICAgICAgaWYgKHRhZyAhPT0gQ09OU1RBTlRfVEFHKSBvcHRpbWl6ZWQucHVzaCh0YWcpOwogICAgICBub2RlID0gc2xpY2UubmV4dE5vZGUobm9kZSk7CiAgICB9CgogICAgcmV0dXJuIF9jb21iaW5lKG9wdGltaXplZCk7CiAgfQoKICBmdW5jdGlvbiBjb21iaW5lKHRhZ3MpIHsKICAgIHZhciBvcHRpbWl6ZWQgPSBbXTsKCiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRhZ3MubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgIHZhciB0YWcgPSB0YWdzW2ldOwogICAgICBpZiAodGFnID09PSBDT05TVEFOVF9UQUcpIGNvbnRpbnVlOwogICAgICBvcHRpbWl6ZWQucHVzaCh0YWcpOwogICAgfQoKICAgIHJldHVybiBfY29tYmluZShvcHRpbWl6ZWQpOwogIH0KCiAgZnVuY3Rpb24gX2NvbWJpbmUodGFncykgewogICAgc3dpdGNoICh0YWdzLmxlbmd0aCkgewogICAgICBjYXNlIDA6CiAgICAgICAgcmV0dXJuIENPTlNUQU5UX1RBRzsKCiAgICAgIGNhc2UgMToKICAgICAgICByZXR1cm4gdGFnc1swXTsKCiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdmFyIHRhZyA9IG5ldyBNb25vbW9ycGhpY1RhZ0ltcGwoMgogICAgICAgIC8qIENvbWJpbmF0b3IgKi8KICAgICAgICApOwogICAgICAgIHRhZy5zdWJ0YWdzID0gdGFnczsKICAgICAgICByZXR1cm4gdGFnOwogICAgfQogIH0KCiAgdmFyIENhY2hlZFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENhY2hlZFJlZmVyZW5jZSgpIHsKICAgICAgdGhpcy5sYXN0UmV2aXNpb24gPSBudWxsOwogICAgICB0aGlzLmxhc3RWYWx1ZSA9IG51bGw7CiAgICB9CgogICAgdmFyIF9wcm90bzQgPSBDYWNoZWRSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzQudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgdmFyIHRhZyA9IHRoaXMudGFnLAogICAgICAgICAgbGFzdFJldmlzaW9uID0gdGhpcy5sYXN0UmV2aXNpb24sCiAgICAgICAgICBsYXN0VmFsdWUgPSB0aGlzLmxhc3RWYWx1ZTsKCiAgICAgIGlmIChsYXN0UmV2aXNpb24gPT09IG51bGwgfHwgIXZhbGlkYXRlKHRhZywgbGFzdFJldmlzaW9uKSkgewogICAgICAgIGxhc3RWYWx1ZSA9IHRoaXMubGFzdFZhbHVlID0gdGhpcy5jb21wdXRlKCk7CiAgICAgICAgdGhpcy5sYXN0UmV2aXNpb24gPSBfdmFsdWUyKHRhZyk7CiAgICAgIH0KCiAgICAgIHJldHVybiBsYXN0VmFsdWU7CiAgICB9OwoKICAgIF9wcm90bzQuaW52YWxpZGF0ZSA9IGZ1bmN0aW9uIGludmFsaWRhdGUoKSB7CiAgICAgIHRoaXMubGFzdFJldmlzaW9uID0gbnVsbDsKICAgIH07CgogICAgcmV0dXJuIENhY2hlZFJlZmVyZW5jZTsKICB9KCk7CgogIF9leHBvcnRzLkNhY2hlZFJlZmVyZW5jZSA9IENhY2hlZFJlZmVyZW5jZTsKCiAgdmFyIE1hcHBlclJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ2FjaGVkUmVmZXJlbmNlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTWFwcGVyUmVmZXJlbmNlLCBfQ2FjaGVkUmVmZXJlbmNlKTsKCiAgICBmdW5jdGlvbiBNYXBwZXJSZWZlcmVuY2UocmVmZXJlbmNlLCBtYXBwZXIpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfQ2FjaGVkUmVmZXJlbmNlLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXMudGFnID0gcmVmZXJlbmNlLnRhZzsKICAgICAgX3RoaXMucmVmZXJlbmNlID0gcmVmZXJlbmNlOwogICAgICBfdGhpcy5tYXBwZXIgPSBtYXBwZXI7CiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNSA9IE1hcHBlclJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNS5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgdmFyIHJlZmVyZW5jZSA9IHRoaXMucmVmZXJlbmNlLAogICAgICAgICAgbWFwcGVyID0gdGhpcy5tYXBwZXI7CiAgICAgIHJldHVybiBtYXBwZXIocmVmZXJlbmNlLnZhbHVlKCkpOwogICAgfTsKCiAgICByZXR1cm4gTWFwcGVyUmVmZXJlbmNlOwogIH0oQ2FjaGVkUmVmZXJlbmNlKTsKCiAgZnVuY3Rpb24gbWFwKHJlZmVyZW5jZSwgbWFwcGVyKSB7CiAgICByZXR1cm4gbmV3IE1hcHBlclJlZmVyZW5jZShyZWZlcmVuY2UsIG1hcHBlcik7CiAgfSAvLy8vLy8vLy8vCgoKICB2YXIgUmVmZXJlbmNlQ2FjaGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBSZWZlcmVuY2VDYWNoZShyZWZlcmVuY2UpIHsKICAgICAgdGhpcy5sYXN0VmFsdWUgPSBudWxsOwogICAgICB0aGlzLmxhc3RSZXZpc2lvbiA9IG51bGw7CiAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSBmYWxzZTsKICAgICAgdGhpcy50YWcgPSByZWZlcmVuY2UudGFnOwogICAgICB0aGlzLnJlZmVyZW5jZSA9IHJlZmVyZW5jZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNiA9IFJlZmVyZW5jZUNhY2hlLnByb3RvdHlwZTsKCiAgICBfcHJvdG82LnBlZWsgPSBmdW5jdGlvbiBwZWVrKCkgewogICAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZWQpIHsKICAgICAgICByZXR1cm4gdGhpcy5pbml0aWFsaXplKCk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLmxhc3RWYWx1ZTsKICAgIH07CgogICAgX3Byb3RvNi5yZXZhbGlkYXRlID0gZnVuY3Rpb24gcmV2YWxpZGF0ZSgpIHsKICAgICAgaWYgKCF0aGlzLmluaXRpYWxpemVkKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW5pdGlhbGl6ZSgpOwogICAgICB9CgogICAgICB2YXIgcmVmZXJlbmNlID0gdGhpcy5yZWZlcmVuY2UsCiAgICAgICAgICBsYXN0UmV2aXNpb24gPSB0aGlzLmxhc3RSZXZpc2lvbjsKICAgICAgdmFyIHRhZyA9IHJlZmVyZW5jZS50YWc7CiAgICAgIGlmICh2YWxpZGF0ZSh0YWcsIGxhc3RSZXZpc2lvbikpIHJldHVybiBOT1RfTU9ESUZJRUQ7CiAgICAgIHRoaXMubGFzdFJldmlzaW9uID0gX3ZhbHVlMih0YWcpOwogICAgICB2YXIgbGFzdFZhbHVlID0gdGhpcy5sYXN0VmFsdWU7CiAgICAgIHZhciBjdXJyZW50VmFsdWUgPSByZWZlcmVuY2UudmFsdWUoKTsKICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA9PT0gbGFzdFZhbHVlKSByZXR1cm4gTk9UX01PRElGSUVEOwogICAgICB0aGlzLmxhc3RWYWx1ZSA9IGN1cnJlbnRWYWx1ZTsKICAgICAgcmV0dXJuIGN1cnJlbnRWYWx1ZTsKICAgIH07CgogICAgX3Byb3RvNi5pbml0aWFsaXplID0gZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHsKICAgICAgdmFyIHJlZmVyZW5jZSA9IHRoaXMucmVmZXJlbmNlOwogICAgICB2YXIgY3VycmVudFZhbHVlID0gdGhpcy5sYXN0VmFsdWUgPSByZWZlcmVuY2UudmFsdWUoKTsKICAgICAgdGhpcy5sYXN0UmV2aXNpb24gPSBfdmFsdWUyKHJlZmVyZW5jZS50YWcpOwogICAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTsKICAgICAgcmV0dXJuIGN1cnJlbnRWYWx1ZTsKICAgIH07CgogICAgcmV0dXJuIFJlZmVyZW5jZUNhY2hlOwogIH0oKTsKCiAgX2V4cG9ydHMuUmVmZXJlbmNlQ2FjaGUgPSBSZWZlcmVuY2VDYWNoZTsKICB2YXIgTk9UX01PRElGSUVEID0gJ2FkYjNiNzhlLTNkMjItNGU0Yi04NzdhLTYzMTdjMmM1YzE0NSc7CgogIGZ1bmN0aW9uIGlzTW9kaWZpZWQodmFsdWUkJDEpIHsKICAgIHJldHVybiB2YWx1ZSQkMSAhPT0gTk9UX01PRElGSUVEOwogIH0KCiAgdmFyIENvbnN0UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ29uc3RSZWZlcmVuY2UoaW5uZXIpIHsKICAgICAgdGhpcy5pbm5lciA9IGlubmVyOwogICAgICB0aGlzLnRhZyA9IENPTlNUQU5UX1RBRzsKICAgIH0KCiAgICB2YXIgX3Byb3RvNyA9IENvbnN0UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG83LnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHJldHVybiB0aGlzLmlubmVyOwogICAgfTsKCiAgICByZXR1cm4gQ29uc3RSZWZlcmVuY2U7CiAgfSgpOwoKICBfZXhwb3J0cy5Db25zdFJlZmVyZW5jZSA9IENvbnN0UmVmZXJlbmNlOwoKICB2YXIgTGlzdEl0ZW0gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0xpc3ROb2RlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTGlzdEl0ZW0sIF9MaXN0Tm9kZSk7CgogICAgZnVuY3Rpb24gTGlzdEl0ZW0oaXRlcmFibGUsIHJlc3VsdCkgewogICAgICB2YXIgX3RoaXMyOwoKICAgICAgX3RoaXMyID0gX0xpc3ROb2RlLmNhbGwodGhpcywgaXRlcmFibGUudmFsdWVSZWZlcmVuY2VGb3IocmVzdWx0KSkgfHwgdGhpczsKICAgICAgX3RoaXMyLnJldGFpbmVkID0gZmFsc2U7CiAgICAgIF90aGlzMi5zZWVuID0gZmFsc2U7CiAgICAgIF90aGlzMi5rZXkgPSByZXN1bHQua2V5OwogICAgICBfdGhpczIuaXRlcmFibGUgPSBpdGVyYWJsZTsKICAgICAgX3RoaXMyLm1lbW8gPSBpdGVyYWJsZS5tZW1vUmVmZXJlbmNlRm9yKHJlc3VsdCk7CiAgICAgIHJldHVybiBfdGhpczI7CiAgICB9CgogICAgdmFyIF9wcm90bzggPSBMaXN0SXRlbS5wcm90b3R5cGU7CgogICAgX3Byb3RvOC51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoaXRlbSkgewogICAgICB0aGlzLnJldGFpbmVkID0gdHJ1ZTsKICAgICAgdGhpcy5pdGVyYWJsZS51cGRhdGVWYWx1ZVJlZmVyZW5jZSh0aGlzLnZhbHVlLCBpdGVtKTsKICAgICAgdGhpcy5pdGVyYWJsZS51cGRhdGVNZW1vUmVmZXJlbmNlKHRoaXMubWVtbywgaXRlbSk7CiAgICB9OwoKICAgIF9wcm90bzguc2hvdWxkUmVtb3ZlID0gZnVuY3Rpb24gc2hvdWxkUmVtb3ZlKCkgewogICAgICByZXR1cm4gIXRoaXMucmV0YWluZWQ7CiAgICB9OwoKICAgIF9wcm90bzgucmVzZXQgPSBmdW5jdGlvbiByZXNldCgpIHsKICAgICAgdGhpcy5yZXRhaW5lZCA9IGZhbHNlOwogICAgICB0aGlzLnNlZW4gPSBmYWxzZTsKICAgIH07CgogICAgcmV0dXJuIExpc3RJdGVtOwogIH0oX3V0aWwuTGlzdE5vZGUpOwoKICBfZXhwb3J0cy5MaXN0SXRlbSA9IExpc3RJdGVtOwoKICB2YXIgSXRlcmF0aW9uQXJ0aWZhY3RzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSXRlcmF0aW9uQXJ0aWZhY3RzKGl0ZXJhYmxlKSB7CiAgICAgIHRoaXMuaXRlcmF0b3IgPSBudWxsOwogICAgICB0aGlzLm1hcCA9ICgwLCBfdXRpbC5kaWN0KSgpOwogICAgICB0aGlzLmxpc3QgPSBuZXcgX3V0aWwuTGlua2VkTGlzdCgpOwogICAgICB0aGlzLnRhZyA9IGl0ZXJhYmxlLnRhZzsKICAgICAgdGhpcy5pdGVyYWJsZSA9IGl0ZXJhYmxlOwogICAgfQoKICAgIHZhciBfcHJvdG85ID0gSXRlcmF0aW9uQXJ0aWZhY3RzLnByb3RvdHlwZTsKCiAgICBfcHJvdG85LmlzRW1wdHkgPSBmdW5jdGlvbiBpc0VtcHR5KCkgewogICAgICB2YXIgaXRlcmF0b3IgPSB0aGlzLml0ZXJhdG9yID0gdGhpcy5pdGVyYWJsZS5pdGVyYXRlKCk7CiAgICAgIHJldHVybiBpdGVyYXRvci5pc0VtcHR5KCk7CiAgICB9OwoKICAgIF9wcm90bzkuaXRlcmF0ZSA9IGZ1bmN0aW9uIGl0ZXJhdGUoKSB7CiAgICAgIHZhciBpdGVyYXRvcjsKCiAgICAgIGlmICh0aGlzLml0ZXJhdG9yID09PSBudWxsKSB7CiAgICAgICAgaXRlcmF0b3IgPSB0aGlzLml0ZXJhYmxlLml0ZXJhdGUoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpdGVyYXRvciA9IHRoaXMuaXRlcmF0b3I7CiAgICAgIH0KCiAgICAgIHRoaXMuaXRlcmF0b3IgPSBudWxsOwogICAgICByZXR1cm4gaXRlcmF0b3I7CiAgICB9OwoKICAgIF9wcm90bzkuaGFzID0gZnVuY3Rpb24gaGFzKGtleSkgewogICAgICByZXR1cm4gISF0aGlzLm1hcFtrZXldOwogICAgfTsKCiAgICBfcHJvdG85LmdldCA9IGZ1bmN0aW9uIGdldChrZXkpIHsKICAgICAgcmV0dXJuIHRoaXMubWFwW2tleV07CiAgICB9OwoKICAgIF9wcm90bzkud2FzU2VlbiA9IGZ1bmN0aW9uIHdhc1NlZW4oa2V5KSB7CiAgICAgIHZhciBub2RlID0gdGhpcy5tYXBba2V5XTsKICAgICAgcmV0dXJuIG5vZGUgIT09IHVuZGVmaW5lZCAmJiBub2RlLnNlZW47CiAgICB9OwoKICAgIF9wcm90bzkuYXBwZW5kID0gZnVuY3Rpb24gYXBwZW5kKGl0ZW0pIHsKICAgICAgdmFyIG1hcCA9IHRoaXMubWFwLAogICAgICAgICAgbGlzdCA9IHRoaXMubGlzdCwKICAgICAgICAgIGl0ZXJhYmxlID0gdGhpcy5pdGVyYWJsZTsKICAgICAgdmFyIG5vZGUgPSBtYXBbaXRlbS5rZXldID0gbmV3IExpc3RJdGVtKGl0ZXJhYmxlLCBpdGVtKTsKICAgICAgbGlzdC5hcHBlbmQobm9kZSk7CiAgICAgIHJldHVybiBub2RlOwogICAgfTsKCiAgICBfcHJvdG85Lmluc2VydEJlZm9yZSA9IGZ1bmN0aW9uIGluc2VydEJlZm9yZShpdGVtLCByZWZlcmVuY2UpIHsKICAgICAgdmFyIG1hcCA9IHRoaXMubWFwLAogICAgICAgICAgbGlzdCA9IHRoaXMubGlzdCwKICAgICAgICAgIGl0ZXJhYmxlID0gdGhpcy5pdGVyYWJsZTsKICAgICAgdmFyIG5vZGUgPSBtYXBbaXRlbS5rZXldID0gbmV3IExpc3RJdGVtKGl0ZXJhYmxlLCBpdGVtKTsKICAgICAgbm9kZS5yZXRhaW5lZCA9IHRydWU7CiAgICAgIGxpc3QuaW5zZXJ0QmVmb3JlKG5vZGUsIHJlZmVyZW5jZSk7CiAgICAgIHJldHVybiBub2RlOwogICAgfTsKCiAgICBfcHJvdG85Lm1vdmUgPSBmdW5jdGlvbiBtb3ZlKGl0ZW0sIHJlZmVyZW5jZSkgewogICAgICB2YXIgbGlzdCA9IHRoaXMubGlzdDsKICAgICAgaXRlbS5yZXRhaW5lZCA9IHRydWU7CiAgICAgIGxpc3QucmVtb3ZlKGl0ZW0pOwogICAgICBsaXN0Lmluc2VydEJlZm9yZShpdGVtLCByZWZlcmVuY2UpOwogICAgfTsKCiAgICBfcHJvdG85LnJlbW92ZSA9IGZ1bmN0aW9uIHJlbW92ZShpdGVtKSB7CiAgICAgIHZhciBsaXN0ID0gdGhpcy5saXN0OwogICAgICBsaXN0LnJlbW92ZShpdGVtKTsKICAgICAgZGVsZXRlIHRoaXMubWFwW2l0ZW0ua2V5XTsKICAgIH07CgogICAgX3Byb3RvOS5uZXh0Tm9kZSA9IGZ1bmN0aW9uIG5leHROb2RlKGl0ZW0pIHsKICAgICAgcmV0dXJuIHRoaXMubGlzdC5uZXh0Tm9kZShpdGVtKTsKICAgIH07CgogICAgX3Byb3RvOS5oZWFkID0gZnVuY3Rpb24gaGVhZCgpIHsKICAgICAgcmV0dXJuIHRoaXMubGlzdC5oZWFkKCk7CiAgICB9OwoKICAgIHJldHVybiBJdGVyYXRpb25BcnRpZmFjdHM7CiAgfSgpOwoKICBfZXhwb3J0cy5JdGVyYXRpb25BcnRpZmFjdHMgPSBJdGVyYXRpb25BcnRpZmFjdHM7CgogIHZhciBSZWZlcmVuY2VJdGVyYXRvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIC8vIGlmIGFueW9uZSBuZWVkcyB0byBjb25zdHJ1Y3QgdGhpcyBvYmplY3Qgd2l0aCBzb21ldGhpbmcgb3RoZXIgdGhhbgogICAgLy8gYW4gaXRlcmFibGUsIGxldCBAd3ljYXRzIGtub3cuCiAgICBmdW5jdGlvbiBSZWZlcmVuY2VJdGVyYXRvcihpdGVyYWJsZSkgewogICAgICB0aGlzLml0ZXJhdG9yID0gbnVsbDsKICAgICAgdmFyIGFydGlmYWN0cyA9IG5ldyBJdGVyYXRpb25BcnRpZmFjdHMoaXRlcmFibGUpOwogICAgICB0aGlzLmFydGlmYWN0cyA9IGFydGlmYWN0czsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTAgPSBSZWZlcmVuY2VJdGVyYXRvci5wcm90b3R5cGU7CgogICAgX3Byb3RvMTAubmV4dCA9IGZ1bmN0aW9uIG5leHQoKSB7CiAgICAgIHZhciBhcnRpZmFjdHMgPSB0aGlzLmFydGlmYWN0czsKICAgICAgdmFyIGl0ZXJhdG9yID0gdGhpcy5pdGVyYXRvciA9IHRoaXMuaXRlcmF0b3IgfHwgYXJ0aWZhY3RzLml0ZXJhdGUoKTsKICAgICAgdmFyIGl0ZW0gPSBpdGVyYXRvci5uZXh0KCk7CiAgICAgIGlmIChpdGVtID09PSBudWxsKSByZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuIGFydGlmYWN0cy5hcHBlbmQoaXRlbSk7CiAgICB9OwoKICAgIHJldHVybiBSZWZlcmVuY2VJdGVyYXRvcjsKICB9KCk7CgogIF9leHBvcnRzLlJlZmVyZW5jZUl0ZXJhdG9yID0gUmVmZXJlbmNlSXRlcmF0b3I7CiAgdmFyIFBoYXNlOwoKICAoZnVuY3Rpb24gKFBoYXNlKSB7CiAgICBQaGFzZVtQaGFzZVsiQXBwZW5kIl0gPSAwXSA9ICJBcHBlbmQiOwogICAgUGhhc2VbUGhhc2VbIlBydW5lIl0gPSAxXSA9ICJQcnVuZSI7CiAgICBQaGFzZVtQaGFzZVsiRG9uZSJdID0gMl0gPSAiRG9uZSI7CiAgfSkoUGhhc2UgfHwgKFBoYXNlID0ge30pKTsKCiAgdmFyIEl0ZXJhdG9yU3luY2hyb25pemVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSXRlcmF0b3JTeW5jaHJvbml6ZXIoX3JlZjIpIHsKICAgICAgdmFyIHRhcmdldCA9IF9yZWYyLnRhcmdldCwKICAgICAgICAgIGFydGlmYWN0cyA9IF9yZWYyLmFydGlmYWN0czsKICAgICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7CiAgICAgIHRoaXMuYXJ0aWZhY3RzID0gYXJ0aWZhY3RzOwogICAgICB0aGlzLml0ZXJhdG9yID0gYXJ0aWZhY3RzLml0ZXJhdGUoKTsKICAgICAgdGhpcy5jdXJyZW50ID0gYXJ0aWZhY3RzLmhlYWQoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTEgPSBJdGVyYXRvclN5bmNocm9uaXplci5wcm90b3R5cGU7CgogICAgX3Byb3RvMTEuc3luYyA9IGZ1bmN0aW9uIHN5bmMoKSB7CiAgICAgIHZhciBwaGFzZSA9IFBoYXNlLkFwcGVuZDsKCiAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgc3dpdGNoIChwaGFzZSkgewogICAgICAgICAgY2FzZSBQaGFzZS5BcHBlbmQ6CiAgICAgICAgICAgIHBoYXNlID0gdGhpcy5uZXh0QXBwZW5kKCk7CiAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgIGNhc2UgUGhhc2UuUHJ1bmU6CiAgICAgICAgICAgIHBoYXNlID0gdGhpcy5uZXh0UHJ1bmUoKTsKICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgY2FzZSBQaGFzZS5Eb25lOgogICAgICAgICAgICB0aGlzLm5leHREb25lKCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTEuYWR2YW5jZVRvS2V5ID0gZnVuY3Rpb24gYWR2YW5jZVRvS2V5KGtleSkgewogICAgICB2YXIgY3VycmVudCA9IHRoaXMuY3VycmVudCwKICAgICAgICAgIGFydGlmYWN0cyA9IHRoaXMuYXJ0aWZhY3RzOwogICAgICB2YXIgc2VlayA9IGN1cnJlbnQ7CgogICAgICB3aGlsZSAoc2VlayAhPT0gbnVsbCAmJiBzZWVrLmtleSAhPT0ga2V5KSB7CiAgICAgICAgc2Vlay5zZWVuID0gdHJ1ZTsKICAgICAgICBzZWVrID0gYXJ0aWZhY3RzLm5leHROb2RlKHNlZWspOwogICAgICB9CgogICAgICBpZiAoc2VlayAhPT0gbnVsbCkgewogICAgICAgIHRoaXMuY3VycmVudCA9IGFydGlmYWN0cy5uZXh0Tm9kZShzZWVrKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8xMS5uZXh0QXBwZW5kID0gZnVuY3Rpb24gbmV4dEFwcGVuZCgpIHsKICAgICAgdmFyIGl0ZXJhdG9yID0gdGhpcy5pdGVyYXRvciwKICAgICAgICAgIGN1cnJlbnQgPSB0aGlzLmN1cnJlbnQsCiAgICAgICAgICBhcnRpZmFjdHMgPSB0aGlzLmFydGlmYWN0czsKICAgICAgdmFyIGl0ZW0gPSBpdGVyYXRvci5uZXh0KCk7CgogICAgICBpZiAoaXRlbSA9PT0gbnVsbCkgewogICAgICAgIHJldHVybiB0aGlzLnN0YXJ0UHJ1bmUoKTsKICAgICAgfQoKICAgICAgdmFyIGtleSA9IGl0ZW0ua2V5OwoKICAgICAgaWYgKGN1cnJlbnQgIT09IG51bGwgJiYgY3VycmVudC5rZXkgPT09IGtleSkgewogICAgICAgIHRoaXMubmV4dFJldGFpbihpdGVtKTsKICAgICAgfSBlbHNlIGlmIChhcnRpZmFjdHMuaGFzKGtleSkpIHsKICAgICAgICB0aGlzLm5leHRNb3ZlKGl0ZW0pOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMubmV4dEluc2VydChpdGVtKTsKICAgICAgfQoKICAgICAgcmV0dXJuIFBoYXNlLkFwcGVuZDsKICAgIH07CgogICAgX3Byb3RvMTEubmV4dFJldGFpbiA9IGZ1bmN0aW9uIG5leHRSZXRhaW4oaXRlbSkgewogICAgICB2YXIgYXJ0aWZhY3RzID0gdGhpcy5hcnRpZmFjdHMsCiAgICAgICAgICBjdXJyZW50ID0gdGhpcy5jdXJyZW50OwogICAgICBjdXJyZW50ID0gY3VycmVudDsKICAgICAgY3VycmVudC51cGRhdGUoaXRlbSk7CiAgICAgIHRoaXMuY3VycmVudCA9IGFydGlmYWN0cy5uZXh0Tm9kZShjdXJyZW50KTsKICAgICAgdGhpcy50YXJnZXQucmV0YWluKGl0ZW0ua2V5LCBjdXJyZW50LnZhbHVlLCBjdXJyZW50Lm1lbW8pOwogICAgfTsKCiAgICBfcHJvdG8xMS5uZXh0TW92ZSA9IGZ1bmN0aW9uIG5leHRNb3ZlKGl0ZW0pIHsKICAgICAgdmFyIGN1cnJlbnQgPSB0aGlzLmN1cnJlbnQsCiAgICAgICAgICBhcnRpZmFjdHMgPSB0aGlzLmFydGlmYWN0cywKICAgICAgICAgIHRhcmdldCA9IHRoaXMudGFyZ2V0OwogICAgICB2YXIga2V5ID0gaXRlbS5rZXk7CiAgICAgIHZhciBmb3VuZCA9IGFydGlmYWN0cy5nZXQoaXRlbS5rZXkpOwogICAgICBmb3VuZC51cGRhdGUoaXRlbSk7CgogICAgICBpZiAoYXJ0aWZhY3RzLndhc1NlZW4oaXRlbS5rZXkpKSB7CiAgICAgICAgYXJ0aWZhY3RzLm1vdmUoZm91bmQsIGN1cnJlbnQpOwogICAgICAgIHRhcmdldC5tb3ZlKGZvdW5kLmtleSwgZm91bmQudmFsdWUsIGZvdW5kLm1lbW8sIGN1cnJlbnQgPyBjdXJyZW50LmtleSA6IG51bGwpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuYWR2YW5jZVRvS2V5KGtleSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTEubmV4dEluc2VydCA9IGZ1bmN0aW9uIG5leHRJbnNlcnQoaXRlbSkgewogICAgICB2YXIgYXJ0aWZhY3RzID0gdGhpcy5hcnRpZmFjdHMsCiAgICAgICAgICB0YXJnZXQgPSB0aGlzLnRhcmdldCwKICAgICAgICAgIGN1cnJlbnQgPSB0aGlzLmN1cnJlbnQ7CiAgICAgIHZhciBub2RlID0gYXJ0aWZhY3RzLmluc2VydEJlZm9yZShpdGVtLCBjdXJyZW50KTsKICAgICAgdGFyZ2V0Lmluc2VydChub2RlLmtleSwgbm9kZS52YWx1ZSwgbm9kZS5tZW1vLCBjdXJyZW50ID8gY3VycmVudC5rZXkgOiBudWxsKTsKICAgIH07CgogICAgX3Byb3RvMTEuc3RhcnRQcnVuZSA9IGZ1bmN0aW9uIHN0YXJ0UHJ1bmUoKSB7CiAgICAgIHRoaXMuY3VycmVudCA9IHRoaXMuYXJ0aWZhY3RzLmhlYWQoKTsKICAgICAgcmV0dXJuIFBoYXNlLlBydW5lOwogICAgfTsKCiAgICBfcHJvdG8xMS5uZXh0UHJ1bmUgPSBmdW5jdGlvbiBuZXh0UHJ1bmUoKSB7CiAgICAgIHZhciBhcnRpZmFjdHMgPSB0aGlzLmFydGlmYWN0cywKICAgICAgICAgIHRhcmdldCA9IHRoaXMudGFyZ2V0LAogICAgICAgICAgY3VycmVudCA9IHRoaXMuY3VycmVudDsKCiAgICAgIGlmIChjdXJyZW50ID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIFBoYXNlLkRvbmU7CiAgICAgIH0KCiAgICAgIHZhciBub2RlID0gY3VycmVudDsKICAgICAgdGhpcy5jdXJyZW50ID0gYXJ0aWZhY3RzLm5leHROb2RlKG5vZGUpOwoKICAgICAgaWYgKG5vZGUuc2hvdWxkUmVtb3ZlKCkpIHsKICAgICAgICBhcnRpZmFjdHMucmVtb3ZlKG5vZGUpOwogICAgICAgIHRhcmdldC5kZWxldGUobm9kZS5rZXkpOwogICAgICB9IGVsc2UgewogICAgICAgIG5vZGUucmVzZXQoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIFBoYXNlLlBydW5lOwogICAgfTsKCiAgICBfcHJvdG8xMS5uZXh0RG9uZSA9IGZ1bmN0aW9uIG5leHREb25lKCkgewogICAgICB0aGlzLnRhcmdldC5kb25lKCk7CiAgICB9OwoKICAgIHJldHVybiBJdGVyYXRvclN5bmNocm9uaXplcjsKICB9KCk7CgogIF9leHBvcnRzLkl0ZXJhdG9yU3luY2hyb25pemVyID0gSXRlcmF0b3JTeW5jaHJvbml6ZXI7Cn0pOwpkZWZpbmUoIkBnbGltbWVyL3J1bnRpbWUiLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiLCAiQGdsaW1tZXIvdXRpbCIsICJAZ2xpbW1lci9yZWZlcmVuY2UiLCAiQGdsaW1tZXIvdm0iLCAiQGdsaW1tZXIvbG93LWxldmVsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2VtYmVyQmFiZWwsIF91dGlsLCBfcmVmZXJlbmNlMiwgX3ZtMiwgX2xvd0xldmVsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5yZW5kZXJNYWluID0gcmVuZGVyTWFpbjsKICBfZXhwb3J0cy5yZW5kZXJDb21wb25lbnQgPSByZW5kZXJDb21wb25lbnQ7CiAgX2V4cG9ydHMuc2V0RGVidWdnZXJDYWxsYmFjayA9IHNldERlYnVnZ2VyQ2FsbGJhY2s7CiAgX2V4cG9ydHMucmVzZXREZWJ1Z2dlckNhbGxiYWNrID0gcmVzZXREZWJ1Z2dlckNhbGxiYWNrOwogIF9leHBvcnRzLmdldER5bmFtaWNWYXIgPSBnZXREeW5hbWljVmFyOwogIF9leHBvcnRzLmlzQ3VycmllZENvbXBvbmVudERlZmluaXRpb24gPSBpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uOwogIF9leHBvcnRzLmN1cnJ5ID0gY3Vycnk7CiAgX2V4cG9ydHMuaXNXaGl0ZXNwYWNlID0gaXNXaGl0ZXNwYWNlOwogIF9leHBvcnRzLm5vcm1hbGl6ZVByb3BlcnR5ID0gbm9ybWFsaXplUHJvcGVydHk7CiAgX2V4cG9ydHMuY2xpZW50QnVpbGRlciA9IGNsaWVudEJ1aWxkZXI7CiAgX2V4cG9ydHMucmVoeWRyYXRpb25CdWlsZGVyID0gcmVoeWRyYXRpb25CdWlsZGVyOwogIF9leHBvcnRzLmlzU2VyaWFsaXphdGlvbkZpcnN0Tm9kZSA9IGlzU2VyaWFsaXphdGlvbkZpcnN0Tm9kZTsKICBfZXhwb3J0cy5jYXBhYmlsaXR5RmxhZ3NGcm9tID0gY2FwYWJpbGl0eUZsYWdzRnJvbTsKICBfZXhwb3J0cy5oYXNDYXBhYmlsaXR5ID0gaGFzQ2FwYWJpbGl0eTsKICBfZXhwb3J0cy5DdXJzb3IgPSBfZXhwb3J0cy5Db25jcmV0ZUJvdW5kcyA9IF9leHBvcnRzLlNFUklBTElaQVRJT05fRklSU1RfTk9ERV9TVFJJTkcgPSBfZXhwb3J0cy5SZWh5ZHJhdGVCdWlsZGVyID0gX2V4cG9ydHMuTmV3RWxlbWVudEJ1aWxkZXIgPSBfZXhwb3J0cy5ET01UcmVlQ29uc3RydWN0aW9uID0gX2V4cG9ydHMuSURPTUNoYW5nZXMgPSBfZXhwb3J0cy5TVkdfTkFNRVNQQUNFID0gX2V4cG9ydHMuRE9NQ2hhbmdlcyA9IF9leHBvcnRzLkN1cnJpZWRDb21wb25lbnREZWZpbml0aW9uID0gX2V4cG9ydHMuTUlOSU1BTF9DQVBBQklMSVRJRVMgPSBfZXhwb3J0cy5ERUZBVUxUX0NBUEFCSUxJVElFUyA9IF9leHBvcnRzLkRlZmF1bHRFbnZpcm9ubWVudCA9IF9leHBvcnRzLkVudmlyb25tZW50ID0gX2V4cG9ydHMuU2NvcGUgPSBfZXhwb3J0cy5FTVBUWV9BUkdTID0gX2V4cG9ydHMuRHluYW1pY0F0dHJpYnV0ZSA9IF9leHBvcnRzLlNpbXBsZUR5bmFtaWNBdHRyaWJ1dGUgPSBfZXhwb3J0cy5SZW5kZXJSZXN1bHQgPSBfZXhwb3J0cy5VcGRhdGluZ1ZNID0gX2V4cG9ydHMuTG93TGV2ZWxWTSA9IF9leHBvcnRzLkNvbmRpdGlvbmFsUmVmZXJlbmNlID0gX2V4cG9ydHMuUHJpbWl0aXZlUmVmZXJlbmNlID0gX2V4cG9ydHMuVU5ERUZJTkVEX1JFRkVSRU5DRSA9IF9leHBvcnRzLk5VTExfUkVGRVJFTkNFID0gdm9pZCAwOwoKICAvLyB0aGVzZSBpbXBvcnQgYmluZGluZ3Mgd2lsbCBiZSBzdHJpcHBlZCBmcm9tIGJ1aWxkCiAgdmFyIEFwcGVuZE9wY29kZXMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBBcHBlbmRPcGNvZGVzKCkgewogICAgICB0aGlzLmV2YWx1YXRlT3Bjb2RlID0gKDAsIF91dGlsLmZpbGxOdWxscykoOTgKICAgICAgLyogU2l6ZSAqLwogICAgICApLnNsaWNlKCk7CiAgICB9CgogICAgdmFyIF9wcm90byA9IEFwcGVuZE9wY29kZXMucHJvdG90eXBlOwoKICAgIF9wcm90by5hZGQgPSBmdW5jdGlvbiBhZGQobmFtZSwgZXZhbHVhdGUsIGtpbmQpIHsKICAgICAgaWYgKGtpbmQgPT09IHZvaWQgMCkgewogICAgICAgIGtpbmQgPSAnc3lzY2FsbCc7CiAgICAgIH0KCiAgICAgIHRoaXMuZXZhbHVhdGVPcGNvZGVbbmFtZV0gPSB7CiAgICAgICAgc3lzY2FsbDoga2luZCA9PT0gJ3N5c2NhbGwnLAogICAgICAgIGV2YWx1YXRlOiBldmFsdWF0ZQogICAgICB9OwogICAgfTsKCiAgICBfcHJvdG8uZGVidWdCZWZvcmUgPSBmdW5jdGlvbiBkZWJ1Z0JlZm9yZSh2bSwgb3Bjb2RlLCB0eXBlKSB7CiAgICAgIHZhciBzcDsKICAgICAgdmFyIHN0YXRlOwogICAgICByZXR1cm4gewogICAgICAgIHNwOiBzcCwKICAgICAgICBzdGF0ZTogc3RhdGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvLmRlYnVnQWZ0ZXIgPSBmdW5jdGlvbiBkZWJ1Z0FmdGVyKHZtLCBvcGNvZGUsIHR5cGUsIHByZSkgewogICAgICB2YXIgZXhwZWN0ZWRDaGFuZ2U7CiAgICAgIHZhciBzcCA9IHByZS5zcCwKICAgICAgICAgIHN0YXRlID0gcHJlLnN0YXRlOwogICAgICB2YXIgbWV0YWRhdGEgPSBudWxsOwoKICAgICAgaWYgKG1ldGFkYXRhICE9PSBudWxsKSB7CiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YS5zdGFja0NoYW5nZSA9PT0gJ251bWJlcicpIHsKICAgICAgICAgIGV4cGVjdGVkQ2hhbmdlID0gbWV0YWRhdGEuc3RhY2tDaGFuZ2U7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGV4cGVjdGVkQ2hhbmdlID0gbWV0YWRhdGEuc3RhY2tDaGFuZ2UoewogICAgICAgICAgICBvcGNvZGU6IG9wY29kZSwKICAgICAgICAgICAgY29uc3RhbnRzOiB2bS5jb25zdGFudHMsCiAgICAgICAgICAgIHN0YXRlOiBzdGF0ZQogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAoaXNOYU4oZXhwZWN0ZWRDaGFuZ2UpKSB0aHJvdyAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKHZtLCBvcGNvZGUsIHR5cGUpIHsKICAgICAgdmFyIG9wZXJhdGlvbiA9IHRoaXMuZXZhbHVhdGVPcGNvZGVbdHlwZV07CgogICAgICBpZiAob3BlcmF0aW9uLnN5c2NhbGwpIHsKICAgICAgICBvcGVyYXRpb24uZXZhbHVhdGUodm0sIG9wY29kZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgb3BlcmF0aW9uLmV2YWx1YXRlKHZtLmlubmVyLCBvcGNvZGUpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBBcHBlbmRPcGNvZGVzOwogIH0oKTsKCiAgdmFyIEFQUEVORF9PUENPREVTID0gbmV3IEFwcGVuZE9wY29kZXMoKTsKCiAgdmFyIEFic3RyYWN0T3Bjb2RlID0gZnVuY3Rpb24gQWJzdHJhY3RPcGNvZGUoKSB7CiAgICAoMCwgX3V0aWwuaW5pdGlhbGl6ZUd1aWQpKHRoaXMpOwogIH07CgogIHZhciBVcGRhdGluZ09wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQWJzdHJhY3RPcGNvZGUpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShVcGRhdGluZ09wY29kZSwgX0Fic3RyYWN0T3Bjb2RlKTsKCiAgICBmdW5jdGlvbiBVcGRhdGluZ09wY29kZSgpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfQWJzdHJhY3RPcGNvZGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpcy5uZXh0ID0gbnVsbDsKICAgICAgX3RoaXMucHJldiA9IG51bGw7CiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KCiAgICByZXR1cm4gVXBkYXRpbmdPcGNvZGU7CiAgfShBYnN0cmFjdE9wY29kZSk7CgogIHZhciBQcmltaXRpdmVSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NvbnN0UmVmZXJlbmNlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUHJpbWl0aXZlUmVmZXJlbmNlLCBfQ29uc3RSZWZlcmVuY2UpOwoKICAgIGZ1bmN0aW9uIFByaW1pdGl2ZVJlZmVyZW5jZSh2YWx1ZSQkMSkgewogICAgICByZXR1cm4gX0NvbnN0UmVmZXJlbmNlLmNhbGwodGhpcywgdmFsdWUkJDEpIHx8IHRoaXM7CiAgICB9CgogICAgUHJpbWl0aXZlUmVmZXJlbmNlLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSh2YWx1ZSQkMSkgewogICAgICBpZiAodmFsdWUkJDEgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBVTkRFRklORURfUkVGRVJFTkNFOwogICAgICB9IGVsc2UgaWYgKHZhbHVlJCQxID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIE5VTExfUkVGRVJFTkNFOwogICAgICB9IGVsc2UgaWYgKHZhbHVlJCQxID09PSB0cnVlKSB7CiAgICAgICAgcmV0dXJuIFRSVUVfUkVGRVJFTkNFOwogICAgICB9IGVsc2UgaWYgKHZhbHVlJCQxID09PSBmYWxzZSkgewogICAgICAgIHJldHVybiBGQUxTRV9SRUZFUkVOQ0U7CiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlJCQxID09PSAnbnVtYmVyJykgewogICAgICAgIHJldHVybiBuZXcgVmFsdWVSZWZlcmVuY2UodmFsdWUkJDEpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBuZXcgU3RyaW5nUmVmZXJlbmNlKHZhbHVlJCQxKTsKICAgICAgfQogICAgfTsKCiAgICB2YXIgX3Byb3RvMiA9IFByaW1pdGl2ZVJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5nZXQgPSBmdW5jdGlvbiBnZXQoX2tleSkgewogICAgICByZXR1cm4gVU5ERUZJTkVEX1JFRkVSRU5DRTsKICAgIH07CgogICAgcmV0dXJuIFByaW1pdGl2ZVJlZmVyZW5jZTsKICB9KF9yZWZlcmVuY2UyLkNvbnN0UmVmZXJlbmNlKTsKCiAgX2V4cG9ydHMuUHJpbWl0aXZlUmVmZXJlbmNlID0gUHJpbWl0aXZlUmVmZXJlbmNlOwoKICB2YXIgU3RyaW5nUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9QcmltaXRpdmVSZWZlcmVuY2UpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShTdHJpbmdSZWZlcmVuY2UsIF9QcmltaXRpdmVSZWZlcmVuY2UpOwoKICAgIGZ1bmN0aW9uIFN0cmluZ1JlZmVyZW5jZSgpIHsKICAgICAgdmFyIF90aGlzMjsKCiAgICAgIF90aGlzMiA9IF9QcmltaXRpdmVSZWZlcmVuY2UuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpczIubGVuZ3RoUmVmZXJlbmNlID0gbnVsbDsKICAgICAgcmV0dXJuIF90aGlzMjsKICAgIH0KCiAgICB2YXIgX3Byb3RvMyA9IFN0cmluZ1JlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMy5nZXQgPSBmdW5jdGlvbiBnZXQoa2V5KSB7CiAgICAgIGlmIChrZXkgPT09ICdsZW5ndGgnKSB7CiAgICAgICAgdmFyIGxlbmd0aFJlZmVyZW5jZSA9IHRoaXMubGVuZ3RoUmVmZXJlbmNlOwoKICAgICAgICBpZiAobGVuZ3RoUmVmZXJlbmNlID09PSBudWxsKSB7CiAgICAgICAgICBsZW5ndGhSZWZlcmVuY2UgPSB0aGlzLmxlbmd0aFJlZmVyZW5jZSA9IG5ldyBWYWx1ZVJlZmVyZW5jZSh0aGlzLmlubmVyLmxlbmd0aCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gbGVuZ3RoUmVmZXJlbmNlOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBfUHJpbWl0aXZlUmVmZXJlbmNlLnByb3RvdHlwZS5nZXQuY2FsbCh0aGlzLCBrZXkpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBTdHJpbmdSZWZlcmVuY2U7CiAgfShQcmltaXRpdmVSZWZlcmVuY2UpOwoKICB2YXIgVmFsdWVSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1ByaW1pdGl2ZVJlZmVyZW5jZTIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShWYWx1ZVJlZmVyZW5jZSwgX1ByaW1pdGl2ZVJlZmVyZW5jZTIpOwoKICAgIGZ1bmN0aW9uIFZhbHVlUmVmZXJlbmNlKHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiBfUHJpbWl0aXZlUmVmZXJlbmNlMi5jYWxsKHRoaXMsIHZhbHVlJCQxKSB8fCB0aGlzOwogICAgfQoKICAgIHJldHVybiBWYWx1ZVJlZmVyZW5jZTsKICB9KFByaW1pdGl2ZVJlZmVyZW5jZSk7CgogIHZhciBVTkRFRklORURfUkVGRVJFTkNFID0gbmV3IFZhbHVlUmVmZXJlbmNlKHVuZGVmaW5lZCk7CiAgX2V4cG9ydHMuVU5ERUZJTkVEX1JFRkVSRU5DRSA9IFVOREVGSU5FRF9SRUZFUkVOQ0U7CiAgdmFyIE5VTExfUkVGRVJFTkNFID0gbmV3IFZhbHVlUmVmZXJlbmNlKG51bGwpOwogIF9leHBvcnRzLk5VTExfUkVGRVJFTkNFID0gTlVMTF9SRUZFUkVOQ0U7CiAgdmFyIFRSVUVfUkVGRVJFTkNFID0gbmV3IFZhbHVlUmVmZXJlbmNlKHRydWUpOwogIHZhciBGQUxTRV9SRUZFUkVOQ0UgPSBuZXcgVmFsdWVSZWZlcmVuY2UoZmFsc2UpOwoKICB2YXIgQ29uZGl0aW9uYWxSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDb25kaXRpb25hbFJlZmVyZW5jZShpbm5lcikgewogICAgICB0aGlzLmlubmVyID0gaW5uZXI7CiAgICAgIHRoaXMudGFnID0gaW5uZXIudGFnOwogICAgfQoKICAgIHZhciBfcHJvdG80ID0gQ29uZGl0aW9uYWxSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzQudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgcmV0dXJuIHRoaXMudG9Cb29sKHRoaXMuaW5uZXIudmFsdWUoKSk7CiAgICB9OwoKICAgIF9wcm90bzQudG9Cb29sID0gZnVuY3Rpb24gdG9Cb29sKHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiAhIXZhbHVlJCQxOwogICAgfTsKCiAgICByZXR1cm4gQ29uZGl0aW9uYWxSZWZlcmVuY2U7CiAgfSgpOwoKICBfZXhwb3J0cy5Db25kaXRpb25hbFJlZmVyZW5jZSA9IENvbmRpdGlvbmFsUmVmZXJlbmNlOwoKICB2YXIgQ29uY2F0UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9DYWNoZWRSZWZlcmVuY2UpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDb25jYXRSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UpOwoKICAgIGZ1bmN0aW9uIENvbmNhdFJlZmVyZW5jZShwYXJ0cykgewogICAgICB2YXIgX3RoaXMzOwoKICAgICAgX3RoaXMzID0gX0NhY2hlZFJlZmVyZW5jZS5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMy5wYXJ0cyA9IHBhcnRzOwogICAgICBfdGhpczMudGFnID0gKDAsIF9yZWZlcmVuY2UyLmNvbWJpbmVUYWdnZWQpKHBhcnRzKTsKICAgICAgcmV0dXJuIF90aGlzMzsKICAgIH0KCiAgICB2YXIgX3Byb3RvNSA9IENvbmNhdFJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNS5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgdmFyIHBhcnRzID0gbmV3IEFycmF5KCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucGFydHMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgdmFsdWUkJDEgPSB0aGlzLnBhcnRzW2ldLnZhbHVlKCk7CgogICAgICAgIGlmICh2YWx1ZSQkMSAhPT0gbnVsbCAmJiB2YWx1ZSQkMSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBwYXJ0c1tpXSA9IGNhc3RUb1N0cmluZyh2YWx1ZSQkMSk7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAocGFydHMubGVuZ3RoID4gMCkgewogICAgICAgIHJldHVybiBwYXJ0cy5qb2luKCcnKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG51bGw7CiAgICB9OwoKICAgIHJldHVybiBDb25jYXRSZWZlcmVuY2U7CiAgfShfcmVmZXJlbmNlMi5DYWNoZWRSZWZlcmVuY2UpOwoKICBmdW5jdGlvbiBjYXN0VG9TdHJpbmcodmFsdWUkJDEpIHsKICAgIGlmICh0eXBlb2YgdmFsdWUkJDEudG9TdHJpbmcgIT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuICcnOwogICAgfQoKICAgIHJldHVybiBTdHJpbmcodmFsdWUkJDEpOwogIH0KCiAgQVBQRU5EX09QQ09ERVMuYWRkKDEKICAvKiBIZWxwZXIgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZikgewogICAgdmFyIGhhbmRsZSA9IF9yZWYub3AxOwogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgaGVscGVyID0gdm0uY29uc3RhbnRzLnJlc29sdmVIYW5kbGUoaGFuZGxlKTsKICAgIHZhciBhcmdzID0gc3RhY2sucG9wKCk7CiAgICB2YXIgdmFsdWUkJDEgPSBoZWxwZXIodm0sIGFyZ3MpOwogICAgdm0ubG9hZFZhbHVlKF92bTIuUmVnaXN0ZXIudjAsIHZhbHVlJCQxKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNgogIC8qIEdldFZhcmlhYmxlICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYyKSB7CiAgICB2YXIgc3ltYm9sID0gX3JlZjIub3AxOwogICAgdmFyIGV4cHIgPSB2bS5yZWZlcmVuY2VGb3JTeW1ib2woc3ltYm9sKTsKICAgIHZtLnN0YWNrLnB1c2goZXhwcik7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDQKICAvKiBTZXRWYXJpYWJsZSAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMykgewogICAgdmFyIHN5bWJvbCA9IF9yZWYzLm9wMTsKICAgIHZhciBleHByID0gdm0uc3RhY2sucG9wKCk7CiAgICB2bS5zY29wZSgpLmJpbmRTeW1ib2woc3ltYm9sLCBleHByKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNQogIC8qIFNldEJsb2NrICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY0KSB7CiAgICB2YXIgc3ltYm9sID0gX3JlZjQub3AxOwogICAgdmFyIGhhbmRsZSA9IHZtLnN0YWNrLnBvcCgpOwogICAgdmFyIHNjb3BlID0gdm0uc3RhY2sucG9wKCk7IC8vIEZJWE1FKG1tdW4pOiBzaG91bGRuJ3QgbmVlZCB0byBjYXN0IHRoaXMKCiAgICB2YXIgdGFibGUgPSB2bS5zdGFjay5wb3AoKTsKICAgIHZhciBibG9jayA9IHRhYmxlID8gW2hhbmRsZSwgc2NvcGUsIHRhYmxlXSA6IG51bGw7CiAgICB2bS5zY29wZSgpLmJpbmRCbG9jayhzeW1ib2wsIGJsb2NrKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoOTYKICAvKiBSZXNvbHZlTWF5YmVMb2NhbCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNSkgewogICAgdmFyIF9uYW1lID0gX3JlZjUub3AxOwogICAgdmFyIG5hbWUgPSB2bS5jb25zdGFudHMuZ2V0U3RyaW5nKF9uYW1lKTsKICAgIHZhciBsb2NhbHMgPSB2bS5zY29wZSgpLmdldFBhcnRpYWxNYXAoKTsKICAgIHZhciByZWYgPSBsb2NhbHNbbmFtZV07CgogICAgaWYgKHJlZiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJlZiA9IHZtLmdldFNlbGYoKS5nZXQobmFtZSk7CiAgICB9CgogICAgdm0uc3RhY2sucHVzaChyZWYpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgyMAogIC8qIFJvb3RTY29wZSAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNikgewogICAgdmFyIHN5bWJvbHMgPSBfcmVmNi5vcDEsCiAgICAgICAgYmluZENhbGxlclNjb3BlID0gX3JlZjYub3AyOwogICAgdm0ucHVzaFJvb3RTY29wZShzeW1ib2xzLCAhIWJpbmRDYWxsZXJTY29wZSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDcKICAvKiBHZXRQcm9wZXJ0eSAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNykgewogICAgdmFyIF9rZXkgPSBfcmVmNy5vcDE7CiAgICB2YXIga2V5ID0gdm0uY29uc3RhbnRzLmdldFN0cmluZyhfa2V5KTsKICAgIHZhciBleHByID0gdm0uc3RhY2sucG9wKCk7CiAgICB2bS5zdGFjay5wdXNoKGV4cHIuZ2V0KGtleSkpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4CiAgLyogR2V0QmxvY2sgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjgpIHsKICAgIHZhciBfYmxvY2sgPSBfcmVmOC5vcDE7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciBibG9jayA9IHZtLnNjb3BlKCkuZ2V0QmxvY2soX2Jsb2NrKTsKCiAgICBpZiAoYmxvY2spIHsKICAgICAgc3RhY2sucHVzaChibG9ja1syXSk7CiAgICAgIHN0YWNrLnB1c2goYmxvY2tbMV0pOwogICAgICBzdGFjay5wdXNoKGJsb2NrWzBdKTsKICAgIH0gZWxzZSB7CiAgICAgIHN0YWNrLnB1c2gobnVsbCk7CiAgICAgIHN0YWNrLnB1c2gobnVsbCk7CiAgICAgIHN0YWNrLnB1c2gobnVsbCk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDkKICAvKiBIYXNCbG9jayAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmOSkgewogICAgdmFyIF9ibG9jayA9IF9yZWY5Lm9wMTsKICAgIHZhciBoYXNCbG9jayA9ICEhdm0uc2NvcGUoKS5nZXRCbG9jayhfYmxvY2spOwogICAgdm0uc3RhY2sucHVzaChoYXNCbG9jayA/IFRSVUVfUkVGRVJFTkNFIDogRkFMU0VfUkVGRVJFTkNFKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMTAKICAvKiBIYXNCbG9ja1BhcmFtcyAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICAvLyBGSVhNRShtbXVuKTogc2hvdWxkIG9ubHkgbmVlZCB0byBwdXNoIHRoZSBzeW1ib2wgdGFibGUKICAgIHZhciBibG9jayA9IHZtLnN0YWNrLnBvcCgpOwogICAgdmFyIHNjb3BlID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgdGFibGUgPSB2bS5zdGFjay5wb3AoKTsKICAgIHZhciBoYXNCbG9ja1BhcmFtcyA9IHRhYmxlICYmIHRhYmxlLnBhcmFtZXRlcnMubGVuZ3RoOwogICAgdm0uc3RhY2sucHVzaChoYXNCbG9ja1BhcmFtcyA/IFRSVUVfUkVGRVJFTkNFIDogRkFMU0VfUkVGRVJFTkNFKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMTEKICAvKiBDb25jYXQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjEwKSB7CiAgICB2YXIgY291bnQgPSBfcmVmMTAub3AxOwogICAgdmFyIG91dCA9IG5ldyBBcnJheShjb3VudCk7CgogICAgZm9yICh2YXIgaSA9IGNvdW50OyBpID4gMDsgaS0tKSB7CiAgICAgIHZhciBvZmZzZXQgPSBpIC0gMTsKICAgICAgb3V0W29mZnNldF0gPSB2bS5zdGFjay5wb3AoKTsKICAgIH0KCiAgICB2bS5zdGFjay5wdXNoKG5ldyBDb25jYXRSZWZlcmVuY2Uob3V0KSk7CiAgfSk7CiAgdmFyIENVUlJJRURfQ09NUE9ORU5UX0RFRklOSVRJT05fQlJBTkQgPSAnQ1VSUklFRCBDT01QT05FTlQgREVGSU5JVElPTiBbaWQ9NmYwMGZlYjktYTBlZi00NTQ3LTk5ZWEtYWMzMjhmODBhY2VhXSc7CgogIGZ1bmN0aW9uIGlzQ3VycmllZENvbXBvbmVudERlZmluaXRpb24oZGVmaW5pdGlvbikgewogICAgcmV0dXJuICEhKGRlZmluaXRpb24gJiYgZGVmaW5pdGlvbltDVVJSSUVEX0NPTVBPTkVOVF9ERUZJTklUSU9OX0JSQU5EXSk7CiAgfQoKICBmdW5jdGlvbiBpc0NvbXBvbmVudERlZmluaXRpb24oZGVmaW5pdGlvbikgewogICAgcmV0dXJuIGRlZmluaXRpb24gJiYgZGVmaW5pdGlvbltDVVJSSUVEX0NPTVBPTkVOVF9ERUZJTklUSU9OX0JSQU5EXTsKICB9CgogIHZhciBDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIC8qKiBAaW50ZXJuYWwgKi8KICAgIGZ1bmN0aW9uIEN1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGlubmVyLCBhcmdzKSB7CiAgICAgIHRoaXMuaW5uZXIgPSBpbm5lcjsKICAgICAgdGhpcy5hcmdzID0gYXJnczsKICAgICAgdGhpc1tDVVJSSUVEX0NPTVBPTkVOVF9ERUZJTklUSU9OX0JSQU5EXSA9IHRydWU7CiAgICB9CgogICAgdmFyIF9wcm90bzYgPSBDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbi5wcm90b3R5cGU7CgogICAgX3Byb3RvNi51bndyYXAgPSBmdW5jdGlvbiB1bndyYXAoYXJncykgewogICAgICBhcmdzLnJlYWxsb2ModGhpcy5vZmZzZXQpOwogICAgICB2YXIgZGVmaW5pdGlvbiA9IHRoaXM7CgogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgIHZhciBfZGVmaW5pdGlvbiA9IGRlZmluaXRpb24sCiAgICAgICAgICAgIGN1cnJpZWRBcmdzID0gX2RlZmluaXRpb24uYXJncywKICAgICAgICAgICAgaW5uZXIgPSBfZGVmaW5pdGlvbi5pbm5lcjsKCiAgICAgICAgaWYgKGN1cnJpZWRBcmdzKSB7CiAgICAgICAgICBhcmdzLnBvc2l0aW9uYWwucHJlcGVuZChjdXJyaWVkQXJncy5wb3NpdGlvbmFsKTsKICAgICAgICAgIGFyZ3MubmFtZWQubWVyZ2UoY3VycmllZEFyZ3MubmFtZWQpOwogICAgICAgIH0KCiAgICAgICAgaWYgKCFpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGlubmVyKSkgewogICAgICAgICAgcmV0dXJuIGlubmVyOwogICAgICAgIH0KCiAgICAgICAgZGVmaW5pdGlvbiA9IGlubmVyOwogICAgICB9CiAgICB9CiAgICAvKiogQGludGVybmFsICovCiAgICA7CgogICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbiwgW3sKICAgICAga2V5OiAib2Zmc2V0IiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIGlubmVyID0gdGhpcy5pbm5lciwKICAgICAgICAgICAgYXJncyA9IHRoaXMuYXJnczsKICAgICAgICB2YXIgbGVuZ3RoID0gYXJncyA/IGFyZ3MucG9zaXRpb25hbC5sZW5ndGggOiAwOwogICAgICAgIHJldHVybiBpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGlubmVyKSA/IGxlbmd0aCArIGlubmVyLm9mZnNldCA6IGxlbmd0aDsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIEN1cnJpZWRDb21wb25lbnREZWZpbml0aW9uOwogIH0oKTsKCiAgX2V4cG9ydHMuQ3VycmllZENvbXBvbmVudERlZmluaXRpb24gPSBDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbjsKCiAgZnVuY3Rpb24gY3Vycnkoc3BlYywgYXJncykgewogICAgaWYgKGFyZ3MgPT09IHZvaWQgMCkgewogICAgICBhcmdzID0gbnVsbDsKICAgIH0KCiAgICByZXR1cm4gbmV3IEN1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKHNwZWMsIGFyZ3MpOwogIH0KCiAgZnVuY3Rpb24gbm9ybWFsaXplU3RyaW5nVmFsdWUodmFsdWUkJDEpIHsKICAgIGlmIChpc0VtcHR5KHZhbHVlJCQxKSkgewogICAgICByZXR1cm4gJyc7CiAgICB9CgogICAgcmV0dXJuIFN0cmluZyh2YWx1ZSQkMSk7CiAgfQoKICBmdW5jdGlvbiBzaG91bGRDb2VyY2UodmFsdWUkJDEpIHsKICAgIHJldHVybiBpc1N0cmluZyh2YWx1ZSQkMSkgfHwgaXNFbXB0eSh2YWx1ZSQkMSkgfHwgdHlwZW9mIHZhbHVlJCQxID09PSAnYm9vbGVhbicgfHwgdHlwZW9mIHZhbHVlJCQxID09PSAnbnVtYmVyJzsKICB9CgogIGZ1bmN0aW9uIGlzRW1wdHkodmFsdWUkJDEpIHsKICAgIHJldHVybiB2YWx1ZSQkMSA9PT0gbnVsbCB8fCB2YWx1ZSQkMSA9PT0gdW5kZWZpbmVkIHx8IHR5cGVvZiB2YWx1ZSQkMS50b1N0cmluZyAhPT0gJ2Z1bmN0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGlzU2FmZVN0cmluZyh2YWx1ZSQkMSkgewogICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSQkMSA9PT0gJ29iamVjdCcgJiYgdmFsdWUkJDEgIT09IG51bGwgJiYgdHlwZW9mIHZhbHVlJCQxLnRvSFRNTCA9PT0gJ2Z1bmN0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGlzTm9kZSh2YWx1ZSQkMSkgewogICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSQkMSA9PT0gJ29iamVjdCcgJiYgdmFsdWUkJDEgIT09IG51bGwgJiYgdHlwZW9mIHZhbHVlJCQxLm5vZGVUeXBlID09PSAnbnVtYmVyJzsKICB9CgogIGZ1bmN0aW9uIGlzRnJhZ21lbnQodmFsdWUkJDEpIHsKICAgIHJldHVybiBpc05vZGUodmFsdWUkJDEpICYmIHZhbHVlJCQxLm5vZGVUeXBlID09PSAxMTsKICB9CgogIGZ1bmN0aW9uIGlzU3RyaW5nKHZhbHVlJCQxKSB7CiAgICByZXR1cm4gdHlwZW9mIHZhbHVlJCQxID09PSAnc3RyaW5nJzsKICB9CgogIHZhciBEeW5hbWljVGV4dENvbnRlbnQgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1VwZGF0aW5nT3Bjb2RlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRHluYW1pY1RleHRDb250ZW50LCBfVXBkYXRpbmdPcGNvZGUpOwoKICAgIGZ1bmN0aW9uIER5bmFtaWNUZXh0Q29udGVudChub2RlLCByZWZlcmVuY2UsIGxhc3RWYWx1ZSkgewogICAgICB2YXIgX3RoaXM0OwoKICAgICAgX3RoaXM0ID0gX1VwZGF0aW5nT3Bjb2RlLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXM0Lm5vZGUgPSBub2RlOwogICAgICBfdGhpczQucmVmZXJlbmNlID0gcmVmZXJlbmNlOwogICAgICBfdGhpczQubGFzdFZhbHVlID0gbGFzdFZhbHVlOwogICAgICBfdGhpczQudHlwZSA9ICdkeW5hbWljLXRleHQnOwogICAgICBfdGhpczQudGFnID0gcmVmZXJlbmNlLnRhZzsKICAgICAgX3RoaXM0Lmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlMi52YWx1ZSkoX3RoaXM0LnRhZyk7CiAgICAgIHJldHVybiBfdGhpczQ7CiAgICB9CgogICAgdmFyIF9wcm90bzcgPSBEeW5hbWljVGV4dENvbnRlbnQucHJvdG90eXBlOwoKICAgIF9wcm90bzcuZXZhbHVhdGUgPSBmdW5jdGlvbiBldmFsdWF0ZSgpIHsKICAgICAgdmFyIHJlZmVyZW5jZSA9IHRoaXMucmVmZXJlbmNlLAogICAgICAgICAgdGFnID0gdGhpcy50YWc7CgogICAgICBpZiAoISgwLCBfcmVmZXJlbmNlMi52YWxpZGF0ZSkodGFnLCB0aGlzLmxhc3RSZXZpc2lvbikpIHsKICAgICAgICB0aGlzLmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlMi52YWx1ZSkodGFnKTsKICAgICAgICB0aGlzLnVwZGF0ZShyZWZlcmVuY2UudmFsdWUoKSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNy51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUodmFsdWUkJDEpIHsKICAgICAgdmFyIGxhc3RWYWx1ZSA9IHRoaXMubGFzdFZhbHVlOwogICAgICBpZiAodmFsdWUkJDEgPT09IGxhc3RWYWx1ZSkgcmV0dXJuOwogICAgICB2YXIgbm9ybWFsaXplZDsKCiAgICAgIGlmIChpc0VtcHR5KHZhbHVlJCQxKSkgewogICAgICAgIG5vcm1hbGl6ZWQgPSAnJzsKICAgICAgfSBlbHNlIGlmIChpc1N0cmluZyh2YWx1ZSQkMSkpIHsKICAgICAgICBub3JtYWxpemVkID0gdmFsdWUkJDE7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbm9ybWFsaXplZCA9IFN0cmluZyh2YWx1ZSQkMSk7CiAgICAgIH0KCiAgICAgIGlmIChub3JtYWxpemVkICE9PSBsYXN0VmFsdWUpIHsKICAgICAgICB2YXIgdGV4dE5vZGUgPSB0aGlzLm5vZGU7CiAgICAgICAgdGV4dE5vZGUubm9kZVZhbHVlID0gdGhpcy5sYXN0VmFsdWUgPSBub3JtYWxpemVkOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBEeW5hbWljVGV4dENvbnRlbnQ7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBJc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Db25kaXRpb25hbFJlZmVyZW5jZSkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKElzQ3VycmllZENvbXBvbmVudERlZmluaXRpb25SZWZlcmVuY2UsIF9Db25kaXRpb25hbFJlZmVyZW5jZSk7CgogICAgZnVuY3Rpb24gSXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvblJlZmVyZW5jZSgpIHsKICAgICAgcmV0dXJuIF9Db25kaXRpb25hbFJlZmVyZW5jZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgSXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvblJlZmVyZW5jZS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoaW5uZXIpIHsKICAgICAgcmV0dXJuIG5ldyBJc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uUmVmZXJlbmNlKGlubmVyKTsKICAgIH07CgogICAgdmFyIF9wcm90bzggPSBJc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG84LnRvQm9vbCA9IGZ1bmN0aW9uIHRvQm9vbCh2YWx1ZSQkMSkgewogICAgICByZXR1cm4gaXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbih2YWx1ZSQkMSk7CiAgICB9OwoKICAgIHJldHVybiBJc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uUmVmZXJlbmNlOwogIH0oQ29uZGl0aW9uYWxSZWZlcmVuY2UpOwoKICB2YXIgQ29udGVudFR5cGVSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDb250ZW50VHlwZVJlZmVyZW5jZShpbm5lcikgewogICAgICB0aGlzLmlubmVyID0gaW5uZXI7CiAgICAgIHRoaXMudGFnID0gaW5uZXIudGFnOwogICAgfQoKICAgIHZhciBfcHJvdG85ID0gQ29udGVudFR5cGVSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzkudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgdmFyIHZhbHVlJCQxID0gdGhpcy5pbm5lci52YWx1ZSgpOwoKICAgICAgaWYgKHNob3VsZENvZXJjZSh2YWx1ZSQkMSkpIHsKICAgICAgICByZXR1cm4gMQogICAgICAgIC8qIFN0cmluZyAqLwogICAgICAgIDsKICAgICAgfSBlbHNlIGlmIChpc0NvbXBvbmVudERlZmluaXRpb24odmFsdWUkJDEpKSB7CiAgICAgICAgcmV0dXJuIDAKICAgICAgICAvKiBDb21wb25lbnQgKi8KICAgICAgICA7CiAgICAgIH0gZWxzZSBpZiAoaXNTYWZlU3RyaW5nKHZhbHVlJCQxKSkgewogICAgICAgIHJldHVybiAzCiAgICAgICAgLyogU2FmZVN0cmluZyAqLwogICAgICAgIDsKICAgICAgfSBlbHNlIGlmIChpc0ZyYWdtZW50KHZhbHVlJCQxKSkgewogICAgICAgIHJldHVybiA0CiAgICAgICAgLyogRnJhZ21lbnQgKi8KICAgICAgICA7CiAgICAgIH0gZWxzZSBpZiAoaXNOb2RlKHZhbHVlJCQxKSkgewogICAgICAgIHJldHVybiA1CiAgICAgICAgLyogTm9kZSAqLwogICAgICAgIDsKICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAxCiAgICAgICAgICAvKiBTdHJpbmcgKi8KICAgICAgICAgIDsKICAgICAgICB9CiAgICB9OwoKICAgIHJldHVybiBDb250ZW50VHlwZVJlZmVyZW5jZTsKICB9KCk7CgogIEFQUEVORF9PUENPREVTLmFkZCgyOAogIC8qIEFwcGVuZEhUTUwgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIHJlZmVyZW5jZSA9IHZtLnN0YWNrLnBvcCgpOwogICAgdmFyIHJhd1ZhbHVlID0gcmVmZXJlbmNlLnZhbHVlKCk7CiAgICB2YXIgdmFsdWUkJDEgPSBpc0VtcHR5KHJhd1ZhbHVlKSA/ICcnIDogU3RyaW5nKHJhd1ZhbHVlKTsKICAgIHZtLmVsZW1lbnRzKCkuYXBwZW5kRHluYW1pY0hUTUwodmFsdWUkJDEpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgyOQogIC8qIEFwcGVuZFNhZmVIVE1MICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciByZWZlcmVuY2UgPSB2bS5zdGFjay5wb3AoKTsKICAgIHZhciByYXdWYWx1ZSA9IHJlZmVyZW5jZS52YWx1ZSgpLnRvSFRNTCgpOwogICAgdmFyIHZhbHVlJCQxID0gaXNFbXB0eShyYXdWYWx1ZSkgPyAnJyA6IHJhd1ZhbHVlOwogICAgdm0uZWxlbWVudHMoKS5hcHBlbmREeW5hbWljSFRNTCh2YWx1ZSQkMSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDMyCiAgLyogQXBwZW5kVGV4dCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgcmVmZXJlbmNlID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgcmF3VmFsdWUgPSByZWZlcmVuY2UudmFsdWUoKTsKICAgIHZhciB2YWx1ZSQkMSA9IGlzRW1wdHkocmF3VmFsdWUpID8gJycgOiBTdHJpbmcocmF3VmFsdWUpOwogICAgdmFyIG5vZGUgPSB2bS5lbGVtZW50cygpLmFwcGVuZER5bmFtaWNUZXh0KHZhbHVlJCQxKTsKCiAgICBpZiAoISgwLCBfcmVmZXJlbmNlMi5pc0NvbnN0KShyZWZlcmVuY2UpKSB7CiAgICAgIHZtLnVwZGF0ZVdpdGgobmV3IER5bmFtaWNUZXh0Q29udGVudChub2RlLCByZWZlcmVuY2UsIHZhbHVlJCQxKSk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDMwCiAgLyogQXBwZW5kRG9jdW1lbnRGcmFnbWVudCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgcmVmZXJlbmNlID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgdmFsdWUkJDEgPSByZWZlcmVuY2UudmFsdWUoKTsKICAgIHZtLmVsZW1lbnRzKCkuYXBwZW5kRHluYW1pY0ZyYWdtZW50KHZhbHVlJCQxKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMzEKICAvKiBBcHBlbmROb2RlICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciByZWZlcmVuY2UgPSB2bS5zdGFjay5wb3AoKTsKICAgIHZhciB2YWx1ZSQkMSA9IHJlZmVyZW5jZS52YWx1ZSgpOwogICAgdm0uZWxlbWVudHMoKS5hcHBlbmREeW5hbWljTm9kZSh2YWx1ZSQkMSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDIyCiAgLyogQ2hpbGRTY29wZSAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICByZXR1cm4gdm0ucHVzaENoaWxkU2NvcGUoKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMjMKICAvKiBQb3BTY29wZSAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICByZXR1cm4gdm0ucG9wU2NvcGUoKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNDQKICAvKiBQdXNoRHluYW1pY1Njb3BlICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHJldHVybiB2bS5wdXNoRHluYW1pY1Njb3BlKCk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDQ1CiAgLyogUG9wRHluYW1pY1Njb3BlICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHJldHVybiB2bS5wb3BEeW5hbWljU2NvcGUoKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMTIKICAvKiBDb25zdGFudCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMTEpIHsKICAgIHZhciBvdGhlciA9IF9yZWYxMS5vcDE7CiAgICB2bS5zdGFjay5wdXNoKHZtLmNvbnN0YW50cy5nZXRPdGhlcihvdGhlcikpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgxMwogIC8qIFByaW1pdGl2ZSAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMTIpIHsKICAgIHZhciBwcmltaXRpdmUgPSBfcmVmMTIub3AxOwogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgZmxhZyA9IHByaW1pdGl2ZSAmIDc7IC8vIDExMQoKICAgIHZhciB2YWx1ZSQkMSA9IHByaW1pdGl2ZSA+PiAzOwoKICAgIHN3aXRjaCAoZmxhZykgewogICAgICBjYXNlIDAKICAgICAgLyogTlVNQkVSICovCiAgICAgIDoKICAgICAgICBzdGFjay5wdXNoKHZhbHVlJCQxKTsKICAgICAgICBicmVhazsKCiAgICAgIGNhc2UgMQogICAgICAvKiBGTE9BVCAqLwogICAgICA6CiAgICAgICAgc3RhY2sucHVzaCh2bS5jb25zdGFudHMuZ2V0TnVtYmVyKHZhbHVlJCQxKSk7CiAgICAgICAgYnJlYWs7CgogICAgICBjYXNlIDIKICAgICAgLyogU1RSSU5HICovCiAgICAgIDoKICAgICAgICBzdGFjay5wdXNoKHZtLmNvbnN0YW50cy5nZXRTdHJpbmcodmFsdWUkJDEpKTsKICAgICAgICBicmVhazsKCiAgICAgIGNhc2UgMwogICAgICAvKiBCT09MRUFOX09SX1ZPSUQgKi8KICAgICAgOgogICAgICAgIHN0YWNrLnB1c2hFbmNvZGVkSW1tZWRpYXRlKHByaW1pdGl2ZSk7CiAgICAgICAgYnJlYWs7CgogICAgICBjYXNlIDQKICAgICAgLyogTkVHQVRJVkUgKi8KICAgICAgOgogICAgICAgIHN0YWNrLnB1c2godm0uY29uc3RhbnRzLmdldE51bWJlcih2YWx1ZSQkMSkpOwogICAgICAgIGJyZWFrOwoKICAgICAgY2FzZSA1CiAgICAgIC8qIEJJR19OVU0gKi8KICAgICAgOgogICAgICAgIHN0YWNrLnB1c2godm0uY29uc3RhbnRzLmdldE51bWJlcih2YWx1ZSQkMSkpOwogICAgICAgIGJyZWFrOwogICAgfQogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgxNAogIC8qIFByaW1pdGl2ZVJlZmVyZW5jZSAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHN0YWNrLnB1c2goUHJpbWl0aXZlUmVmZXJlbmNlLmNyZWF0ZShzdGFjay5wb3AoKSkpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgxNQogIC8qIFJlaWZ5VTMyICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgc3RhY2sucHVzaChzdGFjay5wZWVrKCkudmFsdWUoKSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDE2CiAgLyogRHVwICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYxMykgewogICAgdmFyIHJlZ2lzdGVyID0gX3JlZjEzLm9wMSwKICAgICAgICBvZmZzZXQgPSBfcmVmMTMub3AyOwogICAgdmFyIHBvc2l0aW9uID0gdm0uZmV0Y2hWYWx1ZShyZWdpc3RlcikgLSBvZmZzZXQ7CiAgICB2bS5zdGFjay5kdXAocG9zaXRpb24pOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgxNwogIC8qIFBvcCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMTQpIHsKICAgIHZhciBjb3VudCA9IF9yZWYxNC5vcDE7CiAgICB2bS5zdGFjay5wb3AoY291bnQpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgxOAogIC8qIExvYWQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjE1KSB7CiAgICB2YXIgcmVnaXN0ZXIgPSBfcmVmMTUub3AxOwogICAgdm0ubG9hZChyZWdpc3Rlcik7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDE5CiAgLyogRmV0Y2ggKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjE2KSB7CiAgICB2YXIgcmVnaXN0ZXIgPSBfcmVmMTYub3AxOwogICAgdm0uZmV0Y2gocmVnaXN0ZXIpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg0MwogIC8qIEJpbmREeW5hbWljU2NvcGUgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjE3KSB7CiAgICB2YXIgX25hbWVzID0gX3JlZjE3Lm9wMTsKICAgIHZhciBuYW1lcyA9IHZtLmNvbnN0YW50cy5nZXRBcnJheShfbmFtZXMpOwogICAgdm0uYmluZER5bmFtaWNTY29wZShuYW1lcyk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDYxCiAgLyogRW50ZXIgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjE4KSB7CiAgICB2YXIgYXJncyA9IF9yZWYxOC5vcDE7CiAgICB2bS5lbnRlcihhcmdzKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNjIKICAvKiBFeGl0ICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZtLmV4aXQoKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNDgKICAvKiBQdXNoU3ltYm9sVGFibGUgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjE5KSB7CiAgICB2YXIgX3RhYmxlID0gX3JlZjE5Lm9wMTsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgc3RhY2sucHVzaCh2bS5jb25zdGFudHMuZ2V0U2VyaWFsaXphYmxlKF90YWJsZSkpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg0NwogIC8qIFB1c2hCbG9ja1Njb3BlICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgc3RhY2sucHVzaCh2bS5zY29wZSgpKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNDYKICAvKiBDb21waWxlQmxvY2sgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgYmxvY2sgPSBzdGFjay5wb3AoKTsKCiAgICBpZiAoYmxvY2spIHsKICAgICAgc3RhY2sucHVzaChibG9jay5jb21waWxlKCkpOwogICAgfSBlbHNlIHsKICAgICAgc3RhY2sucHVzaE51bGwoKTsKICAgIH0KICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNTEKICAvKiBJbnZva2VZaWVsZCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciBoYW5kbGUgPSBzdGFjay5wb3AoKTsKICAgIHZhciBzY29wZSA9IHN0YWNrLnBvcCgpOyAvLyBGSVhNRShtbXVuKTogc2hvdWxkbid0IG5lZWQgdG8gY2FzdCB0aGlzCgogICAgdmFyIHRhYmxlID0gc3RhY2sucG9wKCk7CiAgICB2YXIgYXJncyA9IHN0YWNrLnBvcCgpOwoKICAgIGlmICh0YWJsZSA9PT0gbnVsbCkgewogICAgICAvLyBUbyBiYWxhbmNlIHRoZSBwb3B7RnJhbWUsU2NvcGV9CiAgICAgIHZtLnB1c2hGcmFtZSgpOwogICAgICB2bS5wdXNoU2NvcGUoc2NvcGUpOyAvLyBDb3VsZCBiZSBudWxsIGJ1dCBpdCBkb2VzbnQgbWF0dGVyIGFzIGl0IGlzIGltbWVkaWF0ZWxseSBwb3BwZWQuCgogICAgICByZXR1cm47CiAgICB9CgogICAgdmFyIGludm9raW5nU2NvcGUgPSBzY29wZTsgLy8gSWYgbmVjZXNzYXJ5LCBjcmVhdGUgYSBjaGlsZCBzY29wZQoKICAgIHsKICAgICAgdmFyIGxvY2FscyA9IHRhYmxlLnBhcmFtZXRlcnM7CiAgICAgIHZhciBsb2NhbHNDb3VudCA9IGxvY2Fscy5sZW5ndGg7CgogICAgICBpZiAobG9jYWxzQ291bnQgPiAwKSB7CiAgICAgICAgaW52b2tpbmdTY29wZSA9IGludm9raW5nU2NvcGUuY2hpbGQoKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb2NhbHNDb3VudDsgaSsrKSB7CiAgICAgICAgICBpbnZva2luZ1Njb3BlLmJpbmRTeW1ib2wobG9jYWxzW2ldLCBhcmdzLmF0KGkpKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHZtLnB1c2hGcmFtZSgpOwogICAgdm0ucHVzaFNjb3BlKGludm9raW5nU2NvcGUpOwogICAgdm0uY2FsbChoYW5kbGUpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg1MwogIC8qIEp1bXBJZiAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMjApIHsKICAgIHZhciB0YXJnZXQgPSBfcmVmMjAub3AxOwogICAgdmFyIHJlZmVyZW5jZSA9IHZtLnN0YWNrLnBvcCgpOwoKICAgIGlmICgoMCwgX3JlZmVyZW5jZTIuaXNDb25zdCkocmVmZXJlbmNlKSkgewogICAgICBpZiAocmVmZXJlbmNlLnZhbHVlKCkpIHsKICAgICAgICB2bS5nb3RvKHRhcmdldCk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhciBjYWNoZSA9IG5ldyBfcmVmZXJlbmNlMi5SZWZlcmVuY2VDYWNoZShyZWZlcmVuY2UpOwoKICAgICAgaWYgKGNhY2hlLnBlZWsoKSkgewogICAgICAgIHZtLmdvdG8odGFyZ2V0KTsKICAgICAgfQoKICAgICAgdm0udXBkYXRlV2l0aChuZXcgQXNzZXJ0KGNhY2hlKSk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDU0CiAgLyogSnVtcFVubGVzcyAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMjEpIHsKICAgIHZhciB0YXJnZXQgPSBfcmVmMjEub3AxOwogICAgdmFyIHJlZmVyZW5jZSA9IHZtLnN0YWNrLnBvcCgpOwoKICAgIGlmICgoMCwgX3JlZmVyZW5jZTIuaXNDb25zdCkocmVmZXJlbmNlKSkgewogICAgICBpZiAoIXJlZmVyZW5jZS52YWx1ZSgpKSB7CiAgICAgICAgdm0uZ290byh0YXJnZXQpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB2YXIgY2FjaGUgPSBuZXcgX3JlZmVyZW5jZTIuUmVmZXJlbmNlQ2FjaGUocmVmZXJlbmNlKTsKCiAgICAgIGlmICghY2FjaGUucGVlaygpKSB7CiAgICAgICAgdm0uZ290byh0YXJnZXQpOwogICAgICB9CgogICAgICB2bS51cGRhdGVXaXRoKG5ldyBBc3NlcnQoY2FjaGUpKTsKICAgIH0KICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNTUKICAvKiBKdW1wRXEgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjIyKSB7CiAgICB2YXIgdGFyZ2V0ID0gX3JlZjIyLm9wMSwKICAgICAgICBjb21wYXJpc29uID0gX3JlZjIyLm9wMjsKICAgIHZhciBvdGhlciA9IHZtLnN0YWNrLnBlZWsoKTsKCiAgICBpZiAob3RoZXIgPT09IGNvbXBhcmlzb24pIHsKICAgICAgdm0uZ290byh0YXJnZXQpOwogICAgfQogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg1NgogIC8qIEFzc2VydFNhbWUgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIHJlZmVyZW5jZSA9IHZtLnN0YWNrLnBlZWsoKTsKCiAgICBpZiAoISgwLCBfcmVmZXJlbmNlMi5pc0NvbnN0KShyZWZlcmVuY2UpKSB7CiAgICAgIHZtLnVwZGF0ZVdpdGgoQXNzZXJ0LmluaXRpYWxpemUobmV3IF9yZWZlcmVuY2UyLlJlZmVyZW5jZUNhY2hlKHJlZmVyZW5jZSkpKTsKICAgIH0KICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNjMKICAvKiBUb0Jvb2xlYW4gKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIGVudiA9IHZtLmVudiwKICAgICAgICBzdGFjayA9IHZtLnN0YWNrOwogICAgc3RhY2sucHVzaChlbnYudG9Db25kaXRpb25hbFJlZmVyZW5jZShzdGFjay5wb3AoKSkpOwogIH0pOwoKICB2YXIgQXNzZXJ0ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9VcGRhdGluZ09wY29kZTIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShBc3NlcnQsIF9VcGRhdGluZ09wY29kZTIpOwoKICAgIGZ1bmN0aW9uIEFzc2VydChjYWNoZSkgewogICAgICB2YXIgX3RoaXM1OwoKICAgICAgX3RoaXM1ID0gX1VwZGF0aW5nT3Bjb2RlMi5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzNS50eXBlID0gJ2Fzc2VydCc7CiAgICAgIF90aGlzNS50YWcgPSBjYWNoZS50YWc7CiAgICAgIF90aGlzNS5jYWNoZSA9IGNhY2hlOwogICAgICByZXR1cm4gX3RoaXM1OwogICAgfQoKICAgIEFzc2VydC5pbml0aWFsaXplID0gZnVuY3Rpb24gaW5pdGlhbGl6ZShjYWNoZSkgewogICAgICB2YXIgYXNzZXJ0ID0gbmV3IEFzc2VydChjYWNoZSk7CiAgICAgIGNhY2hlLnBlZWsoKTsKICAgICAgcmV0dXJuIGFzc2VydDsKICAgIH07CgogICAgdmFyIF9wcm90bzEwID0gQXNzZXJ0LnByb3RvdHlwZTsKCiAgICBfcHJvdG8xMC5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKHZtKSB7CiAgICAgIHZhciBjYWNoZSA9IHRoaXMuY2FjaGU7CgogICAgICBpZiAoKDAsIF9yZWZlcmVuY2UyLmlzTW9kaWZpZWQpKGNhY2hlLnJldmFsaWRhdGUoKSkpIHsKICAgICAgICB2bS50aHJvdygpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBBc3NlcnQ7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBKdW1wSWZOb3RNb2RpZmllZE9wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfVXBkYXRpbmdPcGNvZGUzKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoSnVtcElmTm90TW9kaWZpZWRPcGNvZGUsIF9VcGRhdGluZ09wY29kZTMpOwoKICAgIGZ1bmN0aW9uIEp1bXBJZk5vdE1vZGlmaWVkT3Bjb2RlKHRhZywgdGFyZ2V0KSB7CiAgICAgIHZhciBfdGhpczY7CgogICAgICBfdGhpczYgPSBfVXBkYXRpbmdPcGNvZGUzLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXM2LnRhcmdldCA9IHRhcmdldDsKICAgICAgX3RoaXM2LnR5cGUgPSAnanVtcC1pZi1ub3QtbW9kaWZpZWQnOwogICAgICBfdGhpczYudGFnID0gdGFnOwogICAgICBfdGhpczYubGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UyLnZhbHVlKSh0YWcpOwogICAgICByZXR1cm4gX3RoaXM2OwogICAgfQoKICAgIHZhciBfcHJvdG8xMSA9IEp1bXBJZk5vdE1vZGlmaWVkT3Bjb2RlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xMS5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKHZtKSB7CiAgICAgIHZhciB0YWcgPSB0aGlzLnRhZywKICAgICAgICAgIHRhcmdldCA9IHRoaXMudGFyZ2V0LAogICAgICAgICAgbGFzdFJldmlzaW9uID0gdGhpcy5sYXN0UmV2aXNpb247CgogICAgICBpZiAoIXZtLmFsd2F5c1JldmFsaWRhdGUgJiYgKDAsIF9yZWZlcmVuY2UyLnZhbGlkYXRlKSh0YWcsIGxhc3RSZXZpc2lvbikpIHsKICAgICAgICB2bS5nb3RvKHRhcmdldCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTEuZGlkTW9kaWZ5ID0gZnVuY3Rpb24gZGlkTW9kaWZ5KCkgewogICAgICB0aGlzLmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlMi52YWx1ZSkodGhpcy50YWcpOwogICAgfTsKCiAgICByZXR1cm4gSnVtcElmTm90TW9kaWZpZWRPcGNvZGU7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBEaWRNb2RpZnlPcGNvZGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1VwZGF0aW5nT3Bjb2RlNCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKERpZE1vZGlmeU9wY29kZSwgX1VwZGF0aW5nT3Bjb2RlNCk7CgogICAgZnVuY3Rpb24gRGlkTW9kaWZ5T3Bjb2RlKHRhcmdldCkgewogICAgICB2YXIgX3RoaXM3OwoKICAgICAgX3RoaXM3ID0gX1VwZGF0aW5nT3Bjb2RlNC5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzNy50YXJnZXQgPSB0YXJnZXQ7CiAgICAgIF90aGlzNy50eXBlID0gJ2RpZC1tb2RpZnknOwogICAgICBfdGhpczcudGFnID0gX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHOwogICAgICByZXR1cm4gX3RoaXM3OwogICAgfQoKICAgIHZhciBfcHJvdG8xMiA9IERpZE1vZGlmeU9wY29kZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMTIuZXZhbHVhdGUgPSBmdW5jdGlvbiBldmFsdWF0ZSgpIHsKICAgICAgdGhpcy50YXJnZXQuZGlkTW9kaWZ5KCk7CiAgICB9OwoKICAgIHJldHVybiBEaWRNb2RpZnlPcGNvZGU7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBMYWJlbE9wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIExhYmVsT3Bjb2RlKGxhYmVsKSB7CiAgICAgIHRoaXMudGFnID0gX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHOwogICAgICB0aGlzLnR5cGUgPSAnbGFiZWwnOwogICAgICB0aGlzLmxhYmVsID0gbnVsbDsKICAgICAgdGhpcy5wcmV2ID0gbnVsbDsKICAgICAgdGhpcy5uZXh0ID0gbnVsbDsKICAgICAgKDAsIF91dGlsLmluaXRpYWxpemVHdWlkKSh0aGlzKTsKICAgICAgdGhpcy5sYWJlbCA9IGxhYmVsOwogICAgfQoKICAgIHZhciBfcHJvdG8xMyA9IExhYmVsT3Bjb2RlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xMy5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKCkge307CgogICAgX3Byb3RvMTMuaW5zcGVjdCA9IGZ1bmN0aW9uIGluc3BlY3QoKSB7CiAgICAgIHJldHVybiB0aGlzLmxhYmVsICsgIiBbIiArIHRoaXMuX2d1aWQgKyAiXSI7CiAgICB9OwoKICAgIHJldHVybiBMYWJlbE9wY29kZTsKICB9KCk7CgogIEFQUEVORF9PUENPREVTLmFkZCgyNgogIC8qIFRleHQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjIzKSB7CiAgICB2YXIgdGV4dCA9IF9yZWYyMy5vcDE7CiAgICB2bS5lbGVtZW50cygpLmFwcGVuZFRleHQodm0uY29uc3RhbnRzLmdldFN0cmluZyh0ZXh0KSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDI3CiAgLyogQ29tbWVudCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMjQpIHsKICAgIHZhciB0ZXh0ID0gX3JlZjI0Lm9wMTsKICAgIHZtLmVsZW1lbnRzKCkuYXBwZW5kQ29tbWVudCh2bS5jb25zdGFudHMuZ2V0U3RyaW5nKHRleHQpKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMzMKICAvKiBPcGVuRWxlbWVudCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMjUpIHsKICAgIHZhciB0YWcgPSBfcmVmMjUub3AxOwogICAgdm0uZWxlbWVudHMoKS5vcGVuRWxlbWVudCh2bS5jb25zdGFudHMuZ2V0U3RyaW5nKHRhZykpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgzNAogIC8qIE9wZW5EeW5hbWljRWxlbWVudCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgdGFnTmFtZSA9IHZtLnN0YWNrLnBvcCgpLnZhbHVlKCk7CiAgICB2bS5lbGVtZW50cygpLm9wZW5FbGVtZW50KHRhZ05hbWUpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg0MQogIC8qIFB1c2hSZW1vdGVFbGVtZW50ICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBlbGVtZW50UmVmID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgbmV4dFNpYmxpbmdSZWYgPSB2bS5zdGFjay5wb3AoKTsKICAgIHZhciBndWlkUmVmID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgZWxlbWVudDsKICAgIHZhciBuZXh0U2libGluZzsKICAgIHZhciBndWlkID0gZ3VpZFJlZi52YWx1ZSgpOwoKICAgIGlmICgoMCwgX3JlZmVyZW5jZTIuaXNDb25zdCkoZWxlbWVudFJlZikpIHsKICAgICAgZWxlbWVudCA9IGVsZW1lbnRSZWYudmFsdWUoKTsKICAgIH0gZWxzZSB7CiAgICAgIHZhciBjYWNoZSA9IG5ldyBfcmVmZXJlbmNlMi5SZWZlcmVuY2VDYWNoZShlbGVtZW50UmVmKTsKICAgICAgZWxlbWVudCA9IGNhY2hlLnBlZWsoKTsKICAgICAgdm0udXBkYXRlV2l0aChuZXcgQXNzZXJ0KGNhY2hlKSk7CiAgICB9CgogICAgaWYgKCgwLCBfcmVmZXJlbmNlMi5pc0NvbnN0KShuZXh0U2libGluZ1JlZikpIHsKICAgICAgbmV4dFNpYmxpbmcgPSBuZXh0U2libGluZ1JlZi52YWx1ZSgpOwogICAgfSBlbHNlIHsKICAgICAgdmFyIF9jYWNoZSA9IG5ldyBfcmVmZXJlbmNlMi5SZWZlcmVuY2VDYWNoZShuZXh0U2libGluZ1JlZik7CgogICAgICBuZXh0U2libGluZyA9IF9jYWNoZS5wZWVrKCk7CiAgICAgIHZtLnVwZGF0ZVdpdGgobmV3IEFzc2VydChfY2FjaGUpKTsKICAgIH0KCiAgICB2bS5lbGVtZW50cygpLnB1c2hSZW1vdGVFbGVtZW50KGVsZW1lbnQsIGd1aWQsIG5leHRTaWJsaW5nKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNDIKICAvKiBQb3BSZW1vdGVFbGVtZW50ICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZtLmVsZW1lbnRzKCkucG9wUmVtb3RlRWxlbWVudCgpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgzOAogIC8qIEZsdXNoRWxlbWVudCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgb3BlcmF0aW9ucyA9IHZtLmZldGNoVmFsdWUoX3ZtMi5SZWdpc3Rlci50MCk7CiAgICB2YXIgbW9kaWZpZXJzID0gbnVsbDsKCiAgICBpZiAob3BlcmF0aW9ucykgewogICAgICBtb2RpZmllcnMgPSBvcGVyYXRpb25zLmZsdXNoKHZtKTsKICAgICAgdm0ubG9hZFZhbHVlKF92bTIuUmVnaXN0ZXIudDAsIG51bGwpOwogICAgfQoKICAgIHZtLmVsZW1lbnRzKCkuZmx1c2hFbGVtZW50KG1vZGlmaWVycyk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDM5CiAgLyogQ2xvc2VFbGVtZW50ICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBtb2RpZmllcnMgPSB2bS5lbGVtZW50cygpLmNsb3NlRWxlbWVudCgpOwoKICAgIGlmIChtb2RpZmllcnMpIHsKICAgICAgbW9kaWZpZXJzLmZvckVhY2goZnVuY3Rpb24gKF9yZWYyNikgewogICAgICAgIHZhciBtYW5hZ2VyID0gX3JlZjI2WzBdLAogICAgICAgICAgICBtb2RpZmllciA9IF9yZWYyNlsxXTsKICAgICAgICB2bS5lbnYuc2NoZWR1bGVJbnN0YWxsTW9kaWZpZXIobW9kaWZpZXIsIG1hbmFnZXIpOwogICAgICAgIHZhciBkZXN0cnVjdG9yID0gbWFuYWdlci5nZXREZXN0cnVjdG9yKG1vZGlmaWVyKTsKCiAgICAgICAgaWYgKGRlc3RydWN0b3IpIHsKICAgICAgICAgIHZtLm5ld0Rlc3Ryb3lhYmxlKGRlc3RydWN0b3IpOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDQwCiAgLyogTW9kaWZpZXIgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjI3KSB7CiAgICB2YXIgaGFuZGxlID0gX3JlZjI3Lm9wMTsKCiAgICB2YXIgX3ZtJGNvbnN0YW50cyRyZXNvbHZlID0gdm0uY29uc3RhbnRzLnJlc29sdmVIYW5kbGUoaGFuZGxlKSwKICAgICAgICBtYW5hZ2VyID0gX3ZtJGNvbnN0YW50cyRyZXNvbHZlLm1hbmFnZXIsCiAgICAgICAgc3RhdGUgPSBfdm0kY29uc3RhbnRzJHJlc29sdmUuc3RhdGU7CgogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgYXJncyA9IHN0YWNrLnBvcCgpOwoKICAgIHZhciBfdm0kZWxlbWVudHMgPSB2bS5lbGVtZW50cygpLAogICAgICAgIGNvbnN0cnVjdGluZyA9IF92bSRlbGVtZW50cy5jb25zdHJ1Y3RpbmcsCiAgICAgICAgdXBkYXRlT3BlcmF0aW9ucyA9IF92bSRlbGVtZW50cy51cGRhdGVPcGVyYXRpb25zOwoKICAgIHZhciBkeW5hbWljU2NvcGUgPSB2bS5keW5hbWljU2NvcGUoKTsKICAgIHZhciBtb2RpZmllciA9IG1hbmFnZXIuY3JlYXRlKGNvbnN0cnVjdGluZywgc3RhdGUsIGFyZ3MsIGR5bmFtaWNTY29wZSwgdXBkYXRlT3BlcmF0aW9ucyk7CiAgICB2YXIgb3BlcmF0aW9ucyA9IHZtLmZldGNoVmFsdWUoX3ZtMi5SZWdpc3Rlci50MCk7CiAgICBvcGVyYXRpb25zLmFkZE1vZGlmaWVyKG1hbmFnZXIsIG1vZGlmaWVyKTsKICAgIHZhciB0YWcgPSBtYW5hZ2VyLmdldFRhZyhtb2RpZmllcik7CgogICAgaWYgKCEoMCwgX3JlZmVyZW5jZTIuaXNDb25zdFRhZykodGFnKSkgewogICAgICB2bS51cGRhdGVXaXRoKG5ldyBVcGRhdGVNb2RpZmllck9wY29kZSh0YWcsIG1hbmFnZXIsIG1vZGlmaWVyKSk7CiAgICB9CiAgfSk7CgogIHZhciBVcGRhdGVNb2RpZmllck9wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfVXBkYXRpbmdPcGNvZGU1KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoVXBkYXRlTW9kaWZpZXJPcGNvZGUsIF9VcGRhdGluZ09wY29kZTUpOwoKICAgIGZ1bmN0aW9uIFVwZGF0ZU1vZGlmaWVyT3Bjb2RlKHRhZywgbWFuYWdlciwgbW9kaWZpZXIpIHsKICAgICAgdmFyIF90aGlzODsKCiAgICAgIF90aGlzOCA9IF9VcGRhdGluZ09wY29kZTUuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczgudGFnID0gdGFnOwogICAgICBfdGhpczgubWFuYWdlciA9IG1hbmFnZXI7CiAgICAgIF90aGlzOC5tb2RpZmllciA9IG1vZGlmaWVyOwogICAgICBfdGhpczgudHlwZSA9ICd1cGRhdGUtbW9kaWZpZXInOwogICAgICBfdGhpczgubGFzdFVwZGF0ZWQgPSAoMCwgX3JlZmVyZW5jZTIudmFsdWUpKHRhZyk7CiAgICAgIHJldHVybiBfdGhpczg7CiAgICB9CgogICAgdmFyIF9wcm90bzE0ID0gVXBkYXRlTW9kaWZpZXJPcGNvZGUucHJvdG90eXBlOwoKICAgIF9wcm90bzE0LmV2YWx1YXRlID0gZnVuY3Rpb24gZXZhbHVhdGUodm0pIHsKICAgICAgdmFyIG1hbmFnZXIgPSB0aGlzLm1hbmFnZXIsCiAgICAgICAgICBtb2RpZmllciA9IHRoaXMubW9kaWZpZXIsCiAgICAgICAgICB0YWcgPSB0aGlzLnRhZywKICAgICAgICAgIGxhc3RVcGRhdGVkID0gdGhpcy5sYXN0VXBkYXRlZDsKCiAgICAgIGlmICghKDAsIF9yZWZlcmVuY2UyLnZhbGlkYXRlKSh0YWcsIGxhc3RVcGRhdGVkKSkgewogICAgICAgIHZtLmVudi5zY2hlZHVsZVVwZGF0ZU1vZGlmaWVyKG1vZGlmaWVyLCBtYW5hZ2VyKTsKICAgICAgICB0aGlzLmxhc3RVcGRhdGVkID0gKDAsIF9yZWZlcmVuY2UyLnZhbHVlKSh0YWcpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBVcGRhdGVNb2RpZmllck9wY29kZTsKICB9KFVwZGF0aW5nT3Bjb2RlKTsKCiAgQVBQRU5EX09QQ09ERVMuYWRkKDM1CiAgLyogU3RhdGljQXR0ciAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMjgpIHsKICAgIHZhciBfbmFtZSA9IF9yZWYyOC5vcDEsCiAgICAgICAgX3ZhbHVlID0gX3JlZjI4Lm9wMiwKICAgICAgICBfbmFtZXNwYWNlID0gX3JlZjI4Lm9wMzsKICAgIHZhciBuYW1lID0gdm0uY29uc3RhbnRzLmdldFN0cmluZyhfbmFtZSk7CiAgICB2YXIgdmFsdWUkJDEgPSB2bS5jb25zdGFudHMuZ2V0U3RyaW5nKF92YWx1ZSk7CiAgICB2YXIgbmFtZXNwYWNlID0gX25hbWVzcGFjZSA/IHZtLmNvbnN0YW50cy5nZXRTdHJpbmcoX25hbWVzcGFjZSkgOiBudWxsOwogICAgdm0uZWxlbWVudHMoKS5zZXRTdGF0aWNBdHRyaWJ1dGUobmFtZSwgdmFsdWUkJDEsIG5hbWVzcGFjZSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDM2CiAgLyogRHluYW1pY0F0dHIgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjI5KSB7CiAgICB2YXIgX25hbWUgPSBfcmVmMjkub3AxLAogICAgICAgIHRydXN0aW5nID0gX3JlZjI5Lm9wMiwKICAgICAgICBfbmFtZXNwYWNlID0gX3JlZjI5Lm9wMzsKICAgIHZhciBuYW1lID0gdm0uY29uc3RhbnRzLmdldFN0cmluZyhfbmFtZSk7CiAgICB2YXIgcmVmZXJlbmNlID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgdmFsdWUkJDEgPSByZWZlcmVuY2UudmFsdWUoKTsKICAgIHZhciBuYW1lc3BhY2UgPSBfbmFtZXNwYWNlID8gdm0uY29uc3RhbnRzLmdldFN0cmluZyhfbmFtZXNwYWNlKSA6IG51bGw7CiAgICB2YXIgYXR0cmlidXRlID0gdm0uZWxlbWVudHMoKS5zZXREeW5hbWljQXR0cmlidXRlKG5hbWUsIHZhbHVlJCQxLCAhIXRydXN0aW5nLCBuYW1lc3BhY2UpOwoKICAgIGlmICghKDAsIF9yZWZlcmVuY2UyLmlzQ29uc3QpKHJlZmVyZW5jZSkpIHsKICAgICAgdm0udXBkYXRlV2l0aChuZXcgVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZShyZWZlcmVuY2UsIGF0dHJpYnV0ZSkpOwogICAgfQogIH0pOwoKICB2YXIgVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfVXBkYXRpbmdPcGNvZGU2KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZSwgX1VwZGF0aW5nT3Bjb2RlNik7CgogICAgZnVuY3Rpb24gVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZShyZWZlcmVuY2UsIGF0dHJpYnV0ZSkgewogICAgICB2YXIgX3RoaXM5OwoKICAgICAgX3RoaXM5ID0gX1VwZGF0aW5nT3Bjb2RlNi5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzOS5yZWZlcmVuY2UgPSByZWZlcmVuY2U7CiAgICAgIF90aGlzOS5hdHRyaWJ1dGUgPSBhdHRyaWJ1dGU7CiAgICAgIF90aGlzOS50eXBlID0gJ3BhdGNoLWVsZW1lbnQnOwogICAgICB2YXIgdGFnID0gcmVmZXJlbmNlLnRhZzsKICAgICAgX3RoaXM5LnRhZyA9IHRhZzsKICAgICAgX3RoaXM5Lmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlMi52YWx1ZSkodGFnKTsKICAgICAgcmV0dXJuIF90aGlzOTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTUgPSBVcGRhdGVEeW5hbWljQXR0cmlidXRlT3Bjb2RlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xNS5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKHZtKSB7CiAgICAgIHZhciBhdHRyaWJ1dGUgPSB0aGlzLmF0dHJpYnV0ZSwKICAgICAgICAgIHJlZmVyZW5jZSA9IHRoaXMucmVmZXJlbmNlLAogICAgICAgICAgdGFnID0gdGhpcy50YWc7CgogICAgICBpZiAoISgwLCBfcmVmZXJlbmNlMi52YWxpZGF0ZSkodGFnLCB0aGlzLmxhc3RSZXZpc2lvbikpIHsKICAgICAgICB0aGlzLmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlMi52YWx1ZSkodGFnKTsKICAgICAgICBhdHRyaWJ1dGUudXBkYXRlKHJlZmVyZW5jZS52YWx1ZSgpLCB2bS5lbnYpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBVcGRhdGVEeW5hbWljQXR0cmlidXRlT3Bjb2RlOwogIH0oVXBkYXRpbmdPcGNvZGUpOwoKICBmdW5jdGlvbiByZXNvbHZlQ29tcG9uZW50KHJlc29sdmVyLCBuYW1lLCBtZXRhKSB7CiAgICB2YXIgZGVmaW5pdGlvbiA9IHJlc29sdmVyLmxvb2t1cENvbXBvbmVudERlZmluaXRpb24obmFtZSwgbWV0YSk7CiAgICByZXR1cm4gZGVmaW5pdGlvbjsKICB9CgogIHZhciBDdXJyeUNvbXBvbmVudFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEN1cnJ5Q29tcG9uZW50UmVmZXJlbmNlKGlubmVyLCByZXNvbHZlciwgbWV0YSwgYXJncykgewogICAgICB0aGlzLmlubmVyID0gaW5uZXI7CiAgICAgIHRoaXMucmVzb2x2ZXIgPSByZXNvbHZlcjsKICAgICAgdGhpcy5tZXRhID0gbWV0YTsKICAgICAgdGhpcy5hcmdzID0gYXJnczsKICAgICAgdGhpcy50YWcgPSBpbm5lci50YWc7CiAgICAgIHRoaXMubGFzdFZhbHVlID0gbnVsbDsKICAgICAgdGhpcy5sYXN0RGVmaW5pdGlvbiA9IG51bGw7CiAgICB9CgogICAgdmFyIF9wcm90bzE2ID0gQ3VycnlDb21wb25lbnRSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzE2LnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHZhciBpbm5lciA9IHRoaXMuaW5uZXIsCiAgICAgICAgICBsYXN0VmFsdWUgPSB0aGlzLmxhc3RWYWx1ZTsKICAgICAgdmFyIHZhbHVlJCQxID0gaW5uZXIudmFsdWUoKTsKCiAgICAgIGlmICh2YWx1ZSQkMSA9PT0gbGFzdFZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHRoaXMubGFzdERlZmluaXRpb247CiAgICAgIH0KCiAgICAgIHZhciBkZWZpbml0aW9uID0gbnVsbDsKCiAgICAgIGlmIChpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKHZhbHVlJCQxKSkgewogICAgICAgIGRlZmluaXRpb24gPSB2YWx1ZSQkMTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUkJDEgPT09ICdzdHJpbmcnICYmIHZhbHVlJCQxKSB7CiAgICAgICAgdmFyIHJlc29sdmVyID0gdGhpcy5yZXNvbHZlciwKICAgICAgICAgICAgbWV0YSA9IHRoaXMubWV0YTsKICAgICAgICBkZWZpbml0aW9uID0gcmVzb2x2ZUNvbXBvbmVudChyZXNvbHZlciwgdmFsdWUkJDEsIG1ldGEpOwogICAgICB9CgogICAgICBkZWZpbml0aW9uID0gdGhpcy5jdXJyeShkZWZpbml0aW9uKTsKICAgICAgdGhpcy5sYXN0VmFsdWUgPSB2YWx1ZSQkMTsKICAgICAgdGhpcy5sYXN0RGVmaW5pdGlvbiA9IGRlZmluaXRpb247CiAgICAgIHJldHVybiBkZWZpbml0aW9uOwogICAgfTsKCiAgICBfcHJvdG8xNi5nZXQgPSBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBVTkRFRklORURfUkVGRVJFTkNFOwogICAgfTsKCiAgICBfcHJvdG8xNi5jdXJyeSA9IGZ1bmN0aW9uIGN1cnJ5KGRlZmluaXRpb24pIHsKICAgICAgdmFyIGFyZ3MgPSB0aGlzLmFyZ3M7CgogICAgICBpZiAoIWFyZ3MgJiYgaXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbihkZWZpbml0aW9uKSkgewogICAgICAgIHJldHVybiBkZWZpbml0aW9uOwogICAgICB9IGVsc2UgaWYgKCFkZWZpbml0aW9uKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyBDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbihkZWZpbml0aW9uLCBhcmdzKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gQ3VycnlDb21wb25lbnRSZWZlcmVuY2U7CiAgfSgpOwoKICB2YXIgQ2xhc3NMaXN0UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ2xhc3NMaXN0UmVmZXJlbmNlKGxpc3QpIHsKICAgICAgdGhpcy5saXN0ID0gbGlzdDsKICAgICAgdGhpcy50YWcgPSAoMCwgX3JlZmVyZW5jZTIuY29tYmluZVRhZ2dlZCkobGlzdCk7CiAgICAgIHRoaXMubGlzdCA9IGxpc3Q7CiAgICB9CgogICAgdmFyIF9wcm90bzE3ID0gQ2xhc3NMaXN0UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xNy52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICB2YXIgcmV0ID0gW107CiAgICAgIHZhciBsaXN0ID0gdGhpcy5saXN0OwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIHZhbHVlJCQxID0gbm9ybWFsaXplU3RyaW5nVmFsdWUobGlzdFtpXS52YWx1ZSgpKTsKICAgICAgICBpZiAodmFsdWUkJDEpIHJldC5wdXNoKHZhbHVlJCQxKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJldC5sZW5ndGggPT09IDAgPyBudWxsIDogcmV0LmpvaW4oJyAnKTsKICAgIH07CgogICAgcmV0dXJuIENsYXNzTGlzdFJlZmVyZW5jZTsKICB9KCk7CiAgLyoqCiAgICogQ29udmVydHMgYSBDb21wb25lbnRDYXBhYmlsaXRpZXMgb2JqZWN0IGludG8gYSAzMi1iaXQgaW50ZWdlciByZXByZXNlbnRhdGlvbi4KICAgKi8KCgogIGZ1bmN0aW9uIGNhcGFiaWxpdHlGbGFnc0Zyb20oY2FwYWJpbGl0aWVzKSB7CiAgICByZXR1cm4gMCB8IChjYXBhYmlsaXRpZXMuZHluYW1pY0xheW91dCA/IDEKICAgIC8qIER5bmFtaWNMYXlvdXQgKi8KICAgIDogMCkgfCAoY2FwYWJpbGl0aWVzLmR5bmFtaWNUYWcgPyAyCiAgICAvKiBEeW5hbWljVGFnICovCiAgICA6IDApIHwgKGNhcGFiaWxpdGllcy5wcmVwYXJlQXJncyA/IDQKICAgIC8qIFByZXBhcmVBcmdzICovCiAgICA6IDApIHwgKGNhcGFiaWxpdGllcy5jcmVhdGVBcmdzID8gOAogICAgLyogQ3JlYXRlQXJncyAqLwogICAgOiAwKSB8IChjYXBhYmlsaXRpZXMuYXR0cmlidXRlSG9vayA/IDE2CiAgICAvKiBBdHRyaWJ1dGVIb29rICovCiAgICA6IDApIHwgKGNhcGFiaWxpdGllcy5lbGVtZW50SG9vayA/IDMyCiAgICAvKiBFbGVtZW50SG9vayAqLwogICAgOiAwKSB8IChjYXBhYmlsaXRpZXMuZHluYW1pY1Njb3BlID8gNjQKICAgIC8qIER5bmFtaWNTY29wZSAqLwogICAgOiAwKSB8IChjYXBhYmlsaXRpZXMuY3JlYXRlQ2FsbGVyID8gMTI4CiAgICAvKiBDcmVhdGVDYWxsZXIgKi8KICAgIDogMCkgfCAoY2FwYWJpbGl0aWVzLnVwZGF0ZUhvb2sgPyAyNTYKICAgIC8qIFVwZGF0ZUhvb2sgKi8KICAgIDogMCkgfCAoY2FwYWJpbGl0aWVzLmNyZWF0ZUluc3RhbmNlID8gNTEyCiAgICAvKiBDcmVhdGVJbnN0YW5jZSAqLwogICAgOiAwKTsKICB9CgogIGZ1bmN0aW9uIGhhc0NhcGFiaWxpdHkoY2FwYWJpbGl0aWVzLCBjYXBhYmlsaXR5KSB7CiAgICByZXR1cm4gISEoY2FwYWJpbGl0aWVzICYgY2FwYWJpbGl0eSk7CiAgfQoKICBBUFBFTkRfT1BDT0RFUy5hZGQoNjkKICAvKiBJc0NvbXBvbmVudCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciByZWYgPSBzdGFjay5wb3AoKTsKICAgIHN0YWNrLnB1c2goSXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvblJlZmVyZW5jZS5jcmVhdGUocmVmKSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDcwCiAgLyogQ29udGVudFR5cGUgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgcmVmID0gc3RhY2sucGVlaygpOwogICAgc3RhY2sucHVzaChuZXcgQ29udGVudFR5cGVSZWZlcmVuY2UocmVmKSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDcxCiAgLyogQ3VycnlDb21wb25lbnQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjMwKSB7CiAgICB2YXIgX21ldGEgPSBfcmVmMzAub3AxOwogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgZGVmaW5pdGlvbiA9IHN0YWNrLnBvcCgpOwogICAgdmFyIGNhcHR1cmVkQXJncyA9IHN0YWNrLnBvcCgpOwogICAgdmFyIG1ldGEgPSB2bS5jb25zdGFudHMuZ2V0U2VyaWFsaXphYmxlKF9tZXRhKTsKICAgIHZhciByZXNvbHZlciA9IHZtLmNvbnN0YW50cy5yZXNvbHZlcjsKICAgIHZtLmxvYWRWYWx1ZShfdm0yLlJlZ2lzdGVyLnYwLCBuZXcgQ3VycnlDb21wb25lbnRSZWZlcmVuY2UoZGVmaW5pdGlvbiwgcmVzb2x2ZXIsIG1ldGEsIGNhcHR1cmVkQXJncykpOyAvLyBleHBlY3RTdGFja0NoYW5nZSh2bS5zdGFjaywgLWFyZ3MubGVuZ3RoIC0gMSwgJ0N1cnJ5Q29tcG9uZW50Jyk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDcyCiAgLyogUHVzaENvbXBvbmVudERlZmluaXRpb24gKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjMxKSB7CiAgICB2YXIgaGFuZGxlID0gX3JlZjMxLm9wMTsKICAgIHZhciBkZWZpbml0aW9uID0gdm0uY29uc3RhbnRzLnJlc29sdmVIYW5kbGUoaGFuZGxlKTsKICAgIHZhciBtYW5hZ2VyID0gZGVmaW5pdGlvbi5tYW5hZ2VyOwogICAgdmFyIGNhcGFiaWxpdGllcyA9IGNhcGFiaWxpdHlGbGFnc0Zyb20obWFuYWdlci5nZXRDYXBhYmlsaXRpZXMoZGVmaW5pdGlvbi5zdGF0ZSkpOwogICAgdmFyIGluc3RhbmNlID0gewogICAgICBkZWZpbml0aW9uOiBkZWZpbml0aW9uLAogICAgICBtYW5hZ2VyOiBtYW5hZ2VyLAogICAgICBjYXBhYmlsaXRpZXM6IGNhcGFiaWxpdGllcywKICAgICAgc3RhdGU6IG51bGwsCiAgICAgIGhhbmRsZTogbnVsbCwKICAgICAgdGFibGU6IG51bGwsCiAgICAgIGxvb2t1cDogbnVsbAogICAgfTsKICAgIHZtLnN0YWNrLnB1c2goaW5zdGFuY2UpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg3NQogIC8qIFJlc29sdmVEeW5hbWljQ29tcG9uZW50ICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYzMikgewogICAgdmFyIF9tZXRhID0gX3JlZjMyLm9wMTsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIGNvbXBvbmVudCA9IHN0YWNrLnBvcCgpLnZhbHVlKCk7CiAgICB2YXIgbWV0YSA9IHZtLmNvbnN0YW50cy5nZXRTZXJpYWxpemFibGUoX21ldGEpOwogICAgdm0ubG9hZFZhbHVlKF92bTIuUmVnaXN0ZXIudDEsIG51bGwpOyAvLyBDbGVhciB0aGUgdGVtcCByZWdpc3RlcgoKICAgIHZhciBkZWZpbml0aW9uOwoKICAgIGlmICh0eXBlb2YgY29tcG9uZW50ID09PSAnc3RyaW5nJykgewogICAgICB2YXIgcmVzb2x2ZXIgPSB2bS5jb25zdGFudHMucmVzb2x2ZXI7CiAgICAgIHZhciByZXNvbHZlZERlZmluaXRpb24gPSByZXNvbHZlQ29tcG9uZW50KHJlc29sdmVyLCBjb21wb25lbnQsIG1ldGEpOwogICAgICBkZWZpbml0aW9uID0gcmVzb2x2ZWREZWZpbml0aW9uOwogICAgfSBlbHNlIGlmIChpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGNvbXBvbmVudCkpIHsKICAgICAgZGVmaW5pdGlvbiA9IGNvbXBvbmVudDsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoKTsKICAgIH0KCiAgICBzdGFjay5wdXNoKGRlZmluaXRpb24pOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg3MwogIC8qIFB1c2hEeW5hbWljQ29tcG9uZW50SW5zdGFuY2UgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgZGVmaW5pdGlvbiA9IHN0YWNrLnBvcCgpOwogICAgdmFyIGNhcGFiaWxpdGllcywgbWFuYWdlcjsKCiAgICBpZiAoaXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbihkZWZpbml0aW9uKSkgewogICAgICBtYW5hZ2VyID0gY2FwYWJpbGl0aWVzID0gbnVsbDsKICAgIH0gZWxzZSB7CiAgICAgIG1hbmFnZXIgPSBkZWZpbml0aW9uLm1hbmFnZXI7CiAgICAgIGNhcGFiaWxpdGllcyA9IGNhcGFiaWxpdHlGbGFnc0Zyb20obWFuYWdlci5nZXRDYXBhYmlsaXRpZXMoZGVmaW5pdGlvbi5zdGF0ZSkpOwogICAgfQoKICAgIHN0YWNrLnB1c2goewogICAgICBkZWZpbml0aW9uOiBkZWZpbml0aW9uLAogICAgICBjYXBhYmlsaXRpZXM6IGNhcGFiaWxpdGllcywKICAgICAgbWFuYWdlcjogbWFuYWdlciwKICAgICAgc3RhdGU6IG51bGwsCiAgICAgIGhhbmRsZTogbnVsbCwKICAgICAgdGFibGU6IG51bGwKICAgIH0pOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg3NAogIC8qIFB1c2hDdXJyaWVkQ29tcG9uZW50ICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYzMykgewogICAgKDAsIF9lbWJlckJhYmVsLm9iamVjdERlc3RydWN0dXJpbmdFbXB0eSkoX3JlZjMzKTsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIGNvbXBvbmVudCA9IHN0YWNrLnBvcCgpLnZhbHVlKCk7CiAgICB2YXIgZGVmaW5pdGlvbjsKCiAgICBpZiAoaXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbihjb21wb25lbnQpKSB7CiAgICAgIGRlZmluaXRpb24gPSBjb21wb25lbnQ7CiAgICB9IGVsc2UgewogICAgICB0aHJvdyAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCk7CiAgICB9CgogICAgc3RhY2sucHVzaChkZWZpbml0aW9uKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNzYKICAvKiBQdXNoQXJncyAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMzQpIHsKICAgIHZhciBfbmFtZXMgPSBfcmVmMzQub3AxLAogICAgICAgIGZsYWdzID0gX3JlZjM0Lm9wMjsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIG5hbWVzID0gdm0uY29uc3RhbnRzLmdldFN0cmluZ0FycmF5KF9uYW1lcyk7CiAgICB2YXIgcG9zaXRpb25hbENvdW50ID0gZmxhZ3MgPj4gNDsKICAgIHZhciBzeW50aGV0aWMgPSBmbGFncyAmIDg7CiAgICB2YXIgYmxvY2tOYW1lcyA9IFtdOwogICAgaWYgKGZsYWdzICYgNCkgYmxvY2tOYW1lcy5wdXNoKCdtYWluJyk7CiAgICBpZiAoZmxhZ3MgJiAyKSBibG9ja05hbWVzLnB1c2goJ2Vsc2UnKTsKICAgIGlmIChmbGFncyAmIDEpIGJsb2NrTmFtZXMucHVzaCgnYXR0cnMnKTsKICAgIHZtLmFyZ3Muc2V0dXAoc3RhY2ssIG5hbWVzLCBibG9ja05hbWVzLCBwb3NpdGlvbmFsQ291bnQsICEhc3ludGhldGljKTsKICAgIHN0YWNrLnB1c2godm0uYXJncyk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDc3CiAgLyogUHVzaEVtcHR5QXJncyAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHN0YWNrLnB1c2godm0uYXJncy5lbXB0eShzdGFjaykpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4MAogIC8qIENhcHR1cmVBcmdzICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIGFyZ3MgPSBzdGFjay5wb3AoKTsKICAgIHZhciBjYXB0dXJlZEFyZ3MgPSBhcmdzLmNhcHR1cmUoKTsKICAgIHN0YWNrLnB1c2goY2FwdHVyZWRBcmdzKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNzkKICAvKiBQcmVwYXJlQXJncyAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMzUpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmMzUub3AxOwogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgaW5zdGFuY2UgPSB2bS5mZXRjaFZhbHVlKF9zdGF0ZSk7CiAgICB2YXIgYXJncyA9IHN0YWNrLnBvcCgpOwogICAgdmFyIGRlZmluaXRpb24gPSBpbnN0YW5jZS5kZWZpbml0aW9uOwoKICAgIGlmIChpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGRlZmluaXRpb24pKSB7CiAgICAgIGRlZmluaXRpb24gPSByZXNvbHZlQ3VycmllZENvbXBvbmVudERlZmluaXRpb24oaW5zdGFuY2UsIGRlZmluaXRpb24sIGFyZ3MpOwogICAgfQoKICAgIHZhciBfZGVmaW5pdGlvbjIgPSBkZWZpbml0aW9uLAogICAgICAgIG1hbmFnZXIgPSBfZGVmaW5pdGlvbjIubWFuYWdlciwKICAgICAgICBzdGF0ZSA9IF9kZWZpbml0aW9uMi5zdGF0ZTsKICAgIHZhciBjYXBhYmlsaXRpZXMgPSBpbnN0YW5jZS5jYXBhYmlsaXRpZXM7CgogICAgaWYgKGhhc0NhcGFiaWxpdHkoY2FwYWJpbGl0aWVzLCA0CiAgICAvKiBQcmVwYXJlQXJncyAqLwogICAgKSAhPT0gdHJ1ZSkgewogICAgICBzdGFjay5wdXNoKGFyZ3MpOwogICAgICByZXR1cm47CiAgICB9CgogICAgdmFyIGJsb2NrcyA9IGFyZ3MuYmxvY2tzLnZhbHVlczsKICAgIHZhciBibG9ja05hbWVzID0gYXJncy5ibG9ja3MubmFtZXM7CiAgICB2YXIgcHJlcGFyZWRBcmdzID0gbWFuYWdlci5wcmVwYXJlQXJncyhzdGF0ZSwgYXJncyk7CgogICAgaWYgKHByZXBhcmVkQXJncykgewogICAgICBhcmdzLmNsZWFyKCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2Nrcy5sZW5ndGg7IGkrKykgewogICAgICAgIHN0YWNrLnB1c2goYmxvY2tzW2ldKTsKICAgICAgfQoKICAgICAgdmFyIHBvc2l0aW9uYWwgPSBwcmVwYXJlZEFyZ3MucG9zaXRpb25hbCwKICAgICAgICAgIG5hbWVkID0gcHJlcGFyZWRBcmdzLm5hbWVkOwogICAgICB2YXIgcG9zaXRpb25hbENvdW50ID0gcG9zaXRpb25hbC5sZW5ndGg7CgogICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgcG9zaXRpb25hbENvdW50OyBfaSsrKSB7CiAgICAgICAgc3RhY2sucHVzaChwb3NpdGlvbmFsW19pXSk7CiAgICAgIH0KCiAgICAgIHZhciBuYW1lcyA9IE9iamVjdC5rZXlzKG5hbWVkKTsKCiAgICAgIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IG5hbWVzLmxlbmd0aDsgX2kyKyspIHsKICAgICAgICBzdGFjay5wdXNoKG5hbWVkW25hbWVzW19pMl1dKTsKICAgICAgfQoKICAgICAgYXJncy5zZXR1cChzdGFjaywgbmFtZXMsIGJsb2NrTmFtZXMsIHBvc2l0aW9uYWxDb3VudCwgdHJ1ZSk7CiAgICB9CgogICAgc3RhY2sucHVzaChhcmdzKTsKICB9KTsKCiAgZnVuY3Rpb24gcmVzb2x2ZUN1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGluc3RhbmNlLCBkZWZpbml0aW9uLCBhcmdzKSB7CiAgICB2YXIgdW53cmFwcGVkRGVmaW5pdGlvbiA9IGluc3RhbmNlLmRlZmluaXRpb24gPSBkZWZpbml0aW9uLnVud3JhcChhcmdzKTsKICAgIHZhciBtYW5hZ2VyID0gdW53cmFwcGVkRGVmaW5pdGlvbi5tYW5hZ2VyLAogICAgICAgIHN0YXRlID0gdW53cmFwcGVkRGVmaW5pdGlvbi5zdGF0ZTsKICAgIGluc3RhbmNlLm1hbmFnZXIgPSBtYW5hZ2VyOwogICAgaW5zdGFuY2UuY2FwYWJpbGl0aWVzID0gY2FwYWJpbGl0eUZsYWdzRnJvbShtYW5hZ2VyLmdldENhcGFiaWxpdGllcyhzdGF0ZSkpOwogICAgcmV0dXJuIHVud3JhcHBlZERlZmluaXRpb247CiAgfQoKICBBUFBFTkRfT1BDT0RFUy5hZGQoODEKICAvKiBDcmVhdGVDb21wb25lbnQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjM2KSB7CiAgICB2YXIgZmxhZ3MgPSBfcmVmMzYub3AxLAogICAgICAgIF9zdGF0ZSA9IF9yZWYzNi5vcDI7CiAgICB2YXIgaW5zdGFuY2UgPSB2bS5mZXRjaFZhbHVlKF9zdGF0ZSk7CiAgICB2YXIgZGVmaW5pdGlvbiA9IGluc3RhbmNlLmRlZmluaXRpb24sCiAgICAgICAgbWFuYWdlciA9IGluc3RhbmNlLm1hbmFnZXI7CiAgICB2YXIgY2FwYWJpbGl0aWVzID0gaW5zdGFuY2UuY2FwYWJpbGl0aWVzID0gY2FwYWJpbGl0eUZsYWdzRnJvbShtYW5hZ2VyLmdldENhcGFiaWxpdGllcyhkZWZpbml0aW9uLnN0YXRlKSk7CiAgICB2YXIgZHluYW1pY1Njb3BlID0gbnVsbDsKCiAgICBpZiAoaGFzQ2FwYWJpbGl0eShjYXBhYmlsaXRpZXMsIDY0CiAgICAvKiBEeW5hbWljU2NvcGUgKi8KICAgICkpIHsKICAgICAgZHluYW1pY1Njb3BlID0gdm0uZHluYW1pY1Njb3BlKCk7CiAgICB9CgogICAgdmFyIGhhc0RlZmF1bHRCbG9jayA9IGZsYWdzICYgMTsKICAgIHZhciBhcmdzID0gbnVsbDsKCiAgICBpZiAoaGFzQ2FwYWJpbGl0eShjYXBhYmlsaXRpZXMsIDgKICAgIC8qIENyZWF0ZUFyZ3MgKi8KICAgICkpIHsKICAgICAgYXJncyA9IHZtLnN0YWNrLnBlZWsoKTsKICAgIH0KCiAgICB2YXIgc2VsZiA9IG51bGw7CgogICAgaWYgKGhhc0NhcGFiaWxpdHkoY2FwYWJpbGl0aWVzLCAxMjgKICAgIC8qIENyZWF0ZUNhbGxlciAqLwogICAgKSkgewogICAgICBzZWxmID0gdm0uZ2V0U2VsZigpOwogICAgfQoKICAgIHZhciBzdGF0ZSA9IG1hbmFnZXIuY3JlYXRlKHZtLmVudiwgZGVmaW5pdGlvbi5zdGF0ZSwgYXJncywgZHluYW1pY1Njb3BlLCBzZWxmLCAhIWhhc0RlZmF1bHRCbG9jayk7IC8vIFdlIHdhbnQgdG8gcmV1c2UgdGhlIGBzdGF0ZWAgUE9KTyBoZXJlLCBiZWNhdXNlIHdlIGtub3cgdGhhdCB0aGUgb3Bjb2RlcwogICAgLy8gb25seSB0cmFuc2l0aW9uIGF0IGV4YWN0bHkgb25lIHBsYWNlLgoKICAgIGluc3RhbmNlLnN0YXRlID0gc3RhdGU7CiAgICB2YXIgdGFnID0gbWFuYWdlci5nZXRUYWcoc3RhdGUpOwoKICAgIGlmIChoYXNDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgMjU2CiAgICAvKiBVcGRhdGVIb29rICovCiAgICApICYmICEoMCwgX3JlZmVyZW5jZTIuaXNDb25zdFRhZykodGFnKSkgewogICAgICB2bS51cGRhdGVXaXRoKG5ldyBVcGRhdGVDb21wb25lbnRPcGNvZGUodGFnLCBzdGF0ZSwgbWFuYWdlciwgZHluYW1pY1Njb3BlKSk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDgyCiAgLyogUmVnaXN0ZXJDb21wb25lbnREZXN0cnVjdG9yICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYzNykgewogICAgdmFyIF9zdGF0ZSA9IF9yZWYzNy5vcDE7CgogICAgdmFyIF92bSRmZXRjaFZhbHVlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpLAogICAgICAgIG1hbmFnZXIgPSBfdm0kZmV0Y2hWYWx1ZS5tYW5hZ2VyLAogICAgICAgIHN0YXRlID0gX3ZtJGZldGNoVmFsdWUuc3RhdGU7CgogICAgdmFyIGRlc3RydWN0b3IgPSBtYW5hZ2VyLmdldERlc3RydWN0b3Ioc3RhdGUpOwogICAgaWYgKGRlc3RydWN0b3IpIHZtLm5ld0Rlc3Ryb3lhYmxlKGRlc3RydWN0b3IpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg5MQogIC8qIEJlZ2luQ29tcG9uZW50VHJhbnNhY3Rpb24gKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdm0uYmVnaW5DYWNoZUdyb3VwKCk7CiAgICB2bS5lbGVtZW50cygpLnB1c2hTaW1wbGVCbG9jaygpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4MwogIC8qIFB1dENvbXBvbmVudE9wZXJhdGlvbnMgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdm0ubG9hZFZhbHVlKF92bTIuUmVnaXN0ZXIudDAsIG5ldyBDb21wb25lbnRFbGVtZW50T3BlcmF0aW9ucygpKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMzcKICAvKiBDb21wb25lbnRBdHRyICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYzOCkgewogICAgdmFyIF9uYW1lID0gX3JlZjM4Lm9wMSwKICAgICAgICB0cnVzdGluZyA9IF9yZWYzOC5vcDIsCiAgICAgICAgX25hbWVzcGFjZSA9IF9yZWYzOC5vcDM7CiAgICB2YXIgbmFtZSA9IHZtLmNvbnN0YW50cy5nZXRTdHJpbmcoX25hbWUpOwogICAgdmFyIHJlZmVyZW5jZSA9IHZtLnN0YWNrLnBvcCgpOwogICAgdmFyIG5hbWVzcGFjZSA9IF9uYW1lc3BhY2UgPyB2bS5jb25zdGFudHMuZ2V0U3RyaW5nKF9uYW1lc3BhY2UpIDogbnVsbDsKICAgIHZtLmZldGNoVmFsdWUoX3ZtMi5SZWdpc3Rlci50MCkuc2V0QXR0cmlidXRlKG5hbWUsIHJlZmVyZW5jZSwgISF0cnVzdGluZywgbmFtZXNwYWNlKTsKICB9KTsKCiAgdmFyIENvbXBvbmVudEVsZW1lbnRPcGVyYXRpb25zID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ29tcG9uZW50RWxlbWVudE9wZXJhdGlvbnMoKSB7CiAgICAgIHRoaXMuYXR0cmlidXRlcyA9ICgwLCBfdXRpbC5kaWN0KSgpOwogICAgICB0aGlzLmNsYXNzZXMgPSBbXTsKICAgICAgdGhpcy5tb2RpZmllcnMgPSBbXTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTggPSBDb21wb25lbnRFbGVtZW50T3BlcmF0aW9ucy5wcm90b3R5cGU7CgogICAgX3Byb3RvMTguc2V0QXR0cmlidXRlID0gZnVuY3Rpb24gc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlJCQxLCB0cnVzdGluZywgbmFtZXNwYWNlKSB7CiAgICAgIHZhciBkZWZlcnJlZCA9IHsKICAgICAgICB2YWx1ZTogdmFsdWUkJDEsCiAgICAgICAgbmFtZXNwYWNlOiBuYW1lc3BhY2UsCiAgICAgICAgdHJ1c3Rpbmc6IHRydXN0aW5nCiAgICAgIH07CgogICAgICBpZiAobmFtZSA9PT0gJ2NsYXNzJykgewogICAgICAgIHRoaXMuY2xhc3Nlcy5wdXNoKHZhbHVlJCQxKTsKICAgICAgfQoKICAgICAgdGhpcy5hdHRyaWJ1dGVzW25hbWVdID0gZGVmZXJyZWQ7CiAgICB9OwoKICAgIF9wcm90bzE4LmFkZE1vZGlmaWVyID0gZnVuY3Rpb24gYWRkTW9kaWZpZXIobWFuYWdlciwgbW9kaWZpZXIpIHsKICAgICAgdGhpcy5tb2RpZmllcnMucHVzaChbbWFuYWdlciwgbW9kaWZpZXJdKTsKICAgIH07CgogICAgX3Byb3RvMTguZmx1c2ggPSBmdW5jdGlvbiBmbHVzaCh2bSkgewogICAgICBmb3IgKHZhciBuYW1lIGluIHRoaXMuYXR0cmlidXRlcykgewogICAgICAgIHZhciBhdHRyID0gdGhpcy5hdHRyaWJ1dGVzW25hbWVdOwogICAgICAgIHZhciByZWZlcmVuY2UgPSBhdHRyLnZhbHVlLAogICAgICAgICAgICBuYW1lc3BhY2UgPSBhdHRyLm5hbWVzcGFjZSwKICAgICAgICAgICAgdHJ1c3RpbmcgPSBhdHRyLnRydXN0aW5nOwoKICAgICAgICBpZiAobmFtZSA9PT0gJ2NsYXNzJykgewogICAgICAgICAgcmVmZXJlbmNlID0gbmV3IENsYXNzTGlzdFJlZmVyZW5jZSh0aGlzLmNsYXNzZXMpOwogICAgICAgIH0KCiAgICAgICAgaWYgKG5hbWUgPT09ICd0eXBlJykgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICB2YXIgYXR0cmlidXRlID0gdm0uZWxlbWVudHMoKS5zZXREeW5hbWljQXR0cmlidXRlKG5hbWUsIHJlZmVyZW5jZS52YWx1ZSgpLCB0cnVzdGluZywgbmFtZXNwYWNlKTsKCiAgICAgICAgaWYgKCEoMCwgX3JlZmVyZW5jZTIuaXNDb25zdCkocmVmZXJlbmNlKSkgewogICAgICAgICAgdm0udXBkYXRlV2l0aChuZXcgVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZShyZWZlcmVuY2UsIGF0dHJpYnV0ZSkpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKCd0eXBlJyBpbiB0aGlzLmF0dHJpYnV0ZXMpIHsKICAgICAgICB2YXIgdHlwZSA9IHRoaXMuYXR0cmlidXRlcy50eXBlOwogICAgICAgIHZhciBfcmVmZXJlbmNlID0gdHlwZS52YWx1ZSwKICAgICAgICAgICAgX25hbWVzcGFjZTIgPSB0eXBlLm5hbWVzcGFjZSwKICAgICAgICAgICAgX3RydXN0aW5nID0gdHlwZS50cnVzdGluZzsKCiAgICAgICAgdmFyIF9hdHRyaWJ1dGUgPSB2bS5lbGVtZW50cygpLnNldER5bmFtaWNBdHRyaWJ1dGUoJ3R5cGUnLCBfcmVmZXJlbmNlLnZhbHVlKCksIF90cnVzdGluZywgX25hbWVzcGFjZTIpOwoKICAgICAgICBpZiAoISgwLCBfcmVmZXJlbmNlMi5pc0NvbnN0KShfcmVmZXJlbmNlKSkgewogICAgICAgICAgdm0udXBkYXRlV2l0aChuZXcgVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZShfcmVmZXJlbmNlLCBfYXR0cmlidXRlKSk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5tb2RpZmllcnM7CiAgICB9OwoKICAgIHJldHVybiBDb21wb25lbnRFbGVtZW50T3BlcmF0aW9uczsKICB9KCk7CgogIEFQUEVORF9PUENPREVTLmFkZCg5MwogIC8qIERpZENyZWF0ZUVsZW1lbnQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjM5KSB7CiAgICB2YXIgX3N0YXRlID0gX3JlZjM5Lm9wMTsKCiAgICB2YXIgX3ZtJGZldGNoVmFsdWUyID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpLAogICAgICAgIGRlZmluaXRpb24gPSBfdm0kZmV0Y2hWYWx1ZTIuZGVmaW5pdGlvbiwKICAgICAgICBzdGF0ZSA9IF92bSRmZXRjaFZhbHVlMi5zdGF0ZTsKCiAgICB2YXIgbWFuYWdlciA9IGRlZmluaXRpb24ubWFuYWdlcjsKICAgIHZhciBvcGVyYXRpb25zID0gdm0uZmV0Y2hWYWx1ZShfdm0yLlJlZ2lzdGVyLnQwKTsKICAgIHZhciBhY3Rpb24gPSAnRGlkQ3JlYXRlRWxlbWVudE9wY29kZSNldmFsdWF0ZSc7CiAgICBtYW5hZ2VyLmRpZENyZWF0ZUVsZW1lbnQoc3RhdGUsIHZtLmVsZW1lbnRzKCkuZXhwZWN0Q29uc3RydWN0aW5nKGFjdGlvbiksIG9wZXJhdGlvbnMpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4NAogIC8qIEdldENvbXBvbmVudFNlbGYgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjQwKSB7CiAgICB2YXIgX3N0YXRlID0gX3JlZjQwLm9wMTsKCiAgICB2YXIgX3ZtJGZldGNoVmFsdWUzID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpLAogICAgICAgIGRlZmluaXRpb24gPSBfdm0kZmV0Y2hWYWx1ZTMuZGVmaW5pdGlvbiwKICAgICAgICBzdGF0ZSA9IF92bSRmZXRjaFZhbHVlMy5zdGF0ZTsKCiAgICB2YXIgbWFuYWdlciA9IGRlZmluaXRpb24ubWFuYWdlcjsKICAgIHZtLnN0YWNrLnB1c2gobWFuYWdlci5nZXRTZWxmKHN0YXRlKSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDg1CiAgLyogR2V0Q29tcG9uZW50VGFnTmFtZSAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNDEpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNDEub3AxOwoKICAgIHZhciBfdm0kZmV0Y2hWYWx1ZTQgPSB2bS5mZXRjaFZhbHVlKF9zdGF0ZSksCiAgICAgICAgZGVmaW5pdGlvbiA9IF92bSRmZXRjaFZhbHVlNC5kZWZpbml0aW9uLAogICAgICAgIHN0YXRlID0gX3ZtJGZldGNoVmFsdWU0LnN0YXRlOwoKICAgIHZhciBtYW5hZ2VyID0gZGVmaW5pdGlvbi5tYW5hZ2VyOwogICAgdm0uc3RhY2sucHVzaChtYW5hZ2VyLmdldFRhZ05hbWUoc3RhdGUpKTsKICB9KTsgLy8gRHluYW1pYyBJbnZvY2F0aW9uIE9ubHkKCiAgQVBQRU5EX09QQ09ERVMuYWRkKDg2CiAgLyogR2V0Q29tcG9uZW50TGF5b3V0ICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY0MikgewogICAgdmFyIF9zdGF0ZSA9IF9yZWY0Mi5vcDE7CiAgICB2YXIgaW5zdGFuY2UgPSB2bS5mZXRjaFZhbHVlKF9zdGF0ZSk7CiAgICB2YXIgbWFuYWdlciA9IGluc3RhbmNlLm1hbmFnZXIsCiAgICAgICAgZGVmaW5pdGlvbiA9IGluc3RhbmNlLmRlZmluaXRpb247CiAgICB2YXIgcmVzb2x2ZXIgPSB2bS5jb25zdGFudHMucmVzb2x2ZXIsCiAgICAgICAgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciBpbnN0YW5jZVN0YXRlID0gaW5zdGFuY2Uuc3RhdGUsCiAgICAgICAgY2FwYWJpbGl0aWVzID0gaW5zdGFuY2UuY2FwYWJpbGl0aWVzOwogICAgdmFyIGRlZmluaXRpb25TdGF0ZSA9IGRlZmluaXRpb24uc3RhdGU7CiAgICB2YXIgaW52b2tlOwoKICAgIGlmIChoYXNTdGF0aWNMYXlvdXRDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgbWFuYWdlcikpIHsKICAgICAgaW52b2tlID0gbWFuYWdlci5nZXRMYXlvdXQoZGVmaW5pdGlvblN0YXRlLCByZXNvbHZlcik7CiAgICB9IGVsc2UgaWYgKGhhc0R5bmFtaWNMYXlvdXRDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgbWFuYWdlcikpIHsKICAgICAgaW52b2tlID0gbWFuYWdlci5nZXREeW5hbWljTGF5b3V0KGluc3RhbmNlU3RhdGUsIHJlc29sdmVyKTsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoKTsKICAgIH0KCiAgICBzdGFjay5wdXNoKGludm9rZS5zeW1ib2xUYWJsZSk7CiAgICBzdGFjay5wdXNoKGludm9rZS5oYW5kbGUpOwogIH0pOwoKICBmdW5jdGlvbiBoYXNTdGF0aWNMYXlvdXRDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgX21hbmFnZXIpIHsKICAgIHJldHVybiBoYXNDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgMQogICAgLyogRHluYW1pY0xheW91dCAqLwogICAgKSA9PT0gZmFsc2U7CiAgfQoKICBmdW5jdGlvbiBoYXNEeW5hbWljTGF5b3V0Q2FwYWJpbGl0eShjYXBhYmlsaXRpZXMsIF9tYW5hZ2VyKSB7CiAgICByZXR1cm4gaGFzQ2FwYWJpbGl0eShjYXBhYmlsaXRpZXMsIDEKICAgIC8qIER5bmFtaWNMYXlvdXQgKi8KICAgICkgPT09IHRydWU7CiAgfQoKICBBUFBFTkRfT1BDT0RFUy5hZGQoNjgKICAvKiBNYWluICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY0MykgewogICAgdmFyIHJlZ2lzdGVyID0gX3JlZjQzLm9wMTsKICAgIHZhciBkZWZpbml0aW9uID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgaW52b2NhdGlvbiA9IHZtLnN0YWNrLnBvcCgpOwogICAgdmFyIG1hbmFnZXIgPSBkZWZpbml0aW9uLm1hbmFnZXI7CiAgICB2YXIgY2FwYWJpbGl0aWVzID0gY2FwYWJpbGl0eUZsYWdzRnJvbShtYW5hZ2VyLmdldENhcGFiaWxpdGllcyhkZWZpbml0aW9uLnN0YXRlKSk7CiAgICB2YXIgc3RhdGUgPSB7CiAgICAgIGRlZmluaXRpb246IGRlZmluaXRpb24sCiAgICAgIG1hbmFnZXI6IG1hbmFnZXIsCiAgICAgIGNhcGFiaWxpdGllczogY2FwYWJpbGl0aWVzLAogICAgICBzdGF0ZTogbnVsbCwKICAgICAgaGFuZGxlOiBpbnZvY2F0aW9uLmhhbmRsZSwKICAgICAgdGFibGU6IGludm9jYXRpb24uc3ltYm9sVGFibGUsCiAgICAgIGxvb2t1cDogbnVsbAogICAgfTsKICAgIHZtLmxvYWRWYWx1ZShyZWdpc3Rlciwgc3RhdGUpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4OQogIC8qIFBvcHVsYXRlTGF5b3V0ICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY0NCkgewogICAgdmFyIF9zdGF0ZSA9IF9yZWY0NC5vcDE7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciBoYW5kbGUgPSBzdGFjay5wb3AoKTsKICAgIHZhciB0YWJsZSA9IHN0YWNrLnBvcCgpOwogICAgdmFyIHN0YXRlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpOwogICAgc3RhdGUuaGFuZGxlID0gaGFuZGxlOwogICAgc3RhdGUudGFibGUgPSB0YWJsZTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMjEKICAvKiBWaXJ0dWFsUm9vdFNjb3BlICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY0NSkgewogICAgdmFyIF9zdGF0ZSA9IF9yZWY0NS5vcDE7CiAgICB2YXIgc3ltYm9scyA9IHZtLmZldGNoVmFsdWUoX3N0YXRlKS50YWJsZS5zeW1ib2xzOwogICAgdm0ucHVzaFJvb3RTY29wZShzeW1ib2xzLmxlbmd0aCArIDEsIHRydWUpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4NwogIC8qIFNldHVwRm9yRXZhbCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNDYpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNDYub3AxOwogICAgdmFyIHN0YXRlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpOwoKICAgIGlmIChzdGF0ZS50YWJsZS5oYXNFdmFsKSB7CiAgICAgIHZhciBsb29rdXAgPSBzdGF0ZS5sb29rdXAgPSAoMCwgX3V0aWwuZGljdCkoKTsKICAgICAgdm0uc2NvcGUoKS5iaW5kRXZhbFNjb3BlKGxvb2t1cCk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDIKICAvKiBTZXROYW1lZFZhcmlhYmxlcyAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNDcpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNDcub3AxOwogICAgdmFyIHN0YXRlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpOwogICAgdmFyIHNjb3BlID0gdm0uc2NvcGUoKTsKICAgIHZhciBhcmdzID0gdm0uc3RhY2sucGVlaygpOwogICAgdmFyIGNhbGxlck5hbWVzID0gYXJncy5uYW1lZC5hdE5hbWVzOwoKICAgIGZvciAodmFyIGkgPSBjYWxsZXJOYW1lcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICB2YXIgYXROYW1lID0gY2FsbGVyTmFtZXNbaV07CiAgICAgIHZhciBzeW1ib2wgPSBzdGF0ZS50YWJsZS5zeW1ib2xzLmluZGV4T2YoY2FsbGVyTmFtZXNbaV0pOwogICAgICB2YXIgdmFsdWUkJDEgPSBhcmdzLm5hbWVkLmdldChhdE5hbWUsIGZhbHNlKTsKICAgICAgaWYgKHN5bWJvbCAhPT0gLTEpIHNjb3BlLmJpbmRTeW1ib2woc3ltYm9sICsgMSwgdmFsdWUkJDEpOwogICAgICBpZiAoc3RhdGUubG9va3VwKSBzdGF0ZS5sb29rdXBbYXROYW1lXSA9IHZhbHVlJCQxOwogICAgfQogIH0pOwoKICBmdW5jdGlvbiBiaW5kQmxvY2soc3ltYm9sTmFtZSwgYmxvY2tOYW1lLCBzdGF0ZSwgYmxvY2tzLCB2bSkgewogICAgdmFyIHN5bWJvbCA9IHN0YXRlLnRhYmxlLnN5bWJvbHMuaW5kZXhPZihzeW1ib2xOYW1lKTsKICAgIHZhciBibG9jayA9IGJsb2Nrcy5nZXQoYmxvY2tOYW1lKTsKCiAgICBpZiAoc3ltYm9sICE9PSAtMSkgewogICAgICB2bS5zY29wZSgpLmJpbmRCbG9jayhzeW1ib2wgKyAxLCBibG9jayk7CiAgICB9CgogICAgaWYgKHN0YXRlLmxvb2t1cCkgc3RhdGUubG9va3VwW3N5bWJvbE5hbWVdID0gYmxvY2s7CiAgfQoKICBBUFBFTkRfT1BDT0RFUy5hZGQoMwogIC8qIFNldEJsb2NrcyAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNDgpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNDgub3AxOwogICAgdmFyIHN0YXRlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpOwoKICAgIHZhciBfdm0kc3RhY2skcGVlayA9IHZtLnN0YWNrLnBlZWsoKSwKICAgICAgICBibG9ja3MgPSBfdm0kc3RhY2skcGVlay5ibG9ja3M7CgogICAgYmluZEJsb2NrKCcmYXR0cnMnLCAnYXR0cnMnLCBzdGF0ZSwgYmxvY2tzLCB2bSk7CiAgICBiaW5kQmxvY2soJyZpbnZlcnNlJywgJ2Vsc2UnLCBzdGF0ZSwgYmxvY2tzLCB2bSk7CiAgICBiaW5kQmxvY2soJyZkZWZhdWx0JywgJ21haW4nLCBzdGF0ZSwgYmxvY2tzLCB2bSk7CiAgfSk7IC8vIER5bmFtaWMgSW52b2NhdGlvbiBPbmx5CgogIEFQUEVORF9PUENPREVTLmFkZCg5MAogIC8qIEludm9rZUNvbXBvbmVudExheW91dCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNDkpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNDkub3AxOwogICAgdmFyIHN0YXRlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpOwogICAgdm0uY2FsbChzdGF0ZS5oYW5kbGUpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg5NAogIC8qIERpZFJlbmRlckxheW91dCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNTApIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNTAub3AxOwoKICAgIHZhciBfdm0kZmV0Y2hWYWx1ZTUgPSB2bS5mZXRjaFZhbHVlKF9zdGF0ZSksCiAgICAgICAgbWFuYWdlciA9IF92bSRmZXRjaFZhbHVlNS5tYW5hZ2VyLAogICAgICAgIHN0YXRlID0gX3ZtJGZldGNoVmFsdWU1LnN0YXRlOwoKICAgIHZhciBib3VuZHMgPSB2bS5lbGVtZW50cygpLnBvcEJsb2NrKCk7CiAgICB2YXIgbWdyID0gbWFuYWdlcjsKICAgIG1nci5kaWRSZW5kZXJMYXlvdXQoc3RhdGUsIGJvdW5kcyk7CiAgICB2bS5lbnYuZGlkQ3JlYXRlKHN0YXRlLCBtYW5hZ2VyKTsKICAgIHZtLnVwZGF0ZVdpdGgobmV3IERpZFVwZGF0ZUxheW91dE9wY29kZShtYW5hZ2VyLCBzdGF0ZSwgYm91bmRzKSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDkyCiAgLyogQ29tbWl0Q29tcG9uZW50VHJhbnNhY3Rpb24gKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdm0uY29tbWl0Q2FjaGVHcm91cCgpOwogIH0pOwoKICB2YXIgVXBkYXRlQ29tcG9uZW50T3Bjb2RlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9VcGRhdGluZ09wY29kZTcpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShVcGRhdGVDb21wb25lbnRPcGNvZGUsIF9VcGRhdGluZ09wY29kZTcpOwoKICAgIGZ1bmN0aW9uIFVwZGF0ZUNvbXBvbmVudE9wY29kZSh0YWcsIGNvbXBvbmVudCwgbWFuYWdlciwgZHluYW1pY1Njb3BlKSB7CiAgICAgIHZhciBfdGhpczEwOwoKICAgICAgX3RoaXMxMCA9IF9VcGRhdGluZ09wY29kZTcuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczEwLnRhZyA9IHRhZzsKICAgICAgX3RoaXMxMC5jb21wb25lbnQgPSBjb21wb25lbnQ7CiAgICAgIF90aGlzMTAubWFuYWdlciA9IG1hbmFnZXI7CiAgICAgIF90aGlzMTAuZHluYW1pY1Njb3BlID0gZHluYW1pY1Njb3BlOwogICAgICBfdGhpczEwLnR5cGUgPSAndXBkYXRlLWNvbXBvbmVudCc7CiAgICAgIHJldHVybiBfdGhpczEwOwogICAgfQoKICAgIHZhciBfcHJvdG8xOSA9IFVwZGF0ZUNvbXBvbmVudE9wY29kZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMTkuZXZhbHVhdGUgPSBmdW5jdGlvbiBldmFsdWF0ZShfdm0pIHsKICAgICAgdmFyIGNvbXBvbmVudCA9IHRoaXMuY29tcG9uZW50LAogICAgICAgICAgbWFuYWdlciA9IHRoaXMubWFuYWdlciwKICAgICAgICAgIGR5bmFtaWNTY29wZSA9IHRoaXMuZHluYW1pY1Njb3BlOwogICAgICBtYW5hZ2VyLnVwZGF0ZShjb21wb25lbnQsIGR5bmFtaWNTY29wZSk7CiAgICB9OwoKICAgIHJldHVybiBVcGRhdGVDb21wb25lbnRPcGNvZGU7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBEaWRVcGRhdGVMYXlvdXRPcGNvZGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1VwZGF0aW5nT3Bjb2RlOCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKERpZFVwZGF0ZUxheW91dE9wY29kZSwgX1VwZGF0aW5nT3Bjb2RlOCk7CgogICAgZnVuY3Rpb24gRGlkVXBkYXRlTGF5b3V0T3Bjb2RlKG1hbmFnZXIsIGNvbXBvbmVudCwgYm91bmRzKSB7CiAgICAgIHZhciBfdGhpczExOwoKICAgICAgX3RoaXMxMSA9IF9VcGRhdGluZ09wY29kZTguY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczExLm1hbmFnZXIgPSBtYW5hZ2VyOwogICAgICBfdGhpczExLmNvbXBvbmVudCA9IGNvbXBvbmVudDsKICAgICAgX3RoaXMxMS5ib3VuZHMgPSBib3VuZHM7CiAgICAgIF90aGlzMTEudHlwZSA9ICdkaWQtdXBkYXRlLWxheW91dCc7CiAgICAgIF90aGlzMTEudGFnID0gX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHOwogICAgICByZXR1cm4gX3RoaXMxMTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMjAgPSBEaWRVcGRhdGVMYXlvdXRPcGNvZGUucHJvdG90eXBlOwoKICAgIF9wcm90bzIwLmV2YWx1YXRlID0gZnVuY3Rpb24gZXZhbHVhdGUodm0pIHsKICAgICAgdmFyIG1hbmFnZXIgPSB0aGlzLm1hbmFnZXIsCiAgICAgICAgICBjb21wb25lbnQgPSB0aGlzLmNvbXBvbmVudCwKICAgICAgICAgIGJvdW5kcyA9IHRoaXMuYm91bmRzOwogICAgICBtYW5hZ2VyLmRpZFVwZGF0ZUxheW91dChjb21wb25lbnQsIGJvdW5kcyk7CiAgICAgIHZtLmVudi5kaWRVcGRhdGUoY29tcG9uZW50LCBtYW5hZ2VyKTsKICAgIH07CgogICAgcmV0dXJuIERpZFVwZGF0ZUxheW91dE9wY29kZTsKICB9KFVwZGF0aW5nT3Bjb2RlKTsKICAvKiB0c2xpbnQ6ZGlzYWJsZSAqLwoKCiAgZnVuY3Rpb24gZGVidWdDYWxsYmFjayhjb250ZXh0LCBnZXQpIHsKICAgIGNvbnNvbGUuaW5mbygnVXNlIGBjb250ZXh0YCwgYW5kIGBnZXQoPHBhdGg+KWAgdG8gZGVidWcgdGhpcyB0ZW1wbGF0ZS4nKTsgLy8gZm9yIGV4YW1wbGUuLi4KCiAgICBjb250ZXh0ID09PSBnZXQoJ3RoaXMnKTsKICAgIGRlYnVnZ2VyOwogIH0KICAvKiB0c2xpbnQ6ZW5hYmxlICovCgoKICB2YXIgY2FsbGJhY2sgPSBkZWJ1Z0NhbGxiYWNrOyAvLyBGb3IgdGVzdGluZyBwdXJwb3NlcwoKICBmdW5jdGlvbiBzZXREZWJ1Z2dlckNhbGxiYWNrKGNiKSB7CiAgICBjYWxsYmFjayA9IGNiOwogIH0KCiAgZnVuY3Rpb24gcmVzZXREZWJ1Z2dlckNhbGxiYWNrKCkgewogICAgY2FsbGJhY2sgPSBkZWJ1Z0NhbGxiYWNrOwogIH0KCiAgdmFyIFNjb3BlSW5zcGVjdG9yID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gU2NvcGVJbnNwZWN0b3Ioc2NvcGUsIHN5bWJvbHMsIGV2YWxJbmZvKSB7CiAgICAgIHRoaXMuc2NvcGUgPSBzY29wZTsKICAgICAgdGhpcy5sb2NhbHMgPSAoMCwgX3V0aWwuZGljdCkoKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXZhbEluZm8ubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgc2xvdCA9IGV2YWxJbmZvW2ldOwogICAgICAgIHZhciBuYW1lID0gc3ltYm9sc1tzbG90IC0gMV07CiAgICAgICAgdmFyIHJlZiA9IHNjb3BlLmdldFN5bWJvbChzbG90KTsKICAgICAgICB0aGlzLmxvY2Fsc1tuYW1lXSA9IHJlZjsKICAgICAgfQogICAgfQoKICAgIHZhciBfcHJvdG8yMSA9IFNjb3BlSW5zcGVjdG9yLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yMS5nZXQgPSBmdW5jdGlvbiBnZXQocGF0aCkgewogICAgICB2YXIgc2NvcGUgPSB0aGlzLnNjb3BlLAogICAgICAgICAgbG9jYWxzID0gdGhpcy5sb2NhbHM7CiAgICAgIHZhciBwYXJ0cyA9IHBhdGguc3BsaXQoJy4nKTsKCiAgICAgIHZhciBfcGF0aCRzcGxpdCA9IHBhdGguc3BsaXQoJy4nKSwKICAgICAgICAgIGhlYWQgPSBfcGF0aCRzcGxpdFswXSwKICAgICAgICAgIHRhaWwgPSBfcGF0aCRzcGxpdC5zbGljZSgxKTsKCiAgICAgIHZhciBldmFsU2NvcGUgPSBzY29wZS5nZXRFdmFsU2NvcGUoKTsKICAgICAgdmFyIHJlZjsKCiAgICAgIGlmIChoZWFkID09PSAndGhpcycpIHsKICAgICAgICByZWYgPSBzY29wZS5nZXRTZWxmKCk7CiAgICAgIH0gZWxzZSBpZiAobG9jYWxzW2hlYWRdKSB7CiAgICAgICAgcmVmID0gbG9jYWxzW2hlYWRdOwogICAgICB9IGVsc2UgaWYgKGhlYWQuaW5kZXhPZignQCcpID09PSAwICYmIGV2YWxTY29wZVtoZWFkXSkgewogICAgICAgIHJlZiA9IGV2YWxTY29wZVtoZWFkXTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZWYgPSB0aGlzLnNjb3BlLmdldFNlbGYoKTsKICAgICAgICB0YWlsID0gcGFydHM7CiAgICAgIH0KCiAgICAgIHJldHVybiB0YWlsLnJlZHVjZShmdW5jdGlvbiAociwgcGFydCkgewogICAgICAgIHJldHVybiByLmdldChwYXJ0KTsKICAgICAgfSwgcmVmKTsKICAgIH07CgogICAgcmV0dXJuIFNjb3BlSW5zcGVjdG9yOwogIH0oKTsKCiAgQVBQRU5EX09QQ09ERVMuYWRkKDk3CiAgLyogRGVidWdnZXIgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjUxKSB7CiAgICB2YXIgX3N5bWJvbHMgPSBfcmVmNTEub3AxLAogICAgICAgIF9ldmFsSW5mbyA9IF9yZWY1MS5vcDI7CiAgICB2YXIgc3ltYm9scyA9IHZtLmNvbnN0YW50cy5nZXRTdHJpbmdBcnJheShfc3ltYm9scyk7CiAgICB2YXIgZXZhbEluZm8gPSB2bS5jb25zdGFudHMuZ2V0QXJyYXkoX2V2YWxJbmZvKTsKICAgIHZhciBpbnNwZWN0b3IgPSBuZXcgU2NvcGVJbnNwZWN0b3Iodm0uc2NvcGUoKSwgc3ltYm9scywgZXZhbEluZm8pOwogICAgY2FsbGJhY2sodm0uZ2V0U2VsZigpLnZhbHVlKCksIGZ1bmN0aW9uIChwYXRoKSB7CiAgICAgIHJldHVybiBpbnNwZWN0b3IuZ2V0KHBhdGgpLnZhbHVlKCk7CiAgICB9KTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoOTUKICAvKiBJbnZva2VQYXJ0aWFsICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY1MikgewogICAgdmFyIF9tZXRhID0gX3JlZjUyLm9wMSwKICAgICAgICBfc3ltYm9scyA9IF9yZWY1Mi5vcDIsCiAgICAgICAgX2V2YWxJbmZvID0gX3JlZjUyLm9wMzsKICAgIHZhciBjb25zdGFudHMgPSB2bS5jb25zdGFudHMsCiAgICAgICAgcmVzb2x2ZXIgPSB2bS5jb25zdGFudHMucmVzb2x2ZXIsCiAgICAgICAgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciBuYW1lID0gc3RhY2sucG9wKCkudmFsdWUoKTsKICAgIHZhciBtZXRhID0gY29uc3RhbnRzLmdldFNlcmlhbGl6YWJsZShfbWV0YSk7CiAgICB2YXIgb3V0ZXJTeW1ib2xzID0gY29uc3RhbnRzLmdldFN0cmluZ0FycmF5KF9zeW1ib2xzKTsKICAgIHZhciBldmFsSW5mbyA9IGNvbnN0YW50cy5nZXRBcnJheShfZXZhbEluZm8pOwogICAgdmFyIGhhbmRsZSA9IHJlc29sdmVyLmxvb2t1cFBhcnRpYWwobmFtZSwgbWV0YSk7CiAgICB2YXIgZGVmaW5pdGlvbiA9IHJlc29sdmVyLnJlc29sdmUoaGFuZGxlKTsKCiAgICB2YXIgX2RlZmluaXRpb24kZ2V0UGFydGlhID0gZGVmaW5pdGlvbi5nZXRQYXJ0aWFsKCksCiAgICAgICAgc3ltYm9sVGFibGUgPSBfZGVmaW5pdGlvbiRnZXRQYXJ0aWEuc3ltYm9sVGFibGUsCiAgICAgICAgdm1IYW5kbGUgPSBfZGVmaW5pdGlvbiRnZXRQYXJ0aWEuaGFuZGxlOwoKICAgIHsKICAgICAgdmFyIHBhcnRpYWxTeW1ib2xzID0gc3ltYm9sVGFibGUuc3ltYm9sczsKICAgICAgdmFyIG91dGVyU2NvcGUgPSB2bS5zY29wZSgpOwogICAgICB2YXIgcGFydGlhbFNjb3BlID0gdm0ucHVzaFJvb3RTY29wZShwYXJ0aWFsU3ltYm9scy5sZW5ndGgsIGZhbHNlKTsKICAgICAgdmFyIGV2YWxTY29wZSA9IG91dGVyU2NvcGUuZ2V0RXZhbFNjb3BlKCk7CiAgICAgIHBhcnRpYWxTY29wZS5iaW5kQ2FsbGVyU2NvcGUob3V0ZXJTY29wZS5nZXRDYWxsZXJTY29wZSgpKTsKICAgICAgcGFydGlhbFNjb3BlLmJpbmRFdmFsU2NvcGUoZXZhbFNjb3BlKTsKICAgICAgcGFydGlhbFNjb3BlLmJpbmRTZWxmKG91dGVyU2NvcGUuZ2V0U2VsZigpKTsKICAgICAgdmFyIGxvY2FscyA9IE9iamVjdC5jcmVhdGUob3V0ZXJTY29wZS5nZXRQYXJ0aWFsTWFwKCkpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldmFsSW5mby5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBzbG90ID0gZXZhbEluZm9baV07CiAgICAgICAgdmFyIF9uYW1lMiA9IG91dGVyU3ltYm9sc1tzbG90IC0gMV07CiAgICAgICAgdmFyIHJlZiA9IG91dGVyU2NvcGUuZ2V0U3ltYm9sKHNsb3QpOwogICAgICAgIGxvY2Fsc1tfbmFtZTJdID0gcmVmOwogICAgICB9CgogICAgICBpZiAoZXZhbFNjb3BlKSB7CiAgICAgICAgZm9yICh2YXIgX2kzID0gMDsgX2kzIDwgcGFydGlhbFN5bWJvbHMubGVuZ3RoOyBfaTMrKykgewogICAgICAgICAgdmFyIF9uYW1lMyA9IHBhcnRpYWxTeW1ib2xzW19pM107CiAgICAgICAgICB2YXIgc3ltYm9sID0gX2kzICsgMTsKICAgICAgICAgIHZhciB2YWx1ZSQkMSA9IGV2YWxTY29wZVtfbmFtZTNdOwogICAgICAgICAgaWYgKHZhbHVlJCQxICE9PSB1bmRlZmluZWQpIHBhcnRpYWxTY29wZS5iaW5kKHN5bWJvbCwgdmFsdWUkJDEpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcGFydGlhbFNjb3BlLmJpbmRQYXJ0aWFsTWFwKGxvY2Fscyk7CiAgICAgIHZtLnB1c2hGcmFtZSgpOyAvLyBzcCArPSAyCgogICAgICB2bS5jYWxsKHZtSGFuZGxlKTsKICAgIH0KICB9KTsKCiAgdmFyIEl0ZXJhYmxlUHJlc2VuY2VSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBJdGVyYWJsZVByZXNlbmNlUmVmZXJlbmNlKGFydGlmYWN0cykgewogICAgICB0aGlzLnRhZyA9IGFydGlmYWN0cy50YWc7CiAgICAgIHRoaXMuYXJ0aWZhY3RzID0gYXJ0aWZhY3RzOwogICAgfQoKICAgIHZhciBfcHJvdG8yMiA9IEl0ZXJhYmxlUHJlc2VuY2VSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzIyLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHJldHVybiAhdGhpcy5hcnRpZmFjdHMuaXNFbXB0eSgpOwogICAgfTsKCiAgICByZXR1cm4gSXRlcmFibGVQcmVzZW5jZVJlZmVyZW5jZTsKICB9KCk7CgogIEFQUEVORF9PUENPREVTLmFkZCg2NgogIC8qIFB1dEl0ZXJhdG9yICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIGxpc3RSZWYgPSBzdGFjay5wb3AoKTsKICAgIHZhciBrZXkgPSBzdGFjay5wb3AoKTsKICAgIHZhciBpdGVyYWJsZSA9IHZtLmVudi5pdGVyYWJsZUZvcihsaXN0UmVmLCBrZXkudmFsdWUoKSk7CiAgICB2YXIgaXRlcmF0b3IgPSBuZXcgX3JlZmVyZW5jZTIuUmVmZXJlbmNlSXRlcmF0b3IoaXRlcmFibGUpOwogICAgc3RhY2sucHVzaChpdGVyYXRvcik7CiAgICBzdGFjay5wdXNoKG5ldyBJdGVyYWJsZVByZXNlbmNlUmVmZXJlbmNlKGl0ZXJhdG9yLmFydGlmYWN0cykpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg2NAogIC8qIEVudGVyTGlzdCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNTMpIHsKICAgIHZhciByZWxhdGl2ZVN0YXJ0ID0gX3JlZjUzLm9wMTsKICAgIHZtLmVudGVyTGlzdChyZWxhdGl2ZVN0YXJ0KTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNjUKICAvKiBFeGl0TGlzdCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2bS5leGl0TGlzdCgpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg2NwogIC8qIEl0ZXJhdGUgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjU0KSB7CiAgICB2YXIgYnJlYWtzID0gX3JlZjU0Lm9wMTsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIGl0ZW0gPSBzdGFjay5wZWVrKCkubmV4dCgpOwoKICAgIGlmIChpdGVtKSB7CiAgICAgIHZhciB0cnlPcGNvZGUgPSB2bS5pdGVyYXRlKGl0ZW0ubWVtbywgaXRlbS52YWx1ZSk7CiAgICAgIHZtLmVudGVySXRlbShpdGVtLmtleSwgdHJ5T3Bjb2RlKTsKICAgIH0gZWxzZSB7CiAgICAgIHZtLmdvdG8oYnJlYWtzKTsKICAgIH0KICB9KTsKCiAgdmFyIEN1cnNvciA9IGZ1bmN0aW9uIEN1cnNvcihlbGVtZW50LCBuZXh0U2libGluZykgewogICAgdGhpcy5lbGVtZW50ID0gZWxlbWVudDsKICAgIHRoaXMubmV4dFNpYmxpbmcgPSBuZXh0U2libGluZzsKICB9OwoKICBfZXhwb3J0cy5DdXJzb3IgPSBDdXJzb3I7CgogIHZhciBDb25jcmV0ZUJvdW5kcyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENvbmNyZXRlQm91bmRzKHBhcmVudE5vZGUsIGZpcnN0LCBsYXN0KSB7CiAgICAgIHRoaXMucGFyZW50Tm9kZSA9IHBhcmVudE5vZGU7CiAgICAgIHRoaXMuZmlyc3QgPSBmaXJzdDsKICAgICAgdGhpcy5sYXN0ID0gbGFzdDsKICAgIH0KCiAgICB2YXIgX3Byb3RvMjMgPSBDb25jcmV0ZUJvdW5kcy5wcm90b3R5cGU7CgogICAgX3Byb3RvMjMucGFyZW50RWxlbWVudCA9IGZ1bmN0aW9uIHBhcmVudEVsZW1lbnQoKSB7CiAgICAgIHJldHVybiB0aGlzLnBhcmVudE5vZGU7CiAgICB9OwoKICAgIF9wcm90bzIzLmZpcnN0Tm9kZSA9IGZ1bmN0aW9uIGZpcnN0Tm9kZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZmlyc3Q7CiAgICB9OwoKICAgIF9wcm90bzIzLmxhc3ROb2RlID0gZnVuY3Rpb24gbGFzdE5vZGUoKSB7CiAgICAgIHJldHVybiB0aGlzLmxhc3Q7CiAgICB9OwoKICAgIHJldHVybiBDb25jcmV0ZUJvdW5kczsKICB9KCk7CgogIF9leHBvcnRzLkNvbmNyZXRlQm91bmRzID0gQ29uY3JldGVCb3VuZHM7CgogIHZhciBTaW5nbGVOb2RlQm91bmRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gU2luZ2xlTm9kZUJvdW5kcyhwYXJlbnROb2RlLCBub2RlKSB7CiAgICAgIHRoaXMucGFyZW50Tm9kZSA9IHBhcmVudE5vZGU7CiAgICAgIHRoaXMubm9kZSA9IG5vZGU7CiAgICB9CgogICAgdmFyIF9wcm90bzI0ID0gU2luZ2xlTm9kZUJvdW5kcy5wcm90b3R5cGU7CgogICAgX3Byb3RvMjQucGFyZW50RWxlbWVudCA9IGZ1bmN0aW9uIHBhcmVudEVsZW1lbnQoKSB7CiAgICAgIHJldHVybiB0aGlzLnBhcmVudE5vZGU7CiAgICB9OwoKICAgIF9wcm90bzI0LmZpcnN0Tm9kZSA9IGZ1bmN0aW9uIGZpcnN0Tm9kZSgpIHsKICAgICAgcmV0dXJuIHRoaXMubm9kZTsKICAgIH07CgogICAgX3Byb3RvMjQubGFzdE5vZGUgPSBmdW5jdGlvbiBsYXN0Tm9kZSgpIHsKICAgICAgcmV0dXJuIHRoaXMubm9kZTsKICAgIH07CgogICAgcmV0dXJuIFNpbmdsZU5vZGVCb3VuZHM7CiAgfSgpOwoKICBmdW5jdGlvbiBfbW92ZShib3VuZHMsIHJlZmVyZW5jZSkgewogICAgdmFyIHBhcmVudCA9IGJvdW5kcy5wYXJlbnRFbGVtZW50KCk7CiAgICB2YXIgZmlyc3QgPSBib3VuZHMuZmlyc3ROb2RlKCk7CiAgICB2YXIgbGFzdCA9IGJvdW5kcy5sYXN0Tm9kZSgpOwogICAgdmFyIGN1cnJlbnQgPSBmaXJzdDsKCiAgICB3aGlsZSAodHJ1ZSkgewogICAgICB2YXIgbmV4dCA9IGN1cnJlbnQubmV4dFNpYmxpbmc7CiAgICAgIHBhcmVudC5pbnNlcnRCZWZvcmUoY3VycmVudCwgcmVmZXJlbmNlKTsKCiAgICAgIGlmIChjdXJyZW50ID09PSBsYXN0KSB7CiAgICAgICAgcmV0dXJuIG5leHQ7CiAgICAgIH0KCiAgICAgIGN1cnJlbnQgPSBuZXh0OwogICAgfQogIH0KCiAgZnVuY3Rpb24gY2xlYXIoYm91bmRzKSB7CiAgICB2YXIgcGFyZW50ID0gYm91bmRzLnBhcmVudEVsZW1lbnQoKTsKICAgIHZhciBmaXJzdCA9IGJvdW5kcy5maXJzdE5vZGUoKTsKICAgIHZhciBsYXN0ID0gYm91bmRzLmxhc3ROb2RlKCk7CiAgICB2YXIgY3VycmVudCA9IGZpcnN0OwoKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIHZhciBuZXh0ID0gY3VycmVudC5uZXh0U2libGluZzsKICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKGN1cnJlbnQpOwoKICAgICAgaWYgKGN1cnJlbnQgPT09IGxhc3QpIHsKICAgICAgICByZXR1cm4gbmV4dDsKICAgICAgfQoKICAgICAgY3VycmVudCA9IG5leHQ7CiAgICB9CiAgfSAvLyBQYXRjaDogICAgaW5zZXJ0QWRqYWNlbnRIVE1MIG9uIFNWRyBGaXgKICAvLyBCcm93c2VyczogU2FmYXJpLCBJRSwgRWRnZSwgRmlyZWZveCB+MzMtMzQKICAvLyBSZWFzb246ICAgaW5zZXJ0QWRqYWNlbnRIVE1MIGRvZXMgbm90IGV4aXN0IG9uIFNWRyBlbGVtZW50cyBpbiBTYWZhcmkuIEl0IGlzCiAgLy8gICAgICAgICAgIHByZXNlbnQgYnV0IHRocm93cyBhbiBleGNlcHRpb24gb24gSUUgYW5kIEVkZ2UuIE9sZCB2ZXJzaW9ucyBvZgogIC8vICAgICAgICAgICBGaXJlZm94IGNyZWF0ZSBub2RlcyBpbiB0aGUgaW5jb3JyZWN0IG5hbWVzcGFjZS4KICAvLyBGaXg6ICAgICAgU2luY2UgSUUgYW5kIEVkZ2Ugc2lsZW50bHkgZmFpbCB0byBjcmVhdGUgU1ZHIG5vZGVzIHVzaW5nCiAgLy8gICAgICAgICAgIGlubmVySFRNTCwgYW5kIGJlY2F1c2UgRmlyZWZveCBtYXkgY3JlYXRlIG5vZGVzIGluIHRoZSBpbmNvcnJlY3QKICAvLyAgICAgICAgICAgbmFtZXNwYWNlIHVzaW5nIGlubmVySFRNTCBvbiBTVkcgZWxlbWVudHMsIGFuIEhUTUwtc3RyaW5nIHdyYXBwaW5nCiAgLy8gICAgICAgICAgIGFwcHJvYWNoIGlzIHVzZWQuIEEgcHJlL3Bvc3QgU1ZHIHRhZyBpcyBhZGRlZCB0byB0aGUgc3RyaW5nLCB0aGVuCiAgLy8gICAgICAgICAgIHRoYXQgd2hvbGUgc3RyaW5nIGlzIGFkZGVkIHRvIGEgZGl2LiBUaGUgY3JlYXRlZCBub2RlcyBhcmUgcGx1Y2tlZAogIC8vICAgICAgICAgICBvdXQgYW5kIGFwcGxpZWQgdG8gdGhlIHRhcmdldCBsb2NhdGlvbiBvbiBET00uCgoKICBmdW5jdGlvbiBhcHBseVNWR0lubmVySFRNTEZpeChkb2N1bWVudCwgRE9NQ2xhc3MsIHN2Z05hbWVzcGFjZSkgewogICAgaWYgKCFkb2N1bWVudCkgcmV0dXJuIERPTUNsYXNzOwoKICAgIGlmICghc2hvdWxkQXBwbHlGaXgoZG9jdW1lbnQsIHN2Z05hbWVzcGFjZSkpIHsKICAgICAgcmV0dXJuIERPTUNsYXNzOwogICAgfQoKICAgIHZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgIHJldHVybiAoCiAgICAgIC8qI19fUFVSRV9fKi8KICAgICAgZnVuY3Rpb24gKF9ET01DbGFzcykgewogICAgICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShET01DaGFuZ2VzV2l0aFNWR0lubmVySFRNTEZpeCwgX0RPTUNsYXNzKTsKCiAgICAgICAgZnVuY3Rpb24gRE9NQ2hhbmdlc1dpdGhTVkdJbm5lckhUTUxGaXgoKSB7CiAgICAgICAgICByZXR1cm4gX0RPTUNsYXNzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgICAgICB9CgogICAgICAgIHZhciBfcHJvdG8yNSA9IERPTUNoYW5nZXNXaXRoU1ZHSW5uZXJIVE1MRml4LnByb3RvdHlwZTsKCiAgICAgICAgX3Byb3RvMjUuaW5zZXJ0SFRNTEJlZm9yZSA9IGZ1bmN0aW9uIGluc2VydEhUTUxCZWZvcmUocGFyZW50LCBuZXh0U2libGluZywgaHRtbCkgewogICAgICAgICAgaWYgKGh0bWwgPT09ICcnKSB7CiAgICAgICAgICAgIHJldHVybiBfRE9NQ2xhc3MucHJvdG90eXBlLmluc2VydEhUTUxCZWZvcmUuY2FsbCh0aGlzLCBwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAocGFyZW50Lm5hbWVzcGFjZVVSSSAhPT0gc3ZnTmFtZXNwYWNlKSB7CiAgICAgICAgICAgIHJldHVybiBfRE9NQ2xhc3MucHJvdG90eXBlLmluc2VydEhUTUxCZWZvcmUuY2FsbCh0aGlzLCBwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKTsKICAgICAgICAgIH0KCiAgICAgICAgICByZXR1cm4gZml4U1ZHKHBhcmVudCwgZGl2LCBodG1sLCBuZXh0U2libGluZyk7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIERPTUNoYW5nZXNXaXRoU1ZHSW5uZXJIVE1MRml4OwogICAgICB9KERPTUNsYXNzKQogICAgKTsKICB9CgogIGZ1bmN0aW9uIGZpeFNWRyhwYXJlbnQsIGRpdiwgaHRtbCwgcmVmZXJlbmNlKSB7CiAgICB2YXIgc291cmNlOyAvLyBUaGlzIGlzIGltcG9ydGFudCwgYmVjYXVzZSBkZWNlbmRhbnRzIG9mIHRoZSA8Zm9yZWlnbk9iamVjdD4gaW50ZWdyYXRpb24KICAgIC8vIHBvaW50IGFyZSBwYXJzZWQgaW4gdGhlIEhUTUwgbmFtZXNwYWNlCgogICAgaWYgKHBhcmVudC50YWdOYW1lLnRvVXBwZXJDYXNlKCkgPT09ICdGT1JFSUdOT0JKRUNUJykgewogICAgICAvLyBJRSwgRWRnZTogYWxzbyBkbyBub3QgY29ycmVjdGx5IHN1cHBvcnQgdXNpbmcgYGlubmVySFRNTGAgb24gU1ZHCiAgICAgIC8vIG5hbWVzcGFjZWQgZWxlbWVudHMuIFNvIGhlcmUgYSB3cmFwcGVyIGlzIHVzZWQuCiAgICAgIHZhciB3cmFwcGVkSHRtbCA9ICc8c3ZnPjxmb3JlaWduT2JqZWN0PicgKyBodG1sICsgJzwvZm9yZWlnbk9iamVjdD48L3N2Zz4nOwogICAgICBkaXYuaW5uZXJIVE1MID0gd3JhcHBlZEh0bWw7CiAgICAgIHNvdXJjZSA9IGRpdi5maXJzdENoaWxkLmZpcnN0Q2hpbGQ7CiAgICB9IGVsc2UgewogICAgICAvLyBJRSwgRWRnZTogYWxzbyBkbyBub3QgY29ycmVjdGx5IHN1cHBvcnQgdXNpbmcgYGlubmVySFRNTGAgb24gU1ZHCiAgICAgIC8vIG5hbWVzcGFjZWQgZWxlbWVudHMuIFNvIGhlcmUgYSB3cmFwcGVyIGlzIHVzZWQuCiAgICAgIHZhciBfd3JhcHBlZEh0bWwgPSAnPHN2Zz4nICsgaHRtbCArICc8L3N2Zz4nOwoKICAgICAgZGl2LmlubmVySFRNTCA9IF93cmFwcGVkSHRtbDsKICAgICAgc291cmNlID0gZGl2LmZpcnN0Q2hpbGQ7CiAgICB9CgogICAgcmV0dXJuIG1vdmVOb2Rlc0JlZm9yZShzb3VyY2UsIHBhcmVudCwgcmVmZXJlbmNlKTsKICB9CgogIGZ1bmN0aW9uIHNob3VsZEFwcGx5Rml4KGRvY3VtZW50LCBzdmdOYW1lc3BhY2UpIHsKICAgIHZhciBzdmcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoc3ZnTmFtZXNwYWNlLCAnc3ZnJyk7CgogICAgdHJ5IHsKICAgICAgc3ZnWydpbnNlcnRBZGphY2VudEhUTUwnXSgnYmVmb3JlZW5kJywgJzxjaXJjbGU+PC9jaXJjbGU+Jyk7CiAgICB9IGNhdGNoIChlKSB7Ly8gSUUsIEVkZ2U6IFdpbGwgdGhyb3csIGluc2VydEFkamFjZW50SFRNTCBpcyB1bnN1cHBvcnRlZCBvbiBTVkcKICAgICAgLy8gU2FmYXJpOiBXaWxsIHRocm93LCBpbnNlcnRBZGphY2VudEhUTUwgaXMgbm90IHByZXNlbnQgb24gU1ZHCiAgICB9IGZpbmFsbHkgewogICAgICAvLyBGRjogT2xkIHZlcnNpb25zIHdpbGwgY3JlYXRlIGEgbm9kZSBpbiB0aGUgd3JvbmcgbmFtZXNwYWNlCiAgICAgIGlmIChzdmcuY2hpbGROb2Rlcy5sZW5ndGggPT09IDEgJiYgc3ZnLmZpcnN0Q2hpbGQubmFtZXNwYWNlVVJJID09PSBTVkdfTkFNRVNQQUNFKSB7CiAgICAgICAgLy8gVGhlIHRlc3Qgd29ya2VkIGFzIGV4cGVjdGVkLCBubyBmaXggcmVxdWlyZWQKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIHJldHVybiB0cnVlOwogICAgfQogIH0gLy8gUGF0Y2g6ICAgIEFkamFjZW50IHRleHQgbm9kZSBtZXJnaW5nIGZpeAogIC8vIEJyb3dzZXJzOiBJRSwgRWRnZSwgRmlyZWZveCB3L28gaW5zcGVjdG9yIG9wZW4KICAvLyBSZWFzb246ICAgVGhlc2UgYnJvd3NlcnMgd2lsbCBtZXJnZSBhZGphY2VudCB0ZXh0IG5vZGVzLiBGb3IgZXhtYXBsZSBnaXZlbgogIC8vICAgICAgICAgICA8ZGl2PkhlbGxvPC9kaXY+IHdpdGggZGl2Lmluc2VydEFkamFjZW50SFRNTCgnIHdvcmxkJykgYnJvd3NlcnMKICAvLyAgICAgICAgICAgd2l0aCBwcm9wZXIgYmVoYXZpb3Igd2lsbCBwb3B1bGF0ZSBkaXYuY2hpbGROb2RlcyB3aXRoIHR3byBpdGVtcy4KICAvLyAgICAgICAgICAgVGhlc2UgYnJvd3NlcnMgd2lsbCBwb3B1bGF0ZSBpdCB3aXRoIG9uZSBtZXJnZWQgbm9kZSBpbnN0ZWFkLgogIC8vIEZpeDogICAgICBBZGQgdGhlc2Ugbm9kZXMgdG8gYSB3cmFwcGVyIGVsZW1lbnQsIHRoZW4gaXRlcmF0ZSB0aGUgY2hpbGROb2RlcwogIC8vICAgICAgICAgICBvZiB0aGF0IHdyYXBwZXIgYW5kIG1vdmUgdGhlIG5vZGVzIHRvIHRoZWlyIHRhcmdldCBsb2NhdGlvbi4gTm90ZQogIC8vICAgICAgICAgICB0aGF0IHBvdGVudGlhbCBTVkcgYnVncyB3aWxsIGhhdmUgYmVlbiBoYW5kbGVkIGJlZm9yZSB0aGlzIGZpeC4KICAvLyAgICAgICAgICAgTm90ZSB0aGF0IHRoaXMgZml4IG11c3Qgb25seSBhcHBseSB0byB0aGUgcHJldmlvdXMgdGV4dCBub2RlLCBhcwogIC8vICAgICAgICAgICB0aGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgaW5zZXJ0SFRNTEJlZm9yZWAgYWxyZWFkeSBoYW5kbGVzCiAgLy8gICAgICAgICAgIGZvbGxvd2luZyB0ZXh0IG5vZGVzIGNvcnJlY3RseS4KCgogIGZ1bmN0aW9uIGFwcGx5VGV4dE5vZGVNZXJnaW5nRml4KGRvY3VtZW50LCBET01DbGFzcykgewogICAgaWYgKCFkb2N1bWVudCkgcmV0dXJuIERPTUNsYXNzOwoKICAgIGlmICghc2hvdWxkQXBwbHlGaXgkMShkb2N1bWVudCkpIHsKICAgICAgcmV0dXJuIERPTUNsYXNzOwogICAgfQoKICAgIHJldHVybiAoCiAgICAgIC8qI19fUFVSRV9fKi8KICAgICAgZnVuY3Rpb24gKF9ET01DbGFzczIpIHsKICAgICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRE9NQ2hhbmdlc1dpdGhUZXh0Tm9kZU1lcmdpbmdGaXgsIF9ET01DbGFzczIpOwoKICAgICAgICBmdW5jdGlvbiBET01DaGFuZ2VzV2l0aFRleHROb2RlTWVyZ2luZ0ZpeChkb2N1bWVudCkgewogICAgICAgICAgdmFyIF90aGlzMTI7CgogICAgICAgICAgX3RoaXMxMiA9IF9ET01DbGFzczIuY2FsbCh0aGlzLCBkb2N1bWVudCkgfHwgdGhpczsKICAgICAgICAgIF90aGlzMTIudXNlbGVzc0NvbW1lbnQgPSBkb2N1bWVudC5jcmVhdGVDb21tZW50KCcnKTsKICAgICAgICAgIHJldHVybiBfdGhpczEyOwogICAgICAgIH0KCiAgICAgICAgdmFyIF9wcm90bzI2ID0gRE9NQ2hhbmdlc1dpdGhUZXh0Tm9kZU1lcmdpbmdGaXgucHJvdG90eXBlOwoKICAgICAgICBfcHJvdG8yNi5pbnNlcnRIVE1MQmVmb3JlID0gZnVuY3Rpb24gaW5zZXJ0SFRNTEJlZm9yZShwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKSB7CiAgICAgICAgICBpZiAoaHRtbCA9PT0gJycpIHsKICAgICAgICAgICAgcmV0dXJuIF9ET01DbGFzczIucHJvdG90eXBlLmluc2VydEhUTUxCZWZvcmUuY2FsbCh0aGlzLCBwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKTsKICAgICAgICAgIH0KCiAgICAgICAgICB2YXIgZGlkU2V0VXNlbGVzc0NvbW1lbnQgPSBmYWxzZTsKICAgICAgICAgIHZhciBuZXh0UHJldmlvdXMgPSBuZXh0U2libGluZyA/IG5leHRTaWJsaW5nLnByZXZpb3VzU2libGluZyA6IHBhcmVudC5sYXN0Q2hpbGQ7CgogICAgICAgICAgaWYgKG5leHRQcmV2aW91cyAmJiBuZXh0UHJldmlvdXMgaW5zdGFuY2VvZiBUZXh0KSB7CiAgICAgICAgICAgIGRpZFNldFVzZWxlc3NDb21tZW50ID0gdHJ1ZTsKICAgICAgICAgICAgcGFyZW50Lmluc2VydEJlZm9yZSh0aGlzLnVzZWxlc3NDb21tZW50LCBuZXh0U2libGluZyk7CiAgICAgICAgICB9CgogICAgICAgICAgdmFyIGJvdW5kcyA9IF9ET01DbGFzczIucHJvdG90eXBlLmluc2VydEhUTUxCZWZvcmUuY2FsbCh0aGlzLCBwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKTsKCiAgICAgICAgICBpZiAoZGlkU2V0VXNlbGVzc0NvbW1lbnQpIHsKICAgICAgICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKHRoaXMudXNlbGVzc0NvbW1lbnQpOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBib3VuZHM7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIERPTUNoYW5nZXNXaXRoVGV4dE5vZGVNZXJnaW5nRml4OwogICAgICB9KERPTUNsYXNzKQogICAgKTsKICB9CgogIGZ1bmN0aW9uIHNob3VsZEFwcGx5Rml4JDEoZG9jdW1lbnQpIHsKICAgIHZhciBtZXJnaW5nVGV4dERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgbWVyZ2luZ1RleHREaXYuaW5uZXJIVE1MID0gJ2ZpcnN0JzsKICAgIG1lcmdpbmdUZXh0RGl2Lmluc2VydEFkamFjZW50SFRNTCgnYmVmb3JlZW5kJywgJ3NlY29uZCcpOwoKICAgIGlmIChtZXJnaW5nVGV4dERpdi5jaGlsZE5vZGVzLmxlbmd0aCA9PT0gMikgewogICAgICAvLyBJdCB3b3JrZWQgYXMgZXhwZWN0ZWQsIG5vIGZpeCByZXF1aXJlZAogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgcmV0dXJuIHRydWU7CiAgfQoKICB2YXIgU1ZHX05BTUVTUEFDRSA9ICJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAvKiBTVkcgKi8KICA7IC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2h0bWwvc3ludGF4Lmh0bWwjaHRtbC1pbnRlZ3JhdGlvbi1wb2ludAoKICBfZXhwb3J0cy5TVkdfTkFNRVNQQUNFID0gU1ZHX05BTUVTUEFDRTsKICB2YXIgU1ZHX0lOVEVHUkFUSU9OX1BPSU5UUyA9IHsKICAgIGZvcmVpZ25PYmplY3Q6IDEsCiAgICBkZXNjOiAxLAogICAgdGl0bGU6IDEKICB9OyAvLyBodHRwOi8vd3d3LnczLm9yZy9UUi9odG1sL3N5bnRheC5odG1sI2FkanVzdC1zdmctYXR0cmlidXRlcwogIC8vIFRPRE86IEFkanVzdCBTVkcgYXR0cmlidXRlcwogIC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2h0bWwvc3ludGF4Lmh0bWwjcGFyc2luZy1tYWluLWluZm9yZWlnbgogIC8vIFRPRE86IEFkanVzdCBTVkcgZWxlbWVudHMKICAvLyBodHRwOi8vd3d3LnczLm9yZy9UUi9odG1sL3N5bnRheC5odG1sI3BhcnNpbmctbWFpbi1pbmZvcmVpZ24KCiAgdmFyIEJMQUNLTElTVF9UQUJMRSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgWydiJywgJ2JpZycsICdibG9ja3F1b3RlJywgJ2JvZHknLCAnYnInLCAnY2VudGVyJywgJ2NvZGUnLCAnZGQnLCAnZGl2JywgJ2RsJywgJ2R0JywgJ2VtJywgJ2VtYmVkJywgJ2gxJywgJ2gyJywgJ2gzJywgJ2g0JywgJ2g1JywgJ2g2JywgJ2hlYWQnLCAnaHInLCAnaScsICdpbWcnLCAnbGknLCAnbGlzdGluZycsICdtYWluJywgJ21ldGEnLCAnbm9icicsICdvbCcsICdwJywgJ3ByZScsICdydWJ5JywgJ3MnLCAnc21hbGwnLCAnc3BhbicsICdzdHJvbmcnLCAnc3RyaWtlJywgJ3N1YicsICdzdXAnLCAndGFibGUnLCAndHQnLCAndScsICd1bCcsICd2YXInXS5mb3JFYWNoKGZ1bmN0aW9uICh0YWcpIHsKICAgIHJldHVybiBCTEFDS0xJU1RfVEFCTEVbdGFnXSA9IDE7CiAgfSk7CiAgdmFyIFdISVRFU1BBQ0UgPSAvW1x0LVxyIFx4QTBcdTE2ODBcdTE4MEVcdTIwMDAtXHUyMDBBXHUyMDI4XHUyMDI5XHUyMDJGXHUyMDVGXHUzMDAwXHVGRUZGXS87CiAgdmFyIGRvYyA9IHR5cGVvZiBkb2N1bWVudCA9PT0gJ3VuZGVmaW5lZCcgPyBudWxsIDogZG9jdW1lbnQ7CgogIGZ1bmN0aW9uIGlzV2hpdGVzcGFjZShzdHJpbmcpIHsKICAgIHJldHVybiBXSElURVNQQUNFLnRlc3Qoc3RyaW5nKTsKICB9CgogIGZ1bmN0aW9uIG1vdmVOb2Rlc0JlZm9yZShzb3VyY2UsIHRhcmdldCwgbmV4dFNpYmxpbmcpIHsKICAgIHZhciBmaXJzdCA9IHNvdXJjZS5maXJzdENoaWxkOwogICAgdmFyIGxhc3QgPSBmaXJzdDsKICAgIHZhciBjdXJyZW50ID0gZmlyc3Q7CgogICAgd2hpbGUgKGN1cnJlbnQpIHsKICAgICAgdmFyIG5leHQgPSBjdXJyZW50Lm5leHRTaWJsaW5nOwogICAgICB0YXJnZXQuaW5zZXJ0QmVmb3JlKGN1cnJlbnQsIG5leHRTaWJsaW5nKTsKICAgICAgbGFzdCA9IGN1cnJlbnQ7CiAgICAgIGN1cnJlbnQgPSBuZXh0OwogICAgfQoKICAgIHJldHVybiBuZXcgQ29uY3JldGVCb3VuZHModGFyZ2V0LCBmaXJzdCwgbGFzdCk7CiAgfQoKICB2YXIgRE9NT3BlcmF0aW9ucyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIERPTU9wZXJhdGlvbnMoZG9jdW1lbnQpIHsKICAgICAgdGhpcy5kb2N1bWVudCA9IGRvY3VtZW50OwogICAgICB0aGlzLnNldHVwVXNlbGVzc0VsZW1lbnQoKTsKICAgIH0gLy8gc3BsaXQgaW50byBzZXBlcmF0ZSBtZXRob2Qgc28gdGhhdCBOb2RlRE9NVHJlZUNvbnN0cnVjdGlvbgogICAgLy8gY2FuIG92ZXJyaWRlIGl0LgoKCiAgICB2YXIgX3Byb3RvMjcgPSBET01PcGVyYXRpb25zLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yNy5zZXR1cFVzZWxlc3NFbGVtZW50ID0gZnVuY3Rpb24gc2V0dXBVc2VsZXNzRWxlbWVudCgpIHsKICAgICAgdGhpcy51c2VsZXNzRWxlbWVudCA9IHRoaXMuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICB9OwoKICAgIF9wcm90bzI3LmNyZWF0ZUVsZW1lbnQgPSBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHRhZywgY29udGV4dCkgewogICAgICB2YXIgaXNFbGVtZW50SW5TVkdOYW1lc3BhY2UsIGlzSFRNTEludGVncmF0aW9uUG9pbnQ7CgogICAgICBpZiAoY29udGV4dCkgewogICAgICAgIGlzRWxlbWVudEluU1ZHTmFtZXNwYWNlID0gY29udGV4dC5uYW1lc3BhY2VVUkkgPT09IFNWR19OQU1FU1BBQ0UgfHwgdGFnID09PSAnc3ZnJzsKICAgICAgICBpc0hUTUxJbnRlZ3JhdGlvblBvaW50ID0gU1ZHX0lOVEVHUkFUSU9OX1BPSU5UU1tjb250ZXh0LnRhZ05hbWVdOwogICAgICB9IGVsc2UgewogICAgICAgIGlzRWxlbWVudEluU1ZHTmFtZXNwYWNlID0gdGFnID09PSAnc3ZnJzsKICAgICAgICBpc0hUTUxJbnRlZ3JhdGlvblBvaW50ID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIGlmIChpc0VsZW1lbnRJblNWR05hbWVzcGFjZSAmJiAhaXNIVE1MSW50ZWdyYXRpb25Qb2ludCkgewogICAgICAgIC8vIEZJWE1FOiBUaGlzIGRvZXMgbm90IHByb3Blcmx5IGhhbmRsZSA8Zm9udD4gd2l0aCBjb2xvciwgZmFjZSwgb3IKICAgICAgICAvLyBzaXplIGF0dHJpYnV0ZXMsIHdoaWNoIGlzIGFsc28gZGlzYWxsb3dlZCBieSB0aGUgc3BlYy4gV2Ugc2hvdWxkIGZpeAogICAgICAgIC8vIHRoaXMuCiAgICAgICAgaWYgKEJMQUNLTElTVF9UQUJMRVt0YWddKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkNhbm5vdCBjcmVhdGUgYSAiICsgdGFnICsgIiBpbnNpZGUgYW4gU1ZHIGNvbnRleHQiKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhTVkdfTkFNRVNQQUNFLCB0YWcpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8yNy5pbnNlcnRCZWZvcmUgPSBmdW5jdGlvbiBpbnNlcnRCZWZvcmUocGFyZW50LCBub2RlLCByZWZlcmVuY2UpIHsKICAgICAgcGFyZW50Lmluc2VydEJlZm9yZShub2RlLCByZWZlcmVuY2UpOwogICAgfTsKCiAgICBfcHJvdG8yNy5pbnNlcnRIVE1MQmVmb3JlID0gZnVuY3Rpb24gaW5zZXJ0SFRNTEJlZm9yZShwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKSB7CiAgICAgIGlmIChodG1sID09PSAnJykgewogICAgICAgIHZhciBjb21tZW50ID0gdGhpcy5jcmVhdGVDb21tZW50KCcnKTsKICAgICAgICBwYXJlbnQuaW5zZXJ0QmVmb3JlKGNvbW1lbnQsIG5leHRTaWJsaW5nKTsKICAgICAgICByZXR1cm4gbmV3IENvbmNyZXRlQm91bmRzKHBhcmVudCwgY29tbWVudCwgY29tbWVudCk7CiAgICAgIH0KCiAgICAgIHZhciBwcmV2ID0gbmV4dFNpYmxpbmcgPyBuZXh0U2libGluZy5wcmV2aW91c1NpYmxpbmcgOiBwYXJlbnQubGFzdENoaWxkOwogICAgICB2YXIgbGFzdDsKCiAgICAgIGlmIChuZXh0U2libGluZyA9PT0gbnVsbCkgewogICAgICAgIHBhcmVudC5pbnNlcnRBZGphY2VudEhUTUwoImJlZm9yZWVuZCIKICAgICAgICAvKiBiZWZvcmVlbmQgKi8KICAgICAgICAsIGh0bWwpOwogICAgICAgIGxhc3QgPSBwYXJlbnQubGFzdENoaWxkOwogICAgICB9IGVsc2UgaWYgKG5leHRTaWJsaW5nIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHsKICAgICAgICBuZXh0U2libGluZy5pbnNlcnRBZGphY2VudEhUTUwoImJlZm9yZWJlZ2luIgogICAgICAgIC8qIGJlZm9yZWJlZ2luICovCiAgICAgICAgLCBodG1sKTsKICAgICAgICBsYXN0ID0gbmV4dFNpYmxpbmcucHJldmlvdXNTaWJsaW5nOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIE5vbi1lbGVtZW50IG5vZGVzIGRvIG5vdCBzdXBwb3J0IGluc2VydEFkamFjZW50SFRNTCwgc28gYWRkIGFuCiAgICAgICAgLy8gZWxlbWVudCBhbmQgY2FsbCBpdCBvbiB0aGF0IGVsZW1lbnQuIFRoZW4gcmVtb3ZlIHRoZSBlbGVtZW50LgogICAgICAgIC8vCiAgICAgICAgLy8gVGhpcyBhbHNvIHByb3RlY3RzIEVkZ2UsIElFIGFuZCBGaXJlZm94IHcvbyB0aGUgaW5zcGVjdG9yIG9wZW4KICAgICAgICAvLyBmcm9tIG1lcmdpbmcgYWRqYWNlbnQgdGV4dCBub2Rlcy4gU2VlIC4vY29tcGF0L3RleHQtbm9kZS1tZXJnaW5nLWZpeC50cwogICAgICAgIHZhciB1c2VsZXNzRWxlbWVudCA9IHRoaXMudXNlbGVzc0VsZW1lbnQ7CiAgICAgICAgcGFyZW50Lmluc2VydEJlZm9yZSh1c2VsZXNzRWxlbWVudCwgbmV4dFNpYmxpbmcpOwogICAgICAgIHVzZWxlc3NFbGVtZW50Lmluc2VydEFkamFjZW50SFRNTCgiYmVmb3JlYmVnaW4iCiAgICAgICAgLyogYmVmb3JlYmVnaW4gKi8KICAgICAgICAsIGh0bWwpOwogICAgICAgIGxhc3QgPSB1c2VsZXNzRWxlbWVudC5wcmV2aW91c1NpYmxpbmc7CiAgICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKHVzZWxlc3NFbGVtZW50KTsKICAgICAgfQoKICAgICAgdmFyIGZpcnN0ID0gcHJldiA/IHByZXYubmV4dFNpYmxpbmcgOiBwYXJlbnQuZmlyc3RDaGlsZDsKICAgICAgcmV0dXJuIG5ldyBDb25jcmV0ZUJvdW5kcyhwYXJlbnQsIGZpcnN0LCBsYXN0KTsKICAgIH07CgogICAgX3Byb3RvMjcuY3JlYXRlVGV4dE5vZGUgPSBmdW5jdGlvbiBjcmVhdGVUZXh0Tm9kZSh0ZXh0KSB7CiAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHRleHQpOwogICAgfTsKCiAgICBfcHJvdG8yNy5jcmVhdGVDb21tZW50ID0gZnVuY3Rpb24gY3JlYXRlQ29tbWVudChkYXRhKSB7CiAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZUNvbW1lbnQoZGF0YSk7CiAgICB9OwoKICAgIHJldHVybiBET01PcGVyYXRpb25zOwogIH0oKTsKCiAgdmFyIERPTTsKCiAgKGZ1bmN0aW9uIChET00pIHsKICAgIHZhciBUcmVlQ29uc3RydWN0aW9uID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uIChfRE9NT3BlcmF0aW9ucykgewogICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoVHJlZUNvbnN0cnVjdGlvbiwgX0RPTU9wZXJhdGlvbnMpOwoKICAgICAgZnVuY3Rpb24gVHJlZUNvbnN0cnVjdGlvbigpIHsKICAgICAgICByZXR1cm4gX0RPTU9wZXJhdGlvbnMuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICB9CgogICAgICB2YXIgX3Byb3RvMjggPSBUcmVlQ29uc3RydWN0aW9uLnByb3RvdHlwZTsKCiAgICAgIF9wcm90bzI4LmNyZWF0ZUVsZW1lbnROUyA9IGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnROUyhuYW1lc3BhY2UsIHRhZykgewogICAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhuYW1lc3BhY2UsIHRhZyk7CiAgICAgIH07CgogICAgICBfcHJvdG8yOC5zZXRBdHRyaWJ1dGUgPSBmdW5jdGlvbiBzZXRBdHRyaWJ1dGUoZWxlbWVudCwgbmFtZSwgdmFsdWUkJDEsIG5hbWVzcGFjZSkgewogICAgICAgIGlmIChuYW1lc3BhY2UgPT09IHZvaWQgMCkgewogICAgICAgICAgbmFtZXNwYWNlID0gbnVsbDsKICAgICAgICB9CgogICAgICAgIGlmIChuYW1lc3BhY2UpIHsKICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlTlMobmFtZXNwYWNlLCBuYW1lLCB2YWx1ZSQkMSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlJCQxKTsKICAgICAgICB9CiAgICAgIH07CgogICAgICByZXR1cm4gVHJlZUNvbnN0cnVjdGlvbjsKICAgIH0oRE9NT3BlcmF0aW9ucyk7CgogICAgRE9NLlRyZWVDb25zdHJ1Y3Rpb24gPSBUcmVlQ29uc3RydWN0aW9uOwogICAgdmFyIGFwcGxpZWRUcmVlQ29udHJ1Y3Rpb24gPSBUcmVlQ29uc3RydWN0aW9uOwogICAgYXBwbGllZFRyZWVDb250cnVjdGlvbiA9IGFwcGx5VGV4dE5vZGVNZXJnaW5nRml4KGRvYywgYXBwbGllZFRyZWVDb250cnVjdGlvbik7CiAgICBhcHBsaWVkVHJlZUNvbnRydWN0aW9uID0gYXBwbHlTVkdJbm5lckhUTUxGaXgoZG9jLCBhcHBsaWVkVHJlZUNvbnRydWN0aW9uLCBTVkdfTkFNRVNQQUNFKTsKICAgIERPTS5ET01UcmVlQ29uc3RydWN0aW9uID0gYXBwbGllZFRyZWVDb250cnVjdGlvbjsKICB9KShET00gfHwgKERPTSA9IHt9KSk7CgogIHZhciBET01DaGFuZ2VzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9ET01PcGVyYXRpb25zMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKERPTUNoYW5nZXMsIF9ET01PcGVyYXRpb25zMik7CgogICAgZnVuY3Rpb24gRE9NQ2hhbmdlcyhkb2N1bWVudCkgewogICAgICB2YXIgX3RoaXMxMzsKCiAgICAgIF90aGlzMTMgPSBfRE9NT3BlcmF0aW9uczIuY2FsbCh0aGlzLCBkb2N1bWVudCkgfHwgdGhpczsKICAgICAgX3RoaXMxMy5kb2N1bWVudCA9IGRvY3VtZW50OwogICAgICBfdGhpczEzLm5hbWVzcGFjZSA9IG51bGw7CiAgICAgIHJldHVybiBfdGhpczEzOwogICAgfQoKICAgIHZhciBfcHJvdG8yOSA9IERPTUNoYW5nZXMucHJvdG90eXBlOwoKICAgIF9wcm90bzI5LnNldEF0dHJpYnV0ZSA9IGZ1bmN0aW9uIHNldEF0dHJpYnV0ZShlbGVtZW50LCBuYW1lLCB2YWx1ZSQkMSkgewogICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzI5LnJlbW92ZUF0dHJpYnV0ZSA9IGZ1bmN0aW9uIHJlbW92ZUF0dHJpYnV0ZShlbGVtZW50LCBuYW1lKSB7CiAgICAgIGVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKG5hbWUpOwogICAgfTsKCiAgICBfcHJvdG8yOS5pbnNlcnRBZnRlciA9IGZ1bmN0aW9uIGluc2VydEFmdGVyKGVsZW1lbnQsIG5vZGUsIHJlZmVyZW5jZSkgewogICAgICB0aGlzLmluc2VydEJlZm9yZShlbGVtZW50LCBub2RlLCByZWZlcmVuY2UubmV4dFNpYmxpbmcpOwogICAgfTsKCiAgICByZXR1cm4gRE9NQ2hhbmdlczsKICB9KERPTU9wZXJhdGlvbnMpOwoKICBfZXhwb3J0cy5JRE9NQ2hhbmdlcyA9IERPTUNoYW5nZXM7CiAgdmFyIGhlbHBlciA9IERPTUNoYW5nZXM7CiAgaGVscGVyID0gYXBwbHlUZXh0Tm9kZU1lcmdpbmdGaXgoZG9jLCBoZWxwZXIpOwogIGhlbHBlciA9IGFwcGx5U1ZHSW5uZXJIVE1MRml4KGRvYywgaGVscGVyLCBTVkdfTkFNRVNQQUNFKTsKICB2YXIgaGVscGVyJDEgPSBoZWxwZXI7CiAgX2V4cG9ydHMuRE9NQ2hhbmdlcyA9IGhlbHBlciQxOwogIHZhciBET01UcmVlQ29uc3RydWN0aW9uID0gRE9NLkRPTVRyZWVDb25zdHJ1Y3Rpb247CiAgX2V4cG9ydHMuRE9NVHJlZUNvbnN0cnVjdGlvbiA9IERPTVRyZWVDb25zdHJ1Y3Rpb247CiAgdmFyIGJhZFByb3RvY29scyA9IFsnamF2YXNjcmlwdDonLCAndmJzY3JpcHQ6J107CiAgdmFyIGJhZFRhZ3MgPSBbJ0EnLCAnQk9EWScsICdMSU5LJywgJ0lNRycsICdJRlJBTUUnLCAnQkFTRScsICdGT1JNJ107CiAgdmFyIGJhZFRhZ3NGb3JEYXRhVVJJID0gWydFTUJFRCddOwogIHZhciBiYWRBdHRyaWJ1dGVzID0gWydocmVmJywgJ3NyYycsICdiYWNrZ3JvdW5kJywgJ2FjdGlvbiddOwogIHZhciBiYWRBdHRyaWJ1dGVzRm9yRGF0YVVSSSA9IFsnc3JjJ107CgogIGZ1bmN0aW9uIGhhcyhhcnJheSwgaXRlbSkgewogICAgcmV0dXJuIGFycmF5LmluZGV4T2YoaXRlbSkgIT09IC0xOwogIH0KCiAgZnVuY3Rpb24gY2hlY2tVUkkodGFnTmFtZSwgYXR0cmlidXRlKSB7CiAgICByZXR1cm4gKHRhZ05hbWUgPT09IG51bGwgfHwgaGFzKGJhZFRhZ3MsIHRhZ05hbWUpKSAmJiBoYXMoYmFkQXR0cmlidXRlcywgYXR0cmlidXRlKTsKICB9CgogIGZ1bmN0aW9uIGNoZWNrRGF0YVVSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpIHsKICAgIGlmICh0YWdOYW1lID09PSBudWxsKSByZXR1cm4gZmFsc2U7CiAgICByZXR1cm4gaGFzKGJhZFRhZ3NGb3JEYXRhVVJJLCB0YWdOYW1lKSAmJiBoYXMoYmFkQXR0cmlidXRlc0ZvckRhdGFVUkksIGF0dHJpYnV0ZSk7CiAgfQoKICBmdW5jdGlvbiByZXF1aXJlc1Nhbml0aXphdGlvbih0YWdOYW1lLCBhdHRyaWJ1dGUpIHsKICAgIHJldHVybiBjaGVja1VSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpIHx8IGNoZWNrRGF0YVVSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpOwogIH0KCiAgZnVuY3Rpb24gc2FuaXRpemVBdHRyaWJ1dGVWYWx1ZShlbnYsIGVsZW1lbnQsIGF0dHJpYnV0ZSwgdmFsdWUkJDEpIHsKICAgIHZhciB0YWdOYW1lID0gbnVsbDsKCiAgICBpZiAodmFsdWUkJDEgPT09IG51bGwgfHwgdmFsdWUkJDEgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gdmFsdWUkJDE7CiAgICB9CgogICAgaWYgKGlzU2FmZVN0cmluZyh2YWx1ZSQkMSkpIHsKICAgICAgcmV0dXJuIHZhbHVlJCQxLnRvSFRNTCgpOwogICAgfQoKICAgIGlmICghZWxlbWVudCkgewogICAgICB0YWdOYW1lID0gbnVsbDsKICAgIH0gZWxzZSB7CiAgICAgIHRhZ05hbWUgPSBlbGVtZW50LnRhZ05hbWUudG9VcHBlckNhc2UoKTsKICAgIH0KCiAgICB2YXIgc3RyID0gbm9ybWFsaXplU3RyaW5nVmFsdWUodmFsdWUkJDEpOwoKICAgIGlmIChjaGVja1VSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpKSB7CiAgICAgIHZhciBwcm90b2NvbCA9IGVudi5wcm90b2NvbEZvclVSTChzdHIpOwoKICAgICAgaWYgKGhhcyhiYWRQcm90b2NvbHMsIHByb3RvY29sKSkgewogICAgICAgIHJldHVybiAidW5zYWZlOiIgKyBzdHI7CiAgICAgIH0KICAgIH0KCiAgICBpZiAoY2hlY2tEYXRhVVJJKHRhZ05hbWUsIGF0dHJpYnV0ZSkpIHsKICAgICAgcmV0dXJuICJ1bnNhZmU6IiArIHN0cjsKICAgIH0KCiAgICByZXR1cm4gc3RyOwogIH0KICAvKgogICAqIEBtZXRob2Qgbm9ybWFsaXplUHJvcGVydHkKICAgKiBAcGFyYW0gZWxlbWVudCB7SFRNTEVsZW1lbnR9CiAgICogQHBhcmFtIHNsb3ROYW1lIHtTdHJpbmd9CiAgICogQHJldHVybnMge09iamVjdH0geyBuYW1lLCB0eXBlIH0KICAgKi8KCgogIGZ1bmN0aW9uIG5vcm1hbGl6ZVByb3BlcnR5KGVsZW1lbnQsIHNsb3ROYW1lKSB7CiAgICB2YXIgdHlwZSwgbm9ybWFsaXplZDsKCiAgICBpZiAoc2xvdE5hbWUgaW4gZWxlbWVudCkgewogICAgICBub3JtYWxpemVkID0gc2xvdE5hbWU7CiAgICAgIHR5cGUgPSAncHJvcCc7CiAgICB9IGVsc2UgewogICAgICB2YXIgbG93ZXIgPSBzbG90TmFtZS50b0xvd2VyQ2FzZSgpOwoKICAgICAgaWYgKGxvd2VyIGluIGVsZW1lbnQpIHsKICAgICAgICB0eXBlID0gJ3Byb3AnOwogICAgICAgIG5vcm1hbGl6ZWQgPSBsb3dlcjsKICAgICAgfSBlbHNlIHsKICAgICAgICB0eXBlID0gJ2F0dHInOwogICAgICAgIG5vcm1hbGl6ZWQgPSBzbG90TmFtZTsKICAgICAgfQogICAgfQoKICAgIGlmICh0eXBlID09PSAncHJvcCcgJiYgKG5vcm1hbGl6ZWQudG9Mb3dlckNhc2UoKSA9PT0gJ3N0eWxlJyB8fCBwcmVmZXJBdHRyKGVsZW1lbnQudGFnTmFtZSwgbm9ybWFsaXplZCkpKSB7CiAgICAgIHR5cGUgPSAnYXR0cic7CiAgICB9CgogICAgcmV0dXJuIHsKICAgICAgbm9ybWFsaXplZDogbm9ybWFsaXplZCwKICAgICAgdHlwZTogdHlwZQogICAgfTsKICB9IC8vIHByb3BlcnRpZXMgdGhhdCBNVVNUIGJlIHNldCBhcyBhdHRyaWJ1dGVzLCBkdWUgdG86CiAgLy8gKiBicm93c2VyIGJ1ZwogIC8vICogc3RyYW5nZSBzcGVjIG91dGxpZXIKCgogIHZhciBBVFRSX09WRVJSSURFUyA9IHsKICAgIElOUFVUOiB7CiAgICAgIGZvcm06IHRydWUsCiAgICAgIC8vIENocm9tZSA0Ni4wLjI0NjQuMDogJ2F1dG9jb3JyZWN0JyBpbiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbnB1dCcpID09PSBmYWxzZQogICAgICAvLyBTYWZhcmkgOC4wLjc6ICdhdXRvY29ycmVjdCcgaW4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKSA9PT0gZmFsc2UKICAgICAgLy8gTW9iaWxlIFNhZmFyaSAoaU9TIDguNCBzaW11bGF0b3IpOiAnYXV0b2NvcnJlY3QnIGluIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0JykgPT09IHRydWUKICAgICAgYXV0b2NvcnJlY3Q6IHRydWUsCiAgICAgIC8vIENocm9tZSA1NC4wLjI4NDAuOTg6ICdsaXN0JyBpbiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbnB1dCcpID09PSB0cnVlCiAgICAgIC8vIFNhZmFyaSA5LjEuMzogJ2xpc3QnIGluIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0JykgPT09IGZhbHNlCiAgICAgIGxpc3Q6IHRydWUKICAgIH0sCiAgICAvLyBlbGVtZW50LmZvcm0gaXMgYWN0dWFsbHkgYSBsZWdpdGltYXRlIHJlYWRPbmx5IHByb3BlcnR5LCB0aGF0IGlzIHRvIGJlCiAgICAvLyBtdXRhdGVkLCBidXQgbXVzdCBiZSBtdXRhdGVkIGJ5IHNldEF0dHJpYnV0ZS4uLgogICAgU0VMRUNUOiB7CiAgICAgIGZvcm06IHRydWUKICAgIH0sCiAgICBPUFRJT046IHsKICAgICAgZm9ybTogdHJ1ZQogICAgfSwKICAgIFRFWFRBUkVBOiB7CiAgICAgIGZvcm06IHRydWUKICAgIH0sCiAgICBMQUJFTDogewogICAgICBmb3JtOiB0cnVlCiAgICB9LAogICAgRklFTERTRVQ6IHsKICAgICAgZm9ybTogdHJ1ZQogICAgfSwKICAgIExFR0VORDogewogICAgICBmb3JtOiB0cnVlCiAgICB9LAogICAgT0JKRUNUOiB7CiAgICAgIGZvcm06IHRydWUKICAgIH0sCiAgICBCVVRUT046IHsKICAgICAgZm9ybTogdHJ1ZQogICAgfQogIH07CgogIGZ1bmN0aW9uIHByZWZlckF0dHIodGFnTmFtZSwgcHJvcE5hbWUpIHsKICAgIHZhciB0YWcgPSBBVFRSX09WRVJSSURFU1t0YWdOYW1lLnRvVXBwZXJDYXNlKCldOwogICAgcmV0dXJuIHRhZyAmJiB0YWdbcHJvcE5hbWUudG9Mb3dlckNhc2UoKV0gfHwgZmFsc2U7CiAgfQoKICBmdW5jdGlvbiBkeW5hbWljQXR0cmlidXRlKGVsZW1lbnQsIGF0dHIsIG5hbWVzcGFjZSkgewogICAgdmFyIHRhZ05hbWUgPSBlbGVtZW50LnRhZ05hbWUsCiAgICAgICAgbmFtZXNwYWNlVVJJID0gZWxlbWVudC5uYW1lc3BhY2VVUkk7CiAgICB2YXIgYXR0cmlidXRlID0gewogICAgICBlbGVtZW50OiBlbGVtZW50LAogICAgICBuYW1lOiBhdHRyLAogICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZQogICAgfTsKCiAgICBpZiAobmFtZXNwYWNlVVJJID09PSBTVkdfTkFNRVNQQUNFKSB7CiAgICAgIHJldHVybiBidWlsZER5bmFtaWNBdHRyaWJ1dGUodGFnTmFtZSwgYXR0ciwgYXR0cmlidXRlKTsKICAgIH0KCiAgICB2YXIgX25vcm1hbGl6ZVByb3BlcnR5ID0gbm9ybWFsaXplUHJvcGVydHkoZWxlbWVudCwgYXR0ciksCiAgICAgICAgdHlwZSA9IF9ub3JtYWxpemVQcm9wZXJ0eS50eXBlLAogICAgICAgIG5vcm1hbGl6ZWQgPSBfbm9ybWFsaXplUHJvcGVydHkubm9ybWFsaXplZDsKCiAgICBpZiAodHlwZSA9PT0gJ2F0dHInKSB7CiAgICAgIHJldHVybiBidWlsZER5bmFtaWNBdHRyaWJ1dGUodGFnTmFtZSwgbm9ybWFsaXplZCwgYXR0cmlidXRlKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBidWlsZER5bmFtaWNQcm9wZXJ0eSh0YWdOYW1lLCBub3JtYWxpemVkLCBhdHRyaWJ1dGUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gYnVpbGREeW5hbWljQXR0cmlidXRlKHRhZ05hbWUsIG5hbWUsIGF0dHJpYnV0ZSkgewogICAgaWYgKHJlcXVpcmVzU2FuaXRpemF0aW9uKHRhZ05hbWUsIG5hbWUpKSB7CiAgICAgIHJldHVybiBuZXcgU2FmZUR5bmFtaWNBdHRyaWJ1dGUoYXR0cmlidXRlKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBuZXcgU2ltcGxlRHluYW1pY0F0dHJpYnV0ZShhdHRyaWJ1dGUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gYnVpbGREeW5hbWljUHJvcGVydHkodGFnTmFtZSwgbmFtZSwgYXR0cmlidXRlKSB7CiAgICBpZiAocmVxdWlyZXNTYW5pdGl6YXRpb24odGFnTmFtZSwgbmFtZSkpIHsKICAgICAgcmV0dXJuIG5ldyBTYWZlRHluYW1pY1Byb3BlcnR5KG5hbWUsIGF0dHJpYnV0ZSk7CiAgICB9CgogICAgaWYgKGlzVXNlcklucHV0VmFsdWUodGFnTmFtZSwgbmFtZSkpIHsKICAgICAgcmV0dXJuIG5ldyBJbnB1dFZhbHVlRHluYW1pY0F0dHJpYnV0ZShuYW1lLCBhdHRyaWJ1dGUpOwogICAgfQoKICAgIGlmIChpc09wdGlvblNlbGVjdGVkKHRhZ05hbWUsIG5hbWUpKSB7CiAgICAgIHJldHVybiBuZXcgT3B0aW9uU2VsZWN0ZWREeW5hbWljQXR0cmlidXRlKG5hbWUsIGF0dHJpYnV0ZSk7CiAgICB9CgogICAgcmV0dXJuIG5ldyBEZWZhdWx0RHluYW1pY1Byb3BlcnR5KG5hbWUsIGF0dHJpYnV0ZSk7CiAgfQoKICB2YXIgRHluYW1pY0F0dHJpYnV0ZSA9IGZ1bmN0aW9uIER5bmFtaWNBdHRyaWJ1dGUoYXR0cmlidXRlKSB7CiAgICB0aGlzLmF0dHJpYnV0ZSA9IGF0dHJpYnV0ZTsKICB9OwoKICBfZXhwb3J0cy5EeW5hbWljQXR0cmlidXRlID0gRHluYW1pY0F0dHJpYnV0ZTsKCiAgdmFyIFNpbXBsZUR5bmFtaWNBdHRyaWJ1dGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0R5bmFtaWNBdHRyaWJ1dGUpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShTaW1wbGVEeW5hbWljQXR0cmlidXRlLCBfRHluYW1pY0F0dHJpYnV0ZSk7CgogICAgZnVuY3Rpb24gU2ltcGxlRHluYW1pY0F0dHJpYnV0ZSgpIHsKICAgICAgcmV0dXJuIF9EeW5hbWljQXR0cmlidXRlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvMzAgPSBTaW1wbGVEeW5hbWljQXR0cmlidXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zMC5zZXQgPSBmdW5jdGlvbiBzZXQoZG9tLCB2YWx1ZSQkMSwgX2VudikgewogICAgICB2YXIgbm9ybWFsaXplZFZhbHVlID0gbm9ybWFsaXplVmFsdWUodmFsdWUkJDEpOwoKICAgICAgaWYgKG5vcm1hbGl6ZWRWYWx1ZSAhPT0gbnVsbCkgewogICAgICAgIHZhciBfdGhpcyRhdHRyaWJ1dGUgPSB0aGlzLmF0dHJpYnV0ZSwKICAgICAgICAgICAgbmFtZSA9IF90aGlzJGF0dHJpYnV0ZS5uYW1lLAogICAgICAgICAgICBuYW1lc3BhY2UgPSBfdGhpcyRhdHRyaWJ1dGUubmFtZXNwYWNlOwoKICAgICAgICBkb20uX19zZXRBdHRyaWJ1dGUobmFtZSwgbm9ybWFsaXplZFZhbHVlLCBuYW1lc3BhY2UpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzMwLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZSh2YWx1ZSQkMSwgX2VudikgewogICAgICB2YXIgbm9ybWFsaXplZFZhbHVlID0gbm9ybWFsaXplVmFsdWUodmFsdWUkJDEpOwogICAgICB2YXIgX3RoaXMkYXR0cmlidXRlMiA9IHRoaXMuYXR0cmlidXRlLAogICAgICAgICAgZWxlbWVudCA9IF90aGlzJGF0dHJpYnV0ZTIuZWxlbWVudCwKICAgICAgICAgIG5hbWUgPSBfdGhpcyRhdHRyaWJ1dGUyLm5hbWU7CgogICAgICBpZiAobm9ybWFsaXplZFZhbHVlID09PSBudWxsKSB7CiAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUobmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUobmFtZSwgbm9ybWFsaXplZFZhbHVlKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gU2ltcGxlRHluYW1pY0F0dHJpYnV0ZTsKICB9KER5bmFtaWNBdHRyaWJ1dGUpOwoKICBfZXhwb3J0cy5TaW1wbGVEeW5hbWljQXR0cmlidXRlID0gU2ltcGxlRHluYW1pY0F0dHJpYnV0ZTsKCiAgdmFyIERlZmF1bHREeW5hbWljUHJvcGVydHkgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0R5bmFtaWNBdHRyaWJ1dGUyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRGVmYXVsdER5bmFtaWNQcm9wZXJ0eSwgX0R5bmFtaWNBdHRyaWJ1dGUyKTsKCiAgICBmdW5jdGlvbiBEZWZhdWx0RHluYW1pY1Byb3BlcnR5KG5vcm1hbGl6ZWROYW1lLCBhdHRyaWJ1dGUpIHsKICAgICAgdmFyIF90aGlzMTQ7CgogICAgICBfdGhpczE0ID0gX0R5bmFtaWNBdHRyaWJ1dGUyLmNhbGwodGhpcywgYXR0cmlidXRlKSB8fCB0aGlzOwogICAgICBfdGhpczE0Lm5vcm1hbGl6ZWROYW1lID0gbm9ybWFsaXplZE5hbWU7CiAgICAgIHJldHVybiBfdGhpczE0OwogICAgfQoKICAgIHZhciBfcHJvdG8zMSA9IERlZmF1bHREeW5hbWljUHJvcGVydHkucHJvdG90eXBlOwoKICAgIF9wcm90bzMxLnNldCA9IGZ1bmN0aW9uIHNldChkb20sIHZhbHVlJCQxLCBfZW52KSB7CiAgICAgIGlmICh2YWx1ZSQkMSAhPT0gbnVsbCAmJiB2YWx1ZSQkMSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlJCQxOwoKICAgICAgICBkb20uX19zZXRQcm9wZXJ0eSh0aGlzLm5vcm1hbGl6ZWROYW1lLCB2YWx1ZSQkMSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMzEudXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKHZhbHVlJCQxLCBfZW52KSB7CiAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5hdHRyaWJ1dGUuZWxlbWVudDsKCiAgICAgIGlmICh0aGlzLnZhbHVlICE9PSB2YWx1ZSQkMSkgewogICAgICAgIGVsZW1lbnRbdGhpcy5ub3JtYWxpemVkTmFtZV0gPSB0aGlzLnZhbHVlID0gdmFsdWUkJDE7CgogICAgICAgIGlmICh2YWx1ZSQkMSA9PT0gbnVsbCB8fCB2YWx1ZSQkMSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB0aGlzLnJlbW92ZUF0dHJpYnV0ZSgpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zMS5yZW1vdmVBdHRyaWJ1dGUgPSBmdW5jdGlvbiByZW1vdmVBdHRyaWJ1dGUoKSB7CiAgICAgIC8vIFRPRE8gdGhpcyBzdWNrcyBidXQgdG8gcHJlc2VydmUgcHJvcGVydGllcyBmaXJzdCBhbmQgdG8gbWVldCBjdXJyZW50CiAgICAgIC8vIHNlbWFudGljcyB3ZSBtdXN0IGRvIHRoaXMuCiAgICAgIHZhciBfdGhpcyRhdHRyaWJ1dGUzID0gdGhpcy5hdHRyaWJ1dGUsCiAgICAgICAgICBlbGVtZW50ID0gX3RoaXMkYXR0cmlidXRlMy5lbGVtZW50LAogICAgICAgICAgbmFtZXNwYWNlID0gX3RoaXMkYXR0cmlidXRlMy5uYW1lc3BhY2U7CgogICAgICBpZiAobmFtZXNwYWNlKSB7CiAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGVOUyhuYW1lc3BhY2UsIHRoaXMubm9ybWFsaXplZE5hbWUpOwogICAgICB9IGVsc2UgewogICAgICAgIGVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKHRoaXMubm9ybWFsaXplZE5hbWUpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBEZWZhdWx0RHluYW1pY1Byb3BlcnR5OwogIH0oRHluYW1pY0F0dHJpYnV0ZSk7CgogIHZhciBTYWZlRHluYW1pY1Byb3BlcnR5ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9EZWZhdWx0RHluYW1pY1Byb3BlcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFNhZmVEeW5hbWljUHJvcGVydHksIF9EZWZhdWx0RHluYW1pY1Byb3Blcik7CgogICAgZnVuY3Rpb24gU2FmZUR5bmFtaWNQcm9wZXJ0eSgpIHsKICAgICAgcmV0dXJuIF9EZWZhdWx0RHluYW1pY1Byb3Blci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzMyID0gU2FmZUR5bmFtaWNQcm9wZXJ0eS5wcm90b3R5cGU7CgogICAgX3Byb3RvMzIuc2V0ID0gZnVuY3Rpb24gc2V0KGRvbSwgdmFsdWUkJDEsIGVudikgewogICAgICB2YXIgX3RoaXMkYXR0cmlidXRlNCA9IHRoaXMuYXR0cmlidXRlLAogICAgICAgICAgZWxlbWVudCA9IF90aGlzJGF0dHJpYnV0ZTQuZWxlbWVudCwKICAgICAgICAgIG5hbWUgPSBfdGhpcyRhdHRyaWJ1dGU0Lm5hbWU7CiAgICAgIHZhciBzYW5pdGl6ZWQgPSBzYW5pdGl6ZUF0dHJpYnV0ZVZhbHVlKGVudiwgZWxlbWVudCwgbmFtZSwgdmFsdWUkJDEpOwoKICAgICAgX0RlZmF1bHREeW5hbWljUHJvcGVyLnByb3RvdHlwZS5zZXQuY2FsbCh0aGlzLCBkb20sIHNhbml0aXplZCwgZW52KTsKICAgIH07CgogICAgX3Byb3RvMzIudXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKHZhbHVlJCQxLCBlbnYpIHsKICAgICAgdmFyIF90aGlzJGF0dHJpYnV0ZTUgPSB0aGlzLmF0dHJpYnV0ZSwKICAgICAgICAgIGVsZW1lbnQgPSBfdGhpcyRhdHRyaWJ1dGU1LmVsZW1lbnQsCiAgICAgICAgICBuYW1lID0gX3RoaXMkYXR0cmlidXRlNS5uYW1lOwogICAgICB2YXIgc2FuaXRpemVkID0gc2FuaXRpemVBdHRyaWJ1dGVWYWx1ZShlbnYsIGVsZW1lbnQsIG5hbWUsIHZhbHVlJCQxKTsKCiAgICAgIF9EZWZhdWx0RHluYW1pY1Byb3Blci5wcm90b3R5cGUudXBkYXRlLmNhbGwodGhpcywgc2FuaXRpemVkLCBlbnYpOwogICAgfTsKCiAgICByZXR1cm4gU2FmZUR5bmFtaWNQcm9wZXJ0eTsKICB9KERlZmF1bHREeW5hbWljUHJvcGVydHkpOwoKICB2YXIgU2FmZUR5bmFtaWNBdHRyaWJ1dGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1NpbXBsZUR5bmFtaWNBdHRyaWJ1KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoU2FmZUR5bmFtaWNBdHRyaWJ1dGUsIF9TaW1wbGVEeW5hbWljQXR0cmlidSk7CgogICAgZnVuY3Rpb24gU2FmZUR5bmFtaWNBdHRyaWJ1dGUoKSB7CiAgICAgIHJldHVybiBfU2ltcGxlRHluYW1pY0F0dHJpYnUuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8zMyA9IFNhZmVEeW5hbWljQXR0cmlidXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zMy5zZXQgPSBmdW5jdGlvbiBzZXQoZG9tLCB2YWx1ZSQkMSwgZW52KSB7CiAgICAgIHZhciBfdGhpcyRhdHRyaWJ1dGU2ID0gdGhpcy5hdHRyaWJ1dGUsCiAgICAgICAgICBlbGVtZW50ID0gX3RoaXMkYXR0cmlidXRlNi5lbGVtZW50LAogICAgICAgICAgbmFtZSA9IF90aGlzJGF0dHJpYnV0ZTYubmFtZTsKICAgICAgdmFyIHNhbml0aXplZCA9IHNhbml0aXplQXR0cmlidXRlVmFsdWUoZW52LCBlbGVtZW50LCBuYW1lLCB2YWx1ZSQkMSk7CgogICAgICBfU2ltcGxlRHluYW1pY0F0dHJpYnUucHJvdG90eXBlLnNldC5jYWxsKHRoaXMsIGRvbSwgc2FuaXRpemVkLCBlbnYpOwogICAgfTsKCiAgICBfcHJvdG8zMy51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUodmFsdWUkJDEsIGVudikgewogICAgICB2YXIgX3RoaXMkYXR0cmlidXRlNyA9IHRoaXMuYXR0cmlidXRlLAogICAgICAgICAgZWxlbWVudCA9IF90aGlzJGF0dHJpYnV0ZTcuZWxlbWVudCwKICAgICAgICAgIG5hbWUgPSBfdGhpcyRhdHRyaWJ1dGU3Lm5hbWU7CiAgICAgIHZhciBzYW5pdGl6ZWQgPSBzYW5pdGl6ZUF0dHJpYnV0ZVZhbHVlKGVudiwgZWxlbWVudCwgbmFtZSwgdmFsdWUkJDEpOwoKICAgICAgX1NpbXBsZUR5bmFtaWNBdHRyaWJ1LnByb3RvdHlwZS51cGRhdGUuY2FsbCh0aGlzLCBzYW5pdGl6ZWQsIGVudik7CiAgICB9OwoKICAgIHJldHVybiBTYWZlRHluYW1pY0F0dHJpYnV0ZTsKICB9KFNpbXBsZUR5bmFtaWNBdHRyaWJ1dGUpOwoKICB2YXIgSW5wdXRWYWx1ZUR5bmFtaWNBdHRyaWJ1dGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0RlZmF1bHREeW5hbWljUHJvcGVyMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKElucHV0VmFsdWVEeW5hbWljQXR0cmlidXRlLCBfRGVmYXVsdER5bmFtaWNQcm9wZXIyKTsKCiAgICBmdW5jdGlvbiBJbnB1dFZhbHVlRHluYW1pY0F0dHJpYnV0ZSgpIHsKICAgICAgcmV0dXJuIF9EZWZhdWx0RHluYW1pY1Byb3BlcjIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8zNCA9IElucHV0VmFsdWVEeW5hbWljQXR0cmlidXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zNC5zZXQgPSBmdW5jdGlvbiBzZXQoZG9tLCB2YWx1ZSQkMSkgewogICAgICBkb20uX19zZXRQcm9wZXJ0eSgndmFsdWUnLCBub3JtYWxpemVTdHJpbmdWYWx1ZSh2YWx1ZSQkMSkpOwogICAgfTsKCiAgICBfcHJvdG8zNC51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUodmFsdWUkJDEpIHsKICAgICAgdmFyIGlucHV0ID0gdGhpcy5hdHRyaWJ1dGUuZWxlbWVudDsKICAgICAgdmFyIGN1cnJlbnRWYWx1ZSA9IGlucHV0LnZhbHVlOwogICAgICB2YXIgbm9ybWFsaXplZFZhbHVlID0gbm9ybWFsaXplU3RyaW5nVmFsdWUodmFsdWUkJDEpOwoKICAgICAgaWYgKGN1cnJlbnRWYWx1ZSAhPT0gbm9ybWFsaXplZFZhbHVlKSB7CiAgICAgICAgaW5wdXQudmFsdWUgPSBub3JtYWxpemVkVmFsdWU7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIElucHV0VmFsdWVEeW5hbWljQXR0cmlidXRlOwogIH0oRGVmYXVsdER5bmFtaWNQcm9wZXJ0eSk7CgogIHZhciBPcHRpb25TZWxlY3RlZER5bmFtaWNBdHRyaWJ1dGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0RlZmF1bHREeW5hbWljUHJvcGVyMykgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE9wdGlvblNlbGVjdGVkRHluYW1pY0F0dHJpYnV0ZSwgX0RlZmF1bHREeW5hbWljUHJvcGVyMyk7CgogICAgZnVuY3Rpb24gT3B0aW9uU2VsZWN0ZWREeW5hbWljQXR0cmlidXRlKCkgewogICAgICByZXR1cm4gX0RlZmF1bHREeW5hbWljUHJvcGVyMy5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzM1ID0gT3B0aW9uU2VsZWN0ZWREeW5hbWljQXR0cmlidXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zNS5zZXQgPSBmdW5jdGlvbiBzZXQoZG9tLCB2YWx1ZSQkMSkgewogICAgICBpZiAodmFsdWUkJDEgIT09IG51bGwgJiYgdmFsdWUkJDEgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSQkMSAhPT0gZmFsc2UpIHsKICAgICAgICBkb20uX19zZXRQcm9wZXJ0eSgnc2VsZWN0ZWQnLCB0cnVlKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zNS51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUodmFsdWUkJDEpIHsKICAgICAgdmFyIG9wdGlvbiA9IHRoaXMuYXR0cmlidXRlLmVsZW1lbnQ7CgogICAgICBpZiAodmFsdWUkJDEpIHsKICAgICAgICBvcHRpb24uc2VsZWN0ZWQgPSB0cnVlOwogICAgICB9IGVsc2UgewogICAgICAgIG9wdGlvbi5zZWxlY3RlZCA9IGZhbHNlOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBPcHRpb25TZWxlY3RlZER5bmFtaWNBdHRyaWJ1dGU7CiAgfShEZWZhdWx0RHluYW1pY1Byb3BlcnR5KTsKCiAgZnVuY3Rpb24gaXNPcHRpb25TZWxlY3RlZCh0YWdOYW1lLCBhdHRyaWJ1dGUpIHsKICAgIHJldHVybiB0YWdOYW1lID09PSAnT1BUSU9OJyAmJiBhdHRyaWJ1dGUgPT09ICdzZWxlY3RlZCc7CiAgfQoKICBmdW5jdGlvbiBpc1VzZXJJbnB1dFZhbHVlKHRhZ05hbWUsIGF0dHJpYnV0ZSkgewogICAgcmV0dXJuICh0YWdOYW1lID09PSAnSU5QVVQnIHx8IHRhZ05hbWUgPT09ICdURVhUQVJFQScpICYmIGF0dHJpYnV0ZSA9PT0gJ3ZhbHVlJzsKICB9CgogIGZ1bmN0aW9uIG5vcm1hbGl6ZVZhbHVlKHZhbHVlJCQxKSB7CiAgICBpZiAodmFsdWUkJDEgPT09IGZhbHNlIHx8IHZhbHVlJCQxID09PSB1bmRlZmluZWQgfHwgdmFsdWUkJDEgPT09IG51bGwgfHwgdHlwZW9mIHZhbHVlJCQxLnRvU3RyaW5nID09PSAndW5kZWZpbmVkJykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KCiAgICBpZiAodmFsdWUkJDEgPT09IHRydWUpIHsKICAgICAgcmV0dXJuICcnOwogICAgfSAvLyBvbmNsaWNrIGZ1bmN0aW9uIGV0YyBpbiBTU1IKCgogICAgaWYgKHR5cGVvZiB2YWx1ZSQkMSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KCiAgICByZXR1cm4gU3RyaW5nKHZhbHVlJCQxKTsKICB9CgogIHZhciBTY29wZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFNjb3BlKCAvLyB0aGUgMHRoIHNsb3QgaXMgYHNlbGZgCiAgICBzbG90cywgY2FsbGVyU2NvcGUsIC8vIG5hbWVkIGFyZ3VtZW50cyBhbmQgYmxvY2tzIHBhc3NlZCB0byBhIGxheW91dCB0aGF0IHVzZXMgZXZhbAogICAgZXZhbFNjb3BlLCAvLyBsb2NhbHMgaW4gc2NvcGUgd2hlbiB0aGUgcGFydGlhbCB3YXMgaW52b2tlZAogICAgcGFydGlhbE1hcCkgewogICAgICB0aGlzLnNsb3RzID0gc2xvdHM7CiAgICAgIHRoaXMuY2FsbGVyU2NvcGUgPSBjYWxsZXJTY29wZTsKICAgICAgdGhpcy5ldmFsU2NvcGUgPSBldmFsU2NvcGU7CiAgICAgIHRoaXMucGFydGlhbE1hcCA9IHBhcnRpYWxNYXA7CiAgICB9CgogICAgU2NvcGUucm9vdCA9IGZ1bmN0aW9uIHJvb3Qoc2VsZiwgc2l6ZSkgewogICAgICBpZiAoc2l6ZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgc2l6ZSA9IDA7CiAgICAgIH0KCiAgICAgIHZhciByZWZzID0gbmV3IEFycmF5KHNpemUgKyAxKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDw9IHNpemU7IGkrKykgewogICAgICAgIHJlZnNbaV0gPSBVTkRFRklORURfUkVGRVJFTkNFOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IFNjb3BlKHJlZnMsIG51bGwsIG51bGwsIG51bGwpLmluaXQoewogICAgICAgIHNlbGY6IHNlbGYKICAgICAgfSk7CiAgICB9OwoKICAgIFNjb3BlLnNpemVkID0gZnVuY3Rpb24gc2l6ZWQoc2l6ZSkgewogICAgICBpZiAoc2l6ZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgc2l6ZSA9IDA7CiAgICAgIH0KCiAgICAgIHZhciByZWZzID0gbmV3IEFycmF5KHNpemUgKyAxKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDw9IHNpemU7IGkrKykgewogICAgICAgIHJlZnNbaV0gPSBVTkRFRklORURfUkVGRVJFTkNFOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IFNjb3BlKHJlZnMsIG51bGwsIG51bGwsIG51bGwpOwogICAgfTsKCiAgICB2YXIgX3Byb3RvMzYgPSBTY29wZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMzYuaW5pdCA9IGZ1bmN0aW9uIGluaXQoX3JlZjU1KSB7CiAgICAgIHZhciBzZWxmID0gX3JlZjU1LnNlbGY7CiAgICAgIHRoaXMuc2xvdHNbMF0gPSBzZWxmOwogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgX3Byb3RvMzYuZ2V0U2VsZiA9IGZ1bmN0aW9uIGdldFNlbGYoKSB7CiAgICAgIHJldHVybiB0aGlzLmdldCgwKTsKICAgIH07CgogICAgX3Byb3RvMzYuZ2V0U3ltYm9sID0gZnVuY3Rpb24gZ2V0U3ltYm9sKHN5bWJvbCkgewogICAgICByZXR1cm4gdGhpcy5nZXQoc3ltYm9sKTsKICAgIH07CgogICAgX3Byb3RvMzYuZ2V0QmxvY2sgPSBmdW5jdGlvbiBnZXRCbG9jayhzeW1ib2wpIHsKICAgICAgdmFyIGJsb2NrID0gdGhpcy5nZXQoc3ltYm9sKTsKICAgICAgcmV0dXJuIGJsb2NrID09PSBVTkRFRklORURfUkVGRVJFTkNFID8gbnVsbCA6IGJsb2NrOwogICAgfTsKCiAgICBfcHJvdG8zNi5nZXRFdmFsU2NvcGUgPSBmdW5jdGlvbiBnZXRFdmFsU2NvcGUoKSB7CiAgICAgIHJldHVybiB0aGlzLmV2YWxTY29wZTsKICAgIH07CgogICAgX3Byb3RvMzYuZ2V0UGFydGlhbE1hcCA9IGZ1bmN0aW9uIGdldFBhcnRpYWxNYXAoKSB7CiAgICAgIHJldHVybiB0aGlzLnBhcnRpYWxNYXA7CiAgICB9OwoKICAgIF9wcm90bzM2LmJpbmQgPSBmdW5jdGlvbiBiaW5kKHN5bWJvbCwgdmFsdWUkJDEpIHsKICAgICAgdGhpcy5zZXQoc3ltYm9sLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzM2LmJpbmRTZWxmID0gZnVuY3Rpb24gYmluZFNlbGYoc2VsZikgewogICAgICB0aGlzLnNldCgwLCBzZWxmKTsKICAgIH07CgogICAgX3Byb3RvMzYuYmluZFN5bWJvbCA9IGZ1bmN0aW9uIGJpbmRTeW1ib2woc3ltYm9sLCB2YWx1ZSQkMSkgewogICAgICB0aGlzLnNldChzeW1ib2wsIHZhbHVlJCQxKTsKICAgIH07CgogICAgX3Byb3RvMzYuYmluZEJsb2NrID0gZnVuY3Rpb24gYmluZEJsb2NrKHN5bWJvbCwgdmFsdWUkJDEpIHsKICAgICAgdGhpcy5zZXQoc3ltYm9sLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzM2LmJpbmRFdmFsU2NvcGUgPSBmdW5jdGlvbiBiaW5kRXZhbFNjb3BlKG1hcCkgewogICAgICB0aGlzLmV2YWxTY29wZSA9IG1hcDsKICAgIH07CgogICAgX3Byb3RvMzYuYmluZFBhcnRpYWxNYXAgPSBmdW5jdGlvbiBiaW5kUGFydGlhbE1hcChtYXApIHsKICAgICAgdGhpcy5wYXJ0aWFsTWFwID0gbWFwOwogICAgfTsKCiAgICBfcHJvdG8zNi5iaW5kQ2FsbGVyU2NvcGUgPSBmdW5jdGlvbiBiaW5kQ2FsbGVyU2NvcGUoc2NvcGUpIHsKICAgICAgdGhpcy5jYWxsZXJTY29wZSA9IHNjb3BlOwogICAgfTsKCiAgICBfcHJvdG8zNi5nZXRDYWxsZXJTY29wZSA9IGZ1bmN0aW9uIGdldENhbGxlclNjb3BlKCkgewogICAgICByZXR1cm4gdGhpcy5jYWxsZXJTY29wZTsKICAgIH07CgogICAgX3Byb3RvMzYuY2hpbGQgPSBmdW5jdGlvbiBjaGlsZCgpIHsKICAgICAgcmV0dXJuIG5ldyBTY29wZSh0aGlzLnNsb3RzLnNsaWNlKCksIHRoaXMuY2FsbGVyU2NvcGUsIHRoaXMuZXZhbFNjb3BlLCB0aGlzLnBhcnRpYWxNYXApOwogICAgfTsKCiAgICBfcHJvdG8zNi5nZXQgPSBmdW5jdGlvbiBnZXQoaW5kZXgpIHsKICAgICAgaWYgKGluZGV4ID49IHRoaXMuc2xvdHMubGVuZ3RoKSB7CiAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoIkJVRzogY2Fubm90IGdldCAkIiArIGluZGV4ICsgIiBmcm9tIHNjb3BlOyBsZW5ndGg9IiArIHRoaXMuc2xvdHMubGVuZ3RoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuc2xvdHNbaW5kZXhdOwogICAgfTsKCiAgICBfcHJvdG8zNi5zZXQgPSBmdW5jdGlvbiBzZXQoaW5kZXgsIHZhbHVlJCQxKSB7CiAgICAgIGlmIChpbmRleCA+PSB0aGlzLnNsb3RzLmxlbmd0aCkgewogICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCJCVUc6IGNhbm5vdCBnZXQgJCIgKyBpbmRleCArICIgZnJvbSBzY29wZTsgbGVuZ3RoPSIgKyB0aGlzLnNsb3RzLmxlbmd0aCk7CiAgICAgIH0KCiAgICAgIHRoaXMuc2xvdHNbaW5kZXhdID0gdmFsdWUkJDE7CiAgICB9OwoKICAgIHJldHVybiBTY29wZTsKICB9KCk7CgogIF9leHBvcnRzLlNjb3BlID0gU2NvcGU7CgogIHZhciBUcmFuc2FjdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFRyYW5zYWN0aW9uKCkgewogICAgICB0aGlzLnNjaGVkdWxlZEluc3RhbGxNYW5hZ2VycyA9IFtdOwogICAgICB0aGlzLnNjaGVkdWxlZEluc3RhbGxNb2RpZmllcnMgPSBbXTsKICAgICAgdGhpcy5zY2hlZHVsZWRVcGRhdGVNb2RpZmllck1hbmFnZXJzID0gW107CiAgICAgIHRoaXMuc2NoZWR1bGVkVXBkYXRlTW9kaWZpZXJzID0gW107CiAgICAgIHRoaXMuY3JlYXRlZENvbXBvbmVudHMgPSBbXTsKICAgICAgdGhpcy5jcmVhdGVkTWFuYWdlcnMgPSBbXTsKICAgICAgdGhpcy51cGRhdGVkQ29tcG9uZW50cyA9IFtdOwogICAgICB0aGlzLnVwZGF0ZWRNYW5hZ2VycyA9IFtdOwogICAgICB0aGlzLmRlc3RydWN0b3JzID0gW107CiAgICB9CgogICAgdmFyIF9wcm90bzM3ID0gVHJhbnNhY3Rpb24ucHJvdG90eXBlOwoKICAgIF9wcm90bzM3LmRpZENyZWF0ZSA9IGZ1bmN0aW9uIGRpZENyZWF0ZShjb21wb25lbnQsIG1hbmFnZXIpIHsKICAgICAgdGhpcy5jcmVhdGVkQ29tcG9uZW50cy5wdXNoKGNvbXBvbmVudCk7CiAgICAgIHRoaXMuY3JlYXRlZE1hbmFnZXJzLnB1c2gobWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM3LmRpZFVwZGF0ZSA9IGZ1bmN0aW9uIGRpZFVwZGF0ZShjb21wb25lbnQsIG1hbmFnZXIpIHsKICAgICAgdGhpcy51cGRhdGVkQ29tcG9uZW50cy5wdXNoKGNvbXBvbmVudCk7CiAgICAgIHRoaXMudXBkYXRlZE1hbmFnZXJzLnB1c2gobWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM3LnNjaGVkdWxlSW5zdGFsbE1vZGlmaWVyID0gZnVuY3Rpb24gc2NoZWR1bGVJbnN0YWxsTW9kaWZpZXIobW9kaWZpZXIsIG1hbmFnZXIpIHsKICAgICAgdGhpcy5zY2hlZHVsZWRJbnN0YWxsTW9kaWZpZXJzLnB1c2gobW9kaWZpZXIpOwogICAgICB0aGlzLnNjaGVkdWxlZEluc3RhbGxNYW5hZ2Vycy5wdXNoKG1hbmFnZXIpOwogICAgfTsKCiAgICBfcHJvdG8zNy5zY2hlZHVsZVVwZGF0ZU1vZGlmaWVyID0gZnVuY3Rpb24gc2NoZWR1bGVVcGRhdGVNb2RpZmllcihtb2RpZmllciwgbWFuYWdlcikgewogICAgICB0aGlzLnNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVycy5wdXNoKG1vZGlmaWVyKTsKICAgICAgdGhpcy5zY2hlZHVsZWRVcGRhdGVNb2RpZmllck1hbmFnZXJzLnB1c2gobWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM3LmRpZERlc3Ryb3kgPSBmdW5jdGlvbiBkaWREZXN0cm95KGQpIHsKICAgICAgdGhpcy5kZXN0cnVjdG9ycy5wdXNoKGQpOwogICAgfTsKCiAgICBfcHJvdG8zNy5jb21taXQgPSBmdW5jdGlvbiBjb21taXQoKSB7CiAgICAgIHZhciBjcmVhdGVkQ29tcG9uZW50cyA9IHRoaXMuY3JlYXRlZENvbXBvbmVudHMsCiAgICAgICAgICBjcmVhdGVkTWFuYWdlcnMgPSB0aGlzLmNyZWF0ZWRNYW5hZ2VyczsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY3JlYXRlZENvbXBvbmVudHMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgY29tcG9uZW50ID0gY3JlYXRlZENvbXBvbmVudHNbaV07CiAgICAgICAgdmFyIG1hbmFnZXIgPSBjcmVhdGVkTWFuYWdlcnNbaV07CiAgICAgICAgbWFuYWdlci5kaWRDcmVhdGUoY29tcG9uZW50KTsKICAgICAgfQoKICAgICAgdmFyIHVwZGF0ZWRDb21wb25lbnRzID0gdGhpcy51cGRhdGVkQ29tcG9uZW50cywKICAgICAgICAgIHVwZGF0ZWRNYW5hZ2VycyA9IHRoaXMudXBkYXRlZE1hbmFnZXJzOwoKICAgICAgZm9yICh2YXIgX2k0ID0gMDsgX2k0IDwgdXBkYXRlZENvbXBvbmVudHMubGVuZ3RoOyBfaTQrKykgewogICAgICAgIHZhciBfY29tcG9uZW50ID0gdXBkYXRlZENvbXBvbmVudHNbX2k0XTsKICAgICAgICB2YXIgX21hbmFnZXIyID0gdXBkYXRlZE1hbmFnZXJzW19pNF07CgogICAgICAgIF9tYW5hZ2VyMi5kaWRVcGRhdGUoX2NvbXBvbmVudCk7CiAgICAgIH0KCiAgICAgIHZhciBkZXN0cnVjdG9ycyA9IHRoaXMuZGVzdHJ1Y3RvcnM7CgogICAgICBmb3IgKHZhciBfaTUgPSAwOyBfaTUgPCBkZXN0cnVjdG9ycy5sZW5ndGg7IF9pNSsrKSB7CiAgICAgICAgZGVzdHJ1Y3RvcnNbX2k1XS5kZXN0cm95KCk7CiAgICAgIH0KCiAgICAgIHZhciBzY2hlZHVsZWRJbnN0YWxsTWFuYWdlcnMgPSB0aGlzLnNjaGVkdWxlZEluc3RhbGxNYW5hZ2VycywKICAgICAgICAgIHNjaGVkdWxlZEluc3RhbGxNb2RpZmllcnMgPSB0aGlzLnNjaGVkdWxlZEluc3RhbGxNb2RpZmllcnM7CgogICAgICBmb3IgKHZhciBfaTYgPSAwOyBfaTYgPCBzY2hlZHVsZWRJbnN0YWxsTWFuYWdlcnMubGVuZ3RoOyBfaTYrKykgewogICAgICAgIHZhciBtb2RpZmllciA9IHNjaGVkdWxlZEluc3RhbGxNb2RpZmllcnNbX2k2XTsKICAgICAgICB2YXIgX21hbmFnZXIzID0gc2NoZWR1bGVkSW5zdGFsbE1hbmFnZXJzW19pNl07CgogICAgICAgIF9tYW5hZ2VyMy5pbnN0YWxsKG1vZGlmaWVyKTsKICAgICAgfQoKICAgICAgdmFyIHNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVyTWFuYWdlcnMgPSB0aGlzLnNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVyTWFuYWdlcnMsCiAgICAgICAgICBzY2hlZHVsZWRVcGRhdGVNb2RpZmllcnMgPSB0aGlzLnNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVyczsKCiAgICAgIGZvciAodmFyIF9pNyA9IDA7IF9pNyA8IHNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVyTWFuYWdlcnMubGVuZ3RoOyBfaTcrKykgewogICAgICAgIHZhciBfbW9kaWZpZXIgPSBzY2hlZHVsZWRVcGRhdGVNb2RpZmllcnNbX2k3XTsKICAgICAgICB2YXIgX21hbmFnZXI0ID0gc2NoZWR1bGVkVXBkYXRlTW9kaWZpZXJNYW5hZ2Vyc1tfaTddOwoKICAgICAgICBfbWFuYWdlcjQudXBkYXRlKF9tb2RpZmllcik7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIFRyYW5zYWN0aW9uOwogIH0oKTsKCiAgdmFyIEVudmlyb25tZW50ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRW52aXJvbm1lbnQoX3JlZjU2KSB7CiAgICAgIHZhciBhcHBlbmRPcGVyYXRpb25zID0gX3JlZjU2LmFwcGVuZE9wZXJhdGlvbnMsCiAgICAgICAgICB1cGRhdGVPcGVyYXRpb25zID0gX3JlZjU2LnVwZGF0ZU9wZXJhdGlvbnM7CiAgICAgIHRoaXMuX3RyYW5zYWN0aW9uID0gbnVsbDsKICAgICAgdGhpcy5hcHBlbmRPcGVyYXRpb25zID0gYXBwZW5kT3BlcmF0aW9uczsKICAgICAgdGhpcy51cGRhdGVPcGVyYXRpb25zID0gdXBkYXRlT3BlcmF0aW9uczsKICAgIH0KCiAgICB2YXIgX3Byb3RvMzggPSBFbnZpcm9ubWVudC5wcm90b3R5cGU7CgogICAgX3Byb3RvMzgudG9Db25kaXRpb25hbFJlZmVyZW5jZSA9IGZ1bmN0aW9uIHRvQ29uZGl0aW9uYWxSZWZlcmVuY2UocmVmZXJlbmNlKSB7CiAgICAgIHJldHVybiBuZXcgQ29uZGl0aW9uYWxSZWZlcmVuY2UocmVmZXJlbmNlKTsKICAgIH07CgogICAgX3Byb3RvMzguZ2V0QXBwZW5kT3BlcmF0aW9ucyA9IGZ1bmN0aW9uIGdldEFwcGVuZE9wZXJhdGlvbnMoKSB7CiAgICAgIHJldHVybiB0aGlzLmFwcGVuZE9wZXJhdGlvbnM7CiAgICB9OwoKICAgIF9wcm90bzM4LmdldERPTSA9IGZ1bmN0aW9uIGdldERPTSgpIHsKICAgICAgcmV0dXJuIHRoaXMudXBkYXRlT3BlcmF0aW9uczsKICAgIH07CgogICAgX3Byb3RvMzguYmVnaW4gPSBmdW5jdGlvbiBiZWdpbigpIHsKICAgICAgdGhpcy5fdHJhbnNhY3Rpb24gPSBuZXcgVHJhbnNhY3Rpb24oKTsKICAgIH07CgogICAgX3Byb3RvMzguZGlkQ3JlYXRlID0gZnVuY3Rpb24gZGlkQ3JlYXRlKGNvbXBvbmVudCwgbWFuYWdlcikgewogICAgICB0aGlzLnRyYW5zYWN0aW9uLmRpZENyZWF0ZShjb21wb25lbnQsIG1hbmFnZXIpOwogICAgfTsKCiAgICBfcHJvdG8zOC5kaWRVcGRhdGUgPSBmdW5jdGlvbiBkaWRVcGRhdGUoY29tcG9uZW50LCBtYW5hZ2VyKSB7CiAgICAgIHRoaXMudHJhbnNhY3Rpb24uZGlkVXBkYXRlKGNvbXBvbmVudCwgbWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM4LnNjaGVkdWxlSW5zdGFsbE1vZGlmaWVyID0gZnVuY3Rpb24gc2NoZWR1bGVJbnN0YWxsTW9kaWZpZXIobW9kaWZpZXIsIG1hbmFnZXIpIHsKICAgICAgdGhpcy50cmFuc2FjdGlvbi5zY2hlZHVsZUluc3RhbGxNb2RpZmllcihtb2RpZmllciwgbWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM4LnNjaGVkdWxlVXBkYXRlTW9kaWZpZXIgPSBmdW5jdGlvbiBzY2hlZHVsZVVwZGF0ZU1vZGlmaWVyKG1vZGlmaWVyLCBtYW5hZ2VyKSB7CiAgICAgIHRoaXMudHJhbnNhY3Rpb24uc2NoZWR1bGVVcGRhdGVNb2RpZmllcihtb2RpZmllciwgbWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM4LmRpZERlc3Ryb3kgPSBmdW5jdGlvbiBkaWREZXN0cm95KGQpIHsKICAgICAgdGhpcy50cmFuc2FjdGlvbi5kaWREZXN0cm95KGQpOwogICAgfTsKCiAgICBfcHJvdG8zOC5jb21taXQgPSBmdW5jdGlvbiBjb21taXQoKSB7CiAgICAgIHZhciB0cmFuc2FjdGlvbiA9IHRoaXMudHJhbnNhY3Rpb247CiAgICAgIHRoaXMuX3RyYW5zYWN0aW9uID0gbnVsbDsKICAgICAgdHJhbnNhY3Rpb24uY29tbWl0KCk7CiAgICB9OwoKICAgIF9wcm90bzM4LmF0dHJpYnV0ZUZvciA9IGZ1bmN0aW9uIGF0dHJpYnV0ZUZvcihlbGVtZW50LCBhdHRyLCBfaXNUcnVzdGluZywgbmFtZXNwYWNlKSB7CiAgICAgIGlmIChuYW1lc3BhY2UgPT09IHZvaWQgMCkgewogICAgICAgIG5hbWVzcGFjZSA9IG51bGw7CiAgICAgIH0KCiAgICAgIHJldHVybiBkeW5hbWljQXR0cmlidXRlKGVsZW1lbnQsIGF0dHIsIG5hbWVzcGFjZSk7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoRW52aXJvbm1lbnQsIFt7CiAgICAgIGtleTogInRyYW5zYWN0aW9uIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3RyYW5zYWN0aW9uOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gRW52aXJvbm1lbnQ7CiAgfSgpOwoKICBfZXhwb3J0cy5FbnZpcm9ubWVudCA9IEVudmlyb25tZW50OwoKICB2YXIgRGVmYXVsdEVudmlyb25tZW50ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9FbnZpcm9ubWVudCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKERlZmF1bHRFbnZpcm9ubWVudCwgX0Vudmlyb25tZW50KTsKCiAgICBmdW5jdGlvbiBEZWZhdWx0RW52aXJvbm1lbnQob3B0aW9ucykgewogICAgICBpZiAoIW9wdGlvbnMpIHsKICAgICAgICB2YXIgX2RvY3VtZW50ID0gd2luZG93LmRvY3VtZW50OwogICAgICAgIHZhciBhcHBlbmRPcGVyYXRpb25zID0gbmV3IERPTVRyZWVDb25zdHJ1Y3Rpb24oX2RvY3VtZW50KTsKICAgICAgICB2YXIgdXBkYXRlT3BlcmF0aW9ucyA9IG5ldyBET01DaGFuZ2VzKF9kb2N1bWVudCk7CiAgICAgICAgb3B0aW9ucyA9IHsKICAgICAgICAgIGFwcGVuZE9wZXJhdGlvbnM6IGFwcGVuZE9wZXJhdGlvbnMsCiAgICAgICAgICB1cGRhdGVPcGVyYXRpb25zOiB1cGRhdGVPcGVyYXRpb25zCiAgICAgICAgfTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9FbnZpcm9ubWVudC5jYWxsKHRoaXMsIG9wdGlvbnMpIHx8IHRoaXM7CiAgICB9CgogICAgcmV0dXJuIERlZmF1bHRFbnZpcm9ubWVudDsKICB9KEVudmlyb25tZW50KTsKCiAgX2V4cG9ydHMuRGVmYXVsdEVudmlyb25tZW50ID0gRGVmYXVsdEVudmlyb25tZW50OwoKICB2YXIgTG93TGV2ZWxWTSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIExvd0xldmVsVk0oc3RhY2ssIGhlYXAsIHByb2dyYW0sIGV4dGVybnMsIHBjLCByYSkgewogICAgICBpZiAocGMgPT09IHZvaWQgMCkgewogICAgICAgIHBjID0gLTE7CiAgICAgIH0KCiAgICAgIGlmIChyYSA9PT0gdm9pZCAwKSB7CiAgICAgICAgcmEgPSAtMTsKICAgICAgfQoKICAgICAgdGhpcy5zdGFjayA9IHN0YWNrOwogICAgICB0aGlzLmhlYXAgPSBoZWFwOwogICAgICB0aGlzLnByb2dyYW0gPSBwcm9ncmFtOwogICAgICB0aGlzLmV4dGVybnMgPSBleHRlcm5zOwogICAgICB0aGlzLnBjID0gcGM7CiAgICAgIHRoaXMucmEgPSByYTsKICAgICAgdGhpcy5jdXJyZW50T3BTaXplID0gMDsKICAgIH0gLy8gU3RhcnQgYSBuZXcgZnJhbWUgYW5kIHNhdmUgJHJhIGFuZCAkZnAgb24gdGhlIHN0YWNrCgoKICAgIHZhciBfcHJvdG8zOSA9IExvd0xldmVsVk0ucHJvdG90eXBlOwoKICAgIF9wcm90bzM5LnB1c2hGcmFtZSA9IGZ1bmN0aW9uIHB1c2hGcmFtZSgpIHsKICAgICAgdGhpcy5zdGFjay5wdXNoKHRoaXMucmEpOwogICAgICB0aGlzLnN0YWNrLnB1c2godGhpcy5zdGFjay5mcCk7CiAgICAgIHRoaXMuc3RhY2suZnAgPSB0aGlzLnN0YWNrLnNwIC0gMTsKICAgIH0gLy8gUmVzdG9yZSAkcmEsICRzcCBhbmQgJGZwCiAgICA7CgogICAgX3Byb3RvMzkucG9wRnJhbWUgPSBmdW5jdGlvbiBwb3BGcmFtZSgpIHsKICAgICAgdGhpcy5zdGFjay5zcCA9IHRoaXMuc3RhY2suZnAgLSAxOwogICAgICB0aGlzLnJhID0gdGhpcy5zdGFjay5nZXQoMCk7CiAgICAgIHRoaXMuc3RhY2suZnAgPSB0aGlzLnN0YWNrLmdldCgxKTsKICAgIH07CgogICAgX3Byb3RvMzkucHVzaFNtYWxsRnJhbWUgPSBmdW5jdGlvbiBwdXNoU21hbGxGcmFtZSgpIHsKICAgICAgdGhpcy5zdGFjay5wdXNoKHRoaXMucmEpOwogICAgfTsKCiAgICBfcHJvdG8zOS5wb3BTbWFsbEZyYW1lID0gZnVuY3Rpb24gcG9wU21hbGxGcmFtZSgpIHsKICAgICAgdGhpcy5yYSA9IHRoaXMuc3RhY2sucG9wU21pKCk7CiAgICB9IC8vIEp1bXAgdG8gYW4gYWRkcmVzcyBpbiBgcHJvZ3JhbWAKICAgIDsKCiAgICBfcHJvdG8zOS5nb3RvID0gZnVuY3Rpb24gZ290byhvZmZzZXQpIHsKICAgICAgdmFyIGFkZHIgPSB0aGlzLnBjICsgb2Zmc2V0IC0gdGhpcy5jdXJyZW50T3BTaXplOwogICAgICB0aGlzLnBjID0gYWRkcjsKICAgIH0gLy8gU2F2ZSAkcGMgaW50byAkcmEsIHRoZW4ganVtcCB0byBhIG5ldyBhZGRyZXNzIGluIGBwcm9ncmFtYCAoamFsIGluIE1JUFMpCiAgICA7CgogICAgX3Byb3RvMzkuY2FsbCA9IGZ1bmN0aW9uIGNhbGwoaGFuZGxlKSB7CiAgICAgIHRoaXMucmEgPSB0aGlzLnBjOwogICAgICB0aGlzLnBjID0gdGhpcy5oZWFwLmdldGFkZHIoaGFuZGxlKTsKICAgIH0gLy8gUHV0IGEgc3BlY2lmaWMgYHByb2dyYW1gIGFkZHJlc3MgaW4gJHJhCiAgICA7CgogICAgX3Byb3RvMzkucmV0dXJuVG8gPSBmdW5jdGlvbiByZXR1cm5UbyhvZmZzZXQpIHsKICAgICAgdmFyIGFkZHIgPSB0aGlzLnBjICsgb2Zmc2V0IC0gdGhpcy5jdXJyZW50T3BTaXplOwogICAgICB0aGlzLnJhID0gYWRkcjsKICAgIH0gLy8gUmV0dXJuIHRvIHRoZSBgcHJvZ3JhbWAgYWRkcmVzcyBzdG9yZWQgaW4gJHJhCiAgICA7CgogICAgX3Byb3RvMzkucmV0dXJuID0gZnVuY3Rpb24gX3JldHVybigpIHsKICAgICAgdGhpcy5wYyA9IHRoaXMucmE7CiAgICB9OwoKICAgIF9wcm90bzM5Lm5leHRTdGF0ZW1lbnQgPSBmdW5jdGlvbiBuZXh0U3RhdGVtZW50KCkgewogICAgICB2YXIgcGMgPSB0aGlzLnBjLAogICAgICAgICAgcHJvZ3JhbSA9IHRoaXMucHJvZ3JhbTsKCiAgICAgIGlmIChwYyA9PT0gLTEpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfSAvLyBXZSBoYXZlIHRvIHNhdmUgb2ZmIHRoZSBjdXJyZW50IG9wZXJhdGlvbnMgc2l6ZSBzbyB0aGF0CiAgICAgIC8vIHdoZW4gd2UgZG8gYSBqdW1wIHdlIGNhbiBjYWxjdWxhdGUgdGhlIGNvcnJlY3Qgb2Zmc2V0CiAgICAgIC8vIHRvIHdoZXJlIHdlIGFyZSBnb2luZy4gV2UgY2FuJ3Qgc2ltcGx5IGFzayBmb3IgdGhlIHNpemUKICAgICAgLy8gaW4gYSBqdW1wIGJlY2F1c2Ugd2UgaGF2ZSBoYXZlIGFscmVhZHkgaW5jcmVtZW50ZWQgdGhlCiAgICAgIC8vIHByb2dyYW0gY291bnRlciB0byB0aGUgbmV4dCBpbnN0cnVjdGlvbiBwcmlvciB0byBleGVjdXRpbmcuCgoKICAgICAgdmFyIF90aGlzJHByb2dyYW0kb3Bjb2RlID0gdGhpcy5wcm9ncmFtLm9wY29kZShwYyksCiAgICAgICAgICBzaXplID0gX3RoaXMkcHJvZ3JhbSRvcGNvZGUuc2l6ZTsKCiAgICAgIHZhciBvcGVyYXRpb25TaXplID0gdGhpcy5jdXJyZW50T3BTaXplID0gc2l6ZTsKICAgICAgdGhpcy5wYyArPSBvcGVyYXRpb25TaXplOwogICAgICByZXR1cm4gcHJvZ3JhbS5vcGNvZGUocGMpOwogICAgfTsKCiAgICBfcHJvdG8zOS5ldmFsdWF0ZU91dGVyID0gZnVuY3Rpb24gZXZhbHVhdGVPdXRlcihvcGNvZGUsIHZtKSB7CiAgICAgIHsKICAgICAgICB0aGlzLmV2YWx1YXRlSW5uZXIob3Bjb2RlLCB2bSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMzkuZXZhbHVhdGVJbm5lciA9IGZ1bmN0aW9uIGV2YWx1YXRlSW5uZXIob3Bjb2RlLCB2bSkgewogICAgICBpZiAob3Bjb2RlLmlzTWFjaGluZSkgewogICAgICAgIHRoaXMuZXZhbHVhdGVNYWNoaW5lKG9wY29kZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5ldmFsdWF0ZVN5c2NhbGwob3Bjb2RlLCB2bSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMzkuZXZhbHVhdGVNYWNoaW5lID0gZnVuY3Rpb24gZXZhbHVhdGVNYWNoaW5lKG9wY29kZSkgewogICAgICBzd2l0Y2ggKG9wY29kZS50eXBlKSB7CiAgICAgICAgY2FzZSA1NwogICAgICAgIC8qIFB1c2hGcmFtZSAqLwogICAgICAgIDoKICAgICAgICAgIHJldHVybiB0aGlzLnB1c2hGcmFtZSgpOwoKICAgICAgICBjYXNlIDU4CiAgICAgICAgLyogUG9wRnJhbWUgKi8KICAgICAgICA6CiAgICAgICAgICByZXR1cm4gdGhpcy5wb3BGcmFtZSgpOwoKICAgICAgICBjYXNlIDU5CiAgICAgICAgLyogUHVzaFNtYWxsRnJhbWUgKi8KICAgICAgICA6CiAgICAgICAgICByZXR1cm4gdGhpcy5wdXNoU21hbGxGcmFtZSgpOwoKICAgICAgICBjYXNlIDYwCiAgICAgICAgLyogUG9wU21hbGxGcmFtZSAqLwogICAgICAgIDoKICAgICAgICAgIHJldHVybiB0aGlzLnBvcFNtYWxsRnJhbWUoKTsKCiAgICAgICAgY2FzZSA1MAogICAgICAgIC8qIEludm9rZVN0YXRpYyAqLwogICAgICAgIDoKICAgICAgICAgIHJldHVybiB0aGlzLmNhbGwob3Bjb2RlLm9wMSk7CgogICAgICAgIGNhc2UgNDkKICAgICAgICAvKiBJbnZva2VWaXJ0dWFsICovCiAgICAgICAgOgogICAgICAgICAgcmV0dXJuIHRoaXMuY2FsbCh0aGlzLnN0YWNrLnBvcFNtaSgpKTsKCiAgICAgICAgY2FzZSA1MgogICAgICAgIC8qIEp1bXAgKi8KICAgICAgICA6CiAgICAgICAgICByZXR1cm4gdGhpcy5nb3RvKG9wY29kZS5vcDEpOwoKICAgICAgICBjYXNlIDI0CiAgICAgICAgLyogUmV0dXJuICovCiAgICAgICAgOgogICAgICAgICAgcmV0dXJuIHRoaXMucmV0dXJuKCk7CgogICAgICAgIGNhc2UgMjUKICAgICAgICAvKiBSZXR1cm5UbyAqLwogICAgICAgIDoKICAgICAgICAgIHJldHVybiB0aGlzLnJldHVyblRvKG9wY29kZS5vcDEpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzM5LmV2YWx1YXRlU3lzY2FsbCA9IGZ1bmN0aW9uIGV2YWx1YXRlU3lzY2FsbChvcGNvZGUsIHZtKSB7CiAgICAgIEFQUEVORF9PUENPREVTLmV2YWx1YXRlKHZtLCBvcGNvZGUsIG9wY29kZS50eXBlKTsKICAgIH07CgogICAgcmV0dXJuIExvd0xldmVsVk07CiAgfSgpOwoKICB2YXIgRmlyc3QgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBGaXJzdChub2RlKSB7CiAgICAgIHRoaXMubm9kZSA9IG5vZGU7CiAgICB9CgogICAgdmFyIF9wcm90bzQwID0gRmlyc3QucHJvdG90eXBlOwoKICAgIF9wcm90bzQwLmZpcnN0Tm9kZSA9IGZ1bmN0aW9uIGZpcnN0Tm9kZSgpIHsKICAgICAgcmV0dXJuIHRoaXMubm9kZTsKICAgIH07CgogICAgcmV0dXJuIEZpcnN0OwogIH0oKTsKCiAgdmFyIExhc3QgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBMYXN0KG5vZGUpIHsKICAgICAgdGhpcy5ub2RlID0gbm9kZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDEgPSBMYXN0LnByb3RvdHlwZTsKCiAgICBfcHJvdG80MS5sYXN0Tm9kZSA9IGZ1bmN0aW9uIGxhc3ROb2RlKCkgewogICAgICByZXR1cm4gdGhpcy5ub2RlOwogICAgfTsKCiAgICByZXR1cm4gTGFzdDsKICB9KCk7CgogIHZhciBOZXdFbGVtZW50QnVpbGRlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIE5ld0VsZW1lbnRCdWlsZGVyKGVudiwgcGFyZW50Tm9kZSwgbmV4dFNpYmxpbmcpIHsKICAgICAgdGhpcy5jb25zdHJ1Y3RpbmcgPSBudWxsOwogICAgICB0aGlzLm9wZXJhdGlvbnMgPSBudWxsOwogICAgICB0aGlzLmN1cnNvclN0YWNrID0gbmV3IF91dGlsLlN0YWNrKCk7CiAgICAgIHRoaXMubW9kaWZpZXJTdGFjayA9IG5ldyBfdXRpbC5TdGFjaygpOwogICAgICB0aGlzLmJsb2NrU3RhY2sgPSBuZXcgX3V0aWwuU3RhY2soKTsKICAgICAgdGhpcy5wdXNoRWxlbWVudChwYXJlbnROb2RlLCBuZXh0U2libGluZyk7CiAgICAgIHRoaXMuZW52ID0gZW52OwogICAgICB0aGlzLmRvbSA9IGVudi5nZXRBcHBlbmRPcGVyYXRpb25zKCk7CiAgICAgIHRoaXMudXBkYXRlT3BlcmF0aW9ucyA9IGVudi5nZXRET00oKTsKICAgIH0KCiAgICBOZXdFbGVtZW50QnVpbGRlci5mb3JJbml0aWFsUmVuZGVyID0gZnVuY3Rpb24gZm9ySW5pdGlhbFJlbmRlcihlbnYsIGN1cnNvcikgewogICAgICB2YXIgYnVpbGRlciA9IG5ldyB0aGlzKGVudiwgY3Vyc29yLmVsZW1lbnQsIGN1cnNvci5uZXh0U2libGluZyk7CiAgICAgIGJ1aWxkZXIucHVzaFNpbXBsZUJsb2NrKCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfTsKCiAgICBOZXdFbGVtZW50QnVpbGRlci5yZXN1bWUgPSBmdW5jdGlvbiByZXN1bWUoZW52LCB0cmFja2VyLCBuZXh0U2libGluZykgewogICAgICB2YXIgcGFyZW50Tm9kZSA9IHRyYWNrZXIucGFyZW50RWxlbWVudCgpOwogICAgICB2YXIgc3RhY2sgPSBuZXcgdGhpcyhlbnYsIHBhcmVudE5vZGUsIG5leHRTaWJsaW5nKTsKICAgICAgc3RhY2sucHVzaFNpbXBsZUJsb2NrKCk7CiAgICAgIHN0YWNrLnB1c2hCbG9ja1RyYWNrZXIodHJhY2tlcik7CiAgICAgIHJldHVybiBzdGFjazsKICAgIH07CgogICAgdmFyIF9wcm90bzQyID0gTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzQyLmV4cGVjdENvbnN0cnVjdGluZyA9IGZ1bmN0aW9uIGV4cGVjdENvbnN0cnVjdGluZyhtZXRob2QpIHsKICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0aW5nOwogICAgfTsKCiAgICBfcHJvdG80Mi5ibG9jayA9IGZ1bmN0aW9uIGJsb2NrKCkgewogICAgICByZXR1cm4gdGhpcy5ibG9ja1N0YWNrLmN1cnJlbnQ7CiAgICB9OwoKICAgIF9wcm90bzQyLnBvcEVsZW1lbnQgPSBmdW5jdGlvbiBwb3BFbGVtZW50KCkgewogICAgICB0aGlzLmN1cnNvclN0YWNrLnBvcCgpOwogICAgICB0aGlzLmN1cnNvclN0YWNrLmN1cnJlbnQ7CiAgICB9OwoKICAgIF9wcm90bzQyLnB1c2hTaW1wbGVCbG9jayA9IGZ1bmN0aW9uIHB1c2hTaW1wbGVCbG9jaygpIHsKICAgICAgcmV0dXJuIHRoaXMucHVzaEJsb2NrVHJhY2tlcihuZXcgU2ltcGxlQmxvY2tUcmFja2VyKHRoaXMuZWxlbWVudCkpOwogICAgfTsKCiAgICBfcHJvdG80Mi5wdXNoVXBkYXRhYmxlQmxvY2sgPSBmdW5jdGlvbiBwdXNoVXBkYXRhYmxlQmxvY2soKSB7CiAgICAgIHJldHVybiB0aGlzLnB1c2hCbG9ja1RyYWNrZXIobmV3IFVwZGF0YWJsZUJsb2NrVHJhY2tlcih0aGlzLmVsZW1lbnQpKTsKICAgIH07CgogICAgX3Byb3RvNDIucHVzaEJsb2NrTGlzdCA9IGZ1bmN0aW9uIHB1c2hCbG9ja0xpc3QobGlzdCkgewogICAgICByZXR1cm4gdGhpcy5wdXNoQmxvY2tUcmFja2VyKG5ldyBCbG9ja0xpc3RUcmFja2VyKHRoaXMuZWxlbWVudCwgbGlzdCkpOwogICAgfTsKCiAgICBfcHJvdG80Mi5wdXNoQmxvY2tUcmFja2VyID0gZnVuY3Rpb24gcHVzaEJsb2NrVHJhY2tlcih0cmFja2VyLCBpc1JlbW90ZSkgewogICAgICBpZiAoaXNSZW1vdGUgPT09IHZvaWQgMCkgewogICAgICAgIGlzUmVtb3RlID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIHZhciBjdXJyZW50ID0gdGhpcy5ibG9ja1N0YWNrLmN1cnJlbnQ7CgogICAgICBpZiAoY3VycmVudCAhPT0gbnVsbCkgewogICAgICAgIGN1cnJlbnQubmV3RGVzdHJveWFibGUodHJhY2tlcik7CgogICAgICAgIGlmICghaXNSZW1vdGUpIHsKICAgICAgICAgIGN1cnJlbnQuZGlkQXBwZW5kQm91bmRzKHRyYWNrZXIpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdGhpcy5fX29wZW5CbG9jaygpOwoKICAgICAgdGhpcy5ibG9ja1N0YWNrLnB1c2godHJhY2tlcik7CiAgICAgIHJldHVybiB0cmFja2VyOwogICAgfTsKCiAgICBfcHJvdG80Mi5wb3BCbG9jayA9IGZ1bmN0aW9uIHBvcEJsb2NrKCkgewogICAgICB0aGlzLmJsb2NrKCkuZmluYWxpemUodGhpcyk7CgogICAgICB0aGlzLl9fY2xvc2VCbG9jaygpOwoKICAgICAgcmV0dXJuIHRoaXMuYmxvY2tTdGFjay5wb3AoKTsKICAgIH07CgogICAgX3Byb3RvNDIuX19vcGVuQmxvY2sgPSBmdW5jdGlvbiBfX29wZW5CbG9jaygpIHt9OwoKICAgIF9wcm90bzQyLl9fY2xvc2VCbG9jayA9IGZ1bmN0aW9uIF9fY2xvc2VCbG9jaygpIHt9IC8vIHRvZG8gcmV0dXJuIHNlZW1zIHVudXNlZAogICAgOwoKICAgIF9wcm90bzQyLm9wZW5FbGVtZW50ID0gZnVuY3Rpb24gb3BlbkVsZW1lbnQodGFnKSB7CiAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5fX29wZW5FbGVtZW50KHRhZyk7CgogICAgICB0aGlzLmNvbnN0cnVjdGluZyA9IGVsZW1lbnQ7CiAgICAgIHJldHVybiBlbGVtZW50OwogICAgfTsKCiAgICBfcHJvdG80Mi5fX29wZW5FbGVtZW50ID0gZnVuY3Rpb24gX19vcGVuRWxlbWVudCh0YWcpIHsKICAgICAgcmV0dXJuIHRoaXMuZG9tLmNyZWF0ZUVsZW1lbnQodGFnLCB0aGlzLmVsZW1lbnQpOwogICAgfTsKCiAgICBfcHJvdG80Mi5mbHVzaEVsZW1lbnQgPSBmdW5jdGlvbiBmbHVzaEVsZW1lbnQobW9kaWZpZXJzKSB7CiAgICAgIHZhciBwYXJlbnQgPSB0aGlzLmVsZW1lbnQ7CiAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5jb25zdHJ1Y3Rpbmc7CgogICAgICB0aGlzLl9fZmx1c2hFbGVtZW50KHBhcmVudCwgZWxlbWVudCk7CgogICAgICB0aGlzLmNvbnN0cnVjdGluZyA9IG51bGw7CiAgICAgIHRoaXMub3BlcmF0aW9ucyA9IG51bGw7CiAgICAgIHRoaXMucHVzaE1vZGlmaWVycyhtb2RpZmllcnMpOwogICAgICB0aGlzLnB1c2hFbGVtZW50KGVsZW1lbnQsIG51bGwpOwogICAgICB0aGlzLmRpZE9wZW5FbGVtZW50KGVsZW1lbnQpOwogICAgfTsKCiAgICBfcHJvdG80Mi5fX2ZsdXNoRWxlbWVudCA9IGZ1bmN0aW9uIF9fZmx1c2hFbGVtZW50KHBhcmVudCwgY29uc3RydWN0aW5nKSB7CiAgICAgIHRoaXMuZG9tLmluc2VydEJlZm9yZShwYXJlbnQsIGNvbnN0cnVjdGluZywgdGhpcy5uZXh0U2libGluZyk7CiAgICB9OwoKICAgIF9wcm90bzQyLmNsb3NlRWxlbWVudCA9IGZ1bmN0aW9uIGNsb3NlRWxlbWVudCgpIHsKICAgICAgdGhpcy53aWxsQ2xvc2VFbGVtZW50KCk7CiAgICAgIHRoaXMucG9wRWxlbWVudCgpOwogICAgICByZXR1cm4gdGhpcy5wb3BNb2RpZmllcnMoKTsKICAgIH07CgogICAgX3Byb3RvNDIucHVzaFJlbW90ZUVsZW1lbnQgPSBmdW5jdGlvbiBwdXNoUmVtb3RlRWxlbWVudChlbGVtZW50LCBndWlkLCBuZXh0U2libGluZykgewogICAgICBpZiAobmV4dFNpYmxpbmcgPT09IHZvaWQgMCkgewogICAgICAgIG5leHRTaWJsaW5nID0gbnVsbDsKICAgICAgfQoKICAgICAgdGhpcy5fX3B1c2hSZW1vdGVFbGVtZW50KGVsZW1lbnQsIGd1aWQsIG5leHRTaWJsaW5nKTsKICAgIH07CgogICAgX3Byb3RvNDIuX19wdXNoUmVtb3RlRWxlbWVudCA9IGZ1bmN0aW9uIF9fcHVzaFJlbW90ZUVsZW1lbnQoZWxlbWVudCwgX2d1aWQsIG5leHRTaWJsaW5nKSB7CiAgICAgIHRoaXMucHVzaEVsZW1lbnQoZWxlbWVudCwgbmV4dFNpYmxpbmcpOwogICAgICB2YXIgdHJhY2tlciA9IG5ldyBSZW1vdGVCbG9ja1RyYWNrZXIoZWxlbWVudCk7CiAgICAgIHRoaXMucHVzaEJsb2NrVHJhY2tlcih0cmFja2VyLCB0cnVlKTsKICAgIH07CgogICAgX3Byb3RvNDIucG9wUmVtb3RlRWxlbWVudCA9IGZ1bmN0aW9uIHBvcFJlbW90ZUVsZW1lbnQoKSB7CiAgICAgIHRoaXMucG9wQmxvY2soKTsKICAgICAgdGhpcy5wb3BFbGVtZW50KCk7CiAgICB9OwoKICAgIF9wcm90bzQyLnB1c2hFbGVtZW50ID0gZnVuY3Rpb24gcHVzaEVsZW1lbnQoZWxlbWVudCwgbmV4dFNpYmxpbmcpIHsKICAgICAgdGhpcy5jdXJzb3JTdGFjay5wdXNoKG5ldyBDdXJzb3IoZWxlbWVudCwgbmV4dFNpYmxpbmcpKTsKICAgIH07CgogICAgX3Byb3RvNDIucHVzaE1vZGlmaWVycyA9IGZ1bmN0aW9uIHB1c2hNb2RpZmllcnMobW9kaWZpZXJzKSB7CiAgICAgIHRoaXMubW9kaWZpZXJTdGFjay5wdXNoKG1vZGlmaWVycyk7CiAgICB9OwoKICAgIF9wcm90bzQyLnBvcE1vZGlmaWVycyA9IGZ1bmN0aW9uIHBvcE1vZGlmaWVycygpIHsKICAgICAgcmV0dXJuIHRoaXMubW9kaWZpZXJTdGFjay5wb3AoKTsKICAgIH07CgogICAgX3Byb3RvNDIuZGlkQWRkRGVzdHJveWFibGUgPSBmdW5jdGlvbiBkaWRBZGREZXN0cm95YWJsZShkKSB7CiAgICAgIHRoaXMuYmxvY2soKS5uZXdEZXN0cm95YWJsZShkKTsKICAgIH07CgogICAgX3Byb3RvNDIuZGlkQXBwZW5kQm91bmRzID0gZnVuY3Rpb24gZGlkQXBwZW5kQm91bmRzKGJvdW5kcykgewogICAgICB0aGlzLmJsb2NrKCkuZGlkQXBwZW5kQm91bmRzKGJvdW5kcyk7CiAgICAgIHJldHVybiBib3VuZHM7CiAgICB9OwoKICAgIF9wcm90bzQyLmRpZEFwcGVuZE5vZGUgPSBmdW5jdGlvbiBkaWRBcHBlbmROb2RlKG5vZGUpIHsKICAgICAgdGhpcy5ibG9jaygpLmRpZEFwcGVuZE5vZGUobm9kZSk7CiAgICAgIHJldHVybiBub2RlOwogICAgfTsKCiAgICBfcHJvdG80Mi5kaWRPcGVuRWxlbWVudCA9IGZ1bmN0aW9uIGRpZE9wZW5FbGVtZW50KGVsZW1lbnQpIHsKICAgICAgdGhpcy5ibG9jaygpLm9wZW5FbGVtZW50KGVsZW1lbnQpOwogICAgICByZXR1cm4gZWxlbWVudDsKICAgIH07CgogICAgX3Byb3RvNDIud2lsbENsb3NlRWxlbWVudCA9IGZ1bmN0aW9uIHdpbGxDbG9zZUVsZW1lbnQoKSB7CiAgICAgIHRoaXMuYmxvY2soKS5jbG9zZUVsZW1lbnQoKTsKICAgIH07CgogICAgX3Byb3RvNDIuYXBwZW5kVGV4dCA9IGZ1bmN0aW9uIGFwcGVuZFRleHQoc3RyaW5nKSB7CiAgICAgIHJldHVybiB0aGlzLmRpZEFwcGVuZE5vZGUodGhpcy5fX2FwcGVuZFRleHQoc3RyaW5nKSk7CiAgICB9OwoKICAgIF9wcm90bzQyLl9fYXBwZW5kVGV4dCA9IGZ1bmN0aW9uIF9fYXBwZW5kVGV4dCh0ZXh0KSB7CiAgICAgIHZhciBkb20gPSB0aGlzLmRvbSwKICAgICAgICAgIGVsZW1lbnQgPSB0aGlzLmVsZW1lbnQsCiAgICAgICAgICBuZXh0U2libGluZyA9IHRoaXMubmV4dFNpYmxpbmc7CiAgICAgIHZhciBub2RlID0gZG9tLmNyZWF0ZVRleHROb2RlKHRleHQpOwogICAgICBkb20uaW5zZXJ0QmVmb3JlKGVsZW1lbnQsIG5vZGUsIG5leHRTaWJsaW5nKTsKICAgICAgcmV0dXJuIG5vZGU7CiAgICB9OwoKICAgIF9wcm90bzQyLl9fYXBwZW5kTm9kZSA9IGZ1bmN0aW9uIF9fYXBwZW5kTm9kZShub2RlKSB7CiAgICAgIHRoaXMuZG9tLmluc2VydEJlZm9yZSh0aGlzLmVsZW1lbnQsIG5vZGUsIHRoaXMubmV4dFNpYmxpbmcpOwogICAgICByZXR1cm4gbm9kZTsKICAgIH07CgogICAgX3Byb3RvNDIuX19hcHBlbmRGcmFnbWVudCA9IGZ1bmN0aW9uIF9fYXBwZW5kRnJhZ21lbnQoZnJhZ21lbnQpIHsKICAgICAgdmFyIGZpcnN0ID0gZnJhZ21lbnQuZmlyc3RDaGlsZDsKCiAgICAgIGlmIChmaXJzdCkgewogICAgICAgIHZhciByZXQgPSBuZXcgQ29uY3JldGVCb3VuZHModGhpcy5lbGVtZW50LCBmaXJzdCwgZnJhZ21lbnQubGFzdENoaWxkKTsKICAgICAgICB0aGlzLmRvbS5pbnNlcnRCZWZvcmUodGhpcy5lbGVtZW50LCBmcmFnbWVudCwgdGhpcy5uZXh0U2libGluZyk7CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbmV3IFNpbmdsZU5vZGVCb3VuZHModGhpcy5lbGVtZW50LCB0aGlzLl9fYXBwZW5kQ29tbWVudCgnJykpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQyLl9fYXBwZW5kSFRNTCA9IGZ1bmN0aW9uIF9fYXBwZW5kSFRNTChodG1sKSB7CiAgICAgIHJldHVybiB0aGlzLmRvbS5pbnNlcnRIVE1MQmVmb3JlKHRoaXMuZWxlbWVudCwgdGhpcy5uZXh0U2libGluZywgaHRtbCk7CiAgICB9OwoKICAgIF9wcm90bzQyLmFwcGVuZER5bmFtaWNIVE1MID0gZnVuY3Rpb24gYXBwZW5kRHluYW1pY0hUTUwodmFsdWUkJDEpIHsKICAgICAgdmFyIGJvdW5kcyA9IHRoaXMudHJ1c3RlZENvbnRlbnQodmFsdWUkJDEpOwogICAgICB0aGlzLmRpZEFwcGVuZEJvdW5kcyhib3VuZHMpOwogICAgfTsKCiAgICBfcHJvdG80Mi5hcHBlbmREeW5hbWljVGV4dCA9IGZ1bmN0aW9uIGFwcGVuZER5bmFtaWNUZXh0KHZhbHVlJCQxKSB7CiAgICAgIHZhciBub2RlID0gdGhpcy51bnRydXN0ZWRDb250ZW50KHZhbHVlJCQxKTsKICAgICAgdGhpcy5kaWRBcHBlbmROb2RlKG5vZGUpOwogICAgICByZXR1cm4gbm9kZTsKICAgIH07CgogICAgX3Byb3RvNDIuYXBwZW5kRHluYW1pY0ZyYWdtZW50ID0gZnVuY3Rpb24gYXBwZW5kRHluYW1pY0ZyYWdtZW50KHZhbHVlJCQxKSB7CiAgICAgIHZhciBib3VuZHMgPSB0aGlzLl9fYXBwZW5kRnJhZ21lbnQodmFsdWUkJDEpOwoKICAgICAgdGhpcy5kaWRBcHBlbmRCb3VuZHMoYm91bmRzKTsKICAgIH07CgogICAgX3Byb3RvNDIuYXBwZW5kRHluYW1pY05vZGUgPSBmdW5jdGlvbiBhcHBlbmREeW5hbWljTm9kZSh2YWx1ZSQkMSkgewogICAgICB2YXIgbm9kZSA9IHRoaXMuX19hcHBlbmROb2RlKHZhbHVlJCQxKTsKCiAgICAgIHZhciBib3VuZHMgPSBuZXcgU2luZ2xlTm9kZUJvdW5kcyh0aGlzLmVsZW1lbnQsIG5vZGUpOwogICAgICB0aGlzLmRpZEFwcGVuZEJvdW5kcyhib3VuZHMpOwogICAgfTsKCiAgICBfcHJvdG80Mi50cnVzdGVkQ29udGVudCA9IGZ1bmN0aW9uIHRydXN0ZWRDb250ZW50KHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiB0aGlzLl9fYXBwZW5kSFRNTCh2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzQyLnVudHJ1c3RlZENvbnRlbnQgPSBmdW5jdGlvbiB1bnRydXN0ZWRDb250ZW50KHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiB0aGlzLl9fYXBwZW5kVGV4dCh2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzQyLmFwcGVuZENvbW1lbnQgPSBmdW5jdGlvbiBhcHBlbmRDb21tZW50KHN0cmluZykgewogICAgICByZXR1cm4gdGhpcy5kaWRBcHBlbmROb2RlKHRoaXMuX19hcHBlbmRDb21tZW50KHN0cmluZykpOwogICAgfTsKCiAgICBfcHJvdG80Mi5fX2FwcGVuZENvbW1lbnQgPSBmdW5jdGlvbiBfX2FwcGVuZENvbW1lbnQoc3RyaW5nKSB7CiAgICAgIHZhciBkb20gPSB0aGlzLmRvbSwKICAgICAgICAgIGVsZW1lbnQgPSB0aGlzLmVsZW1lbnQsCiAgICAgICAgICBuZXh0U2libGluZyA9IHRoaXMubmV4dFNpYmxpbmc7CiAgICAgIHZhciBub2RlID0gZG9tLmNyZWF0ZUNvbW1lbnQoc3RyaW5nKTsKICAgICAgZG9tLmluc2VydEJlZm9yZShlbGVtZW50LCBub2RlLCBuZXh0U2libGluZyk7CiAgICAgIHJldHVybiBub2RlOwogICAgfTsKCiAgICBfcHJvdG80Mi5fX3NldEF0dHJpYnV0ZSA9IGZ1bmN0aW9uIF9fc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlJCQxLCBuYW1lc3BhY2UpIHsKICAgICAgdGhpcy5kb20uc2V0QXR0cmlidXRlKHRoaXMuY29uc3RydWN0aW5nLCBuYW1lLCB2YWx1ZSQkMSwgbmFtZXNwYWNlKTsKICAgIH07CgogICAgX3Byb3RvNDIuX19zZXRQcm9wZXJ0eSA9IGZ1bmN0aW9uIF9fc2V0UHJvcGVydHkobmFtZSwgdmFsdWUkJDEpIHsKICAgICAgdGhpcy5jb25zdHJ1Y3RpbmdbbmFtZV0gPSB2YWx1ZSQkMTsKICAgIH07CgogICAgX3Byb3RvNDIuc2V0U3RhdGljQXR0cmlidXRlID0gZnVuY3Rpb24gc2V0U3RhdGljQXR0cmlidXRlKG5hbWUsIHZhbHVlJCQxLCBuYW1lc3BhY2UpIHsKICAgICAgdGhpcy5fX3NldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSQkMSwgbmFtZXNwYWNlKTsKICAgIH07CgogICAgX3Byb3RvNDIuc2V0RHluYW1pY0F0dHJpYnV0ZSA9IGZ1bmN0aW9uIHNldER5bmFtaWNBdHRyaWJ1dGUobmFtZSwgdmFsdWUkJDEsIHRydXN0aW5nLCBuYW1lc3BhY2UpIHsKICAgICAgdmFyIGVsZW1lbnQgPSB0aGlzLmNvbnN0cnVjdGluZzsKICAgICAgdmFyIGF0dHJpYnV0ZSA9IHRoaXMuZW52LmF0dHJpYnV0ZUZvcihlbGVtZW50LCBuYW1lLCB0cnVzdGluZywgbmFtZXNwYWNlKTsKICAgICAgYXR0cmlidXRlLnNldCh0aGlzLCB2YWx1ZSQkMSwgdGhpcy5lbnYpOwogICAgICByZXR1cm4gYXR0cmlidXRlOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKE5ld0VsZW1lbnRCdWlsZGVyLCBbewogICAgICBrZXk6ICJlbGVtZW50IiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuY3Vyc29yU3RhY2suY3VycmVudC5lbGVtZW50OwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogIm5leHRTaWJsaW5nIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuY3Vyc29yU3RhY2suY3VycmVudC5uZXh0U2libGluZzsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIE5ld0VsZW1lbnRCdWlsZGVyOwogIH0oKTsKCiAgX2V4cG9ydHMuTmV3RWxlbWVudEJ1aWxkZXIgPSBOZXdFbGVtZW50QnVpbGRlcjsKCiAgdmFyIFNpbXBsZUJsb2NrVHJhY2tlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFNpbXBsZUJsb2NrVHJhY2tlcihwYXJlbnQpIHsKICAgICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7CiAgICAgIHRoaXMuZmlyc3QgPSBudWxsOwogICAgICB0aGlzLmxhc3QgPSBudWxsOwogICAgICB0aGlzLmRlc3Ryb3lhYmxlcyA9IG51bGw7CiAgICAgIHRoaXMubmVzdGluZyA9IDA7CiAgICB9CgogICAgdmFyIF9wcm90bzQzID0gU2ltcGxlQmxvY2tUcmFja2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG80My5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdmFyIGRlc3Ryb3lhYmxlcyA9IHRoaXMuZGVzdHJveWFibGVzOwoKICAgICAgaWYgKGRlc3Ryb3lhYmxlcyAmJiBkZXN0cm95YWJsZXMubGVuZ3RoKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkZXN0cm95YWJsZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGRlc3Ryb3lhYmxlc1tpXS5kZXN0cm95KCk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQzLnBhcmVudEVsZW1lbnQgPSBmdW5jdGlvbiBwYXJlbnRFbGVtZW50KCkgewogICAgICByZXR1cm4gdGhpcy5wYXJlbnQ7CiAgICB9OwoKICAgIF9wcm90bzQzLmZpcnN0Tm9kZSA9IGZ1bmN0aW9uIGZpcnN0Tm9kZSgpIHsKICAgICAgdmFyIGZpcnN0ID0gdGhpcy5maXJzdDsKICAgICAgcmV0dXJuIGZpcnN0LmZpcnN0Tm9kZSgpOwogICAgfTsKCiAgICBfcHJvdG80My5sYXN0Tm9kZSA9IGZ1bmN0aW9uIGxhc3ROb2RlKCkgewogICAgICB2YXIgbGFzdCA9IHRoaXMubGFzdDsKICAgICAgcmV0dXJuIGxhc3QubGFzdE5vZGUoKTsKICAgIH07CgogICAgX3Byb3RvNDMub3BlbkVsZW1lbnQgPSBmdW5jdGlvbiBvcGVuRWxlbWVudChlbGVtZW50KSB7CiAgICAgIHRoaXMuZGlkQXBwZW5kTm9kZShlbGVtZW50KTsKICAgICAgdGhpcy5uZXN0aW5nKys7CiAgICB9OwoKICAgIF9wcm90bzQzLmNsb3NlRWxlbWVudCA9IGZ1bmN0aW9uIGNsb3NlRWxlbWVudCgpIHsKICAgICAgdGhpcy5uZXN0aW5nLS07CiAgICB9OwoKICAgIF9wcm90bzQzLmRpZEFwcGVuZE5vZGUgPSBmdW5jdGlvbiBkaWRBcHBlbmROb2RlKG5vZGUpIHsKICAgICAgaWYgKHRoaXMubmVzdGluZyAhPT0gMCkgcmV0dXJuOwoKICAgICAgaWYgKCF0aGlzLmZpcnN0KSB7CiAgICAgICAgdGhpcy5maXJzdCA9IG5ldyBGaXJzdChub2RlKTsKICAgICAgfQoKICAgICAgdGhpcy5sYXN0ID0gbmV3IExhc3Qobm9kZSk7CiAgICB9OwoKICAgIF9wcm90bzQzLmRpZEFwcGVuZEJvdW5kcyA9IGZ1bmN0aW9uIGRpZEFwcGVuZEJvdW5kcyhib3VuZHMpIHsKICAgICAgaWYgKHRoaXMubmVzdGluZyAhPT0gMCkgcmV0dXJuOwoKICAgICAgaWYgKCF0aGlzLmZpcnN0KSB7CiAgICAgICAgdGhpcy5maXJzdCA9IGJvdW5kczsKICAgICAgfQoKICAgICAgdGhpcy5sYXN0ID0gYm91bmRzOwogICAgfTsKCiAgICBfcHJvdG80My5uZXdEZXN0cm95YWJsZSA9IGZ1bmN0aW9uIG5ld0Rlc3Ryb3lhYmxlKGQpIHsKICAgICAgdGhpcy5kZXN0cm95YWJsZXMgPSB0aGlzLmRlc3Ryb3lhYmxlcyB8fCBbXTsKICAgICAgdGhpcy5kZXN0cm95YWJsZXMucHVzaChkKTsKICAgIH07CgogICAgX3Byb3RvNDMuZmluYWxpemUgPSBmdW5jdGlvbiBmaW5hbGl6ZShzdGFjaykgewogICAgICBpZiAodGhpcy5maXJzdCA9PT0gbnVsbCkgewogICAgICAgIHN0YWNrLmFwcGVuZENvbW1lbnQoJycpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBTaW1wbGVCbG9ja1RyYWNrZXI7CiAgfSgpOwoKICB2YXIgUmVtb3RlQmxvY2tUcmFja2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9TaW1wbGVCbG9ja1RyYWNrZXIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShSZW1vdGVCbG9ja1RyYWNrZXIsIF9TaW1wbGVCbG9ja1RyYWNrZXIpOwoKICAgIGZ1bmN0aW9uIFJlbW90ZUJsb2NrVHJhY2tlcigpIHsKICAgICAgcmV0dXJuIF9TaW1wbGVCbG9ja1RyYWNrZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG80NCA9IFJlbW90ZUJsb2NrVHJhY2tlci5wcm90b3R5cGU7CgogICAgX3Byb3RvNDQuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIF9TaW1wbGVCbG9ja1RyYWNrZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTsKCiAgICAgIGNsZWFyKHRoaXMpOwogICAgfTsKCiAgICByZXR1cm4gUmVtb3RlQmxvY2tUcmFja2VyOwogIH0oU2ltcGxlQmxvY2tUcmFja2VyKTsKCiAgdmFyIFVwZGF0YWJsZUJsb2NrVHJhY2tlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfU2ltcGxlQmxvY2tUcmFja2VyMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFVwZGF0YWJsZUJsb2NrVHJhY2tlciwgX1NpbXBsZUJsb2NrVHJhY2tlcjIpOwoKICAgIGZ1bmN0aW9uIFVwZGF0YWJsZUJsb2NrVHJhY2tlcigpIHsKICAgICAgcmV0dXJuIF9TaW1wbGVCbG9ja1RyYWNrZXIyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDUgPSBVcGRhdGFibGVCbG9ja1RyYWNrZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzQ1LnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoZW52KSB7CiAgICAgIHZhciBkZXN0cm95YWJsZXMgPSB0aGlzLmRlc3Ryb3lhYmxlczsKCiAgICAgIGlmIChkZXN0cm95YWJsZXMgJiYgZGVzdHJveWFibGVzLmxlbmd0aCkgewogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVzdHJveWFibGVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBlbnYuZGlkRGVzdHJveShkZXN0cm95YWJsZXNbaV0pOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdmFyIG5leHRTaWJsaW5nID0gY2xlYXIodGhpcyk7CiAgICAgIHRoaXMuZmlyc3QgPSBudWxsOwogICAgICB0aGlzLmxhc3QgPSBudWxsOwogICAgICB0aGlzLmRlc3Ryb3lhYmxlcyA9IG51bGw7CiAgICAgIHRoaXMubmVzdGluZyA9IDA7CiAgICAgIHJldHVybiBuZXh0U2libGluZzsKICAgIH07CgogICAgcmV0dXJuIFVwZGF0YWJsZUJsb2NrVHJhY2tlcjsKICB9KFNpbXBsZUJsb2NrVHJhY2tlcik7CgogIHZhciBCbG9ja0xpc3RUcmFja2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQmxvY2tMaXN0VHJhY2tlcihwYXJlbnQsIGJvdW5kTGlzdCkgewogICAgICB0aGlzLnBhcmVudCA9IHBhcmVudDsKICAgICAgdGhpcy5ib3VuZExpc3QgPSBib3VuZExpc3Q7CiAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50OwogICAgICB0aGlzLmJvdW5kTGlzdCA9IGJvdW5kTGlzdDsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDYgPSBCbG9ja0xpc3RUcmFja2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG80Ni5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdGhpcy5ib3VuZExpc3QuZm9yRWFjaE5vZGUoZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICByZXR1cm4gbm9kZS5kZXN0cm95KCk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG80Ni5wYXJlbnRFbGVtZW50ID0gZnVuY3Rpb24gcGFyZW50RWxlbWVudCgpIHsKICAgICAgcmV0dXJuIHRoaXMucGFyZW50OwogICAgfTsKCiAgICBfcHJvdG80Ni5maXJzdE5vZGUgPSBmdW5jdGlvbiBmaXJzdE5vZGUoKSB7CiAgICAgIHZhciBoZWFkID0gdGhpcy5ib3VuZExpc3QuaGVhZCgpOwogICAgICByZXR1cm4gaGVhZC5maXJzdE5vZGUoKTsKICAgIH07CgogICAgX3Byb3RvNDYubGFzdE5vZGUgPSBmdW5jdGlvbiBsYXN0Tm9kZSgpIHsKICAgICAgdmFyIHRhaWwgPSB0aGlzLmJvdW5kTGlzdC50YWlsKCk7CiAgICAgIHJldHVybiB0YWlsLmxhc3ROb2RlKCk7CiAgICB9OwoKICAgIF9wcm90bzQ2Lm9wZW5FbGVtZW50ID0gZnVuY3Rpb24gb3BlbkVsZW1lbnQoX2VsZW1lbnQpIHt9OwoKICAgIF9wcm90bzQ2LmNsb3NlRWxlbWVudCA9IGZ1bmN0aW9uIGNsb3NlRWxlbWVudCgpIHt9OwoKICAgIF9wcm90bzQ2LmRpZEFwcGVuZE5vZGUgPSBmdW5jdGlvbiBkaWRBcHBlbmROb2RlKF9ub2RlKSB7fTsKCiAgICBfcHJvdG80Ni5kaWRBcHBlbmRCb3VuZHMgPSBmdW5jdGlvbiBkaWRBcHBlbmRCb3VuZHMoX2JvdW5kcykge307CgogICAgX3Byb3RvNDYubmV3RGVzdHJveWFibGUgPSBmdW5jdGlvbiBuZXdEZXN0cm95YWJsZShfZCkge307CgogICAgX3Byb3RvNDYuZmluYWxpemUgPSBmdW5jdGlvbiBmaW5hbGl6ZShfc3RhY2spIHt9OwoKICAgIHJldHVybiBCbG9ja0xpc3RUcmFja2VyOwogIH0oKTsKCiAgZnVuY3Rpb24gY2xpZW50QnVpbGRlcihlbnYsIGN1cnNvcikgewogICAgcmV0dXJuIE5ld0VsZW1lbnRCdWlsZGVyLmZvckluaXRpYWxSZW5kZXIoZW52LCBjdXJzb3IpOwogIH0KCiAgdmFyIE1BWF9TTUkgPSAweGZmZmZmZmY7CgogIHZhciBJbm5lclN0YWNrID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSW5uZXJTdGFjayhpbm5lciwganMpIHsKICAgICAgaWYgKGlubmVyID09PSB2b2lkIDApIHsKICAgICAgICBpbm5lciA9IG5ldyBfbG93TGV2ZWwuU3RhY2soKTsKICAgICAgfQoKICAgICAgaWYgKGpzID09PSB2b2lkIDApIHsKICAgICAgICBqcyA9IFtdOwogICAgICB9CgogICAgICB0aGlzLmlubmVyID0gaW5uZXI7CiAgICAgIHRoaXMuanMgPSBqczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDcgPSBJbm5lclN0YWNrLnByb3RvdHlwZTsKCiAgICBfcHJvdG80Ny5zbGljZSA9IGZ1bmN0aW9uIHNsaWNlKHN0YXJ0LCBlbmQpIHsKICAgICAgdmFyIGlubmVyOwoKICAgICAgaWYgKHR5cGVvZiBzdGFydCA9PT0gJ251bWJlcicgJiYgdHlwZW9mIGVuZCA9PT0gJ251bWJlcicpIHsKICAgICAgICBpbm5lciA9IHRoaXMuaW5uZXIuc2xpY2Uoc3RhcnQsIGVuZCk7CiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHN0YXJ0ID09PSAnbnVtYmVyJyAmJiBlbmQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGlubmVyID0gdGhpcy5pbm5lci5zbGljZUZyb20oc3RhcnQpOwogICAgICB9IGVsc2UgewogICAgICAgIGlubmVyID0gdGhpcy5pbm5lci5jbG9uZSgpOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IElubmVyU3RhY2soaW5uZXIsIHRoaXMuanMuc2xpY2Uoc3RhcnQsIGVuZCkpOwogICAgfTsKCiAgICBfcHJvdG80Ny5zbGljZUlubmVyID0gZnVuY3Rpb24gc2xpY2VJbm5lcihzdGFydCwgZW5kKSB7CiAgICAgIHZhciBvdXQgPSBbXTsKCiAgICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7CiAgICAgICAgb3V0LnB1c2godGhpcy5nZXQoaSkpOwogICAgICB9CgogICAgICByZXR1cm4gb3V0OwogICAgfTsKCiAgICBfcHJvdG80Ny5jb3B5ID0gZnVuY3Rpb24gY29weShmcm9tLCB0bykgewogICAgICB0aGlzLmlubmVyLmNvcHkoZnJvbSwgdG8pOwogICAgfTsKCiAgICBfcHJvdG80Ny53cml0ZSA9IGZ1bmN0aW9uIHdyaXRlKHBvcywgdmFsdWUkJDEpIHsKICAgICAgaWYgKGlzSW1tZWRpYXRlKHZhbHVlJCQxKSkgewogICAgICAgIHRoaXMuaW5uZXIud3JpdGVSYXcocG9zLCBlbmNvZGVJbW1lZGlhdGUodmFsdWUkJDEpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgaWR4ID0gdGhpcy5qcy5sZW5ndGg7CiAgICAgICAgdGhpcy5qcy5wdXNoKHZhbHVlJCQxKTsKICAgICAgICB0aGlzLmlubmVyLndyaXRlUmF3KHBvcywgfmlkeCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNDcud3JpdGVSYXcgPSBmdW5jdGlvbiB3cml0ZVJhdyhwb3MsIHZhbHVlJCQxKSB7CiAgICAgIHRoaXMuaW5uZXIud3JpdGVSYXcocG9zLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzQ3LmdldCA9IGZ1bmN0aW9uIGdldChwb3MpIHsKICAgICAgdmFyIHZhbHVlJCQxID0gdGhpcy5pbm5lci5nZXRSYXcocG9zKTsKCiAgICAgIGlmICh2YWx1ZSQkMSA8IDApIHsKICAgICAgICByZXR1cm4gdGhpcy5qc1t+dmFsdWUkJDFdOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBkZWNvZGVJbW1lZGlhdGUodmFsdWUkJDEpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQ3LnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoKSB7CiAgICAgIHRoaXMuaW5uZXIucmVzZXQoKTsKICAgICAgdGhpcy5qcy5sZW5ndGggPSAwOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKElubmVyU3RhY2ssIFt7CiAgICAgIGtleTogImxlbmd0aCIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmlubmVyLmxlbigpOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gSW5uZXJTdGFjazsKICB9KCk7CgogIHZhciBFdmFsdWF0aW9uU3RhY2sgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBFdmFsdWF0aW9uU3RhY2soc3RhY2ssIGZwLCBzcCkgewogICAgICB0aGlzLnN0YWNrID0gc3RhY2s7CiAgICAgIHRoaXMuZnAgPSBmcDsKICAgICAgdGhpcy5zcCA9IHNwOwogICAgfQoKICAgIEV2YWx1YXRpb25TdGFjay5lbXB0eSA9IGZ1bmN0aW9uIGVtcHR5KCkgewogICAgICByZXR1cm4gbmV3IHRoaXMobmV3IElubmVyU3RhY2soKSwgMCwgLTEpOwogICAgfTsKCiAgICBFdmFsdWF0aW9uU3RhY2sucmVzdG9yZSA9IGZ1bmN0aW9uIHJlc3RvcmUoc25hcHNob3QpIHsKICAgICAgdmFyIHN0YWNrID0gbmV3IElubmVyU3RhY2soKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc25hcHNob3QubGVuZ3RoOyBpKyspIHsKICAgICAgICBzdGFjay53cml0ZShpLCBzbmFwc2hvdFtpXSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXcgdGhpcyhzdGFjaywgMCwgc25hcHNob3QubGVuZ3RoIC0gMSk7CiAgICB9OwoKICAgIHZhciBfcHJvdG80OCA9IEV2YWx1YXRpb25TdGFjay5wcm90b3R5cGU7CgogICAgX3Byb3RvNDgucHVzaCA9IGZ1bmN0aW9uIHB1c2godmFsdWUkJDEpIHsKICAgICAgdGhpcy5zdGFjay53cml0ZSgrK3RoaXMuc3AsIHZhbHVlJCQxKTsKICAgIH07CgogICAgX3Byb3RvNDgucHVzaEVuY29kZWRJbW1lZGlhdGUgPSBmdW5jdGlvbiBwdXNoRW5jb2RlZEltbWVkaWF0ZSh2YWx1ZSQkMSkgewogICAgICB0aGlzLnN0YWNrLndyaXRlUmF3KCsrdGhpcy5zcCwgdmFsdWUkJDEpOwogICAgfTsKCiAgICBfcHJvdG80OC5wdXNoTnVsbCA9IGZ1bmN0aW9uIHB1c2hOdWxsKCkgewogICAgICB0aGlzLnN0YWNrLndyaXRlKCsrdGhpcy5zcCwgbnVsbCk7CiAgICB9OwoKICAgIF9wcm90bzQ4LmR1cCA9IGZ1bmN0aW9uIGR1cChwb3NpdGlvbikgewogICAgICBpZiAocG9zaXRpb24gPT09IHZvaWQgMCkgewogICAgICAgIHBvc2l0aW9uID0gdGhpcy5zcDsKICAgICAgfQoKICAgICAgdGhpcy5zdGFjay5jb3B5KHBvc2l0aW9uLCArK3RoaXMuc3ApOwogICAgfTsKCiAgICBfcHJvdG80OC5jb3B5ID0gZnVuY3Rpb24gY29weShmcm9tLCB0bykgewogICAgICB0aGlzLnN0YWNrLmNvcHkoZnJvbSwgdG8pOwogICAgfTsKCiAgICBfcHJvdG80OC5wb3AgPSBmdW5jdGlvbiBwb3AobikgewogICAgICBpZiAobiA9PT0gdm9pZCAwKSB7CiAgICAgICAgbiA9IDE7CiAgICAgIH0KCiAgICAgIHZhciB0b3AgPSB0aGlzLnN0YWNrLmdldCh0aGlzLnNwKTsKICAgICAgdGhpcy5zcCAtPSBuOwogICAgICByZXR1cm4gdG9wOwogICAgfTsKCiAgICBfcHJvdG80OC5wb3BTbWkgPSBmdW5jdGlvbiBwb3BTbWkoKSB7CiAgICAgIHJldHVybiB0aGlzLnN0YWNrLmdldCh0aGlzLnNwLS0pOwogICAgfTsKCiAgICBfcHJvdG80OC5wZWVrID0gZnVuY3Rpb24gcGVlayhvZmZzZXQpIHsKICAgICAgaWYgKG9mZnNldCA9PT0gdm9pZCAwKSB7CiAgICAgICAgb2Zmc2V0ID0gMDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suZ2V0KHRoaXMuc3AgLSBvZmZzZXQpOwogICAgfTsKCiAgICBfcHJvdG80OC5nZXQgPSBmdW5jdGlvbiBnZXQob2Zmc2V0LCBiYXNlKSB7CiAgICAgIGlmIChiYXNlID09PSB2b2lkIDApIHsKICAgICAgICBiYXNlID0gdGhpcy5mcDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suZ2V0KGJhc2UgKyBvZmZzZXQpOwogICAgfTsKCiAgICBfcHJvdG80OC5zZXQgPSBmdW5jdGlvbiBzZXQodmFsdWUkJDEsIG9mZnNldCwgYmFzZSkgewogICAgICBpZiAoYmFzZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgYmFzZSA9IHRoaXMuZnA7CiAgICAgIH0KCiAgICAgIHRoaXMuc3RhY2sud3JpdGUoYmFzZSArIG9mZnNldCwgdmFsdWUkJDEpOwogICAgfTsKCiAgICBfcHJvdG80OC5zbGljZSA9IGZ1bmN0aW9uIHNsaWNlKHN0YXJ0LCBlbmQpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suc2xpY2Uoc3RhcnQsIGVuZCk7CiAgICB9OwoKICAgIF9wcm90bzQ4LnNsaWNlQXJyYXkgPSBmdW5jdGlvbiBzbGljZUFycmF5KHN0YXJ0LCBlbmQpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suc2xpY2VJbm5lcihzdGFydCwgZW5kKTsKICAgIH07CgogICAgX3Byb3RvNDguY2FwdHVyZSA9IGZ1bmN0aW9uIGNhcHR1cmUoaXRlbXMpIHsKICAgICAgdmFyIGVuZCA9IHRoaXMuc3AgKyAxOwogICAgICB2YXIgc3RhcnQgPSBlbmQgLSBpdGVtczsKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suc2xpY2VJbm5lcihzdGFydCwgZW5kKTsKICAgIH07CgogICAgX3Byb3RvNDgucmVzZXQgPSBmdW5jdGlvbiByZXNldCgpIHsKICAgICAgdGhpcy5zdGFjay5yZXNldCgpOwogICAgfTsKCiAgICBfcHJvdG80OC50b0FycmF5ID0gZnVuY3Rpb24gdG9BcnJheSgpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suc2xpY2VJbm5lcih0aGlzLmZwLCB0aGlzLnNwICsgMSk7CiAgICB9OwoKICAgIHJldHVybiBFdmFsdWF0aW9uU3RhY2s7CiAgfSgpOwoKICBmdW5jdGlvbiBpc0ltbWVkaWF0ZSh2YWx1ZSQkMSkgewogICAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWUkJDE7CiAgICBpZiAodmFsdWUkJDEgPT09IG51bGwgfHwgdmFsdWUkJDEgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRydWU7CgogICAgc3dpdGNoICh0eXBlKSB7CiAgICAgIGNhc2UgJ2Jvb2xlYW4nOgogICAgICBjYXNlICd1bmRlZmluZWQnOgogICAgICAgIHJldHVybiB0cnVlOwoKICAgICAgY2FzZSAnbnVtYmVyJzoKICAgICAgICAvLyBub3QgYW4gaW50ZWdlcgogICAgICAgIGlmICh2YWx1ZSQkMSAlIDEgIT09IDApIHJldHVybiBmYWxzZTsKICAgICAgICB2YXIgYWJzID0gTWF0aC5hYnModmFsdWUkJDEpOwogICAgICAgIGlmIChhYnMgPiBNQVhfU01JKSByZXR1cm4gZmFsc2U7CiAgICAgICAgcmV0dXJuIHRydWU7CgogICAgICBkZWZhdWx0OgogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGVuY29kZVNtaShwcmltaXRpdmUpIHsKICAgIGlmIChwcmltaXRpdmUgPCAwKSB7CiAgICAgIHZhciBhYnMgPSBNYXRoLmFicyhwcmltaXRpdmUpOwogICAgICBpZiAoYWJzID4gTUFYX1NNSSkgdGhyb3cgbmV3IEVycm9yKCdub3Qgc21pJyk7CiAgICAgIHJldHVybiBNYXRoLmFicyhwcmltaXRpdmUpIDw8IDMgfCA0CiAgICAgIC8qIE5FR0FUSVZFICovCiAgICAgIDsKICAgIH0gZWxzZSB7CiAgICAgIGlmIChwcmltaXRpdmUgPiBNQVhfU01JKSB0aHJvdyBuZXcgRXJyb3IoJ25vdCBzbWknKTsKICAgICAgcmV0dXJuIHByaW1pdGl2ZSA8PCAzIHwgMAogICAgICAvKiBOVU1CRVIgKi8KICAgICAgOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZW5jb2RlSW1tZWRpYXRlKHByaW1pdGl2ZSkgewogICAgc3dpdGNoICh0eXBlb2YgcHJpbWl0aXZlKSB7CiAgICAgIGNhc2UgJ251bWJlcic6CiAgICAgICAgcmV0dXJuIGVuY29kZVNtaShwcmltaXRpdmUpOwoKICAgICAgY2FzZSAnYm9vbGVhbic6CiAgICAgICAgcmV0dXJuIHByaW1pdGl2ZSA/IDExCiAgICAgICAgLyogVHJ1ZSAqLwogICAgICAgIDogMwogICAgICAgIC8qIEZhbHNlICovCiAgICAgICAgOwoKICAgICAgY2FzZSAnb2JqZWN0JzoKICAgICAgICAvLyBhc3N1bWUgbnVsbAogICAgICAgIHJldHVybiAxOQogICAgICAgIC8qIE51bGwgKi8KICAgICAgICA7CgogICAgICBjYXNlICd1bmRlZmluZWQnOgogICAgICAgIHJldHVybiAyNwogICAgICAgIC8qIFVuZGVmICovCiAgICAgICAgOwoKICAgICAgZGVmYXVsdDoKICAgICAgICB0aHJvdyAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBkZWNvZGVTbWkoc21pKSB7CiAgICBzd2l0Y2ggKHNtaSAmIDcpIHsKICAgICAgY2FzZSAwCiAgICAgIC8qIE5VTUJFUiAqLwogICAgICA6CiAgICAgICAgcmV0dXJuIHNtaSA+PiAzOwoKICAgICAgY2FzZSA0CiAgICAgIC8qIE5FR0FUSVZFICovCiAgICAgIDoKICAgICAgICByZXR1cm4gLShzbWkgPj4gMyk7CgogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGRlY29kZUltbWVkaWF0ZShpbW1lZGlhdGUpIHsKICAgIHN3aXRjaCAoaW1tZWRpYXRlKSB7CiAgICAgIGNhc2UgMwogICAgICAvKiBGYWxzZSAqLwogICAgICA6CiAgICAgICAgcmV0dXJuIGZhbHNlOwoKICAgICAgY2FzZSAxMQogICAgICAvKiBUcnVlICovCiAgICAgIDoKICAgICAgICByZXR1cm4gdHJ1ZTsKCiAgICAgIGNhc2UgMTkKICAgICAgLyogTnVsbCAqLwogICAgICA6CiAgICAgICAgcmV0dXJuIG51bGw7CgogICAgICBjYXNlIDI3CiAgICAgIC8qIFVuZGVmICovCiAgICAgIDoKICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwoKICAgICAgZGVmYXVsdDoKICAgICAgICByZXR1cm4gZGVjb2RlU21pKGltbWVkaWF0ZSk7CiAgICB9CiAgfQoKICB2YXIgVXBkYXRpbmdWTSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFVwZGF0aW5nVk0oZW52LCBwcm9ncmFtLCBfcmVmNTcpIHsKICAgICAgdmFyIF9yZWY1NyRhbHdheXNSZXZhbGlkYSA9IF9yZWY1Ny5hbHdheXNSZXZhbGlkYXRlLAogICAgICAgICAgYWx3YXlzUmV2YWxpZGF0ZSA9IF9yZWY1NyRhbHdheXNSZXZhbGlkYSA9PT0gdm9pZCAwID8gZmFsc2UgOiBfcmVmNTckYWx3YXlzUmV2YWxpZGE7CiAgICAgIHRoaXMuZnJhbWVTdGFjayA9IG5ldyBfdXRpbC5TdGFjaygpOwogICAgICB0aGlzLmVudiA9IGVudjsKICAgICAgdGhpcy5jb25zdGFudHMgPSBwcm9ncmFtLmNvbnN0YW50czsKICAgICAgdGhpcy5kb20gPSBlbnYuZ2V0RE9NKCk7CiAgICAgIHRoaXMuYWx3YXlzUmV2YWxpZGF0ZSA9IGFsd2F5c1JldmFsaWRhdGU7CiAgICB9CgogICAgdmFyIF9wcm90bzQ5ID0gVXBkYXRpbmdWTS5wcm90b3R5cGU7CgogICAgX3Byb3RvNDkuZXhlY3V0ZSA9IGZ1bmN0aW9uIGV4ZWN1dGUob3Bjb2RlcywgaGFuZGxlcikgewogICAgICB2YXIgZnJhbWVTdGFjayA9IHRoaXMuZnJhbWVTdGFjazsKICAgICAgdGhpcy50cnkob3Bjb2RlcywgaGFuZGxlcik7CgogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgIGlmIChmcmFtZVN0YWNrLmlzRW1wdHkoKSkgYnJlYWs7CiAgICAgICAgdmFyIG9wY29kZSA9IHRoaXMuZnJhbWUubmV4dFN0YXRlbWVudCgpOwoKICAgICAgICBpZiAob3Bjb2RlID09PSBudWxsKSB7CiAgICAgICAgICB0aGlzLmZyYW1lU3RhY2sucG9wKCk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIG9wY29kZS5ldmFsdWF0ZSh0aGlzKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG80OS5nb3RvID0gZnVuY3Rpb24gZ290byhvcCkgewogICAgICB0aGlzLmZyYW1lLmdvdG8ob3ApOwogICAgfTsKCiAgICBfcHJvdG80OS50cnkgPSBmdW5jdGlvbiBfdHJ5KG9wcywgaGFuZGxlcikgewogICAgICB0aGlzLmZyYW1lU3RhY2sucHVzaChuZXcgVXBkYXRpbmdWTUZyYW1lKG9wcywgaGFuZGxlcikpOwogICAgfTsKCiAgICBfcHJvdG80OS50aHJvdyA9IGZ1bmN0aW9uIF90aHJvdygpIHsKICAgICAgdGhpcy5mcmFtZS5oYW5kbGVFeGNlcHRpb24oKTsKICAgICAgdGhpcy5mcmFtZVN0YWNrLnBvcCgpOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKFVwZGF0aW5nVk0sIFt7CiAgICAgIGtleTogImZyYW1lIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZnJhbWVTdGFjay5jdXJyZW50OwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gVXBkYXRpbmdWTTsKICB9KCk7CgogIF9leHBvcnRzLlVwZGF0aW5nVk0gPSBVcGRhdGluZ1ZNOwoKICB2YXIgQmxvY2tPcGNvZGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1VwZGF0aW5nT3Bjb2RlOSkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEJsb2NrT3Bjb2RlLCBfVXBkYXRpbmdPcGNvZGU5KTsKCiAgICBmdW5jdGlvbiBCbG9ja09wY29kZShzdGFydCwgc3RhdGUsIHJ1bnRpbWUsIGJvdW5kcywgY2hpbGRyZW4pIHsKICAgICAgdmFyIF90aGlzMTU7CgogICAgICBfdGhpczE1ID0gX1VwZGF0aW5nT3Bjb2RlOS5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMTUuc3RhcnQgPSBzdGFydDsKICAgICAgX3RoaXMxNS5zdGF0ZSA9IHN0YXRlOwogICAgICBfdGhpczE1LnJ1bnRpbWUgPSBydW50aW1lOwogICAgICBfdGhpczE1LnR5cGUgPSAnYmxvY2snOwogICAgICBfdGhpczE1Lm5leHQgPSBudWxsOwogICAgICBfdGhpczE1LnByZXYgPSBudWxsOwogICAgICBfdGhpczE1LmNoaWxkcmVuID0gY2hpbGRyZW47CiAgICAgIF90aGlzMTUuYm91bmRzID0gYm91bmRzOwogICAgICByZXR1cm4gX3RoaXMxNTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTAgPSBCbG9ja09wY29kZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNTAucGFyZW50RWxlbWVudCA9IGZ1bmN0aW9uIHBhcmVudEVsZW1lbnQoKSB7CiAgICAgIHJldHVybiB0aGlzLmJvdW5kcy5wYXJlbnRFbGVtZW50KCk7CiAgICB9OwoKICAgIF9wcm90bzUwLmZpcnN0Tm9kZSA9IGZ1bmN0aW9uIGZpcnN0Tm9kZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuYm91bmRzLmZpcnN0Tm9kZSgpOwogICAgfTsKCiAgICBfcHJvdG81MC5sYXN0Tm9kZSA9IGZ1bmN0aW9uIGxhc3ROb2RlKCkgewogICAgICByZXR1cm4gdGhpcy5ib3VuZHMubGFzdE5vZGUoKTsKICAgIH07CgogICAgX3Byb3RvNTAuZXZhbHVhdGUgPSBmdW5jdGlvbiBldmFsdWF0ZSh2bSkgewogICAgICB2bS50cnkodGhpcy5jaGlsZHJlbiwgbnVsbCk7CiAgICB9OwoKICAgIF9wcm90bzUwLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICB0aGlzLmJvdW5kcy5kZXN0cm95KCk7CiAgICB9OwoKICAgIF9wcm90bzUwLmRpZERlc3Ryb3kgPSBmdW5jdGlvbiBkaWREZXN0cm95KCkgewogICAgICB0aGlzLnJ1bnRpbWUuZW52LmRpZERlc3Ryb3kodGhpcy5ib3VuZHMpOwogICAgfTsKCiAgICByZXR1cm4gQmxvY2tPcGNvZGU7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBUcnlPcGNvZGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Jsb2NrT3Bjb2RlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoVHJ5T3Bjb2RlLCBfQmxvY2tPcGNvZGUpOwoKICAgIGZ1bmN0aW9uIFRyeU9wY29kZShzdGFydCwgc3RhdGUsIHJ1bnRpbWUsIGJvdW5kcywgY2hpbGRyZW4pIHsKICAgICAgdmFyIF90aGlzMTY7CgogICAgICBfdGhpczE2ID0gX0Jsb2NrT3Bjb2RlLmNhbGwodGhpcywgc3RhcnQsIHN0YXRlLCBydW50aW1lLCBib3VuZHMsIGNoaWxkcmVuKSB8fCB0aGlzOwogICAgICBfdGhpczE2LnR5cGUgPSAndHJ5JzsKICAgICAgX3RoaXMxNi50YWcgPSBfdGhpczE2Ll90YWcgPSAoMCwgX3JlZmVyZW5jZTIuY3JlYXRlVXBkYXRhYmxlVGFnKSgpOwogICAgICByZXR1cm4gX3RoaXMxNjsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTEgPSBUcnlPcGNvZGUucHJvdG90eXBlOwoKICAgIF9wcm90bzUxLmRpZEluaXRpYWxpemVDaGlsZHJlbiA9IGZ1bmN0aW9uIGRpZEluaXRpYWxpemVDaGlsZHJlbigpIHsKICAgICAgKDAsIF9yZWZlcmVuY2UyLnVwZGF0ZSkodGhpcy5fdGFnLCAoMCwgX3JlZmVyZW5jZTIuY29tYmluZVNsaWNlKSh0aGlzLmNoaWxkcmVuKSk7CiAgICB9OwoKICAgIF9wcm90bzUxLmV2YWx1YXRlID0gZnVuY3Rpb24gZXZhbHVhdGUodm0pIHsKICAgICAgdm0udHJ5KHRoaXMuY2hpbGRyZW4sIHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG81MS5oYW5kbGVFeGNlcHRpb24gPSBmdW5jdGlvbiBoYW5kbGVFeGNlcHRpb24oKSB7CiAgICAgIHZhciBfdGhpczE3ID0gdGhpczsKCiAgICAgIHZhciBzdGF0ZSA9IHRoaXMuc3RhdGUsCiAgICAgICAgICBib3VuZHMgPSB0aGlzLmJvdW5kcywKICAgICAgICAgIGNoaWxkcmVuID0gdGhpcy5jaGlsZHJlbiwKICAgICAgICAgIHN0YXJ0ID0gdGhpcy5zdGFydCwKICAgICAgICAgIHByZXYgPSB0aGlzLnByZXYsCiAgICAgICAgICBuZXh0ID0gdGhpcy5uZXh0LAogICAgICAgICAgcnVudGltZSA9IHRoaXMucnVudGltZTsKICAgICAgY2hpbGRyZW4uY2xlYXIoKTsKICAgICAgdmFyIGVsZW1lbnRTdGFjayA9IE5ld0VsZW1lbnRCdWlsZGVyLnJlc3VtZShydW50aW1lLmVudiwgYm91bmRzLCBib3VuZHMucmVzZXQocnVudGltZS5lbnYpKTsKICAgICAgdmFyIHZtID0gVk0ucmVzdW1lKHN0YXRlLCBydW50aW1lLCBlbGVtZW50U3RhY2spOwogICAgICB2YXIgdXBkYXRpbmcgPSBuZXcgX3V0aWwuTGlua2VkTGlzdCgpOwogICAgICB2bS5leGVjdXRlKHN0YXJ0LCBmdW5jdGlvbiAodm0pIHsKICAgICAgICB2bS5zdGFjayA9IEV2YWx1YXRpb25TdGFjay5yZXN0b3JlKHN0YXRlLnN0YWNrKTsKICAgICAgICB2bS51cGRhdGluZ09wY29kZVN0YWNrLnB1c2godXBkYXRpbmcpOwogICAgICAgIHZtLnVwZGF0ZVdpdGgoX3RoaXMxNyk7CiAgICAgICAgdm0udXBkYXRpbmdPcGNvZGVTdGFjay5wdXNoKGNoaWxkcmVuKTsKICAgICAgfSk7CiAgICAgIHRoaXMucHJldiA9IHByZXY7CiAgICAgIHRoaXMubmV4dCA9IG5leHQ7CiAgICB9OwoKICAgIHJldHVybiBUcnlPcGNvZGU7CiAgfShCbG9ja09wY29kZSk7CgogIHZhciBMaXN0UmV2YWxpZGF0aW9uRGVsZWdhdGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBMaXN0UmV2YWxpZGF0aW9uRGVsZWdhdGUob3Bjb2RlLCBtYXJrZXIpIHsKICAgICAgdGhpcy5vcGNvZGUgPSBvcGNvZGU7CiAgICAgIHRoaXMubWFya2VyID0gbWFya2VyOwogICAgICB0aGlzLmRpZEluc2VydCA9IGZhbHNlOwogICAgICB0aGlzLmRpZERlbGV0ZSA9IGZhbHNlOwogICAgICB0aGlzLm1hcCA9IG9wY29kZS5tYXA7CiAgICAgIHRoaXMudXBkYXRpbmcgPSBvcGNvZGVbJ2NoaWxkcmVuJ107CiAgICB9CgogICAgdmFyIF9wcm90bzUyID0gTGlzdFJldmFsaWRhdGlvbkRlbGVnYXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG81Mi5pbnNlcnQgPSBmdW5jdGlvbiBpbnNlcnQoa2V5LCBpdGVtLCBtZW1vLCBiZWZvcmUpIHsKICAgICAgdmFyIG1hcCA9IHRoaXMubWFwLAogICAgICAgICAgb3Bjb2RlID0gdGhpcy5vcGNvZGUsCiAgICAgICAgICB1cGRhdGluZyA9IHRoaXMudXBkYXRpbmc7CiAgICAgIHZhciBuZXh0U2libGluZyA9IG51bGw7CiAgICAgIHZhciByZWZlcmVuY2UgPSBudWxsOwoKICAgICAgaWYgKHR5cGVvZiBiZWZvcmUgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgcmVmZXJlbmNlID0gbWFwW2JlZm9yZV07CiAgICAgICAgbmV4dFNpYmxpbmcgPSByZWZlcmVuY2VbJ2JvdW5kcyddLmZpcnN0Tm9kZSgpOwogICAgICB9IGVsc2UgewogICAgICAgIG5leHRTaWJsaW5nID0gdGhpcy5tYXJrZXI7CiAgICAgIH0KCiAgICAgIHZhciB2bSA9IG9wY29kZS52bUZvckluc2VydGlvbihuZXh0U2libGluZyk7CiAgICAgIHZhciB0cnlPcGNvZGUgPSBudWxsOwogICAgICB2YXIgc3RhcnQgPSBvcGNvZGUuc3RhcnQ7CiAgICAgIHZtLmV4ZWN1dGUoc3RhcnQsIGZ1bmN0aW9uICh2bSkgewogICAgICAgIG1hcFtrZXldID0gdHJ5T3Bjb2RlID0gdm0uaXRlcmF0ZShtZW1vLCBpdGVtKTsKICAgICAgICB2bS51cGRhdGluZ09wY29kZVN0YWNrLnB1c2gobmV3IF91dGlsLkxpbmtlZExpc3QoKSk7CiAgICAgICAgdm0udXBkYXRlV2l0aCh0cnlPcGNvZGUpOwogICAgICAgIHZtLnVwZGF0aW5nT3Bjb2RlU3RhY2sucHVzaCh0cnlPcGNvZGUuY2hpbGRyZW4pOwogICAgICB9KTsKICAgICAgdXBkYXRpbmcuaW5zZXJ0QmVmb3JlKHRyeU9wY29kZSwgcmVmZXJlbmNlKTsKICAgICAgdGhpcy5kaWRJbnNlcnQgPSB0cnVlOwogICAgfTsKCiAgICBfcHJvdG81Mi5yZXRhaW4gPSBmdW5jdGlvbiByZXRhaW4oX2tleSwgX2l0ZW0sIF9tZW1vKSB7fTsKCiAgICBfcHJvdG81Mi5tb3ZlID0gZnVuY3Rpb24gbW92ZShrZXksIF9pdGVtLCBfbWVtbywgYmVmb3JlKSB7CiAgICAgIHZhciBtYXAgPSB0aGlzLm1hcCwKICAgICAgICAgIHVwZGF0aW5nID0gdGhpcy51cGRhdGluZzsKICAgICAgdmFyIGVudHJ5ID0gbWFwW2tleV07CiAgICAgIHZhciByZWZlcmVuY2UgPSBtYXBbYmVmb3JlXSB8fCBudWxsOwoKICAgICAgaWYgKHR5cGVvZiBiZWZvcmUgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgX21vdmUoZW50cnksIHJlZmVyZW5jZS5maXJzdE5vZGUoKSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgX21vdmUoZW50cnksIHRoaXMubWFya2VyKTsKICAgICAgfQoKICAgICAgdXBkYXRpbmcucmVtb3ZlKGVudHJ5KTsKICAgICAgdXBkYXRpbmcuaW5zZXJ0QmVmb3JlKGVudHJ5LCByZWZlcmVuY2UpOwogICAgfTsKCiAgICBfcHJvdG81Mi5kZWxldGUgPSBmdW5jdGlvbiBfZGVsZXRlKGtleSkgewogICAgICB2YXIgbWFwID0gdGhpcy5tYXA7CiAgICAgIHZhciBvcGNvZGUgPSBtYXBba2V5XTsKICAgICAgb3Bjb2RlLmRpZERlc3Ryb3koKTsKICAgICAgY2xlYXIob3Bjb2RlKTsKICAgICAgdGhpcy51cGRhdGluZy5yZW1vdmUob3Bjb2RlKTsKICAgICAgZGVsZXRlIG1hcFtrZXldOwogICAgICB0aGlzLmRpZERlbGV0ZSA9IHRydWU7CiAgICB9OwoKICAgIF9wcm90bzUyLmRvbmUgPSBmdW5jdGlvbiBkb25lKCkgewogICAgICB0aGlzLm9wY29kZS5kaWRJbml0aWFsaXplQ2hpbGRyZW4odGhpcy5kaWRJbnNlcnQgfHwgdGhpcy5kaWREZWxldGUpOwogICAgfTsKCiAgICByZXR1cm4gTGlzdFJldmFsaWRhdGlvbkRlbGVnYXRlOwogIH0oKTsKCiAgdmFyIExpc3RCbG9ja09wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQmxvY2tPcGNvZGUyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTGlzdEJsb2NrT3Bjb2RlLCBfQmxvY2tPcGNvZGUyKTsKCiAgICBmdW5jdGlvbiBMaXN0QmxvY2tPcGNvZGUoc3RhcnQsIHN0YXRlLCBydW50aW1lLCBib3VuZHMsIGNoaWxkcmVuLCBhcnRpZmFjdHMpIHsKICAgICAgdmFyIF90aGlzMTg7CgogICAgICBfdGhpczE4ID0gX0Jsb2NrT3Bjb2RlMi5jYWxsKHRoaXMsIHN0YXJ0LCBzdGF0ZSwgcnVudGltZSwgYm91bmRzLCBjaGlsZHJlbikgfHwgdGhpczsKICAgICAgX3RoaXMxOC50eXBlID0gJ2xpc3QtYmxvY2snOwogICAgICBfdGhpczE4Lm1hcCA9ICgwLCBfdXRpbC5kaWN0KSgpOwogICAgICBfdGhpczE4Lmxhc3RJdGVyYXRlZCA9IF9yZWZlcmVuY2UyLklOSVRJQUw7CiAgICAgIF90aGlzMTguYXJ0aWZhY3RzID0gYXJ0aWZhY3RzOwoKICAgICAgdmFyIF90YWcgPSBfdGhpczE4Ll90YWcgPSAoMCwgX3JlZmVyZW5jZTIuY3JlYXRlVXBkYXRhYmxlVGFnKSgpOwoKICAgICAgX3RoaXMxOC50YWcgPSAoMCwgX3JlZmVyZW5jZTIuY29tYmluZSkoW2FydGlmYWN0cy50YWcsIF90YWddKTsKICAgICAgcmV0dXJuIF90aGlzMTg7CiAgICB9CgogICAgdmFyIF9wcm90bzUzID0gTGlzdEJsb2NrT3Bjb2RlLnByb3RvdHlwZTsKCiAgICBfcHJvdG81My5kaWRJbml0aWFsaXplQ2hpbGRyZW4gPSBmdW5jdGlvbiBkaWRJbml0aWFsaXplQ2hpbGRyZW4obGlzdERpZENoYW5nZSkgewogICAgICBpZiAobGlzdERpZENoYW5nZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgbGlzdERpZENoYW5nZSA9IHRydWU7CiAgICAgIH0KCiAgICAgIHRoaXMubGFzdEl0ZXJhdGVkID0gKDAsIF9yZWZlcmVuY2UyLnZhbHVlKSh0aGlzLmFydGlmYWN0cy50YWcpOwoKICAgICAgaWYgKGxpc3REaWRDaGFuZ2UpIHsKICAgICAgICAoMCwgX3JlZmVyZW5jZTIudXBkYXRlKSh0aGlzLl90YWcsICgwLCBfcmVmZXJlbmNlMi5jb21iaW5lU2xpY2UpKHRoaXMuY2hpbGRyZW4pKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG81My5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKHZtKSB7CiAgICAgIHZhciBhcnRpZmFjdHMgPSB0aGlzLmFydGlmYWN0cywKICAgICAgICAgIGxhc3RJdGVyYXRlZCA9IHRoaXMubGFzdEl0ZXJhdGVkOwoKICAgICAgaWYgKCEoMCwgX3JlZmVyZW5jZTIudmFsaWRhdGUpKGFydGlmYWN0cy50YWcsIGxhc3RJdGVyYXRlZCkpIHsKICAgICAgICB2YXIgYm91bmRzID0gdGhpcy5ib3VuZHM7CiAgICAgICAgdmFyIGRvbSA9IHZtLmRvbTsKICAgICAgICB2YXIgbWFya2VyID0gZG9tLmNyZWF0ZUNvbW1lbnQoJycpOwogICAgICAgIGRvbS5pbnNlcnRBZnRlcihib3VuZHMucGFyZW50RWxlbWVudCgpLCBtYXJrZXIsIGJvdW5kcy5sYXN0Tm9kZSgpKTsKICAgICAgICB2YXIgdGFyZ2V0ID0gbmV3IExpc3RSZXZhbGlkYXRpb25EZWxlZ2F0ZSh0aGlzLCBtYXJrZXIpOwogICAgICAgIHZhciBzeW5jaHJvbml6ZXIgPSBuZXcgX3JlZmVyZW5jZTIuSXRlcmF0b3JTeW5jaHJvbml6ZXIoewogICAgICAgICAgdGFyZ2V0OiB0YXJnZXQsCiAgICAgICAgICBhcnRpZmFjdHM6IGFydGlmYWN0cwogICAgICAgIH0pOwogICAgICAgIHN5bmNocm9uaXplci5zeW5jKCk7CiAgICAgICAgdGhpcy5wYXJlbnRFbGVtZW50KCkucmVtb3ZlQ2hpbGQobWFya2VyKTsKICAgICAgfSAvLyBSdW4gbm93LXVwZGF0ZWQgdXBkYXRpbmcgb3Bjb2RlcwoKCiAgICAgIF9CbG9ja09wY29kZTIucHJvdG90eXBlLmV2YWx1YXRlLmNhbGwodGhpcywgdm0pOwogICAgfTsKCiAgICBfcHJvdG81My52bUZvckluc2VydGlvbiA9IGZ1bmN0aW9uIHZtRm9ySW5zZXJ0aW9uKG5leHRTaWJsaW5nKSB7CiAgICAgIHZhciBib3VuZHMgPSB0aGlzLmJvdW5kcywKICAgICAgICAgIHN0YXRlID0gdGhpcy5zdGF0ZSwKICAgICAgICAgIHJ1bnRpbWUgPSB0aGlzLnJ1bnRpbWU7CiAgICAgIHZhciBlbGVtZW50U3RhY2sgPSBOZXdFbGVtZW50QnVpbGRlci5mb3JJbml0aWFsUmVuZGVyKHJ1bnRpbWUuZW52LCB7CiAgICAgICAgZWxlbWVudDogYm91bmRzLnBhcmVudEVsZW1lbnQoKSwKICAgICAgICBuZXh0U2libGluZzogbmV4dFNpYmxpbmcKICAgICAgfSk7CiAgICAgIHJldHVybiBWTS5yZXN1bWUoc3RhdGUsIHJ1bnRpbWUsIGVsZW1lbnRTdGFjayk7CiAgICB9OwoKICAgIHJldHVybiBMaXN0QmxvY2tPcGNvZGU7CiAgfShCbG9ja09wY29kZSk7CgogIHZhciBVcGRhdGluZ1ZNRnJhbWUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBVcGRhdGluZ1ZNRnJhbWUob3BzLCBleGNlcHRpb25IYW5kbGVyKSB7CiAgICAgIHRoaXMub3BzID0gb3BzOwogICAgICB0aGlzLmV4Y2VwdGlvbkhhbmRsZXIgPSBleGNlcHRpb25IYW5kbGVyOwogICAgICB0aGlzLmN1cnJlbnQgPSBvcHMuaGVhZCgpOwogICAgfQoKICAgIHZhciBfcHJvdG81NCA9IFVwZGF0aW5nVk1GcmFtZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNTQuZ290byA9IGZ1bmN0aW9uIGdvdG8ob3ApIHsKICAgICAgdGhpcy5jdXJyZW50ID0gb3A7CiAgICB9OwoKICAgIF9wcm90bzU0Lm5leHRTdGF0ZW1lbnQgPSBmdW5jdGlvbiBuZXh0U3RhdGVtZW50KCkgewogICAgICB2YXIgY3VycmVudCA9IHRoaXMuY3VycmVudCwKICAgICAgICAgIG9wcyA9IHRoaXMub3BzOwogICAgICBpZiAoY3VycmVudCkgdGhpcy5jdXJyZW50ID0gb3BzLm5leHROb2RlKGN1cnJlbnQpOwogICAgICByZXR1cm4gY3VycmVudDsKICAgIH07CgogICAgX3Byb3RvNTQuaGFuZGxlRXhjZXB0aW9uID0gZnVuY3Rpb24gaGFuZGxlRXhjZXB0aW9uKCkgewogICAgICBpZiAodGhpcy5leGNlcHRpb25IYW5kbGVyKSB7CiAgICAgICAgdGhpcy5leGNlcHRpb25IYW5kbGVyLmhhbmRsZUV4Y2VwdGlvbigpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBVcGRhdGluZ1ZNRnJhbWU7CiAgfSgpOwoKICB2YXIgUmVuZGVyUmVzdWx0ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUmVuZGVyUmVzdWx0KGVudiwgcHJvZ3JhbSwgdXBkYXRpbmcsIGJvdW5kcykgewogICAgICB0aGlzLmVudiA9IGVudjsKICAgICAgdGhpcy5wcm9ncmFtID0gcHJvZ3JhbTsKICAgICAgdGhpcy51cGRhdGluZyA9IHVwZGF0aW5nOwogICAgICB0aGlzLmJvdW5kcyA9IGJvdW5kczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTUgPSBSZW5kZXJSZXN1bHQucHJvdG90eXBlOwoKICAgIF9wcm90bzU1LnJlcmVuZGVyID0gZnVuY3Rpb24gcmVyZW5kZXIoX3RlbXApIHsKICAgICAgdmFyIF9yZWY1OCA9IF90ZW1wID09PSB2b2lkIDAgPyB7CiAgICAgICAgYWx3YXlzUmV2YWxpZGF0ZTogZmFsc2UKICAgICAgfSA6IF90ZW1wLAogICAgICAgICAgX3JlZjU4JGFsd2F5c1JldmFsaWRhID0gX3JlZjU4LmFsd2F5c1JldmFsaWRhdGUsCiAgICAgICAgICBhbHdheXNSZXZhbGlkYXRlID0gX3JlZjU4JGFsd2F5c1JldmFsaWRhID09PSB2b2lkIDAgPyBmYWxzZSA6IF9yZWY1OCRhbHdheXNSZXZhbGlkYTsKCiAgICAgIHZhciBlbnYgPSB0aGlzLmVudiwKICAgICAgICAgIHByb2dyYW0gPSB0aGlzLnByb2dyYW0sCiAgICAgICAgICB1cGRhdGluZyA9IHRoaXMudXBkYXRpbmc7CiAgICAgIHZhciB2bSA9IG5ldyBVcGRhdGluZ1ZNKGVudiwgcHJvZ3JhbSwgewogICAgICAgIGFsd2F5c1JldmFsaWRhdGU6IGFsd2F5c1JldmFsaWRhdGUKICAgICAgfSk7CiAgICAgIHZtLmV4ZWN1dGUodXBkYXRpbmcsIHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG81NS5wYXJlbnRFbGVtZW50ID0gZnVuY3Rpb24gcGFyZW50RWxlbWVudCgpIHsKICAgICAgcmV0dXJuIHRoaXMuYm91bmRzLnBhcmVudEVsZW1lbnQoKTsKICAgIH07CgogICAgX3Byb3RvNTUuZmlyc3ROb2RlID0gZnVuY3Rpb24gZmlyc3ROb2RlKCkgewogICAgICByZXR1cm4gdGhpcy5ib3VuZHMuZmlyc3ROb2RlKCk7CiAgICB9OwoKICAgIF9wcm90bzU1Lmxhc3ROb2RlID0gZnVuY3Rpb24gbGFzdE5vZGUoKSB7CiAgICAgIHJldHVybiB0aGlzLmJvdW5kcy5sYXN0Tm9kZSgpOwogICAgfTsKCiAgICBfcHJvdG81NS5oYW5kbGVFeGNlcHRpb24gPSBmdW5jdGlvbiBoYW5kbGVFeGNlcHRpb24oKSB7CiAgICAgIHRocm93ICd0aGlzIHNob3VsZCBuZXZlciBoYXBwZW4nOwogICAgfTsKCiAgICBfcHJvdG81NS5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdGhpcy5ib3VuZHMuZGVzdHJveSgpOwogICAgICBjbGVhcih0aGlzLmJvdW5kcyk7CiAgICB9OwoKICAgIHJldHVybiBSZW5kZXJSZXN1bHQ7CiAgfSgpOwoKICBfZXhwb3J0cy5SZW5kZXJSZXN1bHQgPSBSZW5kZXJSZXN1bHQ7CgogIHZhciBBcmd1bWVudHMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBBcmd1bWVudHMoKSB7CiAgICAgIHRoaXMuc3RhY2sgPSBudWxsOwogICAgICB0aGlzLnBvc2l0aW9uYWwgPSBuZXcgUG9zaXRpb25hbEFyZ3VtZW50cygpOwogICAgICB0aGlzLm5hbWVkID0gbmV3IE5hbWVkQXJndW1lbnRzKCk7CiAgICAgIHRoaXMuYmxvY2tzID0gbmV3IEJsb2NrQXJndW1lbnRzKCk7CiAgICB9CgogICAgdmFyIF9wcm90bzU2ID0gQXJndW1lbnRzLnByb3RvdHlwZTsKCiAgICBfcHJvdG81Ni5lbXB0eSA9IGZ1bmN0aW9uIGVtcHR5KHN0YWNrKSB7CiAgICAgIHZhciBiYXNlID0gc3RhY2suc3AgKyAxOwogICAgICB0aGlzLm5hbWVkLmVtcHR5KHN0YWNrLCBiYXNlKTsKICAgICAgdGhpcy5wb3NpdGlvbmFsLmVtcHR5KHN0YWNrLCBiYXNlKTsKICAgICAgdGhpcy5ibG9ja3MuZW1wdHkoc3RhY2ssIGJhc2UpOwogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgX3Byb3RvNTYuc2V0dXAgPSBmdW5jdGlvbiBzZXR1cChzdGFjaywgbmFtZXMsIGJsb2NrTmFtZXMsIHBvc2l0aW9uYWxDb3VudCwgc3ludGhldGljKSB7CiAgICAgIHRoaXMuc3RhY2sgPSBzdGFjazsKICAgICAgLyoKICAgICAgICAgICAgIHwgLi4uIHwgYmxvY2tzICAgICAgfCBwb3NpdGlvbmFsICB8IG5hbWVkIHwKICAgICAgICAgICAgIHwgLi4uIHwgYjAgICAgYjEgICAgfCBwMCBwMSBwMiBwMyB8IG4wIG4xIHwKICAgICAgIGluZGV4IHwgLi4uIHwgNC81LzYgNy84LzkgfCAxMCAxMSAxMiAxMyB8IDE0IDE1IHwKICAgICAgICAgICAgICAgICAgICAgXiAgICAgICAgICAgICBeICAgICAgICAgICAgIF4gIF4KICAgICAgICAgICAgICAgICAgIGJiYXNlICAgICAgICAgcGJhc2UgICAgICAgbmJhc2UgIHNwCiAgICAgICovCgogICAgICB2YXIgbmFtZWQgPSB0aGlzLm5hbWVkOwogICAgICB2YXIgbmFtZWRDb3VudCA9IG5hbWVzLmxlbmd0aDsKICAgICAgdmFyIG5hbWVkQmFzZSA9IHN0YWNrLnNwIC0gbmFtZWRDb3VudCArIDE7CiAgICAgIG5hbWVkLnNldHVwKHN0YWNrLCBuYW1lZEJhc2UsIG5hbWVkQ291bnQsIG5hbWVzLCBzeW50aGV0aWMpOwogICAgICB2YXIgcG9zaXRpb25hbCA9IHRoaXMucG9zaXRpb25hbDsKICAgICAgdmFyIHBvc2l0aW9uYWxCYXNlID0gbmFtZWRCYXNlIC0gcG9zaXRpb25hbENvdW50OwogICAgICBwb3NpdGlvbmFsLnNldHVwKHN0YWNrLCBwb3NpdGlvbmFsQmFzZSwgcG9zaXRpb25hbENvdW50KTsKICAgICAgdmFyIGJsb2NrcyA9IHRoaXMuYmxvY2tzOwogICAgICB2YXIgYmxvY2tzQ291bnQgPSBibG9ja05hbWVzLmxlbmd0aDsKICAgICAgdmFyIGJsb2Nrc0Jhc2UgPSBwb3NpdGlvbmFsQmFzZSAtIGJsb2Nrc0NvdW50ICogMzsKICAgICAgYmxvY2tzLnNldHVwKHN0YWNrLCBibG9ja3NCYXNlLCBibG9ja3NDb3VudCwgYmxvY2tOYW1lcyk7CiAgICB9OwoKICAgIF9wcm90bzU2LmF0ID0gZnVuY3Rpb24gYXQocG9zKSB7CiAgICAgIHJldHVybiB0aGlzLnBvc2l0aW9uYWwuYXQocG9zKTsKICAgIH07CgogICAgX3Byb3RvNTYucmVhbGxvYyA9IGZ1bmN0aW9uIHJlYWxsb2Mob2Zmc2V0KSB7CiAgICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2s7CgogICAgICBpZiAob2Zmc2V0ID4gMCAmJiBzdGFjayAhPT0gbnVsbCkgewogICAgICAgIHZhciBwb3NpdGlvbmFsID0gdGhpcy5wb3NpdGlvbmFsLAogICAgICAgICAgICBuYW1lZCA9IHRoaXMubmFtZWQ7CiAgICAgICAgdmFyIG5ld0Jhc2UgPSBwb3NpdGlvbmFsLmJhc2UgKyBvZmZzZXQ7CiAgICAgICAgdmFyIGxlbmd0aCA9IHBvc2l0aW9uYWwubGVuZ3RoICsgbmFtZWQubGVuZ3RoOwoKICAgICAgICBmb3IgKHZhciBpID0gbGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICAgIHN0YWNrLmNvcHkoaSArIHBvc2l0aW9uYWwuYmFzZSwgaSArIG5ld0Jhc2UpOwogICAgICAgIH0KCiAgICAgICAgcG9zaXRpb25hbC5iYXNlICs9IG9mZnNldDsKICAgICAgICBuYW1lZC5iYXNlICs9IG9mZnNldDsKICAgICAgICBzdGFjay5zcCArPSBvZmZzZXQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNTYuY2FwdHVyZSA9IGZ1bmN0aW9uIGNhcHR1cmUoKSB7CiAgICAgIHZhciBwb3NpdGlvbmFsID0gdGhpcy5wb3NpdGlvbmFsLmxlbmd0aCA9PT0gMCA/IEVNUFRZX1BPU0lUSU9OQUwgOiB0aGlzLnBvc2l0aW9uYWwuY2FwdHVyZSgpOwogICAgICB2YXIgbmFtZWQgPSB0aGlzLm5hbWVkLmxlbmd0aCA9PT0gMCA/IEVNUFRZX05BTUVEIDogdGhpcy5uYW1lZC5jYXB0dXJlKCk7CiAgICAgIHJldHVybiBuZXcgQ2FwdHVyZWRBcmd1bWVudHModGhpcy50YWcsIHBvc2l0aW9uYWwsIG5hbWVkLCB0aGlzLmxlbmd0aCk7CiAgICB9OwoKICAgIF9wcm90bzU2LmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7CiAgICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2ssCiAgICAgICAgICBsZW5ndGggPSB0aGlzLmxlbmd0aDsKICAgICAgaWYgKGxlbmd0aCA+IDAgJiYgc3RhY2sgIT09IG51bGwpIHN0YWNrLnBvcChsZW5ndGgpOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKEFyZ3VtZW50cywgW3sKICAgICAga2V5OiAidGFnIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuICgwLCBfcmVmZXJlbmNlMi5jb21iaW5lVGFnZ2VkKShbdGhpcy5wb3NpdGlvbmFsLCB0aGlzLm5hbWVkXSk7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiYmFzZSIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmJsb2Nrcy5iYXNlOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImxlbmd0aCIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLnBvc2l0aW9uYWwubGVuZ3RoICsgdGhpcy5uYW1lZC5sZW5ndGggKyB0aGlzLmJsb2Nrcy5sZW5ndGggKiAzOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gQXJndW1lbnRzOwogIH0oKTsKCiAgdmFyIENhcHR1cmVkQXJndW1lbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ2FwdHVyZWRBcmd1bWVudHModGFnLCBwb3NpdGlvbmFsLCBuYW1lZCwgbGVuZ3RoKSB7CiAgICAgIHRoaXMudGFnID0gdGFnOwogICAgICB0aGlzLnBvc2l0aW9uYWwgPSBwb3NpdGlvbmFsOwogICAgICB0aGlzLm5hbWVkID0gbmFtZWQ7CiAgICAgIHRoaXMubGVuZ3RoID0gbGVuZ3RoOwogICAgfQoKICAgIHZhciBfcHJvdG81NyA9IENhcHR1cmVkQXJndW1lbnRzLnByb3RvdHlwZTsKCiAgICBfcHJvdG81Ny52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICByZXR1cm4gewogICAgICAgIG5hbWVkOiB0aGlzLm5hbWVkLnZhbHVlKCksCiAgICAgICAgcG9zaXRpb25hbDogdGhpcy5wb3NpdGlvbmFsLnZhbHVlKCkKICAgICAgfTsKICAgIH07CgogICAgcmV0dXJuIENhcHR1cmVkQXJndW1lbnRzOwogIH0oKTsKCiAgdmFyIFBvc2l0aW9uYWxBcmd1bWVudHMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBQb3NpdGlvbmFsQXJndW1lbnRzKCkgewogICAgICB0aGlzLmJhc2UgPSAwOwogICAgICB0aGlzLmxlbmd0aCA9IDA7CiAgICAgIHRoaXMuc3RhY2sgPSBudWxsOwogICAgICB0aGlzLl90YWcgPSBudWxsOwogICAgICB0aGlzLl9yZWZlcmVuY2VzID0gbnVsbDsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTggPSBQb3NpdGlvbmFsQXJndW1lbnRzLnByb3RvdHlwZTsKCiAgICBfcHJvdG81OC5lbXB0eSA9IGZ1bmN0aW9uIGVtcHR5KHN0YWNrLCBiYXNlKSB7CiAgICAgIHRoaXMuc3RhY2sgPSBzdGFjazsKICAgICAgdGhpcy5iYXNlID0gYmFzZTsKICAgICAgdGhpcy5sZW5ndGggPSAwOwogICAgICB0aGlzLl90YWcgPSBfcmVmZXJlbmNlMi5DT05TVEFOVF9UQUc7CiAgICAgIHRoaXMuX3JlZmVyZW5jZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgIH07CgogICAgX3Byb3RvNTguc2V0dXAgPSBmdW5jdGlvbiBzZXR1cChzdGFjaywgYmFzZSwgbGVuZ3RoKSB7CiAgICAgIHRoaXMuc3RhY2sgPSBzdGFjazsKICAgICAgdGhpcy5iYXNlID0gYmFzZTsKICAgICAgdGhpcy5sZW5ndGggPSBsZW5ndGg7CgogICAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgICAgdGhpcy5fdGFnID0gX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHOwogICAgICAgIHRoaXMuX3JlZmVyZW5jZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLl90YWcgPSBudWxsOwogICAgICAgIHRoaXMuX3JlZmVyZW5jZXMgPSBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzU4LmF0ID0gZnVuY3Rpb24gYXQocG9zaXRpb24pIHsKICAgICAgdmFyIGJhc2UgPSB0aGlzLmJhc2UsCiAgICAgICAgICBsZW5ndGggPSB0aGlzLmxlbmd0aCwKICAgICAgICAgIHN0YWNrID0gdGhpcy5zdGFjazsKCiAgICAgIGlmIChwb3NpdGlvbiA8IDAgfHwgcG9zaXRpb24gPj0gbGVuZ3RoKSB7CiAgICAgICAgcmV0dXJuIFVOREVGSU5FRF9SRUZFUkVOQ0U7CiAgICAgIH0KCiAgICAgIHJldHVybiBzdGFjay5nZXQocG9zaXRpb24sIGJhc2UpOwogICAgfTsKCiAgICBfcHJvdG81OC5jYXB0dXJlID0gZnVuY3Rpb24gY2FwdHVyZSgpIHsKICAgICAgcmV0dXJuIG5ldyBDYXB0dXJlZFBvc2l0aW9uYWxBcmd1bWVudHModGhpcy50YWcsIHRoaXMucmVmZXJlbmNlcyk7CiAgICB9OwoKICAgIF9wcm90bzU4LnByZXBlbmQgPSBmdW5jdGlvbiBwcmVwZW5kKG90aGVyKSB7CiAgICAgIHZhciBhZGRpdGlvbnMgPSBvdGhlci5sZW5ndGg7CgogICAgICBpZiAoYWRkaXRpb25zID4gMCkgewogICAgICAgIHZhciBiYXNlID0gdGhpcy5iYXNlLAogICAgICAgICAgICBsZW5ndGggPSB0aGlzLmxlbmd0aCwKICAgICAgICAgICAgc3RhY2sgPSB0aGlzLnN0YWNrOwogICAgICAgIHRoaXMuYmFzZSA9IGJhc2UgPSBiYXNlIC0gYWRkaXRpb25zOwogICAgICAgIHRoaXMubGVuZ3RoID0gbGVuZ3RoICsgYWRkaXRpb25zOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFkZGl0aW9uczsgaSsrKSB7CiAgICAgICAgICBzdGFjay5zZXQob3RoZXIuYXQoaSksIGksIGJhc2UpOwogICAgICAgIH0KCiAgICAgICAgdGhpcy5fdGFnID0gbnVsbDsKICAgICAgICB0aGlzLl9yZWZlcmVuY2VzID0gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKFBvc2l0aW9uYWxBcmd1bWVudHMsIFt7CiAgICAgIGtleTogInRhZyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciB0YWcgPSB0aGlzLl90YWc7CgogICAgICAgIGlmICghdGFnKSB7CiAgICAgICAgICB0YWcgPSB0aGlzLl90YWcgPSAoMCwgX3JlZmVyZW5jZTIuY29tYmluZVRhZ2dlZCkodGhpcy5yZWZlcmVuY2VzKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0YWc7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAicmVmZXJlbmNlcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciByZWZlcmVuY2VzID0gdGhpcy5fcmVmZXJlbmNlczsKCiAgICAgICAgaWYgKCFyZWZlcmVuY2VzKSB7CiAgICAgICAgICB2YXIgc3RhY2sgPSB0aGlzLnN0YWNrLAogICAgICAgICAgICAgIGJhc2UgPSB0aGlzLmJhc2UsCiAgICAgICAgICAgICAgbGVuZ3RoID0gdGhpcy5sZW5ndGg7CiAgICAgICAgICByZWZlcmVuY2VzID0gdGhpcy5fcmVmZXJlbmNlcyA9IHN0YWNrLnNsaWNlQXJyYXkoYmFzZSwgYmFzZSArIGxlbmd0aCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcmVmZXJlbmNlczsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIFBvc2l0aW9uYWxBcmd1bWVudHM7CiAgfSgpOwoKICB2YXIgQ2FwdHVyZWRQb3NpdGlvbmFsQXJndW1lbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ2FwdHVyZWRQb3NpdGlvbmFsQXJndW1lbnRzKHRhZywgcmVmZXJlbmNlcywgbGVuZ3RoKSB7CiAgICAgIGlmIChsZW5ndGggPT09IHZvaWQgMCkgewogICAgICAgIGxlbmd0aCA9IHJlZmVyZW5jZXMubGVuZ3RoOwogICAgICB9CgogICAgICB0aGlzLnRhZyA9IHRhZzsKICAgICAgdGhpcy5yZWZlcmVuY2VzID0gcmVmZXJlbmNlczsKICAgICAgdGhpcy5sZW5ndGggPSBsZW5ndGg7CiAgICB9CgogICAgQ2FwdHVyZWRQb3NpdGlvbmFsQXJndW1lbnRzLmVtcHR5ID0gZnVuY3Rpb24gZW1wdHkoKSB7CiAgICAgIHJldHVybiBuZXcgQ2FwdHVyZWRQb3NpdGlvbmFsQXJndW1lbnRzKF9yZWZlcmVuY2UyLkNPTlNUQU5UX1RBRywgX3V0aWwuRU1QVFlfQVJSQVksIDApOwogICAgfTsKCiAgICB2YXIgX3Byb3RvNTkgPSBDYXB0dXJlZFBvc2l0aW9uYWxBcmd1bWVudHMucHJvdG90eXBlOwoKICAgIF9wcm90bzU5LmF0ID0gZnVuY3Rpb24gYXQocG9zaXRpb24pIHsKICAgICAgcmV0dXJuIHRoaXMucmVmZXJlbmNlc1twb3NpdGlvbl07CiAgICB9OwoKICAgIF9wcm90bzU5LnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHJldHVybiB0aGlzLnJlZmVyZW5jZXMubWFwKHRoaXMudmFsdWVPZik7CiAgICB9OwoKICAgIF9wcm90bzU5LmdldCA9IGZ1bmN0aW9uIGdldChuYW1lKSB7CiAgICAgIHZhciByZWZlcmVuY2VzID0gdGhpcy5yZWZlcmVuY2VzLAogICAgICAgICAgbGVuZ3RoID0gdGhpcy5sZW5ndGg7CgogICAgICBpZiAobmFtZSA9PT0gJ2xlbmd0aCcpIHsKICAgICAgICByZXR1cm4gUHJpbWl0aXZlUmVmZXJlbmNlLmNyZWF0ZShsZW5ndGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHZhciBpZHggPSBwYXJzZUludChuYW1lLCAxMCk7CgogICAgICAgIGlmIChpZHggPCAwIHx8IGlkeCA+PSBsZW5ndGgpIHsKICAgICAgICAgIHJldHVybiBVTkRFRklORURfUkVGRVJFTkNFOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVmZXJlbmNlc1tpZHhdOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG81OS52YWx1ZU9mID0gZnVuY3Rpb24gdmFsdWVPZihyZWZlcmVuY2UpIHsKICAgICAgcmV0dXJuIHJlZmVyZW5jZS52YWx1ZSgpOwogICAgfTsKCiAgICByZXR1cm4gQ2FwdHVyZWRQb3NpdGlvbmFsQXJndW1lbnRzOwogIH0oKTsKCiAgdmFyIE5hbWVkQXJndW1lbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gTmFtZWRBcmd1bWVudHMoKSB7CiAgICAgIHRoaXMuYmFzZSA9IDA7CiAgICAgIHRoaXMubGVuZ3RoID0gMDsKICAgICAgdGhpcy5fcmVmZXJlbmNlcyA9IG51bGw7CiAgICAgIHRoaXMuX25hbWVzID0gX3V0aWwuRU1QVFlfQVJSQVk7CiAgICAgIHRoaXMuX2F0TmFtZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjAgPSBOYW1lZEFyZ3VtZW50cy5wcm90b3R5cGU7CgogICAgX3Byb3RvNjAuZW1wdHkgPSBmdW5jdGlvbiBlbXB0eShzdGFjaywgYmFzZSkgewogICAgICB0aGlzLnN0YWNrID0gc3RhY2s7CiAgICAgIHRoaXMuYmFzZSA9IGJhc2U7CiAgICAgIHRoaXMubGVuZ3RoID0gMDsKICAgICAgdGhpcy5fcmVmZXJlbmNlcyA9IF91dGlsLkVNUFRZX0FSUkFZOwogICAgICB0aGlzLl9uYW1lcyA9IF91dGlsLkVNUFRZX0FSUkFZOwogICAgICB0aGlzLl9hdE5hbWVzID0gX3V0aWwuRU1QVFlfQVJSQVk7CiAgICB9OwoKICAgIF9wcm90bzYwLnNldHVwID0gZnVuY3Rpb24gc2V0dXAoc3RhY2ssIGJhc2UsIGxlbmd0aCwgbmFtZXMsIHN5bnRoZXRpYykgewogICAgICB0aGlzLnN0YWNrID0gc3RhY2s7CiAgICAgIHRoaXMuYmFzZSA9IGJhc2U7CiAgICAgIHRoaXMubGVuZ3RoID0gbGVuZ3RoOwoKICAgICAgaWYgKGxlbmd0aCA9PT0gMCkgewogICAgICAgIHRoaXMuX3JlZmVyZW5jZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgICAgICB0aGlzLl9uYW1lcyA9IF91dGlsLkVNUFRZX0FSUkFZOwogICAgICAgIHRoaXMuX2F0TmFtZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLl9yZWZlcmVuY2VzID0gbnVsbDsKCiAgICAgICAgaWYgKHN5bnRoZXRpYykgewogICAgICAgICAgdGhpcy5fbmFtZXMgPSBuYW1lczsKICAgICAgICAgIHRoaXMuX2F0TmFtZXMgPSBudWxsOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9uYW1lcyA9IG51bGw7CiAgICAgICAgICB0aGlzLl9hdE5hbWVzID0gbmFtZXM7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzYwLmhhcyA9IGZ1bmN0aW9uIGhhcyhuYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLm5hbWVzLmluZGV4T2YobmFtZSkgIT09IC0xOwogICAgfTsKCiAgICBfcHJvdG82MC5nZXQgPSBmdW5jdGlvbiBnZXQobmFtZSwgc3ludGhldGljKSB7CiAgICAgIGlmIChzeW50aGV0aWMgPT09IHZvaWQgMCkgewogICAgICAgIHN5bnRoZXRpYyA9IHRydWU7CiAgICAgIH0KCiAgICAgIHZhciBiYXNlID0gdGhpcy5iYXNlLAogICAgICAgICAgc3RhY2sgPSB0aGlzLnN0YWNrOwogICAgICB2YXIgbmFtZXMgPSBzeW50aGV0aWMgPyB0aGlzLm5hbWVzIDogdGhpcy5hdE5hbWVzOwogICAgICB2YXIgaWR4ID0gbmFtZXMuaW5kZXhPZihuYW1lKTsKCiAgICAgIGlmIChpZHggPT09IC0xKSB7CiAgICAgICAgcmV0dXJuIFVOREVGSU5FRF9SRUZFUkVOQ0U7CiAgICAgIH0KCiAgICAgIHJldHVybiBzdGFjay5nZXQoaWR4LCBiYXNlKTsKICAgIH07CgogICAgX3Byb3RvNjAuY2FwdHVyZSA9IGZ1bmN0aW9uIGNhcHR1cmUoKSB7CiAgICAgIHJldHVybiBuZXcgQ2FwdHVyZWROYW1lZEFyZ3VtZW50cyh0aGlzLnRhZywgdGhpcy5uYW1lcywgdGhpcy5yZWZlcmVuY2VzKTsKICAgIH07CgogICAgX3Byb3RvNjAubWVyZ2UgPSBmdW5jdGlvbiBtZXJnZShvdGhlcikgewogICAgICB2YXIgZXh0cmFzID0gb3RoZXIubGVuZ3RoOwoKICAgICAgaWYgKGV4dHJhcyA+IDApIHsKICAgICAgICB2YXIgbmFtZXMgPSB0aGlzLm5hbWVzLAogICAgICAgICAgICBsZW5ndGggPSB0aGlzLmxlbmd0aCwKICAgICAgICAgICAgc3RhY2sgPSB0aGlzLnN0YWNrOwogICAgICAgIHZhciBleHRyYU5hbWVzID0gb3RoZXIubmFtZXM7CgogICAgICAgIGlmIChPYmplY3QuaXNGcm96ZW4obmFtZXMpICYmIG5hbWVzLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgbmFtZXMgPSBbXTsKICAgICAgICB9CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXh0cmFzOyBpKyspIHsKICAgICAgICAgIHZhciBuYW1lID0gZXh0cmFOYW1lc1tpXTsKICAgICAgICAgIHZhciBpZHggPSBuYW1lcy5pbmRleE9mKG5hbWUpOwoKICAgICAgICAgIGlmIChpZHggPT09IC0xKSB7CiAgICAgICAgICAgIGxlbmd0aCA9IG5hbWVzLnB1c2gobmFtZSk7CiAgICAgICAgICAgIHN0YWNrLnB1c2gob3RoZXIucmVmZXJlbmNlc1tpXSk7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB0aGlzLmxlbmd0aCA9IGxlbmd0aDsKICAgICAgICB0aGlzLl9yZWZlcmVuY2VzID0gbnVsbDsKICAgICAgICB0aGlzLl9uYW1lcyA9IG5hbWVzOwogICAgICAgIHRoaXMuX2F0TmFtZXMgPSBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzYwLnRvU3ludGhldGljTmFtZSA9IGZ1bmN0aW9uIHRvU3ludGhldGljTmFtZShuYW1lKSB7CiAgICAgIHJldHVybiBuYW1lLnNsaWNlKDEpOwogICAgfTsKCiAgICBfcHJvdG82MC50b0F0TmFtZSA9IGZ1bmN0aW9uIHRvQXROYW1lKG5hbWUpIHsKICAgICAgcmV0dXJuICJAIiArIG5hbWU7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoTmFtZWRBcmd1bWVudHMsIFt7CiAgICAgIGtleTogInRhZyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiAoMCwgX3JlZmVyZW5jZTIuY29tYmluZVRhZ2dlZCkodGhpcy5yZWZlcmVuY2VzKTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJuYW1lcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBuYW1lcyA9IHRoaXMuX25hbWVzOwoKICAgICAgICBpZiAoIW5hbWVzKSB7CiAgICAgICAgICBuYW1lcyA9IHRoaXMuX25hbWVzID0gdGhpcy5fYXROYW1lcy5tYXAodGhpcy50b1N5bnRoZXRpY05hbWUpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIG5hbWVzOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImF0TmFtZXMiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICB2YXIgYXROYW1lcyA9IHRoaXMuX2F0TmFtZXM7CgogICAgICAgIGlmICghYXROYW1lcykgewogICAgICAgICAgYXROYW1lcyA9IHRoaXMuX2F0TmFtZXMgPSB0aGlzLl9uYW1lcy5tYXAodGhpcy50b0F0TmFtZSk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gYXROYW1lczsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJyZWZlcmVuY2VzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIHJlZmVyZW5jZXMgPSB0aGlzLl9yZWZlcmVuY2VzOwoKICAgICAgICBpZiAoIXJlZmVyZW5jZXMpIHsKICAgICAgICAgIHZhciBiYXNlID0gdGhpcy5iYXNlLAogICAgICAgICAgICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoLAogICAgICAgICAgICAgIHN0YWNrID0gdGhpcy5zdGFjazsKICAgICAgICAgIHJlZmVyZW5jZXMgPSB0aGlzLl9yZWZlcmVuY2VzID0gc3RhY2suc2xpY2VBcnJheShiYXNlLCBiYXNlICsgbGVuZ3RoKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiByZWZlcmVuY2VzOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gTmFtZWRBcmd1bWVudHM7CiAgfSgpOwoKICB2YXIgQ2FwdHVyZWROYW1lZEFyZ3VtZW50cyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENhcHR1cmVkTmFtZWRBcmd1bWVudHModGFnLCBuYW1lcywgcmVmZXJlbmNlcykgewogICAgICB0aGlzLnRhZyA9IHRhZzsKICAgICAgdGhpcy5uYW1lcyA9IG5hbWVzOwogICAgICB0aGlzLnJlZmVyZW5jZXMgPSByZWZlcmVuY2VzOwogICAgICB0aGlzLmxlbmd0aCA9IG5hbWVzLmxlbmd0aDsKICAgICAgdGhpcy5fbWFwID0gbnVsbDsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjEgPSBDYXB0dXJlZE5hbWVkQXJndW1lbnRzLnByb3RvdHlwZTsKCiAgICBfcHJvdG82MS5oYXMgPSBmdW5jdGlvbiBoYXMobmFtZSkgewogICAgICByZXR1cm4gdGhpcy5uYW1lcy5pbmRleE9mKG5hbWUpICE9PSAtMTsKICAgIH07CgogICAgX3Byb3RvNjEuZ2V0ID0gZnVuY3Rpb24gZ2V0KG5hbWUpIHsKICAgICAgdmFyIG5hbWVzID0gdGhpcy5uYW1lcywKICAgICAgICAgIHJlZmVyZW5jZXMgPSB0aGlzLnJlZmVyZW5jZXM7CiAgICAgIHZhciBpZHggPSBuYW1lcy5pbmRleE9mKG5hbWUpOwoKICAgICAgaWYgKGlkeCA9PT0gLTEpIHsKICAgICAgICByZXR1cm4gVU5ERUZJTkVEX1JFRkVSRU5DRTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gcmVmZXJlbmNlc1tpZHhdOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzYxLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHZhciBuYW1lcyA9IHRoaXMubmFtZXMsCiAgICAgICAgICByZWZlcmVuY2VzID0gdGhpcy5yZWZlcmVuY2VzOwogICAgICB2YXIgb3V0ID0gKDAsIF91dGlsLmRpY3QpKCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIG5hbWUgPSBuYW1lc1tpXTsKICAgICAgICBvdXRbbmFtZV0gPSByZWZlcmVuY2VzW2ldLnZhbHVlKCk7CiAgICAgIH0KCiAgICAgIHJldHVybiBvdXQ7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoQ2FwdHVyZWROYW1lZEFyZ3VtZW50cywgW3sKICAgICAga2V5OiAibWFwIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIG1hcCA9IHRoaXMuX21hcDsKCiAgICAgICAgaWYgKCFtYXApIHsKICAgICAgICAgIHZhciBuYW1lcyA9IHRoaXMubmFtZXMsCiAgICAgICAgICAgICAgcmVmZXJlbmNlcyA9IHRoaXMucmVmZXJlbmNlczsKICAgICAgICAgIG1hcCA9IHRoaXMuX21hcCA9ICgwLCBfdXRpbC5kaWN0KSgpOwoKICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFtZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgdmFyIG5hbWUgPSBuYW1lc1tpXTsKICAgICAgICAgICAgbWFwW25hbWVdID0gcmVmZXJlbmNlc1tpXTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiBtYXA7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBDYXB0dXJlZE5hbWVkQXJndW1lbnRzOwogIH0oKTsKCiAgdmFyIEJsb2NrQXJndW1lbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQmxvY2tBcmd1bWVudHMoKSB7CiAgICAgIHRoaXMuaW50ZXJuYWxWYWx1ZXMgPSBudWxsOwogICAgICB0aGlzLmludGVybmFsVGFnID0gbnVsbDsKICAgICAgdGhpcy5uYW1lcyA9IF91dGlsLkVNUFRZX0FSUkFZOwogICAgICB0aGlzLmxlbmd0aCA9IDA7CiAgICAgIHRoaXMuYmFzZSA9IDA7CiAgICB9CgogICAgdmFyIF9wcm90bzYyID0gQmxvY2tBcmd1bWVudHMucHJvdG90eXBlOwoKICAgIF9wcm90bzYyLmVtcHR5ID0gZnVuY3Rpb24gZW1wdHkoc3RhY2ssIGJhc2UpIHsKICAgICAgdGhpcy5zdGFjayA9IHN0YWNrOwogICAgICB0aGlzLm5hbWVzID0gX3V0aWwuRU1QVFlfQVJSQVk7CiAgICAgIHRoaXMuYmFzZSA9IGJhc2U7CiAgICAgIHRoaXMubGVuZ3RoID0gMDsKICAgICAgdGhpcy5pbnRlcm5hbFRhZyA9IF9yZWZlcmVuY2UyLkNPTlNUQU5UX1RBRzsKICAgICAgdGhpcy5pbnRlcm5hbFZhbHVlcyA9IF91dGlsLkVNUFRZX0FSUkFZOwogICAgfTsKCiAgICBfcHJvdG82Mi5zZXR1cCA9IGZ1bmN0aW9uIHNldHVwKHN0YWNrLCBiYXNlLCBsZW5ndGgsIG5hbWVzKSB7CiAgICAgIHRoaXMuc3RhY2sgPSBzdGFjazsKICAgICAgdGhpcy5uYW1lcyA9IG5hbWVzOwogICAgICB0aGlzLmJhc2UgPSBiYXNlOwogICAgICB0aGlzLmxlbmd0aCA9IGxlbmd0aDsKCiAgICAgIGlmIChsZW5ndGggPT09IDApIHsKICAgICAgICB0aGlzLmludGVybmFsVGFnID0gX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHOwogICAgICAgIHRoaXMuaW50ZXJuYWxWYWx1ZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLmludGVybmFsVGFnID0gbnVsbDsKICAgICAgICB0aGlzLmludGVybmFsVmFsdWVzID0gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG82Mi5oYXMgPSBmdW5jdGlvbiBoYXMobmFtZSkgewogICAgICByZXR1cm4gdGhpcy5uYW1lcy5pbmRleE9mKG5hbWUpICE9PSAtMTsKICAgIH07CgogICAgX3Byb3RvNjIuZ2V0ID0gZnVuY3Rpb24gZ2V0KG5hbWUpIHsKICAgICAgdmFyIGJhc2UgPSB0aGlzLmJhc2UsCiAgICAgICAgICBzdGFjayA9IHRoaXMuc3RhY2ssCiAgICAgICAgICBuYW1lcyA9IHRoaXMubmFtZXM7CiAgICAgIHZhciBpZHggPSBuYW1lcy5pbmRleE9mKG5hbWUpOwoKICAgICAgaWYgKG5hbWVzLmluZGV4T2YobmFtZSkgPT09IC0xKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KCiAgICAgIHZhciB0YWJsZSA9IHN0YWNrLmdldChpZHggKiAzLCBiYXNlKTsKICAgICAgdmFyIHNjb3BlID0gc3RhY2suZ2V0KGlkeCAqIDMgKyAxLCBiYXNlKTsgLy8gRklYTUUobW11bik6IHNob3VsZG4ndCBuZWVkIHRvIGNhc3QgdGhpcwoKICAgICAgdmFyIGhhbmRsZSA9IHN0YWNrLmdldChpZHggKiAzICsgMiwgYmFzZSk7CiAgICAgIHJldHVybiBoYW5kbGUgPT09IG51bGwgPyBudWxsIDogW2hhbmRsZSwgc2NvcGUsIHRhYmxlXTsKICAgIH07CgogICAgX3Byb3RvNjIuY2FwdHVyZSA9IGZ1bmN0aW9uIGNhcHR1cmUoKSB7CiAgICAgIHJldHVybiBuZXcgQ2FwdHVyZWRCbG9ja0FyZ3VtZW50cyh0aGlzLm5hbWVzLCB0aGlzLnZhbHVlcyk7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoQmxvY2tBcmd1bWVudHMsIFt7CiAgICAgIGtleTogInZhbHVlcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciB2YWx1ZXMgPSB0aGlzLmludGVybmFsVmFsdWVzOwoKICAgICAgICBpZiAoIXZhbHVlcykgewogICAgICAgICAgdmFyIGJhc2UgPSB0aGlzLmJhc2UsCiAgICAgICAgICAgICAgbGVuZ3RoID0gdGhpcy5sZW5ndGgsCiAgICAgICAgICAgICAgc3RhY2sgPSB0aGlzLnN0YWNrOwogICAgICAgICAgdmFsdWVzID0gdGhpcy5pbnRlcm5hbFZhbHVlcyA9IHN0YWNrLnNsaWNlQXJyYXkoYmFzZSwgYmFzZSArIGxlbmd0aCAqIDMpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHZhbHVlczsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIEJsb2NrQXJndW1lbnRzOwogIH0oKTsKCiAgdmFyIENhcHR1cmVkQmxvY2tBcmd1bWVudHMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDYXB0dXJlZEJsb2NrQXJndW1lbnRzKG5hbWVzLCB2YWx1ZXMpIHsKICAgICAgdGhpcy5uYW1lcyA9IG5hbWVzOwogICAgICB0aGlzLnZhbHVlcyA9IHZhbHVlczsKICAgICAgdGhpcy5sZW5ndGggPSBuYW1lcy5sZW5ndGg7CiAgICB9CgogICAgdmFyIF9wcm90bzYzID0gQ2FwdHVyZWRCbG9ja0FyZ3VtZW50cy5wcm90b3R5cGU7CgogICAgX3Byb3RvNjMuaGFzID0gZnVuY3Rpb24gaGFzKG5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXMubmFtZXMuaW5kZXhPZihuYW1lKSAhPT0gLTE7CiAgICB9OwoKICAgIF9wcm90bzYzLmdldCA9IGZ1bmN0aW9uIGdldChuYW1lKSB7CiAgICAgIHZhciBpZHggPSB0aGlzLm5hbWVzLmluZGV4T2YobmFtZSk7CiAgICAgIGlmIChpZHggPT09IC0xKSByZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuIFt0aGlzLnZhbHVlc1tpZHggKiAzICsgMl0sIHRoaXMudmFsdWVzW2lkeCAqIDMgKyAxXSwgdGhpcy52YWx1ZXNbaWR4ICogM11dOwogICAgfTsKCiAgICByZXR1cm4gQ2FwdHVyZWRCbG9ja0FyZ3VtZW50czsKICB9KCk7CgogIHZhciBFTVBUWV9OQU1FRCA9IG5ldyBDYXB0dXJlZE5hbWVkQXJndW1lbnRzKF9yZWZlcmVuY2UyLkNPTlNUQU5UX1RBRywgX3V0aWwuRU1QVFlfQVJSQVksIF91dGlsLkVNUFRZX0FSUkFZKTsKICB2YXIgRU1QVFlfUE9TSVRJT05BTCA9IG5ldyBDYXB0dXJlZFBvc2l0aW9uYWxBcmd1bWVudHMoX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHLCBfdXRpbC5FTVBUWV9BUlJBWSk7CiAgdmFyIEVNUFRZX0FSR1MgPSBuZXcgQ2FwdHVyZWRBcmd1bWVudHMoX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHLCBFTVBUWV9QT1NJVElPTkFMLCBFTVBUWV9OQU1FRCwgMCk7CiAgX2V4cG9ydHMuRU1QVFlfQVJHUyA9IEVNUFRZX0FSR1M7CgogIHZhciBWTSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFZNKHJ1bnRpbWUsIHNjb3BlLCBkeW5hbWljU2NvcGUsIGVsZW1lbnRTdGFjaykgewogICAgICB2YXIgX3RoaXMxOSA9IHRoaXM7CgogICAgICB0aGlzLnJ1bnRpbWUgPSBydW50aW1lOwogICAgICB0aGlzLmVsZW1lbnRTdGFjayA9IGVsZW1lbnRTdGFjazsKICAgICAgdGhpcy5keW5hbWljU2NvcGVTdGFjayA9IG5ldyBfdXRpbC5TdGFjaygpOwogICAgICB0aGlzLnNjb3BlU3RhY2sgPSBuZXcgX3V0aWwuU3RhY2soKTsKICAgICAgdGhpcy51cGRhdGluZ09wY29kZVN0YWNrID0gbmV3IF91dGlsLlN0YWNrKCk7CiAgICAgIHRoaXMuY2FjaGVHcm91cHMgPSBuZXcgX3V0aWwuU3RhY2soKTsKICAgICAgdGhpcy5saXN0QmxvY2tTdGFjayA9IG5ldyBfdXRpbC5TdGFjaygpOwogICAgICB0aGlzLnMwID0gbnVsbDsKICAgICAgdGhpcy5zMSA9IG51bGw7CiAgICAgIHRoaXMudDAgPSBudWxsOwogICAgICB0aGlzLnQxID0gbnVsbDsKICAgICAgdGhpcy52MCA9IG51bGw7CiAgICAgIHRoaXMuaGVhcCA9IHRoaXMucHJvZ3JhbS5oZWFwOwogICAgICB0aGlzLmNvbnN0YW50cyA9IHRoaXMucHJvZ3JhbS5jb25zdGFudHM7CiAgICAgIHRoaXMuZWxlbWVudFN0YWNrID0gZWxlbWVudFN0YWNrOwogICAgICB0aGlzLnNjb3BlU3RhY2sucHVzaChzY29wZSk7CiAgICAgIHRoaXMuZHluYW1pY1Njb3BlU3RhY2sucHVzaChkeW5hbWljU2NvcGUpOwogICAgICB0aGlzLmFyZ3MgPSBuZXcgQXJndW1lbnRzKCk7CiAgICAgIHRoaXMuaW5uZXIgPSBuZXcgTG93TGV2ZWxWTShFdmFsdWF0aW9uU3RhY2suZW1wdHkoKSwgdGhpcy5oZWFwLCBydW50aW1lLnByb2dyYW0sIHsKICAgICAgICBkZWJ1Z0JlZm9yZTogZnVuY3Rpb24gZGVidWdCZWZvcmUob3Bjb2RlKSB7CiAgICAgICAgICByZXR1cm4gQVBQRU5EX09QQ09ERVMuZGVidWdCZWZvcmUoX3RoaXMxOSwgb3Bjb2RlLCBvcGNvZGUudHlwZSk7CiAgICAgICAgfSwKICAgICAgICBkZWJ1Z0FmdGVyOiBmdW5jdGlvbiBkZWJ1Z0FmdGVyKG9wY29kZSwgc3RhdGUpIHsKICAgICAgICAgIEFQUEVORF9PUENPREVTLmRlYnVnQWZ0ZXIoX3RoaXMxOSwgb3Bjb2RlLCBvcGNvZGUudHlwZSwgc3RhdGUpOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CgogICAgdmFyIF9wcm90bzY0ID0gVk0ucHJvdG90eXBlOwoKICAgIC8vIEZldGNoIGEgdmFsdWUgZnJvbSBhIHJlZ2lzdGVyIG9udG8gdGhlIHN0YWNrCiAgICBfcHJvdG82NC5mZXRjaCA9IGZ1bmN0aW9uIGZldGNoKHJlZ2lzdGVyKSB7CiAgICAgIHRoaXMuc3RhY2sucHVzaCh0aGlzW192bTIuUmVnaXN0ZXJbcmVnaXN0ZXJdXSk7CiAgICB9IC8vIExvYWQgYSB2YWx1ZSBmcm9tIHRoZSBzdGFjayBpbnRvIGEgcmVnaXN0ZXIKICAgIDsKCiAgICBfcHJvdG82NC5sb2FkID0gZnVuY3Rpb24gbG9hZChyZWdpc3RlcikgewogICAgICB0aGlzW192bTIuUmVnaXN0ZXJbcmVnaXN0ZXJdXSA9IHRoaXMuc3RhY2sucG9wKCk7CiAgICB9IC8vIEZldGNoIGEgdmFsdWUgZnJvbSBhIHJlZ2lzdGVyCiAgICA7CgogICAgX3Byb3RvNjQuZmV0Y2hWYWx1ZSA9IGZ1bmN0aW9uIGZldGNoVmFsdWUocmVnaXN0ZXIpIHsKICAgICAgcmV0dXJuIHRoaXNbX3ZtMi5SZWdpc3RlcltyZWdpc3Rlcl1dOwogICAgfSAvLyBMb2FkIGEgdmFsdWUgaW50byBhIHJlZ2lzdGVyCiAgICA7CgogICAgX3Byb3RvNjQubG9hZFZhbHVlID0gZnVuY3Rpb24gbG9hZFZhbHVlKHJlZ2lzdGVyLCB2YWx1ZSQkMSkgewogICAgICB0aGlzW192bTIuUmVnaXN0ZXJbcmVnaXN0ZXJdXSA9IHZhbHVlJCQxOwogICAgfQogICAgLyoqCiAgICAgKiBNaWdyYXRlZCB0byBJbm5lcgogICAgICovCiAgICAvLyBTdGFydCBhIG5ldyBmcmFtZSBhbmQgc2F2ZSAkcmEgYW5kICRmcCBvbiB0aGUgc3RhY2sKICAgIDsKCiAgICBfcHJvdG82NC5wdXNoRnJhbWUgPSBmdW5jdGlvbiBwdXNoRnJhbWUoKSB7CiAgICAgIHRoaXMuaW5uZXIucHVzaEZyYW1lKCk7CiAgICB9IC8vIFJlc3RvcmUgJHJhLCAkc3AgYW5kICRmcAogICAgOwoKICAgIF9wcm90bzY0LnBvcEZyYW1lID0gZnVuY3Rpb24gcG9wRnJhbWUoKSB7CiAgICAgIHRoaXMuaW5uZXIucG9wRnJhbWUoKTsKICAgIH0gLy8gSnVtcCB0byBhbiBhZGRyZXNzIGluIGBwcm9ncmFtYAogICAgOwoKICAgIF9wcm90bzY0LmdvdG8gPSBmdW5jdGlvbiBnb3RvKG9mZnNldCkgewogICAgICB0aGlzLmlubmVyLmdvdG8ob2Zmc2V0KTsKICAgIH0gLy8gU2F2ZSAkcGMgaW50byAkcmEsIHRoZW4ganVtcCB0byBhIG5ldyBhZGRyZXNzIGluIGBwcm9ncmFtYCAoamFsIGluIE1JUFMpCiAgICA7CgogICAgX3Byb3RvNjQuY2FsbCA9IGZ1bmN0aW9uIGNhbGwoaGFuZGxlKSB7CiAgICAgIHRoaXMuaW5uZXIuY2FsbChoYW5kbGUpOwogICAgfSAvLyBQdXQgYSBzcGVjaWZpYyBgcHJvZ3JhbWAgYWRkcmVzcyBpbiAkcmEKICAgIDsKCiAgICBfcHJvdG82NC5yZXR1cm5UbyA9IGZ1bmN0aW9uIHJldHVyblRvKG9mZnNldCkgewogICAgICB0aGlzLmlubmVyLnJldHVyblRvKG9mZnNldCk7CiAgICB9IC8vIFJldHVybiB0byB0aGUgYHByb2dyYW1gIGFkZHJlc3Mgc3RvcmVkIGluICRyYQogICAgOwoKICAgIF9wcm90bzY0LnJldHVybiA9IGZ1bmN0aW9uIF9yZXR1cm4oKSB7CiAgICAgIHRoaXMuaW5uZXIucmV0dXJuKCk7CiAgICB9CiAgICAvKioKICAgICAqIEVuZCBvZiBtaWdyYXRlZC4KICAgICAqLwogICAgOwoKICAgIFZNLmluaXRpYWwgPSBmdW5jdGlvbiBpbml0aWFsKHByb2dyYW0sIGVudiwgc2VsZiwgZHluYW1pY1Njb3BlLCBlbGVtZW50U3RhY2ssIGhhbmRsZSkgewogICAgICB2YXIgc2NvcGVTaXplID0gcHJvZ3JhbS5oZWFwLnNjb3Blc2l6ZW9mKGhhbmRsZSk7CiAgICAgIHZhciBzY29wZSA9IFNjb3BlLnJvb3Qoc2VsZiwgc2NvcGVTaXplKTsKICAgICAgdmFyIHZtID0gbmV3IFZNKHsKICAgICAgICBwcm9ncmFtOiBwcm9ncmFtLAogICAgICAgIGVudjogZW52CiAgICAgIH0sIHNjb3BlLCBkeW5hbWljU2NvcGUsIGVsZW1lbnRTdGFjayk7CiAgICAgIHZtLnBjID0gdm0uaGVhcC5nZXRhZGRyKGhhbmRsZSk7CiAgICAgIHZtLnVwZGF0aW5nT3Bjb2RlU3RhY2sucHVzaChuZXcgX3V0aWwuTGlua2VkTGlzdCgpKTsKICAgICAgcmV0dXJuIHZtOwogICAgfTsKCiAgICBWTS5lbXB0eSA9IGZ1bmN0aW9uIGVtcHR5KHByb2dyYW0sIGVudiwgZWxlbWVudFN0YWNrLCBoYW5kbGUpIHsKICAgICAgdmFyIGR5bmFtaWNTY29wZSA9IHsKICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICAgIHJldHVybiBVTkRFRklORURfUkVGRVJFTkNFOwogICAgICAgIH0sCiAgICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoKSB7CiAgICAgICAgICByZXR1cm4gVU5ERUZJTkVEX1JFRkVSRU5DRTsKICAgICAgICB9LAogICAgICAgIGNoaWxkOiBmdW5jdGlvbiBjaGlsZCgpIHsKICAgICAgICAgIHJldHVybiBkeW5hbWljU2NvcGU7CiAgICAgICAgfQogICAgICB9OwogICAgICB2YXIgdm0gPSBuZXcgVk0oewogICAgICAgIHByb2dyYW06IHByb2dyYW0sCiAgICAgICAgZW52OiBlbnYKICAgICAgfSwgU2NvcGUucm9vdChVTkRFRklORURfUkVGRVJFTkNFLCAwKSwgZHluYW1pY1Njb3BlLCBlbGVtZW50U3RhY2spOwogICAgICB2bS51cGRhdGluZ09wY29kZVN0YWNrLnB1c2gobmV3IF91dGlsLkxpbmtlZExpc3QoKSk7CiAgICAgIHZtLnBjID0gdm0uaGVhcC5nZXRhZGRyKGhhbmRsZSk7CiAgICAgIHJldHVybiB2bTsKICAgIH07CgogICAgVk0ucmVzdW1lID0gZnVuY3Rpb24gcmVzdW1lKF9yZWY1OSwgcnVudGltZSwgc3RhY2spIHsKICAgICAgdmFyIHNjb3BlID0gX3JlZjU5LnNjb3BlLAogICAgICAgICAgZHluYW1pY1Njb3BlID0gX3JlZjU5LmR5bmFtaWNTY29wZTsKICAgICAgcmV0dXJuIG5ldyBWTShydW50aW1lLCBzY29wZSwgZHluYW1pY1Njb3BlLCBzdGFjayk7CiAgICB9OwoKICAgIF9wcm90bzY0LmNhcHR1cmUgPSBmdW5jdGlvbiBjYXB0dXJlKGFyZ3MpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBkeW5hbWljU2NvcGU6IHRoaXMuZHluYW1pY1Njb3BlKCksCiAgICAgICAgc2NvcGU6IHRoaXMuc2NvcGUoKSwKICAgICAgICBzdGFjazogdGhpcy5zdGFjay5jYXB0dXJlKGFyZ3MpCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzY0LmJlZ2luQ2FjaGVHcm91cCA9IGZ1bmN0aW9uIGJlZ2luQ2FjaGVHcm91cCgpIHsKICAgICAgdGhpcy5jYWNoZUdyb3Vwcy5wdXNoKHRoaXMudXBkYXRpbmcoKS50YWlsKCkpOwogICAgfTsKCiAgICBfcHJvdG82NC5jb21taXRDYWNoZUdyb3VwID0gZnVuY3Rpb24gY29tbWl0Q2FjaGVHcm91cCgpIHsKICAgICAgLy8gICAgICAgIEp1bXBJZk5vdE1vZGlmaWVkKEVORCkKICAgICAgLy8gICAgICAgIChoZWFkKQogICAgICAvLyAgICAgICAgKC4uLi4pCiAgICAgIC8vICAgICAgICAodGFpbCkKICAgICAgLy8gICAgICAgIERpZE1vZGlmeQogICAgICAvLyBFTkQ6ICAgTm9vcAogICAgICB2YXIgRU5EID0gbmV3IExhYmVsT3Bjb2RlKCdFTkQnKTsKICAgICAgdmFyIG9wY29kZXMgPSB0aGlzLnVwZGF0aW5nKCk7CiAgICAgIHZhciBtYXJrZXIgPSB0aGlzLmNhY2hlR3JvdXBzLnBvcCgpOwogICAgICB2YXIgaGVhZCA9IG1hcmtlciA/IG9wY29kZXMubmV4dE5vZGUobWFya2VyKSA6IG9wY29kZXMuaGVhZCgpOwogICAgICB2YXIgdGFpbCA9IG9wY29kZXMudGFpbCgpOwogICAgICB2YXIgdGFnID0gKDAsIF9yZWZlcmVuY2UyLmNvbWJpbmVTbGljZSkobmV3IF91dGlsLkxpc3RTbGljZShoZWFkLCB0YWlsKSk7CiAgICAgIHZhciBndWFyZCA9IG5ldyBKdW1wSWZOb3RNb2RpZmllZE9wY29kZSh0YWcsIEVORCk7CiAgICAgIG9wY29kZXMuaW5zZXJ0QmVmb3JlKGd1YXJkLCBoZWFkKTsKICAgICAgb3Bjb2Rlcy5hcHBlbmQobmV3IERpZE1vZGlmeU9wY29kZShndWFyZCkpOwogICAgICBvcGNvZGVzLmFwcGVuZChFTkQpOwogICAgfTsKCiAgICBfcHJvdG82NC5lbnRlciA9IGZ1bmN0aW9uIGVudGVyKGFyZ3MpIHsKICAgICAgdmFyIHVwZGF0aW5nID0gbmV3IF91dGlsLkxpbmtlZExpc3QoKTsKICAgICAgdmFyIHN0YXRlID0gdGhpcy5jYXB0dXJlKGFyZ3MpOwogICAgICB2YXIgdHJhY2tlciA9IHRoaXMuZWxlbWVudHMoKS5wdXNoVXBkYXRhYmxlQmxvY2soKTsKICAgICAgdmFyIHRyeU9wY29kZSA9IG5ldyBUcnlPcGNvZGUodGhpcy5oZWFwLmdldGhhbmRsZSh0aGlzLnBjKSwgc3RhdGUsIHRoaXMucnVudGltZSwgdHJhY2tlciwgdXBkYXRpbmcpOwogICAgICB0aGlzLmRpZEVudGVyKHRyeU9wY29kZSk7CiAgICB9OwoKICAgIF9wcm90bzY0Lml0ZXJhdGUgPSBmdW5jdGlvbiBpdGVyYXRlKG1lbW8sIHZhbHVlJCQxKSB7CiAgICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2s7CiAgICAgIHN0YWNrLnB1c2godmFsdWUkJDEpOwogICAgICBzdGFjay5wdXNoKG1lbW8pOwogICAgICB2YXIgc3RhdGUgPSB0aGlzLmNhcHR1cmUoMik7CiAgICAgIHZhciB0cmFja2VyID0gdGhpcy5lbGVtZW50cygpLnB1c2hVcGRhdGFibGVCbG9jaygpOyAvLyBsZXQgaXAgPSB0aGlzLmlwOwogICAgICAvLyB0aGlzLmlwID0gZW5kICsgNDsKICAgICAgLy8gdGhpcy5mcmFtZXMucHVzaChpcCk7CgogICAgICByZXR1cm4gbmV3IFRyeU9wY29kZSh0aGlzLmhlYXAuZ2V0aGFuZGxlKHRoaXMucGMpLCBzdGF0ZSwgdGhpcy5ydW50aW1lLCB0cmFja2VyLCBuZXcgX3V0aWwuTGlua2VkTGlzdCgpKTsKICAgIH07CgogICAgX3Byb3RvNjQuZW50ZXJJdGVtID0gZnVuY3Rpb24gZW50ZXJJdGVtKGtleSwgb3Bjb2RlKSB7CiAgICAgIHRoaXMubGlzdEJsb2NrKCkubWFwW2tleV0gPSBvcGNvZGU7CiAgICAgIHRoaXMuZGlkRW50ZXIob3Bjb2RlKTsKICAgIH07CgogICAgX3Byb3RvNjQuZW50ZXJMaXN0ID0gZnVuY3Rpb24gZW50ZXJMaXN0KHJlbGF0aXZlU3RhcnQpIHsKICAgICAgdmFyIHVwZGF0aW5nID0gbmV3IF91dGlsLkxpbmtlZExpc3QoKTsKICAgICAgdmFyIHN0YXRlID0gdGhpcy5jYXB0dXJlKDApOwogICAgICB2YXIgdHJhY2tlciA9IHRoaXMuZWxlbWVudHMoKS5wdXNoQmxvY2tMaXN0KHVwZGF0aW5nKTsKICAgICAgdmFyIGFydGlmYWN0cyA9IHRoaXMuc3RhY2sucGVlaygpLmFydGlmYWN0czsKICAgICAgdmFyIGFkZHIgPSB0aGlzLnBjICsgcmVsYXRpdmVTdGFydCAtIHRoaXMuY3VycmVudE9wU2l6ZTsKICAgICAgdmFyIHN0YXJ0ID0gdGhpcy5oZWFwLmdldGhhbmRsZShhZGRyKTsKICAgICAgdmFyIG9wY29kZSA9IG5ldyBMaXN0QmxvY2tPcGNvZGUoc3RhcnQsIHN0YXRlLCB0aGlzLnJ1bnRpbWUsIHRyYWNrZXIsIHVwZGF0aW5nLCBhcnRpZmFjdHMpOwogICAgICB0aGlzLmxpc3RCbG9ja1N0YWNrLnB1c2gob3Bjb2RlKTsKICAgICAgdGhpcy5kaWRFbnRlcihvcGNvZGUpOwogICAgfTsKCiAgICBfcHJvdG82NC5kaWRFbnRlciA9IGZ1bmN0aW9uIGRpZEVudGVyKG9wY29kZSkgewogICAgICB0aGlzLnVwZGF0ZVdpdGgob3Bjb2RlKTsKICAgICAgdGhpcy51cGRhdGluZ09wY29kZVN0YWNrLnB1c2gob3Bjb2RlLmNoaWxkcmVuKTsKICAgIH07CgogICAgX3Byb3RvNjQuZXhpdCA9IGZ1bmN0aW9uIGV4aXQoKSB7CiAgICAgIHRoaXMuZWxlbWVudHMoKS5wb3BCbG9jaygpOwogICAgICB0aGlzLnVwZGF0aW5nT3Bjb2RlU3RhY2sucG9wKCk7CiAgICAgIHZhciBwYXJlbnQgPSB0aGlzLnVwZGF0aW5nKCkudGFpbCgpOwogICAgICBwYXJlbnQuZGlkSW5pdGlhbGl6ZUNoaWxkcmVuKCk7CiAgICB9OwoKICAgIF9wcm90bzY0LmV4aXRMaXN0ID0gZnVuY3Rpb24gZXhpdExpc3QoKSB7CiAgICAgIHRoaXMuZXhpdCgpOwogICAgICB0aGlzLmxpc3RCbG9ja1N0YWNrLnBvcCgpOwogICAgfTsKCiAgICBfcHJvdG82NC51cGRhdGVXaXRoID0gZnVuY3Rpb24gdXBkYXRlV2l0aChvcGNvZGUpIHsKICAgICAgdGhpcy51cGRhdGluZygpLmFwcGVuZChvcGNvZGUpOwogICAgfTsKCiAgICBfcHJvdG82NC5saXN0QmxvY2sgPSBmdW5jdGlvbiBsaXN0QmxvY2soKSB7CiAgICAgIHJldHVybiB0aGlzLmxpc3RCbG9ja1N0YWNrLmN1cnJlbnQ7CiAgICB9OwoKICAgIF9wcm90bzY0LnVwZGF0aW5nID0gZnVuY3Rpb24gdXBkYXRpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLnVwZGF0aW5nT3Bjb2RlU3RhY2suY3VycmVudDsKICAgIH07CgogICAgX3Byb3RvNjQuZWxlbWVudHMgPSBmdW5jdGlvbiBlbGVtZW50cygpIHsKICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudFN0YWNrOwogICAgfTsKCiAgICBfcHJvdG82NC5zY29wZSA9IGZ1bmN0aW9uIHNjb3BlKCkgewogICAgICByZXR1cm4gdGhpcy5zY29wZVN0YWNrLmN1cnJlbnQ7CiAgICB9OwoKICAgIF9wcm90bzY0LmR5bmFtaWNTY29wZSA9IGZ1bmN0aW9uIGR5bmFtaWNTY29wZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZHluYW1pY1Njb3BlU3RhY2suY3VycmVudDsKICAgIH07CgogICAgX3Byb3RvNjQucHVzaENoaWxkU2NvcGUgPSBmdW5jdGlvbiBwdXNoQ2hpbGRTY29wZSgpIHsKICAgICAgdGhpcy5zY29wZVN0YWNrLnB1c2godGhpcy5zY29wZSgpLmNoaWxkKCkpOwogICAgfTsKCiAgICBfcHJvdG82NC5wdXNoRHluYW1pY1Njb3BlID0gZnVuY3Rpb24gcHVzaER5bmFtaWNTY29wZSgpIHsKICAgICAgdmFyIGNoaWxkID0gdGhpcy5keW5hbWljU2NvcGUoKS5jaGlsZCgpOwogICAgICB0aGlzLmR5bmFtaWNTY29wZVN0YWNrLnB1c2goY2hpbGQpOwogICAgICByZXR1cm4gY2hpbGQ7CiAgICB9OwoKICAgIF9wcm90bzY0LnB1c2hSb290U2NvcGUgPSBmdW5jdGlvbiBwdXNoUm9vdFNjb3BlKHNpemUsIGJpbmRDYWxsZXIpIHsKICAgICAgdmFyIHNjb3BlID0gU2NvcGUuc2l6ZWQoc2l6ZSk7CiAgICAgIGlmIChiaW5kQ2FsbGVyKSBzY29wZS5iaW5kQ2FsbGVyU2NvcGUodGhpcy5zY29wZSgpKTsKICAgICAgdGhpcy5zY29wZVN0YWNrLnB1c2goc2NvcGUpOwogICAgICByZXR1cm4gc2NvcGU7CiAgICB9OwoKICAgIF9wcm90bzY0LnB1c2hTY29wZSA9IGZ1bmN0aW9uIHB1c2hTY29wZShzY29wZSkgewogICAgICB0aGlzLnNjb3BlU3RhY2sucHVzaChzY29wZSk7CiAgICB9OwoKICAgIF9wcm90bzY0LnBvcFNjb3BlID0gZnVuY3Rpb24gcG9wU2NvcGUoKSB7CiAgICAgIHRoaXMuc2NvcGVTdGFjay5wb3AoKTsKICAgIH07CgogICAgX3Byb3RvNjQucG9wRHluYW1pY1Njb3BlID0gZnVuY3Rpb24gcG9wRHluYW1pY1Njb3BlKCkgewogICAgICB0aGlzLmR5bmFtaWNTY29wZVN0YWNrLnBvcCgpOwogICAgfTsKCiAgICBfcHJvdG82NC5uZXdEZXN0cm95YWJsZSA9IGZ1bmN0aW9uIG5ld0Rlc3Ryb3lhYmxlKGQpIHsKICAgICAgdGhpcy5lbGVtZW50cygpLmRpZEFkZERlc3Ryb3lhYmxlKGQpOwogICAgfSAvLy8gU0NPUEUgSEVMUEVSUwogICAgOwoKICAgIF9wcm90bzY0LmdldFNlbGYgPSBmdW5jdGlvbiBnZXRTZWxmKCkgewogICAgICByZXR1cm4gdGhpcy5zY29wZSgpLmdldFNlbGYoKTsKICAgIH07CgogICAgX3Byb3RvNjQucmVmZXJlbmNlRm9yU3ltYm9sID0gZnVuY3Rpb24gcmVmZXJlbmNlRm9yU3ltYm9sKHN5bWJvbCkgewogICAgICByZXR1cm4gdGhpcy5zY29wZSgpLmdldFN5bWJvbChzeW1ib2wpOwogICAgfSAvLy8gRVhFQ1VUSU9OCiAgICA7CgogICAgX3Byb3RvNjQuZXhlY3V0ZSA9IGZ1bmN0aW9uIGV4ZWN1dGUoc3RhcnQsIGluaXRpYWxpemUpIHsKICAgICAgdGhpcy5wYyA9IHRoaXMuaGVhcC5nZXRhZGRyKHN0YXJ0KTsKICAgICAgaWYgKGluaXRpYWxpemUpIGluaXRpYWxpemUodGhpcyk7CiAgICAgIHZhciByZXN1bHQ7CgogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgIHJlc3VsdCA9IHRoaXMubmV4dCgpOwogICAgICAgIGlmIChyZXN1bHQuZG9uZSkgYnJlYWs7CiAgICAgIH0KCiAgICAgIHJldHVybiByZXN1bHQudmFsdWU7CiAgICB9OwoKICAgIF9wcm90bzY0Lm5leHQgPSBmdW5jdGlvbiBuZXh0KCkgewogICAgICB2YXIgZW52ID0gdGhpcy5lbnYsCiAgICAgICAgICBwcm9ncmFtID0gdGhpcy5wcm9ncmFtLAogICAgICAgICAgdXBkYXRpbmdPcGNvZGVTdGFjayA9IHRoaXMudXBkYXRpbmdPcGNvZGVTdGFjaywKICAgICAgICAgIGVsZW1lbnRTdGFjayA9IHRoaXMuZWxlbWVudFN0YWNrOwogICAgICB2YXIgb3Bjb2RlID0gdGhpcy5pbm5lci5uZXh0U3RhdGVtZW50KCk7CiAgICAgIHZhciByZXN1bHQ7CgogICAgICBpZiAob3Bjb2RlICE9PSBudWxsKSB7CiAgICAgICAgdGhpcy5pbm5lci5ldmFsdWF0ZU91dGVyKG9wY29kZSwgdGhpcyk7CiAgICAgICAgcmVzdWx0ID0gewogICAgICAgICAgZG9uZTogZmFsc2UsCiAgICAgICAgICB2YWx1ZTogbnVsbAogICAgICAgIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gVW5sb2FkIHRoZSBzdGFjawogICAgICAgIHRoaXMuc3RhY2sucmVzZXQoKTsKICAgICAgICByZXN1bHQgPSB7CiAgICAgICAgICBkb25lOiB0cnVlLAogICAgICAgICAgdmFsdWU6IG5ldyBSZW5kZXJSZXN1bHQoZW52LCBwcm9ncmFtLCB1cGRhdGluZ09wY29kZVN0YWNrLnBvcCgpLCBlbGVtZW50U3RhY2sucG9wQmxvY2soKSkKICAgICAgICB9OwogICAgICB9CgogICAgICByZXR1cm4gcmVzdWx0OwogICAgfTsKCiAgICBfcHJvdG82NC5iaW5kRHluYW1pY1Njb3BlID0gZnVuY3Rpb24gYmluZER5bmFtaWNTY29wZShuYW1lcykgewogICAgICB2YXIgc2NvcGUgPSB0aGlzLmR5bmFtaWNTY29wZSgpOwoKICAgICAgZm9yICh2YXIgaSA9IG5hbWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgdmFyIG5hbWUgPSB0aGlzLmNvbnN0YW50cy5nZXRTdHJpbmcobmFtZXNbaV0pOwogICAgICAgIHNjb3BlLnNldChuYW1lLCB0aGlzLnN0YWNrLnBvcCgpKTsKICAgICAgfQogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKFZNLCBbewogICAgICBrZXk6ICJzdGFjayIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmlubmVyLnN0YWNrOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSQkMSkgewogICAgICAgIHRoaXMuaW5uZXIuc3RhY2sgPSB2YWx1ZSQkMTsKICAgICAgfQogICAgICAvKiBSZWdpc3RlcnMgKi8KCiAgICB9LCB7CiAgICAgIGtleTogImN1cnJlbnRPcFNpemUiLAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSQkMSkgewogICAgICAgIHRoaXMuaW5uZXIuY3VycmVudE9wU2l6ZSA9IHZhbHVlJCQxOwogICAgICB9LAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5pbm5lci5jdXJyZW50T3BTaXplOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInBjIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW5uZXIucGM7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHZhbHVlJCQxKSB7CiAgICAgICAgdGhpcy5pbm5lci5wYyA9IHZhbHVlJCQxOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInJhIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW5uZXIucmE7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHZhbHVlJCQxKSB7CiAgICAgICAgdGhpcy5pbm5lci5yYSA9IHZhbHVlJCQxOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImZwIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuc3RhY2suZnA7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KGZwKSB7CiAgICAgICAgdGhpcy5zdGFjay5mcCA9IGZwOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInNwIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuc3RhY2suc3A7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHNwKSB7CiAgICAgICAgdGhpcy5zdGFjay5zcCA9IHNwOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInByb2dyYW0iLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5ydW50aW1lLnByb2dyYW07CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiZW52IiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMucnVudGltZS5lbnY7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBWTTsKICB9KCk7CgogIF9leHBvcnRzLkxvd0xldmVsVk0gPSBWTTsKCiAgdmFyIFRlbXBsYXRlSXRlcmF0b3JJbXBsID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gVGVtcGxhdGVJdGVyYXRvckltcGwodm0pIHsKICAgICAgdGhpcy52bSA9IHZtOwogICAgfQoKICAgIHZhciBfcHJvdG82NSA9IFRlbXBsYXRlSXRlcmF0b3JJbXBsLnByb3RvdHlwZTsKCiAgICBfcHJvdG82NS5uZXh0ID0gZnVuY3Rpb24gbmV4dCgpIHsKICAgICAgcmV0dXJuIHRoaXMudm0ubmV4dCgpOwogICAgfTsKCiAgICByZXR1cm4gVGVtcGxhdGVJdGVyYXRvckltcGw7CiAgfSgpOwoKICBmdW5jdGlvbiByZW5kZXJNYWluKHByb2dyYW0sIGVudiwgc2VsZiwgZHluYW1pY1Njb3BlLCBidWlsZGVyLCBoYW5kbGUpIHsKICAgIHZhciB2bSA9IFZNLmluaXRpYWwocHJvZ3JhbSwgZW52LCBzZWxmLCBkeW5hbWljU2NvcGUsIGJ1aWxkZXIsIGhhbmRsZSk7CiAgICByZXR1cm4gbmV3IFRlbXBsYXRlSXRlcmF0b3JJbXBsKHZtKTsKICB9CiAgLyoqCiAgICogUmV0dXJucyBhIFRlbXBsYXRlSXRlcmF0b3IgY29uZmlndXJlZCB0byByZW5kZXIgYSByb290IGNvbXBvbmVudC4KICAgKi8KCgogIGZ1bmN0aW9uIHJlbmRlckNvbXBvbmVudChwcm9ncmFtLCBlbnYsIGJ1aWxkZXIsIG1haW4sIG5hbWUsIGFyZ3MpIHsKICAgIGlmIChhcmdzID09PSB2b2lkIDApIHsKICAgICAgYXJncyA9IHt9OwogICAgfQoKICAgIHZhciB2bSA9IFZNLmVtcHR5KHByb2dyYW0sIGVudiwgYnVpbGRlciwgbWFpbik7CiAgICB2YXIgcmVzb2x2ZXIgPSB2bS5jb25zdGFudHMucmVzb2x2ZXI7CiAgICB2YXIgZGVmaW5pdGlvbiA9IHJlc29sdmVDb21wb25lbnQocmVzb2x2ZXIsIG5hbWUsIG51bGwpOwogICAgdmFyIG1hbmFnZXIgPSBkZWZpbml0aW9uLm1hbmFnZXIsCiAgICAgICAgc3RhdGUgPSBkZWZpbml0aW9uLnN0YXRlOwogICAgdmFyIGNhcGFiaWxpdGllcyA9IGNhcGFiaWxpdHlGbGFnc0Zyb20obWFuYWdlci5nZXRDYXBhYmlsaXRpZXMoc3RhdGUpKTsKICAgIHZhciBpbnZvY2F0aW9uOwoKICAgIGlmIChoYXNTdGF0aWNMYXlvdXRDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgbWFuYWdlcikpIHsKICAgICAgaW52b2NhdGlvbiA9IG1hbmFnZXIuZ2V0TGF5b3V0KHN0YXRlLCByZXNvbHZlcik7CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBpbnZva2UgY29tcG9uZW50cyB3aXRoIGR5bmFtaWMgbGF5b3V0cyBhcyBhIHJvb3QgY29tcG9uZW50LicpOwogICAgfSAvLyBHZXQgYSBsaXN0IG9mIHR1cGxlcyBvZiBhcmd1bWVudCBuYW1lcyBhbmQgcmVmZXJlbmNlcywgbGlrZQogICAgLy8gW1sndGl0bGUnLCByZWZlcmVuY2VdLCBbJ25hbWUnLCByZWZlcmVuY2VdXQoKCiAgICB2YXIgYXJnTGlzdCA9IE9iamVjdC5rZXlzKGFyZ3MpLm1hcChmdW5jdGlvbiAoa2V5KSB7CiAgICAgIHJldHVybiBba2V5LCBhcmdzW2tleV1dOwogICAgfSk7CiAgICB2YXIgYmxvY2tOYW1lcyA9IFsnbWFpbicsICdlbHNlJywgJ2F0dHJzJ107IC8vIFByZWZpeCBhcmd1bWVudCBuYW1lcyB3aXRoIGBAYCBzeW1ib2wKCiAgICB2YXIgYXJnTmFtZXMgPSBhcmdMaXN0Lm1hcChmdW5jdGlvbiAoX3JlZjYwKSB7CiAgICAgIHZhciBuYW1lID0gX3JlZjYwWzBdOwogICAgICByZXR1cm4gIkAiICsgbmFtZTsKICAgIH0pOwogICAgdm0ucHVzaEZyYW1lKCk7IC8vIFB1c2ggYmxvY2tzIG9uIHRvIHRoZSBzdGFjaywgdGhyZWUgc3RhY2sgdmFsdWVzIHBlciBibG9jawoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMyAqIGJsb2NrTmFtZXMubGVuZ3RoOyBpKyspIHsKICAgICAgdm0uc3RhY2sucHVzaChudWxsKTsKICAgIH0KCiAgICB2bS5zdGFjay5wdXNoKG51bGwpOyAvLyBGb3IgZWFjaCBhcmd1bWVudCwgcHVzaCBpdHMgYmFja2luZyByZWZlcmVuY2Ugb24gdG8gdGhlIHN0YWNrCgogICAgYXJnTGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChfcmVmNjEpIHsKICAgICAgdmFyIHJlZmVyZW5jZSA9IF9yZWY2MVsxXTsKICAgICAgdm0uc3RhY2sucHVzaChyZWZlcmVuY2UpOwogICAgfSk7IC8vIENvbmZpZ3VyZSBWTSBiYXNlZCBvbiBibG9ja3MgYW5kIGFyZ3MganVzdCBwdXNoZWQgb24gdG8gdGhlIHN0YWNrLgoKICAgIHZtLmFyZ3Muc2V0dXAodm0uc3RhY2ssIGFyZ05hbWVzLCBibG9ja05hbWVzLCAwLCBmYWxzZSk7IC8vIE5lZWRlZCBmb3IgdGhlIE9wLk1haW4gb3Bjb2RlOiBhcmd1bWVudHMsIGNvbXBvbmVudCBpbnZvY2F0aW9uIG9iamVjdCwgYW5kCiAgICAvLyBjb21wb25lbnQgZGVmaW5pdGlvbi4KCiAgICB2bS5zdGFjay5wdXNoKHZtLmFyZ3MpOwogICAgdm0uc3RhY2sucHVzaChpbnZvY2F0aW9uKTsKICAgIHZtLnN0YWNrLnB1c2goZGVmaW5pdGlvbik7CiAgICByZXR1cm4gbmV3IFRlbXBsYXRlSXRlcmF0b3JJbXBsKHZtKTsKICB9CgogIHZhciBEeW5hbWljVmFyUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRHluYW1pY1ZhclJlZmVyZW5jZShzY29wZSwgbmFtZVJlZikgewogICAgICB0aGlzLnNjb3BlID0gc2NvcGU7CiAgICAgIHRoaXMubmFtZVJlZiA9IG5hbWVSZWY7CiAgICAgIHZhciB2YXJUYWcgPSB0aGlzLnZhclRhZyA9ICgwLCBfcmVmZXJlbmNlMi5jcmVhdGVVcGRhdGFibGVUYWcpKCk7CiAgICAgIHRoaXMudGFnID0gKDAsIF9yZWZlcmVuY2UyLmNvbWJpbmUpKFtuYW1lUmVmLnRhZywgdmFyVGFnXSk7CiAgICB9CgogICAgdmFyIF9wcm90bzY2ID0gRHluYW1pY1ZhclJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNjYudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZ2V0VmFyKCkudmFsdWUoKTsKICAgIH07CgogICAgX3Byb3RvNjYuZ2V0ID0gZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICByZXR1cm4gdGhpcy5nZXRWYXIoKS5nZXQoa2V5KTsKICAgIH07CgogICAgX3Byb3RvNjYuZ2V0VmFyID0gZnVuY3Rpb24gZ2V0VmFyKCkgewogICAgICB2YXIgbmFtZSA9IFN0cmluZyh0aGlzLm5hbWVSZWYudmFsdWUoKSk7CiAgICAgIHZhciByZWYgPSB0aGlzLnNjb3BlLmdldChuYW1lKTsKICAgICAgKDAsIF9yZWZlcmVuY2UyLnVwZGF0ZSkodGhpcy52YXJUYWcsIHJlZi50YWcpOwogICAgICByZXR1cm4gcmVmOwogICAgfTsKCiAgICByZXR1cm4gRHluYW1pY1ZhclJlZmVyZW5jZTsKICB9KCk7CgogIGZ1bmN0aW9uIGdldER5bmFtaWNWYXIodm0sIGFyZ3MpIHsKICAgIHZhciBzY29wZSA9IHZtLmR5bmFtaWNTY29wZSgpOwogICAgdmFyIG5hbWVSZWYgPSBhcmdzLnBvc2l0aW9uYWwuYXQoMCk7CiAgICByZXR1cm4gbmV3IER5bmFtaWNWYXJSZWZlcmVuY2Uoc2NvcGUsIG5hbWVSZWYpOwogIH0KICAvKiogQGludGVybmFsICovCgoKICB2YXIgREVGQVVMVF9DQVBBQklMSVRJRVMgPSB7CiAgICBkeW5hbWljTGF5b3V0OiB0cnVlLAogICAgZHluYW1pY1RhZzogdHJ1ZSwKICAgIHByZXBhcmVBcmdzOiB0cnVlLAogICAgY3JlYXRlQXJnczogdHJ1ZSwKICAgIGF0dHJpYnV0ZUhvb2s6IGZhbHNlLAogICAgZWxlbWVudEhvb2s6IGZhbHNlLAogICAgZHluYW1pY1Njb3BlOiB0cnVlLAogICAgY3JlYXRlQ2FsbGVyOiBmYWxzZSwKICAgIHVwZGF0ZUhvb2s6IHRydWUsCiAgICBjcmVhdGVJbnN0YW5jZTogdHJ1ZQogIH07CiAgX2V4cG9ydHMuREVGQVVMVF9DQVBBQklMSVRJRVMgPSBERUZBVUxUX0NBUEFCSUxJVElFUzsKICB2YXIgTUlOSU1BTF9DQVBBQklMSVRJRVMgPSB7CiAgICBkeW5hbWljTGF5b3V0OiBmYWxzZSwKICAgIGR5bmFtaWNUYWc6IGZhbHNlLAogICAgcHJlcGFyZUFyZ3M6IGZhbHNlLAogICAgY3JlYXRlQXJnczogZmFsc2UsCiAgICBhdHRyaWJ1dGVIb29rOiBmYWxzZSwKICAgIGVsZW1lbnRIb29rOiBmYWxzZSwKICAgIGR5bmFtaWNTY29wZTogZmFsc2UsCiAgICBjcmVhdGVDYWxsZXI6IGZhbHNlLAogICAgdXBkYXRlSG9vazogZmFsc2UsCiAgICBjcmVhdGVJbnN0YW5jZTogZmFsc2UKICB9OwogIF9leHBvcnRzLk1JTklNQUxfQ0FQQUJJTElUSUVTID0gTUlOSU1BTF9DQVBBQklMSVRJRVM7CiAgdmFyIFNFUklBTElaQVRJT05fRklSU1RfTk9ERV9TVFJJTkcgPSAnJStiOjAlJzsKICBfZXhwb3J0cy5TRVJJQUxJWkFUSU9OX0ZJUlNUX05PREVfU1RSSU5HID0gU0VSSUFMSVpBVElPTl9GSVJTVF9OT0RFX1NUUklORzsKCiAgZnVuY3Rpb24gaXNTZXJpYWxpemF0aW9uRmlyc3ROb2RlKG5vZGUpIHsKICAgIHJldHVybiBub2RlLm5vZGVWYWx1ZSA9PT0gU0VSSUFMSVpBVElPTl9GSVJTVF9OT0RFX1NUUklORzsKICB9CgogIHZhciBSZWh5ZHJhdGluZ0N1cnNvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ3Vyc29yKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUmVoeWRyYXRpbmdDdXJzb3IsIF9DdXJzb3IpOwoKICAgIGZ1bmN0aW9uIFJlaHlkcmF0aW5nQ3Vyc29yKGVsZW1lbnQsIG5leHRTaWJsaW5nLCBzdGFydGluZ0Jsb2NrRGVwdGgpIHsKICAgICAgdmFyIF90aGlzMjA7CgogICAgICBfdGhpczIwID0gX0N1cnNvci5jYWxsKHRoaXMsIGVsZW1lbnQsIG5leHRTaWJsaW5nKSB8fCB0aGlzOwogICAgICBfdGhpczIwLnN0YXJ0aW5nQmxvY2tEZXB0aCA9IHN0YXJ0aW5nQmxvY2tEZXB0aDsKICAgICAgX3RoaXMyMC5jYW5kaWRhdGUgPSBudWxsOwogICAgICBfdGhpczIwLmluamVjdGVkT21pdHRlZE5vZGUgPSBmYWxzZTsKICAgICAgX3RoaXMyMC5vcGVuQmxvY2tEZXB0aCA9IHN0YXJ0aW5nQmxvY2tEZXB0aCAtIDE7CiAgICAgIHJldHVybiBfdGhpczIwOwogICAgfQoKICAgIHJldHVybiBSZWh5ZHJhdGluZ0N1cnNvcjsKICB9KEN1cnNvcik7CgogIHZhciBSZWh5ZHJhdGVCdWlsZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9OZXdFbGVtZW50QnVpbGRlcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFJlaHlkcmF0ZUJ1aWxkZXIsIF9OZXdFbGVtZW50QnVpbGRlcik7CgogICAgLy8gcHJpdmF0ZSBjYW5kaWRhdGU6IE9wdGlvbjxTaW1wbGUuTm9kZT4gPSBudWxsOwogICAgZnVuY3Rpb24gUmVoeWRyYXRlQnVpbGRlcihlbnYsIHBhcmVudE5vZGUsIG5leHRTaWJsaW5nKSB7CiAgICAgIHZhciBfdGhpczIxOwoKICAgICAgX3RoaXMyMSA9IF9OZXdFbGVtZW50QnVpbGRlci5jYWxsKHRoaXMsIGVudiwgcGFyZW50Tm9kZSwgbmV4dFNpYmxpbmcpIHx8IHRoaXM7CiAgICAgIF90aGlzMjEudW5tYXRjaGVkQXR0cmlidXRlcyA9IG51bGw7CiAgICAgIF90aGlzMjEuYmxvY2tEZXB0aCA9IDA7CiAgICAgIGlmIChuZXh0U2libGluZykgdGhyb3cgbmV3IEVycm9yKCdSZWh5ZHJhdGlvbiB3aXRoIG5leHRTaWJsaW5nIG5vdCBzdXBwb3J0ZWQnKTsKICAgICAgdmFyIG5vZGUgPSBfdGhpczIxLmN1cnJlbnRDdXJzb3IuZWxlbWVudC5maXJzdENoaWxkOwoKICAgICAgd2hpbGUgKG5vZGUgIT09IG51bGwpIHsKICAgICAgICBpZiAoaXNDb21tZW50KG5vZGUpICYmIGlzU2VyaWFsaXphdGlvbkZpcnN0Tm9kZShub2RlKSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICBub2RlID0gbm9kZS5uZXh0U2libGluZzsKICAgICAgfQoKICAgICAgX3RoaXMyMS5jYW5kaWRhdGUgPSBub2RlOwogICAgICByZXR1cm4gX3RoaXMyMTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjcgPSBSZWh5ZHJhdGVCdWlsZGVyLnByb3RvdHlwZTsKCiAgICBfcHJvdG82Ny5wdXNoRWxlbWVudCA9IGZ1bmN0aW9uIHB1c2hFbGVtZW50KGVsZW1lbnQsIG5leHRTaWJsaW5nKSB7CiAgICAgIHZhciBfdGhpcyRibG9ja0RlcHRoID0gdGhpcy5ibG9ja0RlcHRoLAogICAgICAgICAgYmxvY2tEZXB0aCA9IF90aGlzJGJsb2NrRGVwdGggPT09IHZvaWQgMCA/IDAgOiBfdGhpcyRibG9ja0RlcHRoOwogICAgICB2YXIgY3Vyc29yID0gbmV3IFJlaHlkcmF0aW5nQ3Vyc29yKGVsZW1lbnQsIG5leHRTaWJsaW5nLCBibG9ja0RlcHRoKTsKICAgICAgdmFyIGN1cnJlbnRDdXJzb3IgPSB0aGlzLmN1cnJlbnRDdXJzb3I7CgogICAgICBpZiAoY3VycmVudEN1cnNvcikgewogICAgICAgIGlmIChjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSkgewogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8ZGl2PiAgIDwtLS0tLS0tLS0tLS0tLS0gIGN1cnJlbnRDdXJzb3IuZWxlbWVudAogICAgICAgICAgICogICA8IS0tJStiOjElLS0+CiAgICAgICAgICAgKiAgIDxkaXY+IDwtLS0tLS0tLS0tLS0tLS0gIGN1cnJlbnRDdXJzb3IuY2FuZGlkYXRlIC0+IGN1cnNvci5lbGVtZW50CiAgICAgICAgICAgKiAgICAgPCEtLSUrYjoyJS0tPiA8LSAgY3VycmVudEN1cnNvci5jYW5kaWRhdGUuZmlyc3RDaGlsZCAtPiBjdXJzb3IuY2FuZGlkYXRlCiAgICAgICAgICAgKiAgICAgRm9vCiAgICAgICAgICAgKiAgICAgPCEtLSUtYjoyJS0tPgogICAgICAgICAgICogICA8L2Rpdj4KICAgICAgICAgICAqICAgPCEtLSUtYjoxJS0tPiAgPC0tICBiZWNvbWVzIGN1cnJlbnRDdXJzb3IuY2FuZGlkYXRlCiAgICAgICAgICAgKi8KICAgICAgICAgIC8vIHdoZXJlIHRvIHJlaHlkcmF0ZSBmcm9tIGlmIHdlIGFyZSBpbiByZWh5ZHJhdGlvbiBtb2RlCiAgICAgICAgICBjdXJzb3IuY2FuZGlkYXRlID0gZWxlbWVudC5maXJzdENoaWxkOyAvLyB3aGVyZSB0byBjb250aW51ZSB3aGVuIHdlIHBvcAoKICAgICAgICAgIGN1cnJlbnRDdXJzb3IuY2FuZGlkYXRlID0gZWxlbWVudC5uZXh0U2libGluZzsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHRoaXMuY3Vyc29yU3RhY2sucHVzaChjdXJzb3IpOwogICAgfTsKCiAgICBfcHJvdG82Ny5jbGVhck1pc21hdGNoID0gZnVuY3Rpb24gY2xlYXJNaXNtYXRjaChjYW5kaWRhdGUpIHsKICAgICAgdmFyIGN1cnJlbnQgPSBjYW5kaWRhdGU7CiAgICAgIHZhciBjdXJyZW50Q3Vyc29yID0gdGhpcy5jdXJyZW50Q3Vyc29yOwoKICAgICAgaWYgKGN1cnJlbnRDdXJzb3IgIT09IG51bGwpIHsKICAgICAgICB2YXIgb3BlbkJsb2NrRGVwdGggPSBjdXJyZW50Q3Vyc29yLm9wZW5CbG9ja0RlcHRoOwoKICAgICAgICBpZiAob3BlbkJsb2NrRGVwdGggPj0gY3VycmVudEN1cnNvci5zdGFydGluZ0Jsb2NrRGVwdGgpIHsKICAgICAgICAgIHdoaWxlIChjdXJyZW50ICYmICEoaXNDb21tZW50KGN1cnJlbnQpICYmIGdldENsb3NlQmxvY2tEZXB0aChjdXJyZW50KSA9PT0gb3BlbkJsb2NrRGVwdGgpKSB7CiAgICAgICAgICAgIGN1cnJlbnQgPSB0aGlzLnJlbW92ZShjdXJyZW50KTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgd2hpbGUgKGN1cnJlbnQgIT09IG51bGwpIHsKICAgICAgICAgICAgY3VycmVudCA9IHRoaXMucmVtb3ZlKGN1cnJlbnQpOwogICAgICAgICAgfQogICAgICAgIH0gLy8gY3VycmVudCBjdXJzb3IgcGFyZW50Tm9kZSBzaG91bGQgYmUgb3BlbkNhbmRpZGF0ZSBpZiBlbGVtZW50CiAgICAgICAgLy8gb3Igb3BlbkNhbmRpZGF0ZS5wYXJlbnROb2RlIGlmIGNvbW1lbnQKCgogICAgICAgIGN1cnJlbnRDdXJzb3IubmV4dFNpYmxpbmcgPSBjdXJyZW50OyAvLyBkaXNhYmxlIHJlaHlkcmF0aW9uIHVudGlsIHdlIHBvcEVsZW1lbnQgb3IgY2xvc2VCbG9jayBmb3Igb3BlbkJsb2NrRGVwdGgKCiAgICAgICAgY3VycmVudEN1cnNvci5jYW5kaWRhdGUgPSBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzY3Ll9fb3BlbkJsb2NrID0gZnVuY3Rpb24gX19vcGVuQmxvY2soKSB7CiAgICAgIHZhciBjdXJyZW50Q3Vyc29yID0gdGhpcy5jdXJyZW50Q3Vyc29yOwogICAgICBpZiAoY3VycmVudEN1cnNvciA9PT0gbnVsbCkgcmV0dXJuOwogICAgICB2YXIgYmxvY2tEZXB0aCA9IHRoaXMuYmxvY2tEZXB0aDsKICAgICAgdGhpcy5ibG9ja0RlcHRoKys7CiAgICAgIHZhciBjYW5kaWRhdGUgPSBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZTsKICAgICAgaWYgKGNhbmRpZGF0ZSA9PT0gbnVsbCkgcmV0dXJuOwogICAgICB2YXIgdGFnTmFtZSA9IGN1cnJlbnRDdXJzb3IuZWxlbWVudC50YWdOYW1lOwoKICAgICAgaWYgKGlzQ29tbWVudChjYW5kaWRhdGUpICYmIGdldE9wZW5CbG9ja0RlcHRoKGNhbmRpZGF0ZSkgPT09IGJsb2NrRGVwdGgpIHsKICAgICAgICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSA9IHRoaXMucmVtb3ZlKGNhbmRpZGF0ZSk7CiAgICAgICAgY3VycmVudEN1cnNvci5vcGVuQmxvY2tEZXB0aCA9IGJsb2NrRGVwdGg7CiAgICAgIH0gZWxzZSBpZiAodGFnTmFtZSAhPT0gJ1RJVExFJyAmJiB0YWdOYW1lICE9PSAnU0NSSVBUJyAmJiB0YWdOYW1lICE9PSAnU1RZTEUnKSB7CiAgICAgICAgdGhpcy5jbGVhck1pc21hdGNoKGNhbmRpZGF0ZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNjcuX19jbG9zZUJsb2NrID0gZnVuY3Rpb24gX19jbG9zZUJsb2NrKCkgewogICAgICB2YXIgY3VycmVudEN1cnNvciA9IHRoaXMuY3VycmVudEN1cnNvcjsKICAgICAgaWYgKGN1cnJlbnRDdXJzb3IgPT09IG51bGwpIHJldHVybjsgLy8gb3BlbkJsb2NrIGlzIHRoZSBsYXN0IHJlaHlkcmF0ZWQgb3BlbiBibG9jawoKICAgICAgdmFyIG9wZW5CbG9ja0RlcHRoID0gY3VycmVudEN1cnNvci5vcGVuQmxvY2tEZXB0aDsgLy8gdGhpcyBjdXJyZW50bHkgaXMgdGhlIGV4cGVjdGVkIG5leHQgb3BlbiBibG9jayBkZXB0aAoKICAgICAgdGhpcy5ibG9ja0RlcHRoLS07CiAgICAgIHZhciBjYW5kaWRhdGUgPSBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZTsgLy8gcmVoeWRyYXRpbmcKCiAgICAgIGlmIChjYW5kaWRhdGUgIT09IG51bGwpIHsKICAgICAgICBpZiAoaXNDb21tZW50KGNhbmRpZGF0ZSkgJiYgZ2V0Q2xvc2VCbG9ja0RlcHRoKGNhbmRpZGF0ZSkgPT09IG9wZW5CbG9ja0RlcHRoKSB7CiAgICAgICAgICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSA9IHRoaXMucmVtb3ZlKGNhbmRpZGF0ZSk7CiAgICAgICAgICBjdXJyZW50Q3Vyc29yLm9wZW5CbG9ja0RlcHRoLS07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuY2xlYXJNaXNtYXRjaChjYW5kaWRhdGUpOwogICAgICAgIH0gLy8gaWYgdGhlIG9wZW5CbG9ja0RlcHRoIG1hdGNoZXMgdGhlIGJsb2NrRGVwdGggd2UganVzdCBjbG9zZWQgdG8KICAgICAgICAvLyB0aGVuIHJlc3RvcmUgcmVoeWRyYXRpb24KCiAgICAgIH0KCiAgICAgIGlmIChjdXJyZW50Q3Vyc29yLm9wZW5CbG9ja0RlcHRoID09PSB0aGlzLmJsb2NrRGVwdGgpIHsKICAgICAgICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSA9IHRoaXMucmVtb3ZlKGN1cnJlbnRDdXJzb3IubmV4dFNpYmxpbmcpOwogICAgICAgIGN1cnJlbnRDdXJzb3Iub3BlbkJsb2NrRGVwdGgtLTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG82Ny5fX2FwcGVuZE5vZGUgPSBmdW5jdGlvbiBfX2FwcGVuZE5vZGUobm9kZSkgewogICAgICB2YXIgY2FuZGlkYXRlID0gdGhpcy5jYW5kaWRhdGU7IC8vIFRoaXMgY29kZSBwYXRoIGlzIG9ubHkgdXNlZCB3aGVuIGluc2VydGluZyBwcmVjaXNlbHkgb25lIG5vZGUuIEl0IG5lZWRzIG1vcmUKICAgICAgLy8gY29tcGFyaXNvbiBsb2dpYywgYnV0IHdlIGNhbiBwcm9iYWJseSBsZWFuIG9uIHRoZSBjYXNlcyB3aGVyZSB0aGlzIGNvZGUgcGF0aAogICAgICAvLyBpcyBhY3R1YWxseSB1c2VkLgoKICAgICAgaWYgKGNhbmRpZGF0ZSkgewogICAgICAgIHJldHVybiBjYW5kaWRhdGU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuX19hcHBlbmROb2RlLmNhbGwodGhpcywgbm9kZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNjcuX19hcHBlbmRIVE1MID0gZnVuY3Rpb24gX19hcHBlbmRIVE1MKGh0bWwpIHsKICAgICAgdmFyIGNhbmRpZGF0ZUJvdW5kcyA9IHRoaXMubWFya2VyQm91bmRzKCk7CgogICAgICBpZiAoY2FuZGlkYXRlQm91bmRzKSB7CiAgICAgICAgdmFyIGZpcnN0ID0gY2FuZGlkYXRlQm91bmRzLmZpcnN0Tm9kZSgpOwogICAgICAgIHZhciBsYXN0ID0gY2FuZGlkYXRlQm91bmRzLmxhc3ROb2RlKCk7CiAgICAgICAgdmFyIG5ld0JvdW5kcyA9IG5ldyBDb25jcmV0ZUJvdW5kcyh0aGlzLmVsZW1lbnQsIGZpcnN0Lm5leHRTaWJsaW5nLCBsYXN0LnByZXZpb3VzU2libGluZyk7CiAgICAgICAgdmFyIHBvc3NpYmxlRW1wdHlNYXJrZXIgPSB0aGlzLnJlbW92ZShmaXJzdCk7CiAgICAgICAgdGhpcy5yZW1vdmUobGFzdCk7CgogICAgICAgIGlmIChwb3NzaWJsZUVtcHR5TWFya2VyICE9PSBudWxsICYmIGlzRW1wdHkkMShwb3NzaWJsZUVtcHR5TWFya2VyKSkgewogICAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSB0aGlzLnJlbW92ZShwb3NzaWJsZUVtcHR5TWFya2VyKTsKCiAgICAgICAgICBpZiAodGhpcy5jYW5kaWRhdGUgIT09IG51bGwpIHsKICAgICAgICAgICAgdGhpcy5jbGVhck1pc21hdGNoKHRoaXMuY2FuZGlkYXRlKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiBuZXdCb3VuZHM7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuX19hcHBlbmRIVE1MLmNhbGwodGhpcywgaHRtbCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNjcucmVtb3ZlID0gZnVuY3Rpb24gcmVtb3ZlKG5vZGUpIHsKICAgICAgdmFyIGVsZW1lbnQgPSBub2RlLnBhcmVudE5vZGU7CiAgICAgIHZhciBuZXh0ID0gbm9kZS5uZXh0U2libGluZzsKICAgICAgZWxlbWVudC5yZW1vdmVDaGlsZChub2RlKTsKICAgICAgcmV0dXJuIG5leHQ7CiAgICB9OwoKICAgIF9wcm90bzY3Lm1hcmtlckJvdW5kcyA9IGZ1bmN0aW9uIG1hcmtlckJvdW5kcygpIHsKICAgICAgdmFyIF9jYW5kaWRhdGUgPSB0aGlzLmNhbmRpZGF0ZTsKCiAgICAgIGlmIChfY2FuZGlkYXRlICYmIGlzTWFya2VyKF9jYW5kaWRhdGUpKSB7CiAgICAgICAgdmFyIGZpcnN0ID0gX2NhbmRpZGF0ZTsKICAgICAgICB2YXIgbGFzdCA9IGZpcnN0Lm5leHRTaWJsaW5nOwoKICAgICAgICB3aGlsZSAobGFzdCAmJiAhaXNNYXJrZXIobGFzdCkpIHsKICAgICAgICAgIGxhc3QgPSBsYXN0Lm5leHRTaWJsaW5nOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIG5ldyBDb25jcmV0ZUJvdW5kcyh0aGlzLmVsZW1lbnQsIGZpcnN0LCBsYXN0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG82Ny5fX2FwcGVuZFRleHQgPSBmdW5jdGlvbiBfX2FwcGVuZFRleHQoc3RyaW5nKSB7CiAgICAgIHZhciBjYW5kaWRhdGUgPSB0aGlzLmNhbmRpZGF0ZTsKCiAgICAgIGlmIChjYW5kaWRhdGUpIHsKICAgICAgICBpZiAoaXNUZXh0Tm9kZShjYW5kaWRhdGUpKSB7CiAgICAgICAgICBpZiAoY2FuZGlkYXRlLm5vZGVWYWx1ZSAhPT0gc3RyaW5nKSB7CiAgICAgICAgICAgIGNhbmRpZGF0ZS5ub2RlVmFsdWUgPSBzdHJpbmc7CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSBjYW5kaWRhdGUubmV4dFNpYmxpbmc7CiAgICAgICAgICByZXR1cm4gY2FuZGlkYXRlOwogICAgICAgIH0gZWxzZSBpZiAoY2FuZGlkYXRlICYmIChpc1NlcGFyYXRvcihjYW5kaWRhdGUpIHx8IGlzRW1wdHkkMShjYW5kaWRhdGUpKSkgewogICAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSBjYW5kaWRhdGUubmV4dFNpYmxpbmc7CiAgICAgICAgICB0aGlzLnJlbW92ZShjYW5kaWRhdGUpOwogICAgICAgICAgcmV0dXJuIHRoaXMuX19hcHBlbmRUZXh0KHN0cmluZyk7CiAgICAgICAgfSBlbHNlIGlmIChpc0VtcHR5JDEoY2FuZGlkYXRlKSkgewogICAgICAgICAgdmFyIG5leHQgPSB0aGlzLnJlbW92ZShjYW5kaWRhdGUpOwogICAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSBuZXh0OwogICAgICAgICAgdmFyIHRleHQgPSB0aGlzLmRvbS5jcmVhdGVUZXh0Tm9kZShzdHJpbmcpOwogICAgICAgICAgdGhpcy5kb20uaW5zZXJ0QmVmb3JlKHRoaXMuZWxlbWVudCwgdGV4dCwgbmV4dCk7CiAgICAgICAgICByZXR1cm4gdGV4dDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhpcy5jbGVhck1pc21hdGNoKGNhbmRpZGF0ZSk7CiAgICAgICAgICByZXR1cm4gX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS5fX2FwcGVuZFRleHQuY2FsbCh0aGlzLCBzdHJpbmcpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS5fX2FwcGVuZFRleHQuY2FsbCh0aGlzLCBzdHJpbmcpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzY3Ll9fYXBwZW5kQ29tbWVudCA9IGZ1bmN0aW9uIF9fYXBwZW5kQ29tbWVudChzdHJpbmcpIHsKICAgICAgdmFyIF9jYW5kaWRhdGUgPSB0aGlzLmNhbmRpZGF0ZTsKCiAgICAgIGlmIChfY2FuZGlkYXRlICYmIGlzQ29tbWVudChfY2FuZGlkYXRlKSkgewogICAgICAgIGlmIChfY2FuZGlkYXRlLm5vZGVWYWx1ZSAhPT0gc3RyaW5nKSB7CiAgICAgICAgICBfY2FuZGlkYXRlLm5vZGVWYWx1ZSA9IHN0cmluZzsKICAgICAgICB9CgogICAgICAgIHRoaXMuY2FuZGlkYXRlID0gX2NhbmRpZGF0ZS5uZXh0U2libGluZzsKICAgICAgICByZXR1cm4gX2NhbmRpZGF0ZTsKICAgICAgfSBlbHNlIGlmIChfY2FuZGlkYXRlKSB7CiAgICAgICAgdGhpcy5jbGVhck1pc21hdGNoKF9jYW5kaWRhdGUpOwogICAgICB9CgogICAgICByZXR1cm4gX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS5fX2FwcGVuZENvbW1lbnQuY2FsbCh0aGlzLCBzdHJpbmcpOwogICAgfTsKCiAgICBfcHJvdG82Ny5fX29wZW5FbGVtZW50ID0gZnVuY3Rpb24gX19vcGVuRWxlbWVudCh0YWcpIHsKICAgICAgdmFyIF9jYW5kaWRhdGUgPSB0aGlzLmNhbmRpZGF0ZTsKCiAgICAgIGlmIChfY2FuZGlkYXRlICYmIGlzRWxlbWVudChfY2FuZGlkYXRlKSAmJiBpc1NhbWVOb2RlVHlwZShfY2FuZGlkYXRlLCB0YWcpKSB7CiAgICAgICAgdGhpcy51bm1hdGNoZWRBdHRyaWJ1dGVzID0gW10uc2xpY2UuY2FsbChfY2FuZGlkYXRlLmF0dHJpYnV0ZXMpOwogICAgICAgIHJldHVybiBfY2FuZGlkYXRlOwogICAgICB9IGVsc2UgaWYgKF9jYW5kaWRhdGUpIHsKICAgICAgICBpZiAoaXNFbGVtZW50KF9jYW5kaWRhdGUpICYmIF9jYW5kaWRhdGUudGFnTmFtZSA9PT0gJ1RCT0RZJykgewogICAgICAgICAgdGhpcy5wdXNoRWxlbWVudChfY2FuZGlkYXRlLCBudWxsKTsKICAgICAgICAgIHRoaXMuY3VycmVudEN1cnNvci5pbmplY3RlZE9taXR0ZWROb2RlID0gdHJ1ZTsKICAgICAgICAgIHJldHVybiB0aGlzLl9fb3BlbkVsZW1lbnQodGFnKTsKICAgICAgICB9CgogICAgICAgIHRoaXMuY2xlYXJNaXNtYXRjaChfY2FuZGlkYXRlKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuX19vcGVuRWxlbWVudC5jYWxsKHRoaXMsIHRhZyk7CiAgICB9OwoKICAgIF9wcm90bzY3Ll9fc2V0QXR0cmlidXRlID0gZnVuY3Rpb24gX19zZXRBdHRyaWJ1dGUobmFtZSwgdmFsdWUkJDEsIG5hbWVzcGFjZSkgewogICAgICB2YXIgdW5tYXRjaGVkID0gdGhpcy51bm1hdGNoZWRBdHRyaWJ1dGVzOwoKICAgICAgaWYgKHVubWF0Y2hlZCkgewogICAgICAgIHZhciBhdHRyID0gZmluZEJ5TmFtZSh1bm1hdGNoZWQsIG5hbWUpOwoKICAgICAgICBpZiAoYXR0cikgewogICAgICAgICAgaWYgKGF0dHIudmFsdWUgIT09IHZhbHVlJCQxKSB7CiAgICAgICAgICAgIGF0dHIudmFsdWUgPSB2YWx1ZSQkMTsKICAgICAgICAgIH0KCiAgICAgICAgICB1bm1hdGNoZWQuc3BsaWNlKHVubWF0Y2hlZC5pbmRleE9mKGF0dHIpLCAxKTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fc2V0QXR0cmlidXRlLmNhbGwodGhpcywgbmFtZSwgdmFsdWUkJDEsIG5hbWVzcGFjZSk7CiAgICB9OwoKICAgIF9wcm90bzY3Ll9fc2V0UHJvcGVydHkgPSBmdW5jdGlvbiBfX3NldFByb3BlcnR5KG5hbWUsIHZhbHVlJCQxKSB7CiAgICAgIHZhciB1bm1hdGNoZWQgPSB0aGlzLnVubWF0Y2hlZEF0dHJpYnV0ZXM7CgogICAgICBpZiAodW5tYXRjaGVkKSB7CiAgICAgICAgdmFyIGF0dHIgPSBmaW5kQnlOYW1lKHVubWF0Y2hlZCwgbmFtZSk7CgogICAgICAgIGlmIChhdHRyKSB7CiAgICAgICAgICBpZiAoYXR0ci52YWx1ZSAhPT0gdmFsdWUkJDEpIHsKICAgICAgICAgICAgYXR0ci52YWx1ZSA9IHZhbHVlJCQxOwogICAgICAgICAgfQoKICAgICAgICAgIHVubWF0Y2hlZC5zcGxpY2UodW5tYXRjaGVkLmluZGV4T2YoYXR0ciksIDEpOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuX19zZXRQcm9wZXJ0eS5jYWxsKHRoaXMsIG5hbWUsIHZhbHVlJCQxKTsKICAgIH07CgogICAgX3Byb3RvNjcuX19mbHVzaEVsZW1lbnQgPSBmdW5jdGlvbiBfX2ZsdXNoRWxlbWVudChwYXJlbnQsIGNvbnN0cnVjdGluZykgewogICAgICB2YXIgdW5tYXRjaGVkID0gdGhpcy51bm1hdGNoZWRBdHRyaWJ1dGVzOwoKICAgICAgaWYgKHVubWF0Y2hlZCkgewogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdW5tYXRjaGVkLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICB0aGlzLmNvbnN0cnVjdGluZy5yZW1vdmVBdHRyaWJ1dGUodW5tYXRjaGVkW2ldLm5hbWUpOwogICAgICAgIH0KCiAgICAgICAgdGhpcy51bm1hdGNoZWRBdHRyaWJ1dGVzID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fZmx1c2hFbGVtZW50LmNhbGwodGhpcywgcGFyZW50LCBjb25zdHJ1Y3RpbmcpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzY3LndpbGxDbG9zZUVsZW1lbnQgPSBmdW5jdGlvbiB3aWxsQ2xvc2VFbGVtZW50KCkgewogICAgICB2YXIgY2FuZGlkYXRlID0gdGhpcy5jYW5kaWRhdGUsCiAgICAgICAgICBjdXJyZW50Q3Vyc29yID0gdGhpcy5jdXJyZW50Q3Vyc29yOwoKICAgICAgaWYgKGNhbmRpZGF0ZSAhPT0gbnVsbCkgewogICAgICAgIHRoaXMuY2xlYXJNaXNtYXRjaChjYW5kaWRhdGUpOwogICAgICB9CgogICAgICBpZiAoY3VycmVudEN1cnNvciAmJiBjdXJyZW50Q3Vyc29yLmluamVjdGVkT21pdHRlZE5vZGUpIHsKICAgICAgICB0aGlzLnBvcEVsZW1lbnQoKTsKICAgICAgfQoKICAgICAgX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS53aWxsQ2xvc2VFbGVtZW50LmNhbGwodGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzY3LmdldE1hcmtlciA9IGZ1bmN0aW9uIGdldE1hcmtlcihlbGVtZW50LCBndWlkKSB7CiAgICAgIHZhciBtYXJrZXIgPSBlbGVtZW50LnF1ZXJ5U2VsZWN0b3IoInNjcmlwdFtnbG1yPVwiIiArIGd1aWQgKyAiXCJdIik7CgogICAgICBpZiAobWFya2VyKSB7CiAgICAgICAgcmV0dXJuIG1hcmtlcjsKICAgICAgfQoKICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZmluZCBzZXJpYWxpemVkIGN1cnNvciBmb3IgYGluLWVsZW1lbnRgJyk7CiAgICB9OwoKICAgIF9wcm90bzY3Ll9fcHVzaFJlbW90ZUVsZW1lbnQgPSBmdW5jdGlvbiBfX3B1c2hSZW1vdGVFbGVtZW50KGVsZW1lbnQsIGN1cnNvcklkLCBuZXh0U2libGluZykgewogICAgICBpZiAobmV4dFNpYmxpbmcgPT09IHZvaWQgMCkgewogICAgICAgIG5leHRTaWJsaW5nID0gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIG1hcmtlciA9IHRoaXMuZ2V0TWFya2VyKGVsZW1lbnQsIGN1cnNvcklkKTsKCiAgICAgIGlmIChtYXJrZXIucGFyZW50Tm9kZSA9PT0gZWxlbWVudCkgewogICAgICAgIHZhciBjdXJyZW50Q3Vyc29yID0gdGhpcy5jdXJyZW50Q3Vyc29yOwogICAgICAgIHZhciBjYW5kaWRhdGUgPSBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZTsKICAgICAgICB0aGlzLnB1c2hFbGVtZW50KGVsZW1lbnQsIG5leHRTaWJsaW5nKTsKICAgICAgICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSA9IGNhbmRpZGF0ZTsKICAgICAgICB0aGlzLmNhbmRpZGF0ZSA9IHRoaXMucmVtb3ZlKG1hcmtlcik7CiAgICAgICAgdmFyIHRyYWNrZXIgPSBuZXcgUmVtb3RlQmxvY2tUcmFja2VyKGVsZW1lbnQpOwogICAgICAgIHRoaXMucHVzaEJsb2NrVHJhY2tlcih0cmFja2VyLCB0cnVlKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG82Ny5kaWRBcHBlbmRCb3VuZHMgPSBmdW5jdGlvbiBkaWRBcHBlbmRCb3VuZHMoYm91bmRzKSB7CiAgICAgIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuZGlkQXBwZW5kQm91bmRzLmNhbGwodGhpcywgYm91bmRzKTsKCiAgICAgIGlmICh0aGlzLmNhbmRpZGF0ZSkgewogICAgICAgIHZhciBsYXN0ID0gYm91bmRzLmxhc3ROb2RlKCk7CiAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSBsYXN0ICYmIGxhc3QubmV4dFNpYmxpbmc7CiAgICAgIH0KCiAgICAgIHJldHVybiBib3VuZHM7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoUmVoeWRyYXRlQnVpbGRlciwgW3sKICAgICAga2V5OiAiY3VycmVudEN1cnNvciIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmN1cnNvclN0YWNrLmN1cnJlbnQ7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiY2FuZGlkYXRlIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMuY3VycmVudEN1cnNvcikgewogICAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudEN1cnNvci5jYW5kaWRhdGU7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQobm9kZSkgewogICAgICAgIHRoaXMuY3VycmVudEN1cnNvci5jYW5kaWRhdGUgPSBub2RlOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gUmVoeWRyYXRlQnVpbGRlcjsKICB9KE5ld0VsZW1lbnRCdWlsZGVyKTsKCiAgX2V4cG9ydHMuUmVoeWRyYXRlQnVpbGRlciA9IFJlaHlkcmF0ZUJ1aWxkZXI7CgogIGZ1bmN0aW9uIGlzVGV4dE5vZGUobm9kZSkgewogICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IDM7CiAgfQoKICBmdW5jdGlvbiBpc0NvbW1lbnQobm9kZSkgewogICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IDg7CiAgfQoKICBmdW5jdGlvbiBnZXRPcGVuQmxvY2tEZXB0aChub2RlKSB7CiAgICB2YXIgYm91bmRzRGVwdGggPSBub2RlLm5vZGVWYWx1ZS5tYXRjaCgvXiVcK2I6KFxkKyklJC8pOwoKICAgIGlmIChib3VuZHNEZXB0aCAmJiBib3VuZHNEZXB0aFsxXSkgewogICAgICByZXR1cm4gTnVtYmVyKGJvdW5kc0RlcHRoWzFdKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZ2V0Q2xvc2VCbG9ja0RlcHRoKG5vZGUpIHsKICAgIHZhciBib3VuZHNEZXB0aCA9IG5vZGUubm9kZVZhbHVlLm1hdGNoKC9eJVwtYjooXGQrKSUkLyk7CgogICAgaWYgKGJvdW5kc0RlcHRoICYmIGJvdW5kc0RlcHRoWzFdKSB7CiAgICAgIHJldHVybiBOdW1iZXIoYm91bmRzRGVwdGhbMV0pOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBpc0VsZW1lbnQobm9kZSkgewogICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IDE7CiAgfQoKICBmdW5jdGlvbiBpc01hcmtlcihub2RlKSB7CiAgICByZXR1cm4gbm9kZS5ub2RlVHlwZSA9PT0gOCAmJiBub2RlLm5vZGVWYWx1ZSA9PT0gJyVnbG1yJSc7CiAgfQoKICBmdW5jdGlvbiBpc1NlcGFyYXRvcihub2RlKSB7CiAgICByZXR1cm4gbm9kZS5ub2RlVHlwZSA9PT0gOCAmJiBub2RlLm5vZGVWYWx1ZSA9PT0gJyV8JSc7CiAgfQoKICBmdW5jdGlvbiBpc0VtcHR5JDEobm9kZSkgewogICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IDggJiYgbm9kZS5ub2RlVmFsdWUgPT09ICclICUnOwogIH0KCiAgZnVuY3Rpb24gaXNTYW1lTm9kZVR5cGUoY2FuZGlkYXRlLCB0YWcpIHsKICAgIGlmIChjYW5kaWRhdGUubmFtZXNwYWNlVVJJID09PSBTVkdfTkFNRVNQQUNFKSB7CiAgICAgIHJldHVybiBjYW5kaWRhdGUudGFnTmFtZSA9PT0gdGFnOwogICAgfQoKICAgIHJldHVybiBjYW5kaWRhdGUudGFnTmFtZSA9PT0gdGFnLnRvVXBwZXJDYXNlKCk7CiAgfQoKICBmdW5jdGlvbiBmaW5kQnlOYW1lKGFycmF5LCBuYW1lKSB7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBhdHRyID0gYXJyYXlbaV07CiAgICAgIGlmIChhdHRyLm5hbWUgPT09IG5hbWUpIHJldHVybiBhdHRyOwogICAgfQoKICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQoKICBmdW5jdGlvbiByZWh5ZHJhdGlvbkJ1aWxkZXIoZW52LCBjdXJzb3IpIHsKICAgIHJldHVybiBSZWh5ZHJhdGVCdWlsZGVyLmZvckluaXRpYWxSZW5kZXIoZW52LCBjdXJzb3IpOwogIH0KfSk7CmRlZmluZSgiQGdsaW1tZXIvdXRpbCIsIFsiZXhwb3J0cyIsICJlbWJlci1iYWJlbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5hc3NlcnQgPSBkZWJ1Z0Fzc2VydDsKICBfZXhwb3J0cy5hc3NpZ24gPSBhc3NpZ247CiAgX2V4cG9ydHMuZmlsbE51bGxzID0gZmlsbE51bGxzOwogIF9leHBvcnRzLmVuc3VyZUd1aWQgPSBlbnN1cmVHdWlkOwogIF9leHBvcnRzLmluaXRpYWxpemVHdWlkID0gaW5pdGlhbGl6ZUd1aWQ7CiAgX2V4cG9ydHMuZGljdCA9IGRpY3Q7CiAgX2V4cG9ydHMudW53cmFwID0gdW53cmFwOwogIF9leHBvcnRzLmV4cGVjdCA9IGV4cGVjdDsKICBfZXhwb3J0cy51bnJlYWNoYWJsZSA9IHVucmVhY2hhYmxlOwogIF9leHBvcnRzLkVNUFRZX0FSUkFZID0gX2V4cG9ydHMuTGlzdFNsaWNlID0gX2V4cG9ydHMuTGlzdE5vZGUgPSBfZXhwb3J0cy5MaW5rZWRMaXN0ID0gX2V4cG9ydHMuRU1QVFlfU0xJQ0UgPSBfZXhwb3J0cy5EaWN0U2V0ID0gX2V4cG9ydHMuU3RhY2sgPSB2b2lkIDA7CgogIGZ1bmN0aW9uIHVud3JhcCh2YWwpIHsKICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQpIHRocm93IG5ldyBFcnJvcigiRXhwZWN0ZWQgdmFsdWUgdG8gYmUgcHJlc2VudCIpOwogICAgcmV0dXJuIHZhbDsKICB9CgogIGZ1bmN0aW9uIGV4cGVjdCh2YWwsIG1lc3NhZ2UpIHsKICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQpIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTsKICAgIHJldHVybiB2YWw7CiAgfQoKICBmdW5jdGlvbiB1bnJlYWNoYWJsZShtZXNzYWdlKSB7CiAgICBpZiAobWVzc2FnZSA9PT0gdm9pZCAwKSB7CiAgICAgIG1lc3NhZ2UgPSAndW5yZWFjaGFibGUnOwogICAgfQoKICAgIHJldHVybiBuZXcgRXJyb3IobWVzc2FnZSk7CiAgfSAvLyBpbXBvcnQgTG9nZ2VyIGZyb20gJy4vbG9nZ2VyJzsKICAvLyBsZXQgYWxyZWFkeVdhcm5lZCA9IGZhbHNlOwoKCiAgZnVuY3Rpb24gZGVidWdBc3NlcnQodGVzdCwgbXNnKSB7CiAgICAvLyBpZiAoIWFscmVhZHlXYXJuZWQpIHsKICAgIC8vICAgYWxyZWFkeVdhcm5lZCA9IHRydWU7CiAgICAvLyAgIExvZ2dlci53YXJuKCJEb24ndCBsZWF2ZSBkZWJ1ZyBhc3NlcnRpb25zIG9uIGluIHB1YmxpYyBidWlsZHMiKTsKICAgIC8vIH0KICAgIGlmICghdGVzdCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IobXNnIHx8ICdhc3NlcnRpb24gZmFpbHVyZScpOwogICAgfQogIH0KCiAgdmFyIG9iaktleXMgPSBPYmplY3Qua2V5czsKCiAgZnVuY3Rpb24gYXNzaWduKG9iaikgewogICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGFzc2lnbm1lbnQgPSBhcmd1bWVudHNbaV07CiAgICAgIGlmIChhc3NpZ25tZW50ID09PSBudWxsIHx8IHR5cGVvZiBhc3NpZ25tZW50ICE9PSAnb2JqZWN0JykgY29udGludWU7CiAgICAgIHZhciBrZXlzID0gb2JqS2V5cyhhc3NpZ25tZW50KTsKCiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwga2V5cy5sZW5ndGg7IGorKykgewogICAgICAgIHZhciBrZXkgPSBrZXlzW2pdOwogICAgICAgIG9ialtrZXldID0gYXNzaWdubWVudFtrZXldOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIG9iajsKICB9CgogIGZ1bmN0aW9uIGZpbGxOdWxscyhjb3VudCkgewogICAgdmFyIGFyciA9IG5ldyBBcnJheShjb3VudCk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIGFycltpXSA9IG51bGw7CiAgICB9CgogICAgcmV0dXJuIGFycjsKICB9CgogIHZhciBHVUlEID0gMDsKCiAgZnVuY3Rpb24gaW5pdGlhbGl6ZUd1aWQob2JqZWN0KSB7CiAgICByZXR1cm4gb2JqZWN0Ll9ndWlkID0gKytHVUlEOwogIH0KCiAgZnVuY3Rpb24gZW5zdXJlR3VpZChvYmplY3QpIHsKICAgIHJldHVybiBvYmplY3QuX2d1aWQgfHwgaW5pdGlhbGl6ZUd1aWQob2JqZWN0KTsKICB9CgogIGZ1bmN0aW9uIGRpY3QoKSB7CiAgICByZXR1cm4gT2JqZWN0LmNyZWF0ZShudWxsKTsKICB9CgogIHZhciBEaWN0U2V0ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRGljdFNldCgpIHsKICAgICAgdGhpcy5kaWN0ID0gZGljdCgpOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBEaWN0U2V0LnByb3RvdHlwZTsKCiAgICBfcHJvdG8uYWRkID0gZnVuY3Rpb24gYWRkKG9iaikgewogICAgICBpZiAodHlwZW9mIG9iaiA9PT0gJ3N0cmluZycpIHRoaXMuZGljdFtvYmpdID0gb2JqO2Vsc2UgdGhpcy5kaWN0W2Vuc3VyZUd1aWQob2JqKV0gPSBvYmo7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICBfcHJvdG8uZGVsZXRlID0gZnVuY3Rpb24gX2RlbGV0ZShvYmopIHsKICAgICAgaWYgKHR5cGVvZiBvYmogPT09ICdzdHJpbmcnKSBkZWxldGUgdGhpcy5kaWN0W29ial07ZWxzZSBpZiAob2JqLl9ndWlkKSBkZWxldGUgdGhpcy5kaWN0W29iai5fZ3VpZF07CiAgICB9OwoKICAgIHJldHVybiBEaWN0U2V0OwogIH0oKTsKCiAgX2V4cG9ydHMuRGljdFNldCA9IERpY3RTZXQ7CgogIHZhciBTdGFjayA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFN0YWNrKCkgewogICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgIHRoaXMuY3VycmVudCA9IG51bGw7CiAgICB9CgogICAgdmFyIF9wcm90bzIgPSBTdGFjay5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5wdXNoID0gZnVuY3Rpb24gcHVzaChpdGVtKSB7CiAgICAgIHRoaXMuY3VycmVudCA9IGl0ZW07CiAgICAgIHRoaXMuc3RhY2sucHVzaChpdGVtKTsKICAgIH07CgogICAgX3Byb3RvMi5wb3AgPSBmdW5jdGlvbiBwb3AoKSB7CiAgICAgIHZhciBpdGVtID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgdmFyIGxlbiA9IHRoaXMuc3RhY2subGVuZ3RoOwogICAgICB0aGlzLmN1cnJlbnQgPSBsZW4gPT09IDAgPyBudWxsIDogdGhpcy5zdGFja1tsZW4gLSAxXTsKICAgICAgcmV0dXJuIGl0ZW0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBpdGVtOwogICAgfTsKCiAgICBfcHJvdG8yLmlzRW1wdHkgPSBmdW5jdGlvbiBpc0VtcHR5KCkgewogICAgICByZXR1cm4gdGhpcy5zdGFjay5sZW5ndGggPT09IDA7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoU3RhY2ssIFt7CiAgICAgIGtleTogInNpemUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5zdGFjay5sZW5ndGg7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBTdGFjazsKICB9KCk7CgogIF9leHBvcnRzLlN0YWNrID0gU3RhY2s7CgogIHZhciBMaXN0Tm9kZSA9IGZ1bmN0aW9uIExpc3ROb2RlKHZhbHVlKSB7CiAgICB0aGlzLm5leHQgPSBudWxsOwogICAgdGhpcy5wcmV2ID0gbnVsbDsKICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICB9OwoKICBfZXhwb3J0cy5MaXN0Tm9kZSA9IExpc3ROb2RlOwoKICB2YXIgTGlua2VkTGlzdCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIExpbmtlZExpc3QoKSB7CiAgICAgIHRoaXMuY2xlYXIoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMyA9IExpbmtlZExpc3QucHJvdG90eXBlOwoKICAgIF9wcm90bzMuaGVhZCA9IGZ1bmN0aW9uIGhlYWQoKSB7CiAgICAgIHJldHVybiB0aGlzLl9oZWFkOwogICAgfTsKCiAgICBfcHJvdG8zLnRhaWwgPSBmdW5jdGlvbiB0YWlsKCkgewogICAgICByZXR1cm4gdGhpcy5fdGFpbDsKICAgIH07CgogICAgX3Byb3RvMy5jbGVhciA9IGZ1bmN0aW9uIGNsZWFyKCkgewogICAgICB0aGlzLl9oZWFkID0gdGhpcy5fdGFpbCA9IG51bGw7CiAgICB9OwoKICAgIF9wcm90bzMudG9BcnJheSA9IGZ1bmN0aW9uIHRvQXJyYXkoKSB7CiAgICAgIHZhciBvdXQgPSBbXTsKICAgICAgdGhpcy5mb3JFYWNoTm9kZShmdW5jdGlvbiAobikgewogICAgICAgIHJldHVybiBvdXQucHVzaChuKTsKICAgICAgfSk7CiAgICAgIHJldHVybiBvdXQ7CiAgICB9OwoKICAgIF9wcm90bzMubmV4dE5vZGUgPSBmdW5jdGlvbiBuZXh0Tm9kZShub2RlKSB7CiAgICAgIHJldHVybiBub2RlLm5leHQ7CiAgICB9OwoKICAgIF9wcm90bzMuZm9yRWFjaE5vZGUgPSBmdW5jdGlvbiBmb3JFYWNoTm9kZShjYWxsYmFjaykgewogICAgICB2YXIgbm9kZSA9IHRoaXMuX2hlYWQ7CgogICAgICB3aGlsZSAobm9kZSAhPT0gbnVsbCkgewogICAgICAgIGNhbGxiYWNrKG5vZGUpOwogICAgICAgIG5vZGUgPSBub2RlLm5leHQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMy5pbnNlcnRCZWZvcmUgPSBmdW5jdGlvbiBpbnNlcnRCZWZvcmUobm9kZSwgcmVmZXJlbmNlKSB7CiAgICAgIGlmIChyZWZlcmVuY2UgPT09IHZvaWQgMCkgewogICAgICAgIHJlZmVyZW5jZSA9IG51bGw7CiAgICAgIH0KCiAgICAgIGlmIChyZWZlcmVuY2UgPT09IG51bGwpIHJldHVybiB0aGlzLmFwcGVuZChub2RlKTsKICAgICAgaWYgKHJlZmVyZW5jZS5wcmV2KSByZWZlcmVuY2UucHJldi5uZXh0ID0gbm9kZTtlbHNlIHRoaXMuX2hlYWQgPSBub2RlOwogICAgICBub2RlLnByZXYgPSByZWZlcmVuY2UucHJldjsKICAgICAgbm9kZS5uZXh0ID0gcmVmZXJlbmNlOwogICAgICByZWZlcmVuY2UucHJldiA9IG5vZGU7CiAgICAgIHJldHVybiBub2RlOwogICAgfTsKCiAgICBfcHJvdG8zLmFwcGVuZCA9IGZ1bmN0aW9uIGFwcGVuZChub2RlKSB7CiAgICAgIHZhciB0YWlsID0gdGhpcy5fdGFpbDsKCiAgICAgIGlmICh0YWlsKSB7CiAgICAgICAgdGFpbC5uZXh0ID0gbm9kZTsKICAgICAgICBub2RlLnByZXYgPSB0YWlsOwogICAgICAgIG5vZGUubmV4dCA9IG51bGw7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5faGVhZCA9IG5vZGU7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLl90YWlsID0gbm9kZTsKICAgIH07CgogICAgX3Byb3RvMy5yZW1vdmUgPSBmdW5jdGlvbiByZW1vdmUobm9kZSkgewogICAgICBpZiAobm9kZS5wcmV2KSBub2RlLnByZXYubmV4dCA9IG5vZGUubmV4dDtlbHNlIHRoaXMuX2hlYWQgPSBub2RlLm5leHQ7CiAgICAgIGlmIChub2RlLm5leHQpIG5vZGUubmV4dC5wcmV2ID0gbm9kZS5wcmV2O2Vsc2UgdGhpcy5fdGFpbCA9IG5vZGUucHJldjsKICAgICAgcmV0dXJuIG5vZGU7CiAgICB9OwoKICAgIHJldHVybiBMaW5rZWRMaXN0OwogIH0oKTsKCiAgX2V4cG9ydHMuTGlua2VkTGlzdCA9IExpbmtlZExpc3Q7CgogIHZhciBMaXN0U2xpY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBMaXN0U2xpY2UoaGVhZCwgdGFpbCkgewogICAgICB0aGlzLl9oZWFkID0gaGVhZDsKICAgICAgdGhpcy5fdGFpbCA9IHRhaWw7CiAgICB9CgogICAgdmFyIF9wcm90bzQgPSBMaXN0U2xpY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzQuZm9yRWFjaE5vZGUgPSBmdW5jdGlvbiBmb3JFYWNoTm9kZShjYWxsYmFjaykgewogICAgICB2YXIgbm9kZSA9IHRoaXMuX2hlYWQ7CgogICAgICB3aGlsZSAobm9kZSAhPT0gbnVsbCkgewogICAgICAgIGNhbGxiYWNrKG5vZGUpOwogICAgICAgIG5vZGUgPSB0aGlzLm5leHROb2RlKG5vZGUpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQuaGVhZCA9IGZ1bmN0aW9uIGhlYWQoKSB7CiAgICAgIHJldHVybiB0aGlzLl9oZWFkOwogICAgfTsKCiAgICBfcHJvdG80LnRhaWwgPSBmdW5jdGlvbiB0YWlsKCkgewogICAgICByZXR1cm4gdGhpcy5fdGFpbDsKICAgIH07CgogICAgX3Byb3RvNC50b0FycmF5ID0gZnVuY3Rpb24gdG9BcnJheSgpIHsKICAgICAgdmFyIG91dCA9IFtdOwogICAgICB0aGlzLmZvckVhY2hOb2RlKGZ1bmN0aW9uIChuKSB7CiAgICAgICAgcmV0dXJuIG91dC5wdXNoKG4pOwogICAgICB9KTsKICAgICAgcmV0dXJuIG91dDsKICAgIH07CgogICAgX3Byb3RvNC5uZXh0Tm9kZSA9IGZ1bmN0aW9uIG5leHROb2RlKG5vZGUpIHsKICAgICAgaWYgKG5vZGUgPT09IHRoaXMuX3RhaWwpIHJldHVybiBudWxsOwogICAgICByZXR1cm4gbm9kZS5uZXh0OwogICAgfTsKCiAgICByZXR1cm4gTGlzdFNsaWNlOwogIH0oKTsKCiAgX2V4cG9ydHMuTGlzdFNsaWNlID0gTGlzdFNsaWNlOwogIHZhciBFTVBUWV9TTElDRSA9IG5ldyBMaXN0U2xpY2UobnVsbCwgbnVsbCk7CiAgX2V4cG9ydHMuRU1QVFlfU0xJQ0UgPSBFTVBUWV9TTElDRTsKICB2YXIgRU1QVFlfQVJSQVkgPSBPYmplY3QuZnJlZXplKFtdKTsKICBfZXhwb3J0cy5FTVBUWV9BUlJBWSA9IEVNUFRZX0FSUkFZOwp9KTsKZGVmaW5lKCJAZ2xpbW1lci92bSIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLlJlZ2lzdGVyID0gdm9pZCAwOwoKICAvKioKICAgKiBSZWdpc3RlcnMKICAgKgogICAqIEZvciB0aGUgbW9zdCBwYXJ0LCB0aGVzZSBmb2xsb3dzIE1JUFMgbmFtaW5nIGNvbnZlbnRpb25zLCBob3dldmVyIHRoZQogICAqIHJlZ2lzdGVyIG51bWJlcnMgYXJlIGRpZmZlcmVudC4KICAgKi8KICB2YXIgUmVnaXN0ZXI7CiAgX2V4cG9ydHMuUmVnaXN0ZXIgPSBSZWdpc3RlcjsKCiAgKGZ1bmN0aW9uIChSZWdpc3RlcikgewogICAgLy8gJDAgb3IgJHBjIChwcm9ncmFtIGNvdW50ZXIpOiBwb2ludGVyIGludG8gYHByb2dyYW1gIGZvciB0aGUgbmV4dCBpbnN0dXJjdGlvbjsgLTEgbWVhbnMgZXhpdAogICAgUmVnaXN0ZXJbUmVnaXN0ZXJbInBjIl0gPSAwXSA9ICJwYyI7IC8vICQxIG9yICRyYSAocmV0dXJuIGFkZHJlc3MpOiBwb2ludGVyIGludG8gYHByb2dyYW1gIGZvciB0aGUgcmV0dXJuCgogICAgUmVnaXN0ZXJbUmVnaXN0ZXJbInJhIl0gPSAxXSA9ICJyYSI7IC8vICQyIG9yICRmcCAoZnJhbWUgcG9pbnRlcik6IHBvaW50ZXIgaW50byB0aGUgYGV2YWxTdGFja2AgZm9yIHRoZSBiYXNlIG9mIHRoZSBzdGFjawoKICAgIFJlZ2lzdGVyW1JlZ2lzdGVyWyJmcCJdID0gMl0gPSAiZnAiOyAvLyAkMyBvciAkc3AgKHN0YWNrIHBvaW50ZXIpOiBwb2ludGVyIGludG8gdGhlIGBldmFsU3RhY2tgIGZvciB0aGUgdG9wIG9mIHRoZSBzdGFjawoKICAgIFJlZ2lzdGVyW1JlZ2lzdGVyWyJzcCJdID0gM10gPSAic3AiOyAvLyAkNC0kNSBvciAkczAtJHMxIChzYXZlZCk6IGNhbGxlZSBzYXZlZCBnZW5lcmFsLXB1cnBvc2UgcmVnaXN0ZXJzCgogICAgUmVnaXN0ZXJbUmVnaXN0ZXJbInMwIl0gPSA0XSA9ICJzMCI7CiAgICBSZWdpc3RlcltSZWdpc3RlclsiczEiXSA9IDVdID0gInMxIjsgLy8gJDYtJDcgb3IgJHQwLSR0MSAodGVtcG9yYXJpZXMpOiBjYWxsZXIgc2F2ZWQgZ2VuZXJhbC1wdXJwb3NlIHJlZ2lzdGVycwoKICAgIFJlZ2lzdGVyW1JlZ2lzdGVyWyJ0MCJdID0gNl0gPSAidDAiOwogICAgUmVnaXN0ZXJbUmVnaXN0ZXJbInQxIl0gPSA3XSA9ICJ0MSI7IC8vICQ4IG9yICR2MCAocmV0dXJuIHZhbHVlKQoKICAgIFJlZ2lzdGVyW1JlZ2lzdGVyWyJ2MCJdID0gOF0gPSAidjAiOwogIH0pKFJlZ2lzdGVyIHx8IChfZXhwb3J0cy5SZWdpc3RlciA9IFJlZ2lzdGVyID0ge30pKTsKfSk7CmRlZmluZSgiQGdsaW1tZXIvd2lyZS1mb3JtYXQiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5pcyA9IGlzOwogIF9leHBvcnRzLmlzQXR0cmlidXRlID0gaXNBdHRyaWJ1dGU7CiAgX2V4cG9ydHMuaXNBcmd1bWVudCA9IGlzQXJndW1lbnQ7CiAgX2V4cG9ydHMuaXNNYXliZUxvY2FsID0gX2V4cG9ydHMuaXNHZXQgPSBfZXhwb3J0cy5pc0ZsdXNoRWxlbWVudCA9IF9leHBvcnRzLk9wcyA9IHZvaWQgMDsKICB2YXIgT3Bjb2RlczsKICBfZXhwb3J0cy5PcHMgPSBPcGNvZGVzOwoKICAoZnVuY3Rpb24gKE9wY29kZXMpIHsKICAgIC8vIFN0YXRlbWVudHMKICAgIE9wY29kZXNbT3Bjb2Rlc1siVGV4dCJdID0gMF0gPSAiVGV4dCI7CiAgICBPcGNvZGVzW09wY29kZXNbIkFwcGVuZCJdID0gMV0gPSAiQXBwZW5kIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siQ29tbWVudCJdID0gMl0gPSAiQ29tbWVudCI7CiAgICBPcGNvZGVzW09wY29kZXNbIk1vZGlmaWVyIl0gPSAzXSA9ICJNb2RpZmllciI7CiAgICBPcGNvZGVzW09wY29kZXNbIkJsb2NrIl0gPSA0XSA9ICJCbG9jayI7CiAgICBPcGNvZGVzW09wY29kZXNbIkNvbXBvbmVudCJdID0gNV0gPSAiQ29tcG9uZW50IjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siRHluYW1pY0NvbXBvbmVudCJdID0gNl0gPSAiRHluYW1pY0NvbXBvbmVudCI7CiAgICBPcGNvZGVzW09wY29kZXNbIk9wZW5FbGVtZW50Il0gPSA3XSA9ICJPcGVuRWxlbWVudCI7CiAgICBPcGNvZGVzW09wY29kZXNbIkZsdXNoRWxlbWVudCJdID0gOF0gPSAiRmx1c2hFbGVtZW50IjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siQ2xvc2VFbGVtZW50Il0gPSA5XSA9ICJDbG9zZUVsZW1lbnQiOwogICAgT3Bjb2Rlc1tPcGNvZGVzWyJTdGF0aWNBdHRyIl0gPSAxMF0gPSAiU3RhdGljQXR0ciI7CiAgICBPcGNvZGVzW09wY29kZXNbIkR5bmFtaWNBdHRyIl0gPSAxMV0gPSAiRHluYW1pY0F0dHIiOwogICAgT3Bjb2Rlc1tPcGNvZGVzWyJDb21wb25lbnRBdHRyIl0gPSAxMl0gPSAiQ29tcG9uZW50QXR0ciI7CiAgICBPcGNvZGVzW09wY29kZXNbIkF0dHJTcGxhdCJdID0gMTNdID0gIkF0dHJTcGxhdCI7CiAgICBPcGNvZGVzW09wY29kZXNbIllpZWxkIl0gPSAxNF0gPSAiWWllbGQiOwogICAgT3Bjb2Rlc1tPcGNvZGVzWyJQYXJ0aWFsIl0gPSAxNV0gPSAiUGFydGlhbCI7CiAgICBPcGNvZGVzW09wY29kZXNbIkR5bmFtaWNBcmciXSA9IDE2XSA9ICJEeW5hbWljQXJnIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siU3RhdGljQXJnIl0gPSAxN10gPSAiU3RhdGljQXJnIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siVHJ1c3RpbmdBdHRyIl0gPSAxOF0gPSAiVHJ1c3RpbmdBdHRyIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siVHJ1c3RpbmdDb21wb25lbnRBdHRyIl0gPSAxOV0gPSAiVHJ1c3RpbmdDb21wb25lbnRBdHRyIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siRGVidWdnZXIiXSA9IDIwXSA9ICJEZWJ1Z2dlciI7CiAgICBPcGNvZGVzW09wY29kZXNbIkNsaWVudFNpZGVTdGF0ZW1lbnQiXSA9IDIxXSA9ICJDbGllbnRTaWRlU3RhdGVtZW50IjsgLy8gRXhwcmVzc2lvbnMKCiAgICBPcGNvZGVzW09wY29kZXNbIlVua25vd24iXSA9IDIyXSA9ICJVbmtub3duIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siR2V0Il0gPSAyM10gPSAiR2V0IjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siTWF5YmVMb2NhbCJdID0gMjRdID0gIk1heWJlTG9jYWwiOwogICAgT3Bjb2Rlc1tPcGNvZGVzWyJIYXNCbG9jayJdID0gMjVdID0gIkhhc0Jsb2NrIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siSGFzQmxvY2tQYXJhbXMiXSA9IDI2XSA9ICJIYXNCbG9ja1BhcmFtcyI7CiAgICBPcGNvZGVzW09wY29kZXNbIlVuZGVmaW5lZCJdID0gMjddID0gIlVuZGVmaW5lZCI7CiAgICBPcGNvZGVzW09wY29kZXNbIkhlbHBlciJdID0gMjhdID0gIkhlbHBlciI7CiAgICBPcGNvZGVzW09wY29kZXNbIkNvbmNhdCJdID0gMjldID0gIkNvbmNhdCI7CiAgICBPcGNvZGVzW09wY29kZXNbIkNsaWVudFNpZGVFeHByZXNzaW9uIl0gPSAzMF0gPSAiQ2xpZW50U2lkZUV4cHJlc3Npb24iOwogIH0pKE9wY29kZXMgfHwgKF9leHBvcnRzLk9wcyA9IE9wY29kZXMgPSB7fSkpOwoKICBmdW5jdGlvbiBpcyh2YXJpYW50KSB7CiAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKSAmJiB2YWx1ZVswXSA9PT0gdmFyaWFudDsKICAgIH07CiAgfSAvLyBTdGF0ZW1lbnRzCgoKICB2YXIgaXNGbHVzaEVsZW1lbnQgPSBpcyhPcGNvZGVzLkZsdXNoRWxlbWVudCk7CiAgX2V4cG9ydHMuaXNGbHVzaEVsZW1lbnQgPSBpc0ZsdXNoRWxlbWVudDsKCiAgZnVuY3Rpb24gaXNBdHRyaWJ1dGUodmFsKSB7CiAgICByZXR1cm4gdmFsWzBdID09PSBPcGNvZGVzLlN0YXRpY0F0dHIgfHwgdmFsWzBdID09PSBPcGNvZGVzLkR5bmFtaWNBdHRyIHx8IHZhbFswXSA9PT0gT3Bjb2Rlcy5Db21wb25lbnRBdHRyIHx8IHZhbFswXSA9PT0gT3Bjb2Rlcy5UcnVzdGluZ0F0dHIgfHwgdmFsWzBdID09PSBPcGNvZGVzLlRydXN0aW5nQ29tcG9uZW50QXR0ciB8fCB2YWxbMF0gPT09IE9wY29kZXMuQXR0clNwbGF0IHx8IHZhbFswXSA9PT0gT3Bjb2Rlcy5Nb2RpZmllcjsKICB9CgogIGZ1bmN0aW9uIGlzQXJndW1lbnQodmFsKSB7CiAgICByZXR1cm4gdmFsWzBdID09PSBPcGNvZGVzLlN0YXRpY0FyZyB8fCB2YWxbMF0gPT09IE9wY29kZXMuRHluYW1pY0FyZzsKICB9IC8vIEV4cHJlc3Npb25zCgoKICB2YXIgaXNHZXQgPSBpcyhPcGNvZGVzLkdldCk7CiAgX2V4cG9ydHMuaXNHZXQgPSBpc0dldDsKICB2YXIgaXNNYXliZUxvY2FsID0gaXMoT3Bjb2Rlcy5NYXliZUxvY2FsKTsKICBfZXhwb3J0cy5pc01heWJlTG9jYWwgPSBpc01heWJlTG9jYWw7Cn0pOwpkZWZpbmUoImJhY2tidXJuZXIiLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuYnVpbGRQbGF0Zm9ybSA9IGJ1aWxkUGxhdGZvcm07CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKICB2YXIgU0VUX1RJTUVPVVQgPSBzZXRUaW1lb3V0OwoKICB2YXIgTk9PUCA9IGZ1bmN0aW9uIE5PT1AoKSB7fTsKCiAgZnVuY3Rpb24gYnVpbGROZXh0KGZsdXNoKSB7CiAgICAvLyBVc2luZyAicHJvbWlzZXMgZmlyc3QiIGhlcmUgdG86CiAgICAvLwogICAgLy8gMSkgRW5zdXJlIG1vcmUgY29uc2lzdGVudCBleHBlcmllbmNlIG9uIGJyb3dzZXJzIHRoYXQKICAgIC8vICAgIGhhdmUgZGlmZmVyZW50bHkgcXVldWVkIG1pY3JvdGFza3MgKHNlcGFyYXRlIHF1ZXVlcyBmb3IKICAgIC8vICAgIE11dGF0aW9uT2JzZXJ2ZXIgdnMgUHJvbWlzZXMpLgogICAgLy8gMikgRW5zdXJlIGJldHRlciBkZWJ1Z2dpbmcgZXhwZXJpZW5jZXMgKGl0IHNob3dzIHVwIGluIENocm9tZQogICAgLy8gICAgY2FsbCBzdGFjayBhcyAiUHJvbWlzZS50aGVuIChhc3luYykiKSB3aGljaCBpcyBtb3JlIGNvbnNpc3RlbnQKICAgIC8vICAgIHdpdGggdXNlciBleHBlY3RhdGlvbnMKICAgIC8vCiAgICAvLyBXaGVuIFByb21pc2UgaXMgdW5hdmFpbGFibGUgdXNlIE11dGF0aW9uT2JzZXJ2ZXIgKG1vc3RseSBzbyB0aGF0IHdlCiAgICAvLyBzdGlsbCBnZXQgbWljcm90YXNrcyBvbiBJRTExKSwgYW5kIHdoZW4gbmVpdGhlciBNdXRhdGlvbk9ic2VydmVyIGFuZAogICAgLy8gUHJvbWlzZSBhcmUgcHJlc2VudCB1c2UgYSBwbGFpbiBvbGQgc2V0VGltZW91dC4KICAgIGlmICh0eXBlb2YgUHJvbWlzZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICB2YXIgYXV0b3J1blByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTsKICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gYXV0b3J1blByb21pc2UudGhlbihmbHVzaCk7CiAgICAgIH07CiAgICB9IGVsc2UgaWYgKHR5cGVvZiBNdXRhdGlvbk9ic2VydmVyID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIHZhciBpdGVyYXRpb25zID0gMDsKICAgICAgdmFyIG9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoZmx1c2gpOwogICAgICB2YXIgbm9kZSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCcnKTsKICAgICAgb2JzZXJ2ZXIub2JzZXJ2ZShub2RlLCB7CiAgICAgICAgY2hhcmFjdGVyRGF0YTogdHJ1ZQogICAgICB9KTsKICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgICBpdGVyYXRpb25zID0gKytpdGVyYXRpb25zICUgMjsKICAgICAgICBub2RlLmRhdGEgPSAnJyArIGl0ZXJhdGlvbnM7CiAgICAgICAgcmV0dXJuIGl0ZXJhdGlvbnM7CiAgICAgIH07CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBTRVRfVElNRU9VVChmbHVzaCwgMCk7CiAgICAgIH07CiAgICB9CiAgfQoKICBmdW5jdGlvbiBidWlsZFBsYXRmb3JtKGZsdXNoKSB7CiAgICB2YXIgY2xlYXJOZXh0ID0gTk9PUDsKICAgIHJldHVybiB7CiAgICAgIHNldFRpbWVvdXQ6IGZ1bmN0aW9uIChfc2V0VGltZW91dCkgewogICAgICAgIGZ1bmN0aW9uIHNldFRpbWVvdXQoX3gsIF94MikgewogICAgICAgICAgcmV0dXJuIF9zZXRUaW1lb3V0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICAgICAgfQoKICAgICAgICBzZXRUaW1lb3V0LnRvU3RyaW5nID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuIF9zZXRUaW1lb3V0LnRvU3RyaW5nKCk7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQ7CiAgICAgIH0oZnVuY3Rpb24gKGZuLCBtcykgewogICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZuLCBtcyk7CiAgICAgIH0pLAogICAgICBjbGVhclRpbWVvdXQ6IGZ1bmN0aW9uIChfY2xlYXJUaW1lb3V0KSB7CiAgICAgICAgZnVuY3Rpb24gY2xlYXJUaW1lb3V0KF94MykgewogICAgICAgICAgcmV0dXJuIF9jbGVhclRpbWVvdXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgICAgICB9CgogICAgICAgIGNsZWFyVGltZW91dC50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBfY2xlYXJUaW1lb3V0LnRvU3RyaW5nKCk7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dDsKICAgICAgfShmdW5jdGlvbiAodGltZXJJZCkgewogICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQodGltZXJJZCk7CiAgICAgIH0pLAogICAgICBub3c6IGZ1bmN0aW9uIG5vdygpIHsKICAgICAgICByZXR1cm4gRGF0ZS5ub3coKTsKICAgICAgfSwKICAgICAgbmV4dDogYnVpbGROZXh0KGZsdXNoKSwKICAgICAgY2xlYXJOZXh0OiBjbGVhck5leHQKICAgIH07CiAgfQoKICB2YXIgTlVNQkVSID0gL1xkKy87CiAgdmFyIFRJTUVSU19PRkZTRVQgPSA2OwoKICBmdW5jdGlvbiBpc0NvZXJjYWJsZU51bWJlcihzdXNwZWN0KSB7CiAgICB2YXIgdHlwZSA9IHR5cGVvZiBzdXNwZWN0OwogICAgcmV0dXJuIHR5cGUgPT09ICdudW1iZXInICYmIHN1c3BlY3QgPT09IHN1c3BlY3QgfHwgdHlwZSA9PT0gJ3N0cmluZycgJiYgTlVNQkVSLnRlc3Qoc3VzcGVjdCk7CiAgfQoKICBmdW5jdGlvbiBnZXRPbkVycm9yKG9wdGlvbnMpIHsKICAgIHJldHVybiBvcHRpb25zLm9uRXJyb3IgfHwgb3B0aW9ucy5vbkVycm9yVGFyZ2V0ICYmIG9wdGlvbnMub25FcnJvclRhcmdldFtvcHRpb25zLm9uRXJyb3JNZXRob2RdOwogIH0KCiAgZnVuY3Rpb24gZmluZEl0ZW0odGFyZ2V0LCBtZXRob2QsIGNvbGxlY3Rpb24pIHsKICAgIHZhciBpbmRleCA9IC0xOwoKICAgIGZvciAodmFyIGkgPSAwLCBsID0gY29sbGVjdGlvbi5sZW5ndGg7IGkgPCBsOyBpICs9IDQpIHsKICAgICAgaWYgKGNvbGxlY3Rpb25baV0gPT09IHRhcmdldCAmJiBjb2xsZWN0aW9uW2kgKyAxXSA9PT0gbWV0aG9kKSB7CiAgICAgICAgaW5kZXggPSBpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGluZGV4OwogIH0KCiAgZnVuY3Rpb24gZmluZFRpbWVySXRlbSh0YXJnZXQsIG1ldGhvZCwgY29sbGVjdGlvbikgewogICAgdmFyIGluZGV4ID0gLTE7CgogICAgZm9yICh2YXIgaSA9IDIsIGwgPSBjb2xsZWN0aW9uLmxlbmd0aDsgaSA8IGw7IGkgKz0gNikgewogICAgICBpZiAoY29sbGVjdGlvbltpXSA9PT0gdGFyZ2V0ICYmIGNvbGxlY3Rpb25baSArIDFdID09PSBtZXRob2QpIHsKICAgICAgICBpbmRleCA9IGkgLSAyOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGluZGV4OwogIH0KCiAgZnVuY3Rpb24gZ2V0UXVldWVJdGVtcyhpdGVtcywgcXVldWVJdGVtTGVuZ3RoLCBxdWV1ZUl0ZW1Qb3NpdGlvbk9mZnNldCkgewogICAgaWYgKHF1ZXVlSXRlbVBvc2l0aW9uT2Zmc2V0ID09PSB2b2lkIDApIHsKICAgICAgcXVldWVJdGVtUG9zaXRpb25PZmZzZXQgPSAwOwogICAgfQoKICAgIHZhciBxdWV1ZUl0ZW1zID0gW107CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpdGVtcy5sZW5ndGg7IGkgKz0gcXVldWVJdGVtTGVuZ3RoKSB7CiAgICAgIHZhciBtYXliZUVycm9yID0gaXRlbXNbaSArIDMKICAgICAgLyogc3RhY2sgKi8KICAgICAgKyBxdWV1ZUl0ZW1Qb3NpdGlvbk9mZnNldF07CiAgICAgIHZhciBxdWV1ZUl0ZW0gPSB7CiAgICAgICAgdGFyZ2V0OiBpdGVtc1tpICsgMAogICAgICAgIC8qIHRhcmdldCAqLwogICAgICAgICsgcXVldWVJdGVtUG9zaXRpb25PZmZzZXRdLAogICAgICAgIG1ldGhvZDogaXRlbXNbaSArIDEKICAgICAgICAvKiBtZXRob2QgKi8KICAgICAgICArIHF1ZXVlSXRlbVBvc2l0aW9uT2Zmc2V0XSwKICAgICAgICBhcmdzOiBpdGVtc1tpICsgMgogICAgICAgIC8qIGFyZ3MgKi8KICAgICAgICArIHF1ZXVlSXRlbVBvc2l0aW9uT2Zmc2V0XSwKICAgICAgICBzdGFjazogbWF5YmVFcnJvciAhPT0gdW5kZWZpbmVkICYmICdzdGFjaycgaW4gbWF5YmVFcnJvciA/IG1heWJlRXJyb3Iuc3RhY2sgOiAnJwogICAgICB9OwogICAgICBxdWV1ZUl0ZW1zLnB1c2gocXVldWVJdGVtKTsKICAgIH0KCiAgICByZXR1cm4gcXVldWVJdGVtczsKICB9CgogIGZ1bmN0aW9uIGJpbmFyeVNlYXJjaCh0aW1lLCB0aW1lcnMpIHsKICAgIHZhciBzdGFydCA9IDA7CiAgICB2YXIgZW5kID0gdGltZXJzLmxlbmd0aCAtIFRJTUVSU19PRkZTRVQ7CiAgICB2YXIgbWlkZGxlOwogICAgdmFyIGw7CgogICAgd2hpbGUgKHN0YXJ0IDwgZW5kKSB7CiAgICAgIC8vIHNpbmNlIHRpbWVycyBpcyBhbiBhcnJheSBvZiBwYWlycyAnbCcgd2lsbCBhbHdheXMKICAgICAgLy8gYmUgYW4gaW50ZWdlcgogICAgICBsID0gKGVuZCAtIHN0YXJ0KSAvIFRJTUVSU19PRkZTRVQ7IC8vIGNvbXBlbnNhdGUgZm9yIHRoZSBpbmRleCBpbiBjYXNlIGV2ZW4gbnVtYmVyCiAgICAgIC8vIG9mIHBhaXJzIGluc2lkZSB0aW1lcnMKCiAgICAgIG1pZGRsZSA9IHN0YXJ0ICsgbCAtIGwgJSBUSU1FUlNfT0ZGU0VUOwoKICAgICAgaWYgKHRpbWUgPj0gdGltZXJzW21pZGRsZV0pIHsKICAgICAgICBzdGFydCA9IG1pZGRsZSArIFRJTUVSU19PRkZTRVQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZW5kID0gbWlkZGxlOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHRpbWUgPj0gdGltZXJzW3N0YXJ0XSA/IHN0YXJ0ICsgVElNRVJTX09GRlNFVCA6IHN0YXJ0OwogIH0KCiAgdmFyIFFVRVVFX0lURU1fTEVOR1RIID0gNDsKCiAgdmFyIFF1ZXVlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUXVldWUobmFtZSwgb3B0aW9ucywgZ2xvYmFsT3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICBpZiAoZ2xvYmFsT3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgZ2xvYmFsT3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICB0aGlzLl9xdWV1ZUJlaW5nRmx1c2hlZCA9IFtdOwogICAgICB0aGlzLnRhcmdldFF1ZXVlcyA9IG5ldyBNYXAoKTsKICAgICAgdGhpcy5pbmRleCA9IDA7CiAgICAgIHRoaXMuX3F1ZXVlID0gW107CiAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7CiAgICAgIHRoaXMuZ2xvYmFsT3B0aW9ucyA9IGdsb2JhbE9wdGlvbnM7CiAgICB9CgogICAgdmFyIF9wcm90byA9IFF1ZXVlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uc3RhY2tGb3IgPSBmdW5jdGlvbiBzdGFja0ZvcihpbmRleCkgewogICAgICBpZiAoaW5kZXggPCB0aGlzLl9xdWV1ZS5sZW5ndGgpIHsKICAgICAgICB2YXIgZW50cnkgPSB0aGlzLl9xdWV1ZVtpbmRleCAqIDMgKyBRVUVVRV9JVEVNX0xFTkdUSF07CgogICAgICAgIGlmIChlbnRyeSkgewogICAgICAgICAgcmV0dXJuIGVudHJ5LnN0YWNrOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmZsdXNoID0gZnVuY3Rpb24gZmx1c2goc3luYykgewogICAgICB2YXIgX3RoaXMkb3B0aW9ucyA9IHRoaXMub3B0aW9ucywKICAgICAgICAgIGJlZm9yZSA9IF90aGlzJG9wdGlvbnMuYmVmb3JlLAogICAgICAgICAgYWZ0ZXIgPSBfdGhpcyRvcHRpb25zLmFmdGVyOwogICAgICB2YXIgdGFyZ2V0OwogICAgICB2YXIgbWV0aG9kOwogICAgICB2YXIgYXJnczsKICAgICAgdmFyIGVycm9yUmVjb3JkZWRGb3JTdGFjazsKICAgICAgdGhpcy50YXJnZXRRdWV1ZXMuY2xlYXIoKTsKCiAgICAgIGlmICh0aGlzLl9xdWV1ZUJlaW5nRmx1c2hlZC5sZW5ndGggPT09IDApIHsKICAgICAgICB0aGlzLl9xdWV1ZUJlaW5nRmx1c2hlZCA9IHRoaXMuX3F1ZXVlOwogICAgICAgIHRoaXMuX3F1ZXVlID0gW107CiAgICAgIH0KCiAgICAgIGlmIChiZWZvcmUgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGJlZm9yZSgpOwogICAgICB9CgogICAgICB2YXIgaW52b2tlOwogICAgICB2YXIgcXVldWVJdGVtcyA9IHRoaXMuX3F1ZXVlQmVpbmdGbHVzaGVkOwoKICAgICAgaWYgKHF1ZXVlSXRlbXMubGVuZ3RoID4gMCkgewogICAgICAgIHZhciBvbkVycm9yID0gZ2V0T25FcnJvcih0aGlzLmdsb2JhbE9wdGlvbnMpOwogICAgICAgIGludm9rZSA9IG9uRXJyb3IgPyB0aGlzLmludm9rZVdpdGhPbkVycm9yIDogdGhpcy5pbnZva2U7CgogICAgICAgIGZvciAodmFyIGkgPSB0aGlzLmluZGV4OyBpIDwgcXVldWVJdGVtcy5sZW5ndGg7IGkgKz0gUVVFVUVfSVRFTV9MRU5HVEgpIHsKICAgICAgICAgIHRoaXMuaW5kZXggKz0gUVVFVUVfSVRFTV9MRU5HVEg7CiAgICAgICAgICBtZXRob2QgPSBxdWV1ZUl0ZW1zW2kgKyAxXTsgLy8gbWV0aG9kIGNvdWxkIGhhdmUgYmVlbiBudWxsaWZpZWQgLyBjYW5jZWxlZCBkdXJpbmcgZmx1c2gKCiAgICAgICAgICBpZiAobWV0aG9kICE9PSBudWxsKSB7CiAgICAgICAgICAgIC8vCiAgICAgICAgICAgIC8vICAgICoqIEF0dGVudGlvbiBpbnRyZXBpZCBkZXZlbG9wZXIgKioKICAgICAgICAgICAgLy8KICAgICAgICAgICAgLy8gICAgVG8gZmluZCBvdXQgdGhlIHN0YWNrIG9mIHRoaXMgdGFzayB3aGVuIGl0IHdhcyBzY2hlZHVsZWQgb250bwogICAgICAgICAgICAvLyAgICB0aGUgcnVuIGxvb3AsIGFkZCB0aGUgZm9sbG93aW5nIHRvIHlvdXIgYXBwLmpzOgogICAgICAgICAgICAvLwogICAgICAgICAgICAvLyAgICBFbWJlci5ydW4uYmFja2J1cm5lci5ERUJVRyA9IHRydWU7IC8vIE5PVEU6IFRoaXMgc2xvd3MgeW91ciBhcHAsIGRvbid0IGxlYXZlIGl0IG9uIGluIHByb2R1Y3Rpb24uCiAgICAgICAgICAgIC8vCiAgICAgICAgICAgIC8vICAgIE9uY2UgdGhhdCBpcyBpbiBwbGFjZSwgd2hlbiB5b3UgYXJlIGF0IGEgYnJlYWtwb2ludCBhbmQgbmF2aWdhdGUKICAgICAgICAgICAgLy8gICAgaGVyZSBpbiB0aGUgc3RhY2sgZXhwbG9yZXIsIHlvdSBjYW4gbG9vayBhdCBgZXJyb3JSZWNvcmRlZEZvclN0YWNrLnN0YWNrYCwKICAgICAgICAgICAgLy8gICAgd2hpY2ggd2lsbCBiZSB0aGUgY2FwdHVyZWQgc3RhY2sgd2hlbiB0aGlzIGpvYiB3YXMgc2NoZWR1bGVkLgogICAgICAgICAgICAvLwogICAgICAgICAgICAvLyAgICBPbmUgcG9zc2libGUgbG9uZy10ZXJtIHNvbHV0aW9uIGlzIHRoZSBmb2xsb3dpbmcgQ2hyb21lIGlzc3VlOgogICAgICAgICAgICAvLyAgICAgICBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD0zMzI2MjQKICAgICAgICAgICAgLy8KICAgICAgICAgICAgdGFyZ2V0ID0gcXVldWVJdGVtc1tpXTsKICAgICAgICAgICAgYXJncyA9IHF1ZXVlSXRlbXNbaSArIDJdOwogICAgICAgICAgICBlcnJvclJlY29yZGVkRm9yU3RhY2sgPSBxdWV1ZUl0ZW1zW2kgKyAzXTsgLy8gRGVidWdnaW5nIGFzc2lzdGFuY2UKCiAgICAgICAgICAgIGludm9rZSh0YXJnZXQsIG1ldGhvZCwgYXJncywgb25FcnJvciwgZXJyb3JSZWNvcmRlZEZvclN0YWNrKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAodGhpcy5pbmRleCAhPT0gdGhpcy5fcXVldWVCZWluZ0ZsdXNoZWQubGVuZ3RoICYmIHRoaXMuZ2xvYmFsT3B0aW9ucy5tdXN0WWllbGQgJiYgdGhpcy5nbG9iYWxPcHRpb25zLm11c3RZaWVsZCgpKSB7CiAgICAgICAgICAgIHJldHVybiAxCiAgICAgICAgICAgIC8qIFBhdXNlICovCiAgICAgICAgICAgIDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChhZnRlciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgYWZ0ZXIoKTsKICAgICAgfQoKICAgICAgdGhpcy5fcXVldWVCZWluZ0ZsdXNoZWQubGVuZ3RoID0gMDsKICAgICAgdGhpcy5pbmRleCA9IDA7CgogICAgICBpZiAoc3luYyAhPT0gZmFsc2UgJiYgdGhpcy5fcXVldWUubGVuZ3RoID4gMCkgewogICAgICAgIC8vIGNoZWNrIGlmIG5ldyBpdGVtcyBoYXZlIGJlZW4gYWRkZWQKICAgICAgICB0aGlzLmZsdXNoKHRydWUpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5oYXNXb3JrID0gZnVuY3Rpb24gaGFzV29yaygpIHsKICAgICAgcmV0dXJuIHRoaXMuX3F1ZXVlQmVpbmdGbHVzaGVkLmxlbmd0aCA+IDAgfHwgdGhpcy5fcXVldWUubGVuZ3RoID4gMDsKICAgIH07CgogICAgX3Byb3RvLmNhbmNlbCA9IGZ1bmN0aW9uIGNhbmNlbChfcmVmKSB7CiAgICAgIHZhciB0YXJnZXQgPSBfcmVmLnRhcmdldCwKICAgICAgICAgIG1ldGhvZCA9IF9yZWYubWV0aG9kOwogICAgICB2YXIgcXVldWUgPSB0aGlzLl9xdWV1ZTsKICAgICAgdmFyIHRhcmdldFF1ZXVlTWFwID0gdGhpcy50YXJnZXRRdWV1ZXMuZ2V0KHRhcmdldCk7CgogICAgICBpZiAodGFyZ2V0UXVldWVNYXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHRhcmdldFF1ZXVlTWFwLmRlbGV0ZShtZXRob2QpOwogICAgICB9CgogICAgICB2YXIgaW5kZXggPSBmaW5kSXRlbSh0YXJnZXQsIG1ldGhvZCwgcXVldWUpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICBxdWV1ZS5zcGxpY2UoaW5kZXgsIFFVRVVFX0lURU1fTEVOR1RIKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfSAvLyBpZiBub3QgZm91bmQgaW4gY3VycmVudCBxdWV1ZQogICAgICAvLyBjb3VsZCBiZSBpbiB0aGUgcXVldWUgdGhhdCBpcyBiZWluZyBmbHVzaGVkCgoKICAgICAgcXVldWUgPSB0aGlzLl9xdWV1ZUJlaW5nRmx1c2hlZDsKICAgICAgaW5kZXggPSBmaW5kSXRlbSh0YXJnZXQsIG1ldGhvZCwgcXVldWUpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICBxdWV1ZVtpbmRleCArIDFdID0gbnVsbDsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfTsKCiAgICBfcHJvdG8ucHVzaCA9IGZ1bmN0aW9uIHB1c2godGFyZ2V0LCBtZXRob2QsIGFyZ3MsIHN0YWNrKSB7CiAgICAgIHRoaXMuX3F1ZXVlLnB1c2godGFyZ2V0LCBtZXRob2QsIGFyZ3MsIHN0YWNrKTsKCiAgICAgIHJldHVybiB7CiAgICAgICAgcXVldWU6IHRoaXMsCiAgICAgICAgdGFyZ2V0OiB0YXJnZXQsCiAgICAgICAgbWV0aG9kOiBtZXRob2QKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvLnB1c2hVbmlxdWUgPSBmdW5jdGlvbiBwdXNoVW5pcXVlKHRhcmdldCwgbWV0aG9kLCBhcmdzLCBzdGFjaykgewogICAgICB2YXIgbG9jYWxRdWV1ZU1hcCA9IHRoaXMudGFyZ2V0UXVldWVzLmdldCh0YXJnZXQpOwoKICAgICAgaWYgKGxvY2FsUXVldWVNYXAgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGxvY2FsUXVldWVNYXAgPSBuZXcgTWFwKCk7CiAgICAgICAgdGhpcy50YXJnZXRRdWV1ZXMuc2V0KHRhcmdldCwgbG9jYWxRdWV1ZU1hcCk7CiAgICAgIH0KCiAgICAgIHZhciBpbmRleCA9IGxvY2FsUXVldWVNYXAuZ2V0KG1ldGhvZCk7CgogICAgICBpZiAoaW5kZXggPT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhciBxdWV1ZUluZGV4ID0gdGhpcy5fcXVldWUucHVzaCh0YXJnZXQsIG1ldGhvZCwgYXJncywgc3RhY2spIC0gUVVFVUVfSVRFTV9MRU5HVEg7CiAgICAgICAgbG9jYWxRdWV1ZU1hcC5zZXQobWV0aG9kLCBxdWV1ZUluZGV4KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgcXVldWUgPSB0aGlzLl9xdWV1ZTsKICAgICAgICBxdWV1ZVtpbmRleCArIDJdID0gYXJnczsgLy8gcmVwbGFjZSBhcmdzCgogICAgICAgIHF1ZXVlW2luZGV4ICsgM10gPSBzdGFjazsgLy8gcmVwbGFjZSBzdGFjawogICAgICB9CgogICAgICByZXR1cm4gewogICAgICAgIHF1ZXVlOiB0aGlzLAogICAgICAgIHRhcmdldDogdGFyZ2V0LAogICAgICAgIG1ldGhvZDogbWV0aG9kCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90by5fZ2V0RGVidWdJbmZvID0gZnVuY3Rpb24gX2dldERlYnVnSW5mbyhkZWJ1Z0VuYWJsZWQpIHsKICAgICAgaWYgKGRlYnVnRW5hYmxlZCkgewogICAgICAgIHZhciBkZWJ1Z0luZm8gPSBnZXRRdWV1ZUl0ZW1zKHRoaXMuX3F1ZXVlLCBRVUVVRV9JVEVNX0xFTkdUSCk7CiAgICAgICAgcmV0dXJuIGRlYnVnSW5mbzsKICAgICAgfQoKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH07CgogICAgX3Byb3RvLmludm9rZSA9IGZ1bmN0aW9uIGludm9rZSh0YXJnZXQsIG1ldGhvZCwgYXJncwogICAgLyosIG9uRXJyb3IsIGVycm9yUmVjb3JkZWRGb3JTdGFjayAqLwogICAgKSB7CiAgICAgIGlmIChhcmdzID09PSB1bmRlZmluZWQpIHsKICAgICAgICBtZXRob2QuY2FsbCh0YXJnZXQpOwogICAgICB9IGVsc2UgewogICAgICAgIG1ldGhvZC5hcHBseSh0YXJnZXQsIGFyZ3MpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5pbnZva2VXaXRoT25FcnJvciA9IGZ1bmN0aW9uIGludm9rZVdpdGhPbkVycm9yKHRhcmdldCwgbWV0aG9kLCBhcmdzLCBvbkVycm9yLCBlcnJvclJlY29yZGVkRm9yU3RhY2spIHsKICAgICAgdHJ5IHsKICAgICAgICBpZiAoYXJncyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBtZXRob2QuY2FsbCh0YXJnZXQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBtZXRob2QuYXBwbHkodGFyZ2V0LCBhcmdzKTsKICAgICAgICB9CiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgb25FcnJvcihlcnJvciwgZXJyb3JSZWNvcmRlZEZvclN0YWNrKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gUXVldWU7CiAgfSgpOwoKICB2YXIgRGVmZXJyZWRBY3Rpb25RdWV1ZXMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBEZWZlcnJlZEFjdGlvblF1ZXVlcyhxdWV1ZU5hbWVzLCBvcHRpb25zKSB7CiAgICAgIGlmIChxdWV1ZU5hbWVzID09PSB2b2lkIDApIHsKICAgICAgICBxdWV1ZU5hbWVzID0gW107CiAgICAgIH0KCiAgICAgIHRoaXMucXVldWVzID0ge307CiAgICAgIHRoaXMucXVldWVOYW1lSW5kZXggPSAwOwogICAgICB0aGlzLnF1ZXVlTmFtZXMgPSBxdWV1ZU5hbWVzOwogICAgICBxdWV1ZU5hbWVzLnJlZHVjZShmdW5jdGlvbiAocXVldWVzLCBxdWV1ZU5hbWUpIHsKICAgICAgICBxdWV1ZXNbcXVldWVOYW1lXSA9IG5ldyBRdWV1ZShxdWV1ZU5hbWUsIG9wdGlvbnNbcXVldWVOYW1lXSwgb3B0aW9ucyk7CiAgICAgICAgcmV0dXJuIHF1ZXVlczsKICAgICAgfSwgdGhpcy5xdWV1ZXMpOwogICAgfQogICAgLyoqCiAgICAgKiBAbWV0aG9kIHNjaGVkdWxlCiAgICAgKiBAcGFyYW0ge1N0cmluZ30gcXVldWVOYW1lCiAgICAgKiBAcGFyYW0ge0FueX0gdGFyZ2V0CiAgICAgKiBAcGFyYW0ge0FueX0gbWV0aG9kCiAgICAgKiBAcGFyYW0ge0FueX0gYXJncwogICAgICogQHBhcmFtIHtCb29sZWFufSBvbmNlRmxhZwogICAgICogQHBhcmFtIHtBbnl9IHN0YWNrCiAgICAgKiBAcmV0dXJuIHF1ZXVlCiAgICAgKi8KCgogICAgdmFyIF9wcm90bzIgPSBEZWZlcnJlZEFjdGlvblF1ZXVlcy5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5zY2hlZHVsZSA9IGZ1bmN0aW9uIHNjaGVkdWxlKHF1ZXVlTmFtZSwgdGFyZ2V0LCBtZXRob2QsIGFyZ3MsIG9uY2VGbGFnLCBzdGFjaykgewogICAgICB2YXIgcXVldWVzID0gdGhpcy5xdWV1ZXM7CiAgICAgIHZhciBxdWV1ZSA9IHF1ZXVlc1txdWV1ZU5hbWVdOwoKICAgICAgaWYgKHF1ZXVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIllvdSBhdHRlbXB0ZWQgdG8gc2NoZWR1bGUgYW4gYWN0aW9uIGluIGEgcXVldWUgKCIgKyBxdWV1ZU5hbWUgKyAiKSB0aGF0IGRvZXNuJ3QgZXhpc3QiKTsKICAgICAgfQoKICAgICAgaWYgKG1ldGhvZCA9PT0gdW5kZWZpbmVkIHx8IG1ldGhvZCA9PT0gbnVsbCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiWW91IGF0dGVtcHRlZCB0byBzY2hlZHVsZSBhbiBhY3Rpb24gaW4gYSBxdWV1ZSAoIiArIHF1ZXVlTmFtZSArICIpIGZvciBhIG1ldGhvZCB0aGF0IGRvZXNuJ3QgZXhpc3QiKTsKICAgICAgfQoKICAgICAgdGhpcy5xdWV1ZU5hbWVJbmRleCA9IDA7CgogICAgICBpZiAob25jZUZsYWcpIHsKICAgICAgICByZXR1cm4gcXVldWUucHVzaFVuaXF1ZSh0YXJnZXQsIG1ldGhvZCwgYXJncywgc3RhY2spOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBxdWV1ZS5wdXNoKHRhcmdldCwgbWV0aG9kLCBhcmdzLCBzdGFjayk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogRGVmZXJyZWRBY3Rpb25RdWV1ZXMuZmx1c2goKSBjYWxscyBRdWV1ZS5mbHVzaCgpCiAgICAgKgogICAgICogQG1ldGhvZCBmbHVzaAogICAgICogQHBhcmFtIHtCb29sZWFufSBmcm9tQXV0b3J1bgogICAgICovCiAgICA7CgogICAgX3Byb3RvMi5mbHVzaCA9IGZ1bmN0aW9uIGZsdXNoKGZyb21BdXRvcnVuKSB7CiAgICAgIGlmIChmcm9tQXV0b3J1biA9PT0gdm9pZCAwKSB7CiAgICAgICAgZnJvbUF1dG9ydW4gPSBmYWxzZTsKICAgICAgfQoKICAgICAgdmFyIHF1ZXVlOwogICAgICB2YXIgcXVldWVOYW1lOwogICAgICB2YXIgbnVtYmVyT2ZRdWV1ZXMgPSB0aGlzLnF1ZXVlTmFtZXMubGVuZ3RoOwoKICAgICAgd2hpbGUgKHRoaXMucXVldWVOYW1lSW5kZXggPCBudW1iZXJPZlF1ZXVlcykgewogICAgICAgIHF1ZXVlTmFtZSA9IHRoaXMucXVldWVOYW1lc1t0aGlzLnF1ZXVlTmFtZUluZGV4XTsKICAgICAgICBxdWV1ZSA9IHRoaXMucXVldWVzW3F1ZXVlTmFtZV07CgogICAgICAgIGlmIChxdWV1ZS5oYXNXb3JrKCkgPT09IGZhbHNlKSB7CiAgICAgICAgICB0aGlzLnF1ZXVlTmFtZUluZGV4Kys7CgogICAgICAgICAgaWYgKGZyb21BdXRvcnVuICYmIHRoaXMucXVldWVOYW1lSW5kZXggPCBudW1iZXJPZlF1ZXVlcykgewogICAgICAgICAgICByZXR1cm4gMQogICAgICAgICAgICAvKiBQYXVzZSAqLwogICAgICAgICAgICA7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChxdWV1ZS5mbHVzaChmYWxzZQogICAgICAgICAgLyogYXN5bmMgKi8KICAgICAgICAgICkgPT09IDEKICAgICAgICAgIC8qIFBhdXNlICovCiAgICAgICAgICApIHsKICAgICAgICAgICAgICByZXR1cm4gMQogICAgICAgICAgICAgIC8qIFBhdXNlICovCiAgICAgICAgICAgICAgOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIFJldHVybnMgZGVidWcgaW5mb3JtYXRpb24gZm9yIHRoZSBjdXJyZW50IHF1ZXVlcy4KICAgICAqCiAgICAgKiBAbWV0aG9kIF9nZXREZWJ1Z0luZm8KICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gZGVidWdFbmFibGVkCiAgICAgKiBAcmV0dXJucyB7SURlYnVnSW5mbyB8IHVuZGVmaW5lZH0KICAgICAqLwogICAgOwoKICAgIF9wcm90bzIuX2dldERlYnVnSW5mbyA9IGZ1bmN0aW9uIF9nZXREZWJ1Z0luZm8oZGVidWdFbmFibGVkKSB7CiAgICAgIGlmIChkZWJ1Z0VuYWJsZWQpIHsKICAgICAgICB2YXIgZGVidWdJbmZvID0ge307CiAgICAgICAgdmFyIHF1ZXVlOwogICAgICAgIHZhciBxdWV1ZU5hbWU7CiAgICAgICAgdmFyIG51bWJlck9mUXVldWVzID0gdGhpcy5xdWV1ZU5hbWVzLmxlbmd0aDsKICAgICAgICB2YXIgaSA9IDA7CgogICAgICAgIHdoaWxlIChpIDwgbnVtYmVyT2ZRdWV1ZXMpIHsKICAgICAgICAgIHF1ZXVlTmFtZSA9IHRoaXMucXVldWVOYW1lc1tpXTsKICAgICAgICAgIHF1ZXVlID0gdGhpcy5xdWV1ZXNbcXVldWVOYW1lXTsKICAgICAgICAgIGRlYnVnSW5mb1txdWV1ZU5hbWVdID0gcXVldWUuX2dldERlYnVnSW5mbyhkZWJ1Z0VuYWJsZWQpOwogICAgICAgICAgaSsrOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGRlYnVnSW5mbzsKICAgICAgfQoKICAgICAgcmV0dXJuOwogICAgfTsKCiAgICByZXR1cm4gRGVmZXJyZWRBY3Rpb25RdWV1ZXM7CiAgfSgpOwoKICBmdW5jdGlvbiBpdGVyYXRvckRyYWluKGZuKSB7CiAgICB2YXIgaXRlcmF0b3IgPSBmbigpOwogICAgdmFyIHJlc3VsdCA9IGl0ZXJhdG9yLm5leHQoKTsKCiAgICB3aGlsZSAocmVzdWx0LmRvbmUgPT09IGZhbHNlKSB7CiAgICAgIHJlc3VsdC52YWx1ZSgpOwogICAgICByZXN1bHQgPSBpdGVyYXRvci5uZXh0KCk7CiAgICB9CiAgfQoKICB2YXIgbm9vcCA9IGZ1bmN0aW9uIG5vb3AoKSB7fTsKCiAgdmFyIERJU0FCTEVfU0NIRURVTEUgPSBPYmplY3QuZnJlZXplKFtdKTsKCiAgZnVuY3Rpb24gcGFyc2VBcmdzKCkgewogICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7CiAgICB2YXIgYXJnczsKICAgIHZhciBtZXRob2Q7CiAgICB2YXIgdGFyZ2V0OwoKICAgIGlmIChsZW5ndGggPT09IDApIHt9IGVsc2UgaWYgKGxlbmd0aCA9PT0gMSkgewogICAgICB0YXJnZXQgPSBudWxsOwogICAgICBtZXRob2QgPSBhcmd1bWVudHNbMF07CiAgICB9IGVsc2UgewogICAgICB2YXIgYXJnc0luZGV4ID0gMjsKICAgICAgdmFyIG1ldGhvZE9yVGFyZ2V0ID0gYXJndW1lbnRzWzBdOwogICAgICB2YXIgbWV0aG9kT3JBcmdzID0gYXJndW1lbnRzWzFdOwogICAgICB2YXIgdHlwZSA9IHR5cGVvZiBtZXRob2RPckFyZ3M7CgogICAgICBpZiAodHlwZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIHRhcmdldCA9IG1ldGhvZE9yVGFyZ2V0OwogICAgICAgIG1ldGhvZCA9IG1ldGhvZE9yQXJnczsKICAgICAgfSBlbHNlIGlmIChtZXRob2RPclRhcmdldCAhPT0gbnVsbCAmJiB0eXBlID09PSAnc3RyaW5nJyAmJiBtZXRob2RPckFyZ3MgaW4gbWV0aG9kT3JUYXJnZXQpIHsKICAgICAgICB0YXJnZXQgPSBtZXRob2RPclRhcmdldDsKICAgICAgICBtZXRob2QgPSB0YXJnZXRbbWV0aG9kT3JBcmdzXTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbWV0aG9kT3JUYXJnZXQgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICBhcmdzSW5kZXggPSAxOwogICAgICAgIHRhcmdldCA9IG51bGw7CiAgICAgICAgbWV0aG9kID0gbWV0aG9kT3JUYXJnZXQ7CiAgICAgIH0KCiAgICAgIGlmIChsZW5ndGggPiBhcmdzSW5kZXgpIHsKICAgICAgICB2YXIgbGVuID0gbGVuZ3RoIC0gYXJnc0luZGV4OwogICAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpICsgYXJnc0luZGV4XTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gW3RhcmdldCwgbWV0aG9kLCBhcmdzXTsKICB9CgogIGZ1bmN0aW9uIHBhcnNlVGltZXJBcmdzKCkgewogICAgdmFyIF9wYXJzZUFyZ3MgPSBwYXJzZUFyZ3MuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpLAogICAgICAgIHRhcmdldCA9IF9wYXJzZUFyZ3NbMF0sCiAgICAgICAgbWV0aG9kID0gX3BhcnNlQXJnc1sxXSwKICAgICAgICBhcmdzID0gX3BhcnNlQXJnc1syXTsKCiAgICB2YXIgd2FpdCA9IDA7CiAgICB2YXIgbGVuZ3RoID0gYXJncyAhPT0gdW5kZWZpbmVkID8gYXJncy5sZW5ndGggOiAwOwoKICAgIGlmIChsZW5ndGggPiAwKSB7CiAgICAgIHZhciBsYXN0ID0gYXJnc1tsZW5ndGggLSAxXTsKCiAgICAgIGlmIChpc0NvZXJjYWJsZU51bWJlcihsYXN0KSkgewogICAgICAgIHdhaXQgPSBwYXJzZUludChhcmdzLnBvcCgpLCAxMCk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gW3RhcmdldCwgbWV0aG9kLCBhcmdzLCB3YWl0XTsKICB9CgogIGZ1bmN0aW9uIHBhcnNlRGVib3VuY2VBcmdzKCkgewogICAgdmFyIHRhcmdldDsKICAgIHZhciBtZXRob2Q7CiAgICB2YXIgaXNJbW1lZGlhdGU7CiAgICB2YXIgYXJnczsKICAgIHZhciB3YWl0OwoKICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyKSB7CiAgICAgIG1ldGhvZCA9IGFyZ3VtZW50c1swXTsKICAgICAgd2FpdCA9IGFyZ3VtZW50c1sxXTsKICAgICAgdGFyZ2V0ID0gbnVsbDsKICAgIH0gZWxzZSB7CiAgICAgIHZhciBfcGFyc2VBcmdzMiA9IHBhcnNlQXJncy5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cyk7CgogICAgICB0YXJnZXQgPSBfcGFyc2VBcmdzMlswXTsKICAgICAgbWV0aG9kID0gX3BhcnNlQXJnczJbMV07CiAgICAgIGFyZ3MgPSBfcGFyc2VBcmdzMlsyXTsKCiAgICAgIGlmIChhcmdzID09PSB1bmRlZmluZWQpIHsKICAgICAgICB3YWl0ID0gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICB3YWl0ID0gYXJncy5wb3AoKTsKCiAgICAgICAgaWYgKCFpc0NvZXJjYWJsZU51bWJlcih3YWl0KSkgewogICAgICAgICAgaXNJbW1lZGlhdGUgPSB3YWl0ID09PSB0cnVlOwogICAgICAgICAgd2FpdCA9IGFyZ3MucG9wKCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgd2FpdCA9IHBhcnNlSW50KHdhaXQsIDEwKTsKICAgIHJldHVybiBbdGFyZ2V0LCBtZXRob2QsIGFyZ3MsIHdhaXQsIGlzSW1tZWRpYXRlXTsKICB9CgogIHZhciBVVUlEID0gMDsKICB2YXIgYmVnaW5Db3VudCA9IDA7CiAgdmFyIGVuZENvdW50ID0gMDsKICB2YXIgYmVnaW5FdmVudENvdW50ID0gMDsKICB2YXIgZW5kRXZlbnRDb3VudCA9IDA7CiAgdmFyIHJ1bkNvdW50ID0gMDsKICB2YXIgam9pbkNvdW50ID0gMDsKICB2YXIgZGVmZXJDb3VudCA9IDA7CiAgdmFyIHNjaGVkdWxlQ291bnQgPSAwOwogIHZhciBzY2hlZHVsZUl0ZXJhYmxlQ291bnQgPSAwOwogIHZhciBkZWZlck9uY2VDb3VudCA9IDA7CiAgdmFyIHNjaGVkdWxlT25jZUNvdW50ID0gMDsKICB2YXIgc2V0VGltZW91dENvdW50ID0gMDsKICB2YXIgbGF0ZXJDb3VudCA9IDA7CiAgdmFyIHRocm90dGxlQ291bnQgPSAwOwogIHZhciBkZWJvdW5jZUNvdW50ID0gMDsKICB2YXIgY2FuY2VsVGltZXJzQ291bnQgPSAwOwogIHZhciBjYW5jZWxDb3VudCA9IDA7CiAgdmFyIGF1dG9ydW5zQ3JlYXRlZENvdW50ID0gMDsKICB2YXIgYXV0b3J1bnNDb21wbGV0ZWRDb3VudCA9IDA7CiAgdmFyIGRlZmVycmVkQWN0aW9uUXVldWVzQ3JlYXRlZENvdW50ID0gMDsKICB2YXIgbmVzdGVkRGVmZXJyZWRBY3Rpb25RdWV1ZXNDcmVhdGVkID0gMDsKCiAgdmFyIEJhY2tidXJuZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBCYWNrYnVybmVyKHF1ZXVlTmFtZXMsIG9wdGlvbnMpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHRoaXMuREVCVUcgPSBmYWxzZTsKICAgICAgdGhpcy5jdXJyZW50SW5zdGFuY2UgPSBudWxsOwogICAgICB0aGlzLmluc3RhbmNlU3RhY2sgPSBbXTsKICAgICAgdGhpcy5fZXZlbnRDYWxsYmFja3MgPSB7CiAgICAgICAgZW5kOiBbXSwKICAgICAgICBiZWdpbjogW10KICAgICAgfTsKICAgICAgdGhpcy5fdGltZXJUaW1lb3V0SWQgPSBudWxsOwogICAgICB0aGlzLl90aW1lcnMgPSBbXTsKICAgICAgdGhpcy5fYXV0b3J1biA9IGZhbHNlOwogICAgICB0aGlzLl9hdXRvcnVuU3RhY2sgPSBudWxsOwogICAgICB0aGlzLnF1ZXVlTmFtZXMgPSBxdWV1ZU5hbWVzOwogICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zIHx8IHt9OwoKICAgICAgaWYgKHR5cGVvZiB0aGlzLm9wdGlvbnMuZGVmYXVsdFF1ZXVlID09PSAnc3RyaW5nJykgewogICAgICAgIHRoaXMuX2RlZmF1bHRRdWV1ZSA9IHRoaXMub3B0aW9ucy5kZWZhdWx0UXVldWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fZGVmYXVsdFF1ZXVlID0gdGhpcy5xdWV1ZU5hbWVzWzBdOwogICAgICB9CgogICAgICB0aGlzLl9vbkJlZ2luID0gdGhpcy5vcHRpb25zLm9uQmVnaW4gfHwgbm9vcDsKICAgICAgdGhpcy5fb25FbmQgPSB0aGlzLm9wdGlvbnMub25FbmQgfHwgbm9vcDsKICAgICAgdGhpcy5fYm91bmRSdW5FeHBpcmVkVGltZXJzID0gdGhpcy5fcnVuRXhwaXJlZFRpbWVycy5iaW5kKHRoaXMpOwoKICAgICAgdGhpcy5fYm91bmRBdXRvcnVuRW5kID0gZnVuY3Rpb24gKCkgewogICAgICAgIGF1dG9ydW5zQ29tcGxldGVkQ291bnQrKzsgLy8gaWYgdGhlIGF1dG9ydW4gd2FzIGFscmVhZHkgZmx1c2hlZCwgZG8gbm90aGluZwoKICAgICAgICBpZiAoX3RoaXMuX2F1dG9ydW4gPT09IGZhbHNlKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBfdGhpcy5fYXV0b3J1biA9IGZhbHNlOwogICAgICAgIF90aGlzLl9hdXRvcnVuU3RhY2sgPSBudWxsOwoKICAgICAgICBfdGhpcy5fZW5kKHRydWUKICAgICAgICAvKiBmcm9tQXV0b3J1biAqLwogICAgICAgICk7CiAgICAgIH07CgogICAgICB2YXIgYnVpbGRlciA9IHRoaXMub3B0aW9ucy5fYnVpbGRQbGF0Zm9ybSB8fCBidWlsZFBsYXRmb3JtOwogICAgICB0aGlzLl9wbGF0Zm9ybSA9IGJ1aWxkZXIodGhpcy5fYm91bmRBdXRvcnVuRW5kKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMyA9IEJhY2tidXJuZXIucHJvdG90eXBlOwoKICAgIC8qCiAgICAgIEBtZXRob2QgYmVnaW4KICAgICAgQHJldHVybiBpbnN0YW50aWF0ZWQgY2xhc3MgRGVmZXJyZWRBY3Rpb25RdWV1ZXMKICAgICovCiAgICBfcHJvdG8zLmJlZ2luID0gZnVuY3Rpb24gYmVnaW4oKSB7CiAgICAgIGJlZ2luQ291bnQrKzsKICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7CiAgICAgIHZhciBwcmV2aW91c0luc3RhbmNlID0gdGhpcy5jdXJyZW50SW5zdGFuY2U7CiAgICAgIHZhciBjdXJyZW50OwoKICAgICAgaWYgKHRoaXMuX2F1dG9ydW4gIT09IGZhbHNlKSB7CiAgICAgICAgY3VycmVudCA9IHByZXZpb3VzSW5zdGFuY2U7CgogICAgICAgIHRoaXMuX2NhbmNlbEF1dG9ydW4oKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAocHJldmlvdXNJbnN0YW5jZSAhPT0gbnVsbCkgewogICAgICAgICAgbmVzdGVkRGVmZXJyZWRBY3Rpb25RdWV1ZXNDcmVhdGVkKys7CiAgICAgICAgICB0aGlzLmluc3RhbmNlU3RhY2sucHVzaChwcmV2aW91c0luc3RhbmNlKTsKICAgICAgICB9CgogICAgICAgIGRlZmVycmVkQWN0aW9uUXVldWVzQ3JlYXRlZENvdW50Kys7CiAgICAgICAgY3VycmVudCA9IHRoaXMuY3VycmVudEluc3RhbmNlID0gbmV3IERlZmVycmVkQWN0aW9uUXVldWVzKHRoaXMucXVldWVOYW1lcywgb3B0aW9ucyk7CiAgICAgICAgYmVnaW5FdmVudENvdW50Kys7CgogICAgICAgIHRoaXMuX3RyaWdnZXIoJ2JlZ2luJywgY3VycmVudCwgcHJldmlvdXNJbnN0YW5jZSk7CiAgICAgIH0KCiAgICAgIHRoaXMuX29uQmVnaW4oY3VycmVudCwgcHJldmlvdXNJbnN0YW5jZSk7CgogICAgICByZXR1cm4gY3VycmVudDsKICAgIH07CgogICAgX3Byb3RvMy5lbmQgPSBmdW5jdGlvbiBlbmQoKSB7CiAgICAgIGVuZENvdW50Kys7CgogICAgICB0aGlzLl9lbmQoZmFsc2UpOwogICAgfTsKCiAgICBfcHJvdG8zLm9uID0gZnVuY3Rpb24gb24oZXZlbnROYW1lLCBjYWxsYmFjaykgewogICAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2FsbGJhY2sgbXVzdCBiZSBhIGZ1bmN0aW9uIik7CiAgICAgIH0KCiAgICAgIHZhciBjYWxsYmFja3MgPSB0aGlzLl9ldmVudENhbGxiYWNrc1tldmVudE5hbWVdOwoKICAgICAgaWYgKGNhbGxiYWNrcyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgY2FsbGJhY2tzLnB1c2goY2FsbGJhY2spOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIkNhbm5vdCBvbigpIGV2ZW50ICIgKyBldmVudE5hbWUgKyAiIGJlY2F1c2UgaXQgZG9lcyBub3QgZXhpc3QiKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zLm9mZiA9IGZ1bmN0aW9uIG9mZihldmVudE5hbWUsIGNhbGxiYWNrKSB7CiAgICAgIHZhciBjYWxsYmFja3MgPSB0aGlzLl9ldmVudENhbGxiYWNrc1tldmVudE5hbWVdOwoKICAgICAgaWYgKCFldmVudE5hbWUgfHwgY2FsbGJhY2tzID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3Qgb2ZmKCkgZXZlbnQgIiArIGV2ZW50TmFtZSArICIgYmVjYXVzZSBpdCBkb2VzIG5vdCBleGlzdCIpOwogICAgICB9CgogICAgICB2YXIgY2FsbGJhY2tGb3VuZCA9IGZhbHNlOwoKICAgICAgaWYgKGNhbGxiYWNrKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjYWxsYmFja3MubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGlmIChjYWxsYmFja3NbaV0gPT09IGNhbGxiYWNrKSB7CiAgICAgICAgICAgIGNhbGxiYWNrRm91bmQgPSB0cnVlOwogICAgICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpOwogICAgICAgICAgICBpLS07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoIWNhbGxiYWNrRm91bmQpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3Qgb2ZmKCkgY2FsbGJhY2sgdGhhdCBkb2VzIG5vdCBleGlzdCIpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzMucnVuID0gZnVuY3Rpb24gcnVuKCkgewogICAgICBydW5Db3VudCsrOwoKICAgICAgdmFyIF9wYXJzZUFyZ3MzID0gcGFyc2VBcmdzLmFwcGx5KHZvaWQgMCwgYXJndW1lbnRzKSwKICAgICAgICAgIHRhcmdldCA9IF9wYXJzZUFyZ3MzWzBdLAogICAgICAgICAgbWV0aG9kID0gX3BhcnNlQXJnczNbMV0sCiAgICAgICAgICBhcmdzID0gX3BhcnNlQXJnczNbMl07CgogICAgICByZXR1cm4gdGhpcy5fcnVuKHRhcmdldCwgbWV0aG9kLCBhcmdzKTsKICAgIH07CgogICAgX3Byb3RvMy5qb2luID0gZnVuY3Rpb24gam9pbigpIHsKICAgICAgam9pbkNvdW50Kys7CgogICAgICB2YXIgX3BhcnNlQXJnczQgPSBwYXJzZUFyZ3MuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpLAogICAgICAgICAgdGFyZ2V0ID0gX3BhcnNlQXJnczRbMF0sCiAgICAgICAgICBtZXRob2QgPSBfcGFyc2VBcmdzNFsxXSwKICAgICAgICAgIGFyZ3MgPSBfcGFyc2VBcmdzNFsyXTsKCiAgICAgIHJldHVybiB0aGlzLl9qb2luKHRhcmdldCwgbWV0aG9kLCBhcmdzKTsKICAgIH0KICAgIC8qKgogICAgICogQGRlcHJlY2F0ZWQgcGxlYXNlIHVzZSBzY2hlZHVsZSBpbnN0ZWFkLgogICAgICovCiAgICA7CgogICAgX3Byb3RvMy5kZWZlciA9IGZ1bmN0aW9uIGRlZmVyKHF1ZXVlTmFtZSwgdGFyZ2V0LCBtZXRob2QpIHsKICAgICAgZGVmZXJDb3VudCsrOwoKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDMgPyBfbGVuIC0gMyA6IDApLCBfa2V5ID0gMzsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleSAtIDNdID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5zY2hlZHVsZS5hcHBseSh0aGlzLCBbcXVldWVOYW1lLCB0YXJnZXQsIG1ldGhvZF0uY29uY2F0KGFyZ3MpKTsKICAgIH07CgogICAgX3Byb3RvMy5zY2hlZHVsZSA9IGZ1bmN0aW9uIHNjaGVkdWxlKHF1ZXVlTmFtZSkgewogICAgICBzY2hlZHVsZUNvdW50Kys7CgogICAgICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIF9hcmdzID0gbmV3IEFycmF5KF9sZW4yID4gMSA/IF9sZW4yIC0gMSA6IDApLCBfa2V5MiA9IDE7IF9rZXkyIDwgX2xlbjI7IF9rZXkyKyspIHsKICAgICAgICBfYXJnc1tfa2V5MiAtIDFdID0gYXJndW1lbnRzW19rZXkyXTsKICAgICAgfQoKICAgICAgdmFyIF9wYXJzZUFyZ3M1ID0gcGFyc2VBcmdzLmFwcGx5KHZvaWQgMCwgX2FyZ3MpLAogICAgICAgICAgdGFyZ2V0ID0gX3BhcnNlQXJnczVbMF0sCiAgICAgICAgICBtZXRob2QgPSBfcGFyc2VBcmdzNVsxXSwKICAgICAgICAgIGFyZ3MgPSBfcGFyc2VBcmdzNVsyXTsKCiAgICAgIHZhciBzdGFjayA9IHRoaXMuREVCVUcgPyBuZXcgRXJyb3IoKSA6IHVuZGVmaW5lZDsKICAgICAgcmV0dXJuIHRoaXMuX2Vuc3VyZUluc3RhbmNlKCkuc2NoZWR1bGUocXVldWVOYW1lLCB0YXJnZXQsIG1ldGhvZCwgYXJncywgZmFsc2UsIHN0YWNrKTsKICAgIH0KICAgIC8qCiAgICAgIERlZmVyIHRoZSBwYXNzZWQgaXRlcmFibGUgb2YgZnVuY3Rpb25zIHRvIHJ1biBpbnNpZGUgdGhlIHNwZWNpZmllZCBxdWV1ZS4KICAgICAgICAgQG1ldGhvZCBzY2hlZHVsZUl0ZXJhYmxlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBxdWV1ZU5hbWUKICAgICAgQHBhcmFtIHtJdGVyYWJsZX0gYW4gaXRlcmFibGUgb2YgZnVuY3Rpb25zIHRvIGV4ZWN1dGUKICAgICAgQHJldHVybiBtZXRob2QgcmVzdWx0CiAgICAqLwogICAgOwoKICAgIF9wcm90bzMuc2NoZWR1bGVJdGVyYWJsZSA9IGZ1bmN0aW9uIHNjaGVkdWxlSXRlcmFibGUocXVldWVOYW1lLCBpdGVyYWJsZSkgewogICAgICBzY2hlZHVsZUl0ZXJhYmxlQ291bnQrKzsKICAgICAgdmFyIHN0YWNrID0gdGhpcy5ERUJVRyA/IG5ldyBFcnJvcigpIDogdW5kZWZpbmVkOwogICAgICByZXR1cm4gdGhpcy5fZW5zdXJlSW5zdGFuY2UoKS5zY2hlZHVsZShxdWV1ZU5hbWUsIG51bGwsIGl0ZXJhdG9yRHJhaW4sIFtpdGVyYWJsZV0sIGZhbHNlLCBzdGFjayk7CiAgICB9CiAgICAvKioKICAgICAqIEBkZXByZWNhdGVkIHBsZWFzZSB1c2Ugc2NoZWR1bGVPbmNlIGluc3RlYWQuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zLmRlZmVyT25jZSA9IGZ1bmN0aW9uIGRlZmVyT25jZShxdWV1ZU5hbWUsIHRhcmdldCwgbWV0aG9kKSB7CiAgICAgIGRlZmVyT25jZUNvdW50Kys7CgogICAgICBmb3IgKHZhciBfbGVuMyA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjMgPiAzID8gX2xlbjMgLSAzIDogMCksIF9rZXkzID0gMzsgX2tleTMgPCBfbGVuMzsgX2tleTMrKykgewogICAgICAgIGFyZ3NbX2tleTMgLSAzXSA9IGFyZ3VtZW50c1tfa2V5M107CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLnNjaGVkdWxlT25jZS5hcHBseSh0aGlzLCBbcXVldWVOYW1lLCB0YXJnZXQsIG1ldGhvZF0uY29uY2F0KGFyZ3MpKTsKICAgIH07CgogICAgX3Byb3RvMy5zY2hlZHVsZU9uY2UgPSBmdW5jdGlvbiBzY2hlZHVsZU9uY2UocXVldWVOYW1lKSB7CiAgICAgIHNjaGVkdWxlT25jZUNvdW50Kys7CgogICAgICBmb3IgKHZhciBfbGVuNCA9IGFyZ3VtZW50cy5sZW5ndGgsIF9hcmdzID0gbmV3IEFycmF5KF9sZW40ID4gMSA/IF9sZW40IC0gMSA6IDApLCBfa2V5NCA9IDE7IF9rZXk0IDwgX2xlbjQ7IF9rZXk0KyspIHsKICAgICAgICBfYXJnc1tfa2V5NCAtIDFdID0gYXJndW1lbnRzW19rZXk0XTsKICAgICAgfQoKICAgICAgdmFyIF9wYXJzZUFyZ3M2ID0gcGFyc2VBcmdzLmFwcGx5KHZvaWQgMCwgX2FyZ3MpLAogICAgICAgICAgdGFyZ2V0ID0gX3BhcnNlQXJnczZbMF0sCiAgICAgICAgICBtZXRob2QgPSBfcGFyc2VBcmdzNlsxXSwKICAgICAgICAgIGFyZ3MgPSBfcGFyc2VBcmdzNlsyXTsKCiAgICAgIHZhciBzdGFjayA9IHRoaXMuREVCVUcgPyBuZXcgRXJyb3IoKSA6IHVuZGVmaW5lZDsKICAgICAgcmV0dXJuIHRoaXMuX2Vuc3VyZUluc3RhbmNlKCkuc2NoZWR1bGUocXVldWVOYW1lLCB0YXJnZXQsIG1ldGhvZCwgYXJncywgdHJ1ZSwgc3RhY2spOwogICAgfTsKCiAgICBfcHJvdG8zLnNldFRpbWVvdXQgPSBmdW5jdGlvbiBzZXRUaW1lb3V0KCkgewogICAgICBzZXRUaW1lb3V0Q291bnQrKzsKICAgICAgcmV0dXJuIHRoaXMubGF0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH07CgogICAgX3Byb3RvMy5sYXRlciA9IGZ1bmN0aW9uIGxhdGVyKCkgewogICAgICBsYXRlckNvdW50Kys7CgogICAgICB2YXIgX3BhcnNlVGltZXJBcmdzID0gcGFyc2VUaW1lckFyZ3MuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpLAogICAgICAgICAgdGFyZ2V0ID0gX3BhcnNlVGltZXJBcmdzWzBdLAogICAgICAgICAgbWV0aG9kID0gX3BhcnNlVGltZXJBcmdzWzFdLAogICAgICAgICAgYXJncyA9IF9wYXJzZVRpbWVyQXJnc1syXSwKICAgICAgICAgIHdhaXQgPSBfcGFyc2VUaW1lckFyZ3NbM107CgogICAgICByZXR1cm4gdGhpcy5fbGF0ZXIodGFyZ2V0LCBtZXRob2QsIGFyZ3MsIHdhaXQpOwogICAgfTsKCiAgICBfcHJvdG8zLnRocm90dGxlID0gZnVuY3Rpb24gdGhyb3R0bGUoKSB7CiAgICAgIHRocm90dGxlQ291bnQrKzsKCiAgICAgIHZhciBfcGFyc2VEZWJvdW5jZUFyZ3MgPSBwYXJzZURlYm91bmNlQXJncy5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cyksCiAgICAgICAgICB0YXJnZXQgPSBfcGFyc2VEZWJvdW5jZUFyZ3NbMF0sCiAgICAgICAgICBtZXRob2QgPSBfcGFyc2VEZWJvdW5jZUFyZ3NbMV0sCiAgICAgICAgICBhcmdzID0gX3BhcnNlRGVib3VuY2VBcmdzWzJdLAogICAgICAgICAgd2FpdCA9IF9wYXJzZURlYm91bmNlQXJnc1szXSwKICAgICAgICAgIF9wYXJzZURlYm91bmNlQXJncyQgPSBfcGFyc2VEZWJvdW5jZUFyZ3NbNF0sCiAgICAgICAgICBpc0ltbWVkaWF0ZSA9IF9wYXJzZURlYm91bmNlQXJncyQgPT09IHZvaWQgMCA/IHRydWUgOiBfcGFyc2VEZWJvdW5jZUFyZ3MkOwoKICAgICAgdmFyIGluZGV4ID0gZmluZFRpbWVySXRlbSh0YXJnZXQsIG1ldGhvZCwgdGhpcy5fdGltZXJzKTsKICAgICAgdmFyIHRpbWVySWQ7CgogICAgICBpZiAoaW5kZXggPT09IC0xKSB7CiAgICAgICAgdGltZXJJZCA9IHRoaXMuX2xhdGVyKHRhcmdldCwgbWV0aG9kLCBpc0ltbWVkaWF0ZSA/IERJU0FCTEVfU0NIRURVTEUgOiBhcmdzLCB3YWl0KTsKCiAgICAgICAgaWYgKGlzSW1tZWRpYXRlKSB7CiAgICAgICAgICB0aGlzLl9qb2luKHRhcmdldCwgbWV0aG9kLCBhcmdzKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGltZXJJZCA9IHRoaXMuX3RpbWVyc1tpbmRleCArIDFdOwogICAgICAgIHZhciBhcmdJbmRleCA9IGluZGV4ICsgNDsKCiAgICAgICAgaWYgKHRoaXMuX3RpbWVyc1thcmdJbmRleF0gIT09IERJU0FCTEVfU0NIRURVTEUpIHsKICAgICAgICAgIHRoaXMuX3RpbWVyc1thcmdJbmRleF0gPSBhcmdzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHRpbWVySWQ7CiAgICB9OwoKICAgIF9wcm90bzMuZGVib3VuY2UgPSBmdW5jdGlvbiBkZWJvdW5jZSgpIHsKICAgICAgZGVib3VuY2VDb3VudCsrOwoKICAgICAgdmFyIF9wYXJzZURlYm91bmNlQXJnczIgPSBwYXJzZURlYm91bmNlQXJncy5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cyksCiAgICAgICAgICB0YXJnZXQgPSBfcGFyc2VEZWJvdW5jZUFyZ3MyWzBdLAogICAgICAgICAgbWV0aG9kID0gX3BhcnNlRGVib3VuY2VBcmdzMlsxXSwKICAgICAgICAgIGFyZ3MgPSBfcGFyc2VEZWJvdW5jZUFyZ3MyWzJdLAogICAgICAgICAgd2FpdCA9IF9wYXJzZURlYm91bmNlQXJnczJbM10sCiAgICAgICAgICBfcGFyc2VEZWJvdW5jZUFyZ3MyJCA9IF9wYXJzZURlYm91bmNlQXJnczJbNF0sCiAgICAgICAgICBpc0ltbWVkaWF0ZSA9IF9wYXJzZURlYm91bmNlQXJnczIkID09PSB2b2lkIDAgPyBmYWxzZSA6IF9wYXJzZURlYm91bmNlQXJnczIkOwoKICAgICAgdmFyIF90aW1lcnMgPSB0aGlzLl90aW1lcnM7CiAgICAgIHZhciBpbmRleCA9IGZpbmRUaW1lckl0ZW0odGFyZ2V0LCBtZXRob2QsIF90aW1lcnMpOwogICAgICB2YXIgdGltZXJJZDsKCiAgICAgIGlmIChpbmRleCA9PT0gLTEpIHsKICAgICAgICB0aW1lcklkID0gdGhpcy5fbGF0ZXIodGFyZ2V0LCBtZXRob2QsIGlzSW1tZWRpYXRlID8gRElTQUJMRV9TQ0hFRFVMRSA6IGFyZ3MsIHdhaXQpOwoKICAgICAgICBpZiAoaXNJbW1lZGlhdGUpIHsKICAgICAgICAgIHRoaXMuX2pvaW4odGFyZ2V0LCBtZXRob2QsIGFyZ3MpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgZXhlY3V0ZUF0ID0gdGhpcy5fcGxhdGZvcm0ubm93KCkgKyB3YWl0OwogICAgICAgIHZhciBhcmdJbmRleCA9IGluZGV4ICsgNDsKCiAgICAgICAgaWYgKF90aW1lcnNbYXJnSW5kZXhdID09PSBESVNBQkxFX1NDSEVEVUxFKSB7CiAgICAgICAgICBhcmdzID0gRElTQUJMRV9TQ0hFRFVMRTsKICAgICAgICB9CgogICAgICAgIHRpbWVySWQgPSBfdGltZXJzW2luZGV4ICsgMV07CiAgICAgICAgdmFyIGkgPSBiaW5hcnlTZWFyY2goZXhlY3V0ZUF0LCBfdGltZXJzKTsKCiAgICAgICAgaWYgKGluZGV4ICsgVElNRVJTX09GRlNFVCA9PT0gaSkgewogICAgICAgICAgX3RpbWVyc1tpbmRleF0gPSBleGVjdXRlQXQ7CiAgICAgICAgICBfdGltZXJzW2FyZ0luZGV4XSA9IGFyZ3M7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBzdGFjayA9IHRoaXMuX3RpbWVyc1tpbmRleCArIDVdOwoKICAgICAgICAgIHRoaXMuX3RpbWVycy5zcGxpY2UoaSwgMCwgZXhlY3V0ZUF0LCB0aW1lcklkLCB0YXJnZXQsIG1ldGhvZCwgYXJncywgc3RhY2spOwoKICAgICAgICAgIHRoaXMuX3RpbWVycy5zcGxpY2UoaW5kZXgsIFRJTUVSU19PRkZTRVQpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGluZGV4ID09PSAwKSB7CiAgICAgICAgICB0aGlzLl9yZWluc3RhbGxUaW1lclRpbWVvdXQoKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiB0aW1lcklkOwogICAgfTsKCiAgICBfcHJvdG8zLmNhbmNlbFRpbWVycyA9IGZ1bmN0aW9uIGNhbmNlbFRpbWVycygpIHsKICAgICAgY2FuY2VsVGltZXJzQ291bnQrKzsKCiAgICAgIHRoaXMuX2NsZWFyVGltZXJUaW1lb3V0KCk7CgogICAgICB0aGlzLl90aW1lcnMgPSBbXTsKCiAgICAgIHRoaXMuX2NhbmNlbEF1dG9ydW4oKTsKICAgIH07CgogICAgX3Byb3RvMy5oYXNUaW1lcnMgPSBmdW5jdGlvbiBoYXNUaW1lcnMoKSB7CiAgICAgIHJldHVybiB0aGlzLl90aW1lcnMubGVuZ3RoID4gMCB8fCB0aGlzLl9hdXRvcnVuOwogICAgfTsKCiAgICBfcHJvdG8zLmNhbmNlbCA9IGZ1bmN0aW9uIGNhbmNlbCh0aW1lcikgewogICAgICBjYW5jZWxDb3VudCsrOwoKICAgICAgaWYgKHRpbWVyID09PSBudWxsIHx8IHRpbWVyID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIHZhciB0aW1lclR5cGUgPSB0eXBlb2YgdGltZXI7CgogICAgICBpZiAodGltZXJUeXBlID09PSAnbnVtYmVyJykgewogICAgICAgIC8vIHdlJ3JlIGNhbmNlbGxpbmcgYSBzZXRUaW1lb3V0IG9yIHRocm90dGxlIG9yIGRlYm91bmNlCiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbmNlbExhdGVyVGltZXIodGltZXIpOwogICAgICB9IGVsc2UgaWYgKHRpbWVyVHlwZSA9PT0gJ29iamVjdCcgJiYgdGltZXIucXVldWUgJiYgdGltZXIubWV0aG9kKSB7CiAgICAgICAgLy8gd2UncmUgY2FuY2VsbGluZyBhIGRlZmVyT25jZQogICAgICAgIHJldHVybiB0aW1lci5xdWV1ZS5jYW5jZWwodGltZXIpOwogICAgICB9CgogICAgICByZXR1cm4gZmFsc2U7CiAgICB9OwoKICAgIF9wcm90bzMuZW5zdXJlSW5zdGFuY2UgPSBmdW5jdGlvbiBlbnN1cmVJbnN0YW5jZSgpIHsKICAgICAgdGhpcy5fZW5zdXJlSW5zdGFuY2UoKTsKICAgIH0KICAgIC8qKgogICAgICogUmV0dXJucyBkZWJ1ZyBpbmZvcm1hdGlvbiByZWxhdGVkIHRvIHRoZSBjdXJyZW50IGluc3RhbmNlIG9mIEJhY2tidXJuZXIKICAgICAqCiAgICAgKiBAbWV0aG9kIGdldERlYnVnSW5mbwogICAgICogQHJldHVybnMge09iamVjdCB8IHVuZGVmaW5lZH0gV2lsbCByZXR1cm4gYW5kIE9iamVjdCBjb250YWluaW5nIGRlYnVnIGluZm9ybWF0aW9uIGlmCiAgICAgKiB0aGUgREVCVUcgZmxhZyBpcyBzZXQgdG8gdHJ1ZSBvbiB0aGUgY3VycmVudCBpbnN0YW5jZSBvZiBCYWNrYnVybmVyLCBlbHNlIHVuZGVmaW5lZC4KICAgICAqLwogICAgOwoKICAgIF9wcm90bzMuZ2V0RGVidWdJbmZvID0gZnVuY3Rpb24gZ2V0RGVidWdJbmZvKCkgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIGlmICh0aGlzLkRFQlVHKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGF1dG9ydW46IHRoaXMuX2F1dG9ydW5TdGFjaywKICAgICAgICAgIGNvdW50ZXJzOiB0aGlzLmNvdW50ZXJzLAogICAgICAgICAgdGltZXJzOiBnZXRRdWV1ZUl0ZW1zKHRoaXMuX3RpbWVycywgVElNRVJTX09GRlNFVCwgMiksCiAgICAgICAgICBpbnN0YW5jZVN0YWNrOiBbdGhpcy5jdXJyZW50SW5zdGFuY2VdLmNvbmNhdCh0aGlzLmluc3RhbmNlU3RhY2spLm1hcChmdW5jdGlvbiAoZGVmZXJyZWRBY3Rpb25RdWV1ZSkgewogICAgICAgICAgICByZXR1cm4gZGVmZXJyZWRBY3Rpb25RdWV1ZSAmJiBkZWZlcnJlZEFjdGlvblF1ZXVlLl9nZXREZWJ1Z0luZm8oX3RoaXMyLkRFQlVHKTsKICAgICAgICAgIH0pCiAgICAgICAgfTsKICAgICAgfQoKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH07CgogICAgX3Byb3RvMy5fZW5kID0gZnVuY3Rpb24gX2VuZChmcm9tQXV0b3J1bikgewogICAgICB2YXIgY3VycmVudEluc3RhbmNlID0gdGhpcy5jdXJyZW50SW5zdGFuY2U7CiAgICAgIHZhciBuZXh0SW5zdGFuY2UgPSBudWxsOwoKICAgICAgaWYgKGN1cnJlbnRJbnN0YW5jZSA9PT0gbnVsbCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiZW5kIGNhbGxlZCB3aXRob3V0IGJlZ2luIik7CiAgICAgIH0gLy8gUHJldmVudCBkb3VibGUtZmluYWxseSBidWcgaW4gU2FmYXJpIDYuMC4yIGFuZCBpT1MgNgogICAgICAvLyBUaGlzIGJ1ZyBhcHBlYXJzIHRvIGJlIHJlc29sdmVkIGluIFNhZmFyaSA2LjAuNSBhbmQgaU9TIDcKCgogICAgICB2YXIgZmluYWxseUFscmVhZHlDYWxsZWQgPSBmYWxzZTsKICAgICAgdmFyIHJlc3VsdDsKCiAgICAgIHRyeSB7CiAgICAgICAgcmVzdWx0ID0gY3VycmVudEluc3RhbmNlLmZsdXNoKGZyb21BdXRvcnVuKTsKICAgICAgfSBmaW5hbGx5IHsKICAgICAgICBpZiAoIWZpbmFsbHlBbHJlYWR5Q2FsbGVkKSB7CiAgICAgICAgICBmaW5hbGx5QWxyZWFkeUNhbGxlZCA9IHRydWU7CgogICAgICAgICAgaWYgKHJlc3VsdCA9PT0gMQogICAgICAgICAgLyogUGF1c2UgKi8KICAgICAgICAgICkgewogICAgICAgICAgICAgIHZhciBwbGFubmVkTmV4dFF1ZXVlID0gdGhpcy5xdWV1ZU5hbWVzW2N1cnJlbnRJbnN0YW5jZS5xdWV1ZU5hbWVJbmRleF07CgogICAgICAgICAgICAgIHRoaXMuX3NjaGVkdWxlQXV0b3J1bihwbGFubmVkTmV4dFF1ZXVlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGhpcy5jdXJyZW50SW5zdGFuY2UgPSBudWxsOwoKICAgICAgICAgICAgaWYgKHRoaXMuaW5zdGFuY2VTdGFjay5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgbmV4dEluc3RhbmNlID0gdGhpcy5pbnN0YW5jZVN0YWNrLnBvcCgpOwogICAgICAgICAgICAgIHRoaXMuY3VycmVudEluc3RhbmNlID0gbmV4dEluc3RhbmNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICB0aGlzLl90cmlnZ2VyKCdlbmQnLCBjdXJyZW50SW5zdGFuY2UsIG5leHRJbnN0YW5jZSk7CgogICAgICAgICAgICB0aGlzLl9vbkVuZChjdXJyZW50SW5zdGFuY2UsIG5leHRJbnN0YW5jZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzMuX2pvaW4gPSBmdW5jdGlvbiBfam9pbih0YXJnZXQsIG1ldGhvZCwgYXJncykgewogICAgICBpZiAodGhpcy5jdXJyZW50SW5zdGFuY2UgPT09IG51bGwpIHsKICAgICAgICByZXR1cm4gdGhpcy5fcnVuKHRhcmdldCwgbWV0aG9kLCBhcmdzKTsKICAgICAgfQoKICAgICAgaWYgKHRhcmdldCA9PT0gdW5kZWZpbmVkICYmIGFyZ3MgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBtZXRob2QoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbWV0aG9kLmFwcGx5KHRhcmdldCwgYXJncyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMy5fcnVuID0gZnVuY3Rpb24gX3J1bih0YXJnZXQsIG1ldGhvZCwgYXJncykgewogICAgICB2YXIgb25FcnJvciA9IGdldE9uRXJyb3IodGhpcy5vcHRpb25zKTsKICAgICAgdGhpcy5iZWdpbigpOwoKICAgICAgaWYgKG9uRXJyb3IpIHsKICAgICAgICB0cnkgewogICAgICAgICAgcmV0dXJuIG1ldGhvZC5hcHBseSh0YXJnZXQsIGFyZ3MpOwogICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICBvbkVycm9yKGVycm9yKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgdGhpcy5lbmQoKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHJldHVybiBtZXRob2QuYXBwbHkodGFyZ2V0LCBhcmdzKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgdGhpcy5lbmQoKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMy5fY2FuY2VsQXV0b3J1biA9IGZ1bmN0aW9uIF9jYW5jZWxBdXRvcnVuKCkgewogICAgICBpZiAodGhpcy5fYXV0b3J1bikgewogICAgICAgIHRoaXMuX3BsYXRmb3JtLmNsZWFyTmV4dCgpOwoKICAgICAgICB0aGlzLl9hdXRvcnVuID0gZmFsc2U7CiAgICAgICAgdGhpcy5fYXV0b3J1blN0YWNrID0gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zLl9sYXRlciA9IGZ1bmN0aW9uIF9sYXRlcih0YXJnZXQsIG1ldGhvZCwgYXJncywgd2FpdCkgewogICAgICB2YXIgc3RhY2sgPSB0aGlzLkRFQlVHID8gbmV3IEVycm9yKCkgOiB1bmRlZmluZWQ7CiAgICAgIHZhciBleGVjdXRlQXQgPSB0aGlzLl9wbGF0Zm9ybS5ub3coKSArIHdhaXQ7CiAgICAgIHZhciBpZCA9IFVVSUQrKzsKCiAgICAgIGlmICh0aGlzLl90aW1lcnMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgdGhpcy5fdGltZXJzLnB1c2goZXhlY3V0ZUF0LCBpZCwgdGFyZ2V0LCBtZXRob2QsIGFyZ3MsIHN0YWNrKTsKCiAgICAgICAgdGhpcy5faW5zdGFsbFRpbWVyVGltZW91dCgpOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIGZpbmQgcG9zaXRpb24gdG8gaW5zZXJ0CiAgICAgICAgdmFyIGkgPSBiaW5hcnlTZWFyY2goZXhlY3V0ZUF0LCB0aGlzLl90aW1lcnMpOwoKICAgICAgICB0aGlzLl90aW1lcnMuc3BsaWNlKGksIDAsIGV4ZWN1dGVBdCwgaWQsIHRhcmdldCwgbWV0aG9kLCBhcmdzLCBzdGFjayk7IC8vIGFsd2F5cyByZWluc3RhbGwgc2luY2UgaXQgY291bGQgYmUgb3V0IG9mIHN5bmMKCgogICAgICAgIHRoaXMuX3JlaW5zdGFsbFRpbWVyVGltZW91dCgpOwogICAgICB9CgogICAgICByZXR1cm4gaWQ7CiAgICB9OwoKICAgIF9wcm90bzMuX2NhbmNlbExhdGVyVGltZXIgPSBmdW5jdGlvbiBfY2FuY2VsTGF0ZXJUaW1lcih0aW1lcikgewogICAgICBmb3IgKHZhciBpID0gMTsgaSA8IHRoaXMuX3RpbWVycy5sZW5ndGg7IGkgKz0gVElNRVJTX09GRlNFVCkgewogICAgICAgIGlmICh0aGlzLl90aW1lcnNbaV0gPT09IHRpbWVyKSB7CiAgICAgICAgICB0aGlzLl90aW1lcnMuc3BsaWNlKGkgLSAxLCBUSU1FUlNfT0ZGU0VUKTsKCiAgICAgICAgICBpZiAoaSA9PT0gMSkgewogICAgICAgICAgICB0aGlzLl9yZWluc3RhbGxUaW1lclRpbWVvdXQoKTsKICAgICAgICAgIH0KCiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIC8qKgogICAgIFRyaWdnZXIgYW4gZXZlbnQuIFN1cHBvcnRzIHVwIHRvIHR3byBhcmd1bWVudHMuIERlc2lnbmVkIGFyb3VuZAogICAgIHRyaWdnZXJpbmcgdHJhbnNpdGlvbiBldmVudHMgZnJvbSBvbmUgcnVuIGxvb3AgaW5zdGFuY2UgdG8gdGhlCiAgICAgbmV4dCwgd2hpY2ggcmVxdWlyZXMgYW4gYXJndW1lbnQgZm9yIHRoZSAgaW5zdGFuY2UgYW5kIHRoZW4KICAgICBhbiBhcmd1bWVudCBmb3IgdGhlIG5leHQgaW5zdGFuY2UuCiAgICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIF90cmlnZ2VyCiAgICAgQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZQogICAgIEBwYXJhbSB7YW55fSBhcmcxCiAgICAgQHBhcmFtIHthbnl9IGFyZzIKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMuX3RyaWdnZXIgPSBmdW5jdGlvbiBfdHJpZ2dlcihldmVudE5hbWUsIGFyZzEsIGFyZzIpIHsKICAgICAgdmFyIGNhbGxiYWNrcyA9IHRoaXMuX2V2ZW50Q2FsbGJhY2tzW2V2ZW50TmFtZV07CgogICAgICBpZiAoY2FsbGJhY2tzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNhbGxiYWNrcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgY2FsbGJhY2tzW2ldKGFyZzEsIGFyZzIpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zLl9ydW5FeHBpcmVkVGltZXJzID0gZnVuY3Rpb24gX3J1bkV4cGlyZWRUaW1lcnMoKSB7CiAgICAgIHRoaXMuX3RpbWVyVGltZW91dElkID0gbnVsbDsKCiAgICAgIGlmICh0aGlzLl90aW1lcnMubGVuZ3RoID4gMCkgewogICAgICAgIHRoaXMuYmVnaW4oKTsKCiAgICAgICAgdGhpcy5fc2NoZWR1bGVFeHBpcmVkVGltZXJzKCk7CgogICAgICAgIHRoaXMuZW5kKCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMy5fc2NoZWR1bGVFeHBpcmVkVGltZXJzID0gZnVuY3Rpb24gX3NjaGVkdWxlRXhwaXJlZFRpbWVycygpIHsKICAgICAgdmFyIHRpbWVycyA9IHRoaXMuX3RpbWVyczsKICAgICAgdmFyIGkgPSAwOwogICAgICB2YXIgbCA9IHRpbWVycy5sZW5ndGg7CiAgICAgIHZhciBkZWZhdWx0UXVldWUgPSB0aGlzLl9kZWZhdWx0UXVldWU7CgogICAgICB2YXIgbiA9IHRoaXMuX3BsYXRmb3JtLm5vdygpOwoKICAgICAgZm9yICg7IGkgPCBsOyBpICs9IFRJTUVSU19PRkZTRVQpIHsKICAgICAgICB2YXIgZXhlY3V0ZUF0ID0gdGltZXJzW2ldOwoKICAgICAgICBpZiAoZXhlY3V0ZUF0ID4gbikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICB2YXIgYXJncyA9IHRpbWVyc1tpICsgNF07CgogICAgICAgIGlmIChhcmdzICE9PSBESVNBQkxFX1NDSEVEVUxFKSB7CiAgICAgICAgICB2YXIgdGFyZ2V0ID0gdGltZXJzW2kgKyAyXTsKICAgICAgICAgIHZhciBtZXRob2QgPSB0aW1lcnNbaSArIDNdOwogICAgICAgICAgdmFyIHN0YWNrID0gdGltZXJzW2kgKyA1XTsKICAgICAgICAgIHRoaXMuY3VycmVudEluc3RhbmNlLnNjaGVkdWxlKGRlZmF1bHRRdWV1ZSwgdGFyZ2V0LCBtZXRob2QsIGFyZ3MsIGZhbHNlLCBzdGFjayk7CiAgICAgICAgfQogICAgICB9CgogICAgICB0aW1lcnMuc3BsaWNlKDAsIGkpOwoKICAgICAgdGhpcy5faW5zdGFsbFRpbWVyVGltZW91dCgpOwogICAgfTsKCiAgICBfcHJvdG8zLl9yZWluc3RhbGxUaW1lclRpbWVvdXQgPSBmdW5jdGlvbiBfcmVpbnN0YWxsVGltZXJUaW1lb3V0KCkgewogICAgICB0aGlzLl9jbGVhclRpbWVyVGltZW91dCgpOwoKICAgICAgdGhpcy5faW5zdGFsbFRpbWVyVGltZW91dCgpOwogICAgfTsKCiAgICBfcHJvdG8zLl9jbGVhclRpbWVyVGltZW91dCA9IGZ1bmN0aW9uIF9jbGVhclRpbWVyVGltZW91dCgpIHsKICAgICAgaWYgKHRoaXMuX3RpbWVyVGltZW91dElkID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9wbGF0Zm9ybS5jbGVhclRpbWVvdXQodGhpcy5fdGltZXJUaW1lb3V0SWQpOwoKICAgICAgdGhpcy5fdGltZXJUaW1lb3V0SWQgPSBudWxsOwogICAgfTsKCiAgICBfcHJvdG8zLl9pbnN0YWxsVGltZXJUaW1lb3V0ID0gZnVuY3Rpb24gX2luc3RhbGxUaW1lclRpbWVvdXQoKSB7CiAgICAgIGlmICh0aGlzLl90aW1lcnMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgbWluRXhwaXJlc0F0ID0gdGhpcy5fdGltZXJzWzBdOwoKICAgICAgdmFyIG4gPSB0aGlzLl9wbGF0Zm9ybS5ub3coKTsKCiAgICAgIHZhciB3YWl0ID0gTWF0aC5tYXgoMCwgbWluRXhwaXJlc0F0IC0gbik7CiAgICAgIHRoaXMuX3RpbWVyVGltZW91dElkID0gdGhpcy5fcGxhdGZvcm0uc2V0VGltZW91dCh0aGlzLl9ib3VuZFJ1bkV4cGlyZWRUaW1lcnMsIHdhaXQpOwogICAgfTsKCiAgICBfcHJvdG8zLl9lbnN1cmVJbnN0YW5jZSA9IGZ1bmN0aW9uIF9lbnN1cmVJbnN0YW5jZSgpIHsKICAgICAgdmFyIGN1cnJlbnRJbnN0YW5jZSA9IHRoaXMuY3VycmVudEluc3RhbmNlOwoKICAgICAgaWYgKGN1cnJlbnRJbnN0YW5jZSA9PT0gbnVsbCkgewogICAgICAgIHRoaXMuX2F1dG9ydW5TdGFjayA9IHRoaXMuREVCVUcgPyBuZXcgRXJyb3IoKSA6IHVuZGVmaW5lZDsKICAgICAgICBjdXJyZW50SW5zdGFuY2UgPSB0aGlzLmJlZ2luKCk7CgogICAgICAgIHRoaXMuX3NjaGVkdWxlQXV0b3J1bih0aGlzLnF1ZXVlTmFtZXNbMF0pOwogICAgICB9CgogICAgICByZXR1cm4gY3VycmVudEluc3RhbmNlOwogICAgfTsKCiAgICBfcHJvdG8zLl9zY2hlZHVsZUF1dG9ydW4gPSBmdW5jdGlvbiBfc2NoZWR1bGVBdXRvcnVuKHBsYW5uZWROZXh0UXVldWUpIHsKICAgICAgYXV0b3J1bnNDcmVhdGVkQ291bnQrKzsKICAgICAgdmFyIG5leHQgPSB0aGlzLl9wbGF0Zm9ybS5uZXh0OwogICAgICB2YXIgZmx1c2ggPSB0aGlzLm9wdGlvbnMuZmx1c2g7CgogICAgICBpZiAoZmx1c2gpIHsKICAgICAgICBmbHVzaChwbGFubmVkTmV4dFF1ZXVlLCBuZXh0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBuZXh0KCk7CiAgICAgIH0KCiAgICAgIHRoaXMuX2F1dG9ydW4gPSB0cnVlOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKEJhY2tidXJuZXIsIFt7CiAgICAgIGtleTogImNvdW50ZXJzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGJlZ2luOiBiZWdpbkNvdW50LAogICAgICAgICAgZW5kOiBlbmRDb3VudCwKICAgICAgICAgIGV2ZW50czogewogICAgICAgICAgICBiZWdpbjogYmVnaW5FdmVudENvdW50LAogICAgICAgICAgICBlbmQ6IGVuZEV2ZW50Q291bnQKICAgICAgICAgIH0sCiAgICAgICAgICBhdXRvcnVuczogewogICAgICAgICAgICBjcmVhdGVkOiBhdXRvcnVuc0NyZWF0ZWRDb3VudCwKICAgICAgICAgICAgY29tcGxldGVkOiBhdXRvcnVuc0NvbXBsZXRlZENvdW50CiAgICAgICAgICB9LAogICAgICAgICAgcnVuOiBydW5Db3VudCwKICAgICAgICAgIGpvaW46IGpvaW5Db3VudCwKICAgICAgICAgIGRlZmVyOiBkZWZlckNvdW50LAogICAgICAgICAgc2NoZWR1bGU6IHNjaGVkdWxlQ291bnQsCiAgICAgICAgICBzY2hlZHVsZUl0ZXJhYmxlOiBzY2hlZHVsZUl0ZXJhYmxlQ291bnQsCiAgICAgICAgICBkZWZlck9uY2U6IGRlZmVyT25jZUNvdW50LAogICAgICAgICAgc2NoZWR1bGVPbmNlOiBzY2hlZHVsZU9uY2VDb3VudCwKICAgICAgICAgIHNldFRpbWVvdXQ6IHNldFRpbWVvdXRDb3VudCwKICAgICAgICAgIGxhdGVyOiBsYXRlckNvdW50LAogICAgICAgICAgdGhyb3R0bGU6IHRocm90dGxlQ291bnQsCiAgICAgICAgICBkZWJvdW5jZTogZGVib3VuY2VDb3VudCwKICAgICAgICAgIGNhbmNlbFRpbWVyczogY2FuY2VsVGltZXJzQ291bnQsCiAgICAgICAgICBjYW5jZWw6IGNhbmNlbENvdW50LAogICAgICAgICAgbG9vcHM6IHsKICAgICAgICAgICAgdG90YWw6IGRlZmVycmVkQWN0aW9uUXVldWVzQ3JlYXRlZENvdW50LAogICAgICAgICAgICBuZXN0ZWQ6IG5lc3RlZERlZmVycmVkQWN0aW9uUXVldWVzQ3JlYXRlZAogICAgICAgICAgfQogICAgICAgIH07CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiZGVmYXVsdFF1ZXVlIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZmF1bHRRdWV1ZTsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIEJhY2tidXJuZXI7CiAgfSgpOwoKICBCYWNrYnVybmVyLlF1ZXVlID0gUXVldWU7CiAgQmFja2J1cm5lci5idWlsZFBsYXRmb3JtID0gYnVpbGRQbGF0Zm9ybTsKICBCYWNrYnVybmVyLmJ1aWxkTmV4dCA9IGJ1aWxkTmV4dDsKICB2YXIgX2RlZmF1bHQgPSBCYWNrYnVybmVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiZGFnLW1hcCIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAqIEEgdG9wb2xvZ2ljYWxseSBvcmRlcmVkIG1hcCBvZiBrZXkvdmFsdWUgcGFpcnMgd2l0aCBhIHNpbXBsZSBBUEkgZm9yIGFkZGluZyBjb25zdHJhaW50cy4KICAgKgogICAqIEVkZ2VzIGNhbiBmb3J3YXJkIHJlZmVyZW5jZSBrZXlzIHRoYXQgaGF2ZSBub3QgYmVlbiBhZGRlZCB5ZXQgKHRoZSBmb3J3YXJkIHJlZmVyZW5jZSB3aWxsCiAgICogbWFwIHRoZSBrZXkgdG8gdW5kZWZpbmVkKS4KICAgKi8KICB2YXIgREFHID0gZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gREFHKCkgewogICAgICB0aGlzLl92ZXJ0aWNlcyA9IG5ldyBWZXJ0aWNlcygpOwogICAgfQogICAgLyoqCiAgICAgKiBBZGRzIGEga2V5L3ZhbHVlIHBhaXIgd2l0aCBkZXBlbmRlbmNpZXMgb24gb3RoZXIga2V5L3ZhbHVlIHBhaXJzLgogICAgICoKICAgICAqIEBwdWJsaWMKICAgICAqIEBwYXJhbSBrZXkgICAgVGhlIGtleSBvZiB0aGUgdmVydGV4IHRvIGJlIGFkZGVkLgogICAgICogQHBhcmFtIHZhbHVlICBUaGUgdmFsdWUgb2YgdGhhdCB2ZXJ0ZXguCiAgICAgKiBAcGFyYW0gYmVmb3JlIEEga2V5IG9yIGFycmF5IG9mIGtleXMgb2YgdGhlIHZlcnRpY2VzIHRoYXQgbXVzdAogICAgICogICAgICAgICAgICAgICBiZSB2aXNpdGVkIGJlZm9yZSB0aGlzIHZlcnRleC4KICAgICAqIEBwYXJhbSBhZnRlciAgQW4gc3RyaW5nIG9yIGFycmF5IG9mIHN0cmluZ3Mgd2l0aCB0aGUga2V5cyBvZiB0aGUKICAgICAqICAgICAgICAgICAgICAgdmVydGljZXMgdGhhdCBtdXN0IGJlIGFmdGVyIHRoaXMgdmVydGV4IGlzIHZpc2l0ZWQuCiAgICAgKi8KCgogICAgREFHLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSwgYmVmb3JlLCBhZnRlcikgewogICAgICBpZiAoIWtleSkgdGhyb3cgbmV3IEVycm9yKCdhcmd1bWVudCBga2V5YCBpcyByZXF1aXJlZCcpOwogICAgICB2YXIgdmVydGljZXMgPSB0aGlzLl92ZXJ0aWNlczsKICAgICAgdmFyIHYgPSB2ZXJ0aWNlcy5hZGQoa2V5KTsKICAgICAgdi52YWwgPSB2YWx1ZTsKCiAgICAgIGlmIChiZWZvcmUpIHsKICAgICAgICBpZiAodHlwZW9mIGJlZm9yZSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgIHZlcnRpY2VzLmFkZEVkZ2UodiwgdmVydGljZXMuYWRkKGJlZm9yZSkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJlZm9yZS5sZW5ndGg7IGkrKykgewogICAgICAgICAgICB2ZXJ0aWNlcy5hZGRFZGdlKHYsIHZlcnRpY2VzLmFkZChiZWZvcmVbaV0pKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChhZnRlcikgewogICAgICAgIGlmICh0eXBlb2YgYWZ0ZXIgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICB2ZXJ0aWNlcy5hZGRFZGdlKHZlcnRpY2VzLmFkZChhZnRlciksIHYpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFmdGVyLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHZlcnRpY2VzLmFkZEVkZ2UodmVydGljZXMuYWRkKGFmdGVyW2ldKSwgdik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwogICAgLyoqCiAgICAgKiBAZGVwcmVjYXRlZCBwbGVhc2UgdXNlIGFkZC4KICAgICAqLwoKCiAgICBEQUcucHJvdG90eXBlLmFkZEVkZ2VzID0gZnVuY3Rpb24gKGtleSwgdmFsdWUsIGJlZm9yZSwgYWZ0ZXIpIHsKICAgICAgdGhpcy5hZGQoa2V5LCB2YWx1ZSwgYmVmb3JlLCBhZnRlcik7CiAgICB9OwogICAgLyoqCiAgICAgKiBWaXNpdHMga2V5L3ZhbHVlIHBhaXJzIGluIHRvcG9sb2dpY2FsIG9yZGVyLgogICAgICoKICAgICAqIEBwdWJsaWMKICAgICAqIEBwYXJhbSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gYmUgaW52b2tlZCB3aXRoIGVhY2gga2V5L3ZhbHVlLgogICAgICovCgoKICAgIERBRy5wcm90b3R5cGUuZWFjaCA9IGZ1bmN0aW9uIChjYWxsYmFjaykgewogICAgICB0aGlzLl92ZXJ0aWNlcy53YWxrKGNhbGxiYWNrKTsKICAgIH07CiAgICAvKioKICAgICAqIEBkZXByZWNhdGVkIHBsZWFzZSB1c2UgZWFjaC4KICAgICAqLwoKCiAgICBEQUcucHJvdG90eXBlLnRvcHNvcnQgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHsKICAgICAgdGhpcy5lYWNoKGNhbGxiYWNrKTsKICAgIH07CgogICAgcmV0dXJuIERBRzsKICB9KCk7CgogIHZhciBfZGVmYXVsdCA9IERBRzsKICAvKiogQHByaXZhdGUgKi8KCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OwoKICB2YXIgVmVydGljZXMgPSBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBWZXJ0aWNlcygpIHsKICAgICAgdGhpcy5sZW5ndGggPSAwOwogICAgICB0aGlzLnN0YWNrID0gbmV3IEludFN0YWNrKCk7CiAgICAgIHRoaXMucGF0aCA9IG5ldyBJbnRTdGFjaygpOwogICAgICB0aGlzLnJlc3VsdCA9IG5ldyBJbnRTdGFjaygpOwogICAgfQoKICAgIFZlcnRpY2VzLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAoa2V5KSB7CiAgICAgIGlmICgha2V5KSB0aHJvdyBuZXcgRXJyb3IoIm1pc3Npbmcga2V5Iik7CiAgICAgIHZhciBsID0gdGhpcy5sZW5ndGggfCAwOwogICAgICB2YXIgdmVydGV4OwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHsKICAgICAgICB2ZXJ0ZXggPSB0aGlzW2ldOwogICAgICAgIGlmICh2ZXJ0ZXgua2V5ID09PSBrZXkpIHJldHVybiB2ZXJ0ZXg7CiAgICAgIH0KCiAgICAgIHRoaXMubGVuZ3RoID0gbCArIDE7CiAgICAgIHJldHVybiB0aGlzW2xdID0gewogICAgICAgIGlkeDogbCwKICAgICAgICBrZXk6IGtleSwKICAgICAgICB2YWw6IHVuZGVmaW5lZCwKICAgICAgICBvdXQ6IGZhbHNlLAogICAgICAgIGZsYWc6IGZhbHNlLAogICAgICAgIGxlbmd0aDogMAogICAgICB9OwogICAgfTsKCiAgICBWZXJ0aWNlcy5wcm90b3R5cGUuYWRkRWRnZSA9IGZ1bmN0aW9uICh2LCB3KSB7CiAgICAgIHRoaXMuY2hlY2sodiwgdy5rZXkpOwogICAgICB2YXIgbCA9IHcubGVuZ3RoIHwgMDsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgaWYgKHdbaV0gPT09IHYuaWR4KSByZXR1cm47CiAgICAgIH0KCiAgICAgIHcubGVuZ3RoID0gbCArIDE7CiAgICAgIHdbbF0gPSB2LmlkeDsKICAgICAgdi5vdXQgPSB0cnVlOwogICAgfTsKCiAgICBWZXJ0aWNlcy5wcm90b3R5cGUud2FsayA9IGZ1bmN0aW9uIChjYikgewogICAgICB0aGlzLnJlc2V0KCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgdmVydGV4ID0gdGhpc1tpXTsKICAgICAgICBpZiAodmVydGV4Lm91dCkgY29udGludWU7CiAgICAgICAgdGhpcy52aXNpdCh2ZXJ0ZXgsICIiKTsKICAgICAgfQoKICAgICAgdGhpcy5lYWNoKHRoaXMucmVzdWx0LCBjYik7CiAgICB9OwoKICAgIFZlcnRpY2VzLnByb3RvdHlwZS5jaGVjayA9IGZ1bmN0aW9uICh2LCB3KSB7CiAgICAgIGlmICh2LmtleSA9PT0gdykgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiY3ljbGUgZGV0ZWN0ZWQ6ICIgKyB3ICsgIiA8LSAiICsgdyk7CiAgICAgIH0gLy8gcXVpY2sgY2hlY2sKCgogICAgICBpZiAodi5sZW5ndGggPT09IDApIHJldHVybjsgLy8gc2hhbGxvdyBjaGVjawoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGtleSA9IHRoaXNbdltpXV0ua2V5OwoKICAgICAgICBpZiAoa2V5ID09PSB3KSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImN5Y2xlIGRldGVjdGVkOiAiICsgdyArICIgPC0gIiArIHYua2V5ICsgIiA8LSAiICsgdyk7CiAgICAgICAgfQogICAgICB9IC8vIGRlZXAgY2hlY2sKCgogICAgICB0aGlzLnJlc2V0KCk7CiAgICAgIHRoaXMudmlzaXQodiwgdyk7CgogICAgICBpZiAodGhpcy5wYXRoLmxlbmd0aCA+IDApIHsKICAgICAgICB2YXIgbXNnXzEgPSAiY3ljbGUgZGV0ZWN0ZWQ6ICIgKyB3OwogICAgICAgIHRoaXMuZWFjaCh0aGlzLnBhdGgsIGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgIG1zZ18xICs9ICIgPC0gIiArIGtleTsKICAgICAgICB9KTsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnXzEpOwogICAgICB9CiAgICB9OwoKICAgIFZlcnRpY2VzLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uICgpIHsKICAgICAgdGhpcy5zdGFjay5sZW5ndGggPSAwOwogICAgICB0aGlzLnBhdGgubGVuZ3RoID0gMDsKICAgICAgdGhpcy5yZXN1bHQubGVuZ3RoID0gMDsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gdGhpcy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICB0aGlzW2ldLmZsYWcgPSBmYWxzZTsKICAgICAgfQogICAgfTsKCiAgICBWZXJ0aWNlcy5wcm90b3R5cGUudmlzaXQgPSBmdW5jdGlvbiAoc3RhcnQsIHNlYXJjaCkgewogICAgICB2YXIgX2EgPSB0aGlzLAogICAgICAgICAgc3RhY2sgPSBfYS5zdGFjaywKICAgICAgICAgIHBhdGggPSBfYS5wYXRoLAogICAgICAgICAgcmVzdWx0ID0gX2EucmVzdWx0OwoKICAgICAgc3RhY2sucHVzaChzdGFydC5pZHgpOwoKICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCkgewogICAgICAgIHZhciBpbmRleCA9IHN0YWNrLnBvcCgpIHwgMDsKCiAgICAgICAgaWYgKGluZGV4ID49IDApIHsKICAgICAgICAgIC8vIGVudGVyCiAgICAgICAgICB2YXIgdmVydGV4ID0gdGhpc1tpbmRleF07CiAgICAgICAgICBpZiAodmVydGV4LmZsYWcpIGNvbnRpbnVlOwogICAgICAgICAgdmVydGV4LmZsYWcgPSB0cnVlOwogICAgICAgICAgcGF0aC5wdXNoKGluZGV4KTsKICAgICAgICAgIGlmIChzZWFyY2ggPT09IHZlcnRleC5rZXkpIGJyZWFrOyAvLyBwdXNoIGV4aXQKCiAgICAgICAgICBzdGFjay5wdXNoKH5pbmRleCk7CiAgICAgICAgICB0aGlzLnB1c2hJbmNvbWluZyh2ZXJ0ZXgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBleGl0CiAgICAgICAgICBwYXRoLnBvcCgpOwogICAgICAgICAgcmVzdWx0LnB1c2gofmluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgVmVydGljZXMucHJvdG90eXBlLnB1c2hJbmNvbWluZyA9IGZ1bmN0aW9uIChpbmNvbW1pbmcpIHsKICAgICAgdmFyIHN0YWNrID0gdGhpcy5zdGFjazsKCiAgICAgIGZvciAodmFyIGkgPSBpbmNvbW1pbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICB2YXIgaW5kZXggPSBpbmNvbW1pbmdbaV07CgogICAgICAgIGlmICghdGhpc1tpbmRleF0uZmxhZykgewogICAgICAgICAgc3RhY2sucHVzaChpbmRleCk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIFZlcnRpY2VzLnByb3RvdHlwZS5lYWNoID0gZnVuY3Rpb24gKGluZGljZXMsIGNiKSB7CiAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gaW5kaWNlcy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICB2YXIgdmVydGV4ID0gdGhpc1tpbmRpY2VzW2ldXTsKICAgICAgICBjYih2ZXJ0ZXgua2V5LCB2ZXJ0ZXgudmFsKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gVmVydGljZXM7CiAgfSgpOwogIC8qKiBAcHJpdmF0ZSAqLwoKCiAgdmFyIEludFN0YWNrID0gZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSW50U3RhY2soKSB7CiAgICAgIHRoaXMubGVuZ3RoID0gMDsKICAgIH0KCiAgICBJbnRTdGFjay5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uIChuKSB7CiAgICAgIHRoaXNbdGhpcy5sZW5ndGgrK10gPSBuIHwgMDsKICAgIH07CgogICAgSW50U3RhY2sucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIHRoaXNbLS10aGlzLmxlbmd0aF0gfCAwOwogICAgfTsKCiAgICByZXR1cm4gSW50U3RhY2s7CiAgfSgpOwp9KTsKZGVmaW5lKCJlbWJlci1iYWJlbCIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLndyYXBOYXRpdmVTdXBlciA9IHdyYXBOYXRpdmVTdXBlcjsKICBfZXhwb3J0cy5jbGFzc0NhbGxDaGVjayA9IGNsYXNzQ2FsbENoZWNrOwogIF9leHBvcnRzLmluaGVyaXRzTG9vc2UgPSBpbmhlcml0c0xvb3NlOwogIF9leHBvcnRzLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlID0gdGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2U7CiAgX2V4cG9ydHMuY3JlYXRlQ2xhc3MgPSBjcmVhdGVDbGFzczsKICBfZXhwb3J0cy5hc3NlcnRUaGlzSW5pdGlhbGl6ZWQgPSBhc3NlcnRUaGlzSW5pdGlhbGl6ZWQ7CiAgX2V4cG9ydHMucG9zc2libGVDb25zdHJ1Y3RvclJldHVybiA9IHBvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm47CiAgX2V4cG9ydHMub2JqZWN0RGVzdHJ1Y3R1cmluZ0VtcHR5ID0gb2JqZWN0RGVzdHJ1Y3R1cmluZ0VtcHR5OwogIHZhciBzZXRQcm90b3R5cGVPZiA9IE9iamVjdC5zZXRQcm90b3R5cGVPZjsKICB2YXIgbmF0aXZlV3JhcHBlckNhY2hlID0gbmV3IE1hcCgpOyAvLyBTdXBlciBtaW5pbWFsIHZlcnNpb24gb2YgQmFiZWwncyB3cmFwTmF0aXZlU3VwZXIuIFdlIG9ubHkgdXNlIHRoaXMgZm9yCiAgLy8gZXh0ZW5kaW5nIEZ1bmN0aW9uLCBmb3IgQ29tcHV0ZWREZWNvcmF0b3JJbXBsIGFuZCBBbGlhc0RlY29yYXRvckltcGwuIFdlIGtub3cKICAvLyB3ZSB3aWxsIG5ldmVyIGRpcmVjdGx5IGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiB0aGVzZSBjbGFzc2VzIHNvIG5vIG5lZWQgdG8KICAvLyBpbmNsdWRlIGBjb25zdHJ1Y3RgIGNvZGUgb3Igb3RoZXIgaGVscGVycy4KCiAgZnVuY3Rpb24gd3JhcE5hdGl2ZVN1cGVyKENsYXNzKSB7CiAgICBpZiAobmF0aXZlV3JhcHBlckNhY2hlLmhhcyhDbGFzcykpIHsKICAgICAgcmV0dXJuIG5hdGl2ZVdyYXBwZXJDYWNoZS5nZXQoQ2xhc3MpOwogICAgfQoKICAgIGZ1bmN0aW9uIFdyYXBwZXIoKSB7fQoKICAgIFdyYXBwZXIucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShDbGFzcy5wcm90b3R5cGUsIHsKICAgICAgY29uc3RydWN0b3I6IHsKICAgICAgICB2YWx1ZTogV3JhcHBlciwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICBjb25maWd1cmFibGU6IHRydWUKICAgICAgfQogICAgfSk7CiAgICBuYXRpdmVXcmFwcGVyQ2FjaGUuc2V0KENsYXNzLCBXcmFwcGVyKTsKICAgIHJldHVybiBzZXRQcm90b3R5cGVPZihXcmFwcGVyLCBDbGFzcyk7CiAgfQoKICBmdW5jdGlvbiBjbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgewogICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOwogICAgICB9CiAgICB9CiAgfQogIC8qCiAgICBPdmVycmlkZXMgZGVmYXVsdCBgaW5oZXJpdHNMb29zZWAgdG8gX2Fsc29fIGNhbGwgYE9iamVjdC5zZXRQcm90b3R5cGVPZmAuCiAgICBUaGlzIGlzIG5lZWRlZCBzbyB0aGF0IHdlIGNhbiB1c2UgYGxvb3NlYCBvcHRpb24gd2l0aCB0aGUKICAgIGBAYmFiZWwvcGx1Z2luLXRyYW5zZm9ybS1jbGFzc2VzYCAoYmVjYXVzZSB3ZSB3YW50IHNpbXBsZSBhc3NpZ25tZW50IHRvIHRoZQogICAgcHJvdG90eXBlIHdoZXJlZXZlciBwb3NzaWJsZSkgYnV0IGFsc28ga2VlcCBvdXIgY29uc3RydWN0b3IgYmFzZWQgcHJvdG90eXBhbAogICAgaW5oZXJpdGFuY2Ugd29ya2luZyBwcm9wZXJseQogICovCgoKICBmdW5jdGlvbiBpbmhlcml0c0xvb3NlKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7CiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbicpOwogICAgICB9CiAgICB9CgogICAgc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzID09PSBudWxsID8gbnVsbCA6IHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7CiAgICAgIGNvbnN0cnVjdG9yOiB7CiAgICAgICAgdmFsdWU6IHN1YkNsYXNzLAogICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogICAgICB9CiAgICB9KTsKCiAgICBpZiAoc3VwZXJDbGFzcyAhPT0gbnVsbCkgewogICAgICBzZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcyk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiB0YWdnZWRUZW1wbGF0ZUxpdGVyYWxMb29zZShzdHJpbmdzLCByYXcpIHsKICAgIGlmICghcmF3KSB7CiAgICAgIHJhdyA9IHN0cmluZ3Muc2xpY2UoMCk7CiAgICB9CgogICAgc3RyaW5ncy5yYXcgPSByYXc7CiAgICByZXR1cm4gc3RyaW5nczsKICB9CgogIGZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsKICAgICAgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOwogICAgICBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7CiAgICAgIGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOwogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7CiAgICB9CiAgfQogIC8qCiAgICBEaWZmZXJzIGZyb20gZGVmYXVsdCBpbXBsZW1lbnRhdGlvbiBieSBhdm9pZGluZyBib29sZWFuIGNvZXJjaW9uIG9mCiAgICBgcHJvdG9Qcm9wc2AgYW5kIGBzdGF0aWNQcm9wc2AuCiAgKi8KCgogIGZ1bmN0aW9uIGNyZWF0ZUNsYXNzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgewogICAgaWYgKHByb3RvUHJvcHMgIT09IG51bGwgJiYgcHJvdG9Qcm9wcyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIF9kZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7CiAgICB9CgogICAgaWYgKHN0YXRpY1Byb3BzICE9PSBudWxsICYmIHN0YXRpY1Byb3BzICE9PSB1bmRlZmluZWQpIHsKICAgICAgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsKICAgIH0KCiAgICByZXR1cm4gQ29uc3RydWN0b3I7CiAgfQoKICBmdW5jdGlvbiBhc3NlcnRUaGlzSW5pdGlhbGl6ZWQoc2VsZikgewogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgJiYgc2VsZiA9PT0gdm9pZCAwKSB7CiAgICAgIHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcigidGhpcyBoYXNuJ3QgYmVlbiBpbml0aWFsaXNlZCAtIHN1cGVyKCkgaGFzbid0IGJlZW4gY2FsbGVkIik7CiAgICB9CgogICAgcmV0dXJuIHNlbGY7CiAgfQogIC8qCiAgICBBZGRzIGBERUJVR2AgZ3VhcmQgdG8gZXJyb3IgYmVpbmcgdGhyb3duLCBhbmQgYXZvaWRzIGJvb2xlYW4gY29lcmNpb24gb2YgYGNhbGxgLgogICovCgoKICBmdW5jdGlvbiBwb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHsKICAgIGlmICh0eXBlb2YgY2FsbCA9PT0gJ29iamVjdCcgJiYgY2FsbCAhPT0gbnVsbCB8fCB0eXBlb2YgY2FsbCA9PT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gY2FsbDsKICAgIH0KCiAgICByZXR1cm4gYXNzZXJ0VGhpc0luaXRpYWxpemVkKHNlbGYpOwogIH0KCiAgZnVuY3Rpb24gb2JqZWN0RGVzdHJ1Y3R1cmluZ0VtcHR5KG9iaikgewogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgJiYgKG9iaiA9PT0gbnVsbCB8fCBvYmogPT09IHVuZGVmaW5lZCkpIHsKICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGRlc3RydWN0dXJlIHVuZGVmaW5lZCcpOwogICAgfQogIH0KfSk7CmRlZmluZSgiZW1iZXIvaW5kZXgiLCBbImV4cG9ydHMiLCAicmVxdWlyZSIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCIsICJub2RlLW1vZHVsZSIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvLWludGVybmFscy9jb250YWluZXIiLCAiQGVtYmVyL2luc3RydW1lbnRhdGlvbiIsICJAZW1iZXIvLWludGVybmFscy9tZXRhIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci9jYW5hcnktZmVhdHVyZXMiLCAiQGVtYmVyL2RlYnVnIiwgImJhY2tidXJuZXIiLCAiQGVtYmVyLy1pbnRlcm5hbHMvY29uc29sZSIsICJAZW1iZXIvY29udHJvbGxlciIsICJAZW1iZXIvY29udHJvbGxlci9saWIvY29udHJvbGxlcl9taXhpbiIsICJAZW1iZXIvc3RyaW5nIiwgIkBlbWJlci9zZXJ2aWNlIiwgIkBlbWJlci9vYmplY3QiLCAiQGVtYmVyL29iamVjdC9jb21wYXQiLCAiQGVtYmVyL29iamVjdC9jb21wdXRlZCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIiwgIkBlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIiLCAiZW1iZXIvdmVyc2lvbiIsICJAZW1iZXIvLWludGVybmFscy92aWV3cyIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nIiwgIkBlbWJlci8taW50ZXJuYWxzL2V4dGVuc2lvbi1zdXBwb3J0IiwgIkBlbWJlci9lcnJvciIsICJAZW1iZXIvcnVubG9vcCIsICJAZW1iZXIvLWludGVybmFscy9lcnJvci1oYW5kbGluZyIsICJAZW1iZXIvLWludGVybmFscy9vd25lciIsICJAZW1iZXIvYXBwbGljYXRpb24iLCAiQGVtYmVyL2FwcGxpY2F0aW9uL2dsb2JhbHMtcmVzb2x2ZXIiLCAiQGVtYmVyL2FwcGxpY2F0aW9uL2luc3RhbmNlIiwgIkBlbWJlci9lbmdpbmUiLCAiQGVtYmVyL2VuZ2luZS9pbnN0YW5jZSIsICJAZW1iZXIvcG9seWZpbGxzIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIiwgIkBlbWJlci9jb21wb25lbnQvdGVtcGxhdGUtb25seSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9yZXF1aXJlLCBfZW52aXJvbm1lbnQsIF9ub2RlTW9kdWxlLCB1dGlscywgX2NvbnRhaW5lciwgaW5zdHJ1bWVudGF0aW9uLCBfbWV0YSwgbWV0YWwsIF9jYW5hcnlGZWF0dXJlcywgRW1iZXJEZWJ1ZywgX2JhY2tidXJuZXIsIF9jb25zb2xlLCBfY29udHJvbGxlciwgX2NvbnRyb2xsZXJfbWl4aW4sIF9zdHJpbmcsIF9zZXJ2aWNlLCBfb2JqZWN0LCBfY29tcGF0LCBfY29tcHV0ZWQsIF9ydW50aW1lLCBfZ2xpbW1lciwgX3ZlcnNpb24sIHZpZXdzLCByb3V0aW5nLCBleHRlbnNpb25TdXBwb3J0LCBfZXJyb3IsIHJ1bmxvb3AsIF9lcnJvckhhbmRsaW5nLCBfb3duZXIsIF9hcHBsaWNhdGlvbiwgX2dsb2JhbHNSZXNvbHZlciwgX2luc3RhbmNlLCBfZW5naW5lLCBfaW5zdGFuY2UyLCBfcG9seWZpbGxzLCBfZGVwcmVjYXRlZEZlYXR1cmVzLCBfdGVtcGxhdGVPbmx5KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tdW5yZXNvbHZlZAogIC8vICoqKipAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCoqKioKICB2YXIgRW1iZXIgPSB0eXBlb2YgX2Vudmlyb25tZW50LmNvbnRleHQuaW1wb3J0cy5FbWJlciA9PT0gJ29iamVjdCcgJiYgX2Vudmlyb25tZW50LmNvbnRleHQuaW1wb3J0cy5FbWJlciB8fCB7fTsKICBFbWJlci5pc05hbWVzcGFjZSA9IHRydWU7CgogIEVtYmVyLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkgewogICAgcmV0dXJuICdFbWJlcic7CiAgfTsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEVtYmVyLCAnRU5WJywgewogICAgZ2V0OiBfZW52aXJvbm1lbnQuZ2V0RU5WLAogICAgZW51bWVyYWJsZTogZmFsc2UKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICdsb29rdXAnLCB7CiAgICBnZXQ6IF9lbnZpcm9ubWVudC5nZXRMb29rdXAsCiAgICBzZXQ6IF9lbnZpcm9ubWVudC5zZXRMb29rdXAsCiAgICBlbnVtZXJhYmxlOiBmYWxzZQogIH0pOwoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5FTUJFUl9FWFRFTkRfUFJPVE9UWVBFUykgewogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEVtYmVyLCAnRVhURU5EX1BST1RPVFlQRVMnLCB7CiAgICAgIGVudW1lcmFibGU6IGZhbHNlLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIEVtYmVyRGVidWcuZGVwcmVjYXRlKSgnQWNjZXNzaW5nIEVtYmVyLkVYVEVORF9QUk9UT1RZUEVTIGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSBtaWdyYXRlIHRvIEVtYmVyLkVOVi5FWFRFTkRfUFJPVE9UWVBFUycsIGZhbHNlLCB7CiAgICAgICAgICBpZDogJ2VtYmVyLWVudi5vbGQtZXh0ZW5kLXByb3RvdHlwZXMnLAogICAgICAgICAgdW50aWw6ICc0LjAuMCcKICAgICAgICB9KSk7CiAgICAgICAgcmV0dXJuIF9lbnZpcm9ubWVudC5FTlYuRVhURU5EX1BST1RPVFlQRVM7CiAgICAgIH0KICAgIH0pOwogIH0gLy8gKioqKkBlbWJlci9hcHBsaWNhdGlvbioqKioKCgogIEVtYmVyLmdldE93bmVyID0gX293bmVyLmdldE93bmVyOwogIEVtYmVyLnNldE93bmVyID0gX293bmVyLnNldE93bmVyOwogIEVtYmVyLkFwcGxpY2F0aW9uID0gX2FwcGxpY2F0aW9uLmRlZmF1bHQ7CiAgRW1iZXIuRGVmYXVsdFJlc29sdmVyID0gRW1iZXIuUmVzb2x2ZXIgPSBfZ2xvYmFsc1Jlc29sdmVyLmRlZmF1bHQ7CiAgRW1iZXIuQXBwbGljYXRpb25JbnN0YW5jZSA9IF9pbnN0YW5jZS5kZWZhdWx0OyAvLyAqKioqQGVtYmVyL2VuZ2luZSoqKioKCiAgRW1iZXIuRW5naW5lID0gX2VuZ2luZS5kZWZhdWx0OwogIEVtYmVyLkVuZ2luZUluc3RhbmNlID0gX2luc3RhbmNlMi5kZWZhdWx0OyAvLyAqKioqQGVtYmVyL3BvbHlmaWxscyoqKioKCiAgRW1iZXIuYXNzaWduID0gX3BvbHlmaWxscy5hc3NpZ247CiAgRW1iZXIubWVyZ2UgPSBfcG9seWZpbGxzLm1lcmdlOyAvLyAqKioqQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMqKioqCgogIEVtYmVyLmdlbmVyYXRlR3VpZCA9IHV0aWxzLmdlbmVyYXRlR3VpZDsKICBFbWJlci5HVUlEX0tFWSA9IHV0aWxzLkdVSURfS0VZOwogIEVtYmVyLmd1aWRGb3IgPSB1dGlscy5ndWlkRm9yOwogIEVtYmVyLmluc3BlY3QgPSB1dGlscy5pbnNwZWN0OwogIEVtYmVyLm1ha2VBcnJheSA9IHV0aWxzLm1ha2VBcnJheTsKICBFbWJlci5jYW5JbnZva2UgPSB1dGlscy5jYW5JbnZva2U7CiAgRW1iZXIudHJ5SW52b2tlID0gdXRpbHMudHJ5SW52b2tlOwogIEVtYmVyLndyYXAgPSB1dGlscy53cmFwOwogIEVtYmVyLnV1aWQgPSB1dGlscy51dWlkOyAvLyAqKioqQGVtYmVyLy1pbnRlcm5hbHMvY29udGFpbmVyKioqKgoKICBFbWJlci5Db250YWluZXIgPSBfY29udGFpbmVyLkNvbnRhaW5lcjsKICBFbWJlci5SZWdpc3RyeSA9IF9jb250YWluZXIuUmVnaXN0cnk7IC8vICoqKipAZW1iZXIvZGVidWcqKioqCgogIEVtYmVyLmFzc2VydCA9IEVtYmVyRGVidWcuYXNzZXJ0OwogIEVtYmVyLndhcm4gPSBFbWJlckRlYnVnLndhcm47CiAgRW1iZXIuZGVidWcgPSBFbWJlckRlYnVnLmRlYnVnOwogIEVtYmVyLmRlcHJlY2F0ZSA9IEVtYmVyRGVidWcuZGVwcmVjYXRlOwogIEVtYmVyLmRlcHJlY2F0ZUZ1bmMgPSBFbWJlckRlYnVnLmRlcHJlY2F0ZUZ1bmM7CiAgRW1iZXIucnVuSW5EZWJ1ZyA9IEVtYmVyRGVidWcucnVuSW5EZWJ1ZzsgLy8gKioqKkBlbWJlci9lcnJvcioqKioKCiAgRW1iZXIuRXJyb3IgPSBfZXJyb3IuZGVmYXVsdDsKICAvKioKICAgIEBwdWJsaWMKICAgIEBjbGFzcyBFbWJlci5EZWJ1ZwogICovCgogIEVtYmVyLkRlYnVnID0gewogICAgcmVnaXN0ZXJEZXByZWNhdGlvbkhhbmRsZXI6IEVtYmVyRGVidWcucmVnaXN0ZXJEZXByZWNhdGlvbkhhbmRsZXIsCiAgICByZWdpc3Rlcldhcm5IYW5kbGVyOiBFbWJlckRlYnVnLnJlZ2lzdGVyV2FybkhhbmRsZXIsCiAgICBpc0NvbXB1dGVkOiBtZXRhbC5pc0NvbXB1dGVkCiAgfTsgLy8gKioqKkBlbWJlci9pbnN0cnVtZW50YXRpb24qKioqCgogIEVtYmVyLmluc3RydW1lbnQgPSBpbnN0cnVtZW50YXRpb24uaW5zdHJ1bWVudDsKICBFbWJlci5zdWJzY3JpYmUgPSBpbnN0cnVtZW50YXRpb24uc3Vic2NyaWJlOwogIEVtYmVyLkluc3RydW1lbnRhdGlvbiA9IHsKICAgIGluc3RydW1lbnQ6IGluc3RydW1lbnRhdGlvbi5pbnN0cnVtZW50LAogICAgc3Vic2NyaWJlOiBpbnN0cnVtZW50YXRpb24uc3Vic2NyaWJlLAogICAgdW5zdWJzY3JpYmU6IGluc3RydW1lbnRhdGlvbi51bnN1YnNjcmliZSwKICAgIHJlc2V0OiBpbnN0cnVtZW50YXRpb24ucmVzZXQKICB9OyAvLyAqKioqQGVtYmVyL3J1bmxvb3AqKioqCiAgLy8gVXNpbmcgX2dsb2JhbHNSdW4gaGVyZSBzbyB0aGF0IG11dGF0aW5nIHRoZSBmdW5jdGlvbiAoYWRkaW5nCiAgLy8gYG5leHRgLCBgbGF0ZXJgLCBldGMgdG8gaXQpIGlzIG9ubHkgYXZhaWxhYmxlIGluIGdsb2JhbHMgYnVpbGRzCgogIEVtYmVyLnJ1biA9IHJ1bmxvb3AuX2dsb2JhbHNSdW47CiAgRW1iZXIucnVuLmJhY2tidXJuZXIgPSBydW5sb29wLmJhY2tidXJuZXI7CiAgRW1iZXIucnVuLmJlZ2luID0gcnVubG9vcC5iZWdpbjsKICBFbWJlci5ydW4uYmluZCA9IHJ1bmxvb3AuYmluZDsKICBFbWJlci5ydW4uY2FuY2VsID0gcnVubG9vcC5jYW5jZWw7CiAgRW1iZXIucnVuLmRlYm91bmNlID0gcnVubG9vcC5kZWJvdW5jZTsKICBFbWJlci5ydW4uZW5kID0gcnVubG9vcC5lbmQ7CiAgRW1iZXIucnVuLmhhc1NjaGVkdWxlZFRpbWVycyA9IHJ1bmxvb3AuaGFzU2NoZWR1bGVkVGltZXJzOwogIEVtYmVyLnJ1bi5qb2luID0gcnVubG9vcC5qb2luOwogIEVtYmVyLnJ1bi5sYXRlciA9IHJ1bmxvb3AubGF0ZXI7CiAgRW1iZXIucnVuLm5leHQgPSBydW5sb29wLm5leHQ7CiAgRW1iZXIucnVuLm9uY2UgPSBydW5sb29wLm9uY2U7CiAgRW1iZXIucnVuLnNjaGVkdWxlID0gcnVubG9vcC5zY2hlZHVsZTsKICBFbWJlci5ydW4uc2NoZWR1bGVPbmNlID0gcnVubG9vcC5zY2hlZHVsZU9uY2U7CiAgRW1iZXIucnVuLnRocm90dGxlID0gcnVubG9vcC50aHJvdHRsZTsKICBFbWJlci5ydW4uY2FuY2VsVGltZXJzID0gcnVubG9vcC5jYW5jZWxUaW1lcnM7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEVtYmVyLnJ1biwgJ2N1cnJlbnRSdW5Mb29wJywgewogICAgZ2V0OiBydW5sb29wLmdldEN1cnJlbnRSdW5Mb29wLAogICAgZW51bWVyYWJsZTogZmFsc2UKICB9KTsgLy8gKioqKkBlbWJlci8taW50ZXJuYWxzL21ldGFsKioqKgogIC8vIFVzaW5nIF9nbG9iYWxzQ29tcHV0ZWQgaGVyZSBzbyB0aGF0IG11dGF0aW5nIHRoZSBmdW5jdGlvbiBpcyBvbmx5IGF2YWlsYWJsZQogIC8vIGluIGdsb2JhbHMgYnVpbGRzCgogIHZhciBjb21wdXRlZCA9IG1ldGFsLl9nbG9iYWxzQ29tcHV0ZWQ7CiAgRW1iZXIuY29tcHV0ZWQgPSBjb21wdXRlZDsKICBFbWJlci5fZGVzY3JpcHRvciA9IG1ldGFsLm5hdGl2ZURlc2NEZWNvcmF0b3I7CiAgRW1iZXIuX3RyYWNrZWQgPSBtZXRhbC50cmFja2VkOwogIGNvbXB1dGVkLmFsaWFzID0gbWV0YWwuYWxpYXM7CiAgRW1iZXIuY2FjaGVGb3IgPSBtZXRhbC5nZXRDYWNoZWRWYWx1ZUZvcjsKICBFbWJlci5Db21wdXRlZFByb3BlcnR5ID0gbWV0YWwuQ29tcHV0ZWRQcm9wZXJ0eTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICdfc2V0Q29tcHV0ZWREZWNvcmF0b3InLCB7CiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBFbWJlckRlYnVnLmRlcHJlY2F0ZSkoJ1BsZWFzZSBtaWdyYXRlIGZyb20gRW1iZXIuX3NldENvbXB1dGVkRGVjb3JhdG9yIHRvIEVtYmVyLl9zZXRDbGFzc2ljRGVjb3JhdG9yJywgZmFsc2UsIHsKICAgICAgICBpZDogJ2VtYmVyLl9zZXRDb21wdXRlZERlY29yYXRvcicsCiAgICAgICAgdW50aWw6ICczLjEzLjAnCiAgICAgIH0pKTsKICAgICAgcmV0dXJuIG1ldGFsLnNldENsYXNzaWNEZWNvcmF0b3I7CiAgICB9CiAgfSk7CiAgRW1iZXIuX3NldENsYXNzaWNEZWNvcmF0b3IgPSBtZXRhbC5zZXRDbGFzc2ljRGVjb3JhdG9yOwogIEVtYmVyLm1ldGEgPSBfbWV0YS5tZXRhOwogIEVtYmVyLmdldCA9IG1ldGFsLmdldDsKICBFbWJlci5nZXRXaXRoRGVmYXVsdCA9IG1ldGFsLmdldFdpdGhEZWZhdWx0OwogIEVtYmVyLl9nZXRQYXRoID0gbWV0YWwuX2dldFBhdGg7CiAgRW1iZXIuc2V0ID0gbWV0YWwuc2V0OwogIEVtYmVyLnRyeVNldCA9IG1ldGFsLnRyeVNldDsKICBFbWJlci5GRUFUVVJFUyA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoewogICAgaXNFbmFibGVkOiBfY2FuYXJ5RmVhdHVyZXMuaXNFbmFibGVkCiAgfSwgX2NhbmFyeUZlYXR1cmVzLkZFQVRVUkVTKTsKICBFbWJlci5fQ2FjaGUgPSB1dGlscy5DYWNoZTsKICBFbWJlci5vbiA9IG1ldGFsLm9uOwogIEVtYmVyLmFkZExpc3RlbmVyID0gbWV0YWwuYWRkTGlzdGVuZXI7CiAgRW1iZXIucmVtb3ZlTGlzdGVuZXIgPSBtZXRhbC5yZW1vdmVMaXN0ZW5lcjsKICBFbWJlci5zZW5kRXZlbnQgPSBtZXRhbC5zZW5kRXZlbnQ7CiAgRW1iZXIuaGFzTGlzdGVuZXJzID0gbWV0YWwuaGFzTGlzdGVuZXJzOwogIEVtYmVyLmlzTm9uZSA9IG1ldGFsLmlzTm9uZTsKICBFbWJlci5pc0VtcHR5ID0gbWV0YWwuaXNFbXB0eTsKICBFbWJlci5pc0JsYW5rID0gbWV0YWwuaXNCbGFuazsKICBFbWJlci5pc1ByZXNlbnQgPSBtZXRhbC5pc1ByZXNlbnQ7CiAgRW1iZXIubm90aWZ5UHJvcGVydHlDaGFuZ2UgPSBtZXRhbC5ub3RpZnlQcm9wZXJ0eUNoYW5nZTsKICBFbWJlci5vdmVycmlkZUNoYWlucyA9IG1ldGFsLm92ZXJyaWRlQ2hhaW5zOwogIEVtYmVyLmJlZ2luUHJvcGVydHlDaGFuZ2VzID0gbWV0YWwuYmVnaW5Qcm9wZXJ0eUNoYW5nZXM7CiAgRW1iZXIuZW5kUHJvcGVydHlDaGFuZ2VzID0gbWV0YWwuZW5kUHJvcGVydHlDaGFuZ2VzOwogIEVtYmVyLmNoYW5nZVByb3BlcnRpZXMgPSBtZXRhbC5jaGFuZ2VQcm9wZXJ0aWVzOwogIEVtYmVyLnBsYXRmb3JtID0gewogICAgZGVmaW5lUHJvcGVydHk6IHRydWUsCiAgICBoYXNQcm9wZXJ0eUFjY2Vzc29yczogdHJ1ZQogIH07CiAgRW1iZXIuZGVmaW5lUHJvcGVydHkgPSBtZXRhbC5kZWZpbmVQcm9wZXJ0eTsKICBFbWJlci53YXRjaEtleSA9IG1ldGFsLndhdGNoS2V5OwogIEVtYmVyLnVud2F0Y2hLZXkgPSBtZXRhbC51bndhdGNoS2V5OwogIEVtYmVyLnJlbW92ZUNoYWluV2F0Y2hlciA9IG1ldGFsLnJlbW92ZUNoYWluV2F0Y2hlcjsKICBFbWJlci5fQ2hhaW5Ob2RlID0gbWV0YWwuQ2hhaW5Ob2RlOwogIEVtYmVyLmZpbmlzaENoYWlucyA9IG1ldGFsLmZpbmlzaENoYWluczsKICBFbWJlci53YXRjaFBhdGggPSBtZXRhbC53YXRjaFBhdGg7CiAgRW1iZXIudW53YXRjaFBhdGggPSBtZXRhbC51bndhdGNoUGF0aDsKICBFbWJlci53YXRjaCA9IG1ldGFsLndhdGNoOwogIEVtYmVyLmlzV2F0Y2hpbmcgPSBtZXRhbC5pc1dhdGNoaW5nOwogIEVtYmVyLnVud2F0Y2ggPSBtZXRhbC51bndhdGNoOwogIEVtYmVyLmRlc3Ryb3kgPSBfbWV0YS5kZWxldGVNZXRhOwogIEVtYmVyLmxpYnJhcmllcyA9IG1ldGFsLmxpYnJhcmllczsKICBFbWJlci5nZXRQcm9wZXJ0aWVzID0gbWV0YWwuZ2V0UHJvcGVydGllczsKICBFbWJlci5zZXRQcm9wZXJ0aWVzID0gbWV0YWwuc2V0UHJvcGVydGllczsKICBFbWJlci5leHBhbmRQcm9wZXJ0aWVzID0gbWV0YWwuZXhwYW5kUHJvcGVydGllczsKICBFbWJlci5hZGRPYnNlcnZlciA9IG1ldGFsLmFkZE9ic2VydmVyOwogIEVtYmVyLnJlbW92ZU9ic2VydmVyID0gbWV0YWwucmVtb3ZlT2JzZXJ2ZXI7CiAgRW1iZXIuYWxpYXNNZXRob2QgPSBtZXRhbC5hbGlhc01ldGhvZDsKICBFbWJlci5vYnNlcnZlciA9IG1ldGFsLm9ic2VydmVyOwogIEVtYmVyLm1peGluID0gbWV0YWwubWl4aW47CiAgRW1iZXIuTWl4aW4gPSBtZXRhbC5NaXhpbjsKICAvKioKICAgIEEgZnVuY3Rpb24gbWF5IGJlIGFzc2lnbmVkIHRvIGBFbWJlci5vbmVycm9yYCB0byBiZSBjYWxsZWQgd2hlbiBFbWJlcgogICAgaW50ZXJuYWxzIGVuY291bnRlciBhbiBlcnJvci4gVGhpcyBpcyB1c2VmdWwgZm9yIHNwZWNpYWxpemVkIGVycm9yIGhhbmRsaW5nCiAgICBhbmQgcmVwb3J0aW5nIGNvZGUuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgJCBmcm9tICdqcXVlcnknOwogIAogICAgRW1iZXIub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7CiAgICAgICQuYWpheCgnL3JlcG9ydC1lcnJvcicsICdQT1NUJywgewogICAgICAgIHN0YWNrOiBlcnJvci5zdGFjaywKICAgICAgICBvdGhlckluZm9ybWF0aW9uOiAnd2hhdGV2ZXIgYXBwIHN0YXRlIHlvdSB3YW50IHRvIHByb3ZpZGUnCiAgICAgIH0pOwogICAgfTsKICAgIGBgYAogIAogICAgSW50ZXJuYWxseSwgYEVtYmVyLm9uZXJyb3JgIGlzIHVzZWQgYXMgQmFja2J1cm5lcidzIGVycm9yIGhhbmRsZXIuCiAgCiAgICBAZXZlbnQgb25lcnJvcgogICAgQGZvciBFbWJlcgogICAgQHBhcmFtIHtFeGNlcHRpb259IGVycm9yIHRoZSBlcnJvciBvYmplY3QKICAgIEBwdWJsaWMKICAqLwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICdvbmVycm9yJywgewogICAgZ2V0OiBfZXJyb3JIYW5kbGluZy5nZXRPbmVycm9yLAogICAgc2V0OiBfZXJyb3JIYW5kbGluZy5zZXRPbmVycm9yLAogICAgZW51bWVyYWJsZTogZmFsc2UKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICd0ZXN0aW5nJywgewogICAgZ2V0OiBFbWJlckRlYnVnLmlzVGVzdGluZywKICAgIHNldDogRW1iZXJEZWJ1Zy5zZXRUZXN0aW5nLAogICAgZW51bWVyYWJsZTogZmFsc2UKICB9KTsKICBFbWJlci5fQmFja2J1cm5lciA9IF9iYWNrYnVybmVyLmRlZmF1bHQ7IC8vICoqKipAZW1iZXIvLWludGVybmFscy9jb25zb2xlKioqKgoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5MT0dHRVIpIHsKICAgIEVtYmVyLkxvZ2dlciA9IF9jb25zb2xlLmRlZmF1bHQ7CiAgfSAvLyAqKioqQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSoqKioKCgogIEVtYmVyLkEgPSBfcnVudGltZS5BOwogIEVtYmVyLlN0cmluZyA9IHsKICAgIGxvYzogX3N0cmluZy5sb2MsCiAgICB3OiBfc3RyaW5nLncsCiAgICBkYXNoZXJpemU6IF9zdHJpbmcuZGFzaGVyaXplLAogICAgZGVjYW1lbGl6ZTogX3N0cmluZy5kZWNhbWVsaXplLAogICAgY2FtZWxpemU6IF9zdHJpbmcuY2FtZWxpemUsCiAgICBjbGFzc2lmeTogX3N0cmluZy5jbGFzc2lmeSwKICAgIHVuZGVyc2NvcmU6IF9zdHJpbmcudW5kZXJzY29yZSwKICAgIGNhcGl0YWxpemU6IF9zdHJpbmcuY2FwaXRhbGl6ZQogIH07CiAgRW1iZXIuT2JqZWN0ID0gX3J1bnRpbWUuT2JqZWN0OwogIEVtYmVyLl9SZWdpc3RyeVByb3h5TWl4aW4gPSBfcnVudGltZS5SZWdpc3RyeVByb3h5TWl4aW47CiAgRW1iZXIuX0NvbnRhaW5lclByb3h5TWl4aW4gPSBfcnVudGltZS5Db250YWluZXJQcm94eU1peGluOwogIEVtYmVyLmNvbXBhcmUgPSBfcnVudGltZS5jb21wYXJlOwogIEVtYmVyLmNvcHkgPSBfcnVudGltZS5jb3B5OwogIEVtYmVyLmlzRXF1YWwgPSBfcnVudGltZS5pc0VxdWFsOwoKICBpZiAodHJ1ZQogIC8qIEVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQgKi8KICApIHsKICAgICAgRW1iZXIuX3NldEZyYW1ld29ya0NsYXNzID0gX3J1bnRpbWUuc2V0RnJhbWV3b3JrQ2xhc3M7CiAgICB9CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgTmFtZXNwYWNlIGZvciBpbmplY3Rpb24gaGVscGVyIG1ldGhvZHMuCiAgCiAgICBAY2xhc3MgaW5qZWN0CiAgICBAbmFtZXNwYWNlIEVtYmVyCiAgICBAc3RhdGljCiAgICBAcHVibGljCiAgKi8KCgogIEVtYmVyLmluamVjdCA9IGZ1bmN0aW9uIGluamVjdCgpIHsKICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgRW1iZXJEZWJ1Zy5hc3NlcnQpKCJJbmplY3RlZCBwcm9wZXJ0aWVzIG11c3QgYmUgY3JlYXRlZCB0aHJvdWdoIGhlbHBlcnMsIHNlZSAnIiArIE9iamVjdC5rZXlzKGluamVjdCkubWFwKGZ1bmN0aW9uIChrKSB7CiAgICAgIHJldHVybiAiJ2luamVjdC4iICsgayArICInIjsKICAgIH0pLmpvaW4oJyBvciAnKSArICInIikpOwogIH07CgogIEVtYmVyLmluamVjdC5zZXJ2aWNlID0gX3NlcnZpY2UuaW5qZWN0OwogIEVtYmVyLmluamVjdC5jb250cm9sbGVyID0gX2NvbnRyb2xsZXIuaW5qZWN0OwogIEVtYmVyLkFycmF5ID0gX3J1bnRpbWUuQXJyYXk7CiAgRW1iZXIuQ29tcGFyYWJsZSA9IF9ydW50aW1lLkNvbXBhcmFibGU7CiAgRW1iZXIuRW51bWVyYWJsZSA9IF9ydW50aW1lLkVudW1lcmFibGU7CiAgRW1iZXIuQXJyYXlQcm94eSA9IF9ydW50aW1lLkFycmF5UHJveHk7CiAgRW1iZXIuT2JqZWN0UHJveHkgPSBfcnVudGltZS5PYmplY3RQcm94eTsKICBFbWJlci5BY3Rpb25IYW5kbGVyID0gX3J1bnRpbWUuQWN0aW9uSGFuZGxlcjsKICBFbWJlci5Db3JlT2JqZWN0ID0gX3J1bnRpbWUuQ29yZU9iamVjdDsKICBFbWJlci5OYXRpdmVBcnJheSA9IF9ydW50aW1lLk5hdGl2ZUFycmF5OwogIEVtYmVyLkNvcHlhYmxlID0gX3J1bnRpbWUuQ29weWFibGU7CiAgRW1iZXIuTXV0YWJsZUVudW1lcmFibGUgPSBfcnVudGltZS5NdXRhYmxlRW51bWVyYWJsZTsKICBFbWJlci5NdXRhYmxlQXJyYXkgPSBfcnVudGltZS5NdXRhYmxlQXJyYXk7CiAgRW1iZXIuVGFyZ2V0QWN0aW9uU3VwcG9ydCA9IF9ydW50aW1lLlRhcmdldEFjdGlvblN1cHBvcnQ7CiAgRW1iZXIuRXZlbnRlZCA9IF9ydW50aW1lLkV2ZW50ZWQ7CiAgRW1iZXIuUHJvbWlzZVByb3h5TWl4aW4gPSBfcnVudGltZS5Qcm9taXNlUHJveHlNaXhpbjsKICBFbWJlci5PYnNlcnZhYmxlID0gX3J1bnRpbWUuT2JzZXJ2YWJsZTsKICBFbWJlci50eXBlT2YgPSBfcnVudGltZS50eXBlT2Y7CiAgRW1iZXIuaXNBcnJheSA9IF9ydW50aW1lLmlzQXJyYXk7CiAgRW1iZXIuT2JqZWN0ID0gX3J1bnRpbWUuT2JqZWN0OwogIEVtYmVyLm9uTG9hZCA9IF9hcHBsaWNhdGlvbi5vbkxvYWQ7CiAgRW1iZXIucnVuTG9hZEhvb2tzID0gX2FwcGxpY2F0aW9uLnJ1bkxvYWRIb29rczsKICBFbWJlci5Db250cm9sbGVyID0gX2NvbnRyb2xsZXIuZGVmYXVsdDsKICBFbWJlci5Db250cm9sbGVyTWl4aW4gPSBfY29udHJvbGxlcl9taXhpbi5kZWZhdWx0OwogIEVtYmVyLlNlcnZpY2UgPSBfc2VydmljZS5kZWZhdWx0OwogIEVtYmVyLl9Qcm94eU1peGluID0gX3J1bnRpbWUuX1Byb3h5TWl4aW47CiAgRW1iZXIuUlNWUCA9IF9ydW50aW1lLlJTVlA7CiAgRW1iZXIuTmFtZXNwYWNlID0gX3J1bnRpbWUuTmFtZXNwYWNlOwogIEVtYmVyLl9hY3Rpb24gPSBfb2JqZWN0LmFjdGlvbjsKICBFbWJlci5fZGVwZW5kZW50S2V5Q29tcGF0ID0gX2NvbXBhdC5kZXBlbmRlbnRLZXlDb21wYXQ7CiAgY29tcHV0ZWQuZW1wdHkgPSBfY29tcHV0ZWQuZW1wdHk7CiAgY29tcHV0ZWQubm90RW1wdHkgPSBfY29tcHV0ZWQubm90RW1wdHk7CiAgY29tcHV0ZWQubm9uZSA9IF9jb21wdXRlZC5ub25lOwogIGNvbXB1dGVkLm5vdCA9IF9jb21wdXRlZC5ub3Q7CiAgY29tcHV0ZWQuYm9vbCA9IF9jb21wdXRlZC5ib29sOwogIGNvbXB1dGVkLm1hdGNoID0gX2NvbXB1dGVkLm1hdGNoOwogIGNvbXB1dGVkLmVxdWFsID0gX2NvbXB1dGVkLmVxdWFsOwogIGNvbXB1dGVkLmd0ID0gX2NvbXB1dGVkLmd0OwogIGNvbXB1dGVkLmd0ZSA9IF9jb21wdXRlZC5ndGU7CiAgY29tcHV0ZWQubHQgPSBfY29tcHV0ZWQubHQ7CiAgY29tcHV0ZWQubHRlID0gX2NvbXB1dGVkLmx0ZTsKICBjb21wdXRlZC5vbmVXYXkgPSBfY29tcHV0ZWQub25lV2F5OwogIGNvbXB1dGVkLnJlYWRzID0gX2NvbXB1dGVkLm9uZVdheTsKICBjb21wdXRlZC5yZWFkT25seSA9IF9jb21wdXRlZC5yZWFkT25seTsKICBjb21wdXRlZC5kZXByZWNhdGluZ0FsaWFzID0gX2NvbXB1dGVkLmRlcHJlY2F0aW5nQWxpYXM7CiAgY29tcHV0ZWQuYW5kID0gX2NvbXB1dGVkLmFuZDsKICBjb21wdXRlZC5vciA9IF9jb21wdXRlZC5vcjsKICBjb21wdXRlZC5zdW0gPSBfY29tcHV0ZWQuc3VtOwogIGNvbXB1dGVkLm1pbiA9IF9jb21wdXRlZC5taW47CiAgY29tcHV0ZWQubWF4ID0gX2NvbXB1dGVkLm1heDsKICBjb21wdXRlZC5tYXAgPSBfY29tcHV0ZWQubWFwOwogIGNvbXB1dGVkLnNvcnQgPSBfY29tcHV0ZWQuc29ydDsKICBjb21wdXRlZC5zZXREaWZmID0gX2NvbXB1dGVkLnNldERpZmY7CiAgY29tcHV0ZWQubWFwQnkgPSBfY29tcHV0ZWQubWFwQnk7CiAgY29tcHV0ZWQuZmlsdGVyID0gX2NvbXB1dGVkLmZpbHRlcjsKICBjb21wdXRlZC5maWx0ZXJCeSA9IF9jb21wdXRlZC5maWx0ZXJCeTsKICBjb21wdXRlZC51bmlxID0gX2NvbXB1dGVkLnVuaXE7CiAgY29tcHV0ZWQudW5pcUJ5ID0gX2NvbXB1dGVkLnVuaXFCeTsKICBjb21wdXRlZC51bmlvbiA9IF9jb21wdXRlZC51bmlvbjsKICBjb21wdXRlZC5pbnRlcnNlY3QgPSBfY29tcHV0ZWQuaW50ZXJzZWN0OwogIGNvbXB1dGVkLmNvbGxlY3QgPSBfY29tcHV0ZWQuY29sbGVjdDsKICAvKioKICAgIERlZmluZXMgdGhlIGhhc2ggb2YgbG9jYWxpemVkIHN0cmluZ3MgZm9yIHRoZSBjdXJyZW50IGxhbmd1YWdlLiBVc2VkIGJ5CiAgICB0aGUgYFN0cmluZy5sb2NgIGhlbHBlci4gVG8gbG9jYWxpemUsIGFkZCBzdHJpbmcgdmFsdWVzIHRvIHRoaXMKICAgIGhhc2guCiAgCiAgICBAcHJvcGVydHkgU1RSSU5HUwogICAgQGZvciBFbWJlcgogICAgQHR5cGUgT2JqZWN0CiAgICBAcHJpdmF0ZQogICovCgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFbWJlciwgJ1NUUklOR1MnLCB7CiAgICBjb25maWd1cmFibGU6IGZhbHNlLAogICAgZ2V0OiBfc3RyaW5nLl9nZXRTdHJpbmdzLAogICAgc2V0OiBfc3RyaW5nLl9zZXRTdHJpbmdzCiAgfSk7CiAgLyoqCiAgICBXaGV0aGVyIHNlYXJjaGluZyBvbiB0aGUgZ2xvYmFsIGZvciBuZXcgTmFtZXNwYWNlIGluc3RhbmNlcyBpcyBlbmFibGVkLgogIAogICAgVGhpcyBpcyBvbmx5IGV4cG9ydGVkIGhlcmUgYXMgdG8gbm90IGJyZWFrIGFueSBhZGRvbnMuICBHaXZlbiB0aGUgbmV3CiAgICB2aXNpdCBBUEksIHlvdSB3aWxsIGhhdmUgaXNzdWVzIGlmIHlvdSB0cmVhdCB0aGlzIGFzIGEgaW5kaWNhdG9yIG9mCiAgICBib290ZWQuCiAgCiAgICBJbnRlcm5hbGx5IHRoaXMgaXMgb25seSBleHBvc2luZyBhIGZsYWcgaW4gTmFtZXNwYWNlLgogIAogICAgQHByb3BlcnR5IEJPT1RFRAogICAgQGZvciBFbWJlcgogICAgQHR5cGUgQm9vbGVhbgogICAgQHByaXZhdGUKICAqLwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICdCT09URUQnLCB7CiAgICBjb25maWd1cmFibGU6IGZhbHNlLAogICAgZW51bWVyYWJsZTogZmFsc2UsCiAgICBnZXQ6IG1ldGFsLmlzTmFtZXNwYWNlU2VhcmNoRGlzYWJsZWQsCiAgICBzZXQ6IG1ldGFsLnNldE5hbWVzcGFjZVNlYXJjaERpc2FibGVkCiAgfSk7IC8vICoqKipAZW1iZXIvLWludGVybmFscy9nbGltbWVyKioqKgoKICBFbWJlci5Db21wb25lbnQgPSBfZ2xpbW1lci5Db21wb25lbnQ7CiAgX2dsaW1tZXIuSGVscGVyLmhlbHBlciA9IF9nbGltbWVyLmhlbHBlcjsKICBFbWJlci5IZWxwZXIgPSBfZ2xpbW1lci5IZWxwZXI7CiAgRW1iZXIuQ2hlY2tib3ggPSBfZ2xpbW1lci5DaGVja2JveDsKICBFbWJlci5UZXh0RmllbGQgPSBfZ2xpbW1lci5UZXh0RmllbGQ7CiAgRW1iZXIuVGV4dEFyZWEgPSBfZ2xpbW1lci5UZXh0QXJlYTsKICBFbWJlci5MaW5rQ29tcG9uZW50ID0gX2dsaW1tZXIuTGlua0NvbXBvbmVudDsKICBFbWJlci5fc2V0Q29tcG9uZW50TWFuYWdlciA9IF9nbGltbWVyLnNldENvbXBvbmVudE1hbmFnZXI7CiAgRW1iZXIuX2NvbXBvbmVudE1hbmFnZXJDYXBhYmlsaXRpZXMgPSBfZ2xpbW1lci5jYXBhYmlsaXRpZXM7CiAgRW1iZXIuX3NldE1vZGlmaWVyTWFuYWdlciA9IF9nbGltbWVyLnNldE1vZGlmaWVyTWFuYWdlcjsKICBFbWJlci5fbW9kaWZpZXJNYW5hZ2VyQ2FwYWJpbGl0aWVzID0gX2dsaW1tZXIubW9kaWZpZXJDYXBhYmlsaXRpZXM7CgogIGlmICh0cnVlCiAgLyogRU1CRVJfR0xJTU1FUl9TRVRfQ09NUE9ORU5UX1RFTVBMQVRFICovCiAgKSB7CiAgICAgIEVtYmVyLl9nZXRDb21wb25lbnRUZW1wbGF0ZSA9IF9nbGltbWVyLmdldENvbXBvbmVudFRlbXBsYXRlOwogICAgICBFbWJlci5fc2V0Q29tcG9uZW50VGVtcGxhdGUgPSBfZ2xpbW1lci5zZXRDb21wb25lbnRUZW1wbGF0ZTsKICAgICAgRW1iZXIuX3RlbXBsYXRlT25seUNvbXBvbmVudCA9IF90ZW1wbGF0ZU9ubHkuZGVmYXVsdDsKICAgIH0KCiAgRW1iZXIuSGFuZGxlYmFycyA9IHsKICAgIHRlbXBsYXRlOiBfZ2xpbW1lci50ZW1wbGF0ZSwKICAgIFV0aWxzOiB7CiAgICAgIGVzY2FwZUV4cHJlc3Npb246IF9nbGltbWVyLmVzY2FwZUV4cHJlc3Npb24KICAgIH0KICB9OwogIEVtYmVyLkhUTUxCYXJzID0gewogICAgdGVtcGxhdGU6IF9nbGltbWVyLnRlbXBsYXRlCiAgfTsKCiAgaWYgKF9lbnZpcm9ubWVudC5FTlYuRVhURU5EX1BST1RPVFlQRVMuU3RyaW5nKSB7CiAgICBTdHJpbmcucHJvdG90eXBlLmh0bWxTYWZlID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gKDAsIF9nbGltbWVyLmh0bWxTYWZlKSh0aGlzKTsKICAgIH07CiAgfQoKICBFbWJlci5TdHJpbmcuaHRtbFNhZmUgPSBfZ2xpbW1lci5odG1sU2FmZTsKICBFbWJlci5TdHJpbmcuaXNIVE1MU2FmZSA9IF9nbGltbWVyLmlzSFRNTFNhZmU7CiAgLyoqCiAgICBHbG9iYWwgaGFzaCBvZiBzaGFyZWQgdGVtcGxhdGVzLiBUaGlzIHdpbGwgYXV0b21hdGljYWxseSBiZSBwb3B1bGF0ZWQKICAgIGJ5IHRoZSBidWlsZCB0b29scyBzbyB0aGF0IHlvdSBjYW4gc3RvcmUgeW91ciBIYW5kbGViYXJzIHRlbXBsYXRlcyBpbgogICAgc2VwYXJhdGUgZmlsZXMgdGhhdCBnZXQgbG9hZGVkIGludG8gSmF2YVNjcmlwdCBhdCBidWlsZHRpbWUuCiAgCiAgICBAcHJvcGVydHkgVEVNUExBVEVTCiAgICBAZm9yIEVtYmVyCiAgICBAdHlwZSBPYmplY3QKICAgIEBwcml2YXRlCiAgKi8KCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEVtYmVyLCAnVEVNUExBVEVTJywgewogICAgZ2V0OiBfZ2xpbW1lci5nZXRUZW1wbGF0ZXMsCiAgICBzZXQ6IF9nbGltbWVyLnNldFRlbXBsYXRlcywKICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsCiAgICBlbnVtZXJhYmxlOiBmYWxzZQogIH0pOwogIC8qKgogICAgVGhlIHNlbWFudGljIHZlcnNpb24KICAKICAgIEBwcm9wZXJ0eSBWRVJTSU9OCiAgICBAdHlwZSBTdHJpbmcKICAgIEBwdWJsaWMKICAqLwoKICBFbWJlci5WRVJTSU9OID0gX3ZlcnNpb24uZGVmYXVsdDsgLy8gKioqKkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzKioqKgoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5KUVVFUllfSU5URUdSQVRJT04gJiYgIXZpZXdzLmpRdWVyeURpc2FibGVkKSB7CiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICckJywgewogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIEVtYmVyRGVidWcuZGVwcmVjYXRlKSgiVXNpbmcgRW1iZXIuJCgpIGhhcyBiZWVuIGRlcHJlY2F0ZWQsIHVzZSBgaW1wb3J0IGpRdWVyeSBmcm9tICdqcXVlcnknO2AgaW5zdGVhZCIsIGZhbHNlLCB7CiAgICAgICAgICBpZDogJ2VtYmVyLXZpZXdzLmN1cmx5LWNvbXBvbmVudHMuanF1ZXJ5LWVsZW1lbnQnLAogICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY19qcXVlcnktYXBpcycKICAgICAgICB9KSk7CiAgICAgICAgcmV0dXJuIHZpZXdzLmpRdWVyeTsKICAgICAgfSwKICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICBlbnVtZXJhYmxlOiB0cnVlCiAgICB9KTsKICB9CgogIEVtYmVyLlZpZXdVdGlscyA9IHsKICAgIGlzU2ltcGxlQ2xpY2s6IHZpZXdzLmlzU2ltcGxlQ2xpY2ssCiAgICBnZXRFbGVtZW50Vmlldzogdmlld3MuZ2V0RWxlbWVudFZpZXcsCiAgICBnZXRWaWV3RWxlbWVudDogdmlld3MuZ2V0Vmlld0VsZW1lbnQsCiAgICBnZXRWaWV3Qm91bmRzOiB2aWV3cy5nZXRWaWV3Qm91bmRzLAogICAgZ2V0Vmlld0NsaWVudFJlY3RzOiB2aWV3cy5nZXRWaWV3Q2xpZW50UmVjdHMsCiAgICBnZXRWaWV3Qm91bmRpbmdDbGllbnRSZWN0OiB2aWV3cy5nZXRWaWV3Qm91bmRpbmdDbGllbnRSZWN0LAogICAgZ2V0Um9vdFZpZXdzOiB2aWV3cy5nZXRSb290Vmlld3MsCiAgICBnZXRDaGlsZFZpZXdzOiB2aWV3cy5nZXRDaGlsZFZpZXdzLAogICAgaXNTZXJpYWxpemF0aW9uRmlyc3ROb2RlOiBfZ2xpbW1lci5pc1NlcmlhbGl6YXRpb25GaXJzdE5vZGUKICB9OwogIEVtYmVyLlRleHRTdXBwb3J0ID0gdmlld3MuVGV4dFN1cHBvcnQ7CiAgRW1iZXIuQ29tcG9uZW50TG9va3VwID0gdmlld3MuQ29tcG9uZW50TG9va3VwOwogIEVtYmVyLkV2ZW50RGlzcGF0Y2hlciA9IHZpZXdzLkV2ZW50RGlzcGF0Y2hlcjsgLy8gKioqKkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcqKioqCgogIEVtYmVyLkxvY2F0aW9uID0gcm91dGluZy5Mb2NhdGlvbjsKICBFbWJlci5BdXRvTG9jYXRpb24gPSByb3V0aW5nLkF1dG9Mb2NhdGlvbjsKICBFbWJlci5IYXNoTG9jYXRpb24gPSByb3V0aW5nLkhhc2hMb2NhdGlvbjsKICBFbWJlci5IaXN0b3J5TG9jYXRpb24gPSByb3V0aW5nLkhpc3RvcnlMb2NhdGlvbjsKICBFbWJlci5Ob25lTG9jYXRpb24gPSByb3V0aW5nLk5vbmVMb2NhdGlvbjsKICBFbWJlci5jb250cm9sbGVyRm9yID0gcm91dGluZy5jb250cm9sbGVyRm9yOwogIEVtYmVyLmdlbmVyYXRlQ29udHJvbGxlckZhY3RvcnkgPSByb3V0aW5nLmdlbmVyYXRlQ29udHJvbGxlckZhY3Rvcnk7CiAgRW1iZXIuZ2VuZXJhdGVDb250cm9sbGVyID0gcm91dGluZy5nZW5lcmF0ZUNvbnRyb2xsZXI7CiAgRW1iZXIuUm91dGVyRFNMID0gcm91dGluZy5Sb3V0ZXJEU0w7CiAgRW1iZXIuUm91dGVyID0gcm91dGluZy5Sb3V0ZXI7CiAgRW1iZXIuUm91dGUgPSByb3V0aW5nLlJvdXRlOwogICgwLCBfYXBwbGljYXRpb24ucnVuTG9hZEhvb2tzKSgnRW1iZXIuQXBwbGljYXRpb24nLCBfYXBwbGljYXRpb24uZGVmYXVsdCk7CiAgRW1iZXIuRGF0YUFkYXB0ZXIgPSBleHRlbnNpb25TdXBwb3J0LkRhdGFBZGFwdGVyOwogIEVtYmVyLkNvbnRhaW5lckRlYnVnQWRhcHRlciA9IGV4dGVuc2lvblN1cHBvcnQuQ29udGFpbmVyRGVidWdBZGFwdGVyOwoKICBpZiAoKDAsIF9yZXF1aXJlLmhhcykoJ2VtYmVyLXRlbXBsYXRlLWNvbXBpbGVyJykpIHsKICAgICgwLCBfcmVxdWlyZS5kZWZhdWx0KSgiZW1iZXItdGVtcGxhdGUtY29tcGlsZXIiKTsKICB9IC8vIGRvIHRoaXMgdG8gZW5zdXJlIHRoYXQgRW1iZXIuVGVzdCBpcyBkZWZpbmVkIHByb3Blcmx5IG9uIHRoZSBnbG9iYWwKICAvLyBpZiBpdCBpcyBwcmVzZW50LgoKCiAgaWYgKCgwLCBfcmVxdWlyZS5oYXMpKCdlbWJlci10ZXN0aW5nJykpIHsKICAgIHZhciB0ZXN0aW5nID0gKDAsIF9yZXF1aXJlLmRlZmF1bHQpKCJlbWJlci10ZXN0aW5nIik7CiAgICBFbWJlci5UZXN0ID0gdGVzdGluZy5UZXN0OwogICAgRW1iZXIuVGVzdC5BZGFwdGVyID0gdGVzdGluZy5BZGFwdGVyOwogICAgRW1iZXIuVGVzdC5RVW5pdEFkYXB0ZXIgPSB0ZXN0aW5nLlFVbml0QWRhcHRlcjsKICAgIEVtYmVyLnNldHVwRm9yVGVzdGluZyA9IHRlc3Rpbmcuc2V0dXBGb3JUZXN0aW5nOwogIH0KCiAgKDAsIF9hcHBsaWNhdGlvbi5ydW5Mb2FkSG9va3MpKCdFbWJlcicpOwogIHZhciBfZGVmYXVsdCA9IEVtYmVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKCiAgaWYgKF9ub2RlTW9kdWxlLklTX05PREUpIHsKICAgIF9ub2RlTW9kdWxlLm1vZHVsZS5leHBvcnRzID0gRW1iZXI7CiAgfSBlbHNlIHsKICAgIF9lbnZpcm9ubWVudC5jb250ZXh0LmV4cG9ydHMuRW1iZXIgPSBfZW52aXJvbm1lbnQuY29udGV4dC5leHBvcnRzLkVtID0gRW1iZXI7CiAgfQogIC8qKgogICBAbW9kdWxlIGpxdWVyeQogICBAcHVibGljCiAgICovCgogIC8qKgogICBAY2xhc3MganF1ZXJ5CiAgIEBwdWJsaWMKICAgQHN0YXRpYwogICAqLwoKICAvKioKICAgIEFsaWFzIGZvciBqUXVlcnkKICAKICAgIEBmb3IganF1ZXJ5CiAgICBAbWV0aG9kICQKICAgIEBzdGF0aWMKICAgIEBwdWJsaWMKICAqLwoKfSk7CmRlZmluZSgiZW1iZXIvdmVyc2lvbiIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CiAgdmFyIF9kZWZhdWx0ID0gIjMuMTMuMyI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJub2RlLW1vZHVsZS9pbmRleCIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLnJlcXVpcmUgPSBfZXhwb3J0cy5tb2R1bGUgPSBfZXhwb3J0cy5JU19OT0RFID0gdm9pZCAwOwoKICAvKmdsb2JhbCBtb2R1bGUgKi8KICB2YXIgSVNfTk9ERSA9IHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUucmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJzsKICBfZXhwb3J0cy5JU19OT0RFID0gSVNfTk9ERTsKICB2YXIgZXhwb3J0TW9kdWxlOwogIF9leHBvcnRzLm1vZHVsZSA9IGV4cG9ydE1vZHVsZTsKICB2YXIgZXhwb3J0UmVxdWlyZTsKICBfZXhwb3J0cy5yZXF1aXJlID0gZXhwb3J0UmVxdWlyZTsKCiAgaWYgKElTX05PREUpIHsKICAgIF9leHBvcnRzLm1vZHVsZSA9IGV4cG9ydE1vZHVsZSA9IG1vZHVsZTsKICAgIF9leHBvcnRzLnJlcXVpcmUgPSBleHBvcnRSZXF1aXJlID0gbW9kdWxlLnJlcXVpcmU7CiAgfSBlbHNlIHsKICAgIF9leHBvcnRzLm1vZHVsZSA9IGV4cG9ydE1vZHVsZSA9IG51bGw7CiAgICBfZXhwb3J0cy5yZXF1aXJlID0gZXhwb3J0UmVxdWlyZSA9IG51bGw7CiAgfQp9KTsKZGVmaW5lKCJyb3V0ZS1yZWNvZ25pemVyIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKICB2YXIgY3JlYXRlT2JqZWN0ID0gT2JqZWN0LmNyZWF0ZTsKCiAgZnVuY3Rpb24gY3JlYXRlTWFwKCkgewogICAgdmFyIG1hcCA9IGNyZWF0ZU9iamVjdChudWxsKTsKICAgIG1hcFsiX18iXSA9IHVuZGVmaW5lZDsKICAgIGRlbGV0ZSBtYXBbIl9fIl07CiAgICByZXR1cm4gbWFwOwogIH0KCiAgdmFyIFRhcmdldCA9IGZ1bmN0aW9uIFRhcmdldChwYXRoLCBtYXRjaGVyLCBkZWxlZ2F0ZSkgewogICAgdGhpcy5wYXRoID0gcGF0aDsKICAgIHRoaXMubWF0Y2hlciA9IG1hdGNoZXI7CiAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7CiAgfTsKCiAgVGFyZ2V0LnByb3RvdHlwZS50byA9IGZ1bmN0aW9uIHRvKHRhcmdldCwgY2FsbGJhY2spIHsKICAgIHZhciBkZWxlZ2F0ZSA9IHRoaXMuZGVsZWdhdGU7CgogICAgaWYgKGRlbGVnYXRlICYmIGRlbGVnYXRlLndpbGxBZGRSb3V0ZSkgewogICAgICB0YXJnZXQgPSBkZWxlZ2F0ZS53aWxsQWRkUm91dGUodGhpcy5tYXRjaGVyLnRhcmdldCwgdGFyZ2V0KTsKICAgIH0KCiAgICB0aGlzLm1hdGNoZXIuYWRkKHRoaXMucGF0aCwgdGFyZ2V0KTsKCiAgICBpZiAoY2FsbGJhY2spIHsKICAgICAgaWYgKGNhbGxiYWNrLmxlbmd0aCA9PT0gMCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiWW91IG11c3QgaGF2ZSBhbiBhcmd1bWVudCBpbiB0aGUgZnVuY3Rpb24gcGFzc2VkIHRvIGB0b2AiKTsKICAgICAgfQoKICAgICAgdGhpcy5tYXRjaGVyLmFkZENoaWxkKHRoaXMucGF0aCwgdGFyZ2V0LCBjYWxsYmFjaywgdGhpcy5kZWxlZ2F0ZSk7CiAgICB9CiAgfTsKCiAgdmFyIE1hdGNoZXIgPSBmdW5jdGlvbiBNYXRjaGVyKHRhcmdldCkgewogICAgdGhpcy5yb3V0ZXMgPSBjcmVhdGVNYXAoKTsKICAgIHRoaXMuY2hpbGRyZW4gPSBjcmVhdGVNYXAoKTsKICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0OwogIH07CgogIE1hdGNoZXIucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uIGFkZChwYXRoLCB0YXJnZXQpIHsKICAgIHRoaXMucm91dGVzW3BhdGhdID0gdGFyZ2V0OwogIH07CgogIE1hdGNoZXIucHJvdG90eXBlLmFkZENoaWxkID0gZnVuY3Rpb24gYWRkQ2hpbGQocGF0aCwgdGFyZ2V0LCBjYWxsYmFjaywgZGVsZWdhdGUpIHsKICAgIHZhciBtYXRjaGVyID0gbmV3IE1hdGNoZXIodGFyZ2V0KTsKICAgIHRoaXMuY2hpbGRyZW5bcGF0aF0gPSBtYXRjaGVyOwogICAgdmFyIG1hdGNoID0gZ2VuZXJhdGVNYXRjaChwYXRoLCBtYXRjaGVyLCBkZWxlZ2F0ZSk7CgogICAgaWYgKGRlbGVnYXRlICYmIGRlbGVnYXRlLmNvbnRleHRFbnRlcmVkKSB7CiAgICAgIGRlbGVnYXRlLmNvbnRleHRFbnRlcmVkKHRhcmdldCwgbWF0Y2gpOwogICAgfQoKICAgIGNhbGxiYWNrKG1hdGNoKTsKICB9OwoKICBmdW5jdGlvbiBnZW5lcmF0ZU1hdGNoKHN0YXJ0aW5nUGF0aCwgbWF0Y2hlciwgZGVsZWdhdGUpIHsKICAgIGZ1bmN0aW9uIG1hdGNoKHBhdGgsIGNhbGxiYWNrKSB7CiAgICAgIHZhciBmdWxsUGF0aCA9IHN0YXJ0aW5nUGF0aCArIHBhdGg7CgogICAgICBpZiAoY2FsbGJhY2spIHsKICAgICAgICBjYWxsYmFjayhnZW5lcmF0ZU1hdGNoKGZ1bGxQYXRoLCBtYXRjaGVyLCBkZWxlZ2F0ZSkpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBuZXcgVGFyZ2V0KGZ1bGxQYXRoLCBtYXRjaGVyLCBkZWxlZ2F0ZSk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gbWF0Y2g7CiAgfQoKICBmdW5jdGlvbiBhZGRSb3V0ZShyb3V0ZUFycmF5LCBwYXRoLCBoYW5kbGVyKSB7CiAgICB2YXIgbGVuID0gMDsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvdXRlQXJyYXkubGVuZ3RoOyBpKyspIHsKICAgICAgbGVuICs9IHJvdXRlQXJyYXlbaV0ucGF0aC5sZW5ndGg7CiAgICB9CgogICAgcGF0aCA9IHBhdGguc3Vic3RyKGxlbik7CiAgICB2YXIgcm91dGUgPSB7CiAgICAgIHBhdGg6IHBhdGgsCiAgICAgIGhhbmRsZXI6IGhhbmRsZXIKICAgIH07CiAgICByb3V0ZUFycmF5LnB1c2gocm91dGUpOwogIH0KCiAgZnVuY3Rpb24gZWFjaFJvdXRlKGJhc2VSb3V0ZSwgbWF0Y2hlciwgY2FsbGJhY2ssIGJpbmRpbmcpIHsKICAgIHZhciByb3V0ZXMgPSBtYXRjaGVyLnJvdXRlczsKICAgIHZhciBwYXRocyA9IE9iamVjdC5rZXlzKHJvdXRlcyk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRocy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgcGF0aCA9IHBhdGhzW2ldOwogICAgICB2YXIgcm91dGVBcnJheSA9IGJhc2VSb3V0ZS5zbGljZSgpOwogICAgICBhZGRSb3V0ZShyb3V0ZUFycmF5LCBwYXRoLCByb3V0ZXNbcGF0aF0pOwogICAgICB2YXIgbmVzdGVkID0gbWF0Y2hlci5jaGlsZHJlbltwYXRoXTsKCiAgICAgIGlmIChuZXN0ZWQpIHsKICAgICAgICBlYWNoUm91dGUocm91dGVBcnJheSwgbmVzdGVkLCBjYWxsYmFjaywgYmluZGluZyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY2FsbGJhY2suY2FsbChiaW5kaW5nLCByb3V0ZUFycmF5KTsKICAgICAgfQogICAgfQogIH0KCiAgdmFyIG1hcCA9IGZ1bmN0aW9uIG1hcChjYWxsYmFjaywgYWRkUm91dGVDYWxsYmFjaykgewogICAgdmFyIG1hdGNoZXIgPSBuZXcgTWF0Y2hlcigpOwogICAgY2FsbGJhY2soZ2VuZXJhdGVNYXRjaCgiIiwgbWF0Y2hlciwgdGhpcy5kZWxlZ2F0ZSkpOwogICAgZWFjaFJvdXRlKFtdLCBtYXRjaGVyLCBmdW5jdGlvbiAocm91dGVzKSB7CiAgICAgIGlmIChhZGRSb3V0ZUNhbGxiYWNrKSB7CiAgICAgICAgYWRkUm91dGVDYWxsYmFjayh0aGlzLCByb3V0ZXMpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuYWRkKHJvdXRlcyk7CiAgICAgIH0KICAgIH0sIHRoaXMpOwogIH07IC8vIE5vcm1hbGl6ZXMgcGVyY2VudC1lbmNvZGVkIHZhbHVlcyBpbiBgcGF0aGAgdG8gdXBwZXItY2FzZSBhbmQgZGVjb2RlcyBwZXJjZW50LWVuY29kZWQKICAvLyB2YWx1ZXMgdGhhdCBhcmUgbm90IHJlc2VydmVkIChpLmUuLCB1bmljb2RlIGNoYXJhY3RlcnMsIGVtb2ppLCBldGMpLiBUaGUgcmVzZXJ2ZWQKICAvLyBjaGFycyBhcmUgIi8iIGFuZCAiJSIuCiAgLy8gU2FmZSB0byBjYWxsIG11bHRpcGxlIHRpbWVzIG9uIHRoZSBzYW1lIHBhdGguCiAgLy8gTm9ybWFsaXplcyBwZXJjZW50LWVuY29kZWQgdmFsdWVzIGluIGBwYXRoYCB0byB1cHBlci1jYXNlIGFuZCBkZWNvZGVzIHBlcmNlbnQtZW5jb2RlZAoKCiAgZnVuY3Rpb24gbm9ybWFsaXplUGF0aChwYXRoKSB7CiAgICByZXR1cm4gcGF0aC5zcGxpdCgiLyIpLm1hcChub3JtYWxpemVTZWdtZW50KS5qb2luKCIvIik7CiAgfSAvLyBXZSB3YW50IHRvIGVuc3VyZSB0aGUgY2hhcmFjdGVycyAiJSIgYW5kICIvIiByZW1haW4gaW4gcGVyY2VudC1lbmNvZGVkCiAgLy8gZm9ybSB3aGVuIG5vcm1hbGl6aW5nIHBhdGhzLCBzbyByZXBsYWNlIHRoZW0gd2l0aCB0aGVpciBlbmNvZGVkIGZvcm0gYWZ0ZXIKICAvLyBkZWNvZGluZyB0aGUgcmVzdCBvZiB0aGUgcGF0aAoKCiAgdmFyIFNFR01FTlRfUkVTRVJWRURfQ0hBUlMgPSAvJXxcLy9nOwoKICBmdW5jdGlvbiBub3JtYWxpemVTZWdtZW50KHNlZ21lbnQpIHsKICAgIGlmIChzZWdtZW50Lmxlbmd0aCA8IDMgfHwgc2VnbWVudC5pbmRleE9mKCIlIikgPT09IC0xKSB7CiAgICAgIHJldHVybiBzZWdtZW50OwogICAgfQoKICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQoc2VnbWVudCkucmVwbGFjZShTRUdNRU5UX1JFU0VSVkVEX0NIQVJTLCBlbmNvZGVVUklDb21wb25lbnQpOwogIH0gLy8gV2UgZG8gbm90IHdhbnQgdG8gZW5jb2RlIHRoZXNlIGNoYXJhY3RlcnMgd2hlbiBnZW5lcmF0aW5nIGR5bmFtaWMgcGF0aCBzZWdtZW50cwogIC8vIFNlZSBodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjMzk4NiNzZWN0aW9uLTMuMwogIC8vIHN1Yi1kZWxpbXM6ICIhIiwgIiQiLCAiJiIsICInIiwgIigiLCAiKSIsICIqIiwgIisiLCAiLCIsICI7IiwgIj0iCiAgLy8gb3RoZXJzIGFsbG93ZWQgYnkgUkZDIDM5ODY6ICI6IiwgIkAiCiAgLy8KICAvLyBGaXJzdCBlbmNvZGUgdGhlIGVudGlyZSBwYXRoIHNlZ21lbnQsIHRoZW4gZGVjb2RlIGFueSBvZiB0aGUgZW5jb2RlZCBzcGVjaWFsIGNoYXJzLgogIC8vCiAgLy8gVGhlIGNoYXJzICIhIiwgIiciLCAiKCIsICIpIiwgIioiIGRvIG5vdCBnZXQgY2hhbmdlZCBieSBgZW5jb2RlVVJJQ29tcG9uZW50YCwKICAvLyBzbyB0aGUgcG9zc2libGUgZW5jb2RlZCBjaGFycyBhcmU6CiAgLy8gWyclMjQnLCAnJTI2JywgJyUyQicsICclMkMnLCAnJTNCJywgJyUzRCcsICclM0EnLCAnJTQwJ10uCgoKICB2YXIgUEFUSF9TRUdNRU5UX0VOQ09ESU5HUyA9IC8lKD86Mig/OjR8NnxCfEMpfDMoPzpCfER8QSl8NDApL2c7CgogIGZ1bmN0aW9uIGVuY29kZVBhdGhTZWdtZW50KHN0cikgewogICAgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoUEFUSF9TRUdNRU5UX0VOQ09ESU5HUywgZGVjb2RlVVJJQ29tcG9uZW50KTsKICB9CgogIHZhciBlc2NhcGVSZWdleCA9IC8oXC98XC58XCp8XCt8XD98XHx8XCh8XCl8XFt8XF18XHt8XH18XFwpL2c7CiAgdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5OwogIHZhciBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7CgogIGZ1bmN0aW9uIGdldFBhcmFtKHBhcmFtcywga2V5KSB7CiAgICBpZiAodHlwZW9mIHBhcmFtcyAhPT0gIm9iamVjdCIgfHwgcGFyYW1zID09PSBudWxsKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiWW91IG11c3QgcGFzcyBhbiBvYmplY3QgYXMgdGhlIHNlY29uZCBhcmd1bWVudCB0byBgZ2VuZXJhdGVgLiIpOwogICAgfQoKICAgIGlmICghaGFzT3duUHJvcGVydHkuY2FsbChwYXJhbXMsIGtleSkpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJZb3UgbXVzdCBwcm92aWRlIHBhcmFtIGAiICsga2V5ICsgImAgdG8gYGdlbmVyYXRlYC4iKTsKICAgIH0KCiAgICB2YXIgdmFsdWUgPSBwYXJhbXNba2V5XTsKICAgIHZhciBzdHIgPSB0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciID8gdmFsdWUgOiAiIiArIHZhbHVlOwoKICAgIGlmIChzdHIubGVuZ3RoID09PSAwKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiWW91IG11c3QgcHJvdmlkZSBhIHBhcmFtIGAiICsga2V5ICsgImAuIik7CiAgICB9CgogICAgcmV0dXJuIHN0cjsKICB9CgogIHZhciBlYWNoQ2hhciA9IFtdOwoKICBlYWNoQ2hhclswCiAgLyogU3RhdGljICovCiAgXSA9IGZ1bmN0aW9uIChzZWdtZW50LCBjdXJyZW50U3RhdGUpIHsKICAgIHZhciBzdGF0ZSA9IGN1cnJlbnRTdGF0ZTsKICAgIHZhciB2YWx1ZSA9IHNlZ21lbnQudmFsdWU7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWx1ZS5sZW5ndGg7IGkrKykgewogICAgICB2YXIgY2ggPSB2YWx1ZS5jaGFyQ29kZUF0KGkpOwogICAgICBzdGF0ZSA9IHN0YXRlLnB1dChjaCwgZmFsc2UsIGZhbHNlKTsKICAgIH0KCiAgICByZXR1cm4gc3RhdGU7CiAgfTsKCiAgZWFjaENoYXJbMQogIC8qIER5bmFtaWMgKi8KICBdID0gZnVuY3Rpb24gKF8sIGN1cnJlbnRTdGF0ZSkgewogICAgcmV0dXJuIGN1cnJlbnRTdGF0ZS5wdXQoNDcKICAgIC8qIFNMQVNIICovCiAgICAsIHRydWUsIHRydWUpOwogIH07CgogIGVhY2hDaGFyWzIKICAvKiBTdGFyICovCiAgXSA9IGZ1bmN0aW9uIChfLCBjdXJyZW50U3RhdGUpIHsKICAgIHJldHVybiBjdXJyZW50U3RhdGUucHV0KC0xCiAgICAvKiBBTlkgKi8KICAgICwgZmFsc2UsIHRydWUpOwogIH07CgogIGVhY2hDaGFyWzQKICAvKiBFcHNpbG9uICovCiAgXSA9IGZ1bmN0aW9uIChfLCBjdXJyZW50U3RhdGUpIHsKICAgIHJldHVybiBjdXJyZW50U3RhdGU7CiAgfTsKCiAgdmFyIHJlZ2V4ID0gW107CgogIHJlZ2V4WzAKICAvKiBTdGF0aWMgKi8KICBdID0gZnVuY3Rpb24gKHNlZ21lbnQpIHsKICAgIHJldHVybiBzZWdtZW50LnZhbHVlLnJlcGxhY2UoZXNjYXBlUmVnZXgsICJcXCQxIik7CiAgfTsKCiAgcmVnZXhbMQogIC8qIER5bmFtaWMgKi8KICBdID0gZnVuY3Rpb24gKCkgewogICAgcmV0dXJuICIoW14vXSspIjsKICB9OwoKICByZWdleFsyCiAgLyogU3RhciAqLwogIF0gPSBmdW5jdGlvbiAoKSB7CiAgICByZXR1cm4gIiguKykiOwogIH07CgogIHJlZ2V4WzQKICAvKiBFcHNpbG9uICovCiAgXSA9IGZ1bmN0aW9uICgpIHsKICAgIHJldHVybiAiIjsKICB9OwoKICB2YXIgZ2VuZXJhdGUgPSBbXTsKCiAgZ2VuZXJhdGVbMAogIC8qIFN0YXRpYyAqLwogIF0gPSBmdW5jdGlvbiAoc2VnbWVudCkgewogICAgcmV0dXJuIHNlZ21lbnQudmFsdWU7CiAgfTsKCiAgZ2VuZXJhdGVbMQogIC8qIER5bmFtaWMgKi8KICBdID0gZnVuY3Rpb24gKHNlZ21lbnQsIHBhcmFtcykgewogICAgdmFyIHZhbHVlID0gZ2V0UGFyYW0ocGFyYW1zLCBzZWdtZW50LnZhbHVlKTsKCiAgICBpZiAoUm91dGVSZWNvZ25pemVyLkVOQ09ERV9BTkRfREVDT0RFX1BBVEhfU0VHTUVOVFMpIHsKICAgICAgcmV0dXJuIGVuY29kZVBhdGhTZWdtZW50KHZhbHVlKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KICB9OwoKICBnZW5lcmF0ZVsyCiAgLyogU3RhciAqLwogIF0gPSBmdW5jdGlvbiAoc2VnbWVudCwgcGFyYW1zKSB7CiAgICByZXR1cm4gZ2V0UGFyYW0ocGFyYW1zLCBzZWdtZW50LnZhbHVlKTsKICB9OwoKICBnZW5lcmF0ZVs0CiAgLyogRXBzaWxvbiAqLwogIF0gPSBmdW5jdGlvbiAoKSB7CiAgICByZXR1cm4gIiI7CiAgfTsKCiAgdmFyIEVtcHR5T2JqZWN0ID0gT2JqZWN0LmZyZWV6ZSh7fSk7CiAgdmFyIEVtcHR5QXJyYXkgPSBPYmplY3QuZnJlZXplKFtdKTsgLy8gVGhlIGBuYW1lc2Agd2lsbCBiZSBwb3B1bGF0ZWQgd2l0aCB0aGUgcGFyYW10ZXIgbmFtZSBmb3IgZWFjaCBkeW5hbWljL3N0YXIKICAvLyBzZWdtZW50LiBgc2hvdWxkRGVjb2Rlc2Agd2lsbCBiZSBwb3B1bGF0ZWQgd2l0aCBhIGJvb2xlYW4gZm9yIGVhY2ggZHlhbmFtaWMvc3RhcgogIC8vIHNlZ21lbnQsIGluZGljYXRpbmcgd2hldGhlciBpdCBzaG91bGQgYmUgZGVjb2RlZCBkdXJpbmcgcmVjb2duaXRpb24uCgogIGZ1bmN0aW9uIHBhcnNlKHNlZ21lbnRzLCByb3V0ZSwgdHlwZXMpIHsKICAgIC8vIG5vcm1hbGl6ZSByb3V0ZSBhcyBub3Qgc3RhcnRpbmcgd2l0aCBhICIvIi4gUmVjb2duaXRpb24gd2lsbAogICAgLy8gYWxzbyBub3JtYWxpemUuCiAgICBpZiAocm91dGUubGVuZ3RoID4gMCAmJiByb3V0ZS5jaGFyQ29kZUF0KDApID09PSA0NwogICAgLyogU0xBU0ggKi8KICAgICkgewogICAgICAgIHJvdXRlID0gcm91dGUuc3Vic3RyKDEpOwogICAgICB9CgogICAgdmFyIHBhcnRzID0gcm91dGUuc3BsaXQoIi8iKTsKICAgIHZhciBuYW1lcyA9IHVuZGVmaW5lZDsKICAgIHZhciBzaG91bGREZWNvZGVzID0gdW5kZWZpbmVkOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIHBhcnQgPSBwYXJ0c1tpXTsKICAgICAgdmFyIGZsYWdzID0gMDsKICAgICAgdmFyIHR5cGUgPSAwOwoKICAgICAgaWYgKHBhcnQgPT09ICIiKSB7CiAgICAgICAgdHlwZSA9IDQKICAgICAgICAvKiBFcHNpbG9uICovCiAgICAgICAgOwogICAgICB9IGVsc2UgaWYgKHBhcnQuY2hhckNvZGVBdCgwKSA9PT0gNTgKICAgICAgLyogQ09MT04gKi8KICAgICAgKSB7CiAgICAgICAgICB0eXBlID0gMQogICAgICAgICAgLyogRHluYW1pYyAqLwogICAgICAgICAgOwogICAgICAgIH0gZWxzZSBpZiAocGFydC5jaGFyQ29kZUF0KDApID09PSA0MgogICAgICAvKiBTVEFSICovCiAgICAgICkgewogICAgICAgICAgdHlwZSA9IDIKICAgICAgICAgIC8qIFN0YXIgKi8KICAgICAgICAgIDsKICAgICAgICB9IGVsc2UgewogICAgICAgIHR5cGUgPSAwCiAgICAgICAgLyogU3RhdGljICovCiAgICAgICAgOwogICAgICB9CgogICAgICBmbGFncyA9IDIgPDwgdHlwZTsKCiAgICAgIGlmIChmbGFncyAmIDEyCiAgICAgIC8qIE5hbWVkICovCiAgICAgICkgewogICAgICAgICAgcGFydCA9IHBhcnQuc2xpY2UoMSk7CiAgICAgICAgICBuYW1lcyA9IG5hbWVzIHx8IFtdOwogICAgICAgICAgbmFtZXMucHVzaChwYXJ0KTsKICAgICAgICAgIHNob3VsZERlY29kZXMgPSBzaG91bGREZWNvZGVzIHx8IFtdOwogICAgICAgICAgc2hvdWxkRGVjb2Rlcy5wdXNoKChmbGFncyAmIDQKICAgICAgICAgIC8qIERlY29kZWQgKi8KICAgICAgICAgICkgIT09IDApOwogICAgICAgIH0KCiAgICAgIGlmIChmbGFncyAmIDE0CiAgICAgIC8qIENvdW50ZWQgKi8KICAgICAgKSB7CiAgICAgICAgICB0eXBlc1t0eXBlXSsrOwogICAgICAgIH0KCiAgICAgIHNlZ21lbnRzLnB1c2goewogICAgICAgIHR5cGU6IHR5cGUsCiAgICAgICAgdmFsdWU6IG5vcm1hbGl6ZVNlZ21lbnQocGFydCkKICAgICAgfSk7CiAgICB9CgogICAgcmV0dXJuIHsKICAgICAgbmFtZXM6IG5hbWVzIHx8IEVtcHR5QXJyYXksCiAgICAgIHNob3VsZERlY29kZXM6IHNob3VsZERlY29kZXMgfHwgRW1wdHlBcnJheQogICAgfTsKICB9CgogIGZ1bmN0aW9uIGlzRXF1YWxDaGFyU3BlYyhzcGVjLCBjaGFyLCBuZWdhdGUpIHsKICAgIHJldHVybiBzcGVjLmNoYXIgPT09IGNoYXIgJiYgc3BlYy5uZWdhdGUgPT09IG5lZ2F0ZTsKICB9IC8vIEEgU3RhdGUgaGFzIGEgY2hhcmFjdGVyIHNwZWNpZmljYXRpb24gYW5kIChgY2hhclNwZWNgKSBhbmQgYSBsaXN0IG9mIHBvc3NpYmxlCiAgLy8gc3Vic2VxdWVudCBzdGF0ZXMgKGBuZXh0U3RhdGVzYCkuCiAgLy8KICAvLyBJZiBhIFN0YXRlIGlzIGFuIGFjY2VwdGluZyBzdGF0ZSwgaXQgd2lsbCBhbHNvIGhhdmUgc2V2ZXJhbCBhZGRpdGlvbmFsCiAgLy8gcHJvcGVydGllczoKICAvLwogIC8vICogYHJlZ2V4YDogQSByZWd1bGFyIGV4cHJlc3Npb24gdGhhdCBpcyB1c2VkIHRvIGV4dHJhY3QgcGFyYW1ldGVycyBmcm9tIHBhdGhzCiAgLy8gICB0aGF0IHJlYWNoZWQgdGhpcyBhY2NlcHRpbmcgc3RhdGUuCiAgLy8gKiBgaGFuZGxlcnNgOiBJbmZvcm1hdGlvbiBvbiBob3cgdG8gY29udmVydCB0aGUgbGlzdCBvZiBjYXB0dXJlcyBpbnRvIGNhbGxzCiAgLy8gICB0byByZWdpc3RlcmVkIGhhbmRsZXJzIHdpdGggdGhlIHNwZWNpZmllZCBwYXJhbWV0ZXJzCiAgLy8gKiBgdHlwZXNgOiBIb3cgbWFueSBzdGF0aWMsIGR5bmFtaWMgb3Igc3RhciBzZWdtZW50cyBpbiB0aGlzIHJvdXRlLiBVc2VkIHRvCiAgLy8gICBkZWNpZGUgd2hpY2ggcm91dGUgdG8gdXNlIGlmIG11bHRpcGxlIHJlZ2lzdGVyZWQgcm91dGVzIG1hdGNoIGEgcGF0aC4KICAvLwogIC8vIEN1cnJlbnRseSwgU3RhdGUgaXMgaW1wbGVtZW50ZWQgbmFpdmVseSBieSBsb29waW5nIG92ZXIgYG5leHRTdGF0ZXNgIGFuZAogIC8vIGNvbXBhcmluZyBhIGNoYXJhY3RlciBzcGVjaWZpY2F0aW9uIGFnYWluc3QgYSBjaGFyYWN0ZXIuIEEgbW9yZSBlZmZpY2llbnQKICAvLyBpbXBsZW1lbnRhdGlvbiB3b3VsZCB1c2UgYSBoYXNoIG9mIGtleXMgcG9pbnRpbmcgYXQgb25lIG9yIG1vcmUgbmV4dCBzdGF0ZXMuCgoKICB2YXIgU3RhdGUgPSBmdW5jdGlvbiBTdGF0ZShzdGF0ZXMsIGlkLCBjaGFyLCBuZWdhdGUsIHJlcGVhdCkgewogICAgdGhpcy5zdGF0ZXMgPSBzdGF0ZXM7CiAgICB0aGlzLmlkID0gaWQ7CiAgICB0aGlzLmNoYXIgPSBjaGFyOwogICAgdGhpcy5uZWdhdGUgPSBuZWdhdGU7CiAgICB0aGlzLm5leHRTdGF0ZXMgPSByZXBlYXQgPyBpZCA6IG51bGw7CiAgICB0aGlzLnBhdHRlcm4gPSAiIjsKICAgIHRoaXMuX3JlZ2V4ID0gdW5kZWZpbmVkOwogICAgdGhpcy5oYW5kbGVycyA9IHVuZGVmaW5lZDsKICAgIHRoaXMudHlwZXMgPSB1bmRlZmluZWQ7CiAgfTsKCiAgU3RhdGUucHJvdG90eXBlLnJlZ2V4ID0gZnVuY3Rpb24gcmVnZXgkMSgpIHsKICAgIGlmICghdGhpcy5fcmVnZXgpIHsKICAgICAgdGhpcy5fcmVnZXggPSBuZXcgUmVnRXhwKHRoaXMucGF0dGVybik7CiAgICB9CgogICAgcmV0dXJuIHRoaXMuX3JlZ2V4OwogIH07CgogIFN0YXRlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiBnZXQoY2hhciwgbmVnYXRlKSB7CiAgICB2YXIgdGhpcyQxID0gdGhpczsKICAgIHZhciBuZXh0U3RhdGVzID0gdGhpcy5uZXh0U3RhdGVzOwoKICAgIGlmIChuZXh0U3RhdGVzID09PSBudWxsKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoaXNBcnJheShuZXh0U3RhdGVzKSkgewogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5leHRTdGF0ZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgY2hpbGQgPSB0aGlzJDEuc3RhdGVzW25leHRTdGF0ZXNbaV1dOwoKICAgICAgICBpZiAoaXNFcXVhbENoYXJTcGVjKGNoaWxkLCBjaGFyLCBuZWdhdGUpKSB7CiAgICAgICAgICByZXR1cm4gY2hpbGQ7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICB2YXIgY2hpbGQkMSA9IHRoaXMuc3RhdGVzW25leHRTdGF0ZXNdOwoKICAgICAgaWYgKGlzRXF1YWxDaGFyU3BlYyhjaGlsZCQxLCBjaGFyLCBuZWdhdGUpKSB7CiAgICAgICAgcmV0dXJuIGNoaWxkJDE7CiAgICAgIH0KICAgIH0KICB9OwoKICBTdGF0ZS5wcm90b3R5cGUucHV0ID0gZnVuY3Rpb24gcHV0KGNoYXIsIG5lZ2F0ZSwgcmVwZWF0KSB7CiAgICB2YXIgc3RhdGU7IC8vIElmIHRoZSBjaGFyYWN0ZXIgc3BlY2lmaWNhdGlvbiBhbHJlYWR5IGV4aXN0cyBpbiBhIGNoaWxkIG9mIHRoZSBjdXJyZW50CiAgICAvLyBzdGF0ZSwganVzdCByZXR1cm4gdGhhdCBzdGF0ZS4KCiAgICBpZiAoc3RhdGUgPSB0aGlzLmdldChjaGFyLCBuZWdhdGUpKSB7CiAgICAgIHJldHVybiBzdGF0ZTsKICAgIH0gLy8gTWFrZSBhIG5ldyBzdGF0ZSBmb3IgdGhlIGNoYXJhY3RlciBzcGVjCgoKICAgIHZhciBzdGF0ZXMgPSB0aGlzLnN0YXRlczsKICAgIHN0YXRlID0gbmV3IFN0YXRlKHN0YXRlcywgc3RhdGVzLmxlbmd0aCwgY2hhciwgbmVnYXRlLCByZXBlYXQpOwogICAgc3RhdGVzW3N0YXRlcy5sZW5ndGhdID0gc3RhdGU7IC8vIEluc2VydCB0aGUgbmV3IHN0YXRlIGFzIGEgY2hpbGQgb2YgdGhlIGN1cnJlbnQgc3RhdGUKCiAgICBpZiAodGhpcy5uZXh0U3RhdGVzID09IG51bGwpIHsKICAgICAgdGhpcy5uZXh0U3RhdGVzID0gc3RhdGUuaWQ7CiAgICB9IGVsc2UgaWYgKGlzQXJyYXkodGhpcy5uZXh0U3RhdGVzKSkgewogICAgICB0aGlzLm5leHRTdGF0ZXMucHVzaChzdGF0ZS5pZCk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLm5leHRTdGF0ZXMgPSBbdGhpcy5uZXh0U3RhdGVzLCBzdGF0ZS5pZF07CiAgICB9IC8vIFJldHVybiB0aGUgbmV3IHN0YXRlCgoKICAgIHJldHVybiBzdGF0ZTsKICB9OyAvLyBGaW5kIGEgbGlzdCBvZiBjaGlsZCBzdGF0ZXMgbWF0Y2hpbmcgdGhlIG5leHQgY2hhcmFjdGVyCgoKICBTdGF0ZS5wcm90b3R5cGUubWF0Y2ggPSBmdW5jdGlvbiBtYXRjaChjaCkgewogICAgdmFyIHRoaXMkMSA9IHRoaXM7CiAgICB2YXIgbmV4dFN0YXRlcyA9IHRoaXMubmV4dFN0YXRlczsKCiAgICBpZiAoIW5leHRTdGF0ZXMpIHsKICAgICAgcmV0dXJuIFtdOwogICAgfQoKICAgIHZhciByZXR1cm5lZCA9IFtdOwoKICAgIGlmIChpc0FycmF5KG5leHRTdGF0ZXMpKSB7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmV4dFN0YXRlcy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBjaGlsZCA9IHRoaXMkMS5zdGF0ZXNbbmV4dFN0YXRlc1tpXV07CgogICAgICAgIGlmIChpc01hdGNoKGNoaWxkLCBjaCkpIHsKICAgICAgICAgIHJldHVybmVkLnB1c2goY2hpbGQpOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdmFyIGNoaWxkJDEgPSB0aGlzLnN0YXRlc1tuZXh0U3RhdGVzXTsKCiAgICAgIGlmIChpc01hdGNoKGNoaWxkJDEsIGNoKSkgewogICAgICAgIHJldHVybmVkLnB1c2goY2hpbGQkMSk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcmV0dXJuZWQ7CiAgfTsKCiAgZnVuY3Rpb24gaXNNYXRjaChzcGVjLCBjaGFyKSB7CiAgICByZXR1cm4gc3BlYy5uZWdhdGUgPyBzcGVjLmNoYXIgIT09IGNoYXIgJiYgc3BlYy5jaGFyICE9PSAtMQogICAgLyogQU5ZICovCiAgICA6IHNwZWMuY2hhciA9PT0gY2hhciB8fCBzcGVjLmNoYXIgPT09IC0xCiAgICAvKiBBTlkgKi8KICAgIDsKICB9IC8vIFRoaXMgaXMgYSBzb21ld2hhdCBuYWl2ZSBzdHJhdGVneSwgYnV0IHNob3VsZCB3b3JrIGluIGEgbG90IG9mIGNhc2VzCiAgLy8gQSBiZXR0ZXIgc3RyYXRlZ3kgd291bGQgcHJvcGVybHkgcmVzb2x2ZSAvcG9zdHMvOmlkL25ldyBhbmQgL3Bvc3RzL2VkaXQvOmlkLgogIC8vCiAgLy8gVGhpcyBzdHJhdGVneSBnZW5lcmFsbHkgcHJlZmVycyBtb3JlIHN0YXRpYyBhbmQgbGVzcyBkeW5hbWljIG1hdGNoaW5nLgogIC8vIFNwZWNpZmljYWxseSwgaXQKICAvLwogIC8vICAqIHByZWZlcnMgZmV3ZXIgc3RhcnMgdG8gbW9yZSwgdGhlbgogIC8vICAqIHByZWZlcnMgdXNpbmcgc3RhcnMgZm9yIGxlc3Mgb2YgdGhlIG1hdGNoIHRvIG1vcmUsIHRoZW4KICAvLyAgKiBwcmVmZXJzIGZld2VyIGR5bmFtaWMgc2VnbWVudHMgdG8gbW9yZSwgdGhlbgogIC8vICAqIHByZWZlcnMgbW9yZSBzdGF0aWMgc2VnbWVudHMgdG8gbW9yZQoKCiAgZnVuY3Rpb24gc29ydFNvbHV0aW9ucyhzdGF0ZXMpIHsKICAgIHJldHVybiBzdGF0ZXMuc29ydChmdW5jdGlvbiAoYSwgYikgewogICAgICB2YXIgcmVmID0gYS50eXBlcyB8fCBbMCwgMCwgMF07CiAgICAgIHZhciBhc3RhdGljcyA9IHJlZlswXTsKICAgICAgdmFyIGFkeW5hbWljcyA9IHJlZlsxXTsKICAgICAgdmFyIGFzdGFycyA9IHJlZlsyXTsKICAgICAgdmFyIHJlZiQxID0gYi50eXBlcyB8fCBbMCwgMCwgMF07CiAgICAgIHZhciBic3RhdGljcyA9IHJlZiQxWzBdOwogICAgICB2YXIgYmR5bmFtaWNzID0gcmVmJDFbMV07CiAgICAgIHZhciBic3RhcnMgPSByZWYkMVsyXTsKCiAgICAgIGlmIChhc3RhcnMgIT09IGJzdGFycykgewogICAgICAgIHJldHVybiBhc3RhcnMgLSBic3RhcnM7CiAgICAgIH0KCiAgICAgIGlmIChhc3RhcnMpIHsKICAgICAgICBpZiAoYXN0YXRpY3MgIT09IGJzdGF0aWNzKSB7CiAgICAgICAgICByZXR1cm4gYnN0YXRpY3MgLSBhc3RhdGljczsKICAgICAgICB9CgogICAgICAgIGlmIChhZHluYW1pY3MgIT09IGJkeW5hbWljcykgewogICAgICAgICAgcmV0dXJuIGJkeW5hbWljcyAtIGFkeW5hbWljczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChhZHluYW1pY3MgIT09IGJkeW5hbWljcykgewogICAgICAgIHJldHVybiBhZHluYW1pY3MgLSBiZHluYW1pY3M7CiAgICAgIH0KCiAgICAgIGlmIChhc3RhdGljcyAhPT0gYnN0YXRpY3MpIHsKICAgICAgICByZXR1cm4gYnN0YXRpY3MgLSBhc3RhdGljczsKICAgICAgfQoKICAgICAgcmV0dXJuIDA7CiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHJlY29nbml6ZUNoYXIoc3RhdGVzLCBjaCkgewogICAgdmFyIG5leHRTdGF0ZXMgPSBbXTsKCiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHN0YXRlcy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgdmFyIHN0YXRlID0gc3RhdGVzW2ldOwogICAgICBuZXh0U3RhdGVzID0gbmV4dFN0YXRlcy5jb25jYXQoc3RhdGUubWF0Y2goY2gpKTsKICAgIH0KCiAgICByZXR1cm4gbmV4dFN0YXRlczsKICB9CgogIHZhciBSZWNvZ25pemVSZXN1bHRzID0gZnVuY3Rpb24gUmVjb2duaXplUmVzdWx0cyhxdWVyeVBhcmFtcykgewogICAgdGhpcy5sZW5ndGggPSAwOwogICAgdGhpcy5xdWVyeVBhcmFtcyA9IHF1ZXJ5UGFyYW1zIHx8IHt9OwogIH07CgogIFJlY29nbml6ZVJlc3VsdHMucHJvdG90eXBlLnNwbGljZSA9IEFycmF5LnByb3RvdHlwZS5zcGxpY2U7CiAgUmVjb2duaXplUmVzdWx0cy5wcm90b3R5cGUuc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7CiAgUmVjb2duaXplUmVzdWx0cy5wcm90b3R5cGUucHVzaCA9IEFycmF5LnByb3RvdHlwZS5wdXNoOwoKICBmdW5jdGlvbiBmaW5kSGFuZGxlcihzdGF0ZSwgb3JpZ2luYWxQYXRoLCBxdWVyeVBhcmFtcykgewogICAgdmFyIGhhbmRsZXJzID0gc3RhdGUuaGFuZGxlcnM7CiAgICB2YXIgcmVnZXggPSBzdGF0ZS5yZWdleCgpOwoKICAgIGlmICghcmVnZXggfHwgIWhhbmRsZXJzKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigic3RhdGUgbm90IGluaXRpYWxpemVkIik7CiAgICB9CgogICAgdmFyIGNhcHR1cmVzID0gb3JpZ2luYWxQYXRoLm1hdGNoKHJlZ2V4KTsKICAgIHZhciBjdXJyZW50Q2FwdHVyZSA9IDE7CiAgICB2YXIgcmVzdWx0ID0gbmV3IFJlY29nbml6ZVJlc3VsdHMocXVlcnlQYXJhbXMpOwogICAgcmVzdWx0Lmxlbmd0aCA9IGhhbmRsZXJzLmxlbmd0aDsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhbmRsZXJzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBoYW5kbGVyID0gaGFuZGxlcnNbaV07CiAgICAgIHZhciBuYW1lcyA9IGhhbmRsZXIubmFtZXM7CiAgICAgIHZhciBzaG91bGREZWNvZGVzID0gaGFuZGxlci5zaG91bGREZWNvZGVzOwogICAgICB2YXIgcGFyYW1zID0gRW1wdHlPYmplY3Q7CiAgICAgIHZhciBpc0R5bmFtaWMgPSBmYWxzZTsKCiAgICAgIGlmIChuYW1lcyAhPT0gRW1wdHlBcnJheSAmJiBzaG91bGREZWNvZGVzICE9PSBFbXB0eUFycmF5KSB7CiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBuYW1lcy5sZW5ndGg7IGorKykgewogICAgICAgICAgaXNEeW5hbWljID0gdHJ1ZTsKICAgICAgICAgIHZhciBuYW1lID0gbmFtZXNbal07CiAgICAgICAgICB2YXIgY2FwdHVyZSA9IGNhcHR1cmVzICYmIGNhcHR1cmVzW2N1cnJlbnRDYXB0dXJlKytdOwoKICAgICAgICAgIGlmIChwYXJhbXMgPT09IEVtcHR5T2JqZWN0KSB7CiAgICAgICAgICAgIHBhcmFtcyA9IHt9OwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChSb3V0ZVJlY29nbml6ZXIuRU5DT0RFX0FORF9ERUNPREVfUEFUSF9TRUdNRU5UUyAmJiBzaG91bGREZWNvZGVzW2pdKSB7CiAgICAgICAgICAgIHBhcmFtc1tuYW1lXSA9IGNhcHR1cmUgJiYgZGVjb2RlVVJJQ29tcG9uZW50KGNhcHR1cmUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcGFyYW1zW25hbWVdID0gY2FwdHVyZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJlc3VsdFtpXSA9IHsKICAgICAgICBoYW5kbGVyOiBoYW5kbGVyLmhhbmRsZXIsCiAgICAgICAgcGFyYW1zOiBwYXJhbXMsCiAgICAgICAgaXNEeW5hbWljOiBpc0R5bmFtaWMKICAgICAgfTsKICAgIH0KCiAgICByZXR1cm4gcmVzdWx0OwogIH0KCiAgZnVuY3Rpb24gZGVjb2RlUXVlcnlQYXJhbVBhcnQocGFydCkgewogICAgLy8gaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQwMS9pbnRlcmFjdC9mb3Jtcy5odG1sI2gtMTcuMTMuNC4xCiAgICBwYXJ0ID0gcGFydC5yZXBsYWNlKC9cKy9nbSwgIiUyMCIpOwogICAgdmFyIHJlc3VsdDsKCiAgICB0cnkgewogICAgICByZXN1bHQgPSBkZWNvZGVVUklDb21wb25lbnQocGFydCk7CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgICByZXN1bHQgPSAiIjsKICAgIH0KCiAgICByZXR1cm4gcmVzdWx0OwogIH0KCiAgdmFyIFJvdXRlUmVjb2duaXplciA9IGZ1bmN0aW9uIFJvdXRlUmVjb2duaXplcigpIHsKICAgIHRoaXMubmFtZXMgPSBjcmVhdGVNYXAoKTsKICAgIHZhciBzdGF0ZXMgPSBbXTsKICAgIHZhciBzdGF0ZSA9IG5ldyBTdGF0ZShzdGF0ZXMsIDAsIC0xCiAgICAvKiBBTlkgKi8KICAgICwgdHJ1ZSwgZmFsc2UpOwogICAgc3RhdGVzWzBdID0gc3RhdGU7CiAgICB0aGlzLnN0YXRlcyA9IHN0YXRlczsKICAgIHRoaXMucm9vdFN0YXRlID0gc3RhdGU7CiAgfTsKCiAgUm91dGVSZWNvZ25pemVyLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiBhZGQocm91dGVzLCBvcHRpb25zKSB7CiAgICB2YXIgY3VycmVudFN0YXRlID0gdGhpcy5yb290U3RhdGU7CiAgICB2YXIgcGF0dGVybiA9ICJeIjsKICAgIHZhciB0eXBlcyA9IFswLCAwLCAwXTsKICAgIHZhciBoYW5kbGVycyA9IG5ldyBBcnJheShyb3V0ZXMubGVuZ3RoKTsKICAgIHZhciBhbGxTZWdtZW50cyA9IFtdOwogICAgdmFyIGlzRW1wdHkgPSB0cnVlOwogICAgdmFyIGogPSAwOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm91dGVzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciByb3V0ZSA9IHJvdXRlc1tpXTsKICAgICAgdmFyIHJlZiA9IHBhcnNlKGFsbFNlZ21lbnRzLCByb3V0ZS5wYXRoLCB0eXBlcyk7CiAgICAgIHZhciBuYW1lcyA9IHJlZi5uYW1lczsKICAgICAgdmFyIHNob3VsZERlY29kZXMgPSByZWYuc2hvdWxkRGVjb2RlczsgLy8gcHJlc2VydmUgaiBzbyBpdCBwb2ludHMgdG8gdGhlIHN0YXJ0IG9mIG5ld2x5IGFkZGVkIHNlZ21lbnRzCgogICAgICBmb3IgKDsgaiA8IGFsbFNlZ21lbnRzLmxlbmd0aDsgaisrKSB7CiAgICAgICAgdmFyIHNlZ21lbnQgPSBhbGxTZWdtZW50c1tqXTsKCiAgICAgICAgaWYgKHNlZ21lbnQudHlwZSA9PT0gNAogICAgICAgIC8qIEVwc2lsb24gKi8KICAgICAgICApIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CgogICAgICAgIGlzRW1wdHkgPSBmYWxzZTsgLy8gQWRkIGEgIi8iIGZvciB0aGUgbmV3IHNlZ21lbnQKCiAgICAgICAgY3VycmVudFN0YXRlID0gY3VycmVudFN0YXRlLnB1dCg0NwogICAgICAgIC8qIFNMQVNIICovCiAgICAgICAgLCBmYWxzZSwgZmFsc2UpOwogICAgICAgIHBhdHRlcm4gKz0gIi8iOyAvLyBBZGQgYSByZXByZXNlbnRhdGlvbiBvZiB0aGUgc2VnbWVudCB0byB0aGUgTkZBIGFuZCByZWdleAoKICAgICAgICBjdXJyZW50U3RhdGUgPSBlYWNoQ2hhcltzZWdtZW50LnR5cGVdKHNlZ21lbnQsIGN1cnJlbnRTdGF0ZSk7CiAgICAgICAgcGF0dGVybiArPSByZWdleFtzZWdtZW50LnR5cGVdKHNlZ21lbnQpOwogICAgICB9CgogICAgICBoYW5kbGVyc1tpXSA9IHsKICAgICAgICBoYW5kbGVyOiByb3V0ZS5oYW5kbGVyLAogICAgICAgIG5hbWVzOiBuYW1lcywKICAgICAgICBzaG91bGREZWNvZGVzOiBzaG91bGREZWNvZGVzCiAgICAgIH07CiAgICB9CgogICAgaWYgKGlzRW1wdHkpIHsKICAgICAgY3VycmVudFN0YXRlID0gY3VycmVudFN0YXRlLnB1dCg0NwogICAgICAvKiBTTEFTSCAqLwogICAgICAsIGZhbHNlLCBmYWxzZSk7CiAgICAgIHBhdHRlcm4gKz0gIi8iOwogICAgfQoKICAgIGN1cnJlbnRTdGF0ZS5oYW5kbGVycyA9IGhhbmRsZXJzOwogICAgY3VycmVudFN0YXRlLnBhdHRlcm4gPSBwYXR0ZXJuICsgIiQiOwogICAgY3VycmVudFN0YXRlLnR5cGVzID0gdHlwZXM7CiAgICB2YXIgbmFtZTsKCiAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICJvYmplY3QiICYmIG9wdGlvbnMgIT09IG51bGwgJiYgb3B0aW9ucy5hcykgewogICAgICBuYW1lID0gb3B0aW9ucy5hczsKICAgIH0KCiAgICBpZiAobmFtZSkgewogICAgICAvLyBpZiAodGhpcy5uYW1lc1tuYW1lXSkgewogICAgICAvLyAgIHRocm93IG5ldyBFcnJvcigiWW91IG1heSBub3QgYWRkIGEgZHVwbGljYXRlIHJvdXRlIG5hbWVkIGAiICsgbmFtZSArICJgLiIpOwogICAgICAvLyB9CiAgICAgIHRoaXMubmFtZXNbbmFtZV0gPSB7CiAgICAgICAgc2VnbWVudHM6IGFsbFNlZ21lbnRzLAogICAgICAgIGhhbmRsZXJzOiBoYW5kbGVycwogICAgICB9OwogICAgfQogIH07CgogIFJvdXRlUmVjb2duaXplci5wcm90b3R5cGUuaGFuZGxlcnNGb3IgPSBmdW5jdGlvbiBoYW5kbGVyc0ZvcihuYW1lKSB7CiAgICB2YXIgcm91dGUgPSB0aGlzLm5hbWVzW25hbWVdOwoKICAgIGlmICghcm91dGUpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJUaGVyZSBpcyBubyByb3V0ZSBuYW1lZCAiICsgbmFtZSk7CiAgICB9CgogICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShyb3V0ZS5oYW5kbGVycy5sZW5ndGgpOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm91dGUuaGFuZGxlcnMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGhhbmRsZXIgPSByb3V0ZS5oYW5kbGVyc1tpXTsKICAgICAgcmVzdWx0W2ldID0gaGFuZGxlcjsKICAgIH0KCiAgICByZXR1cm4gcmVzdWx0OwogIH07CgogIFJvdXRlUmVjb2duaXplci5wcm90b3R5cGUuaGFzUm91dGUgPSBmdW5jdGlvbiBoYXNSb3V0ZShuYW1lKSB7CiAgICByZXR1cm4gISF0aGlzLm5hbWVzW25hbWVdOwogIH07CgogIFJvdXRlUmVjb2duaXplci5wcm90b3R5cGUuZ2VuZXJhdGUgPSBmdW5jdGlvbiBnZW5lcmF0ZSQxKG5hbWUsIHBhcmFtcykgewogICAgdmFyIHJvdXRlID0gdGhpcy5uYW1lc1tuYW1lXTsKICAgIHZhciBvdXRwdXQgPSAiIjsKCiAgICBpZiAoIXJvdXRlKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiVGhlcmUgaXMgbm8gcm91dGUgbmFtZWQgIiArIG5hbWUpOwogICAgfQoKICAgIHZhciBzZWdtZW50cyA9IHJvdXRlLnNlZ21lbnRzOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VnbWVudHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIHNlZ21lbnQgPSBzZWdtZW50c1tpXTsKCiAgICAgIGlmIChzZWdtZW50LnR5cGUgPT09IDQKICAgICAgLyogRXBzaWxvbiAqLwogICAgICApIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KCiAgICAgIG91dHB1dCArPSAiLyI7CiAgICAgIG91dHB1dCArPSBnZW5lcmF0ZVtzZWdtZW50LnR5cGVdKHNlZ21lbnQsIHBhcmFtcyk7CiAgICB9CgogICAgaWYgKG91dHB1dC5jaGFyQXQoMCkgIT09ICIvIikgewogICAgICBvdXRwdXQgPSAiLyIgKyBvdXRwdXQ7CiAgICB9CgogICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMucXVlcnlQYXJhbXMpIHsKICAgICAgb3V0cHV0ICs9IHRoaXMuZ2VuZXJhdGVRdWVyeVN0cmluZyhwYXJhbXMucXVlcnlQYXJhbXMpOwogICAgfQoKICAgIHJldHVybiBvdXRwdXQ7CiAgfTsKCiAgUm91dGVSZWNvZ25pemVyLnByb3RvdHlwZS5nZW5lcmF0ZVF1ZXJ5U3RyaW5nID0gZnVuY3Rpb24gZ2VuZXJhdGVRdWVyeVN0cmluZyhwYXJhbXMpIHsKICAgIHZhciBwYWlycyA9IFtdOwogICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhwYXJhbXMpOwogICAga2V5cy5zb3J0KCk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBrZXkgPSBrZXlzW2ldOwogICAgICB2YXIgdmFsdWUgPSBwYXJhbXNba2V5XTsKCiAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIHZhciBwYWlyID0gZW5jb2RlVVJJQ29tcG9uZW50KGtleSk7CgogICAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHZhbHVlLmxlbmd0aDsgaisrKSB7CiAgICAgICAgICB2YXIgYXJyYXlQYWlyID0ga2V5ICsgIltdIiArICI9IiArIGVuY29kZVVSSUNvbXBvbmVudCh2YWx1ZVtqXSk7CiAgICAgICAgICBwYWlycy5wdXNoKGFycmF5UGFpcik7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHBhaXIgKz0gIj0iICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKTsKICAgICAgICBwYWlycy5wdXNoKHBhaXIpOwogICAgICB9CiAgICB9CgogICAgaWYgKHBhaXJzLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gIiI7CiAgICB9CgogICAgcmV0dXJuICI/IiArIHBhaXJzLmpvaW4oIiYiKTsKICB9OwoKICBSb3V0ZVJlY29nbml6ZXIucHJvdG90eXBlLnBhcnNlUXVlcnlTdHJpbmcgPSBmdW5jdGlvbiBwYXJzZVF1ZXJ5U3RyaW5nKHF1ZXJ5U3RyaW5nKSB7CiAgICB2YXIgcGFpcnMgPSBxdWVyeVN0cmluZy5zcGxpdCgiJiIpOwogICAgdmFyIHF1ZXJ5UGFyYW1zID0ge307CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYWlycy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgcGFpciA9IHBhaXJzW2ldLnNwbGl0KCI9IiksCiAgICAgICAgICBrZXkgPSBkZWNvZGVRdWVyeVBhcmFtUGFydChwYWlyWzBdKSwKICAgICAgICAgIGtleUxlbmd0aCA9IGtleS5sZW5ndGgsCiAgICAgICAgICBpc0FycmF5ID0gZmFsc2UsCiAgICAgICAgICB2YWx1ZSA9IHZvaWQgMDsKCiAgICAgIGlmIChwYWlyLmxlbmd0aCA9PT0gMSkgewogICAgICAgIHZhbHVlID0gInRydWUiOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIEhhbmRsZSBhcnJheXMKICAgICAgICBpZiAoa2V5TGVuZ3RoID4gMiAmJiBrZXkuc2xpY2Uoa2V5TGVuZ3RoIC0gMikgPT09ICJbXSIpIHsKICAgICAgICAgIGlzQXJyYXkgPSB0cnVlOwogICAgICAgICAga2V5ID0ga2V5LnNsaWNlKDAsIGtleUxlbmd0aCAtIDIpOwoKICAgICAgICAgIGlmICghcXVlcnlQYXJhbXNba2V5XSkgewogICAgICAgICAgICBxdWVyeVBhcmFtc1trZXldID0gW107CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB2YWx1ZSA9IHBhaXJbMV0gPyBkZWNvZGVRdWVyeVBhcmFtUGFydChwYWlyWzFdKSA6ICIiOwogICAgICB9CgogICAgICBpZiAoaXNBcnJheSkgewogICAgICAgIHF1ZXJ5UGFyYW1zW2tleV0ucHVzaCh2YWx1ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcXVlcnlQYXJhbXNba2V5XSA9IHZhbHVlOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHF1ZXJ5UGFyYW1zOwogIH07CgogIFJvdXRlUmVjb2duaXplci5wcm90b3R5cGUucmVjb2duaXplID0gZnVuY3Rpb24gcmVjb2duaXplKHBhdGgpIHsKICAgIHZhciByZXN1bHRzOwogICAgdmFyIHN0YXRlcyA9IFt0aGlzLnJvb3RTdGF0ZV07CiAgICB2YXIgcXVlcnlQYXJhbXMgPSB7fTsKICAgIHZhciBpc1NsYXNoRHJvcHBlZCA9IGZhbHNlOwogICAgdmFyIGhhc2hTdGFydCA9IHBhdGguaW5kZXhPZigiIyIpOwoKICAgIGlmIChoYXNoU3RhcnQgIT09IC0xKSB7CiAgICAgIHBhdGggPSBwYXRoLnN1YnN0cigwLCBoYXNoU3RhcnQpOwogICAgfQoKICAgIHZhciBxdWVyeVN0YXJ0ID0gcGF0aC5pbmRleE9mKCI/Iik7CgogICAgaWYgKHF1ZXJ5U3RhcnQgIT09IC0xKSB7CiAgICAgIHZhciBxdWVyeVN0cmluZyA9IHBhdGguc3Vic3RyKHF1ZXJ5U3RhcnQgKyAxLCBwYXRoLmxlbmd0aCk7CiAgICAgIHBhdGggPSBwYXRoLnN1YnN0cigwLCBxdWVyeVN0YXJ0KTsKICAgICAgcXVlcnlQYXJhbXMgPSB0aGlzLnBhcnNlUXVlcnlTdHJpbmcocXVlcnlTdHJpbmcpOwogICAgfQoKICAgIGlmIChwYXRoLmNoYXJBdCgwKSAhPT0gIi8iKSB7CiAgICAgIHBhdGggPSAiLyIgKyBwYXRoOwogICAgfQoKICAgIHZhciBvcmlnaW5hbFBhdGggPSBwYXRoOwoKICAgIGlmIChSb3V0ZVJlY29nbml6ZXIuRU5DT0RFX0FORF9ERUNPREVfUEFUSF9TRUdNRU5UUykgewogICAgICBwYXRoID0gbm9ybWFsaXplUGF0aChwYXRoKTsKICAgIH0gZWxzZSB7CiAgICAgIHBhdGggPSBkZWNvZGVVUkkocGF0aCk7CiAgICAgIG9yaWdpbmFsUGF0aCA9IGRlY29kZVVSSShvcmlnaW5hbFBhdGgpOwogICAgfQoKICAgIHZhciBwYXRoTGVuID0gcGF0aC5sZW5ndGg7CgogICAgaWYgKHBhdGhMZW4gPiAxICYmIHBhdGguY2hhckF0KHBhdGhMZW4gLSAxKSA9PT0gIi8iKSB7CiAgICAgIHBhdGggPSBwYXRoLnN1YnN0cigwLCBwYXRoTGVuIC0gMSk7CiAgICAgIG9yaWdpbmFsUGF0aCA9IG9yaWdpbmFsUGF0aC5zdWJzdHIoMCwgb3JpZ2luYWxQYXRoLmxlbmd0aCAtIDEpOwogICAgICBpc1NsYXNoRHJvcHBlZCA9IHRydWU7CiAgICB9CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRoLmxlbmd0aDsgaSsrKSB7CiAgICAgIHN0YXRlcyA9IHJlY29nbml6ZUNoYXIoc3RhdGVzLCBwYXRoLmNoYXJDb2RlQXQoaSkpOwoKICAgICAgaWYgKCFzdGF0ZXMubGVuZ3RoKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KCiAgICB2YXIgc29sdXRpb25zID0gW107CgogICAgZm9yICh2YXIgaSQxID0gMDsgaSQxIDwgc3RhdGVzLmxlbmd0aDsgaSQxKyspIHsKICAgICAgaWYgKHN0YXRlc1tpJDFdLmhhbmRsZXJzKSB7CiAgICAgICAgc29sdXRpb25zLnB1c2goc3RhdGVzW2kkMV0pOwogICAgICB9CiAgICB9CgogICAgc3RhdGVzID0gc29ydFNvbHV0aW9ucyhzb2x1dGlvbnMpOwogICAgdmFyIHN0YXRlID0gc29sdXRpb25zWzBdOwoKICAgIGlmIChzdGF0ZSAmJiBzdGF0ZS5oYW5kbGVycykgewogICAgICAvLyBpZiBhIHRyYWlsaW5nIHNsYXNoIHdhcyBkcm9wcGVkIGFuZCBhIHN0YXIgc2VnbWVudCBpcyB0aGUgbGFzdCBzZWdtZW50CiAgICAgIC8vIHNwZWNpZmllZCwgcHV0IHRoZSB0cmFpbGluZyBzbGFzaCBiYWNrCiAgICAgIGlmIChpc1NsYXNoRHJvcHBlZCAmJiBzdGF0ZS5wYXR0ZXJuICYmIHN0YXRlLnBhdHRlcm4uc2xpY2UoLTUpID09PSAiKC4rKSQiKSB7CiAgICAgICAgb3JpZ2luYWxQYXRoID0gb3JpZ2luYWxQYXRoICsgIi8iOwogICAgICB9CgogICAgICByZXN1bHRzID0gZmluZEhhbmRsZXIoc3RhdGUsIG9yaWdpbmFsUGF0aCwgcXVlcnlQYXJhbXMpOwogICAgfQoKICAgIHJldHVybiByZXN1bHRzOwogIH07CgogIFJvdXRlUmVjb2duaXplci5WRVJTSU9OID0gIjAuMy40IjsgLy8gU2V0IHRvIGZhbHNlIHRvIG9wdC1vdXQgb2YgZW5jb2RpbmcgYW5kIGRlY29kaW5nIHBhdGggc2VnbWVudHMuCiAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS90aWxkZWlvL3JvdXRlLXJlY29nbml6ZXIvcHVsbC81NQoKICBSb3V0ZVJlY29nbml6ZXIuRU5DT0RFX0FORF9ERUNPREVfUEFUSF9TRUdNRU5UUyA9IHRydWU7CiAgUm91dGVSZWNvZ25pemVyLk5vcm1hbGl6ZXIgPSB7CiAgICBub3JtYWxpemVTZWdtZW50OiBub3JtYWxpemVTZWdtZW50LAogICAgbm9ybWFsaXplUGF0aDogbm9ybWFsaXplUGF0aCwKICAgIGVuY29kZVBhdGhTZWdtZW50OiBlbmNvZGVQYXRoU2VnbWVudAogIH07CiAgUm91dGVSZWNvZ25pemVyLnByb3RvdHlwZS5tYXAgPSBtYXA7CiAgdmFyIF9kZWZhdWx0ID0gUm91dGVSZWNvZ25pemVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgicm91dGVyX2pzIiwgWyJleHBvcnRzIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiZW1iZXItYmFiZWwiLCAicnN2cCIsICJyb3V0ZS1yZWNvZ25pemVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3BvbHlmaWxscywgX2VtYmVyQmFiZWwsIF9yc3ZwLCBfcm91dGVSZWNvZ25pemVyKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5sb2dBYm9ydCA9IGxvZ0Fib3J0OwogIF9leHBvcnRzLkludGVybmFsUm91dGVJbmZvID0gX2V4cG9ydHMuVHJhbnNpdGlvbkVycm9yID0gX2V4cG9ydHMuVHJhbnNpdGlvblN0YXRlID0gX2V4cG9ydHMuUVVFUllfUEFSQU1TX1NZTUJPTCA9IF9leHBvcnRzLlBBUkFNU19TWU1CT0wgPSBfZXhwb3J0cy5TVEFURV9TWU1CT0wgPSBfZXhwb3J0cy5JbnRlcm5hbFRyYW5zaXRpb24gPSBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICB2YXIgVHJhbnNpdGlvbkFib3J0ZWRFcnJvciA9IGZ1bmN0aW9uICgpIHsKICAgIFRyYW5zaXRpb25BYm9ydGVkRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFcnJvci5wcm90b3R5cGUpOwogICAgVHJhbnNpdGlvbkFib3J0ZWRFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBUcmFuc2l0aW9uQWJvcnRlZEVycm9yOwoKICAgIGZ1bmN0aW9uIFRyYW5zaXRpb25BYm9ydGVkRXJyb3IobWVzc2FnZSkgewogICAgICB2YXIgZXJyb3IgPSBFcnJvci5jYWxsKHRoaXMsIG1lc3NhZ2UpOwogICAgICB0aGlzLm5hbWUgPSAnVHJhbnNpdGlvbkFib3J0ZWQnOwogICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlIHx8ICdUcmFuc2l0aW9uQWJvcnRlZCc7CgogICAgICBpZiAoRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpIHsKICAgICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBUcmFuc2l0aW9uQWJvcnRlZEVycm9yKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnN0YWNrID0gZXJyb3Iuc3RhY2s7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gVHJhbnNpdGlvbkFib3J0ZWRFcnJvcjsKICB9KCk7CgogIHZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTsKICB2YXIgaGFzT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5OwogIC8qKgogICAgRGV0ZXJtaW5lcyBpZiBhbiBvYmplY3QgaXMgUHJvbWlzZSBieSBjaGVja2luZyBpZiBpdCBpcyAidGhlbmFibGUiLgogICoqLwoKICBmdW5jdGlvbiBpc1Byb21pc2UocCkgewogICAgcmV0dXJuIHAgIT09IG51bGwgJiYgdHlwZW9mIHAgPT09ICdvYmplY3QnICYmIHR5cGVvZiBwLnRoZW4gPT09ICdmdW5jdGlvbic7CiAgfQoKICBmdW5jdGlvbiBtZXJnZShoYXNoLCBvdGhlcikgewogICAgZm9yICh2YXIgcHJvcCBpbiBvdGhlcikgewogICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvdGhlciwgcHJvcCkpIHsKICAgICAgICBoYXNoW3Byb3BdID0gb3RoZXJbcHJvcF07CiAgICAgIH0KICAgIH0KICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogIAogICAgRXh0cmFjdHMgcXVlcnkgcGFyYW1zIGZyb20gdGhlIGVuZCBvZiBhbiBhcnJheQogICoqLwoKCiAgZnVuY3Rpb24gZXh0cmFjdFF1ZXJ5UGFyYW1zKGFycmF5KSB7CiAgICB2YXIgbGVuID0gYXJyYXkgJiYgYXJyYXkubGVuZ3RoLAogICAgICAgIGhlYWQsCiAgICAgICAgcXVlcnlQYXJhbXM7CgogICAgaWYgKGxlbiAmJiBsZW4gPiAwKSB7CiAgICAgIHZhciBvYmogPSBhcnJheVtsZW4gLSAxXTsKCiAgICAgIGlmIChpc1F1ZXJ5UGFyYW1zKG9iaikpIHsKICAgICAgICBxdWVyeVBhcmFtcyA9IG9iai5xdWVyeVBhcmFtczsKICAgICAgICBoZWFkID0gc2xpY2UuY2FsbChhcnJheSwgMCwgbGVuIC0gMSk7CiAgICAgICAgcmV0dXJuIFtoZWFkLCBxdWVyeVBhcmFtc107CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gW2FycmF5LCBudWxsXTsKICB9CgogIGZ1bmN0aW9uIGlzUXVlcnlQYXJhbXMob2JqKSB7CiAgICByZXR1cm4gb2JqICYmIGhhc093blByb3BlcnR5LmNhbGwob2JqLCAncXVlcnlQYXJhbXMnKTsKICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogIAogICAgQ29lcmNlcyBxdWVyeSBwYXJhbSBwcm9wZXJ0aWVzIGFuZCBhcnJheSBlbGVtZW50cyBpbnRvIHN0cmluZ3MuCiAgKiovCgoKICBmdW5jdGlvbiBjb2VyY2VRdWVyeVBhcmFtc1RvU3RyaW5nKHF1ZXJ5UGFyYW1zKSB7CiAgICBmb3IgKHZhciBrZXkgaW4gcXVlcnlQYXJhbXMpIHsKICAgICAgdmFyIHZhbCA9IHF1ZXJ5UGFyYW1zW2tleV07CgogICAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHsKICAgICAgICBxdWVyeVBhcmFtc1trZXldID0gJycgKyB2YWw7CiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSB2YWwubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICB2YWxbaV0gPSAnJyArIHZhbFtpXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogICAqLwoKCiAgZnVuY3Rpb24gX2xvZyhyb3V0ZXIpIHsKICAgIGlmICghcm91dGVyLmxvZykgewogICAgICByZXR1cm47CiAgICB9CgogICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5ID0gMTsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICBhcmdzW19rZXkgLSAxXSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgIH0KCiAgICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHsKICAgICAgdmFyIHNlcXVlbmNlID0gYXJnc1swXSwKICAgICAgICAgIG1zZyA9IGFyZ3NbMV07CiAgICAgIHJvdXRlci5sb2coJ1RyYW5zaXRpb24gIycgKyBzZXF1ZW5jZSArICc6ICcgKyBtc2cpOwogICAgfSBlbHNlIHsKICAgICAgdmFyIF9tc2cgPSBhcmdzWzBdOwogICAgICByb3V0ZXIubG9nKF9tc2cpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gaXNQYXJhbShvYmplY3QpIHsKICAgIHJldHVybiB0eXBlb2Ygb2JqZWN0ID09PSAnc3RyaW5nJyB8fCBvYmplY3QgaW5zdGFuY2VvZiBTdHJpbmcgfHwgdHlwZW9mIG9iamVjdCA9PT0gJ251bWJlcicgfHwgb2JqZWN0IGluc3RhbmNlb2YgTnVtYmVyOwogIH0KCiAgZnVuY3Rpb24gZm9yRWFjaChhcnJheSwgY2FsbGJhY2spIHsKICAgIGZvciAodmFyIGkgPSAwLCBsID0gYXJyYXkubGVuZ3RoOyBpIDwgbCAmJiBjYWxsYmFjayhhcnJheVtpXSkgIT09IGZhbHNlOyBpKyspIHsvLyBlbXB0eSBpbnRlbnRpb25hbGx5CiAgICB9CiAgfQoKICBmdW5jdGlvbiBnZXRDaGFuZ2VsaXN0KG9sZE9iamVjdCwgbmV3T2JqZWN0KSB7CiAgICB2YXIga2V5OwogICAgdmFyIHJlc3VsdHMgPSB7CiAgICAgIGFsbDoge30sCiAgICAgIGNoYW5nZWQ6IHt9LAogICAgICByZW1vdmVkOiB7fQogICAgfTsKICAgIG1lcmdlKHJlc3VsdHMuYWxsLCBuZXdPYmplY3QpOwogICAgdmFyIGRpZENoYW5nZSA9IGZhbHNlOwogICAgY29lcmNlUXVlcnlQYXJhbXNUb1N0cmluZyhvbGRPYmplY3QpOwogICAgY29lcmNlUXVlcnlQYXJhbXNUb1N0cmluZyhuZXdPYmplY3QpOyAvLyBDYWxjdWxhdGUgcmVtb3ZhbHMKCiAgICBmb3IgKGtleSBpbiBvbGRPYmplY3QpIHsKICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2xkT2JqZWN0LCBrZXkpKSB7CiAgICAgICAgaWYgKCFoYXNPd25Qcm9wZXJ0eS5jYWxsKG5ld09iamVjdCwga2V5KSkgewogICAgICAgICAgZGlkQ2hhbmdlID0gdHJ1ZTsKICAgICAgICAgIHJlc3VsdHMucmVtb3ZlZFtrZXldID0gb2xkT2JqZWN0W2tleV07CiAgICAgICAgfQogICAgICB9CiAgICB9IC8vIENhbGN1bGF0ZSBjaGFuZ2VzCgoKICAgIGZvciAoa2V5IGluIG5ld09iamVjdCkgewogICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChuZXdPYmplY3QsIGtleSkpIHsKICAgICAgICB2YXIgb2xkRWxlbWVudCA9IG9sZE9iamVjdFtrZXldOwogICAgICAgIHZhciBuZXdFbGVtZW50ID0gbmV3T2JqZWN0W2tleV07CgogICAgICAgIGlmIChpc0FycmF5KG9sZEVsZW1lbnQpICYmIGlzQXJyYXkobmV3RWxlbWVudCkpIHsKICAgICAgICAgIGlmIChvbGRFbGVtZW50Lmxlbmd0aCAhPT0gbmV3RWxlbWVudC5sZW5ndGgpIHsKICAgICAgICAgICAgcmVzdWx0cy5jaGFuZ2VkW2tleV0gPSBuZXdPYmplY3Rba2V5XTsKICAgICAgICAgICAgZGlkQ2hhbmdlID0gdHJ1ZTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gb2xkRWxlbWVudC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgICAgICBpZiAob2xkRWxlbWVudFtpXSAhPT0gbmV3RWxlbWVudFtpXSkgewogICAgICAgICAgICAgICAgcmVzdWx0cy5jaGFuZ2VkW2tleV0gPSBuZXdPYmplY3Rba2V5XTsKICAgICAgICAgICAgICAgIGRpZENoYW5nZSA9IHRydWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChvbGRPYmplY3Rba2V5XSAhPT0gbmV3T2JqZWN0W2tleV0pIHsKICAgICAgICAgIHJlc3VsdHMuY2hhbmdlZFtrZXldID0gbmV3T2JqZWN0W2tleV07CiAgICAgICAgICBkaWRDaGFuZ2UgPSB0cnVlOwogICAgICAgIH0KICAgICAgfQogICAgfQoKICAgIHJldHVybiBkaWRDaGFuZ2UgPyByZXN1bHRzIDogdW5kZWZpbmVkOwogIH0KCiAgZnVuY3Rpb24gaXNBcnJheShvYmopIHsKICAgIHJldHVybiBBcnJheS5pc0FycmF5KG9iaik7CiAgfQoKICBmdW5jdGlvbiBfcHJvbWlzZUxhYmVsKGxhYmVsKSB7CiAgICByZXR1cm4gJ1JvdXRlcjogJyArIGxhYmVsOwogIH0KCiAgdmFyIFNUQVRFX1NZTUJPTCA9ICJfX1NUQVRFX18tMjYxOTg2MDAwMTM0NTkyMC0zMzIydzMiOwogIF9leHBvcnRzLlNUQVRFX1NZTUJPTCA9IFNUQVRFX1NZTUJPTDsKICB2YXIgUEFSQU1TX1NZTUJPTCA9ICJfX1BBUkFNU19fLTI2MTk4NjIzMjk5MjgzMDIwMy0yMzMyMyI7CiAgX2V4cG9ydHMuUEFSQU1TX1NZTUJPTCA9IFBBUkFNU19TWU1CT0w7CiAgdmFyIFFVRVJZX1BBUkFNU19TWU1CT0wgPSAiX19RUFNfXy0yNjE5ODYzOTI5ODI0ODQ0LTMyMzIzIjsKICAvKioKICAgIEEgVHJhbnNpdGlvbiBpcyBhIHRoZW5uYWJsZSAoYSBwcm9taXNlLWxpa2Ugb2JqZWN0KSB0aGF0IHJlcHJlc2VudHMKICAgIGFuIGF0dGVtcHQgdG8gdHJhbnNpdGlvbiB0byBhbm90aGVyIHJvdXRlLiBJdCBjYW4gYmUgYWJvcnRlZCwgZWl0aGVyCiAgICBleHBsaWNpdGx5IHZpYSBgYWJvcnRgIG9yIGJ5IGF0dGVtcHRpbmcgYW5vdGhlciB0cmFuc2l0aW9uIHdoaWxlIGEKICAgIHByZXZpb3VzIG9uZSBpcyBzdGlsbCB1bmRlcndheS4gQW4gYWJvcnRlZCB0cmFuc2l0aW9uIGNhbiBhbHNvCiAgICBiZSBgcmV0cnkoKWBkIGxhdGVyLgogIAogICAgQGNsYXNzIFRyYW5zaXRpb24KICAgIEBjb25zdHJ1Y3RvcgogICAgQHBhcmFtIHtPYmplY3R9IHJvdXRlcgogICAgQHBhcmFtIHtPYmplY3R9IGludGVudAogICAgQHBhcmFtIHtPYmplY3R9IHN0YXRlCiAgICBAcGFyYW0ge09iamVjdH0gZXJyb3IKICAgIEBwcml2YXRlCiAgICovCgogIF9leHBvcnRzLlFVRVJZX1BBUkFNU19TWU1CT0wgPSBRVUVSWV9QQVJBTVNfU1lNQk9MOwoKICB2YXIgVHJhbnNpdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFRyYW5zaXRpb24ocm91dGVyLCBpbnRlbnQsIHN0YXRlLCBlcnJvciwgcHJldmlvdXNUcmFuc2l0aW9uKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICBpZiAoZXJyb3IgPT09IHZvaWQgMCkgewogICAgICAgIGVycm9yID0gdW5kZWZpbmVkOwogICAgICB9CgogICAgICBpZiAocHJldmlvdXNUcmFuc2l0aW9uID09PSB2b2lkIDApIHsKICAgICAgICBwcmV2aW91c1RyYW5zaXRpb24gPSB1bmRlZmluZWQ7CiAgICAgIH0KCiAgICAgIHRoaXMuZnJvbSA9IG51bGw7CiAgICAgIHRoaXMudG8gPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuaXNBYm9ydGVkID0gZmFsc2U7CiAgICAgIHRoaXMuaXNBY3RpdmUgPSB0cnVlOwogICAgICB0aGlzLnVybE1ldGhvZCA9ICd1cGRhdGUnOwogICAgICB0aGlzLnJlc29sdmVJbmRleCA9IDA7CiAgICAgIHRoaXMucXVlcnlQYXJhbXNPbmx5ID0gZmFsc2U7CiAgICAgIHRoaXMuaXNUcmFuc2l0aW9uID0gdHJ1ZTsKICAgICAgdGhpcy5pc0NhdXNlZEJ5QWJvcnRpbmdUcmFuc2l0aW9uID0gZmFsc2U7CiAgICAgIHRoaXMuaXNDYXVzZWRCeUluaXRpYWxUcmFuc2l0aW9uID0gZmFsc2U7CiAgICAgIHRoaXMuaXNDYXVzZWRCeUFib3J0aW5nUmVwbGFjZVRyYW5zaXRpb24gPSBmYWxzZTsKICAgICAgdGhpcy5fdmlzaWJsZVF1ZXJ5UGFyYW1zID0ge307CiAgICAgIHRoaXNbU1RBVEVfU1lNQk9MXSA9IHN0YXRlIHx8IHJvdXRlci5zdGF0ZTsKICAgICAgdGhpcy5pbnRlbnQgPSBpbnRlbnQ7CiAgICAgIHRoaXMucm91dGVyID0gcm91dGVyOwogICAgICB0aGlzLmRhdGEgPSBpbnRlbnQgJiYgaW50ZW50LmRhdGEgfHwge307CiAgICAgIHRoaXMucmVzb2x2ZWRNb2RlbHMgPSB7fTsKICAgICAgdGhpc1tRVUVSWV9QQVJBTVNfU1lNQk9MXSA9IHt9OwogICAgICB0aGlzLnByb21pc2UgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuZXJyb3IgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXNbUEFSQU1TX1NZTUJPTF0gPSB7fTsKICAgICAgdGhpcy5yb3V0ZUluZm9zID0gW107CiAgICAgIHRoaXMudGFyZ2V0TmFtZSA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5waXZvdEhhbmRsZXIgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuc2VxdWVuY2UgPSAtMTsKCiAgICAgIGlmIChlcnJvcikgewogICAgICAgIHRoaXMucHJvbWlzZSA9IF9yc3ZwLlByb21pc2UucmVqZWN0KGVycm9yKTsKICAgICAgICB0aGlzLmVycm9yID0gZXJyb3I7CiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIGlmIHlvdSdyZSBkb2luZyBtdWx0aXBsZSByZWRpcmVjdHMsIG5lZWQgdGhlIG5ldyB0cmFuc2l0aW9uIHRvIGtub3cgaWYgaXQKICAgICAgLy8gaXMgYWN0dWFsbHkgcGFydCBvZiB0aGUgZmlyc3QgdHJhbnNpdGlvbiBvciBub3QuIEFueSBmdXJ0aGVyIHJlZGlyZWN0cwogICAgICAvLyBpbiB0aGUgaW5pdGlhbCB0cmFuc2l0aW9uIGFsc28gbmVlZCB0byBrbm93IGlmIHRoZXkgYXJlIHBhcnQgb2YgdGhlCiAgICAgIC8vIGluaXRpYWwgdHJhbnNpdGlvbgoKCiAgICAgIHRoaXMuaXNDYXVzZWRCeUFib3J0aW5nVHJhbnNpdGlvbiA9ICEhcHJldmlvdXNUcmFuc2l0aW9uOwogICAgICB0aGlzLmlzQ2F1c2VkQnlJbml0aWFsVHJhbnNpdGlvbiA9ICEhcHJldmlvdXNUcmFuc2l0aW9uICYmIChwcmV2aW91c1RyYW5zaXRpb24uaXNDYXVzZWRCeUluaXRpYWxUcmFuc2l0aW9uIHx8IHByZXZpb3VzVHJhbnNpdGlvbi5zZXF1ZW5jZSA9PT0gMCk7IC8vIEV2ZXJ5IHRyYW5zaXRpb24gaW4gdGhlIGNoYWluIGlzIGEgcmVwbGFjZQoKICAgICAgdGhpcy5pc0NhdXNlZEJ5QWJvcnRpbmdSZXBsYWNlVHJhbnNpdGlvbiA9ICEhcHJldmlvdXNUcmFuc2l0aW9uICYmIHByZXZpb3VzVHJhbnNpdGlvbi51cmxNZXRob2QgPT09ICdyZXBsYWNlJyAmJiAoIXByZXZpb3VzVHJhbnNpdGlvbi5pc0NhdXNlZEJ5QWJvcnRpbmdUcmFuc2l0aW9uIHx8IHByZXZpb3VzVHJhbnNpdGlvbi5pc0NhdXNlZEJ5QWJvcnRpbmdSZXBsYWNlVHJhbnNpdGlvbik7CgogICAgICBpZiAoc3RhdGUpIHsKICAgICAgICB0aGlzW1BBUkFNU19TWU1CT0xdID0gc3RhdGUucGFyYW1zOwogICAgICAgIHRoaXNbUVVFUllfUEFSQU1TX1NZTUJPTF0gPSBzdGF0ZS5xdWVyeVBhcmFtczsKICAgICAgICB0aGlzLnJvdXRlSW5mb3MgPSBzdGF0ZS5yb3V0ZUluZm9zOwogICAgICAgIHZhciBsZW4gPSBzdGF0ZS5yb3V0ZUluZm9zLmxlbmd0aDsKCiAgICAgICAgaWYgKGxlbikgewogICAgICAgICAgdGhpcy50YXJnZXROYW1lID0gc3RhdGUucm91dGVJbmZvc1tsZW4gLSAxXS5uYW1lOwogICAgICAgIH0KCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSkgewogICAgICAgICAgdmFyIGhhbmRsZXJJbmZvID0gc3RhdGUucm91dGVJbmZvc1tpXTsgLy8gVE9ETzogdGhpcyBhbGwgc2VlbXMgaGFja3kKCiAgICAgICAgICBpZiAoIWhhbmRsZXJJbmZvLmlzUmVzb2x2ZWQpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5waXZvdEhhbmRsZXIgPSBoYW5kbGVySW5mby5yb3V0ZTsKICAgICAgICB9CgogICAgICAgIHRoaXMuc2VxdWVuY2UgPSByb3V0ZXIuY3VycmVudFNlcXVlbmNlKys7CiAgICAgICAgdGhpcy5wcm9taXNlID0gc3RhdGUucmVzb2x2ZShmdW5jdGlvbiAoKSB7CiAgICAgICAgICBpZiAoX3RoaXMuaXNBYm9ydGVkKSB7CiAgICAgICAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlamVjdChmYWxzZSwgX3Byb21pc2VMYWJlbCgnVHJhbnNpdGlvbiBhYm9ydGVkIC0gcmVqZWN0JykpOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlc29sdmUodHJ1ZSk7CiAgICAgICAgfSwgdGhpcykuY2F0Y2goZnVuY3Rpb24gKHJlc3VsdCkgewogICAgICAgICAgcmV0dXJuIF9yc3ZwLlByb21pc2UucmVqZWN0KF90aGlzLnJvdXRlci50cmFuc2l0aW9uRGlkRXJyb3IocmVzdWx0LCBfdGhpcykpOwogICAgICAgIH0sIF9wcm9taXNlTGFiZWwoJ0hhbmRsZSBBYm9ydCcpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnByb21pc2UgPSBfcnN2cC5Qcm9taXNlLnJlc29sdmUodGhpc1tTVEFURV9TWU1CT0xdKTsKICAgICAgICB0aGlzW1BBUkFNU19TWU1CT0xdID0ge307CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBUaGUgVHJhbnNpdGlvbidzIGludGVybmFsIHByb21pc2UuIENhbGxpbmcgYC50aGVuYCBvbiB0aGlzIHByb3BlcnR5CiAgICAgIGlzIHRoYXQgc2FtZSBhcyBjYWxsaW5nIGAudGhlbmAgb24gdGhlIFRyYW5zaXRpb24gb2JqZWN0IGl0c2VsZiwgYnV0CiAgICAgIHRoaXMgcHJvcGVydHkgaXMgZXhwb3NlZCBmb3Igd2hlbiB5b3Ugd2FudCB0byBwYXNzIGFyb3VuZCBhCiAgICAgIFRyYW5zaXRpb24ncyBwcm9taXNlLCBidXQgbm90IHRoZSBUcmFuc2l0aW9uIG9iamVjdCBpdHNlbGYsIHNpbmNlCiAgICAgIFRyYW5zaXRpb24gb2JqZWN0IGNhbiBiZSBleHRlcm5hbGx5IGBhYm9ydGBlZCwgd2hpbGUgdGhlIHByb21pc2UKICAgICAgY2Fubm90LgogICAgICAgICBAcHJvcGVydHkgcHJvbWlzZQogICAgICBAdHlwZSB7T2JqZWN0fQogICAgICBAcHVibGljCiAgICAgKi8KCiAgICAvKioKICAgICAgQ3VzdG9tIHN0YXRlIGNhbiBiZSBzdG9yZWQgb24gYSBUcmFuc2l0aW9uJ3MgYGRhdGFgIG9iamVjdC4KICAgICAgVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBkZWNvcmF0aW5nIGEgVHJhbnNpdGlvbiB3aXRoaW4gYW4gZWFybGllcgogICAgICBob29rIGFuZCBzaGFyZWQgd2l0aCBhIGxhdGVyIGhvb2suIFByb3BlcnRpZXMgc2V0IG9uIGBkYXRhYCB3aWxsCiAgICAgIGJlIGNvcGllZCB0byBuZXcgdHJhbnNpdGlvbnMgZ2VuZXJhdGVkIGJ5IGNhbGxpbmcgYHJldHJ5YCBvbiB0aGlzCiAgICAgIHRyYW5zaXRpb24uCiAgICAgICAgIEBwcm9wZXJ0eSBkYXRhCiAgICAgIEB0eXBlIHtPYmplY3R9CiAgICAgIEBwdWJsaWMKICAgICAqLwoKICAgIC8qKgogICAgICBBIHN0YW5kYXJkIHByb21pc2UgaG9vayB0aGF0IHJlc29sdmVzIGlmIHRoZSB0cmFuc2l0aW9uCiAgICAgIHN1Y2NlZWRzIGFuZCByZWplY3RzIGlmIGl0IGZhaWxzL3JlZGlyZWN0cy9hYm9ydHMuCiAgICAgICAgIEZvcndhcmRzIHRvIHRoZSBpbnRlcm5hbCBgcHJvbWlzZWAgcHJvcGVydHkgd2hpY2ggeW91IGNhbgogICAgICB1c2UgaW4gc2l0dWF0aW9ucyB3aGVyZSB5b3Ugd2FudCB0byBwYXNzIGFyb3VuZCBhIHRoZW5uYWJsZSwKICAgICAgYnV0IG5vdCB0aGUgVHJhbnNpdGlvbiBpdHNlbGYuCiAgICAgICAgIEBtZXRob2QgdGhlbgogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvbkZ1bGZpbGxlZAogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGVkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBsYWJlbCBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICAgIEByZXR1cm4ge1Byb21pc2V9CiAgICAgIEBwdWJsaWMKICAgICAqLwoKCiAgICB2YXIgX3Byb3RvID0gVHJhbnNpdGlvbi5wcm90b3R5cGU7CgogICAgX3Byb3RvLnRoZW4gPSBmdW5jdGlvbiB0aGVuKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkLCBsYWJlbCkgewogICAgICByZXR1cm4gdGhpcy5wcm9taXNlLnRoZW4ob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQsIGxhYmVsKTsKICAgIH0KICAgIC8qKgogICAgICAgICBGb3J3YXJkcyB0byB0aGUgaW50ZXJuYWwgYHByb21pc2VgIHByb3BlcnR5IHdoaWNoIHlvdSBjYW4KICAgICAgdXNlIGluIHNpdHVhdGlvbnMgd2hlcmUgeW91IHdhbnQgdG8gcGFzcyBhcm91bmQgYSB0aGVubmFibGUsCiAgICAgIGJ1dCBub3QgdGhlIFRyYW5zaXRpb24gaXRzZWxmLgogICAgICAgICBAbWV0aG9kIGNhdGNoCiAgICAgIEBwYXJhbSB7RnVuY3Rpb259IG9uUmVqZWN0aW9uCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBsYWJlbCBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICAgIEByZXR1cm4ge1Byb21pc2V9CiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by5jYXRjaCA9IGZ1bmN0aW9uIF9jYXRjaChvblJlamVjdGlvbiwgbGFiZWwpIHsKICAgICAgcmV0dXJuIHRoaXMucHJvbWlzZS5jYXRjaChvblJlamVjdGlvbiwgbGFiZWwpOwogICAgfQogICAgLyoqCiAgICAgICAgIEZvcndhcmRzIHRvIHRoZSBpbnRlcm5hbCBgcHJvbWlzZWAgcHJvcGVydHkgd2hpY2ggeW91IGNhbgogICAgICB1c2UgaW4gc2l0dWF0aW9ucyB3aGVyZSB5b3Ugd2FudCB0byBwYXNzIGFyb3VuZCBhIHRoZW5uYWJsZSwKICAgICAgYnV0IG5vdCB0aGUgVHJhbnNpdGlvbiBpdHNlbGYuCiAgICAgICAgIEBtZXRob2QgZmluYWxseQogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgICBAcGFyYW0ge1N0cmluZ30gbGFiZWwgb3B0aW9uYWwgc3RyaW5nIGZvciBsYWJlbGluZyB0aGUgcHJvbWlzZS4KICAgICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgICBAcmV0dXJuIHtQcm9taXNlfQogICAgICBAcHVibGljCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZmluYWxseSA9IGZ1bmN0aW9uIF9maW5hbGx5KGNhbGxiYWNrLCBsYWJlbCkgewogICAgICByZXR1cm4gdGhpcy5wcm9taXNlLmZpbmFsbHkoY2FsbGJhY2ssIGxhYmVsKTsKICAgIH0KICAgIC8qKgogICAgICBBYm9ydHMgdGhlIFRyYW5zaXRpb24uIE5vdGUgeW91IGNhbiBhbHNvIGltcGxpY2l0bHkgYWJvcnQgYSB0cmFuc2l0aW9uCiAgICAgIGJ5IGluaXRpYXRpbmcgYW5vdGhlciB0cmFuc2l0aW9uIHdoaWxlIGEgcHJldmlvdXMgb25lIGlzIHVuZGVyd2F5LgogICAgICAgICBAbWV0aG9kIGFib3J0CiAgICAgIEByZXR1cm4ge1RyYW5zaXRpb259IHRoaXMgdHJhbnNpdGlvbgogICAgICBAcHVibGljCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uYWJvcnQgPSBmdW5jdGlvbiBhYm9ydCgpIHsKICAgICAgdGhpcy5yb2xsYmFjaygpOwogICAgICB2YXIgdHJhbnNpdGlvbiA9IG5ldyBUcmFuc2l0aW9uKHRoaXMucm91dGVyLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkKTsKICAgICAgdHJhbnNpdGlvbi50byA9IHRoaXMuZnJvbTsKICAgICAgdHJhbnNpdGlvbi5mcm9tID0gdGhpcy5mcm9tOwogICAgICB0cmFuc2l0aW9uLmlzQWJvcnRlZCA9IHRydWU7CiAgICAgIHRoaXMucm91dGVyLnJvdXRlV2lsbENoYW5nZSh0cmFuc2l0aW9uKTsKICAgICAgdGhpcy5yb3V0ZXIucm91dGVEaWRDaGFuZ2UodHJhbnNpdGlvbik7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICBfcHJvdG8ucm9sbGJhY2sgPSBmdW5jdGlvbiByb2xsYmFjaygpIHsKICAgICAgaWYgKCF0aGlzLmlzQWJvcnRlZCkgewogICAgICAgIF9sb2codGhpcy5yb3V0ZXIsIHRoaXMuc2VxdWVuY2UsIHRoaXMudGFyZ2V0TmFtZSArICc6IHRyYW5zaXRpb24gd2FzIGFib3J0ZWQnKTsKCiAgICAgICAgaWYgKHRoaXMuaW50ZW50ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnRlbnQgIT09IG51bGwpIHsKICAgICAgICAgIHRoaXMuaW50ZW50LnByZVRyYW5zaXRpb25TdGF0ZSA9IHRoaXMucm91dGVyLnN0YXRlOwogICAgICAgIH0KCiAgICAgICAgdGhpcy5pc0Fib3J0ZWQgPSB0cnVlOwogICAgICAgIHRoaXMuaXNBY3RpdmUgPSBmYWxzZTsKICAgICAgICB0aGlzLnJvdXRlci5hY3RpdmVUcmFuc2l0aW9uID0gdW5kZWZpbmVkOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZWRpcmVjdCA9IGZ1bmN0aW9uIHJlZGlyZWN0KG5ld1RyYW5zaXRpb24pIHsKICAgICAgdGhpcy5yb2xsYmFjaygpOwogICAgICB0aGlzLnJvdXRlci5yb3V0ZVdpbGxDaGFuZ2UobmV3VHJhbnNpdGlvbik7CiAgICB9CiAgICAvKioKICAgICAgICAgUmV0cmllcyBhIHByZXZpb3VzbHktYWJvcnRlZCB0cmFuc2l0aW9uIChtYWtpbmcgc3VyZSB0byBhYm9ydCB0aGUKICAgICAgdHJhbnNpdGlvbiBpZiBpdCdzIHN0aWxsIGFjdGl2ZSkuIFJldHVybnMgYSBuZXcgdHJhbnNpdGlvbiB0aGF0CiAgICAgIHJlcHJlc2VudHMgdGhlIG5ldyBhdHRlbXB0IHRvIHRyYW5zaXRpb24uCiAgICAgICAgIEBtZXRob2QgcmV0cnkKICAgICAgQHJldHVybiB7VHJhbnNpdGlvbn0gbmV3IHRyYW5zaXRpb24KICAgICAgQHB1YmxpYwogICAgICovCiAgICA7CgogICAgX3Byb3RvLnJldHJ5ID0gZnVuY3Rpb24gcmV0cnkoKSB7CiAgICAgIC8vIFRPRE86IGFkZCB0ZXN0cyBmb3IgbWVyZ2VkIHN0YXRlIHJldHJ5KClzCiAgICAgIHRoaXMuYWJvcnQoKTsKICAgICAgdmFyIG5ld1RyYW5zaXRpb24gPSB0aGlzLnJvdXRlci50cmFuc2l0aW9uQnlJbnRlbnQodGhpcy5pbnRlbnQsIGZhbHNlKTsgLy8gaW5oZXJpdGluZyBhIGBudWxsYCB1cmxNZXRob2QgaXMgbm90IHZhbGlkCiAgICAgIC8vIHRoZSB1cmxNZXRob2QgaXMgb25seSBzZXQgdG8gYG51bGxgIHdoZW4KICAgICAgLy8gdGhlIHRyYW5zaXRpb24gaXMgaW5pdGlhdGVkICphZnRlciogdGhlIHVybAogICAgICAvLyBoYXMgYmVlbiB1cGRhdGVkIChpLmUuIGByb3V0ZXIuaGFuZGxlVVJMYCkKICAgICAgLy8KICAgICAgLy8gaW4gdGhhdCBzY2VuYXJpbywgdGhlIHVybCBtZXRob2QgY2Fubm90IGJlCiAgICAgIC8vIGluaGVyaXRlZCBmb3IgYSBuZXcgdHJhbnNpdGlvbiBiZWNhdXNlIHRoZW4KICAgICAgLy8gdGhlIHVybCB3b3VsZCBub3QgdXBkYXRlIGV2ZW4gdGhvdWdoIGl0IHNob3VsZAoKICAgICAgaWYgKHRoaXMudXJsTWV0aG9kICE9PSBudWxsKSB7CiAgICAgICAgbmV3VHJhbnNpdGlvbi5tZXRob2QodGhpcy51cmxNZXRob2QpOwogICAgICB9CgogICAgICByZXR1cm4gbmV3VHJhbnNpdGlvbjsKICAgIH0KICAgIC8qKgogICAgICAgICBTZXRzIHRoZSBVUkwtY2hhbmdpbmcgbWV0aG9kIHRvIGJlIGVtcGxveWVkIGF0IHRoZSBlbmQgb2YgYQogICAgICBzdWNjZXNzZnVsIHRyYW5zaXRpb24uIEJ5IGRlZmF1bHQsIGEgbmV3IFRyYW5zaXRpb24gd2lsbCBqdXN0CiAgICAgIHVzZSBgdXBkYXRlVVJMYCwgYnV0IHBhc3NpbmcgJ3JlcGxhY2UnIHRvIHRoaXMgbWV0aG9kIHdpbGwKICAgICAgY2F1c2UgdGhlIFVSTCB0byB1cGRhdGUgdXNpbmcgJ3JlcGxhY2VXaXRoJyBpbnN0ZWFkLiBPbWl0dGluZwogICAgICBhIHBhcmFtZXRlciB3aWxsIGRpc2FibGUgdGhlIFVSTCBjaGFuZ2UsIGFsbG93aW5nIGZvciB0cmFuc2l0aW9ucwogICAgICB0aGF0IGRvbid0IHVwZGF0ZSB0aGUgVVJMIGF0IGNvbXBsZXRpb24gKHRoaXMgaXMgYWxzbyB1c2VkIGZvcgogICAgICBoYW5kbGVVUkwsIHNpbmNlIHRoZSBVUkwgaGFzIGFscmVhZHkgY2hhbmdlZCBiZWZvcmUgdGhlCiAgICAgIHRyYW5zaXRpb24gdG9vayBwbGFjZSkuCiAgICAgICAgIEBtZXRob2QgbWV0aG9kCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgdGhlIHR5cGUgb2YgVVJMLWNoYW5naW5nIG1ldGhvZCB0byB1c2UKICAgICAgICBhdCB0aGUgZW5kIG9mIGEgdHJhbnNpdGlvbi4gQWNjZXB0ZWQgdmFsdWVzIGFyZSAncmVwbGFjZScsCiAgICAgICAgZmFsc3kgdmFsdWVzLCBvciBhbnkgb3RoZXIgbm9uLWZhbHN5IHZhbHVlICh3aGljaCBpcwogICAgICAgIGludGVycHJldGVkIGFzIGFuIHVwZGF0ZVVSTCB0cmFuc2l0aW9uKS4KICAgICAgICAgQHJldHVybiB7VHJhbnNpdGlvbn0gdGhpcyB0cmFuc2l0aW9uCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by5tZXRob2QgPSBmdW5jdGlvbiBtZXRob2QoX21ldGhvZCkgewogICAgICB0aGlzLnVybE1ldGhvZCA9IF9tZXRob2Q7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSAvLyBBbGlhcyAndHJpZ2dlcicgYXMgJ3NlbmQnCiAgICA7CgogICAgX3Byb3RvLnNlbmQgPSBmdW5jdGlvbiBzZW5kKGlnbm9yZUZhaWx1cmUsIF9uYW1lLCBlcnIsIHRyYW5zaXRpb24sIGhhbmRsZXIpIHsKICAgICAgaWYgKGlnbm9yZUZhaWx1cmUgPT09IHZvaWQgMCkgewogICAgICAgIGlnbm9yZUZhaWx1cmUgPSBmYWxzZTsKICAgICAgfQoKICAgICAgdGhpcy50cmlnZ2VyKGlnbm9yZUZhaWx1cmUsIF9uYW1lLCBlcnIsIHRyYW5zaXRpb24sIGhhbmRsZXIpOwogICAgfQogICAgLyoqCiAgICAgICAgIEZpcmVzIGFuIGV2ZW50IG9uIHRoZSBjdXJyZW50IGxpc3Qgb2YgcmVzb2x2ZWQvcmVzb2x2aW5nCiAgICAgIGhhbmRsZXJzIHdpdGhpbiB0aGlzIHRyYW5zaXRpb24uIFVzZWZ1bCBmb3IgZmlyaW5nIGV2ZW50cwogICAgICBvbiByb3V0ZSBoaWVyYXJjaGllcyB0aGF0IGhhdmVuJ3QgZnVsbHkgYmVlbiBlbnRlcmVkIHlldC4KICAgICAgICAgTm90ZTogVGhpcyBtZXRob2QgaXMgYWxzbyBhbGlhc2VkIGFzIGBzZW5kYAogICAgICAgICBAbWV0aG9kIHRyaWdnZXIKICAgICAgQHBhcmFtIHtCb29sZWFufSBbaWdub3JlRmFpbHVyZT1mYWxzZV0gYSBib29sZWFuIHNwZWNpZnlpbmcgd2hldGhlciB1bmhhbmRsZWQgZXZlbnRzIHRocm93IGFuIGVycm9yCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBmaXJlCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by50cmlnZ2VyID0gZnVuY3Rpb24gdHJpZ2dlcihpZ25vcmVGYWlsdXJlLCBuYW1lKSB7CiAgICAgIGlmIChpZ25vcmVGYWlsdXJlID09PSB2b2lkIDApIHsKICAgICAgICBpZ25vcmVGYWlsdXJlID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIC8vIFRPRE86IERlcHJlY2F0ZSB0aGUgY3VycmVudCBzaWduYXR1cmUKICAgICAgaWYgKHR5cGVvZiBpZ25vcmVGYWlsdXJlID09PSAnc3RyaW5nJykgewogICAgICAgIG5hbWUgPSBpZ25vcmVGYWlsdXJlOwogICAgICAgIGlnbm9yZUZhaWx1cmUgPSBmYWxzZTsKICAgICAgfQoKICAgICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4yID4gMiA/IF9sZW4yIC0gMiA6IDApLCBfa2V5MiA9IDI7IF9rZXkyIDwgX2xlbjI7IF9rZXkyKyspIHsKICAgICAgICBhcmdzW19rZXkyIC0gMl0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICB9CgogICAgICB0aGlzLnJvdXRlci50cmlnZ2VyRXZlbnQodGhpc1tTVEFURV9TWU1CT0xdLnJvdXRlSW5mb3Muc2xpY2UoMCwgdGhpcy5yZXNvbHZlSW5kZXggKyAxKSwgaWdub3JlRmFpbHVyZSwgbmFtZSwgYXJncyk7CiAgICB9CiAgICAvKioKICAgICAgVHJhbnNpdGlvbnMgYXJlIGFib3J0ZWQgYW5kIHRoZWlyIHByb21pc2VzIHJlamVjdGVkCiAgICAgIHdoZW4gcmVkaXJlY3RzIG9jY3VyOyB0aGlzIG1ldGhvZCByZXR1cm5zIGEgcHJvbWlzZQogICAgICB0aGF0IHdpbGwgZm9sbG93IGFueSByZWRpcmVjdHMgdGhhdCBvY2N1ciBhbmQgZnVsZmlsbAogICAgICB3aXRoIHRoZSB2YWx1ZSBmdWxmaWxsZWQgYnkgYW55IHJlZGlyZWN0aW5nIHRyYW5zaXRpb25zCiAgICAgIHRoYXQgb2NjdXIuCiAgICAgICAgIEBtZXRob2QgZm9sbG93UmVkaXJlY3RzCiAgICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIHdpdGggdGhlIHNhbWUKICAgICAgICB2YWx1ZSB0aGF0IHRoZSBmaW5hbCByZWRpcmVjdGluZyB0cmFuc2l0aW9uIGZ1bGZpbGxzIHdpdGgKICAgICAgQHB1YmxpYwogICAgICovCiAgICA7CgogICAgX3Byb3RvLmZvbGxvd1JlZGlyZWN0cyA9IGZ1bmN0aW9uIGZvbGxvd1JlZGlyZWN0cygpIHsKICAgICAgdmFyIHJvdXRlciA9IHRoaXMucm91dGVyOwogICAgICByZXR1cm4gdGhpcy5wcm9taXNlLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICBpZiAocm91dGVyLmFjdGl2ZVRyYW5zaXRpb24pIHsKICAgICAgICAgIHJldHVybiByb3V0ZXIuYWN0aXZlVHJhbnNpdGlvbi5mb2xsb3dSZWRpcmVjdHMoKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlamVjdChyZWFzb24pOwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiAnVHJhbnNpdGlvbiAoc2VxdWVuY2UgJyArIHRoaXMuc2VxdWVuY2UgKyAnKSc7CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAqLwogICAgOwoKICAgIF9wcm90by5sb2cgPSBmdW5jdGlvbiBsb2cobWVzc2FnZSkgewogICAgICBfbG9nKHRoaXMucm91dGVyLCB0aGlzLnNlcXVlbmNlLCBtZXNzYWdlKTsKICAgIH07CgogICAgcmV0dXJuIFRyYW5zaXRpb247CiAgfSgpOwogIC8qKgogICAgQHByaXZhdGUKICAKICAgIExvZ3MgYW5kIHJldHVybnMgYW4gaW5zdGFuY2Ugb2YgVHJhbnNpdGlvbkFib3J0ZWQuCiAgICovCgoKICBfZXhwb3J0cy5JbnRlcm5hbFRyYW5zaXRpb24gPSBUcmFuc2l0aW9uOwoKICBmdW5jdGlvbiBsb2dBYm9ydCh0cmFuc2l0aW9uKSB7CiAgICBfbG9nKHRyYW5zaXRpb24ucm91dGVyLCB0cmFuc2l0aW9uLnNlcXVlbmNlLCAnZGV0ZWN0ZWQgYWJvcnQuJyk7CgogICAgcmV0dXJuIG5ldyBUcmFuc2l0aW9uQWJvcnRlZEVycm9yKCk7CiAgfQoKICBmdW5jdGlvbiBpc1RyYW5zaXRpb24ob2JqKSB7CiAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgb2JqIGluc3RhbmNlb2YgVHJhbnNpdGlvbiAmJiBvYmouaXNUcmFuc2l0aW9uOwogIH0KCiAgZnVuY3Rpb24gcHJlcGFyZVJlc3VsdChvYmopIHsKICAgIGlmIChpc1RyYW5zaXRpb24ob2JqKSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KCiAgICByZXR1cm4gb2JqOwogIH0KCiAgdmFyIFJPVVRFX0lORk9TID0gbmV3IFdlYWtNYXAoKTsKCiAgZnVuY3Rpb24gdG9SZWFkT25seVJvdXRlSW5mbyhyb3V0ZUluZm9zLCBxdWVyeVBhcmFtcywgaW5jbHVkZUF0dHJpYnV0ZXMpIHsKICAgIGlmIChxdWVyeVBhcmFtcyA9PT0gdm9pZCAwKSB7CiAgICAgIHF1ZXJ5UGFyYW1zID0ge307CiAgICB9CgogICAgaWYgKGluY2x1ZGVBdHRyaWJ1dGVzID09PSB2b2lkIDApIHsKICAgICAgaW5jbHVkZUF0dHJpYnV0ZXMgPSBmYWxzZTsKICAgIH0KCiAgICByZXR1cm4gcm91dGVJbmZvcy5tYXAoZnVuY3Rpb24gKGluZm8sIGkpIHsKICAgICAgdmFyIG5hbWUgPSBpbmZvLm5hbWUsCiAgICAgICAgICBwYXJhbXMgPSBpbmZvLnBhcmFtcywKICAgICAgICAgIHBhcmFtTmFtZXMgPSBpbmZvLnBhcmFtTmFtZXMsCiAgICAgICAgICBjb250ZXh0ID0gaW5mby5jb250ZXh0LAogICAgICAgICAgcm91dGUgPSBpbmZvLnJvdXRlOwoKICAgICAgaWYgKFJPVVRFX0lORk9TLmhhcyhpbmZvKSAmJiBpbmNsdWRlQXR0cmlidXRlcykgewogICAgICAgIHZhciBfcm91dGVJbmZvID0gUk9VVEVfSU5GT1MuZ2V0KGluZm8pOwoKICAgICAgICBfcm91dGVJbmZvID0gYXR0YWNoTWV0YWRhdGEocm91dGUsIF9yb3V0ZUluZm8pOwogICAgICAgIHZhciByb3V0ZUluZm9XaXRoQXR0cmlidXRlID0gY3JlYXRlUm91dGVJbmZvV2l0aEF0dHJpYnV0ZXMoX3JvdXRlSW5mbywgY29udGV4dCk7CiAgICAgICAgUk9VVEVfSU5GT1Muc2V0KGluZm8sIHJvdXRlSW5mb1dpdGhBdHRyaWJ1dGUpOwogICAgICAgIHJldHVybiByb3V0ZUluZm9XaXRoQXR0cmlidXRlOwogICAgICB9CgogICAgICB2YXIgcm91dGVJbmZvID0gewogICAgICAgIGZpbmQ6IGZ1bmN0aW9uIGZpbmQocHJlZGljYXRlLCB0aGlzQXJnKSB7CiAgICAgICAgICB2YXIgcHVibGljSW5mbzsKICAgICAgICAgIHZhciBhcnIgPSBbXTsKCiAgICAgICAgICBpZiAocHJlZGljYXRlLmxlbmd0aCA9PT0gMykgewogICAgICAgICAgICBhcnIgPSByb3V0ZUluZm9zLm1hcChmdW5jdGlvbiAoaW5mbykgewogICAgICAgICAgICAgIHJldHVybiBST1VURV9JTkZPUy5nZXQoaW5mbyk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQoKICAgICAgICAgIGZvciAodmFyIF9pID0gMDsgcm91dGVJbmZvcy5sZW5ndGggPiBfaTsgX2krKykgewogICAgICAgICAgICBwdWJsaWNJbmZvID0gUk9VVEVfSU5GT1MuZ2V0KHJvdXRlSW5mb3NbX2ldKTsKCiAgICAgICAgICAgIGlmIChwcmVkaWNhdGUuY2FsbCh0aGlzQXJnLCBwdWJsaWNJbmZvLCBfaSwgYXJyKSkgewogICAgICAgICAgICAgIHJldHVybiBwdWJsaWNJbmZvOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgICAgICB9LAoKICAgICAgICBnZXQgbmFtZSgpIHsKICAgICAgICAgIHJldHVybiBuYW1lOwogICAgICAgIH0sCgogICAgICAgIGdldCBwYXJhbU5hbWVzKCkgewogICAgICAgICAgcmV0dXJuIHBhcmFtTmFtZXM7CiAgICAgICAgfSwKCiAgICAgICAgZ2V0IG1ldGFkYXRhKCkgewogICAgICAgICAgcmV0dXJuIGJ1aWxkUm91dGVJbmZvTWV0YWRhdGEoaW5mby5yb3V0ZSk7CiAgICAgICAgfSwKCiAgICAgICAgZ2V0IHBhcmVudCgpIHsKICAgICAgICAgIHZhciBwYXJlbnQgPSByb3V0ZUluZm9zW2kgLSAxXTsKCiAgICAgICAgICBpZiAocGFyZW50ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIFJPVVRFX0lORk9TLmdldChwYXJlbnQpOwogICAgICAgIH0sCgogICAgICAgIGdldCBjaGlsZCgpIHsKICAgICAgICAgIHZhciBjaGlsZCA9IHJvdXRlSW5mb3NbaSArIDFdOwoKICAgICAgICAgIGlmIChjaGlsZCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBST1VURV9JTkZPUy5nZXQoY2hpbGQpOwogICAgICAgIH0sCgogICAgICAgIGdldCBsb2NhbE5hbWUoKSB7CiAgICAgICAgICB2YXIgcGFydHMgPSB0aGlzLm5hbWUuc3BsaXQoJy4nKTsKICAgICAgICAgIHJldHVybiBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXTsKICAgICAgICB9LAoKICAgICAgICBnZXQgcGFyYW1zKCkgewogICAgICAgICAgcmV0dXJuIHBhcmFtczsKICAgICAgICB9LAoKICAgICAgICBnZXQgcXVlcnlQYXJhbXMoKSB7CiAgICAgICAgICByZXR1cm4gcXVlcnlQYXJhbXM7CiAgICAgICAgfQoKICAgICAgfTsKCiAgICAgIGlmIChpbmNsdWRlQXR0cmlidXRlcykgewogICAgICAgIHJvdXRlSW5mbyA9IGNyZWF0ZVJvdXRlSW5mb1dpdGhBdHRyaWJ1dGVzKHJvdXRlSW5mbywgY29udGV4dCk7CiAgICAgIH0KCiAgICAgIFJPVVRFX0lORk9TLnNldChpbmZvLCByb3V0ZUluZm8pOwogICAgICByZXR1cm4gcm91dGVJbmZvOwogICAgfSk7CiAgfQoKICBmdW5jdGlvbiBjcmVhdGVSb3V0ZUluZm9XaXRoQXR0cmlidXRlcyhyb3V0ZUluZm8sIGNvbnRleHQpIHsKICAgIHZhciBhdHRyaWJ1dGVzID0gewogICAgICBnZXQgYXR0cmlidXRlcygpIHsKICAgICAgICByZXR1cm4gY29udGV4dDsKICAgICAgfQoKICAgIH07CgogICAgaWYgKE9iamVjdC5pc0Zyb3plbihyb3V0ZUluZm8pIHx8IHJvdXRlSW5mby5oYXNPd25Qcm9wZXJ0eSgnYXR0cmlidXRlcycpKSB7CiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKCgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIHJvdXRlSW5mbywgYXR0cmlidXRlcykpOwogICAgfQoKICAgIHJldHVybiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHJvdXRlSW5mbywgYXR0cmlidXRlcyk7CiAgfQoKICBmdW5jdGlvbiBidWlsZFJvdXRlSW5mb01ldGFkYXRhKHJvdXRlKSB7CiAgICBpZiAocm91dGUgIT09IHVuZGVmaW5lZCAmJiByb3V0ZSAhPT0gbnVsbCAmJiByb3V0ZS5idWlsZFJvdXRlSW5mb01ldGFkYXRhICE9PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuIHJvdXRlLmJ1aWxkUm91dGVJbmZvTWV0YWRhdGEoKTsKICAgIH0KCiAgICByZXR1cm4gbnVsbDsKICB9CgogIGZ1bmN0aW9uIGF0dGFjaE1ldGFkYXRhKHJvdXRlLCByb3V0ZUluZm8pIHsKICAgIHZhciBtZXRhZGF0YSA9IHsKICAgICAgZ2V0IG1ldGFkYXRhKCkgewogICAgICAgIHJldHVybiBidWlsZFJvdXRlSW5mb01ldGFkYXRhKHJvdXRlKTsKICAgICAgfQoKICAgIH07CgogICAgaWYgKE9iamVjdC5pc0Zyb3plbihyb3V0ZUluZm8pIHx8IHJvdXRlSW5mby5oYXNPd25Qcm9wZXJ0eSgnbWV0YWRhdGEnKSkgewogICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSgoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCByb3V0ZUluZm8sIG1ldGFkYXRhKSk7CiAgICB9CgogICAgcmV0dXJuICgwLCBfcG9seWZpbGxzLmFzc2lnbikocm91dGVJbmZvLCBtZXRhZGF0YSk7CiAgfQoKICB2YXIgSW50ZXJuYWxSb3V0ZUluZm8gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBJbnRlcm5hbFJvdXRlSW5mbyhyb3V0ZXIsIG5hbWUsIHBhcmFtTmFtZXMsIHJvdXRlKSB7CiAgICAgIHRoaXMuX3JvdXRlUHJvbWlzZSA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5fcm91dGUgPSBudWxsOwogICAgICB0aGlzLnBhcmFtcyA9IHt9OwogICAgICB0aGlzLmlzUmVzb2x2ZWQgPSBmYWxzZTsKICAgICAgdGhpcy5uYW1lID0gbmFtZTsKICAgICAgdGhpcy5wYXJhbU5hbWVzID0gcGFyYW1OYW1lczsKICAgICAgdGhpcy5yb3V0ZXIgPSByb3V0ZXI7CgogICAgICBpZiAocm91dGUpIHsKICAgICAgICB0aGlzLl9wcm9jZXNzUm91dGUocm91dGUpOwogICAgICB9CiAgICB9CgogICAgdmFyIF9wcm90bzIgPSBJbnRlcm5hbFJvdXRlSW5mby5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5nZXRNb2RlbCA9IGZ1bmN0aW9uIGdldE1vZGVsKF90cmFuc2l0aW9uKSB7CiAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlc29sdmUodGhpcy5jb250ZXh0KTsKICAgIH07CgogICAgX3Byb3RvMi5zZXJpYWxpemUgPSBmdW5jdGlvbiBzZXJpYWxpemUoX2NvbnRleHQpIHsKICAgICAgcmV0dXJuIHRoaXMucGFyYW1zIHx8IHt9OwogICAgfTsKCiAgICBfcHJvdG8yLnJlc29sdmUgPSBmdW5jdGlvbiByZXNvbHZlKHNob3VsZENvbnRpbnVlLCB0cmFuc2l0aW9uKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgcmV0dXJuIF9yc3ZwLlByb21pc2UucmVzb2x2ZSh0aGlzLnJvdXRlUHJvbWlzZSkudGhlbihmdW5jdGlvbiAocm91dGUpIHsKICAgICAgICByZXR1cm4gX3RoaXMyLmNoZWNrRm9yQWJvcnQoc2hvdWxkQ29udGludWUsIHJvdXRlKTsKICAgICAgfSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIF90aGlzMi5ydW5CZWZvcmVNb2RlbEhvb2sodHJhbnNpdGlvbik7CiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBfdGhpczIuY2hlY2tGb3JBYm9ydChzaG91bGRDb250aW51ZSwgbnVsbCk7CiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBfdGhpczIuZ2V0TW9kZWwodHJhbnNpdGlvbik7CiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKHJlc29sdmVkTW9kZWwpIHsKICAgICAgICByZXR1cm4gX3RoaXMyLmNoZWNrRm9yQWJvcnQoc2hvdWxkQ29udGludWUsIHJlc29sdmVkTW9kZWwpOwogICAgICB9KS50aGVuKGZ1bmN0aW9uIChyZXNvbHZlZE1vZGVsKSB7CiAgICAgICAgcmV0dXJuIF90aGlzMi5ydW5BZnRlck1vZGVsSG9vayh0cmFuc2l0aW9uLCByZXNvbHZlZE1vZGVsKTsKICAgICAgfSkudGhlbihmdW5jdGlvbiAocmVzb2x2ZWRNb2RlbCkgewogICAgICAgIHJldHVybiBfdGhpczIuYmVjb21lUmVzb2x2ZWQodHJhbnNpdGlvbiwgcmVzb2x2ZWRNb2RlbCk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8yLmJlY29tZVJlc29sdmVkID0gZnVuY3Rpb24gYmVjb21lUmVzb2x2ZWQodHJhbnNpdGlvbiwgcmVzb2x2ZWRDb250ZXh0KSB7CiAgICAgIHZhciBwYXJhbXMgPSB0aGlzLnNlcmlhbGl6ZShyZXNvbHZlZENvbnRleHQpOwoKICAgICAgaWYgKHRyYW5zaXRpb24pIHsKICAgICAgICB0aGlzLnN0YXNoUmVzb2x2ZWRNb2RlbCh0cmFuc2l0aW9uLCByZXNvbHZlZENvbnRleHQpOwogICAgICAgIHRyYW5zaXRpb25bUEFSQU1TX1NZTUJPTF0gPSB0cmFuc2l0aW9uW1BBUkFNU19TWU1CT0xdIHx8IHt9OwogICAgICAgIHRyYW5zaXRpb25bUEFSQU1TX1NZTUJPTF1bdGhpcy5uYW1lXSA9IHBhcmFtczsKICAgICAgfQoKICAgICAgdmFyIGNvbnRleHQ7CiAgICAgIHZhciBjb250ZXh0c01hdGNoID0gcmVzb2x2ZWRDb250ZXh0ID09PSB0aGlzLmNvbnRleHQ7CgogICAgICBpZiAoJ2NvbnRleHQnIGluIHRoaXMgfHwgIWNvbnRleHRzTWF0Y2gpIHsKICAgICAgICBjb250ZXh0ID0gcmVzb2x2ZWRDb250ZXh0OwogICAgICB9CgogICAgICB2YXIgY2FjaGVkID0gUk9VVEVfSU5GT1MuZ2V0KHRoaXMpOwogICAgICB2YXIgcmVzb2x2ZWQgPSBuZXcgUmVzb2x2ZWRSb3V0ZUluZm8odGhpcy5yb3V0ZXIsIHRoaXMubmFtZSwgdGhpcy5wYXJhbU5hbWVzLCBwYXJhbXMsIHRoaXMucm91dGUsIGNvbnRleHQpOwoKICAgICAgaWYgKGNhY2hlZCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgUk9VVEVfSU5GT1Muc2V0KHJlc29sdmVkLCBjYWNoZWQpOwogICAgICB9CgogICAgICByZXR1cm4gcmVzb2x2ZWQ7CiAgICB9OwoKICAgIF9wcm90bzIuc2hvdWxkU3VwZXJjZWRlID0gZnVuY3Rpb24gc2hvdWxkU3VwZXJjZWRlKHJvdXRlSW5mbykgewogICAgICAvLyBQcmVmZXIgdGhpcyBuZXdlciByb3V0ZUluZm8gb3ZlciBgb3RoZXJgIGlmOgogICAgICAvLyAxKSBUaGUgb3RoZXIgb25lIGRvZXNuJ3QgZXhpc3QKICAgICAgLy8gMikgVGhlIG5hbWVzIGRvbid0IG1hdGNoCiAgICAgIC8vIDMpIFRoaXMgcm91dGUgaGFzIGEgY29udGV4dCB0aGF0IGRvZXNuJ3QgbWF0Y2gKICAgICAgLy8gICAgdGhlIG90aGVyIG9uZSAob3IgdGhlIG90aGVyIG9uZSBkb2Vzbid0IGhhdmUgb25lKS4KICAgICAgLy8gNCkgVGhpcyByb3V0ZSBoYXMgcGFyYW1ldGVycyB0aGF0IGRvbid0IG1hdGNoIHRoZSBvdGhlci4KICAgICAgaWYgKCFyb3V0ZUluZm8pIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgdmFyIGNvbnRleHRzTWF0Y2ggPSByb3V0ZUluZm8uY29udGV4dCA9PT0gdGhpcy5jb250ZXh0OwogICAgICByZXR1cm4gcm91dGVJbmZvLm5hbWUgIT09IHRoaXMubmFtZSB8fCAnY29udGV4dCcgaW4gdGhpcyAmJiAhY29udGV4dHNNYXRjaCB8fCB0aGlzLmhhc093blByb3BlcnR5KCdwYXJhbXMnKSAmJiAhcGFyYW1zTWF0Y2godGhpcy5wYXJhbXMsIHJvdXRlSW5mby5wYXJhbXMpOwogICAgfTsKCiAgICBfcHJvdG8yLmxvZyA9IGZ1bmN0aW9uIGxvZyh0cmFuc2l0aW9uLCBtZXNzYWdlKSB7CiAgICAgIGlmICh0cmFuc2l0aW9uLmxvZykgewogICAgICAgIHRyYW5zaXRpb24ubG9nKHRoaXMubmFtZSArICc6ICcgKyBtZXNzYWdlKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8yLnVwZGF0ZVJvdXRlID0gZnVuY3Rpb24gdXBkYXRlUm91dGUocm91dGUpIHsKICAgICAgcm91dGUuX2ludGVybmFsTmFtZSA9IHRoaXMubmFtZTsKICAgICAgcmV0dXJuIHRoaXMucm91dGUgPSByb3V0ZTsKICAgIH07CgogICAgX3Byb3RvMi5ydW5CZWZvcmVNb2RlbEhvb2sgPSBmdW5jdGlvbiBydW5CZWZvcmVNb2RlbEhvb2sodHJhbnNpdGlvbikgewogICAgICBpZiAodHJhbnNpdGlvbi50cmlnZ2VyKSB7CiAgICAgICAgdHJhbnNpdGlvbi50cmlnZ2VyKHRydWUsICd3aWxsUmVzb2x2ZU1vZGVsJywgdHJhbnNpdGlvbiwgdGhpcy5yb3V0ZSk7CiAgICAgIH0KCiAgICAgIHZhciByZXN1bHQ7CgogICAgICBpZiAodGhpcy5yb3V0ZSkgewogICAgICAgIGlmICh0aGlzLnJvdXRlLmJlZm9yZU1vZGVsICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJlc3VsdCA9IHRoaXMucm91dGUuYmVmb3JlTW9kZWwodHJhbnNpdGlvbik7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoaXNUcmFuc2l0aW9uKHJlc3VsdCkpIHsKICAgICAgICByZXN1bHQgPSBudWxsOwogICAgICB9CgogICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7CiAgICB9OwoKICAgIF9wcm90bzIucnVuQWZ0ZXJNb2RlbEhvb2sgPSBmdW5jdGlvbiBydW5BZnRlck1vZGVsSG9vayh0cmFuc2l0aW9uLCByZXNvbHZlZE1vZGVsKSB7CiAgICAgIC8vIFN0YXNoIHRoZSByZXNvbHZlZCBtb2RlbCBvbiB0aGUgcGF5bG9hZC4KICAgICAgLy8gVGhpcyBtYWtlcyBpdCBwb3NzaWJsZSBmb3IgdXNlcnMgdG8gc3dhcCBvdXQKICAgICAgLy8gdGhlIHJlc29sdmVkIG1vZGVsIGluIGFmdGVyTW9kZWwuCiAgICAgIHZhciBuYW1lID0gdGhpcy5uYW1lOwogICAgICB0aGlzLnN0YXNoUmVzb2x2ZWRNb2RlbCh0cmFuc2l0aW9uLCByZXNvbHZlZE1vZGVsKTsKICAgICAgdmFyIHJlc3VsdDsKCiAgICAgIGlmICh0aGlzLnJvdXRlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBpZiAodGhpcy5yb3V0ZS5hZnRlck1vZGVsICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJlc3VsdCA9IHRoaXMucm91dGUuYWZ0ZXJNb2RlbChyZXNvbHZlZE1vZGVsLCB0cmFuc2l0aW9uKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJlc3VsdCA9IHByZXBhcmVSZXN1bHQocmVzdWx0KTsKICAgICAgcmV0dXJuIF9yc3ZwLlByb21pc2UucmVzb2x2ZShyZXN1bHQpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIC8vIElnbm9yZSB0aGUgZnVsZmlsbGVkIHZhbHVlIHJldHVybmVkIGZyb20gYWZ0ZXJNb2RlbC4KICAgICAgICAvLyBSZXR1cm4gdGhlIHZhbHVlIHN0YXNoZWQgaW4gcmVzb2x2ZWRNb2RlbHMsIHdoaWNoCiAgICAgICAgLy8gbWlnaHQgaGF2ZSBiZWVuIHN3YXBwZWQgb3V0IGluIGFmdGVyTW9kZWwuCiAgICAgICAgcmV0dXJuIHRyYW5zaXRpb24ucmVzb2x2ZWRNb2RlbHNbbmFtZV07CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8yLmNoZWNrRm9yQWJvcnQgPSBmdW5jdGlvbiBjaGVja0ZvckFib3J0KHNob3VsZENvbnRpbnVlLCB2YWx1ZSkgewogICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZXNvbHZlKHNob3VsZENvbnRpbnVlKCkpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIC8vIFdlIGRvbid0IGNhcmUgYWJvdXQgc2hvdWxkQ29udGludWUncyByZXNvbHZlIHZhbHVlOwogICAgICAgIC8vIHBhc3MgYWxvbmcgdGhlIG9yaWdpbmFsIHZhbHVlIHBhc3NlZCB0byB0aGlzIGZuLgogICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgfSwgbnVsbCk7CiAgICB9OwoKICAgIF9wcm90bzIuc3Rhc2hSZXNvbHZlZE1vZGVsID0gZnVuY3Rpb24gc3Rhc2hSZXNvbHZlZE1vZGVsKHRyYW5zaXRpb24sIHJlc29sdmVkTW9kZWwpIHsKICAgICAgdHJhbnNpdGlvbi5yZXNvbHZlZE1vZGVscyA9IHRyYW5zaXRpb24ucmVzb2x2ZWRNb2RlbHMgfHwge307CiAgICAgIHRyYW5zaXRpb24ucmVzb2x2ZWRNb2RlbHNbdGhpcy5uYW1lXSA9IHJlc29sdmVkTW9kZWw7CiAgICB9OwoKICAgIF9wcm90bzIuZmV0Y2hSb3V0ZSA9IGZ1bmN0aW9uIGZldGNoUm91dGUoKSB7CiAgICAgIHZhciByb3V0ZSA9IHRoaXMucm91dGVyLmdldFJvdXRlKHRoaXMubmFtZSk7CiAgICAgIHJldHVybiB0aGlzLl9wcm9jZXNzUm91dGUocm91dGUpOwogICAgfTsKCiAgICBfcHJvdG8yLl9wcm9jZXNzUm91dGUgPSBmdW5jdGlvbiBfcHJvY2Vzc1JvdXRlKHJvdXRlKSB7CiAgICAgIHZhciBfdGhpczMgPSB0aGlzOwoKICAgICAgLy8gU2V0dXAgYSByb3V0ZVByb21pc2Ugc28gdGhhdCB3ZSBjYW4gd2FpdCBmb3IgYXN5bmNocm9ub3VzbHkgbG9hZGVkIHJvdXRlcwogICAgICB0aGlzLnJvdXRlUHJvbWlzZSA9IF9yc3ZwLlByb21pc2UucmVzb2x2ZShyb3V0ZSk7IC8vIFdhaXQgdW50aWwgdGhlICdyb3V0ZScgcHJvcGVydHkgaGFzIGJlZW4gdXBkYXRlZCB3aGVuIGNoYWluaW5nIHRvIGEgcm91dGUKICAgICAgLy8gdGhhdCBpcyBhIHByb21pc2UKCiAgICAgIGlmIChpc1Byb21pc2Uocm91dGUpKSB7CiAgICAgICAgdGhpcy5yb3V0ZVByb21pc2UgPSB0aGlzLnJvdXRlUHJvbWlzZS50aGVuKGZ1bmN0aW9uIChyKSB7CiAgICAgICAgICByZXR1cm4gX3RoaXMzLnVwZGF0ZVJvdXRlKHIpOwogICAgICAgIH0pOyAvLyBzZXQgdG8gdW5kZWZpbmVkIHRvIGF2b2lkIHJlY3Vyc2l2ZSBsb29wIGluIHRoZSByb3V0ZSBnZXR0ZXIKCiAgICAgICAgcmV0dXJuIHRoaXMucm91dGUgPSB1bmRlZmluZWQ7CiAgICAgIH0gZWxzZSBpZiAocm91dGUpIHsKICAgICAgICByZXR1cm4gdGhpcy51cGRhdGVSb3V0ZShyb3V0ZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoSW50ZXJuYWxSb3V0ZUluZm8sIFt7CiAgICAgIGtleTogInJvdXRlIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgLy8gX3JvdXRlIGNvdWxkIGJlIHNldCB0byBlaXRoZXIgYSByb3V0ZSBvYmplY3Qgb3IgdW5kZWZpbmVkLCBzbyB3ZQogICAgICAgIC8vIGNvbXBhcmUgYWdhaW5zdCBudWxsIHRvIGtub3cgd2hlbiBpdCdzIGJlZW4gc2V0CiAgICAgICAgaWYgKHRoaXMuX3JvdXRlICE9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fcm91dGU7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5mZXRjaFJvdXRlKCk7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHJvdXRlKSB7CiAgICAgICAgdGhpcy5fcm91dGUgPSByb3V0ZTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJyb3V0ZVByb21pc2UiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fcm91dGVQcm9taXNlKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fcm91dGVQcm9taXNlOwogICAgICAgIH0KCiAgICAgICAgdGhpcy5mZXRjaFJvdXRlKCk7CiAgICAgICAgcmV0dXJuIHRoaXMuX3JvdXRlUHJvbWlzZTsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQocm91dGVQcm9taXNlKSB7CiAgICAgICAgdGhpcy5fcm91dGVQcm9taXNlID0gcm91dGVQcm9taXNlOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gSW50ZXJuYWxSb3V0ZUluZm87CiAgfSgpOwoKICBfZXhwb3J0cy5JbnRlcm5hbFJvdXRlSW5mbyA9IEludGVybmFsUm91dGVJbmZvOwoKICB2YXIgUmVzb2x2ZWRSb3V0ZUluZm8gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0ludGVybmFsUm91dGVJbmZvKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUmVzb2x2ZWRSb3V0ZUluZm8sIF9JbnRlcm5hbFJvdXRlSW5mbyk7CgogICAgZnVuY3Rpb24gUmVzb2x2ZWRSb3V0ZUluZm8ocm91dGVyLCBuYW1lLCBwYXJhbU5hbWVzLCBwYXJhbXMsIHJvdXRlLCBjb250ZXh0KSB7CiAgICAgIHZhciBfdGhpczQ7CgogICAgICBfdGhpczQgPSBfSW50ZXJuYWxSb3V0ZUluZm8uY2FsbCh0aGlzLCByb3V0ZXIsIG5hbWUsIHBhcmFtTmFtZXMsIHJvdXRlKSB8fCB0aGlzOwogICAgICBfdGhpczQucGFyYW1zID0gcGFyYW1zOwogICAgICBfdGhpczQuaXNSZXNvbHZlZCA9IHRydWU7CiAgICAgIF90aGlzNC5jb250ZXh0ID0gY29udGV4dDsKICAgICAgcmV0dXJuIF90aGlzNDsKICAgIH0KCiAgICB2YXIgX3Byb3RvMyA9IFJlc29sdmVkUm91dGVJbmZvLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zLnJlc29sdmUgPSBmdW5jdGlvbiByZXNvbHZlKF9zaG91bGRDb250aW51ZSwgdHJhbnNpdGlvbikgewogICAgICAvLyBBIFJlc29sdmVkUm91dGVJbmZvIGp1c3QgcmVzb2x2ZWQgd2l0aCBpdHNlbGYuCiAgICAgIGlmICh0cmFuc2l0aW9uICYmIHRyYW5zaXRpb24ucmVzb2x2ZWRNb2RlbHMpIHsKICAgICAgICB0cmFuc2l0aW9uLnJlc29sdmVkTW9kZWxzW3RoaXMubmFtZV0gPSB0aGlzLmNvbnRleHQ7CiAgICAgIH0KCiAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlc29sdmUodGhpcyk7CiAgICB9OwoKICAgIHJldHVybiBSZXNvbHZlZFJvdXRlSW5mbzsKICB9KEludGVybmFsUm91dGVJbmZvKTsKCiAgdmFyIFVucmVzb2x2ZWRSb3V0ZUluZm9CeVBhcmFtID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9JbnRlcm5hbFJvdXRlSW5mbzIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShVbnJlc29sdmVkUm91dGVJbmZvQnlQYXJhbSwgX0ludGVybmFsUm91dGVJbmZvMik7CgogICAgZnVuY3Rpb24gVW5yZXNvbHZlZFJvdXRlSW5mb0J5UGFyYW0ocm91dGVyLCBuYW1lLCBwYXJhbU5hbWVzLCBwYXJhbXMsIHJvdXRlKSB7CiAgICAgIHZhciBfdGhpczU7CgogICAgICBfdGhpczUgPSBfSW50ZXJuYWxSb3V0ZUluZm8yLmNhbGwodGhpcywgcm91dGVyLCBuYW1lLCBwYXJhbU5hbWVzLCByb3V0ZSkgfHwgdGhpczsKICAgICAgX3RoaXM1LnBhcmFtcyA9IHt9OwogICAgICBfdGhpczUucGFyYW1zID0gcGFyYW1zOwogICAgICByZXR1cm4gX3RoaXM1OwogICAgfQoKICAgIHZhciBfcHJvdG80ID0gVW5yZXNvbHZlZFJvdXRlSW5mb0J5UGFyYW0ucHJvdG90eXBlOwoKICAgIF9wcm90bzQuZ2V0TW9kZWwgPSBmdW5jdGlvbiBnZXRNb2RlbCh0cmFuc2l0aW9uKSB7CiAgICAgIHZhciBmdWxsUGFyYW1zID0gdGhpcy5wYXJhbXM7CgogICAgICBpZiAodHJhbnNpdGlvbiAmJiB0cmFuc2l0aW9uW1FVRVJZX1BBUkFNU19TWU1CT0xdKSB7CiAgICAgICAgZnVsbFBhcmFtcyA9IHt9OwogICAgICAgIG1lcmdlKGZ1bGxQYXJhbXMsIHRoaXMucGFyYW1zKTsKICAgICAgICBmdWxsUGFyYW1zLnF1ZXJ5UGFyYW1zID0gdHJhbnNpdGlvbltRVUVSWV9QQVJBTVNfU1lNQk9MXTsKICAgICAgfQoKICAgICAgdmFyIHJvdXRlID0gdGhpcy5yb3V0ZTsKICAgICAgdmFyIHJlc3VsdCA9IHVuZGVmaW5lZDsKCiAgICAgIGlmIChyb3V0ZS5kZXNlcmlhbGl6ZSkgewogICAgICAgIHJlc3VsdCA9IHJvdXRlLmRlc2VyaWFsaXplKGZ1bGxQYXJhbXMsIHRyYW5zaXRpb24pOwogICAgICB9IGVsc2UgaWYgKHJvdXRlLm1vZGVsKSB7CiAgICAgICAgcmVzdWx0ID0gcm91dGUubW9kZWwoZnVsbFBhcmFtcywgdHJhbnNpdGlvbik7CiAgICAgIH0KCiAgICAgIGlmIChyZXN1bHQgJiYgaXNUcmFuc2l0aW9uKHJlc3VsdCkpIHsKICAgICAgICByZXN1bHQgPSB1bmRlZmluZWQ7CiAgICAgIH0KCiAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlc29sdmUocmVzdWx0KTsKICAgIH07CgogICAgcmV0dXJuIFVucmVzb2x2ZWRSb3V0ZUluZm9CeVBhcmFtOwogIH0oSW50ZXJuYWxSb3V0ZUluZm8pOwoKICB2YXIgVW5yZXNvbHZlZFJvdXRlSW5mb0J5T2JqZWN0ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9JbnRlcm5hbFJvdXRlSW5mbzMpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShVbnJlc29sdmVkUm91dGVJbmZvQnlPYmplY3QsIF9JbnRlcm5hbFJvdXRlSW5mbzMpOwoKICAgIGZ1bmN0aW9uIFVucmVzb2x2ZWRSb3V0ZUluZm9CeU9iamVjdChyb3V0ZXIsIG5hbWUsIHBhcmFtTmFtZXMsIGNvbnRleHQpIHsKICAgICAgdmFyIF90aGlzNjsKCiAgICAgIF90aGlzNiA9IF9JbnRlcm5hbFJvdXRlSW5mbzMuY2FsbCh0aGlzLCByb3V0ZXIsIG5hbWUsIHBhcmFtTmFtZXMpIHx8IHRoaXM7CiAgICAgIF90aGlzNi5jb250ZXh0ID0gY29udGV4dDsKICAgICAgX3RoaXM2LnNlcmlhbGl6ZXIgPSBfdGhpczYucm91dGVyLmdldFNlcmlhbGl6ZXIobmFtZSk7CiAgICAgIHJldHVybiBfdGhpczY7CiAgICB9CgogICAgdmFyIF9wcm90bzUgPSBVbnJlc29sdmVkUm91dGVJbmZvQnlPYmplY3QucHJvdG90eXBlOwoKICAgIF9wcm90bzUuZ2V0TW9kZWwgPSBmdW5jdGlvbiBnZXRNb2RlbCh0cmFuc2l0aW9uKSB7CiAgICAgIGlmICh0aGlzLnJvdXRlci5sb2cgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHRoaXMucm91dGVyLmxvZyh0aGlzLm5hbWUgKyAnOiByZXNvbHZpbmcgcHJvdmlkZWQgbW9kZWwnKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9JbnRlcm5hbFJvdXRlSW5mbzMucHJvdG90eXBlLmdldE1vZGVsLmNhbGwodGhpcywgdHJhbnNpdGlvbik7CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgU2VyaWFsaXplcyBhIHJvdXRlIHVzaW5nIGl0cyBjdXN0b20gYHNlcmlhbGl6ZWAgbWV0aG9kIG9yCiAgICAgIGJ5IGEgZGVmYXVsdCB0aGF0IGxvb2tzIHVwIHRoZSBleHBlY3RlZCBwcm9wZXJ0eSBuYW1lIGZyb20KICAgICAgdGhlIGR5bmFtaWMgc2VnbWVudC4KICAgICAgICAgQHBhcmFtIHtPYmplY3R9IG1vZGVsIHRoZSBtb2RlbCB0byBiZSBzZXJpYWxpemVkIGZvciB0aGlzIHJvdXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90bzUuc2VyaWFsaXplID0gZnVuY3Rpb24gc2VyaWFsaXplKG1vZGVsKSB7CiAgICAgIHZhciBwYXJhbU5hbWVzID0gdGhpcy5wYXJhbU5hbWVzLAogICAgICAgICAgY29udGV4dCA9IHRoaXMuY29udGV4dDsKCiAgICAgIGlmICghbW9kZWwpIHsKICAgICAgICBtb2RlbCA9IGNvbnRleHQ7CiAgICAgIH0KCiAgICAgIHZhciBvYmplY3QgPSB7fTsKCiAgICAgIGlmIChpc1BhcmFtKG1vZGVsKSkgewogICAgICAgIG9iamVjdFtwYXJhbU5hbWVzWzBdXSA9IG1vZGVsOwogICAgICAgIHJldHVybiBvYmplY3Q7CiAgICAgIH0gLy8gVXNlIGN1c3RvbSBzZXJpYWxpemUgaWYgaXQgZXhpc3RzLgoKCiAgICAgIGlmICh0aGlzLnNlcmlhbGl6ZXIpIHsKICAgICAgICAvLyBpbnZva2UgdGhpcy5zZXJpYWxpemVyIHVuYm91bmQgKGdldFNlcmlhbGl6ZXIgcmV0dXJucyBhIHN0YXRlbGVzcyBmdW5jdGlvbikKICAgICAgICByZXR1cm4gdGhpcy5zZXJpYWxpemVyLmNhbGwobnVsbCwgbW9kZWwsIHBhcmFtTmFtZXMpOwogICAgICB9IGVsc2UgaWYgKHRoaXMucm91dGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGlmICh0aGlzLnJvdXRlLnNlcmlhbGl6ZSkgewogICAgICAgICAgcmV0dXJuIHRoaXMucm91dGUuc2VyaWFsaXplKG1vZGVsLCBwYXJhbU5hbWVzKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChwYXJhbU5hbWVzLmxlbmd0aCAhPT0gMSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIG5hbWUgPSBwYXJhbU5hbWVzWzBdOwoKICAgICAgaWYgKC9faWQkLy50ZXN0KG5hbWUpKSB7CiAgICAgICAgb2JqZWN0W25hbWVdID0gbW9kZWwuaWQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgb2JqZWN0W25hbWVdID0gbW9kZWw7CiAgICAgIH0KCiAgICAgIHJldHVybiBvYmplY3Q7CiAgICB9OwoKICAgIHJldHVybiBVbnJlc29sdmVkUm91dGVJbmZvQnlPYmplY3Q7CiAgfShJbnRlcm5hbFJvdXRlSW5mbyk7CgogIGZ1bmN0aW9uIHBhcmFtc01hdGNoKGEsIGIpIHsKICAgIGlmICghYSAhPT0gIWIpIHsKICAgICAgLy8gT25seSBvbmUgaXMgbnVsbC4KICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIGlmICghYSkgewogICAgICAvLyBCb3RoIG11c3QgYmUgbnVsbC4KICAgICAgcmV0dXJuIHRydWU7CiAgICB9IC8vIE5vdGU6IHRoaXMgYXNzdW1lcyB0aGF0IGJvdGggcGFyYW1zIGhhdmUgdGhlIHNhbWUKICAgIC8vIG51bWJlciBvZiBrZXlzLCBidXQgc2luY2Ugd2UncmUgY29tcGFyaW5nIHRoZQogICAgLy8gc2FtZSByb3V0ZXMsIHRoZXkgc2hvdWxkLgoKCiAgICBmb3IgKHZhciBrIGluIGEpIHsKICAgICAgaWYgKGEuaGFzT3duUHJvcGVydHkoaykgJiYgYVtrXSAhPT0gYltrXSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiB0cnVlOwogIH0KCiAgdmFyIFRyYW5zaXRpb25JbnRlbnQgPSBmdW5jdGlvbiBUcmFuc2l0aW9uSW50ZW50KHJvdXRlciwgZGF0YSkgewogICAgaWYgKGRhdGEgPT09IHZvaWQgMCkgewogICAgICBkYXRhID0ge307CiAgICB9CgogICAgdGhpcy5yb3V0ZXIgPSByb3V0ZXI7CiAgICB0aGlzLmRhdGEgPSBkYXRhOwogIH07CgogIHZhciBUcmFuc2l0aW9uU3RhdGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBUcmFuc2l0aW9uU3RhdGUoKSB7CiAgICAgIHRoaXMucm91dGVJbmZvcyA9IFtdOwogICAgICB0aGlzLnF1ZXJ5UGFyYW1zID0ge307CiAgICAgIHRoaXMucGFyYW1zID0ge307CiAgICB9CgogICAgdmFyIF9wcm90bzYgPSBUcmFuc2l0aW9uU3RhdGUucHJvdG90eXBlOwoKICAgIF9wcm90bzYucHJvbWlzZUxhYmVsID0gZnVuY3Rpb24gcHJvbWlzZUxhYmVsKGxhYmVsKSB7CiAgICAgIHZhciB0YXJnZXROYW1lID0gJyc7CiAgICAgIGZvckVhY2godGhpcy5yb3V0ZUluZm9zLCBmdW5jdGlvbiAocm91dGVJbmZvKSB7CiAgICAgICAgaWYgKHRhcmdldE5hbWUgIT09ICcnKSB7CiAgICAgICAgICB0YXJnZXROYW1lICs9ICcuJzsKICAgICAgICB9CgogICAgICAgIHRhcmdldE5hbWUgKz0gcm91dGVJbmZvLm5hbWU7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0pOwogICAgICByZXR1cm4gX3Byb21pc2VMYWJlbCgiJyIgKyB0YXJnZXROYW1lICsgIic6ICIgKyBsYWJlbCk7CiAgICB9OwoKICAgIF9wcm90bzYucmVzb2x2ZSA9IGZ1bmN0aW9uIHJlc29sdmUoc2hvdWxkQ29udGludWUsIHRyYW5zaXRpb24pIHsKICAgICAgLy8gRmlyc3QsIGNhbGN1bGF0ZSBwYXJhbXMgZm9yIHRoaXMgc3RhdGUuIFRoaXMgaXMgdXNlZnVsCiAgICAgIC8vIGluZm9ybWF0aW9uIHRvIHByb3ZpZGUgdG8gdGhlIHZhcmlvdXMgcm91dGUgaG9va3MuCiAgICAgIHZhciBwYXJhbXMgPSB0aGlzLnBhcmFtczsKICAgICAgZm9yRWFjaCh0aGlzLnJvdXRlSW5mb3MsIGZ1bmN0aW9uIChyb3V0ZUluZm8pIHsKICAgICAgICBwYXJhbXNbcm91dGVJbmZvLm5hbWVdID0gcm91dGVJbmZvLnBhcmFtcyB8fCB7fTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfSk7CiAgICAgIHRyYW5zaXRpb24ucmVzb2x2ZUluZGV4ID0gMDsKICAgICAgdmFyIGN1cnJlbnRTdGF0ZSA9IHRoaXM7CiAgICAgIHZhciB3YXNBYm9ydGVkID0gZmFsc2U7IC8vIFRoZSBwcmVsdWRlIFJTVlAucmVzb2x2ZSgpIGFzeW5jcyB1cyBpbnRvIHRoZSBwcm9taXNlIGxhbmQuCgogICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZXNvbHZlKG51bGwsIHRoaXMucHJvbWlzZUxhYmVsKCdTdGFydCB0cmFuc2l0aW9uJykpLnRoZW4ocmVzb2x2ZU9uZVJvdXRlSW5mbywgbnVsbCwgdGhpcy5wcm9taXNlTGFiZWwoJ1Jlc29sdmUgcm91dGUnKSkuY2F0Y2goaGFuZGxlRXJyb3IsIHRoaXMucHJvbWlzZUxhYmVsKCdIYW5kbGUgZXJyb3InKSk7CgogICAgICBmdW5jdGlvbiBpbm5lclNob3VsZENvbnRpbnVlKCkgewogICAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlc29sdmUoc2hvdWxkQ29udGludWUoKSwgY3VycmVudFN0YXRlLnByb21pc2VMYWJlbCgnQ2hlY2sgaWYgc2hvdWxkIGNvbnRpbnVlJykpLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgIC8vIFdlIGRpc3Rpbmd1aXNoIGJldHdlZW4gZXJyb3JzIHRoYXQgb2NjdXJyZWQKICAgICAgICAgIC8vIGR1cmluZyByZXNvbHV0aW9uIChlLmcuIGJlZm9yZSJNb2RlbC9tb2RlbC9hZnRlck1vZGVsKSwKICAgICAgICAgIC8vIGFuZCBhYm9ydHMgZHVlIHRvIGEgcmVqZWN0aW5nIHByb21pc2UgZnJvbSBzaG91bGRDb250aW51ZSgpLgogICAgICAgICAgd2FzQWJvcnRlZCA9IHRydWU7CiAgICAgICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZWplY3QocmVhc29uKTsKICAgICAgICB9LCBjdXJyZW50U3RhdGUucHJvbWlzZUxhYmVsKCdIYW5kbGUgYWJvcnQnKSk7CiAgICAgIH0KCiAgICAgIGZ1bmN0aW9uIGhhbmRsZUVycm9yKGVycm9yKSB7CiAgICAgICAgLy8gVGhpcyBpcyB0aGUgb25seSBwb3NzaWJsZQogICAgICAgIC8vIHJlamVjdCB2YWx1ZSBvZiBUcmFuc2l0aW9uU3RhdGUjcmVzb2x2ZQogICAgICAgIHZhciByb3V0ZUluZm9zID0gY3VycmVudFN0YXRlLnJvdXRlSW5mb3M7CiAgICAgICAgdmFyIGVycm9ySGFuZGxlckluZGV4ID0gdHJhbnNpdGlvbi5yZXNvbHZlSW5kZXggPj0gcm91dGVJbmZvcy5sZW5ndGggPyByb3V0ZUluZm9zLmxlbmd0aCAtIDEgOiB0cmFuc2l0aW9uLnJlc29sdmVJbmRleDsKICAgICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZWplY3QobmV3IFRyYW5zaXRpb25FcnJvcihlcnJvciwgY3VycmVudFN0YXRlLnJvdXRlSW5mb3NbZXJyb3JIYW5kbGVySW5kZXhdLnJvdXRlLCB3YXNBYm9ydGVkLCBjdXJyZW50U3RhdGUpKTsKICAgICAgfQoKICAgICAgZnVuY3Rpb24gcHJvY2VlZChyZXNvbHZlZFJvdXRlSW5mbykgewogICAgICAgIHZhciB3YXNBbHJlYWR5UmVzb2x2ZWQgPSBjdXJyZW50U3RhdGUucm91dGVJbmZvc1t0cmFuc2l0aW9uLnJlc29sdmVJbmRleF0uaXNSZXNvbHZlZDsgLy8gU3dhcCB0aGUgcHJldmlvdXNseSB1bnJlc29sdmVkIHJvdXRlSW5mbyB3aXRoCiAgICAgICAgLy8gdGhlIHJlc29sdmVkIHJvdXRlSW5mbwoKICAgICAgICBjdXJyZW50U3RhdGUucm91dGVJbmZvc1t0cmFuc2l0aW9uLnJlc29sdmVJbmRleCsrXSA9IHJlc29sdmVkUm91dGVJbmZvOwoKICAgICAgICBpZiAoIXdhc0FscmVhZHlSZXNvbHZlZCkgewogICAgICAgICAgLy8gQ2FsbCB0aGUgcmVkaXJlY3QgaG9vay4gVGhlIHJlYXNvbiB3ZSBjYWxsIGl0IGhlcmUKICAgICAgICAgIC8vIHZzLiBhZnRlck1vZGVsIGlzIHNvIHRoYXQgcmVkaXJlY3RzIGludG8gY2hpbGQKICAgICAgICAgIC8vIHJvdXRlcyBkb24ndCByZS1ydW4gdGhlIG1vZGVsIGhvb2tzIGZvciB0aGlzCiAgICAgICAgICAvLyBhbHJlYWR5LXJlc29sdmVkIHJvdXRlLgogICAgICAgICAgdmFyIHJvdXRlID0gcmVzb2x2ZWRSb3V0ZUluZm8ucm91dGU7CgogICAgICAgICAgaWYgKHJvdXRlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgaWYgKHJvdXRlLnJlZGlyZWN0KSB7CiAgICAgICAgICAgICAgcm91dGUucmVkaXJlY3QocmVzb2x2ZWRSb3V0ZUluZm8uY29udGV4dCwgdHJhbnNpdGlvbik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IC8vIFByb2NlZWQgYWZ0ZXIgZW5zdXJpbmcgdGhhdCB0aGUgcmVkaXJlY3QgaG9vawogICAgICAgIC8vIGRpZG4ndCBhYm9ydCB0aGlzIHRyYW5zaXRpb24gYnkgdHJhbnNpdGlvbmluZyBlbHNld2hlcmUuCgoKICAgICAgICByZXR1cm4gaW5uZXJTaG91bGRDb250aW51ZSgpLnRoZW4ocmVzb2x2ZU9uZVJvdXRlSW5mbywgbnVsbCwgY3VycmVudFN0YXRlLnByb21pc2VMYWJlbCgnUmVzb2x2ZSByb3V0ZScpKTsKICAgICAgfQoKICAgICAgZnVuY3Rpb24gcmVzb2x2ZU9uZVJvdXRlSW5mbygpIHsKICAgICAgICBpZiAodHJhbnNpdGlvbi5yZXNvbHZlSW5kZXggPT09IGN1cnJlbnRTdGF0ZS5yb3V0ZUluZm9zLmxlbmd0aCkgewogICAgICAgICAgLy8gVGhpcyBpcyBpcyB0aGUgb25seSBwb3NzaWJsZQogICAgICAgICAgLy8gZnVsZmlsbCB2YWx1ZSBvZiBUcmFuc2l0aW9uU3RhdGUjcmVzb2x2ZQogICAgICAgICAgcmV0dXJuIGN1cnJlbnRTdGF0ZTsKICAgICAgICB9CgogICAgICAgIHZhciByb3V0ZUluZm8gPSBjdXJyZW50U3RhdGUucm91dGVJbmZvc1t0cmFuc2l0aW9uLnJlc29sdmVJbmRleF07CiAgICAgICAgcmV0dXJuIHJvdXRlSW5mby5yZXNvbHZlKGlubmVyU2hvdWxkQ29udGludWUsIHRyYW5zaXRpb24pLnRoZW4ocHJvY2VlZCwgbnVsbCwgY3VycmVudFN0YXRlLnByb21pc2VMYWJlbCgnUHJvY2VlZCcpKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gVHJhbnNpdGlvblN0YXRlOwogIH0oKTsKCiAgX2V4cG9ydHMuVHJhbnNpdGlvblN0YXRlID0gVHJhbnNpdGlvblN0YXRlOwoKICB2YXIgVHJhbnNpdGlvbkVycm9yID0gZnVuY3Rpb24gVHJhbnNpdGlvbkVycm9yKGVycm9yLCByb3V0ZSwgd2FzQWJvcnRlZCwgc3RhdGUpIHsKICAgIHRoaXMuZXJyb3IgPSBlcnJvcjsKICAgIHRoaXMucm91dGUgPSByb3V0ZTsKICAgIHRoaXMud2FzQWJvcnRlZCA9IHdhc0Fib3J0ZWQ7CiAgICB0aGlzLnN0YXRlID0gc3RhdGU7CiAgfTsKCiAgX2V4cG9ydHMuVHJhbnNpdGlvbkVycm9yID0gVHJhbnNpdGlvbkVycm9yOwoKICB2YXIgTmFtZWRUcmFuc2l0aW9uSW50ZW50ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9UcmFuc2l0aW9uSW50ZW50KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTmFtZWRUcmFuc2l0aW9uSW50ZW50LCBfVHJhbnNpdGlvbkludGVudCk7CgogICAgZnVuY3Rpb24gTmFtZWRUcmFuc2l0aW9uSW50ZW50KHJvdXRlciwgbmFtZSwgcGl2b3RIYW5kbGVyLCBjb250ZXh0cywgcXVlcnlQYXJhbXMsIGRhdGEpIHsKICAgICAgdmFyIF90aGlzNzsKCiAgICAgIGlmIChjb250ZXh0cyA9PT0gdm9pZCAwKSB7CiAgICAgICAgY29udGV4dHMgPSBbXTsKICAgICAgfQoKICAgICAgaWYgKHF1ZXJ5UGFyYW1zID09PSB2b2lkIDApIHsKICAgICAgICBxdWVyeVBhcmFtcyA9IHt9OwogICAgICB9CgogICAgICBfdGhpczcgPSBfVHJhbnNpdGlvbkludGVudC5jYWxsKHRoaXMsIHJvdXRlciwgZGF0YSkgfHwgdGhpczsKICAgICAgX3RoaXM3LnByZVRyYW5zaXRpb25TdGF0ZSA9IHVuZGVmaW5lZDsKICAgICAgX3RoaXM3Lm5hbWUgPSBuYW1lOwogICAgICBfdGhpczcucGl2b3RIYW5kbGVyID0gcGl2b3RIYW5kbGVyOwogICAgICBfdGhpczcuY29udGV4dHMgPSBjb250ZXh0czsKICAgICAgX3RoaXM3LnF1ZXJ5UGFyYW1zID0gcXVlcnlQYXJhbXM7CiAgICAgIHJldHVybiBfdGhpczc7CiAgICB9CgogICAgdmFyIF9wcm90bzcgPSBOYW1lZFRyYW5zaXRpb25JbnRlbnQucHJvdG90eXBlOwoKICAgIF9wcm90bzcuYXBwbHlUb1N0YXRlID0gZnVuY3Rpb24gYXBwbHlUb1N0YXRlKG9sZFN0YXRlLCBpc0ludGVybWVkaWF0ZSkgewogICAgICAvLyBUT0RPOiBXVEYgZml4IG1lCiAgICAgIHZhciBwYXJ0aXRpb25lZEFyZ3MgPSBleHRyYWN0UXVlcnlQYXJhbXMoW3RoaXMubmFtZV0uY29uY2F0KHRoaXMuY29udGV4dHMpKSwKICAgICAgICAgIHB1cmVBcmdzID0gcGFydGl0aW9uZWRBcmdzWzBdLAogICAgICAgICAgaGFuZGxlcnMgPSB0aGlzLnJvdXRlci5yZWNvZ25pemVyLmhhbmRsZXJzRm9yKHB1cmVBcmdzWzBdKTsKICAgICAgdmFyIHRhcmdldFJvdXRlTmFtZSA9IGhhbmRsZXJzW2hhbmRsZXJzLmxlbmd0aCAtIDFdLmhhbmRsZXI7CiAgICAgIHJldHVybiB0aGlzLmFwcGx5VG9IYW5kbGVycyhvbGRTdGF0ZSwgaGFuZGxlcnMsIHRhcmdldFJvdXRlTmFtZSwgaXNJbnRlcm1lZGlhdGUsIGZhbHNlKTsKICAgIH07CgogICAgX3Byb3RvNy5hcHBseVRvSGFuZGxlcnMgPSBmdW5jdGlvbiBhcHBseVRvSGFuZGxlcnMob2xkU3RhdGUsIHBhcnNlZEhhbmRsZXJzLCB0YXJnZXRSb3V0ZU5hbWUsIGlzSW50ZXJtZWRpYXRlLCBjaGVja2luZ0lmQWN0aXZlKSB7CiAgICAgIHZhciBpLCBsZW47CiAgICAgIHZhciBuZXdTdGF0ZSA9IG5ldyBUcmFuc2l0aW9uU3RhdGUoKTsKICAgICAgdmFyIG9iamVjdHMgPSB0aGlzLmNvbnRleHRzLnNsaWNlKDApOwogICAgICB2YXIgaW52YWxpZGF0ZUluZGV4ID0gcGFyc2VkSGFuZGxlcnMubGVuZ3RoOyAvLyBQaXZvdCBoYW5kbGVycyBhcmUgcHJvdmlkZWQgZm9yIHJlZnJlc2ggdHJhbnNpdGlvbnMKCiAgICAgIGlmICh0aGlzLnBpdm90SGFuZGxlcikgewogICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IHBhcnNlZEhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgICAgICBpZiAocGFyc2VkSGFuZGxlcnNbaV0uaGFuZGxlciA9PT0gdGhpcy5waXZvdEhhbmRsZXIuX2ludGVybmFsTmFtZSkgewogICAgICAgICAgICBpbnZhbGlkYXRlSW5kZXggPSBpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGZvciAoaSA9IHBhcnNlZEhhbmRsZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgdmFyIHJlc3VsdCA9IHBhcnNlZEhhbmRsZXJzW2ldOwogICAgICAgIHZhciBuYW1lID0gcmVzdWx0LmhhbmRsZXI7CiAgICAgICAgdmFyIG9sZEhhbmRsZXJJbmZvID0gb2xkU3RhdGUucm91dGVJbmZvc1tpXTsKICAgICAgICB2YXIgbmV3SGFuZGxlckluZm8gPSBudWxsOwoKICAgICAgICBpZiAocmVzdWx0Lm5hbWVzLmxlbmd0aCA+IDApIHsKICAgICAgICAgIGlmIChpID49IGludmFsaWRhdGVJbmRleCkgewogICAgICAgICAgICBuZXdIYW5kbGVySW5mbyA9IHRoaXMuY3JlYXRlUGFyYW1IYW5kbGVySW5mbyhuYW1lLCByZXN1bHQubmFtZXMsIG9iamVjdHMsIG9sZEhhbmRsZXJJbmZvKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG5ld0hhbmRsZXJJbmZvID0gdGhpcy5nZXRIYW5kbGVySW5mb0ZvckR5bmFtaWNTZWdtZW50KG5hbWUsIHJlc3VsdC5uYW1lcywgb2JqZWN0cywgb2xkSGFuZGxlckluZm8sIHRhcmdldFJvdXRlTmFtZSwgaSk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vIFRoaXMgcm91dGUgaGFzIG5vIGR5bmFtaWMgc2VnbWVudC4KICAgICAgICAgIC8vIFRoZXJlZm9yZSB0cmVhdCBhcyBhIHBhcmFtLWJhc2VkIGhhbmRsZXJJbmZvCiAgICAgICAgICAvLyB3aXRoIGVtcHR5IHBhcmFtcy4gVGhpcyB3aWxsIGNhdXNlIHRoZSBgbW9kZWxgCiAgICAgICAgICAvLyBob29rIHRvIGJlIGNhbGxlZCB3aXRoIGVtcHR5IHBhcmFtcywgd2hpY2ggaXMgZGVzaXJhYmxlLgogICAgICAgICAgbmV3SGFuZGxlckluZm8gPSB0aGlzLmNyZWF0ZVBhcmFtSGFuZGxlckluZm8obmFtZSwgcmVzdWx0Lm5hbWVzLCBvYmplY3RzLCBvbGRIYW5kbGVySW5mbyk7CiAgICAgICAgfQoKICAgICAgICBpZiAoY2hlY2tpbmdJZkFjdGl2ZSkgewogICAgICAgICAgLy8gSWYgd2UncmUgcGVyZm9ybWluZyBhbiBpc0FjdGl2ZSBjaGVjaywgd2Ugd2FudCB0bwogICAgICAgICAgLy8gc2VyaWFsaXplIFVSTCBwYXJhbXMgd2l0aCB0aGUgcHJvdmlkZWQgY29udGV4dCwgYnV0CiAgICAgICAgICAvLyBpZ25vcmUgbWlzbWF0Y2hlcyBiZXR3ZWVuIG9sZCBhbmQgbmV3IGNvbnRleHQuCiAgICAgICAgICBuZXdIYW5kbGVySW5mbyA9IG5ld0hhbmRsZXJJbmZvLmJlY29tZVJlc29sdmVkKG51bGwsIG5ld0hhbmRsZXJJbmZvLmNvbnRleHQpOwogICAgICAgICAgdmFyIG9sZENvbnRleHQgPSBvbGRIYW5kbGVySW5mbyAmJiBvbGRIYW5kbGVySW5mby5jb250ZXh0OwoKICAgICAgICAgIGlmIChyZXN1bHQubmFtZXMubGVuZ3RoID4gMCAmJiBvbGRIYW5kbGVySW5mby5jb250ZXh0ICE9PSB1bmRlZmluZWQgJiYgbmV3SGFuZGxlckluZm8uY29udGV4dCA9PT0gb2xkQ29udGV4dCkgewogICAgICAgICAgICAvLyBJZiBjb250ZXh0cyBtYXRjaCBpbiBpc0FjdGl2ZSB0ZXN0LCBhc3N1bWUgcGFyYW1zIGFsc28gbWF0Y2guCiAgICAgICAgICAgIC8vIFRoaXMgYWxsb3dzIGZvciBmbGV4aWJpbGl0eSBpbiBub3QgcmVxdWlyaW5nIHRoYXQgZXZlcnkgbGFzdAogICAgICAgICAgICAvLyBoYW5kbGVyIHByb3ZpZGUgYSBgc2VyaWFsaXplYCBtZXRob2QKICAgICAgICAgICAgbmV3SGFuZGxlckluZm8ucGFyYW1zID0gb2xkSGFuZGxlckluZm8gJiYgb2xkSGFuZGxlckluZm8ucGFyYW1zOwogICAgICAgICAgfQoKICAgICAgICAgIG5ld0hhbmRsZXJJbmZvLmNvbnRleHQgPSBvbGRDb250ZXh0OwogICAgICAgIH0KCiAgICAgICAgdmFyIGhhbmRsZXJUb1VzZSA9IG9sZEhhbmRsZXJJbmZvOwoKICAgICAgICBpZiAoaSA+PSBpbnZhbGlkYXRlSW5kZXggfHwgbmV3SGFuZGxlckluZm8uc2hvdWxkU3VwZXJjZWRlKG9sZEhhbmRsZXJJbmZvKSkgewogICAgICAgICAgaW52YWxpZGF0ZUluZGV4ID0gTWF0aC5taW4oaSwgaW52YWxpZGF0ZUluZGV4KTsKICAgICAgICAgIGhhbmRsZXJUb1VzZSA9IG5ld0hhbmRsZXJJbmZvOwogICAgICAgIH0KCiAgICAgICAgaWYgKGlzSW50ZXJtZWRpYXRlICYmICFjaGVja2luZ0lmQWN0aXZlKSB7CiAgICAgICAgICBoYW5kbGVyVG9Vc2UgPSBoYW5kbGVyVG9Vc2UuYmVjb21lUmVzb2x2ZWQobnVsbCwgaGFuZGxlclRvVXNlLmNvbnRleHQpOwogICAgICAgIH0KCiAgICAgICAgbmV3U3RhdGUucm91dGVJbmZvcy51bnNoaWZ0KGhhbmRsZXJUb1VzZSk7CiAgICAgIH0KCiAgICAgIGlmIChvYmplY3RzLmxlbmd0aCA+IDApIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vcmUgY29udGV4dCBvYmplY3RzIHdlcmUgcGFzc2VkIHRoYW4gdGhlcmUgYXJlIGR5bmFtaWMgc2VnbWVudHMgZm9yIHRoZSByb3V0ZTogJyArIHRhcmdldFJvdXRlTmFtZSk7CiAgICAgIH0KCiAgICAgIGlmICghaXNJbnRlcm1lZGlhdGUpIHsKICAgICAgICB0aGlzLmludmFsaWRhdGVDaGlsZHJlbihuZXdTdGF0ZS5yb3V0ZUluZm9zLCBpbnZhbGlkYXRlSW5kZXgpOwogICAgICB9CgogICAgICBtZXJnZShuZXdTdGF0ZS5xdWVyeVBhcmFtcywgdGhpcy5xdWVyeVBhcmFtcyB8fCB7fSk7CiAgICAgIHJldHVybiBuZXdTdGF0ZTsKICAgIH07CgogICAgX3Byb3RvNy5pbnZhbGlkYXRlQ2hpbGRyZW4gPSBmdW5jdGlvbiBpbnZhbGlkYXRlQ2hpbGRyZW4oaGFuZGxlckluZm9zLCBpbnZhbGlkYXRlSW5kZXgpIHsKICAgICAgZm9yICh2YXIgaSA9IGludmFsaWRhdGVJbmRleCwgbCA9IGhhbmRsZXJJbmZvcy5sZW5ndGg7IGkgPCBsOyArK2kpIHsKICAgICAgICB2YXIgaGFuZGxlckluZm8gPSBoYW5kbGVySW5mb3NbaV07CgogICAgICAgIGlmIChoYW5kbGVySW5mby5pc1Jlc29sdmVkKSB7CiAgICAgICAgICB2YXIgX2hhbmRsZXJJbmZvcyRpID0gaGFuZGxlckluZm9zW2ldLAogICAgICAgICAgICAgIG5hbWUgPSBfaGFuZGxlckluZm9zJGkubmFtZSwKICAgICAgICAgICAgICBwYXJhbXMgPSBfaGFuZGxlckluZm9zJGkucGFyYW1zLAogICAgICAgICAgICAgIHJvdXRlID0gX2hhbmRsZXJJbmZvcyRpLnJvdXRlLAogICAgICAgICAgICAgIHBhcmFtTmFtZXMgPSBfaGFuZGxlckluZm9zJGkucGFyYW1OYW1lczsKICAgICAgICAgIGhhbmRsZXJJbmZvc1tpXSA9IG5ldyBVbnJlc29sdmVkUm91dGVJbmZvQnlQYXJhbSh0aGlzLnJvdXRlciwgbmFtZSwgcGFyYW1OYW1lcywgcGFyYW1zLCByb3V0ZSk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzcuZ2V0SGFuZGxlckluZm9Gb3JEeW5hbWljU2VnbWVudCA9IGZ1bmN0aW9uIGdldEhhbmRsZXJJbmZvRm9yRHluYW1pY1NlZ21lbnQobmFtZSwgbmFtZXMsIG9iamVjdHMsIG9sZEhhbmRsZXJJbmZvLCBfdGFyZ2V0Um91dGVOYW1lLCBpKSB7CiAgICAgIHZhciBvYmplY3RUb1VzZTsKCiAgICAgIGlmIChvYmplY3RzLmxlbmd0aCA+IDApIHsKICAgICAgICAvLyBVc2UgdGhlIG9iamVjdHMgcHJvdmlkZWQgZm9yIHRoaXMgdHJhbnNpdGlvbi4KICAgICAgICBvYmplY3RUb1VzZSA9IG9iamVjdHNbb2JqZWN0cy5sZW5ndGggLSAxXTsKCiAgICAgICAgaWYgKGlzUGFyYW0ob2JqZWN0VG9Vc2UpKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVQYXJhbUhhbmRsZXJJbmZvKG5hbWUsIG5hbWVzLCBvYmplY3RzLCBvbGRIYW5kbGVySW5mbyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9iamVjdHMucG9wKCk7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKG9sZEhhbmRsZXJJbmZvICYmIG9sZEhhbmRsZXJJbmZvLm5hbWUgPT09IG5hbWUpIHsKICAgICAgICAvLyBSZXVzZSB0aGUgbWF0Y2hpbmcgb2xkSGFuZGxlckluZm8KICAgICAgICByZXR1cm4gb2xkSGFuZGxlckluZm87CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaWYgKHRoaXMucHJlVHJhbnNpdGlvblN0YXRlKSB7CiAgICAgICAgICB2YXIgcHJlVHJhbnNpdGlvbkhhbmRsZXJJbmZvID0gdGhpcy5wcmVUcmFuc2l0aW9uU3RhdGUucm91dGVJbmZvc1tpXTsKICAgICAgICAgIG9iamVjdFRvVXNlID0gcHJlVHJhbnNpdGlvbkhhbmRsZXJJbmZvICYmIHByZVRyYW5zaXRpb25IYW5kbGVySW5mby5jb250ZXh0OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBJZGVhbGx5IHdlIHNob3VsZCB0aHJvdyB0aGlzIGVycm9yIHRvIHByb3ZpZGUgbWF4aW1hbAogICAgICAgICAgLy8gaW5mb3JtYXRpb24gdG8gdGhlIHVzZXIgdGhhdCBub3QgZW5vdWdoIGNvbnRleHQgb2JqZWN0cwogICAgICAgICAgLy8gd2VyZSBwcm92aWRlZCwgYnV0IHRoaXMgcHJvdmVzIHRvbyBjdW1iZXJzb21lIGluIEVtYmVyCiAgICAgICAgICAvLyBpbiBjYXNlcyB3aGVyZSBpbm5lciB0ZW1wbGF0ZSBoZWxwZXJzIGFyZSBldmFsdWF0ZWQKICAgICAgICAgIC8vIGJlZm9yZSBwYXJlbnQgaGVscGVycyB1bi1yZW5kZXIsIGluIHdoaWNoIGNhc2VzIHRoaXMKICAgICAgICAgIC8vIGVycm9yIHNvbWV3aGF0IHByZW1hdHVyZWx5IGZpcmVzLgogICAgICAgICAgLy90aHJvdyBuZXcgRXJyb3IoIk5vdCBlbm91Z2ggY29udGV4dCBvYmplY3RzIHdlcmUgcHJvdmlkZWQgdG8gY29tcGxldGUgYSB0cmFuc2l0aW9uIHRvICIgKyB0YXJnZXRSb3V0ZU5hbWUgKyAiLiBTcGVjaWZpY2FsbHksIHRoZSAiICsgbmFtZSArICIgcm91dGUgbmVlZHMgYW4gb2JqZWN0IHRoYXQgY2FuIGJlIHNlcmlhbGl6ZWQgaW50byBpdHMgZHluYW1pYyBVUkwgc2VnbWVudHMgWyIgKyBuYW1lcy5qb2luKCcsICcpICsgIl0iKTsKICAgICAgICAgIHJldHVybiBvbGRIYW5kbGVySW5mbzsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXcgVW5yZXNvbHZlZFJvdXRlSW5mb0J5T2JqZWN0KHRoaXMucm91dGVyLCBuYW1lLCBuYW1lcywgb2JqZWN0VG9Vc2UpOwogICAgfTsKCiAgICBfcHJvdG83LmNyZWF0ZVBhcmFtSGFuZGxlckluZm8gPSBmdW5jdGlvbiBjcmVhdGVQYXJhbUhhbmRsZXJJbmZvKG5hbWUsIG5hbWVzLCBvYmplY3RzLCBvbGRIYW5kbGVySW5mbykgewogICAgICB2YXIgcGFyYW1zID0ge307IC8vIFNvYWsgdXAgYWxsIHRoZSBwcm92aWRlZCBzdHJpbmcvbnVtYmVycwoKICAgICAgdmFyIG51bU5hbWVzID0gbmFtZXMubGVuZ3RoOwogICAgICB2YXIgbWlzc2luZ1BhcmFtcyA9IFtdOwoKICAgICAgd2hpbGUgKG51bU5hbWVzLS0pIHsKICAgICAgICAvLyBPbmx5IHVzZSBvbGQgcGFyYW1zIGlmIHRoZSBuYW1lcyBtYXRjaCB3aXRoIHRoZSBuZXcgaGFuZGxlcgogICAgICAgIHZhciBvbGRQYXJhbXMgPSBvbGRIYW5kbGVySW5mbyAmJiBuYW1lID09PSBvbGRIYW5kbGVySW5mby5uYW1lICYmIG9sZEhhbmRsZXJJbmZvLnBhcmFtcyB8fCB7fTsKICAgICAgICB2YXIgcGVlayA9IG9iamVjdHNbb2JqZWN0cy5sZW5ndGggLSAxXTsKICAgICAgICB2YXIgcGFyYW1OYW1lID0gbmFtZXNbbnVtTmFtZXNdOwoKICAgICAgICBpZiAoaXNQYXJhbShwZWVrKSkgewogICAgICAgICAgcGFyYW1zW3BhcmFtTmFtZV0gPSAnJyArIG9iamVjdHMucG9wKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vIElmIHdlJ3JlIGhlcmUsIHRoaXMgbWVhbnMgb25seSBzb21lIG9mIHRoZSBwYXJhbXMKICAgICAgICAgIC8vIHdlcmUgc3RyaW5nL251bWJlciBwYXJhbXMsIHNvIHRyeSBhbmQgdXNlIGEgcGFyYW0KICAgICAgICAgIC8vIHZhbHVlIGZyb20gYSBwcmV2aW91cyBoYW5kbGVyLgogICAgICAgICAgaWYgKG9sZFBhcmFtcy5oYXNPd25Qcm9wZXJ0eShwYXJhbU5hbWUpKSB7CiAgICAgICAgICAgIHBhcmFtc1twYXJhbU5hbWVdID0gb2xkUGFyYW1zW3BhcmFtTmFtZV07CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBtaXNzaW5nUGFyYW1zLnB1c2gocGFyYW1OYW1lKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChtaXNzaW5nUGFyYW1zLmxlbmd0aCA+IDApIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIllvdSBkaWRuJ3QgcHJvdmlkZSBlbm91Z2ggc3RyaW5nL251bWVyaWMgcGFyYW1ldGVycyB0byBzYXRpc2Z5IGFsbCBvZiB0aGUgZHluYW1pYyBzZWdtZW50cyBmb3Igcm91dGUgIiArIG5hbWUgKyAiLiIgKyAoIiBNaXNzaW5nIHBhcmFtczogIiArIG1pc3NpbmdQYXJhbXMpKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5ldyBVbnJlc29sdmVkUm91dGVJbmZvQnlQYXJhbSh0aGlzLnJvdXRlciwgbmFtZSwgbmFtZXMsIHBhcmFtcyk7CiAgICB9OwoKICAgIHJldHVybiBOYW1lZFRyYW5zaXRpb25JbnRlbnQ7CiAgfShUcmFuc2l0aW9uSW50ZW50KTsKCiAgdmFyIFVucmVjb2duaXplZFVSTEVycm9yID0gZnVuY3Rpb24gKCkgewogICAgVW5yZWNvZ25pemVkVVJMRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFcnJvci5wcm90b3R5cGUpOwogICAgVW5yZWNvZ25pemVkVVJMRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gVW5yZWNvZ25pemVkVVJMRXJyb3I7CgogICAgZnVuY3Rpb24gVW5yZWNvZ25pemVkVVJMRXJyb3IobWVzc2FnZSkgewogICAgICB2YXIgZXJyb3IgPSBFcnJvci5jYWxsKHRoaXMsIG1lc3NhZ2UpOwogICAgICB0aGlzLm5hbWUgPSAnVW5yZWNvZ25pemVkVVJMRXJyb3InOwogICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlIHx8ICdVbnJlY29nbml6ZWRVUkwnOwoKICAgICAgaWYgKEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKSB7CiAgICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgVW5yZWNvZ25pemVkVVJMRXJyb3IpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuc3RhY2sgPSBlcnJvci5zdGFjazsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBVbnJlY29nbml6ZWRVUkxFcnJvcjsKICB9KCk7CgogIHZhciBVUkxUcmFuc2l0aW9uSW50ZW50ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9UcmFuc2l0aW9uSW50ZW50MikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFVSTFRyYW5zaXRpb25JbnRlbnQsIF9UcmFuc2l0aW9uSW50ZW50Mik7CgogICAgZnVuY3Rpb24gVVJMVHJhbnNpdGlvbkludGVudChyb3V0ZXIsIHVybCwgZGF0YSkgewogICAgICB2YXIgX3RoaXM4OwoKICAgICAgX3RoaXM4ID0gX1RyYW5zaXRpb25JbnRlbnQyLmNhbGwodGhpcywgcm91dGVyLCBkYXRhKSB8fCB0aGlzOwogICAgICBfdGhpczgudXJsID0gdXJsOwogICAgICBfdGhpczgucHJlVHJhbnNpdGlvblN0YXRlID0gdW5kZWZpbmVkOwogICAgICByZXR1cm4gX3RoaXM4OwogICAgfQoKICAgIHZhciBfcHJvdG84ID0gVVJMVHJhbnNpdGlvbkludGVudC5wcm90b3R5cGU7CgogICAgX3Byb3RvOC5hcHBseVRvU3RhdGUgPSBmdW5jdGlvbiBhcHBseVRvU3RhdGUob2xkU3RhdGUpIHsKICAgICAgdmFyIG5ld1N0YXRlID0gbmV3IFRyYW5zaXRpb25TdGF0ZSgpOwogICAgICB2YXIgcmVzdWx0cyA9IHRoaXMucm91dGVyLnJlY29nbml6ZXIucmVjb2duaXplKHRoaXMudXJsKSwKICAgICAgICAgIGksCiAgICAgICAgICBsZW47CgogICAgICBpZiAoIXJlc3VsdHMpIHsKICAgICAgICB0aHJvdyBuZXcgVW5yZWNvZ25pemVkVVJMRXJyb3IodGhpcy51cmwpOwogICAgICB9CgogICAgICB2YXIgc3RhdGVzRGlmZmVyID0gZmFsc2U7CiAgICAgIHZhciBfdXJsID0gdGhpcy51cmw7IC8vIENoZWNrcyBpZiBhIGhhbmRsZXIgaXMgYWNjZXNzaWJsZSBieSBVUkwuIElmIGl0IGlzIG5vdCwgYW4gZXJyb3IgaXMgdGhyb3duLgogICAgICAvLyBGb3IgdGhlIGNhc2Ugd2hlcmUgdGhlIGhhbmRsZXIgaXMgbG9hZGVkIGFzeW5jaHJvbm91c2x5LCB0aGUgZXJyb3Igd2lsbCBiZQogICAgICAvLyB0aHJvd24gb25jZSBpdCBpcyBsb2FkZWQuCgogICAgICBmdW5jdGlvbiBjaGVja0hhbmRsZXJBY2Nlc3NpYmlsaXR5KGhhbmRsZXIpIHsKICAgICAgICBpZiAoaGFuZGxlciAmJiBoYW5kbGVyLmluYWNjZXNzaWJsZUJ5VVJMKSB7CiAgICAgICAgICB0aHJvdyBuZXcgVW5yZWNvZ25pemVkVVJMRXJyb3IoX3VybCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gaGFuZGxlcjsKICAgICAgfQoKICAgICAgZm9yIChpID0gMCwgbGVuID0gcmVzdWx0cy5sZW5ndGg7IGkgPCBsZW47ICsraSkgewogICAgICAgIHZhciByZXN1bHQgPSByZXN1bHRzW2ldOwogICAgICAgIHZhciBuYW1lID0gcmVzdWx0LmhhbmRsZXI7CiAgICAgICAgdmFyIHBhcmFtTmFtZXMgPSBbXTsKCiAgICAgICAgaWYgKHRoaXMucm91dGVyLnJlY29nbml6ZXIuaGFzUm91dGUobmFtZSkpIHsKICAgICAgICAgIHBhcmFtTmFtZXMgPSB0aGlzLnJvdXRlci5yZWNvZ25pemVyLmhhbmRsZXJzRm9yKG5hbWUpW2ldLm5hbWVzOwogICAgICAgIH0KCiAgICAgICAgdmFyIG5ld1JvdXRlSW5mbyA9IG5ldyBVbnJlc29sdmVkUm91dGVJbmZvQnlQYXJhbSh0aGlzLnJvdXRlciwgbmFtZSwgcGFyYW1OYW1lcywgcmVzdWx0LnBhcmFtcyk7CiAgICAgICAgdmFyIHJvdXRlID0gbmV3Um91dGVJbmZvLnJvdXRlOwoKICAgICAgICBpZiAocm91dGUpIHsKICAgICAgICAgIGNoZWNrSGFuZGxlckFjY2Vzc2liaWxpdHkocm91dGUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBJZiB0aGUgaGFubGRlciBpcyBiZWluZyBsb2FkZWQgYXN5bmNocm9ub3VzbHksIGNoZWNrIGlmIHdlIGNhbgogICAgICAgICAgLy8gYWNjZXNzIGl0IGFmdGVyIGl0IGhhcyByZXNvbHZlZAogICAgICAgICAgbmV3Um91dGVJbmZvLnJvdXRlUHJvbWlzZSA9IG5ld1JvdXRlSW5mby5yb3V0ZVByb21pc2UudGhlbihjaGVja0hhbmRsZXJBY2Nlc3NpYmlsaXR5KTsKICAgICAgICB9CgogICAgICAgIHZhciBvbGRSb3V0ZUluZm8gPSBvbGRTdGF0ZS5yb3V0ZUluZm9zW2ldOwoKICAgICAgICBpZiAoc3RhdGVzRGlmZmVyIHx8IG5ld1JvdXRlSW5mby5zaG91bGRTdXBlcmNlZGUob2xkUm91dGVJbmZvKSkgewogICAgICAgICAgc3RhdGVzRGlmZmVyID0gdHJ1ZTsKICAgICAgICAgIG5ld1N0YXRlLnJvdXRlSW5mb3NbaV0gPSBuZXdSb3V0ZUluZm87CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG5ld1N0YXRlLnJvdXRlSW5mb3NbaV0gPSBvbGRSb3V0ZUluZm87CiAgICAgICAgfQogICAgICB9CgogICAgICBtZXJnZShuZXdTdGF0ZS5xdWVyeVBhcmFtcywgcmVzdWx0cy5xdWVyeVBhcmFtcyk7CiAgICAgIHJldHVybiBuZXdTdGF0ZTsKICAgIH07CgogICAgcmV0dXJuIFVSTFRyYW5zaXRpb25JbnRlbnQ7CiAgfShUcmFuc2l0aW9uSW50ZW50KTsKCiAgdmFyIFJvdXRlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJvdXRlcihsb2dnZXIpIHsKICAgICAgdGhpcy5fbGFzdFF1ZXJ5UGFyYW1zID0ge307CiAgICAgIHRoaXMuc3RhdGUgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMub2xkU3RhdGUgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuYWN0aXZlVHJhbnNpdGlvbiA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5jdXJyZW50Um91dGVJbmZvcyA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5fY2hhbmdlZFF1ZXJ5UGFyYW1zID0gdW5kZWZpbmVkOwogICAgICB0aGlzLmN1cnJlbnRTZXF1ZW5jZSA9IDA7CiAgICAgIHRoaXMubG9nID0gbG9nZ2VyOwogICAgICB0aGlzLnJlY29nbml6ZXIgPSBuZXcgX3JvdXRlUmVjb2duaXplci5kZWZhdWx0KCk7CiAgICAgIHRoaXMucmVzZXQoKTsKICAgIH0KICAgIC8qKgogICAgICBUaGUgbWFpbiBlbnRyeSBwb2ludCBpbnRvIHRoZSByb3V0ZXIuIFRoZSBBUEkgaXMgZXNzZW50aWFsbHkKICAgICAgdGhlIHNhbWUgYXMgdGhlIGBtYXBgIG1ldGhvZCBpbiBgcm91dGUtcmVjb2duaXplcmAuCiAgICAgICAgIFRoaXMgbWV0aG9kIGV4dHJhY3RzIHRoZSBTdHJpbmcgaGFuZGxlciBhdCB0aGUgbGFzdCBgLnRvKClgCiAgICAgIGNhbGwgYW5kIHVzZXMgaXQgYXMgdGhlIG5hbWUgb2YgdGhlIHdob2xlIHJvdXRlLgogICAgICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgKi8KCgogICAgdmFyIF9wcm90bzkgPSBSb3V0ZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzkubWFwID0gZnVuY3Rpb24gbWFwKGNhbGxiYWNrKSB7CiAgICAgIHRoaXMucmVjb2duaXplci5tYXAoY2FsbGJhY2ssIGZ1bmN0aW9uIChyZWNvZ25pemVyLCByb3V0ZXMpIHsKICAgICAgICBmb3IgKHZhciBpID0gcm91dGVzLmxlbmd0aCAtIDEsIHByb2NlZWQgPSB0cnVlOyBpID49IDAgJiYgcHJvY2VlZDsgLS1pKSB7CiAgICAgICAgICB2YXIgcm91dGUgPSByb3V0ZXNbaV07CiAgICAgICAgICB2YXIgaGFuZGxlciA9IHJvdXRlLmhhbmRsZXI7CiAgICAgICAgICByZWNvZ25pemVyLmFkZChyb3V0ZXMsIHsKICAgICAgICAgICAgYXM6IGhhbmRsZXIKICAgICAgICAgIH0pOwogICAgICAgICAgcHJvY2VlZCA9IHJvdXRlLnBhdGggPT09ICcvJyB8fCByb3V0ZS5wYXRoID09PSAnJyB8fCBoYW5kbGVyLnNsaWNlKC02KSA9PT0gJy5pbmRleCc7CiAgICAgICAgfQogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvOS5oYXNSb3V0ZSA9IGZ1bmN0aW9uIGhhc1JvdXRlKHJvdXRlKSB7CiAgICAgIHJldHVybiB0aGlzLnJlY29nbml6ZXIuaGFzUm91dGUocm91dGUpOwogICAgfTsKCiAgICBfcHJvdG85LnF1ZXJ5UGFyYW1zVHJhbnNpdGlvbiA9IGZ1bmN0aW9uIHF1ZXJ5UGFyYW1zVHJhbnNpdGlvbihjaGFuZ2VsaXN0LCB3YXNUcmFuc2l0aW9uaW5nLCBvbGRTdGF0ZSwgbmV3U3RhdGUpIHsKICAgICAgdmFyIF90aGlzOSA9IHRoaXM7CgogICAgICB0aGlzLmZpcmVRdWVyeVBhcmFtRGlkQ2hhbmdlKG5ld1N0YXRlLCBjaGFuZ2VsaXN0KTsKCiAgICAgIGlmICghd2FzVHJhbnNpdGlvbmluZyAmJiB0aGlzLmFjdGl2ZVRyYW5zaXRpb24pIHsKICAgICAgICAvLyBPbmUgb2YgdGhlIHJvdXRlcyBpbiBxdWVyeVBhcmFtc0RpZENoYW5nZQogICAgICAgIC8vIGNhdXNlZCBhIHRyYW5zaXRpb24uIEp1c3QgcmV0dXJuIHRoYXQgdHJhbnNpdGlvbi4KICAgICAgICByZXR1cm4gdGhpcy5hY3RpdmVUcmFuc2l0aW9uOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIFJ1bm5pbmcgcXVlcnlQYXJhbXNEaWRDaGFuZ2UgZGlkbid0IGNoYW5nZSBhbnl0aGluZy4KICAgICAgICAvLyBKdXN0IHVwZGF0ZSBxdWVyeSBwYXJhbXMgYW5kIGJlIG9uIG91ciB3YXkuCiAgICAgICAgLy8gV2UgaGF2ZSB0byByZXR1cm4gYSBub29wIHRyYW5zaXRpb24gdGhhdCB3aWxsCiAgICAgICAgLy8gcGVyZm9ybSBhIFVSTCB1cGRhdGUgYXQgdGhlIGVuZC4gVGhpcyBnaXZlcwogICAgICAgIC8vIHRoZSB1c2VyIHRoZSBhYmlsaXR5IHRvIHNldCB0aGUgdXJsIHVwZGF0ZQogICAgICAgIC8vIG1ldGhvZCAoZGVmYXVsdCBpcyByZXBsYWNlU3RhdGUpLgogICAgICAgIHZhciBuZXdUcmFuc2l0aW9uID0gbmV3IFRyYW5zaXRpb24odGhpcywgdW5kZWZpbmVkLCB1bmRlZmluZWQpOwogICAgICAgIG5ld1RyYW5zaXRpb24ucXVlcnlQYXJhbXNPbmx5ID0gdHJ1ZTsKICAgICAgICBvbGRTdGF0ZS5xdWVyeVBhcmFtcyA9IHRoaXMuZmluYWxpemVRdWVyeVBhcmFtQ2hhbmdlKG5ld1N0YXRlLnJvdXRlSW5mb3MsIG5ld1N0YXRlLnF1ZXJ5UGFyYW1zLCBuZXdUcmFuc2l0aW9uKTsKICAgICAgICBuZXdUcmFuc2l0aW9uW1FVRVJZX1BBUkFNU19TWU1CT0xdID0gbmV3U3RhdGUucXVlcnlQYXJhbXM7CiAgICAgICAgdGhpcy50b1JlYWRPbmx5SW5mb3MobmV3VHJhbnNpdGlvbiwgbmV3U3RhdGUpOwogICAgICAgIHRoaXMucm91dGVXaWxsQ2hhbmdlKG5ld1RyYW5zaXRpb24pOwogICAgICAgIG5ld1RyYW5zaXRpb24ucHJvbWlzZSA9IG5ld1RyYW5zaXRpb24ucHJvbWlzZS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHsKICAgICAgICAgIF90aGlzOS5fdXBkYXRlVVJMKG5ld1RyYW5zaXRpb24sIG9sZFN0YXRlKTsKCiAgICAgICAgICBfdGhpczkuZGlkVHJhbnNpdGlvbihfdGhpczkuY3VycmVudFJvdXRlSW5mb3MpOwoKICAgICAgICAgIF90aGlzOS50b0luZm9zKG5ld1RyYW5zaXRpb24sIG5ld1N0YXRlLnJvdXRlSW5mb3MsIHRydWUpOwoKICAgICAgICAgIF90aGlzOS5yb3V0ZURpZENoYW5nZShuZXdUcmFuc2l0aW9uKTsKCiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0sIG51bGwsIF9wcm9taXNlTGFiZWwoJ1RyYW5zaXRpb24gY29tcGxldGUnKSk7CiAgICAgICAgcmV0dXJuIG5ld1RyYW5zaXRpb247CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvOS50cmFuc2l0aW9uQnlJbnRlbnQgPSBmdW5jdGlvbiB0cmFuc2l0aW9uQnlJbnRlbnQoaW50ZW50LCBpc0ludGVybWVkaWF0ZSkgewogICAgICB0cnkgewogICAgICAgIHJldHVybiB0aGlzLmdldFRyYW5zaXRpb25CeUludGVudChpbnRlbnQsIGlzSW50ZXJtZWRpYXRlKTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIHJldHVybiBuZXcgVHJhbnNpdGlvbih0aGlzLCBpbnRlbnQsIHVuZGVmaW5lZCwgZSwgdW5kZWZpbmVkKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG85LnJlY29nbml6ZSA9IGZ1bmN0aW9uIHJlY29nbml6ZSh1cmwpIHsKICAgICAgdmFyIGludGVudCA9IG5ldyBVUkxUcmFuc2l0aW9uSW50ZW50KHRoaXMsIHVybCk7CiAgICAgIHZhciBuZXdTdGF0ZSA9IHRoaXMuZ2VuZXJhdGVOZXdTdGF0ZShpbnRlbnQpOwoKICAgICAgaWYgKG5ld1N0YXRlID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIG5ld1N0YXRlOwogICAgICB9CgogICAgICB2YXIgcmVhZG9ubHlJbmZvcyA9IHRvUmVhZE9ubHlSb3V0ZUluZm8obmV3U3RhdGUucm91dGVJbmZvcywgbmV3U3RhdGUucXVlcnlQYXJhbXMpOwogICAgICByZXR1cm4gcmVhZG9ubHlJbmZvc1tyZWFkb25seUluZm9zLmxlbmd0aCAtIDFdOwogICAgfTsKCiAgICBfcHJvdG85LnJlY29nbml6ZUFuZExvYWQgPSBmdW5jdGlvbiByZWNvZ25pemVBbmRMb2FkKHVybCkgewogICAgICB2YXIgaW50ZW50ID0gbmV3IFVSTFRyYW5zaXRpb25JbnRlbnQodGhpcywgdXJsKTsKICAgICAgdmFyIG5ld1N0YXRlID0gdGhpcy5nZW5lcmF0ZU5ld1N0YXRlKGludGVudCk7CgogICAgICBpZiAobmV3U3RhdGUgPT09IG51bGwpIHsKICAgICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZWplY3QoIlVSTCAiICsgdXJsICsgIiB3YXMgbm90IHJlY29nbml6ZWQiKTsKICAgICAgfQoKICAgICAgdmFyIG5ld1RyYW5zaXRpb24gPSBuZXcgVHJhbnNpdGlvbih0aGlzLCBpbnRlbnQsIG5ld1N0YXRlLCB1bmRlZmluZWQpOwogICAgICByZXR1cm4gbmV3VHJhbnNpdGlvbi50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgcm91dGVJbmZvc1dpdGhBdHRyaWJ1dGVzID0gdG9SZWFkT25seVJvdXRlSW5mbyhuZXdTdGF0ZS5yb3V0ZUluZm9zLCBuZXdUcmFuc2l0aW9uW1FVRVJZX1BBUkFNU19TWU1CT0xdLCB0cnVlKTsKICAgICAgICByZXR1cm4gcm91dGVJbmZvc1dpdGhBdHRyaWJ1dGVzW3JvdXRlSW5mb3NXaXRoQXR0cmlidXRlcy5sZW5ndGggLSAxXTsKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90bzkuZ2VuZXJhdGVOZXdTdGF0ZSA9IGZ1bmN0aW9uIGdlbmVyYXRlTmV3U3RhdGUoaW50ZW50KSB7CiAgICAgIHRyeSB7CiAgICAgICAgcmV0dXJuIGludGVudC5hcHBseVRvU3RhdGUodGhpcy5zdGF0ZSwgZmFsc2UpOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvOS5nZXRUcmFuc2l0aW9uQnlJbnRlbnQgPSBmdW5jdGlvbiBnZXRUcmFuc2l0aW9uQnlJbnRlbnQoaW50ZW50LCBpc0ludGVybWVkaWF0ZSkgewogICAgICB2YXIgX3RoaXMxMCA9IHRoaXM7CgogICAgICB2YXIgd2FzVHJhbnNpdGlvbmluZyA9ICEhdGhpcy5hY3RpdmVUcmFuc2l0aW9uOwogICAgICB2YXIgb2xkU3RhdGUgPSB3YXNUcmFuc2l0aW9uaW5nID8gdGhpcy5hY3RpdmVUcmFuc2l0aW9uW1NUQVRFX1NZTUJPTF0gOiB0aGlzLnN0YXRlOwogICAgICB2YXIgbmV3VHJhbnNpdGlvbjsKICAgICAgdmFyIG5ld1N0YXRlID0gaW50ZW50LmFwcGx5VG9TdGF0ZShvbGRTdGF0ZSwgaXNJbnRlcm1lZGlhdGUpOwogICAgICB2YXIgcXVlcnlQYXJhbUNoYW5nZWxpc3QgPSBnZXRDaGFuZ2VsaXN0KG9sZFN0YXRlLnF1ZXJ5UGFyYW1zLCBuZXdTdGF0ZS5xdWVyeVBhcmFtcyk7CgogICAgICBpZiAocm91dGVJbmZvc0VxdWFsKG5ld1N0YXRlLnJvdXRlSW5mb3MsIG9sZFN0YXRlLnJvdXRlSW5mb3MpKSB7CiAgICAgICAgLy8gVGhpcyBpcyBhIG5vLW9wIHRyYW5zaXRpb24uIFNlZSBpZiBxdWVyeSBwYXJhbXMgY2hhbmdlZC4KICAgICAgICBpZiAocXVlcnlQYXJhbUNoYW5nZWxpc3QpIHsKICAgICAgICAgIHZhciBfbmV3VHJhbnNpdGlvbiA9IHRoaXMucXVlcnlQYXJhbXNUcmFuc2l0aW9uKHF1ZXJ5UGFyYW1DaGFuZ2VsaXN0LCB3YXNUcmFuc2l0aW9uaW5nLCBvbGRTdGF0ZSwgbmV3U3RhdGUpOwoKICAgICAgICAgIF9uZXdUcmFuc2l0aW9uLnF1ZXJ5UGFyYW1zT25seSA9IHRydWU7CiAgICAgICAgICByZXR1cm4gX25ld1RyYW5zaXRpb247CiAgICAgICAgfSAvLyBOby1vcC4gTm8gbmVlZCB0byBjcmVhdGUgYSBuZXcgdHJhbnNpdGlvbi4KCgogICAgICAgIHJldHVybiB0aGlzLmFjdGl2ZVRyYW5zaXRpb24gfHwgbmV3IFRyYW5zaXRpb24odGhpcywgdW5kZWZpbmVkLCB1bmRlZmluZWQpOwogICAgICB9CgogICAgICBpZiAoaXNJbnRlcm1lZGlhdGUpIHsKICAgICAgICB2YXIgdHJhbnNpdGlvbiA9IG5ldyBUcmFuc2l0aW9uKHRoaXMsIHVuZGVmaW5lZCwgdW5kZWZpbmVkKTsKICAgICAgICB0aGlzLnRvUmVhZE9ubHlJbmZvcyh0cmFuc2l0aW9uLCBuZXdTdGF0ZSk7CiAgICAgICAgdGhpcy5zZXR1cENvbnRleHRzKG5ld1N0YXRlKTsKICAgICAgICB0aGlzLnJvdXRlV2lsbENoYW5nZSh0cmFuc2l0aW9uKTsKICAgICAgICByZXR1cm4gdGhpcy5hY3RpdmVUcmFuc2l0aW9uOwogICAgICB9IC8vIENyZWF0ZSBhIG5ldyB0cmFuc2l0aW9uIHRvIHRoZSBkZXN0aW5hdGlvbiByb3V0ZS4KCgogICAgICBuZXdUcmFuc2l0aW9uID0gbmV3IFRyYW5zaXRpb24odGhpcywgaW50ZW50LCBuZXdTdGF0ZSwgdW5kZWZpbmVkLCB0aGlzLmFjdGl2ZVRyYW5zaXRpb24pOyAvLyB0cmFuc2l0aW9uIGlzIHRvIHNhbWUgcm91dGUgd2l0aCBzYW1lIHBhcmFtcywgb25seSBxdWVyeSBwYXJhbXMgZGlmZmVyLgogICAgICAvLyBub3QgY2F1Z2h0IGFib3ZlIHByb2JhYmx5IGJlY2F1c2UgcmVmcmVzaCgpIGhhcyBiZWVuIHVzZWQKCiAgICAgIGlmIChyb3V0ZUluZm9zU2FtZUV4Y2VwdFF1ZXJ5UGFyYW1zKG5ld1N0YXRlLnJvdXRlSW5mb3MsIG9sZFN0YXRlLnJvdXRlSW5mb3MpKSB7CiAgICAgICAgbmV3VHJhbnNpdGlvbi5xdWVyeVBhcmFtc09ubHkgPSB0cnVlOwogICAgICB9CgogICAgICB0aGlzLnRvUmVhZE9ubHlJbmZvcyhuZXdUcmFuc2l0aW9uLCBuZXdTdGF0ZSk7IC8vIEFib3J0IGFuZCB1c3VycCBhbnkgcHJldmlvdXNseSBhY3RpdmUgdHJhbnNpdGlvbi4KCiAgICAgIGlmICh0aGlzLmFjdGl2ZVRyYW5zaXRpb24pIHsKICAgICAgICB0aGlzLmFjdGl2ZVRyYW5zaXRpb24ucmVkaXJlY3QobmV3VHJhbnNpdGlvbik7CiAgICAgIH0KCiAgICAgIHRoaXMuYWN0aXZlVHJhbnNpdGlvbiA9IG5ld1RyYW5zaXRpb247IC8vIFRyYW5zaXRpb24gcHJvbWlzZXMgYnkgZGVmYXVsdCByZXNvbHZlIHdpdGggcmVzb2x2ZWQgc3RhdGUuCiAgICAgIC8vIEZvciBvdXIgcHVycG9zZXMsIHN3YXAgb3V0IHRoZSBwcm9taXNlIHRvIHJlc29sdmUKICAgICAgLy8gYWZ0ZXIgdGhlIHRyYW5zaXRpb24gaGFzIGJlZW4gZmluYWxpemVkLgoKICAgICAgbmV3VHJhbnNpdGlvbi5wcm9taXNlID0gbmV3VHJhbnNpdGlvbi5wcm9taXNlLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkgewogICAgICAgIHJldHVybiBfdGhpczEwLmZpbmFsaXplVHJhbnNpdGlvbihuZXdUcmFuc2l0aW9uLCByZXN1bHQpOwogICAgICB9LCBudWxsLCBfcHJvbWlzZUxhYmVsKCdTZXR0bGUgdHJhbnNpdGlvbiBwcm9taXNlIHdoZW4gdHJhbnNpdGlvbiBpcyBmaW5hbGl6ZWQnKSk7CgogICAgICBpZiAoIXdhc1RyYW5zaXRpb25pbmcpIHsKICAgICAgICB0aGlzLm5vdGlmeUV4aXN0aW5nSGFuZGxlcnMobmV3U3RhdGUsIG5ld1RyYW5zaXRpb24pOwogICAgICB9CgogICAgICB0aGlzLmZpcmVRdWVyeVBhcmFtRGlkQ2hhbmdlKG5ld1N0YXRlLCBxdWVyeVBhcmFtQ2hhbmdlbGlzdCk7CiAgICAgIHJldHVybiBuZXdUcmFuc2l0aW9uOwogICAgfQogICAgLyoqCiAgICBAcHJpdmF0ZQogICAgICAgQmVnaW5zIGFuZCByZXR1cm5zIGEgVHJhbnNpdGlvbiBiYXNlZCBvbiB0aGUgcHJvdmlkZWQKICAgIGFyZ3VtZW50cy4gQWNjZXB0cyBhcmd1bWVudHMgaW4gdGhlIGZvcm0gb2YgYm90aCBVUkwKICAgIHRyYW5zaXRpb25zIGFuZCBuYW1lZCB0cmFuc2l0aW9ucy4KICAgICAgIEBwYXJhbSB7Um91dGVyfSByb3V0ZXIKICAgIEBwYXJhbSB7QXJyYXlbT2JqZWN0XX0gYXJncyBhcmd1bWVudHMgcGFzc2VkIHRvIHRyYW5zaXRpb25UbywKICAgICAgcmVwbGFjZVdpdGgsIG9yIGhhbmRsZVVSTAogICAgKi8KICAgIDsKCiAgICBfcHJvdG85LmRvVHJhbnNpdGlvbiA9IGZ1bmN0aW9uIGRvVHJhbnNpdGlvbihuYW1lLCBtb2RlbHNBcnJheSwgaXNJbnRlcm1lZGlhdGUpIHsKICAgICAgaWYgKG1vZGVsc0FycmF5ID09PSB2b2lkIDApIHsKICAgICAgICBtb2RlbHNBcnJheSA9IFtdOwogICAgICB9CgogICAgICBpZiAoaXNJbnRlcm1lZGlhdGUgPT09IHZvaWQgMCkgewogICAgICAgIGlzSW50ZXJtZWRpYXRlID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIHZhciBsYXN0QXJnID0gbW9kZWxzQXJyYXlbbW9kZWxzQXJyYXkubGVuZ3RoIC0gMV07CiAgICAgIHZhciBxdWVyeVBhcmFtcyA9IHt9OwoKICAgICAgaWYgKGxhc3RBcmcgIT09IHVuZGVmaW5lZCAmJiBsYXN0QXJnLmhhc093blByb3BlcnR5KCdxdWVyeVBhcmFtcycpKSB7CiAgICAgICAgcXVlcnlQYXJhbXMgPSBtb2RlbHNBcnJheS5wb3AoKS5xdWVyeVBhcmFtczsKICAgICAgfQoKICAgICAgdmFyIGludGVudDsKCiAgICAgIGlmIChuYW1lID09PSB1bmRlZmluZWQpIHsKICAgICAgICBfbG9nKHRoaXMsICdVcGRhdGluZyBxdWVyeSBwYXJhbXMnKTsgLy8gQSBxdWVyeSBwYXJhbSB1cGRhdGUgaXMgcmVhbGx5IGp1c3QgYSB0cmFuc2l0aW9uCiAgICAgICAgLy8gaW50byB0aGUgcm91dGUgeW91J3JlIGFscmVhZHkgb24uCgoKICAgICAgICB2YXIgcm91dGVJbmZvcyA9IHRoaXMuc3RhdGUucm91dGVJbmZvczsKICAgICAgICBpbnRlbnQgPSBuZXcgTmFtZWRUcmFuc2l0aW9uSW50ZW50KHRoaXMsIHJvdXRlSW5mb3Nbcm91dGVJbmZvcy5sZW5ndGggLSAxXS5uYW1lLCB1bmRlZmluZWQsIFtdLCBxdWVyeVBhcmFtcyk7CiAgICAgIH0gZWxzZSBpZiAobmFtZS5jaGFyQXQoMCkgPT09ICcvJykgewogICAgICAgIF9sb2codGhpcywgJ0F0dGVtcHRpbmcgVVJMIHRyYW5zaXRpb24gdG8gJyArIG5hbWUpOwoKICAgICAgICBpbnRlbnQgPSBuZXcgVVJMVHJhbnNpdGlvbkludGVudCh0aGlzLCBuYW1lKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBfbG9nKHRoaXMsICdBdHRlbXB0aW5nIHRyYW5zaXRpb24gdG8gJyArIG5hbWUpOwoKICAgICAgICBpbnRlbnQgPSBuZXcgTmFtZWRUcmFuc2l0aW9uSW50ZW50KHRoaXMsIG5hbWUsIHVuZGVmaW5lZCwgbW9kZWxzQXJyYXksIHF1ZXJ5UGFyYW1zKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMudHJhbnNpdGlvbkJ5SW50ZW50KGludGVudCwgaXNJbnRlcm1lZGlhdGUpOwogICAgfQogICAgLyoqCiAgICBAcHJpdmF0ZQogICAgICAgVXBkYXRlcyB0aGUgVVJMIChpZiBuZWNlc3NhcnkpIGFuZCBjYWxscyBgc2V0dXBDb250ZXh0c2AKICAgIHRvIHVwZGF0ZSB0aGUgcm91dGVyJ3MgYXJyYXkgb2YgYGN1cnJlbnRSb3V0ZUluZm9zYC4KICAgICovCiAgICA7CgogICAgX3Byb3RvOS5maW5hbGl6ZVRyYW5zaXRpb24gPSBmdW5jdGlvbiBmaW5hbGl6ZVRyYW5zaXRpb24odHJhbnNpdGlvbiwgbmV3U3RhdGUpIHsKICAgICAgdHJ5IHsKICAgICAgICBfbG9nKHRyYW5zaXRpb24ucm91dGVyLCB0cmFuc2l0aW9uLnNlcXVlbmNlLCAnUmVzb2x2ZWQgYWxsIG1vZGVscyBvbiBkZXN0aW5hdGlvbiByb3V0ZTsgZmluYWxpemluZyB0cmFuc2l0aW9uLicpOwoKICAgICAgICB2YXIgcm91dGVJbmZvcyA9IG5ld1N0YXRlLnJvdXRlSW5mb3M7IC8vIFJ1biBhbGwgdGhlIG5lY2Vzc2FyeSBlbnRlci9zZXR1cC9leGl0IGhvb2tzCgogICAgICAgIHRoaXMuc2V0dXBDb250ZXh0cyhuZXdTdGF0ZSwgdHJhbnNpdGlvbik7IC8vIENoZWNrIGlmIGEgcmVkaXJlY3Qgb2NjdXJyZWQgaW4gZW50ZXIvc2V0dXAKCiAgICAgICAgaWYgKHRyYW5zaXRpb24uaXNBYm9ydGVkKSB7CiAgICAgICAgICAvLyBUT0RPOiBjbGVhbmVyIHdheT8gZGlzdGluZ3Vpc2ggYi93IHRhcmdldFJvdXRlSW5mb3M/CiAgICAgICAgICB0aGlzLnN0YXRlLnJvdXRlSW5mb3MgPSB0aGlzLmN1cnJlbnRSb3V0ZUluZm9zOwogICAgICAgICAgcmV0dXJuIF9yc3ZwLlByb21pc2UucmVqZWN0KGxvZ0Fib3J0KHRyYW5zaXRpb24pKTsKICAgICAgICB9CgogICAgICAgIHRoaXMuX3VwZGF0ZVVSTCh0cmFuc2l0aW9uLCBuZXdTdGF0ZSk7CgogICAgICAgIHRyYW5zaXRpb24uaXNBY3RpdmUgPSBmYWxzZTsKICAgICAgICB0aGlzLmFjdGl2ZVRyYW5zaXRpb24gPSB1bmRlZmluZWQ7CiAgICAgICAgdGhpcy50cmlnZ2VyRXZlbnQodGhpcy5jdXJyZW50Um91dGVJbmZvcywgdHJ1ZSwgJ2RpZFRyYW5zaXRpb24nLCBbXSk7CiAgICAgICAgdGhpcy5kaWRUcmFuc2l0aW9uKHRoaXMuY3VycmVudFJvdXRlSW5mb3MpOwogICAgICAgIHRoaXMudG9JbmZvcyh0cmFuc2l0aW9uLCBuZXdTdGF0ZS5yb3V0ZUluZm9zLCB0cnVlKTsKICAgICAgICB0aGlzLnJvdXRlRGlkQ2hhbmdlKHRyYW5zaXRpb24pOwoKICAgICAgICBfbG9nKHRoaXMsIHRyYW5zaXRpb24uc2VxdWVuY2UsICdUUkFOU0lUSU9OIENPTVBMRVRFLicpOyAvLyBSZXNvbHZlIHdpdGggdGhlIGZpbmFsIHJvdXRlLgoKCiAgICAgICAgcmV0dXJuIHJvdXRlSW5mb3Nbcm91dGVJbmZvcy5sZW5ndGggLSAxXS5yb3V0ZTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBUcmFuc2l0aW9uQWJvcnRlZEVycm9yKSkgewogICAgICAgICAgdmFyIGluZm9zID0gdHJhbnNpdGlvbltTVEFURV9TWU1CT0xdLnJvdXRlSW5mb3M7CiAgICAgICAgICB0cmFuc2l0aW9uLnRyaWdnZXIodHJ1ZSwgJ2Vycm9yJywgZSwgdHJhbnNpdGlvbiwgaW5mb3NbaW5mb3MubGVuZ3RoIC0gMV0ucm91dGUpOwogICAgICAgICAgdHJhbnNpdGlvbi5hYm9ydCgpOwogICAgICAgIH0KCiAgICAgICAgdGhyb3cgZTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICBAcHJpdmF0ZQogICAgICAgVGFrZXMgYW4gQXJyYXkgb2YgYFJvdXRlSW5mb2BzLCBmaWd1cmVzIG91dCB3aGljaCBvbmVzIGFyZQogICAgZXhpdGluZywgZW50ZXJpbmcsIG9yIGNoYW5naW5nIGNvbnRleHRzLCBhbmQgY2FsbHMgdGhlCiAgICBwcm9wZXIgcm91dGUgaG9va3MuCiAgICAgICBGb3IgZXhhbXBsZSwgY29uc2lkZXIgdGhlIGZvbGxvd2luZyB0cmVlIG9mIHJvdXRlcy4gRWFjaCByb3V0ZSBpcwogICAgZm9sbG93ZWQgYnkgdGhlIFVSTCBzZWdtZW50IGl0IGhhbmRsZXMuCiAgICAgICBgYGAKICAgIHx+aW5kZXggKCIvIikKICAgIHwgfH5wb3N0cyAoIi9wb3N0cyIpCiAgICB8IHwgfC1zaG93UG9zdCAoIi86aWQiKQogICAgfCB8IHwtbmV3UG9zdCAoIi9uZXciKQogICAgfCB8IHwtZWRpdFBvc3QgKCIvZWRpdCIpCiAgICB8IHx+YWJvdXQgKCIvYWJvdXQvOmlkIikKICAgIGBgYAogICAgICAgQ29uc2lkZXIgdGhlIGZvbGxvd2luZyB0cmFuc2l0aW9uczoKICAgICAgIDEuIEEgVVJMIHRyYW5zaXRpb24gdG8gYC9wb3N0cy8xYC4KICAgICAgIDEuIFRyaWdnZXJzIHRoZSBgKm1vZGVsYCBjYWxsYmFja3Mgb24gdGhlCiAgICAgICAgICBgaW5kZXhgLCBgcG9zdHNgLCBhbmQgYHNob3dQb3N0YCByb3V0ZXMKICAgICAgIDIuIFRyaWdnZXJzIHRoZSBgZW50ZXJgIGNhbGxiYWNrIG9uIHRoZSBzYW1lCiAgICAgICAzLiBUcmlnZ2VycyB0aGUgYHNldHVwYCBjYWxsYmFjayBvbiB0aGUgc2FtZQogICAgMi4gQSBkaXJlY3QgdHJhbnNpdGlvbiB0byBgbmV3UG9zdGAKICAgICAgIDEuIFRyaWdnZXJzIHRoZSBgZXhpdGAgY2FsbGJhY2sgb24gYHNob3dQb3N0YAogICAgICAgMi4gVHJpZ2dlcnMgdGhlIGBlbnRlcmAgY2FsbGJhY2sgb24gYG5ld1Bvc3RgCiAgICAgICAzLiBUcmlnZ2VycyB0aGUgYHNldHVwYCBjYWxsYmFjayBvbiBgbmV3UG9zdGAKICAgIDMuIEEgZGlyZWN0IHRyYW5zaXRpb24gdG8gYGFib3V0YCB3aXRoIGEgc3BlY2lmaWVkCiAgICAgICBjb250ZXh0IG9iamVjdAogICAgICAgMS4gVHJpZ2dlcnMgdGhlIGBleGl0YCBjYWxsYmFjayBvbiBgbmV3UG9zdGAKICAgICAgICAgIGFuZCBgcG9zdHNgCiAgICAgICAyLiBUcmlnZ2VycyB0aGUgYHNlcmlhbGl6ZWAgY2FsbGJhY2sgb24gYGFib3V0YAogICAgICAgMy4gVHJpZ2dlcnMgdGhlIGBlbnRlcmAgY2FsbGJhY2sgb24gYGFib3V0YAogICAgICAgNC4gVHJpZ2dlcnMgdGhlIGBzZXR1cGAgY2FsbGJhY2sgb24gYGFib3V0YAogICAgICAgQHBhcmFtIHtSb3V0ZXJ9IHRyYW5zaXRpb24KICAgIEBwYXJhbSB7VHJhbnNpdGlvblN0YXRlfSBuZXdTdGF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG85LnNldHVwQ29udGV4dHMgPSBmdW5jdGlvbiBzZXR1cENvbnRleHRzKG5ld1N0YXRlLCB0cmFuc2l0aW9uKSB7CiAgICAgIHZhciBwYXJ0aXRpb24gPSB0aGlzLnBhcnRpdGlvblJvdXRlcyh0aGlzLnN0YXRlLCBuZXdTdGF0ZSk7CiAgICAgIHZhciBpLCBsLCByb3V0ZTsKCiAgICAgIGZvciAoaSA9IDAsIGwgPSBwYXJ0aXRpb24uZXhpdGVkLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICAgIHJvdXRlID0gcGFydGl0aW9uLmV4aXRlZFtpXS5yb3V0ZTsKICAgICAgICBkZWxldGUgcm91dGUuY29udGV4dDsKCiAgICAgICAgaWYgKHJvdXRlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGlmIChyb3V0ZS5faW50ZXJuYWxSZXNldCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHJvdXRlLl9pbnRlcm5hbFJlc2V0KHRydWUsIHRyYW5zaXRpb24pOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChyb3V0ZS5leGl0ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgcm91dGUuZXhpdCh0cmFuc2l0aW9uKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciBvbGRTdGF0ZSA9IHRoaXMub2xkU3RhdGUgPSB0aGlzLnN0YXRlOwogICAgICB0aGlzLnN0YXRlID0gbmV3U3RhdGU7CiAgICAgIHZhciBjdXJyZW50Um91dGVJbmZvcyA9IHRoaXMuY3VycmVudFJvdXRlSW5mb3MgPSBwYXJ0aXRpb24udW5jaGFuZ2VkLnNsaWNlKCk7CgogICAgICB0cnkgewogICAgICAgIGZvciAoaSA9IDAsIGwgPSBwYXJ0aXRpb24ucmVzZXQubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICByb3V0ZSA9IHBhcnRpdGlvbi5yZXNldFtpXS5yb3V0ZTsKCiAgICAgICAgICBpZiAocm91dGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBpZiAocm91dGUuX2ludGVybmFsUmVzZXQgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIHJvdXRlLl9pbnRlcm5hbFJlc2V0KGZhbHNlLCB0cmFuc2l0aW9uKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZm9yIChpID0gMCwgbCA9IHBhcnRpdGlvbi51cGRhdGVkQ29udGV4dC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgIHRoaXMucm91dGVFbnRlcmVkT3JVcGRhdGVkKGN1cnJlbnRSb3V0ZUluZm9zLCBwYXJ0aXRpb24udXBkYXRlZENvbnRleHRbaV0sIGZhbHNlLCB0cmFuc2l0aW9uKTsKICAgICAgICB9CgogICAgICAgIGZvciAoaSA9IDAsIGwgPSBwYXJ0aXRpb24uZW50ZXJlZC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgIHRoaXMucm91dGVFbnRlcmVkT3JVcGRhdGVkKGN1cnJlbnRSb3V0ZUluZm9zLCBwYXJ0aXRpb24uZW50ZXJlZFtpXSwgdHJ1ZSwgdHJhbnNpdGlvbik7CiAgICAgICAgfQogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgdGhpcy5zdGF0ZSA9IG9sZFN0YXRlOwogICAgICAgIHRoaXMuY3VycmVudFJvdXRlSW5mb3MgPSBvbGRTdGF0ZS5yb3V0ZUluZm9zOwogICAgICAgIHRocm93IGU7CiAgICAgIH0KCiAgICAgIHRoaXMuc3RhdGUucXVlcnlQYXJhbXMgPSB0aGlzLmZpbmFsaXplUXVlcnlQYXJhbUNoYW5nZShjdXJyZW50Um91dGVJbmZvcywgbmV3U3RhdGUucXVlcnlQYXJhbXMsIHRyYW5zaXRpb24pOwogICAgfQogICAgLyoqCiAgICBAcHJpdmF0ZQogICAgICAgRmlyZXMgcXVlcnlQYXJhbXNEaWRDaGFuZ2UgZXZlbnQKICAgICovCiAgICA7CgogICAgX3Byb3RvOS5maXJlUXVlcnlQYXJhbURpZENoYW5nZSA9IGZ1bmN0aW9uIGZpcmVRdWVyeVBhcmFtRGlkQ2hhbmdlKG5ld1N0YXRlLCBxdWVyeVBhcmFtQ2hhbmdlbGlzdCkgewogICAgICAvLyBJZiBxdWVyeVBhcmFtcyBjaGFuZ2VkIHRyaWdnZXIgZXZlbnQKICAgICAgaWYgKHF1ZXJ5UGFyYW1DaGFuZ2VsaXN0KSB7CiAgICAgICAgLy8gVGhpcyBpcyBhIGxpdHRsZSBoYWNreSBidXQgd2UgbmVlZCBzb21lIHdheSBvZiBzdG9yaW5nCiAgICAgICAgLy8gY2hhbmdlZCBxdWVyeSBwYXJhbXMgZ2l2ZW4gdGhhdCBubyBhY3RpdmVUcmFuc2l0aW9uCiAgICAgICAgLy8gaXMgZ3VhcmFudGVlZCB0byBoYXZlIG9jY3VycmVkLgogICAgICAgIHRoaXMuX2NoYW5nZWRRdWVyeVBhcmFtcyA9IHF1ZXJ5UGFyYW1DaGFuZ2VsaXN0LmFsbDsKICAgICAgICB0aGlzLnRyaWdnZXJFdmVudChuZXdTdGF0ZS5yb3V0ZUluZm9zLCB0cnVlLCAncXVlcnlQYXJhbXNEaWRDaGFuZ2UnLCBbcXVlcnlQYXJhbUNoYW5nZWxpc3QuY2hhbmdlZCwgcXVlcnlQYXJhbUNoYW5nZWxpc3QuYWxsLCBxdWVyeVBhcmFtQ2hhbmdlbGlzdC5yZW1vdmVkXSk7CiAgICAgICAgdGhpcy5fY2hhbmdlZFF1ZXJ5UGFyYW1zID0gdW5kZWZpbmVkOwogICAgICB9CiAgICB9CiAgICAvKioKICAgIEBwcml2YXRlCiAgICAgICBIZWxwZXIgbWV0aG9kIHVzZWQgYnkgc2V0dXBDb250ZXh0cy4gSGFuZGxlcyBlcnJvcnMgb3IgcmVkaXJlY3RzCiAgICB0aGF0IG1heSBoYXBwZW4gaW4gZW50ZXIvc2V0dXAuCiAgICAqLwogICAgOwoKICAgIF9wcm90bzkucm91dGVFbnRlcmVkT3JVcGRhdGVkID0gZnVuY3Rpb24gcm91dGVFbnRlcmVkT3JVcGRhdGVkKGN1cnJlbnRSb3V0ZUluZm9zLCByb3V0ZUluZm8sIGVudGVyLCB0cmFuc2l0aW9uKSB7CiAgICAgIHZhciByb3V0ZSA9IHJvdXRlSW5mby5yb3V0ZSwKICAgICAgICAgIGNvbnRleHQgPSByb3V0ZUluZm8uY29udGV4dDsKCiAgICAgIGZ1bmN0aW9uIF9yb3V0ZUVudGVyZWRPclVwZGF0ZWQocm91dGUpIHsKICAgICAgICBpZiAoZW50ZXIpIHsKICAgICAgICAgIGlmIChyb3V0ZS5lbnRlciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHJvdXRlLmVudGVyKHRyYW5zaXRpb24pOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKHRyYW5zaXRpb24gJiYgdHJhbnNpdGlvbi5pc0Fib3J0ZWQpIHsKICAgICAgICAgIHRocm93IG5ldyBUcmFuc2l0aW9uQWJvcnRlZEVycm9yKCk7CiAgICAgICAgfQoKICAgICAgICByb3V0ZS5jb250ZXh0ID0gY29udGV4dDsKCiAgICAgICAgaWYgKHJvdXRlLmNvbnRleHREaWRDaGFuZ2UgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcm91dGUuY29udGV4dERpZENoYW5nZSgpOwogICAgICAgIH0KCiAgICAgICAgaWYgKHJvdXRlLnNldHVwICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJvdXRlLnNldHVwKGNvbnRleHQsIHRyYW5zaXRpb24pOwogICAgICAgIH0KCiAgICAgICAgaWYgKHRyYW5zaXRpb24gJiYgdHJhbnNpdGlvbi5pc0Fib3J0ZWQpIHsKICAgICAgICAgIHRocm93IG5ldyBUcmFuc2l0aW9uQWJvcnRlZEVycm9yKCk7CiAgICAgICAgfQoKICAgICAgICBjdXJyZW50Um91dGVJbmZvcy5wdXNoKHJvdXRlSW5mbyk7CiAgICAgICAgcmV0dXJuIHJvdXRlOwogICAgICB9IC8vIElmIHRoZSByb3V0ZSBkb2Vzbid0IGV4aXN0LCBpdCBtZWFucyB3ZSBoYXZlbid0IHJlc29sdmVkIHRoZSByb3V0ZSBwcm9taXNlIHlldAoKCiAgICAgIGlmIChyb3V0ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcm91dGVJbmZvLnJvdXRlUHJvbWlzZSA9IHJvdXRlSW5mby5yb3V0ZVByb21pc2UudGhlbihfcm91dGVFbnRlcmVkT3JVcGRhdGVkKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBfcm91dGVFbnRlcmVkT3JVcGRhdGVkKHJvdXRlKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICAvKioKICAgIEBwcml2YXRlCiAgICAgICBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuIHRyYW5zaXRpb25pbmcgZnJvbSBvbmUgVVJMIHRvCiAgICBhbm90aGVyIHRvIGRldGVybWluZSB3aGljaCByb3V0ZXMgYXJlIG5vIGxvbmdlciBhY3RpdmUsCiAgICB3aGljaCByb3V0ZXMgYXJlIG5ld2x5IGFjdGl2ZSwgYW5kIHdoaWNoIHJvdXRlcyByZW1haW4KICAgIGFjdGl2ZSBidXQgaGF2ZSB0aGVpciBjb250ZXh0IGNoYW5nZWQuCiAgICAgICBUYWtlIGEgbGlzdCBvZiBvbGQgcm91dGVzIGFuZCBuZXcgcm91dGVzIGFuZCBwYXJ0aXRpb24KICAgIHRoZW0gaW50byBmb3VyIGJ1Y2tldHM6CiAgICAgICAqIHVuY2hhbmdlZDogdGhlIHJvdXRlIHdhcyBhY3RpdmUgaW4gYm90aCB0aGUgb2xkIGFuZAogICAgICBuZXcgVVJMLCBhbmQgaXRzIGNvbnRleHQgcmVtYWlucyB0aGUgc2FtZQogICAgKiB1cGRhdGVkIGNvbnRleHQ6IHRoZSByb3V0ZSB3YXMgYWN0aXZlIGluIGJvdGggdGhlCiAgICAgIG9sZCBhbmQgbmV3IFVSTCwgYnV0IGl0cyBjb250ZXh0IGNoYW5nZWQuIFRoZSByb3V0ZSdzCiAgICAgIGBzZXR1cGAgbWV0aG9kLCBpZiBhbnksIHdpbGwgYmUgY2FsbGVkIHdpdGggdGhlIG5ldwogICAgICBjb250ZXh0LgogICAgKiBleGl0ZWQ6IHRoZSByb3V0ZSB3YXMgYWN0aXZlIGluIHRoZSBvbGQgVVJMLCBidXQgaXMKICAgICAgbm8gbG9uZ2VyIGFjdGl2ZS4KICAgICogZW50ZXJlZDogdGhlIHJvdXRlIHdhcyBub3QgYWN0aXZlIGluIHRoZSBvbGQgVVJMLCBidXQKICAgICAgaXMgbm93IGFjdGl2ZS4KICAgICAgIFRoZSBQYXJ0aXRpb25lZFJvdXRlcyBzdHJ1Y3R1cmUgaGFzIGZvdXIgZmllbGRzOgogICAgICAgKiBgdXBkYXRlZENvbnRleHRgOiBhIGxpc3Qgb2YgYFJvdXRlSW5mb2Agb2JqZWN0cyB0aGF0CiAgICAgIHJlcHJlc2VudCByb3V0ZXMgdGhhdCByZW1haW4gYWN0aXZlIGJ1dCBoYXZlIGEgY2hhbmdlZAogICAgICBjb250ZXh0CiAgICAqIGBlbnRlcmVkYDogYSBsaXN0IG9mIGBSb3V0ZUluZm9gIG9iamVjdHMgdGhhdCByZXByZXNlbnQKICAgICAgcm91dGVzIHRoYXQgYXJlIG5ld2x5IGFjdGl2ZQogICAgKiBgZXhpdGVkYDogYSBsaXN0IG9mIGBSb3V0ZUluZm9gIG9iamVjdHMgdGhhdCBhcmUgbm8KICAgICAgbG9uZ2VyIGFjdGl2ZS4KICAgICogYHVuY2hhbmdlZGA6IGEgbGlzdCBvZiBgUm91dGVJbmZvYCBvYmplY3RzIHRoYXQgcmVtYWluIGFjdGl2ZS4KICAgICAgIEBwYXJhbSB7QXJyYXlbSW50ZXJuYWxSb3V0ZUluZm9dfSBvbGRSb3V0ZXMgYSBsaXN0IG9mIHRoZSByb3V0ZQogICAgICBpbmZvcm1hdGlvbiBmb3IgdGhlIHByZXZpb3VzIFVSTCAob3IgYFtdYCBpZiB0aGlzIGlzIHRoZQogICAgICBmaXJzdCBoYW5kbGVkIHRyYW5zaXRpb24pCiAgICBAcGFyYW0ge0FycmF5W0ludGVybmFsUm91dGVJbmZvXX0gbmV3Um91dGVzIGEgbGlzdCBvZiB0aGUgcm91dGUKICAgICAgaW5mb3JtYXRpb24gZm9yIHRoZSBuZXcgVVJMCiAgICAgICBAcmV0dXJuIHtQYXJ0aXRpb259CiAgICAqLwogICAgOwoKICAgIF9wcm90bzkucGFydGl0aW9uUm91dGVzID0gZnVuY3Rpb24gcGFydGl0aW9uUm91dGVzKG9sZFN0YXRlLCBuZXdTdGF0ZSkgewogICAgICB2YXIgb2xkUm91dGVJbmZvcyA9IG9sZFN0YXRlLnJvdXRlSW5mb3M7CiAgICAgIHZhciBuZXdSb3V0ZUluZm9zID0gbmV3U3RhdGUucm91dGVJbmZvczsKICAgICAgdmFyIHJvdXRlcyA9IHsKICAgICAgICB1cGRhdGVkQ29udGV4dDogW10sCiAgICAgICAgZXhpdGVkOiBbXSwKICAgICAgICBlbnRlcmVkOiBbXSwKICAgICAgICB1bmNoYW5nZWQ6IFtdLAogICAgICAgIHJlc2V0OiBbXQogICAgICB9OwogICAgICB2YXIgcm91dGVDaGFuZ2VkLAogICAgICAgICAgY29udGV4dENoYW5nZWQgPSBmYWxzZSwKICAgICAgICAgIGksCiAgICAgICAgICBsOwoKICAgICAgZm9yIChpID0gMCwgbCA9IG5ld1JvdXRlSW5mb3MubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgdmFyIG9sZFJvdXRlSW5mbyA9IG9sZFJvdXRlSW5mb3NbaV0sCiAgICAgICAgICAgIG5ld1JvdXRlSW5mbyA9IG5ld1JvdXRlSW5mb3NbaV07CgogICAgICAgIGlmICghb2xkUm91dGVJbmZvIHx8IG9sZFJvdXRlSW5mby5yb3V0ZSAhPT0gbmV3Um91dGVJbmZvLnJvdXRlKSB7CiAgICAgICAgICByb3V0ZUNoYW5nZWQgPSB0cnVlOwogICAgICAgIH0KCiAgICAgICAgaWYgKHJvdXRlQ2hhbmdlZCkgewogICAgICAgICAgcm91dGVzLmVudGVyZWQucHVzaChuZXdSb3V0ZUluZm8pOwoKICAgICAgICAgIGlmIChvbGRSb3V0ZUluZm8pIHsKICAgICAgICAgICAgcm91dGVzLmV4aXRlZC51bnNoaWZ0KG9sZFJvdXRlSW5mbyk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjb250ZXh0Q2hhbmdlZCB8fCBvbGRSb3V0ZUluZm8uY29udGV4dCAhPT0gbmV3Um91dGVJbmZvLmNvbnRleHQpIHsKICAgICAgICAgIGNvbnRleHRDaGFuZ2VkID0gdHJ1ZTsKICAgICAgICAgIHJvdXRlcy51cGRhdGVkQ29udGV4dC5wdXNoKG5ld1JvdXRlSW5mbyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJvdXRlcy51bmNoYW5nZWQucHVzaChvbGRSb3V0ZUluZm8pOwogICAgICAgIH0KICAgICAgfQoKICAgICAgZm9yIChpID0gbmV3Um91dGVJbmZvcy5sZW5ndGgsIGwgPSBvbGRSb3V0ZUluZm9zLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICAgIHJvdXRlcy5leGl0ZWQudW5zaGlmdChvbGRSb3V0ZUluZm9zW2ldKTsKICAgICAgfQoKICAgICAgcm91dGVzLnJlc2V0ID0gcm91dGVzLnVwZGF0ZWRDb250ZXh0LnNsaWNlKCk7CiAgICAgIHJvdXRlcy5yZXNldC5yZXZlcnNlKCk7CiAgICAgIHJldHVybiByb3V0ZXM7CiAgICB9OwoKICAgIF9wcm90bzkuX3VwZGF0ZVVSTCA9IGZ1bmN0aW9uIF91cGRhdGVVUkwodHJhbnNpdGlvbiwgc3RhdGUpIHsKICAgICAgdmFyIHVybE1ldGhvZCA9IHRyYW5zaXRpb24udXJsTWV0aG9kOwoKICAgICAgaWYgKCF1cmxNZXRob2QpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciByb3V0ZUluZm9zID0gc3RhdGUucm91dGVJbmZvczsKICAgICAgdmFyIHJvdXRlTmFtZSA9IHJvdXRlSW5mb3Nbcm91dGVJbmZvcy5sZW5ndGggLSAxXS5uYW1lOwogICAgICB2YXIgcGFyYW1zID0ge307CgogICAgICBmb3IgKHZhciBpID0gcm91dGVJbmZvcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgewogICAgICAgIHZhciByb3V0ZUluZm8gPSByb3V0ZUluZm9zW2ldOwogICAgICAgIG1lcmdlKHBhcmFtcywgcm91dGVJbmZvLnBhcmFtcyk7CgogICAgICAgIGlmIChyb3V0ZUluZm8ucm91dGUuaW5hY2Nlc3NpYmxlQnlVUkwpIHsKICAgICAgICAgIHVybE1ldGhvZCA9IG51bGw7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAodXJsTWV0aG9kKSB7CiAgICAgICAgcGFyYW1zLnF1ZXJ5UGFyYW1zID0gdHJhbnNpdGlvbi5fdmlzaWJsZVF1ZXJ5UGFyYW1zIHx8IHN0YXRlLnF1ZXJ5UGFyYW1zOwogICAgICAgIHZhciB1cmwgPSB0aGlzLnJlY29nbml6ZXIuZ2VuZXJhdGUocm91dGVOYW1lLCBwYXJhbXMpOyAvLyB0cmFuc2l0aW9ucyBkdXJpbmcgdGhlIGluaXRpYWwgdHJhbnNpdGlvbiBtdXN0IGFsd2F5cyB1c2UgcmVwbGFjZVVSTC4KICAgICAgICAvLyBXaGVuIHRoZSBhcHAgYm9vdHMsIHlvdSBhcmUgYXQgYSB1cmwsIGUuZy4gL2Zvby4gSWYgc29tZSByb3V0ZQogICAgICAgIC8vIHJlZGlyZWN0cyB0byBiYXIgYXMgcGFydCBvZiB0aGUgaW5pdGlhbCB0cmFuc2l0aW9uLCB5b3UgZG9uJ3Qgd2FudCB0bwogICAgICAgIC8vIGFkZCBhIGhpc3RvcnkgZW50cnkgZm9yIC9mb28uIElmIHlvdSBkbywgcHJlc3NpbmcgYmFjayB3aWxsIGltbWVkaWF0ZWx5CiAgICAgICAgLy8gaGl0IHRoZSByZWRpcmVjdCBhZ2FpbiBhbmQgdGFrZSB5b3UgYmFjayB0byAvYmFyLCB0aHVzIGtpbGxpbmcgdGhlIGJhY2sKICAgICAgICAvLyBidXR0b24KCiAgICAgICAgdmFyIGluaXRpYWwgPSB0cmFuc2l0aW9uLmlzQ2F1c2VkQnlJbml0aWFsVHJhbnNpdGlvbjsgLy8gc2F5IHlvdSBhcmUgYXQgLyBhbmQgeW91IGNsaWNrIGEgbGluayB0byByb3V0ZSAvZm9vLiBJbiAvZm9vJ3MKICAgICAgICAvLyByb3V0ZSwgdGhlIHRyYW5zaXRpb24gaXMgYWJvcnRlZCB1c2luZyByZXBsYWNld2l0aCgnL2JhcicpLgogICAgICAgIC8vIEJlY2F1c2UgdGhlIGN1cnJlbnQgdXJsIGlzIHN0aWxsIC8sIHRoZSBoaXN0b3J5IGVudHJ5IGZvciAvIGlzCiAgICAgICAgLy8gcmVtb3ZlZCBmcm9tIHRoZSBoaXN0b3J5LiBDbGlja2luZyBiYWNrIHdpbGwgdGFrZSB5b3UgdG8gdGhlIHBhZ2UKICAgICAgICAvLyB5b3Ugd2VyZSBvbiBiZWZvcmUgLywgd2hpY2ggaXMgb2Z0ZW4gbm90IGV2ZW4gdGhlIGFwcCwgdGh1cyBraWxsaW5nCiAgICAgICAgLy8gdGhlIGJhY2sgYnV0dG9uLiBUaGF0J3Mgd2h5IHVwZGF0ZVVSTCBpcyBhbHdheXMgY29ycmVjdCBmb3IgYW4KICAgICAgICAvLyBhYm9ydGluZyB0cmFuc2l0aW9uIHRoYXQncyBub3QgdGhlIGluaXRpYWwgdHJhbnNpdGlvbgoKICAgICAgICB2YXIgcmVwbGFjZUFuZE5vdEFib3J0aW5nID0gdXJsTWV0aG9kID09PSAncmVwbGFjZScgJiYgIXRyYW5zaXRpb24uaXNDYXVzZWRCeUFib3J0aW5nVHJhbnNpdGlvbjsgLy8gYmVjYXVzZSBjYWxsaW5nIHJlZnJlc2ggY2F1c2VzIGFuIGFib3J0ZWQgdHJhbnNpdGlvbiwgdGhpcyBuZWVkcyB0byBiZQogICAgICAgIC8vIHNwZWNpYWwgY2FzZWQgLSBpZiB0aGUgaW5pdGlhbCB0cmFuc2l0aW9uIGlzIGEgcmVwbGFjZSB0cmFuc2l0aW9uLCB0aGUKICAgICAgICAvLyB1cmxNZXRob2Qgc2hvdWxkIGJlIGhvbm9yZWQgaGVyZS4KCiAgICAgICAgdmFyIGlzUXVlcnlQYXJhbXNSZWZyZXNoVHJhbnNpdGlvbiA9IHRyYW5zaXRpb24ucXVlcnlQYXJhbXNPbmx5ICYmIHVybE1ldGhvZCA9PT0gJ3JlcGxhY2UnOyAvLyBzYXkgeW91IGFyZSBhdCAvIGFuZCB5b3UgYSBgcmVwbGFjZVdpdGgoL2ZvbylgIGlzIGNhbGxlZC4gVGhlbiwgdGhhdAogICAgICAgIC8vIHRyYW5zaXRpb24gaXMgYWJvcnRlZCB3aXRoIGByZXBsYWNlV2l0aCgvYmFyKWAuIEF0IHRoZSBlbmQsIHdlIHNob3VsZAogICAgICAgIC8vIGVuZCB1cCB3aXRoIC9iYXIgcmVwbGFjaW5nIC8uIFdlIGFyZSByZXBsYWNpbmcgdGhlIHJlcGxhY2UuIFdlIG9ubHkKICAgICAgICAvLyB3aWxsIHJlcGxhY2UgdGhlIGluaXRpYWwgcm91dGUgaWYgYWxsIHN1YnNlcXVlbnQgYWJvcnRzIGFyZSBhbHNvCiAgICAgICAgLy8gcmVwbGFjZXMuIEhvd2V2ZXIsIHRoZXJlIGlzIHNvbWUgYW1iaWd1aXR5IGFyb3VuZCB0aGUgY29ycmVjdCBiZWhhdmlvcgogICAgICAgIC8vIGhlcmUuCgogICAgICAgIHZhciByZXBsYWNpbmdSZXBsYWNlID0gdXJsTWV0aG9kID09PSAncmVwbGFjZScgJiYgdHJhbnNpdGlvbi5pc0NhdXNlZEJ5QWJvcnRpbmdSZXBsYWNlVHJhbnNpdGlvbjsKCiAgICAgICAgaWYgKGluaXRpYWwgfHwgcmVwbGFjZUFuZE5vdEFib3J0aW5nIHx8IGlzUXVlcnlQYXJhbXNSZWZyZXNoVHJhbnNpdGlvbiB8fCByZXBsYWNpbmdSZXBsYWNlKSB7CiAgICAgICAgICB0aGlzLnJlcGxhY2VVUkwodXJsKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhpcy51cGRhdGVVUkwodXJsKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvOS5maW5hbGl6ZVF1ZXJ5UGFyYW1DaGFuZ2UgPSBmdW5jdGlvbiBmaW5hbGl6ZVF1ZXJ5UGFyYW1DaGFuZ2UocmVzb2x2ZWRIYW5kbGVycywgbmV3UXVlcnlQYXJhbXMsIHRyYW5zaXRpb24pIHsKICAgICAgLy8gV2UgZmlyZSBhIGZpbmFsaXplUXVlcnlQYXJhbUNoYW5nZSBldmVudCB3aGljaAogICAgICAvLyBnaXZlcyB0aGUgbmV3IHJvdXRlIGhpZXJhcmNoeSBhIGNoYW5jZSB0byB0ZWxsCiAgICAgIC8vIHVzIHdoaWNoIHF1ZXJ5IHBhcmFtcyBpdCdzIGNvbnN1bWluZyBhbmQgd2hhdAogICAgICAvLyB0aGVpciBmaW5hbCB2YWx1ZXMgYXJlLiBJZiBhIHF1ZXJ5IHBhcmFtIGlzCiAgICAgIC8vIG5vIGxvbmdlciBjb25zdW1lZCBpbiB0aGUgZmluYWwgcm91dGUgaGllcmFyY2h5LAogICAgICAvLyBpdHMgc2VyaWFsaXplZCBzZWdtZW50IHdpbGwgYmUgcmVtb3ZlZAogICAgICAvLyBmcm9tIHRoZSBVUkwuCiAgICAgIGZvciAodmFyIGsgaW4gbmV3UXVlcnlQYXJhbXMpIHsKICAgICAgICBpZiAobmV3UXVlcnlQYXJhbXMuaGFzT3duUHJvcGVydHkoaykgJiYgbmV3UXVlcnlQYXJhbXNba10gPT09IG51bGwpIHsKICAgICAgICAgIGRlbGV0ZSBuZXdRdWVyeVBhcmFtc1trXTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciBmaW5hbFF1ZXJ5UGFyYW1zQXJyYXkgPSBbXTsKICAgICAgdGhpcy50cmlnZ2VyRXZlbnQocmVzb2x2ZWRIYW5kbGVycywgdHJ1ZSwgJ2ZpbmFsaXplUXVlcnlQYXJhbUNoYW5nZScsIFtuZXdRdWVyeVBhcmFtcywgZmluYWxRdWVyeVBhcmFtc0FycmF5LCB0cmFuc2l0aW9uXSk7CgogICAgICBpZiAodHJhbnNpdGlvbikgewogICAgICAgIHRyYW5zaXRpb24uX3Zpc2libGVRdWVyeVBhcmFtcyA9IHt9OwogICAgICB9CgogICAgICB2YXIgZmluYWxRdWVyeVBhcmFtcyA9IHt9OwoKICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGZpbmFsUXVlcnlQYXJhbXNBcnJheS5sZW5ndGg7IGkgPCBsZW47ICsraSkgewogICAgICAgIHZhciBxcCA9IGZpbmFsUXVlcnlQYXJhbXNBcnJheVtpXTsKICAgICAgICBmaW5hbFF1ZXJ5UGFyYW1zW3FwLmtleV0gPSBxcC52YWx1ZTsKCiAgICAgICAgaWYgKHRyYW5zaXRpb24gJiYgcXAudmlzaWJsZSAhPT0gZmFsc2UpIHsKICAgICAgICAgIHRyYW5zaXRpb24uX3Zpc2libGVRdWVyeVBhcmFtc1txcC5rZXldID0gcXAudmFsdWU7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gZmluYWxRdWVyeVBhcmFtczsKICAgIH07CgogICAgX3Byb3RvOS50b1JlYWRPbmx5SW5mb3MgPSBmdW5jdGlvbiB0b1JlYWRPbmx5SW5mb3MobmV3VHJhbnNpdGlvbiwgbmV3U3RhdGUpIHsKICAgICAgdmFyIG9sZFJvdXRlSW5mb3MgPSB0aGlzLnN0YXRlLnJvdXRlSW5mb3M7CiAgICAgIHRoaXMuZnJvbUluZm9zKG5ld1RyYW5zaXRpb24sIG9sZFJvdXRlSW5mb3MpOwogICAgICB0aGlzLnRvSW5mb3MobmV3VHJhbnNpdGlvbiwgbmV3U3RhdGUucm91dGVJbmZvcyk7CiAgICAgIHRoaXMuX2xhc3RRdWVyeVBhcmFtcyA9IG5ld1N0YXRlLnF1ZXJ5UGFyYW1zOwogICAgfTsKCiAgICBfcHJvdG85LmZyb21JbmZvcyA9IGZ1bmN0aW9uIGZyb21JbmZvcyhuZXdUcmFuc2l0aW9uLCBvbGRSb3V0ZUluZm9zKSB7CiAgICAgIGlmIChuZXdUcmFuc2l0aW9uICE9PSB1bmRlZmluZWQgJiYgb2xkUm91dGVJbmZvcy5sZW5ndGggPiAwKSB7CiAgICAgICAgdmFyIGZyb21JbmZvcyA9IHRvUmVhZE9ubHlSb3V0ZUluZm8ob2xkUm91dGVJbmZvcywgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgdGhpcy5fbGFzdFF1ZXJ5UGFyYW1zKSwgdHJ1ZSk7CiAgICAgICAgbmV3VHJhbnNpdGlvbi5mcm9tID0gZnJvbUluZm9zW2Zyb21JbmZvcy5sZW5ndGggLSAxXSB8fCBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzkudG9JbmZvcyA9IGZ1bmN0aW9uIHRvSW5mb3MobmV3VHJhbnNpdGlvbiwgbmV3Um91dGVJbmZvcywgaW5jbHVkZUF0dHJpYnV0ZXMpIHsKICAgICAgaWYgKGluY2x1ZGVBdHRyaWJ1dGVzID09PSB2b2lkIDApIHsKICAgICAgICBpbmNsdWRlQXR0cmlidXRlcyA9IGZhbHNlOwogICAgICB9CgogICAgICBpZiAobmV3VHJhbnNpdGlvbiAhPT0gdW5kZWZpbmVkICYmIG5ld1JvdXRlSW5mb3MubGVuZ3RoID4gMCkgewogICAgICAgIHZhciB0b0luZm9zID0gdG9SZWFkT25seVJvdXRlSW5mbyhuZXdSb3V0ZUluZm9zLCAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBuZXdUcmFuc2l0aW9uW1FVRVJZX1BBUkFNU19TWU1CT0xdKSwgaW5jbHVkZUF0dHJpYnV0ZXMpOwogICAgICAgIG5ld1RyYW5zaXRpb24udG8gPSB0b0luZm9zW3RvSW5mb3MubGVuZ3RoIC0gMV0gfHwgbnVsbDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG85Lm5vdGlmeUV4aXN0aW5nSGFuZGxlcnMgPSBmdW5jdGlvbiBub3RpZnlFeGlzdGluZ0hhbmRsZXJzKG5ld1N0YXRlLCBuZXdUcmFuc2l0aW9uKSB7CiAgICAgIHZhciBvbGRSb3V0ZUluZm9zID0gdGhpcy5zdGF0ZS5yb3V0ZUluZm9zLAogICAgICAgICAgaSwKICAgICAgICAgIG9sZFJvdXRlSW5mb0xlbiwKICAgICAgICAgIG9sZEhhbmRsZXIsCiAgICAgICAgICBuZXdSb3V0ZUluZm87CiAgICAgIG9sZFJvdXRlSW5mb0xlbiA9IG9sZFJvdXRlSW5mb3MubGVuZ3RoOwoKICAgICAgZm9yIChpID0gMDsgaSA8IG9sZFJvdXRlSW5mb0xlbjsgaSsrKSB7CiAgICAgICAgb2xkSGFuZGxlciA9IG9sZFJvdXRlSW5mb3NbaV07CiAgICAgICAgbmV3Um91dGVJbmZvID0gbmV3U3RhdGUucm91dGVJbmZvc1tpXTsKCiAgICAgICAgaWYgKCFuZXdSb3V0ZUluZm8gfHwgb2xkSGFuZGxlci5uYW1lICE9PSBuZXdSb3V0ZUluZm8ubmFtZSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICBpZiAoIW5ld1JvdXRlSW5mby5pc1Jlc29sdmVkKSB7fQogICAgICB9CgogICAgICB0aGlzLnRyaWdnZXJFdmVudChvbGRSb3V0ZUluZm9zLCB0cnVlLCAnd2lsbFRyYW5zaXRpb24nLCBbbmV3VHJhbnNpdGlvbl0pOwogICAgICB0aGlzLnJvdXRlV2lsbENoYW5nZShuZXdUcmFuc2l0aW9uKTsKICAgICAgdGhpcy53aWxsVHJhbnNpdGlvbihvbGRSb3V0ZUluZm9zLCBuZXdTdGF0ZS5yb3V0ZUluZm9zLCBuZXdUcmFuc2l0aW9uKTsKICAgIH0KICAgIC8qKgogICAgICBDbGVhcnMgdGhlIGN1cnJlbnQgYW5kIHRhcmdldCByb3V0ZSByb3V0ZXMgYW5kIHRyaWdnZXJzIGV4aXQKICAgICAgb24gZWFjaCBvZiB0aGVtIHN0YXJ0aW5nIGF0IHRoZSBsZWFmIGFuZCB0cmF2ZXJzaW5nIHVwIHRocm91Z2gKICAgICAgaXRzIGFuY2VzdG9ycy4KICAgICovCiAgICA7CgogICAgX3Byb3RvOS5yZXNldCA9IGZ1bmN0aW9uIHJlc2V0KCkgewogICAgICBpZiAodGhpcy5zdGF0ZSkgewogICAgICAgIGZvckVhY2godGhpcy5zdGF0ZS5yb3V0ZUluZm9zLnNsaWNlKCkucmV2ZXJzZSgpLCBmdW5jdGlvbiAocm91dGVJbmZvKSB7CiAgICAgICAgICB2YXIgcm91dGUgPSByb3V0ZUluZm8ucm91dGU7CgogICAgICAgICAgaWYgKHJvdXRlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgaWYgKHJvdXRlLmV4aXQgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIHJvdXRlLmV4aXQoKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0pOwogICAgICB9CgogICAgICB0aGlzLm9sZFN0YXRlID0gdW5kZWZpbmVkOwogICAgICB0aGlzLnN0YXRlID0gbmV3IFRyYW5zaXRpb25TdGF0ZSgpOwogICAgICB0aGlzLmN1cnJlbnRSb3V0ZUluZm9zID0gdW5kZWZpbmVkOwogICAgfQogICAgLyoqCiAgICAgIGxldCBoYW5kbGVyID0gcm91dGVJbmZvLmhhbmRsZXI7CiAgICAgIFRoZSBlbnRyeSBwb2ludCBmb3IgaGFuZGxpbmcgYSBjaGFuZ2UgdG8gdGhlIFVSTCAodXN1YWxseQogICAgICB2aWEgdGhlIGJhY2sgYW5kIGZvcndhcmQgYnV0dG9uKS4KICAgICAgICAgUmV0dXJucyBhbiBBcnJheSBvZiBoYW5kbGVycyBhbmQgdGhlIHBhcmFtZXRlcnMgYXNzb2NpYXRlZAogICAgICB3aXRoIHRob3NlIHBhcmFtZXRlcnMuCiAgICAgICAgIEBwYXJhbSB7U3RyaW5nfSB1cmwgYSBVUkwgdG8gcHJvY2VzcwogICAgICAgICBAcmV0dXJuIHtBcnJheX0gYW4gQXJyYXkgb2YgYFtoYW5kbGVyLCBwYXJhbWV0ZXJdYCB0dXBsZXMKICAgICovCiAgICA7CgogICAgX3Byb3RvOS5oYW5kbGVVUkwgPSBmdW5jdGlvbiBoYW5kbGVVUkwodXJsKSB7CiAgICAgIC8vIFBlcmZvcm0gYSBVUkwtYmFzZWQgdHJhbnNpdGlvbiwgYnV0IGRvbid0IGNoYW5nZQogICAgICAvLyB0aGUgVVJMIGFmdGVyd2FyZCwgc2luY2UgaXQgYWxyZWFkeSBoYXBwZW5lZC4KICAgICAgaWYgKHVybC5jaGFyQXQoMCkgIT09ICcvJykgewogICAgICAgIHVybCA9ICcvJyArIHVybDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuZG9UcmFuc2l0aW9uKHVybCkubWV0aG9kKG51bGwpOwogICAgfQogICAgLyoqCiAgICAgIFRyYW5zaXRpb24gaW50byB0aGUgc3BlY2lmaWVkIG5hbWVkIHJvdXRlLgogICAgICAgICBJZiBuZWNlc3NhcnksIHRyaWdnZXIgdGhlIGV4aXQgY2FsbGJhY2sgb24gYW55IHJvdXRlcwogICAgICB0aGF0IGFyZSBubyBsb25nZXIgcmVwcmVzZW50ZWQgYnkgdGhlIHRhcmdldCByb3V0ZS4KICAgICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIHJvdXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90bzkudHJhbnNpdGlvblRvID0gZnVuY3Rpb24gdHJhbnNpdGlvblRvKG5hbWUpIHsKICAgICAgZm9yICh2YXIgX2xlbjMgPSBhcmd1bWVudHMubGVuZ3RoLCBjb250ZXh0cyA9IG5ldyBBcnJheShfbGVuMyA+IDEgPyBfbGVuMyAtIDEgOiAwKSwgX2tleTMgPSAxOyBfa2V5MyA8IF9sZW4zOyBfa2V5MysrKSB7CiAgICAgICAgY29udGV4dHNbX2tleTMgLSAxXSA9IGFyZ3VtZW50c1tfa2V5M107CiAgICAgIH0KCiAgICAgIGlmICh0eXBlb2YgbmFtZSA9PT0gJ29iamVjdCcpIHsKICAgICAgICBjb250ZXh0cy5wdXNoKG5hbWUpOwogICAgICAgIHJldHVybiB0aGlzLmRvVHJhbnNpdGlvbih1bmRlZmluZWQsIGNvbnRleHRzLCBmYWxzZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLmRvVHJhbnNpdGlvbihuYW1lLCBjb250ZXh0cyk7CiAgICB9OwoKICAgIF9wcm90bzkuaW50ZXJtZWRpYXRlVHJhbnNpdGlvblRvID0gZnVuY3Rpb24gaW50ZXJtZWRpYXRlVHJhbnNpdGlvblRvKG5hbWUpIHsKICAgICAgZm9yICh2YXIgX2xlbjQgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW40ID4gMSA/IF9sZW40IC0gMSA6IDApLCBfa2V5NCA9IDE7IF9rZXk0IDwgX2xlbjQ7IF9rZXk0KyspIHsKICAgICAgICBhcmdzW19rZXk0IC0gMV0gPSBhcmd1bWVudHNbX2tleTRdOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5kb1RyYW5zaXRpb24obmFtZSwgYXJncywgdHJ1ZSk7CiAgICB9OwoKICAgIF9wcm90bzkucmVmcmVzaCA9IGZ1bmN0aW9uIHJlZnJlc2gocGl2b3RSb3V0ZSkgewogICAgICB2YXIgcHJldmlvdXNUcmFuc2l0aW9uID0gdGhpcy5hY3RpdmVUcmFuc2l0aW9uOwogICAgICB2YXIgc3RhdGUgPSBwcmV2aW91c1RyYW5zaXRpb24gPyBwcmV2aW91c1RyYW5zaXRpb25bU1RBVEVfU1lNQk9MXSA6IHRoaXMuc3RhdGU7CiAgICAgIHZhciByb3V0ZUluZm9zID0gc3RhdGUucm91dGVJbmZvczsKCiAgICAgIGlmIChwaXZvdFJvdXRlID09PSB1bmRlZmluZWQpIHsKICAgICAgICBwaXZvdFJvdXRlID0gcm91dGVJbmZvc1swXS5yb3V0ZTsKICAgICAgfQoKICAgICAgX2xvZyh0aGlzLCAnU3RhcnRpbmcgYSByZWZyZXNoIHRyYW5zaXRpb24nKTsKCiAgICAgIHZhciBuYW1lID0gcm91dGVJbmZvc1tyb3V0ZUluZm9zLmxlbmd0aCAtIDFdLm5hbWU7CiAgICAgIHZhciBpbnRlbnQgPSBuZXcgTmFtZWRUcmFuc2l0aW9uSW50ZW50KHRoaXMsIG5hbWUsIHBpdm90Um91dGUsIFtdLCB0aGlzLl9jaGFuZ2VkUXVlcnlQYXJhbXMgfHwgc3RhdGUucXVlcnlQYXJhbXMpOwogICAgICB2YXIgbmV3VHJhbnNpdGlvbiA9IHRoaXMudHJhbnNpdGlvbkJ5SW50ZW50KGludGVudCwgZmFsc2UpOyAvLyBpZiB0aGUgcHJldmlvdXMgdHJhbnNpdGlvbiBpcyBhIHJlcGxhY2UgdHJhbnNpdGlvbiwgdGhhdCBuZWVkcyB0byBiZSBwcmVzZXJ2ZWQKCiAgICAgIGlmIChwcmV2aW91c1RyYW5zaXRpb24gJiYgcHJldmlvdXNUcmFuc2l0aW9uLnVybE1ldGhvZCA9PT0gJ3JlcGxhY2UnKSB7CiAgICAgICAgbmV3VHJhbnNpdGlvbi5tZXRob2QocHJldmlvdXNUcmFuc2l0aW9uLnVybE1ldGhvZCk7CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXdUcmFuc2l0aW9uOwogICAgfQogICAgLyoqCiAgICAgIElkZW50aWNhbCB0byBgdHJhbnNpdGlvblRvYCBleGNlcHQgdGhhdCB0aGUgY3VycmVudCBVUkwgd2lsbCBiZSByZXBsYWNlZAogICAgICBpZiBwb3NzaWJsZS4KICAgICAgICAgVGhpcyBtZXRob2QgaXMgaW50ZW5kZWQgcHJpbWFyaWx5IGZvciB1c2Ugd2l0aCBgcmVwbGFjZVN0YXRlYC4KICAgICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIHJvdXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90bzkucmVwbGFjZVdpdGggPSBmdW5jdGlvbiByZXBsYWNlV2l0aChuYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLmRvVHJhbnNpdGlvbihuYW1lKS5tZXRob2QoJ3JlcGxhY2UnKTsKICAgIH0KICAgIC8qKgogICAgICBUYWtlIGEgbmFtZWQgcm91dGUgYW5kIGNvbnRleHQgb2JqZWN0cyBhbmQgZ2VuZXJhdGUgYQogICAgICBVUkwuCiAgICAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZSB0byBnZW5lcmF0ZQogICAgICAgIGEgVVJMIGZvcgogICAgICBAcGFyYW0gey4uLk9iamVjdH0gb2JqZWN0cyBhIGxpc3Qgb2Ygb2JqZWN0cyB0byBzZXJpYWxpemUKICAgICAgICAgQHJldHVybiB7U3RyaW5nfSBhIFVSTAogICAgKi8KICAgIDsKCiAgICBfcHJvdG85LmdlbmVyYXRlID0gZnVuY3Rpb24gZ2VuZXJhdGUocm91dGVOYW1lKSB7CiAgICAgIGZvciAodmFyIF9sZW41ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuNSA+IDEgPyBfbGVuNSAtIDEgOiAwKSwgX2tleTUgPSAxOyBfa2V5NSA8IF9sZW41OyBfa2V5NSsrKSB7CiAgICAgICAgYXJnc1tfa2V5NSAtIDFdID0gYXJndW1lbnRzW19rZXk1XTsKICAgICAgfQoKICAgICAgdmFyIHBhcnRpdGlvbmVkQXJncyA9IGV4dHJhY3RRdWVyeVBhcmFtcyhhcmdzKSwKICAgICAgICAgIHN1cHBsaWVkUGFyYW1zID0gcGFydGl0aW9uZWRBcmdzWzBdLAogICAgICAgICAgcXVlcnlQYXJhbXMgPSBwYXJ0aXRpb25lZEFyZ3NbMV07IC8vIENvbnN0cnVjdCBhIFRyYW5zaXRpb25JbnRlbnQgd2l0aCB0aGUgcHJvdmlkZWQgcGFyYW1zCiAgICAgIC8vIGFuZCBhcHBseSBpdCB0byB0aGUgcHJlc2VudCBzdGF0ZSBvZiB0aGUgcm91dGVyLgoKICAgICAgdmFyIGludGVudCA9IG5ldyBOYW1lZFRyYW5zaXRpb25JbnRlbnQodGhpcywgcm91dGVOYW1lLCB1bmRlZmluZWQsIHN1cHBsaWVkUGFyYW1zKTsKICAgICAgdmFyIHN0YXRlID0gaW50ZW50LmFwcGx5VG9TdGF0ZSh0aGlzLnN0YXRlLCBmYWxzZSk7CiAgICAgIHZhciBwYXJhbXMgPSB7fTsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBzdGF0ZS5yb3V0ZUluZm9zLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgICAgdmFyIHJvdXRlSW5mbyA9IHN0YXRlLnJvdXRlSW5mb3NbaV07CiAgICAgICAgdmFyIHJvdXRlUGFyYW1zID0gcm91dGVJbmZvLnNlcmlhbGl6ZSgpOwogICAgICAgIG1lcmdlKHBhcmFtcywgcm91dGVQYXJhbXMpOwogICAgICB9CgogICAgICBwYXJhbXMucXVlcnlQYXJhbXMgPSBxdWVyeVBhcmFtczsKICAgICAgcmV0dXJuIHRoaXMucmVjb2duaXplci5nZW5lcmF0ZShyb3V0ZU5hbWUsIHBhcmFtcyk7CiAgICB9OwoKICAgIF9wcm90bzkuYXBwbHlJbnRlbnQgPSBmdW5jdGlvbiBhcHBseUludGVudChyb3V0ZU5hbWUsIGNvbnRleHRzKSB7CiAgICAgIHZhciBpbnRlbnQgPSBuZXcgTmFtZWRUcmFuc2l0aW9uSW50ZW50KHRoaXMsIHJvdXRlTmFtZSwgdW5kZWZpbmVkLCBjb250ZXh0cyk7CiAgICAgIHZhciBzdGF0ZSA9IHRoaXMuYWN0aXZlVHJhbnNpdGlvbiAmJiB0aGlzLmFjdGl2ZVRyYW5zaXRpb25bU1RBVEVfU1lNQk9MXSB8fCB0aGlzLnN0YXRlOwogICAgICByZXR1cm4gaW50ZW50LmFwcGx5VG9TdGF0ZShzdGF0ZSwgZmFsc2UpOwogICAgfTsKCiAgICBfcHJvdG85LmlzQWN0aXZlSW50ZW50ID0gZnVuY3Rpb24gaXNBY3RpdmVJbnRlbnQocm91dGVOYW1lLCBjb250ZXh0cywgcXVlcnlQYXJhbXMsIF9zdGF0ZSkgewogICAgICB2YXIgc3RhdGUgPSBfc3RhdGUgfHwgdGhpcy5zdGF0ZSwKICAgICAgICAgIHRhcmdldFJvdXRlSW5mb3MgPSBzdGF0ZS5yb3V0ZUluZm9zLAogICAgICAgICAgcm91dGVJbmZvLAogICAgICAgICAgbGVuOwoKICAgICAgaWYgKCF0YXJnZXRSb3V0ZUluZm9zLmxlbmd0aCkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgdmFyIHRhcmdldEhhbmRsZXIgPSB0YXJnZXRSb3V0ZUluZm9zW3RhcmdldFJvdXRlSW5mb3MubGVuZ3RoIC0gMV0ubmFtZTsKICAgICAgdmFyIHJlY29nSGFuZGxlcnMgPSB0aGlzLnJlY29nbml6ZXIuaGFuZGxlcnNGb3IodGFyZ2V0SGFuZGxlcik7CiAgICAgIHZhciBpbmRleCA9IDA7CgogICAgICBmb3IgKGxlbiA9IHJlY29nSGFuZGxlcnMubGVuZ3RoOyBpbmRleCA8IGxlbjsgKytpbmRleCkgewogICAgICAgIHJvdXRlSW5mbyA9IHRhcmdldFJvdXRlSW5mb3NbaW5kZXhdOwoKICAgICAgICBpZiAocm91dGVJbmZvLm5hbWUgPT09IHJvdXRlTmFtZSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoaW5kZXggPT09IHJlY29nSGFuZGxlcnMubGVuZ3RoKSB7CiAgICAgICAgLy8gVGhlIHByb3ZpZGVkIHJvdXRlIG5hbWUgaXNuJ3QgZXZlbiBpbiB0aGUgcm91dGUgaGllcmFyY2h5LgogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgdmFyIHRlc3RTdGF0ZSA9IG5ldyBUcmFuc2l0aW9uU3RhdGUoKTsKICAgICAgdGVzdFN0YXRlLnJvdXRlSW5mb3MgPSB0YXJnZXRSb3V0ZUluZm9zLnNsaWNlKDAsIGluZGV4ICsgMSk7CiAgICAgIHJlY29nSGFuZGxlcnMgPSByZWNvZ0hhbmRsZXJzLnNsaWNlKDAsIGluZGV4ICsgMSk7CiAgICAgIHZhciBpbnRlbnQgPSBuZXcgTmFtZWRUcmFuc2l0aW9uSW50ZW50KHRoaXMsIHRhcmdldEhhbmRsZXIsIHVuZGVmaW5lZCwgY29udGV4dHMpOwogICAgICB2YXIgbmV3U3RhdGUgPSBpbnRlbnQuYXBwbHlUb0hhbmRsZXJzKHRlc3RTdGF0ZSwgcmVjb2dIYW5kbGVycywgdGFyZ2V0SGFuZGxlciwgdHJ1ZSwgdHJ1ZSk7CiAgICAgIHZhciByb3V0ZXNFcXVhbCA9IHJvdXRlSW5mb3NFcXVhbChuZXdTdGF0ZS5yb3V0ZUluZm9zLCB0ZXN0U3RhdGUucm91dGVJbmZvcyk7CgogICAgICBpZiAoIXF1ZXJ5UGFyYW1zIHx8ICFyb3V0ZXNFcXVhbCkgewogICAgICAgIHJldHVybiByb3V0ZXNFcXVhbDsKICAgICAgfSAvLyBHZXQgYSBoYXNoIG9mIFFQcyB0aGF0IHdpbGwgc3RpbGwgYmUgYWN0aXZlIG9uIG5ldyByb3V0ZQoKCiAgICAgIHZhciBhY3RpdmVRUHNPbk5ld0hhbmRsZXIgPSB7fTsKICAgICAgbWVyZ2UoYWN0aXZlUVBzT25OZXdIYW5kbGVyLCBxdWVyeVBhcmFtcyk7CiAgICAgIHZhciBhY3RpdmVRdWVyeVBhcmFtcyA9IHN0YXRlLnF1ZXJ5UGFyYW1zOwoKICAgICAgZm9yICh2YXIga2V5IGluIGFjdGl2ZVF1ZXJ5UGFyYW1zKSB7CiAgICAgICAgaWYgKGFjdGl2ZVF1ZXJ5UGFyYW1zLmhhc093blByb3BlcnR5KGtleSkgJiYgYWN0aXZlUVBzT25OZXdIYW5kbGVyLmhhc093blByb3BlcnR5KGtleSkpIHsKICAgICAgICAgIGFjdGl2ZVFQc09uTmV3SGFuZGxlcltrZXldID0gYWN0aXZlUXVlcnlQYXJhbXNba2V5XTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiByb3V0ZXNFcXVhbCAmJiAhZ2V0Q2hhbmdlbGlzdChhY3RpdmVRUHNPbk5ld0hhbmRsZXIsIHF1ZXJ5UGFyYW1zKTsKICAgIH07CgogICAgX3Byb3RvOS5pc0FjdGl2ZSA9IGZ1bmN0aW9uIGlzQWN0aXZlKHJvdXRlTmFtZSkgewogICAgICBmb3IgKHZhciBfbGVuNiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjYgPiAxID8gX2xlbjYgLSAxIDogMCksIF9rZXk2ID0gMTsgX2tleTYgPCBfbGVuNjsgX2tleTYrKykgewogICAgICAgIGFyZ3NbX2tleTYgLSAxXSA9IGFyZ3VtZW50c1tfa2V5Nl07CiAgICAgIH0KCiAgICAgIHZhciBwYXJ0aXRpb25lZEFyZ3MgPSBleHRyYWN0UXVlcnlQYXJhbXMoYXJncyk7CiAgICAgIHJldHVybiB0aGlzLmlzQWN0aXZlSW50ZW50KHJvdXRlTmFtZSwgcGFydGl0aW9uZWRBcmdzWzBdLCBwYXJ0aXRpb25lZEFyZ3NbMV0pOwogICAgfTsKCiAgICBfcHJvdG85LnRyaWdnZXIgPSBmdW5jdGlvbiB0cmlnZ2VyKG5hbWUpIHsKICAgICAgZm9yICh2YXIgX2xlbjcgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW43ID4gMSA/IF9sZW43IC0gMSA6IDApLCBfa2V5NyA9IDE7IF9rZXk3IDwgX2xlbjc7IF9rZXk3KyspIHsKICAgICAgICBhcmdzW19rZXk3IC0gMV0gPSBhcmd1bWVudHNbX2tleTddOwogICAgICB9CgogICAgICB0aGlzLnRyaWdnZXJFdmVudCh0aGlzLmN1cnJlbnRSb3V0ZUluZm9zLCBmYWxzZSwgbmFtZSwgYXJncyk7CiAgICB9OwoKICAgIHJldHVybiBSb3V0ZXI7CiAgfSgpOwoKICBmdW5jdGlvbiByb3V0ZUluZm9zRXF1YWwocm91dGVJbmZvcywgb3RoZXJSb3V0ZUluZm9zKSB7CiAgICBpZiAocm91dGVJbmZvcy5sZW5ndGggIT09IG90aGVyUm91dGVJbmZvcy5sZW5ndGgpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSByb3V0ZUluZm9zLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgIGlmIChyb3V0ZUluZm9zW2ldICE9PSBvdGhlclJvdXRlSW5mb3NbaV0pIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKICB9CgogIGZ1bmN0aW9uIHJvdXRlSW5mb3NTYW1lRXhjZXB0UXVlcnlQYXJhbXMocm91dGVJbmZvcywgb3RoZXJSb3V0ZUluZm9zKSB7CiAgICBpZiAocm91dGVJbmZvcy5sZW5ndGggIT09IG90aGVyUm91dGVJbmZvcy5sZW5ndGgpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSByb3V0ZUluZm9zLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgIGlmIChyb3V0ZUluZm9zW2ldLm5hbWUgIT09IG90aGVyUm91dGVJbmZvc1tpXS5uYW1lKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CgogICAgICBpZiAoIXBhcmFtc0VxdWFsKHJvdXRlSW5mb3NbaV0ucGFyYW1zLCBvdGhlclJvdXRlSW5mb3NbaV0ucGFyYW1zKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiB0cnVlOwogIH0KCiAgZnVuY3Rpb24gcGFyYW1zRXF1YWwocGFyYW1zLCBvdGhlclBhcmFtcykgewogICAgaWYgKCFwYXJhbXMgJiYgIW90aGVyUGFyYW1zKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSBlbHNlIGlmICghcGFyYW1zICYmICEhb3RoZXJQYXJhbXMgfHwgISFwYXJhbXMgJiYgIW90aGVyUGFyYW1zKSB7CiAgICAgIC8vIG9uZSBpcyBmYWxzeSBidXQgb3RoZXIgaXMgbm90OwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhwYXJhbXMpOwogICAgdmFyIG90aGVyS2V5cyA9IE9iamVjdC5rZXlzKG90aGVyUGFyYW1zKTsKCiAgICBpZiAoa2V5cy5sZW5ndGggIT09IG90aGVyS2V5cy5sZW5ndGgpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBrZXlzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgIHZhciBrZXkgPSBrZXlzW2ldOwoKICAgICAgaWYgKHBhcmFtc1trZXldICE9PSBvdGhlclBhcmFtc1trZXldKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHRydWU7CiAgfQoKICB2YXIgX2RlZmF1bHQgPSBSb3V0ZXI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJyc3ZwIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2VtYmVyQmFiZWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmFzYXAgPSBhc2FwOwogIF9leHBvcnRzLmFsbCA9IGFsbCQxOwogIF9leHBvcnRzLmFsbFNldHRsZWQgPSBhbGxTZXR0bGVkOwogIF9leHBvcnRzLnJhY2UgPSByYWNlJDE7CiAgX2V4cG9ydHMuaGFzaCA9IGhhc2g7CiAgX2V4cG9ydHMuaGFzaFNldHRsZWQgPSBoYXNoU2V0dGxlZDsKICBfZXhwb3J0cy5yZXRocm93ID0gcmV0aHJvdzsKICBfZXhwb3J0cy5kZWZlciA9IGRlZmVyOwogIF9leHBvcnRzLmRlbm9kZWlmeSA9IGRlbm9kZWlmeTsKICBfZXhwb3J0cy5jb25maWd1cmUgPSBjb25maWd1cmU7CiAgX2V4cG9ydHMub24gPSBvbjsKICBfZXhwb3J0cy5vZmYgPSBvZmY7CiAgX2V4cG9ydHMucmVzb2x2ZSA9IHJlc29sdmUkMjsKICBfZXhwb3J0cy5yZWplY3QgPSByZWplY3QkMjsKICBfZXhwb3J0cy5tYXAgPSBtYXA7CiAgX2V4cG9ydHMuZmlsdGVyID0gZmlsdGVyOwogIF9leHBvcnRzLmFzeW5jID0gX2V4cG9ydHMuRXZlbnRUYXJnZXQgPSBfZXhwb3J0cy5Qcm9taXNlID0gX2V4cG9ydHMuY2FzdCA9IF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIGZ1bmN0aW9uIGNhbGxiYWNrc0ZvcihvYmplY3QpIHsKICAgIHZhciBjYWxsYmFja3MgPSBvYmplY3QuX3Byb21pc2VDYWxsYmFja3M7CgogICAgaWYgKCFjYWxsYmFja3MpIHsKICAgICAgY2FsbGJhY2tzID0gb2JqZWN0Ll9wcm9taXNlQ2FsbGJhY2tzID0ge307CiAgICB9CgogICAgcmV0dXJuIGNhbGxiYWNrczsKICB9CiAgLyoqCiAgICBAY2xhc3MgRXZlbnRUYXJnZXQKICAgIEBmb3IgcnN2cAogICAgQHB1YmxpYwogICovCgoKICB2YXIgRXZlbnRUYXJnZXQgPSB7CiAgICAvKioKICAgICAgYEV2ZW50VGFyZ2V0Lm1peGluYCBleHRlbmRzIGFuIG9iamVjdCB3aXRoIEV2ZW50VGFyZ2V0IG1ldGhvZHMuIEZvcgogICAgICBFeGFtcGxlOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgRXZlbnRUYXJnZXQgZnJvbSAncnN2cCc7CiAgICAgICBsZXQgb2JqZWN0ID0ge307CiAgICAgICBFdmVudFRhcmdldC5taXhpbihvYmplY3QpOwogICAgICAgb2JqZWN0Lm9uKCdmaW5pc2hlZCcsIGZ1bmN0aW9uKGV2ZW50KSB7CiAgICAgICAgLy8gaGFuZGxlIGV2ZW50CiAgICAgIH0pOwogICAgICAgb2JqZWN0LnRyaWdnZXIoJ2ZpbmlzaGVkJywgeyBkZXRhaWw6IHZhbHVlIH0pOwogICAgICBgYGAKICAgICAgIGBFdmVudFRhcmdldC5taXhpbmAgYWxzbyB3b3JrcyB3aXRoIHByb3RvdHlwZXM6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFdmVudFRhcmdldCBmcm9tICdyc3ZwJzsKICAgICAgIGxldCBQZXJzb24gPSBmdW5jdGlvbigpIHt9OwogICAgICBFdmVudFRhcmdldC5taXhpbihQZXJzb24ucHJvdG90eXBlKTsKICAgICAgIGxldCB5ZWh1ZGEgPSBuZXcgUGVyc29uKCk7CiAgICAgIGxldCB0b20gPSBuZXcgUGVyc29uKCk7CiAgICAgICB5ZWh1ZGEub24oJ3Bva2UnLCBmdW5jdGlvbihldmVudCkgewogICAgICAgIGNvbnNvbGUubG9nKCdZZWh1ZGEgc2F5cyBPVycpOwogICAgICB9KTsKICAgICAgIHRvbS5vbigncG9rZScsIGZ1bmN0aW9uKGV2ZW50KSB7CiAgICAgICAgY29uc29sZS5sb2coJ1RvbSBzYXlzIE9XJyk7CiAgICAgIH0pOwogICAgICAgeWVodWRhLnRyaWdnZXIoJ3Bva2UnKTsKICAgICAgdG9tLnRyaWdnZXIoJ3Bva2UnKTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIG1peGluCiAgICAgIEBmb3IgcnN2cAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge09iamVjdH0gb2JqZWN0IG9iamVjdCB0byBleHRlbmQgd2l0aCBFdmVudFRhcmdldCBtZXRob2RzCiAgICAqLwogICAgbWl4aW46IGZ1bmN0aW9uIG1peGluKG9iamVjdCkgewogICAgICBvYmplY3Qub24gPSB0aGlzLm9uOwogICAgICBvYmplY3Qub2ZmID0gdGhpcy5vZmY7CiAgICAgIG9iamVjdC50cmlnZ2VyID0gdGhpcy50cmlnZ2VyOwogICAgICBvYmplY3QuX3Byb21pc2VDYWxsYmFja3MgPSB1bmRlZmluZWQ7CiAgICAgIHJldHVybiBvYmplY3Q7CiAgICB9LAoKICAgIC8qKgogICAgICBSZWdpc3RlcnMgYSBjYWxsYmFjayB0byBiZSBleGVjdXRlZCB3aGVuIGBldmVudE5hbWVgIGlzIHRyaWdnZXJlZAogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBvYmplY3Qub24oJ2V2ZW50JywgZnVuY3Rpb24oZXZlbnRJbmZvKXsKICAgICAgICAvLyBoYW5kbGUgdGhlIGV2ZW50CiAgICAgIH0pOwogICAgICAgb2JqZWN0LnRyaWdnZXIoJ2V2ZW50Jyk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBvbgogICAgICBAZm9yIEV2ZW50VGFyZ2V0CiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBldmVudE5hbWUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gbGlzdGVuIGZvcgogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgdHJpZ2dlcmVkLgogICAgKi8KICAgIG9uOiBmdW5jdGlvbiBvbihldmVudE5hbWUsIGNhbGxiYWNrKSB7CiAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09ICdmdW5jdGlvbicpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYWxsYmFjayBtdXN0IGJlIGEgZnVuY3Rpb24nKTsKICAgICAgfQoKICAgICAgdmFyIGFsbENhbGxiYWNrcyA9IGNhbGxiYWNrc0Zvcih0aGlzKTsKICAgICAgdmFyIGNhbGxiYWNrcyA9IGFsbENhbGxiYWNrc1tldmVudE5hbWVdOwoKICAgICAgaWYgKCFjYWxsYmFja3MpIHsKICAgICAgICBjYWxsYmFja3MgPSBhbGxDYWxsYmFja3NbZXZlbnROYW1lXSA9IFtdOwogICAgICB9CgogICAgICBpZiAoY2FsbGJhY2tzLmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkgewogICAgICAgIGNhbGxiYWNrcy5wdXNoKGNhbGxiYWNrKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgWW91IGNhbiB1c2UgYG9mZmAgdG8gc3RvcCBmaXJpbmcgYSBwYXJ0aWN1bGFyIGNhbGxiYWNrIGZvciBhbiBldmVudDoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgZnVuY3Rpb24gZG9TdHVmZigpIHsgLy8gZG8gc3R1ZmYhIH0KICAgICAgb2JqZWN0Lm9uKCdzdHVmZicsIGRvU3R1ZmYpOwogICAgICAgb2JqZWN0LnRyaWdnZXIoJ3N0dWZmJyk7IC8vIGRvU3R1ZmYgd2lsbCBiZSBjYWxsZWQKICAgICAgIC8vIFVucmVnaXN0ZXIgT05MWSB0aGUgZG9TdHVmZiBjYWxsYmFjawogICAgICBvYmplY3Qub2ZmKCdzdHVmZicsIGRvU3R1ZmYpOwogICAgICBvYmplY3QudHJpZ2dlcignc3R1ZmYnKTsgLy8gZG9TdHVmZiB3aWxsIE5PVCBiZSBjYWxsZWQKICAgICAgYGBgCiAgICAgICBJZiB5b3UgZG9uJ3QgcGFzcyBhIGBjYWxsYmFja2AgYXJndW1lbnQgdG8gYG9mZmAsIEFMTCBjYWxsYmFja3MgZm9yIHRoZQogICAgICBldmVudCB3aWxsIG5vdCBiZSBleGVjdXRlZCB3aGVuIHRoZSBldmVudCBmaXJlcy4gRm9yIGV4YW1wbGU6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjYWxsYmFjazEgPSBmdW5jdGlvbigpe307CiAgICAgIGxldCBjYWxsYmFjazIgPSBmdW5jdGlvbigpe307CiAgICAgICBvYmplY3Qub24oJ3N0dWZmJywgY2FsbGJhY2sxKTsKICAgICAgb2JqZWN0Lm9uKCdzdHVmZicsIGNhbGxiYWNrMik7CiAgICAgICBvYmplY3QudHJpZ2dlcignc3R1ZmYnKTsgLy8gY2FsbGJhY2sxIGFuZCBjYWxsYmFjazIgd2lsbCBiZSBleGVjdXRlZC4KICAgICAgIG9iamVjdC5vZmYoJ3N0dWZmJyk7CiAgICAgIG9iamVjdC50cmlnZ2VyKCdzdHVmZicpOyAvLyBjYWxsYmFjazEgYW5kIGNhbGxiYWNrMiB3aWxsIG5vdCBiZSBleGVjdXRlZCEKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIG9mZgogICAgICBAZm9yIHJzdnAKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZSBldmVudCB0byBzdG9wIGxpc3RlbmluZyB0bwogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBbY2FsbGJhY2tdIG9wdGlvbmFsIGFyZ3VtZW50LiBJZiBnaXZlbiwgb25seSB0aGUgZnVuY3Rpb24KICAgICAgZ2l2ZW4gd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIGV2ZW50J3MgY2FsbGJhY2sgcXVldWUuIElmIG5vIGBjYWxsYmFja2AKICAgICAgYXJndW1lbnQgaXMgZ2l2ZW4sIGFsbCBjYWxsYmFja3Mgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIGV2ZW50J3MgY2FsbGJhY2sKICAgICAgcXVldWUuCiAgICAqLwogICAgb2ZmOiBmdW5jdGlvbiBvZmYoZXZlbnROYW1lLCBjYWxsYmFjaykgewogICAgICB2YXIgYWxsQ2FsbGJhY2tzID0gY2FsbGJhY2tzRm9yKHRoaXMpOwoKICAgICAgaWYgKCFjYWxsYmFjaykgewogICAgICAgIGFsbENhbGxiYWNrc1tldmVudE5hbWVdID0gW107CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgY2FsbGJhY2tzID0gYWxsQ2FsbGJhY2tzW2V2ZW50TmFtZV07CiAgICAgIHZhciBpbmRleCA9IGNhbGxiYWNrcy5pbmRleE9mKGNhbGxiYWNrKTsKCiAgICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGluZGV4LCAxKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgVXNlIGB0cmlnZ2VyYCB0byBmaXJlIGN1c3RvbSBldmVudHMuIEZvciBleGFtcGxlOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBvYmplY3Qub24oJ2ZvbycsIGZ1bmN0aW9uKCl7CiAgICAgICAgY29uc29sZS5sb2coJ2ZvbyBldmVudCBoYXBwZW5lZCEnKTsKICAgICAgfSk7CiAgICAgIG9iamVjdC50cmlnZ2VyKCdmb28nKTsKICAgICAgLy8gJ2ZvbyBldmVudCBoYXBwZW5lZCEnIGxvZ2dlZCB0byB0aGUgY29uc29sZQogICAgICBgYGAKICAgICAgIFlvdSBjYW4gYWxzbyBwYXNzIGEgdmFsdWUgYXMgYSBzZWNvbmQgYXJndW1lbnQgdG8gYHRyaWdnZXJgIHRoYXQgd2lsbCBiZQogICAgICBwYXNzZWQgYXMgYW4gYXJndW1lbnQgdG8gYWxsIGV2ZW50IGxpc3RlbmVycyBmb3IgdGhlIGV2ZW50OgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBvYmplY3Qub24oJ2ZvbycsIGZ1bmN0aW9uKHZhbHVlKXsKICAgICAgICBjb25zb2xlLmxvZyh2YWx1ZS5uYW1lKTsKICAgICAgfSk7CiAgICAgICBvYmplY3QudHJpZ2dlcignZm9vJywgeyBuYW1lOiAnYmFyJyB9KTsKICAgICAgLy8gJ2JhcicgbG9nZ2VkIHRvIHRoZSBjb25zb2xlCiAgICAgIGBgYAogICAgICAgQG1ldGhvZCB0cmlnZ2VyCiAgICAgIEBmb3IgcnN2cAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGJlIHRyaWdnZXJlZAogICAgICBAcGFyYW0geyp9IFtvcHRpb25zXSBvcHRpb25hbCB2YWx1ZSB0byBiZSBwYXNzZWQgdG8gYW55IGV2ZW50IGhhbmRsZXJzIGZvcgogICAgICB0aGUgZ2l2ZW4gYGV2ZW50TmFtZWAKICAgICovCiAgICB0cmlnZ2VyOiBmdW5jdGlvbiB0cmlnZ2VyKGV2ZW50TmFtZSwgb3B0aW9ucywgbGFiZWwpIHsKICAgICAgdmFyIGFsbENhbGxiYWNrcyA9IGNhbGxiYWNrc0Zvcih0aGlzKTsKICAgICAgdmFyIGNhbGxiYWNrcyA9IGFsbENhbGxiYWNrc1tldmVudE5hbWVdOwoKICAgICAgaWYgKGNhbGxiYWNrcykgewogICAgICAgIC8vIERvbid0IGNhY2hlIHRoZSBjYWxsYmFja3MubGVuZ3RoIHNpbmNlIGl0IG1heSBncm93CiAgICAgICAgdmFyIGNhbGxiYWNrOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNhbGxiYWNrcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgY2FsbGJhY2sgPSBjYWxsYmFja3NbaV07CiAgICAgICAgICBjYWxsYmFjayhvcHRpb25zLCBsYWJlbCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfTsKICBfZXhwb3J0cy5FdmVudFRhcmdldCA9IEV2ZW50VGFyZ2V0OwogIHZhciBjb25maWcgPSB7CiAgICBpbnN0cnVtZW50OiBmYWxzZQogIH07CiAgRXZlbnRUYXJnZXRbJ21peGluJ10oY29uZmlnKTsKCiAgZnVuY3Rpb24gY29uZmlndXJlKG5hbWUsIHZhbHVlKSB7CiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgewogICAgICBjb25maWdbbmFtZV0gPSB2YWx1ZTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBjb25maWdbbmFtZV07CiAgICB9CiAgfQoKICB2YXIgcXVldWUgPSBbXTsKCiAgZnVuY3Rpb24gc2NoZWR1bGVGbHVzaCgpIHsKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgewogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHF1ZXVlLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGVudHJ5ID0gcXVldWVbaV07CiAgICAgICAgdmFyIHBheWxvYWQgPSBlbnRyeS5wYXlsb2FkOwogICAgICAgIHBheWxvYWQuZ3VpZCA9IHBheWxvYWQua2V5ICsgcGF5bG9hZC5pZDsKICAgICAgICBwYXlsb2FkLmNoaWxkR3VpZCA9IHBheWxvYWQua2V5ICsgcGF5bG9hZC5jaGlsZElkOwoKICAgICAgICBpZiAocGF5bG9hZC5lcnJvcikgewogICAgICAgICAgcGF5bG9hZC5zdGFjayA9IHBheWxvYWQuZXJyb3Iuc3RhY2s7CiAgICAgICAgfQoKICAgICAgICBjb25maWdbJ3RyaWdnZXInXShlbnRyeS5uYW1lLCBlbnRyeS5wYXlsb2FkKTsKICAgICAgfQoKICAgICAgcXVldWUubGVuZ3RoID0gMDsKICAgIH0sIDUwKTsKICB9CgogIGZ1bmN0aW9uIGluc3RydW1lbnQoZXZlbnROYW1lLCBwcm9taXNlLCBjaGlsZCkgewogICAgaWYgKDEgPT09IHF1ZXVlLnB1c2goewogICAgICBuYW1lOiBldmVudE5hbWUsCiAgICAgIHBheWxvYWQ6IHsKICAgICAgICBrZXk6IHByb21pc2UuX2d1aWRLZXksCiAgICAgICAgaWQ6IHByb21pc2UuX2lkLAogICAgICAgIGV2ZW50TmFtZTogZXZlbnROYW1lLAogICAgICAgIGRldGFpbDogcHJvbWlzZS5fcmVzdWx0LAogICAgICAgIGNoaWxkSWQ6IGNoaWxkICYmIGNoaWxkLl9pZCwKICAgICAgICBsYWJlbDogcHJvbWlzZS5fbGFiZWwsCiAgICAgICAgdGltZVN0YW1wOiBEYXRlLm5vdygpLAogICAgICAgIGVycm9yOiBjb25maWdbImluc3RydW1lbnQtd2l0aC1zdGFjayJdID8gbmV3IEVycm9yKHByb21pc2UuX2xhYmVsKSA6IG51bGwKICAgICAgfQogICAgfSkpIHsKICAgICAgc2NoZWR1bGVGbHVzaCgpOwogICAgfQogIH0KICAvKioKICAgIGBQcm9taXNlLnJlc29sdmVgIHJldHVybnMgYSBwcm9taXNlIHRoYXQgd2lsbCBiZWNvbWUgcmVzb2x2ZWQgd2l0aCB0aGUKICAgIHBhc3NlZCBgdmFsdWVgLiBJdCBpcyBzaG9ydGhhbmQgZm9yIHRoZSBmb2xsb3dpbmc6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXsKICAgICAgcmVzb2x2ZSgxKTsKICAgIH0pOwogIAogICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXsKICAgICAgLy8gdmFsdWUgPT09IDEKICAgIH0pOwogICAgYGBgCiAgCiAgICBJbnN0ZWFkIG9mIHdyaXRpbmcgdGhlIGFib3ZlLCB5b3VyIGNvZGUgbm93IHNpbXBseSBiZWNvbWVzIHRoZSBmb2xsb3dpbmc6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlID0gUlNWUC5Qcm9taXNlLnJlc29sdmUoMSk7CiAgCiAgICBwcm9taXNlLnRoZW4oZnVuY3Rpb24odmFsdWUpewogICAgICAvLyB2YWx1ZSA9PT0gMQogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgcmVzb2x2ZQogICAgQGZvciBQcm9taXNlCiAgICBAc3RhdGljCiAgICBAcGFyYW0geyp9IG9iamVjdCB2YWx1ZSB0aGF0IHRoZSByZXR1cm5lZCBwcm9taXNlIHdpbGwgYmUgcmVzb2x2ZWQgd2l0aAogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGZvciBpZGVudGlmeWluZyB0aGUgcmV0dXJuZWQgcHJvbWlzZS4KICAgIFVzZWZ1bCBmb3IgdG9vbGluZy4KICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IHdpbGwgYmVjb21lIGZ1bGZpbGxlZCB3aXRoIHRoZSBnaXZlbgogICAgYHZhbHVlYAogICovCgoKICBmdW5jdGlvbiByZXNvbHZlJCQxKG9iamVjdCwgbGFiZWwpIHsKICAgIC8qanNoaW50IHZhbGlkdGhpczp0cnVlICovCiAgICB2YXIgQ29uc3RydWN0b3IgPSB0aGlzOwoKICAgIGlmIChvYmplY3QgJiYgdHlwZW9mIG9iamVjdCA9PT0gJ29iamVjdCcgJiYgb2JqZWN0LmNvbnN0cnVjdG9yID09PSBDb25zdHJ1Y3RvcikgewogICAgICByZXR1cm4gb2JqZWN0OwogICAgfQoKICAgIHZhciBwcm9taXNlID0gbmV3IENvbnN0cnVjdG9yKG5vb3AsIGxhYmVsKTsKICAgIHJlc29sdmUkMShwcm9taXNlLCBvYmplY3QpOwogICAgcmV0dXJuIHByb21pc2U7CiAgfQoKICBmdW5jdGlvbiB3aXRoT3duUHJvbWlzZSgpIHsKICAgIHJldHVybiBuZXcgVHlwZUVycm9yKCdBIHByb21pc2VzIGNhbGxiYWNrIGNhbm5vdCByZXR1cm4gdGhhdCBzYW1lIHByb21pc2UuJyk7CiAgfQoKICBmdW5jdGlvbiBvYmplY3RPckZ1bmN0aW9uKHgpIHsKICAgIHZhciB0eXBlID0gdHlwZW9mIHg7CiAgICByZXR1cm4geCAhPT0gbnVsbCAmJiAodHlwZSA9PT0gJ29iamVjdCcgfHwgdHlwZSA9PT0gJ2Z1bmN0aW9uJyk7CiAgfQoKICBmdW5jdGlvbiBub29wKCkge30KCiAgdmFyIFBFTkRJTkcgPSB2b2lkIDA7CiAgdmFyIEZVTEZJTExFRCA9IDE7CiAgdmFyIFJFSkVDVEVEID0gMjsKCiAgZnVuY3Rpb24gdHJ5VGhlbih0aGVuJCQxLCB2YWx1ZSwgZnVsZmlsbG1lbnRIYW5kbGVyLCByZWplY3Rpb25IYW5kbGVyKSB7CiAgICB0cnkgewogICAgICB0aGVuJCQxLmNhbGwodmFsdWUsIGZ1bGZpbGxtZW50SGFuZGxlciwgcmVqZWN0aW9uSGFuZGxlcik7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHJldHVybiBlOwogICAgfQogIH0KCiAgZnVuY3Rpb24gaGFuZGxlRm9yZWlnblRoZW5hYmxlKHByb21pc2UsIHRoZW5hYmxlLCB0aGVuJCQxKSB7CiAgICBjb25maWcuYXN5bmMoZnVuY3Rpb24gKHByb21pc2UpIHsKICAgICAgdmFyIHNlYWxlZCA9IGZhbHNlOwogICAgICB2YXIgZXJyb3IgPSB0cnlUaGVuKHRoZW4kJDEsIHRoZW5hYmxlLCBmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgICBpZiAoc2VhbGVkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBzZWFsZWQgPSB0cnVlOwoKICAgICAgICBpZiAodGhlbmFibGUgPT09IHZhbHVlKSB7CiAgICAgICAgICBmdWxmaWxsKHByb21pc2UsIHZhbHVlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzb2x2ZSQxKHByb21pc2UsIHZhbHVlKTsKICAgICAgICB9CiAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICBpZiAoc2VhbGVkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBzZWFsZWQgPSB0cnVlOwogICAgICAgIHJlamVjdChwcm9taXNlLCByZWFzb24pOwogICAgICB9LCAnU2V0dGxlOiAnICsgKHByb21pc2UuX2xhYmVsIHx8ICcgdW5rbm93biBwcm9taXNlJykpOwoKICAgICAgaWYgKCFzZWFsZWQgJiYgZXJyb3IpIHsKICAgICAgICBzZWFsZWQgPSB0cnVlOwogICAgICAgIHJlamVjdChwcm9taXNlLCBlcnJvcik7CiAgICAgIH0KICAgIH0sIHByb21pc2UpOwogIH0KCiAgZnVuY3Rpb24gaGFuZGxlT3duVGhlbmFibGUocHJvbWlzZSwgdGhlbmFibGUpIHsKICAgIGlmICh0aGVuYWJsZS5fc3RhdGUgPT09IEZVTEZJTExFRCkgewogICAgICBmdWxmaWxsKHByb21pc2UsIHRoZW5hYmxlLl9yZXN1bHQpOwogICAgfSBlbHNlIGlmICh0aGVuYWJsZS5fc3RhdGUgPT09IFJFSkVDVEVEKSB7CiAgICAgIHRoZW5hYmxlLl9vbkVycm9yID0gbnVsbDsKICAgICAgcmVqZWN0KHByb21pc2UsIHRoZW5hYmxlLl9yZXN1bHQpOwogICAgfSBlbHNlIHsKICAgICAgc3Vic2NyaWJlKHRoZW5hYmxlLCB1bmRlZmluZWQsIGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgIGlmICh0aGVuYWJsZSA9PT0gdmFsdWUpIHsKICAgICAgICAgIGZ1bGZpbGwocHJvbWlzZSwgdmFsdWUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXNvbHZlJDEocHJvbWlzZSwgdmFsdWUpOwogICAgICAgIH0KICAgICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgIHJldHVybiByZWplY3QocHJvbWlzZSwgcmVhc29uKTsKICAgICAgfSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBoYW5kbGVNYXliZVRoZW5hYmxlKHByb21pc2UsIG1heWJlVGhlbmFibGUsIHRoZW4kJDEpIHsKICAgIHZhciBpc093blRoZW5hYmxlID0gbWF5YmVUaGVuYWJsZS5jb25zdHJ1Y3RvciA9PT0gcHJvbWlzZS5jb25zdHJ1Y3RvciAmJiB0aGVuJCQxID09PSB0aGVuICYmIHByb21pc2UuY29uc3RydWN0b3IucmVzb2x2ZSA9PT0gcmVzb2x2ZSQkMTsKCiAgICBpZiAoaXNPd25UaGVuYWJsZSkgewogICAgICBoYW5kbGVPd25UaGVuYWJsZShwcm9taXNlLCBtYXliZVRoZW5hYmxlKTsKICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoZW4kJDEgPT09ICdmdW5jdGlvbicpIHsKICAgICAgaGFuZGxlRm9yZWlnblRoZW5hYmxlKHByb21pc2UsIG1heWJlVGhlbmFibGUsIHRoZW4kJDEpOwogICAgfSBlbHNlIHsKICAgICAgZnVsZmlsbChwcm9taXNlLCBtYXliZVRoZW5hYmxlKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHJlc29sdmUkMShwcm9taXNlLCB2YWx1ZSkgewogICAgaWYgKHByb21pc2UgPT09IHZhbHVlKSB7CiAgICAgIGZ1bGZpbGwocHJvbWlzZSwgdmFsdWUpOwogICAgfSBlbHNlIGlmIChvYmplY3RPckZ1bmN0aW9uKHZhbHVlKSkgewogICAgICB2YXIgdGhlbiQkMTsKCiAgICAgIHRyeSB7CiAgICAgICAgdGhlbiQkMSA9IHZhbHVlLnRoZW47CiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgcmVqZWN0KHByb21pc2UsIGVycm9yKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGhhbmRsZU1heWJlVGhlbmFibGUocHJvbWlzZSwgdmFsdWUsIHRoZW4kJDEpOwogICAgfSBlbHNlIHsKICAgICAgZnVsZmlsbChwcm9taXNlLCB2YWx1ZSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBwdWJsaXNoUmVqZWN0aW9uKHByb21pc2UpIHsKICAgIGlmIChwcm9taXNlLl9vbkVycm9yKSB7CiAgICAgIHByb21pc2UuX29uRXJyb3IocHJvbWlzZS5fcmVzdWx0KTsKICAgIH0KCiAgICBwdWJsaXNoKHByb21pc2UpOwogIH0KCiAgZnVuY3Rpb24gZnVsZmlsbChwcm9taXNlLCB2YWx1ZSkgewogICAgaWYgKHByb21pc2UuX3N0YXRlICE9PSBQRU5ESU5HKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBwcm9taXNlLl9yZXN1bHQgPSB2YWx1ZTsKICAgIHByb21pc2UuX3N0YXRlID0gRlVMRklMTEVEOwoKICAgIGlmIChwcm9taXNlLl9zdWJzY3JpYmVycy5sZW5ndGggPT09IDApIHsKICAgICAgaWYgKGNvbmZpZy5pbnN0cnVtZW50KSB7CiAgICAgICAgaW5zdHJ1bWVudCgnZnVsZmlsbGVkJywgcHJvbWlzZSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGNvbmZpZy5hc3luYyhwdWJsaXNoLCBwcm9taXNlKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHJlamVjdChwcm9taXNlLCByZWFzb24pIHsKICAgIGlmIChwcm9taXNlLl9zdGF0ZSAhPT0gUEVORElORykgewogICAgICByZXR1cm47CiAgICB9CgogICAgcHJvbWlzZS5fc3RhdGUgPSBSRUpFQ1RFRDsKICAgIHByb21pc2UuX3Jlc3VsdCA9IHJlYXNvbjsKICAgIGNvbmZpZy5hc3luYyhwdWJsaXNoUmVqZWN0aW9uLCBwcm9taXNlKTsKICB9CgogIGZ1bmN0aW9uIHN1YnNjcmliZShwYXJlbnQsIGNoaWxkLCBvbkZ1bGZpbGxtZW50LCBvblJlamVjdGlvbikgewogICAgdmFyIHN1YnNjcmliZXJzID0gcGFyZW50Ll9zdWJzY3JpYmVyczsKICAgIHZhciBsZW5ndGggPSBzdWJzY3JpYmVycy5sZW5ndGg7CiAgICBwYXJlbnQuX29uRXJyb3IgPSBudWxsOwogICAgc3Vic2NyaWJlcnNbbGVuZ3RoXSA9IGNoaWxkOwogICAgc3Vic2NyaWJlcnNbbGVuZ3RoICsgRlVMRklMTEVEXSA9IG9uRnVsZmlsbG1lbnQ7CiAgICBzdWJzY3JpYmVyc1tsZW5ndGggKyBSRUpFQ1RFRF0gPSBvblJlamVjdGlvbjsKCiAgICBpZiAobGVuZ3RoID09PSAwICYmIHBhcmVudC5fc3RhdGUpIHsKICAgICAgY29uZmlnLmFzeW5jKHB1Ymxpc2gsIHBhcmVudCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBwdWJsaXNoKHByb21pc2UpIHsKICAgIHZhciBzdWJzY3JpYmVycyA9IHByb21pc2UuX3N1YnNjcmliZXJzOwogICAgdmFyIHNldHRsZWQgPSBwcm9taXNlLl9zdGF0ZTsKCiAgICBpZiAoY29uZmlnLmluc3RydW1lbnQpIHsKICAgICAgaW5zdHJ1bWVudChzZXR0bGVkID09PSBGVUxGSUxMRUQgPyAnZnVsZmlsbGVkJyA6ICdyZWplY3RlZCcsIHByb21pc2UpOwogICAgfQoKICAgIGlmIChzdWJzY3JpYmVycy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBjaGlsZCwKICAgICAgICBjYWxsYmFjaywKICAgICAgICByZXN1bHQgPSBwcm9taXNlLl9yZXN1bHQ7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdWJzY3JpYmVycy5sZW5ndGg7IGkgKz0gMykgewogICAgICBjaGlsZCA9IHN1YnNjcmliZXJzW2ldOwogICAgICBjYWxsYmFjayA9IHN1YnNjcmliZXJzW2kgKyBzZXR0bGVkXTsKCiAgICAgIGlmIChjaGlsZCkgewogICAgICAgIGludm9rZUNhbGxiYWNrKHNldHRsZWQsIGNoaWxkLCBjYWxsYmFjaywgcmVzdWx0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjYWxsYmFjayhyZXN1bHQpOwogICAgICB9CiAgICB9CgogICAgcHJvbWlzZS5fc3Vic2NyaWJlcnMubGVuZ3RoID0gMDsKICB9CgogIGZ1bmN0aW9uIGludm9rZUNhbGxiYWNrKHN0YXRlLCBwcm9taXNlLCBjYWxsYmFjaywgcmVzdWx0KSB7CiAgICB2YXIgaGFzQ2FsbGJhY2sgPSB0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbic7CiAgICB2YXIgdmFsdWUsCiAgICAgICAgc3VjY2VlZGVkID0gdHJ1ZSwKICAgICAgICBlcnJvcjsKCiAgICBpZiAoaGFzQ2FsbGJhY2spIHsKICAgICAgdHJ5IHsKICAgICAgICB2YWx1ZSA9IGNhbGxiYWNrKHJlc3VsdCk7CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBzdWNjZWVkZWQgPSBmYWxzZTsKICAgICAgICBlcnJvciA9IGU7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhbHVlID0gcmVzdWx0OwogICAgfQoKICAgIGlmIChwcm9taXNlLl9zdGF0ZSAhPT0gUEVORElORykgey8vIG5vb3AKICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IHByb21pc2UpIHsKICAgICAgcmVqZWN0KHByb21pc2UsIHdpdGhPd25Qcm9taXNlKCkpOwogICAgfSBlbHNlIGlmIChzdWNjZWVkZWQgPT09IGZhbHNlKSB7CiAgICAgIHJlamVjdChwcm9taXNlLCBlcnJvcik7CiAgICB9IGVsc2UgaWYgKGhhc0NhbGxiYWNrKSB7CiAgICAgIHJlc29sdmUkMShwcm9taXNlLCB2YWx1ZSk7CiAgICB9IGVsc2UgaWYgKHN0YXRlID09PSBGVUxGSUxMRUQpIHsKICAgICAgZnVsZmlsbChwcm9taXNlLCB2YWx1ZSk7CiAgICB9IGVsc2UgaWYgKHN0YXRlID09PSBSRUpFQ1RFRCkgewogICAgICByZWplY3QocHJvbWlzZSwgdmFsdWUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gaW5pdGlhbGl6ZVByb21pc2UocHJvbWlzZSwgcmVzb2x2ZXIpIHsKICAgIHZhciByZXNvbHZlZCA9IGZhbHNlOwoKICAgIHRyeSB7CiAgICAgIHJlc29sdmVyKGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgIGlmIChyZXNvbHZlZCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgcmVzb2x2ZWQgPSB0cnVlOwogICAgICAgIHJlc29sdmUkMShwcm9taXNlLCB2YWx1ZSk7CiAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICBpZiAocmVzb2x2ZWQpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHJlc29sdmVkID0gdHJ1ZTsKICAgICAgICByZWplY3QocHJvbWlzZSwgcmVhc29uKTsKICAgICAgfSk7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHJlamVjdChwcm9taXNlLCBlKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHRoZW4ob25GdWxmaWxsbWVudCwgb25SZWplY3Rpb24sIGxhYmVsKSB7CiAgICB2YXIgcGFyZW50ID0gdGhpczsKICAgIHZhciBzdGF0ZSA9IHBhcmVudC5fc3RhdGU7CgogICAgaWYgKHN0YXRlID09PSBGVUxGSUxMRUQgJiYgIW9uRnVsZmlsbG1lbnQgfHwgc3RhdGUgPT09IFJFSkVDVEVEICYmICFvblJlamVjdGlvbikgewogICAgICBjb25maWcuaW5zdHJ1bWVudCAmJiBpbnN0cnVtZW50KCdjaGFpbmVkJywgcGFyZW50LCBwYXJlbnQpOwogICAgICByZXR1cm4gcGFyZW50OwogICAgfQoKICAgIHBhcmVudC5fb25FcnJvciA9IG51bGw7CiAgICB2YXIgY2hpbGQgPSBuZXcgcGFyZW50LmNvbnN0cnVjdG9yKG5vb3AsIGxhYmVsKTsKICAgIHZhciByZXN1bHQgPSBwYXJlbnQuX3Jlc3VsdDsKICAgIGNvbmZpZy5pbnN0cnVtZW50ICYmIGluc3RydW1lbnQoJ2NoYWluZWQnLCBwYXJlbnQsIGNoaWxkKTsKCiAgICBpZiAoc3RhdGUgPT09IFBFTkRJTkcpIHsKICAgICAgc3Vic2NyaWJlKHBhcmVudCwgY2hpbGQsIG9uRnVsZmlsbG1lbnQsIG9uUmVqZWN0aW9uKTsKICAgIH0gZWxzZSB7CiAgICAgIHZhciBjYWxsYmFjayA9IHN0YXRlID09PSBGVUxGSUxMRUQgPyBvbkZ1bGZpbGxtZW50IDogb25SZWplY3Rpb247CiAgICAgIGNvbmZpZy5hc3luYyhmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIGludm9rZUNhbGxiYWNrKHN0YXRlLCBjaGlsZCwgY2FsbGJhY2ssIHJlc3VsdCk7CiAgICAgIH0pOwogICAgfQoKICAgIHJldHVybiBjaGlsZDsKICB9CgogIHZhciBFbnVtZXJhdG9yID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRW51bWVyYXRvcihDb25zdHJ1Y3RvciwgaW5wdXQsIGFib3J0T25SZWplY3QsIGxhYmVsKSB7CiAgICAgIHRoaXMuX2luc3RhbmNlQ29uc3RydWN0b3IgPSBDb25zdHJ1Y3RvcjsKICAgICAgdGhpcy5wcm9taXNlID0gbmV3IENvbnN0cnVjdG9yKG5vb3AsIGxhYmVsKTsKICAgICAgdGhpcy5fYWJvcnRPblJlamVjdCA9IGFib3J0T25SZWplY3Q7CiAgICAgIHRoaXMuX2lzVXNpbmdPd25Qcm9taXNlID0gQ29uc3RydWN0b3IgPT09IFByb21pc2U7CiAgICAgIHRoaXMuX2lzVXNpbmdPd25SZXNvbHZlID0gQ29uc3RydWN0b3IucmVzb2x2ZSA9PT0gcmVzb2x2ZSQkMTsKCiAgICAgIHRoaXMuX2luaXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gRW51bWVyYXRvci5wcm90b3R5cGU7CgogICAgX3Byb3RvLl9pbml0ID0gZnVuY3Rpb24gX2luaXQoQ29uc3RydWN0b3IsIGlucHV0KSB7CiAgICAgIHZhciBsZW4gPSBpbnB1dC5sZW5ndGggfHwgMDsKICAgICAgdGhpcy5sZW5ndGggPSBsZW47CiAgICAgIHRoaXMuX3JlbWFpbmluZyA9IGxlbjsKICAgICAgdGhpcy5fcmVzdWx0ID0gbmV3IEFycmF5KGxlbik7CgogICAgICB0aGlzLl9lbnVtZXJhdGUoaW5wdXQpOwogICAgfTsKCiAgICBfcHJvdG8uX2VudW1lcmF0ZSA9IGZ1bmN0aW9uIF9lbnVtZXJhdGUoaW5wdXQpIHsKICAgICAgdmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoOwogICAgICB2YXIgcHJvbWlzZSA9IHRoaXMucHJvbWlzZTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBwcm9taXNlLl9zdGF0ZSA9PT0gUEVORElORyAmJiBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICB0aGlzLl9lYWNoRW50cnkoaW5wdXRbaV0sIGksIHRydWUpOwogICAgICB9CgogICAgICB0aGlzLl9jaGVja0Z1bGxmaWxsbWVudCgpOwogICAgfTsKCiAgICBfcHJvdG8uX2NoZWNrRnVsbGZpbGxtZW50ID0gZnVuY3Rpb24gX2NoZWNrRnVsbGZpbGxtZW50KCkgewogICAgICBpZiAodGhpcy5fcmVtYWluaW5nID09PSAwKSB7CiAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuX3Jlc3VsdDsKICAgICAgICBmdWxmaWxsKHRoaXMucHJvbWlzZSwgcmVzdWx0KTsKICAgICAgICB0aGlzLl9yZXN1bHQgPSBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fc2V0dGxlTWF5YmVUaGVuYWJsZSA9IGZ1bmN0aW9uIF9zZXR0bGVNYXliZVRoZW5hYmxlKGVudHJ5LCBpLCBmaXJzdFBhc3MpIHsKICAgICAgdmFyIGMgPSB0aGlzLl9pbnN0YW5jZUNvbnN0cnVjdG9yOwoKICAgICAgaWYgKHRoaXMuX2lzVXNpbmdPd25SZXNvbHZlKSB7CiAgICAgICAgdmFyIHRoZW4kJDEsCiAgICAgICAgICAgIGVycm9yLAogICAgICAgICAgICBzdWNjZWVkZWQgPSB0cnVlOwoKICAgICAgICB0cnkgewogICAgICAgICAgdGhlbiQkMSA9IGVudHJ5LnRoZW47CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgc3VjY2VlZGVkID0gZmFsc2U7CiAgICAgICAgICBlcnJvciA9IGU7CiAgICAgICAgfQoKICAgICAgICBpZiAodGhlbiQkMSA9PT0gdGhlbiAmJiBlbnRyeS5fc3RhdGUgIT09IFBFTkRJTkcpIHsKICAgICAgICAgIGVudHJ5Ll9vbkVycm9yID0gbnVsbDsKCiAgICAgICAgICB0aGlzLl9zZXR0bGVkQXQoZW50cnkuX3N0YXRlLCBpLCBlbnRyeS5fcmVzdWx0LCBmaXJzdFBhc3MpOwogICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoZW4kJDEgIT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIHRoaXMuX3NldHRsZWRBdChGVUxGSUxMRUQsIGksIGVudHJ5LCBmaXJzdFBhc3MpOwogICAgICAgIH0gZWxzZSBpZiAodGhpcy5faXNVc2luZ093blByb21pc2UpIHsKICAgICAgICAgIHZhciBwcm9taXNlID0gbmV3IGMobm9vcCk7CgogICAgICAgICAgaWYgKHN1Y2NlZWRlZCA9PT0gZmFsc2UpIHsKICAgICAgICAgICAgcmVqZWN0KHByb21pc2UsIGVycm9yKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGhhbmRsZU1heWJlVGhlbmFibGUocHJvbWlzZSwgZW50cnksIHRoZW4kJDEpOwoKICAgICAgICAgICAgdGhpcy5fd2lsbFNldHRsZUF0KHByb21pc2UsIGksIGZpcnN0UGFzcyk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuX3dpbGxTZXR0bGVBdChuZXcgYyhmdW5jdGlvbiAocmVzb2x2ZSkgewogICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShlbnRyeSk7CiAgICAgICAgICB9KSwgaSwgZmlyc3RQYXNzKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fd2lsbFNldHRsZUF0KGMucmVzb2x2ZShlbnRyeSksIGksIGZpcnN0UGFzcyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9lYWNoRW50cnkgPSBmdW5jdGlvbiBfZWFjaEVudHJ5KGVudHJ5LCBpLCBmaXJzdFBhc3MpIHsKICAgICAgaWYgKGVudHJ5ICE9PSBudWxsICYmIHR5cGVvZiBlbnRyeSA9PT0gJ29iamVjdCcpIHsKICAgICAgICB0aGlzLl9zZXR0bGVNYXliZVRoZW5hYmxlKGVudHJ5LCBpLCBmaXJzdFBhc3MpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuX3NldFJlc3VsdEF0KEZVTEZJTExFRCwgaSwgZW50cnksIGZpcnN0UGFzcyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9zZXR0bGVkQXQgPSBmdW5jdGlvbiBfc2V0dGxlZEF0KHN0YXRlLCBpLCB2YWx1ZSwgZmlyc3RQYXNzKSB7CiAgICAgIHZhciBwcm9taXNlID0gdGhpcy5wcm9taXNlOwoKICAgICAgaWYgKHByb21pc2UuX3N0YXRlID09PSBQRU5ESU5HKSB7CiAgICAgICAgaWYgKHRoaXMuX2Fib3J0T25SZWplY3QgJiYgc3RhdGUgPT09IFJFSkVDVEVEKSB7CiAgICAgICAgICByZWplY3QocHJvbWlzZSwgdmFsdWUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9zZXRSZXN1bHRBdChzdGF0ZSwgaSwgdmFsdWUsIGZpcnN0UGFzcyk7CgogICAgICAgICAgdGhpcy5fY2hlY2tGdWxsZmlsbG1lbnQoKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9zZXRSZXN1bHRBdCA9IGZ1bmN0aW9uIF9zZXRSZXN1bHRBdChzdGF0ZSwgaSwgdmFsdWUsIGZpcnN0UGFzcykgewogICAgICB0aGlzLl9yZW1haW5pbmctLTsKICAgICAgdGhpcy5fcmVzdWx0W2ldID0gdmFsdWU7CiAgICB9OwoKICAgIF9wcm90by5fd2lsbFNldHRsZUF0ID0gZnVuY3Rpb24gX3dpbGxTZXR0bGVBdChwcm9taXNlLCBpLCBmaXJzdFBhc3MpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHN1YnNjcmliZShwcm9taXNlLCB1bmRlZmluZWQsIGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgIHJldHVybiBfdGhpcy5fc2V0dGxlZEF0KEZVTEZJTExFRCwgaSwgdmFsdWUsIGZpcnN0UGFzcyk7CiAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICByZXR1cm4gX3RoaXMuX3NldHRsZWRBdChSRUpFQ1RFRCwgaSwgcmVhc29uLCBmaXJzdFBhc3MpOwogICAgICB9KTsKICAgIH07CgogICAgcmV0dXJuIEVudW1lcmF0b3I7CiAgfSgpOwoKICBmdW5jdGlvbiBzZXRTZXR0bGVkUmVzdWx0KHN0YXRlLCBpLCB2YWx1ZSkgewogICAgdGhpcy5fcmVtYWluaW5nLS07CgogICAgaWYgKHN0YXRlID09PSBGVUxGSUxMRUQpIHsKICAgICAgdGhpcy5fcmVzdWx0W2ldID0gewogICAgICAgIHN0YXRlOiAnZnVsZmlsbGVkJywKICAgICAgICB2YWx1ZTogdmFsdWUKICAgICAgfTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuX3Jlc3VsdFtpXSA9IHsKICAgICAgICBzdGF0ZTogJ3JlamVjdGVkJywKICAgICAgICByZWFzb246IHZhbHVlCiAgICAgIH07CiAgICB9CiAgfQogIC8qKgogICAgYFByb21pc2UuYWxsYCBhY2NlcHRzIGFuIGFycmF5IG9mIHByb21pc2VzLCBhbmQgcmV0dXJucyBhIG5ldyBwcm9taXNlIHdoaWNoCiAgICBpcyBmdWxmaWxsZWQgd2l0aCBhbiBhcnJheSBvZiBmdWxmaWxsbWVudCB2YWx1ZXMgZm9yIHRoZSBwYXNzZWQgcHJvbWlzZXMsIG9yCiAgICByZWplY3RlZCB3aXRoIHRoZSByZWFzb24gb2YgdGhlIGZpcnN0IHBhc3NlZCBwcm9taXNlIHRvIGJlIHJlamVjdGVkLiBJdCBjYXN0cyBhbGwKICAgIGVsZW1lbnRzIG9mIHRoZSBwYXNzZWQgaXRlcmFibGUgdG8gcHJvbWlzZXMgYXMgaXQgcnVucyB0aGlzIGFsZ29yaXRobS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSwgeyByZXNvbHZlIH0gZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgcHJvbWlzZTEgPSByZXNvbHZlKDEpOwogICAgbGV0IHByb21pc2UyID0gcmVzb2x2ZSgyKTsKICAgIGxldCBwcm9taXNlMyA9IHJlc29sdmUoMyk7CiAgICBsZXQgcHJvbWlzZXMgPSBbIHByb21pc2UxLCBwcm9taXNlMiwgcHJvbWlzZTMgXTsKICAKICAgIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKGZ1bmN0aW9uKGFycmF5KXsKICAgICAgLy8gVGhlIGFycmF5IGhlcmUgd291bGQgYmUgWyAxLCAyLCAzIF07CiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgYW55IG9mIHRoZSBgcHJvbWlzZXNgIGdpdmVuIHRvIGBSU1ZQLmFsbGAgYXJlIHJlamVjdGVkLCB0aGUgZmlyc3QgcHJvbWlzZQogICAgdGhhdCBpcyByZWplY3RlZCB3aWxsIGJlIGdpdmVuIGFzIGFuIGFyZ3VtZW50IHRvIHRoZSByZXR1cm5lZCBwcm9taXNlcydzCiAgICByZWplY3Rpb24gaGFuZGxlci4gRm9yIGV4YW1wbGU6CiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IFByb21pc2UsIHsgcmVzb2x2ZSwgcmVqZWN0IH0gZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgcHJvbWlzZTEgPSByZXNvbHZlKDEpOwogICAgbGV0IHByb21pc2UyID0gcmVqZWN0KG5ldyBFcnJvcigiMiIpKTsKICAgIGxldCBwcm9taXNlMyA9IHJlamVjdChuZXcgRXJyb3IoIjMiKSk7CiAgICBsZXQgcHJvbWlzZXMgPSBbIHByb21pc2UxLCBwcm9taXNlMiwgcHJvbWlzZTMgXTsKICAKICAgIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKGZ1bmN0aW9uKGFycmF5KXsKICAgICAgLy8gQ29kZSBoZXJlIG5ldmVyIHJ1bnMgYmVjYXVzZSB0aGVyZSBhcmUgcmVqZWN0ZWQgcHJvbWlzZXMhCiAgICB9LCBmdW5jdGlvbihlcnJvcikgewogICAgICAvLyBlcnJvci5tZXNzYWdlID09PSAiMiIKICAgIH0pOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGFsbAogICAgQGZvciBQcm9taXNlCiAgICBAcGFyYW0ge0FycmF5fSBlbnRyaWVzIGFycmF5IG9mIHByb21pc2VzCiAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCB3aGVuIGFsbCBgcHJvbWlzZXNgIGhhdmUgYmVlbgogICAgZnVsZmlsbGVkLCBvciByZWplY3RlZCBpZiBhbnkgb2YgdGhlbSBiZWNvbWUgcmVqZWN0ZWQuCiAgICBAc3RhdGljCiAgKi8KCgogIGZ1bmN0aW9uIGFsbChlbnRyaWVzLCBsYWJlbCkgewogICAgaWYgKCFBcnJheS5pc0FycmF5KGVudHJpZXMpKSB7CiAgICAgIHJldHVybiB0aGlzLnJlamVjdChuZXcgVHlwZUVycm9yKCJQcm9taXNlLmFsbCBtdXN0IGJlIGNhbGxlZCB3aXRoIGFuIGFycmF5IiksIGxhYmVsKTsKICAgIH0KCiAgICByZXR1cm4gbmV3IEVudW1lcmF0b3IodGhpcywgZW50cmllcywgdHJ1ZQogICAgLyogYWJvcnQgb24gcmVqZWN0ICovCiAgICAsIGxhYmVsKS5wcm9taXNlOwogIH0KICAvKioKICAgIGBQcm9taXNlLnJhY2VgIHJldHVybnMgYSBuZXcgcHJvbWlzZSB3aGljaCBpcyBzZXR0bGVkIGluIHRoZSBzYW1lIHdheSBhcyB0aGUKICAgIGZpcnN0IHBhc3NlZCBwcm9taXNlIHRvIHNldHRsZS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlMSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7CiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKXsKICAgICAgICByZXNvbHZlKCdwcm9taXNlIDEnKTsKICAgICAgfSwgMjAwKTsKICAgIH0pOwogIAogICAgbGV0IHByb21pc2UyID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXsKICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpewogICAgICAgIHJlc29sdmUoJ3Byb21pc2UgMicpOwogICAgICB9LCAxMDApOwogICAgfSk7CiAgCiAgICBQcm9taXNlLnJhY2UoW3Byb21pc2UxLCBwcm9taXNlMl0pLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXsKICAgICAgLy8gcmVzdWx0ID09PSAncHJvbWlzZSAyJyBiZWNhdXNlIGl0IHdhcyByZXNvbHZlZCBiZWZvcmUgcHJvbWlzZTEKICAgICAgLy8gd2FzIHJlc29sdmVkLgogICAgfSk7CiAgICBgYGAKICAKICAgIGBQcm9taXNlLnJhY2VgIGlzIGRldGVybWluaXN0aWMgaW4gdGhhdCBvbmx5IHRoZSBzdGF0ZSBvZiB0aGUgZmlyc3QKICAgIHNldHRsZWQgcHJvbWlzZSBtYXR0ZXJzLiBGb3IgZXhhbXBsZSwgZXZlbiBpZiBvdGhlciBwcm9taXNlcyBnaXZlbiB0byB0aGUKICAgIGBwcm9taXNlc2AgYXJyYXkgYXJndW1lbnQgYXJlIHJlc29sdmVkLCBidXQgdGhlIGZpcnN0IHNldHRsZWQgcHJvbWlzZSBoYXMKICAgIGJlY29tZSByZWplY3RlZCBiZWZvcmUgdGhlIG90aGVyIHByb21pc2VzIGJlY2FtZSBmdWxmaWxsZWQsIHRoZSByZXR1cm5lZAogICAgcHJvbWlzZSB3aWxsIGJlY29tZSByZWplY3RlZDoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBQcm9taXNlIGZyb20gJ3JzdnAnOwogIAogICAgbGV0IHByb21pc2UxID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXsKICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpewogICAgICAgIHJlc29sdmUoJ3Byb21pc2UgMScpOwogICAgICB9LCAyMDApOwogICAgfSk7CiAgCiAgICBsZXQgcHJvbWlzZTIgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpewogICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7CiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcigncHJvbWlzZSAyJykpOwogICAgICB9LCAxMDApOwogICAgfSk7CiAgCiAgICBQcm9taXNlLnJhY2UoW3Byb21pc2UxLCBwcm9taXNlMl0pLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXsKICAgICAgLy8gQ29kZSBoZXJlIG5ldmVyIHJ1bnMKICAgIH0sIGZ1bmN0aW9uKHJlYXNvbil7CiAgICAgIC8vIHJlYXNvbi5tZXNzYWdlID09PSAncHJvbWlzZSAyJyBiZWNhdXNlIHByb21pc2UgMiBiZWNhbWUgcmVqZWN0ZWQgYmVmb3JlCiAgICAgIC8vIHByb21pc2UgMSBiZWNhbWUgZnVsZmlsbGVkCiAgICB9KTsKICAgIGBgYAogIAogICAgQW4gZXhhbXBsZSByZWFsLXdvcmxkIHVzZSBjYXNlIGlzIGltcGxlbWVudGluZyB0aW1lb3V0czoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBQcm9taXNlIGZyb20gJ3JzdnAnOwogIAogICAgUHJvbWlzZS5yYWNlKFthamF4KCdmb28uanNvbicpLCB0aW1lb3V0KDUwMDApXSkKICAgIGBgYAogIAogICAgQG1ldGhvZCByYWNlCiAgICBAZm9yIFByb21pc2UKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7QXJyYXl9IGVudHJpZXMgYXJyYXkgb2YgcHJvbWlzZXMgdG8gb2JzZXJ2ZQogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGZvciBkZXNjcmliaW5nIHRoZSBwcm9taXNlIHJldHVybmVkLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHdoaWNoIHNldHRsZXMgaW4gdGhlIHNhbWUgd2F5IGFzIHRoZSBmaXJzdCBwYXNzZWQKICAgIHByb21pc2UgdG8gc2V0dGxlLgogICovCgoKICBmdW5jdGlvbiByYWNlKGVudHJpZXMsIGxhYmVsKSB7CiAgICAvKmpzaGludCB2YWxpZHRoaXM6dHJ1ZSAqLwogICAgdmFyIENvbnN0cnVjdG9yID0gdGhpczsKICAgIHZhciBwcm9taXNlID0gbmV3IENvbnN0cnVjdG9yKG5vb3AsIGxhYmVsKTsKCiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZW50cmllcykpIHsKICAgICAgcmVqZWN0KHByb21pc2UsIG5ldyBUeXBlRXJyb3IoJ1Byb21pc2UucmFjZSBtdXN0IGJlIGNhbGxlZCB3aXRoIGFuIGFycmF5JykpOwogICAgICByZXR1cm4gcHJvbWlzZTsKICAgIH0KCiAgICBmb3IgKHZhciBpID0gMDsgcHJvbWlzZS5fc3RhdGUgPT09IFBFTkRJTkcgJiYgaSA8IGVudHJpZXMubGVuZ3RoOyBpKyspIHsKICAgICAgc3Vic2NyaWJlKENvbnN0cnVjdG9yLnJlc29sdmUoZW50cmllc1tpXSksIHVuZGVmaW5lZCwgZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHJlc29sdmUkMShwcm9taXNlLCB2YWx1ZSk7CiAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICByZXR1cm4gcmVqZWN0KHByb21pc2UsIHJlYXNvbik7CiAgICAgIH0pOwogICAgfQoKICAgIHJldHVybiBwcm9taXNlOwogIH0KICAvKioKICAgIGBQcm9taXNlLnJlamVjdGAgcmV0dXJucyBhIHByb21pc2UgcmVqZWN0ZWQgd2l0aCB0aGUgcGFzc2VkIGByZWFzb25gLgogICAgSXQgaXMgc2hvcnRoYW5kIGZvciB0aGUgZm9sbG93aW5nOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IFByb21pc2UgZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7CiAgICAgIHJlamVjdChuZXcgRXJyb3IoJ1dIT09QUycpKTsKICAgIH0pOwogIAogICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXsKICAgICAgLy8gQ29kZSBoZXJlIGRvZXNuJ3QgcnVuIGJlY2F1c2UgdGhlIHByb21pc2UgaXMgcmVqZWN0ZWQhCiAgICB9LCBmdW5jdGlvbihyZWFzb24pewogICAgICAvLyByZWFzb24ubWVzc2FnZSA9PT0gJ1dIT09QUycKICAgIH0pOwogICAgYGBgCiAgCiAgICBJbnN0ZWFkIG9mIHdyaXRpbmcgdGhlIGFib3ZlLCB5b3VyIGNvZGUgbm93IHNpbXBseSBiZWNvbWVzIHRoZSBmb2xsb3dpbmc6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlID0gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdXSE9PUFMnKSk7CiAgCiAgICBwcm9taXNlLnRoZW4oZnVuY3Rpb24odmFsdWUpewogICAgICAvLyBDb2RlIGhlcmUgZG9lc24ndCBydW4gYmVjYXVzZSB0aGUgcHJvbWlzZSBpcyByZWplY3RlZCEKICAgIH0sIGZ1bmN0aW9uKHJlYXNvbil7CiAgICAgIC8vIHJlYXNvbi5tZXNzYWdlID09PSAnV0hPT1BTJwogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgcmVqZWN0CiAgICBAZm9yIFByb21pc2UKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7Kn0gcmVhc29uIHZhbHVlIHRoYXQgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoLgogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGZvciBpZGVudGlmeWluZyB0aGUgcmV0dXJuZWQgcHJvbWlzZS4KICAgIFVzZWZ1bCBmb3IgdG9vbGluZy4KICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSByZWplY3RlZCB3aXRoIHRoZSBnaXZlbiBgcmVhc29uYC4KICAqLwoKCiAgZnVuY3Rpb24gcmVqZWN0JDEocmVhc29uLCBsYWJlbCkgewogICAgLypqc2hpbnQgdmFsaWR0aGlzOnRydWUgKi8KICAgIHZhciBDb25zdHJ1Y3RvciA9IHRoaXM7CiAgICB2YXIgcHJvbWlzZSA9IG5ldyBDb25zdHJ1Y3Rvcihub29wLCBsYWJlbCk7CiAgICByZWplY3QocHJvbWlzZSwgcmVhc29uKTsKICAgIHJldHVybiBwcm9taXNlOwogIH0KCiAgdmFyIGd1aWRLZXkgPSAncnN2cF8nICsgRGF0ZS5ub3coKSArICctJzsKICB2YXIgY291bnRlciA9IDA7CgogIGZ1bmN0aW9uIG5lZWRzUmVzb2x2ZXIoKSB7CiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdZb3UgbXVzdCBwYXNzIGEgcmVzb2x2ZXIgZnVuY3Rpb24gYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHRvIHRoZSBwcm9taXNlIGNvbnN0cnVjdG9yJyk7CiAgfQoKICBmdW5jdGlvbiBuZWVkc05ldygpIHsKICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIkZhaWxlZCB0byBjb25zdHJ1Y3QgJ1Byb21pc2UnOiBQbGVhc2UgdXNlIHRoZSAnbmV3JyBvcGVyYXRvciwgdGhpcyBvYmplY3QgY29uc3RydWN0b3IgY2Fubm90IGJlIGNhbGxlZCBhcyBhIGZ1bmN0aW9uLiIpOwogIH0KICAvKioKICAgIFByb21pc2Ugb2JqZWN0cyByZXByZXNlbnQgdGhlIGV2ZW50dWFsIHJlc3VsdCBvZiBhbiBhc3luY2hyb25vdXMgb3BlcmF0aW9uLiBUaGUKICAgIHByaW1hcnkgd2F5IG9mIGludGVyYWN0aW5nIHdpdGggYSBwcm9taXNlIGlzIHRocm91Z2ggaXRzIGB0aGVuYCBtZXRob2QsIHdoaWNoCiAgICByZWdpc3RlcnMgY2FsbGJhY2tzIHRvIHJlY2VpdmUgZWl0aGVyIGEgcHJvbWlzZeKAmXMgZXZlbnR1YWwgdmFsdWUgb3IgdGhlIHJlYXNvbgogICAgd2h5IHRoZSBwcm9taXNlIGNhbm5vdCBiZSBmdWxmaWxsZWQuCiAgCiAgICBUZXJtaW5vbG9neQogICAgLS0tLS0tLS0tLS0KICAKICAgIC0gYHByb21pc2VgIGlzIGFuIG9iamVjdCBvciBmdW5jdGlvbiB3aXRoIGEgYHRoZW5gIG1ldGhvZCB3aG9zZSBiZWhhdmlvciBjb25mb3JtcyB0byB0aGlzIHNwZWNpZmljYXRpb24uCiAgICAtIGB0aGVuYWJsZWAgaXMgYW4gb2JqZWN0IG9yIGZ1bmN0aW9uIHRoYXQgZGVmaW5lcyBhIGB0aGVuYCBtZXRob2QuCiAgICAtIGB2YWx1ZWAgaXMgYW55IGxlZ2FsIEphdmFTY3JpcHQgdmFsdWUgKGluY2x1ZGluZyB1bmRlZmluZWQsIGEgdGhlbmFibGUsIG9yIGEgcHJvbWlzZSkuCiAgICAtIGBleGNlcHRpb25gIGlzIGEgdmFsdWUgdGhhdCBpcyB0aHJvd24gdXNpbmcgdGhlIHRocm93IHN0YXRlbWVudC4KICAgIC0gYHJlYXNvbmAgaXMgYSB2YWx1ZSB0aGF0IGluZGljYXRlcyB3aHkgYSBwcm9taXNlIHdhcyByZWplY3RlZC4KICAgIC0gYHNldHRsZWRgIHRoZSBmaW5hbCByZXN0aW5nIHN0YXRlIG9mIGEgcHJvbWlzZSwgZnVsZmlsbGVkIG9yIHJlamVjdGVkLgogIAogICAgQSBwcm9taXNlIGNhbiBiZSBpbiBvbmUgb2YgdGhyZWUgc3RhdGVzOiBwZW5kaW5nLCBmdWxmaWxsZWQsIG9yIHJlamVjdGVkLgogIAogICAgUHJvbWlzZXMgdGhhdCBhcmUgZnVsZmlsbGVkIGhhdmUgYSBmdWxmaWxsbWVudCB2YWx1ZSBhbmQgYXJlIGluIHRoZSBmdWxmaWxsZWQKICAgIHN0YXRlLiAgUHJvbWlzZXMgdGhhdCBhcmUgcmVqZWN0ZWQgaGF2ZSBhIHJlamVjdGlvbiByZWFzb24gYW5kIGFyZSBpbiB0aGUKICAgIHJlamVjdGVkIHN0YXRlLiAgQSBmdWxmaWxsbWVudCB2YWx1ZSBpcyBuZXZlciBhIHRoZW5hYmxlLgogIAogICAgUHJvbWlzZXMgY2FuIGFsc28gYmUgc2FpZCB0byAqcmVzb2x2ZSogYSB2YWx1ZS4gIElmIHRoaXMgdmFsdWUgaXMgYWxzbyBhCiAgICBwcm9taXNlLCB0aGVuIHRoZSBvcmlnaW5hbCBwcm9taXNlJ3Mgc2V0dGxlZCBzdGF0ZSB3aWxsIG1hdGNoIHRoZSB2YWx1ZSdzCiAgICBzZXR0bGVkIHN0YXRlLiAgU28gYSBwcm9taXNlIHRoYXQgKnJlc29sdmVzKiBhIHByb21pc2UgdGhhdCByZWplY3RzIHdpbGwKICAgIGl0c2VsZiByZWplY3QsIGFuZCBhIHByb21pc2UgdGhhdCAqcmVzb2x2ZXMqIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIHdpbGwKICAgIGl0c2VsZiBmdWxmaWxsLgogIAogIAogICAgQmFzaWMgVXNhZ2U6CiAgICAtLS0tLS0tLS0tLS0KICAKICAgIGBgYGpzCiAgICBsZXQgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkgewogICAgICAvLyBvbiBzdWNjZXNzCiAgICAgIHJlc29sdmUodmFsdWUpOwogIAogICAgICAvLyBvbiBmYWlsdXJlCiAgICAgIHJlamVjdChyZWFzb24pOwogICAgfSk7CiAgCiAgICBwcm9taXNlLnRoZW4oZnVuY3Rpb24odmFsdWUpIHsKICAgICAgLy8gb24gZnVsZmlsbG1lbnQKICAgIH0sIGZ1bmN0aW9uKHJlYXNvbikgewogICAgICAvLyBvbiByZWplY3Rpb24KICAgIH0pOwogICAgYGBgCiAgCiAgICBBZHZhbmNlZCBVc2FnZToKICAgIC0tLS0tLS0tLS0tLS0tLQogIAogICAgUHJvbWlzZXMgc2hpbmUgd2hlbiBhYnN0cmFjdGluZyBhd2F5IGFzeW5jaHJvbm91cyBpbnRlcmFjdGlvbnMgc3VjaCBhcwogICAgYFhNTEh0dHBSZXF1ZXN0YHMuCiAgCiAgICBgYGBqcwogICAgZnVuY3Rpb24gZ2V0SlNPTih1cmwpIHsKICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7CiAgICAgICAgbGV0IHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpOwogIAogICAgICAgIHhoci5vcGVuKCdHRVQnLCB1cmwpOwogICAgICAgIHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBoYW5kbGVyOwogICAgICAgIHhoci5yZXNwb25zZVR5cGUgPSAnanNvbic7CiAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoJ0FjY2VwdCcsICdhcHBsaWNhdGlvbi9qc29uJyk7CiAgICAgICAgeGhyLnNlbmQoKTsKICAKICAgICAgICBmdW5jdGlvbiBoYW5kbGVyKCkgewogICAgICAgICAgaWYgKHRoaXMucmVhZHlTdGF0ZSA9PT0gdGhpcy5ET05FKSB7CiAgICAgICAgICAgIGlmICh0aGlzLnN0YXR1cyA9PT0gMjAwKSB7CiAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLnJlc3BvbnNlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdnZXRKU09OOiBgJyArIHVybCArICdgIGZhaWxlZCB3aXRoIHN0YXR1czogWycgKyB0aGlzLnN0YXR1cyArICddJykpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgfSk7CiAgICB9CiAgCiAgICBnZXRKU09OKCcvcG9zdHMuanNvbicpLnRoZW4oZnVuY3Rpb24oanNvbikgewogICAgICAvLyBvbiBmdWxmaWxsbWVudAogICAgfSwgZnVuY3Rpb24ocmVhc29uKSB7CiAgICAgIC8vIG9uIHJlamVjdGlvbgogICAgfSk7CiAgICBgYGAKICAKICAgIFVubGlrZSBjYWxsYmFja3MsIHByb21pc2VzIGFyZSBncmVhdCBjb21wb3NhYmxlIHByaW1pdGl2ZXMuCiAgCiAgICBgYGBqcwogICAgUHJvbWlzZS5hbGwoWwogICAgICBnZXRKU09OKCcvcG9zdHMnKSwKICAgICAgZ2V0SlNPTignL2NvbW1lbnRzJykKICAgIF0pLnRoZW4oZnVuY3Rpb24odmFsdWVzKXsKICAgICAgdmFsdWVzWzBdIC8vID0+IHBvc3RzSlNPTgogICAgICB2YWx1ZXNbMV0gLy8gPT4gY29tbWVudHNKU09OCiAgCiAgICAgIHJldHVybiB2YWx1ZXM7CiAgICB9KTsKICAgIGBgYAogIAogICAgQGNsYXNzIFByb21pc2UKICAgIEBwdWJsaWMKICAgIEBwYXJhbSB7ZnVuY3Rpb259IHJlc29sdmVyCiAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQGNvbnN0cnVjdG9yCiAgKi8KCgogIHZhciBQcm9taXNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUHJvbWlzZShyZXNvbHZlciwgbGFiZWwpIHsKICAgICAgdGhpcy5faWQgPSBjb3VudGVyKys7CiAgICAgIHRoaXMuX2xhYmVsID0gbGFiZWw7CiAgICAgIHRoaXMuX3N0YXRlID0gdW5kZWZpbmVkOwogICAgICB0aGlzLl9yZXN1bHQgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuX3N1YnNjcmliZXJzID0gW107CiAgICAgIGNvbmZpZy5pbnN0cnVtZW50ICYmIGluc3RydW1lbnQoJ2NyZWF0ZWQnLCB0aGlzKTsKCiAgICAgIGlmIChub29wICE9PSByZXNvbHZlcikgewogICAgICAgIHR5cGVvZiByZXNvbHZlciAhPT0gJ2Z1bmN0aW9uJyAmJiBuZWVkc1Jlc29sdmVyKCk7CiAgICAgICAgdGhpcyBpbnN0YW5jZW9mIFByb21pc2UgPyBpbml0aWFsaXplUHJvbWlzZSh0aGlzLCByZXNvbHZlcikgOiBuZWVkc05ldygpOwogICAgICB9CiAgICB9CgogICAgdmFyIF9wcm90bzIgPSBQcm9taXNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yLl9vbkVycm9yID0gZnVuY3Rpb24gX29uRXJyb3IocmVhc29uKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgY29uZmlnLmFmdGVyKGZ1bmN0aW9uICgpIHsKICAgICAgICBpZiAoX3RoaXMyLl9vbkVycm9yKSB7CiAgICAgICAgICBjb25maWcudHJpZ2dlcignZXJyb3InLCByZWFzb24sIF90aGlzMi5fbGFiZWwpOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CiAgICAvKioKICAgICAgYGNhdGNoYCBpcyBzaW1wbHkgc3VnYXIgZm9yIGB0aGVuKHVuZGVmaW5lZCwgb25SZWplY3Rpb24pYCB3aGljaCBtYWtlcyBpdCB0aGUgc2FtZQogICAgICBhcyB0aGUgY2F0Y2ggYmxvY2sgb2YgYSB0cnkvY2F0Y2ggc3RhdGVtZW50LgogICAgCiAgICAgIGBgYGpzCiAgICAgIGZ1bmN0aW9uIGZpbmRBdXRob3IoKXsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkblwndCBmaW5kIHRoYXQgYXV0aG9yJyk7CiAgICAgIH0KICAgIAogICAgICAvLyBzeW5jaHJvbm91cwogICAgICB0cnkgewogICAgICAgIGZpbmRBdXRob3IoKTsKICAgICAgfSBjYXRjaChyZWFzb24pIHsKICAgICAgICAvLyBzb21ldGhpbmcgd2VudCB3cm9uZwogICAgICB9CiAgICAKICAgICAgLy8gYXN5bmMgd2l0aCBwcm9taXNlcwogICAgICBmaW5kQXV0aG9yKCkuY2F0Y2goZnVuY3Rpb24ocmVhc29uKXsKICAgICAgICAvLyBzb21ldGhpbmcgd2VudCB3cm9uZwogICAgICB9KTsKICAgICAgYGBgCiAgICAKICAgICAgQG1ldGhvZCBjYXRjaAogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGlvbgogICAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICAgIEByZXR1cm4ge1Byb21pc2V9CiAgICAqLwogICAgOwoKICAgIF9wcm90bzIuY2F0Y2ggPSBmdW5jdGlvbiBfY2F0Y2gob25SZWplY3Rpb24sIGxhYmVsKSB7CiAgICAgIHJldHVybiB0aGlzLnRoZW4odW5kZWZpbmVkLCBvblJlamVjdGlvbiwgbGFiZWwpOwogICAgfQogICAgLyoqCiAgICAgIGBmaW5hbGx5YCB3aWxsIGJlIGludm9rZWQgcmVnYXJkbGVzcyBvZiB0aGUgcHJvbWlzZSdzIGZhdGUganVzdCBhcyBuYXRpdmUKICAgICAgdHJ5L2NhdGNoL2ZpbmFsbHkgYmVoYXZlcwogICAgCiAgICAgIFN5bmNocm9ub3VzIGV4YW1wbGU6CiAgICAKICAgICAgYGBganMKICAgICAgZmluZEF1dGhvcigpIHsKICAgICAgICBpZiAoTWF0aC5yYW5kb20oKSA+IDAuNSkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgQXV0aG9yKCk7CiAgICAgIH0KICAgIAogICAgICB0cnkgewogICAgICAgIHJldHVybiBmaW5kQXV0aG9yKCk7IC8vIHN1Y2NlZWQgb3IgZmFpbAogICAgICB9IGNhdGNoKGVycm9yKSB7CiAgICAgICAgcmV0dXJuIGZpbmRPdGhlckF1dGhvcigpOwogICAgICB9IGZpbmFsbHkgewogICAgICAgIC8vIGFsd2F5cyBydW5zCiAgICAgICAgLy8gZG9lc24ndCBhZmZlY3QgdGhlIHJldHVybiB2YWx1ZQogICAgICB9CiAgICAgIGBgYAogICAgCiAgICAgIEFzeW5jaHJvbm91cyBleGFtcGxlOgogICAgCiAgICAgIGBgYGpzCiAgICAgIGZpbmRBdXRob3IoKS5jYXRjaChmdW5jdGlvbihyZWFzb24pewogICAgICAgIHJldHVybiBmaW5kT3RoZXJBdXRob3IoKTsKICAgICAgfSkuZmluYWxseShmdW5jdGlvbigpewogICAgICAgIC8vIGF1dGhvciB3YXMgZWl0aGVyIGZvdW5kLCBvciBub3QKICAgICAgfSk7CiAgICAgIGBgYAogICAgCiAgICAgIEBtZXRob2QgZmluYWxseQogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICAgIEByZXR1cm4ge1Byb21pc2V9CiAgICAqLwogICAgOwoKICAgIF9wcm90bzIuZmluYWxseSA9IGZ1bmN0aW9uIF9maW5hbGx5KGNhbGxiYWNrLCBsYWJlbCkgewogICAgICB2YXIgcHJvbWlzZSA9IHRoaXM7CiAgICAgIHZhciBjb25zdHJ1Y3RvciA9IHByb21pc2UuY29uc3RydWN0b3I7CgogICAgICBpZiAodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgICAgIHJldHVybiBjb25zdHJ1Y3Rvci5yZXNvbHZlKGNhbGxiYWNrKCkpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgICB9KTsKICAgICAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICByZXR1cm4gY29uc3RydWN0b3IucmVzb2x2ZShjYWxsYmFjaygpKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgdGhyb3cgcmVhc29uOwogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBwcm9taXNlLnRoZW4oY2FsbGJhY2ssIGNhbGxiYWNrKTsKICAgIH07CgogICAgcmV0dXJuIFByb21pc2U7CiAgfSgpOwoKICBfZXhwb3J0cy5Qcm9taXNlID0gUHJvbWlzZTsKICBQcm9taXNlLmNhc3QgPSByZXNvbHZlJCQxOyAvLyBkZXByZWNhdGVkCgogIFByb21pc2UuYWxsID0gYWxsOwogIFByb21pc2UucmFjZSA9IHJhY2U7CiAgUHJvbWlzZS5yZXNvbHZlID0gcmVzb2x2ZSQkMTsKICBQcm9taXNlLnJlamVjdCA9IHJlamVjdCQxOwogIFByb21pc2UucHJvdG90eXBlLl9ndWlkS2V5ID0gZ3VpZEtleTsKICAvKioKICAgIFRoZSBwcmltYXJ5IHdheSBvZiBpbnRlcmFjdGluZyB3aXRoIGEgcHJvbWlzZSBpcyB0aHJvdWdoIGl0cyBgdGhlbmAgbWV0aG9kLAogICAgd2hpY2ggcmVnaXN0ZXJzIGNhbGxiYWNrcyB0byByZWNlaXZlIGVpdGhlciBhIHByb21pc2UncyBldmVudHVhbCB2YWx1ZSBvciB0aGUKICAgIHJlYXNvbiB3aHkgdGhlIHByb21pc2UgY2Fubm90IGJlIGZ1bGZpbGxlZC4KICAKICAgIGBgYGpzCiAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24odXNlcil7CiAgICAgIC8vIHVzZXIgaXMgYXZhaWxhYmxlCiAgICB9LCBmdW5jdGlvbihyZWFzb24pewogICAgICAvLyB1c2VyIGlzIHVuYXZhaWxhYmxlLCBhbmQgeW91IGFyZSBnaXZlbiB0aGUgcmVhc29uIHdoeQogICAgfSk7CiAgICBgYGAKICAKICAgIENoYWluaW5nCiAgICAtLS0tLS0tLQogIAogICAgVGhlIHJldHVybiB2YWx1ZSBvZiBgdGhlbmAgaXMgaXRzZWxmIGEgcHJvbWlzZS4gIFRoaXMgc2Vjb25kLCAnZG93bnN0cmVhbScKICAgIHByb21pc2UgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBmaXJzdCBwcm9taXNlJ3MgZnVsZmlsbG1lbnQKICAgIG9yIHJlamVjdGlvbiBoYW5kbGVyLCBvciByZWplY3RlZCBpZiB0aGUgaGFuZGxlciB0aHJvd3MgYW4gZXhjZXB0aW9uLgogIAogICAgYGBganMKICAgIGZpbmRVc2VyKCkudGhlbihmdW5jdGlvbiAodXNlcikgewogICAgICByZXR1cm4gdXNlci5uYW1lOwogICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICByZXR1cm4gJ2RlZmF1bHQgbmFtZSc7CiAgICB9KS50aGVuKGZ1bmN0aW9uICh1c2VyTmFtZSkgewogICAgICAvLyBJZiBgZmluZFVzZXJgIGZ1bGZpbGxlZCwgYHVzZXJOYW1lYCB3aWxsIGJlIHRoZSB1c2VyJ3MgbmFtZSwgb3RoZXJ3aXNlIGl0CiAgICAgIC8vIHdpbGwgYmUgYCdkZWZhdWx0IG5hbWUnYAogICAgfSk7CiAgCiAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24gKHVzZXIpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdGb3VuZCB1c2VyLCBidXQgc3RpbGwgdW5oYXBweScpOwogICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ2BmaW5kVXNlcmAgcmVqZWN0ZWQgYW5kIHdlXCdyZSB1bmhhcHB5Jyk7CiAgICB9KS50aGVuKGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAvLyBuZXZlciByZWFjaGVkCiAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgIC8vIGlmIGBmaW5kVXNlcmAgZnVsZmlsbGVkLCBgcmVhc29uYCB3aWxsIGJlICdGb3VuZCB1c2VyLCBidXQgc3RpbGwgdW5oYXBweScuCiAgICAgIC8vIElmIGBmaW5kVXNlcmAgcmVqZWN0ZWQsIGByZWFzb25gIHdpbGwgYmUgJ2BmaW5kVXNlcmAgcmVqZWN0ZWQgYW5kIHdlXCdyZSB1bmhhcHB5Jy4KICAgIH0pOwogICAgYGBgCiAgICBJZiB0aGUgZG93bnN0cmVhbSBwcm9taXNlIGRvZXMgbm90IHNwZWNpZnkgYSByZWplY3Rpb24gaGFuZGxlciwgcmVqZWN0aW9uIHJlYXNvbnMgd2lsbCBiZSBwcm9wYWdhdGVkIGZ1cnRoZXIgZG93bnN0cmVhbS4KICAKICAgIGBgYGpzCiAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24gKHVzZXIpIHsKICAgICAgdGhyb3cgbmV3IFBlZGFnb2dpY2FsRXhjZXB0aW9uKCdVcHN0cmVhbSBlcnJvcicpOwogICAgfSkudGhlbihmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgLy8gbmV2ZXIgcmVhY2hlZAogICAgfSkudGhlbihmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgLy8gbmV2ZXIgcmVhY2hlZAogICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAvLyBUaGUgYFBlZGdhZ29jaWFsRXhjZXB0aW9uYCBpcyBwcm9wYWdhdGVkIGFsbCB0aGUgd2F5IGRvd24gdG8gaGVyZQogICAgfSk7CiAgICBgYGAKICAKICAgIEFzc2ltaWxhdGlvbgogICAgLS0tLS0tLS0tLS0tCiAgCiAgICBTb21ldGltZXMgdGhlIHZhbHVlIHlvdSB3YW50IHRvIHByb3BhZ2F0ZSB0byBhIGRvd25zdHJlYW0gcHJvbWlzZSBjYW4gb25seSBiZQogICAgcmV0cmlldmVkIGFzeW5jaHJvbm91c2x5LiBUaGlzIGNhbiBiZSBhY2hpZXZlZCBieSByZXR1cm5pbmcgYSBwcm9taXNlIGluIHRoZQogICAgZnVsZmlsbG1lbnQgb3IgcmVqZWN0aW9uIGhhbmRsZXIuIFRoZSBkb3duc3RyZWFtIHByb21pc2Ugd2lsbCB0aGVuIGJlIHBlbmRpbmcKICAgIHVudGlsIHRoZSByZXR1cm5lZCBwcm9taXNlIGlzIHNldHRsZWQuIFRoaXMgaXMgY2FsbGVkICphc3NpbWlsYXRpb24qLgogIAogICAgYGBganMKICAgIGZpbmRVc2VyKCkudGhlbihmdW5jdGlvbiAodXNlcikgewogICAgICByZXR1cm4gZmluZENvbW1lbnRzQnlBdXRob3IodXNlcik7CiAgICB9KS50aGVuKGZ1bmN0aW9uIChjb21tZW50cykgewogICAgICAvLyBUaGUgdXNlcidzIGNvbW1lbnRzIGFyZSBub3cgYXZhaWxhYmxlCiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgdGhlIGFzc2ltbGlhdGVkIHByb21pc2UgcmVqZWN0cywgdGhlbiB0aGUgZG93bnN0cmVhbSBwcm9taXNlIHdpbGwgYWxzbyByZWplY3QuCiAgCiAgICBgYGBqcwogICAgZmluZFVzZXIoKS50aGVuKGZ1bmN0aW9uICh1c2VyKSB7CiAgICAgIHJldHVybiBmaW5kQ29tbWVudHNCeUF1dGhvcih1c2VyKTsKICAgIH0pLnRoZW4oZnVuY3Rpb24gKGNvbW1lbnRzKSB7CiAgICAgIC8vIElmIGBmaW5kQ29tbWVudHNCeUF1dGhvcmAgZnVsZmlsbHMsIHdlJ2xsIGhhdmUgdGhlIHZhbHVlIGhlcmUKICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgLy8gSWYgYGZpbmRDb21tZW50c0J5QXV0aG9yYCByZWplY3RzLCB3ZSdsbCBoYXZlIHRoZSByZWFzb24gaGVyZQogICAgfSk7CiAgICBgYGAKICAKICAgIFNpbXBsZSBFeGFtcGxlCiAgICAtLS0tLS0tLS0tLS0tLQogIAogICAgU3luY2hyb25vdXMgRXhhbXBsZQogIAogICAgYGBgamF2YXNjcmlwdAogICAgbGV0IHJlc3VsdDsKICAKICAgIHRyeSB7CiAgICAgIHJlc3VsdCA9IGZpbmRSZXN1bHQoKTsKICAgICAgLy8gc3VjY2VzcwogICAgfSBjYXRjaChyZWFzb24pIHsKICAgICAgLy8gZmFpbHVyZQogICAgfQogICAgYGBgCiAgCiAgICBFcnJiYWNrIEV4YW1wbGUKICAKICAgIGBgYGpzCiAgICBmaW5kUmVzdWx0KGZ1bmN0aW9uKHJlc3VsdCwgZXJyKXsKICAgICAgaWYgKGVycikgewogICAgICAgIC8vIGZhaWx1cmUKICAgICAgfSBlbHNlIHsKICAgICAgICAvLyBzdWNjZXNzCiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBQcm9taXNlIEV4YW1wbGU7CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBmaW5kUmVzdWx0KCkudGhlbihmdW5jdGlvbihyZXN1bHQpewogICAgICAvLyBzdWNjZXNzCiAgICB9LCBmdW5jdGlvbihyZWFzb24pewogICAgICAvLyBmYWlsdXJlCiAgICB9KTsKICAgIGBgYAogIAogICAgQWR2YW5jZWQgRXhhbXBsZQogICAgLS0tLS0tLS0tLS0tLS0KICAKICAgIFN5bmNocm9ub3VzIEV4YW1wbGUKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCBhdXRob3IsIGJvb2tzOwogIAogICAgdHJ5IHsKICAgICAgYXV0aG9yID0gZmluZEF1dGhvcigpOwogICAgICBib29rcyAgPSBmaW5kQm9va3NCeUF1dGhvcihhdXRob3IpOwogICAgICAvLyBzdWNjZXNzCiAgICB9IGNhdGNoKHJlYXNvbikgewogICAgICAvLyBmYWlsdXJlCiAgICB9CiAgICBgYGAKICAKICAgIEVycmJhY2sgRXhhbXBsZQogIAogICAgYGBganMKICAKICAgIGZ1bmN0aW9uIGZvdW5kQm9va3MoYm9va3MpIHsKICAKICAgIH0KICAKICAgIGZ1bmN0aW9uIGZhaWx1cmUocmVhc29uKSB7CiAgCiAgICB9CiAgCiAgICBmaW5kQXV0aG9yKGZ1bmN0aW9uKGF1dGhvciwgZXJyKXsKICAgICAgaWYgKGVycikgewogICAgICAgIGZhaWx1cmUoZXJyKTsKICAgICAgICAvLyBmYWlsdXJlCiAgICAgIH0gZWxzZSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGZpbmRCb29va3NCeUF1dGhvcihhdXRob3IsIGZ1bmN0aW9uKGJvb2tzLCBlcnIpIHsKICAgICAgICAgICAgaWYgKGVycikgewogICAgICAgICAgICAgIGZhaWx1cmUoZXJyKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgZm91bmRCb29rcyhib29rcyk7CiAgICAgICAgICAgICAgfSBjYXRjaChyZWFzb24pIHsKICAgICAgICAgICAgICAgIGZhaWx1cmUocmVhc29uKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0gY2F0Y2goZXJyb3IpIHsKICAgICAgICAgIGZhaWx1cmUoZXJyKTsKICAgICAgICB9CiAgICAgICAgLy8gc3VjY2VzcwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgUHJvbWlzZSBFeGFtcGxlOwogIAogICAgYGBgamF2YXNjcmlwdAogICAgZmluZEF1dGhvcigpLgogICAgICB0aGVuKGZpbmRCb29rc0J5QXV0aG9yKS4KICAgICAgdGhlbihmdW5jdGlvbihib29rcyl7CiAgICAgICAgLy8gZm91bmQgYm9va3MKICAgIH0pLmNhdGNoKGZ1bmN0aW9uKHJlYXNvbil7CiAgICAgIC8vIHNvbWV0aGluZyB3ZW50IHdyb25nCiAgICB9KTsKICAgIGBgYAogIAogICAgQG1ldGhvZCB0aGVuCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvbkZ1bGZpbGxtZW50CiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGlvbgogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGZvciBsYWJlbGluZyB0aGUgcHJvbWlzZS4KICAgIFVzZWZ1bCBmb3IgdG9vbGluZy4KICAgIEByZXR1cm4ge1Byb21pc2V9CiAgKi8KCiAgUHJvbWlzZS5wcm90b3R5cGUudGhlbiA9IHRoZW47CgogIGZ1bmN0aW9uIG1ha2VPYmplY3QoXywgYXJndW1lbnROYW1lcykgewogICAgdmFyIG9iaiA9IHt9OwogICAgdmFyIGxlbmd0aCA9IF8ubGVuZ3RoOwogICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkobGVuZ3RoKTsKCiAgICBmb3IgKHZhciB4ID0gMDsgeCA8IGxlbmd0aDsgeCsrKSB7CiAgICAgIGFyZ3NbeF0gPSBfW3hdOwogICAgfQoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnROYW1lcy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgbmFtZSA9IGFyZ3VtZW50TmFtZXNbaV07CiAgICAgIG9ialtuYW1lXSA9IGFyZ3NbaSArIDFdOwogICAgfQoKICAgIHJldHVybiBvYmo7CiAgfQoKICBmdW5jdGlvbiBhcnJheVJlc3VsdChfKSB7CiAgICB2YXIgbGVuZ3RoID0gXy5sZW5ndGg7CiAgICB2YXIgYXJncyA9IG5ldyBBcnJheShsZW5ndGggLSAxKTsKCiAgICBmb3IgKHZhciBpID0gMTsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIGFyZ3NbaSAtIDFdID0gX1tpXTsKICAgIH0KCiAgICByZXR1cm4gYXJnczsKICB9CgogIGZ1bmN0aW9uIHdyYXBUaGVuYWJsZShfdGhlbiwgcHJvbWlzZSkgewogICAgcmV0dXJuIHsKICAgICAgdGhlbjogZnVuY3Rpb24gdGhlbihvbkZ1bEZpbGxtZW50LCBvblJlamVjdGlvbikgewogICAgICAgIHJldHVybiBfdGhlbi5jYWxsKHByb21pc2UsIG9uRnVsRmlsbG1lbnQsIG9uUmVqZWN0aW9uKTsKICAgICAgfQogICAgfTsKICB9CiAgLyoqCiAgICBgZGVub2RlaWZ5YCB0YWtlcyBhICdub2RlLXN0eWxlJyBmdW5jdGlvbiBhbmQgcmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQKICAgIHdpbGwgcmV0dXJuIGFuIGBQcm9taXNlYC4gWW91IGNhbiB1c2UgYGRlbm9kZWlmeWAgaW4gTm9kZS5qcyBvciB0aGUKICAgIGJyb3dzZXIgd2hlbiB5b3UnZCBwcmVmZXIgdG8gdXNlIHByb21pc2VzIG92ZXIgdXNpbmcgY2FsbGJhY2tzLiBGb3IgZXhhbXBsZSwKICAgIGBkZW5vZGVpZnlgIHRyYW5zZm9ybXMgdGhlIGZvbGxvd2luZzoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCBmcyA9IHJlcXVpcmUoJ2ZzJyk7CiAgCiAgICBmcy5yZWFkRmlsZSgnbXlmaWxlLnR4dCcsIGZ1bmN0aW9uKGVyciwgZGF0YSl7CiAgICAgIGlmIChlcnIpIHJldHVybiBoYW5kbGVFcnJvcihlcnIpOwogICAgICBoYW5kbGVEYXRhKGRhdGEpOwogICAgfSk7CiAgICBgYGAKICAKICAgIGludG86CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBsZXQgZnMgPSByZXF1aXJlKCdmcycpOwogICAgbGV0IHJlYWRGaWxlID0gZGVub2RlaWZ5KGZzLnJlYWRGaWxlKTsKICAKICAgIHJlYWRGaWxlKCdteWZpbGUudHh0JykudGhlbihoYW5kbGVEYXRhLCBoYW5kbGVFcnJvcik7CiAgICBgYGAKICAKICAgIElmIHRoZSBub2RlIGZ1bmN0aW9uIGhhcyBtdWx0aXBsZSBzdWNjZXNzIHBhcmFtZXRlcnMsIHRoZW4gYGRlbm9kZWlmeWAKICAgIGp1c3QgcmV0dXJucyB0aGUgZmlyc3Qgb25lOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgbGV0IHJlcXVlc3QgPSBkZW5vZGVpZnkocmVxdWlyZSgncmVxdWVzdCcpKTsKICAKICAgIHJlcXVlc3QoJ2h0dHA6Ly9leGFtcGxlLmNvbScpLnRoZW4oZnVuY3Rpb24ocmVzKSB7CiAgICAgIC8vIC4uLgogICAgfSk7CiAgICBgYGAKICAKICAgIEhvd2V2ZXIsIGlmIHlvdSBuZWVkIGFsbCBzdWNjZXNzIHBhcmFtZXRlcnMsIHNldHRpbmcgYGRlbm9kZWlmeWAncwogICAgc2Vjb25kIHBhcmFtZXRlciB0byBgdHJ1ZWAgY2F1c2VzIGl0IHRvIHJldHVybiBhbGwgc3VjY2VzcyBwYXJhbWV0ZXJzCiAgICBhcyBhbiBhcnJheToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCByZXF1ZXN0ID0gZGVub2RlaWZ5KHJlcXVpcmUoJ3JlcXVlc3QnKSwgdHJ1ZSk7CiAgCiAgICByZXF1ZXN0KCdodHRwOi8vZXhhbXBsZS5jb20nKS50aGVuKGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAvLyByZXN1bHRbMF0gLT4gcmVzCiAgICAgIC8vIHJlc3VsdFsxXSAtPiBib2R5CiAgICB9KTsKICAgIGBgYAogIAogICAgT3IgaWYgeW91IHBhc3MgaXQgYW4gYXJyYXkgd2l0aCBuYW1lcyBpdCByZXR1cm5zIHRoZSBwYXJhbWV0ZXJzIGFzIGEgaGFzaDoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCByZXF1ZXN0ID0gZGVub2RlaWZ5KHJlcXVpcmUoJ3JlcXVlc3QnKSwgWydyZXMnLCAnYm9keSddKTsKICAKICAgIHJlcXVlc3QoJ2h0dHA6Ly9leGFtcGxlLmNvbScpLnRoZW4oZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgIC8vIHJlc3VsdC5yZXMKICAgICAgLy8gcmVzdWx0LmJvZHkKICAgIH0pOwogICAgYGBgCiAgCiAgICBTb21ldGltZXMgeW91IG5lZWQgdG8gcmV0YWluIHRoZSBgdGhpc2A6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBsZXQgYXBwID0gcmVxdWlyZSgnZXhwcmVzcycpKCk7CiAgICBsZXQgcmVuZGVyID0gZGVub2RlaWZ5KGFwcC5yZW5kZXIuYmluZChhcHApKTsKICAgIGBgYAogIAogICAgVGhlIGRlbm9kaWZpZWQgZnVuY3Rpb24gaW5oZXJpdHMgZnJvbSB0aGUgb3JpZ2luYWwgZnVuY3Rpb24uIEl0IHdvcmtzIGluIGFsbAogICAgZW52aXJvbm1lbnRzLCBleGNlcHQgSUUgMTAgYW5kIGJlbG93LiBDb25zZXF1ZW50bHkgYWxsIHByb3BlcnRpZXMgb2YgdGhlIG9yaWdpbmFsCiAgICBmdW5jdGlvbiBhcmUgYXZhaWxhYmxlIHRvIHlvdS4gSG93ZXZlciwgYW55IHByb3BlcnRpZXMgeW91IGNoYW5nZSBvbiB0aGUKICAgIGRlbm9kZWlmaWVkIGZ1bmN0aW9uIHdvbid0IGJlIGNoYW5nZWQgb24gdGhlIG9yaWdpbmFsIGZ1bmN0aW9uLiBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgbGV0IHJlcXVlc3QgPSBkZW5vZGVpZnkocmVxdWlyZSgncmVxdWVzdCcpKSwKICAgICAgICBjb29raWVKYXIgPSByZXF1ZXN0LmphcigpOyAvLyA8LSBJbmhlcml0YW5jZSBpcyB1c2VkIGhlcmUKICAKICAgIHJlcXVlc3QoJ2h0dHA6Ly9leGFtcGxlLmNvbScsIHtqYXI6IGNvb2tpZUphcn0pLnRoZW4oZnVuY3Rpb24ocmVzKSB7CiAgICAgIC8vIGNvb2tpZUphci5jb29raWVzIGhvbGRzIG5vdyB0aGUgY29va2llcyByZXR1cm5lZCBieSBleGFtcGxlLmNvbQogICAgfSk7CiAgICBgYGAKICAKICAgIFVzaW5nIGBkZW5vZGVpZnlgIG1ha2VzIGl0IGVhc2llciB0byBjb21wb3NlIGFzeW5jaHJvbm91cyBvcGVyYXRpb25zIGluc3RlYWQKICAgIG9mIHVzaW5nIGNhbGxiYWNrcy4gRm9yIGV4YW1wbGUsIGluc3RlYWQgb2Y6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBsZXQgZnMgPSByZXF1aXJlKCdmcycpOwogIAogICAgZnMucmVhZEZpbGUoJ215ZmlsZS50eHQnLCBmdW5jdGlvbihlcnIsIGRhdGEpewogICAgICBpZiAoZXJyKSB7IC4uLiB9IC8vIEhhbmRsZSBlcnJvcgogICAgICBmcy53cml0ZUZpbGUoJ215ZmlsZTIudHh0JywgZGF0YSwgZnVuY3Rpb24oZXJyKXsKICAgICAgICBpZiAoZXJyKSB7IC4uLiB9IC8vIEhhbmRsZSBlcnJvcgogICAgICAgIGNvbnNvbGUubG9nKCdkb25lJykKICAgICAgfSk7CiAgICB9KTsKICAgIGBgYAogIAogICAgeW91IGNhbiBjaGFpbiB0aGUgb3BlcmF0aW9ucyB0b2dldGhlciB1c2luZyBgdGhlbmAgZnJvbSB0aGUgcmV0dXJuZWQgcHJvbWlzZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCBmcyA9IHJlcXVpcmUoJ2ZzJyk7CiAgICBsZXQgcmVhZEZpbGUgPSBkZW5vZGVpZnkoZnMucmVhZEZpbGUpOwogICAgbGV0IHdyaXRlRmlsZSA9IGRlbm9kZWlmeShmcy53cml0ZUZpbGUpOwogIAogICAgcmVhZEZpbGUoJ215ZmlsZS50eHQnKS50aGVuKGZ1bmN0aW9uKGRhdGEpewogICAgICByZXR1cm4gd3JpdGVGaWxlKCdteWZpbGUyLnR4dCcsIGRhdGEpOwogICAgfSkudGhlbihmdW5jdGlvbigpewogICAgICBjb25zb2xlLmxvZygnZG9uZScpCiAgICB9KS5jYXRjaChmdW5jdGlvbihlcnJvcil7CiAgICAgIC8vIEhhbmRsZSBlcnJvcgogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgZGVub2RlaWZ5CiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIHJzdnAKICAgIEBwYXJhbSB7RnVuY3Rpb259IG5vZGVGdW5jIGEgJ25vZGUtc3R5bGUnIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSBjYWxsYmFjayBhcwogICAgaXRzIGxhc3QgYXJndW1lbnQuIFRoZSBjYWxsYmFjayBleHBlY3RzIGFuIGVycm9yIHRvIGJlIHBhc3NlZCBhcyBpdHMgZmlyc3QKICAgIGFyZ3VtZW50IChpZiBhbiBlcnJvciBvY2N1cnJlZCwgb3RoZXJ3aXNlIG51bGwpLCBhbmQgdGhlIHZhbHVlIGZyb20gdGhlCiAgICBvcGVyYXRpb24gYXMgaXRzIHNlY29uZCBhcmd1bWVudCAoJ2Z1bmN0aW9uKGVyciwgdmFsdWUpeyB9JykuCiAgICBAcGFyYW0ge0Jvb2xlYW58QXJyYXl9IFtvcHRpb25zXSBBbiBvcHRpb25hbCBwYXJhbXRlciB0aGF0IGlmIHNldAogICAgdG8gYHRydWVgIGNhdXNlcyB0aGUgcHJvbWlzZSB0byBmdWxmaWxsIHdpdGggdGhlIGNhbGxiYWNrJ3Mgc3VjY2VzcyBhcmd1bWVudHMKICAgIGFzIGFuIGFycmF5LiBUaGlzIGlzIHVzZWZ1bCBpZiB0aGUgbm9kZSBmdW5jdGlvbiBoYXMgbXVsdGlwbGUgc3VjY2VzcwogICAgcGFyYW10ZXJzLiBJZiB5b3Ugc2V0IHRoaXMgcGFyYW10ZXIgdG8gYW4gYXJyYXkgd2l0aCBuYW1lcywgdGhlIHByb21pc2Ugd2lsbAogICAgZnVsZmlsbCB3aXRoIGEgaGFzaCB3aXRoIHRoZXNlIG5hbWVzIGFzIGtleXMgYW5kIHRoZSBzdWNjZXNzIHBhcmFtZXRlcnMgYXMKICAgIHZhbHVlcy4KICAgIEByZXR1cm4ge0Z1bmN0aW9ufSBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYG5vZGVGdW5jYCB0byByZXR1cm4gYSBgUHJvbWlzZWAKICAqLwoKCiAgZnVuY3Rpb24gZGVub2RlaWZ5KG5vZGVGdW5jLCBvcHRpb25zKSB7CiAgICB2YXIgZm4gPSBmdW5jdGlvbiBmbigpIHsKICAgICAgdmFyIGwgPSBhcmd1bWVudHMubGVuZ3RoOwogICAgICB2YXIgYXJncyA9IG5ldyBBcnJheShsICsgMSk7CiAgICAgIHZhciBwcm9taXNlSW5wdXQgPSBmYWxzZTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgKytpKSB7CiAgICAgICAgdmFyIGFyZyA9IGFyZ3VtZW50c1tpXTsgLy8gVE9ETzogdGhpcyBjb2RlIHJlYWxseSBuZWVkcyB0byBiZSBjbGVhbmVkIHVwCgogICAgICAgIGlmICghcHJvbWlzZUlucHV0KSB7CiAgICAgICAgICBpZiAoYXJnICE9PSBudWxsICYmIHR5cGVvZiBhcmcgPT09ICdvYmplY3QnKSB7CiAgICAgICAgICAgIGlmIChhcmcuY29uc3RydWN0b3IgPT09IFByb21pc2UpIHsKICAgICAgICAgICAgICBwcm9taXNlSW5wdXQgPSB0cnVlOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBwcm9taXNlSW5wdXQgPSBhcmcudGhlbjsKICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgdmFyIHAgPSBuZXcgUHJvbWlzZShub29wKTsKICAgICAgICAgICAgICAgIHJlamVjdChwLCBlcnJvcik7CiAgICAgICAgICAgICAgICByZXR1cm4gcDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHByb21pc2VJbnB1dCA9IGZhbHNlOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChwcm9taXNlSW5wdXQgJiYgcHJvbWlzZUlucHV0ICE9PSB0cnVlKSB7CiAgICAgICAgICAgIGFyZyA9IHdyYXBUaGVuYWJsZShwcm9taXNlSW5wdXQsIGFyZyk7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBhcmdzW2ldID0gYXJnOwogICAgICB9CgogICAgICB2YXIgcHJvbWlzZSA9IG5ldyBQcm9taXNlKG5vb3ApOwoKICAgICAgYXJnc1tsXSA9IGZ1bmN0aW9uIChlcnIsIHZhbCkgewogICAgICAgIGlmIChlcnIpIHsKICAgICAgICAgIHJlamVjdChwcm9taXNlLCBlcnIpOwogICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICByZXNvbHZlJDEocHJvbWlzZSwgdmFsKTsKICAgICAgICB9IGVsc2UgaWYgKG9wdGlvbnMgPT09IHRydWUpIHsKICAgICAgICAgIHJlc29sdmUkMShwcm9taXNlLCBhcnJheVJlc3VsdChhcmd1bWVudHMpKTsKICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucykpIHsKICAgICAgICAgIHJlc29sdmUkMShwcm9taXNlLCBtYWtlT2JqZWN0KGFyZ3VtZW50cywgb3B0aW9ucykpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXNvbHZlJDEocHJvbWlzZSwgdmFsKTsKICAgICAgICB9CiAgICAgIH07CgogICAgICBpZiAocHJvbWlzZUlucHV0KSB7CiAgICAgICAgcmV0dXJuIGhhbmRsZVByb21pc2VJbnB1dChwcm9taXNlLCBhcmdzLCBub2RlRnVuYywgdGhpcyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGhhbmRsZVZhbHVlSW5wdXQocHJvbWlzZSwgYXJncywgbm9kZUZ1bmMsIHRoaXMpOwogICAgICB9CiAgICB9OwoKICAgIGZuLl9fcHJvdG9fXyA9IG5vZGVGdW5jOwogICAgcmV0dXJuIGZuOwogIH0KCiAgZnVuY3Rpb24gaGFuZGxlVmFsdWVJbnB1dChwcm9taXNlLCBhcmdzLCBub2RlRnVuYywgc2VsZikgewogICAgdHJ5IHsKICAgICAgbm9kZUZ1bmMuYXBwbHkoc2VsZiwgYXJncyk7CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgICByZWplY3QocHJvbWlzZSwgZXJyb3IpOwogICAgfQoKICAgIHJldHVybiBwcm9taXNlOwogIH0KCiAgZnVuY3Rpb24gaGFuZGxlUHJvbWlzZUlucHV0KHByb21pc2UsIGFyZ3MsIG5vZGVGdW5jLCBzZWxmKSB7CiAgICByZXR1cm4gUHJvbWlzZS5hbGwoYXJncykudGhlbihmdW5jdGlvbiAoYXJncykgewogICAgICByZXR1cm4gaGFuZGxlVmFsdWVJbnB1dChwcm9taXNlLCBhcmdzLCBub2RlRnVuYywgc2VsZik7CiAgICB9KTsKICB9CiAgLyoqCiAgICBUaGlzIGlzIGEgY29udmVuaWVudCBhbGlhcyBmb3IgYFByb21pc2UuYWxsYC4KICAKICAgIEBtZXRob2QgYWxsCiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIHJzdnAKICAgIEBwYXJhbSB7QXJyYXl9IGFycmF5IEFycmF5IG9mIHByb21pc2VzLgogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gQW4gb3B0aW9uYWwgbGFiZWwuIFRoaXMgaXMgdXNlZnVsCiAgICBmb3IgdG9vbGluZy4KICAqLwoKCiAgZnVuY3Rpb24gYWxsJDEoYXJyYXksIGxhYmVsKSB7CiAgICByZXR1cm4gUHJvbWlzZS5hbGwoYXJyYXksIGxhYmVsKTsKICB9CiAgLyoqCiAgQG1vZHVsZSByc3ZwCiAgQHB1YmxpYwogICoqLwoKCiAgdmFyIEFsbFNldHRsZWQgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0VudW1lcmF0b3IpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShBbGxTZXR0bGVkLCBfRW51bWVyYXRvcik7CgogICAgZnVuY3Rpb24gQWxsU2V0dGxlZChDb25zdHJ1Y3RvciwgZW50cmllcywgbGFiZWwpIHsKICAgICAgcmV0dXJuIF9FbnVtZXJhdG9yLmNhbGwodGhpcywgQ29uc3RydWN0b3IsIGVudHJpZXMsIGZhbHNlCiAgICAgIC8qIGRvbid0IGFib3J0IG9uIHJlamVjdCAqLwogICAgICAsIGxhYmVsKSB8fCB0aGlzOwogICAgfQoKICAgIHJldHVybiBBbGxTZXR0bGVkOwogIH0oRW51bWVyYXRvcik7CgogIEFsbFNldHRsZWQucHJvdG90eXBlLl9zZXRSZXN1bHRBdCA9IHNldFNldHRsZWRSZXN1bHQ7CiAgLyoqCiAgYFJTVlAuYWxsU2V0dGxlZGAgaXMgc2ltaWxhciB0byBgUlNWUC5hbGxgLCBidXQgaW5zdGVhZCBvZiBpbXBsZW1lbnRpbmcKICBhIGZhaWwtZmFzdCBtZXRob2QsIGl0IHdhaXRzIHVudGlsIGFsbCB0aGUgcHJvbWlzZXMgaGF2ZSByZXR1cm5lZCBhbmQKICBzaG93cyB5b3UgYWxsIHRoZSByZXN1bHRzLiBUaGlzIGlzIHVzZWZ1bCBpZiB5b3Ugd2FudCB0byBoYW5kbGUgbXVsdGlwbGUKICBwcm9taXNlcycgZmFpbHVyZSBzdGF0ZXMgdG9nZXRoZXIgYXMgYSBzZXQuCiAgIFJldHVybnMgYSBwcm9taXNlIHRoYXQgaXMgZnVsZmlsbGVkIHdoZW4gYWxsIHRoZSBnaXZlbiBwcm9taXNlcyBoYXZlIGJlZW4KICBzZXR0bGVkLiBUaGUgcmV0dXJuIHByb21pc2UgaXMgZnVsZmlsbGVkIHdpdGggYW4gYXJyYXkgb2YgdGhlIHN0YXRlcyBvZgogIHRoZSBwcm9taXNlcyBwYXNzZWQgaW50byB0aGUgYHByb21pc2VzYCBhcnJheSBhcmd1bWVudC4KICAgRWFjaCBzdGF0ZSBvYmplY3Qgd2lsbCBlaXRoZXIgaW5kaWNhdGUgZnVsZmlsbG1lbnQgb3IgcmVqZWN0aW9uLCBhbmQKICBwcm92aWRlIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlIG9yIHJlYXNvbi4gVGhlIHN0YXRlcyB3aWxsIHRha2Ugb25lIG9mCiAgdGhlIGZvbGxvd2luZyBmb3JtYXRzOgogICBgYGBqYXZhc2NyaXB0CiAgeyBzdGF0ZTogJ2Z1bGZpbGxlZCcsIHZhbHVlOiB2YWx1ZSB9CiAgICBvcgogIHsgc3RhdGU6ICdyZWplY3RlZCcsIHJlYXNvbjogcmVhc29uIH0KICBgYGAKICAgRXhhbXBsZToKICAgYGBgamF2YXNjcmlwdAogIGxldCBwcm9taXNlMSA9IFJTVlAuUHJvbWlzZS5yZXNvbHZlKDEpOwogIGxldCBwcm9taXNlMiA9IFJTVlAuUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCcyJykpOwogIGxldCBwcm9taXNlMyA9IFJTVlAuUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCczJykpOwogIGxldCBwcm9taXNlcyA9IFsgcHJvbWlzZTEsIHByb21pc2UyLCBwcm9taXNlMyBdOwogICBSU1ZQLmFsbFNldHRsZWQocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oYXJyYXkpewogICAgLy8gYXJyYXkgPT0gWwogICAgLy8gICB7IHN0YXRlOiAnZnVsZmlsbGVkJywgdmFsdWU6IDEgfSwKICAgIC8vICAgeyBzdGF0ZTogJ3JlamVjdGVkJywgcmVhc29uOiBFcnJvciB9LAogICAgLy8gICB7IHN0YXRlOiAncmVqZWN0ZWQnLCByZWFzb246IEVycm9yIH0KICAgIC8vIF0KICAgIC8vIE5vdGUgdGhhdCBmb3IgdGhlIHNlY29uZCBpdGVtLCByZWFzb24ubWVzc2FnZSB3aWxsIGJlICcyJywgYW5kIGZvciB0aGUKICAgIC8vIHRoaXJkIGl0ZW0sIHJlYXNvbi5tZXNzYWdlIHdpbGwgYmUgJzMnLgogIH0sIGZ1bmN0aW9uKGVycm9yKSB7CiAgICAvLyBOb3QgcnVuLiAoVGhpcyBibG9jayB3b3VsZCBvbmx5IGJlIGNhbGxlZCBpZiBhbGxTZXR0bGVkIGhhZCBmYWlsZWQsCiAgICAvLyBmb3IgaW5zdGFuY2UgaWYgcGFzc2VkIGFuIGluY29ycmVjdCBhcmd1bWVudCB0eXBlLikKICB9KTsKICBgYGAKICAgQG1ldGhvZCBhbGxTZXR0bGVkCiAgQHB1YmxpYwogIEBzdGF0aWMKICBAZm9yIHJzdnAKICBAcGFyYW0ge0FycmF5fSBlbnRyaWVzCiAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gLSBvcHRpb25hbCBzdHJpbmcgdGhhdCBkZXNjcmliZXMgdGhlIHByb21pc2UuCiAgVXNlZnVsIGZvciB0b29saW5nLgogIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UgdGhhdCBpcyBmdWxmaWxsZWQgd2l0aCBhbiBhcnJheSBvZiB0aGUgc2V0dGxlZAogIHN0YXRlcyBvZiB0aGUgY29uc3RpdHVlbnQgcHJvbWlzZXMuCiAgKi8KCiAgZnVuY3Rpb24gYWxsU2V0dGxlZChlbnRyaWVzLCBsYWJlbCkgewogICAgaWYgKCFBcnJheS5pc0FycmF5KGVudHJpZXMpKSB7CiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgVHlwZUVycm9yKCJQcm9taXNlLmFsbFNldHRsZWQgbXVzdCBiZSBjYWxsZWQgd2l0aCBhbiBhcnJheSIpLCBsYWJlbCk7CiAgICB9CgogICAgcmV0dXJuIG5ldyBBbGxTZXR0bGVkKFByb21pc2UsIGVudHJpZXMsIGxhYmVsKS5wcm9taXNlOwogIH0KICAvKioKICAgIFRoaXMgaXMgYSBjb252ZW5pZW50IGFsaWFzIGZvciBgUHJvbWlzZS5yYWNlYC4KICAKICAgIEBtZXRob2QgcmFjZQogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQGZvciByc3ZwCiAgICBAcGFyYW0ge0FycmF5fSBhcnJheSBBcnJheSBvZiBwcm9taXNlcy4KICAgIEBwYXJhbSB7U3RyaW5nfSBbbGFiZWxdIEFuIG9wdGlvbmFsIGxhYmVsLiBUaGlzIGlzIHVzZWZ1bAogICAgZm9yIHRvb2xpbmcuCiAgICovCgoKICBmdW5jdGlvbiByYWNlJDEoYXJyYXksIGxhYmVsKSB7CiAgICByZXR1cm4gUHJvbWlzZS5yYWNlKGFycmF5LCBsYWJlbCk7CiAgfQoKICB2YXIgUHJvbWlzZUhhc2ggPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0VudW1lcmF0b3IyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUHJvbWlzZUhhc2gsIF9FbnVtZXJhdG9yMik7CgogICAgZnVuY3Rpb24gUHJvbWlzZUhhc2goQ29uc3RydWN0b3IsIG9iamVjdCwgYWJvcnRPblJlamVjdCwgbGFiZWwpIHsKICAgICAgaWYgKGFib3J0T25SZWplY3QgPT09IHZvaWQgMCkgewogICAgICAgIGFib3J0T25SZWplY3QgPSB0cnVlOwogICAgICB9CgogICAgICByZXR1cm4gX0VudW1lcmF0b3IyLmNhbGwodGhpcywgQ29uc3RydWN0b3IsIG9iamVjdCwgYWJvcnRPblJlamVjdCwgbGFiZWwpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzMgPSBQcm9taXNlSGFzaC5wcm90b3R5cGU7CgogICAgX3Byb3RvMy5faW5pdCA9IGZ1bmN0aW9uIF9pbml0KENvbnN0cnVjdG9yLCBvYmplY3QpIHsKICAgICAgdGhpcy5fcmVzdWx0ID0ge307CgogICAgICB0aGlzLl9lbnVtZXJhdGUob2JqZWN0KTsKICAgIH07CgogICAgX3Byb3RvMy5fZW51bWVyYXRlID0gZnVuY3Rpb24gX2VudW1lcmF0ZShpbnB1dCkgewogICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGlucHV0KTsKICAgICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoOwogICAgICB2YXIgcHJvbWlzZSA9IHRoaXMucHJvbWlzZTsKICAgICAgdGhpcy5fcmVtYWluaW5nID0gbGVuZ3RoOwogICAgICB2YXIga2V5LCB2YWw7CgogICAgICBmb3IgKHZhciBpID0gMDsgcHJvbWlzZS5fc3RhdGUgPT09IFBFTkRJTkcgJiYgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAga2V5ID0ga2V5c1tpXTsKICAgICAgICB2YWwgPSBpbnB1dFtrZXldOwoKICAgICAgICB0aGlzLl9lYWNoRW50cnkodmFsLCBrZXksIHRydWUpOwogICAgICB9CgogICAgICB0aGlzLl9jaGVja0Z1bGxmaWxsbWVudCgpOwogICAgfTsKCiAgICByZXR1cm4gUHJvbWlzZUhhc2g7CiAgfShFbnVtZXJhdG9yKTsKICAvKioKICAgIGBoYXNoYCBpcyBzaW1pbGFyIHRvIGBhbGxgLCBidXQgdGFrZXMgYW4gb2JqZWN0IGluc3RlYWQgb2YgYW4gYXJyYXkKICAgIGZvciBpdHMgYHByb21pc2VzYCBhcmd1bWVudC4KICAKICAgIFJldHVybnMgYSBwcm9taXNlIHRoYXQgaXMgZnVsZmlsbGVkIHdoZW4gYWxsIHRoZSBnaXZlbiBwcm9taXNlcyBoYXZlIGJlZW4KICAgIGZ1bGZpbGxlZCwgb3IgcmVqZWN0ZWQgaWYgYW55IG9mIHRoZW0gYmVjb21lIHJlamVjdGVkLiBUaGUgcmV0dXJuZWQgcHJvbWlzZQogICAgaXMgZnVsZmlsbGVkIHdpdGggYSBoYXNoIHRoYXQgaGFzIHRoZSBzYW1lIGtleSBuYW1lcyBhcyB0aGUgYHByb21pc2VzYCBvYmplY3QKICAgIGFyZ3VtZW50LiBJZiBhbnkgb2YgdGhlIHZhbHVlcyBpbiB0aGUgb2JqZWN0IGFyZSBub3QgcHJvbWlzZXMsIHRoZXkgd2lsbAogICAgc2ltcGx5IGJlIGNvcGllZCBvdmVyIHRvIHRoZSBmdWxmaWxsZWQgb2JqZWN0LgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCBwcm9taXNlcyA9IHsKICAgICAgbXlQcm9taXNlOiByZXNvbHZlKDEpLAogICAgICB5b3VyUHJvbWlzZTogcmVzb2x2ZSgyKSwKICAgICAgdGhlaXJQcm9taXNlOiByZXNvbHZlKDMpLAogICAgICBub3RBUHJvbWlzZTogNAogICAgfTsKICAKICAgIGhhc2gocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oaGFzaCl7CiAgICAgIC8vIGhhc2ggaGVyZSBpcyBhbiBvYmplY3QgdGhhdCBsb29rcyBsaWtlOgogICAgICAvLyB7CiAgICAgIC8vICAgbXlQcm9taXNlOiAxLAogICAgICAvLyAgIHlvdXJQcm9taXNlOiAyLAogICAgICAvLyAgIHRoZWlyUHJvbWlzZTogMywKICAgICAgLy8gICBub3RBUHJvbWlzZTogNAogICAgICAvLyB9CiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgYW55IG9mIHRoZSBgcHJvbWlzZXNgIGdpdmVuIHRvIGBoYXNoYCBhcmUgcmVqZWN0ZWQsIHRoZSBmaXJzdCBwcm9taXNlCiAgICB0aGF0IGlzIHJlamVjdGVkIHdpbGwgYmUgZ2l2ZW4gYXMgdGhlIHJlYXNvbiB0byB0aGUgcmVqZWN0aW9uIGhhbmRsZXIuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgbGV0IHByb21pc2VzID0gewogICAgICBteVByb21pc2U6IHJlc29sdmUoMSksCiAgICAgIHJlamVjdGVkUHJvbWlzZTogcmVqZWN0KG5ldyBFcnJvcigncmVqZWN0ZWRQcm9taXNlJykpLAogICAgICBhbm90aGVyUmVqZWN0ZWRQcm9taXNlOiByZWplY3QobmV3IEVycm9yKCdhbm90aGVyUmVqZWN0ZWRQcm9taXNlJykpLAogICAgfTsKICAKICAgIGhhc2gocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oaGFzaCl7CiAgICAgIC8vIENvZGUgaGVyZSBuZXZlciBydW5zIGJlY2F1c2UgdGhlcmUgYXJlIHJlamVjdGVkIHByb21pc2VzIQogICAgfSwgZnVuY3Rpb24ocmVhc29uKSB7CiAgICAgIC8vIHJlYXNvbi5tZXNzYWdlID09PSAncmVqZWN0ZWRQcm9taXNlJwogICAgfSk7CiAgICBgYGAKICAKICAgIEFuIGltcG9ydGFudCBub3RlOiBgaGFzaGAgaXMgaW50ZW5kZWQgZm9yIHBsYWluIEphdmFTY3JpcHQgb2JqZWN0cyB0aGF0CiAgICBhcmUganVzdCBhIHNldCBvZiBrZXlzIGFuZCB2YWx1ZXMuIGBoYXNoYCB3aWxsIE5PVCBwcmVzZXJ2ZSBwcm90b3R5cGUKICAgIGNoYWlucy4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBoYXNoLCByZXNvbHZlIH0gZnJvbSAncnN2cCc7CiAgICBmdW5jdGlvbiBNeUNvbnN0cnVjdG9yKCl7CiAgICAgIHRoaXMuZXhhbXBsZSA9IHJlc29sdmUoJ0V4YW1wbGUnKTsKICAgIH0KICAKICAgIE15Q29uc3RydWN0b3IucHJvdG90eXBlID0gewogICAgICBwcm90b1Byb3BlcnR5OiByZXNvbHZlKCdQcm90byBQcm9wZXJ0eScpCiAgICB9OwogIAogICAgbGV0IG15T2JqZWN0ID0gbmV3IE15Q29uc3RydWN0b3IoKTsKICAKICAgIGhhc2gobXlPYmplY3QpLnRoZW4oZnVuY3Rpb24oaGFzaCl7CiAgICAgIC8vIHByb3RvUHJvcGVydHkgd2lsbCBub3QgYmUgcHJlc2VudCwgaW5zdGVhZCB5b3Ugd2lsbCBqdXN0IGhhdmUgYW4KICAgICAgLy8gb2JqZWN0IHRoYXQgbG9va3MgbGlrZToKICAgICAgLy8gewogICAgICAvLyAgIGV4YW1wbGU6ICdFeGFtcGxlJwogICAgICAvLyB9CiAgICAgIC8vCiAgICAgIC8vIGhhc2guaGFzT3duUHJvcGVydHkoJ3Byb3RvUHJvcGVydHknKTsgLy8gZmFsc2UKICAgICAgLy8gJ3VuZGVmaW5lZCcgPT09IHR5cGVvZiBoYXNoLnByb3RvUHJvcGVydHkKICAgIH0pOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGhhc2gKICAgIEBwdWJsaWMKICAgIEBzdGF0aWMKICAgIEBmb3IgcnN2cAogICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdAogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIHRoYXQgZGVzY3JpYmVzIHRoZSBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCB3aGVuIGFsbCBwcm9wZXJ0aWVzIG9mIGBwcm9taXNlc2AKICAgIGhhdmUgYmVlbiBmdWxmaWxsZWQsIG9yIHJlamVjdGVkIGlmIGFueSBvZiB0aGVtIGJlY29tZSByZWplY3RlZC4KICAqLwoKCiAgZnVuY3Rpb24gaGFzaChvYmplY3QsIGxhYmVsKSB7CiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG9iamVjdCwgbGFiZWwpLnRoZW4oZnVuY3Rpb24gKG9iamVjdCkgewogICAgICBpZiAob2JqZWN0ID09PSBudWxsIHx8IHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnKSB7CiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiUHJvbWlzZS5oYXNoIG11c3QgYmUgY2FsbGVkIHdpdGggYW4gb2JqZWN0Iik7CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXcgUHJvbWlzZUhhc2goUHJvbWlzZSwgb2JqZWN0LCBsYWJlbCkucHJvbWlzZTsKICAgIH0pOwogIH0KCiAgdmFyIEhhc2hTZXR0bGVkID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Qcm9taXNlSGFzaCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEhhc2hTZXR0bGVkLCBfUHJvbWlzZUhhc2gpOwoKICAgIGZ1bmN0aW9uIEhhc2hTZXR0bGVkKENvbnN0cnVjdG9yLCBvYmplY3QsIGxhYmVsKSB7CiAgICAgIHJldHVybiBfUHJvbWlzZUhhc2guY2FsbCh0aGlzLCBDb25zdHJ1Y3Rvciwgb2JqZWN0LCBmYWxzZSwgbGFiZWwpIHx8IHRoaXM7CiAgICB9CgogICAgcmV0dXJuIEhhc2hTZXR0bGVkOwogIH0oUHJvbWlzZUhhc2gpOwoKICBIYXNoU2V0dGxlZC5wcm90b3R5cGUuX3NldFJlc3VsdEF0ID0gc2V0U2V0dGxlZFJlc3VsdDsKICAvKioKICAgIGBoYXNoU2V0dGxlZGAgaXMgc2ltaWxhciB0byBgYWxsU2V0dGxlZGAsIGJ1dCB0YWtlcyBhbiBvYmplY3QKICAgIGluc3RlYWQgb2YgYW4gYXJyYXkgZm9yIGl0cyBgcHJvbWlzZXNgIGFyZ3VtZW50LgogIAogICAgVW5saWtlIGBhbGxgIG9yIGBoYXNoYCwgd2hpY2ggaW1wbGVtZW50IGEgZmFpbC1mYXN0IG1ldGhvZCwKICAgIGJ1dCBsaWtlIGBhbGxTZXR0bGVkYCwgYGhhc2hTZXR0bGVkYCB3YWl0cyB1bnRpbCBhbGwgdGhlCiAgICBjb25zdGl0dWVudCBwcm9taXNlcyBoYXZlIHJldHVybmVkIGFuZCB0aGVuIHNob3dzIHlvdSBhbGwgdGhlIHJlc3VsdHMKICAgIHdpdGggdGhlaXIgc3RhdGVzIGFuZCB2YWx1ZXMvcmVhc29ucy4gVGhpcyBpcyB1c2VmdWwgaWYgeW91IHdhbnQgdG8KICAgIGhhbmRsZSBtdWx0aXBsZSBwcm9taXNlcycgZmFpbHVyZSBzdGF0ZXMgdG9nZXRoZXIgYXMgYSBzZXQuCiAgCiAgICBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCB3aGVuIGFsbCB0aGUgZ2l2ZW4gcHJvbWlzZXMgaGF2ZSBiZWVuCiAgICBzZXR0bGVkLCBvciByZWplY3RlZCBpZiB0aGUgcGFzc2VkIHBhcmFtZXRlcnMgYXJlIGludmFsaWQuCiAgCiAgICBUaGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBmdWxmaWxsZWQgd2l0aCBhIGhhc2ggdGhhdCBoYXMgdGhlIHNhbWUga2V5IG5hbWVzIGFzCiAgICB0aGUgYHByb21pc2VzYCBvYmplY3QgYXJndW1lbnQuIElmIGFueSBvZiB0aGUgdmFsdWVzIGluIHRoZSBvYmplY3QgYXJlIG5vdAogICAgcHJvbWlzZXMsIHRoZXkgd2lsbCBiZSBjb3BpZWQgb3ZlciB0byB0aGUgZnVsZmlsbGVkIG9iamVjdCBhbmQgbWFya2VkIHdpdGggc3RhdGUKICAgICdmdWxmaWxsZWQnLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGhhc2hTZXR0bGVkLCByZXNvbHZlIH0gZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgcHJvbWlzZXMgPSB7CiAgICAgIG15UHJvbWlzZTogcmVzb2x2ZSgxKSwKICAgICAgeW91clByb21pc2U6IHJlc29sdmUoMiksCiAgICAgIHRoZWlyUHJvbWlzZTogcmVzb2x2ZSgzKSwKICAgICAgbm90QVByb21pc2U6IDQKICAgIH07CiAgCiAgICBoYXNoU2V0dGxlZChwcm9taXNlcykudGhlbihmdW5jdGlvbihoYXNoKXsKICAgICAgLy8gaGFzaCBoZXJlIGlzIGFuIG9iamVjdCB0aGF0IGxvb2tzIGxpa2U6CiAgICAgIC8vIHsKICAgICAgLy8gICBteVByb21pc2U6IHsgc3RhdGU6ICdmdWxmaWxsZWQnLCB2YWx1ZTogMSB9LAogICAgICAvLyAgIHlvdXJQcm9taXNlOiB7IHN0YXRlOiAnZnVsZmlsbGVkJywgdmFsdWU6IDIgfSwKICAgICAgLy8gICB0aGVpclByb21pc2U6IHsgc3RhdGU6ICdmdWxmaWxsZWQnLCB2YWx1ZTogMyB9LAogICAgICAvLyAgIG5vdEFQcm9taXNlOiB7IHN0YXRlOiAnZnVsZmlsbGVkJywgdmFsdWU6IDQgfQogICAgICAvLyB9CiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgYW55IG9mIHRoZSBgcHJvbWlzZXNgIGdpdmVuIHRvIGBoYXNoYCBhcmUgcmVqZWN0ZWQsIHRoZSBzdGF0ZSB3aWxsCiAgICBiZSBzZXQgdG8gJ3JlamVjdGVkJyBhbmQgdGhlIHJlYXNvbiBmb3IgcmVqZWN0aW9uIHByb3ZpZGVkLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGhhc2hTZXR0bGVkLCByZWplY3QsIHJlc29sdmUgfSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlcyA9IHsKICAgICAgbXlQcm9taXNlOiByZXNvbHZlKDEpLAogICAgICByZWplY3RlZFByb21pc2U6IHJlamVjdChuZXcgRXJyb3IoJ3JlamVjdGlvbicpKSwKICAgICAgYW5vdGhlclJlamVjdGVkUHJvbWlzZTogcmVqZWN0KG5ldyBFcnJvcignbW9yZSByZWplY3Rpb24nKSksCiAgICB9OwogIAogICAgaGFzaFNldHRsZWQocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oaGFzaCl7CiAgICAgIC8vIGhhc2ggaGVyZSBpcyBhbiBvYmplY3QgdGhhdCBsb29rcyBsaWtlOgogICAgICAvLyB7CiAgICAgIC8vICAgbXlQcm9taXNlOiAgICAgICAgICAgICAgeyBzdGF0ZTogJ2Z1bGZpbGxlZCcsIHZhbHVlOiAxIH0sCiAgICAgIC8vICAgcmVqZWN0ZWRQcm9taXNlOiAgICAgICAgeyBzdGF0ZTogJ3JlamVjdGVkJywgcmVhc29uOiBFcnJvciB9LAogICAgICAvLyAgIGFub3RoZXJSZWplY3RlZFByb21pc2U6IHsgc3RhdGU6ICdyZWplY3RlZCcsIHJlYXNvbjogRXJyb3IgfSwKICAgICAgLy8gfQogICAgICAvLyBOb3RlIHRoYXQgZm9yIHJlamVjdGVkUHJvbWlzZSwgcmVhc29uLm1lc3NhZ2UgPT0gJ3JlamVjdGlvbicsCiAgICAgIC8vIGFuZCBmb3IgYW5vdGhlclJlamVjdGVkUHJvbWlzZSwgcmVhc29uLm1lc3NhZ2UgPT0gJ21vcmUgcmVqZWN0aW9uJy4KICAgIH0pOwogICAgYGBgCiAgCiAgICBBbiBpbXBvcnRhbnQgbm90ZTogYGhhc2hTZXR0bGVkYCBpcyBpbnRlbmRlZCBmb3IgcGxhaW4gSmF2YVNjcmlwdCBvYmplY3RzIHRoYXQKICAgIGFyZSBqdXN0IGEgc2V0IG9mIGtleXMgYW5kIHZhbHVlcy4gYGhhc2hTZXR0bGVkYCB3aWxsIE5PVCBwcmVzZXJ2ZSBwcm90b3R5cGUKICAgIGNoYWlucy4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSwgeyBoYXNoU2V0dGxlZCwgcmVzb2x2ZSB9IGZyb20gJ3JzdnAnOwogIAogICAgZnVuY3Rpb24gTXlDb25zdHJ1Y3RvcigpewogICAgICB0aGlzLmV4YW1wbGUgPSByZXNvbHZlKCdFeGFtcGxlJyk7CiAgICB9CiAgCiAgICBNeUNvbnN0cnVjdG9yLnByb3RvdHlwZSA9IHsKICAgICAgcHJvdG9Qcm9wZXJ0eTogUHJvbWlzZS5yZXNvbHZlKCdQcm90byBQcm9wZXJ0eScpCiAgICB9OwogIAogICAgbGV0IG15T2JqZWN0ID0gbmV3IE15Q29uc3RydWN0b3IoKTsKICAKICAgIGhhc2hTZXR0bGVkKG15T2JqZWN0KS50aGVuKGZ1bmN0aW9uKGhhc2gpewogICAgICAvLyBwcm90b1Byb3BlcnR5IHdpbGwgbm90IGJlIHByZXNlbnQsIGluc3RlYWQgeW91IHdpbGwganVzdCBoYXZlIGFuCiAgICAgIC8vIG9iamVjdCB0aGF0IGxvb2tzIGxpa2U6CiAgICAgIC8vIHsKICAgICAgLy8gICBleGFtcGxlOiB7IHN0YXRlOiAnZnVsZmlsbGVkJywgdmFsdWU6ICdFeGFtcGxlJyB9CiAgICAgIC8vIH0KICAgICAgLy8KICAgICAgLy8gaGFzaC5oYXNPd25Qcm9wZXJ0eSgncHJvdG9Qcm9wZXJ0eScpOyAvLyBmYWxzZQogICAgICAvLyAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIGhhc2gucHJvdG9Qcm9wZXJ0eQogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgaGFzaFNldHRsZWQKICAgIEBwdWJsaWMKICAgIEBmb3IgcnN2cAogICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdAogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIHRoYXQgZGVzY3JpYmVzIHRoZSBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCB3aGVuIHdoZW4gYWxsIHByb3BlcnRpZXMgb2YgYHByb21pc2VzYAogICAgaGF2ZSBiZWVuIHNldHRsZWQuCiAgICBAc3RhdGljCiAgKi8KCiAgZnVuY3Rpb24gaGFzaFNldHRsZWQob2JqZWN0LCBsYWJlbCkgewogICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShvYmplY3QsIGxhYmVsKS50aGVuKGZ1bmN0aW9uIChvYmplY3QpIHsKICAgICAgaWYgKG9iamVjdCA9PT0gbnVsbCB8fCB0eXBlb2Ygb2JqZWN0ICE9PSAnb2JqZWN0JykgewogICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoImhhc2hTZXR0bGVkIG11c3QgYmUgY2FsbGVkIHdpdGggYW4gb2JqZWN0Iik7CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXcgSGFzaFNldHRsZWQoUHJvbWlzZSwgb2JqZWN0LCBmYWxzZSwgbGFiZWwpLnByb21pc2U7CiAgICB9KTsKICB9CiAgLyoqCiAgICBgcmV0aHJvd2Agd2lsbCByZXRocm93IGFuIGVycm9yIG9uIHRoZSBuZXh0IHR1cm4gb2YgdGhlIEphdmFTY3JpcHQgZXZlbnQKICAgIGxvb3AgaW4gb3JkZXIgdG8gYWlkIGRlYnVnZ2luZy4KICAKICAgIFByb21pc2VzIEErIHNwZWNpZmllcyB0aGF0IGFueSBleGNlcHRpb25zIHRoYXQgb2NjdXIgd2l0aCBhIHByb21pc2UgbXVzdCBiZQogICAgY2F1Z2h0IGJ5IHRoZSBwcm9taXNlcyBpbXBsZW1lbnRhdGlvbiBhbmQgYnViYmxlZCB0byB0aGUgbGFzdCBoYW5kbGVyLiBGb3IKICAgIHRoaXMgcmVhc29uLCBpdCBpcyByZWNvbW1lbmRlZCB0aGF0IHlvdSBhbHdheXMgc3BlY2lmeSBhIHNlY29uZCByZWplY3Rpb24KICAgIGhhbmRsZXIgZnVuY3Rpb24gdG8gYHRoZW5gLiBIb3dldmVyLCBgcmV0aHJvd2Agd2lsbCB0aHJvdyB0aGUgZXhjZXB0aW9uCiAgICBvdXRzaWRlIG9mIHRoZSBwcm9taXNlLCBzbyBpdCBidWJibGVzIHVwIHRvIHlvdXIgY29uc29sZSBpZiBpbiB0aGUgYnJvd3NlciwKICAgIG9yIGRvbWFpbi9jYXVzZSB1bmNhdWdodCBleGNlcHRpb24gaW4gTm9kZS4gYHJldGhyb3dgIHdpbGwgYWxzbyB0aHJvdyB0aGUKICAgIGVycm9yIGFnYWluIHNvIHRoZSBlcnJvciBjYW4gYmUgaGFuZGxlZCBieSB0aGUgcHJvbWlzZSBwZXIgdGhlIHNwZWMuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyByZXRocm93IH0gZnJvbSAncnN2cCc7CiAgCiAgICBmdW5jdGlvbiB0aHJvd3MoKXsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdXaG9vcHMhJyk7CiAgICB9CiAgCiAgICBsZXQgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7CiAgICAgIHRocm93cygpOwogICAgfSk7CiAgCiAgICBwcm9taXNlLmNhdGNoKHJldGhyb3cpLnRoZW4oZnVuY3Rpb24oKXsKICAgICAgLy8gQ29kZSBoZXJlIGRvZXNuJ3QgcnVuIGJlY2F1c2UgdGhlIHByb21pc2UgYmVjYW1lIHJlamVjdGVkIGR1ZSB0byBhbgogICAgICAvLyBlcnJvciEKICAgIH0sIGZ1bmN0aW9uIChlcnIpewogICAgICAvLyBoYW5kbGUgdGhlIGVycm9yIGhlcmUKICAgIH0pOwogICAgYGBgCiAgCiAgICBUaGUgJ1dob29wcycgZXJyb3Igd2lsbCBiZSB0aHJvd24gb24gdGhlIG5leHQgdHVybiBvZiB0aGUgZXZlbnQgbG9vcAogICAgYW5kIHlvdSBjYW4gd2F0Y2ggZm9yIGl0IGluIHlvdXIgY29uc29sZS4gWW91IGNhbiBhbHNvIGhhbmRsZSBpdCB1c2luZyBhCiAgICByZWplY3Rpb24gaGFuZGxlciBnaXZlbiB0byBgLnRoZW5gIG9yIGAuY2F0Y2hgIG9uIHRoZSByZXR1cm5lZCBwcm9taXNlLgogIAogICAgQG1ldGhvZCByZXRocm93CiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIHJzdnAKICAgIEBwYXJhbSB7RXJyb3J9IHJlYXNvbiByZWFzb24gdGhlIHByb21pc2UgYmVjYW1lIHJlamVjdGVkLgogICAgQHRocm93cyBFcnJvcgogICAgQHN0YXRpYwogICovCgoKICBmdW5jdGlvbiByZXRocm93KHJlYXNvbikgewogICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7CiAgICAgIHRocm93IHJlYXNvbjsKICAgIH0pOwogICAgdGhyb3cgcmVhc29uOwogIH0KICAvKioKICAgIGBkZWZlcmAgcmV0dXJucyBhbiBvYmplY3Qgc2ltaWxhciB0byBqUXVlcnkncyBgJC5EZWZlcnJlZGAuCiAgICBgZGVmZXJgIHNob3VsZCBiZSB1c2VkIHdoZW4gcG9ydGluZyBvdmVyIGNvZGUgcmVsaWFudCBvbiBgJC5EZWZlcnJlZGAncwogICAgaW50ZXJmYWNlLiBOZXcgY29kZSBzaG91bGQgdXNlIHRoZSBgUHJvbWlzZWAgY29uc3RydWN0b3IgaW5zdGVhZC4KICAKICAgIFRoZSBvYmplY3QgcmV0dXJuZWQgZnJvbSBgZGVmZXJgIGlzIGEgcGxhaW4gb2JqZWN0IHdpdGggdGhyZWUgcHJvcGVydGllczoKICAKICAgICogcHJvbWlzZSAtIGFuIGBQcm9taXNlYC4KICAgICogcmVqZWN0IC0gYSBmdW5jdGlvbiB0aGF0IGNhdXNlcyB0aGUgYHByb21pc2VgIHByb3BlcnR5IG9uIHRoaXMgb2JqZWN0IHRvCiAgICAgIGJlY29tZSByZWplY3RlZAogICAgKiByZXNvbHZlIC0gYSBmdW5jdGlvbiB0aGF0IGNhdXNlcyB0aGUgYHByb21pc2VgIHByb3BlcnR5IG9uIHRoaXMgb2JqZWN0IHRvCiAgICAgIGJlY29tZSBmdWxmaWxsZWQuCiAgCiAgICBFeGFtcGxlOgogIAogICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgZGVmZXJyZWQgPSBkZWZlcigpOwogIAogICAgIGRlZmVycmVkLnJlc29sdmUoIlN1Y2Nlc3MhIik7CiAgCiAgICAgZGVmZXJyZWQucHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXsKICAgICAgIC8vIHZhbHVlIGhlcmUgaXMgIlN1Y2Nlc3MhIgogICAgIH0pOwogICAgIGBgYAogIAogICAgQG1ldGhvZCBkZWZlcgogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQGZvciByc3ZwCiAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7T2JqZWN0fQogICAqLwoKCiAgZnVuY3Rpb24gZGVmZXIobGFiZWwpIHsKICAgIHZhciBkZWZlcnJlZCA9IHsKICAgICAgcmVzb2x2ZTogdW5kZWZpbmVkLAogICAgICByZWplY3Q6IHVuZGVmaW5lZAogICAgfTsKICAgIGRlZmVycmVkLnByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7CiAgICAgIGRlZmVycmVkLnJlc29sdmUgPSByZXNvbHZlOwogICAgICBkZWZlcnJlZC5yZWplY3QgPSByZWplY3Q7CiAgICB9LCBsYWJlbCk7CiAgICByZXR1cm4gZGVmZXJyZWQ7CiAgfQoKICB2YXIgTWFwRW51bWVyYXRvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW51bWVyYXRvcjMpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShNYXBFbnVtZXJhdG9yLCBfRW51bWVyYXRvcjMpOwoKICAgIGZ1bmN0aW9uIE1hcEVudW1lcmF0b3IoQ29uc3RydWN0b3IsIGVudHJpZXMsIG1hcEZuLCBsYWJlbCkgewogICAgICByZXR1cm4gX0VudW1lcmF0b3IzLmNhbGwodGhpcywgQ29uc3RydWN0b3IsIGVudHJpZXMsIHRydWUsIGxhYmVsLCBtYXBGbikgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNCA9IE1hcEVudW1lcmF0b3IucHJvdG90eXBlOwoKICAgIF9wcm90bzQuX2luaXQgPSBmdW5jdGlvbiBfaW5pdChDb25zdHJ1Y3RvciwgaW5wdXQsIGJvb2wsIGxhYmVsLCBtYXBGbikgewogICAgICB2YXIgbGVuID0gaW5wdXQubGVuZ3RoIHx8IDA7CiAgICAgIHRoaXMubGVuZ3RoID0gbGVuOwogICAgICB0aGlzLl9yZW1haW5pbmcgPSBsZW47CiAgICAgIHRoaXMuX3Jlc3VsdCA9IG5ldyBBcnJheShsZW4pOwogICAgICB0aGlzLl9tYXBGbiA9IG1hcEZuOwoKICAgICAgdGhpcy5fZW51bWVyYXRlKGlucHV0KTsKICAgIH07CgogICAgX3Byb3RvNC5fc2V0UmVzdWx0QXQgPSBmdW5jdGlvbiBfc2V0UmVzdWx0QXQoc3RhdGUsIGksIHZhbHVlLCBmaXJzdFBhc3MpIHsKICAgICAgaWYgKGZpcnN0UGFzcykgewogICAgICAgIHRyeSB7CiAgICAgICAgICB0aGlzLl9lYWNoRW50cnkodGhpcy5fbWFwRm4odmFsdWUsIGkpLCBpLCBmYWxzZSk7CiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgIHRoaXMuX3NldHRsZWRBdChSRUpFQ1RFRCwgaSwgZXJyb3IsIGZhbHNlKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fcmVtYWluaW5nLS07CiAgICAgICAgdGhpcy5fcmVzdWx0W2ldID0gdmFsdWU7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIE1hcEVudW1lcmF0b3I7CiAgfShFbnVtZXJhdG9yKTsKICAvKioKICAgYG1hcGAgaXMgc2ltaWxhciB0byBKYXZhU2NyaXB0J3MgbmF0aXZlIGBtYXBgIG1ldGhvZC4gYG1hcEZuYCBpcyBlYWdlcmx5IGNhbGxlZAogICAgbWVhbmluZyB0aGF0IGFzIHNvb24gYXMgYW55IHByb21pc2UgcmVzb2x2ZXMgaXRzIHZhbHVlIHdpbGwgYmUgcGFzc2VkIHRvIGBtYXBGbmAuCiAgICBgbWFwYCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHdpbGwgYmVjb21lIGZ1bGZpbGxlZCB3aXRoIHRoZSByZXN1bHQgb2YgcnVubmluZwogICAgYG1hcEZuYCBvbiB0aGUgdmFsdWVzIHRoZSBwcm9taXNlcyBiZWNvbWUgZnVsZmlsbGVkIHdpdGguCiAgCiAgICBGb3IgZXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IG1hcCwgcmVzb2x2ZSB9IGZyb20gJ3JzdnAnOwogIAogICAgbGV0IHByb21pc2UxID0gcmVzb2x2ZSgxKTsKICAgIGxldCBwcm9taXNlMiA9IHJlc29sdmUoMik7CiAgICBsZXQgcHJvbWlzZTMgPSByZXNvbHZlKDMpOwogICAgbGV0IHByb21pc2VzID0gWyBwcm9taXNlMSwgcHJvbWlzZTIsIHByb21pc2UzIF07CiAgCiAgICBsZXQgbWFwRm4gPSBmdW5jdGlvbihpdGVtKXsKICAgICAgcmV0dXJuIGl0ZW0gKyAxOwogICAgfTsKICAKICAgIG1hcChwcm9taXNlcywgbWFwRm4pLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXsKICAgICAgLy8gcmVzdWx0IGlzIFsgMiwgMywgNCBdCiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgYW55IG9mIHRoZSBgcHJvbWlzZXNgIGdpdmVuIHRvIGBtYXBgIGFyZSByZWplY3RlZCwgdGhlIGZpcnN0IHByb21pc2UKICAgIHRoYXQgaXMgcmVqZWN0ZWQgd2lsbCBiZSBnaXZlbiBhcyBhbiBhcmd1bWVudCB0byB0aGUgcmV0dXJuZWQgcHJvbWlzZSdzCiAgICByZWplY3Rpb24gaGFuZGxlci4gRm9yIGV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBtYXAsIHJlamVjdCwgcmVzb2x2ZSB9IGZyb20gJ3JzdnAnOwogIAogICAgbGV0IHByb21pc2UxID0gcmVzb2x2ZSgxKTsKICAgIGxldCBwcm9taXNlMiA9IHJlamVjdChuZXcgRXJyb3IoJzInKSk7CiAgICBsZXQgcHJvbWlzZTMgPSByZWplY3QobmV3IEVycm9yKCczJykpOwogICAgbGV0IHByb21pc2VzID0gWyBwcm9taXNlMSwgcHJvbWlzZTIsIHByb21pc2UzIF07CiAgCiAgICBsZXQgbWFwRm4gPSBmdW5jdGlvbihpdGVtKXsKICAgICAgcmV0dXJuIGl0ZW0gKyAxOwogICAgfTsKICAKICAgIG1hcChwcm9taXNlcywgbWFwRm4pLnRoZW4oZnVuY3Rpb24oYXJyYXkpewogICAgICAvLyBDb2RlIGhlcmUgbmV2ZXIgcnVucyBiZWNhdXNlIHRoZXJlIGFyZSByZWplY3RlZCBwcm9taXNlcyEKICAgIH0sIGZ1bmN0aW9uKHJlYXNvbikgewogICAgICAvLyByZWFzb24ubWVzc2FnZSA9PT0gJzInCiAgICB9KTsKICAgIGBgYAogIAogICAgYG1hcGAgd2lsbCBhbHNvIHdhaXQgaWYgYSBwcm9taXNlIGlzIHJldHVybmVkIGZyb20gYG1hcEZuYC4gRm9yIGV4YW1wbGUsCiAgICBzYXkgeW91IHdhbnQgdG8gZ2V0IGFsbCBjb21tZW50cyBmcm9tIGEgc2V0IG9mIGJsb2cgcG9zdHMsIGJ1dCB5b3UgbmVlZAogICAgdGhlIGJsb2cgcG9zdHMgZmlyc3QgYmVjYXVzZSB0aGV5IGNvbnRhaW4gYSB1cmwgdG8gdGhvc2UgY29tbWVudHMuCiAgCiAgICBgYGBqYXZzY3JpcHQKICAgIGltcG9ydCB7IG1hcCB9IGZyb20gJ3JzdnAnOwogIAogICAgbGV0IG1hcEZuID0gZnVuY3Rpb24oYmxvZ1Bvc3QpewogICAgICAvLyBnZXRDb21tZW50cyBkb2VzIHNvbWUgYWpheCBhbmQgcmV0dXJucyBhbiBQcm9taXNlIHRoYXQgaXMgZnVsZmlsbGVkCiAgICAgIC8vIHdpdGggc29tZSBjb21tZW50cyBkYXRhCiAgICAgIHJldHVybiBnZXRDb21tZW50cyhibG9nUG9zdC5jb21tZW50c191cmwpOwogICAgfTsKICAKICAgIC8vIGdldEJsb2dQb3N0cyBkb2VzIHNvbWUgYWpheCBhbmQgcmV0dXJucyBhbiBQcm9taXNlIHRoYXQgaXMgZnVsZmlsbGVkCiAgICAvLyB3aXRoIHNvbWUgYmxvZyBwb3N0IGRhdGEKICAgIG1hcChnZXRCbG9nUG9zdHMoKSwgbWFwRm4pLnRoZW4oZnVuY3Rpb24oY29tbWVudHMpewogICAgICAvLyBjb21tZW50cyBpcyB0aGUgcmVzdWx0IG9mIGFza2luZyB0aGUgc2VydmVyIGZvciB0aGUgY29tbWVudHMKICAgICAgLy8gb2YgYWxsIGJsb2cgcG9zdHMgcmV0dXJuZWQgZnJvbSBnZXRCbG9nUG9zdHMoKQogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgbWFwCiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIHJzdnAKICAgIEBwYXJhbSB7QXJyYXl9IHByb21pc2VzCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBtYXBGbiBmdW5jdGlvbiB0byBiZSBjYWxsZWQgb24gZWFjaCBmdWxmaWxsZWQgcHJvbWlzZS4KICAgIEBwYXJhbSB7U3RyaW5nfSBbbGFiZWxdIG9wdGlvbmFsIHN0cmluZyBmb3IgbGFiZWxpbmcgdGhlIHByb21pc2UuCiAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHRoYXQgaXMgZnVsZmlsbGVkIHdpdGggdGhlIHJlc3VsdCBvZiBjYWxsaW5nCiAgICBgbWFwRm5gIG9uIGVhY2ggZnVsZmlsbGVkIHByb21pc2Ugb3IgdmFsdWUgd2hlbiB0aGV5IGJlY29tZSBmdWxmaWxsZWQuCiAgICAgVGhlIHByb21pc2Ugd2lsbCBiZSByZWplY3RlZCBpZiBhbnkgb2YgdGhlIGdpdmVuIGBwcm9taXNlc2AgYmVjb21lIHJlamVjdGVkLgogICovCgoKICBmdW5jdGlvbiBtYXAocHJvbWlzZXMsIG1hcEZuLCBsYWJlbCkgewogICAgaWYgKHR5cGVvZiBtYXBGbiAhPT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IFR5cGVFcnJvcigibWFwIGV4cGVjdHMgYSBmdW5jdGlvbiBhcyBhIHNlY29uZCBhcmd1bWVudCIpLCBsYWJlbCk7CiAgICB9CgogICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwcm9taXNlcywgbGFiZWwpLnRoZW4oZnVuY3Rpb24gKHByb21pc2VzKSB7CiAgICAgIGlmICghQXJyYXkuaXNBcnJheShwcm9taXNlcykpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJtYXAgbXVzdCBiZSBjYWxsZWQgd2l0aCBhbiBhcnJheSIpOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IE1hcEVudW1lcmF0b3IoUHJvbWlzZSwgcHJvbWlzZXMsIG1hcEZuLCBsYWJlbCkucHJvbWlzZTsKICAgIH0pOwogIH0KICAvKioKICAgIFRoaXMgaXMgYSBjb252ZW5pZW50IGFsaWFzIGZvciBgUHJvbWlzZS5yZXNvbHZlYC4KICAKICAgIEBtZXRob2QgcmVzb2x2ZQogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQGZvciByc3ZwCiAgICBAcGFyYW0geyp9IHZhbHVlIHZhbHVlIHRoYXQgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCBiZSByZXNvbHZlZCB3aXRoCiAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGlkZW50aWZ5aW5nIHRoZSByZXR1cm5lZCBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHRoYXQgd2lsbCBiZWNvbWUgZnVsZmlsbGVkIHdpdGggdGhlIGdpdmVuCiAgICBgdmFsdWVgCiAgKi8KCgogIGZ1bmN0aW9uIHJlc29sdmUkMih2YWx1ZSwgbGFiZWwpIHsKICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodmFsdWUsIGxhYmVsKTsKICB9CiAgLyoqCiAgICBUaGlzIGlzIGEgY29udmVuaWVudCBhbGlhcyBmb3IgYFByb21pc2UucmVqZWN0YC4KICAKICAgIEBtZXRob2QgcmVqZWN0CiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIHJzdnAKICAgIEBwYXJhbSB7Kn0gcmVhc29uIHZhbHVlIHRoYXQgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoLgogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGZvciBpZGVudGlmeWluZyB0aGUgcmV0dXJuZWQgcHJvbWlzZS4KICAgIFVzZWZ1bCBmb3IgdG9vbGluZy4KICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSByZWplY3RlZCB3aXRoIHRoZSBnaXZlbiBgcmVhc29uYC4KICAqLwoKCiAgZnVuY3Rpb24gcmVqZWN0JDIocmVhc29uLCBsYWJlbCkgewogICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHJlYXNvbiwgbGFiZWwpOwogIH0KCiAgdmFyIEVNUFRZX09CSkVDVCA9IHt9OwoKICB2YXIgRmlsdGVyRW51bWVyYXRvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfTWFwRW51bWVyYXRvcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEZpbHRlckVudW1lcmF0b3IsIF9NYXBFbnVtZXJhdG9yKTsKCiAgICBmdW5jdGlvbiBGaWx0ZXJFbnVtZXJhdG9yKCkgewogICAgICByZXR1cm4gX01hcEVudW1lcmF0b3IuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG81ID0gRmlsdGVyRW51bWVyYXRvci5wcm90b3R5cGU7CgogICAgX3Byb3RvNS5fY2hlY2tGdWxsZmlsbG1lbnQgPSBmdW5jdGlvbiBfY2hlY2tGdWxsZmlsbG1lbnQoKSB7CiAgICAgIGlmICh0aGlzLl9yZW1haW5pbmcgPT09IDAgJiYgdGhpcy5fcmVzdWx0ICE9PSBudWxsKSB7CiAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuX3Jlc3VsdC5maWx0ZXIoZnVuY3Rpb24gKHZhbCkgewogICAgICAgICAgcmV0dXJuIHZhbCAhPT0gRU1QVFlfT0JKRUNUOwogICAgICAgIH0pOwoKICAgICAgICBmdWxmaWxsKHRoaXMucHJvbWlzZSwgcmVzdWx0KTsKICAgICAgICB0aGlzLl9yZXN1bHQgPSBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzUuX3NldFJlc3VsdEF0ID0gZnVuY3Rpb24gX3NldFJlc3VsdEF0KHN0YXRlLCBpLCB2YWx1ZSwgZmlyc3RQYXNzKSB7CiAgICAgIGlmIChmaXJzdFBhc3MpIHsKICAgICAgICB0aGlzLl9yZXN1bHRbaV0gPSB2YWx1ZTsKICAgICAgICB2YXIgdmFsLAogICAgICAgICAgICBzdWNjZWVkZWQgPSB0cnVlOwoKICAgICAgICB0cnkgewogICAgICAgICAgdmFsID0gdGhpcy5fbWFwRm4odmFsdWUsIGkpOwogICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICBzdWNjZWVkZWQgPSBmYWxzZTsKCiAgICAgICAgICB0aGlzLl9zZXR0bGVkQXQoUkVKRUNURUQsIGksIGVycm9yLCBmYWxzZSk7CiAgICAgICAgfQoKICAgICAgICBpZiAoc3VjY2VlZGVkKSB7CiAgICAgICAgICB0aGlzLl9lYWNoRW50cnkodmFsLCBpLCBmYWxzZSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuX3JlbWFpbmluZy0tOwoKICAgICAgICBpZiAoIXZhbHVlKSB7CiAgICAgICAgICB0aGlzLl9yZXN1bHRbaV0gPSBFTVBUWV9PQkpFQ1Q7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBGaWx0ZXJFbnVtZXJhdG9yOwogIH0oTWFwRW51bWVyYXRvcik7CiAgLyoqCiAgIGBmaWx0ZXJgIGlzIHNpbWlsYXIgdG8gSmF2YVNjcmlwdCdzIG5hdGl2ZSBgZmlsdGVyYCBtZXRob2QuCiAgIGBmaWx0ZXJGbmAgaXMgZWFnZXJseSBjYWxsZWQgbWVhbmluZyB0aGF0IGFzIHNvb24gYXMgYW55IHByb21pc2UKICAgIHJlc29sdmVzIGl0cyB2YWx1ZSB3aWxsIGJlIHBhc3NlZCB0byBgZmlsdGVyRm5gLiBgZmlsdGVyYCByZXR1cm5zCiAgICBhIHByb21pc2UgdGhhdCB3aWxsIGJlY29tZSBmdWxmaWxsZWQgd2l0aCB0aGUgcmVzdWx0IG9mIHJ1bm5pbmcKICAgIGBmaWx0ZXJGbmAgb24gdGhlIHZhbHVlcyB0aGUgcHJvbWlzZXMgYmVjb21lIGZ1bGZpbGxlZCB3aXRoLgogIAogICAgRm9yIGV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBmaWx0ZXIsIHJlc29sdmUgfSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlMSA9IHJlc29sdmUoMSk7CiAgICBsZXQgcHJvbWlzZTIgPSByZXNvbHZlKDIpOwogICAgbGV0IHByb21pc2UzID0gcmVzb2x2ZSgzKTsKICAKICAgIGxldCBwcm9taXNlcyA9IFtwcm9taXNlMSwgcHJvbWlzZTIsIHByb21pc2UzXTsKICAKICAgIGxldCBmaWx0ZXJGbiA9IGZ1bmN0aW9uKGl0ZW0pewogICAgICByZXR1cm4gaXRlbSA+IDE7CiAgICB9OwogIAogICAgZmlsdGVyKHByb21pc2VzLCBmaWx0ZXJGbikudGhlbihmdW5jdGlvbihyZXN1bHQpewogICAgICAvLyByZXN1bHQgaXMgWyAyLCAzIF0KICAgIH0pOwogICAgYGBgCiAgCiAgICBJZiBhbnkgb2YgdGhlIGBwcm9taXNlc2AgZ2l2ZW4gdG8gYGZpbHRlcmAgYXJlIHJlamVjdGVkLCB0aGUgZmlyc3QgcHJvbWlzZQogICAgdGhhdCBpcyByZWplY3RlZCB3aWxsIGJlIGdpdmVuIGFzIGFuIGFyZ3VtZW50IHRvIHRoZSByZXR1cm5lZCBwcm9taXNlJ3MKICAgIHJlamVjdGlvbiBoYW5kbGVyLiBGb3IgZXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGZpbHRlciwgcmVqZWN0LCByZXNvbHZlIH0gZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgcHJvbWlzZTEgPSByZXNvbHZlKDEpOwogICAgbGV0IHByb21pc2UyID0gcmVqZWN0KG5ldyBFcnJvcignMicpKTsKICAgIGxldCBwcm9taXNlMyA9IHJlamVjdChuZXcgRXJyb3IoJzMnKSk7CiAgICBsZXQgcHJvbWlzZXMgPSBbIHByb21pc2UxLCBwcm9taXNlMiwgcHJvbWlzZTMgXTsKICAKICAgIGxldCBmaWx0ZXJGbiA9IGZ1bmN0aW9uKGl0ZW0pewogICAgICByZXR1cm4gaXRlbSA+IDE7CiAgICB9OwogIAogICAgZmlsdGVyKHByb21pc2VzLCBmaWx0ZXJGbikudGhlbihmdW5jdGlvbihhcnJheSl7CiAgICAgIC8vIENvZGUgaGVyZSBuZXZlciBydW5zIGJlY2F1c2UgdGhlcmUgYXJlIHJlamVjdGVkIHByb21pc2VzIQogICAgfSwgZnVuY3Rpb24ocmVhc29uKSB7CiAgICAgIC8vIHJlYXNvbi5tZXNzYWdlID09PSAnMicKICAgIH0pOwogICAgYGBgCiAgCiAgICBgZmlsdGVyYCB3aWxsIGFsc28gd2FpdCBmb3IgYW55IHByb21pc2VzIHJldHVybmVkIGZyb20gYGZpbHRlckZuYC4KICAgIEZvciBpbnN0YW5jZSwgeW91IG1heSB3YW50IHRvIGZldGNoIGEgbGlzdCBvZiB1c2VycyB0aGVuIHJldHVybiBhIHN1YnNldAogICAgb2YgdGhvc2UgdXNlcnMgYmFzZWQgb24gc29tZSBhc3luY2hyb25vdXMgb3BlcmF0aW9uOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZmlsdGVyLCByZXNvbHZlIH0gZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgYWxpY2UgPSB7IG5hbWU6ICdhbGljZScgfTsKICAgIGxldCBib2IgICA9IHsgbmFtZTogJ2JvYicgfTsKICAgIGxldCB1c2VycyA9IFsgYWxpY2UsIGJvYiBdOwogIAogICAgbGV0IHByb21pc2VzID0gdXNlcnMubWFwKGZ1bmN0aW9uKHVzZXIpewogICAgICByZXR1cm4gcmVzb2x2ZSh1c2VyKTsKICAgIH0pOwogIAogICAgbGV0IGZpbHRlckZuID0gZnVuY3Rpb24odXNlcil7CiAgICAgIC8vIEhlcmUsIEFsaWNlIGhhcyBwZXJtaXNzaW9ucyB0byBjcmVhdGUgYSBibG9nIHBvc3QsIGJ1dCBCb2IgZG9lcyBub3QuCiAgICAgIHJldHVybiBnZXRQcml2aWxlZ2VzRm9yVXNlcih1c2VyKS50aGVuKGZ1bmN0aW9uKHByaXZzKXsKICAgICAgICByZXR1cm4gcHJpdnMuY2FuX2NyZWF0ZV9ibG9nX3Bvc3QgPT09IHRydWU7CiAgICAgIH0pOwogICAgfTsKICAgIGZpbHRlcihwcm9taXNlcywgZmlsdGVyRm4pLnRoZW4oZnVuY3Rpb24odXNlcnMpewogICAgICAvLyB0cnVlLCBiZWNhdXNlIHRoZSBzZXJ2ZXIgdG9sZCB1cyBvbmx5IEFsaWNlIGNhbiBjcmVhdGUgYSBibG9nIHBvc3QuCiAgICAgIHVzZXJzLmxlbmd0aCA9PT0gMTsKICAgICAgLy8gZmFsc2UsIGJlY2F1c2UgQWxpY2UgaXMgdGhlIG9ubHkgdXNlciBwcmVzZW50IGluIGB1c2Vyc2AKICAgICAgdXNlcnNbMF0gPT09IGJvYjsKICAgIH0pOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGZpbHRlcgogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQGZvciByc3ZwCiAgICBAcGFyYW0ge0FycmF5fSBwcm9taXNlcwogICAgQHBhcmFtIHtGdW5jdGlvbn0gZmlsdGVyRm4gLSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgb24gZWFjaCByZXNvbHZlZCB2YWx1ZSB0bwogICAgZmlsdGVyIHRoZSBmaW5hbCByZXN1bHRzLgogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGRlc2NyaWJpbmcgdGhlIHByb21pc2UuIFVzZWZ1bCBmb3IKICAgIHRvb2xpbmcuCiAgICBAcmV0dXJuIHtQcm9taXNlfQogICovCgoKICBmdW5jdGlvbiBmaWx0ZXIocHJvbWlzZXMsIGZpbHRlckZuLCBsYWJlbCkgewogICAgaWYgKHR5cGVvZiBmaWx0ZXJGbiAhPT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IFR5cGVFcnJvcigiZmlsdGVyIGV4cGVjdHMgZnVuY3Rpb24gYXMgYSBzZWNvbmQgYXJndW1lbnQiKSwgbGFiZWwpOwogICAgfQoKICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocHJvbWlzZXMsIGxhYmVsKS50aGVuKGZ1bmN0aW9uIChwcm9taXNlcykgewogICAgICBpZiAoIUFycmF5LmlzQXJyYXkocHJvbWlzZXMpKSB7CiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiZmlsdGVyIG11c3QgYmUgY2FsbGVkIHdpdGggYW4gYXJyYXkiKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5ldyBGaWx0ZXJFbnVtZXJhdG9yKFByb21pc2UsIHByb21pc2VzLCBmaWx0ZXJGbiwgbGFiZWwpLnByb21pc2U7CiAgICB9KTsKICB9CgogIHZhciBsZW4gPSAwOwogIHZhciB2ZXJ0eE5leHQ7CgogIGZ1bmN0aW9uIGFzYXAoY2FsbGJhY2ssIGFyZykgewogICAgcXVldWUkMVtsZW5dID0gY2FsbGJhY2s7CiAgICBxdWV1ZSQxW2xlbiArIDFdID0gYXJnOwogICAgbGVuICs9IDI7CgogICAgaWYgKGxlbiA9PT0gMikgewogICAgICAvLyBJZiBsZW4gaXMgMSwgdGhhdCBtZWFucyB0aGF0IHdlIG5lZWQgdG8gc2NoZWR1bGUgYW4gYXN5bmMgZmx1c2guCiAgICAgIC8vIElmIGFkZGl0aW9uYWwgY2FsbGJhY2tzIGFyZSBxdWV1ZWQgYmVmb3JlIHRoZSBxdWV1ZSBpcyBmbHVzaGVkLCB0aGV5CiAgICAgIC8vIHdpbGwgYmUgcHJvY2Vzc2VkIGJ5IHRoaXMgZmx1c2ggdGhhdCB3ZSBhcmUgc2NoZWR1bGluZy4KICAgICAgc2NoZWR1bGVGbHVzaCQxKCk7CiAgICB9CiAgfQoKICB2YXIgYnJvd3NlcldpbmRvdyA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93IDogdW5kZWZpbmVkOwogIHZhciBicm93c2VyR2xvYmFsID0gYnJvd3NlcldpbmRvdyB8fCB7fTsKICB2YXIgQnJvd3Nlck11dGF0aW9uT2JzZXJ2ZXIgPSBicm93c2VyR2xvYmFsLk11dGF0aW9uT2JzZXJ2ZXIgfHwgYnJvd3Nlckdsb2JhbC5XZWJLaXRNdXRhdGlvbk9ic2VydmVyOwogIHZhciBpc05vZGUgPSB0eXBlb2Ygc2VsZiA9PT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmIHt9LnRvU3RyaW5nLmNhbGwocHJvY2VzcykgPT09ICdbb2JqZWN0IHByb2Nlc3NdJzsgLy8gdGVzdCBmb3Igd2ViIHdvcmtlciBidXQgbm90IGluIElFMTAKCiAgdmFyIGlzV29ya2VyID0gdHlwZW9mIFVpbnQ4Q2xhbXBlZEFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgaW1wb3J0U2NyaXB0cyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIE1lc3NhZ2VDaGFubmVsICE9PSAndW5kZWZpbmVkJzsgLy8gbm9kZQoKICBmdW5jdGlvbiB1c2VOZXh0VGljaygpIHsKICAgIHZhciBuZXh0VGljayA9IHByb2Nlc3MubmV4dFRpY2s7IC8vIG5vZGUgdmVyc2lvbiAwLjEwLnggZGlzcGxheXMgYSBkZXByZWNhdGlvbiB3YXJuaW5nIHdoZW4gbmV4dFRpY2sgaXMgdXNlZCByZWN1cnNpdmVseQogICAgLy8gc2V0SW1tZWRpYXRlIHNob3VsZCBiZSB1c2VkIGluc3RlYWQgaW5zdGVhZAoKICAgIHZhciB2ZXJzaW9uID0gcHJvY2Vzcy52ZXJzaW9ucy5ub2RlLm1hdGNoKC9eKD86KFxkKylcLik/KD86KFxkKylcLik/KFwqfFxkKykkLyk7CgogICAgaWYgKEFycmF5LmlzQXJyYXkodmVyc2lvbikgJiYgdmVyc2lvblsxXSA9PT0gJzAnICYmIHZlcnNpb25bMl0gPT09ICcxMCcpIHsKICAgICAgbmV4dFRpY2sgPSBzZXRJbW1lZGlhdGU7CiAgICB9CgogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIG5leHRUaWNrKGZsdXNoKTsKICAgIH07CiAgfSAvLyB2ZXJ0eAoKCiAgZnVuY3Rpb24gdXNlVmVydHhUaW1lcigpIHsKICAgIGlmICh0eXBlb2YgdmVydHhOZXh0ICE9PSAndW5kZWZpbmVkJykgewogICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgIHZlcnR4TmV4dChmbHVzaCk7CiAgICAgIH07CiAgICB9CgogICAgcmV0dXJuIHVzZVNldFRpbWVvdXQoKTsKICB9CgogIGZ1bmN0aW9uIHVzZU11dGF0aW9uT2JzZXJ2ZXIoKSB7CiAgICB2YXIgaXRlcmF0aW9ucyA9IDA7CiAgICB2YXIgb2JzZXJ2ZXIgPSBuZXcgQnJvd3Nlck11dGF0aW9uT2JzZXJ2ZXIoZmx1c2gpOwogICAgdmFyIG5vZGUgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJyk7CiAgICBvYnNlcnZlci5vYnNlcnZlKG5vZGUsIHsKICAgICAgY2hhcmFjdGVyRGF0YTogdHJ1ZQogICAgfSk7CiAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gbm9kZS5kYXRhID0gaXRlcmF0aW9ucyA9ICsraXRlcmF0aW9ucyAlIDI7CiAgICB9OwogIH0gLy8gd2ViIHdvcmtlcgoKCiAgZnVuY3Rpb24gdXNlTWVzc2FnZUNoYW5uZWwoKSB7CiAgICB2YXIgY2hhbm5lbCA9IG5ldyBNZXNzYWdlQ2hhbm5lbCgpOwogICAgY2hhbm5lbC5wb3J0MS5vbm1lc3NhZ2UgPSBmbHVzaDsKICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBjaGFubmVsLnBvcnQyLnBvc3RNZXNzYWdlKDApOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIHVzZVNldFRpbWVvdXQoKSB7CiAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gc2V0VGltZW91dChmbHVzaCwgMSk7CiAgICB9OwogIH0KCiAgdmFyIHF1ZXVlJDEgPSBuZXcgQXJyYXkoMTAwMCk7CgogIGZ1bmN0aW9uIGZsdXNoKCkgewogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkgKz0gMikgewogICAgICB2YXIgY2FsbGJhY2sgPSBxdWV1ZSQxW2ldOwogICAgICB2YXIgYXJnID0gcXVldWUkMVtpICsgMV07CiAgICAgIGNhbGxiYWNrKGFyZyk7CiAgICAgIHF1ZXVlJDFbaV0gPSB1bmRlZmluZWQ7CiAgICAgIHF1ZXVlJDFbaSArIDFdID0gdW5kZWZpbmVkOwogICAgfQoKICAgIGxlbiA9IDA7CiAgfQoKICBmdW5jdGlvbiBhdHRlbXB0VmVydGV4KCkgewogICAgdHJ5IHsKICAgICAgdmFyIHZlcnR4ID0gRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKS5yZXF1aXJlKCd2ZXJ0eCcpOwoKICAgICAgdmVydHhOZXh0ID0gdmVydHgucnVuT25Mb29wIHx8IHZlcnR4LnJ1bk9uQ29udGV4dDsKICAgICAgcmV0dXJuIHVzZVZlcnR4VGltZXIoKTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgcmV0dXJuIHVzZVNldFRpbWVvdXQoKTsKICAgIH0KICB9CgogIHZhciBzY2hlZHVsZUZsdXNoJDE7IC8vIERlY2lkZSB3aGF0IGFzeW5jIG1ldGhvZCB0byB1c2UgdG8gdHJpZ2dlcmluZyBwcm9jZXNzaW5nIG9mIHF1ZXVlZCBjYWxsYmFja3M6CgogIGlmIChpc05vZGUpIHsKICAgIHNjaGVkdWxlRmx1c2gkMSA9IHVzZU5leHRUaWNrKCk7CiAgfSBlbHNlIGlmIChCcm93c2VyTXV0YXRpb25PYnNlcnZlcikgewogICAgc2NoZWR1bGVGbHVzaCQxID0gdXNlTXV0YXRpb25PYnNlcnZlcigpOwogIH0gZWxzZSBpZiAoaXNXb3JrZXIpIHsKICAgIHNjaGVkdWxlRmx1c2gkMSA9IHVzZU1lc3NhZ2VDaGFubmVsKCk7CiAgfSBlbHNlIGlmIChicm93c2VyV2luZG93ID09PSB1bmRlZmluZWQgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicpIHsKICAgIHNjaGVkdWxlRmx1c2gkMSA9IGF0dGVtcHRWZXJ0ZXgoKTsKICB9IGVsc2UgewogICAgc2NoZWR1bGVGbHVzaCQxID0gdXNlU2V0VGltZW91dCgpOwogIH0gLy8gZGVmYXVsdHMKCgogIGNvbmZpZy5hc3luYyA9IGFzYXA7CgogIGNvbmZpZy5hZnRlciA9IGZ1bmN0aW9uIChjYikgewogICAgcmV0dXJuIHNldFRpbWVvdXQoY2IsIDApOwogIH07CgogIHZhciBjYXN0ID0gcmVzb2x2ZSQyOwogIF9leHBvcnRzLmNhc3QgPSBjYXN0OwoKICB2YXIgYXN5bmMgPSBmdW5jdGlvbiBhc3luYyhjYWxsYmFjaywgYXJnKSB7CiAgICByZXR1cm4gY29uZmlnLmFzeW5jKGNhbGxiYWNrLCBhcmcpOwogIH07CgogIF9leHBvcnRzLmFzeW5jID0gYXN5bmM7CgogIGZ1bmN0aW9uIG9uKCkgewogICAgY29uZmlnLm9uLmFwcGx5KGNvbmZpZywgYXJndW1lbnRzKTsKICB9CgogIGZ1bmN0aW9uIG9mZigpIHsKICAgIGNvbmZpZy5vZmYuYXBwbHkoY29uZmlnLCBhcmd1bWVudHMpOwogIH0gLy8gU2V0IHVwIGluc3RydW1lbnRhdGlvbiB0aHJvdWdoIGB3aW5kb3cuX19QUk9NSVNFX0lOVFJVTUVOVEFUSU9OX19gCgoKICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHdpbmRvd1snX19QUk9NSVNFX0lOU1RSVU1FTlRBVElPTl9fJ10gPT09ICdvYmplY3QnKSB7CiAgICB2YXIgY2FsbGJhY2tzID0gd2luZG93WydfX1BST01JU0VfSU5TVFJVTUVOVEFUSU9OX18nXTsKICAgIGNvbmZpZ3VyZSgnaW5zdHJ1bWVudCcsIHRydWUpOwoKICAgIGZvciAodmFyIGV2ZW50TmFtZSBpbiBjYWxsYmFja3MpIHsKICAgICAgaWYgKGNhbGxiYWNrcy5oYXNPd25Qcm9wZXJ0eShldmVudE5hbWUpKSB7CiAgICAgICAgb24oZXZlbnROYW1lLCBjYWxsYmFja3NbZXZlbnROYW1lXSk7CiAgICAgIH0KICAgIH0KICB9IC8vIHRoZSBkZWZhdWx0IGV4cG9ydCBoZXJlIGlzIGZvciBiYWNrd2FyZHMgY29tcGF0OgogIC8vICAgaHR0cHM6Ly9naXRodWIuY29tL3RpbGRlaW8vcnN2cC5qcy9pc3N1ZXMvNDM0CgoKICB2YXIgcnN2cCA9IHsKICAgIGFzYXA6IGFzYXAsCiAgICBjYXN0OiBjYXN0LAogICAgUHJvbWlzZTogUHJvbWlzZSwKICAgIEV2ZW50VGFyZ2V0OiBFdmVudFRhcmdldCwKICAgIGFsbDogYWxsJDEsCiAgICBhbGxTZXR0bGVkOiBhbGxTZXR0bGVkLAogICAgcmFjZTogcmFjZSQxLAogICAgaGFzaDogaGFzaCwKICAgIGhhc2hTZXR0bGVkOiBoYXNoU2V0dGxlZCwKICAgIHJldGhyb3c6IHJldGhyb3csCiAgICBkZWZlcjogZGVmZXIsCiAgICBkZW5vZGVpZnk6IGRlbm9kZWlmeSwKICAgIGNvbmZpZ3VyZTogY29uZmlndXJlLAogICAgb246IG9uLAogICAgb2ZmOiBvZmYsCiAgICByZXNvbHZlOiByZXNvbHZlJDIsCiAgICByZWplY3Q6IHJlamVjdCQyLAogICAgbWFwOiBtYXAsCiAgICBhc3luYzogYXN5bmMsCiAgICBmaWx0ZXI6IGZpbHRlcgogIH07CiAgdmFyIF9kZWZhdWx0ID0gcnN2cDsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpyZXF1aXJlKCdlbWJlcicpOwp9KCkpOwovLyMgc291cmNlTWFwcGluZ1VSTD1lbWJlci5tYXAKCjtkZWZpbmUoJ0BlbWJlci1kYXRhL2FkYXB0ZXIvLXByaXZhdGUnLCBbJ2V4cG9ydHMnLCAncmVxdWlyZScsICdlbWJlci1pbmZsZWN0b3InXSwgZnVuY3Rpb24gKGV4cG9ydHMsIHJlcXVpcmUsIGVtYmVySW5mbGVjdG9yKSB7ICd1c2Ugc3RyaWN0JzsKCiAgdmFyIHJlcXVpcmVfX2RlZmF1bHQgPSAnZGVmYXVsdCcgaW4gcmVxdWlyZSA/IHJlcXVpcmVbJ2RlZmF1bHQnXSA6IHJlcXVpcmU7CgogIHZhciBuZXdsaW5lID0gL1xyP1xuLzsKICBmdW5jdGlvbiBwYXJzZVJlc3BvbnNlSGVhZGVycyhoZWFkZXJzU3RyaW5nKSB7CiAgICB2YXIgaGVhZGVycyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CgogICAgaWYgKCFoZWFkZXJzU3RyaW5nKSB7CiAgICAgIHJldHVybiBoZWFkZXJzOwogICAgfQoKICAgIHZhciBoZWFkZXJQYWlycyA9IGhlYWRlcnNTdHJpbmcuc3BsaXQobmV3bGluZSk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoZWFkZXJQYWlycy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgaGVhZGVyID0gaGVhZGVyUGFpcnNbaV07CiAgICAgIHZhciBqID0gMDsKICAgICAgdmFyIGZvdW5kU2VwID0gZmFsc2U7CgogICAgICBmb3IgKDsgaiA8IGhlYWRlci5sZW5ndGg7IGorKykgewogICAgICAgIGlmIChoZWFkZXIuY2hhckNvZGVBdChqKSA9PT0gNTgKICAgICAgICAvKiAnOicgKi8KICAgICAgICApIHsKICAgICAgICAgICAgZm91bmRTZXAgPSB0cnVlOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKGZvdW5kU2VwID09PSBmYWxzZSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICB2YXIgZmllbGQgPSBoZWFkZXIuc3Vic3RyaW5nKDAsIGopLnRyaW0oKTsKICAgICAgdmFyIHZhbHVlID0gaGVhZGVyLnN1YnN0cmluZyhqICsgMSwgaGVhZGVyLmxlbmd0aCkudHJpbSgpOwoKICAgICAgaWYgKHZhbHVlKSB7CiAgICAgICAgdmFyIGxvd2VyQ2FzZWRGaWVsZCA9IGZpZWxkLnRvTG93ZXJDYXNlKCk7CiAgICAgICAgaGVhZGVyc1tsb3dlckNhc2VkRmllbGRdID0gdmFsdWU7CiAgICAgICAgaGVhZGVyc1tmaWVsZF0gPSB2YWx1ZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBoZWFkZXJzOwogIH0KCiAgLyoKICAgKiBGdW5jdGlvbiB0aGF0IGFsd2F5cyBhdHRlbXB0cyB0byBwYXJzZSB0aGUgcmVzcG9uc2UgYXMganNvbiwgYW5kIGlmIGFuIGVycm9yIGlzIHRocm93biwKICAgKiByZXR1cm5zIGB1bmRlZmluZWRgIGlmIHRoZSByZXNwb25zZSBpcyBzdWNjZXNzZnVsIGFuZCBoYXMgYSBzdGF0dXMgY29kZSBvZiAyMDQgKE5vIENvbnRlbnQpLAogICAqIG9yIDIwNSAoUmVzZXQgQ29udGVudCkgb3IgaWYgdGhlIHJlcXVlc3QgbWV0aG9kIHdhcyAnSEVBRCcsIGFuZCB0aGUgcGxhaW4gcGF5bG9hZCBvdGhlcndpc2UuCiAgICovCiAgZnVuY3Rpb24gZGV0ZXJtaW5lQm9keVByb21pc2UocmVzcG9uc2UsIHJlcXVlc3REYXRhKSB7CiAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpLnRoZW4oZnVuY3Rpb24gKHBheWxvYWQpIHsKICAgICAgdmFyIHJldCA9IHBheWxvYWQ7CgogICAgICB0cnkgewogICAgICAgIHJldCA9IEpTT04ucGFyc2UocGF5bG9hZCk7CiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgaWYgKCEoZXJyb3IgaW5zdGFuY2VvZiBTeW50YXhFcnJvcikpIHsKICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgIH0KCiAgICAgICAgdmFyIHN0YXR1cyA9IHJlc3BvbnNlLnN0YXR1czsKCiAgICAgICAgaWYgKHJlc3BvbnNlLm9rICYmIChzdGF0dXMgPT09IDIwNCB8fCBzdGF0dXMgPT09IDIwNSB8fCByZXF1ZXN0RGF0YS5tZXRob2QgPT09ICdIRUFEJykpIHsKICAgICAgICAgIHJldCA9IHVuZGVmaW5lZDsKICAgICAgICB9IGVsc2UgewoKCiAgICAgICAgICBjb25zb2xlLndhcm4oJ1RoaXMgcmVzcG9uc2Ugd2FzIHVuYWJsZSB0byBiZSBwYXJzZWQgYXMganNvbi4nLCBwYXlsb2FkKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiByZXQ7CiAgICB9KTsKICB9CgogIHZhciBSQlJBQ0tFVCA9IC9cW1xdJC87CgogIGZ1bmN0aW9uIGlzUGxhaW5PYmplY3Qob2JqKSB7CiAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IE9iamVjdF0nOwogIH0KICAvKgogICAqIEhlbHBlciBmdW5jdGlvbiB0aGF0IHR1cm5zIHRoZSBkYXRhL2JvZHkgb2YgYSByZXF1ZXN0IGludG8gYSBxdWVyeSBwYXJhbSBzdHJpbmcuCiAgICogVGhpcyBpcyBkaXJlY3RseSBjb3BpZWQgZnJvbSBqUXVlcnkucGFyYW0uCiAgICovCgoKICBmdW5jdGlvbiBzZXJpYWxpemVRdWVyeVBhcmFtcyhxdWVyeVBhcmFtc09iamVjdCkgewogICAgdmFyIHMgPSBbXTsKCiAgICBmdW5jdGlvbiBidWlsZFBhcmFtcyhwcmVmaXgsIG9iaikgewogICAgICB2YXIgaSwgbGVuLCBrZXk7CgogICAgICBpZiAocHJlZml4KSB7CiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkgewogICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gb2JqLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgICAgICAgIGlmIChSQlJBQ0tFVC50ZXN0KHByZWZpeCkpIHsKICAgICAgICAgICAgICBhZGQocywgcHJlZml4LCBvYmpbaV0pOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGJ1aWxkUGFyYW1zKHByZWZpeCArICdbJyArICh0eXBlb2Ygb2JqW2ldID09PSAnb2JqZWN0JyA/IGkgOiAnJykgKyAnXScsIG9ialtpXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGlzUGxhaW5PYmplY3Qob2JqKSkgewogICAgICAgICAgZm9yIChrZXkgaW4gb2JqKSB7CiAgICAgICAgICAgIGJ1aWxkUGFyYW1zKHByZWZpeCArICdbJyArIGtleSArICddJywgb2JqW2tleV0pOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBhZGQocywgcHJlZml4LCBvYmopOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHsKICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBvYmoubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHsKICAgICAgICAgIGFkZChzLCBvYmpbaV0ubmFtZSwgb2JqW2ldLnZhbHVlKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yIChrZXkgaW4gb2JqKSB7CiAgICAgICAgICBidWlsZFBhcmFtcyhrZXksIG9ialtrZXldKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBzOwogICAgfQoKICAgIHJldHVybiBidWlsZFBhcmFtcygnJywgcXVlcnlQYXJhbXNPYmplY3QpLmpvaW4oJyYnKS5yZXBsYWNlKC8lMjAvZywgJysnKTsKICB9CiAgLyoKICAgKiBQYXJ0IG9mIHRoZSBgc2VyaWFsaXplUXVlcnlQYXJhbXNgIGhlbHBlciBmdW5jdGlvbi4KICAgKi8KCiAgZnVuY3Rpb24gYWRkKHMsIGssIHYpIHsKICAgIC8vIFN0cmlwIG91dCBrZXlzIHdpdGggdW5kZWZpbmVkIHZhbHVlIGFuZCByZXBsYWNlIG51bGwgdmFsdWVzIHdpdGgKICAgIC8vIGVtcHR5IHN0cmluZ3MgKG1pbWljcyBqUXVlcnkuYWpheCkKICAgIGlmICh2ID09PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuOwogICAgfSBlbHNlIGlmICh2ID09PSBudWxsKSB7CiAgICAgIHYgPSAnJzsKICAgIH0KCiAgICB2ID0gdHlwZW9mIHYgPT09ICdmdW5jdGlvbicgPyB2KCkgOiB2OwogICAgc1tzLmxlbmd0aF0gPSBlbmNvZGVVUklDb21wb25lbnQoaykgKyAiPSIgKyBlbmNvZGVVUklDb21wb25lbnQodik7CiAgfQoKICB2YXIgX2ZldGNoID0gbnVsbDsKICBmdW5jdGlvbiBnZXRGZXRjaEZ1bmN0aW9uKCkgewogICAgaWYgKF9mZXRjaCAhPT0gbnVsbCkgewogICAgICByZXR1cm4gX2ZldGNoKCk7CiAgICB9CgogICAgaWYgKHJlcXVpcmUuaGFzKCdmZXRjaCcpKSB7CiAgICAgIC8vIHVzZSBgZmV0Y2hgIG1vZHVsZSBieSBkZWZhdWx0LCB0aGlzIGlzIGNvbW1vbmx5IHByb3ZpZGVkIGJ5IGVtYmVyLWZldGNoCiAgICAgIHZhciBmZXRjaEZuID0gcmVxdWlyZV9fZGVmYXVsdCgnZmV0Y2gnKS5kZWZhdWx0OwoKICAgICAgX2ZldGNoID0gZnVuY3Rpb24gX2ZldGNoKCkgewogICAgICAgIHJldHVybiBmZXRjaEZuOwogICAgICB9OwogICAgfSBlbHNlIGlmICh0eXBlb2YgZmV0Y2ggPT09ICdmdW5jdGlvbicpIHsKICAgICAgLy8gZmFsbGJhY2sgdG8gdXNpbmcgZ2xvYmFsIGZldGNoCiAgICAgIF9mZXRjaCA9IGZ1bmN0aW9uIF9mZXRjaCgpIHsKICAgICAgICByZXR1cm4gZmV0Y2g7CiAgICAgIH07CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBmaW5kIHRoZSBgZmV0Y2hgIG1vZHVsZSBvciB0aGUgYGZldGNoYCBnbG9iYWwuIERpZCB5b3UgbWVhbiB0byBpbnN0YWxsIHRoZSBgZW1iZXItZmV0Y2hgIGFkZG9uPycpOwogICAgfQoKICAgIHJldHVybiBfZmV0Y2goKTsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9hZGFwdGVyCiAgKi8KCiAgLyoqCiAgICAjIyBVc2luZyBCdWlsZFVSTE1peGluCgogICAgVG8gdXNlIFVSTCBidWlsZGluZywgaW5jbHVkZSB0aGUgbWl4aW4gd2hlbiBleHRlbmRpbmcgYW4gYWRhcHRlciwgYW5kIGNhbGwgYGJ1aWxkVVJMYCB3aGVyZSBuZWVkZWQuCiAgICBUaGUgZGVmYXVsdCBiZWhhdmlvdXIgaXMgZGVzaWduZWQgZm9yIFJFU1RBZGFwdGVyLgoKICAgICMjIyBFeGFtcGxlCgogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEFkYXB0ZXIsIHsgQnVpbGRVUkxNaXhpbiB9IGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwoKICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKEJ1aWxkVVJMTWl4aW4sIHsKICAgICAgZmluZFJlY29yZDogZnVuY3Rpb24oc3RvcmUsIHR5cGUsIGlkLCBzbmFwc2hvdCkgewogICAgICAgIHZhciB1cmwgPSB0aGlzLmJ1aWxkVVJMKHR5cGUubW9kZWxOYW1lLCBpZCwgc25hcHNob3QsICdmaW5kUmVjb3JkJyk7CiAgICAgICAgcmV0dXJuIHRoaXMuYWpheCh1cmwsICdHRVQnKTsKICAgICAgfQogICAgfSk7CiAgICBgYGAKCiAgICAjIyMgQXR0cmlidXRlcwoKICAgIFRoZSBgaG9zdGAgYW5kIGBuYW1lc3BhY2VgIGF0dHJpYnV0ZXMgd2lsbCBiZSB1c2VkIGlmIGRlZmluZWQsIGFuZCBhcmUgb3B0aW9uYWwuCgogICAgQGNsYXNzIEJ1aWxkVVJMTWl4aW4KICAqLwoKICB2YXIgYnVpbGRVcmxNaXhpbiA9IEVtYmVyLk1peGluLmNyZWF0ZSh7CiAgICAvKioKICAgICAgQnVpbGRzIGEgVVJMIGZvciBhIGdpdmVuIHR5cGUgYW5kIG9wdGlvbmFsIElELgogICAgICAgQnkgZGVmYXVsdCwgaXQgcGx1cmFsaXplcyB0aGUgdHlwZSdzIG5hbWUgKGZvciBleGFtcGxlLCAncG9zdCcKICAgICAgYmVjb21lcyAncG9zdHMnIGFuZCAncGVyc29uJyBiZWNvbWVzICdwZW9wbGUnKS4gVG8gb3ZlcnJpZGUgdGhlCiAgICAgIHBsdXJhbGl6YXRpb24gc2VlIFtwYXRoRm9yVHlwZV0oQnVpbGRVcmxNaXhpbi9tZXRob2RzL3BhdGhGb3JUeXBlP2FuY2hvcj1wYXRoRm9yVHlwZSkuCiAgICAgICBJZiBhbiBJRCBpcyBzcGVjaWZpZWQsIGl0IGFkZHMgdGhlIElEIHRvIHRoZSBwYXRoIGdlbmVyYXRlZAogICAgICBmb3IgdGhlIHR5cGUsIHNlcGFyYXRlZCBieSBhIGAvYC4KICAgICAgIFdoZW4gY2FsbGVkIGJ5IGBSRVNUQWRhcHRlci5maW5kTWFueSgpYCB0aGUgYGlkYCBhbmQgYHNuYXBzaG90YCBwYXJhbWV0ZXJzCiAgICAgIHdpbGwgYmUgYXJyYXlzIG9mIGlkcyBhbmQgc25hcHNob3RzLgogICAgICAgQG1ldGhvZCBidWlsZFVSTAogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7KFN0cmluZ3xBcnJheXxPYmplY3QpfSBpZCBzaW5nbGUgaWQgb3IgYXJyYXkgb2YgaWRzIG9yIHF1ZXJ5CiAgICAgIEBwYXJhbSB7KFNuYXBzaG90fFNuYXBzaG90UmVjb3JkQXJyYXkpfSBzbmFwc2hvdCBzaW5nbGUgc25hcHNob3Qgb3IgYXJyYXkgb2Ygc25hcHNob3RzCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcGFyYW0ge09iamVjdH0gcXVlcnkgb2JqZWN0IG9mIHF1ZXJ5IHBhcmFtZXRlcnMgdG8gc2VuZCBmb3IgcXVlcnkgcmVxdWVzdHMuCiAgICAgIEByZXR1cm4ge1N0cmluZ30gdXJsCiAgICAqLwogICAgYnVpbGRVUkw6IGZ1bmN0aW9uIGJ1aWxkVVJMKG1vZGVsTmFtZSwgaWQsIHNuYXBzaG90LCByZXF1ZXN0VHlwZSwgcXVlcnkpIHsKICAgICAgc3dpdGNoIChyZXF1ZXN0VHlwZSkgewogICAgICAgIGNhc2UgJ2ZpbmRSZWNvcmQnOgogICAgICAgICAgcmV0dXJuIHRoaXMudXJsRm9yRmluZFJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCk7CgogICAgICAgIGNhc2UgJ2ZpbmRBbGwnOgogICAgICAgICAgcmV0dXJuIHRoaXMudXJsRm9yRmluZEFsbChtb2RlbE5hbWUsIHNuYXBzaG90KTsKCiAgICAgICAgY2FzZSAncXVlcnknOgogICAgICAgICAgcmV0dXJuIHRoaXMudXJsRm9yUXVlcnkocXVlcnksIG1vZGVsTmFtZSk7CgogICAgICAgIGNhc2UgJ3F1ZXJ5UmVjb3JkJzoKICAgICAgICAgIHJldHVybiB0aGlzLnVybEZvclF1ZXJ5UmVjb3JkKHF1ZXJ5LCBtb2RlbE5hbWUpOwoKICAgICAgICBjYXNlICdmaW5kTWFueSc6CiAgICAgICAgICByZXR1cm4gdGhpcy51cmxGb3JGaW5kTWFueShpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCk7CgogICAgICAgIGNhc2UgJ2ZpbmRIYXNNYW55JzoKICAgICAgICAgIHJldHVybiB0aGlzLnVybEZvckZpbmRIYXNNYW55KGlkLCBtb2RlbE5hbWUsIHNuYXBzaG90KTsKCiAgICAgICAgY2FzZSAnZmluZEJlbG9uZ3NUbyc6CiAgICAgICAgICByZXR1cm4gdGhpcy51cmxGb3JGaW5kQmVsb25nc1RvKGlkLCBtb2RlbE5hbWUsIHNuYXBzaG90KTsKCiAgICAgICAgY2FzZSAnY3JlYXRlUmVjb3JkJzoKICAgICAgICAgIHJldHVybiB0aGlzLnVybEZvckNyZWF0ZVJlY29yZChtb2RlbE5hbWUsIHNuYXBzaG90KTsKCiAgICAgICAgY2FzZSAndXBkYXRlUmVjb3JkJzoKICAgICAgICAgIHJldHVybiB0aGlzLnVybEZvclVwZGF0ZVJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCk7CgogICAgICAgIGNhc2UgJ2RlbGV0ZVJlY29yZCc6CiAgICAgICAgICByZXR1cm4gdGhpcy51cmxGb3JEZWxldGVSZWNvcmQoaWQsIG1vZGVsTmFtZSwgc25hcHNob3QpOwoKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgcmV0dXJuIHRoaXMuX2J1aWxkVVJMKG1vZGVsTmFtZSwgaWQpOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIF9idWlsZFVSTAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBpZAogICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybAogICAgKi8KICAgIF9idWlsZFVSTDogZnVuY3Rpb24gX2J1aWxkVVJMKG1vZGVsTmFtZSwgaWQpIHsKICAgICAgdmFyIHBhdGg7CiAgICAgIHZhciB1cmwgPSBbXTsKICAgICAgdmFyIGhvc3QgPSBFbWJlci5nZXQodGhpcywgJ2hvc3QnKTsKICAgICAgdmFyIHByZWZpeCA9IHRoaXMudXJsUHJlZml4KCk7CgogICAgICBpZiAobW9kZWxOYW1lKSB7CiAgICAgICAgcGF0aCA9IHRoaXMucGF0aEZvclR5cGUobW9kZWxOYW1lKTsKCiAgICAgICAgaWYgKHBhdGgpIHsKICAgICAgICAgIHVybC5wdXNoKHBhdGgpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKGlkKSB7CiAgICAgICAgdXJsLnB1c2goZW5jb2RlVVJJQ29tcG9uZW50KGlkKSk7CiAgICAgIH0KCiAgICAgIGlmIChwcmVmaXgpIHsKICAgICAgICB1cmwudW5zaGlmdChwcmVmaXgpOwogICAgICB9CgogICAgICB1cmwgPSB1cmwuam9pbignLycpOwoKICAgICAgaWYgKCFob3N0ICYmIHVybCAmJiB1cmwuY2hhckF0KDApICE9PSAnLycpIHsKICAgICAgICB1cmwgPSAnLycgKyB1cmw7CiAgICAgIH0KCiAgICAgIHJldHVybiB1cmw7CiAgICB9LAoKICAgIC8qKgogICAgIEJ1aWxkcyBhIFVSTCBmb3IgYSBgc3RvcmUuZmluZFJlY29yZCh0eXBlLCBpZClgIGNhbGwuCiAgICAgIEV4YW1wbGU6CiAgICAgIGBgYGFwcC9hZGFwdGVycy91c2VyLmpzCiAgICAgaW1wb3J0IEpTT05BUElBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvanNvbi1hcGknOwogICAgICBleHBvcnQgZGVmYXVsdCBKU09OQVBJQWRhcHRlci5leHRlbmQoewogICAgICAgdXJsRm9yRmluZFJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICAgICBsZXQgYmFzZVVybCA9IHRoaXMuYnVpbGRVUkwobW9kZWxOYW1lLCBpZCwgc25hcHNob3QpOwogICAgICAgICByZXR1cm4gYCR7YmFzZVVybH0vdXNlcnMvJHtzbmFwc2hvdC5hZGFwdGVyT3B0aW9ucy51c2VyX2lkfS9wbGF5bGlzdHMvJHtpZH1gOwogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIHVybEZvckZpbmRSZWNvcmQKICAgICBAcGFyYW0ge1N0cmluZ30gaWQKICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybAogICAgICAqLwogICAgdXJsRm9yRmluZFJlY29yZDogZnVuY3Rpb24gdXJsRm9yRmluZFJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICB9LAoKICAgIC8qKgogICAgIEJ1aWxkcyBhIFVSTCBmb3IgYSBgc3RvcmUuZmluZEFsbCh0eXBlKWAgY2FsbC4KICAgICAgRXhhbXBsZToKICAgICAgYGBgYXBwL2FkYXB0ZXJzL2NvbW1lbnQuanMKICAgICBpbXBvcnQgSlNPTkFQSUFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9qc29uLWFwaSc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05BUElBZGFwdGVyLmV4dGVuZCh7CiAgICAgICB1cmxGb3JGaW5kQWxsKG1vZGVsTmFtZSwgc25hcHNob3QpIHsKICAgICAgICAgcmV0dXJuICdkYXRhL2NvbW1lbnRzLmpzb24nOwogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIHVybEZvckZpbmRBbGwKICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgQHBhcmFtIHtTbmFwc2hvdFJlY29yZEFycmF5fSBzbmFwc2hvdAogICAgIEByZXR1cm4ge1N0cmluZ30gdXJsCiAgICAgKi8KICAgIHVybEZvckZpbmRBbGw6IGZ1bmN0aW9uIHVybEZvckZpbmRBbGwobW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lKTsKICAgIH0sCgogICAgLyoqCiAgICAgQnVpbGRzIGEgVVJMIGZvciBhIGBzdG9yZS5xdWVyeSh0eXBlLCBxdWVyeSlgIGNhbGwuCiAgICAgIEV4YW1wbGU6CiAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgICBleHBvcnQgZGVmYXVsdCBSRVNUQWRhcHRlci5leHRlbmQoewogICAgICAgaG9zdDogJ2h0dHBzOi8vYXBpLmdpdGh1Yi5jb20nLAogICAgICAgdXJsRm9yUXVlcnkgKHF1ZXJ5LCBtb2RlbE5hbWUpIHsKICAgICAgICAgc3dpdGNoKG1vZGVsTmFtZSkgewogICAgICAgICAgIGNhc2UgJ3JlcG8nOgogICAgICAgICAgICAgcmV0dXJuIGBodHRwczovL2FwaS5naXRodWIuY29tL29yZ3MvJHtxdWVyeS5vcmdJZH0vcmVwb3NgOwogICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICByZXR1cm4gdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICAgfQogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIHVybEZvclF1ZXJ5CiAgICAgQHBhcmFtIHtPYmplY3R9IHF1ZXJ5CiAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgIEByZXR1cm4ge1N0cmluZ30gdXJsCiAgICAgKi8KICAgIHVybEZvclF1ZXJ5OiBmdW5jdGlvbiB1cmxGb3JRdWVyeShxdWVyeSwgbW9kZWxOYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLl9idWlsZFVSTChtb2RlbE5hbWUpOwogICAgfSwKCiAgICAvKioKICAgICBCdWlsZHMgYSBVUkwgZm9yIGEgYHN0b3JlLnF1ZXJ5UmVjb3JkKHR5cGUsIHF1ZXJ5KWAgY2FsbC4KICAgICAgRXhhbXBsZToKICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgaW1wb3J0IFJFU1RBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgICB1cmxGb3JRdWVyeVJlY29yZCh7IHNsdWcgfSwgbW9kZWxOYW1lKSB7CiAgICAgICAgIGxldCBiYXNlVXJsID0gdGhpcy5idWlsZFVSTCgpOwogICAgICAgICByZXR1cm4gYCR7YmFzZVVybH0vJHtlbmNvZGVVUklDb21wb25lbnQoc2x1Zyl9YDsKICAgICAgIH0KICAgICB9KTsKICAgICBgYGAKICAgICAgQG1ldGhvZCB1cmxGb3JRdWVyeVJlY29yZAogICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeQogICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybAogICAgICovCiAgICB1cmxGb3JRdWVyeVJlY29yZDogZnVuY3Rpb24gdXJsRm9yUXVlcnlSZWNvcmQocXVlcnksIG1vZGVsTmFtZSkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lKTsKICAgIH0sCgogICAgLyoqCiAgICAgQnVpbGRzIGEgVVJMIGZvciBjb2FsZXNjaW5nIG11bHRpcGxlIGBzdG9yZS5maW5kUmVjb3JkKHR5cGUsIGlkKWAKICAgICByZWNvcmRzIGludG8gMSByZXF1ZXN0IHdoZW4gdGhlIGFkYXB0ZXIncyBgY29hbGVzY2VGaW5kUmVxdWVzdHNgCiAgICAgcHJvcGVydHkgaXMgYHRydWVgLgogICAgICBFeGFtcGxlOgogICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICBpbXBvcnQgUkVTVEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9yZXN0JzsKICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgIHVybEZvckZpbmRNYW55KGlkcywgbW9kZWxOYW1lKSB7CiAgICAgICAgIGxldCBiYXNlVXJsID0gdGhpcy5idWlsZFVSTCgpOwogICAgICAgICByZXR1cm4gYCR7YmFzZVVybH0vY29hbGVzY2VgOwogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIHVybEZvckZpbmRNYW55CiAgICAgQHBhcmFtIHtBcnJheX0gaWRzCiAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgIEBwYXJhbSB7QXJyYXl9IHNuYXBzaG90cwogICAgIEByZXR1cm4ge1N0cmluZ30gdXJsCiAgICAgKi8KICAgIHVybEZvckZpbmRNYW55OiBmdW5jdGlvbiB1cmxGb3JGaW5kTWFueShpZHMsIG1vZGVsTmFtZSwgc25hcHNob3RzKSB7CiAgICAgIHJldHVybiB0aGlzLl9idWlsZFVSTChtb2RlbE5hbWUpOwogICAgfSwKCiAgICAvKioKICAgICBCdWlsZHMgYSBVUkwgZm9yIGZldGNoaW5nIGFuIGFzeW5jIGBoYXNNYW55YCByZWxhdGlvbnNoaXAgd2hlbiBhIFVSTAogICAgIGlzIG5vdCBwcm92aWRlZCBieSB0aGUgc2VydmVyLgogICAgICBFeGFtcGxlOgogICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICBpbXBvcnQgSlNPTkFQSUFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9qc29uLWFwaSc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05BUElBZGFwdGVyLmV4dGVuZCh7CiAgICAgICB1cmxGb3JGaW5kSGFzTWFueShpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICAgICBsZXQgYmFzZVVybCA9IHRoaXMuYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICAgICAgIHJldHVybiBgJHtiYXNlVXJsfS9yZWxhdGlvbnNoaXBzYDsKICAgICAgIH0KICAgICB9KTsKICAgICBgYGAKICAgICAgQG1ldGhvZCB1cmxGb3JGaW5kSGFzTWFueQogICAgIEBwYXJhbSB7U3RyaW5nfSBpZAogICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgIEByZXR1cm4ge1N0cmluZ30gdXJsCiAgICAgKi8KICAgIHVybEZvckZpbmRIYXNNYW55OiBmdW5jdGlvbiB1cmxGb3JGaW5kSGFzTWFueShpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICB9LAoKICAgIC8qKgogICAgIEJ1aWxkcyBhIFVSTCBmb3IgZmV0Y2hpbmcgYW4gYXN5bmMgYGJlbG9uZ3NUb2AgcmVsYXRpb25zaGlwIHdoZW4gYSB1cmwKICAgICBpcyBub3QgcHJvdmlkZWQgYnkgdGhlIHNlcnZlci4KICAgICAgRXhhbXBsZToKICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgaW1wb3J0IEpTT05BUElBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvanNvbi1hcGknOwogICAgICBleHBvcnQgZGVmYXVsdCBKU09OQVBJQWRhcHRlci5leHRlbmQoewogICAgICAgdXJsRm9yRmluZEJlbG9uZ3NUbyhpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICAgICBsZXQgYmFzZVVybCA9IHRoaXMuYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICAgICAgIHJldHVybiBgJHtiYXNlVXJsfS9yZWxhdGlvbnNoaXBzYDsKICAgICAgIH0KICAgICB9KTsKICAgICBgYGAKICAgICAgQG1ldGhvZCB1cmxGb3JGaW5kQmVsb25nc1RvCiAgICAgQHBhcmFtIHtTdHJpbmd9IGlkCiAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgQHJldHVybiB7U3RyaW5nfSB1cmwKICAgICAqLwogICAgdXJsRm9yRmluZEJlbG9uZ3NUbzogZnVuY3Rpb24gdXJsRm9yRmluZEJlbG9uZ3NUbyhpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICB9LAoKICAgIC8qKgogICAgIEJ1aWxkcyBhIFVSTCBmb3IgYSBgcmVjb3JkLnNhdmUoKWAgY2FsbCB3aGVuIHRoZSByZWNvcmQgd2FzIGNyZWF0ZWQKICAgICBsb2NhbGx5IHVzaW5nIGBzdG9yZS5jcmVhdGVSZWNvcmQoKWAuCiAgICAgIEV4YW1wbGU6CiAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgICBleHBvcnQgZGVmYXVsdCBSRVNUQWRhcHRlci5leHRlbmQoewogICAgICAgdXJsRm9yQ3JlYXRlUmVjb3JkKG1vZGVsTmFtZSwgc25hcHNob3QpIHsKICAgICAgICAgcmV0dXJuIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cykgKyAnL25ldyc7CiAgICAgICB9CiAgICAgfSk7CiAgICAgYGBgCiAgICAgIEBtZXRob2QgdXJsRm9yQ3JlYXRlUmVjb3JkCiAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgQHJldHVybiB7U3RyaW5nfSB1cmwKICAgICAqLwogICAgdXJsRm9yQ3JlYXRlUmVjb3JkOiBmdW5jdGlvbiB1cmxGb3JDcmVhdGVSZWNvcmQobW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lKTsKICAgIH0sCgogICAgLyoqCiAgICAgQnVpbGRzIGEgVVJMIGZvciBhIGByZWNvcmQuc2F2ZSgpYCBjYWxsIHdoZW4gdGhlIHJlY29yZCBoYXMgYmVlbiB1cGRhdGVkIGxvY2FsbHkuCiAgICAgIEV4YW1wbGU6CiAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgICBleHBvcnQgZGVmYXVsdCBSRVNUQWRhcHRlci5leHRlbmQoewogICAgICAgdXJsRm9yVXBkYXRlUmVjb3JkKGlkLCBtb2RlbE5hbWUsIHNuYXBzaG90KSB7CiAgICAgICAgIHJldHVybiBgLyR7aWR9L2ZlZWQ/YWNjZXNzX3Rva2VuPSR7c25hcHNob3QuYWRhcHRlck9wdGlvbnMudG9rZW59YDsKICAgICAgIH0KICAgICB9KTsKICAgICBgYGAKICAgICAgQG1ldGhvZCB1cmxGb3JVcGRhdGVSZWNvcmQKICAgICBAcGFyYW0ge1N0cmluZ30gaWQKICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybAogICAgICovCiAgICB1cmxGb3JVcGRhdGVSZWNvcmQ6IGZ1bmN0aW9uIHVybEZvclVwZGF0ZVJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICB9LAoKICAgIC8qKgogICAgIEJ1aWxkcyBhIFVSTCBmb3IgYSBgcmVjb3JkLnNhdmUoKWAgY2FsbCB3aGVuIHRoZSByZWNvcmQgaGFzIGJlZW4gZGVsZXRlZCBsb2NhbGx5LgogICAgICBFeGFtcGxlOgogICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICBpbXBvcnQgUkVTVEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9yZXN0JzsKICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgIHVybEZvckRlbGV0ZVJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICAgICByZXR1cm4gdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKSArICcvZGVzdHJveSc7CiAgICAgICB9CiAgICAgfSk7CiAgICAgYGBgCiAgICAgIEBtZXRob2QgdXJsRm9yRGVsZXRlUmVjb3JkCiAgICAgQHBhcmFtIHtTdHJpbmd9IGlkCiAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgQHJldHVybiB7U3RyaW5nfSB1cmwKICAgICAqLwogICAgdXJsRm9yRGVsZXRlUmVjb3JkOiBmdW5jdGlvbiB1cmxGb3JEZWxldGVSZWNvcmQoaWQsIG1vZGVsTmFtZSwgc25hcHNob3QpIHsKICAgICAgcmV0dXJuIHRoaXMuX2J1aWxkVVJMKG1vZGVsTmFtZSwgaWQpOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCB1cmxQcmVmaXgKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IHBhdGgKICAgICAgQHBhcmFtIHtTdHJpbmd9IHBhcmVudFVSTAogICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybFByZWZpeAogICAgKi8KICAgIHVybFByZWZpeDogZnVuY3Rpb24gdXJsUHJlZml4KHBhdGgsIHBhcmVudFVSTCkgewogICAgICB2YXIgaG9zdCA9IEVtYmVyLmdldCh0aGlzLCAnaG9zdCcpOwogICAgICB2YXIgbmFtZXNwYWNlID0gRW1iZXIuZ2V0KHRoaXMsICduYW1lc3BhY2UnKTsKCiAgICAgIGlmICghaG9zdCB8fCBob3N0ID09PSAnLycpIHsKICAgICAgICBob3N0ID0gJyc7CiAgICAgIH0KCiAgICAgIGlmIChwYXRoKSB7CiAgICAgICAgLy8gUHJvdG9jb2wgcmVsYXRpdmUgdXJsCiAgICAgICAgaWYgKC9eXC9cLy8udGVzdChwYXRoKSB8fCAvaHR0cChzKT86XC9cLy8udGVzdChwYXRoKSkgewogICAgICAgICAgLy8gRG8gbm90aGluZywgdGhlIGZ1bGwgaG9zdCBpcyBhbHJlYWR5IGluY2x1ZGVkLgogICAgICAgICAgcmV0dXJuIHBhdGg7IC8vIEFic29sdXRlIHBhdGgKICAgICAgICB9IGVsc2UgaWYgKHBhdGguY2hhckF0KDApID09PSAnLycpIHsKICAgICAgICAgIHJldHVybiAiIiArIGhvc3QgKyBwYXRoOyAvLyBSZWxhdGl2ZSBwYXRoCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBwYXJlbnRVUkwgKyAiLyIgKyBwYXRoOwogICAgICAgIH0KICAgICAgfSAvLyBObyBwYXRoIHByb3ZpZGVkCgoKICAgICAgdmFyIHVybCA9IFtdOwoKICAgICAgaWYgKGhvc3QpIHsKICAgICAgICB1cmwucHVzaChob3N0KTsKICAgICAgfQoKICAgICAgaWYgKG5hbWVzcGFjZSkgewogICAgICAgIHVybC5wdXNoKG5hbWVzcGFjZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB1cmwuam9pbignLycpOwogICAgfSwKCiAgICAvKioKICAgICAgRGV0ZXJtaW5lcyB0aGUgcGF0aG5hbWUgZm9yIGEgZ2l2ZW4gdHlwZS4KICAgICAgIEJ5IGRlZmF1bHQsIGl0IHBsdXJhbGl6ZXMgdGhlIHR5cGUncyBuYW1lIChmb3IgZXhhbXBsZSwKICAgICAgJ3Bvc3QnIGJlY29tZXMgJ3Bvc3RzJyBhbmQgJ3BlcnNvbicgYmVjb21lcyAncGVvcGxlJykuCiAgICAgICAjIyMgUGF0aG5hbWUgY3VzdG9taXphdGlvbgogICAgICAgRm9yIGV4YW1wbGUsIGlmIHlvdSBoYXZlIGFuIG9iamVjdCBgTGluZUl0ZW1gIHdpdGggYW4KICAgICAgZW5kcG9pbnQgb2YgYC9saW5lX2l0ZW1zL2AuCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJFU1RBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCc7CiAgICAgIGltcG9ydCB7IGRlY2FtZWxpemUgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAgICAgaW1wb3J0IHsgcGx1cmFsaXplIH0gZnJvbSAnZW1iZXItaW5mbGVjdG9yJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgcGF0aEZvclR5cGU6IGZ1bmN0aW9uKG1vZGVsTmFtZSkgewogICAgICAgICAgdmFyIGRlY2FtZWxpemVkID0gZGVjYW1lbGl6ZShtb2RlbE5hbWUpOwogICAgICAgICAgcmV0dXJuIHBsdXJhbGl6ZShkZWNhbWVsaXplZCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHBhdGhGb3JUeXBlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHJldHVybiB7U3RyaW5nfSBwYXRoCiAgICAqKi8KICAgIHBhdGhGb3JUeXBlOiBmdW5jdGlvbiBwYXRoRm9yVHlwZShtb2RlbE5hbWUpIHsKICAgICAgdmFyIGNhbWVsaXplZCA9IEVtYmVyLlN0cmluZy5jYW1lbGl6ZShtb2RlbE5hbWUpOwogICAgICByZXR1cm4gZW1iZXJJbmZsZWN0b3IucGx1cmFsaXplKGNhbWVsaXplZCk7CiAgICB9CiAgfSk7CgogIGZ1bmN0aW9uIHNlcmlhbGl6ZUludG9IYXNoKHN0b3JlLCBtb2RlbENsYXNzLCBzbmFwc2hvdCwgb3B0aW9ucykgewogICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICBvcHRpb25zID0gewogICAgICAgIGluY2x1ZGVJZDogdHJ1ZQogICAgICB9OwogICAgfQoKICAgIHZhciBzZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcihtb2RlbENsYXNzLm1vZGVsTmFtZSk7CgogICAgaWYgKHR5cGVvZiBzZXJpYWxpemVyLnNlcmlhbGl6ZUludG9IYXNoID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIHZhciBkYXRhID0ge307CiAgICAgIHNlcmlhbGl6ZXIuc2VyaWFsaXplSW50b0hhc2goZGF0YSwgbW9kZWxDbGFzcywgc25hcHNob3QsIG9wdGlvbnMpOwogICAgICByZXR1cm4gZGF0YTsKICAgIH0KCiAgICByZXR1cm4gc2VyaWFsaXplci5zZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpOwogIH0KCiAgZXhwb3J0cy5CdWlsZFVSTE1peGluID0gYnVpbGRVcmxNaXhpbjsKICBleHBvcnRzLmRldGVybWluZUJvZHlQcm9taXNlID0gZGV0ZXJtaW5lQm9keVByb21pc2U7CiAgZXhwb3J0cy5mZXRjaCA9IGdldEZldGNoRnVuY3Rpb247CiAgZXhwb3J0cy5wYXJzZVJlc3BvbnNlSGVhZGVycyA9IHBhcnNlUmVzcG9uc2VIZWFkZXJzOwogIGV4cG9ydHMuc2VyaWFsaXplSW50b0hhc2ggPSBzZXJpYWxpemVJbnRvSGFzaDsKICBleHBvcnRzLnNlcmlhbGl6ZVF1ZXJ5UGFyYW1zID0gc2VyaWFsaXplUXVlcnlQYXJhbXM7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7Cgp9KTsKCjtkZWZpbmUoIkBlbWJlci1kYXRhL2FkYXB0ZXIvZXJyb3IiLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvc3RvcmUvLXByaXZhdGUiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfcHJpdmF0ZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZXJyb3JzSGFzaFRvQXJyYXkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJpdmF0ZS5lcnJvcnNIYXNoVG9BcnJheTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJlcnJvcnNBcnJheVRvSGFzaCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9wcml2YXRlLmVycm9yc0FycmF5VG9IYXNoOwogICAgfQogIH0pOwogIF9leHBvcnRzLlNlcnZlckVycm9yID0gX2V4cG9ydHMuQ29uZmxpY3RFcnJvciA9IF9leHBvcnRzLk5vdEZvdW5kRXJyb3IgPSBfZXhwb3J0cy5Gb3JiaWRkZW5FcnJvciA9IF9leHBvcnRzLlVuYXV0aG9yaXplZEVycm9yID0gX2V4cG9ydHMuQWJvcnRFcnJvciA9IF9leHBvcnRzLlRpbWVvdXRFcnJvciA9IF9leHBvcnRzLkludmFsaWRFcnJvciA9IF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9hZGFwdGVyCiAgKi8KCiAgLyoqCiAgICBBIGBBZGFwdGVyRXJyb3JgIGlzIHVzZWQgYnkgYW4gYWRhcHRlciB0byBzaWduYWwgdGhhdCBhbiBlcnJvciBvY2N1cnJlZAogICAgZHVyaW5nIGEgcmVxdWVzdCB0byBhbiBleHRlcm5hbCBBUEkuIEl0IGluZGljYXRlcyBhIGdlbmVyaWMgZXJyb3IsIGFuZAogICAgc3ViY2xhc3NlcyBhcmUgdXNlZCB0byBpbmRpY2F0ZSBzcGVjaWZpYyBlcnJvciBzdGF0ZXMuIFRoZSBmb2xsb3dpbmcKICAgIHN1YmNsYXNzZXMgYXJlIHByb3ZpZGVkOgogIAogICAgLSBgSW52YWxpZEVycm9yYAogICAgLSBgVGltZW91dEVycm9yYAogICAgLSBgQWJvcnRFcnJvcmAKICAgIC0gYFVuYXV0aG9yaXplZEVycm9yYAogICAgLSBgRm9yYmlkZGVuRXJyb3JgCiAgICAtIGBOb3RGb3VuZEVycm9yYAogICAgLSBgQ29uZmxpY3RFcnJvcmAKICAgIC0gYFNlcnZlckVycm9yYAogIAogICAgVG8gY3JlYXRlIGEgY3VzdG9tIGVycm9yIHRvIHNpZ25hbCBhIHNwZWNpZmljIGVycm9yIHN0YXRlIGluIGNvbW11bmljYXRpbmcKICAgIHdpdGggYW4gZXh0ZXJuYWwgQVBJLCBleHRlbmQgdGhlIGBBZGFwdGVyRXJyb3JgLiBGb3IgZXhhbXBsZSwgaWYgdGhlCiAgICBleHRlcm5hbCBBUEkgZXhjbHVzaXZlbHkgdXNlZCBIVFRQIGA1MDMgU2VydmljZSBVbmF2YWlsYWJsZWAgdG8gaW5kaWNhdGUKICAgIGl0IHdhcyBjbG9zZWQgZm9yIG1haW50ZW5hbmNlOgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL21haW50ZW5hbmNlLWVycm9yLmpzCiAgICBpbXBvcnQgQWRhcHRlckVycm9yIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvZXJyb3InOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlckVycm9yLmV4dGVuZCh7IG1lc3NhZ2U6ICJEb3duIGZvciBtYWludGVuYW5jZS4iIH0pOwogICAgYGBgCiAgCiAgICBUaGlzIGVycm9yIHdvdWxkIHRoZW4gYmUgcmV0dXJuZWQgYnkgYW4gYWRhcHRlcidzIGBoYW5kbGVSZXNwb25zZWAgbWV0aG9kOgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgSlNPTkFQSUFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9qc29uLWFwaSc7CiAgICBpbXBvcnQgTWFpbnRlbmFuY2VFcnJvciBmcm9tICcuL21haW50ZW5hbmNlLWVycm9yJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IEpTT05BUElBZGFwdGVyLmV4dGVuZCh7CiAgICAgIGhhbmRsZVJlc3BvbnNlKHN0YXR1cykgewogICAgICAgIGlmICg1MDMgPT09IHN0YXR1cykgewogICAgICAgICAgcmV0dXJuIG5ldyBNYWludGVuYW5jZUVycm9yKCk7CiAgICAgICAgfQogIAogICAgICAgIHJldHVybiB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQW5kIGNhbiB0aGVuIGJlIGRldGVjdGVkIGluIGFuIGFwcGxpY2F0aW9uIGFuZCB1c2VkIHRvIHNlbmQgdGhlIHVzZXIgdG8gYW4KICAgIGB1bmRlci1tYWludGVuYW5jZWAgcm91dGU6CiAgCiAgICBgYGBhcHAvcm91dGVzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgaW1wb3J0IE1haW50ZW5hbmNlRXJyb3IgZnJvbSAnLi4vYWRhcHRlcnMvbWFpbnRlbmFuY2UtZXJyb3InOwogIAogICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgYWN0aW9uczogewogICAgICAgIGVycm9yKGVycm9yLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBNYWludGVuYW5jZUVycm9yKSB7CiAgICAgICAgICAgIHRoaXMudHJhbnNpdGlvblRvKCd1bmRlci1tYWludGVuYW5jZScpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CiAgCiAgICAgICAgICAvLyAuLi5vdGhlciBlcnJvciBoYW5kbGluZyBsb2dpYwogICAgICAgIH0KICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBBZGFwdGVyRXJyb3IKICAqLwogIGZ1bmN0aW9uIEFkYXB0ZXJFcnJvcihlcnJvcnMsIG1lc3NhZ2UpIHsKICAgIGlmIChtZXNzYWdlID09PSB2b2lkIDApIHsKICAgICAgbWVzc2FnZSA9ICdBZGFwdGVyIG9wZXJhdGlvbiBmYWlsZWQnOwogICAgfQoKICAgIHRoaXMuaXNBZGFwdGVyRXJyb3IgPSB0cnVlOwogICAgdmFyIGVycm9yID0gRW1iZXIuRXJyb3IuY2FsbCh0aGlzLCBtZXNzYWdlKTsgLy8gaW4gZW1iZXIgMy44KyBFcnJvciBpcyBhIE5hdGl2ZSBFcnJvciBhbmQgd2UgZG9uJ3QKICAgIC8vIGdhaW4gdGhlc2UgYXV0b21hdGljYWxseSBmcm9tIHRoZSBFbWJlckVycm9yLmNhbGwKCiAgICBpZiAoZXJyb3IpIHsKICAgICAgdGhpcy5zdGFjayA9IGVycm9yLnN0YWNrOwogICAgICB0aGlzLmRlc2NyaXB0aW9uID0gZXJyb3IuZGVzY3JpcHRpb247CiAgICAgIHRoaXMuZmlsZU5hbWUgPSBlcnJvci5maWxlTmFtZTsKICAgICAgdGhpcy5saW5lTnVtYmVyID0gZXJyb3IubGluZU51bWJlcjsKICAgICAgdGhpcy5tZXNzYWdlID0gZXJyb3IubWVzc2FnZTsKICAgICAgdGhpcy5uYW1lID0gZXJyb3IubmFtZTsKICAgICAgdGhpcy5udW1iZXIgPSBlcnJvci5udW1iZXI7CiAgICB9CgogICAgdGhpcy5lcnJvcnMgPSBlcnJvcnMgfHwgW3sKICAgICAgdGl0bGU6ICdBZGFwdGVyIEVycm9yJywKICAgICAgZGV0YWlsOiBtZXNzYWdlCiAgICB9XTsKICB9CgogIHZhciBfZGVmYXVsdCA9IEFkYXB0ZXJFcnJvcjsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7CgogIGZ1bmN0aW9uIGV4dGVuZEZuKEVycm9yQ2xhc3MpIHsKICAgIHJldHVybiBmdW5jdGlvbiAoX3RlbXApIHsKICAgICAgdmFyIF9yZWYgPSBfdGVtcCA9PT0gdm9pZCAwID8ge30gOiBfdGVtcCwKICAgICAgICAgIGRlZmF1bHRNZXNzYWdlID0gX3JlZi5tZXNzYWdlOwoKICAgICAgcmV0dXJuIGV4dGVuZChFcnJvckNsYXNzLCBkZWZhdWx0TWVzc2FnZSk7CiAgICB9OwogIH0KCiAgZnVuY3Rpb24gZXh0ZW5kKFBhcmVudEVycm9yQ2xhc3MsIGRlZmF1bHRNZXNzYWdlKSB7CiAgICB2YXIgRXJyb3JDbGFzcyA9IGZ1bmN0aW9uIEVycm9yQ2xhc3MoZXJyb3JzLCBtZXNzYWdlKSB7CiAgICAgIChmYWxzZSAmJiAhKEFycmF5LmlzQXJyYXkoZXJyb3JzIHx8IFtdKSkgJiYgRW1iZXIuYXNzZXJ0KCdgQWRhcHRlckVycm9yYCBleHBlY3RzIGpzb24tYXBpIGZvcm1hdHRlZCBlcnJvcnMgYXJyYXkuJywgQXJyYXkuaXNBcnJheShlcnJvcnMgfHwgW10pKSk7CiAgICAgIFBhcmVudEVycm9yQ2xhc3MuY2FsbCh0aGlzLCBlcnJvcnMsIG1lc3NhZ2UgfHwgZGVmYXVsdE1lc3NhZ2UpOwogICAgfTsKCiAgICBFcnJvckNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoUGFyZW50RXJyb3JDbGFzcy5wcm90b3R5cGUpOwogICAgRXJyb3JDbGFzcy5leHRlbmQgPSBleHRlbmRGbihFcnJvckNsYXNzKTsKICAgIHJldHVybiBFcnJvckNsYXNzOwogIH0KCiAgQWRhcHRlckVycm9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRW1iZXIuRXJyb3IucHJvdG90eXBlKTsKICBBZGFwdGVyRXJyb3IucHJvdG90eXBlLmNvZGUgPSAnQWRhcHRlckVycm9yJzsKICBBZGFwdGVyRXJyb3IuZXh0ZW5kID0gZXh0ZW5kRm4oQWRhcHRlckVycm9yKTsKICAvKioKICAgIEEgYEludmFsaWRFcnJvcmAgaXMgdXNlZCBieSBhbiBhZGFwdGVyIHRvIHNpZ25hbCB0aGUgZXh0ZXJuYWwgQVBJCiAgICB3YXMgdW5hYmxlIHRvIHByb2Nlc3MgYSByZXF1ZXN0IGJlY2F1c2UgdGhlIGNvbnRlbnQgd2FzIG5vdAogICAgc2VtYW50aWNhbGx5IGNvcnJlY3Qgb3IgbWVhbmluZ2Z1bCBwZXIgdGhlIEFQSS4gVXN1YWxseSwgdGhpcyBtZWFucyBhCiAgICByZWNvcmQgZmFpbGVkIHNvbWUgZm9ybSBvZiBzZXJ2ZXItc2lkZSB2YWxpZGF0aW9uLiBXaGVuIGEgcHJvbWlzZQogICAgZnJvbSBhbiBhZGFwdGVyIGlzIHJlamVjdGVkIHdpdGggYSBgSW52YWxpZEVycm9yYCB0aGUgcmVjb3JkIHdpbGwKICAgIHRyYW5zaXRpb24gdG8gdGhlIGBpbnZhbGlkYCBzdGF0ZSBhbmQgdGhlIGVycm9ycyB3aWxsIGJlIHNldCB0byB0aGUKICAgIGBlcnJvcnNgIHByb3BlcnR5IG9uIHRoZSByZWNvcmQuCiAgCiAgICBGb3IgRW1iZXIgRGF0YSB0byBjb3JyZWN0bHkgbWFwIGVycm9ycyB0byB0aGVpciBjb3JyZXNwb25kaW5nCiAgICBwcm9wZXJ0aWVzIG9uIHRoZSBtb2RlbCwgRW1iZXIgRGF0YSBleHBlY3RzIGVhY2ggZXJyb3IgdG8gYmUKICAgIGEgdmFsaWQgSlNPTi1BUEkgZXJyb3Igb2JqZWN0IHdpdGggYSBgc291cmNlL3BvaW50ZXJgIHRoYXQgbWF0Y2hlcwogICAgdGhlIHByb3BlcnR5IG5hbWUuIEZvciBleGFtcGxlLCBpZiB5b3UgaGFkIGEgUG9zdCBtb2RlbCB0aGF0CiAgICBsb29rZWQgbGlrZSB0aGlzLgogIAogICAgYGBgYXBwL21vZGVscy9wb3N0LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHRpdGxlOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgY29udGVudDogYXR0cignc3RyaW5nJykKICAgIH0pOwogICAgYGBgCiAgCiAgICBUbyBzaG93IGFuIGVycm9yIGZyb20gdGhlIHNlcnZlciByZWxhdGVkIHRvIHRoZSBgdGl0bGVgIGFuZAogICAgYGNvbnRlbnRgIHByb3BlcnRpZXMgeW91ciBhZGFwdGVyIGNvdWxkIHJldHVybiBhIHByb21pc2UgdGhhdAogICAgcmVqZWN0cyB3aXRoIGEgYEludmFsaWRFcnJvcmAgb2JqZWN0IHRoYXQgbG9va3MgbGlrZSB0aGlzOgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL3Bvc3QuanMKICAgIGltcG9ydCBSU1ZQIGZyb20gJ1JTVlAnOwogICAgaW1wb3J0IFJFU1RBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCc7CiAgICBpbXBvcnQgeyBJbnZhbGlkRXJyb3IgfSBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL2Vycm9yJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgIHVwZGF0ZVJlY29yZCgpIHsKICAgICAgICAvLyBGaWN0aW9uYWwgYWRhcHRlciB0aGF0IGFsd2F5cyByZWplY3RzCiAgICAgICAgcmV0dXJuIFJTVlAucmVqZWN0KG5ldyBJbnZhbGlkRXJyb3IoWwogICAgICAgICAgewogICAgICAgICAgICBkZXRhaWw6ICdNdXN0IGJlIHVuaXF1ZScsCiAgICAgICAgICAgIHNvdXJjZTogeyBwb2ludGVyOiAnL2RhdGEvYXR0cmlidXRlcy90aXRsZScgfQogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgZGV0YWlsOiAnTXVzdCBub3QgYmUgYmxhbmsnLAogICAgICAgICAgICBzb3VyY2U6IHsgcG9pbnRlcjogJy9kYXRhL2F0dHJpYnV0ZXMvY29udGVudCd9CiAgICAgICAgICB9CiAgICAgICAgXSkpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgWW91ciBiYWNrZW5kIG1heSB1c2UgZGlmZmVyZW50IHByb3BlcnR5IG5hbWVzIGZvciB5b3VyIHJlY29yZHMgdGhlCiAgICBzdG9yZSB3aWxsIGF0dGVtcHQgdG8gZXh0cmFjdCBhbmQgbm9ybWFsaXplIHRoZSBlcnJvcnMgdXNpbmcgdGhlCiAgICBzZXJpYWxpemVyJ3MgYGV4dHJhY3RFcnJvcnNgIG1ldGhvZCBiZWZvcmUgdGhlIGVycm9ycyBnZXQgYWRkZWQgdG8KICAgIHRoZSBtb2RlbC4gQXMgYSByZXN1bHQsIGl0IGlzIHNhZmUgZm9yIHRoZSBgSW52YWxpZEVycm9yYCB0bwogICAgd3JhcCB0aGUgZXJyb3IgcGF5bG9hZCB1bmFsdGVyZWQuCiAgCiAgICBAY2xhc3MgSW52YWxpZEVycm9yCiAgICBAZXh0ZW5kcyBBZGFwdGVyRXJyb3IKICAqLwoKICB2YXIgSW52YWxpZEVycm9yID0gZXh0ZW5kKEFkYXB0ZXJFcnJvciwgJ1RoZSBhZGFwdGVyIHJlamVjdGVkIHRoZSBjb21taXQgYmVjYXVzZSBpdCB3YXMgaW52YWxpZCcpOwogIF9leHBvcnRzLkludmFsaWRFcnJvciA9IEludmFsaWRFcnJvcjsKICBJbnZhbGlkRXJyb3IucHJvdG90eXBlLmNvZGUgPSAnSW52YWxpZEVycm9yJzsKICAvKioKICAgIEEgYFRpbWVvdXRFcnJvcmAgaXMgdXNlZCBieSBhbiBhZGFwdGVyIHRvIHNpZ25hbCB0aGF0IGEgcmVxdWVzdAogICAgdG8gdGhlIGV4dGVybmFsIEFQSSBoYXMgdGltZWQgb3V0LiBJLmUuIG5vIHJlc3BvbnNlIHdhcyByZWNlaXZlZCBmcm9tCiAgICB0aGUgZXh0ZXJuYWwgQVBJIHdpdGhpbiBhbiBhbGxvd2VkIHRpbWUgcGVyaW9kLgogIAogICAgQW4gZXhhbXBsZSB1c2UgY2FzZSB3b3VsZCBiZSB0byB3YXJuIHRoZSB1c2VyIHRvIGNoZWNrIHRoZWlyIGludGVybmV0CiAgICBjb25uZWN0aW9uIGlmIGFuIGFkYXB0ZXIgb3BlcmF0aW9uIGhhcyB0aW1lZCBvdXQ6CiAgCiAgICBgYGBhcHAvcm91dGVzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgaW1wb3J0IHsgVGltZW91dEVycm9yIH0gZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9lcnJvcic7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICBhY3Rpb25zOiB7CiAgICAgICAgZXJyb3IoZXJyb3IsIHRyYW5zaXRpb24pIHsKICAgICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFRpbWVvdXRFcnJvcikgewogICAgICAgICAgICAvLyBhbGVydCB0aGUgdXNlcgogICAgICAgICAgICBhbGVydCgnQXJlIHlvdSBzdGlsbCBjb25uZWN0ZWQgdG8gdGhlIGludGVybmV0PycpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CiAgCiAgICAgICAgICAvLyAuLi5vdGhlciBlcnJvciBoYW5kbGluZyBsb2dpYwogICAgICAgIH0KICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBUaW1lb3V0RXJyb3IKICAgIEBleHRlbmRzIEFkYXB0ZXJFcnJvcgogICovCgogIHZhciBUaW1lb3V0RXJyb3IgPSBleHRlbmQoQWRhcHRlckVycm9yLCAnVGhlIGFkYXB0ZXIgb3BlcmF0aW9uIHRpbWVkIG91dCcpOwogIF9leHBvcnRzLlRpbWVvdXRFcnJvciA9IFRpbWVvdXRFcnJvcjsKICBUaW1lb3V0RXJyb3IucHJvdG90eXBlLmNvZGUgPSAnVGltZW91dEVycm9yJzsKICAvKioKICAgIEEgYEFib3J0RXJyb3JgIGlzIHVzZWQgYnkgYW4gYWRhcHRlciB0byBzaWduYWwgdGhhdCBhIHJlcXVlc3QgdG8KICAgIHRoZSBleHRlcm5hbCBBUEkgd2FzIGFib3J0ZWQuIEZvciBleGFtcGxlLCB0aGlzIGNhbiBvY2N1ciBpZiB0aGUgdXNlcgogICAgbmF2aWdhdGVzIGF3YXkgZnJvbSB0aGUgY3VycmVudCBwYWdlIGFmdGVyIGEgcmVxdWVzdCB0byB0aGUgZXh0ZXJuYWwgQVBJCiAgICBoYXMgYmVlbiBpbml0aWF0ZWQgYnV0IGJlZm9yZSBhIHJlc3BvbnNlIGhhcyBiZWVuIHJlY2VpdmVkLgogIAogICAgQGNsYXNzIEFib3J0RXJyb3IKICAgIEBleHRlbmRzIEFkYXB0ZXJFcnJvcgogICovCgogIHZhciBBYm9ydEVycm9yID0gZXh0ZW5kKEFkYXB0ZXJFcnJvciwgJ1RoZSBhZGFwdGVyIG9wZXJhdGlvbiB3YXMgYWJvcnRlZCcpOwogIF9leHBvcnRzLkFib3J0RXJyb3IgPSBBYm9ydEVycm9yOwogIEFib3J0RXJyb3IucHJvdG90eXBlLmNvZGUgPSAnQWJvcnRFcnJvcic7CiAgLyoqCiAgICBBIGBVbmF1dGhvcml6ZWRFcnJvcmAgZXF1YXRlcyB0byBhIEhUVFAgYDQwMSBVbmF1dGhvcml6ZWRgIHJlc3BvbnNlCiAgICBzdGF0dXMuIEl0IGlzIHVzZWQgYnkgYW4gYWRhcHRlciB0byBzaWduYWwgdGhhdCBhIHJlcXVlc3QgdG8gdGhlIGV4dGVybmFsCiAgICBBUEkgd2FzIHJlamVjdGVkIGJlY2F1c2UgYXV0aG9yaXphdGlvbiBpcyByZXF1aXJlZCBhbmQgaGFzIGZhaWxlZCBvciBoYXMgbm90CiAgICB5ZXQgYmVlbiBwcm92aWRlZC4KICAKICAgIEFuIGV4YW1wbGUgdXNlIGNhc2Ugd291bGQgYmUgdG8gcmVkaXJlY3QgdGhlIHVzZXIgdG8gYSBsb2dpbiByb3V0ZSBpZiBhCiAgICByZXF1ZXN0IGlzIHVuYXV0aG9yaXplZDoKICAKICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICBpbXBvcnQgeyBVbmF1dGhvcml6ZWRFcnJvciB9IGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvZXJyb3InOwogIAogICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgYWN0aW9uczogewogICAgICAgIGVycm9yKGVycm9yLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBVbmF1dGhvcml6ZWRFcnJvcikgewogICAgICAgICAgICAvLyBnbyB0byB0aGUgc2lnbiBpbiByb3V0ZQogICAgICAgICAgICB0aGlzLnRyYW5zaXRpb25UbygnbG9naW4nKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgfQogIAogICAgICAgICAgLy8gLi4ub3RoZXIgZXJyb3IgaGFuZGxpbmcgbG9naWMKICAgICAgICB9CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBAY2xhc3MgVW5hdXRob3JpemVkRXJyb3IKICAgIEBleHRlbmRzIEFkYXB0ZXJFcnJvcgogICovCgogIHZhciBVbmF1dGhvcml6ZWRFcnJvciA9IGV4dGVuZChBZGFwdGVyRXJyb3IsICdUaGUgYWRhcHRlciBvcGVyYXRpb24gaXMgdW5hdXRob3JpemVkJyk7CiAgX2V4cG9ydHMuVW5hdXRob3JpemVkRXJyb3IgPSBVbmF1dGhvcml6ZWRFcnJvcjsKICBVbmF1dGhvcml6ZWRFcnJvci5wcm90b3R5cGUuY29kZSA9ICdVbmF1dGhvcml6ZWRFcnJvcic7CiAgLyoqCiAgICBBIGBGb3JiaWRkZW5FcnJvcmAgZXF1YXRlcyB0byBhIEhUVFAgYDQwMyBGb3JiaWRkZW5gIHJlc3BvbnNlIHN0YXR1cy4KICAgIEl0IGlzIHVzZWQgYnkgYW4gYWRhcHRlciB0byBzaWduYWwgdGhhdCBhIHJlcXVlc3QgdG8gdGhlIGV4dGVybmFsIEFQSSB3YXMKICAgIHZhbGlkIGJ1dCB0aGUgc2VydmVyIGlzIHJlZnVzaW5nIHRvIHJlc3BvbmQgdG8gaXQuIElmIGF1dGhvcml6YXRpb24gd2FzCiAgICBwcm92aWRlZCBhbmQgaXMgdmFsaWQsIHRoZW4gdGhlIGF1dGhlbnRpY2F0ZWQgdXNlciBkb2VzIG5vdCBoYXZlIHRoZQogICAgbmVjZXNzYXJ5IHBlcm1pc3Npb25zIGZvciB0aGUgcmVxdWVzdC4KICAKICAgIEBjbGFzcyBGb3JiaWRkZW5FcnJvcgogICAgQGV4dGVuZHMgQWRhcHRlckVycm9yCiAgKi8KCiAgdmFyIEZvcmJpZGRlbkVycm9yID0gZXh0ZW5kKEFkYXB0ZXJFcnJvciwgJ1RoZSBhZGFwdGVyIG9wZXJhdGlvbiBpcyBmb3JiaWRkZW4nKTsKICBfZXhwb3J0cy5Gb3JiaWRkZW5FcnJvciA9IEZvcmJpZGRlbkVycm9yOwogIEZvcmJpZGRlbkVycm9yLnByb3RvdHlwZS5jb2RlID0gJ0ZvcmJpZGRlbkVycm9yJzsKICAvKioKICAgIEEgYE5vdEZvdW5kRXJyb3JgIGVxdWF0ZXMgdG8gYSBIVFRQIGA0MDQgTm90IEZvdW5kYCByZXNwb25zZSBzdGF0dXMuCiAgICBJdCBpcyB1c2VkIGJ5IGFuIGFkYXB0ZXIgdG8gc2lnbmFsIHRoYXQgYSByZXF1ZXN0IHRvIHRoZSBleHRlcm5hbCBBUEkKICAgIHdhcyByZWplY3RlZCBiZWNhdXNlIHRoZSByZXNvdXJjZSBjb3VsZCBub3QgYmUgZm91bmQgb24gdGhlIEFQSS4KICAKICAgIEFuIGV4YW1wbGUgdXNlIGNhc2Ugd291bGQgYmUgdG8gZGV0ZWN0IGlmIHRoZSB1c2VyIGhhcyBlbnRlcmVkIGEgcm91dGUKICAgIGZvciBhIHNwZWNpZmljIG1vZGVsIHRoYXQgZG9lcyBub3QgZXhpc3QuIEZvciBleGFtcGxlOgogIAogICAgYGBgYXBwL3JvdXRlcy9wb3N0LmpzCiAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgaW1wb3J0IHsgTm90Rm91bmRFcnJvciB9IGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvZXJyb3InOwogIAogICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgbW9kZWwocGFyYW1zKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KCdzdG9yZScpLmZpbmRSZWNvcmQoJ3Bvc3QnLCBwYXJhbXMucG9zdF9pZCk7CiAgICAgIH0sCiAgCiAgICAgIGFjdGlvbnM6IHsKICAgICAgICBlcnJvcihlcnJvciwgdHJhbnNpdGlvbikgewogICAgICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgTm90Rm91bmRFcnJvcikgewogICAgICAgICAgICAvLyByZWRpcmVjdCB0byBhIGxpc3Qgb2YgYWxsIHBvc3RzIGluc3RlYWQKICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ3Bvc3RzJyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvLyBvdGhlcndpc2UgbGV0IHRoZSBlcnJvciBidWJibGUKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQGNsYXNzIE5vdEZvdW5kRXJyb3IKICAgIEBleHRlbmRzIEFkYXB0ZXJFcnJvcgogICovCgogIHZhciBOb3RGb3VuZEVycm9yID0gZXh0ZW5kKEFkYXB0ZXJFcnJvciwgJ1RoZSBhZGFwdGVyIGNvdWxkIG5vdCBmaW5kIHRoZSByZXNvdXJjZScpOwogIF9leHBvcnRzLk5vdEZvdW5kRXJyb3IgPSBOb3RGb3VuZEVycm9yOwogIE5vdEZvdW5kRXJyb3IucHJvdG90eXBlLmNvZGUgPSAnTm90Rm91bmRFcnJvcic7CiAgLyoqCiAgICBBIGBDb25mbGljdEVycm9yYCBlcXVhdGVzIHRvIGEgSFRUUCBgNDA5IENvbmZsaWN0YCByZXNwb25zZSBzdGF0dXMuCiAgICBJdCBpcyB1c2VkIGJ5IGFuIGFkYXB0ZXIgdG8gaW5kaWNhdGUgdGhhdCB0aGUgcmVxdWVzdCBjb3VsZCBub3QgYmUgcHJvY2Vzc2VkCiAgICBiZWNhdXNlIG9mIGEgY29uZmxpY3QgaW4gdGhlIHJlcXVlc3QuIEFuIGV4YW1wbGUgc2NlbmFyaW8gd291bGQgYmUgd2hlbgogICAgY3JlYXRpbmcgYSByZWNvcmQgd2l0aCBhIGNsaWVudC1nZW5lcmF0ZWQgSUQgYnV0IHRoYXQgSUQgaXMgYWxyZWFkeSBrbm93bgogICAgdG8gdGhlIGV4dGVybmFsIEFQSS4KICAKICAgIEBjbGFzcyBDb25mbGljdEVycm9yCiAgICBAZXh0ZW5kcyBBZGFwdGVyRXJyb3IKICAqLwoKICB2YXIgQ29uZmxpY3RFcnJvciA9IGV4dGVuZChBZGFwdGVyRXJyb3IsICdUaGUgYWRhcHRlciBvcGVyYXRpb24gZmFpbGVkIGR1ZSB0byBhIGNvbmZsaWN0Jyk7CiAgX2V4cG9ydHMuQ29uZmxpY3RFcnJvciA9IENvbmZsaWN0RXJyb3I7CiAgQ29uZmxpY3RFcnJvci5wcm90b3R5cGUuY29kZSA9ICdDb25mbGljdEVycm9yJzsKICAvKioKICAgIEEgYFNlcnZlckVycm9yYCBlcXVhdGVzIHRvIGEgSFRUUCBgNTAwIEludGVybmFsIFNlcnZlciBFcnJvcmAgcmVzcG9uc2UKICAgIHN0YXR1cy4gSXQgaXMgdXNlZCBieSB0aGUgYWRhcHRlciB0byBpbmRpY2F0ZSB0aGF0IGEgcmVxdWVzdCBoYXMgZmFpbGVkCiAgICBiZWNhdXNlIG9mIGFuIGVycm9yIGluIHRoZSBleHRlcm5hbCBBUEkuCiAgCiAgICBAY2xhc3MgU2VydmVyRXJyb3IKICAgIEBleHRlbmRzIEFkYXB0ZXJFcnJvcgogICovCgogIHZhciBTZXJ2ZXJFcnJvciA9IGV4dGVuZChBZGFwdGVyRXJyb3IsICdUaGUgYWRhcHRlciBvcGVyYXRpb24gZmFpbGVkIGR1ZSB0byBhIHNlcnZlciBlcnJvcicpOwogIF9leHBvcnRzLlNlcnZlckVycm9yID0gU2VydmVyRXJyb3I7CiAgU2VydmVyRXJyb3IucHJvdG90eXBlLmNvZGUgPSAnU2VydmVyRXJyb3InOwp9KTsKO2RlZmluZSgiQGVtYmVyLWRhdGEvYWRhcHRlci9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9hZGFwdGVyLy1wcml2YXRlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3ByaXZhdGUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkJ1aWxkVVJMTWl4aW4iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJpdmF0ZS5CdWlsZFVSTE1peGluOwogICAgfQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAgQW4gYWRhcHRlciBpcyBhbiBvYmplY3QgdGhhdCByZWNlaXZlcyByZXF1ZXN0cyBmcm9tIGEgc3RvcmUgYW5kCiAgICB0cmFuc2xhdGVzIHRoZW0gaW50byB0aGUgYXBwcm9wcmlhdGUgYWN0aW9uIHRvIHRha2UgYWdhaW5zdCB5b3VyCiAgICBwZXJzaXN0ZW5jZSBsYXllci4gVGhlIHBlcnNpc3RlbmNlIGxheWVyIGlzIHVzdWFsbHkgYW4gSFRUUCBBUEkgYnV0CiAgICBtYXkgYmUgYW55dGhpbmcsIHN1Y2ggYXMgdGhlIGJyb3dzZXIncyBsb2NhbCBzdG9yYWdlLiBUeXBpY2FsbHkgdGhlCiAgICBhZGFwdGVyIGlzIG5vdCBpbnZva2VkIGRpcmVjdGx5IGluc3RlYWQgaXRzIGZ1bmN0aW9uYWxpdHkgaXMgYWNjZXNzZWQKICAgIHRocm91Z2ggdGhlIGBzdG9yZWAuCiAgCiAgICAjIyMgQ3JlYXRpbmcgYW4gQWRhcHRlcgogIAogICAgQ3JlYXRlIGEgbmV3IHN1YmNsYXNzIG9mIGBBZGFwdGVyYCBpbiB0aGUgYGFwcC9hZGFwdGVyc2AgZm9sZGVyOgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgLy8gLi4ueW91ciBjb2RlIGhlcmUKICAgIH0pOwogICAgYGBgCiAgCiAgICBNb2RlbC1zcGVjaWZpYyBhZGFwdGVycyBjYW4gYmUgY3JlYXRlZCBieSBwdXR0aW5nIHlvdXIgYWRhcHRlcgogICAgY2xhc3MgaW4gYW4gYGFwcC9hZGFwdGVycy9gICsgYG1vZGVsLW5hbWVgICsgYC5qc2AgZmlsZSBvZiB0aGUgYXBwbGljYXRpb24uCiAgCiAgICBgYGBhcHAvYWRhcHRlcnMvcG9zdC5qcwogICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgIC8vIC4uLlBvc3Qtc3BlY2lmaWMgYWRhcHRlciBjb2RlIGdvZXMgaGVyZQogICAgfSk7CiAgICBgYGAKICAKICAgIGBBZGFwdGVyYCBpcyBhbiBhYnN0cmFjdCBiYXNlIGNsYXNzIHRoYXQgeW91IHNob3VsZCBvdmVycmlkZSBpbiB5b3VyCiAgICBhcHBsaWNhdGlvbiB0byBjdXN0b21pemUgaXQgZm9yIHlvdXIgYmFja2VuZC4gVGhlIG1pbmltdW0gc2V0IG9mIG1ldGhvZHMKICAgIHRoYXQgeW91IHNob3VsZCBpbXBsZW1lbnQgaXM6CiAgCiAgICAgICogYGZpbmRSZWNvcmQoKWAKICAgICAgKiBgY3JlYXRlUmVjb3JkKClgCiAgICAgICogYHVwZGF0ZVJlY29yZCgpYAogICAgICAqIGBkZWxldGVSZWNvcmQoKWAKICAgICAgKiBgZmluZEFsbCgpYAogICAgICAqIGBxdWVyeSgpYAogIAogICAgVG8gaW1wcm92ZSB0aGUgbmV0d29yayBwZXJmb3JtYW5jZSBvZiB5b3VyIGFwcGxpY2F0aW9uLCB5b3UgY2FuIG9wdGltaXplCiAgICB5b3VyIGFkYXB0ZXIgYnkgb3ZlcnJpZGluZyB0aGVzZSBsb3dlci1sZXZlbCBtZXRob2RzOgogIAogICAgICAqIGBmaW5kTWFueSgpYAogIAogIAogICAgRm9yIGFuIGV4YW1wbGUgb2YgdGhlIGltcGxlbWVudGF0aW9uLCBzZWUgYFJFU1RBZGFwdGVyYCwgdGhlCiAgICBpbmNsdWRlZCBSRVNUIGFkYXB0ZXIuCiAgCiAgICBAY2xhc3MgQWRhcHRlcgogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAqLwogIHZhciBfZGVmYXVsdCA9IEVtYmVyLk9iamVjdC5leHRlbmQoewogICAgLyoqCiAgICAgIElmIHlvdSB3b3VsZCBsaWtlIHlvdXIgYWRhcHRlciB0byB1c2UgYSBjdXN0b20gc2VyaWFsaXplciB5b3UgY2FuCiAgICAgIHNldCB0aGUgYGRlZmF1bHRTZXJpYWxpemVyYCBwcm9wZXJ0eSB0byBiZSB0aGUgbmFtZSBvZiB0aGUgY3VzdG9tCiAgICAgIHNlcmlhbGl6ZXIuCiAgICAgICBOb3RlIHRoZSBgZGVmYXVsdFNlcmlhbGl6ZXJgIHNlcmlhbGl6ZXIgaGFzIGEgbG93ZXIgcHJpb3JpdHkgdGhhbgogICAgICBhIG1vZGVsIHNwZWNpZmljIHNlcmlhbGl6ZXIgKGkuZS4gYFBvc3RTZXJpYWxpemVyYCkgb3IgdGhlCiAgICAgIGBhcHBsaWNhdGlvbmAgc2VyaWFsaXplci4KICAgICAgIGBgYGFwcC9hZGFwdGVycy9kamFuZ28uanMKICAgICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgZGVmYXVsdFNlcmlhbGl6ZXI6ICdkamFuZ28nCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBkZWZhdWx0U2VyaWFsaXplcgogICAgICBAdHlwZSB7U3RyaW5nfQogICAgKi8KICAgIGRlZmF1bHRTZXJpYWxpemVyOiAnLWRlZmF1bHQnLAoKICAgIC8qKgogICAgICBUaGUgYGZpbmRSZWNvcmQoKWAgbWV0aG9kIGlzIGludm9rZWQgd2hlbiB0aGUgc3RvcmUgaXMgYXNrZWQgZm9yIGEgcmVjb3JkIHRoYXQKICAgICAgaGFzIG5vdCBwcmV2aW91c2x5IGJlZW4gbG9hZGVkLiBJbiByZXNwb25zZSB0byBgZmluZFJlY29yZCgpYCBiZWluZyBjYWxsZWQsIHlvdQogICAgICBzaG91bGQgcXVlcnkgeW91ciBwZXJzaXN0ZW5jZSBsYXllciBmb3IgYSByZWNvcmQgd2l0aCB0aGUgZ2l2ZW4gSUQuIFRoZSBgZmluZFJlY29yZGAKICAgICAgbWV0aG9kIHNob3VsZCByZXR1cm4gYSBwcm9taXNlIHRoYXQgd2lsbCByZXNvbHZlIHRvIGEgSmF2YVNjcmlwdCBvYmplY3QgdGhhdCB3aWxsIGJlCiAgICAgIG5vcm1hbGl6ZWQgYnkgdGhlIHNlcmlhbGl6ZXIuCiAgICAgICBIZXJlIGlzIGFuIGV4YW1wbGUgb2YgdGhlIGBmaW5kUmVjb3JkYCBpbXBsZW1lbnRhdGlvbjoKICAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyJzsKICAgICAgaW1wb3J0IFJTVlAgZnJvbSAnUlNWUCc7CiAgICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgZmluZFJlY29yZChzdG9yZSwgdHlwZSwgaWQsIHNuYXBzaG90KSB7CiAgICAgICAgICByZXR1cm4gbmV3IFJTVlAuUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICAgICAgJC5nZXRKU09OKGAvJHt0eXBlLm1vZGVsTmFtZX0vJHtpZH1gKS50aGVuKGZ1bmN0aW9uKGRhdGEpIHsKICAgICAgICAgICAgICByZXNvbHZlKGRhdGEpOwogICAgICAgICAgICB9LCBmdW5jdGlvbihqcVhIUikgewogICAgICAgICAgICAgIHJlamVjdChqcVhIUik7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGZpbmRSZWNvcmQKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZQogICAgICBAcGFyYW0ge1N0cmluZ30gaWQKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIGZpbmRSZWNvcmQ6IG51bGwsCgogICAgLyoqCiAgICAgIFRoZSBgZmluZEFsbCgpYCBtZXRob2QgaXMgdXNlZCB0byByZXRyaWV2ZSBhbGwgcmVjb3JkcyBmb3IgYSBnaXZlbiB0eXBlLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICBpbXBvcnQgUlNWUCBmcm9tICdSU1ZQJzsKICAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBmaW5kQWxsKHN0b3JlLCB0eXBlKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFJTVlAuUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICAgICAgJC5nZXRKU09OKGAvJHt0eXBlLm1vZGVsTmFtZX1gKS50aGVuKGZ1bmN0aW9uKGRhdGEpIHsKICAgICAgICAgICAgICByZXNvbHZlKGRhdGEpOwogICAgICAgICAgICB9LCBmdW5jdGlvbihqcVhIUikgewogICAgICAgICAgICAgIHJlamVjdChqcVhIUik7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGZpbmRBbGwKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZQogICAgICBAcGFyYW0ge3VuZGVmaW5lZH0gbmV2ZXJTZXQgYSB2YWx1ZSBpcyBuZXZlciBwcm92aWRlZCB0byB0aGlzIGFyZ3VtZW50CiAgICAgIEBwYXJhbSB7U25hcHNob3RSZWNvcmRBcnJheX0gc25hcHNob3RSZWNvcmRBcnJheQogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgZmluZEFsbDogbnVsbCwKCiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIHdoZW4geW91IGNhbGwgYHF1ZXJ5YCBvbiB0aGUgc3RvcmUuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CiAgICAgIGltcG9ydCBSU1ZQIGZyb20gJ1JTVlAnOwogICAgICBpbXBvcnQgJCBmcm9tICdqcXVlcnknOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlci5leHRlbmQoewogICAgICAgIHF1ZXJ5KHN0b3JlLCB0eXBlLCBxdWVyeSkgewogICAgICAgICAgcmV0dXJuIG5ldyBSU1ZQLlByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7CiAgICAgICAgICAgICQuZ2V0SlNPTihgLyR7dHlwZS5tb2RlbE5hbWV9YCwgcXVlcnkpLnRoZW4oZnVuY3Rpb24oZGF0YSkgewogICAgICAgICAgICAgIHJlc29sdmUoZGF0YSk7CiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGpxWEhSKSB7CiAgICAgICAgICAgICAgcmVqZWN0KGpxWEhSKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgcXVlcnkKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZQogICAgICBAcGFyYW0ge09iamVjdH0gcXVlcnkKICAgICAgQHBhcmFtIHtBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXl9IHJlY29yZEFycmF5CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBxdWVyeTogbnVsbCwKCiAgICAvKioKICAgICAgVGhlIGBxdWVyeVJlY29yZCgpYCBtZXRob2QgaXMgaW52b2tlZCB3aGVuIHRoZSBzdG9yZSBpcyBhc2tlZCBmb3IgYSBzaW5nbGUKICAgICAgcmVjb3JkIHRocm91Z2ggYSBxdWVyeSBvYmplY3QuCiAgICAgICBJbiByZXNwb25zZSB0byBgcXVlcnlSZWNvcmQoKWAgYmVpbmcgY2FsbGVkLCB5b3Ugc2hvdWxkIGFsd2F5cyBmZXRjaCBmcmVzaAogICAgICBkYXRhLiBPbmNlIGZvdW5kLCB5b3UgY2FuIGFzeW5jaHJvbm91c2x5IGNhbGwgdGhlIHN0b3JlJ3MgYHB1c2goKWAgbWV0aG9kCiAgICAgIHRvIHB1c2ggdGhlIHJlY29yZCBpbnRvIHRoZSBzdG9yZS4KICAgICAgIEhlcmUgaXMgYW4gZXhhbXBsZSBgcXVlcnlSZWNvcmRgIGltcGxlbWVudGF0aW9uOgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBBZGFwdGVyLCB7IEJ1aWxkVVJMTWl4aW4gfSBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyJzsKICAgICAgaW1wb3J0IFJTVlAgZnJvbSAnUlNWUCc7CiAgICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZChCdWlsZFVSTE1peGluLCB7CiAgICAgICAgcXVlcnlSZWNvcmQoc3RvcmUsIHR5cGUsIHF1ZXJ5KSB7CiAgICAgICAgICByZXR1cm4gbmV3IFJTVlAuUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICAgICAgJC5nZXRKU09OKGAvJHt0eXBlLm1vZGVsTmFtZX1gLCBxdWVyeSkudGhlbihmdW5jdGlvbihkYXRhKSB7CiAgICAgICAgICAgICAgcmVzb2x2ZShkYXRhKTsKICAgICAgICAgICAgfSwgZnVuY3Rpb24oanFYSFIpIHsKICAgICAgICAgICAgICByZWplY3QoanFYSFIpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBxdWVyeVJlY29yZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge3N1YmNsYXNzIG9mIE1vZGVsfSB0eXBlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeQogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgcXVlcnlSZWNvcmQ6IG51bGwsCgogICAgLyoqCiAgICAgIElmIHRoZSBnbG9iYWxseSB1bmlxdWUgSURzIGZvciB5b3VyIHJlY29yZHMgc2hvdWxkIGJlIGdlbmVyYXRlZCBvbiB0aGUgY2xpZW50LAogICAgICBpbXBsZW1lbnQgdGhlIGBnZW5lcmF0ZUlkRm9yUmVjb3JkKClgIG1ldGhvZC4gVGhpcyBtZXRob2Qgd2lsbCBiZSBpbnZva2VkCiAgICAgIGVhY2ggdGltZSB5b3UgY3JlYXRlIGEgbmV3IHJlY29yZCwgYW5kIHRoZSB2YWx1ZSByZXR1cm5lZCBmcm9tIGl0IHdpbGwgYmUKICAgICAgYXNzaWduZWQgdG8gdGhlIHJlY29yZCdzIGBwcmltYXJ5S2V5YC4KICAgICAgIE1vc3QgdHJhZGl0aW9uYWwgUkVTVC1saWtlIEhUVFAgQVBJcyB3aWxsIG5vdCB1c2UgdGhpcyBtZXRob2QuIEluc3RlYWQsIHRoZSBJRAogICAgICBvZiB0aGUgcmVjb3JkIHdpbGwgYmUgc2V0IGJ5IHRoZSBzZXJ2ZXIsIGFuZCB5b3VyIGFkYXB0ZXIgd2lsbCB1cGRhdGUgdGhlIHN0b3JlCiAgICAgIHdpdGggdGhlIG5ldyBJRCB3aGVuIGl0IGNhbGxzIGBkaWRDcmVhdGVSZWNvcmQoKWAuIE9ubHkgaW1wbGVtZW50IHRoaXMgbWV0aG9kIGlmCiAgICAgIHlvdSBpbnRlbmQgdG8gZ2VuZXJhdGUgcmVjb3JkIElEcyBvbiB0aGUgY2xpZW50LXNpZGUuCiAgICAgICBUaGUgYGdlbmVyYXRlSWRGb3JSZWNvcmQoKWAgbWV0aG9kIHdpbGwgYmUgaW52b2tlZCB3aXRoIHRoZSByZXF1ZXN0aW5nIHN0b3JlIGFzCiAgICAgIHRoZSBmaXJzdCBwYXJhbWV0ZXIgYW5kIHRoZSBuZXdseSBjcmVhdGVkIHJlY29yZCBhcyB0aGUgc2Vjb25kIHBhcmFtZXRlcjoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CiAgICAgIGltcG9ydCB7IHY0IH0gZnJvbSAndXVpZCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgZ2VuZXJhdGVJZEZvclJlY29yZChzdG9yZSwgdHlwZSwgaW5wdXRQcm9wZXJ0aWVzKSB7CiAgICAgICAgICByZXR1cm4gdjQoKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZ2VuZXJhdGVJZEZvclJlY29yZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlICAgdGhlIE1vZGVsIGNsYXNzIG9mIHRoZSByZWNvcmQKICAgICAgQHBhcmFtIHtPYmplY3R9IGlucHV0UHJvcGVydGllcyBhIGhhc2ggb2YgcHJvcGVydGllcyB0byBzZXQgb24gdGhlCiAgICAgICAgbmV3bHkgY3JlYXRlZCByZWNvcmQuCiAgICAgIEByZXR1cm4geyhTdHJpbmd8TnVtYmVyKX0gaWQKICAgICovCiAgICBnZW5lcmF0ZUlkRm9yUmVjb3JkOiBudWxsLAoKICAgIC8qKgogICAgICBQcm94aWVzIHRvIHRoZSBzZXJpYWxpemVyJ3MgYHNlcmlhbGl6ZWAgbWV0aG9kLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlci5leHRlbmQoewogICAgICAgIGNyZWF0ZVJlY29yZChzdG9yZSwgdHlwZSwgc25hcHNob3QpIHsKICAgICAgICAgIGxldCBkYXRhID0gdGhpcy5zZXJpYWxpemUoc25hcHNob3QsIHsgaW5jbHVkZUlkOiB0cnVlIH0pOwogICAgICAgICAgbGV0IHVybCA9IGAvJHt0eXBlLm1vZGVsTmFtZX1gOwogICAgICAgICAgIC8vIC4uLgogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXJpYWxpemUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHBhcmFtIHtPYmplY3R9ICAgb3B0aW9ucwogICAgICBAcmV0dXJuIHtPYmplY3R9IHNlcmlhbGl6ZWQgc25hcHNob3QKICAgICovCiAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIHNlcmlhbGl6ZShzbmFwc2hvdCwgb3B0aW9ucykgewogICAgICByZXR1cm4gc25hcHNob3Quc2VyaWFsaXplKG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICAgSW1wbGVtZW50IHRoaXMgbWV0aG9kIGluIGEgc3ViY2xhc3MgdG8gaGFuZGxlIHRoZSBjcmVhdGlvbiBvZgogICAgICBuZXcgcmVjb3Jkcy4KICAgICAgIFNlcmlhbGl6ZXMgdGhlIHJlY29yZCBhbmQgc2VuZHMgaXQgdG8gdGhlIHNlcnZlci4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyJzsKICAgICAgaW1wb3J0IHsgcnVuIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogICAgICBpbXBvcnQgUlNWUCBmcm9tICdSU1ZQJzsKICAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBjcmVhdGVSZWNvcmQoc3RvcmUsIHR5cGUsIHNuYXBzaG90KSB7CiAgICAgICAgICBsZXQgZGF0YSA9IHRoaXMuc2VyaWFsaXplKHNuYXBzaG90LCB7IGluY2x1ZGVJZDogdHJ1ZSB9KTsKICAgICAgICAgICByZXR1cm4gbmV3IFJTVlAuUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICAgICAgJC5hamF4KHsKICAgICAgICAgICAgICB0eXBlOiAnUE9TVCcsCiAgICAgICAgICAgICAgdXJsOiBgLyR7dHlwZS5tb2RlbE5hbWV9YCwKICAgICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLAogICAgICAgICAgICAgIGRhdGE6IGRhdGEKICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbihkYXRhKSB7CiAgICAgICAgICAgICAgcnVuKG51bGwsIHJlc29sdmUsIGRhdGEpOwogICAgICAgICAgICB9LCBmdW5jdGlvbihqcVhIUikgewogICAgICAgICAgICAgIGpxWEhSLnRoZW4gPSBudWxsOyAvLyB0YW1lIGpRdWVyeSdzIGlsbCBtYW5uZXJlZCBwcm9taXNlcwogICAgICAgICAgICAgIHJ1bihudWxsLCByZWplY3QsIGpxWEhSKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgY3JlYXRlUmVjb3JkCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGUgICB0aGUgTW9kZWwgY2xhc3Mgb2YgdGhlIHJlY29yZAogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgY3JlYXRlUmVjb3JkOiBudWxsLAoKICAgIC8qKgogICAgICBJbXBsZW1lbnQgdGhpcyBtZXRob2QgaW4gYSBzdWJjbGFzcyB0byBoYW5kbGUgdGhlIHVwZGF0aW5nIG9mCiAgICAgIGEgcmVjb3JkLgogICAgICAgU2VyaWFsaXplcyB0aGUgcmVjb3JkIHVwZGF0ZSBhbmQgc2VuZHMgaXQgdG8gdGhlIHNlcnZlci4KICAgICAgIFRoZSB1cGRhdGVSZWNvcmQgbWV0aG9kIGlzIGV4cGVjdGVkIHRvIHJldHVybiBhIHByb21pc2UgdGhhdCB3aWxsCiAgICAgIHJlc29sdmUgd2l0aCB0aGUgc2VyaWFsaXplZCByZWNvcmQuIFRoaXMgYWxsb3dzIHRoZSBiYWNrZW5kIHRvCiAgICAgIGluZm9ybSB0aGUgRW1iZXIgRGF0YSBzdG9yZSB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGlzIHJlY29yZCBhZnRlcgogICAgICB0aGUgdXBkYXRlLiBJZiBpdCBpcyBub3QgcG9zc2libGUgdG8gcmV0dXJuIGEgc2VyaWFsaXplZCByZWNvcmQKICAgICAgdGhlIHVwZGF0ZVJlY29yZCBwcm9taXNlIGNhbiBhbHNvIHJlc29sdmUgd2l0aCBgdW5kZWZpbmVkYCBhbmQgdGhlCiAgICAgIEVtYmVyIERhdGEgc3RvcmUgd2lsbCBhc3N1bWUgYWxsIG9mIHRoZSB1cGRhdGVzIHdlcmUgc3VjY2Vzc2Z1bGx5CiAgICAgIGFwcGxpZWQgb24gdGhlIGJhY2tlbmQuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CiAgICAgIGltcG9ydCB7IHJ1biB9IGZyb20gJ0BlbWJlci9ydW5sb29wJzsKICAgICAgaW1wb3J0IFJTVlAgZnJvbSAnUlNWUCc7CiAgICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgdXBkYXRlUmVjb3JkKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCkgewogICAgICAgICAgbGV0IGRhdGEgPSB0aGlzLnNlcmlhbGl6ZShzbmFwc2hvdCwgeyBpbmNsdWRlSWQ6IHRydWUgfSk7CiAgICAgICAgICBsZXQgaWQgPSBzbmFwc2hvdC5pZDsKICAgICAgICAgICByZXR1cm4gbmV3IFJTVlAuUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICAgICAgJC5hamF4KHsKICAgICAgICAgICAgICB0eXBlOiAnUFVUJywKICAgICAgICAgICAgICB1cmw6IGAvJHt0eXBlLm1vZGVsTmFtZX0vJHtpZH1gLAogICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsCiAgICAgICAgICAgICAgZGF0YTogZGF0YQogICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uKGRhdGEpIHsKICAgICAgICAgICAgICBydW4obnVsbCwgcmVzb2x2ZSwgZGF0YSk7CiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGpxWEhSKSB7CiAgICAgICAgICAgICAganFYSFIudGhlbiA9IG51bGw7IC8vIHRhbWUgalF1ZXJ5J3MgaWxsIG1hbm5lcmVkIHByb21pc2VzCiAgICAgICAgICAgICAgcnVuKG51bGwsIHJlamVjdCwganFYSFIpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCB1cGRhdGVSZWNvcmQKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZSAgIHRoZSBNb2RlbCBjbGFzcyBvZiB0aGUgcmVjb3JkCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICB1cGRhdGVSZWNvcmQ6IG51bGwsCgogICAgLyoqCiAgICAgIEltcGxlbWVudCB0aGlzIG1ldGhvZCBpbiBhIHN1YmNsYXNzIHRvIGhhbmRsZSB0aGUgZGVsZXRpb24gb2YKICAgICAgYSByZWNvcmQuCiAgICAgICBTZW5kcyBhIGRlbGV0ZSByZXF1ZXN0IGZvciB0aGUgcmVjb3JkIHRvIHRoZSBzZXJ2ZXIuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CiAgICAgIGltcG9ydCB7IHJ1biB9IGZyb20gJ0BlbWJlci9ydW5sb29wJzsKICAgICAgaW1wb3J0IFJTVlAgZnJvbSAnUlNWUCc7CiAgICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgZGVsZXRlUmVjb3JkKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCkgewogICAgICAgICAgbGV0IGRhdGEgPSB0aGlzLnNlcmlhbGl6ZShzbmFwc2hvdCwgeyBpbmNsdWRlSWQ6IHRydWUgfSk7CiAgICAgICAgICBsZXQgaWQgPSBzbmFwc2hvdC5pZDsKICAgICAgICAgICByZXR1cm4gbmV3IFJTVlAuUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICAgICAgJC5hamF4KHsKICAgICAgICAgICAgICB0eXBlOiAnREVMRVRFJywKICAgICAgICAgICAgICB1cmw6IGAvJHt0eXBlLm1vZGVsTmFtZX0vJHtpZH1gLAogICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsCiAgICAgICAgICAgICAgZGF0YTogZGF0YQogICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uKGRhdGEpIHsKICAgICAgICAgICAgICBydW4obnVsbCwgcmVzb2x2ZSwgZGF0YSk7CiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGpxWEhSKSB7CiAgICAgICAgICAgICAganFYSFIudGhlbiA9IG51bGw7IC8vIHRhbWUgalF1ZXJ5J3MgaWxsIG1hbm5lcmVkIHByb21pc2VzCiAgICAgICAgICAgICAgcnVuKG51bGwsIHJlamVjdCwganFYSFIpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBkZWxldGVSZWNvcmQKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZSAgIHRoZSBNb2RlbCBjbGFzcyBvZiB0aGUgcmVjb3JkCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBkZWxldGVSZWNvcmQ6IG51bGwsCgogICAgLyoqCiAgICAgIEJ5IGRlZmF1bHQgdGhlIHN0b3JlIHdpbGwgdHJ5IHRvIGNvYWxlc2NlIGFsbCBgZmV0Y2hSZWNvcmRgIGNhbGxzIHdpdGhpbiB0aGUgc2FtZSBydW5sb29wCiAgICAgIGludG8gYXMgZmV3IHJlcXVlc3RzIGFzIHBvc3NpYmxlIGJ5IGNhbGxpbmcgZ3JvdXBSZWNvcmRzRm9yRmluZE1hbnkgYW5kIHBhc3NpbmcgaXQgaW50byBhIGZpbmRNYW55IGNhbGwuCiAgICAgIFlvdSBjYW4gb3B0IG91dCBvZiB0aGlzIGJlaGF2aW91ciBieSBlaXRoZXIgbm90IGltcGxlbWVudGluZyB0aGUgZmluZE1hbnkgaG9vayBvciBieSBzZXR0aW5nCiAgICAgIGNvYWxlc2NlRmluZFJlcXVlc3RzIHRvIGZhbHNlLgogICAgICAgQHByb3BlcnR5IGNvYWxlc2NlRmluZFJlcXVlc3RzCiAgICAgIEB0eXBlIHtib29sZWFufQogICAgKi8KICAgIGNvYWxlc2NlRmluZFJlcXVlc3RzOiB0cnVlLAoKICAgIC8qKgogICAgICBUaGUgc3RvcmUgd2lsbCBjYWxsIGBmaW5kTWFueWAgaW5zdGVhZCBvZiBtdWx0aXBsZSBgZmluZFJlY29yZGAKICAgICAgcmVxdWVzdHMgdG8gZmluZCBtdWx0aXBsZSByZWNvcmRzIGF0IG9uY2UgaWYgY29hbGVzY2VGaW5kUmVxdWVzdHMKICAgICAgaXMgdHJ1ZS4KICAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyJzsKICAgICAgaW1wb3J0IHsgcnVuIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogICAgICBpbXBvcnQgUlNWUCBmcm9tICdSU1ZQJzsKICAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBmaW5kTWFueShzdG9yZSwgdHlwZSwgaWRzLCBzbmFwc2hvdHMpIHsKICAgICAgICAgIHJldHVybiBuZXcgUlNWUC5Qcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgICAgICAkLmFqYXgoewogICAgICAgICAgICAgIHR5cGU6ICdHRVQnLAogICAgICAgICAgICAgIHVybDogYC8ke3R5cGUubW9kZWxOYW1lfS9gLAogICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsCiAgICAgICAgICAgICAgZGF0YTogeyBmaWx0ZXI6IHsgaWQ6IGlkcy5qb2luKCcsJykgfSB9CiAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24oZGF0YSkgewogICAgICAgICAgICAgIHJ1bihudWxsLCByZXNvbHZlLCBkYXRhKTsKICAgICAgICAgICAgfSwgZnVuY3Rpb24oanFYSFIpIHsKICAgICAgICAgICAgICBqcVhIUi50aGVuID0gbnVsbDsgLy8gdGFtZSBqUXVlcnkncyBpbGwgbWFubmVyZWQgcHJvbWlzZXMKICAgICAgICAgICAgICBydW4obnVsbCwgcmVqZWN0LCBqcVhIUik7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGZpbmRNYW55CiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGUgICB0aGUgTW9kZWwgY2xhc3Mgb2YgdGhlIHJlY29yZHMKICAgICAgQHBhcmFtIHtBcnJheX0gICAgaWRzCiAgICAgIEBwYXJhbSB7QXJyYXl9IHNuYXBzaG90cwogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgZmluZE1hbnk6IG51bGwsCgogICAgLyoqCiAgICAgIE9yZ2FuaXplIHJlY29yZHMgaW50byBncm91cHMsIGVhY2ggb2Ygd2hpY2ggaXMgdG8gYmUgcGFzc2VkIHRvIHNlcGFyYXRlCiAgICAgIGNhbGxzIHRvIGBmaW5kTWFueWAuCiAgICAgICBGb3IgZXhhbXBsZSwgaWYgeW91ciBBUEkgaGFzIG5lc3RlZCBVUkxzIHRoYXQgZGVwZW5kIG9uIHRoZSBwYXJlbnQsIHlvdSB3aWxsCiAgICAgIHdhbnQgdG8gZ3JvdXAgcmVjb3JkcyBieSB0aGVpciBwYXJlbnQuCiAgICAgICBUaGUgZGVmYXVsdCBpbXBsZW1lbnRhdGlvbiByZXR1cm5zIHRoZSByZWNvcmRzIGFzIGEgc2luZ2xlIGdyb3VwLgogICAgICAgQG1ldGhvZCBncm91cFJlY29yZHNGb3JGaW5kTWFueQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge0FycmF5fSBzbmFwc2hvdHMKICAgICAgQHJldHVybiB7QXJyYXl9ICBhbiBhcnJheSBvZiBhcnJheXMgb2YgcmVjb3JkcywgZWFjaCBvZiB3aGljaCBpcyB0byBiZQogICAgICAgICAgICAgICAgICAgICAgICBsb2FkZWQgc2VwYXJhdGVseSBieSBgZmluZE1hbnlgLgogICAgKi8KICAgIGdyb3VwUmVjb3Jkc0ZvckZpbmRNYW55OiBmdW5jdGlvbiBncm91cFJlY29yZHNGb3JGaW5kTWFueShzdG9yZSwgc25hcHNob3RzKSB7CiAgICAgIHJldHVybiBbc25hcHNob3RzXTsKICAgIH0sCgogICAgLyoqCiAgICAgIFRoaXMgbWV0aG9kIGlzIHVzZWQgYnkgdGhlIHN0b3JlIHRvIGRldGVybWluZSBpZiB0aGUgc3RvcmUgc2hvdWxkCiAgICAgIHJlbG9hZCBhIHJlY29yZCBmcm9tIHRoZSBhZGFwdGVyIHdoZW4gYSByZWNvcmQgaXMgcmVxdWVzdGVkIGJ5CiAgICAgIGBzdG9yZS5maW5kUmVjb3JkYC4KICAgICAgIElmIHRoaXMgbWV0aG9kIHJldHVybnMgYHRydWVgLCB0aGUgc3RvcmUgd2lsbCByZS1mZXRjaCBhIHJlY29yZCBmcm9tCiAgICAgIHRoZSBhZGFwdGVyLiBJZiB0aGlzIG1ldGhvZCByZXR1cm5zIGBmYWxzZWAsIHRoZSBzdG9yZSB3aWxsIHJlc29sdmUKICAgICAgaW1tZWRpYXRlbHkgdXNpbmcgdGhlIGNhY2hlZCByZWNvcmQuCiAgICAgICBGb3IgZXhhbXBsZSwgaWYgeW91IGFyZSBidWlsZGluZyBhbiBldmVudHMgdGlja2V0aW5nIHN5c3RlbSwgaW4gd2hpY2ggdXNlcnMKICAgICAgY2FuIG9ubHkgcmVzZXJ2ZSB0aWNrZXRzIGZvciAyMCBtaW51dGVzIGF0IGEgdGltZSwgYW5kIHdhbnQgdG8gZW5zdXJlIHRoYXQKICAgICAgaW4gZWFjaCByb3V0ZSB5b3UgaGF2ZSBkYXRhIHRoYXQgaXMgbm8gbW9yZSB0aGFuIDIwIG1pbnV0ZXMgb2xkIHlvdSBjb3VsZAogICAgICB3cml0ZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc2hvdWxkUmVsb2FkUmVjb3JkKHN0b3JlLCB0aWNrZXRTbmFwc2hvdCkgewogICAgICAgIGxldCBsYXN0QWNjZXNzZWRBdCA9IHRpY2tldFNuYXBzaG90LmF0dHIoJ2xhc3RBY2Nlc3NlZEF0Jyk7CiAgICAgICAgbGV0IHRpbWVEaWZmID0gbW9tZW50KCkuZGlmZihsYXN0QWNjZXNzZWRBdCwgJ21pbnV0ZXMnKTsKICAgICAgICAgaWYgKHRpbWVEaWZmID4gMjApIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgVGhpcyBtZXRob2Qgd291bGQgZW5zdXJlIHRoYXQgd2hlbmV2ZXIgeW91IGRvIGBzdG9yZS5maW5kUmVjb3JkKCd0aWNrZXQnLAogICAgICBpZClgIHlvdSB3aWxsIGFsd2F5cyBnZXQgYSB0aWNrZXQgdGhhdCBpcyBubyBtb3JlIHRoYW4gMjAgbWludXRlcyBvbGQuIEluCiAgICAgIGNhc2UgdGhlIGNhY2hlZCB2ZXJzaW9uIGlzIG1vcmUgdGhhbiAyMCBtaW51dGVzIG9sZCwgYGZpbmRSZWNvcmRgIHdpbGwgbm90CiAgICAgIHJlc29sdmUgdW50aWwgeW91IGZldGNoZWQgdGhlIGxhdGVzdCB2ZXJzaW9uLgogICAgICAgQnkgZGVmYXVsdCB0aGlzIGhvb2sgcmV0dXJucyBgZmFsc2VgLCBhcyBtb3N0IFVJcyBzaG91bGQgbm90IGJsb2NrIHVzZXIKICAgICAgaW50ZXJhY3Rpb25zIHdoaWxlIHdhaXRpbmcgb24gZGF0YSB1cGRhdGUuCiAgICAgICBOb3RlIHRoYXQsIHdpdGggZGVmYXVsdCBzZXR0aW5ncywgYHNob3VsZEJhY2tncm91bmRSZWxvYWRSZWNvcmRgIHdpbGwgYWx3YXlzCiAgICAgIHJlLWZldGNoIHRoZSByZWNvcmRzIGluIHRoZSBiYWNrZ3JvdW5kIGV2ZW4gaWYgYHNob3VsZFJlbG9hZFJlY29yZGAgcmV0dXJucwogICAgICBgZmFsc2VgLiBZb3UgY2FuIG92ZXJyaWRlIGBzaG91bGRCYWNrZ3JvdW5kUmVsb2FkUmVjb3JkYCBpZiB0aGlzIGRvZXMgbm90CiAgICAgIHN1aXQgeW91ciB1c2UgY2FzZS4KICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBzaG91bGRSZWxvYWRSZWNvcmQKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHJldHVybiB7Qm9vbGVhbn0KICAgICovCiAgICBzaG91bGRSZWxvYWRSZWNvcmQ6IGZ1bmN0aW9uIHNob3VsZFJlbG9hZFJlY29yZChzdG9yZSwgc25hcHNob3QpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfSwKCiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgdXNlZCBieSB0aGUgc3RvcmUgdG8gZGV0ZXJtaW5lIGlmIHRoZSBzdG9yZSBzaG91bGQKICAgICAgcmVsb2FkIGFsbCByZWNvcmRzIGZyb20gdGhlIGFkYXB0ZXIgd2hlbiByZWNvcmRzIGFyZSByZXF1ZXN0ZWQgYnkKICAgICAgYHN0b3JlLmZpbmRBbGxgLgogICAgICAgSWYgdGhpcyBtZXRob2QgcmV0dXJucyBgdHJ1ZWAsIHRoZSBzdG9yZSB3aWxsIHJlLWZldGNoIGFsbCByZWNvcmRzIGZyb20KICAgICAgdGhlIGFkYXB0ZXIuIElmIHRoaXMgbWV0aG9kIHJldHVybnMgYGZhbHNlYCwgdGhlIHN0b3JlIHdpbGwgcmVzb2x2ZQogICAgICBpbW1lZGlhdGVseSB1c2luZyB0aGUgY2FjaGVkIHJlY29yZHMuCiAgICAgICBGb3IgZXhhbXBsZSwgaWYgeW91IGFyZSBidWlsZGluZyBhbiBldmVudHMgdGlja2V0aW5nIHN5c3RlbSwgaW4gd2hpY2ggdXNlcnMKICAgICAgY2FuIG9ubHkgcmVzZXJ2ZSB0aWNrZXRzIGZvciAyMCBtaW51dGVzIGF0IGEgdGltZSwgYW5kIHdhbnQgdG8gZW5zdXJlIHRoYXQKICAgICAgaW4gZWFjaCByb3V0ZSB5b3UgaGF2ZSBkYXRhIHRoYXQgaXMgbm8gbW9yZSB0aGFuIDIwIG1pbnV0ZXMgb2xkIHlvdSBjb3VsZAogICAgICB3cml0ZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc2hvdWxkUmVsb2FkQWxsKHN0b3JlLCBzbmFwc2hvdEFycmF5KSB7CiAgICAgICAgbGV0IHNuYXBzaG90cyA9IHNuYXBzaG90QXJyYXkuc25hcHNob3RzKCk7CiAgICAgICAgIHJldHVybiBzbmFwc2hvdHMuYW55KCh0aWNrZXRTbmFwc2hvdCkgPT4gewogICAgICAgICAgbGV0IGxhc3RBY2Nlc3NlZEF0ID0gdGlja2V0U25hcHNob3QuYXR0cignbGFzdEFjY2Vzc2VkQXQnKTsKICAgICAgICAgIGxldCB0aW1lRGlmZiA9IG1vbWVudCgpLmRpZmYobGFzdEFjY2Vzc2VkQXQsICdtaW51dGVzJyk7CiAgICAgICAgICAgaWYgKHRpbWVEaWZmID4gMjApIHsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBUaGlzIG1ldGhvZCB3b3VsZCBlbnN1cmUgdGhhdCB3aGVuZXZlciB5b3UgZG8gYHN0b3JlLmZpbmRBbGwoJ3RpY2tldCcpYCB5b3UKICAgICAgd2lsbCBhbHdheXMgZ2V0IGEgbGlzdCBvZiB0aWNrZXRzIHRoYXQgYXJlIG5vIG1vcmUgdGhhbiAyMCBtaW51dGVzIG9sZC4gSW4KICAgICAgY2FzZSBhIGNhY2hlZCB2ZXJzaW9uIGlzIG1vcmUgdGhhbiAyMCBtaW51dGVzIG9sZCwgYGZpbmRBbGxgIHdpbGwgbm90CiAgICAgIHJlc29sdmUgdW50aWwgeW91IGZldGNoZWQgdGhlIGxhdGVzdCB2ZXJzaW9ucy4KICAgICAgIEJ5IGRlZmF1bHQsIHRoaXMgbWV0aG9kIHJldHVybnMgYHRydWVgIGlmIHRoZSBwYXNzZWQgYHNuYXBzaG90UmVjb3JkQXJyYXlgCiAgICAgIGlzIGVtcHR5IChtZWFuaW5nIHRoYXQgdGhlcmUgYXJlIG5vIHJlY29yZHMgbG9jYWxseSBhdmFpbGFibGUgeWV0KSwKICAgICAgb3RoZXJ3aXNlLCBpdCByZXR1cm5zIGBmYWxzZWAuCiAgICAgICBOb3RlIHRoYXQsIHdpdGggZGVmYXVsdCBzZXR0aW5ncywgYHNob3VsZEJhY2tncm91bmRSZWxvYWRBbGxgIHdpbGwgYWx3YXlzCiAgICAgIHJlLWZldGNoIGFsbCB0aGUgcmVjb3JkcyBpbiB0aGUgYmFja2dyb3VuZCBldmVuIGlmIGBzaG91bGRSZWxvYWRBbGxgIHJldHVybnMKICAgICAgYGZhbHNlYC4gWW91IGNhbiBvdmVycmlkZSBgc2hvdWxkQmFja2dyb3VuZFJlbG9hZEFsbGAgaWYgdGhpcyBkb2VzIG5vdCBzdWl0CiAgICAgIHlvdXIgdXNlIGNhc2UuCiAgICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgc2hvdWxkUmVsb2FkQWxsCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7U25hcHNob3RSZWNvcmRBcnJheX0gc25hcHNob3RSZWNvcmRBcnJheQogICAgICBAcmV0dXJuIHtCb29sZWFufQogICAgKi8KICAgIHNob3VsZFJlbG9hZEFsbDogZnVuY3Rpb24gc2hvdWxkUmVsb2FkQWxsKHN0b3JlLCBzbmFwc2hvdFJlY29yZEFycmF5KSB7CiAgICAgIHJldHVybiAhc25hcHNob3RSZWNvcmRBcnJheS5sZW5ndGg7CiAgICB9LAoKICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBpcyB1c2VkIGJ5IHRoZSBzdG9yZSB0byBkZXRlcm1pbmUgaWYgdGhlIHN0b3JlIHNob3VsZAogICAgICByZWxvYWQgYSByZWNvcmQgYWZ0ZXIgdGhlIGBzdG9yZS5maW5kUmVjb3JkYCBtZXRob2QgcmVzb2x2ZXMgYQogICAgICBjYWNoZWQgcmVjb3JkLgogICAgICAgVGhpcyBtZXRob2QgaXMgKm9ubHkqIGNoZWNrZWQgYnkgdGhlIHN0b3JlIHdoZW4gdGhlIHN0b3JlIGlzCiAgICAgIHJldHVybmluZyBhIGNhY2hlZCByZWNvcmQuCiAgICAgICBJZiB0aGlzIG1ldGhvZCByZXR1cm5zIGB0cnVlYCB0aGUgc3RvcmUgd2lsbCByZS1mZXRjaCBhIHJlY29yZCBmcm9tCiAgICAgIHRoZSBhZGFwdGVyLgogICAgICAgRm9yIGV4YW1wbGUsIGlmIHlvdSBkbyBub3Qgd2FudCB0byBmZXRjaCBjb21wbGV4IGRhdGEgb3ZlciBhIG1vYmlsZQogICAgICBjb25uZWN0aW9uLCBvciBpZiB0aGUgbmV0d29yayBpcyBkb3duLCB5b3UgY2FuIGltcGxlbWVudAogICAgICBgc2hvdWxkQmFja2dyb3VuZFJlbG9hZFJlY29yZGAgYXMgZm9sbG93czoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc2hvdWxkQmFja2dyb3VuZFJlbG9hZFJlY29yZChzdG9yZSwgc25hcHNob3QpIHsKICAgICAgICBsZXQgeyBkb3dubGluaywgZWZmZWN0aXZlVHlwZSB9ID0gbmF2aWdhdG9yLmNvbm5lY3Rpb247CiAgICAgICAgIHJldHVybiBkb3dubGluayA+IDAgJiYgZWZmZWN0aXZlVHlwZSA9PT0gJzRnJzsKICAgICAgfQogICAgICBgYGAKICAgICAgIEJ5IGRlZmF1bHQsIHRoaXMgaG9vayByZXR1cm5zIGB0cnVlYCBzbyB0aGUgZGF0YSBmb3IgdGhlIHJlY29yZCBpcyB1cGRhdGVkCiAgICAgIGluIHRoZSBiYWNrZ3JvdW5kLgogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIHNob3VsZEJhY2tncm91bmRSZWxvYWRSZWNvcmQKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHJldHVybiB7Qm9vbGVhbn0KICAgICovCiAgICBzaG91bGRCYWNrZ3JvdW5kUmVsb2FkUmVjb3JkOiBmdW5jdGlvbiBzaG91bGRCYWNrZ3JvdW5kUmVsb2FkUmVjb3JkKHN0b3JlLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0sCgogICAgLyoqCiAgICAgIFRoaXMgbWV0aG9kIGlzIHVzZWQgYnkgdGhlIHN0b3JlIHRvIGRldGVybWluZSBpZiB0aGUgc3RvcmUgc2hvdWxkCiAgICAgIHJlbG9hZCBhIHJlY29yZCBhcnJheSBhZnRlciB0aGUgYHN0b3JlLmZpbmRBbGxgIG1ldGhvZCByZXNvbHZlcwogICAgICB3aXRoIGEgY2FjaGVkIHJlY29yZCBhcnJheS4KICAgICAgIFRoaXMgbWV0aG9kIGlzICpvbmx5KiBjaGVja2VkIGJ5IHRoZSBzdG9yZSB3aGVuIHRoZSBzdG9yZSBpcwogICAgICByZXR1cm5pbmcgYSBjYWNoZWQgcmVjb3JkIGFycmF5LgogICAgICAgSWYgdGhpcyBtZXRob2QgcmV0dXJucyBgdHJ1ZWAgdGhlIHN0b3JlIHdpbGwgcmUtZmV0Y2ggYWxsIHJlY29yZHMKICAgICAgZnJvbSB0aGUgYWRhcHRlci4KICAgICAgIEZvciBleGFtcGxlLCBpZiB5b3UgZG8gbm90IHdhbnQgdG8gZmV0Y2ggY29tcGxleCBkYXRhIG92ZXIgYSBtb2JpbGUKICAgICAgY29ubmVjdGlvbiwgb3IgaWYgdGhlIG5ldHdvcmsgaXMgZG93biwgeW91IGNhbiBpbXBsZW1lbnQKICAgICAgYHNob3VsZEJhY2tncm91bmRSZWxvYWRBbGxgIGFzIGZvbGxvd3M6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHNob3VsZEJhY2tncm91bmRSZWxvYWRBbGwoc3RvcmUsIHNuYXBzaG90QXJyYXkpIHsKICAgICAgICBsZXQgeyBkb3dubGluaywgZWZmZWN0aXZlVHlwZSB9ID0gbmF2aWdhdG9yLmNvbm5lY3Rpb247CiAgICAgICAgIHJldHVybiBkb3dubGluayA+IDAgJiYgZWZmZWN0aXZlVHlwZSA9PT0gJzRnJzsKICAgICAgfQogICAgICBgYGAKICAgICAgIEJ5IGRlZmF1bHQgdGhpcyBtZXRob2QgcmV0dXJucyBgdHJ1ZWAsIGluZGljYXRpbmcgdGhhdCBhIGJhY2tncm91bmQgcmVsb2FkCiAgICAgIHNob3VsZCBhbHdheXMgYmUgdHJpZ2dlcmVkLgogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIHNob3VsZEJhY2tncm91bmRSZWxvYWRBbGwKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtTbmFwc2hvdFJlY29yZEFycmF5fSBzbmFwc2hvdFJlY29yZEFycmF5CiAgICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICAqLwogICAgc2hvdWxkQmFja2dyb3VuZFJlbG9hZEFsbDogZnVuY3Rpb24gc2hvdWxkQmFja2dyb3VuZFJlbG9hZEFsbChzdG9yZSwgc25hcHNob3RSZWNvcmRBcnJheSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKO2RlZmluZSgiQGVtYmVyLWRhdGEvYWRhcHRlci9qc29uLWFwaSIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QiLCAiZW1iZXItaW5mbGVjdG9yIiwgIkBlbWJlci1kYXRhL2FkYXB0ZXIvLXByaXZhdGUiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfcmVzdCwgX2VtYmVySW5mbGVjdG9yLCBfcHJpdmF0ZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgICBUaGUgYEpTT05BUElBZGFwdGVyYCBpcyB0aGUgZGVmYXVsdCBhZGFwdGVyIHVzZWQgYnkgRW1iZXIgRGF0YS4gSXQKICAgIGlzIHJlc3BvbnNpYmxlIGZvciB0cmFuc2Zvcm1pbmcgdGhlIHN0b3JlJ3MgcmVxdWVzdHMgaW50byBIVFRQCiAgICByZXF1ZXN0cyB0aGF0IGZvbGxvdyB0aGUgW0pTT04gQVBJXShodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0LykKICAgIGZvcm1hdC4KICAKICAgICMjIEpTT04gQVBJIENvbnZlbnRpb25zCiAgCiAgICBUaGUgSlNPTkFQSUFkYXB0ZXIgdXNlcyBKU09OIEFQSSBjb252ZW50aW9ucyBmb3IgYnVpbGRpbmcgdGhlIFVSTAogICAgZm9yIGEgcmVjb3JkIGFuZCBzZWxlY3RpbmcgdGhlIEhUVFAgdmVyYiB0byB1c2Ugd2l0aCBhIHJlcXVlc3QuIFRoZQogICAgYWN0aW9ucyB5b3UgY2FuIHRha2Ugb24gYSByZWNvcmQgbWFwIG9udG8gdGhlIGZvbGxvd2luZyBVUkxzIGluIHRoZQogICAgSlNPTiBBUEkgYWRhcHRlcjoKICAKICA8dGFibGU+CiAgICA8dHI+CiAgICAgIDx0aD4KICAgICAgICBBY3Rpb24KICAgICAgPC90aD4KICAgICAgPHRoPgogICAgICAgIEhUVFAgVmVyYgogICAgICA8L3RoPgogICAgICA8dGg+CiAgICAgICAgVVJMCiAgICAgIDwvdGg+CiAgICA8L3RyPgogICAgPHRyPgogICAgICA8dGg+CiAgICAgICAgYHN0b3JlLmZpbmRSZWNvcmQoJ3Bvc3QnLCAxMjMpYAogICAgICA8L3RoPgogICAgICA8dGQ+CiAgICAgICAgR0VUCiAgICAgIDwvdGQ+CiAgICAgIDx0ZD4KICAgICAgICAvcG9zdHMvMTIzCiAgICAgIDwvdGQ+CiAgICA8L3RyPgogICAgPHRyPgogICAgICA8dGg+CiAgICAgICAgYHN0b3JlLmZpbmRBbGwoJ3Bvc3QnKWAKICAgICAgPC90aD4KICAgICAgPHRkPgogICAgICAgIEdFVAogICAgICA8L3RkPgogICAgICA8dGQ+CiAgICAgICAgL3Bvc3RzCiAgICAgIDwvdGQ+CiAgICA8L3RyPgogICAgPHRyPgogICAgICA8dGg+CiAgICAgICAgVXBkYXRlIGBwb3N0UmVjb3JkLnNhdmUoKWAKICAgICAgPC90aD4KICAgICAgPHRkPgogICAgICAgIFBBVENICiAgICAgIDwvdGQ+CiAgICAgIDx0ZD4KICAgICAgICAvcG9zdHMvMTIzCiAgICAgIDwvdGQ+CiAgICA8L3RyPgogICAgPHRyPgogICAgICA8dGg+CiAgICAgICAgQ3JlYXRlIGBzdG9yZS5jcmVhdGVSZWNvcmQoJ3Bvc3QnKS5zYXZlKClgCiAgICAgIDwvdGg+CiAgICAgIDx0ZD4KICAgICAgICBQT1NUCiAgICAgIDwvdGQ+CiAgICAgIDx0ZD4KICAgICAgICAvcG9zdHMKICAgICAgPC90ZD4KICAgIDwvdHI+CiAgICA8dHI+CiAgICAgIDx0aD4KICAgICAgICBEZWxldGUgYHBvc3RSZWNvcmQuZGVzdHJveVJlY29yZCgpYAogICAgICA8L3RoPgogICAgICA8dGQ+CiAgICAgICAgREVMRVRFCiAgICAgIDwvdGQ+CiAgICAgIDx0ZD4KICAgICAgICAvcG9zdHMvMTIzCiAgICAgIDwvdGQ+CiAgICA8L3RyPgogIDwvdGFibGU+CiAgCiAgICAjIyBTdWNjZXNzIGFuZCBmYWlsdXJlCiAgCiAgICBUaGUgSlNPTkFQSUFkYXB0ZXIgd2lsbCBjb25zaWRlciBhIHN1Y2Nlc3MgYW55IHJlc3BvbnNlIHdpdGggYQogICAgc3RhdHVzIGNvZGUgb2YgdGhlIDJ4eCBmYW1pbHkgKCJTdWNjZXNzIiksIGFzIHdlbGwgYXMgMzA0ICgiTm90CiAgICBNb2RpZmllZCIpLiBBbnkgb3RoZXIgc3RhdHVzIGNvZGUgd2lsbCBiZSBjb25zaWRlcmVkIGEgZmFpbHVyZS4KICAKICAgIE9uIHN1Y2Nlc3MsIHRoZSByZXF1ZXN0IHByb21pc2Ugd2lsbCBiZSByZXNvbHZlZCB3aXRoIHRoZSBmdWxsCiAgICByZXNwb25zZSBwYXlsb2FkLgogIAogICAgRmFpbGVkIHJlc3BvbnNlcyB3aXRoIHN0YXR1cyBjb2RlIDQyMiAoIlVucHJvY2Vzc2FibGUgRW50aXR5Iikgd2lsbAogICAgYmUgY29uc2lkZXJlZCAiaW52YWxpZCIuIFRoZSByZXNwb25zZSB3aWxsIGJlIGRpc2NhcmRlZCwgZXhjZXB0IGZvcgogICAgdGhlIGBlcnJvcnNgIGtleS4gVGhlIHJlcXVlc3QgcHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkIHdpdGggYQogICAgYEludmFsaWRFcnJvcmAuIFRoaXMgZXJyb3Igb2JqZWN0IHdpbGwgZW5jYXBzdWxhdGUgdGhlIHNhdmVkCiAgICBgZXJyb3JzYCB2YWx1ZS4KICAKICAgIEFueSBvdGhlciBzdGF0dXMgY29kZXMgd2lsbCBiZSB0cmVhdGVkIGFzIGFuIGFkYXB0ZXIgZXJyb3IuIFRoZQogICAgcmVxdWVzdCBwcm9taXNlIHdpbGwgYmUgcmVqZWN0ZWQsIHNpbWlsYXJseSB0byB0aGUgaW52YWxpZCBjYXNlLAogICAgYnV0IHdpdGggYW4gaW5zdGFuY2Ugb2YgYEFkYXB0ZXJFcnJvcmAgaW5zdGVhZC4KICAKICAgICMjIyBFbmRwb2ludCBwYXRoIGN1c3RvbWl6YXRpb24KICAKICAgIEVuZHBvaW50IHBhdGhzIGNhbiBiZSBwcmVmaXhlZCB3aXRoIGEgYG5hbWVzcGFjZWAgYnkgc2V0dGluZyB0aGUKICAgIG5hbWVzcGFjZSBwcm9wZXJ0eSBvbiB0aGUgYWRhcHRlcjoKICAKICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgaW1wb3J0IEpTT05BUElBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvanNvbi1hcGknOwogIAogICAgZXhwb3J0IGRlZmF1bHQgSlNPTkFQSUFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgbmFtZXNwYWNlOiAnYXBpLzEnCiAgICB9KTsKICAgIGBgYAogICAgUmVxdWVzdHMgZm9yIHRoZSBgcGVyc29uYCBtb2RlbCB3b3VsZCBub3cgdGFyZ2V0IGAvYXBpLzEvcGVvcGxlLzFgLgogIAogICAgIyMjIEhvc3QgY3VzdG9taXphdGlvbgogIAogICAgQW4gYWRhcHRlciBjYW4gdGFyZ2V0IG90aGVyIGhvc3RzIGJ5IHNldHRpbmcgdGhlIGBob3N0YCBwcm9wZXJ0eS4KICAKICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgaW1wb3J0IEpTT05BUElBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvanNvbi1hcGknOwogIAogICAgZXhwb3J0IGRlZmF1bHQgSlNPTkFQSUFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgaG9zdDogJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJwogICAgfSk7CiAgICBgYGAKICAKICAgIFJlcXVlc3RzIGZvciB0aGUgYHBlcnNvbmAgbW9kZWwgd291bGQgbm93IHRhcmdldAogICAgYGh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3Blb3BsZS8xYC4KICAKICAgIEBzaW5jZSAxLjEzLjAKICAgIEBjbGFzcyBKU09OQVBJQWRhcHRlcgogICAgQGNvbnN0cnVjdG9yCiAgICBAZXh0ZW5kcyBSRVNUQWRhcHRlcgogICovCiAgdmFyIEpTT05BUElBZGFwdGVyID0gX3Jlc3QuZGVmYXVsdC5leHRlbmQoewogICAgZGVmYXVsdFNlcmlhbGl6ZXI6ICctanNvbi1hcGknLAogICAgX2RlZmF1bHRDb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL3ZuZC5hcGkranNvbicsCgogICAgLyoqCiAgICAgIEBtZXRob2QgYWpheE9wdGlvbnMKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IHVybAogICAgICBAcGFyYW0ge1N0cmluZ30gdHlwZSBUaGUgcmVxdWVzdCB0eXBlIEdFVCwgUE9TVCwgUFVULCBERUxFVEUgZXRjLgogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgYWpheE9wdGlvbnM6IGZ1bmN0aW9uIGFqYXhPcHRpb25zKHVybCwgdHlwZSwgb3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICB2YXIgaGFzaCA9IHRoaXMuX3N1cGVyKHVybCwgdHlwZSwgb3B0aW9ucyk7CgogICAgICBoYXNoLmhlYWRlcnNbJ0FjY2VwdCddID0gaGFzaC5oZWFkZXJzWydBY2NlcHQnXSB8fCAnYXBwbGljYXRpb24vdm5kLmFwaStqc29uJzsKICAgICAgcmV0dXJuIGhhc2g7CiAgICB9LAoKICAgIC8qKgogICAgICBCeSBkZWZhdWx0IHRoZSBKU09OQVBJQWRhcHRlciB3aWxsIHNlbmQgZWFjaCBmaW5kIHJlcXVlc3QgY29taW5nIGZyb20gYSBgc3RvcmUuZmluZGAKICAgICAgb3IgZnJvbSBhY2Nlc3NpbmcgYSByZWxhdGlvbnNoaXAgc2VwYXJhdGVseSB0byB0aGUgc2VydmVyLiBJZiB5b3VyIHNlcnZlciBzdXBwb3J0cyBwYXNzaW5nCiAgICAgIGlkcyBhcyBhIHF1ZXJ5IHN0cmluZywgeW91IGNhbiBzZXQgY29hbGVzY2VGaW5kUmVxdWVzdHMgdG8gdHJ1ZSB0byBjb2FsZXNjZSBhbGwgZmluZCByZXF1ZXN0cwogICAgICB3aXRoaW4gYSBzaW5nbGUgcnVubG9vcC4KICAgICAgIEZvciBleGFtcGxlLCBpZiB5b3UgaGF2ZSBhbiBpbml0aWFsIHBheWxvYWQgb2Y6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHsKICAgICAgICBkYXRhOiB7CiAgICAgICAgICBpZDogMSwKICAgICAgICAgIHR5cGU6ICdwb3N0JywKICAgICAgICAgIHJlbGF0aW9uc2hpcDogewogICAgICAgICAgICBjb21tZW50czogewogICAgICAgICAgICAgIGRhdGE6IFsKICAgICAgICAgICAgICAgIHsgaWQ6IDEsIHR5cGU6ICdjb21tZW50JyB9LAogICAgICAgICAgICAgICAgeyBpZDogMiwgdHlwZTogJ2NvbW1lbnQnIH0KICAgICAgICAgICAgICBdCiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBCeSBkZWZhdWx0IGNhbGxpbmcgYHBvc3QuZ2V0KCdjb21tZW50cycpYCB3aWxsIHRyaWdnZXIgdGhlIGZvbGxvd2luZyByZXF1ZXN0cyhhc3N1bWluZyB0aGUKICAgICAgY29tbWVudHMgaGF2ZW4ndCBiZWVuIGxvYWRlZCBiZWZvcmUpOgogICAgICAgYGBgCiAgICAgIEdFVCAvY29tbWVudHMvMQogICAgICBHRVQgL2NvbW1lbnRzLzIKICAgICAgYGBgCiAgICAgICBJZiB5b3Ugc2V0IGNvYWxlc2NlRmluZFJlcXVlc3RzIHRvIGB0cnVlYCBpdCB3aWxsIGluc3RlYWQgdHJpZ2dlciB0aGUgZm9sbG93aW5nIHJlcXVlc3Q6CiAgICAgICBgYGAKICAgICAgR0VUIC9jb21tZW50cz9maWx0ZXJbaWRdPTEsMgogICAgICBgYGAKICAgICAgIFNldHRpbmcgY29hbGVzY2VGaW5kUmVxdWVzdHMgdG8gYHRydWVgIGFsc28gd29ya3MgZm9yIGBzdG9yZS5maW5kYCByZXF1ZXN0cyBhbmQgYGJlbG9uZ3NUb2AKICAgICAgcmVsYXRpb25zaGlwcyBhY2Nlc3NlZCB3aXRoaW4gdGhlIHNhbWUgcnVubG9vcC4gSWYgeW91IHNldCBgY29hbGVzY2VGaW5kUmVxdWVzdHM6IHRydWVgCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0b3JlLmZpbmRSZWNvcmQoJ2NvbW1lbnQnLCAxKTsKICAgICAgc3RvcmUuZmluZFJlY29yZCgnY29tbWVudCcsIDIpOwogICAgICBgYGAKICAgICAgIHdpbGwgYWxzbyBzZW5kIGEgcmVxdWVzdCB0bzogYEdFVCAvY29tbWVudHM/ZmlsdGVyW2lkXT0xLDJgCiAgICAgICBOb3RlOiBSZXF1ZXN0cyBjb2FsZXNjaW5nIHJlbHkgb24gVVJMIGJ1aWxkaW5nIHN0cmF0ZWd5LiBTbyBpZiB5b3Ugb3ZlcnJpZGUgYGJ1aWxkVVJMYCBpbiB5b3VyIGFwcAogICAgICBgZ3JvdXBSZWNvcmRzRm9yRmluZE1hbnlgIG1vcmUgbGlrZWx5IHNob3VsZCBiZSBvdmVycmlkZGVuIGFzIHdlbGwgaW4gb3JkZXIgZm9yIGNvYWxlc2NpbmcgdG8gd29yay4KICAgICAgIEBwcm9wZXJ0eSBjb2FsZXNjZUZpbmRSZXF1ZXN0cwogICAgICBAdHlwZSB7Ym9vbGVhbn0KICAgICovCiAgICBjb2FsZXNjZUZpbmRSZXF1ZXN0czogZmFsc2UsCiAgICBmaW5kTWFueTogZnVuY3Rpb24gZmluZE1hbnkoc3RvcmUsIHR5cGUsIGlkcywgc25hcHNob3RzKSB7CiAgICAgIHZhciB1cmwgPSB0aGlzLmJ1aWxkVVJMKHR5cGUubW9kZWxOYW1lLCBpZHMsIHNuYXBzaG90cywgJ2ZpbmRNYW55Jyk7CiAgICAgIHJldHVybiB0aGlzLmFqYXgodXJsLCAnR0VUJywgewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIGZpbHRlcjogewogICAgICAgICAgICBpZDogaWRzLmpvaW4oJywnKQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICB9LAogICAgcGF0aEZvclR5cGU6IGZ1bmN0aW9uIHBhdGhGb3JUeXBlKG1vZGVsTmFtZSkgewogICAgICB2YXIgZGFzaGVyaXplZCA9IEVtYmVyLlN0cmluZy5kYXNoZXJpemUobW9kZWxOYW1lKTsKICAgICAgcmV0dXJuICgwLCBfZW1iZXJJbmZsZWN0b3IucGx1cmFsaXplKShkYXNoZXJpemVkKTsKICAgIH0sCiAgICB1cGRhdGVSZWNvcmQ6IGZ1bmN0aW9uIHVwZGF0ZVJlY29yZChzdG9yZSwgdHlwZSwgc25hcHNob3QpIHsKICAgICAgdmFyIGRhdGEgPSAoMCwgX3ByaXZhdGUuc2VyaWFsaXplSW50b0hhc2gpKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCk7CiAgICAgIHZhciB1cmwgPSB0aGlzLmJ1aWxkVVJMKHR5cGUubW9kZWxOYW1lLCBzbmFwc2hvdC5pZCwgc25hcHNob3QsICd1cGRhdGVSZWNvcmQnKTsKICAgICAgcmV0dXJuIHRoaXMuYWpheCh1cmwsICdQQVRDSCcsIHsKICAgICAgICBkYXRhOiBkYXRhCiAgICAgIH0pOwogICAgfQogIH0pOwoKICB2YXIgX2RlZmF1bHQgPSBKU09OQVBJQWRhcHRlcjsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwo7ZGVmaW5lKCJAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QiLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvYWRhcHRlciIsICJAZW1iZXItZGF0YS9hZGFwdGVyLy1wcml2YXRlIiwgIkBlbWJlci1kYXRhL2FkYXB0ZXIvZXJyb3IiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfYWRhcHRlciwgX3ByaXZhdGUsIF9lcnJvcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZmV0Y2hPcHRpb25zID0gZmV0Y2hPcHRpb25zOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CiAgdmFyIFByb21pc2UgPSBFbWJlci5SU1ZQLlByb21pc2U7CiAgdmFyIGhhc0pRdWVyeSA9IHR5cGVvZiBqUXVlcnkgIT09ICd1bmRlZmluZWQnOwogIHZhciBoYXNOYWpheCA9IHR5cGVvZiBuYWpheCAhPT0gJ3VuZGVmaW5lZCc7CiAgLyoqCiAgICBUaGUgUkVTVCBhZGFwdGVyIGFsbG93cyB5b3VyIHN0b3JlIHRvIGNvbW11bmljYXRlIHdpdGggYW4gSFRUUCBzZXJ2ZXIgYnkKICAgIHRyYW5zbWl0dGluZyBKU09OIHZpYSBYSFIuIE1vc3QgRW1iZXIuanMgYXBwcyB0aGF0IGNvbnN1bWUgYSBKU09OIEFQSQogICAgc2hvdWxkIHVzZSB0aGUgUkVTVCBhZGFwdGVyLgogIAogICAgVGhpcyBhZGFwdGVyIGlzIGRlc2lnbmVkIGFyb3VuZCB0aGUgaWRlYSB0aGF0IHRoZSBKU09OIGV4Y2hhbmdlZCB3aXRoCiAgICB0aGUgc2VydmVyIHNob3VsZCBiZSBjb252ZW50aW9uYWwuCiAgCiAgICAjIyBTdWNjZXNzIGFuZCBmYWlsdXJlCiAgCiAgICBUaGUgUkVTVCBhZGFwdGVyIHdpbGwgY29uc2lkZXIgYSBzdWNjZXNzIGFueSByZXNwb25zZSB3aXRoIGEgc3RhdHVzIGNvZGUKICAgIG9mIHRoZSAyeHggZmFtaWx5ICgiU3VjY2VzcyIpLCBhcyB3ZWxsIGFzIDMwNCAoIk5vdCBNb2RpZmllZCIpLiBBbnkgb3RoZXIKICAgIHN0YXR1cyBjb2RlIHdpbGwgYmUgY29uc2lkZXJlZCBhIGZhaWx1cmUuCiAgCiAgICBPbiBzdWNjZXNzLCB0aGUgcmVxdWVzdCBwcm9taXNlIHdpbGwgYmUgcmVzb2x2ZWQgd2l0aCB0aGUgZnVsbCByZXNwb25zZQogICAgcGF5bG9hZC4KICAKICAgIEZhaWxlZCByZXNwb25zZXMgd2l0aCBzdGF0dXMgY29kZSA0MjIgKCJVbnByb2Nlc3NhYmxlIEVudGl0eSIpIHdpbGwgYmUKICAgIGNvbnNpZGVyZWQgImludmFsaWQiLiBUaGUgcmVzcG9uc2Ugd2lsbCBiZSBkaXNjYXJkZWQsIGV4Y2VwdCBmb3IgdGhlCiAgICBgZXJyb3JzYCBrZXkuIFRoZSByZXF1ZXN0IHByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoIGEgYEludmFsaWRFcnJvcmAuCiAgICBUaGlzIGVycm9yIG9iamVjdCB3aWxsIGVuY2Fwc3VsYXRlIHRoZSBzYXZlZCBgZXJyb3JzYCB2YWx1ZS4KICAKICAgIEFueSBvdGhlciBzdGF0dXMgY29kZXMgd2lsbCBiZSB0cmVhdGVkIGFzIGFuICJhZGFwdGVyIGVycm9yIi4gVGhlIHJlcXVlc3QKICAgIHByb21pc2Ugd2lsbCBiZSByZWplY3RlZCwgc2ltaWxhcmx5IHRvIHRoZSAiaW52YWxpZCIgY2FzZSwgYnV0IHdpdGgKICAgIGFuIGluc3RhbmNlIG9mIGBBZGFwdGVyRXJyb3JgIGluc3RlYWQuCiAgCiAgICAjIyBKU09OIFN0cnVjdHVyZQogIAogICAgVGhlIFJFU1QgYWRhcHRlciBleHBlY3RzIHRoZSBKU09OIHJldHVybmVkIGZyb20geW91ciBzZXJ2ZXIgdG8gZm9sbG93CiAgICB0aGVzZSBjb252ZW50aW9ucy4KICAKICAgICMjIyBPYmplY3QgUm9vdAogIAogICAgVGhlIEpTT04gcGF5bG9hZCBzaG91bGQgYmUgYW4gb2JqZWN0IHRoYXQgY29udGFpbnMgdGhlIHJlY29yZCBpbnNpZGUgYQogICAgcm9vdCBwcm9wZXJ0eS4gRm9yIGV4YW1wbGUsIGluIHJlc3BvbnNlIHRvIGEgYEdFVGAgcmVxdWVzdCBmb3IKICAgIGAvcG9zdHMvMWAsIHRoZSBKU09OIHNob3VsZCBsb29rIGxpa2UgdGhpczoKICAKICAgIGBgYGpzCiAgICB7CiAgICAgICJwb3N0cyI6IHsKICAgICAgICAiaWQiOiAxLAogICAgICAgICJ0aXRsZSI6ICJJJ20gUnVubmluZyB0byBSZWZvcm0gdGhlIFczQydzIFRhZyIsCiAgICAgICAgImF1dGhvciI6ICJZZWh1ZGEgS2F0eiIKICAgICAgfQogICAgfQogICAgYGBgCiAgCiAgICBTaW1pbGFybHksIGluIHJlc3BvbnNlIHRvIGEgYEdFVGAgcmVxdWVzdCBmb3IgYC9wb3N0c2AsIHRoZSBKU09OIHNob3VsZAogICAgbG9vayBsaWtlIHRoaXM6CiAgCiAgICBgYGBqcwogICAgewogICAgICAicG9zdHMiOiBbCiAgICAgICAgewogICAgICAgICAgImlkIjogMSwKICAgICAgICAgICJ0aXRsZSI6ICJJJ20gUnVubmluZyB0byBSZWZvcm0gdGhlIFczQydzIFRhZyIsCiAgICAgICAgICAiYXV0aG9yIjogIlllaHVkYSBLYXR6IgogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgImlkIjogMiwKICAgICAgICAgICJ0aXRsZSI6ICJSYWlscyBpcyBvbWFrYXNlIiwKICAgICAgICAgICJhdXRob3IiOiAiRDJIIgogICAgICAgIH0KICAgICAgXQogICAgfQogICAgYGBgCiAgCiAgICBOb3RlIHRoYXQgdGhlIG9iamVjdCByb290IGNhbiBiZSBwbHVyYWxpemVkIGZvciBib3RoIGEgc2luZ2xlLW9iamVjdCByZXNwb25zZQogICAgYW5kIGFuIGFycmF5IHJlc3BvbnNlOiB0aGUgUkVTVCBhZGFwdGVyIGlzIG5vdCBzdHJpY3Qgb24gdGhpcy4gRnVydGhlciwgaWYgdGhlCiAgICBIVFRQIHNlcnZlciByZXNwb25kcyB0byBhIGBHRVRgIHJlcXVlc3QgdG8gYC9wb3N0cy8xYCAoZS5nLiB0aGUgcmVzcG9uc2UgdG8gYQogICAgYGZpbmRSZWNvcmRgIHF1ZXJ5KSB3aXRoIG1vcmUgdGhhbiBvbmUgb2JqZWN0IGluIHRoZSBhcnJheSwgRW1iZXIgRGF0YSB3aWxsCiAgICBvbmx5IGRpc3BsYXkgdGhlIG9iamVjdCB3aXRoIHRoZSBtYXRjaGluZyBJRC4KICAKICAgICMjIyBDb252ZW50aW9uYWwgTmFtZXMKICAKICAgIEF0dHJpYnV0ZSBuYW1lcyBpbiB5b3VyIEpTT04gcGF5bG9hZCBzaG91bGQgYmUgdGhlIGNhbWVsQ2FzZWQgdmVyc2lvbnMgb2YKICAgIHRoZSBhdHRyaWJ1dGVzIGluIHlvdXIgRW1iZXIuanMgbW9kZWxzLgogIAogICAgRm9yIGV4YW1wbGUsIGlmIHlvdSBoYXZlIGEgYFBlcnNvbmAgbW9kZWw6CiAgCiAgICBgYGBhcHAvbW9kZWxzL3BlcnNvbi5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBmaXJzdE5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICBsYXN0TmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgIG9jY3VwYXRpb246IGF0dHIoJ3N0cmluZycpCiAgICB9KTsKICAgIGBgYAogIAogICAgVGhlIEpTT04gcmV0dXJuZWQgc2hvdWxkIGxvb2sgbGlrZSB0aGlzOgogIAogICAgYGBganMKICAgIHsKICAgICAgInBlb3BsZSI6IHsKICAgICAgICAiaWQiOiA1LAogICAgICAgICJmaXJzdE5hbWUiOiAiWmFwaG9kIiwKICAgICAgICAibGFzdE5hbWUiOiAiQmVlYmxlYnJveCIsCiAgICAgICAgIm9jY3VwYXRpb24iOiAiUHJlc2lkZW50IgogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgICMjIyMgUmVsYXRpb25zaGlwcwogIAogICAgUmVsYXRpb25zaGlwcyBhcmUgdXN1YWxseSByZXByZXNlbnRlZCBieSBpZHMgdG8gdGhlIHJlY29yZCBpbiB0aGUKICAgIHJlbGF0aW9uc2hpcC4gVGhlIHJlbGF0ZWQgcmVjb3JkcyBjYW4gdGhlbiBiZSBzaWRlbG9hZGVkIGluIHRoZQogICAgcmVzcG9uc2UgdW5kZXIgYSBrZXkgZm9yIHRoZSB0eXBlLgogIAogICAgYGBganMKICAgIHsKICAgICAgInBvc3RzIjogewogICAgICAgICJpZCI6IDUsCiAgICAgICAgInRpdGxlIjogIkknbSBSdW5uaW5nIHRvIFJlZm9ybSB0aGUgVzNDJ3MgVGFnIiwKICAgICAgICAiYXV0aG9yIjogIlllaHVkYSBLYXR6IiwKICAgICAgICAiY29tbWVudHMiOiBbMSwgMl0KICAgICAgfSwKICAgICAgImNvbW1lbnRzIjogW3sKICAgICAgICAiaWQiOiAxLAogICAgICAgICJhdXRob3IiOiAiVXNlciAxIiwKICAgICAgICAibWVzc2FnZSI6ICJGaXJzdCEiLAogICAgICB9LCB7CiAgICAgICAgImlkIjogMiwKICAgICAgICAiYXV0aG9yIjogIlVzZXIgMiIsCiAgICAgICAgIm1lc3NhZ2UiOiAiR29vZCBMdWNrISIsCiAgICAgIH1dCiAgICB9CiAgICBgYGAKICAKICAgIElmIHRoZSByZWNvcmRzIGluIHRoZSByZWxhdGlvbnNoaXAgYXJlIG5vdCBrbm93biB3aGVuIHRoZSByZXNwb25zZQogICAgaXMgc2VyaWFsaXplZCBpdCdzIGFsc28gcG9zc2libGUgdG8gcmVwcmVzZW50IHRoZSByZWxhdGlvbnNoaXAgYXMgYQogICAgVVJMIHVzaW5nIHRoZSBgbGlua3NgIGtleSBpbiB0aGUgcmVzcG9uc2UuIEVtYmVyIERhdGEgd2lsbCBmZXRjaAogICAgdGhpcyBVUkwgdG8gcmVzb2x2ZSB0aGUgcmVsYXRpb25zaGlwIHdoZW4gaXQgaXMgYWNjZXNzZWQgZm9yIHRoZQogICAgZmlyc3QgdGltZS4KICAKICAgIGBgYGpzCiAgICB7CiAgICAgICJwb3N0cyI6IHsKICAgICAgICAiaWQiOiA1LAogICAgICAgICJ0aXRsZSI6ICJJJ20gUnVubmluZyB0byBSZWZvcm0gdGhlIFczQydzIFRhZyIsCiAgICAgICAgImF1dGhvciI6ICJZZWh1ZGEgS2F0eiIsCiAgICAgICAgImxpbmtzIjogewogICAgICAgICAgImNvbW1lbnRzIjogIi9wb3N0cy81L2NvbW1lbnRzIgogICAgICAgIH0KICAgICAgfQogICAgfQogICAgYGBgCiAgCiAgICAjIyMgRXJyb3JzCiAgCiAgICBJZiBhIHJlc3BvbnNlIGlzIGNvbnNpZGVyZWQgYSBmYWlsdXJlLCB0aGUgSlNPTiBwYXlsb2FkIGlzIGV4cGVjdGVkIHRvIGluY2x1ZGUKICAgIGEgdG9wLWxldmVsIGtleSBgZXJyb3JzYCwgZGV0YWlsaW5nIGFueSBzcGVjaWZpYyBpc3N1ZXMuIEZvciBleGFtcGxlOgogIAogICAgYGBganMKICAgIHsKICAgICAgImVycm9ycyI6IHsKICAgICAgICAibXNnIjogIlNvbWV0aGluZyB3ZW50IHdyb25nIgogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIFRoaXMgYWRhcHRlciBkb2VzIG5vdCBtYWtlIGFueSBhc3N1bXB0aW9ucyBhcyB0byB0aGUgZm9ybWF0IG9mIHRoZSBgZXJyb3JzYAogICAgb2JqZWN0LiBJdCB3aWxsIHNpbXBseSBiZSBwYXNzZWQgYWxvbmcgYXMgaXMsIHdyYXBwZWQgaW4gYW4gaW5zdGFuY2UKICAgIG9mIGBJbnZhbGlkRXJyb3JgIG9yIGBBZGFwdGVyRXJyb3JgLiBUaGUgc2VyaWFsaXplciBjYW4gaW50ZXJwcmV0IGl0CiAgICBhZnRlcndhcmRzLgogIAogICAgIyMgQ3VzdG9taXphdGlvbgogIAogICAgIyMjIEVuZHBvaW50IHBhdGggY3VzdG9taXphdGlvbgogIAogICAgRW5kcG9pbnQgcGF0aHMgY2FuIGJlIHByZWZpeGVkIHdpdGggYSBgbmFtZXNwYWNlYCBieSBzZXR0aW5nIHRoZSBuYW1lc3BhY2UKICAgIHByb3BlcnR5IG9uIHRoZSBhZGFwdGVyOgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgUkVTVEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9yZXN0JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgIG5hbWVzcGFjZTogJ2FwaS8xJwogICAgfSk7CiAgICBgYGAKICAgIFJlcXVlc3RzIGZvciB0aGUgYFBlcnNvbmAgbW9kZWwgd291bGQgbm93IHRhcmdldCBgL2FwaS8xL3Blb3BsZS8xYC4KICAKICAgICMjIyBIb3N0IGN1c3RvbWl6YXRpb24KICAKICAgIEFuIGFkYXB0ZXIgY2FuIHRhcmdldCBvdGhlciBob3N0cyBieSBzZXR0aW5nIHRoZSBgaG9zdGAgcHJvcGVydHkuCiAgCiAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgaG9zdDogJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJwogICAgfSk7CiAgICBgYGAKICAKICAgICMjIyBIZWFkZXJzIGN1c3RvbWl6YXRpb24KICAKICAgIFNvbWUgQVBJcyByZXF1aXJlIEhUVFAgaGVhZGVycywgZS5nLiB0byBwcm92aWRlIGFuIEFQSSBrZXkuIEFyYml0cmFyeQogICAgaGVhZGVycyBjYW4gYmUgc2V0IGFzIGtleS92YWx1ZSBwYWlycyBvbiB0aGUgYFJFU1RBZGFwdGVyYCdzIGBoZWFkZXJzYAogICAgb2JqZWN0IGFuZCBFbWJlciBEYXRhIHdpbGwgc2VuZCB0aGVtIGFsb25nIHdpdGggZWFjaCBhamF4IHJlcXVlc3QuCiAgCiAgCiAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgaW1wb3J0IHsgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgIGhlYWRlcnM6IGNvbXB1dGVkKGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiB7CiAgICAgICAgICAnQVBJX0tFWSc6ICdzZWNyZXQga2V5JywKICAgICAgICAgICdBTk9USEVSX0hFQURFUic6ICdTb21lIGhlYWRlciB2YWx1ZScKICAgICAgICB9OwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgYGhlYWRlcnNgIGNhbiBhbHNvIGJlIHVzZWQgYXMgYSBjb21wdXRlZCBwcm9wZXJ0eSB0byBzdXBwb3J0IGR5bmFtaWMKICAgIGhlYWRlcnMuIEluIHRoZSBleGFtcGxlIGJlbG93LCB0aGUgYHNlc3Npb25gIG9iamVjdCBoYXMgYmVlbgogICAgaW5qZWN0ZWQgaW50byBhbiBhZGFwdGVyIGJ5IEVtYmVyJ3MgY29udGFpbmVyLgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgUkVTVEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9yZXN0JzsKICAgIGltcG9ydCB7IGNvbXB1dGVkIH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBSRVNUQWRhcHRlci5leHRlbmQoewogICAgICBoZWFkZXJzOiBjb21wdXRlZCgnc2Vzc2lvbi5hdXRoVG9rZW4nLCBmdW5jdGlvbigpIHsKICAgICAgICByZXR1cm4gewogICAgICAgICAgJ0FQSV9LRVknOiB0aGlzLmdldCgnc2Vzc2lvbi5hdXRoVG9rZW4nKSwKICAgICAgICAgICdBTk9USEVSX0hFQURFUic6ICdTb21lIGhlYWRlciB2YWx1ZScKICAgICAgICB9OwogICAgICB9KQogICAgfSk7CiAgICBgYGAKICAKICAgIEluIHNvbWUgY2FzZXMsIHlvdXIgZHluYW1pYyBoZWFkZXJzIG1heSByZXF1aXJlIGRhdGEgZnJvbSBzb21lCiAgICBvYmplY3Qgb3V0c2lkZSBvZiBFbWJlcidzIG9ic2VydmVyIHN5c3RlbSAoZm9yIGV4YW1wbGUKICAgIGBkb2N1bWVudC5jb29raWVgKS4gWW91IGNhbiB1c2UgdGhlCiAgICBbdm9sYXRpbGVdKC9hcGkvY2xhc3Nlcy9FbWJlci5Db21wdXRlZFByb3BlcnR5Lmh0bWw/YW5jaG9yPXZvbGF0aWxlKQogICAgZnVuY3Rpb24gdG8gc2V0IHRoZSBwcm9wZXJ0eSBpbnRvIGEgbm9uLWNhY2hlZCBtb2RlIGNhdXNpbmcgdGhlIGhlYWRlcnMgdG8KICAgIGJlIHJlY29tcHV0ZWQgd2l0aCBldmVyeSByZXF1ZXN0LgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgUkVTVEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9yZXN0JzsKICAgIGltcG9ydCB7IGdldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgIGhlYWRlcnM6IGNvbXB1dGVkKGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiB7CiAgICAgICAgICAnQVBJX0tFWSc6IGdldChkb2N1bWVudC5jb29raWUubWF0Y2goL2FwaUtleVw9KFteO10qKS8pLCAnMScpLAogICAgICAgICAgJ0FOT1RIRVJfSEVBREVSJzogJ1NvbWUgaGVhZGVyIHZhbHVlJwogICAgICAgIH07CiAgICAgIH0pLnZvbGF0aWxlKCkKICAgIH0pOwogICAgYGBgCiAgCiAgICBAY2xhc3MgUkVTVEFkYXB0ZXIKICAgIEBjb25zdHJ1Y3RvcgogICAgQGV4dGVuZHMgQWRhcHRlcgogICAgQHVzZXMgQnVpbGRVUkxNaXhpbgogICovCgogIHZhciBSRVNUQWRhcHRlciA9IF9hZGFwdGVyLmRlZmF1bHQuZXh0ZW5kKF9hZGFwdGVyLkJ1aWxkVVJMTWl4aW4sIHsKICAgIGRlZmF1bHRTZXJpYWxpemVyOiAnLXJlc3QnLAogICAgX2RlZmF1bHRDb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9dXRmLTgnLAogICAgZmFzdGJvb3Q6IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIEVtYmVyLmdldE93bmVyKHRoaXMpLmxvb2t1cCgnc2VydmljZTpmYXN0Ym9vdCcpOwogICAgfSksCiAgICB1c2VGZXRjaDogRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgICB2YXIgRU5WID0gRW1iZXIuZ2V0T3duZXIodGhpcykucmVzb2x2ZVJlZ2lzdHJhdGlvbignY29uZmlnOmVudmlyb25tZW50Jyk7IC8vIFRPRE86IGh0dHBzOi8vZ2l0aHViLmNvbS9lbWJlcmpzL2RhdGEvaXNzdWVzLzYwOTMKCiAgICAgIHZhciBqUXVlcnlJbnRlZ3JhdGlvbkRpc2FibGVkID0gRU5WICYmIEVOVi5FbWJlckVOViAmJiBFTlYuRW1iZXJFTlYuX0pRVUVSWV9JTlRFR1JBVElPTiA9PT0gZmFsc2U7CgogICAgICBpZiAoalF1ZXJ5SW50ZWdyYXRpb25EaXNhYmxlZCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9IGVsc2UgaWYgKGhhc05hamF4IHx8IGhhc0pRdWVyeSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgfSksCgogICAgLyoqCiAgICAgIEJ5IGRlZmF1bHQsIHRoZSBSRVNUQWRhcHRlciB3aWxsIHNlbmQgdGhlIHF1ZXJ5IHBhcmFtcyBzb3J0ZWQgYWxwaGFiZXRpY2FsbHkgdG8gdGhlCiAgICAgIHNlcnZlci4KICAgICAgIEZvciBleGFtcGxlOgogICAgICAgYGBganMKICAgICAgc3RvcmUucXVlcnkoJ3Bvc3RzJywgeyBzb3J0OiAncHJpY2UnLCBjYXRlZ29yeTogJ3BldHMnIH0pOwogICAgICBgYGAKICAgICAgIHdpbGwgZ2VuZXJhdGUgYSByZXF1ZXN0cyBsaWtlIHRoaXMgYC9wb3N0cz9jYXRlZ29yeT1wZXRzJnNvcnQ9cHJpY2VgLCBldmVuIGlmIHRoZQogICAgICBwYXJhbWV0ZXJzIHdlcmUgc3BlY2lmaWVkIGluIGEgZGlmZmVyZW50IG9yZGVyLgogICAgICAgVGhhdCB3YXkgdGhlIGdlbmVyYXRlZCBVUkwgd2lsbCBiZSBkZXRlcm1pbmlzdGljIGFuZCB0aGF0IHNpbXBsaWZpZXMgY2FjaGluZyBtZWNoYW5pc21zCiAgICAgIGluIHRoZSBiYWNrZW5kLgogICAgICAgU2V0dGluZyBgc29ydFF1ZXJ5UGFyYW1zYCB0byBhIGZhbHNleSB2YWx1ZSB3aWxsIHJlc3BlY3QgdGhlIG9yaWdpbmFsIG9yZGVyLgogICAgICAgSW4gY2FzZSB5b3Ugd2FudCB0byBzb3J0IHRoZSBxdWVyeSBwYXJhbWV0ZXJzIHdpdGggYSBkaWZmZXJlbnQgY3JpdGVyaWEsIHNldAogICAgICBgc29ydFF1ZXJ5UGFyYW1zYCB0byB5b3VyIGN1c3RvbSBzb3J0IGZ1bmN0aW9uLgogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBzb3J0UXVlcnlQYXJhbXMocGFyYW1zKSB7CiAgICAgICAgICBsZXQgc29ydGVkS2V5cyA9IE9iamVjdC5rZXlzKHBhcmFtcykuc29ydCgpLnJldmVyc2UoKTsKICAgICAgICAgIGxldCBsZW4gPSBzb3J0ZWRLZXlzLmxlbmd0aCwgbmV3UGFyYW1zID0ge307CiAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICAgICAgICBuZXdQYXJhbXNbc29ydGVkS2V5c1tpXV0gPSBwYXJhbXNbc29ydGVkS2V5c1tpXV07CiAgICAgICAgICB9CiAgICAgICAgICAgcmV0dXJuIG5ld1BhcmFtczsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc29ydFF1ZXJ5UGFyYW1zCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvYmoKICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgKi8KICAgIHNvcnRRdWVyeVBhcmFtczogZnVuY3Rpb24gc29ydFF1ZXJ5UGFyYW1zKG9iaikgewogICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7CiAgICAgIHZhciBsZW4gPSBrZXlzLmxlbmd0aDsKCiAgICAgIGlmIChsZW4gPCAyKSB7CiAgICAgICAgcmV0dXJuIG9iajsKICAgICAgfQoKICAgICAgdmFyIG5ld1F1ZXJ5UGFyYW1zID0ge307CiAgICAgIHZhciBzb3J0ZWRLZXlzID0ga2V5cy5zb3J0KCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgICAgbmV3UXVlcnlQYXJhbXNbc29ydGVkS2V5c1tpXV0gPSBvYmpbc29ydGVkS2V5c1tpXV07CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXdRdWVyeVBhcmFtczsKICAgIH0sCgogICAgLyoqCiAgICAgIEJ5IGRlZmF1bHQgdGhlIFJFU1RBZGFwdGVyIHdpbGwgc2VuZCBlYWNoIGZpbmQgcmVxdWVzdCBjb21pbmcgZnJvbSBhIGBzdG9yZS5maW5kYAogICAgICBvciBmcm9tIGFjY2Vzc2luZyBhIHJlbGF0aW9uc2hpcCBzZXBhcmF0ZWx5IHRvIHRoZSBzZXJ2ZXIuIElmIHlvdXIgc2VydmVyIHN1cHBvcnRzIHBhc3NpbmcKICAgICAgaWRzIGFzIGEgcXVlcnkgc3RyaW5nLCB5b3UgY2FuIHNldCBjb2FsZXNjZUZpbmRSZXF1ZXN0cyB0byB0cnVlIHRvIGNvYWxlc2NlIGFsbCBmaW5kIHJlcXVlc3RzCiAgICAgIHdpdGhpbiBhIHNpbmdsZSBydW5sb29wLgogICAgICAgRm9yIGV4YW1wbGUsIGlmIHlvdSBoYXZlIGFuIGluaXRpYWwgcGF5bG9hZCBvZjoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgewogICAgICAgIHBvc3Q6IHsKICAgICAgICAgIGlkOiAxLAogICAgICAgICAgY29tbWVudHM6IFsxLCAyXQogICAgICAgIH0KICAgICAgfQogICAgICBgYGAKICAgICAgIEJ5IGRlZmF1bHQgY2FsbGluZyBgcG9zdC5nZXQoJ2NvbW1lbnRzJylgIHdpbGwgdHJpZ2dlciB0aGUgZm9sbG93aW5nIHJlcXVlc3RzKGFzc3VtaW5nIHRoZQogICAgICBjb21tZW50cyBoYXZlbid0IGJlZW4gbG9hZGVkIGJlZm9yZSk6CiAgICAgICBgYGAKICAgICAgR0VUIC9jb21tZW50cy8xCiAgICAgIEdFVCAvY29tbWVudHMvMgogICAgICBgYGAKICAgICAgIElmIHlvdSBzZXQgY29hbGVzY2VGaW5kUmVxdWVzdHMgdG8gYHRydWVgIGl0IHdpbGwgaW5zdGVhZCB0cmlnZ2VyIHRoZSBmb2xsb3dpbmcgcmVxdWVzdDoKICAgICAgIGBgYAogICAgICBHRVQgL2NvbW1lbnRzP2lkc1tdPTEmaWRzW109MgogICAgICBgYGAKICAgICAgIFNldHRpbmcgY29hbGVzY2VGaW5kUmVxdWVzdHMgdG8gYHRydWVgIGFsc28gd29ya3MgZm9yIGBzdG9yZS5maW5kYCByZXF1ZXN0cyBhbmQgYGJlbG9uZ3NUb2AKICAgICAgcmVsYXRpb25zaGlwcyBhY2Nlc3NlZCB3aXRoaW4gdGhlIHNhbWUgcnVubG9vcC4gSWYgeW91IHNldCBgY29hbGVzY2VGaW5kUmVxdWVzdHM6IHRydWVgCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0b3JlLmZpbmRSZWNvcmQoJ2NvbW1lbnQnLCAxKTsKICAgICAgc3RvcmUuZmluZFJlY29yZCgnY29tbWVudCcsIDIpOwogICAgICBgYGAKICAgICAgIHdpbGwgYWxzbyBzZW5kIGEgcmVxdWVzdCB0bzogYEdFVCAvY29tbWVudHM/aWRzW109MSZpZHNbXT0yYAogICAgICAgTm90ZTogUmVxdWVzdHMgY29hbGVzY2luZyByZWx5IG9uIFVSTCBidWlsZGluZyBzdHJhdGVneS4gU28gaWYgeW91IG92ZXJyaWRlIGBidWlsZFVSTGAgaW4geW91ciBhcHAKICAgICAgYGdyb3VwUmVjb3Jkc0ZvckZpbmRNYW55YCBtb3JlIGxpa2VseSBzaG91bGQgYmUgb3ZlcnJpZGRlbiBhcyB3ZWxsIGluIG9yZGVyIGZvciBjb2FsZXNjaW5nIHRvIHdvcmsuCiAgICAgICBAcHJvcGVydHkgY29hbGVzY2VGaW5kUmVxdWVzdHMKICAgICAgQHR5cGUge2Jvb2xlYW59CiAgICAqLwogICAgY29hbGVzY2VGaW5kUmVxdWVzdHM6IGZhbHNlLAoKICAgIC8qKgogICAgICBFbmRwb2ludCBwYXRocyBjYW4gYmUgcHJlZml4ZWQgd2l0aCBhIGBuYW1lc3BhY2VgIGJ5IHNldHRpbmcgdGhlIG5hbWVzcGFjZQogICAgICBwcm9wZXJ0eSBvbiB0aGUgYWRhcHRlcjoKICAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgUkVTVEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9yZXN0JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgbmFtZXNwYWNlOiAnYXBpLzEnCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFJlcXVlc3RzIGZvciB0aGUgYFBvc3RgIG1vZGVsIHdvdWxkIG5vdyB0YXJnZXQgYC9hcGkvMS9wb3N0L2AuCiAgICAgICBAcHJvcGVydHkgbmFtZXNwYWNlCiAgICAgIEB0eXBlIHtTdHJpbmd9CiAgICAqLwoKICAgIC8qKgogICAgICBBbiBhZGFwdGVyIGNhbiB0YXJnZXQgb3RoZXIgaG9zdHMgYnkgc2V0dGluZyB0aGUgYGhvc3RgIHByb3BlcnR5LgogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBob3N0OiAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFJlcXVlc3RzIGZvciB0aGUgYFBvc3RgIG1vZGVsIHdvdWxkIG5vdyB0YXJnZXQgYGh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3Bvc3QvYC4KICAgICAgIEBwcm9wZXJ0eSBob3N0CiAgICAgIEB0eXBlIHtTdHJpbmd9CiAgICAqLwoKICAgIC8qKgogICAgICBTb21lIEFQSXMgcmVxdWlyZSBIVFRQIGhlYWRlcnMsIGUuZy4gdG8gcHJvdmlkZSBhbiBBUEkKICAgICAga2V5LiBBcmJpdHJhcnkgaGVhZGVycyBjYW4gYmUgc2V0IGFzIGtleS92YWx1ZSBwYWlycyBvbiB0aGUKICAgICAgYFJFU1RBZGFwdGVyYCdzIGBoZWFkZXJzYCBvYmplY3QgYW5kIEVtYmVyIERhdGEgd2lsbCBzZW5kIHRoZW0KICAgICAgYWxvbmcgd2l0aCBlYWNoIGFqYXggcmVxdWVzdC4gRm9yIGR5bmFtaWMgaGVhZGVycyBzZWUgW2hlYWRlcnMKICAgICAgY3VzdG9taXphdGlvbl0oL2VtYmVyLWRhdGEvcmVsZWFzZS9jbGFzc2VzL1JFU1RBZGFwdGVyKS4KICAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgUkVTVEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9yZXN0JzsKICAgICAgaW1wb3J0IHsgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgaGVhZGVyczogY29tcHV0ZWQoZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAnQVBJX0tFWSc6ICdzZWNyZXQga2V5JywKICAgICAgICAgICAgJ0FOT1RIRVJfSEVBREVSJzogJ1NvbWUgaGVhZGVyIHZhbHVlJwogICAgICAgICAgfTsKICAgICAgICB9KQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAcHJvcGVydHkgaGVhZGVycwogICAgICBAdHlwZSB7T2JqZWN0fQogICAgICovCgogICAgLyoqCiAgICAgIENhbGxlZCBieSB0aGUgc3RvcmUgaW4gb3JkZXIgdG8gZmV0Y2ggdGhlIEpTT04gZm9yIGEgZ2l2ZW4KICAgICAgdHlwZSBhbmQgSUQuCiAgICAgICBUaGUgYGZpbmRSZWNvcmRgIG1ldGhvZCBtYWtlcyBhbiBBamF4IHJlcXVlc3QgdG8gYSBVUkwgY29tcHV0ZWQgYnkKICAgICAgYGJ1aWxkVVJMYCwgYW5kIHJldHVybnMgYSBwcm9taXNlIGZvciB0aGUgcmVzdWx0aW5nIHBheWxvYWQuCiAgICAgICBUaGlzIG1ldGhvZCBwZXJmb3JtcyBhbiBIVFRQIGBHRVRgIHJlcXVlc3Qgd2l0aCB0aGUgaWQgcHJvdmlkZWQgYXMgcGFydCBvZiB0aGUgcXVlcnkgc3RyaW5nLgogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIGZpbmRSZWNvcmQKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZQogICAgICBAcGFyYW0ge1N0cmluZ30gaWQKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIGZpbmRSZWNvcmQ6IGZ1bmN0aW9uIGZpbmRSZWNvcmQoc3RvcmUsIHR5cGUsIGlkLCBzbmFwc2hvdCkgewogICAgICB2YXIgdXJsID0gdGhpcy5idWlsZFVSTCh0eXBlLm1vZGVsTmFtZSwgaWQsIHNuYXBzaG90LCAnZmluZFJlY29yZCcpOwogICAgICB2YXIgcXVlcnkgPSB0aGlzLmJ1aWxkUXVlcnkoc25hcHNob3QpOwogICAgICByZXR1cm4gdGhpcy5hamF4KHVybCwgJ0dFVCcsIHsKICAgICAgICBkYXRhOiBxdWVyeQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIENhbGxlZCBieSB0aGUgc3RvcmUgaW4gb3JkZXIgdG8gZmV0Y2ggYSBKU09OIGFycmF5IGZvciBhbGwKICAgICAgb2YgdGhlIHJlY29yZHMgZm9yIGEgZ2l2ZW4gdHlwZS4KICAgICAgIFRoZSBgZmluZEFsbGAgbWV0aG9kIG1ha2VzIGFuIEFqYXggKEhUVFAgR0VUKSByZXF1ZXN0IHRvIGEgVVJMIGNvbXB1dGVkIGJ5IGBidWlsZFVSTGAsIGFuZCByZXR1cm5zIGEKICAgICAgcHJvbWlzZSBmb3IgdGhlIHJlc3VsdGluZyBwYXlsb2FkLgogICAgICAgQG1ldGhvZCBmaW5kQWxsCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGUKICAgICAgQHBhcmFtIHt1bmRlZmluZWR9IG5ldmVyU2V0IGEgdmFsdWUgaXMgbmV2ZXIgcHJvdmlkZWQgdG8gdGhpcyBhcmd1bWVudAogICAgICBAcGFyYW0ge1NuYXBzaG90UmVjb3JkQXJyYXl9IHNuYXBzaG90UmVjb3JkQXJyYXkKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIGZpbmRBbGw6IGZ1bmN0aW9uIGZpbmRBbGwoc3RvcmUsIHR5cGUsIHNpbmNlVG9rZW4sIHNuYXBzaG90UmVjb3JkQXJyYXkpIHsKICAgICAgdmFyIHF1ZXJ5ID0gdGhpcy5idWlsZFF1ZXJ5KHNuYXBzaG90UmVjb3JkQXJyYXkpOwogICAgICB2YXIgdXJsID0gdGhpcy5idWlsZFVSTCh0eXBlLm1vZGVsTmFtZSwgbnVsbCwgc25hcHNob3RSZWNvcmRBcnJheSwgJ2ZpbmRBbGwnKTsKCiAgICAgIGlmIChzaW5jZVRva2VuKSB7CiAgICAgICAgcXVlcnkuc2luY2UgPSBzaW5jZVRva2VuOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5hamF4KHVybCwgJ0dFVCcsIHsKICAgICAgICBkYXRhOiBxdWVyeQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIENhbGxlZCBieSB0aGUgc3RvcmUgaW4gb3JkZXIgdG8gZmV0Y2ggYSBKU09OIGFycmF5IGZvcgogICAgICB0aGUgcmVjb3JkcyB0aGF0IG1hdGNoIGEgcGFydGljdWxhciBxdWVyeS4KICAgICAgIFRoZSBgcXVlcnlgIG1ldGhvZCBtYWtlcyBhbiBBamF4IChIVFRQIEdFVCkgcmVxdWVzdCB0byBhIFVSTAogICAgICBjb21wdXRlZCBieSBgYnVpbGRVUkxgLCBhbmQgcmV0dXJucyBhIHByb21pc2UgZm9yIHRoZSByZXN1bHRpbmcKICAgICAgcGF5bG9hZC4KICAgICAgIFRoZSBgcXVlcnlgIGFyZ3VtZW50IGlzIGEgc2ltcGxlIEphdmFTY3JpcHQgb2JqZWN0IHRoYXQgd2lsbCBiZSBwYXNzZWQgZGlyZWN0bHkKICAgICAgdG8gdGhlIHNlcnZlciBhcyBwYXJhbWV0ZXJzLgogICAgICAgQG1ldGhvZCBxdWVyeQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeQogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgcXVlcnk6IGZ1bmN0aW9uIHF1ZXJ5KHN0b3JlLCB0eXBlLCBfcXVlcnkpIHsKICAgICAgdmFyIHVybCA9IHRoaXMuYnVpbGRVUkwodHlwZS5tb2RlbE5hbWUsIG51bGwsIG51bGwsICdxdWVyeScsIF9xdWVyeSk7CgogICAgICBpZiAodGhpcy5zb3J0UXVlcnlQYXJhbXMpIHsKICAgICAgICBfcXVlcnkgPSB0aGlzLnNvcnRRdWVyeVBhcmFtcyhfcXVlcnkpOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5hamF4KHVybCwgJ0dFVCcsIHsKICAgICAgICBkYXRhOiBfcXVlcnkKICAgICAgfSk7CiAgICB9LAoKICAgIC8qKgogICAgICBDYWxsZWQgYnkgdGhlIHN0b3JlIGluIG9yZGVyIHRvIGZldGNoIGEgSlNPTiBvYmplY3QgZm9yCiAgICAgIHRoZSByZWNvcmQgdGhhdCBtYXRjaGVzIGEgcGFydGljdWxhciBxdWVyeS4KICAgICAgIFRoZSBgcXVlcnlSZWNvcmRgIG1ldGhvZCBtYWtlcyBhbiBBamF4IChIVFRQIEdFVCkgcmVxdWVzdCB0byBhIFVSTAogICAgICBjb21wdXRlZCBieSBgYnVpbGRVUkxgLCBhbmQgcmV0dXJucyBhIHByb21pc2UgZm9yIHRoZSByZXN1bHRpbmcKICAgICAgcGF5bG9hZC4KICAgICAgIFRoZSBgcXVlcnlgIGFyZ3VtZW50IGlzIGEgc2ltcGxlIEphdmFTY3JpcHQgb2JqZWN0IHRoYXQgd2lsbCBiZSBwYXNzZWQgZGlyZWN0bHkKICAgICAgdG8gdGhlIHNlcnZlciBhcyBwYXJhbWV0ZXJzLgogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIHF1ZXJ5UmVjb3JkCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGUKICAgICAgQHBhcmFtIHtPYmplY3R9IHF1ZXJ5CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBxdWVyeVJlY29yZDogZnVuY3Rpb24gcXVlcnlSZWNvcmQoc3RvcmUsIHR5cGUsIHF1ZXJ5KSB7CiAgICAgIHZhciB1cmwgPSB0aGlzLmJ1aWxkVVJMKHR5cGUubW9kZWxOYW1lLCBudWxsLCBudWxsLCAncXVlcnlSZWNvcmQnLCBxdWVyeSk7CgogICAgICBpZiAodGhpcy5zb3J0UXVlcnlQYXJhbXMpIHsKICAgICAgICBxdWVyeSA9IHRoaXMuc29ydFF1ZXJ5UGFyYW1zKHF1ZXJ5KTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuYWpheCh1cmwsICdHRVQnLCB7CiAgICAgICAgZGF0YTogcXVlcnkKICAgICAgfSk7CiAgICB9LAoKICAgIC8qKgogICAgICBDYWxsZWQgYnkgdGhlIHN0b3JlIGluIG9yZGVyIHRvIGZldGNoIHNldmVyYWwgcmVjb3JkcyB0b2dldGhlciBpZiBgY29hbGVzY2VGaW5kUmVxdWVzdHNgIGlzIHRydWUKICAgICAgIEZvciBleGFtcGxlLCBpZiB0aGUgb3JpZ2luYWwgcGF5bG9hZCBsb29rcyBsaWtlOgogICAgICAgYGBganMKICAgICAgewogICAgICAgICJpZCI6IDEsCiAgICAgICAgInRpdGxlIjogIlJhaWxzIGlzIG9tYWthc2UiLAogICAgICAgICJjb21tZW50cyI6IFsgMSwgMiwgMyBdCiAgICAgIH0KICAgICAgYGBgCiAgICAgICBUaGUgSURzIHdpbGwgYmUgcGFzc2VkIGFzIGEgVVJMLWVuY29kZWQgQXJyYXkgb2YgSURzLCBpbiB0aGlzIGZvcm06CiAgICAgICBgYGAKICAgICAgaWRzW109MSZpZHNbXT0yJmlkc1tdPTMKICAgICAgYGBgCiAgICAgICBNYW55IHNlcnZlcnMsIHN1Y2ggYXMgUmFpbHMgYW5kIFBIUCwgd2lsbCBhdXRvbWF0aWNhbGx5IGNvbnZlcnQgdGhpcyBVUkwtZW5jb2RlZCBhcnJheQogICAgICBpbnRvIGFuIEFycmF5IGZvciB5b3Ugb24gdGhlIHNlcnZlci1zaWRlLiBJZiB5b3Ugd2FudCB0byBlbmNvZGUgdGhlCiAgICAgIElEcywgZGlmZmVyZW50bHksIGp1c3Qgb3ZlcnJpZGUgdGhpcyAob25lLWxpbmUpIG1ldGhvZC4KICAgICAgIFRoZSBgZmluZE1hbnlgIG1ldGhvZCBtYWtlcyBhbiBBamF4IChIVFRQIEdFVCkgcmVxdWVzdCB0byBhIFVSTCBjb21wdXRlZCBieSBgYnVpbGRVUkxgLCBhbmQgcmV0dXJucyBhCiAgICAgIHByb21pc2UgZm9yIHRoZSByZXN1bHRpbmcgcGF5bG9hZC4KICAgICAgIEBtZXRob2QgZmluZE1hbnkKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZQogICAgICBAcGFyYW0ge0FycmF5fSBpZHMKICAgICAgQHBhcmFtIHtBcnJheX0gc25hcHNob3RzCiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBmaW5kTWFueTogZnVuY3Rpb24gZmluZE1hbnkoc3RvcmUsIHR5cGUsIGlkcywgc25hcHNob3RzKSB7CiAgICAgIHZhciB1cmwgPSB0aGlzLmJ1aWxkVVJMKHR5cGUubW9kZWxOYW1lLCBpZHMsIHNuYXBzaG90cywgJ2ZpbmRNYW55Jyk7CiAgICAgIHJldHVybiB0aGlzLmFqYXgodXJsLCAnR0VUJywgewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIGlkczogaWRzCiAgICAgICAgfQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIENhbGxlZCBieSB0aGUgc3RvcmUgaW4gb3JkZXIgdG8gZmV0Y2ggYSBKU09OIGFycmF5IGZvcgogICAgICB0aGUgdW5sb2FkZWQgcmVjb3JkcyBpbiBhIGhhcy1tYW55IHJlbGF0aW9uc2hpcCB0aGF0IHdlcmUgb3JpZ2luYWxseQogICAgICBzcGVjaWZpZWQgYXMgYSBVUkwgKGluc2lkZSBvZiBgbGlua3NgKS4KICAgICAgIEZvciBleGFtcGxlLCBpZiB5b3VyIG9yaWdpbmFsIHBheWxvYWQgbG9va3MgbGlrZSB0aGlzOgogICAgICAgYGBganMKICAgICAgewogICAgICAgICJwb3N0IjogewogICAgICAgICAgImlkIjogMSwKICAgICAgICAgICJ0aXRsZSI6ICJSYWlscyBpcyBvbWFrYXNlIiwKICAgICAgICAgICJsaW5rcyI6IHsgImNvbW1lbnRzIjogIi9wb3N0cy8xL2NvbW1lbnRzIiB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgVGhpcyBtZXRob2Qgd2lsbCBiZSBjYWxsZWQgd2l0aCB0aGUgcGFyZW50IHJlY29yZCBhbmQgYC9wb3N0cy8xL2NvbW1lbnRzYC4KICAgICAgIFRoZSBgZmluZEhhc01hbnlgIG1ldGhvZCB3aWxsIG1ha2UgYW4gQWpheCAoSFRUUCBHRVQpIHJlcXVlc3QgdG8gdGhlIG9yaWdpbmFsbHkgc3BlY2lmaWVkIFVSTC4KICAgICAgIFRoZSBmb3JtYXQgb2YgeW91ciBgbGlua3NgIHZhbHVlIHdpbGwgaW5mbHVlbmNlIHRoZSBmaW5hbCByZXF1ZXN0IFVSTCB2aWEgdGhlIGB1cmxQcmVmaXhgIG1ldGhvZDoKICAgICAgICogTGlua3MgYmVnaW5uaW5nIHdpdGggYC8vYCwgYGh0dHA6Ly9gLCBgaHR0cHM6Ly9gLCB3aWxsIGJlIHVzZWQgYXMgaXMsIHdpdGggbm8gZnVydGhlciBtYW5pcHVsYXRpb24uCiAgICAgICAqIExpbmtzIGJlZ2lubmluZyB3aXRoIGEgc2luZ2xlIGAvYCB3aWxsIGhhdmUgdGhlIGN1cnJlbnQgYWRhcHRlcidzIGBob3N0YCB2YWx1ZSBwcmVwZW5kZWQgdG8gaXQuCiAgICAgICAqIExpbmtzIHdpdGggbm8gYmVnaW5uaW5nIGAvYCB3aWxsIGhhdmUgYSBwYXJlbnRVUkwgcHJlcGVuZGVkIHRvIGl0LCB2aWEgdGhlIGN1cnJlbnQgYWRhcHRlcidzIGBidWlsZFVSTGAuCiAgICAgICBAbWV0aG9kIGZpbmRIYXNNYW55CiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEBwYXJhbSB7U3RyaW5nfSB1cmwKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlbGF0aW9uc2hpcCBtZXRhIG9iamVjdCBkZXNjcmliaW5nIHRoZSByZWxhdGlvbnNoaXAKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIGZpbmRIYXNNYW55OiBmdW5jdGlvbiBmaW5kSGFzTWFueShzdG9yZSwgc25hcHNob3QsIHVybCwgcmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBpZCA9IHNuYXBzaG90LmlkOwogICAgICB2YXIgdHlwZSA9IHNuYXBzaG90Lm1vZGVsTmFtZTsKICAgICAgdXJsID0gdGhpcy51cmxQcmVmaXgodXJsLCB0aGlzLmJ1aWxkVVJMKHR5cGUsIGlkLCBzbmFwc2hvdCwgJ2ZpbmRIYXNNYW55JykpOwogICAgICByZXR1cm4gdGhpcy5hamF4KHVybCwgJ0dFVCcpOwogICAgfSwKCiAgICAvKioKICAgICAgQ2FsbGVkIGJ5IHRoZSBzdG9yZSBpbiBvcmRlciB0byBmZXRjaCB0aGUgSlNPTiBmb3IgdGhlIHVubG9hZGVkIHJlY29yZCBpbiBhCiAgICAgIGJlbG9uZ3MtdG8gcmVsYXRpb25zaGlwIHRoYXQgd2FzIG9yaWdpbmFsbHkgc3BlY2lmaWVkIGFzIGEgVVJMIChpbnNpZGUgb2YKICAgICAgYGxpbmtzYCkuCiAgICAgICBGb3IgZXhhbXBsZSwgaWYgeW91ciBvcmlnaW5hbCBwYXlsb2FkIGxvb2tzIGxpa2UgdGhpczoKICAgICAgIGBgYGpzCiAgICAgIHsKICAgICAgICAicGVyc29uIjogewogICAgICAgICAgImlkIjogMSwKICAgICAgICAgICJuYW1lIjogIlRvbSBEYWxlIiwKICAgICAgICAgICJsaW5rcyI6IHsgImdyb3VwIjogIi9wZW9wbGUvMS9ncm91cCIgfQogICAgICAgIH0KICAgICAgfQogICAgICBgYGAKICAgICAgIFRoaXMgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIHdpdGggdGhlIHBhcmVudCByZWNvcmQgYW5kIGAvcGVvcGxlLzEvZ3JvdXBgLgogICAgICAgVGhlIGBmaW5kQmVsb25nc1RvYCBtZXRob2Qgd2lsbCBtYWtlIGFuIEFqYXggKEhUVFAgR0VUKSByZXF1ZXN0IHRvIHRoZSBvcmlnaW5hbGx5IHNwZWNpZmllZCBVUkwuCiAgICAgICBUaGUgZm9ybWF0IG9mIHlvdXIgYGxpbmtzYCB2YWx1ZSB3aWxsIGluZmx1ZW5jZSB0aGUgZmluYWwgcmVxdWVzdCBVUkwgdmlhIHRoZSBgdXJsUHJlZml4YCBtZXRob2Q6CiAgICAgICAqIExpbmtzIGJlZ2lubmluZyB3aXRoIGAvL2AsIGBodHRwOi8vYCwgYGh0dHBzOi8vYCwgd2lsbCBiZSB1c2VkIGFzIGlzLCB3aXRoIG5vIGZ1cnRoZXIgbWFuaXB1bGF0aW9uLgogICAgICAgKiBMaW5rcyBiZWdpbm5pbmcgd2l0aCBhIHNpbmdsZSBgL2Agd2lsbCBoYXZlIHRoZSBjdXJyZW50IGFkYXB0ZXIncyBgaG9zdGAgdmFsdWUgcHJlcGVuZGVkIHRvIGl0LgogICAgICAgKiBMaW5rcyB3aXRoIG5vIGJlZ2lubmluZyBgL2Agd2lsbCBoYXZlIGEgcGFyZW50VVJMIHByZXBlbmRlZCB0byBpdCwgdmlhIHRoZSBjdXJyZW50IGFkYXB0ZXIncyBgYnVpbGRVUkxgLgogICAgICAgQG1ldGhvZCBmaW5kQmVsb25nc1RvCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEBwYXJhbSB7U3RyaW5nfSB1cmwKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlbGF0aW9uc2hpcCBtZXRhIG9iamVjdCBkZXNjcmliaW5nIHRoZSByZWxhdGlvbnNoaXAKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIGZpbmRCZWxvbmdzVG86IGZ1bmN0aW9uIGZpbmRCZWxvbmdzVG8oc3RvcmUsIHNuYXBzaG90LCB1cmwsIHJlbGF0aW9uc2hpcCkgewogICAgICB2YXIgaWQgPSBzbmFwc2hvdC5pZDsKICAgICAgdmFyIHR5cGUgPSBzbmFwc2hvdC5tb2RlbE5hbWU7CiAgICAgIHVybCA9IHRoaXMudXJsUHJlZml4KHVybCwgdGhpcy5idWlsZFVSTCh0eXBlLCBpZCwgc25hcHNob3QsICdmaW5kQmVsb25nc1RvJykpOwogICAgICByZXR1cm4gdGhpcy5hamF4KHVybCwgJ0dFVCcpOwogICAgfSwKCiAgICAvKioKICAgICAgQ2FsbGVkIGJ5IHRoZSBzdG9yZSB3aGVuIGEgbmV3bHkgY3JlYXRlZCByZWNvcmQgaXMKICAgICAgc2F2ZWQgdmlhIHRoZSBgc2F2ZWAgbWV0aG9kIG9uIGEgbW9kZWwgcmVjb3JkIGluc3RhbmNlLgogICAgICAgVGhlIGBjcmVhdGVSZWNvcmRgIG1ldGhvZCBzZXJpYWxpemVzIHRoZSByZWNvcmQgYW5kIG1ha2VzIGFuIEFqYXggKEhUVFAgUE9TVCkgcmVxdWVzdAogICAgICB0byBhIFVSTCBjb21wdXRlZCBieSBgYnVpbGRVUkxgLgogICAgICAgU2VlIGBzZXJpYWxpemVgIGZvciBpbmZvcm1hdGlvbiBvbiBob3cgdG8gY3VzdG9taXplIHRoZSBzZXJpYWxpemVkIGZvcm0KICAgICAgb2YgYSByZWNvcmQuCiAgICAgICBAbWV0aG9kIGNyZWF0ZVJlY29yZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBjcmVhdGVSZWNvcmQ6IGZ1bmN0aW9uIGNyZWF0ZVJlY29yZChzdG9yZSwgdHlwZSwgc25hcHNob3QpIHsKICAgICAgdmFyIHVybCA9IHRoaXMuYnVpbGRVUkwodHlwZS5tb2RlbE5hbWUsIG51bGwsIHNuYXBzaG90LCAnY3JlYXRlUmVjb3JkJyk7CiAgICAgIHZhciBkYXRhID0gKDAsIF9wcml2YXRlLnNlcmlhbGl6ZUludG9IYXNoKShzdG9yZSwgdHlwZSwgc25hcHNob3QpOwogICAgICByZXR1cm4gdGhpcy5hamF4KHVybCwgJ1BPU1QnLCB7CiAgICAgICAgZGF0YTogZGF0YQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIENhbGxlZCBieSB0aGUgc3RvcmUgd2hlbiBhbiBleGlzdGluZyByZWNvcmQgaXMgc2F2ZWQKICAgICAgdmlhIHRoZSBgc2F2ZWAgbWV0aG9kIG9uIGEgbW9kZWwgcmVjb3JkIGluc3RhbmNlLgogICAgICAgVGhlIGB1cGRhdGVSZWNvcmRgIG1ldGhvZCBzZXJpYWxpemVzIHRoZSByZWNvcmQgYW5kIG1ha2VzIGFuIEFqYXggKEhUVFAgUFVUKSByZXF1ZXN0CiAgICAgIHRvIGEgVVJMIGNvbXB1dGVkIGJ5IGBidWlsZFVSTGAuCiAgICAgICBTZWUgYHNlcmlhbGl6ZWAgZm9yIGluZm9ybWF0aW9uIG9uIGhvdyB0byBjdXN0b21pemUgdGhlIHNlcmlhbGl6ZWQgZm9ybQogICAgICBvZiBhIHJlY29yZC4KICAgICAgIEBtZXRob2QgdXBkYXRlUmVjb3JkCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIHVwZGF0ZVJlY29yZDogZnVuY3Rpb24gdXBkYXRlUmVjb3JkKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCkgewogICAgICB2YXIgZGF0YSA9ICgwLCBfcHJpdmF0ZS5zZXJpYWxpemVJbnRvSGFzaCkoc3RvcmUsIHR5cGUsIHNuYXBzaG90LCB7fSk7CiAgICAgIHZhciBpZCA9IHNuYXBzaG90LmlkOwogICAgICB2YXIgdXJsID0gdGhpcy5idWlsZFVSTCh0eXBlLm1vZGVsTmFtZSwgaWQsIHNuYXBzaG90LCAndXBkYXRlUmVjb3JkJyk7CiAgICAgIHJldHVybiB0aGlzLmFqYXgodXJsLCAnUFVUJywgewogICAgICAgIGRhdGE6IGRhdGEKICAgICAgfSk7CiAgICB9LAoKICAgIC8qKgogICAgICBDYWxsZWQgYnkgdGhlIHN0b3JlIHdoZW4gYSByZWNvcmQgaXMgZGVsZXRlZC4KICAgICAgIFRoZSBgZGVsZXRlUmVjb3JkYCBtZXRob2QgIG1ha2VzIGFuIEFqYXggKEhUVFAgREVMRVRFKSByZXF1ZXN0IHRvIGEgVVJMIGNvbXB1dGVkIGJ5IGBidWlsZFVSTGAuCiAgICAgICBAbWV0aG9kIGRlbGV0ZVJlY29yZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBkZWxldGVSZWNvcmQ6IGZ1bmN0aW9uIGRlbGV0ZVJlY29yZChzdG9yZSwgdHlwZSwgc25hcHNob3QpIHsKICAgICAgdmFyIGlkID0gc25hcHNob3QuaWQ7CiAgICAgIHJldHVybiB0aGlzLmFqYXgodGhpcy5idWlsZFVSTCh0eXBlLm1vZGVsTmFtZSwgaWQsIHNuYXBzaG90LCAnZGVsZXRlUmVjb3JkJyksICdERUxFVEUnKTsKICAgIH0sCiAgICBfc3RyaXBJREZyb21VUkw6IGZ1bmN0aW9uIF9zdHJpcElERnJvbVVSTChzdG9yZSwgc25hcHNob3QpIHsKICAgICAgdmFyIHVybCA9IHRoaXMuYnVpbGRVUkwoc25hcHNob3QubW9kZWxOYW1lLCBzbmFwc2hvdC5pZCwgc25hcHNob3QpOwogICAgICB2YXIgZXhwYW5kZWRVUkwgPSB1cmwuc3BsaXQoJy8nKTsgLy8gQ2FzZSB3aGVuIHRoZSB1cmwgaXMgb2YgdGhlIGZvcm1hdCAuLi5zb21ldGhpbmcvOmlkCiAgICAgIC8vIFdlIGFyZSBkZWNvZGVVUklDb21wb25lbnQtaW5nIHRoZSBsYXN0U2VnbWVudCBiZWNhdXNlIGlmIGl0IHJlcHJlc2VudHMKICAgICAgLy8gdGhlIGlkLCBpdCBoYXMgYmVlbiBlbmNvZGVVUklDb21wb25lbnQtaWZpZWQgd2l0aGluIGBidWlsZFVSTGAuIElmIHdlCiAgICAgIC8vIGRvbid0IGRvIHRoaXMsIHRoZW4gcmVjb3JkcyB3aXRoIGlkIGhhdmluZyBzcGVjaWFsIGNoYXJhY3RlcnMgYXJlIG5vdAogICAgICAvLyBjb2FsZXNjZWQgY29ycmVjdGx5IChzZWUgR0ggIzQxOTAgZm9yIHRoZSByZXBvcnRlZCBidWcpCgogICAgICB2YXIgbGFzdFNlZ21lbnQgPSBleHBhbmRlZFVSTFtleHBhbmRlZFVSTC5sZW5ndGggLSAxXTsKICAgICAgdmFyIGlkID0gc25hcHNob3QuaWQ7CgogICAgICBpZiAoZGVjb2RlVVJJQ29tcG9uZW50KGxhc3RTZWdtZW50KSA9PT0gaWQpIHsKICAgICAgICBleHBhbmRlZFVSTFtleHBhbmRlZFVSTC5sZW5ndGggLSAxXSA9ICcnOwogICAgICB9IGVsc2UgaWYgKGVuZHNXaXRoKGxhc3RTZWdtZW50LCAnP2lkPScgKyBpZCkpIHsKICAgICAgICAvL0Nhc2Ugd2hlbiB0aGUgdXJsIGlzIG9mIHRoZSBmb3JtYXQgLi4uc29tZXRoaW5nP2lkPTppZAogICAgICAgIGV4cGFuZGVkVVJMW2V4cGFuZGVkVVJMLmxlbmd0aCAtIDFdID0gbGFzdFNlZ21lbnQuc3Vic3RyaW5nKDAsIGxhc3RTZWdtZW50Lmxlbmd0aCAtIGlkLmxlbmd0aCAtIDEpOwogICAgICB9CgogICAgICByZXR1cm4gZXhwYW5kZWRVUkwuam9pbignLycpOwogICAgfSwKICAgIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNDE3MTQyL3doYXQtaXMtdGhlLW1heGltdW0tbGVuZ3RoLW9mLWEtdXJsLWluLWRpZmZlcmVudC1icm93c2VycwogICAgbWF4VVJMTGVuZ3RoOiAyMDQ4LAoKICAgIC8qKgogICAgICBPcmdhbml6ZSByZWNvcmRzIGludG8gZ3JvdXBzLCBlYWNoIG9mIHdoaWNoIGlzIHRvIGJlIHBhc3NlZCB0byBzZXBhcmF0ZQogICAgICBjYWxscyB0byBgZmluZE1hbnlgLgogICAgICAgVGhpcyBpbXBsZW1lbnRhdGlvbiBncm91cHMgdG9nZXRoZXIgcmVjb3JkcyB0aGF0IGhhdmUgdGhlIHNhbWUgYmFzZSBVUkwgYnV0CiAgICAgIGRpZmZlcmluZyBpZHMuIEZvciBleGFtcGxlIGAvY29tbWVudHMvMWAgYW5kIGAvY29tbWVudHMvMmAgd2lsbCBiZSBncm91cGVkIHRvZ2V0aGVyCiAgICAgIGJlY2F1c2Ugd2Uga25vdyBmaW5kTWFueSBjYW4gY29hbGVzY2UgdGhlbSB0b2dldGhlciBhcyBgL2NvbW1lbnRzP2lkc1tdPTEmaWRzW109MmAKICAgICAgIEl0IGFsc28gc3VwcG9ydHMgdXJscyB3aGVyZSBpZHMgYXJlIHBhc3NlZCBhcyBhIHF1ZXJ5IHBhcmFtLCBzdWNoIGFzIGAvY29tbWVudHM/aWQ9MWAKICAgICAgYnV0IG5vdCB0aG9zZSB3aGVyZSB0aGVyZSBpcyBtb3JlIHRoYW4gMSBxdWVyeSBwYXJhbSBzdWNoIGFzIGAvY29tbWVudHM/aWQ9MiZuYW1lPURhdmlkYAogICAgICBDdXJyZW50bHkgb25seSB0aGUgcXVlcnkgcGFyYW0gb2YgYGlkYCBpcyBzdXBwb3J0ZWQuIElmIHlvdSBuZWVkIHRvIHN1cHBvcnQgb3RoZXJzLCBwbGVhc2UKICAgICAgb3ZlcnJpZGUgdGhpcyBvciB0aGUgYF9zdHJpcElERnJvbVVSTGAgbWV0aG9kLgogICAgICAgSXQgZG9lcyBub3QgZ3JvdXAgcmVjb3JkcyB0aGF0IGhhdmUgZGlmZmVyaW5nIGJhc2UgdXJscywgc3VjaCBhcyBmb3IgZXhhbXBsZTogYC9wb3N0cy8xL2NvbW1lbnRzLzJgCiAgICAgIGFuZCBgL3Bvc3RzLzIvY29tbWVudHMvM2AKICAgICAgIEBtZXRob2QgZ3JvdXBSZWNvcmRzRm9yRmluZE1hbnkKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtBcnJheX0gc25hcHNob3RzCiAgICAgIEByZXR1cm4ge0FycmF5fSAgYW4gYXJyYXkgb2YgYXJyYXlzIG9mIHJlY29yZHMsIGVhY2ggb2Ygd2hpY2ggaXMgdG8gYmUKICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkIHNlcGFyYXRlbHkgYnkgYGZpbmRNYW55YC4KICAgICovCiAgICBncm91cFJlY29yZHNGb3JGaW5kTWFueTogZnVuY3Rpb24gZ3JvdXBSZWNvcmRzRm9yRmluZE1hbnkoc3RvcmUsIHNuYXBzaG90cykgewogICAgICB2YXIgZ3JvdXBzID0gbmV3IE1hcCgpOwogICAgICB2YXIgYWRhcHRlciA9IHRoaXM7CiAgICAgIHZhciBtYXhVUkxMZW5ndGggPSB0aGlzLm1heFVSTExlbmd0aDsKICAgICAgc25hcHNob3RzLmZvckVhY2goZnVuY3Rpb24gKHNuYXBzaG90KSB7CiAgICAgICAgdmFyIGJhc2VVcmwgPSBhZGFwdGVyLl9zdHJpcElERnJvbVVSTChzdG9yZSwgc25hcHNob3QpOwoKICAgICAgICBpZiAoIWdyb3Vwcy5oYXMoYmFzZVVybCkpIHsKICAgICAgICAgIGdyb3Vwcy5zZXQoYmFzZVVybCwgW10pOwogICAgICAgIH0KCiAgICAgICAgZ3JvdXBzLmdldChiYXNlVXJsKS5wdXNoKHNuYXBzaG90KTsKICAgICAgfSk7CgogICAgICBmdW5jdGlvbiBzcGxpdEdyb3VwVG9GaXRJblVybChncm91cCwgbWF4VVJMTGVuZ3RoLCBwYXJhbU5hbWVMZW5ndGgpIHsKICAgICAgICB2YXIgaWRzU2l6ZSA9IDA7CgogICAgICAgIHZhciBiYXNlVXJsID0gYWRhcHRlci5fc3RyaXBJREZyb21VUkwoc3RvcmUsIGdyb3VwWzBdKTsKCiAgICAgICAgdmFyIHNwbGl0R3JvdXBzID0gW1tdXTsKICAgICAgICBncm91cC5mb3JFYWNoKGZ1bmN0aW9uIChzbmFwc2hvdCkgewogICAgICAgICAgdmFyIGFkZGl0aW9uYWxMZW5ndGggPSBlbmNvZGVVUklDb21wb25lbnQoc25hcHNob3QuaWQpLmxlbmd0aCArIHBhcmFtTmFtZUxlbmd0aDsKCiAgICAgICAgICBpZiAoYmFzZVVybC5sZW5ndGggKyBpZHNTaXplICsgYWRkaXRpb25hbExlbmd0aCA+PSBtYXhVUkxMZW5ndGgpIHsKICAgICAgICAgICAgaWRzU2l6ZSA9IDA7CiAgICAgICAgICAgIHNwbGl0R3JvdXBzLnB1c2goW10pOwogICAgICAgICAgfQoKICAgICAgICAgIGlkc1NpemUgKz0gYWRkaXRpb25hbExlbmd0aDsKICAgICAgICAgIHZhciBsYXN0R3JvdXBJbmRleCA9IHNwbGl0R3JvdXBzLmxlbmd0aCAtIDE7CiAgICAgICAgICBzcGxpdEdyb3Vwc1tsYXN0R3JvdXBJbmRleF0ucHVzaChzbmFwc2hvdCk7CiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIHNwbGl0R3JvdXBzOwogICAgICB9CgogICAgICB2YXIgZ3JvdXBzQXJyYXkgPSBbXTsKICAgICAgZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGdyb3VwLCBrZXkpIHsKICAgICAgICB2YXIgcGFyYW1OYW1lTGVuZ3RoID0gJyZpZHMlNUIlNUQ9Jy5sZW5ndGg7CiAgICAgICAgdmFyIHNwbGl0R3JvdXBzID0gc3BsaXRHcm91cFRvRml0SW5VcmwoZ3JvdXAsIG1heFVSTExlbmd0aCwgcGFyYW1OYW1lTGVuZ3RoKTsKICAgICAgICBzcGxpdEdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChzcGxpdEdyb3VwKSB7CiAgICAgICAgICByZXR1cm4gZ3JvdXBzQXJyYXkucHVzaChzcGxpdEdyb3VwKTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICAgIHJldHVybiBncm91cHNBcnJheTsKICAgIH0sCgogICAgLyoqCiAgICAgIFRha2VzIGFuIGFqYXggcmVzcG9uc2UsIGFuZCByZXR1cm5zIHRoZSBqc29uIHBheWxvYWQgb3IgYW4gZXJyb3IuCiAgICAgICBCeSBkZWZhdWx0IHRoaXMgaG9vayBqdXN0IHJldHVybnMgdGhlIGpzb24gcGF5bG9hZCBwYXNzZWQgdG8gaXQuCiAgICAgIFlvdSBtaWdodCB3YW50IHRvIG92ZXJyaWRlIGl0IGluIHR3byBjYXNlczoKICAgICAgIDEuIFlvdXIgQVBJIG1pZ2h0IHJldHVybiB1c2VmdWwgcmVzdWx0cyBpbiB0aGUgcmVzcG9uc2UgaGVhZGVycy4KICAgICAgUmVzcG9uc2UgaGVhZGVycyBhcmUgcGFzc2VkIGluIGFzIHRoZSBzZWNvbmQgYXJndW1lbnQuCiAgICAgICAyLiBZb3VyIEFQSSBtaWdodCByZXR1cm4gZXJyb3JzIGFzIHN1Y2Nlc3NmdWwgcmVzcG9uc2VzIHdpdGggc3RhdHVzIGNvZGUKICAgICAgMjAwIGFuZCBhbiBFcnJvcnMgdGV4dCBvciBvYmplY3QuIFlvdSBjYW4gcmV0dXJuIGEgYEludmFsaWRFcnJvcmAgb3IgYQogICAgICBgQWRhcHRlckVycm9yYCAob3IgYSBzdWIgY2xhc3MpIGZyb20gdGhpcyBob29rIGFuZCBpdCB3aWxsIGF1dG9tYXRpY2FsbHkKICAgICAgcmVqZWN0IHRoZSBwcm9taXNlIGFuZCBwdXQgeW91ciByZWNvcmQgaW50byB0aGUgaW52YWxpZCBvciBlcnJvciBzdGF0ZS4KICAgICAgIFJldHVybmluZyBhIGBJbnZhbGlkRXJyb3JgIGZyb20gdGhpcyBtZXRob2Qgd2lsbCBjYXVzZSB0aGUKICAgICAgcmVjb3JkIHRvIHRyYW5zaXRpb24gaW50byB0aGUgYGludmFsaWRgIHN0YXRlIGFuZCBtYWtlIHRoZQogICAgICBgZXJyb3JzYCBvYmplY3QgYXZhaWxhYmxlIG9uIHRoZSByZWNvcmQuIFdoZW4gcmV0dXJuaW5nIGFuCiAgICAgIGBJbnZhbGlkRXJyb3JgIHRoZSBzdG9yZSB3aWxsIGF0dGVtcHQgdG8gbm9ybWFsaXplIHRoZSBlcnJvciBkYXRhCiAgICAgIHJldHVybmVkIGZyb20gdGhlIHNlcnZlciB1c2luZyB0aGUgc2VyaWFsaXplcidzIGBleHRyYWN0RXJyb3JzYAogICAgICBtZXRob2QuCiAgICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2QgaGFuZGxlUmVzcG9uc2UKICAgICAgQHBhcmFtICB7TnVtYmVyfSBzdGF0dXMKICAgICAgQHBhcmFtICB7T2JqZWN0fSBoZWFkZXJzCiAgICAgIEBwYXJhbSAge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0gIHtPYmplY3R9IHJlcXVlc3REYXRhIC0gdGhlIG9yaWdpbmFsIHJlcXVlc3QgaW5mb3JtYXRpb24KICAgICAgQHJldHVybiB7T2JqZWN0IHwgQWRhcHRlckVycm9yfSByZXNwb25zZQogICAgKi8KICAgIGhhbmRsZVJlc3BvbnNlOiBmdW5jdGlvbiBoYW5kbGVSZXNwb25zZShzdGF0dXMsIGhlYWRlcnMsIHBheWxvYWQsIHJlcXVlc3REYXRhKSB7CiAgICAgIGlmICh0aGlzLmlzU3VjY2VzcyhzdGF0dXMsIGhlYWRlcnMsIHBheWxvYWQpKSB7CiAgICAgICAgcmV0dXJuIHBheWxvYWQ7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5pc0ludmFsaWQoc3RhdHVzLCBoZWFkZXJzLCBwYXlsb2FkKSkgewogICAgICAgIHJldHVybiBuZXcgX2Vycm9yLkludmFsaWRFcnJvcihwYXlsb2FkLmVycm9ycyk7CiAgICAgIH0KCiAgICAgIHZhciBlcnJvcnMgPSB0aGlzLm5vcm1hbGl6ZUVycm9yUmVzcG9uc2Uoc3RhdHVzLCBoZWFkZXJzLCBwYXlsb2FkKTsKICAgICAgdmFyIGRldGFpbGVkTWVzc2FnZSA9IHRoaXMuZ2VuZXJhdGVkRGV0YWlsZWRNZXNzYWdlKHN0YXR1cywgaGVhZGVycywgcGF5bG9hZCwgcmVxdWVzdERhdGEpOwoKICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICBjYXNlIDQwMToKICAgICAgICAgIHJldHVybiBuZXcgX2Vycm9yLlVuYXV0aG9yaXplZEVycm9yKGVycm9ycywgZGV0YWlsZWRNZXNzYWdlKTsKCiAgICAgICAgY2FzZSA0MDM6CiAgICAgICAgICByZXR1cm4gbmV3IF9lcnJvci5Gb3JiaWRkZW5FcnJvcihlcnJvcnMsIGRldGFpbGVkTWVzc2FnZSk7CgogICAgICAgIGNhc2UgNDA0OgogICAgICAgICAgcmV0dXJuIG5ldyBfZXJyb3IuTm90Rm91bmRFcnJvcihlcnJvcnMsIGRldGFpbGVkTWVzc2FnZSk7CgogICAgICAgIGNhc2UgNDA5OgogICAgICAgICAgcmV0dXJuIG5ldyBfZXJyb3IuQ29uZmxpY3RFcnJvcihlcnJvcnMsIGRldGFpbGVkTWVzc2FnZSk7CgogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBpZiAoc3RhdHVzID49IDUwMCkgewogICAgICAgICAgICByZXR1cm4gbmV3IF9lcnJvci5TZXJ2ZXJFcnJvcihlcnJvcnMsIGRldGFpbGVkTWVzc2FnZSk7CiAgICAgICAgICB9CgogICAgICB9CgogICAgICByZXR1cm4gbmV3IF9lcnJvci5kZWZhdWx0KGVycm9ycywgZGV0YWlsZWRNZXNzYWdlKTsKICAgIH0sCgogICAgLyoqCiAgICAgIERlZmF1bHQgYGhhbmRsZVJlc3BvbnNlYCBpbXBsZW1lbnRhdGlvbiB1c2VzIHRoaXMgaG9vayB0byBkZWNpZGUgaWYgdGhlCiAgICAgIHJlc3BvbnNlIGlzIGEgc3VjY2Vzcy4KICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBpc1N1Y2Nlc3MKICAgICAgQHBhcmFtICB7TnVtYmVyfSBzdGF0dXMKICAgICAgQHBhcmFtICB7T2JqZWN0fSBoZWFkZXJzCiAgICAgIEBwYXJhbSAge09iamVjdH0gcGF5bG9hZAogICAgICBAcmV0dXJuIHtCb29sZWFufQogICAgKi8KICAgIGlzU3VjY2VzczogZnVuY3Rpb24gaXNTdWNjZXNzKHN0YXR1cywgaGVhZGVycywgcGF5bG9hZCkgewogICAgICByZXR1cm4gc3RhdHVzID49IDIwMCAmJiBzdGF0dXMgPCAzMDAgfHwgc3RhdHVzID09PSAzMDQ7CiAgICB9LAoKICAgIC8qKgogICAgICBEZWZhdWx0IGBoYW5kbGVSZXNwb25zZWAgaW1wbGVtZW50YXRpb24gdXNlcyB0aGlzIGhvb2sgdG8gZGVjaWRlIGlmIHRoZQogICAgICByZXNwb25zZSBpcyBhbiBpbnZhbGlkIGVycm9yLgogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIGlzSW52YWxpZAogICAgICBAcGFyYW0gIHtOdW1iZXJ9IHN0YXR1cwogICAgICBAcGFyYW0gIHtPYmplY3R9IGhlYWRlcnMKICAgICAgQHBhcmFtICB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICAqLwogICAgaXNJbnZhbGlkOiBmdW5jdGlvbiBpc0ludmFsaWQoc3RhdHVzLCBoZWFkZXJzLCBwYXlsb2FkKSB7CiAgICAgIHJldHVybiBzdGF0dXMgPT09IDQyMjsKICAgIH0sCgogICAgLyoqCiAgICAgIFRha2VzIGEgVVJMLCBhbiBIVFRQIG1ldGhvZCBhbmQgYSBoYXNoIG9mIGRhdGEsIGFuZCBtYWtlcyBhbgogICAgICBIVFRQIHJlcXVlc3QuCiAgICAgICBXaGVuIHRoZSBzZXJ2ZXIgcmVzcG9uZHMgd2l0aCBhIHBheWxvYWQsIEVtYmVyIERhdGEgd2lsbCBjYWxsIGludG8gYGV4dHJhY3RTaW5nbGVgCiAgICAgIG9yIGBleHRyYWN0QXJyYXlgIChkZXBlbmRpbmcgb24gd2hldGhlciB0aGUgb3JpZ2luYWwgcXVlcnkgd2FzIGZvciBvbmUgcmVjb3JkIG9yCiAgICAgIG1hbnkgcmVjb3JkcykuCiAgICAgICBCeSBkZWZhdWx0LCBgYWpheGAgbWV0aG9kIGhhcyB0aGUgZm9sbG93aW5nIGJlaGF2aW9yOgogICAgICAgKiBJdCBzZXRzIHRoZSByZXNwb25zZSBgZGF0YVR5cGVgIHRvIGAianNvbiJgCiAgICAgICogSWYgdGhlIEhUVFAgbWV0aG9kIGlzIG5vdCBgIkdFVCJgLCBpdCBzZXRzIHRoZSBgQ29udGVudC1UeXBlYCB0byBiZQogICAgICAgIGBhcHBsaWNhdGlvbi9qc29uOyBjaGFyc2V0PXV0Zi04YAogICAgICAqIElmIHRoZSBIVFRQIG1ldGhvZCBpcyBub3QgYCJHRVQiYCwgaXQgc3RyaW5naWZpZXMgdGhlIGRhdGEgcGFzc2VkIGluLiBUaGUKICAgICAgICBkYXRhIGlzIHRoZSBzZXJpYWxpemVkIHJlY29yZCBpbiB0aGUgY2FzZSBvZiBhIHNhdmUuCiAgICAgICogUmVnaXN0ZXJzIHN1Y2Nlc3MgYW5kIGZhaWx1cmUgaGFuZGxlcnMuCiAgICAgICBAbWV0aG9kIGFqYXgKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IHVybAogICAgICBAcGFyYW0ge1N0cmluZ30gdHlwZSBUaGUgcmVxdWVzdCB0eXBlIEdFVCwgUE9TVCwgUFVULCBERUxFVEUgZXRjLgogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgYWpheDogZnVuY3Rpb24gYWpheCh1cmwsIHR5cGUsIG9wdGlvbnMpIHsKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzOwogICAgICB2YXIgdXNlRmV0Y2ggPSBFbWJlci5nZXQodGhpcywgJ3VzZUZldGNoJyk7CiAgICAgIHZhciByZXF1ZXN0RGF0YSA9IHsKICAgICAgICB1cmw6IHVybCwKICAgICAgICBtZXRob2Q6IHR5cGUKICAgICAgfTsKICAgICAgdmFyIGhhc2ggPSBhZGFwdGVyLmFqYXhPcHRpb25zKHVybCwgdHlwZSwgb3B0aW9ucyk7CgogICAgICBpZiAodXNlRmV0Y2gpIHsKICAgICAgICByZXR1cm4gdGhpcy5fZmV0Y2hSZXF1ZXN0KGhhc2gpLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlKSB7CiAgICAgICAgICByZXR1cm4gRW1iZXIuUlNWUC5oYXNoKHsKICAgICAgICAgICAgcmVzcG9uc2U6IHJlc3BvbnNlLAogICAgICAgICAgICBwYXlsb2FkOiAoMCwgX3ByaXZhdGUuZGV0ZXJtaW5lQm9keVByb21pc2UpKHJlc3BvbnNlLCByZXF1ZXN0RGF0YSkKICAgICAgICAgIH0pOwogICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKF9yZWYpIHsKICAgICAgICAgIHZhciByZXNwb25zZSA9IF9yZWYucmVzcG9uc2UsCiAgICAgICAgICAgICAgcGF5bG9hZCA9IF9yZWYucGF5bG9hZDsKCiAgICAgICAgICBpZiAocmVzcG9uc2Uub2spIHsKICAgICAgICAgICAgcmV0dXJuIGZldGNoU3VjY2Vzc0hhbmRsZXIoYWRhcHRlciwgcGF5bG9hZCwgcmVzcG9uc2UsIHJlcXVlc3REYXRhKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRocm93IGZldGNoRXJyb3JIYW5kbGVyKGFkYXB0ZXIsIHBheWxvYWQsIHJlc3BvbnNlLCBudWxsLCByZXF1ZXN0RGF0YSk7CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7CiAgICAgICAgaGFzaC5zdWNjZXNzID0gZnVuY3Rpb24gKHBheWxvYWQsIHRleHRTdGF0dXMsIGpxWEhSKSB7CiAgICAgICAgICB2YXIgcmVzcG9uc2UgPSBhamF4U3VjY2Vzc0hhbmRsZXIoYWRhcHRlciwgcGF5bG9hZCwganFYSFIsIHJlcXVlc3REYXRhKTsKICAgICAgICAgIEVtYmVyLnJ1bi5qb2luKG51bGwsIHJlc29sdmUsIHJlc3BvbnNlKTsKICAgICAgICB9OwoKICAgICAgICBoYXNoLmVycm9yID0gZnVuY3Rpb24gKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikgewogICAgICAgICAgdmFyIGVycm9yID0gYWpheEVycm9ySGFuZGxlcihhZGFwdGVyLCBqcVhIUiwgZXJyb3JUaHJvd24sIHJlcXVlc3REYXRhKTsKICAgICAgICAgIEVtYmVyLnJ1bi5qb2luKG51bGwsIHJlamVjdCwgZXJyb3IpOwogICAgICAgIH07CgogICAgICAgIGFkYXB0ZXIuX2FqYXgoaGFzaCk7CiAgICAgIH0sICdEUzogUkVTVEFkYXB0ZXIjYWpheCAnICsgdHlwZSArICcgdG8gJyArIHVybCk7CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIF9hamF4UmVxdWVzdAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBqUXVlcnkgYWpheCBvcHRpb25zIHRvIGJlIHVzZWQgZm9yIHRoZSBhamF4IHJlcXVlc3QKICAgICovCiAgICBfYWpheFJlcXVlc3Q6IGZ1bmN0aW9uIF9hamF4UmVxdWVzdChvcHRpb25zKSB7CiAgICAgIGpRdWVyeS5hamF4KG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBfbmFqYXhSZXF1ZXN0CiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIGpRdWVyeSBhamF4IG9wdGlvbnMgdG8gYmUgdXNlZCBmb3IgdGhlIG5hamF4IHJlcXVlc3QKICAgICovCiAgICBfbmFqYXhSZXF1ZXN0OiBmdW5jdGlvbiBfbmFqYXhSZXF1ZXN0KG9wdGlvbnMpIHsKICAgICAgaWYgKGhhc05hamF4KSB7CiAgICAgICAgbmFqYXgob3B0aW9ucyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCduYWpheCBkb2VzIG5vdCBzZWVtIHRvIGJlIGRlZmluZWQgaW4geW91ciBhcHAuIERpZCB5b3Ugb3ZlcnJpZGUgaXQgdmlhIGBhZGRPck92ZXJyaWRlU2FuZGJveEdsb2JhbHNgIGluIHRoZSBmYXN0Ym9vdCBzZXJ2ZXI/Jyk7CiAgICAgIH0KICAgIH0sCiAgICBfZmV0Y2hSZXF1ZXN0OiBmdW5jdGlvbiBfZmV0Y2hSZXF1ZXN0KG9wdGlvbnMpIHsKICAgICAgdmFyIGZldGNoRnVuY3Rpb24gPSAoMCwgX3ByaXZhdGUuZmV0Y2gpKCk7CgogICAgICBpZiAoZmV0Y2hGdW5jdGlvbikgewogICAgICAgIHJldHVybiBmZXRjaEZ1bmN0aW9uKG9wdGlvbnMudXJsLCBvcHRpb25zKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBmaW5kIHRoZSBgZmV0Y2hgIG1vZHVsZSBvciB0aGUgYGZldGNoYCBnbG9iYWwuIERpZCB5b3UgbWVhbiB0byBpbnN0YWxsIHRoZSBgZW1iZXItZmV0Y2hgIGFkZG9uPycpOwogICAgICB9CiAgICB9LAogICAgX2FqYXg6IGZ1bmN0aW9uIF9hamF4KG9wdGlvbnMpIHsKICAgICAgaWYgKEVtYmVyLmdldCh0aGlzLCAndXNlRmV0Y2gnKSkgewogICAgICAgIHRoaXMuX2ZldGNoUmVxdWVzdChvcHRpb25zKTsKICAgICAgfSBlbHNlIGlmIChFbWJlci5nZXQodGhpcywgJ2Zhc3Rib290LmlzRmFzdEJvb3QnKSkgewogICAgICAgIHRoaXMuX25hamF4UmVxdWVzdChvcHRpb25zKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLl9hamF4UmVxdWVzdChvcHRpb25zKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBhamF4T3B0aW9ucwogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gdXJsCiAgICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlIFRoZSByZXF1ZXN0IHR5cGUgR0VULCBQT1NULCBQVVQsIERFTEVURSBldGMuCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICovCiAgICBhamF4T3B0aW9uczogZnVuY3Rpb24gYWpheE9wdGlvbnModXJsLCBtZXRob2QsIG9wdGlvbnMpIHsKICAgICAgb3B0aW9ucyA9IEVtYmVyLmFzc2lnbih7CiAgICAgICAgdXJsOiB1cmwsCiAgICAgICAgbWV0aG9kOiBtZXRob2QsCiAgICAgICAgdHlwZTogbWV0aG9kCiAgICAgIH0sIG9wdGlvbnMpOwogICAgICB2YXIgaGVhZGVycyA9IEVtYmVyLmdldCh0aGlzLCAnaGVhZGVycycpOwoKICAgICAgaWYgKGhlYWRlcnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgIG9wdGlvbnMuaGVhZGVycyA9IEVtYmVyLmFzc2lnbih7fSwgb3B0aW9ucy5oZWFkZXJzLCBoZWFkZXJzKTsKICAgICAgfSBlbHNlIGlmICghb3B0aW9ucy5oZWFkZXJzKSB7CiAgICAgICAgb3B0aW9ucy5oZWFkZXJzID0ge307CiAgICAgIH0KCiAgICAgIHZhciBjb250ZW50VHlwZSA9IG9wdGlvbnMuY29udGVudFR5cGUgfHwgdGhpcy5fZGVmYXVsdENvbnRlbnRUeXBlOwoKICAgICAgaWYgKEVtYmVyLmdldCh0aGlzLCAndXNlRmV0Y2gnKSkgewogICAgICAgIGlmIChvcHRpb25zLmRhdGEgJiYgb3B0aW9ucy50eXBlICE9PSAnR0VUJykgewogICAgICAgICAgaWYgKCFvcHRpb25zLmhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddICYmICFvcHRpb25zLmhlYWRlcnNbJ2NvbnRlbnQtdHlwZSddKSB7CiAgICAgICAgICAgIG9wdGlvbnMuaGVhZGVyc1snY29udGVudC10eXBlJ10gPSBjb250ZW50VHlwZTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIG9wdGlvbnMgPSBmZXRjaE9wdGlvbnMob3B0aW9ucywgdGhpcyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gR0VUIHJlcXVlc3RzIHdpdGhvdXQgYSBib2R5IHNob3VsZCBub3QgaGF2ZSBhIGNvbnRlbnQtdHlwZSBoZWFkZXIKICAgICAgICAvLyBhbmQgbWF5IGJlIHVuZXhwZWN0ZWQgYnkgYSBzZXJ2ZXIKICAgICAgICBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMudHlwZSAhPT0gJ0dFVCcpIHsKICAgICAgICAgIG9wdGlvbnMgPSBFbWJlci5hc3NpZ24ob3B0aW9ucywgewogICAgICAgICAgICBjb250ZW50VHlwZTogY29udGVudFR5cGUKICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgb3B0aW9ucyA9IF9hamF4T3B0aW9ucyhvcHRpb25zLCB0aGlzKTsKICAgICAgfQoKICAgICAgb3B0aW9ucy51cmwgPSB0aGlzLl9hamF4VVJMKG9wdGlvbnMudXJsKTsKICAgICAgcmV0dXJuIG9wdGlvbnM7CiAgICB9LAogICAgX2FqYXhVUkw6IGZ1bmN0aW9uIF9hamF4VVJMKHVybCkgewogICAgICBpZiAoRW1iZXIuZ2V0KHRoaXMsICdmYXN0Ym9vdC5pc0Zhc3RCb290JykpIHsKICAgICAgICB2YXIgaHR0cFJlZ2V4ID0gL15odHRwcz86XC9cLy87CiAgICAgICAgdmFyIHByb3RvY29sUmVsYXRpdmVSZWdleCA9IC9eXC9cLy87CiAgICAgICAgdmFyIHByb3RvY29sID0gRW1iZXIuZ2V0KHRoaXMsICdmYXN0Ym9vdC5yZXF1ZXN0LnByb3RvY29sJyk7CiAgICAgICAgdmFyIGhvc3QgPSBFbWJlci5nZXQodGhpcywgJ2Zhc3Rib290LnJlcXVlc3QuaG9zdCcpOwoKICAgICAgICBpZiAocHJvdG9jb2xSZWxhdGl2ZVJlZ2V4LnRlc3QodXJsKSkgewogICAgICAgICAgcmV0dXJuICIiICsgcHJvdG9jb2wgKyB1cmw7CiAgICAgICAgfSBlbHNlIGlmICghaHR0cFJlZ2V4LnRlc3QodXJsKSkgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcmV0dXJuIHByb3RvY29sICsgIi8vIiArIGhvc3QgKyB1cmw7CiAgICAgICAgICB9IGNhdGNoIChmYkVycm9yKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWW91IGFyZSB1c2luZyBFbWJlciBEYXRhIHdpdGggbm8gaG9zdCBkZWZpbmVkIGluIHlvdXIgYWRhcHRlci4gVGhpcyB3aWxsIGF0dGVtcHQgdG8gdXNlIHRoZSBob3N0IG9mIHRoZSBGYXN0Qm9vdCByZXF1ZXN0LCB3aGljaCBpcyBub3QgY29uZmlndXJlZCBmb3IgdGhlIGN1cnJlbnQgaG9zdCBvZiB0aGlzIHJlcXVlc3QuIFBsZWFzZSBzZXQgdGhlIGhvc3RXaGl0ZWxpc3QgcHJvcGVydHkgZm9yIGluIHlvdXIgZW52aXJvbm1lbnQuanMuIEZhc3RCb290IEVycm9yOiAnICsgZmJFcnJvci5tZXNzYWdlKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiB1cmw7CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIHBhcnNlRXJyb3JSZXNwb25zZQogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gcmVzcG9uc2VUZXh0CiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICovCiAgICBwYXJzZUVycm9yUmVzcG9uc2U6IGZ1bmN0aW9uIHBhcnNlRXJyb3JSZXNwb25zZShyZXNwb25zZVRleHQpIHsKICAgICAgdmFyIGpzb24gPSByZXNwb25zZVRleHQ7CgogICAgICB0cnkgewogICAgICAgIGpzb24gPSBKU09OLnBhcnNlKHJlc3BvbnNlVGV4dCk7CiAgICAgIH0gY2F0Y2ggKGUpIHsvLyBpZ25vcmVkCiAgICAgIH0KCiAgICAgIHJldHVybiBqc29uOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBub3JtYWxpemVFcnJvclJlc3BvbnNlCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSAge051bWJlcn0gc3RhdHVzCiAgICAgIEBwYXJhbSAge09iamVjdH0gaGVhZGVycwogICAgICBAcGFyYW0gIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHJldHVybiB7QXJyYXl9IGVycm9ycyBwYXlsb2FkCiAgICAqLwogICAgbm9ybWFsaXplRXJyb3JSZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplRXJyb3JSZXNwb25zZShzdGF0dXMsIGhlYWRlcnMsIHBheWxvYWQpIHsKICAgICAgaWYgKHBheWxvYWQgJiYgdHlwZW9mIHBheWxvYWQgPT09ICdvYmplY3QnICYmIHBheWxvYWQuZXJyb3JzKSB7CiAgICAgICAgcmV0dXJuIHBheWxvYWQuZXJyb3JzOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBbewogICAgICAgICAgc3RhdHVzOiAiIiArIHN0YXR1cywKICAgICAgICAgIHRpdGxlOiAnVGhlIGJhY2tlbmQgcmVzcG9uZGVkIHdpdGggYW4gZXJyb3InLAogICAgICAgICAgZGV0YWlsOiAiIiArIHBheWxvYWQKICAgICAgICB9XTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgR2VuZXJhdGVzIGEgZGV0YWlsZWQgKCJmcmllbmRseSIpIGVycm9yIG1lc3NhZ2UsIHdpdGggcGxlbnR5CiAgICAgIG9mIGluZm9ybWF0aW9uIGZvciBkZWJ1Z2dpbmcgKGdvb2QgbHVjayEpCiAgICAgICBAbWV0aG9kIGdlbmVyYXRlZERldGFpbGVkTWVzc2FnZQogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0gIHtOdW1iZXJ9IHN0YXR1cwogICAgICBAcGFyYW0gIHtPYmplY3R9IGhlYWRlcnMKICAgICAgQHBhcmFtICB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSAge09iamVjdH0gcmVxdWVzdERhdGEKICAgICAgQHJldHVybiB7U3RyaW5nfSBkZXRhaWxlZCBlcnJvciBtZXNzYWdlCiAgICAqLwogICAgZ2VuZXJhdGVkRGV0YWlsZWRNZXNzYWdlOiBmdW5jdGlvbiBnZW5lcmF0ZWREZXRhaWxlZE1lc3NhZ2Uoc3RhdHVzLCBoZWFkZXJzLCBwYXlsb2FkLCByZXF1ZXN0RGF0YSkgewogICAgICB2YXIgc2hvcnRlbmVkUGF5bG9hZDsKICAgICAgdmFyIHBheWxvYWRDb250ZW50VHlwZSA9IGhlYWRlcnNbJ2NvbnRlbnQtdHlwZSddIHx8ICdFbXB0eSBDb250ZW50LVR5cGUnOwoKICAgICAgaWYgKHBheWxvYWRDb250ZW50VHlwZSA9PT0gJ3RleHQvaHRtbCcgJiYgcGF5bG9hZC5sZW5ndGggPiAyNTApIHsKICAgICAgICBzaG9ydGVuZWRQYXlsb2FkID0gJ1tPbWl0dGVkIExlbmd0aHkgSFRNTF0nOwogICAgICB9IGVsc2UgewogICAgICAgIHNob3J0ZW5lZFBheWxvYWQgPSBwYXlsb2FkOwogICAgICB9CgogICAgICB2YXIgcmVxdWVzdERlc2NyaXB0aW9uID0gcmVxdWVzdERhdGEubWV0aG9kICsgJyAnICsgcmVxdWVzdERhdGEudXJsOwogICAgICB2YXIgcGF5bG9hZERlc2NyaXB0aW9uID0gJ1BheWxvYWQgKCcgKyBwYXlsb2FkQ29udGVudFR5cGUgKyAnKSc7CiAgICAgIHJldHVybiBbJ0VtYmVyIERhdGEgUmVxdWVzdCAnICsgcmVxdWVzdERlc2NyaXB0aW9uICsgJyByZXR1cm5lZCBhICcgKyBzdGF0dXMsIHBheWxvYWREZXNjcmlwdGlvbiwgc2hvcnRlbmVkUGF5bG9hZF0uam9pbignXG4nKTsKICAgIH0sCiAgICAvLyBAc2luY2UgMi41LjAKICAgIGJ1aWxkUXVlcnk6IGZ1bmN0aW9uIGJ1aWxkUXVlcnkoc25hcHNob3QpIHsKICAgICAgdmFyIHF1ZXJ5ID0ge307CgogICAgICBpZiAoc25hcHNob3QpIHsKICAgICAgICB2YXIgaW5jbHVkZSA9IHNuYXBzaG90LmluY2x1ZGU7CgogICAgICAgIGlmIChpbmNsdWRlKSB7CiAgICAgICAgICBxdWVyeS5pbmNsdWRlID0gaW5jbHVkZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBxdWVyeTsKICAgIH0KICB9KTsKCiAgZnVuY3Rpb24gYWpheFN1Y2Nlc3MoYWRhcHRlciwgcGF5bG9hZCwgcmVxdWVzdERhdGEsIHJlc3BvbnNlRGF0YSkgewogICAgdmFyIHJlc3BvbnNlOwoKICAgIHRyeSB7CiAgICAgIHJlc3BvbnNlID0gYWRhcHRlci5oYW5kbGVSZXNwb25zZShyZXNwb25zZURhdGEuc3RhdHVzLCByZXNwb25zZURhdGEuaGVhZGVycywgcGF5bG9hZCwgcmVxdWVzdERhdGEpOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTsKICAgIH0KCiAgICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2UuaXNBZGFwdGVyRXJyb3IpIHsKICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHJlc3BvbnNlKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiByZXNwb25zZTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGFqYXhFcnJvcihhZGFwdGVyLCBwYXlsb2FkLCByZXF1ZXN0RGF0YSwgcmVzcG9uc2VEYXRhKSB7CiAgICB2YXIgZXJyb3I7CgogICAgaWYgKHJlc3BvbnNlRGF0YS5lcnJvclRocm93biBpbnN0YW5jZW9mIEVycm9yKSB7CiAgICAgIGVycm9yID0gcmVzcG9uc2VEYXRhLmVycm9yVGhyb3duOwogICAgfSBlbHNlIGlmIChyZXNwb25zZURhdGEudGV4dFN0YXR1cyA9PT0gJ3RpbWVvdXQnKSB7CiAgICAgIGVycm9yID0gbmV3IF9lcnJvci5UaW1lb3V0RXJyb3IoKTsKICAgIH0gZWxzZSBpZiAocmVzcG9uc2VEYXRhLnRleHRTdGF0dXMgPT09ICdhYm9ydCcgfHwgcmVzcG9uc2VEYXRhLnN0YXR1cyA9PT0gMCkgewogICAgICBlcnJvciA9IGhhbmRsZUFib3J0KHJlcXVlc3REYXRhLCByZXNwb25zZURhdGEpOwogICAgfSBlbHNlIHsKICAgICAgdHJ5IHsKICAgICAgICBlcnJvciA9IGFkYXB0ZXIuaGFuZGxlUmVzcG9uc2UocmVzcG9uc2VEYXRhLnN0YXR1cywgcmVzcG9uc2VEYXRhLmhlYWRlcnMsIHBheWxvYWQgfHwgcmVzcG9uc2VEYXRhLmVycm9yVGhyb3duLCByZXF1ZXN0RGF0YSk7CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBlcnJvciA9IGU7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gZXJyb3I7CiAgfSAvLyBBZGFwdGVyIGFib3J0IGVycm9yIHRvIGluY2x1ZGUgYW55IHJlbGV2ZW50IGluZm8sIGUuZy4gcmVxdWVzdC9yZXNwb25zZToKCgogIGZ1bmN0aW9uIGhhbmRsZUFib3J0KHJlcXVlc3REYXRhLCByZXNwb25zZURhdGEpIHsKICAgIHZhciBtZXRob2QgPSByZXF1ZXN0RGF0YS5tZXRob2QsCiAgICAgICAgdXJsID0gcmVxdWVzdERhdGEudXJsLAogICAgICAgIGVycm9yVGhyb3duID0gcmVxdWVzdERhdGEuZXJyb3JUaHJvd247CiAgICB2YXIgc3RhdHVzID0gcmVzcG9uc2VEYXRhLnN0YXR1czsKICAgIHZhciBtc2cgPSAiUmVxdWVzdCBmYWlsZWQ6ICIgKyBtZXRob2QgKyAiICIgKyB1cmwgKyAiICIgKyAoZXJyb3JUaHJvd24gfHwgJycpOwogICAgdmFyIGVycm9ycyA9IFt7CiAgICAgIHRpdGxlOiAnQWRhcHRlciBFcnJvcicsCiAgICAgIGRldGFpbDogbXNnLnRyaW0oKSwKICAgICAgc3RhdHVzOiBzdGF0dXMKICAgIH1dOwogICAgcmV0dXJuIG5ldyBfZXJyb3IuQWJvcnRFcnJvcihlcnJvcnMpOwogIH0gLy9Gcm9tIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjgwNjM0L2VuZHN3aXRoLWluLWphdmFzY3JpcHQKCgogIGZ1bmN0aW9uIGVuZHNXaXRoKHN0cmluZywgc3VmZml4KSB7CiAgICBpZiAodHlwZW9mIFN0cmluZy5wcm90b3R5cGUuZW5kc1dpdGggIT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuIHN0cmluZy5pbmRleE9mKHN1ZmZpeCwgc3RyaW5nLmxlbmd0aCAtIHN1ZmZpeC5sZW5ndGgpICE9PSAtMTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBzdHJpbmcuZW5kc1dpdGgoc3VmZml4KTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGZldGNoU3VjY2Vzc0hhbmRsZXIoYWRhcHRlciwgcGF5bG9hZCwgcmVzcG9uc2UsIHJlcXVlc3REYXRhKSB7CiAgICB2YXIgcmVzcG9uc2VEYXRhID0gZmV0Y2hSZXNwb25zZURhdGEocmVzcG9uc2UpOwogICAgcmV0dXJuIGFqYXhTdWNjZXNzKGFkYXB0ZXIsIHBheWxvYWQsIHJlcXVlc3REYXRhLCByZXNwb25zZURhdGEpOwogIH0KCiAgZnVuY3Rpb24gZmV0Y2hFcnJvckhhbmRsZXIoYWRhcHRlciwgcGF5bG9hZCwgcmVzcG9uc2UsIGVycm9yVGhyb3duLCByZXF1ZXN0RGF0YSkgewogICAgdmFyIHJlc3BvbnNlRGF0YSA9IGZldGNoUmVzcG9uc2VEYXRhKHJlc3BvbnNlKTsKICAgIHJlc3BvbnNlRGF0YS5lcnJvclRocm93biA9IGVycm9yVGhyb3duOwogICAgcmV0dXJuIGFqYXhFcnJvcihhZGFwdGVyLCBwYXlsb2FkLCByZXF1ZXN0RGF0YSwgcmVzcG9uc2VEYXRhKTsKICB9CgogIGZ1bmN0aW9uIGFqYXhTdWNjZXNzSGFuZGxlcihhZGFwdGVyLCBwYXlsb2FkLCBqcVhIUiwgcmVxdWVzdERhdGEpIHsKICAgIHZhciByZXNwb25zZURhdGEgPSBhamF4UmVzcG9uc2VEYXRhKGpxWEhSKTsKICAgIHJldHVybiBhamF4U3VjY2VzcyhhZGFwdGVyLCBwYXlsb2FkLCByZXF1ZXN0RGF0YSwgcmVzcG9uc2VEYXRhKTsKICB9CgogIGZ1bmN0aW9uIGFqYXhFcnJvckhhbmRsZXIoYWRhcHRlciwganFYSFIsIGVycm9yVGhyb3duLCByZXF1ZXN0RGF0YSkgewogICAgdmFyIHJlc3BvbnNlRGF0YSA9IGFqYXhSZXNwb25zZURhdGEoanFYSFIpOwogICAgcmVzcG9uc2VEYXRhLmVycm9yVGhyb3duID0gZXJyb3JUaHJvd247CiAgICB2YXIgcGF5bG9hZCA9IGFkYXB0ZXIucGFyc2VFcnJvclJlc3BvbnNlKGpxWEhSLnJlc3BvbnNlVGV4dCk7CgogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgKSB7CiAgICAgIHZhciBtZXNzYWdlID0gIlRoZSBzZXJ2ZXIgcmV0dXJuZWQgYW4gZW1wdHkgc3RyaW5nIGZvciAiICsgcmVxdWVzdERhdGEubWV0aG9kICsgIiAiICsgcmVxdWVzdERhdGEudXJsICsgIiwgd2hpY2ggY2Fubm90IGJlIHBhcnNlZCBpbnRvIGEgdmFsaWQgSlNPTi4gUmV0dXJuIGVpdGhlciBudWxsIG9yIHt9LiI7CiAgICAgIHZhciB2YWxpZEpTT05TdHJpbmcgPSAhKHJlc3BvbnNlRGF0YS50ZXh0U3RhdHVzID09PSAncGFyc2VyZXJyb3InICYmIHBheWxvYWQgPT09ICcnKTsKICAgICAgKGZhbHNlICYmIEVtYmVyLndhcm4obWVzc2FnZSwgdmFsaWRKU09OU3RyaW5nLCB7CiAgICAgICAgaWQ6ICdkcy5hZGFwdGVyLnJldHVybmVkLWVtcHR5LXN0cmluZy1hcy1KU09OJwogICAgICB9KSk7CiAgICB9CgogICAgcmV0dXJuIGFqYXhFcnJvcihhZGFwdGVyLCBwYXlsb2FkLCByZXF1ZXN0RGF0YSwgcmVzcG9uc2VEYXRhKTsKICB9CgogIGZ1bmN0aW9uIGZldGNoUmVzcG9uc2VEYXRhKHJlc3BvbnNlKSB7CiAgICByZXR1cm4gewogICAgICBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cywKICAgICAgdGV4dFN0YXR1czogcmVzcG9uc2UudGV4dFN0YXR1cywKICAgICAgaGVhZGVyczogaGVhZGVyc1RvT2JqZWN0KHJlc3BvbnNlLmhlYWRlcnMpCiAgICB9OwogIH0KCiAgZnVuY3Rpb24gYWpheFJlc3BvbnNlRGF0YShqcVhIUikgewogICAgcmV0dXJuIHsKICAgICAgc3RhdHVzOiBqcVhIUi5zdGF0dXMsCiAgICAgIHRleHRTdGF0dXM6IGpxWEhSLnN0YXR1c1RleHQsCiAgICAgIGhlYWRlcnM6ICgwLCBfcHJpdmF0ZS5wYXJzZVJlc3BvbnNlSGVhZGVycykoanFYSFIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkpCiAgICB9OwogIH0KCiAgZnVuY3Rpb24gaGVhZGVyc1RvT2JqZWN0KGhlYWRlcnMpIHsKICAgIHZhciBoZWFkZXJzT2JqZWN0ID0ge307CgogICAgaWYgKGhlYWRlcnMpIHsKICAgICAgaGVhZGVycy5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7CiAgICAgICAgcmV0dXJuIGhlYWRlcnNPYmplY3Rba2V5XSA9IHZhbHVlOwogICAgICB9KTsKICAgIH0KCiAgICByZXR1cm4gaGVhZGVyc09iamVjdDsKICB9CiAgLyoqCiAgICogSGVscGVyIGZ1bmN0aW9uIHRoYXQgdHJhbnNsYXRlcyB0aGUgb3B0aW9ucyBwYXNzZWQgdG8gYGpRdWVyeS5hamF4YCBpbnRvIGEgZm9ybWF0IHRoYXQgYGZldGNoYCBleHBlY3RzLgogICAqIEBwYXJhbSB7T2JqZWN0fSBfb3B0aW9ucwogICAqIEBwYXJhbSB7QWRhcHRlcn0gYWRhcHRlcgogICAqIEByZXR1cm5zIHtPYmplY3R9CiAgICovCgoKICBmdW5jdGlvbiBmZXRjaE9wdGlvbnMob3B0aW9ucywgYWRhcHRlcikgewogICAgb3B0aW9ucy5jcmVkZW50aWFscyA9ICdzYW1lLW9yaWdpbic7CgogICAgaWYgKG9wdGlvbnMuZGF0YSkgewogICAgICAvLyBHRVQgYW5kIEhFQUQgcmVxdWVzdHMgY2FuJ3QgaGF2ZSBhIGBib2R5YAogICAgICBpZiAob3B0aW9ucy5tZXRob2QgPT09ICdHRVQnIHx8IG9wdGlvbnMubWV0aG9kID09PSAnSEVBRCcpIHsKICAgICAgICAvLyBJZiBubyBvcHRpb25zIGFyZSBwYXNzZWQsIEVtYmVyIERhdGEgc2V0cyBgZGF0YWAgdG8gYW4gZW1wdHkgb2JqZWN0LCB3aGljaCB3ZSB0ZXN0IGZvci4KICAgICAgICBpZiAoT2JqZWN0LmtleXMob3B0aW9ucy5kYXRhKS5sZW5ndGgpIHsKICAgICAgICAgIC8vIFRlc3QgaWYgdGhlcmUgYXJlIGFscmVhZHkgcXVlcnkgcGFyYW1zIGluIHRoZSB1cmwgKG1pbWljcyBqUXVleS5hamF4KS4KICAgICAgICAgIHZhciBxdWVyeVBhcmFtRGVsaW1pdGVyID0gb3B0aW9ucy51cmwuaW5kZXhPZignPycpID4gLTEgPyAnJicgOiAnPyc7CiAgICAgICAgICBvcHRpb25zLnVybCArPSAiIiArIHF1ZXJ5UGFyYW1EZWxpbWl0ZXIgKyAoMCwgX3ByaXZhdGUuc2VyaWFsaXplUXVlcnlQYXJhbXMpKG9wdGlvbnMuZGF0YSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIC8vIE5PVEU6IGEgcmVxdWVzdCdzIGJvZHkgY2Fubm90IGJlIGFuIG9iamVjdCwgc28gd2Ugc3RyaW5naWZ5IGl0IGlmIGl0IGlzLgogICAgICAgIC8vIEpTT04uc3RyaW5naWZ5IHJlbW92ZXMga2V5cyB3aXRoIHZhbHVlcyBvZiBgdW5kZWZpbmVkYCAobWltaWNzIGpRdWVyeS5hamF4KS4KICAgICAgICAvLyBJZiB0aGUgZGF0YSBpcyBub3QgYSBQT0pPIChpdCdzIGEgU3RyaW5nLCBGb3JtRGF0YSwgZXRjKSwgd2UganVzdCBzZXQgaXQuCiAgICAgICAgLy8gSWYgdGhlIGRhdGEgaXMgYSBzdHJpbmcsIHdlIGFzc3VtZSBpdCdzIGEgc3RyaW5naWZpZWQgb2JqZWN0LgoKICAgICAgICAvKiBXZSBjaGVjayBmb3IgT2JqZWN0cyB0aGlzIHdheSBiZWNhdXNlIHdlIHdhbnQgdGhlIGxvZ2ljIGluc2lkZSB0aGUgY29uc2VxdWVudCB0byBydW4KICAgICAgICAgKiBpZiBgb3B0aW9ucy5kYXRhYCBpcyBhIFBPSk8sIG5vdCBpZiBpdCBpcyBhIGRhdGEgc3RydWN0dXJlIHdob3NlIGB0eXBlb2ZgIHJldHVybnMgIm9iamVjdCIKICAgICAgICAgKiB3aGVuIGl0J3Mgbm90IChBcnJheSwgRm9ybURhdGEsIGV0YykuIFRoZSByZWFzb24gd2UgZG9uJ3QgdXNlIGBvcHRpb25zLmRhdGEuY29uc3RydWN0b3JgCiAgICAgICAgICogdG8gY2hlY2sgaXMgaW4gY2FzZSBgZGF0YWAgaXMgYW4gb2JqZWN0IHdpdGggbm8gcHJvdG90eXBlIChlLmcuIGNyZWF0ZWQgd2l0aCBudWxsKS4KICAgICAgICAgKi8KICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9wdGlvbnMuZGF0YSkgPT09ICdbb2JqZWN0IE9iamVjdF0nKSB7CiAgICAgICAgICBvcHRpb25zLmJvZHkgPSBKU09OLnN0cmluZ2lmeShvcHRpb25zLmRhdGEpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcHRpb25zLmJvZHkgPSBvcHRpb25zLmRhdGE7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgcmV0dXJuIG9wdGlvbnM7CiAgfQoKICBmdW5jdGlvbiBfYWpheE9wdGlvbnMob3B0aW9ucywgYWRhcHRlcikgewogICAgb3B0aW9ucy5kYXRhVHlwZSA9ICdqc29uJzsKICAgIG9wdGlvbnMuY29udGV4dCA9IGFkYXB0ZXI7CgogICAgaWYgKG9wdGlvbnMuZGF0YSAmJiBvcHRpb25zLnR5cGUgIT09ICdHRVQnKSB7CiAgICAgIG9wdGlvbnMuZGF0YSA9IEpTT04uc3RyaW5naWZ5KG9wdGlvbnMuZGF0YSk7CiAgICB9CgogICAgb3B0aW9ucy5iZWZvcmVTZW5kID0gZnVuY3Rpb24gKHhocikgewogICAgICBPYmplY3Qua2V5cyhvcHRpb25zLmhlYWRlcnMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgIHJldHVybiB4aHIuc2V0UmVxdWVzdEhlYWRlcihrZXksIG9wdGlvbnMuaGVhZGVyc1trZXldKTsKICAgICAgfSk7CiAgICB9OwoKICAgIHJldHVybiBvcHRpb25zOwogIH0KCiAgdmFyIF9kZWZhdWx0ID0gUkVTVEFkYXB0ZXI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKO2RlZmluZSgiQGVtYmVyLWRhdGEvY2FuYXJ5LWZlYXR1cmVzL2RlZmF1bHQtZmVhdHVyZXMiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvY2FuYXJ5LWZlYXR1cmVzCiAgKi8KCiAgLyoKICAgIFRoaXMgbGlzdCBvZiBmZWF0dXJlcyBpcyB1c2VkIGJvdGggYXQgYnVpbGQgdGltZSAoYnkgYEBlbWJlci1kYXRhLy1idWlsZC1pbmZyYWApCiAgICBhbmQgYXQgcnVudGltZSAoYnkgYEBlbWJlci1kYXRhL2NhbmFyeS1mZWF0dXJlc2ApLgogIAogICAgVGhlIHZhbGlkIHZhbHVlcyBhcmU6CiAgCiAgICAtIHRydWUgLSBUaGUgZmVhdHVyZSBpcyBlbmFibGVkIGF0IGFsbCB0aW1lcywgYW5kIGNhbm5vdCBiZSBkaXNhYmxlZC4KICAgIC0gZmFsc2UgLSBUaGUgZmVhdHVyZSBpcyBkaXNhYmxlZCBhdCBhbGwgdGltZXMsIGFuZCBjYW5ub3QgYmUgZW5hYmxlZC4KICAgIC0gbnVsbCAtIFRoZSBmZWF0dXJlIGlzIGRpc2FibGVkIGJ5IGRlZmF1bHQsIGJ1dCBjYW4gYmUgZW5hYmxlZCBhdCBydW50aW1lIHZpYSBgRW1iZXJEYXRhRU5WYC4KICAqLwogIHZhciBfZGVmYXVsdCA9IHsKICAgIFNBTVBMRV9GRUFUVVJFX0ZMQUc6IG51bGwsCiAgICBSRUNPUkRfREFUQV9FUlJPUlM6IG51bGwsCiAgICBSRUNPUkRfREFUQV9TVEFURTogbnVsbCwKICAgIElERU5USUZJRVJTOiB0cnVlLAogICAgUkVRVUVTVF9TRVJWSUNFOiBudWxsLAogICAgQ1VTVE9NX01PREVMX0NMQVNTOiBudWxsCiAgfTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwo7ZGVmaW5lKCJAZW1iZXItZGF0YS9jYW5hcnktZmVhdHVyZXMvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvY2FuYXJ5LWZlYXR1cmVzL2RlZmF1bHQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVmYXVsdEZlYXR1cmVzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5DVVNUT01fTU9ERUxfQ0xBU1MgPSBfZXhwb3J0cy5JREVOVElGSUVSUyA9IF9leHBvcnRzLlJFUVVFU1RfU0VSVklDRSA9IF9leHBvcnRzLlJFQ09SRF9EQVRBX1NUQVRFID0gX2V4cG9ydHMuUkVDT1JEX0RBVEFfRVJST1JTID0gX2V4cG9ydHMuU0FNUExFX0ZFQVRVUkVfRkxBRyA9IF9leHBvcnRzLkZFQVRVUkVTID0gdm9pZCAwOwoKICBmdW5jdGlvbiBfdHlwZW9mKG9iaikgeyBpZiAodHlwZW9mIFN5bWJvbCA9PT0gImZ1bmN0aW9uIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSAic3ltYm9sIikgeyBfdHlwZW9mID0gZnVuY3Rpb24gX3R5cGVvZihvYmopIHsgcmV0dXJuIHR5cGVvZiBvYmo7IH07IH0gZWxzZSB7IF90eXBlb2YgPSBmdW5jdGlvbiBfdHlwZW9mKG9iaikgeyByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09ICJmdW5jdGlvbiIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gInN5bWJvbCIgOiB0eXBlb2Ygb2JqOyB9OyB9IHJldHVybiBfdHlwZW9mKG9iaik7IH0KCiAgdmFyIEVOViA9ICh0eXBlb2YgRW1iZXJEYXRhRU5WID09PSAidW5kZWZpbmVkIiA/ICJ1bmRlZmluZWQiIDogX3R5cGVvZihFbWJlckRhdGFFTlYpKSA9PT0gJ29iamVjdCcgJiYgRW1iZXJEYXRhRU5WICE9PSBudWxsID8gRW1iZXJEYXRhRU5WIDoge307CgogIGZ1bmN0aW9uIGZlYXR1cmVWYWx1ZSh2YWx1ZSkgewogICAgaWYgKEVOVi5FTkFCTEVfT1BUSU9OQUxfRkVBVFVSRVMgJiYgdmFsdWUgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgcmV0dXJuIHZhbHVlOwogIH0KCiAgdmFyIEZFQVRVUkVTID0gRW1iZXIuYXNzaWduKHt9LCBfZGVmYXVsdEZlYXR1cmVzLmRlZmF1bHQsIEVOVi5GRUFUVVJFUyk7CiAgX2V4cG9ydHMuRkVBVFVSRVMgPSBGRUFUVVJFUzsKICB2YXIgU0FNUExFX0ZFQVRVUkVfRkxBRyA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5TQU1QTEVfRkVBVFVSRV9GTEFHKTsKICBfZXhwb3J0cy5TQU1QTEVfRkVBVFVSRV9GTEFHID0gU0FNUExFX0ZFQVRVUkVfRkxBRzsKICB2YXIgUkVDT1JEX0RBVEFfRVJST1JTID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLlJFQ09SRF9EQVRBX0VSUk9SUyk7CiAgX2V4cG9ydHMuUkVDT1JEX0RBVEFfRVJST1JTID0gUkVDT1JEX0RBVEFfRVJST1JTOwogIHZhciBSRUNPUkRfREFUQV9TVEFURSA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5SRUNPUkRfREFUQV9TVEFURSk7CiAgX2V4cG9ydHMuUkVDT1JEX0RBVEFfU1RBVEUgPSBSRUNPUkRfREFUQV9TVEFURTsKICB2YXIgUkVRVUVTVF9TRVJWSUNFID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLlJFUVVFU1RfU0VSVklDRSk7CiAgX2V4cG9ydHMuUkVRVUVTVF9TRVJWSUNFID0gUkVRVUVTVF9TRVJWSUNFOwogIHZhciBJREVOVElGSUVSUyA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5JREVOVElGSUVSUyk7CiAgX2V4cG9ydHMuSURFTlRJRklFUlMgPSBJREVOVElGSUVSUzsKICB2YXIgQ1VTVE9NX01PREVMX0NMQVNTID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLkNVU1RPTV9NT0RFTF9DTEFTUyk7CiAgX2V4cG9ydHMuQ1VTVE9NX01PREVMX0NMQVNTID0gQ1VTVE9NX01PREVMX0NMQVNTOwp9KTsKO2RlZmluZSgiQGVtYmVyLWRhdGEvZGVidWcvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvZGVidWcvc2V0dXAiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfc2V0dXApIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAgSW1wbGVtZW50cyBgQGVtYmVyL2RlYnVnL2RhdGEtYWRhcHRlcmAgd2l0aCBmb3IgRW1iZXJEYXRhCiAgICBpbnRlZ3JhdGlvbiB3aXRoIHRoZSBlbWJlci1pbnNwZWN0b3IuCiAgCiAgICBAY2xhc3MgSW5zcGVjdG9yRGVidWdBZGFwdGVyCiAgICBAZXh0ZW5kcyBEYXRhQWRhcHRlcgogICAgQHByaXZhdGUKICAqLwogIHZhciBfZGVmYXVsdCA9IEVtYmVyLkRhdGFBZGFwdGVyLmV4dGVuZCh7CiAgICBzdG9yZTogRW1iZXIuaW5qZWN0LnNlcnZpY2UoJ3N0b3JlJyksCgogICAgLyoqCiAgICAgIFNwZWNpZmllcyBob3cgcmVjb3JkcyBjYW4gYmUgZmlsdGVyZWQgYmFzZWQgb24gdGhlIHN0YXRlIG9mIHRoZSByZWNvcmQKICAgICAgUmVjb3JkcyByZXR1cm5lZCB3aWxsIG5lZWQgdG8gaGF2ZSBhIGBmaWx0ZXJWYWx1ZXNgCiAgICAgIHByb3BlcnR5IHdpdGggYSBrZXkgZm9yIGV2ZXJ5IG5hbWUgaW4gdGhlIHJldHVybmVkIGFycmF5CiAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZ2V0RmlsdGVycwogICAgICBAcmV0dXJuIHtBcnJheX0gTGlzdCBvZiBvYmplY3RzIGRlZmluaW5nIGZpbHRlcnMKICAgICAgIFRoZSBvYmplY3Qgc2hvdWxkIGhhdmUgYSBgbmFtZWAgYW5kIGBkZXNjYCBwcm9wZXJ0eQogICAgKi8KICAgIGdldEZpbHRlcnM6IGZ1bmN0aW9uIGdldEZpbHRlcnMoKSB7CiAgICAgIHJldHVybiBbewogICAgICAgIG5hbWU6ICdpc05ldycsCiAgICAgICAgZGVzYzogJ05ldycKICAgICAgfSwgewogICAgICAgIG5hbWU6ICdpc01vZGlmaWVkJywKICAgICAgICBkZXNjOiAnTW9kaWZpZWQnCiAgICAgIH0sIHsKICAgICAgICBuYW1lOiAnaXNDbGVhbicsCiAgICAgICAgZGVzYzogJ0NsZWFuJwogICAgICB9XTsKICAgIH0sCiAgICBfbmFtZVRvQ2xhc3M6IGZ1bmN0aW9uIF9uYW1lVG9DbGFzcyh0eXBlKSB7CiAgICAgIHJldHVybiBFbWJlci5nZXQodGhpcywgJ3N0b3JlJykubW9kZWxGb3IodHlwZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBGZXRjaCB0aGUgbW9kZWwgdHlwZXMgYW5kIG9ic2VydmUgdGhlbSBmb3IgY2hhbmdlcy4KICAgICAgTWFpbnRhaW5zIHRoZSBsaXN0IG9mIG1vZGVsIHR5cGVzIHdpdGhvdXQgbmVlZGluZyB0aGUgTW9kZWwgcGFja2FnZSBmb3IgZGV0ZWN0aW9uLgogICAgICBAcHVibGljCiAgICAgIEBtZXRob2Qgd2F0Y2hNb2RlbFR5cGVzCiAgICAgIEBwYXJhbSB7RnVuY3Rpb259IHR5cGVzQWRkZWQgQ2FsbGJhY2sgdG8gY2FsbCB0byBhZGQgdHlwZXMuCiAgICAgIFRha2VzIGFuIGFycmF5IG9mIG9iamVjdHMgY29udGFpbmluZyB3cmFwcGVkIHR5cGVzIChyZXR1cm5lZCBmcm9tIGB3cmFwTW9kZWxUeXBlYCkuCiAgICAgIEBwYXJhbSB7RnVuY3Rpb259IHR5cGVzVXBkYXRlZCBDYWxsYmFjayB0byBjYWxsIHdoZW4gYSB0eXBlIGhhcyBjaGFuZ2VkLgogICAgICBUYWtlcyBhbiBhcnJheSBvZiBvYmplY3RzIGNvbnRhaW5pbmcgd3JhcHBlZCB0eXBlcy4KICAgICAgQHJldHVybiB7RnVuY3Rpb259IE1ldGhvZCB0byBjYWxsIHRvIHJlbW92ZSBhbGwgb2JzZXJ2ZXJzCiAgICAqLwogICAgd2F0Y2hNb2RlbFR5cGVzOiBmdW5jdGlvbiB3YXRjaE1vZGVsVHlwZXModHlwZXNBZGRlZCwgdHlwZXNVcGRhdGVkKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICB2YXIgc3RvcmUgPSBFbWJlci5nZXQodGhpcywgJ3N0b3JlJyk7CiAgICAgIHZhciBfX2NyZWF0ZVJlY29yZERhdGEgPSBzdG9yZS5fY3JlYXRlUmVjb3JkRGF0YTsKICAgICAgdmFyIF9yZWxlYXNlTWV0aG9kcyA9IFtdOwogICAgICB2YXIgZGlzY292ZXJlZFR5cGVzID0gKDAsIF9zZXR1cC50eXBlc01hcEZvcikoc3RvcmUpOyAvLyBBZGQgYW55IG1vZGVscyB0aGF0IHdlcmUgYWRkZWQgZHVyaW5nIGluaXRpYWxpemF0aW9uIG9mIHRoZSBhcHAsIGJlZm9yZSB0aGUgaW5zcGVjdG9yIHdhcyBvcGVuZWQKCiAgICAgIGRpc2NvdmVyZWRUeXBlcy5mb3JFYWNoKGZ1bmN0aW9uIChfLCB0eXBlKSB7CiAgICAgICAgX3RoaXMud2F0Y2hUeXBlSWZVbnNlZW4oc3RvcmUsIGRpc2NvdmVyZWRUeXBlcywgdHlwZSwgdHlwZXNBZGRlZCwgdHlwZXNVcGRhdGVkLCBfcmVsZWFzZU1ldGhvZHMpOwogICAgICB9KTsgLy8gT3ZlcndyaXRlIF9jcmVhdGVSZWNvcmREYXRhIHNvIG5ld2x5IGFkZGVkIG1vZGVscyB3aWxsIGdldCBhZGRlZCB0byB0aGUgbGlzdAoKICAgICAgc3RvcmUuX2NyZWF0ZVJlY29yZERhdGEgPSBmdW5jdGlvbiAoaWRlbnRpZmllcikgewogICAgICAgIF90aGlzLndhdGNoVHlwZUlmVW5zZWVuKHN0b3JlLCBkaXNjb3ZlcmVkVHlwZXMsIGlkZW50aWZpZXIudHlwZSwgdHlwZXNBZGRlZCwgdHlwZXNVcGRhdGVkLCBfcmVsZWFzZU1ldGhvZHMpOwoKICAgICAgICByZXR1cm4gX19jcmVhdGVSZWNvcmREYXRhLmNhbGwoc3RvcmUsIGlkZW50aWZpZXIpOwogICAgICB9OwoKICAgICAgdmFyIHJlbGVhc2UgPSBmdW5jdGlvbiByZWxlYXNlKCkgewogICAgICAgIF9yZWxlYXNlTWV0aG9kcy5mb3JFYWNoKGZ1bmN0aW9uIChmbikgewogICAgICAgICAgcmV0dXJuIGZuKCk7CiAgICAgICAgfSk7CgogICAgICAgIHN0b3JlLl9jcmVhdGVSZWNvcmREYXRhID0gX19jcmVhdGVSZWNvcmREYXRhOyAvLyByZXNldCB0aGUgbGlzdCBzbyB0aGUgbW9kZWxzIGNhbiBiZSBhZGRlZCBpZiB0aGUgaW5zcGVjdG9yIGlzIHJlLW9wZW5lZAogICAgICAgIC8vIHRoZSBlbnRyaWVzIGFyZSBzZXQgdG8gZmFsc2UgaW5zdGVhZCBvZiByZW1vdmVkLCBzaW5jZSB0aGUgbW9kZWxzIHN0aWxsIGV4aXN0IGluIHRoZSBhcHAKICAgICAgICAvLyB3ZSBqdXN0IG5lZWQgdGhlIGluc3BlY3RvciB0byBiZWNvbWUgYXdhcmUgb2YgdGhlbQoKICAgICAgICBkaXNjb3ZlcmVkVHlwZXMuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkgewogICAgICAgICAgZGlzY292ZXJlZFR5cGVzLnNldChrZXksIGZhbHNlKTsKICAgICAgICB9KTsKCiAgICAgICAgX3RoaXMucmVsZWFzZU1ldGhvZHMucmVtb3ZlT2JqZWN0KHJlbGVhc2UpOwogICAgICB9OwoKICAgICAgdGhpcy5yZWxlYXNlTWV0aG9kcy5wdXNoT2JqZWN0KHJlbGVhc2UpOwogICAgICByZXR1cm4gcmVsZWFzZTsKICAgIH0sCgogICAgLyoqCiAgICAgKiBMb29wIG92ZXIgdGhlIGRpc2NvdmVyZWQgdHlwZXMgYW5kIHVzZSB0aGUgY2FsbGJhY2tzIGZyb20gd2F0Y2hNb2RlbFR5cGVzIHRvIG5vdGlmeQogICAgICogdGhlIGNvbnN1bWVyIG9mIHRoaXMgYWRhcHRlciBhYm91dCB0aGUgbWRvZWxzLgogICAgICoKICAgICAqIEBwYXJhbSB7c3RvcmV9IHN0b3JlCiAgICAgKiBAcGFyYW0ge01hcH0gZGlzY292ZXJlZFR5cGVzCiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdHlwZQogICAgICogQHBhcmFtIHtGdW5jdGlvbn0gdHlwZXNBZGRlZAogICAgICogQHBhcmFtIHtGdW5jdGlvbn0gdHlwZXNVcGRhdGVkCiAgICAgKiBAcGFyYW0ge0FycmF5fSByZWxlYXNlTWV0aG9kcwogICAgICovCiAgICB3YXRjaFR5cGVJZlVuc2VlbjogZnVuY3Rpb24gd2F0Y2hUeXBlSWZVbnNlZW4oc3RvcmUsIGRpc2NvdmVyZWRUeXBlcywgdHlwZSwgdHlwZXNBZGRlZCwgdHlwZXNVcGRhdGVkLCByZWxlYXNlTWV0aG9kcykgewogICAgICBpZiAoZGlzY292ZXJlZFR5cGVzLmdldCh0eXBlKSAhPT0gdHJ1ZSkgewogICAgICAgIHZhciBrbGFzcyA9IHN0b3JlLm1vZGVsRm9yKHR5cGUpOwogICAgICAgIHZhciB3cmFwcGVkID0gdGhpcy53cmFwTW9kZWxUeXBlKGtsYXNzLCB0eXBlKTsKICAgICAgICByZWxlYXNlTWV0aG9kcy5wdXNoKHRoaXMub2JzZXJ2ZU1vZGVsVHlwZSh0eXBlLCB0eXBlc1VwZGF0ZWQpKTsKICAgICAgICB0eXBlc0FkZGVkKFt3cmFwcGVkXSk7CiAgICAgICAgZGlzY292ZXJlZFR5cGVzLnNldCh0eXBlLCB0cnVlKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgQ3JlYXRlcyBhIGh1bWFuIHJlYWRhYmxlIHN0cmluZyB1c2VkIGZvciBjb2x1bW4gaGVhZGVycwogICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGNvbHVtbk5hbWVUb0Rlc2MKICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIGF0dHJpYnV0ZSBuYW1lCiAgICAgIEByZXR1cm4ge1N0cmluZ30gSHVtYW4gcmVhZGFibGUgc3RyaW5nIGJhc2VkIG9uIHRoZSBhdHRyaWJ1dGUgbmFtZQogICAgKi8KICAgIGNvbHVtbk5hbWVUb0Rlc2M6IGZ1bmN0aW9uIGNvbHVtbk5hbWVUb0Rlc2MobmFtZSkgewogICAgICByZXR1cm4gRW1iZXIuU3RyaW5nLmNhcGl0YWxpemUoRW1iZXIuU3RyaW5nLnVuZGVyc2NvcmUobmFtZSkucmVwbGFjZSgvXy9nLCAnICcpLnRyaW0oKSk7CiAgICB9LAoKICAgIC8qKgogICAgICBHZXQgdGhlIGNvbHVtbnMgZm9yIGEgZ2l2ZW4gbW9kZWwgdHlwZQogICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGNvbHVtbnNGb3JUeXBlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGVDbGFzcwogICAgICBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2YgY29sdW1ucyBvZiB0aGUgZm9sbG93aW5nIGZvcm1hdDoKICAgICAgIG5hbWU6IHtTdHJpbmd9IFRoZSBuYW1lIG9mIHRoZSBjb2x1bW4KICAgICAgIGRlc2M6IHtTdHJpbmd9IEh1bWFuaXplZCBkZXNjcmlwdGlvbiAod2hhdCB3b3VsZCBzaG93IGluIGEgdGFibGUgY29sdW1uIG5hbWUpCiAgICAqLwogICAgY29sdW1uc0ZvclR5cGU6IGZ1bmN0aW9uIGNvbHVtbnNGb3JUeXBlKHR5cGVDbGFzcykgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIHZhciBjb2x1bW5zID0gW3sKICAgICAgICBuYW1lOiAnaWQnLAogICAgICAgIGRlc2M6ICdJZCcKICAgICAgfV07CiAgICAgIHZhciBjb3VudCA9IDA7CiAgICAgIHZhciBzZWxmID0gdGhpczsKICAgICAgRW1iZXIuZ2V0KHR5cGVDbGFzcywgJ2F0dHJpYnV0ZXMnKS5mb3JFYWNoKGZ1bmN0aW9uIChtZXRhLCBuYW1lKSB7CiAgICAgICAgaWYgKGNvdW50KysgPiBzZWxmLmF0dHJpYnV0ZUxpbWl0KSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICB2YXIgZGVzYyA9IF90aGlzMi5jb2x1bW5OYW1lVG9EZXNjKG5hbWUpOwoKICAgICAgICBjb2x1bW5zLnB1c2goewogICAgICAgICAgbmFtZTogbmFtZSwKICAgICAgICAgIGRlc2M6IGRlc2MKICAgICAgICB9KTsKICAgICAgfSk7CiAgICAgIHJldHVybiBjb2x1bW5zOwogICAgfSwKCiAgICAvKioKICAgICAgRmV0Y2hlcyBhbGwgbG9hZGVkIHJlY29yZHMgZm9yIGEgZ2l2ZW4gdHlwZQogICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGdldFJlY29yZHMKICAgICAgQHBhcmFtIHtNb2RlbH0gbW9kZWxDbGFzcyBvZiB0aGUgcmVjb3JkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUgb2YgdGhlIHJlY29yZAogICAgICBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2YgTW9kZWwgcmVjb3JkcwogICAgICAgVGhpcyBhcnJheSB3aWxsIGJlIG9ic2VydmVkIGZvciBjaGFuZ2VzLAogICAgICAgc28gaXQgc2hvdWxkIHVwZGF0ZSB3aGVuIG5ldyByZWNvcmRzIGFyZSBhZGRlZC9yZW1vdmVkCiAgICAqLwogICAgZ2V0UmVjb3JkczogZnVuY3Rpb24gZ2V0UmVjb3Jkcyhtb2RlbENsYXNzLCBtb2RlbE5hbWUpIHsKICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7CiAgICAgICAgLy8gTGVnYWN5IEVtYmVyLmpzIDwgMS4xMyBzdXBwb3J0CiAgICAgICAgdmFyIGNvbnRhaW5lcktleSA9IG1vZGVsQ2xhc3MuX2RlYnVnQ29udGFpbmVyS2V5OwoKICAgICAgICBpZiAoY29udGFpbmVyS2V5KSB7CiAgICAgICAgICB2YXIgbWF0Y2ggPSBjb250YWluZXJLZXkubWF0Y2goL21vZGVsOiguKikvKTsKCiAgICAgICAgICBpZiAobWF0Y2ggIT09IG51bGwpIHsKICAgICAgICAgICAgbW9kZWxOYW1lID0gbWF0Y2hbMV07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICAoZmFsc2UgJiYgISghIW1vZGVsTmFtZSkgJiYgRW1iZXIuYXNzZXJ0KCdDYW5ub3QgZmluZCBtb2RlbCBuYW1lLiBQbGVhc2UgdXBncmFkZSB0byBFbWJlci5qcyA+PSAxLjEzIGZvciBFbWJlciBJbnNwZWN0b3Igc3VwcG9ydCcsICEhbW9kZWxOYW1lKSk7CiAgICAgIHJldHVybiB0aGlzLmdldCgnc3RvcmUnKS5wZWVrQWxsKG1vZGVsTmFtZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBHZXRzIHRoZSB2YWx1ZXMgZm9yIGVhY2ggY29sdW1uCiAgICAgIFRoaXMgaXMgdGhlIGF0dHJpYnV0ZSB2YWx1ZXMgZm9yIGEgZ2l2ZW4gcmVjb3JkCiAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZ2V0UmVjb3JkQ29sdW1uVmFsdWVzCiAgICAgIEBwYXJhbSB7TW9kZWx9IHJlY29yZCB0byBnZXQgdmFsdWVzIGZyb20KICAgICAgQHJldHVybiB7T2JqZWN0fSBLZXlzIHNob3VsZCBtYXRjaCBjb2x1bW4gbmFtZXMgZGVmaW5lZCBieSB0aGUgbW9kZWwgdHlwZQogICAgKi8KICAgIGdldFJlY29yZENvbHVtblZhbHVlczogZnVuY3Rpb24gZ2V0UmVjb3JkQ29sdW1uVmFsdWVzKHJlY29yZCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHZhciBjb3VudCA9IDA7CiAgICAgIHZhciBjb2x1bW5WYWx1ZXMgPSB7CiAgICAgICAgaWQ6IEVtYmVyLmdldChyZWNvcmQsICdpZCcpCiAgICAgIH07CiAgICAgIHJlY29yZC5lYWNoQXR0cmlidXRlKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICBpZiAoY291bnQrKyA+IF90aGlzMy5hdHRyaWJ1dGVMaW1pdCkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgY29sdW1uVmFsdWVzW2tleV0gPSBFbWJlci5nZXQocmVjb3JkLCBrZXkpOwogICAgICB9KTsKICAgICAgcmV0dXJuIGNvbHVtblZhbHVlczsKICAgIH0sCgogICAgLyoqCiAgICAgIFJldHVybnMga2V5d29yZHMgdG8gbWF0Y2ggd2hlbiBzZWFyY2hpbmcgcmVjb3JkcwogICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGdldFJlY29yZEtleXdvcmRzCiAgICAgIEBwYXJhbSB7TW9kZWx9IHJlY29yZAogICAgICBAcmV0dXJuIHtBcnJheX0gUmVsZXZhbnQga2V5d29yZHMgZm9yIHNlYXJjaCBiYXNlZCBvbiB0aGUgcmVjb3JkJ3MgYXR0cmlidXRlIHZhbHVlcwogICAgKi8KICAgIGdldFJlY29yZEtleXdvcmRzOiBmdW5jdGlvbiBnZXRSZWNvcmRLZXl3b3JkcyhyZWNvcmQpIHsKICAgICAgdmFyIGtleXdvcmRzID0gW107CiAgICAgIHZhciBrZXlzID0gRW1iZXIuQShbJ2lkJ10pOwogICAgICByZWNvcmQuZWFjaEF0dHJpYnV0ZShmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgcmV0dXJuIGtleXMucHVzaChrZXkpOwogICAgICB9KTsKICAgICAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICByZXR1cm4ga2V5d29yZHMucHVzaChFbWJlci5nZXQocmVjb3JkLCBrZXkpKTsKICAgICAgfSk7CiAgICAgIHJldHVybiBrZXl3b3JkczsKICAgIH0sCgogICAgLyoqCiAgICAgIFJldHVybnMgdGhlIHZhbHVlcyBvZiBmaWx0ZXJzIGRlZmluZWQgYnkgYGdldEZpbHRlcnNgCiAgICAgIFRoZXNlIHJlZmxlY3QgdGhlIHN0YXRlIG9mIHRoZSByZWNvcmQKICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBnZXRSZWNvcmRGaWx0ZXJWYWx1ZXMKICAgICAgQHBhcmFtIHtNb2RlbH0gcmVjb3JkCiAgICAgIEByZXR1cm4ge09iamVjdH0gVGhlIHJlY29yZCBzdGF0ZSBmaWx0ZXIgdmFsdWVzCiAgICAqLwogICAgZ2V0UmVjb3JkRmlsdGVyVmFsdWVzOiBmdW5jdGlvbiBnZXRSZWNvcmRGaWx0ZXJWYWx1ZXMocmVjb3JkKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgaXNOZXc6IHJlY29yZC5nZXQoJ2lzTmV3JyksCiAgICAgICAgaXNNb2RpZmllZDogcmVjb3JkLmdldCgnaGFzRGlydHlBdHRyaWJ1dGVzJykgJiYgIXJlY29yZC5nZXQoJ2lzTmV3JyksCiAgICAgICAgaXNDbGVhbjogIXJlY29yZC5nZXQoJ2hhc0RpcnR5QXR0cmlidXRlcycpCiAgICAgIH07CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIGEgY29sb3IgdGhhdCByZXByZXNlbnRzIHRoZSByZWNvcmQncyBzdGF0ZQogICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGdldFJlY29yZENvbG9yCiAgICAgIEBwYXJhbSB7TW9kZWx9IHJlY29yZAogICAgICBAcmV0dXJuIHtTdHJpbmd9IFRoZSByZWNvcmQgY29sb3IKICAgICAgICBQb3NzaWJsZSBvcHRpb25zOiBibGFjaywgYmx1ZSwgZ3JlZW4KICAgICovCiAgICBnZXRSZWNvcmRDb2xvcjogZnVuY3Rpb24gZ2V0UmVjb3JkQ29sb3IocmVjb3JkKSB7CiAgICAgIHZhciBjb2xvciA9ICdibGFjayc7CgogICAgICBpZiAocmVjb3JkLmdldCgnaXNOZXcnKSkgewogICAgICAgIGNvbG9yID0gJ2dyZWVuJzsKICAgICAgfSBlbHNlIGlmIChyZWNvcmQuZ2V0KCdoYXNEaXJ0eUF0dHJpYnV0ZXMnKSkgewogICAgICAgIGNvbG9yID0gJ2JsdWUnOwogICAgICB9CgogICAgICByZXR1cm4gY29sb3I7CiAgICB9LAoKICAgIC8qKgogICAgICBPYnNlcnZlcyBhbGwgcmVsZXZhbnQgcHJvcGVydGllcyBhbmQgcmUtc2VuZHMgdGhlIHdyYXBwZWQgcmVjb3JkCiAgICAgIHdoZW4gYSBjaGFuZ2Ugb2NjdXJzCiAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2Qgb2JzZXJ2ZXJSZWNvcmQKICAgICAgQHBhcmFtIHtNb2RlbH0gcmVjb3JkCiAgICAgIEBwYXJhbSB7RnVuY3Rpb259IHJlY29yZFVwZGF0ZWQgQ2FsbGJhY2sgdXNlZCB0byBub3RpZnkgY2hhbmdlcwogICAgICBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGZ1bmN0aW9uIHRvIGNhbGwgdG8gcmVtb3ZlIGFsbCBvYnNlcnZlcnMKICAgICovCiAgICBvYnNlcnZlUmVjb3JkOiBmdW5jdGlvbiBvYnNlcnZlUmVjb3JkKHJlY29yZCwgcmVjb3JkVXBkYXRlZCkgewogICAgICB2YXIgcmVsZWFzZU1ldGhvZHMgPSBFbWJlci5BKCk7CiAgICAgIHZhciBrZXlzVG9PYnNlcnZlID0gRW1iZXIuQShbJ2lkJywgJ2lzTmV3JywgJ2hhc0RpcnR5QXR0cmlidXRlcyddKTsKICAgICAgcmVjb3JkLmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24gKGtleSkgewogICAgICAgIHJldHVybiBrZXlzVG9PYnNlcnZlLnB1c2goa2V5KTsKICAgICAgfSk7CiAgICAgIHZhciBhZGFwdGVyID0gdGhpczsKICAgICAga2V5c1RvT2JzZXJ2ZS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICB2YXIgaGFuZGxlciA9IGZ1bmN0aW9uIGhhbmRsZXIoKSB7CiAgICAgICAgICByZWNvcmRVcGRhdGVkKGFkYXB0ZXIud3JhcFJlY29yZChyZWNvcmQpKTsKICAgICAgICB9OwoKICAgICAgICBFbWJlci5hZGRPYnNlcnZlcihyZWNvcmQsIGtleSwgaGFuZGxlcik7CiAgICAgICAgcmVsZWFzZU1ldGhvZHMucHVzaChmdW5jdGlvbiAoKSB7CiAgICAgICAgICBFbWJlci5yZW1vdmVPYnNlcnZlcihyZWNvcmQsIGtleSwgaGFuZGxlcik7CiAgICAgICAgfSk7CiAgICAgIH0pOwoKICAgICAgdmFyIHJlbGVhc2UgPSBmdW5jdGlvbiByZWxlYXNlKCkgewogICAgICAgIHJlbGVhc2VNZXRob2RzLmZvckVhY2goZnVuY3Rpb24gKGZuKSB7CiAgICAgICAgICByZXR1cm4gZm4oKTsKICAgICAgICB9KTsKICAgICAgfTsKCiAgICAgIHJldHVybiByZWxlYXNlOwogICAgfQogIH0pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwo7ZGVmaW5lKCJAZW1iZXItZGF0YS9kZWJ1Zy9zZXR1cCIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9zdG9yZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9zdG9yZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMudHlwZXNNYXBGb3IgPSB0eXBlc01hcEZvcjsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwogIHZhciBTdG9yZVR5cGVzTWFwID0gbmV3IFdlYWtNYXAoKTsKCiAgZnVuY3Rpb24gdHlwZXNNYXBGb3Ioc3RvcmUpIHsKICAgIHZhciB0eXBlc01hcCA9IFN0b3JlVHlwZXNNYXAuZ2V0KHN0b3JlKTsKCiAgICBpZiAodHlwZXNNYXAgPT09IHVuZGVmaW5lZCkgewogICAgICB0eXBlc01hcCA9IG5ldyBNYXAoKTsKICAgICAgU3RvcmVUeXBlc01hcC5zZXQoc3RvcmUsIHR5cGVzTWFwKTsKICAgIH0KCiAgICByZXR1cm4gdHlwZXNNYXA7CiAgfSAvLyBvdmVycmlkZSBfY3JlYXRlUmVjb3JkRGF0YSB0byBhZGQgdGhlIGtub3duIG1vZGVscyB0byB0aGUgdHlwZXNNYXAKCgogIHZhciBfX2NyZWF0ZVJlY29yZERhdGEgPSBfc3RvcmUuZGVmYXVsdC5wcm90b3R5cGUuX2NyZWF0ZVJlY29yZERhdGE7CgogIF9zdG9yZS5kZWZhdWx0LnByb3RvdHlwZS5fY3JlYXRlUmVjb3JkRGF0YSA9IGZ1bmN0aW9uIChpZGVudGlmaWVyKSB7CiAgICB2YXIgdHlwZXNNYXAgPSB0eXBlc01hcEZvcih0aGlzKTsKCiAgICBpZiAoIXR5cGVzTWFwLmhhcyhpZGVudGlmaWVyLnR5cGUpKSB7CiAgICAgIHR5cGVzTWFwLnNldChpZGVudGlmaWVyLnR5cGUsIGZhbHNlKTsKICAgIH0KCiAgICByZXR1cm4gX19jcmVhdGVSZWNvcmREYXRhLmNhbGwodGhpcywgaWRlbnRpZmllcik7CiAgfTsKCiAgdmFyIF9kZWZhdWx0ID0gewogICAgbmFtZTogJ0BlbWJlci1kYXRhL2RhdGEtYWRhcHRlcicsCiAgICBpbml0aWFsaXplOiBmdW5jdGlvbiBpbml0aWFsaXplKCkge30KICB9OwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CjtkZWZpbmUoJ0BlbWJlci1kYXRhL21vZGVsLy1wcml2YXRlJywgWydleHBvcnRzJywgJ0BlbWJlci1kYXRhL3N0b3JlLy1wcml2YXRlJywgJ0BlbWJlci1kYXRhL2NhbmFyeS1mZWF0dXJlcycsICdAZW1iZXItZGF0YS9zdG9yZSddLCBmdW5jdGlvbiAoZXhwb3J0cywgUHJpdmF0ZSwgY2FuYXJ5RmVhdHVyZXMsIHN0b3JlKSB7ICd1c2Ugc3RyaWN0JzsKCiAgZnVuY3Rpb24gaXNFbGVtZW50RGVzY3JpcHRvcihhcmdzKSB7CiAgICB2YXIgbWF5YmVUYXJnZXQgPSBhcmdzWzBdLAogICAgICAgIG1heWJlS2V5ID0gYXJnc1sxXSwKICAgICAgICBtYXliZURlc2MgPSBhcmdzWzJdOwogICAgcmV0dXJuICgvLyBFbnN1cmUgd2UgaGF2ZSB0aGUgcmlnaHQgbnVtYmVyIG9mIGFyZ3MKICAgICAgYXJncy5sZW5ndGggPT09IDMgJiYgKCAvLyBNYWtlIHN1cmUgdGhlIHRhcmdldCBpcyBhIGNsYXNzIG9yIG9iamVjdCAocHJvdG90eXBlKQogICAgICB0eXBlb2YgbWF5YmVUYXJnZXQgPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIG1heWJlVGFyZ2V0ID09PSAnb2JqZWN0JyAmJiBtYXliZVRhcmdldCAhPT0gbnVsbCkgJiYgLy8gTWFrZSBzdXJlIHRoZSBrZXkgaXMgYSBzdHJpbmcKICAgICAgdHlwZW9mIG1heWJlS2V5ID09PSAnc3RyaW5nJyAmJiAoIC8vIE1ha2Ugc3VyZSB0aGUgZGVzY3JpcHRvciBpcyB0aGUgcmlnaHQgc2hhcGUKICAgICAgdHlwZW9mIG1heWJlRGVzYyA9PT0gJ29iamVjdCcgJiYgbWF5YmVEZXNjICE9PSBudWxsICYmICdlbnVtZXJhYmxlJyBpbiBtYXliZURlc2MgJiYgJ2NvbmZpZ3VyYWJsZScgaW4gbWF5YmVEZXNjIHx8IC8vIFRTIGNvbXBhdGliaWxpdHkKICAgICAgbWF5YmVEZXNjID09PSB1bmRlZmluZWQpCiAgICApOwogIH0KICBmdW5jdGlvbiBjb21wdXRlZE1hY3JvV2l0aE9wdGlvbmFsUGFyYW1zKGZuKSB7CiAgICB7CiAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIG1heWJlRGVzYyA9IG5ldyBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgICAgIG1heWJlRGVzY1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBpc0VsZW1lbnREZXNjcmlwdG9yKG1heWJlRGVzYykgPyBmbigpLmFwcGx5KHZvaWQgMCwgbWF5YmVEZXNjKSA6IGZuLmFwcGx5KHZvaWQgMCwgbWF5YmVEZXNjKTsKICAgICAgfTsKICAgIH0KICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9tb2RlbAogICovCgogIGZ1bmN0aW9uIGdldERlZmF1bHRWYWx1ZShyZWNvcmQsIG9wdGlvbnMsIGtleSkgewogICAgaWYgKHR5cGVvZiBvcHRpb25zLmRlZmF1bHRWYWx1ZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gb3B0aW9ucy5kZWZhdWx0VmFsdWUuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgIH0gZWxzZSB7CiAgICAgIHZhciBkZWZhdWx0VmFsdWUgPSBvcHRpb25zLmRlZmF1bHRWYWx1ZTsKICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGhhc1ZhbHVlKGludGVybmFsTW9kZWwsIGtleSkgewogICAgcmV0dXJuIFByaXZhdGUucmVjb3JkRGF0YUZvcihpbnRlcm5hbE1vZGVsKS5oYXNBdHRyKGtleSk7CiAgfQogIC8qKgogICAgYGF0dHJgIGRlZmluZXMgYW4gYXR0cmlidXRlIG9uIGEgW01vZGVsXSgvZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvTW9kZWwpLgogICAgQnkgZGVmYXVsdCwgYXR0cmlidXRlcyBhcmUgcGFzc2VkIHRocm91Z2ggYXMtaXMsIGhvd2V2ZXIgeW91IGNhbiBzcGVjaWZ5IGFuCiAgICBvcHRpb25hbCB0eXBlIHRvIGhhdmUgdGhlIHZhbHVlIGF1dG9tYXRpY2FsbHkgdHJhbnNmb3JtZWQuCiAgICBFbWJlciBEYXRhIHNoaXBzIHdpdGggZm91ciBiYXNpYyB0cmFuc2Zvcm0gdHlwZXM6IGBzdHJpbmdgLCBgbnVtYmVyYCwKICAgIGBib29sZWFuYCBhbmQgYGRhdGVgLiBZb3UgY2FuIGRlZmluZSB5b3VyIG93biB0cmFuc2Zvcm1zIGJ5IHN1YmNsYXNzaW5nCiAgICBbVHJhbnNmb3JtXSgvZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvVHJhbnNmb3JtKS4KCiAgICBOb3RlIHRoYXQgeW91IGNhbm5vdCB1c2UgYGF0dHJgIHRvIGRlZmluZSBhbiBhdHRyaWJ1dGUgb2YgYGlkYC4KCiAgICBgYXR0cmAgdGFrZXMgYW4gb3B0aW9uYWwgaGFzaCBhcyBhIHNlY29uZCBwYXJhbWV0ZXIsIGN1cnJlbnRseQogICAgc3VwcG9ydGVkIG9wdGlvbnMgYXJlOgoKICAgIC0gYGRlZmF1bHRWYWx1ZWA6IFBhc3MgYSBzdHJpbmcgb3IgYSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgdG8gc2V0IHRoZSBhdHRyaWJ1dGUKICAgIHRvIGEgZGVmYXVsdCB2YWx1ZSBpZiBub25lIGlzIHN1cHBsaWVkLgoKICAgIEV4YW1wbGUKCiAgICBgYGBhcHAvbW9kZWxzL3VzZXIuanMKICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHVzZXJuYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgZW1haWw6IGF0dHIoJ3N0cmluZycpLAogICAgICB2ZXJpZmllZDogYXR0cignYm9vbGVhbicsIHsgZGVmYXVsdFZhbHVlOiBmYWxzZSB9KQogICAgfSk7CiAgICBgYGAKCiAgICBEZWZhdWx0IHZhbHVlIGNhbiBhbHNvIGJlIGEgZnVuY3Rpb24uIFRoaXMgaXMgdXNlZnVsIGl0IHlvdSB3YW50IHRvIHJldHVybgogICAgYSBuZXcgb2JqZWN0IGZvciBlYWNoIGF0dHJpYnV0ZS4KCiAgICBgYGBhcHAvbW9kZWxzL3VzZXIuanMKICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHVzZXJuYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgZW1haWw6IGF0dHIoJ3N0cmluZycpLAogICAgICBzZXR0aW5nczogYXR0cih7CiAgICAgICAgZGVmYXVsdFZhbHVlKCkgewogICAgICAgICAgcmV0dXJuIHt9OwogICAgICAgIH0KICAgICAgfSkKICAgIH0pOwogICAgYGBgCgogICAgVGhlIGBvcHRpb25zYCBoYXNoIGlzIHBhc3NlZCBhcyBzZWNvbmQgYXJndW1lbnQgdG8gYSB0cmFuc2Zvcm1zJwogICAgYHNlcmlhbGl6ZWAgYW5kIGBkZXNlcmlhbGl6ZWAgbWV0aG9kLiBUaGlzIGFsbG93cyB0byBjb25maWd1cmUgYQogICAgdHJhbnNmb3JtYXRpb24gYW5kIGFkYXB0IHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlLCBiYXNlZCBvbiB0aGUgY29uZmlnOgoKICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgdGV4dDogYXR0cigndGV4dCcsIHsKICAgICAgICB1cHBlcmNhc2U6IHRydWUKICAgICAgfSkKICAgIH0pOwogICAgYGBgCgogICAgYGBgYXBwL3RyYW5zZm9ybXMvdGV4dC5qcwogICAgaW1wb3J0IFRyYW5zZm9ybSBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3RyYW5zZm9ybSc7CgogICAgZXhwb3J0IGRlZmF1bHQgVHJhbnNmb3JtLmV4dGVuZCh7CiAgICAgIHNlcmlhbGl6ZSh2YWx1ZSwgb3B0aW9ucykgewogICAgICAgIGlmIChvcHRpb25zLnVwcGVyY2FzZSkgewogICAgICAgICAgcmV0dXJuIHZhbHVlLnRvVXBwZXJDYXNlKCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0sCgogICAgICBkZXNlcmlhbGl6ZSh2YWx1ZSkgewogICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgfQogICAgfSkKICAgIGBgYAoKICAgIEBtZXRob2QgYXR0cgogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXItZGF0YS9tb2RlbAogICAgQHBhcmFtIHtTdHJpbmd8T2JqZWN0fSB0eXBlIHRoZSBhdHRyaWJ1dGUgdHlwZQogICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgYSBoYXNoIG9mIG9wdGlvbnMKICAgIEByZXR1cm4ge0F0dHJpYnV0ZX0KICAqLwoKCiAgZnVuY3Rpb24gYXR0cih0eXBlLCBvcHRpb25zKSB7CiAgICBpZiAodHlwZW9mIHR5cGUgPT09ICdvYmplY3QnKSB7CiAgICAgIG9wdGlvbnMgPSB0eXBlOwogICAgICB0eXBlID0gdW5kZWZpbmVkOwogICAgfSBlbHNlIHsKICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307CiAgICB9CgogICAgdmFyIG1ldGEgPSB7CiAgICAgIHR5cGU6IHR5cGUsCiAgICAgIGlzQXR0cmlidXRlOiB0cnVlLAogICAgICBraW5kOiAnYXR0cmlidXRlJywKICAgICAgb3B0aW9uczogb3B0aW9ucwogICAgfTsKICAgIHJldHVybiBFbWJlci5jb21wdXRlZCh7CiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KGtleSkgewoKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IHRoaXMuX2ludGVybmFsTW9kZWw7CgogICAgICAgIGlmIChoYXNWYWx1ZShpbnRlcm5hbE1vZGVsLCBrZXkpKSB7CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5nZXRBdHRyaWJ1dGVWYWx1ZShrZXkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gZ2V0RGVmYXVsdFZhbHVlKHRoaXMsIG9wdGlvbnMsIGtleSk7CiAgICAgICAgfQogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldChrZXksIHZhbHVlKSB7CgogICAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9FUlJPUlMpIHsKICAgICAgICAgIHZhciBvbGRWYWx1ZSA9IHRoaXMuX2ludGVybmFsTW9kZWwuX3JlY29yZERhdGEuZ2V0QXR0cihrZXkpOwoKICAgICAgICAgIGlmIChvbGRWYWx1ZSAhPT0gdmFsdWUpIHsKICAgICAgICAgICAgdmFyIGVycm9ycyA9IHRoaXMuZ2V0KCdlcnJvcnMnKTsKCiAgICAgICAgICAgIGlmIChlcnJvcnMuZ2V0KGtleSkpIHsKICAgICAgICAgICAgICBlcnJvcnMucmVtb3ZlKGtleSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHRoaXMuX21hcmtJbnZhbGlkUmVxdWVzdEFzQ2xlYW4oKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsLnNldERpcnR5QXR0cmlidXRlKGtleSwgdmFsdWUpOwogICAgICB9CiAgICB9KS5tZXRhKG1ldGEpOwogIH0KCiAgdmFyIGF0dHIkMSA9IGNvbXB1dGVkTWFjcm9XaXRoT3B0aW9uYWxQYXJhbXMoYXR0cik7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9tb2RlbAogICovCgogIC8qKgogICAgYGJlbG9uZ3NUb2AgaXMgdXNlZCB0byBkZWZpbmUgT25lLVRvLU9uZSBhbmQgT25lLVRvLU1hbnkKICAgIHJlbGF0aW9uc2hpcHMgb24gYSBbTW9kZWxdKC9lbWJlci1kYXRhL3JlbGVhc2UvY2xhc3Nlcy9Nb2RlbCkuCgoKICAgIGBiZWxvbmdzVG9gIHRha2VzIGFuIG9wdGlvbmFsIGhhc2ggYXMgYSBzZWNvbmQgcGFyYW1ldGVyLCBjdXJyZW50bHkKICAgIHN1cHBvcnRlZCBvcHRpb25zIGFyZToKCiAgICAtIGBhc3luY2A6IEEgYm9vbGVhbiB2YWx1ZSB1c2VkIHRvIGV4cGxpY2l0bHkgZGVjbGFyZSB0aGlzIHRvIGJlIGFuIGFzeW5jIHJlbGF0aW9uc2hpcC4gVGhlIGRlZmF1bHQgaXMgdHJ1ZS4KICAgIC0gYGludmVyc2VgOiBBIHN0cmluZyB1c2VkIHRvIGlkZW50aWZ5IHRoZSBpbnZlcnNlIHByb3BlcnR5IG9uIGEKICAgICAgcmVsYXRlZCBtb2RlbCBpbiBhIE9uZS1Uby1NYW55IHJlbGF0aW9uc2hpcC4gU2VlIFtFeHBsaWNpdCBJbnZlcnNlc10oI2V4cGxpY2l0LWludmVyc2VzKQogICAgLSBgcG9seW1vcnBoaWNgIEEgYm9vbGVhbiB2YWx1ZSB0byBtYXJrIHRoZSByZWxhdGlvbnNoaXAgYXMgcG9seW1vcnBoaWMKCiAgICAjIyMjIE9uZS1Uby1PbmUKICAgIFRvIGRlY2xhcmUgYSBvbmUtdG8tb25lIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHR3byBtb2RlbHMsIHVzZQogICAgYGJlbG9uZ3NUb2A6CgogICAgYGBgYXBwL21vZGVscy91c2VyLmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHByb2ZpbGU6IGJlbG9uZ3NUbygncHJvZmlsZScpCiAgICB9KTsKICAgIGBgYAoKICAgIGBgYGFwcC9tb2RlbHMvcHJvZmlsZS5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICB1c2VyOiBiZWxvbmdzVG8oJ3VzZXInKQogICAgfSk7CiAgICBgYGAKCiAgICAjIyMjIE9uZS1Uby1NYW55CiAgICBUbyBkZWNsYXJlIGEgb25lLXRvLW1hbnkgcmVsYXRpb25zaGlwIGJldHdlZW4gdHdvIG1vZGVscywgdXNlCiAgICBgYmVsb25nc1RvYCBpbiBjb21iaW5hdGlvbiB3aXRoIGBoYXNNYW55YCwgbGlrZSB0aGlzOgoKICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgY29tbWVudHM6IGhhc01hbnkoJ2NvbW1lbnQnKQogICAgfSk7CiAgICBgYGAKCiAgICBgYGBhcHAvbW9kZWxzL2NvbW1lbnQuanMKICAgIGltcG9ydCBNb2RlbCwgeyBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgcG9zdDogYmVsb25nc1RvKCdwb3N0JykKICAgIH0pOwogICAgYGBgCgogICAgWW91IGNhbiBhdm9pZCBwYXNzaW5nIGEgc3RyaW5nIGFzIHRoZSBmaXJzdCBwYXJhbWV0ZXIuIEluIHRoYXQgY2FzZSBFbWJlciBEYXRhCiAgICB3aWxsIGluZmVyIHRoZSB0eXBlIGZyb20gdGhlIGtleSBuYW1lLgoKICAgIGBgYGFwcC9tb2RlbHMvY29tbWVudC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBwb3N0OiBiZWxvbmdzVG8oKQogICAgfSk7CiAgICBgYGAKCiAgICB3aWxsIGxvb2t1cCBmb3IgYSBQb3N0IHR5cGUuCgogICAgIyMjIyBTeW5jIHJlbGF0aW9uc2hpcHMKCiAgICBFbWJlciBEYXRhIHJlc29sdmVzIHN5bmMgcmVsYXRpb25zaGlwcyB3aXRoIHRoZSByZWxhdGVkIHJlc291cmNlcwogICAgYXZhaWxhYmxlIGluIGl0cyBsb2NhbCBzdG9yZSwgaGVuY2UgaXQgaXMgZXhwZWN0ZWQgdGhlc2UgcmVzb3VyY2VzCiAgICB0byBiZSBsb2FkZWQgYmVmb3JlIG9yIGFsb25nLXNpZGUgdGhlIHByaW1hcnkgcmVzb3VyY2UuCgogICAgYGBgYXBwL21vZGVscy9jb21tZW50LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHBvc3Q6IGJlbG9uZ3NUbygncG9zdCcsIHsKICAgICAgICBhc3luYzogZmFsc2UKICAgICAgfSkKICAgIH0pOwogICAgYGBgCgogICAgSW4gY29udHJhc3QgdG8gYXN5bmMgcmVsYXRpb25zaGlwLCBhY2Nlc3NpbmcgYSBzeW5jIHJlbGF0aW9uc2hpcAogICAgd2lsbCBhbHdheXMgcmV0dXJuIHRoZSByZWNvcmQgKE1vZGVsIGluc3RhbmNlKSBmb3IgdGhlIGV4aXN0aW5nCiAgICBsb2NhbCByZXNvdXJjZSwgb3IgbnVsbC4gQnV0IGl0IHdpbGwgZXJyb3Igb24gYWNjZXNzIHdoZW4KICAgIGEgcmVsYXRlZCByZXNvdXJjZSBpcyBrbm93biB0byBleGlzdCBhbmQgaXQgaGFzIG5vdCBiZWVuIGxvYWRlZC4KCiAgICBgYGAKICAgIGxldCBwb3N0ID0gY29tbWVudC5nZXQoJ3Bvc3QnKTsKCiAgICBgYGAKCiAgICBAbWV0aG9kIGJlbG9uZ3NUbwogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXItZGF0YS9tb2RlbAogICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZSAob3B0aW9uYWwpIHR5cGUgb2YgdGhlIHJlbGF0aW9uc2hpcAogICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgKG9wdGlvbmFsKSBhIGhhc2ggb2Ygb3B0aW9ucwogICAgQHJldHVybiB7RW1iZXIuY29tcHV0ZWR9IHJlbGF0aW9uc2hpcAogICovCgogIGZ1bmN0aW9uIGJlbG9uZ3NUbyhtb2RlbE5hbWUsIG9wdGlvbnMpIHsKICAgIHZhciBvcHRzLCB1c2VyRW50ZXJlZE1vZGVsTmFtZTsKCiAgICBpZiAodHlwZW9mIG1vZGVsTmFtZSA9PT0gJ29iamVjdCcpIHsKICAgICAgb3B0cyA9IG1vZGVsTmFtZTsKICAgICAgdXNlckVudGVyZWRNb2RlbE5hbWUgPSB1bmRlZmluZWQ7CiAgICB9IGVsc2UgewogICAgICBvcHRzID0gb3B0aW9uczsKICAgICAgdXNlckVudGVyZWRNb2RlbE5hbWUgPSBtb2RlbE5hbWU7CiAgICB9CgogICAgaWYgKHR5cGVvZiB1c2VyRW50ZXJlZE1vZGVsTmFtZSA9PT0gJ3N0cmluZycpIHsKICAgICAgdXNlckVudGVyZWRNb2RlbE5hbWUgPSBzdG9yZS5ub3JtYWxpemVNb2RlbE5hbWUodXNlckVudGVyZWRNb2RlbE5hbWUpOwogICAgfQogICAgb3B0cyA9IG9wdHMgfHwge307CiAgICB2YXIgbWV0YSA9IHsKICAgICAgdHlwZTogdXNlckVudGVyZWRNb2RlbE5hbWUsCiAgICAgIGlzUmVsYXRpb25zaGlwOiB0cnVlLAogICAgICBvcHRpb25zOiBvcHRzLAogICAgICBraW5kOiAnYmVsb25nc1RvJywKICAgICAgbmFtZTogJ0JlbG9uZ3MgVG8nLAogICAgICBrZXk6IG51bGwKICAgIH07CiAgICByZXR1cm4gRW1iZXIuY29tcHV0ZWQoewogICAgICBnZXQ6IGZ1bmN0aW9uIGdldChrZXkpIHsKCiAgICAgICAgcmV0dXJuIHRoaXMuX2ludGVybmFsTW9kZWwuZ2V0QmVsb25nc1RvKGtleSk7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUpIHsKCiAgICAgICAgdGhpcy5faW50ZXJuYWxNb2RlbC5zZXREaXJ0eUJlbG9uZ3NUbyhrZXksIHZhbHVlKTsKCiAgICAgICAgcmV0dXJuIHRoaXMuX2ludGVybmFsTW9kZWwuZ2V0QmVsb25nc1RvKGtleSk7CiAgICAgIH0KICAgIH0pLm1ldGEobWV0YSk7CiAgfQoKICB2YXIgYmVsb25nc1RvJDEgPSBjb21wdXRlZE1hY3JvV2l0aE9wdGlvbmFsUGFyYW1zKGJlbG9uZ3NUbyk7CgogIC8qKgogICAgYGhhc01hbnlgIGlzIHVzZWQgdG8gZGVmaW5lIE9uZS1Uby1NYW55IGFuZCBNYW55LVRvLU1hbnkKICAgIHJlbGF0aW9uc2hpcHMgb24gYSBbTW9kZWxdKC9lbWJlci1kYXRhL3JlbGVhc2UvY2xhc3Nlcy9Nb2RlbCkuCgogICAgYGhhc01hbnlgIHRha2VzIGFuIG9wdGlvbmFsIGhhc2ggYXMgYSBzZWNvbmQgcGFyYW1ldGVyLCBjdXJyZW50bHkKICAgIHN1cHBvcnRlZCBvcHRpb25zIGFyZToKCiAgICAtIGBhc3luY2A6IEEgYm9vbGVhbiB2YWx1ZSB1c2VkIHRvIGV4cGxpY2l0bHkgZGVjbGFyZSB0aGlzIHRvIGJlIGFuIGFzeW5jIHJlbGF0aW9uc2hpcC4gVGhlIGRlZmF1bHQgaXMgdHJ1ZS4KICAgIC0gYGludmVyc2VgOiBBIHN0cmluZyB1c2VkIHRvIGlkZW50aWZ5IHRoZSBpbnZlcnNlIHByb3BlcnR5IG9uIGEgcmVsYXRlZCBtb2RlbC4KICAgIC0gYHBvbHltb3JwaGljYCBBIGJvb2xlYW4gdmFsdWUgdG8gbWFyayB0aGUgcmVsYXRpb25zaGlwIGFzIHBvbHltb3JwaGljCgogICAgIyMjIyBPbmUtVG8tTWFueQogICAgVG8gZGVjbGFyZSBhIG9uZS10by1tYW55IHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHR3byBtb2RlbHMsIHVzZQogICAgYGJlbG9uZ3NUb2AgaW4gY29tYmluYXRpb24gd2l0aCBgaGFzTWFueWAsIGxpa2UgdGhpczoKCiAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIGNvbW1lbnRzOiBoYXNNYW55KCdjb21tZW50JykKICAgIH0pOwogICAgYGBgCgogICAgYGBgYXBwL21vZGVscy9jb21tZW50LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHBvc3Q6IGJlbG9uZ3NUbygncG9zdCcpCiAgICB9KTsKICAgIGBgYAoKICAgICMjIyMgTWFueS1Uby1NYW55CiAgICBUbyBkZWNsYXJlIGEgbWFueS10by1tYW55IHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHR3byBtb2RlbHMsIHVzZQogICAgYGhhc01hbnlgOgoKICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgdGFnczogaGFzTWFueSgndGFnJykKICAgIH0pOwogICAgYGBgCgogICAgYGBgYXBwL21vZGVscy90YWcuanMKICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHBvc3RzOiBoYXNNYW55KCdwb3N0JykKICAgIH0pOwogICAgYGBgCgogICAgWW91IGNhbiBhdm9pZCBwYXNzaW5nIGEgc3RyaW5nIGFzIHRoZSBmaXJzdCBwYXJhbWV0ZXIuIEluIHRoYXQgY2FzZSBFbWJlciBEYXRhCiAgICB3aWxsIGluZmVyIHRoZSB0eXBlIGZyb20gdGhlIHNpbmd1bGFyaXplZCBrZXkgbmFtZS4KCiAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHRhZ3M6IGhhc01hbnkoKQogICAgfSk7CiAgICBgYGAKCiAgICB3aWxsIGxvb2t1cCBmb3IgYSBUYWcgdHlwZS4KCiAgICAjIyMjIEV4cGxpY2l0IEludmVyc2VzCgogICAgRW1iZXIgRGF0YSB3aWxsIGRvIGl0cyBiZXN0IHRvIGRpc2NvdmVyIHdoaWNoIHJlbGF0aW9uc2hpcHMgbWFwIHRvCiAgICBvbmUgYW5vdGhlci4gSW4gdGhlIG9uZS10by1tYW55IGNvZGUgYWJvdmUsIGZvciBleGFtcGxlLCBFbWJlciBEYXRhCiAgICBjYW4gZmlndXJlIG91dCB0aGF0IGNoYW5naW5nIHRoZSBgY29tbWVudHNgIHJlbGF0aW9uc2hpcCBzaG91bGQgdXBkYXRlCiAgICB0aGUgYHBvc3RgIHJlbGF0aW9uc2hpcCBvbiB0aGUgaW52ZXJzZSBiZWNhdXNlIHBvc3QgaXMgdGhlIG9ubHkKICAgIHJlbGF0aW9uc2hpcCB0byB0aGF0IG1vZGVsLgoKICAgIEhvd2V2ZXIsIHNvbWV0aW1lcyB5b3UgbWF5IGhhdmUgbXVsdGlwbGUgYGJlbG9uZ3NUb2AvYGhhc01hbnlgIGZvciB0aGUKICAgIHNhbWUgdHlwZS4gWW91IGNhbiBzcGVjaWZ5IHdoaWNoIHByb3BlcnR5IG9uIHRoZSByZWxhdGVkIG1vZGVsIGlzCiAgICB0aGUgaW52ZXJzZSB1c2luZyBgaGFzTWFueWAncyBgaW52ZXJzZWAgb3B0aW9uOgoKICAgIGBgYGFwcC9tb2RlbHMvY29tbWVudC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBvbmVQb3N0OiBiZWxvbmdzVG8oJ3Bvc3QnKSwKICAgICAgdHdvUG9zdDogYmVsb25nc1RvKCdwb3N0JyksCiAgICAgIHJlZFBvc3Q6IGJlbG9uZ3NUbygncG9zdCcpLAogICAgICBibHVlUG9zdDogYmVsb25nc1RvKCdwb3N0JykKICAgIH0pOwogICAgYGBgCgogICAgYGBgYXBwL21vZGVscy9wb3N0LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBjb21tZW50czogaGFzTWFueSgnY29tbWVudCcsIHsKICAgICAgICBpbnZlcnNlOiAncmVkUG9zdCcKICAgICAgfSkKICAgIH0pOwogICAgYGBgCgogICAgWW91IGNhbiBhbHNvIHNwZWNpZnkgYW4gaW52ZXJzZSBvbiBhIGBiZWxvbmdzVG9gLCB3aGljaCB3b3JrcyBob3cKICAgIHlvdSdkIGV4cGVjdC4KCiAgICAjIyMjIFN5bmMgcmVsYXRpb25zaGlwcwoKICAgIEVtYmVyIERhdGEgcmVzb2x2ZXMgc3luYyByZWxhdGlvbnNoaXBzIHdpdGggdGhlIHJlbGF0ZWQgcmVzb3VyY2VzCiAgICBhdmFpbGFibGUgaW4gaXRzIGxvY2FsIHN0b3JlLCBoZW5jZSBpdCBpcyBleHBlY3RlZCB0aGVzZSByZXNvdXJjZXMKICAgIHRvIGJlIGxvYWRlZCBiZWZvcmUgb3IgYWxvbmctc2lkZSB0aGUgcHJpbWFyeSByZXNvdXJjZS4KCiAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIGNvbW1lbnRzOiBoYXNNYW55KCdjb21tZW50JywgewogICAgICAgIGFzeW5jOiBmYWxzZQogICAgICB9KQogICAgfSk7CiAgICBgYGAKCiAgICBJbiBjb250cmFzdCB0byBhc3luYyByZWxhdGlvbnNoaXAsIGFjY2Vzc2luZyBhIHN5bmMgcmVsYXRpb25zaGlwCiAgICB3aWxsIGFsd2F5cyByZXR1cm4gYSBbTWFueUFycmF5XSgvZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvTWFueUFycmF5KSBpbnN0YW5jZQogICAgY29udGFpbmluZyB0aGUgZXhpc3RpbmcgbG9jYWwgcmVzb3VyY2VzLiBCdXQgaXQgd2lsbCBlcnJvciBvbiBhY2Nlc3MKICAgIHdoZW4gYW55IG9mIHRoZSBrbm93biByZWxhdGVkIHJlc291cmNlcyBoYXZlIG5vdCBiZWVuIGxvYWRlZC4KCiAgICBgYGAKICAgIHBvc3QuZ2V0KCdjb21tZW50cycpLmZvckVhY2goKGNvbW1lbnQpID0+IHsKCiAgICB9KTsKCiAgICBgYGAKCiAgICBJZiB5b3UgYXJlIHVzaW5nIGBsaW5rc2Agd2l0aCBzeW5jIHJlbGF0aW9uc2hpcHMsIHlvdSBoYXZlIHRvIHVzZQogICAgYHJlZi5yZWxvYWRgIHRvIGZldGNoIHRoZSByZXNvdXJjZXMuCgogICAgQG1ldGhvZCBoYXNNYW55CiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci1kYXRhL21vZGVsCiAgICBAcGFyYW0ge1N0cmluZ30gdHlwZSAob3B0aW9uYWwpIHR5cGUgb2YgdGhlIHJlbGF0aW9uc2hpcAogICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgKG9wdGlvbmFsKSBhIGhhc2ggb2Ygb3B0aW9ucwogICAgQHJldHVybiB7RW1iZXIuY29tcHV0ZWR9IHJlbGF0aW9uc2hpcAogICovCgogIGZ1bmN0aW9uIGhhc01hbnkodHlwZSwgb3B0aW9ucykgewogICAgaWYgKHR5cGVvZiB0eXBlID09PSAnb2JqZWN0JykgewogICAgICBvcHRpb25zID0gdHlwZTsKICAgICAgdHlwZSA9IHVuZGVmaW5lZDsKICAgIH0KICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9OwoKICAgIGlmICh0eXBlb2YgdHlwZSA9PT0gJ3N0cmluZycpIHsKICAgICAgdHlwZSA9IHN0b3JlLm5vcm1hbGl6ZU1vZGVsTmFtZSh0eXBlKTsKICAgIH0gLy8gTWV0YWRhdGEgYWJvdXQgcmVsYXRpb25zaGlwcyBpcyBzdG9yZWQgb24gdGhlIG1ldGEgb2YKICAgIC8vIHRoZSByZWxhdGlvbnNoaXAuIFRoaXMgaXMgdXNlZCBmb3IgaW50cm9zcGVjdGlvbiBhbmQKICAgIC8vIHNlcmlhbGl6YXRpb24uIE5vdGUgdGhhdCBga2V5YCBpcyBwb3B1bGF0ZWQgbGF6aWx5CiAgICAvLyB0aGUgZmlyc3QgdGltZSB0aGUgQ1AgaXMgY2FsbGVkLgoKCiAgICB2YXIgbWV0YSA9IHsKICAgICAgdHlwZTogdHlwZSwKICAgICAgb3B0aW9uczogb3B0aW9ucywKICAgICAgaXNSZWxhdGlvbnNoaXA6IHRydWUsCiAgICAgIGtpbmQ6ICdoYXNNYW55JywKICAgICAgbmFtZTogJ0hhcyBNYW55JywKICAgICAga2V5OiBudWxsCiAgICB9OwogICAgcmV0dXJuIEVtYmVyLmNvbXB1dGVkKHsKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoa2V5KSB7CgogICAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsLmdldEhhc01hbnkoa2V5KTsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5LCByZWNvcmRzKSB7CgogICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gdGhpcy5faW50ZXJuYWxNb2RlbDsKICAgICAgICBpbnRlcm5hbE1vZGVsLnNldERpcnR5SGFzTWFueShrZXksIHJlY29yZHMpOwogICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLmdldEhhc01hbnkoa2V5KTsKICAgICAgfQogICAgfSkubWV0YShtZXRhKTsKICB9CgogIHZhciBoYXNNYW55JDEgPSBjb21wdXRlZE1hY3JvV2l0aE9wdGlvbmFsUGFyYW1zKGhhc01hbnkpOwoKICB2YXIgY2hhbmdlUHJvcGVydGllcyA9IEVtYmVyLmNoYW5nZVByb3BlcnRpZXM7CgogIGZ1bmN0aW9uIGlzSW52YWxpZEVycm9yKGVycm9yKSB7CiAgICByZXR1cm4gZXJyb3IgJiYgZXJyb3IuaXNBZGFwdGVyRXJyb3IgPT09IHRydWUgJiYgZXJyb3IuY29kZSA9PT0gJ0ludmFsaWRFcnJvcic7CiAgfQoKICBmdW5jdGlvbiBmaW5kUG9zc2libGVJbnZlcnNlcyh0eXBlLCBpbnZlcnNlVHlwZSwgbmFtZSwgcmVsYXRpb25zaGlwc1NvRmFyKSB7CiAgICB2YXIgcG9zc2libGVSZWxhdGlvbnNoaXBzID0gcmVsYXRpb25zaGlwc1NvRmFyIHx8IFtdOwogICAgdmFyIHJlbGF0aW9uc2hpcE1hcCA9IEVtYmVyLmdldChpbnZlcnNlVHlwZSwgJ3JlbGF0aW9uc2hpcHMnKTsKCiAgICBpZiAoIXJlbGF0aW9uc2hpcE1hcCkgewogICAgICByZXR1cm4gcG9zc2libGVSZWxhdGlvbnNoaXBzOwogICAgfQoKICAgIHZhciByZWxhdGlvbnNoaXBzRm9yVHlwZSA9IHJlbGF0aW9uc2hpcE1hcC5nZXQodHlwZS5tb2RlbE5hbWUpOwogICAgdmFyIHJlbGF0aW9uc2hpcHMgPSBBcnJheS5pc0FycmF5KHJlbGF0aW9uc2hpcHNGb3JUeXBlKSA/IHJlbGF0aW9uc2hpcHNGb3JUeXBlLmZpbHRlcihmdW5jdGlvbiAocmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBvcHRpb25zRm9yUmVsYXRpb25zaGlwID0gaW52ZXJzZVR5cGUubWV0YUZvclByb3BlcnR5KHJlbGF0aW9uc2hpcC5uYW1lKS5vcHRpb25zOwoKICAgICAgaWYgKCFvcHRpb25zRm9yUmVsYXRpb25zaGlwLmludmVyc2UgJiYgb3B0aW9uc0ZvclJlbGF0aW9uc2hpcC5pbnZlcnNlICE9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIHJldHVybiBuYW1lID09PSBvcHRpb25zRm9yUmVsYXRpb25zaGlwLmludmVyc2U7CiAgICB9KSA6IG51bGw7CgogICAgaWYgKHJlbGF0aW9uc2hpcHMpIHsKICAgICAgcG9zc2libGVSZWxhdGlvbnNoaXBzLnB1c2guYXBwbHkocG9zc2libGVSZWxhdGlvbnNoaXBzLCByZWxhdGlvbnNoaXBzKTsKICAgIH0gLy9SZWN1cnNlIHRvIHN1cHBvcnQgcG9seW1vcnBoaXNtCgoKICAgIGlmICh0eXBlLnN1cGVyY2xhc3MpIHsKICAgICAgZmluZFBvc3NpYmxlSW52ZXJzZXModHlwZS5zdXBlcmNsYXNzLCBpbnZlcnNlVHlwZSwgbmFtZSwgcG9zc2libGVSZWxhdGlvbnNoaXBzKTsKICAgIH0KCiAgICByZXR1cm4gcG9zc2libGVSZWxhdGlvbnNoaXBzOwogIH0KCiAgdmFyIHJldHJpZXZlRnJvbUN1cnJlbnRTdGF0ZSA9IEVtYmVyLmNvbXB1dGVkKCdjdXJyZW50U3RhdGUnLCBmdW5jdGlvbiAoa2V5KSB7CiAgICByZXR1cm4gRW1iZXIuZ2V0KHRoaXMuX2ludGVybmFsTW9kZWwuY3VycmVudFN0YXRlLCBrZXkpOwogIH0pLnJlYWRPbmx5KCk7CiAgdmFyIGlzVmFsaWRSZWNvcmREYXRhID0gRW1iZXIuY29tcHV0ZWQoJ2Vycm9ycy5sZW5ndGgnLCBmdW5jdGlvbiAoa2V5KSB7CiAgICByZXR1cm4gISh0aGlzLmdldCgnZXJyb3JzLmxlbmd0aCcpID4gMCk7CiAgfSkucmVhZE9ubHkoKTsKICB2YXIgaXNWYWxpZCA9IGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX0VSUk9SUyA/IGlzVmFsaWRSZWNvcmREYXRhIDogcmV0cmlldmVGcm9tQ3VycmVudFN0YXRlOwogIHZhciBpc0RlbGV0ZWRDUDsKCiAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX1NUQVRFKSB7CiAgICBpc0RlbGV0ZWRDUCA9IEVtYmVyLmNvbXB1dGVkKCdjdXJyZW50U3RhdGUnLCBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciByZCA9IFByaXZhdGUucmVjb3JkRGF0YUZvcih0aGlzKTsKCiAgICAgIGlmIChyZC5pc0RlbGV0ZWQpIHsKICAgICAgICByZXR1cm4gcmQuaXNEZWxldGVkKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVtYmVyLmdldCh0aGlzLl9pbnRlcm5hbE1vZGVsLmN1cnJlbnRTdGF0ZSwgJ2lzRGVsZXRlZCcpOwogICAgICB9CiAgICB9KS5yZWFkT25seSgpOwogIH0gZWxzZSB7CiAgICBpc0RlbGV0ZWRDUCA9IHJldHJpZXZlRnJvbUN1cnJlbnRTdGF0ZTsKICB9CgogIHZhciBpc05ld0NQOwoKICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfU1RBVEUpIHsKICAgIGlzTmV3Q1AgPSBFbWJlci5jb21wdXRlZCgnY3VycmVudFN0YXRlJywgZnVuY3Rpb24gKCkgewogICAgICB2YXIgcmQgPSBQcml2YXRlLnJlY29yZERhdGFGb3IodGhpcyk7CgogICAgICBpZiAocmQuaXNOZXcpIHsKICAgICAgICByZXR1cm4gcmQuaXNOZXcoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRW1iZXIuZ2V0KHRoaXMuX2ludGVybmFsTW9kZWwuY3VycmVudFN0YXRlLCAnaXNOZXcnKTsKICAgICAgfQogICAgfSkucmVhZE9ubHkoKTsKICB9IGVsc2UgewogICAgaXNOZXdDUCA9IHJldHJpZXZlRnJvbUN1cnJlbnRTdGF0ZTsKICB9CgogIHZhciBhZGFwdGVyRXJyb3I7CgogIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgIGFkYXB0ZXJFcnJvciA9IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIHJlcXVlc3QgPSB0aGlzLl9sYXN0RXJyb3I7CgogICAgICBpZiAoIXJlcXVlc3QpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlcXVlc3Quc3RhdGUgPT09ICdyZWplY3RlZCcgJiYgcmVxdWVzdC5yZXNwb25zZS5kYXRhOwogICAgfSk7CiAgfSBlbHNlIHsKICAgIGFkYXB0ZXJFcnJvciA9IG51bGw7CiAgfQoKICB2YXIgaXNFcnJvcjsKCiAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgaXNFcnJvciA9IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGVycm9yUmVxID0gdGhpcy5fZXJyb3JSZXF1ZXN0c1t0aGlzLl9lcnJvclJlcXVlc3RzLmxlbmd0aCAtIDFdOwoKICAgICAgaWYgKCFlcnJvclJlcSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgfSk7CiAgfSBlbHNlIHsKICAgIGlzRXJyb3IgPSBmYWxzZTsKICB9CgogIHZhciBpc1JlbG9hZGluZzsKCiAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgaXNSZWxvYWRpbmcgPSBFbWJlci5jb21wdXRlZChmdW5jdGlvbiAoKSB7CiAgICAgIHZhciByZXF1ZXN0cyA9IHRoaXMuc3RvcmUuZ2V0UmVxdWVzdFN0YXRlU2VydmljZSgpLmdldFBlbmRpbmdSZXF1ZXN0c0ZvclJlY29yZChQcml2YXRlLnJlY29yZElkZW50aWZpZXJGb3IodGhpcykpOwogICAgICByZXR1cm4gISFyZXF1ZXN0cy5maW5kKGZ1bmN0aW9uIChyZXEpIHsKICAgICAgICByZXR1cm4gcmVxLnJlcXVlc3QuZGF0YVswXS5vcHRpb25zLmlzUmVsb2FkaW5nOwogICAgICB9KTsKICAgIH0pOwogIH0gZWxzZSB7CiAgICBpc1JlbG9hZGluZyA9IGZhbHNlOwogIH0KICAvKioKICAgIEBjbGFzcyBNb2RlbAogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9tb2RlbAogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAgIEB1c2VzIEVtYmVyRGF0YS5EZXByZWNhdGVkRXZlbnRlZAogICovCgoKICB2YXIgTW9kZWwgPSBFbWJlci5PYmplY3QuZXh0ZW5kKFByaXZhdGUuRGVwcmVjYXRlZEV2ZW50ZWQsIHsKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX0VSUk9SUykgewogICAgICAgIHRoaXMuX2ludmFsaWRSZXF1ZXN0cyA9IFtdOwogICAgICB9CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgdGhpcy5zdG9yZS5nZXRSZXF1ZXN0U3RhdGVTZXJ2aWNlKCkuc3Vic2NyaWJlRm9yUmVjb3JkKHRoaXMuX2ludGVybmFsTW9kZWwuaWRlbnRpZmllciwgZnVuY3Rpb24gKHJlcXVlc3QpIHsKICAgICAgICAgIGlmIChyZXF1ZXN0LnN0YXRlID09PSAncmVqZWN0ZWQnKSB7CiAgICAgICAgICAgIC8vIFRPRE8gZmlsdGVyIG91dCBxdWVyaWVzCiAgICAgICAgICAgIF90aGlzLl9sYXN0RXJyb3IgPSByZXF1ZXN0OwoKICAgICAgICAgICAgaWYgKCEocmVxdWVzdC5yZXNwb25zZSAmJiBpc0ludmFsaWRFcnJvcihyZXF1ZXN0LnJlc3BvbnNlLmRhdGEpKSkgewogICAgICAgICAgICAgIF90aGlzLl9lcnJvclJlcXVlc3RzLnB1c2gocmVxdWVzdCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgX3RoaXMuX2ludmFsaWRSZXF1ZXN0cy5wdXNoKHJlcXVlc3QpOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgaWYgKHJlcXVlc3Quc3RhdGUgPT09ICdmdWxmaWxsZWQnKSB7CiAgICAgICAgICAgIF90aGlzLl9pbnZhbGlkUmVxdWVzdHMgPSBbXTsKICAgICAgICAgICAgX3RoaXMuX2Vycm9yUmVxdWVzdHMgPSBbXTsKICAgICAgICAgICAgX3RoaXMuX2xhc3RFcnJvciA9IG51bGw7CiAgICAgICAgICB9CgogICAgICAgICAgX3RoaXMuX25vdGlmeU5ldHdvcmtDaGFuZ2VzKCk7CiAgICAgICAgfSk7CiAgICAgICAgdGhpcy5fZXJyb3JSZXF1ZXN0cyA9IFtdOwogICAgICAgIHRoaXMuX2xhc3RFcnJvciA9IG51bGw7CiAgICAgIH0KICAgIH0sCiAgICBfbm90aWZ5TmV0d29ya0NoYW5nZXM6IGZ1bmN0aW9uIF9ub3RpZnlOZXR3b3JrQ2hhbmdlcygpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgWydpc1NhdmluZycsICdpc1ZhbGlkJywgJ2lzRXJyb3InLCAnYWRhcHRlckVycm9yJywgJ2lzUmVsb2FkaW5nJ10uZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgICByZXR1cm4gX3RoaXMyLm5vdGlmeVByb3BlcnR5Q2hhbmdlKGtleSk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgWydpc1ZhbGlkJ10uZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgICByZXR1cm4gX3RoaXMyLm5vdGlmeVByb3BlcnR5Q2hhbmdlKGtleSk7CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIElmIHRoaXMgcHJvcGVydHkgaXMgYHRydWVgIHRoZSByZWNvcmQgaXMgaW4gdGhlIGBlbXB0eWAKICAgICAgc3RhdGUuIEVtcHR5IGlzIHRoZSBmaXJzdCBzdGF0ZSBhbGwgcmVjb3JkcyBlbnRlciBhZnRlciB0aGV5IGhhdmUKICAgICAgYmVlbiBjcmVhdGVkLiBNb3N0IHJlY29yZHMgY3JlYXRlZCBieSB0aGUgc3RvcmUgd2lsbCBxdWlja2x5CiAgICAgIHRyYW5zaXRpb24gdG8gdGhlIGBsb2FkaW5nYCBzdGF0ZSBpZiBkYXRhIG5lZWRzIHRvIGJlIGZldGNoZWQgZnJvbQogICAgICB0aGUgc2VydmVyIG9yIHRoZSBgY3JlYXRlZGAgc3RhdGUgaWYgdGhlIHJlY29yZCBpcyBjcmVhdGVkIG9uIHRoZQogICAgICBjbGllbnQuIEEgcmVjb3JkIGNhbiBhbHNvIGVudGVyIHRoZSBlbXB0eSBzdGF0ZSBpZiB0aGUgYWRhcHRlciBpcwogICAgICB1bmFibGUgdG8gbG9jYXRlIHRoZSByZWNvcmQuCiAgICAgICBAcHJvcGVydHkgaXNFbXB0eQogICAgICBAdHlwZSB7Qm9vbGVhbn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgaXNFbXB0eTogcmV0cmlldmVGcm9tQ3VycmVudFN0YXRlLAoKICAgIC8qKgogICAgICBJZiB0aGlzIHByb3BlcnR5IGlzIGB0cnVlYCB0aGUgcmVjb3JkIGlzIGluIHRoZSBgbG9hZGluZ2Agc3RhdGUuIEEKICAgICAgcmVjb3JkIGVudGVycyB0aGlzIHN0YXRlIHdoZW4gdGhlIHN0b3JlIGFza3MgdGhlIGFkYXB0ZXIgZm9yIGl0cwogICAgICBkYXRhLiBJdCByZW1haW5zIGluIHRoaXMgc3RhdGUgdW50aWwgdGhlIGFkYXB0ZXIgcHJvdmlkZXMgdGhlCiAgICAgIHJlcXVlc3RlZCBkYXRhLgogICAgICAgQHByb3BlcnR5IGlzTG9hZGluZwogICAgICBAdHlwZSB7Qm9vbGVhbn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgaXNMb2FkaW5nOiByZXRyaWV2ZUZyb21DdXJyZW50U3RhdGUsCgogICAgLyoqCiAgICAgIElmIHRoaXMgcHJvcGVydHkgaXMgYHRydWVgIHRoZSByZWNvcmQgaXMgaW4gdGhlIGBsb2FkZWRgIHN0YXRlLiBBCiAgICAgIHJlY29yZCBlbnRlcnMgdGhpcyBzdGF0ZSB3aGVuIGl0cyBkYXRhIGlzIHBvcHVsYXRlZC4gTW9zdCBvZiBhCiAgICAgIHJlY29yZCdzIGxpZmVjeWNsZSBpcyBzcGVudCBpbnNpZGUgc3Vic3RhdGVzIG9mIHRoZSBgbG9hZGVkYAogICAgICBzdGF0ZS4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IHJlY29yZCA9IHN0b3JlLmNyZWF0ZVJlY29yZCgnbW9kZWwnKTsKICAgICAgcmVjb3JkLmdldCgnaXNMb2FkZWQnKTsgLy8gdHJ1ZQogICAgICAgc3RvcmUuZmluZFJlY29yZCgnbW9kZWwnLCAxKS50aGVuKGZ1bmN0aW9uKG1vZGVsKSB7CiAgICAgICAgbW9kZWwuZ2V0KCdpc0xvYWRlZCcpOyAvLyB0cnVlCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBpc0xvYWRlZAogICAgICBAdHlwZSB7Qm9vbGVhbn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgaXNMb2FkZWQ6IHJldHJpZXZlRnJvbUN1cnJlbnRTdGF0ZSwKCiAgICAvKioKICAgICAgSWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAgdGhlIHJlY29yZCBpcyBpbiB0aGUgYGRpcnR5YCBzdGF0ZS4gVGhlCiAgICAgIHJlY29yZCBoYXMgbG9jYWwgY2hhbmdlcyB0aGF0IGhhdmUgbm90IHlldCBiZWVuIHNhdmVkIGJ5IHRoZQogICAgICBhZGFwdGVyLiBUaGlzIGluY2x1ZGVzIHJlY29yZHMgdGhhdCBoYXZlIGJlZW4gY3JlYXRlZCAoYnV0IG5vdCB5ZXQKICAgICAgc2F2ZWQpIG9yIGRlbGV0ZWQuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCByZWNvcmQgPSBzdG9yZS5jcmVhdGVSZWNvcmQoJ21vZGVsJyk7CiAgICAgIHJlY29yZC5nZXQoJ2hhc0RpcnR5QXR0cmlidXRlcycpOyAvLyB0cnVlCiAgICAgICBzdG9yZS5maW5kUmVjb3JkKCdtb2RlbCcsIDEpLnRoZW4oZnVuY3Rpb24obW9kZWwpIHsKICAgICAgICBtb2RlbC5nZXQoJ2hhc0RpcnR5QXR0cmlidXRlcycpOyAvLyBmYWxzZQogICAgICAgIG1vZGVsLnNldCgnZm9vJywgJ3NvbWUgdmFsdWUnKTsKICAgICAgICBtb2RlbC5nZXQoJ2hhc0RpcnR5QXR0cmlidXRlcycpOyAvLyB0cnVlCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQHByb3BlcnR5IGhhc0RpcnR5QXR0cmlidXRlcwogICAgICBAdHlwZSB7Qm9vbGVhbn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgaGFzRGlydHlBdHRyaWJ1dGVzOiBFbWJlci5jb21wdXRlZCgnY3VycmVudFN0YXRlLmlzRGlydHknLCBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiB0aGlzLmdldCgnY3VycmVudFN0YXRlLmlzRGlydHknKTsKICAgIH0pLAoKICAgIC8qKgogICAgICBJZiB0aGlzIHByb3BlcnR5IGlzIGB0cnVlYCB0aGUgcmVjb3JkIGlzIGluIHRoZSBgc2F2aW5nYCBzdGF0ZS4gQQogICAgICByZWNvcmQgZW50ZXJzIHRoZSBzYXZpbmcgc3RhdGUgd2hlbiBgc2F2ZWAgaXMgY2FsbGVkLCBidXQgdGhlCiAgICAgIGFkYXB0ZXIgaGFzIG5vdCB5ZXQgYWNrbm93bGVkZ2VkIHRoYXQgdGhlIGNoYW5nZXMgaGF2ZSBiZWVuCiAgICAgIHBlcnNpc3RlZCB0byB0aGUgYmFja2VuZC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IHJlY29yZCA9IHN0b3JlLmNyZWF0ZVJlY29yZCgnbW9kZWwnKTsKICAgICAgcmVjb3JkLmdldCgnaXNTYXZpbmcnKTsgLy8gZmFsc2UKICAgICAgbGV0IHByb21pc2UgPSByZWNvcmQuc2F2ZSgpOwogICAgICByZWNvcmQuZ2V0KCdpc1NhdmluZycpOyAvLyB0cnVlCiAgICAgIHByb21pc2UudGhlbihmdW5jdGlvbigpIHsKICAgICAgICByZWNvcmQuZ2V0KCdpc1NhdmluZycpOyAvLyBmYWxzZQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAcHJvcGVydHkgaXNTYXZpbmcKICAgICAgQHR5cGUge0Jvb2xlYW59CiAgICAgIEByZWFkT25seQogICAgKi8KICAgIGlzU2F2aW5nOiByZXRyaWV2ZUZyb21DdXJyZW50U3RhdGUsCgogICAgLyoqCiAgICAgIElmIHRoaXMgcHJvcGVydHkgaXMgYHRydWVgIHRoZSByZWNvcmQgaXMgaW4gdGhlIGBkZWxldGVkYCBzdGF0ZQogICAgICBhbmQgaGFzIGJlZW4gbWFya2VkIGZvciBkZWxldGlvbi4gV2hlbiBgaXNEZWxldGVkYCBpcyB0cnVlIGFuZAogICAgICBgaGFzRGlydHlBdHRyaWJ1dGVzYCBpcyB0cnVlLCB0aGUgcmVjb3JkIGlzIGRlbGV0ZWQgbG9jYWxseSBidXQgdGhlIGRlbGV0aW9uCiAgICAgIHdhcyBub3QgeWV0IHBlcnNpc3RlZC4gV2hlbiBgaXNTYXZpbmdgIGlzIHRydWUsIHRoZSBjaGFuZ2UgaXMKICAgICAgaW4tZmxpZ2h0LiBXaGVuIGJvdGggYGhhc0RpcnR5QXR0cmlidXRlc2AgYW5kIGBpc1NhdmluZ2AgYXJlIGZhbHNlLCB0aGUKICAgICAgY2hhbmdlIGhhcyBwZXJzaXN0ZWQuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCByZWNvcmQgPSBzdG9yZS5jcmVhdGVSZWNvcmQoJ21vZGVsJyk7CiAgICAgIHJlY29yZC5nZXQoJ2lzRGVsZXRlZCcpOyAgICAvLyBmYWxzZQogICAgICByZWNvcmQuZGVsZXRlUmVjb3JkKCk7CiAgICAgICAvLyBMb2NhbGx5IGRlbGV0ZWQKICAgICAgcmVjb3JkLmdldCgnaXNEZWxldGVkJyk7ICAgICAgICAgICAvLyB0cnVlCiAgICAgIHJlY29yZC5nZXQoJ2hhc0RpcnR5QXR0cmlidXRlcycpOyAgLy8gdHJ1ZQogICAgICByZWNvcmQuZ2V0KCdpc1NhdmluZycpOyAgICAgICAgICAgIC8vIGZhbHNlCiAgICAgICAvLyBQZXJzaXN0aW5nIHRoZSBkZWxldGlvbgogICAgICBsZXQgcHJvbWlzZSA9IHJlY29yZC5zYXZlKCk7CiAgICAgIHJlY29yZC5nZXQoJ2lzRGVsZXRlZCcpOyAgICAvLyB0cnVlCiAgICAgIHJlY29yZC5nZXQoJ2lzU2F2aW5nJyk7ICAgICAvLyB0cnVlCiAgICAgICAvLyBEZWxldGlvbiBQZXJzaXN0ZWQKICAgICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKCkgewogICAgICAgIHJlY29yZC5nZXQoJ2lzRGVsZXRlZCcpOyAgICAgICAgICAvLyB0cnVlCiAgICAgICAgcmVjb3JkLmdldCgnaXNTYXZpbmcnKTsgICAgICAgICAgIC8vIGZhbHNlCiAgICAgICAgcmVjb3JkLmdldCgnaGFzRGlydHlBdHRyaWJ1dGVzJyk7IC8vIGZhbHNlCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBpc0RlbGV0ZWQKICAgICAgQHR5cGUge0Jvb2xlYW59CiAgICAgIEByZWFkT25seQogICAgKi8KICAgIGlzRGVsZXRlZDogaXNEZWxldGVkQ1AsCgogICAgLyoqCiAgICAgIElmIHRoaXMgcHJvcGVydHkgaXMgYHRydWVgIHRoZSByZWNvcmQgaXMgaW4gdGhlIGBuZXdgIHN0YXRlLiBBCiAgICAgIHJlY29yZCB3aWxsIGJlIGluIHRoZSBgbmV3YCBzdGF0ZSB3aGVuIGl0IGhhcyBiZWVuIGNyZWF0ZWQgb24gdGhlCiAgICAgIGNsaWVudCBhbmQgdGhlIGFkYXB0ZXIgaGFzIG5vdCB5ZXQgcmVwb3J0IHRoYXQgaXQgd2FzIHN1Y2Nlc3NmdWxseQogICAgICBzYXZlZC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IHJlY29yZCA9IHN0b3JlLmNyZWF0ZVJlY29yZCgnbW9kZWwnKTsKICAgICAgcmVjb3JkLmdldCgnaXNOZXcnKTsgLy8gdHJ1ZQogICAgICAgcmVjb3JkLnNhdmUoKS50aGVuKGZ1bmN0aW9uKG1vZGVsKSB7CiAgICAgICAgbW9kZWwuZ2V0KCdpc05ldycpOyAvLyBmYWxzZQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAcHJvcGVydHkgaXNOZXcKICAgICAgQHR5cGUge0Jvb2xlYW59CiAgICAgIEByZWFkT25seQogICAgKi8KICAgIGlzTmV3OiBpc05ld0NQLAoKICAgIC8qKgogICAgICBJZiB0aGlzIHByb3BlcnR5IGlzIGB0cnVlYCB0aGUgcmVjb3JkIGlzIGluIHRoZSBgdmFsaWRgIHN0YXRlLgogICAgICAgQSByZWNvcmQgd2lsbCBiZSBpbiB0aGUgYHZhbGlkYCBzdGF0ZSB3aGVuIHRoZSBhZGFwdGVyIGRpZCBub3QgcmVwb3J0IGFueQogICAgICBzZXJ2ZXItc2lkZSB2YWxpZGF0aW9uIGZhaWx1cmVzLgogICAgICAgQHByb3BlcnR5IGlzVmFsaWQKICAgICAgQHR5cGUge0Jvb2xlYW59CiAgICAgIEByZWFkT25seQogICAgKi8KICAgIGlzVmFsaWQ6IGlzVmFsaWQsCiAgICBfbWFya0ludmFsaWRSZXF1ZXN0QXNDbGVhbjogZnVuY3Rpb24gX21hcmtJbnZhbGlkUmVxdWVzdEFzQ2xlYW4oKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9FUlJPUlMpIHsKICAgICAgICB0aGlzLl9pbnZhbGlkUmVxdWVzdHMgPSBbXTsKCiAgICAgICAgdGhpcy5fbm90aWZ5TmV0d29ya0NoYW5nZXMoKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgSWYgdGhlIHJlY29yZCBpcyBpbiB0aGUgZGlydHkgc3RhdGUgdGhpcyBwcm9wZXJ0eSB3aWxsIHJlcG9ydCB3aGF0CiAgICAgIGtpbmQgb2YgY2hhbmdlIGhhcyBjYXVzZWQgaXQgdG8gbW92ZSBpbnRvIHRoZSBkaXJ0eQogICAgICBzdGF0ZS4gUG9zc2libGUgdmFsdWVzIGFyZToKICAgICAgIC0gYGNyZWF0ZWRgIFRoZSByZWNvcmQgaGFzIGJlZW4gY3JlYXRlZCBieSB0aGUgY2xpZW50IGFuZCBub3QgeWV0IHNhdmVkIHRvIHRoZSBhZGFwdGVyLgogICAgICAtIGB1cGRhdGVkYCBUaGUgcmVjb3JkIGhhcyBiZWVuIHVwZGF0ZWQgYnkgdGhlIGNsaWVudCBhbmQgbm90IHlldCBzYXZlZCB0byB0aGUgYWRhcHRlci4KICAgICAgLSBgZGVsZXRlZGAgVGhlIHJlY29yZCBoYXMgYmVlbiBkZWxldGVkIGJ5IHRoZSBjbGllbnQgYW5kIG5vdCB5ZXQgc2F2ZWQgdG8gdGhlIGFkYXB0ZXIuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCByZWNvcmQgPSBzdG9yZS5jcmVhdGVSZWNvcmQoJ21vZGVsJyk7CiAgICAgIHJlY29yZC5nZXQoJ2RpcnR5VHlwZScpOyAvLyAnY3JlYXRlZCcKICAgICAgYGBgCiAgICAgICBAcHJvcGVydHkgZGlydHlUeXBlCiAgICAgIEB0eXBlIHtTdHJpbmd9CiAgICAgIEByZWFkT25seQogICAgKi8KICAgIGRpcnR5VHlwZTogcmV0cmlldmVGcm9tQ3VycmVudFN0YXRlLAoKICAgIC8qKgogICAgICBJZiBgdHJ1ZWAgdGhlIGFkYXB0ZXIgcmVwb3J0ZWQgdGhhdCBpdCB3YXMgdW5hYmxlIHRvIHNhdmUgbG9jYWwKICAgICAgY2hhbmdlcyB0byB0aGUgYmFja2VuZCBmb3IgYW55IHJlYXNvbiBvdGhlciB0aGFuIGEgc2VydmVyLXNpZGUKICAgICAgdmFsaWRhdGlvbiBlcnJvci4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgcmVjb3JkLmdldCgnaXNFcnJvcicpOyAvLyBmYWxzZQogICAgICByZWNvcmQuc2V0KCdmb28nLCAndmFsaWQgdmFsdWUnKTsKICAgICAgcmVjb3JkLnNhdmUoKS50aGVuKG51bGwsIGZ1bmN0aW9uKCkgewogICAgICAgIHJlY29yZC5nZXQoJ2lzRXJyb3InKTsgLy8gdHJ1ZQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAcHJvcGVydHkgaXNFcnJvcgogICAgICBAdHlwZSB7Qm9vbGVhbn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgaXNFcnJvcjogaXNFcnJvciwKICAgIF9tYXJrRXJyb3JSZXF1ZXN0QXNDbGVhbjogZnVuY3Rpb24gX21hcmtFcnJvclJlcXVlc3RBc0NsZWFuKCkgewogICAgICB0aGlzLl9lcnJvclJlcXVlc3RzID0gW107CiAgICAgIHRoaXMuX2xhc3RFcnJvciA9IG51bGw7CgogICAgICB0aGlzLl9ub3RpZnlOZXR3b3JrQ2hhbmdlcygpOwogICAgfSwKCiAgICAvKioKICAgICAgSWYgYHRydWVgIHRoZSBzdG9yZSBpcyBhdHRlbXB0aW5nIHRvIHJlbG9hZCB0aGUgcmVjb3JkIGZyb20gdGhlIGFkYXB0ZXIuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHJlY29yZC5nZXQoJ2lzUmVsb2FkaW5nJyk7IC8vIGZhbHNlCiAgICAgIHJlY29yZC5yZWxvYWQoKTsKICAgICAgcmVjb3JkLmdldCgnaXNSZWxvYWRpbmcnKTsgLy8gdHJ1ZQogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBpc1JlbG9hZGluZwogICAgICBAdHlwZSB7Qm9vbGVhbn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgaXNSZWxvYWRpbmc6IGlzUmVsb2FkaW5nLAoKICAgIC8qKgogICAgICBBbGwgZW1iZXIgbW9kZWxzIGhhdmUgYW4gaWQgcHJvcGVydHkuIFRoaXMgaXMgYW4gaWRlbnRpZmllcgogICAgICBtYW5hZ2VkIGJ5IGFuIGV4dGVybmFsIHNvdXJjZS4gVGhlc2UgYXJlIGFsd2F5cyBjb2VyY2VkIHRvIGJlCiAgICAgIHN0cmluZ3MgYmVmb3JlIGJlaW5nIHVzZWQgaW50ZXJuYWxseS4gTm90ZSB3aGVuIGRlY2xhcmluZyB0aGUKICAgICAgYXR0cmlidXRlcyBmb3IgYSBtb2RlbCBpdCBpcyBhbiBlcnJvciB0byBkZWNsYXJlIGFuIGlkCiAgICAgIGF0dHJpYnV0ZS4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IHJlY29yZCA9IHN0b3JlLmNyZWF0ZVJlY29yZCgnbW9kZWwnKTsKICAgICAgcmVjb3JkLmdldCgnaWQnKTsgLy8gbnVsbAogICAgICAgc3RvcmUuZmluZFJlY29yZCgnbW9kZWwnLCAxKS50aGVuKGZ1bmN0aW9uKG1vZGVsKSB7CiAgICAgICAgbW9kZWwuZ2V0KCdpZCcpOyAvLyAnMScKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQHByb3BlcnR5IGlkCiAgICAgIEB0eXBlIHtTdHJpbmd9CiAgICAqLwoKICAgIC8qKgogICAgICBAcHJvcGVydHkgY3VycmVudFN0YXRlCiAgICAgIEBwcml2YXRlCiAgICAgIEB0eXBlIHtPYmplY3R9CiAgICAqLwogICAgY3VycmVudFN0YXRlOiBQcml2YXRlLlJvb3RTdGF0ZS5lbXB0eSwKICAgIC8vIGRlZmluZWQgaGVyZSB0byBhdm9pZCB0cmlnZ2VyaW5nIHNldFVua25vd25Qcm9wZXJ0eQoKICAgIC8qKgogICAgIEBwcm9wZXJ0eSBfaW50ZXJuYWxNb2RlbAogICAgIEBwcml2YXRlCiAgICAgQHR5cGUge09iamVjdH0KICAgICAqLwogICAgX2ludGVybmFsTW9kZWw6IG51bGwsCiAgICAvLyBkZWZpbmVkIGhlcmUgdG8gYXZvaWQgdHJpZ2dlcmluZyBzZXRVbmtub3duUHJvcGVydHkKCiAgICAvKioKICAgICBAcHJvcGVydHkgcmVjb3JkRGF0YQogICAgIEBwcml2YXRlCiAgICAgQHR5cGUgdW5kZWZpbmVkIChyZXNlcnZlZCkKICAgICAqLwogICAgLy8gd2lsbCBiZSBkZWZpbmVkIGhlcmUgdG8gYXZvaWQgdHJpZ2dlcmluZyBzZXRVbmtub3duUHJvcGVydHkKCiAgICAvKioKICAgICBAcHJvcGVydHkgc3RvcmUKICAgICAqLwogICAgc3RvcmU6IG51bGwsCiAgICAvLyBkZWZpbmVkIGhlcmUgdG8gYXZvaWQgdHJpZ2dlcmluZyBzZXRVbmtub3duUHJvcGVydHkKCiAgICAvKioKICAgICAgV2hlbiB0aGUgcmVjb3JkIGlzIGluIHRoZSBgaW52YWxpZGAgc3RhdGUgdGhpcyBvYmplY3Qgd2lsbCBjb250YWluCiAgICAgIGFueSBlcnJvcnMgcmV0dXJuZWQgYnkgdGhlIGFkYXB0ZXIuIFdoZW4gcHJlc2VudCB0aGUgZXJyb3JzIGhhc2gKICAgICAgY29udGFpbnMga2V5cyBjb3JyZXNwb25kaW5nIHRvIHRoZSBpbnZhbGlkIHByb3BlcnR5IG5hbWVzCiAgICAgIGFuZCB2YWx1ZXMgd2hpY2ggYXJlIGFycmF5cyBvZiBKYXZhc2NyaXB0IG9iamVjdHMgd2l0aCB0d28ga2V5czoKICAgICAgIC0gYG1lc3NhZ2VgIEEgc3RyaW5nIGNvbnRhaW5pbmcgdGhlIGVycm9yIG1lc3NhZ2UgZnJvbSB0aGUgYmFja2VuZAogICAgICAtIGBhdHRyaWJ1dGVgIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSBhc3NvY2lhdGVkIHdpdGggdGhpcyBlcnJvciBtZXNzYWdlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHJlY29yZC5nZXQoJ2Vycm9ycy5sZW5ndGgnKTsgLy8gMAogICAgICByZWNvcmQuc2V0KCdmb28nLCAnaW52YWxpZCB2YWx1ZScpOwogICAgICByZWNvcmQuc2F2ZSgpLmNhdGNoKGZ1bmN0aW9uKCkgewogICAgICAgIHJlY29yZC5nZXQoJ2Vycm9ycycpLmdldCgnZm9vJyk7CiAgICAgICAgLy8gW3ttZXNzYWdlOiAnZm9vIHNob3VsZCBiZSBhIG51bWJlci4nLCBhdHRyaWJ1dGU6ICdmb28nfV0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVGhlIGBlcnJvcnNgIHByb3BlcnR5IHVzIHVzZWZ1bCBmb3IgZGlzcGxheWluZyBlcnJvciBtZXNzYWdlcyB0bwogICAgICB0aGUgdXNlci4KICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPGxhYmVsPlVzZXJuYW1lOiB7e2lucHV0IHZhbHVlPXVzZXJuYW1lfX0gPC9sYWJlbD4KICAgICAge3sjZWFjaCBtb2RlbC5lcnJvcnMudXNlcm5hbWUgYXMgfGVycm9yfH19CiAgICAgICAgPGRpdiBjbGFzcz0iZXJyb3IiPgogICAgICAgICAge3tlcnJvci5tZXNzYWdlfX0KICAgICAgICA8L2Rpdj4KICAgICAge3svZWFjaH19CiAgICAgIDxsYWJlbD5FbWFpbDoge3tpbnB1dCB2YWx1ZT1lbWFpbH19IDwvbGFiZWw+CiAgICAgIHt7I2VhY2ggbW9kZWwuZXJyb3JzLmVtYWlsIGFzIHxlcnJvcnx9fQogICAgICAgIDxkaXYgY2xhc3M9ImVycm9yIj4KICAgICAgICAgIHt7ZXJyb3IubWVzc2FnZX19CiAgICAgICAgPC9kaXY+CiAgICAgIHt7L2VhY2h9fQogICAgICBgYGAKICAgICAgICBZb3UgY2FuIGFsc28gYWNjZXNzIHRoZSBzcGVjaWFsIGBtZXNzYWdlc2AgcHJvcGVydHkgb24gdGhlIGVycm9yCiAgICAgIG9iamVjdCB0byBnZXQgYW4gYXJyYXkgb2YgYWxsIHRoZSBlcnJvciBzdHJpbmdzLgogICAgICAgYGBgaGFuZGxlYmFycwogICAgICB7eyNlYWNoIG1vZGVsLmVycm9ycy5tZXNzYWdlcyBhcyB8bWVzc2FnZXx9fQogICAgICAgIDxkaXYgY2xhc3M9ImVycm9yIj4KICAgICAgICAgIHt7bWVzc2FnZX19CiAgICAgICAgPC9kaXY+CiAgICAgIHt7L2VhY2h9fQogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBlcnJvcnMKICAgICAgQHR5cGUge0Vycm9yc30KICAgICovCiAgICBlcnJvcnM6IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIF90aGlzMyA9IHRoaXM7CgogICAgICB2YXIgZXJyb3JzID0gUHJpdmF0ZS5FcnJvcnMuY3JlYXRlKCk7CgogICAgICBlcnJvcnMuX3JlZ2lzdGVySGFuZGxlcnMoZnVuY3Rpb24gKCkgewogICAgICAgIF90aGlzMy5zZW5kKCdiZWNhbWVJbnZhbGlkJyk7CiAgICAgIH0sIGZ1bmN0aW9uICgpIHsKICAgICAgICBfdGhpczMuc2VuZCgnYmVjYW1lVmFsaWQnKTsKICAgICAgfSk7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfRVJST1JTKSB7CiAgICAgICAgdmFyIHJlY29yZERhdGEgPSBQcml2YXRlLnJlY29yZERhdGFGb3IodGhpcyk7CiAgICAgICAgdmFyIGpzb25BcGlFcnJvcnM7CgogICAgICAgIGlmIChyZWNvcmREYXRhLmdldEVycm9ycykgewogICAgICAgICAganNvbkFwaUVycm9ycyA9IHJlY29yZERhdGEuZ2V0RXJyb3JzKCk7CgogICAgICAgICAgaWYgKGpzb25BcGlFcnJvcnMpIHsKICAgICAgICAgICAgdmFyIGVycm9yc0hhc2ggPSBQcml2YXRlLmVycm9yc0FycmF5VG9IYXNoKGpzb25BcGlFcnJvcnMpOwogICAgICAgICAgICB2YXIgZXJyb3JLZXlzID0gT2JqZWN0LmtleXMoZXJyb3JzSGFzaCk7CgogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVycm9yS2V5cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgIGVycm9ycy5fYWRkKGVycm9yS2V5c1tpXSwgZXJyb3JzSGFzaFtlcnJvcktleXNbaV1dKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGVycm9yczsKICAgIH0pLnJlYWRPbmx5KCksCiAgICBpbnZhbGlkRXJyb3JzQ2hhbmdlZDogZnVuY3Rpb24gaW52YWxpZEVycm9yc0NoYW5nZWQoanNvbkFwaUVycm9ycykgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfRVJST1JTKSB7CiAgICAgICAgdGhpcy5fY2xlYXJFcnJvck1lc3NhZ2VzKCk7CgogICAgICAgIHZhciBlcnJvcnMgPSBQcml2YXRlLmVycm9yc0FycmF5VG9IYXNoKGpzb25BcGlFcnJvcnMpOwogICAgICAgIHZhciBlcnJvcktleXMgPSBPYmplY3Qua2V5cyhlcnJvcnMpOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVycm9yS2V5cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgdGhpcy5fYWRkRXJyb3JNZXNzYWdlVG9BdHRyaWJ1dGUoZXJyb3JLZXlzW2ldLCBlcnJvcnNbZXJyb3JLZXlzW2ldXSk7CiAgICAgICAgfQogICAgICB9CiAgICB9LAogICAgX2FkZEVycm9yTWVzc2FnZVRvQXR0cmlidXRlOiBmdW5jdGlvbiBfYWRkRXJyb3JNZXNzYWdlVG9BdHRyaWJ1dGUoYXR0cmlidXRlLCBtZXNzYWdlKSB7CiAgICAgIHRoaXMuZ2V0KCdlcnJvcnMnKS5fYWRkKGF0dHJpYnV0ZSwgbWVzc2FnZSk7CiAgICB9LAogICAgX2NsZWFyRXJyb3JNZXNzYWdlczogZnVuY3Rpb24gX2NsZWFyRXJyb3JNZXNzYWdlcygpIHsKICAgICAgdGhpcy5nZXQoJ2Vycm9ycycpLl9jbGVhcigpOwogICAgfSwKCiAgICAvKioKICAgICAgVGhpcyBwcm9wZXJ0eSBob2xkcyB0aGUgYEFkYXB0ZXJFcnJvcmAgb2JqZWN0IHdpdGggd2hpY2gKICAgICAgbGFzdCBhZGFwdGVyIG9wZXJhdGlvbiB3YXMgcmVqZWN0ZWQuCiAgICAgICBAcHJvcGVydHkgYWRhcHRlckVycm9yCiAgICAgIEB0eXBlIHtBZGFwdGVyRXJyb3J9CiAgICAqLwogICAgYWRhcHRlckVycm9yOiBhZGFwdGVyRXJyb3IsCgogICAgLyoqCiAgICAgIENyZWF0ZSBhIEpTT04gcmVwcmVzZW50YXRpb24gb2YgdGhlIHJlY29yZCwgdXNpbmcgdGhlIHNlcmlhbGl6YXRpb24KICAgICAgc3RyYXRlZ3kgb2YgdGhlIHN0b3JlJ3MgYWRhcHRlci4KICAgICAgYHNlcmlhbGl6ZWAgdGFrZXMgYW4gb3B0aW9uYWwgaGFzaCBhcyBhIHBhcmFtZXRlciwgY3VycmVudGx5CiAgICAgIHN1cHBvcnRlZCBvcHRpb25zIGFyZToKICAgICAgLSBgaW5jbHVkZUlkYDogYHRydWVgIGlmIHRoZSByZWNvcmQncyBJRCBzaG91bGQgYmUgaW5jbHVkZWQgaW4gdGhlCiAgICAgICAgSlNPTiByZXByZXNlbnRhdGlvbi4KICAgICAgIEBtZXRob2Qgc2VyaWFsaXplCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgIEByZXR1cm4ge09iamVjdH0gYW4gb2JqZWN0IHdob3NlIHZhbHVlcyBhcmUgcHJpbWl0aXZlIEpTT04gdmFsdWVzIG9ubHkKICAgICovCiAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIHNlcmlhbGl6ZShvcHRpb25zKSB7CiAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsLmNyZWF0ZVNuYXBzaG90KCkuc2VyaWFsaXplKG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICAgVXNlIFtKU09OU2VyaWFsaXplcl0oSlNPTlNlcmlhbGl6ZXIuaHRtbCkgdG8KICAgICAgZ2V0IHRoZSBKU09OIHJlcHJlc2VudGF0aW9uIG9mIGEgcmVjb3JkLgogICAgICAgYHRvSlNPTmAgdGFrZXMgYW4gb3B0aW9uYWwgaGFzaCBhcyBhIHBhcmFtZXRlciwgY3VycmVudGx5CiAgICAgIHN1cHBvcnRlZCBvcHRpb25zIGFyZToKICAgICAgIC0gYGluY2x1ZGVJZGA6IGB0cnVlYCBpZiB0aGUgcmVjb3JkJ3MgSUQgc2hvdWxkIGJlIGluY2x1ZGVkIGluIHRoZQogICAgICAgIEpTT04gcmVwcmVzZW50YXRpb24uCiAgICAgICBAbWV0aG9kIHRvSlNPTgogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgICBAcmV0dXJuIHtPYmplY3R9IEEgSlNPTiByZXByZXNlbnRhdGlvbiBvZiB0aGUgb2JqZWN0LgogICAgKi8KICAgIHRvSlNPTjogZnVuY3Rpb24gdG9KU09OKG9wdGlvbnMpIHsKCiAgICAgIHZhciBzZXJpYWxpemVyID0gdGhpcy5faW50ZXJuYWxNb2RlbC5zdG9yZS5zZXJpYWxpemVyRm9yKCctZGVmYXVsdCcpOwoKICAgICAgdmFyIHNuYXBzaG90ID0gdGhpcy5faW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdCgpOwoKICAgICAgcmV0dXJuIHNlcmlhbGl6ZXIuc2VyaWFsaXplKHNuYXBzaG90LCBvcHRpb25zKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEZpcmVkIHdoZW4gdGhlIHJlY29yZCBpcyByZWFkeSB0byBiZSBpbnRlcmFjdGVkIHdpdGgsCiAgICAgIHRoYXQgaXMgZWl0aGVyIGxvYWRlZCBmcm9tIHRoZSBzZXJ2ZXIgb3IgY3JlYXRlZCBsb2NhbGx5LgogICAgICAgQGV2ZW50IHJlYWR5CiAgICAqLwogICAgcmVhZHk6IG51bGwsCgogICAgLyoqCiAgICAgIEZpcmVkIHdoZW4gdGhlIHJlY29yZCBpcyBsb2FkZWQgZnJvbSB0aGUgc2VydmVyLgogICAgICAgQGV2ZW50IGRpZExvYWQKICAgICovCiAgICBkaWRMb2FkOiBudWxsLAoKICAgIC8qKgogICAgICBGaXJlZCB3aGVuIHRoZSByZWNvcmQgaXMgdXBkYXRlZC4KICAgICAgIEBldmVudCBkaWRVcGRhdGUKICAgICovCiAgICBkaWRVcGRhdGU6IG51bGwsCgogICAgLyoqCiAgICAgIEZpcmVkIHdoZW4gYSBuZXcgcmVjb3JkIGlzIGNvbW1pdGVkIHRvIHRoZSBzZXJ2ZXIuCiAgICAgICBAZXZlbnQgZGlkQ3JlYXRlCiAgICAqLwogICAgZGlkQ3JlYXRlOiBudWxsLAoKICAgIC8qKgogICAgICBGaXJlZCB3aGVuIHRoZSByZWNvcmQgaXMgZGVsZXRlZC4KICAgICAgIEBldmVudCBkaWREZWxldGUKICAgICovCiAgICBkaWREZWxldGU6IG51bGwsCgogICAgLyoqCiAgICAgIEZpcmVkIHdoZW4gdGhlIHJlY29yZCBiZWNvbWVzIGludmFsaWQuCiAgICAgICBAZXZlbnQgYmVjYW1lSW52YWxpZAogICAgKi8KICAgIGJlY2FtZUludmFsaWQ6IG51bGwsCgogICAgLyoqCiAgICAgIEZpcmVkIHdoZW4gdGhlIHJlY29yZCBlbnRlcnMgdGhlIGVycm9yIHN0YXRlLgogICAgICAgQGV2ZW50IGJlY2FtZUVycm9yCiAgICAqLwogICAgYmVjYW1lRXJyb3I6IG51bGwsCgogICAgLyoqCiAgICAgIEZpcmVkIHdoZW4gdGhlIHJlY29yZCBpcyByb2xsZWQgYmFjay4KICAgICAgIEBldmVudCByb2xsZWRCYWNrCiAgICAqLwogICAgcm9sbGVkQmFjazogbnVsbCwKICAgIC8vVE9ETyBEbyB3ZSB3YW50IHRvIGRlcHJlY2F0ZSB0aGVzZT8KCiAgICAvKioKICAgICAgQG1ldGhvZCBzZW5kCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBjb250ZXh0CiAgICAqLwogICAgc2VuZDogZnVuY3Rpb24gc2VuZChuYW1lLCBjb250ZXh0KSB7CiAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsLnNlbmQobmFtZSwgY29udGV4dCk7CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIHRyYW5zaXRpb25UbwogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZQogICAgKi8KICAgIHRyYW5zaXRpb25UbzogZnVuY3Rpb24gdHJhbnNpdGlvblRvKG5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXMuX2ludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKG5hbWUpOwogICAgfSwKCiAgICAvKioKICAgICAgTWFya3MgdGhlIHJlY29yZCBhcyBkZWxldGVkIGJ1dCBkb2VzIG5vdCBzYXZlIGl0LiBZb3UgbXVzdCBjYWxsCiAgICAgIGBzYXZlYCBhZnRlcndhcmRzIGlmIHlvdSB3YW50IHRvIHBlcnNpc3QgaXQuIFlvdSBtaWdodCB1c2UgdGhpcwogICAgICBtZXRob2QgaWYgeW91IHdhbnQgdG8gYWxsb3cgdGhlIHVzZXIgdG8gc3RpbGwgYHJvbGxiYWNrQXR0cmlidXRlcygpYAogICAgICBhZnRlciBhIGRlbGV0ZSB3YXMgbWFkZS4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9yb3V0ZXMvbW9kZWwvZGVsZXRlLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHNvZnREZWxldGUoKSB7CiAgICAgICAgICAgIHRoaXMuZ2V0KCdjb250cm9sbGVyLm1vZGVsJykuZGVsZXRlUmVjb3JkKCk7CiAgICAgICAgICB9LAogICAgICAgICAgY29uZmlybSgpIHsKICAgICAgICAgICAgdGhpcy5nZXQoJ2NvbnRyb2xsZXIubW9kZWwnKS5zYXZlKCk7CiAgICAgICAgICB9LAogICAgICAgICAgdW5kbygpIHsKICAgICAgICAgICAgdGhpcy5nZXQoJ2NvbnRyb2xsZXIubW9kZWwnKS5yb2xsYmFja0F0dHJpYnV0ZXMoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZGVsZXRlUmVjb3JkCiAgICAqLwogICAgZGVsZXRlUmVjb3JkOiBmdW5jdGlvbiBkZWxldGVSZWNvcmQoKSB7CiAgICAgIHRoaXMuX2ludGVybmFsTW9kZWwuZGVsZXRlUmVjb3JkKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBTYW1lIGFzIGBkZWxldGVSZWNvcmRgLCBidXQgc2F2ZXMgdGhlIHJlY29yZCBpbW1lZGlhdGVseS4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9yb3V0ZXMvbW9kZWwvZGVsZXRlLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIGRlbGV0ZSgpIHsKICAgICAgICAgICAgdGhpcy5nZXQoJ2NvbnRyb2xsZXIubW9kZWwnKS5kZXN0cm95UmVjb3JkKCkudGhlbihmdW5jdGlvbigpIHsKICAgICAgICAgICAgICBjb250cm9sbGVyLnRyYW5zaXRpb25Ub1JvdXRlKCdtb2RlbC5pbmRleCcpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIElmIHlvdSBwYXNzIGFuIG9iamVjdCBvbiB0aGUgYGFkYXB0ZXJPcHRpb25zYCBwcm9wZXJ0eSBvZiB0aGUgb3B0aW9ucwogICAgICBhcmd1bWVudCBpdCB3aWxsIGJlIHBhc3NlZCB0byB5b3VyIGFkYXB0ZXIgdmlhIHRoZSBzbmFwc2hvdAogICAgICAgYGBganMKICAgICAgcmVjb3JkLmRlc3Ryb3lSZWNvcmQoeyBhZGFwdGVyT3B0aW9uczogeyBzdWJzY3JpYmU6IGZhbHNlIH0gfSk7CiAgICAgIGBgYAogICAgICAgYGBgYXBwL2FkYXB0ZXJzL3Bvc3QuanMKICAgICAgaW1wb3J0IE15Q3VzdG9tQWRhcHRlciBmcm9tICcuL2N1c3RvbS1hZGFwdGVyJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IE15Q3VzdG9tQWRhcHRlci5leHRlbmQoewogICAgICAgIGRlbGV0ZVJlY29yZChzdG9yZSwgdHlwZSwgc25hcHNob3QpIHsKICAgICAgICAgIGlmIChzbmFwc2hvdC5hZGFwdGVyT3B0aW9ucy5zdWJzY3JpYmUpIHsKICAgICAgICAgICAgLy8gLi4uCiAgICAgICAgICB9CiAgICAgICAgICAvLyAuLi4KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZGVzdHJveVJlY29yZAogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgICBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCB3aWxsIGJlIHJlc29sdmVkIHdoZW4gdGhlIGFkYXB0ZXIgcmV0dXJucwogICAgICBzdWNjZXNzZnVsbHkgb3IgcmVqZWN0ZWQgaWYgdGhlIGFkYXB0ZXIgcmV0dXJucyB3aXRoIGFuIGVycm9yLgogICAgKi8KICAgIGRlc3Ryb3lSZWNvcmQ6IGZ1bmN0aW9uIGRlc3Ryb3lSZWNvcmQob3B0aW9ucykgewogICAgICB0aGlzLmRlbGV0ZVJlY29yZCgpOwogICAgICByZXR1cm4gdGhpcy5zYXZlKG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICAgVW5sb2FkcyB0aGUgcmVjb3JkIGZyb20gdGhlIHN0b3JlLiBUaGlzIHdpbGwgbm90IHNlbmQgYSBkZWxldGUgcmVxdWVzdAogICAgICB0byB5b3VyIHNlcnZlciwgaXQganVzdCB1bmxvYWRzIHRoZSByZWNvcmQgZnJvbSBtZW1vcnkuCiAgICAgICBAbWV0aG9kIHVubG9hZFJlY29yZAogICAgKi8KICAgIHVubG9hZFJlY29yZDogZnVuY3Rpb24gdW5sb2FkUmVjb3JkKCkgewogICAgICBpZiAodGhpcy5pc0Rlc3Ryb3llZCkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5faW50ZXJuYWxNb2RlbC51bmxvYWRSZWNvcmQoKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBtZXRob2QgX25vdGlmeVByb3BlcnRpZXMKICAgICAgQHByaXZhdGUKICAgICovCiAgICBfbm90aWZ5UHJvcGVydGllczogZnVuY3Rpb24gX25vdGlmeVByb3BlcnRpZXMoa2V5cykgewogICAgICB2YXIgX3RoaXM0ID0gdGhpczsKCiAgICAgIC8vIGNoYW5nZVByb3BlcnRpZXMgZGVmZXJzIG5vdGlmaWNhdGlvbnMgdW50aWwgYWZ0ZXIgdGhlIGRlbGVnYXRlCiAgICAgIC8vIGFuZCBwcm90ZWN0cyB3aXRoIGEgdHJ5Li4uZmluYWxseSBibG9jawogICAgICAvLyBwcmV2aW91c2x5IHVzZWQgYmVnaW4uLi5lbmRQcm9wZXJ0eUNoYW5nZXMgYnV0IHRoaXMgaXMgcHJpdmF0ZSBBUEkKICAgICAgY2hhbmdlUHJvcGVydGllcyhmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIGtleTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGtleSA9IGtleXNbaV07CgogICAgICAgICAgX3RoaXM0Lm5vdGlmeVByb3BlcnR5Q2hhbmdlKGtleSk7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIFJldHVybnMgYW4gb2JqZWN0LCB3aG9zZSBrZXlzIGFyZSBjaGFuZ2VkIHByb3BlcnRpZXMsIGFuZCB2YWx1ZSBpcwogICAgICBhbiBbb2xkUHJvcCwgbmV3UHJvcF0gYXJyYXkuCiAgICAgICBUaGUgYXJyYXkgcmVwcmVzZW50cyB0aGUgZGlmZiBvZiB0aGUgY2Fub25pY2FsIHN0YXRlIHdpdGggdGhlIGxvY2FsIHN0YXRlCiAgICAgIG9mIHRoZSBtb2RlbC4gTm90ZTogaWYgdGhlIG1vZGVsIGlzIGNyZWF0ZWQgbG9jYWxseSwgdGhlIGNhbm9uaWNhbCBzdGF0ZSBpcwogICAgICBlbXB0eSBzaW5jZSB0aGUgYWRhcHRlciBoYXNuJ3QgYWNrbm93bGVkZ2VkIHRoZSBhdHRyaWJ1dGVzIHlldDoKICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9tb2RlbHMvbWFzY290LmpzCiAgICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICBuYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgICBpc0FkbWluOiBhdHRyKCdib29sZWFuJywgewogICAgICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZQogICAgICAgIH0pCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IG1hc2NvdCA9IHN0b3JlLmNyZWF0ZVJlY29yZCgnbWFzY290Jyk7CiAgICAgICBtYXNjb3QuY2hhbmdlZEF0dHJpYnV0ZXMoKTsgLy8ge30KICAgICAgIG1hc2NvdC5zZXQoJ25hbWUnLCAnVG9tc3RlcicpOwogICAgICBtYXNjb3QuY2hhbmdlZEF0dHJpYnV0ZXMoKTsgLy8geyBuYW1lOiBbdW5kZWZpbmVkLCAnVG9tc3RlciddIH0KICAgICAgIG1hc2NvdC5zZXQoJ2lzQWRtaW4nLCB0cnVlKTsKICAgICAgbWFzY290LmNoYW5nZWRBdHRyaWJ1dGVzKCk7IC8vIHsgaXNBZG1pbjogW3VuZGVmaW5lZCwgdHJ1ZV0sIG5hbWU6IFt1bmRlZmluZWQsICdUb21zdGVyJ10gfQogICAgICAgbWFzY290LnNhdmUoKS50aGVuKGZ1bmN0aW9uKCkgewogICAgICAgIG1hc2NvdC5jaGFuZ2VkQXR0cmlidXRlcygpOyAvLyB7fQogICAgICAgICBtYXNjb3Quc2V0KCdpc0FkbWluJywgZmFsc2UpOwogICAgICAgIG1hc2NvdC5jaGFuZ2VkQXR0cmlidXRlcygpOyAvLyB7IGlzQWRtaW46IFt0cnVlLCBmYWxzZV0gfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGNoYW5nZWRBdHRyaWJ1dGVzCiAgICAgIEByZXR1cm4ge09iamVjdH0gYW4gb2JqZWN0LCB3aG9zZSBrZXlzIGFyZSBjaGFuZ2VkIHByb3BlcnRpZXMsCiAgICAgICAgYW5kIHZhbHVlIGlzIGFuIFtvbGRQcm9wLCBuZXdQcm9wXSBhcnJheS4KICAgICovCiAgICBjaGFuZ2VkQXR0cmlidXRlczogZnVuY3Rpb24gY2hhbmdlZEF0dHJpYnV0ZXMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsLmNoYW5nZWRBdHRyaWJ1dGVzKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBJZiB0aGUgbW9kZWwgYGhhc0RpcnR5QXR0cmlidXRlc2AgdGhpcyBmdW5jdGlvbiB3aWxsIGRpc2NhcmQgYW55IHVuc2F2ZWQKICAgICAgY2hhbmdlcy4gSWYgdGhlIG1vZGVsIGBpc05ld2AgaXQgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIHN0b3JlLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICByZWNvcmQuZ2V0KCduYW1lJyk7IC8vICdVbnRpdGxlZCBEb2N1bWVudCcKICAgICAgcmVjb3JkLnNldCgnbmFtZScsICdEb2MgMScpOwogICAgICByZWNvcmQuZ2V0KCduYW1lJyk7IC8vICdEb2MgMScKICAgICAgcmVjb3JkLnJvbGxiYWNrQXR0cmlidXRlcygpOwogICAgICByZWNvcmQuZ2V0KCduYW1lJyk7IC8vICdVbnRpdGxlZCBEb2N1bWVudCcKICAgICAgYGBgCiAgICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgcm9sbGJhY2tBdHRyaWJ1dGVzCiAgICAqLwogICAgcm9sbGJhY2tBdHRyaWJ1dGVzOiBmdW5jdGlvbiByb2xsYmFja0F0dHJpYnV0ZXMoKSB7CiAgICAgIHRoaXMuX2ludGVybmFsTW9kZWwucm9sbGJhY2tBdHRyaWJ1dGVzKCk7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfRVJST1JTKSB7CiAgICAgICAgdGhpcy5fbWFya0ludmFsaWRSZXF1ZXN0QXNDbGVhbigpOwogICAgICB9CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgdGhpcy5fbWFya0Vycm9yUmVxdWVzdEFzQ2xlYW4oKTsKICAgICAgfQogICAgfSwKCiAgICAvKgogICAgICBAbWV0aG9kIF9jcmVhdGVTbmFwc2hvdAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9jcmVhdGVTbmFwc2hvdDogZnVuY3Rpb24gX2NyZWF0ZVNuYXBzaG90KCkgewogICAgICByZXR1cm4gdGhpcy5faW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdCgpOwogICAgfSwKICAgIHRvU3RyaW5nRXh0ZW5zaW9uOiBmdW5jdGlvbiB0b1N0cmluZ0V4dGVuc2lvbigpIHsKICAgICAgLy8gdGhlIF9pbnRlcm5hbE1vZGVsIGd1YXJkIGV4aXN0cywgYmVjYXVzZSBzb21lIGRldi1vbmx5IGRlcHJlY2F0aW9uIGNvZGUKICAgICAgLy8gKGFkZExpc3RlbmVyIHZpYSB2YWxpZGF0ZVByb3BlcnR5SW5qZWN0aW9ucykgaW52b2tlcyB0b1N0cmluZyBiZWZvcmUgdGhlCiAgICAgIC8vIG9iamVjdCBpcyByZWFsLgogICAgICByZXR1cm4gdGhpcy5faW50ZXJuYWxNb2RlbCAmJiB0aGlzLl9pbnRlcm5hbE1vZGVsLmlkOwogICAgfSwKCiAgICAvKioKICAgICAgU2F2ZSB0aGUgcmVjb3JkIGFuZCBwZXJzaXN0IGFueSBjaGFuZ2VzIHRvIHRoZSByZWNvcmQgdG8gYW4KICAgICAgZXh0ZXJuYWwgc291cmNlIHZpYSB0aGUgYWRhcHRlci4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgcmVjb3JkLnNldCgnbmFtZScsICdUb21zdGVyJyk7CiAgICAgIHJlY29yZC5zYXZlKCkudGhlbihmdW5jdGlvbigpIHsKICAgICAgICAvLyBTdWNjZXNzIGNhbGxiYWNrCiAgICAgIH0sIGZ1bmN0aW9uKCkgewogICAgICAgIC8vIEVycm9yIGNhbGxiYWNrCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgSWYgeW91IHBhc3MgYW4gb2JqZWN0IHVzaW5nIHRoZSBgYWRhcHRlck9wdGlvbnNgIHByb3BlcnR5IG9mIHRoZSBvcHRpb25zCiAgICAgYXJndW1lbnQgaXQgd2lsbCBiZSBwYXNzZWQgdG8geW91ciBhZGFwdGVyIHZpYSB0aGUgc25hcHNob3QuCiAgICAgICBgYGBqcwogICAgICByZWNvcmQuc2F2ZSh7IGFkYXB0ZXJPcHRpb25zOiB7IHN1YnNjcmliZTogZmFsc2UgfSB9KTsKICAgICAgYGBgCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvcG9zdC5qcwogICAgICBpbXBvcnQgTXlDdXN0b21BZGFwdGVyIGZyb20gJy4vY3VzdG9tLWFkYXB0ZXInOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTXlDdXN0b21BZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgdXBkYXRlUmVjb3JkKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCkgewogICAgICAgICAgaWYgKHNuYXBzaG90LmFkYXB0ZXJPcHRpb25zLnN1YnNjcmliZSkgewogICAgICAgICAgICAvLyAuLi4KICAgICAgICAgIH0KICAgICAgICAgIC8vIC4uLgogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzYXZlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IHdpbGwgYmUgcmVzb2x2ZWQgd2hlbiB0aGUgYWRhcHRlciByZXR1cm5zCiAgICAgIHN1Y2Nlc3NmdWxseSBvciByZWplY3RlZCBpZiB0aGUgYWRhcHRlciByZXR1cm5zIHdpdGggYW4gZXJyb3IuCiAgICAqLwogICAgc2F2ZTogZnVuY3Rpb24gc2F2ZShvcHRpb25zKSB7CiAgICAgIHZhciBfdGhpczUgPSB0aGlzOwoKICAgICAgcmV0dXJuIFByaXZhdGUuUHJvbWlzZU9iamVjdC5jcmVhdGUoewogICAgICAgIHByb21pc2U6IHRoaXMuX2ludGVybmFsTW9kZWwuc2F2ZShvcHRpb25zKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBfdGhpczU7CiAgICAgICAgfSkKICAgICAgfSk7CiAgICB9LAoKICAgIC8qKgogICAgICBSZWxvYWQgdGhlIHJlY29yZCBmcm9tIHRoZSBhZGFwdGVyLgogICAgICAgVGhpcyB3aWxsIG9ubHkgd29yayBpZiB0aGUgcmVjb3JkIGhhcyBhbHJlYWR5IGZpbmlzaGVkIGxvYWRpbmcuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvcm91dGVzL21vZGVsL3ZpZXcuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgcmVsb2FkKCkgewogICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZ2V0KCdtb2RlbCcpLnJlbG9hZCgpLnRoZW4oZnVuY3Rpb24obW9kZWwpIHsKICAgICAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgd2l0aCB0aGUgcmVsb2FkZWQgbW9kZWwKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHJlbG9hZAogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBvcHRpb25hbCwgbWF5IGluY2x1ZGUgYGFkYXB0ZXJPcHRpb25zYCBoYXNoIHdoaWNoIHdpbGwgYmUgcGFzc2VkIHRvIGFkYXB0ZXIgcmVxdWVzdAogICAgICBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCB3aWxsIGJlIHJlc29sdmVkIHdpdGggdGhlIHJlY29yZCB3aGVuIHRoZQogICAgICBhZGFwdGVyIHJldHVybnMgc3VjY2Vzc2Z1bGx5IG9yIHJlamVjdGVkIGlmIHRoZSBhZGFwdGVyIHJldHVybnMKICAgICAgd2l0aCBhbiBlcnJvci4KICAgICovCiAgICByZWxvYWQ6IGZ1bmN0aW9uIHJlbG9hZChvcHRpb25zKSB7CiAgICAgIHZhciBfdGhpczYgPSB0aGlzOwoKICAgICAgdmFyIHdyYXBwZWRBZGFwdGVyT3B0aW9uczsKCiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ29iamVjdCcgJiYgb3B0aW9ucyAhPT0gbnVsbCAmJiBvcHRpb25zLmFkYXB0ZXJPcHRpb25zKSB7CiAgICAgICAgd3JhcHBlZEFkYXB0ZXJPcHRpb25zID0gewogICAgICAgICAgYWRhcHRlck9wdGlvbnM6IG9wdGlvbnMuYWRhcHRlck9wdGlvbnMKICAgICAgICB9OwogICAgICB9CgogICAgICByZXR1cm4gUHJpdmF0ZS5Qcm9taXNlT2JqZWN0LmNyZWF0ZSh7CiAgICAgICAgcHJvbWlzZTogdGhpcy5faW50ZXJuYWxNb2RlbC5yZWxvYWQod3JhcHBlZEFkYXB0ZXJPcHRpb25zKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBfdGhpczY7CiAgICAgICAgfSkKICAgICAgfSk7CiAgICB9LAoKICAgIC8qKgogICAgICBPdmVycmlkZSB0aGUgZGVmYXVsdCBldmVudCBmaXJpbmcgZnJvbSBFbWJlci5FdmVudGVkIHRvCiAgICAgIGFsc28gY2FsbCBtZXRob2RzIHdpdGggdGhlIGdpdmVuIG5hbWUuCiAgICAgICBAbWV0aG9kIHRyaWdnZXIKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUKICAgICovCiAgICB0cmlnZ2VyOiBmdW5jdGlvbiB0cmlnZ2VyKG5hbWUpIHsKICAgICAgdmFyIGZuID0gdGhpc1tuYW1lXTsKCiAgICAgIGlmICh0eXBlb2YgZm4gPT09ICdmdW5jdGlvbicpIHsKICAgICAgICB2YXIgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aDsKICAgICAgICB2YXIgYXJncyA9IG5ldyBBcnJheShsZW5ndGggLSAxKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07CiAgICAgICAgfQoKICAgICAgICBmbi5hcHBseSh0aGlzLCBhcmdzKTsKICAgICAgfQoKICAgICAgdmFyIF9oYXNFdmVudCA9ICB0aGlzLmhhcyhuYW1lKTsKCiAgICAgIGlmIChfaGFzRXZlbnQpIHsKICAgICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgICB9CiAgICB9LAogICAgYXR0cjogZnVuY3Rpb24gYXR0cigpIHsKICAgIH0sCgogICAgLyoqCiAgICAgIEdldCB0aGUgcmVmZXJlbmNlIGZvciB0aGUgc3BlY2lmaWVkIGJlbG9uZ3NUbyByZWxhdGlvbnNoaXAuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvbW9kZWxzL2Jsb2cuanMKICAgICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdXNlcjogYmVsb25nc1RvKHsgYXN5bmM6IHRydWUgfSkKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgYmxvZyA9IHN0b3JlLnB1c2goewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIHR5cGU6ICdibG9nJywKICAgICAgICAgIGlkOiAxLAogICAgICAgICAgcmVsYXRpb25zaGlwczogewogICAgICAgICAgICB1c2VyOiB7CiAgICAgICAgICAgICAgZGF0YTogeyB0eXBlOiAndXNlcicsIGlkOiAxIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGxldCB1c2VyUmVmID0gYmxvZy5iZWxvbmdzVG8oJ3VzZXInKTsKICAgICAgIC8vIGNoZWNrIGlmIHRoZSB1c2VyIHJlbGF0aW9uc2hpcCBpcyBsb2FkZWQKICAgICAgbGV0IGlzTG9hZGVkID0gdXNlclJlZi52YWx1ZSgpICE9PSBudWxsOwogICAgICAgLy8gZ2V0IHRoZSByZWNvcmQgb2YgdGhlIHJlZmVyZW5jZSAobnVsbCBpZiBub3QgeWV0IGF2YWlsYWJsZSkKICAgICAgbGV0IHVzZXIgPSB1c2VyUmVmLnZhbHVlKCk7CiAgICAgICAvLyBnZXQgdGhlIGlkZW50aWZpZXIgb2YgdGhlIHJlZmVyZW5jZQogICAgICBpZiAodXNlclJlZi5yZW1vdGVUeXBlKCkgPT09ICJpZCIpIHsKICAgICAgICBsZXQgaWQgPSB1c2VyUmVmLmlkKCk7CiAgICAgIH0gZWxzZSBpZiAodXNlclJlZi5yZW1vdGVUeXBlKCkgPT09ICJsaW5rIikgewogICAgICAgIGxldCBsaW5rID0gdXNlclJlZi5saW5rKCk7CiAgICAgIH0KICAgICAgIC8vIGxvYWQgdXNlciAodmlhIHN0b3JlLmZpbmRSZWNvcmQgb3Igc3RvcmUuZmluZEJlbG9uZ3NUbykKICAgICAgdXNlclJlZi5sb2FkKCkudGhlbiguLi4pCiAgICAgICAvLyBvciB0cmlnZ2VyIGEgcmVsb2FkCiAgICAgIHVzZXJSZWYucmVsb2FkKCkudGhlbiguLi4pCiAgICAgICAvLyBwcm92aWRlIGRhdGEgZm9yIHJlZmVyZW5jZQogICAgICB1c2VyUmVmLnB1c2goewogICAgICAgIHR5cGU6ICd1c2VyJywKICAgICAgICBpZDogMSwKICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICB1c2VybmFtZTogIkB1c2VyIgogICAgICAgIH0KICAgICAgfSkudGhlbihmdW5jdGlvbih1c2VyKSB7CiAgICAgICAgdXNlclJlZi52YWx1ZSgpID09PSB1c2VyOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGJlbG9uZ3NUbwogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiB0aGUgcmVsYXRpb25zaGlwCiAgICAgIEBzaW5jZSAyLjUuMAogICAgICBAcmV0dXJuIHtCZWxvbmdzVG9SZWZlcmVuY2V9IHJlZmVyZW5jZSBmb3IgdGhpcyByZWxhdGlvbnNoaXAKICAgICovCiAgICBiZWxvbmdzVG86IGZ1bmN0aW9uIGJlbG9uZ3NUbyhuYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsLnJlZmVyZW5jZUZvcignYmVsb25nc1RvJywgbmFtZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBHZXQgdGhlIHJlZmVyZW5jZSBmb3IgdGhlIHNwZWNpZmllZCBoYXNNYW55IHJlbGF0aW9uc2hpcC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9tb2RlbHMvYmxvZy5qcwogICAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgY29tbWVudHM6IGhhc01hbnkoeyBhc3luYzogdHJ1ZSB9KQogICAgICB9KTsKICAgICAgIGxldCBibG9nID0gc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ2Jsb2cnLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgIGNvbW1lbnRzOiB7CiAgICAgICAgICAgICAgZGF0YTogWwogICAgICAgICAgICAgICAgeyB0eXBlOiAnY29tbWVudCcsIGlkOiAxIH0sCiAgICAgICAgICAgICAgICB7IHR5cGU6ICdjb21tZW50JywgaWQ6IDIgfQogICAgICAgICAgICAgIF0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGxldCBjb21tZW50c1JlZiA9IGJsb2cuaGFzTWFueSgnY29tbWVudHMnKTsKICAgICAgIC8vIGNoZWNrIGlmIHRoZSBjb21tZW50cyBhcmUgbG9hZGVkIGFscmVhZHkKICAgICAgbGV0IGlzTG9hZGVkID0gY29tbWVudHNSZWYudmFsdWUoKSAhPT0gbnVsbDsKICAgICAgIC8vIGdldCB0aGUgcmVjb3JkcyBvZiB0aGUgcmVmZXJlbmNlIChudWxsIGlmIG5vdCB5ZXQgYXZhaWxhYmxlKQogICAgICBsZXQgY29tbWVudHMgPSBjb21tZW50c1JlZi52YWx1ZSgpOwogICAgICAgLy8gZ2V0IHRoZSBpZGVudGlmaWVyIG9mIHRoZSByZWZlcmVuY2UKICAgICAgaWYgKGNvbW1lbnRzUmVmLnJlbW90ZVR5cGUoKSA9PT0gImlkcyIpIHsKICAgICAgICBsZXQgaWRzID0gY29tbWVudHNSZWYuaWRzKCk7CiAgICAgIH0gZWxzZSBpZiAoY29tbWVudHNSZWYucmVtb3RlVHlwZSgpID09PSAibGluayIpIHsKICAgICAgICBsZXQgbGluayA9IGNvbW1lbnRzUmVmLmxpbmsoKTsKICAgICAgfQogICAgICAgLy8gbG9hZCBjb21tZW50cyAodmlhIHN0b3JlLmZpbmRNYW55IG9yIHN0b3JlLmZpbmRIYXNNYW55KQogICAgICBjb21tZW50c1JlZi5sb2FkKCkudGhlbiguLi4pCiAgICAgICAvLyBvciB0cmlnZ2VyIGEgcmVsb2FkCiAgICAgIGNvbW1lbnRzUmVmLnJlbG9hZCgpLnRoZW4oLi4uKQogICAgICAgLy8gcHJvdmlkZSBkYXRhIGZvciByZWZlcmVuY2UKICAgICAgY29tbWVudHNSZWYucHVzaChbeyB0eXBlOiAnY29tbWVudCcsIGlkOiAxIH0sIHsgdHlwZTogJ2NvbW1lbnQnLCBpZDogMiB9XSkudGhlbihmdW5jdGlvbihjb21tZW50cykgewogICAgICAgIGNvbW1lbnRzUmVmLnZhbHVlKCkgPT09IGNvbW1lbnRzOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGhhc01hbnkKICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgb2YgdGhlIHJlbGF0aW9uc2hpcAogICAgICBAc2luY2UgMi41LjAKICAgICAgQHJldHVybiB7SGFzTWFueVJlZmVyZW5jZX0gcmVmZXJlbmNlIGZvciB0aGlzIHJlbGF0aW9uc2hpcAogICAgKi8KICAgIGhhc01hbnk6IGZ1bmN0aW9uIGhhc01hbnkobmFtZSkgewogICAgICByZXR1cm4gdGhpcy5faW50ZXJuYWxNb2RlbC5yZWZlcmVuY2VGb3IoJ2hhc01hbnknLCBuYW1lKTsKICAgIH0sCgogICAgLyoqCiAgICAgUHJvdmlkZXMgaW5mbyBhYm91dCB0aGUgbW9kZWwgZm9yIGRlYnVnZ2luZyBwdXJwb3NlcwogICAgIGJ5IGdyb3VwaW5nIHRoZSBwcm9wZXJ0aWVzIGludG8gbW9yZSBzZW1hbnRpYyBncm91cHMuCiAgICAgIE1lYW50IHRvIGJlIHVzZWQgYnkgZGVidWdnaW5nIHRvb2xzIHN1Y2ggYXMgdGhlIENocm9tZSBFbWJlciBFeHRlbnNpb24uCiAgICAgIC0gR3JvdXBzIGFsbCBhdHRyaWJ1dGVzIGluICJBdHRyaWJ1dGVzIiBncm91cC4KICAgICAtIEdyb3VwcyBhbGwgYmVsb25nc1RvIHJlbGF0aW9uc2hpcHMgaW4gIkJlbG9uZ3MgVG8iIGdyb3VwLgogICAgIC0gR3JvdXBzIGFsbCBoYXNNYW55IHJlbGF0aW9uc2hpcHMgaW4gIkhhcyBNYW55IiBncm91cC4KICAgICAtIEdyb3VwcyBhbGwgZmxhZ3MgaW4gIkZsYWdzIiBncm91cC4KICAgICAtIEZsYWdzIHJlbGF0aW9uc2hpcCBDUHMgYXMgZXhwZW5zaXZlIHByb3BlcnRpZXMuCiAgICAgIEBtZXRob2QgX2RlYnVnSW5mbwogICAgIEBmb3IgTW9kZWwKICAgICBAcHJpdmF0ZQogICAgICovCiAgICBfZGVidWdJbmZvOiBmdW5jdGlvbiBfZGVidWdJbmZvKCkgewogICAgICB2YXIgYXR0cmlidXRlcyA9IFsnaWQnXTsKICAgICAgdmFyIHJlbGF0aW9uc2hpcHMgPSB7fTsKICAgICAgdmFyIGV4cGVuc2l2ZVByb3BlcnRpZXMgPSBbXTsKICAgICAgdGhpcy5lYWNoQXR0cmlidXRlKGZ1bmN0aW9uIChuYW1lLCBtZXRhKSB7CiAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZXMucHVzaChuYW1lKTsKICAgICAgfSk7CiAgICAgIHZhciBncm91cHMgPSBbewogICAgICAgIG5hbWU6ICdBdHRyaWJ1dGVzJywKICAgICAgICBwcm9wZXJ0aWVzOiBhdHRyaWJ1dGVzLAogICAgICAgIGV4cGFuZDogdHJ1ZQogICAgICB9XTsKICAgICAgdGhpcy5lYWNoUmVsYXRpb25zaGlwKGZ1bmN0aW9uIChuYW1lLCByZWxhdGlvbnNoaXApIHsKICAgICAgICB2YXIgcHJvcGVydGllcyA9IHJlbGF0aW9uc2hpcHNbcmVsYXRpb25zaGlwLmtpbmRdOwoKICAgICAgICBpZiAocHJvcGVydGllcyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBwcm9wZXJ0aWVzID0gcmVsYXRpb25zaGlwc1tyZWxhdGlvbnNoaXAua2luZF0gPSBbXTsKICAgICAgICAgIGdyb3Vwcy5wdXNoKHsKICAgICAgICAgICAgbmFtZTogcmVsYXRpb25zaGlwLmtpbmQsCiAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BlcnRpZXMsCiAgICAgICAgICAgIGV4cGFuZDogdHJ1ZQogICAgICAgICAgfSk7CiAgICAgICAgfQoKICAgICAgICBwcm9wZXJ0aWVzLnB1c2gobmFtZSk7CiAgICAgICAgZXhwZW5zaXZlUHJvcGVydGllcy5wdXNoKG5hbWUpOwogICAgICB9KTsKICAgICAgZ3JvdXBzLnB1c2goewogICAgICAgIG5hbWU6ICdGbGFncycsCiAgICAgICAgcHJvcGVydGllczogWydpc0xvYWRlZCcsICdoYXNEaXJ0eUF0dHJpYnV0ZXMnLCAnaXNTYXZpbmcnLCAnaXNEZWxldGVkJywgJ2lzRXJyb3InLCAnaXNOZXcnLCAnaXNWYWxpZCddCiAgICAgIH0pOwogICAgICByZXR1cm4gewogICAgICAgIHByb3BlcnR5SW5mbzogewogICAgICAgICAgLy8gaW5jbHVkZSBhbGwgb3RoZXIgbWl4aW5zIC8gcHJvcGVydGllcyAobm90IGp1c3QgdGhlIGdyb3VwZWQgb25lcykKICAgICAgICAgIGluY2x1ZGVPdGhlclByb3BlcnRpZXM6IHRydWUsCiAgICAgICAgICBncm91cHM6IGdyb3VwcywKICAgICAgICAgIC8vIGRvbid0IHByZS1jYWxjdWxhdGUgdW5sZXNzIGNhY2hlZAogICAgICAgICAgZXhwZW5zaXZlUHJvcGVydGllczogZXhwZW5zaXZlUHJvcGVydGllcwogICAgICAgIH0KICAgICAgfTsKICAgIH0sCiAgICBub3RpZnlCZWxvbmdzVG9DaGFuZ2U6IGZ1bmN0aW9uIG5vdGlmeUJlbG9uZ3NUb0NoYW5nZShrZXkpIHsKICAgICAgdGhpcy5ub3RpZnlQcm9wZXJ0eUNoYW5nZShrZXkpOwogICAgfSwKCiAgICAvKioKICAgICBHaXZlbiBhIGNhbGxiYWNrLCBpdGVyYXRlcyBvdmVyIGVhY2ggb2YgdGhlIHJlbGF0aW9uc2hpcHMgaW4gdGhlIG1vZGVsLAogICAgIGludm9raW5nIHRoZSBjYWxsYmFjayB3aXRoIHRoZSBuYW1lIG9mIGVhY2ggcmVsYXRpb25zaGlwIGFuZCBpdHMgcmVsYXRpb25zaGlwCiAgICAgZGVzY3JpcHRvci4KICAgICAgIFRoZSBjYWxsYmFjayBtZXRob2QgeW91IHByb3ZpZGUgc2hvdWxkIGhhdmUgdGhlIGZvbGxvd2luZyBzaWduYXR1cmUgKGFsbAogICAgIHBhcmFtZXRlcnMgYXJlIG9wdGlvbmFsKToKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGZ1bmN0aW9uKG5hbWUsIGRlc2NyaXB0b3IpOwogICAgIGBgYAogICAgICAtIGBuYW1lYCB0aGUgbmFtZSBvZiB0aGUgY3VycmVudCBwcm9wZXJ0eSBpbiB0aGUgaXRlcmF0aW9uCiAgICAgLSBgZGVzY3JpcHRvcmAgdGhlIG1ldGEgb2JqZWN0IHRoYXQgZGVzY3JpYmVzIHRoaXMgcmVsYXRpb25zaGlwCiAgICAgIFRoZSByZWxhdGlvbnNoaXAgZGVzY3JpcHRvciBhcmd1bWVudCBpcyBhbiBvYmplY3Qgd2l0aCB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMuCiAgICAgIC0gKiprZXkqKiA8c3BhbiBjbGFzcz0idHlwZSI+U3RyaW5nPC9zcGFuPiB0aGUgbmFtZSBvZiB0aGlzIHJlbGF0aW9uc2hpcCBvbiB0aGUgTW9kZWwKICAgICAtICoqa2luZCoqIDxzcGFuIGNsYXNzPSJ0eXBlIj5TdHJpbmc8L3NwYW4+ICJoYXNNYW55IiBvciAiYmVsb25nc1RvIgogICAgIC0gKipvcHRpb25zKiogPHNwYW4gY2xhc3M9InR5cGUiPk9iamVjdDwvc3Bhbj4gdGhlIG9yaWdpbmFsIG9wdGlvbnMgaGFzaCBwYXNzZWQgd2hlbiB0aGUgcmVsYXRpb25zaGlwIHdhcyBkZWNsYXJlZAogICAgIC0gKipwYXJlbnRUeXBlKiogPHNwYW4gY2xhc3M9InR5cGUiPk1vZGVsPC9zcGFuPiB0aGUgdHlwZSBvZiB0aGUgTW9kZWwgdGhhdCBvd25zIHRoaXMgcmVsYXRpb25zaGlwCiAgICAgLSAqKnR5cGUqKiA8c3BhbiBjbGFzcz0idHlwZSI+U3RyaW5nPC9zcGFuPiB0aGUgdHlwZSBuYW1lIG9mIHRoZSByZWxhdGVkIE1vZGVsCiAgICAgIE5vdGUgdGhhdCBpbiBhZGRpdGlvbiB0byBhIGNhbGxiYWNrLCB5b3UgY2FuIGFsc28gcGFzcyBhbiBvcHRpb25hbCB0YXJnZXQKICAgICBvYmplY3QgdGhhdCB3aWxsIGJlIHNldCBhcyBgdGhpc2Agb24gdGhlIGNvbnRleHQuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgaW1wb3J0IEpTT05TZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbic7CiAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05TZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24ocmVjb3JkLCBvcHRpb25zKSB7CiAgICAgICAgbGV0IGpzb24gPSB7fTsKICAgICAgICAgcmVjb3JkLmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24obmFtZSwgZGVzY3JpcHRvcikgewogICAgICAgICAgaWYgKGRlc2NyaXB0b3Iua2luZCA9PT0gJ2hhc01hbnknKSB7CiAgICAgICAgICAgIGxldCBzZXJpYWxpemVkSGFzTWFueU5hbWUgPSBuYW1lLnRvVXBwZXJDYXNlKCkgKyAnX0lEUyc7CiAgICAgICAgICAgIGpzb25bc2VyaWFsaXplZEhhc01hbnlOYW1lXSA9IHJlY29yZC5nZXQobmFtZSkubWFwQnkoJ2lkJyk7CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgICAgIHJldHVybiBqc29uOwogICAgICB9CiAgICB9KTsKICAgICBgYGAKICAgICAgQG1ldGhvZCBlYWNoUmVsYXRpb25zaGlwCiAgICAgQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgdGhlIGNhbGxiYWNrIHRvIGludm9rZQogICAgIEBwYXJhbSB7YW55fSBiaW5kaW5nIHRoZSB2YWx1ZSB0byB3aGljaCB0aGUgY2FsbGJhY2sncyBgdGhpc2Agc2hvdWxkIGJlIGJvdW5kCiAgICAgKi8KICAgIGVhY2hSZWxhdGlvbnNoaXA6IGZ1bmN0aW9uIGVhY2hSZWxhdGlvbnNoaXAoY2FsbGJhY2ssIGJpbmRpbmcpIHsKICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5lYWNoUmVsYXRpb25zaGlwKGNhbGxiYWNrLCBiaW5kaW5nKTsKICAgIH0sCiAgICByZWxhdGlvbnNoaXBGb3I6IGZ1bmN0aW9uIHJlbGF0aW9uc2hpcEZvcihuYW1lKSB7CiAgICAgIHJldHVybiBFbWJlci5nZXQodGhpcy5jb25zdHJ1Y3RvciwgJ3JlbGF0aW9uc2hpcHNCeU5hbWUnKS5nZXQobmFtZSk7CiAgICB9LAogICAgaW52ZXJzZUZvcjogZnVuY3Rpb24gaW52ZXJzZUZvcihrZXkpIHsKICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuaW52ZXJzZUZvcihrZXksIHRoaXMuX2ludGVybmFsTW9kZWwuc3RvcmUpOwogICAgfSwKICAgIG5vdGlmeUhhc01hbnlBZGRlZDogZnVuY3Rpb24gbm90aWZ5SGFzTWFueUFkZGVkKGtleSkgewogICAgICAvL1dlIG5lZWQgdG8gbm90aWZ5UHJvcGVydHlDaGFuZ2UgaW4gdGhlIGFkZGluZyBjYXNlIGJlY2F1c2Ugd2UgbmVlZCB0byBtYWtlIHN1cmUKICAgICAgLy93ZSBmZXRjaCB0aGUgbmV3bHkgYWRkZWQgcmVjb3JkIGluIGNhc2UgaXQgaXMgdW5sb2FkZWQKICAgICAgLy9UT0RPKElnb3IpOiBDb25zaWRlciB3aGV0aGVyIHdlIGNvdWxkIGRvIHRoaXMgb25seSBpZiB0aGUgcmVjb3JkIHN0YXRlIGlzIHVubG9hZGVkCiAgICAgIHRoaXMubm90aWZ5UHJvcGVydHlDaGFuZ2Uoa2V5KTsKICAgIH0sCiAgICBlYWNoQXR0cmlidXRlOiBmdW5jdGlvbiBlYWNoQXR0cmlidXRlKGNhbGxiYWNrLCBiaW5kaW5nKSB7CiAgICAgIHRoaXMuY29uc3RydWN0b3IuZWFjaEF0dHJpYnV0ZShjYWxsYmFjaywgYmluZGluZyk7CiAgICB9CiAgfSk7CiAgLyoqCiAgIEBwcm9wZXJ0eSBkYXRhCiAgIEBwcml2YXRlCiAgIEBkZXByZWNhdGVkCiAgIEB0eXBlIHtPYmplY3R9CiAgICovCgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShNb2RlbC5wcm90b3R5cGUsICdkYXRhJywgewogICAgY29uZmlndXJhYmxlOiBmYWxzZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5yZWNvcmREYXRhRm9yKHRoaXMpLl9kYXRhOwogICAgfQogIH0pOwogIHZhciBJRF9ERVNDUklQVE9SID0gewogICAgY29uZmlndXJhYmxlOiBmYWxzZSwKICAgIHNldDogZnVuY3Rpb24gc2V0KGlkKSB7CiAgICAgIHZhciBub3JtYWxpemVkSWQgPSBQcml2YXRlLmNvZXJjZUlkKGlkKTsKCiAgICAgIGlmIChub3JtYWxpemVkSWQgIT09IG51bGwpIHsKICAgICAgICB0aGlzLl9pbnRlcm5hbE1vZGVsLnNldElkKG5vcm1hbGl6ZWRJZCk7CiAgICAgIH0KICAgIH0sCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgLy8gdGhlIF9pbnRlcm5hbE1vZGVsIGd1YXJkIGV4aXN0cywgYmVjYXVzZSBzb21lIGRldi1vbmx5IGRlcHJlY2F0aW9uIGNvZGUKICAgICAgLy8gKGFkZExpc3RlbmVyIHZpYSB2YWxpZGF0ZVByb3BlcnR5SW5qZWN0aW9ucykgaW52b2tlcyB0b1N0cmluZyBiZWZvcmUgdGhlCiAgICAgIC8vIG9iamVjdCBpcyByZWFsLgogICAgICByZXR1cm4gdGhpcy5faW50ZXJuYWxNb2RlbCAmJiB0aGlzLl9pbnRlcm5hbE1vZGVsLmlkOwogICAgfQogIH07CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE1vZGVsLnByb3RvdHlwZSwgJ2lkJywgSURfREVTQ1JJUFRPUik7CgogIE1vZGVsLnJlb3BlbkNsYXNzKHsKICAgIGlzTW9kZWw6IHRydWUsCgogICAgLyoqCiAgICAgIENyZWF0ZSBzaG91bGQgb25seSBldmVyIGJlIGNhbGxlZCBieSB0aGUgc3RvcmUuIFRvIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiBhCiAgICAgIGBNb2RlbGAgaW4gYSBkaXJ0eSBzdGF0ZSB1c2UgYHN0b3JlLmNyZWF0ZVJlY29yZGAuCiAgICAgIFRvIGNyZWF0ZSBpbnN0YW5jZXMgb2YgYE1vZGVsYCBpbiBhIGNsZWFuIHN0YXRlLCB1c2UgYHN0b3JlLnB1c2hgCiAgICAgICBAbWV0aG9kIGNyZWF0ZQogICAgICBAcHJpdmF0ZQogICAgICBAc3RhdGljCiAgICAqLwoKICAgIC8qKgogICAgIFJlcHJlc2VudHMgdGhlIG1vZGVsJ3MgY2xhc3MgbmFtZSBhcyBhIHN0cmluZy4gVGhpcyBjYW4gYmUgdXNlZCB0byBsb29rIHVwIHRoZSBtb2RlbCdzIGNsYXNzIG5hbWUgdGhyb3VnaAogICAgIGBTdG9yZWAncyBtb2RlbEZvciBtZXRob2QuCiAgICAgIGBtb2RlbE5hbWVgIGlzIGdlbmVyYXRlZCBmb3IgeW91IGJ5IEVtYmVyIERhdGEuIEl0IHdpbGwgYmUgYSBsb3dlcmNhc2VkLCBkYXNoZXJpemVkIHN0cmluZy4KICAgICBGb3IgZXhhbXBsZToKICAgICAgYGBgamF2YXNjcmlwdAogICAgIHN0b3JlLm1vZGVsRm9yKCdwb3N0JykubW9kZWxOYW1lOyAvLyAncG9zdCcKICAgICBzdG9yZS5tb2RlbEZvcignYmxvZy1wb3N0JykubW9kZWxOYW1lOyAvLyAnYmxvZy1wb3N0JwogICAgIGBgYAogICAgICBUaGUgbW9zdCBjb21tb24gcGxhY2UgeW91J2xsIHdhbnQgdG8gYWNjZXNzIGBtb2RlbE5hbWVgIGlzIGluIHlvdXIgc2VyaWFsaXplcidzIGBwYXlsb2FkS2V5RnJvbU1vZGVsTmFtZWAgbWV0aG9kLiBGb3IgZXhhbXBsZSwgdG8gY2hhbmdlIHBheWxvYWQKICAgICBrZXlzIHRvIHVuZGVyc2NvcmUgKGluc3RlYWQgb2YgZGFzaGVyaXplZCksIHlvdSBtaWdodCB1c2UgdGhlIGZvbGxvd2luZyBjb2RlOgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CiAgICAgaW1wb3J0IHsgdW5kZXJzY29yZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogICAgICBleHBvcnQgZGVmYXVsdCBjb25zdCBQb3N0U2VyaWFsaXplciA9IFJFU1RTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICBwYXlsb2FkS2V5RnJvbU1vZGVsTmFtZShtb2RlbE5hbWUpIHsKICAgICAgICAgcmV0dXJuIHVuZGVyc2NvcmUobW9kZWxOYW1lKTsKICAgICAgIH0KICAgICB9KTsKICAgICBgYGAKICAgICBAcHJvcGVydHkgbW9kZWxOYW1lCiAgICAgQHR5cGUgU3RyaW5nCiAgICAgQHJlYWRvbmx5CiAgICAgQHN0YXRpYwogICAgKi8KICAgIG1vZGVsTmFtZTogbnVsbCwKCiAgICAvKgogICAgIFRoZXNlIGNsYXNzIG1ldGhvZHMgYmVsb3cgcHJvdmlkZSByZWxhdGlvbnNoaXAKICAgICBpbnRyb3NwZWN0aW9uIGFiaWxpdGllcyBhYm91dCByZWxhdGlvbnNoaXBzLgogICAgICBBIG5vdGUgYWJvdXQgdGhlIGNvbXB1dGVkIHByb3BlcnRpZXMgY29udGFpbmVkIGhlcmU6CiAgICAgICoqVGhlc2UgcHJvcGVydGllcyBhcmUgZWZmZWN0aXZlbHkgc2VhbGVkIG9uY2UgY2FsbGVkIGZvciB0aGUgZmlyc3QgdGltZS4qKgogICAgIFRvIGF2b2lkIHJlcGVhdGVkbHkgZG9pbmcgZXhwZW5zaXZlIGl0ZXJhdGlvbiBvdmVyIGEgbW9kZWwncyBmaWVsZHMsIHRoZXNlCiAgICAgdmFsdWVzIGFyZSBjb21wdXRlZCBvbmNlIGFuZCB0aGVuIGNhY2hlZCBmb3IgdGhlIHJlbWFpbmRlciBvZiB0aGUgcnVudGltZSBvZgogICAgIHlvdXIgYXBwbGljYXRpb24uCiAgICAgIElmIHlvdXIgYXBwbGljYXRpb24gbmVlZHMgdG8gbW9kaWZ5IGEgY2xhc3MgYWZ0ZXIgaXRzIGluaXRpYWwgZGVmaW5pdGlvbgogICAgIChmb3IgZXhhbXBsZSwgdXNpbmcgYHJlb3BlbigpYCB0byBhZGQgYWRkaXRpb25hbCBhdHRyaWJ1dGVzKSwgbWFrZSBzdXJlIHlvdQogICAgIGRvIGl0IGJlZm9yZSB1c2luZyB5b3VyIG1vZGVsIHdpdGggdGhlIHN0b3JlLCB3aGljaCB1c2VzIHRoZXNlIHByb3BlcnRpZXMKICAgICBleHRlbnNpdmVseS4KICAgICAqLwoKICAgIC8qKgogICAgIEZvciBhIGdpdmVuIHJlbGF0aW9uc2hpcCBuYW1lLCByZXR1cm5zIHRoZSBtb2RlbCB0eXBlIG9mIHRoZSByZWxhdGlvbnNoaXAuCiAgICAgIEZvciBleGFtcGxlLCBpZiB5b3UgZGVmaW5lIGEgbW9kZWwgbGlrZSB0aGlzOgogICAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICBjb21tZW50czogaGFzTWFueSgnY29tbWVudCcpCiAgICAgIH0pOwogICAgIGBgYAogICAgICBDYWxsaW5nIGBzdG9yZS5tb2RlbEZvcigncG9zdCcpLnR5cGVGb3JSZWxhdGlvbnNoaXAoJ2NvbW1lbnRzJywgc3RvcmUpYCB3aWxsIHJldHVybiBgQ29tbWVudGAuCiAgICAgIEBtZXRob2QgdHlwZUZvclJlbGF0aW9uc2hpcAogICAgIEBzdGF0aWMKICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSB0aGUgbmFtZSBvZiB0aGUgcmVsYXRpb25zaGlwCiAgICAgQHBhcmFtIHtzdG9yZX0gc3RvcmUgYW4gaW5zdGFuY2Ugb2YgU3RvcmUKICAgICBAcmV0dXJuIHtNb2RlbH0gdGhlIHR5cGUgb2YgdGhlIHJlbGF0aW9uc2hpcCwgb3IgdW5kZWZpbmVkCiAgICAgKi8KICAgIHR5cGVGb3JSZWxhdGlvbnNoaXA6IGZ1bmN0aW9uIHR5cGVGb3JSZWxhdGlvbnNoaXAobmFtZSwgc3RvcmUpIHsKICAgICAgdmFyIHJlbGF0aW9uc2hpcCA9IEVtYmVyLmdldCh0aGlzLCAncmVsYXRpb25zaGlwc0J5TmFtZScpLmdldChuYW1lKTsKICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcCAmJiBzdG9yZS5tb2RlbEZvcihyZWxhdGlvbnNoaXAudHlwZSk7CiAgICB9LAogICAgaW52ZXJzZU1hcDogRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIH0pLAoKICAgIC8qKgogICAgIEZpbmQgdGhlIHJlbGF0aW9uc2hpcCB3aGljaCBpcyB0aGUgaW52ZXJzZSBvZiB0aGUgb25lIGFza2VkIGZvci4KICAgICAgRm9yIGV4YW1wbGUsIGlmIHlvdSBkZWZpbmUgbW9kZWxzIGxpa2UgdGhpczoKICAgICAgYGBgYXBwL21vZGVscy9wb3N0LmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgY29tbWVudHM6IGhhc01hbnkoJ21lc3NhZ2UnKQogICAgICB9KTsKICAgICBgYGAKICAgICAgYGBgYXBwL21vZGVscy9tZXNzYWdlLmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICBvd25lcjogYmVsb25nc1RvKCdwb3N0JykKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYCBqcwogICAgIHN0b3JlLm1vZGVsRm9yKCdwb3N0JykuaW52ZXJzZUZvcignY29tbWVudHMnLCBzdG9yZSkgLy8geyB0eXBlOiBBcHAuTWVzc2FnZSwgbmFtZTogJ293bmVyJywga2luZDogJ2JlbG9uZ3NUbycgfQogICAgIHN0b3JlLm1vZGVsRm9yKCdtZXNzYWdlJykuaW52ZXJzZUZvcignb3duZXInLCBzdG9yZSkgLy8geyB0eXBlOiBBcHAuUG9zdCwgbmFtZTogJ2NvbW1lbnRzJywga2luZDogJ2hhc01hbnknIH0KICAgICBgYGAKICAgICAgQG1ldGhvZCBpbnZlcnNlRm9yCiAgICAgQHN0YXRpYwogICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSByZWxhdGlvbnNoaXAKICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgIEByZXR1cm4ge09iamVjdH0gdGhlIGludmVyc2UgcmVsYXRpb25zaGlwLCBvciBudWxsCiAgICAgKi8KICAgIGludmVyc2VGb3I6IGZ1bmN0aW9uIGludmVyc2VGb3IobmFtZSwgc3RvcmUpIHsKICAgICAgdmFyIGludmVyc2VNYXAgPSBFbWJlci5nZXQodGhpcywgJ2ludmVyc2VNYXAnKTsKCiAgICAgIGlmIChpbnZlcnNlTWFwW25hbWVdKSB7CiAgICAgICAgcmV0dXJuIGludmVyc2VNYXBbbmFtZV07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIGludmVyc2UgPSB0aGlzLl9maW5kSW52ZXJzZUZvcihuYW1lLCBzdG9yZSk7CgogICAgICAgIGludmVyc2VNYXBbbmFtZV0gPSBpbnZlcnNlOwogICAgICAgIHJldHVybiBpbnZlcnNlOwogICAgICB9CiAgICB9LAogICAgLy9DYWxjdWxhdGUgdGhlIGludmVyc2UsIGlnbm9yaW5nIHRoZSBjYWNoZQogICAgX2ZpbmRJbnZlcnNlRm9yOiBmdW5jdGlvbiBfZmluZEludmVyc2VGb3IobmFtZSwgc3RvcmUpIHsKICAgICAgdmFyIGludmVyc2VUeXBlID0gdGhpcy50eXBlRm9yUmVsYXRpb25zaGlwKG5hbWUsIHN0b3JlKTsKCiAgICAgIGlmICghaW52ZXJzZVR5cGUpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIHByb3BlcnR5TWV0YSA9IHRoaXMubWV0YUZvclByb3BlcnR5KG5hbWUpOyAvL0lmIGludmVyc2UgaXMgbWFudWFsbHkgc3BlY2lmaWVkIHRvIGJlIG51bGwsIGxpa2UgIGBjb21tZW50czogaGFzTWFueSgnbWVzc2FnZScsIHsgaW52ZXJzZTogbnVsbCB9KWAKCiAgICAgIHZhciBvcHRpb25zID0gcHJvcGVydHlNZXRhLm9wdGlvbnM7CgogICAgICBpZiAob3B0aW9ucy5pbnZlcnNlID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KCiAgICAgIHZhciBpbnZlcnNlTmFtZSwgaW52ZXJzZUtpbmQsIGludmVyc2UsIGludmVyc2VPcHRpb25zOyAvL0lmIGludmVyc2UgaXMgc3BlY2lmaWVkIG1hbnVhbGx5LCByZXR1cm4gdGhlIGludmVyc2UKCiAgICAgIGlmIChvcHRpb25zLmludmVyc2UpIHsKICAgICAgICBpbnZlcnNlTmFtZSA9IG9wdGlvbnMuaW52ZXJzZTsKICAgICAgICBpbnZlcnNlID0gRW1iZXIuZ2V0KGludmVyc2VUeXBlLCAncmVsYXRpb25zaGlwc0J5TmFtZScpLmdldChpbnZlcnNlTmFtZSk7CgogICAgICAgIGludmVyc2VLaW5kID0gaW52ZXJzZS5raW5kOwogICAgICAgIGludmVyc2VPcHRpb25zID0gaW52ZXJzZS5vcHRpb25zOwogICAgICB9IGVsc2UgewogICAgICAgIC8vTm8gaW52ZXJzZSB3YXMgc3BlY2lmaWVkIG1hbnVhbGx5LCB3ZSBuZWVkIHRvIHVzZSBhIGhldXJpc3RpYyB0byBndWVzcyBvbmUKICAgICAgICBpZiAocHJvcGVydHlNZXRhLnR5cGUgPT09IHByb3BlcnR5TWV0YS5wYXJlbnRNb2RlbE5hbWUpIDsKCiAgICAgICAgdmFyIHBvc3NpYmxlUmVsYXRpb25zaGlwcyA9IGZpbmRQb3NzaWJsZUludmVyc2VzKHRoaXMsIGludmVyc2VUeXBlLCBuYW1lKTsKCiAgICAgICAgaWYgKHBvc3NpYmxlUmVsYXRpb25zaGlwcy5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KCiAgICAgICAgdmFyIGZpbHRlcmVkUmVsYXRpb25zaGlwcyA9IHBvc3NpYmxlUmVsYXRpb25zaGlwcy5maWx0ZXIoZnVuY3Rpb24gKHBvc3NpYmxlUmVsYXRpb25zaGlwKSB7CiAgICAgICAgICB2YXIgb3B0aW9uc0ZvclJlbGF0aW9uc2hpcCA9IGludmVyc2VUeXBlLm1ldGFGb3JQcm9wZXJ0eShwb3NzaWJsZVJlbGF0aW9uc2hpcC5uYW1lKS5vcHRpb25zOwogICAgICAgICAgcmV0dXJuIG5hbWUgPT09IG9wdGlvbnNGb3JSZWxhdGlvbnNoaXAuaW52ZXJzZTsKICAgICAgICB9KTsKCiAgICAgICAgaWYgKGZpbHRlcmVkUmVsYXRpb25zaGlwcy5sZW5ndGggPT09IDEpIHsKICAgICAgICAgIHBvc3NpYmxlUmVsYXRpb25zaGlwcyA9IGZpbHRlcmVkUmVsYXRpb25zaGlwczsKICAgICAgICB9CiAgICAgICAgaW52ZXJzZU5hbWUgPSBwb3NzaWJsZVJlbGF0aW9uc2hpcHNbMF0ubmFtZTsKICAgICAgICBpbnZlcnNlS2luZCA9IHBvc3NpYmxlUmVsYXRpb25zaGlwc1swXS5raW5kOwogICAgICAgIGludmVyc2VPcHRpb25zID0gcG9zc2libGVSZWxhdGlvbnNoaXBzWzBdLm9wdGlvbnM7CiAgICAgIH0KICAgICAgcmV0dXJuIHsKICAgICAgICB0eXBlOiBpbnZlcnNlVHlwZSwKICAgICAgICBuYW1lOiBpbnZlcnNlTmFtZSwKICAgICAgICBraW5kOiBpbnZlcnNlS2luZCwKICAgICAgICBvcHRpb25zOiBpbnZlcnNlT3B0aW9ucwogICAgICB9OwogICAgfSwKCiAgICAvKioKICAgICBUaGUgbW9kZWwncyByZWxhdGlvbnNoaXBzIGFzIGEgbWFwLCBrZXllZCBvbiB0aGUgdHlwZSBvZiB0aGUKICAgICByZWxhdGlvbnNoaXAuIFRoZSB2YWx1ZSBvZiBlYWNoIGVudHJ5IGlzIGFuIGFycmF5IGNvbnRhaW5pbmcgYSBkZXNjcmlwdG9yCiAgICAgZm9yIGVhY2ggcmVsYXRpb25zaGlwIHdpdGggdGhhdCB0eXBlLCBkZXNjcmliaW5nIHRoZSBuYW1lIG9mIHRoZSByZWxhdGlvbnNoaXAKICAgICBhcyB3ZWxsIGFzIHRoZSB0eXBlLgogICAgICBGb3IgZXhhbXBsZSwgZ2l2ZW4gdGhlIGZvbGxvd2luZyBtb2RlbCBkZWZpbml0aW9uOgogICAgICBgYGBhcHAvbW9kZWxzL2Jsb2cuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvLCBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIHVzZXJzOiBoYXNNYW55KCd1c2VyJyksCiAgICAgICAgb3duZXI6IGJlbG9uZ3NUbygndXNlcicpLAogICAgICAgIHBvc3RzOiBoYXNNYW55KCdwb3N0JykKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIFRoaXMgY29tcHV0ZWQgcHJvcGVydHkgd291bGQgcmV0dXJuIGEgbWFwIGRlc2NyaWJpbmcgdGhlc2UKICAgICByZWxhdGlvbnNoaXBzLCBsaWtlIHRoaXM6CiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBpbXBvcnQgRW1iZXIgZnJvbSAnZW1iZXInOwogICAgIGltcG9ydCBCbG9nIGZyb20gJ2FwcC9tb2RlbHMvYmxvZyc7CiAgICAgaW1wb3J0IFVzZXIgZnJvbSAnYXBwL21vZGVscy91c2VyJzsKICAgICBpbXBvcnQgUG9zdCBmcm9tICdhcHAvbW9kZWxzL3Bvc3QnOwogICAgICBsZXQgcmVsYXRpb25zaGlwcyA9IEVtYmVyLmdldChCbG9nLCAncmVsYXRpb25zaGlwcycpOwogICAgIHJlbGF0aW9uc2hpcHMuZ2V0KCd1c2VyJyk7CiAgICAgLy89PiBbIHsgbmFtZTogJ3VzZXJzJywga2luZDogJ2hhc01hbnknIH0sCiAgICAgLy8gICAgIHsgbmFtZTogJ293bmVyJywga2luZDogJ2JlbG9uZ3NUbycgfSBdCiAgICAgcmVsYXRpb25zaGlwcy5nZXQoJ3Bvc3QnKTsKICAgICAvLz0+IFsgeyBuYW1lOiAncG9zdHMnLCBraW5kOiAnaGFzTWFueScgfSBdCiAgICAgYGBgCiAgICAgIEBwcm9wZXJ0eSByZWxhdGlvbnNoaXBzCiAgICAgQHN0YXRpYwogICAgIEB0eXBlIE1hcAogICAgIEByZWFkT25seQogICAgICovCiAgICByZWxhdGlvbnNoaXBzOiBQcml2YXRlLnJlbGF0aW9uc2hpcHNEZXNjcmlwdG9yLAoKICAgIC8qKgogICAgIEEgaGFzaCBjb250YWluaW5nIGxpc3RzIG9mIHRoZSBtb2RlbCdzIHJlbGF0aW9uc2hpcHMsIGdyb3VwZWQKICAgICBieSB0aGUgcmVsYXRpb25zaGlwIGtpbmQuIEZvciBleGFtcGxlLCBnaXZlbiBhIG1vZGVsIHdpdGggdGhpcwogICAgIGRlZmluaXRpb246CiAgICAgIGBgYGFwcC9tb2RlbHMvYmxvZy5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBiZWxvbmdzVG8sIGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdXNlcnM6IGhhc01hbnkoJ3VzZXInKSwKICAgICAgICBvd25lcjogYmVsb25nc1RvKCd1c2VyJyksCiAgICAgICAgIHBvc3RzOiBoYXNNYW55KCdwb3N0JykKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIFRoaXMgcHJvcGVydHkgd291bGQgY29udGFpbiB0aGUgZm9sbG93aW5nOgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgaW1wb3J0IEVtYmVyIGZyb20gJ2VtYmVyJzsKICAgICBpbXBvcnQgQmxvZyBmcm9tICdhcHAvbW9kZWxzL2Jsb2cnOwogICAgICBsZXQgcmVsYXRpb25zaGlwTmFtZXMgPSBFbWJlci5nZXQoQmxvZywgJ3JlbGF0aW9uc2hpcE5hbWVzJyk7CiAgICAgcmVsYXRpb25zaGlwTmFtZXMuaGFzTWFueTsKICAgICAvLz0+IFsndXNlcnMnLCAncG9zdHMnXQogICAgIHJlbGF0aW9uc2hpcE5hbWVzLmJlbG9uZ3NUbzsKICAgICAvLz0+IFsnb3duZXInXQogICAgIGBgYAogICAgICBAcHJvcGVydHkgcmVsYXRpb25zaGlwTmFtZXMKICAgICBAc3RhdGljCiAgICAgQHR5cGUgT2JqZWN0CiAgICAgQHJlYWRPbmx5CiAgICAgKi8KICAgIHJlbGF0aW9uc2hpcE5hbWVzOiBFbWJlci5jb21wdXRlZChmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBuYW1lcyA9IHsKICAgICAgICBoYXNNYW55OiBbXSwKICAgICAgICBiZWxvbmdzVG86IFtdCiAgICAgIH07CiAgICAgIHRoaXMuZWFjaENvbXB1dGVkUHJvcGVydHkoZnVuY3Rpb24gKG5hbWUsIG1ldGEpIHsKICAgICAgICBpZiAobWV0YS5pc1JlbGF0aW9uc2hpcCkgewogICAgICAgICAgbmFtZXNbbWV0YS5raW5kXS5wdXNoKG5hbWUpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiBuYW1lczsKICAgIH0pLAoKICAgIC8qKgogICAgIEFuIGFycmF5IG9mIHR5cGVzIGRpcmVjdGx5IHJlbGF0ZWQgdG8gYSBtb2RlbC4gRWFjaCB0eXBlIHdpbGwgYmUKICAgICBpbmNsdWRlZCBvbmNlLCByZWdhcmRsZXNzIG9mIHRoZSBudW1iZXIgb2YgcmVsYXRpb25zaGlwcyBpdCBoYXMgd2l0aAogICAgIHRoZSBtb2RlbC4KICAgICAgRm9yIGV4YW1wbGUsIGdpdmVuIGEgbW9kZWwgd2l0aCB0aGlzIGRlZmluaXRpb246CiAgICAgIGBgYGFwcC9tb2RlbHMvYmxvZy5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBiZWxvbmdzVG8sIGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdXNlcnM6IGhhc01hbnkoJ3VzZXInKSwKICAgICAgICBvd25lcjogYmVsb25nc1RvKCd1c2VyJyksCiAgICAgICAgIHBvc3RzOiBoYXNNYW55KCdwb3N0JykKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIFRoaXMgcHJvcGVydHkgd291bGQgY29udGFpbiB0aGUgZm9sbG93aW5nOgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgaW1wb3J0IEVtYmVyIGZyb20gJ2VtYmVyJzsKICAgICBpbXBvcnQgQmxvZyBmcm9tICdhcHAvbW9kZWxzL2Jsb2cnOwogICAgICBsZXQgcmVsYXRlZFR5cGVzID0gRW1iZXIuZ2V0KEJsb2csICdyZWxhdGVkVHlwZXMnKTsKICAgICAvLz0+IFsgVXNlciwgUG9zdCBdCiAgICAgYGBgCiAgICAgIEBwcm9wZXJ0eSByZWxhdGVkVHlwZXMKICAgICBAc3RhdGljCiAgICAgQHR5cGUgRW1iZXIuQXJyYXkKICAgICBAcmVhZE9ubHkKICAgICAqLwogICAgcmVsYXRlZFR5cGVzOiBQcml2YXRlLnJlbGF0ZWRUeXBlc0Rlc2NyaXB0b3IsCgogICAgLyoqCiAgICAgQSBtYXAgd2hvc2Uga2V5cyBhcmUgdGhlIHJlbGF0aW9uc2hpcHMgb2YgYSBtb2RlbCBhbmQgd2hvc2UgdmFsdWVzIGFyZQogICAgIHJlbGF0aW9uc2hpcCBkZXNjcmlwdG9ycy4KICAgICAgRm9yIGV4YW1wbGUsIGdpdmVuIGEgbW9kZWwgd2l0aCB0aGlzCiAgICAgZGVmaW5pdGlvbjoKICAgICAgYGBgYXBwL21vZGVscy9ibG9nLmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbywgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICB1c2VyczogaGFzTWFueSgndXNlcicpLAogICAgICAgIG93bmVyOiBiZWxvbmdzVG8oJ3VzZXInKSwKICAgICAgICAgcG9zdHM6IGhhc01hbnkoJ3Bvc3QnKQogICAgICB9KTsKICAgICBgYGAKICAgICAgVGhpcyBwcm9wZXJ0eSB3b3VsZCBjb250YWluIHRoZSBmb2xsb3dpbmc6CiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBpbXBvcnQgRW1iZXIgZnJvbSAnZW1iZXInOwogICAgIGltcG9ydCBCbG9nIGZyb20gJ2FwcC9tb2RlbHMvYmxvZyc7CiAgICAgIGxldCByZWxhdGlvbnNoaXBzQnlOYW1lID0gRW1iZXIuZ2V0KEJsb2csICdyZWxhdGlvbnNoaXBzQnlOYW1lJyk7CiAgICAgcmVsYXRpb25zaGlwc0J5TmFtZS5nZXQoJ3VzZXJzJyk7CiAgICAgLy89PiB7IGtleTogJ3VzZXJzJywga2luZDogJ2hhc01hbnknLCB0eXBlOiAndXNlcicsIG9wdGlvbnM6IE9iamVjdCwgaXNSZWxhdGlvbnNoaXA6IHRydWUgfQogICAgIHJlbGF0aW9uc2hpcHNCeU5hbWUuZ2V0KCdvd25lcicpOwogICAgIC8vPT4geyBrZXk6ICdvd25lcicsIGtpbmQ6ICdiZWxvbmdzVG8nLCB0eXBlOiAndXNlcicsIG9wdGlvbnM6IE9iamVjdCwgaXNSZWxhdGlvbnNoaXA6IHRydWUgfQogICAgIGBgYAogICAgICBAcHJvcGVydHkgcmVsYXRpb25zaGlwc0J5TmFtZQogICAgIEBzdGF0aWMKICAgICBAdHlwZSBNYXAKICAgICBAcmVhZE9ubHkKICAgICAqLwogICAgcmVsYXRpb25zaGlwc0J5TmFtZTogUHJpdmF0ZS5yZWxhdGlvbnNoaXBzQnlOYW1lRGVzY3JpcHRvciwKICAgIHJlbGF0aW9uc2hpcHNPYmplY3Q6IFByaXZhdGUucmVsYXRpb25zaGlwc09iamVjdERlc2NyaXB0b3IsCgogICAgLyoqCiAgICAgQSBtYXAgd2hvc2Uga2V5cyBhcmUgdGhlIGZpZWxkcyBvZiB0aGUgbW9kZWwgYW5kIHdob3NlIHZhbHVlcyBhcmUgc3RyaW5ncwogICAgIGRlc2NyaWJpbmcgdGhlIGtpbmQgb2YgdGhlIGZpZWxkLiBBIG1vZGVsJ3MgZmllbGRzIGFyZSB0aGUgdW5pb24gb2YgYWxsIG9mIGl0cwogICAgIGF0dHJpYnV0ZXMgYW5kIHJlbGF0aW9uc2hpcHMuCiAgICAgIEZvciBleGFtcGxlOgogICAgICBgYGBhcHAvbW9kZWxzL2Jsb2cuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciwgYmVsb25nc1RvLCBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIHVzZXJzOiBoYXNNYW55KCd1c2VyJyksCiAgICAgICAgb3duZXI6IGJlbG9uZ3NUbygndXNlcicpLAogICAgICAgICBwb3N0czogaGFzTWFueSgncG9zdCcpLAogICAgICAgICB0aXRsZTogYXR0cignc3RyaW5nJykKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYGpzCiAgICAgaW1wb3J0IEVtYmVyIGZyb20gJ2VtYmVyJzsKICAgICBpbXBvcnQgQmxvZyBmcm9tICdhcHAvbW9kZWxzL2Jsb2cnOwogICAgICBsZXQgZmllbGRzID0gRW1iZXIuZ2V0KEJsb2csICdmaWVsZHMnKTsKICAgICBmaWVsZHMuZm9yRWFjaChmdW5jdGlvbihraW5kLCBmaWVsZCkgewogICAgICAgIGNvbnNvbGUubG9nKGZpZWxkLCBraW5kKTsKICAgICAgfSk7CiAgICAgIC8vIHByaW50czoKICAgICAvLyB1c2VycywgaGFzTWFueQogICAgIC8vIG93bmVyLCBiZWxvbmdzVG8KICAgICAvLyBwb3N0cywgaGFzTWFueQogICAgIC8vIHRpdGxlLCBhdHRyaWJ1dGUKICAgICBgYGAKICAgICAgQHByb3BlcnR5IGZpZWxkcwogICAgIEBzdGF0aWMKICAgICBAdHlwZSBNYXAKICAgICBAcmVhZE9ubHkKICAgICAqLwogICAgZmllbGRzOiBFbWJlci5jb21wdXRlZChmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBtYXAgPSBuZXcgTWFwKCk7CiAgICAgIHRoaXMuZWFjaENvbXB1dGVkUHJvcGVydHkoZnVuY3Rpb24gKG5hbWUsIG1ldGEpIHsKICAgICAgICBpZiAobWV0YS5pc1JlbGF0aW9uc2hpcCkgewogICAgICAgICAgbWFwLnNldChuYW1lLCBtZXRhLmtpbmQpOwogICAgICAgIH0gZWxzZSBpZiAobWV0YS5pc0F0dHJpYnV0ZSkgewogICAgICAgICAgbWFwLnNldChuYW1lLCAnYXR0cmlidXRlJyk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIG1hcDsKICAgIH0pLnJlYWRPbmx5KCksCgogICAgLyoqCiAgICAgR2l2ZW4gYSBjYWxsYmFjaywgaXRlcmF0ZXMgb3ZlciBlYWNoIG9mIHRoZSByZWxhdGlvbnNoaXBzIGluIHRoZSBtb2RlbCwKICAgICBpbnZva2luZyB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgbmFtZSBvZiBlYWNoIHJlbGF0aW9uc2hpcCBhbmQgaXRzIHJlbGF0aW9uc2hpcAogICAgIGRlc2NyaXB0b3IuCiAgICAgIEBtZXRob2QgZWFjaFJlbGF0aW9uc2hpcAogICAgIEBzdGF0aWMKICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayB0aGUgY2FsbGJhY2sgdG8gaW52b2tlCiAgICAgQHBhcmFtIHthbnl9IGJpbmRpbmcgdGhlIHZhbHVlIHRvIHdoaWNoIHRoZSBjYWxsYmFjaydzIGB0aGlzYCBzaG91bGQgYmUgYm91bmQKICAgICAqLwogICAgZWFjaFJlbGF0aW9uc2hpcDogZnVuY3Rpb24gZWFjaFJlbGF0aW9uc2hpcChjYWxsYmFjaywgYmluZGluZykgewogICAgICBFbWJlci5nZXQodGhpcywgJ3JlbGF0aW9uc2hpcHNCeU5hbWUnKS5mb3JFYWNoKGZ1bmN0aW9uIChyZWxhdGlvbnNoaXAsIG5hbWUpIHsKICAgICAgICBjYWxsYmFjay5jYWxsKGJpbmRpbmcsIG5hbWUsIHJlbGF0aW9uc2hpcCk7CiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICBHaXZlbiBhIGNhbGxiYWNrLCBpdGVyYXRlcyBvdmVyIGVhY2ggb2YgdGhlIHR5cGVzIHJlbGF0ZWQgdG8gYSBtb2RlbCwKICAgICBpbnZva2luZyB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgcmVsYXRlZCB0eXBlJ3MgY2xhc3MuIEVhY2ggdHlwZSB3aWxsIGJlCiAgICAgcmV0dXJuZWQganVzdCBvbmNlLCByZWdhcmRsZXNzIG9mIGhvdyBtYW55IGRpZmZlcmVudCByZWxhdGlvbnNoaXBzIGl0IGhhcwogICAgIHdpdGggYSBtb2RlbC4KICAgICAgQG1ldGhvZCBlYWNoUmVsYXRlZFR5cGUKICAgICBAc3RhdGljCiAgICAgQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgdGhlIGNhbGxiYWNrIHRvIGludm9rZQogICAgIEBwYXJhbSB7YW55fSBiaW5kaW5nIHRoZSB2YWx1ZSB0byB3aGljaCB0aGUgY2FsbGJhY2sncyBgdGhpc2Agc2hvdWxkIGJlIGJvdW5kCiAgICAgKi8KICAgIGVhY2hSZWxhdGVkVHlwZTogZnVuY3Rpb24gZWFjaFJlbGF0ZWRUeXBlKGNhbGxiYWNrLCBiaW5kaW5nKSB7CiAgICAgIHZhciByZWxhdGlvbnNoaXBUeXBlcyA9IEVtYmVyLmdldCh0aGlzLCAncmVsYXRlZFR5cGVzJyk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbGF0aW9uc2hpcFR5cGVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIHR5cGUgPSByZWxhdGlvbnNoaXBUeXBlc1tpXTsKICAgICAgICBjYWxsYmFjay5jYWxsKGJpbmRpbmcsIHR5cGUpOwogICAgICB9CiAgICB9LAogICAgZGV0ZXJtaW5lUmVsYXRpb25zaGlwVHlwZTogZnVuY3Rpb24gZGV0ZXJtaW5lUmVsYXRpb25zaGlwVHlwZShrbm93blNpZGUsIHN0b3JlKSB7CiAgICAgIHZhciBrbm93bktleSA9IGtub3duU2lkZS5rZXk7CiAgICAgIHZhciBrbm93bktpbmQgPSBrbm93blNpZGUua2luZDsKICAgICAgdmFyIGludmVyc2UgPSB0aGlzLmludmVyc2VGb3Ioa25vd25LZXksIHN0b3JlKTsgLy8gbGV0IGtleTsKCiAgICAgIHZhciBvdGhlcktpbmQ7CgogICAgICBpZiAoIWludmVyc2UpIHsKICAgICAgICByZXR1cm4ga25vd25LaW5kID09PSAnYmVsb25nc1RvJyA/ICdvbmVUb05vbmUnIDogJ21hbnlUb05vbmUnOwogICAgICB9IC8vIGtleSA9IGludmVyc2UubmFtZTsKCgogICAgICBvdGhlcktpbmQgPSBpbnZlcnNlLmtpbmQ7CgogICAgICBpZiAob3RoZXJLaW5kID09PSAnYmVsb25nc1RvJykgewogICAgICAgIHJldHVybiBrbm93bktpbmQgPT09ICdiZWxvbmdzVG8nID8gJ29uZVRvT25lJyA6ICdtYW55VG9PbmUnOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBrbm93bktpbmQgPT09ICdiZWxvbmdzVG8nID8gJ29uZVRvTWFueScgOiAnbWFueVRvTWFueSc7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgQSBtYXAgd2hvc2Uga2V5cyBhcmUgdGhlIGF0dHJpYnV0ZXMgb2YgdGhlIG1vZGVsIChwcm9wZXJ0aWVzCiAgICAgZGVzY3JpYmVkIGJ5IGF0dHIpIGFuZCB3aG9zZSB2YWx1ZXMgYXJlIHRoZSBtZXRhIG9iamVjdCBmb3IgdGhlCiAgICAgcHJvcGVydHkuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgYXBwL21vZGVscy9wZXJzb24uanMKICAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICBmaXJzdE5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICAgIGxhc3ROYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgICBiaXJ0aGRheTogYXR0cignZGF0ZScpCiAgICAgIH0pOwogICAgIGBgYAogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgaW1wb3J0IEVtYmVyIGZyb20gJ2VtYmVyJzsKICAgICBpbXBvcnQgUGVyc29uIGZyb20gJ2FwcC9tb2RlbHMvcGVyc29uJzsKICAgICAgbGV0IGF0dHJpYnV0ZXMgPSBFbWJlci5nZXQoUGVyc29uLCAnYXR0cmlidXRlcycpCiAgICAgIGF0dHJpYnV0ZXMuZm9yRWFjaChmdW5jdGlvbihtZXRhLCBuYW1lKSB7CiAgICAgICAgY29uc29sZS5sb2cobmFtZSwgbWV0YSk7CiAgICAgIH0pOwogICAgICAvLyBwcmludHM6CiAgICAgLy8gZmlyc3ROYW1lIHt0eXBlOiAic3RyaW5nIiwgaXNBdHRyaWJ1dGU6IHRydWUsIG9wdGlvbnM6IE9iamVjdCwgcGFyZW50VHlwZTogZnVuY3Rpb24sIG5hbWU6ICJmaXJzdE5hbWUifQogICAgIC8vIGxhc3ROYW1lIHt0eXBlOiAic3RyaW5nIiwgaXNBdHRyaWJ1dGU6IHRydWUsIG9wdGlvbnM6IE9iamVjdCwgcGFyZW50VHlwZTogZnVuY3Rpb24sIG5hbWU6ICJsYXN0TmFtZSJ9CiAgICAgLy8gYmlydGhkYXkge3R5cGU6ICJkYXRlIiwgaXNBdHRyaWJ1dGU6IHRydWUsIG9wdGlvbnM6IE9iamVjdCwgcGFyZW50VHlwZTogZnVuY3Rpb24sIG5hbWU6ICJiaXJ0aGRheSJ9CiAgICAgYGBgCiAgICAgIEBwcm9wZXJ0eSBhdHRyaWJ1dGVzCiAgICAgQHN0YXRpYwogICAgIEB0eXBlIHtNYXB9CiAgICAgQHJlYWRPbmx5CiAgICAgKi8KICAgIGF0dHJpYnV0ZXM6IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKCiAgICAgIHZhciBtYXAgPSBuZXcgTWFwKCk7CiAgICAgIHRoaXMuZWFjaENvbXB1dGVkUHJvcGVydHkoZnVuY3Rpb24gKG5hbWUsIG1ldGEpIHsKICAgICAgICBpZiAobWV0YS5pc0F0dHJpYnV0ZSkgewogICAgICAgICAgbWV0YS5uYW1lID0gbmFtZTsKICAgICAgICAgIG1hcC5zZXQobmFtZSwgbWV0YSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIG1hcDsKICAgIH0pLnJlYWRPbmx5KCksCgogICAgLyoqCiAgICAgQSBtYXAgd2hvc2Uga2V5cyBhcmUgdGhlIGF0dHJpYnV0ZXMgb2YgdGhlIG1vZGVsIChwcm9wZXJ0aWVzCiAgICAgZGVzY3JpYmVkIGJ5IGF0dHIpIGFuZCB3aG9zZSB2YWx1ZXMgYXJlIHR5cGUgb2YgdHJhbnNmb3JtYXRpb24KICAgICBhcHBsaWVkIHRvIGVhY2ggYXR0cmlidXRlLiBUaGlzIG1hcCBkb2VzIG5vdCBpbmNsdWRlIGFueQogICAgIGF0dHJpYnV0ZXMgdGhhdCBkbyBub3QgaGF2ZSBhbiB0cmFuc2Zvcm1hdGlvbiB0eXBlLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGFwcC9tb2RlbHMvcGVyc29uLmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgZmlyc3ROYW1lOiBhdHRyKCksCiAgICAgICAgbGFzdE5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICAgIGJpcnRoZGF5OiBhdHRyKCdkYXRlJykKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBpbXBvcnQgRW1iZXIgZnJvbSAnZW1iZXInOwogICAgIGltcG9ydCBQZXJzb24gZnJvbSAnYXBwL21vZGVscy9wZXJzb24nOwogICAgICBsZXQgdHJhbnNmb3JtZWRBdHRyaWJ1dGVzID0gRW1iZXIuZ2V0KFBlcnNvbiwgJ3RyYW5zZm9ybWVkQXR0cmlidXRlcycpCiAgICAgIHRyYW5zZm9ybWVkQXR0cmlidXRlcy5mb3JFYWNoKGZ1bmN0aW9uKGZpZWxkLCB0eXBlKSB7CiAgICAgICAgY29uc29sZS5sb2coZmllbGQsIHR5cGUpOwogICAgICB9KTsKICAgICAgLy8gcHJpbnRzOgogICAgIC8vIGxhc3ROYW1lIHN0cmluZwogICAgIC8vIGJpcnRoZGF5IGRhdGUKICAgICBgYGAKICAgICAgQHByb3BlcnR5IHRyYW5zZm9ybWVkQXR0cmlidXRlcwogICAgIEBzdGF0aWMKICAgICBAdHlwZSB7TWFwfQogICAgIEByZWFkT25seQogICAgICovCiAgICB0cmFuc2Zvcm1lZEF0dHJpYnV0ZXM6IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIG1hcCA9IG5ldyBNYXAoKTsKICAgICAgdGhpcy5lYWNoQXR0cmlidXRlKGZ1bmN0aW9uIChrZXksIG1ldGEpIHsKICAgICAgICBpZiAobWV0YS50eXBlKSB7CiAgICAgICAgICBtYXAuc2V0KGtleSwgbWV0YS50eXBlKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gbWFwOwogICAgfSkucmVhZE9ubHkoKSwKCiAgICAvKioKICAgICBJdGVyYXRlcyB0aHJvdWdoIHRoZSBhdHRyaWJ1dGVzIG9mIHRoZSBtb2RlbCwgY2FsbGluZyB0aGUgcGFzc2VkIGZ1bmN0aW9uIG9uIGVhY2gKICAgICBhdHRyaWJ1dGUuCiAgICAgIFRoZSBjYWxsYmFjayBtZXRob2QgeW91IHByb3ZpZGUgc2hvdWxkIGhhdmUgdGhlIGZvbGxvd2luZyBzaWduYXR1cmUgKGFsbAogICAgIHBhcmFtZXRlcnMgYXJlIG9wdGlvbmFsKToKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGZ1bmN0aW9uKG5hbWUsIG1ldGEpOwogICAgIGBgYAogICAgICAtIGBuYW1lYCB0aGUgbmFtZSBvZiB0aGUgY3VycmVudCBwcm9wZXJ0eSBpbiB0aGUgaXRlcmF0aW9uCiAgICAgLSBgbWV0YWAgdGhlIG1ldGEgb2JqZWN0IGZvciB0aGUgYXR0cmlidXRlIHByb3BlcnR5IGluIHRoZSBpdGVyYXRpb24KICAgICAgTm90ZSB0aGF0IGluIGFkZGl0aW9uIHRvIGEgY2FsbGJhY2ssIHlvdSBjYW4gYWxzbyBwYXNzIGFuIG9wdGlvbmFsIHRhcmdldAogICAgIG9iamVjdCB0aGF0IHdpbGwgYmUgc2V0IGFzIGB0aGlzYCBvbiB0aGUgY29udGV4dC4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgIGxldCBQZXJzb24gPSBNb2RlbC5leHRlbmQoewogICAgICAgIGZpcnN0TmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgICAgbGFzdE5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICAgIGJpcnRoZGF5OiBhdHRyKCdkYXRlJykKICAgICAgfSk7CiAgICAgIFBlcnNvbi5lYWNoQXR0cmlidXRlKGZ1bmN0aW9uKG5hbWUsIG1ldGEpIHsKICAgICAgICBjb25zb2xlLmxvZyhuYW1lLCBtZXRhKTsKICAgICAgfSk7CiAgICAgIC8vIHByaW50czoKICAgICAvLyBmaXJzdE5hbWUge3R5cGU6ICJzdHJpbmciLCBpc0F0dHJpYnV0ZTogdHJ1ZSwgb3B0aW9uczogT2JqZWN0LCBwYXJlbnRUeXBlOiBmdW5jdGlvbiwgbmFtZTogImZpcnN0TmFtZSJ9CiAgICAgLy8gbGFzdE5hbWUge3R5cGU6ICJzdHJpbmciLCBpc0F0dHJpYnV0ZTogdHJ1ZSwgb3B0aW9uczogT2JqZWN0LCBwYXJlbnRUeXBlOiBmdW5jdGlvbiwgbmFtZTogImxhc3ROYW1lIn0KICAgICAvLyBiaXJ0aGRheSB7dHlwZTogImRhdGUiLCBpc0F0dHJpYnV0ZTogdHJ1ZSwgb3B0aW9uczogT2JqZWN0LCBwYXJlbnRUeXBlOiBmdW5jdGlvbiwgbmFtZTogImJpcnRoZGF5In0KICAgICBgYGAKICAgICAgQG1ldGhvZCBlYWNoQXR0cmlidXRlCiAgICAgQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGNhbGxiYWNrIHRvIGV4ZWN1dGUKICAgICBAcGFyYW0ge09iamVjdH0gW2JpbmRpbmddIHRoZSB2YWx1ZSB0byB3aGljaCB0aGUgY2FsbGJhY2sncyBgdGhpc2Agc2hvdWxkIGJlIGJvdW5kCiAgICAgQHN0YXRpYwogICAgICovCiAgICBlYWNoQXR0cmlidXRlOiBmdW5jdGlvbiBlYWNoQXR0cmlidXRlKGNhbGxiYWNrLCBiaW5kaW5nKSB7CiAgICAgIEVtYmVyLmdldCh0aGlzLCAnYXR0cmlidXRlcycpLmZvckVhY2goZnVuY3Rpb24gKG1ldGEsIG5hbWUpIHsKICAgICAgICBjYWxsYmFjay5jYWxsKGJpbmRpbmcsIG5hbWUsIG1ldGEpOwogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgSXRlcmF0ZXMgdGhyb3VnaCB0aGUgdHJhbnNmb3JtZWRBdHRyaWJ1dGVzIG9mIHRoZSBtb2RlbCwgY2FsbGluZwogICAgIHRoZSBwYXNzZWQgZnVuY3Rpb24gb24gZWFjaCBhdHRyaWJ1dGUuIE5vdGUgdGhlIGNhbGxiYWNrIHdpbGwgbm90IGJlCiAgICAgY2FsbGVkIGZvciBhbnkgYXR0cmlidXRlcyB0aGF0IGRvIG5vdCBoYXZlIGFuIHRyYW5zZm9ybWF0aW9uIHR5cGUuCiAgICAgIFRoZSBjYWxsYmFjayBtZXRob2QgeW91IHByb3ZpZGUgc2hvdWxkIGhhdmUgdGhlIGZvbGxvd2luZyBzaWduYXR1cmUgKGFsbAogICAgIHBhcmFtZXRlcnMgYXJlIG9wdGlvbmFsKToKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGZ1bmN0aW9uKG5hbWUsIHR5cGUpOwogICAgIGBgYAogICAgICAtIGBuYW1lYCB0aGUgbmFtZSBvZiB0aGUgY3VycmVudCBwcm9wZXJ0eSBpbiB0aGUgaXRlcmF0aW9uCiAgICAgLSBgdHlwZWAgYSBzdHJpbmcgY29udGFpbmluZyB0aGUgbmFtZSBvZiB0aGUgdHlwZSBvZiB0cmFuc2Zvcm1lZAogICAgIGFwcGxpZWQgdG8gdGhlIGF0dHJpYnV0ZQogICAgICBOb3RlIHRoYXQgaW4gYWRkaXRpb24gdG8gYSBjYWxsYmFjaywgeW91IGNhbiBhbHNvIHBhc3MgYW4gb3B0aW9uYWwgdGFyZ2V0CiAgICAgb2JqZWN0IHRoYXQgd2lsbCBiZSBzZXQgYXMgYHRoaXNgIG9uIHRoZSBjb250ZXh0LgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgbGV0IFBlcnNvbiA9IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgZmlyc3ROYW1lOiBhdHRyKCksCiAgICAgICAgbGFzdE5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICAgIGJpcnRoZGF5OiBhdHRyKCdkYXRlJykKICAgICAgfSk7CiAgICAgIFBlcnNvbi5lYWNoVHJhbnNmb3JtZWRBdHRyaWJ1dGUoZnVuY3Rpb24obmFtZSwgdHlwZSkgewogICAgICAgIGNvbnNvbGUubG9nKG5hbWUsIHR5cGUpOwogICAgICB9KTsKICAgICAgLy8gcHJpbnRzOgogICAgIC8vIGxhc3ROYW1lIHN0cmluZwogICAgIC8vIGJpcnRoZGF5IGRhdGUKICAgICBgYGAKICAgICAgQG1ldGhvZCBlYWNoVHJhbnNmb3JtZWRBdHRyaWJ1dGUKICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgY2FsbGJhY2sgdG8gZXhlY3V0ZQogICAgIEBwYXJhbSB7T2JqZWN0fSBbYmluZGluZ10gdGhlIHZhbHVlIHRvIHdoaWNoIHRoZSBjYWxsYmFjaydzIGB0aGlzYCBzaG91bGQgYmUgYm91bmQKICAgICBAc3RhdGljCiAgICAgKi8KICAgIGVhY2hUcmFuc2Zvcm1lZEF0dHJpYnV0ZTogZnVuY3Rpb24gZWFjaFRyYW5zZm9ybWVkQXR0cmlidXRlKGNhbGxiYWNrLCBiaW5kaW5nKSB7CiAgICAgIEVtYmVyLmdldCh0aGlzLCAndHJhbnNmb3JtZWRBdHRyaWJ1dGVzJykuZm9yRWFjaChmdW5jdGlvbiAodHlwZSwgbmFtZSkgewogICAgICAgIGNhbGxiYWNrLmNhbGwoYmluZGluZywgbmFtZSwgdHlwZSk7CiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICBSZXR1cm5zIHRoZSBuYW1lIG9mIHRoZSBtb2RlbCBjbGFzcy4KICAgICAgQG1ldGhvZCB0b1N0cmluZwogICAgIEBzdGF0aWMKICAgICAqLwogICAgdG9TdHJpbmc6IGZ1bmN0aW9uIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gIm1vZGVsOiIgKyBFbWJlci5nZXQodGhpcywgJ21vZGVsTmFtZScpOwogICAgfQogIH0pOwoKICBleHBvcnRzLk1vZGVsID0gTW9kZWw7CiAgZXhwb3J0cy5hdHRyID0gYXR0ciQxOwogIGV4cG9ydHMuYmVsb25nc1RvID0gYmVsb25nc1RvJDE7CiAgZXhwb3J0cy5oYXNNYW55ID0gaGFzTWFueSQxOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pOwoKfSk7Cgo7ZGVmaW5lKCJAZW1iZXItZGF0YS9tb2RlbC9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9tb2RlbC8tcHJpdmF0ZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9wcml2YXRlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJkZWZhdWx0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUuTW9kZWw7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiYXR0ciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9wcml2YXRlLmF0dHI7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiYmVsb25nc1RvIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUuYmVsb25nc1RvOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImhhc01hbnkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJpdmF0ZS5oYXNNYW55OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgnQGVtYmVyLWRhdGEvcmVjb3JkLWRhdGEvLXByaXZhdGUnLCBbJ2V4cG9ydHMnLCAnQGVtYmVyLWRhdGEvc3RvcmUvLXByaXZhdGUnLCAnQGVtYmVyL29yZGVyZWQtc2V0JywgJ0BlbWJlci1kYXRhL2NhbmFyeS1mZWF0dXJlcyddLCBmdW5jdGlvbiAoZXhwb3J0cywgUHJpdmF0ZSwgRW1iZXJPcmRlcmVkU2V0LCBjYW5hcnlGZWF0dXJlcykgeyAndXNlIHN0cmljdCc7CgogIEVtYmVyT3JkZXJlZFNldCA9IEVtYmVyT3JkZXJlZFNldCAmJiBFbWJlck9yZGVyZWRTZXQuaGFzT3duUHJvcGVydHkoJ2RlZmF1bHQnKSA/IEVtYmVyT3JkZXJlZFNldFsnZGVmYXVsdCddIDogRW1iZXJPcmRlcmVkU2V0OwoKICBmdW5jdGlvbiByZWxhdGlvbnNoaXBzRm9yKGluc3RhbmNlKSB7CiAgICB2YXIgcmVjb3JkRGF0YSA9IFByaXZhdGUucmVjb3JkRGF0YUZvcihpbnN0YW5jZSkgfHwgaW5zdGFuY2U7CiAgICByZXR1cm4gcmVjb3JkRGF0YS5fcmVsYXRpb25zaGlwczsKICB9CiAgZnVuY3Rpb24gcmVsYXRpb25zaGlwU3RhdGVGb3IoaW5zdGFuY2UsIHByb3BlcnR5TmFtZSkgewogICAgcmV0dXJuIHJlbGF0aW9uc2hpcHNGb3IoaW5zdGFuY2UpLmdldChwcm9wZXJ0eU5hbWUpOwogIH0KICBmdW5jdGlvbiBpbXBsaWNpdFJlbGF0aW9uc2hpcHNGb3IoaW5zdGFuY2UpIHsKICAgIHZhciByZWNvcmREYXRhID0gUHJpdmF0ZS5yZWNvcmREYXRhRm9yKGluc3RhbmNlKSB8fCBpbnN0YW5jZTsKICAgIHJldHVybiByZWNvcmREYXRhLl9pbXBsaWNpdFJlbGF0aW9uc2hpcHM7CiAgfQogIGZ1bmN0aW9uIGltcGxpY2l0UmVsYXRpb25zaGlwU3RhdGVGb3IoaW5zdGFuY2UsIHByb3BlcnR5TmFtZSkgewogICAgcmV0dXJuIGltcGxpY2l0UmVsYXRpb25zaGlwc0ZvcihpbnN0YW5jZSlbcHJvcGVydHlOYW1lXTsKICB9CgogIGZ1bmN0aW9uIF9pbmhlcml0c0xvb3NlKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcy5wcm90b3R5cGUpOyBzdWJDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBzdWJDbGFzczsgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfQoKICB2YXIgRW1iZXJEYXRhT3JkZXJlZFNldCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW1iZXJPcmRlcmVkU2V0KSB7CiAgICBfaW5oZXJpdHNMb29zZShFbWJlckRhdGFPcmRlcmVkU2V0LCBfRW1iZXJPcmRlcmVkU2V0KTsKCiAgICBmdW5jdGlvbiBFbWJlckRhdGFPcmRlcmVkU2V0KCkgewogICAgICByZXR1cm4gX0VtYmVyT3JkZXJlZFNldC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgRW1iZXJEYXRhT3JkZXJlZFNldC5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoKSB7CiAgICAgIHJldHVybiBuZXcgdGhpcygpOwogICAgfTsKCiAgICB2YXIgX3Byb3RvID0gRW1iZXJEYXRhT3JkZXJlZFNldC5wcm90b3R5cGU7CgogICAgX3Byb3RvLmFkZFdpdGhJbmRleCA9IGZ1bmN0aW9uIGFkZFdpdGhJbmRleChvYmosIGlkeCkgewogICAgICB2YXIgZ3VpZCA9IEVtYmVyLmd1aWRGb3Iob2JqKTsKICAgICAgdmFyIHByZXNlbmNlU2V0ID0gdGhpcy5wcmVzZW5jZVNldDsKICAgICAgdmFyIGxpc3QgPSB0aGlzLmxpc3Q7CgogICAgICBpZiAocHJlc2VuY2VTZXRbZ3VpZF0gPT09IHRydWUpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHByZXNlbmNlU2V0W2d1aWRdID0gdHJ1ZTsKCiAgICAgIGlmIChpZHggPT09IHVuZGVmaW5lZCB8fCBpZHggPT09IG51bGwpIHsKICAgICAgICBsaXN0LnB1c2gob2JqKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBsaXN0LnNwbGljZShpZHgsIDAsIG9iaik7CiAgICAgIH0KCiAgICAgIHRoaXMuc2l6ZSArPSAxOwogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgcmV0dXJuIEVtYmVyRGF0YU9yZGVyZWRTZXQ7CiAgfShFbWJlck9yZGVyZWRTZXQpOwoKICAvKgogICAgVGhpcyBtZXRob2Qgbm9ybWFsaXplcyBhIGxpbmsgdG8gYW4gImxpbmtzIG9iamVjdCIuIElmIHRoZSBwYXNzZWQgbGluayBpcwogICAgYWxyZWFkeSBhbiBvYmplY3QgaXQncyByZXR1cm5lZCB3aXRob3V0IGFueSBtb2RpZmljYXRpb25zLgoKICAgIFNlZSBodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0LyNkb2N1bWVudC1saW5rcyBmb3IgbW9yZSBpbmZvcm1hdGlvbi4KCiAgICBAbWV0aG9kIF9ub3JtYWxpemVMaW5rCiAgICBAaW50ZXJuYWwKICAgIEBwYXJhbSB7U3RyaW5nfSBsaW5rCiAgICBAcmV0dXJuIHtPYmplY3R8bnVsbH0KICAqLwogIGZ1bmN0aW9uIF9ub3JtYWxpemVMaW5rKGxpbmspIHsKICAgIHN3aXRjaCAodHlwZW9mIGxpbmspIHsKICAgICAgY2FzZSAnb2JqZWN0JzoKICAgICAgICByZXR1cm4gbGluazsKCiAgICAgIGNhc2UgJ3N0cmluZyc6CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGhyZWY6IGxpbmsKICAgICAgICB9OwogICAgfQoKICAgIHJldHVybiBudWxsOwogIH0KCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoInZhbHVlIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0KCiAgZnVuY3Rpb24gX2NyZWF0ZUNsYXNzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH0KICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICB2YXIgUmVsYXRpb25zaGlwID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUmVsYXRpb25zaGlwKHN0b3JlLCBpbnZlcnNlS2V5LCByZWxhdGlvbnNoaXBNZXRhLCByZWNvcmREYXRhLCBpbnZlcnNlSXNBc3luYykgewogICAgICB0aGlzLmludmVyc2VJc0FzeW5jID0gdm9pZCAwOwogICAgICB0aGlzLmtpbmQgPSB2b2lkIDA7CiAgICAgIHRoaXMucmVjb3JkRGF0YSA9IHZvaWQgMDsKICAgICAgdGhpcy5tZW1iZXJzID0gdm9pZCAwOwogICAgICB0aGlzLmNhbm9uaWNhbE1lbWJlcnMgPSB2b2lkIDA7CiAgICAgIHRoaXMuc3RvcmUgPSB2b2lkIDA7CiAgICAgIHRoaXMua2V5ID0gdm9pZCAwOwogICAgICB0aGlzLmludmVyc2VLZXkgPSB2b2lkIDA7CiAgICAgIHRoaXMuaXNBc3luYyA9IHZvaWQgMDsKICAgICAgdGhpcy5pc1BvbHltb3JwaGljID0gdm9pZCAwOwogICAgICB0aGlzLnJlbGF0aW9uc2hpcE1ldGEgPSB2b2lkIDA7CiAgICAgIHRoaXMuaW52ZXJzZUtleUZvckltcGxpY2l0ID0gdm9pZCAwOwogICAgICB0aGlzLm1ldGEgPSB2b2lkIDA7CiAgICAgIHRoaXMuX19pbnZlcnNlTWV0YSA9IHZvaWQgMDsKICAgICAgdGhpcy5fdGVtcE1vZGVsTmFtZSA9IHZvaWQgMDsKICAgICAgdGhpcy5zaG91bGRGb3JjZVJlbG9hZCA9IGZhbHNlOwogICAgICB0aGlzLnJlbGF0aW9uc2hpcElzU3RhbGUgPSB2b2lkIDA7CiAgICAgIHRoaXMuaGFzRGVtYXRlcmlhbGl6ZWRJbnZlcnNlID0gdm9pZCAwOwogICAgICB0aGlzLmhhc0FueVJlbGF0aW9uc2hpcERhdGEgPSB2b2lkIDA7CiAgICAgIHRoaXMucmVsYXRpb25zaGlwSXNFbXB0eSA9IHZvaWQgMDsKICAgICAgdGhpcy5oYXNGYWlsZWRMb2FkQXR0ZW1wdCA9IGZhbHNlOwogICAgICB0aGlzLmxpbmsgPSB2b2lkIDA7CiAgICAgIHRoaXMud2lsbFN5bmMgPSB2b2lkIDA7CiAgICAgIHRoaXMuaW52ZXJzZUlzQXN5bmMgPSBpbnZlcnNlSXNBc3luYzsKICAgICAgdGhpcy5raW5kID0gcmVsYXRpb25zaGlwTWV0YS5raW5kOwogICAgICB2YXIgYXN5bmMgPSByZWxhdGlvbnNoaXBNZXRhLm9wdGlvbnMuYXN5bmM7CiAgICAgIHZhciBwb2x5bW9ycGhpYyA9IHJlbGF0aW9uc2hpcE1ldGEub3B0aW9ucy5wb2x5bW9ycGhpYzsKICAgICAgdGhpcy5yZWNvcmREYXRhID0gcmVjb3JkRGF0YTsKICAgICAgdGhpcy5tZW1iZXJzID0gbmV3IEVtYmVyRGF0YU9yZGVyZWRTZXQoKTsKICAgICAgdGhpcy5jYW5vbmljYWxNZW1iZXJzID0gbmV3IEVtYmVyRGF0YU9yZGVyZWRTZXQoKTsKICAgICAgdGhpcy5zdG9yZSA9IHN0b3JlOwogICAgICB0aGlzLmtleSA9IHJlbGF0aW9uc2hpcE1ldGEua2V5IHx8IG51bGw7CiAgICAgIHRoaXMuaW52ZXJzZUtleSA9IGludmVyc2VLZXk7CiAgICAgIHRoaXMuaXNBc3luYyA9IHR5cGVvZiBhc3luYyA9PT0gJ3VuZGVmaW5lZCcgPyB0cnVlIDogYXN5bmM7CiAgICAgIHRoaXMuaXNQb2x5bW9ycGhpYyA9IHR5cGVvZiBwb2x5bW9ycGhpYyA9PT0gJ3VuZGVmaW5lZCcgPyBmYWxzZSA6IHBvbHltb3JwaGljOwogICAgICB0aGlzLnJlbGF0aW9uc2hpcE1ldGEgPSByZWxhdGlvbnNoaXBNZXRhOyAvL1RoaXMgcHJvYmFibHkgYnJlYWtzIGZvciBwb2x5bW9ycGhpYyByZWxhdGlvbnNoaXAgaW4gY29tcGxleCBzY2VuYXJpb3MsIGR1ZSB0bwogICAgICAvL211bHRpcGxlIHBvc3NpYmxlIG1vZGVsTmFtZXMKCiAgICAgIHRoaXMuaW52ZXJzZUtleUZvckltcGxpY2l0ID0gdGhpcy5fdGVtcE1vZGVsTmFtZSArIHRoaXMua2V5OwogICAgICB0aGlzLm1ldGEgPSBudWxsOwogICAgICB0aGlzLl9faW52ZXJzZU1ldGEgPSB1bmRlZmluZWQ7CiAgICAgIC8qCiAgICAgICBUaGlzIGZsYWcgZm9yY2VzIGZldGNoLiBgdHJ1ZWAgZm9yIGEgc2luZ2xlIHJlcXVlc3Qgb25jZSBgcmVsb2FkKClgCiAgICAgICAgIGhhcyBiZWVuIGNhbGxlZCBgZmFsc2VgIGF0IGFsbCBvdGhlciB0aW1lcy4KICAgICAgKi8KICAgICAgLy8gdGhpcy5zaG91bGRGb3JjZVJlbG9hZCA9IGZhbHNlOwoKICAgICAgLyoKICAgICAgICAgVGhpcyBmbGFnIGluZGljYXRlcyB3aGV0aGVyIHdlIHNob3VsZAogICAgICAgICAgcmUtZmV0Y2ggdGhlIHJlbGF0aW9uc2hpcCB0aGUgbmV4dCB0aW1lCiAgICAgICAgICBpdCBpcyBhY2Nlc3NlZC4KICAgICAgICAgICBUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoaXMgZmxhZyBhbmQgYHNob3VsZEZvcmNlUmVsb2FkYAogICAgICAgICAgaXMgaW4gaG93IHdlIHRyZWF0IHRoZSBwcmVzZW5jZSBvZiBwYXJ0aWFsbHkgbWlzc2luZyBkYXRhOgogICAgICAgICAgICAtIGZvciBhIGZvcmNlZCByZWxvYWQsIHdlIHdpbGwgcmVsb2FkIHRoZSBsaW5rIG9yIEVWRVJZIHJlY29yZAogICAgICAgICAgICAtIGZvciBhIHN0YWxlIHJlbG9hZCwgd2Ugd2lsbCByZWxvYWQgdGhlIGxpbmsgKGlmIHByZXNlbnQpIGVsc2Ugb25seSBNSVNTSU5HIHJlY29yZHMKICAgICAgICAgICBJZGVhbGx5IHRoZXNlIGZsYWdzIGNvdWxkIGJlIG1lcmdlZCwgYnV0IGJlY2F1c2Ugd2UgZG9uJ3QgZ2l2ZSB0aGUKICAgICAgICAgIHJlcXVlc3QgbGF5ZXIgdGhlIG9wdGlvbiBvZiBkZWNpZGluZyBob3cgdG8gcmVzb2x2ZSB0aGUgZGF0YSBiZWluZyBxdWVyaWVkCiAgICAgICAgICB3ZSBhcmUgZm9yY2VkIHRvIGRpZmZlcmVudGlhdGUgZm9yIG5vdy4KICAgICAgICAgICBJdCBpcyBhbHNvIHBvc3NpYmxlIGZvciBhIHJlbGF0aW9uc2hpcCB0byByZW1haW4gc3RhbGUgYWZ0ZXIgYSBmb3JjZWQgcmVsb2FkOyBob3dldmVyLAogICAgICAgICAgaW4gdGhpcyBjYXNlIGBoYXNGYWlsZWRMb2FkQXR0ZW1wdGAgb3VnaHQgdG8gYmUgYHRydWVgLgogICAgICAgICBmYWxzZSB3aGVuCiAgICAgICAgICA9PiByZWNvcmREYXRhLmlzTmV3KCkgb24gaW5pdGlhbCBzZXR1cAogICAgICAgICAgPT4gYSBwcmV2aW91c2x5IHRyaWdnZXJlZCByZXF1ZXN0IGhhcyByZXNvbHZlZAogICAgICAgICAgPT4gd2UgZ2V0IHJlbGF0aW9uc2hpcCBkYXRhIHZpYSBwdXNoCiAgICAgICAgIHRydWUgd2hlbgogICAgICAgICAgPT4gIXJlY29yZERhdGEuaXNOZXcoKSBvbiBpbml0aWFsIHNldHVwCiAgICAgICAgICA9PiBhbiBpbnZlcnNlIGhhcyBiZWVuIHVubG9hZGVkCiAgICAgICAgICA9PiB3ZSBnZXQgYSBuZXcgbGluayBmb3IgdGhlIHJlbGF0aW9uc2hpcAogICAgICAgICBUT0RPIEBydW5zcGlyZWQgdW5za2lwIHRoZSBhY2NlcHRhbmNlIHRlc3RzIGFuZCBmaXggdGhlc2UgZmxhZ3MKICAgICAgICovCgogICAgICB0aGlzLnJlbGF0aW9uc2hpcElzU3RhbGUgPSBmYWxzZTsKICAgICAgLyoKICAgICAgIFRoaXMgZmxhZyBpbmRpY2F0ZXMgd2hldGhlciB3ZSBzaG91bGQKICAgICAgICAqKnBhcnRpYWxseSoqIHJlLWZldGNoIHRoZSByZWxhdGlvbnNoaXAgdGhlCiAgICAgICAgbmV4dCB0aW1lIGl0IGlzIGFjY2Vzc2VkLgogICAgICAgZmFsc2Ugd2hlbgogICAgICAgID0+IGluaXRpYWwgc2V0dXAKICAgICAgICA9PiBhIHByZXZpb3VzbHkgdHJpZ2dlcmVkIHJlcXVlc3QgaGFzIHJlc29sdmVkCiAgICAgICB0cnVlIHdoZW4KICAgICAgICA9PiBhbiBpbnZlcnNlIGhhcyBiZWVuIHVubG9hZGVkCiAgICAgICovCgogICAgICB0aGlzLmhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSA9IGZhbHNlOwogICAgICAvKgogICAgICAgIFRoaXMgZmxhZyBpbmRpY2F0ZXMgd2hldGhlciB3ZSBzaG91bGQgY29uc2lkZXIgdGhlIGNvbnRlbnQKICAgICAgICAgb2YgdGhpcyByZWxhdGlvbnNoaXAgImtub3duIi4KICAgICAgICAgSWYgd2UgaGF2ZSBubyByZWxhdGlvbnNoaXAga25vd2xlZGdlLCBhbmQgdGhlIHJlbGF0aW9uc2hpcAogICAgICAgICBpcyBgYXN5bmNgLCB3ZSB3aWxsIGF0dGVtcHQgdG8gZmV0Y2ggdGhlIHJlbGF0aW9uc2hpcCBvbgogICAgICAgICBhY2Nlc3MgaWYgaXQgaXMgYWxzbyBzdGFsZS4KICAgICAgICBTbmFwc2hvdCB1c2VzIHRoaXMgdG8gdGVsbCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHVua25vd24KICAgICAgICAoYHVuZGVmaW5lZGApIG9yIGVtcHR5IChgbnVsbGApLiBUaGUgcmVhc29uIGZvciB0aGlzIGlzIHRoYXQKICAgICAgICB3ZSB3b3VsZG4ndCB3YW50IHRvIHNlcmlhbGl6ZSAgdW5rbm93biByZWxhdGlvbnNoaXBzIGFzIGBudWxsYAogICAgICAgIGFzIHRoYXQgbWlnaHQgb3ZlcndyaXRlIHJlbW90ZSBzdGF0ZS4KICAgICAgICAgQWxsIHJlbGF0aW9uc2hpcHMgZm9yIGEgbmV3bHkgY3JlYXRlZCAoYHN0b3JlLmNyZWF0ZVJlY29yZCgpYCkgYXJlCiAgICAgICAgIGNvbnNpZGVyZWQga25vd24gKGBoYXNBbnlSZWxhdGlvbnNoaXBEYXRhID09PSB0cnVlYCkuCiAgICAgICAgIHRydWUgd2hlbgogICAgICAgICAgPT4gd2UgcmVjZWl2ZSBhIHB1c2ggd2l0aCBlaXRoZXIgbmV3IGRhdGEgb3IgZXhwbGljaXQgZW1wdHkgKGBbXWAgb3IgYG51bGxgKQogICAgICAgICAgPT4gdGhlIHJlbGF0aW9uc2hpcCBpcyBhIGJlbG9uZ3NUbyBhbmQgd2UgaGF2ZSByZWNlaXZlZCBkYXRhIGZyb20KICAgICAgICAgICAgICAgdGhlIG90aGVyIHNpZGUuCiAgICAgICAgIGZhbHNlIHdoZW4KICAgICAgICAgID0+IHdlIGhhdmUgcmVjZWl2ZWQgbm8gc2lnbmFsIGFib3V0IHdoYXQgZGF0YSBiZWxvbmdzIGluIHRoaXMgcmVsYXRpb25zaGlwCiAgICAgICAgICA9PiB0aGUgcmVsYXRpb25zaGlwIGlzIGEgaGFzTWFueSBhbmQgd2UgaGF2ZSBvbmx5IHJlY2VpdmVkIGRhdGEgZnJvbQogICAgICAgICAgICAgIHRoZSBvdGhlciBzaWRlLgogICAgICAgKi8KCiAgICAgIHRoaXMuaGFzQW55UmVsYXRpb25zaGlwRGF0YSA9IGZhbHNlOwogICAgICAvKgogICAgICAgIEZsYWcgdGhhdCBpbmRpY2F0ZXMgd2hldGhlciBhbiBlbXB0eSByZWxhdGlvbnNoaXAgaXMgZXhwbGljaXRseSBlbXB0eQogICAgICAgICAgKHNpZ25hbGVkIGJ5IHB1c2ggZ2l2aW5nIHVzIGFuIGVtcHR5IGFycmF5IG9yIG51bGwgcmVsYXRpb25zaGlwKQogICAgICAgICAgZS5nLiBhbiBBUEkgcmVzcG9uc2UgaGFzIHRvbGQgdXMgdGhhdCB0aGlzIHJlbGF0aW9uc2hpcCBpcyBlbXB0eS4KICAgICAgICAgVGh1cyBmYXIsIGl0IGRvZXMgbm90IGFwcGVhciB0aGF0IHdlIGFjdHVhbGx5IG5lZWQgdGhpcyBmbGFnOyBob3dldmVyLAogICAgICAgICAgQHJ1bnNwaXJlZCBoYXMgZm91bmQgaXQgaW52YWx1YWJsZSB3aGVuIGRlYnVnZ2luZyByZWxhdGlvbnNoaXAgdGVzdHMKICAgICAgICAgIHRvIGRldGVybWluZSB3aGV0aGVyIChhbmQgd2h5IGlmIHNvKSB3ZSBhcmUgaW4gYW4gaW5jb3JyZWN0IHN0YXRlLgogICAgICAgICB0cnVlIHdoZW4KICAgICAgICAgID0+IHdlIHJlY2VpdmUgYSBwdXNoIHdpdGggZXhwbGljaXQgZW1wdHkgKGBbXWAgb3IgYG51bGxgKQogICAgICAgICAgPT4gd2UgaGF2ZSByZWNlaXZlZCBubyBzaWduYWwgYWJvdXQgd2hhdCBkYXRhIGJlbG9uZ3MgaW4gdGhpcyByZWxhdGlvbnNoaXAKICAgICAgICAgID0+IG9uIGluaXRpYWwgY3JlYXRlIChhcyBubyBzaWduYWwgaXMga25vd24geWV0KQogICAgICAgICBmYWxzZSBhdCBhbGwgb3RoZXIgdGltZXMKICAgICAgICovCgogICAgICB0aGlzLnJlbGF0aW9uc2hpcElzRW1wdHkgPSB0cnVlOwogICAgICAvKgogICAgICAgIEZsYWcgZGVmIGhlcmUgZm9yIHJlZmVyZW5jZSwgZGVmaW5lZCBhcyBnZXR0ZXIgaW4gaGFzLW1hbnkuanMgLyBiZWxvbmdzLXRvLmpzCiAgICAgICAgIHRydWUgd2hlbgogICAgICAgICAgPT4gaGFzQW55UmVsYXRpb25zaGlwRGF0YSBpcyB0cnVlCiAgICAgICAgICBBTkQKICAgICAgICAgID0+IG1lbWJlcnMgKE5PVCBjYW5vbmljYWxNZW1iZXJzKSBAZWFjaCAhaXNFbXB0eQogICAgICAgICBUT0RPLCBjb25zaWRlciBjaGFuZ2luZyB0aGUgY29uZGl0aW9uYWwgaGVyZSBmcm9tICFpc0VtcHR5IHRvICFoaWRkZW5Gcm9tUmVjb3JkQXJyYXlzCiAgICAgICovCiAgICAgIC8vIFRPRE8gZG8gd2Ugd2FudCB0aGlzIGFueW1vcmU/IFNlZW1zIHNvbWV3aGF0IHVzZWZ1bAogICAgICAvLyAgIGVzcGVjaWFsbHkgaWYgd2UgcmVuYW1lIHRvIGBoYXNVcGRhdGVkTGlua2AKICAgICAgLy8gICB3aGljaCB3b3VsZCB0ZWxsIHVzIHNsaWdodGx5IG1vcmUgYWJvdXQgd2h5IHRoZQogICAgICAvLyAgIHJlbGF0aW9uc2hpcCBpcyBzdGFsZQogICAgICAvLyB0aGlzLnVwZGF0ZWRMaW5rID0gZmFsc2U7CiAgICB9CgogICAgdmFyIF9wcm90byA9IFJlbGF0aW9uc2hpcC5wcm90b3R5cGU7CgogICAgX3Byb3RvLl9pbnZlcnNlSXNBc3luYyA9IGZ1bmN0aW9uIF9pbnZlcnNlSXNBc3luYygpIHsKICAgICAgcmV0dXJuICEhdGhpcy5pbnZlcnNlSXNBc3luYzsKICAgIH07CgogICAgX3Byb3RvLl9pbnZlcnNlSXNTeW5jID0gZnVuY3Rpb24gX2ludmVyc2VJc1N5bmMoKSB7CiAgICAgIHJldHVybiAhISh0aGlzLmludmVyc2VLZXkgJiYgIXRoaXMuaW52ZXJzZUlzQXN5bmMpOwogICAgfTsKCiAgICBfcHJvdG8uX2hhc1N1cHBvcnRGb3JJbXBsaWNpdFJlbGF0aW9uc2hpcHMgPSBmdW5jdGlvbiBfaGFzU3VwcG9ydEZvckltcGxpY2l0UmVsYXRpb25zaGlwcyhyZWNvcmREYXRhKSB7CiAgICAgIHJldHVybiByZWNvcmREYXRhLl9pbXBsaWNpdFJlbGF0aW9uc2hpcHMgIT09IHVuZGVmaW5lZCAmJiByZWNvcmREYXRhLl9pbXBsaWNpdFJlbGF0aW9uc2hpcHMgIT09IG51bGw7CiAgICB9OwoKICAgIF9wcm90by5faGFzU3VwcG9ydEZvclJlbGF0aW9uc2hpcHMgPSBmdW5jdGlvbiBfaGFzU3VwcG9ydEZvclJlbGF0aW9uc2hpcHMocmVjb3JkRGF0YSkgewogICAgICByZXR1cm4gcmVjb3JkRGF0YS5fcmVsYXRpb25zaGlwcyAhPT0gdW5kZWZpbmVkICYmIHJlY29yZERhdGEuX3JlbGF0aW9uc2hpcHMgIT09IG51bGw7CiAgICB9OwoKICAgIF9wcm90by5yZWNvcmREYXRhRGlkRGVtYXRlcmlhbGl6ZSA9IGZ1bmN0aW9uIHJlY29yZERhdGFEaWREZW1hdGVyaWFsaXplKCkgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgdmFyIGludmVyc2VLZXkgPSB0aGlzLmludmVyc2VLZXk7CgogICAgICBpZiAoIWludmVyc2VLZXkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gLy8gd2UgYWN0dWFsbHkgd2FudCBhIHVuaW9uIG9mIG1lbWJlcnMgYW5kIGNhbm9uaWNhbE1lbWJlcnMKICAgICAgLy8gdGhleSBzaG91bGQgYmUgZGlzam9pbnQgYnV0IGN1cnJlbnRseSBhcmUgbm90IGR1ZSB0byBhIGJ1ZwoKCiAgICAgIHRoaXMuZm9yQWxsTWVtYmVycyhmdW5jdGlvbiAoaW52ZXJzZVJlY29yZERhdGEpIHsKICAgICAgICBpZiAoIV90aGlzLl9oYXNTdXBwb3J0Rm9yUmVsYXRpb25zaGlwcyhpbnZlcnNlUmVjb3JkRGF0YSkpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHZhciByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXBTdGF0ZUZvcihpbnZlcnNlUmVjb3JkRGF0YSwgaW52ZXJzZUtleSk7CgogICAgICAgIHZhciBiZWxvbmdzVG9SZWxhdGlvbnNoaXAgPSBpbnZlcnNlUmVjb3JkRGF0YS5nZXRCZWxvbmdzVG8oaW52ZXJzZUtleSkuX3JlbGF0aW9uc2hpcDsgLy8gRm9yIGNhbm9uaWNhbCBtZW1iZXJzLCBpdCBpcyBwb3NzaWJsZSB0aGF0IGludmVyc2VSZWNvcmREYXRhIGhhcyBhbHJlYWR5IGJlZW4gYXNzb2NpYXRlZCB0bwogICAgICAgIC8vIHRvIGFub3RoZXIgcmVjb3JkLiBGb3Igc3VjaCBjYXNlcywgZG8gbm90IGRlbWF0ZXJpYWxpemUgdGhlIGludmVyc2VSZWNvcmREYXRhCgoKICAgICAgICBpZiAoIWJlbG9uZ3NUb1JlbGF0aW9uc2hpcCB8fCAhYmVsb25nc1RvUmVsYXRpb25zaGlwLmludmVyc2VSZWNvcmREYXRhIHx8IF90aGlzLnJlY29yZERhdGEgPT09IGJlbG9uZ3NUb1JlbGF0aW9uc2hpcC5pbnZlcnNlUmVjb3JkRGF0YSkgewogICAgICAgICAgcmVsYXRpb25zaGlwLmludmVyc2VEaWREZW1hdGVyaWFsaXplKF90aGlzLnJlY29yZERhdGEpOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5mb3JBbGxNZW1iZXJzID0gZnVuY3Rpb24gZm9yQWxsTWVtYmVycyhjYWxsYmFjaykgewogICAgICB2YXIgc2VlbiA9IE9iamVjdC5jcmVhdGUobnVsbCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubWVtYmVycy5saXN0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGludmVyc2VJbnRlcm5hbE1vZGVsID0gdGhpcy5tZW1iZXJzLmxpc3RbaV07CiAgICAgICAgdmFyIGlkID0gRW1iZXIuZ3VpZEZvcihpbnZlcnNlSW50ZXJuYWxNb2RlbCk7CgogICAgICAgIGlmICghc2VlbltpZF0pIHsKICAgICAgICAgIHNlZW5baWRdID0gdHJ1ZTsKICAgICAgICAgIGNhbGxiYWNrKGludmVyc2VJbnRlcm5hbE1vZGVsKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCB0aGlzLmNhbm9uaWNhbE1lbWJlcnMubGlzdC5sZW5ndGg7IF9pKyspIHsKICAgICAgICB2YXIgX2ludmVyc2VJbnRlcm5hbE1vZGVsID0gdGhpcy5jYW5vbmljYWxNZW1iZXJzLmxpc3RbX2ldOwoKICAgICAgICB2YXIgX2lkID0gRW1iZXIuZ3VpZEZvcihfaW52ZXJzZUludGVybmFsTW9kZWwpOwoKICAgICAgICBpZiAoIXNlZW5bX2lkXSkgewogICAgICAgICAgc2VlbltfaWRdID0gdHJ1ZTsKICAgICAgICAgIGNhbGxiYWNrKF9pbnZlcnNlSW50ZXJuYWxNb2RlbCk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5pbnZlcnNlRGlkRGVtYXRlcmlhbGl6ZSA9IGZ1bmN0aW9uIGludmVyc2VEaWREZW1hdGVyaWFsaXplKGludmVyc2VSZWNvcmREYXRhKSB7CiAgICAgIGlmICghdGhpcy5pc0FzeW5jIHx8IGludmVyc2VSZWNvcmREYXRhICYmIGludmVyc2VSZWNvcmREYXRhLmlzTmV3KCkpIHsKICAgICAgICAvLyB1bmxvYWRpbmcgaW52ZXJzZSBvZiBhIHN5bmMgcmVsYXRpb25zaGlwIGlzIHRyZWF0ZWQgYXMgYSBjbGllbnQtc2lkZQogICAgICAgIC8vIGRlbGV0ZSwgc28gYWN0dWFsbHkgcmVtb3ZlIHRoZSBtb2RlbHMgZG9uJ3QgbWVyZWx5IGludmFsaWRhdGUgdGhlIGNwCiAgICAgICAgLy8gY2FjaGUuCiAgICAgICAgLy8gaWYgdGhlIHJlY29yZCBiZWluZyB1bmxvYWRlZCBvbmx5IGV4aXN0cyBvbiB0aGUgY2xpZW50LCB3ZSBzaW1pbGFybHkKICAgICAgICAvLyB0cmVhdCBpdCBhcyBhIGNsaWVudCBzaWRlIGRlbGV0ZQogICAgICAgIHRoaXMucmVtb3ZlUmVjb3JkRGF0YUZyb21Pd24oaW52ZXJzZVJlY29yZERhdGEpOwogICAgICAgIHRoaXMucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YUZyb21Pd24oaW52ZXJzZVJlY29yZERhdGEpOwogICAgICAgIHRoaXMuc2V0UmVsYXRpb25zaGlwSXNFbXB0eSh0cnVlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnNldEhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSh0cnVlKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8udXBkYXRlTWV0YSA9IGZ1bmN0aW9uIHVwZGF0ZU1ldGEobWV0YSkgewogICAgICB0aGlzLm1ldGEgPSBtZXRhOwogICAgfTsKCiAgICBfcHJvdG8uY2xlYXIgPSBmdW5jdGlvbiBjbGVhcigpIHsKICAgICAgdmFyIG1lbWJlcnMgPSB0aGlzLm1lbWJlcnMubGlzdDsKCiAgICAgIHdoaWxlIChtZW1iZXJzLmxlbmd0aCA+IDApIHsKICAgICAgICB2YXIgbWVtYmVyID0gbWVtYmVyc1swXTsKICAgICAgICB0aGlzLnJlbW92ZVJlY29yZERhdGEobWVtYmVyKTsKICAgICAgfQoKICAgICAgdmFyIGNhbm9uaWNhbE1lbWJlcnMgPSB0aGlzLmNhbm9uaWNhbE1lbWJlcnMubGlzdDsKCiAgICAgIHdoaWxlIChjYW5vbmljYWxNZW1iZXJzLmxlbmd0aCA+IDApIHsKICAgICAgICB2YXIgX21lbWJlciA9IGNhbm9uaWNhbE1lbWJlcnNbMF07CiAgICAgICAgdGhpcy5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhKF9tZW1iZXIpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVBbGxSZWNvcmREYXRhc0Zyb21Pd24gPSBmdW5jdGlvbiByZW1vdmVBbGxSZWNvcmREYXRhc0Zyb21Pd24oKSB7CiAgICAgIHRoaXMuc2V0UmVsYXRpb25zaGlwSXNTdGFsZSh0cnVlKTsKICAgICAgdGhpcy5tZW1iZXJzLmNsZWFyKCk7CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVBbGxDYW5vbmljYWxSZWNvcmREYXRhc0Zyb21Pd24gPSBmdW5jdGlvbiByZW1vdmVBbGxDYW5vbmljYWxSZWNvcmREYXRhc0Zyb21Pd24oKSB7CiAgICAgIHRoaXMuY2Fub25pY2FsTWVtYmVycy5jbGVhcigpOwogICAgICB0aGlzLmZsdXNoQ2Fub25pY2FsTGF0ZXIoKTsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZVJlY29yZERhdGFzID0gZnVuY3Rpb24gcmVtb3ZlUmVjb3JkRGF0YXMocmVjb3JkRGF0YXMpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICByZWNvcmREYXRhcy5mb3JFYWNoKGZ1bmN0aW9uIChyZWNvcmREYXRhKSB7CiAgICAgICAgcmV0dXJuIF90aGlzMi5yZW1vdmVSZWNvcmREYXRhKHJlY29yZERhdGEpOwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvLmFkZFJlY29yZERhdGFzID0gZnVuY3Rpb24gYWRkUmVjb3JkRGF0YXMocmVjb3JkRGF0YXMsIGlkeCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHJlY29yZERhdGFzLmZvckVhY2goZnVuY3Rpb24gKHJlY29yZERhdGEpIHsKICAgICAgICBfdGhpczMuYWRkUmVjb3JkRGF0YShyZWNvcmREYXRhLCBpZHgpOwoKICAgICAgICBpZiAoaWR4ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGlkeCsrOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5hZGRDYW5vbmljYWxSZWNvcmREYXRhcyA9IGZ1bmN0aW9uIGFkZENhbm9uaWNhbFJlY29yZERhdGFzKHJlY29yZERhdGFzLCBpZHgpIHsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZWNvcmREYXRhcy5sZW5ndGg7IGkrKykgewogICAgICAgIGlmIChpZHggIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdGhpcy5hZGRDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGFzW2ldLCBpICsgaWR4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhpcy5hZGRDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGFzW2ldKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmFkZENhbm9uaWNhbFJlY29yZERhdGEgPSBmdW5jdGlvbiBhZGRDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGEsIGlkeCkgewogICAgICBpZiAoIXRoaXMuY2Fub25pY2FsTWVtYmVycy5oYXMocmVjb3JkRGF0YSkpIHsKICAgICAgICB0aGlzLmNhbm9uaWNhbE1lbWJlcnMuYWRkKHJlY29yZERhdGEpOwogICAgICAgIHRoaXMuc2V0dXBJbnZlcnNlUmVsYXRpb25zaGlwKHJlY29yZERhdGEpOwogICAgICB9CgogICAgICB0aGlzLmZsdXNoQ2Fub25pY2FsTGF0ZXIoKTsKICAgICAgdGhpcy5zZXRIYXNBbnlSZWxhdGlvbnNoaXBEYXRhKHRydWUpOwogICAgfTsKCiAgICBfcHJvdG8uc2V0dXBJbnZlcnNlUmVsYXRpb25zaGlwID0gZnVuY3Rpb24gc2V0dXBJbnZlcnNlUmVsYXRpb25zaGlwKHJlY29yZERhdGEpIHsKICAgICAgaWYgKHRoaXMuaW52ZXJzZUtleSkgewogICAgICAgIGlmICghdGhpcy5faGFzU3VwcG9ydEZvclJlbGF0aW9uc2hpcHMocmVjb3JkRGF0YSkpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHZhciByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXBTdGF0ZUZvcihyZWNvcmREYXRhLCB0aGlzLmludmVyc2VLZXkpOyAvLyBpZiB3ZSBoYXZlIG9ubHkganVzdCBpbml0aWFsaXplZCB0aGUgaW52ZXJzZSByZWxhdGlvbnNoaXAsIHRoZW4gaXQKICAgICAgICAvLyBhbHJlYWR5IGhhcyB0aGlzLnJlY29yZERhdGEgaW4gaXRzIGNhbm9uaWNhbE1lbWJlcnMsIHNvIHNraXAgdGhlCiAgICAgICAgLy8gdW5uZWNlc3Nhcnkgd29yay4gIFRoZSBleGNlcHRpb24gdG8gdGhpcyBpcyBwb2x5bW9ycGhpYwogICAgICAgIC8vIHJlbGF0aW9uc2hpcHMgd2hvc2UgbWVtYmVycyBhcmUgZGV0ZXJtaW5lZCBieSB0aGVpciBpbnZlcnNlLCBhcyB0aG9zZQogICAgICAgIC8vIHJlbGF0aW9uc2hpcHMgY2Fubm90IGVmZmljaWVudGx5IGZpbmQgdGhlaXIgaW52ZXJzZSBwYXlsb2Fkcy4KCiAgICAgICAgcmVsYXRpb25zaGlwLmFkZENhbm9uaWNhbFJlY29yZERhdGEodGhpcy5yZWNvcmREYXRhKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAoIXRoaXMuX2hhc1N1cHBvcnRGb3JJbXBsaWNpdFJlbGF0aW9uc2hpcHMocmVjb3JkRGF0YSkpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHZhciByZWxhdGlvbnNoaXBzID0gcmVjb3JkRGF0YS5faW1wbGljaXRSZWxhdGlvbnNoaXBzOwogICAgICAgIHZhciBfcmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwc1t0aGlzLmludmVyc2VLZXlGb3JJbXBsaWNpdF07CgogICAgICAgIGlmICghX3JlbGF0aW9uc2hpcCkgewogICAgICAgICAgX3JlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcHNbdGhpcy5pbnZlcnNlS2V5Rm9ySW1wbGljaXRdID0gbmV3IFJlbGF0aW9uc2hpcCh0aGlzLnN0b3JlLCB0aGlzLmtleSwgewogICAgICAgICAgICBvcHRpb25zOiB7CiAgICAgICAgICAgICAgYXN5bmM6IHRoaXMuaXNBc3luYwogICAgICAgICAgICB9CiAgICAgICAgICB9LCByZWNvcmREYXRhKTsKICAgICAgICB9CgogICAgICAgIF9yZWxhdGlvbnNoaXAuYWRkQ2Fub25pY2FsUmVjb3JkRGF0YSh0aGlzLnJlY29yZERhdGEpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhcyA9IGZ1bmN0aW9uIHJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFzKHJlY29yZERhdGFzLCBpZHgpIHsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZWNvcmREYXRhcy5sZW5ndGg7IGkrKykgewogICAgICAgIGlmIChpZHggIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdGhpcy5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGFzW2ldLCBpICsgaWR4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhpcy5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGFzW2ldKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGEgPSBmdW5jdGlvbiByZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGEsIGlkeCkgewogICAgICBpZiAodGhpcy5jYW5vbmljYWxNZW1iZXJzLmhhcyhyZWNvcmREYXRhKSkgewogICAgICAgIHRoaXMucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YUZyb21Pd24ocmVjb3JkRGF0YSk7CgogICAgICAgIGlmICh0aGlzLmludmVyc2VLZXkpIHsKICAgICAgICAgIHRoaXMucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YUZyb21JbnZlcnNlKHJlY29yZERhdGEpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAodGhpcy5faGFzU3VwcG9ydEZvckltcGxpY2l0UmVsYXRpb25zaGlwcyhyZWNvcmREYXRhKSAmJiByZWNvcmREYXRhLl9pbXBsaWNpdFJlbGF0aW9uc2hpcHNbdGhpcy5pbnZlcnNlS2V5Rm9ySW1wbGljaXRdKSB7CiAgICAgICAgICAgIHJlY29yZERhdGEuX2ltcGxpY2l0UmVsYXRpb25zaGlwc1t0aGlzLmludmVyc2VLZXlGb3JJbXBsaWNpdF0ucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YSh0aGlzLnJlY29yZERhdGEpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgdGhpcy5mbHVzaENhbm9uaWNhbExhdGVyKCk7CiAgICB9OwoKICAgIF9wcm90by5hZGRSZWNvcmREYXRhID0gZnVuY3Rpb24gYWRkUmVjb3JkRGF0YShyZWNvcmREYXRhLCBpZHgpIHsKICAgICAgaWYgKCF0aGlzLm1lbWJlcnMuaGFzKHJlY29yZERhdGEpKSB7CiAgICAgICAgdGhpcy5tZW1iZXJzLmFkZFdpdGhJbmRleChyZWNvcmREYXRhLCBpZHgpOwogICAgICAgIHRoaXMubm90aWZ5UmVjb3JkUmVsYXRpb25zaGlwQWRkZWQocmVjb3JkRGF0YSwgaWR4KTsKCiAgICAgICAgaWYgKHRoaXMuX2hhc1N1cHBvcnRGb3JSZWxhdGlvbnNoaXBzKHJlY29yZERhdGEpICYmIHRoaXMuaW52ZXJzZUtleSkgewogICAgICAgICAgcmVsYXRpb25zaGlwU3RhdGVGb3IocmVjb3JkRGF0YSwgdGhpcy5pbnZlcnNlS2V5KS5hZGRSZWNvcmREYXRhKHRoaXMucmVjb3JkRGF0YSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmICh0aGlzLl9oYXNTdXBwb3J0Rm9ySW1wbGljaXRSZWxhdGlvbnNoaXBzKHJlY29yZERhdGEpKSB7CiAgICAgICAgICAgIGlmICghcmVjb3JkRGF0YS5faW1wbGljaXRSZWxhdGlvbnNoaXBzW3RoaXMuaW52ZXJzZUtleUZvckltcGxpY2l0XSkgewogICAgICAgICAgICAgIHJlY29yZERhdGEuX2ltcGxpY2l0UmVsYXRpb25zaGlwc1t0aGlzLmludmVyc2VLZXlGb3JJbXBsaWNpdF0gPSBuZXcgUmVsYXRpb25zaGlwKHRoaXMuc3RvcmUsIHRoaXMua2V5LCB7CiAgICAgICAgICAgICAgICBvcHRpb25zOiB7CiAgICAgICAgICAgICAgICAgIGFzeW5jOiB0aGlzLmlzQXN5bmMKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9LCByZWNvcmREYXRhLCB0aGlzLmlzQXN5bmMpOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZWNvcmREYXRhLl9pbXBsaWNpdFJlbGF0aW9uc2hpcHNbdGhpcy5pbnZlcnNlS2V5Rm9ySW1wbGljaXRdLmFkZFJlY29yZERhdGEodGhpcy5yZWNvcmREYXRhKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHRoaXMuc2V0SGFzQW55UmVsYXRpb25zaGlwRGF0YSh0cnVlKTsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZVJlY29yZERhdGEgPSBmdW5jdGlvbiByZW1vdmVSZWNvcmREYXRhKHJlY29yZERhdGEpIHsKICAgICAgaWYgKHRoaXMubWVtYmVycy5oYXMocmVjb3JkRGF0YSkpIHsKICAgICAgICB0aGlzLnJlbW92ZVJlY29yZERhdGFGcm9tT3duKHJlY29yZERhdGEpOwoKICAgICAgICBpZiAodGhpcy5pbnZlcnNlS2V5KSB7CiAgICAgICAgICB0aGlzLnJlbW92ZVJlY29yZERhdGFGcm9tSW52ZXJzZShyZWNvcmREYXRhKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKHRoaXMuX2hhc1N1cHBvcnRGb3JJbXBsaWNpdFJlbGF0aW9uc2hpcHMocmVjb3JkRGF0YSkgJiYgcmVjb3JkRGF0YS5faW1wbGljaXRSZWxhdGlvbnNoaXBzW3RoaXMuaW52ZXJzZUtleUZvckltcGxpY2l0XSkgewogICAgICAgICAgICByZWNvcmREYXRhLl9pbXBsaWNpdFJlbGF0aW9uc2hpcHNbdGhpcy5pbnZlcnNlS2V5Rm9ySW1wbGljaXRdLnJlbW92ZVJlY29yZERhdGEodGhpcy5yZWNvcmREYXRhKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnJlbW92ZVJlY29yZERhdGFGcm9tSW52ZXJzZSA9IGZ1bmN0aW9uIHJlbW92ZVJlY29yZERhdGFGcm9tSW52ZXJzZShyZWNvcmREYXRhKSB7CiAgICAgIGlmICghdGhpcy5faGFzU3VwcG9ydEZvclJlbGF0aW9uc2hpcHMocmVjb3JkRGF0YSkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmludmVyc2VLZXkpIHsKICAgICAgICB2YXIgaW52ZXJzZVJlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcFN0YXRlRm9yKHJlY29yZERhdGEsIHRoaXMuaW52ZXJzZUtleSk7IC8vTmVlZCB0byBjaGVjayBmb3IgZXhpc3RlbmNlLCBhcyB0aGUgcmVjb3JkIG1pZ2h0IHVubG9hZGluZyBhdCB0aGUgbW9tZW50CgogICAgICAgIGlmIChpbnZlcnNlUmVsYXRpb25zaGlwKSB7CiAgICAgICAgICBpbnZlcnNlUmVsYXRpb25zaGlwLnJlbW92ZVJlY29yZERhdGFGcm9tT3duKHRoaXMucmVjb3JkRGF0YSk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVSZWNvcmREYXRhRnJvbU93biA9IGZ1bmN0aW9uIHJlbW92ZVJlY29yZERhdGFGcm9tT3duKHJlY29yZERhdGEsIGlkeCkgewogICAgICB0aGlzLm1lbWJlcnMuZGVsZXRlKHJlY29yZERhdGEpOwogICAgfTsKCiAgICBfcHJvdG8ucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YUZyb21JbnZlcnNlID0gZnVuY3Rpb24gcmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YUZyb21JbnZlcnNlKHJlY29yZERhdGEpIHsKICAgICAgaWYgKCF0aGlzLl9oYXNTdXBwb3J0Rm9yUmVsYXRpb25zaGlwcyhyZWNvcmREYXRhKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuaW52ZXJzZUtleSkgewogICAgICAgIHZhciBpbnZlcnNlUmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwU3RhdGVGb3IocmVjb3JkRGF0YSwgdGhpcy5pbnZlcnNlS2V5KTsgLy9OZWVkIHRvIGNoZWNrIGZvciBleGlzdGVuY2UsIGFzIHRoZSByZWNvcmQgbWlnaHQgdW5sb2FkaW5nIGF0IHRoZSBtb21lbnQKCiAgICAgICAgaWYgKGludmVyc2VSZWxhdGlvbnNoaXApIHsKICAgICAgICAgIGludmVyc2VSZWxhdGlvbnNoaXAucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YUZyb21Pd24odGhpcy5yZWNvcmREYXRhKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tT3duID0gZnVuY3Rpb24gcmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YUZyb21Pd24ocmVjb3JkRGF0YSwgaWR4KSB7CiAgICAgIHRoaXMuY2Fub25pY2FsTWVtYmVycy5kZWxldGUocmVjb3JkRGF0YSk7CiAgICAgIHRoaXMuZmx1c2hDYW5vbmljYWxMYXRlcigpOwogICAgfQogICAgLyoKICAgICAgQ2FsbCB0aGlzIG1ldGhvZCBvbmNlIGEgcmVjb3JkIGRlbGV0aW9uIGhhcyBiZWVuIHBlcnNpc3RlZAogICAgICB0byBwdXJnZSBpdCBmcm9tIEJPVEggY3VycmVudCBhbmQgY2Fub25pY2FsIHN0YXRlIG9mIGFsbAogICAgICByZWxhdGlvbnNoaXBzLgogICAgICAgQG1ldGhvZCByZW1vdmVDb21wbGV0ZWx5RnJvbUludmVyc2UKICAgICAgQHByaXZhdGUKICAgICAqLwogICAgOwoKICAgIF9wcm90by5yZW1vdmVDb21wbGV0ZWx5RnJvbUludmVyc2UgPSBmdW5jdGlvbiByZW1vdmVDb21wbGV0ZWx5RnJvbUludmVyc2UoKSB7CiAgICAgIHZhciBfdGhpczQgPSB0aGlzOwoKICAgICAgaWYgKCF0aGlzLmludmVyc2VLZXkgJiYgIXRoaXMuaW52ZXJzZUtleUZvckltcGxpY2l0KSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIHdlIGFjdHVhbGx5IHdhbnQgYSB1bmlvbiBvZiBtZW1iZXJzIGFuZCBjYW5vbmljYWxNZW1iZXJzCiAgICAgIC8vIHRoZXkgc2hvdWxkIGJlIGRpc2pvaW50IGJ1dCBjdXJyZW50bHkgYXJlIG5vdCBkdWUgdG8gYSBidWcKCgogICAgICB2YXIgc2VlbiA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHZhciByZWNvcmREYXRhID0gdGhpcy5yZWNvcmREYXRhOwogICAgICB2YXIgdW5sb2FkOwoKICAgICAgaWYgKHRoaXMuaW52ZXJzZUtleSkgewogICAgICAgIHVubG9hZCA9IGZ1bmN0aW9uIHVubG9hZChpbnZlcnNlUmVjb3JkRGF0YSkgewogICAgICAgICAgdmFyIGlkID0gRW1iZXIuZ3VpZEZvcihpbnZlcnNlUmVjb3JkRGF0YSk7CgogICAgICAgICAgaWYgKF90aGlzNC5faGFzU3VwcG9ydEZvclJlbGF0aW9uc2hpcHMoaW52ZXJzZVJlY29yZERhdGEpICYmIHNlZW5baWRdID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgaWYgKF90aGlzNC5pbnZlcnNlS2V5KSB7CiAgICAgICAgICAgICAgdmFyIHJlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcFN0YXRlRm9yKGludmVyc2VSZWNvcmREYXRhLCBfdGhpczQuaW52ZXJzZUtleSk7CiAgICAgICAgICAgICAgcmVsYXRpb25zaGlwLnJlbW92ZUNvbXBsZXRlbHlGcm9tT3duKHJlY29yZERhdGEpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBzZWVuW2lkXSA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgfSBlbHNlIHsKICAgICAgICB1bmxvYWQgPSBmdW5jdGlvbiB1bmxvYWQoaW52ZXJzZVJlY29yZERhdGEpIHsKICAgICAgICAgIHZhciBpZCA9IEVtYmVyLmd1aWRGb3IoaW52ZXJzZVJlY29yZERhdGEpOwoKICAgICAgICAgIGlmIChfdGhpczQuX2hhc1N1cHBvcnRGb3JJbXBsaWNpdFJlbGF0aW9uc2hpcHMoaW52ZXJzZVJlY29yZERhdGEpICYmIHNlZW5baWRdID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgdmFyIHJlbGF0aW9uc2hpcCA9IGltcGxpY2l0UmVsYXRpb25zaGlwU3RhdGVGb3IoaW52ZXJzZVJlY29yZERhdGEsIF90aGlzNC5pbnZlcnNlS2V5Rm9ySW1wbGljaXQpOwogICAgICAgICAgICByZWxhdGlvbnNoaXAucmVtb3ZlQ29tcGxldGVseUZyb21Pd24ocmVjb3JkRGF0YSk7CiAgICAgICAgICAgIHNlZW5baWRdID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICB9CgogICAgICB0aGlzLm1lbWJlcnMuZm9yRWFjaCh1bmxvYWQpOwogICAgICB0aGlzLmNhbm9uaWNhbE1lbWJlcnMuZm9yRWFjaCh1bmxvYWQpOwoKICAgICAgaWYgKCF0aGlzLmlzQXN5bmMpIHsKICAgICAgICB0aGlzLmNsZWFyKCk7CiAgICAgIH0KICAgIH0KICAgIC8qCiAgICAgIFJlbW92ZXMgdGhlIGdpdmVuIFJlY29yZERhdGEgZnJvbSBCT1RIIGNhbm9uaWNhbCBBTkQgY3VycmVudCBzdGF0ZS4KICAgICAgIFRoaXMgbWV0aG9kIGlzIHVzZWZ1bCB3aGVuIGVpdGhlciBhIGRlbGV0aW9uIG9yIGEgcm9sbGJhY2sgb24gYSBuZXcgcmVjb3JkCiAgICAgIG5lZWRzIHRvIGVudGlyZWx5IHB1cmdlIGl0c2VsZiBmcm9tIGFuIGludmVyc2UgcmVsYXRpb25zaGlwLgogICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlbW92ZUNvbXBsZXRlbHlGcm9tT3duID0gZnVuY3Rpb24gcmVtb3ZlQ29tcGxldGVseUZyb21Pd24ocmVjb3JkRGF0YSkgewogICAgICB0aGlzLmNhbm9uaWNhbE1lbWJlcnMuZGVsZXRlKHJlY29yZERhdGEpOwogICAgICB0aGlzLm1lbWJlcnMuZGVsZXRlKHJlY29yZERhdGEpOwogICAgfTsKCiAgICBfcHJvdG8uZmx1c2hDYW5vbmljYWwgPSBmdW5jdGlvbiBmbHVzaENhbm9uaWNhbCgpIHsKICAgICAgdmFyIGxpc3QgPSB0aGlzLm1lbWJlcnMubGlzdDsKICAgICAgdGhpcy53aWxsU3luYyA9IGZhbHNlOyAvL2EgaGFjayBmb3Igbm90IHJlbW92aW5nIG5ldyBSZWNvcmREYXRhcwogICAgICAvL1RPRE8gcmVtb3ZlIG9uY2Ugd2UgaGF2ZSBwcm9wZXIgZGlmZmluZwoKICAgICAgdmFyIG5ld1JlY29yZERhdGFzID0gW107CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHsKICAgICAgICAvLyBUT0RPIElnb3IgZGVhbCB3aXRoIHRoaXMKICAgICAgICBpZiAobGlzdFtpXS5pc05ldygpKSB7CiAgICAgICAgICBuZXdSZWNvcmREYXRhcy5wdXNoKGxpc3RbaV0pOwogICAgICAgIH0KICAgICAgfSAvL1RPRE8oSWdvcikgbWFrZSB0aGlzIGxlc3MgYWJ5c21hbGx5IHNsb3cKCgogICAgICB0aGlzLm1lbWJlcnMgPSB0aGlzLmNhbm9uaWNhbE1lbWJlcnMuY29weSgpOwoKICAgICAgZm9yICh2YXIgX2kyID0gMDsgX2kyIDwgbmV3UmVjb3JkRGF0YXMubGVuZ3RoOyBfaTIrKykgewogICAgICAgIHRoaXMubWVtYmVycy5hZGQobmV3UmVjb3JkRGF0YXNbX2kyXSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmZsdXNoQ2Fub25pY2FsTGF0ZXIgPSBmdW5jdGlvbiBmbHVzaENhbm9uaWNhbExhdGVyKCkgewogICAgICBpZiAodGhpcy53aWxsU3luYykgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy53aWxsU3luYyA9IHRydWU7IC8vIFJlYWNoaW5nIGJhY2sgaW50byB0aGUgc3RvcmUgdG8gdXNlIEVEJ3MgcnVubG9vcAoKICAgICAgdGhpcy5zdG9yZS5fdXBkYXRlUmVsYXRpb25zaGlwU3RhdGUodGhpcyk7CiAgICB9OwoKICAgIF9wcm90by51cGRhdGVMaW5rID0gZnVuY3Rpb24gdXBkYXRlTGluayhsaW5rKSB7CiAgICAgIHRoaXMubGluayA9IGxpbms7CiAgICB9OwoKICAgIF9wcm90by51cGRhdGVSZWNvcmREYXRhc0Zyb21BZGFwdGVyID0gZnVuY3Rpb24gdXBkYXRlUmVjb3JkRGF0YXNGcm9tQWRhcHRlcihyZWNvcmREYXRhcykgewogICAgICB0aGlzLnNldEhhc0FueVJlbGF0aW9uc2hpcERhdGEodHJ1ZSk7IC8vVE9ETyhJZ29yKSBtb3ZlIHRoaXMgdG8gYSBwcm9wZXIgcGxhY2UKICAgICAgLy9UT0RPIE9uY2Ugd2UgaGF2ZSBhZGFwdGVyIHN1cHBvcnQsIHdlIG5lZWQgdG8gaGFuZGxlIHVwZGF0ZWQgYW5kIGNhbm9uaWNhbCBjaGFuZ2VzCgogICAgICB0aGlzLmNvbXB1dGVDaGFuZ2VzKHJlY29yZERhdGFzKTsKICAgIH07CgogICAgX3Byb3RvLmNvbXB1dGVDaGFuZ2VzID0gZnVuY3Rpb24gY29tcHV0ZUNoYW5nZXMocmVjb3JkRGF0YXMpIHt9OwoKICAgIF9wcm90by5ub3RpZnlSZWNvcmRSZWxhdGlvbnNoaXBBZGRlZCA9IGZ1bmN0aW9uIG5vdGlmeVJlY29yZFJlbGF0aW9uc2hpcEFkZGVkKHJlY29yZERhdGEsIGlkeHMpIHt9OwoKICAgIF9wcm90by5zZXRIYXNBbnlSZWxhdGlvbnNoaXBEYXRhID0gZnVuY3Rpb24gc2V0SGFzQW55UmVsYXRpb25zaGlwRGF0YSh2YWx1ZSkgewogICAgICB0aGlzLmhhc0FueVJlbGF0aW9uc2hpcERhdGEgPSB2YWx1ZTsKICAgIH07CgogICAgX3Byb3RvLnNldEhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSA9IGZ1bmN0aW9uIHNldEhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSh2YWx1ZSkgewogICAgICB0aGlzLmhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSA9IHZhbHVlOwogICAgfTsKCiAgICBfcHJvdG8uc2V0UmVsYXRpb25zaGlwSXNTdGFsZSA9IGZ1bmN0aW9uIHNldFJlbGF0aW9uc2hpcElzU3RhbGUodmFsdWUpIHsKICAgICAgdGhpcy5yZWxhdGlvbnNoaXBJc1N0YWxlID0gdmFsdWU7CiAgICB9OwoKICAgIF9wcm90by5zZXRSZWxhdGlvbnNoaXBJc0VtcHR5ID0gZnVuY3Rpb24gc2V0UmVsYXRpb25zaGlwSXNFbXB0eSh2YWx1ZSkgewogICAgICB0aGlzLnJlbGF0aW9uc2hpcElzRW1wdHkgPSB2YWx1ZTsKICAgIH07CgogICAgX3Byb3RvLnNldFNob3VsZEZvcmNlUmVsb2FkID0gZnVuY3Rpb24gc2V0U2hvdWxkRm9yY2VSZWxvYWQodmFsdWUpIHsKICAgICAgdGhpcy5zaG91bGRGb3JjZVJlbG9hZCA9IHZhbHVlOwogICAgfTsKCiAgICBfcHJvdG8uc2V0SGFzRmFpbGVkTG9hZEF0dGVtcHQgPSBmdW5jdGlvbiBzZXRIYXNGYWlsZWRMb2FkQXR0ZW1wdCh2YWx1ZSkgewogICAgICB0aGlzLmhhc0ZhaWxlZExvYWRBdHRlbXB0ID0gdmFsdWU7CiAgICB9CiAgICAvKgogICAgIGBwdXNoYCBmb3IgYSByZWxhdGlvbnNoaXAgYWxsb3dzIHRoZSBzdG9yZSB0byBwdXNoIGEgSlNPTiBBUEkgUmVsYXRpb25zaGlwCiAgICAgT2JqZWN0IG9udG8gdGhlIHJlbGF0aW9uc2hpcC4gVGhlIHJlbGF0aW9uc2hpcCB3aWxsIHRoZW4gZXh0cmFjdCBhbmQgc2V0IHRoZQogICAgIG1ldGEsIGRhdGEgYW5kIGxpbmtzIG9mIHRoYXQgcmVsYXRpb25zaGlwLgogICAgICBgcHVzaGAgdXNlIGB1cGRhdGVNZXRhYCwgYHVwZGF0ZURhdGFgIGFuZCBgdXBkYXRlTGlua2AgdG8gdXBkYXRlIHRoZSBzdGF0ZQogICAgIG9mIHRoZSByZWxhdGlvbnNoaXAuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucHVzaCA9IGZ1bmN0aW9uIHB1c2gocGF5bG9hZCwgaW5pdGlhbCkgewogICAgICB2YXIgaGFzUmVsYXRpb25zaGlwRGF0YVByb3BlcnR5ID0gZmFsc2U7CiAgICAgIHZhciBoYXNMaW5rID0gZmFsc2U7CgogICAgICBpZiAocGF5bG9hZC5tZXRhKSB7CiAgICAgICAgdGhpcy51cGRhdGVNZXRhKHBheWxvYWQubWV0YSk7CiAgICAgIH0KCiAgICAgIGlmIChwYXlsb2FkLmRhdGEgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGhhc1JlbGF0aW9uc2hpcERhdGFQcm9wZXJ0eSA9IHRydWU7CiAgICAgICAgdGhpcy51cGRhdGVEYXRhKHBheWxvYWQuZGF0YSwgaW5pdGlhbCk7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5pc0FzeW5jID09PSBmYWxzZSAmJiAhdGhpcy5oYXNBbnlSZWxhdGlvbnNoaXBEYXRhKSB7CiAgICAgICAgaGFzUmVsYXRpb25zaGlwRGF0YVByb3BlcnR5ID0gdHJ1ZTsKICAgICAgICB2YXIgZGF0YSA9IHRoaXMua2luZCA9PT0gJ2hhc01hbnknID8gW10gOiBudWxsOwogICAgICAgIHRoaXMudXBkYXRlRGF0YShkYXRhLCBpbml0aWFsKTsKICAgICAgfQoKICAgICAgaWYgKHBheWxvYWQubGlua3MgJiYgcGF5bG9hZC5saW5rcy5yZWxhdGVkKSB7CiAgICAgICAgdmFyIHJlbGF0ZWRMaW5rID0gX25vcm1hbGl6ZUxpbmsocGF5bG9hZC5saW5rcy5yZWxhdGVkKTsKCiAgICAgICAgaWYgKHJlbGF0ZWRMaW5rICYmIHJlbGF0ZWRMaW5rLmhyZWYgJiYgcmVsYXRlZExpbmsuaHJlZiAhPT0gdGhpcy5saW5rKSB7CiAgICAgICAgICBoYXNMaW5rID0gdHJ1ZTsKICAgICAgICAgIHRoaXMudXBkYXRlTGluayhyZWxhdGVkTGluay5ocmVmKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgLyoKICAgICAgIERhdGEgYmVpbmcgcHVzaGVkIGludG8gdGhlIHJlbGF0aW9uc2hpcCBtaWdodCBjb250YWluIG9ubHkgZGF0YSBvciBsaW5rcywKICAgICAgIG9yIGEgY29tYmluYXRpb24gb2YgYm90aC4KICAgICAgICBJRiBjb250YWlucyBvbmx5IGRhdGEKICAgICAgIElGIGNvbnRhaW5zIGJvdGggbGlua3MgYW5kIGRhdGEKICAgICAgICByZWxhdGlvbnNoaXBJc0VtcHR5IC0+IHRydWUgaWYgaXMgZW1wdHkgYXJyYXkgKGhhcy1tYW55KSBvciBpcyBudWxsIChiZWxvbmdzLXRvKQogICAgICAgIGhhc0FueVJlbGF0aW9uc2hpcERhdGEgLT4gdHJ1ZQogICAgICAgIGhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSAtPiBmYWxzZQogICAgICAgIHJlbGF0aW9uc2hpcElzU3RhbGUgLT4gZmFsc2UKICAgICAgICBhbGxJbnZlcnNlUmVjb3Jkc0FyZUxvYWRlZCAtPiBydW4tY2hlY2stdG8tZGV0ZXJtaW5lCiAgICAgICAgSUYgY29udGFpbnMgb25seSBsaW5rcwogICAgICAgIHJlbGF0aW9uc2hpcElzU3RhbGUgLT4gdHJ1ZQogICAgICAgKi8KCgogICAgICB0aGlzLnNldEhhc0ZhaWxlZExvYWRBdHRlbXB0KGZhbHNlKTsKCiAgICAgIGlmIChoYXNSZWxhdGlvbnNoaXBEYXRhUHJvcGVydHkpIHsKICAgICAgICB2YXIgcmVsYXRpb25zaGlwSXNFbXB0eSA9IHBheWxvYWQuZGF0YSA9PT0gbnVsbCB8fCBBcnJheS5pc0FycmF5KHBheWxvYWQuZGF0YSkgJiYgcGF5bG9hZC5kYXRhLmxlbmd0aCA9PT0gMDsKICAgICAgICB0aGlzLnNldEhhc0FueVJlbGF0aW9uc2hpcERhdGEodHJ1ZSk7CiAgICAgICAgdGhpcy5zZXRSZWxhdGlvbnNoaXBJc1N0YWxlKGZhbHNlKTsKICAgICAgICB0aGlzLnNldEhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZShmYWxzZSk7CiAgICAgICAgdGhpcy5zZXRSZWxhdGlvbnNoaXBJc0VtcHR5KHJlbGF0aW9uc2hpcElzRW1wdHkpOwogICAgICB9IGVsc2UgaWYgKGhhc0xpbmspIHsKICAgICAgICB0aGlzLnNldFJlbGF0aW9uc2hpcElzU3RhbGUodHJ1ZSk7CgogICAgICAgIGlmICghaW5pdGlhbCkgewogICAgICAgICAgdmFyIHJlY29yZERhdGEgPSB0aGlzLnJlY29yZERhdGE7CiAgICAgICAgICB2YXIgc3RvcmVXcmFwcGVyID0gdGhpcy5yZWNvcmREYXRhLnN0b3JlV3JhcHBlcjsKCiAgICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICAgIHN0b3JlV3JhcHBlci5ub3RpZnlCZWxvbmdzVG9DaGFuZ2UocmVjb3JkRGF0YS5tb2RlbE5hbWUsIHJlY29yZERhdGEuaWQsIHJlY29yZERhdGEuY2xpZW50SWQsIHRoaXMua2V5KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0b3JlV3JhcHBlci5ub3RpZnlQcm9wZXJ0eUNoYW5nZShyZWNvcmREYXRhLm1vZGVsTmFtZSwgcmVjb3JkRGF0YS5pZCwgcmVjb3JkRGF0YS5jbGllbnRJZCwgLy8gV2Uga25vdyB3ZSBhcmUgbm90IGFuIGltcGxpY2l0IHJlbGF0aW9uc2hpcCBoZXJlCiAgICAgICAgICAgIHRoaXMua2V5KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmxvY2FsU3RhdGVJc0VtcHR5ID0gZnVuY3Rpb24gbG9jYWxTdGF0ZUlzRW1wdHkoKSB7fTsKCiAgICBfcHJvdG8udXBkYXRlRGF0YSA9IGZ1bmN0aW9uIHVwZGF0ZURhdGEocGF5bG9hZCwgaW5pdGlhbCkge307CgogICAgX3Byb3RvLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkge307CgogICAgX2NyZWF0ZUNsYXNzKFJlbGF0aW9uc2hpcCwgW3sKICAgICAga2V5OiAiaXNOZXciLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5yZWNvcmREYXRhLmlzTmV3KCk7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiX2ludmVyc2VNZXRhIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMuX19pbnZlcnNlTWV0YSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YXIgaW52ZXJzZU1ldGEgPSBudWxsOwoKICAgICAgICAgIGlmICh0aGlzLmludmVyc2VLZXkpIHsKICAgICAgICAgICAgLy8gV2Uga25vdyB3ZSBoYXZlIGEgZnVsbCBpbnZlcnNlIHJlbGF0aW9uc2hpcAogICAgICAgICAgICB2YXIgdHlwZSA9IHRoaXMucmVsYXRpb25zaGlwTWV0YS50eXBlOwogICAgICAgICAgICB2YXIgaW52ZXJzZU1vZGVsQ2xhc3MgPSB0aGlzLnN0b3JlLm1vZGVsRm9yKHR5cGUpOwogICAgICAgICAgICB2YXIgaW52ZXJzZVJlbGF0aW9uc2hpcHMgPSBFbWJlci5nZXQoaW52ZXJzZU1vZGVsQ2xhc3MsICdyZWxhdGlvbnNoaXBzQnlOYW1lJyk7CiAgICAgICAgICAgIGludmVyc2VNZXRhID0gaW52ZXJzZVJlbGF0aW9uc2hpcHMuZ2V0KHRoaXMuaW52ZXJzZUtleSk7CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5fX2ludmVyc2VNZXRhID0gaW52ZXJzZU1ldGE7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fX2ludmVyc2VNZXRhOwogICAgICB9CiAgICB9XSk7CgogICAgcmV0dXJuIFJlbGF0aW9uc2hpcDsKICB9KCk7CgogIGZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0aWVzJDEodGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoInZhbHVlIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0KCiAgZnVuY3Rpb24gX2NyZWF0ZUNsYXNzJDEoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQxKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMkMShDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH0KCiAgZnVuY3Rpb24gX2luaGVyaXRzTG9vc2UkMShzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MucHJvdG90eXBlKTsgc3ViQ2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gc3ViQ2xhc3M7IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH0KICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICB2YXIgTWFueVJlbGF0aW9uc2hpcCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfUmVsYXRpb25zaGlwKSB7CiAgICBfaW5oZXJpdHNMb29zZSQxKE1hbnlSZWxhdGlvbnNoaXAsIF9SZWxhdGlvbnNoaXApOwoKICAgIGZ1bmN0aW9uIE1hbnlSZWxhdGlvbnNoaXAoc3RvcmUsIGludmVyc2VLZXksIHJlbGF0aW9uc2hpcE1ldGEsIHJlY29yZERhdGEsIGludmVyc2VJc0FzeW5jKSB7CiAgICAgIHZhciBfdGhpczsKCiAgICAgIF90aGlzID0gX1JlbGF0aW9uc2hpcC5jYWxsKHRoaXMsIHN0b3JlLCBpbnZlcnNlS2V5LCByZWxhdGlvbnNoaXBNZXRhLCByZWNvcmREYXRhLCBpbnZlcnNlSXNBc3luYykgfHwgdGhpczsKICAgICAgX3RoaXMuY2Fub25pY2FsU3RhdGUgPSB2b2lkIDA7CiAgICAgIF90aGlzLmN1cnJlbnRTdGF0ZSA9IHZvaWQgMDsKICAgICAgX3RoaXMuX3dpbGxVcGRhdGVNYW55QXJyYXkgPSB2b2lkIDA7CiAgICAgIF90aGlzLl9wZW5kaW5nTWFueUFycmF5VXBkYXRlcyA9IHZvaWQgMDsKICAgICAgX3RoaXMua2V5ID0gdm9pZCAwOwogICAgICBfdGhpcy5jYW5vbmljYWxTdGF0ZSA9IFtdOwogICAgICBfdGhpcy5jdXJyZW50U3RhdGUgPSBbXTsKICAgICAgX3RoaXMuX3dpbGxVcGRhdGVNYW55QXJyYXkgPSBmYWxzZTsKICAgICAgX3RoaXMuX3BlbmRpbmdNYW55QXJyYXlVcGRhdGVzID0gbnVsbDsKICAgICAgX3RoaXMua2V5ID0gcmVsYXRpb25zaGlwTWV0YS5rZXk7CiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gTWFueVJlbGF0aW9uc2hpcC5wcm90b3R5cGU7CgogICAgX3Byb3RvLmFkZENhbm9uaWNhbFJlY29yZERhdGEgPSBmdW5jdGlvbiBhZGRDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGEsIGlkeCkgewogICAgICBpZiAodGhpcy5jYW5vbmljYWxNZW1iZXJzLmhhcyhyZWNvcmREYXRhKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgaWYgKGlkeCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdGhpcy5jYW5vbmljYWxTdGF0ZS5zcGxpY2UoaWR4LCAwLCByZWNvcmREYXRhKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLmNhbm9uaWNhbFN0YXRlLnB1c2gocmVjb3JkRGF0YSk7CiAgICAgIH0KCiAgICAgIF9SZWxhdGlvbnNoaXAucHJvdG90eXBlLmFkZENhbm9uaWNhbFJlY29yZERhdGEuY2FsbCh0aGlzLCByZWNvcmREYXRhLCBpZHgpOwogICAgfTsKCiAgICBfcHJvdG8uaW52ZXJzZURpZERlbWF0ZXJpYWxpemUgPSBmdW5jdGlvbiBpbnZlcnNlRGlkRGVtYXRlcmlhbGl6ZShpbnZlcnNlUmVjb3JkRGF0YSkgewogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5pbnZlcnNlRGlkRGVtYXRlcmlhbGl6ZS5jYWxsKHRoaXMsIGludmVyc2VSZWNvcmREYXRhKTsKCiAgICAgIGlmICh0aGlzLmlzQXN5bmMpIHsKICAgICAgICB0aGlzLm5vdGlmeU1hbnlBcnJheUlzU3RhbGUoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uYWRkUmVjb3JkRGF0YSA9IGZ1bmN0aW9uIGFkZFJlY29yZERhdGEocmVjb3JkRGF0YSwgaWR4KSB7CiAgICAgIGlmICh0aGlzLm1lbWJlcnMuaGFzKHJlY29yZERhdGEpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIFRPRE8gVHlwZSB0aGlzCgoKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUuYWRkUmVjb3JkRGF0YS5jYWxsKHRoaXMsIHJlY29yZERhdGEsIGlkeCk7IC8vIG1ha2UgbGF6eSBsYXRlcgoKCiAgICAgIGlmIChpZHggPT09IHVuZGVmaW5lZCkgewogICAgICAgIGlkeCA9IHRoaXMuY3VycmVudFN0YXRlLmxlbmd0aDsKICAgICAgfQoKICAgICAgdGhpcy5jdXJyZW50U3RhdGUuc3BsaWNlKGlkeCwgMCwgcmVjb3JkRGF0YSk7IC8vIFRPRE8gSWdvciBjb25zaWRlciBtYWtpbmcgZGlyZWN0IHRvIHJlbW92ZSB0aGUgaW5kaXJlY3Rpb24KICAgICAgLy8gV2UgYXJlIG5vdCBsYXppbHkgYWNjZXNzaW5nIHRoZSBtYW55QXJyYXkgaGVyZSBiZWNhdXNlIHRoZSBjaGFuZ2UgaXMgY29taW5nIGZyb20gYXBwIHNpZGUKICAgICAgLy8gdGhpcy5tYW55QXJyYXkuZmx1c2hDYW5vbmljYWwodGhpcy5jdXJyZW50U3RhdGUpOwoKICAgICAgdGhpcy5ub3RpZnlIYXNNYW55Q2hhbmdlKCk7CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhRnJvbU93biA9IGZ1bmN0aW9uIHJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tT3duKHJlY29yZERhdGEsIGlkeCkgewogICAgICB2YXIgaSA9IGlkeDsKCiAgICAgIGlmICghdGhpcy5jYW5vbmljYWxNZW1iZXJzLmhhcyhyZWNvcmREYXRhKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgaWYgKGkgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGkgPSB0aGlzLmNhbm9uaWNhbFN0YXRlLmluZGV4T2YocmVjb3JkRGF0YSk7CiAgICAgIH0KCiAgICAgIGlmIChpID4gLTEpIHsKICAgICAgICB0aGlzLmNhbm9uaWNhbFN0YXRlLnNwbGljZShpLCAxKTsKICAgICAgfQoKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YUZyb21Pd24uY2FsbCh0aGlzLCByZWNvcmREYXRhLCBpZHgpOyAvL1RPRE8oSWdvcikgRmlndXJlIG91dCB3aGF0IHRvIGRvIGhlcmUKCiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVBbGxDYW5vbmljYWxSZWNvcmREYXRhc0Zyb21Pd24gPSBmdW5jdGlvbiByZW1vdmVBbGxDYW5vbmljYWxSZWNvcmREYXRhc0Zyb21Pd24oKSB7CiAgICAgIF9SZWxhdGlvbnNoaXAucHJvdG90eXBlLnJlbW92ZUFsbENhbm9uaWNhbFJlY29yZERhdGFzRnJvbU93bi5jYWxsKHRoaXMpOwoKICAgICAgdGhpcy5jYW5vbmljYWxNZW1iZXJzLmNsZWFyKCk7CiAgICAgIHRoaXMuY2Fub25pY2FsU3RhdGUuc3BsaWNlKDAsIHRoaXMuY2Fub25pY2FsU3RhdGUubGVuZ3RoKTsKCiAgICAgIF9SZWxhdGlvbnNoaXAucHJvdG90eXBlLnJlbW92ZUFsbENhbm9uaWNhbFJlY29yZERhdGFzRnJvbU93bi5jYWxsKHRoaXMpOwogICAgfSAvL1RPRE8oSWdvcikgRE8gV0UgTkVFRCBUSElTPwogICAgOwoKICAgIF9wcm90by5yZW1vdmVDb21wbGV0ZWx5RnJvbU93biA9IGZ1bmN0aW9uIHJlbW92ZUNvbXBsZXRlbHlGcm9tT3duKHJlY29yZERhdGEpIHsKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUucmVtb3ZlQ29tcGxldGVseUZyb21Pd24uY2FsbCh0aGlzLCByZWNvcmREYXRhKTsgLy8gVE9ETyBTa0VQVElDQUwKCgogICAgICB2YXIgY2Fub25pY2FsSW5kZXggPSB0aGlzLmNhbm9uaWNhbFN0YXRlLmluZGV4T2YocmVjb3JkRGF0YSk7CgogICAgICBpZiAoY2Fub25pY2FsSW5kZXggIT09IC0xKSB7CiAgICAgICAgdGhpcy5jYW5vbmljYWxTdGF0ZS5zcGxpY2UoY2Fub25pY2FsSW5kZXgsIDEpOwogICAgICB9CgogICAgICB0aGlzLnJlbW92ZVJlY29yZERhdGFGcm9tT3duKHJlY29yZERhdGEpOwogICAgfTsKCiAgICBfcHJvdG8uZmx1c2hDYW5vbmljYWwgPSBmdW5jdGlvbiBmbHVzaENhbm9uaWNhbCgpIHsKICAgICAgdmFyIHRvU2V0ID0gdGhpcy5jYW5vbmljYWxTdGF0ZTsgLy9hIGhhY2sgZm9yIG5vdCByZW1vdmluZyBuZXcgcmVjb3JkcwogICAgICAvL1RPRE8gcmVtb3ZlIG9uY2Ugd2UgaGF2ZSBwcm9wZXIgZGlmZmluZwoKICAgICAgdmFyIG5ld1JlY29yZERhdGFzID0gdGhpcy5jdXJyZW50U3RhdGUuZmlsdGVyKCAvLyBvbmx5IGFkZCBuZXcgaW50ZXJuYWxNb2RlbHMgd2hpY2ggYXJlIG5vdCB5ZXQgaW4gdGhlIGNhbm9uaWNhbCBzdGF0ZSBvZiB0aGlzCiAgICAgIC8vIHJlbGF0aW9uc2hpcCAoYSBuZXcgaW50ZXJuYWxNb2RlbCBjYW4gYmUgaW4gdGhlIGNhbm9uaWNhbCBzdGF0ZSBpZiBpdCBoYXMKICAgICAgLy8gYmVlbiAnYWNrbm93bGVnZWQnIHRvIGJlIGluIHRoZSByZWxhdGlvbnNoaXAgdmlhIGEgc3RvcmUucHVzaCkKICAgICAgLy9UT0RPIElnb3IgZGVhbCB3aXRoIHRoaXMKICAgICAgZnVuY3Rpb24gKHJlY29yZERhdGEpIHsKICAgICAgICByZXR1cm4gcmVjb3JkRGF0YS5pc05ldygpICYmIHRvU2V0LmluZGV4T2YocmVjb3JkRGF0YSkgPT09IC0xOwogICAgICB9KTsKICAgICAgdG9TZXQgPSB0b1NldC5jb25jYXQobmV3UmVjb3JkRGF0YXMpOwogICAgICAvKgogICAgICBpZiAodGhpcy5fbWFueUFycmF5KSB7CiAgICAgICAgdGhpcy5fbWFueUFycmF5LmZsdXNoQ2Fub25pY2FsKHRvU2V0KTsKICAgICAgfQogICAgICAqLwoKICAgICAgdGhpcy5jdXJyZW50U3RhdGUgPSB0b1NldDsKCiAgICAgIF9SZWxhdGlvbnNoaXAucHJvdG90eXBlLmZsdXNoQ2Fub25pY2FsLmNhbGwodGhpcyk7IC8vIE9uY2Ugd2UgY2xlYW4gdXAgYWxsIHRoZSBmbHVzaGluZywgd2Ugd2lsbCBiZSBsZWZ0IHdpdGggYXQgbGVhc3QgdGhlIG5vdGlmeWluZyBwYXJ0CgoKICAgICAgdGhpcy5ub3RpZnlIYXNNYW55Q2hhbmdlKCk7CiAgICB9IC8vVE9ETyhJZ29yKSBpZHggbm90IHVzZWQgY3VycmVudGx5LCBmaXgKICAgIDsKCiAgICBfcHJvdG8ucmVtb3ZlUmVjb3JkRGF0YUZyb21Pd24gPSBmdW5jdGlvbiByZW1vdmVSZWNvcmREYXRhRnJvbU93bihyZWNvcmREYXRhLCBpZHgpIHsKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUucmVtb3ZlUmVjb3JkRGF0YUZyb21Pd24uY2FsbCh0aGlzLCByZWNvcmREYXRhLCBpZHgpOwoKICAgICAgdmFyIGluZGV4ID0gaWR4IHx8IHRoaXMuY3VycmVudFN0YXRlLmluZGV4T2YocmVjb3JkRGF0YSk7IC8vVE9ETyBJR09SIERBVklEIElOVkVTVElHQVRFCgogICAgICBpZiAoaW5kZXggPT09IC0xKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLmN1cnJlbnRTdGF0ZS5zcGxpY2UoaW5kZXgsIDEpOyAvLyBUT0RPIElnb3IgY29uc2lkZXIgbWFraW5nIGRpcmVjdCB0byByZW1vdmUgdGhlIGluZGlyZWN0aW9uCiAgICAgIC8vIFdlIGFyZSBub3QgbGF6aWx5IGFjY2Vzc2luZyB0aGUgbWFueUFycmF5IGhlcmUgYmVjYXVzZSB0aGUgY2hhbmdlIGlzIGNvbWluZyBmcm9tIGFwcCBzaWRlCgogICAgICB0aGlzLm5vdGlmeUhhc01hbnlDaGFuZ2UoKTsgLy8gdGhpcy5tYW55QXJyYXkuZmx1c2hDYW5vbmljYWwodGhpcy5jdXJyZW50U3RhdGUpOwogICAgfTsKCiAgICBfcHJvdG8ubm90aWZ5UmVjb3JkUmVsYXRpb25zaGlwQWRkZWQgPSBmdW5jdGlvbiBub3RpZnlSZWNvcmRSZWxhdGlvbnNoaXBBZGRlZCgpIHsKICAgICAgdGhpcy5ub3RpZnlIYXNNYW55Q2hhbmdlKCk7CiAgICB9OwoKICAgIF9wcm90by5jb21wdXRlQ2hhbmdlcyA9IGZ1bmN0aW9uIGNvbXB1dGVDaGFuZ2VzKHJlY29yZERhdGFzKSB7CiAgICAgIGlmIChyZWNvcmREYXRhcyA9PT0gdm9pZCAwKSB7CiAgICAgICAgcmVjb3JkRGF0YXMgPSBbXTsKICAgICAgfQoKICAgICAgdmFyIG1lbWJlcnMgPSB0aGlzLmNhbm9uaWNhbE1lbWJlcnM7CiAgICAgIHZhciByZWNvcmREYXRhc1RvUmVtb3ZlID0gW107CiAgICAgIHZhciByZWNvcmREYXRhc1NldCA9IHNldEZvckFycmF5KHJlY29yZERhdGFzKTsKICAgICAgbWVtYmVycy5mb3JFYWNoKGZ1bmN0aW9uIChtZW1iZXIpIHsKICAgICAgICBpZiAocmVjb3JkRGF0YXNTZXQuaGFzKG1lbWJlcikpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHJlY29yZERhdGFzVG9SZW1vdmUucHVzaChtZW1iZXIpOwogICAgICB9KTsKICAgICAgdGhpcy5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhcyhyZWNvcmREYXRhc1RvUmVtb3ZlKTsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gcmVjb3JkRGF0YXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgdmFyIHJlY29yZERhdGEgPSByZWNvcmREYXRhc1tpXTsKICAgICAgICB0aGlzLnJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGEocmVjb3JkRGF0YSk7CiAgICAgICAgdGhpcy5hZGRDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGEsIGkpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5zZXRJbml0aWFsUmVjb3JkRGF0YXMgPSBmdW5jdGlvbiBzZXRJbml0aWFsUmVjb3JkRGF0YXMocmVjb3JkRGF0YXMpIHsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVjb3JkRGF0YXMpID09PSBmYWxzZSB8fCAhcmVjb3JkRGF0YXMgfHwgcmVjb3JkRGF0YXMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlY29yZERhdGFzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIHJlY29yZERhdGEgPSByZWNvcmREYXRhc1tpXTsKCiAgICAgICAgaWYgKHRoaXMuY2Fub25pY2FsTWVtYmVycy5oYXMocmVjb3JkRGF0YSkpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KCiAgICAgICAgdGhpcy5jYW5vbmljYWxNZW1iZXJzLmFkZChyZWNvcmREYXRhKTsKICAgICAgICB0aGlzLm1lbWJlcnMuYWRkKHJlY29yZERhdGEpOwogICAgICAgIHRoaXMuc2V0dXBJbnZlcnNlUmVsYXRpb25zaGlwKHJlY29yZERhdGEpOwogICAgICB9CgogICAgICB0aGlzLmNhbm9uaWNhbFN0YXRlID0gdGhpcy5jYW5vbmljYWxNZW1iZXJzLnRvQXJyYXkoKTsKICAgIH0KICAgIC8qCiAgICAgIFRoaXMgaXMgZXNzZW50aWFsbHkgYSAic3luYyIgdmVyc2lvbiBvZgogICAgICAgIG5vdGlmeUhhc01hbnlDaGFuZ2UuIFdlIHNob3VsZCB3b3JrIHRvIHVuaWZ5CiAgICAgICAgdGhlc2Ugd29ybGRzCiAgICAgICAgIC0gQHJ1bnNwaXJlZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ubm90aWZ5TWFueUFycmF5SXNTdGFsZSA9IGZ1bmN0aW9uIG5vdGlmeU1hbnlBcnJheUlzU3RhbGUoKSB7CiAgICAgIHZhciByZWNvcmREYXRhID0gdGhpcy5yZWNvcmREYXRhOwogICAgICB2YXIgc3RvcmVXcmFwcGVyID0gcmVjb3JkRGF0YS5zdG9yZVdyYXBwZXI7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgc3RvcmVXcmFwcGVyLm5vdGlmeUhhc01hbnlDaGFuZ2UocmVjb3JkRGF0YS5tb2RlbE5hbWUsIHJlY29yZERhdGEuaWQsIHJlY29yZERhdGEuY2xpZW50SWQsIHRoaXMua2V5KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBzdG9yZVdyYXBwZXIubm90aWZ5UHJvcGVydHlDaGFuZ2UocmVjb3JkRGF0YS5tb2RlbE5hbWUsIHJlY29yZERhdGEuaWQsIHJlY29yZERhdGEuY2xpZW50SWQsIHRoaXMua2V5KTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ubm90aWZ5SGFzTWFueUNoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeUhhc01hbnlDaGFuZ2UoKSB7CiAgICAgIHZhciByZWNvcmREYXRhID0gdGhpcy5yZWNvcmREYXRhOwogICAgICB2YXIgc3RvcmVXcmFwcGVyID0gcmVjb3JkRGF0YS5zdG9yZVdyYXBwZXI7CiAgICAgIHN0b3JlV3JhcHBlci5ub3RpZnlIYXNNYW55Q2hhbmdlKHJlY29yZERhdGEubW9kZWxOYW1lLCByZWNvcmREYXRhLmlkLCByZWNvcmREYXRhLmNsaWVudElkLCB0aGlzLmtleSk7CiAgICB9OwoKICAgIF9wcm90by5nZXREYXRhID0gZnVuY3Rpb24gZ2V0RGF0YSgpIHsKICAgICAgdmFyIHBheWxvYWQgPSB7fTsKCiAgICAgIGlmICh0aGlzLmhhc0FueVJlbGF0aW9uc2hpcERhdGEpIHsKICAgICAgICBwYXlsb2FkLmRhdGEgPSB0aGlzLmN1cnJlbnRTdGF0ZS5tYXAoZnVuY3Rpb24gKHJlY29yZERhdGEpIHsKICAgICAgICAgIHJldHVybiByZWNvcmREYXRhLmdldFJlc291cmNlSWRlbnRpZmllcigpOwogICAgICAgIH0pOwogICAgICB9CgogICAgICBpZiAodGhpcy5saW5rKSB7CiAgICAgICAgcGF5bG9hZC5saW5rcyA9IHsKICAgICAgICAgIHJlbGF0ZWQ6IHRoaXMubGluawogICAgICAgIH07CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLm1ldGEpIHsKICAgICAgICBwYXlsb2FkLm1ldGEgPSB0aGlzLm1ldGE7CiAgICAgIH0gLy8gVE9ETyBAcnVuc3BpcmVkOiB0aGUgQGlnb3IgcmVmYWN0b3IgaXMgdG9vIGxpbWl0aW5nIGZvciByZWxhdGlvbnNoaXAgc3RhdGUKICAgICAgLy8gICB3ZSBzaG91bGQgcmVjb25zaWRlciB3aGVyZSB3ZSBmZXRjaCBmcm9tLgoKCiAgICAgIHBheWxvYWQuX3JlbGF0aW9uc2hpcCA9IHRoaXM7CiAgICAgIHJldHVybiBwYXlsb2FkOwogICAgfTsKCiAgICBfcHJvdG8udXBkYXRlRGF0YSA9IGZ1bmN0aW9uIHVwZGF0ZURhdGEoZGF0YSwgaW5pdGlhbCkgewogICAgICB2YXIgcmVjb3JkRGF0YXM7CgogICAgICBpZiAoRW1iZXIuaXNOb25lKGRhdGEpKSB7CiAgICAgICAgcmVjb3JkRGF0YXMgPSB1bmRlZmluZWQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmVjb3JkRGF0YXMgPSBuZXcgQXJyYXkoZGF0YS5sZW5ndGgpOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHJlY29yZERhdGFzW2ldID0gdGhpcy5yZWNvcmREYXRhLnN0b3JlV3JhcHBlci5yZWNvcmREYXRhRm9yKGRhdGFbaV0udHlwZSwgZGF0YVtpXS5pZCk7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoaW5pdGlhbCkgewogICAgICAgIHRoaXMuc2V0SW5pdGlhbFJlY29yZERhdGFzKHJlY29yZERhdGFzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnVwZGF0ZVJlY29yZERhdGFzRnJvbUFkYXB0ZXIocmVjb3JkRGF0YXMpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIEZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIGFsbCBpbnZlcnNlIHJlY29yZHMgYXJlIGF2YWlsYWJsZQogICAgICoKICAgICAqIHRydWUgaWYgaW52ZXJzZSByZWNvcmRzIGV4aXN0IGFuZCBhcmUgYWxsIGxvYWRlZCAoYWxsIG5vdCBlbXB0eSkKICAgICAqIHRydWUgaWYgdGhlcmUgYXJlIG5vIGludmVyc2UgcmVjb3JkcwogICAgICogZmFsc2UgaWYgdGhlIGludmVyc2UgcmVjb3JkcyBleGlzdCBhbmQgYW55IGFyZSBub3QgbG9hZGVkIChhbnkgZW1wdHkpCiAgICAgKgogICAgICogQHJldHVybiB7Ym9vbGVhbn0KICAgICAqLwogICAgOwoKICAgIF9jcmVhdGVDbGFzcyQxKE1hbnlSZWxhdGlvbnNoaXAsIFt7CiAgICAgIGtleTogImFsbEludmVyc2VSZWNvcmRzQXJlTG9hZGVkIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgLy8gY2hlY2sgY3VycmVudFN0YXRlIGZvciB1bmxvYWRlZCByZWNvcmRzCiAgICAgICAgdmFyIGhhc0VtcHR5UmVjb3JkcyA9IHRoaXMuY3VycmVudFN0YXRlLnJlZHVjZShmdW5jdGlvbiAoaGFzRW1wdHlNb2RlbCwgaSkgewogICAgICAgICAgcmV0dXJuIGhhc0VtcHR5TW9kZWwgfHwgaS5pc0VtcHR5KCk7CiAgICAgICAgfSwgZmFsc2UpOyAvLyBjaGVjayB1bi1zeW5jZWQgc3RhdGUgZm9yIHVubG9hZGVkIHJlY29yZHMKCiAgICAgICAgaWYgKCFoYXNFbXB0eVJlY29yZHMgJiYgdGhpcy53aWxsU3luYykgewogICAgICAgICAgaGFzRW1wdHlSZWNvcmRzID0gdGhpcy5jYW5vbmljYWxTdGF0ZS5yZWR1Y2UoZnVuY3Rpb24gKGhhc0VtcHR5TW9kZWwsIGkpIHsKICAgICAgICAgICAgcmV0dXJuIGhhc0VtcHR5TW9kZWwgfHwgIWkuaXNFbXB0eSgpOwogICAgICAgICAgfSwgZmFsc2UpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuICFoYXNFbXB0eVJlY29yZHM7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gTWFueVJlbGF0aW9uc2hpcDsKICB9KFJlbGF0aW9uc2hpcCk7CgogIGZ1bmN0aW9uIHNldEZvckFycmF5KGFycmF5KSB7CiAgICB2YXIgc2V0ID0gbmV3IEVtYmVyRGF0YU9yZGVyZWRTZXQoKTsKCiAgICBpZiAoYXJyYXkpIHsKICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBhcnJheS5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICBzZXQuYWRkKGFycmF5W2ldKTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBzZXQ7CiAgfQoKICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyQyKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyQyKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMkMihDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDIoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIGZ1bmN0aW9uIF9pbmhlcml0c0xvb3NlJDIoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzLnByb3RvdHlwZSk7IHN1YkNsYXNzLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IHN1YkNsYXNzOyBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9CgogIHZhciBCZWxvbmdzVG9SZWxhdGlvbnNoaXAgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1JlbGF0aW9uc2hpcCkgewogICAgX2luaGVyaXRzTG9vc2UkMihCZWxvbmdzVG9SZWxhdGlvbnNoaXAsIF9SZWxhdGlvbnNoaXApOwoKICAgIGZ1bmN0aW9uIEJlbG9uZ3NUb1JlbGF0aW9uc2hpcChzdG9yZSwgaW52ZXJzZUtleSwgcmVsYXRpb25zaGlwTWV0YSwgcmVjb3JkRGF0YSwgaW52ZXJzZUlzQXN5bmMpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfUmVsYXRpb25zaGlwLmNhbGwodGhpcywgc3RvcmUsIGludmVyc2VLZXksIHJlbGF0aW9uc2hpcE1ldGEsIHJlY29yZERhdGEsIGludmVyc2VJc0FzeW5jKSB8fCB0aGlzOwogICAgICBfdGhpcy5pbnZlcnNlUmVjb3JkRGF0YSA9IHZvaWQgMDsKICAgICAgX3RoaXMuY2Fub25pY2FsU3RhdGUgPSB2b2lkIDA7CiAgICAgIF90aGlzLmtleSA9IHZvaWQgMDsKICAgICAgX3RoaXMua2V5ID0gcmVsYXRpb25zaGlwTWV0YS5rZXk7CiAgICAgIF90aGlzLmludmVyc2VSZWNvcmREYXRhID0gbnVsbDsKICAgICAgX3RoaXMuY2Fub25pY2FsU3RhdGUgPSBudWxsOwogICAgICBfdGhpcy5rZXkgPSByZWxhdGlvbnNoaXBNZXRhLmtleTsKICAgICAgcmV0dXJuIF90aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBCZWxvbmdzVG9SZWxhdGlvbnNoaXAucHJvdG90eXBlOwoKICAgIF9wcm90by5zZXRSZWNvcmREYXRhID0gZnVuY3Rpb24gc2V0UmVjb3JkRGF0YShyZWNvcmREYXRhKSB7CiAgICAgIGlmIChyZWNvcmREYXRhKSB7CiAgICAgICAgdGhpcy5hZGRSZWNvcmREYXRhKHJlY29yZERhdGEpOwogICAgICB9IGVsc2UgaWYgKHRoaXMuaW52ZXJzZVJlY29yZERhdGEpIHsKICAgICAgICB0aGlzLnJlbW92ZVJlY29yZERhdGEodGhpcy5pbnZlcnNlUmVjb3JkRGF0YSk7CiAgICAgIH0KCiAgICAgIHRoaXMuc2V0SGFzQW55UmVsYXRpb25zaGlwRGF0YSh0cnVlKTsKICAgICAgdGhpcy5zZXRSZWxhdGlvbnNoaXBJc1N0YWxlKGZhbHNlKTsKICAgICAgdGhpcy5zZXRSZWxhdGlvbnNoaXBJc0VtcHR5KGZhbHNlKTsKICAgIH07CgogICAgX3Byb3RvLnNldENhbm9uaWNhbFJlY29yZERhdGEgPSBmdW5jdGlvbiBzZXRDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGEpIHsKICAgICAgaWYgKHJlY29yZERhdGEpIHsKICAgICAgICB0aGlzLmFkZENhbm9uaWNhbFJlY29yZERhdGEocmVjb3JkRGF0YSk7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5jYW5vbmljYWxTdGF0ZSkgewogICAgICAgIHRoaXMucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YSh0aGlzLmNhbm9uaWNhbFN0YXRlKTsKICAgICAgfQoKICAgICAgdGhpcy5mbHVzaENhbm9uaWNhbExhdGVyKCk7CiAgICB9OwoKICAgIF9wcm90by5zZXRJbml0aWFsQ2Fub25pY2FsUmVjb3JkRGF0YSA9IGZ1bmN0aW9uIHNldEluaXRpYWxDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGEpIHsKICAgICAgaWYgKCFyZWNvcmREYXRhKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIFdoZW4gd2UgaW5pdGlhbGl6ZSBhIGJlbG9uZ3NUbyByZWxhdGlvbnNoaXAsIHdlIHdhbnQgdG8gYXZvaWQgd29yayBsaWtlCiAgICAgIC8vIG5vdGlmeWluZyBvdXIgaW50ZXJuYWxNb2RlbCB0aGF0IHdlJ3ZlICJjaGFuZ2VkIiBhbmQgZXhjZXNzaXZlIHRocmFzaCBvbgogICAgICAvLyBzZXR0aW5nIHVwIGludmVyc2UgcmVsYXRpb25zaGlwcwoKCiAgICAgIHRoaXMuY2Fub25pY2FsTWVtYmVycy5hZGQocmVjb3JkRGF0YSk7CiAgICAgIHRoaXMubWVtYmVycy5hZGQocmVjb3JkRGF0YSk7CiAgICAgIHRoaXMuaW52ZXJzZVJlY29yZERhdGEgPSB0aGlzLmNhbm9uaWNhbFN0YXRlID0gcmVjb3JkRGF0YTsKICAgICAgdGhpcy5zZXR1cEludmVyc2VSZWxhdGlvbnNoaXAocmVjb3JkRGF0YSk7CiAgICB9OwoKICAgIF9wcm90by5hZGRDYW5vbmljYWxSZWNvcmREYXRhID0gZnVuY3Rpb24gYWRkQ2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhKSB7CiAgICAgIGlmICh0aGlzLmNhbm9uaWNhbE1lbWJlcnMuaGFzKHJlY29yZERhdGEpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAodGhpcy5jYW5vbmljYWxTdGF0ZSkgewogICAgICAgIHRoaXMucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YSh0aGlzLmNhbm9uaWNhbFN0YXRlKTsKICAgICAgfQoKICAgICAgdGhpcy5jYW5vbmljYWxTdGF0ZSA9IHJlY29yZERhdGE7CgogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5hZGRDYW5vbmljYWxSZWNvcmREYXRhLmNhbGwodGhpcywgcmVjb3JkRGF0YSk7CgogICAgICB0aGlzLnNldEhhc0FueVJlbGF0aW9uc2hpcERhdGEodHJ1ZSk7CiAgICAgIHRoaXMuc2V0UmVsYXRpb25zaGlwSXNFbXB0eShmYWxzZSk7CiAgICB9OwoKICAgIF9wcm90by5pbnZlcnNlRGlkRGVtYXRlcmlhbGl6ZSA9IGZ1bmN0aW9uIGludmVyc2VEaWREZW1hdGVyaWFsaXplKCkgewogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5pbnZlcnNlRGlkRGVtYXRlcmlhbGl6ZS5jYWxsKHRoaXMsIHRoaXMuaW52ZXJzZVJlY29yZERhdGEpOwoKICAgICAgdGhpcy5ub3RpZnlCZWxvbmdzVG9DaGFuZ2UoKTsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUNvbXBsZXRlbHlGcm9tT3duID0gZnVuY3Rpb24gcmVtb3ZlQ29tcGxldGVseUZyb21Pd24ocmVjb3JkRGF0YSkgewogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5yZW1vdmVDb21wbGV0ZWx5RnJvbU93bi5jYWxsKHRoaXMsIHJlY29yZERhdGEpOwoKICAgICAgaWYgKHRoaXMuY2Fub25pY2FsU3RhdGUgPT09IHJlY29yZERhdGEpIHsKICAgICAgICB0aGlzLmNhbm9uaWNhbFN0YXRlID0gbnVsbDsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuaW52ZXJzZVJlY29yZERhdGEgPT09IHJlY29yZERhdGEpIHsKICAgICAgICB0aGlzLmludmVyc2VSZWNvcmREYXRhID0gbnVsbDsKICAgICAgICB0aGlzLm5vdGlmeUJlbG9uZ3NUb0NoYW5nZSgpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVDb21wbGV0ZWx5RnJvbUludmVyc2UgPSBmdW5jdGlvbiByZW1vdmVDb21wbGV0ZWx5RnJvbUludmVyc2UoKSB7CiAgICAgIF9SZWxhdGlvbnNoaXAucHJvdG90eXBlLnJlbW92ZUNvbXBsZXRlbHlGcm9tSW52ZXJzZS5jYWxsKHRoaXMpOwoKICAgICAgdGhpcy5pbnZlcnNlUmVjb3JkRGF0YSA9IG51bGw7CiAgICB9OwoKICAgIF9wcm90by5mbHVzaENhbm9uaWNhbCA9IGZ1bmN0aW9uIGZsdXNoQ2Fub25pY2FsKCkgewogICAgICAvL3RlbXBvcmFyeSBmaXggdG8gbm90IHJlbW92ZSBuZXdseSBjcmVhdGVkIHJlY29yZHMgaWYgc2VydmVyIHJldHVybmVkIG51bGwuCiAgICAgIC8vVE9ETyByZW1vdmUgb25jZSB3ZSBoYXZlIHByb3BlciBkaWZmaW5nCiAgICAgIGlmICh0aGlzLmludmVyc2VSZWNvcmREYXRhICYmIHRoaXMuaW52ZXJzZVJlY29yZERhdGEuaXNOZXcoKSAmJiAhdGhpcy5jYW5vbmljYWxTdGF0ZSkgewogICAgICAgIHRoaXMud2lsbFN5bmMgPSBmYWxzZTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmludmVyc2VSZWNvcmREYXRhICE9PSB0aGlzLmNhbm9uaWNhbFN0YXRlKSB7CiAgICAgICAgdGhpcy5pbnZlcnNlUmVjb3JkRGF0YSA9IHRoaXMuY2Fub25pY2FsU3RhdGU7CiAgICAgICAgdGhpcy5ub3RpZnlCZWxvbmdzVG9DaGFuZ2UoKTsKICAgICAgfQoKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUuZmx1c2hDYW5vbmljYWwuY2FsbCh0aGlzKTsKICAgIH07CgogICAgX3Byb3RvLmFkZFJlY29yZERhdGEgPSBmdW5jdGlvbiBhZGRSZWNvcmREYXRhKHJlY29yZERhdGEpIHsKICAgICAgaWYgKHRoaXMubWVtYmVycy5oYXMocmVjb3JkRGF0YSkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gLy8gVE9ETyBJZ29yIGNsZWFudXAKCgogICAgICBpZiAodGhpcy5pbnZlcnNlUmVjb3JkRGF0YSkgewogICAgICAgIHRoaXMucmVtb3ZlUmVjb3JkRGF0YSh0aGlzLmludmVyc2VSZWNvcmREYXRhKTsKICAgICAgfQoKICAgICAgdGhpcy5pbnZlcnNlUmVjb3JkRGF0YSA9IHJlY29yZERhdGE7CgogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5hZGRSZWNvcmREYXRhLmNhbGwodGhpcywgcmVjb3JkRGF0YSk7CgogICAgICB0aGlzLm5vdGlmeUJlbG9uZ3NUb0NoYW5nZSgpOwogICAgfTsKCiAgICBfcHJvdG8ucmVtb3ZlUmVjb3JkRGF0YUZyb21Pd24gPSBmdW5jdGlvbiByZW1vdmVSZWNvcmREYXRhRnJvbU93bihyZWNvcmREYXRhKSB7CiAgICAgIGlmICghdGhpcy5tZW1iZXJzLmhhcyhyZWNvcmREYXRhKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5pbnZlcnNlUmVjb3JkRGF0YSA9IG51bGw7CgogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5yZW1vdmVSZWNvcmREYXRhRnJvbU93bi5jYWxsKHRoaXMsIHJlY29yZERhdGEpOwoKICAgICAgdGhpcy5ub3RpZnlCZWxvbmdzVG9DaGFuZ2UoKTsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUFsbFJlY29yZERhdGFzRnJvbU93biA9IGZ1bmN0aW9uIHJlbW92ZUFsbFJlY29yZERhdGFzRnJvbU93bigpIHsKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUucmVtb3ZlQWxsUmVjb3JkRGF0YXNGcm9tT3duLmNhbGwodGhpcyk7CgogICAgICB0aGlzLmludmVyc2VSZWNvcmREYXRhID0gbnVsbDsKICAgICAgdGhpcy5ub3RpZnlCZWxvbmdzVG9DaGFuZ2UoKTsKICAgIH07CgogICAgX3Byb3RvLm5vdGlmeUJlbG9uZ3NUb0NoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeUJlbG9uZ3NUb0NoYW5nZSgpIHsKICAgICAgdmFyIHJlY29yZERhdGEgPSB0aGlzLnJlY29yZERhdGE7CiAgICAgIHZhciBzdG9yZVdyYXBwZXIgPSB0aGlzLnJlY29yZERhdGEuc3RvcmVXcmFwcGVyOwogICAgICBzdG9yZVdyYXBwZXIubm90aWZ5QmVsb25nc1RvQ2hhbmdlKHJlY29yZERhdGEubW9kZWxOYW1lLCByZWNvcmREYXRhLmlkLCByZWNvcmREYXRhLmNsaWVudElkLCB0aGlzLmtleSk7CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhRnJvbU93biA9IGZ1bmN0aW9uIHJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tT3duKHJlY29yZERhdGEpIHsKICAgICAgaWYgKCF0aGlzLmNhbm9uaWNhbE1lbWJlcnMuaGFzKHJlY29yZERhdGEpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLmNhbm9uaWNhbFN0YXRlID0gbnVsbDsKICAgICAgdGhpcy5zZXRIYXNBbnlSZWxhdGlvbnNoaXBEYXRhKHRydWUpOwogICAgICB0aGlzLnNldFJlbGF0aW9uc2hpcElzRW1wdHkodHJ1ZSk7CgogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhRnJvbU93bi5jYWxsKHRoaXMsIHJlY29yZERhdGEpOwogICAgfTsKCiAgICBfcHJvdG8ucmVtb3ZlQWxsQ2Fub25pY2FsUmVjb3JkRGF0YXNGcm9tT3duID0gZnVuY3Rpb24gcmVtb3ZlQWxsQ2Fub25pY2FsUmVjb3JkRGF0YXNGcm9tT3duKCkgewogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5yZW1vdmVBbGxDYW5vbmljYWxSZWNvcmREYXRhc0Zyb21Pd24uY2FsbCh0aGlzKTsKCiAgICAgIHRoaXMuY2Fub25pY2FsU3RhdGUgPSBudWxsOwogICAgfTsKCiAgICBfcHJvdG8uZ2V0RGF0YSA9IGZ1bmN0aW9uIGdldERhdGEoKSB7CiAgICAgIHZhciBkYXRhOwogICAgICB2YXIgcGF5bG9hZCA9IHt9OwoKICAgICAgaWYgKHRoaXMuaW52ZXJzZVJlY29yZERhdGEpIHsKICAgICAgICBkYXRhID0gdGhpcy5pbnZlcnNlUmVjb3JkRGF0YS5nZXRSZXNvdXJjZUlkZW50aWZpZXIoKTsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuaW52ZXJzZVJlY29yZERhdGEgPT09IG51bGwgJiYgdGhpcy5oYXNBbnlSZWxhdGlvbnNoaXBEYXRhKSB7CiAgICAgICAgZGF0YSA9IG51bGw7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmxpbmspIHsKICAgICAgICBwYXlsb2FkLmxpbmtzID0gewogICAgICAgICAgcmVsYXRlZDogdGhpcy5saW5rCiAgICAgICAgfTsKICAgICAgfQoKICAgICAgaWYgKGRhdGEgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHBheWxvYWQuZGF0YSA9IGRhdGE7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLm1ldGEpIHsKICAgICAgICBwYXlsb2FkLm1ldGEgPSB0aGlzLm1ldGE7CiAgICAgIH0KCiAgICAgIHBheWxvYWQuX3JlbGF0aW9uc2hpcCA9IHRoaXM7CiAgICAgIHJldHVybiBwYXlsb2FkOwogICAgfQogICAgLyoqCiAgICAgKiBGbGFnIGluZGljYXRpbmcgd2hldGhlciBhbGwgaW52ZXJzZSByZWNvcmRzIGFyZSBhdmFpbGFibGUKICAgICAqCiAgICAgKiB0cnVlIGlmIHRoZSBpbnZlcnNlIGV4aXN0cyBhbmQgaXMgbG9hZGVkIChub3QgZW1wdHkpCiAgICAgKiB0cnVlIGlmIHRoZXJlIGlzIG5vIGludmVyc2UKICAgICAqIGZhbHNlIGlmIHRoZSBpbnZlcnNlIGV4aXN0cyBhbmQgaXMgbm90IGxvYWRlZCAoZW1wdHkpCiAgICAgKgogICAgICogQHJldHVybiB7Ym9vbGVhbn0KICAgICAqLwogICAgOwoKICAgIF9wcm90by51cGRhdGVEYXRhID0gZnVuY3Rpb24gdXBkYXRlRGF0YShkYXRhLCBpbml0aWFsKSB7CiAgICAgIHZhciByZWNvcmREYXRhOwoKICAgICAgaWYgKEVtYmVyLmlzTm9uZShkYXRhKSkgewogICAgICAgIHJlY29yZERhdGEgPSBudWxsOwogICAgICB9CgogICAgICBpZiAocmVjb3JkRGF0YSAhPT0gbnVsbCkgewogICAgICAgIHJlY29yZERhdGEgPSB0aGlzLnJlY29yZERhdGEuc3RvcmVXcmFwcGVyLnJlY29yZERhdGFGb3IoZGF0YS50eXBlLCBkYXRhLmlkKTsKICAgICAgfQoKICAgICAgaWYgKGluaXRpYWwpIHsKICAgICAgICB0aGlzLnNldEluaXRpYWxDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGEpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuc2V0Q2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhKTsKICAgICAgfQogICAgfTsKCiAgICBfY3JlYXRlQ2xhc3MkMihCZWxvbmdzVG9SZWxhdGlvbnNoaXAsIFt7CiAgICAgIGtleTogImFsbEludmVyc2VSZWNvcmRzQXJlTG9hZGVkIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIHJlY29yZERhdGEgPSB0aGlzLmludmVyc2VSZWNvcmREYXRhOwogICAgICAgIHZhciBpc0VtcHR5ID0gcmVjb3JkRGF0YSAhPT0gbnVsbCAmJiByZWNvcmREYXRhLmlzRW1wdHkoKTsKICAgICAgICByZXR1cm4gIWlzRW1wdHk7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gQmVsb25nc1RvUmVsYXRpb25zaGlwOwogIH0oUmVsYXRpb25zaGlwKTsKCiAgZnVuY3Rpb24gY3JlYXRlUmVsYXRpb25zaGlwRm9yKHJlbGF0aW9uc2hpcE1ldGEsIHN0b3JlLCByZWNvcmREYXRhLCBrZXkpIHsKICAgIHZhciBpbnZlcnNlS2V5ID0gcmVjb3JkRGF0YS5zdG9yZVdyYXBwZXIuaW52ZXJzZUZvclJlbGF0aW9uc2hpcChyZWNvcmREYXRhLm1vZGVsTmFtZSwga2V5KTsKICAgIHZhciBpbnZlcnNlSXNBc3luYyA9IHJlY29yZERhdGEuc3RvcmVXcmFwcGVyLmludmVyc2VJc0FzeW5jRm9yUmVsYXRpb25zaGlwKHJlY29yZERhdGEubW9kZWxOYW1lLCBrZXkpOwoKICAgIGlmIChyZWxhdGlvbnNoaXBNZXRhLmtpbmQgPT09ICdoYXNNYW55JykgewogICAgICByZXR1cm4gbmV3IE1hbnlSZWxhdGlvbnNoaXAoc3RvcmUsIGludmVyc2VLZXksIHJlbGF0aW9uc2hpcE1ldGEsIHJlY29yZERhdGEsIGludmVyc2VJc0FzeW5jKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBuZXcgQmVsb25nc1RvUmVsYXRpb25zaGlwKHN0b3JlLCBpbnZlcnNlS2V5LCByZWxhdGlvbnNoaXBNZXRhLCByZWNvcmREYXRhLCBpbnZlcnNlSXNBc3luYyk7CiAgICB9CiAgfQoKICB2YXIgUmVsYXRpb25zaGlwcyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJlbGF0aW9uc2hpcHMocmVjb3JkRGF0YSkgewogICAgICB0aGlzLnJlY29yZERhdGEgPSByZWNvcmREYXRhOwogICAgICB0aGlzLl9zdG9yZSA9IHZvaWQgMDsKICAgICAgdGhpcy5fc3RvcmVXcmFwcGVyID0gdm9pZCAwOwogICAgICB0aGlzLmluaXRpYWxpemVkUmVsYXRpb25zaGlwcyA9IHZvaWQgMDsKICAgICAgdGhpcy5pbml0aWFsaXplZFJlbGF0aW9uc2hpcHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9zdG9yZVdyYXBwZXIgPSBQcml2YXRlLnVwZ3JhZGVGb3JJbnRlcm5hbChyZWNvcmREYXRhLnN0b3JlV3JhcHBlcik7CiAgICAgIHRoaXMuX3N0b3JlID0gdGhpcy5fc3RvcmVXcmFwcGVyLl9zdG9yZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gUmVsYXRpb25zaGlwcy5wcm90b3R5cGU7CgogICAgX3Byb3RvLmhhcyA9IGZ1bmN0aW9uIGhhcyhrZXkpIHsKICAgICAgcmV0dXJuICEhdGhpcy5pbml0aWFsaXplZFJlbGF0aW9uc2hpcHNba2V5XTsKICAgIH07CgogICAgX3Byb3RvLmZvckVhY2ggPSBmdW5jdGlvbiBmb3JFYWNoKGNiKSB7CiAgICAgIHZhciByZWxzID0gdGhpcy5pbml0aWFsaXplZFJlbGF0aW9uc2hpcHM7CiAgICAgIE9iamVjdC5rZXlzKHJlbHMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHsKICAgICAgICBjYihuYW1lLCByZWxzW25hbWVdKTsKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5nZXQgPSBmdW5jdGlvbiBnZXQoa2V5KSB7CiAgICAgIHZhciByZWxhdGlvbnNoaXBzID0gdGhpcy5pbml0aWFsaXplZFJlbGF0aW9uc2hpcHM7CiAgICAgIHZhciByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXBzW2tleV07CgogICAgICBpZiAoIXJlbGF0aW9uc2hpcCkgewogICAgICAgIHZhciBfcmVjb3JkRGF0YSA9IHRoaXMucmVjb3JkRGF0YTsKICAgICAgICB2YXIgcmVsID0gdGhpcy5yZWNvcmREYXRhLnN0b3JlV3JhcHBlci5yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcih0aGlzLnJlY29yZERhdGEubW9kZWxOYW1lKVtrZXldOwoKICAgICAgICBpZiAocmVsKSB7CiAgICAgICAgICByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXBzW2tleV0gPSBjcmVhdGVSZWxhdGlvbnNoaXBGb3IocmVsLCB0aGlzLl9zdG9yZSwgX3JlY29yZERhdGEsIGtleSk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gcmVsYXRpb25zaGlwOwogICAgfTsKCiAgICByZXR1cm4gUmVsYXRpb25zaGlwczsKICB9KCk7CgogIC8vIFVzZWQgYnkgdGhlIHN0b3JlIHRvIG5vcm1hbGl6ZSBJRHMgZW50ZXJpbmcgdGhlIHN0b3JlLiAgRGVzcGl0ZSB0aGUgZmFjdAogIC8vIHRoYXQgZGV2ZWxvcGVycyBtYXkgcHJvdmlkZSBJRHMgYXMgbnVtYmVycyAoZS5nLiwgYHN0b3JlLmZpbmRSZWNvcmQoJ3BlcnNvbicsIDEpYCksCiAgLy8gaXQgaXMgaW1wb3J0YW50IHRoYXQgaW50ZXJuYWxseSB3ZSB1c2Ugc3RyaW5ncywgc2luY2UgSURzIG1heSBiZSBzZXJpYWxpemVkCiAgLy8gYW5kIGxvc2UgdHlwZSBpbmZvcm1hdGlvbi4gIEZvciBleGFtcGxlLCBFbWJlcidzIHJvdXRlciBtYXkgcHV0IGEgcmVjb3JkJ3MKICAvLyBJRCBpbnRvIHRoZSBVUkwsIGFuZCBpZiB3ZSBsYXRlciB0cnkgdG8gZGVzZXJpYWxpemUgdGhhdCBVUkwgYW5kIGZpbmQgdGhlCiAgLy8gY29ycmVzcG9uZGluZyByZWNvcmQsIHdlIHdpbGwgbm90IGtub3cgaWYgaXQgaXMgYSBzdHJpbmcgb3IgYSBudW1iZXIuCiAgZnVuY3Rpb24gY29lcmNlSWQoaWQpIHsKICAgIGlmIChpZCA9PT0gbnVsbCB8fCBpZCA9PT0gdW5kZWZpbmVkIHx8IGlkID09PSAnJykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KCiAgICBpZiAodHlwZW9mIGlkID09PSAnc3RyaW5nJykgewogICAgICByZXR1cm4gaWQ7CiAgICB9CgogICAgaWYgKHR5cGVvZiBpZCA9PT0gJ3N5bWJvbCcpIHsKICAgICAgcmV0dXJuIGlkLnRvU3RyaW5nKCk7CiAgICB9CgogICAgcmV0dXJuICcnICsgaWQ7CiAgfQoKICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyQzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyQzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMkMyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CiAgdmFyIG5leHRCZnNJZCA9IDE7CgogIHZhciBSZWNvcmREYXRhRGVmYXVsdCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJlY29yZERhdGFEZWZhdWx0KGFyZzEsIGFyZzIpIHsKICAgICAgdGhpcy5fZXJyb3JzID0gdm9pZCAwOwogICAgICB0aGlzLl9fcmVsYXRpb25zaGlwcyA9IHZvaWQgMDsKICAgICAgdGhpcy5fX2ltcGxpY2l0UmVsYXRpb25zaGlwcyA9IHZvaWQgMDsKICAgICAgdGhpcy5tb2RlbE5hbWUgPSB2b2lkIDA7CiAgICAgIHRoaXMuY2xpZW50SWQgPSB2b2lkIDA7CiAgICAgIHRoaXMuaWQgPSB2b2lkIDA7CiAgICAgIHRoaXMuaXNEZXN0cm95ZWQgPSB2b2lkIDA7CiAgICAgIHRoaXMuX2lzTmV3ID0gdm9pZCAwOwogICAgICB0aGlzLl9iZnNJZCA9IHZvaWQgMDsKICAgICAgdGhpcy5fX2F0dHJpYnV0ZXMgPSB2b2lkIDA7CiAgICAgIHRoaXMuX19pbkZsaWdodEF0dHJpYnV0ZXMgPSB2b2lkIDA7CiAgICAgIHRoaXMuX19kYXRhID0gdm9pZCAwOwogICAgICB0aGlzLl9zY2hlZHVsZWREZXN0cm95ID0gdm9pZCAwOwogICAgICB0aGlzLl9pc0RlbGV0ZWQgPSB2b2lkIDA7CiAgICAgIHRoaXMuX2lzRGVsZXRpb25Db21taXRlZCA9IHZvaWQgMDsKICAgICAgdGhpcy5pZGVudGlmaWVyID0gdm9pZCAwOwogICAgICB0aGlzLnN0b3JlV3JhcHBlciA9IHZvaWQgMDsKCiAgICAgIHsKICAgICAgICB2YXIgX2lkZW50aWZpZXIgPSBhcmd1bWVudHNbMF0sCiAgICAgICAgICAgIF9zdG9yZVdyYXBwZXIgPSBhcmd1bWVudHNbMV07CiAgICAgICAgdGhpcy5pZGVudGlmaWVyID0gX2lkZW50aWZpZXI7CiAgICAgICAgdGhpcy5tb2RlbE5hbWUgPSBfaWRlbnRpZmllci50eXBlOwogICAgICAgIHRoaXMuY2xpZW50SWQgPSBfaWRlbnRpZmllci5saWQ7CiAgICAgICAgdGhpcy5pZCA9IF9pZGVudGlmaWVyLmlkOwogICAgICAgIHRoaXMuc3RvcmVXcmFwcGVyID0gX3N0b3JlV3JhcHBlcjsKICAgICAgfQoKICAgICAgdGhpcy5fX3JlbGF0aW9uc2hpcHMgPSBudWxsOwogICAgICB0aGlzLl9faW1wbGljaXRSZWxhdGlvbnNoaXBzID0gbnVsbDsKICAgICAgdGhpcy5pc0Rlc3Ryb3llZCA9IGZhbHNlOwogICAgICB0aGlzLl9pc05ldyA9IGZhbHNlOwogICAgICB0aGlzLl9pc0RlbGV0ZWQgPSBmYWxzZTsgLy8gVXNlZCBkdXJpbmcgdGhlIG1hcmsgcGhhc2Ugb2YgdW5sb2FkaW5nIHRvIGF2b2lkIGNoZWNraW5nIHRoZSBzYW1lIGludGVybmFsCiAgICAgIC8vIG1vZGVsIHR3aWNlIGluIHRoZSBzYW1lIHNjYW4KCiAgICAgIHRoaXMuX2Jmc0lkID0gMDsKICAgICAgdGhpcy5yZXNldCgpOwogICAgfSAvLyBQVUJMSUMgQVBJCgoKICAgIHZhciBfcHJvdG8gPSBSZWNvcmREYXRhRGVmYXVsdC5wcm90b3R5cGU7CgogICAgX3Byb3RvLmdldFJlc291cmNlSWRlbnRpZmllciA9IGZ1bmN0aW9uIGdldFJlc291cmNlSWRlbnRpZmllcigpIHsKICAgICAgcmV0dXJuICB0aGlzLmlkZW50aWZpZXIgOwogICAgfTsKCiAgICBfcHJvdG8ucHVzaERhdGEgPSBmdW5jdGlvbiBwdXNoRGF0YShkYXRhLCBjYWxjdWxhdGVDaGFuZ2UpIHsKICAgICAgdmFyIGNoYW5nZWRLZXlzOwoKICAgICAgaWYgKHRoaXMuX2lzTmV3KSB7CiAgICAgICAgdGhpcy5faXNOZXcgPSBmYWxzZTsKICAgICAgICB0aGlzLm5vdGlmeVN0YXRlQ2hhbmdlKCk7CiAgICAgIH0KCiAgICAgIGlmIChjYWxjdWxhdGVDaGFuZ2UpIHsKICAgICAgICBjaGFuZ2VkS2V5cyA9IHRoaXMuX2NoYW5nZWRLZXlzKGRhdGEuYXR0cmlidXRlcyk7CiAgICAgIH0KCiAgICAgIEVtYmVyLmFzc2lnbih0aGlzLl9kYXRhLCBkYXRhLmF0dHJpYnV0ZXMpOwoKICAgICAgaWYgKHRoaXMuX19hdHRyaWJ1dGVzKSB7CiAgICAgICAgLy8gb25seSBkbyBpZiB3ZSBoYXZlIGF0dHJpYnV0ZSBjaGFuZ2VzCiAgICAgICAgdGhpcy5fdXBkYXRlQ2hhbmdlZEF0dHJpYnV0ZXMoKTsKICAgICAgfQoKICAgICAgaWYgKGRhdGEucmVsYXRpb25zaGlwcykgewogICAgICAgIHRoaXMuX3NldHVwUmVsYXRpb25zaGlwcyhkYXRhKTsKICAgICAgfQoKICAgICAgaWYgKGRhdGEuaWQpIHsKICAgICAgICB0aGlzLmlkID0gY29lcmNlSWQoZGF0YS5pZCk7CiAgICAgIH0KCiAgICAgIHJldHVybiBjaGFuZ2VkS2V5czsKICAgIH07CgogICAgX3Byb3RvLndpbGxDb21taXQgPSBmdW5jdGlvbiB3aWxsQ29tbWl0KCkgewogICAgICB0aGlzLl9pbkZsaWdodEF0dHJpYnV0ZXMgPSB0aGlzLl9hdHRyaWJ1dGVzOwogICAgICB0aGlzLl9hdHRyaWJ1dGVzID0gbnVsbDsKICAgIH07CgogICAgX3Byb3RvLmhhc0NoYW5nZWRBdHRyaWJ1dGVzID0gZnVuY3Rpb24gaGFzQ2hhbmdlZEF0dHJpYnV0ZXMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9fYXR0cmlidXRlcyAhPT0gbnVsbCAmJiBPYmplY3Qua2V5cyh0aGlzLl9fYXR0cmlidXRlcykubGVuZ3RoID4gMDsKICAgIH07CgogICAgX3Byb3RvLl9jbGVhckVycm9ycyA9IGZ1bmN0aW9uIF9jbGVhckVycm9ycygpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX0VSUk9SUykgewogICAgICAgIGlmICh0aGlzLl9lcnJvcnMpIHsKICAgICAgICAgIHRoaXMuX2Vycm9ycyA9IHVuZGVmaW5lZDsKICAgICAgICAgIHRoaXMuc3RvcmVXcmFwcGVyLm5vdGlmeUVycm9yc0NoYW5nZSh0aGlzLm1vZGVsTmFtZSwgdGhpcy5pZCwgdGhpcy5jbGllbnRJZCk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5nZXRFcnJvcnMgPSBmdW5jdGlvbiBnZXRFcnJvcnMoKSB7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfRVJST1JTKSB7CiAgICAgICAgdmFyIGVycm9ycyA9IHRoaXMuX2Vycm9ycyB8fCBbXTsKICAgICAgICByZXR1cm4gZXJyb3JzOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBbXTsKICAgICAgfQogICAgfSAvLyB0aGlzIGlzIGEgaGFjayBiYyB3ZSBkb24ndCBoYXZlIGFjY2VzcyB0byB0aGUgc3RhdGUgbWFjaGluZQogICAgLy8gICBhbmQgcmVsYXRpb25zaGlwcyBuZWVkIHRoaXMgaW5mbyBhbmQgQHJ1bnNwaXJlZCBkaWRuJ3Qgc2VlCiAgICAvLyAgIGhvdyB0byBnZXQgaXQganVzdCB5ZXQgZnJvbSBzdG9yZVdyYXBwZXIuCiAgICA7CgogICAgX3Byb3RvLmlzRW1wdHkgPSBmdW5jdGlvbiBpc0VtcHR5KCkgewogICAgICByZXR1cm4gdGhpcy5fX2F0dHJpYnV0ZXMgPT09IG51bGwgJiYgdGhpcy5fX2luRmxpZ2h0QXR0cmlidXRlcyA9PT0gbnVsbCAmJiB0aGlzLl9fZGF0YSA9PT0gbnVsbDsKICAgIH07CgogICAgX3Byb3RvLmRlbGV0ZVJlY29yZCA9IGZ1bmN0aW9uIGRlbGV0ZVJlY29yZCgpIHsKICAgICAgdGhpcy5faXNEZWxldGVkID0gdHJ1ZTsKICAgICAgdGhpcy5ub3RpZnlTdGF0ZUNoYW5nZSgpOwogICAgfTsKCiAgICBfcHJvdG8uaXNEZWxldGVkID0gZnVuY3Rpb24gaXNEZWxldGVkKCkgewogICAgICByZXR1cm4gdGhpcy5faXNEZWxldGVkOwogICAgfTsKCiAgICBfcHJvdG8uc2V0SXNEZWxldGVkID0gZnVuY3Rpb24gc2V0SXNEZWxldGVkKGlzRGVsZXRlZCkgewogICAgICB0aGlzLl9pc0RlbGV0ZWQgPSBpc0RlbGV0ZWQ7CgogICAgICBpZiAodGhpcy5faXNOZXcpIHsKICAgICAgICB0aGlzLl9kZWxldGlvbkNvbmZpcm1lZCgpOwogICAgICB9CgogICAgICB0aGlzLm5vdGlmeVN0YXRlQ2hhbmdlKCk7CiAgICB9OwoKICAgIF9wcm90by5pc0RlbGV0aW9uQ29tbWl0dGVkID0gZnVuY3Rpb24gaXNEZWxldGlvbkNvbW1pdHRlZCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2lzRGVsZXRpb25Db21taXRlZDsKICAgIH07CgogICAgX3Byb3RvLnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoKSB7CiAgICAgIHRoaXMuX19hdHRyaWJ1dGVzID0gbnVsbDsKICAgICAgdGhpcy5fX2luRmxpZ2h0QXR0cmlidXRlcyA9IG51bGw7CiAgICAgIHRoaXMuX19kYXRhID0gbnVsbDsKICAgICAgdGhpcy5fZXJyb3JzID0gdW5kZWZpbmVkOwogICAgfTsKCiAgICBfcHJvdG8uX3NldHVwUmVsYXRpb25zaGlwcyA9IGZ1bmN0aW9uIF9zZXR1cFJlbGF0aW9uc2hpcHMoZGF0YSkgewogICAgICB2YXIgcmVsYXRpb25zaGlwcyA9IHRoaXMuc3RvcmVXcmFwcGVyLnJlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKHRoaXMubW9kZWxOYW1lKTsKICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhyZWxhdGlvbnNoaXBzKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciByZWxhdGlvbnNoaXBOYW1lID0ga2V5c1tpXTsKCiAgICAgICAgaWYgKCFkYXRhLnJlbGF0aW9uc2hpcHNbcmVsYXRpb25zaGlwTmFtZV0pIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0gLy8gaW4gZGVidWcsIGFzc2VydCBwYXlsb2FkIHZhbGlkaXR5IGVhZ2VybHkKCgogICAgICAgIHZhciByZWxhdGlvbnNoaXBEYXRhID0gZGF0YS5yZWxhdGlvbnNoaXBzW3JlbGF0aW9uc2hpcE5hbWVdOwoKICAgICAgICB2YXIgcmVsYXRpb25zaGlwID0gdGhpcy5fcmVsYXRpb25zaGlwcy5nZXQocmVsYXRpb25zaGlwTmFtZSk7CgogICAgICAgIHJlbGF0aW9uc2hpcC5wdXNoKHJlbGF0aW9uc2hpcERhdGEpOwogICAgICB9CiAgICB9CiAgICAvKgogICAgICBDaGVja3MgaWYgdGhlIGF0dHJpYnV0ZXMgd2hpY2ggYXJlIGNvbnNpZGVyZWQgYXMgY2hhbmdlZCBhcmUgc3RpbGwKICAgICAgZGlmZmVyZW50IHRvIHRoZSBzdGF0ZSB3aGljaCBpcyBhY2tub3dsZWRnZWQgYnkgdGhlIHNlcnZlci4KICAgICAgIFRoaXMgbWV0aG9kIGlzIG5lZWRlZCB3aGVuIGRhdGEgZm9yIHRoZSBpbnRlcm5hbCBtb2RlbCBpcyBwdXNoZWQgYW5kIHRoZQogICAgICBwdXNoZWQgZGF0YSBtaWdodCBhY2tub3dsZWRnZSBkaXJ0eSBhdHRyaWJ1dGVzIGFzIGNvbmZpcm1lZC4KICAgICAgIEBtZXRob2QgdXBkYXRlQ2hhbmdlZEF0dHJpYnV0ZXMKICAgICAgQHByaXZhdGUKICAgICAqLwogICAgOwoKICAgIF9wcm90by5fdXBkYXRlQ2hhbmdlZEF0dHJpYnV0ZXMgPSBmdW5jdGlvbiBfdXBkYXRlQ2hhbmdlZEF0dHJpYnV0ZXMoKSB7CiAgICAgIHZhciBjaGFuZ2VkQXR0cmlidXRlcyA9IHRoaXMuY2hhbmdlZEF0dHJpYnV0ZXMoKTsKICAgICAgdmFyIGNoYW5nZWRBdHRyaWJ1dGVOYW1lcyA9IE9iamVjdC5rZXlzKGNoYW5nZWRBdHRyaWJ1dGVzKTsKICAgICAgdmFyIGF0dHJzID0gdGhpcy5fYXR0cmlidXRlczsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBjaGFuZ2VkQXR0cmlidXRlTmFtZXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgYXR0cmlidXRlID0gY2hhbmdlZEF0dHJpYnV0ZU5hbWVzW2ldOwogICAgICAgIHZhciBkYXRhID0gY2hhbmdlZEF0dHJpYnV0ZXNbYXR0cmlidXRlXTsKICAgICAgICB2YXIgb2xkRGF0YSA9IGRhdGFbMF07CiAgICAgICAgdmFyIG5ld0RhdGEgPSBkYXRhWzFdOwoKICAgICAgICBpZiAob2xkRGF0YSA9PT0gbmV3RGF0YSkgewogICAgICAgICAgZGVsZXRlIGF0dHJzW2F0dHJpYnV0ZV07CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKgogICAgICBSZXR1cm5zIGFuIG9iamVjdCwgd2hvc2Uga2V5cyBhcmUgY2hhbmdlZCBwcm9wZXJ0aWVzLCBhbmQgdmFsdWUgaXMgYW4KICAgICAgW29sZFByb3AsIG5ld1Byb3BdIGFycmF5LgogICAgICAgQG1ldGhvZCBjaGFuZ2VkQXR0cmlidXRlcwogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uY2hhbmdlZEF0dHJpYnV0ZXMgPSBmdW5jdGlvbiBjaGFuZ2VkQXR0cmlidXRlcygpIHsKICAgICAgdmFyIG9sZERhdGEgPSB0aGlzLl9kYXRhOwogICAgICB2YXIgY3VycmVudERhdGEgPSB0aGlzLl9hdHRyaWJ1dGVzOwogICAgICB2YXIgaW5GbGlnaHREYXRhID0gdGhpcy5faW5GbGlnaHRBdHRyaWJ1dGVzOwogICAgICB2YXIgbmV3RGF0YSA9IEVtYmVyLmFzc2lnbih7fSwgaW5GbGlnaHREYXRhLCBjdXJyZW50RGF0YSk7CiAgICAgIHZhciBkaWZmRGF0YSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHZhciBuZXdEYXRhS2V5cyA9IE9iamVjdC5rZXlzKG5ld0RhdGEpOwoKICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IG5ld0RhdGFLZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIF9rZXkgPSBuZXdEYXRhS2V5c1tpXTsKICAgICAgICBkaWZmRGF0YVtfa2V5XSA9IFtvbGREYXRhW19rZXldLCBuZXdEYXRhW19rZXldXTsKICAgICAgfQoKICAgICAgcmV0dXJuIGRpZmZEYXRhOwogICAgfTsKCiAgICBfcHJvdG8uaXNOZXcgPSBmdW5jdGlvbiBpc05ldygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2lzTmV3OwogICAgfTsKCiAgICBfcHJvdG8ucm9sbGJhY2tBdHRyaWJ1dGVzID0gZnVuY3Rpb24gcm9sbGJhY2tBdHRyaWJ1dGVzKCkgewogICAgICB2YXIgZGlydHlLZXlzOwogICAgICB0aGlzLl9pc0RlbGV0ZWQgPSBmYWxzZTsKCiAgICAgIGlmICh0aGlzLmhhc0NoYW5nZWRBdHRyaWJ1dGVzKCkpIHsKICAgICAgICBkaXJ0eUtleXMgPSBPYmplY3Qua2V5cyh0aGlzLl9hdHRyaWJ1dGVzKTsKICAgICAgICB0aGlzLl9hdHRyaWJ1dGVzID0gbnVsbDsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuaXNOZXcoKSkgewogICAgICAgIHRoaXMucmVtb3ZlRnJvbUludmVyc2VSZWxhdGlvbnNoaXBzKHRydWUpOwogICAgICAgIHRoaXMuX2lzRGVsZXRlZCA9IHRydWU7CiAgICAgICAgdGhpcy5faXNOZXcgPSBmYWxzZTsKICAgICAgfQoKICAgICAgdGhpcy5faW5GbGlnaHRBdHRyaWJ1dGVzID0gbnVsbDsKCiAgICAgIHRoaXMuX2NsZWFyRXJyb3JzKCk7CgogICAgICB0aGlzLm5vdGlmeVN0YXRlQ2hhbmdlKCk7CiAgICAgIHJldHVybiBkaXJ0eUtleXM7CiAgICB9OwoKICAgIF9wcm90by5fZGVsZXRpb25Db25maXJtZWQgPSBmdW5jdGlvbiBfZGVsZXRpb25Db25maXJtZWQoKSB7CiAgICAgIHRoaXMucmVtb3ZlRnJvbUludmVyc2VSZWxhdGlvbnNoaXBzKCk7CiAgICB9OwoKICAgIF9wcm90by5kaWRDb21taXQgPSBmdW5jdGlvbiBkaWRDb21taXQoZGF0YSkgewogICAgICBpZiAodGhpcy5faXNEZWxldGVkKSB7CiAgICAgICAgdGhpcy5fZGVsZXRpb25Db25maXJtZWQoKTsKCiAgICAgICAgdGhpcy5faXNEZWxldGlvbkNvbW1pdGVkID0gdHJ1ZTsKICAgICAgfQoKICAgICAgdGhpcy5faXNOZXcgPSBmYWxzZTsKICAgICAgdmFyIG5ld0Nhbm9uaWNhbEF0dHJpYnV0ZXMgPSBudWxsOwoKICAgICAgaWYgKGRhdGEpIHsKICAgICAgICAvLyB0aGlzLnN0b3JlLl9pbnRlcm5hbE1vZGVsRGlkUmVjZWl2ZVJlbGF0aW9uc2hpcERhdGEodGhpcy5tb2RlbE5hbWUsIHRoaXMuaWQsIGRhdGEucmVsYXRpb25zaGlwcyk7CiAgICAgICAgaWYgKGRhdGEucmVsYXRpb25zaGlwcykgewogICAgICAgICAgdGhpcy5fc2V0dXBSZWxhdGlvbnNoaXBzKGRhdGEpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGRhdGEuaWQpIHsKICAgICAgICAgIC8vIGRpZENvbW1pdCBwcm92aWRlZCBhbiBJRCwgbm90aWZ5IHRoZSBzdG9yZSBvZiBpdAogICAgICAgICAgdGhpcy5zdG9yZVdyYXBwZXIuc2V0UmVjb3JkSWQodGhpcy5tb2RlbE5hbWUsIGRhdGEuaWQsIHRoaXMuY2xpZW50SWQpOwogICAgICAgICAgdGhpcy5pZCA9IGNvZXJjZUlkKGRhdGEuaWQpOwogICAgICAgIH0KCiAgICAgICAgbmV3Q2Fub25pY2FsQXR0cmlidXRlcyA9IGRhdGEuYXR0cmlidXRlcyB8fCBudWxsOwogICAgICB9CgogICAgICB2YXIgY2hhbmdlZEtleXMgPSB0aGlzLl9jaGFuZ2VkS2V5cyhuZXdDYW5vbmljYWxBdHRyaWJ1dGVzKTsKCiAgICAgIEVtYmVyLmFzc2lnbih0aGlzLl9kYXRhLCB0aGlzLl9faW5GbGlnaHRBdHRyaWJ1dGVzLCBuZXdDYW5vbmljYWxBdHRyaWJ1dGVzKTsKICAgICAgdGhpcy5faW5GbGlnaHRBdHRyaWJ1dGVzID0gbnVsbDsKCiAgICAgIHRoaXMuX3VwZGF0ZUNoYW5nZWRBdHRyaWJ1dGVzKCk7CgogICAgICB0aGlzLl9jbGVhckVycm9ycygpOwoKICAgICAgdGhpcy5ub3RpZnlTdGF0ZUNoYW5nZSgpOwogICAgICByZXR1cm4gY2hhbmdlZEtleXM7CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlTdGF0ZUNoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeVN0YXRlQ2hhbmdlKCkgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfU1RBVEUpIHsKICAgICAgICB0aGlzLnN0b3JlV3JhcHBlci5ub3RpZnlTdGF0ZUNoYW5nZSh0aGlzLm1vZGVsTmFtZSwgdGhpcy5pZCwgdGhpcy5jbGllbnRJZCk7CiAgICAgIH0KICAgIH0gLy8gZ2V0IFJlc291cmNlSWRlbnRpZmllcnMgZm9yICJjdXJyZW50IHN0YXRlIgogICAgOwoKICAgIF9wcm90by5nZXRIYXNNYW55ID0gZnVuY3Rpb24gZ2V0SGFzTWFueShrZXkpIHsKICAgICAgcmV0dXJuIHRoaXMuX3JlbGF0aW9uc2hpcHMuZ2V0KGtleSkuZ2V0RGF0YSgpOwogICAgfSAvLyBzZXQgYSBuZXcgImN1cnJlbnQgc3RhdGUiIHZpYSBSZXNvdXJjZUlkZW50aWZpZXJzCiAgICA7CgogICAgX3Byb3RvLnNldERpcnR5SGFzTWFueSA9IGZ1bmN0aW9uIHNldERpcnR5SGFzTWFueShrZXksIHJlY29yZERhdGFzKSB7CiAgICAgIHZhciByZWxhdGlvbnNoaXAgPSB0aGlzLl9yZWxhdGlvbnNoaXBzLmdldChrZXkpOwoKICAgICAgcmVsYXRpb25zaGlwLmNsZWFyKCk7CiAgICAgIHJlbGF0aW9uc2hpcC5hZGRSZWNvcmREYXRhcyhyZWNvcmREYXRhcyk7CiAgICB9IC8vIGFwcGVuZCB0byAiY3VycmVudCBzdGF0ZSIgdmlhIFJlY29yZERhdGFzCiAgICA7CgogICAgX3Byb3RvLmFkZFRvSGFzTWFueSA9IGZ1bmN0aW9uIGFkZFRvSGFzTWFueShrZXksIHJlY29yZERhdGFzLCBpZHgpIHsKICAgICAgdGhpcy5fcmVsYXRpb25zaGlwcy5nZXQoa2V5KS5hZGRSZWNvcmREYXRhcyhyZWNvcmREYXRhcywgaWR4KTsKICAgIH0gLy8gcmVtb3ZlIGZyb20gImN1cnJlbnQgc3RhdGUiIHZpYSBSZWNvcmREYXRhcwogICAgOwoKICAgIF9wcm90by5yZW1vdmVGcm9tSGFzTWFueSA9IGZ1bmN0aW9uIHJlbW92ZUZyb21IYXNNYW55KGtleSwgcmVjb3JkRGF0YXMpIHsKICAgICAgdGhpcy5fcmVsYXRpb25zaGlwcy5nZXQoa2V5KS5yZW1vdmVSZWNvcmREYXRhcyhyZWNvcmREYXRhcyk7CiAgICB9OwoKICAgIF9wcm90by5jb21taXRXYXNSZWplY3RlZCA9IGZ1bmN0aW9uIGNvbW1pdFdhc1JlamVjdGVkKGlkZW50aWZpZXIsIGVycm9ycykgewogICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuX2luRmxpZ2h0QXR0cmlidXRlcyk7CgogICAgICBpZiAoa2V5cy5sZW5ndGggPiAwKSB7CiAgICAgICAgdmFyIGF0dHJzID0gdGhpcy5fYXR0cmlidXRlczsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBpZiAoYXR0cnNba2V5c1tpXV0gPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBhdHRyc1trZXlzW2ldXSA9IHRoaXMuX2luRmxpZ2h0QXR0cmlidXRlc1trZXlzW2ldXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHRoaXMuX2luRmxpZ2h0QXR0cmlidXRlcyA9IG51bGw7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfRVJST1JTKSB7CiAgICAgICAgaWYgKGVycm9ycykgewogICAgICAgICAgdGhpcy5fZXJyb3JzID0gZXJyb3JzOwogICAgICAgIH0KCiAgICAgICAgdGhpcy5zdG9yZVdyYXBwZXIubm90aWZ5RXJyb3JzQ2hhbmdlKHRoaXMubW9kZWxOYW1lLCB0aGlzLmlkLCB0aGlzLmNsaWVudElkKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uZ2V0QmVsb25nc1RvID0gZnVuY3Rpb24gZ2V0QmVsb25nc1RvKGtleSkgewogICAgICByZXR1cm4gdGhpcy5fcmVsYXRpb25zaGlwcy5nZXQoa2V5KS5nZXREYXRhKCk7CiAgICB9OwoKICAgIF9wcm90by5zZXREaXJ0eUJlbG9uZ3NUbyA9IGZ1bmN0aW9uIHNldERpcnR5QmVsb25nc1RvKGtleSwgcmVjb3JkRGF0YSkgewogICAgICB0aGlzLl9yZWxhdGlvbnNoaXBzLmdldChrZXkpLnNldFJlY29yZERhdGEocmVjb3JkRGF0YSk7CiAgICB9OwoKICAgIF9wcm90by5zZXREaXJ0eUF0dHJpYnV0ZSA9IGZ1bmN0aW9uIHNldERpcnR5QXR0cmlidXRlKGtleSwgdmFsdWUpIHsKICAgICAgdmFyIG9yaWdpbmFsVmFsdWU7IC8vIEFkZCB0aGUgbmV3IHZhbHVlIHRvIHRoZSBjaGFuZ2VkIGF0dHJpYnV0ZXMgaGFzaAoKICAgICAgdGhpcy5fYXR0cmlidXRlc1trZXldID0gdmFsdWU7CgogICAgICBpZiAoa2V5IGluIHRoaXMuX2luRmxpZ2h0QXR0cmlidXRlcykgewogICAgICAgIG9yaWdpbmFsVmFsdWUgPSB0aGlzLl9pbkZsaWdodEF0dHJpYnV0ZXNba2V5XTsKICAgICAgfSBlbHNlIHsKICAgICAgICBvcmlnaW5hbFZhbHVlID0gdGhpcy5fZGF0YVtrZXldOwogICAgICB9IC8vIElmIHdlIHdlbnQgYmFjayB0byBvdXIgb3JpZ2luYWwgdmFsdWUsIHdlIHNob3VsZG4ndCBrZWVwIHRoZSBhdHRyaWJ1dGUgYXJvdW5kIGFueW1vcmUKCgogICAgICBpZiAodmFsdWUgPT09IG9yaWdpbmFsVmFsdWUpIHsKICAgICAgICBkZWxldGUgdGhpcy5fYXR0cmlidXRlc1trZXldOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5nZXRBdHRyID0gZnVuY3Rpb24gZ2V0QXR0cihrZXkpIHsKICAgICAgaWYgKGtleSBpbiB0aGlzLl9hdHRyaWJ1dGVzKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2F0dHJpYnV0ZXNba2V5XTsKICAgICAgfSBlbHNlIGlmIChrZXkgaW4gdGhpcy5faW5GbGlnaHRBdHRyaWJ1dGVzKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2luRmxpZ2h0QXR0cmlidXRlc1trZXldOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0aGlzLl9kYXRhW2tleV07CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmhhc0F0dHIgPSBmdW5jdGlvbiBoYXNBdHRyKGtleSkgewogICAgICByZXR1cm4ga2V5IGluIHRoaXMuX2F0dHJpYnV0ZXMgfHwga2V5IGluIHRoaXMuX2luRmxpZ2h0QXR0cmlidXRlcyB8fCBrZXkgaW4gdGhpcy5fZGF0YTsKICAgIH07CgogICAgX3Byb3RvLnVubG9hZFJlY29yZCA9IGZ1bmN0aW9uIHVubG9hZFJlY29yZCgpIHsKICAgICAgaWYgKHRoaXMuaXNEZXN0cm95ZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuX2Rlc3Ryb3lSZWxhdGlvbnNoaXBzKCk7CgogICAgICB0aGlzLnJlc2V0KCk7CgogICAgICBpZiAoIXRoaXMuX3NjaGVkdWxlZERlc3Ryb3kpIHsKICAgICAgICB0aGlzLl9zY2hlZHVsZWREZXN0cm95ID0gRW1iZXIucnVuLmJhY2tidXJuZXIuc2NoZWR1bGUoJ2Rlc3Ryb3knLCB0aGlzLCAnX2NsZWFudXBPcnBoYW5lZFJlY29yZERhdGFzJyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9jbGVhbnVwT3JwaGFuZWRSZWNvcmREYXRhcyA9IGZ1bmN0aW9uIF9jbGVhbnVwT3JwaGFuZWRSZWNvcmREYXRhcygpIHsKICAgICAgdmFyIHJlbGF0ZWRSZWNvcmREYXRhcyA9IHRoaXMuX2FsbFJlbGF0ZWRSZWNvcmREYXRhcygpOwoKICAgICAgaWYgKGFyZUFsbE1vZGVsc1VubG9hZGVkKHJlbGF0ZWRSZWNvcmREYXRhcykpIHsKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbGF0ZWRSZWNvcmREYXRhcy5sZW5ndGg7ICsraSkgewogICAgICAgICAgdmFyIHJlY29yZERhdGEgPSByZWxhdGVkUmVjb3JkRGF0YXNbaV07CgogICAgICAgICAgaWYgKCFyZWNvcmREYXRhLmlzRGVzdHJveWVkKSB7CiAgICAgICAgICAgIHJlY29yZERhdGEuZGVzdHJveSgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgdGhpcy5fc2NoZWR1bGVkRGVzdHJveSA9IG51bGw7CiAgICB9OwoKICAgIF9wcm90by5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdGhpcy5fcmVsYXRpb25zaGlwcy5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lLCByZWwpIHsKICAgICAgICByZXR1cm4gcmVsLmRlc3Ryb3koKTsKICAgICAgfSk7CgogICAgICB0aGlzLmlzRGVzdHJveWVkID0gdHJ1ZTsKICAgICAgdGhpcy5zdG9yZVdyYXBwZXIuZGlzY29ubmVjdFJlY29yZCh0aGlzLm1vZGVsTmFtZSwgdGhpcy5pZCwgdGhpcy5jbGllbnRJZCk7CiAgICB9OwoKICAgIF9wcm90by5pc1JlY29yZEluVXNlID0gZnVuY3Rpb24gaXNSZWNvcmRJblVzZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RvcmVXcmFwcGVyLmlzUmVjb3JkSW5Vc2UodGhpcy5tb2RlbE5hbWUsIHRoaXMuaWQsIHRoaXMuY2xpZW50SWQpOwogICAgfQogICAgLyoqCiAgICAgIENvbXB1dGVzIHRoZSBzZXQgb2YgaW50ZXJuYWwgbW9kZWxzIHJlYWNoYWJsZSBmcm9tIGB0aGlzYCBhY3Jvc3MgZXhhY3RseSBvbmUKICAgICAgcmVsYXRpb25zaGlwLgogICAgICAgQHJldHVybiB7QXJyYXl9IEFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIGludGVybmFsIG1vZGVscyB0aGF0IGB0aGlzYCBiZWxvbmdzCiAgICAgIHRvIG9yIGhhcyBtYW55LgogICAgICovCiAgICA7CgogICAgX3Byb3RvLl9kaXJlY3RseVJlbGF0ZWRSZWNvcmREYXRhcyA9IGZ1bmN0aW9uIF9kaXJlY3RseVJlbGF0ZWRSZWNvcmREYXRhcygpIHsKICAgICAgdmFyIGFycmF5ID0gW107CgogICAgICB0aGlzLl9yZWxhdGlvbnNoaXBzLmZvckVhY2goZnVuY3Rpb24gKG5hbWUsIHJlbCkgewogICAgICAgIHZhciBtZW1iZXJzID0gcmVsLm1lbWJlcnMubGlzdDsKICAgICAgICB2YXIgY2Fub25pY2FsTWVtYmVycyA9IHJlbC5jYW5vbmljYWxNZW1iZXJzLmxpc3Q7CiAgICAgICAgYXJyYXkgPSBhcnJheS5jb25jYXQobWVtYmVycywgY2Fub25pY2FsTWVtYmVycyk7CiAgICAgIH0pOwoKICAgICAgcmV0dXJuIGFycmF5OwogICAgfQogICAgLyoqCiAgICAgIENvbXB1dGVzIHRoZSBzZXQgb2YgaW50ZXJuYWwgbW9kZWxzIHJlYWNoYWJsZSBmcm9tIHRoaXMgaW50ZXJuYWwgbW9kZWwuCiAgICAgICBSZWFjaGFiaWxpdHkgaXMgZGV0ZXJtaW5lZCBvdmVyIHRoZSByZWxhdGlvbnNoaXAgZ3JhcGggKGllIGEgZ3JhcGggd2hlcmUKICAgICAgbm9kZXMgYXJlIGludGVybmFsIG1vZGVscyBhbmQgZWRnZXMgYXJlIGJlbG9uZ3MgdG8gb3IgaGFzIG1hbnkKICAgICAgcmVsYXRpb25zaGlwcykuCiAgICAgICBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgaW5jbHVkaW5nIGB0aGlzYCBhbmQgYWxsIGludGVybmFsIG1vZGVscyByZWFjaGFibGUKICAgICAgZnJvbSBgdGhpc2AuCiAgICAqLwogICAgOwoKICAgIF9wcm90by5fYWxsUmVsYXRlZFJlY29yZERhdGFzID0gZnVuY3Rpb24gX2FsbFJlbGF0ZWRSZWNvcmREYXRhcygpIHsKICAgICAgdmFyIGFycmF5ID0gW107CiAgICAgIHZhciBxdWV1ZSA9IFtdOwogICAgICB2YXIgYmZzSWQgPSBuZXh0QmZzSWQrKzsKICAgICAgcXVldWUucHVzaCh0aGlzKTsKICAgICAgdGhpcy5fYmZzSWQgPSBiZnNJZDsKCiAgICAgIHdoaWxlIChxdWV1ZS5sZW5ndGggPiAwKSB7CiAgICAgICAgdmFyIG5vZGUgPSBxdWV1ZS5zaGlmdCgpOwogICAgICAgIGFycmF5LnB1c2gobm9kZSk7CgogICAgICAgIHZhciByZWxhdGVkID0gbm9kZS5fZGlyZWN0bHlSZWxhdGVkUmVjb3JkRGF0YXMoKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZWxhdGVkLmxlbmd0aDsgKytpKSB7CiAgICAgICAgICB2YXIgcmVjb3JkRGF0YSA9IHJlbGF0ZWRbaV07CgogICAgICAgICAgaWYgKHJlY29yZERhdGEgaW5zdGFuY2VvZiBSZWNvcmREYXRhRGVmYXVsdCkgewoKICAgICAgICAgICAgaWYgKHJlY29yZERhdGEuX2Jmc0lkIDwgYmZzSWQpIHsKICAgICAgICAgICAgICBxdWV1ZS5wdXNoKHJlY29yZERhdGEpOwogICAgICAgICAgICAgIHJlY29yZERhdGEuX2Jmc0lkID0gYmZzSWQ7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBhcnJheTsKICAgIH07CgogICAgX3Byb3RvLmlzQXR0ckRpcnR5ID0gZnVuY3Rpb24gaXNBdHRyRGlydHkoa2V5KSB7CiAgICAgIGlmICh0aGlzLl9hdHRyaWJ1dGVzW2tleV0gPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgdmFyIG9yaWdpbmFsVmFsdWU7CgogICAgICBpZiAodGhpcy5faW5GbGlnaHRBdHRyaWJ1dGVzW2tleV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgIG9yaWdpbmFsVmFsdWUgPSB0aGlzLl9pbkZsaWdodEF0dHJpYnV0ZXNba2V5XTsKICAgICAgfSBlbHNlIHsKICAgICAgICBvcmlnaW5hbFZhbHVlID0gdGhpcy5fZGF0YVtrZXldOwogICAgICB9CgogICAgICByZXR1cm4gb3JpZ2luYWxWYWx1ZSAhPT0gdGhpcy5fYXR0cmlidXRlc1trZXldOwogICAgfTsKCiAgICAvKioKICAgICAqIFJlY2VpdmVzIG9wdGlvbnMgcGFzc2VkIHRvIGBzdG9yZS5jcmVhdGVSZWNvcmRgIGFuZCBpcyBnaXZlbiB0aGUgb3Bwb3J0dW5pdHkKICAgICAqIHRvIGhhbmRsZSB0aGVtLgogICAgICoKICAgICAqIFRoZSByZXR1cm4gdmFsdWUgaXMgYW4gb2JqZWN0IG9mIG9wdGlvbnMgdG8gcGFzcyB0byBgUmVjb3JkLmNyZWF0ZSgpYAogICAgICoKICAgICAqIEBwYXJhbSBvcHRpb25zCiAgICAgKiBAcHJpdmF0ZQogICAgICovCiAgICBfcHJvdG8uX2luaXRSZWNvcmRDcmVhdGVPcHRpb25zID0gZnVuY3Rpb24gX2luaXRSZWNvcmRDcmVhdGVPcHRpb25zKG9wdGlvbnMpIHsKICAgICAgdmFyIGNyZWF0ZU9wdGlvbnMgPSB7fTsKCiAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB2YXIgX21vZGVsTmFtZTIgPSB0aGlzLm1vZGVsTmFtZSwKICAgICAgICAgICAgX3N0b3JlV3JhcHBlcjQgPSB0aGlzLnN0b3JlV3JhcHBlcjsKCiAgICAgICAgdmFyIGF0dHJpYnV0ZURlZnMgPSBfc3RvcmVXcmFwcGVyNC5hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvcihfbW9kZWxOYW1lMik7CgogICAgICAgIHZhciByZWxhdGlvbnNoaXBEZWZzID0gX3N0b3JlV3JhcHBlcjQucmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IoX21vZGVsTmFtZTIpOwoKICAgICAgICB2YXIgcmVsYXRpb25zaGlwcyA9IHRoaXMuX3JlbGF0aW9uc2hpcHM7CiAgICAgICAgdmFyIHByb3BlcnR5TmFtZXMgPSBPYmplY3Qua2V5cyhvcHRpb25zKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wZXJ0eU5hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICB2YXIgbmFtZSA9IHByb3BlcnR5TmFtZXNbaV07CiAgICAgICAgICB2YXIgcHJvcGVydHlWYWx1ZSA9IG9wdGlvbnNbbmFtZV07CgogICAgICAgICAgaWYgKG5hbWUgPT09ICdpZCcpIHsKICAgICAgICAgICAgdGhpcy5pZCA9IHByb3BlcnR5VmFsdWU7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQoKICAgICAgICAgIHZhciBmaWVsZFR5cGUgPSByZWxhdGlvbnNoaXBEZWZzW25hbWVdIHx8IGF0dHJpYnV0ZURlZnNbbmFtZV07CiAgICAgICAgICB2YXIga2luZCA9IGZpZWxkVHlwZSAhPT0gdW5kZWZpbmVkID8gZmllbGRUeXBlLmtpbmQgOiBudWxsOwogICAgICAgICAgdmFyIHJlbGF0aW9uc2hpcCA9IHZvaWQgMDsKCiAgICAgICAgICBzd2l0Y2ggKGtpbmQpIHsKICAgICAgICAgICAgY2FzZSAnYXR0cmlidXRlJzoKICAgICAgICAgICAgICB0aGlzLnNldERpcnR5QXR0cmlidXRlKG5hbWUsIHByb3BlcnR5VmFsdWUpOwogICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgY2FzZSAnYmVsb25nc1RvJzoKICAgICAgICAgICAgICB0aGlzLnNldERpcnR5QmVsb25nc1RvKG5hbWUsIHByb3BlcnR5VmFsdWUpOwogICAgICAgICAgICAgIHJlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcHMuZ2V0KG5hbWUpOwogICAgICAgICAgICAgIHJlbGF0aW9uc2hpcC5zZXRIYXNBbnlSZWxhdGlvbnNoaXBEYXRhKHRydWUpOwogICAgICAgICAgICAgIHJlbGF0aW9uc2hpcC5zZXRSZWxhdGlvbnNoaXBJc0VtcHR5KGZhbHNlKTsKICAgICAgICAgICAgICBicmVhazsKCiAgICAgICAgICAgIGNhc2UgJ2hhc01hbnknOgogICAgICAgICAgICAgIHRoaXMuc2V0RGlydHlIYXNNYW55KG5hbWUsIHByb3BlcnR5VmFsdWUpOwogICAgICAgICAgICAgIHJlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcHMuZ2V0KG5hbWUpOwogICAgICAgICAgICAgIHJlbGF0aW9uc2hpcC5zZXRIYXNBbnlSZWxhdGlvbnNoaXBEYXRhKHRydWUpOwogICAgICAgICAgICAgIHJlbGF0aW9uc2hpcC5zZXRSZWxhdGlvbnNoaXBJc0VtcHR5KGZhbHNlKTsKICAgICAgICAgICAgICBicmVhazsKCiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgLy8gcmVmbGVjdCBiYWNrIChwYXNzLXRocnUpIHVua25vd24gcHJvcGVydGllcwogICAgICAgICAgICAgIGNyZWF0ZU9wdGlvbnNbbmFtZV0gPSBwcm9wZXJ0eVZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGNyZWF0ZU9wdGlvbnM7CiAgICB9CiAgICAvKgogICAgICAgIFRPRE8gSUdPUiBBTkQgREFWSUQgdGhpcyBzaG91bGRuJ3QgYmUgcHVibGljCiAgICAgVGhpcyBtZXRob2Qgc2hvdWxkIG9ubHkgYmUgY2FsbGVkIGJ5IHJlY29yZHMgaW4gdGhlIGBpc05ldygpYCBzdGF0ZSBPUiBvbmNlIHRoZSByZWNvcmQKICAgICBoYXMgYmVlbiBkZWxldGVkIGFuZCB0aGF0IGRlbGV0aW9uIGhhcyBiZWVuIHBlcnNpc3RlZC4KICAgICAgSXQgd2lsbCByZW1vdmUgdGhpcyByZWNvcmQgZnJvbSBhbnkgYXNzb2NpYXRlZCByZWxhdGlvbnNoaXBzLgogICAgICBJZiBgaXNOZXdgIGlzIHRydWUgKGRlZmF1bHQgZmFsc2UpLCBpdCB3aWxsIGFsc28gY29tcGxldGVseSByZXNldCBhbGwKICAgICAgcmVsYXRpb25zaGlwcyB0byBhbiBlbXB0eSBzdGF0ZSBhcyB3ZWxsLgogICAgICAgQG1ldGhvZCByZW1vdmVGcm9tSW52ZXJzZVJlbGF0aW9uc2hpcHMKICAgICAgQHBhcmFtIHtCb29sZWFufSBpc05ldyB3aGV0aGVyIHRvIHVubG9hZCBmcm9tIHRoZSBgaXNOZXdgIHBlcnNwZWN0aXZlCiAgICAgIEBwcml2YXRlCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVtb3ZlRnJvbUludmVyc2VSZWxhdGlvbnNoaXBzID0gZnVuY3Rpb24gcmVtb3ZlRnJvbUludmVyc2VSZWxhdGlvbnNoaXBzKGlzTmV3KSB7CiAgICAgIGlmIChpc05ldyA9PT0gdm9pZCAwKSB7CiAgICAgICAgaXNOZXcgPSBmYWxzZTsKICAgICAgfQoKICAgICAgdGhpcy5fcmVsYXRpb25zaGlwcy5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lLCByZWwpIHsKICAgICAgICByZWwucmVtb3ZlQ29tcGxldGVseUZyb21JbnZlcnNlKCk7CgogICAgICAgIGlmIChpc05ldyA9PT0gdHJ1ZSkgewogICAgICAgICAgcmVsLmNsZWFyKCk7CiAgICAgICAgfQogICAgICB9KTsKCiAgICAgIHZhciBpbXBsaWNpdFJlbGF0aW9uc2hpcHMgPSB0aGlzLl9pbXBsaWNpdFJlbGF0aW9uc2hpcHM7CiAgICAgIHRoaXMuX19pbXBsaWNpdFJlbGF0aW9uc2hpcHMgPSBudWxsOwogICAgICBPYmplY3Qua2V5cyhpbXBsaWNpdFJlbGF0aW9uc2hpcHMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgIHZhciByZWwgPSBpbXBsaWNpdFJlbGF0aW9uc2hpcHNba2V5XTsKICAgICAgICByZWwucmVtb3ZlQ29tcGxldGVseUZyb21JbnZlcnNlKCk7CgogICAgICAgIGlmIChpc05ldyA9PT0gdHJ1ZSkgewogICAgICAgICAgcmVsLmNsZWFyKCk7CiAgICAgICAgfQogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvLl9kZXN0cm95UmVsYXRpb25zaGlwcyA9IGZ1bmN0aW9uIF9kZXN0cm95UmVsYXRpb25zaGlwcygpIHsKICAgICAgdmFyIHJlbGF0aW9uc2hpcHMgPSB0aGlzLl9yZWxhdGlvbnNoaXBzOwogICAgICByZWxhdGlvbnNoaXBzLmZvckVhY2goZnVuY3Rpb24gKG5hbWUsIHJlbCkgewogICAgICAgIHJldHVybiBkZXN0cm95UmVsYXRpb25zaGlwKHJlbCk7CiAgICAgIH0pOwogICAgICB2YXIgaW1wbGljaXRSZWxhdGlvbnNoaXBzID0gdGhpcy5faW1wbGljaXRSZWxhdGlvbnNoaXBzOwogICAgICB0aGlzLl9faW1wbGljaXRSZWxhdGlvbnNoaXBzID0gbnVsbDsKICAgICAgT2JqZWN0LmtleXMoaW1wbGljaXRSZWxhdGlvbnNoaXBzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICB2YXIgcmVsID0gaW1wbGljaXRSZWxhdGlvbnNoaXBzW2tleV07CiAgICAgICAgZGVzdHJveVJlbGF0aW9uc2hpcChyZWwpOwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvLmNsaWVudERpZENyZWF0ZSA9IGZ1bmN0aW9uIGNsaWVudERpZENyZWF0ZSgpIHsKICAgICAgdGhpcy5faXNOZXcgPSB0cnVlOwogICAgfQogICAgLyoKICAgICAgRW1iZXIgRGF0YSBoYXMgMyBidWNrZXRzIGZvciBzdG9yaW5nIHRoZSB2YWx1ZSBvZiBhbiBhdHRyaWJ1dGUgb24gYW4gaW50ZXJuYWxNb2RlbC4KICAgICAgIGBfZGF0YWAgaG9sZHMgYWxsIG9mIHRoZSBhdHRyaWJ1dGVzIHRoYXQgaGF2ZSBiZWVuIGFja25vd2xlZGdlZCBieQogICAgICBhIGJhY2tlbmQgdmlhIHRoZSBhZGFwdGVyLiBXaGVuIHJvbGxiYWNrQXR0cmlidXRlcyBpcyBjYWxsZWQgb24gYSBtb2RlbCBhbGwKICAgICAgYXR0cmlidXRlcyB3aWxsIHJldmVydCB0byB0aGUgcmVjb3JkJ3Mgc3RhdGUgaW4gYF9kYXRhYC4KICAgICAgIGBfYXR0cmlidXRlc2AgaG9sZHMgYW55IGNoYW5nZSB0aGUgdXNlciBoYXMgbWFkZSB0byBhbiBhdHRyaWJ1dGUKICAgICAgdGhhdCBoYXMgbm90IGJlZW4gYWNrbm93bGVkZ2VkIGJ5IHRoZSBhZGFwdGVyLiBBbnkgdmFsdWVzIGluCiAgICAgIGBfYXR0cmlidXRlc2AgYXJlIGhhdmUgcHJpb3JpdHkgb3ZlciB2YWx1ZXMgaW4gYF9kYXRhYC4KICAgICAgIGBfaW5GbGlnaHRBdHRyaWJ1dGVzYC4gV2hlbiBhIHJlY29yZCBpcyBiZWluZyBzeW5jZWQgd2l0aCB0aGUKICAgICAgYmFja2VuZCB0aGUgdmFsdWVzIGluIGBfYXR0cmlidXRlc2AgYXJlIGNvcGllZCB0bwogICAgICBgX2luRmxpZ2h0QXR0cmlidXRlc2AuIFRoaXMgd2F5IGlmIHRoZSBiYWNrZW5kIGFja25vd2xlZGdlcyB0aGUKICAgICAgc2F2ZSBidXQgZG9lcyBub3QgcmV0dXJuIHRoZSBuZXcgc3RhdGUgRW1iZXIgRGF0YSBjYW4gY29weSB0aGUKICAgICAgdmFsdWVzIGZyb20gYF9pbkZsaWdodEF0dHJpYnV0ZXNgIHRvIGBfZGF0YWAuIFdpdGhvdXQgaGF2aW5nIHRvCiAgICAgIHdvcnJ5IGFib3V0IGNoYW5nZXMgbWFkZSB0byBgX2F0dHJpYnV0ZXNgIHdoaWxlIHRoZSBzYXZlIHdhcwogICAgICBoYXBwZW5pZ24uCiAgICAgICAgQ2hhbmdlZCBrZXlzIGJ1aWxkcyBhIGxpc3Qgb2YgYWxsIG9mIHRoZSB2YWx1ZXMgdGhhdCBtYXkgaGF2ZSBiZWVuCiAgICAgIGNoYW5nZWQgYnkgdGhlIGJhY2tlbmQgYWZ0ZXIgYSBzdWNjZXNzZnVsIHNhdmUuCiAgICAgICBJdCBkb2VzIHRoaXMgYnkgaXRlcmF0aW5nIG92ZXIgZWFjaCBrZXksIHZhbHVlIHBhaXIgaW4gdGhlIHBheWxvYWQKICAgICAgcmV0dXJuZWQgZnJvbSB0aGUgc2VydmVyIGFmdGVyIGEgc2F2ZS4gSWYgdGhlIGBrZXlgIGlzIGZvdW5kIGluCiAgICAgIGBfYXR0cmlidXRlc2AgdGhlbiB0aGUgdXNlciBoYXMgYSBsb2NhbCBjaGFuZ2VkIHRvIHRoZSBhdHRyaWJ1dGUKICAgICAgdGhhdCBoYXMgbm90IGJlZW4gc3luY2VkIHdpdGggdGhlIHNlcnZlciBhbmQgdGhlIGtleSBpcyBub3QKICAgICAgaW5jbHVkZWQgaW4gdGhlIGxpc3Qgb2YgY2hhbmdlZCBrZXlzLgogICAgCiAgICAgIElmIHRoZSB2YWx1ZSwgZm9yIGEga2V5IGRpZmZlcnMgZnJvbSB0aGUgdmFsdWUgaW4gd2hhdCBFbWJlciBEYXRhCiAgICAgIGJlbGlldmVzIHRvIGJlIHRoZSB0cnV0aCBhYm91dCB0aGUgYmFja2VuZCBzdGF0ZSAoQSBtZXJnZXIgb2YgdGhlCiAgICAgIGBfZGF0YWAgYW5kIGBfaW5GbGlnaHRBdHRyaWJ1dGVzYCBvYmplY3RzIHdoZXJlCiAgICAgIGBfaW5GbGlnaHRBdHRyaWJ1dGVzYCBoYXMgcHJpb3JpdHkpIHRoZW4gdGhhdCBtZWFucyB0aGUgYmFja2VuZAogICAgICBoYXMgdXBkYXRlZCB0aGUgdmFsdWUgYW5kIHRoZSBrZXkgaXMgYWRkZWQgdG8gdGhlIGxpc3Qgb2YgY2hhbmdlZAogICAgICBrZXlzLgogICAgICAgQG1ldGhvZCBfY2hhbmdlZEtleXMKICAgICAgQHByaXZhdGUKICAgICovCgogICAgLyoKICAgICAgICBUT0RPIElHT1IgREFWSUQKICAgICAgICBUaGVyZSBzZWVtcyB0byBiZSBhIHBvdGVudGlhbCBidWcgaGVyZSwgd2hlcmUgd2Ugd2lsbCByZXR1cm4ga2V5cyB0aGF0IGFyZSBub3QKICAgICAgICBpbiB0aGUgc2NoZW1hCiAgICAqLwogICAgOwoKICAgIF9wcm90by5fY2hhbmdlZEtleXMgPSBmdW5jdGlvbiBfY2hhbmdlZEtleXModXBkYXRlcykgewogICAgICB2YXIgY2hhbmdlZEtleXMgPSBbXTsKCiAgICAgIGlmICh1cGRhdGVzKSB7CiAgICAgICAgdmFyIG9yaWdpbmFsLCBpLCB2YWx1ZSwgX2tleTI7CgogICAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXModXBkYXRlcyk7CiAgICAgICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoOwogICAgICAgIHZhciBoYXNBdHRycyA9IHRoaXMuaGFzQ2hhbmdlZEF0dHJpYnV0ZXMoKTsKICAgICAgICB2YXIgYXR0cnM7CgogICAgICAgIGlmIChoYXNBdHRycykgewogICAgICAgICAgYXR0cnMgPSB0aGlzLl9hdHRyaWJ1dGVzOwogICAgICAgIH0KCiAgICAgICAgb3JpZ2luYWwgPSBFbWJlci5hc3NpZ24oT2JqZWN0LmNyZWF0ZShudWxsKSwgdGhpcy5fZGF0YSwgdGhpcy5fX2luRmxpZ2h0QXR0cmlidXRlcyk7CgogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgX2tleTIgPSBrZXlzW2ldOwogICAgICAgICAgdmFsdWUgPSB1cGRhdGVzW19rZXkyXTsgLy8gQSB2YWx1ZSBpbiBfYXR0cmlidXRlcyBtZWFucyB0aGUgdXNlciBoYXMgYSBsb2NhbCBjaGFuZ2UgdG8KICAgICAgICAgIC8vIHRoaXMgYXR0cmlidXRlcy4gV2UgbmV2ZXIgb3ZlcnJpZGUgdGhpcyB2YWx1ZSB3aGVuIG1lcmdpbmcKICAgICAgICAgIC8vIHVwZGF0ZXMgZnJvbSB0aGUgYmFja2VuZCBzbyB3ZSBzaG91bGQgbm90IHNlbnQgYSBjaGFuZ2UKICAgICAgICAgIC8vIG5vdGlmaWNhdGlvbiBpZiB0aGUgc2VydmVyIHZhbHVlIGRpZmZlcnMgZnJvbSB0aGUgb3JpZ2luYWwuCgogICAgICAgICAgaWYgKGhhc0F0dHJzID09PSB0cnVlICYmIGF0dHJzW19rZXkyXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQoKICAgICAgICAgIGlmICghRW1iZXIuaXNFcXVhbChvcmlnaW5hbFtfa2V5Ml0sIHZhbHVlKSkgewogICAgICAgICAgICBjaGFuZ2VkS2V5cy5wdXNoKF9rZXkyKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBjaGFuZ2VkS2V5czsKICAgIH07CgogICAgX3Byb3RvLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiAiPCIgKyB0aGlzLm1vZGVsTmFtZSArICI6IiArIHRoaXMuaWQgKyAiPiI7CiAgICB9OwoKICAgIF9jcmVhdGVDbGFzcyQzKFJlY29yZERhdGFEZWZhdWx0LCBbewogICAgICBrZXk6ICJfYXR0cmlidXRlcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIGlmICh0aGlzLl9fYXR0cmlidXRlcyA9PT0gbnVsbCkgewogICAgICAgICAgdGhpcy5fX2F0dHJpYnV0ZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMuX19hdHRyaWJ1dGVzOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2KSB7CiAgICAgICAgdGhpcy5fX2F0dHJpYnV0ZXMgPSB2OwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogIl9yZWxhdGlvbnNoaXBzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMuX19yZWxhdGlvbnNoaXBzID09PSBudWxsKSB7CiAgICAgICAgICB0aGlzLl9fcmVsYXRpb25zaGlwcyA9IG5ldyBSZWxhdGlvbnNoaXBzKHRoaXMpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMuX19yZWxhdGlvbnNoaXBzOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogIl9kYXRhIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMuX19kYXRhID09PSBudWxsKSB7CiAgICAgICAgICB0aGlzLl9fZGF0YSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fX2RhdGE7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHYpIHsKICAgICAgICB0aGlzLl9fZGF0YSA9IHY7CiAgICAgIH0KICAgICAgLyoKICAgICAgIGltcGxpY2l0IHJlbGF0aW9uc2hpcHMgYXJlIHJlbGF0aW9uc2hpcCB3aGljaCBoYXZlIG5vdCBiZWVuIGRlY2xhcmVkIGJ1dCB0aGUgaW52ZXJzZSBzaWRlIGV4aXN0cyBvbgogICAgICAgYW5vdGhlciByZWNvcmQgc29tZXdoZXJlCiAgICAgICBGb3IgZXhhbXBsZSBpZiB0aGVyZSB3YXMKICAgICAgICBgYGBhcHAvbW9kZWxzL2NvbW1lbnQuanMKICAgICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgIG5hbWU6IGF0dHIoKQogICAgICAgfSk7CiAgICAgICBgYGAKICAgICAgICBidXQgdGhlcmUgaXMgYWxzbwogICAgICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIsIGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICAgbmFtZTogYXR0cigpLAogICAgICAgICBjb21tZW50czogaGFzTWFueSgnY29tbWVudCcpCiAgICAgICB9KTsKICAgICAgIGBgYAogICAgICAgIHdvdWxkIGhhdmUgYSBpbXBsaWNpdCBwb3N0IHJlbGF0aW9uc2hpcCBpbiBvcmRlciB0byBiZSBkbyB0aGluZ3MgbGlrZSByZW1vdmUgb3Vyc2VsdmVzIGZyb20gdGhlIHBvc3QKICAgICAgIHdoZW4gd2UgYXJlIGRlbGV0ZWQKICAgICAgKi8KCiAgICB9LCB7CiAgICAgIGtleTogIl9pbXBsaWNpdFJlbGF0aW9uc2hpcHMiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fX2ltcGxpY2l0UmVsYXRpb25zaGlwcyA9PT0gbnVsbCkgewogICAgICAgICAgdmFyIHJlbGF0aW9uc2hpcHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgdGhpcy5fX2ltcGxpY2l0UmVsYXRpb25zaGlwcyA9IHJlbGF0aW9uc2hpcHM7CiAgICAgICAgICByZXR1cm4gcmVsYXRpb25zaGlwczsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9faW1wbGljaXRSZWxhdGlvbnNoaXBzOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogIl9pbkZsaWdodEF0dHJpYnV0ZXMiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fX2luRmxpZ2h0QXR0cmlidXRlcyA9PT0gbnVsbCkgewogICAgICAgICAgdGhpcy5fX2luRmxpZ2h0QXR0cmlidXRlcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fX2luRmxpZ2h0QXR0cmlidXRlczsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQodikgewogICAgICAgIHRoaXMuX19pbkZsaWdodEF0dHJpYnV0ZXMgPSB2OwogICAgICB9CiAgICB9XSk7CgogICAgcmV0dXJuIFJlY29yZERhdGFEZWZhdWx0OwogIH0oKTsKICAvLyByZWxhdGlvbnNoaXAgb2YgdGhlIGRlbWF0ZXJpYWxpemF0aW9uOiB0aGlzIGlzIGRvbmUgc28gdGhlIHJlbGF0aW9uc2hpcCBjYW4KICAvLyBub3RpZnkgaXRzIGludmVyc2Ugd2hpY2ggbmVlZHMgdG8gdXBkYXRlIHN0YXRlCiAgLy8KICAvLyBJZiB0aGUgaW52ZXJzZSBpcyBzeW5jLCB1bmxvYWRpbmcgdGhpcyByZWNvcmQgaXMgdHJlYXRlZCBhcyBhIGNsaWVudC1zaWRlCiAgLy8gZGVsZXRlLCBzbyB3ZSByZW1vdmUgdGhlIGludmVyc2UgcmVjb3JkcyBmcm9tIHRoaXMgcmVsYXRpb25zaGlwIHRvCiAgLy8gZGlzY29ubmVjdCB0aGUgZ3JhcGguICBCZWNhdXNlIGl0J3Mgbm90IGFzeW5jLCB3ZSBkb24ndCBuZWVkIHRvIGtlZXAgYXJvdW5kCiAgLy8gdGhlIGludGVybmFsTW9kZWwgYXMgYW4gaWQtd3JhcHBlciBmb3IgcmVmZXJlbmNlcyBhbmQgYmVjYXVzZSB0aGUgZ3JhcGggaXMKICAvLyBkaXNjb25uZWN0ZWQgd2UgY2FuIGFjdHVhbGx5IGRlc3Ryb3kgdGhlIGludGVybmFsTW9kZWwgd2hlbiBjaGVja2luZyBmb3IKICAvLyBvcnBoYW5lZCBtb2RlbHMuCgoKICBmdW5jdGlvbiBkZXN0cm95UmVsYXRpb25zaGlwKHJlbCkgewogICAgcmVsLnJlY29yZERhdGFEaWREZW1hdGVyaWFsaXplKCk7CgogICAgaWYgKHJlbC5faW52ZXJzZUlzU3luYygpKSB7CiAgICAgIHJlbC5yZW1vdmVBbGxSZWNvcmREYXRhc0Zyb21Pd24oKTsKICAgICAgcmVsLnJlbW92ZUFsbENhbm9uaWNhbFJlY29yZERhdGFzRnJvbU93bigpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gYXJlQWxsTW9kZWxzVW5sb2FkZWQocmVjb3JkRGF0YXMpIHsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVjb3JkRGF0YXMubGVuZ3RoOyArK2kpIHsKICAgICAgaWYgKHJlY29yZERhdGFzW2ldLmlzUmVjb3JkSW5Vc2UoKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiB0cnVlOwogIH0KCiAgZXhwb3J0cy5CZWxvbmdzVG9SZWxhdGlvbnNoaXAgPSBCZWxvbmdzVG9SZWxhdGlvbnNoaXA7CiAgZXhwb3J0cy5NYW55UmVsYXRpb25zaGlwID0gTWFueVJlbGF0aW9uc2hpcDsKICBleHBvcnRzLlJlY29yZERhdGEgPSBSZWNvcmREYXRhRGVmYXVsdDsKICBleHBvcnRzLlJlbGF0aW9uc2hpcCA9IFJlbGF0aW9uc2hpcDsKICBleHBvcnRzLnJlbGF0aW9uc2hpcFN0YXRlRm9yID0gcmVsYXRpb25zaGlwU3RhdGVGb3I7CiAgZXhwb3J0cy5yZWxhdGlvbnNoaXBzRm9yID0gcmVsYXRpb25zaGlwc0ZvcjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTsKCn0pOwoKO2RlZmluZSgnQGVtYmVyLWRhdGEvc2VyaWFsaXplci8tcHJpdmF0ZScsIFsnZXhwb3J0cyddLCBmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zZXJpYWxpemVyCiAgKi8KCiAgLyoqCiAgICAjIyBVc2luZyBFbWJlZGRlZCBSZWNvcmRzCgogICAgYEVtYmVkZGVkUmVjb3Jkc01peGluYCBzdXBwb3J0cyBzZXJpYWxpemluZyBlbWJlZGRlZCByZWNvcmRzLgoKICAgIFRvIHNldCB1cCBlbWJlZGRlZCByZWNvcmRzLCBpbmNsdWRlIHRoZSBtaXhpbiB3aGVuIGV4dGVuZGluZyBhIHNlcmlhbGl6ZXIsCiAgICB0aGVuIGRlZmluZSBhbmQgY29uZmlndXJlIGVtYmVkZGVkIChtb2RlbCkgcmVsYXRpb25zaGlwcy4KCiAgICBOb3RlIHRoYXQgZW1iZWRkZWQgcmVjb3JkcyB3aWxsIHNlcmlhbGl6ZSB3aXRoIHRoZSBzZXJpYWxpemVyIGZvciB0aGVpciBtb2RlbCBpbnN0ZWFkIG9mIHRoZSBzZXJpYWxpemVyIGluIHdoaWNoIHRoZXkgYXJlIGRlZmluZWQuCgogICAgQmVsb3cgaXMgYW4gZXhhbXBsZSBvZiBhIHBlci10eXBlIHNlcmlhbGl6ZXIgKGBwb3N0YCB0eXBlKS4KCiAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyLCB7IEVtYmVkZGVkUmVjb3Jkc01peGluIH0gZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKCiAgICBleHBvcnQgZGVmYXVsdCBSRVNUU2VyaWFsaXplci5leHRlbmQoRW1iZWRkZWRSZWNvcmRzTWl4aW4sIHsKICAgICAgYXR0cnM6IHsKICAgICAgICBhdXRob3I6IHsgZW1iZWRkZWQ6ICdhbHdheXMnIH0sCiAgICAgICAgY29tbWVudHM6IHsgc2VyaWFsaXplOiAnaWRzJyB9CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgICBOb3RlIHRoYXQgdGhpcyB1c2Ugb2YgYHsgZW1iZWRkZWQ6ICdhbHdheXMnIH1gIGlzIHVucmVsYXRlZCB0bwogICAgdGhlIGB7IGVtYmVkZGVkOiAnYWx3YXlzJyB9YCB0aGF0IGlzIGRlZmluZWQgYXMgYW4gb3B0aW9uIG9uIGBhdHRyYCBhcyBwYXJ0IG9mCiAgICBkZWZpbmluZyBhIG1vZGVsIHdoaWxlIHdvcmtpbmcgd2l0aCB0aGUgYEFjdGl2ZU1vZGVsU2VyaWFsaXplcmAuICBOZXZlcnRoZWxlc3MsCiAgICB1c2luZyBgeyBlbWJlZGRlZDogJ2Fsd2F5cycgfWAgYXMgYW4gb3B0aW9uIHRvIGBhdHRyYCBpcyBub3QgYSB2YWxpZCB3YXkgdG8gc2V0IHVwCiAgICBlbWJlZGRlZCByZWNvcmRzLgoKICAgIFRoZSBgYXR0cnNgIG9wdGlvbiBmb3IgYSByZXNvdXJjZSBgeyBlbWJlZGRlZDogJ2Fsd2F5cycgfWAgaXMgc2hvcnRoYW5kIGZvcjoKCiAgICBgYGBqcwogICAgewogICAgICBzZXJpYWxpemU6ICdyZWNvcmRzJywKICAgICAgZGVzZXJpYWxpemU6ICdyZWNvcmRzJwogICAgfQogICAgYGBgCgogICAgIyMjIENvbmZpZ3VyaW5nIEF0dHJzCgogICAgQSByZXNvdXJjZSdzIGBhdHRyc2Agb3B0aW9uIG1heSBiZSBzZXQgdG8gdXNlIGBpZHNgLCBgcmVjb3Jkc2Agb3IgZmFsc2UgZm9yIHRoZQogICAgYHNlcmlhbGl6ZWAgIGFuZCBgZGVzZXJpYWxpemVgIHNldHRpbmdzLgoKICAgIFRoZSBgYXR0cnNgIHByb3BlcnR5IGNhbiBiZSBzZXQgb24gdGhlIGBBcHBsaWNhdGlvblNlcmlhbGl6ZXJgIG9yIGEgcGVyLXR5cGUKICAgIHNlcmlhbGl6ZXIuCgogICAgSW4gdGhlIGNhc2Ugd2hlcmUgZW1iZWRkZWQgSlNPTiBpcyBleHBlY3RlZCB3aGlsZSBleHRyYWN0aW5nIGEgcGF5bG9hZCAocmVhZGluZykKICAgIHRoZSBzZXR0aW5nIGlzIGBkZXNlcmlhbGl6ZTogJ3JlY29yZHMnYCwgdGhlcmUgaXMgbm8gbmVlZCB0byB1c2UgYGlkc2Agd2hlbgogICAgZXh0cmFjdGluZyBhcyB0aGF0IGlzIHRoZSBkZWZhdWx0IGJlaGF2aW91ciB3aXRob3V0IHRoaXMgbWl4aW4gaWYgeW91IGFyZSB1c2luZwogICAgdGhlIHZhbmlsbGEgYEVtYmVkZGVkUmVjb3Jkc01peGluYC4gTGlrZXdpc2UsIHRvIGVtYmVkIEpTT04gaW4gdGhlIHBheWxvYWQgd2hpbGUKICAgIHNlcmlhbGl6aW5nIGBzZXJpYWxpemU6ICdyZWNvcmRzJ2AgaXMgdGhlIHNldHRpbmcgdG8gdXNlLiBUaGVyZSBpcyBhbiBvcHRpb24gb2YKICAgIG5vdCBlbWJlZGRpbmcgSlNPTiBpbiB0aGUgc2VyaWFsaXplZCBwYXlsb2FkIGJ5IHVzaW5nIGBzZXJpYWxpemU6ICdpZHMnYC4gSWYgeW91CiAgICBkbyBub3Qgd2FudCB0aGUgcmVsYXRpb25zaGlwIHNlbnQgYXQgYWxsLCB5b3UgY2FuIHVzZSBgc2VyaWFsaXplOiBmYWxzZWAuCgoKICAgICMjIyBFbWJlZGRlZFJlY29yZHNNaXhpbiBkZWZhdWx0cwogICAgSWYgeW91IGRvIG5vdCBvdmVyd3JpdGUgYGF0dHJzYCBmb3IgYSBzcGVjaWZpYyByZWxhdGlvbnNoaXAsIHRoZSBgRW1iZWRkZWRSZWNvcmRzTWl4aW5gCiAgICB3aWxsIGJlaGF2ZSBpbiB0aGUgZm9sbG93aW5nIHdheToKCiAgICBCZWxvbmdzVG86IGB7IHNlcmlhbGl6ZTogJ2lkJywgZGVzZXJpYWxpemU6ICdpZCcgfWAKICAgIEhhc01hbnk6ICAgYHsgc2VyaWFsaXplOiBmYWxzZSwgZGVzZXJpYWxpemU6ICdpZHMnIH1gCgogICAgIyMjIE1vZGVsIFJlbGF0aW9uc2hpcHMKCiAgICBFbWJlZGRlZCByZWNvcmRzIG11c3QgaGF2ZSBhIG1vZGVsIGRlZmluZWQgdG8gYmUgZXh0cmFjdGVkIGFuZCBzZXJpYWxpemVkLiBOb3RlIHRoYXQKICAgIHdoZW4gZGVmaW5pbmcgYW55IHJlbGF0aW9uc2hpcHMgb24geW91ciBtb2RlbCBzdWNoIGFzIGBiZWxvbmdzVG9gIGFuZCBgaGFzTWFueWAsIHlvdQogICAgc2hvdWxkIG5vdCBib3RoIHNwZWNpZnkgYGFzeW5jOiB0cnVlYCBhbmQgYWxzbyBpbmRpY2F0ZSB0aHJvdWdoIHRoZSBzZXJpYWxpemVyJ3MKICAgIGBhdHRyc2AgYXR0cmlidXRlIHRoYXQgdGhlIHJlbGF0ZWQgbW9kZWwgc2hvdWxkIGJlIGVtYmVkZGVkIGZvciBkZXNlcmlhbGl6YXRpb24uCiAgICBJZiBhIG1vZGVsIGlzIGRlY2xhcmVkIGVtYmVkZGVkIGZvciBkZXNlcmlhbGl6YXRpb24gKGBlbWJlZGRlZDogJ2Fsd2F5cydgIG9yIGBkZXNlcmlhbGl6ZTogJ3JlY29yZHMnYCksCiAgICB0aGVuIGRvIG5vdCB1c2UgYGFzeW5jOiB0cnVlYC4KCiAgICBUbyBzdWNjZXNzZnVsbHkgZXh0cmFjdCBhbmQgc2VyaWFsaXplIGVtYmVkZGVkIHJlY29yZHMgdGhlIG1vZGVsIHJlbGF0aW9uc2hpcHMKICAgIG11c3QgYmUgc2V0IHVwIGNvcnJlY3RseS4gU2VlIHRoZQogICAgW2RlZmluaW5nIHJlbGF0aW9uc2hpcHNdKGh0dHBzOi8vZ3VpZGVzLmVtYmVyanMuY29tL2N1cnJlbnQvbW9kZWxzL3JlbGF0aW9uc2hpcHMpCiAgICBzZWN0aW9uIG9mIHRoZSAqKkRlZmluaW5nIE1vZGVscyoqIGd1aWRlIHBhZ2UuCgogICAgUmVjb3JkcyB3aXRob3V0IGFuIGBpZGAgcHJvcGVydHkgYXJlIG5vdCBjb25zaWRlcmVkIGVtYmVkZGVkIHJlY29yZHMsIG1vZGVsCiAgICBpbnN0YW5jZXMgbXVzdCBoYXZlIGFuIGBpZGAgcHJvcGVydHkgdG8gYmUgdXNlZCB3aXRoIEVtYmVyIERhdGEuCgogICAgIyMjIEV4YW1wbGUgSlNPTiBwYXlsb2FkcywgTW9kZWxzIGFuZCBTZXJpYWxpemVycwoKICAgICoqV2hlbiBjdXN0b21pemluZyBhIHNlcmlhbGl6ZXIgaXQgaXMgaW1wb3J0YW50IHRvIGdyb2sgd2hhdCB0aGUgY3VzdG9taXphdGlvbnMKICAgIGFyZS4gUGxlYXNlIHJlYWQgdGhlIGRvY3MgZm9yIHRoZSBtZXRob2RzIHRoaXMgbWl4aW4gcHJvdmlkZXMsIGluIGNhc2UgeW91IG5lZWQKICAgIHRvIG1vZGlmeSBpdCB0byBmaXQgeW91ciBzcGVjaWZpYyBuZWVkcy4qKgoKICAgIEZvciBleGFtcGxlLCByZXZpZXcgdGhlIGRvY3MgZm9yIGVhY2ggbWV0aG9kIG9mIHRoaXMgbWl4aW46CiAgICAqIFtub3JtYWxpemVdKC9lbWJlci1kYXRhL3JlbGVhc2UvY2xhc3Nlcy9FbWJlZGRlZFJlY29yZHNNaXhpbi9tZXRob2RzL25vcm1hbGl6ZT9hbmNob3I9bm9ybWFsaXplKQogICAgKiBbc2VyaWFsaXplQmVsb25nc1RvXSgvZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvRW1iZWRkZWRSZWNvcmRzTWl4aW4vbWV0aG9kcy9zZXJpYWxpemVCZWxvbmdzVG8/YW5jaG9yPXNlcmlhbGl6ZUJlbG9uZ3NUbykKICAgICogW3NlcmlhbGl6ZUhhc01hbnldKC9lbWJlci1kYXRhL3JlbGVhc2UvY2xhc3Nlcy9FbWJlZGRlZFJlY29yZHNNaXhpbi9tZXRob2RzL3NlcmlhbGl6ZUhhc01hbnk/YW5jaG9yPXNlcmlhbGl6ZUhhc01hbnkpCgogICAgQGNsYXNzIEVtYmVkZGVkUmVjb3Jkc01peGluCiAgKi8KICB2YXIgZW1iZWRkZWRSZWNvcmRzTWl4aW4gPSBFbWJlci5NaXhpbi5jcmVhdGUoewogICAgLyoqCiAgICAgIE5vcm1hbGl6ZSB0aGUgcmVjb3JkIGFuZCByZWN1cnNpdmVseSBub3JtYWxpemUvZXh0cmFjdCBhbGwgdGhlIGVtYmVkZGVkIHJlY29yZHMKICAgICAgd2hpbGUgcHVzaGluZyB0aGVtIGludG8gdGhlIHN0b3JlIGFzIHRoZXkgYXJlIGVuY291bnRlcmVkCiAgICAgICBBIHBheWxvYWQgd2l0aCBhbiBhdHRyIGNvbmZpZ3VyZWQgZm9yIGVtYmVkZGVkIHJlY29yZHMgbmVlZHMgdG8gYmUgZXh0cmFjdGVkOgogICAgICAgYGBganMKICAgICAgewogICAgICAgICJwb3N0IjogewogICAgICAgICAgImlkIjogIjEiCiAgICAgICAgICAidGl0bGUiOiAiUmFpbHMgaXMgb21ha2FzZSIsCiAgICAgICAgICAiY29tbWVudHMiOiBbewogICAgICAgICAgICAiaWQiOiAiMSIsCiAgICAgICAgICAgICJib2R5IjogIlJhaWxzIGlzIHVuYWdpIgogICAgICAgICAgfSwgewogICAgICAgICAgICAiaWQiOiAiMiIsCiAgICAgICAgICAgICJib2R5IjogIk9tYWthc2UgT19vIgogICAgICAgICAgfV0KICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgQG1ldGhvZCBub3JtYWxpemUKICAgICBAcGFyYW0ge01vZGVsfSB0eXBlQ2xhc3MKICAgICBAcGFyYW0ge09iamVjdH0gaGFzaCB0byBiZSBub3JtYWxpemVkCiAgICAgQHBhcmFtIHtTdHJpbmd9IHByb3AgdGhlIGhhc2ggaGFzIGJlZW4gcmVmZXJlbmNlZCBieQogICAgIEByZXR1cm4ge09iamVjdH0gdGhlIG5vcm1hbGl6ZWQgaGFzaAogICAgKiovCiAgICBub3JtYWxpemU6IGZ1bmN0aW9uIG5vcm1hbGl6ZSh0eXBlQ2xhc3MsIGhhc2gsIHByb3ApIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRIYXNoID0gdGhpcy5fc3VwZXIodHlwZUNsYXNzLCBoYXNoLCBwcm9wKTsKCiAgICAgIHJldHVybiB0aGlzLl9leHRyYWN0RW1iZWRkZWRSZWNvcmRzKHRoaXMsIHRoaXMuc3RvcmUsIHR5cGVDbGFzcywgbm9ybWFsaXplZEhhc2gpOwogICAgfSwKICAgIGtleUZvclJlbGF0aW9uc2hpcDogZnVuY3Rpb24ga2V5Rm9yUmVsYXRpb25zaGlwKGtleSwgdHlwZUNsYXNzLCBtZXRob2QpIHsKICAgICAgaWYgKG1ldGhvZCA9PT0gJ3NlcmlhbGl6ZScgJiYgdGhpcy5oYXNTZXJpYWxpemVSZWNvcmRzT3B0aW9uKGtleSkgfHwgbWV0aG9kID09PSAnZGVzZXJpYWxpemUnICYmIHRoaXMuaGFzRGVzZXJpYWxpemVSZWNvcmRzT3B0aW9uKGtleSkpIHsKICAgICAgICByZXR1cm4gdGhpcy5rZXlGb3JBdHRyaWJ1dGUoa2V5LCBtZXRob2QpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0aGlzLl9zdXBlcihrZXksIHR5cGVDbGFzcywgbWV0aG9kKSB8fCBrZXk7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIFNlcmlhbGl6ZSBgYmVsb25nc1RvYCByZWxhdGlvbnNoaXAgd2hlbiBpdCBpcyBjb25maWd1cmVkIGFzIGFuIGVtYmVkZGVkIG9iamVjdC4KICAgICAgIFRoaXMgZXhhbXBsZSBvZiBhbiBhdXRob3IgbW9kZWwgYmVsb25ncyB0byBhIHBvc3QgbW9kZWw6CiAgICAgICBgYGBqcwogICAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciwgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgUG9zdCA9IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdGl0bGU6ICAgIGF0dHIoJ3N0cmluZycpLAogICAgICAgIGJvZHk6ICAgICBhdHRyKCdzdHJpbmcnKSwKICAgICAgICBhdXRob3I6ICAgYmVsb25nc1RvKCdhdXRob3InKQogICAgICB9KTsKICAgICAgIEF1dGhvciA9IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgbmFtZTogICAgIGF0dHIoJ3N0cmluZycpLAogICAgICAgIHBvc3Q6ICAgICBiZWxvbmdzVG8oJ3Bvc3QnKQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBVc2UgYSBjdXN0b20gKHR5cGUpIHNlcmlhbGl6ZXIgZm9yIHRoZSBwb3N0IG1vZGVsIHRvIGNvbmZpZ3VyZSBlbWJlZGRlZCBhdXRob3IKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBSRVNUU2VyaWFsaXplciwgeyBFbWJlZGRlZFJlY29yZHNNaXhpbiB9IGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSRVNUU2VyaWFsaXplci5leHRlbmQoRW1iZWRkZWRSZWNvcmRzTWl4aW4sIHsKICAgICAgICBhdHRyczogewogICAgICAgICAgYXV0aG9yOiB7IGVtYmVkZGVkOiAnYWx3YXlzJyB9CiAgICAgICAgfQogICAgICB9KQogICAgICBgYGAKICAgICAgIEEgcGF5bG9hZCB3aXRoIGFuIGF0dHJpYnV0ZSBjb25maWd1cmVkIGZvciBlbWJlZGRlZCByZWNvcmRzIGNhbiBzZXJpYWxpemUKICAgICAgdGhlIHJlY29yZHMgdG9nZXRoZXIgdW5kZXIgdGhlIHJvb3QgYXR0cmlidXRlJ3MgcGF5bG9hZDoKICAgICAgIGBgYGpzCiAgICAgIHsKICAgICAgICAicG9zdCI6IHsKICAgICAgICAgICJpZCI6ICIxIgogICAgICAgICAgInRpdGxlIjogIlJhaWxzIGlzIG9tYWthc2UiLAogICAgICAgICAgImF1dGhvciI6IHsKICAgICAgICAgICAgImlkIjogIjIiCiAgICAgICAgICAgICJuYW1lIjogImRoaCIKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZUJlbG9uZ3NUbwogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcGFyYW0ge09iamVjdH0ganNvbgogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwCiAgICAqLwogICAgc2VyaWFsaXplQmVsb25nc1RvOiBmdW5jdGlvbiBzZXJpYWxpemVCZWxvbmdzVG8oc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCkgewogICAgICB2YXIgYXR0ciA9IHJlbGF0aW9uc2hpcC5rZXk7CgogICAgICBpZiAodGhpcy5ub1NlcmlhbGl6ZU9wdGlvblNwZWNpZmllZChhdHRyKSkgewogICAgICAgIHRoaXMuX3N1cGVyKHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApOwoKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBpbmNsdWRlSWRzID0gdGhpcy5oYXNTZXJpYWxpemVJZHNPcHRpb24oYXR0cik7CiAgICAgIHZhciBpbmNsdWRlUmVjb3JkcyA9IHRoaXMuaGFzU2VyaWFsaXplUmVjb3Jkc09wdGlvbihhdHRyKTsKICAgICAgdmFyIGVtYmVkZGVkU25hcHNob3QgPSBzbmFwc2hvdC5iZWxvbmdzVG8oYXR0cik7CgogICAgICBpZiAoaW5jbHVkZUlkcykgewogICAgICAgIHZhciBzZXJpYWxpemVkS2V5ID0gdGhpcy5fZ2V0TWFwcGVkS2V5KHJlbGF0aW9uc2hpcC5rZXksIHNuYXBzaG90LnR5cGUpOwoKICAgICAgICBpZiAoc2VyaWFsaXplZEtleSA9PT0gcmVsYXRpb25zaGlwLmtleSAmJiB0aGlzLmtleUZvclJlbGF0aW9uc2hpcCkgewogICAgICAgICAgc2VyaWFsaXplZEtleSA9IHRoaXMua2V5Rm9yUmVsYXRpb25zaGlwKHJlbGF0aW9uc2hpcC5rZXksIHJlbGF0aW9uc2hpcC5raW5kLCAnc2VyaWFsaXplJyk7CiAgICAgICAgfQoKICAgICAgICBpZiAoIWVtYmVkZGVkU25hcHNob3QpIHsKICAgICAgICAgIGpzb25bc2VyaWFsaXplZEtleV0gPSBudWxsOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBqc29uW3NlcmlhbGl6ZWRLZXldID0gZW1iZWRkZWRTbmFwc2hvdC5pZDsKCiAgICAgICAgICBpZiAocmVsYXRpb25zaGlwLm9wdGlvbnMucG9seW1vcnBoaWMpIHsKICAgICAgICAgICAgdGhpcy5zZXJpYWxpemVQb2x5bW9ycGhpY1R5cGUoc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGluY2x1ZGVSZWNvcmRzKSB7CiAgICAgICAgdGhpcy5fc2VyaWFsaXplRW1iZWRkZWRCZWxvbmdzVG8oc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCk7CiAgICAgIH0KICAgIH0sCiAgICBfc2VyaWFsaXplRW1iZWRkZWRCZWxvbmdzVG86IGZ1bmN0aW9uIF9zZXJpYWxpemVFbWJlZGRlZEJlbG9uZ3NUbyhzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBlbWJlZGRlZFNuYXBzaG90ID0gc25hcHNob3QuYmVsb25nc1RvKHJlbGF0aW9uc2hpcC5rZXkpOwoKICAgICAgdmFyIHNlcmlhbGl6ZWRLZXkgPSB0aGlzLl9nZXRNYXBwZWRLZXkocmVsYXRpb25zaGlwLmtleSwgc25hcHNob3QudHlwZSk7CgogICAgICBpZiAoc2VyaWFsaXplZEtleSA9PT0gcmVsYXRpb25zaGlwLmtleSAmJiB0aGlzLmtleUZvclJlbGF0aW9uc2hpcCkgewogICAgICAgIHNlcmlhbGl6ZWRLZXkgPSB0aGlzLmtleUZvclJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXAua2V5LCByZWxhdGlvbnNoaXAua2luZCwgJ3NlcmlhbGl6ZScpOwogICAgICB9CgogICAgICBpZiAoIWVtYmVkZGVkU25hcHNob3QpIHsKICAgICAgICBqc29uW3NlcmlhbGl6ZWRLZXldID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICBqc29uW3NlcmlhbGl6ZWRLZXldID0gZW1iZWRkZWRTbmFwc2hvdC5zZXJpYWxpemUoewogICAgICAgICAgaW5jbHVkZUlkOiB0cnVlCiAgICAgICAgfSk7CiAgICAgICAgdGhpcy5yZW1vdmVFbWJlZGRlZEZvcmVpZ25LZXkoc25hcHNob3QsIGVtYmVkZGVkU25hcHNob3QsIHJlbGF0aW9uc2hpcCwganNvbltzZXJpYWxpemVkS2V5XSk7CgogICAgICAgIGlmIChyZWxhdGlvbnNoaXAub3B0aW9ucy5wb2x5bW9ycGhpYykgewogICAgICAgICAgdGhpcy5zZXJpYWxpemVQb2x5bW9ycGhpY1R5cGUoc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCk7CiAgICAgICAgfQogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBTZXJpYWxpemVzIGBoYXNNYW55YCByZWxhdGlvbnNoaXBzIHdoZW4gaXQgaXMgY29uZmlndXJlZCBhcyBlbWJlZGRlZCBvYmplY3RzLgogICAgICAgVGhpcyBleGFtcGxlIG9mIGEgcG9zdCBtb2RlbCBoYXMgbWFueSBjb21tZW50czoKICAgICAgIGBgYGpzCiAgICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyLCBiZWxvbmdzVG8sIGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgICBQb3N0ID0gTW9kZWwuZXh0ZW5kKHsKICAgICAgICB0aXRsZTogICAgYXR0cignc3RyaW5nJyksCiAgICAgICAgYm9keTogICAgIGF0dHIoJ3N0cmluZycpLAogICAgICAgIGNvbW1lbnRzOiBoYXNNYW55KCdjb21tZW50JykKICAgICAgfSk7CiAgICAgICBDb21tZW50ID0gTW9kZWwuZXh0ZW5kKHsKICAgICAgICBib2R5OiAgICAgYXR0cignc3RyaW5nJyksCiAgICAgICAgcG9zdDogICAgIGJlbG9uZ3NUbygncG9zdCcpCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFVzZSBhIGN1c3RvbSAodHlwZSkgc2VyaWFsaXplciBmb3IgdGhlIHBvc3QgbW9kZWwgdG8gY29uZmlndXJlIGVtYmVkZGVkIGNvbW1lbnRzCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIsIHsgRW1iZWRkZWRSZWNvcmRzTWl4aW4gfSBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKEVtYmVkZGVkUmVjb3Jkc01peGluLCB7CiAgICAgICAgYXR0cnM6IHsKICAgICAgICAgIGNvbW1lbnRzOiB7IGVtYmVkZGVkOiAnYWx3YXlzJyB9CiAgICAgICAgfQogICAgICB9KQogICAgICBgYGAKICAgICAgIEEgcGF5bG9hZCB3aXRoIGFuIGF0dHJpYnV0ZSBjb25maWd1cmVkIGZvciBlbWJlZGRlZCByZWNvcmRzIGNhbiBzZXJpYWxpemUKICAgICAgdGhlIHJlY29yZHMgdG9nZXRoZXIgdW5kZXIgdGhlIHJvb3QgYXR0cmlidXRlJ3MgcGF5bG9hZDoKICAgICAgIGBgYGpzCiAgICAgIHsKICAgICAgICAicG9zdCI6IHsKICAgICAgICAgICJpZCI6ICIxIgogICAgICAgICAgInRpdGxlIjogIlJhaWxzIGlzIG9tYWthc2UiLAogICAgICAgICAgImJvZHkiOiAiSSB3YW50IHRoaXMgZm9yIG15IE9STSwgSSB3YW50IHRoYXQgZm9yIG15IHRlbXBsYXRlIGxhbmd1YWdlLi4uIgogICAgICAgICAgImNvbW1lbnRzIjogW3sKICAgICAgICAgICAgImlkIjogIjEiLAogICAgICAgICAgICAiYm9keSI6ICJSYWlscyBpcyB1bmFnaSIKICAgICAgICAgIH0sIHsKICAgICAgICAgICAgImlkIjogIjIiLAogICAgICAgICAgICAiYm9keSI6ICJPbWFrYXNlIE9fbyIKICAgICAgICAgIH1dCiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgVGhlIGF0dHJzIG9wdGlvbnMgb2JqZWN0IGNhbiB1c2UgbW9yZSBzcGVjaWZpYyBpbnN0cnVjdGlvbiBmb3IgZXh0cmFjdGluZyBhbmQKICAgICAgc2VyaWFsaXppbmcuIFdoZW4gc2VyaWFsaXppbmcsIGFuIG9wdGlvbiB0byBlbWJlZCBgaWRzYCwgYGlkcy1hbmQtdHlwZXNgIG9yIGByZWNvcmRzYCBjYW4gYmUgc2V0LgogICAgICBXaGVuIGV4dHJhY3RpbmcgdGhlIG9ubHkgb3B0aW9uIGlzIGByZWNvcmRzYC4KICAgICAgIFNvIGB7IGVtYmVkZGVkOiAnYWx3YXlzJyB9YCBpcyBzaG9ydGhhbmQgZm9yOgogICAgICBgeyBzZXJpYWxpemU6ICdyZWNvcmRzJywgZGVzZXJpYWxpemU6ICdyZWNvcmRzJyB9YAogICAgICAgVG8gZW1iZWQgdGhlIGBpZHNgIGZvciBhIHJlbGF0ZWQgb2JqZWN0ICh1c2luZyBhIGhhc01hbnkgcmVsYXRpb25zaGlwKToKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBSRVNUU2VyaWFsaXplciwgeyBFbWJlZGRlZFJlY29yZHNNaXhpbiB9IGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSRVNUU2VyaWFsaXplci5leHRlbmQoRW1iZWRkZWRSZWNvcmRzTWl4aW4sIHsKICAgICAgICBhdHRyczogewogICAgICAgICAgY29tbWVudHM6IHsgc2VyaWFsaXplOiAnaWRzJywgZGVzZXJpYWxpemU6ICdyZWNvcmRzJyB9CiAgICAgICAgfQogICAgICB9KQogICAgICBgYGAKICAgICAgIGBgYGpzCiAgICAgIHsKICAgICAgICAicG9zdCI6IHsKICAgICAgICAgICJpZCI6ICIxIgogICAgICAgICAgInRpdGxlIjogIlJhaWxzIGlzIG9tYWthc2UiLAogICAgICAgICAgImJvZHkiOiAiSSB3YW50IHRoaXMgZm9yIG15IE9STSwgSSB3YW50IHRoYXQgZm9yIG15IHRlbXBsYXRlIGxhbmd1YWdlLi4uIgogICAgICAgICAgImNvbW1lbnRzIjogWyIxIiwgIjIiXQogICAgICAgIH0KICAgICAgfQogICAgICBgYGAKICAgICAgIFRvIGVtYmVkIHRoZSByZWxhdGlvbnNoaXAgYXMgYSBjb2xsZWN0aW9uIG9mIG9iamVjdHMgd2l0aCBgaWRgIGFuZCBgdHlwZWAga2V5cywgc2V0CiAgICAgIGBpZHMtYW5kLXR5cGVzYCBmb3IgdGhlIHJlbGF0ZWQgb2JqZWN0LgogICAgICAgVGhpcyBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIGZvciBwb2x5bW9ycGhpYyByZWxhdGlvbnNoaXBzIHdoZXJlIHJlY29yZHMgZG9uJ3Qgc2hhcmUKICAgICAgdGhlIHNhbWUgdGFibGUgYW5kIHRoZSBgaWRgIGlzIG5vdCBlbm91Z2ggaW5mb3JtYXRpb24uCiAgICAgICBGb3IgZXhhbXBsZSBoYXZpbmcgYSB1c2VyIHRoYXQgaGFzIG1hbnkgcGV0czoKICAgICAgIGBgYGpzCiAgICAgIFVzZXIgPSBNb2RlbC5leHRlbmQoewogICAgICAgIG5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICAgIHBldHM6IGhhc01hbnkoJ3BldCcsIHsgcG9seW1vcnBoaWM6IHRydWUgfSkKICAgICAgfSk7CiAgICAgICBQZXQgPSBNb2RlbC5leHRlbmQoewogICAgICAgIG5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICB9KTsKICAgICAgIENhdCA9IFBldC5leHRlbmQoewogICAgICAgIC8vIC4uLgogICAgICB9KTsKICAgICAgIFBhcnJvdCA9IFBldC5leHRlbmQoewogICAgICAgIC8vIC4uLgogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvdXNlci5qcwogICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIsIHsgRW1iZWRkZWRSZWNvcmRzTWl4aW4gfSBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKEVtYmVkZGVkUmVjb3Jkc01peGluLCB7CiAgICAgICAgYXR0cnM6IHsKICAgICAgICAgIHBldHM6IHsgc2VyaWFsaXplOiAnaWRzLWFuZC10eXBlcycsIGRlc2VyaWFsaXplOiAncmVjb3JkcycgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBganMKICAgICAgewogICAgICAgICJ1c2VyIjogewogICAgICAgICAgImlkIjogIjEiCiAgICAgICAgICAibmFtZSI6ICJCZXJ0aW4gT3Nib3JuZSIsCiAgICAgICAgICAicGV0cyI6IFsKICAgICAgICAgICAgeyAiaWQiOiAiMSIsICJ0eXBlIjogIkNhdCIgfSwKICAgICAgICAgICAgeyAiaWQiOiAiMSIsICJ0eXBlIjogIlBhcnJvdCJ9CiAgICAgICAgICBdCiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXJpYWxpemVIYXNNYW55CiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEBwYXJhbSB7T2JqZWN0fSBqc29uCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZWxhdGlvbnNoaXAKICAgICovCiAgICBzZXJpYWxpemVIYXNNYW55OiBmdW5jdGlvbiBzZXJpYWxpemVIYXNNYW55KHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIGF0dHIgPSByZWxhdGlvbnNoaXAua2V5OwoKICAgICAgaWYgKHRoaXMubm9TZXJpYWxpemVPcHRpb25TcGVjaWZpZWQoYXR0cikpIHsKICAgICAgICB0aGlzLl9zdXBlcihzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKTsKCiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAodGhpcy5oYXNTZXJpYWxpemVJZHNPcHRpb24oYXR0cikpIHsKICAgICAgICB2YXIgc2VyaWFsaXplZEtleSA9IHRoaXMuX2dldE1hcHBlZEtleShyZWxhdGlvbnNoaXAua2V5LCBzbmFwc2hvdC50eXBlKTsKCiAgICAgICAgaWYgKHNlcmlhbGl6ZWRLZXkgPT09IHJlbGF0aW9uc2hpcC5rZXkgJiYgdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXApIHsKICAgICAgICAgIHNlcmlhbGl6ZWRLZXkgPSB0aGlzLmtleUZvclJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXAua2V5LCByZWxhdGlvbnNoaXAua2luZCwgJ3NlcmlhbGl6ZScpOwogICAgICAgIH0KCiAgICAgICAganNvbltzZXJpYWxpemVkS2V5XSA9IHNuYXBzaG90Lmhhc01hbnkoYXR0ciwgewogICAgICAgICAgaWRzOiB0cnVlCiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5oYXNTZXJpYWxpemVSZWNvcmRzT3B0aW9uKGF0dHIpKSB7CiAgICAgICAgdGhpcy5fc2VyaWFsaXplRW1iZWRkZWRIYXNNYW55KHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApOwogICAgICB9IGVsc2UgewogICAgICAgIGlmICh0aGlzLmhhc1NlcmlhbGl6ZUlkc0FuZFR5cGVzT3B0aW9uKGF0dHIpKSB7CiAgICAgICAgICB0aGlzLl9zZXJpYWxpemVIYXNNYW55QXNJZHNBbmRUeXBlcyhzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0sCgogICAgLyoKICAgICAgU2VyaWFsaXplcyBhIGhhc01hbnkgcmVsYXRpb25zaGlwIGFzIGFuIGFycmF5IG9mIG9iamVjdHMgY29udGFpbmluZyBvbmx5IGBpZGAgYW5kIGB0eXBlYAogICAgICBrZXlzLgogICAgICBUaGlzIGhhcyBpdHMgdXNlIGNhc2Ugb24gcG9seW1vcnBoaWMgaGFzTWFueSByZWxhdGlvbnNoaXBzIHdoZXJlIHRoZSBzZXJ2ZXIgaXMgbm90IHN0b3JpbmcKICAgICAgYWxsIHJlY29yZHMgaW4gdGhlIHNhbWUgdGFibGUgdXNpbmcgU1RJLCBhbmQgdGhlcmVmb3JlIHRoZSBgaWRgIGlzIG5vdCBlbm91Z2ggaW5mb3JtYXRpb24KICAgICAgIFRPRE86IE1ha2UgdGhlIGRlZmF1bHQgaW4gRW1iZXItZGF0YSAzLjA/PwogICAgKi8KICAgIF9zZXJpYWxpemVIYXNNYW55QXNJZHNBbmRUeXBlczogZnVuY3Rpb24gX3NlcmlhbGl6ZUhhc01hbnlBc0lkc0FuZFR5cGVzKHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIHNlcmlhbGl6ZWRLZXkgPSB0aGlzLmtleUZvckF0dHJpYnV0ZShyZWxhdGlvbnNoaXAua2V5LCAnc2VyaWFsaXplJyk7CiAgICAgIHZhciBoYXNNYW55ID0gc25hcHNob3QuaGFzTWFueShyZWxhdGlvbnNoaXAua2V5KTsKICAgICAganNvbltzZXJpYWxpemVkS2V5XSA9IEVtYmVyLkEoaGFzTWFueSkubWFwKGZ1bmN0aW9uIChyZWNvcmRTbmFwc2hvdCkgewogICAgICAgIC8vCiAgICAgICAgLy8gSSdtIHN1cmUgSSdtIGJlaW5nIHV0dGVybHkgbmFpdmUgaGVyZS4gUHJvcGFibHkgaWQgaXMgYSBjb25maWd1cmF0ZSBwcm9wZXJ0eSBhbmQKICAgICAgICAvLyB0eXBlIHRvbywgYW5kIHRoZSBtb2RlbE5hbWUgaGFzIHRvIGJlIG5vcm1hbGl6ZWQgc29tZWhvdy4KICAgICAgICAvLwogICAgICAgIHJldHVybiB7CiAgICAgICAgICBpZDogcmVjb3JkU25hcHNob3QuaWQsCiAgICAgICAgICB0eXBlOiByZWNvcmRTbmFwc2hvdC5tb2RlbE5hbWUKICAgICAgICB9OwogICAgICB9KTsKICAgIH0sCiAgICBfc2VyaWFsaXplRW1iZWRkZWRIYXNNYW55OiBmdW5jdGlvbiBfc2VyaWFsaXplRW1iZWRkZWRIYXNNYW55KHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIHNlcmlhbGl6ZWRLZXkgPSB0aGlzLl9nZXRNYXBwZWRLZXkocmVsYXRpb25zaGlwLmtleSwgc25hcHNob3QudHlwZSk7CgogICAgICBpZiAoc2VyaWFsaXplZEtleSA9PT0gcmVsYXRpb25zaGlwLmtleSAmJiB0aGlzLmtleUZvclJlbGF0aW9uc2hpcCkgewogICAgICAgIHNlcmlhbGl6ZWRLZXkgPSB0aGlzLmtleUZvclJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXAua2V5LCByZWxhdGlvbnNoaXAua2luZCwgJ3NlcmlhbGl6ZScpOwogICAgICB9CiAgICAgIGpzb25bc2VyaWFsaXplZEtleV0gPSB0aGlzLl9nZW5lcmF0ZVNlcmlhbGl6ZWRIYXNNYW55KHNuYXBzaG90LCByZWxhdGlvbnNoaXApOwogICAgfSwKCiAgICAvKgogICAgICBSZXR1cm5zIGFuIGFycmF5IG9mIGVtYmVkZGVkIHJlY29yZHMgc2VyaWFsaXplZCB0byBKU09OCiAgICAqLwogICAgX2dlbmVyYXRlU2VyaWFsaXplZEhhc01hbnk6IGZ1bmN0aW9uIF9nZW5lcmF0ZVNlcmlhbGl6ZWRIYXNNYW55KHNuYXBzaG90LCByZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIGhhc01hbnkgPSBzbmFwc2hvdC5oYXNNYW55KHJlbGF0aW9uc2hpcC5rZXkpOwogICAgICB2YXIgbWFueUFycmF5ID0gRW1iZXIuQShoYXNNYW55KTsKICAgICAgdmFyIHJldCA9IG5ldyBBcnJheShtYW55QXJyYXkubGVuZ3RoKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWFueUFycmF5Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGVtYmVkZGVkU25hcHNob3QgPSBtYW55QXJyYXlbaV07CiAgICAgICAgdmFyIGVtYmVkZGVkSnNvbiA9IGVtYmVkZGVkU25hcHNob3Quc2VyaWFsaXplKHsKICAgICAgICAgIGluY2x1ZGVJZDogdHJ1ZQogICAgICAgIH0pOwogICAgICAgIHRoaXMucmVtb3ZlRW1iZWRkZWRGb3JlaWduS2V5KHNuYXBzaG90LCBlbWJlZGRlZFNuYXBzaG90LCByZWxhdGlvbnNoaXAsIGVtYmVkZGVkSnNvbik7CiAgICAgICAgcmV0W2ldID0gZW1iZWRkZWRKc29uOwogICAgICB9CgogICAgICByZXR1cm4gcmV0OwogICAgfSwKCiAgICAvKioKICAgICAgV2hlbiBzZXJpYWxpemluZyBhbiBlbWJlZGRlZCByZWNvcmQsIG1vZGlmeSB0aGUgcHJvcGVydHkgKGluIHRoZSBgSlNPTmAgcGF5bG9hZCkKICAgICAgdGhhdCByZWZlcnMgdG8gdGhlIHBhcmVudCByZWNvcmQgKGZvcmVpZ24ga2V5IGZvciB0aGUgcmVsYXRpb25zaGlwKS4KICAgICAgIFNlcmlhbGl6aW5nIGEgYGJlbG9uZ3NUb2AgcmVsYXRpb25zaGlwIHJlbW92ZXMgdGhlIHByb3BlcnR5IHRoYXQgcmVmZXJzIHRvIHRoZQogICAgICBwYXJlbnQgcmVjb3JkCiAgICAgICBTZXJpYWxpemluZyBhIGBoYXNNYW55YCByZWxhdGlvbnNoaXAgZG9lcyBub3QgcmVtb3ZlIHRoZSBwcm9wZXJ0eSB0aGF0IHJlZmVycyB0bwogICAgICB0aGUgcGFyZW50IHJlY29yZC4KICAgICAgIEBtZXRob2QgcmVtb3ZlRW1iZWRkZWRGb3JlaWduS2V5CiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEBwYXJhbSB7U25hcHNob3R9IGVtYmVkZGVkU25hcHNob3QKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlbGF0aW9uc2hpcAogICAgICBAcGFyYW0ge09iamVjdH0ganNvbgogICAgKi8KICAgIHJlbW92ZUVtYmVkZGVkRm9yZWlnbktleTogZnVuY3Rpb24gcmVtb3ZlRW1iZWRkZWRGb3JlaWduS2V5KHNuYXBzaG90LCBlbWJlZGRlZFNuYXBzaG90LCByZWxhdGlvbnNoaXAsIGpzb24pIHsKICAgICAgaWYgKHJlbGF0aW9uc2hpcC5raW5kID09PSAnYmVsb25nc1RvJykgewogICAgICAgIHZhciBwYXJlbnRSZWNvcmQgPSBzbmFwc2hvdC50eXBlLmludmVyc2VGb3IocmVsYXRpb25zaGlwLmtleSwgdGhpcy5zdG9yZSk7CgogICAgICAgIGlmIChwYXJlbnRSZWNvcmQpIHsKICAgICAgICAgIHZhciBuYW1lID0gcGFyZW50UmVjb3JkLm5hbWU7CiAgICAgICAgICB2YXIgZW1iZWRkZWRTZXJpYWxpemVyID0gdGhpcy5zdG9yZS5zZXJpYWxpemVyRm9yKGVtYmVkZGVkU25hcHNob3QubW9kZWxOYW1lKTsKICAgICAgICAgIHZhciBwYXJlbnRLZXkgPSBlbWJlZGRlZFNlcmlhbGl6ZXIua2V5Rm9yUmVsYXRpb25zaGlwKG5hbWUsIHBhcmVudFJlY29yZC5raW5kLCAnZGVzZXJpYWxpemUnKTsKCiAgICAgICAgICBpZiAocGFyZW50S2V5KSB7CiAgICAgICAgICAgIGRlbGV0ZSBqc29uW3BhcmVudEtleV07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qZWxzZSBpZiAocmVsYXRpb25zaGlwLmtpbmQgPT09ICdoYXNNYW55JykgewogICAgICByZXR1cm47CiAgICAgIH0qLwoKICAgIH0sCiAgICAvLyBjaGVja3MgY29uZmlnIGZvciBhdHRycyBvcHRpb24gdG8gZW1iZWRkZWQgKGFsd2F5cykgLSBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplCiAgICBoYXNFbWJlZGRlZEFsd2F5c09wdGlvbjogZnVuY3Rpb24gaGFzRW1iZWRkZWRBbHdheXNPcHRpb24oYXR0cikgewogICAgICB2YXIgb3B0aW9uID0gdGhpcy5hdHRyc09wdGlvbihhdHRyKTsKICAgICAgcmV0dXJuIG9wdGlvbiAmJiBvcHRpb24uZW1iZWRkZWQgPT09ICdhbHdheXMnOwogICAgfSwKICAgIC8vIGNoZWNrcyBjb25maWcgZm9yIGF0dHJzIG9wdGlvbiB0byBzZXJpYWxpemUgaWRzCiAgICBoYXNTZXJpYWxpemVSZWNvcmRzT3B0aW9uOiBmdW5jdGlvbiBoYXNTZXJpYWxpemVSZWNvcmRzT3B0aW9uKGF0dHIpIHsKICAgICAgdmFyIGFsd2F5c0VtYmVkID0gdGhpcy5oYXNFbWJlZGRlZEFsd2F5c09wdGlvbihhdHRyKTsKICAgICAgdmFyIG9wdGlvbiA9IHRoaXMuYXR0cnNPcHRpb24oYXR0cik7CiAgICAgIHJldHVybiBhbHdheXNFbWJlZCB8fCBvcHRpb24gJiYgb3B0aW9uLnNlcmlhbGl6ZSA9PT0gJ3JlY29yZHMnOwogICAgfSwKICAgIC8vIGNoZWNrcyBjb25maWcgZm9yIGF0dHJzIG9wdGlvbiB0byBzZXJpYWxpemUgcmVjb3JkcwogICAgaGFzU2VyaWFsaXplSWRzT3B0aW9uOiBmdW5jdGlvbiBoYXNTZXJpYWxpemVJZHNPcHRpb24oYXR0cikgewogICAgICB2YXIgb3B0aW9uID0gdGhpcy5hdHRyc09wdGlvbihhdHRyKTsKICAgICAgcmV0dXJuIG9wdGlvbiAmJiAob3B0aW9uLnNlcmlhbGl6ZSA9PT0gJ2lkcycgfHwgb3B0aW9uLnNlcmlhbGl6ZSA9PT0gJ2lkJyk7CiAgICB9LAogICAgLy8gY2hlY2tzIGNvbmZpZyBmb3IgYXR0cnMgb3B0aW9uIHRvIHNlcmlhbGl6ZSByZWNvcmRzIGFzIG9iamVjdHMgY29udGFpbmluZyBpZCBhbmQgdHlwZXMKICAgIGhhc1NlcmlhbGl6ZUlkc0FuZFR5cGVzT3B0aW9uOiBmdW5jdGlvbiBoYXNTZXJpYWxpemVJZHNBbmRUeXBlc09wdGlvbihhdHRyKSB7CiAgICAgIHZhciBvcHRpb24gPSB0aGlzLmF0dHJzT3B0aW9uKGF0dHIpOwogICAgICByZXR1cm4gb3B0aW9uICYmIChvcHRpb24uc2VyaWFsaXplID09PSAnaWRzLWFuZC10eXBlcycgfHwgb3B0aW9uLnNlcmlhbGl6ZSA9PT0gJ2lkLWFuZC10eXBlJyk7CiAgICB9LAogICAgLy8gY2hlY2tzIGNvbmZpZyBmb3IgYXR0cnMgb3B0aW9uIHRvIHNlcmlhbGl6ZSByZWNvcmRzCiAgICBub1NlcmlhbGl6ZU9wdGlvblNwZWNpZmllZDogZnVuY3Rpb24gbm9TZXJpYWxpemVPcHRpb25TcGVjaWZpZWQoYXR0cikgewogICAgICB2YXIgb3B0aW9uID0gdGhpcy5hdHRyc09wdGlvbihhdHRyKTsKICAgICAgcmV0dXJuICEob3B0aW9uICYmIChvcHRpb24uc2VyaWFsaXplIHx8IG9wdGlvbi5lbWJlZGRlZCkpOwogICAgfSwKICAgIC8vIGNoZWNrcyBjb25maWcgZm9yIGF0dHJzIG9wdGlvbiB0byBkZXNlcmlhbGl6ZSByZWNvcmRzCiAgICAvLyBhIGRlZmluZWQgb3B0aW9uIG9iamVjdCBmb3IgYSByZXNvdXJjZSBpcyB0cmVhdGVkIHRoZSBzYW1lIGFzCiAgICAvLyBgZGVzZXJpYWxpemU6ICdyZWNvcmRzJ2AKICAgIGhhc0Rlc2VyaWFsaXplUmVjb3Jkc09wdGlvbjogZnVuY3Rpb24gaGFzRGVzZXJpYWxpemVSZWNvcmRzT3B0aW9uKGF0dHIpIHsKICAgICAgdmFyIGFsd2F5c0VtYmVkID0gdGhpcy5oYXNFbWJlZGRlZEFsd2F5c09wdGlvbihhdHRyKTsKICAgICAgdmFyIG9wdGlvbiA9IHRoaXMuYXR0cnNPcHRpb24oYXR0cik7CiAgICAgIHJldHVybiBhbHdheXNFbWJlZCB8fCBvcHRpb24gJiYgb3B0aW9uLmRlc2VyaWFsaXplID09PSAncmVjb3Jkcyc7CiAgICB9LAogICAgYXR0cnNPcHRpb246IGZ1bmN0aW9uIGF0dHJzT3B0aW9uKGF0dHIpIHsKICAgICAgdmFyIGF0dHJzID0gdGhpcy5nZXQoJ2F0dHJzJyk7CiAgICAgIHJldHVybiBhdHRycyAmJiAoYXR0cnNbRW1iZXIuU3RyaW5nLmNhbWVsaXplKGF0dHIpXSB8fCBhdHRyc1thdHRyXSk7CiAgICB9LAoKICAgIC8qKgogICAgIEBtZXRob2QgX2V4dHJhY3RFbWJlZGRlZFJlY29yZHMKICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9leHRyYWN0RW1iZWRkZWRSZWNvcmRzOiBmdW5jdGlvbiBfZXh0cmFjdEVtYmVkZGVkUmVjb3JkcyhzZXJpYWxpemVyLCBzdG9yZSwgdHlwZUNsYXNzLCBwYXJ0aWFsKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICB0eXBlQ2xhc3MuZWFjaFJlbGF0aW9uc2hpcChmdW5jdGlvbiAoa2V5LCByZWxhdGlvbnNoaXApIHsKICAgICAgICBpZiAoc2VyaWFsaXplci5oYXNEZXNlcmlhbGl6ZVJlY29yZHNPcHRpb24oa2V5KSkgewogICAgICAgICAgaWYgKHJlbGF0aW9uc2hpcC5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgICAgICAgX3RoaXMuX2V4dHJhY3RFbWJlZGRlZEhhc01hbnkoc3RvcmUsIGtleSwgcGFydGlhbCwgcmVsYXRpb25zaGlwKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAocmVsYXRpb25zaGlwLmtpbmQgPT09ICdiZWxvbmdzVG8nKSB7CiAgICAgICAgICAgIF90aGlzLl9leHRyYWN0RW1iZWRkZWRCZWxvbmdzVG8oc3RvcmUsIGtleSwgcGFydGlhbCwgcmVsYXRpb25zaGlwKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gcGFydGlhbDsKICAgIH0sCgogICAgLyoqCiAgICAgQG1ldGhvZCBfZXh0cmFjdEVtYmVkZGVkSGFzTWFueQogICAgIEBwcml2YXRlCiAgICAqLwogICAgX2V4dHJhY3RFbWJlZGRlZEhhc01hbnk6IGZ1bmN0aW9uIF9leHRyYWN0RW1iZWRkZWRIYXNNYW55KHN0b3JlLCBrZXksIGhhc2gsIHJlbGF0aW9uc2hpcE1ldGEpIHsKICAgICAgdmFyIHJlbGF0aW9uc2hpcEhhc2ggPSBFbWJlci5nZXQoaGFzaCwgImRhdGEucmVsYXRpb25zaGlwcy4iICsga2V5ICsgIi5kYXRhIik7CgogICAgICBpZiAoIXJlbGF0aW9uc2hpcEhhc2gpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBoYXNNYW55ID0gbmV3IEFycmF5KHJlbGF0aW9uc2hpcEhhc2gubGVuZ3RoKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVsYXRpb25zaGlwSGFzaC5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBpdGVtID0gcmVsYXRpb25zaGlwSGFzaFtpXTsKCiAgICAgICAgdmFyIF90aGlzJF9ub3JtYWxpemVFbWJlZCA9IHRoaXMuX25vcm1hbGl6ZUVtYmVkZGVkUmVsYXRpb25zaGlwKHN0b3JlLCByZWxhdGlvbnNoaXBNZXRhLCBpdGVtKSwKICAgICAgICAgICAgZGF0YSA9IF90aGlzJF9ub3JtYWxpemVFbWJlZC5kYXRhLAogICAgICAgICAgICBpbmNsdWRlZCA9IF90aGlzJF9ub3JtYWxpemVFbWJlZC5pbmNsdWRlZDsKCiAgICAgICAgaGFzaC5pbmNsdWRlZCA9IGhhc2guaW5jbHVkZWQgfHwgW107CiAgICAgICAgaGFzaC5pbmNsdWRlZC5wdXNoKGRhdGEpOwoKICAgICAgICBpZiAoaW5jbHVkZWQpIHsKICAgICAgICAgIHZhciBfaGFzaCRpbmNsdWRlZDsKCiAgICAgICAgICAoX2hhc2gkaW5jbHVkZWQgPSBoYXNoLmluY2x1ZGVkKS5wdXNoLmFwcGx5KF9oYXNoJGluY2x1ZGVkLCBpbmNsdWRlZCk7CiAgICAgICAgfQoKICAgICAgICBoYXNNYW55W2ldID0gewogICAgICAgICAgaWQ6IGRhdGEuaWQsCiAgICAgICAgICB0eXBlOiBkYXRhLnR5cGUKICAgICAgICB9OwogICAgICB9CgogICAgICB2YXIgcmVsYXRpb25zaGlwID0gewogICAgICAgIGRhdGE6IGhhc01hbnkKICAgICAgfTsKICAgICAgRW1iZXIuc2V0KGhhc2gsICJkYXRhLnJlbGF0aW9uc2hpcHMuIiArIGtleSwgcmVsYXRpb25zaGlwKTsKICAgIH0sCgogICAgLyoqCiAgICAgQG1ldGhvZCBfZXh0cmFjdEVtYmVkZGVkQmVsb25nc1RvCiAgICAgQHByaXZhdGUKICAgICovCiAgICBfZXh0cmFjdEVtYmVkZGVkQmVsb25nc1RvOiBmdW5jdGlvbiBfZXh0cmFjdEVtYmVkZGVkQmVsb25nc1RvKHN0b3JlLCBrZXksIGhhc2gsIHJlbGF0aW9uc2hpcE1ldGEpIHsKICAgICAgdmFyIHJlbGF0aW9uc2hpcEhhc2ggPSBFbWJlci5nZXQoaGFzaCwgImRhdGEucmVsYXRpb25zaGlwcy4iICsga2V5ICsgIi5kYXRhIik7CgogICAgICBpZiAoIXJlbGF0aW9uc2hpcEhhc2gpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBfdGhpcyRfbm9ybWFsaXplRW1iZWQyID0gdGhpcy5fbm9ybWFsaXplRW1iZWRkZWRSZWxhdGlvbnNoaXAoc3RvcmUsIHJlbGF0aW9uc2hpcE1ldGEsIHJlbGF0aW9uc2hpcEhhc2gpLAogICAgICAgICAgZGF0YSA9IF90aGlzJF9ub3JtYWxpemVFbWJlZDIuZGF0YSwKICAgICAgICAgIGluY2x1ZGVkID0gX3RoaXMkX25vcm1hbGl6ZUVtYmVkMi5pbmNsdWRlZDsKCiAgICAgIGhhc2guaW5jbHVkZWQgPSBoYXNoLmluY2x1ZGVkIHx8IFtdOwogICAgICBoYXNoLmluY2x1ZGVkLnB1c2goZGF0YSk7CgogICAgICBpZiAoaW5jbHVkZWQpIHsKICAgICAgICB2YXIgX2hhc2gkaW5jbHVkZWQyOwoKICAgICAgICAoX2hhc2gkaW5jbHVkZWQyID0gaGFzaC5pbmNsdWRlZCkucHVzaC5hcHBseShfaGFzaCRpbmNsdWRlZDIsIGluY2x1ZGVkKTsKICAgICAgfQoKICAgICAgdmFyIGJlbG9uZ3NUbyA9IHsKICAgICAgICBpZDogZGF0YS5pZCwKICAgICAgICB0eXBlOiBkYXRhLnR5cGUKICAgICAgfTsKICAgICAgdmFyIHJlbGF0aW9uc2hpcCA9IHsKICAgICAgICBkYXRhOiBiZWxvbmdzVG8KICAgICAgfTsKICAgICAgRW1iZXIuc2V0KGhhc2gsICJkYXRhLnJlbGF0aW9uc2hpcHMuIiArIGtleSwgcmVsYXRpb25zaGlwKTsKICAgIH0sCgogICAgLyoqCiAgICAgQG1ldGhvZCBfbm9ybWFsaXplRW1iZWRkZWRSZWxhdGlvbnNoaXAKICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ub3JtYWxpemVFbWJlZGRlZFJlbGF0aW9uc2hpcDogZnVuY3Rpb24gX25vcm1hbGl6ZUVtYmVkZGVkUmVsYXRpb25zaGlwKHN0b3JlLCByZWxhdGlvbnNoaXBNZXRhLCByZWxhdGlvbnNoaXBIYXNoKSB7CiAgICAgIHZhciBtb2RlbE5hbWUgPSByZWxhdGlvbnNoaXBNZXRhLnR5cGU7CgogICAgICBpZiAocmVsYXRpb25zaGlwTWV0YS5vcHRpb25zLnBvbHltb3JwaGljKSB7CiAgICAgICAgbW9kZWxOYW1lID0gcmVsYXRpb25zaGlwSGFzaC50eXBlOwogICAgICB9CgogICAgICB2YXIgbW9kZWxDbGFzcyA9IHN0b3JlLm1vZGVsRm9yKG1vZGVsTmFtZSk7CiAgICAgIHZhciBzZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcihtb2RlbE5hbWUpOwogICAgICByZXR1cm4gc2VyaWFsaXplci5ub3JtYWxpemUobW9kZWxDbGFzcywgcmVsYXRpb25zaGlwSGFzaCwgbnVsbCk7CiAgICB9LAogICAgaXNFbWJlZGRlZFJlY29yZHNNaXhpbjogdHJ1ZQogIH0pOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc2VyaWFsaXplcgogICovCgogIC8qCiAgICBDaGVjayBpZiB0aGUgcGFzc2VkIG1vZGVsIGhhcyBhIGB0eXBlYCBhdHRyaWJ1dGUgb3IgYSByZWxhdGlvbnNoaXAgbmFtZWQgYHR5cGVgLgoKICAgIEBtZXRob2QgbW9kZWxIYXNBdHRyaWJ1dGVPclJlbGF0aW9uc2hpcE5hbWVkVHlwZQogICAgQHBhcmFtIG1vZGVsQ2xhc3MKICAgKi8KICBmdW5jdGlvbiBtb2RlbEhhc0F0dHJpYnV0ZU9yUmVsYXRpb25zaGlwTmFtZWRUeXBlKG1vZGVsQ2xhc3MpIHsKICAgIHJldHVybiBFbWJlci5nZXQobW9kZWxDbGFzcywgJ2F0dHJpYnV0ZXMnKS5oYXMoJ3R5cGUnKSB8fCBFbWJlci5nZXQobW9kZWxDbGFzcywgJ3JlbGF0aW9uc2hpcHNCeU5hbWUnKS5oYXMoJ3R5cGUnKTsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zZXJpYWxpemVyCiAgKi8KCiAgLyoqCiAgICBUaGUgYFRyYW5zZm9ybWAgY2xhc3MgaXMgdXNlZCB0byBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplIG1vZGVsCiAgICBhdHRyaWJ1dGVzIHdoZW4gdGhleSBhcmUgc2F2ZWQgb3IgbG9hZGVkIGZyb20gYW4KICAgIGFkYXB0ZXIuIFN1YmNsYXNzaW5nIGBUcmFuc2Zvcm1gIGlzIHVzZWZ1bCBmb3IgY3JlYXRpbmcgY3VzdG9tCiAgICBhdHRyaWJ1dGVzLiBBbGwgc3ViY2xhc3NlcyBvZiBgVHJhbnNmb3JtYCBtdXN0IGltcGxlbWVudCBhCiAgICBgc2VyaWFsaXplYCBhbmQgYSBgZGVzZXJpYWxpemVgIG1ldGhvZC4KCiAgICBFeGFtcGxlCgogICAgYGBgYXBwL3RyYW5zZm9ybXMvdGVtcGVyYXR1cmUuanMKICAgIGltcG9ydCBUcmFuc2Zvcm0gZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci90cmFuc2Zvcm0nOwoKICAgIC8vIENvbnZlcnRzIGNlbnRpZ3JhZGUgaW4gdGhlIEpTT04gdG8gZmFocmVuaGVpdCBpbiB0aGUgYXBwCiAgICBleHBvcnQgZGVmYXVsdCBUcmFuc2Zvcm0uZXh0ZW5kKHsKICAgICAgZGVzZXJpYWxpemUoc2VyaWFsaXplZCwgb3B0aW9ucykgewogICAgICAgIHJldHVybiAoc2VyaWFsaXplZCAqICAxLjgpICsgMzI7CiAgICAgIH0sCgogICAgICBzZXJpYWxpemUoZGVzZXJpYWxpemVkLCBvcHRpb25zKSB7CiAgICAgICAgcmV0dXJuIChkZXNlcmlhbGl6ZWQgLSAzMikgLyAxLjg7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCgogICAgVXNhZ2UKCiAgICBgYGBhcHAvbW9kZWxzL3JlcXVpcmVtZW50LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBuYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgdGVtcGVyYXR1cmU6IGF0dHIoJ3RlbXBlcmF0dXJlJykKICAgIH0pOwogICAgYGBgCgogICAgVGhlIG9wdGlvbnMgcGFzc2VkIGludG8gdGhlIGBhdHRyYCBmdW5jdGlvbiB3aGVuIHRoZSBhdHRyaWJ1dGUgaXMKICAgIGRlY2xhcmVkIG9uIHRoZSBtb2RlbCBpcyBhbHNvIGF2YWlsYWJsZSBpbiB0aGUgdHJhbnNmb3JtLgoKICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgdGl0bGU6IGF0dHIoJ3N0cmluZycpLAogICAgICBtYXJrZG93bjogYXR0cignbWFya2Rvd24nLCB7CiAgICAgICAgbWFya2Rvd246IHsKICAgICAgICAgIGdmbTogZmFsc2UsCiAgICAgICAgICBzYW5pdGl6ZTogdHJ1ZQogICAgICAgIH0KICAgICAgfSkKICAgIH0pOwogICAgYGBgCgogICAgYGBgYXBwL3RyYW5zZm9ybXMvbWFya2Rvd24uanMKICAgIGltcG9ydCBUcmFuc2Zvcm0gZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci90cmFuc2Zvcm0nOwoKICAgIGV4cG9ydCBkZWZhdWx0IFRyYW5zZm9ybS5leHRlbmQoewogICAgICBzZXJpYWxpemUoZGVzZXJpYWxpemVkLCBvcHRpb25zKSB7CiAgICAgICAgcmV0dXJuIGRlc2VyaWFsaXplZC5yYXc7CiAgICAgIH0sCgogICAgICBkZXNlcmlhbGl6ZShzZXJpYWxpemVkLCBvcHRpb25zKSB7CiAgICAgICAgdmFyIG1hcmtkb3duT3B0aW9ucyA9IG9wdGlvbnMubWFya2Rvd24gfHwge307CgogICAgICAgIHJldHVybiBtYXJrZWQoc2VyaWFsaXplZCwgbWFya2Rvd25PcHRpb25zKTsKICAgICAgfQogICAgfSk7CiAgICBgYGAKCiAgICBAY2xhc3MgVHJhbnNmb3JtCiAgICovCiAgdmFyIFRyYW5zZm9ybSA9IEVtYmVyLk9iamVjdC5leHRlbmQoewogICAgLyoqCiAgICAgIFdoZW4gZ2l2ZW4gYSBkZXNlcmlhbGl6ZWQgdmFsdWUgZnJvbSBhIHJlY29yZCBhdHRyaWJ1dGUgdGhpcwogICAgICBtZXRob2QgbXVzdCByZXR1cm4gdGhlIHNlcmlhbGl6ZWQgdmFsdWUuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCB7IGlzRW1wdHkgfSBmcm9tICdAZW1iZXIvdXRpbHMnOwogICAgICAgc2VyaWFsaXplKGRlc2VyaWFsaXplZCwgb3B0aW9ucykgewogICAgICAgIHJldHVybiBpc0VtcHR5KGRlc2VyaWFsaXplZCkgPyBudWxsIDogTnVtYmVyKGRlc2VyaWFsaXplZCk7CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZQogICAgICBAcGFyYW0gZGVzZXJpYWxpemVkIFRoZSBkZXNlcmlhbGl6ZWQgdmFsdWUKICAgICAgQHBhcmFtIG9wdGlvbnMgaGFzaCBvZiBvcHRpb25zIHBhc3NlZCB0byBgYXR0cmAKICAgICAgQHJldHVybiBUaGUgc2VyaWFsaXplZCB2YWx1ZQogICAgKi8KICAgIHNlcmlhbGl6ZTogbnVsbCwKCiAgICAvKioKICAgICAgV2hlbiBnaXZlbiBhIHNlcmlhbGl6ZWQgdmFsdWUgZnJvbSBhIEpTT04gb2JqZWN0IHRoaXMgbWV0aG9kIG11c3QKICAgICAgcmV0dXJuIHRoZSBkZXNlcmlhbGl6ZWQgdmFsdWUgZm9yIHRoZSByZWNvcmQgYXR0cmlidXRlLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBkZXNlcmlhbGl6ZShzZXJpYWxpemVkLCBvcHRpb25zKSB7CiAgICAgICAgcmV0dXJuIGVtcHR5KHNlcmlhbGl6ZWQpID8gbnVsbCA6IE51bWJlcihzZXJpYWxpemVkKTsKICAgICAgfQogICAgICBgYGAKICAgICAgIEBtZXRob2QgZGVzZXJpYWxpemUKICAgICAgQHBhcmFtIHNlcmlhbGl6ZWQgVGhlIHNlcmlhbGl6ZWQgdmFsdWUKICAgICAgQHBhcmFtIG9wdGlvbnMgaGFzaCBvZiBvcHRpb25zIHBhc3NlZCB0byBgYXR0cmAKICAgICAgQHJldHVybiBUaGUgZGVzZXJpYWxpemVkIHZhbHVlCiAgICAqLwogICAgZGVzZXJpYWxpemU6IG51bGwKICB9KTsKCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3NlcmlhbGl6ZXIKICAqLwoKICAvKioKICAgIFRoZSBgQm9vbGVhblRyYW5zZm9ybWAgY2xhc3MgaXMgdXNlZCB0byBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplCiAgICBib29sZWFuIGF0dHJpYnV0ZXMgb24gRW1iZXIgRGF0YSByZWNvcmQgb2JqZWN0cy4gVGhpcyB0cmFuc2Zvcm0gaXMKICAgIHVzZWQgd2hlbiBgYm9vbGVhbmAgaXMgcGFzc2VkIGFzIHRoZSB0eXBlIHBhcmFtZXRlciB0byB0aGUKICAgIFthdHRyXSgvZW1iZXItZGF0YS9yZWxlYXNlL2Z1bmN0aW9ucy9AZW1iZXItZGF0YSUyRm1vZGVsL2F0dHIpIGZ1bmN0aW9uLgoKICAgIFVzYWdlCgogICAgYGBgYXBwL21vZGVscy91c2VyLmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBpc0FkbWluOiBhdHRyKCdib29sZWFuJyksCiAgICAgIG5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICBlbWFpbDogYXR0cignc3RyaW5nJykKICAgIH0pOwogICAgYGBgCgogICAgQnkgZGVmYXVsdCwgdGhlIGJvb2xlYW4gdHJhbnNmb3JtIG9ubHkgYWxsb3dzIGZvciB2YWx1ZXMgb2YgYHRydWVgIG9yCiAgICBgZmFsc2VgLiBZb3UgY2FuIG9wdCBpbnRvIGFsbG93aW5nIGBudWxsYCB2YWx1ZXMgZm9yCiAgICBib29sZWFuIGF0dHJpYnV0ZXMgdmlhIGBhdHRyKCdib29sZWFuJywgeyBhbGxvd051bGw6IHRydWUgfSlgCgogICAgYGBgYXBwL21vZGVscy91c2VyLmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBlbWFpbDogYXR0cignc3RyaW5nJyksCiAgICAgIHVzZXJuYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgd2FudHNXZWVrbHlFbWFpbDogYXR0cignYm9vbGVhbicsIHsgYWxsb3dOdWxsOiB0cnVlIH0pCiAgICB9KTsKICAgIGBgYAoKICAgIEBjbGFzcyBCb29sZWFuVHJhbnNmb3JtCiAgICBAZXh0ZW5kcyBUcmFuc2Zvcm0KICAgKi8KCiAgdmFyIGJvb2xlYW4gPSBUcmFuc2Zvcm0uZXh0ZW5kKHsKICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiBkZXNlcmlhbGl6ZShzZXJpYWxpemVkLCBvcHRpb25zKSB7CiAgICAgIGlmIChFbWJlci5pc05vbmUoc2VyaWFsaXplZCkgJiYgb3B0aW9ucy5hbGxvd051bGwgPT09IHRydWUpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIHR5cGUgPSB0eXBlb2Ygc2VyaWFsaXplZDsKCiAgICAgIGlmICh0eXBlID09PSAnYm9vbGVhbicpIHsKICAgICAgICByZXR1cm4gc2VyaWFsaXplZDsKICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykgewogICAgICAgIHJldHVybiAvXih0cnVlfHR8MSkkL2kudGVzdChzZXJpYWxpemVkKTsKICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJykgewogICAgICAgIHJldHVybiBzZXJpYWxpemVkID09PSAxOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfSwKICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gc2VyaWFsaXplKGRlc2VyaWFsaXplZCwgb3B0aW9ucykgewogICAgICBpZiAoRW1iZXIuaXNOb25lKGRlc2VyaWFsaXplZCkgJiYgb3B0aW9ucy5hbGxvd051bGwgPT09IHRydWUpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgcmV0dXJuIEJvb2xlYW4oZGVzZXJpYWxpemVkKTsKICAgIH0KICB9KTsKCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3NlcmlhbGl6ZXIKICAqLwoKICAvKioKICAgVGhlIGBEYXRlVHJhbnNmb3JtYCBjbGFzcyBpcyB1c2VkIHRvIHNlcmlhbGl6ZSBhbmQgZGVzZXJpYWxpemUKICAgZGF0ZSBhdHRyaWJ1dGVzIG9uIEVtYmVyIERhdGEgcmVjb3JkIG9iamVjdHMuIFRoaXMgdHJhbnNmb3JtIGlzIHVzZWQKICAgd2hlbiBgZGF0ZWAgaXMgcGFzc2VkIGFzIHRoZSB0eXBlIHBhcmFtZXRlciB0byB0aGUKICAgW2F0dHJdKC9lbWJlci1kYXRhL3JlbGVhc2UvZnVuY3Rpb25zL0BlbWJlci1kYXRhJTJGbW9kZWwvYXR0cikgZnVuY3Rpb24uIEl0IHVzZXMgdGhlIFtgSVNPIDg2MDFgXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9JU09fODYwMSkKICAgc3RhbmRhcmQuCgogICBgYGBhcHAvbW9kZWxzL3Njb3JlLmpzCiAgIGltcG9ydCBNb2RlbCwgeyBhdHRyLCBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICB2YWx1ZTogYXR0cignbnVtYmVyJyksCiAgICAgIHBsYXllcjogYmVsb25nc1RvKCdwbGF5ZXInKSwKICAgICAgZGF0ZTogYXR0cignZGF0ZScpCiAgICB9KTsKICAgYGBgCgogICBAY2xhc3MgRGF0ZVRyYW5zZm9ybQogICBAZXh0ZW5kcyBUcmFuc2Zvcm0KICAgKi8KCiAgdmFyIGRhdGUgPSBUcmFuc2Zvcm0uZXh0ZW5kKHsKICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiBkZXNlcmlhbGl6ZShzZXJpYWxpemVkKSB7CiAgICAgIHZhciB0eXBlID0gdHlwZW9mIHNlcmlhbGl6ZWQ7CgogICAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHsKICAgICAgICB2YXIgb2Zmc2V0ID0gc2VyaWFsaXplZC5pbmRleE9mKCcrJyk7CgogICAgICAgIGlmIChvZmZzZXQgIT09IC0xICYmIHNlcmlhbGl6ZWQubGVuZ3RoIC0gNSA9PT0gb2Zmc2V0KSB7CiAgICAgICAgICBvZmZzZXQgKz0gMzsKICAgICAgICAgIHJldHVybiBuZXcgRGF0ZShzZXJpYWxpemVkLnNsaWNlKDAsIG9mZnNldCkgKyAnOicgKyBzZXJpYWxpemVkLnNsaWNlKG9mZnNldCkpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIG5ldyBEYXRlKHNlcmlhbGl6ZWQpOwogICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdudW1iZXInKSB7CiAgICAgICAgcmV0dXJuIG5ldyBEYXRlKHNlcmlhbGl6ZWQpOwogICAgICB9IGVsc2UgaWYgKHNlcmlhbGl6ZWQgPT09IG51bGwgfHwgc2VyaWFsaXplZCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgLy8gaWYgdGhlIHZhbHVlIGlzIG51bGwgcmV0dXJuIG51bGwKICAgICAgICAvLyBpZiB0aGUgdmFsdWUgaXMgbm90IHByZXNlbnQgaW4gdGhlIGRhdGEgcmV0dXJuIHVuZGVmaW5lZAogICAgICAgIHJldHVybiBzZXJpYWxpemVkOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICB9LAogICAgc2VyaWFsaXplOiBmdW5jdGlvbiBzZXJpYWxpemUoZGF0ZSkgewogICAgICBpZiAoZGF0ZSBpbnN0YW5jZW9mIERhdGUgJiYgIWlzTmFOKGRhdGUpKSB7CiAgICAgICAgcmV0dXJuIGRhdGUudG9JU09TdHJpbmcoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQogIH0pOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc2VyaWFsaXplcgogICovCgogIGZ1bmN0aW9uIGlzTnVtYmVyKHZhbHVlKSB7CiAgICByZXR1cm4gdmFsdWUgPT09IHZhbHVlICYmIHZhbHVlICE9PSBJbmZpbml0eSAmJiB2YWx1ZSAhPT0gLUluZmluaXR5OwogIH0KICAvKioKICAgIFRoZSBgTnVtYmVyVHJhbnNmb3JtYCBjbGFzcyBpcyB1c2VkIHRvIHNlcmlhbGl6ZSBhbmQgZGVzZXJpYWxpemUKICAgIG51bWVyaWMgYXR0cmlidXRlcyBvbiBFbWJlciBEYXRhIHJlY29yZCBvYmplY3RzLiBUaGlzIHRyYW5zZm9ybSBpcwogICAgdXNlZCB3aGVuIGBudW1iZXJgIGlzIHBhc3NlZCBhcyB0aGUgdHlwZSBwYXJhbWV0ZXIgdG8gdGhlCiAgICBbYXR0cl0oL2VtYmVyLWRhdGEvcmVsZWFzZS9mdW5jdGlvbnMvQGVtYmVyLWRhdGElMkZtb2RlbC9hdHRyKSBmdW5jdGlvbi4KCiAgICBVc2FnZQoKICAgIGBgYGFwcC9tb2RlbHMvc2NvcmUuanMKICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyLCBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgdmFsdWU6IGF0dHIoJ251bWJlcicpLAogICAgICBwbGF5ZXI6IGJlbG9uZ3NUbygncGxheWVyJyksCiAgICAgIGRhdGU6IGF0dHIoJ2RhdGUnKQogICAgfSk7CiAgICBgYGAKCiAgICBAY2xhc3MgTnVtYmVyVHJhbnNmb3JtCiAgICBAZXh0ZW5kcyBUcmFuc2Zvcm0KICAgKi8KCgogIHZhciBudW1iZXIgPSBUcmFuc2Zvcm0uZXh0ZW5kKHsKICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiBkZXNlcmlhbGl6ZShzZXJpYWxpemVkKSB7CiAgICAgIHZhciB0cmFuc2Zvcm1lZDsKCiAgICAgIGlmIChzZXJpYWxpemVkID09PSAnJyB8fCBzZXJpYWxpemVkID09PSBudWxsIHx8IHNlcmlhbGl6ZWQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9IGVsc2UgewogICAgICAgIHRyYW5zZm9ybWVkID0gTnVtYmVyKHNlcmlhbGl6ZWQpOwogICAgICAgIHJldHVybiBpc051bWJlcih0cmFuc2Zvcm1lZCkgPyB0cmFuc2Zvcm1lZCA6IG51bGw7CiAgICAgIH0KICAgIH0sCiAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIHNlcmlhbGl6ZShkZXNlcmlhbGl6ZWQpIHsKICAgICAgdmFyIHRyYW5zZm9ybWVkOwoKICAgICAgaWYgKGRlc2VyaWFsaXplZCA9PT0gJycgfHwgZGVzZXJpYWxpemVkID09PSBudWxsIHx8IGRlc2VyaWFsaXplZCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdHJhbnNmb3JtZWQgPSBOdW1iZXIoZGVzZXJpYWxpemVkKTsKICAgICAgICByZXR1cm4gaXNOdW1iZXIodHJhbnNmb3JtZWQpID8gdHJhbnNmb3JtZWQgOiBudWxsOwogICAgICB9CiAgICB9CiAgfSk7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zZXJpYWxpemVyCiAgKi8KCiAgLyoqCiAgICBUaGUgYFN0cmluZ1RyYW5zZm9ybWAgY2xhc3MgaXMgdXNlZCB0byBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplCiAgICBzdHJpbmcgYXR0cmlidXRlcyBvbiBFbWJlciBEYXRhIHJlY29yZCBvYmplY3RzLiBUaGlzIHRyYW5zZm9ybSBpcwogICAgdXNlZCB3aGVuIGBzdHJpbmdgIGlzIHBhc3NlZCBhcyB0aGUgdHlwZSBwYXJhbWV0ZXIgdG8gdGhlCiAgICBbYXR0cl0oL2VtYmVyLWRhdGEvcmVsZWFzZS9mdW5jdGlvbnMvQGVtYmVyLWRhdGElMkZtb2RlbC9hdHRyKSBmdW5jdGlvbi4KCiAgICBVc2FnZQoKICAgIGBgYGFwcC9tb2RlbHMvdXNlci5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIsIGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBpc0FkbWluOiBhdHRyKCdib29sZWFuJyksCiAgICAgIG5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICBlbWFpbDogYXR0cignc3RyaW5nJykKICAgIH0pOwogICAgYGBgCgogICAgQGNsYXNzIFN0cmluZ1RyYW5zZm9ybQogICAgQGV4dGVuZHMgVHJhbnNmb3JtCiAgICovCgogIHZhciBzdHJpbmcgPSBUcmFuc2Zvcm0uZXh0ZW5kKHsKICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiBkZXNlcmlhbGl6ZShzZXJpYWxpemVkKSB7CiAgICAgIHJldHVybiBFbWJlci5pc05vbmUoc2VyaWFsaXplZCkgPyBudWxsIDogU3RyaW5nKHNlcmlhbGl6ZWQpOwogICAgfSwKICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gc2VyaWFsaXplKGRlc2VyaWFsaXplZCkgewogICAgICByZXR1cm4gRW1iZXIuaXNOb25lKGRlc2VyaWFsaXplZCkgPyBudWxsIDogU3RyaW5nKGRlc2VyaWFsaXplZCk7CiAgICB9CiAgfSk7CgogIGV4cG9ydHMuQm9vbGVhblRyYW5zZm9ybSA9IGJvb2xlYW47CiAgZXhwb3J0cy5EYXRlVHJhbnNmb3JtID0gZGF0ZTsKICBleHBvcnRzLkVtYmVkZGVkUmVjb3Jkc01peGluID0gZW1iZWRkZWRSZWNvcmRzTWl4aW47CiAgZXhwb3J0cy5OdW1iZXJUcmFuc2Zvcm0gPSBudW1iZXI7CiAgZXhwb3J0cy5TdHJpbmdUcmFuc2Zvcm0gPSBzdHJpbmc7CiAgZXhwb3J0cy5UcmFuc2Zvcm0gPSBUcmFuc2Zvcm07CiAgZXhwb3J0cy5tb2RlbEhhc0F0dHJpYnV0ZU9yUmVsYXRpb25zaGlwTmFtZWRUeXBlID0gbW9kZWxIYXNBdHRyaWJ1dGVPclJlbGF0aW9uc2hpcE5hbWVkVHlwZTsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTsKCn0pOwoKO2RlZmluZSgiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9pbmRleCIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAgYFNlcmlhbGl6ZXJgIGlzIGFuIGFic3RyYWN0IGJhc2UgY2xhc3MgdGhhdCB5b3Ugc2hvdWxkIG92ZXJyaWRlIGluIHlvdXIKICAgIGFwcGxpY2F0aW9uIHRvIGN1c3RvbWl6ZSBpdCBmb3IgeW91ciBiYWNrZW5kLiBUaGUgbWluaW11bSBzZXQgb2YgbWV0aG9kcwogICAgdGhhdCB5b3Ugc2hvdWxkIGltcGxlbWVudCBpczoKICAKICAgICAgKiBgbm9ybWFsaXplUmVzcG9uc2UoKWAKICAgICAgKiBgc2VyaWFsaXplKClgCiAgCiAgICBBbmQgeW91IGNhbiBvcHRpb25hbGx5IG92ZXJyaWRlIHRoZSBmb2xsb3dpbmcgbWV0aG9kczoKICAKICAgICAgKiBgbm9ybWFsaXplKClgCiAgCiAgICBGb3IgYW4gZXhhbXBsZSBpbXBsZW1lbnRhdGlvbiwgc2VlCiAgICBbSlNPTlNlcmlhbGl6ZXJdKEpTT05TZXJpYWxpemVyKSwgdGhlIGluY2x1ZGVkIEpTT04gc2VyaWFsaXplci4KICAKICAgIEBjbGFzcyBTZXJpYWxpemVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICovCiAgdmFyIF9kZWZhdWx0ID0gRW1iZXIuT2JqZWN0LmV4dGVuZCh7CiAgICAvKioKICAgICAgVGhlIGBzdG9yZWAgcHJvcGVydHkgaXMgdGhlIGFwcGxpY2F0aW9uJ3MgYHN0b3JlYCB0aGF0IGNvbnRhaW5zCiAgICAgIGFsbCByZWNvcmRzLiBJdCBjYW4gYmUgdXNlZCB0byBsb29rIHVwIHNlcmlhbGl6ZXJzIGZvciBvdGhlciBtb2RlbAogICAgICB0eXBlcyB0aGF0IG1heSBiZSBuZXN0ZWQgaW5zaWRlIHRoZSBwYXlsb2FkIHJlc3BvbnNlLgogICAgICAgRXhhbXBsZToKICAgICAgIGBgYGpzCiAgICAgIFNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBleHRyYWN0UmVsYXRpb25zaGlwKHJlbGF0aW9uc2hpcE1vZGVsTmFtZSwgcmVsYXRpb25zaGlwSGFzaCkgewogICAgICAgICAgdmFyIG1vZGVsQ2xhc3MgPSB0aGlzLnN0b3JlLm1vZGVsRm9yKHJlbGF0aW9uc2hpcE1vZGVsTmFtZSk7CiAgICAgICAgICB2YXIgcmVsYXRpb25zaGlwU2VyaWFsaXplciA9IHRoaXMuc3RvcmUuc2VyaWFsaXplckZvcihyZWxhdGlvbnNoaXBNb2RlbE5hbWUpOwogICAgICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcFNlcmlhbGl6ZXIubm9ybWFsaXplKG1vZGVsQ2xhc3MsIHJlbGF0aW9uc2hpcEhhc2gpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQHByb3BlcnR5IHN0b3JlCiAgICAgIEB0eXBlIHtTdG9yZX0KICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgVGhlIGBub3JtYWxpemVSZXNwb25zZWAgbWV0aG9kIGlzIHVzZWQgdG8gbm9ybWFsaXplIGEgcGF5bG9hZCBmcm9tIHRoZQogICAgICBzZXJ2ZXIgdG8gYSBKU09OLUFQSSBEb2N1bWVudC4KICAgICAgIGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2RvY3VtZW50LXN0cnVjdHVyZQogICAgICAgRXhhbXBsZToKICAgICAgIGBgYGpzCiAgICAgIFNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBub3JtYWxpemVSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICAgICAgaWYgKHJlcXVlc3RUeXBlID09PSAnZmluZFJlY29yZCcpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplKHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBwYXlsb2FkLnJlZHVjZShmdW5jdGlvbihkb2N1bWVudEhhc2gsIGl0ZW0pIHsKICAgICAgICAgICAgICBsZXQgeyBkYXRhLCBpbmNsdWRlZCB9ID0gdGhpcy5ub3JtYWxpemUocHJpbWFyeU1vZGVsQ2xhc3MsIGl0ZW0pOwogICAgICAgICAgICAgIGRvY3VtZW50SGFzaC5pbmNsdWRlZC5wdXNoKC4uLmluY2x1ZGVkKTsKICAgICAgICAgICAgICBkb2N1bWVudEhhc2guZGF0YS5wdXNoKGRhdGEpOwogICAgICAgICAgICAgIHJldHVybiBkb2N1bWVudEhhc2g7CiAgICAgICAgICAgIH0sIHsgZGF0YTogW10sIGluY2x1ZGVkOiBbXSB9KQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIG5vcm1hbGl6ZVJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICovCiAgICBub3JtYWxpemVSZXNwb25zZTogbnVsbCwKCiAgICAvKioKICAgICAgVGhlIGBzZXJpYWxpemVgIG1ldGhvZCBpcyB1c2VkIHdoZW4gYSByZWNvcmQgaXMgc2F2ZWQgaW4gb3JkZXIgdG8gY29udmVydAogICAgICB0aGUgcmVjb3JkIGludG8gdGhlIGZvcm0gdGhhdCB5b3VyIGV4dGVybmFsIGRhdGEgc291cmNlIGV4cGVjdHMuCiAgICAgICBgc2VyaWFsaXplYCB0YWtlcyBhbiBvcHRpb25hbCBgb3B0aW9uc2AgaGFzaCB3aXRoIGEgc2luZ2xlIG9wdGlvbjoKICAgICAgIC0gYGluY2x1ZGVJZGA6IElmIHRoaXMgaXMgYHRydWVgLCBgc2VyaWFsaXplYCBzaG91bGQgaW5jbHVkZSB0aGUgSUQKICAgICAgICBpbiB0aGUgc2VyaWFsaXplZCBvYmplY3QgaXQgYnVpbGRzLgogICAgICAgRXhhbXBsZToKICAgICAgIGBgYGpzCiAgICAgIFNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBzZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpIHsKICAgICAgICAgIHZhciBqc29uID0gewogICAgICAgICAgICBpZDogc25hcHNob3QuaWQKICAgICAgICAgIH07CiAgICAgICAgICAgc25hcHNob3QuZWFjaEF0dHJpYnV0ZSgoa2V5LCBhdHRyaWJ1dGUpID0+IHsKICAgICAgICAgICAganNvbltrZXldID0gc25hcHNob3QuYXR0cihrZXkpOwogICAgICAgICAgfSk7CiAgICAgICAgICAgc25hcHNob3QuZWFjaFJlbGF0aW9uc2hpcCgoa2V5LCByZWxhdGlvbnNoaXApID0+IHsKICAgICAgICAgICAgaWYgKHJlbGF0aW9uc2hpcC5raW5kID09PSAnYmVsb25nc1RvJykgewogICAgICAgICAgICAgIGpzb25ba2V5XSA9IHNuYXBzaG90LmJlbG9uZ3NUbyhrZXksIHsgaWQ6IHRydWUgfSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAocmVsYXRpb25zaGlwLmtpbmQgPT09ICdoYXNNYW55JykgewogICAgICAgICAgICAgIGpzb25ba2V5XSA9IHNuYXBzaG90Lmhhc01hbnkoa2V5LCB7IGlkczogdHJ1ZSB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgICAgcmV0dXJuIGpzb247CiAgICAgICAgfSwKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXJpYWxpemUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXQogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgc2VyaWFsaXplOiBudWxsLAoKICAgIC8qKgogICAgICBUaGUgYG5vcm1hbGl6ZWAgbWV0aG9kIGlzIHVzZWQgdG8gY29udmVydCBhIHBheWxvYWQgcmVjZWl2ZWQgZnJvbSB5b3VyCiAgICAgIGV4dGVybmFsIGRhdGEgc291cmNlIGludG8gdGhlIG5vcm1hbGl6ZWQgZm9ybSBgc3RvcmUucHVzaCgpYCBleHBlY3RzLiBZb3UKICAgICAgc2hvdWxkIG92ZXJyaWRlIHRoaXMgbWV0aG9kLCBtdW5nZSB0aGUgaGFzaCBhbmQgcmV0dXJuIHRoZSBub3JtYWxpemVkCiAgICAgIHBheWxvYWQuCiAgICAgICBFeGFtcGxlOgogICAgICAgYGBganMKICAgICAgU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIG5vcm1hbGl6ZShtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpIHsKICAgICAgICAgIHZhciBkYXRhID0gewogICAgICAgICAgICBpZDogICAgICAgICAgICByZXNvdXJjZUhhc2guaWQsCiAgICAgICAgICAgIHR5cGU6ICAgICAgICAgIG1vZGVsQ2xhc3MubW9kZWxOYW1lLAogICAgICAgICAgICBhdHRyaWJ1dGVzOiAgICByZXNvdXJjZUhhc2gKICAgICAgICAgIH07CiAgICAgICAgICByZXR1cm4geyBkYXRhOiBkYXRhIH07CiAgICAgICAgfQogICAgICB9KQogICAgICBgYGAKICAgICAgIEBtZXRob2Qgbm9ybWFsaXplCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGVDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gaGFzaAogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgbm9ybWFsaXplOiBmdW5jdGlvbiBub3JtYWxpemUodHlwZUNsYXNzLCBoYXNoKSB7CiAgICAgIHJldHVybiBoYXNoOwogICAgfQogIH0pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwo7ZGVmaW5lKCJAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24tYXBpIiwgWyJleHBvcnRzIiwgImVtYmVyLWluZmxlY3RvciIsICJAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24iLCAiQGVtYmVyLWRhdGEvc3RvcmUiLCAiQGVtYmVyLWRhdGEvY2FuYXJ5LWZlYXR1cmVzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2VtYmVySW5mbGVjdG9yLCBfanNvbiwgX3N0b3JlLCBfY2FuYXJ5RmVhdHVyZXMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAgRW1iZXIgRGF0YSAyLjAgU2VyaWFsaXplcjoKICAKICAgIEluIEVtYmVyIERhdGEgYSBTZXJpYWxpemVyIGlzIHVzZWQgdG8gc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZQogICAgcmVjb3JkcyB3aGVuIHRoZXkgYXJlIHRyYW5zZmVycmVkIGluIGFuZCBvdXQgb2YgYW4gZXh0ZXJuYWwgc291cmNlLgogICAgVGhpcyBwcm9jZXNzIGludm9sdmVzIG5vcm1hbGl6aW5nIHByb3BlcnR5IG5hbWVzLCB0cmFuc2Zvcm1pbmcKICAgIGF0dHJpYnV0ZSB2YWx1ZXMgYW5kIHNlcmlhbGl6aW5nIHJlbGF0aW9uc2hpcHMuCiAgCiAgICBgSlNPTkFQSVNlcmlhbGl6ZXJgIHN1cHBvcnRzIHRoZSBodHRwOi8vanNvbmFwaS5vcmcvIHNwZWMgYW5kIGlzIHRoZQogICAgc2VyaWFsaXplciByZWNvbW1lbmRlZCBieSBFbWJlciBEYXRhLgogIAogICAgVGhpcyBzZXJpYWxpemVyIG5vcm1hbGl6ZXMgYSBKU09OIEFQSSBwYXlsb2FkIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGFwcC9tb2RlbHMvcGxheWVyLmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciwgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgbmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgIHNraWxsOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgZ2FtZXNQbGF5ZWQ6IGF0dHIoJ251bWJlcicpLAogICAgICBjbHViOiBiZWxvbmdzVG8oJ2NsdWInKQogICAgfSk7CiAgICBgYGAKICAKICAgIGBgYGFwcC9tb2RlbHMvY2x1Yi5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIsIGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBuYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgbG9jYXRpb246IGF0dHIoJ3N0cmluZycpLAogICAgICBwbGF5ZXJzOiBoYXNNYW55KCdwbGF5ZXInKQogICAgfSk7CiAgICBgYGAKICAKICAgIGBgYGpzCiAgICAgIHsKICAgICAgICAiZGF0YSI6IFsKICAgICAgICAgIHsKICAgICAgICAgICAgImF0dHJpYnV0ZXMiOiB7CiAgICAgICAgICAgICAgIm5hbWUiOiAiQmVuZmljYSIsCiAgICAgICAgICAgICAgImxvY2F0aW9uIjogIlBvcnR1Z2FsIgogICAgICAgICAgICB9LAogICAgICAgICAgICAiaWQiOiAiMSIsCiAgICAgICAgICAgICJyZWxhdGlvbnNoaXBzIjogewogICAgICAgICAgICAgICJwbGF5ZXJzIjogewogICAgICAgICAgICAgICAgImRhdGEiOiBbCiAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAiaWQiOiAiMyIsCiAgICAgICAgICAgICAgICAgICAgInR5cGUiOiAicGxheWVycyIKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgXQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgInR5cGUiOiAiY2x1YnMiCiAgICAgICAgICB9CiAgICAgICAgXSwKICAgICAgICAiaW5jbHVkZWQiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJhdHRyaWJ1dGVzIjogewogICAgICAgICAgICAgICJuYW1lIjogIkV1c2ViaW8gU2lsdmEgRmVycmVpcmEiLAogICAgICAgICAgICAgICJza2lsbCI6ICJSb2NrZXQgc2hvdCIsCiAgICAgICAgICAgICAgImdhbWVzLXBsYXllZCI6IDQzMQogICAgICAgICAgICB9LAogICAgICAgICAgICAiaWQiOiAiMyIsCiAgICAgICAgICAgICJyZWxhdGlvbnNoaXBzIjogewogICAgICAgICAgICAgICJjbHViIjogewogICAgICAgICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICJpZCI6ICIxIiwKICAgICAgICAgICAgICAgICAgInR5cGUiOiAiY2x1YnMiCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICAidHlwZSI6ICJwbGF5ZXJzIgogICAgICAgICAgfQogICAgICAgIF0KICAgICAgfQogICAgYGBgCiAgCiAgICB0byB0aGUgZm9ybWF0IHRoYXQgdGhlIEVtYmVyIERhdGEgc3RvcmUgZXhwZWN0cy4KICAKICAgICMjIyBDdXN0b21pemluZyBtZXRhCiAgCiAgICBTaW5jZSBhIEpTT04gQVBJIERvY3VtZW50IGNhbiBoYXZlIG1ldGEgZGVmaW5lZCBpbiBtdWx0aXBsZSBsb2NhdGlvbnMgeW91IGNhbgogICAgdXNlIHRoZSBzcGVjaWZpYyBzZXJpYWxpemVyIGhvb2tzIGlmIHlvdSBuZWVkIHRvIGN1c3RvbWl6ZSB0aGUgbWV0YS4KICAKICAgIE9uZSBzY2VuYXJpbyB3b3VsZCBiZSB0byBjYW1lbENhc2UgdGhlIG1ldGEga2V5cyBvZiB5b3VyIHBheWxvYWQuIFRoZSBleGFtcGxlCiAgICBiZWxvdyBzaG93cyBob3cgdGhpcyBjb3VsZCBiZSBkb25lIHVzaW5nIGBub3JtYWxpemVBcnJheVJlc3BvbnNlYCBhbmQKICAgIGBleHRyYWN0UmVsYXRpb25zaGlwYC4KICAKICAgIGBgYGFwcC9zZXJpYWxpemVycy9hcHBsaWNhdGlvbi5qcwogICAgZXhwb3J0IGRlZmF1bHQgSlNPTkFQSVNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgbm9ybWFsaXplQXJyYXlSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICAgIGxldCBub3JtYWxpemVkRG9jdW1lbnQgPSB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogIAogICAgICAgIC8vIEN1c3RvbWl6ZSBkb2N1bWVudCBtZXRhCiAgICAgICAgbm9ybWFsaXplZERvY3VtZW50Lm1ldGEgPSBjYW1lbENhc2VLZXlzKG5vcm1hbGl6ZWREb2N1bWVudC5tZXRhKTsKICAKICAgICAgICByZXR1cm4gbm9ybWFsaXplZERvY3VtZW50OwogICAgICB9LAogIAogICAgICBleHRyYWN0UmVsYXRpb25zaGlwKHJlbGF0aW9uc2hpcEhhc2gpIHsKICAgICAgICBsZXQgbm9ybWFsaXplZFJlbGF0aW9uc2hpcCA9IHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cyk7CiAgCiAgICAgICAgLy8gQ3VzdG9taXplIHJlbGF0aW9uc2hpcCBtZXRhCiAgICAgICAgbm9ybWFsaXplZFJlbGF0aW9uc2hpcC5tZXRhID0gY2FtZWxDYXNlS2V5cyhub3JtYWxpemVkUmVsYXRpb25zaGlwLm1ldGEpOwogIAogICAgICAgIHJldHVybiBub3JtYWxpemVkUmVsYXRpb25zaGlwOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQHNpbmNlIDEuMTMuMAogICAgQGNsYXNzIEpTT05BUElTZXJpYWxpemVyCiAgICBAZXh0ZW5kcyBKU09OU2VyaWFsaXplcgogICovCiAgdmFyIEpTT05BUElTZXJpYWxpemVyID0gX2pzb24uZGVmYXVsdC5leHRlbmQoewogICAgLyoqCiAgICAgIEBtZXRob2QgX25vcm1hbGl6ZURvY3VtZW50SGVscGVyCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBkb2N1bWVudEhhc2gKICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ub3JtYWxpemVEb2N1bWVudEhlbHBlcjogZnVuY3Rpb24gX25vcm1hbGl6ZURvY3VtZW50SGVscGVyKGRvY3VtZW50SGFzaCkgewogICAgICBpZiAoRW1iZXIudHlwZU9mKGRvY3VtZW50SGFzaC5kYXRhKSA9PT0gJ29iamVjdCcpIHsKICAgICAgICBkb2N1bWVudEhhc2guZGF0YSA9IHRoaXMuX25vcm1hbGl6ZVJlc291cmNlSGVscGVyKGRvY3VtZW50SGFzaC5kYXRhKTsKICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGRvY3VtZW50SGFzaC5kYXRhKSkgewogICAgICAgIHZhciByZXQgPSBuZXcgQXJyYXkoZG9jdW1lbnRIYXNoLmRhdGEubGVuZ3RoKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkb2N1bWVudEhhc2guZGF0YS5sZW5ndGg7IGkrKykgewogICAgICAgICAgdmFyIGRhdGEgPSBkb2N1bWVudEhhc2guZGF0YVtpXTsKICAgICAgICAgIHJldFtpXSA9IHRoaXMuX25vcm1hbGl6ZVJlc291cmNlSGVscGVyKGRhdGEpOwogICAgICAgIH0KCiAgICAgICAgZG9jdW1lbnRIYXNoLmRhdGEgPSByZXQ7CiAgICAgIH0KCiAgICAgIGlmIChBcnJheS5pc0FycmF5KGRvY3VtZW50SGFzaC5pbmNsdWRlZCkpIHsKICAgICAgICB2YXIgX3JldCA9IG5ldyBBcnJheSgpOwoKICAgICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgZG9jdW1lbnRIYXNoLmluY2x1ZGVkLmxlbmd0aDsgX2krKykgewogICAgICAgICAgdmFyIGluY2x1ZGVkID0gZG9jdW1lbnRIYXNoLmluY2x1ZGVkW19pXTsKCiAgICAgICAgICB2YXIgbm9ybWFsaXplZCA9IHRoaXMuX25vcm1hbGl6ZVJlc291cmNlSGVscGVyKGluY2x1ZGVkKTsKCiAgICAgICAgICBpZiAobm9ybWFsaXplZCAhPT0gbnVsbCkgewogICAgICAgICAgICAvLyBjYW4gYmUgbnVsbCB3aGVuIHVua25vd24gdHlwZSBpcyBlbmNvdW50ZXJlZAogICAgICAgICAgICBfcmV0LnB1c2gobm9ybWFsaXplZCk7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBkb2N1bWVudEhhc2guaW5jbHVkZWQgPSBfcmV0OwogICAgICB9CgogICAgICByZXR1cm4gZG9jdW1lbnRIYXNoOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBfbm9ybWFsaXplUmVsYXRpb25zaGlwRGF0YUhlbHBlcgogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwRGF0YUhhc2gKICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ub3JtYWxpemVSZWxhdGlvbnNoaXBEYXRhSGVscGVyOiBmdW5jdGlvbiBfbm9ybWFsaXplUmVsYXRpb25zaGlwRGF0YUhlbHBlcihyZWxhdGlvbnNoaXBEYXRhSGFzaCkgewogICAgICByZWxhdGlvbnNoaXBEYXRhSGFzaC50eXBlID0gdGhpcy5tb2RlbE5hbWVGcm9tUGF5bG9hZEtleShyZWxhdGlvbnNoaXBEYXRhSGFzaC50eXBlKTsKICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcERhdGFIYXNoOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBfbm9ybWFsaXplUmVzb3VyY2VIZWxwZXIKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlc291cmNlSGFzaAogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX25vcm1hbGl6ZVJlc291cmNlSGVscGVyOiBmdW5jdGlvbiBfbm9ybWFsaXplUmVzb3VyY2VIZWxwZXIocmVzb3VyY2VIYXNoKSB7CiAgICAgIChmYWxzZSAmJiAhKCFFbWJlci5pc05vbmUocmVzb3VyY2VIYXNoLnR5cGUpKSAmJiBFbWJlci5hc3NlcnQodGhpcy53YXJuTWVzc2FnZUZvclVuZGVmaW5lZFR5cGUoKSwgIUVtYmVyLmlzTm9uZShyZXNvdXJjZUhhc2gudHlwZSksIHsKICAgICAgICBpZDogJ2RzLnNlcmlhbGl6ZXIudHlwZS1pcy11bmRlZmluZWQnCiAgICAgIH0pKTsKICAgICAgdmFyIG1vZGVsTmFtZSwgdXNlZExvb2t1cDsKICAgICAgbW9kZWxOYW1lID0gdGhpcy5tb2RlbE5hbWVGcm9tUGF5bG9hZEtleShyZXNvdXJjZUhhc2gudHlwZSk7CiAgICAgIHVzZWRMb29rdXAgPSAnbW9kZWxOYW1lRnJvbVBheWxvYWRLZXknOwoKICAgICAgaWYgKCF0aGlzLnN0b3JlLl9oYXNNb2RlbEZvcihtb2RlbE5hbWUpKSB7CiAgICAgICAgKGZhbHNlICYmIEVtYmVyLndhcm4odGhpcy53YXJuTWVzc2FnZU5vTW9kZWxGb3JUeXBlKG1vZGVsTmFtZSwgcmVzb3VyY2VIYXNoLnR5cGUsIHVzZWRMb29rdXApLCBmYWxzZSwgewogICAgICAgICAgaWQ6ICdkcy5zZXJpYWxpemVyLm1vZGVsLWZvci10eXBlLW1pc3NpbmcnCiAgICAgICAgfSkpOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgbW9kZWxDbGFzcyA9IHRoaXMuc3RvcmUubW9kZWxGb3IobW9kZWxOYW1lKTsKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSB0aGlzLnN0b3JlLnNlcmlhbGl6ZXJGb3IobW9kZWxOYW1lKTsKCiAgICAgIHZhciBfc2VyaWFsaXplciRub3JtYWxpemUgPSBzZXJpYWxpemVyLm5vcm1hbGl6ZShtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpLAogICAgICAgICAgZGF0YSA9IF9zZXJpYWxpemVyJG5vcm1hbGl6ZS5kYXRhOwoKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIHB1c2hQYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAqLwogICAgcHVzaFBheWxvYWQ6IGZ1bmN0aW9uIHB1c2hQYXlsb2FkKHN0b3JlLCBwYXlsb2FkKSB7CiAgICAgIHZhciBub3JtYWxpemVkUGF5bG9hZCA9IHRoaXMuX25vcm1hbGl6ZURvY3VtZW50SGVscGVyKHBheWxvYWQpOwoKICAgICAgc3RvcmUucHVzaChub3JtYWxpemVkUGF5bG9hZCk7CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIF9ub3JtYWxpemVSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcGFyYW0ge0Jvb2xlYW59IGlzU2luZ2xlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICAgQHByaXZhdGUKICAgICovCiAgICBfbm9ybWFsaXplUmVzcG9uc2U6IGZ1bmN0aW9uIF9ub3JtYWxpemVSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSwgaXNTaW5nbGUpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRQYXlsb2FkID0gdGhpcy5fbm9ybWFsaXplRG9jdW1lbnRIZWxwZXIocGF5bG9hZCk7CgogICAgICByZXR1cm4gbm9ybWFsaXplZFBheWxvYWQ7CiAgICB9LAogICAgbm9ybWFsaXplUXVlcnlSZWNvcmRSZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplUXVlcnlSZWNvcmRSZXNwb25zZSgpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWQgPSB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgKGZhbHNlICYmICEoIUFycmF5LmlzQXJyYXkobm9ybWFsaXplZC5kYXRhKSkgJiYgRW1iZXIuYXNzZXJ0KCdFeHBlY3RlZCB0aGUgcHJpbWFyeSBkYXRhIHJldHVybmVkIGJ5IHRoZSBzZXJpYWxpemVyIGZvciBhIGBxdWVyeVJlY29yZGAgcmVzcG9uc2UgdG8gYmUgYSBzaW5nbGUgb2JqZWN0IGJ1dCBpbnN0ZWFkIGl0IHdhcyBhbiBhcnJheS4nLCAhQXJyYXkuaXNBcnJheShub3JtYWxpemVkLmRhdGEpLCB7CiAgICAgICAgaWQ6ICdkcy5zZXJpYWxpemVyLmpzb24tYXBpLnF1ZXJ5UmVjb3JkLWFycmF5LXJlc3BvbnNlJwogICAgICB9KSk7CiAgICAgIHJldHVybiBub3JtYWxpemVkOwogICAgfSwKICAgIGV4dHJhY3RBdHRyaWJ1dGVzOiBmdW5jdGlvbiBleHRyYWN0QXR0cmlidXRlcyhtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHZhciBhdHRyaWJ1dGVzID0ge307CgogICAgICBpZiAocmVzb3VyY2VIYXNoLmF0dHJpYnV0ZXMpIHsKICAgICAgICBtb2RlbENsYXNzLmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgdmFyIGF0dHJpYnV0ZUtleSA9IF90aGlzLmtleUZvckF0dHJpYnV0ZShrZXksICdkZXNlcmlhbGl6ZScpOwoKICAgICAgICAgIGlmIChyZXNvdXJjZUhhc2guYXR0cmlidXRlc1thdHRyaWJ1dGVLZXldICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgYXR0cmlidXRlc1trZXldID0gcmVzb3VyY2VIYXNoLmF0dHJpYnV0ZXNbYXR0cmlidXRlS2V5XTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoZmFsc2UKICAgICAgICAgIC8qIERFQlVHICovCiAgICAgICAgICApIHsKICAgICAgICAgICAgaWYgKHJlc291cmNlSGFzaC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZUtleV0gPT09IHVuZGVmaW5lZCAmJiByZXNvdXJjZUhhc2guYXR0cmlidXRlc1trZXldICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgRW1iZXIuYXNzZXJ0KCJZb3VyIHBheWxvYWQgZm9yICciICsgbW9kZWxDbGFzcy5tb2RlbE5hbWUgKyAiJyBjb250YWlucyAnIiArIGtleSArICInLCBidXQgeW91ciBzZXJpYWxpemVyIGlzIHNldHVwIHRvIGxvb2sgZm9yICciICsgYXR0cmlidXRlS2V5ICsgIicuIFRoaXMgaXMgbW9zdCBsaWtlbHkgYmVjYXVzZSBFbWJlciBEYXRhJ3MgSlNPTiBBUEkgc2VyaWFsaXplciBkYXNoZXJpemVzIGF0dHJpYnV0ZSBrZXlzIGJ5IGRlZmF1bHQuIFlvdSBzaG91bGQgc3ViY2xhc3MgSlNPTkFQSVNlcmlhbGl6ZXIgYW5kIGltcGxlbWVudCAna2V5Rm9yQXR0cmlidXRlKGtleSkgeyByZXR1cm4ga2V5OyB9JyB0byBwcmV2ZW50IEVtYmVyIERhdGEgZnJvbSBjdXN0b21pemluZyB5b3VyIGF0dHJpYnV0ZSBrZXlzLiIsIGZhbHNlKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIGF0dHJpYnV0ZXM7CiAgICB9LAoKICAgIC8qKgogICAgICAgUmV0dXJucyBhIHJlbGF0aW9uc2hpcCBmb3JtYXR0ZWQgYXMgYSBKU09OLUFQSSAicmVsYXRpb25zaGlwIG9iamVjdCIuCiAgICAgICAgaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdC8jZG9jdW1lbnQtcmVzb3VyY2Utb2JqZWN0LXJlbGF0aW9uc2hpcHMKICAgICAgICBAbWV0aG9kIGV4dHJhY3RSZWxhdGlvbnNoaXAKICAgICAgIEBwYXJhbSB7T2JqZWN0fSByZWxhdGlvbnNoaXBIYXNoCiAgICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgZXh0cmFjdFJlbGF0aW9uc2hpcDogZnVuY3Rpb24gZXh0cmFjdFJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXBIYXNoKSB7CiAgICAgIGlmIChFbWJlci50eXBlT2YocmVsYXRpb25zaGlwSGFzaC5kYXRhKSA9PT0gJ29iamVjdCcpIHsKICAgICAgICByZWxhdGlvbnNoaXBIYXNoLmRhdGEgPSB0aGlzLl9ub3JtYWxpemVSZWxhdGlvbnNoaXBEYXRhSGVscGVyKHJlbGF0aW9uc2hpcEhhc2guZGF0YSk7CiAgICAgIH0KCiAgICAgIGlmIChBcnJheS5pc0FycmF5KHJlbGF0aW9uc2hpcEhhc2guZGF0YSkpIHsKICAgICAgICB2YXIgcmV0ID0gbmV3IEFycmF5KHJlbGF0aW9uc2hpcEhhc2guZGF0YS5sZW5ndGgpOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbGF0aW9uc2hpcEhhc2guZGF0YS5sZW5ndGg7IGkrKykgewogICAgICAgICAgdmFyIGRhdGEgPSByZWxhdGlvbnNoaXBIYXNoLmRhdGFbaV07CiAgICAgICAgICByZXRbaV0gPSB0aGlzLl9ub3JtYWxpemVSZWxhdGlvbnNoaXBEYXRhSGVscGVyKGRhdGEpOwogICAgICAgIH0KCiAgICAgICAgcmVsYXRpb25zaGlwSGFzaC5kYXRhID0gcmV0OwogICAgICB9CgogICAgICByZXR1cm4gcmVsYXRpb25zaGlwSGFzaDsKICAgIH0sCgogICAgLyoqCiAgICAgICBSZXR1cm5zIHRoZSByZXNvdXJjZSdzIHJlbGF0aW9uc2hpcHMgZm9ybWF0dGVkIGFzIGEgSlNPTi1BUEkgInJlbGF0aW9uc2hpcHMgb2JqZWN0Ii4KICAgICAgICBodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0LyNkb2N1bWVudC1yZXNvdXJjZS1vYmplY3QtcmVsYXRpb25zaGlwcwogICAgICAgIEBtZXRob2QgZXh0cmFjdFJlbGF0aW9uc2hpcHMKICAgICAgIEBwYXJhbSB7T2JqZWN0fSBtb2RlbENsYXNzCiAgICAgICBAcGFyYW0ge09iamVjdH0gcmVzb3VyY2VIYXNoCiAgICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgZXh0cmFjdFJlbGF0aW9uc2hpcHM6IGZ1bmN0aW9uIGV4dHJhY3RSZWxhdGlvbnNoaXBzKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCkgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIHZhciByZWxhdGlvbnNoaXBzID0ge307CgogICAgICBpZiAocmVzb3VyY2VIYXNoLnJlbGF0aW9uc2hpcHMpIHsKICAgICAgICBtb2RlbENsYXNzLmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24gKGtleSwgcmVsYXRpb25zaGlwTWV0YSkgewogICAgICAgICAgdmFyIHJlbGF0aW9uc2hpcEtleSA9IF90aGlzMi5rZXlGb3JSZWxhdGlvbnNoaXAoa2V5LCByZWxhdGlvbnNoaXBNZXRhLmtpbmQsICdkZXNlcmlhbGl6ZScpOwoKICAgICAgICAgIGlmIChyZXNvdXJjZUhhc2gucmVsYXRpb25zaGlwc1tyZWxhdGlvbnNoaXBLZXldICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgdmFyIHJlbGF0aW9uc2hpcEhhc2ggPSByZXNvdXJjZUhhc2gucmVsYXRpb25zaGlwc1tyZWxhdGlvbnNoaXBLZXldOwogICAgICAgICAgICByZWxhdGlvbnNoaXBzW2tleV0gPSBfdGhpczIuZXh0cmFjdFJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXBIYXNoKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoZmFsc2UKICAgICAgICAgIC8qIERFQlVHICovCiAgICAgICAgICApIHsKICAgICAgICAgICAgaWYgKHJlc291cmNlSGFzaC5yZWxhdGlvbnNoaXBzW3JlbGF0aW9uc2hpcEtleV0gPT09IHVuZGVmaW5lZCAmJiByZXNvdXJjZUhhc2gucmVsYXRpb25zaGlwc1trZXldICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgRW1iZXIuYXNzZXJ0KCJZb3VyIHBheWxvYWQgZm9yICciICsgbW9kZWxDbGFzcy5tb2RlbE5hbWUgKyAiJyBjb250YWlucyAnIiArIGtleSArICInLCBidXQgeW91ciBzZXJpYWxpemVyIGlzIHNldHVwIHRvIGxvb2sgZm9yICciICsgcmVsYXRpb25zaGlwS2V5ICsgIicuIFRoaXMgaXMgbW9zdCBsaWtlbHkgYmVjYXVzZSBFbWJlciBEYXRhJ3MgSlNPTiBBUEkgc2VyaWFsaXplciBkYXNoZXJpemVzIHJlbGF0aW9uc2hpcCBrZXlzIGJ5IGRlZmF1bHQuIFlvdSBzaG91bGQgc3ViY2xhc3MgSlNPTkFQSVNlcmlhbGl6ZXIgYW5kIGltcGxlbWVudCAna2V5Rm9yUmVsYXRpb25zaGlwKGtleSkgeyByZXR1cm4ga2V5OyB9JyB0byBwcmV2ZW50IEVtYmVyIERhdGEgZnJvbSBjdXN0b21pemluZyB5b3VyIHJlbGF0aW9uc2hpcCBrZXlzLiIsIGZhbHNlKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcHM7CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIF9leHRyYWN0VHlwZQogICAgICBAcGFyYW0ge01vZGVsfSBtb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZXNvdXJjZUhhc2gKICAgICAgQHJldHVybiB7U3RyaW5nfQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9leHRyYWN0VHlwZTogZnVuY3Rpb24gX2V4dHJhY3RUeXBlKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCkgewogICAgICByZXR1cm4gdGhpcy5tb2RlbE5hbWVGcm9tUGF5bG9hZEtleShyZXNvdXJjZUhhc2gudHlwZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBEYXNoZXJpemVzIGFuZCBzaW5ndWxhcml6ZXMgdGhlIG1vZGVsIG5hbWUgaW4gdGhlIHBheWxvYWQgdG8gbWF0Y2gKICAgICAgdGhlIGZvcm1hdCBFbWJlciBEYXRhIHVzZXMgaW50ZXJuYWxseSBmb3IgdGhlIG1vZGVsIG5hbWUuCiAgICAgICBGb3IgZXhhbXBsZSB0aGUga2V5IGBwb3N0c2Agd291bGQgYmUgY29udmVydGVkIHRvIGBwb3N0YCBhbmQgdGhlCiAgICAgIGtleSBgc3R1ZGVudEFzc2VzbWVudHNgIHdvdWxkIGJlIGNvbnZlcnRlZCB0byBgc3R1ZGVudC1hc3Nlc21lbnRgLgogICAgICAgQG1ldGhvZCBtb2RlbE5hbWVGcm9tUGF5bG9hZEtleQogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5CiAgICAgIEByZXR1cm4ge1N0cmluZ30gdGhlIG1vZGVsJ3MgbW9kZWxOYW1lCiAgICAqLwogICAgLy8gVE9ETyBAZGVwcmVjYXRlZCBVc2UgbW9kZWxOYW1lRnJvbVBheWxvYWRUeXBlIGluc3RlYWQKICAgIG1vZGVsTmFtZUZyb21QYXlsb2FkS2V5OiBmdW5jdGlvbiBtb2RlbE5hbWVGcm9tUGF5bG9hZEtleShrZXkpIHsKICAgICAgcmV0dXJuICgwLCBfZW1iZXJJbmZsZWN0b3Iuc2luZ3VsYXJpemUpKCgwLCBfc3RvcmUubm9ybWFsaXplTW9kZWxOYW1lKShrZXkpKTsKICAgIH0sCgogICAgLyoqCiAgICAgIENvbnZlcnRzIHRoZSBtb2RlbCBuYW1lIHRvIGEgcGx1cmFsaXplZCB2ZXJzaW9uIG9mIHRoZSBtb2RlbCBuYW1lLgogICAgICAgRm9yIGV4YW1wbGUgYHBvc3RgIHdvdWxkIGJlIGNvbnZlcnRlZCB0byBgcG9zdHNgIGFuZAogICAgICBgc3R1ZGVudC1hc3Nlc21lbnRgIHdvdWxkIGJlIGNvbnZlcnRlZCB0byBgc3R1ZGVudC1hc3Nlc21lbnRzYC4KICAgICAgIEBtZXRob2QgcGF5bG9hZEtleUZyb21Nb2RlbE5hbWUKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcmV0dXJuIHtTdHJpbmd9CiAgICAqLwogICAgLy8gVE9ETyBAZGVwcmVjYXRlZCBVc2UgcGF5bG9hZFR5cGVGcm9tTW9kZWxOYW1lIGluc3RlYWQKICAgIHBheWxvYWRLZXlGcm9tTW9kZWxOYW1lOiBmdW5jdGlvbiBwYXlsb2FkS2V5RnJvbU1vZGVsTmFtZShtb2RlbE5hbWUpIHsKICAgICAgcmV0dXJuICgwLCBfZW1iZXJJbmZsZWN0b3IucGx1cmFsaXplKShtb2RlbE5hbWUpOwogICAgfSwKICAgIG5vcm1hbGl6ZTogZnVuY3Rpb24gbm9ybWFsaXplKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCkgewogICAgICBpZiAocmVzb3VyY2VIYXNoLmF0dHJpYnV0ZXMpIHsKICAgICAgICB0aGlzLm5vcm1hbGl6ZVVzaW5nRGVjbGFyZWRNYXBwaW5nKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaC5hdHRyaWJ1dGVzKTsKICAgICAgfQoKICAgICAgaWYgKHJlc291cmNlSGFzaC5yZWxhdGlvbnNoaXBzKSB7CiAgICAgICAgdGhpcy5ub3JtYWxpemVVc2luZ0RlY2xhcmVkTWFwcGluZyhtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gucmVsYXRpb25zaGlwcyk7CiAgICAgIH0KCiAgICAgIHZhciBkYXRhID0gewogICAgICAgIGlkOiB0aGlzLmV4dHJhY3RJZChtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpLAogICAgICAgIHR5cGU6IHRoaXMuX2V4dHJhY3RUeXBlKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCksCiAgICAgICAgYXR0cmlidXRlczogdGhpcy5leHRyYWN0QXR0cmlidXRlcyhtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpLAogICAgICAgIHJlbGF0aW9uc2hpcHM6IHRoaXMuZXh0cmFjdFJlbGF0aW9uc2hpcHMobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKQogICAgICB9OwogICAgICB0aGlzLmFwcGx5VHJhbnNmb3Jtcyhtb2RlbENsYXNzLCBkYXRhLmF0dHJpYnV0ZXMpOwogICAgICByZXR1cm4gewogICAgICAgIGRhdGE6IGRhdGEKICAgICAgfTsKICAgIH0sCgogICAgLyoqCiAgICAgIGBrZXlGb3JBdHRyaWJ1dGVgIGNhbiBiZSB1c2VkIHRvIGRlZmluZSBydWxlcyBmb3IgaG93IHRvIGNvbnZlcnQgYW4KICAgICAgYXR0cmlidXRlIG5hbWUgaW4geW91ciBtb2RlbCB0byBhIGtleSBpbiB5b3VyIEpTT04uCiAgICAgIEJ5IGRlZmF1bHQgYEpTT05BUElTZXJpYWxpemVyYCBmb2xsb3dzIHRoZSBmb3JtYXQgdXNlZCBvbiB0aGUgZXhhbXBsZXMgb2YKICAgICAgaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdCBhbmQgdXNlcyBkYXNoZXMgYXMgdGhlIHdvcmQgc2VwYXJhdG9yIGluIHRoZSBKU09OCiAgICAgIGF0dHJpYnV0ZSBrZXlzLgogICAgICAgVGhpcyBiZWhhdmlvdXIgY2FuIGJlIGVhc2lseSBjdXN0b21pemVkIGJ5IGV4dGVuZGluZyB0aGlzIG1ldGhvZC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgSlNPTkFQSVNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uLWFwaSc7CiAgICAgIGltcG9ydCB7IGRhc2hlcml6ZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTkFQSVNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBrZXlGb3JBdHRyaWJ1dGUoYXR0ciwgbWV0aG9kKSB7CiAgICAgICAgICByZXR1cm4gZGFzaGVyaXplKGF0dHIpLnRvVXBwZXJDYXNlKCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGtleUZvckF0dHJpYnV0ZQogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QKICAgICAgQHJldHVybiB7U3RyaW5nfSBub3JtYWxpemVkIGtleQogICAgKi8KICAgIGtleUZvckF0dHJpYnV0ZTogZnVuY3Rpb24ga2V5Rm9yQXR0cmlidXRlKGtleSwgbWV0aG9kKSB7CiAgICAgIHJldHVybiBFbWJlci5TdHJpbmcuZGFzaGVyaXplKGtleSk7CiAgICB9LAoKICAgIC8qKgogICAgIGBrZXlGb3JSZWxhdGlvbnNoaXBgIGNhbiBiZSB1c2VkIHRvIGRlZmluZSBhIGN1c3RvbSBrZXkgd2hlbgogICAgIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHJlbGF0aW9uc2hpcCBwcm9wZXJ0aWVzLgogICAgIEJ5IGRlZmF1bHQgYEpTT05BUElTZXJpYWxpemVyYCBmb2xsb3dzIHRoZSBmb3JtYXQgdXNlZCBvbiB0aGUgZXhhbXBsZXMgb2YKICAgICBodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0IGFuZCB1c2VzIGRhc2hlcyBhcyB3b3JkIHNlcGFyYXRvcnMgaW4KICAgICByZWxhdGlvbnNoaXAgcHJvcGVydGllcy4KICAgICAgVGhpcyBiZWhhdmlvdXIgY2FuIGJlIGVhc2lseSBjdXN0b21pemVkIGJ5IGV4dGVuZGluZyB0aGlzIG1ldGhvZC4KICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL3Bvc3QuanMKICAgICAgaW1wb3J0IEpTT05BUElTZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbi1hcGknOwogICAgICBpbXBvcnQgeyB1bmRlcnNjb3JlIH0gZnJvbSAnQGVtYmVyL3N0cmluZyc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OQVBJU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIGtleUZvclJlbGF0aW9uc2hpcChrZXksIHJlbGF0aW9uc2hpcCwgbWV0aG9kKSB7CiAgICAgICAgICByZXR1cm4gdW5kZXJzY29yZShrZXkpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgIEBtZXRob2Qga2V5Rm9yUmVsYXRpb25zaGlwCiAgICAgQHBhcmFtIHtTdHJpbmd9IGtleQogICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlQ2xhc3MKICAgICBAcGFyYW0ge1N0cmluZ30gbWV0aG9kCiAgICAgQHJldHVybiB7U3RyaW5nfSBub3JtYWxpemVkIGtleQogICAgKi8KICAgIGtleUZvclJlbGF0aW9uc2hpcDogZnVuY3Rpb24ga2V5Rm9yUmVsYXRpb25zaGlwKGtleSwgdHlwZUNsYXNzLCBtZXRob2QpIHsKICAgICAgcmV0dXJuIEVtYmVyLlN0cmluZy5kYXNoZXJpemUoa2V5KTsKICAgIH0sCiAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIHNlcmlhbGl6ZShzbmFwc2hvdCwgb3B0aW9ucykgewogICAgICB2YXIgZGF0YSA9IHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICBkYXRhLnR5cGUgPSB0aGlzLnBheWxvYWRLZXlGcm9tTW9kZWxOYW1lKHNuYXBzaG90Lm1vZGVsTmFtZSk7CiAgICAgIHJldHVybiB7CiAgICAgICAgZGF0YTogZGF0YQogICAgICB9OwogICAgfSwKICAgIHNlcmlhbGl6ZUF0dHJpYnV0ZTogZnVuY3Rpb24gc2VyaWFsaXplQXR0cmlidXRlKHNuYXBzaG90LCBqc29uLCBrZXksIGF0dHJpYnV0ZSkgewogICAgICB2YXIgdHlwZSA9IGF0dHJpYnV0ZS50eXBlOwoKICAgICAgaWYgKHRoaXMuX2NhblNlcmlhbGl6ZShrZXkpKSB7CiAgICAgICAganNvbi5hdHRyaWJ1dGVzID0ganNvbi5hdHRyaWJ1dGVzIHx8IHt9OwogICAgICAgIHZhciB2YWx1ZSA9IHNuYXBzaG90LmF0dHIoa2V5KTsKCiAgICAgICAgaWYgKHR5cGUpIHsKICAgICAgICAgIHZhciB0cmFuc2Zvcm0gPSB0aGlzLnRyYW5zZm9ybUZvcih0eXBlKTsKICAgICAgICAgIHZhbHVlID0gdHJhbnNmb3JtLnNlcmlhbGl6ZSh2YWx1ZSwgYXR0cmlidXRlLm9wdGlvbnMpOwogICAgICAgIH0KCiAgICAgICAgdmFyIHBheWxvYWRLZXkgPSB0aGlzLl9nZXRNYXBwZWRLZXkoa2V5LCBzbmFwc2hvdC50eXBlKTsKCiAgICAgICAgaWYgKHBheWxvYWRLZXkgPT09IGtleSkgewogICAgICAgICAgcGF5bG9hZEtleSA9IHRoaXMua2V5Rm9yQXR0cmlidXRlKGtleSwgJ3NlcmlhbGl6ZScpOwogICAgICAgIH0KCiAgICAgICAganNvbi5hdHRyaWJ1dGVzW3BheWxvYWRLZXldID0gdmFsdWU7CiAgICAgIH0KICAgIH0sCiAgICBzZXJpYWxpemVCZWxvbmdzVG86IGZ1bmN0aW9uIHNlcmlhbGl6ZUJlbG9uZ3NUbyhzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBrZXkgPSByZWxhdGlvbnNoaXAua2V5OwoKICAgICAgaWYgKHRoaXMuX2NhblNlcmlhbGl6ZShrZXkpKSB7CiAgICAgICAgdmFyIGJlbG9uZ3NUbyA9IHNuYXBzaG90LmJlbG9uZ3NUbyhrZXkpOwogICAgICAgIHZhciBiZWxvbmdzVG9Jc05vdE5ldzsKCiAgICAgICAgaWYgKF9jYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICAgIGJlbG9uZ3NUb0lzTm90TmV3ID0gYmVsb25nc1RvICYmICFiZWxvbmdzVG8uaXNOZXc7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGJlbG9uZ3NUb0lzTm90TmV3ID0gYmVsb25nc1RvICYmIGJlbG9uZ3NUby5yZWNvcmQgJiYgIWJlbG9uZ3NUby5yZWNvcmQuZ2V0KCdpc05ldycpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGJlbG9uZ3NUbyA9PT0gbnVsbCB8fCBiZWxvbmdzVG9Jc05vdE5ldykgewogICAgICAgICAganNvbi5yZWxhdGlvbnNoaXBzID0ganNvbi5yZWxhdGlvbnNoaXBzIHx8IHt9OwoKICAgICAgICAgIHZhciBwYXlsb2FkS2V5ID0gdGhpcy5fZ2V0TWFwcGVkS2V5KGtleSwgc25hcHNob3QudHlwZSk7CgogICAgICAgICAgaWYgKHBheWxvYWRLZXkgPT09IGtleSkgewogICAgICAgICAgICBwYXlsb2FkS2V5ID0gdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXAoa2V5LCAnYmVsb25nc1RvJywgJ3NlcmlhbGl6ZScpOwogICAgICAgICAgfQoKICAgICAgICAgIHZhciBkYXRhID0gbnVsbDsKCiAgICAgICAgICBpZiAoYmVsb25nc1RvKSB7CiAgICAgICAgICAgIHZhciBwYXlsb2FkVHlwZSA9IHRoaXMucGF5bG9hZEtleUZyb21Nb2RlbE5hbWUoYmVsb25nc1RvLm1vZGVsTmFtZSk7CiAgICAgICAgICAgIGRhdGEgPSB7CiAgICAgICAgICAgICAgdHlwZTogcGF5bG9hZFR5cGUsCiAgICAgICAgICAgICAgaWQ6IGJlbG9uZ3NUby5pZAogICAgICAgICAgICB9OwogICAgICAgICAgfQoKICAgICAgICAgIGpzb24ucmVsYXRpb25zaGlwc1twYXlsb2FkS2V5XSA9IHsKICAgICAgICAgICAgZGF0YTogZGF0YQogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgIH0KICAgIH0sCiAgICBzZXJpYWxpemVIYXNNYW55OiBmdW5jdGlvbiBzZXJpYWxpemVIYXNNYW55KHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIGtleSA9IHJlbGF0aW9uc2hpcC5rZXk7CgogICAgICBpZiAodGhpcy5zaG91bGRTZXJpYWxpemVIYXNNYW55KHNuYXBzaG90LCBrZXksIHJlbGF0aW9uc2hpcCkpIHsKICAgICAgICB2YXIgaGFzTWFueSA9IHNuYXBzaG90Lmhhc01hbnkoa2V5KTsKCiAgICAgICAgaWYgKGhhc01hbnkgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAganNvbi5yZWxhdGlvbnNoaXBzID0ganNvbi5yZWxhdGlvbnNoaXBzIHx8IHt9OwoKICAgICAgICAgIHZhciBwYXlsb2FkS2V5ID0gdGhpcy5fZ2V0TWFwcGVkS2V5KGtleSwgc25hcHNob3QudHlwZSk7CgogICAgICAgICAgaWYgKHBheWxvYWRLZXkgPT09IGtleSAmJiB0aGlzLmtleUZvclJlbGF0aW9uc2hpcCkgewogICAgICAgICAgICBwYXlsb2FkS2V5ID0gdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXAoa2V5LCAnaGFzTWFueScsICdzZXJpYWxpemUnKTsKICAgICAgICAgIH0gLy8gb25seSBzZXJpYWxpemUgaGFzIG1hbnkgcmVsYXRpb25zaGlwcyB0aGF0IGFyZSBub3QgbmV3CgoKICAgICAgICAgIHZhciBub25OZXdIYXNNYW55ID0gaGFzTWFueS5maWx0ZXIoZnVuY3Rpb24gKGl0ZW0pIHsKICAgICAgICAgICAgcmV0dXJuIGl0ZW0ucmVjb3JkICYmICFpdGVtLnJlY29yZC5nZXQoJ2lzTmV3Jyk7CiAgICAgICAgICB9KTsKICAgICAgICAgIHZhciBkYXRhID0gbmV3IEFycmF5KG5vbk5ld0hhc01hbnkubGVuZ3RoKTsKCiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vbk5ld0hhc01hbnkubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgdmFyIGl0ZW0gPSBoYXNNYW55W2ldOwogICAgICAgICAgICB2YXIgcGF5bG9hZFR5cGUgPSB0aGlzLnBheWxvYWRLZXlGcm9tTW9kZWxOYW1lKGl0ZW0ubW9kZWxOYW1lKTsKICAgICAgICAgICAgZGF0YVtpXSA9IHsKICAgICAgICAgICAgICB0eXBlOiBwYXlsb2FkVHlwZSwKICAgICAgICAgICAgICBpZDogaXRlbS5pZAogICAgICAgICAgICB9OwogICAgICAgICAgfQoKICAgICAgICAgIGpzb24ucmVsYXRpb25zaGlwc1twYXlsb2FkS2V5XSA9IHsKICAgICAgICAgICAgZGF0YTogZGF0YQogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9KTsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIEpTT05BUElTZXJpYWxpemVyLnJlb3Blbih7CiAgICAgIHdpbGxNZXJnZU1peGluOiBmdW5jdGlvbiB3aWxsTWVyZ2VNaXhpbihwcm9wcykgewogICAgICAgIHZhciBjb25zdHJ1Y3RvciA9IHRoaXMuY29uc3RydWN0b3I7CiAgICAgICAgKGZhbHNlICYmIEVtYmVyLndhcm4oIllvdSd2ZSBkZWZpbmVkICdleHRyYWN0TWV0YScgaW4gIiArIGNvbnN0cnVjdG9yLnRvU3RyaW5nKCkgKyAiIHdoaWNoIGlzIG5vdCB1c2VkIGZvciBzZXJpYWxpemVycyBleHRlbmRpbmcgSlNPTkFQSVNlcmlhbGl6ZXIuIFJlYWQgbW9yZSBhdCBodHRwczovL2FwaS5lbWJlcmpzLmNvbS9lbWJlci1kYXRhL3JlbGVhc2UvY2xhc3Nlcy9KU09OQVBJU2VyaWFsaXplciBvbiBob3cgdG8gY3VzdG9taXplIG1ldGEgd2hlbiB1c2luZyBKU09OIEFQSS4iLCBFbWJlci5pc05vbmUocHJvcHMuZXh0cmFjdE1ldGEpIHx8IHByb3BzLmV4dHJhY3RNZXRhID09PSBfanNvbi5kZWZhdWx0LnByb3RvdHlwZS5leHRyYWN0TWV0YSwgewogICAgICAgICAgaWQ6ICdkcy5zZXJpYWxpemVyLmpzb24tYXBpLmV4dHJhY3RNZXRhJwogICAgICAgIH0pKTsKICAgICAgICAoZmFsc2UgJiYgRW1iZXIud2FybignVGhlIEpTT05BUElTZXJpYWxpemVyIGRvZXMgbm90IHdvcmsgd2l0aCB0aGUgRW1iZWRkZWRSZWNvcmRzTWl4aW4gYmVjYXVzZSB0aGUgSlNPTiBBUEkgc3BlYyBkb2VzIG5vdCBkZXNjcmliZSBob3cgdG8gZm9ybWF0IGVtYmVkZGVkIHJlc291cmNlcy4nLCAhcHJvcHMuaXNFbWJlZGRlZFJlY29yZHNNaXhpbiwgewogICAgICAgICAgaWQ6ICdkcy5zZXJpYWxpemVyLmVtYmVkZGVkLXJlY29yZHMtbWl4aW4tbm90LXN1cHBvcnRlZCcKICAgICAgICB9KSk7CiAgICAgIH0sCiAgICAgIHdhcm5NZXNzYWdlRm9yVW5kZWZpbmVkVHlwZTogZnVuY3Rpb24gd2Fybk1lc3NhZ2VGb3JVbmRlZmluZWRUeXBlKCkgewogICAgICAgIHJldHVybiAnRW5jb3VudGVyZWQgYSByZXNvdXJjZSBvYmplY3Qgd2l0aCBhbiB1bmRlZmluZWQgdHlwZSAocmVzb2x2ZWQgcmVzb3VyY2UgdXNpbmcgJyArIHRoaXMuY29uc3RydWN0b3IudG9TdHJpbmcoKSArICcpJzsKICAgICAgfSwKICAgICAgd2Fybk1lc3NhZ2VOb01vZGVsRm9yVHlwZTogZnVuY3Rpb24gd2Fybk1lc3NhZ2VOb01vZGVsRm9yVHlwZShtb2RlbE5hbWUsIG9yaWdpbmFsVHlwZSwgdXNlZExvb2t1cCkgewogICAgICAgIHJldHVybiAiRW5jb3VudGVyZWQgYSByZXNvdXJjZSBvYmplY3Qgd2l0aCB0eXBlIFwiIiArIG9yaWdpbmFsVHlwZSArICJcIiwgYnV0IG5vIG1vZGVsIHdhcyBmb3VuZCBmb3IgbW9kZWwgbmFtZSBcIiIgKyBtb2RlbE5hbWUgKyAiXCIgKHJlc29sdmVkIG1vZGVsIG5hbWUgdXNpbmcgJyIgKyB0aGlzLmNvbnN0cnVjdG9yLnRvU3RyaW5nKCkgKyAiLiIgKyB1c2VkTG9va3VwICsgIihcIiIgKyBvcmlnaW5hbFR5cGUgKyAiXCIpJykuIjsKICAgICAgfQogICAgfSk7CiAgfQoKICB2YXIgX2RlZmF1bHQgPSBKU09OQVBJU2VyaWFsaXplcjsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwo7ZGVmaW5lKCJAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24iLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplciIsICJAZW1iZXItZGF0YS9zdG9yZS8tcHJpdmF0ZSIsICJAZW1iZXItZGF0YS9zZXJpYWxpemVyLy1wcml2YXRlIiwgIkBlbWJlci1kYXRhL3N0b3JlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3NlcmlhbGl6ZXIsIF9wcml2YXRlLCBfcHJpdmF0ZTIsIF9zdG9yZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3NlcmlhbGl6ZXIKICAqLwoKICAvKioKICAgIEVtYmVyIERhdGEgMi4wIFNlcmlhbGl6ZXI6CiAgCiAgICBJbiBFbWJlciBEYXRhIGEgU2VyaWFsaXplciBpcyB1c2VkIHRvIHNlcmlhbGl6ZSBhbmQgZGVzZXJpYWxpemUKICAgIHJlY29yZHMgd2hlbiB0aGV5IGFyZSB0cmFuc2ZlcnJlZCBpbiBhbmQgb3V0IG9mIGFuIGV4dGVybmFsIHNvdXJjZS4KICAgIFRoaXMgcHJvY2VzcyBpbnZvbHZlcyBub3JtYWxpemluZyBwcm9wZXJ0eSBuYW1lcywgdHJhbnNmb3JtaW5nCiAgICBhdHRyaWJ1dGUgdmFsdWVzIGFuZCBzZXJpYWxpemluZyByZWxhdGlvbnNoaXBzLgogIAogICAgQnkgZGVmYXVsdCwgRW1iZXIgRGF0YSB1c2VzIGFuZCByZWNvbW1lbmRzIHRoZSBgSlNPTkFQSVNlcmlhbGl6ZXJgLgogIAogICAgYEpTT05TZXJpYWxpemVyYCBpcyB1c2VmdWwgZm9yIHNpbXBsZXIgb3IgbGVnYWN5IGJhY2tlbmRzIHRoYXQgbWF5CiAgICBub3Qgc3VwcG9ydCB0aGUgaHR0cDovL2pzb25hcGkub3JnLyBzcGVjLgogIAogICAgRm9yIGV4YW1wbGUsIGdpdmVuIHRoZSBmb2xsb3dpbmcgYFVzZXJgIG1vZGVsIGFuZCBKU09OIHBheWxvYWQ6CiAgCiAgICBgYGBhcHAvbW9kZWxzL3VzZXIuanMKICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyLCBiZWxvbmdzVG8sIGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBmcmllbmRzOiBoYXNNYW55KCd1c2VyJyksCiAgICAgIGhvdXNlOiBiZWxvbmdzVG8oJ2xvY2F0aW9uJyksCiAgCiAgICAgIG5hbWU6IGF0dHIoJ3N0cmluZycpCiAgICB9KTsKICAgIGBgYAogIAogICAgYGBganMKICAgIHsKICAgICAgaWQ6IDEsCiAgICAgIG5hbWU6ICdTZWJhc3RpYW4nLAogICAgICBmcmllbmRzOiBbMywgNF0sCiAgICAgIGxpbmtzOiB7CiAgICAgICAgaG91c2U6ICcvaG91c2VzL2xlZmthZGEnCiAgICAgIH0KICAgIH0KICAgIGBgYAogIAogICAgYEpTT05TZXJpYWxpemVyYCB3aWxsIG5vcm1hbGl6ZSB0aGUgSlNPTiBwYXlsb2FkIHRvIHRoZSBKU09OIEFQSSBmb3JtYXQgdGhhdCB0aGUKICAgIEVtYmVyIERhdGEgc3RvcmUgZXhwZWN0cy4KICAKICAgIFlvdSBjYW4gY3VzdG9taXplIGhvdyBKU09OU2VyaWFsaXplciBwcm9jZXNzZXMgaXRzIHBheWxvYWQgYnkgcGFzc2luZyBvcHRpb25zIGluCiAgICB0aGUgYGF0dHJzYCBoYXNoIG9yIGJ5IHN1YmNsYXNzaW5nIHRoZSBgSlNPTlNlcmlhbGl6ZXJgIGFuZCBvdmVycmlkaW5nIGhvb2tzOgogIAogICAgICAtIFRvIGN1c3RvbWl6ZSBob3cgYSBzaW5nbGUgcmVjb3JkIGlzIG5vcm1hbGl6ZWQsIHVzZSB0aGUgYG5vcm1hbGl6ZWAgaG9vay4KICAgICAgLSBUbyBjdXN0b21pemUgaG93IGBKU09OU2VyaWFsaXplcmAgbm9ybWFsaXplcyB0aGUgd2hvbGUgc2VydmVyIHJlc3BvbnNlLCB1c2UgdGhlCiAgICAgICAgYG5vcm1hbGl6ZVJlc3BvbnNlYCBob29rLgogICAgICAtIFRvIGN1c3RvbWl6ZSBob3cgYEpTT05TZXJpYWxpemVyYCBub3JtYWxpemVzIGEgc3BlY2lmaWMgcmVzcG9uc2UgZnJvbSB0aGUgc2VydmVyLAogICAgICAgIHVzZSBvbmUgb2YgdGhlIG1hbnkgc3BlY2lmaWMgYG5vcm1hbGl6ZVJlc3BvbnNlYCBob29rcy4KICAgICAgLSBUbyBjdXN0b21pemUgaG93IGBKU09OU2VyaWFsaXplcmAgbm9ybWFsaXplcyB5b3VyIGlkLCBhdHRyaWJ1dGVzIG9yIHJlbGF0aW9uc2hpcHMsCiAgICAgICAgdXNlIHRoZSBgZXh0cmFjdElkYCwgYGV4dHJhY3RBdHRyaWJ1dGVzYCBhbmQgYGV4dHJhY3RSZWxhdGlvbnNoaXBzYCBob29rcy4KICAKICAgIFRoZSBgSlNPTlNlcmlhbGl6ZXJgIG5vcm1hbGl6YXRpb24gcHJvY2VzcyBmb2xsb3dzIHRoZXNlIHN0ZXBzOgogIAogICAgICAtIGBub3JtYWxpemVSZXNwb25zZWAgLSBlbnRyeSBtZXRob2QgdG8gdGhlIHNlcmlhbGl6ZXIuCiAgICAgIC0gYG5vcm1hbGl6ZUNyZWF0ZVJlY29yZFJlc3BvbnNlYCAtIGEgYG5vcm1hbGl6ZVJlc3BvbnNlYCBmb3IgYSBzcGVjaWZpYyBvcGVyYXRpb24gaXMgY2FsbGVkLgogICAgICAtIGBub3JtYWxpemVTaW5nbGVSZXNwb25zZWB8YG5vcm1hbGl6ZUFycmF5UmVzcG9uc2VgIC0gZm9yIG1ldGhvZHMgbGlrZSBgY3JlYXRlUmVjb3JkYCB3ZSBleHBlY3QKICAgICAgICBhIHNpbmdsZSByZWNvcmQgYmFjaywgd2hpbGUgZm9yIG1ldGhvZHMgbGlrZSBgZmluZEFsbGAgd2UgZXhwZWN0IG11bHRpcGxlIHJlY29yZHMgYmFjay4KICAgICAgLSBgbm9ybWFsaXplYCAtIGBub3JtYWxpemVBcnJheWAgaXRlcmF0ZXMgYW5kIGNhbGxzIGBub3JtYWxpemVgIGZvciBlYWNoIG9mIGl0cyByZWNvcmRzIHdoaWxlIGBub3JtYWxpemVTaW5nbGVgCiAgICAgICAgY2FsbHMgaXQgb25jZS4gVGhpcyBpcyB0aGUgbWV0aG9kIHlvdSBtb3N0IGxpa2VseSB3YW50IHRvIHN1YmNsYXNzLgogICAgICAtIGBleHRyYWN0SWRgIHwgYGV4dHJhY3RBdHRyaWJ1dGVzYCB8IGBleHRyYWN0UmVsYXRpb25zaGlwc2AgLSBgbm9ybWFsaXplYCBkZWxlZ2F0ZXMgdG8gdGhlc2UgbWV0aG9kcyB0bwogICAgICAgIHR1cm4gdGhlIHJlY29yZCBwYXlsb2FkIGludG8gdGhlIEpTT04gQVBJIGZvcm1hdC4KICAKICAgIEBjbGFzcyBKU09OU2VyaWFsaXplcgogICAgQGV4dGVuZHMgU2VyaWFsaXplcgogICovCiAgdmFyIEpTT05TZXJpYWxpemVyID0gX3NlcmlhbGl6ZXIuZGVmYXVsdC5leHRlbmQoewogICAgLyoqCiAgICAgIFRoZSBgcHJpbWFyeUtleWAgaXMgdXNlZCB3aGVuIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nCiAgICAgIGRhdGEuIEVtYmVyIERhdGEgYWx3YXlzIHVzZXMgdGhlIGBpZGAgcHJvcGVydHkgdG8gc3RvcmUgdGhlIGlkIG9mCiAgICAgIHRoZSByZWNvcmQuIFRoZSBleHRlcm5hbCBzb3VyY2UgbWF5IG5vdCBhbHdheXMgZm9sbG93IHRoaXMKICAgICAgY29udmVudGlvbi4gSW4gdGhlc2UgY2FzZXMgaXQgaXMgdXNlZnVsIHRvIG92ZXJyaWRlIHRoZQogICAgICBgcHJpbWFyeUtleWAgcHJvcGVydHkgdG8gbWF0Y2ggdGhlIGBwcmltYXJ5S2V5YCBvZiB5b3VyIGV4dGVybmFsCiAgICAgIHN0b3JlLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBKU09OU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24nOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBwcmltYXJ5S2V5OiAnX2lkJwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAcHJvcGVydHkgcHJpbWFyeUtleQogICAgICBAdHlwZSB7U3RyaW5nfQogICAgICBAZGVmYXVsdCAnaWQnCiAgICAqLwogICAgcHJpbWFyeUtleTogJ2lkJywKCiAgICAvKioKICAgICAgVGhlIGBhdHRyc2Agb2JqZWN0IGNhbiBiZSB1c2VkIHRvIGRlY2xhcmUgYSBzaW1wbGUgbWFwcGluZyBiZXR3ZWVuCiAgICAgIHByb3BlcnR5IG5hbWVzIG9uIGBNb2RlbGAgcmVjb3JkcyBhbmQgcGF5bG9hZCBrZXlzIGluIHRoZQogICAgICBzZXJpYWxpemVkIEpTT04gb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgcmVjb3JkLiBBbiBvYmplY3Qgd2l0aCB0aGUKICAgICAgcHJvcGVydHkgYGtleWAgY2FuIGFsc28gYmUgdXNlZCB0byBkZXNpZ25hdGUgdGhlIGF0dHJpYnV0ZSdzIGtleSBvbgogICAgICB0aGUgcmVzcG9uc2UgcGF5bG9hZC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9tb2RlbHMvcGVyc29uLmpzCiAgICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICBmaXJzdE5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICAgIGxhc3ROYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgICBvY2N1cGF0aW9uOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgICBhZG1pbjogYXR0cignYm9vbGVhbicpCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9wZXJzb24uanMKICAgICAgaW1wb3J0IEpTT05TZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIGF0dHJzOiB7CiAgICAgICAgICBhZG1pbjogJ2lzX2FkbWluJywKICAgICAgICAgIG9jY3VwYXRpb246IHsga2V5OiAnY2FyZWVyJyB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBZb3UgY2FuIGFsc28gcmVtb3ZlIGF0dHJpYnV0ZXMgYW5kIHJlbGF0aW9uc2hpcHMgYnkgc2V0dGluZyB0aGUgYHNlcmlhbGl6ZWAKICAgICAga2V5IHRvIGBmYWxzZWAgaW4geW91ciBtYXBwaW5nIG9iamVjdC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9wZXJzb24uanMKICAgICAgaW1wb3J0IEpTT05TZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIGF0dHJzOiB7CiAgICAgICAgICBhZG1pbjogeyBzZXJpYWxpemU6IGZhbHNlIH0sCiAgICAgICAgICBvY2N1cGF0aW9uOiB7IGtleTogJ2NhcmVlcicgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgV2hlbiBzZXJpYWxpemVkOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICB7CiAgICAgICAgImZpcnN0TmFtZSI6ICJIYXJyeSIsCiAgICAgICAgImxhc3ROYW1lIjogIkhvdWRpbmkiLAogICAgICAgICJjYXJlZXIiOiAibWFnaWNpYW4iCiAgICAgIH0KICAgICAgYGBgCiAgICAgICBOb3RlIHRoYXQgdGhlIGBhZG1pbmAgaXMgbm93IG5vdCBpbmNsdWRlZCBpbiB0aGUgcGF5bG9hZC4KICAgICAgIFNldHRpbmcgYHNlcmlhbGl6ZWAgdG8gYHRydWVgIGVuZm9yY2VzIHNlcmlhbGl6YXRpb24gZm9yIGhhc01hbnkKICAgICAgcmVsYXRpb25zaGlwcyBldmVuIGlmIGl0J3MgbmVpdGhlciBhIG1hbnktdG8tbWFueSBub3IgbWFueS10by1ub25lCiAgICAgIHJlbGF0aW9uc2hpcC4KICAgICAgIEBwcm9wZXJ0eSBhdHRycwogICAgICBAdHlwZSB7T2JqZWN0fQogICAgKi8KICAgIG1lcmdlZFByb3BlcnRpZXM6IFsnYXR0cnMnXSwKCiAgICAvKioKICAgICBHaXZlbiBhIHN1YmNsYXNzIG9mIGBNb2RlbGAgYW5kIGEgSlNPTiBvYmplY3QgdGhpcyBtZXRob2Qgd2lsbAogICAgIGl0ZXJhdGUgdGhyb3VnaCBlYWNoIGF0dHJpYnV0ZSBvZiB0aGUgYE1vZGVsYCBhbmQgaW52b2tlIHRoZQogICAgIGBUcmFuc2Zvcm0jZGVzZXJpYWxpemVgIG1ldGhvZCBvbiB0aGUgbWF0Y2hpbmcgcHJvcGVydHkgb2YgdGhlCiAgICAgSlNPTiBvYmplY3QuICBUaGlzIG1ldGhvZCBpcyB0eXBpY2FsbHkgY2FsbGVkIGFmdGVyIHRoZQogICAgIHNlcmlhbGl6ZXIncyBgbm9ybWFsaXplYCBtZXRob2QuCiAgICAgIEBtZXRob2QgYXBwbHlUcmFuc2Zvcm1zCiAgICAgQHByaXZhdGUKICAgICBAcGFyYW0ge01vZGVsfSB0eXBlQ2xhc3MKICAgICBAcGFyYW0ge09iamVjdH0gZGF0YSBUaGUgZGF0YSB0byB0cmFuc2Zvcm0KICAgICBAcmV0dXJuIHtPYmplY3R9IGRhdGEgVGhlIHRyYW5zZm9ybWVkIGRhdGEgb2JqZWN0CiAgICAqLwogICAgYXBwbHlUcmFuc2Zvcm1zOiBmdW5jdGlvbiBhcHBseVRyYW5zZm9ybXModHlwZUNsYXNzLCBkYXRhKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICB2YXIgYXR0cmlidXRlcyA9IEVtYmVyLmdldCh0eXBlQ2xhc3MsICdhdHRyaWJ1dGVzJyk7CiAgICAgIHR5cGVDbGFzcy5lYWNoVHJhbnNmb3JtZWRBdHRyaWJ1dGUoZnVuY3Rpb24gKGtleSwgdHlwZUNsYXNzKSB7CiAgICAgICAgaWYgKGRhdGFba2V5XSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICB2YXIgdHJhbnNmb3JtID0gX3RoaXMudHJhbnNmb3JtRm9yKHR5cGVDbGFzcyk7CgogICAgICAgIHZhciB0cmFuc2Zvcm1NZXRhID0gYXR0cmlidXRlcy5nZXQoa2V5KTsKICAgICAgICBkYXRhW2tleV0gPSB0cmFuc2Zvcm0uZGVzZXJpYWxpemUoZGF0YVtrZXldLCB0cmFuc2Zvcm1NZXRhLm9wdGlvbnMpOwogICAgICB9KTsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9LAoKICAgIC8qKgogICAgICBUaGUgYG5vcm1hbGl6ZVJlc3BvbnNlYCBtZXRob2QgaXMgdXNlZCB0byBub3JtYWxpemUgYSBwYXlsb2FkIGZyb20gdGhlCiAgICAgIHNlcnZlciB0byBhIEpTT04tQVBJIERvY3VtZW50LgogICAgICAgaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdC8jZG9jdW1lbnQtc3RydWN0dXJlCiAgICAgICBUaGlzIG1ldGhvZCBkZWxlZ2F0ZXMgdG8gYSBtb3JlIHNwZWNpZmljIG5vcm1hbGl6ZSBtZXRob2QgYmFzZWQgb24KICAgICAgdGhlIGByZXF1ZXN0VHlwZWAuCiAgICAgICBUbyBvdmVycmlkZSB0aGlzIG1ldGhvZCB3aXRoIGEgY3VzdG9tIG9uZSwgbWFrZSBzdXJlIHRvIGNhbGwKICAgICAgYHJldHVybiB0aGlzLl9zdXBlcihzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSlgIHdpdGggeW91cgogICAgICBwcmUtcHJvY2Vzc2VkIGRhdGEuCiAgICAgICBIZXJlJ3MgYW4gZXhhbXBsZSBvZiB1c2luZyBgbm9ybWFsaXplUmVzcG9uc2VgIG1hbnVhbGx5OgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBzb2NrZXQub24oJ21lc3NhZ2UnLCBmdW5jdGlvbihtZXNzYWdlKSB7CiAgICAgICAgdmFyIGRhdGEgPSBtZXNzYWdlLmRhdGE7CiAgICAgICAgdmFyIG1vZGVsQ2xhc3MgPSBzdG9yZS5tb2RlbEZvcihkYXRhLm1vZGVsTmFtZSk7CiAgICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBzdG9yZS5zZXJpYWxpemVyRm9yKGRhdGEubW9kZWxOYW1lKTsKICAgICAgICB2YXIgbm9ybWFsaXplZCA9IHNlcmlhbGl6ZXIubm9ybWFsaXplU2luZ2xlUmVzcG9uc2Uoc3RvcmUsIG1vZGVsQ2xhc3MsIGRhdGEsIGRhdGEuaWQpOwogICAgICAgICBzdG9yZS5wdXNoKG5vcm1hbGl6ZWQpOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplUmVzcG9uc2UKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gcHJpbWFyeU1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgICBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFR5cGUKICAgICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICAgKi8KICAgIG5vcm1hbGl6ZVJlc3BvbnNlOiBmdW5jdGlvbiBub3JtYWxpemVSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICBzd2l0Y2ggKHJlcXVlc3RUeXBlKSB7CiAgICAgICAgY2FzZSAnZmluZFJlY29yZCc6CiAgICAgICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVGaW5kUmVjb3JkUmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgICAgY2FzZSAncXVlcnlSZWNvcmQnOgogICAgICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplUXVlcnlSZWNvcmRSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgICBjYXNlICdmaW5kQWxsJzoKICAgICAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZUZpbmRBbGxSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgICBjYXNlICdmaW5kQmVsb25nc1RvJzoKICAgICAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZUZpbmRCZWxvbmdzVG9SZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgICBjYXNlICdmaW5kSGFzTWFueSc6CiAgICAgICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVGaW5kSGFzTWFueVJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAgIGNhc2UgJ2ZpbmRNYW55JzoKICAgICAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZUZpbmRNYW55UmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgICAgY2FzZSAncXVlcnknOgogICAgICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplUXVlcnlSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgICBjYXNlICdjcmVhdGVSZWNvcmQnOgogICAgICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplQ3JlYXRlUmVjb3JkUmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgICAgY2FzZSAnZGVsZXRlUmVjb3JkJzoKICAgICAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZURlbGV0ZVJlY29yZFJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAgIGNhc2UgJ3VwZGF0ZVJlY29yZCc6CiAgICAgICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVVcGRhdGVSZWNvcmRSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplRmluZFJlY29yZFJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICovCiAgICBub3JtYWxpemVGaW5kUmVjb3JkUmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZUZpbmRSZWNvcmRSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVTaW5nbGVSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfSwKCiAgICAvKioKICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIG5vcm1hbGl6ZVF1ZXJ5UmVjb3JkUmVzcG9uc2UKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gcHJpbWFyeU1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgICBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFR5cGUKICAgICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICAgKi8KICAgIG5vcm1hbGl6ZVF1ZXJ5UmVjb3JkUmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZVF1ZXJ5UmVjb3JkUmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplU2luZ2xlUmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBub3JtYWxpemVGaW5kQWxsUmVzcG9uc2UKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gcHJpbWFyeU1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgICBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFR5cGUKICAgICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICAgKi8KICAgIG5vcm1hbGl6ZUZpbmRBbGxSZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplRmluZEFsbFJlc3BvbnNlKHN0b3JlLCBwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCwgaWQsIHJlcXVlc3RUeXBlKSB7CiAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZUFycmF5UmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBub3JtYWxpemVGaW5kQmVsb25nc1RvUmVzcG9uc2UKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gcHJpbWFyeU1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgICBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFR5cGUKICAgICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICAgKi8KICAgIG5vcm1hbGl6ZUZpbmRCZWxvbmdzVG9SZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplRmluZEJlbG9uZ3NUb1Jlc3BvbnNlKHN0b3JlLCBwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCwgaWQsIHJlcXVlc3RUeXBlKSB7CiAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZVNpbmdsZVJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplRmluZEhhc01hbnlSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAqLwogICAgbm9ybWFsaXplRmluZEhhc01hbnlSZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplRmluZEhhc01hbnlSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVBcnJheVJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplRmluZE1hbnlSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAqLwogICAgbm9ybWFsaXplRmluZE1hbnlSZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplRmluZE1hbnlSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVBcnJheVJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplUXVlcnlSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAqLwogICAgbm9ybWFsaXplUXVlcnlSZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplUXVlcnlSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVBcnJheVJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplQ3JlYXRlUmVjb3JkUmVzcG9uc2UKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gcHJpbWFyeU1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgICBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFR5cGUKICAgICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICAgKi8KICAgIG5vcm1hbGl6ZUNyZWF0ZVJlY29yZFJlc3BvbnNlOiBmdW5jdGlvbiBub3JtYWxpemVDcmVhdGVSZWNvcmRSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVTYXZlUmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBub3JtYWxpemVEZWxldGVSZWNvcmRSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAqLwogICAgbm9ybWFsaXplRGVsZXRlUmVjb3JkUmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZURlbGV0ZVJlY29yZFJlc3BvbnNlKHN0b3JlLCBwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCwgaWQsIHJlcXVlc3RUeXBlKSB7CiAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZVNhdmVSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfSwKCiAgICAvKioKICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIG5vcm1hbGl6ZVVwZGF0ZVJlY29yZFJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICovCiAgICBub3JtYWxpemVVcGRhdGVSZWNvcmRSZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplVXBkYXRlUmVjb3JkUmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplU2F2ZVJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplU2F2ZVJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICovCiAgICBub3JtYWxpemVTYXZlUmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZVNhdmVSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVTaW5nbGVSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfSwKCiAgICAvKioKICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIG5vcm1hbGl6ZVNpbmdsZVJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICovCiAgICBub3JtYWxpemVTaW5nbGVSZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplU2luZ2xlUmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMuX25vcm1hbGl6ZVJlc3BvbnNlKHN0b3JlLCBwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCwgaWQsIHJlcXVlc3RUeXBlLCB0cnVlKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBub3JtYWxpemVBcnJheVJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICovCiAgICBub3JtYWxpemVBcnJheVJlc3BvbnNlOiBmdW5jdGlvbiBub3JtYWxpemVBcnJheVJlc3BvbnNlKHN0b3JlLCBwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCwgaWQsIHJlcXVlc3RUeXBlKSB7CiAgICAgIHJldHVybiB0aGlzLl9ub3JtYWxpemVSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSwgZmFsc2UpOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBfbm9ybWFsaXplUmVzcG9uc2UKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gcHJpbWFyeU1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgICBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFR5cGUKICAgICAgQHBhcmFtIHtCb29sZWFufSBpc1NpbmdsZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX25vcm1hbGl6ZVJlc3BvbnNlOiBmdW5jdGlvbiBfbm9ybWFsaXplUmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUsIGlzU2luZ2xlKSB7CiAgICAgIHZhciBkb2N1bWVudEhhc2ggPSB7CiAgICAgICAgZGF0YTogbnVsbCwKICAgICAgICBpbmNsdWRlZDogW10KICAgICAgfTsKICAgICAgdmFyIG1ldGEgPSB0aGlzLmV4dHJhY3RNZXRhKHN0b3JlLCBwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCk7CgogICAgICBpZiAobWV0YSkgewogICAgICAgIChmYWxzZSAmJiAhKEVtYmVyLnR5cGVPZihtZXRhKSA9PT0gJ29iamVjdCcpICYmIEVtYmVyLmFzc2VydCgnVGhlIGBtZXRhYCByZXR1cm5lZCBmcm9tIGBleHRyYWN0TWV0YWAgaGFzIHRvIGJlIGFuIG9iamVjdCwgbm90ICInICsgRW1iZXIudHlwZU9mKG1ldGEpICsgJyIuJywgRW1iZXIudHlwZU9mKG1ldGEpID09PSAnb2JqZWN0JykpOwogICAgICAgIGRvY3VtZW50SGFzaC5tZXRhID0gbWV0YTsKICAgICAgfQoKICAgICAgaWYgKGlzU2luZ2xlKSB7CiAgICAgICAgdmFyIF90aGlzJG5vcm1hbGl6ZSA9IHRoaXMubm9ybWFsaXplKHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkKSwKICAgICAgICAgICAgZGF0YSA9IF90aGlzJG5vcm1hbGl6ZS5kYXRhLAogICAgICAgICAgICBpbmNsdWRlZCA9IF90aGlzJG5vcm1hbGl6ZS5pbmNsdWRlZDsKCiAgICAgICAgZG9jdW1lbnRIYXNoLmRhdGEgPSBkYXRhOwoKICAgICAgICBpZiAoaW5jbHVkZWQpIHsKICAgICAgICAgIGRvY3VtZW50SGFzaC5pbmNsdWRlZCA9IGluY2x1ZGVkOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgcmV0ID0gbmV3IEFycmF5KHBheWxvYWQubGVuZ3RoKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBwYXlsb2FkLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICAgICAgdmFyIGl0ZW0gPSBwYXlsb2FkW2ldOwoKICAgICAgICAgIHZhciBfdGhpcyRub3JtYWxpemUyID0gdGhpcy5ub3JtYWxpemUocHJpbWFyeU1vZGVsQ2xhc3MsIGl0ZW0pLAogICAgICAgICAgICAgIF9kYXRhID0gX3RoaXMkbm9ybWFsaXplMi5kYXRhLAogICAgICAgICAgICAgIF9pbmNsdWRlZCA9IF90aGlzJG5vcm1hbGl6ZTIuaW5jbHVkZWQ7CgogICAgICAgICAgaWYgKF9pbmNsdWRlZCkgewogICAgICAgICAgICB2YXIgX2RvY3VtZW50SGFzaCRpbmNsdWRlOwoKICAgICAgICAgICAgKF9kb2N1bWVudEhhc2gkaW5jbHVkZSA9IGRvY3VtZW50SGFzaC5pbmNsdWRlZCkucHVzaC5hcHBseShfZG9jdW1lbnRIYXNoJGluY2x1ZGUsIF9pbmNsdWRlZCk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0W2ldID0gX2RhdGE7CiAgICAgICAgfQoKICAgICAgICBkb2N1bWVudEhhc2guZGF0YSA9IHJldDsKICAgICAgfQoKICAgICAgcmV0dXJuIGRvY3VtZW50SGFzaDsKICAgIH0sCgogICAgLyoqCiAgICAgIE5vcm1hbGl6ZXMgYSBwYXJ0IG9mIHRoZSBKU09OIHBheWxvYWQgcmV0dXJuZWQgYnkKICAgICAgdGhlIHNlcnZlci4gWW91IHNob3VsZCBvdmVycmlkZSB0aGlzIG1ldGhvZCwgbXVuZ2UgdGhlIGhhc2gKICAgICAgYW5kIGNhbGwgc3VwZXIgaWYgeW91IGhhdmUgZ2VuZXJpYyBub3JtYWxpemF0aW9uIHRvIGRvLgogICAgICAgSXQgdGFrZXMgdGhlIHR5cGUgb2YgdGhlIHJlY29yZCB0aGF0IGlzIGJlaW5nIG5vcm1hbGl6ZWQKICAgICAgKGFzIGEgTW9kZWwgY2xhc3MpLCB0aGUgcHJvcGVydHkgd2hlcmUgdGhlIGhhc2ggd2FzCiAgICAgIG9yaWdpbmFsbHkgZm91bmQsIGFuZCB0aGUgaGFzaCB0byBub3JtYWxpemUuCiAgICAgICBZb3UgY2FuIHVzZSB0aGlzIG1ldGhvZCwgZm9yIGV4YW1wbGUsIHRvIG5vcm1hbGl6ZSB1bmRlcnNjb3JlZCBrZXlzIHRvIGNhbWVsaXplZAogICAgICBvciBvdGhlciBnZW5lcmFsLXB1cnBvc2Ugbm9ybWFsaXphdGlvbnMuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IEpTT05TZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbic7CiAgICAgIGltcG9ydCB7IHVuZGVyc2NvcmUgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAgICAgaW1wb3J0IHsgZ2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIG5vcm1hbGl6ZSh0eXBlQ2xhc3MsIGhhc2gpIHsKICAgICAgICAgIHZhciBmaWVsZHMgPSBnZXQodHlwZUNsYXNzLCAnZmllbGRzJyk7CiAgICAgICAgICAgZmllbGRzLmZvckVhY2goZnVuY3Rpb24odHlwZSwgZmllbGQpIHsKICAgICAgICAgICAgdmFyIHBheWxvYWRGaWVsZCA9IHVuZGVyc2NvcmUoZmllbGQpOwogICAgICAgICAgICBpZiAoZmllbGQgPT09IHBheWxvYWRGaWVsZCkgeyByZXR1cm47IH0KICAgICAgICAgICAgIGhhc2hbZmllbGRdID0gaGFzaFtwYXlsb2FkRmllbGRdOwogICAgICAgICAgICBkZWxldGUgaGFzaFtwYXlsb2FkRmllbGRdOwogICAgICAgICAgfSk7CiAgICAgICAgICAgcmV0dXJuIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIG5vcm1hbGl6ZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IGhhc2gKICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgKi8KICAgIG5vcm1hbGl6ZTogZnVuY3Rpb24gbm9ybWFsaXplKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCkgewogICAgICB2YXIgZGF0YSA9IG51bGw7CgogICAgICBpZiAocmVzb3VyY2VIYXNoKSB7CiAgICAgICAgdGhpcy5ub3JtYWxpemVVc2luZ0RlY2xhcmVkTWFwcGluZyhtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpOwoKICAgICAgICBpZiAoRW1iZXIudHlwZU9mKHJlc291cmNlSGFzaC5saW5rcykgPT09ICdvYmplY3QnKSB7CiAgICAgICAgICB0aGlzLm5vcm1hbGl6ZVVzaW5nRGVjbGFyZWRNYXBwaW5nKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaC5saW5rcyk7CiAgICAgICAgfQoKICAgICAgICBkYXRhID0gewogICAgICAgICAgaWQ6IHRoaXMuZXh0cmFjdElkKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCksCiAgICAgICAgICB0eXBlOiBtb2RlbENsYXNzLm1vZGVsTmFtZSwKICAgICAgICAgIGF0dHJpYnV0ZXM6IHRoaXMuZXh0cmFjdEF0dHJpYnV0ZXMobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKSwKICAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHRoaXMuZXh0cmFjdFJlbGF0aW9uc2hpcHMobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKQogICAgICAgIH07CiAgICAgICAgdGhpcy5hcHBseVRyYW5zZm9ybXMobW9kZWxDbGFzcywgZGF0YS5hdHRyaWJ1dGVzKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHsKICAgICAgICBkYXRhOiBkYXRhCiAgICAgIH07CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSByZXNvdXJjZSdzIElELgogICAgICAgQG1ldGhvZCBleHRyYWN0SWQKICAgICAgQHBhcmFtIHtPYmplY3R9IG1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlc291cmNlSGFzaAogICAgICBAcmV0dXJuIHtTdHJpbmd9CiAgICAqLwogICAgZXh0cmFjdElkOiBmdW5jdGlvbiBleHRyYWN0SWQobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKSB7CiAgICAgIHZhciBwcmltYXJ5S2V5ID0gRW1iZXIuZ2V0KHRoaXMsICdwcmltYXJ5S2V5Jyk7CiAgICAgIHZhciBpZCA9IHJlc291cmNlSGFzaFtwcmltYXJ5S2V5XTsKICAgICAgcmV0dXJuICgwLCBfcHJpdmF0ZS5jb2VyY2VJZCkoaWQpOwogICAgfSwKCiAgICAvKioKICAgICAgUmV0dXJucyB0aGUgcmVzb3VyY2UncyBhdHRyaWJ1dGVzIGZvcm1hdHRlZCBhcyBhIEpTT04tQVBJICJhdHRyaWJ1dGVzIG9iamVjdCIuCiAgICAgICBodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0LyNkb2N1bWVudC1yZXNvdXJjZS1vYmplY3QtYXR0cmlidXRlcwogICAgICAgQG1ldGhvZCBleHRyYWN0QXR0cmlidXRlcwogICAgICBAcGFyYW0ge09iamVjdH0gbW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcmVzb3VyY2VIYXNoCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICovCiAgICBleHRyYWN0QXR0cmlidXRlczogZnVuY3Rpb24gZXh0cmFjdEF0dHJpYnV0ZXMobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgdmFyIGF0dHJpYnV0ZUtleTsKICAgICAgdmFyIGF0dHJpYnV0ZXMgPSB7fTsKICAgICAgbW9kZWxDbGFzcy5lYWNoQXR0cmlidXRlKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICBhdHRyaWJ1dGVLZXkgPSBfdGhpczIua2V5Rm9yQXR0cmlidXRlKGtleSwgJ2Rlc2VyaWFsaXplJyk7CgogICAgICAgIGlmIChyZXNvdXJjZUhhc2hbYXR0cmlidXRlS2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBhdHRyaWJ1dGVzW2tleV0gPSByZXNvdXJjZUhhc2hbYXR0cmlidXRlS2V5XTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gYXR0cmlidXRlczsKICAgIH0sCgogICAgLyoqCiAgICAgIFJldHVybnMgYSByZWxhdGlvbnNoaXAgZm9ybWF0dGVkIGFzIGEgSlNPTi1BUEkgInJlbGF0aW9uc2hpcCBvYmplY3QiLgogICAgICAgaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdC8jZG9jdW1lbnQtcmVzb3VyY2Utb2JqZWN0LXJlbGF0aW9uc2hpcHMKICAgICAgIEBtZXRob2QgZXh0cmFjdFJlbGF0aW9uc2hpcAogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwTW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZWxhdGlvbnNoaXBIYXNoCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICovCiAgICBleHRyYWN0UmVsYXRpb25zaGlwOiBmdW5jdGlvbiBleHRyYWN0UmVsYXRpb25zaGlwKHJlbGF0aW9uc2hpcE1vZGVsTmFtZSwgcmVsYXRpb25zaGlwSGFzaCkgewogICAgICBpZiAoRW1iZXIuaXNOb25lKHJlbGF0aW9uc2hpcEhhc2gpKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgLyoKICAgICAgICBXaGVuIGByZWxhdGlvbnNoaXBIYXNoYCBpcyBhbiBvYmplY3QgaXQgdXN1YWxseSBtZWFucyB0aGF0IHRoZSByZWxhdGlvbnNoaXAKICAgICAgICBpcyBwb2x5bW9ycGhpYy4gSXQgY291bGQgaG93ZXZlciBhbHNvIGJlIGVtYmVkZGVkIHJlc291cmNlcyB0aGF0IHRoZQogICAgICAgIEVtYmVkZGVkUmVjb3Jkc01peGluIGhhcyBiZSBhYmxlIHRvIHByb2Nlc3MuCiAgICAgICovCgoKICAgICAgaWYgKEVtYmVyLnR5cGVPZihyZWxhdGlvbnNoaXBIYXNoKSA9PT0gJ29iamVjdCcpIHsKICAgICAgICBpZiAocmVsYXRpb25zaGlwSGFzaC5pZCkgewogICAgICAgICAgcmVsYXRpb25zaGlwSGFzaC5pZCA9ICgwLCBfcHJpdmF0ZS5jb2VyY2VJZCkocmVsYXRpb25zaGlwSGFzaC5pZCk7CiAgICAgICAgfQoKICAgICAgICB2YXIgbW9kZWxDbGFzcyA9IHRoaXMuc3RvcmUubW9kZWxGb3IocmVsYXRpb25zaGlwTW9kZWxOYW1lKTsKCiAgICAgICAgaWYgKHJlbGF0aW9uc2hpcEhhc2gudHlwZSAmJiAhKDAsIF9wcml2YXRlMi5tb2RlbEhhc0F0dHJpYnV0ZU9yUmVsYXRpb25zaGlwTmFtZWRUeXBlKShtb2RlbENsYXNzKSkgewogICAgICAgICAgcmVsYXRpb25zaGlwSGFzaC50eXBlID0gdGhpcy5tb2RlbE5hbWVGcm9tUGF5bG9hZEtleShyZWxhdGlvbnNoaXBIYXNoLnR5cGUpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcEhhc2g7CiAgICAgIH0KCiAgICAgIHJldHVybiB7CiAgICAgICAgaWQ6ICgwLCBfcHJpdmF0ZS5jb2VyY2VJZCkocmVsYXRpb25zaGlwSGFzaCksCiAgICAgICAgdHlwZTogcmVsYXRpb25zaGlwTW9kZWxOYW1lCiAgICAgIH07CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIGEgcG9seW1vcnBoaWMgcmVsYXRpb25zaGlwIGZvcm1hdHRlZCBhcyBhIEpTT04tQVBJICJyZWxhdGlvbnNoaXAgb2JqZWN0Ii4KICAgICAgIGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2RvY3VtZW50LXJlc291cmNlLW9iamVjdC1yZWxhdGlvbnNoaXBzCiAgICAgICBgcmVsYXRpb25zaGlwT3B0aW9uc2AgaXMgYSBoYXNoIHdoaWNoIGNvbnRhaW5zIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhlCiAgICAgIHBvbHltb3JwaGljIHJlbGF0aW9uc2hpcCB3aGljaCBzaG91bGQgYmUgZXh0cmFjdGVkOgogICAgICAgIC0gYHJlc291cmNlSGFzaGAgY29tcGxldGUgaGFzaCBvZiB0aGUgcmVzb3VyY2UgdGhlIHJlbGF0aW9uc2hpcCBzaG91bGQgYmUKICAgICAgICAgIGV4dHJhY3RlZCBmcm9tCiAgICAgICAgLSBgcmVsYXRpb25zaGlwS2V5YCBrZXkgdW5kZXIgd2hpY2ggdGhlIHZhbHVlIGZvciB0aGUgcmVsYXRpb25zaGlwIGlzCiAgICAgICAgICBleHRyYWN0ZWQgZnJvbSB0aGUgcmVzb3VyY2VIYXNoCiAgICAgICAgLSBgcmVsYXRpb25zaGlwTWV0YWAgbWV0YSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcmVsYXRpb25zaGlwCiAgICAgICBAbWV0aG9kIGV4dHJhY3RQb2x5bW9ycGhpY1JlbGF0aW9uc2hpcAogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwTW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZWxhdGlvbnNoaXBIYXNoCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZWxhdGlvbnNoaXBPcHRpb25zCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICovCiAgICBleHRyYWN0UG9seW1vcnBoaWNSZWxhdGlvbnNoaXA6IGZ1bmN0aW9uIGV4dHJhY3RQb2x5bW9ycGhpY1JlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXBNb2RlbE5hbWUsIHJlbGF0aW9uc2hpcEhhc2gsIHJlbGF0aW9uc2hpcE9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMuZXh0cmFjdFJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXBNb2RlbE5hbWUsIHJlbGF0aW9uc2hpcEhhc2gpOwogICAgfSwKCiAgICAvKioKICAgICAgUmV0dXJucyB0aGUgcmVzb3VyY2UncyByZWxhdGlvbnNoaXBzIGZvcm1hdHRlZCBhcyBhIEpTT04tQVBJICJyZWxhdGlvbnNoaXBzIG9iamVjdCIuCiAgICAgICBodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0LyNkb2N1bWVudC1yZXNvdXJjZS1vYmplY3QtcmVsYXRpb25zaGlwcwogICAgICAgQG1ldGhvZCBleHRyYWN0UmVsYXRpb25zaGlwcwogICAgICBAcGFyYW0ge09iamVjdH0gbW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcmVzb3VyY2VIYXNoCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICovCiAgICBleHRyYWN0UmVsYXRpb25zaGlwczogZnVuY3Rpb24gZXh0cmFjdFJlbGF0aW9uc2hpcHMobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKSB7CiAgICAgIHZhciBfdGhpczMgPSB0aGlzOwoKICAgICAgdmFyIHJlbGF0aW9uc2hpcHMgPSB7fTsKICAgICAgbW9kZWxDbGFzcy5lYWNoUmVsYXRpb25zaGlwKGZ1bmN0aW9uIChrZXksIHJlbGF0aW9uc2hpcE1ldGEpIHsKICAgICAgICB2YXIgcmVsYXRpb25zaGlwID0gbnVsbDsKCiAgICAgICAgdmFyIHJlbGF0aW9uc2hpcEtleSA9IF90aGlzMy5rZXlGb3JSZWxhdGlvbnNoaXAoa2V5LCByZWxhdGlvbnNoaXBNZXRhLmtpbmQsICdkZXNlcmlhbGl6ZScpOwoKICAgICAgICBpZiAocmVzb3VyY2VIYXNoW3JlbGF0aW9uc2hpcEtleV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdmFyIGRhdGEgPSBudWxsOwogICAgICAgICAgdmFyIHJlbGF0aW9uc2hpcEhhc2ggPSByZXNvdXJjZUhhc2hbcmVsYXRpb25zaGlwS2V5XTsKCiAgICAgICAgICBpZiAocmVsYXRpb25zaGlwTWV0YS5raW5kID09PSAnYmVsb25nc1RvJykgewogICAgICAgICAgICBpZiAocmVsYXRpb25zaGlwTWV0YS5vcHRpb25zLnBvbHltb3JwaGljKSB7CiAgICAgICAgICAgICAgLy8gZXh0cmFjdGluZyBhIHBvbHltb3JwaGljIGJlbG9uZ3NUbyBtYXkgbmVlZCBtb3JlIGluZm9ybWF0aW9uCiAgICAgICAgICAgICAgLy8gdGhhbiB0aGUgdHlwZSBhbmQgdGhlIGhhc2ggKHdoaWNoIG1pZ2h0IG9ubHkgYmUgYW4gaWQpIGZvciB0aGUKICAgICAgICAgICAgICAvLyByZWxhdGlvbnNoaXAsIGhlbmNlIHdlIHBhc3MgdGhlIGtleSwgcmVzb3VyY2UgYW5kCiAgICAgICAgICAgICAgLy8gcmVsYXRpb25zaGlwTWV0YSB0b28KICAgICAgICAgICAgICBkYXRhID0gX3RoaXMzLmV4dHJhY3RQb2x5bW9ycGhpY1JlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXBNZXRhLnR5cGUsIHJlbGF0aW9uc2hpcEhhc2gsIHsKICAgICAgICAgICAgICAgIGtleToga2V5LAogICAgICAgICAgICAgICAgcmVzb3VyY2VIYXNoOiByZXNvdXJjZUhhc2gsCiAgICAgICAgICAgICAgICByZWxhdGlvbnNoaXBNZXRhOiByZWxhdGlvbnNoaXBNZXRhCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZGF0YSA9IF90aGlzMy5leHRyYWN0UmVsYXRpb25zaGlwKHJlbGF0aW9uc2hpcE1ldGEudHlwZSwgcmVsYXRpb25zaGlwSGFzaCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSBpZiAocmVsYXRpb25zaGlwTWV0YS5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgICAgICAgaWYgKCFFbWJlci5pc05vbmUocmVsYXRpb25zaGlwSGFzaCkpIHsKICAgICAgICAgICAgICBkYXRhID0gbmV3IEFycmF5KHJlbGF0aW9uc2hpcEhhc2gubGVuZ3RoKTsKCiAgICAgICAgICAgICAgaWYgKHJlbGF0aW9uc2hpcE1ldGEub3B0aW9ucy5wb2x5bW9ycGhpYykgewogICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSByZWxhdGlvbnNoaXBIYXNoLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICAgICAgICAgICAgICB2YXIgaXRlbSA9IHJlbGF0aW9uc2hpcEhhc2hbaV07CiAgICAgICAgICAgICAgICAgIGRhdGFbaV0gPSBfdGhpczMuZXh0cmFjdFBvbHltb3JwaGljUmVsYXRpb25zaGlwKHJlbGF0aW9uc2hpcE1ldGEudHlwZSwgaXRlbSwgewogICAgICAgICAgICAgICAgICAgIGtleToga2V5LAogICAgICAgICAgICAgICAgICAgIHJlc291cmNlSGFzaDogcmVzb3VyY2VIYXNoLAogICAgICAgICAgICAgICAgICAgIHJlbGF0aW9uc2hpcE1ldGE6IHJlbGF0aW9uc2hpcE1ldGEKICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2wgPSByZWxhdGlvbnNoaXBIYXNoLmxlbmd0aDsgX2kgPCBfbDsgX2krKykgewogICAgICAgICAgICAgICAgICB2YXIgX2l0ZW0gPSByZWxhdGlvbnNoaXBIYXNoW19pXTsKICAgICAgICAgICAgICAgICAgZGF0YVtfaV0gPSBfdGhpczMuZXh0cmFjdFJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXBNZXRhLnR5cGUsIF9pdGVtKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICByZWxhdGlvbnNoaXAgPSB7CiAgICAgICAgICAgIGRhdGE6IGRhdGEKICAgICAgICAgIH07CiAgICAgICAgfQoKICAgICAgICB2YXIgbGlua0tleSA9IF90aGlzMy5rZXlGb3JMaW5rKGtleSwgcmVsYXRpb25zaGlwTWV0YS5raW5kKTsKCiAgICAgICAgaWYgKHJlc291cmNlSGFzaC5saW5rcyAmJiByZXNvdXJjZUhhc2gubGlua3NbbGlua0tleV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdmFyIHJlbGF0ZWQgPSByZXNvdXJjZUhhc2gubGlua3NbbGlua0tleV07CiAgICAgICAgICByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXAgfHwge307CiAgICAgICAgICByZWxhdGlvbnNoaXAubGlua3MgPSB7CiAgICAgICAgICAgIHJlbGF0ZWQ6IHJlbGF0ZWQKICAgICAgICAgIH07CiAgICAgICAgfQoKICAgICAgICBpZiAocmVsYXRpb25zaGlwKSB7CiAgICAgICAgICByZWxhdGlvbnNoaXBzW2tleV0gPSByZWxhdGlvbnNoaXA7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcHM7CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIG1vZGVsTmFtZUZyb21QYXlsb2FkS2V5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkKICAgICAgQHJldHVybiB7U3RyaW5nfSB0aGUgbW9kZWwncyBtb2RlbE5hbWUKICAgICovCiAgICAvLyBUT0RPIEBkZXByZWNhdGVkIFVzZSBtb2RlbE5hbWVGcm9tUGF5bG9hZFR5cGUgaW5zdGVhZAogICAgbW9kZWxOYW1lRnJvbVBheWxvYWRLZXk6IGZ1bmN0aW9uIG1vZGVsTmFtZUZyb21QYXlsb2FkS2V5KGtleSkgewogICAgICByZXR1cm4gKDAsIF9zdG9yZS5ub3JtYWxpemVNb2RlbE5hbWUpKGtleSk7CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIG5vcm1hbGl6ZVJlbGF0aW9uc2hpcHMKICAgICAgQHByaXZhdGUKICAgICovCiAgICBub3JtYWxpemVSZWxhdGlvbnNoaXBzOiBmdW5jdGlvbiBub3JtYWxpemVSZWxhdGlvbnNoaXBzKHR5cGVDbGFzcywgaGFzaCkgewogICAgICB2YXIgX3RoaXM0ID0gdGhpczsKCiAgICAgIHZhciBwYXlsb2FkS2V5OwoKICAgICAgaWYgKHRoaXMua2V5Rm9yUmVsYXRpb25zaGlwKSB7CiAgICAgICAgdHlwZUNsYXNzLmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24gKGtleSwgcmVsYXRpb25zaGlwKSB7CiAgICAgICAgICBwYXlsb2FkS2V5ID0gX3RoaXM0LmtleUZvclJlbGF0aW9uc2hpcChrZXksIHJlbGF0aW9uc2hpcC5raW5kLCAnZGVzZXJpYWxpemUnKTsKCiAgICAgICAgICBpZiAoa2V5ID09PSBwYXlsb2FkS2V5KSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoaGFzaFtwYXlsb2FkS2V5XSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KCiAgICAgICAgICBoYXNoW2tleV0gPSBoYXNoW3BheWxvYWRLZXldOwogICAgICAgICAgZGVsZXRlIGhhc2hbcGF5bG9hZEtleV07CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplVXNpbmdEZWNsYXJlZE1hcHBpbmcKICAgICAgQHByaXZhdGUKICAgICovCiAgICBub3JtYWxpemVVc2luZ0RlY2xhcmVkTWFwcGluZzogZnVuY3Rpb24gbm9ybWFsaXplVXNpbmdEZWNsYXJlZE1hcHBpbmcobW9kZWxDbGFzcywgaGFzaCkgewogICAgICB2YXIgYXR0cnMgPSBFbWJlci5nZXQodGhpcywgJ2F0dHJzJyk7CiAgICAgIHZhciBub3JtYWxpemVkS2V5OwogICAgICB2YXIgcGF5bG9hZEtleTsKCiAgICAgIGlmIChhdHRycykgewogICAgICAgIGZvciAodmFyIGtleSBpbiBhdHRycykgewogICAgICAgICAgbm9ybWFsaXplZEtleSA9IHBheWxvYWRLZXkgPSB0aGlzLl9nZXRNYXBwZWRLZXkoa2V5LCBtb2RlbENsYXNzKTsKCiAgICAgICAgICBpZiAoaGFzaFtwYXlsb2FkS2V5XSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChFbWJlci5nZXQobW9kZWxDbGFzcywgJ2F0dHJpYnV0ZXMnKS5oYXMoa2V5KSkgewogICAgICAgICAgICBub3JtYWxpemVkS2V5ID0gdGhpcy5rZXlGb3JBdHRyaWJ1dGUoa2V5KTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoRW1iZXIuZ2V0KG1vZGVsQ2xhc3MsICdyZWxhdGlvbnNoaXBzQnlOYW1lJykuaGFzKGtleSkpIHsKICAgICAgICAgICAgbm9ybWFsaXplZEtleSA9IHRoaXMua2V5Rm9yUmVsYXRpb25zaGlwKGtleSk7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKHBheWxvYWRLZXkgIT09IG5vcm1hbGl6ZWRLZXkpIHsKICAgICAgICAgICAgaGFzaFtub3JtYWxpemVkS2V5XSA9IGhhc2hbcGF5bG9hZEtleV07CiAgICAgICAgICAgIGRlbGV0ZSBoYXNoW3BheWxvYWRLZXldOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgTG9va3MgdXAgdGhlIHByb3BlcnR5IGtleSB0aGF0IHdhcyBzZXQgYnkgdGhlIGN1c3RvbSBgYXR0cmAgbWFwcGluZwogICAgICBwYXNzZWQgdG8gdGhlIHNlcmlhbGl6ZXIuCiAgICAgICBAbWV0aG9kIF9nZXRNYXBwZWRLZXkKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleQogICAgICBAcmV0dXJuIHtTdHJpbmd9IGtleQogICAgKi8KICAgIF9nZXRNYXBwZWRLZXk6IGZ1bmN0aW9uIF9nZXRNYXBwZWRLZXkoa2V5LCBtb2RlbENsYXNzKSB7CiAgICAgIChmYWxzZSAmJiBFbWJlci53YXJuKCdUaGVyZSBpcyBubyBhdHRyaWJ1dGUgb3IgcmVsYXRpb25zaGlwIHdpdGggdGhlIG5hbWUgYCcgKyBrZXkgKyAnYCBvbiBgJyArIG1vZGVsQ2xhc3MubW9kZWxOYW1lICsgJ2AuIENoZWNrIHlvdXIgc2VyaWFsaXplcnMgYXR0cnMgaGFzaC4nLCBFbWJlci5nZXQobW9kZWxDbGFzcywgJ2F0dHJpYnV0ZXMnKS5oYXMoa2V5KSB8fCBFbWJlci5nZXQobW9kZWxDbGFzcywgJ3JlbGF0aW9uc2hpcHNCeU5hbWUnKS5oYXMoa2V5KSwgewogICAgICAgIGlkOiAnZHMuc2VyaWFsaXplci5uby1tYXBwZWQtYXR0cnMta2V5JwogICAgICB9KSk7CiAgICAgIHZhciBhdHRycyA9IEVtYmVyLmdldCh0aGlzLCAnYXR0cnMnKTsKICAgICAgdmFyIG1hcHBlZEtleTsKCiAgICAgIGlmIChhdHRycyAmJiBhdHRyc1trZXldKSB7CiAgICAgICAgbWFwcGVkS2V5ID0gYXR0cnNba2V5XTsgLy9XZSBuZWVkIHRvIGFjY291bnQgZm9yIGJvdGggdGhlIHsgdGl0bGU6ICdwb3N0X3RpdGxlJyB9IGFuZAogICAgICAgIC8veyB0aXRsZTogeyBrZXk6ICdwb3N0X3RpdGxlJyB9fSBmb3JtcwoKICAgICAgICBpZiAobWFwcGVkS2V5LmtleSkgewogICAgICAgICAgbWFwcGVkS2V5ID0gbWFwcGVkS2V5LmtleTsKICAgICAgICB9CgogICAgICAgIGlmICh0eXBlb2YgbWFwcGVkS2V5ID09PSAnc3RyaW5nJykgewogICAgICAgICAga2V5ID0gbWFwcGVkS2V5OwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGtleTsKICAgIH0sCgogICAgLyoqCiAgICAgIENoZWNrIGF0dHJzLmtleS5zZXJpYWxpemUgcHJvcGVydHkgdG8gaW5mb3JtIGlmIHRoZSBga2V5YAogICAgICBjYW4gYmUgc2VyaWFsaXplZAogICAgICAgQG1ldGhvZCBfY2FuU2VyaWFsaXplCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkKICAgICAgQHJldHVybiB7Ym9vbGVhbn0gdHJ1ZSBpZiB0aGUga2V5IGNhbiBiZSBzZXJpYWxpemVkCiAgICAqLwogICAgX2NhblNlcmlhbGl6ZTogZnVuY3Rpb24gX2NhblNlcmlhbGl6ZShrZXkpIHsKICAgICAgdmFyIGF0dHJzID0gRW1iZXIuZ2V0KHRoaXMsICdhdHRycycpOwogICAgICByZXR1cm4gIWF0dHJzIHx8ICFhdHRyc1trZXldIHx8IGF0dHJzW2tleV0uc2VyaWFsaXplICE9PSBmYWxzZTsKICAgIH0sCgogICAgLyoqCiAgICAgIFdoZW4gYXR0cnMua2V5LnNlcmlhbGl6ZSBpcyBzZXQgdG8gdHJ1ZSB0aGVuCiAgICAgIGl0IHRha2VzIHByaW9yaXR5IG92ZXIgdGhlIG90aGVyIGNoZWNrcyBhbmQgdGhlIHJlbGF0ZWQKICAgICAgYXR0cmlidXRlL3JlbGF0aW9uc2hpcCB3aWxsIGJlIHNlcmlhbGl6ZWQKICAgICAgIEBtZXRob2QgX211c3RTZXJpYWxpemUKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleQogICAgICBAcmV0dXJuIHtib29sZWFufSB0cnVlIGlmIHRoZSBrZXkgbXVzdCBiZSBzZXJpYWxpemVkCiAgICAqLwogICAgX211c3RTZXJpYWxpemU6IGZ1bmN0aW9uIF9tdXN0U2VyaWFsaXplKGtleSkgewogICAgICB2YXIgYXR0cnMgPSBFbWJlci5nZXQodGhpcywgJ2F0dHJzJyk7CiAgICAgIHJldHVybiBhdHRycyAmJiBhdHRyc1trZXldICYmIGF0dHJzW2tleV0uc2VyaWFsaXplID09PSB0cnVlOwogICAgfSwKCiAgICAvKioKICAgICAgQ2hlY2sgaWYgdGhlIGdpdmVuIGhhc01hbnkgcmVsYXRpb25zaGlwIHNob3VsZCBiZSBzZXJpYWxpemVkCiAgICAgICBCeSBkZWZhdWx0IG9ubHkgbWFueS10by1tYW55IGFuZCBtYW55LXRvLW5vbmUgcmVsYXRpb25zaGlwcyBhcmUgc2VyaWFsaXplZC4KICAgICAgVGhpcyBjb3VsZCBiZSBjb25maWd1cmVkIHBlciByZWxhdGlvbnNoaXAgYnkgU2VyaWFsaXplcidzIGBhdHRyc2Agb2JqZWN0LgogICAgICAgQG1ldGhvZCBzaG91bGRTZXJpYWxpemVIYXNNYW55CiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlbGF0aW9uc2hpcFR5cGUKICAgICAgQHJldHVybiB7Ym9vbGVhbn0gdHJ1ZSBpZiB0aGUgaGFzTWFueSByZWxhdGlvbnNoaXAgc2hvdWxkIGJlIHNlcmlhbGl6ZWQKICAgICovCiAgICBzaG91bGRTZXJpYWxpemVIYXNNYW55OiBmdW5jdGlvbiBzaG91bGRTZXJpYWxpemVIYXNNYW55KHNuYXBzaG90LCBrZXksIHJlbGF0aW9uc2hpcCkgewogICAgICB2YXIgcmVsYXRpb25zaGlwVHlwZSA9IHNuYXBzaG90LnR5cGUuZGV0ZXJtaW5lUmVsYXRpb25zaGlwVHlwZShyZWxhdGlvbnNoaXAsIHRoaXMuc3RvcmUpOwoKICAgICAgaWYgKHRoaXMuX211c3RTZXJpYWxpemUoa2V5KSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fY2FuU2VyaWFsaXplKGtleSkgJiYgKHJlbGF0aW9uc2hpcFR5cGUgPT09ICdtYW55VG9Ob25lJyB8fCByZWxhdGlvbnNoaXBUeXBlID09PSAnbWFueVRvTWFueScpOwogICAgfSwKICAgIC8vIFNFUklBTElaRQoKICAgIC8qKgogICAgICBDYWxsZWQgd2hlbiBhIHJlY29yZCBpcyBzYXZlZCBpbiBvcmRlciB0byBjb252ZXJ0IHRoZQogICAgICByZWNvcmQgaW50byBKU09OLgogICAgICAgQnkgZGVmYXVsdCwgaXQgY3JlYXRlcyBhIEpTT04gb2JqZWN0IHdpdGggYSBrZXkgZm9yCiAgICAgIGVhY2ggYXR0cmlidXRlIGFuZCBiZWxvbmdzVG8gcmVsYXRpb25zaGlwLgogICAgICAgRm9yIGV4YW1wbGUsIGNvbnNpZGVyIHRoaXMgbW9kZWw6CiAgICAgICBgYGBhcHAvbW9kZWxzL2NvbW1lbnQuanMKICAgICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIsIGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdGl0bGU6IGF0dHIoKSwKICAgICAgICBib2R5OiBhdHRyKCksCiAgICAgICAgIGF1dGhvcjogYmVsb25nc1RvKCd1c2VyJykKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVGhlIGRlZmF1bHQgc2VyaWFsaXphdGlvbiB3b3VsZCBjcmVhdGUgYSBKU09OIG9iamVjdCBsaWtlOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICB7CiAgICAgICAgInRpdGxlIjogIlJhaWxzIGlzIHVuYWdpIiwKICAgICAgICAiYm9keSI6ICJSYWlscz8gT21ha2FzZT8gT19PIiwKICAgICAgICAiYXV0aG9yIjogMTIKICAgICAgfQogICAgICBgYGAKICAgICAgIEJ5IGRlZmF1bHQsIGF0dHJpYnV0ZXMgYXJlIHBhc3NlZCB0aHJvdWdoIGFzLWlzLCB1bmxlc3MKICAgICAgeW91IHNwZWNpZmllZCBhbiBhdHRyaWJ1dGUgdHlwZSAoYGF0dHIoJ2RhdGUnKWApLiBJZgogICAgICB5b3Ugc3BlY2lmeSBhIHRyYW5zZm9ybSwgdGhlIEphdmFTY3JpcHQgdmFsdWUgd2lsbCBiZQogICAgICBzZXJpYWxpemVkIHdoZW4gaW5zZXJ0ZWQgaW50byB0aGUgSlNPTiBoYXNoLgogICAgICAgQnkgZGVmYXVsdCwgYmVsb25ncy10byByZWxhdGlvbnNoaXBzIGFyZSBjb252ZXJ0ZWQgaW50bwogICAgICBJRHMgd2hlbiBpbnNlcnRlZCBpbnRvIHRoZSBKU09OIGhhc2guCiAgICAgICAjIyBJRHMKICAgICAgIGBzZXJpYWxpemVgIHRha2VzIGFuIG9wdGlvbnMgaGFzaCB3aXRoIGEgc2luZ2xlIG9wdGlvbjoKICAgICAgYGluY2x1ZGVJZGAuIElmIHRoaXMgb3B0aW9uIGlzIGB0cnVlYCwgYHNlcmlhbGl6ZWAgd2lsbCwKICAgICAgYnkgZGVmYXVsdCBpbmNsdWRlIHRoZSBJRCBpbiB0aGUgSlNPTiBvYmplY3QgaXQgYnVpbGRzLgogICAgICAgVGhlIGFkYXB0ZXIgcGFzc2VzIGluIGBpbmNsdWRlSWQ6IHRydWVgIHdoZW4gc2VyaWFsaXppbmcKICAgICAgYSByZWNvcmQgZm9yIGBjcmVhdGVSZWNvcmRgLCBidXQgbm90IGZvciBgdXBkYXRlUmVjb3JkYC4KICAgICAgICMjIEN1c3RvbWl6YXRpb24KICAgICAgIFlvdXIgc2VydmVyIG1heSBleHBlY3QgYSBkaWZmZXJlbnQgSlNPTiBmb3JtYXQgdGhhbiB0aGUKICAgICAgYnVpbHQtaW4gc2VyaWFsaXphdGlvbiBmb3JtYXQuCiAgICAgICBJbiB0aGF0IGNhc2UsIHlvdSBjYW4gaW1wbGVtZW50IGBzZXJpYWxpemVgIHlvdXJzZWxmIGFuZAogICAgICByZXR1cm4gYSBKU09OIGhhc2ggb2YgeW91ciBjaG9vc2luZy4KICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBKU09OU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24nOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBzZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpIHsKICAgICAgICAgIHZhciBqc29uID0gewogICAgICAgICAgICBQT1NUX1RUTDogc25hcHNob3QuYXR0cigndGl0bGUnKSwKICAgICAgICAgICAgUE9TVF9CRFk6IHNuYXBzaG90LmF0dHIoJ2JvZHknKSwKICAgICAgICAgICAgUE9TVF9DTVM6IHNuYXBzaG90Lmhhc01hbnkoJ2NvbW1lbnRzJywgeyBpZHM6IHRydWUgfSkKICAgICAgICAgIH07CiAgICAgICAgICAgaWYgKG9wdGlvbnMuaW5jbHVkZUlkKSB7CiAgICAgICAgICAgIGpzb24uUE9TVF9JRF8gPSBzbmFwc2hvdC5pZDsKICAgICAgICAgIH0KICAgICAgICAgICByZXR1cm4ganNvbjsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICMjIEN1c3RvbWl6aW5nIGFuIEFwcC1XaWRlIFNlcmlhbGl6ZXIKICAgICAgIElmIHlvdSB3YW50IHRvIGRlZmluZSBhIHNlcmlhbGl6ZXIgZm9yIHlvdXIgZW50aXJlCiAgICAgIGFwcGxpY2F0aW9uLCB5b3UnbGwgcHJvYmFibHkgd2FudCB0byB1c2UgYGVhY2hBdHRyaWJ1dGVgCiAgICAgIGFuZCBgZWFjaFJlbGF0aW9uc2hpcGAgb24gdGhlIHJlY29yZC4KICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgSlNPTlNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uJzsKICAgICAgaW1wb3J0IHsgc2luZ3VsYXJpemUgfSBmcm9tICdlbWJlci1pbmZsZWN0b3InOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBzZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpIHsKICAgICAgICAgIHZhciBqc29uID0ge307CiAgICAgICAgICAgc25hcHNob3QuZWFjaEF0dHJpYnV0ZShmdW5jdGlvbihuYW1lKSB7CiAgICAgICAgICAgIGpzb25bc2VydmVyQXR0cmlidXRlTmFtZShuYW1lKV0gPSBzbmFwc2hvdC5hdHRyKG5hbWUpOwogICAgICAgICAgfSk7CiAgICAgICAgICAgc25hcHNob3QuZWFjaFJlbGF0aW9uc2hpcChmdW5jdGlvbihuYW1lLCByZWxhdGlvbnNoaXApIHsKICAgICAgICAgICAgaWYgKHJlbGF0aW9uc2hpcC5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgICAgICAgICBqc29uW3NlcnZlckhhc01hbnlOYW1lKG5hbWUpXSA9IHNuYXBzaG90Lmhhc01hbnkobmFtZSwgeyBpZHM6IHRydWUgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgICAgIGlmIChvcHRpb25zLmluY2x1ZGVJZCkgewogICAgICAgICAgICBqc29uLklEXyA9IHNuYXBzaG90LmlkOwogICAgICAgICAgfQogICAgICAgICAgIHJldHVybiBqc29uOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBmdW5jdGlvbiBzZXJ2ZXJBdHRyaWJ1dGVOYW1lKGF0dHJpYnV0ZSkgewogICAgICAgIHJldHVybiBhdHRyaWJ1dGUudW5kZXJzY29yZSgpLnRvVXBwZXJDYXNlKCk7CiAgICAgIH0KICAgICAgIGZ1bmN0aW9uIHNlcnZlckhhc01hbnlOYW1lKG5hbWUpIHsKICAgICAgICByZXR1cm4gc2VydmVyQXR0cmlidXRlTmFtZShzaW5ndWxhcml6ZShuYW1lKSkgKyAiX0lEUyI7CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBUaGlzIHNlcmlhbGl6ZXIgd2lsbCBnZW5lcmF0ZSBKU09OIHRoYXQgbG9va3MgbGlrZSB0aGlzOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICB7CiAgICAgICAgIlRJVExFIjogIlJhaWxzIGlzIG9tYWthc2UiLAogICAgICAgICJCT0RZIjogIlllcC4gT21ha2FzZS4iLAogICAgICAgICJDT01NRU5UX0lEUyI6IFsgMSwgMiwgMyBdCiAgICAgIH0KICAgICAgYGBgCiAgICAgICAjIyBUd2Vha2luZyB0aGUgRGVmYXVsdCBKU09OCiAgICAgICBJZiB5b3UganVzdCB3YW50IHRvIGRvIHNvbWUgc21hbGwgdHdlYWtzIG9uIHRoZSBkZWZhdWx0IEpTT04sCiAgICAgIHlvdSBjYW4gY2FsbCBzdXBlciBmaXJzdCBhbmQgbWFrZSB0aGUgdHdlYWtzIG9uIHRoZSByZXR1cm5lZAogICAgICBKU09OLgogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL3Bvc3QuanMKICAgICAgaW1wb3J0IEpTT05TZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIHNlcmlhbGl6ZShzbmFwc2hvdCwgb3B0aW9ucykgewogICAgICAgICAgdmFyIGpzb24gPSB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogICAgICAgICAgIGpzb24uc3ViamVjdCA9IGpzb24udGl0bGU7CiAgICAgICAgICBkZWxldGUganNvbi50aXRsZTsKICAgICAgICAgICByZXR1cm4ganNvbjsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc2VyaWFsaXplCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgIEByZXR1cm4ge09iamVjdH0ganNvbgogICAgKi8KICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gc2VyaWFsaXplKHNuYXBzaG90LCBvcHRpb25zKSB7CiAgICAgIHZhciBfdGhpczUgPSB0aGlzOwoKICAgICAgdmFyIGpzb24gPSB7fTsKCiAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuaW5jbHVkZUlkKSB7CiAgICAgICAgdmFyIGlkID0gc25hcHNob3QuaWQ7CgogICAgICAgIGlmIChpZCkgewogICAgICAgICAganNvbltFbWJlci5nZXQodGhpcywgJ3ByaW1hcnlLZXknKV0gPSBpZDsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHNuYXBzaG90LmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24gKGtleSwgYXR0cmlidXRlKSB7CiAgICAgICAgX3RoaXM1LnNlcmlhbGl6ZUF0dHJpYnV0ZShzbmFwc2hvdCwganNvbiwga2V5LCBhdHRyaWJ1dGUpOwogICAgICB9KTsKICAgICAgc25hcHNob3QuZWFjaFJlbGF0aW9uc2hpcChmdW5jdGlvbiAoa2V5LCByZWxhdGlvbnNoaXApIHsKICAgICAgICBpZiAocmVsYXRpb25zaGlwLmtpbmQgPT09ICdiZWxvbmdzVG8nKSB7CiAgICAgICAgICBfdGhpczUuc2VyaWFsaXplQmVsb25nc1RvKHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApOwogICAgICAgIH0gZWxzZSBpZiAocmVsYXRpb25zaGlwLmtpbmQgPT09ICdoYXNNYW55JykgewogICAgICAgICAgX3RoaXM1LnNlcmlhbGl6ZUhhc01hbnkoc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIGpzb247CiAgICB9LAoKICAgIC8qKgogICAgICBZb3UgY2FuIHVzZSB0aGlzIG1ldGhvZCB0byBjdXN0b21pemUgaG93IGEgc2VyaWFsaXplZCByZWNvcmQgaXMgYWRkZWQgdG8gdGhlIGNvbXBsZXRlCiAgICAgIEpTT04gaGFzaCB0byBiZSBzZW50IHRvIHRoZSBzZXJ2ZXIuIEJ5IGRlZmF1bHQgdGhlIEpTT04gU2VyaWFsaXplciBkb2VzIG5vdCBuYW1lc3BhY2UKICAgICAgdGhlIHBheWxvYWQgYW5kIGp1c3Qgc2VuZHMgdGhlIHJhdyBzZXJpYWxpemVkIEpTT04gb2JqZWN0LgogICAgICBJZiB5b3VyIHNlcnZlciBleHBlY3RzIG5hbWVzcGFjZWQga2V5cywgeW91IHNob3VsZCBjb25zaWRlciB1c2luZyB0aGUgUkVTVFNlcmlhbGl6ZXIuCiAgICAgIE90aGVyd2lzZSB5b3UgY2FuIG92ZXJyaWRlIHRoaXMgbWV0aG9kIHRvIGN1c3RvbWl6ZSBob3cgdGhlIHJlY29yZCBpcyBhZGRlZCB0byB0aGUgaGFzaC4KICAgICAgVGhlIGhhc2ggcHJvcGVydHkgc2hvdWxkIGJlIG1vZGlmaWVkIGJ5IHJlZmVyZW5jZS4KICAgICAgIEZvciBleGFtcGxlLCB5b3VyIHNlcnZlciBtYXkgZXhwZWN0IHVuZGVyc2NvcmVkIHJvb3Qgb2JqZWN0cy4KICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKICAgICAgaW1wb3J0IHsgZGVjYW1lbGl6ZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBzZXJpYWxpemVJbnRvSGFzaChkYXRhLCB0eXBlLCBzbmFwc2hvdCwgb3B0aW9ucykgewogICAgICAgICAgdmFyIHJvb3QgPSBkZWNhbWVsaXplKHR5cGUubW9kZWxOYW1lKTsKICAgICAgICAgIGRhdGFbcm9vdF0gPSB0aGlzLnNlcmlhbGl6ZShzbmFwc2hvdCwgb3B0aW9ucyk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZUludG9IYXNoCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBoYXNoCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGVDbGFzcwogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgKi8KICAgIHNlcmlhbGl6ZUludG9IYXNoOiBmdW5jdGlvbiBzZXJpYWxpemVJbnRvSGFzaChoYXNoLCB0eXBlQ2xhc3MsIHNuYXBzaG90LCBvcHRpb25zKSB7CiAgICAgIEVtYmVyLmFzc2lnbihoYXNoLCB0aGlzLnNlcmlhbGl6ZShzbmFwc2hvdCwgb3B0aW9ucykpOwogICAgfSwKCiAgICAvKioKICAgICAgYHNlcmlhbGl6ZUF0dHJpYnV0ZWAgY2FuIGJlIHVzZWQgdG8gY3VzdG9taXplIGhvdyBgYXR0cmAKICAgICAgcHJvcGVydGllcyBhcmUgc2VyaWFsaXplZAogICAgICAgRm9yIGV4YW1wbGUgaWYgeW91IHdhbnRlZCB0byBlbnN1cmUgYWxsIHlvdXIgYXR0cmlidXRlcyB3ZXJlIGFsd2F5cwogICAgICBzZXJpYWxpemVkIGFzIHByb3BlcnRpZXMgb24gYW4gYGF0dHJpYnV0ZXNgIG9iamVjdCB5b3UgY291bGQKICAgICAgd3JpdGU6CiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IEpTT05TZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIHNlcmlhbGl6ZUF0dHJpYnV0ZShzbmFwc2hvdCwganNvbiwga2V5LCBhdHRyaWJ1dGVzKSB7CiAgICAgICAgICBqc29uLmF0dHJpYnV0ZXMgPSBqc29uLmF0dHJpYnV0ZXMgfHwge307CiAgICAgICAgICB0aGlzLl9zdXBlcihzbmFwc2hvdCwganNvbi5hdHRyaWJ1dGVzLCBrZXksIGF0dHJpYnV0ZXMpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXJpYWxpemVBdHRyaWJ1dGUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHBhcmFtIHtPYmplY3R9IGpzb24KICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleQogICAgICBAcGFyYW0ge09iamVjdH0gYXR0cmlidXRlCiAgICAqLwogICAgc2VyaWFsaXplQXR0cmlidXRlOiBmdW5jdGlvbiBzZXJpYWxpemVBdHRyaWJ1dGUoc25hcHNob3QsIGpzb24sIGtleSwgYXR0cmlidXRlKSB7CiAgICAgIGlmICh0aGlzLl9jYW5TZXJpYWxpemUoa2V5KSkgewogICAgICAgIHZhciB0eXBlID0gYXR0cmlidXRlLnR5cGU7CiAgICAgICAgdmFyIHZhbHVlID0gc25hcHNob3QuYXR0cihrZXkpOwoKICAgICAgICBpZiAodHlwZSkgewogICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHRoaXMudHJhbnNmb3JtRm9yKHR5cGUpOwogICAgICAgICAgdmFsdWUgPSB0cmFuc2Zvcm0uc2VyaWFsaXplKHZhbHVlLCBhdHRyaWJ1dGUub3B0aW9ucyk7CiAgICAgICAgfSAvLyBpZiBwcm92aWRlZCwgdXNlIHRoZSBtYXBwaW5nIHByb3ZpZGVkIGJ5IGBhdHRyc2AgaW4KICAgICAgICAvLyB0aGUgc2VyaWFsaXplcgoKCiAgICAgICAgdmFyIHBheWxvYWRLZXkgPSB0aGlzLl9nZXRNYXBwZWRLZXkoa2V5LCBzbmFwc2hvdC50eXBlKTsKCiAgICAgICAgaWYgKHBheWxvYWRLZXkgPT09IGtleSAmJiB0aGlzLmtleUZvckF0dHJpYnV0ZSkgewogICAgICAgICAgcGF5bG9hZEtleSA9IHRoaXMua2V5Rm9yQXR0cmlidXRlKGtleSwgJ3NlcmlhbGl6ZScpOwogICAgICAgIH0KCiAgICAgICAganNvbltwYXlsb2FkS2V5XSA9IHZhbHVlOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBgc2VyaWFsaXplQmVsb25nc1RvYCBjYW4gYmUgdXNlZCB0byBjdXN0b21pemUgaG93IGBiZWxvbmdzVG9gCiAgICAgIHByb3BlcnRpZXMgYXJlIHNlcmlhbGl6ZWQuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgSlNPTlNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uJzsKICAgICAgaW1wb3J0IHsgaXNOb25lIH0gZnJvbSAnQGVtYmVyL3V0aWxzJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05TZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgc2VyaWFsaXplQmVsb25nc1RvKHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApIHsKICAgICAgICAgIHZhciBrZXkgPSByZWxhdGlvbnNoaXAua2V5OwogICAgICAgICAgdmFyIGJlbG9uZ3NUbyA9IHNuYXBzaG90LmJlbG9uZ3NUbyhrZXkpOwogICAgICAgICAgIGtleSA9IHRoaXMua2V5Rm9yUmVsYXRpb25zaGlwID8gdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXAoa2V5LCAiYmVsb25nc1RvIiwgInNlcmlhbGl6ZSIpIDoga2V5OwogICAgICAgICAgIGpzb25ba2V5XSA9IGlzTm9uZShiZWxvbmdzVG8pID8gYmVsb25nc1RvIDogYmVsb25nc1RvLnJlY29yZC50b0pTT04oKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc2VyaWFsaXplQmVsb25nc1RvCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEBwYXJhbSB7T2JqZWN0fSBqc29uCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZWxhdGlvbnNoaXAKICAgICovCiAgICBzZXJpYWxpemVCZWxvbmdzVG86IGZ1bmN0aW9uIHNlcmlhbGl6ZUJlbG9uZ3NUbyhzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBrZXkgPSByZWxhdGlvbnNoaXAua2V5OwoKICAgICAgaWYgKHRoaXMuX2NhblNlcmlhbGl6ZShrZXkpKSB7CiAgICAgICAgdmFyIGJlbG9uZ3NUb0lkID0gc25hcHNob3QuYmVsb25nc1RvKGtleSwgewogICAgICAgICAgaWQ6IHRydWUKICAgICAgICB9KTsgLy8gaWYgcHJvdmlkZWQsIHVzZSB0aGUgbWFwcGluZyBwcm92aWRlZCBieSBgYXR0cnNgIGluCiAgICAgICAgLy8gdGhlIHNlcmlhbGl6ZXIKCiAgICAgICAgdmFyIHBheWxvYWRLZXkgPSB0aGlzLl9nZXRNYXBwZWRLZXkoa2V5LCBzbmFwc2hvdC50eXBlKTsKCiAgICAgICAgaWYgKHBheWxvYWRLZXkgPT09IGtleSAmJiB0aGlzLmtleUZvclJlbGF0aW9uc2hpcCkgewogICAgICAgICAgcGF5bG9hZEtleSA9IHRoaXMua2V5Rm9yUmVsYXRpb25zaGlwKGtleSwgJ2JlbG9uZ3NUbycsICdzZXJpYWxpemUnKTsKICAgICAgICB9IC8vTmVlZCB0byBjaGVjayB3aGV0aGVyIHRoZSBpZCBpcyB0aGVyZSBmb3IgbmV3JmFzeW5jIHJlY29yZHMKCgogICAgICAgIGlmIChFbWJlci5pc05vbmUoYmVsb25nc1RvSWQpKSB7CiAgICAgICAgICBqc29uW3BheWxvYWRLZXldID0gbnVsbDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAganNvbltwYXlsb2FkS2V5XSA9IGJlbG9uZ3NUb0lkOwogICAgICAgIH0KCiAgICAgICAgaWYgKHJlbGF0aW9uc2hpcC5vcHRpb25zLnBvbHltb3JwaGljKSB7CiAgICAgICAgICB0aGlzLnNlcmlhbGl6ZVBvbHltb3JwaGljVHlwZShzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgYHNlcmlhbGl6ZUhhc01hbnlgIGNhbiBiZSB1c2VkIHRvIGN1c3RvbWl6ZSBob3cgYGhhc01hbnlgCiAgICAgcHJvcGVydGllcyBhcmUgc2VyaWFsaXplZC4KICAgICAgRXhhbXBsZQogICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgIGltcG9ydCBKU09OU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24nOwogICAgIGltcG9ydCBEUyBmcm9tICdlbWJlci1kYXRhJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgIHNlcmlhbGl6ZUhhc01hbnkoc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCkgewogICAgICAgICB2YXIga2V5ID0gcmVsYXRpb25zaGlwLmtleTsKICAgICAgICAgaWYgKGtleSA9PT0gJ2NvbW1lbnRzJykgewogICAgICAgICAgIHJldHVybjsKICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogICAgICAgICB9CiAgICAgICB9CiAgICAgfSk7CiAgICAgYGBgCiAgICAgIEBtZXRob2Qgc2VyaWFsaXplSGFzTWFueQogICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgQHBhcmFtIHtPYmplY3R9IGpzb24KICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwCiAgICAqLwogICAgc2VyaWFsaXplSGFzTWFueTogZnVuY3Rpb24gc2VyaWFsaXplSGFzTWFueShzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBrZXkgPSByZWxhdGlvbnNoaXAua2V5OwoKICAgICAgaWYgKHRoaXMuc2hvdWxkU2VyaWFsaXplSGFzTWFueShzbmFwc2hvdCwga2V5LCByZWxhdGlvbnNoaXApKSB7CiAgICAgICAgdmFyIGhhc01hbnkgPSBzbmFwc2hvdC5oYXNNYW55KGtleSwgewogICAgICAgICAgaWRzOiB0cnVlCiAgICAgICAgfSk7CgogICAgICAgIGlmIChoYXNNYW55ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIC8vIGlmIHByb3ZpZGVkLCB1c2UgdGhlIG1hcHBpbmcgcHJvdmlkZWQgYnkgYGF0dHJzYCBpbgogICAgICAgICAgLy8gdGhlIHNlcmlhbGl6ZXIKICAgICAgICAgIHZhciBwYXlsb2FkS2V5ID0gdGhpcy5fZ2V0TWFwcGVkS2V5KGtleSwgc25hcHNob3QudHlwZSk7CgogICAgICAgICAgaWYgKHBheWxvYWRLZXkgPT09IGtleSAmJiB0aGlzLmtleUZvclJlbGF0aW9uc2hpcCkgewogICAgICAgICAgICBwYXlsb2FkS2V5ID0gdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXAoa2V5LCAnaGFzTWFueScsICdzZXJpYWxpemUnKTsKICAgICAgICAgIH0KCiAgICAgICAgICBqc29uW3BheWxvYWRLZXldID0gaGFzTWFueTsgLy8gVE9ETyBzdXBwb3J0IGZvciBwb2x5bW9ycGhpYyBtYW55VG9Ob25lIGFuZCBtYW55VG9NYW55IHJlbGF0aW9uc2hpcHMKICAgICAgICB9CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIFlvdSBjYW4gdXNlIHRoaXMgbWV0aG9kIHRvIGN1c3RvbWl6ZSBob3cgcG9seW1vcnBoaWMgb2JqZWN0cyBhcmUKICAgICAgc2VyaWFsaXplZC4gT2JqZWN0cyBhcmUgY29uc2lkZXJlZCB0byBiZSBwb2x5bW9ycGhpYyBpZgogICAgICBgeyBwb2x5bW9ycGhpYzogdHJ1ZSB9YCBpcyBwYXNzIGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgdG8gdGhlCiAgICAgIGBiZWxvbmdzVG9gIGZ1bmN0aW9uLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL2NvbW1lbnQuanMKICAgICAgaW1wb3J0IEpTT05TZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbic7CiAgICAgIGltcG9ydCB7IGlzTm9uZSB9IGZyb20gJ0BlbWJlci91dGlscyc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIHNlcmlhbGl6ZVBvbHltb3JwaGljVHlwZShzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKSB7CiAgICAgICAgICB2YXIga2V5ID0gcmVsYXRpb25zaGlwLmtleTsKICAgICAgICAgIHZhciBiZWxvbmdzVG8gPSBzbmFwc2hvdC5iZWxvbmdzVG8oa2V5KTsKICAgICAgICAgICBrZXkgPSB0aGlzLmtleUZvckF0dHJpYnV0ZSA/IHRoaXMua2V5Rm9yQXR0cmlidXRlKGtleSwgJ3NlcmlhbGl6ZScpIDoga2V5OwogICAgICAgICAgIGlmIChpc05vbmUoYmVsb25nc1RvKSkgewogICAgICAgICAgICBqc29uW2tleSArICdfdHlwZSddID0gbnVsbDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGpzb25ba2V5ICsgJ190eXBlJ10gPSBiZWxvbmdzVG8ubW9kZWxOYW1lOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXJpYWxpemVQb2x5bW9ycGhpY1R5cGUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHBhcmFtIHtPYmplY3R9IGpzb24KICAgICAgQHBhcmFtIHtPYmplY3R9IHJlbGF0aW9uc2hpcAogICAgKi8KICAgIHNlcmlhbGl6ZVBvbHltb3JwaGljVHlwZTogZnVuY3Rpb24gc2VyaWFsaXplUG9seW1vcnBoaWNUeXBlKCkge30sCgogICAgLyoqCiAgICAgIGBleHRyYWN0TWV0YWAgaXMgdXNlZCB0byBkZXNlcmlhbGl6ZSBhbnkgbWV0YSBpbmZvcm1hdGlvbiBpbiB0aGUKICAgICAgYWRhcHRlciBwYXlsb2FkLiBCeSBkZWZhdWx0IEVtYmVyIERhdGEgZXhwZWN0cyBtZXRhIGluZm9ybWF0aW9uIHRvCiAgICAgIGJlIGxvY2F0ZWQgb24gdGhlIGBtZXRhYCBwcm9wZXJ0eSBvZiB0aGUgcGF5bG9hZCBvYmplY3QuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgSlNPTlNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05TZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgZXh0cmFjdE1ldGEoc3RvcmUsIHR5cGVDbGFzcywgcGF5bG9hZCkgewogICAgICAgICAgaWYgKHBheWxvYWQgJiYgcGF5bG9hZC5oYXNPd25Qcm9wZXJ0eSgnX3BhZ2luYXRpb24nKSkgewogICAgICAgICAgICBsZXQgbWV0YSA9IHBheWxvYWQuX3BhZ2luYXRpb247CiAgICAgICAgICAgIGRlbGV0ZSBwYXlsb2FkLl9wYWdpbmF0aW9uOwogICAgICAgICAgICByZXR1cm4gbWV0YTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZXh0cmFjdE1ldGEKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gbW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgKi8KICAgIGV4dHJhY3RNZXRhOiBmdW5jdGlvbiBleHRyYWN0TWV0YShzdG9yZSwgbW9kZWxDbGFzcywgcGF5bG9hZCkgewogICAgICBpZiAocGF5bG9hZCAmJiBwYXlsb2FkWydtZXRhJ10gIT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhciBtZXRhID0gcGF5bG9hZC5tZXRhOwogICAgICAgIGRlbGV0ZSBwYXlsb2FkLm1ldGE7CiAgICAgICAgcmV0dXJuIG1ldGE7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIGBleHRyYWN0RXJyb3JzYCBpcyB1c2VkIHRvIGV4dHJhY3QgbW9kZWwgZXJyb3JzIHdoZW4gYSBjYWxsCiAgICAgIHRvIGBNb2RlbCNzYXZlYCBmYWlscyB3aXRoIGFuIGBJbnZhbGlkRXJyb3JgLiBCeSBkZWZhdWx0CiAgICAgIEVtYmVyIERhdGEgZXhwZWN0cyBlcnJvciBpbmZvcm1hdGlvbiB0byBiZSBsb2NhdGVkIG9uIHRoZSBgZXJyb3JzYAogICAgICBwcm9wZXJ0eSBvZiB0aGUgcGF5bG9hZCBvYmplY3QuCiAgICAgICBUaGlzIHNlcmlhbGl6ZXIgZXhwZWN0cyB0aGlzIGBlcnJvcnNgIG9iamVjdCB0byBiZSBhbiBBcnJheSBzaW1pbGFyCiAgICAgIHRvIHRoZSBmb2xsb3dpbmcsIGNvbXBsaWFudCB3aXRoIHRoZSBodHRwczovL2pzb25hcGkub3JnL2Zvcm1hdC8jZXJyb3JzIHNwZWNpZmljYXRpb246CiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgImVycm9ycyI6IFsKICAgICAgICAgIHsKICAgICAgICAgICAgImRldGFpbCI6ICJUaGlzIHVzZXJuYW1lIGlzIGFscmVhZHkgdGFrZW4hIiwKICAgICAgICAgICAgInNvdXJjZSI6IHsKICAgICAgICAgICAgICAicG9pbnRlciI6ICJkYXRhL2F0dHJpYnV0ZXMvdXNlcm5hbWUiCiAgICAgICAgICAgIH0KICAgICAgICAgIH0sIHsKICAgICAgICAgICAgImRldGFpbCI6ICJEb2Vzbid0IGxvb2sgbGlrZSBhIHZhbGlkIGVtYWlsLiIsCiAgICAgICAgICAgICJzb3VyY2UiOiB7CiAgICAgICAgICAgICAgInBvaW50ZXIiOiAiZGF0YS9hdHRyaWJ1dGVzL2VtYWlsIgogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9CiAgICAgIGBgYAogICAgICAgVGhlIGtleSBgZGV0YWlsYCBwcm92aWRlcyBhIHRleHR1YWwgZGVzY3JpcHRpb24gb2YgdGhlIHByb2JsZW0uCiAgICAgIEFsdGVybmF0aXZlbHksIHRoZSBrZXkgYHRpdGxlYCBjYW4gYmUgdXNlZCBmb3IgdGhlIHNhbWUgcHVycG9zZS4KICAgICAgIFRoZSBuZXN0ZWQga2V5cyBgc291cmNlLnBvaW50ZXJgIGRldGFpbCB3aGljaCBzcGVjaWZpYyBlbGVtZW50CiAgICAgIG9mIHRoZSByZXF1ZXN0IGRhdGEgd2FzIGludmFsaWQuCiAgICAgICBOb3RlIHRoYXQgSlNPTi1BUEkgYWxzbyBhbGxvd3MgZm9yIG9iamVjdC1sZXZlbCBlcnJvcnMgdG8gYmUgcGxhY2VkCiAgICAgIGluIGFuIG9iamVjdCB3aXRoIHBvaW50ZXIgYGRhdGFgLCBzaWduaWZ5aW5nIHRoYXQgdGhlIHByb2JsZW0KICAgICAgY2Fubm90IGJlIHRyYWNlZCB0byBhIHNwZWNpZmljIGF0dHJpYnV0ZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgewogICAgICAgICJlcnJvcnMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJkZXRhaWwiOiAiU29tZSBnZW5lcmljIG5vbiBwcm9wZXJ0eSBlcnJvciBtZXNzYWdlIiwKICAgICAgICAgICAgInNvdXJjZSI6IHsKICAgICAgICAgICAgICAicG9pbnRlciI6ICJkYXRhIgogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9CiAgICAgIGBgYAogICAgICAgV2hlbiB0dXJuIGludG8gYSBgRXJyb3JzYCBvYmplY3QsIHlvdSBjYW4gcmVhZCB0aGVzZSBlcnJvcnMKICAgICAgdGhyb3VnaCB0aGUgcHJvcGVydHkgYGJhc2VgOgogICAgICAgYGBgaGFuZGxlYmFycwogICAgICB7eyNlYWNoIG1vZGVsLmVycm9ycy5iYXNlIGFzIHxlcnJvcnx9fQogICAgICAgIDxkaXYgY2xhc3M9ImVycm9yIj4KICAgICAgICAgIHt7ZXJyb3IubWVzc2FnZX19CiAgICAgICAgPC9kaXY+CiAgICAgIHt7L2VhY2h9fQogICAgICBgYGAKICAgICAgIEV4YW1wbGUgb2YgYWx0ZXJuYXRpdmUgaW1wbGVtZW50YXRpb24sIG92ZXJyaWRpbmcgdGhlIGRlZmF1bHQKICAgICAgYmVoYXZpb3IgdG8gZGVhbCB3aXRoIGEgZGlmZmVyZW50IGZvcm1hdCBvZiBlcnJvcnM6CiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgRFMgZnJvbSAnZW1iZXItZGF0YSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIGV4dHJhY3RFcnJvcnMoc3RvcmUsIHR5cGVDbGFzcywgcGF5bG9hZCwgaWQpIHsKICAgICAgICAgIGlmIChwYXlsb2FkICYmIHR5cGVvZiBwYXlsb2FkID09PSAnb2JqZWN0JyAmJiBwYXlsb2FkLl9wcm9ibGVtcykgewogICAgICAgICAgICBwYXlsb2FkID0gcGF5bG9hZC5fcHJvYmxlbXM7CiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplRXJyb3JzKHR5cGVDbGFzcywgcGF5bG9hZCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gcGF5bG9hZDsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZXh0cmFjdEVycm9ycwogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHsoU3RyaW5nfE51bWJlcil9IGlkCiAgICAgIEByZXR1cm4ge09iamVjdH0ganNvbiBUaGUgZGVzZXJpYWxpemVkIGVycm9ycwogICAgKi8KICAgIGV4dHJhY3RFcnJvcnM6IGZ1bmN0aW9uIGV4dHJhY3RFcnJvcnMoc3RvcmUsIHR5cGVDbGFzcywgcGF5bG9hZCwgaWQpIHsKICAgICAgdmFyIF90aGlzNiA9IHRoaXM7CgogICAgICBpZiAocGF5bG9hZCAmJiB0eXBlb2YgcGF5bG9hZCA9PT0gJ29iamVjdCcgJiYgcGF5bG9hZC5lcnJvcnMpIHsKICAgICAgICBwYXlsb2FkID0gKDAsIF9wcml2YXRlLmVycm9yc0FycmF5VG9IYXNoKShwYXlsb2FkLmVycm9ycyk7CiAgICAgICAgdGhpcy5ub3JtYWxpemVVc2luZ0RlY2xhcmVkTWFwcGluZyh0eXBlQ2xhc3MsIHBheWxvYWQpOwogICAgICAgIHR5cGVDbGFzcy5lYWNoQXR0cmlidXRlKGZ1bmN0aW9uIChuYW1lKSB7CiAgICAgICAgICB2YXIga2V5ID0gX3RoaXM2LmtleUZvckF0dHJpYnV0ZShuYW1lLCAnZGVzZXJpYWxpemUnKTsKCiAgICAgICAgICBpZiAoa2V5ICE9PSBuYW1lICYmIHBheWxvYWRba2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHBheWxvYWRbbmFtZV0gPSBwYXlsb2FkW2tleV07CiAgICAgICAgICAgIGRlbGV0ZSBwYXlsb2FkW2tleV07CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgICAgdHlwZUNsYXNzLmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24gKG5hbWUpIHsKICAgICAgICAgIHZhciBrZXkgPSBfdGhpczYua2V5Rm9yUmVsYXRpb25zaGlwKG5hbWUsICdkZXNlcmlhbGl6ZScpOwoKICAgICAgICAgIGlmIChrZXkgIT09IG5hbWUgJiYgcGF5bG9hZFtrZXldICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgcGF5bG9hZFtuYW1lXSA9IHBheWxvYWRba2V5XTsKICAgICAgICAgICAgZGVsZXRlIHBheWxvYWRba2V5XTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIHBheWxvYWQ7CiAgICB9LAoKICAgIC8qKgogICAgICBga2V5Rm9yQXR0cmlidXRlYCBjYW4gYmUgdXNlZCB0byBkZWZpbmUgcnVsZXMgZm9yIGhvdyB0byBjb252ZXJ0IGFuCiAgICAgIGF0dHJpYnV0ZSBuYW1lIGluIHlvdXIgbW9kZWwgdG8gYSBrZXkgaW4geW91ciBKU09OLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBKU09OU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24nOwogICAgICBpbXBvcnQgeyB1bmRlcnNjb3JlIH0gZnJvbSAnQGVtYmVyL3N0cmluZyc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIGtleUZvckF0dHJpYnV0ZShhdHRyLCBtZXRob2QpIHsKICAgICAgICAgIHJldHVybiB1bmRlcnNjb3JlKGF0dHIpLnRvVXBwZXJDYXNlKCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGtleUZvckF0dHJpYnV0ZQogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QKICAgICAgQHJldHVybiB7U3RyaW5nfSBub3JtYWxpemVkIGtleQogICAgKi8KICAgIGtleUZvckF0dHJpYnV0ZTogZnVuY3Rpb24ga2V5Rm9yQXR0cmlidXRlKGtleSwgbWV0aG9kKSB7CiAgICAgIHJldHVybiBrZXk7CiAgICB9LAoKICAgIC8qKgogICAgICBga2V5Rm9yUmVsYXRpb25zaGlwYCBjYW4gYmUgdXNlZCB0byBkZWZpbmUgYSBjdXN0b20ga2V5IHdoZW4KICAgICAgc2VyaWFsaXppbmcgYW5kIGRlc2VyaWFsaXppbmcgcmVsYXRpb25zaGlwIHByb3BlcnRpZXMuIEJ5IGRlZmF1bHQKICAgICAgYEpTT05TZXJpYWxpemVyYCBkb2VzIG5vdCBwcm92aWRlIGFuIGltcGxlbWVudGF0aW9uIG9mIHRoaXMgbWV0aG9kLgogICAgICAgRXhhbXBsZQogICAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICAgIGltcG9ydCBKU09OU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24nOwogICAgICAgIGltcG9ydCB7IHVuZGVyc2NvcmUgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICAgIGtleUZvclJlbGF0aW9uc2hpcChrZXksIHJlbGF0aW9uc2hpcCwgbWV0aG9kKSB7CiAgICAgICAgICAgIHJldHVybiBgcmVsXyR7dW5kZXJzY29yZShrZXkpfWA7CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGtleUZvclJlbGF0aW9uc2hpcAogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlQ2xhc3MKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1ldGhvZAogICAgICBAcmV0dXJuIHtTdHJpbmd9IG5vcm1hbGl6ZWQga2V5CiAgICAqLwogICAga2V5Rm9yUmVsYXRpb25zaGlwOiBmdW5jdGlvbiBrZXlGb3JSZWxhdGlvbnNoaXAoa2V5LCB0eXBlQ2xhc3MsIG1ldGhvZCkgewogICAgICByZXR1cm4ga2V5OwogICAgfSwKCiAgICAvKioKICAgICBga2V5Rm9yTGlua2AgY2FuIGJlIHVzZWQgdG8gZGVmaW5lIGEgY3VzdG9tIGtleSB3aGVuIGRlc2VyaWFsaXppbmcgbGluawogICAgIHByb3BlcnRpZXMuCiAgICAgIEBtZXRob2Qga2V5Rm9yTGluawogICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkKICAgICBAcGFyYW0ge1N0cmluZ30ga2luZCBgYmVsb25nc1RvYCBvciBgaGFzTWFueWAKICAgICBAcmV0dXJuIHtTdHJpbmd9IG5vcm1hbGl6ZWQga2V5CiAgICAqLwogICAga2V5Rm9yTGluazogZnVuY3Rpb24ga2V5Rm9yTGluayhrZXksIGtpbmQpIHsKICAgICAgcmV0dXJuIGtleTsKICAgIH0sCiAgICAvLyBIRUxQRVJTCgogICAgLyoqCiAgICAgQG1ldGhvZCB0cmFuc2Zvcm1Gb3IKICAgICBAcHJpdmF0ZQogICAgIEBwYXJhbSB7U3RyaW5nfSBhdHRyaWJ1dGVUeXBlCiAgICAgQHBhcmFtIHtCb29sZWFufSBza2lwQXNzZXJ0aW9uCiAgICAgQHJldHVybiB7VHJhbnNmb3JtfSB0cmFuc2Zvcm0KICAgICovCiAgICB0cmFuc2Zvcm1Gb3I6IGZ1bmN0aW9uIHRyYW5zZm9ybUZvcihhdHRyaWJ1dGVUeXBlLCBza2lwQXNzZXJ0aW9uKSB7CiAgICAgIHZhciB0cmFuc2Zvcm0gPSBFbWJlci5nZXRPd25lcih0aGlzKS5sb29rdXAoJ3RyYW5zZm9ybTonICsgYXR0cmlidXRlVHlwZSk7CiAgICAgIChmYWxzZSAmJiAhKHNraXBBc3NlcnRpb24gfHwgISF0cmFuc2Zvcm0pICYmIEVtYmVyLmFzc2VydCgiVW5hYmxlIHRvIGZpbmQgdGhlIHRyYW5zZm9ybSBmb3IgYGF0dHIoJyIgKyBhdHRyaWJ1dGVUeXBlICsgIicpYCIsIHNraXBBc3NlcnRpb24gfHwgISF0cmFuc2Zvcm0pKTsKICAgICAgcmV0dXJuIHRyYW5zZm9ybTsKICAgIH0KICB9KTsKCiAgdmFyIF9kZWZhdWx0ID0gSlNPTlNlcmlhbGl6ZXI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKO2RlZmluZSgiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0IiwgWyJleHBvcnRzIiwgImVtYmVyLWluZmxlY3RvciIsICJAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24iLCAiQGVtYmVyLWRhdGEvc3RvcmUvLXByaXZhdGUiLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplci8tcHJpdmF0ZSIsICJAZW1iZXItZGF0YS9zdG9yZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckluZmxlY3RvciwgX2pzb24sIF9wcml2YXRlLCBfcHJpdmF0ZTIsIF9zdG9yZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiRW1iZWRkZWRSZWNvcmRzTWl4aW4iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJpdmF0ZTIuRW1iZWRkZWRSZWNvcmRzTWl4aW47CiAgICB9CiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgICBOb3JtYWxseSwgYXBwbGljYXRpb25zIHdpbGwgdXNlIHRoZSBgUkVTVFNlcmlhbGl6ZXJgIGJ5IGltcGxlbWVudGluZwogICAgdGhlIGBub3JtYWxpemVgIG1ldGhvZC4KICAKICAgIFRoaXMgYWxsb3dzIHlvdSB0byBkbyB3aGF0ZXZlciBraW5kIG9mIG11bmdpbmcgeW91IG5lZWQgYW5kIGlzCiAgICBlc3BlY2lhbGx5IHVzZWZ1bCBpZiB5b3VyIHNlcnZlciBpcyBpbmNvbnNpc3RlbnQgYW5kIHlvdSBuZWVkIHRvCiAgICBkbyBtdW5naW5nIGRpZmZlcmVudGx5IGZvciBtYW55IGRpZmZlcmVudCBraW5kcyBvZiByZXNwb25zZXMuCiAgCiAgICBTZWUgdGhlIGBub3JtYWxpemVgIGRvY3VtZW50YXRpb24gZm9yIG1vcmUgaW5mb3JtYXRpb24uCiAgCiAgICAjIyBBY3Jvc3MgdGhlIEJvYXJkIE5vcm1hbGl6YXRpb24KICAKICAgIFRoZXJlIGFyZSBhbHNvIGEgbnVtYmVyIG9mIGhvb2tzIHRoYXQgeW91IG1pZ2h0IGZpbmQgdXNlZnVsIHRvIGRlZmluZQogICAgYWNyb3NzLXRoZS1ib2FyZCBydWxlcyBmb3IgeW91ciBwYXlsb2FkLiBUaGVzZSBydWxlcyB3aWxsIGJlIHVzZWZ1bAogICAgaWYgeW91ciBzZXJ2ZXIgaXMgY29uc2lzdGVudCwgb3IgaWYgeW91J3JlIGJ1aWxkaW5nIGFuIGFkYXB0ZXIgZm9yCiAgICBhbiBpbmZyYXN0cnVjdHVyZSBzZXJ2aWNlLCBsaWtlIEZpcmViYXNlLCBhbmQgd2FudCB0byBlbmNvZGUgc2VydmljZQogICAgY29udmVudGlvbnMuCiAgCiAgICBGb3IgZXhhbXBsZSwgaWYgYWxsIG9mIHlvdXIga2V5cyBhcmUgdW5kZXJzY29yZWQgYW5kIGFsbC1jYXBzLCBidXQKICAgIG90aGVyd2lzZSBjb25zaXN0ZW50IHdpdGggdGhlIG5hbWVzIHlvdSB1c2UgaW4geW91ciBtb2RlbHMsIHlvdQogICAgY2FuIGltcGxlbWVudCBhY3Jvc3MtdGhlLWJvYXJkIHJ1bGVzIGZvciBob3cgdG8gY29udmVydCBhbiBhdHRyaWJ1dGUKICAgIG5hbWUgaW4geW91ciBtb2RlbCB0byBhIGtleSBpbiB5b3VyIEpTT04uCiAgCiAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSRVNUU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgaW1wb3J0IHsgdW5kZXJzY29yZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAga2V5Rm9yQXR0cmlidXRlKGF0dHIsIG1ldGhvZCkgewogICAgICAgIHJldHVybiB1bmRlcnNjb3JlKGF0dHIpLnRvVXBwZXJDYXNlKCk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBZb3UgY2FuIGFsc28gaW1wbGVtZW50IGBrZXlGb3JSZWxhdGlvbnNoaXBgLCB3aGljaCB0YWtlcyB0aGUgbmFtZQogICAgb2YgdGhlIHJlbGF0aW9uc2hpcCBhcyB0aGUgZmlyc3QgcGFyYW1ldGVyLCB0aGUga2luZCBvZgogICAgcmVsYXRpb25zaGlwIChgaGFzTWFueWAgb3IgYGJlbG9uZ3NUb2ApIGFzIHRoZSBzZWNvbmQgcGFyYW1ldGVyLCBhbmQKICAgIHRoZSBtZXRob2QgKGBzZXJpYWxpemVgIG9yIGBkZXNlcmlhbGl6ZWApIGFzIHRoZSB0aGlyZCBwYXJhbWV0ZXIuCiAgCiAgICBAY2xhc3MgUkVTVFNlcmlhbGl6ZXIKICAgIEBleHRlbmRzIEpTT05TZXJpYWxpemVyCiAgKi8KICB2YXIgUkVTVFNlcmlhbGl6ZXIgPSBfanNvbi5kZWZhdWx0LmV4dGVuZCh7CiAgICAvKioKICAgICBga2V5Rm9yUG9seW1vcnBoaWNUeXBlYCBjYW4gYmUgdXNlZCB0byBkZWZpbmUgYSBjdXN0b20ga2V5IHdoZW4KICAgICBzZXJpYWxpemluZyBhbmQgZGVzZXJpYWxpemluZyBhIHBvbHltb3JwaGljIHR5cGUuIEJ5IGRlZmF1bHQsIHRoZQogICAgIHJldHVybmVkIGtleSBpcyBgJHtrZXl9VHlwZWAuCiAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBSRVNUU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBrZXlGb3JQb2x5bW9ycGhpY1R5cGUoa2V5LCByZWxhdGlvbnNoaXApIHsKICAgICAgICAgIHZhciByZWxhdGlvbnNoaXBLZXkgPSB0aGlzLmtleUZvclJlbGF0aW9uc2hpcChrZXkpOwogICAgICAgICAgIHJldHVybiAndHlwZS0nICsgcmVsYXRpb25zaGlwS2V5OwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICBAbWV0aG9kIGtleUZvclBvbHltb3JwaGljVHlwZQogICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkKICAgICBAcGFyYW0ge1N0cmluZ30gdHlwZUNsYXNzCiAgICAgQHBhcmFtIHtTdHJpbmd9IG1ldGhvZAogICAgIEByZXR1cm4ge1N0cmluZ30gbm9ybWFsaXplZCBrZXkKICAgICovCiAgICBrZXlGb3JQb2x5bW9ycGhpY1R5cGU6IGZ1bmN0aW9uIGtleUZvclBvbHltb3JwaGljVHlwZShrZXksIHR5cGVDbGFzcywgbWV0aG9kKSB7CiAgICAgIHZhciByZWxhdGlvbnNoaXBLZXkgPSB0aGlzLmtleUZvclJlbGF0aW9uc2hpcChrZXkpOwogICAgICByZXR1cm4gcmVsYXRpb25zaGlwS2V5ICsgIlR5cGUiOwogICAgfSwKCiAgICAvKioKICAgICAgTm9ybWFsaXplcyBhIHBhcnQgb2YgdGhlIEpTT04gcGF5bG9hZCByZXR1cm5lZCBieQogICAgICB0aGUgc2VydmVyLiBZb3Ugc2hvdWxkIG92ZXJyaWRlIHRoaXMgbWV0aG9kLCBtdW5nZSB0aGUgaGFzaAogICAgICBhbmQgY2FsbCBzdXBlciBpZiB5b3UgaGF2ZSBnZW5lcmljIG5vcm1hbGl6YXRpb24gdG8gZG8uCiAgICAgICBJdCB0YWtlcyB0aGUgdHlwZSBvZiB0aGUgcmVjb3JkIHRoYXQgaXMgYmVpbmcgbm9ybWFsaXplZAogICAgICAoYXMgYSBNb2RlbCBjbGFzcyksIHRoZSBwcm9wZXJ0eSB3aGVyZSB0aGUgaGFzaCB3YXMKICAgICAgb3JpZ2luYWxseSBmb3VuZCwgYW5kIHRoZSBoYXNoIHRvIG5vcm1hbGl6ZS4KICAgICAgIEZvciBleGFtcGxlLCBpZiB5b3UgaGF2ZSBhIHBheWxvYWQgdGhhdCBsb29rcyBsaWtlIHRoaXM6CiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgInBvc3QiOiB7CiAgICAgICAgICAiaWQiOiAxLAogICAgICAgICAgInRpdGxlIjogIlJhaWxzIGlzIG9tYWthc2UiLAogICAgICAgICAgImNvbW1lbnRzIjogWyAxLCAyIF0KICAgICAgICB9LAogICAgICAgICJjb21tZW50cyI6IFt7CiAgICAgICAgICAiaWQiOiAxLAogICAgICAgICAgImJvZHkiOiAiRklSU1QiCiAgICAgICAgfSwgewogICAgICAgICAgImlkIjogMiwKICAgICAgICAgICJib2R5IjogIlJhaWxzIGlzIHVuYWdpIgogICAgICAgIH1dCiAgICAgIH0KICAgICAgYGBgCiAgICAgICBUaGUgYG5vcm1hbGl6ZWAgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIHRocmVlIHRpbWVzOgogICAgICAgKiBXaXRoIGBBcHAuUG9zdGAsIGAicG9zdHMiYCBhbmQgYHsgaWQ6IDEsIHRpdGxlOiAiUmFpbHMgaXMgb21ha2FzZSIsIC4uLiB9YAogICAgICAqIFdpdGggYEFwcC5Db21tZW50YCwgYCJjb21tZW50cyJgIGFuZCBgeyBpZDogMSwgYm9keTogIkZJUlNUIiB9YAogICAgICAqIFdpdGggYEFwcC5Db21tZW50YCwgYCJjb21tZW50cyJgIGFuZCBgeyBpZDogMiwgYm9keTogIlJhaWxzIGlzIHVuYWdpIiB9YAogICAgICAgWW91IGNhbiB1c2UgdGhpcyBtZXRob2QsIGZvciBleGFtcGxlLCB0byBub3JtYWxpemUgdW5kZXJzY29yZWQga2V5cyB0byBjYW1lbGl6ZWQKICAgICAgb3Igb3RoZXIgZ2VuZXJhbC1wdXJwb3NlIG5vcm1hbGl6YXRpb25zLiBZb3Ugd2lsbCBvbmx5IG5lZWQgdG8gaW1wbGVtZW50CiAgICAgIGBub3JtYWxpemVgIGFuZCBtYW5pcHVsYXRlIHRoZSBwYXlsb2FkIGFzIGRlc2lyZWQuCiAgICAgICBGb3IgZXhhbXBsZSwgaWYgdGhlIGBJRHNgIHVuZGVyIGAiY29tbWVudHMiYCBhcmUgcHJvdmlkZWQgYXMgYF9pZGAgaW5zdGVhZCBvZgogICAgICBgaWRgLCB5b3UgY2FuIHNwZWNpZnkgaG93IHRvIG5vcm1hbGl6ZSBqdXN0IHRoZSBjb21tZW50czoKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBSRVNUU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBub3JtYWxpemUobW9kZWwsIGhhc2gsIHByb3ApIHsKICAgICAgICAgIGlmIChwcm9wID09PSAnY29tbWVudHMnKSB7CiAgICAgICAgICAgIGhhc2guaWQgPSBoYXNoLl9pZDsKICAgICAgICAgICAgZGVsZXRlIGhhc2guX2lkOwogICAgICAgICAgfQogICAgICAgICAgIHJldHVybiB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgT24gZWFjaCBjYWxsIHRvIHRoZSBgbm9ybWFsaXplYCBtZXRob2QsIHRoZSB0aGlyZCBwYXJhbWV0ZXIgKGBwcm9wYCkgaXMgYWx3YXlzCiAgICAgIG9uZSBvZiB0aGUga2V5cyB0aGF0IHdlcmUgaW4gdGhlIG9yaWdpbmFsIHBheWxvYWQgb3IgaW4gdGhlIHJlc3VsdCBvZiBhbm90aGVyCiAgICAgIG5vcm1hbGl6YXRpb24gYXMgYG5vcm1hbGl6ZVJlc3BvbnNlYC4KICAgICAgIEBtZXRob2Qgbm9ybWFsaXplCiAgICAgIEBwYXJhbSB7TW9kZWx9IG1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlc291cmNlSGFzaAogICAgICBAcGFyYW0ge1N0cmluZ30gcHJvcAogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwoKICAgIC8qKgogICAgICBOb3JtYWxpemVzIGFuIGFycmF5IG9mIHJlc291cmNlIHBheWxvYWRzIGFuZCByZXR1cm5zIGEgSlNPTi1BUEkgRG9jdW1lbnQKICAgICAgd2l0aCBwcmltYXJ5IGRhdGEgYW5kLCBpZiBhbnksIGluY2x1ZGVkIGRhdGEgYXMgYHsgZGF0YSwgaW5jbHVkZWQgfWAuCiAgICAgICBAbWV0aG9kIF9ub3JtYWxpemVBcnJheQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBhcnJheUhhc2gKICAgICAgQHBhcmFtIHtTdHJpbmd9IHByb3AKICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ub3JtYWxpemVBcnJheTogZnVuY3Rpb24gX25vcm1hbGl6ZUFycmF5KHN0b3JlLCBtb2RlbE5hbWUsIGFycmF5SGFzaCwgcHJvcCkgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgdmFyIGRvY3VtZW50SGFzaCA9IHsKICAgICAgICBkYXRhOiBbXSwKICAgICAgICBpbmNsdWRlZDogW10KICAgICAgfTsKICAgICAgdmFyIG1vZGVsQ2xhc3MgPSBzdG9yZS5tb2RlbEZvcihtb2RlbE5hbWUpOwogICAgICB2YXIgc2VyaWFsaXplciA9IHN0b3JlLnNlcmlhbGl6ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgRW1iZXIubWFrZUFycmF5KGFycmF5SGFzaCkuZm9yRWFjaChmdW5jdGlvbiAoaGFzaCkgewogICAgICAgIHZhciBfdGhpcyRfbm9ybWFsaXplUG9seW0gPSBfdGhpcy5fbm9ybWFsaXplUG9seW1vcnBoaWNSZWNvcmQoc3RvcmUsIGhhc2gsIHByb3AsIG1vZGVsQ2xhc3MsIHNlcmlhbGl6ZXIpLAogICAgICAgICAgICBkYXRhID0gX3RoaXMkX25vcm1hbGl6ZVBvbHltLmRhdGEsCiAgICAgICAgICAgIGluY2x1ZGVkID0gX3RoaXMkX25vcm1hbGl6ZVBvbHltLmluY2x1ZGVkOwoKICAgICAgICBkb2N1bWVudEhhc2guZGF0YS5wdXNoKGRhdGEpOwoKICAgICAgICBpZiAoaW5jbHVkZWQpIHsKICAgICAgICAgIHZhciBfZG9jdW1lbnRIYXNoJGluY2x1ZGU7CgogICAgICAgICAgKF9kb2N1bWVudEhhc2gkaW5jbHVkZSA9IGRvY3VtZW50SGFzaC5pbmNsdWRlZCkucHVzaC5hcHBseShfZG9jdW1lbnRIYXNoJGluY2x1ZGUsIGluY2x1ZGVkKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gZG9jdW1lbnRIYXNoOwogICAgfSwKICAgIF9ub3JtYWxpemVQb2x5bW9ycGhpY1JlY29yZDogZnVuY3Rpb24gX25vcm1hbGl6ZVBvbHltb3JwaGljUmVjb3JkKHN0b3JlLCBoYXNoLCBwcm9wLCBwcmltYXJ5TW9kZWxDbGFzcywgcHJpbWFyeVNlcmlhbGl6ZXIpIHsKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBwcmltYXJ5U2VyaWFsaXplcjsKICAgICAgdmFyIG1vZGVsQ2xhc3MgPSBwcmltYXJ5TW9kZWxDbGFzczsKICAgICAgdmFyIHByaW1hcnlIYXNUeXBlQXR0cmlidXRlID0gKDAsIF9wcml2YXRlMi5tb2RlbEhhc0F0dHJpYnV0ZU9yUmVsYXRpb25zaGlwTmFtZWRUeXBlKShwcmltYXJ5TW9kZWxDbGFzcyk7CgogICAgICBpZiAoIXByaW1hcnlIYXNUeXBlQXR0cmlidXRlICYmIGhhc2gudHlwZSkgewogICAgICAgIC8vIFN1cHBvcnQgcG9seW1vcnBoaWMgcmVjb3JkcyBpbiBhc3luYyByZWxhdGlvbnNoaXBzCiAgICAgICAgdmFyIG1vZGVsTmFtZSA9IHRoaXMubW9kZWxOYW1lRnJvbVBheWxvYWRLZXkoaGFzaC50eXBlKTsKCiAgICAgICAgaWYgKHN0b3JlLl9oYXNNb2RlbEZvcihtb2RlbE5hbWUpKSB7CiAgICAgICAgICBzZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcihtb2RlbE5hbWUpOwogICAgICAgICAgbW9kZWxDbGFzcyA9IHN0b3JlLm1vZGVsRm9yKG1vZGVsTmFtZSk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gc2VyaWFsaXplci5ub3JtYWxpemUobW9kZWxDbGFzcywgaGFzaCwgcHJvcCk7CiAgICB9LAoKICAgIC8qCiAgICAgIEBtZXRob2QgX25vcm1hbGl6ZVJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEBwYXJhbSB7Qm9vbGVhbn0gaXNTaW5nbGUKICAgICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ub3JtYWxpemVSZXNwb25zZTogZnVuY3Rpb24gX25vcm1hbGl6ZVJlc3BvbnNlKHN0b3JlLCBwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCwgaWQsIHJlcXVlc3RUeXBlLCBpc1NpbmdsZSkgewogICAgICB2YXIgZG9jdW1lbnRIYXNoID0gewogICAgICAgIGRhdGE6IG51bGwsCiAgICAgICAgaW5jbHVkZWQ6IFtdCiAgICAgIH07CiAgICAgIHZhciBtZXRhID0gdGhpcy5leHRyYWN0TWV0YShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQpOwoKICAgICAgaWYgKG1ldGEpIHsKICAgICAgICAoZmFsc2UgJiYgIShFbWJlci50eXBlT2YobWV0YSkgPT09ICdvYmplY3QnKSAmJiBFbWJlci5hc3NlcnQoJ1RoZSBgbWV0YWAgcmV0dXJuZWQgZnJvbSBgZXh0cmFjdE1ldGFgIGhhcyB0byBiZSBhbiBvYmplY3QsIG5vdCAiJyArIEVtYmVyLnR5cGVPZihtZXRhKSArICciLicsIEVtYmVyLnR5cGVPZihtZXRhKSA9PT0gJ29iamVjdCcpKTsKICAgICAgICBkb2N1bWVudEhhc2gubWV0YSA9IG1ldGE7CiAgICAgIH0KCiAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMocGF5bG9hZCk7CgogICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0ga2V5cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgIHZhciBwcm9wID0ga2V5c1tpXTsKICAgICAgICB2YXIgbW9kZWxOYW1lID0gcHJvcDsKICAgICAgICB2YXIgZm9yY2VkU2Vjb25kYXJ5ID0gZmFsc2U7CiAgICAgICAgLyoKICAgICAgICAgIElmIHlvdSB3YW50IHRvIHByb3ZpZGUgc2lkZWxvYWRlZCByZWNvcmRzIG9mIHRoZSBzYW1lIHR5cGUgdGhhdCB0aGUKICAgICAgICAgIHByaW1hcnkgZGF0YSB5b3UgY2FuIGRvIHRoYXQgYnkgcHJlZml4aW5nIHRoZSBrZXkgd2l0aCBgX2AuCiAgICAgICAgICAgRXhhbXBsZQogICAgICAgICAgIGBgYAogICAgICAgICAgewogICAgICAgICAgICB1c2VyczogWwogICAgICAgICAgICAgIHsgaWQ6IDEsIHRpdGxlOiAnVG9tJywgbWFuYWdlcjogMyB9LAogICAgICAgICAgICAgIHsgaWQ6IDIsIHRpdGxlOiAnWWVodWRhJywgbWFuYWdlcjogMyB9CiAgICAgICAgICAgIF0sCiAgICAgICAgICAgIF91c2VyczogWwogICAgICAgICAgICAgIHsgaWQ6IDMsIHRpdGxlOiAnVG9tc3RlcicgfQogICAgICAgICAgICBdCiAgICAgICAgICB9CiAgICAgICAgICBgYGAKICAgICAgICAgICBUaGlzIGZvcmNlcyBgX3VzZXJzYCB0byBiZSBhZGRlZCB0byBgaW5jbHVkZWRgIGluc3RlYWQgb2YgYGRhdGFgLgogICAgICAgICAqLwoKICAgICAgICBpZiAocHJvcC5jaGFyQXQoMCkgPT09ICdfJykgewogICAgICAgICAgZm9yY2VkU2Vjb25kYXJ5ID0gdHJ1ZTsKICAgICAgICAgIG1vZGVsTmFtZSA9IHByb3Auc3Vic3RyKDEpOwogICAgICAgIH0KCiAgICAgICAgdmFyIHR5cGVOYW1lID0gdGhpcy5tb2RlbE5hbWVGcm9tUGF5bG9hZEtleShtb2RlbE5hbWUpOwoKICAgICAgICBpZiAoIXN0b3JlLl9oYXNNb2RlbEZvcih0eXBlTmFtZSkpIHsKICAgICAgICAgIChmYWxzZSAmJiBFbWJlci53YXJuKHRoaXMud2Fybk1lc3NhZ2VOb01vZGVsRm9yS2V5KG1vZGVsTmFtZSwgdHlwZU5hbWUpLCBmYWxzZSwgewogICAgICAgICAgICBpZDogJ2RzLnNlcmlhbGl6ZXIubW9kZWwtZm9yLWtleS1taXNzaW5nJwogICAgICAgICAgfSkpOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICB2YXIgaXNQcmltYXJ5ID0gIWZvcmNlZFNlY29uZGFyeSAmJiB0aGlzLmlzUHJpbWFyeVR5cGUoc3RvcmUsIHR5cGVOYW1lLCBwcmltYXJ5TW9kZWxDbGFzcyk7CiAgICAgICAgdmFyIHZhbHVlID0gcGF5bG9hZFtwcm9wXTsKCiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIGlmIChmYWxzZQogICAgICAgIC8qIERFQlVHICovCiAgICAgICAgKSB7CiAgICAgICAgICB2YXIgaXNRdWVyeVJlY29yZEFuQXJyYXkgPSByZXF1ZXN0VHlwZSA9PT0gJ3F1ZXJ5UmVjb3JkJyAmJiBpc1ByaW1hcnkgJiYgQXJyYXkuaXNBcnJheSh2YWx1ZSk7CiAgICAgICAgICB2YXIgbWVzc2FnZSA9ICdUaGUgYWRhcHRlciByZXR1cm5lZCBhbiBhcnJheSBmb3IgdGhlIHByaW1hcnkgZGF0YSBvZiBhIGBxdWVyeVJlY29yZGAgcmVzcG9uc2UuIFRoaXMgaXMgZGVwcmVjYXRlZCBhcyBgcXVlcnlSZWNvcmRgIHNob3VsZCByZXR1cm4gYSBzaW5nbGUgcmVjb3JkLic7CiAgICAgICAgICAoZmFsc2UgJiYgISghaXNRdWVyeVJlY29yZEFuQXJyYXkpICYmIEVtYmVyLmRlcHJlY2F0ZShtZXNzYWdlLCAhaXNRdWVyeVJlY29yZEFuQXJyYXksIHsKICAgICAgICAgICAgaWQ6ICdkcy5zZXJpYWxpemVyLnJlc3QucXVlcnlSZWNvcmQtYXJyYXktcmVzcG9uc2UnLAogICAgICAgICAgICB1bnRpbDogJzMuMCcsCiAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vZGVwcmVjYXRpb25zLmVtYmVyanMuY29tL2VtYmVyLWRhdGEvdjIueC8jdG9jX3N0b3JlLXF1ZXJ5cmVjb3JkLWFycmF5LXJlc3BvbnNlLXdpdGgtcmVzdHNlcmlhbGl6ZXInCiAgICAgICAgICB9KSk7CiAgICAgICAgfQogICAgICAgIC8qCiAgICAgICAgICBTdXBwb3J0IHByaW1hcnkgZGF0YSBhcyBhbiBvYmplY3QgaW5zdGVhZCBvZiBhbiBhcnJheS4KICAgICAgICAgICBFeGFtcGxlCiAgICAgICAgICAgYGBgCiAgICAgICAgICB7CiAgICAgICAgICAgIHVzZXI6IHsgaWQ6IDEsIHRpdGxlOiAnVG9tJywgbWFuYWdlcjogMyB9CiAgICAgICAgICB9CiAgICAgICAgICBgYGAKICAgICAgICAgKi8KCgogICAgICAgIGlmIChpc1ByaW1hcnkgJiYgIUFycmF5LmlzQXJyYXkodmFsdWUpKSB7CiAgICAgICAgICB2YXIgX3RoaXMkX25vcm1hbGl6ZVBvbHltMiA9IHRoaXMuX25vcm1hbGl6ZVBvbHltb3JwaGljUmVjb3JkKHN0b3JlLCB2YWx1ZSwgcHJvcCwgcHJpbWFyeU1vZGVsQ2xhc3MsIHRoaXMpLAogICAgICAgICAgICAgIF9kYXRhID0gX3RoaXMkX25vcm1hbGl6ZVBvbHltMi5kYXRhLAogICAgICAgICAgICAgIF9pbmNsdWRlZCA9IF90aGlzJF9ub3JtYWxpemVQb2x5bTIuaW5jbHVkZWQ7CgogICAgICAgICAgZG9jdW1lbnRIYXNoLmRhdGEgPSBfZGF0YTsKCiAgICAgICAgICBpZiAoX2luY2x1ZGVkKSB7CiAgICAgICAgICAgIHZhciBfZG9jdW1lbnRIYXNoJGluY2x1ZGUyOwoKICAgICAgICAgICAgKF9kb2N1bWVudEhhc2gkaW5jbHVkZTIgPSBkb2N1bWVudEhhc2guaW5jbHVkZWQpLnB1c2guYXBwbHkoX2RvY3VtZW50SGFzaCRpbmNsdWRlMiwgX2luY2x1ZGVkKTsKICAgICAgICAgIH0KCiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIHZhciBfdGhpcyRfbm9ybWFsaXplQXJyYXkgPSB0aGlzLl9ub3JtYWxpemVBcnJheShzdG9yZSwgdHlwZU5hbWUsIHZhbHVlLCBwcm9wKSwKICAgICAgICAgICAgZGF0YSA9IF90aGlzJF9ub3JtYWxpemVBcnJheS5kYXRhLAogICAgICAgICAgICBpbmNsdWRlZCA9IF90aGlzJF9ub3JtYWxpemVBcnJheS5pbmNsdWRlZDsKCiAgICAgICAgaWYgKGluY2x1ZGVkKSB7CiAgICAgICAgICB2YXIgX2RvY3VtZW50SGFzaCRpbmNsdWRlMzsKCiAgICAgICAgICAoX2RvY3VtZW50SGFzaCRpbmNsdWRlMyA9IGRvY3VtZW50SGFzaC5pbmNsdWRlZCkucHVzaC5hcHBseShfZG9jdW1lbnRIYXNoJGluY2x1ZGUzLCBpbmNsdWRlZCk7CiAgICAgICAgfQoKICAgICAgICBpZiAoaXNTaW5nbGUpIHsKICAgICAgICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAocmVzb3VyY2UpIHsKICAgICAgICAgICAgLyoKICAgICAgICAgICAgICBGaWd1cmVzIG91dCBpZiB0aGlzIGlzIHRoZSBwcmltYXJ5IHJlY29yZCBvciBub3QuCiAgICAgICAgICAgICAgIEl0J3MgZWl0aGVyOgogICAgICAgICAgICAgICAxLiBUaGUgcmVjb3JkIHdpdGggdGhlIHNhbWUgSUQgYXMgdGhlIG9yaWdpbmFsIHJlcXVlc3QKICAgICAgICAgICAgICAyLiBJZiBpdCdzIGEgbmV3bHkgY3JlYXRlZCByZWNvcmQgd2l0aG91dCBhbiBJRCwgdGhlIGZpcnN0IHJlY29yZAogICAgICAgICAgICAgICAgIGluIHRoZSBhcnJheQogICAgICAgICAgICAgKi8KICAgICAgICAgICAgdmFyIGlzVXBkYXRlZFJlY29yZCA9IGlzUHJpbWFyeSAmJiAoMCwgX3ByaXZhdGUuY29lcmNlSWQpKHJlc291cmNlLmlkKSA9PT0gaWQ7CiAgICAgICAgICAgIHZhciBpc0ZpcnN0Q3JlYXRlZFJlY29yZCA9IGlzUHJpbWFyeSAmJiAhaWQgJiYgIWRvY3VtZW50SGFzaC5kYXRhOwoKICAgICAgICAgICAgaWYgKGlzRmlyc3RDcmVhdGVkUmVjb3JkIHx8IGlzVXBkYXRlZFJlY29yZCkgewogICAgICAgICAgICAgIGRvY3VtZW50SGFzaC5kYXRhID0gcmVzb3VyY2U7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZG9jdW1lbnRIYXNoLmluY2x1ZGVkLnB1c2gocmVzb3VyY2UpOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKGlzUHJpbWFyeSkgewogICAgICAgICAgICBkb2N1bWVudEhhc2guZGF0YSA9IGRhdGE7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpZiAoZGF0YSkgewogICAgICAgICAgICAgIHZhciBfZG9jdW1lbnRIYXNoJGluY2x1ZGU0OwoKICAgICAgICAgICAgICAoX2RvY3VtZW50SGFzaCRpbmNsdWRlNCA9IGRvY3VtZW50SGFzaC5pbmNsdWRlZCkucHVzaC5hcHBseShfZG9jdW1lbnRIYXNoJGluY2x1ZGU0LCBkYXRhKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGRvY3VtZW50SGFzaDsKICAgIH0sCiAgICBpc1ByaW1hcnlUeXBlOiBmdW5jdGlvbiBpc1ByaW1hcnlUeXBlKHN0b3JlLCB0eXBlTmFtZSwgcHJpbWFyeVR5cGVDbGFzcykgewogICAgICByZXR1cm4gc3RvcmUubW9kZWxGb3IodHlwZU5hbWUpID09PSBwcmltYXJ5VHlwZUNsYXNzOwogICAgfSwKCiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgYWxsb3dzIHlvdSB0byBwdXNoIGEgcGF5bG9hZCBjb250YWluaW5nIHRvcC1sZXZlbAogICAgICBjb2xsZWN0aW9ucyBvZiByZWNvcmRzIG9yZ2FuaXplZCBwZXIgdHlwZS4KICAgICAgIGBgYGpzCiAgICAgIHsKICAgICAgICAicG9zdHMiOiBbewogICAgICAgICAgImlkIjogIjEiLAogICAgICAgICAgInRpdGxlIjogIlJhaWxzIGlzIG9tYWthc2UiLAogICAgICAgICAgImF1dGhvciIsICIxIiwKICAgICAgICAgICJjb21tZW50cyI6IFsgIjEiIF0KICAgICAgICB9XSwKICAgICAgICAiY29tbWVudHMiOiBbewogICAgICAgICAgImlkIjogIjEiLAogICAgICAgICAgImJvZHkiOiAiRklSU1QiCiAgICAgICAgfV0sCiAgICAgICAgInVzZXJzIjogW3sKICAgICAgICAgICJpZCI6ICIxIiwKICAgICAgICAgICJuYW1lIjogIkBkMmgiCiAgICAgICAgfV0KICAgICAgfQogICAgICBgYGAKICAgICAgIEl0IHdpbGwgZmlyc3Qgbm9ybWFsaXplIHRoZSBwYXlsb2FkLCBzbyB5b3UgY2FuIHVzZSB0aGlzIHRvIHB1c2gKICAgICAgaW4gZGF0YSBzdHJlYW1pbmcgaW4gZnJvbSB5b3VyIHNlcnZlciBzdHJ1Y3R1cmVkIHRoZSBzYW1lIHdheQogICAgICB0aGF0IGZldGNoZXMgYW5kIHNhdmVzIGFyZSBzdHJ1Y3R1cmVkLgogICAgICAgQG1ldGhvZCBwdXNoUGF5bG9hZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgKi8KICAgIHB1c2hQYXlsb2FkOiBmdW5jdGlvbiBwdXNoUGF5bG9hZChzdG9yZSwgcGF5bG9hZCkgewogICAgICB2YXIgZG9jdW1lbnRIYXNoID0gewogICAgICAgIGRhdGE6IFtdLAogICAgICAgIGluY2x1ZGVkOiBbXQogICAgICB9OwoKICAgICAgZm9yICh2YXIgcHJvcCBpbiBwYXlsb2FkKSB7CiAgICAgICAgdmFyIG1vZGVsTmFtZSA9IHRoaXMubW9kZWxOYW1lRnJvbVBheWxvYWRLZXkocHJvcCk7CgogICAgICAgIGlmICghc3RvcmUuX2hhc01vZGVsRm9yKG1vZGVsTmFtZSkpIHsKICAgICAgICAgIChmYWxzZSAmJiBFbWJlci53YXJuKHRoaXMud2Fybk1lc3NhZ2VOb01vZGVsRm9yS2V5KHByb3AsIG1vZGVsTmFtZSksIGZhbHNlLCB7CiAgICAgICAgICAgIGlkOiAnZHMuc2VyaWFsaXplci5tb2RlbC1mb3Ita2V5LW1pc3NpbmcnCiAgICAgICAgICB9KSk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIHZhciB0eXBlID0gc3RvcmUubW9kZWxGb3IobW9kZWxOYW1lKTsKICAgICAgICB2YXIgdHlwZVNlcmlhbGl6ZXIgPSBzdG9yZS5zZXJpYWxpemVyRm9yKHR5cGUubW9kZWxOYW1lKTsKICAgICAgICBFbWJlci5tYWtlQXJyYXkocGF5bG9hZFtwcm9wXSkuZm9yRWFjaChmdW5jdGlvbiAoaGFzaCkgewogICAgICAgICAgdmFyIF90eXBlU2VyaWFsaXplciRub3JtYSA9IHR5cGVTZXJpYWxpemVyLm5vcm1hbGl6ZSh0eXBlLCBoYXNoLCBwcm9wKSwKICAgICAgICAgICAgICBkYXRhID0gX3R5cGVTZXJpYWxpemVyJG5vcm1hLmRhdGEsCiAgICAgICAgICAgICAgaW5jbHVkZWQgPSBfdHlwZVNlcmlhbGl6ZXIkbm9ybWEuaW5jbHVkZWQ7CgogICAgICAgICAgZG9jdW1lbnRIYXNoLmRhdGEucHVzaChkYXRhKTsKCiAgICAgICAgICBpZiAoaW5jbHVkZWQpIHsKICAgICAgICAgICAgdmFyIF9kb2N1bWVudEhhc2gkaW5jbHVkZTU7CgogICAgICAgICAgICAoX2RvY3VtZW50SGFzaCRpbmNsdWRlNSA9IGRvY3VtZW50SGFzaC5pbmNsdWRlZCkucHVzaC5hcHBseShfZG9jdW1lbnRIYXNoJGluY2x1ZGU1LCBpbmNsdWRlZCk7CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHN0b3JlLnB1c2goZG9jdW1lbnRIYXNoKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gY29udmVydCBlYWNoIEpTT04gcm9vdCBrZXkgaW4gdGhlIHBheWxvYWQKICAgICAgaW50byBhIG1vZGVsTmFtZSB0aGF0IGl0IGNhbiB1c2UgdG8gbG9vayB1cCB0aGUgYXBwcm9wcmlhdGUgbW9kZWwgZm9yCiAgICAgIHRoYXQgcGFydCBvZiB0aGUgcGF5bG9hZC4KICAgICAgIEZvciBleGFtcGxlLCB5b3VyIHNlcnZlciBtYXkgc2VuZCBhIG1vZGVsIG5hbWUgdGhhdCBkb2VzIG5vdCBjb3JyZXNwb25kIHdpdGgKICAgICAgdGhlIG5hbWUgb2YgdGhlIG1vZGVsIGluIHlvdXIgYXBwLiBMZXQncyB0YWtlIGEgbG9vayBhdCBhbiBleGFtcGxlIG1vZGVsLAogICAgICBhbmQgYW4gZXhhbXBsZSBwYXlsb2FkOgogICAgICAgYGBgYXBwL21vZGVscy9wb3N0LmpzCiAgICAgIGltcG9ydCBNb2RlbCBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgICAgewogICAgICAgICAgImJsb2cvcG9zdCI6IHsKICAgICAgICAgICAgImlkIjogIjEKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIGBgYAogICAgICAgRW1iZXIgRGF0YSBpcyBnb2luZyB0byBub3JtYWxpemUgdGhlIHBheWxvYWQncyByb290IGtleSBmb3IgdGhlIG1vZGVsTmFtZS4gQXMgYSByZXN1bHQsCiAgICAgIGl0IHdpbGwgdHJ5IHRvIGxvb2sgdXAgdGhlICJibG9nL3Bvc3QiIG1vZGVsLiBTaW5jZSB3ZSBkb24ndCBoYXZlIGEgbW9kZWwgY2FsbGVkICJibG9nL3Bvc3QiCiAgICAgIChvciBhIGZpbGUgY2FsbGVkIGFwcC9tb2RlbHMvYmxvZy9wb3N0LmpzIGluIGVtYmVyLWNsaSksIEVtYmVyIERhdGEgd2lsbCB0aHJvdyBhbiBlcnJvcgogICAgICBiZWNhdXNlIGl0IGNhbm5vdCBmaW5kIHRoZSAiYmxvZy9wb3N0IiBtb2RlbC4KICAgICAgIFNpbmNlIHdlIHdhbnQgdG8gcmVtb3ZlIHRoaXMgbmFtZXNwYWNlLCB3ZSBjYW4gZGVmaW5lIGEgc2VyaWFsaXplciBmb3IgdGhlIGFwcGxpY2F0aW9uIHRoYXQgd2lsbAogICAgICByZW1vdmUgImJsb2cvIiBmcm9tIHRoZSBwYXlsb2FkIGtleSB3aGVudmVyIGl0J3MgZW5jb3VudGVyZWQgYnkgRW1iZXIgRGF0YToKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgbW9kZWxOYW1lRnJvbVBheWxvYWRLZXkocGF5bG9hZEtleSkgewogICAgICAgICAgaWYgKHBheWxvYWRLZXkgPT09ICdibG9nL3Bvc3QnKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9zdXBlcihwYXlsb2FkS2V5LnJlcGxhY2UoJ2Jsb2cvJywgJycpKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgcmV0dXJuIHRoaXMuX3N1cGVyKHBheWxvYWRLZXkpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQWZ0ZXIgcmVmcmVzaGluZywgRW1iZXIgRGF0YSB3aWxsIGFwcHJvcHJpYXRlbHkgbG9vayB1cCB0aGUgInBvc3QiIG1vZGVsLgogICAgICAgQnkgZGVmYXVsdCB0aGUgbW9kZWxOYW1lIGZvciBhIG1vZGVsIGlzIGl0cwogICAgICBuYW1lIGluIGRhc2hlcml6ZWQgZm9ybS4gVGhpcyBtZWFucyB0aGF0IGEgcGF5bG9hZCBrZXkgbGlrZSAiYmxvZ1Bvc3QiIHdvdWxkIGJlCiAgICAgIG5vcm1hbGl6ZWQgdG8gImJsb2ctcG9zdCIgd2hlbiBFbWJlciBEYXRhIGxvb2tzIHVwIHRoZSBtb2RlbC4gVXN1YWxseSwgRW1iZXIgRGF0YQogICAgICBjYW4gdXNlIHRoZSBjb3JyZWN0IGluZmxlY3Rpb24gdG8gZG8gdGhpcyBmb3IgeW91LiBNb3N0IG9mIHRoZSB0aW1lLCB5b3Ugd29uJ3QKICAgICAgbmVlZCB0byBvdmVycmlkZSBgbW9kZWxOYW1lRnJvbVBheWxvYWRLZXlgIGZvciB0aGlzIHB1cnBvc2UuCiAgICAgICBAbWV0aG9kIG1vZGVsTmFtZUZyb21QYXlsb2FkS2V5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkKICAgICAgQHJldHVybiB7U3RyaW5nfSB0aGUgbW9kZWwncyBtb2RlbE5hbWUKICAgICovCiAgICBtb2RlbE5hbWVGcm9tUGF5bG9hZEtleTogZnVuY3Rpb24gbW9kZWxOYW1lRnJvbVBheWxvYWRLZXkoa2V5KSB7CiAgICAgIHJldHVybiAoMCwgX2VtYmVySW5mbGVjdG9yLnNpbmd1bGFyaXplKSgoMCwgX3N0b3JlLm5vcm1hbGl6ZU1vZGVsTmFtZSkoa2V5KSk7CiAgICB9LAogICAgLy8gU0VSSUFMSVpFCgogICAgLyoqCiAgICAgIENhbGxlZCB3aGVuIGEgcmVjb3JkIGlzIHNhdmVkIGluIG9yZGVyIHRvIGNvbnZlcnQgdGhlCiAgICAgIHJlY29yZCBpbnRvIEpTT04uCiAgICAgICBCeSBkZWZhdWx0LCBpdCBjcmVhdGVzIGEgSlNPTiBvYmplY3Qgd2l0aCBhIGtleSBmb3IKICAgICAgZWFjaCBhdHRyaWJ1dGUgYW5kIGJlbG9uZ3NUbyByZWxhdGlvbnNoaXAuCiAgICAgICBGb3IgZXhhbXBsZSwgY29uc2lkZXIgdGhpcyBtb2RlbDoKICAgICAgIGBgYGFwcC9tb2RlbHMvY29tbWVudC5qcwogICAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciwgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICB0aXRsZTogYXR0cigpLAogICAgICAgIGJvZHk6IGF0dHIoKSwKICAgICAgICAgYXV0aG9yOiBiZWxvbmdzVG8oJ3VzZXInKQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBUaGUgZGVmYXVsdCBzZXJpYWxpemF0aW9uIHdvdWxkIGNyZWF0ZSBhIEpTT04gb2JqZWN0IGxpa2U6CiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgInRpdGxlIjogIlJhaWxzIGlzIHVuYWdpIiwKICAgICAgICAiYm9keSI6ICJSYWlscz8gT21ha2FzZT8gT19PIiwKICAgICAgICAiYXV0aG9yIjogMTIKICAgICAgfQogICAgICBgYGAKICAgICAgIEJ5IGRlZmF1bHQsIGF0dHJpYnV0ZXMgYXJlIHBhc3NlZCB0aHJvdWdoIGFzLWlzLCB1bmxlc3MKICAgICAgeW91IHNwZWNpZmllZCBhbiBhdHRyaWJ1dGUgdHlwZSAoYGF0dHIoJ2RhdGUnKWApLiBJZgogICAgICB5b3Ugc3BlY2lmeSBhIHRyYW5zZm9ybSwgdGhlIEphdmFTY3JpcHQgdmFsdWUgd2lsbCBiZQogICAgICBzZXJpYWxpemVkIHdoZW4gaW5zZXJ0ZWQgaW50byB0aGUgSlNPTiBoYXNoLgogICAgICAgQnkgZGVmYXVsdCwgYmVsb25ncy10byByZWxhdGlvbnNoaXBzIGFyZSBjb252ZXJ0ZWQgaW50bwogICAgICBJRHMgd2hlbiBpbnNlcnRlZCBpbnRvIHRoZSBKU09OIGhhc2guCiAgICAgICAjIyBJRHMKICAgICAgIGBzZXJpYWxpemVgIHRha2VzIGFuIG9wdGlvbnMgaGFzaCB3aXRoIGEgc2luZ2xlIG9wdGlvbjoKICAgICAgYGluY2x1ZGVJZGAuIElmIHRoaXMgb3B0aW9uIGlzIGB0cnVlYCwgYHNlcmlhbGl6ZWAgd2lsbCwKICAgICAgYnkgZGVmYXVsdCBpbmNsdWRlIHRoZSBJRCBpbiB0aGUgSlNPTiBvYmplY3QgaXQgYnVpbGRzLgogICAgICAgVGhlIGFkYXB0ZXIgcGFzc2VzIGluIGBpbmNsdWRlSWQ6IHRydWVgIHdoZW4gc2VyaWFsaXppbmcKICAgICAgYSByZWNvcmQgZm9yIGBjcmVhdGVSZWNvcmRgLCBidXQgbm90IGZvciBgdXBkYXRlUmVjb3JkYC4KICAgICAgICMjIEN1c3RvbWl6YXRpb24KICAgICAgIFlvdXIgc2VydmVyIG1heSBleHBlY3QgYSBkaWZmZXJlbnQgSlNPTiBmb3JtYXQgdGhhbiB0aGUKICAgICAgYnVpbHQtaW4gc2VyaWFsaXphdGlvbiBmb3JtYXQuCiAgICAgICBJbiB0aGF0IGNhc2UsIHlvdSBjYW4gaW1wbGVtZW50IGBzZXJpYWxpemVgIHlvdXJzZWxmIGFuZAogICAgICByZXR1cm4gYSBKU09OIGhhc2ggb2YgeW91ciBjaG9vc2luZy4KICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBSRVNUU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBzZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpIHsKICAgICAgICAgIHZhciBqc29uID0gewogICAgICAgICAgICBQT1NUX1RUTDogc25hcHNob3QuYXR0cigndGl0bGUnKSwKICAgICAgICAgICAgUE9TVF9CRFk6IHNuYXBzaG90LmF0dHIoJ2JvZHknKSwKICAgICAgICAgICAgUE9TVF9DTVM6IHNuYXBzaG90Lmhhc01hbnkoJ2NvbW1lbnRzJywgeyBpZHM6IHRydWUgfSkKICAgICAgICAgIH07CiAgICAgICAgICAgaWYgKG9wdGlvbnMuaW5jbHVkZUlkKSB7CiAgICAgICAgICAgIGpzb24uUE9TVF9JRF8gPSBzbmFwc2hvdC5pZDsKICAgICAgICAgIH0KICAgICAgICAgICByZXR1cm4ganNvbjsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICMjIEN1c3RvbWl6aW5nIGFuIEFwcC1XaWRlIFNlcmlhbGl6ZXIKICAgICAgIElmIHlvdSB3YW50IHRvIGRlZmluZSBhIHNlcmlhbGl6ZXIgZm9yIHlvdXIgZW50aXJlCiAgICAgIGFwcGxpY2F0aW9uLCB5b3UnbGwgcHJvYmFibHkgd2FudCB0byB1c2UgYGVhY2hBdHRyaWJ1dGVgCiAgICAgIGFuZCBgZWFjaFJlbGF0aW9uc2hpcGAgb24gdGhlIHJlY29yZC4KICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKICAgICAgaW1wb3J0IHsgcGx1cmFsaXplIH0gZnJvbSAnZW1iZXItaW5mbGVjdG9yJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgc2VyaWFsaXplKHNuYXBzaG90LCBvcHRpb25zKSB7CiAgICAgICAgICB2YXIganNvbiA9IHt9OwogICAgICAgICAgIHNuYXBzaG90LmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24obmFtZSkgewogICAgICAgICAgICBqc29uW3NlcnZlckF0dHJpYnV0ZU5hbWUobmFtZSldID0gc25hcHNob3QuYXR0cihuYW1lKTsKICAgICAgICAgIH0pOwogICAgICAgICAgIHNuYXBzaG90LmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24obmFtZSwgcmVsYXRpb25zaGlwKSB7CiAgICAgICAgICAgIGlmIChyZWxhdGlvbnNoaXAua2luZCA9PT0gJ2hhc01hbnknKSB7CiAgICAgICAgICAgICAganNvbltzZXJ2ZXJIYXNNYW55TmFtZShuYW1lKV0gPSBzbmFwc2hvdC5oYXNNYW55KG5hbWUsIHsgaWRzOiB0cnVlIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICAgICBpZiAob3B0aW9ucy5pbmNsdWRlSWQpIHsKICAgICAgICAgICAganNvbi5JRF8gPSBzbmFwc2hvdC5pZDsKICAgICAgICAgIH0KICAgICAgICAgICByZXR1cm4ganNvbjsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgZnVuY3Rpb24gc2VydmVyQXR0cmlidXRlTmFtZShhdHRyaWJ1dGUpIHsKICAgICAgICByZXR1cm4gYXR0cmlidXRlLnVuZGVyc2NvcmUoKS50b1VwcGVyQ2FzZSgpOwogICAgICB9CiAgICAgICBmdW5jdGlvbiBzZXJ2ZXJIYXNNYW55TmFtZShuYW1lKSB7CiAgICAgICAgcmV0dXJuIHNlcnZlckF0dHJpYnV0ZU5hbWUoc2luZ3VsYXJpemUobmFtZSkpICsgIl9JRFMiOwogICAgICB9CiAgICAgIGBgYAogICAgICAgVGhpcyBzZXJpYWxpemVyIHdpbGwgZ2VuZXJhdGUgSlNPTiB0aGF0IGxvb2tzIGxpa2UgdGhpczoKICAgICAgIGBgYGpzCiAgICAgIHsKICAgICAgICAiVElUTEUiOiAiUmFpbHMgaXMgb21ha2FzZSIsCiAgICAgICAgIkJPRFkiOiAiWWVwLiBPbWFrYXNlLiIsCiAgICAgICAgIkNPTU1FTlRfSURTIjogWyAxLCAyLCAzIF0KICAgICAgfQogICAgICBgYGAKICAgICAgICMjIFR3ZWFraW5nIHRoZSBEZWZhdWx0IEpTT04KICAgICAgIElmIHlvdSBqdXN0IHdhbnQgdG8gZG8gc29tZSBzbWFsbCB0d2Vha3Mgb24gdGhlIGRlZmF1bHQgSlNPTiwKICAgICAgeW91IGNhbiBjYWxsIHN1cGVyIGZpcnN0IGFuZCBtYWtlIHRoZSB0d2Vha3Mgb24gdGhlIHJldHVybmVkCiAgICAgIEpTT04uCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgc2VyaWFsaXplKHNuYXBzaG90LCBvcHRpb25zKSB7CiAgICAgICAgICB2YXIganNvbiA9IHRoaXMuX3N1cGVyKHNuYXBzaG90LCBvcHRpb25zKTsKICAgICAgICAgICBqc29uLnN1YmplY3QgPSBqc29uLnRpdGxlOwogICAgICAgICAgZGVsZXRlIGpzb24udGl0bGU7CiAgICAgICAgICAgcmV0dXJuIGpzb247CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZQogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgICBAcmV0dXJuIHtPYmplY3R9IGpzb24KICAgICovCiAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIHNlcmlhbGl6ZShzbmFwc2hvdCwgb3B0aW9ucykgewogICAgICByZXR1cm4gdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFlvdSBjYW4gdXNlIHRoaXMgbWV0aG9kIHRvIGN1c3RvbWl6ZSB0aGUgcm9vdCBrZXlzIHNlcmlhbGl6ZWQgaW50byB0aGUgSlNPTi4KICAgICAgVGhlIGhhc2ggcHJvcGVydHkgc2hvdWxkIGJlIG1vZGlmaWVkIGJ5IHJlZmVyZW5jZSAocG9zc2libHkgdXNpbmcgc29tZXRoaW5nIGxpa2UgXy5leHRlbmQpCiAgICAgIEJ5IGRlZmF1bHQgdGhlIFJFU1QgU2VyaWFsaXplciBzZW5kcyB0aGUgbW9kZWxOYW1lIG9mIGEgbW9kZWwsIHdoaWNoIGlzIGEgY2FtZWxpemVkCiAgICAgIHZlcnNpb24gb2YgdGhlIG5hbWUuCiAgICAgICBGb3IgZXhhbXBsZSwgeW91ciBzZXJ2ZXIgbWF5IGV4cGVjdCB1bmRlcnNjb3JlZCByb290IG9iamVjdHMuCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CiAgICAgIGltcG9ydCB7IGRlY2FtZWxpemUgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgc2VyaWFsaXplSW50b0hhc2goZGF0YSwgdHlwZSwgcmVjb3JkLCBvcHRpb25zKSB7CiAgICAgICAgICB2YXIgcm9vdCA9IGRlY2FtZWxpemUodHlwZS5tb2RlbE5hbWUpOwogICAgICAgICAgZGF0YVtyb290XSA9IHRoaXMuc2VyaWFsaXplKHJlY29yZCwgb3B0aW9ucyk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZUludG9IYXNoCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBoYXNoCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGVDbGFzcwogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgKi8KICAgIHNlcmlhbGl6ZUludG9IYXNoOiBmdW5jdGlvbiBzZXJpYWxpemVJbnRvSGFzaChoYXNoLCB0eXBlQ2xhc3MsIHNuYXBzaG90LCBvcHRpb25zKSB7CiAgICAgIHZhciBub3JtYWxpemVkUm9vdEtleSA9IHRoaXMucGF5bG9hZEtleUZyb21Nb2RlbE5hbWUodHlwZUNsYXNzLm1vZGVsTmFtZSk7CiAgICAgIGhhc2hbbm9ybWFsaXplZFJvb3RLZXldID0gdGhpcy5zZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICAgWW91IGNhbiB1c2UgYHBheWxvYWRLZXlGcm9tTW9kZWxOYW1lYCB0byBvdmVycmlkZSB0aGUgcm9vdCBrZXkgZm9yIGFuIG91dGdvaW5nCiAgICAgIHJlcXVlc3QuIEJ5IGRlZmF1bHQsIHRoZSBSRVNUU2VyaWFsaXplciByZXR1cm5zIGEgY2FtZWxpemVkIHZlcnNpb24gb2YgdGhlCiAgICAgIG1vZGVsJ3MgbmFtZS4KICAgICAgIEZvciBhIG1vZGVsIGNhbGxlZCBUYWNvUGFydHksIGl0cyBgbW9kZWxOYW1lYCB3b3VsZCBiZSB0aGUgc3RyaW5nIGB0YWNvLXBhcnR5YC4gVGhlIFJFU1RTZXJpYWxpemVyCiAgICAgIHdpbGwgc2VuZCBpdCB0byB0aGUgc2VydmVyIHdpdGggYHRhY29QYXJ0eWAgYXMgdGhlIHJvb3Qga2V5IGluIHRoZSBKU09OIHBheWxvYWQ6CiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgInRhY29QYXJ0eSI6IHsKICAgICAgICAgICJpZCI6ICIxIiwKICAgICAgICAgICJsb2NhdGlvbiI6ICJNYXR0aGV3IEJlYWxlJ3MgSG91c2UiCiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgRm9yIGV4YW1wbGUsIHlvdXIgc2VydmVyIG1heSBleHBlY3QgZGFzaGVyaXplZCByb290IG9iamVjdHM6CiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CiAgICAgIGltcG9ydCB7IGRhc2hlcml6ZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBwYXlsb2FkS2V5RnJvbU1vZGVsTmFtZShtb2RlbE5hbWUpIHsKICAgICAgICAgIHJldHVybiBkYXNoZXJpemUobW9kZWxOYW1lKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEdpdmVuIGEgYFRhY29QYXJ0eWAgbW9kZWwsIGNhbGxpbmcgYHNhdmVgIG9uIGl0IHdvdWxkIHByb2R1Y2UgYW4gb3V0Z29pbmcKICAgICAgcmVxdWVzdCBsaWtlOgogICAgICAgYGBganMKICAgICAgewogICAgICAgICJ0YWNvLXBhcnR5IjogewogICAgICAgICAgImlkIjogIjEiLAogICAgICAgICAgImxvY2F0aW9uIjogIk1hdHRoZXcgQmVhbGUncyBIb3VzZSIKICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHBheWxvYWRLZXlGcm9tTW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHJldHVybiB7U3RyaW5nfQogICAgKi8KICAgIHBheWxvYWRLZXlGcm9tTW9kZWxOYW1lOiBmdW5jdGlvbiBwYXlsb2FkS2V5RnJvbU1vZGVsTmFtZShtb2RlbE5hbWUpIHsKICAgICAgcmV0dXJuIEVtYmVyLlN0cmluZy5jYW1lbGl6ZShtb2RlbE5hbWUpOwogICAgfSwKCiAgICAvKioKICAgICAgWW91IGNhbiB1c2UgdGhpcyBtZXRob2QgdG8gY3VzdG9taXplIGhvdyBwb2x5bW9ycGhpYyBvYmplY3RzIGFyZSBzZXJpYWxpemVkLgogICAgICBCeSBkZWZhdWx0IHRoZSBSRVNUIFNlcmlhbGl6ZXIgY3JlYXRlcyB0aGUga2V5IGJ5IGFwcGVuZGluZyBgVHlwZWAgdG8KICAgICAgdGhlIGF0dHJpYnV0ZSBhbmQgdmFsdWUgZnJvbSB0aGUgbW9kZWwncyBjYW1lbGNhc2VkIG1vZGVsIG5hbWUuCiAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZVBvbHltb3JwaGljVHlwZQogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcGFyYW0ge09iamVjdH0ganNvbgogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwCiAgICAqLwogICAgc2VyaWFsaXplUG9seW1vcnBoaWNUeXBlOiBmdW5jdGlvbiBzZXJpYWxpemVQb2x5bW9ycGhpY1R5cGUoc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCkgewogICAgICB2YXIga2V5ID0gcmVsYXRpb25zaGlwLmtleTsKICAgICAgdmFyIHR5cGVLZXkgPSB0aGlzLmtleUZvclBvbHltb3JwaGljVHlwZShrZXksIHJlbGF0aW9uc2hpcC50eXBlLCAnc2VyaWFsaXplJyk7CiAgICAgIHZhciBiZWxvbmdzVG8gPSBzbmFwc2hvdC5iZWxvbmdzVG8oa2V5KTsKCiAgICAgIGlmIChFbWJlci5pc05vbmUoYmVsb25nc1RvKSkgewogICAgICAgIGpzb25bdHlwZUtleV0gPSBudWxsOwogICAgICB9IGVsc2UgewogICAgICAgIGpzb25bdHlwZUtleV0gPSBFbWJlci5TdHJpbmcuY2FtZWxpemUoYmVsb25nc1RvLm1vZGVsTmFtZSk7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIFlvdSBjYW4gdXNlIHRoaXMgbWV0aG9kIHRvIGN1c3RvbWl6ZSBob3cgYSBwb2x5bW9ycGhpYyByZWxhdGlvbnNoaXAgc2hvdWxkCiAgICAgIGJlIGV4dHJhY3RlZC4KICAgICAgIEBtZXRob2QgZXh0cmFjdFBvbHltb3JwaGljUmVsYXRpb25zaGlwCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZWxhdGlvbnNoaXBUeXBlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZWxhdGlvbnNoaXBIYXNoCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZWxhdGlvbnNoaXBPcHRpb25zCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICAqLwogICAgZXh0cmFjdFBvbHltb3JwaGljUmVsYXRpb25zaGlwOiBmdW5jdGlvbiBleHRyYWN0UG9seW1vcnBoaWNSZWxhdGlvbnNoaXAocmVsYXRpb25zaGlwVHlwZSwgcmVsYXRpb25zaGlwSGFzaCwgcmVsYXRpb25zaGlwT3B0aW9ucykgewogICAgICB2YXIga2V5ID0gcmVsYXRpb25zaGlwT3B0aW9ucy5rZXksCiAgICAgICAgICByZXNvdXJjZUhhc2ggPSByZWxhdGlvbnNoaXBPcHRpb25zLnJlc291cmNlSGFzaCwKICAgICAgICAgIHJlbGF0aW9uc2hpcE1ldGEgPSByZWxhdGlvbnNoaXBPcHRpb25zLnJlbGF0aW9uc2hpcE1ldGE7IC8vIEEgcG9seW1vcnBoaWMgYmVsb25nc1RvIHJlbGF0aW9uc2hpcCBjYW4gYmUgcHJlc2VudCBpbiB0aGUgcGF5bG9hZAogICAgICAvLyBlaXRoZXIgaW4gdGhlIGZvcm0gd2hlcmUgdGhlIGBpZGAgYW5kIHRoZSBgdHlwZWAgYXJlIGdpdmVuOgogICAgICAvLwogICAgICAvLyAgIHsKICAgICAgLy8gICAgIG1lc3NhZ2U6IHsgaWQ6IDEsIHR5cGU6ICdwb3N0JyB9CiAgICAgIC8vICAgfQogICAgICAvLwogICAgICAvLyBvciBieSB0aGUgYGlkYCBhbmQgYSBgPHJlbGF0aW9uc2hpcD5UeXBlYCBhdHRyaWJ1dGU6CiAgICAgIC8vCiAgICAgIC8vICAgewogICAgICAvLyAgICAgbWVzc2FnZTogMSwKICAgICAgLy8gICAgIG1lc3NhZ2VUeXBlOiAncG9zdCcKICAgICAgLy8gICB9CiAgICAgIC8vCiAgICAgIC8vIFRoZSBuZXh0IGNvZGUgY2hlY2tzIGlmIHRoZSBsYXR0ZXIgY2FzZSBpcyBwcmVzZW50IGFuZCByZXR1cm5zIHRoZQogICAgICAvLyBjb3JyZXNwb25kaW5nIEpTT04tQVBJIHJlcHJlc2VudGF0aW9uLiBUaGUgZm9ybWVyIGNhc2UgaXMgaGFuZGxlZCB3aXRoaW4KICAgICAgLy8gdGhlIGJhc2UgY2xhc3MgSlNPTlNlcmlhbGl6ZXIuCgogICAgICB2YXIgaXNQb2x5bW9ycGhpYyA9IHJlbGF0aW9uc2hpcE1ldGEub3B0aW9ucy5wb2x5bW9ycGhpYzsKICAgICAgdmFyIHR5cGVQcm9wZXJ0eSA9IHRoaXMua2V5Rm9yUG9seW1vcnBoaWNUeXBlKGtleSwgcmVsYXRpb25zaGlwVHlwZSwgJ2Rlc2VyaWFsaXplJyk7CgogICAgICBpZiAoaXNQb2x5bW9ycGhpYyAmJiByZXNvdXJjZUhhc2hbdHlwZVByb3BlcnR5XSAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiByZWxhdGlvbnNoaXBIYXNoICE9PSAnb2JqZWN0JykgewogICAgICAgIHZhciB0eXBlID0gdGhpcy5tb2RlbE5hbWVGcm9tUGF5bG9hZEtleShyZXNvdXJjZUhhc2hbdHlwZVByb3BlcnR5XSk7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGlkOiByZWxhdGlvbnNoaXBIYXNoLAogICAgICAgICAgdHlwZTogdHlwZQogICAgICAgIH07CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfQogIH0pOwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgUkVTVFNlcmlhbGl6ZXIucmVvcGVuKHsKICAgICAgd2Fybk1lc3NhZ2VOb01vZGVsRm9yS2V5OiBmdW5jdGlvbiB3YXJuTWVzc2FnZU5vTW9kZWxGb3JLZXkocHJvcCwgdHlwZUtleSkgewogICAgICAgIHJldHVybiAnRW5jb3VudGVyZWQgIicgKyBwcm9wICsgJyIgaW4gcGF5bG9hZCwgYnV0IG5vIG1vZGVsIHdhcyBmb3VuZCBmb3IgbW9kZWwgbmFtZSAiJyArIHR5cGVLZXkgKyAnIiAocmVzb2x2ZWQgbW9kZWwgbmFtZSB1c2luZyAnICsgdGhpcy5jb25zdHJ1Y3Rvci50b1N0cmluZygpICsgJy5tb2RlbE5hbWVGcm9tUGF5bG9hZEtleSgiJyArIHByb3AgKyAnIikpJzsKICAgICAgfQogICAgfSk7CiAgfQoKICB2YXIgX2RlZmF1bHQgPSBSRVNUU2VyaWFsaXplcjsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwo7ZGVmaW5lKCJAZW1iZXItZGF0YS9zZXJpYWxpemVyL3RyYW5zZm9ybSIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9zZXJpYWxpemVyLy1wcml2YXRlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3ByaXZhdGUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zZXJpYWxpemVyCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfcHJpdmF0ZS5UcmFuc2Zvcm07CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKO2RlZmluZSgnQGVtYmVyLWRhdGEvc3RvcmUvLXByaXZhdGUnLCBbJ2V4cG9ydHMnLCAncmVxdWlyZScsICdAZW1iZXItZGF0YS9jYW5hcnktZmVhdHVyZXMnLCAnZW1iZXItaW5mbGVjdG9yJ10sIGZ1bmN0aW9uIChleHBvcnRzLCByZXF1aXJlLCBjYW5hcnlGZWF0dXJlcywgZW1iZXJJbmZsZWN0b3IpIHsgJ3VzZSBzdHJpY3QnOwoKICB2YXIgcmVxdWlyZV9fZGVmYXVsdCA9ICdkZWZhdWx0JyBpbiByZXF1aXJlID8gcmVxdWlyZVsnZGVmYXVsdCddIDogcmVxdWlyZTsKCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KCiAgdmFyIERlcHJlY2F0ZWRFdmVudGVkID0gIEVtYmVyLkV2ZW50ZWQ7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICAgSG9sZHMgdmFsaWRhdGlvbiBlcnJvcnMgZm9yIGEgZ2l2ZW4gcmVjb3JkLCBvcmdhbml6ZWQgYnkgYXR0cmlidXRlIG5hbWVzLgoKICAgIEV2ZXJ5IGBNb2RlbGAgaGFzIGFuIGBlcnJvcnNgIHByb3BlcnR5IHRoYXQgaXMgYW4gaW5zdGFuY2Ugb2YKICAgIGBFcnJvcnNgLiBUaGlzIGNhbiBiZSB1c2VkIHRvIGRpc3BsYXkgdmFsaWRhdGlvbiBlcnJvcgogICAgbWVzc2FnZXMgcmV0dXJuZWQgZnJvbSB0aGUgc2VydmVyIHdoZW4gYSBgcmVjb3JkLnNhdmUoKWAgcmVqZWN0cy4KCiAgICBGb3IgRXhhbXBsZSwgaWYgeW91IGhhZCBhIGBVc2VyYCBtb2RlbCB0aGF0IGxvb2tlZCBsaWtlIHRoaXM6CgogICAgYGBgYXBwL21vZGVscy91c2VyLmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICB1c2VybmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgIGVtYWlsOiBhdHRyKCdzdHJpbmcnKQogICAgfSk7CiAgICBgYGAKICAgIEFuZCB5b3UgYXR0ZW1wdGVkIHRvIHNhdmUgYSByZWNvcmQgdGhhdCBkaWQgbm90IHZhbGlkYXRlIG9uIHRoZSBiYWNrZW5kOgoKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCB1c2VyID0gc3RvcmUuY3JlYXRlUmVjb3JkKCd1c2VyJywgewogICAgICB1c2VybmFtZTogJ3RvbXN0ZXInLAogICAgICBlbWFpbDogJ2ludmFsaWRFbWFpbCcKICAgIH0pOwogICAgdXNlci5zYXZlKCk7CiAgICBgYGAKCiAgICBZb3VyIGJhY2tlbmQgd291bGQgYmUgZXhwZWN0ZWQgdG8gcmV0dXJuIGFuIGVycm9yIHJlc3BvbnNlIHRoYXQgZGVzY3JpYmVkCiAgICB0aGUgcHJvYmxlbSwgc28gdGhhdCBlcnJvciBtZXNzYWdlcyBjYW4gYmUgZ2VuZXJhdGVkIG9uIHRoZSBhcHAuCgogICAgQVBJIHJlc3BvbnNlcyB3aWxsIGJlIHRyYW5zbGF0ZWQgaW50byBpbnN0YW5jZXMgb2YgYEVycm9yc2AgZGlmZmVyZW50bHksCiAgICBkZXBlbmRpbmcgb24gdGhlIHNwZWNpZmljIGNvbWJpbmF0aW9uIG9mIGFkYXB0ZXIgYW5kIHNlcmlhbGl6ZXIgdXNlZC4gWW91CiAgICBtYXkgd2FudCB0byBjaGVjayB0aGUgZG9jdW1lbnRhdGlvbiBvciB0aGUgc291cmNlIGNvZGUgb2YgdGhlIGxpYnJhcmllcwogICAgdGhhdCB5b3UgYXJlIHVzaW5nLCB0byBrbm93IGhvdyB0aGV5IGV4cGVjdCBlcnJvcnMgdG8gYmUgY29tbXVuaWNhdGVkLgoKICAgIEVycm9ycyBjYW4gYmUgZGlzcGxheWVkIHRvIHRoZSB1c2VyIGJ5IGFjY2Vzc2luZyB0aGVpciBwcm9wZXJ0eSBuYW1lCiAgICB0byBnZXQgYW4gYXJyYXkgb2YgYWxsIHRoZSBlcnJvciBvYmplY3RzIGZvciB0aGF0IHByb3BlcnR5LiBFYWNoCiAgICBlcnJvciBvYmplY3QgaXMgYSBKYXZhU2NyaXB0IG9iamVjdCB3aXRoIHR3byBrZXlzOgoKICAgIC0gYG1lc3NhZ2VgIEEgc3RyaW5nIGNvbnRhaW5pbmcgdGhlIGVycm9yIG1lc3NhZ2UgZnJvbSB0aGUgYmFja2VuZAogICAgLSBgYXR0cmlidXRlYCBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgYXNzb2NpYXRlZCB3aXRoIHRoaXMgZXJyb3IgbWVzc2FnZQoKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxsYWJlbD5Vc2VybmFtZToge3tpbnB1dCB2YWx1ZT11c2VybmFtZX19IDwvbGFiZWw+CiAgICB7eyNlYWNoIG1vZGVsLmVycm9ycy51c2VybmFtZSBhcyB8ZXJyb3J8fX0KICAgICAgPGRpdiBjbGFzcz0iZXJyb3IiPgogICAgICAgIHt7ZXJyb3IubWVzc2FnZX19CiAgICAgIDwvZGl2PgogICAge3svZWFjaH19CgogICAgPGxhYmVsPkVtYWlsOiB7e2lucHV0IHZhbHVlPWVtYWlsfX0gPC9sYWJlbD4KICAgIHt7I2VhY2ggbW9kZWwuZXJyb3JzLmVtYWlsIGFzIHxlcnJvcnx9fQogICAgICA8ZGl2IGNsYXNzPSJlcnJvciI+CiAgICAgICAge3tlcnJvci5tZXNzYWdlfX0KICAgICAgPC9kaXY+CiAgICB7ey9lYWNofX0KICAgIGBgYAoKICAgIFlvdSBjYW4gYWxzbyBhY2Nlc3MgdGhlIHNwZWNpYWwgYG1lc3NhZ2VzYCBwcm9wZXJ0eSBvbiB0aGUgZXJyb3IKICAgIG9iamVjdCB0byBnZXQgYW4gYXJyYXkgb2YgYWxsIHRoZSBlcnJvciBzdHJpbmdzLgoKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7I2VhY2ggbW9kZWwuZXJyb3JzLm1lc3NhZ2VzIGFzIHxtZXNzYWdlfH19CiAgICAgIDxkaXYgY2xhc3M9ImVycm9yIj4KICAgICAgICB7e21lc3NhZ2V9fQogICAgICA8L2Rpdj4KICAgIHt7L2VhY2h9fQogICAgYGBgCgogICAgQGNsYXNzIEVycm9ycwogICAgQGV4dGVuZHMgRW1iZXIuQXJyYXlQcm94eQogICAgQHVzZXMgRW1iZXIuRXZlbnRlZAogICAqLwogIHZhciBlcnJvcnMgPSBFbWJlci5BcnJheVByb3h5LmV4dGVuZChEZXByZWNhdGVkRXZlbnRlZCwgewogICAgLyoqCiAgICAgIFJlZ2lzdGVyIHdpdGggdGFyZ2V0IGhhbmRsZXIKICAgICAgIEBtZXRob2QgX3JlZ2lzdGVySGFuZGxlcnMKICAgICAgQHByaXZhdGUKICAgICovCiAgICBfcmVnaXN0ZXJIYW5kbGVyczogZnVuY3Rpb24gX3JlZ2lzdGVySGFuZGxlcnMoYmVjYW1lSW52YWxpZCwgYmVjYW1lVmFsaWQpIHsKICAgICAgdGhpcy5fcmVnaXN0ZXJlZEhhbmRsZXJzID0gewogICAgICAgIGJlY2FtZUludmFsaWQ6IGJlY2FtZUludmFsaWQsCiAgICAgICAgYmVjYW1lVmFsaWQ6IGJlY2FtZVZhbGlkCiAgICAgIH07CiAgICB9LAoKICAgIC8qKgogICAgICBAcHJvcGVydHkgZXJyb3JzQnlBdHRyaWJ1dGVOYW1lCiAgICAgIEB0eXBlIHtNYXBXaXRoRGVmYXVsdH0KICAgICAgQHByaXZhdGUKICAgICovCiAgICBlcnJvcnNCeUF0dHJpYnV0ZU5hbWU6IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIG5ldyBNYXAoKTsKICAgIH0pLAoKICAgIC8qKgogICAgICBSZXR1cm5zIGVycm9ycyBmb3IgYSBnaXZlbiBhdHRyaWJ1dGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IHVzZXIgPSBzdG9yZS5jcmVhdGVSZWNvcmQoJ3VzZXInLCB7CiAgICAgICAgdXNlcm5hbWU6ICd0b21zdGVyJywKICAgICAgICBlbWFpbDogJ2ludmFsaWRFbWFpbCcKICAgICAgfSk7CiAgICAgIHVzZXIuc2F2ZSgpLmNhdGNoKGZ1bmN0aW9uKCl7CiAgICAgICAgdXNlci5nZXQoJ2Vycm9ycycpLmVycm9yc0ZvcignZW1haWwnKTsgLy8gcmV0dXJuczoKICAgICAgICAvLyBbe2F0dHJpYnV0ZTogImVtYWlsIiwgbWVzc2FnZTogIkRvZXNuJ3QgbG9vayBsaWtlIGEgdmFsaWQgZW1haWwuIn1dCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZXJyb3JzRm9yCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBhdHRyaWJ1dGUKICAgICAgQHJldHVybiB7QXJyYXl9CiAgICAqLwogICAgZXJyb3JzRm9yOiBmdW5jdGlvbiBlcnJvcnNGb3IoYXR0cmlidXRlKSB7CiAgICAgIHZhciBtYXAgPSBFbWJlci5nZXQodGhpcywgJ2Vycm9yc0J5QXR0cmlidXRlTmFtZScpOwoKICAgICAgaWYgKCFtYXAuaGFzKGF0dHJpYnV0ZSkpIHsKICAgICAgICBtYXAuc2V0KGF0dHJpYnV0ZSwgRW1iZXIuQSgpKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG1hcC5nZXQoYXR0cmlidXRlKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIG9mIHRoZSBlcnJvciBtZXNzYWdlcyBmb3IgdGhpcwogICAgICByZWNvcmQuIFRoaXMgaXMgdXNlZnVsIGZvciBkaXNwbGF5aW5nIGFsbCBlcnJvcnMgdG8gdGhlIHVzZXIuCiAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIHt7I2VhY2ggbW9kZWwuZXJyb3JzLm1lc3NhZ2VzIGFzIHxtZXNzYWdlfH19CiAgICAgICAgPGRpdiBjbGFzcz0iZXJyb3IiPgogICAgICAgICAge3ttZXNzYWdlfX0KICAgICAgICA8L2Rpdj4KICAgICAge3svZWFjaH19CiAgICAgIGBgYAogICAgICAgQHByb3BlcnR5IG1lc3NhZ2VzCiAgICAgIEB0eXBlIHtBcnJheX0KICAgICovCiAgICBtZXNzYWdlczogRW1iZXIuY29tcHV0ZWQubWFwQnkoJ2NvbnRlbnQnLCAnbWVzc2FnZScpLAoKICAgIC8qKgogICAgICBAcHJvcGVydHkgY29udGVudAogICAgICBAdHlwZSB7QXJyYXl9CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgY29udGVudDogRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gRW1iZXIuQSgpOwogICAgfSksCgogICAgLyoqCiAgICAgIEBtZXRob2QgdW5rbm93blByb3BlcnR5CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgdW5rbm93blByb3BlcnR5OiBmdW5jdGlvbiB1bmtub3duUHJvcGVydHkoYXR0cmlidXRlKSB7CiAgICAgIHZhciBlcnJvcnMgPSB0aGlzLmVycm9yc0ZvcihhdHRyaWJ1dGUpOwoKICAgICAgaWYgKGVycm9ycy5sZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgICB9CgogICAgICByZXR1cm4gZXJyb3JzOwogICAgfSwKCiAgICAvKioKICAgICAgVG90YWwgbnVtYmVyIG9mIGVycm9ycy4KICAgICAgIEBwcm9wZXJ0eSBsZW5ndGgKICAgICAgQHR5cGUge051bWJlcn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwoKICAgIC8qKgogICAgICBAcHJvcGVydHkgaXNFbXB0eQogICAgICBAdHlwZSB7Qm9vbGVhbn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgaXNFbXB0eTogRW1iZXIuY29tcHV0ZWQubm90KCdsZW5ndGgnKS5yZWFkT25seSgpLAoKICAgIC8qKgogICAgIE1hbnVhbGx5IGFkZHMgZXJyb3JzIHRvIHRoZSByZWNvcmQuIFRoaXMgd2lsbCB0cmlnZXIgdGhlIGBiZWNhbWVJbnZhbGlkYCBldmVudC8gbGlmZWN5Y2xlIG1ldGhvZCBvbgogICAgICB0aGUgcmVjb3JkIGFuZCB0cmFuc2l0aW9uIHRoZSByZWNvcmQgaW50byBhbiBgaW52YWxpZGAgc3RhdGUuCiAgICAgIEV4YW1wbGUKICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBlcnJvcnMgPSBnZXQodXNlciwgJ2Vycm9ycycpOwogICAgICAgLy8gYWRkIG11bHRpcGxlIGVycm9ycwogICAgICBlcnJvcnMuYWRkKCdwYXNzd29yZCcsIFsKICAgICAgICAnTXVzdCBiZSBhdCBsZWFzdCAxMiBjaGFyYWN0ZXJzJywKICAgICAgICAnTXVzdCBjb250YWluIGF0IGxlYXN0IG9uZSBzeW1ib2wnLAogICAgICAgICdDYW5ub3QgY29udGFpbiB5b3VyIG5hbWUnCiAgICAgIF0pOwogICAgICAgZXJyb3JzLmVycm9yc0ZvcigncGFzc3dvcmQnKTsKICAgICAgLy8gPT4KICAgICAgLy8gWwogICAgICAvLyAgIHsgYXR0cmlidXRlOiAncGFzc3dvcmQnLCBtZXNzYWdlOiAnTXVzdCBiZSBhdCBsZWFzdCAxMiBjaGFyYWN0ZXJzJyB9LAogICAgICAvLyAgIHsgYXR0cmlidXRlOiAncGFzc3dvcmQnLCBtZXNzYWdlOiAnTXVzdCBjb250YWluIGF0IGxlYXN0IG9uZSBzeW1ib2wnIH0sCiAgICAgIC8vICAgeyBhdHRyaWJ1dGU6ICdwYXNzd29yZCcsIG1lc3NhZ2U6ICdDYW5ub3QgY29udGFpbiB5b3VyIG5hbWUnIH0sCiAgICAgIC8vIF0KICAgICAgIC8vIGFkZCBhIHNpbmdsZSBlcnJvcgogICAgICBlcnJvcnMuYWRkKCd1c2VybmFtZScsICdUaGlzIGZpZWxkIGlzIHJlcXVpcmVkJyk7CiAgICAgICBlcnJvcnMuZXJyb3JzRm9yKCdwYXNzd29yZCcpOwogICAgICAvLyA9PgogICAgICAvLyBbCiAgICAgIC8vICAgeyBhdHRyaWJ1dGU6ICd1c2VybmFtZScsIG1lc3NhZ2U6ICdUaGlzIGZpZWxkIGlzIHJlcXVpcmVkJyB9LAogICAgICAvLyBdCiAgICAgYGBgCiAgICBAbWV0aG9kIGFkZAogICAgQHBhcmFtIHtzdHJpbmd9IGF0dHJpYnV0ZSAtIHRoZSBwcm9wZXJ0eSBuYW1lIG9mIGFuIGF0dHJpYnV0ZSBvciByZWxhdGlvbnNoaXAKICAgIEBwYXJhbSB7c3RyaW5nW118c3RyaW5nfSBtZXNzYWdlcyAtIGFuIGVycm9yIG1lc3NhZ2Ugb3IgYXJyYXkgb2YgZXJyb3IgbWVzc2FnZXMgZm9yIHRoZSBhdHRyaWJ1dGUKICAgICAqLwogICAgYWRkOiBmdW5jdGlvbiBhZGQoYXR0cmlidXRlLCBtZXNzYWdlcykgewogICAgICB2YXIgd2FzRW1wdHkgPSBFbWJlci5nZXQodGhpcywgJ2lzRW1wdHknKTsKCiAgICAgIHRoaXMuX2FkZChhdHRyaWJ1dGUsIG1lc3NhZ2VzKTsKCiAgICAgIGlmICh3YXNFbXB0eSAmJiAhRW1iZXIuZ2V0KHRoaXMsICdpc0VtcHR5JykpIHsKICAgICAgICB0aGlzLl9yZWdpc3RlcmVkSGFuZGxlcnMgJiYgdGhpcy5fcmVnaXN0ZXJlZEhhbmRsZXJzLmJlY2FtZUludmFsaWQoKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgQWRkcyBlcnJvciBtZXNzYWdlcyB0byBhIGdpdmVuIGF0dHJpYnV0ZSB3aXRob3V0IHNlbmRpbmcgZXZlbnQuCiAgICAgICBAbWV0aG9kIF9hZGQKICAgICAgQHByaXZhdGUKICAgICovCiAgICBfYWRkOiBmdW5jdGlvbiBfYWRkKGF0dHJpYnV0ZSwgbWVzc2FnZXMpIHsKICAgICAgbWVzc2FnZXMgPSB0aGlzLl9maW5kT3JDcmVhdGVNZXNzYWdlcyhhdHRyaWJ1dGUsIG1lc3NhZ2VzKTsKICAgICAgdGhpcy5hZGRPYmplY3RzKG1lc3NhZ2VzKTsKICAgICAgdGhpcy5lcnJvcnNGb3IoYXR0cmlidXRlKS5hZGRPYmplY3RzKG1lc3NhZ2VzKTsKICAgICAgdGhpcy5ub3RpZnlQcm9wZXJ0eUNoYW5nZShhdHRyaWJ1dGUpOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBfZmluZE9yQ3JlYXRlTWVzc2FnZXMKICAgICAgQHByaXZhdGUKICAgICovCiAgICBfZmluZE9yQ3JlYXRlTWVzc2FnZXM6IGZ1bmN0aW9uIF9maW5kT3JDcmVhdGVNZXNzYWdlcyhhdHRyaWJ1dGUsIG1lc3NhZ2VzKSB7CiAgICAgIHZhciBlcnJvcnMgPSB0aGlzLmVycm9yc0ZvcihhdHRyaWJ1dGUpOwogICAgICB2YXIgbWVzc2FnZXNBcnJheSA9IEVtYmVyLm1ha2VBcnJheShtZXNzYWdlcyk7CgogICAgICB2YXIgX21lc3NhZ2VzID0gbmV3IEFycmF5KG1lc3NhZ2VzQXJyYXkubGVuZ3RoKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZXNBcnJheS5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBtZXNzYWdlID0gbWVzc2FnZXNBcnJheVtpXTsKICAgICAgICB2YXIgZXJyID0gZXJyb3JzLmZpbmRCeSgnbWVzc2FnZScsIG1lc3NhZ2UpOwoKICAgICAgICBpZiAoZXJyKSB7CiAgICAgICAgICBfbWVzc2FnZXNbaV0gPSBlcnI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIF9tZXNzYWdlc1tpXSA9IHsKICAgICAgICAgICAgYXR0cmlidXRlOiBhdHRyaWJ1dGUsCiAgICAgICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UKICAgICAgICAgIH07CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gX21lc3NhZ2VzOwogICAgfSwKCiAgICAvKioKICAgICBNYW51YWxseSByZW1vdmVzIGFsbCBlcnJvcnMgZm9yIGEgZ2l2ZW4gbWVtYmVyIGZyb20gdGhlIHJlY29yZC4KICAgICAgIFRoaXMgd2lsbCB0cmFuc2l0aW9uIHRoZSByZWNvcmQgaW50byBhIGB2YWxpZGAgc3RhdGUsIGFuZAogICAgICB0cmlnZ2VycyB0aGUgYGJlY2FtZVZhbGlkYCBldmVudCBhbmQgbGlmZWN5Y2xlIG1ldGhvZC4KICAgICAgRXhhbXBsZToKICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgZXJyb3JzID0gZ2V0KCd1c2VyJywgZXJyb3JzKTsKICAgICAgZXJyb3JzLmFkZCgncGhvbmUnLCBbJ2Vycm9yLTEnLCAnZXJyb3ItMiddKTsKICAgICAgIGVycm9ycy5lcnJvcnNGb3IoJ3Bob25lJyk7CiAgICAgIC8vID0+CiAgICAgIC8vIFsKICAgICAgLy8gICB7IGF0dHJpYnV0ZTogJ3Bob25lJywgbWVzc2FnZTogJ2Vycm9yLTEnIH0sCiAgICAgIC8vICAgeyBhdHRyaWJ1dGU6ICdwaG9uZScsIG1lc3NhZ2U6ICdlcnJvci0yJyB9LAogICAgICAvLyBdCiAgICAgICBlcnJvcnMucmVtb3ZlKCdwaG9uZScpOwogICAgICAgZXJyb3JzLmVycm9yc0ZvcigncGhvbmUnKTsKICAgICAgLy8gPT4gdW5kZWZpbmVkCiAgICAgYGBgCiAgICAgQG1ldGhvZCByZW1vdmUKICAgICBAcGFyYW0ge3N0cmluZ30gbWVtYmVyIC0gdGhlIHByb3BlcnR5IG5hbWUgb2YgYW4gYXR0cmlidXRlIG9yIHJlbGF0aW9uc2hpcAogICAgICovCiAgICByZW1vdmU6IGZ1bmN0aW9uIHJlbW92ZShhdHRyaWJ1dGUpIHsKICAgICAgaWYgKEVtYmVyLmdldCh0aGlzLCAnaXNFbXB0eScpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9yZW1vdmUoYXR0cmlidXRlKTsKCiAgICAgIGlmIChFbWJlci5nZXQodGhpcywgJ2lzRW1wdHknKSkgewogICAgICAgIHRoaXMuX3JlZ2lzdGVyZWRIYW5kbGVycyAmJiB0aGlzLl9yZWdpc3RlcmVkSGFuZGxlcnMuYmVjYW1lVmFsaWQoKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgUmVtb3ZlcyBhbGwgZXJyb3IgbWVzc2FnZXMgZnJvbSB0aGUgZ2l2ZW4gYXR0cmlidXRlIHdpdGhvdXQgc2VuZGluZyBldmVudC4KICAgICAgIEBtZXRob2QgX3JlbW92ZQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9yZW1vdmU6IGZ1bmN0aW9uIF9yZW1vdmUoYXR0cmlidXRlKSB7CiAgICAgIGlmIChFbWJlci5nZXQodGhpcywgJ2lzRW1wdHknKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIGNvbnRlbnQgPSB0aGlzLnJlamVjdEJ5KCdhdHRyaWJ1dGUnLCBhdHRyaWJ1dGUpOwogICAgICBFbWJlci5nZXQodGhpcywgJ2NvbnRlbnQnKS5zZXRPYmplY3RzKGNvbnRlbnQpOwogICAgICBFbWJlci5nZXQodGhpcywgJ2Vycm9yc0J5QXR0cmlidXRlTmFtZScpLmRlbGV0ZShhdHRyaWJ1dGUpOwogICAgICB0aGlzLm5vdGlmeVByb3BlcnR5Q2hhbmdlKGF0dHJpYnV0ZSk7CiAgICAgIHRoaXMubm90aWZ5UHJvcGVydHlDaGFuZ2UoJ2xlbmd0aCcpOwogICAgfSwKCiAgICAvKioKICAgICBNYW51YWxseSBjbGVhcnMgYWxsIGVycm9ycyBmb3IgdGhlIHJlY29yZC4KICAgICAgIFRoaXMgd2lsbCB0cmFuc2l0aW9uIHRoZSByZWNvcmQgaW50byBhIGB2YWxpZGAgc3RhdGUsIGFuZAogICAgICAgd2lsbCB0cmlnZ2VyIHRoZSBgYmVjYW1lVmFsaWRgIGV2ZW50IGFuZCBsaWZlY3ljbGUgbWV0aG9kLgogICAgIEV4YW1wbGU6CiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgZXJyb3JzID0gZ2V0KCd1c2VyJywgZXJyb3JzKTsKICAgICBlcnJvcnMuYWRkKCd1c2VybmFtZScsIFsnZXJyb3ItYSddKTsKICAgICBlcnJvcnMuYWRkKCdwaG9uZScsIFsnZXJyb3ItMScsICdlcnJvci0yJ10pOwogICAgICBlcnJvcnMuZXJyb3JzRm9yKCd1c2VybmFtZScpOwogICAgIC8vID0+CiAgICAgLy8gWwogICAgIC8vICAgeyBhdHRyaWJ1dGU6ICd1c2VybmFtZScsIG1lc3NhZ2U6ICdlcnJvci1hJyB9LAogICAgIC8vIF0KICAgICAgZXJyb3JzLmVycm9yc0ZvcigncGhvbmUnKTsKICAgICAvLyA9PgogICAgIC8vIFsKICAgICAvLyAgIHsgYXR0cmlidXRlOiAncGhvbmUnLCBtZXNzYWdlOiAnZXJyb3ItMScgfSwKICAgICAvLyAgIHsgYXR0cmlidXRlOiAncGhvbmUnLCBtZXNzYWdlOiAnZXJyb3ItMicgfSwKICAgICAvLyBdCiAgICAgIGVycm9ycy5jbGVhcigpOwogICAgICBlcnJvcnMuZXJyb3JzRm9yKCd1c2VybmFtZScpOwogICAgIC8vID0+IHVuZGVmaW5lZAogICAgICBlcnJvcnMuZXJyb3JzRm9yKCdwaG9uZScpOwogICAgIC8vID0+IHVuZGVmaW5lZAogICAgICBlcnJvcnMuZ2V0KCdtZXNzYWdlcycpCiAgICAgLy8gPT4gW10KICAgICBgYGAKICAgICBAbWV0aG9kIHJlbW92ZQogICAgICovCiAgICBjbGVhcjogZnVuY3Rpb24gY2xlYXIoKSB7CiAgICAgIGlmIChFbWJlci5nZXQodGhpcywgJ2lzRW1wdHknKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5fY2xlYXIoKTsKCiAgICAgIHRoaXMuX3JlZ2lzdGVyZWRIYW5kbGVycyAmJiB0aGlzLl9yZWdpc3RlcmVkSGFuZGxlcnMuYmVjYW1lVmFsaWQoKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFJlbW92ZXMgYWxsIGVycm9yIG1lc3NhZ2VzLgogICAgICB0byB0aGUgcmVjb3JkLgogICAgICAgQG1ldGhvZCBfY2xlYXIKICAgICAgQHByaXZhdGUKICAgICovCiAgICBfY2xlYXI6IGZ1bmN0aW9uIF9jbGVhcigpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIGlmIChFbWJlci5nZXQodGhpcywgJ2lzRW1wdHknKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIGVycm9yc0J5QXR0cmlidXRlTmFtZSA9IEVtYmVyLmdldCh0aGlzLCAnZXJyb3JzQnlBdHRyaWJ1dGVOYW1lJyk7CiAgICAgIHZhciBhdHRyaWJ1dGVzID0gW107CiAgICAgIGVycm9yc0J5QXR0cmlidXRlTmFtZS5mb3JFYWNoKGZ1bmN0aW9uIChfLCBhdHRyaWJ1dGUpIHsKICAgICAgICBhdHRyaWJ1dGVzLnB1c2goYXR0cmlidXRlKTsKICAgICAgfSk7CiAgICAgIGVycm9yc0J5QXR0cmlidXRlTmFtZS5jbGVhcigpOwogICAgICBhdHRyaWJ1dGVzLmZvckVhY2goZnVuY3Rpb24gKGF0dHJpYnV0ZSkgewogICAgICAgIF90aGlzLm5vdGlmeVByb3BlcnR5Q2hhbmdlKGF0dHJpYnV0ZSk7CiAgICAgIH0pOwogICAgICBFbWJlci5BcnJheVByb3h5LnByb3RvdHlwZS5jbGVhci5jYWxsKHRoaXMpOwogICAgfSwKCiAgICAvKioKICAgICAgQ2hlY2tzIGlmIHRoZXJlIGFyZSBlcnJvciBtZXNzYWdlcyBmb3IgdGhlIGdpdmVuIGF0dHJpYnV0ZS4KICAgICAgIGBgYGFwcC9yb3V0ZXMvdXNlci9lZGl0LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHNhdmU6IGZ1bmN0aW9uKHVzZXIpIHsKICAgICAgICAgICAgaWYgKHVzZXIuZ2V0KCdlcnJvcnMnKS5oYXMoJ2VtYWlsJykpIHsKICAgICAgICAgICAgICByZXR1cm4gYWxlcnQoJ1BsZWFzZSB1cGRhdGUgeW91ciBlbWFpbCBiZWZvcmUgYXR0ZW1wdGluZyB0byBzYXZlLicpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHVzZXIuc2F2ZSgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBoYXMKICAgICAgQHBhcmFtIHtTdHJpbmd9IGF0dHJpYnV0ZQogICAgICBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHRoZXJlIHNvbWUgZXJyb3JzIG9uIGdpdmVuIGF0dHJpYnV0ZQogICAgKi8KICAgIGhhczogZnVuY3Rpb24gaGFzKGF0dHJpYnV0ZSkgewogICAgICByZXR1cm4gdGhpcy5lcnJvcnNGb3IoYXR0cmlidXRlKS5sZW5ndGggPiAwOwogICAgfQogIH0pOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwogIC8vIEFsbCBtb2RlbE5hbWVzIGFyZSBkYXNoZXJpemVkIGludGVybmFsbHkuIENoYW5naW5nIHRoaXMgZnVuY3Rpb24gbWF5CiAgLy8gcmVxdWlyZSBjaGFuZ2VzIHRvIG90aGVyIG5vcm1hbGl6YXRpb24gaG9va3MgKHN1Y2ggYXMgdHlwZUZvclJvb3QpLgoKICAvKioKICAgVGhpcyBtZXRob2Qgbm9ybWFsaXplcyBhIG1vZGVsTmFtZSBpbnRvIHRoZSBmb3JtYXQgRW1iZXIgRGF0YSB1c2VzCiAgIGludGVybmFsbHkuCgogICAgQG1ldGhvZCBub3JtYWxpemVNb2RlbE5hbWUKICAgIEBwdWJsaWMKICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgIEByZXR1cm4ge1N0cmluZ30gbm9ybWFsaXplZE1vZGVsTmFtZQogICovCiAgZnVuY3Rpb24gbm9ybWFsaXplTW9kZWxOYW1lKG1vZGVsTmFtZSkgewogICAgcmV0dXJuIEVtYmVyLlN0cmluZy5kYXNoZXJpemUobW9kZWxOYW1lKTsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICAqIFRoaXMgc3ltYm9sIHByb3ZpZGVzIGEgU3ltYm9sIHJlcGxhY2VtZW50IGZvciBicm93c2VycyB0aGF0IGRvIG5vdCBoYXZlIGl0CiAgICogKGVnLiBJRSAxMSkuCiAgICoKICAgKiBUaGUgcmVwbGFjZW1lbnQgaXMgZGlmZmVyZW50IGZyb20gdGhlIG5hdGl2ZSBTeW1ib2wgaW4gc29tZSB3YXlzLiBJdCBpcyBhCiAgICogZnVuY3Rpb24gdGhhdCBwcm9kdWNlcyBhbiBvdXRwdXQ6CiAgICogLSBpdGVyYWJsZTsKICAgKiAtIHRoYXQgaXMgYSBzdHJpbmcsIG5vdCBhIHN5bWJvbC4KICAgKgogICAqIEBpbnRlcm5hbAogICAqLwogIHZhciBzeW1ib2wgPSB0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyA/IFN5bWJvbCA6IGZ1bmN0aW9uIChrZXkpIHsKICAgIHJldHVybiAiX18iICsga2V5ICsgTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogRGF0ZS5ub3coKSkgKyAiX18iOwogIH07CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICAqIFVzZSB0aGlzIGJyYW5kIHRvIGFzc2lnbiBhIHN0cmluZyBrZXkgdG8gYW4gaW50ZXJmYWNlCiAgICogZm9yIG1hcHBpbmcgdGhlIGludGVyZmFjZSB0byBhIHRpZ2h0bHkgY291cGxlZCBpbnRlcm5hbAogICAqIGNsYXNzIGltcGxlbWVudGF0aW9uLgogICAqCiAgICogVGhpcyBhbGxvd3MgdXMgdG8gZXhwb3NlIHRoZSBpbnRlcmZhY2UgcHVibGljbHkgYnV0CiAgICogc2VhbWxlc3NseSB1cGdyYWRlIHRoZXNlIGludGVyZmFjZXMgZm9yIG91ciBvd24gdXNlCiAgICogaW50ZXJuYWxseSB3aGVuIGludGVybmFsIG1ldGhvZHMgYW5kIHByb3BlcnRpZXMgYXJlCiAgICogbmVlZGVkLgogICAqCiAgICogQGludGVybmFsCiAgICovCgogIHZhciBCUkFORF9TWU1CT0wgPSBzeW1ib2woJ0RFQlVHLXRzLWJyYW5kJyk7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICAqIENhc3RzIGEgcHVibGljIGludGVyZmFjZSB0byB0aGUgbWF0Y2hpbmcgaW50ZXJuYWwgY2xhc3MgaW1wbGVtZW50YXRpb24KICAgKgogICAqIEBpbnRlcm5hbAogICAqLwogIGZ1bmN0aW9uIHVwZ3JhZGVGb3JJbnRlcm5hbChleHRlcm5hbCkgewogICAgcmV0dXJuIGV4dGVybmFsOwogIH0KCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KICAvLyBVc2VkIGJ5IHRoZSBzdG9yZSB0byBub3JtYWxpemUgSURzIGVudGVyaW5nIHRoZSBzdG9yZS4gIERlc3BpdGUgdGhlIGZhY3QKICAvLyB0aGF0IGRldmVsb3BlcnMgbWF5IHByb3ZpZGUgSURzIGFzIG51bWJlcnMgKGUuZy4sIGBzdG9yZS5maW5kUmVjb3JkKCdwZXJzb24nLCAxKWApLAogIC8vIGl0IGlzIGltcG9ydGFudCB0aGF0IGludGVybmFsbHkgd2UgdXNlIHN0cmluZ3MsIHNpbmNlIElEcyBtYXkgYmUgc2VyaWFsaXplZAogIC8vIGFuZCBsb3NlIHR5cGUgaW5mb3JtYXRpb24uICBGb3IgZXhhbXBsZSwgRW1iZXIncyByb3V0ZXIgbWF5IHB1dCBhIHJlY29yZCdzCiAgLy8gSUQgaW50byB0aGUgVVJMLCBhbmQgaWYgd2UgbGF0ZXIgdHJ5IHRvIGRlc2VyaWFsaXplIHRoYXQgVVJMIGFuZCBmaW5kIHRoZQogIC8vIGNvcnJlc3BvbmRpbmcgcmVjb3JkLCB3ZSB3aWxsIG5vdCBrbm93IGlmIGl0IGlzIGEgc3RyaW5nIG9yIGEgbnVtYmVyLgogIGZ1bmN0aW9uIGNvZXJjZUlkKGlkKSB7CiAgICBpZiAoaWQgPT09IG51bGwgfHwgaWQgPT09IHVuZGVmaW5lZCB8fCBpZCA9PT0gJycpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CgogICAgaWYgKHR5cGVvZiBpZCA9PT0gJ3N0cmluZycpIHsKICAgICAgcmV0dXJuIGlkOwogICAgfQoKICAgIGlmICh0eXBlb2YgaWQgPT09ICdzeW1ib2wnKSB7CiAgICAgIHJldHVybiBpZC50b1N0cmluZygpOwogICAgfQoKICAgIHJldHVybiAnJyArIGlkOwogIH0KCiAgZnVuY3Rpb24gZW5zdXJlU3RyaW5nSWQoaWQpIHsKICAgIHZhciBub3JtYWxpemVkID0gbnVsbDsKCiAgICBpZiAodHlwZW9mIGlkID09PSAnc3RyaW5nJykgewogICAgICBub3JtYWxpemVkID0gaWQubGVuZ3RoID4gMCA/IGlkIDogbnVsbDsKICAgIH0gZWxzZSBpZiAodHlwZW9mIGlkID09PSAnbnVtYmVyJyAmJiAhaXNOYU4oaWQpKSB7CiAgICAgIG5vcm1hbGl6ZWQgPSAnJyArIGlkOwogICAgfQoKICAgIHJldHVybiBub3JtYWxpemVkOwogIH0KCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KICAvLyBzdXBwb3J0IElFMTEKICB2YXIgQ1JZUFRPID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgd2luZG93Lm1zQ3J5cHRvICYmIHR5cGVvZiB3aW5kb3cubXNDcnlwdG8uZ2V0UmFuZG9tVmFsdWVzID09PSAnZnVuY3Rpb24nID8gd2luZG93Lm1zQ3J5cHRvIDogd2luZG93LmNyeXB0bzsgLy8gd2UgbWlnaHQgYmUgYWJsZSB0byBvcHRpbWl6ZSB0aGlzIGJ5IHJlcXVlc3RpbmcgbW9yZSBieXRlcyB0aGFuIHdlIG5lZWQgYXQgYSB0aW1lCgogIGZ1bmN0aW9uIHJuZygpIHsKICAgIC8vIFdIQVRXRyBjcnlwdG8gUk5HIC0gaHR0cDovL3dpa2kud2hhdHdnLm9yZy93aWtpL0NyeXB0bwogICAgdmFyIHJuZHM4ID0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgcmV0dXJuIENSWVBUTy5nZXRSYW5kb21WYWx1ZXMocm5kczgpOwogIH0KICAvKioKICAgKiBDb252ZXJ0IGFycmF5IG9mIDE2IGJ5dGUgdmFsdWVzIHRvIFVVSUQgc3RyaW5nIGZvcm1hdCBvZiB0aGUgZm9ybToKICAgKiBYWFhYWFhYWC1YWFhYLVhYWFgtWFhYWC1YWFhYWFhYWFhYWFgKICAgKi8KCgogIHZhciBieXRlVG9IZXggPSBbXTsKCiAgZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7ICsraSkgewogICAgYnl0ZVRvSGV4W2ldID0gKGkgKyAweDEwMCkudG9TdHJpbmcoMTYpLnN1YnN0cigxKTsKICB9CgogIGZ1bmN0aW9uIGJ5dGVzVG9VdWlkKGJ1ZikgewogICAgdmFyIGJ0aCA9IGJ5dGVUb0hleDsgLy8gam9pbiB1c2VkIHRvIGZpeCBtZW1vcnkgaXNzdWUgY2F1c2VkIGJ5IGNvbmNhdGVuYXRpb246IGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTMxNzUjYzQKCiAgICByZXR1cm4gW2J0aFtidWZbMF1dLCBidGhbYnVmWzFdXSwgYnRoW2J1ZlsyXV0sIGJ0aFtidWZbM11dLCAnLScsIGJ0aFtidWZbNF1dLCBidGhbYnVmWzVdXSwgJy0nLCBidGhbYnVmWzZdXSwgYnRoW2J1Zls3XV0sICctJywgYnRoW2J1Zls4XV0sIGJ0aFtidWZbOV1dLCAnLScsIGJ0aFtidWZbMTBdXSwgYnRoW2J1ZlsxMV1dLCBidGhbYnVmWzEyXV0sIGJ0aFtidWZbMTNdXSwgYnRoW2J1ZlsxNF1dLCBidGhbYnVmWzE1XV1dLmpvaW4oJycpOwogIH0KCiAgZnVuY3Rpb24gdXVpZHY0KCkgewogICAgdmFyIHJuZHMgPSBybmcoKTsgLy8gUGVyIDQuNCwgc2V0IGJpdHMgZm9yIHZlcnNpb24gYW5kIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYAoKICAgIHJuZHNbNl0gPSBybmRzWzZdICYgMHgwZiB8IDB4NDA7CiAgICBybmRzWzhdID0gcm5kc1s4XSAmIDB4M2YgfCAweDgwOwogICAgcmV0dXJuIGJ5dGVzVG9VdWlkKHJuZHMpOwogIH0KCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KICB2YXIgSURFTlRJRklFUlMgPSBuZXcgV2Vha01hcCgpOwogIGZ1bmN0aW9uIGlzU3RhYmxlSWRlbnRpZmllcihpZGVudGlmaWVyKSB7CiAgICByZXR1cm4gSURFTlRJRklFUlMuaGFzKGlkZW50aWZpZXIpOwogIH0KICBmdW5jdGlvbiBtYXJrU3RhYmxlSWRlbnRpZmllcihpZGVudGlmaWVyKSB7CiAgICBJREVOVElGSUVSUy5zZXQoaWRlbnRpZmllciwgJ2lzLWlkZW50aWZpZXInKTsKICB9CiAgZnVuY3Rpb24gdW5tYXJrU3RhYmxlSWRlbnRpZmllcihpZGVudGlmaWVyKSB7CiAgICBJREVOVElGSUVSUy5kZWxldGUoaWRlbnRpZmllcik7CiAgfQoKICBmdW5jdGlvbiBpc05vbkVtcHR5U3RyaW5nKHN0cikgewogICAgcmV0dXJuIHR5cGVvZiBzdHIgPT09ICdzdHJpbmcnICYmIHN0ci5sZW5ndGggPiAwOwogIH0KCiAgdmFyIGNvbmZpZ3VyZWRGb3JnZXRNZXRob2Q7CiAgdmFyIGNvbmZpZ3VyZWRHZW5lcmF0aW9uTWV0aG9kOwogIHZhciBjb25maWd1cmVkUmVzZXRNZXRob2Q7CiAgdmFyIGNvbmZpZ3VyZWRVcGRhdGVNZXRob2Q7CiAgZnVuY3Rpb24gc2V0SWRlbnRpZmllckdlbmVyYXRpb25NZXRob2QobWV0aG9kKSB7CiAgICBjb25maWd1cmVkR2VuZXJhdGlvbk1ldGhvZCA9IG1ldGhvZDsKICB9CiAgZnVuY3Rpb24gc2V0SWRlbnRpZmllclVwZGF0ZU1ldGhvZChtZXRob2QpIHsKICAgIGNvbmZpZ3VyZWRVcGRhdGVNZXRob2QgPSBtZXRob2Q7CiAgfQogIGZ1bmN0aW9uIHNldElkZW50aWZpZXJGb3JnZXRNZXRob2QobWV0aG9kKSB7CiAgICBjb25maWd1cmVkRm9yZ2V0TWV0aG9kID0gbWV0aG9kOwogIH0KICBmdW5jdGlvbiBzZXRJZGVudGlmaWVyUmVzZXRNZXRob2QobWV0aG9kKSB7CiAgICBjb25maWd1cmVkUmVzZXRNZXRob2QgPSBtZXRob2Q7CiAgfQoKICBmdW5jdGlvbiBkZWZhdWx0R2VuZXJhdGlvbk1ldGhvZChkYXRhLCBidWNrZXQpIHsKICAgIGlmIChpc05vbkVtcHR5U3RyaW5nKGRhdGEubGlkKSkgewogICAgICByZXR1cm4gZGF0YS5saWQ7CiAgICB9CgogICAgdmFyIHR5cGUgPSBkYXRhLnR5cGUsCiAgICAgICAgaWQgPSBkYXRhLmlkOwoKICAgIGlmIChpc05vbkVtcHR5U3RyaW5nKGlkKSkgewogICAgICByZXR1cm4gIkBlbWJlci1kYXRhOmxpZC0iICsgbm9ybWFsaXplTW9kZWxOYW1lKHR5cGUpICsgIi0iICsgaWQ7CiAgICB9CgogICAgcmV0dXJuIHV1aWR2NCgpOwogIH0KCiAgdmFyIElkZW50aWZpZXJDYWNoZXMgPSBuZXcgV2Vha01hcCgpOwogIGZ1bmN0aW9uIGlkZW50aWZpZXJDYWNoZUZvcihzdG9yZSkgewogICAgdmFyIGNhY2hlID0gSWRlbnRpZmllckNhY2hlcy5nZXQoc3RvcmUpOwoKICAgIGlmIChjYWNoZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGNhY2hlID0gbmV3IElkZW50aWZpZXJDYWNoZSgpOwogICAgICBJZGVudGlmaWVyQ2FjaGVzLnNldChzdG9yZSwgY2FjaGUpOwogICAgfQoKICAgIHJldHVybiBjYWNoZTsKICB9CgogIGZ1bmN0aW9uIGRlZmF1bHRFbXB0eUNhbGxiYWNrKCkge30KCiAgdmFyIElkZW50aWZpZXJDYWNoZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIC8vIFR5cGVzY3JpcHQgc3RpbGwgbGVha3MgcHJpdmF0ZSBwcm9wZXJ0aWVzIGluIHRoZSBmaW5hbAogICAgLy8gY29tcGlsZWQgY2xhc3MsIHNvIHdlIG1heSB3YW50IHRvIG1vdmUgdGhlc2UgZnJvbSBfdW5kZXJzY29yZQogICAgLy8gdG8gYSBXZWFrTWFwIHRvIGF2b2lkIGxlYWtpbmcKICAgIC8vIGN1cnJlbnRseSB3ZSBsZWFrIHRoaXMgZm9yIHRlc3QgcHVycG9zZXMKICAgIGZ1bmN0aW9uIElkZW50aWZpZXJDYWNoZSgpIHsKICAgICAgdGhpcy5fY2FjaGUgPSB7CiAgICAgICAgbGlkczogT2JqZWN0LmNyZWF0ZShudWxsKSwKICAgICAgICB0eXBlczogT2JqZWN0LmNyZWF0ZShudWxsKQogICAgICB9OwogICAgICB0aGlzLl9nZW5lcmF0ZSA9IHZvaWQgMDsKICAgICAgdGhpcy5fdXBkYXRlID0gdm9pZCAwOwogICAgICB0aGlzLl9mb3JnZXQgPSB2b2lkIDA7CiAgICAgIHRoaXMuX3Jlc2V0ID0gdm9pZCAwOwogICAgICB0aGlzLl9tZXJnZSA9IHZvaWQgMDsKICAgICAgLy8gd2UgY2FjaGUgdGhlIHVzZXIgY29uZmlndXJlZEdlbmVyYXRpb25NZXRob2QgYXQgaW5pdCBiZWNhdXNlIGl0IG11c3QKICAgICAgLy8gYmUgY29uZmlndXJlZCBwcmlvciBhbmQgaXMgbm90IGFsbG93ZWQgdG8gYmUgY2hhbmdlZAogICAgICB0aGlzLl9nZW5lcmF0ZSA9IGNvbmZpZ3VyZWRHZW5lcmF0aW9uTWV0aG9kIHx8IGRlZmF1bHRHZW5lcmF0aW9uTWV0aG9kOwogICAgICB0aGlzLl91cGRhdGUgPSBjb25maWd1cmVkVXBkYXRlTWV0aG9kIHx8IGRlZmF1bHRFbXB0eUNhbGxiYWNrOwogICAgICB0aGlzLl9mb3JnZXQgPSBjb25maWd1cmVkRm9yZ2V0TWV0aG9kIHx8IGRlZmF1bHRFbXB0eUNhbGxiYWNrOwogICAgICB0aGlzLl9yZXNldCA9IGNvbmZpZ3VyZWRSZXNldE1ldGhvZCB8fCBkZWZhdWx0RW1wdHlDYWxsYmFjazsKICAgICAgdGhpcy5fbWVyZ2UgPSBkZWZhdWx0RW1wdHlDYWxsYmFjazsKICAgIH0KICAgIC8qKgogICAgICogaG9vayB0byBhbGxvdyBtYW5hZ2VtZW50IG9mIG1lcmdlIGNvbmZsaWN0cyB3aXRoIGlkZW50aWZpZXJzLgogICAgICoKICAgICAqIHdlIGFsbG93IGxhdGUgYmluZGluZyBvZiB0aGlzIHByaXZhdGUgaW50ZXJuYWwgbWVyZ2Ugc28gdGhhdCBgaW50ZXJuYWxNb2RlbEZhY3RvcnlgCiAgICAgKiBjYW4gaW5zZXJ0IGl0c2VsZiBoZXJlIHRvIGhhbmRsZSBlbGltaW5hdGlvbiBvZiBkdXBsaWNhdGVzCiAgICAgKgogICAgICogQGludGVybmFsCiAgICAgKi8KCgogICAgdmFyIF9wcm90byA9IElkZW50aWZpZXJDYWNoZS5wcm90b3R5cGU7CgogICAgX3Byb3RvLl9fY29uZmlndXJlTWVyZ2UgPSBmdW5jdGlvbiBfX2NvbmZpZ3VyZU1lcmdlKG1ldGhvZCkgewogICAgICB0aGlzLl9tZXJnZSA9IG1ldGhvZCB8fCBkZWZhdWx0RW1wdHlDYWxsYmFjazsKICAgIH0KICAgIC8qKgogICAgICogQGludGVybmFsCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX2dldFJlY29yZElkZW50aWZpZXIgPSBmdW5jdGlvbiBfZ2V0UmVjb3JkSWRlbnRpZmllcihyZXNvdXJjZSwgc2hvdWxkR2VuZXJhdGUpIHsKICAgICAgaWYgKHNob3VsZEdlbmVyYXRlID09PSB2b2lkIDApIHsKICAgICAgICBzaG91bGRHZW5lcmF0ZSA9IGZhbHNlOwogICAgICB9CgogICAgICAvLyBzaG9ydCBjaXJjdWl0IGlmIHdlJ3JlIGFscmVhZHkgdGhlIHN0YWJsZSB2ZXJzaW9uCiAgICAgIGlmIChpc1N0YWJsZUlkZW50aWZpZXIocmVzb3VyY2UpKSB7CgogICAgICAgIHJldHVybiByZXNvdXJjZTsKICAgICAgfSAvLyBgdHlwZWAgbXVzdCBhbHdheXMgYmUgcHJlc2VudAoKICAgICAgdmFyIHR5cGUgPSBub3JtYWxpemVNb2RlbE5hbWUocmVzb3VyY2UudHlwZSk7CiAgICAgIHZhciBrZXlPcHRpb25zID0gZ2V0VHlwZUluZGV4KHRoaXMuX2NhY2hlLnR5cGVzLCB0eXBlKTsKICAgICAgdmFyIGlkZW50aWZpZXI7CiAgICAgIHZhciBsaWQgPSBjb2VyY2VJZChyZXNvdXJjZS5saWQpOwogICAgICB2YXIgaWQgPSBjb2VyY2VJZChyZXNvdXJjZS5pZCk7IC8vIGdvIHN0cmFpZ2h0IGZvciB0aGUgc3RhYmxlIFJlY29yZElkZW50aWZpZXIga2V5J2QgdG8gYGxpZGAKCiAgICAgIGlmIChsaWQgIT09IG51bGwpIHsKICAgICAgICBpZGVudGlmaWVyID0ga2V5T3B0aW9ucy5saWRbbGlkXTsKICAgICAgfSAvLyB3ZSBtYXkgaGF2ZSBub3Qgc2VlbiB0aGlzIHJlc291cmNlIGJlZm9yZQogICAgICAvLyBidXQganVzdCBpbiBjYXNlIHdlIGNoZWNrIG91ciBvd24gc2Vjb25kYXJ5IGxvb2t1cCAoYGlkYCkKCgogICAgICBpZiAoaWRlbnRpZmllciA9PT0gdW5kZWZpbmVkICYmIGlkICE9PSBudWxsKSB7CiAgICAgICAgaWRlbnRpZmllciA9IGtleU9wdGlvbnMuaWRbaWRdOwogICAgICB9CgogICAgICBpZiAoaWRlbnRpZmllciA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgLy8gd2UgaGF2ZSBkZWZpbml0ZWx5IG5vdCBzZWVuIHRoaXMgcmVzb3VyY2UgYmVmb3JlCiAgICAgICAgLy8gc28gd2UgYWxsb3cgdGhlIHVzZXIgY29uZmlndXJlZCBgR2VuZXJhdGlvbk1ldGhvZGAgdG8gdGVsbCB1cwogICAgICAgIHZhciBuZXdMaWQgPSB0aGlzLl9nZW5lcmF0ZShyZXNvdXJjZSwgJ3JlY29yZCcpOyAvLyB3ZSBkbyB0aGlzIF9ldmVuXyB3aGVuIGBsaWRgIGlzIHByZXNlbnQgYmVjYXVzZSBzZWNvbmRhcnkgbG9va3VwcwogICAgICAgIC8vIG1heSBuZWVkIHRvIGJlIHBvcHVsYXRlZCwgYnV0IHdlIGVuZm9yY2Ugbm90IGdpdmluZyB1cyBzb21ldGhpbmcKICAgICAgICAvLyBkaWZmZXJlbnQgdGhhbiBleHBlY3RlZAoKCiAgICAgICAgaWYgKGxpZCAhPT0gbnVsbCAmJiBuZXdMaWQgIT09IGxpZCkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJZb3Ugc2hvdWxkIG5vdCBjaGFuZ2UgdGhlIDxsaWQ+IG9mIGEgUmVjb3JkSWRlbnRpZmllciIpOwogICAgICAgIH0gZWxzZSBpZiAobGlkID09PSBudWxsKSB7CiAgICAgICAgICAvLyBhbGxvdyBjb25maWd1cmF0aW9uIHRvIHRlbGwgdXMgdGhhdCB3ZSBoYXZlCiAgICAgICAgICAvLyBzZWVuIHRoaXMgYGxpZGAgYmVmb3JlLiBFLmcuIGEgc2Vjb25kYXJ5IGxvb2t1cAogICAgICAgICAgLy8gY29ubmVjdHMgdGhpcyByZXNvdXJjZSB0byBhIHByZXZpb3VzbHkgc2VlbgogICAgICAgICAgLy8gcmVzb3VyY2UuCiAgICAgICAgICBpZGVudGlmaWVyID0ga2V5T3B0aW9ucy5saWRbbmV3TGlkXTsKICAgICAgICB9CgogICAgICAgIGlmIChzaG91bGRHZW5lcmF0ZSA9PT0gdHJ1ZSkgewogICAgICAgICAgaWYgKGlkZW50aWZpZXIgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAvLyBpZiB3ZSBzdGlsbCBkb24ndCBoYXZlIGFuIGlkZW50aWZpZXIsIHRpbWUgdG8gZ2VuZXJhdGUgb25lCiAgICAgICAgICAgIGlkZW50aWZpZXIgPSBtYWtlU3RhYmxlUmVjb3JkSWRlbnRpZmllcihpZCwgdHlwZSwgbmV3TGlkKTsgLy8gcG9wdWxhdGUgb3VyIHVuaXF1ZSB0YWJsZQoKICAgICAgICAgICAgdGhpcy5fY2FjaGUubGlkc1tpZGVudGlmaWVyLmxpZF0gPSBpZGVudGlmaWVyOyAvLyBwb3B1bGF0ZSBvdXIgcHJpbWFyeSBsb29rdXAgdGFibGUKICAgICAgICAgICAgLy8gVE9ETyBjb25zaWRlciBoYXZpbmcgdGhlIGBsaWRgIGNhY2hlIGJlCiAgICAgICAgICAgIC8vIG9uZSBsZXZlbCB1cAoKICAgICAgICAgICAga2V5T3B0aW9ucy5saWRbaWRlbnRpZmllci5saWRdID0gaWRlbnRpZmllcjsgLy8gVE9ETyBleGlzdHMgdGVtcG9yYXJpbHkgdG8gc3VwcG9ydCBgcGVla0FsbGAKICAgICAgICAgICAgLy8gYnV0IGxpa2VseSB0byBtb3ZlCgogICAgICAgICAgICBrZXlPcHRpb25zLl9hbGxJZGVudGlmaWVycy5wdXNoKGlkZW50aWZpZXIpOwogICAgICAgICAgfSAvLyBwb3B1bGF0ZSBvdXIgb3duIHNlY29uZGFyeSBsb29rdXAgdGFibGUKICAgICAgICAgIC8vIGV2ZW4gZm9yIHRoZSAic3VjY2Vzc2Z1bCIgc2Vjb25kYXJ5IGxvb2t1cAogICAgICAgICAgLy8gYnkgYF9nZW5lcmF0ZSgpYCwgc2luY2Ugd2UgbWlzc2VkIHRoZSBjYWNoZQogICAgICAgICAgLy8gcHJldmlvdXNseQogICAgICAgICAgLy8gd2UgdXNlIGlkZW50aWZpZXIuaWQgaW5zdGVhZCBvZiBpZCBoZXJlCiAgICAgICAgICAvLyBiZWNhdXNlIHRoZXkgbWF5IG5vdCBtYXRjaCBhbmQgd2UgcHJlZmVyCiAgICAgICAgICAvLyB3aGF0IHdlJ3ZlIHNldCB2aWEgcmVzb3VyY2UgZGF0YQoKCiAgICAgICAgICBpZiAoaWRlbnRpZmllci5pZCAhPT0gbnVsbCkgewogICAgICAgICAgICBrZXlPcHRpb25zLmlkW2lkZW50aWZpZXIuaWRdID0gaWRlbnRpZmllcjsgLy8gVE9ETyBhbGxvdyBmaWxsaW5nIG91dCBvZiBgaWRgIGhlcmUKICAgICAgICAgICAgLy8gZm9yIHRoZSBgdXNlcm5hbWVgIG5vbi1jbGllbnQgY3JlYXRlZAogICAgICAgICAgICAvLyBjYXNlLgogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGlkZW50aWZpZXI7CiAgICB9CiAgICAvKioKICAgICAqIGFsbG93cyB1cyB0byBwZWVrIHdpdGhvdXQgZ2VuZXJhdGluZyB3aGVuIG5lZWRlZAogICAgICogdXNlZnVsIGZvciB0aGUgImNyZWF0ZSIgY2FzZSB3aGVuIHdlIG5lZWQgdG8gc2VlIGlmCiAgICAgKiB3ZSBhcmUgYWNjaWRlbnRhbGx5IG92ZXJ3cml0dGluZyBzb21ldGhpbmcKICAgICAqCiAgICAgKiBAaW50ZXJuYWwKICAgICAqLwogICAgOwoKICAgIF9wcm90by5wZWVrUmVjb3JkSWRlbnRpZmllciA9IGZ1bmN0aW9uIHBlZWtSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlKSB7CiAgICAgIHJldHVybiB0aGlzLl9nZXRSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlLCBmYWxzZSk7CiAgICB9CiAgICAvKgogICAgICBSZXR1cm5zIHRoZSBJZGVudGlmaWVyIGZvciB0aGUgZ2l2ZW4gUmVzb3VyY2UsIGNyZWF0ZXMgb25lIGlmIGl0IGRvZXMgbm90IHlldCBleGlzdC4KICAgICAgIFNwZWNpZmljYWxseSB0aGlzIG1lYW5zIHRoYXQgd2U6CiAgICAgICAtIHZhbGlkYXRlIHRoZSBgaWRgIGB0eXBlYCBhbmQgYGxpZGAgY29tYm8gYWdhaW5zdCBrbm93biBpZGVudGlmaWVycwogICAgICAtIHJldHVybiBhbiBvYmplY3Qgd2l0aCBhbiBgbGlkYCB0aGF0IGlzIHN0YWJsZSAocmVwZWF0ZWQgY2FsbHMgd2l0aCB0aGUgc2FtZQogICAgICAgIGBpZGAgKyBgdHlwZWAgb3IgYGxpZGAgd2lsbCByZXR1cm4gdGhlIHNhbWUgYGxpZGAgdmFsdWUpCiAgICAgIC0gdGhpcyByZWZlcmVudGlhbCBzdGFiaWxpdHkgb2YgdGhlIG9iamVjdCBpdHNlbGYgaXMgZ3VhcmFudGVlZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZ2V0T3JDcmVhdGVSZWNvcmRJZGVudGlmaWVyID0gZnVuY3Rpb24gZ2V0T3JDcmVhdGVSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlKSB7CiAgICAgIHJldHVybiB0aGlzLl9nZXRSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlLCB0cnVlKTsKICAgIH0KICAgIC8qCiAgICAgUmV0dXJucyBhIG5ldyBJZGVudGlmaWVyIGZvciB0aGUgc3VwcGxpZWQgZGF0YS4gQ2FsbCB0aGlzIG1ldGhvZCB0byBnZW5lcmF0ZQogICAgIGFuIGlkZW50aWZpZXIgd2hlbiBhIG5ldyByZXNvdXJjZSBpcyBiZWluZyBjcmVhdGVkIGxvY2FsIHRvIHRoZSBjbGllbnQgYW5kCiAgICAgcG90ZW50aWFsbHkgZG9lcyBub3QgaGF2ZSBhbiBgaWRgLgogICAgICBEZWxlZ2F0ZXMgZ2VuZXJhdGlvbiB0byB0aGUgdXNlciBzdXBwbGllZCBgR2VuZXJhdGVNZXRob2RgIGlmIG9uZSBoYXMgYmVlbiBwcm92aWRlZAogICAgIHdpdGggdGhlIHNpZ25hdHVyZSBgZ2VuZXJhdGVNZXRob2QoeyB0eXBlIH0sICdyZWNvcmQnKWAuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uY3JlYXRlSWRlbnRpZmllckZvck5ld1JlY29yZCA9IGZ1bmN0aW9uIGNyZWF0ZUlkZW50aWZpZXJGb3JOZXdSZWNvcmQoZGF0YSkgewogICAgICB2YXIgbmV3TGlkID0gdGhpcy5fZ2VuZXJhdGUoZGF0YSwgJ3JlY29yZCcpOwoKICAgICAgdmFyIGlkZW50aWZpZXIgPSBtYWtlU3RhYmxlUmVjb3JkSWRlbnRpZmllcihkYXRhLmlkIHx8IG51bGwsIGRhdGEudHlwZSwgbmV3TGlkKTsKICAgICAgdmFyIGtleU9wdGlvbnMgPSBnZXRUeXBlSW5kZXgodGhpcy5fY2FjaGUudHlwZXMsIGRhdGEudHlwZSk7IC8vIHBvcHVsYXRlIG91ciB1bmlxdWUgdGFibGUKCiAgICAgIHRoaXMuX2NhY2hlLmxpZHNbaWRlbnRpZmllci5saWRdID0gaWRlbnRpZmllcjsgLy8gcG9wdWxhdGUgdGhlIHR5cGUrbGlkIGNhY2hlCgogICAgICBrZXlPcHRpb25zLmxpZFtuZXdMaWRdID0gaWRlbnRpZmllcjsgLy8gZW5zdXJlIGEgcGVla0FsbCBzZWVzIG91ciBuZXcgaWRlbnRpZmllciB0b28KICAgICAgLy8gVE9ETyBtb3ZlIHRoaXMgb3V0dGEgaGVyZT8KCiAgICAgIGtleU9wdGlvbnMuX2FsbElkZW50aWZpZXJzLnB1c2goaWRlbnRpZmllcik7CgogICAgICByZXR1cm4gaWRlbnRpZmllcjsKICAgIH0KICAgIC8qCiAgICAgUHJvdmlkZXMgdGhlIG9wcG9ydHVuaXR5IHRvIHVwZGF0ZSBzZWNvbmRhcnkgbG9va3VwIHRhYmxlcyBmb3IgZXhpc3RpbmcgaWRlbnRpZmllcnMKICAgICBDYWxsZWQgYWZ0ZXIgYW4gaWRlbnRpZmllciBjcmVhdGVkIHdpdGggYGNyZWF0ZUlkZW50aWZpZXJGb3JOZXdSZWNvcmRgIGhhcyBiZWVuCiAgICAgY29tbWl0dGVkLgogICAgICBBc3NpZ25lZCBgaWRgIHRvIGFuIGBJZGVudGlmaWVyYCBpZiBgaWRgIGhhcyBub3QgcHJldmlvdXNseSBleGlzdGVkOyBob3dldmVyLAogICAgIGF0dGVtcHRpbmcgdG8gY2hhbmdlIHRoZSBgaWRgIG9yIGNhbGxpbmcgdXBkYXRlIHdpdGhvdXQgcHJvdmlkaW5nIGFuIGBpZGAgd2hlbgogICAgIG9uZSBpcyBtaXNzaW5nIHdpbGwgdGhyb3cgYW4gZXJyb3IuCiAgICAgICAtIHNldHMgYGlkYCAoaWYgYGlkYCB3YXMgcHJldmlvdXNseSBgbnVsbGApCiAgICAgIC0gYGxpZGAgYW5kIGB0eXBlYCBNVVNUIE5PVCBiZSBhbHRlcmVkIHBvc3QgY3JlYXRpb24KICAgICAgIElmIGEgbWVyZ2Ugb2NjdXJzLCBpdCBpcyBwb3NzaWJsZSB0aGUgcmV0dXJuZWQgaWRlbnRpZmllciBkb2VzIG5vdCBtYXRjaCB0aGUgb3JpZ2luYWxseQogICAgICBwcm92aWRlZCBpZGVudGlmaWVyLiBJbiB0aGlzIGNhc2UgdGhlIGFiYW5kb25lZCBpZGVudGlmaWVyIHdpbGwgZ28gdGhyb3VnaCB0aGUgdXN1YWwKICAgICAgYGZvcmdldFJlY29yZElkZW50aWZpZXJgIGNvZGVwYXRocy4KICAgICovCiAgICA7CgogICAgX3Byb3RvLnVwZGF0ZVJlY29yZElkZW50aWZpZXIgPSBmdW5jdGlvbiB1cGRhdGVSZWNvcmRJZGVudGlmaWVyKGlkZW50aWZpZXJPYmplY3QsIGRhdGEpIHsKICAgICAgdmFyIGlkZW50aWZpZXIgPSB0aGlzLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihpZGVudGlmaWVyT2JqZWN0KTsKICAgICAgdmFyIGlkID0gaWRlbnRpZmllci5pZDsKICAgICAgdmFyIG5ld0lkID0gY29lcmNlSWQoZGF0YS5pZCk7CiAgICAgIHZhciBrZXlPcHRpb25zID0gZ2V0VHlwZUluZGV4KHRoaXMuX2NhY2hlLnR5cGVzLCBpZGVudGlmaWVyLnR5cGUpOwogICAgICB2YXIgZXhpc3RpbmdJZGVudGlmaWVyID0gZGV0ZWN0TWVyZ2Uoa2V5T3B0aW9ucywgaWRlbnRpZmllciwgbmV3SWQpOwoKICAgICAgaWYgKGV4aXN0aW5nSWRlbnRpZmllcikgewogICAgICAgIGlkZW50aWZpZXIgPSB0aGlzLl9tZXJnZVJlY29yZElkZW50aWZpZXJzKGtleU9wdGlvbnMsIGlkZW50aWZpZXIsIGV4aXN0aW5nSWRlbnRpZmllciwgZGF0YSwgbmV3SWQpOwogICAgICB9CgogICAgICBpZCA9IGlkZW50aWZpZXIuaWQ7CiAgICAgIHBlcmZvcm1SZWNvcmRJZGVudGlmaWVyVXBkYXRlKGlkZW50aWZpZXIsIGRhdGEsIHRoaXMuX3VwZGF0ZSk7CiAgICAgIG5ld0lkID0gaWRlbnRpZmllci5pZDsgLy8gYWRkIHRvIG91ciBvd24gc2Vjb25kYXJ5IGxvb2t1cCB0YWJsZQoKICAgICAgaWYgKGlkICE9PSBuZXdJZCAmJiBuZXdJZCAhPT0gbnVsbCkgewogICAgICAgIHZhciBfa2V5T3B0aW9ucyA9IGdldFR5cGVJbmRleCh0aGlzLl9jYWNoZS50eXBlcywgaWRlbnRpZmllci50eXBlKTsKCiAgICAgICAgX2tleU9wdGlvbnMuaWRbbmV3SWRdID0gaWRlbnRpZmllcjsKCiAgICAgICAgaWYgKGlkICE9PSBudWxsKSB7CiAgICAgICAgICBkZWxldGUgX2tleU9wdGlvbnMuaWRbaWRdOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGlkZW50aWZpZXI7CiAgICB9OwoKICAgIF9wcm90by5fbWVyZ2VSZWNvcmRJZGVudGlmaWVycyA9IGZ1bmN0aW9uIF9tZXJnZVJlY29yZElkZW50aWZpZXJzKGtleU9wdGlvbnMsIGlkZW50aWZpZXIsIGV4aXN0aW5nSWRlbnRpZmllciwgZGF0YSwgbmV3SWQpIHsKICAgICAgLy8gZGVsZWdhdGUgZGV0ZXJtaW5pbmcgd2hpY2ggaWRlbnRpZmllciB0byBrZWVwIHRvIHRoZSBjb25maWd1cmVkIE1lcmdlTWV0aG9kCiAgICAgIHZhciBrZXB0ID0gdGhpcy5fbWVyZ2UoaWRlbnRpZmllciwgZXhpc3RpbmdJZGVudGlmaWVyLCBkYXRhKTsKCiAgICAgIHZhciBhYmFuZG9uZWQgPSBrZXB0ID09PSBpZGVudGlmaWVyID8gZXhpc3RpbmdJZGVudGlmaWVyIDogaWRlbnRpZmllcjsgLy8gY2xlYW51cCB0aGUgaWRlbnRpZmllciB3ZSBubyBsb25nZXIgbmVlZAoKICAgICAgdGhpcy5mb3JnZXRSZWNvcmRJZGVudGlmaWVyKGFiYW5kb25lZCk7IC8vIGVuc3VyZSBhIHNlY29uZGFyeSBjYWNoZSBlbnRyeSBmb3IgdGhpcyBpZCBmb3IgdGhlIGlkZW50aWZpZXIgd2UgZG8ga2VlcAoKICAgICAga2V5T3B0aW9ucy5pZFtuZXdJZF0gPSBrZXB0OyAvLyBtYWtlIHN1cmUgdGhhdCB0aGUgYGxpZGAgb24gdGhlIGRhdGEgd2UgYXJlIHByb2Nlc3NpbmcgbWF0Y2hlcyB0aGUgbGlkIHdlIGtlcHQKCiAgICAgIGRhdGEubGlkID0ga2VwdC5saWQ7CiAgICAgIHJldHVybiBrZXB0OwogICAgfQogICAgLyoKICAgICBQcm92aWRlcyB0aGUgb3Bwb3J0dW5pdHkgdG8gZWxpbWluYXRlIGFuIGlkZW50aWZpZXIgZnJvbSBzZWNvbmRhcnkgbG9va3VwIHRhYmxlcwogICAgIGFzIHdlbGwgYXMgZWxpbWluYXRlcyBpdCBmcm9tIGVtYmVyLWRhdGEncyBvd24gbG9va3VwIHRhYmxlcyBhbmQgYm9vayBrZWVwaW5nLgogICAgICBVc2VmdWwgd2hlbiBhIHJlY29yZCBoYXMgYmVlbiBkZWxldGVkIGFuZCB0aGUgZGVsZXRpb24gaGFzIGJlZW4gcGVyc2lzdGVkIGFuZAogICAgIHdlIGRvIG5vdCBjYXJlIGFib3V0IHRoZSByZWNvcmQgYW55bW9yZS4gRXNwZWNpYWxseSB1c2VmdWwgd2hlbiBhbiBgaWRgIG9mIGEKICAgICBkZWxldGVkIHJlY29yZCBtaWdodCBiZSByZXVzZWQgbGF0ZXIgZm9yIGEgbmV3IHJlY29yZC4KICAgICovCiAgICA7CgogICAgX3Byb3RvLmZvcmdldFJlY29yZElkZW50aWZpZXIgPSBmdW5jdGlvbiBmb3JnZXRSZWNvcmRJZGVudGlmaWVyKGlkZW50aWZpZXJPYmplY3QpIHsKICAgICAgdmFyIGlkZW50aWZpZXIgPSB0aGlzLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihpZGVudGlmaWVyT2JqZWN0KTsKICAgICAgdmFyIGtleU9wdGlvbnMgPSBnZXRUeXBlSW5kZXgodGhpcy5fY2FjaGUudHlwZXMsIGlkZW50aWZpZXIudHlwZSk7CgogICAgICBpZiAoaWRlbnRpZmllci5pZCAhPT0gbnVsbCkgewogICAgICAgIGRlbGV0ZSBrZXlPcHRpb25zLmlkW2lkZW50aWZpZXIuaWRdOwogICAgICB9CgogICAgICBkZWxldGUgdGhpcy5fY2FjaGUubGlkc1tpZGVudGlmaWVyLmxpZF07CiAgICAgIGRlbGV0ZSBrZXlPcHRpb25zLmxpZFtpZGVudGlmaWVyLmxpZF07CgogICAgICB2YXIgaW5kZXggPSBrZXlPcHRpb25zLl9hbGxJZGVudGlmaWVycy5pbmRleE9mKGlkZW50aWZpZXIpOwoKICAgICAga2V5T3B0aW9ucy5fYWxsSWRlbnRpZmllcnMuc3BsaWNlKGluZGV4LCAxKTsKCiAgICAgIHVubWFya1N0YWJsZUlkZW50aWZpZXIoaWRlbnRpZmllck9iamVjdCk7CgogICAgICB0aGlzLl9mb3JnZXQoaWRlbnRpZmllciwgJ3JlY29yZCcpOwogICAgfTsKCiAgICBfcHJvdG8uZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3Jlc2V0KCk7CiAgICB9OwoKICAgIHJldHVybiBJZGVudGlmaWVyQ2FjaGU7CiAgfSgpOwoKICBmdW5jdGlvbiBnZXRUeXBlSW5kZXgodHlwZU1hcCwgdHlwZSkgewogICAgdmFyIHR5cGVJbmRleCA9IHR5cGVNYXBbdHlwZV07CgogICAgaWYgKHR5cGVJbmRleCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHR5cGVJbmRleCA9IHsKICAgICAgICBsaWQ6IE9iamVjdC5jcmVhdGUobnVsbCksCiAgICAgICAgaWQ6IE9iamVjdC5jcmVhdGUobnVsbCksCiAgICAgICAgX2FsbElkZW50aWZpZXJzOiBbXQogICAgICB9OwogICAgICB0eXBlTWFwW3R5cGVdID0gdHlwZUluZGV4OwogICAgfQoKICAgIHJldHVybiB0eXBlSW5kZXg7CiAgfQoKICBmdW5jdGlvbiBtYWtlU3RhYmxlUmVjb3JkSWRlbnRpZmllcihpZCwgdHlwZSwgbGlkLCBidWNrZXQsIGNsaWVudE9yaWdpbmF0ZWQpIHsKCiAgICB2YXIgcmVjb3JkSWRlbnRpZmllciA9IHsKICAgICAgbGlkOiBsaWQsCiAgICAgIGlkOiBpZCwKICAgICAgdHlwZTogdHlwZQogICAgfTsKICAgIG1hcmtTdGFibGVJZGVudGlmaWVyKHJlY29yZElkZW50aWZpZXIpOwoKICAgIHJldHVybiByZWNvcmRJZGVudGlmaWVyOwogIH0KCiAgZnVuY3Rpb24gcGVyZm9ybVJlY29yZElkZW50aWZpZXJVcGRhdGUoaWRlbnRpZmllciwgZGF0YSwgdXBkYXRlRm4pIHsKICAgIHZhciBpZCA9IGRhdGEuaWQsCiAgICAgICAgbGlkID0gZGF0YS5saWQ7CiAgICB2YXIgdHlwZSA9IG5vcm1hbGl6ZU1vZGVsTmFtZShkYXRhLnR5cGUpOwoKICAgIHsKICAgICAgdXBkYXRlRm4oaWRlbnRpZmllciwgZGF0YSwgJ3JlY29yZCcpOwogICAgfSAvLyB1cGdyYWRlIHRoZSBJRCwgdGhpcyBpcyBhICJvbmUgdGltZSBvbmx5IiBhYmlsaXR5CiAgICAvLyBmb3IgdGhlIG11bHRpcGxlLWNhY2hlLWtleSBzY2VuYXJpbyB3ZSAiY291bGQiCiAgICAvLyB1c2UgYSBoZXVyaXN0aWMgdG8gZ3Vlc3MgdGhlIGJlc3QgaWQgZm9yIGRpc3BsYXkKICAgIC8vICh1c3VhbGx5IHdoZW4gYGRhdGEuaWRgIGlzIGF2YWlsYWJsZSBhbmQgYGRhdGEuYXR0cmlidXRlc2AgaXMgbm90KQoKCiAgICBpZiAoaWQgIT09IHVuZGVmaW5lZCkgewogICAgICBpZGVudGlmaWVyLmlkID0gY29lcmNlSWQoaWQpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZGV0ZWN0TWVyZ2Uoa2V5T3B0aW9ucywgaWRlbnRpZmllciwgbmV3SWQpIHsKICAgIHZhciBpZCA9IGlkZW50aWZpZXIuaWQ7CgogICAgaWYgKGlkICE9PSBudWxsICYmIGlkICE9PSBuZXdJZCAmJiBuZXdJZCAhPT0gbnVsbCkgewogICAgICB2YXIgZXhpc3RpbmdJZGVudGlmaWVyID0ga2V5T3B0aW9ucy5pZFtuZXdJZF07CiAgICAgIHJldHVybiBleGlzdGluZ0lkZW50aWZpZXIgIT09IHVuZGVmaW5lZCA/IGV4aXN0aW5nSWRlbnRpZmllciA6IGZhbHNlOwogICAgfQoKICAgIHJldHVybiBmYWxzZTsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCiAgLyoKICAgIFRoaXMgZmlsZSBlbmNhcHN1bGF0ZXMgdGhlIHZhcmlvdXMgc3RhdGVzIHRoYXQgYSByZWNvcmQgY2FuIHRyYW5zaXRpb24KICAgIHRocm91Z2ggZHVyaW5nIGl0cyBsaWZlY3ljbGUuCiAgKi8KCiAgLyoqCiAgICAjIyMgU3RhdGUKCiAgICBFYWNoIHJlY29yZCBoYXMgYSBgY3VycmVudFN0YXRlYCBwcm9wZXJ0eSB0aGF0IGV4cGxpY2l0bHkgdHJhY2tzIHdoYXQKICAgIHN0YXRlIGEgcmVjb3JkIGlzIGluIGF0IGFueSBnaXZlbiB0aW1lLiBGb3IgaW5zdGFuY2UsIGlmIGEgcmVjb3JkIGlzCiAgICBuZXdseSBjcmVhdGVkIGFuZCBoYXMgbm90IHlldCBiZWVuIHNlbnQgdG8gdGhlIGFkYXB0ZXIgdG8gYmUgc2F2ZWQsCiAgICBpdCB3b3VsZCBiZSBpbiB0aGUgYHJvb3QubG9hZGVkLmNyZWF0ZWQudW5jb21taXR0ZWRgIHN0YXRlLiAgSWYgYQogICAgcmVjb3JkIGhhcyBoYWQgbG9jYWwgbW9kaWZpY2F0aW9ucyBtYWRlIHRvIGl0IHRoYXQgYXJlIGluIHRoZQogICAgcHJvY2VzcyBvZiBiZWluZyBzYXZlZCwgdGhlIHJlY29yZCB3b3VsZCBiZSBpbiB0aGUKICAgIGByb290LmxvYWRlZC51cGRhdGVkLmluRmxpZ2h0YCBzdGF0ZS4gKFRoaXMgc3RhdGUgcGF0aCB3aWxsIGJlCiAgICBleHBsYWluZWQgaW4gbW9yZSBkZXRhaWwgYmVsb3cuKQoKICAgIEV2ZW50cyBhcmUgc2VudCBieSB0aGUgcmVjb3JkIG9yIGl0cyBzdG9yZSB0byB0aGUgcmVjb3JkJ3MKICAgIGBjdXJyZW50U3RhdGVgIHByb3BlcnR5LiBIb3cgdGhlIHN0YXRlIHJlYWN0cyB0byB0aGVzZSBldmVudHMgaXMKICAgIGRlcGVuZGVudCBvbiB3aGljaCBzdGF0ZSBpdCBpcyBpbi4gSW4gc29tZSBzdGF0ZXMsIGNlcnRhaW4gZXZlbnRzCiAgICB3aWxsIGJlIGludmFsaWQgYW5kIHdpbGwgY2F1c2UgYW4gZXhjZXB0aW9uIHRvIGJlIHJhaXNlZC4KCiAgICBTdGF0ZXMgYXJlIGhpZXJhcmNoaWNhbCBhbmQgZXZlcnkgc3RhdGUgaXMgYSBzdWItc3RhdGUgb2YgdGhlCiAgICBgUm9vdFN0YXRlYC4gRm9yIGV4YW1wbGUsIGEgcmVjb3JkIGNhbiBiZSBpbiB0aGUKICAgIGByb290LmRlbGV0ZWQudW5jb21taXR0ZWRgIHN0YXRlIHRoZW4gdHJhbnNpdGlvbnMgaW50byB0aGUKICAgIGByb290LmRlbGV0ZWQuaW5GbGlnaHRgIHN0YXRlLiBJZiBhIGNoaWxkIHN0YXRlIGRvZXMgbm90IGltcGxlbWVudAogICAgYW4gZXZlbnQgaGFuZGxlciwgdGhlIHN0YXRlIG1hbmFnZXIgd2lsbCBhdHRlbXB0IHRvIGludm9rZSB0aGUgZXZlbnQKICAgIG9uIGFsbCBwYXJlbnQgc3RhdGVzIHVudGlsIHRoZSByb290IHN0YXRlIGlzIHJlYWNoZWQuIFRoZSBzdGF0ZQogICAgaGllcmFyY2h5IG9mIGEgcmVjb3JkIGlzIGRlc2NyaWJlZCBpbiB0ZXJtcyBvZiBhIHBhdGggc3RyaW5nLiBZb3UKICAgIGNhbiBkZXRlcm1pbmUgYSByZWNvcmQncyBjdXJyZW50IHN0YXRlIGJ5IGdldHRpbmcgdGhlIHN0YXRlJ3MKICAgIGBzdGF0ZU5hbWVgIHByb3BlcnR5OgoKICAgIGBgYGphdmFzY3JpcHQKICAgIHJlY29yZC5nZXQoJ2N1cnJlbnRTdGF0ZS5zdGF0ZU5hbWUnKTsKICAgIC8vPT4gInJvb3QuY3JlYXRlZC51bmNvbW1pdHRlZCIKICAgICBgYGAKCiAgICBUaGUgaGllcmFyY2h5IG9mIHZhbGlkIHN0YXRlcyB0aGF0IHNoaXAgd2l0aCBlbWJlciBkYXRhIGxvb2tzIGxpa2UKICAgIHRoaXM6CgogICAgYGBgdGV4dAogICAgKiByb290CiAgICAgICogZGVsZXRlZAogICAgICAgICogc2F2ZWQKICAgICAgICAqIHVuY29tbWl0dGVkCiAgICAgICAgKiBpbkZsaWdodAogICAgICAqIGVtcHR5CiAgICAgICogbG9hZGVkCiAgICAgICAgKiBjcmVhdGVkCiAgICAgICAgICAqIHVuY29tbWl0dGVkCiAgICAgICAgICAqIGluRmxpZ2h0CiAgICAgICAgKiBzYXZlZAogICAgICAgICogdXBkYXRlZAogICAgICAgICAgKiB1bmNvbW1pdHRlZAogICAgICAgICAgKiBpbkZsaWdodAogICAgICAqIGxvYWRpbmcKICAgIGBgYAoKICAgIFRoZSBgTW9kZWxgIHN0YXRlcyBhcmUgdGhlbXNlbHZlcyBzdGF0ZWxlc3MuIFdoYXQgdGhhdCBtZWFucyBpcwogICAgdGhhdCwgdGhlIGhpZXJhcmNoaWNhbCBzdGF0ZXMgdGhhdCBlYWNoIG9mICp0aG9zZSogcG9pbnRzIHRvIGlzIGEKICAgIHNoYXJlZCBkYXRhIHN0cnVjdHVyZS4gRm9yIHBlcmZvcm1hbmNlIHJlYXNvbnMsIGluc3RlYWQgb2YgZWFjaAogICAgcmVjb3JkIGdldHRpbmcgaXRzIG93biBjb3B5IG9mIHRoZSBoaWVyYXJjaHkgb2Ygc3RhdGVzLCBlYWNoIHJlY29yZAogICAgcG9pbnRzIHRvIHRoaXMgZ2xvYmFsLCBpbW11dGFibGUgc2hhcmVkIGluc3RhbmNlLiBIb3cgZG9lcyBhIHN0YXRlCiAgICBrbm93IHdoaWNoIHJlY29yZCBpdCBzaG91bGQgYmUgYWN0aW5nIG9uPyBXZSBwYXNzIHRoZSByZWNvcmQKICAgIGluc3RhbmNlIGludG8gdGhlIHN0YXRlJ3MgZXZlbnQgaGFuZGxlcnMgYXMgdGhlIGZpcnN0IGFyZ3VtZW50LgoKICAgIFRoZSByZWNvcmQgcGFzc2VkIGFzIHRoZSBmaXJzdCBwYXJhbWV0ZXIgaXMgd2hlcmUgeW91IHNob3VsZCBzdGFzaAogICAgc3RhdGUgYWJvdXQgdGhlIHJlY29yZCBpZiBuZWVkZWQ7IHlvdSBzaG91bGQgbmV2ZXIgc3RvcmUgZGF0YSBvbiB0aGUgc3RhdGUKICAgIG9iamVjdCBpdHNlbGYuCgogICAgIyMjIEV2ZW50cyBhbmQgRmxhZ3MKCiAgICBBIHN0YXRlIG1heSBpbXBsZW1lbnQgemVybyBvciBtb3JlIGV2ZW50cyBhbmQgZmxhZ3MuCgogICAgIyMjIyBFdmVudHMKCiAgICBFdmVudHMgYXJlIG5hbWVkIGZ1bmN0aW9ucyB0aGF0IGFyZSBpbnZva2VkIHdoZW4gc2VudCB0byBhIHJlY29yZC4gVGhlCiAgICByZWNvcmQgd2lsbCBmaXJzdCBsb29rIGZvciBhIG1ldGhvZCB3aXRoIHRoZSBnaXZlbiBuYW1lIG9uIHRoZQogICAgY3VycmVudCBzdGF0ZS4gSWYgbm8gbWV0aG9kIGlzIGZvdW5kLCBpdCB3aWxsIHNlYXJjaCB0aGUgY3VycmVudAogICAgc3RhdGUncyBwYXJlbnQsIGFuZCB0aGVuIGl0cyBncmFuZHBhcmVudCwgYW5kIHNvIG9uIHVudGlsIHJlYWNoaW5nCiAgICB0aGUgdG9wIG9mIHRoZSBoaWVyYXJjaHkuIElmIHRoZSByb290IGlzIHJlYWNoZWQgd2l0aG91dCBhbiBldmVudAogICAgaGFuZGxlciBiZWluZyBmb3VuZCwgYW4gZXhjZXB0aW9uIHdpbGwgYmUgcmFpc2VkLiBUaGlzIGNhbiBiZSB2ZXJ5CiAgICBoZWxwZnVsIHdoZW4gZGVidWdnaW5nIG5ldyBmZWF0dXJlcy4KCiAgICBIZXJlJ3MgYW4gZXhhbXBsZSBpbXBsZW1lbnRhdGlvbiBvZiBhIHN0YXRlIHdpdGggYSBgbXlFdmVudGAgZXZlbnQgaGFuZGxlcjoKCiAgICBgYGBqYXZhc2NyaXB0CiAgICBhU3RhdGU6IFN0YXRlLmNyZWF0ZSh7CiAgICAgIG15RXZlbnQ6IGZ1bmN0aW9uKG1hbmFnZXIsIHBhcmFtKSB7CiAgICAgICAgY29uc29sZS5sb2coIlJlY2VpdmVkIG15RXZlbnQgd2l0aCIsIHBhcmFtKTsKICAgICAgfQogICAgfSkKICAgIGBgYAoKICAgIFRvIHRyaWdnZXIgdGhpcyBldmVudDoKCiAgICBgYGBqYXZhc2NyaXB0CiAgICByZWNvcmQuc2VuZCgnbXlFdmVudCcsICdmb28nKTsKICAgIC8vPT4gIlJlY2VpdmVkIG15RXZlbnQgd2l0aCBmb28iCiAgICBgYGAKCiAgICBOb3RlIHRoYXQgYW4gb3B0aW9uYWwgcGFyYW1ldGVyIGNhbiBiZSBzZW50IHRvIGEgcmVjb3JkJ3MgYHNlbmQoKWAgbWV0aG9kLAogICAgd2hpY2ggd2lsbCBiZSBwYXNzZWQgYXMgdGhlIHNlY29uZCBwYXJhbWV0ZXIgdG8gdGhlIGV2ZW50IGhhbmRsZXIuCgogICAgRXZlbnRzIHNob3VsZCB0cmFuc2l0aW9uIHRvIGEgZGlmZmVyZW50IHN0YXRlIGlmIGFwcHJvcHJpYXRlLiBUaGlzIGNhbiBiZQogICAgZG9uZSBieSBjYWxsaW5nIHRoZSByZWNvcmQncyBgdHJhbnNpdGlvblRvKClgIG1ldGhvZCB3aXRoIGEgcGF0aCB0byB0aGUKICAgIGRlc2lyZWQgc3RhdGUuIFRoZSBzdGF0ZSBtYW5hZ2VyIHdpbGwgYXR0ZW1wdCB0byByZXNvbHZlIHRoZSBzdGF0ZSBwYXRoCiAgICByZWxhdGl2ZSB0byB0aGUgY3VycmVudCBzdGF0ZS4gSWYgbm8gc3RhdGUgaXMgZm91bmQgYXQgdGhhdCBwYXRoLCBpdCB3aWxsCiAgICBhdHRlbXB0IHRvIHJlc29sdmUgaXQgcmVsYXRpdmUgdG8gdGhlIGN1cnJlbnQgc3RhdGUncyBwYXJlbnQsIGFuZCB0aGVuIGl0cwogICAgcGFyZW50LCBhbmQgc28gb24gdW50aWwgdGhlIHJvb3QgaXMgcmVhY2hlZC4gRm9yIGV4YW1wbGUsIGltYWdpbmUgYSBoaWVyYXJjaHkKICAgIGxpa2UgdGhpczoKCiAgICAgICAgKiBjcmVhdGVkCiAgICAgICAgICAqIHVuY29tbWl0dGVkIDwtLSBjdXJyZW50U3RhdGUKICAgICAgICAgICogaW5GbGlnaHQKICAgICAgICAqIHVwZGF0ZWQKICAgICAgICAgICogaW5GbGlnaHQKCiAgICBJZiB3ZSBhcmUgY3VycmVudGx5IGluIHRoZSBgdW5jb21taXR0ZWRgIHN0YXRlLCBjYWxsaW5nCiAgICBgdHJhbnNpdGlvblRvKCdpbkZsaWdodCcpYCB3b3VsZCB0cmFuc2l0aW9uIHRvIHRoZSBgY3JlYXRlZC5pbkZsaWdodGAgc3RhdGUsCiAgICB3aGlsZSBjYWxsaW5nIGB0cmFuc2l0aW9uVG8oJ3VwZGF0ZWQuaW5GbGlnaHQnKWAgd291bGQgdHJhbnNpdGlvbiB0bwogICAgdGhlIGB1cGRhdGVkLmluRmxpZ2h0YCBzdGF0ZS4KCiAgICBSZW1lbWJlciB0aGF0ICpvbmx5IGV2ZW50cyogc2hvdWxkIGV2ZXIgY2F1c2UgYSBzdGF0ZSB0cmFuc2l0aW9uLiBZb3Ugc2hvdWxkCiAgICBuZXZlciBjYWxsIGB0cmFuc2l0aW9uVG8oKWAgZnJvbSBvdXRzaWRlIGEgc3RhdGUncyBldmVudCBoYW5kbGVyLiBJZiB5b3UgYXJlCiAgICB0ZW1wdGVkIHRvIGRvIHNvLCBjcmVhdGUgYSBuZXcgZXZlbnQgYW5kIHNlbmQgdGhhdCB0byB0aGUgc3RhdGUgbWFuYWdlci4KCiAgICAjIyMjIEZsYWdzCgogICAgRmxhZ3MgYXJlIEJvb2xlYW4gdmFsdWVzIHRoYXQgY2FuIGJlIHVzZWQgdG8gaW50cm9zcGVjdCBhIHJlY29yZCdzIGN1cnJlbnQKICAgIHN0YXRlIGluIGEgbW9yZSB1c2VyLWZyaWVuZGx5IHdheSB0aGFuIGV4YW1pbmluZyBpdHMgc3RhdGUgcGF0aC4gRm9yIGV4YW1wbGUsCiAgICBpbnN0ZWFkIG9mIGRvaW5nIHRoaXM6CgogICAgYGBgamF2YXNjcmlwdAogICAgdmFyIHN0YXRlUGF0aCA9IHJlY29yZC5nZXQoJ3N0YXRlTWFuYWdlci5jdXJyZW50UGF0aCcpOwogICAgaWYgKHN0YXRlUGF0aCA9PT0gJ2NyZWF0ZWQuaW5GbGlnaHQnKSB7CiAgICAgIGRvU29tZXRoaW5nKCk7CiAgICB9CiAgICBgYGAKCiAgICBZb3UgY2FuIHNheToKCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpZiAocmVjb3JkLmdldCgnaXNOZXcnKSAmJiByZWNvcmQuZ2V0KCdpc1NhdmluZycpKSB7CiAgICAgIGRvU29tZXRoaW5nKCk7CiAgICB9CiAgICBgYGAKCiAgICBJZiB5b3VyIHN0YXRlIGRvZXMgbm90IHNldCBhIHZhbHVlIGZvciBhIGdpdmVuIGZsYWcsIHRoZSB2YWx1ZSB3aWxsCiAgICBiZSBpbmhlcml0ZWQgZnJvbSBpdHMgcGFyZW50IChvciB0aGUgZmlyc3QgcGxhY2UgaW4gdGhlIHN0YXRlIGhpZXJhcmNoeQogICAgd2hlcmUgaXQgaXMgZGVmaW5lZCkuCgogICAgVGhlIGN1cnJlbnQgc2V0IG9mIGZsYWdzIGFyZSBkZWZpbmVkIGJlbG93LiBJZiB5b3Ugd2FudCB0byBhZGQgYSBuZXcgZmxhZywKICAgIGluIGFkZGl0aW9uIHRvIHRoZSBhcmVhIGJlbG93LCB5b3Ugd2lsbCBhbHNvIG5lZWQgdG8gZGVjbGFyZSBpdCBpbiB0aGUKICAgIGBNb2RlbGAgY2xhc3MuCgoKICAgICAqIFtpc0VtcHR5XShNb2RlbC9wcm9wZXJ0aWVzL2lzRW1wdHk/YW5jaG9yPWlzRW1wdHkpCiAgICAgKiBbaXNMb2FkaW5nXShNb2RlbC9wcm9wZXJ0aWVzL2lzTG9hZGluZz9hbmNob3I9aXNMb2FkaW5nKQogICAgICogW2lzTG9hZGVkXShNb2RlbC9wcm9wZXJ0aWVzL2lzTG9hZGVkP2FuY2hvcj1pc0xvYWRlZCkKICAgICAqIFtoYXNEaXJ0eUF0dHJpYnV0ZXNdKE1vZGVsL3Byb3BlcnRpZXMvaGFzRGlydHlBdHRyaWJ1dGVzP2FuY2hvcj1oYXNEaXJ0eUF0dHJpYnV0ZXMpCiAgICAgKiBbaXNTYXZpbmddKE1vZGVsL3Byb3BlcnRpZXMvaXNTYXZpbmc/YW5jaG9yPWlzU2F2aW5nKQogICAgICogW2lzRGVsZXRlZF0oTW9kZWwvcHJvcGVydGllcy9pc0RlbGV0ZWQ/YW5jaG9yPWlzRGVsZXRlZCkKICAgICAqIFtpc05ld10oTW9kZWwvcHJvcGVydGllcy9pc05ldz9hbmNob3I9aXNOZXcpCiAgICAgKiBbaXNWYWxpZF0oTW9kZWwvcHJvcGVydGllcy9pc1ZhbGlkP2FuY2hvcj1pc1ZhbGlkKQoKICAgIEBjbGFzcyBSb290U3RhdGUKICAqLwoKICBmdW5jdGlvbiBfZGlkU2V0UHJvcGVydHkoaW50ZXJuYWxNb2RlbCwgY29udGV4dCkgewogICAgaWYgKGNvbnRleHQuaXNEaXJ0eSkgewogICAgICBpbnRlcm5hbE1vZGVsLnNlbmQoJ2JlY29tZURpcnR5Jyk7CiAgICB9IGVsc2UgewogICAgICBpbnRlcm5hbE1vZGVsLnNlbmQoJ3Byb3BlcnR5V2FzUmVzZXQnKTsKICAgIH0KCiAgICBpbnRlcm5hbE1vZGVsLnVwZGF0ZVJlY29yZEFycmF5cygpOwogIH0gLy8gSW1wbGVtZW50YXRpb24gbm90ZXM6CiAgLy8KICAvLyBFYWNoIHN0YXRlIGhhcyBhIGJvb2xlYW4gdmFsdWUgZm9yIGFsbCBvZiB0aGUgZm9sbG93aW5nIGZsYWdzOgogIC8vCiAgLy8gKiBpc0xvYWRlZDogVGhlIHJlY29yZCBoYXMgYSBwb3B1bGF0ZWQgYGRhdGFgIHByb3BlcnR5LiBXaGVuIGEKICAvLyAgIHJlY29yZCBpcyBsb2FkZWQgdmlhIGBzdG9yZS5maW5kYCwgYGlzTG9hZGVkYCBpcyBmYWxzZQogIC8vICAgdW50aWwgdGhlIGFkYXB0ZXIgc2V0cyBpdC4gV2hlbiBhIHJlY29yZCBpcyBjcmVhdGVkIGxvY2FsbHksCiAgLy8gICBpdHMgYGlzTG9hZGVkYCBwcm9wZXJ0eSBpcyBhbHdheXMgdHJ1ZS4KICAvLyAqIGlzRGlydHk6IFRoZSByZWNvcmQgaGFzIGxvY2FsIGNoYW5nZXMgdGhhdCBoYXZlIG5vdCB5ZXQgYmVlbgogIC8vICAgc2F2ZWQgYnkgdGhlIGFkYXB0ZXIuIFRoaXMgaW5jbHVkZXMgcmVjb3JkcyB0aGF0IGhhdmUgYmVlbgogIC8vICAgY3JlYXRlZCAoYnV0IG5vdCB5ZXQgc2F2ZWQpIG9yIGRlbGV0ZWQuCiAgLy8gKiBpc1NhdmluZzogVGhlIHJlY29yZCBoYXMgYmVlbiBjb21taXR0ZWQsIGJ1dAogIC8vICAgdGhlIGFkYXB0ZXIgaGFzIG5vdCB5ZXQgYWNrbm93bGVkZ2VkIHRoYXQgdGhlIGNoYW5nZXMgaGF2ZQogIC8vICAgYmVlbiBwZXJzaXN0ZWQgdG8gdGhlIGJhY2tlbmQuCiAgLy8gKiBpc0RlbGV0ZWQ6IFRoZSByZWNvcmQgd2FzIG1hcmtlZCBmb3IgZGVsZXRpb24uIFdoZW4gYGlzRGVsZXRlZGAKICAvLyAgIGlzIHRydWUgYW5kIGBpc0RpcnR5YCBpcyB0cnVlLCB0aGUgcmVjb3JkIGlzIGRlbGV0ZWQgbG9jYWxseQogIC8vICAgYnV0IHRoZSBkZWxldGlvbiB3YXMgbm90IHlldCBwZXJzaXN0ZWQuIFdoZW4gYGlzU2F2aW5nYCBpcwogIC8vICAgdHJ1ZSwgdGhlIGNoYW5nZSBpcyBpbi1mbGlnaHQuIFdoZW4gYm90aCBgaXNEaXJ0eWAgYW5kCiAgLy8gICBgaXNTYXZpbmdgIGFyZSBmYWxzZSwgdGhlIGNoYW5nZSBoYXMgcGVyc2lzdGVkLgogIC8vICogaXNOZXc6IFRoZSByZWNvcmQgd2FzIGNyZWF0ZWQgb24gdGhlIGNsaWVudCBhbmQgdGhlIGFkYXB0ZXIKICAvLyAgIGRpZCBub3QgeWV0IHJlcG9ydCB0aGF0IGl0IHdhcyBzdWNjZXNzZnVsbHkgc2F2ZWQuCiAgLy8gKiBpc1ZhbGlkOiBUaGUgYWRhcHRlciBkaWQgbm90IHJlcG9ydCBhbnkgc2VydmVyLXNpZGUgdmFsaWRhdGlvbgogIC8vICAgZmFpbHVyZXMuCiAgLy8gVGhlIGRpcnR5IHN0YXRlIGlzIGEgYWJzdHJhY3Qgc3RhdGUgd2hvc2UgZnVuY3Rpb25hbGl0eSBpcwogIC8vIHNoYXJlZCBiZXR3ZWVuIHRoZSBgY3JlYXRlZGAgYW5kIGB1cGRhdGVkYCBzdGF0ZXMuCiAgLy8KICAvLyBUaGUgZGVsZXRlZCBzdGF0ZSBzaGFyZXMgdGhlIGBpc0RpcnR5YCBmbGFnIHdpdGggdGhlCiAgLy8gc3ViY2xhc3NlcyBvZiBgRGlydHlTdGF0ZWAsIGJ1dCB3aXRoIGEgdmVyeSBkaWZmZXJlbnQKICAvLyBpbXBsZW1lbnRhdGlvbi4KICAvLwogIC8vIERpcnR5IHN0YXRlcyBoYXZlIHRocmVlIGNoaWxkIHN0YXRlczoKICAvLwogIC8vIGB1bmNvbW1pdHRlZGA6IHRoZSBzdG9yZSBoYXMgbm90IHlldCBoYW5kZWQgb2ZmIHRoZSByZWNvcmQKICAvLyAgIHRvIGJlIHNhdmVkLgogIC8vIGBpbkZsaWdodGA6IHRoZSBzdG9yZSBoYXMgaGFuZGVkIG9mZiB0aGUgcmVjb3JkIHRvIGJlIHNhdmVkLAogIC8vICAgYnV0IHRoZSBhZGFwdGVyIGhhcyBub3QgeWV0IGFja25vd2xlZGdlZCBzdWNjZXNzLgogIC8vIGBpbnZhbGlkYDogdGhlIHJlY29yZCBoYXMgaW52YWxpZCBpbmZvcm1hdGlvbiBhbmQgY2Fubm90IGJlCiAgLy8gICBzZW50IHRvIHRoZSBhZGFwdGVyIHlldC4KCgogIHZhciBEaXJ0eVN0YXRlID0gewogICAgaW5pdGlhbFN0YXRlOiAndW5jb21taXR0ZWQnLAogICAgLy8gRkxBR1MKICAgIGlzRGlydHk6IHRydWUsCiAgICAvLyBTVUJTVEFURVMKICAgIC8vIFdoZW4gYSByZWNvcmQgZmlyc3QgYmVjb21lcyBkaXJ0eSwgaXQgaXMgYHVuY29tbWl0dGVkYC4KICAgIC8vIFRoaXMgbWVhbnMgdGhhdCB0aGVyZSBhcmUgbG9jYWwgcGVuZGluZyBjaGFuZ2VzLCBidXQgdGhleQogICAgLy8gaGF2ZSBub3QgeWV0IGJlZ3VuIHRvIGJlIHNhdmVkLCBhbmQgYXJlIG5vdCBpbnZhbGlkLgogICAgdW5jb21taXR0ZWQ6IHsKICAgICAgLy8gRVZFTlRTCiAgICAgIGRpZFNldFByb3BlcnR5OiBfZGlkU2V0UHJvcGVydHksCiAgICAgIC8vVE9ETyhJZ29yKSByZWxvYWRpbmcgbm93IHRyaWdnZXJzIGEKICAgICAgLy9sb2FkaW5nRGF0YSBldmVudCwgdGhvdWdoIGl0IHNlZW1zIGZpbmU/CiAgICAgIGxvYWRpbmdEYXRhOiBmdW5jdGlvbiBsb2FkaW5nRGF0YSgpIHt9LAogICAgICBwcm9wZXJ0eVdhc1Jlc2V0OiBmdW5jdGlvbiBwcm9wZXJ0eVdhc1Jlc2V0KGludGVybmFsTW9kZWwsIG5hbWUpIHsKICAgICAgICBpZiAoIWludGVybmFsTW9kZWwuaGFzQ2hhbmdlZEF0dHJpYnV0ZXMoKSkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC5zZW5kKCdyb2xsZWRCYWNrJyk7CiAgICAgICAgfQogICAgICB9LAogICAgICBwdXNoZWREYXRhOiBmdW5jdGlvbiBwdXNoZWREYXRhKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpZiAoIWludGVybmFsTW9kZWwuaGFzQ2hhbmdlZEF0dHJpYnV0ZXMoKSkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2xvYWRlZC5zYXZlZCcpOwogICAgICAgIH0KICAgICAgfSwKICAgICAgYmVjb21lRGlydHk6IGZ1bmN0aW9uIGJlY29tZURpcnR5KCkge30sCiAgICAgIHdpbGxDb21taXQ6IGZ1bmN0aW9uIHdpbGxDb21taXQoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdpbkZsaWdodCcpOwogICAgICB9LAogICAgICByZWxvYWRSZWNvcmQ6IGZ1bmN0aW9uIHJlbG9hZFJlY29yZChpbnRlcm5hbE1vZGVsLCBfcmVmKSB7CiAgICAgICAgdmFyIHJlc29sdmUgPSBfcmVmLnJlc29sdmUsCiAgICAgICAgICAgIG9wdGlvbnMgPSBfcmVmLm9wdGlvbnM7CiAgICAgICAgcmVzb2x2ZShpbnRlcm5hbE1vZGVsLnN0b3JlLl9yZWxvYWRSZWNvcmQoaW50ZXJuYWxNb2RlbCwgb3B0aW9ucykpOwogICAgICB9LAogICAgICByb2xsZWRCYWNrOiBmdW5jdGlvbiByb2xsZWRCYWNrKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnbG9hZGVkLnNhdmVkJyk7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ3JvbGxlZEJhY2snKTsKICAgICAgfSwKICAgICAgYmVjYW1lSW52YWxpZDogZnVuY3Rpb24gYmVjYW1lSW52YWxpZChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2ludmFsaWQnKTsKICAgICAgfSwKICAgICAgcm9sbGJhY2s6IGZ1bmN0aW9uIHJvbGxiYWNrKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnJvbGxiYWNrQXR0cmlidXRlcygpOwogICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdyZWFkeScpOwogICAgICB9CiAgICB9LAogICAgLy8gT25jZSBhIHJlY29yZCBoYXMgYmVlbiBoYW5kZWQgb2ZmIHRvIHRoZSBhZGFwdGVyIHRvIGJlCiAgICAvLyBzYXZlZCwgaXQgaXMgaW4gdGhlICdpbiBmbGlnaHQnIHN0YXRlLiBDaGFuZ2VzIHRvIHRoZQogICAgLy8gcmVjb3JkIGNhbm5vdCBiZSBtYWRlIGR1cmluZyB0aGlzIHdpbmRvdy4KICAgIGluRmxpZ2h0OiB7CiAgICAgIC8vIEZMQUdTCiAgICAgIGlzU2F2aW5nOiB0cnVlLAogICAgICAvLyBFVkVOVFMKICAgICAgZGlkU2V0UHJvcGVydHk6IF9kaWRTZXRQcm9wZXJ0eSwKICAgICAgYmVjb21lRGlydHk6IGZ1bmN0aW9uIGJlY29tZURpcnR5KCkge30sCiAgICAgIHB1c2hlZERhdGE6IGZ1bmN0aW9uIHB1c2hlZERhdGEoKSB7fSwKICAgICAgdW5sb2FkUmVjb3JkOiBhc3NlcnRBZ2FpbnN0VW5sb2FkUmVjb3JkLAogICAgICAvLyBUT0RPOiBNb3JlIHJvYnVzdCBzZW1hbnRpY3MgYXJvdW5kIHNhdmUtd2hpbGUtaW4tZmxpZ2h0CiAgICAgIHdpbGxDb21taXQ6IGZ1bmN0aW9uIHdpbGxDb21taXQoKSB7fSwKICAgICAgZGlkQ29tbWl0OiBmdW5jdGlvbiBkaWRDb21taXQoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdzYXZlZCcpOwogICAgICAgIGludGVybmFsTW9kZWwuc2VuZCgnaW52b2tlTGlmZWN5Y2xlQ2FsbGJhY2tzJywgdGhpcy5kaXJ0eVR5cGUpOwogICAgICB9LAogICAgICByb2xsZWRCYWNrOiBmdW5jdGlvbiByb2xsZWRCYWNrKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcigncm9sbGVkQmFjaycpOwogICAgICB9LAogICAgICBiZWNhbWVJbnZhbGlkOiBmdW5jdGlvbiBiZWNhbWVJbnZhbGlkKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnaW52YWxpZCcpOwogICAgICAgIGludGVybmFsTW9kZWwuc2VuZCgnaW52b2tlTGlmZWN5Y2xlQ2FsbGJhY2tzJyk7CiAgICAgIH0sCiAgICAgIGJlY2FtZUVycm9yOiBmdW5jdGlvbiBiZWNhbWVFcnJvcihpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ3VuY29tbWl0dGVkJyk7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ2JlY2FtZUVycm9yJywgaW50ZXJuYWxNb2RlbCk7CiAgICAgIH0KICAgIH0sCiAgICAvLyBBIHJlY29yZCBpcyBpbiB0aGUgYGludmFsaWRgIGlmIHRoZSBhZGFwdGVyIGhhcyBpbmRpY2F0ZWQKICAgIC8vIHRoZSB0aGUgcmVjb3JkIGZhaWxlZCBzZXJ2ZXItc2lkZSBpbnZhbGlkYXRpb25zLgogICAgaW52YWxpZDogewogICAgICAvLyBGTEFHUwogICAgICBpc1ZhbGlkOiBmYWxzZSwKICAgICAgLy8gRVZFTlRTCiAgICAgIGRlbGV0ZVJlY29yZDogZnVuY3Rpb24gZGVsZXRlUmVjb3JkKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnZGVsZXRlZC51bmNvbW1pdHRlZCcpOwogICAgICB9LAogICAgICBkaWRTZXRQcm9wZXJ0eTogZnVuY3Rpb24gZGlkU2V0UHJvcGVydHkoaW50ZXJuYWxNb2RlbCwgY29udGV4dCkgewogICAgICAgIGludGVybmFsTW9kZWwucmVtb3ZlRXJyb3JNZXNzYWdlRnJvbUF0dHJpYnV0ZShjb250ZXh0Lm5hbWUpOwoKICAgICAgICBfZGlkU2V0UHJvcGVydHkoaW50ZXJuYWxNb2RlbCwgY29udGV4dCk7CgogICAgICAgIGlmICghaW50ZXJuYWxNb2RlbC5oYXNFcnJvcnMoKSkgewogICAgICAgICAgdGhpcy5iZWNhbWVWYWxpZChpbnRlcm5hbE1vZGVsKTsKICAgICAgICB9CiAgICAgIH0sCiAgICAgIGJlY2FtZUludmFsaWQ6IGZ1bmN0aW9uIGJlY2FtZUludmFsaWQoKSB7fSwKICAgICAgYmVjb21lRGlydHk6IGZ1bmN0aW9uIGJlY29tZURpcnR5KCkge30sCiAgICAgIHB1c2hlZERhdGE6IGZ1bmN0aW9uIHB1c2hlZERhdGEoKSB7fSwKICAgICAgd2lsbENvbW1pdDogZnVuY3Rpb24gd2lsbENvbW1pdChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC5jbGVhckVycm9yTWVzc2FnZXMoKTsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnaW5GbGlnaHQnKTsKICAgICAgfSwKICAgICAgcm9sbGVkQmFjazogZnVuY3Rpb24gcm9sbGVkQmFjayhpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC5jbGVhckVycm9yTWVzc2FnZXMoKTsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnbG9hZGVkLnNhdmVkJyk7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ3JlYWR5Jyk7CiAgICAgIH0sCiAgICAgIGJlY2FtZVZhbGlkOiBmdW5jdGlvbiBiZWNhbWVWYWxpZChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ3VuY29tbWl0dGVkJyk7CiAgICAgIH0sCiAgICAgIGludm9rZUxpZmVjeWNsZUNhbGxiYWNrczogZnVuY3Rpb24gaW52b2tlTGlmZWN5Y2xlQ2FsbGJhY2tzKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcignYmVjYW1lSW52YWxpZCcsIGludGVybmFsTW9kZWwpOwogICAgICB9CiAgICB9CiAgfTsgLy8gVGhlIGNyZWF0ZWQgYW5kIHVwZGF0ZWQgc3RhdGVzIGFyZSBjcmVhdGVkIG91dHNpZGUgdGhlIHN0YXRlCiAgLy8gY2hhcnQgc28gd2UgY2FuIHJlb3BlbiB0aGVpciBzdWJzdGF0ZXMgYW5kIGFkZCBtaXhpbnMgYXMKICAvLyBuZWNlc3NhcnkuCgogIGZ1bmN0aW9uIGRlZXBDbG9uZShvYmplY3QpIHsKICAgIHZhciBjbG9uZSA9IHt9OwogICAgdmFyIHZhbHVlOwoKICAgIGZvciAodmFyIHByb3AgaW4gb2JqZWN0KSB7CiAgICAgIHZhbHVlID0gb2JqZWN0W3Byb3BdOwoKICAgICAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHsKICAgICAgICBjbG9uZVtwcm9wXSA9IGRlZXBDbG9uZSh2YWx1ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY2xvbmVbcHJvcF0gPSB2YWx1ZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBjbG9uZTsKICB9CgogIGZ1bmN0aW9uIG1peGluKG9yaWdpbmFsLCBoYXNoKSB7CiAgICBmb3IgKHZhciBwcm9wIGluIGhhc2gpIHsKICAgICAgb3JpZ2luYWxbcHJvcF0gPSBoYXNoW3Byb3BdOwogICAgfQoKICAgIHJldHVybiBvcmlnaW5hbDsKICB9CgogIGZ1bmN0aW9uIGRpcnR5U3RhdGUob3B0aW9ucykgewogICAgdmFyIG5ld1N0YXRlID0gZGVlcENsb25lKERpcnR5U3RhdGUpOwogICAgcmV0dXJuIG1peGluKG5ld1N0YXRlLCBvcHRpb25zKTsKICB9CgogIHZhciBjcmVhdGVkU3RhdGUgPSBkaXJ0eVN0YXRlKHsKICAgIGRpcnR5VHlwZTogJ2NyZWF0ZWQnLAogICAgLy8gRkxBR1MKICAgIGlzTmV3OiB0cnVlCiAgfSk7CgogIGNyZWF0ZWRTdGF0ZS5pbnZhbGlkLnJvbGxlZEJhY2sgPSBmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2RlbGV0ZWQuc2F2ZWQnKTsKICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdyb2xsZWRCYWNrJyk7CiAgfTsKCiAgY3JlYXRlZFN0YXRlLnVuY29tbWl0dGVkLnJvbGxlZEJhY2sgPSBmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2RlbGV0ZWQuc2F2ZWQnKTsKICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdyb2xsZWRCYWNrJyk7CiAgfTsKCiAgdmFyIHVwZGF0ZWRTdGF0ZSA9IGRpcnR5U3RhdGUoewogICAgZGlydHlUeXBlOiAndXBkYXRlZCcKICB9KTsKCiAgZnVuY3Rpb24gY3JlYXRlZFN0YXRlRGVsZXRlUmVjb3JkKGludGVybmFsTW9kZWwpIHsKICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdkZWxldGVkLnNhdmVkJyk7CiAgICBpbnRlcm5hbE1vZGVsLnNlbmQoJ2ludm9rZUxpZmVjeWNsZUNhbGxiYWNrcycpOwogIH0KCiAgY3JlYXRlZFN0YXRlLnVuY29tbWl0dGVkLmRlbGV0ZVJlY29yZCA9IGNyZWF0ZWRTdGF0ZURlbGV0ZVJlY29yZDsKICBjcmVhdGVkU3RhdGUuaW52YWxpZC5kZWxldGVSZWNvcmQgPSBjcmVhdGVkU3RhdGVEZWxldGVSZWNvcmQ7CgogIGNyZWF0ZWRTdGF0ZS51bmNvbW1pdHRlZC5yb2xsYmFjayA9IGZ1bmN0aW9uIChpbnRlcm5hbE1vZGVsKSB7CiAgICBEaXJ0eVN0YXRlLnVuY29tbWl0dGVkLnJvbGxiYWNrLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnZGVsZXRlZC5zYXZlZCcpOwogIH07CgogIGNyZWF0ZWRTdGF0ZS51bmNvbW1pdHRlZC5wdXNoZWREYXRhID0gZnVuY3Rpb24gKGludGVybmFsTW9kZWwpIHsKICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdsb2FkZWQudXBkYXRlZC51bmNvbW1pdHRlZCcpOwogICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ2RpZExvYWQnKTsKICB9OwoKICBjcmVhdGVkU3RhdGUudW5jb21taXR0ZWQucHJvcGVydHlXYXNSZXNldCA9IGZ1bmN0aW9uICgpIHt9OwoKICBmdW5jdGlvbiBhc3NlcnRBZ2FpbnN0VW5sb2FkUmVjb3JkKGludGVybmFsTW9kZWwpIHsKICB9CgogIHVwZGF0ZWRTdGF0ZS5pbnZhbGlkLmJlY2FtZVZhbGlkID0gZnVuY3Rpb24gKGludGVybmFsTW9kZWwpIHsKICAgIC8vIHdlJ3JlIGVhZ2VybHkgdHJhbnNpdGlvbiBpbnRvIHRoZSBsb2FkZWQuc2F2ZWQgc3RhdGUsIGV2ZW4gdGhvdWdoIHdlIGNvdWxkCiAgICAvLyBiZSBzdGlsbCBkaXJ0eTsgYnV0IHRoZSBzZXR1cCBob29rIG9mIHRoZSBsb2FkZWQuc2F2ZWQgc3RhdGUgY2hlY2tzIGZvcgogICAgLy8gZGlydHkgYXR0cmlidXRlcyBhbmQgdHJhbnNpdGlvbnMgaW50byB0aGUgY29ycmVzcG9uZGluZyBkaXJ0eSBzdGF0ZQogICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2xvYWRlZC5zYXZlZCcpOwogIH07CgogIHVwZGF0ZWRTdGF0ZS5pbkZsaWdodC51bmxvYWRSZWNvcmQgPSBhc3NlcnRBZ2FpbnN0VW5sb2FkUmVjb3JkOwoKICB1cGRhdGVkU3RhdGUudW5jb21taXR0ZWQuZGVsZXRlUmVjb3JkID0gZnVuY3Rpb24gKGludGVybmFsTW9kZWwpIHsKICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdkZWxldGVkLnVuY29tbWl0dGVkJyk7CiAgfTsKCiAgdXBkYXRlZFN0YXRlLmludmFsaWQucm9sbGVkQmFjayA9IGZ1bmN0aW9uIChpbnRlcm5hbE1vZGVsKSB7CiAgICBpbnRlcm5hbE1vZGVsLmNsZWFyRXJyb3JNZXNzYWdlcygpOwogICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2xvYWRlZC5zYXZlZCcpOwogICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ3JvbGxlZEJhY2snKTsKICB9OwoKICB2YXIgUm9vdFN0YXRlID0gewogICAgLy8gRkxBR1MKICAgIGlzRW1wdHk6IGZhbHNlLAogICAgaXNMb2FkaW5nOiBmYWxzZSwKICAgIGlzTG9hZGVkOiBmYWxzZSwKICAgIGlzRGlydHk6IGZhbHNlLAogICAgaXNTYXZpbmc6IGZhbHNlLAogICAgaXNEZWxldGVkOiBmYWxzZSwKICAgIGlzTmV3OiBmYWxzZSwKICAgIGlzVmFsaWQ6IHRydWUsCiAgICAvLyBERUZBVUxUIEVWRU5UUwogICAgLy8gVHJ5aW5nIHRvIHJvbGwgYmFjayBpZiB5b3UncmUgbm90IGluIHRoZSBkaXJ0eSBzdGF0ZQogICAgLy8gZG9lc24ndCBjaGFuZ2UgeW91ciBzdGF0ZS4gRm9yIGV4YW1wbGUsIGlmIHlvdSdyZSBpbiB0aGUKICAgIC8vIGluLWZsaWdodCBzdGF0ZSwgcm9sbGluZyBiYWNrIHRoZSByZWNvcmQgZG9lc24ndCBtb3ZlCiAgICAvLyB5b3Ugb3V0IG9mIHRoZSBpbi1mbGlnaHQgc3RhdGUuCiAgICByb2xsZWRCYWNrOiBmdW5jdGlvbiByb2xsZWRCYWNrKCkge30sCiAgICB1bmxvYWRSZWNvcmQ6IGZ1bmN0aW9uIHVubG9hZFJlY29yZChpbnRlcm5hbE1vZGVsKSB7fSwKICAgIHByb3BlcnR5V2FzUmVzZXQ6IGZ1bmN0aW9uIHByb3BlcnR5V2FzUmVzZXQoKSB7fSwKICAgIC8vIFNVQlNUQVRFUwogICAgLy8gQSByZWNvcmQgYmVnaW5zIGl0cyBsaWZlY3ljbGUgaW4gdGhlIGBlbXB0eWAgc3RhdGUuCiAgICAvLyBJZiBpdHMgZGF0YSB3aWxsIGNvbWUgZnJvbSB0aGUgYWRhcHRlciwgaXQgd2lsbAogICAgLy8gdHJhbnNpdGlvbiBpbnRvIHRoZSBgbG9hZGluZ2Agc3RhdGUuIE90aGVyd2lzZSwgaWYKICAgIC8vIHRoZSByZWNvcmQgaXMgYmVpbmcgY3JlYXRlZCBvbiB0aGUgY2xpZW50LCBpdCB3aWxsCiAgICAvLyB0cmFuc2l0aW9uIGludG8gdGhlIGBjcmVhdGVkYCBzdGF0ZS4KICAgIGVtcHR5OiB7CiAgICAgIGlzRW1wdHk6IHRydWUsCiAgICAgIC8vIEVWRU5UUwogICAgICBsb2FkaW5nRGF0YTogZnVuY3Rpb24gbG9hZGluZ0RhdGEoaW50ZXJuYWxNb2RlbCwgcHJvbWlzZSkgewogICAgICAgIGlmICghY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLl9wcm9taXNlUHJveHkgPSBwcm9taXNlOwogICAgICAgIH0KCiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2xvYWRpbmcnKTsKICAgICAgfSwKICAgICAgbG9hZGVkRGF0YTogZnVuY3Rpb24gbG9hZGVkRGF0YShpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2xvYWRlZC5jcmVhdGVkLnVuY29tbWl0dGVkJyk7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ3JlYWR5Jyk7CiAgICAgIH0sCiAgICAgIHB1c2hlZERhdGE6IGZ1bmN0aW9uIHB1c2hlZERhdGEoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdsb2FkZWQuc2F2ZWQnKTsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcignZGlkTG9hZCcpOwogICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdyZWFkeScpOwogICAgICB9CiAgICB9LAogICAgLy8gQSByZWNvcmQgZW50ZXJzIHRoaXMgc3RhdGUgd2hlbiB0aGUgc3RvcmUgYXNrcwogICAgLy8gdGhlIGFkYXB0ZXIgZm9yIGl0cyBkYXRhLiBJdCByZW1haW5zIGluIHRoaXMgc3RhdGUKICAgIC8vIHVudGlsIHRoZSBhZGFwdGVyIHByb3ZpZGVzIHRoZSByZXF1ZXN0ZWQgZGF0YS4KICAgIC8vCiAgICAvLyBVc3VhbGx5LCB0aGlzIHByb2Nlc3MgaXMgYXN5bmNocm9ub3VzLCB1c2luZyBhbgogICAgLy8gWEhSIHRvIHJldHJpZXZlIHRoZSBkYXRhLgogICAgbG9hZGluZzogewogICAgICAvLyBGTEFHUwogICAgICBpc0xvYWRpbmc6IHRydWUsCiAgICAgIGV4aXQ6IGZ1bmN0aW9uIGV4aXQoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwuX3Byb21pc2VQcm94eSA9IG51bGw7CiAgICAgIH0sCiAgICAgIGxvYWRpbmdEYXRhOiBmdW5jdGlvbiBsb2FkaW5nRGF0YSgpIHt9LAogICAgICAvLyBFVkVOVFMKICAgICAgcHVzaGVkRGF0YTogZnVuY3Rpb24gcHVzaGVkRGF0YShpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2xvYWRlZC5zYXZlZCcpOwogICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdkaWRMb2FkJyk7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ3JlYWR5Jyk7IC8vVE9ETyB0aGlzIHNlZW1zIG91dCBvZiBwbGFjZSBoZXJlCgogICAgICAgIGludGVybmFsTW9kZWwuZGlkQ2xlYW5FcnJvcigpOwogICAgICB9LAogICAgICBiZWNhbWVFcnJvcjogZnVuY3Rpb24gYmVjYW1lRXJyb3IoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdiZWNhbWVFcnJvcicsIGludGVybmFsTW9kZWwpOwogICAgICB9LAogICAgICBub3RGb3VuZDogZnVuY3Rpb24gbm90Rm91bmQoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdlbXB0eScpOwogICAgICB9CiAgICB9LAogICAgLy8gQSByZWNvcmQgZW50ZXJzIHRoaXMgc3RhdGUgd2hlbiBpdHMgZGF0YSBpcyBwb3B1bGF0ZWQuCiAgICAvLyBNb3N0IG9mIGEgcmVjb3JkJ3MgbGlmZWN5Y2xlIGlzIHNwZW50IGluc2lkZSBzdWJzdGF0ZXMKICAgIC8vIG9mIHRoZSBgbG9hZGVkYCBzdGF0ZS4KICAgIGxvYWRlZDogewogICAgICBpbml0aWFsU3RhdGU6ICdzYXZlZCcsCiAgICAgIC8vIEZMQUdTCiAgICAgIGlzTG9hZGVkOiB0cnVlLAogICAgICAvL1RPRE8oSWdvcikgUmVsb2FkaW5nIG5vdyB0cmlnZ2VycyBhIGxvYWRpbmdEYXRhIGV2ZW50LAogICAgICAvL2J1dCBpdCBzaG91bGQgYmUgb2s/CiAgICAgIGxvYWRpbmdEYXRhOiBmdW5jdGlvbiBsb2FkaW5nRGF0YSgpIHt9LAogICAgICAvLyBTVUJTVEFURVMKICAgICAgLy8gSWYgdGhlcmUgYXJlIG5vIGxvY2FsIGNoYW5nZXMgdG8gYSByZWNvcmQsIGl0IHJlbWFpbnMKICAgICAgLy8gaW4gdGhlIGBzYXZlZGAgc3RhdGUuCiAgICAgIHNhdmVkOiB7CiAgICAgICAgc2V0dXA6IGZ1bmN0aW9uIHNldHVwKGludGVybmFsTW9kZWwpIHsKICAgICAgICAgIGlmIChpbnRlcm5hbE1vZGVsLmhhc0NoYW5nZWRBdHRyaWJ1dGVzKCkpIHsKICAgICAgICAgICAgaW50ZXJuYWxNb2RlbC5hZGFwdGVyRGlkRGlydHkoKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8vIEVWRU5UUwogICAgICAgIGRpZFNldFByb3BlcnR5OiBfZGlkU2V0UHJvcGVydHksCiAgICAgICAgcHVzaGVkRGF0YTogZnVuY3Rpb24gcHVzaGVkRGF0YSgpIHt9LAogICAgICAgIGJlY29tZURpcnR5OiBmdW5jdGlvbiBiZWNvbWVEaXJ0eShpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygndXBkYXRlZC51bmNvbW1pdHRlZCcpOwogICAgICAgIH0sCiAgICAgICAgd2lsbENvbW1pdDogZnVuY3Rpb24gd2lsbENvbW1pdChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygndXBkYXRlZC5pbkZsaWdodCcpOwogICAgICAgIH0sCiAgICAgICAgcmVsb2FkUmVjb3JkOiBmdW5jdGlvbiByZWxvYWRSZWNvcmQoaW50ZXJuYWxNb2RlbCwgX3JlZjIpIHsKICAgICAgICAgIHZhciByZXNvbHZlID0gX3JlZjIucmVzb2x2ZSwKICAgICAgICAgICAgICBvcHRpb25zID0gX3JlZjIub3B0aW9uczsKCiAgICAgICAgICBpZiAoIWNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgICAgICAgICByZXNvbHZlKGludGVybmFsTW9kZWwuc3RvcmUuX3JlbG9hZFJlY29yZChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKSk7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICBkZWxldGVSZWNvcmQ6IGZ1bmN0aW9uIGRlbGV0ZVJlY29yZChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnZGVsZXRlZC51bmNvbW1pdHRlZCcpOwogICAgICAgIH0sCiAgICAgICAgdW5sb2FkUmVjb3JkOiBmdW5jdGlvbiB1bmxvYWRSZWNvcmQoaW50ZXJuYWxNb2RlbCkge30sCiAgICAgICAgZGlkQ29tbWl0OiBmdW5jdGlvbiBkaWRDb21taXQoKSB7fSwKICAgICAgICAvLyBsb2FkZWQuc2F2ZWQubm90Rm91bmQgd291bGQgYmUgdHJpZ2dlcmVkIGJ5IGEgZmFpbGVkCiAgICAgICAgLy8gYHJlbG9hZCgpYCBvbiBhbiB1bmNoYW5nZWQgcmVjb3JkCiAgICAgICAgbm90Rm91bmQ6IGZ1bmN0aW9uIG5vdEZvdW5kKCkge30KICAgICAgfSwKICAgICAgLy8gQSByZWNvcmQgaXMgaW4gdGhpcyBzdGF0ZSBhZnRlciBpdCBoYXMgYmVlbiBsb2NhbGx5CiAgICAgIC8vIGNyZWF0ZWQgYnV0IGJlZm9yZSB0aGUgYWRhcHRlciBoYXMgaW5kaWNhdGVkIHRoYXQKICAgICAgLy8gaXQgaGFzIGJlZW4gc2F2ZWQuCiAgICAgIGNyZWF0ZWQ6IGNyZWF0ZWRTdGF0ZSwKICAgICAgLy8gQSByZWNvcmQgaXMgaW4gdGhpcyBzdGF0ZSBpZiBpdCBoYXMgYWxyZWFkeSBiZWVuCiAgICAgIC8vIHNhdmVkIHRvIHRoZSBzZXJ2ZXIsIGJ1dCB0aGVyZSBhcmUgbmV3IGxvY2FsIGNoYW5nZXMKICAgICAgLy8gdGhhdCBoYXZlIG5vdCB5ZXQgYmVlbiBzYXZlZC4KICAgICAgdXBkYXRlZDogdXBkYXRlZFN0YXRlCiAgICB9LAogICAgLy8gQSByZWNvcmQgaXMgaW4gdGhpcyBzdGF0ZSBpZiBpdCB3YXMgZGVsZXRlZCBmcm9tIHRoZSBzdG9yZS4KICAgIGRlbGV0ZWQ6IHsKICAgICAgaW5pdGlhbFN0YXRlOiAndW5jb21taXR0ZWQnLAogICAgICBkaXJ0eVR5cGU6ICdkZWxldGVkJywKICAgICAgLy8gRkxBR1MKICAgICAgaXNEZWxldGVkOiB0cnVlLAogICAgICBpc0xvYWRlZDogdHJ1ZSwKICAgICAgaXNEaXJ0eTogdHJ1ZSwKICAgICAgLy8gVFJBTlNJVElPTlMKICAgICAgc2V0dXA6IGZ1bmN0aW9uIHNldHVwKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnVwZGF0ZVJlY29yZEFycmF5cygpOwogICAgICB9LAogICAgICAvLyBTVUJTVEFURVMKICAgICAgLy8gV2hlbiBhIHJlY29yZCBpcyBkZWxldGVkLCBpdCBlbnRlcnMgdGhlIGBzdGFydGAKICAgICAgLy8gc3RhdGUuIEl0IHdpbGwgZXhpdCB0aGlzIHN0YXRlIHdoZW4gdGhlIHJlY29yZAogICAgICAvLyBzdGFydHMgdG8gY29tbWl0LgogICAgICB1bmNvbW1pdHRlZDogewogICAgICAgIC8vIEVWRU5UUwogICAgICAgIHdpbGxDb21taXQ6IGZ1bmN0aW9uIHdpbGxDb21taXQoaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2luRmxpZ2h0Jyk7CiAgICAgICAgfSwKICAgICAgICByb2xsYmFjazogZnVuY3Rpb24gcm9sbGJhY2soaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC5yb2xsYmFja0F0dHJpYnV0ZXMoKTsKICAgICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdyZWFkeScpOwogICAgICAgIH0sCiAgICAgICAgcHVzaGVkRGF0YTogZnVuY3Rpb24gcHVzaGVkRGF0YSgpIHt9LAogICAgICAgIGJlY29tZURpcnR5OiBmdW5jdGlvbiBiZWNvbWVEaXJ0eSgpIHt9LAogICAgICAgIGRlbGV0ZVJlY29yZDogZnVuY3Rpb24gZGVsZXRlUmVjb3JkKCkge30sCiAgICAgICAgcm9sbGVkQmFjazogZnVuY3Rpb24gcm9sbGVkQmFjayhpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnbG9hZGVkLnNhdmVkJyk7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcigncmVhZHknKTsKICAgICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdyb2xsZWRCYWNrJyk7CiAgICAgICAgfQogICAgICB9LAogICAgICAvLyBBZnRlciBhIHJlY29yZCBzdGFydHMgY29tbWl0dGluZywgYnV0CiAgICAgIC8vIGJlZm9yZSB0aGUgYWRhcHRlciBpbmRpY2F0ZXMgdGhhdCB0aGUgZGVsZXRpb24KICAgICAgLy8gaGFzIHNhdmVkIHRvIHRoZSBzZXJ2ZXIsIGEgcmVjb3JkIGlzIGluIHRoZQogICAgICAvLyBgaW5GbGlnaHRgIHN1YnN0YXRlIG9mIGBkZWxldGVkYC4KICAgICAgaW5GbGlnaHQ6IHsKICAgICAgICAvLyBGTEFHUwogICAgICAgIGlzU2F2aW5nOiB0cnVlLAogICAgICAgIC8vIEVWRU5UUwogICAgICAgIHVubG9hZFJlY29yZDogYXNzZXJ0QWdhaW5zdFVubG9hZFJlY29yZCwKICAgICAgICAvLyBUT0RPOiBNb3JlIHJvYnVzdCBzZW1hbnRpY3MgYXJvdW5kIHNhdmUtd2hpbGUtaW4tZmxpZ2h0CiAgICAgICAgd2lsbENvbW1pdDogZnVuY3Rpb24gd2lsbENvbW1pdCgpIHt9LAogICAgICAgIGRpZENvbW1pdDogZnVuY3Rpb24gZGlkQ29tbWl0KGludGVybmFsTW9kZWwpIHsKICAgICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdzYXZlZCcpOwogICAgICAgICAgaW50ZXJuYWxNb2RlbC5zZW5kKCdpbnZva2VMaWZlY3ljbGVDYWxsYmFja3MnKTsKICAgICAgICB9LAogICAgICAgIGJlY2FtZUVycm9yOiBmdW5jdGlvbiBiZWNhbWVFcnJvcihpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygndW5jb21taXR0ZWQnKTsKICAgICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdiZWNhbWVFcnJvcicsIGludGVybmFsTW9kZWwpOwogICAgICAgIH0sCiAgICAgICAgYmVjYW1lSW52YWxpZDogZnVuY3Rpb24gYmVjYW1lSW52YWxpZChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnaW52YWxpZCcpOwogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ2JlY2FtZUludmFsaWQnLCBpbnRlcm5hbE1vZGVsKTsKICAgICAgICB9CiAgICAgIH0sCiAgICAgIC8vIE9uY2UgdGhlIGFkYXB0ZXIgaW5kaWNhdGVzIHRoYXQgdGhlIGRlbGV0aW9uIGhhcwogICAgICAvLyBiZWVuIHNhdmVkLCB0aGUgcmVjb3JkIGVudGVycyB0aGUgYHNhdmVkYCBzdWJzdGF0ZQogICAgICAvLyBvZiBgZGVsZXRlZGAuCiAgICAgIHNhdmVkOiB7CiAgICAgICAgLy8gRkxBR1MKICAgICAgICBpc0RpcnR5OiBmYWxzZSwKICAgICAgICBzZXR1cDogZnVuY3Rpb24gc2V0dXAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC5yZW1vdmVGcm9tSW52ZXJzZVJlbGF0aW9uc2hpcHMoKTsKICAgICAgICB9LAogICAgICAgIGludm9rZUxpZmVjeWNsZUNhbGxiYWNrczogZnVuY3Rpb24gaW52b2tlTGlmZWN5Y2xlQ2FsbGJhY2tzKGludGVybmFsTW9kZWwpIHsKICAgICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdkaWREZWxldGUnLCBpbnRlcm5hbE1vZGVsKTsKICAgICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdkaWRDb21taXQnLCBpbnRlcm5hbE1vZGVsKTsKICAgICAgICB9LAogICAgICAgIHdpbGxDb21taXQ6IGZ1bmN0aW9uIHdpbGxDb21taXQoKSB7fSwKICAgICAgICBkaWRDb21taXQ6IGZ1bmN0aW9uIGRpZENvbW1pdCgpIHt9LAogICAgICAgIHB1c2hlZERhdGE6IGZ1bmN0aW9uIHB1c2hlZERhdGEoKSB7fQogICAgICB9LAogICAgICBpbnZhbGlkOiB7CiAgICAgICAgaXNWYWxpZDogZmFsc2UsCiAgICAgICAgZGlkU2V0UHJvcGVydHk6IGZ1bmN0aW9uIGRpZFNldFByb3BlcnR5KGludGVybmFsTW9kZWwsIGNvbnRleHQpIHsKICAgICAgICAgIGludGVybmFsTW9kZWwucmVtb3ZlRXJyb3JNZXNzYWdlRnJvbUF0dHJpYnV0ZShjb250ZXh0Lm5hbWUpOwoKICAgICAgICAgIF9kaWRTZXRQcm9wZXJ0eShpbnRlcm5hbE1vZGVsLCBjb250ZXh0KTsKCiAgICAgICAgICBpZiAoIWludGVybmFsTW9kZWwuaGFzRXJyb3JzKCkpIHsKICAgICAgICAgICAgdGhpcy5iZWNhbWVWYWxpZChpbnRlcm5hbE1vZGVsKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGJlY2FtZUludmFsaWQ6IGZ1bmN0aW9uIGJlY2FtZUludmFsaWQoKSB7fSwKICAgICAgICBiZWNvbWVEaXJ0eTogZnVuY3Rpb24gYmVjb21lRGlydHkoKSB7fSwKICAgICAgICBkZWxldGVSZWNvcmQ6IGZ1bmN0aW9uIGRlbGV0ZVJlY29yZCgpIHt9LAogICAgICAgIHdpbGxDb21taXQ6IGZ1bmN0aW9uIHdpbGxDb21taXQoKSB7fSwKICAgICAgICByb2xsZWRCYWNrOiBmdW5jdGlvbiByb2xsZWRCYWNrKGludGVybmFsTW9kZWwpIHsKICAgICAgICAgIGludGVybmFsTW9kZWwuY2xlYXJFcnJvck1lc3NhZ2VzKCk7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnbG9hZGVkLnNhdmVkJyk7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcigncmVhZHknKTsKICAgICAgICB9LAogICAgICAgIGJlY2FtZVZhbGlkOiBmdW5jdGlvbiBiZWNhbWVWYWxpZChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygndW5jb21taXR0ZWQnKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0sCiAgICBpbnZva2VMaWZlY3ljbGVDYWxsYmFja3M6IGZ1bmN0aW9uIGludm9rZUxpZmVjeWNsZUNhbGxiYWNrcyhpbnRlcm5hbE1vZGVsLCBkaXJ0eVR5cGUpIHsKICAgICAgaWYgKGRpcnR5VHlwZSA9PT0gJ2NyZWF0ZWQnKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ2RpZENyZWF0ZScsIGludGVybmFsTW9kZWwpOwogICAgICB9IGVsc2UgewogICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdkaWRVcGRhdGUnLCBpbnRlcm5hbE1vZGVsKTsKICAgICAgfQoKICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ2RpZENvbW1pdCcsIGludGVybmFsTW9kZWwpOwogICAgfQogIH07CgogIGZ1bmN0aW9uIHdpcmVTdGF0ZShvYmplY3QsIHBhcmVudCwgbmFtZSkgewogICAgLy8gVE9ETzogVXNlIE9iamVjdC5jcmVhdGUgYW5kIGNvcHkgaW5zdGVhZAogICAgb2JqZWN0ID0gbWl4aW4ocGFyZW50ID8gT2JqZWN0LmNyZWF0ZShwYXJlbnQpIDoge30sIG9iamVjdCk7CiAgICBvYmplY3QucGFyZW50U3RhdGUgPSBwYXJlbnQ7CiAgICBvYmplY3Quc3RhdGVOYW1lID0gbmFtZTsKCiAgICBmb3IgKHZhciBwcm9wIGluIG9iamVjdCkgewogICAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3ApIHx8IHByb3AgPT09ICdwYXJlbnRTdGF0ZScgfHwgcHJvcCA9PT0gJ3N0YXRlTmFtZScpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQoKICAgICAgaWYgKHR5cGVvZiBvYmplY3RbcHJvcF0gPT09ICdvYmplY3QnKSB7CiAgICAgICAgb2JqZWN0W3Byb3BdID0gd2lyZVN0YXRlKG9iamVjdFtwcm9wXSwgb2JqZWN0LCBuYW1lICsgJy4nICsgcHJvcCk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gb2JqZWN0OwogIH0KCiAgdmFyIFJvb3RTdGF0ZSQxID0gd2lyZVN0YXRlKFJvb3RTdGF0ZSwgbnVsbCwgJ3Jvb3QnKTsKCiAgLyoKICAgKiBSZXR1cm5zIHRoZSBSZWNvcmREYXRhIGluc3RhbmNlIGFzc29jaWF0ZWQgd2l0aCBhIGdpdmVuCiAgICogTW9kZWwgb3IgSW50ZXJuYWxNb2RlbC4KICAgKgogICAqIEludGVudGlvbmFsbHkgImxvb3NlIiB0byBhbGxvdyBhbnl0aGluZyB3aXRoIGFuIF9pbnRlcm5hbE1vZGVsCiAgICogcHJvcGVydHkgdW50aWwgSW50ZXJuYWxNb2RlbCBpcyBlbGltaW5hdGVkLgogICAqCiAgICogSW50ZW50aW9uYWxseSBub3QgdHlwZWQgdG8gYEludGVybmFsTW9kZWxgIGR1ZSB0byBjaXJjdWxhciBkZXBlbmRlbmN5CiAgICogIHdoaWNoIHRoYXQgY3JlYXRlcy4KICAgKgogICAqIE92ZXJ0aW1lLCB0aGlzIHNob3VsZCBzaGlmdCB0byBhICJ3ZWFrbWFwIiBiYXNlZCBsb29rdXAgaW4gdGhlCiAgICogICJFbWJlci5nZXRPd25lcihvYmopIiBzdHlsZS4KICAgKi8KICBmdW5jdGlvbiByZWNvcmREYXRhRm9yKGluc3RhbmNlKSB7CiAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGluc3RhbmNlLl9pbnRlcm5hbE1vZGVsIHx8IGluc3RhbmNlLmludGVybmFsTW9kZWwgfHwgaW5zdGFuY2U7CiAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5fcmVjb3JkRGF0YSB8fCBudWxsOwogIH0KCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoInZhbHVlIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0KCiAgZnVuY3Rpb24gX2NyZWF0ZUNsYXNzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH0KCiAgZnVuY3Rpb24gcmVsYXRpb25zaGlwc0ZvcihpbnN0YW5jZSkgewogICAgdmFyIHJlY29yZERhdGEgPSByZWNvcmREYXRhRm9yKGluc3RhbmNlKSB8fCBpbnN0YW5jZTsKICAgIHJldHVybiByZWNvcmREYXRhLl9yZWxhdGlvbnNoaXBzOwogIH0KCiAgZnVuY3Rpb24gcmVsYXRpb25zaGlwU3RhdGVGb3IoaW5zdGFuY2UsIHByb3BlcnR5TmFtZSkgewogICAgcmV0dXJuIHJlbGF0aW9uc2hpcHNGb3IoaW5zdGFuY2UpLmdldChwcm9wZXJ0eU5hbWUpOwogIH0KICAvKioKICAgIEBjbGFzcyBTbmFwc2hvdAogICAgQHByaXZhdGUKICAgIEBjb25zdHJ1Y3RvcgogICAgQHBhcmFtIHtNb2RlbH0gaW50ZXJuYWxNb2RlbCBUaGUgbW9kZWwgdG8gY3JlYXRlIGEgc25hcHNob3QgZnJvbQogICovCgoKICB2YXIgU25hcHNob3QgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBTbmFwc2hvdChvcHRpb25zLCBpZGVudGlmaWVyLCBzdG9yZSkgewogICAgICB0aGlzLl9fYXR0cmlidXRlcyA9IG51bGw7CiAgICAgIHRoaXMuX2JlbG9uZ3NUb1JlbGF0aW9uc2hpcHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9iZWxvbmdzVG9JZHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9oYXNNYW55UmVsYXRpb25zaGlwcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHRoaXMuX2hhc01hbnlJZHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwoKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSB0aGlzLl9pbnRlcm5hbE1vZGVsID0gc3RvcmUuX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShpZGVudGlmaWVyKTsKCiAgICAgIHRoaXMuX3N0b3JlID0gc3RvcmU7CiAgICAgIHRoaXMubW9kZWxOYW1lID0gaWRlbnRpZmllci50eXBlOwoKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgIHRoaXMuaWRlbnRpZmllciA9IGlkZW50aWZpZXI7CiAgICAgIH0KICAgICAgLyoKICAgICAgICBJZiB0aGUgaW50ZXJuYWxNb2RlbCBkb2VzIG5vdCB5ZXQgaGF2ZSBhIHJlY29yZCwgdGhlbiB3ZSBhcmUKICAgICAgICBsaWtlbHkgYSBzbmFwc2hvdCBiZWluZyBwcm92aWRlZCB0byBhIGZpbmQgcmVxdWVzdCwgc28gd2UKICAgICAgICBwb3B1bGF0ZSBfX2F0dHJpYnV0ZXMgbGF6aWx5LiBFbHNlLCB0byBwcmVzZXJ2ZSB0aGUgIm1vbWVudAogICAgICAgIGluIHRpbWUiIGluIHdoaWNoIGEgc25hcHNob3QgaXMgY3JlYXRlZCwgd2UgZ3JlZWRpbHkgZ3JhYgogICAgICAgIHRoZSB2YWx1ZXMuCiAgICAgICAqLwoKCiAgICAgIGlmIChpbnRlcm5hbE1vZGVsLmhhc1JlY29yZCkgewogICAgICAgIHRoaXMuX2F0dHJpYnV0ZXM7CiAgICAgIH0KICAgICAgLyoqTwogICAgICAgVGhlIGlkIG9mIHRoZSBzbmFwc2hvdCdzIHVuZGVybHlpbmcgcmVjb3JkCiAgICAgICAgRXhhbXBsZQogICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgIC8vIHN0b3JlLnB1c2goJ3Bvc3QnLCB7IGlkOiAxLCBhdXRob3I6ICdUb21zdGVyJywgdGl0bGU6ICdFbWJlci5qcyByb2NrcycgfSk7CiAgICAgICBwb3N0U25hcHNob3QuaWQ7IC8vID0+ICcxJwogICAgICAgYGBgCiAgICAgICAgQHByb3BlcnR5IGlkCiAgICAgICBAdHlwZSB7U3RyaW5nfQogICAgICAgKi8KCgogICAgICB0aGlzLmlkID0gaWRlbnRpZmllci5pZDsKICAgICAgLyoqCiAgICAgICBBIGhhc2ggb2YgYWRhcHRlciBvcHRpb25zCiAgICAgICBAcHJvcGVydHkgYWRhcHRlck9wdGlvbnMKICAgICAgIEB0eXBlIHtPYmplY3R9CiAgICAgICAqLwoKICAgICAgdGhpcy5hZGFwdGVyT3B0aW9ucyA9IG9wdGlvbnMuYWRhcHRlck9wdGlvbnM7CiAgICAgIHRoaXMuaW5jbHVkZSA9IG9wdGlvbnMuaW5jbHVkZTsKICAgICAgLyoqCiAgICAgICBUaGUgbmFtZSBvZiB0aGUgdHlwZSBvZiB0aGUgdW5kZXJseWluZyByZWNvcmQgZm9yIHRoaXMgc25hcHNob3QsIGFzIGEgc3RyaW5nLgogICAgICAgIEBwcm9wZXJ0eSBtb2RlbE5hbWUKICAgICAgIEB0eXBlIHtTdHJpbmd9CiAgICAgICAqLwoKICAgICAgdGhpcy5tb2RlbE5hbWUgPSBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZTsKCiAgICAgIGlmIChpbnRlcm5hbE1vZGVsLmhhc1JlY29yZCkgewogICAgICAgIHRoaXMuX2NoYW5nZWRBdHRyaWJ1dGVzID0gcmVjb3JkRGF0YUZvcihpbnRlcm5hbE1vZGVsKS5jaGFuZ2VkQXR0cmlidXRlcygpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICBUaGUgdW5kZXJseWluZyByZWNvcmQgZm9yIHRoaXMgc25hcHNob3QuIENhbiBiZSB1c2VkIHRvIGFjY2VzcyBtZXRob2RzIGFuZAogICAgIHByb3BlcnRpZXMgZGVmaW5lZCBvbiB0aGUgcmVjb3JkLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQganNvbiA9IHNuYXBzaG90LnJlY29yZC50b0pTT04oKTsKICAgICBgYGAKICAgICAgQHByb3BlcnR5IHJlY29yZAogICAgIEB0eXBlIHtNb2RlbH0KICAgICAqLwoKCiAgICB2YXIgX3Byb3RvID0gU25hcHNob3QucHJvdG90eXBlOwoKICAgIC8qKgogICAgIFJldHVybnMgdGhlIHZhbHVlIG9mIGFuIGF0dHJpYnV0ZS4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgLy8gc3RvcmUucHVzaCgncG9zdCcsIHsgaWQ6IDEsIGF1dGhvcjogJ1RvbXN0ZXInLCB0aXRsZTogJ0VtYmVyLmpzIHJvY2tzJyB9KTsKICAgICBwb3N0U25hcHNob3QuYXR0cignYXV0aG9yJyk7IC8vID0+ICdUb21zdGVyJwogICAgIHBvc3RTbmFwc2hvdC5hdHRyKCd0aXRsZScpOyAvLyA9PiAnRW1iZXIuanMgcm9ja3MnCiAgICAgYGBgCiAgICAgIE5vdGU6IFZhbHVlcyBhcmUgbG9hZGVkIGVhZ2VybHkgYW5kIGNhY2hlZCB3aGVuIHRoZSBzbmFwc2hvdCBpcyBjcmVhdGVkLgogICAgICBAbWV0aG9kIGF0dHIKICAgICBAcGFyYW0ge1N0cmluZ30ga2V5TmFtZQogICAgIEByZXR1cm4ge09iamVjdH0gVGhlIGF0dHJpYnV0ZSB2YWx1ZSBvciB1bmRlZmluZWQKICAgICAqLwogICAgX3Byb3RvLmF0dHIgPSBmdW5jdGlvbiBhdHRyKGtleU5hbWUpIHsKICAgICAgaWYgKGtleU5hbWUgaW4gdGhpcy5fYXR0cmlidXRlcykgewogICAgICAgIHJldHVybiB0aGlzLl9hdHRyaWJ1dGVzW2tleU5hbWVdOwogICAgICB9CgogICAgICB0aHJvdyBuZXcgRW1iZXIuRXJyb3IoIk1vZGVsICciICsgRW1iZXIuaW5zcGVjdCh0aGlzLnJlY29yZCkgKyAiJyBoYXMgbm8gYXR0cmlidXRlIG5hbWVkICciICsga2V5TmFtZSArICInIGRlZmluZWQuIik7CiAgICB9CiAgICAvKioKICAgICBSZXR1cm5zIGFsbCBhdHRyaWJ1dGVzIGFuZCB0aGVpciBjb3JyZXNwb25kaW5nIHZhbHVlcy4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgLy8gc3RvcmUucHVzaCgncG9zdCcsIHsgaWQ6IDEsIGF1dGhvcjogJ1RvbXN0ZXInLCB0aXRsZTogJ0VtYmVyLmpzIHJvY2tzJyB9KTsKICAgICBwb3N0U25hcHNob3QuYXR0cmlidXRlcygpOyAvLyA9PiB7IGF1dGhvcjogJ1RvbXN0ZXInLCB0aXRsZTogJ0VtYmVyLmpzIHJvY2tzJyB9CiAgICAgYGBgCiAgICAgIEBtZXRob2QgYXR0cmlidXRlcwogICAgIEByZXR1cm4ge09iamVjdH0gQWxsIGF0dHJpYnV0ZXMgb2YgdGhlIGN1cnJlbnQgc25hcHNob3QKICAgICAqLwogICAgOwoKICAgIF9wcm90by5hdHRyaWJ1dGVzID0gZnVuY3Rpb24gYXR0cmlidXRlcygpIHsKICAgICAgcmV0dXJuIEVtYmVyLmFzc2lnbih7fSwgdGhpcy5fYXR0cmlidXRlcyk7CiAgICB9CiAgICAvKioKICAgICBSZXR1cm5zIGFsbCBjaGFuZ2VkIGF0dHJpYnV0ZXMgYW5kIHRoZWlyIG9sZCBhbmQgbmV3IHZhbHVlcy4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgLy8gc3RvcmUucHVzaCgncG9zdCcsIHsgaWQ6IDEsIGF1dGhvcjogJ1RvbXN0ZXInLCB0aXRsZTogJ0VtYmVyLmpzIHJvY2tzJyB9KTsKICAgICBwb3N0TW9kZWwuc2V0KCd0aXRsZScsICdFbWJlci5qcyByb2NrcyEnKTsKICAgICBwb3N0U25hcHNob3QuY2hhbmdlZEF0dHJpYnV0ZXMoKTsgLy8gPT4geyB0aXRsZTogWydFbWJlci5qcyByb2NrcycsICdFbWJlci5qcyByb2NrcyEnXSB9CiAgICAgYGBgCiAgICAgIEBtZXRob2QgY2hhbmdlZEF0dHJpYnV0ZXMKICAgICBAcmV0dXJuIHtPYmplY3R9IEFsbCBjaGFuZ2VkIGF0dHJpYnV0ZXMgb2YgdGhlIGN1cnJlbnQgc25hcHNob3QKICAgICAqLwogICAgOwoKICAgIF9wcm90by5jaGFuZ2VkQXR0cmlidXRlcyA9IGZ1bmN0aW9uIGNoYW5nZWRBdHRyaWJ1dGVzKCkgewogICAgICB2YXIgY2hhbmdlZEF0dHJpYnV0ZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB2YXIgY2hhbmdlZEF0dHJpYnV0ZUtleXMgPSBPYmplY3Qua2V5cyh0aGlzLl9jaGFuZ2VkQXR0cmlidXRlcyk7CgogICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gY2hhbmdlZEF0dHJpYnV0ZUtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIga2V5ID0gY2hhbmdlZEF0dHJpYnV0ZUtleXNbaV07CiAgICAgICAgY2hhbmdlZEF0dHJpYnV0ZXNba2V5XSA9IHRoaXMuX2NoYW5nZWRBdHRyaWJ1dGVzW2tleV0uc2xpY2UoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGNoYW5nZWRBdHRyaWJ1dGVzOwogICAgfQogICAgLyoqCiAgICAgUmV0dXJucyB0aGUgY3VycmVudCB2YWx1ZSBvZiBhIGJlbG9uZ3NUbyByZWxhdGlvbnNoaXAuCiAgICAgIGBiZWxvbmdzVG9gIHRha2VzIGFuIG9wdGlvbmFsIGhhc2ggb2Ygb3B0aW9ucyBhcyBhIHNlY29uZCBwYXJhbWV0ZXIsCiAgICAgY3VycmVudGx5IHN1cHBvcnRlZCBvcHRpb25zIGFyZToKICAgICAgLSBgaWRgOiBzZXQgdG8gYHRydWVgIGlmIHlvdSBvbmx5IHdhbnQgdGhlIElEIG9mIHRoZSByZWxhdGVkIHJlY29yZCB0byBiZQogICAgIHJldHVybmVkLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAvLyBzdG9yZS5wdXNoKCdwb3N0JywgeyBpZDogMSwgdGl0bGU6ICdIZWxsbyBXb3JsZCcgfSk7CiAgICAgLy8gc3RvcmUuY3JlYXRlUmVjb3JkKCdjb21tZW50JywgeyBib2R5OiAnTG9yZW0gaXBzdW0nLCBwb3N0OiBwb3N0IH0pOwogICAgIGNvbW1lbnRTbmFwc2hvdC5iZWxvbmdzVG8oJ3Bvc3QnKTsgLy8gPT4gU25hcHNob3QKICAgICBjb21tZW50U25hcHNob3QuYmVsb25nc1RvKCdwb3N0JywgeyBpZDogdHJ1ZSB9KTsgLy8gPT4gJzEnCiAgICAgIC8vIHN0b3JlLnB1c2goJ2NvbW1lbnQnLCB7IGlkOiAxLCBib2R5OiAnTG9yZW0gaXBzdW0nIH0pOwogICAgIGNvbW1lbnRTbmFwc2hvdC5iZWxvbmdzVG8oJ3Bvc3QnKTsgLy8gPT4gdW5kZWZpbmVkCiAgICAgYGBgCiAgICAgIENhbGxpbmcgYGJlbG9uZ3NUb2Agd2lsbCByZXR1cm4gYSBuZXcgU25hcHNob3QgYXMgbG9uZyBhcyB0aGVyZSdzIGFueSBrbm93bgogICAgIGRhdGEgZm9yIHRoZSByZWxhdGlvbnNoaXAgYXZhaWxhYmxlLCBzdWNoIGFzIGFuIElELiBJZiB0aGUgcmVsYXRpb25zaGlwIGlzCiAgICAga25vd24gYnV0IHVuc2V0LCBgYmVsb25nc1RvYCB3aWxsIHJldHVybiBgbnVsbGAuIElmIHRoZSBjb250ZW50cyBvZiB0aGUKICAgICByZWxhdGlvbnNoaXAgaXMgdW5rbm93biBgYmVsb25nc1RvYCB3aWxsIHJldHVybiBgdW5kZWZpbmVkYC4KICAgICAgTm90ZTogUmVsYXRpb25zaGlwcyBhcmUgbG9hZGVkIGxhemlseSBhbmQgY2FjaGVkIHVwb24gZmlyc3QgYWNjZXNzLgogICAgICBAbWV0aG9kIGJlbG9uZ3NUbwogICAgIEBwYXJhbSB7U3RyaW5nfSBrZXlOYW1lCiAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXQogICAgIEByZXR1cm4geyhTbmFwc2hvdHxTdHJpbmd8bnVsbHx1bmRlZmluZWQpfSBBIHNuYXBzaG90IG9yIElEIG9mIGEga25vd24KICAgICByZWxhdGlvbnNoaXAgb3IgbnVsbCBpZiB0aGUgcmVsYXRpb25zaGlwIGlzIGtub3duIGJ1dCB1bnNldC4gdW5kZWZpbmVkCiAgICAgd2lsbCBiZSByZXR1cm5lZCBpZiB0aGUgY29udGVudHMgb2YgdGhlIHJlbGF0aW9uc2hpcCBpcyB1bmtub3duLgogICAgICovCiAgICA7CgogICAgX3Byb3RvLmJlbG9uZ3NUbyA9IGZ1bmN0aW9uIGJlbG9uZ3NUbyhrZXlOYW1lLCBvcHRpb25zKSB7CiAgICAgIHZhciBpZCA9IG9wdGlvbnMgJiYgb3B0aW9ucy5pZDsKICAgICAgdmFyIHJlbGF0aW9uc2hpcDsKICAgICAgdmFyIGludmVyc2VJbnRlcm5hbE1vZGVsOwogICAgICB2YXIgcmVzdWx0OwogICAgICB2YXIgc3RvcmUgPSB0aGlzLl9pbnRlcm5hbE1vZGVsLnN0b3JlOwoKICAgICAgaWYgKGlkICYmIGtleU5hbWUgaW4gdGhpcy5fYmVsb25nc1RvSWRzKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2JlbG9uZ3NUb0lkc1trZXlOYW1lXTsKICAgICAgfQoKICAgICAgaWYgKCFpZCAmJiBrZXlOYW1lIGluIHRoaXMuX2JlbG9uZ3NUb1JlbGF0aW9uc2hpcHMpIHsKICAgICAgICByZXR1cm4gdGhpcy5fYmVsb25nc1RvUmVsYXRpb25zaGlwc1trZXlOYW1lXTsKICAgICAgfQoKICAgICAgdmFyIHJlbGF0aW9uc2hpcE1ldGEgPSBzdG9yZS5fcmVsYXRpb25zaGlwTWV0YUZvcih0aGlzLm1vZGVsTmFtZSwgbnVsbCwga2V5TmFtZSk7CgogICAgICBpZiAoIShyZWxhdGlvbnNoaXBNZXRhICYmIHJlbGF0aW9uc2hpcE1ldGEua2luZCA9PT0gJ2JlbG9uZ3NUbycpKSB7CiAgICAgICAgdGhyb3cgbmV3IEVtYmVyLkVycm9yKCJNb2RlbCAnIiArIEVtYmVyLmluc3BlY3QodGhpcy5yZWNvcmQpICsgIicgaGFzIG5vIGJlbG9uZ3NUbyByZWxhdGlvbnNoaXAgbmFtZWQgJyIgKyBrZXlOYW1lICsgIicgZGVmaW5lZC4iKTsKICAgICAgfQoKICAgICAgcmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwU3RhdGVGb3IodGhpcywga2V5TmFtZSk7CiAgICAgIHZhciB2YWx1ZSA9IHJlbGF0aW9uc2hpcC5nZXREYXRhKCk7CiAgICAgIHZhciBkYXRhID0gdmFsdWUgJiYgdmFsdWUuZGF0YTsKICAgICAgaW52ZXJzZUludGVybmFsTW9kZWwgPSBkYXRhICYmIHN0b3JlLl9pbnRlcm5hbE1vZGVsRm9yUmVzb3VyY2UoZGF0YSk7CgogICAgICBpZiAodmFsdWUgJiYgdmFsdWUuZGF0YSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgaWYgKGludmVyc2VJbnRlcm5hbE1vZGVsICYmICFpbnZlcnNlSW50ZXJuYWxNb2RlbC5pc0RlbGV0ZWQoKSkgewogICAgICAgICAgaWYgKGlkKSB7CiAgICAgICAgICAgIHJlc3VsdCA9IEVtYmVyLmdldChpbnZlcnNlSW50ZXJuYWxNb2RlbCwgJ2lkJyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXN1bHQgPSBpbnZlcnNlSW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdCgpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQgPSBudWxsOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKGlkKSB7CiAgICAgICAgdGhpcy5fYmVsb25nc1RvSWRzW2tleU5hbWVdID0gcmVzdWx0OwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuX2JlbG9uZ3NUb1JlbGF0aW9uc2hpcHNba2V5TmFtZV0gPSByZXN1bHQ7CiAgICAgIH0KCiAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9CiAgICAvKioKICAgICBSZXR1cm5zIHRoZSBjdXJyZW50IHZhbHVlIG9mIGEgaGFzTWFueSByZWxhdGlvbnNoaXAuCiAgICAgIGBoYXNNYW55YCB0YWtlcyBhbiBvcHRpb25hbCBoYXNoIG9mIG9wdGlvbnMgYXMgYSBzZWNvbmQgcGFyYW1ldGVyLAogICAgIGN1cnJlbnRseSBzdXBwb3J0ZWQgb3B0aW9ucyBhcmU6CiAgICAgIC0gYGlkc2A6IHNldCB0byBgdHJ1ZWAgaWYgeW91IG9ubHkgd2FudCB0aGUgSURzIG9mIHRoZSByZWxhdGVkIHJlY29yZHMgdG8gYmUKICAgICByZXR1cm5lZC4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgLy8gc3RvcmUucHVzaCgncG9zdCcsIHsgaWQ6IDEsIHRpdGxlOiAnSGVsbG8gV29ybGQnLCBjb21tZW50czogWzIsIDNdIH0pOwogICAgIHBvc3RTbmFwc2hvdC5oYXNNYW55KCdjb21tZW50cycpOyAvLyA9PiBbU25hcHNob3QsIFNuYXBzaG90XQogICAgIHBvc3RTbmFwc2hvdC5oYXNNYW55KCdjb21tZW50cycsIHsgaWRzOiB0cnVlIH0pOyAvLyA9PiBbJzInLCAnMyddCiAgICAgIC8vIHN0b3JlLnB1c2goJ3Bvc3QnLCB7IGlkOiAxLCB0aXRsZTogJ0hlbGxvIFdvcmxkJyB9KTsKICAgICBwb3N0U25hcHNob3QuaGFzTWFueSgnY29tbWVudHMnKTsgLy8gPT4gdW5kZWZpbmVkCiAgICAgYGBgCiAgICAgIE5vdGU6IFJlbGF0aW9uc2hpcHMgYXJlIGxvYWRlZCBsYXppbHkgYW5kIGNhY2hlZCB1cG9uIGZpcnN0IGFjY2Vzcy4KICAgICAgQG1ldGhvZCBoYXNNYW55CiAgICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUKICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdCiAgICAgQHJldHVybiB7KEFycmF5fHVuZGVmaW5lZCl9IEFuIGFycmF5IG9mIHNuYXBzaG90cyBvciBJRHMgb2YgYSBrbm93bgogICAgIHJlbGF0aW9uc2hpcCBvciBhbiBlbXB0eSBhcnJheSBpZiB0aGUgcmVsYXRpb25zaGlwIGlzIGtub3duIGJ1dCB1bnNldC4KICAgICB1bmRlZmluZWQgd2lsbCBiZSByZXR1cm5lZCBpZiB0aGUgY29udGVudHMgb2YgdGhlIHJlbGF0aW9uc2hpcCBpcyB1bmtub3duLgogICAgICovCiAgICA7CgogICAgX3Byb3RvLmhhc01hbnkgPSBmdW5jdGlvbiBoYXNNYW55KGtleU5hbWUsIG9wdGlvbnMpIHsKICAgICAgdmFyIGlkcyA9IG9wdGlvbnMgJiYgb3B0aW9ucy5pZHM7CiAgICAgIHZhciByZWxhdGlvbnNoaXA7CiAgICAgIHZhciByZXN1bHRzOwoKICAgICAgaWYgKGlkcyAmJiBrZXlOYW1lIGluIHRoaXMuX2hhc01hbnlJZHMpIHsKICAgICAgICByZXR1cm4gdGhpcy5faGFzTWFueUlkc1trZXlOYW1lXTsKICAgICAgfQoKICAgICAgaWYgKCFpZHMgJiYga2V5TmFtZSBpbiB0aGlzLl9oYXNNYW55UmVsYXRpb25zaGlwcykgewogICAgICAgIHJldHVybiB0aGlzLl9oYXNNYW55UmVsYXRpb25zaGlwc1trZXlOYW1lXTsKICAgICAgfQoKICAgICAgdmFyIHN0b3JlID0gdGhpcy5faW50ZXJuYWxNb2RlbC5zdG9yZTsKCiAgICAgIHZhciByZWxhdGlvbnNoaXBNZXRhID0gc3RvcmUuX3JlbGF0aW9uc2hpcE1ldGFGb3IodGhpcy5tb2RlbE5hbWUsIG51bGwsIGtleU5hbWUpOwoKICAgICAgaWYgKCEocmVsYXRpb25zaGlwTWV0YSAmJiByZWxhdGlvbnNoaXBNZXRhLmtpbmQgPT09ICdoYXNNYW55JykpIHsKICAgICAgICB0aHJvdyBuZXcgRW1iZXIuRXJyb3IoIk1vZGVsICciICsgRW1iZXIuaW5zcGVjdCh0aGlzLnJlY29yZCkgKyAiJyBoYXMgbm8gaGFzTWFueSByZWxhdGlvbnNoaXAgbmFtZWQgJyIgKyBrZXlOYW1lICsgIicgZGVmaW5lZC4iKTsKICAgICAgfQoKICAgICAgcmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwU3RhdGVGb3IodGhpcywga2V5TmFtZSk7CiAgICAgIHZhciB2YWx1ZSA9IHJlbGF0aW9uc2hpcC5nZXREYXRhKCk7CgogICAgICBpZiAodmFsdWUuZGF0YSkgewogICAgICAgIHJlc3VsdHMgPSBbXTsKICAgICAgICB2YWx1ZS5kYXRhLmZvckVhY2goZnVuY3Rpb24gKG1lbWJlcikgewogICAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBzdG9yZS5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlKG1lbWJlcik7CgogICAgICAgICAgaWYgKCFpbnRlcm5hbE1vZGVsLmlzRGVsZXRlZCgpKSB7CiAgICAgICAgICAgIGlmIChpZHMpIHsKICAgICAgICAgICAgICByZXN1bHRzLnB1c2gobWVtYmVyLmlkKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXN1bHRzLnB1c2goaW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdCgpKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CgogICAgICBpZiAoaWRzKSB7CiAgICAgICAgdGhpcy5faGFzTWFueUlkc1trZXlOYW1lXSA9IHJlc3VsdHM7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5faGFzTWFueVJlbGF0aW9uc2hpcHNba2V5TmFtZV0gPSByZXN1bHRzOwogICAgICB9CgogICAgICByZXR1cm4gcmVzdWx0czsKICAgIH0KICAgIC8qKgogICAgICBJdGVyYXRlcyB0aHJvdWdoIGFsbCB0aGUgYXR0cmlidXRlcyBvZiB0aGUgbW9kZWwsIGNhbGxpbmcgdGhlIHBhc3NlZAogICAgICBmdW5jdGlvbiBvbiBlYWNoIGF0dHJpYnV0ZS4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc25hcHNob3QuZWFjaEF0dHJpYnV0ZShmdW5jdGlvbihuYW1lLCBtZXRhKSB7CiAgICAgICAgLy8gLi4uCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZWFjaEF0dHJpYnV0ZQogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayB0aGUgY2FsbGJhY2sgdG8gZXhlY3V0ZQogICAgICBAcGFyYW0ge09iamVjdH0gW2JpbmRpbmddIHRoZSB2YWx1ZSB0byB3aGljaCB0aGUgY2FsbGJhY2sncyBgdGhpc2Agc2hvdWxkIGJlIGJvdW5kCiAgICAqLwogICAgOwoKICAgIF9wcm90by5lYWNoQXR0cmlidXRlID0gZnVuY3Rpb24gZWFjaEF0dHJpYnV0ZShjYWxsYmFjaywgYmluZGluZykgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgdmFyIGF0dHJEZWZzID0gdGhpcy5fc3RvcmUuX2F0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKHRoaXMubW9kZWxOYW1lLCB0aGlzLmlkZW50aWZpZXIpOwoKICAgICAgICBPYmplY3Qua2V5cyhhdHRyRGVmcykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgICBjYWxsYmFjay5jYWxsKGJpbmRpbmcsIGtleSwgYXR0ckRlZnNba2V5XSk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5yZWNvcmQuZWFjaEF0dHJpYnV0ZShjYWxsYmFjaywgYmluZGluZyk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBJdGVyYXRlcyB0aHJvdWdoIGFsbCB0aGUgcmVsYXRpb25zaGlwcyBvZiB0aGUgbW9kZWwsIGNhbGxpbmcgdGhlIHBhc3NlZAogICAgICBmdW5jdGlvbiBvbiBlYWNoIHJlbGF0aW9uc2hpcC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc25hcHNob3QuZWFjaFJlbGF0aW9uc2hpcChmdW5jdGlvbihuYW1lLCByZWxhdGlvbnNoaXApIHsKICAgICAgICAvLyAuLi4KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBlYWNoUmVsYXRpb25zaGlwCiAgICAgIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIHRoZSBjYWxsYmFjayB0byBleGVjdXRlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBbYmluZGluZ10gdGhlIHZhbHVlIHRvIHdoaWNoIHRoZSBjYWxsYmFjaydzIGB0aGlzYCBzaG91bGQgYmUgYm91bmQKICAgICovCiAgICA7CgogICAgX3Byb3RvLmVhY2hSZWxhdGlvbnNoaXAgPSBmdW5jdGlvbiBlYWNoUmVsYXRpb25zaGlwKGNhbGxiYWNrLCBiaW5kaW5nKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICB2YXIgcmVsYXRpb25zaGlwRGVmcyA9IHRoaXMuX3N0b3JlLl9yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcih0aGlzLm1vZGVsTmFtZSwgdGhpcy5pZGVudGlmaWVyKTsKCiAgICAgICAgT2JqZWN0LmtleXMocmVsYXRpb25zaGlwRGVmcykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgICBjYWxsYmFjay5jYWxsKGJpbmRpbmcsIGtleSwgcmVsYXRpb25zaGlwRGVmc1trZXldKTsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnJlY29yZC5lYWNoUmVsYXRpb25zaGlwKGNhbGxiYWNrLCBiaW5kaW5nKTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgIFNlcmlhbGl6ZXMgdGhlIHNuYXBzaG90IHVzaW5nIHRoZSBzZXJpYWxpemVyIGZvciB0aGUgbW9kZWwuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgY3JlYXRlUmVjb3JkKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCkgewogICAgICAgICAgdmFyIGRhdGEgPSBzbmFwc2hvdC5zZXJpYWxpemUoeyBpbmNsdWRlSWQ6IHRydWUgfSk7CiAgICAgICAgICB2YXIgdXJsID0gYC8ke3R5cGUubW9kZWxOYW1lfWA7CiAgICAgICAgICAgcmV0dXJuIGZldGNoKHVybCwgewogICAgICAgICAgICBtZXRob2Q6ICdQT1NUJywKICAgICAgICAgICAgYm9keTogZGF0YSwKICAgICAgICAgIH0pLnRoZW4oKHJlc3BvbnNlKSA9PiByZXNwb25zZS5qc29uKCkpCiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZQogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgICBAcmV0dXJuIHtPYmplY3R9IGFuIG9iamVjdCB3aG9zZSB2YWx1ZXMgYXJlIHByaW1pdGl2ZSBKU09OIHZhbHVlcyBvbmx5CiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uc2VyaWFsaXplID0gZnVuY3Rpb24gc2VyaWFsaXplKG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMucmVjb3JkLnN0b3JlLnNlcmlhbGl6ZXJGb3IodGhpcy5tb2RlbE5hbWUpLnNlcmlhbGl6ZSh0aGlzLCBvcHRpb25zKTsKICAgIH07CgogICAgX2NyZWF0ZUNsYXNzKFNuYXBzaG90LCBbewogICAgICBrZXk6ICJyZWNvcmQiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5faW50ZXJuYWxNb2RlbC5nZXRSZWNvcmQoKTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJfYXR0cmlidXRlcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICAgIHZhciBhdHRyaWJ1dGVzID0gdGhpcy5fX2F0dHJpYnV0ZXM7CgogICAgICAgIGlmIChhdHRyaWJ1dGVzID09PSBudWxsKSB7CiAgICAgICAgICB2YXIgcmVjb3JkID0gdGhpcy5yZWNvcmQ7CiAgICAgICAgICBhdHRyaWJ1dGVzID0gdGhpcy5fX2F0dHJpYnV0ZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgdmFyIGF0dHJzOwoKICAgICAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICAgICAgYXR0cnMgPSBPYmplY3Qua2V5cyh0aGlzLl9zdG9yZS5fYXR0cmlidXRlc0RlZmluaXRpb25Gb3IodGhpcy5tb2RlbE5hbWUsIHRoaXMuaWRlbnRpZmllcikpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYXR0cnMgPSBPYmplY3Qua2V5cyh0aGlzLl9zdG9yZS5fYXR0cmlidXRlc0RlZmluaXRpb25Gb3IodGhpcy5tb2RlbE5hbWUsIHJlY29yZC5pZCkpOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICAgICAgYXR0cnMuZm9yRWFjaChmdW5jdGlvbiAoa2V5TmFtZSkgewogICAgICAgICAgICAgIGlmIChfdGhpcy50eXBlLmlzTW9kZWwpIHsKICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXNba2V5TmFtZV0gPSBFbWJlci5nZXQocmVjb3JkLCBrZXlOYW1lKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgYXR0cmlidXRlc1trZXlOYW1lXSA9IHJlY29yZERhdGFGb3IoX3RoaXMuX2ludGVybmFsTW9kZWwpLmdldEF0dHIoa2V5TmFtZSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJlY29yZC5lYWNoQXR0cmlidXRlKGZ1bmN0aW9uIChrZXlOYW1lKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZXNba2V5TmFtZV0gPSBFbWJlci5nZXQocmVjb3JkLCBrZXlOYW1lKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gYXR0cmlidXRlczsKICAgICAgfQogICAgICAvKioKICAgICAgIFRoZSB0eXBlIG9mIHRoZSB1bmRlcmx5aW5nIHJlY29yZCBmb3IgdGhpcyBzbmFwc2hvdCwgYXMgYSBNb2RlbC4KICAgICAgICBAcHJvcGVydHkgdHlwZQogICAgICAgQHR5cGUge01vZGVsfQogICAgICAgKi8KCiAgICB9LCB7CiAgICAgIGtleTogInR5cGUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICAvLyBUT0RPIEBydW5zcGlyZWQgd2Ugc2hvdWxkIGRlcHJlY2F0ZSB0aGlzIGluIGZhdm9yIG9mIG1vZGVsQ2xhc3MgYnV0IG9ubHkgb25jZQogICAgICAgIC8vIHdlJ3ZlIGNsZWFuZWQgdXAgdGhlIGludGVybmFscyBlbm91Z2ggdGhhdCBhIHB1YmxpYyBjaGFuZ2UgdG8gZm9sbG93IHN1aXRlIGlzCiAgICAgICAgLy8gdW5jb250cm92ZXJzaWFsLgogICAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsLm1vZGVsQ2xhc3M7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiaXNOZXciLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAoIWNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpc05ldyBpcyBvbmx5IGF2YWlsYWJsZSB3aGVuIGN1c3RvbSBtb2RlbCBjbGFzcyBmZiBpcyBvbicpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMuX2ludGVybmFsTW9kZWwuaXNOZXcoKTsKICAgICAgfQogICAgfV0pOwoKICAgIHJldHVybiBTbmFwc2hvdDsKICB9KCk7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qCiAgICBBIGBQcm9taXNlQXJyYXlgIGlzIGFuIG9iamVjdCB0aGF0IGFjdHMgbGlrZSBib3RoIGFuIGBFbWJlci5BcnJheWAKICAgIGFuZCBhIHByb21pc2UuIFdoZW4gdGhlIHByb21pc2UgaXMgcmVzb2x2ZWQgdGhlIHJlc3VsdGluZyB2YWx1ZQogICAgd2lsbCBiZSBzZXQgdG8gdGhlIGBQcm9taXNlQXJyYXlgJ3MgYGNvbnRlbnRgIHByb3BlcnR5LiBUaGlzIG1ha2VzCiAgICBpdCBlYXN5IHRvIGNyZWF0ZSBkYXRhIGJpbmRpbmdzIHdpdGggdGhlIGBQcm9taXNlQXJyYXlgIHRoYXQgd2lsbCBiZQogICAgdXBkYXRlZCB3aGVuIHRoZSBwcm9taXNlIHJlc29sdmVzLgoKICAgIEZvciBtb3JlIGluZm9ybWF0aW9uIHNlZSB0aGUgW0VtYmVyLlByb21pc2VQcm94eU1peGluCiAgICBkb2N1bWVudGF0aW9uXSgvYXBpL2NsYXNzZXMvRW1iZXIuUHJvbWlzZVByb3h5TWl4aW4uaHRtbCkuCgogICAgRXhhbXBsZQoKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCBwcm9taXNlQXJyYXkgPSBQcm9taXNlQXJyYXkuY3JlYXRlKHsKICAgICAgcHJvbWlzZTogJC5nZXRKU09OKCcvc29tZS9yZW1vdGUvZGF0YS5qc29uJykKICAgIH0pOwoKICAgIHByb21pc2VBcnJheS5nZXQoJ2xlbmd0aCcpOyAvLyAwCgogICAgcHJvbWlzZUFycmF5LnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgIHByb21pc2VBcnJheS5nZXQoJ2xlbmd0aCcpOyAvLyAxMDAKICAgIH0pOwogICAgYGBgCgogICAgQGNsYXNzIFByb21pc2VBcnJheQogICAgQGV4dGVuZHMgRW1iZXIuQXJyYXlQcm94eQogICAgQHVzZXMgRW1iZXIuUHJvbWlzZVByb3h5TWl4aW4KICAqLwogIHZhciBQcm9taXNlQXJyYXkgPSBFbWJlci5BcnJheVByb3h5LmV4dGVuZChFbWJlci5Qcm9taXNlUHJveHlNaXhpbiwgewogICAgbWV0YTogRW1iZXIuY29tcHV0ZWQucmVhZHMoJ2NvbnRlbnQubWV0YScpCiAgfSk7CiAgLyoKICAgIEEgYFByb21pc2VPYmplY3RgIGlzIGFuIG9iamVjdCB0aGF0IGFjdHMgbGlrZSBib3RoIGFuIGBFbWJlck9iamVjdGAKICAgIGFuZCBhIHByb21pc2UuIFdoZW4gdGhlIHByb21pc2UgaXMgcmVzb2x2ZWQsIHRoZW4gdGhlIHJlc3VsdGluZyB2YWx1ZQogICAgd2lsbCBiZSBzZXQgdG8gdGhlIGBQcm9taXNlT2JqZWN0YCdzIGBjb250ZW50YCBwcm9wZXJ0eS4gVGhpcyBtYWtlcwogICAgaXQgZWFzeSB0byBjcmVhdGUgZGF0YSBiaW5kaW5ncyB3aXRoIHRoZSBgUHJvbWlzZU9iamVjdGAgdGhhdCB3aWxsCiAgICBiZSB1cGRhdGVkIHdoZW4gdGhlIHByb21pc2UgcmVzb2x2ZXMuCgogICAgRm9yIG1vcmUgaW5mb3JtYXRpb24gc2VlIHRoZSBbRW1iZXIuUHJvbWlzZVByb3h5TWl4aW4KICAgIGRvY3VtZW50YXRpb25dKC9hcGkvY2xhc3Nlcy9FbWJlci5Qcm9taXNlUHJveHlNaXhpbi5odG1sKS4KCiAgICBFeGFtcGxlCgogICAgYGBgamF2YXNjcmlwdAogICAgbGV0IHByb21pc2VPYmplY3QgPSBQcm9taXNlT2JqZWN0LmNyZWF0ZSh7CiAgICAgIHByb21pc2U6ICQuZ2V0SlNPTignL3NvbWUvcmVtb3RlL2RhdGEuanNvbicpCiAgICB9KTsKCiAgICBwcm9taXNlT2JqZWN0LmdldCgnbmFtZScpOyAvLyBudWxsCgogICAgcHJvbWlzZU9iamVjdC50aGVuKGZ1bmN0aW9uKCkgewogICAgICBwcm9taXNlT2JqZWN0LmdldCgnbmFtZScpOyAvLyAnVG9tc3RlcicKICAgIH0pOwogICAgYGBgCgogICAgQGNsYXNzIFByb21pc2VPYmplY3QKICAgIEBleHRlbmRzIEVtYmVyLk9iamVjdFByb3h5CiAgICBAdXNlcyBFbWJlci5Qcm9taXNlUHJveHlNaXhpbgogICovCgogIHZhciBQcm9taXNlT2JqZWN0ID0gRW1iZXIuT2JqZWN0UHJveHkuZXh0ZW5kKEVtYmVyLlByb21pc2VQcm94eU1peGluKTsKICBmdW5jdGlvbiBwcm9taXNlT2JqZWN0KHByb21pc2UsIGxhYmVsKSB7CiAgICByZXR1cm4gUHJvbWlzZU9iamVjdC5jcmVhdGUoewogICAgICBwcm9taXNlOiBFbWJlci5SU1ZQLlByb21pc2UucmVzb2x2ZShwcm9taXNlLCBsYWJlbCkKICAgIH0pOwogIH0KICBmdW5jdGlvbiBwcm9taXNlQXJyYXkocHJvbWlzZSwgbGFiZWwpIHsKICAgIHJldHVybiBQcm9taXNlQXJyYXkuY3JlYXRlKHsKICAgICAgcHJvbWlzZTogRW1iZXIuUlNWUC5Qcm9taXNlLnJlc29sdmUocHJvbWlzZSwgbGFiZWwpCiAgICB9KTsKICB9CiAgdmFyIFByb21pc2VCZWxvbmdzVG8gPSBQcm9taXNlT2JqZWN0LmV4dGVuZCh7CiAgICAvLyB3ZSBkb24ndCBwcm94eSBtZXRhIGJlY2F1c2Ugd2Ugd291bGQgbmVlZCB0byBwcm94eSBpdCB0byB0aGUgcmVsYXRpb25zaGlwIHN0YXRlIGNvbnRhaW5lcgogICAgLy8gIGhvd2V2ZXIsIG1ldGEgb24gcmVsYXRpb25zaGlwcyBkb2VzIG5vdCB0cmlnZ2VyIGNoYW5nZSBub3RpZmljYXRpb25zLgogICAgLy8gIGlmIHlvdSBuZWVkIHJlbGF0aW9uc2hpcCBtZXRhLCB5b3Ugc2hvdWxkIGRvIGByZWNvcmQuYmVsb25nc1RvKHJlbGF0aW9uc2hpcE5hbWUpLm1ldGEoKWAKICAgIG1ldGE6IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgIH0pLAogICAgcmVsb2FkOiBmdW5jdGlvbiByZWxvYWQob3B0aW9ucykgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwogICAgICB2YXIgX3RoaXMkX2JlbG9uZ3NUb1N0YXRlID0gdGhpcy5fYmVsb25nc1RvU3RhdGUsCiAgICAgICAgICBrZXkgPSBfdGhpcyRfYmVsb25nc1RvU3RhdGUua2V5LAogICAgICAgICAgc3RvcmUgPSBfdGhpcyRfYmVsb25nc1RvU3RhdGUuc3RvcmUsCiAgICAgICAgICBvcmlnaW5hdGluZ0ludGVybmFsTW9kZWwgPSBfdGhpcyRfYmVsb25nc1RvU3RhdGUub3JpZ2luYXRpbmdJbnRlcm5hbE1vZGVsOwogICAgICByZXR1cm4gc3RvcmUucmVsb2FkQmVsb25nc1RvKHRoaXMsIG9yaWdpbmF0aW5nSW50ZXJuYWxNb2RlbCwga2V5LCBvcHRpb25zKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gX3RoaXM7CiAgICAgIH0pOwogICAgfQogIH0pOwogIGZ1bmN0aW9uIHByb3h5VG9Db250ZW50KG1ldGhvZCkgewogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIF9FbWJlckdldDsKCiAgICAgIHJldHVybiAoX0VtYmVyR2V0ID0gRW1iZXIuZ2V0KHRoaXMsICdjb250ZW50JykpW21ldGhvZF0uYXBwbHkoX0VtYmVyR2V0LCBhcmd1bWVudHMpOwogICAgfTsKICB9CiAgLyoKICAgIEEgUHJvbWlzZU1hbnlBcnJheSBpcyBhIFByb21pc2VBcnJheSB0aGF0IGFsc28gcHJveGllcyBjZXJ0YWluIG1ldGhvZCBjYWxscwogICAgdG8gdGhlIHVuZGVybHlpbmcgbWFueUFycmF5LgogICAgUmlnaHQgbm93IHdlIHByb3h5OgoKICAgICAgKiBgcmVsb2FkKClgCiAgICAgICogYGNyZWF0ZVJlY29yZCgpYAogICAgICAqIGBvbigpYAogICAgICAqIGBvbmUoKWAKICAgICAgKiBgdHJpZ2dlcigpYAogICAgICAqIGBvZmYoKWAKICAgICAgKiBgaGFzKClgCgogICAgQGNsYXNzIFByb21pc2VNYW55QXJyYXkKICAgIEBleHRlbmRzIEVtYmVyLkFycmF5UHJveHkKICAqLwoKICB2YXIgUHJvbWlzZU1hbnlBcnJheSA9IFByb21pc2VBcnJheS5leHRlbmQoewogICAgcmVsb2FkOiBmdW5jdGlvbiByZWxvYWQob3B0aW9ucykgewogICAgICB0aGlzLnNldCgncHJvbWlzZScsIHRoaXMuZ2V0KCdjb250ZW50JykucmVsb2FkKG9wdGlvbnMpKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAogICAgY3JlYXRlUmVjb3JkOiBwcm94eVRvQ29udGVudCgnY3JlYXRlUmVjb3JkJyksCiAgICBvbjogcHJveHlUb0NvbnRlbnQoJ29uJyksCiAgICBvbmU6IHByb3h5VG9Db250ZW50KCdvbmUnKSwKICAgIHRyaWdnZXI6IHByb3h5VG9Db250ZW50KCd0cmlnZ2VyJyksCiAgICBvZmY6IHByb3h5VG9Db250ZW50KCdvZmYnKSwKICAgIGhhczogcHJveHlUb0NvbnRlbnQoJ2hhcycpCiAgfSk7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCiAgZnVuY3Rpb24gX2JpbmQoZm4pIHsKICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4gPiAxID8gX2xlbiAtIDEgOiAwKSwgX2tleSA9IDE7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgYXJnc1tfa2V5IC0gMV0gPSBhcmd1bWVudHNbX2tleV07CiAgICB9CgogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIGZuLmFwcGx5KHVuZGVmaW5lZCwgYXJncyk7CiAgICB9OwogIH0KICBmdW5jdGlvbiBfZ3VhcmQocHJvbWlzZSwgdGVzdCkgewogICAgdmFyIGd1YXJkZWQgPSBwcm9taXNlLmZpbmFsbHkoZnVuY3Rpb24gKCkgewogICAgICBpZiAoIXRlc3QoKSkgewogICAgICAgIGd1YXJkZWQuX3N1YnNjcmliZXJzLmxlbmd0aCA9IDA7CiAgICAgIH0KICAgIH0pOwogICAgcmV0dXJuIGd1YXJkZWQ7CiAgfQogIGZ1bmN0aW9uIF9vYmplY3RJc0FsaXZlKG9iamVjdCkgewogICAgcmV0dXJuICEoRW1iZXIuZ2V0KG9iamVjdCwgJ2lzRGVzdHJveWVkJykgfHwgRW1iZXIuZ2V0KG9iamVjdCwgJ2lzRGVzdHJveWluZycpKTsKICB9CiAgZnVuY3Rpb24gZ3VhcmREZXN0cm95ZWRTdG9yZShwcm9taXNlLCBzdG9yZSwgbGFiZWwpIHsKCiAgICB2YXIgd3JhcHBlclByb21pc2UgPSBFbWJlci5SU1ZQLnJlc29sdmUocHJvbWlzZSwgbGFiZWwpLnRoZW4oZnVuY3Rpb24gKHYpIHsKICAgICAgcmV0dXJuIHByb21pc2U7CiAgICB9KTsKICAgIHJldHVybiBfZ3VhcmQod3JhcHBlclByb21pc2UsIGZ1bmN0aW9uICgpIHsKCiAgICAgIHJldHVybiBfb2JqZWN0SXNBbGl2ZShzdG9yZSk7CiAgICB9KTsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICAgQG1ldGhvZCBkaWZmQXJyYXkKICAgIEBwcml2YXRlCiAgICBAcGFyYW0ge0FycmF5fSBvbGRBcnJheSB0aGUgb2xkIGFycmF5CiAgICBAcGFyYW0ge0FycmF5fSBuZXdBcnJheSB0aGUgbmV3IGFycmF5CiAgICBAcmV0dXJuIHtoYXNofSB7CiAgICAgICAgZmlyc3RDaGFuZ2VJbmRleDogPGludGVnZXI+LCAgLy8gbnVsbCBpZiBubyBjaGFuZ2UKICAgICAgICBhZGRlZENvdW50OiA8aW50ZWdlcj4sICAgICAgICAvLyAwIGlmIG5vIGNoYW5nZQogICAgICAgIHJlbW92ZWRDb3VudDogPGludGVnZXI+ICAgICAgIC8vIDAgaWYgbm8gY2hhbmdlCiAgICAgIH0KICAqLwogIGZ1bmN0aW9uIGRpZmZBcnJheShvbGRBcnJheSwgbmV3QXJyYXkpIHsKICAgIHZhciBvbGRMZW5ndGggPSBvbGRBcnJheS5sZW5ndGg7CiAgICB2YXIgbmV3TGVuZ3RoID0gbmV3QXJyYXkubGVuZ3RoOwogICAgdmFyIHNob3J0ZXN0TGVuZ3RoID0gTWF0aC5taW4ob2xkTGVuZ3RoLCBuZXdMZW5ndGgpOwogICAgdmFyIGZpcnN0Q2hhbmdlSW5kZXggPSBudWxsOyAvLyBudWxsIHNpZ25pZmllcyBubyBjaGFuZ2VzCiAgICAvLyBmaW5kIHRoZSBmaXJzdCBjaGFuZ2UKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNob3J0ZXN0TGVuZ3RoOyBpKyspIHsKICAgICAgLy8gY29tcGFyZSBlYWNoIGl0ZW0gaW4gdGhlIGFycmF5CiAgICAgIGlmIChvbGRBcnJheVtpXSAhPT0gbmV3QXJyYXlbaV0pIHsKICAgICAgICBmaXJzdENoYW5nZUluZGV4ID0gaTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQoKICAgIGlmIChmaXJzdENoYW5nZUluZGV4ID09PSBudWxsICYmIG5ld0xlbmd0aCAhPT0gb2xkTGVuZ3RoKSB7CiAgICAgIC8vIG5vIGNoYW5nZSBmb3VuZCBpbiB0aGUgb3ZlcmxhcHBpbmcgYmxvY2sKICAgICAgLy8gYW5kIGFycmF5IGxlbmd0aHMgZGlmZmVyLAogICAgICAvLyBzbyBjaGFuZ2Ugc3RhcnRzIGF0IGVuZCBvZiBvdmVybGFwCiAgICAgIGZpcnN0Q2hhbmdlSW5kZXggPSBzaG9ydGVzdExlbmd0aDsKICAgIH0KCiAgICB2YXIgYWRkZWRDb3VudCA9IDA7CiAgICB2YXIgcmVtb3ZlZENvdW50ID0gMDsKCiAgICBpZiAoZmlyc3RDaGFuZ2VJbmRleCAhPT0gbnVsbCkgewogICAgICAvLyB3ZSBmb3VuZCBhIGNoYW5nZSwgZmluZCB0aGUgZW5kIG9mIHRoZSBjaGFuZ2UKICAgICAgdmFyIHVuY2hhbmdlZEVuZEJsb2NrTGVuZ3RoID0gc2hvcnRlc3RMZW5ndGggLSBmaXJzdENoYW5nZUluZGV4OyAvLyB3YWxrIGJhY2sgZnJvbSB0aGUgZW5kIG9mIGJvdGggYXJyYXlzIHVudGlsIHdlIGZpbmQgYSBjaGFuZ2UKCiAgICAgIGZvciAodmFyIF9pID0gMTsgX2kgPD0gc2hvcnRlc3RMZW5ndGg7IF9pKyspIHsKICAgICAgICAvLyBjb21wYXJlIGVhY2ggaXRlbSBpbiB0aGUgYXJyYXkKICAgICAgICBpZiAob2xkQXJyYXlbb2xkTGVuZ3RoIC0gX2ldICE9PSBuZXdBcnJheVtuZXdMZW5ndGggLSBfaV0pIHsKICAgICAgICAgIHVuY2hhbmdlZEVuZEJsb2NrTGVuZ3RoID0gX2kgLSAxOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CgogICAgICBhZGRlZENvdW50ID0gbmV3TGVuZ3RoIC0gdW5jaGFuZ2VkRW5kQmxvY2tMZW5ndGggLSBmaXJzdENoYW5nZUluZGV4OwogICAgICByZW1vdmVkQ291bnQgPSBvbGRMZW5ndGggLSB1bmNoYW5nZWRFbmRCbG9ja0xlbmd0aCAtIGZpcnN0Q2hhbmdlSW5kZXg7CiAgICB9CgogICAgcmV0dXJuIHsKICAgICAgZmlyc3RDaGFuZ2VJbmRleDogZmlyc3RDaGFuZ2VJbmRleCwKICAgICAgYWRkZWRDb3VudDogYWRkZWRDb3VudCwKICAgICAgcmVtb3ZlZENvdW50OiByZW1vdmVkQ291bnQKICAgIH07CiAgfQoKICAvL2ltcG9ydCBFdmVudGVkIGZyb20gJ0BlbWJlci9vYmplY3QvZXZlbnRlZCc7CiAgLyoqCiAgICBBIGBNYW55QXJyYXlgIGlzIGEgYE11dGFibGVBcnJheWAgdGhhdCByZXByZXNlbnRzIHRoZSBjb250ZW50cyBvZiBhIGhhcy1tYW55CiAgICByZWxhdGlvbnNoaXAuCgogICAgVGhlIGBNYW55QXJyYXlgIGlzIGluc3RhbnRpYXRlZCBsYXppbHkgdGhlIGZpcnN0IHRpbWUgdGhlIHJlbGF0aW9uc2hpcCBpcwogICAgcmVxdWVzdGVkLgoKICAgICMjIyBJbnZlcnNlcwoKICAgIE9mdGVuLCB0aGUgcmVsYXRpb25zaGlwcyBpbiBFbWJlciBEYXRhIGFwcGxpY2F0aW9ucyB3aWxsIGhhdmUKICAgIGFuIGludmVyc2UuIEZvciBleGFtcGxlLCBpbWFnaW5lIHRoZSBmb2xsb3dpbmcgbW9kZWxzIGFyZQogICAgZGVmaW5lZDoKCiAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIGNvbW1lbnRzOiBoYXNNYW55KCdjb21tZW50JykKICAgIH0pOwogICAgYGBgCgogICAgYGBgYXBwL21vZGVscy9jb21tZW50LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHBvc3Q6IGJlbG9uZ3NUbygncG9zdCcpCiAgICB9KTsKICAgIGBgYAoKICAgIElmIHlvdSBjcmVhdGVkIGEgbmV3IGluc3RhbmNlIG9mIGBQb3N0YCBhbmQgYWRkZWQKICAgIGEgYENvbW1lbnRgIHJlY29yZCB0byBpdHMgYGNvbW1lbnRzYCBoYXMtbWFueQogICAgcmVsYXRpb25zaGlwLCB5b3Ugd291bGQgZXhwZWN0IHRoZSBjb21tZW50J3MgYHBvc3RgCiAgICBwcm9wZXJ0eSB0byBiZSBzZXQgdG8gdGhlIHBvc3QgdGhhdCBjb250YWluZWQKICAgIHRoZSBoYXMtbWFueS4KCiAgICBXZSBjYWxsIHRoZSByZWNvcmQgdG8gd2hpY2ggYSByZWxhdGlvbnNoaXAgYmVsb25ncy10byB0aGUKICAgIHJlbGF0aW9uc2hpcCdzIF9vd25lcl8uCgogICAgQGNsYXNzIE1hbnlBcnJheQogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAgIEB1c2VzIEVtYmVyLk11dGFibGVBcnJheSwgRW1iZXJEYXRhLkRlcHJlY2F0ZWRFdmVudAogICovCgogIHZhciBNYW55QXJyYXkgPSBFbWJlci5PYmplY3QuZXh0ZW5kKEVtYmVyLk11dGFibGVBcnJheSwgRGVwcmVjYXRlZEV2ZW50ZWQsIHsKICAgIC8vIGhlcmUgdG8gbWFrZSBUUyBoYXBweQogICAgX2ludmVyc2VJc0FzeW5jOiBmYWxzZSwKICAgIGlzTG9hZGVkOiBmYWxzZSwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICAgIC8qKgogICAgICBUaGUgbG9hZGluZyBzdGF0ZSBvZiB0aGlzIGFycmF5CiAgICAgICBAcHJvcGVydHkge0Jvb2xlYW59IGlzTG9hZGVkCiAgICAgICovCgoKICAgICAgdGhpcy5pc0xvYWRlZCA9IHRoaXMuaXNMb2FkZWQgfHwgZmFsc2U7CiAgICAgIHRoaXMubGVuZ3RoID0gMDsKICAgICAgLyoqCiAgICAgIFVzZWQgZm9yIGFzeW5jIGBoYXNNYW55YCBhcnJheXMKICAgICAgdG8ga2VlcCB0cmFjayBvZiB3aGVuIHRoZXkgd2lsbCByZXNvbHZlLgogICAgICAgQHByb3BlcnR5IHtFbWJlci5SU1ZQLlByb21pc2V9IHByb21pc2UKICAgICAgQHByaXZhdGUKICAgICAgKi8KCiAgICAgIHRoaXMucHJvbWlzZSA9IG51bGw7CiAgICAgIC8qKgogICAgICBNZXRhZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhlIHJlcXVlc3QgZm9yIGFzeW5jIGhhc01hbnkgcmVsYXRpb25zaGlwcy4KICAgICAgIEV4YW1wbGUKICAgICAgIEdpdmVuIHRoYXQgdGhlIHNlcnZlciByZXR1cm5zIHRoZSBmb2xsb3dpbmcgSlNPTiBwYXlsb2FkIHdoZW4gZmV0Y2hpbmcgYQogICAgICBoYXNNYW55IHJlbGF0aW9uc2hpcDoKICAgICAgIGBgYGpzCiAgICAgIHsKICAgICAgICAiY29tbWVudHMiOiBbewogICAgICAgICAgImlkIjogMSwKICAgICAgICAgICJjb21tZW50IjogIlRoaXMgaXMgdGhlIGZpcnN0IGNvbW1lbnQiLAogICAgICAgIH0sIHsKICAgICAgLy8gLi4uCiAgICAgICAgfV0sCiAgICAgICAgICJtZXRhIjogewogICAgICAgICAgInBhZ2UiOiAxLAogICAgICAgICAgInRvdGFsIjogNQogICAgICAgIH0KICAgICAgfQogICAgICBgYGAKICAgICAgIFlvdSBjYW4gdGhlbiBhY2Nlc3MgdGhlIG1ldGFkYXRhIHZpYSB0aGUgYG1ldGFgIHByb3BlcnR5OgogICAgICAgYGBganMKICAgICAgcG9zdC5nZXQoJ2NvbW1lbnRzJykudGhlbihmdW5jdGlvbihjb21tZW50cykgewogICAgICAgIHZhciBtZXRhID0gY29tbWVudHMuZ2V0KCdtZXRhJyk7CiAgICAgICAvLyBtZXRhLnBhZ2UgPT4gMQogICAgICAvLyBtZXRhLnRvdGFsID0+IDUKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQHByb3BlcnR5IHtPYmplY3R9IG1ldGEKICAgICAgQHB1YmxpYwogICAgICAqLwogICAgICAvLyBUT0RPIHRoaXMgaXMgbGlrZWx5IGJyb2tlbiBpbiBvdXIgcmVmYWN0b3IKCiAgICAgIHRoaXMubWV0YSA9IHRoaXMubWV0YSB8fCBudWxsOwogICAgICAvKioKICAgICAgYHRydWVgIGlmIHRoZSByZWxhdGlvbnNoaXAgaXMgcG9seW1vcnBoaWMsIGBmYWxzZWAgb3RoZXJ3aXNlLgogICAgICAgQHByb3BlcnR5IHtCb29sZWFufSBpc1BvbHltb3JwaGljCiAgICAgIEBwcml2YXRlCiAgICAgICovCgogICAgICB0aGlzLmlzUG9seW1vcnBoaWMgPSB0aGlzLmlzUG9seW1vcnBoaWMgfHwgZmFsc2U7CiAgICAgIC8qKgogICAgICBUaGUgcmVsYXRpb25zaGlwIHdoaWNoIG1hbmFnZXMgdGhpcyBhcnJheS4KICAgICAgIEBwcm9wZXJ0eSB7TWFueVJlbGF0aW9uc2hpcH0gcmVsYXRpb25zaGlwCiAgICAgIEBwcml2YXRlCiAgICAgICovCgogICAgICB0aGlzLmN1cnJlbnRTdGF0ZSA9IFtdOwogICAgICB0aGlzLmZsdXNoQ2Fub25pY2FsKHRoaXMuaW5pdGlhbFN0YXRlLCBmYWxzZSk7CiAgICB9LAogICAgLy8gVE9ETzogaWYoREVCVUcpCiAgICBhbnlVbmxvYWRlZDogZnVuY3Rpb24gYW55VW5sb2FkZWQoKSB7CiAgICAgIC8vIFVzZSBgZmlsdGVyWzBdYCBhcyBvcHBvc2VkIHRvIGBmaW5kYCBiZWNhdXNlIG9mIElFMTEKICAgICAgdmFyIHVubG9hZGVkID0gdGhpcy5jdXJyZW50U3RhdGUuZmlsdGVyKGZ1bmN0aW9uIChpbSkgewogICAgICAgIHJldHVybiBpbS5faXNEZW1hdGVyaWFsaXppbmcgfHwgIWltLmlzTG9hZGVkKCk7CiAgICAgIH0pWzBdOwogICAgICByZXR1cm4gISF1bmxvYWRlZDsKICAgIH0sCiAgICByZW1vdmVVbmxvYWRlZEludGVybmFsTW9kZWw6IGZ1bmN0aW9uIHJlbW92ZVVubG9hZGVkSW50ZXJuYWxNb2RlbCgpIHsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmN1cnJlbnRTdGF0ZS5sZW5ndGg7ICsraSkgewogICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gdGhpcy5jdXJyZW50U3RhdGVbaV07CiAgICAgICAgdmFyIHNob3VsZFJlbW92ZSA9IHZvaWQgMDsKCiAgICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgICAgc2hvdWxkUmVtb3ZlID0gaW50ZXJuYWxNb2RlbC5faXNEZW1hdGVyaWFsaXppbmc7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHNob3VsZFJlbW92ZSA9IGludGVybmFsTW9kZWwuX2lzRGVtYXRlcmlhbGl6aW5nIHx8ICFpbnRlcm5hbE1vZGVsLmlzTG9hZGVkKCk7CiAgICAgICAgfQoKICAgICAgICBpZiAoc2hvdWxkUmVtb3ZlKSB7CiAgICAgICAgICB0aGlzLmFycmF5Q29udGVudFdpbGxDaGFuZ2UoaSwgMSwgMCk7CiAgICAgICAgICB0aGlzLmN1cnJlbnRTdGF0ZS5zcGxpY2UoaSwgMSk7CiAgICAgICAgICB0aGlzLnNldCgnbGVuZ3RoJywgdGhpcy5jdXJyZW50U3RhdGUubGVuZ3RoKTsKICAgICAgICAgIHRoaXMuYXJyYXlDb250ZW50RGlkQ2hhbmdlKGksIDEsIDApOwogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gZmFsc2U7CiAgICB9LAogICAgb2JqZWN0QXQ6IGZ1bmN0aW9uIG9iamVjdEF0KGluZGV4KSB7CiAgICAgIC8vIFRPRE8gd2UgbGlrZWx5IG5lZWQgdG8gZm9yY2UgZmx1c2ggaGVyZQoKICAgICAgLyoKICAgICAgaWYgKHRoaXMucmVsYXRpb25zaGlwLl93aWxsVXBkYXRlTWFueUFycmF5KSB7CiAgICAgICAgdGhpcy5yZWxhdGlvbnNoaXAuX2ZsdXNoUGVuZGluZ01hbnlBcnJheVVwZGF0ZXMoKTsKICAgICAgfQogICAgICAqLwogICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IHRoaXMuY3VycmVudFN0YXRlW2luZGV4XTsKCiAgICAgIGlmIChpbnRlcm5hbE1vZGVsID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLmdldFJlY29yZCgpOwogICAgfSwKICAgIGZsdXNoQ2Fub25pY2FsOiBmdW5jdGlvbiBmbHVzaENhbm9uaWNhbCh0b1NldCwgaXNJbml0aWFsaXplZCkgewogICAgICBpZiAoaXNJbml0aWFsaXplZCA9PT0gdm9pZCAwKSB7CiAgICAgICAgaXNJbml0aWFsaXplZCA9IHRydWU7CiAgICAgIH0KCiAgICAgIC8vIEl04oCZcyBwb3NzaWJsZSB0aGUgcGFyZW50IHNpZGUgb2YgdGhlIHJlbGF0aW9uc2hpcCBtYXkgaGF2ZSBiZWVuIHVubG9hZGVkIGJ5IHRoaXMgcG9pbnQKICAgICAgaWYgKCFfb2JqZWN0SXNBbGl2ZSh0aGlzKSkgewogICAgICAgIHJldHVybjsKICAgICAgfSAvLyBkaWZmIHRvIGZpbmQgY2hhbmdlcwoKCiAgICAgIHZhciBkaWZmID0gZGlmZkFycmF5KHRoaXMuY3VycmVudFN0YXRlLCB0b1NldCk7CgogICAgICBpZiAoZGlmZi5maXJzdENoYW5nZUluZGV4ICE9PSBudWxsKSB7CiAgICAgICAgLy8gaXQncyBudWxsIGlmIG5vIGNoYW5nZSBmb3VuZAogICAgICAgIC8vIHdlIGZvdW5kIGEgY2hhbmdlCiAgICAgICAgdGhpcy5hcnJheUNvbnRlbnRXaWxsQ2hhbmdlKGRpZmYuZmlyc3RDaGFuZ2VJbmRleCwgZGlmZi5yZW1vdmVkQ291bnQsIGRpZmYuYWRkZWRDb3VudCk7CiAgICAgICAgdGhpcy5zZXQoJ2xlbmd0aCcsIHRvU2V0Lmxlbmd0aCk7CiAgICAgICAgdGhpcy5jdXJyZW50U3RhdGUgPSB0b1NldC5zbGljZSgpOwogICAgICAgIHRoaXMuYXJyYXlDb250ZW50RGlkQ2hhbmdlKGRpZmYuZmlyc3RDaGFuZ2VJbmRleCwgZGlmZi5yZW1vdmVkQ291bnQsIGRpZmYuYWRkZWRDb3VudCk7CgogICAgICAgIGlmIChpc0luaXRpYWxpemVkICYmIGRpZmYuYWRkZWRDb3VudCA+IDApIHsKICAgICAgICAgIC8vbm90aWZ5IG9ubHkgb24gYWRkaXRpb25zCiAgICAgICAgICAvL1RPRE8gb25seSBub3RpZnkgaWYgdW5sb2FkZWQKICAgICAgICAgIHRoaXMuaW50ZXJuYWxNb2RlbC5tYW55QXJyYXlSZWNvcmRBZGRlZCh0aGlzLmdldCgna2V5JykpOwogICAgICAgIH0KICAgICAgfQogICAgfSwKICAgIHJlcGxhY2U6IGZ1bmN0aW9uIHJlcGxhY2UoaWR4LCBhbXQsIG9iamVjdHMpIHsKICAgICAgdmFyIGludGVybmFsTW9kZWxzOwoKICAgICAgaWYgKGFtdCA+IDApIHsKICAgICAgICBpbnRlcm5hbE1vZGVscyA9IHRoaXMuY3VycmVudFN0YXRlLnNsaWNlKGlkeCwgaWR4ICsgYW10KTsKICAgICAgICB0aGlzLmdldCgncmVjb3JkRGF0YScpLnJlbW92ZUZyb21IYXNNYW55KHRoaXMuZ2V0KCdrZXknKSwgaW50ZXJuYWxNb2RlbHMubWFwKGZ1bmN0aW9uIChpbSkgewogICAgICAgICAgcmV0dXJuIHJlY29yZERhdGFGb3IoaW0pOwogICAgICAgIH0pKTsKICAgICAgfQoKICAgICAgaWYgKG9iamVjdHMpIHsKICAgICAgICB0aGlzLmdldCgncmVjb3JkRGF0YScpLmFkZFRvSGFzTWFueSh0aGlzLmdldCgna2V5JyksIG9iamVjdHMubWFwKGZ1bmN0aW9uIChvYmopIHsKICAgICAgICAgIHJldHVybiByZWNvcmREYXRhRm9yKG9iaik7CiAgICAgICAgfSksIGlkeCk7CiAgICAgIH0KCiAgICAgIHRoaXMucmV0cmlldmVMYXRlc3QoKTsKICAgIH0sCiAgICAvLyBPayB0aGlzIGlzIGtpbmRhIGZ1bmt5IGJlY2F1c2UgaWYgYnVnZ3kgd2UgbWlnaHQgbG9zZSBwb3NpdGlvbnMsIGV0Yy4KICAgIC8vIGJ1dCBjdXJyZW50IGNvZGUgaXMgdGhpcyB3YXkgc28gc2hvdWxkbid0IGJlIHRvbyBiaWcgb2YgYSBwcm9ibGVtCiAgICByZXRyaWV2ZUxhdGVzdDogZnVuY3Rpb24gcmV0cmlldmVMYXRlc3QoKSB7CiAgICAgIHZhciBqc29uQXBpID0gdGhpcy5nZXQoJ3JlY29yZERhdGEnKS5nZXRIYXNNYW55KHRoaXMuZ2V0KCdrZXknKSk7IC8vIFRPRE8gdGhpcyBpcyBvZGQsIHdoeSBzaG91bGQgTWFueUFycmF5IGV2ZXIgdGVsbCBpdHNlbGYgdG8gcmVzeW5jPwoKICAgICAgdmFyIGludGVybmFsTW9kZWxzID0gdGhpcy5zdG9yZS5fZ2V0SGFzTWFueUJ5SnNvbkFwaVJlc291cmNlKGpzb25BcGkpOwoKICAgICAgaWYgKGpzb25BcGkubWV0YSkgewogICAgICAgIHRoaXMuc2V0KCdtZXRhJywganNvbkFwaS5tZXRhKTsKICAgICAgfQoKICAgICAgdGhpcy5mbHVzaENhbm9uaWNhbChpbnRlcm5hbE1vZGVscywgdHJ1ZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBSZWxvYWRzIGFsbCBvZiB0aGUgcmVjb3JkcyBpbiB0aGUgbWFueUFycmF5LiBJZiB0aGUgbWFueUFycmF5CiAgICAgIGhvbGRzIGEgcmVsYXRpb25zaGlwIHRoYXQgd2FzIG9yaWdpbmFsbHkgZmV0Y2hlZCB1c2luZyBhIGxpbmtzIHVybAogICAgICBFbWJlciBEYXRhIHdpbGwgcmV2aXNpdCB0aGUgb3JpZ2luYWwgbGlua3MgdXJsIHRvIHJlcG9wdWxhdGUgdGhlCiAgICAgIHJlbGF0aW9uc2hpcC4KICAgICAgIElmIHRoZSBtYW55QXJyYXkgaG9sZHMgdGhlIHJlc3VsdCBvZiBhIGBzdG9yZS5xdWVyeSgpYCByZWxvYWQgd2lsbAogICAgICByZS1ydW4gdGhlIG9yaWdpbmFsIHF1ZXJ5LgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICB2YXIgdXNlciA9IHN0b3JlLnBlZWtSZWNvcmQoJ3VzZXInLCAxKQogICAgICB1c2VyLmxvZ2luKCkudGhlbihmdW5jdGlvbigpIHsKICAgICAgICB1c2VyLmdldCgncGVybWlzc2lvbnMnKS50aGVuKGZ1bmN0aW9uKHBlcm1pc3Npb25zKSB7CiAgICAgICAgICByZXR1cm4gcGVybWlzc2lvbnMucmVsb2FkKCk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgcmVsb2FkCiAgICAgIEBwdWJsaWMKICAgICovCiAgICByZWxvYWQ6IGZ1bmN0aW9uIHJlbG9hZChvcHRpb25zKSB7CiAgICAgIC8vIFRPRE8gdGhpcyBpcyBvZGQsIHdlIGRvbid0IGFzayB0aGUgc3RvcmUgZm9yIGFueXRoaW5nIGVsc2UgbGlrZSB0aGlzPwogICAgICByZXR1cm4gdGhpcy5nZXQoJ3N0b3JlJykucmVsb2FkTWFueUFycmF5KHRoaXMsIHRoaXMuZ2V0KCdpbnRlcm5hbE1vZGVsJyksIHRoaXMuZ2V0KCdrZXknKSwgb3B0aW9ucyk7CiAgICB9LAoKICAgIC8qKgogICAgICBTYXZlcyBhbGwgb2YgdGhlIHJlY29yZHMgaW4gdGhlIGBNYW55QXJyYXlgLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBzdG9yZS5maW5kUmVjb3JkKCdpbmJveCcsIDEpLnRoZW4oZnVuY3Rpb24oaW5ib3gpIHsKICAgICAgICBpbmJveC5nZXQoJ21lc3NhZ2VzJykudGhlbihmdW5jdGlvbihtZXNzYWdlcykgewogICAgICAgICAgbWVzc2FnZXMuZm9yRWFjaChmdW5jdGlvbihtZXNzYWdlKSB7CiAgICAgICAgICAgIG1lc3NhZ2Uuc2V0KCdpc1JlYWQnLCB0cnVlKTsKICAgICAgICAgIH0pOwogICAgICAgICAgbWVzc2FnZXMuc2F2ZSgpCiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc2F2ZQogICAgICBAcmV0dXJuIHtQcm9taXNlQXJyYXl9IHByb21pc2UKICAgICovCiAgICBzYXZlOiBmdW5jdGlvbiBzYXZlKCkgewogICAgICB2YXIgbWFueUFycmF5ID0gdGhpczsKICAgICAgdmFyIHByb21pc2VMYWJlbCA9ICdEUzogTWFueUFycmF5I3NhdmUgJyArIEVtYmVyLmdldCh0aGlzLCAndHlwZScpOwogICAgICB2YXIgcHJvbWlzZSA9IEVtYmVyLlJTVlAuYWxsKHRoaXMuaW52b2tlKCdzYXZlJyksIHByb21pc2VMYWJlbCkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIG1hbnlBcnJheTsKICAgICAgfSwgbnVsbCwgJ0RTOiBNYW55QXJyYXkjc2F2ZSByZXR1cm4gTWFueUFycmF5Jyk7CiAgICAgIHJldHVybiBQcm9taXNlQXJyYXkuY3JlYXRlKHsKICAgICAgICBwcm9taXNlOiBwcm9taXNlCiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICAgQ3JlYXRlIGEgY2hpbGQgcmVjb3JkIHdpdGhpbiB0aGUgb3duZXIKICAgICAgIEBtZXRob2QgY3JlYXRlUmVjb3JkCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBoYXNoCiAgICAgIEByZXR1cm4ge01vZGVsfSByZWNvcmQKICAgICovCiAgICBjcmVhdGVSZWNvcmQ6IGZ1bmN0aW9uIGNyZWF0ZVJlY29yZChoYXNoKSB7CiAgICAgIHZhciBzdG9yZSA9IEVtYmVyLmdldCh0aGlzLCAnc3RvcmUnKTsKICAgICAgdmFyIHR5cGUgPSBFbWJlci5nZXQodGhpcywgJ3R5cGUnKTsKICAgICAgdmFyIHJlY29yZCA9IHN0b3JlLmNyZWF0ZVJlY29yZCh0eXBlLm1vZGVsTmFtZSwgaGFzaCk7CiAgICAgIHRoaXMucHVzaE9iamVjdChyZWNvcmQpOwogICAgICByZXR1cm4gcmVjb3JkOwogICAgfQogIH0pOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwogIHZhciBTT1VSQ0VfUE9JTlRFUl9SRUdFWFAgPSAvXlwvP2RhdGFcLyhhdHRyaWJ1dGVzfHJlbGF0aW9uc2hpcHMpXC8oLiopLzsKICB2YXIgU09VUkNFX1BPSU5URVJfUFJJTUFSWV9SRUdFWFAgPSAvXlwvP2RhdGEvOwogIHZhciBQUklNQVJZX0FUVFJJQlVURV9LRVkgPSAnYmFzZSc7CiAgLyoqCiAgICBDb252ZXJ0IGFuIGhhc2ggb2YgZXJyb3JzIGludG8gYW4gYXJyYXkgd2l0aCBlcnJvcnMgaW4gSlNPTi1BUEkgZm9ybWF0LgogICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBEUyBmcm9tICdlbWJlci1kYXRhJzsKICAgICBjb25zdCB7IGVycm9yc0hhc2hUb0FycmF5IH0gPSBEUzsKICAgICBsZXQgZXJyb3JzID0gewogICAgICBiYXNlOiAnSW52YWxpZCBhdHRyaWJ1dGVzIG9uIHNhdmluZyB0aGlzIHJlY29yZCcsCiAgICAgIG5hbWU6ICdNdXN0IGJlIHByZXNlbnQnLAogICAgICBhZ2U6IFsnTXVzdCBiZSBwcmVzZW50JywgJ011c3QgYmUgYSBudW1iZXInXQogICAgfTsKICAgICBsZXQgZXJyb3JzQXJyYXkgPSBlcnJvcnNIYXNoVG9BcnJheShlcnJvcnMpOwogICAgLy8gWwogICAgLy8gICB7CiAgICAvLyAgICAgdGl0bGU6ICJJbnZhbGlkIERvY3VtZW50IiwKICAgIC8vICAgICBkZXRhaWw6ICJJbnZhbGlkIGF0dHJpYnV0ZXMgb24gc2F2aW5nIHRoaXMgcmVjb3JkIiwKICAgIC8vICAgICBzb3VyY2U6IHsgcG9pbnRlcjogIi9kYXRhIiB9CiAgICAvLyAgIH0sCiAgICAvLyAgIHsKICAgIC8vICAgICB0aXRsZTogIkludmFsaWQgQXR0cmlidXRlIiwKICAgIC8vICAgICBkZXRhaWw6ICJNdXN0IGJlIHByZXNlbnQiLAogICAgLy8gICAgIHNvdXJjZTogeyBwb2ludGVyOiAiL2RhdGEvYXR0cmlidXRlcy9uYW1lIiB9CiAgICAvLyAgIH0sCiAgICAvLyAgIHsKICAgIC8vICAgICB0aXRsZTogIkludmFsaWQgQXR0cmlidXRlIiwKICAgIC8vICAgICBkZXRhaWw6ICJNdXN0IGJlIHByZXNlbnQiLAogICAgLy8gICAgIHNvdXJjZTogeyBwb2ludGVyOiAiL2RhdGEvYXR0cmlidXRlcy9hZ2UiIH0KICAgIC8vICAgfSwKICAgIC8vICAgewogICAgLy8gICAgIHRpdGxlOiAiSW52YWxpZCBBdHRyaWJ1dGUiLAogICAgLy8gICAgIGRldGFpbDogIk11c3QgYmUgYSBudW1iZXIiLAogICAgLy8gICAgIHNvdXJjZTogeyBwb2ludGVyOiAiL2RhdGEvYXR0cmlidXRlcy9hZ2UiIH0KICAgIC8vICAgfQogICAgLy8gXQogICAgYGBgCiAgICBAbWV0aG9kIGVycm9yc0hhc2hUb0FycmF5CiAgICBAcHVibGljCiAgICBAcGFyYW0ge09iamVjdH0gZXJyb3JzIGhhc2ggd2l0aCBlcnJvcnMgYXMgcHJvcGVydGllcwogICAgQHJldHVybiB7QXJyYXl9IGFycmF5IG9mIGVycm9ycyBpbiBKU09OLUFQSSBmb3JtYXQKICAqLwoKICBmdW5jdGlvbiBlcnJvcnNIYXNoVG9BcnJheShlcnJvcnMpIHsKICAgIHZhciBvdXQgPSBbXTsKCiAgICBpZiAoRW1iZXIuaXNQcmVzZW50KGVycm9ycykpIHsKICAgICAgT2JqZWN0LmtleXMoZXJyb3JzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICB2YXIgbWVzc2FnZXMgPSBFbWJlci5tYWtlQXJyYXkoZXJyb3JzW2tleV0pOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2VzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICB2YXIgdGl0bGUgPSAnSW52YWxpZCBBdHRyaWJ1dGUnOwogICAgICAgICAgdmFyIHBvaW50ZXIgPSAiL2RhdGEvYXR0cmlidXRlcy8iICsga2V5OwoKICAgICAgICAgIGlmIChrZXkgPT09IFBSSU1BUllfQVRUUklCVVRFX0tFWSkgewogICAgICAgICAgICB0aXRsZSA9ICdJbnZhbGlkIERvY3VtZW50JzsKICAgICAgICAgICAgcG9pbnRlciA9ICIvZGF0YSI7CiAgICAgICAgICB9CgogICAgICAgICAgb3V0LnB1c2goewogICAgICAgICAgICB0aXRsZTogdGl0bGUsCiAgICAgICAgICAgIGRldGFpbDogbWVzc2FnZXNbaV0sCiAgICAgICAgICAgIHNvdXJjZTogewogICAgICAgICAgICAgIHBvaW50ZXI6IHBvaW50ZXIKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KCiAgICByZXR1cm4gb3V0OwogIH0KICAvKioKICAgIENvbnZlcnQgYW4gYXJyYXkgb2YgZXJyb3JzIGluIEpTT04tQVBJIGZvcm1hdCBpbnRvIGFuIG9iamVjdC4KCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRFMgZnJvbSAnZW1iZXItZGF0YSc7CgogICAgY29uc3QgeyBlcnJvcnNBcnJheVRvSGFzaCB9ID0gRFM7CgogICAgbGV0IGVycm9yc0FycmF5ID0gWwogICAgICB7CiAgICAgICAgdGl0bGU6ICdJbnZhbGlkIEF0dHJpYnV0ZScsCiAgICAgICAgZGV0YWlsOiAnTXVzdCBiZSBwcmVzZW50JywKICAgICAgICBzb3VyY2U6IHsgcG9pbnRlcjogJy9kYXRhL2F0dHJpYnV0ZXMvbmFtZScgfQogICAgICB9LAogICAgICB7CiAgICAgICAgdGl0bGU6ICdJbnZhbGlkIEF0dHJpYnV0ZScsCiAgICAgICAgZGV0YWlsOiAnTXVzdCBiZSBwcmVzZW50JywKICAgICAgICBzb3VyY2U6IHsgcG9pbnRlcjogJy9kYXRhL2F0dHJpYnV0ZXMvYWdlJyB9CiAgICAgIH0sCiAgICAgIHsKICAgICAgICB0aXRsZTogJ0ludmFsaWQgQXR0cmlidXRlJywKICAgICAgICBkZXRhaWw6ICdNdXN0IGJlIGEgbnVtYmVyJywKICAgICAgICBzb3VyY2U6IHsgcG9pbnRlcjogJy9kYXRhL2F0dHJpYnV0ZXMvYWdlJyB9CiAgICAgIH0KICAgIF07CgogICAgbGV0IGVycm9ycyA9IGVycm9yc0FycmF5VG9IYXNoKGVycm9yc0FycmF5KTsKICAgIC8vIHsKICAgIC8vICAgIm5hbWUiOiBbIk11c3QgYmUgcHJlc2VudCJdLAogICAgLy8gICAiYWdlIjogIFsiTXVzdCBiZSBwcmVzZW50IiwgIm11c3QgYmUgYSBudW1iZXIiXQogICAgLy8gfQogICAgYGBgCgogICAgQG1ldGhvZCBlcnJvcnNBcnJheVRvSGFzaAogICAgQHB1YmxpYwogICAgQHBhcmFtIHtBcnJheX0gZXJyb3JzIGFycmF5IG9mIGVycm9ycyBpbiBKU09OLUFQSSBmb3JtYXQKICAgIEByZXR1cm4ge09iamVjdH0KICAqLwoKICBmdW5jdGlvbiBlcnJvcnNBcnJheVRvSGFzaChlcnJvcnMpIHsKICAgIHZhciBvdXQgPSB7fTsKCiAgICBpZiAoRW1iZXIuaXNQcmVzZW50KGVycm9ycykpIHsKICAgICAgZXJyb3JzLmZvckVhY2goZnVuY3Rpb24gKGVycm9yKSB7CiAgICAgICAgaWYgKGVycm9yLnNvdXJjZSAmJiBlcnJvci5zb3VyY2UucG9pbnRlcikgewogICAgICAgICAgdmFyIGtleSA9IGVycm9yLnNvdXJjZS5wb2ludGVyLm1hdGNoKFNPVVJDRV9QT0lOVEVSX1JFR0VYUCk7CgogICAgICAgICAgaWYgKGtleSkgewogICAgICAgICAgICBrZXkgPSBrZXlbMl07CiAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yLnNvdXJjZS5wb2ludGVyLnNlYXJjaChTT1VSQ0VfUE9JTlRFUl9QUklNQVJZX1JFR0VYUCkgIT09IC0xKSB7CiAgICAgICAgICAgIGtleSA9IFBSSU1BUllfQVRUUklCVVRFX0tFWTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoa2V5KSB7CiAgICAgICAgICAgIG91dFtrZXldID0gb3V0W2tleV0gfHwgW107CiAgICAgICAgICAgIG91dFtrZXldLnB1c2goZXJyb3IuZGV0YWlsIHx8IGVycm9yLnRpdGxlKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgfQoKICAgIHJldHVybiBvdXQ7CiAgfQoKICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyQxKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyQxKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMkMShDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDEoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICAgQGNsYXNzIFNuYXBzaG90UmVjb3JkQXJyYXkKICAgIEBwcml2YXRlCiAgICBAY29uc3RydWN0b3IKICAgIEBwYXJhbSB7QXJyYXl9IHNuYXBzaG90cyBBbiBhcnJheSBvZiBzbmFwc2hvdHMKICAgIEBwYXJhbSB7T2JqZWN0fSBtZXRhCiAgKi8KICB2YXIgU25hcHNob3RSZWNvcmRBcnJheSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFNuYXBzaG90UmVjb3JkQXJyYXkocmVjb3JkQXJyYXksIG1ldGEsIG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgfQoKICAgICAgLyoqCiAgICAgICAgQW4gYXJyYXkgb2Ygc25hcHNob3RzCiAgICAgICAgQHByaXZhdGUKICAgICAgICBAcHJvcGVydHkgX3NuYXBzaG90cwogICAgICAgIEB0eXBlIHtBcnJheX0KICAgICAgKi8KICAgICAgdGhpcy5fc25hcHNob3RzID0gbnVsbDsKICAgICAgLyoqCiAgICAgICAgQW4gYXJyYXkgb2YgcmVjb3JkcwogICAgICAgIEBwcml2YXRlCiAgICAgICAgQHByb3BlcnR5IF9yZWNvcmRBcnJheQogICAgICAgIEB0eXBlIHtBcnJheX0KICAgICAgKi8KCiAgICAgIHRoaXMuX3JlY29yZEFycmF5ID0gcmVjb3JkQXJyYXk7CiAgICAgIC8qKgogICAgICAgIE51bWJlciBvZiByZWNvcmRzIGluIHRoZSBhcnJheQogICAgICAgICBFeGFtcGxlCiAgICAgICAgIGBgYGFwcC9hZGFwdGVycy9wb3N0LmpzCiAgICAgICAgaW1wb3J0IEpTT05BUElBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvanNvbi1hcGknOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OQVBJQWRhcHRlci5leHRlbmQoewogICAgICAgICAgc2hvdWxkUmVsb2FkQWxsKHN0b3JlLCBzbmFwc2hvdFJlY29yZEFycmF5KSB7CiAgICAgICAgICAgIHJldHVybiAhc25hcHNob3RSZWNvcmRBcnJheS5sZW5ndGg7CiAgICAgICAgICB9LAogICAgICAgIH0pOwogICAgICAgIGBgYAogICAgICAgICBAcHJvcGVydHkgbGVuZ3RoCiAgICAgICAgQHR5cGUge051bWJlcn0KICAgICAgKi8KCiAgICAgIHRoaXMubGVuZ3RoID0gcmVjb3JkQXJyYXkuZ2V0KCdsZW5ndGgnKTsKICAgICAgdGhpcy5fdHlwZSA9IG51bGw7CiAgICAgIC8qKgogICAgICAgIE1ldGEgb2JqZWN0cyBmb3IgdGhlIHJlY29yZCBhcnJheS4KICAgICAgICAgRXhhbXBsZQogICAgICAgICBgYGBhcHAvYWRhcHRlcnMvcG9zdC5qcwogICAgICAgIGltcG9ydCBKU09OQVBJQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL2pzb24tYXBpJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTkFQSUFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICAgIHNob3VsZFJlbG9hZEFsbChzdG9yZSwgc25hcHNob3RSZWNvcmRBcnJheSkgewogICAgICAgICAgICB2YXIgbGFzdFJlcXVlc3RUaW1lID0gc25hcHNob3RSZWNvcmRBcnJheS5tZXRhLmxhc3RSZXF1ZXN0VGltZTsKICAgICAgICAgICAgdmFyIHR3ZW50eU1pbnV0ZXMgPSAyMCAqIDYwICogMTAwMDsKICAgICAgICAgICAgcmV0dXJuIERhdGUubm93KCkgPiBsYXN0UmVxdWVzdFRpbWUgKyB0d2VudHlNaW51dGVzOwogICAgICAgICAgfSwKICAgICAgICB9KTsKICAgICAgICBgYGAKICAgICAgICAgQHByb3BlcnR5IG1ldGEKICAgICAgICBAdHlwZSB7T2JqZWN0fQogICAgICAqLwoKICAgICAgdGhpcy5tZXRhID0gbWV0YTsKICAgICAgLyoqCiAgICAgICAgQSBoYXNoIG9mIGFkYXB0ZXIgb3B0aW9ucyBwYXNzZWQgaW50byB0aGUgc3RvcmUgbWV0aG9kIGZvciB0aGlzIHJlcXVlc3QuCiAgICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL2FkYXB0ZXJzL3Bvc3QuanMKICAgICAgICBpbXBvcnQgTXlDdXN0b21BZGFwdGVyIGZyb20gJy4vY3VzdG9tLWFkYXB0ZXInOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBNeUN1c3RvbUFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICAgIGZpbmRBbGwoc3RvcmUsIHR5cGUsIHNpbmNlVG9rZW4sIHNuYXBzaG90UmVjb3JkQXJyYXkpIHsKICAgICAgICAgICAgaWYgKHNuYXBzaG90UmVjb3JkQXJyYXkuYWRhcHRlck9wdGlvbnMuc3Vic2NyaWJlKSB7CiAgICAgICAgICAgICAgLy8gLi4uCiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gLi4uCiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgICAgYGBgCiAgICAgICAgIEBwcm9wZXJ0eSBhZGFwdGVyT3B0aW9ucwogICAgICAgIEB0eXBlIHtPYmplY3R9CiAgICAgICovCgogICAgICB0aGlzLmFkYXB0ZXJPcHRpb25zID0gb3B0aW9ucy5hZGFwdGVyT3B0aW9uczsKICAgICAgLyoqCiAgICAgICAgVGhlIHJlbGF0aW9uc2hpcHMgdG8gaW5jbHVkZSBmb3IgdGhpcyByZXF1ZXN0LgogICAgICAgICBFeGFtcGxlCiAgICAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgICBmaW5kQWxsKHN0b3JlLCB0eXBlLCBzbmFwc2hvdFJlY29yZEFycmF5KSB7CiAgICAgICAgICAgIHZhciB1cmwgPSBgLyR7dHlwZS5tb2RlbE5hbWV9P2luY2x1ZGU9JHtlbmNvZGVVUklDb21wb25lbnQoc25hcHNob3RSZWNvcmRBcnJheS5pbmNsdWRlKX1gOwogICAgICAgICAgICAgcmV0dXJuIGZldGNoKHVybCkudGhlbigocmVzcG9uc2UpID0+IHJlc3BvbnNlLmpzb24oKSkKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgICAgQHByb3BlcnR5IGluY2x1ZGUKICAgICAgICBAdHlwZSB7U3RyaW5nfEFycmF5fQogICAgICAqLwoKICAgICAgdGhpcy5pbmNsdWRlID0gb3B0aW9ucy5pbmNsdWRlOwogICAgfQogICAgLyoqCiAgICAgIFRoZSB0eXBlIG9mIHRoZSB1bmRlcmx5aW5nIHJlY29yZHMgZm9yIHRoZSBzbmFwc2hvdHMgaW4gdGhlIGFycmF5LCBhcyBhIE1vZGVsCiAgICAgIEBwcm9wZXJ0eSB0eXBlCiAgICAgIEB0eXBlIHtNb2RlbH0KICAgICovCgoKICAgIHZhciBfcHJvdG8gPSBTbmFwc2hvdFJlY29yZEFycmF5LnByb3RvdHlwZTsKCiAgICAvKioKICAgICAgR2V0IHNuYXBzaG90cyBvZiB0aGUgdW5kZXJseWluZyByZWNvcmQgYXJyYXkKICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9hZGFwdGVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBKU09OQVBJQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL2pzb24tYXBpJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05BUElBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgc2hvdWxkUmVsb2FkQWxsKHN0b3JlLCBzbmFwc2hvdEFycmF5KSB7CiAgICAgICAgICB2YXIgc25hcHNob3RzID0gc25hcHNob3RBcnJheS5zbmFwc2hvdHMoKTsKICAgICAgICAgICByZXR1cm4gc25hcHNob3RzLmFueShmdW5jdGlvbih0aWNrZXRTbmFwc2hvdCkgewogICAgICAgICAgICB2YXIgdGltZURpZmYgPSBtb21lbnQoKS5kaWZmKHRpY2tldFNuYXBzaG90LmF0dHIoJ2xhc3RBY2Nlc3NlZEF0JyksICdtaW51dGVzJyk7CiAgICAgICAgICAgIGlmICh0aW1lRGlmZiA+IDIwKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc25hcHNob3RzCiAgICAgIEByZXR1cm4ge0FycmF5fSBBcnJheSBvZiBzbmFwc2hvdHMKICAgICovCiAgICBfcHJvdG8uc25hcHNob3RzID0gZnVuY3Rpb24gc25hcHNob3RzKCkgewogICAgICBpZiAodGhpcy5fc25hcHNob3RzICE9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3NuYXBzaG90czsKICAgICAgfQoKICAgICAgdGhpcy5fc25hcHNob3RzID0gdGhpcy5fcmVjb3JkQXJyYXkuX3Rha2VTbmFwc2hvdCgpOwogICAgICByZXR1cm4gdGhpcy5fc25hcHNob3RzOwogICAgfTsKCiAgICBfY3JlYXRlQ2xhc3MkMShTbmFwc2hvdFJlY29yZEFycmF5LCBbewogICAgICBrZXk6ICJ0eXBlIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3R5cGUgfHwgKHRoaXMuX3R5cGUgPSB0aGlzLl9yZWNvcmRBcnJheS5nZXQoJ3R5cGUnKSk7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAgVGhlIG1vZGVsTmFtZSBvZiB0aGUgdW5kZXJseWluZyByZWNvcmRzIGZvciB0aGUgc25hcHNob3RzIGluIHRoZSBhcnJheSwgYXMgYSBNb2RlbAogICAgICAgIEBwcm9wZXJ0eSB0eXBlCiAgICAgICAgQHR5cGUge01vZGVsfQogICAgICAqLwoKICAgIH0sIHsKICAgICAga2V5OiAibW9kZWxOYW1lIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3JlY29yZEFycmF5Lm1vZGVsTmFtZTsKICAgICAgfQogICAgfV0pOwoKICAgIHJldHVybiBTbmFwc2hvdFJlY29yZEFycmF5OwogIH0oKTsKCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KICAvKioKICAgIEEgcmVjb3JkIGFycmF5IGlzIGFuIGFycmF5IHRoYXQgY29udGFpbnMgcmVjb3JkcyBvZiBhIGNlcnRhaW4gbW9kZWxOYW1lLiBUaGUgcmVjb3JkCiAgICBhcnJheSBtYXRlcmlhbGl6ZXMgcmVjb3JkcyBhcyBuZWVkZWQgd2hlbiB0aGV5IGFyZSByZXRyaWV2ZWQgZm9yIHRoZSBmaXJzdAogICAgdGltZS4gWW91IHNob3VsZCBub3QgY3JlYXRlIHJlY29yZCBhcnJheXMgeW91cnNlbGYuIEluc3RlYWQsIGFuIGluc3RhbmNlIG9mCiAgICBgUmVjb3JkQXJyYXlgIG9yIGl0cyBzdWJjbGFzc2VzIHdpbGwgYmUgcmV0dXJuZWQgYnkgeW91ciBhcHBsaWNhdGlvbidzIHN0b3JlCiAgICBpbiByZXNwb25zZSB0byBxdWVyaWVzLgoKICAgIEBjbGFzcyBSZWNvcmRBcnJheQogICAgQGV4dGVuZHMgQXJyYXlQcm94eQogICAgQHVzZXMgRW1iZXIuRXZlbnRlZAogICovCgogIHZhciBSZWNvcmRBcnJheSA9IEVtYmVyLkFycmF5UHJveHkuZXh0ZW5kKERlcHJlY2F0ZWRFdmVudGVkLCB7CiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewoKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgICAgLyoqCiAgICAgICAgVGhlIGFycmF5IG9mIGNsaWVudCBpZHMgYmFja2luZyB0aGUgcmVjb3JkIGFycmF5LiBXaGVuIGEKICAgICAgICByZWNvcmQgaXMgcmVxdWVzdGVkIGZyb20gdGhlIHJlY29yZCBhcnJheSwgdGhlIHJlY29yZAogICAgICAgIGZvciB0aGUgY2xpZW50IGlkIGF0IHRoZSBzYW1lIGluZGV4IGlzIG1hdGVyaWFsaXplZCwgaWYKICAgICAgICBuZWNlc3NhcnksIGJ5IHRoZSBzdG9yZS4KICAgICAgICAgQHByb3BlcnR5IGNvbnRlbnQKICAgICAgICBAcHJpdmF0ZQogICAgICAgIEB0eXBlIEVtYmVyLkFycmF5CiAgICAgICAgKi8KCgogICAgICB0aGlzLnNldCgnY29udGVudCcsIHRoaXMuY29udGVudCB8fCBudWxsKTsKICAgICAgLyoqCiAgICAgIFRoZSBmbGFnIHRvIHNpZ25hbCBhIGBSZWNvcmRBcnJheWAgaXMgZmluaXNoZWQgbG9hZGluZyBkYXRhLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICB2YXIgcGVvcGxlID0gc3RvcmUucGVla0FsbCgncGVyc29uJyk7CiAgICAgIHBlb3BsZS5nZXQoJ2lzTG9hZGVkJyk7IC8vIHRydWUKICAgICAgYGBgCiAgICAgICBAcHJvcGVydHkgaXNMb2FkZWQKICAgICAgQHR5cGUgQm9vbGVhbgogICAgICAqLwoKICAgICAgdGhpcy5pc0xvYWRlZCA9IHRoaXMuaXNMb2FkZWQgfHwgZmFsc2U7CiAgICAgIC8qKgogICAgICBUaGUgZmxhZyB0byBzaWduYWwgYSBgUmVjb3JkQXJyYXlgIGlzIGN1cnJlbnRseSBsb2FkaW5nIGRhdGEuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHZhciBwZW9wbGUgPSBzdG9yZS5wZWVrQWxsKCdwZXJzb24nKTsKICAgICAgcGVvcGxlLmdldCgnaXNVcGRhdGluZycpOyAvLyBmYWxzZQogICAgICBwZW9wbGUudXBkYXRlKCk7CiAgICAgIHBlb3BsZS5nZXQoJ2lzVXBkYXRpbmcnKTsgLy8gdHJ1ZQogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBpc1VwZGF0aW5nCiAgICAgIEB0eXBlIEJvb2xlYW4KICAgICAgKi8KCiAgICAgIHRoaXMuaXNVcGRhdGluZyA9IGZhbHNlOwogICAgICAvKioKICAgICAgVGhlIHN0b3JlIHRoYXQgY3JlYXRlZCB0aGlzIHJlY29yZCBhcnJheS4KICAgICAgIEBwcm9wZXJ0eSBzdG9yZQogICAgICBAcHJpdmF0ZQogICAgICBAdHlwZSBTdG9yZQogICAgICAqLwoKICAgICAgdGhpcy5zdG9yZSA9IHRoaXMuc3RvcmUgfHwgbnVsbDsKICAgICAgdGhpcy5fdXBkYXRpbmdQcm9taXNlID0gbnVsbDsKICAgIH0sCiAgICByZXBsYWNlOiBmdW5jdGlvbiByZXBsYWNlKCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIlRoZSByZXN1bHQgb2YgYSBzZXJ2ZXIgcXVlcnkgKGZvciBhbGwgIiArIHRoaXMubW9kZWxOYW1lICsgIiB0eXBlcykgaXMgaW1tdXRhYmxlLiBUbyBtb2RpZnkgY29udGVudHMsIHVzZSB0b0FycmF5KCkiKTsKICAgIH0sCgogICAgLyoqCiAgICAgVGhlIG1vZGVsQ2xhc3MgcmVwcmVzZW50ZWQgYnkgdGhpcyByZWNvcmQgYXJyYXkuCiAgICAgIEBwcm9wZXJ0eSB0eXBlCiAgICAgQHR5cGUgTW9kZWwKICAgICAqLwogICAgdHlwZTogRW1iZXIuY29tcHV0ZWQoJ21vZGVsTmFtZScsIGZ1bmN0aW9uICgpIHsKICAgICAgaWYgKCF0aGlzLm1vZGVsTmFtZSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5zdG9yZS5tb2RlbEZvcih0aGlzLm1vZGVsTmFtZSk7CiAgICB9KS5yZWFkT25seSgpLAoKICAgIC8qKgogICAgICBSZXRyaWV2ZXMgYW4gb2JqZWN0IGZyb20gdGhlIGNvbnRlbnQgYnkgaW5kZXguCiAgICAgICBAbWV0aG9kIG9iamVjdEF0Q29udGVudAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge051bWJlcn0gaW5kZXgKICAgICAgQHJldHVybiB7TW9kZWx9IHJlY29yZAogICAgKi8KICAgIG9iamVjdEF0Q29udGVudDogZnVuY3Rpb24gb2JqZWN0QXRDb250ZW50KGluZGV4KSB7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gRW1iZXIuZ2V0KHRoaXMsICdjb250ZW50Jykub2JqZWN0QXQoaW5kZXgpOwogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbCAmJiBpbnRlcm5hbE1vZGVsLmdldFJlY29yZCgpOwogICAgfSwKCiAgICAvKioKICAgICAgVXNlZCB0byBnZXQgdGhlIGxhdGVzdCB2ZXJzaW9uIG9mIGFsbCBvZiB0aGUgcmVjb3JkcyBpbiB0aGlzIGFycmF5CiAgICAgIGZyb20gdGhlIGFkYXB0ZXIuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHZhciBwZW9wbGUgPSBzdG9yZS5wZWVrQWxsKCdwZXJzb24nKTsKICAgICAgcGVvcGxlLmdldCgnaXNVcGRhdGluZycpOyAvLyBmYWxzZQogICAgICAgcGVvcGxlLnVwZGF0ZSgpLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgICAgcGVvcGxlLmdldCgnaXNVcGRhdGluZycpOyAvLyBmYWxzZQogICAgICB9KTsKICAgICAgIHBlb3BsZS5nZXQoJ2lzVXBkYXRpbmcnKTsgLy8gdHJ1ZQogICAgICBgYGAKICAgICAgIEBtZXRob2QgdXBkYXRlCiAgICAqLwogICAgdXBkYXRlOiBmdW5jdGlvbiB1cGRhdGUoKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgaWYgKEVtYmVyLmdldCh0aGlzLCAnaXNVcGRhdGluZycpKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3VwZGF0aW5nUHJvbWlzZTsKICAgICAgfQoKICAgICAgdGhpcy5zZXQoJ2lzVXBkYXRpbmcnLCB0cnVlKTsKCiAgICAgIHZhciB1cGRhdGluZ1Byb21pc2UgPSB0aGlzLl91cGRhdGUoKS5maW5hbGx5KGZ1bmN0aW9uICgpIHsKICAgICAgICBfdGhpczIuX3VwZGF0aW5nUHJvbWlzZSA9IG51bGw7CgogICAgICAgIGlmIChfdGhpczIuZ2V0KCdpc0Rlc3Ryb3lpbmcnKSB8fCBfdGhpczIuZ2V0KCdpc0Rlc3Ryb3llZCcpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBfdGhpczIuc2V0KCdpc1VwZGF0aW5nJywgZmFsc2UpOwogICAgICB9KTsKCiAgICAgIHRoaXMuX3VwZGF0aW5nUHJvbWlzZSA9IHVwZGF0aW5nUHJvbWlzZTsKICAgICAgcmV0dXJuIHVwZGF0aW5nUHJvbWlzZTsKICAgIH0sCgogICAgLyoKICAgICAgVXBkYXRlIHRoaXMgUmVjb3JkQXJyYXkgYW5kIHJldHVybiBhIHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgb25jZSB0aGUgdXBkYXRlCiAgICAgIGlzIGZpbmlzaGVkLgogICAgICovCiAgICBfdXBkYXRlOiBmdW5jdGlvbiBfdXBkYXRlKCkgewogICAgICByZXR1cm4gdGhpcy5zdG9yZS5maW5kQWxsKHRoaXMubW9kZWxOYW1lLCB7CiAgICAgICAgcmVsb2FkOiB0cnVlCiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICAgQWRkcyBhbiBpbnRlcm5hbCBtb2RlbCB0byB0aGUgYFJlY29yZEFycmF5YCB3aXRob3V0IGR1cGxpY2F0ZXMKICAgICAgIEBtZXRob2QgX3B1c2hJbnRlcm5hbE1vZGVscwogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge0ludGVybmFsTW9kZWx9IGludGVybmFsTW9kZWwKICAgICovCiAgICBfcHVzaEludGVybmFsTW9kZWxzOiBmdW5jdGlvbiBfcHVzaEludGVybmFsTW9kZWxzKGludGVybmFsTW9kZWxzKSB7CiAgICAgIC8vIHB1c2hPYmplY3RzIGJlY2F1c2UgdGhlIGludGVybmFsTW9kZWxzLl9yZWNvcmRBcnJheXMgc2V0IHdhcyBhbHJlYWR5CiAgICAgIC8vIGNvbnN1bHRlZCBmb3IgaW5jbHVzaW9uLCBzbyBhZGRPYmplY3QgYW5kIGl0cyBvbiAuY29udGFpbnMgY2FsbCBpcyBub3QKICAgICAgLy8gcmVxdWlyZWQuCiAgICAgIEVtYmVyLmdldCh0aGlzLCAnY29udGVudCcpLnB1c2hPYmplY3RzKGludGVybmFsTW9kZWxzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFJlbW92ZXMgYW4gaW50ZXJuYWxNb2RlbCB0byB0aGUgYFJlY29yZEFycmF5YC4KICAgICAgIEBtZXRob2QgcmVtb3ZlSW50ZXJuYWxNb2RlbAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge0ludGVybmFsTW9kZWx9IGludGVybmFsTW9kZWwKICAgICovCiAgICBfcmVtb3ZlSW50ZXJuYWxNb2RlbHM6IGZ1bmN0aW9uIF9yZW1vdmVJbnRlcm5hbE1vZGVscyhpbnRlcm5hbE1vZGVscykgewogICAgICBFbWJlci5nZXQodGhpcywgJ2NvbnRlbnQnKS5yZW1vdmVPYmplY3RzKGludGVybmFsTW9kZWxzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFNhdmVzIGFsbCBvZiB0aGUgcmVjb3JkcyBpbiB0aGUgYFJlY29yZEFycmF5YC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgdmFyIG1lc3NhZ2VzID0gc3RvcmUucGVla0FsbCgnbWVzc2FnZScpOwogICAgICBtZXNzYWdlcy5mb3JFYWNoKGZ1bmN0aW9uKG1lc3NhZ2UpIHsKICAgICAgICBtZXNzYWdlLnNldCgnaGFzQmVlblNlZW4nLCB0cnVlKTsKICAgICAgfSk7CiAgICAgIG1lc3NhZ2VzLnNhdmUoKTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHNhdmUKICAgICAgQHJldHVybiB7UHJvbWlzZUFycmF5fSBwcm9taXNlCiAgICAqLwogICAgc2F2ZTogZnVuY3Rpb24gc2F2ZSgpIHsKICAgICAgdmFyIF90aGlzMyA9IHRoaXM7CgogICAgICB2YXIgcHJvbWlzZUxhYmVsID0gIkRTOiBSZWNvcmRBcnJheSNzYXZlICIgKyB0aGlzLm1vZGVsTmFtZTsKICAgICAgdmFyIHByb21pc2UgPSBFbWJlci5SU1ZQLlByb21pc2UuYWxsKHRoaXMuaW52b2tlKCdzYXZlJyksIHByb21pc2VMYWJlbCkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIF90aGlzMzsKICAgICAgfSwgbnVsbCwgJ0RTOiBSZWNvcmRBcnJheSNzYXZlIHJldHVybiBSZWNvcmRBcnJheScpOwogICAgICByZXR1cm4gUHJvbWlzZUFycmF5LmNyZWF0ZSh7CiAgICAgICAgcHJvbWlzZTogcHJvbWlzZQogICAgICB9KTsKICAgIH0sCiAgICBfZGlzc29jaWF0ZUZyb21Pd25SZWNvcmRzOiBmdW5jdGlvbiBfZGlzc29jaWF0ZUZyb21Pd25SZWNvcmRzKCkgewogICAgICB2YXIgX3RoaXM0ID0gdGhpczsKCiAgICAgIHRoaXMuZ2V0KCdjb250ZW50JykuZm9yRWFjaChmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIHZhciByZWNvcmRBcnJheXMgPSBpbnRlcm5hbE1vZGVsLl9fcmVjb3JkQXJyYXlzOwoKICAgICAgICBpZiAocmVjb3JkQXJyYXlzKSB7CiAgICAgICAgICByZWNvcmRBcnJheXMuZGVsZXRlKF90aGlzNCk7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBtZXRob2QgX3VucmVnaXN0ZXJGcm9tTWFuYWdlcgogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF91bnJlZ2lzdGVyRnJvbU1hbmFnZXI6IGZ1bmN0aW9uIF91bnJlZ2lzdGVyRnJvbU1hbmFnZXIoKSB7CiAgICAgIHRoaXMubWFuYWdlci51bnJlZ2lzdGVyUmVjb3JkQXJyYXkodGhpcyk7CiAgICB9LAogICAgd2lsbERlc3Ryb3k6IGZ1bmN0aW9uIHdpbGxEZXN0cm95KCkgewogICAgICB0aGlzLl91bnJlZ2lzdGVyRnJvbU1hbmFnZXIoKTsKCiAgICAgIHRoaXMuX2Rpc3NvY2lhdGVGcm9tT3duUmVjb3JkcygpOyAvLyBUT0RPOiB3ZSBzaG91bGQgbm90IGRvIHdvcmsgZHVyaW5nIGRlc3Ryb3k6CiAgICAgIC8vICAgKiB3aGVuIG9iamVjdHMgYXJlIGRlc3Ryb3llZCwgdGhleSBzaG91bGQgc2ltcGx5IGJlIGxlZnQgdG8gZG8KICAgICAgLy8gICAqIGlmIGxvZ2ljIGVycm9ycyBkbyB0byB0aGlzLCB0aGF0IGxvZ2ljIG5lZWRzIHRvIGJlIG1vcmUgY2FyZWZ1bCBkdXJpbmcKICAgICAgLy8gICAgdGVhcmRvd24gKGVtYmVyIHByb3ZpZGVzIGlzRGVzdHJveWluZy9pc0Rlc3Ryb3llZCkgZm9yIHRoaXMgcmVhc29uCiAgICAgIC8vICAgKiB0aGUgZXhjZXB0aW9uIGJlaW5nOiBpZiBhbiBkb21pbmF0b3IgaGFzIGEgcmVmZXJlbmNlIHRvIHRoaXMgb2JqZWN0LAogICAgICAvLyAgICAgYW5kIG11c3QgYmUgaW5mb3JtZWQgdG8gcmVsZWFzZSBlLmcuIGUuZy4gcmVtb3ZpbmcgaXRzZWxmIGZyb20gdGgKICAgICAgLy8gICAgIHJlY29yZEFycmF5TWFuYW5nZXIKCgogICAgICBFbWJlci5zZXQodGhpcywgJ2NvbnRlbnQnLCBudWxsKTsKICAgICAgRW1iZXIuc2V0KHRoaXMsICdsZW5ndGgnLCAwKTsKCiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qCiAgICAgIEBtZXRob2QgX2NyZWF0ZVNuYXBzaG90CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX2NyZWF0ZVNuYXBzaG90OiBmdW5jdGlvbiBfY3JlYXRlU25hcHNob3Qob3B0aW9ucykgewogICAgICAvLyB0aGlzIGlzIHByaXZhdGUgZm9yIHVzZXJzLCBidXQgcHVibGljIGZvciBlbWJlci1kYXRhIGludGVybmFscwogICAgICByZXR1cm4gbmV3IFNuYXBzaG90UmVjb3JkQXJyYXkodGhpcywgdGhpcy5nZXQoJ21ldGEnKSwgb3B0aW9ucyk7CiAgICB9LAoKICAgIC8qCiAgICAgIEBtZXRob2QgX3Rha2VTbmFwc2hvdAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF90YWtlU25hcHNob3Q6IGZ1bmN0aW9uIF90YWtlU25hcHNob3QoKSB7CiAgICAgIHJldHVybiBFbWJlci5nZXQodGhpcywgJ2NvbnRlbnQnKS5tYXAoZnVuY3Rpb24gKGludGVybmFsTW9kZWwpIHsKICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdCgpOwogICAgICB9KTsKICAgIH0KICB9KTsKCiAgZnVuY3Rpb24gaXNSZXNvdXJjZUlkZW50aWZlcldpdGhSZWxhdGVkTGlua3ModmFsdWUpIHsKICAgIHJldHVybiB2YWx1ZSAmJiB2YWx1ZS5saW5rcyAmJiB2YWx1ZS5saW5rcy5yZWxhdGVkOwogIH0KICAvKioKICAgIFRoaXMgaXMgdGhlIGJhc2VDbGFzcyBmb3IgdGhlIGRpZmZlcmVudCBSZWZlcmVuY2VzCiAgICBsaWtlIFJlY29yZFJlZmVyZW5jZS9IYXNNYW55UmVmZXJlbmNlL0JlbG9uZ3NUb1JlZmVyZW5jZQoKICAgQGNsYXNzIFJlZmVyZW5jZQogICAqLwoKCiAgdmFyIFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJlZmVyZW5jZShzdG9yZSwgaW50ZXJuYWxNb2RlbCkgewogICAgICB0aGlzLnN0b3JlID0gc3RvcmU7CiAgICAgIHRoaXMuaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWw7CiAgICAgIHRoaXMucmVjb3JkRGF0YSA9IHZvaWQgMDsKICAgICAgdGhpcy5yZWNvcmREYXRhID0gcmVjb3JkRGF0YUZvcih0aGlzKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uX3Jlc291cmNlID0gZnVuY3Rpb24gX3Jlc291cmNlKCkge30KICAgIC8qKgogICAgIFRoaXMgcmV0dXJucyBhIHN0cmluZyB0aGF0IHJlcHJlc2VudHMgaG93IHRoZSByZWZlcmVuY2Ugd2lsbCBiZQogICAgIGxvb2tlZCB1cCB3aGVuIGl0IGlzIGxvYWRlZC4gSWYgdGhlIHJlbGF0aW9uc2hpcCBoYXMgYSBsaW5rIGl0IHdpbGwKICAgICB1c2UgdGhlICJsaW5rIiBvdGhlcndpc2UgaXQgZGVmYXVsdHMgdG8gImlkIi4KICAgICAgRXhhbXBsZQogICAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgIGNvbW1lbnRzOiBoYXNNYW55KHsgYXN5bmM6IHRydWUgfSkKICAgICB9KTsKICAgICBgYGAKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGxldCBwb3N0ID0gc3RvcmUucHVzaCh7CiAgICAgICBkYXRhOiB7CiAgICAgICAgIHR5cGU6ICdwb3N0JywKICAgICAgICAgaWQ6IDEsCiAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICBjb21tZW50czogewogICAgICAgICAgICAgZGF0YTogW3sgdHlwZTogJ2NvbW1lbnQnLCBpZDogMSB9XQogICAgICAgICAgIH0KICAgICAgICAgfQogICAgICAgfQogICAgIH0pOwogICAgICBsZXQgY29tbWVudHNSZWYgPSBwb3N0Lmhhc01hbnkoJ2NvbW1lbnRzJyk7CiAgICAgIC8vIGdldCB0aGUgaWRlbnRpZmllciBvZiB0aGUgcmVmZXJlbmNlCiAgICAgaWYgKGNvbW1lbnRzUmVmLnJlbW90ZVR5cGUoKSA9PT0gImlkcyIpIHsKICAgICAgIGxldCBpZHMgPSBjb21tZW50c1JlZi5pZHMoKTsKICAgICB9IGVsc2UgaWYgKGNvbW1lbnRzUmVmLnJlbW90ZVR5cGUoKSA9PT0gImxpbmsiKSB7CiAgICAgICBsZXQgbGluayA9IGNvbW1lbnRzUmVmLmxpbmsoKTsKICAgICB9CiAgICAgYGBgCiAgICAgIEBtZXRob2QgcmVtb3RlVHlwZQogICAgIEByZXR1cm4ge1N0cmluZ30gVGhlIG5hbWUgb2YgdGhlIHJlbW90ZSB0eXBlLiBUaGlzIHNob3VsZCBlaXRoZXIgYmUgImxpbmsiIG9yICJpZHMiCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVtb3RlVHlwZSA9IGZ1bmN0aW9uIHJlbW90ZVR5cGUoKSB7CiAgICAgIHZhciB2YWx1ZSA9IHRoaXMuX3Jlc291cmNlKCk7CgogICAgICBpZiAoaXNSZXNvdXJjZUlkZW50aWZlcldpdGhSZWxhdGVkTGlua3ModmFsdWUpKSB7CiAgICAgICAgcmV0dXJuICdsaW5rJzsKICAgICAgfQoKICAgICAgcmV0dXJuICdpZCc7CiAgICB9CiAgICAvKioKICAgICBUaGUgbGluayBFbWJlciBEYXRhIHdpbGwgdXNlIHRvIGZldGNoIG9yIHJlbG9hZCB0aGlzIGJlbG9uZ3MtdG8KICAgICByZWxhdGlvbnNoaXAuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgamF2YXNjcmlwdAogICAgIC8vIG1vZGVscy9ibG9nLmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIHVzZXI6IGJlbG9uZ3NUbyh7IGFzeW5jOiB0cnVlIH0pCiAgICAgIH0pOwogICAgICBsZXQgYmxvZyA9IHN0b3JlLnB1c2goewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIHR5cGU6ICdibG9nJywKICAgICAgICAgIGlkOiAxLAogICAgICAgICAgcmVsYXRpb25zaGlwczogewogICAgICAgICAgICB1c2VyOiB7CiAgICAgICAgICAgICAgbGlua3M6IHsKICAgICAgICAgICAgICAgIHJlbGF0ZWQ6ICcvYXJ0aWNsZXMvMS9hdXRob3InCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICBsZXQgdXNlclJlZiA9IGJsb2cuYmVsb25nc1RvKCd1c2VyJyk7CiAgICAgIC8vIGdldCB0aGUgaWRlbnRpZmllciBvZiB0aGUgcmVmZXJlbmNlCiAgICAgaWYgKHVzZXJSZWYucmVtb3RlVHlwZSgpID09PSAibGluayIpIHsKICAgICAgICBsZXQgbGluayA9IHVzZXJSZWYubGluaygpOwogICAgICB9CiAgICAgYGBgCiAgICAgIEBtZXRob2QgbGluawogICAgIEByZXR1cm4ge1N0cmluZ30gVGhlIGxpbmsgRW1iZXIgRGF0YSB3aWxsIHVzZSB0byBmZXRjaCBvciByZWxvYWQgdGhpcyBiZWxvbmdzLXRvIHJlbGF0aW9uc2hpcC4KICAgICAqLwogICAgOwoKICAgIF9wcm90by5saW5rID0gZnVuY3Rpb24gbGluaygpIHsKICAgICAgdmFyIGxpbmsgPSBudWxsOwoKICAgICAgdmFyIHJlc291cmNlID0gdGhpcy5fcmVzb3VyY2UoKTsKCiAgICAgIGlmIChpc1Jlc291cmNlSWRlbnRpZmVyV2l0aFJlbGF0ZWRMaW5rcyhyZXNvdXJjZSkpIHsKICAgICAgICBpZiAocmVzb3VyY2UubGlua3MpIHsKICAgICAgICAgIGxpbmsgPSByZXNvdXJjZS5saW5rcy5yZWxhdGVkOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGxpbms7CiAgICB9CiAgICAvKioKICAgICBUaGUgbWV0YSBkYXRhIGZvciB0aGUgYmVsb25ncy10byByZWxhdGlvbnNoaXAuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgamF2YXNjcmlwdAogICAgIC8vIG1vZGVscy9ibG9nLmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIHVzZXI6IGJlbG9uZ3NUbyh7IGFzeW5jOiB0cnVlIH0pCiAgICAgIH0pOwogICAgICBsZXQgYmxvZyA9IHN0b3JlLnB1c2goewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIHR5cGU6ICdibG9nJywKICAgICAgICAgIGlkOiAxLAogICAgICAgICAgcmVsYXRpb25zaGlwczogewogICAgICAgICAgICB1c2VyOiB7CiAgICAgICAgICAgICAgbGlua3M6IHsKICAgICAgICAgICAgICAgIHJlbGF0ZWQ6IHsKICAgICAgICAgICAgICAgICAgaHJlZjogJy9hcnRpY2xlcy8xL2F1dGhvcicKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICBtZXRhOiB7CiAgICAgICAgICAgICAgICAgIGxhc3RVcGRhdGVkOiAxNDU4MDE0NDAwMDAwCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgbGV0IHVzZXJSZWYgPSBibG9nLmJlbG9uZ3NUbygndXNlcicpOwogICAgICB1c2VyUmVmLm1ldGEoKSAvLyB7IGxhc3RVcGRhdGVkOiAxNDU4MDE0NDAwMDAwIH0KICAgICBgYGAKICAgICAgQG1ldGhvZCBtZXRhCiAgICAgQHJldHVybiB7T2JqZWN0fSBUaGUgbWV0YSBpbmZvcm1hdGlvbiBmb3IgdGhlIGJlbG9uZ3MtdG8gcmVsYXRpb25zaGlwLgogICAgICovCiAgICA7CgogICAgX3Byb3RvLm1ldGEgPSBmdW5jdGlvbiBtZXRhKCkgewogICAgICB2YXIgbWV0YSA9IG51bGw7CgogICAgICB2YXIgcmVzb3VyY2UgPSB0aGlzLl9yZXNvdXJjZSgpOwoKICAgICAgaWYgKHJlc291cmNlICYmIHJlc291cmNlLm1ldGEgJiYgdHlwZW9mIHJlc291cmNlLm1ldGEgPT09ICdvYmplY3QnKSB7CiAgICAgICAgbWV0YSA9IHJlc291cmNlLm1ldGE7CiAgICAgIH0KCiAgICAgIHJldHVybiBtZXRhOwogICAgfTsKCiAgICByZXR1cm4gUmVmZXJlbmNlOwogIH0oKTsKCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXMkMih0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgidmFsdWUiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfQoKICBmdW5jdGlvbiBfY3JlYXRlQ2xhc3MkMihDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDIoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQyKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfQoKICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZShzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MucHJvdG90eXBlKTsgc3ViQ2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gc3ViQ2xhc3M7IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH0KCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KCiAgLyoqCiAgICAgQSBgUmVjb3JkUmVmZXJlbmNlYCBpcyBhIGxvdy1sZXZlbCBBUEkgdGhhdCBhbGxvd3MgdXNlcnMgYW5kCiAgICAgYWRkb24gYXV0aG9ycyB0byBwZXJmb3JtIG1ldGEtb3BlcmF0aW9ucyBvbiBhIHJlY29yZC4KCiAgICAgQGNsYXNzIFJlY29yZFJlZmVyZW5jZQogICAgIEBleHRlbmRzIFJlZmVyZW5jZQogICovCiAgdmFyIFJlY29yZFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfUmVmZXJlbmNlKSB7CiAgICBfaW5oZXJpdHNMb29zZShSZWNvcmRSZWZlcmVuY2UsIF9SZWZlcmVuY2UpOwoKICAgIGZ1bmN0aW9uIFJlY29yZFJlZmVyZW5jZSgpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgICAgfQoKICAgICAgX3RoaXMgPSBfUmVmZXJlbmNlLmNhbGwuYXBwbHkoX1JlZmVyZW5jZSwgW3RoaXNdLmNvbmNhdChhcmdzKSkgfHwgdGhpczsKICAgICAgX3RoaXMudHlwZSA9IF90aGlzLmludGVybmFsTW9kZWwubW9kZWxOYW1lOwogICAgICByZXR1cm4gX3RoaXM7CiAgICB9CgogICAgdmFyIF9wcm90byA9IFJlY29yZFJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgLyoqCiAgICAgICBUaGUgYGlkYCBvZiB0aGUgcmVjb3JkIHRoYXQgdGhpcyByZWZlcmVuY2UgcmVmZXJzIHRvLgogICAgICAgIFRvZ2V0aGVyLCB0aGUgYHR5cGVgIGFuZCBgaWRgIHByb3BlcnRpZXMgZm9ybSBhIGNvbXBvc2l0ZSBrZXkgZm9yCiAgICAgICB0aGUgaWRlbnRpdHkgbWFwLgogICAgICAgIEV4YW1wbGUKICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgICBsZXQgdXNlclJlZiA9IHN0b3JlLmdldFJlZmVyZW5jZSgndXNlcicsIDEpOwogICAgICAgIHVzZXJSZWYuaWQoKTsgLy8gJzEnCiAgICAgICBgYGAKICAgICAgICBAbWV0aG9kIGlkCiAgICAgICBAcmV0dXJuIHtTdHJpbmd9IFRoZSBpZCBvZiB0aGUgcmVjb3JkLgogICAgKi8KICAgIF9wcm90by5pZCA9IGZ1bmN0aW9uIGlkKCkgewogICAgICByZXR1cm4gdGhpcy5faWQ7CiAgICB9CiAgICAvKioKICAgICAgIEhvdyB0aGUgcmVmZXJlbmNlIHdpbGwgYmUgbG9va2VkIHVwIHdoZW4gaXQgaXMgbG9hZGVkLiBDdXJyZW50bHkKICAgICAgIHRoaXMgYWx3YXlzIHJldHVybnMgYGlkZW50aXR5YCB0byBzaWduaWZ5IHRoYXQgYSByZWNvcmQgd2lsbCBiZQogICAgICAgbG9hZGVkIGJ5IGl0cyBgdHlwZWAgYW5kIGBpZGAuCiAgICAgICAgRXhhbXBsZQogICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgIGNvbnN0IHVzZXJSZWYgPSBzdG9yZS5nZXRSZWZlcmVuY2UoJ3VzZXInLCAxKTsKICAgICAgICB1c2VyUmVmLnJlbW90ZVR5cGUoKTsgLy8gJ2lkZW50aXR5JwogICAgICAgYGBgCiAgICAgICAgQG1ldGhvZCByZW1vdGVUeXBlCiAgICAgICBAcmV0dXJuIHtTdHJpbmd9ICdpZGVudGl0eScKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlbW90ZVR5cGUgPSBmdW5jdGlvbiByZW1vdGVUeXBlKCkgewogICAgICByZXR1cm4gJ2lkZW50aXR5JzsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIEFQSSBhbGxvd3MgeW91IHRvIHByb3ZpZGUgYSByZWZlcmVuY2Ugd2l0aCBuZXcgZGF0YS4gVGhlCiAgICAgIHNpbXBsZXN0IHVzYWdlIG9mIHRoaXMgQVBJIGlzIHNpbWlsYXIgdG8gYHN0b3JlLnB1c2hgOiB5b3UgcHJvdmlkZSBhCiAgICAgIG5vcm1hbGl6ZWQgaGFzaCBvZiBkYXRhIGFuZCB0aGUgb2JqZWN0IHJlcHJlc2VudGVkIGJ5IHRoZSByZWZlcmVuY2UKICAgICAgd2lsbCB1cGRhdGUuCiAgICAgICBJZiB5b3UgcGFzcyBhIHByb21pc2UgdG8gYHB1c2hgLCBFbWJlciBEYXRhIHdpbGwgbm90IGFzayB0aGUgYWRhcHRlcgogICAgICBmb3IgdGhlIGRhdGEgaWYgYW5vdGhlciBhdHRlbXB0IHRvIGZldGNoIGl0IGlzIG1hZGUgaW4gdGhlCiAgICAgIGludGVyaW0uIFdoZW4gdGhlIHByb21pc2UgcmVzb2x2ZXMsIHRoZSB1bmRlcmx5aW5nIG9iamVjdCBpcyB1cGRhdGVkCiAgICAgIHdpdGggdGhlIG5ldyBkYXRhLCBhbmQgdGhlIHByb21pc2UgcmV0dXJuZWQgYnkgKnRoaXMgZnVuY3Rpb24qIGlzIHJlc29sdmVkCiAgICAgIHdpdGggdGhhdCBvYmplY3QuCiAgICAgICBGb3IgZXhhbXBsZSwgYHJlY29yZFJlZmVyZW5jZS5wdXNoKHByb21pc2UpYCB3aWxsIGJlIHJlc29sdmVkIHdpdGggYQogICAgICByZWNvcmQuCiAgICAgICAgRXhhbXBsZQogICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgIGxldCB1c2VyUmVmID0gc3RvcmUuZ2V0UmVmZXJlbmNlKCd1c2VyJywgMSk7CiAgICAgICAgLy8gcHJvdmlkZSBkYXRhIGZvciByZWZlcmVuY2UKICAgICAgIHVzZXJSZWYucHVzaCh7CiAgICAgICAgIGRhdGE6IHsKICAgICAgICAgICBpZDogIjEiLAogICAgICAgICAgIHR5cGU6ICJ1c2VyIiwKICAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgICB1c2VybmFtZTogIkB1c2VyIgogICAgICAgICAgIH0KICAgICAgICAgfQogICAgICAgfSkudGhlbihmdW5jdGlvbih1c2VyKSB7CiAgICAgICAgIHVzZXJSZWYudmFsdWUoKSA9PT0gdXNlcjsKICAgICAgIH0pOwogICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHB1c2gKICAgICAgQHBhcmFtIG9iamVjdE9yUHJvbWlzZSBhIEpTT046QVBJIFJlc291cmNlRG9jdW1lbnQgb3IgYSBwcm9taXNlIHJlc29sdmluZyB0byBvbmUKICAgICAgQHJldHVybiBhIHByb21pc2UgZm9yIHRoZSB2YWx1ZSAocmVjb3JkIG9yIHJlbGF0aW9uc2hpcCkKICAgICovCiAgICA7CgogICAgX3Byb3RvLnB1c2ggPSBmdW5jdGlvbiBwdXNoKG9iamVjdE9yUHJvbWlzZSkgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIHJldHVybiBFbWJlci5SU1ZQLnJlc29sdmUob2JqZWN0T3JQcm9taXNlKS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgICAgcmV0dXJuIF90aGlzMi5zdG9yZS5wdXNoKGRhdGEpOwogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICBJZiB0aGUgZW50aXR5IHJlZmVycmVkIHRvIGJ5IHRoZSByZWZlcmVuY2UgaXMgYWxyZWFkeSBsb2FkZWQsIGl0IGlzCiAgICAgIHByZXNlbnQgYXMgYHJlZmVyZW5jZS52YWx1ZWAuIE90aGVyd2lzZSB0aGUgdmFsdWUgcmV0dXJuZWQgYnkgdGhpcyBmdW5jdGlvbgogICAgICBpcyBgbnVsbGAuCiAgICAgICAgRXhhbXBsZQogICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgIGxldCB1c2VyUmVmID0gc3RvcmUuZ2V0UmVmZXJlbmNlKCd1c2VyJywgMSk7CiAgICAgICAgdXNlclJlZi52YWx1ZSgpOyAvLyB1c2VyCiAgICAgICBgYGAKICAgICAgICBAbWV0aG9kIHZhbHVlCiAgICAgICBAcmV0dXJuIHtNb2RlbH0gdGhlIHJlY29yZCBmb3IgdGhpcyBSZWNvcmRSZWZlcmVuY2UKICAgICovCiAgICA7CgogICAgX3Byb3RvLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIGlmICh0aGlzLmludGVybmFsTW9kZWwuaGFzUmVjb3JkKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxNb2RlbC5nZXRSZWNvcmQoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICAvKioKICAgICAgIFRyaWdnZXJzIGEgZmV0Y2ggZm9yIHRoZSBiYWNraW5nIGVudGl0eSBiYXNlZCBvbiBpdHMgYHJlbW90ZVR5cGVgCiAgICAgICAoc2VlIGByZW1vdGVUeXBlYCBkZWZpbml0aW9ucyBwZXIgcmVmZXJlbmNlIHR5cGUpLgogICAgICAgIEV4YW1wbGUKICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgICBsZXQgdXNlclJlZiA9IHN0b3JlLmdldFJlZmVyZW5jZSgndXNlcicsIDEpOwogICAgICAgIC8vIGxvYWQgdXNlciAodmlhIHN0b3JlLmZpbmQpCiAgICAgICB1c2VyUmVmLmxvYWQoKS50aGVuKC4uLikKICAgICAgIGBgYAogICAgICAgIEBtZXRob2QgbG9hZAogICAgICAgQHJldHVybiB7UHJvbWlzZTxyZWNvcmQ+fSB0aGUgcmVjb3JkIGZvciB0aGlzIFJlY29yZFJlZmVyZW5jZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ubG9hZCA9IGZ1bmN0aW9uIGxvYWQoKSB7CiAgICAgIGlmICh0aGlzLl9pZCAhPT0gbnVsbCkgewogICAgICAgIHJldHVybiB0aGlzLnN0b3JlLmZpbmRSZWNvcmQodGhpcy50eXBlLCB0aGlzLl9pZCk7CiAgICAgIH0KCiAgICAgIHRocm93IG5ldyBFcnJvcigiVW5hYmxlIHRvIGZldGNoIHJlY29yZCBvZiB0eXBlICIgKyB0aGlzLnR5cGUgKyAiIHdpdGhvdXQgYW4gaWQiKTsKICAgIH0KICAgIC8qKgogICAgICAgUmVsb2FkcyB0aGUgcmVjb3JkIGlmIGl0IGlzIGFscmVhZHkgbG9hZGVkLiBJZiB0aGUgcmVjb3JkIGlzIG5vdAogICAgICAgbG9hZGVkIGl0IHdpbGwgbG9hZCB0aGUgcmVjb3JkIHZpYSBgc3RvcmUuZmluZFJlY29yZGAKICAgICAgICBFeGFtcGxlCiAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICAgbGV0IHVzZXJSZWYgPSBzdG9yZS5nZXRSZWZlcmVuY2UoJ3VzZXInLCAxKTsKICAgICAgICAvLyBvciB0cmlnZ2VyIGEgcmVsb2FkCiAgICAgICB1c2VyUmVmLnJlbG9hZCgpLnRoZW4oLi4uKQogICAgICAgYGBgCiAgICAgICAgQG1ldGhvZCByZWxvYWQKICAgICAgIEByZXR1cm4ge1Byb21pc2U8cmVjb3JkPn0gdGhlIHJlY29yZCBmb3IgdGhpcyBSZWNvcmRSZWZlcmVuY2UKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlbG9hZCA9IGZ1bmN0aW9uIHJlbG9hZCgpIHsKICAgICAgdmFyIHJlY29yZCA9IHRoaXMudmFsdWUoKTsKCiAgICAgIGlmIChyZWNvcmQpIHsKICAgICAgICByZXR1cm4gcmVjb3JkLnJlbG9hZCgpOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5sb2FkKCk7CiAgICB9OwoKICAgIF9jcmVhdGVDbGFzcyQyKFJlY29yZFJlZmVyZW5jZSwgW3sKICAgICAga2V5OiAiX2lkIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxNb2RlbC5pZDsKICAgICAgfQogICAgfV0pOwoKICAgIHJldHVybiBSZWNvcmRSZWZlcmVuY2U7CiAgfShSZWZlcmVuY2UpOwoKICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZSQxKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcy5wcm90b3R5cGUpOyBzdWJDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBzdWJDbGFzczsgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfQogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICBBIGBCZWxvbmdzVG9SZWZlcmVuY2VgIGlzIGEgbG93LWxldmVsIEFQSSB0aGF0IGFsbG93cyB1c2VycyBhbmQKICAgYWRkb24gYXV0aG9ycyB0byBwZXJmb3JtIG1ldGEtb3BlcmF0aW9ucyBvbiBhIGJlbG9uZ3MtdG8KICAgcmVsYXRpb25zaGlwLgoKICAgQGNsYXNzIEJlbG9uZ3NUb1JlZmVyZW5jZQogICBAZXh0ZW5kcyBSZWZlcmVuY2UKICAgKi8KCiAgdmFyIEJlbG9uZ3NUb1JlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfUmVmZXJlbmNlKSB7CiAgICBfaW5oZXJpdHNMb29zZSQxKEJlbG9uZ3NUb1JlZmVyZW5jZSwgX1JlZmVyZW5jZSk7CgogICAgZnVuY3Rpb24gQmVsb25nc1RvUmVmZXJlbmNlKHN0b3JlLCBwYXJlbnRJbnRlcm5hbE1vZGVsLCBiZWxvbmdzVG9SZWxhdGlvbnNoaXAsIGtleSkgewogICAgICB2YXIgX3RoaXM7CgogICAgICBfdGhpcyA9IF9SZWZlcmVuY2UuY2FsbCh0aGlzLCBzdG9yZSwgcGFyZW50SW50ZXJuYWxNb2RlbCkgfHwgdGhpczsKICAgICAgX3RoaXMua2V5ID0ga2V5OwogICAgICBfdGhpcy5iZWxvbmdzVG9SZWxhdGlvbnNoaXAgPSBiZWxvbmdzVG9SZWxhdGlvbnNoaXA7CiAgICAgIF90aGlzLnR5cGUgPSBiZWxvbmdzVG9SZWxhdGlvbnNoaXAucmVsYXRpb25zaGlwTWV0YS50eXBlOwogICAgICBfdGhpcy5wYXJlbnQgPSBwYXJlbnRJbnRlcm5hbE1vZGVsLnJlY29yZFJlZmVyZW5jZTsKICAgICAgX3RoaXMucGFyZW50SW50ZXJuYWxNb2RlbCA9IHBhcmVudEludGVybmFsTW9kZWw7IC8vIFRPRE8gaW52ZXJzZQoKICAgICAgcmV0dXJuIF90aGlzOwogICAgfQogICAgLyoqCiAgICAgVGhlIGBpZGAgb2YgdGhlIHJlY29yZCB0aGF0IHRoaXMgcmVmZXJlbmNlIHJlZmVycyB0by4gVG9nZXRoZXIsIHRoZQogICAgIGB0eXBlKClgIGFuZCBgaWQoKWAgbWV0aG9kcyBmb3JtIGEgY29tcG9zaXRlIGtleSBmb3IgdGhlIGlkZW50aXR5CiAgICAgbWFwLiBUaGlzIGNhbiBiZSB1c2VkIHRvIGFjY2VzcyB0aGUgaWQgb2YgYW4gYXN5bmMgcmVsYXRpb25zaGlwCiAgICAgd2l0aG91dCB0cmlnZ2VyaW5nIGEgZmV0Y2ggdGhhdCB3b3VsZCBub3JtYWxseSBoYXBwZW4gaWYgeW91CiAgICAgYXR0ZW1wdGVkIHRvIHVzZSBgcmVjb3JkLmdldCgncmVsYXRpb25zaGlwLmlkJylgLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAvLyBtb2RlbHMvYmxvZy5qcwogICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdXNlcjogYmVsb25nc1RvKHsgYXN5bmM6IHRydWUgfSkKICAgICAgfSk7CiAgICAgIGxldCBibG9nID0gc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ2Jsb2cnLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgIHVzZXI6IHsKICAgICAgICAgICAgICBkYXRhOiB7IHR5cGU6ICd1c2VyJywgaWQ6IDEgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICBsZXQgdXNlclJlZiA9IGJsb2cuYmVsb25nc1RvKCd1c2VyJyk7CiAgICAgIC8vIGdldCB0aGUgaWRlbnRpZmllciBvZiB0aGUgcmVmZXJlbmNlCiAgICAgaWYgKHVzZXJSZWYucmVtb3RlVHlwZSgpID09PSAiaWQiKSB7CiAgICAgICAgbGV0IGlkID0gdXNlclJlZi5pZCgpOwogICAgICB9CiAgICAgYGBgCiAgICAgIEBtZXRob2QgaWQKICAgICBAcmV0dXJuIHtTdHJpbmd9IFRoZSBpZCBvZiB0aGUgcmVjb3JkIGluIHRoaXMgYmVsb25nc1RvIHJlbGF0aW9uc2hpcC4KICAgICAqLwoKCiAgICB2YXIgX3Byb3RvID0gQmVsb25nc1RvUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uaWQgPSBmdW5jdGlvbiBpZCgpIHsKICAgICAgdmFyIGlkID0gbnVsbDsKCiAgICAgIHZhciByZXNvdXJjZSA9IHRoaXMuX3Jlc291cmNlKCk7CgogICAgICBpZiAocmVzb3VyY2UgJiYgcmVzb3VyY2UuZGF0YSAmJiByZXNvdXJjZS5kYXRhLmlkKSB7CiAgICAgICAgaWQgPSByZXNvdXJjZS5kYXRhLmlkOwogICAgICB9CgogICAgICByZXR1cm4gaWQ7CiAgICB9OwoKICAgIF9wcm90by5fcmVzb3VyY2UgPSBmdW5jdGlvbiBfcmVzb3VyY2UoKSB7CiAgICAgIHJldHVybiB0aGlzLnJlY29yZERhdGEuZ2V0QmVsb25nc1RvKHRoaXMua2V5KTsKICAgIH0KICAgIC8qKgogICAgIGBwdXNoYCBjYW4gYmUgdXNlZCB0byB1cGRhdGUgdGhlIGRhdGEgaW4gdGhlIHJlbGF0aW9uc2hpcCBhbmQgRW1iZXIKICAgICBEYXRhIHdpbGwgdHJlYXQgdGhlIG5ldyBkYXRhIGFzIHRoZSBjb25hbmljYWwgdmFsdWUgb2YgdGhpcwogICAgIHJlbGF0aW9uc2hpcCBvbiB0aGUgYmFja2VuZC4KICAgICAgRXhhbXBsZQogICAgICBgYGBhcHAvbW9kZWxzL2Jsb2cuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIHVzZXI6IGJlbG9uZ3NUbyh7IGFzeW5jOiB0cnVlIH0pCiAgICAgIH0pOwogICAgICBsZXQgYmxvZyA9IHN0b3JlLnB1c2goewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIHR5cGU6ICdibG9nJywKICAgICAgICAgIGlkOiAxLAogICAgICAgICAgcmVsYXRpb25zaGlwczogewogICAgICAgICAgICB1c2VyOiB7CiAgICAgICAgICAgICAgZGF0YTogeyB0eXBlOiAndXNlcicsIGlkOiAxIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgbGV0IHVzZXJSZWYgPSBibG9nLmJlbG9uZ3NUbygndXNlcicpOwogICAgICAvLyBwcm92aWRlIGRhdGEgZm9yIHJlZmVyZW5jZQogICAgIHVzZXJSZWYucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ3VzZXInLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgIHVzZXJuYW1lOiAiQHVzZXIiCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KS50aGVuKGZ1bmN0aW9uKHVzZXIpIHsKICAgICAgICB1c2VyUmVmLnZhbHVlKCkgPT09IHVzZXI7CiAgICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIHB1c2gKICAgICBAcGFyYW0ge09iamVjdHxQcm9taXNlfSBvYmplY3RPclByb21pc2UgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBKU09OQVBJIGRvY3VtZW50IG9iamVjdCBkZXNjcmliaW5nIHRoZSBuZXcgdmFsdWUgb2YgdGhpcyByZWxhdGlvbnNoaXAuCiAgICAgQHJldHVybiB7UHJvbWlzZTxyZWNvcmQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBuZXcgdmFsdWUgaW4gdGhpcyBiZWxvbmdzLXRvIHJlbGF0aW9uc2hpcC4KICAgICAqLwogICAgOwoKICAgIF9wcm90by5wdXNoID0gZnVuY3Rpb24gcHVzaChvYmplY3RPclByb21pc2UpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICAvLyBUT0RPIGRlcHJlY2F0ZSB0aGVuYWJsZSBzdXBwb3J0CiAgICAgIHJldHVybiBFbWJlci5SU1ZQLnJlc29sdmUob2JqZWN0T3JQcm9taXNlKS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgICAgdmFyIHJlY29yZDsgLy8gVE9ETyBkZXByZWNhdGUgZGF0YSBhcyBNb2RlbAoKICAgICAgICBpZiAocGVla1JlY29yZElkZW50aWZpZXIoZGF0YSkpIHsKICAgICAgICAgIHJlY29yZCA9IGRhdGE7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlY29yZCA9IF90aGlzMi5zdG9yZS5wdXNoKGRhdGEpOwogICAgICAgIH0KCiAgICAgICAgLy9UT0RPIElnb3IgY2xlYW51cCwgbWF5YmUgbW92ZSB0byByZWxhdGlvbnNoaXAgcHVzaAogICAgICAgIF90aGlzMi5iZWxvbmdzVG9SZWxhdGlvbnNoaXAuc2V0Q2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhRm9yKHJlY29yZCkpOwoKICAgICAgICByZXR1cm4gcmVjb3JkOwogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgIGB2YWx1ZSgpYCBzeW5jaHJvbm91c2x5IHJldHVybnMgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIGJlbG9uZ3MtdG8KICAgICByZWxhdGlvbnNoaXAuIFVubGlrZSBgcmVjb3JkLmdldCgncmVsYXRpb25zaGlwTmFtZScpYCwgY2FsbGluZwogICAgIGB2YWx1ZSgpYCBvbiBhIHJlZmVyZW5jZSBkb2VzIG5vdCB0cmlnZ2VyIGEgZmV0Y2ggaWYgdGhlIGFzeW5jCiAgICAgcmVsYXRpb25zaGlwIGlzIG5vdCB5ZXQgbG9hZGVkLiBJZiB0aGUgcmVsYXRpb25zaGlwIGlzIG5vdCBsb2FkZWQKICAgICBpdCB3aWxsIGFsd2F5cyByZXR1cm4gYG51bGxgLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAvLyBtb2RlbHMvYmxvZy5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdXNlcjogYmVsb25nc1RvKHsgYXN5bmM6IHRydWUgfSkKICAgICAgfSk7CiAgICAgIGxldCBibG9nID0gc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ2Jsb2cnLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgIHVzZXI6IHsKICAgICAgICAgICAgICBkYXRhOiB7IHR5cGU6ICd1c2VyJywgaWQ6IDEgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICBsZXQgdXNlclJlZiA9IGJsb2cuYmVsb25nc1RvKCd1c2VyJyk7CiAgICAgIHVzZXJSZWYudmFsdWUoKTsgLy8gbnVsbAogICAgICAvLyBwcm92aWRlIGRhdGEgZm9yIHJlZmVyZW5jZQogICAgIHVzZXJSZWYucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ3VzZXInLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgIHVzZXJuYW1lOiAiQHVzZXIiCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KS50aGVuKGZ1bmN0aW9uKHVzZXIpIHsKICAgICAgICB1c2VyUmVmLnZhbHVlKCk7IC8vIHVzZXIKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIEBtZXRob2QgdmFsdWUKICAgICBAcmV0dXJuIHtNb2RlbH0gdGhlIHJlY29yZCBpbiB0aGlzIHJlbGF0aW9uc2hpcAogICAgICovCiAgICA7CgogICAgX3Byb3RvLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHZhciBzdG9yZSA9IHRoaXMucGFyZW50SW50ZXJuYWxNb2RlbC5zdG9yZTsKCiAgICAgIHZhciByZXNvdXJjZSA9IHRoaXMuX3Jlc291cmNlKCk7CgogICAgICBpZiAocmVzb3VyY2UgJiYgcmVzb3VyY2UuZGF0YSkgewogICAgICAgIHZhciBpbnZlcnNlSW50ZXJuYWxNb2RlbCA9IHN0b3JlLl9pbnRlcm5hbE1vZGVsRm9yUmVzb3VyY2UocmVzb3VyY2UuZGF0YSk7CgogICAgICAgIGlmIChpbnZlcnNlSW50ZXJuYWxNb2RlbCAmJiBpbnZlcnNlSW50ZXJuYWxNb2RlbC5pc0xvYWRlZCgpKSB7CiAgICAgICAgICByZXR1cm4gaW52ZXJzZUludGVybmFsTW9kZWwuZ2V0UmVjb3JkKCk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIC8qKgogICAgIExvYWRzIGEgcmVjb3JkIGluIGEgYmVsb25ncy10byByZWxhdGlvbnNoaXAgaWYgaXQgaXMgbm90IGFscmVhZHkKICAgICBsb2FkZWQuIElmIHRoZSByZWxhdGlvbnNoaXAgaXMgYWxyZWFkeSBsb2FkZWQgdGhpcyBtZXRob2QgZG9lcyBub3QKICAgICB0cmlnZ2VyIGEgbmV3IGxvYWQuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgamF2YXNjcmlwdAogICAgIC8vIG1vZGVscy9ibG9nLmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICB1c2VyOiBiZWxvbmdzVG8oeyBhc3luYzogdHJ1ZSB9KQogICAgICB9KTsKICAgICAgbGV0IGJsb2cgPSBzdG9yZS5wdXNoKHsKICAgICAgICBkYXRhOiB7CiAgICAgICAgICB0eXBlOiAnYmxvZycsCiAgICAgICAgICBpZDogMSwKICAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICAgdXNlcjogewogICAgICAgICAgICAgIGRhdGE6IHsgdHlwZTogJ3VzZXInLCBpZDogMSB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgIGxldCB1c2VyUmVmID0gYmxvZy5iZWxvbmdzVG8oJ3VzZXInKTsKICAgICAgdXNlclJlZi52YWx1ZSgpOyAvLyBudWxsCiAgICAgIHVzZXJSZWYubG9hZCgpLnRoZW4oZnVuY3Rpb24odXNlcikgewogICAgICAgIHVzZXJSZWYudmFsdWUoKSA9PT0gdXNlcgogICAgICB9KTsKICAgICBgYGAKICAgICAgWW91IG1heSBhbHNvIHBhc3MgaW4gYW4gb3B0aW9ucyBvYmplY3Qgd2hvc2UgcHJvcGVydGllcyB3aWxsIGJlCiAgICAgZmVkIGZvcndhcmQuIFRoaXMgZW5hYmxlcyB5b3UgdG8gcGFzcyBgYWRhcHRlck9wdGlvbnNgIGludG8gdGhlCiAgICAgcmVxdWVzdCBnaXZlbiB0byB0aGUgYWRhcHRlciB2aWEgdGhlIHJlZmVyZW5jZS4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgdXNlclJlZi5sb2FkKHsgYWRhcHRlck9wdGlvbnM6IHsgaXNQcml2YXRlOiB0cnVlIH0gfSkudGhlbihmdW5jdGlvbih1c2VyKSB7CiAgICAgICB1c2VyUmVmLnZhbHVlKCkgPT09IHVzZXI7CiAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYGFwcC9hZGFwdGVycy91c2VyLmpzCiAgICAgZXhwb3J0IGRlZmF1bHQgQXBwbGljYXRpb25BZGFwdGVyLmV4dGVuZCh7CiAgICAgICBmaW5kUmVjb3JkKHN0b3JlLCB0eXBlLCBpZCwgc25hcHNob3QpIHsKICAgICAgICAgLy8gSW4gdGhlIGFkYXB0ZXIgeW91IHdpbGwgaGF2ZSBhY2Nlc3MgdG8gYWRhcHRlck9wdGlvbnMuCiAgICAgICAgIGxldCBhZGFwdGVyT3B0aW9ucyA9IHNuYXBzaG90LmFkYXB0ZXJPcHRpb25zOwogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIGxvYWQKICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyB0aGUgb3B0aW9ucyB0byBwYXNzIGluLgogICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHJlY29yZCBpbiB0aGlzIGJlbG9uZ3MtdG8gcmVsYXRpb25zaGlwLgogICAgICovCiAgICA7CgogICAgX3Byb3RvLmxvYWQgPSBmdW5jdGlvbiBsb2FkKG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMucGFyZW50SW50ZXJuYWxNb2RlbC5nZXRCZWxvbmdzVG8odGhpcy5rZXksIG9wdGlvbnMpOwogICAgfQogICAgLyoqCiAgICAgVHJpZ2dlcnMgYSByZWxvYWQgb2YgdGhlIHZhbHVlIGluIHRoaXMgcmVsYXRpb25zaGlwLiBJZiB0aGUKICAgICByZW1vdGVUeXBlIGlzIGAibGluayJgIEVtYmVyIERhdGEgd2lsbCB1c2UgdGhlIHJlbGF0aW9uc2hpcCBsaW5rIHRvCiAgICAgcmVsb2FkIHRoZSByZWxhdGlvbnNoaXAuIE90aGVyd2lzZSBpdCB3aWxsIHJlbG9hZCB0aGUgcmVjb3JkIGJ5IGl0cwogICAgIGlkLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAvLyBtb2RlbHMvYmxvZy5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICB1c2VyOiBiZWxvbmdzVG8oeyBhc3luYzogdHJ1ZSB9KQogICAgICB9KTsKICAgICAgbGV0IGJsb2cgPSBzdG9yZS5wdXNoKHsKICAgICAgICBkYXRhOiB7CiAgICAgICAgICB0eXBlOiAnYmxvZycsCiAgICAgICAgICBpZDogMSwKICAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICAgdXNlcjogewogICAgICAgICAgICAgIGRhdGE6IHsgdHlwZTogJ3VzZXInLCBpZDogMSB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgIGxldCB1c2VyUmVmID0gYmxvZy5iZWxvbmdzVG8oJ3VzZXInKTsKICAgICAgdXNlclJlZi5yZWxvYWQoKS50aGVuKGZ1bmN0aW9uKHVzZXIpIHsKICAgICAgICB1c2VyUmVmLnZhbHVlKCkgPT09IHVzZXIKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIFlvdSBtYXkgYWxzbyBwYXNzIGluIGFuIG9wdGlvbnMgb2JqZWN0IHdob3NlIHByb3BlcnRpZXMgd2lsbCBiZQogICAgIGZlZCBmb3J3YXJkLiBUaGlzIGVuYWJsZXMgeW91IHRvIHBhc3MgYGFkYXB0ZXJPcHRpb25zYCBpbnRvIHRoZQogICAgIHJlcXVlc3QgZ2l2ZW4gdG8gdGhlIGFkYXB0ZXIgdmlhIHRoZSByZWZlcmVuY2UuIEEgZnVsbCBleGFtcGxlCiAgICAgY2FuIGJlIGZvdW5kIGluIHRoZSBgbG9hZGAgbWV0aG9kLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICB1c2VyUmVmLnJlbG9hZCh7IGFkYXB0ZXJPcHRpb25zOiB7IGlzUHJpdmF0ZTogdHJ1ZSB9IH0pCiAgICAgYGBgCiAgICAgIEBtZXRob2QgcmVsb2FkCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgdGhlIG9wdGlvbnMgdG8gcGFzcyBpbi4KICAgICBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSByZWNvcmQgaW4gdGhpcyBiZWxvbmdzLXRvIHJlbGF0aW9uc2hpcCBhZnRlciB0aGUgcmVsb2FkIGhhcyBjb21wbGV0ZWQuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVsb2FkID0gZnVuY3Rpb24gcmVsb2FkKG9wdGlvbnMpIHsKICAgICAgdmFyIF90aGlzMyA9IHRoaXM7CgogICAgICByZXR1cm4gdGhpcy5wYXJlbnRJbnRlcm5hbE1vZGVsLnJlbG9hZEJlbG9uZ3NUbyh0aGlzLmtleSwgb3B0aW9ucykudGhlbihmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIHJldHVybiBfdGhpczMudmFsdWUoKTsKICAgICAgfSk7CiAgICB9OwoKICAgIHJldHVybiBCZWxvbmdzVG9SZWZlcmVuY2U7CiAgfShSZWZlcmVuY2UpOwoKICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZSQyKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcy5wcm90b3R5cGUpOyBzdWJDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBzdWJDbGFzczsgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfQogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICBBIGBIYXNNYW55UmVmZXJlbmNlYCBpcyBhIGxvdy1sZXZlbCBBUEkgdGhhdCBhbGxvd3MgdXNlcnMgYW5kIGFkZG9uCiAgIGF1dGhvcnMgdG8gcGVyZm9ybSBtZXRhLW9wZXJhdGlvbnMgb24gYSBoYXMtbWFueSByZWxhdGlvbnNoaXAuCgogICBAY2xhc3MgSGFzTWFueVJlZmVyZW5jZQogICBAZXh0ZW5kcyBSZWZlcmVuY2UKICAgKi8KCiAgdmFyIEhhc01hbnlSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1JlZmVyZW5jZSkgewogICAgX2luaGVyaXRzTG9vc2UkMihIYXNNYW55UmVmZXJlbmNlLCBfUmVmZXJlbmNlKTsKCiAgICBmdW5jdGlvbiBIYXNNYW55UmVmZXJlbmNlKHN0b3JlLCBwYXJlbnRJbnRlcm5hbE1vZGVsLCBoYXNNYW55UmVsYXRpb25zaGlwLCBrZXkpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfUmVmZXJlbmNlLmNhbGwodGhpcywgc3RvcmUsIHBhcmVudEludGVybmFsTW9kZWwpIHx8IHRoaXM7CiAgICAgIF90aGlzLmtleSA9IGtleTsKICAgICAgX3RoaXMuaGFzTWFueVJlbGF0aW9uc2hpcCA9IGhhc01hbnlSZWxhdGlvbnNoaXA7CiAgICAgIF90aGlzLnR5cGUgPSBoYXNNYW55UmVsYXRpb25zaGlwLnJlbGF0aW9uc2hpcE1ldGEudHlwZTsKICAgICAgX3RoaXMucGFyZW50ID0gcGFyZW50SW50ZXJuYWxNb2RlbC5yZWNvcmRSZWZlcmVuY2U7CiAgICAgIF90aGlzLnBhcmVudEludGVybmFsTW9kZWwgPSBwYXJlbnRJbnRlcm5hbE1vZGVsOyAvLyBUT0RPIGludmVyc2UKCiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gSGFzTWFueVJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvLl9yZXNvdXJjZSA9IGZ1bmN0aW9uIF9yZXNvdXJjZSgpIHsKICAgICAgcmV0dXJuIHRoaXMucmVjb3JkRGF0YS5nZXRIYXNNYW55KHRoaXMua2V5KTsKICAgIH0KICAgIC8qKgogICAgIFRoaXMgcmV0dXJucyBhIHN0cmluZyB0aGF0IHJlcHJlc2VudHMgaG93IHRoZSByZWZlcmVuY2Ugd2lsbCBiZQogICAgIGxvb2tlZCB1cCB3aGVuIGl0IGlzIGxvYWRlZC4gSWYgdGhlIHJlbGF0aW9uc2hpcCBoYXMgYSBsaW5rIGl0IHdpbGwKICAgICB1c2UgdGhlICJsaW5rIiBvdGhlcndpc2UgaXQgZGVmYXVsdHMgdG8gImlkIi4KICAgICAgRXhhbXBsZQogICAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgY29tbWVudHM6IGhhc01hbnkoeyBhc3luYzogdHJ1ZSB9KQogICAgIH0pOwogICAgIGBgYAogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHBvc3QgPSBzdG9yZS5wdXNoKHsKICAgICAgIGRhdGE6IHsKICAgICAgICAgdHlwZTogJ3Bvc3QnLAogICAgICAgICBpZDogMSwKICAgICAgICAgcmVsYXRpb25zaGlwczogewogICAgICAgICAgIGNvbW1lbnRzOiB7CiAgICAgICAgICAgICBkYXRhOiBbeyB0eXBlOiAnY29tbWVudCcsIGlkOiAxIH1dCiAgICAgICAgICAgfQogICAgICAgICB9CiAgICAgICB9CiAgICAgfSk7CiAgICAgIGxldCBjb21tZW50c1JlZiA9IHBvc3QuaGFzTWFueSgnY29tbWVudHMnKTsKICAgICAgLy8gZ2V0IHRoZSBpZGVudGlmaWVyIG9mIHRoZSByZWZlcmVuY2UKICAgICBpZiAoY29tbWVudHNSZWYucmVtb3RlVHlwZSgpID09PSAiaWRzIikgewogICAgICAgbGV0IGlkcyA9IGNvbW1lbnRzUmVmLmlkcygpOwogICAgIH0gZWxzZSBpZiAoY29tbWVudHNSZWYucmVtb3RlVHlwZSgpID09PSAibGluayIpIHsKICAgICAgIGxldCBsaW5rID0gY29tbWVudHNSZWYubGluaygpOwogICAgIH0KICAgICBgYGAKICAgICAgQG1ldGhvZCByZW1vdGVUeXBlCiAgICAgQHJldHVybiB7U3RyaW5nfSBUaGUgbmFtZSBvZiB0aGUgcmVtb3RlIHR5cGUuIFRoaXMgc2hvdWxkIGVpdGhlciBiZSBgbGlua2Agb3IgYGlkc2AKICAgICAqLwogICAgOwoKICAgIF9wcm90by5yZW1vdGVUeXBlID0gZnVuY3Rpb24gcmVtb3RlVHlwZSgpIHsKICAgICAgdmFyIHZhbHVlID0gdGhpcy5fcmVzb3VyY2UoKTsKCiAgICAgIGlmICh2YWx1ZSAmJiB2YWx1ZS5saW5rcyAmJiB2YWx1ZS5saW5rcy5yZWxhdGVkKSB7CiAgICAgICAgcmV0dXJuICdsaW5rJzsKICAgICAgfQoKICAgICAgcmV0dXJuICdpZHMnOwogICAgfQogICAgLyoqCiAgICAgYGlkcygpYCByZXR1cm5zIGFuIGFycmF5IG9mIHRoZSByZWNvcmQgSURzIGluIHRoaXMgcmVsYXRpb25zaGlwLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICBjb21tZW50czogaGFzTWFueSh7IGFzeW5jOiB0cnVlIH0pCiAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcG9zdCA9IHN0b3JlLnB1c2goewogICAgICAgZGF0YTogewogICAgICAgICB0eXBlOiAncG9zdCcsCiAgICAgICAgIGlkOiAxLAogICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgY29tbWVudHM6IHsKICAgICAgICAgICAgIGRhdGE6IFt7IHR5cGU6ICdjb21tZW50JywgaWQ6IDEgfV0KICAgICAgICAgICB9CiAgICAgICAgIH0KICAgICAgIH0KICAgICB9KTsKICAgICAgbGV0IGNvbW1lbnRzUmVmID0gcG9zdC5oYXNNYW55KCdjb21tZW50cycpOwogICAgICBjb21tZW50c1JlZi5pZHMoKTsgLy8gWycxJ10KICAgICBgYGAKICAgICAgQG1ldGhvZCBpZHMKICAgICBAcmV0dXJuIHtBcnJheX0gVGhlIGlkcyBpbiB0aGlzIGhhcy1tYW55IHJlbGF0aW9uc2hpcAogICAgICovCiAgICA7CgogICAgX3Byb3RvLmlkcyA9IGZ1bmN0aW9uIGlkcygpIHsKICAgICAgdmFyIHJlc291cmNlID0gdGhpcy5fcmVzb3VyY2UoKTsKCiAgICAgIHZhciBpZHMgPSBbXTsKCiAgICAgIGlmIChyZXNvdXJjZS5kYXRhKSB7CiAgICAgICAgaWRzID0gcmVzb3VyY2UuZGF0YS5tYXAoZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgICAgIHJldHVybiBkYXRhLmlkOwogICAgICAgIH0pOwogICAgICB9CgogICAgICByZXR1cm4gaWRzOwogICAgfQogICAgLyoqCiAgICAgYHB1c2hgIGNhbiBiZSB1c2VkIHRvIHVwZGF0ZSB0aGUgZGF0YSBpbiB0aGUgcmVsYXRpb25zaGlwIGFuZCBFbWJlcgogICAgIERhdGEgd2lsbCB0cmVhdCB0aGUgbmV3IGRhdGEgYXMgdGhlIGNhbm9uaWNhbCB2YWx1ZSBvZiB0aGlzCiAgICAgcmVsYXRpb25zaGlwIG9uIHRoZSBiYWNrZW5kLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICBjb21tZW50czogaGFzTWFueSh7IGFzeW5jOiB0cnVlIH0pCiAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYAogICAgIGxldCBwb3N0ID0gc3RvcmUucHVzaCh7CiAgICAgICBkYXRhOiB7CiAgICAgICAgIHR5cGU6ICdwb3N0JywKICAgICAgICAgaWQ6IDEsCiAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICBjb21tZW50czogewogICAgICAgICAgICAgZGF0YTogW3sgdHlwZTogJ2NvbW1lbnQnLCBpZDogMSB9XQogICAgICAgICAgIH0KICAgICAgICAgfQogICAgICAgfQogICAgIH0pOwogICAgICBsZXQgY29tbWVudHNSZWYgPSBwb3N0Lmhhc01hbnkoJ2NvbW1lbnRzJyk7CiAgICAgIGNvbW1lbnRzUmVmLmlkcygpOyAvLyBbJzEnXQogICAgICBjb21tZW50c1JlZi5wdXNoKFsKICAgICBbeyB0eXBlOiAnY29tbWVudCcsIGlkOiAyIH1dLAogICAgIFt7IHR5cGU6ICdjb21tZW50JywgaWQ6IDMgfV0sCiAgICAgXSkKICAgICAgY29tbWVudHNSZWYuaWRzKCk7IC8vIFsnMicsICczJ10KICAgICBgYGAKICAgICAgQG1ldGhvZCBwdXNoCiAgICAgQHBhcmFtIHtBcnJheXxQcm9taXNlfSBvYmplY3RPclByb21pc2UgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBKU09OQVBJIGRvY3VtZW50IG9iamVjdCBkZXNjcmliaW5nIHRoZSBuZXcgdmFsdWUgb2YgdGhpcyByZWxhdGlvbnNoaXAuCiAgICAgQHJldHVybiB7TWFueUFycmF5fQogICAgICovCiAgICA7CgogICAgX3Byb3RvLnB1c2ggPSBmdW5jdGlvbiBwdXNoKG9iamVjdE9yUHJvbWlzZSkgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIHJldHVybiBFbWJlci5SU1ZQLnJlc29sdmUob2JqZWN0T3JQcm9taXNlKS50aGVuKGZ1bmN0aW9uIChwYXlsb2FkKSB7CiAgICAgICAgdmFyIGFycmF5ID0gcGF5bG9hZDsKCiAgICAgICAgaWYgKHR5cGVvZiBwYXlsb2FkID09PSAnb2JqZWN0JyAmJiBwYXlsb2FkLmRhdGEpIHsKICAgICAgICAgIGFycmF5ID0gcGF5bG9hZC5kYXRhOwogICAgICAgIH0KCiAgICAgICAgdmFyIGludGVybmFsTW9kZWxzID0gYXJyYXkubWFwKGZ1bmN0aW9uIChvYmopIHsKICAgICAgICAgIHZhciByZWNvcmQgPSBfdGhpczIuc3RvcmUucHVzaChvYmopOwoKICAgICAgICAgIHJldHVybiByZWNvcmREYXRhRm9yKHJlY29yZCk7CiAgICAgICAgfSk7CgogICAgICAgIF90aGlzMi5oYXNNYW55UmVsYXRpb25zaGlwLmNvbXB1dGVDaGFuZ2VzKGludGVybmFsTW9kZWxzKTsKCiAgICAgICAgcmV0dXJuIF90aGlzMi5pbnRlcm5hbE1vZGVsLmdldEhhc01hbnkoX3RoaXMyLmhhc01hbnlSZWxhdGlvbnNoaXAua2V5KTsgLy8gVE9ETyBJR09SIGl0IHNlZW1zIHdyb25nIHRoYXQgd2Ugd2VyZSByZXR1cm5pbmcgdGhlIG1hbnkgYXJyYXkgaGVyZQogICAgICAgIC8vcmV0dXJuIHRoaXMuaGFzTWFueVJlbGF0aW9uc2hpcC5tYW55QXJyYXk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8uX2lzTG9hZGVkID0gZnVuY3Rpb24gX2lzTG9hZGVkKCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHZhciBoYXNSZWxhdGlvbnNoaXBEYXRhUHJvcGVydHkgPSBFbWJlci5nZXQodGhpcy5oYXNNYW55UmVsYXRpb25zaGlwLCAnaGFzQW55UmVsYXRpb25zaGlwRGF0YScpOwoKICAgICAgaWYgKCFoYXNSZWxhdGlvbnNoaXBEYXRhUHJvcGVydHkpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIHZhciBtZW1iZXJzID0gdGhpcy5oYXNNYW55UmVsYXRpb25zaGlwLm1lbWJlcnMudG9BcnJheSgpOyAvL1RPRE8gSWdvciBjbGVhbnVwCgogICAgICByZXR1cm4gbWVtYmVycy5ldmVyeShmdW5jdGlvbiAocmVjb3JkRGF0YSkgewogICAgICAgIHZhciBzdG9yZSA9IF90aGlzMy5wYXJlbnRJbnRlcm5hbE1vZGVsLnN0b3JlOwoKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IHN0b3JlLl9pbnRlcm5hbE1vZGVsRm9yUmVzb3VyY2UocmVjb3JkRGF0YS5nZXRSZXNvdXJjZUlkZW50aWZpZXIoKSk7CgogICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLmlzTG9hZGVkKCkgPT09IHRydWU7CiAgICAgIH0pOwogICAgfQogICAgLyoqCiAgICAgYHZhbHVlKClgIHN5bmNocm9ub3VzbHkgcmV0dXJucyB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgaGFzLW1hbnkKICAgICByZWxhdGlvbnNoaXAuIFVubGlrZSBgcmVjb3JkLmdldCgncmVsYXRpb25zaGlwTmFtZScpYCwgY2FsbGluZwogICAgIGB2YWx1ZSgpYCBvbiBhIHJlZmVyZW5jZSBkb2VzIG5vdCB0cmlnZ2VyIGEgZmV0Y2ggaWYgdGhlIGFzeW5jCiAgICAgcmVsYXRpb25zaGlwIGlzIG5vdCB5ZXQgbG9hZGVkLiBJZiB0aGUgcmVsYXRpb25zaGlwIGlzIG5vdCBsb2FkZWQKICAgICBpdCB3aWxsIGFsd2F5cyByZXR1cm4gYG51bGxgLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICBjb21tZW50czogaGFzTWFueSh7IGFzeW5jOiB0cnVlIH0pCiAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcG9zdCA9IHN0b3JlLnB1c2goewogICAgICAgZGF0YTogewogICAgICAgICB0eXBlOiAncG9zdCcsCiAgICAgICAgIGlkOiAxLAogICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgY29tbWVudHM6IHsKICAgICAgICAgICAgIGRhdGE6IFt7IHR5cGU6ICdjb21tZW50JywgaWQ6IDEgfV0KICAgICAgICAgICB9CiAgICAgICAgIH0KICAgICAgIH0KICAgICB9KTsKICAgICAgbGV0IGNvbW1lbnRzUmVmID0gcG9zdC5oYXNNYW55KCdjb21tZW50cycpOwogICAgICBwb3N0LmdldCgnY29tbWVudHMnKS50aGVuKGZ1bmN0aW9uKGNvbW1lbnRzKSB7CiAgICAgICBjb21tZW50c1JlZi52YWx1ZSgpID09PSBjb21tZW50cwogICAgIH0pCiAgICAgYGBgCiAgICAgIEBtZXRob2QgdmFsdWUKICAgICBAcmV0dXJuIHtNYW55QXJyYXl9CiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8udmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgaWYgKHRoaXMuX2lzTG9hZGVkKCkpIHsKICAgICAgICByZXR1cm4gdGhpcy5pbnRlcm5hbE1vZGVsLmdldE1hbnlBcnJheSh0aGlzLmtleSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgLyoqCiAgICAgTG9hZHMgdGhlIHJlbGF0aW9uc2hpcCBpZiBpdCBpcyBub3QgYWxyZWFkeSBsb2FkZWQuICBJZiB0aGUKICAgICByZWxhdGlvbnNoaXAgaXMgYWxyZWFkeSBsb2FkZWQgdGhpcyBtZXRob2QgZG9lcyBub3QgdHJpZ2dlciBhIG5ldwogICAgIGxvYWQuIFRoaXMgY2F1c2VzIGEgcmVxdWVzdCB0byB0aGUgc3BlY2lmaWVkCiAgICAgcmVsYXRpb25zaGlwIGxpbmsgb3IgcmVsb2FkcyBhbGwgaXRlbXMgY3VycmVudGx5IGluIHRoZSByZWxhdGlvbnNoaXAuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgYXBwL21vZGVscy9wb3N0LmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgIGNvbW1lbnRzOiBoYXNNYW55KHsgYXN5bmM6IHRydWUgfSkKICAgICB9KTsKICAgICBgYGAKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGxldCBwb3N0ID0gc3RvcmUucHVzaCh7CiAgICAgICBkYXRhOiB7CiAgICAgICAgIHR5cGU6ICdwb3N0JywKICAgICAgICAgaWQ6IDEsCiAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICBjb21tZW50czogewogICAgICAgICAgICAgZGF0YTogW3sgdHlwZTogJ2NvbW1lbnQnLCBpZDogMSB9XQogICAgICAgICAgIH0KICAgICAgICAgfQogICAgICAgfQogICAgIH0pOwogICAgICBsZXQgY29tbWVudHNSZWYgPSBwb3N0Lmhhc01hbnkoJ2NvbW1lbnRzJyk7CiAgICAgIGNvbW1lbnRzUmVmLmxvYWQoKS50aGVuKGZ1bmN0aW9uKGNvbW1lbnRzKSB7CiAgICAgICAvLy4uLgogICAgIH0pOwogICAgIGBgYAogICAgICBZb3UgbWF5IGFsc28gcGFzcyBpbiBhbiBvcHRpb25zIG9iamVjdCB3aG9zZSBwcm9wZXJ0aWVzIHdpbGwgYmUKICAgICBmZWQgZm9yd2FyZC4gVGhpcyBlbmFibGVzIHlvdSB0byBwYXNzIGBhZGFwdGVyT3B0aW9uc2AgaW50byB0aGUKICAgICByZXF1ZXN0IGdpdmVuIHRvIHRoZSBhZGFwdGVyIHZpYSB0aGUgcmVmZXJlbmNlLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBjb21tZW50c1JlZi5sb2FkKHsgYWRhcHRlck9wdGlvbnM6IHsgaXNQcml2YXRlOiB0cnVlIH0gfSkKICAgICAgIC50aGVuKGZ1bmN0aW9uKGNvbW1lbnRzKSB7CiAgICAgICAgIC8vLi4uCiAgICAgICB9KTsKICAgICBgYGAKICAgICAgYGBgYXBwL2FkYXB0ZXJzL2NvbW1lbnQuanMKICAgICBleHBvcnQgZGVmYXVsdCBBcHBsaWNhdGlvbkFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgIGZpbmRNYW55KHN0b3JlLCB0eXBlLCBpZCwgc25hcHNob3RzKSB7CiAgICAgICAgIC8vIEluIHRoZSBhZGFwdGVyIHlvdSB3aWxsIGhhdmUgYWNjZXNzIHRvIGFkYXB0ZXJPcHRpb25zLgogICAgICAgICBsZXQgYWRhcHRlck9wdGlvbnMgPSBzbmFwc2hvdHNbMF0uYWRhcHRlck9wdGlvbnM7CiAgICAgICB9CiAgICAgfSk7CiAgICAgYGBgCiAgICAgIEBtZXRob2QgbG9hZAogICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIHRoZSBvcHRpb25zIHRvIHBhc3MgaW4uCiAgICAgQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgTWFueUFycmF5IGluCiAgICAgdGhpcyBoYXMtbWFueSByZWxhdGlvbnNoaXAuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ubG9hZCA9IGZ1bmN0aW9uIGxvYWQob3B0aW9ucykgewogICAgICByZXR1cm4gdGhpcy5pbnRlcm5hbE1vZGVsLmdldEhhc01hbnkodGhpcy5rZXksIG9wdGlvbnMpOwogICAgfQogICAgLyoqCiAgICAgUmVsb2FkcyB0aGlzIGhhcy1tYW55IHJlbGF0aW9uc2hpcC4gVGhpcyBjYXVzZXMgYSByZXF1ZXN0IHRvIHRoZSBzcGVjaWZpZWQKICAgICByZWxhdGlvbnNoaXAgbGluayBvciByZWxvYWRzIGFsbCBpdGVtcyBjdXJyZW50bHkgaW4gdGhlIHJlbGF0aW9uc2hpcC4KICAgICAgRXhhbXBsZQogICAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgY29tbWVudHM6IGhhc01hbnkoeyBhc3luYzogdHJ1ZSB9KQogICAgIH0pOwogICAgIGBgYAogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHBvc3QgPSBzdG9yZS5wdXNoKHsKICAgICAgIGRhdGE6IHsKICAgICAgICAgdHlwZTogJ3Bvc3QnLAogICAgICAgICBpZDogMSwKICAgICAgICAgcmVsYXRpb25zaGlwczogewogICAgICAgICAgIGNvbW1lbnRzOiB7CiAgICAgICAgICAgICBkYXRhOiBbeyB0eXBlOiAnY29tbWVudCcsIGlkOiAxIH1dCiAgICAgICAgICAgfQogICAgICAgICB9CiAgICAgICB9CiAgICAgfSk7CiAgICAgIGxldCBjb21tZW50c1JlZiA9IHBvc3QuaGFzTWFueSgnY29tbWVudHMnKTsKICAgICAgY29tbWVudHNSZWYucmVsb2FkKCkudGhlbihmdW5jdGlvbihjb21tZW50cykgewogICAgICAgLy8uLi4KICAgICB9KTsKICAgICBgYGAKICAgICAgWW91IG1heSBhbHNvIHBhc3MgaW4gYW4gb3B0aW9ucyBvYmplY3Qgd2hvc2UgcHJvcGVydGllcyB3aWxsIGJlCiAgICAgZmVkIGZvcndhcmQuIFRoaXMgZW5hYmxlcyB5b3UgdG8gcGFzcyBgYWRhcHRlck9wdGlvbnNgIGludG8gdGhlCiAgICAgcmVxdWVzdCBnaXZlbiB0byB0aGUgYWRhcHRlciB2aWEgdGhlIHJlZmVyZW5jZS4gQSBmdWxsIGV4YW1wbGUKICAgICBjYW4gYmUgZm91bmQgaW4gdGhlIGBsb2FkYCBtZXRob2QuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGNvbW1lbnRzUmVmLnJlbG9hZCh7IGFkYXB0ZXJPcHRpb25zOiB7IGlzUHJpdmF0ZTogdHJ1ZSB9IH0pCiAgICAgYGBgCiAgICAgIEBtZXRob2QgcmVsb2FkCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgdGhlIG9wdGlvbnMgdG8gcGFzcyBpbi4KICAgICBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBNYW55QXJyYXkgaW4gdGhpcyBoYXMtbWFueSByZWxhdGlvbnNoaXAuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVsb2FkID0gZnVuY3Rpb24gcmVsb2FkKG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxNb2RlbC5yZWxvYWRIYXNNYW55KHRoaXMua2V5LCBvcHRpb25zKTsKICAgIH07CgogICAgcmV0dXJuIEhhc01hbnlSZWZlcmVuY2U7CiAgfShSZWZlcmVuY2UpOwoKICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyQzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyQzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMkMyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIC8vIG9uY2UgdGhlIHByZXNlbnRhdGlvbiBsb2dpYyBpcyBtb3ZlZCBpbnRvIHRoZSBNb2RlbCBwYWNrYWdlIHdlIGNhbiBtYWtlCiAgLy8gZWxpbWluYXRlIHRoZXNlIGxvc3N5IGFuZCByZWR1bmRhbnQgaGVscGVycwogIGZ1bmN0aW9uIHJlbGF0aW9uc2hpcHNGb3IkMShpbnN0YW5jZSkgewogICAgdmFyIHJlY29yZERhdGEgPSByZWNvcmREYXRhRm9yKGluc3RhbmNlKTsKICAgIHJldHVybiByZWNvcmREYXRhLl9yZWxhdGlvbnNoaXBzOwogIH0KCiAgZnVuY3Rpb24gcmVsYXRpb25zaGlwU3RhdGVGb3IkMShpbnN0YW5jZSwgcHJvcGVydHlOYW1lKSB7CiAgICByZXR1cm4gcmVsYXRpb25zaGlwc0ZvciQxKGluc3RhbmNlKS5nZXQocHJvcGVydHlOYW1lKTsKICB9CgogIHZhciBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7CiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KICAvLyBtb3ZlIHRvIFRTIGhhY2tzIG1vZHVsZSB0aGF0IHdlIGNhbiBkZWxldGUgd2hlbiB0aGlzIGlzIG5vIGxvbmdlciBhIG5lY2Vzc2FyeSByZWNhc3QKCiAgLy8gVE9ETyB0aGlzIHNob3VsZCBiZSBpbnRlZ3JhdGVkIHdpdGggdGhlIGNvZGUgcmVtb3ZhbCBzbyB3ZSBjYW4gdXNlIGl0IHRvZ2V0aGVyIHdpdGggdGhlIGlmIGNvbmRpdGlvbgogIC8vIGFuZCBub3QgYWxvbmdzaWRlIGl0CiAgZnVuY3Rpb24gaXNOb3RDdXN0b21Nb2RlbENsYXNzKHN0b3JlKSB7CiAgICByZXR1cm4gIWNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUzsKICB9CgogIC8qCiAgICBUaGUgVHJhbnNpdGlvbkNoYWluTWFwIGNhY2hlcyB0aGUgYHN0YXRlLmVudGVyc2AsIGBzdGF0ZS5zZXR1cHNgLCBhbmQgZmluYWwgc3RhdGUgcmVhY2hlZAogICAgd2hlbiB0cmFuc2l0aW9uaW5nIGZyb20gb25lIHN0YXRlIHRvIGFub3RoZXIsIHNvIHRoYXQgZnV0dXJlIHRyYW5zaXRpb25zIGNhbiByZXBsYXkgdGhlCiAgICB0cmFuc2l0aW9uIHdpdGhvdXQgbmVlZGluZyB0byB3YWxrIHRoZSBzdGF0ZSB0cmVlLCBjb2xsZWN0IHRoZXNlIGhvb2sgY2FsbHMgYW5kIGRldGVybWluZQogICAgIHRoZSBzdGF0ZSB0byB0cmFuc2l0aW9uIGludG8uCgogICAgIEEgZnV0dXJlIG9wdGltaXphdGlvbiB3b3VsZCBiZSB0byBidWlsZCBhIHNpbmdsZSBjaGFpbmVkIG1ldGhvZCBvdXQgb2YgdGhlIGNvbGxlY3RlZCBlbnRlcnMKICAgICBhbmQgc2V0dXBzLiBJdCBtYXkgYWxzbyBiZSBmYXN0ZXIgdG8gZG8gYSB0d28gbGV2ZWwgY2FjaGUgKGZyb206IHsgdG8gfSkgaW5zdGVhZCBvZiBjYWNoaW5nIGJhc2VkCiAgICAgb24gYSBrZXkgdGhhdCBhZGRzIHRoZSB0d28gdG9nZXRoZXIuCiAgICovCiAgdmFyIFRyYW5zaXRpb25DaGFpbk1hcCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CgogIHZhciBfZXh0cmFjdFBpdm90TmFtZUNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKCiAgdmFyIF9zcGxpdE9uRG90Q2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwoKICBmdW5jdGlvbiBzcGxpdE9uRG90KG5hbWUpIHsKICAgIHJldHVybiBfc3BsaXRPbkRvdENhY2hlW25hbWVdIHx8IChfc3BsaXRPbkRvdENhY2hlW25hbWVdID0gbmFtZS5zcGxpdCgnLicpKTsKICB9CgogIGZ1bmN0aW9uIGV4dHJhY3RQaXZvdE5hbWUobmFtZSkgewogICAgcmV0dXJuIF9leHRyYWN0UGl2b3ROYW1lQ2FjaGVbbmFtZV0gfHwgKF9leHRyYWN0UGl2b3ROYW1lQ2FjaGVbbmFtZV0gPSBzcGxpdE9uRG90KG5hbWUpWzBdKTsKICB9CiAgLyoKICAgIGBJbnRlcm5hbE1vZGVsYCBpcyB0aGUgTW9kZWwgY2xhc3MgdGhhdCB3ZSB1c2UgaW50ZXJuYWxseSBpbnNpZGUgRW1iZXIgRGF0YSB0byByZXByZXNlbnQgbW9kZWxzLgogICAgSW50ZXJuYWwgRUQgbWV0aG9kcyBzaG91bGQgb25seSBkZWFsIHdpdGggYEludGVybmFsTW9kZWxgIG9iamVjdHMuIEl0IGlzIGEgZmFzdCwgcGxhaW4gSmF2YXNjcmlwdCBjbGFzcy4KCiAgICBXZSBleHBvc2UgYE1vZGVsYCB0byBhcHBsaWNhdGlvbiBjb2RlLCBieSBtYXRlcmlhbGl6aW5nIGEgYE1vZGVsYCBmcm9tIGBJbnRlcm5hbE1vZGVsYCBsYXppbHksIGFzCiAgICBhIHBlcmZvcm1hbmNlIG9wdGltaXphdGlvbi4KCiAgICBgSW50ZXJuYWxNb2RlbGAgc2hvdWxkIG5ldmVyIGJlIGV4cG9zZWQgdG8gYXBwbGljYXRpb24gY29kZS4gQXQgdGhlIGJvdW5kYXJpZXMgb2YgdGhlIHN5c3RlbSwgaW4gcGxhY2VzCiAgICBsaWtlIGBmaW5kYCwgYHB1c2hgLCBldGMuIHdlIGNvbnZlcnQgYmV0d2VlbiBNb2RlbHMgYW5kIEludGVybmFsTW9kZWxzLgoKICAgIFdlIG5lZWQgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIHByb3BlcnRpZXMgZnJvbSBgSW50ZXJuYWxNb2RlbGAgYXJlIGNvcnJlY3RseSBleHBvc2VkL3Byb3hpZWQgb24gYE1vZGVsYAogICAgaWYgdGhleSBhcmUgbmVlZGVkLgoKICAgIEBwcml2YXRlCiAgICBAY2xhc3MgSW50ZXJuYWxNb2RlbAogICovCgoKICB2YXIgSW50ZXJuYWxNb2RlbCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIC8vIE5vdCB0eXBlZCB5ZXQKICAgIC8vIFRoZSBwcmV2aW91cyBNYW55QXJyYXlzIGZvciB0aGlzIHJlbGF0aW9uc2hpcCB3aGljaCB3aWxsIGJlIGRlc3Ryb3llZCB3aGVuCiAgICAvLyB3ZSBjcmVhdGUgYSBuZXcgTWFueUFycmF5LCBidXQgaW4gdGhlIGludGVyaW0gdGhlIHJldGFpbmVkIHZlcnNpb24gd2lsbCBiZQogICAgLy8gdXBkYXRlZCBpZiBpbnZlcnNlIGludGVybmFsIG1vZGVscyBhcmUgdW5sb2FkZWQuCiAgICBmdW5jdGlvbiBJbnRlcm5hbE1vZGVsKHN0b3JlLCBpZGVudGlmaWVyKSB7CiAgICAgIHRoaXMuc3RvcmUgPSBzdG9yZTsKICAgICAgdGhpcy5pZGVudGlmaWVyID0gaWRlbnRpZmllcjsKICAgICAgdGhpcy5faWQgPSB2b2lkIDA7CiAgICAgIHRoaXMubW9kZWxOYW1lID0gdm9pZCAwOwogICAgICB0aGlzLmNsaWVudElkID0gdm9pZCAwOwogICAgICB0aGlzLl9fcmVjb3JkRGF0YSA9IHZvaWQgMDsKICAgICAgdGhpcy5faXNEZXN0cm95ZWQgPSB2b2lkIDA7CiAgICAgIHRoaXMuaXNFcnJvciA9IHZvaWQgMDsKICAgICAgdGhpcy5fcGVuZGluZ1JlY29yZEFycmF5TWFuYWdlckZsdXNoID0gdm9pZCAwOwogICAgICB0aGlzLl9pc0RlbWF0ZXJpYWxpemluZyA9IHZvaWQgMDsKICAgICAgdGhpcy5pc1JlbG9hZGluZyA9IHZvaWQgMDsKICAgICAgdGhpcy5fZG9Ob3REZXN0cm95ID0gdm9pZCAwOwogICAgICB0aGlzLmlzRGVzdHJveWluZyA9IHZvaWQgMDsKICAgICAgdGhpcy5fcHJvbWlzZVByb3h5ID0gdm9pZCAwOwogICAgICB0aGlzLl9yZWNvcmQgPSB2b2lkIDA7CiAgICAgIHRoaXMuX3NjaGVkdWxlZERlc3Ryb3kgPSB2b2lkIDA7CiAgICAgIHRoaXMuX21vZGVsQ2xhc3MgPSB2b2lkIDA7CiAgICAgIHRoaXMuX19kZWZlcnJlZFRyaWdnZXJzID0gdm9pZCAwOwogICAgICB0aGlzLl9fcmVjb3JkQXJyYXlzID0gdm9pZCAwOwogICAgICB0aGlzLl9yZWZlcmVuY2VzID0gdm9pZCAwOwogICAgICB0aGlzLl9yZWNvcmRSZWZlcmVuY2UgPSB2b2lkIDA7CiAgICAgIHRoaXMuX21hbnlBcnJheUNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGhpcy5fcmV0YWluZWRNYW55QXJyYXlDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHRoaXMuX3JlbGF0aW9uc2hpcFByb21pc2VzQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGhpcy5jdXJyZW50U3RhdGUgPSB2b2lkIDA7CiAgICAgIHRoaXMuZXJyb3IgPSB2b2lkIDA7CiAgICAgIHRoaXMuX2lkID0gaWRlbnRpZmllci5pZDsKICAgICAgdGhpcy5tb2RlbE5hbWUgPSBpZGVudGlmaWVyLnR5cGU7CiAgICAgIHRoaXMuY2xpZW50SWQgPSBpZGVudGlmaWVyLmxpZDsKICAgICAgdGhpcy5fX3JlY29yZERhdGEgPSBudWxsOyAvLyB0aGlzIGVuc3VyZSBvcmRlcmVkIHNldCBjYW4gcXVpY2tseSBpZGVudGlmeSB0aGlzIGFzIHVuaXF1ZQoKICAgICAgdGhpc1tFbWJlci5HVUlEX0tFWV0gPSBpZGVudGlmaWVyLmxpZDsKICAgICAgdGhpcy5fcHJvbWlzZVByb3h5ID0gbnVsbDsKICAgICAgdGhpcy5fcmVjb3JkID0gbnVsbDsKICAgICAgdGhpcy5faXNEZXN0cm95ZWQgPSBmYWxzZTsKICAgICAgdGhpcy5pc0Vycm9yID0gZmFsc2U7CiAgICAgIHRoaXMuX3BlbmRpbmdSZWNvcmRBcnJheU1hbmFnZXJGbHVzaCA9IGZhbHNlOyAvLyB1c2VkIGJ5IHRoZSByZWNvcmRBcnJheU1hbmFnZXIKICAgICAgLy8gRHVyaW5nIGRlbWF0ZXJpYWxpemF0aW9uIHdlIGRvbid0IHdhbnQgdG8gcmVtYXRlcmlhbGl6ZSB0aGUgcmVjb3JkLiAgVGhlCiAgICAgIC8vIHJlYXNvbiB0aGlzIG1pZ2h0IGhhcHBlbiBpcyB0aGF0IGRlbWF0ZXJpYWxpemF0aW9uIHJlbW92ZXMgcmVjb3JkcyBmcm9tCiAgICAgIC8vIHJlY29yZCBhcnJheXMsICBhbmQgRW1iZXIgYXJyYXlzIHdpbGwgYWx3YXlzIGBvYmplY3RBdCgwKWAgYW5kCiAgICAgIC8vIGBvYmplY3RBdChsZW4gLSAxKWAgdG8gdGVzdCB3aGV0aGVyIG9yIG5vdCBgZmlyc3RPYmplY3RgIG9yIGBsYXN0T2JqZWN0YAogICAgICAvLyBoYXZlIGNoYW5nZWQuCgogICAgICB0aGlzLl9pc0RlbWF0ZXJpYWxpemluZyA9IGZhbHNlOwogICAgICB0aGlzLl9zY2hlZHVsZWREZXN0cm95ID0gbnVsbDsKICAgICAgdGhpcy5yZXNldFJlY29yZCgpOyAvLyBjYWNoZXMgZm9yIGxhenkgZ2V0dGVycwoKICAgICAgdGhpcy5fbW9kZWxDbGFzcyA9IG51bGw7CiAgICAgIHRoaXMuX19kZWZlcnJlZFRyaWdnZXJzID0gbnVsbDsKICAgICAgdGhpcy5fX3JlY29yZEFycmF5cyA9IG51bGw7CiAgICAgIHRoaXMuX3JlZmVyZW5jZXMgPSBudWxsOwogICAgICB0aGlzLl9yZWNvcmRSZWZlcmVuY2UgPSBudWxsOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBJbnRlcm5hbE1vZGVsLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uaXNIaWRkZW5Gcm9tUmVjb3JkQXJyYXlzID0gZnVuY3Rpb24gaXNIaWRkZW5Gcm9tUmVjb3JkQXJyYXlzKCkgewogICAgICAvLyBEdXJpbmcgZGVtYXRlcmlhbGl6YXRpb24gd2UgZG9uJ3Qgd2FudCB0byByZW1hdGVyaWFsaXplIHRoZSByZWNvcmQuCiAgICAgIC8vIHJlY29yZFdhc0RlbGV0ZWQgY2FuIGNhdXNlIG90aGVyIHJlY29yZHMgdG8gcmVtYXRlcmlhbGl6ZSBiZWNhdXNlIGl0CiAgICAgIC8vIHJlbW92ZXMgdGhlIGludGVybmFsIG1vZGVsIGZyb20gdGhlIGFycmF5IGFuZCBFbWJlciBhcnJheXMgd2lsbCBhbHdheXMKICAgICAgLy8gYG9iamVjdEF0KDApYCBhbmQgYG9iamVjdEF0KGxlbiAtMSlgIHRvIGNoZWNrIHdoZXRoZXIgYGZpcnN0T2JqZWN0YCBvcgogICAgICAvLyBgbGFzdE9iamVjdGAgaGF2ZSBjaGFuZ2VkLiAgV2hlbiB0aGlzIGhhcHBlbnMgd2UgZG9uJ3Qgd2FudCB0aG9zZQogICAgICAvLyBtb2RlbHMgdG8gcmVtYXRlcmlhbGl6ZSB0aGVpciByZWNvcmRzLgogICAgICAvLyBlYWdlciBjaGVja3MgdG8gYXZvaWQgaW5zdGFudGlhdGluZyByZWNvcmQgZGF0YSBpZiB3ZSBhcmUgZW1wdHkgb3IgbG9hZGluZwogICAgICBpZiAodGhpcy5pc0VtcHR5KCkpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX1NUQVRFKSB7CiAgICAgICAgaWYgKHRoaXMuaXNMb2FkaW5nKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciBpc1JlY29yZEZ1bGx5RGVsZXRlZDsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9TVEFURSkgewogICAgICAgIGlzUmVjb3JkRnVsbHlEZWxldGVkID0gdGhpcy5faXNSZWNvcmRGdWxseURlbGV0ZWQoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpc1JlY29yZEZ1bGx5RGVsZXRlZCA9IHRoaXMuY3VycmVudFN0YXRlLnN0YXRlTmFtZSA9PT0gJ3Jvb3QuZGVsZXRlZC5zYXZlZCc7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLl9pc0RlbWF0ZXJpYWxpemluZyB8fCB0aGlzLmhhc1NjaGVkdWxlZERlc3Ryb3koKSB8fCB0aGlzLmlzRGVzdHJveWVkIHx8IGlzUmVjb3JkRnVsbHlEZWxldGVkOwogICAgfTsKCiAgICBfcHJvdG8uX2lzUmVjb3JkRnVsbHlEZWxldGVkID0gZnVuY3Rpb24gX2lzUmVjb3JkRnVsbHlEZWxldGVkKCkgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfU1RBVEUpIHsKICAgICAgICBpZiAodGhpcy5fcmVjb3JkRGF0YS5pc0RlbGV0aW9uQ29tbWl0dGVkICYmIHRoaXMuX3JlY29yZERhdGEuaXNEZWxldGlvbkNvbW1pdHRlZCgpKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX3JlY29yZERhdGEuaXNOZXcgJiYgdGhpcy5fcmVjb3JkRGF0YS5pc0RlbGV0ZWQgJiYgdGhpcy5fcmVjb3JkRGF0YS5pc05ldygpICYmIHRoaXMuX3JlY29yZERhdGEuaXNEZWxldGVkKCkpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50U3RhdGUuc3RhdGVOYW1lID09PSAncm9vdC5kZWxldGVkLnNhdmVkJzsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gYXNzZXJ0IGhlcmUKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmlzUmVjb3JkSW5Vc2UgPSBmdW5jdGlvbiBpc1JlY29yZEluVXNlKCkgewogICAgICB2YXIgcmVjb3JkID0gdGhpcy5fcmVjb3JkOwogICAgICByZXR1cm4gcmVjb3JkICYmICEocmVjb3JkLmdldCgnaXNEZXN0cm95ZWQnKSB8fCByZWNvcmQuZ2V0KCdpc0Rlc3Ryb3lpbmcnKSk7CiAgICB9OwoKICAgIF9wcm90by5pc0VtcHR5ID0gZnVuY3Rpb24gaXNFbXB0eSgpIHsKICAgICAgcmV0dXJuIHRoaXMuY3VycmVudFN0YXRlLmlzRW1wdHk7CiAgICB9OwoKICAgIF9wcm90by5pc0xvYWRpbmcgPSBmdW5jdGlvbiBpc0xvYWRpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5pc0xvYWRpbmc7CiAgICB9OwoKICAgIF9wcm90by5pc0xvYWRlZCA9IGZ1bmN0aW9uIGlzTG9hZGVkKCkgewogICAgICByZXR1cm4gdGhpcy5jdXJyZW50U3RhdGUuaXNMb2FkZWQ7CiAgICB9OwoKICAgIF9wcm90by5oYXNEaXJ0eUF0dHJpYnV0ZXMgPSBmdW5jdGlvbiBoYXNEaXJ0eUF0dHJpYnV0ZXMoKSB7CiAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5oYXNEaXJ0eUF0dHJpYnV0ZXM7CiAgICB9OwoKICAgIF9wcm90by5pc1NhdmluZyA9IGZ1bmN0aW9uIGlzU2F2aW5nKCkgewogICAgICByZXR1cm4gdGhpcy5jdXJyZW50U3RhdGUuaXNTYXZpbmc7CiAgICB9OwoKICAgIF9wcm90by5pc0RlbGV0ZWQgPSBmdW5jdGlvbiBpc0RlbGV0ZWQoKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9TVEFURSkgewogICAgICAgIGlmICh0aGlzLl9yZWNvcmREYXRhLmlzRGVsZXRlZCkgewogICAgICAgICAgcmV0dXJuIHRoaXMuX3JlY29yZERhdGEuaXNEZWxldGVkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5pc0RlbGV0ZWQ7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5pc0RlbGV0ZWQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmlzTmV3ID0gZnVuY3Rpb24gaXNOZXcoKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9TVEFURSkgewogICAgICAgIGlmICh0aGlzLl9yZWNvcmREYXRhLmlzTmV3KSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fcmVjb3JkRGF0YS5pc05ldygpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50U3RhdGUuaXNOZXc7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5pc05ldzsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uaXNWYWxpZCA9IGZ1bmN0aW9uIGlzVmFsaWQoKSB7CiAgICAgIGlmICghY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfRVJST1JTKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudFN0YXRlLmlzVmFsaWQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmRpcnR5VHlwZSA9IGZ1bmN0aW9uIGRpcnR5VHlwZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuY3VycmVudFN0YXRlLmRpcnR5VHlwZTsKICAgIH07CgogICAgX3Byb3RvLmdldFJlY29yZCA9IGZ1bmN0aW9uIGdldFJlY29yZChwcm9wZXJ0aWVzKSB7CiAgICAgIGlmICghdGhpcy5fcmVjb3JkICYmICF0aGlzLl9pc0RlbWF0ZXJpYWxpemluZykgewogICAgICAgIHZhciBfc3RvcmUgPSB0aGlzLnN0b3JlOwoKICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICB0aGlzLl9yZWNvcmQgPSBfc3RvcmUuX2luc3RhbnRpYXRlUmVjb3JkKHRoaXMsIHRoaXMubW9kZWxOYW1lLCB0aGlzLl9yZWNvcmREYXRhLCB0aGlzLmlkZW50aWZpZXIsIHByb3BlcnRpZXMpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoaXNOb3RDdXN0b21Nb2RlbENsYXNzKCkpIHsKICAgICAgICAgICAgLy8gbG9va3VwRmFjdG9yeSBzaG91bGQgcmVhbGx5IHJldHVybiBhbiBvYmplY3QgdGhhdCBjcmVhdGVzCiAgICAgICAgICAgIC8vIGluc3RhbmNlcyB3aXRoIHRoZSBpbmplY3Rpb25zIGFwcGxpZWQKICAgICAgICAgICAgdmFyIGNyZWF0ZU9wdGlvbnMgPSB7CiAgICAgICAgICAgICAgc3RvcmU6IF9zdG9yZSwKICAgICAgICAgICAgICBfaW50ZXJuYWxNb2RlbDogdGhpcywKICAgICAgICAgICAgICBjdXJyZW50U3RhdGU6IHRoaXMuY3VycmVudFN0YXRlCiAgICAgICAgICAgIH07CgogICAgICAgICAgICBpZiAoIWNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgICAgICAgICAgIGNyZWF0ZU9wdGlvbnMuaXNFcnJvciA9IHRoaXMuaXNFcnJvcjsKICAgICAgICAgICAgICBjcmVhdGVPcHRpb25zLmFkYXB0ZXJFcnJvciA9IHRoaXMuZXJyb3I7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzICE9PSB1bmRlZmluZWQpIHsKCiAgICAgICAgICAgICAgaWYgKCdpZCcgaW4gcHJvcGVydGllcykgewogICAgICAgICAgICAgICAgdmFyIGlkID0gY29lcmNlSWQocHJvcGVydGllcy5pZCk7CgogICAgICAgICAgICAgICAgaWYgKGlkICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIHRoaXMuc2V0SWQoaWQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0gLy8gY29udmVydCByZWxhdGlvbnNoaXAgUmVjb3JkcyB0byBSZWNvcmREYXRhcyBiZWZvcmUgcGFzc2luZyB0byBSZWNvcmREYXRhCgoKICAgICAgICAgICAgICB2YXIgZGVmcyA9IF9zdG9yZS5fcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IodGhpcy5tb2RlbE5hbWUpOwoKICAgICAgICAgICAgICBpZiAoZGVmcyAhPT0gbnVsbCkgewogICAgICAgICAgICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKTsKICAgICAgICAgICAgICAgIHZhciByZWxhdGlvbnNoaXBWYWx1ZTsKCiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgICAgdmFyIHByb3AgPSBrZXlzW2ldOwogICAgICAgICAgICAgICAgICB2YXIgZGVmID0gZGVmc1twcm9wXTsKCiAgICAgICAgICAgICAgICAgIGlmIChkZWYgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgICAgIGlmIChkZWYua2luZCA9PT0gJ2hhc01hbnknKSB7CgogICAgICAgICAgICAgICAgICAgICAgcmVsYXRpb25zaGlwVmFsdWUgPSBleHRyYWN0UmVjb3JkRGF0YXNGcm9tUmVjb3Jkcyhwcm9wZXJ0aWVzW3Byb3BdKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgcmVsYXRpb25zaGlwVmFsdWUgPSBleHRyYWN0UmVjb3JkRGF0YUZyb21SZWNvcmQocHJvcGVydGllc1twcm9wXSk7CiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzW3Byb3BdID0gcmVsYXRpb25zaGlwVmFsdWU7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHZhciBhZGRpdGlvbmFsQ3JlYXRlT3B0aW9ucyA9IHRoaXMuX3JlY29yZERhdGEuX2luaXRSZWNvcmRDcmVhdGVPcHRpb25zKHByb3BlcnRpZXMpOwoKICAgICAgICAgICAgRW1iZXIuYXNzaWduKGNyZWF0ZU9wdGlvbnMsIGFkZGl0aW9uYWxDcmVhdGVPcHRpb25zKTsgLy8gZW5zdXJlIHRoYXQgYGdldE93bmVyKHRoaXMpYCB3b3JrcyBpbnNpZGUgYSBtb2RlbCBpbnN0YW5jZQoKICAgICAgICAgICAgRW1iZXIuc2V0T3duZXIoY3JlYXRlT3B0aW9ucywgRW1iZXIuZ2V0T3duZXIoX3N0b3JlKSk7CiAgICAgICAgICAgIHRoaXMuX3JlY29yZCA9IF9zdG9yZS5fbW9kZWxGYWN0b3J5Rm9yKHRoaXMubW9kZWxOYW1lKS5jcmVhdGUoY3JlYXRlT3B0aW9ucyk7CiAgICAgICAgICAgIHNldFJlY29yZElkZW50aWZpZXIodGhpcy5fcmVjb3JkLCB0aGlzLmlkZW50aWZpZXIpOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgdGhpcy5fdHJpZ2dlckRlZmVycmVkVHJpZ2dlcnMoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuX3JlY29yZDsKICAgIH07CgogICAgX3Byb3RvLnJlc2V0UmVjb3JkID0gZnVuY3Rpb24gcmVzZXRSZWNvcmQoKSB7CiAgICAgIHRoaXMuX3JlY29yZCA9IG51bGw7CiAgICAgIHRoaXMuaXNSZWxvYWRpbmcgPSBmYWxzZTsKICAgICAgdGhpcy5lcnJvciA9IG51bGw7CiAgICAgIHRoaXMuY3VycmVudFN0YXRlID0gUm9vdFN0YXRlJDEuZW1wdHk7CiAgICB9OwoKICAgIF9wcm90by5kZW1hdGVyaWFsaXplUmVjb3JkID0gZnVuY3Rpb24gZGVtYXRlcmlhbGl6ZVJlY29yZCgpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHRoaXMuX2lzRGVtYXRlcmlhbGl6aW5nID0gdHJ1ZTsgLy8gVE9ETyBJR09SIGFkZCBhIHRlc3QgdGhhdCBmYWlscyB3aGVuIHRoaXMgaXMgbWlzc2luZywgc29tZXRoaW5nIHRoYXQgaW52b2x2ZXMgY2FuY2VsaWluZyBhIGRlc3Ryb3kKICAgICAgLy8gYW5kIHRoZSBkZXN0cm95IG5vdCBoYXBwZW5pbmcsIGFuZCB0aGVuIGxhdGVyIG9uIHRyeWluZyB0byBkZXN0cm95CgogICAgICB0aGlzLl9kb05vdERlc3Ryb3kgPSBmYWxzZTsKCiAgICAgIGlmICh0aGlzLl9yZWNvcmQpIHsKICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICB0aGlzLnN0b3JlLnRlYXJkb3duUmVjb3JkKHRoaXMuX3JlY29yZCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuX3JlY29yZC5kZXN0cm95KCk7CiAgICAgICAgfQoKICAgICAgICBPYmplY3Qua2V5cyh0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgIGlmIChfdGhpcy5fcmVsYXRpb25zaGlwUHJveHlDYWNoZVtrZXldLmRlc3Ryb3kpIHsKICAgICAgICAgICAgX3RoaXMuX3JlbGF0aW9uc2hpcFByb3h5Q2FjaGVba2V5XS5kZXN0cm95KCk7CiAgICAgICAgICB9CgogICAgICAgICAgZGVsZXRlIF90aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlW2tleV07CiAgICAgICAgfSk7CiAgICAgICAgT2JqZWN0LmtleXModGhpcy5fbWFueUFycmF5Q2FjaGUpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgdmFyIG1hbnlBcnJheSA9IF90aGlzLl9yZXRhaW5lZE1hbnlBcnJheUNhY2hlW2tleV0gPSBfdGhpcy5fbWFueUFycmF5Q2FjaGVba2V5XTsKICAgICAgICAgIGRlbGV0ZSBfdGhpcy5fbWFueUFycmF5Q2FjaGVba2V5XTsKCiAgICAgICAgICBpZiAobWFueUFycmF5ICYmICFtYW55QXJyYXkuX2ludmVyc2VJc0FzeW5jKSB7CiAgICAgICAgICAgIC8qCiAgICAgICAgICAgICAgSWYgdGhlIG1hbnlBcnJheSBpcyBmb3IgYSBzeW5jIHJlbGF0aW9uc2hpcCwgd2Ugc2hvdWxkIGNsZWFyIGl0CiAgICAgICAgICAgICAgICB0byBwcmVzZXJ2ZSB0aGUgc2VtYW50aWNzIG9mIGNsaWVudC1zaWRlIGRlbGV0ZS4KICAgICAgICAgICAgICAgSXQgaXMgbGlrZWx5IGluIHRoaXMgY2FzZSBpbnN0ZWFkIG9mIHJldGFpbmluZyB3ZSBzaG91bGQgZGVzdHJveQogICAgICAgICAgICAgICAgLSBAcnVuc3BpcmVkCiAgICAgICAgICAgICovCiAgICAgICAgICAgIG1hbnlBcnJheS5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9IC8vIG1vdmUgdG8gYW4gZW1wdHkgbmV2ZXItbG9hZGVkIHN0YXRlCgoKICAgICAgdGhpcy5fcmVjb3JkRGF0YS51bmxvYWRSZWNvcmQoKTsKCiAgICAgIHRoaXMucmVzZXRSZWNvcmQoKTsKICAgICAgdGhpcy51cGRhdGVSZWNvcmRBcnJheXMoKTsKICAgIH07CgogICAgX3Byb3RvLmRlbGV0ZVJlY29yZCA9IGZ1bmN0aW9uIGRlbGV0ZVJlY29yZCgpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX1NUQVRFKSB7CiAgICAgICAgaWYgKHRoaXMuX3JlY29yZERhdGEuc2V0SXNEZWxldGVkKSB7CiAgICAgICAgICB0aGlzLl9yZWNvcmREYXRhLnNldElzRGVsZXRlZCh0cnVlKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHRoaXMuc2VuZCgnZGVsZXRlUmVjb3JkJyk7CiAgICB9OwoKICAgIF9wcm90by5zYXZlID0gZnVuY3Rpb24gc2F2ZShvcHRpb25zKSB7CiAgICAgIHZhciBwcm9taXNlTGFiZWwgPSAnRFM6IE1vZGVsI3NhdmUgJyArIHRoaXM7CiAgICAgIHZhciByZXNvbHZlciA9IEVtYmVyLlJTVlAuZGVmZXIocHJvbWlzZUxhYmVsKTsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICAvLyBDYXN0aW5nIHRvIG5hcnJvdyBkdWUgdG8gdGhlIGZlYXR1cmUgZmxhZyBwYXRocyBpbnNpZGUgc2NoZWR1bGVTYXZlCiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuc2NoZWR1bGVTYXZlKHRoaXMsIHJlc29sdmVyLCBvcHRpb25zKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnN0b3JlLnNjaGVkdWxlU2F2ZSh0aGlzLCByZXNvbHZlciwgb3B0aW9ucyk7CiAgICAgICAgcmV0dXJuIHJlc29sdmVyLnByb21pc2U7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnN0YXJ0ZWRSZWxvYWRpbmcgPSBmdW5jdGlvbiBzdGFydGVkUmVsb2FkaW5nKCkgewogICAgICB0aGlzLmlzUmVsb2FkaW5nID0gdHJ1ZTsKCiAgICAgIGlmICh0aGlzLmhhc1JlY29yZCkgewogICAgICAgIEVtYmVyLnNldCh0aGlzLl9yZWNvcmQsICdpc1JlbG9hZGluZycsIHRydWUpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5saW5rV2FzTG9hZGVkRm9yUmVsYXRpb25zaGlwID0gZnVuY3Rpb24gbGlua1dhc0xvYWRlZEZvclJlbGF0aW9uc2hpcChrZXksIGRhdGEpIHsKICAgICAgdmFyIHJlbGF0aW9uc2hpcHMgPSB7fTsKICAgICAgcmVsYXRpb25zaGlwc1trZXldID0gZGF0YTsKCiAgICAgIHRoaXMuX3JlY29yZERhdGEucHVzaERhdGEoewogICAgICAgIGlkOiB0aGlzLmlkLAogICAgICAgIHR5cGU6IHRoaXMubW9kZWxOYW1lLAogICAgICAgIHJlbGF0aW9uc2hpcHM6IHJlbGF0aW9uc2hpcHMKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5maW5pc2hlZFJlbG9hZGluZyA9IGZ1bmN0aW9uIGZpbmlzaGVkUmVsb2FkaW5nKCkgewogICAgICB0aGlzLmlzUmVsb2FkaW5nID0gZmFsc2U7CgogICAgICBpZiAodGhpcy5oYXNSZWNvcmQpIHsKICAgICAgICBFbWJlci5zZXQodGhpcy5fcmVjb3JkLCAnaXNSZWxvYWRpbmcnLCBmYWxzZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnJlbG9hZCA9IGZ1bmN0aW9uIHJlbG9hZChvcHRpb25zKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICBpZiAoIW9wdGlvbnMpIHsKICAgICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgICB9CgogICAgICAgIHRoaXMuc3RhcnRlZFJlbG9hZGluZygpOwogICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gdGhpczsKICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5zdG9yZS5fcmVsb2FkUmVjb3JkKGludGVybmFsTW9kZWwsIG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgLy9UT0RPIE5PVyBzZWVtcyBsaWtlIHdlIHNob3VsZG4ndCBuZWVkIHRvIGRvIHRoaXMKICAgICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsOwogICAgICAgIH0sIGZ1bmN0aW9uIChlcnJvcikgewogICAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgICAgfSwgJ0RTOiBNb2RlbCNyZWxvYWQgY29tcGxldGUsIHVwZGF0ZSBmbGFncycpLmZpbmFsbHkoZnVuY3Rpb24gKCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC5maW5pc2hlZFJlbG9hZGluZygpOwogICAgICAgICAgaW50ZXJuYWxNb2RlbC51cGRhdGVSZWNvcmRBcnJheXMoKTsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnN0YXJ0ZWRSZWxvYWRpbmcoKTsKCiAgICAgICAgdmFyIF9pbnRlcm5hbE1vZGVsID0gdGhpczsKCiAgICAgICAgdmFyIHByb21pc2VMYWJlbCA9ICdEUzogTW9kZWwjcmVsb2FkIG9mICcgKyB0aGlzOwogICAgICAgIHJldHVybiBuZXcgRW1iZXIuUlNWUC5Qcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7CiAgICAgICAgICBfaW50ZXJuYWxNb2RlbC5zZW5kKCdyZWxvYWRSZWNvcmQnLCB7CiAgICAgICAgICAgIHJlc29sdmU6IHJlc29sdmUsCiAgICAgICAgICAgIG9wdGlvbnM6IG9wdGlvbnMKICAgICAgICAgIH0pOwogICAgICAgIH0sIHByb21pc2VMYWJlbCkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICBfaW50ZXJuYWxNb2RlbC5kaWRDbGVhbkVycm9yKCk7CgogICAgICAgICAgcmV0dXJuIF9pbnRlcm5hbE1vZGVsOwogICAgICAgIH0sIGZ1bmN0aW9uIChlcnJvcikgewogICAgICAgICAgX2ludGVybmFsTW9kZWwuZGlkRXJyb3IoZXJyb3IpOwoKICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgIH0sICdEUzogTW9kZWwjcmVsb2FkIGNvbXBsZXRlLCB1cGRhdGUgZmxhZ3MnKS5maW5hbGx5KGZ1bmN0aW9uICgpIHsKICAgICAgICAgIF9pbnRlcm5hbE1vZGVsLmZpbmlzaGVkUmVsb2FkaW5nKCk7CgogICAgICAgICAgX2ludGVybmFsTW9kZWwudXBkYXRlUmVjb3JkQXJyYXlzKCk7CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIC8qCiAgICAgIFVubG9hZCB0aGUgcmVjb3JkIGZvciB0aGlzIGludGVybmFsIG1vZGVsLiBUaGlzIHdpbGwgY2F1c2UgdGhlIHJlY29yZCB0byBiZQogICAgICBkZXN0cm95ZWQgYW5kIGZyZWVkIHVwIGZvciBnYXJiYWdlIGNvbGxlY3Rpb24uIEl0IHdpbGwgYWxzbyBkbyBhIGNoZWNrCiAgICAgIGZvciBjbGVhbmluZyB1cCBpbnRlcm5hbCBtb2RlbHMuCiAgICAgICBUaGlzIGNoZWNrIGlzIHBlcmZvcm1lZCBieSBmaXJzdCBjb21wdXRpbmcgdGhlIHNldCBvZiByZWxhdGVkIGludGVybmFsCiAgICAgIG1vZGVscy4gSWYgYWxsIHJlY29yZHMgaW4gdGhpcyBzZXQgYXJlIHVubG9hZGVkLCB0aGVuIHRoZSBlbnRpcmUgc2V0IGlzCiAgICAgIGRlc3Ryb3llZC4gT3RoZXJ3aXNlLCBub3RoaW5nIGluIHRoZSBzZXQgaXMgZGVzdHJveWVkLgogICAgICAgVGhpcyBtZWFucyB0aGF0IHRoaXMgaW50ZXJuYWwgbW9kZWwgd2lsbCBiZSBmcmVlZCB1cCBmb3IgZ2FyYmFnZSBjb2xsZWN0aW9uCiAgICAgIG9uY2UgYWxsIG1vZGVscyB0aGF0IHJlZmVyIHRvIGl0IHZpYSBzb21lIHJlbGF0aW9uc2hpcCBhcmUgYWxzbyB1bmxvYWRlZC4KICAgICovCiAgICA7CgogICAgX3Byb3RvLnVubG9hZFJlY29yZCA9IGZ1bmN0aW9uIHVubG9hZFJlY29yZCgpIHsKICAgICAgaWYgKHRoaXMuaXNEZXN0cm95ZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuc2VuZCgndW5sb2FkUmVjb3JkJyk7CiAgICAgIHRoaXMuZGVtYXRlcmlhbGl6ZVJlY29yZCgpOwoKICAgICAgaWYgKHRoaXMuX3NjaGVkdWxlZERlc3Ryb3kgPT09IG51bGwpIHsKICAgICAgICB0aGlzLl9zY2hlZHVsZWREZXN0cm95ID0gRW1iZXIucnVuLmJhY2tidXJuZXIuc2NoZWR1bGUoJ2Rlc3Ryb3knLCB0aGlzLCAnX2NoZWNrRm9yT3JwaGFuZWRJbnRlcm5hbE1vZGVscycpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5oYXNTY2hlZHVsZWREZXN0cm95ID0gZnVuY3Rpb24gaGFzU2NoZWR1bGVkRGVzdHJveSgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fc2NoZWR1bGVkRGVzdHJveTsKICAgIH07CgogICAgX3Byb3RvLmNhbmNlbERlc3Ryb3kgPSBmdW5jdGlvbiBjYW5jZWxEZXN0cm95KCkgewogICAgICB0aGlzLl9kb05vdERlc3Ryb3kgPSB0cnVlOwogICAgICB0aGlzLl9pc0RlbWF0ZXJpYWxpemluZyA9IGZhbHNlOwogICAgICBFbWJlci5ydW4uY2FuY2VsKHRoaXMuX3NjaGVkdWxlZERlc3Ryb3kpOwogICAgICB0aGlzLl9zY2hlZHVsZWREZXN0cm95ID0gbnVsbDsKICAgIH0gLy8gdHlwaWNhbGx5LCB3ZSBwcmVmZXIgdG8gYXN5bmMgZGVzdHJveSB0aGlzIGxldHMgdXMgYmF0Y2ggY2xlYW51cCB3b3JrLgogICAgLy8gVW5mb3J0dW5hdGVseSwgc29tZSBzY2VuYXJpb3Mgd2hlcmUgdGhhdCBpcyBub3QgcG9zc2libGUuIFN1Y2ggYXM6CiAgICAvLwogICAgLy8gYGBganMKICAgIC8vIGNvbnN0IHJlY29yZCA9IHN0b3JlLmZpbmQo4oCYcmVjb3Jk4oCZLCAxKTsKICAgIC8vIHJlY29yZC51bmxvYWRSZWNvcmQoKTsKICAgIC8vIHN0b3JlLmNyZWF0ZVJlY29yZCjigJhyZWNvcmTigJksIDEpOwogICAgLy8gYGBgCiAgICAvLwogICAgLy8gSW4gdGhvc2Ugc2NlbmFyaW9zLCB3ZSBtYWtlIHRoYXQgbW9kZWwncyBjbGVhbnVwIHdvcmssIHN5bmMuCiAgICAvLwogICAgOwoKICAgIF9wcm90by5kZXN0cm95U3luYyA9IGZ1bmN0aW9uIGRlc3Ryb3lTeW5jKCkgewogICAgICBpZiAodGhpcy5faXNEZW1hdGVyaWFsaXppbmcpIHsKICAgICAgICB0aGlzLmNhbmNlbERlc3Ryb3koKTsKICAgICAgfQoKICAgICAgdGhpcy5fY2hlY2tGb3JPcnBoYW5lZEludGVybmFsTW9kZWxzKCk7CgogICAgICBpZiAodGhpcy5pc0Rlc3Ryb3llZCB8fCB0aGlzLmlzRGVzdHJveWluZykgewogICAgICAgIHJldHVybjsKICAgICAgfSAvLyBqdXN0IGluLWNhc2Ugd2UgYXJlIG5vdCBvbmUgb2YgdGhlIG9ycGhhbmVkLCB3ZSBzaG91bGQgc3RpbGwKICAgICAgLy8gc3RpbGwgZGVzdHJveSBvdXJzZWx2ZXMKCgogICAgICB0aGlzLmRlc3Ryb3koKTsKICAgIH07CgogICAgX3Byb3RvLl9jaGVja0Zvck9ycGhhbmVkSW50ZXJuYWxNb2RlbHMgPSBmdW5jdGlvbiBfY2hlY2tGb3JPcnBoYW5lZEludGVybmFsTW9kZWxzKCkgewogICAgICB0aGlzLl9pc0RlbWF0ZXJpYWxpemluZyA9IGZhbHNlOwogICAgICB0aGlzLl9zY2hlZHVsZWREZXN0cm95ID0gbnVsbDsKCiAgICAgIGlmICh0aGlzLmlzRGVzdHJveWVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5lYWNoUmVsYXRpb25zaGlwID0gZnVuY3Rpb24gZWFjaFJlbGF0aW9uc2hpcChjYWxsYmFjaywgYmluZGluZykgewogICAgICByZXR1cm4gdGhpcy5tb2RlbENsYXNzLmVhY2hSZWxhdGlvbnNoaXAoY2FsbGJhY2ssIGJpbmRpbmcpOwogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRCZWxvbmdzVG8gPSBmdW5jdGlvbiBfZmluZEJlbG9uZ3NUbyhrZXksIHJlc291cmNlLCByZWxhdGlvbnNoaXBNZXRhLCBvcHRpb25zKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgLy8gVE9ETyBAcnVuc3BpcmVkIGZvbGxvdyB1cCBpZiBwYXJlbnQgaXNOZXcgdGhlbiB3ZSBzaG91bGQgbm90IGJlIGF0dGVtcHRpbmcgbG9hZCBoZXJlCiAgICAgIHJldHVybiB0aGlzLnN0b3JlLl9maW5kQmVsb25nc1RvQnlKc29uQXBpUmVzb3VyY2UocmVzb3VyY2UsIHRoaXMsIHJlbGF0aW9uc2hpcE1ldGEsIG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKGludGVybmFsTW9kZWwpIHsKICAgICAgICByZXR1cm4gaGFuZGxlQ29tcGxldGVkUmVsYXRpb25zaGlwUmVxdWVzdChfdGhpczIsIGtleSwgcmVzb3VyY2UuX3JlbGF0aW9uc2hpcCwgaW50ZXJuYWxNb2RlbCwgbnVsbCk7CiAgICAgIH0sIGZ1bmN0aW9uIChlKSB7CiAgICAgICAgcmV0dXJuIGhhbmRsZUNvbXBsZXRlZFJlbGF0aW9uc2hpcFJlcXVlc3QoX3RoaXMyLCBrZXksIHJlc291cmNlLl9yZWxhdGlvbnNoaXAsIG51bGwsIGUpOwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvLmdldEJlbG9uZ3NUbyA9IGZ1bmN0aW9uIGdldEJlbG9uZ3NUbyhrZXksIG9wdGlvbnMpIHsKICAgICAgdmFyIHJlc291cmNlID0gdGhpcy5fcmVjb3JkRGF0YS5nZXRCZWxvbmdzVG8oa2V5KTsKCiAgICAgIHZhciBpZGVudGlmaWVyID0gcmVzb3VyY2UgJiYgcmVzb3VyY2UuZGF0YSA/IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzLnN0b3JlKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UuZGF0YSkgOiBudWxsOwoKICAgICAgdmFyIHJlbGF0aW9uc2hpcE1ldGEgPSB0aGlzLnN0b3JlLl9yZWxhdGlvbnNoaXBNZXRhRm9yKHRoaXMubW9kZWxOYW1lLCBudWxsLCBrZXkpOwoKICAgICAgdmFyIHN0b3JlID0gdGhpcy5zdG9yZTsKICAgICAgdmFyIGFzeW5jID0gcmVsYXRpb25zaGlwTWV0YS5vcHRpb25zLmFzeW5jOwogICAgICB2YXIgaXNBc3luYyA9IHR5cGVvZiBhc3luYyA9PT0gJ3VuZGVmaW5lZCcgPyB0cnVlIDogYXN5bmM7CiAgICAgIHZhciBfYmVsb25nc1RvU3RhdGUgPSB7CiAgICAgICAga2V5OiBrZXksCiAgICAgICAgc3RvcmU6IHN0b3JlLAogICAgICAgIG9yaWdpbmF0aW5nSW50ZXJuYWxNb2RlbDogdGhpcywKICAgICAgICBtb2RlbE5hbWU6IHJlbGF0aW9uc2hpcE1ldGEudHlwZQogICAgICB9OwoKICAgICAgaWYgKGlzQXN5bmMpIHsKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGlkZW50aWZpZXIgIT09IG51bGwgPyBzdG9yZS5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlKGlkZW50aWZpZXIpIDogbnVsbDsKCiAgICAgICAgaWYgKHJlc291cmNlLl9yZWxhdGlvbnNoaXAuaGFzRmFpbGVkTG9hZEF0dGVtcHQpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlW2tleV07CiAgICAgICAgfQoKICAgICAgICB2YXIgcHJvbWlzZSA9IHRoaXMuX2ZpbmRCZWxvbmdzVG8oa2V5LCByZXNvdXJjZSwgcmVsYXRpb25zaGlwTWV0YSwgb3B0aW9ucyk7CgogICAgICAgIHJldHVybiB0aGlzLl91cGRhdGVQcm9taXNlUHJveHlGb3IoJ2JlbG9uZ3NUbycsIGtleSwgewogICAgICAgICAgcHJvbWlzZTogcHJvbWlzZSwKICAgICAgICAgIGNvbnRlbnQ6IGludGVybmFsTW9kZWwgPyBpbnRlcm5hbE1vZGVsLmdldFJlY29yZCgpIDogbnVsbCwKICAgICAgICAgIF9iZWxvbmdzVG9TdGF0ZTogX2JlbG9uZ3NUb1N0YXRlCiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaWYgKGlkZW50aWZpZXIgPT09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB2YXIgX2ludGVybmFsTW9kZWwyID0gc3RvcmUuX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShpZGVudGlmaWVyKTsKCiAgICAgICAgICB2YXIgdG9SZXR1cm4gPSBfaW50ZXJuYWxNb2RlbDIuZ2V0UmVjb3JkKCk7CiAgICAgICAgICByZXR1cm4gdG9SZXR1cm47CiAgICAgICAgfQogICAgICB9CiAgICB9IC8vIFRPRE8gSWdvciBjb25zaWRlciBnZXR0aW5nIHJpZCBvZiBpbml0aWFsIHN0YXRlCiAgICA7CgogICAgX3Byb3RvLmdldE1hbnlBcnJheSA9IGZ1bmN0aW9uIGdldE1hbnlBcnJheShrZXksIGlzQXN5bmMpIHsKICAgICAgaWYgKGlzQXN5bmMgPT09IHZvaWQgMCkgewogICAgICAgIGlzQXN5bmMgPSBmYWxzZTsKICAgICAgfQoKICAgICAgdmFyIHJlbGF0aW9uc2hpcE1ldGEgPSB0aGlzLnN0b3JlLl9yZWxhdGlvbnNoaXBNZXRhRm9yKHRoaXMubW9kZWxOYW1lLCBudWxsLCBrZXkpOwoKICAgICAgdmFyIGpzb25BcGkgPSB0aGlzLl9yZWNvcmREYXRhLmdldEhhc01hbnkoa2V5KTsKCiAgICAgIHZhciBtYW55QXJyYXkgPSB0aGlzLl9tYW55QXJyYXlDYWNoZVtrZXldOwoKICAgICAgaWYgKCFtYW55QXJyYXkpIHsKICAgICAgICB2YXIgaW5pdGlhbFN0YXRlID0gdGhpcy5zdG9yZS5fZ2V0SGFzTWFueUJ5SnNvbkFwaVJlc291cmNlKGpzb25BcGkpOyAvLyBUT0RPIG1vdmUgdGhpcyB0byBhIHB1YmxpYyBhcGkKCgogICAgICAgIHZhciBpbnZlcnNlSXNBc3luYyA9IGpzb25BcGkuX3JlbGF0aW9uc2hpcCA/IGpzb25BcGkuX3JlbGF0aW9uc2hpcC5faW52ZXJzZUlzQXN5bmMoKSA6IGZhbHNlOwogICAgICAgIG1hbnlBcnJheSA9IE1hbnlBcnJheS5jcmVhdGUoewogICAgICAgICAgc3RvcmU6IHRoaXMuc3RvcmUsCiAgICAgICAgICB0eXBlOiB0aGlzLnN0b3JlLm1vZGVsRm9yKHJlbGF0aW9uc2hpcE1ldGEudHlwZSksCiAgICAgICAgICByZWNvcmREYXRhOiB0aGlzLl9yZWNvcmREYXRhLAogICAgICAgICAgbWV0YToganNvbkFwaS5tZXRhLAogICAgICAgICAga2V5OiBrZXksCiAgICAgICAgICBpc1BvbHltb3JwaGljOiByZWxhdGlvbnNoaXBNZXRhLm9wdGlvbnMucG9seW1vcnBoaWMsCiAgICAgICAgICBpbml0aWFsU3RhdGU6IGluaXRpYWxTdGF0ZS5zbGljZSgpLAogICAgICAgICAgX2ludmVyc2VJc0FzeW5jOiBpbnZlcnNlSXNBc3luYywKICAgICAgICAgIGludGVybmFsTW9kZWw6IHRoaXMsCiAgICAgICAgICBpc0xvYWRlZDogIWlzQXN5bmMKICAgICAgICB9KTsKICAgICAgICB0aGlzLl9tYW55QXJyYXlDYWNoZVtrZXldID0gbWFueUFycmF5OwogICAgICB9CgogICAgICBpZiAodGhpcy5fcmV0YWluZWRNYW55QXJyYXlDYWNoZVtrZXldKSB7CiAgICAgICAgdGhpcy5fcmV0YWluZWRNYW55QXJyYXlDYWNoZVtrZXldLmRlc3Ryb3koKTsKCiAgICAgICAgZGVsZXRlIHRoaXMuX3JldGFpbmVkTWFueUFycmF5Q2FjaGVba2V5XTsKICAgICAgfQoKICAgICAgcmV0dXJuIG1hbnlBcnJheTsKICAgIH07CgogICAgX3Byb3RvLmZldGNoQXN5bmNIYXNNYW55ID0gZnVuY3Rpb24gZmV0Y2hBc3luY0hhc01hbnkoa2V5LCByZWxhdGlvbnNoaXBNZXRhLCBqc29uQXBpLCBtYW55QXJyYXksIG9wdGlvbnMpIHsKICAgICAgdmFyIF90aGlzMyA9IHRoaXM7CgogICAgICAvLyBUT0RPIEBydW5zcGlyZWQgZm9sbG93IHVwIGlmIHBhcmVudCBpc05ldyB0aGVuIHdlIHNob3VsZCBub3QgYmUgYXR0ZW1wdGluZyBsb2FkIGhlcmUKICAgICAgdmFyIGxvYWRpbmdQcm9taXNlID0gdGhpcy5fcmVsYXRpb25zaGlwUHJvbWlzZXNDYWNoZVtrZXldOwoKICAgICAgaWYgKGxvYWRpbmdQcm9taXNlKSB7CiAgICAgICAgcmV0dXJuIGxvYWRpbmdQcm9taXNlOwogICAgICB9CgogICAgICBsb2FkaW5nUHJvbWlzZSA9IHRoaXMuc3RvcmUuX2ZpbmRIYXNNYW55QnlKc29uQXBpUmVzb3VyY2UoanNvbkFwaSwgdGhpcywgcmVsYXRpb25zaGlwTWV0YSwgb3B0aW9ucykudGhlbihmdW5jdGlvbiAoaW5pdGlhbFN0YXRlKSB7CiAgICAgICAgLy8gVE9ETyB3aHkgZG9uJ3Qgd2UgZG8gdGhpcyBpbiB0aGUgc3RvcmUgbWV0aG9kCiAgICAgICAgbWFueUFycmF5LnJldHJpZXZlTGF0ZXN0KCk7CiAgICAgICAgbWFueUFycmF5LnNldCgnaXNMb2FkZWQnLCB0cnVlKTsKICAgICAgICByZXR1cm4gbWFueUFycmF5OwogICAgICB9KS50aGVuKGZ1bmN0aW9uIChtYW55QXJyYXkpIHsKICAgICAgICByZXR1cm4gaGFuZGxlQ29tcGxldGVkUmVsYXRpb25zaGlwUmVxdWVzdChfdGhpczMsIGtleSwganNvbkFwaS5fcmVsYXRpb25zaGlwLCBtYW55QXJyYXksIG51bGwpOwogICAgICB9LCBmdW5jdGlvbiAoZSkgewogICAgICAgIHJldHVybiBoYW5kbGVDb21wbGV0ZWRSZWxhdGlvbnNoaXBSZXF1ZXN0KF90aGlzMywga2V5LCBqc29uQXBpLl9yZWxhdGlvbnNoaXAsIG51bGwsIGUpOwogICAgICB9KTsKICAgICAgdGhpcy5fcmVsYXRpb25zaGlwUHJvbWlzZXNDYWNoZVtrZXldID0gbG9hZGluZ1Byb21pc2U7CiAgICAgIHJldHVybiBsb2FkaW5nUHJvbWlzZTsKICAgIH07CgogICAgX3Byb3RvLmdldEhhc01hbnkgPSBmdW5jdGlvbiBnZXRIYXNNYW55KGtleSwgb3B0aW9ucykgewogICAgICB2YXIganNvbkFwaSA9IHRoaXMuX3JlY29yZERhdGEuZ2V0SGFzTWFueShrZXkpOwoKICAgICAgdmFyIHJlbGF0aW9uc2hpcE1ldGEgPSB0aGlzLnN0b3JlLl9yZWxhdGlvbnNoaXBNZXRhRm9yKHRoaXMubW9kZWxOYW1lLCBudWxsLCBrZXkpOwoKICAgICAgdmFyIGFzeW5jID0gcmVsYXRpb25zaGlwTWV0YS5vcHRpb25zLmFzeW5jOwogICAgICB2YXIgaXNBc3luYyA9IHR5cGVvZiBhc3luYyA9PT0gJ3VuZGVmaW5lZCcgPyB0cnVlIDogYXN5bmM7CiAgICAgIHZhciBtYW55QXJyYXkgPSB0aGlzLmdldE1hbnlBcnJheShrZXksIGlzQXN5bmMpOwoKICAgICAgaWYgKGlzQXN5bmMpIHsKICAgICAgICBpZiAoanNvbkFwaS5fcmVsYXRpb25zaGlwLmhhc0ZhaWxlZExvYWRBdHRlbXB0KSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fcmVsYXRpb25zaGlwUHJveHlDYWNoZVtrZXldOwogICAgICAgIH0KCiAgICAgICAgdmFyIHByb21pc2UgPSB0aGlzLmZldGNoQXN5bmNIYXNNYW55KGtleSwgcmVsYXRpb25zaGlwTWV0YSwganNvbkFwaSwgbWFueUFycmF5LCBvcHRpb25zKTsKICAgICAgICByZXR1cm4gdGhpcy5fdXBkYXRlUHJvbWlzZVByb3h5Rm9yKCdoYXNNYW55Jywga2V5LCB7CiAgICAgICAgICBwcm9taXNlOiBwcm9taXNlLAogICAgICAgICAgY29udGVudDogbWFueUFycmF5CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG1hbnlBcnJheTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX3VwZGF0ZVByb21pc2VQcm94eUZvciA9IGZ1bmN0aW9uIF91cGRhdGVQcm9taXNlUHJveHlGb3Ioa2luZCwga2V5LCBhcmdzKSB7CiAgICAgIHZhciBwcm9taXNlUHJveHkgPSB0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlW2tleV07CgogICAgICBpZiAocHJvbWlzZVByb3h5KSB7CiAgICAgICAgaWYgKGFyZ3MuY29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAvLyB0aGlzIHVzYWdlIG9mIGBhbnlgIGNhbiBiZSByZW1vdmVkIHdoZW4gYEB0eXBlcy9lbWJlcl9vYmplY3RgIHByb3h5IGFsbG93cyBgbnVsbGAgZm9yIGNvbnRlbnQKICAgICAgICAgIHByb21pc2VQcm94eS5zZXQoJ2NvbnRlbnQnLCBhcmdzLmNvbnRlbnQpOwogICAgICAgIH0KCiAgICAgICAgcHJvbWlzZVByb3h5LnNldCgncHJvbWlzZScsIGFyZ3MucHJvbWlzZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIGtsYXNzID0ga2luZCA9PT0gJ2hhc01hbnknID8gUHJvbWlzZU1hbnlBcnJheSA6IFByb21pc2VCZWxvbmdzVG87IC8vIHRoaXMgdXNhZ2Ugb2YgYGFueWAgY2FuIGJlIHJlbW92ZWQgd2hlbiBgQHR5cGVzL2VtYmVyX29iamVjdGAgcHJveHkgYWxsb3dzIGBudWxsYCBmb3IgY29udGVudAoKICAgICAgICB0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlW2tleV0gPSBrbGFzcy5jcmVhdGUoYXJncyk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlW2tleV07CiAgICB9OwoKICAgIF9wcm90by5yZWxvYWRIYXNNYW55ID0gZnVuY3Rpb24gcmVsb2FkSGFzTWFueShrZXksIG9wdGlvbnMpIHsKICAgICAgdmFyIGxvYWRpbmdQcm9taXNlID0gdGhpcy5fcmVsYXRpb25zaGlwUHJvbWlzZXNDYWNoZVtrZXldOwoKICAgICAgaWYgKGxvYWRpbmdQcm9taXNlKSB7CiAgICAgICAgcmV0dXJuIGxvYWRpbmdQcm9taXNlOwogICAgICB9CgogICAgICB2YXIganNvbkFwaSA9IHRoaXMuX3JlY29yZERhdGEuZ2V0SGFzTWFueShrZXkpOyAvLyBUT0RPIG1vdmUgdGhpcyB0byBhIHB1YmxpYyBhcGkKCgogICAgICBpZiAoanNvbkFwaS5fcmVsYXRpb25zaGlwKSB7CiAgICAgICAganNvbkFwaS5fcmVsYXRpb25zaGlwLnNldEhhc0ZhaWxlZExvYWRBdHRlbXB0KGZhbHNlKTsKCiAgICAgICAganNvbkFwaS5fcmVsYXRpb25zaGlwLnNldFNob3VsZEZvcmNlUmVsb2FkKHRydWUpOwogICAgICB9CgogICAgICB2YXIgcmVsYXRpb25zaGlwTWV0YSA9IHRoaXMuc3RvcmUuX3JlbGF0aW9uc2hpcE1ldGFGb3IodGhpcy5tb2RlbE5hbWUsIG51bGwsIGtleSk7CgogICAgICB2YXIgbWFueUFycmF5ID0gdGhpcy5nZXRNYW55QXJyYXkoa2V5KTsKICAgICAgdmFyIHByb21pc2UgPSB0aGlzLmZldGNoQXN5bmNIYXNNYW55KGtleSwgcmVsYXRpb25zaGlwTWV0YSwganNvbkFwaSwgbWFueUFycmF5LCBvcHRpb25zKTsKCiAgICAgIGlmICh0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlW2tleV0pIHsKICAgICAgICByZXR1cm4gdGhpcy5fdXBkYXRlUHJvbWlzZVByb3h5Rm9yKCdoYXNNYW55Jywga2V5LCB7CiAgICAgICAgICBwcm9taXNlOiBwcm9taXNlCiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBwcm9taXNlOwogICAgfTsKCiAgICBfcHJvdG8ucmVsb2FkQmVsb25nc1RvID0gZnVuY3Rpb24gcmVsb2FkQmVsb25nc1RvKGtleSwgb3B0aW9ucykgewogICAgICB2YXIgbG9hZGluZ1Byb21pc2UgPSB0aGlzLl9yZWxhdGlvbnNoaXBQcm9taXNlc0NhY2hlW2tleV07CgogICAgICBpZiAobG9hZGluZ1Byb21pc2UpIHsKICAgICAgICByZXR1cm4gbG9hZGluZ1Byb21pc2U7CiAgICAgIH0KCiAgICAgIHZhciByZXNvdXJjZSA9IHRoaXMuX3JlY29yZERhdGEuZ2V0QmVsb25nc1RvKGtleSk7IC8vIFRPRE8gbW92ZSB0aGlzIHRvIGEgcHVibGljIGFwaQoKCiAgICAgIGlmIChyZXNvdXJjZS5fcmVsYXRpb25zaGlwKSB7CiAgICAgICAgcmVzb3VyY2UuX3JlbGF0aW9uc2hpcC5zZXRIYXNGYWlsZWRMb2FkQXR0ZW1wdChmYWxzZSk7CgogICAgICAgIHJlc291cmNlLl9yZWxhdGlvbnNoaXAuc2V0U2hvdWxkRm9yY2VSZWxvYWQodHJ1ZSk7CiAgICAgIH0KCiAgICAgIHZhciByZWxhdGlvbnNoaXBNZXRhID0gdGhpcy5zdG9yZS5fcmVsYXRpb25zaGlwTWV0YUZvcih0aGlzLm1vZGVsTmFtZSwgbnVsbCwga2V5KTsKCiAgICAgIHZhciBwcm9taXNlID0gdGhpcy5fZmluZEJlbG9uZ3NUbyhrZXksIHJlc291cmNlLCByZWxhdGlvbnNoaXBNZXRhLCBvcHRpb25zKTsKCiAgICAgIGlmICh0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlW2tleV0pIHsKICAgICAgICByZXR1cm4gdGhpcy5fdXBkYXRlUHJvbWlzZVByb3h5Rm9yKCdiZWxvbmdzVG8nLCBrZXksIHsKICAgICAgICAgIHByb21pc2U6IHByb21pc2UKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIHByb21pc2U7CiAgICB9OwoKICAgIF9wcm90by5kZXN0cm95RnJvbVJlY29yZERhdGEgPSBmdW5jdGlvbiBkZXN0cm95RnJvbVJlY29yZERhdGEoKSB7CiAgICAgIGlmICh0aGlzLl9kb05vdERlc3Ryb3kpIHsKICAgICAgICB0aGlzLl9kb05vdERlc3Ryb3kgPSBmYWxzZTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuZGVzdHJveSgpOwogICAgfTsKCiAgICBfcHJvdG8uZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHZhciBfdGhpczQgPSB0aGlzOwogICAgICB0aGlzLmlzRGVzdHJveWluZyA9IHRydWU7CiAgICAgIE9iamVjdC5rZXlzKHRoaXMuX3JldGFpbmVkTWFueUFycmF5Q2FjaGUpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgIF90aGlzNC5fcmV0YWluZWRNYW55QXJyYXlDYWNoZVtrZXldLmRlc3Ryb3koKTsKCiAgICAgICAgZGVsZXRlIF90aGlzNC5fcmV0YWluZWRNYW55QXJyYXlDYWNoZVtrZXldOwogICAgICB9KTsKICAgICAgaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcy5zdG9yZSkucmVtb3ZlKHRoaXMpOwogICAgICB0aGlzLl9pc0Rlc3Ryb3llZCA9IHRydWU7CiAgICB9OwoKICAgIF9wcm90by5lYWNoQXR0cmlidXRlID0gZnVuY3Rpb24gZWFjaEF0dHJpYnV0ZShjYWxsYmFjaywgYmluZGluZykgewogICAgICByZXR1cm4gdGhpcy5tb2RlbENsYXNzLmVhY2hBdHRyaWJ1dGUoY2FsbGJhY2ssIGJpbmRpbmcpOwogICAgfTsKCiAgICBfcHJvdG8uaW52ZXJzZUZvciA9IGZ1bmN0aW9uIGludmVyc2VGb3Ioa2V5KSB7CiAgICAgIHJldHVybiB0aGlzLm1vZGVsQ2xhc3MuaW52ZXJzZUZvcihrZXkpOwogICAgfTsKCiAgICBfcHJvdG8uc2V0dXBEYXRhID0gZnVuY3Rpb24gc2V0dXBEYXRhKGRhdGEpIHsKICAgICAgdmFyIGNoYW5nZWRLZXlzID0gdGhpcy5fcmVjb3JkRGF0YS5wdXNoRGF0YShkYXRhLCB0aGlzLmhhc1JlY29yZCk7CgogICAgICBpZiAodGhpcy5oYXNSZWNvcmQpIHsKICAgICAgICB0aGlzLl9yZWNvcmQuX25vdGlmeVByb3BlcnRpZXMoY2hhbmdlZEtleXMpOwogICAgICB9CgogICAgICB0aGlzLnB1c2hlZERhdGEoKTsKICAgIH07CgogICAgX3Byb3RvLmdldEF0dHJpYnV0ZVZhbHVlID0gZnVuY3Rpb24gZ2V0QXR0cmlidXRlVmFsdWUoa2V5KSB7CiAgICAgIHJldHVybiB0aGlzLl9yZWNvcmREYXRhLmdldEF0dHIoa2V5KTsKICAgIH07CgogICAgX3Byb3RvLnNldERpcnR5SGFzTWFueSA9IGZ1bmN0aW9uIHNldERpcnR5SGFzTWFueShrZXksIHJlY29yZHMpIHsKICAgICAgcmV0dXJuIHRoaXMuX3JlY29yZERhdGEuc2V0RGlydHlIYXNNYW55KGtleSwgZXh0cmFjdFJlY29yZERhdGFzRnJvbVJlY29yZHMocmVjb3JkcykpOwogICAgfTsKCiAgICBfcHJvdG8uc2V0RGlydHlCZWxvbmdzVG8gPSBmdW5jdGlvbiBzZXREaXJ0eUJlbG9uZ3NUbyhrZXksIHZhbHVlKSB7CiAgICAgIHJldHVybiB0aGlzLl9yZWNvcmREYXRhLnNldERpcnR5QmVsb25nc1RvKGtleSwgZXh0cmFjdFJlY29yZERhdGFGcm9tUmVjb3JkKHZhbHVlKSk7CiAgICB9OwoKICAgIF9wcm90by5zZXREaXJ0eUF0dHJpYnV0ZSA9IGZ1bmN0aW9uIHNldERpcnR5QXR0cmlidXRlKGtleSwgdmFsdWUpIHsKICAgICAgaWYgKHRoaXMuaXNEZWxldGVkKCkpIHsKICAgICAgICB0aHJvdyBuZXcgRW1iZXIuRXJyb3IoIkF0dGVtcHRlZCB0byBzZXQgJyIgKyBrZXkgKyAiJyB0byAnIiArIHZhbHVlICsgIicgb24gdGhlIGRlbGV0ZWQgcmVjb3JkICIgKyB0aGlzKTsKICAgICAgfQoKICAgICAgdmFyIGN1cnJlbnRWYWx1ZSA9IHRoaXMuZ2V0QXR0cmlidXRlVmFsdWUoa2V5KTsKCiAgICAgIGlmIChjdXJyZW50VmFsdWUgIT09IHZhbHVlKSB7CiAgICAgICAgdGhpcy5fcmVjb3JkRGF0YS5zZXREaXJ0eUF0dHJpYnV0ZShrZXksIHZhbHVlKTsKCiAgICAgICAgdmFyIGlzRGlydHkgPSB0aGlzLl9yZWNvcmREYXRhLmlzQXR0ckRpcnR5KGtleSk7CgogICAgICAgIHRoaXMuc2VuZCgnZGlkU2V0UHJvcGVydHknLCB7CiAgICAgICAgICBuYW1lOiBrZXksCiAgICAgICAgICBpc0RpcnR5OiBpc0RpcnR5CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH07CgogICAgLyoKICAgICAgQG1ldGhvZCBjcmVhdGVTbmFwc2hvdAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9wcm90by5jcmVhdGVTbmFwc2hvdCA9IGZ1bmN0aW9uIGNyZWF0ZVNuYXBzaG90KG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIG5ldyBTbmFwc2hvdChvcHRpb25zIHx8IHt9LCB0aGlzLmlkZW50aWZpZXIsIHRoaXMuc3RvcmUpOwogICAgfQogICAgLyoKICAgICAgQG1ldGhvZCBsb2FkaW5nRGF0YQogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICA7CgogICAgX3Byb3RvLmxvYWRpbmdEYXRhID0gZnVuY3Rpb24gbG9hZGluZ0RhdGEocHJvbWlzZSkgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgdGhpcy5zZW5kKCdsb2FkaW5nRGF0YScpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuc2VuZCgnbG9hZGluZ0RhdGEnLCBwcm9taXNlKTsKICAgICAgfQogICAgfQogICAgLyoKICAgICAgQG1ldGhvZCBsb2FkZWREYXRhCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5sb2FkZWREYXRhID0gZnVuY3Rpb24gbG9hZGVkRGF0YSgpIHsKICAgICAgdGhpcy5zZW5kKCdsb2FkZWREYXRhJyk7CiAgICB9CiAgICAvKgogICAgICBAbWV0aG9kIG5vdEZvdW5kCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5ub3RGb3VuZCA9IGZ1bmN0aW9uIG5vdEZvdW5kKCkgewogICAgICB0aGlzLnNlbmQoJ25vdEZvdW5kJyk7CiAgICB9CiAgICAvKgogICAgICBAbWV0aG9kIHB1c2hlZERhdGEKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLnB1c2hlZERhdGEgPSBmdW5jdGlvbiBwdXNoZWREYXRhKCkgewogICAgICB0aGlzLnNlbmQoJ3B1c2hlZERhdGEnKTsKICAgIH07CgogICAgX3Byb3RvLmhhc0NoYW5nZWRBdHRyaWJ1dGVzID0gZnVuY3Rpb24gaGFzQ2hhbmdlZEF0dHJpYnV0ZXMoKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICBpZiAoIXRoaXMuX19yZWNvcmREYXRhKSB7CiAgICAgICAgICAvLyBubyBuZWVkIHRvIGNhbGN1bGF0ZSBjaGFuZ2VkIGF0dHJpYnV0ZXMgd2hlbiBjYWxsaW5nIGBmaW5kUmVjb3JkYAogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAodGhpcy5pc0xvYWRpbmcoKSAmJiAhdGhpcy5pc1JlbG9hZGluZykgewogICAgICAgICAgLy8gbm8gbmVlZCB0byBjYWxjdWxhdGUgY2hhbmdlZCBhdHRyaWJ1dGVzIHdoZW4gY2FsbGluZyBgZmluZFJlY29yZGAKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLl9yZWNvcmREYXRhLmhhc0NoYW5nZWRBdHRyaWJ1dGVzKCk7CiAgICB9CiAgICAvKgogICAgICBSZXR1cm5zIGFuIG9iamVjdCwgd2hvc2Uga2V5cyBhcmUgY2hhbmdlZCBwcm9wZXJ0aWVzLCBhbmQgdmFsdWUgaXMgYW4KICAgICAgW29sZFByb3AsIG5ld1Byb3BdIGFycmF5LgogICAgICAgQG1ldGhvZCBjaGFuZ2VkQXR0cmlidXRlcwogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uY2hhbmdlZEF0dHJpYnV0ZXMgPSBmdW5jdGlvbiBjaGFuZ2VkQXR0cmlidXRlcygpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgICAgIGlmICghdGhpcy5fX3JlY29yZERhdGEpIHsKICAgICAgICAgIC8vIG5vIG5lZWQgdG8gY2FsY3VsYXRlIGNoYW5nZWQgYXR0cmlidXRlcyB3aGVuIGNhbGxpbmcgYGZpbmRSZWNvcmRgCiAgICAgICAgICByZXR1cm4ge307CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGlmICh0aGlzLmlzTG9hZGluZygpICYmICF0aGlzLmlzUmVsb2FkaW5nKSB7CiAgICAgICAgICAvLyBubyBuZWVkIHRvIGNhbGN1bGF0ZSBjaGFuZ2VkIGF0dHJpYnV0ZXMgd2hlbiBjYWxsaW5nIGBmaW5kUmVjb3JkYAogICAgICAgICAgcmV0dXJuIHt9OwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuX3JlY29yZERhdGEuY2hhbmdlZEF0dHJpYnV0ZXMoKTsKICAgIH0KICAgIC8qCiAgICAgIEBtZXRob2QgYWRhcHRlcldpbGxDb21taXQKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmFkYXB0ZXJXaWxsQ29tbWl0ID0gZnVuY3Rpb24gYWRhcHRlcldpbGxDb21taXQoKSB7CiAgICAgIHRoaXMuX3JlY29yZERhdGEud2lsbENvbW1pdCgpOwoKICAgICAgdGhpcy5zZW5kKCd3aWxsQ29tbWl0Jyk7CiAgICB9CiAgICAvKgogICAgICBAbWV0aG9kIGFkYXB0ZXJEaWREaXJ0eQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uYWRhcHRlckRpZERpcnR5ID0gZnVuY3Rpb24gYWRhcHRlckRpZERpcnR5KCkgewogICAgICB0aGlzLnNlbmQoJ2JlY29tZURpcnR5Jyk7CiAgICAgIHRoaXMudXBkYXRlUmVjb3JkQXJyYXlzKCk7CiAgICB9CiAgICAvKgogICAgICBAbWV0aG9kIHNlbmQKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUKICAgICAgQHBhcmFtIHtPYmplY3R9IGNvbnRleHQKICAgICovCiAgICA7CgogICAgX3Byb3RvLnNlbmQgPSBmdW5jdGlvbiBzZW5kKG5hbWUsIGNvbnRleHQpIHsKICAgICAgdmFyIGN1cnJlbnRTdGF0ZSA9IHRoaXMuY3VycmVudFN0YXRlOwoKICAgICAgaWYgKCFjdXJyZW50U3RhdGVbbmFtZV0pIHsKICAgICAgICB0aGlzLl91bmhhbmRsZWRFdmVudChjdXJyZW50U3RhdGUsIG5hbWUsIGNvbnRleHQpOwogICAgICB9CgogICAgICByZXR1cm4gY3VycmVudFN0YXRlW25hbWVdKHRoaXMsIGNvbnRleHQpOwogICAgfTsKCiAgICBfcHJvdG8ubWFueUFycmF5UmVjb3JkQWRkZWQgPSBmdW5jdGlvbiBtYW55QXJyYXlSZWNvcmRBZGRlZChrZXkpIHsKICAgICAgaWYgKHRoaXMuaGFzUmVjb3JkKSB7CiAgICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgICAgdGhpcy5zdG9yZS5fbm90aWZpY2F0aW9uTWFuYWdlci5ub3RpZnkodGhpcy5pZGVudGlmaWVyLCAncmVsYXRpb25zaGlwcycpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9yZWNvcmQubm90aWZ5SGFzTWFueUFkZGVkKGtleSk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlIYXNNYW55Q2hhbmdlID0gZnVuY3Rpb24gbm90aWZ5SGFzTWFueUNoYW5nZShrZXkpIHsKICAgICAgaWYgKHRoaXMuaGFzUmVjb3JkKSB7CiAgICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgICAgdGhpcy5zdG9yZS5fbm90aWZpY2F0aW9uTWFuYWdlci5ub3RpZnkodGhpcy5pZGVudGlmaWVyLCAncmVsYXRpb25zaGlwcycpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB2YXIgbWFueUFycmF5ID0gdGhpcy5fbWFueUFycmF5Q2FjaGVba2V5XTsKCiAgICAgICAgICBpZiAobWFueUFycmF5KSB7CiAgICAgICAgICAgIC8vIFRPRE86IHRoaXMgd2lsbCAicmVzdXJyZWN0IiBwcmV2aW91c2x5IHVubG9hZGVkIHJlY29yZHMKICAgICAgICAgICAgLy8gc2VlIHRlc3QgJzE6bWFueSBhc3luYyB1bmxvYWQgbWFueSBzaWRlJwogICAgICAgICAgICAvLyAgaW4gYHRlc3RzL2ludGVncmF0aW9uL3JlY29yZHMvdW5sb2FkLXRlc3QuanNgCiAgICAgICAgICAgIC8vICBwcm9iYWJseSB3ZSBkb24ndCB3YW50IHRvIHJldHJpZXZlIGxhdGVzdCBlYWdlcmx5IHdoZW4gbm90aWZ5aGFzbWFueSBjaGFuZ2VkCiAgICAgICAgICAgIC8vICBidXQgcmF0aGVyIGxhemlseSB3aGVuIHNvbWVvbmUgYWN0dWFsbHkgYXNrcyBmb3IgYSBtYW55YXJyYXkKICAgICAgICAgICAgLy8KICAgICAgICAgICAgLy8gIHRoYXQgc2FpZCwgYWxzbyBub3QgY2xlYXIgd2h5IHdlIGhhdmVuJ3QgbW92ZWQgdGhpcyB0byByZXRhaW5lZG1hbnlhcnJheSBzbyBtYXliZSB0aGF0J3MgdGhlIGJpdCB0aGF0J3MganVzdCBub3Qgd29ya2lnbgogICAgICAgICAgICBtYW55QXJyYXkucmV0cmlldmVMYXRlc3QoKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHRoaXMudXBkYXRlUmVjb3JkQXJyYXlzKCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLm5vdGlmeUJlbG9uZ3NUb0NoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeUJlbG9uZ3NUb0NoYW5nZShrZXkpIHsKICAgICAgaWYgKHRoaXMuaGFzUmVjb3JkKSB7CiAgICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgICAgdGhpcy5zdG9yZS5fbm90aWZpY2F0aW9uTWFuYWdlci5ub3RpZnkodGhpcy5pZGVudGlmaWVyLCAncmVsYXRpb25zaGlwcycpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9yZWNvcmQubm90aWZ5QmVsb25nc1RvQ2hhbmdlKGtleSwgdGhpcy5fcmVjb3JkKTsKICAgICAgICB9CgogICAgICAgIHRoaXMudXBkYXRlUmVjb3JkQXJyYXlzKCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmhhc01hbnlSZW1vdmFsQ2hlY2sgPSBmdW5jdGlvbiBoYXNNYW55UmVtb3ZhbENoZWNrKGtleSkgewogICAgICB2YXIgbWFueUFycmF5ID0gdGhpcy5fbWFueUFycmF5Q2FjaGVba2V5XSB8fCB0aGlzLl9yZXRhaW5lZE1hbnlBcnJheUNhY2hlW2tleV07CiAgICAgIHZhciBkaWRSZW1vdmVVbmxvYWRlZE1vZGVsID0gZmFsc2U7CgogICAgICBpZiAobWFueUFycmF5KSB7CiAgICAgICAgZGlkUmVtb3ZlVW5sb2FkZWRNb2RlbCA9IG1hbnlBcnJheS5yZW1vdmVVbmxvYWRlZEludGVybmFsTW9kZWwoKTsKCiAgICAgICAgaWYgKHRoaXMuX21hbnlBcnJheUNhY2hlW2tleV0gJiYgZGlkUmVtb3ZlVW5sb2FkZWRNb2RlbCkgewogICAgICAgICAgdGhpcy5fcmV0YWluZWRNYW55QXJyYXlDYWNoZVtrZXldID0gdGhpcy5fbWFueUFycmF5Q2FjaGVba2V5XTsKICAgICAgICAgIGRlbGV0ZSB0aGlzLl9tYW55QXJyYXlDYWNoZVtrZXldOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGRpZFJlbW92ZVVubG9hZGVkTW9kZWw7CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlQcm9wZXJ0eUNoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeVByb3BlcnR5Q2hhbmdlKGtleSkgewogICAgICBpZiAodGhpcy5oYXNSZWNvcmQpIHsKICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICB0aGlzLnN0b3JlLl9ub3RpZmljYXRpb25NYW5hZ2VyLm5vdGlmeSh0aGlzLmlkZW50aWZpZXIsICdwcm9wZXJ0eScpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9yZWNvcmQubm90aWZ5UHJvcGVydHlDaGFuZ2Uoa2V5KTsKICAgICAgICB9CgogICAgICAgIHRoaXMudXBkYXRlUmVjb3JkQXJyYXlzKCk7CiAgICAgIH0KCiAgICAgIGlmICghY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgdmFyIG1hbnlBcnJheSA9IHRoaXMuX21hbnlBcnJheUNhY2hlW2tleV0gfHwgdGhpcy5fcmV0YWluZWRNYW55QXJyYXlDYWNoZVtrZXldOwoKICAgICAgICBpZiAobWFueUFycmF5KSB7CiAgICAgICAgICB2YXIgZGlkUmVtb3ZlVW5sb2FkZWRNb2RlbCA9IG1hbnlBcnJheS5yZW1vdmVVbmxvYWRlZEludGVybmFsTW9kZWwoKTsKCiAgICAgICAgICBpZiAodGhpcy5fbWFueUFycmF5Q2FjaGVba2V5XSAmJiBkaWRSZW1vdmVVbmxvYWRlZE1vZGVsKSB7CiAgICAgICAgICAgIHRoaXMuX3JldGFpbmVkTWFueUFycmF5Q2FjaGVba2V5XSA9IHRoaXMuX21hbnlBcnJheUNhY2hlW2tleV07CiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9tYW55QXJyYXlDYWNoZVtrZXldOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ubm90aWZ5U3RhdGVDaGFuZ2UgPSBmdW5jdGlvbiBub3RpZnlTdGF0ZUNoYW5nZShrZXkpIHsKCiAgICAgIGlmICh0aGlzLmhhc1JlY29yZCkgewogICAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICAgIHRoaXMuc3RvcmUuX25vdGlmaWNhdGlvbk1hbmFnZXIubm90aWZ5KHRoaXMuaWRlbnRpZmllciwgJ3N0YXRlJyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmICgha2V5IHx8IGtleSA9PT0gJ2lzTmV3JykgewogICAgICAgICAgICB0aGlzLmdldFJlY29yZCgpLm5vdGlmeVByb3BlcnR5Q2hhbmdlKCdpc05ldycpOwogICAgICAgICAgfQoKICAgICAgICAgIGlmICgha2V5IHx8IGtleSA9PT0gJ2lzRGVsZXRlZCcpIHsKICAgICAgICAgICAgdGhpcy5nZXRSZWNvcmQoKS5ub3RpZnlQcm9wZXJ0eUNoYW5nZSgnaXNEZWxldGVkJyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoIWtleSB8fCBrZXkgPT09ICdpc0RlbGV0aW9uQ29tbWl0dGVkJykgewogICAgICAgIHRoaXMudXBkYXRlUmVjb3JkQXJyYXlzKCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmRpZENyZWF0ZVJlY29yZCA9IGZ1bmN0aW9uIGRpZENyZWF0ZVJlY29yZCgpIHsKICAgICAgdGhpcy5fcmVjb3JkRGF0YS5jbGllbnREaWRDcmVhdGUoKTsKICAgIH07CgogICAgX3Byb3RvLnJvbGxiYWNrQXR0cmlidXRlcyA9IGZ1bmN0aW9uIHJvbGxiYWNrQXR0cmlidXRlcygpIHsKICAgICAgdmFyIGRpcnR5S2V5cyA9IHRoaXMuX3JlY29yZERhdGEucm9sbGJhY2tBdHRyaWJ1dGVzKCk7CgogICAgICBpZiAoRW1iZXIuZ2V0KHRoaXMsICdpc0Vycm9yJykpIHsKICAgICAgICB0aGlzLmRpZENsZWFuRXJyb3IoKTsKICAgICAgfQoKICAgICAgdGhpcy5zZW5kKCdyb2xsZWRCYWNrJyk7CgogICAgICBpZiAodGhpcy5fcmVjb3JkICYmIGRpcnR5S2V5cyAmJiBkaXJ0eUtleXMubGVuZ3RoID4gMCkgewogICAgICAgIHRoaXMuX3JlY29yZC5fbm90aWZ5UHJvcGVydGllcyhkaXJ0eUtleXMpOwogICAgICB9CiAgICB9CiAgICAvKgogICAgICBAbWV0aG9kIHRyYW5zaXRpb25UbwogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8udHJhbnNpdGlvblRvID0gZnVuY3Rpb24gdHJhbnNpdGlvblRvKG5hbWUpIHsKICAgICAgLy8gUE9TU0lCTEUgVE9ETzogUmVtb3ZlIHRoaXMgY29kZSBhbmQgcmVwbGFjZSB3aXRoCiAgICAgIC8vIGFsd2F5cyBoYXZpbmcgZGlyZWN0IHJlZmVyZW5jZSB0byBzdGF0ZSBvYmplY3RzCiAgICAgIHZhciBwaXZvdE5hbWUgPSBleHRyYWN0UGl2b3ROYW1lKG5hbWUpOwogICAgICB2YXIgc3RhdGUgPSB0aGlzLmN1cnJlbnRTdGF0ZTsKICAgICAgdmFyIHRyYW5zaXRpb25NYXBJZCA9IHN0YXRlLnN0YXRlTmFtZSArICItPiIgKyBuYW1lOwoKICAgICAgZG8gewogICAgICAgIGlmIChzdGF0ZS5leGl0KSB7CiAgICAgICAgICBzdGF0ZS5leGl0KHRoaXMpOwogICAgICAgIH0KCiAgICAgICAgc3RhdGUgPSBzdGF0ZS5wYXJlbnRTdGF0ZTsKICAgICAgfSB3aGlsZSAoIXN0YXRlW3Bpdm90TmFtZV0pOwoKICAgICAgdmFyIHNldHVwczsKICAgICAgdmFyIGVudGVyczsKICAgICAgdmFyIGk7CiAgICAgIHZhciBsOwogICAgICB2YXIgbWFwID0gVHJhbnNpdGlvbkNoYWluTWFwW3RyYW5zaXRpb25NYXBJZF07CgogICAgICBpZiAobWFwKSB7CiAgICAgICAgc2V0dXBzID0gbWFwLnNldHVwczsKICAgICAgICBlbnRlcnMgPSBtYXAuZW50ZXJzOwogICAgICAgIHN0YXRlID0gbWFwLnN0YXRlOwogICAgICB9IGVsc2UgewogICAgICAgIHNldHVwcyA9IFtdOwogICAgICAgIGVudGVycyA9IFtdOwogICAgICAgIHZhciBwYXRoID0gc3BsaXRPbkRvdChuYW1lKTsKCiAgICAgICAgZm9yIChpID0gMCwgbCA9IHBhdGgubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICBzdGF0ZSA9IHN0YXRlW3BhdGhbaV1dOwoKICAgICAgICAgIGlmIChzdGF0ZS5lbnRlcikgewogICAgICAgICAgICBlbnRlcnMucHVzaChzdGF0ZSk7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKHN0YXRlLnNldHVwKSB7CiAgICAgICAgICAgIHNldHVwcy5wdXNoKHN0YXRlKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIFRyYW5zaXRpb25DaGFpbk1hcFt0cmFuc2l0aW9uTWFwSWRdID0gewogICAgICAgICAgc2V0dXBzOiBzZXR1cHMsCiAgICAgICAgICBlbnRlcnM6IGVudGVycywKICAgICAgICAgIHN0YXRlOiBzdGF0ZQogICAgICAgIH07CiAgICAgIH0KCiAgICAgIGZvciAoaSA9IDAsIGwgPSBlbnRlcnMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgZW50ZXJzW2ldLmVudGVyKHRoaXMpOwogICAgICB9CgogICAgICB0aGlzLmN1cnJlbnRTdGF0ZSA9IHN0YXRlOwoKICAgICAgaWYgKHRoaXMuaGFzUmVjb3JkKSB7CiAgICAgICAgRW1iZXIuc2V0KHRoaXMuX3JlY29yZCwgJ2N1cnJlbnRTdGF0ZScsIHN0YXRlKTsKICAgICAgfQoKICAgICAgZm9yIChpID0gMCwgbCA9IHNldHVwcy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICBzZXR1cHNbaV0uc2V0dXAodGhpcyk7CiAgICAgIH0KCiAgICAgIHRoaXMudXBkYXRlUmVjb3JkQXJyYXlzKCk7CiAgICB9OwoKICAgIF9wcm90by5fdW5oYW5kbGVkRXZlbnQgPSBmdW5jdGlvbiBfdW5oYW5kbGVkRXZlbnQoc3RhdGUsIG5hbWUsIGNvbnRleHQpIHsKICAgICAgdmFyIGVycm9yTWVzc2FnZSA9ICdBdHRlbXB0ZWQgdG8gaGFuZGxlIGV2ZW50IGAnICsgbmFtZSArICdgICc7CiAgICAgIGVycm9yTWVzc2FnZSArPSAnb24gJyArIFN0cmluZyh0aGlzKSArICcgd2hpbGUgaW4gc3RhdGUgJzsKICAgICAgZXJyb3JNZXNzYWdlICs9IHN0YXRlLnN0YXRlTmFtZSArICcuICc7CgogICAgICBpZiAoY29udGV4dCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZXJyb3JNZXNzYWdlICs9ICdDYWxsZWQgd2l0aCAnICsgRW1iZXIuaW5zcGVjdChjb250ZXh0KSArICcuJzsKICAgICAgfQoKICAgICAgdGhyb3cgbmV3IEVtYmVyLkVycm9yKGVycm9yTWVzc2FnZSk7CiAgICB9OwoKICAgIF9wcm90by50cmlnZ2VyTGF0ZXIgPSBmdW5jdGlvbiB0cmlnZ2VyTGF0ZXIoKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLl9kZWZlcnJlZFRyaWdnZXJzLnB1c2goYXJncykgIT09IDEpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuc3RvcmUuX3VwZGF0ZUludGVybmFsTW9kZWwodGhpcyk7CiAgICB9OwoKICAgIF9wcm90by5fdHJpZ2dlckRlZmVycmVkVHJpZ2dlcnMgPSBmdW5jdGlvbiBfdHJpZ2dlckRlZmVycmVkVHJpZ2dlcnMoKSB7CiAgICAgIC8vVE9ETzogQmVmb3JlIDEuMCB3ZSB3YW50IHRvIHJlbW92ZSBhbGwgdGhlIGV2ZW50cyB0aGF0IGhhcHBlbiBvbiB0aGUgcHJlIG1hdGVyaWFsaXplZCByZWNvcmQsCiAgICAgIC8vYnV0IGZvciBub3csIHdlIHF1ZXVlIHVwIGFsbCB0aGUgZXZlbnRzIHRyaWdnZXJlZCBiZWZvcmUgdGhlIHJlY29yZCB3YXMgbWF0ZXJpYWxpemVkLCBhbmQgZmx1c2gKICAgICAgLy90aGVtIG9uY2Ugd2UgaGF2ZSB0aGUgcmVjb3JkCiAgICAgIGlmICghdGhpcy5oYXNSZWNvcmQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciB0cmlnZ2VycyA9IHRoaXMuX2RlZmVycmVkVHJpZ2dlcnM7CiAgICAgIHZhciByZWNvcmQgPSB0aGlzLl9yZWNvcmQ7CiAgICAgIHZhciB0cmlnZ2VyID0gcmVjb3JkLnRyaWdnZXI7IC8vIFRPRE8gSWdvciBtYWtlIG5pY2VyIGNoZWNrCgogICAgICBpZiAodHJpZ2dlciAmJiB0eXBlb2YgdHJpZ2dlciA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gdHJpZ2dlcnMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICB2YXIgZXZlbnROYW1lID0gdHJpZ2dlcnNbaV07CiAgICAgICAgICB0cmlnZ2VyLmFwcGx5KHJlY29yZCwgZXZlbnROYW1lKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHRyaWdnZXJzLmxlbmd0aCA9IDA7CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVGcm9tSW52ZXJzZVJlbGF0aW9uc2hpcHMgPSBmdW5jdGlvbiByZW1vdmVGcm9tSW52ZXJzZVJlbGF0aW9uc2hpcHMoaXNOZXcpIHsKICAgICAgaWYgKGlzTmV3ID09PSB2b2lkIDApIHsKICAgICAgICBpc05ldyA9IGZhbHNlOwogICAgICB9CgogICAgICB0aGlzLl9yZWNvcmREYXRhLnJlbW92ZUZyb21JbnZlcnNlUmVsYXRpb25zaGlwcyhpc05ldyk7CiAgICB9CiAgICAvKgogICAgICBXaGVuIGEgZmluZCByZXF1ZXN0IGlzIHRyaWdnZXJlZCBvbiB0aGUgc3RvcmUsIHRoZSB1c2VyIGNhbiBvcHRpb25hbGx5IHBhc3MgaW4KICAgICAgYXR0cmlidXRlcyBhbmQgcmVsYXRpb25zaGlwcyB0byBiZSBwcmVsb2FkZWQuIFRoZXNlIGFyZSBtZWFudCB0byBiZWhhdmUgYXMgaWYgdGhleQogICAgICBjYW1lIGJhY2sgZnJvbSB0aGUgc2VydmVyLCBleGNlcHQgdGhlIHVzZXIgb2J0YWluZWQgdGhlbSBvdXQgb2YgYmFuZCBhbmQgaXMgaW5mb3JtaW5nCiAgICAgIHRoZSBzdG9yZSBvZiB0aGVpciBleGlzdGVuY2UuIFRoZSBtb3N0IGNvbW1vbiB1c2UgY2FzZSBpcyBmb3Igc3VwcG9ydGluZyBjbGllbnQgc2lkZQogICAgICBuZXN0ZWQgVVJMcywgc3VjaCBhcyBgL3Bvc3RzLzEvY29tbWVudHMvMmAgc28gdGhlIHVzZXIgY2FuIGRvCiAgICAgIGBzdG9yZS5maW5kUmVjb3JkKCdjb21tZW50JywgMiwgeyBwcmVsb2FkOiB7IHBvc3Q6IDEgfSB9KWAgd2l0aG91dCBoYXZpbmcgdG8gZmV0Y2ggdGhlIHBvc3QuCiAgICAgICBQcmVsb2FkZWQgZGF0YSBjYW4gYmUgYXR0cmlidXRlcyBhbmQgcmVsYXRpb25zaGlwcyBwYXNzZWQgaW4gZWl0aGVyIGFzIElEcyBvciBhcyBhY3R1YWwKICAgICAgbW9kZWxzLgogICAgICAgQG1ldGhvZCBwcmVsb2FkRGF0YQogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge09iamVjdH0gcHJlbG9hZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucHJlbG9hZERhdGEgPSBmdW5jdGlvbiBwcmVsb2FkRGF0YShwcmVsb2FkKSB7CiAgICAgIHZhciBfdGhpczUgPSB0aGlzOwoKICAgICAgdmFyIGpzb25QYXlsb2FkID0ge307IC8vVE9ETyhJZ29yKSBjb25zaWRlciB0aGUgcG9seW1vcnBoaWMgY2FzZQoKICAgICAgT2JqZWN0LmtleXMocHJlbG9hZCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgdmFyIHByZWxvYWRWYWx1ZSA9IEVtYmVyLmdldChwcmVsb2FkLCBrZXkpOwoKICAgICAgICB2YXIgcmVsYXRpb25zaGlwTWV0YSA9IF90aGlzNS5tb2RlbENsYXNzLm1ldGFGb3JQcm9wZXJ0eShrZXkpOwoKICAgICAgICBpZiAocmVsYXRpb25zaGlwTWV0YS5pc1JlbGF0aW9uc2hpcCkgewogICAgICAgICAgaWYgKCFqc29uUGF5bG9hZC5yZWxhdGlvbnNoaXBzKSB7CiAgICAgICAgICAgIGpzb25QYXlsb2FkLnJlbGF0aW9uc2hpcHMgPSB7fTsKICAgICAgICAgIH0KCiAgICAgICAgICBqc29uUGF5bG9hZC5yZWxhdGlvbnNoaXBzW2tleV0gPSBfdGhpczUuX3ByZWxvYWRSZWxhdGlvbnNoaXAoa2V5LCBwcmVsb2FkVmFsdWUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoIWpzb25QYXlsb2FkLmF0dHJpYnV0ZXMpIHsKICAgICAgICAgICAganNvblBheWxvYWQuYXR0cmlidXRlcyA9IHt9OwogICAgICAgICAgfQoKICAgICAgICAgIGpzb25QYXlsb2FkLmF0dHJpYnV0ZXNba2V5XSA9IHByZWxvYWRWYWx1ZTsKICAgICAgICB9CiAgICAgIH0pOwoKICAgICAgdGhpcy5fcmVjb3JkRGF0YS5wdXNoRGF0YShqc29uUGF5bG9hZCk7CiAgICB9OwoKICAgIF9wcm90by5fcHJlbG9hZFJlbGF0aW9uc2hpcCA9IGZ1bmN0aW9uIF9wcmVsb2FkUmVsYXRpb25zaGlwKGtleSwgcHJlbG9hZFZhbHVlKSB7CiAgICAgIHZhciBfdGhpczYgPSB0aGlzOwoKICAgICAgdmFyIHJlbGF0aW9uc2hpcE1ldGEgPSB0aGlzLm1vZGVsQ2xhc3MubWV0YUZvclByb3BlcnR5KGtleSk7CiAgICAgIHZhciBtb2RlbENsYXNzID0gcmVsYXRpb25zaGlwTWV0YS50eXBlOwogICAgICB2YXIgZGF0YTsKCiAgICAgIGlmIChyZWxhdGlvbnNoaXBNZXRhLmtpbmQgPT09ICdoYXNNYW55JykgewogICAgICAgIGRhdGEgPSBwcmVsb2FkVmFsdWUubWFwKGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgICAgcmV0dXJuIF90aGlzNi5fY29udmVydFByZWxvYWRSZWxhdGlvbnNoaXBUb0pTT04odmFsdWUsIG1vZGVsQ2xhc3MpOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIGRhdGEgPSB0aGlzLl9jb252ZXJ0UHJlbG9hZFJlbGF0aW9uc2hpcFRvSlNPTihwcmVsb2FkVmFsdWUsIG1vZGVsQ2xhc3MpOwogICAgICB9CgogICAgICByZXR1cm4gewogICAgICAgIGRhdGE6IGRhdGEKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvLl9jb252ZXJ0UHJlbG9hZFJlbGF0aW9uc2hpcFRvSlNPTiA9IGZ1bmN0aW9uIF9jb252ZXJ0UHJlbG9hZFJlbGF0aW9uc2hpcFRvSlNPTih2YWx1ZSwgbW9kZWxDbGFzcykgewogICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHR5cGU6IG1vZGVsQ2xhc3MsCiAgICAgICAgICBpZDogdmFsdWUKICAgICAgICB9OwogICAgICB9CgogICAgICB2YXIgaW50ZXJuYWxNb2RlbDsKCiAgICAgIGlmICh2YWx1ZS5faW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwgPSB2YWx1ZS5faW50ZXJuYWxNb2RlbDsKICAgICAgfSBlbHNlIHsKICAgICAgICBpbnRlcm5hbE1vZGVsID0gdmFsdWU7CiAgICAgIH0gLy8gVE9ETyBJR09SIERBVklEIGFzc2VydCBpZiBubyBpZCBpcyBwcmVzZW50CgoKICAgICAgcmV0dXJuIHsKICAgICAgICB0eXBlOiBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZSwKICAgICAgICBpZDogaW50ZXJuYWxNb2RlbC5pZAogICAgICB9OwogICAgfQogICAgLyoKICAgICAgVXNlZCB0byBub3RpZnkgdGhlIHN0b3JlIHRvIHVwZGF0ZSBGaWx0ZXJlZFJlY29yZEFycmF5IG1lbWJlcnNoaXAuCiAgICAgICBAbWV0aG9kIHVwZGF0ZVJlY29yZEFycmF5cwogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8udXBkYXRlUmVjb3JkQXJyYXlzID0gZnVuY3Rpb24gdXBkYXRlUmVjb3JkQXJyYXlzKCkgewogICAgICAvLyBAdHMtaWdub3JlOiBTdG9yZSBpcyB1bnR5cGVkIGFuZCB0eXBlc2NyaXB0IGRvZXMgbm90IGRldGVjdCBpbnN0YW5jZSBwcm9wcyBzZXQgaW4gYGluaXRgCiAgICAgIHRoaXMuc3RvcmUucmVjb3JkQXJyYXlNYW5hZ2VyLnJlY29yZERpZENoYW5nZSh0aGlzKTsKICAgIH07CgogICAgX3Byb3RvLnNldElkID0gZnVuY3Rpb24gc2V0SWQoaWQpIHsKCiAgICAgIHZhciBkaWRDaGFuZ2UgPSBpZCAhPT0gdGhpcy5faWQ7CiAgICAgIHRoaXMuX2lkID0gaWQ7CgogICAgICBpZiAoZGlkQ2hhbmdlICYmIGlkICE9PSBudWxsKSB7CiAgICAgICAgdGhpcy5zdG9yZS5zZXRSZWNvcmRJZCh0aGlzLm1vZGVsTmFtZSwgaWQsIHRoaXMuY2xpZW50SWQpOwogICAgICB9CgogICAgICBpZiAoZGlkQ2hhbmdlICYmIHRoaXMuaGFzUmVjb3JkKSB7CiAgICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgICAgdGhpcy5zdG9yZS5fbm90aWZpY2F0aW9uTWFuYWdlci5ub3RpZnkodGhpcy5pZGVudGlmaWVyLCAnaWRlbnRpdHknKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhpcy5ub3RpZnlQcm9wZXJ0eUNoYW5nZSgnaWQnKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmRpZEVycm9yID0gZnVuY3Rpb24gZGlkRXJyb3IoZXJyb3IpIHsKICAgICAgaWYgKCFjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICB0aGlzLmVycm9yID0gZXJyb3I7CiAgICAgICAgdGhpcy5pc0Vycm9yID0gdHJ1ZTsKCiAgICAgICAgaWYgKHRoaXMuaGFzUmVjb3JkKSB7CiAgICAgICAgICB0aGlzLl9yZWNvcmQuc2V0UHJvcGVydGllcyh7CiAgICAgICAgICAgIGlzRXJyb3I6IHRydWUsCiAgICAgICAgICAgIGFkYXB0ZXJFcnJvcjogZXJyb3IKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uZGlkQ2xlYW5FcnJvciA9IGZ1bmN0aW9uIGRpZENsZWFuRXJyb3IoKSB7CiAgICAgIGlmICghY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgdGhpcy5lcnJvciA9IG51bGw7CiAgICAgICAgdGhpcy5pc0Vycm9yID0gZmFsc2U7CgogICAgICAgIGlmICh0aGlzLmhhc1JlY29yZCkgewogICAgICAgICAgdGhpcy5fcmVjb3JkLnNldFByb3BlcnRpZXMoewogICAgICAgICAgICBpc0Vycm9yOiBmYWxzZSwKICAgICAgICAgICAgYWRhcHRlckVycm9yOiBudWxsCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIC8qCiAgICAgIElmIHRoZSBhZGFwdGVyIGRpZCBub3QgcmV0dXJuIGEgaGFzaCBpbiByZXNwb25zZSB0byBhIGNvbW1pdCwKICAgICAgbWVyZ2UgdGhlIGNoYW5nZWQgYXR0cmlidXRlcyBhbmQgcmVsYXRpb25zaGlwcyBpbnRvIHRoZSBleGlzdGluZwogICAgICBzYXZlZCBkYXRhLgogICAgICAgQG1ldGhvZCBhZGFwdGVyRGlkQ29tbWl0CiAgICAqLwogICAgOwoKICAgIF9wcm90by5hZGFwdGVyRGlkQ29tbWl0ID0gZnVuY3Rpb24gYWRhcHRlckRpZENvbW1pdChkYXRhKSB7CiAgICAgIHRoaXMuZGlkQ2xlYW5FcnJvcigpOwoKICAgICAgdmFyIGNoYW5nZWRLZXlzID0gdGhpcy5fcmVjb3JkRGF0YS5kaWRDb21taXQoZGF0YSk7CgogICAgICB0aGlzLnNlbmQoJ2RpZENvbW1pdCcpOwogICAgICB0aGlzLnVwZGF0ZVJlY29yZEFycmF5cygpOwoKICAgICAgaWYgKCFkYXRhKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgdGhpcy5zdG9yZS5fbm90aWZpY2F0aW9uTWFuYWdlci5ub3RpZnkodGhpcy5pZGVudGlmaWVyLCAnYXR0cmlidXRlcycpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuX3JlY29yZC5fbm90aWZ5UHJvcGVydGllcyhjaGFuZ2VkS2V5cyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmFkZEVycm9yTWVzc2FnZVRvQXR0cmlidXRlID0gZnVuY3Rpb24gYWRkRXJyb3JNZXNzYWdlVG9BdHRyaWJ1dGUoYXR0cmlidXRlLCBtZXNzYWdlKSB7CiAgICAgIEVtYmVyLmdldCh0aGlzLmdldFJlY29yZCgpLCAnZXJyb3JzJykuX2FkZChhdHRyaWJ1dGUsIG1lc3NhZ2UpOwogICAgfTsKCiAgICBfcHJvdG8ucmVtb3ZlRXJyb3JNZXNzYWdlRnJvbUF0dHJpYnV0ZSA9IGZ1bmN0aW9uIHJlbW92ZUVycm9yTWVzc2FnZUZyb21BdHRyaWJ1dGUoYXR0cmlidXRlKSB7CiAgICAgIEVtYmVyLmdldCh0aGlzLmdldFJlY29yZCgpLCAnZXJyb3JzJykuX3JlbW92ZShhdHRyaWJ1dGUpOwogICAgfTsKCiAgICBfcHJvdG8uY2xlYXJFcnJvck1lc3NhZ2VzID0gZnVuY3Rpb24gY2xlYXJFcnJvck1lc3NhZ2VzKCkgewogICAgICBFbWJlci5nZXQodGhpcy5nZXRSZWNvcmQoKSwgJ2Vycm9ycycpLl9jbGVhcigpOwogICAgfTsKCiAgICBfcHJvdG8uaGFzRXJyb3JzID0gZnVuY3Rpb24gaGFzRXJyb3JzKCkgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfRVJST1JTKSB7CiAgICAgICAgaWYgKHRoaXMuX3JlY29yZERhdGEuZ2V0RXJyb3JzKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fcmVjb3JkRGF0YS5nZXRFcnJvcnMoIHRoaXMuaWRlbnRpZmllciApLmxlbmd0aCA+IDA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBlcnJvcnMgPSBFbWJlci5nZXQodGhpcy5nZXRSZWNvcmQoKSwgJ2Vycm9ycycpOwogICAgICAgICAgcmV0dXJuIGVycm9ycy5nZXQoJ2xlbmd0aCcpID4gMDsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIF9lcnJvcnMgPSBFbWJlci5nZXQodGhpcy5nZXRSZWNvcmQoKSwgJ2Vycm9ycycpOwoKICAgICAgICByZXR1cm4gX2Vycm9ycy5nZXQoJ2xlbmd0aCcpID4gMDsKICAgICAgfQogICAgfSAvLyBGT1IgVVNFIERVUklORyBDT01NSVQgUFJPQ0VTUwoKICAgIC8qCiAgICAgIEBtZXRob2QgYWRhcHRlckRpZEludmFsaWRhdGUKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmFkYXB0ZXJEaWRJbnZhbGlkYXRlID0gZnVuY3Rpb24gYWRhcHRlckRpZEludmFsaWRhdGUocGFyc2VkRXJyb3JzLCBlcnJvcikgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfRVJST1JTKSB7CiAgICAgICAgdmFyIGF0dHJpYnV0ZTsKCiAgICAgICAgaWYgKGVycm9yICYmIHBhcnNlZEVycm9ycykgewogICAgICAgICAgaWYgKCF0aGlzLl9yZWNvcmREYXRhLmdldEVycm9ycykgewogICAgICAgICAgICBmb3IgKGF0dHJpYnV0ZSBpbiBwYXJzZWRFcnJvcnMpIHsKICAgICAgICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChwYXJzZWRFcnJvcnMsIGF0dHJpYnV0ZSkpIHsKICAgICAgICAgICAgICAgIHRoaXMuYWRkRXJyb3JNZXNzYWdlVG9BdHRyaWJ1dGUoYXR0cmlidXRlLCBwYXJzZWRFcnJvcnNbYXR0cmlidXRlXSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgdmFyIGpzb25BcGlFcnJvcnMgPSBlcnJvcnNIYXNoVG9BcnJheShwYXJzZWRFcnJvcnMpOwogICAgICAgICAgdGhpcy5zZW5kKCdiZWNhbWVJbnZhbGlkJyk7CgogICAgICAgICAgaWYgKGpzb25BcGlFcnJvcnMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgIGpzb25BcGlFcnJvcnMgPSBbewogICAgICAgICAgICAgIHRpdGxlOiAnSW52YWxpZCBFcnJvcicsCiAgICAgICAgICAgICAgZGV0YWlsOiAnJywKICAgICAgICAgICAgICBzb3VyY2U6IHsKICAgICAgICAgICAgICAgIHBvaW50ZXI6ICcvZGF0YScKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH1dOwogICAgICAgICAgfQoKICAgICAgICAgIHRoaXMuX3JlY29yZERhdGEuY29tbWl0V2FzUmVqZWN0ZWQoIHRoaXMuaWRlbnRpZmllciAsIGpzb25BcGlFcnJvcnMpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLnNlbmQoJ2JlY2FtZUVycm9yJyk7CgogICAgICAgICAgdGhpcy5fcmVjb3JkRGF0YS5jb21taXRXYXNSZWplY3RlZCggdGhpcy5pZGVudGlmaWVyICk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHZhciBfYXR0cmlidXRlOwoKICAgICAgICBmb3IgKF9hdHRyaWJ1dGUgaW4gcGFyc2VkRXJyb3JzKSB7CiAgICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChwYXJzZWRFcnJvcnMsIF9hdHRyaWJ1dGUpKSB7CiAgICAgICAgICAgIHRoaXMuYWRkRXJyb3JNZXNzYWdlVG9BdHRyaWJ1dGUoX2F0dHJpYnV0ZSwgcGFyc2VkRXJyb3JzW19hdHRyaWJ1dGVdKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHRoaXMuc2VuZCgnYmVjYW1lSW52YWxpZCcpOwoKICAgICAgICB0aGlzLl9yZWNvcmREYXRhLmNvbW1pdFdhc1JlamVjdGVkKCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLm5vdGlmeUVycm9yc0NoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeUVycm9yc0NoYW5nZSgpIHsKICAgICAgdmFyIGludmFsaWRFcnJvcnM7CgogICAgICBpZiAodGhpcy5fcmVjb3JkRGF0YS5nZXRFcnJvcnMpIHsKICAgICAgICBpbnZhbGlkRXJyb3JzID0gdGhpcy5fcmVjb3JkRGF0YS5nZXRFcnJvcnMoIHRoaXMuaWRlbnRpZmllciApIHx8IFtdOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5ub3RpZnlJbnZhbGlkRXJyb3JzQ2hhbmdlKGludmFsaWRFcnJvcnMpOwogICAgfTsKCiAgICBfcHJvdG8ubm90aWZ5SW52YWxpZEVycm9yc0NoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeUludmFsaWRFcnJvcnNDaGFuZ2UoanNvbkFwaUVycm9ycykgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgdGhpcy5zdG9yZS5fbm90aWZpY2F0aW9uTWFuYWdlci5ub3RpZnkodGhpcy5pZGVudGlmaWVyLCAnZXJyb3JzJyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5nZXRSZWNvcmQoKS5pbnZhbGlkRXJyb3JzQ2hhbmdlZChqc29uQXBpRXJyb3JzKTsKICAgICAgfQogICAgfQogICAgLyoKICAgICAgQG1ldGhvZCBhZGFwdGVyRGlkRXJyb3IKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmFkYXB0ZXJEaWRFcnJvciA9IGZ1bmN0aW9uIGFkYXB0ZXJEaWRFcnJvcihlcnJvcikgewogICAgICB0aGlzLnNlbmQoJ2JlY2FtZUVycm9yJyk7CiAgICAgIHRoaXMuZGlkRXJyb3IoZXJyb3IpOwoKICAgICAgdGhpcy5fcmVjb3JkRGF0YS5jb21taXRXYXNSZWplY3RlZCgpOwogICAgfTsKCiAgICBfcHJvdG8udG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuICI8IiArIHRoaXMubW9kZWxOYW1lICsgIjoiICsgdGhpcy5pZCArICI+IjsKICAgIH07CgogICAgX3Byb3RvLnJlZmVyZW5jZUZvciA9IGZ1bmN0aW9uIHJlZmVyZW5jZUZvcihraW5kLCBuYW1lKSB7CiAgICAgIHZhciByZWZlcmVuY2UgPSB0aGlzLnJlZmVyZW5jZXNbbmFtZV07CgogICAgICBpZiAoIXJlZmVyZW5jZSkgewogICAgICAgIC8vIFRPRE8gSUdPUiBBTkQgREFWSUQgUkVGQUNUT1IKICAgICAgICB2YXIgcmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwU3RhdGVGb3IkMSh0aGlzLCBuYW1lKTsKCiAgICAgICAgdmFyIHJlbGF0aW9uc2hpcEtpbmQgPSByZWxhdGlvbnNoaXAucmVsYXRpb25zaGlwTWV0YS5raW5kOwoKICAgICAgICBpZiAocmVsYXRpb25zaGlwS2luZCA9PT0gJ2JlbG9uZ3NUbycpIHsKICAgICAgICAgIHJlZmVyZW5jZSA9IG5ldyBCZWxvbmdzVG9SZWZlcmVuY2UodGhpcy5zdG9yZSwgdGhpcywgcmVsYXRpb25zaGlwLCBuYW1lKTsKICAgICAgICB9IGVsc2UgaWYgKHJlbGF0aW9uc2hpcEtpbmQgPT09ICdoYXNNYW55JykgewogICAgICAgICAgcmVmZXJlbmNlID0gbmV3IEhhc01hbnlSZWZlcmVuY2UodGhpcy5zdG9yZSwgdGhpcywgcmVsYXRpb25zaGlwLCBuYW1lKTsKICAgICAgICB9CgogICAgICAgIHRoaXMucmVmZXJlbmNlc1tuYW1lXSA9IHJlZmVyZW5jZTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlZmVyZW5jZTsKICAgIH07CgogICAgX2NyZWF0ZUNsYXNzJDMoSW50ZXJuYWxNb2RlbCwgW3sKICAgICAga2V5OiAiaWQiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICB7CiAgICAgICAgICByZXR1cm4gdGhpcy5pZGVudGlmaWVyLmlkOyAvLyB8fCB0aGlzLl9pZDsKICAgICAgICB9CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHZhbHVlKSB7CiAgICAgICAgewogICAgICAgICAgaWYgKHZhbHVlICE9PSB0aGlzLl9pZCkgewogICAgICAgICAgICB2YXIgbmV3SWRlbnRpZmllciA9IHsKICAgICAgICAgICAgICB0eXBlOiB0aGlzLmlkZW50aWZpZXIudHlwZSwKICAgICAgICAgICAgICBsaWQ6IHRoaXMuaWRlbnRpZmllci5saWQsCiAgICAgICAgICAgICAgaWQ6IHZhbHVlCiAgICAgICAgICAgIH07CiAgICAgICAgICAgIGlkZW50aWZpZXJDYWNoZUZvcih0aGlzLnN0b3JlKS51cGRhdGVSZWNvcmRJZGVudGlmaWVyKHRoaXMuaWRlbnRpZmllciwgbmV3SWRlbnRpZmllcik7IC8vIFRPRE8gU2hvdyBkZXByZWNhdGlvbiBmb3IgcHJpdmF0ZSBhcGkKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAibW9kZWxDbGFzcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIGlmICh0aGlzLnN0b3JlLm1vZGVsRm9yKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fbW9kZWxDbGFzcyB8fCAodGhpcy5fbW9kZWxDbGFzcyA9IHRoaXMuc3RvcmUubW9kZWxGb3IodGhpcy5tb2RlbE5hbWUpKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAidHlwZSIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLm1vZGVsQ2xhc3M7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAicmVjb3JkUmVmZXJlbmNlIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMuX3JlY29yZFJlZmVyZW5jZSA9PT0gbnVsbCkgewogICAgICAgICAgdGhpcy5fcmVjb3JkUmVmZXJlbmNlID0gbmV3IFJlY29yZFJlZmVyZW5jZSh0aGlzLnN0b3JlLCB0aGlzKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9yZWNvcmRSZWZlcmVuY2U7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiX3JlY29yZERhdGEiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fX3JlY29yZERhdGEgPT09IG51bGwpIHsKICAgICAgICAgIHZhciByZWNvcmREYXRhID0gdGhpcy5zdG9yZS5fY3JlYXRlUmVjb3JkRGF0YSh0aGlzLmlkZW50aWZpZXIpOwoKICAgICAgICAgIHRoaXMuX3JlY29yZERhdGEgPSByZWNvcmREYXRhOwogICAgICAgICAgcmV0dXJuIHJlY29yZERhdGE7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fX3JlY29yZERhdGE7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KG5ld1ZhbHVlKSB7CiAgICAgICAgdGhpcy5fX3JlY29yZERhdGEgPSBuZXdWYWx1ZTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJfcmVjb3JkQXJyYXlzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMuX19yZWNvcmRBcnJheXMgPT09IG51bGwpIHsKICAgICAgICAgIHRoaXMuX19yZWNvcmRBcnJheXMgPSBuZXcgU2V0KCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fX3JlY29yZEFycmF5czsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJyZWZlcmVuY2VzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMuX3JlZmVyZW5jZXMgPT09IG51bGwpIHsKICAgICAgICAgIHRoaXMuX3JlZmVyZW5jZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMuX3JlZmVyZW5jZXM7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiX2RlZmVycmVkVHJpZ2dlcnMiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fX2RlZmVycmVkVHJpZ2dlcnMgPT09IG51bGwpIHsKICAgICAgICAgIHRoaXMuX19kZWZlcnJlZFRyaWdnZXJzID0gW107CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fX2RlZmVycmVkVHJpZ2dlcnM7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiaXNEZXN0cm95ZWQiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5faXNEZXN0cm95ZWQ7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiaGFzUmVjb3JkIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuICEhdGhpcy5fcmVjb3JkOwogICAgICB9CiAgICB9XSk7CgogICAgcmV0dXJuIEludGVybmFsTW9kZWw7CiAgfSgpOwoKICBmdW5jdGlvbiBoYW5kbGVDb21wbGV0ZWRSZWxhdGlvbnNoaXBSZXF1ZXN0KGludGVybmFsTW9kZWwsIGtleSwgcmVsYXRpb25zaGlwLCB2YWx1ZSwgZXJyb3IpIHsKICAgIGRlbGV0ZSBpbnRlcm5hbE1vZGVsLl9yZWxhdGlvbnNoaXBQcm9taXNlc0NhY2hlW2tleV07CiAgICByZWxhdGlvbnNoaXAuc2V0U2hvdWxkRm9yY2VSZWxvYWQoZmFsc2UpOwoKICAgIGlmIChlcnJvcikgewogICAgICByZWxhdGlvbnNoaXAuc2V0SGFzRmFpbGVkTG9hZEF0dGVtcHQodHJ1ZSk7CiAgICAgIHZhciBwcm94eSA9IGludGVybmFsTW9kZWwuX3JlbGF0aW9uc2hpcFByb3h5Q2FjaGVba2V5XTsgLy8gYmVsb25nc1RvIHJlbGF0aW9uc2hpcHMgYXJlIHNvbWV0aW1lcyB1bmxvYWRlZAogICAgICAvLyB3aGVuIGEgbG9hZCBmYWlscywgaW4gdGhpcyBjYXNlIHdlIG5lZWQKICAgICAgLy8gdG8gbWFrZSBzdXJlIHRoYXQgd2UgYXJlbid0IHByb3h5aW5nCiAgICAgIC8vIHRvIGRlc3Ryb3llZCBjb250ZW50CiAgICAgIC8vIGZvciB0aGUgc3luYyBiZWxvbmdzVG8gcmVsb2FkIGNhc2UgdGhlcmUgd2lsbCBiZSBubyBwcm94eQogICAgICAvLyBmb3IgdGhlIGFzeW5jIHJlbG9hZCBjYXNlIHRoZXJlIHdpbGwgYmUgbm8gcHJveHkgaWYgdGhlIHVpCiAgICAgIC8vIGhhcyBuZXZlciBiZWVuIGFjY2Vzc2VkCgogICAgICBpZiAocHJveHkgJiYgcmVsYXRpb25zaGlwLmtpbmQgPT09ICdiZWxvbmdzVG8nKSB7CiAgICAgICAgaWYgKHByb3h5LmNvbnRlbnQgJiYgcHJveHkuY29udGVudC5pc0Rlc3Ryb3lpbmcpIHsKICAgICAgICAgIHByb3h5LnNldCgnY29udGVudCcsIG51bGwpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdGhyb3cgZXJyb3I7CiAgICB9CgogICAgcmVsYXRpb25zaGlwLnNldEhhc0ZhaWxlZExvYWRBdHRlbXB0KGZhbHNlKTsgLy8gb25seSBzZXQgdG8gbm90IHN0YWxlIGlmIG5vIGVycm9yIGlzIHRocm93bgoKICAgIHJlbGF0aW9uc2hpcC5zZXRSZWxhdGlvbnNoaXBJc1N0YWxlKGZhbHNlKTsKICAgIHJldHVybiB2YWx1ZTsKICB9CiAgZnVuY3Rpb24gZXh0cmFjdFJlY29yZERhdGFzRnJvbVJlY29yZHMocmVjb3JkcykgewogICAgcmV0dXJuIHJlY29yZHMubWFwKGV4dHJhY3RSZWNvcmREYXRhRnJvbVJlY29yZCk7CiAgfQogIGZ1bmN0aW9uIGV4dHJhY3RSZWNvcmREYXRhRnJvbVJlY29yZChyZWNvcmRPclByb21pc2VSZWNvcmQpIHsKICAgIGlmICghcmVjb3JkT3JQcm9taXNlUmVjb3JkKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQoKICAgIGlmIChyZWNvcmRPclByb21pc2VSZWNvcmQudGhlbikgewogICAgICB2YXIgY29udGVudCA9IHJlY29yZE9yUHJvbWlzZVJlY29yZC5nZXQgJiYgcmVjb3JkT3JQcm9taXNlUmVjb3JkLmdldCgnY29udGVudCcpOwogICAgICByZXR1cm4gY29udGVudCA/IHJlY29yZERhdGFGb3IoY29udGVudCkgOiBudWxsOwogICAgfQoKICAgIHJldHVybiByZWNvcmREYXRhRm9yKHJlY29yZE9yUHJvbWlzZVJlY29yZCk7CiAgfQoKICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyQ0KHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyQ0KENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMkNChDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDQoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICBgSW50ZXJuYWxNb2RlbE1hcGAgaXMgYSBjdXN0b20gc3RvcmFnZSBtYXAgZm9yIGludGVybmFsTW9kZWxzIG9mIGEgZ2l2ZW4gbW9kZWxOYW1lCiAgIHVzZWQgYnkgYElkZW50aXR5TWFwYC4KCiAgIEl0IHdhcyBleHRyYWN0ZWQgZnJvbSBhbiBpbXBsaWNpdCBwb2pvIGJhc2VkICJpbnRlcm5hbE1vZGVsIG1hcCIgYW5kIHByZXNlcnZlcwogICB0aGF0IGludGVyZmFjZSB3aGlsZSB3ZSB3b3JrIHRvd2FyZHMgYSBtb3JlIG9mZmljaWFsIEFQSS4KCiAgIEBjbGFzcyBJbnRlcm5hbE1vZGVsTWFwCiAgIEBwcml2YXRlCiAgICovCiAgdmFyIEludGVybmFsTW9kZWxNYXAgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBJbnRlcm5hbE1vZGVsTWFwKG1vZGVsTmFtZSkgewogICAgICB0aGlzLm1vZGVsTmFtZSA9IG1vZGVsTmFtZTsKICAgICAgdGhpcy5faWRUb01vZGVsID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGhpcy5fbW9kZWxzID0gW107CiAgICAgIHRoaXMuX21ldGFkYXRhID0gbnVsbDsKICAgIH0KICAgIC8qKgogICAgICogQG1ldGhvZCBnZXQKICAgICAqIEBwYXJhbSBpZCB7U3RyaW5nfQogICAgICogQHJldHVybiB7SW50ZXJuYWxNb2RlbH0KICAgICAqLwoKCiAgICB2YXIgX3Byb3RvID0gSW50ZXJuYWxNb2RlbE1hcC5wcm90b3R5cGU7CgogICAgX3Byb3RvLmdldCA9IGZ1bmN0aW9uIGdldChpZCkgewogICAgICByZXR1cm4gdGhpcy5faWRUb01vZGVsW2lkXSB8fCBudWxsOwogICAgfTsKCiAgICBfcHJvdG8uaGFzID0gZnVuY3Rpb24gaGFzKGlkKSB7CiAgICAgIHJldHVybiAhIXRoaXMuX2lkVG9Nb2RlbFtpZF07CiAgICB9OwoKICAgIF9wcm90by5zZXQgPSBmdW5jdGlvbiBzZXQoaWQsIGludGVybmFsTW9kZWwpIHsKICAgICAgdGhpcy5faWRUb01vZGVsW2lkXSA9IGludGVybmFsTW9kZWw7CiAgICB9OwoKICAgIF9wcm90by5hZGQgPSBmdW5jdGlvbiBhZGQoaW50ZXJuYWxNb2RlbCwgaWQpIHsKCiAgICAgIGlmIChpZCkgewogICAgICAgIHRoaXMuX2lkVG9Nb2RlbFtpZF0gPSBpbnRlcm5hbE1vZGVsOwogICAgICB9CgogICAgICB0aGlzLl9tb2RlbHMucHVzaChpbnRlcm5hbE1vZGVsKTsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZSA9IGZ1bmN0aW9uIHJlbW92ZShpbnRlcm5hbE1vZGVsLCBpZCkgewogICAgICBkZWxldGUgdGhpcy5faWRUb01vZGVsW2lkXTsKCiAgICAgIHZhciBsb2MgPSB0aGlzLl9tb2RlbHMuaW5kZXhPZihpbnRlcm5hbE1vZGVsKTsKCiAgICAgIGlmIChsb2MgIT09IC0xKSB7CiAgICAgICAgdGhpcy5fbW9kZWxzLnNwbGljZShsb2MsIDEpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5jb250YWlucyA9IGZ1bmN0aW9uIGNvbnRhaW5zKGludGVybmFsTW9kZWwpIHsKICAgICAgcmV0dXJuIHRoaXMuX21vZGVscy5pbmRleE9mKGludGVybmFsTW9kZWwpICE9PSAtMTsKICAgIH0KICAgIC8qKgogICAgIEFuIGFycmF5IG9mIGFsbCBtb2RlbHMgb2YgdGhpcyBtb2RlbE5hbWUKICAgICBAcHJvcGVydHkgbW9kZWxzCiAgICAgQHR5cGUgQXJyYXkKICAgICAqLwogICAgOwoKICAgIC8qKgogICAgIERlc3Ryb3kgYWxsIG1vZGVscyBpbiB0aGUgaW50ZXJuYWxNb2RlbFRlc3QgYW5kIHdpcGUgbWV0YWRhdGEuCiAgICAgIEBtZXRob2QgY2xlYXIKICAgICAqLwogICAgX3Byb3RvLmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVscyA9IHRoaXMuX21vZGVsczsKICAgICAgdGhpcy5fbW9kZWxzID0gW107CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGludGVybmFsTW9kZWxzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsc1tpXTsKICAgICAgICBpbnRlcm5hbE1vZGVsLnVubG9hZFJlY29yZCgpOwogICAgICB9CgogICAgICB0aGlzLl9tZXRhZGF0YSA9IG51bGw7CiAgICB9OwoKICAgIF9jcmVhdGVDbGFzcyQ0KEludGVybmFsTW9kZWxNYXAsIFt7CiAgICAgIGtleTogImxlbmd0aCIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLl9tb2RlbHMubGVuZ3RoOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogIm1vZGVscyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLl9tb2RlbHM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIG1ldGEgaW5mb3JtYXRpb24gYWJvdXQgaW50ZXJuYWxNb2RlbHMKICAgICAgICogQHByb3BlcnR5IG1ldGFkYXRhCiAgICAgICAqIEB0eXBlIE9iamVjdAogICAgICAgKi8KCiAgICB9LCB7CiAgICAgIGtleTogIm1ldGFkYXRhIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX21ldGFkYXRhIHx8ICh0aGlzLl9tZXRhZGF0YSA9IE9iamVjdC5jcmVhdGUobnVsbCkpOwogICAgICB9CiAgICB9XSk7CgogICAgcmV0dXJuIEludGVybmFsTW9kZWxNYXA7CiAgfSgpOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICAvKioKICAgYElkZW50aXR5TWFwYCBpcyBhIGN1c3RvbSBzdG9yYWdlIG1hcCBmb3IgcmVjb3JkcyBieSBtb2RlbE5hbWUKICAgdXNlZCBieSBgU3RvcmVgLgoKICAgQGNsYXNzIElkZW50aXR5TWFwCiAgIEBwcml2YXRlCiAgICovCiAgdmFyIElkZW50aXR5TWFwID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSWRlbnRpdHlNYXAoKSB7CiAgICAgIHRoaXMuX21hcCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB9CgogICAgdmFyIF9wcm90byA9IElkZW50aXR5TWFwLnByb3RvdHlwZTsKCiAgICAvKioKICAgICBSZXRyaWV2ZXMgdGhlIGBJbnRlcm5hbE1vZGVsTWFwYCBmb3IgYSBnaXZlbiBtb2RlbE5hbWUsCiAgICAgY3JlYXRpbmcgb25lIGlmIG9uZSBkaWQgbm90IGFscmVhZHkgZXhpc3QuIFRoaXMgaXMKICAgICBzaW1pbGFyIHRvIGBnZXRXaXRoRGVmYXVsdGAgb3IgYGdldGAgb24gYSBgTWFwV2l0aERlZmF1bHRgCiAgICAgIEBtZXRob2QgcmV0cmlldmUKICAgICBAcGFyYW0gbW9kZWxOYW1lIGEgcHJldmlvdXNseSBub3JtYWxpemVkIG1vZGVsTmFtZQogICAgIEByZXR1cm4ge0ludGVybmFsTW9kZWxNYXB9IHRoZSBJbnRlcm5hbE1vZGVsTWFwIGZvciB0aGUgZ2l2ZW4gbW9kZWxOYW1lCiAgICAgKi8KICAgIF9wcm90by5yZXRyaWV2ZSA9IGZ1bmN0aW9uIHJldHJpZXZlKG1vZGVsTmFtZSkgewogICAgICB2YXIgbWFwID0gdGhpcy5fbWFwW21vZGVsTmFtZV07CgogICAgICBpZiAobWFwID09PSB1bmRlZmluZWQpIHsKICAgICAgICBtYXAgPSB0aGlzLl9tYXBbbW9kZWxOYW1lXSA9IG5ldyBJbnRlcm5hbE1vZGVsTWFwKG1vZGVsTmFtZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBtYXA7CiAgICB9CiAgICAvKioKICAgICBDbGVhcnMgdGhlIGNvbnRlbnRzIG9mIGFsbCBrbm93biBgUmVjb3JkTWFwc2AsIGJ1dCBkb2VzCiAgICAgbm90IHJlbW92ZSB0aGUgSW50ZXJuYWxNb2RlbE1hcCBpbnN0YW5jZXMuCiAgICAgIEBtZXRob2QgY2xlYXIKICAgICAqLwogICAgOwoKICAgIF9wcm90by5jbGVhciA9IGZ1bmN0aW9uIGNsZWFyKCkgewogICAgICB2YXIgbWFwID0gdGhpcy5fbWFwOwogICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG1hcCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTsKICAgICAgICBtYXBba2V5XS5jbGVhcigpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBJZGVudGl0eU1hcDsKICB9KCk7CgogIGZ1bmN0aW9uIGNvbnN0cnVjdFJlc291cmNlKHR5cGUsIGlkLCBsaWQpIHsKICAgIHZhciB0cnVlSWQgPSBjb2VyY2VJZChpZCk7CgogICAgaWYgKCFpc05vbkVtcHR5U3RyaW5nKHRydWVJZCkpIHsKICAgICAgaWYgKGlzTm9uRW1wdHlTdHJpbmcobGlkKSkgewogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiB0eXBlLAogICAgICAgICAgaWQ6IHRydWVJZCwKICAgICAgICAgIGxpZDogbGlkCiAgICAgICAgfTsKICAgICAgfQoKICAgICAgdGhyb3cgbmV3IEVycm9yKCJFeHBlY3RlZCBlaXRoZXIgaWQgb3IgbGlkIHRvIGJlIGEgdmFsaWQgc3RyaW5nIik7CiAgICB9CgogICAgaWYgKGlzTm9uRW1wdHlTdHJpbmcobGlkKSkgewogICAgICByZXR1cm4gewogICAgICAgIHR5cGU6IHR5cGUsCiAgICAgICAgaWQ6IHRydWVJZCwKICAgICAgICBsaWQ6IGxpZAogICAgICB9OwogICAgfQoKICAgIHJldHVybiB7CiAgICAgIHR5cGU6IHR5cGUsCiAgICAgIGlkOiB0cnVlSWQKICAgIH07CiAgfQoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICB2YXIgRmFjdG9yeUNhY2hlID0gbmV3IFdlYWtNYXAoKTsKICB2YXIgUmVjb3JkQ2FjaGUgPSBuZXcgV2Vha01hcCgpOwogIGZ1bmN0aW9uIHBlZWtSZWNvcmRJZGVudGlmaWVyKHJlY29yZCkgewogICAgcmV0dXJuIFJlY29yZENhY2hlLmdldChyZWNvcmQpOwogIH0KICBmdW5jdGlvbiByZWNvcmRJZGVudGlmaWVyRm9yKHJlY29yZCkgewogICAgdmFyIGlkZW50aWZpZXIgPSBSZWNvcmRDYWNoZS5nZXQocmVjb3JkKTsKCiAgICByZXR1cm4gaWRlbnRpZmllcjsKICB9CiAgZnVuY3Rpb24gc2V0UmVjb3JkSWRlbnRpZmllcihyZWNvcmQsIGlkZW50aWZpZXIpIHsKICAgIC8qCiAgICBJdCB3b3VsZCBiZSBuaWNlIHRvIGRvIGEgcmV2ZXJzZSBjaGVjayBoZXJlIHRoYXQgYW4gaWRlbnRpZmllciBoYXMgbm90CiAgICBwcmV2aW91c2x5IGJlZW4gYXNzaWduZWQgYSByZWNvcmQ7IGhvd2V2ZXIsIHVubG9hZCArIHJlbWF0ZXJpYWxpemF0aW9uCiAgICBwcmV2ZW50cyB1cyBmcm9tIGhhdmluZyBhIGdyZWF0IHdheSBvZiBkb2luZyBzbyB3aGVuIEN1c3RvbVJlY29yZENsYXNzZXMKICAgIGRvbid0IG5lY2Vzc2FyaWx5IGdpdmUgdXMgYWNjZXNzIHRvIGEgYGlzRGVzdHJveWVkYCBmb3IgZGVtYXRlcmlhbGl6ZWQKICAgIGluc3RhbmNlLgogICAgKi8KCgogICAgUmVjb3JkQ2FjaGUuc2V0KHJlY29yZCwgaWRlbnRpZmllcik7CiAgfQogIGZ1bmN0aW9uIGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHN0b3JlKSB7CiAgICB2YXIgZmFjdG9yeSA9IEZhY3RvcnlDYWNoZS5nZXQoc3RvcmUpOwoKICAgIGlmIChmYWN0b3J5ID09PSB1bmRlZmluZWQpIHsKICAgICAgZmFjdG9yeSA9IG5ldyBJbnRlcm5hbE1vZGVsRmFjdG9yeShzdG9yZSk7CiAgICAgIEZhY3RvcnlDYWNoZS5zZXQoc3RvcmUsIGZhY3RvcnkpOwogICAgfQoKICAgIHJldHVybiBmYWN0b3J5OwogIH0KICAvKioKICAgKiBUaGUgSW50ZXJuYWxNb2RlbEZhY3RvcnkgaGFuZGxlcyB0aGUgbGlmZWN5bGUgb2YKICAgKiBpbnN0YW50aWF0aW5nLCBjYWNoaW5nLCBhbmQgZGVzdHJveWluZyBJbnRlcm5hbE1vZGVsCiAgICogaW5zdGFuY2VzLgogICAqCiAgICogQGludGVybmFsCiAgICovCgogIHZhciBJbnRlcm5hbE1vZGVsRmFjdG9yeSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEludGVybmFsTW9kZWxGYWN0b3J5KHN0b3JlKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICB0aGlzLnN0b3JlID0gc3RvcmU7CiAgICAgIHRoaXMuX2lkZW50aXR5TWFwID0gdm9pZCAwOwogICAgICB0aGlzLl9uZXdseUNyZWF0ZWQgPSB2b2lkIDA7CiAgICAgIHRoaXMuaWRlbnRpZmllckNhY2hlID0gdm9pZCAwOwogICAgICB0aGlzLmlkZW50aWZpZXJDYWNoZSA9IGlkZW50aWZpZXJDYWNoZUZvcihzdG9yZSk7CgogICAgICB0aGlzLmlkZW50aWZpZXJDYWNoZS5fX2NvbmZpZ3VyZU1lcmdlKGZ1bmN0aW9uIChpZGVudGlmaWVyLCBtYXRjaGVkSWRlbnRpZmllciwgcmVzb3VyY2VEYXRhKSB7CiAgICAgICAgdmFyIGludGVuZGVkSWRlbnRpZmllciA9IGlkZW50aWZpZXIuaWQgPT09IHJlc291cmNlRGF0YS5pZCA/IGlkZW50aWZpZXIgOiBtYXRjaGVkSWRlbnRpZmllcjsKICAgICAgICB2YXIgYWx0SWRlbnRpZmllciA9IGlkZW50aWZpZXIuaWQgPT09IHJlc291cmNlRGF0YS5pZCA/IG1hdGNoZWRJZGVudGlmaWVyIDogaWRlbnRpZmllcjsgLy8gY2hlY2sgZm9yIGR1cGxpY2F0ZSBJbnRlcm5hbE1vZGVsJ3MKCiAgICAgICAgdmFyIG1hcCA9IF90aGlzLm1vZGVsTWFwRm9yKGlkZW50aWZpZXIudHlwZSk7CgogICAgICAgIHZhciBpbSA9IG1hcC5nZXQoaW50ZW5kZWRJZGVudGlmaWVyLmxpZCk7CiAgICAgICAgdmFyIG90aGVySW0gPSBtYXAuZ2V0KGFsdElkZW50aWZpZXIubGlkKTsgLy8gd2UgY2Fubm90IG1lcmdlIGludGVybmFsTW9kZWxzIHdoZW4gYm90aCBoYXZlIHJlY29yZHMKICAgICAgICAvLyAodGhpcyBtYXkgbm90IGJlIHN0cmljdGx5IHRydWUsIHdlIGNvdWxkIHByb2JhYmx5IHN3YXAgdGhlIGludGVybmFsTW9kZWwgdGhlIHJlY29yZCBwb2ludHMgYXQpCgogICAgICAgIGlmIChpbSAmJiBvdGhlckltICYmIGltLmhhc1JlY29yZCAmJiBvdGhlckltLmhhc1JlY29yZCkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJGYWlsZWQgdG8gdXBkYXRlIHRoZSAnaWQnIGZvciB0aGUgUmVjb3JkSWRlbnRpZmllciAnIiArIGlkZW50aWZpZXIgKyAiJyB0byAnIiArIHJlc291cmNlRGF0YS5pZCArICInLCBiZWNhdXNlIHRoYXQgaWQgaXMgYWxyZWFkeSBpbiB1c2UgYnkgJyIgKyBtYXRjaGVkSWRlbnRpZmllciArICInIik7CiAgICAgICAgfSAvLyByZW1vdmUgb3RoZXJJbSBmcm9tIGNhY2hlCgoKICAgICAgICBpZiAob3RoZXJJbSkgewogICAgICAgICAgbWFwLnJlbW92ZShvdGhlckltLCBhbHRJZGVudGlmaWVyLmxpZCk7CiAgICAgICAgfQoKICAgICAgICBpZiAoaW0gPT09IG51bGwgJiYgb3RoZXJJbSA9PT0gbnVsbCkgewogICAgICAgICAgLy8gbm90aGluZyBtb3JlIHRvIGRvCiAgICAgICAgICByZXR1cm4gaW50ZW5kZWRJZGVudGlmaWVyOyAvLyBvbmx5IHRoZSBvdGhlciBoYXMgYW4gSW50ZXJuYWxNb2RlbAogICAgICAgICAgLy8gT1Igb25seSB0aGUgb3RoZXIgaGFzIGEgUmVjb3JkCiAgICAgICAgfSBlbHNlIGlmIChpbSA9PT0gbnVsbCAmJiBvdGhlckltICE9PSBudWxsIHx8IGltICYmICFpbS5oYXNSZWNvcmQgJiYgb3RoZXJJbSAmJiBvdGhlckltLmhhc1JlY29yZCkgewogICAgICAgICAgaWYgKGltKSB7CiAgICAgICAgICAgIC8vIFRPRE8gY2hlY2sgaWYgd2UgYXJlIHJldGFpbmVkIGluIGFueSBhc3luYyByZWxhdGlvbnNoaXBzCiAgICAgICAgICAgIG1hcC5yZW1vdmUoaW0sIGludGVuZGVkSWRlbnRpZmllci5saWQpOyAvLyBpbS5kZXN0cm95KCk7CiAgICAgICAgICB9CgogICAgICAgICAgaW0gPSBvdGhlckltOyAvLyBUT0RPIGRvIHdlIG5lZWQgdG8gbm90aWZ5IHRoZSBpZCBjaGFuZ2U/CgogICAgICAgICAgaW0uX2lkID0gaW50ZW5kZWRJZGVudGlmaWVyLmlkOwogICAgICAgICAgbWFwLmFkZChpbSwgaW50ZW5kZWRJZGVudGlmaWVyLmxpZCk7IC8vIGp1c3QgdXNlIGltCiAgICAgICAgfQoKICAgICAgICByZXR1cm4gaW50ZW5kZWRJZGVudGlmaWVyOwogICAgICB9KTsKCiAgICAgIHRoaXMuX2lkZW50aXR5TWFwID0gbmV3IElkZW50aXR5TWFwKCk7CiAgICB9CiAgICAvKioKICAgICAqIFJldHJpZXZlIHRoZSBJbnRlcm5hbE1vZGVsIGZvciBhIGdpdmVuIHsgdHlwZSwgaWQsIGxpZCB9LgogICAgICoKICAgICAqIElmIGFuIEludGVybmFsTW9kZWwgZG9lcyBub3QgZXhpc3QsIGl0IGluc3RhbnRpYXRlcyBvbmUuCiAgICAgKgogICAgICogSWYgYW4gSW50ZXJuYWxNb2RlbCBkb2VzIGV4aXN0IGJ1cyBoYXMgYSBzY2hlZHVsZWQgZGVzdHJveSwKICAgICAqICAgdGhlIHNjaGVkdWxlZCBkZXN0cm95IHdpbGwgYmUgY2FuY2VsbGVkLgogICAgICoKICAgICAqIEBpbnRlcm5hbAogICAgICovCgoKICAgIHZhciBfcHJvdG8gPSBJbnRlcm5hbE1vZGVsRmFjdG9yeS5wcm90b3R5cGU7CgogICAgX3Byb3RvLmxvb2t1cCA9IGZ1bmN0aW9uIGxvb2t1cChyZXNvdXJjZSwgZGF0YSkgewogICAgICBpZiAoIGRhdGEgIT09IHVuZGVmaW5lZCkgewogICAgICAgIC8vIGlmIHdlJ3ZlIGJlZW4gZ2l2ZW4gZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhpcyBsb29rdXAKICAgICAgICAvLyB3ZSBtdXN0IGZpcnN0IGdpdmUgc2Vjb25kYXJ5LWNhY2hlcyBmb3IgTElEcyB0aGUKICAgICAgICAvLyBvcHBvcnR1bml0eSB0byBwb3B1bGF0ZSBiYXNlZCBvbiBpdAogICAgICAgIHRoaXMuaWRlbnRpZmllckNhY2hlLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihkYXRhKTsKICAgICAgfQoKICAgICAgdmFyIGlkZW50aWZpZXIgPSB0aGlzLmlkZW50aWZpZXJDYWNoZS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UpOwogICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IHRoaXMucGVlayhpZGVudGlmaWVyKTsKCiAgICAgIGlmIChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgLy8gdW5sb2FkUmVjb3JkIGlzIGFzeW5jLCBpZiBvbmUgYXR0ZW1wdHMgdG8gdW5sb2FkICsgdGhlbiBzeW5jIHB1c2gsCiAgICAgICAgLy8gICB3ZSBtdXN0IGVuc3VyZSB0aGUgdW5sb2FkIGlzIGNhbmNlbGVkIGJlZm9yZSBjb250aW51aW5nCiAgICAgICAgLy8gICBUaGUgY3JlYXRlUmVjb3JkIHBhdGggd2lsbCB0YWtlIF9leGlzdGluZ0ludGVybmFsTW9kZWxGb3JJZCgpCiAgICAgICAgLy8gICB3aGljaCB3aWxsIGNhbGwgYGRlc3Ryb3lTeW5jYCBpbnN0ZWFkIGZvciB0aGlzIHVubG9hZCArIHRoZW4KICAgICAgICAvLyAgIHN5bmMgY3JlYXRlUmVjb3JkIHNjZW5hcmlvLiBPbmNlIHdlIGhhdmUgdHJ1ZSBjbGllbnQtc2lkZQogICAgICAgIC8vICAgZGVsZXRlIHNpZ25hbGluZywgd2Ugc2hvdWxkIG5ldmVyIGNhbGwgZGVzdHJveVN5bmMKICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbC5oYXNTY2hlZHVsZWREZXN0cm95KCkpIHsKICAgICAgICAgIGludGVybmFsTW9kZWwuY2FuY2VsRGVzdHJveSgpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWw7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLl9idWlsZChpZGVudGlmaWVyLCBmYWxzZSk7CiAgICB9CiAgICAvKioKICAgICAqIFBlZWsgdGhlIEludGVybmFsTW9kZWwgZm9yIGEgZ2l2ZW4geyB0eXBlLCBpZCwgbGlkIH0uCiAgICAgKgogICAgICogSWYgYW4gSW50ZXJuYWxNb2RlbCBkb2VzIG5vdCBleGlzdCwgcmV0dXJuIGBudWxsYC4KICAgICAqCiAgICAgKiBAaW50ZXJuYWwKICAgICAqLwogICAgOwoKICAgIF9wcm90by5wZWVrID0gZnVuY3Rpb24gcGVlayhpZGVudGlmaWVyKSB7CiAgICAgIHsKICAgICAgICByZXR1cm4gdGhpcy5tb2RlbE1hcEZvcihpZGVudGlmaWVyLnR5cGUpLmdldChpZGVudGlmaWVyLmxpZCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmdldEJ5UmVzb3VyY2UgPSBmdW5jdGlvbiBnZXRCeVJlc291cmNlKHJlc291cmNlKSB7CiAgICAgIHsKICAgICAgICB2YXIgbm9ybWFsaXplZFJlc291cmNlID0gY29uc3RydWN0UmVzb3VyY2UocmVzb3VyY2UudHlwZSwgcmVzb3VyY2UuaWQsIHJlc291cmNlLmxpZCk7CiAgICAgICAgcmV0dXJuIHRoaXMubG9va3VwKG5vcm1hbGl6ZWRSZXNvdXJjZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnNldFJlY29yZElkID0gZnVuY3Rpb24gc2V0UmVjb3JkSWQodHlwZSwgaWQsIGxpZCkgewogICAgICB2YXIgcmVzb3VyY2UgPSB7CiAgICAgICAgdHlwZTogdHlwZSwKICAgICAgICBpZDogbnVsbCwKICAgICAgICBsaWQ6IGxpZAogICAgICB9OwogICAgICB2YXIgaWRlbnRpZmllciA9IHRoaXMuaWRlbnRpZmllckNhY2hlLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihyZXNvdXJjZSk7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gdGhpcy5wZWVrKGlkZW50aWZpZXIpOwoKICAgICAgaWYgKGludGVybmFsTW9kZWwgPT09IG51bGwpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkNhbm5vdCBzZXQgdGhlIGlkICIgKyBpZCArICIgb24gdGhlIHJlY29yZCAiICsgdHlwZSArICI6IiArIGxpZCArICIgYXMgdGhlcmUgaXMgbm8gc3VjaCByZWNvcmQgaW4gdGhlIGNhY2hlLiIpOwogICAgICB9CgogICAgICB2YXIgb2xkSWQgPSBpbnRlcm5hbE1vZGVsLmlkOwogICAgICB2YXIgbW9kZWxOYW1lID0gaW50ZXJuYWxNb2RlbC5tb2RlbE5hbWU7IC8vIElEIGFic29sdXRlbHkgY2FuJ3QgYmUgbWlzc2luZyBpZiB0aGUgb2xkSUQgaXMgZW1wdHkgKG1pc3NpbmcgSWQgaW4gcmVzcG9uc2UgZm9yIGEgbmV3IHJlY29yZCkKICAgICAgLy8gaG93ZXZlciwgdGhpcyBpcyBtb3JlIHRoYW4gbGlrZWx5IGEgZGV2ZWxvcGVyIGVycm9yLgoKICAgICAgaWYgKG9sZElkICE9PSBudWxsICYmIGlkID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgZXhpc3RpbmdJbnRlcm5hbE1vZGVsID0gdGhpcy5wZWVrQnlJZChtb2RlbE5hbWUsIGlkKTsKCiAgICAgIGlmIChpZGVudGlmaWVyLmlkID09PSBudWxsKSB7CiAgICAgICAgdGhpcy5pZGVudGlmaWVyQ2FjaGUudXBkYXRlUmVjb3JkSWRlbnRpZmllcihpZGVudGlmaWVyLCB7CiAgICAgICAgICB0eXBlOiB0eXBlLAogICAgICAgICAgaWQ6IGlkCiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIGludGVybmFsTW9kZWwuc2V0SWQoaWQpOwogICAgfTsKCiAgICBfcHJvdG8ucGVla0J5SWQgPSBmdW5jdGlvbiBwZWVrQnlJZCh0eXBlLCBpZCkgewogICAgICB2YXIgaWRlbnRpZmllciA9IHRoaXMuaWRlbnRpZmllckNhY2hlLnBlZWtSZWNvcmRJZGVudGlmaWVyKHsKICAgICAgICB0eXBlOiB0eXBlLAogICAgICAgIGlkOiBpZAogICAgICB9KTsKICAgICAgdmFyIGludGVybmFsTW9kZWw7CgogICAgICB7CiAgICAgICAgaW50ZXJuYWxNb2RlbCA9IGlkZW50aWZpZXIgPyB0aGlzLm1vZGVsTWFwRm9yKHR5cGUpLmdldChpZGVudGlmaWVyLmxpZCkgOiBudWxsOwogICAgICB9CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbCAmJiBpbnRlcm5hbE1vZGVsLmhhc1NjaGVkdWxlZERlc3Ryb3koKSkgewogICAgICAgIC8vIHVubG9hZFJlY29yZCBpcyBhc3luYywgaWYgb25lIGF0dGVtcHRzIHRvIHVubG9hZCArIHRoZW4gc3luYyBjcmVhdGUsCiAgICAgICAgLy8gICB3ZSBtdXN0IGVuc3VyZSB0aGUgdW5sb2FkIGlzIGNvbXBsZXRlIGJlZm9yZSBzdGFydGluZyB0aGUgY3JlYXRlCiAgICAgICAgLy8gICBUaGUgcHVzaCBwYXRoIHdpbGwgdGFrZSB0aGlzLmxvb2t1cCgpCiAgICAgICAgLy8gICB3aGljaCB3aWxsIGNhbGwgYGNhbmNlbERlc3Ryb3lgIGluc3RlYWQgZm9yIHRoaXMgdW5sb2FkICsgdGhlbgogICAgICAgIC8vICAgc3luYyBwdXNoIHNjZW5hcmlvLiBPbmNlIHdlIGhhdmUgdHJ1ZSBjbGllbnQtc2lkZQogICAgICAgIC8vICAgZGVsZXRlIHNpZ25hbGluZywgd2Ugc2hvdWxkIG5ldmVyIGNhbGwgZGVzdHJveVN5bmMKICAgICAgICBpbnRlcm5hbE1vZGVsLmRlc3Ryb3lTeW5jKCk7CiAgICAgICAgaW50ZXJuYWxNb2RlbCA9IG51bGw7CiAgICAgIH0KCiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsOwogICAgfTsKCiAgICBfcHJvdG8uYnVpbGQgPSBmdW5jdGlvbiBidWlsZChuZXdSZXNvdXJjZUluZm8pIHsKICAgICAgcmV0dXJuIHRoaXMuX2J1aWxkKG5ld1Jlc291cmNlSW5mbywgdHJ1ZSk7CiAgICB9OwoKICAgIF9wcm90by5fYnVpbGQgPSBmdW5jdGlvbiBfYnVpbGQocmVzb3VyY2UsIGlzQ3JlYXRlKSB7CiAgICAgIGlmIChpc0NyZWF0ZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgaXNDcmVhdGUgPSBmYWxzZTsKICAgICAgfQoKICAgICAgaWYgKGlzQ3JlYXRlID09PSB0cnVlICYmIHJlc291cmNlLmlkKSB7CiAgICAgICAgdmFyIGV4aXN0aW5nSW50ZXJuYWxNb2RlbCA9IHRoaXMucGVla0J5SWQocmVzb3VyY2UudHlwZSwgcmVzb3VyY2UuaWQpOwogICAgICB9CgogICAgICB2YXIgaWRlbnRpZmllckNhY2hlID0gdGhpcy5pZGVudGlmaWVyQ2FjaGU7CiAgICAgIHZhciBpZGVudGlmaWVyOwoKICAgICAgaWYgKGlzQ3JlYXRlID09PSB0cnVlKSB7CiAgICAgICAgaWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZS5jcmVhdGVJZGVudGlmaWVyRm9yTmV3UmVjb3JkKHJlc291cmNlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZGVudGlmaWVyID0gcmVzb3VyY2U7CiAgICAgIH0gLy8gbG9va3VwRmFjdG9yeSBzaG91bGQgcmVhbGx5IHJldHVybiBhbiBvYmplY3QgdGhhdCBjcmVhdGVzCiAgICAgIC8vIGluc3RhbmNlcyB3aXRoIHRoZSBpbmplY3Rpb25zIGFwcGxpZWQKCgogICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IG5ldyBJbnRlcm5hbE1vZGVsKHRoaXMuc3RvcmUsIGlkZW50aWZpZXIpOwoKICAgICAgewogICAgICAgIHRoaXMubW9kZWxNYXBGb3IocmVzb3VyY2UudHlwZSkuYWRkKGludGVybmFsTW9kZWwsIGlkZW50aWZpZXIubGlkKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWw7CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmUgPSBmdW5jdGlvbiByZW1vdmUoaW50ZXJuYWxNb2RlbCkgewogICAgICB2YXIgcmVjb3JkTWFwID0gdGhpcy5tb2RlbE1hcEZvcihpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZSk7CiAgICAgIHZhciBjbGllbnRJZCA9IGludGVybmFsTW9kZWwuaWRlbnRpZmllci5saWQ7CgogICAgICB7CiAgICAgICAgcmVjb3JkTWFwLnJlbW92ZShpbnRlcm5hbE1vZGVsLCBjbGllbnRJZCk7CiAgICAgIH0KCiAgICAgIHZhciBpZGVudGlmaWVyID0gaW50ZXJuYWxNb2RlbC5pZGVudGlmaWVyOwogICAgICB0aGlzLmlkZW50aWZpZXJDYWNoZS5mb3JnZXRSZWNvcmRJZGVudGlmaWVyKGlkZW50aWZpZXIpOwogICAgfTsKCiAgICBfcHJvdG8ubW9kZWxNYXBGb3IgPSBmdW5jdGlvbiBtb2RlbE1hcEZvcih0eXBlKSB7CiAgICAgIHJldHVybiB0aGlzLl9pZGVudGl0eU1hcC5yZXRyaWV2ZSh0eXBlKTsKICAgIH07CgogICAgX3Byb3RvLl9uZXdseUNyZWF0ZWRNb2RlbHNGb3IgPSBmdW5jdGlvbiBfbmV3bHlDcmVhdGVkTW9kZWxzRm9yKHR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMuX25ld2x5Q3JlYXRlZC5yZXRyaWV2ZSh0eXBlKTsKICAgIH07CgogICAgX3Byb3RvLmNsZWFyID0gZnVuY3Rpb24gY2xlYXIodHlwZSkgewogICAgICBpZiAodHlwZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdGhpcy5faWRlbnRpdHlNYXAuY2xlYXIoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLm1vZGVsTWFwRm9yKHR5cGUpLmNsZWFyKCk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEludGVybmFsTW9kZWxGYWN0b3J5OwogIH0oKTsKCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXMkNSh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgidmFsdWUiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfQoKICBmdW5jdGlvbiBfY3JlYXRlQ2xhc3MkNShDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDUoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQ1KENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfQoKICB2YXIgUmVjb3JkRGF0YVN0b3JlV3JhcHBlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJlY29yZERhdGFTdG9yZVdyYXBwZXIoX3N0b3JlKSB7CiAgICAgIHRoaXMuX3N0b3JlID0gX3N0b3JlOwogICAgICB0aGlzW0JSQU5EX1NZTUJPTF0gPSB2b2lkIDA7CiAgICAgIHRoaXMuX3dpbGxVcGRhdGVNYW55QXJyYXlzID0gdm9pZCAwOwogICAgICB0aGlzLl9wZW5kaW5nTWFueUFycmF5VXBkYXRlcyA9IHZvaWQgMDsKICAgICAgdGhpcy5fd2lsbFVwZGF0ZU1hbnlBcnJheXMgPSBmYWxzZTsKICAgICAgdGhpcy5fcGVuZGluZ01hbnlBcnJheVVwZGF0ZXMgPSBbXTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gUmVjb3JkRGF0YVN0b3JlV3JhcHBlci5wcm90b3R5cGU7CgogICAgLyoqCiAgICAgKiBFeGlzdHMgc28gdGhhdCBEZWZhdWx0UmVjb3JkRGF0YSBjYW4gY2hlY2sgZm9yIG1vZGVsIHR5cGVzCiAgICAgKiBpbiBERUJVRyBmb3IgcmVsYXRpb25zaGlwcy4gU2hvdWxkIGJlIHJlZmFjdG9yZWQgYXdheS4KICAgICAqCiAgICAgKiBAaW50ZXJuYWwKICAgICAqLwogICAgX3Byb3RvLl9oYXNNb2RlbEZvciA9IGZ1bmN0aW9uIF9oYXNNb2RlbEZvcih0eXBlKSB7CiAgICAgIHJldHVybiB0aGlzLl9zdG9yZS5faGFzTW9kZWxGb3IodHlwZSk7CiAgICB9CiAgICAvKioKICAgICAqIEBpbnRlcm5hbAogICAgICovCiAgICA7CgogICAgX3Byb3RvLl9zY2hlZHVsZU1hbnlBcnJheVVwZGF0ZSA9IGZ1bmN0aW9uIF9zY2hlZHVsZU1hbnlBcnJheVVwZGF0ZShpZGVudGlmaWVyLCBrZXkpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHZhciBwZW5kaW5nID0gdGhpcy5fcGVuZGluZ01hbnlBcnJheVVwZGF0ZXMgPSB0aGlzLl9wZW5kaW5nTWFueUFycmF5VXBkYXRlcyB8fCBbXTsKICAgICAgcGVuZGluZy5wdXNoKGlkZW50aWZpZXIsIGtleSk7CgogICAgICBpZiAodGhpcy5fd2lsbFVwZGF0ZU1hbnlBcnJheXMgPT09IHRydWUpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuX3dpbGxVcGRhdGVNYW55QXJyYXlzID0gdHJ1ZTsKICAgICAgdmFyIGJhY2tidXJuZXIgPSB0aGlzLl9zdG9yZS5fYmFja2J1cm5lcjsKICAgICAgYmFja2J1cm5lci5qb2luKGZ1bmN0aW9uICgpIHsKICAgICAgICBiYWNrYnVybmVyLnNjaGVkdWxlKCdzeW5jUmVsYXRpb25zaGlwcycsIF90aGlzLCBfdGhpcy5fZmx1c2hQZW5kaW5nTWFueUFycmF5VXBkYXRlcyk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8ubm90aWZ5RXJyb3JzQ2hhbmdlID0gZnVuY3Rpb24gbm90aWZ5RXJyb3JzQ2hhbmdlKHR5cGUsIGlkLCBsaWQpIHsKICAgICAgdmFyIHJlc291cmNlID0gY29uc3RydWN0UmVzb3VyY2UodHlwZSwgaWQsIGxpZCk7CiAgICAgIHZhciBpZGVudGlmaWVyID0gaWRlbnRpZmllckNhY2hlRm9yKHRoaXMuX3N0b3JlKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UpOwogICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMuX3N0b3JlKS5wZWVrKGlkZW50aWZpZXIpOwoKICAgICAgaWYgKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLm5vdGlmeUVycm9yc0NoYW5nZSgpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fZmx1c2hQZW5kaW5nTWFueUFycmF5VXBkYXRlcyA9IGZ1bmN0aW9uIF9mbHVzaFBlbmRpbmdNYW55QXJyYXlVcGRhdGVzKCkgewogICAgICBpZiAodGhpcy5fd2lsbFVwZGF0ZU1hbnlBcnJheXMgPT09IGZhbHNlKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgcGVuZGluZyA9IHRoaXMuX3BlbmRpbmdNYW55QXJyYXlVcGRhdGVzOwogICAgICB0aGlzLl9wZW5kaW5nTWFueUFycmF5VXBkYXRlcyA9IFtdOwogICAgICB0aGlzLl93aWxsVXBkYXRlTWFueUFycmF5cyA9IGZhbHNlOwogICAgICB2YXIgZmFjdG9yeSA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMuX3N0b3JlKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGVuZGluZy5sZW5ndGg7IGkgKz0gMikgewogICAgICAgIHZhciBpZGVudGlmaWVyID0gcGVuZGluZ1tpXTsKICAgICAgICB2YXIgX2tleSA9IHBlbmRpbmdbaSArIDFdOwogICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gZmFjdG9yeS5wZWVrKGlkZW50aWZpZXIpOwoKICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC5ub3RpZnlIYXNNYW55Q2hhbmdlKF9rZXkpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uYXR0cmlidXRlc0RlZmluaXRpb25Gb3IgPSBmdW5jdGlvbiBhdHRyaWJ1dGVzRGVmaW5pdGlvbkZvcih0eXBlKSB7CiAgICAgIHJldHVybiB0aGlzLl9zdG9yZS5fYXR0cmlidXRlc0RlZmluaXRpb25Gb3IodHlwZSk7CiAgICB9OwoKICAgIF9wcm90by5yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvciA9IGZ1bmN0aW9uIHJlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKHR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMuX3N0b3JlLl9yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcih0eXBlKTsKICAgIH07CgogICAgX3Byb3RvLmludmVyc2VGb3JSZWxhdGlvbnNoaXAgPSBmdW5jdGlvbiBpbnZlcnNlRm9yUmVsYXRpb25zaGlwKHR5cGUsIGtleSkgewogICAgICB2YXIgbW9kZWxDbGFzcyA9IHRoaXMuX3N0b3JlLm1vZGVsRm9yKHR5cGUpOwoKICAgICAgdmFyIGRlZmluaXRpb24gPSB1cGdyYWRlRm9ySW50ZXJuYWwodGhpcy5yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcih0eXBlKVtrZXldKTsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICBpZiAoZGVmaW5pdGlvbi5pbnZlcnNlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJldHVybiBkZWZpbml0aW9uLmludmVyc2U7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vVE9ETyBhZGQgYSB0ZXN0IGZvciB0aGlzIGJyYW5jaAogICAgICAgICAgaWYgKCFkZWZpbml0aW9uLl9pbnZlcnNlS2V5KSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBkZWZpbml0aW9uLl9pbnZlcnNlS2V5KHRoaXMuX3N0b3JlLCBtb2RlbENsYXNzKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGRlZmluaXRpb24uX2ludmVyc2VLZXkodGhpcy5fc3RvcmUsIG1vZGVsQ2xhc3MpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5pbnZlcnNlSXNBc3luY0ZvclJlbGF0aW9uc2hpcCA9IGZ1bmN0aW9uIGludmVyc2VJc0FzeW5jRm9yUmVsYXRpb25zaGlwKHR5cGUsIGtleSkgewogICAgICB2YXIgbW9kZWxDbGFzcyA9IHRoaXMuX3N0b3JlLm1vZGVsRm9yKHR5cGUpOwoKICAgICAgdmFyIGRlZmluaXRpb24gPSB1cGdyYWRlRm9ySW50ZXJuYWwodGhpcy5yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcih0eXBlKVtrZXldKTsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICBpZiAoZGVmaW5pdGlvbi5pbnZlcnNlID09PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICBpZiAoZGVmaW5pdGlvbi5pbnZlcnNlSXNBc3luYyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICByZXR1cm4gISFkZWZpbml0aW9uLmludmVyc2VJc0FzeW5jOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gZGVmaW5pdGlvbi5faW52ZXJzZUlzQXN5bmModGhpcy5fc3RvcmUsIG1vZGVsQ2xhc3MpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gZGVmaW5pdGlvbi5faW52ZXJzZUlzQXN5bmModGhpcy5fc3RvcmUsIG1vZGVsQ2xhc3MpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlQcm9wZXJ0eUNoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeVByb3BlcnR5Q2hhbmdlKHR5cGUsIGlkLCBsaWQsIGtleSkgewogICAgICB2YXIgcmVzb3VyY2UgPSBjb25zdHJ1Y3RSZXNvdXJjZSh0eXBlLCBpZCwgbGlkKTsKICAgICAgdmFyIGlkZW50aWZpZXIgPSBpZGVudGlmaWVyQ2FjaGVGb3IodGhpcy5fc3RvcmUpLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihyZXNvdXJjZSk7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcy5fc3RvcmUpLnBlZWsoaWRlbnRpZmllcik7CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwubm90aWZ5UHJvcGVydHlDaGFuZ2Uoa2V5KTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ubm90aWZ5SGFzTWFueUNoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeUhhc01hbnlDaGFuZ2UodHlwZSwgaWQsIGxpZCwga2V5KSB7CiAgICAgIHZhciByZXNvdXJjZSA9IGNvbnN0cnVjdFJlc291cmNlKHR5cGUsIGlkLCBsaWQpOwogICAgICB2YXIgaWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzLl9zdG9yZSkuZ2V0T3JDcmVhdGVSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlKTsKCiAgICAgIHRoaXMuX3NjaGVkdWxlTWFueUFycmF5VXBkYXRlKGlkZW50aWZpZXIsIGtleSk7CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlCZWxvbmdzVG9DaGFuZ2UgPSBmdW5jdGlvbiBub3RpZnlCZWxvbmdzVG9DaGFuZ2UodHlwZSwgaWQsIGxpZCwga2V5KSB7CiAgICAgIHZhciByZXNvdXJjZSA9IGNvbnN0cnVjdFJlc291cmNlKHR5cGUsIGlkLCBsaWQpOwogICAgICB2YXIgaWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzLl9zdG9yZSkuZ2V0T3JDcmVhdGVSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlKTsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzLl9zdG9yZSkucGVlayhpZGVudGlmaWVyKTsKCiAgICAgIGlmIChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC5ub3RpZnlCZWxvbmdzVG9DaGFuZ2Uoa2V5KTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ubm90aWZ5U3RhdGVDaGFuZ2UgPSBmdW5jdGlvbiBub3RpZnlTdGF0ZUNoYW5nZSh0eXBlLCBpZCwgbGlkLCBrZXkpIHsKICAgICAgdmFyIHJlc291cmNlID0gY29uc3RydWN0UmVzb3VyY2UodHlwZSwgaWQsIGxpZCk7CiAgICAgIHZhciBpZGVudGlmaWVyID0gaWRlbnRpZmllckNhY2hlRm9yKHRoaXMuX3N0b3JlKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UpOwogICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMuX3N0b3JlKS5wZWVrKGlkZW50aWZpZXIpOwoKICAgICAgaWYgKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLm5vdGlmeVN0YXRlQ2hhbmdlKGtleSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnJlY29yZERhdGFGb3IgPSBmdW5jdGlvbiByZWNvcmREYXRhRm9yKHR5cGUsIGlkLCBsaWQpIHsKICAgICAgdmFyIGlkZW50aWZpZXI7CiAgICAgIHZhciBpc0NyZWF0ZSA9IGZhbHNlOwoKICAgICAgaWYgKCFpZCAmJiAhbGlkKSB7CiAgICAgICAgaXNDcmVhdGUgPSB0cnVlOwogICAgICAgIGlkZW50aWZpZXIgPSB7CiAgICAgICAgICB0eXBlOiB0eXBlCiAgICAgICAgfTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgcmVzb3VyY2UgPSBjb25zdHJ1Y3RSZXNvdXJjZSh0eXBlLCBpZCwgbGlkKTsKICAgICAgICBpZGVudGlmaWVyID0gaWRlbnRpZmllckNhY2hlRm9yKHRoaXMuX3N0b3JlKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UpOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fc3RvcmUucmVjb3JkRGF0YUZvcihpZGVudGlmaWVyLCBpc0NyZWF0ZSk7CiAgICB9OwoKICAgIF9wcm90by5zZXRSZWNvcmRJZCA9IGZ1bmN0aW9uIHNldFJlY29yZElkKHR5cGUsIGlkLCBsaWQpIHsKICAgICAgdGhpcy5fc3RvcmUuc2V0UmVjb3JkSWQodHlwZSwgaWQsIGxpZCk7CiAgICB9OwoKICAgIF9wcm90by5pc1JlY29yZEluVXNlID0gZnVuY3Rpb24gaXNSZWNvcmRJblVzZSh0eXBlLCBpZCwgbGlkKSB7CiAgICAgIHZhciByZXNvdXJjZSA9IGNvbnN0cnVjdFJlc291cmNlKHR5cGUsIGlkLCBsaWQpOwogICAgICB2YXIgaWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzLl9zdG9yZSkuZ2V0T3JDcmVhdGVSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlKTsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzLl9zdG9yZSkucGVlayhpZGVudGlmaWVyKTsKCiAgICAgIGlmICghaW50ZXJuYWxNb2RlbCkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwuaXNSZWNvcmRJblVzZSgpOwogICAgfTsKCiAgICBfcHJvdG8uZGlzY29ubmVjdFJlY29yZCA9IGZ1bmN0aW9uIGRpc2Nvbm5lY3RSZWNvcmQodHlwZSwgaWQsIGxpZCkgewogICAgICB2YXIgcmVzb3VyY2UgPSBjb25zdHJ1Y3RSZXNvdXJjZSh0eXBlLCBpZCwgbGlkKTsKICAgICAgdmFyIGlkZW50aWZpZXIgPSBpZGVudGlmaWVyQ2FjaGVGb3IodGhpcy5fc3RvcmUpLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihyZXNvdXJjZSk7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcy5fc3RvcmUpLnBlZWsoaWRlbnRpZmllcik7CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwuZGVzdHJveUZyb21SZWNvcmREYXRhKCk7CiAgICAgIH0KICAgIH07CgogICAgX2NyZWF0ZUNsYXNzJDUoUmVjb3JkRGF0YVN0b3JlV3JhcHBlciwgW3sKICAgICAga2V5OiAiaWRlbnRpZmllckNhY2hlIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CgogICAgICAgIHJldHVybiBpZGVudGlmaWVyQ2FjaGVGb3IodGhpcy5fc3RvcmUpOwogICAgICB9CiAgICB9XSk7CgogICAgcmV0dXJuIFJlY29yZERhdGFTdG9yZVdyYXBwZXI7CiAgfSgpOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwogIC8qCiAgICBUaGlzIGlzIGEgaGVscGVyIG1ldGhvZCB0aGF0IGFsd2F5cyByZXR1cm5zIGEgSlNPTi1BUEkgRG9jdW1lbnQuCgogICAgQG1ldGhvZCBub3JtYWxpemVSZXNwb25zZUhlbHBlcgogICAgQHBhcmFtIHtTZXJpYWxpemVyfSBzZXJpYWxpemVyCiAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgQHBhcmFtIHtzdWJjbGFzcyBvZiBNb2RlbH0gbW9kZWxDbGFzcwogICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICovCgogIGZ1bmN0aW9uIG5vcm1hbGl6ZVJlc3BvbnNlSGVscGVyKHNlcmlhbGl6ZXIsIHN0b3JlLCBtb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgIHZhciBub3JtYWxpemVkUmVzcG9uc2UgPSBzZXJpYWxpemVyLm5vcm1hbGl6ZVJlc3BvbnNlKHN0b3JlLCBtb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpOwogICAgcmV0dXJuIG5vcm1hbGl6ZWRSZXNwb25zZTsKICB9CgogIHZhciBSZXF1ZXN0U3RhdGVFbnVtOwoKICAoZnVuY3Rpb24gKFJlcXVlc3RTdGF0ZUVudW0pIHsKICAgIFJlcXVlc3RTdGF0ZUVudW1bInBlbmRpbmciXSA9ICJwZW5kaW5nIjsKICAgIFJlcXVlc3RTdGF0ZUVudW1bImZ1bGZpbGxlZCJdID0gImZ1bGZpbGxlZCI7CiAgICBSZXF1ZXN0U3RhdGVFbnVtWyJyZWplY3RlZCJdID0gInJlamVjdGVkIjsKICB9KShSZXF1ZXN0U3RhdGVFbnVtIHx8IChSZXF1ZXN0U3RhdGVFbnVtID0ge30pKTsKCiAgdmFyIFRvdWNoaW5nID0gc3ltYm9sKCd0b3VjaGluZycpOwogIHZhciBSZXF1ZXN0UHJvbWlzZSA9IHN5bWJvbCgncHJvbWlzZScpOwoKICBmdW5jdGlvbiBoYXNSZWNvcmRJZGVudGlmaWVyKG9wKSB7CiAgICByZXR1cm4gJ3JlY29yZElkZW50aWZpZXInIGluIG9wOwogIH0KCiAgdmFyIFJlcXVlc3RDYWNoZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJlcXVlc3RDYWNoZSgpIHsKICAgICAgdGhpcy5fcGVuZGluZyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHRoaXMuX2RvbmUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9zdWJzY3JpcHRpb25zID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gUmVxdWVzdENhY2hlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uZW5xdWV1ZSA9IGZ1bmN0aW9uIGVucXVldWUocHJvbWlzZSwgcXVlcnlSZXF1ZXN0KSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICB2YXIgcXVlcnkgPSBxdWVyeVJlcXVlc3QuZGF0YVswXTsKCiAgICAgIGlmIChoYXNSZWNvcmRJZGVudGlmaWVyKHF1ZXJ5KSkgewogICAgICAgIHZhciBfcmVxdWVzdDsKCiAgICAgICAgdmFyIF9saWQgPSBxdWVyeS5yZWNvcmRJZGVudGlmaWVyLmxpZDsKICAgICAgICB2YXIgdHlwZSA9IHF1ZXJ5Lm9wID09PSAnc2F2ZVJlY29yZCcgPyAnbXV0YXRpb24nIDogJ3F1ZXJ5JzsKCiAgICAgICAgaWYgKCF0aGlzLl9wZW5kaW5nW19saWRdKSB7CiAgICAgICAgICB0aGlzLl9wZW5kaW5nW19saWRdID0gW107CiAgICAgICAgfQoKICAgICAgICB2YXIgcmVxdWVzdCA9IChfcmVxdWVzdCA9IHsKICAgICAgICAgIHN0YXRlOiBSZXF1ZXN0U3RhdGVFbnVtLnBlbmRpbmcsCiAgICAgICAgICByZXF1ZXN0OiBxdWVyeVJlcXVlc3QsCiAgICAgICAgICB0eXBlOiB0eXBlCiAgICAgICAgfSwgX3JlcXVlc3RbVG91Y2hpbmddID0gW3F1ZXJ5LnJlY29yZElkZW50aWZpZXJdLCBfcmVxdWVzdFtSZXF1ZXN0UHJvbWlzZV0gPSBwcm9taXNlLCBfcmVxdWVzdCk7CgogICAgICAgIHRoaXMuX3BlbmRpbmdbX2xpZF0ucHVzaChyZXF1ZXN0KTsKCiAgICAgICAgdGhpcy5fdHJpZ2dlclN1YnNjcmlwdGlvbnMocmVxdWVzdCk7CgogICAgICAgIHByb21pc2UudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7CiAgICAgICAgICB2YXIgX2ZpbmFsaXplZFJlcXVlc3Q7CgogICAgICAgICAgX3RoaXMuX2RlcXVldWUoX2xpZCwgcmVxdWVzdCk7CgogICAgICAgICAgdmFyIGZpbmFsaXplZFJlcXVlc3QgPSAoX2ZpbmFsaXplZFJlcXVlc3QgPSB7CiAgICAgICAgICAgIHN0YXRlOiBSZXF1ZXN0U3RhdGVFbnVtLmZ1bGZpbGxlZCwKICAgICAgICAgICAgcmVxdWVzdDogcXVlcnlSZXF1ZXN0LAogICAgICAgICAgICB0eXBlOiB0eXBlCiAgICAgICAgICB9LCBfZmluYWxpemVkUmVxdWVzdFtUb3VjaGluZ10gPSByZXF1ZXN0W1RvdWNoaW5nXSwgX2ZpbmFsaXplZFJlcXVlc3QucmVzcG9uc2UgPSB7CiAgICAgICAgICAgIGRhdGE6IHJlc3VsdAogICAgICAgICAgfSwgX2ZpbmFsaXplZFJlcXVlc3QpOwoKICAgICAgICAgIF90aGlzLl9hZGREb25lKGZpbmFsaXplZFJlcXVlc3QpOwoKICAgICAgICAgIF90aGlzLl90cmlnZ2VyU3Vic2NyaXB0aW9ucyhmaW5hbGl6ZWRSZXF1ZXN0KTsKICAgICAgICB9LCBmdW5jdGlvbiAoZXJyb3IpIHsKICAgICAgICAgIHZhciBfZmluYWxpemVkUmVxdWVzdDI7CgogICAgICAgICAgX3RoaXMuX2RlcXVldWUoX2xpZCwgcmVxdWVzdCk7CgogICAgICAgICAgdmFyIGZpbmFsaXplZFJlcXVlc3QgPSAoX2ZpbmFsaXplZFJlcXVlc3QyID0gewogICAgICAgICAgICBzdGF0ZTogUmVxdWVzdFN0YXRlRW51bS5yZWplY3RlZCwKICAgICAgICAgICAgcmVxdWVzdDogcXVlcnlSZXF1ZXN0LAogICAgICAgICAgICB0eXBlOiB0eXBlCiAgICAgICAgICB9LCBfZmluYWxpemVkUmVxdWVzdDJbVG91Y2hpbmddID0gcmVxdWVzdFtUb3VjaGluZ10sIF9maW5hbGl6ZWRSZXF1ZXN0Mi5yZXNwb25zZSA9IHsKICAgICAgICAgICAgZGF0YTogZXJyb3IgJiYgZXJyb3IuZXJyb3IKICAgICAgICAgIH0sIF9maW5hbGl6ZWRSZXF1ZXN0Mik7CgogICAgICAgICAgX3RoaXMuX2FkZERvbmUoZmluYWxpemVkUmVxdWVzdCk7CgogICAgICAgICAgX3RoaXMuX3RyaWdnZXJTdWJzY3JpcHRpb25zKGZpbmFsaXplZFJlcXVlc3QpOwogICAgICAgIH0pOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fdHJpZ2dlclN1YnNjcmlwdGlvbnMgPSBmdW5jdGlvbiBfdHJpZ2dlclN1YnNjcmlwdGlvbnMocmVxKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgcmVxW1RvdWNoaW5nXS5mb3JFYWNoKGZ1bmN0aW9uIChpZGVudGlmaWVyKSB7CiAgICAgICAgaWYgKF90aGlzMi5fc3Vic2NyaXB0aW9uc1tpZGVudGlmaWVyLmxpZF0pIHsKICAgICAgICAgIF90aGlzMi5fc3Vic2NyaXB0aW9uc1tpZGVudGlmaWVyLmxpZF0uZm9yRWFjaChmdW5jdGlvbiAoY2FsbGJhY2spIHsKICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHJlcSk7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8uX2RlcXVldWUgPSBmdW5jdGlvbiBfZGVxdWV1ZShsaWQsIHJlcXVlc3QpIHsKICAgICAgdGhpcy5fcGVuZGluZ1tsaWRdID0gdGhpcy5fcGVuZGluZ1tsaWRdLmZpbHRlcihmdW5jdGlvbiAocmVxKSB7CiAgICAgICAgcmV0dXJuIHJlcSAhPT0gcmVxdWVzdDsKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5fYWRkRG9uZSA9IGZ1bmN0aW9uIF9hZGREb25lKHJlcXVlc3QpIHsKICAgICAgdmFyIF90aGlzMyA9IHRoaXM7CgogICAgICByZXF1ZXN0W1RvdWNoaW5nXS5mb3JFYWNoKGZ1bmN0aW9uIChpZGVudGlmaWVyKSB7CiAgICAgICAgaWYgKCFfdGhpczMuX2RvbmVbaWRlbnRpZmllci5saWRdKSB7CiAgICAgICAgICBfdGhpczMuX2RvbmVbaWRlbnRpZmllci5saWRdID0gW107CiAgICAgICAgfSAvLyBUT0RPIGFkZCBzdXBwb3J0IGZvciBtdWx0aXBsZQoKCiAgICAgICAgdmFyIHJlcXVlc3REYXRhT3AgPSByZXF1ZXN0LnJlcXVlc3QuZGF0YVswXS5vcDsKICAgICAgICBfdGhpczMuX2RvbmVbaWRlbnRpZmllci5saWRdID0gX3RoaXMzLl9kb25lW2lkZW50aWZpZXIubGlkXS5maWx0ZXIoZnVuY3Rpb24gKHJlcSkgewogICAgICAgICAgLy8gVE9ETyBhZGQgc3VwcG9ydCBmb3IgbXVsdGlwbGUKICAgICAgICAgIHZhciBkYXRhOwoKICAgICAgICAgIGlmIChyZXEucmVxdWVzdC5kYXRhIGluc3RhbmNlb2YgQXJyYXkpIHsKICAgICAgICAgICAgZGF0YSA9IHJlcS5yZXF1ZXN0LmRhdGFbMF07CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBkYXRhID0gcmVxLnJlcXVlc3QuZGF0YTsKICAgICAgICAgIH0KCiAgICAgICAgICByZXR1cm4gZGF0YS5vcCAhPT0gcmVxdWVzdERhdGFPcDsKICAgICAgICB9KTsKCiAgICAgICAgX3RoaXMzLl9kb25lW2lkZW50aWZpZXIubGlkXS5wdXNoKHJlcXVlc3QpOwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvLnN1YnNjcmliZUZvclJlY29yZCA9IGZ1bmN0aW9uIHN1YnNjcmliZUZvclJlY29yZChpZGVudGlmaWVyLCBjYWxsYmFjaykgewogICAgICBpZiAoIXRoaXMuX3N1YnNjcmlwdGlvbnNbaWRlbnRpZmllci5saWRdKSB7CiAgICAgICAgdGhpcy5fc3Vic2NyaXB0aW9uc1tpZGVudGlmaWVyLmxpZF0gPSBbXTsKICAgICAgfQoKICAgICAgdGhpcy5fc3Vic2NyaXB0aW9uc1tpZGVudGlmaWVyLmxpZF0ucHVzaChjYWxsYmFjayk7CiAgICB9OwoKICAgIF9wcm90by5nZXRQZW5kaW5nUmVxdWVzdHNGb3JSZWNvcmQgPSBmdW5jdGlvbiBnZXRQZW5kaW5nUmVxdWVzdHNGb3JSZWNvcmQoaWRlbnRpZmllcikgewogICAgICBpZiAodGhpcy5fcGVuZGluZ1tpZGVudGlmaWVyLmxpZF0pIHsKICAgICAgICByZXR1cm4gdGhpcy5fcGVuZGluZ1tpZGVudGlmaWVyLmxpZF07CiAgICAgIH0KCiAgICAgIHJldHVybiBbXTsKICAgIH07CgogICAgX3Byb3RvLmdldExhc3RSZXF1ZXN0Rm9yUmVjb3JkID0gZnVuY3Rpb24gZ2V0TGFzdFJlcXVlc3RGb3JSZWNvcmQoaWRlbnRpZmllcikgewogICAgICB2YXIgcmVxdWVzdHMgPSB0aGlzLl9kb25lW2lkZW50aWZpZXIubGlkXTsKCiAgICAgIGlmIChyZXF1ZXN0cykgewogICAgICAgIHJldHVybiByZXF1ZXN0c1tyZXF1ZXN0cy5sZW5ndGggLSAxXTsKICAgICAgfQoKICAgICAgcmV0dXJuIG51bGw7CiAgICB9OwoKICAgIHJldHVybiBSZXF1ZXN0Q2FjaGU7CiAgfSgpOwoKICB2YXIgZW1iZXJSdW4gPSBFbWJlci5ydW4uYmFja2J1cm5lcjsKICB2YXIgU2F2ZU9wID0gc3ltYm9sKCdTYXZlT3AnKTsKCiAgdmFyIEZldGNoTWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIC8vIHNhdmVzIHdoaWNoIGFyZSBwZW5kaW5nIGluIHRoZSBydW5sb29wCiAgICAvLyBmZXRjaGVzIHBlbmRpbmcgaW4gdGhlIHJ1bmxvb3AsIHdhaXRpbmcgdG8gYmUgY29hbGVzY2VkCiAgICBmdW5jdGlvbiBGZXRjaE1hbmFnZXIoX3N0b3JlKSB7CiAgICAgIHRoaXMuX3N0b3JlID0gX3N0b3JlOwogICAgICB0aGlzLmlzRGVzdHJveWVkID0gdm9pZCAwOwogICAgICB0aGlzLnJlcXVlc3RDYWNoZSA9IHZvaWQgMDsKICAgICAgdGhpcy5fcGVuZGluZ1NhdmUgPSB2b2lkIDA7CiAgICAgIHRoaXMuX3BlbmRpbmdGZXRjaCA9IHZvaWQgMDsKICAgICAgLy8gdXNlZCB0byBrZWVwIHRyYWNrIG9mIGFsbCB0aGUgZmluZCByZXF1ZXN0cyB0aGF0IG5lZWQgdG8gYmUgY29hbGVzY2VkCiAgICAgIHRoaXMuX3BlbmRpbmdGZXRjaCA9IG5ldyBNYXAoKTsKICAgICAgdGhpcy5fcGVuZGluZ1NhdmUgPSBbXTsKICAgICAgdGhpcy5yZXF1ZXN0Q2FjaGUgPSBuZXcgUmVxdWVzdENhY2hlKCk7CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIGJ5IGByZWNvcmQuc2F2ZWAsIGFuZCBnZXRzIHBhc3NlZCBhCiAgICAgIHJlc29sdmVyIGZvciB0aGUgcHJvbWlzZSB0aGF0IGByZWNvcmQuc2F2ZWAgcmV0dXJucy4KICAgICAgIEl0IHNjaGVkdWxlcyBzYXZpbmcgdG8gaGFwcGVuIGF0IHRoZSBlbmQgb2YgdGhlIHJ1biBsb29wLgogICAgKi8KCgogICAgdmFyIF9wcm90byA9IEZldGNoTWFuYWdlci5wcm90b3R5cGU7CgogICAgX3Byb3RvLnNjaGVkdWxlU2F2ZSA9IGZ1bmN0aW9uIHNjaGVkdWxlU2F2ZShpZGVudGlmaWVyLCBvcHRpb25zKSB7CiAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsKICAgICAgICBvcHRpb25zID0ge307CiAgICAgIH0KCiAgICAgIHZhciBwcm9taXNlTGFiZWwgPSAnRFM6IE1vZGVsI3NhdmUgJyArIHRoaXM7CiAgICAgIHZhciByZXNvbHZlciA9IEVtYmVyLlJTVlAuZGVmZXIocHJvbWlzZUxhYmVsKTsKICAgICAgdmFyIHF1ZXJ5ID0gewogICAgICAgIG9wOiAnc2F2ZVJlY29yZCcsCiAgICAgICAgcmVjb3JkSWRlbnRpZmllcjogaWRlbnRpZmllciwKICAgICAgICBvcHRpb25zOiBvcHRpb25zCiAgICAgIH07CiAgICAgIHZhciBxdWVyeVJlcXVlc3QgPSB7CiAgICAgICAgZGF0YTogW3F1ZXJ5XQogICAgICB9OwogICAgICB2YXIgc25hcHNob3QgPSBuZXcgU25hcHNob3Qob3B0aW9ucywgaWRlbnRpZmllciwgdGhpcy5fc3RvcmUpOwogICAgICB2YXIgcGVuZGluZ1NhdmVJdGVtID0gewogICAgICAgIHNuYXBzaG90OiBzbmFwc2hvdCwKICAgICAgICByZXNvbHZlcjogcmVzb2x2ZXIsCiAgICAgICAgaWRlbnRpZmllcjogaWRlbnRpZmllciwKICAgICAgICBvcHRpb25zOiBvcHRpb25zLAogICAgICAgIHF1ZXJ5UmVxdWVzdDogcXVlcnlSZXF1ZXN0CiAgICAgIH07CgogICAgICB0aGlzLl9wZW5kaW5nU2F2ZS5wdXNoKHBlbmRpbmdTYXZlSXRlbSk7CgogICAgICBlbWJlclJ1bi5zY2hlZHVsZU9uY2UoJ2FjdGlvbnMnLCB0aGlzLCB0aGlzLl9mbHVzaFBlbmRpbmdTYXZlcyk7CiAgICAgIHRoaXMucmVxdWVzdENhY2hlLmVucXVldWUocmVzb2x2ZXIucHJvbWlzZSwgcGVuZGluZ1NhdmVJdGVtLnF1ZXJ5UmVxdWVzdCk7CiAgICAgIHJldHVybiByZXNvbHZlci5wcm9taXNlOwogICAgfTsKCiAgICBfcHJvdG8uX2ZsdXNoUGVuZGluZ1NhdmUgPSBmdW5jdGlvbiBfZmx1c2hQZW5kaW5nU2F2ZShwZW5kaW5nKSB7CiAgICAgIHZhciBzbmFwc2hvdCA9IHBlbmRpbmcuc25hcHNob3QsCiAgICAgICAgICByZXNvbHZlciA9IHBlbmRpbmcucmVzb2x2ZXIsCiAgICAgICAgICBpZGVudGlmaWVyID0gcGVuZGluZy5pZGVudGlmaWVyLAogICAgICAgICAgb3B0aW9ucyA9IHBlbmRpbmcub3B0aW9uczsKCiAgICAgIHZhciBhZGFwdGVyID0gdGhpcy5fc3RvcmUuYWRhcHRlckZvcihpZGVudGlmaWVyLnR5cGUpOwoKICAgICAgdmFyIG9wZXJhdGlvbiA9IG9wdGlvbnNbU2F2ZU9wXTsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBzbmFwc2hvdC5faW50ZXJuYWxNb2RlbDsKICAgICAgdmFyIG1vZGVsTmFtZSA9IHNuYXBzaG90Lm1vZGVsTmFtZTsKICAgICAgdmFyIHN0b3JlID0gdGhpcy5fc3RvcmU7CiAgICAgIHZhciBtb2RlbENsYXNzID0gc3RvcmUubW9kZWxGb3IobW9kZWxOYW1lKTsKICAgICAgdmFyIHByb21pc2UgPSBFbWJlci5SU1ZQLlByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBhZGFwdGVyW29wZXJhdGlvbl0oc3RvcmUsIG1vZGVsQ2xhc3MsIHNuYXBzaG90KTsKICAgICAgfSk7CiAgICAgIHZhciBzZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcihtb2RlbE5hbWUpOwogICAgICB2YXIgbGFiZWwgPSAiRFM6IEV4dHJhY3QgYW5kIG5vdGlmeSBhYm91dCAiICsgb3BlcmF0aW9uICsgIiBjb21wbGV0aW9uIG9mICIgKyBpbnRlcm5hbE1vZGVsOwogICAgICBwcm9taXNlID0gZ3VhcmREZXN0cm95ZWRTdG9yZShwcm9taXNlLCBzdG9yZSwgbGFiZWwpOwogICAgICBwcm9taXNlID0gX2d1YXJkKHByb21pc2UsIF9iaW5kKF9vYmplY3RJc0FsaXZlLCBpbnRlcm5hbE1vZGVsKSk7CiAgICAgIHByb21pc2UgPSBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKGFkYXB0ZXJQYXlsb2FkKSB7CiAgICAgICAgaWYgKGFkYXB0ZXJQYXlsb2FkKSB7CiAgICAgICAgICByZXR1cm4gbm9ybWFsaXplUmVzcG9uc2VIZWxwZXIoc2VyaWFsaXplciwgc3RvcmUsIG1vZGVsQ2xhc3MsIGFkYXB0ZXJQYXlsb2FkLCBzbmFwc2hvdC5pZCwgb3BlcmF0aW9uKTsKICAgICAgICB9CiAgICAgIH0sIGZ1bmN0aW9uIChlcnJvcikgewogICAgICAgIGlmIChlcnJvciAmJiBlcnJvci5pc0FkYXB0ZXJFcnJvciA9PT0gdHJ1ZSAmJiBlcnJvci5jb2RlID09PSAnSW52YWxpZEVycm9yJykgewogICAgICAgICAgdmFyIHBhcnNlZEVycm9ycyA9IGVycm9yLmVycm9yczsKCiAgICAgICAgICBpZiAodHlwZW9mIHNlcmlhbGl6ZXIuZXh0cmFjdEVycm9ycyA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgICAgICBwYXJzZWRFcnJvcnMgPSBzZXJpYWxpemVyLmV4dHJhY3RFcnJvcnMoc3RvcmUsIG1vZGVsQ2xhc3MsIGVycm9yLCBzbmFwc2hvdC5pZCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBwYXJzZWRFcnJvcnMgPSBlcnJvcnNBcnJheVRvSGFzaChlcnJvci5lcnJvcnMpOwogICAgICAgICAgfQoKICAgICAgICAgIHRocm93IHsKICAgICAgICAgICAgZXJyb3I6IGVycm9yLAogICAgICAgICAgICBwYXJzZWRFcnJvcnM6IHBhcnNlZEVycm9ycwogICAgICAgICAgfTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhyb3cgewogICAgICAgICAgICBlcnJvcjogZXJyb3IKICAgICAgICAgIH07CiAgICAgICAgfQogICAgICB9LCBsYWJlbCk7CiAgICAgIHJlc29sdmVyLnJlc29sdmUocHJvbWlzZSk7CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIGF0IHRoZSBlbmQgb2YgdGhlIHJ1biBsb29wLCBhbmQKICAgICAgZmx1c2hlcyBhbnkgcmVjb3JkcyBwYXNzZWQgaW50byBgc2NoZWR1bGVTYXZlYAogICAgICAgQG1ldGhvZCBmbHVzaFBlbmRpbmdTYXZlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5fZmx1c2hQZW5kaW5nU2F2ZXMgPSBmdW5jdGlvbiBfZmx1c2hQZW5kaW5nU2F2ZXMoKSB7CiAgICAgIHZhciBwZW5kaW5nID0gdGhpcy5fcGVuZGluZ1NhdmUuc2xpY2UoKTsKCiAgICAgIHRoaXMuX3BlbmRpbmdTYXZlID0gW107CgogICAgICBmb3IgKHZhciBpID0gMCwgaiA9IHBlbmRpbmcubGVuZ3RoOyBpIDwgajsgaSsrKSB7CiAgICAgICAgdmFyIHBlbmRpbmdJdGVtID0gcGVuZGluZ1tpXTsKCiAgICAgICAgdGhpcy5fZmx1c2hQZW5kaW5nU2F2ZShwZW5kaW5nSXRlbSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnNjaGVkdWxlRmV0Y2ggPSBmdW5jdGlvbiBzY2hlZHVsZUZldGNoKGlkZW50aWZpZXIsIG9wdGlvbnMsIHNob3VsZFRyYWNlKSB7CiAgICAgIC8vIFRPRE8gUHJvYmFibHkgdGhlIHN0b3JlIHNob3VsZCBwYXNzIGluIHRoZSBxdWVyeSBvYmplY3QKICAgICAgdmFyIHF1ZXJ5ID0gewogICAgICAgIG9wOiAnZmluZFJlY29yZCcsCiAgICAgICAgcmVjb3JkSWRlbnRpZmllcjogaWRlbnRpZmllciwKICAgICAgICBvcHRpb25zOiBvcHRpb25zCiAgICAgIH07CiAgICAgIHZhciBxdWVyeVJlcXVlc3QgPSB7CiAgICAgICAgZGF0YTogW3F1ZXJ5XQogICAgICB9OwoKICAgICAgdmFyIHBlbmRpbmdGZXRjaGVzID0gdGhpcy5fcGVuZGluZ0ZldGNoLmdldChpZGVudGlmaWVyLnR5cGUpOyAvLyBXZSBhbHJlYWR5IGhhdmUgYSBwZW5kaW5nIGZldGNoIGZvciB0aGlzCgoKICAgICAgaWYgKHBlbmRpbmdGZXRjaGVzKSB7CiAgICAgICAgdmFyIG1hdGNoaW5nUGVuZGluZ0ZldGNoID0gcGVuZGluZ0ZldGNoZXMuZmluZChmdW5jdGlvbiAoZmV0Y2gpIHsKICAgICAgICAgIHJldHVybiBmZXRjaC5pZGVudGlmaWVyLmlkID09PSBpZGVudGlmaWVyLmlkOwogICAgICAgIH0pOwoKICAgICAgICBpZiAobWF0Y2hpbmdQZW5kaW5nRmV0Y2gpIHsKICAgICAgICAgIHJldHVybiBtYXRjaGluZ1BlbmRpbmdGZXRjaC5yZXNvbHZlci5wcm9taXNlOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdmFyIGlkID0gaWRlbnRpZmllci5pZDsKICAgICAgdmFyIG1vZGVsTmFtZSA9IGlkZW50aWZpZXIudHlwZTsKICAgICAgdmFyIHJlc29sdmVyID0gRW1iZXIuUlNWUC5kZWZlcigiRmV0Y2hpbmcgIiArIG1vZGVsTmFtZSArICInIHdpdGggaWQ6ICIgKyBpZCk7CiAgICAgIHZhciBwZW5kaW5nRmV0Y2hJdGVtID0gewogICAgICAgIGlkZW50aWZpZXI6IGlkZW50aWZpZXIsCiAgICAgICAgcmVzb2x2ZXI6IHJlc29sdmVyLAogICAgICAgIG9wdGlvbnM6IG9wdGlvbnMsCiAgICAgICAgcXVlcnlSZXF1ZXN0OiBxdWVyeVJlcXVlc3QKICAgICAgfTsKCiAgICAgIHZhciBwcm9taXNlID0gcmVzb2x2ZXIucHJvbWlzZTsKCiAgICAgIGlmICh0aGlzLl9wZW5kaW5nRmV0Y2guc2l6ZSA9PT0gMCkgewogICAgICAgIGVtYmVyUnVuLnNjaGVkdWxlKCdhY3Rpb25zJywgdGhpcywgdGhpcy5mbHVzaEFsbFBlbmRpbmdGZXRjaGVzKTsKICAgICAgfQoKICAgICAgdmFyIGZldGNoZXMgPSB0aGlzLl9wZW5kaW5nRmV0Y2g7CgogICAgICBpZiAoIWZldGNoZXMuaGFzKG1vZGVsTmFtZSkpIHsKICAgICAgICBmZXRjaGVzLnNldChtb2RlbE5hbWUsIFtdKTsKICAgICAgfQoKICAgICAgZmV0Y2hlcy5nZXQobW9kZWxOYW1lKS5wdXNoKHBlbmRpbmdGZXRjaEl0ZW0pOwogICAgICB0aGlzLnJlcXVlc3RDYWNoZS5lbnF1ZXVlKHByb21pc2UsIHBlbmRpbmdGZXRjaEl0ZW0ucXVlcnlSZXF1ZXN0KTsKICAgICAgcmV0dXJuIHByb21pc2U7CiAgICB9OwoKICAgIF9wcm90by5fZmV0Y2hSZWNvcmQgPSBmdW5jdGlvbiBfZmV0Y2hSZWNvcmQoZmV0Y2hJdGVtKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICB2YXIgaWRlbnRpZmllciA9IGZldGNoSXRlbS5pZGVudGlmaWVyOwogICAgICB2YXIgbW9kZWxOYW1lID0gaWRlbnRpZmllci50eXBlOwoKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLl9zdG9yZS5hZGFwdGVyRm9yKG1vZGVsTmFtZSk7CiAgICAgIHZhciBzbmFwc2hvdCA9IG5ldyBTbmFwc2hvdChmZXRjaEl0ZW0ub3B0aW9ucywgaWRlbnRpZmllciwgdGhpcy5fc3RvcmUpOwoKICAgICAgdmFyIGtsYXNzID0gdGhpcy5fc3RvcmUubW9kZWxGb3IoaWRlbnRpZmllci50eXBlKTsKCiAgICAgIHZhciBwcm9taXNlID0gRW1iZXIuUlNWUC5Qcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gYWRhcHRlci5maW5kUmVjb3JkKF90aGlzLl9zdG9yZSwga2xhc3MsIGlkZW50aWZpZXIuaWQsIHNuYXBzaG90KTsKICAgICAgfSk7CiAgICAgIHZhciBpZCA9IGlkZW50aWZpZXIuaWQ7CiAgICAgIHZhciBsYWJlbCA9ICJEUzogSGFuZGxlIEFkYXB0ZXIjZmluZFJlY29yZCBvZiAnIiArIG1vZGVsTmFtZSArICInIHdpdGggaWQ6ICciICsgaWQgKyAiJyI7CiAgICAgIHByb21pc2UgPSBndWFyZERlc3Ryb3llZFN0b3JlKHByb21pc2UsIHRoaXMuX3N0b3JlLCBsYWJlbCk7CiAgICAgIHByb21pc2UgPSBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKGFkYXB0ZXJQYXlsb2FkKSB7CgogICAgICAgIHZhciBzZXJpYWxpemVyID0gX3RoaXMuX3N0b3JlLnNlcmlhbGl6ZXJGb3IobW9kZWxOYW1lKTsKCiAgICAgICAgdmFyIHBheWxvYWQgPSBub3JtYWxpemVSZXNwb25zZUhlbHBlcihzZXJpYWxpemVyLCBfdGhpcy5fc3RvcmUsIGtsYXNzLCBhZGFwdGVyUGF5bG9hZCwgaWQsICdmaW5kUmVjb3JkJyk7CiAgICAgICAgcmV0dXJuIHBheWxvYWQ7CiAgICAgIH0sIGZ1bmN0aW9uIChlcnJvcikgewogICAgICAgIHRocm93IGVycm9yOwogICAgICB9LCAiRFM6IEV4dHJhY3QgcGF5bG9hZCBvZiAnIiArIG1vZGVsTmFtZSArICInIik7CiAgICAgIGZldGNoSXRlbS5yZXNvbHZlci5yZXNvbHZlKHByb21pc2UpOwogICAgfSAvLyBUT0RPIHNob3VsZCBwcm9iYWJseSByZWZhY3RvciBleHBlY3RlZFNuYXBzaG90cyB0byBiZSBpZGVudGlmaWVycwogICAgOwoKICAgIF9wcm90by5oYW5kbGVGb3VuZFJlY29yZHMgPSBmdW5jdGlvbiBoYW5kbGVGb3VuZFJlY29yZHMoc2Vla2luZywgY29hbGVzY2VkUGF5bG9hZCwgZXhwZWN0ZWRTbmFwc2hvdHMpIHsKICAgICAgLy8gcmVzb2x2ZSBmb3VuZCByZWNvcmRzCiAgICAgIHZhciBmb3VuZCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHZhciBwYXlsb2FkcyA9IGNvYWxlc2NlZFBheWxvYWQuZGF0YTsKICAgICAgdmFyIGNvYWxlc2NlZEluY2x1ZGVkID0gY29hbGVzY2VkUGF5bG9hZC5pbmNsdWRlZCB8fCBbXTsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gcGF5bG9hZHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgdmFyIHBheWxvYWQgPSBwYXlsb2Fkc1tpXTsKICAgICAgICB2YXIgcGFpciA9IHNlZWtpbmdbcGF5bG9hZC5pZF07CiAgICAgICAgZm91bmRbcGF5bG9hZC5pZF0gPSBwYXlsb2FkOwogICAgICAgIHZhciBpbmNsdWRlZCA9IGNvYWxlc2NlZEluY2x1ZGVkLmNvbmNhdChwYXlsb2Fkcyk7IC8vIFRPRE8gcmVtb3ZlIG9yaWdpbmFsIGRhdGEgZnJvbSBpbmNsdWRlZAoKICAgICAgICBpZiAocGFpcikgewogICAgICAgICAgdmFyIHJlc29sdmVyID0gcGFpci5yZXNvbHZlcjsKICAgICAgICAgIHJlc29sdmVyLnJlc29sdmUoewogICAgICAgICAgICBkYXRhOiBwYXlsb2FkLAogICAgICAgICAgICBpbmNsdWRlZDogaW5jbHVkZWQKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSAvLyByZWplY3QgbWlzc2luZyByZWNvcmRzCiAgICAgIC8vIFRPRE8gTk9XIGNsZWFuIHRoaXMgdXAgdG8gcmVmZXIgdG8gcGF5bG9hZHMKCgogICAgICB2YXIgbWlzc2luZ1NuYXBzaG90cyA9IFtdOwoKICAgICAgZm9yICh2YXIgX2kgPSAwLCBfbCA9IGV4cGVjdGVkU25hcHNob3RzLmxlbmd0aDsgX2kgPCBfbDsgX2krKykgewogICAgICAgIHZhciBzbmFwc2hvdCA9IGV4cGVjdGVkU25hcHNob3RzW19pXTsKCiAgICAgICAgaWYgKCFmb3VuZFtzbmFwc2hvdC5pZF0pIHsKICAgICAgICAgIG1pc3NpbmdTbmFwc2hvdHMucHVzaChzbmFwc2hvdCk7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAobWlzc2luZ1NuYXBzaG90cy5sZW5ndGgpIHsKICAgICAgICB0aGlzLnJlamVjdEZldGNoZWRJdGVtcyhzZWVraW5nLCBtaXNzaW5nU25hcHNob3RzKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ucmVqZWN0RmV0Y2hlZEl0ZW1zID0gZnVuY3Rpb24gcmVqZWN0RmV0Y2hlZEl0ZW1zKHNlZWtpbmcsIHNuYXBzaG90cywgZXJyb3IpIHsKICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBzbmFwc2hvdHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgdmFyIGlkZW50aWZpZXIgPSBzbmFwc2hvdHNbaV07CiAgICAgICAgdmFyIHBhaXIgPSBzZWVraW5nW2lkZW50aWZpZXIuaWRdOwoKICAgICAgICBpZiAocGFpcikgewogICAgICAgICAgcGFpci5yZXNvbHZlci5yZWplY3QoZXJyb3IgfHwgbmV3IEVycm9yKCJFeHBlY3RlZDogJzwiICsgaWRlbnRpZmllci5tb2RlbE5hbWUgKyAiOiIgKyBpZGVudGlmaWVyLmlkICsgIj4nIHRvIGJlIHByZXNlbnQgaW4gdGhlIGFkYXB0ZXIgcHJvdmlkZWQgcGF5bG9hZCwgYnV0IGl0IHdhcyBub3QgZm91bmQuIikpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRNYW55ID0gZnVuY3Rpb24gX2ZpbmRNYW55KGFkYXB0ZXIsIHN0b3JlLCBtb2RlbE5hbWUsIHNuYXBzaG90cywgaWRlbnRpZmllcnMsIG9wdGlvbnNNYXApIHsKICAgICAgdmFyIG1vZGVsQ2xhc3MgPSBzdG9yZS5tb2RlbEZvcihtb2RlbE5hbWUpOyAvLyBgYWRhcHRlci5maW5kTWFueWAgZ2V0cyB0aGUgbW9kZWxDbGFzcyBzdGlsbAoKICAgICAgdmFyIGlkcyA9IHNuYXBzaG90cy5tYXAoZnVuY3Rpb24gKHMpIHsKICAgICAgICByZXR1cm4gcy5pZDsKICAgICAgfSk7CiAgICAgIHZhciBwcm9taXNlID0gYWRhcHRlci5maW5kTWFueShzdG9yZSwgbW9kZWxDbGFzcywgaWRzLCBFbWJlci5BKHNuYXBzaG90cykpOwogICAgICB2YXIgbGFiZWwgPSAiRFM6IEhhbmRsZSBBZGFwdGVyI2ZpbmRNYW55IG9mICciICsgbW9kZWxOYW1lICsgIiciOwoKICAgICAgaWYgKHByb21pc2UgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcignYWRhcHRlci5maW5kTWFueSByZXR1cm5lZCB1bmRlZmluZWQsIHRoaXMgd2FzIHZlcnkgbGlrZWx5IGEgbWlzdGFrZScpOwogICAgICB9CgogICAgICBwcm9taXNlID0gZ3VhcmREZXN0cm95ZWRTdG9yZShwcm9taXNlLCBzdG9yZSwgbGFiZWwpOwogICAgICByZXR1cm4gcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChhZGFwdGVyUGF5bG9hZCkgewogICAgICAgIHZhciBzZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcihtb2RlbE5hbWUpOwogICAgICAgIHZhciBwYXlsb2FkID0gbm9ybWFsaXplUmVzcG9uc2VIZWxwZXIoc2VyaWFsaXplciwgc3RvcmUsIG1vZGVsQ2xhc3MsIGFkYXB0ZXJQYXlsb2FkLCBudWxsLCAnZmluZE1hbnknKTsKICAgICAgICByZXR1cm4gcGF5bG9hZDsKICAgICAgfSwgbnVsbCwgIkRTOiBFeHRyYWN0IHBheWxvYWQgb2YgIiArIG1vZGVsTmFtZSk7CiAgICB9OwoKICAgIF9wcm90by5fcHJvY2Vzc0NvYWxlc2NlZEdyb3VwID0gZnVuY3Rpb24gX3Byb2Nlc3NDb2FsZXNjZWRHcm91cChzZWVraW5nLCBncm91cCwgYWRhcHRlciwgb3B0aW9uc01hcCwgbW9kZWxOYW1lKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgLy9UT0RPIGNoZWNrIHdoYXQgaGFwcGVuZWQgd2l0aCBpZGVudGlmaWVycyBoZXJlCiAgICAgIHZhciB0b3RhbEluR3JvdXAgPSBncm91cC5sZW5ndGg7CiAgICAgIHZhciBpZHMgPSBuZXcgQXJyYXkodG90YWxJbkdyb3VwKTsKICAgICAgdmFyIGdyb3VwZWRTbmFwc2hvdHMgPSBuZXcgQXJyYXkodG90YWxJbkdyb3VwKTsKCiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdG90YWxJbkdyb3VwOyBqKyspIHsKICAgICAgICBncm91cGVkU25hcHNob3RzW2pdID0gZ3JvdXBbal07CiAgICAgICAgaWRzW2pdID0gZ3JvdXBlZFNuYXBzaG90c1tqXS5pZDsKICAgICAgfQoKICAgICAgdmFyIHN0b3JlID0gdGhpcy5fc3RvcmU7CgogICAgICBpZiAodG90YWxJbkdyb3VwID4gMSkgewogICAgICAgIHRoaXMuX2ZpbmRNYW55KGFkYXB0ZXIsIHN0b3JlLCBtb2RlbE5hbWUsIGdyb3VwLCBncm91cGVkU25hcHNob3RzLCBvcHRpb25zTWFwKS50aGVuKGZ1bmN0aW9uIChwYXlsb2FkcykgewogICAgICAgICAgX3RoaXMyLmhhbmRsZUZvdW5kUmVjb3JkcyhzZWVraW5nLCBwYXlsb2FkcywgZ3JvdXBlZFNuYXBzaG90cyk7CiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7CiAgICAgICAgICBfdGhpczIucmVqZWN0RmV0Y2hlZEl0ZW1zKHNlZWtpbmcsIGdyb3VwZWRTbmFwc2hvdHMsIGVycm9yKTsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIGlmIChpZHMubGVuZ3RoID09PSAxKSB7CiAgICAgICAgdmFyIHBhaXIgPSBzZWVraW5nW2dyb3VwZWRTbmFwc2hvdHNbMF0uaWRdOwoKICAgICAgICB0aGlzLl9mZXRjaFJlY29yZChwYWlyKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2ZsdXNoUGVuZGluZ0ZldGNoRm9yVHlwZSA9IGZ1bmN0aW9uIF9mbHVzaFBlbmRpbmdGZXRjaEZvclR5cGUocGVuZGluZ0ZldGNoSXRlbXMsIG1vZGVsTmFtZSkgewogICAgICB2YXIgYWRhcHRlciA9IHRoaXMuX3N0b3JlLmFkYXB0ZXJGb3IobW9kZWxOYW1lKTsKCiAgICAgIHZhciBzaG91bGRDb2FsZXNjZSA9ICEhYWRhcHRlci5maW5kTWFueSAmJiBhZGFwdGVyLmNvYWxlc2NlRmluZFJlcXVlc3RzOwogICAgICB2YXIgdG90YWxJdGVtcyA9IHBlbmRpbmdGZXRjaEl0ZW1zLmxlbmd0aDsKICAgICAgdmFyIGlkZW50aWZpZXJzID0gbmV3IEFycmF5KHRvdGFsSXRlbXMpOwogICAgICB2YXIgc2Vla2luZyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHZhciBvcHRpb25zTWFwID0gbmV3IFdlYWtNYXAoKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdG90YWxJdGVtczsgaSsrKSB7CiAgICAgICAgdmFyIHBlbmRpbmdJdGVtID0gcGVuZGluZ0ZldGNoSXRlbXNbaV07CiAgICAgICAgdmFyIGlkZW50aWZpZXIgPSBwZW5kaW5nSXRlbS5pZGVudGlmaWVyOwogICAgICAgIGlkZW50aWZpZXJzW2ldID0gaWRlbnRpZmllcjsKICAgICAgICBvcHRpb25zTWFwLnNldChpZGVudGlmaWVyLCBwZW5kaW5nSXRlbS5vcHRpb25zKTsKICAgICAgICBzZWVraW5nW2lkZW50aWZpZXIuaWRdID0gcGVuZGluZ0l0ZW07CiAgICAgIH0KCiAgICAgIGlmIChzaG91bGRDb2FsZXNjZSkgewogICAgICAgIC8vIFRPRE86IEltcHJvdmUgcmVjb3JkcyA9PiBzbmFwc2hvdHMgPT4gcmVjb3JkcyA9PiBzbmFwc2hvdHMKICAgICAgICAvLwogICAgICAgIC8vIFdlIHdhbnQgdG8gcHJvdmlkZSByZWNvcmRzIHRvIGFsbCBzdG9yZSBtZXRob2RzIGFuZCBzbmFwc2hvdHMgdG8gYWxsCiAgICAgICAgLy8gYWRhcHRlciBtZXRob2RzLiBUbyBtYWtlIHN1cmUgd2UncmUgZG9pbmcgdGhhdCB3ZSdyZSBwcm92aWRpbmcgYW4gYXJyYXkKICAgICAgICAvLyBvZiBzbmFwc2hvdHMgdG8gYWRhcHRlci5ncm91cFJlY29yZHNGb3JGaW5kTWFueSgpLCB3aGljaCBpbiB0dXJuIHdpbGwKICAgICAgICAvLyByZXR1cm4gZ3JvdXBlZCBzbmFwc2hvdHMgaW5zdGVhZCBvZiBncm91cGVkIHJlY29yZHMuCiAgICAgICAgLy8KICAgICAgICAvLyBCdXQgc2luY2UgdGhlIF9maW5kTWFueSgpIGZpbmRlciBpcyBhIHN0b3JlIG1ldGhvZCB3ZSBuZWVkIHRvIGdldCB0aGUKICAgICAgICAvLyByZWNvcmRzIGZyb20gdGhlIGdyb3VwZWQgc25hcHNob3RzIGV2ZW4gdGhvdWdoIHRoZSBfZmluZE1hbnkoKSBmaW5kZXIKICAgICAgICAvLyB3aWxsIG9uY2UgYWdhaW4gY29udmVydCB0aGUgcmVjb3JkcyB0byBzbmFwc2hvdHMgZm9yIGFkYXB0ZXIuZmluZE1hbnkoKQogICAgICAgIHZhciBzbmFwc2hvdHMgPSBuZXcgQXJyYXkodG90YWxJdGVtcyk7CgogICAgICAgIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IHRvdGFsSXRlbXM7IF9pMisrKSB7CiAgICAgICAgICB2YXIgb3B0aW9ucyA9IG9wdGlvbnNNYXAuZ2V0KGlkZW50aWZpZXJzW19pMl0pOwogICAgICAgICAgc25hcHNob3RzW19pMl0gPSBuZXcgU25hcHNob3Qob3B0aW9ucywgaWRlbnRpZmllcnNbX2kyXSwgdGhpcy5fc3RvcmUpOwogICAgICAgIH0KCiAgICAgICAgdmFyIGdyb3VwcyA9IGFkYXB0ZXIuZ3JvdXBSZWNvcmRzRm9yRmluZE1hbnkodGhpcywgc25hcHNob3RzKTsKCiAgICAgICAgZm9yICh2YXIgX2kzID0gMCwgbCA9IGdyb3Vwcy5sZW5ndGg7IF9pMyA8IGw7IF9pMysrKSB7CiAgICAgICAgICB0aGlzLl9wcm9jZXNzQ29hbGVzY2VkR3JvdXAoc2Vla2luZywgZ3JvdXBzW19pM10sIGFkYXB0ZXIsIG9wdGlvbnNNYXAsIG1vZGVsTmFtZSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGZvciAodmFyIF9pNCA9IDA7IF9pNCA8IHRvdGFsSXRlbXM7IF9pNCsrKSB7CiAgICAgICAgICB0aGlzLl9mZXRjaFJlY29yZChwZW5kaW5nRmV0Y2hJdGVtc1tfaTRdKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmZsdXNoQWxsUGVuZGluZ0ZldGNoZXMgPSBmdW5jdGlvbiBmbHVzaEFsbFBlbmRpbmdGZXRjaGVzKCkgewogICAgICBpZiAodGhpcy5pc0Rlc3Ryb3llZCkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5fcGVuZGluZ0ZldGNoLmZvckVhY2godGhpcy5fZmx1c2hQZW5kaW5nRmV0Y2hGb3JUeXBlLCB0aGlzKTsKCiAgICAgIHRoaXMuX3BlbmRpbmdGZXRjaC5jbGVhcigpOwogICAgfTsKCiAgICBfcHJvdG8uZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHRoaXMuaXNEZXN0cm95ZWQgPSB0cnVlOwogICAgfTsKCiAgICByZXR1cm4gRmV0Y2hNYW5hZ2VyOwogIH0oKTsKCiAgZnVuY3Rpb24gX2ZpbmQoYWRhcHRlciwgc3RvcmUsIG1vZGVsQ2xhc3MsIGlkLCBpbnRlcm5hbE1vZGVsLCBvcHRpb25zKSB7CgogICAgdmFyIHNuYXBzaG90ID0gaW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdChvcHRpb25zKTsKICAgIHZhciBtb2RlbE5hbWUgPSBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZTsKICAgIHZhciBwcm9taXNlID0gRW1iZXIuUlNWUC5Qcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIGFkYXB0ZXIuZmluZFJlY29yZChzdG9yZSwgbW9kZWxDbGFzcywgaWQsIHNuYXBzaG90KTsKICAgIH0pOwogICAgdmFyIGxhYmVsID0gIkRTOiBIYW5kbGUgQWRhcHRlciNmaW5kUmVjb3JkIG9mICciICsgbW9kZWxOYW1lICsgIicgd2l0aCBpZDogJyIgKyBpZCArICInIjsKICAgIHZhciBpZGVudGlmaWVyID0gaW50ZXJuYWxNb2RlbC5pZGVudGlmaWVyOwogICAgcHJvbWlzZSA9IGd1YXJkRGVzdHJveWVkU3RvcmUocHJvbWlzZSwgc3RvcmUsIGxhYmVsKTsKICAgIHJldHVybiBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKGFkYXB0ZXJQYXlsb2FkKSB7CiAgICAgIHZhciBzZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcihtb2RlbE5hbWUpOwogICAgICB2YXIgcGF5bG9hZCA9IG5vcm1hbGl6ZVJlc3BvbnNlSGVscGVyKHNlcmlhbGl6ZXIsIHN0b3JlLCBtb2RlbENsYXNzLCBhZGFwdGVyUGF5bG9hZCwgaWQsICdmaW5kUmVjb3JkJyk7CgogICAgICB7CiAgICAgICAgLy8gZW5zdXJlIHRoYXQgcmVnYXJkbGVzcyBvZiBpZCByZXR1cm5lZCB3ZSBhc3NpZ24gdG8gdGhlIGNvcnJlY3QgcmVjb3JkCiAgICAgICAgcGF5bG9hZC5kYXRhLmxpZCA9IGlkZW50aWZpZXIubGlkOwogICAgICB9CgogICAgICByZXR1cm4gc3RvcmUuX3B1c2gocGF5bG9hZCk7CiAgICB9LCBmdW5jdGlvbiAoZXJyb3IpIHsKICAgICAgaW50ZXJuYWxNb2RlbC5ub3RGb3VuZCgpOwoKICAgICAgaWYgKGludGVybmFsTW9kZWwuaXNFbXB0eSgpKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC51bmxvYWRSZWNvcmQoKTsKICAgICAgfQoKICAgICAgdGhyb3cgZXJyb3I7CiAgICB9LCAiRFM6IEV4dHJhY3QgcGF5bG9hZCBvZiAnIiArIG1vZGVsTmFtZSArICInIik7CiAgfQogIGZ1bmN0aW9uIF9maW5kTWFueShhZGFwdGVyLCBzdG9yZSwgbW9kZWxOYW1lLCBpZHMsIGludGVybmFsTW9kZWxzLCBvcHRpb25zTWFwKSB7CiAgICB2YXIgc25hcHNob3RzID0gRW1iZXIuQShpbnRlcm5hbE1vZGVscy5tYXAoZnVuY3Rpb24gKGludGVybmFsTW9kZWwpIHsKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwuY3JlYXRlU25hcHNob3Qob3B0aW9uc01hcC5nZXQoaW50ZXJuYWxNb2RlbCkpOwogICAgfSkpOwogICAgdmFyIG1vZGVsQ2xhc3MgPSBzdG9yZS5tb2RlbEZvcihtb2RlbE5hbWUpOyAvLyBgYWRhcHRlci5maW5kTWFueWAgZ2V0cyB0aGUgbW9kZWxDbGFzcyBzdGlsbAoKICAgIHZhciBwcm9taXNlID0gYWRhcHRlci5maW5kTWFueShzdG9yZSwgbW9kZWxDbGFzcywgaWRzLCBzbmFwc2hvdHMpOwogICAgdmFyIGxhYmVsID0gIkRTOiBIYW5kbGUgQWRhcHRlciNmaW5kTWFueSBvZiAnIiArIG1vZGVsTmFtZSArICInIjsKCiAgICBpZiAocHJvbWlzZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignYWRhcHRlci5maW5kTWFueSByZXR1cm5lZCB1bmRlZmluZWQsIHRoaXMgd2FzIHZlcnkgbGlrZWx5IGEgbWlzdGFrZScpOwogICAgfQoKICAgIHByb21pc2UgPSBndWFyZERlc3Ryb3llZFN0b3JlKHByb21pc2UsIHN0b3JlLCBsYWJlbCk7CiAgICByZXR1cm4gcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChhZGFwdGVyUGF5bG9hZCkgewogICAgICB2YXIgc2VyaWFsaXplciA9IHN0b3JlLnNlcmlhbGl6ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgdmFyIHBheWxvYWQgPSBub3JtYWxpemVSZXNwb25zZUhlbHBlcihzZXJpYWxpemVyLCBzdG9yZSwgbW9kZWxDbGFzcywgYWRhcHRlclBheWxvYWQsIG51bGwsICdmaW5kTWFueScpOwogICAgICByZXR1cm4gc3RvcmUuX3B1c2gocGF5bG9hZCk7CiAgICB9LCBudWxsLCAiRFM6IEV4dHJhY3QgcGF5bG9hZCBvZiAiICsgbW9kZWxOYW1lKTsKICB9CgogIGZ1bmN0aW9uIGl0ZXJhdGVEYXRhKGRhdGEsIGZuKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkgewogICAgICByZXR1cm4gZGF0YS5tYXAoZm4pOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIGZuKGRhdGEpOwogICAgfQogIH0gLy8gc3luYwogIC8vIGl0ZXJhdGUgb3ZlciByZWNvcmRzIGluIHBheWxvYWQuZGF0YQogIC8vIGZvciBlYWNoIHJlY29yZAogIC8vICAgYXNzZXJ0IHRoYXQgcmVjb3JkLnJlbGF0aW9uc2hpcHNbaW52ZXJzZV0gaXMgZWl0aGVyIHVuZGVmaW5lZCAoc28gd2UgY2FuIGZpeCBpdCkKICAvLyAgICAgb3IgcHJvdmlkZSBhIGRhdGE6IHtpZCwgdHlwZX0gdGhhdCBtYXRjaGVzIHRoZSByZWNvcmQgdGhhdCByZXF1ZXN0ZWQgaXQKICAvLyAgIHJldHVybiB0aGUgcmVsYXRpb25zaGlwIGRhdGEgZm9yIHRoZSBwYXJlbnQKCgogIGZ1bmN0aW9uIHN5bmNSZWxhdGlvbnNoaXBEYXRhRnJvbUxpbmsoc3RvcmUsIHBheWxvYWQsIHBhcmVudEludGVybmFsTW9kZWwsIHJlbGF0aW9uc2hpcCkgewogICAgdmFyIF9yZWxhdGlvbnNoaXBzOwoKICAgIC8vIGVuc3VyZSB0aGUgcmlnaHQgaGFuZCBzaWRlIChpbmNvbWluZyBwYXlsb2FkKSBwb2ludHMgdG8gdGhlIHBhcmVudCByZWNvcmQgdGhhdAogICAgLy8gcmVxdWVzdGVkIHRoaXMgcmVsYXRpb25zaGlwCiAgICB2YXIgcmVsYXRpb25zaGlwRGF0YSA9IGl0ZXJhdGVEYXRhKHBheWxvYWQuZGF0YSwgZnVuY3Rpb24gKGRhdGEsIGluZGV4KSB7CiAgICAgIHZhciBpZCA9IGRhdGEuaWQsCiAgICAgICAgICB0eXBlID0gZGF0YS50eXBlOwogICAgICBlbnN1cmVSZWxhdGlvbnNoaXBJc1NldFRvUGFyZW50KGRhdGEsIHBhcmVudEludGVybmFsTW9kZWwsIHN0b3JlLCByZWxhdGlvbnNoaXApOwogICAgICByZXR1cm4gewogICAgICAgIGlkOiBpZCwKICAgICAgICB0eXBlOiB0eXBlCiAgICAgIH07CiAgICB9KTsgLy8gbm93LCBwdXNoIHRoZSBsZWZ0IGhhbmQgc2lkZSAodGhlIHBhcmVudCByZWNvcmQpIHRvIGVuc3VyZSB0aGluZ3MgYXJlIGluIHN5bmMsIHNpbmNlCiAgICAvLyB0aGUgcGF5bG9hZCB3aWxsIGJlIHB1c2hlZCB3aXRoIHN0b3JlLl9wdXNoCgogICAgc3RvcmUucHVzaCh7CiAgICAgIGRhdGE6IHsKICAgICAgICBpZDogcGFyZW50SW50ZXJuYWxNb2RlbC5pZCwKICAgICAgICB0eXBlOiBwYXJlbnRJbnRlcm5hbE1vZGVsLm1vZGVsTmFtZSwKICAgICAgICByZWxhdGlvbnNoaXBzOiAoX3JlbGF0aW9uc2hpcHMgPSB7fSwgX3JlbGF0aW9uc2hpcHNbcmVsYXRpb25zaGlwLmtleV0gPSB7CiAgICAgICAgICBkYXRhOiByZWxhdGlvbnNoaXBEYXRhCiAgICAgICAgfSwgX3JlbGF0aW9uc2hpcHMpCiAgICAgIH0KICAgIH0pOwogIH0KCiAgZnVuY3Rpb24gZW5zdXJlUmVsYXRpb25zaGlwSXNTZXRUb1BhcmVudChwYXlsb2FkLCBwYXJlbnRJbnRlcm5hbE1vZGVsLCBzdG9yZSwgcGFyZW50UmVsYXRpb25zaGlwLCBpbmRleCkgewogICAgdmFyIGlkID0gcGF5bG9hZC5pZCwKICAgICAgICB0eXBlID0gcGF5bG9hZC50eXBlOwoKICAgIGlmICghcGF5bG9hZC5yZWxhdGlvbnNoaXBzKSB7CiAgICAgIHBheWxvYWQucmVsYXRpb25zaGlwcyA9IHt9OwogICAgfQoKICAgIHZhciByZWxhdGlvbnNoaXBzID0gcGF5bG9hZC5yZWxhdGlvbnNoaXBzOwogICAgdmFyIGludmVyc2UgPSBnZXRJbnZlcnNlKHN0b3JlLCBwYXJlbnRJbnRlcm5hbE1vZGVsLCBwYXJlbnRSZWxhdGlvbnNoaXAsIHR5cGUpOwoKICAgIGlmIChpbnZlcnNlKSB7CiAgICAgIHZhciBpbnZlcnNlS2V5ID0gaW52ZXJzZS5pbnZlcnNlS2V5LAogICAgICAgICAga2luZCA9IGludmVyc2Uua2luZDsKICAgICAgdmFyIHJlbGF0aW9uc2hpcERhdGEgPSByZWxhdGlvbnNoaXBzW2ludmVyc2VLZXldICYmIHJlbGF0aW9uc2hpcHNbaW52ZXJzZUtleV0uZGF0YTsKCiAgICAgIGlmIChraW5kICE9PSAnaGFzTWFueScgfHwgdHlwZW9mIHJlbGF0aW9uc2hpcERhdGEgIT09ICd1bmRlZmluZWQnKSB7CiAgICAgICAgcmVsYXRpb25zaGlwc1tpbnZlcnNlS2V5XSA9IHJlbGF0aW9uc2hpcHNbaW52ZXJzZUtleV0gfHwge307CiAgICAgICAgcmVsYXRpb25zaGlwc1tpbnZlcnNlS2V5XS5kYXRhID0gZml4UmVsYXRpb25zaGlwRGF0YShyZWxhdGlvbnNoaXBEYXRhLCBraW5kLCBwYXJlbnRJbnRlcm5hbE1vZGVsKTsKICAgICAgfQogICAgfQogIH0KCiAgZnVuY3Rpb24gZ2V0SW52ZXJzZShzdG9yZSwgcGFyZW50SW50ZXJuYWxNb2RlbCwgcGFyZW50UmVsYXRpb25zaGlwLCB0eXBlKSB7CiAgICByZXR1cm4gcmVjb3JkRGF0YUZpbmRJbnZlcnNlUmVsYXRpb25zaGlwSW5mbyhzdG9yZSwgcGFyZW50SW50ZXJuYWxNb2RlbCwgcGFyZW50UmVsYXRpb25zaGlwLCB0eXBlKTsKICB9CgogIGZ1bmN0aW9uIHJlY29yZERhdGFGaW5kSW52ZXJzZVJlbGF0aW9uc2hpcEluZm8oX3JlZiwgcGFyZW50SW50ZXJuYWxNb2RlbCwgcGFyZW50UmVsYXRpb25zaGlwLCB0eXBlKSB7CiAgICB2YXIgX3N0b3JlV3JhcHBlciA9IF9yZWYuX3N0b3JlV3JhcHBlcjsKICAgIHZhciBsaHNfcmVsYXRpb25zaGlwTmFtZSA9IHBhcmVudFJlbGF0aW9uc2hpcC5uYW1lOwogICAgdmFyIG1vZGVsTmFtZSA9IHBhcmVudEludGVybmFsTW9kZWwubW9kZWxOYW1lOwoKICAgIHZhciBpbnZlcnNlS2V5ID0gX3N0b3JlV3JhcHBlci5pbnZlcnNlRm9yUmVsYXRpb25zaGlwKG1vZGVsTmFtZSwgbGhzX3JlbGF0aW9uc2hpcE5hbWUpOwoKICAgIGlmIChpbnZlcnNlS2V5KSB7CiAgICAgIHZhciBraW5kID0gX3N0b3JlV3JhcHBlci5yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcih0eXBlKVtpbnZlcnNlS2V5XS5tZXRhLmtpbmQ7CgogICAgICByZXR1cm4gewogICAgICAgIGludmVyc2VLZXk6IGludmVyc2VLZXksCiAgICAgICAga2luZDoga2luZAogICAgICB9OwogICAgfQogIH0KCiAgZnVuY3Rpb24gZml4UmVsYXRpb25zaGlwRGF0YShyZWxhdGlvbnNoaXBEYXRhLCByZWxhdGlvbnNoaXBLaW5kLCBfcmVmMikgewogICAgdmFyIGlkID0gX3JlZjIuaWQsCiAgICAgICAgbW9kZWxOYW1lID0gX3JlZjIubW9kZWxOYW1lOwogICAgdmFyIHBhcmVudFJlbGF0aW9uc2hpcERhdGEgPSB7CiAgICAgIGlkOiBpZCwKICAgICAgdHlwZTogbW9kZWxOYW1lCiAgICB9OwogICAgdmFyIHBheWxvYWQ7CgogICAgaWYgKHJlbGF0aW9uc2hpcEtpbmQgPT09ICdoYXNNYW55JykgewogICAgICBwYXlsb2FkID0gcmVsYXRpb25zaGlwRGF0YSB8fCBbXTsKICAgICAgcGF5bG9hZC5wdXNoKHBhcmVudFJlbGF0aW9uc2hpcERhdGEpOwogICAgfSBlbHNlIHsKICAgICAgcGF5bG9hZCA9IHJlbGF0aW9uc2hpcERhdGEgfHwge307CiAgICAgIEVtYmVyLmFzc2lnbihwYXlsb2FkLCBwYXJlbnRSZWxhdGlvbnNoaXBEYXRhKTsKICAgIH0KCiAgICByZXR1cm4gcGF5bG9hZDsKICB9CgogIGZ1bmN0aW9uIF9maW5kSGFzTWFueShhZGFwdGVyLCBzdG9yZSwgaW50ZXJuYWxNb2RlbCwgbGluaywgcmVsYXRpb25zaGlwLCBvcHRpb25zKSB7CiAgICB2YXIgc25hcHNob3QgPSBpbnRlcm5hbE1vZGVsLmNyZWF0ZVNuYXBzaG90KG9wdGlvbnMpOwogICAgdmFyIG1vZGVsQ2xhc3MgPSBzdG9yZS5tb2RlbEZvcihyZWxhdGlvbnNoaXAudHlwZSk7CiAgICB2YXIgcHJvbWlzZSA9IGFkYXB0ZXIuZmluZEhhc01hbnkoc3RvcmUsIHNuYXBzaG90LCBsaW5rLCByZWxhdGlvbnNoaXApOwogICAgdmFyIGxhYmVsID0gIkRTOiBIYW5kbGUgQWRhcHRlciNmaW5kSGFzTWFueSBvZiAnIiArIGludGVybmFsTW9kZWwubW9kZWxOYW1lICsgIicgOiAnIiArIHJlbGF0aW9uc2hpcC50eXBlICsgIiciOwogICAgcHJvbWlzZSA9IGd1YXJkRGVzdHJveWVkU3RvcmUocHJvbWlzZSwgc3RvcmUsIGxhYmVsKTsKICAgIHByb21pc2UgPSBfZ3VhcmQocHJvbWlzZSwgX2JpbmQoX29iamVjdElzQWxpdmUsIGludGVybmFsTW9kZWwpKTsKICAgIHJldHVybiBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKGFkYXB0ZXJQYXlsb2FkKSB7CiAgICAgIHZhciBzZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcihyZWxhdGlvbnNoaXAudHlwZSk7CiAgICAgIHZhciBwYXlsb2FkID0gbm9ybWFsaXplUmVzcG9uc2VIZWxwZXIoc2VyaWFsaXplciwgc3RvcmUsIG1vZGVsQ2xhc3MsIGFkYXB0ZXJQYXlsb2FkLCBudWxsLCAnZmluZEhhc01hbnknKTsKICAgICAgc3luY1JlbGF0aW9uc2hpcERhdGFGcm9tTGluayhzdG9yZSwgcGF5bG9hZCwgaW50ZXJuYWxNb2RlbCwgcmVsYXRpb25zaGlwKTsKCiAgICAgIHZhciBpbnRlcm5hbE1vZGVsQXJyYXkgPSBzdG9yZS5fcHVzaChwYXlsb2FkKTsKCiAgICAgIGludGVybmFsTW9kZWxBcnJheS5tZXRhID0gcGF5bG9hZC5tZXRhOwogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbEFycmF5OwogICAgfSwgbnVsbCwgIkRTOiBFeHRyYWN0IHBheWxvYWQgb2YgJyIgKyBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZSArICInIDogaGFzTWFueSAnIiArIHJlbGF0aW9uc2hpcC50eXBlICsgIiciKTsKICB9CiAgZnVuY3Rpb24gX2ZpbmRCZWxvbmdzVG8oYWRhcHRlciwgc3RvcmUsIGludGVybmFsTW9kZWwsIGxpbmssIHJlbGF0aW9uc2hpcCwgb3B0aW9ucykgewogICAgdmFyIHNuYXBzaG90ID0gaW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdChvcHRpb25zKTsKICAgIHZhciBtb2RlbENsYXNzID0gc3RvcmUubW9kZWxGb3IocmVsYXRpb25zaGlwLnR5cGUpOwogICAgdmFyIHByb21pc2UgPSBhZGFwdGVyLmZpbmRCZWxvbmdzVG8oc3RvcmUsIHNuYXBzaG90LCBsaW5rLCByZWxhdGlvbnNoaXApOwogICAgdmFyIGxhYmVsID0gIkRTOiBIYW5kbGUgQWRhcHRlciNmaW5kQmVsb25nc1RvIG9mICIgKyBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZSArICIgOiAiICsgcmVsYXRpb25zaGlwLnR5cGU7CiAgICBwcm9taXNlID0gZ3VhcmREZXN0cm95ZWRTdG9yZShwcm9taXNlLCBzdG9yZSwgbGFiZWwpOwogICAgcHJvbWlzZSA9IF9ndWFyZChwcm9taXNlLCBfYmluZChfb2JqZWN0SXNBbGl2ZSwgaW50ZXJuYWxNb2RlbCkpOwogICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAoYWRhcHRlclBheWxvYWQpIHsKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBzdG9yZS5zZXJpYWxpemVyRm9yKHJlbGF0aW9uc2hpcC50eXBlKTsKICAgICAgdmFyIHBheWxvYWQgPSBub3JtYWxpemVSZXNwb25zZUhlbHBlcihzZXJpYWxpemVyLCBzdG9yZSwgbW9kZWxDbGFzcywgYWRhcHRlclBheWxvYWQsIG51bGwsICdmaW5kQmVsb25nc1RvJyk7CgogICAgICBpZiAoIXBheWxvYWQuZGF0YSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICBzeW5jUmVsYXRpb25zaGlwRGF0YUZyb21MaW5rKHN0b3JlLCBwYXlsb2FkLCBpbnRlcm5hbE1vZGVsLCByZWxhdGlvbnNoaXApOwogICAgICByZXR1cm4gc3RvcmUuX3B1c2gocGF5bG9hZCk7CiAgICB9LCBudWxsLCAiRFM6IEV4dHJhY3QgcGF5bG9hZCBvZiAiICsgaW50ZXJuYWxNb2RlbC5tb2RlbE5hbWUgKyAiIDogIiArIHJlbGF0aW9uc2hpcC50eXBlKTsKICB9CiAgZnVuY3Rpb24gX2ZpbmRBbGwoYWRhcHRlciwgc3RvcmUsIG1vZGVsTmFtZSwgb3B0aW9ucykgewogICAgdmFyIG1vZGVsQ2xhc3MgPSBzdG9yZS5tb2RlbEZvcihtb2RlbE5hbWUpOyAvLyBhZGFwdGVyLmZpbmRBbGwgZGVwZW5kcyBvbiB0aGUgY2xhc3MKCiAgICB2YXIgcmVjb3JkQXJyYXkgPSBzdG9yZS5wZWVrQWxsKG1vZGVsTmFtZSk7CgogICAgdmFyIHNuYXBzaG90QXJyYXkgPSByZWNvcmRBcnJheS5fY3JlYXRlU25hcHNob3Qob3B0aW9ucyk7CgogICAgdmFyIHByb21pc2UgPSBFbWJlci5SU1ZQLlByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gYWRhcHRlci5maW5kQWxsKHN0b3JlLCBtb2RlbENsYXNzLCBudWxsLCBzbmFwc2hvdEFycmF5KTsKICAgIH0pOwogICAgdmFyIGxhYmVsID0gJ0RTOiBIYW5kbGUgQWRhcHRlciNmaW5kQWxsIG9mICcgKyBtb2RlbENsYXNzOwogICAgcHJvbWlzZSA9IGd1YXJkRGVzdHJveWVkU3RvcmUocHJvbWlzZSwgc3RvcmUsIGxhYmVsKTsKICAgIHJldHVybiBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKGFkYXB0ZXJQYXlsb2FkKSB7CiAgICAgIHZhciBzZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcihtb2RlbE5hbWUpOwogICAgICB2YXIgcGF5bG9hZCA9IG5vcm1hbGl6ZVJlc3BvbnNlSGVscGVyKHNlcmlhbGl6ZXIsIHN0b3JlLCBtb2RlbENsYXNzLCBhZGFwdGVyUGF5bG9hZCwgbnVsbCwgJ2ZpbmRBbGwnKTsKCiAgICAgIHN0b3JlLl9wdXNoKHBheWxvYWQpOwoKICAgICAgc3RvcmUuX2RpZFVwZGF0ZUFsbChtb2RlbE5hbWUpOwoKICAgICAgcmV0dXJuIHJlY29yZEFycmF5OwogICAgfSwgbnVsbCwgJ0RTOiBFeHRyYWN0IHBheWxvYWQgb2YgZmluZEFsbCAke21vZGVsTmFtZX0nKTsKICB9CiAgZnVuY3Rpb24gX3F1ZXJ5KGFkYXB0ZXIsIHN0b3JlLCBtb2RlbE5hbWUsIHF1ZXJ5LCByZWNvcmRBcnJheSwgb3B0aW9ucykgewogICAgdmFyIG1vZGVsQ2xhc3MgPSBzdG9yZS5tb2RlbEZvcihtb2RlbE5hbWUpOyAvLyBhZGFwdGVyLnF1ZXJ5IG5lZWRzIHRoZSBjbGFzcwoKICAgIHJlY29yZEFycmF5ID0gcmVjb3JkQXJyYXkgfHwgc3RvcmUucmVjb3JkQXJyYXlNYW5hZ2VyLmNyZWF0ZUFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheShtb2RlbE5hbWUsIHF1ZXJ5KTsKICAgIHZhciBwcm9taXNlID0gRW1iZXIuUlNWUC5Qcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIGFkYXB0ZXIucXVlcnkoc3RvcmUsIG1vZGVsQ2xhc3MsIHF1ZXJ5LCByZWNvcmRBcnJheSwgb3B0aW9ucyk7CiAgICB9KTsKICAgIHZhciBsYWJlbCA9ICJEUzogSGFuZGxlIEFkYXB0ZXIjcXVlcnkgb2YgIiArIG1vZGVsTmFtZTsKICAgIHByb21pc2UgPSBndWFyZERlc3Ryb3llZFN0b3JlKHByb21pc2UsIHN0b3JlLCBsYWJlbCk7CiAgICByZXR1cm4gcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChhZGFwdGVyUGF5bG9hZCkgewogICAgICB2YXIgc2VyaWFsaXplciA9IHN0b3JlLnNlcmlhbGl6ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgdmFyIHBheWxvYWQgPSBub3JtYWxpemVSZXNwb25zZUhlbHBlcihzZXJpYWxpemVyLCBzdG9yZSwgbW9kZWxDbGFzcywgYWRhcHRlclBheWxvYWQsIG51bGwsICdxdWVyeScpOwoKICAgICAgdmFyIGludGVybmFsTW9kZWxzID0gc3RvcmUuX3B1c2gocGF5bG9hZCk7CgogICAgICBpZiAocmVjb3JkQXJyYXkpIHsKICAgICAgICByZWNvcmRBcnJheS5fc2V0SW50ZXJuYWxNb2RlbHMoaW50ZXJuYWxNb2RlbHMsIHBheWxvYWQpOwogICAgICB9IGVsc2UgewogICAgICAgIHJlY29yZEFycmF5ID0gc3RvcmUucmVjb3JkQXJyYXlNYW5hZ2VyLmNyZWF0ZUFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheShtb2RlbE5hbWUsIHF1ZXJ5LCBpbnRlcm5hbE1vZGVscywgcGF5bG9hZCk7CiAgICAgIH0KCiAgICAgIHJldHVybiByZWNvcmRBcnJheTsKICAgIH0sIG51bGwsICJEUzogRXh0cmFjdCBwYXlsb2FkIG9mIHF1ZXJ5ICIgKyBtb2RlbE5hbWUpOwogIH0KICBmdW5jdGlvbiBfcXVlcnlSZWNvcmQoYWRhcHRlciwgc3RvcmUsIG1vZGVsTmFtZSwgcXVlcnksIG9wdGlvbnMpIHsKICAgIHZhciBtb2RlbENsYXNzID0gc3RvcmUubW9kZWxGb3IobW9kZWxOYW1lKTsgLy8gYWRhcHRlci5xdWVyeVJlY29yZCBuZWVkcyB0aGUgY2xhc3MKCiAgICB2YXIgcHJvbWlzZSA9IEVtYmVyLlJTVlAuUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBhZGFwdGVyLnF1ZXJ5UmVjb3JkKHN0b3JlLCBtb2RlbENsYXNzLCBxdWVyeSwgb3B0aW9ucyk7CiAgICB9KTsKICAgIHZhciBsYWJlbCA9ICJEUzogSGFuZGxlIEFkYXB0ZXIjcXVlcnlSZWNvcmQgb2YgIiArIG1vZGVsTmFtZTsKICAgIHByb21pc2UgPSBndWFyZERlc3Ryb3llZFN0b3JlKHByb21pc2UsIHN0b3JlLCBsYWJlbCk7CiAgICByZXR1cm4gcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChhZGFwdGVyUGF5bG9hZCkgewogICAgICB2YXIgc2VyaWFsaXplciA9IHN0b3JlLnNlcmlhbGl6ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgdmFyIHBheWxvYWQgPSBub3JtYWxpemVSZXNwb25zZUhlbHBlcihzZXJpYWxpemVyLCBzdG9yZSwgbW9kZWxDbGFzcywgYWRhcHRlclBheWxvYWQsIG51bGwsICdxdWVyeVJlY29yZCcpOwogICAgICByZXR1cm4gc3RvcmUuX3B1c2gocGF5bG9hZCk7CiAgICB9LCBudWxsLCAiRFM6IEV4dHJhY3QgcGF5bG9hZCBvZiBxdWVyeVJlY29yZCAiICsgbW9kZWxOYW1lKTsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICAgUmVwcmVzZW50cyBhbiBvcmRlcmVkIGxpc3Qgb2YgcmVjb3JkcyB3aG9zZSBvcmRlciBhbmQgbWVtYmVyc2hpcCBpcwogICAgZGV0ZXJtaW5lZCBieSB0aGUgYWRhcHRlci4gRm9yIGV4YW1wbGUsIGEgcXVlcnkgc2VudCB0byB0aGUgYWRhcHRlcgogICAgbWF5IHRyaWdnZXIgYSBzZWFyY2ggb24gdGhlIHNlcnZlciwgd2hvc2UgcmVzdWx0cyB3b3VsZCBiZSBsb2FkZWQKICAgIGludG8gYW4gaW5zdGFuY2Ugb2YgdGhlIGBBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXlgLgoKICAgIC0tLQoKICAgIElmIHlvdSB3YW50IHRvIHVwZGF0ZSB0aGUgYXJyYXkgYW5kIGdldCB0aGUgbGF0ZXN0IHJlY29yZHMgZnJvbSB0aGUKICAgIGFkYXB0ZXIsIHlvdSBjYW4gaW52b2tlIFtgdXBkYXRlKClgXShBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXkvbWV0aG9kcy91cGRhdGU/YW5jaG9yPXVwZGF0ZSk6CgogICAgRXhhbXBsZQoKICAgIGBgYGphdmFzY3JpcHQKICAgIC8vIEdFVCAvdXNlcnM/aXNBZG1pbj10cnVlCiAgICBzdG9yZS5xdWVyeSgndXNlcicsIHsgaXNBZG1pbjogdHJ1ZSB9KS50aGVuKGZ1bmN0aW9uKGFkbWlucykgewoKICAgICAgYWRtaW5zLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgICAgY29uc29sZS5sb2coYWRtaW5zLmdldCgibGVuZ3RoIikpOyAvLyA0MgogICAgICB9KTsKCiAgICAgIC8vIHNvbWV3aGVyZSBsYXRlciBpbiB0aGUgYXBwIGNvZGUsIHdoZW4gbmV3IGFkbWlucyBoYXZlIGJlZW4gY3JlYXRlZAogICAgICAvLyBpbiB0aGUgbWVhbnRpbWUKICAgICAgLy8KICAgICAgLy8gR0VUIC91c2Vycz9pc0FkbWluPXRydWUKICAgICAgYWRtaW5zLnVwZGF0ZSgpLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgICAgYWRtaW5zLmdldCgnaXNVcGRhdGluZycpOyAvLyBmYWxzZQogICAgICAgIGNvbnNvbGUubG9nKGFkbWlucy5nZXQoImxlbmd0aCIpKTsgLy8gMTIzCiAgICAgIH0pOwoKICAgICAgYWRtaW5zLmdldCgnaXNVcGRhdGluZycpOyAvLyB0cnVlCiAgICB9CiAgICBgYGAKCiAgICBAY2xhc3MgQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5CiAgICBAZXh0ZW5kcyBSZWNvcmRBcnJheQogICovCiAgdmFyIEFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheSA9IFJlY29yZEFycmF5LmV4dGVuZCh7CiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewoKICAgICAgLy8geWVzIHdlIGFyZSB0b3VjaGluZyBgdGhpc2AgYmVmb3JlIHN1cGVyLCBidXQgQXJyYXlQcm94eSBoYXMgYSBidWcgdGhhdCByZXF1aXJlcyB0aGlzLgogICAgICB0aGlzLnNldCgnY29udGVudCcsIHRoaXMuZ2V0KCdjb250ZW50JykgfHwgRW1iZXIuQSgpKTsKCiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzLnF1ZXJ5ID0gdGhpcy5xdWVyeSB8fCBudWxsOwogICAgICB0aGlzLmxpbmtzID0gdGhpcy5saW5rcyB8fCBudWxsOwogICAgfSwKICAgIHJlcGxhY2U6IGZ1bmN0aW9uIHJlcGxhY2UoKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiVGhlIHJlc3VsdCBvZiBhIHNlcnZlciBxdWVyeSAob24gIiArIHRoaXMubW9kZWxOYW1lICsgIikgaXMgaW1tdXRhYmxlLiIpOwogICAgfSwKICAgIF91cGRhdGU6IGZ1bmN0aW9uIF91cGRhdGUoKSB7CiAgICAgIHZhciBzdG9yZSA9IEVtYmVyLmdldCh0aGlzLCAnc3RvcmUnKTsKICAgICAgdmFyIHF1ZXJ5ID0gRW1iZXIuZ2V0KHRoaXMsICdxdWVyeScpOwogICAgICByZXR1cm4gc3RvcmUuX3F1ZXJ5KHRoaXMubW9kZWxOYW1lLCBxdWVyeSwgdGhpcyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIF9zZXRJbnRlcm5hbE1vZGVscwogICAgICBAcGFyYW0ge0FycmF5fSBpbnRlcm5hbE1vZGVscwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZCBub3JtYWxpemVkIHBheWxvYWQKICAgICAgQHByaXZhdGUKICAgICovCiAgICBfc2V0SW50ZXJuYWxNb2RlbHM6IGZ1bmN0aW9uIF9zZXRJbnRlcm5hbE1vZGVscyhpbnRlcm5hbE1vZGVscywgcGF5bG9hZCkgewogICAgICAvLyBUT0RPOiBpbml0aWFsIGxvYWQgc2hvdWxkIG5vdCBjYXVzZSBjaGFuZ2UgZXZlbnRzIGF0IGFsbCwgb25seQogICAgICAvLyBzdWJzZXF1ZW50LiBUaGlzIHJlcXVpcmVzIGNoYW5naW5nIHRoZSBwdWJsaWMgYXBpIG9mIGFkYXB0ZXIucXVlcnksIGJ1dAogICAgICAvLyBob3BlZnVsbHkgd2UgY2FuIGRvIHRoYXQgc29vbi4KICAgICAgdGhpcy5nZXQoJ2NvbnRlbnQnKS5zZXRPYmplY3RzKGludGVybmFsTW9kZWxzKTsKICAgICAgdGhpcy5zZXRQcm9wZXJ0aWVzKHsKICAgICAgICBpc0xvYWRlZDogdHJ1ZSwKICAgICAgICBpc1VwZGF0aW5nOiBmYWxzZSwKICAgICAgICBtZXRhOiBFbWJlci5hc3NpZ24oe30sIHBheWxvYWQubWV0YSksCiAgICAgICAgbGlua3M6IEVtYmVyLmFzc2lnbih7fSwgcGF5bG9hZC5saW5rcykKICAgICAgfSk7CgogICAgICB0aGlzLm1hbmFnZXIuX2Fzc29jaWF0ZVdpdGhSZWNvcmRBcnJheShpbnRlcm5hbE1vZGVscywgdGhpcyk7CgogICAgICB2YXIgX2hhc0RpZExvYWQgPSAgdGhpcy5oYXMoJ2RpZExvYWQnKTsKCiAgICAgIGlmIChfaGFzRGlkTG9hZCkgewogICAgICAgIC8vIFRPRE86IHNob3VsZCB0cmlnZ2VyaW5nIGRpZExvYWQgZXZlbnQgYmUgdGhlIGxhc3QgYWN0aW9uIG9mIHRoZSBydW5Mb29wPwogICAgICAgIEVtYmVyLnJ1bi5vbmNlKHRoaXMsICd0cmlnZ2VyJywgJ2RpZExvYWQnKTsKICAgICAgfQogICAgfQogIH0pOwoKICB2YXIgZW1iZXJSdW4kMSA9IEVtYmVyLnJ1bi5iYWNrYnVybmVyOwogIC8qKgogICAgQGNsYXNzIFJlY29yZEFycmF5TWFuYWdlcgogICAgQHByaXZhdGUKICAqLwoKICB2YXIgUmVjb3JkQXJyYXlNYW5hZ2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUmVjb3JkQXJyYXlNYW5hZ2VyKG9wdGlvbnMpIHsKICAgICAgdGhpcy5zdG9yZSA9IG9wdGlvbnMuc3RvcmU7CiAgICAgIHRoaXMuaXNEZXN0cm95aW5nID0gZmFsc2U7CiAgICAgIHRoaXMuaXNEZXN0cm95ZWQgPSBmYWxzZTsKICAgICAgdGhpcy5fbGl2ZVJlY29yZEFycmF5cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHRoaXMuX3BlbmRpbmcgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9hZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXlzID0gW107CiAgICB9CgogICAgdmFyIF9wcm90byA9IFJlY29yZEFycmF5TWFuYWdlci5wcm90b3R5cGU7CgogICAgX3Byb3RvLnJlY29yZERpZENoYW5nZSA9IGZ1bmN0aW9uIHJlY29yZERpZENoYW5nZShpbnRlcm5hbE1vZGVsKSB7CiAgICAgIC8vIFRPRE86IGNoYW5nZSBuYW1lCiAgICAgIC8vIFRPRE86IHRyYWNrIHRoYXQgaXQgd2FzIGFsc28gYSBjaGFuZ2UKICAgICAgdGhpcy5pbnRlcm5hbE1vZGVsRGlkQ2hhbmdlKGludGVybmFsTW9kZWwpOwogICAgfTsKCiAgICBfcHJvdG8ucmVjb3JkV2FzTG9hZGVkID0gZnVuY3Rpb24gcmVjb3JkV2FzTG9hZGVkKGludGVybmFsTW9kZWwpIHsKICAgICAgLy8gVE9ETzogY2hhbmdlIG5hbWUKICAgICAgLy8gVE9ETzogdHJhY2sgdGhhdCBpdCB3YXMgYWxzbyB0aGF0IGl0IHdhcyBmaXJzdCBsb2FkZWQKICAgICAgdGhpcy5pbnRlcm5hbE1vZGVsRGlkQ2hhbmdlKGludGVybmFsTW9kZWwpOwogICAgfTsKCiAgICBfcHJvdG8uaW50ZXJuYWxNb2RlbERpZENoYW5nZSA9IGZ1bmN0aW9uIGludGVybmFsTW9kZWxEaWRDaGFuZ2UoaW50ZXJuYWxNb2RlbCkgewogICAgICB2YXIgbW9kZWxOYW1lID0gaW50ZXJuYWxNb2RlbC5tb2RlbE5hbWU7CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbC5fcGVuZGluZ1JlY29yZEFycmF5TWFuYWdlckZsdXNoKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpbnRlcm5hbE1vZGVsLl9wZW5kaW5nUmVjb3JkQXJyYXlNYW5hZ2VyRmx1c2ggPSB0cnVlOwogICAgICB2YXIgcGVuZGluZyA9IHRoaXMuX3BlbmRpbmc7CiAgICAgIHZhciBtb2RlbHMgPSBwZW5kaW5nW21vZGVsTmFtZV0gPSBwZW5kaW5nW21vZGVsTmFtZV0gfHwgW107CgogICAgICBpZiAobW9kZWxzLnB1c2goaW50ZXJuYWxNb2RlbCkgIT09IDEpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGVtYmVyUnVuJDEuc2NoZWR1bGUoJ2FjdGlvbnMnLCB0aGlzLCB0aGlzLl9mbHVzaCk7CiAgICB9OwoKICAgIF9wcm90by5fZmx1c2hQZW5kaW5nSW50ZXJuYWxNb2RlbHNGb3JNb2RlbE5hbWUgPSBmdW5jdGlvbiBfZmx1c2hQZW5kaW5nSW50ZXJuYWxNb2RlbHNGb3JNb2RlbE5hbWUobW9kZWxOYW1lLCBpbnRlcm5hbE1vZGVscykgewogICAgICB2YXIgbW9kZWxzVG9SZW1vdmUgPSBbXTsKCiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgaW50ZXJuYWxNb2RlbHMubGVuZ3RoOyBqKyspIHsKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxzW2pdOyAvLyBtYXJrIGludGVybmFsTW9kZWxzLCBzbyB0aGV5IGNhbiBvbmNlIGFnYWluIGJlIHByb2Nlc3NlZCBieSB0aGUKICAgICAgICAvLyByZWNvcmRBcnJheU1hbmFnZXIKCiAgICAgICAgaW50ZXJuYWxNb2RlbC5fcGVuZGluZ1JlY29yZEFycmF5TWFuYWdlckZsdXNoID0gZmFsc2U7IC8vIGJ1aWxkIHVwIGEgc2V0IG9mIG1vZGVscyB0byBlbnN1cmUgd2UgaGF2ZSBwdXJnZWQgY29ycmVjdGx5OwoKICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbC5pc0hpZGRlbkZyb21SZWNvcmRBcnJheXMoKSkgewogICAgICAgICAgbW9kZWxzVG9SZW1vdmUucHVzaChpbnRlcm5hbE1vZGVsKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciBhcnJheSA9IHRoaXMuX2xpdmVSZWNvcmRBcnJheXNbbW9kZWxOYW1lXTsKCiAgICAgIGlmIChhcnJheSkgewogICAgICAgIC8vIFRPRE86IHNraXAgaWYgaXQgb25seSBjaGFuZ2VkCiAgICAgICAgLy8gcHJvY2VzcyBsaXZlUmVjb3JkQXJyYXlzCiAgICAgICAgdGhpcy51cGRhdGVMaXZlUmVjb3JkQXJyYXkoYXJyYXksIGludGVybmFsTW9kZWxzKTsKICAgICAgfSAvLyBwcm9jZXNzIGFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheXMKCgogICAgICBpZiAobW9kZWxzVG9SZW1vdmUubGVuZ3RoID4gMCkgewogICAgICAgIHJlbW92ZUZyb21BZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXlzKG1vZGVsc1RvUmVtb3ZlKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2ZsdXNoID0gZnVuY3Rpb24gX2ZsdXNoKCkgewogICAgICB2YXIgcGVuZGluZyA9IHRoaXMuX3BlbmRpbmc7CiAgICAgIHRoaXMuX3BlbmRpbmcgPSBPYmplY3QuY3JlYXRlKG51bGwpOwoKICAgICAgZm9yICh2YXIgbW9kZWxOYW1lIGluIHBlbmRpbmcpIHsKICAgICAgICB0aGlzLl9mbHVzaFBlbmRpbmdJbnRlcm5hbE1vZGVsc0Zvck1vZGVsTmFtZShtb2RlbE5hbWUsIHBlbmRpbmdbbW9kZWxOYW1lXSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnVwZGF0ZUxpdmVSZWNvcmRBcnJheSA9IGZ1bmN0aW9uIHVwZGF0ZUxpdmVSZWNvcmRBcnJheShhcnJheSwgaW50ZXJuYWxNb2RlbHMpIHsKICAgICAgcmV0dXJuIF91cGRhdGVMaXZlUmVjb3JkQXJyYXkoYXJyYXksIGludGVybmFsTW9kZWxzKTsKICAgIH07CgogICAgX3Byb3RvLl9zeW5jTGl2ZVJlY29yZEFycmF5ID0gZnVuY3Rpb24gX3N5bmNMaXZlUmVjb3JkQXJyYXkoYXJyYXksIG1vZGVsTmFtZSkgewogICAgICB2YXIgcGVuZGluZyA9IHRoaXMuX3BlbmRpbmdbbW9kZWxOYW1lXTsKICAgICAgdmFyIGhhc1BlbmRpbmdDaGFuZ2VzID0gQXJyYXkuaXNBcnJheShwZW5kaW5nKTsKICAgICAgdmFyIGhhc05vUG90ZW50aWFsRGVsZXRpb25zID0gIWhhc1BlbmRpbmdDaGFuZ2VzIHx8IHBlbmRpbmcubGVuZ3RoID09PSAwOwogICAgICB2YXIgbWFwID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcy5zdG9yZSkubW9kZWxNYXBGb3IobW9kZWxOYW1lKTsKICAgICAgdmFyIGhhc05vSW5zZXJ0aW9uc09yUmVtb3ZhbHMgPSBFbWJlci5nZXQobWFwLCAnbGVuZ3RoJykgPT09IEVtYmVyLmdldChhcnJheSwgJ2xlbmd0aCcpOwogICAgICAvKgogICAgICAgIElkZWFsbHkgdGhlIHJlY29yZEFycmF5TWFuYWdlciBoYXMga25vd2xlZGdlIG9mIHRoZSBjaGFuZ2VzIHRvIGJlIGFwcGxpZWQgdG8KICAgICAgICBsaXZlUmVjb3JkQXJyYXlzLCBhbmQgaXMgY2FwYWJsZSBvZiBzdHJhdGVnaWNhbGx5IGZsdXNoaW5nIHRob3NlIGNoYW5nZXMgYW5kIGFwcGx5aW5nCiAgICAgICAgc21hbGwgZGlmZnMgaWYgZGVzaXJlZC4gIEhvd2V2ZXIsIHVudGlsIHdlJ3ZlIHJlZmFjdG9yZWQgcmVjb3JkQXJyYXlNYW5hZ2VyLCB0aGlzIGRpcnR5CiAgICAgICAgY2hlY2sgcHJldmVudHMgdXMgZnJvbSB1bm5lY2Vzc2FyaWx5IHdpcGluZyBvdXQgbGl2ZSByZWNvcmQgYXJyYXlzIHJldHVybmVkIGJ5IHBlZWtBbGwuCiAgICAgICAgKi8KCiAgICAgIGlmIChoYXNOb1BvdGVudGlhbERlbGV0aW9ucyAmJiBoYXNOb0luc2VydGlvbnNPclJlbW92YWxzKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAoaGFzUGVuZGluZ0NoYW5nZXMpIHsKICAgICAgICB0aGlzLl9mbHVzaFBlbmRpbmdJbnRlcm5hbE1vZGVsc0Zvck1vZGVsTmFtZShtb2RlbE5hbWUsIHBlbmRpbmcpOwoKICAgICAgICBkZWxldGUgdGhpcy5fcGVuZGluZ1ttb2RlbE5hbWVdOwogICAgICB9CgogICAgICB2YXIgaW50ZXJuYWxNb2RlbHMgPSB0aGlzLl92aXNpYmxlSW50ZXJuYWxNb2RlbHNCeVR5cGUobW9kZWxOYW1lKTsKCiAgICAgIHZhciBtb2RlbHNUb0FkZCA9IFtdOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbnRlcm5hbE1vZGVscy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gaW50ZXJuYWxNb2RlbHNbaV07CiAgICAgICAgdmFyIHJlY29yZEFycmF5cyA9IGludGVybmFsTW9kZWwuX3JlY29yZEFycmF5czsKCiAgICAgICAgaWYgKHJlY29yZEFycmF5cy5oYXMoYXJyYXkpID09PSBmYWxzZSkgewogICAgICAgICAgcmVjb3JkQXJyYXlzLmFkZChhcnJheSk7CiAgICAgICAgICBtb2RlbHNUb0FkZC5wdXNoKGludGVybmFsTW9kZWwpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKG1vZGVsc1RvQWRkLmxlbmd0aCkgewogICAgICAgIGFycmF5Ll9wdXNoSW50ZXJuYWxNb2RlbHMobW9kZWxzVG9BZGQpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fZGlkVXBkYXRlQWxsID0gZnVuY3Rpb24gX2RpZFVwZGF0ZUFsbChtb2RlbE5hbWUpIHsKICAgICAgdmFyIHJlY29yZEFycmF5ID0gdGhpcy5fbGl2ZVJlY29yZEFycmF5c1ttb2RlbE5hbWVdOwoKICAgICAgaWYgKHJlY29yZEFycmF5KSB7CiAgICAgICAgRW1iZXIuc2V0KHJlY29yZEFycmF5LCAnaXNVcGRhdGluZycsIGZhbHNlKTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgIEdldCB0aGUgYFJlY29yZEFycmF5YCBmb3IgYSBtb2RlbE5hbWUsIHdoaWNoIGNvbnRhaW5zIGFsbCBsb2FkZWQgcmVjb3JkcyBvZgogICAgICBnaXZlbiBtb2RlbE5hbWUuCiAgICAgICBAbWV0aG9kIGxpdmVSZWNvcmRBcnJheUZvcgogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEByZXR1cm4ge1JlY29yZEFycmF5fQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ubGl2ZVJlY29yZEFycmF5Rm9yID0gZnVuY3Rpb24gbGl2ZVJlY29yZEFycmF5Rm9yKG1vZGVsTmFtZSkgewogICAgICB2YXIgYXJyYXkgPSB0aGlzLl9saXZlUmVjb3JkQXJyYXlzW21vZGVsTmFtZV07CgogICAgICBpZiAoYXJyYXkpIHsKICAgICAgICAvLyBpZiB0aGUgYXJyYXkgYWxyZWFkeSBleGlzdHMsIHN5bmNocm9uaXplCiAgICAgICAgdGhpcy5fc3luY0xpdmVSZWNvcmRBcnJheShhcnJheSwgbW9kZWxOYW1lKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAvLyBpZiB0aGUgYXJyYXkgaXMgYmVpbmcgbmV3bHkgY3JlYXRlZCBtZXJlbHkgY3JlYXRlIGl0IHdpdGggaXRzIGluaXRpYWwKICAgICAgICAvLyBjb250ZW50IGFscmVhZHkgc2V0LiBUaGlzIHByZXZlbnRzIHVubmVlZGVkIGNoYW5nZSBldmVudHMuCiAgICAgICAgdmFyIGludGVybmFsTW9kZWxzID0gdGhpcy5fdmlzaWJsZUludGVybmFsTW9kZWxzQnlUeXBlKG1vZGVsTmFtZSk7CgogICAgICAgIGFycmF5ID0gdGhpcy5jcmVhdGVSZWNvcmRBcnJheShtb2RlbE5hbWUsIGludGVybmFsTW9kZWxzKTsKICAgICAgICB0aGlzLl9saXZlUmVjb3JkQXJyYXlzW21vZGVsTmFtZV0gPSBhcnJheTsKICAgICAgfQoKICAgICAgcmV0dXJuIGFycmF5OwogICAgfTsKCiAgICBfcHJvdG8uX3Zpc2libGVJbnRlcm5hbE1vZGVsc0J5VHlwZSA9IGZ1bmN0aW9uIF92aXNpYmxlSW50ZXJuYWxNb2RlbHNCeVR5cGUobW9kZWxOYW1lKSB7CiAgICAgIHZhciBhbGwgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzLnN0b3JlKS5tb2RlbE1hcEZvcihtb2RlbE5hbWUpLl9tb2RlbHM7CgogICAgICB2YXIgdmlzaWJsZSA9IFtdOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhbGwubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgbW9kZWwgPSBhbGxbaV07CgogICAgICAgIGlmIChtb2RlbC5pc0hpZGRlbkZyb21SZWNvcmRBcnJheXMoKSA9PT0gZmFsc2UpIHsKICAgICAgICAgIHZpc2libGUucHVzaChtb2RlbCk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdmlzaWJsZTsKICAgIH0KICAgIC8qKgogICAgICBDcmVhdGUgYSBgUmVjb3JkQXJyYXlgIGZvciBhIG1vZGVsTmFtZS4KICAgICAgIEBtZXRob2QgY3JlYXRlUmVjb3JkQXJyYXkKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0ge0FycmF5fSBfY29udGVudCAob3B0aW9uYWx8cHJpdmF0ZSkKICAgICAgQHJldHVybiB7UmVjb3JkQXJyYXl9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5jcmVhdGVSZWNvcmRBcnJheSA9IGZ1bmN0aW9uIGNyZWF0ZVJlY29yZEFycmF5KG1vZGVsTmFtZSwgY29udGVudCkgewogICAgICB2YXIgYXJyYXkgPSBSZWNvcmRBcnJheS5jcmVhdGUoewogICAgICAgIG1vZGVsTmFtZTogbW9kZWxOYW1lLAogICAgICAgIGNvbnRlbnQ6IEVtYmVyLkEoY29udGVudCB8fCBbXSksCiAgICAgICAgc3RvcmU6IHRoaXMuc3RvcmUsCiAgICAgICAgaXNMb2FkZWQ6IHRydWUsCiAgICAgICAgbWFuYWdlcjogdGhpcwogICAgICB9KTsKCiAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvbnRlbnQpKSB7CiAgICAgICAgYXNzb2NpYXRlV2l0aFJlY29yZEFycmF5KGNvbnRlbnQsIGFycmF5KTsKICAgICAgfQoKICAgICAgcmV0dXJuIGFycmF5OwogICAgfQogICAgLyoqCiAgICAgIENyZWF0ZSBhIGBBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXlgIGZvciBhIG1vZGVsTmFtZSB3aXRoIGdpdmVuIHF1ZXJ5LgogICAgICAgQG1ldGhvZCBjcmVhdGVBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXkKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0ge09iamVjdH0gcXVlcnkKICAgICAgQHJldHVybiB7QWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5fQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uY3JlYXRlQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5ID0gZnVuY3Rpb24gY3JlYXRlQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5KG1vZGVsTmFtZSwgcXVlcnksIGludGVybmFsTW9kZWxzLCBwYXlsb2FkKSB7CiAgICAgIHZhciBhcnJheTsKCiAgICAgIGlmIChBcnJheS5pc0FycmF5KGludGVybmFsTW9kZWxzKSkgewogICAgICAgIGFycmF5ID0gQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5LmNyZWF0ZSh7CiAgICAgICAgICBtb2RlbE5hbWU6IG1vZGVsTmFtZSwKICAgICAgICAgIHF1ZXJ5OiBxdWVyeSwKICAgICAgICAgIGNvbnRlbnQ6IEVtYmVyLkEoaW50ZXJuYWxNb2RlbHMpLAogICAgICAgICAgc3RvcmU6IHRoaXMuc3RvcmUsCiAgICAgICAgICBtYW5hZ2VyOiB0aGlzLAogICAgICAgICAgaXNMb2FkZWQ6IHRydWUsCiAgICAgICAgICBpc1VwZGF0aW5nOiBmYWxzZSwKICAgICAgICAgIG1ldGE6IEVtYmVyLmFzc2lnbih7fSwgcGF5bG9hZC5tZXRhKSwKICAgICAgICAgIGxpbmtzOiBFbWJlci5hc3NpZ24oe30sIHBheWxvYWQubGlua3MpCiAgICAgICAgfSk7CiAgICAgICAgYXNzb2NpYXRlV2l0aFJlY29yZEFycmF5KGludGVybmFsTW9kZWxzLCBhcnJheSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYXJyYXkgPSBBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXkuY3JlYXRlKHsKICAgICAgICAgIG1vZGVsTmFtZTogbW9kZWxOYW1lLAogICAgICAgICAgcXVlcnk6IHF1ZXJ5LAogICAgICAgICAgY29udGVudDogRW1iZXIuQSgpLAogICAgICAgICAgc3RvcmU6IHRoaXMuc3RvcmUsCiAgICAgICAgICBtYW5hZ2VyOiB0aGlzCiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHRoaXMuX2FkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheXMucHVzaChhcnJheSk7CgogICAgICByZXR1cm4gYXJyYXk7CiAgICB9CiAgICAvKioKICAgICAgVW5yZWdpc3RlciBhIFJlY29yZEFycmF5LgogICAgICBTbyBtYW5hZ2VyIHdpbGwgbm90IHVwZGF0ZSB0aGlzIGFycmF5LgogICAgICAgQG1ldGhvZCB1bnJlZ2lzdGVyUmVjb3JkQXJyYXkKICAgICAgQHBhcmFtIHtSZWNvcmRBcnJheX0gYXJyYXkKICAgICovCiAgICA7CgogICAgX3Byb3RvLnVucmVnaXN0ZXJSZWNvcmRBcnJheSA9IGZ1bmN0aW9uIHVucmVnaXN0ZXJSZWNvcmRBcnJheShhcnJheSkgewogICAgICB2YXIgbW9kZWxOYW1lID0gYXJyYXkubW9kZWxOYW1lOyAvLyByZW1vdmUgZnJvbSBhZGFwdGVyIHBvcHVsYXRlZCByZWNvcmQgYXJyYXkKCiAgICAgIHZhciByZW1vdmVkRnJvbUFkYXB0ZXJQb3B1bGF0ZWQgPSByZW1vdmUodGhpcy5fYWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5cywgYXJyYXkpOwoKICAgICAgaWYgKCFyZW1vdmVkRnJvbUFkYXB0ZXJQb3B1bGF0ZWQpIHsKICAgICAgICB2YXIgbGl2ZVJlY29yZEFycmF5Rm9yVHlwZSA9IHRoaXMuX2xpdmVSZWNvcmRBcnJheXNbbW9kZWxOYW1lXTsgLy8gdW5yZWdpc3RlciBsaXZlIHJlY29yZCBhcnJheQoKICAgICAgICBpZiAobGl2ZVJlY29yZEFycmF5Rm9yVHlwZSkgewogICAgICAgICAgaWYgKGFycmF5ID09PSBsaXZlUmVjb3JkQXJyYXlGb3JUeXBlKSB7CiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9saXZlUmVjb3JkQXJyYXlzW21vZGVsTmFtZV07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fYXNzb2NpYXRlV2l0aFJlY29yZEFycmF5ID0gZnVuY3Rpb24gX2Fzc29jaWF0ZVdpdGhSZWNvcmRBcnJheShpbnRlcm5hbE1vZGVscywgYXJyYXkpIHsKICAgICAgYXNzb2NpYXRlV2l0aFJlY29yZEFycmF5KGludGVybmFsTW9kZWxzLCBhcnJheSk7CiAgICB9OwoKICAgIF9wcm90by53aWxsRGVzdHJveSA9IGZ1bmN0aW9uIHdpbGxEZXN0cm95KCkgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgT2JqZWN0LmtleXModGhpcy5fbGl2ZVJlY29yZEFycmF5cykuZm9yRWFjaChmdW5jdGlvbiAobW9kZWxOYW1lKSB7CiAgICAgICAgcmV0dXJuIF90aGlzLl9saXZlUmVjb3JkQXJyYXlzW21vZGVsTmFtZV0uZGVzdHJveSgpOwogICAgICB9KTsKCiAgICAgIHRoaXMuX2FkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheXMuZm9yRWFjaChkZXN0cm95KTsKCiAgICAgIHRoaXMuaXNEZXN0cm95ZWQgPSB0cnVlOwogICAgfTsKCiAgICBfcHJvdG8uZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHRoaXMuaXNEZXN0cm95aW5nID0gdHJ1ZTsKICAgICAgZW1iZXJSdW4kMS5zY2hlZHVsZSgnYWN0aW9ucycsIHRoaXMsIHRoaXMud2lsbERlc3Ryb3kpOwogICAgfTsKCiAgICByZXR1cm4gUmVjb3JkQXJyYXlNYW5hZ2VyOwogIH0oKTsKCiAgZnVuY3Rpb24gZGVzdHJveShlbnRyeSkgewogICAgZW50cnkuZGVzdHJveSgpOwogIH0KCiAgZnVuY3Rpb24gcmVtb3ZlKGFycmF5LCBpdGVtKSB7CiAgICB2YXIgaW5kZXggPSBhcnJheS5pbmRleE9mKGl0ZW0pOwoKICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgYXJyYXkuc3BsaWNlKGluZGV4LCAxKTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgcmV0dXJuIGZhbHNlOwogIH0KCiAgZnVuY3Rpb24gX3VwZGF0ZUxpdmVSZWNvcmRBcnJheShhcnJheSwgaW50ZXJuYWxNb2RlbHMpIHsKICAgIHZhciBtb2RlbHNUb0FkZCA9IFtdOwogICAgdmFyIG1vZGVsc1RvUmVtb3ZlID0gW107CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbnRlcm5hbE1vZGVscy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxzW2ldOwogICAgICB2YXIgaXNEZWxldGVkID0gaW50ZXJuYWxNb2RlbC5pc0hpZGRlbkZyb21SZWNvcmRBcnJheXMoKTsKICAgICAgdmFyIHJlY29yZEFycmF5cyA9IGludGVybmFsTW9kZWwuX3JlY29yZEFycmF5czsKCiAgICAgIGlmICghaXNEZWxldGVkICYmICFpbnRlcm5hbE1vZGVsLmlzRW1wdHkoKSkgewogICAgICAgIGlmICghcmVjb3JkQXJyYXlzLmhhcyhhcnJheSkpIHsKICAgICAgICAgIG1vZGVsc1RvQWRkLnB1c2goaW50ZXJuYWxNb2RlbCk7CiAgICAgICAgICByZWNvcmRBcnJheXMuYWRkKGFycmF5KTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChpc0RlbGV0ZWQpIHsKICAgICAgICBtb2RlbHNUb1JlbW92ZS5wdXNoKGludGVybmFsTW9kZWwpOwogICAgICAgIHJlY29yZEFycmF5cy5kZWxldGUoYXJyYXkpOwogICAgICB9CiAgICB9CgogICAgaWYgKG1vZGVsc1RvQWRkLmxlbmd0aCA+IDApIHsKICAgICAgYXJyYXkuX3B1c2hJbnRlcm5hbE1vZGVscyhtb2RlbHNUb0FkZCk7CiAgICB9CgogICAgaWYgKG1vZGVsc1RvUmVtb3ZlLmxlbmd0aCA+IDApIHsKICAgICAgYXJyYXkuX3JlbW92ZUludGVybmFsTW9kZWxzKG1vZGVsc1RvUmVtb3ZlKTsKICAgIH0gLy8gcmV0dXJuIHdoZXRoZXIgd2UgcGVyZm9ybWVkIGFuIHVwZGF0ZS4KICAgIC8vIE5lY2Vzc2FyeSB1bnRpbCAzLjUgYWxsb3dzIHVzIHRvIGZpbmlzaCBvZmYgZW1iZXItZGF0YS1maWx0ZXIgc3VwcG9ydC4KCgogICAgcmV0dXJuIChtb2RlbHNUb0FkZC5sZW5ndGggfHwgbW9kZWxzVG9SZW1vdmUubGVuZ3RoKSA+IDA7CiAgfQoKICBmdW5jdGlvbiByZW1vdmVGcm9tQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5cyhpbnRlcm5hbE1vZGVscykgewogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbnRlcm5hbE1vZGVscy5sZW5ndGg7IGkrKykgewogICAgICByZW1vdmVGcm9tQWxsKGludGVybmFsTW9kZWxzW2ldKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHJlbW92ZUZyb21BbGwoaW50ZXJuYWxNb2RlbCkgewogICAgdmFyIHJlY29yZEFycmF5cyA9IGludGVybmFsTW9kZWwuX3JlY29yZEFycmF5czsKICAgIHJlY29yZEFycmF5cy5mb3JFYWNoKGZ1bmN0aW9uIChyZWNvcmRBcnJheSkgewogICAgICByZWNvcmRBcnJheS5fcmVtb3ZlSW50ZXJuYWxNb2RlbHMoW2ludGVybmFsTW9kZWxdKTsKICAgIH0pOwogICAgcmVjb3JkQXJyYXlzLmNsZWFyKCk7CiAgfQoKICBmdW5jdGlvbiBhc3NvY2lhdGVXaXRoUmVjb3JkQXJyYXkoaW50ZXJuYWxNb2RlbHMsIGFycmF5KSB7CiAgICBmb3IgKHZhciBpID0gMCwgbCA9IGludGVybmFsTW9kZWxzLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxzW2ldOwoKICAgICAgaW50ZXJuYWxNb2RlbC5fcmVjb3JkQXJyYXlzLmFkZChhcnJheSk7CiAgICB9CiAgfQoKICB2YXIgYmFja2J1cm5lciA9IG5ldyBFbWJlci5fQmFja2J1cm5lcihbJ25vcm1hbGl6ZVJlbGF0aW9uc2hpcHMnLCAnc3luY1JlbGF0aW9uc2hpcHMnLCAnZmluaXNoZWQnXSk7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICAqIEdldCB0aGUgbWF0ZXJpYWxpemVkIG1vZGVsIGZyb20gdGhlIGludGVybmFsTW9kZWwvcHJvbWlzZQogICAqIHRoYXQgcmV0dXJucyBhbiBpbnRlcm5hbCBtb2RlbCBhbmQgcmV0dXJuIGl0IGluIGEgcHJvbWlzZU9iamVjdC4KICAgKgogICAqIFVzZWZ1bCBmb3IgcmV0dXJuaW5nIGZyb20gZmluZCBtZXRob2RzCiAgICoKICAgKiBAaW50ZXJuYWwKICAgKi8KICBmdW5jdGlvbiBwcm9taXNlUmVjb3JkKGludGVybmFsTW9kZWxQcm9taXNlLCBsYWJlbCkgewogICAgdmFyIHRvUmV0dXJuID0gaW50ZXJuYWxNb2RlbFByb21pc2UudGhlbihmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5nZXRSZWNvcmQoKTsKICAgIH0pOwogICAgcmV0dXJuIHByb21pc2VPYmplY3QodG9SZXR1cm4sIGxhYmVsKTsKICB9CgogIHZhciBDYWNoZSA9IG5ldyBXZWFrTWFwKCk7CiAgdmFyIFRva2VucyA9IG5ldyBXZWFrTWFwKCk7CiAgLyoKICAgIEN1cnJlbnRseSBvbmx5IHN1cHBvcnQgYSBzaW5nbGUgY2FsbGJhY2sgcGVyIGlkZW50aWZpZXIKICAqLwoKICB2YXIgTm90aWZpY2F0aW9uTWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIE5vdGlmaWNhdGlvbk1hbmFnZXIoc3RvcmUpIHsKICAgICAgdGhpcy5zdG9yZSA9IHN0b3JlOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBOb3RpZmljYXRpb25NYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uc3Vic2NyaWJlID0gZnVuY3Rpb24gc3Vic2NyaWJlKGlkZW50aWZpZXIsIGNhbGxiYWNrKSB7CiAgICAgIHZhciBzdGFibGVJZGVudGlmaWVyID0gaWRlbnRpZmllckNhY2hlRm9yKHRoaXMuc3RvcmUpLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihpZGVudGlmaWVyKTsKICAgICAgQ2FjaGUuc2V0KHN0YWJsZUlkZW50aWZpZXIsIGNhbGxiYWNrKTsKICAgICAgdmFyIHVuc3ViVG9rZW4gPSBuZXcgT2JqZWN0KCk7CiAgICAgIFRva2Vucy5zZXQodW5zdWJUb2tlbiwgc3RhYmxlSWRlbnRpZmllcik7CiAgICAgIHJldHVybiBpZGVudGlmaWVyOwogICAgfTsKCiAgICBfcHJvdG8ubm90aWZ5ID0gZnVuY3Rpb24gbm90aWZ5KGlkZW50aWZpZXIsIHZhbHVlKSB7CiAgICAgIHZhciBzdGFibGVJZGVudGlmaWVyID0gaWRlbnRpZmllckNhY2hlRm9yKHRoaXMuc3RvcmUpLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihpZGVudGlmaWVyKTsKICAgICAgdmFyIGNhbGxiYWNrID0gQ2FjaGUuZ2V0KHN0YWJsZUlkZW50aWZpZXIpOwoKICAgICAgaWYgKCFjYWxsYmFjaykgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgY2FsbGJhY2soc3RhYmxlSWRlbnRpZmllciwgdmFsdWUpOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH07CgogICAgcmV0dXJuIE5vdGlmaWNhdGlvbk1hbmFnZXI7CiAgfSgpOwoKICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyQ2KHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyQ2KENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMkNihDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDYoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIC8vIE1pbWljcyB0aGUgc3RhdGljIGFwaXMgb2YgRFNNb2RlbAogIHZhciBTaGltTW9kZWxDbGFzcyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIC8vIFRPRE8gTWF5YmUgZXhwb3NlIHRoZSBjbGFzcyBoZXJlPwogICAgZnVuY3Rpb24gU2hpbU1vZGVsQ2xhc3MoX19zdG9yZSwgbW9kZWxOYW1lKSB7CiAgICAgIHRoaXMuX19zdG9yZSA9IF9fc3RvcmU7CiAgICAgIHRoaXMubW9kZWxOYW1lID0gbW9kZWxOYW1lOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBTaGltTW9kZWxDbGFzcy5wcm90b3R5cGU7CgogICAgX3Byb3RvLmVhY2hBdHRyaWJ1dGUgPSBmdW5jdGlvbiBlYWNoQXR0cmlidXRlKGNhbGxiYWNrLCBiaW5kaW5nKSB7CiAgICAgIHZhciBhdHRyRGVmcyA9IHRoaXMuX19zdG9yZS5fYXR0cmlidXRlc0RlZmluaXRpb25Gb3IodGhpcy5tb2RlbE5hbWUpOwoKICAgICAgT2JqZWN0LmtleXMoYXR0ckRlZnMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgIGNhbGxiYWNrLmNhbGwoYmluZGluZywga2V5LCBhdHRyRGVmc1trZXldKTsKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5lYWNoUmVsYXRpb25zaGlwID0gZnVuY3Rpb24gZWFjaFJlbGF0aW9uc2hpcChjYWxsYmFjaywgYmluZGluZykgewogICAgICB2YXIgcmVsYXRpb25zaGlwRGVmcyA9IHRoaXMuX19zdG9yZS5fcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IodGhpcy5tb2RlbE5hbWUpOwoKICAgICAgT2JqZWN0LmtleXMocmVsYXRpb25zaGlwRGVmcykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgY2FsbGJhY2suY2FsbChiaW5kaW5nLCBrZXksIHJlbGF0aW9uc2hpcERlZnNba2V5XSk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8uZWFjaFRyYW5zZm9ybWVkQXR0cmlidXRlID0gZnVuY3Rpb24gZWFjaFRyYW5zZm9ybWVkQXR0cmlidXRlKGNhbGxiYWNrLCBiaW5kaW5nKSB7CiAgICAgIHZhciByZWxhdGlvbnNoaXBEZWZzID0gdGhpcy5fX3N0b3JlLl9yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcih0aGlzLm1vZGVsTmFtZSk7CgogICAgICBPYmplY3Qua2V5cyhyZWxhdGlvbnNoaXBEZWZzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICBpZiAocmVsYXRpb25zaGlwRGVmc1trZXldLnR5cGUpIHsKICAgICAgICAgIGNhbGxiYWNrLmNhbGwoYmluZGluZywga2V5LCByZWxhdGlvbnNoaXBEZWZzW2tleV0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9OwoKICAgIF9jcmVhdGVDbGFzcyQ2KFNoaW1Nb2RlbENsYXNzLCBbewogICAgICBrZXk6ICJmaWVsZHMiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICB2YXIgYXR0cnMgPSB0aGlzLl9fc3RvcmUuX2F0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKHRoaXMubW9kZWxOYW1lKTsKCiAgICAgICAgdmFyIHJlbGF0aW9uc2hpcHMgPSB0aGlzLl9fc3RvcmUuX3JlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKHRoaXMubW9kZWxOYW1lKTsKCiAgICAgICAgdmFyIGZpZWxkcyA9IG5ldyBNYXAoKTsKICAgICAgICBPYmplY3Qua2V5cyhhdHRycykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgICByZXR1cm4gZmllbGRzLnNldChrZXksICdhdHRyaWJ1dGUnKTsKICAgICAgICB9KTsKICAgICAgICBPYmplY3Qua2V5cyhyZWxhdGlvbnNoaXBzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgIHJldHVybiBmaWVsZHMuc2V0KGtleSwgcmVsYXRpb25zaGlwc1trZXldLmtpbmQpOwogICAgICAgIH0pOwogICAgICAgIHJldHVybiBmaWVsZHM7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiYXR0cmlidXRlcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBhdHRycyA9IHRoaXMuX19zdG9yZS5fYXR0cmlidXRlc0RlZmluaXRpb25Gb3IodGhpcy5tb2RlbE5hbWUpOwoKICAgICAgICByZXR1cm4gbmV3IE1hcChPYmplY3QuZW50cmllcyhhdHRycykpOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInJlbGF0aW9uc2hpcHNCeU5hbWUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICB2YXIgcmVsYXRpb25zaGlwcyA9IHRoaXMuX19zdG9yZS5fcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IodGhpcy5tb2RlbE5hbWUpOwoKICAgICAgICByZXR1cm4gbmV3IE1hcChPYmplY3QuZW50cmllcyhyZWxhdGlvbnNoaXBzKSk7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gU2hpbU1vZGVsQ2xhc3M7CiAgfSgpOwoKICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyQ3KHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyQ3KENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMkNyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDcoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIGZ1bmN0aW9uIF9hc3NlcnRUaGlzSW5pdGlhbGl6ZWQoc2VsZikgeyBpZiAoc2VsZiA9PT0gdm9pZCAwKSB7IHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcigidGhpcyBoYXNuJ3QgYmVlbiBpbml0aWFsaXNlZCAtIHN1cGVyKCkgaGFzbid0IGJlZW4gY2FsbGVkIik7IH0gcmV0dXJuIHNlbGY7IH0KCiAgZnVuY3Rpb24gX2luaGVyaXRzTG9vc2UkMyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MucHJvdG90eXBlKTsgc3ViQ2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gc3ViQ2xhc3M7IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH0KICB2YXIgZW1iZXJSdW4kMiA9IEVtYmVyLnJ1bi5iYWNrYnVybmVyOwogIHZhciBFTlYgPSBFbWJlci5FTlY7CiAgdmFyIEhBU19TRVJJQUxJWkVSX1BBQ0tBR0UgPSByZXF1aXJlLmhhcygnQGVtYmVyLWRhdGEvc2VyaWFsaXplcicpOwogIHZhciBIQVNfQURBUFRFUl9QQUNLQUdFID0gcmVxdWlyZS5oYXMoJ0BlbWJlci1kYXRhL2FkYXB0ZXInKTsKICB2YXIgSEFTX01PREVMX1BBQ0tBR0UgPSByZXF1aXJlLmhhcygnQGVtYmVyLWRhdGEvbW9kZWwnKTsKCiAgdmFyIF9Nb2RlbDsKCiAgZnVuY3Rpb24gZ2V0TW9kZWwoKSB7CiAgICBpZiAoSEFTX01PREVMX1BBQ0tBR0UpIHsKICAgICAgX01vZGVsID0gX01vZGVsIHx8IHJlcXVpcmVfX2RlZmF1bHQoJ0BlbWJlci1kYXRhL21vZGVsJykuZGVmYXVsdDsKICAgIH0KCiAgICByZXR1cm4gX01vZGVsOwogIH0KICAvKioKICAgIFRoZSBzdG9yZSBjb250YWlucyBhbGwgb2YgdGhlIGRhdGEgZm9yIHJlY29yZHMgbG9hZGVkIGZyb20gdGhlIHNlcnZlci4KICAgIEl0IGlzIGFsc28gcmVzcG9uc2libGUgZm9yIGNyZWF0aW5nIGluc3RhbmNlcyBvZiBgTW9kZWxgIHRoYXQgd3JhcAogICAgdGhlIGluZGl2aWR1YWwgZGF0YSBmb3IgYSByZWNvcmQsIHNvIHRoYXQgdGhleSBjYW4gYmUgYm91bmQgdG8gaW4geW91cgogICAgSGFuZGxlYmFycyB0ZW1wbGF0ZXMuCgogICAgRGVmaW5lIHlvdXIgYXBwbGljYXRpb24ncyBzdG9yZSBsaWtlIHRoaXM6CgogICAgYGBgYXBwL3NlcnZpY2VzL3N0b3JlLmpzCiAgICBpbXBvcnQgU3RvcmUgZnJvbSAnQGVtYmVyLWRhdGEvc3RvcmUnOwoKICAgIGV4cG9ydCBkZWZhdWx0IFN0b3JlLmV4dGVuZCh7CiAgICB9KTsKICAgIGBgYAoKICAgIE1vc3QgRW1iZXIuanMgYXBwbGljYXRpb25zIHdpbGwgb25seSBoYXZlIGEgc2luZ2xlIGBTdG9yZWAgdGhhdCBpcwogICAgYXV0b21hdGljYWxseSBjcmVhdGVkIGJ5IHRoZWlyIGBFbWJlci5BcHBsaWNhdGlvbmAuCgogICAgWW91IGNhbiByZXRyaWV2ZSBtb2RlbHMgZnJvbSB0aGUgc3RvcmUgaW4gc2V2ZXJhbCB3YXlzLiBUbyByZXRyaWV2ZSBhIHJlY29yZAogICAgZm9yIGEgc3BlY2lmaWMgaWQsIHVzZSBgU3RvcmVgJ3MgYGZpbmRSZWNvcmQoKWAgbWV0aG9kOgoKICAgIGBgYGphdmFzY3JpcHQKICAgIHN0b3JlLmZpbmRSZWNvcmQoJ3BlcnNvbicsIDEyMykudGhlbihmdW5jdGlvbiAocGVyc29uKSB7CiAgICB9KTsKICAgIGBgYAoKICAgIEJ5IGRlZmF1bHQsIHRoZSBzdG9yZSB3aWxsIHRhbGsgdG8geW91ciBiYWNrZW5kIHVzaW5nIGEgc3RhbmRhcmQKICAgIFJFU1QgbWVjaGFuaXNtLiBZb3UgY2FuIGN1c3RvbWl6ZSBob3cgdGhlIHN0b3JlIHRhbGtzIHRvIHlvdXIKICAgIGJhY2tlbmQgYnkgc3BlY2lmeWluZyBhIGN1c3RvbSBhZGFwdGVyOgoKICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CgogICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlci5leHRlbmQoewogICAgfSk7CiAgICBgYGAKCiAgICBZb3UgY2FuIGxlYXJuIG1vcmUgYWJvdXQgd3JpdGluZyBhIGN1c3RvbSBhZGFwdGVyIGJ5IHJlYWRpbmcgdGhlIGBBZGFwdGVyYAogICAgZG9jdW1lbnRhdGlvbi4KCiAgICAjIyMgU3RvcmUgY3JlYXRlUmVjb3JkKCkgdnMuIHB1c2goKSB2cy4gcHVzaFBheWxvYWQoKQoKICAgIFRoZSBzdG9yZSBwcm92aWRlcyBtdWx0aXBsZSB3YXlzIHRvIGNyZWF0ZSBuZXcgcmVjb3JkIG9iamVjdHMuIFRoZXkgaGF2ZQogICAgc29tZSBzdWJ0bGUgZGlmZmVyZW5jZXMgaW4gdGhlaXIgdXNlIHdoaWNoIGFyZSBkZXRhaWxlZCBiZWxvdzoKCiAgICBbY3JlYXRlUmVjb3JkXShTdG9yZS9tZXRob2RzL2NyZWF0ZVJlY29yZD9hbmNob3I9Y3JlYXRlUmVjb3JkKSBpcyB1c2VkIGZvciBjcmVhdGluZyBuZXcKICAgIHJlY29yZHMgb24gdGhlIGNsaWVudCBzaWRlLiBUaGlzIHdpbGwgcmV0dXJuIGEgbmV3IHJlY29yZCBpbiB0aGUKICAgIGBjcmVhdGVkLnVuY29tbWl0dGVkYCBzdGF0ZS4gSW4gb3JkZXIgdG8gcGVyc2lzdCB0aGlzIHJlY29yZCB0byB0aGUKICAgIGJhY2tlbmQsIHlvdSB3aWxsIG5lZWQgdG8gY2FsbCBgcmVjb3JkLnNhdmUoKWAuCgogICAgW3B1c2hdKFN0b3JlL21ldGhvZHMvcHVzaD9hbmNob3I9cHVzaCkgaXMgdXNlZCB0byBub3RpZnkgRW1iZXIgRGF0YSdzIHN0b3JlIG9mIG5ldyBvcgogICAgdXBkYXRlZCByZWNvcmRzIHRoYXQgZXhpc3QgaW4gdGhlIGJhY2tlbmQuIFRoaXMgd2lsbCByZXR1cm4gYSByZWNvcmQKICAgIGluIHRoZSBgbG9hZGVkLnNhdmVkYCBzdGF0ZS4gVGhlIHByaW1hcnkgdXNlLWNhc2UgZm9yIGBzdG9yZSNwdXNoYCBpcwogICAgdG8gbm90aWZ5IEVtYmVyIERhdGEgYWJvdXQgcmVjb3JkIHVwZGF0ZXMgKGZ1bGwgb3IgcGFydGlhbCkgdGhhdCBoYXBwZW4KICAgIG91dHNpZGUgb2YgdGhlIG5vcm1hbCBhZGFwdGVyIG1ldGhvZHMgKGZvciBleGFtcGxlCiAgICBbU1NFXShodHRwOi8vZGV2LnczLm9yZy9odG1sNS9ldmVudHNvdXJjZS8pIG9yIFtXZWIKICAgIFNvY2tldHNdKGh0dHA6Ly93d3cudzMub3JnL1RSLzIwMDkvV0Qtd2Vic29ja2V0cy0yMDA5MTIyMi8pKS4KCiAgICBbcHVzaFBheWxvYWRdKFN0b3JlL21ldGhvZHMvcHVzaFBheWxvYWQ/YW5jaG9yPXB1c2hQYXlsb2FkKSBpcyBhIGNvbnZlbmllbmNlIHdyYXBwZXIgZm9yCiAgICBgc3RvcmUjcHVzaGAgdGhhdCB3aWxsIGRlc2VyaWFsaXplIHBheWxvYWRzIGlmIHRoZQogICAgU2VyaWFsaXplciBpbXBsZW1lbnRzIGEgYHB1c2hQYXlsb2FkYCBtZXRob2QuCgogICAgTm90ZTogV2hlbiBjcmVhdGluZyBhIG5ldyByZWNvcmQgdXNpbmcgYW55IG9mIHRoZSBhYm92ZSBtZXRob2RzCiAgICBFbWJlciBEYXRhIHdpbGwgdXBkYXRlIGBSZWNvcmRBcnJheWBzIHN1Y2ggYXMgdGhvc2UgcmV0dXJuZWQgYnkKICAgIGBzdG9yZSNwZWVrQWxsKClgIG9yIGBzdG9yZSNmaW5kQWxsKClgLiBUaGlzIG1lYW5zIGFueQogICAgZGF0YSBiaW5kaW5ncyBvciBjb21wdXRlZCBwcm9wZXJ0aWVzIHRoYXQgZGVwZW5kIG9uIHRoZSBSZWNvcmRBcnJheQogICAgd2lsbCBhdXRvbWF0aWNhbGx5IGJlIHN5bmNlZCB0byBpbmNsdWRlIHRoZSBuZXcgb3IgdXBkYXRlZCByZWNvcmQKICAgIHZhbHVlcy4KCiAgICBAY2xhc3MgU3RvcmUKICAgIEBleHRlbmRzIEVtYmVyLlNlcnZpY2UKICAqLwoKCiAgdmFyIENvcmVTdG9yZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW1iZXJTZXJ2aWNlKSB7CiAgICBfaW5oZXJpdHNMb29zZSQzKENvcmVTdG9yZSwgX0VtYmVyU2VydmljZSk7CgogICAgLyoqCiAgICAgKiBFbWJlckRhdGEgc3BlY2lmaWMgYmFja2J1cm5lciBpbnN0YW5jZQogICAgICovCgogICAgLyoKICAgICAgRW1iZXIgRGF0YSB1c2VzIHNldmVyYWwgc3BlY2lhbGl6ZWQgbWljcm8tcXVldWVzIGZvciBvcmdhbml6aW5nCiAgICAgIGFuZCBjb2FsZXNjaW5nIHNpbWlsYXIgYXN5bmMgd29yay4KICAgICAgIFRoZXNlIHF1ZXVlcyBhcmUgY3VycmVudGx5IGNvbnRyb2xsZWQgYnkgYSBmbHVzaCBzY2hlZHVsZWQgaW50bwogICAgICBlbWJlci1kYXRhJ3MgY3VzdG9tIGJhY2tidXJuZXIgaW5zdGFuY2UuCiAgICAgICovCiAgICAvLyB1c2VkIGZvciBjb2FsZXNjaW5nIHJlY29yZCBzYXZlIHJlcXVlc3RzCiAgICAvLyB1c2VkIGZvciBjb2FsZXNjaW5nIHJlbGF0aW9uc2hpcCB1cGRhdGVzCiAgICAvLyB1c2VkIGZvciBjb2FsZXNjaW5nIGludGVybmFsIG1vZGVsIHVwZGF0ZXMKICAgIC8vIHVzZWQgdG8ga2VlcCB0cmFjayBvZiBhbGwgdGhlIGZpbmQgcmVxdWVzdHMgdGhhdCBuZWVkIHRvIGJlIGNvYWxlc2NlZAogICAgLy8gREVCVUctb25seSBwcm9wZXJ0aWVzCgogICAgLyoqCiAgICAgIFRoZSBkZWZhdWx0IGFkYXB0ZXIgdG8gdXNlIHRvIGNvbW11bmljYXRlIHRvIGEgYmFja2VuZCBzZXJ2ZXIgb3IKICAgICAgb3RoZXIgcGVyc2lzdGVuY2UgbGF5ZXIuIFRoaXMgd2lsbCBiZSBvdmVycmlkZGVuIGJ5IGFuIGFwcGxpY2F0aW9uCiAgICAgIGFkYXB0ZXIgaWYgcHJlc2VudC4KICAgICAgIElmIHlvdSB3YW50IHRvIHNwZWNpZnkgYGFwcC9hZGFwdGVycy9jdXN0b20uanNgIGFzIGEgc3RyaW5nLCBkbzoKICAgICAgIGBgYGpzCiAgICAgIGltcG9ydCBTdG9yZSBmcm9tICdAZW1iZXItZGF0YS9zdG9yZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBTdG9yZS5leHRlbmQoewogICAgICAgIGluaXQoKSB7CiAgICAgICAgICB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogICAgICAgICAgdGhpcy5hZGFwdGVyID0gJ2N1c3RvbSc7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAcHJvcGVydHkgYWRhcHRlcgogICAgICBAZGVmYXVsdCAnLWpzb24tYXBpJwogICAgICBAdHlwZSB7U3RyaW5nfQogICAgKi8KCiAgICAvKioKICAgIFRoaXMgcHJvcGVydHkgcmV0dXJucyB0aGUgYWRhcHRlciwgYWZ0ZXIgcmVzb2x2aW5nIGEgcG9zc2libGUKICAgIHN0cmluZyBrZXkuCiAgICAgSWYgdGhlIHN1cHBsaWVkIGBhZGFwdGVyYCB3YXMgYSBjbGFzcywgb3IgYSBTdHJpbmcgcHJvcGVydHkKICAgIHBhdGggcmVzb2x2ZWQgdG8gYSBjbGFzcywgdGhpcyBwcm9wZXJ0eSB3aWxsIGluc3RhbnRpYXRlIHRoZQogICAgY2xhc3MuCiAgICAgVGhpcyBwcm9wZXJ0eSBpcyBjYWNoZWFibGUsIHNvIHRoZSBzYW1lIGluc3RhbmNlIG9mIGEgc3BlY2lmaWVkCiAgICBhZGFwdGVyIGNsYXNzIHNob3VsZCBiZSB1c2VkIGZvciB0aGUgbGlmZXRpbWUgb2YgdGhlIHN0b3JlLgogICAgIEBwcm9wZXJ0eSBkZWZhdWx0QWRhcHRlcgogICAgQHByaXZhdGUKICAgIEByZXR1cm4gQWRhcHRlcgogICAgKi8KCiAgICAvKioKICAgICAgQG1ldGhvZCBpbml0CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgZnVuY3Rpb24gQ29yZVN0b3JlKCkgewogICAgICB2YXIgX3RoaXM7CgogICAgICBfdGhpcyA9IF9FbWJlclNlcnZpY2UuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpcy5fYmFja2J1cm5lciA9IGJhY2tidXJuZXI7CiAgICAgIF90aGlzLnJlY29yZEFycmF5TWFuYWdlciA9IG5ldyBSZWNvcmRBcnJheU1hbmFnZXIoewogICAgICAgIHN0b3JlOiBfYXNzZXJ0VGhpc0luaXRpYWxpemVkKF90aGlzKQogICAgICB9KTsKICAgICAgX3RoaXMuX25vdGlmaWNhdGlvbk1hbmFnZXIgPSB2b2lkIDA7CiAgICAgIF90aGlzLl9hZGFwdGVyQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBfdGhpcy5fc2VyaWFsaXplckNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgX3RoaXMuX3N0b3JlV3JhcHBlciA9IG5ldyBSZWNvcmREYXRhU3RvcmVXcmFwcGVyKF9hc3NlcnRUaGlzSW5pdGlhbGl6ZWQoX3RoaXMpKTsKICAgICAgX3RoaXMuX3BlbmRpbmdTYXZlID0gW107CiAgICAgIF90aGlzLl91cGRhdGVkUmVsYXRpb25zaGlwcyA9IFtdOwogICAgICBfdGhpcy5fdXBkYXRlZEludGVybmFsTW9kZWxzID0gW107CiAgICAgIF90aGlzLl9wZW5kaW5nRmV0Y2ggPSBuZXcgTWFwKCk7CiAgICAgIF90aGlzLl9mZXRjaE1hbmFnZXIgPSB2b2lkIDA7CiAgICAgIF90aGlzLl9zY2hlbWFEZWZpbml0aW9uU2VydmljZSA9IHZvaWQgMDsKICAgICAgX3RoaXMuX3RyYWNrZWRBc3luY1JlcXVlc3RzID0gdm9pZCAwOwogICAgICBfdGhpcy5zaG91bGRBc3NlcnRNZXRob2RDYWxsc09uRGVzdHJveWVkU3RvcmUgPSBmYWxzZTsKICAgICAgX3RoaXMuc2hvdWxkVHJhY2tBc3luY1JlcXVlc3RzID0gZmFsc2U7CiAgICAgIF90aGlzLmdlbmVyYXRlU3RhY2tUcmFjZXNGb3JUcmFja2VkUmVxdWVzdHMgPSBmYWxzZTsKICAgICAgX3RoaXMuX3RyYWNrQXN5bmNSZXF1ZXN0U3RhcnQgPSB2b2lkIDA7CiAgICAgIF90aGlzLl90cmFja0FzeW5jUmVxdWVzdEVuZCA9IHZvaWQgMDsKICAgICAgX3RoaXMuX19hc3luY1dhaXRlciA9IHZvaWQgMDsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICBfdGhpcy5fZmV0Y2hNYW5hZ2VyID0gbmV3IEZldGNoTWFuYWdlcihfYXNzZXJ0VGhpc0luaXRpYWxpemVkKF90aGlzKSk7CiAgICAgIH0KCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICBfdGhpcy5fbm90aWZpY2F0aW9uTWFuYWdlciA9IG5ldyBOb3RpZmljYXRpb25NYW5hZ2VyKF9hc3NlcnRUaGlzSW5pdGlhbGl6ZWQoX3RoaXMpKTsKICAgICAgICBfdGhpcy5fX3JlY29yZERhdGFGb3IgPSBfdGhpcy5fX3JlY29yZERhdGFGb3IuYmluZChfYXNzZXJ0VGhpc0luaXRpYWxpemVkKF90aGlzKSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gQ29yZVN0b3JlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uZ2V0UmVxdWVzdFN0YXRlU2VydmljZSA9IGZ1bmN0aW9uIGdldFJlcXVlc3RTdGF0ZVNlcnZpY2UoKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICByZXR1cm4gdGhpcy5fZmV0Y2hNYW5hZ2VyLnJlcXVlc3RDYWNoZTsKICAgICAgfQoKICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZXF1ZXN0U2VydmljZSBpcyBub3QgYXZhaWxhYmxlIHVubGVzcyB0aGUgZmVhdHVyZSBmbGFnIGlzIG9uIGFuZCBydW5uaW5nIG9uIGEgY2FuYXJ5IGJ1aWxkJyk7CiAgICB9OwoKICAgIF9wcm90by5faW5zdGFudGlhdGVSZWNvcmQgPSBmdW5jdGlvbiBfaW5zdGFudGlhdGVSZWNvcmQoaW50ZXJuYWxNb2RlbCwgbW9kZWxOYW1lLCByZWNvcmREYXRhLCBpZGVudGlmaWVyLCBwcm9wZXJ0aWVzKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICAvLyBhc3NlcnQgaGVyZQogICAgICAgIGlmIChwcm9wZXJ0aWVzICE9PSB1bmRlZmluZWQpIHsKCiAgICAgICAgICBpZiAoJ2lkJyBpbiBwcm9wZXJ0aWVzKSB7CiAgICAgICAgICAgIGludGVybmFsTW9kZWwuc2V0SWQocHJvcGVydGllcy5pZCk7CiAgICAgICAgICB9IC8vIGNvbnZlcnQgcmVsYXRpb25zaGlwIFJlY29yZHMgdG8gUmVjb3JkRGF0YXMgYmVmb3JlIHBhc3NpbmcgdG8gUmVjb3JkRGF0YQoKCiAgICAgICAgICB2YXIgZGVmcyA9IHRoaXMuX3JlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKG1vZGVsTmFtZSk7CgogICAgICAgICAgaWYgKGRlZnMgIT09IG51bGwpIHsKICAgICAgICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKTsKICAgICAgICAgICAgdmFyIHJlbGF0aW9uc2hpcFZhbHVlOwoKICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgdmFyIHByb3AgPSBrZXlzW2ldOwogICAgICAgICAgICAgIHZhciBkZWYgPSBkZWZzW3Byb3BdOwoKICAgICAgICAgICAgICBpZiAoZGVmICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgIGlmIChkZWYua2luZCA9PT0gJ2hhc01hbnknKSB7CgogICAgICAgICAgICAgICAgICByZWxhdGlvbnNoaXBWYWx1ZSA9IGV4dHJhY3RSZWNvcmREYXRhc0Zyb21SZWNvcmRzKHByb3BlcnRpZXNbcHJvcF0pOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgcmVsYXRpb25zaGlwVmFsdWUgPSBleHRyYWN0UmVjb3JkRGF0YUZyb21SZWNvcmQocHJvcGVydGllc1twcm9wXSk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgcHJvcGVydGllc1twcm9wXSA9IHJlbGF0aW9uc2hpcFZhbHVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0gLy8gVE9ETyBndWFyZCBhZ2FpbnN0IGluaXRSZWNvcmRPcHRpb25zIG5vIGJlaW5nIHRoZXJlCgoKICAgICAgICB2YXIgY3JlYXRlT3B0aW9ucyA9IHJlY29yZERhdGEuX2luaXRSZWNvcmRDcmVhdGVPcHRpb25zKHByb3BlcnRpZXMpOyAvL1RPRE8gSWdvciBwYXNzIGEgd3JhcHBlciBpbnN0ZWFkIG9mIFJECgoKICAgICAgICB2YXIgX3JlY29yZCA9IHRoaXMuaW5zdGFudGlhdGVSZWNvcmQoaWRlbnRpZmllciwgY3JlYXRlT3B0aW9ucywgdGhpcy5fX3JlY29yZERhdGFGb3IsIHRoaXMuX25vdGlmaWNhdGlvbk1hbmFnZXIpOwoKICAgICAgICBzZXRSZWNvcmRJZGVudGlmaWVyKF9yZWNvcmQsIGlkZW50aWZpZXIpOyAvL3JlY29yZFRvSW50ZXJuYWxNb2RlbE1hcC5zZXQocmVjb3JkLCBpbnRlcm5hbE1vZGVsKTsKCiAgICAgICAgcmV0dXJuIF9yZWNvcmQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdzaG91bGQgbm90IGJlIGhlcmUsIGN1c3RvbSBtb2RlbCBjbGFzcyBmZiBlcnJvcicpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5faW50ZXJuYWxEZWxldGVSZWNvcmQgPSBmdW5jdGlvbiBfaW50ZXJuYWxEZWxldGVSZWNvcmQoaW50ZXJuYWxNb2RlbCkgewogICAgICBpbnRlcm5hbE1vZGVsLmRlbGV0ZVJlY29yZCgpOwogICAgfSAvLyBGZWF0dXJlRmxhZ2dlZCBpbiB0aGUgRFNNb2RlbFN0b3JlIGNsYWFzCiAgICA7CgogICAgX3Byb3RvLl9hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvciA9IGZ1bmN0aW9uIF9hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvcihtb2RlbE5hbWUsIGlkZW50aWZpZXIpIHsKICAgICAgaWYgKGlkZW50aWZpZXIpIHsKICAgICAgICByZXR1cm4gdGhpcy5nZXRTY2hlbWFEZWZpbml0aW9uU2VydmljZSgpLmF0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKGlkZW50aWZpZXIpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0aGlzLmdldFNjaGVtYURlZmluaXRpb25TZXJ2aWNlKCkuYXR0cmlidXRlc0RlZmluaXRpb25Gb3IobW9kZWxOYW1lKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX3JlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yID0gZnVuY3Rpb24gX3JlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKG1vZGVsTmFtZSwgaWRlbnRpZmllcikgewogICAgICBpZiAoaWRlbnRpZmllcikgewogICAgICAgIHJldHVybiB0aGlzLmdldFNjaGVtYURlZmluaXRpb25TZXJ2aWNlKCkucmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IoaWRlbnRpZmllcik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UoKS5yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcihtb2RlbE5hbWUpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZWdpc3RlclNjaGVtYURlZmluaXRpb25TZXJ2aWNlID0gZnVuY3Rpb24gcmVnaXN0ZXJTY2hlbWFEZWZpbml0aW9uU2VydmljZShzY2hlbWEpIHsKICAgICAgdGhpcy5fc2NoZW1hRGVmaW5pdGlvblNlcnZpY2UgPSBzY2hlbWE7CiAgICB9OwoKICAgIF9wcm90by5nZXRTY2hlbWFEZWZpbml0aW9uU2VydmljZSA9IGZ1bmN0aW9uIGdldFNjaGVtYURlZmluaXRpb25TZXJ2aWNlKCkgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3NjaGVtYURlZmluaXRpb25TZXJ2aWNlOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcignbmVlZCB0byBlbmFibGUgQ1VTVE9NX01PREVMX0NMQVNTIGZlYXR1cmUgZmxhZyBpbiBvcmRlciB0byBhY2Nlc3MgU2NoZW1hRGVmaW5pdGlvblNlcnZpY2UnKTsKICAgICAgfQogICAgfSAvLyBUT0RPIERvdWJsZSBjaGVjayB0aGlzIHJldHVybiB2YWx1ZSBpcyBjb3JyZWN0CiAgICA7CgogICAgX3Byb3RvLl9yZWxhdGlvbnNoaXBNZXRhRm9yID0gZnVuY3Rpb24gX3JlbGF0aW9uc2hpcE1ldGFGb3IobW9kZWxOYW1lLCBpZCwga2V5KSB7CiAgICAgIHJldHVybiB0aGlzLl9yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcihtb2RlbE5hbWUpW2tleV07CiAgICB9OwoKICAgIF9wcm90by5tb2RlbEZvciA9IGZ1bmN0aW9uIG1vZGVsRm9yKG1vZGVsTmFtZSkgewoKICAgICAgcmV0dXJuIG5ldyBTaGltTW9kZWxDbGFzcyh0aGlzLCBtb2RlbE5hbWUpOwogICAgfSAvLyBGZWF0dXJlIEZsYWdnZWQgaW4gRFNNb2RlbFN0b3JlCgogICAgLyoKICAgIFJldHVybnMgd2hldGhlciBhIE1vZGVsQ2xhc3MgZXhpc3RzIGZvciBhIGdpdmVuIG1vZGVsTmFtZQogICAgVGhpcyBleGlzdHMgZm9yIGxlZ2FjeSBzdXBwb3J0IGZvciB0aGUgUkVTVFNlcmlhbGl6ZXIsCiAgICB3aGljaCBkdWUgdG8gaG93IGl0IG11c3QgZ3Vlc3Mgd2hldGhlciBhIGtleSBpcyBhIG1vZGVsCiAgICBtdXN0IHF1ZXJ5IGZvciB3aGV0aGVyIGEgbWF0Y2ggZXhpc3RzLgogICAgIFdlIHNob3VsZCBpbnZlc3RpZ2F0ZSBhbiBSRkMgdG8gbWFrZSB0aGlzIHB1YmxpYyBvciByZW1vdmluZwogICAgdGhpcyByZXF1aXJlbWVudC4KICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX2hhc01vZGVsRm9yID0gZnVuY3Rpb24gX2hhc01vZGVsRm9yKG1vZGVsTmFtZSkgewogICAgICByZXR1cm4gdGhpcy5nZXRTY2hlbWFEZWZpbml0aW9uU2VydmljZSgpLmRvZXNUeXBlRXhpc3QobW9kZWxOYW1lKTsKICAgIH0gLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uCiAgICAvLyAuIENSRUFURSBORVcgUkVDT1JEIC4KICAgIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLgoKICAgIC8qKgogICAgICBDcmVhdGUgYSBuZXcgcmVjb3JkIGluIHRoZSBjdXJyZW50IHN0b3JlLiBUaGUgcHJvcGVydGllcyBwYXNzZWQKICAgICAgdG8gdGhpcyBtZXRob2QgYXJlIHNldCBvbiB0aGUgbmV3bHkgY3JlYXRlZCByZWNvcmQuCiAgICAgICBUbyBjcmVhdGUgYSBuZXcgaW5zdGFuY2Ugb2YgYSBgUG9zdGA6CiAgICAgICBgYGBqcwogICAgICBzdG9yZS5jcmVhdGVSZWNvcmQoJ3Bvc3QnLCB7CiAgICAgICAgdGl0bGU6ICdFbWJlciBpcyBhd2Vzb21lIScKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVG8gY3JlYXRlIGEgbmV3IGluc3RhbmNlIG9mIGEgYFBvc3RgIHRoYXQgaGFzIGEgcmVsYXRpb25zaGlwIHdpdGggYSBgVXNlcmAgcmVjb3JkOgogICAgICAgYGBganMKICAgICAgbGV0IHVzZXIgPSB0aGlzLnN0b3JlLnBlZWtSZWNvcmQoJ3VzZXInLCAxKTsKICAgICAgc3RvcmUuY3JlYXRlUmVjb3JkKCdwb3N0JywgewogICAgICAgIHRpdGxlOiAnRW1iZXIgaXMgYXdlc29tZSEnLAogICAgICAgIHVzZXI6IHVzZXIKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBjcmVhdGVSZWNvcmQKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0ge09iamVjdH0gaW5wdXRQcm9wZXJ0aWVzIGEgaGFzaCBvZiBwcm9wZXJ0aWVzIHRvIHNldCBvbiB0aGUKICAgICAgICBuZXdseSBjcmVhdGVkIHJlY29yZC4KICAgICAgQHJldHVybiB7TW9kZWx9IHJlY29yZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uY3JlYXRlUmVjb3JkID0gZnVuY3Rpb24gY3JlYXRlUmVjb3JkKG1vZGVsTmFtZSwgaW5wdXRQcm9wZXJ0aWVzKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwogICAgICAvLyAgIGNhbGxzIHRvIGBjcmVhdGVSZWNvcmRgLiBUaGUgcnVuIGxvb3AgdXNhZ2UgaGVyZSBpcyBiZWNhdXNlIHdlIGJhdGNoIHRoZSBqb2luaW5nIGFuZCB1cGRhdGluZwogICAgICAvLyAgIG9mIHJlY29yZC1hcnJheXMgdmlhIGVtYmVyJ3MgcnVuIGxvb3AsIG5vdCBvdXIgb3duLgogICAgICAvLwogICAgICAvLyAgIHRvIHJlbW92ZSB0aGlzLCB3ZSB3b3VsZCBuZWVkIHRvIG1vdmUgdG8gYSBuZXcgYGFzeW5jYCBBUEkuCgogICAgICByZXR1cm4gZW1iZXJSdW4kMi5qb2luKGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gX3RoaXMyLl9iYWNrYnVybmVyLmpvaW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgICAgIHZhciBwcm9wZXJ0aWVzID0gRW1iZXIuYXNzaWduKHt9LCBpbnB1dFByb3BlcnRpZXMpOyAvLyBJZiB0aGUgcGFzc2VkIHByb3BlcnRpZXMgZG8gbm90IGluY2x1ZGUgYSBwcmltYXJ5IGtleSwKICAgICAgICAgIC8vIGdpdmUgdGhlIGFkYXB0ZXIgYW4gb3Bwb3J0dW5pdHkgdG8gZ2VuZXJhdGUgb25lLiBUeXBpY2FsbHksCiAgICAgICAgICAvLyBjbGllbnQtc2lkZSBJRCBnZW5lcmF0b3JzIHdpbGwgdXNlIHNvbWV0aGluZyBsaWtlIHV1aWQuanMKICAgICAgICAgIC8vIHRvIGF2b2lkIGNvbmZsaWN0cy4KCiAgICAgICAgICBpZiAoRW1iZXIuaXNOb25lKHByb3BlcnRpZXMuaWQpKSB7CiAgICAgICAgICAgIHByb3BlcnRpZXMuaWQgPSBfdGhpczIuX2dlbmVyYXRlSWQobm9ybWFsaXplZE1vZGVsTmFtZSwgcHJvcGVydGllcyk7CiAgICAgICAgICB9IC8vIENvZXJjZSBJRCB0byBhIHN0cmluZwoKCiAgICAgICAgICBwcm9wZXJ0aWVzLmlkID0gY29lcmNlSWQocHJvcGVydGllcy5pZCk7CiAgICAgICAgICB2YXIgZmFjdG9yeSA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKF90aGlzMik7CiAgICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGZhY3RvcnkuYnVpbGQoewogICAgICAgICAgICB0eXBlOiBub3JtYWxpemVkTW9kZWxOYW1lLAogICAgICAgICAgICBpZDogcHJvcGVydGllcy5pZAogICAgICAgICAgfSk7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLmxvYWRlZERhdGEoKTsgLy8gVE9ETyB0aGlzIGV4aXN0cyBqdXN0IHRvIHByb3h5IGBpc05ld2AgdG8gUmVjb3JkRGF0YSB3aGljaCBpcyB3ZWlyZAoKICAgICAgICAgIGludGVybmFsTW9kZWwuZGlkQ3JlYXRlUmVjb3JkKCk7CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5nZXRSZWNvcmQocHJvcGVydGllcyk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfQogICAgLyoqCiAgICAgIElmIHBvc3NpYmxlLCB0aGlzIG1ldGhvZCBhc2tzIHRoZSBhZGFwdGVyIHRvIGdlbmVyYXRlIGFuIElEIGZvcgogICAgICBhIG5ld2x5IGNyZWF0ZWQgcmVjb3JkLgogICAgICAgQG1ldGhvZCBfZ2VuZXJhdGVJZAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwcm9wZXJ0aWVzIGZyb20gdGhlIG5ldyByZWNvcmQKICAgICAgQHJldHVybiB7U3RyaW5nfSBpZiB0aGUgYWRhcHRlciBjYW4gZ2VuZXJhdGUgb25lLCBhbiBJRAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX2dlbmVyYXRlSWQgPSBmdW5jdGlvbiBfZ2VuZXJhdGVJZChtb2RlbE5hbWUsIHByb3BlcnRpZXMpIHsKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXJGb3IobW9kZWxOYW1lKTsKCiAgICAgIGlmIChhZGFwdGVyICYmIGFkYXB0ZXIuZ2VuZXJhdGVJZEZvclJlY29yZCkgewogICAgICAgIHJldHVybiBhZGFwdGVyLmdlbmVyYXRlSWRGb3JSZWNvcmQodGhpcywgbW9kZWxOYW1lLCBwcm9wZXJ0aWVzKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG51bGw7CiAgICB9IC8vIC4uLi4uLi4uLi4uLi4uLi4uCiAgICAvLyAuIERFTEVURSBSRUNPUkQgLgogICAgLy8gLi4uLi4uLi4uLi4uLi4uLi4KCiAgICAvKioKICAgICAgRm9yIHN5bW1ldHJ5LCBhIHJlY29yZCBjYW4gYmUgZGVsZXRlZCB2aWEgdGhlIHN0b3JlLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgcG9zdCA9IHN0b3JlLmNyZWF0ZVJlY29yZCgncG9zdCcsIHsKICAgICAgICB0aXRsZTogJ0VtYmVyIGlzIGF3ZXNvbWUhJwogICAgICB9KTsKICAgICAgIHN0b3JlLmRlbGV0ZVJlY29yZChwb3N0KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGRlbGV0ZVJlY29yZAogICAgICBAcGFyYW0ge01vZGVsfSByZWNvcmQKICAgICovCiAgICA7CgogICAgX3Byb3RvLmRlbGV0ZVJlY29yZCA9IGZ1bmN0aW9uIGRlbGV0ZVJlY29yZChyZWNvcmQpIHsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICBpZiAoSEFTX01PREVMX1BBQ0tBR0UgJiYgcmVjb3JkIGluc3RhbmNlb2YgZ2V0TW9kZWwoKSkgewogICAgICAgICAgcmV0dXJuIHJlY29yZC5kZWxldGVSZWNvcmQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFyIF9pZGVudGlmaWVyID0gcmVjb3JkSWRlbnRpZmllckZvcihyZWNvcmQpOwoKICAgICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcykucGVlayhfaWRlbnRpZmllcik7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLmRlbGV0ZVJlY29yZCgpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICByZWNvcmQuZGVsZXRlUmVjb3JkKCk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBGb3Igc3ltbWV0cnksIGEgcmVjb3JkIGNhbiBiZSB1bmxvYWRlZCB2aWEgdGhlIHN0b3JlLgogICAgICBUaGlzIHdpbGwgY2F1c2UgdGhlIHJlY29yZCB0byBiZSBkZXN0cm95ZWQgYW5kIGZyZWVkIHVwIGZvciBnYXJiYWdlIGNvbGxlY3Rpb24uCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0b3JlLmZpbmRSZWNvcmQoJ3Bvc3QnLCAxKS50aGVuKGZ1bmN0aW9uKHBvc3QpIHsKICAgICAgICBzdG9yZS51bmxvYWRSZWNvcmQocG9zdCk7CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgdW5sb2FkUmVjb3JkCiAgICAgIEBwYXJhbSB7TW9kZWx9IHJlY29yZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8udW5sb2FkUmVjb3JkID0gZnVuY3Rpb24gdW5sb2FkUmVjb3JkKHJlY29yZCkgewoKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgIGlmIChIQVNfTU9ERUxfUEFDS0FHRSAmJiByZWNvcmQgaW5zdGFuY2VvZiBnZXRNb2RlbCgpKSB7CiAgICAgICAgICByZXR1cm4gcmVjb3JkLnVubG9hZFJlY29yZCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB2YXIgX2lkZW50aWZpZXIyID0gcmVjb3JkSWRlbnRpZmllckZvcihyZWNvcmQpOwoKICAgICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcykucGVlayhfaWRlbnRpZmllcjIpOwogICAgICAgICAgaW50ZXJuYWxNb2RlbC51bmxvYWRSZWNvcmQoKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmVjb3JkLnVubG9hZFJlY29yZCgpOwogICAgICB9CiAgICB9IC8vIC4uLi4uLi4uLi4uLi4uLi4KICAgIC8vIC4gRklORCBSRUNPUkRTIC4KICAgIC8vIC4uLi4uLi4uLi4uLi4uLi4KCiAgICAvKioKICAgICAgQG1ldGhvZCBmaW5kCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHBhcmFtIHtTdHJpbmd8SW50ZWdlcn0gaWQKICAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZmluZCA9IGZ1bmN0aW9uIGZpbmQobW9kZWxOYW1lLCBpZCwgb3B0aW9ucykgewogICAgICByZXR1cm4gdGhpcy5maW5kUmVjb3JkKG1vZGVsTmFtZSwgaWQpOwogICAgfQogICAgLyoqCiAgICAgIFRoaXMgbWV0aG9kIHJldHVybnMgYSByZWNvcmQgZm9yIGEgZ2l2ZW4gdHlwZSBhbmQgaWQgY29tYmluYXRpb24uCiAgICAgICBUaGUgYGZpbmRSZWNvcmRgIG1ldGhvZCB3aWxsIGFsd2F5cyByZXNvbHZlIGl0cyBwcm9taXNlIHdpdGggdGhlIHNhbWUKICAgICAgb2JqZWN0IGZvciBhIGdpdmVuIHR5cGUgYW5kIGBpZGAuCiAgICAgICBUaGUgYGZpbmRSZWNvcmRgIG1ldGhvZCB3aWxsIGFsd2F5cyByZXR1cm4gYSAqKnByb21pc2UqKiB0aGF0IHdpbGwgYmUKICAgICAgcmVzb2x2ZWQgd2l0aCB0aGUgcmVjb3JkLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIG1vZGVsKHBhcmFtcykgewogICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIHBhcmFtcy5wb3N0X2lkKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIElmIHRoZSByZWNvcmQgaXMgbm90IHlldCBhdmFpbGFibGUsIHRoZSBzdG9yZSB3aWxsIGFzayB0aGUgYWRhcHRlcidzIGBmaW5kYAogICAgICBtZXRob2QgdG8gZmluZCB0aGUgbmVjZXNzYXJ5IGRhdGEuIElmIHRoZSByZWNvcmQgaXMgYWxyZWFkeSBwcmVzZW50IGluIHRoZQogICAgICBzdG9yZSwgaXQgZGVwZW5kcyBvbiB0aGUgcmVsb2FkIGJlaGF2aW9yIF93aGVuXyB0aGUgcmV0dXJuZWQgcHJvbWlzZQogICAgICByZXNvbHZlcy4KICAgICAgICMjIyBQcmVsb2FkaW5nCiAgICAgICBZb3UgY2FuIG9wdGlvbmFsbHkgYHByZWxvYWRgIHNwZWNpZmljIGF0dHJpYnV0ZXMgYW5kIHJlbGF0aW9uc2hpcHMgdGhhdCB5b3Uga25vdyBvZgogICAgICBieSBwYXNzaW5nIHRoZW0gdmlhIHRoZSBwYXNzZWQgYG9wdGlvbnNgLgogICAgICAgRm9yIGV4YW1wbGUsIGlmIHlvdXIgRW1iZXIgcm91dGUgbG9va3MgbGlrZSBgL3Bvc3RzLzEvY29tbWVudHMvMmAgYW5kIHlvdXIgQVBJIHJvdXRlCiAgICAgIGZvciB0aGUgY29tbWVudCBhbHNvIGxvb2tzIGxpa2UgYC9wb3N0cy8xL2NvbW1lbnRzLzJgIGlmIHlvdSB3YW50IHRvIGZldGNoIHRoZSBjb21tZW50CiAgICAgIHdpdGhvdXQgZmV0Y2hpbmcgdGhlIHBvc3QgeW91IGNhbiBwYXNzIGluIHRoZSBwb3N0IHRvIHRoZSBgZmluZFJlY29yZGAgY2FsbDoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc3RvcmUuZmluZFJlY29yZCgnY29tbWVudCcsIDIsIHsgcHJlbG9hZDogeyBwb3N0OiAxIH0gfSk7CiAgICAgIGBgYAogICAgICAgSWYgeW91IGhhdmUgYWNjZXNzIHRvIHRoZSBwb3N0IG1vZGVsIHlvdSBjYW4gYWxzbyBwYXNzIHRoZSBtb2RlbCBpdHNlbGY6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0b3JlLmZpbmRSZWNvcmQoJ3Bvc3QnLCAxKS50aGVuKGZ1bmN0aW9uIChteVBvc3RNb2RlbCkgewogICAgICAgIHN0b3JlLmZpbmRSZWNvcmQoJ2NvbW1lbnQnLCAyLCB7IHBvc3Q6IG15UG9zdE1vZGVsIH0pOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAjIyMgUmVsb2FkaW5nCiAgICAgICBUaGUgcmVsb2FkIGJlaGF2aW9yIGlzIGNvbmZpZ3VyZWQgZWl0aGVyIHZpYSB0aGUgcGFzc2VkIGBvcHRpb25zYCBoYXNoIG9yCiAgICAgIHRoZSByZXN1bHQgb2YgdGhlIGFkYXB0ZXIncyBgc2hvdWxkUmVsb2FkUmVjb3JkYC4KICAgICAgIElmIGB7IHJlbG9hZDogdHJ1ZSB9YCBpcyBwYXNzZWQgb3IgYGFkYXB0ZXIuc2hvdWxkUmVsb2FkUmVjb3JkYCBldmFsdWF0ZXMKICAgICAgdG8gYHRydWVgLCB0aGVuIHRoZSByZXR1cm5lZCBwcm9taXNlIHJlc29sdmVzIG9uY2UgdGhlIGFkYXB0ZXIgcmV0dXJucwogICAgICBkYXRhLCByZWdhcmRsZXNzIGlmIHRoZSByZXF1ZXN0ZWQgcmVjb3JkIGlzIGFscmVhZHkgaW4gdGhlIHN0b3JlOgogICAgICAgYGBganMKICAgICAgc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICB0eXBlOiAncG9zdCcsCiAgICAgICAgICByZXZpc2lvbjogMQogICAgICAgIH0KICAgICAgfSk7CiAgICAgICAvLyBhZGFwdGVyI2ZpbmRSZWNvcmQgcmVzb2x2ZXMgd2l0aAogICAgICAvLyBbCiAgICAgIC8vICAgewogICAgICAvLyAgICAgaWQ6IDEsCiAgICAgIC8vICAgICB0eXBlOiAncG9zdCcsCiAgICAgIC8vICAgICByZXZpc2lvbjogMgogICAgICAvLyAgIH0KICAgICAgLy8gXQogICAgICBzdG9yZS5maW5kUmVjb3JkKCdwb3N0JywgMSwgeyByZWxvYWQ6IHRydWUgfSkudGhlbihmdW5jdGlvbihwb3N0KSB7CiAgICAgICAgcG9zdC5nZXQoJ3JldmlzaW9uJyk7IC8vIDIKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgSWYgbm8gcmVsb2FkIGlzIGluZGljYXRlZCB2aWEgdGhlIGFib3ZlIG1lbnRpb25lZCB3YXlzLCB0aGVuIHRoZSBwcm9taXNlCiAgICAgIGltbWVkaWF0ZWx5IHJlc29sdmVzIHdpdGggdGhlIGNhY2hlZCB2ZXJzaW9uIGluIHRoZSBzdG9yZS4KICAgICAgICMjIyBCYWNrZ3JvdW5kIFJlbG9hZGluZwogICAgICAgT3B0aW9uYWxseSwgaWYgYGFkYXB0ZXIuc2hvdWxkQmFja2dyb3VuZFJlbG9hZFJlY29yZGAgZXZhbHVhdGVzIHRvIGB0cnVlYCwKICAgICAgdGhlbiBhIGJhY2tncm91bmQgcmVsb2FkIGlzIHN0YXJ0ZWQsIHdoaWNoIHVwZGF0ZXMgdGhlIHJlY29yZHMnIGRhdGEsIG9uY2UKICAgICAgaXQgaXMgYXZhaWxhYmxlOgogICAgICAgYGBganMKICAgICAgLy8gYXBwL2FkYXB0ZXJzL3Bvc3QuanMKICAgICAgaW1wb3J0IEFwcGxpY2F0aW9uQWRhcHRlciBmcm9tICIuL2FwcGxpY2F0aW9uIjsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEFwcGxpY2F0aW9uQWRhcHRlci5leHRlbmQoewogICAgICAgIHNob3VsZFJlbG9hZFJlY29yZChzdG9yZSwgc25hcHNob3QpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9LAogICAgICAgICBzaG91bGRCYWNrZ3JvdW5kUmVsb2FkUmVjb3JkKHN0b3JlLCBzbmFwc2hvdCkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgIC8vIC4uLgogICAgICAgc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICB0eXBlOiAncG9zdCcsCiAgICAgICAgICByZXZpc2lvbjogMQogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBsZXQgYmxvZ1Bvc3QgPSBzdG9yZS5maW5kUmVjb3JkKCdwb3N0JywgMSkudGhlbihmdW5jdGlvbihwb3N0KSB7CiAgICAgICAgcG9zdC5nZXQoJ3JldmlzaW9uJyk7IC8vIDEKICAgICAgfSk7CiAgICAgICAvLyBsYXRlciwgb25jZSBhZGFwdGVyI2ZpbmRSZWNvcmQgcmVzb2x2ZWQgd2l0aAogICAgICAvLyBbCiAgICAgIC8vICAgewogICAgICAvLyAgICAgaWQ6IDEsCiAgICAgIC8vICAgICB0eXBlOiAncG9zdCcsCiAgICAgIC8vICAgICByZXZpc2lvbjogMgogICAgICAvLyAgIH0KICAgICAgLy8gXQogICAgICAgYmxvZ1Bvc3QuZ2V0KCdyZXZpc2lvbicpOyAvLyAyCiAgICAgIGBgYAogICAgICAgSWYgeW91IHdvdWxkIGxpa2UgdG8gZm9yY2Ugb3IgcHJldmVudCBiYWNrZ3JvdW5kIHJlbG9hZGluZywgeW91IGNhbiBzZXQgYQogICAgICBib29sZWFuIHZhbHVlIGZvciBgYmFja2dyb3VuZFJlbG9hZGAgaW4gdGhlIG9wdGlvbnMgb2JqZWN0IGZvcgogICAgICBgZmluZFJlY29yZGAuCiAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3QvZWRpdC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBtb2RlbChwYXJhbXMpIHsKICAgICAgICAgIHJldHVybiB0aGlzLnN0b3JlLmZpbmRSZWNvcmQoJ3Bvc3QnLCBwYXJhbXMucG9zdF9pZCwgeyBiYWNrZ3JvdW5kUmVsb2FkOiBmYWxzZSB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIElmIHlvdSBwYXNzIGFuIG9iamVjdCBvbiB0aGUgYGFkYXB0ZXJPcHRpb25zYCBwcm9wZXJ0eSBvZiB0aGUgb3B0aW9ucwogICAgICBhcmd1bWVudCBpdCB3aWxsIGJlIHBhc3NlZCB0byB5b3UgYWRhcHRlciB2aWEgdGhlIHNuYXBzaG90CiAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3QvZWRpdC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBtb2RlbChwYXJhbXMpIHsKICAgICAgICAgIHJldHVybiB0aGlzLnN0b3JlLmZpbmRSZWNvcmQoJ3Bvc3QnLCBwYXJhbXMucG9zdF9pZCwgewogICAgICAgICAgICBhZGFwdGVyT3B0aW9uczogeyBzdWJzY3JpYmU6IGZhbHNlIH0KICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgYXBwL2FkYXB0ZXJzL3Bvc3QuanMKICAgICAgaW1wb3J0IE15Q3VzdG9tQWRhcHRlciBmcm9tICcuL2N1c3RvbS1hZGFwdGVyJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IE15Q3VzdG9tQWRhcHRlci5leHRlbmQoewogICAgICAgIGZpbmRSZWNvcmQoc3RvcmUsIHR5cGUsIGlkLCBzbmFwc2hvdCkgewogICAgICAgICAgaWYgKHNuYXBzaG90LmFkYXB0ZXJPcHRpb25zLnN1YnNjcmliZSkgewogICAgICAgICAgICAvLyAuLi4KICAgICAgICAgIH0KICAgICAgICAgIC8vIC4uLgogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgU2VlIFtwZWVrUmVjb3JkXShTdG9yZS9tZXRob2RzL3BlZWtSZWNvcmQ/YW5jaG9yPXBlZWtSZWNvcmQpIHRvIGdldCB0aGUgY2FjaGVkIHZlcnNpb24gb2YgYSByZWNvcmQuCiAgICAgICAjIyMgUmV0cmlldmluZyBSZWxhdGVkIE1vZGVsIFJlY29yZHMKICAgICAgIElmIHlvdSB1c2UgYW4gYWRhcHRlciBzdWNoIGFzIEVtYmVyJ3MgZGVmYXVsdAogICAgICBbYEpTT05BUElBZGFwdGVyYF0oL2VtYmVyLWRhdGEvcmVsZWFzZS9jbGFzc2VzL0pTT05BUElBZGFwdGVyKQogICAgICB0aGF0IHN1cHBvcnRzIHRoZSBbSlNPTiBBUEkgc3BlY2lmaWNhdGlvbl0oaHR0cDovL2pzb25hcGkub3JnLykgYW5kIGlmIHlvdXIgc2VydmVyCiAgICAgIGVuZHBvaW50IHN1cHBvcnRzIHRoZSB1c2Ugb2YgYW4KICAgICAgWydpbmNsdWRlJyBxdWVyeSBwYXJhbWV0ZXJdKGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2ZldGNoaW5nLWluY2x1ZGVzKSwKICAgICAgeW91IGNhbiB1c2UgYGZpbmRSZWNvcmQoKWAgdG8gYXV0b21hdGljYWxseSByZXRyaWV2ZSBhZGRpdGlvbmFsIHJlY29yZHMgcmVsYXRlZCB0bwogICAgICB0aGUgb25lIHlvdSByZXF1ZXN0IGJ5IHN1cHBseWluZyBhbiBgaW5jbHVkZWAgcGFyYW1ldGVyIGluIHRoZSBgb3B0aW9uc2Agb2JqZWN0LgogICAgICAgRm9yIGV4YW1wbGUsIGdpdmVuIGEgYHBvc3RgIG1vZGVsIHRoYXQgaGFzIGEgYGhhc01hbnlgIHJlbGF0aW9uc2hpcCB3aXRoIGEgYGNvbW1lbnRgCiAgICAgIG1vZGVsLCB3aGVuIHdlIHJldHJpZXZlIGEgc3BlY2lmaWMgcG9zdCB3ZSBjYW4gaGF2ZSB0aGUgc2VydmVyIGFsc28gcmV0dXJuIHRoYXQgcG9zdCdzCiAgICAgIGNvbW1lbnRzIGluIHRoZSBzYW1lIHJlcXVlc3Q6CiAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3QuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgbW9kZWwocGFyYW1zKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5zdG9yZS5maW5kUmVjb3JkKCdwb3N0JywgcGFyYW1zLnBvc3RfaWQsIHsgaW5jbHVkZTogJ2NvbW1lbnRzJyB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgYGBgCiAgICAgIEluIHRoaXMgY2FzZSwgdGhlIHBvc3QncyBjb21tZW50cyB3b3VsZCB0aGVuIGJlIGF2YWlsYWJsZSBpbiB5b3VyIHRlbXBsYXRlIGFzCiAgICAgIGBtb2RlbC5jb21tZW50c2AuCiAgICAgICBNdWx0aXBsZSByZWxhdGlvbnNoaXBzIGNhbiBiZSByZXF1ZXN0ZWQgdXNpbmcgYW4gYGluY2x1ZGVgIHBhcmFtZXRlciBjb25zaXN0aW5nIG9mIGEKICAgICAgY29tbWEtc2VwYXJhdGVkIGxpc3QgKHdpdGhvdXQgd2hpdGUtc3BhY2UpIHdoaWxlIG5lc3RlZCByZWxhdGlvbnNoaXBzIGNhbiBiZSBzcGVjaWZpZWQKICAgICAgdXNpbmcgYSBkb3Qtc2VwYXJhdGVkIHNlcXVlbmNlIG9mIHJlbGF0aW9uc2hpcCBuYW1lcy4gU28gdG8gcmVxdWVzdCBib3RoIHRoZSBwb3N0J3MKICAgICAgY29tbWVudHMgYW5kIHRoZSBhdXRob3JzIG9mIHRob3NlIGNvbW1lbnRzIHRoZSByZXF1ZXN0IHdvdWxkIGxvb2sgbGlrZSB0aGlzOgogICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIG1vZGVsKHBhcmFtcykgewogICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIHBhcmFtcy5wb3N0X2lkLCB7IGluY2x1ZGU6ICdjb21tZW50cyxjb21tZW50cy5hdXRob3InIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBgYGAKICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBmaW5kUmVjb3JkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHBhcmFtIHsoU3RyaW5nfEludGVnZXIpfSBpZAogICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwcmVsb2FkIC0gb3B0aW9uYWwgc2V0IG9mIGF0dHJpYnV0ZXMgYW5kIHJlbGF0aW9uc2hpcHMgcGFzc2VkIGluIGVpdGhlciBhcyBJRHMgb3IgYXMgYWN0dWFsIG1vZGVscwogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5maW5kUmVjb3JkID0gZnVuY3Rpb24gZmluZFJlY29yZChtb2RlbE5hbWUsIGlkLCBvcHRpb25zKSB7CiAgICAgIHZhciB0eXBlID0gbm9ybWFsaXplTW9kZWxOYW1lKG1vZGVsTmFtZSk7CiAgICAgIHZhciBub3JtYWxpemVkSWQgPSBlbnN1cmVTdHJpbmdJZChpZCk7CiAgICAgIHZhciByZXNvdXJjZSA9IGNvbnN0cnVjdFJlc291cmNlKHR5cGUsIG5vcm1hbGl6ZWRJZCk7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcykubG9va3VwKHJlc291cmNlKTsKICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307CgogICAgICBpZiAoIXRoaXMuaGFzUmVjb3JkRm9ySWQodHlwZSwgbm9ybWFsaXplZElkKSkgewogICAgICAgIHJldHVybiB0aGlzLl9maW5kQnlJbnRlcm5hbE1vZGVsKGludGVybmFsTW9kZWwsIG9wdGlvbnMpOwogICAgICB9CgogICAgICB2YXIgZmV0Y2hlZEludGVybmFsTW9kZWwgPSB0aGlzLl9maW5kUmVjb3JkKGludGVybmFsTW9kZWwsIG9wdGlvbnMpOwoKICAgICAgcmV0dXJuIHByb21pc2VSZWNvcmQoZmV0Y2hlZEludGVybmFsTW9kZWwsICJEUzogU3RvcmUjZmluZFJlY29yZCAiICsgdHlwZSArICIgd2l0aCBpZDogIiArIGlkKTsKICAgIH07CgogICAgX3Byb3RvLl9maW5kUmVjb3JkID0gZnVuY3Rpb24gX2ZpbmRSZWNvcmQoaW50ZXJuYWxNb2RlbCwgb3B0aW9ucykgewogICAgICAvLyBSZWZldGNoIGlmIHRoZSByZWxvYWQgb3B0aW9uIGlzIHBhc3NlZAogICAgICBpZiAob3B0aW9ucy5yZWxvYWQpIHsKICAgICAgICByZXR1cm4gdGhpcy5fc2NoZWR1bGVGZXRjaChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKTsKICAgICAgfQoKICAgICAgdmFyIHNuYXBzaG90ID0gaW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdChvcHRpb25zKTsKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXJGb3IoaW50ZXJuYWxNb2RlbC5tb2RlbE5hbWUpOyAvLyBSZWZldGNoIHRoZSByZWNvcmQgaWYgdGhlIGFkYXB0ZXIgdGhpbmtzIHRoZSByZWNvcmQgaXMgc3RhbGUKCiAgICAgIGlmIChhZGFwdGVyLnNob3VsZFJlbG9hZFJlY29yZCh0aGlzLCBzbmFwc2hvdCkpIHsKICAgICAgICByZXR1cm4gdGhpcy5fc2NoZWR1bGVGZXRjaChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKTsKICAgICAgfQoKICAgICAgaWYgKG9wdGlvbnMuYmFja2dyb3VuZFJlbG9hZCA9PT0gZmFsc2UpIHsKICAgICAgICByZXR1cm4gRW1iZXIuUlNWUC5Qcm9taXNlLnJlc29sdmUoaW50ZXJuYWxNb2RlbCk7CiAgICAgIH0gLy8gVHJpZ2dlciB0aGUgYmFja2dyb3VuZCByZWZldGNoIGlmIGJhY2tncm91bmRSZWxvYWQgb3B0aW9uIGlzIHBhc3NlZAoKCiAgICAgIGlmIChvcHRpb25zLmJhY2tncm91bmRSZWxvYWQgfHwgYWRhcHRlci5zaG91bGRCYWNrZ3JvdW5kUmVsb2FkUmVjb3JkKHRoaXMsIHNuYXBzaG90KSkgewogICAgICAgIHRoaXMuX3NjaGVkdWxlRmV0Y2goaW50ZXJuYWxNb2RlbCwgb3B0aW9ucyk7CiAgICAgIH0gLy8gUmV0dXJuIHRoZSBjYWNoZWQgcmVjb3JkCgoKICAgICAgcmV0dXJuIEVtYmVyLlJTVlAuUHJvbWlzZS5yZXNvbHZlKGludGVybmFsTW9kZWwpOwogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRCeUludGVybmFsTW9kZWwgPSBmdW5jdGlvbiBfZmluZEJ5SW50ZXJuYWxNb2RlbChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKSB7CiAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsKICAgICAgICBvcHRpb25zID0ge307CiAgICAgIH0KCiAgICAgIGlmIChvcHRpb25zLnByZWxvYWQpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnByZWxvYWREYXRhKG9wdGlvbnMucHJlbG9hZCk7CiAgICAgIH0KCiAgICAgIHZhciBmZXRjaGVkSW50ZXJuYWxNb2RlbCA9IHRoaXMuX2ZpbmRFbXB0eUludGVybmFsTW9kZWwoaW50ZXJuYWxNb2RlbCwgb3B0aW9ucyk7CgogICAgICByZXR1cm4gcHJvbWlzZVJlY29yZChmZXRjaGVkSW50ZXJuYWxNb2RlbCwgIkRTOiBTdG9yZSNmaW5kUmVjb3JkICIgKyBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZSArICIgd2l0aCBpZDogIiArIGludGVybmFsTW9kZWwuaWQpOwogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRFbXB0eUludGVybmFsTW9kZWwgPSBmdW5jdGlvbiBfZmluZEVtcHR5SW50ZXJuYWxNb2RlbChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKSB7CiAgICAgIGlmIChpbnRlcm5hbE1vZGVsLmlzRW1wdHkoKSkgewogICAgICAgIHJldHVybiB0aGlzLl9zY2hlZHVsZUZldGNoKGludGVybmFsTW9kZWwsIG9wdGlvbnMpOwogICAgICB9IC8vVE9ETyBkb3VibGUgY2hlY2sgYWJvdXQgcmVsb2FkaW5nCgoKICAgICAgaWYgKCFjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbC5pc0xvYWRpbmcoKSkgewogICAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwuX3Byb21pc2VQcm94eTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaWYgKGludGVybmFsTW9kZWwuaXNMb2FkaW5nKCkpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9zY2hlZHVsZUZldGNoKGludGVybmFsTW9kZWwsIG9wdGlvbnMpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIEVtYmVyLlJTVlAuUHJvbWlzZS5yZXNvbHZlKGludGVybmFsTW9kZWwpOwogICAgfQogICAgLyoqCiAgICAgIFRoaXMgbWV0aG9kIG1ha2VzIGEgc2VyaWVzIG9mIHJlcXVlc3RzIHRvIHRoZSBhZGFwdGVyJ3MgYGZpbmRgIG1ldGhvZAogICAgICBhbmQgcmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBvbmNlIHRoZXkgYXJlIGFsbCBsb2FkZWQuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGZpbmRCeUlkcwogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7QXJyYXl9IGlkcwogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5maW5kQnlJZHMgPSBmdW5jdGlvbiBmaW5kQnlJZHMobW9kZWxOYW1lLCBpZHMpIHsKICAgICAgdmFyIHByb21pc2VzID0gbmV3IEFycmF5KGlkcy5sZW5ndGgpOwogICAgICB2YXIgbm9ybWFsaXplZE1vZGVsTmFtZSA9IG5vcm1hbGl6ZU1vZGVsTmFtZShtb2RlbE5hbWUpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHsKICAgICAgICBwcm9taXNlc1tpXSA9IHRoaXMuZmluZFJlY29yZChub3JtYWxpemVkTW9kZWxOYW1lLCBpZHNbaV0pOwogICAgICB9CgogICAgICByZXR1cm4gcHJvbWlzZUFycmF5KEVtYmVyLlJTVlAuYWxsKHByb21pc2VzKS50aGVuKEVtYmVyLkEsIG51bGwsICJEUzogU3RvcmUjZmluZEJ5SWRzIG9mICIgKyBub3JtYWxpemVkTW9kZWxOYW1lICsgIiBjb21wbGV0ZSIpKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgYnkgYGZpbmRSZWNvcmRgIGlmIGl0IGRpc2NvdmVycyB0aGF0IGEgcGFydGljdWxhcgogICAgICB0eXBlL2lkIHBhaXIgaGFzbid0IGJlZW4gbG9hZGVkIHlldCB0byBraWNrIG9mZiBhIHJlcXVlc3QgdG8gdGhlCiAgICAgIGFkYXB0ZXIuCiAgICAgICBAbWV0aG9kIF9mZXRjaFJlY29yZAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge0ludGVybmFsTW9kZWx9IGludGVybmFsTW9kZWwgbW9kZWwKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgICovCiAgICA7CgogICAgX3Byb3RvLl9mZXRjaFJlY29yZCA9IGZ1bmN0aW9uIF9mZXRjaFJlY29yZChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKSB7CiAgICAgIHZhciBtb2RlbE5hbWUgPSBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZTsKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIF9maW5kKGFkYXB0ZXIsIHRoaXMsIGludGVybmFsTW9kZWwudHlwZSwgaW50ZXJuYWxNb2RlbC5pZCwgaW50ZXJuYWxNb2RlbCwgb3B0aW9ucyk7CiAgICB9OwoKICAgIF9wcm90by5fc2NoZWR1bGVGZXRjaE1hbnkgPSBmdW5jdGlvbiBfc2NoZWR1bGVGZXRjaE1hbnkoaW50ZXJuYWxNb2RlbHMsIG9wdGlvbnMpIHsKICAgICAgdmFyIGZldGNoZXMgPSBuZXcgQXJyYXkoaW50ZXJuYWxNb2RlbHMubGVuZ3RoKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW50ZXJuYWxNb2RlbHMubGVuZ3RoOyBpKyspIHsKICAgICAgICBmZXRjaGVzW2ldID0gdGhpcy5fc2NoZWR1bGVGZXRjaChpbnRlcm5hbE1vZGVsc1tpXSwgb3B0aW9ucyk7CiAgICAgIH0KCiAgICAgIHJldHVybiBFbWJlci5SU1ZQLlByb21pc2UuYWxsKGZldGNoZXMpOwogICAgfTsKCiAgICBfcHJvdG8uX3NjaGVkdWxlRmV0Y2hUaHJvdWdoRmV0Y2hNYW5hZ2VyID0gZnVuY3Rpb24gX3NjaGVkdWxlRmV0Y2hUaHJvdWdoRmV0Y2hNYW5hZ2VyKGludGVybmFsTW9kZWwsIG9wdGlvbnMpIHsKICAgICAgdmFyIF90aGlzMyA9IHRoaXM7CgogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICB2YXIgZ2VuZXJhdGVTdGFja1RyYWNlID0gdGhpcy5nZW5lcmF0ZVN0YWNrVHJhY2VzRm9yVHJhY2tlZFJlcXVlc3RzOyAvLyBUT0RPICByZW1vdmUgdGhpcyBvbmNlIHdlIGRvbnQgcmVseSBvbiBzdGF0ZSBtYWNoaW5lCgogICAgICBpbnRlcm5hbE1vZGVsLmxvYWRpbmdEYXRhKCk7CiAgICAgIHZhciBpZGVudGlmaWVyID0gaW50ZXJuYWxNb2RlbC5pZGVudGlmaWVyOwoKICAgICAgdmFyIHByb21pc2UgPSB0aGlzLl9mZXRjaE1hbmFnZXIuc2NoZWR1bGVGZXRjaChpbnRlcm5hbE1vZGVsLmlkZW50aWZpZXIsIG9wdGlvbnMsIGdlbmVyYXRlU3RhY2tUcmFjZSk7CgogICAgICByZXR1cm4gcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChwYXlsb2FkKSB7CiAgICAgICAgewogICAgICAgICAgLy8gZW5zdXJlIHRoYXQgcmVnYXJkbGVzcyBvZiBpZCByZXR1cm5lZCB3ZSBhc3NpZ24gdG8gdGhlIGNvcnJlY3QgcmVjb3JkCiAgICAgICAgICBpZiAocGF5bG9hZC5kYXRhICYmICFBcnJheS5pc0FycmF5KHBheWxvYWQuZGF0YSkpIHsKICAgICAgICAgICAgcGF5bG9hZC5kYXRhLmxpZCA9IGlkZW50aWZpZXIubGlkOwogICAgICAgICAgfQogICAgICAgIH0gLy8gUmV0dXJuaW5nIHRoaXMuX3B1c2ggaGVyZSwgYnJlYWtzIHR5cGluZyBidXQgbm90IGFueSB0ZXN0cywgaW52ZXNzdGlnYXRlIHBvdGVudGlhbCBtaXNzaW5nIHRlc3RzCgoKICAgICAgICB2YXIgcG90ZW50aWFsbHlOZXdJbSA9IF90aGlzMy5fcHVzaChwYXlsb2FkKTsKCiAgICAgICAgaWYgKHBvdGVudGlhbGx5TmV3SW0gJiYgIUFycmF5LmlzQXJyYXkocG90ZW50aWFsbHlOZXdJbSkpIHsKICAgICAgICAgIHJldHVybiBwb3RlbnRpYWxseU5ld0ltOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbDsKICAgICAgICB9CiAgICAgIH0sIGZ1bmN0aW9uIChlcnJvcikgewogICAgICAgIC8vIFRPRE8gIHJlbW92ZSB0aGlzIG9uY2Ugd2UgZG9udCByZWx5IG9uIHN0YXRlIG1hY2hpbmUKICAgICAgICBpbnRlcm5hbE1vZGVsLm5vdEZvdW5kKCk7CgogICAgICAgIGlmIChpbnRlcm5hbE1vZGVsLmlzRW1wdHkoKSkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC51bmxvYWRSZWNvcmQoKTsKICAgICAgICB9CgogICAgICAgIHRocm93IGVycm9yOwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvLl9zY2hlZHVsZUZldGNoID0gZnVuY3Rpb24gX3NjaGVkdWxlRmV0Y2goaW50ZXJuYWxNb2RlbCwgb3B0aW9ucykgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3NjaGVkdWxlRmV0Y2hUaHJvdWdoRmV0Y2hNYW5hZ2VyKGludGVybmFsTW9kZWwsIG9wdGlvbnMpOwogICAgICB9IGVsc2UgewogICAgICAgIGlmIChpbnRlcm5hbE1vZGVsLl9wcm9taXNlUHJveHkpIHsKICAgICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLl9wcm9taXNlUHJveHk7CiAgICAgICAgfQoKICAgICAgICB2YXIgaWQgPSBpbnRlcm5hbE1vZGVsLmlkLAogICAgICAgICAgICBtb2RlbE5hbWUgPSBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZTsKICAgICAgICB2YXIgcmVzb2x2ZXIgPSBFbWJlci5SU1ZQLmRlZmVyKCJGZXRjaGluZyAiICsgbW9kZWxOYW1lICsgIicgd2l0aCBpZDogIiArIGlkKTsKICAgICAgICB2YXIgcGVuZGluZ0ZldGNoSXRlbSA9IHsKICAgICAgICAgIGludGVybmFsTW9kZWw6IGludGVybmFsTW9kZWwsCiAgICAgICAgICByZXNvbHZlcjogcmVzb2x2ZXIsCiAgICAgICAgICBvcHRpb25zOiBvcHRpb25zCiAgICAgICAgfTsKCiAgICAgICAgdmFyIHByb21pc2UgPSByZXNvbHZlci5wcm9taXNlOwogICAgICAgIGludGVybmFsTW9kZWwubG9hZGluZ0RhdGEocHJvbWlzZSk7CgogICAgICAgIGlmICh0aGlzLl9wZW5kaW5nRmV0Y2guc2l6ZSA9PT0gMCkgewogICAgICAgICAgZW1iZXJSdW4kMi5zY2hlZHVsZSgnYWN0aW9ucycsIHRoaXMsIHRoaXMuZmx1c2hBbGxQZW5kaW5nRmV0Y2hlcyk7CiAgICAgICAgfQoKICAgICAgICB2YXIgZmV0Y2hlcyA9IHRoaXMuX3BlbmRpbmdGZXRjaDsKICAgICAgICB2YXIgcGVuZGluZyA9IGZldGNoZXMuZ2V0KG1vZGVsTmFtZSk7CgogICAgICAgIGlmIChwZW5kaW5nID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHBlbmRpbmcgPSBbXTsKICAgICAgICAgIGZldGNoZXMuc2V0KG1vZGVsTmFtZSwgcGVuZGluZyk7CiAgICAgICAgfQoKICAgICAgICBwZW5kaW5nLnB1c2gocGVuZGluZ0ZldGNoSXRlbSk7CiAgICAgICAgcmV0dXJuIHByb21pc2U7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmZsdXNoQWxsUGVuZGluZ0ZldGNoZXMgPSBmdW5jdGlvbiBmbHVzaEFsbFBlbmRpbmdGZXRjaGVzKCkgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgcmV0dXJuOyAvL2Fzc2VydCBoZXJlCiAgICAgIH0gZWxzZSB7CiAgICAgICAgaWYgKHRoaXMuaXNEZXN0cm95ZWQgfHwgdGhpcy5pc0Rlc3Ryb3lpbmcpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHRoaXMuX3BlbmRpbmdGZXRjaC5mb3JFYWNoKHRoaXMuX2ZsdXNoUGVuZGluZ0ZldGNoRm9yVHlwZSwgdGhpcyk7CgogICAgICAgIHRoaXMuX3BlbmRpbmdGZXRjaC5jbGVhcigpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fZmx1c2hQZW5kaW5nRmV0Y2hGb3JUeXBlID0gZnVuY3Rpb24gX2ZsdXNoUGVuZGluZ0ZldGNoRm9yVHlwZShwZW5kaW5nRmV0Y2hJdGVtcywgbW9kZWxOYW1lKSB7CiAgICAgIHZhciBzdG9yZSA9IHRoaXM7CiAgICAgIHZhciBhZGFwdGVyID0gc3RvcmUuYWRhcHRlckZvcihtb2RlbE5hbWUpOwogICAgICB2YXIgc2hvdWxkQ29hbGVzY2UgPSAhIWFkYXB0ZXIuZmluZE1hbnkgJiYgYWRhcHRlci5jb2FsZXNjZUZpbmRSZXF1ZXN0czsKICAgICAgdmFyIHRvdGFsSXRlbXMgPSBwZW5kaW5nRmV0Y2hJdGVtcy5sZW5ndGg7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVscyA9IG5ldyBBcnJheSh0b3RhbEl0ZW1zKTsKICAgICAgdmFyIHNlZWtpbmcgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB2YXIgb3B0aW9uc01hcCA9IG5ldyBXZWFrTWFwKCk7CgogICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgdG90YWxJdGVtczsgX2krKykgewogICAgICAgIHZhciBwZW5kaW5nSXRlbSA9IHBlbmRpbmdGZXRjaEl0ZW1zW19pXTsKICAgICAgICB2YXIgX2ludGVybmFsTW9kZWwgPSBwZW5kaW5nSXRlbS5pbnRlcm5hbE1vZGVsOwogICAgICAgIGludGVybmFsTW9kZWxzW19pXSA9IF9pbnRlcm5hbE1vZGVsOwogICAgICAgIG9wdGlvbnNNYXAuc2V0KF9pbnRlcm5hbE1vZGVsLCBwZW5kaW5nSXRlbS5vcHRpb25zKTsgLy8gV2UgY2FuIHJlbW92ZSB0aGlzICJub3QgbnVsbCIgY2FzdCBvbmNlIHdlIGhhdmUgZW5vdWdoIHR5cGluZwogICAgICAgIC8vIHRvIGtub3cgd2UgYXJlIG9ubHkgZGVhbGluZyB3aXRoIEV4aXN0aW5nUmVzb3VyY2VJZGVudGlmaWVyT2JqZWN0cwoKICAgICAgICBzZWVraW5nW19pbnRlcm5hbE1vZGVsLmlkXSA9IHBlbmRpbmdJdGVtOwogICAgICB9CgogICAgICBmdW5jdGlvbiBfZmV0Y2hSZWNvcmQocmVjb3JkUmVzb2x2ZXJQYWlyKSB7CiAgICAgICAgdmFyIHJlY29yZEZldGNoID0gc3RvcmUuX2ZldGNoUmVjb3JkKHJlY29yZFJlc29sdmVyUGFpci5pbnRlcm5hbE1vZGVsLCByZWNvcmRSZXNvbHZlclBhaXIub3B0aW9ucyk7CgogICAgICAgIHJlY29yZFJlc29sdmVyUGFpci5yZXNvbHZlci5yZXNvbHZlKHJlY29yZEZldGNoKTsKICAgICAgfQoKICAgICAgZnVuY3Rpb24gaGFuZGxlRm91bmRSZWNvcmRzKGZvdW5kSW50ZXJuYWxNb2RlbHMsIGV4cGVjdGVkSW50ZXJuYWxNb2RlbHMpIHsKICAgICAgICAvLyByZXNvbHZlIGZvdW5kIHJlY29yZHMKICAgICAgICB2YXIgZm91bmQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwoKICAgICAgICBmb3IgKHZhciBfaTIgPSAwLCBfbCA9IGZvdW5kSW50ZXJuYWxNb2RlbHMubGVuZ3RoOyBfaTIgPCBfbDsgX2kyKyspIHsKICAgICAgICAgIHZhciBfaW50ZXJuYWxNb2RlbDIgPSBmb3VuZEludGVybmFsTW9kZWxzW19pMl07IC8vIFdlIGNhbiByZW1vdmUgdGhpcyAibm90IG51bGwiIGNhc3Qgb25jZSB3ZSBoYXZlIGVub3VnaCB0eXBpbmcKICAgICAgICAgIC8vIHRvIGtub3cgd2UgYXJlIG9ubHkgZGVhbGluZyB3aXRoIEV4aXN0aW5nUmVzb3VyY2VJZGVudGlmaWVyT2JqZWN0cwoKICAgICAgICAgIHZhciBfcGFpciA9IHNlZWtpbmdbX2ludGVybmFsTW9kZWwyLmlkXTsKICAgICAgICAgIGZvdW5kW19pbnRlcm5hbE1vZGVsMi5pZF0gPSBfaW50ZXJuYWxNb2RlbDI7CgogICAgICAgICAgaWYgKF9wYWlyKSB7CiAgICAgICAgICAgIHZhciByZXNvbHZlciA9IF9wYWlyLnJlc29sdmVyOwogICAgICAgICAgICByZXNvbHZlci5yZXNvbHZlKF9pbnRlcm5hbE1vZGVsMik7CiAgICAgICAgICB9CiAgICAgICAgfSAvLyByZWplY3QgbWlzc2luZyByZWNvcmRzCgoKICAgICAgICB2YXIgbWlzc2luZ0ludGVybmFsTW9kZWxzID0gW107CgogICAgICAgIGZvciAodmFyIF9pMyA9IDAsIF9sMiA9IGV4cGVjdGVkSW50ZXJuYWxNb2RlbHMubGVuZ3RoOyBfaTMgPCBfbDI7IF9pMysrKSB7CiAgICAgICAgICB2YXIgX2ludGVybmFsTW9kZWwzID0gZXhwZWN0ZWRJbnRlcm5hbE1vZGVsc1tfaTNdOyAvLyBXZSBjYW4gcmVtb3ZlIHRoaXMgIm5vdCBudWxsIiBjYXN0IG9uY2Ugd2UgaGF2ZSBlbm91Z2ggdHlwaW5nCiAgICAgICAgICAvLyB0byBrbm93IHdlIGFyZSBvbmx5IGRlYWxpbmcgd2l0aCBFeGlzdGluZ1Jlc291cmNlSWRlbnRpZmllck9iamVjdHMKCiAgICAgICAgICBpZiAoIWZvdW5kW19pbnRlcm5hbE1vZGVsMy5pZF0pIHsKICAgICAgICAgICAgbWlzc2luZ0ludGVybmFsTW9kZWxzLnB1c2goX2ludGVybmFsTW9kZWwzKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmIChtaXNzaW5nSW50ZXJuYWxNb2RlbHMubGVuZ3RoKSB7CiAgICAgICAgICByZWplY3RJbnRlcm5hbE1vZGVscyhtaXNzaW5nSW50ZXJuYWxNb2RlbHMpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgZnVuY3Rpb24gcmVqZWN0SW50ZXJuYWxNb2RlbHMoaW50ZXJuYWxNb2RlbHMsIGVycm9yKSB7CiAgICAgICAgZm9yICh2YXIgX2k0ID0gMCwgX2wzID0gaW50ZXJuYWxNb2RlbHMubGVuZ3RoOyBfaTQgPCBfbDM7IF9pNCsrKSB7CiAgICAgICAgICB2YXIgX2ludGVybmFsTW9kZWw0ID0gaW50ZXJuYWxNb2RlbHNbX2k0XTsgLy8gV2UgY2FuIHJlbW92ZSB0aGlzICJub3QgbnVsbCIgY2FzdCBvbmNlIHdlIGhhdmUgZW5vdWdoIHR5cGluZwogICAgICAgICAgLy8gdG8ga25vdyB3ZSBhcmUgb25seSBkZWFsaW5nIHdpdGggRXhpc3RpbmdSZXNvdXJjZUlkZW50aWZpZXJPYmplY3RzCgogICAgICAgICAgdmFyIF9wYWlyMiA9IHNlZWtpbmdbX2ludGVybmFsTW9kZWw0LmlkXTsKCiAgICAgICAgICBpZiAoX3BhaXIyKSB7CiAgICAgICAgICAgIF9wYWlyMi5yZXNvbHZlci5yZWplY3QoZXJyb3IgfHwgbmV3IEVycm9yKCJFeHBlY3RlZDogJyIgKyBfaW50ZXJuYWxNb2RlbDQgKyAiJyB0byBiZSBwcmVzZW50IGluIHRoZSBhZGFwdGVyIHByb3ZpZGVkIHBheWxvYWQsIGJ1dCBpdCB3YXMgbm90IGZvdW5kLiIpKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChzaG91bGRDb2FsZXNjZSkgewogICAgICAgIC8vIFRPRE86IEltcHJvdmUgcmVjb3JkcyA9PiBzbmFwc2hvdHMgPT4gcmVjb3JkcyA9PiBzbmFwc2hvdHMKICAgICAgICAvLwogICAgICAgIC8vIFdlIHdhbnQgdG8gcHJvdmlkZSByZWNvcmRzIHRvIGFsbCBzdG9yZSBtZXRob2RzIGFuZCBzbmFwc2hvdHMgdG8gYWxsCiAgICAgICAgLy8gYWRhcHRlciBtZXRob2RzLiBUbyBtYWtlIHN1cmUgd2UncmUgZG9pbmcgdGhhdCB3ZSdyZSBwcm92aWRpbmcgYW4gYXJyYXkKICAgICAgICAvLyBvZiBzbmFwc2hvdHMgdG8gYWRhcHRlci5ncm91cFJlY29yZHNGb3JGaW5kTWFueSgpLCB3aGljaCBpbiB0dXJuIHdpbGwKICAgICAgICAvLyByZXR1cm4gZ3JvdXBlZCBzbmFwc2hvdHMgaW5zdGVhZCBvZiBncm91cGVkIHJlY29yZHMuCiAgICAgICAgLy8KICAgICAgICAvLyBCdXQgc2luY2UgdGhlIF9maW5kTWFueSgpIGZpbmRlciBpcyBhIHN0b3JlIG1ldGhvZCB3ZSBuZWVkIHRvIGdldCB0aGUKICAgICAgICAvLyByZWNvcmRzIGZyb20gdGhlIGdyb3VwZWQgc25hcHNob3RzIGV2ZW4gdGhvdWdoIHRoZSBfZmluZE1hbnkoKSBmaW5kZXIKICAgICAgICAvLyB3aWxsIG9uY2UgYWdhaW4gY29udmVydCB0aGUgcmVjb3JkcyB0byBzbmFwc2hvdHMgZm9yIGFkYXB0ZXIuZmluZE1hbnkoKQogICAgICAgIHZhciBzbmFwc2hvdHMgPSBuZXcgQXJyYXkodG90YWxJdGVtcyk7CgogICAgICAgIGZvciAodmFyIF9pNSA9IDA7IF9pNSA8IHRvdGFsSXRlbXM7IF9pNSsrKSB7CiAgICAgICAgICBzbmFwc2hvdHNbX2k1XSA9IGludGVybmFsTW9kZWxzW19pNV0uY3JlYXRlU25hcHNob3Qob3B0aW9uc01hcC5nZXQoaW50ZXJuYWxNb2RlbCkpOwogICAgICAgIH0KCiAgICAgICAgdmFyIGdyb3VwcyA9IGFkYXB0ZXIuZ3JvdXBSZWNvcmRzRm9yRmluZE1hbnkodGhpcywgc25hcHNob3RzKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBncm91cHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICB2YXIgZ3JvdXAgPSBncm91cHNbaV07CiAgICAgICAgICB2YXIgdG90YWxJbkdyb3VwID0gZ3JvdXBzW2ldLmxlbmd0aDsKICAgICAgICAgIHZhciBpZHMgPSBuZXcgQXJyYXkodG90YWxJbkdyb3VwKTsKICAgICAgICAgIHZhciBncm91cGVkSW50ZXJuYWxNb2RlbHMgPSBuZXcgQXJyYXkodG90YWxJbkdyb3VwKTsKCiAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHRvdGFsSW5Hcm91cDsgaisrKSB7CiAgICAgICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gZ3JvdXBbal0uX2ludGVybmFsTW9kZWw7CiAgICAgICAgICAgIGdyb3VwZWRJbnRlcm5hbE1vZGVsc1tqXSA9IGludGVybmFsTW9kZWw7CiAgICAgICAgICAgIGlkc1tqXSA9IGludGVybmFsTW9kZWwuaWQ7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKHRvdGFsSW5Hcm91cCA+IDEpIHsKICAgICAgICAgICAgKGZ1bmN0aW9uIChncm91cGVkSW50ZXJuYWxNb2RlbHMpIHsKICAgICAgICAgICAgICBfZmluZE1hbnkoYWRhcHRlciwgc3RvcmUsIG1vZGVsTmFtZSwgaWRzLCBncm91cGVkSW50ZXJuYWxNb2RlbHMsIG9wdGlvbnNNYXApLnRoZW4oZnVuY3Rpb24gKGZvdW5kSW50ZXJuYWxNb2RlbHMpIHsKICAgICAgICAgICAgICAgIGhhbmRsZUZvdW5kUmVjb3Jkcyhmb3VuZEludGVybmFsTW9kZWxzLCBncm91cGVkSW50ZXJuYWxNb2RlbHMpOwogICAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikgewogICAgICAgICAgICAgICAgcmVqZWN0SW50ZXJuYWxNb2RlbHMoZ3JvdXBlZEludGVybmFsTW9kZWxzLCBlcnJvcik7CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0pKGdyb3VwZWRJbnRlcm5hbE1vZGVscyk7CiAgICAgICAgICB9IGVsc2UgaWYgKGlkcy5sZW5ndGggPT09IDEpIHsKICAgICAgICAgICAgdmFyIHBhaXIgPSBzZWVraW5nW2dyb3VwZWRJbnRlcm5hbE1vZGVsc1swXS5pZF07CgogICAgICAgICAgICBfZmV0Y2hSZWNvcmQocGFpcik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGZvciAodmFyIF9pNiA9IDA7IF9pNiA8IHRvdGFsSXRlbXM7IF9pNisrKSB7CiAgICAgICAgICBfZmV0Y2hSZWNvcmQocGVuZGluZ0ZldGNoSXRlbXNbX2k2XSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgR2V0IHRoZSByZWZlcmVuY2UgZm9yIHRoZSBzcGVjaWZpZWQgcmVjb3JkLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgdXNlclJlZiA9IHN0b3JlLmdldFJlZmVyZW5jZSgndXNlcicsIDEpOwogICAgICAgLy8gY2hlY2sgaWYgdGhlIHVzZXIgaXMgbG9hZGVkCiAgICAgIGxldCBpc0xvYWRlZCA9IHVzZXJSZWYudmFsdWUoKSAhPT0gbnVsbDsKICAgICAgIC8vIGdldCB0aGUgcmVjb3JkIG9mIHRoZSByZWZlcmVuY2UgKG51bGwgaWYgbm90IHlldCBhdmFpbGFibGUpCiAgICAgIGxldCB1c2VyID0gdXNlclJlZi52YWx1ZSgpOwogICAgICAgLy8gZ2V0IHRoZSBpZGVudGlmaWVyIG9mIHRoZSByZWZlcmVuY2UKICAgICAgaWYgKHVzZXJSZWYucmVtb3RlVHlwZSgpID09PSAnaWQnKSB7CiAgICAgIGxldCBpZCA9IHVzZXJSZWYuaWQoKTsKICAgICAgfQogICAgICAgLy8gbG9hZCB1c2VyICh2aWEgc3RvcmUuZmluZCkKICAgICAgdXNlclJlZi5sb2FkKCkudGhlbiguLi4pCiAgICAgICAvLyBvciB0cmlnZ2VyIGEgcmVsb2FkCiAgICAgIHVzZXJSZWYucmVsb2FkKCkudGhlbiguLi4pCiAgICAgICAvLyBwcm92aWRlIGRhdGEgZm9yIHJlZmVyZW5jZQogICAgICB1c2VyUmVmLnB1c2goeyBpZDogMSwgdXNlcm5hbWU6ICdAdXNlcicgfSkudGhlbihmdW5jdGlvbih1c2VyKSB7CiAgICAgICAgdXNlclJlZi52YWx1ZSgpID09PSB1c2VyOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGdldFJlZmVyZW5jZQogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7U3RyaW5nfEludGVnZXJ9IGlkCiAgICAgIEBzaW5jZSAyLjUuMAogICAgICBAcmV0dXJuIHtSZWNvcmRSZWZlcmVuY2V9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5nZXRSZWZlcmVuY2UgPSBmdW5jdGlvbiBnZXRSZWZlcmVuY2UobW9kZWxOYW1lLCBpZCkgewoKICAgICAgdmFyIHR5cGUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgdmFyIG5vcm1hbGl6ZWRJZCA9IGVuc3VyZVN0cmluZ0lkKGlkKTsKICAgICAgdmFyIHJlc291cmNlID0gY29uc3RydWN0UmVzb3VyY2UodHlwZSwgbm9ybWFsaXplZElkKTsKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLmxvb2t1cChyZXNvdXJjZSkucmVjb3JkUmVmZXJlbmNlOwogICAgfQogICAgLyoqCiAgICAgIEdldCBhIHJlY29yZCBieSBhIGdpdmVuIHR5cGUgYW5kIElEIHdpdGhvdXQgdHJpZ2dlcmluZyBhIGZldGNoLgogICAgICAgVGhpcyBtZXRob2Qgd2lsbCBzeW5jaHJvbm91c2x5IHJldHVybiB0aGUgcmVjb3JkIGlmIGl0IGlzIGF2YWlsYWJsZSBpbiB0aGUgc3RvcmUsCiAgICAgIG90aGVyd2lzZSBpdCB3aWxsIHJldHVybiBgbnVsbGAuIEEgcmVjb3JkIGlzIGF2YWlsYWJsZSBpZiBpdCBoYXMgYmVlbiBmZXRjaGVkIGVhcmxpZXIsIG9yCiAgICAgIHB1c2hlZCBtYW51YWxseSBpbnRvIHRoZSBzdG9yZS4KICAgICAgIFNlZSBbZmluZFJlY29yZF0oU3RvcmUvbWV0aG9kcy9maW5kUmVjb3JkP2FuY2hvcj1maW5kUmVjb3JkKSBpZiB5b3Ugd291bGQgbGlrZSB0byByZXF1ZXN0IHRoaXMgcmVjb3JkIGZyb20gdGhlIGJhY2tlbmQuCiAgICAgICBfTm90ZTogVGhpcyBpcyBhIHN5bmNocm9ub3VzIG1ldGhvZCBhbmQgZG9lcyBub3QgcmV0dXJuIGEgcHJvbWlzZS5fCiAgICAgICBgYGBqcwogICAgICBsZXQgcG9zdCA9IHN0b3JlLnBlZWtSZWNvcmQoJ3Bvc3QnLCAxKTsKICAgICAgIHBvc3QuZ2V0KCdpZCcpOyAvLyAxCiAgICAgIGBgYAogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIHBlZWtSZWNvcmQKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0ge1N0cmluZ3xJbnRlZ2VyfSBpZAogICAgICBAcmV0dXJuIHtNb2RlbHxudWxsfSByZWNvcmQKICAgICovCiAgICA7CgogICAgX3Byb3RvLnBlZWtSZWNvcmQgPSBmdW5jdGlvbiBwZWVrUmVjb3JkKG1vZGVsTmFtZSwgaWQpIHsKICAgICAgdmFyIHR5cGUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgdmFyIG5vcm1hbGl6ZWRJZCA9IGVuc3VyZVN0cmluZ0lkKGlkKTsKCiAgICAgIGlmICh0aGlzLmhhc1JlY29yZEZvcklkKHR5cGUsIG5vcm1hbGl6ZWRJZCkpIHsKICAgICAgICB2YXIgcmVzb3VyY2UgPSBjb25zdHJ1Y3RSZXNvdXJjZSh0eXBlLCBub3JtYWxpemVkSWQpOwogICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5sb29rdXAocmVzb3VyY2UpLmdldFJlY29yZCgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIGJ5IHRoZSByZWNvcmQncyBgcmVsb2FkYCBtZXRob2QuCiAgICAgICBUaGlzIG1ldGhvZCBjYWxscyB0aGUgYWRhcHRlcidzIGBmaW5kYCBtZXRob2QsIHdoaWNoIHJldHVybnMgYSBwcm9taXNlLiBXaGVuCiAgICAgICoqdGhhdCoqIHByb21pc2UgcmVzb2x2ZXMsIGBfcmVsb2FkUmVjb3JkYCB3aWxsIHJlc29sdmUgdGhlIHByb21pc2UgcmV0dXJuZWQKICAgICAgYnkgdGhlIHJlY29yZCdzIGByZWxvYWRgLgogICAgICAgQG1ldGhvZCBfcmVsb2FkUmVjb3JkCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7TW9kZWx9IGludGVybmFsTW9kZWwKICAgICAgQHBhcmFtIG9wdGlvbnMgb3B0aW9uYWwgdG8gaW5jbHVkZSBhZGFwdGVyT3B0aW9ucwogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5fcmVsb2FkUmVjb3JkID0gZnVuY3Rpb24gX3JlbG9hZFJlY29yZChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICBvcHRpb25zLmlzUmVsb2FkaW5nID0gdHJ1ZTsKICAgICAgfQoKICAgICAgdmFyIGlkID0gaW50ZXJuYWxNb2RlbC5pZCwKICAgICAgICAgIG1vZGVsTmFtZSA9IGludGVybmFsTW9kZWwubW9kZWxOYW1lOwogICAgICB2YXIgYWRhcHRlciA9IHRoaXMuYWRhcHRlckZvcihtb2RlbE5hbWUpOwogICAgICByZXR1cm4gdGhpcy5fc2NoZWR1bGVGZXRjaChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKTsKICAgIH0KICAgIC8qKgogICAgIFRoaXMgbWV0aG9kIHJldHVybnMgdHJ1ZSBpZiBhIHJlY29yZCBmb3IgYSBnaXZlbiBtb2RlbE5hbWUgYW5kIGlkIGlzIGFscmVhZHkKICAgICBsb2FkZWQgaW4gdGhlIHN0b3JlLiBVc2UgdGhpcyBmdW5jdGlvbiB0byBrbm93IGJlZm9yZWhhbmQgaWYgYSBmaW5kUmVjb3JkKCkKICAgICB3aWxsIHJlc3VsdCBpbiBhIHJlcXVlc3Qgb3IgdGhhdCBpdCB3aWxsIGJlIGEgY2FjaGUgaGl0LgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBzdG9yZS5oYXNSZWNvcmRGb3JJZCgncG9zdCcsIDEpOyAvLyBmYWxzZQogICAgIHN0b3JlLmZpbmRSZWNvcmQoJ3Bvc3QnLCAxKS50aGVuKGZ1bmN0aW9uKCkgewogICAgICAgc3RvcmUuaGFzUmVjb3JkRm9ySWQoJ3Bvc3QnLCAxKTsgLy8gdHJ1ZQogICAgIH0pOwogICAgIGBgYAogICAgICAgQG1ldGhvZCBoYXNSZWNvcmRGb3JJZAogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7KFN0cmluZ3xJbnRlZ2VyKX0gaWQKICAgICAgQHJldHVybiB7Qm9vbGVhbn0KICAgICovCiAgICA7CgogICAgX3Byb3RvLmhhc1JlY29yZEZvcklkID0gZnVuY3Rpb24gaGFzUmVjb3JkRm9ySWQobW9kZWxOYW1lLCBpZCkgewogICAgICB2YXIgdHlwZSA9IG5vcm1hbGl6ZU1vZGVsTmFtZShtb2RlbE5hbWUpOwogICAgICB2YXIgdHJ1ZUlkID0gZW5zdXJlU3RyaW5nSWQoaWQpOwogICAgICB2YXIgcmVzb3VyY2UgPSB7CiAgICAgICAgdHlwZTogdHlwZSwKICAgICAgICBpZDogdHJ1ZUlkCiAgICAgIH07CiAgICAgIHZhciBpZGVudGlmaWVyID0gaWRlbnRpZmllckNhY2hlRm9yKHRoaXMpLnBlZWtSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlKTsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpZGVudGlmaWVyICYmIGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLnBlZWsoaWRlbnRpZmllcik7CiAgICAgIHJldHVybiAhIWludGVybmFsTW9kZWwgJiYgaW50ZXJuYWxNb2RlbC5pc0xvYWRlZCgpOwogICAgfQogICAgLyoqCiAgICAgIFJldHVybnMgaWQgcmVjb3JkIGZvciBhIGdpdmVuIHR5cGUgYW5kIElELiBJZiBvbmUgaXNuJ3QgYWxyZWFkeSBsb2FkZWQsCiAgICAgIGl0IGJ1aWxkcyBhIG5ldyByZWNvcmQgYW5kIGxlYXZlcyBpdCBpbiB0aGUgYGVtcHR5YCBzdGF0ZS4KICAgICAgIEBtZXRob2QgcmVjb3JkRm9ySWQKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0geyhTdHJpbmd8SW50ZWdlcil9IGlkCiAgICAgIEByZXR1cm4ge01vZGVsfSByZWNvcmQKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlY29yZEZvcklkID0gZnVuY3Rpb24gcmVjb3JkRm9ySWQobW9kZWxOYW1lLCBpZCkgewogICAgICB2YXIgcmVzb3VyY2UgPSBjb25zdHJ1Y3RSZXNvdXJjZShtb2RlbE5hbWUsIGVuc3VyZVN0cmluZ0lkKGlkKSk7CiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5sb29rdXAocmVzb3VyY2UpLmdldFJlY29yZCgpOwogICAgfQogICAgLyoqCiAgICAgIEBtZXRob2QgZmluZE1hbnkKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtBcnJheX0gaW50ZXJuYWxNb2RlbHMKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZmluZE1hbnkgPSBmdW5jdGlvbiBmaW5kTWFueShpbnRlcm5hbE1vZGVscywgb3B0aW9ucykgewoKICAgICAgdmFyIGZpbmRzID0gbmV3IEFycmF5KGludGVybmFsTW9kZWxzLmxlbmd0aCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGludGVybmFsTW9kZWxzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgZmluZHNbaV0gPSB0aGlzLl9maW5kRW1wdHlJbnRlcm5hbE1vZGVsKGludGVybmFsTW9kZWxzW2ldLCBvcHRpb25zKTsKICAgICAgfQoKICAgICAgcmV0dXJuIEVtYmVyLlJTVlAuUHJvbWlzZS5hbGwoZmluZHMpOwogICAgfQogICAgLyoqCiAgICAgIElmIGEgcmVsYXRpb25zaGlwIHdhcyBvcmlnaW5hbGx5IHBvcHVsYXRlZCBieSB0aGUgYWRhcHRlciBhcyBhIGxpbmsKICAgICAgKGFzIG9wcG9zZWQgdG8gYSBsaXN0IG9mIElEcyksIHRoaXMgbWV0aG9kIGlzIGNhbGxlZCB3aGVuIHRoZQogICAgICByZWxhdGlvbnNoaXAgaXMgZmV0Y2hlZC4KICAgICAgIFRoZSBsaW5rICh3aGljaCBpcyB1c3VhbGx5IGEgVVJMKSBpcyBwYXNzZWQgdGhyb3VnaCB1bmNoYW5nZWQsIHNvIHRoZQogICAgICBhZGFwdGVyIGNhbiBtYWtlIHdoYXRldmVyIHJlcXVlc3QgaXQgd2FudHMuCiAgICAgICBUaGUgdXN1YWwgdXNlLWNhc2UgaXMgZm9yIHRoZSBzZXJ2ZXIgdG8gcmVnaXN0ZXIgYSBVUkwgYXMgYSBsaW5rLCBhbmQKICAgICAgdGhlbiB1c2UgdGhhdCBVUkwgaW4gdGhlIGZ1dHVyZSB0byBtYWtlIGEgcmVxdWVzdCBmb3IgdGhlIHJlbGF0aW9uc2hpcC4KICAgICAgIEBtZXRob2QgZmluZEhhc01hbnkKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtJbnRlcm5hbE1vZGVsfSBpbnRlcm5hbE1vZGVsCiAgICAgIEBwYXJhbSB7YW55fSBsaW5rCiAgICAgIEBwYXJhbSB7KFJlbGF0aW9uc2hpcCl9IHJlbGF0aW9uc2hpcAogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5maW5kSGFzTWFueSA9IGZ1bmN0aW9uIGZpbmRIYXNNYW55KGludGVybmFsTW9kZWwsIGxpbmssIHJlbGF0aW9uc2hpcCwgb3B0aW9ucykgewoKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXJGb3IoaW50ZXJuYWxNb2RlbC5tb2RlbE5hbWUpOwogICAgICByZXR1cm4gX2ZpbmRIYXNNYW55KGFkYXB0ZXIsIHRoaXMsIGludGVybmFsTW9kZWwsIGxpbmssIHJlbGF0aW9uc2hpcCwgb3B0aW9ucyk7CiAgICB9OwoKICAgIF9wcm90by5fZmluZEhhc01hbnlCeUpzb25BcGlSZXNvdXJjZSA9IGZ1bmN0aW9uIF9maW5kSGFzTWFueUJ5SnNvbkFwaVJlc291cmNlKHJlc291cmNlLCBwYXJlbnRJbnRlcm5hbE1vZGVsLCByZWxhdGlvbnNoaXBNZXRhLCBvcHRpb25zKSB7CiAgICAgIHZhciBfdGhpczQgPSB0aGlzOwoKICAgICAgaWYgKCFyZXNvdXJjZSkgewogICAgICAgIHJldHVybiBFbWJlci5SU1ZQLnJlc29sdmUoW10pOwogICAgICB9CgogICAgICB2YXIgX3Jlc291cmNlJF9yZWxhdGlvbnNoID0gcmVzb3VyY2UuX3JlbGF0aW9uc2hpcCwKICAgICAgICAgIHJlbGF0aW9uc2hpcElzU3RhbGUgPSBfcmVzb3VyY2UkX3JlbGF0aW9uc2gucmVsYXRpb25zaGlwSXNTdGFsZSwKICAgICAgICAgIGFsbEludmVyc2VSZWNvcmRzQXJlTG9hZGVkID0gX3Jlc291cmNlJF9yZWxhdGlvbnNoLmFsbEludmVyc2VSZWNvcmRzQXJlTG9hZGVkLAogICAgICAgICAgaGFzRGVtYXRlcmlhbGl6ZWRJbnZlcnNlID0gX3Jlc291cmNlJF9yZWxhdGlvbnNoLmhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSwKICAgICAgICAgIGhhc0FueVJlbGF0aW9uc2hpcERhdGEgPSBfcmVzb3VyY2UkX3JlbGF0aW9uc2guaGFzQW55UmVsYXRpb25zaGlwRGF0YSwKICAgICAgICAgIHJlbGF0aW9uc2hpcElzRW1wdHkgPSBfcmVzb3VyY2UkX3JlbGF0aW9uc2gucmVsYXRpb25zaGlwSXNFbXB0eSwKICAgICAgICAgIHNob3VsZEZvcmNlUmVsb2FkID0gX3Jlc291cmNlJF9yZWxhdGlvbnNoLnNob3VsZEZvcmNlUmVsb2FkOwogICAgICB2YXIgc2hvdWxkRmluZFZpYUxpbmsgPSByZXNvdXJjZS5saW5rcyAmJiByZXNvdXJjZS5saW5rcy5yZWxhdGVkICYmIChzaG91bGRGb3JjZVJlbG9hZCB8fCBoYXNEZW1hdGVyaWFsaXplZEludmVyc2UgfHwgcmVsYXRpb25zaGlwSXNTdGFsZSB8fCAhYWxsSW52ZXJzZVJlY29yZHNBcmVMb2FkZWQgJiYgIXJlbGF0aW9uc2hpcElzRW1wdHkpOyAvLyBmZXRjaCB2aWEgbGluawoKICAgICAgaWYgKHNob3VsZEZpbmRWaWFMaW5rKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZmluZEhhc01hbnkocGFyZW50SW50ZXJuYWxNb2RlbCwgcmVzb3VyY2UubGlua3MucmVsYXRlZCwgcmVsYXRpb25zaGlwTWV0YSwgb3B0aW9ucykudGhlbihmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbHMpIHsKICAgICAgICAgIHZhciBwYXlsb2FkID0gewogICAgICAgICAgICBkYXRhOiBpbnRlcm5hbE1vZGVscy5tYXAoZnVuY3Rpb24gKGltKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHJlY29yZERhdGFGb3IoaW0pLmdldFJlc291cmNlSWRlbnRpZmllcigpOwogICAgICAgICAgICB9KQogICAgICAgICAgfTsKCiAgICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbHMubWV0YSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHBheWxvYWQubWV0YSA9IGludGVybmFsTW9kZWxzLm1ldGE7CiAgICAgICAgICB9CgogICAgICAgICAgcGFyZW50SW50ZXJuYWxNb2RlbC5saW5rV2FzTG9hZGVkRm9yUmVsYXRpb25zaGlwKHJlbGF0aW9uc2hpcE1ldGEua2V5LCBwYXlsb2FkKTsKICAgICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsczsKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgdmFyIHByZWZlckxvY2FsQ2FjaGUgPSBoYXNBbnlSZWxhdGlvbnNoaXBEYXRhICYmICFyZWxhdGlvbnNoaXBJc0VtcHR5OwogICAgICB2YXIgaGFzTG9jYWxQYXJ0aWFsRGF0YSA9IGhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSB8fCByZWxhdGlvbnNoaXBJc0VtcHR5ICYmIEFycmF5LmlzQXJyYXkocmVzb3VyY2UuZGF0YSkgJiYgcmVzb3VyY2UuZGF0YS5sZW5ndGggPiAwOyAvLyBmZXRjaCB1c2luZyBkYXRhLCBwdWxsaW5nIGZyb20gbG9jYWwgY2FjaGUgaWYgcG9zc2libGUKCiAgICAgIGlmICghc2hvdWxkRm9yY2VSZWxvYWQgJiYgIXJlbGF0aW9uc2hpcElzU3RhbGUgJiYgKHByZWZlckxvY2FsQ2FjaGUgfHwgaGFzTG9jYWxQYXJ0aWFsRGF0YSkpIHsKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbHMgPSByZXNvdXJjZS5kYXRhLm1hcChmdW5jdGlvbiAoanNvbikgewogICAgICAgICAgcmV0dXJuIF90aGlzNC5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlKGpzb24pOwogICAgICAgIH0pOwogICAgICAgIHJldHVybiB0aGlzLmZpbmRNYW55KGludGVybmFsTW9kZWxzLCBvcHRpb25zKTsKICAgICAgfQoKICAgICAgdmFyIGhhc0RhdGEgPSBoYXNBbnlSZWxhdGlvbnNoaXBEYXRhICYmICFyZWxhdGlvbnNoaXBJc0VtcHR5OyAvLyBmZXRjaCBieSBkYXRhCgogICAgICBpZiAoaGFzRGF0YSB8fCBoYXNMb2NhbFBhcnRpYWxEYXRhKSB7CiAgICAgICAgdmFyIF9pbnRlcm5hbE1vZGVscyA9IHJlc291cmNlLmRhdGEubWFwKGZ1bmN0aW9uIChqc29uKSB7CiAgICAgICAgICByZXR1cm4gX3RoaXM0Ll9pbnRlcm5hbE1vZGVsRm9yUmVzb3VyY2UoanNvbik7CiAgICAgICAgfSk7CgogICAgICAgIHJldHVybiB0aGlzLl9zY2hlZHVsZUZldGNoTWFueShfaW50ZXJuYWxNb2RlbHMsIG9wdGlvbnMpOwogICAgICB9IC8vIHdlIHdlcmUgZXhwbGljaXRseSB0b2xkIHdlIGhhdmUgbm8gZGF0YSBhbmQgbm8gbGlua3MuCiAgICAgIC8vICAgVE9ETyBpZiB0aGUgcmVsYXRpb25zaGlwSXNTdGFsZSwgc2hvdWxkIHdlIGhpdCB0aGUgYWRhcHRlciBhbnl3YXk/CgoKICAgICAgcmV0dXJuIEVtYmVyLlJTVlAucmVzb2x2ZShbXSk7CiAgICB9OwoKICAgIF9wcm90by5fZ2V0SGFzTWFueUJ5SnNvbkFwaVJlc291cmNlID0gZnVuY3Rpb24gX2dldEhhc01hbnlCeUpzb25BcGlSZXNvdXJjZShyZXNvdXJjZSkgewogICAgICB2YXIgX3RoaXM1ID0gdGhpczsKCiAgICAgIHZhciBpbnRlcm5hbE1vZGVscyA9IFtdOwoKICAgICAgaWYgKHJlc291cmNlICYmIHJlc291cmNlLmRhdGEpIHsKICAgICAgICBpbnRlcm5hbE1vZGVscyA9IHJlc291cmNlLmRhdGEubWFwKGZ1bmN0aW9uIChyZWZlcmVuY2UpIHsKICAgICAgICAgIHJldHVybiBfdGhpczUuX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShyZWZlcmVuY2UpOwogICAgICAgIH0pOwogICAgICB9CgogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbHM7CiAgICB9CiAgICAvKioKICAgICAgQG1ldGhvZCBmaW5kQmVsb25nc1RvCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7SW50ZXJuYWxNb2RlbH0gaW50ZXJuYWxNb2RlbAogICAgICBAcGFyYW0ge2FueX0gbGluawogICAgICBAcGFyYW0ge1JlbGF0aW9uc2hpcH0gcmVsYXRpb25zaGlwCiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICA7CgogICAgX3Byb3RvLmZpbmRCZWxvbmdzVG8gPSBmdW5jdGlvbiBmaW5kQmVsb25nc1RvKGludGVybmFsTW9kZWwsIGxpbmssIHJlbGF0aW9uc2hpcCwgb3B0aW9ucykgewoKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXJGb3IoaW50ZXJuYWxNb2RlbC5tb2RlbE5hbWUpOwogICAgICByZXR1cm4gX2ZpbmRCZWxvbmdzVG8oYWRhcHRlciwgdGhpcywgaW50ZXJuYWxNb2RlbCwgbGluaywgcmVsYXRpb25zaGlwLCBvcHRpb25zKTsKICAgIH07CgogICAgX3Byb3RvLl9mZXRjaEJlbG9uZ3NUb0xpbmtGcm9tUmVzb3VyY2UgPSBmdW5jdGlvbiBfZmV0Y2hCZWxvbmdzVG9MaW5rRnJvbVJlc291cmNlKHJlc291cmNlLCBwYXJlbnRJbnRlcm5hbE1vZGVsLCByZWxhdGlvbnNoaXBNZXRhLCBvcHRpb25zKSB7CiAgICAgIGlmICghcmVzb3VyY2UgfHwgIXJlc291cmNlLmxpbmtzIHx8ICFyZXNvdXJjZS5saW5rcy5yZWxhdGVkKSB7CiAgICAgICAgLy8gc2hvdWxkIHdlIHdhcm4gaGVyZSwgbm90IHN1cmUgY2F1c2UgaXRzIGFuIGludGVybmFsIG1ldGhvZAogICAgICAgIHJldHVybiBFbWJlci5SU1ZQLnJlc29sdmUobnVsbCk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLmZpbmRCZWxvbmdzVG8ocGFyZW50SW50ZXJuYWxNb2RlbCwgcmVzb3VyY2UubGlua3MucmVsYXRlZCwgcmVsYXRpb25zaGlwTWV0YSwgb3B0aW9ucykudGhlbihmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIHZhciByZXNwb25zZSA9IGludGVybmFsTW9kZWwgJiYgcmVjb3JkRGF0YUZvcihpbnRlcm5hbE1vZGVsKS5nZXRSZXNvdXJjZUlkZW50aWZpZXIoKTsKCiAgICAgICAgcGFyZW50SW50ZXJuYWxNb2RlbC5saW5rV2FzTG9hZGVkRm9yUmVsYXRpb25zaGlwKHJlbGF0aW9uc2hpcE1ldGEua2V5LCB7CiAgICAgICAgICBkYXRhOiByZXNwb25zZQogICAgICAgIH0pOwoKICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbCA9PT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfSAvLyBUT0RPIElnb3IgdGhpcyBkb2Vzbid0IHNlZW0gbGlrZSB0aGUgcmlnaHQgYm91bmRhcnksIHByb2JhYmx5IHRoZSBjYWxsZXIgbWV0aG9kIHNob3VsZCBleHRyYWN0IHRoZSByZWNvcmQgb3V0CgoKICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5nZXRSZWNvcmQoKTsKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5fZmluZEJlbG9uZ3NUb0J5SnNvbkFwaVJlc291cmNlID0gZnVuY3Rpb24gX2ZpbmRCZWxvbmdzVG9CeUpzb25BcGlSZXNvdXJjZShyZXNvdXJjZSwgcGFyZW50SW50ZXJuYWxNb2RlbCwgcmVsYXRpb25zaGlwTWV0YSwgb3B0aW9ucykgewogICAgICBpZiAoIXJlc291cmNlKSB7CiAgICAgICAgcmV0dXJuIEVtYmVyLlJTVlAucmVzb2x2ZShudWxsKTsKICAgICAgfQoKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSByZXNvdXJjZS5kYXRhID8gdGhpcy5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlKHJlc291cmNlLmRhdGEpIDogbnVsbDsKICAgICAgdmFyIF9yZXNvdXJjZSRfcmVsYXRpb25zaDIgPSByZXNvdXJjZS5fcmVsYXRpb25zaGlwLAogICAgICAgICAgcmVsYXRpb25zaGlwSXNTdGFsZSA9IF9yZXNvdXJjZSRfcmVsYXRpb25zaDIucmVsYXRpb25zaGlwSXNTdGFsZSwKICAgICAgICAgIGFsbEludmVyc2VSZWNvcmRzQXJlTG9hZGVkID0gX3Jlc291cmNlJF9yZWxhdGlvbnNoMi5hbGxJbnZlcnNlUmVjb3Jkc0FyZUxvYWRlZCwKICAgICAgICAgIGhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSA9IF9yZXNvdXJjZSRfcmVsYXRpb25zaDIuaGFzRGVtYXRlcmlhbGl6ZWRJbnZlcnNlLAogICAgICAgICAgaGFzQW55UmVsYXRpb25zaGlwRGF0YSA9IF9yZXNvdXJjZSRfcmVsYXRpb25zaDIuaGFzQW55UmVsYXRpb25zaGlwRGF0YSwKICAgICAgICAgIHJlbGF0aW9uc2hpcElzRW1wdHkgPSBfcmVzb3VyY2UkX3JlbGF0aW9uc2gyLnJlbGF0aW9uc2hpcElzRW1wdHksCiAgICAgICAgICBzaG91bGRGb3JjZVJlbG9hZCA9IF9yZXNvdXJjZSRfcmVsYXRpb25zaDIuc2hvdWxkRm9yY2VSZWxvYWQ7CiAgICAgIHZhciBzaG91bGRGaW5kVmlhTGluayA9IHJlc291cmNlLmxpbmtzICYmIHJlc291cmNlLmxpbmtzLnJlbGF0ZWQgJiYgKHNob3VsZEZvcmNlUmVsb2FkIHx8IGhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSB8fCByZWxhdGlvbnNoaXBJc1N0YWxlIHx8ICFhbGxJbnZlcnNlUmVjb3Jkc0FyZUxvYWRlZCAmJiAhcmVsYXRpb25zaGlwSXNFbXB0eSk7CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIC8vIHNob3J0IGNpcmN1aXQgaWYgd2UgYXJlIGFscmVhZHkgbG9hZGluZwogICAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICAgIC8vIFRlbXBvcmFyeSBmaXggZm9yIHJlcXVlc3RzIGFscmVhZHkgbG9hZGluZyB1bnRpbCB3ZSBtb3ZlIHRoaXMgaW5zaWRlIHRoZSBmZXRjaCBtYW5hZ2VyCiAgICAgICAgICB2YXIgcGVuZGluZ1JlcXVlc3RzID0gdGhpcy5nZXRSZXF1ZXN0U3RhdGVTZXJ2aWNlKCkuZ2V0UGVuZGluZ1JlcXVlc3RzRm9yUmVjb3JkKGludGVybmFsTW9kZWwuaWRlbnRpZmllcikuZmlsdGVyKGZ1bmN0aW9uIChyZXEpIHsKICAgICAgICAgICAgcmV0dXJuIHJlcS50eXBlID09PSAncXVlcnknOwogICAgICAgICAgfSk7CgogICAgICAgICAgaWYgKHBlbmRpbmdSZXF1ZXN0cy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIHJldHVybiBwZW5kaW5nUmVxdWVzdHNbMF1bUmVxdWVzdFByb21pc2VdLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLmdldFJlY29yZCgpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKGludGVybmFsTW9kZWwuaXNMb2FkaW5nKCkpIHsKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwuX3Byb21pc2VQcm94eS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5nZXRSZWNvcmQoKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IC8vIGZldGNoIHZpYSBsaW5rCgoKICAgICAgaWYgKHNob3VsZEZpbmRWaWFMaW5rKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2ZldGNoQmVsb25nc1RvTGlua0Zyb21SZXNvdXJjZShyZXNvdXJjZSwgcGFyZW50SW50ZXJuYWxNb2RlbCwgcmVsYXRpb25zaGlwTWV0YSwgb3B0aW9ucyk7CiAgICAgIH0KCiAgICAgIHZhciBwcmVmZXJMb2NhbENhY2hlID0gaGFzQW55UmVsYXRpb25zaGlwRGF0YSAmJiBhbGxJbnZlcnNlUmVjb3Jkc0FyZUxvYWRlZCAmJiAhcmVsYXRpb25zaGlwSXNFbXB0eTsKICAgICAgdmFyIGhhc0xvY2FsUGFydGlhbERhdGEgPSBoYXNEZW1hdGVyaWFsaXplZEludmVyc2UgfHwgcmVsYXRpb25zaGlwSXNFbXB0eSAmJiByZXNvdXJjZS5kYXRhOyAvLyBudWxsIGlzIGV4cGxpY2l0IGVtcHR5LCB1bmRlZmluZWQgaXMgIndlIGRvbid0IGtub3cgYW55dGhpbmciCgogICAgICB2YXIgbG9jYWxEYXRhSXNFbXB0eSA9IHJlc291cmNlLmRhdGEgPT09IHVuZGVmaW5lZCB8fCByZXNvdXJjZS5kYXRhID09PSBudWxsOyAvLyBmZXRjaCB1c2luZyBkYXRhLCBwdWxsaW5nIGZyb20gbG9jYWwgY2FjaGUgaWYgcG9zc2libGUKCiAgICAgIGlmICghc2hvdWxkRm9yY2VSZWxvYWQgJiYgIXJlbGF0aW9uc2hpcElzU3RhbGUgJiYgKHByZWZlckxvY2FsQ2FjaGUgfHwgaGFzTG9jYWxQYXJ0aWFsRGF0YSkpIHsKICAgICAgICAvKgogICAgICAgICAgV2UgaGF2ZSBjYW5vbmljYWwgZGF0YSwgYnV0IG91ciBsb2NhbCBzdGF0ZSBpcyBlbXB0eQogICAgICAgICAqLwogICAgICAgIGlmIChsb2NhbERhdGFJc0VtcHR5KSB7CiAgICAgICAgICByZXR1cm4gRW1iZXIuUlNWUC5yZXNvbHZlKG51bGwpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMuX2ZpbmRCeUludGVybmFsTW9kZWwoaW50ZXJuYWxNb2RlbCwgb3B0aW9ucyk7CiAgICAgIH0KCiAgICAgIHZhciByZXNvdXJjZUlzTG9jYWwgPSAhbG9jYWxEYXRhSXNFbXB0eSAmJiByZXNvdXJjZS5kYXRhLmlkID09PSBudWxsOwoKICAgICAgaWYgKGludGVybmFsTW9kZWwgJiYgcmVzb3VyY2VJc0xvY2FsKSB7CiAgICAgICAgcmV0dXJuIEVtYmVyLlJTVlAucmVzb2x2ZShpbnRlcm5hbE1vZGVsLmdldFJlY29yZCgpKTsKICAgICAgfSAvLyBmZXRjaCBieSBkYXRhCgoKICAgICAgaWYgKGludGVybmFsTW9kZWwgJiYgIWxvY2FsRGF0YUlzRW1wdHkpIHsKICAgICAgICByZXR1cm4gdGhpcy5fc2NoZWR1bGVGZXRjaChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLmdldFJlY29yZCgpOwogICAgICAgIH0pOwogICAgICB9IC8vIHdlIHdlcmUgZXhwbGljaXRseSB0b2xkIHdlIGhhdmUgbm8gZGF0YSBhbmQgbm8gbGlua3MuCiAgICAgIC8vICAgVE9ETyBpZiB0aGUgcmVsYXRpb25zaGlwSXNTdGFsZSwgc2hvdWxkIHdlIGhpdCB0aGUgYWRhcHRlciBhbnl3YXk/CgoKICAgICAgcmV0dXJuIEVtYmVyLlJTVlAucmVzb2x2ZShudWxsKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBkZWxlZ2F0ZXMgYSBxdWVyeSB0byB0aGUgYWRhcHRlci4gVGhpcyBpcyB0aGUgb25lIHBsYWNlIHdoZXJlCiAgICAgIGFkYXB0ZXItbGV2ZWwgc2VtYW50aWNzIGFyZSBleHBvc2VkIHRvIHRoZSBhcHBsaWNhdGlvbi4KICAgICAgIEVhY2ggdGltZSB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgYSBuZXcgcmVxdWVzdCBpcyBtYWRlIHRocm91Z2ggdGhlIGFkYXB0ZXIuCiAgICAgICBFeHBvc2luZyBxdWVyaWVzIHRoaXMgd2F5IHNlZW1zIHByZWZlcmFibGUgdG8gY3JlYXRpbmcgYW4gYWJzdHJhY3QgcXVlcnkKICAgICAgbGFuZ3VhZ2UgZm9yIGFsbCBzZXJ2ZXItc2lkZSBxdWVyaWVzLCBhbmQgdGhlbiByZXF1aXJlIGFsbCBhZGFwdGVycyB0bwogICAgICBpbXBsZW1lbnQgdGhlbS4KICAgICAgIC0tLQogICAgICAgSWYgeW91IGRvIHNvbWV0aGluZyBsaWtlIHRoaXM6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0b3JlLnF1ZXJ5KCdwZXJzb24nLCB7IHBhZ2U6IDEgfSk7CiAgICAgIGBgYAogICAgICAgVGhlIHJlcXVlc3QgbWFkZSB0byB0aGUgc2VydmVyIHdpbGwgbG9vayBzb21ldGhpbmcgbGlrZSB0aGlzOgogICAgICAgYGBgCiAgICAgIEdFVCAiL2FwaS92MS9wZXJzb24/cGFnZT0xIgogICAgICBgYGAKICAgICAgIC0tLQogICAgICAgSWYgeW91IGRvIHNvbWV0aGluZyBsaWtlIHRoaXM6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0b3JlLnF1ZXJ5KCdwZXJzb24nLCB7IGlkczogWzEsIDIsIDNdIH0pOwogICAgICBgYGAKICAgICAgIFRoZSByZXF1ZXN0IG1hZGUgdG8gdGhlIHNlcnZlciB3aWxsIGxvb2sgc29tZXRoaW5nIGxpa2UgdGhpczoKICAgICAgIGBgYAogICAgICBHRVQgIi9hcGkvdjEvcGVyc29uP2lkcyU1QiU1RD0xJmlkcyU1QiU1RD0yJmlkcyU1QiU1RD0zIgogICAgICBkZWNvZGVkOiAiL2FwaS92MS9wZXJzb24/aWRzW109MSZpZHNbXT0yJmlkc1tdPTMiCiAgICAgIGBgYAogICAgICAgVGhpcyBtZXRob2QgcmV0dXJucyBhIHByb21pc2UsIHdoaWNoIGlzIHJlc29sdmVkIHdpdGggYW4KICAgICAgW2BBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXlgXSgvZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5KQogICAgICBvbmNlIHRoZSBzZXJ2ZXIgcmV0dXJucy4KICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBxdWVyeQogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7YW55fSBxdWVyeSBhbiBvcGFxdWUgcXVlcnkgdG8gYmUgdXNlZCBieSB0aGUgYWRhcHRlcgogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBvcHRpb25hbCwgbWF5IGluY2x1ZGUgYGFkYXB0ZXJPcHRpb25zYCBoYXNoIHdoaWNoIHdpbGwgYmUgcGFzc2VkIHRvIGFkYXB0ZXIucXVlcnkKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucXVlcnkgPSBmdW5jdGlvbiBxdWVyeShtb2RlbE5hbWUsIF9xdWVyeTIsIG9wdGlvbnMpIHsKICAgICAgdmFyIGFkYXB0ZXJPcHRpb25zV3JhcHBlciA9IHt9OwoKICAgICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5hZGFwdGVyT3B0aW9ucykgewogICAgICAgIGFkYXB0ZXJPcHRpb25zV3JhcHBlci5hZGFwdGVyT3B0aW9ucyA9IG9wdGlvbnMuYWRhcHRlck9wdGlvbnM7CiAgICAgIH0KCiAgICAgIHZhciBub3JtYWxpemVkTW9kZWxOYW1lID0gbm9ybWFsaXplTW9kZWxOYW1lKG1vZGVsTmFtZSk7CiAgICAgIHJldHVybiB0aGlzLl9xdWVyeShub3JtYWxpemVkTW9kZWxOYW1lLCBfcXVlcnkyLCBudWxsLCBhZGFwdGVyT3B0aW9uc1dyYXBwZXIpOwogICAgfTsKCiAgICBfcHJvdG8uX3F1ZXJ5ID0gZnVuY3Rpb24gX3F1ZXJ5JDEobW9kZWxOYW1lLCBxdWVyeSwgYXJyYXksIG9wdGlvbnMpIHsKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIHByb21pc2VBcnJheShfcXVlcnkoYWRhcHRlciwgdGhpcywgbW9kZWxOYW1lLCBxdWVyeSwgYXJyYXksIG9wdGlvbnMpKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBtYWtlcyBhIHJlcXVlc3QgZm9yIG9uZSByZWNvcmQsIHdoZXJlIHRoZSBgaWRgIGlzIG5vdCBrbm93bgogICAgICBiZWZvcmVoYW5kIChpZiB0aGUgYGlkYCBpcyBrbm93biwgdXNlIFtgZmluZFJlY29yZGBdKFN0b3JlL21ldGhvZHMvZmluZFJlY29yZD9hbmNob3I9ZmluZFJlY29yZCkKICAgICAgaW5zdGVhZCkuCiAgICAgICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB3aGVuIGl0IGlzIGNlcnRhaW4gdGhhdCB0aGUgc2VydmVyIHdpbGwgcmV0dXJuIGEKICAgICAgc2luZ2xlIG9iamVjdCBmb3IgdGhlIHByaW1hcnkgZGF0YS4KICAgICAgIEVhY2ggdGltZSB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgYSBuZXcgcmVxdWVzdCBpcyBtYWRlIHRocm91Z2ggdGhlIGFkYXB0ZXIuCiAgICAgICBMZXQncyBhc3N1bWUgb3VyIEFQSSBwcm92aWRlcyBhbiBlbmRwb2ludCBmb3IgdGhlIGN1cnJlbnRseSBsb2dnZWQgaW4gdXNlcgogICAgICB2aWE6CiAgICAgICBgYGAKICAgICAgLy8gR0VUIC9hcGkvY3VycmVudF91c2VyCiAgICAgIHsKICAgICAgICB1c2VyOiB7CiAgICAgICAgICBpZDogMTIzNCwKICAgICAgICAgIHVzZXJuYW1lOiAnYWRtaW4nCiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgU2luY2UgdGhlIHNwZWNpZmljIGBpZGAgb2YgdGhlIGB1c2VyYCBpcyBub3Qga25vd24gYmVmb3JlaGFuZCwgd2UgY2FuIHVzZQogICAgICBgcXVlcnlSZWNvcmRgIHRvIGdldCB0aGUgdXNlcjoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc3RvcmUucXVlcnlSZWNvcmQoJ3VzZXInLCB7fSkudGhlbihmdW5jdGlvbih1c2VyKSB7CiAgICAgICAgbGV0IHVzZXJuYW1lID0gdXNlci5nZXQoJ3VzZXJuYW1lJyk7CiAgICAgICAgY29uc29sZS5sb2coYEN1cnJlbnRseSBsb2dnZWQgaW4gYXMgJHt1c2VybmFtZX1gKTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVGhlIHJlcXVlc3QgaXMgbWFkZSB0aHJvdWdoIHRoZSBhZGFwdGVycycgYHF1ZXJ5UmVjb3JkYDoKICAgICAgIGBgYGFwcC9hZGFwdGVycy91c2VyLmpzCiAgICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeSc7CiAgICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlci5leHRlbmQoewogICAgICAgIHF1ZXJ5UmVjb3JkKG1vZGVsTmFtZSwgcXVlcnkpIHsKICAgICAgICAgIHJldHVybiAkLmdldEpTT04oJy9hcGkvY3VycmVudF91c2VyJyk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBOb3RlOiB0aGUgcHJpbWFyeSB1c2UgY2FzZSBmb3IgYHN0b3JlLnF1ZXJ5UmVjb3JkYCBpcyB3aGVuIGEgc2luZ2xlIHJlY29yZAogICAgICBpcyBxdWVyaWVkIGFuZCB0aGUgYGlkYCBpcyBub3Qga25vd24gYmVmb3JlaGFuZC4gSW4gYWxsIG90aGVyIGNhc2VzCiAgICAgIGBzdG9yZS5xdWVyeWAgYW5kIHVzaW5nIHRoZSBmaXJzdCBpdGVtIG9mIHRoZSBhcnJheSBpcyBsaWtlbHkgdGhlIHByZWZlcnJlZAogICAgICB3YXk6CiAgICAgICBgYGAKICAgICAgLy8gR0VUIC91c2Vycz91c2VybmFtZT11bmlxdWUKICAgICAgewogICAgICAgIGRhdGE6IFt7CiAgICAgICAgICBpZDogMTIzNCwKICAgICAgICAgIHR5cGU6ICd1c2VyJywKICAgICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgICAgdXNlcm5hbWU6ICJ1bmlxdWUiCiAgICAgICAgICB9CiAgICAgICAgfV0KICAgICAgfQogICAgICBgYGAKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc3RvcmUucXVlcnkoJ3VzZXInLCB7IHVzZXJuYW1lOiAndW5pcXVlJyB9KS50aGVuKGZ1bmN0aW9uKHVzZXJzKSB7CiAgICAgICAgcmV0dXJuIHVzZXJzLmdldCgnZmlyc3RPYmplY3QnKTsKICAgICAgfSkudGhlbihmdW5jdGlvbih1c2VyKSB7CiAgICAgICAgbGV0IGlkID0gdXNlci5nZXQoJ2lkJyk7CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRoaXMgbWV0aG9kIHJldHVybnMgYSBwcm9taXNlLCB3aGljaCByZXNvbHZlcyB3aXRoIHRoZSBmb3VuZCByZWNvcmQuCiAgICAgICBJZiB0aGUgYWRhcHRlciByZXR1cm5zIG5vIGRhdGEgZm9yIHRoZSBwcmltYXJ5IGRhdGEgb2YgdGhlIHBheWxvYWQsIHRoZW4KICAgICAgYHF1ZXJ5UmVjb3JkYCByZXNvbHZlcyB3aXRoIGBudWxsYDoKICAgICAgIGBgYAogICAgICAvLyBHRVQgL3VzZXJzP3VzZXJuYW1lPXVuaXF1ZQogICAgICB7CiAgICAgICAgZGF0YTogbnVsbAogICAgICB9CiAgICAgIGBgYAogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBzdG9yZS5xdWVyeVJlY29yZCgndXNlcicsIHsgdXNlcm5hbWU6ICd1bmlxdWUnIH0pLnRoZW4oZnVuY3Rpb24odXNlcikgewogICAgICAgIGNvbnNvbGUubG9nKHVzZXIpOyAvLyBudWxsCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBxdWVyeVJlY29yZAogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7YW55fSBxdWVyeSBhbiBvcGFxdWUgcXVlcnkgdG8gYmUgdXNlZCBieSB0aGUgYWRhcHRlcgogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBvcHRpb25hbCwgbWF5IGluY2x1ZGUgYGFkYXB0ZXJPcHRpb25zYCBoYXNoIHdoaWNoIHdpbGwgYmUgcGFzc2VkIHRvIGFkYXB0ZXIucXVlcnlSZWNvcmQKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aXRoIHRoZSBmb3VuZCByZWNvcmQgb3IgYG51bGxgCiAgICAqLwogICAgOwoKICAgIF9wcm90by5xdWVyeVJlY29yZCA9IGZ1bmN0aW9uIHF1ZXJ5UmVjb3JkKG1vZGVsTmFtZSwgcXVlcnksIG9wdGlvbnMpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXJGb3Iobm9ybWFsaXplZE1vZGVsTmFtZSk7CiAgICAgIHZhciBhZGFwdGVyT3B0aW9uc1dyYXBwZXIgPSB7fTsKCiAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuYWRhcHRlck9wdGlvbnMpIHsKICAgICAgICBhZGFwdGVyT3B0aW9uc1dyYXBwZXIuYWRhcHRlck9wdGlvbnMgPSBvcHRpb25zLmFkYXB0ZXJPcHRpb25zOwogICAgICB9CiAgICAgIHJldHVybiBwcm9taXNlT2JqZWN0KF9xdWVyeVJlY29yZChhZGFwdGVyLCB0aGlzLCBub3JtYWxpemVkTW9kZWxOYW1lLCBxdWVyeSwgYWRhcHRlck9wdGlvbnNXcmFwcGVyKS50aGVuKGZ1bmN0aW9uIChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgLy8gdGhlIHByb21pc2UgcmV0dXJuZWQgYnkgc3RvcmUucXVlcnlSZWNvcmQgaXMgZXhwZWN0ZWQgdG8gcmVzb2x2ZSB3aXRoCiAgICAgICAgLy8gYW4gaW5zdGFuY2Ugb2YgTW9kZWwKICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwuZ2V0UmVjb3JkKCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfSkpOwogICAgfQogICAgLyoqCiAgICAgIGBmaW5kQWxsYCBhc2tzIHRoZSBhZGFwdGVyJ3MgYGZpbmRBbGxgIG1ldGhvZCB0byBmaW5kIHRoZSByZWNvcmRzIGZvciB0aGUKICAgICAgZ2l2ZW4gdHlwZSwgYW5kIHJldHVybnMgYSBwcm9taXNlIHdoaWNoIHdpbGwgcmVzb2x2ZSB3aXRoIGFsbCByZWNvcmRzIG9mCiAgICAgIHRoaXMgdHlwZSBwcmVzZW50IGluIHRoZSBzdG9yZSwgZXZlbiBpZiB0aGUgYWRhcHRlciBvbmx5IHJldHVybnMgYSBzdWJzZXQKICAgICAgb2YgdGhlbS4KICAgICAgIGBgYGFwcC9yb3V0ZXMvYXV0aG9ycy5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBtb2RlbChwYXJhbXMpIHsKICAgICAgICAgIHJldHVybiB0aGlzLnN0b3JlLmZpbmRBbGwoJ2F1dGhvcicpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgX1doZW5fIHRoZSByZXR1cm5lZCBwcm9taXNlIHJlc29sdmVzIGRlcGVuZHMgb24gdGhlIHJlbG9hZCBiZWhhdmlvciwKICAgICAgY29uZmlndXJlZCB2aWEgdGhlIHBhc3NlZCBgb3B0aW9uc2AgaGFzaCBhbmQgdGhlIHJlc3VsdCBvZiB0aGUgYWRhcHRlcidzCiAgICAgIGBzaG91bGRSZWxvYWRBbGxgIG1ldGhvZC4KICAgICAgICMjIyBSZWxvYWRpbmcKICAgICAgIElmIGB7IHJlbG9hZDogdHJ1ZSB9YCBpcyBwYXNzZWQgb3IgYGFkYXB0ZXIuc2hvdWxkUmVsb2FkQWxsYCBldmFsdWF0ZXMgdG8KICAgICAgYHRydWVgLCB0aGVuIHRoZSByZXR1cm5lZCBwcm9taXNlIHJlc29sdmVzIG9uY2UgdGhlIGFkYXB0ZXIgcmV0dXJucyBkYXRhLAogICAgICByZWdhcmRsZXNzIGlmIHRoZXJlIGFyZSBhbHJlYWR5IHJlY29yZHMgaW4gdGhlIHN0b3JlOgogICAgICAgYGBganMKICAgICAgc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgaWQ6ICdmaXJzdCcsCiAgICAgICAgICB0eXBlOiAnYXV0aG9yJwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICAvLyBhZGFwdGVyI2ZpbmRBbGwgcmVzb2x2ZXMgd2l0aAogICAgICAvLyBbCiAgICAgIC8vICAgewogICAgICAvLyAgICAgaWQ6ICdzZWNvbmQnLAogICAgICAvLyAgICAgdHlwZTogJ2F1dGhvcicKICAgICAgLy8gICB9CiAgICAgIC8vIF0KICAgICAgc3RvcmUuZmluZEFsbCgnYXV0aG9yJywgeyByZWxvYWQ6IHRydWUgfSkudGhlbihmdW5jdGlvbihhdXRob3JzKSB7CiAgICAgICAgYXV0aG9ycy5nZXRFYWNoKCdpZCcpOyAvLyBbJ2ZpcnN0JywgJ3NlY29uZCddCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIElmIG5vIHJlbG9hZCBpcyBpbmRpY2F0ZWQgdmlhIHRoZSBhYm92ZSBtZW50aW9uZWQgd2F5cywgdGhlbiB0aGUgcHJvbWlzZQogICAgICBpbW1lZGlhdGVseSByZXNvbHZlcyB3aXRoIGFsbCB0aGUgcmVjb3JkcyBjdXJyZW50bHkgbG9hZGVkIGluIHRoZSBzdG9yZS4KICAgICAgICMjIyBCYWNrZ3JvdW5kIFJlbG9hZGluZwogICAgICAgT3B0aW9uYWxseSwgaWYgYGFkYXB0ZXIuc2hvdWxkQmFja2dyb3VuZFJlbG9hZEFsbGAgZXZhbHVhdGVzIHRvIGB0cnVlYCwKICAgICAgdGhlbiBhIGJhY2tncm91bmQgcmVsb2FkIGlzIHN0YXJ0ZWQuIE9uY2UgdGhpcyByZXNvbHZlcywgdGhlIGFycmF5IHdpdGgKICAgICAgd2hpY2ggdGhlIHByb21pc2UgcmVzb2x2ZXMsIGlzIHVwZGF0ZWQgYXV0b21hdGljYWxseSBzbyBpdCBjb250YWlucyBhbGwgdGhlCiAgICAgIHJlY29yZHMgaW4gdGhlIHN0b3JlOgogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgc2hvdWxkUmVsb2FkQWxsKHN0b3JlLCBzbmFwc2hvdHNBcnJheSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0sCiAgICAgICAgIHNob3VsZEJhY2tncm91bmRSZWxvYWRBbGwoc3RvcmUsIHNuYXBzaG90c0FycmF5KSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgLy8gLi4uCiAgICAgICBzdG9yZS5wdXNoKHsKICAgICAgICBkYXRhOiB7CiAgICAgICAgICBpZDogJ2ZpcnN0JywKICAgICAgICAgIHR5cGU6ICdhdXRob3InCiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGxldCBhbGxBdXRob3JzOwogICAgICBzdG9yZS5maW5kQWxsKCdhdXRob3InKS50aGVuKGZ1bmN0aW9uKGF1dGhvcnMpIHsKICAgICAgICBhdXRob3JzLmdldEVhY2goJ2lkJyk7IC8vIFsnZmlyc3QnXQogICAgICAgICBhbGxBdXRob3JzID0gYXV0aG9yczsKICAgICAgfSk7CiAgICAgICAvLyBsYXRlciwgb25jZSBhZGFwdGVyI2ZpbmRBbGwgcmVzb2x2ZWQgd2l0aAogICAgICAvLyBbCiAgICAgIC8vICAgewogICAgICAvLyAgICAgaWQ6ICdzZWNvbmQnLAogICAgICAvLyAgICAgdHlwZTogJ2F1dGhvcicKICAgICAgLy8gICB9CiAgICAgIC8vIF0KICAgICAgIGFsbEF1dGhvcnMuZ2V0RWFjaCgnaWQnKTsgLy8gWydmaXJzdCcsICdzZWNvbmQnXQogICAgICBgYGAKICAgICAgIElmIHlvdSB3b3VsZCBsaWtlIHRvIGZvcmNlIG9yIHByZXZlbnQgYmFja2dyb3VuZCByZWxvYWRpbmcsIHlvdSBjYW4gc2V0IGEKICAgICAgYm9vbGVhbiB2YWx1ZSBmb3IgYGJhY2tncm91bmRSZWxvYWRgIGluIHRoZSBvcHRpb25zIG9iamVjdCBmb3IKICAgICAgYGZpbmRBbGxgLgogICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0L2VkaXQuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgbW9kZWwoKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5zdG9yZS5maW5kQWxsKCdwb3N0JywgeyBiYWNrZ3JvdW5kUmVsb2FkOiBmYWxzZSB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIElmIHlvdSBwYXNzIGFuIG9iamVjdCBvbiB0aGUgYGFkYXB0ZXJPcHRpb25zYCBwcm9wZXJ0eSBvZiB0aGUgb3B0aW9ucwogICAgICBhcmd1bWVudCBpdCB3aWxsIGJlIHBhc3NlZCB0byB5b3UgYWRhcHRlciB2aWEgdGhlIGBzbmFwc2hvdFJlY29yZEFycmF5YAogICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0cy5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBtb2RlbChwYXJhbXMpIHsKICAgICAgICAgIHJldHVybiB0aGlzLnN0b3JlLmZpbmRBbGwoJ3Bvc3QnLCB7CiAgICAgICAgICAgIGFkYXB0ZXJPcHRpb25zOiB7IHN1YnNjcmliZTogZmFsc2UgfQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvcG9zdC5qcwogICAgICBpbXBvcnQgTXlDdXN0b21BZGFwdGVyIGZyb20gJy4vY3VzdG9tLWFkYXB0ZXInOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTXlDdXN0b21BZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgZmluZEFsbChzdG9yZSwgdHlwZSwgc2luY2VUb2tlbiwgc25hcHNob3RSZWNvcmRBcnJheSkgewogICAgICAgICAgaWYgKHNuYXBzaG90UmVjb3JkQXJyYXkuYWRhcHRlck9wdGlvbnMuc3Vic2NyaWJlKSB7CiAgICAgICAgICAgIC8vIC4uLgogICAgICAgICAgfQogICAgICAgICAgLy8gLi4uCiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBTZWUgW3BlZWtBbGxdKFN0b3JlL21ldGhvZHMvcGVla0FsbD9hbmNob3I9cGVla0FsbCkgdG8gZ2V0IGFuIGFycmF5IG9mIGN1cnJlbnQgcmVjb3JkcyBpbiB0aGUKICAgICAgc3RvcmUsIHdpdGhvdXQgd2FpdGluZyB1bnRpbCBhIHJlbG9hZCBpcyBmaW5pc2hlZC4KICAgICAgICMjIyBSZXRyaWV2aW5nIFJlbGF0ZWQgTW9kZWwgUmVjb3JkcwogICAgICAgSWYgeW91IHVzZSBhbiBhZGFwdGVyIHN1Y2ggYXMgRW1iZXIncyBkZWZhdWx0CiAgICAgIFtgSlNPTkFQSUFkYXB0ZXJgXSgvZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvSlNPTkFQSUFkYXB0ZXIpCiAgICAgIHRoYXQgc3VwcG9ydHMgdGhlIFtKU09OIEFQSSBzcGVjaWZpY2F0aW9uXShodHRwOi8vanNvbmFwaS5vcmcvKSBhbmQgaWYgeW91ciBzZXJ2ZXIKICAgICAgZW5kcG9pbnQgc3VwcG9ydHMgdGhlIHVzZSBvZiBhbgogICAgICBbJ2luY2x1ZGUnIHF1ZXJ5IHBhcmFtZXRlcl0oaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdC8jZmV0Y2hpbmctaW5jbHVkZXMpLAogICAgICB5b3UgY2FuIHVzZSBgZmluZEFsbCgpYCB0byBhdXRvbWF0aWNhbGx5IHJldHJpZXZlIGFkZGl0aW9uYWwgcmVjb3JkcyByZWxhdGVkIHRvCiAgICAgIHRob3NlIHJlcXVlc3RlZCBieSBzdXBwbHlpbmcgYW4gYGluY2x1ZGVgIHBhcmFtZXRlciBpbiB0aGUgYG9wdGlvbnNgIG9iamVjdC4KICAgICAgIEZvciBleGFtcGxlLCBnaXZlbiBhIGBwb3N0YCBtb2RlbCB0aGF0IGhhcyBhIGBoYXNNYW55YCByZWxhdGlvbnNoaXAgd2l0aCBhIGBjb21tZW50YAogICAgICBtb2RlbCwgd2hlbiB3ZSByZXRyaWV2ZSBhbGwgb2YgdGhlIHBvc3QgcmVjb3JkcyB3ZSBjYW4gaGF2ZSB0aGUgc2VydmVyIGFsc28gcmV0dXJuCiAgICAgIGFsbCBvZiB0aGUgcG9zdHMnIGNvbW1lbnRzIGluIHRoZSBzYW1lIHJlcXVlc3Q6CiAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3RzLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIG1vZGVsKCkgewogICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZmluZEFsbCgncG9zdCcsIHsgaW5jbHVkZTogJ2NvbW1lbnRzJyB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgYGBgCiAgICAgIE11bHRpcGxlIHJlbGF0aW9uc2hpcHMgY2FuIGJlIHJlcXVlc3RlZCB1c2luZyBhbiBgaW5jbHVkZWAgcGFyYW1ldGVyIGNvbnNpc3Rpbmcgb2YgYQogICAgICBjb21tYS1zZXBhcmF0ZWQgbGlzdCAod2l0aG91dCB3aGl0ZS1zcGFjZSkgd2hpbGUgbmVzdGVkIHJlbGF0aW9uc2hpcHMgY2FuIGJlIHNwZWNpZmllZAogICAgICB1c2luZyBhIGRvdC1zZXBhcmF0ZWQgc2VxdWVuY2Ugb2YgcmVsYXRpb25zaGlwIG5hbWVzLiBTbyB0byByZXF1ZXN0IGJvdGggdGhlIHBvc3RzJwogICAgICBjb21tZW50cyBhbmQgdGhlIGF1dGhvcnMgb2YgdGhvc2UgY29tbWVudHMgdGhlIHJlcXVlc3Qgd291bGQgbG9vayBsaWtlIHRoaXM6CiAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3RzLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIG1vZGVsKCkgewogICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZmluZEFsbCgncG9zdCcsIHsgaW5jbHVkZTogJ2NvbW1lbnRzLGNvbW1lbnRzLmF1dGhvcicgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGBgYAogICAgICAgU2VlIFtxdWVyeV0oU3RvcmUvbWV0aG9kcy9xdWVyeT9hbmNob3I9cXVlcnkpIHRvIG9ubHkgZ2V0IGEgc3Vic2V0IG9mIHJlY29yZHMgZnJvbSB0aGUgc2VydmVyLgogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIGZpbmRBbGwKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5maW5kQWxsID0gZnVuY3Rpb24gZmluZEFsbChtb2RlbE5hbWUsIG9wdGlvbnMpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKCiAgICAgIHZhciBmZXRjaCA9IHRoaXMuX2ZldGNoQWxsKG5vcm1hbGl6ZWRNb2RlbE5hbWUsIHRoaXMucGVla0FsbChub3JtYWxpemVkTW9kZWxOYW1lKSwgb3B0aW9ucyk7CgogICAgICByZXR1cm4gZmV0Y2g7CiAgICB9CiAgICAvKioKICAgICAgQG1ldGhvZCBfZmV0Y2hBbGwKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtNb2RlbH0gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7UmVjb3JkQXJyYXl9IGFycmF5CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9mZXRjaEFsbCA9IGZ1bmN0aW9uIF9mZXRjaEFsbChtb2RlbE5hbWUsIGFycmF5LCBvcHRpb25zKSB7CiAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsKICAgICAgICBvcHRpb25zID0ge307CiAgICAgIH0KCiAgICAgIHZhciBhZGFwdGVyID0gdGhpcy5hZGFwdGVyRm9yKG1vZGVsTmFtZSk7CgogICAgICBpZiAob3B0aW9ucy5yZWxvYWQpIHsKICAgICAgICBFbWJlci5zZXQoYXJyYXksICdpc1VwZGF0aW5nJywgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIHByb21pc2VBcnJheShfZmluZEFsbChhZGFwdGVyLCB0aGlzLCBtb2RlbE5hbWUsIG9wdGlvbnMpKTsKICAgICAgfQoKICAgICAgdmFyIHNuYXBzaG90QXJyYXkgPSBhcnJheS5fY3JlYXRlU25hcHNob3Qob3B0aW9ucyk7CgogICAgICBpZiAoYWRhcHRlci5zaG91bGRSZWxvYWRBbGwodGhpcywgc25hcHNob3RBcnJheSkpIHsKICAgICAgICBFbWJlci5zZXQoYXJyYXksICdpc1VwZGF0aW5nJywgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIHByb21pc2VBcnJheShfZmluZEFsbChhZGFwdGVyLCB0aGlzLCBtb2RlbE5hbWUsIG9wdGlvbnMpKTsKICAgICAgfQoKICAgICAgaWYgKG9wdGlvbnMuYmFja2dyb3VuZFJlbG9hZCA9PT0gZmFsc2UpIHsKICAgICAgICByZXR1cm4gcHJvbWlzZUFycmF5KEVtYmVyLlJTVlAuUHJvbWlzZS5yZXNvbHZlKGFycmF5KSk7CiAgICAgIH0KCiAgICAgIGlmIChvcHRpb25zLmJhY2tncm91bmRSZWxvYWQgfHwgYWRhcHRlci5zaG91bGRCYWNrZ3JvdW5kUmVsb2FkQWxsKHRoaXMsIHNuYXBzaG90QXJyYXkpKSB7CiAgICAgICAgRW1iZXIuc2V0KGFycmF5LCAnaXNVcGRhdGluZycsIHRydWUpOwoKICAgICAgICBfZmluZEFsbChhZGFwdGVyLCB0aGlzLCBtb2RlbE5hbWUsIG9wdGlvbnMpOwogICAgICB9CgogICAgICByZXR1cm4gcHJvbWlzZUFycmF5KEVtYmVyLlJTVlAuUHJvbWlzZS5yZXNvbHZlKGFycmF5KSk7CiAgICB9CiAgICAvKioKICAgICAgQG1ldGhvZCBfZGlkVXBkYXRlQWxsCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9kaWRVcGRhdGVBbGwgPSBmdW5jdGlvbiBfZGlkVXBkYXRlQWxsKG1vZGVsTmFtZSkgewogICAgICB0aGlzLnJlY29yZEFycmF5TWFuYWdlci5fZGlkVXBkYXRlQWxsKG1vZGVsTmFtZSk7CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgcmV0dXJucyBhIGZpbHRlcmVkIGFycmF5IHRoYXQgY29udGFpbnMgYWxsIG9mIHRoZQogICAgICBrbm93biByZWNvcmRzIGZvciBhIGdpdmVuIHR5cGUgaW4gdGhlIHN0b3JlLgogICAgICAgTm90ZSB0aGF0IGJlY2F1c2UgaXQncyBqdXN0IGEgZmlsdGVyLCB0aGUgcmVzdWx0IHdpbGwgY29udGFpbiBhbnkKICAgICAgbG9jYWxseSBjcmVhdGVkIHJlY29yZHMgb2YgdGhlIHR5cGUsIGhvd2V2ZXIsIGl0IHdpbGwgbm90IG1ha2UgYQogICAgICByZXF1ZXN0IHRvIHRoZSBiYWNrZW5kIHRvIHJldHJpZXZlIGFkZGl0aW9uYWwgcmVjb3Jkcy4gSWYgeW91CiAgICAgIHdvdWxkIGxpa2UgdG8gcmVxdWVzdCBhbGwgdGhlIHJlY29yZHMgZnJvbSB0aGUgYmFja2VuZCBwbGVhc2UgdXNlCiAgICAgIFtzdG9yZS5maW5kQWxsXShTdG9yZS9tZXRob2RzL2ZpbmRBbGw/YW5jaG9yPWZpbmRBbGwpLgogICAgICAgQWxzbyBub3RlIHRoYXQgbXVsdGlwbGUgY2FsbHMgdG8gYHBlZWtBbGxgIGZvciBhIGdpdmVuIHR5cGUgd2lsbCBhbHdheXMKICAgICAgcmV0dXJuIHRoZSBzYW1lIGBSZWNvcmRBcnJheWAuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBsb2NhbFBvc3RzID0gc3RvcmUucGVla0FsbCgncG9zdCcpOwogICAgICBgYGAKICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBwZWVrQWxsCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHJldHVybiB7UmVjb3JkQXJyYXl9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5wZWVrQWxsID0gZnVuY3Rpb24gcGVla0FsbChtb2RlbE5hbWUpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIHRoaXMucmVjb3JkQXJyYXlNYW5hZ2VyLmxpdmVSZWNvcmRBcnJheUZvcihub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCB1bmxvYWRzIGFsbCByZWNvcmRzIGluIHRoZSBzdG9yZS4KICAgICAgSXQgc2NoZWR1bGVzIHVubG9hZGluZyB0byBoYXBwZW4gZHVyaW5nIHRoZSBuZXh0IHJ1biBsb29wLgogICAgICAgT3B0aW9uYWxseSB5b3UgY2FuIHBhc3MgYSB0eXBlIHdoaWNoIHVubG9hZCBhbGwgcmVjb3JkcyBmb3IgYSBnaXZlbiB0eXBlLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBzdG9yZS51bmxvYWRBbGwoKTsKICAgICAgc3RvcmUudW5sb2FkQWxsKCdwb3N0Jyk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCB1bmxvYWRBbGwKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8udW5sb2FkQWxsID0gZnVuY3Rpb24gdW5sb2FkQWxsKG1vZGVsTmFtZSkgewogICAgICB2YXIgZmFjdG9yeSA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpOwoKICAgICAgaWYgKG1vZGVsTmFtZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZmFjdG9yeS5jbGVhcigpOwogICAgICB9IGVsc2UgewogICAgICAgIHZhciBub3JtYWxpemVkTW9kZWxOYW1lID0gbm9ybWFsaXplTW9kZWxOYW1lKG1vZGVsTmFtZSk7CiAgICAgICAgZmFjdG9yeS5jbGVhcihub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uZmlsdGVyID0gZnVuY3Rpb24gZmlsdGVyKCkgewogICAgfSAvLyAuLi4uLi4uLi4uLi4uLgogICAgLy8gLiBQRVJTSVNUSU5HIC4KICAgIC8vIC4uLi4uLi4uLi4uLi4uCgogICAgLyoqCiAgICAgIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBieSBgcmVjb3JkLnNhdmVgLCBhbmQgZ2V0cyBwYXNzZWQgYQogICAgICByZXNvbHZlciBmb3IgdGhlIHByb21pc2UgdGhhdCBgcmVjb3JkLnNhdmVgIHJldHVybnMuCiAgICAgICBJdCBzY2hlZHVsZXMgc2F2aW5nIHRvIGhhcHBlbiBhdCB0aGUgZW5kIG9mIHRoZSBydW4gbG9vcC4KICAgICAgIEBtZXRob2Qgc2NoZWR1bGVTYXZlCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7SW50ZXJuYWxNb2RlbH0gaW50ZXJuYWxNb2RlbAogICAgICBAcGFyYW0ge1Jlc29sdmVyfSByZXNvbHZlcgogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uc2NoZWR1bGVTYXZlID0gZnVuY3Rpb24gc2NoZWR1bGVTYXZlKGludGVybmFsTW9kZWwsIHJlc29sdmVyLCBvcHRpb25zKSB7CiAgICAgIHZhciBfdGhpczYgPSB0aGlzOwoKICAgICAgdmFyIHNuYXBzaG90ID0gaW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdChvcHRpb25zKTsKCiAgICAgIGlmIChpbnRlcm5hbE1vZGVsLl9pc1JlY29yZEZ1bGx5RGVsZXRlZCgpKSB7CiAgICAgICAgcmVzb2x2ZXIucmVzb2x2ZSgpOwogICAgICAgIHJldHVybiByZXNvbHZlci5wcm9taXNlOwogICAgICB9CgogICAgICBpbnRlcm5hbE1vZGVsLmFkYXB0ZXJXaWxsQ29tbWl0KCk7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgaWYgKCFvcHRpb25zKSB7CiAgICAgICAgICBvcHRpb25zID0ge307CiAgICAgICAgfQoKICAgICAgICB2YXIgcmVjb3JkRGF0YSA9IGludGVybmFsTW9kZWwuX3JlY29yZERhdGE7CiAgICAgICAgdmFyIG9wZXJhdGlvbiA9ICd1cGRhdGVSZWNvcmQnOyAvLyBUT0RPIGhhbmRsZSBtaXNzaW5nIGlzTmV3CgogICAgICAgIGlmIChyZWNvcmREYXRhLmlzTmV3ICYmIHJlY29yZERhdGEuaXNOZXcoKSkgewogICAgICAgICAgb3BlcmF0aW9uID0gJ2NyZWF0ZVJlY29yZCc7CiAgICAgICAgfSBlbHNlIGlmIChyZWNvcmREYXRhLmlzRGVsZXRlZCAmJiByZWNvcmREYXRhLmlzRGVsZXRlZCgpKSB7CiAgICAgICAgICBvcGVyYXRpb24gPSAnZGVsZXRlUmVjb3JkJzsKICAgICAgICB9CgogICAgICAgIG9wdGlvbnNbU2F2ZU9wXSA9IG9wZXJhdGlvbjsKCiAgICAgICAgdmFyIGZldGNoTWFuYWdlclByb21pc2UgPSB0aGlzLl9mZXRjaE1hbmFnZXIuc2NoZWR1bGVTYXZlKGludGVybmFsTW9kZWwuaWRlbnRpZmllciwgb3B0aW9ucyk7CgogICAgICAgIHZhciBwcm9taXNlID0gZmV0Y2hNYW5hZ2VyUHJvbWlzZS50aGVuKGZ1bmN0aW9uIChwYXlsb2FkKSB7CiAgICAgICAgICAvKgogICAgICAgICAgTm90ZSB0byBmdXR1cmUgc3BlbHVua2VycyBob3BpbmcgdG8gb3B0aW1pemUuCiAgICAgICAgICBXZSByZWx5IG9uIHRoaXMgYHJ1bmAgdG8gY3JlYXRlIGEgcnVuIGxvb3AgaWYgbmVlZGVkCiAgICAgICAgICB0aGF0IGBzdG9yZS5fcHVzaGAgYW5kIGBzdG9yZS5kaWRTYXZlUmVjb3JkYCB3aWxsIGJvdGggc2hhcmUuCiAgICAgICAgICBXZSB1c2UgYGpvaW5gIGJlY2F1c2UgaXQgaXMgb2Z0ZW4gdGhlIGNhc2UgdGhhdCB3ZQogICAgICAgICAgaGF2ZSBhbiBvdXRlciBydW4gbG9vcCBhdmFpbGFibGUgc3RpbGwgZnJvbSB0aGUgZmlyc3QKICAgICAgICAgIGNhbGwgdG8gYHN0b3JlLl9wdXNoYDsKICAgICAgICAgICovCiAgICAgICAgICBfdGhpczYuX2JhY2tidXJuZXIuam9pbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIHZhciBkYXRhID0gcGF5bG9hZCAmJiBwYXlsb2FkLmRhdGE7CgogICAgICAgICAgICBfdGhpczYuZGlkU2F2ZVJlY29yZChpbnRlcm5hbE1vZGVsLCB7CiAgICAgICAgICAgICAgZGF0YTogZGF0YQogICAgICAgICAgICB9LCBvcGVyYXRpb24pOwoKICAgICAgICAgICAgaWYgKHBheWxvYWQgJiYgcGF5bG9hZC5pbmNsdWRlZCkgewogICAgICAgICAgICAgIF90aGlzNi5fcHVzaCh7CiAgICAgICAgICAgICAgICBkYXRhOiBudWxsLAogICAgICAgICAgICAgICAgaW5jbHVkZWQ6IHBheWxvYWQuaW5jbHVkZWQKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfSwgZnVuY3Rpb24gKF9yZWYpIHsKICAgICAgICAgIHZhciBlcnJvciA9IF9yZWYuZXJyb3IsCiAgICAgICAgICAgICAgcGFyc2VkRXJyb3JzID0gX3JlZi5wYXJzZWRFcnJvcnM7CgogICAgICAgICAgX3RoaXM2LnJlY29yZFdhc0ludmFsaWQoaW50ZXJuYWxNb2RlbCwgcGFyc2VkRXJyb3JzLCBlcnJvcik7CgogICAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIHByb21pc2U7CiAgICAgIH0KCiAgICAgIHRoaXMuX3BlbmRpbmdTYXZlLnB1c2goewogICAgICAgIHNuYXBzaG90OiBzbmFwc2hvdCwKICAgICAgICByZXNvbHZlcjogcmVzb2x2ZXIKICAgICAgfSk7CgogICAgICBlbWJlclJ1biQyLnNjaGVkdWxlT25jZSgnYWN0aW9ucycsIHRoaXMsIHRoaXMuZmx1c2hQZW5kaW5nU2F2ZSk7CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIGF0IHRoZSBlbmQgb2YgdGhlIHJ1biBsb29wLCBhbmQKICAgICAgZmx1c2hlcyBhbnkgcmVjb3JkcyBwYXNzZWQgaW50byBgc2NoZWR1bGVTYXZlYAogICAgICAgQG1ldGhvZCBmbHVzaFBlbmRpbmdTYXZlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5mbHVzaFBlbmRpbmdTYXZlID0gZnVuY3Rpb24gZmx1c2hQZW5kaW5nU2F2ZSgpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgICAgIC8vIGFzc2VydCBoZXJlCiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgcGVuZGluZyA9IHRoaXMuX3BlbmRpbmdTYXZlLnNsaWNlKCk7CgogICAgICB0aGlzLl9wZW5kaW5nU2F2ZSA9IFtdOwoKICAgICAgZm9yICh2YXIgaSA9IDAsIGogPSBwZW5kaW5nLmxlbmd0aDsgaSA8IGo7IGkrKykgewogICAgICAgIHZhciBwZW5kaW5nSXRlbSA9IHBlbmRpbmdbaV07CiAgICAgICAgdmFyIHNuYXBzaG90ID0gcGVuZGluZ0l0ZW0uc25hcHNob3Q7CiAgICAgICAgdmFyIHJlc29sdmVyID0gcGVuZGluZ0l0ZW0ucmVzb2x2ZXI7CiAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBzbmFwc2hvdC5faW50ZXJuYWxNb2RlbDsKICAgICAgICB2YXIgYWRhcHRlciA9IHRoaXMuYWRhcHRlckZvcihpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZSk7CiAgICAgICAgdmFyIG9wZXJhdGlvbiA9IHZvaWQgMDsKCiAgICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX1NUQVRFKSB7CiAgICAgICAgICAvLyBUT0RPIG1vdmUgdGhpcyBvdXQgb2YgaW50ZXJuYWxNb2RlbAogICAgICAgICAgaWYgKGludGVybmFsTW9kZWwuaXNOZXcoKSkgewogICAgICAgICAgICBvcGVyYXRpb24gPSAnY3JlYXRlUmVjb3JkJzsKICAgICAgICAgIH0gZWxzZSBpZiAoaW50ZXJuYWxNb2RlbC5pc0RlbGV0ZWQoKSkgewogICAgICAgICAgICBvcGVyYXRpb24gPSAnZGVsZXRlUmVjb3JkJzsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9wZXJhdGlvbiA9ICd1cGRhdGVSZWNvcmQnOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbC5jdXJyZW50U3RhdGUuc3RhdGVOYW1lID09PSAncm9vdC5kZWxldGVkLnNhdmVkJykgewogICAgICAgICAgICByZXNvbHZlci5yZXNvbHZlKCk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfSBlbHNlIGlmIChpbnRlcm5hbE1vZGVsLmlzTmV3KCkpIHsKICAgICAgICAgICAgb3BlcmF0aW9uID0gJ2NyZWF0ZVJlY29yZCc7CiAgICAgICAgICB9IGVsc2UgaWYgKGludGVybmFsTW9kZWwuaXNEZWxldGVkKCkpIHsKICAgICAgICAgICAgb3BlcmF0aW9uID0gJ2RlbGV0ZVJlY29yZCc7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcGVyYXRpb24gPSAndXBkYXRlUmVjb3JkJzsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJlc29sdmVyLnJlc29sdmUoX2NvbW1pdChhZGFwdGVyLCB0aGlzLCBvcGVyYXRpb24sIHNuYXBzaG90KSk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgb25jZSB0aGUgcHJvbWlzZSByZXR1cm5lZCBieSBhbgogICAgICBhZGFwdGVyJ3MgYGNyZWF0ZVJlY29yZGAsIGB1cGRhdGVSZWNvcmRgIG9yIGBkZWxldGVSZWNvcmRgCiAgICAgIGlzIHJlc29sdmVkLgogICAgICAgSWYgdGhlIGRhdGEgcHJvdmlkZXMgYSBzZXJ2ZXItZ2VuZXJhdGVkIElELCBpdCB3aWxsCiAgICAgIHVwZGF0ZSB0aGUgcmVjb3JkIGFuZCB0aGUgc3RvcmUncyBpbmRleGVzLgogICAgICAgQG1ldGhvZCBkaWRTYXZlUmVjb3JkCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7SW50ZXJuYWxNb2RlbH0gaW50ZXJuYWxNb2RlbCB0aGUgaW4tZmxpZ2h0IGludGVybmFsIG1vZGVsCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBkYXRhIG9wdGlvbmFsIGRhdGEgKHNlZSBhYm92ZSkKICAgICAgQHBhcmFtIHtzdHJpbmd9IG9wIHRoZSBhZGFwdGVyIG9wZXJhdGlvbiB0aGF0IHdhcyBjb21taXR0ZWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLmRpZFNhdmVSZWNvcmQgPSBmdW5jdGlvbiBkaWRTYXZlUmVjb3JkKGludGVybmFsTW9kZWwsIGRhdGFBcmcsIG9wKSB7CgogICAgICB2YXIgZGF0YTsKCiAgICAgIGlmIChkYXRhQXJnKSB7CiAgICAgICAgZGF0YSA9IGRhdGFBcmcuZGF0YTsKICAgICAgfQoKICAgICAgewogICAgICAgIHZhciBjYWNoZSA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzKTsKICAgICAgICB2YXIgX2lkZW50aWZpZXIzID0gaW50ZXJuYWxNb2RlbC5pZGVudGlmaWVyOwoKICAgICAgICBpZiAob3AgIT09ICdkZWxldGVSZWNvcmQnICYmIGRhdGEpIHsKICAgICAgICAgIGNhY2hlLnVwZGF0ZVJlY29yZElkZW50aWZpZXIoX2lkZW50aWZpZXIzLCBkYXRhKTsKICAgICAgICB9CiAgICAgIH0gLy9XZSBmaXJzdCBtYWtlIHN1cmUgdGhlIHByaW1hcnkgZGF0YSBoYXMgYmVlbiB1cGRhdGVkCiAgICAgIC8vVE9ETyB0cnkgdG8gbW92ZSBub3RpZmljYXRpb24gdG8gdGhlIHVzZXIgdG8gdGhlIGVuZCBvZiB0aGUgcnVubG9vcAoKCiAgICAgIGludGVybmFsTW9kZWwuYWRhcHRlckRpZENvbW1pdChkYXRhKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgb25jZSB0aGUgcHJvbWlzZSByZXR1cm5lZCBieSBhbgogICAgICBhZGFwdGVyJ3MgYGNyZWF0ZVJlY29yZGAsIGB1cGRhdGVSZWNvcmRgIG9yIGBkZWxldGVSZWNvcmRgCiAgICAgIGlzIHJlamVjdGVkIHdpdGggYSBgSW52YWxpZEVycm9yYC4KICAgICAgIEBtZXRob2QgcmVjb3JkV2FzSW52YWxpZAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge0ludGVybmFsTW9kZWx9IGludGVybmFsTW9kZWwKICAgICAgQHBhcmFtIHtPYmplY3R9IGVycm9ycwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVjb3JkV2FzSW52YWxpZCA9IGZ1bmN0aW9uIHJlY29yZFdhc0ludmFsaWQoaW50ZXJuYWxNb2RlbCwgcGFyc2VkRXJyb3JzLCBlcnJvcikgewoKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX0VSUk9SUykgewogICAgICAgIGludGVybmFsTW9kZWwuYWRhcHRlckRpZEludmFsaWRhdGUocGFyc2VkRXJyb3JzLCBlcnJvcik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC5hZGFwdGVyRGlkSW52YWxpZGF0ZShwYXJzZWRFcnJvcnMpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIG9uY2UgdGhlIHByb21pc2UgcmV0dXJuZWQgYnkgYW4KICAgICAgYWRhcHRlcidzIGBjcmVhdGVSZWNvcmRgLCBgdXBkYXRlUmVjb3JkYCBvciBgZGVsZXRlUmVjb3JkYAogICAgICBpcyByZWplY3RlZCAod2l0aCBhbnl0aGluZyBvdGhlciB0aGFuIGEgYEludmFsaWRFcnJvcmApLgogICAgICAgQG1ldGhvZCByZWNvcmRXYXNFcnJvcgogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge0ludGVybmFsTW9kZWx9IGludGVybmFsTW9kZWwKICAgICAgQHBhcmFtIHtFcnJvcn0gZXJyb3IKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlY29yZFdhc0Vycm9yID0gZnVuY3Rpb24gcmVjb3JkV2FzRXJyb3IoaW50ZXJuYWxNb2RlbCwgZXJyb3IpIHsKCiAgICAgIGludGVybmFsTW9kZWwuYWRhcHRlckRpZEVycm9yKGVycm9yKTsKICAgIH0KICAgIC8qKgogICAgICBTZXRzIG5ld2x5IHJlY2VpdmVkIElEIGZyb20gdGhlIGFkYXB0ZXIncyBgY3JlYXRlUmVjb3JkYCwgYHVwZGF0ZVJlY29yZGAKICAgICAgb3IgYGRlbGV0ZVJlY29yZGAuCiAgICAgICBAbWV0aG9kIHNldFJlY29yZElkCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHBhcmFtIHtzdHJpbmd9IG5ld0lkCiAgICAgIEBwYXJhbSB7c3RyaW5nfSBjbGllbnRJZAogICAgICovCiAgICA7CgogICAgX3Byb3RvLnNldFJlY29yZElkID0gZnVuY3Rpb24gc2V0UmVjb3JkSWQobW9kZWxOYW1lLCBuZXdJZCwgY2xpZW50SWQpIHsKCiAgICAgIGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLnNldFJlY29yZElkKG1vZGVsTmFtZSwgbmV3SWQsIGNsaWVudElkKTsKICAgIH0gLy8gLi4uLi4uLi4uLi4uLi4uLgogICAgLy8gLiBMT0FESU5HIERBVEEgLgogICAgLy8gLi4uLi4uLi4uLi4uLi4uLgoKICAgIC8qKgogICAgICBUaGlzIGludGVybmFsIG1ldGhvZCBpcyB1c2VkIGJ5IGBwdXNoYC4KICAgICAgIEBtZXRob2QgX2xvYWQKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtPYmplY3R9IGRhdGEKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9sb2FkID0gZnVuY3Rpb24gX2xvYWQoZGF0YSkgewogICAgICB2YXIgcmVzb3VyY2UgPSBjb25zdHJ1Y3RSZXNvdXJjZShub3JtYWxpemVNb2RlbE5hbWUoZGF0YS50eXBlKSwgZW5zdXJlU3RyaW5nSWQoZGF0YS5pZCksIGNvZXJjZUlkKGRhdGEubGlkKSk7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcykubG9va3VwKHJlc291cmNlLCBkYXRhKTsgLy8gc3RvcmUucHVzaCB3aWxsIGJlIGZyb20gZW1wdHkKICAgICAgLy8gZmluZFJlY29yZCB3aWxsIGJlIGZyb20gcm9vdC5sb2FkaW5nCiAgICAgIC8vIGFsbCBlbHNlIHdpbGwgYmUgdXBkYXRlcwoKICAgICAgdmFyIGlzTG9hZGluZyA9IGludGVybmFsTW9kZWwuY3VycmVudFN0YXRlLnN0YXRlTmFtZSA9PT0gJ3Jvb3QubG9hZGluZyc7CiAgICAgIHZhciBpc1VwZGF0ZSA9IGludGVybmFsTW9kZWwuY3VycmVudFN0YXRlLmlzRW1wdHkgPT09IGZhbHNlICYmICFpc0xvYWRpbmc7CgogICAgICB7CiAgICAgICAgLy8gZXhjbHVkZSBzdG9yZS5wdXNoIChyb290LmVtcHR5KSBjYXNlCiAgICAgICAgaWYgKGlzVXBkYXRlIHx8IGlzTG9hZGluZykgewogICAgICAgICAgdmFyIF9pZGVudGlmaWVyNCA9IGludGVybmFsTW9kZWwuaWRlbnRpZmllcjsKICAgICAgICAgIHZhciB1cGRhdGVkSWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzKS51cGRhdGVSZWNvcmRJZGVudGlmaWVyKF9pZGVudGlmaWVyNCwgZGF0YSk7CgogICAgICAgICAgaWYgKHVwZGF0ZWRJZGVudGlmaWVyICE9PSBfaWRlbnRpZmllcjQpIHsKICAgICAgICAgICAgLy8gd2UgZW5jb3VudGVyZWQgYSBtZXJnZSBvZiBpZGVudGlmaWVycyBpbiB3aGljaAogICAgICAgICAgICAvLyB0d28gaWRlbnRpZmllcnMgKGFuZCBsaWtlbHkgdHdvIGludGVybmFsTW9kZWxzKQogICAgICAgICAgICAvLyBleGlzdGVkIGZvciB0aGUgc2FtZSByZXNvdXJjZS4gTm93IHRoYXQgd2UgaGF2ZQogICAgICAgICAgICAvLyBkZXRlcm1pbmVkIHRoZSBjb3JyZWN0IGlkZW50aWZpZXIgdG8gdXNlLCBtYWtlIHN1cmUKICAgICAgICAgICAgLy8gdGhhdCB3ZSBhbHNvIHVzZSB0aGUgY29ycmVjdCBpbnRlcm5hbE1vZGVsLgogICAgICAgICAgICBfaWRlbnRpZmllcjQgPSB1cGRhdGVkSWRlbnRpZmllcjsKICAgICAgICAgICAgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLmxvb2t1cChfaWRlbnRpZmllcjQpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgaW50ZXJuYWxNb2RlbC5zZXR1cERhdGEoZGF0YSk7CgogICAgICBpZiAoaXNVcGRhdGUpIHsKICAgICAgICB0aGlzLnJlY29yZEFycmF5TWFuYWdlci5yZWNvcmREaWRDaGFuZ2UoaW50ZXJuYWxNb2RlbCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5yZWNvcmRBcnJheU1hbmFnZXIucmVjb3JkV2FzTG9hZGVkKGludGVybmFsTW9kZWwpOwogICAgICB9CgogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbDsKICAgIH0KICAgIC8qKgogICAgICBQdXNoIHNvbWUgZGF0YSBmb3IgYSBnaXZlbiB0eXBlIGludG8gdGhlIHN0b3JlLgogICAgICAgVGhpcyBtZXRob2QgZXhwZWN0cyBub3JtYWxpemVkIFtKU09OIEFQSV0oaHR0cDovL2pzb25hcGkub3JnLykgZG9jdW1lbnQuIFRoaXMgbWVhbnMgeW91IGhhdmUgdG8gZm9sbG93IFtKU09OIEFQSSBzcGVjaWZpY2F0aW9uXShodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0Lykgd2l0aCBmZXcgbWlub3IgYWRqdXN0bWVudHM6CiAgICAgIC0gcmVjb3JkJ3MgYHR5cGVgIHNob3VsZCBhbHdheXMgYmUgaW4gc2luZ3VsYXIsIGRhc2hlcml6ZWQgZm9ybQogICAgICAtIG1lbWJlcnMgKHByb3BlcnRpZXMpIHNob3VsZCBiZSBjYW1lbENhc2VkCiAgICAgICBbWW91ciBwcmltYXJ5IGRhdGEgc2hvdWxkIGJlIHdyYXBwZWQgaW5zaWRlIGBkYXRhYCBwcm9wZXJ0eV0oaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdC8jZG9jdW1lbnQtdG9wLWxldmVsKToKICAgICAgIGBgYGpzCiAgICAgIHN0b3JlLnB1c2goewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIC8vIHByaW1hcnkgZGF0YSBmb3Igc2luZ2xlIHJlY29yZCBvZiB0eXBlIGBQZXJzb25gCiAgICAgICAgICBpZDogJzEnLAogICAgICAgICAgdHlwZTogJ3BlcnNvbicsCiAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgIGZpcnN0TmFtZTogJ0RhbmllbCcsCiAgICAgICAgICAgIGxhc3ROYW1lOiAnS21haycKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFtEZW1vLl0oaHR0cDovL2VtYmVyLXR3aWRkbGUuY29tL2ZiOTlmMThjZDNiNGQzZTJhNGM3KQogICAgICAgYGRhdGFgIHByb3BlcnR5IGNhbiBhbHNvIGhvbGQgYW4gYXJyYXkgKG9mIHJlY29yZHMpOgogICAgICAgYGBganMKICAgICAgc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogWwogICAgICAgICAgLy8gYW4gYXJyYXkgb2YgcmVjb3JkcwogICAgICAgICAgewogICAgICAgICAgICBpZDogJzEnLAogICAgICAgICAgICB0eXBlOiAncGVyc29uJywKICAgICAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgICAgIGZpcnN0TmFtZTogJ0RhbmllbCcsCiAgICAgICAgICAgICAgbGFzdE5hbWU6ICdLbWFrJwogICAgICAgICAgICB9CiAgICAgICAgICB9LAogICAgICAgICAgewogICAgICAgICAgICBpZDogJzInLAogICAgICAgICAgICB0eXBlOiAncGVyc29uJywKICAgICAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgICAgIGZpcnN0TmFtZTogJ1RvbScsCiAgICAgICAgICAgICAgbGFzdE5hbWU6ICdEYWxlJwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBbRGVtby5dKGh0dHA6Ly9lbWJlci10d2lkZGxlLmNvbS82OWNkYmVhYTM3MDIxNTlkYzM1NSkKICAgICAgIFRoZXJlIGFyZSBzb21lIHR5cGljYWwgcHJvcGVydGllcyBmb3IgYEpTT05BUElgIHBheWxvYWQ6CiAgICAgICogYGlkYCAtIG1hbmRhdG9yeSwgdW5pcXVlIHJlY29yZCdzIGtleQogICAgICAqIGB0eXBlYCAtIG1hbmRhdG9yeSBzdHJpbmcgd2hpY2ggbWF0Y2hlcyBgbW9kZWxgJ3MgZGFzaGVyaXplZCBuYW1lIGluIHNpbmd1bGFyIGZvcm0KICAgICAgKiBgYXR0cmlidXRlc2AgLSBvYmplY3Qgd2hpY2ggaG9sZHMgZGF0YSBmb3IgcmVjb3JkIGF0dHJpYnV0ZXMgLSBgYXR0cmAncyBkZWNsYXJlZCBpbiBtb2RlbAogICAgICAqIGByZWxhdGlvbnNoaXBzYCAtIG9iamVjdCB3aGljaCBtdXN0IGNvbnRhaW4gYW55IG9mIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyB1bmRlciBlYWNoIHJlbGF0aW9uc2hpcHMnIHJlc3BlY3RpdmUga2V5IChleGFtcGxlIHBhdGggaXMgYHJlbGF0aW9uc2hpcHMuYWNoaWV2ZW1lbnRzLmRhdGFgKToKICAgICAgICAtIFtgbGlua3NgXShodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0LyNkb2N1bWVudC1saW5rcykKICAgICAgICAtIFtgZGF0YWBdKGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2RvY3VtZW50LXJlc291cmNlLW9iamVjdC1saW5rYWdlKSAtIHBsYWNlIGZvciBwcmltYXJ5IGRhdGEKICAgICAgICAtIFtgbWV0YWBdKGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2RvY3VtZW50LW1ldGEpIC0gb2JqZWN0IHdoaWNoIGNvbnRhaW5zIG1ldGEtaW5mb3JtYXRpb24gYWJvdXQgcmVsYXRpb25zaGlwCiAgICAgICBGb3IgdGhpcyBtb2RlbDoKICAgICAgIGBgYGFwcC9tb2RlbHMvcGVyc29uLmpzCiAgICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyLCBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICBmaXJzdE5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICAgIGxhc3ROYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgICAgY2hpbGRyZW46IGhhc01hbnkoJ3BlcnNvbicpCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRvIHJlcHJlc2VudCB0aGUgY2hpbGRyZW4gYXMgSURzOgogICAgICAgYGBganMKICAgICAgewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIGlkOiAnMScsCiAgICAgICAgICB0eXBlOiAncGVyc29uJywKICAgICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgICAgZmlyc3ROYW1lOiAnVG9tJywKICAgICAgICAgICAgbGFzdE5hbWU6ICdEYWxlJwogICAgICAgICAgfSwKICAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICAgY2hpbGRyZW46IHsKICAgICAgICAgICAgICBkYXRhOiBbCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgIGlkOiAnMicsCiAgICAgICAgICAgICAgICAgIHR5cGU6ICdwZXJzb24nCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICBpZDogJzMnLAogICAgICAgICAgICAgICAgICB0eXBlOiAncGVyc29uJwogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgaWQ6ICc0JywKICAgICAgICAgICAgICAgICAgdHlwZTogJ3BlcnNvbicKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBdCiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBbRGVtby5dKGh0dHA6Ly9lbWJlci10d2lkZGxlLmNvbS8zNDNlMTczNWUwMzQwOTFmNWJkZSkKICAgICAgIFRvIHJlcHJlc2VudCB0aGUgY2hpbGRyZW4gcmVsYXRpb25zaGlwIGFzIGEgVVJMOgogICAgICAgYGBganMKICAgICAgewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIGlkOiAnMScsCiAgICAgICAgICB0eXBlOiAncGVyc29uJywKICAgICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgICAgZmlyc3ROYW1lOiAnVG9tJywKICAgICAgICAgICAgbGFzdE5hbWU6ICdEYWxlJwogICAgICAgICAgfSwKICAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICAgY2hpbGRyZW46IHsKICAgICAgICAgICAgICBsaW5rczogewogICAgICAgICAgICAgICAgcmVsYXRlZDogJy9wZW9wbGUvMS9jaGlsZHJlbicKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBJZiB5b3UncmUgc3RyZWFtaW5nIGRhdGEgb3IgaW1wbGVtZW50aW5nIGFuIGFkYXB0ZXIsIG1ha2Ugc3VyZQogICAgICB0aGF0IHlvdSBoYXZlIGNvbnZlcnRlZCB0aGUgaW5jb21pbmcgZGF0YSBpbnRvIHRoaXMgZm9ybS4gVGhlCiAgICAgIHN0b3JlJ3MgW25vcm1hbGl6ZV0oU3RvcmUvbWV0aG9kcy9ub3JtYWxpemU/YW5jaG9yPW5vcm1hbGl6ZSkgbWV0aG9kIGlzIGEgY29udmVuaWVuY2UKICAgICAgaGVscGVyIGZvciBjb252ZXJ0aW5nIGEganNvbiBwYXlsb2FkIGludG8gdGhlIGZvcm0gRW1iZXIgRGF0YQogICAgICBleHBlY3RzLgogICAgICAgYGBganMKICAgICAgc3RvcmUucHVzaChzdG9yZS5ub3JtYWxpemUoJ3BlcnNvbicsIGRhdGEpKTsKICAgICAgYGBgCiAgICAgICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCBib3RoIHRvIHB1c2ggaW4gYnJhbmQgbmV3CiAgICAgIHJlY29yZHMsIGFzIHdlbGwgYXMgdG8gdXBkYXRlIGV4aXN0aW5nIHJlY29yZHMuCiAgICAgICBAbWV0aG9kIHB1c2gKICAgICAgQHBhcmFtIHtPYmplY3R9IGRhdGEKICAgICAgQHJldHVybiB0aGUgcmVjb3JkKHMpIHRoYXQgd2FzIGNyZWF0ZWQgb3IKICAgICAgICB1cGRhdGVkLgogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucHVzaCA9IGZ1bmN0aW9uIHB1c2goZGF0YSkgewoKICAgICAgdmFyIHB1c2hlZCA9IHRoaXMuX3B1c2goZGF0YSk7CgogICAgICBpZiAoQXJyYXkuaXNBcnJheShwdXNoZWQpKSB7CiAgICAgICAgdmFyIHJlY29yZHMgPSBwdXNoZWQubWFwKGZ1bmN0aW9uIChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5nZXRSZWNvcmQoKTsKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gcmVjb3JkczsKICAgICAgfQoKICAgICAgaWYgKHB1c2hlZCA9PT0gbnVsbCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgcmVjb3JkID0gcHVzaGVkLmdldFJlY29yZCgpOwogICAgICByZXR1cm4gcmVjb3JkOwogICAgfQogICAgLyoKICAgICAgUHVzaCBzb21lIGRhdGEgaW4gdGhlIGZvcm0gb2YgYSBqc29uLWFwaSBkb2N1bWVudCBpbnRvIHRoZSBzdG9yZSwKICAgICAgd2l0aG91dCBjcmVhdGluZyBtYXRlcmlhbGl6ZWQgcmVjb3Jkcy4KICAgICAgIEBtZXRob2QgX3B1c2gKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtPYmplY3R9IGpzb25BcGlEb2MKICAgICAgQHJldHVybiB7SW50ZXJuYWxNb2RlbHxBcnJheTxJbnRlcm5hbE1vZGVsPn0gcHVzaGVkIEludGVybmFsTW9kZWwocykKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9wdXNoID0gZnVuY3Rpb24gX3B1c2goanNvbkFwaURvYykgewogICAgICB2YXIgX3RoaXM3ID0gdGhpczsKCiAgICAgIHZhciBpbnRlcm5hbE1vZGVsT3JNb2RlbHMgPSB0aGlzLl9iYWNrYnVybmVyLmpvaW4oZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBpbmNsdWRlZCA9IGpzb25BcGlEb2MuaW5jbHVkZWQ7CiAgICAgICAgdmFyIGksIGxlbmd0aDsKCiAgICAgICAgaWYgKGluY2x1ZGVkKSB7CiAgICAgICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBpbmNsdWRlZC5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICBfdGhpczcuX3B1c2hJbnRlcm5hbE1vZGVsKGluY2x1ZGVkW2ldKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmIChBcnJheS5pc0FycmF5KGpzb25BcGlEb2MuZGF0YSkpIHsKICAgICAgICAgIGxlbmd0aCA9IGpzb25BcGlEb2MuZGF0YS5sZW5ndGg7CiAgICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbHMgPSBuZXcgQXJyYXkobGVuZ3RoKTsKCiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgaW50ZXJuYWxNb2RlbHNbaV0gPSBfdGhpczcuX3B1c2hJbnRlcm5hbE1vZGVsKGpzb25BcGlEb2MuZGF0YVtpXSk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWxzOwogICAgICAgIH0KCiAgICAgICAgaWYgKGpzb25BcGlEb2MuZGF0YSA9PT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBfdGhpczcuX3B1c2hJbnRlcm5hbE1vZGVsKGpzb25BcGlEb2MuZGF0YSk7CiAgICAgIH0pOyAvLyB0aGlzIHR5cGVjYXN0IGlzIG5lY2Vzc2FyeSBiZWNhdXNlIGBiYWNrYnVybmVyLmpvaW5gIGlzIG1pc3R5cGVkIHRvIHJldHVybiB2b2lkCgoKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWxPck1vZGVsczsKICAgIH07CgogICAgX3Byb3RvLl9wdXNoSW50ZXJuYWxNb2RlbCA9IGZ1bmN0aW9uIF9wdXNoSW50ZXJuYWxNb2RlbChkYXRhKSB7CiAgICAgIHZhciBtb2RlbE5hbWUgPSBkYXRhLnR5cGU7CgoKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSB0aGlzLl9sb2FkKGRhdGEpOyAvLyAgICB0aGlzLl9zZXR1cFJlbGF0aW9uc2hpcHNGb3JNb2RlbChpbnRlcm5hbE1vZGVsLCBkYXRhKTsKCgogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbDsKICAgIH0KICAgIC8qKgogICAgICBQdXNoIHNvbWUgcmF3IGRhdGEgaW50byB0aGUgc3RvcmUuCiAgICAgICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCBib3RoIHRvIHB1c2ggaW4gYnJhbmQgbmV3CiAgICAgIHJlY29yZHMsIGFzIHdlbGwgYXMgdG8gdXBkYXRlIGV4aXN0aW5nIHJlY29yZHMuIFlvdQogICAgICBjYW4gcHVzaCBpbiBtb3JlIHRoYW4gb25lIHR5cGUgb2Ygb2JqZWN0IGF0IG9uY2UuCiAgICAgIEFsbCBvYmplY3RzIHNob3VsZCBiZSBpbiB0aGUgZm9ybWF0IGV4cGVjdGVkIGJ5IHRoZQogICAgICBzZXJpYWxpemVyLgogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBSRVNUU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXI7CiAgICAgIGBgYAogICAgICAgYGBganMKICAgICAgbGV0IHB1c2hEYXRhID0gewogICAgICAgIHBvc3RzOiBbCiAgICAgICAgICB7IGlkOiAxLCBwb3N0VGl0bGU6ICJHcmVhdCBwb3N0IiwgY29tbWVudElkczogWzJdIH0KICAgICAgICBdLAogICAgICAgIGNvbW1lbnRzOiBbCiAgICAgICAgICB7IGlkOiAyLCBjb21tZW50Qm9keTogIkluc2lnaHRmdWwgY29tbWVudCIgfQogICAgICAgIF0KICAgICAgfQogICAgICAgc3RvcmUucHVzaFBheWxvYWQocHVzaERhdGEpOwogICAgICBgYGAKICAgICAgIEJ5IGRlZmF1bHQsIHRoZSBkYXRhIHdpbGwgYmUgZGVzZXJpYWxpemVkIHVzaW5nIGEgZGVmYXVsdAogICAgICBzZXJpYWxpemVyICh0aGUgYXBwbGljYXRpb24gc2VyaWFsaXplciBpZiBpdCBleGlzdHMpLgogICAgICAgQWx0ZXJuYXRpdmVseSwgYHB1c2hQYXlsb2FkYCB3aWxsIGFjY2VwdCBhIG1vZGVsIHR5cGUgd2hpY2gKICAgICAgd2lsbCBkZXRlcm1pbmUgd2hpY2ggc2VyaWFsaXplciB3aWxsIHByb2Nlc3MgdGhlIHBheWxvYWQuCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSRVNUU2VyaWFsaXplcjsKICAgICAgYGBgCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgSlNPTlNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05TZXJpYWxpemVyOwogICAgICBgYGAKICAgICAgIGBgYGpzCiAgICAgIHN0b3JlLnB1c2hQYXlsb2FkKHB1c2hEYXRhKTsgLy8gV2lsbCB1c2UgdGhlIGFwcGxpY2F0aW9uIHNlcmlhbGl6ZXIKICAgICAgc3RvcmUucHVzaFBheWxvYWQoJ3Bvc3QnLCBwdXNoRGF0YSk7IC8vIFdpbGwgdXNlIHRoZSBwb3N0IHNlcmlhbGl6ZXIKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHB1c2hQYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUgT3B0aW9uYWxseSwgYSBtb2RlbCB0eXBlIHVzZWQgdG8gZGV0ZXJtaW5lIHdoaWNoIHNlcmlhbGl6ZXIgd2lsbCBiZSB1c2VkCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBpbnB1dFBheWxvYWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLnB1c2hQYXlsb2FkID0gZnVuY3Rpb24gcHVzaFBheWxvYWQobW9kZWxOYW1lLCBpbnB1dFBheWxvYWQpIHsKCiAgICAgIHZhciBzZXJpYWxpemVyOwogICAgICB2YXIgcGF5bG9hZDsKCiAgICAgIGlmICghaW5wdXRQYXlsb2FkKSB7CiAgICAgICAgcGF5bG9hZCA9IG1vZGVsTmFtZTsKICAgICAgICBzZXJpYWxpemVyID0gdGhpcy5zZXJpYWxpemVyRm9yKCdhcHBsaWNhdGlvbicpOwogICAgICB9IGVsc2UgewogICAgICAgIHBheWxvYWQgPSBpbnB1dFBheWxvYWQ7CiAgICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgICBzZXJpYWxpemVyID0gdGhpcy5zZXJpYWxpemVyRm9yKG5vcm1hbGl6ZWRNb2RlbE5hbWUpOwogICAgICB9CiAgICAgIHNlcmlhbGl6ZXIucHVzaFBheWxvYWQodGhpcywgcGF5bG9hZCk7CiAgICB9OwoKICAgIF9wcm90by5yZWxvYWRNYW55QXJyYXkgPSBmdW5jdGlvbiByZWxvYWRNYW55QXJyYXkobWFueUFycmF5LCBpbnRlcm5hbE1vZGVsLCBrZXksIG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwucmVsb2FkSGFzTWFueShrZXksIG9wdGlvbnMpOwogICAgfTsKCiAgICBfcHJvdG8ucmVsb2FkQmVsb25nc1RvID0gZnVuY3Rpb24gcmVsb2FkQmVsb25nc1RvKGJlbG9uZ3NUb1Byb3h5LCBpbnRlcm5hbE1vZGVsLCBrZXksIG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwucmVsb2FkQmVsb25nc1RvKGtleSwgb3B0aW9ucyk7CiAgICB9OwoKICAgIF9wcm90by5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlID0gZnVuY3Rpb24gX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShyZXNvdXJjZSkgewogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcykuZ2V0QnlSZXNvdXJjZShyZXNvdXJjZSk7CiAgICB9CiAgICAvKioKICAgICAqIFRPRE8gT25seSBuZWVkZWQgdGVtcG9yYXJpbHkgZm9yIHRlc3Qgc3VwcG9ydAogICAgICoKICAgICAqIEBpbnRlcm5hbAogICAgICovCiAgICA7CgogICAgX3Byb3RvLl9pbnRlcm5hbE1vZGVsRm9ySWQgPSBmdW5jdGlvbiBfaW50ZXJuYWxNb2RlbEZvcklkKHR5cGUsIGlkLCBsaWQpIHsKICAgICAgdmFyIHJlc291cmNlID0gY29uc3RydWN0UmVzb3VyY2UodHlwZSwgaWQsIGxpZCk7CiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5sb29rdXAocmVzb3VyY2UpOwogICAgfTsKCiAgICBfcHJvdG8uc2VyaWFsaXplUmVjb3JkID0gZnVuY3Rpb24gc2VyaWFsaXplUmVjb3JkKHJlY29yZCwgb3B0aW9ucykgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgdmFyIF9pZGVudGlmaWVyNSA9IHJlY29yZElkZW50aWZpZXJGb3IocmVjb3JkKTsKCiAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5wZWVrKF9pZGVudGlmaWVyNSk7IC8vIFRPRE8gd2UgdXNlZCB0byBjaGVjayBpZiB0aGUgcmVjb3JkIHdhcyBkZXN0cm95ZWQgaGVyZQoKICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdChvcHRpb25zKS5zZXJpYWxpemUob3B0aW9ucyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdzZXJpYWxpemVSZWNvcmQgaXMgb25seSBhdmFpbGFibGUgd2hlbiBDVVNUT01fTU9ERUxfQ0xBU1MgZmYgaXMgb24nKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uc2F2ZVJlY29yZCA9IGZ1bmN0aW9uIHNhdmVSZWNvcmQocmVjb3JkLCBvcHRpb25zKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICB2YXIgX2lkZW50aWZpZXI2ID0gcmVjb3JkSWRlbnRpZmllckZvcihyZWNvcmQpOwoKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLnBlZWsoX2lkZW50aWZpZXI2KTsgLy8gVE9ETyB3ZSB1c2VkIHRvIGNoZWNrIGlmIHRoZSByZWNvcmQgd2FzIGRlc3Ryb3llZCBoZXJlCiAgICAgICAgLy8gQ2FzdGluZyBjYW4gYmUgcmVtb3ZlZCBvbmNlIFJFUVVFU1RfU0VSVklDRSBmZiBpcyB0dXJuZWQgb24KICAgICAgICAvLyBiZWNhdXNlIGEgYFJlY29yZGAgaXMgcHJvdmlkZWQgdGhlcmUgd2lsbCBhbHdheXMgYmUgYSBtYXRjaGluZyBpbnRlcm5hbE1vZGVsCgogICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLnNhdmUob3B0aW9ucykudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gcmVjb3JkOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcignc2F2ZVJlY29yZCBpcyBvbmx5IGF2YWlsYWJsZSB3aGVuIENVU1RPTV9NT0RFTF9DTEFTUyBmZiBpcyBvbicpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZWxhdGlvbnNoaXBSZWZlcmVuY2VGb3IgPSBmdW5jdGlvbiByZWxhdGlvbnNoaXBSZWZlcmVuY2VGb3IoaWRlbnRpZmllciwga2V5KSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICB2YXIgc3RhYmxlSWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIoaWRlbnRpZmllcik7CiAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5wZWVrKHN0YWJsZUlkZW50aWZpZXIpOyAvLyBUT0RPIHdlIHVzZWQgdG8gY2hlY2sgaWYgdGhlIHJlY29yZCB3YXMgZGVzdHJveWVkIGhlcmUKCiAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwucmVmZXJlbmNlRm9yKG51bGwsIGtleSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZWxhdGlvbnNoaXBSZWZlcmVuY2VGb3IgaXMgb25seSBhdmFpbGFibGUgd2hlbiBDVVNUT01fTU9ERUxfQ0xBU1MgZmYgaXMgb24nKTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiBAaW50ZXJuYWwKICAgICAqLwogICAgOwoKICAgIF9wcm90by5fY3JlYXRlUmVjb3JkRGF0YSA9IGZ1bmN0aW9uIF9jcmVhdGVSZWNvcmREYXRhKGlkZW50aWZpZXIpIHsKICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlUmVjb3JkRGF0YUZvcihpZGVudGlmaWVyLnR5cGUsIGlkZW50aWZpZXIuaWQsIGlkZW50aWZpZXIubGlkLCB0aGlzLl9zdG9yZVdyYXBwZXIpOwogICAgfQogICAgLyoqCiAgICAgKiBJbnN0YW50aWF0aW9uIGhvb2sgYWxsb3dpbmcgYXBwbGljYXRpb25zIG9yIGFkZG9ucyB0byBjb25maWd1cmUgdGhlIHN0b3JlCiAgICAgKiB0byB1dGlsaXplIGEgY3VzdG9tIFJlY29yZERhdGEgaW1wbGVtZW50YXRpb24uCiAgICAgKgogICAgICogQHBhcmFtIG1vZGVsTmFtZQogICAgICogQHBhcmFtIGlkCiAgICAgKiBAcGFyYW0gY2xpZW50SWQKICAgICAqIEBwYXJhbSBzdG9yZVdyYXBwZXIKICAgICAqLwogICAgOwoKICAgIF9wcm90by5jcmVhdGVSZWNvcmREYXRhRm9yID0gZnVuY3Rpb24gY3JlYXRlUmVjb3JkRGF0YUZvcihtb2RlbE5hbWUsIGlkLCBjbGllbnRJZCwgc3RvcmVXcmFwcGVyKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiRXhwZWN0ZWQgc3RvcmUuY3JlYXRlUmVjb3JkRGF0YUZvciB0byBiZSBpbXBsZW1lbnRlZCBidXQgaXQgd2Fzbid0Iik7CiAgICB9CiAgICAvKioKICAgICAqIEBpbnRlcm5hbAogICAgICovCiAgICA7CgogICAgX3Byb3RvLl9fcmVjb3JkRGF0YUZvciA9IGZ1bmN0aW9uIF9fcmVjb3JkRGF0YUZvcihyZXNvdXJjZSkgewogICAgICB2YXIgaWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UpOwogICAgICByZXR1cm4gdGhpcy5yZWNvcmREYXRhRm9yKGlkZW50aWZpZXIsIGZhbHNlKTsKICAgIH0KICAgIC8qKgogICAgICogQGludGVybmFsCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVjb3JkRGF0YUZvciA9IGZ1bmN0aW9uIHJlY29yZERhdGFGb3IkMShpZGVudGlmaWVyLCBpc0NyZWF0ZSkgewogICAgICB2YXIgaW50ZXJuYWxNb2RlbDsKCiAgICAgIGlmIChpc0NyZWF0ZSA9PT0gdHJ1ZSkgewogICAgICAgIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5idWlsZCh7CiAgICAgICAgICB0eXBlOiBpZGVudGlmaWVyLnR5cGUsCiAgICAgICAgICBpZDogbnVsbAogICAgICAgIH0pOwogICAgICAgIGludGVybmFsTW9kZWwubG9hZGVkRGF0YSgpOwogICAgICAgIGludGVybmFsTW9kZWwuZGlkQ3JlYXRlUmVjb3JkKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLmxvb2t1cChpZGVudGlmaWVyKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlY29yZERhdGFGb3IoaW50ZXJuYWxNb2RlbCk7CiAgICB9CiAgICAvKioKICAgICAgYG5vcm1hbGl6ZWAgY29udmVydHMgYSBqc29uIHBheWxvYWQgaW50byB0aGUgbm9ybWFsaXplZCBmb3JtIHRoYXQKICAgICAgW3B1c2hdKFN0b3JlL21ldGhvZHMvcHVzaD9hbmNob3I9cHVzaCkgZXhwZWN0cy4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGpzCiAgICAgIHNvY2tldC5vbignbWVzc2FnZScsIGZ1bmN0aW9uKG1lc3NhZ2UpIHsKICAgICAgICBsZXQgbW9kZWxOYW1lID0gbWVzc2FnZS5tb2RlbDsKICAgICAgICBsZXQgZGF0YSA9IG1lc3NhZ2UuZGF0YTsKICAgICAgICBzdG9yZS5wdXNoKHN0b3JlLm5vcm1hbGl6ZShtb2RlbE5hbWUsIGRhdGEpKTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBub3JtYWxpemUKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZSBUaGUgbmFtZSBvZiB0aGUgbW9kZWwgdHlwZSBmb3IgdGhpcyBwYXlsb2FkCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEByZXR1cm4ge09iamVjdH0gVGhlIG5vcm1hbGl6ZWQgcGF5bG9hZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ubm9ybWFsaXplID0gZnVuY3Rpb24gbm9ybWFsaXplKG1vZGVsTmFtZSwgcGF5bG9hZCkgewogICAgICB2YXIgbm9ybWFsaXplZE1vZGVsTmFtZSA9IG5vcm1hbGl6ZU1vZGVsTmFtZShtb2RlbE5hbWUpOwogICAgICB2YXIgc2VyaWFsaXplciA9IHRoaXMuc2VyaWFsaXplckZvcihub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgdmFyIG1vZGVsID0gdGhpcy5tb2RlbEZvcihub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIHNlcmlhbGl6ZXIubm9ybWFsaXplKG1vZGVsLCBwYXlsb2FkKTsKICAgIH07CgogICAgX3Byb3RvLm5ld0NsaWVudElkID0gZnVuY3Rpb24gbmV3Q2xpZW50SWQoKSB7CiAgICAgIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlByaXZhdGUgQVBJIFJlbW92ZWQiKTsKICAgICAgfQogICAgfSAvL0NhbGxlZCBieSB0aGUgc3RhdGUgbWFjaGluZSB0byBub3RpZnkgdGhlIHN0b3JlIHRoYXQgdGhlIHJlY29yZCBpcyByZWFkeSB0byBiZSBpbnRlcmFjdGVkIHdpdGgKICAgIDsKCiAgICBfcHJvdG8ucmVjb3JkV2FzTG9hZGVkID0gZnVuY3Rpb24gcmVjb3JkV2FzTG9hZGVkKHJlY29yZCkgewoKICAgICAgdGhpcy5yZWNvcmRBcnJheU1hbmFnZXIucmVjb3JkV2FzTG9hZGVkKHJlY29yZCk7CiAgICB9IC8vIC4uLi4uLi4uLi4uLi4uLgogICAgLy8gLiBERVNUUlVDVElPTiAuCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4KCiAgICAvKioKICAgICAqIFRPRE8gcmVtb3ZlIHRlc3QgdXNhZ2UKICAgICAqCiAgICAgKiBAaW50ZXJuYWwKICAgICAqLwogICAgOwoKICAgIF9wcm90by5faW50ZXJuYWxNb2RlbHNGb3IgPSBmdW5jdGlvbiBfaW50ZXJuYWxNb2RlbHNGb3IobW9kZWxOYW1lKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5tb2RlbE1hcEZvcihtb2RlbE5hbWUpOwogICAgfSAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uCiAgICAvLyAuIFBFUi1UWVBFIEFEQVBURVJTCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uCgogICAgLyoqCiAgICAgIFJldHVybnMgYW4gaW5zdGFuY2Ugb2YgdGhlIGFkYXB0ZXIgZm9yIGEgZ2l2ZW4gdHlwZS4gRm9yCiAgICAgIGV4YW1wbGUsIGBhZGFwdGVyRm9yKCdwZXJzb24nKWAgd2lsbCByZXR1cm4gYW4gaW5zdGFuY2Ugb2YKICAgICAgYEFwcC5QZXJzb25BZGFwdGVyYC4KICAgICAgIElmIG5vIGBBcHAuUGVyc29uQWRhcHRlcmAgaXMgZm91bmQsIHRoaXMgbWV0aG9kIHdpbGwgbG9vawogICAgICBmb3IgYW4gYEFwcC5BcHBsaWNhdGlvbkFkYXB0ZXJgICh0aGUgZGVmYXVsdCBhZGFwdGVyIGZvcgogICAgICB5b3VyIGVudGlyZSBhcHBsaWNhdGlvbikuCiAgICAgICBJZiBubyBgQXBwLkFwcGxpY2F0aW9uQWRhcHRlcmAgaXMgZm91bmQsIGl0IHdpbGwgcmV0dXJuCiAgICAgIHRoZSB2YWx1ZSBvZiB0aGUgYGRlZmF1bHRBZGFwdGVyYC4KICAgICAgIEBtZXRob2QgYWRhcHRlckZvcgogICAgICBAcHVibGljCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHJldHVybiBBZGFwdGVyCiAgICAqLwogICAgOwoKICAgIF9wcm90by5hZGFwdGVyRm9yID0gZnVuY3Rpb24gYWRhcHRlckZvcihtb2RlbE5hbWUpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgdmFyIF9hZGFwdGVyQ2FjaGUgPSB0aGlzLl9hZGFwdGVyQ2FjaGU7CiAgICAgIHZhciBhZGFwdGVyID0gX2FkYXB0ZXJDYWNoZVtub3JtYWxpemVkTW9kZWxOYW1lXTsKCiAgICAgIGlmIChhZGFwdGVyKSB7CiAgICAgICAgcmV0dXJuIGFkYXB0ZXI7CiAgICAgIH0KCiAgICAgIHZhciBvd25lciA9IEVtYmVyLmdldE93bmVyKHRoaXMpOwogICAgICBhZGFwdGVyID0gb3duZXIubG9va3VwKCJhZGFwdGVyOiIgKyBub3JtYWxpemVkTW9kZWxOYW1lKTsgLy8gaW4gcHJvZHVjdGlvbiB0aGlzIGlzIGhhbmRsZWQgYnkgdGhlIHJlLWV4cG9ydAoKICAgICAgaWYgKGFkYXB0ZXIgIT09IHVuZGVmaW5lZCkgewogICAgICAgIEVtYmVyLnNldChhZGFwdGVyLCAnc3RvcmUnLCB0aGlzKTsKICAgICAgICBfYWRhcHRlckNhY2hlW25vcm1hbGl6ZWRNb2RlbE5hbWVdID0gYWRhcHRlcjsKICAgICAgICByZXR1cm4gYWRhcHRlcjsKICAgICAgfSAvLyBubyBhZGFwdGVyIGZvdW5kIGZvciB0aGUgc3BlY2lmaWMgbW9kZWwsIGZhbGxiYWNrIGFuZCBjaGVjayBmb3IgYXBwbGljYXRpb24gYWRhcHRlcgoKCiAgICAgIGFkYXB0ZXIgPSBfYWRhcHRlckNhY2hlLmFwcGxpY2F0aW9uIHx8IG93bmVyLmxvb2t1cCgnYWRhcHRlcjphcHBsaWNhdGlvbicpOwoKICAgICAgaWYgKGFkYXB0ZXIgIT09IHVuZGVmaW5lZCkgewogICAgICAgIEVtYmVyLnNldChhZGFwdGVyLCAnc3RvcmUnLCB0aGlzKTsKICAgICAgICBfYWRhcHRlckNhY2hlW25vcm1hbGl6ZWRNb2RlbE5hbWVdID0gYWRhcHRlcjsKICAgICAgICBfYWRhcHRlckNhY2hlLmFwcGxpY2F0aW9uID0gYWRhcHRlcjsKICAgICAgICByZXR1cm4gYWRhcHRlcjsKICAgICAgfSAvLyBubyBtb2RlbCBzcGVjaWZpYyBhZGFwdGVyIG9yIGFwcGxpY2F0aW9uIGFkYXB0ZXIsIGNoZWNrIGZvciBhbiBgYWRhcHRlcmAKICAgICAgLy8gcHJvcGVydHkgZGVmaW5lZCBvbiB0aGUgc3RvcmUKCgogICAgICB2YXIgYWRhcHRlck5hbWUgPSB0aGlzLmFkYXB0ZXIgfHwgJy1qc29uLWFwaSc7CiAgICAgIGFkYXB0ZXIgPSBhZGFwdGVyTmFtZSA/IF9hZGFwdGVyQ2FjaGVbYWRhcHRlck5hbWVdIHx8IG93bmVyLmxvb2t1cCgiYWRhcHRlcjoiICsgYWRhcHRlck5hbWUpIDogdW5kZWZpbmVkOyAvLyBpbiBwcm9kdWN0aW9uIHRoaXMgaXMgaGFuZGxlZCBieSB0aGUgcmUtZXhwb3J0CgogICAgICBpZiAoYWRhcHRlciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgRW1iZXIuc2V0KGFkYXB0ZXIsICdzdG9yZScsIHRoaXMpOwogICAgICAgIF9hZGFwdGVyQ2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV0gPSBhZGFwdGVyOwogICAgICAgIF9hZGFwdGVyQ2FjaGVbYWRhcHRlck5hbWVdID0gYWRhcHRlcjsKICAgICAgICByZXR1cm4gYWRhcHRlcjsKICAgICAgfSAvLyBmaW5hbCBmYWxsYmFjaywgbm8gbW9kZWwgc3BlY2lmaWMgYWRhcHRlciwgbm8gYXBwbGljYXRpb24gYWRhcHRlciwgbm8KICAgICAgLy8gYGFkYXB0ZXJgIHByb3BlcnR5IG9uIHN0b3JlOiB1c2UganNvbi1hcGkgYWRhcHRlcgoKCiAgICAgIGFkYXB0ZXIgPSBfYWRhcHRlckNhY2hlWyctanNvbi1hcGknXSB8fCBvd25lci5sb29rdXAoJ2FkYXB0ZXI6LWpzb24tYXBpJyk7CiAgICAgIEVtYmVyLnNldChhZGFwdGVyLCAnc3RvcmUnLCB0aGlzKTsKICAgICAgX2FkYXB0ZXJDYWNoZVtub3JtYWxpemVkTW9kZWxOYW1lXSA9IGFkYXB0ZXI7CiAgICAgIF9hZGFwdGVyQ2FjaGVbJy1qc29uLWFwaSddID0gYWRhcHRlcjsKICAgICAgcmV0dXJuIGFkYXB0ZXI7CiAgICB9IC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogICAgLy8gLiBSRUNPUkQgQ0hBTkdFIE5PVElGSUNBVElPTiAuCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KCiAgICAvKioKICAgICAgUmV0dXJucyBhbiBpbnN0YW5jZSBvZiB0aGUgc2VyaWFsaXplciBmb3IgYSBnaXZlbiB0eXBlLiBGb3IKICAgICAgZXhhbXBsZSwgYHNlcmlhbGl6ZXJGb3IoJ3BlcnNvbicpYCB3aWxsIHJldHVybiBhbiBpbnN0YW5jZSBvZgogICAgICBgQXBwLlBlcnNvblNlcmlhbGl6ZXJgLgogICAgICAgSWYgbm8gYEFwcC5QZXJzb25TZXJpYWxpemVyYCBpcyBmb3VuZCwgdGhpcyBtZXRob2Qgd2lsbCBsb29rCiAgICAgIGZvciBhbiBgQXBwLkFwcGxpY2F0aW9uU2VyaWFsaXplcmAgKHRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgZm9yCiAgICAgIHlvdXIgZW50aXJlIGFwcGxpY2F0aW9uKS4KICAgICAgIGlmIG5vIGBBcHAuQXBwbGljYXRpb25TZXJpYWxpemVyYCBpcyBmb3VuZCwgaXQgd2lsbCBhdHRlbXB0CiAgICAgIHRvIGdldCB0aGUgYGRlZmF1bHRTZXJpYWxpemVyYCBmcm9tIHRoZSBgUGVyc29uQWRhcHRlcmAKICAgICAgKGBhZGFwdGVyRm9yKCdwZXJzb24nKWApLgogICAgICAgSWYgYSBzZXJpYWxpemVyIGNhbm5vdCBiZSBmb3VuZCBvbiB0aGUgYWRhcHRlciwgaXQgd2lsbCBmYWxsIGJhY2sKICAgICAgdG8gYW4gaW5zdGFuY2Ugb2YgYEpTT05TZXJpYWxpemVyYC4KICAgICAgIEBtZXRob2Qgc2VyaWFsaXplckZvcgogICAgICBAcHVibGljCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUgdGhlIHJlY29yZCB0byBzZXJpYWxpemUKICAgICAgQHJldHVybiB7U2VyaWFsaXplcn0KICAgICovCiAgICA7CgogICAgX3Byb3RvLnNlcmlhbGl6ZXJGb3IgPSBmdW5jdGlvbiBzZXJpYWxpemVyRm9yKG1vZGVsTmFtZSkgewogICAgICB2YXIgbm9ybWFsaXplZE1vZGVsTmFtZSA9IG5vcm1hbGl6ZU1vZGVsTmFtZShtb2RlbE5hbWUpOwogICAgICB2YXIgX3NlcmlhbGl6ZXJDYWNoZSA9IHRoaXMuX3NlcmlhbGl6ZXJDYWNoZTsKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBfc2VyaWFsaXplckNhY2hlW25vcm1hbGl6ZWRNb2RlbE5hbWVdOwoKICAgICAgaWYgKHNlcmlhbGl6ZXIpIHsKICAgICAgICByZXR1cm4gc2VyaWFsaXplcjsKICAgICAgfQoKICAgICAgdmFyIG93bmVyID0gRW1iZXIuZ2V0T3duZXIodGhpcyk7CiAgICAgIHNlcmlhbGl6ZXIgPSBvd25lci5sb29rdXAoInNlcmlhbGl6ZXI6IiArIG5vcm1hbGl6ZWRNb2RlbE5hbWUpOyAvLyBpbiBwcm9kdWN0aW9uIHRoaXMgaXMgaGFuZGxlZCBieSB0aGUgcmUtZXhwb3J0CgogICAgICBpZiAoc2VyaWFsaXplciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgRW1iZXIuc2V0KHNlcmlhbGl6ZXIsICdzdG9yZScsIHRoaXMpOwogICAgICAgIF9zZXJpYWxpemVyQ2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV0gPSBzZXJpYWxpemVyOwogICAgICAgIHJldHVybiBzZXJpYWxpemVyOwogICAgICB9IC8vIG5vIHNlcmlhbGl6ZXIgZm91bmQgZm9yIHRoZSBzcGVjaWZpYyBtb2RlbCwgZmFsbGJhY2sgYW5kIGNoZWNrIGZvciBhcHBsaWNhdGlvbiBzZXJpYWxpemVyCgoKICAgICAgc2VyaWFsaXplciA9IF9zZXJpYWxpemVyQ2FjaGUuYXBwbGljYXRpb24gfHwgb3duZXIubG9va3VwKCdzZXJpYWxpemVyOmFwcGxpY2F0aW9uJyk7CgogICAgICBpZiAoc2VyaWFsaXplciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgRW1iZXIuc2V0KHNlcmlhbGl6ZXIsICdzdG9yZScsIHRoaXMpOwogICAgICAgIF9zZXJpYWxpemVyQ2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV0gPSBzZXJpYWxpemVyOwogICAgICAgIF9zZXJpYWxpemVyQ2FjaGUuYXBwbGljYXRpb24gPSBzZXJpYWxpemVyOwogICAgICAgIHJldHVybiBzZXJpYWxpemVyOwogICAgICB9IC8vIG5vIG1vZGVsIHNwZWNpZmljIHNlcmlhbGl6ZXIgb3IgYXBwbGljYXRpb24gc2VyaWFsaXplciwgY2hlY2sgZm9yIHRoZSBgZGVmYXVsdFNlcmlhbGl6ZXJgCiAgICAgIC8vIHByb3BlcnR5IGRlZmluZWQgb24gdGhlIGFkYXB0ZXIKCgogICAgICB2YXIgYWRhcHRlciA9IHRoaXMuYWRhcHRlckZvcihtb2RlbE5hbWUpOwogICAgICB2YXIgc2VyaWFsaXplck5hbWUgPSBFbWJlci5nZXQoYWRhcHRlciwgJ2RlZmF1bHRTZXJpYWxpemVyJyk7CiAgICAgIHNlcmlhbGl6ZXIgPSBzZXJpYWxpemVyTmFtZSA/IF9zZXJpYWxpemVyQ2FjaGVbc2VyaWFsaXplck5hbWVdIHx8IG93bmVyLmxvb2t1cCgic2VyaWFsaXplcjoiICsgc2VyaWFsaXplck5hbWUpIDogdW5kZWZpbmVkOyAvLyBpbiBwcm9kdWN0aW9uIHRoaXMgaXMgaGFuZGxlZCBieSB0aGUgcmUtZXhwb3J0CgogICAgICBpZiAoc2VyaWFsaXplciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgRW1iZXIuc2V0KHNlcmlhbGl6ZXIsICdzdG9yZScsIHRoaXMpOwogICAgICAgIF9zZXJpYWxpemVyQ2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV0gPSBzZXJpYWxpemVyOwogICAgICAgIF9zZXJpYWxpemVyQ2FjaGVbc2VyaWFsaXplck5hbWVdID0gc2VyaWFsaXplcjsKICAgICAgICByZXR1cm4gc2VyaWFsaXplcjsKICAgICAgfSAvLyBmaW5hbCBmYWxsYmFjaywgbm8gbW9kZWwgc3BlY2lmaWMgc2VyaWFsaXplciwgbm8gYXBwbGljYXRpb24gc2VyaWFsaXplciwgbm8KICAgICAgLy8gYHNlcmlhbGl6ZXJgIHByb3BlcnR5IG9uIHN0b3JlOiB1c2UgdGhlIGNvbnZlbmllbmNlIEpTT05TZXJpYWxpemVyCgoKICAgICAgc2VyaWFsaXplciA9IF9zZXJpYWxpemVyQ2FjaGVbJy1kZWZhdWx0J10gfHwgb3duZXIubG9va3VwKCdzZXJpYWxpemVyOi1kZWZhdWx0Jyk7CiAgICAgIEVtYmVyLnNldChzZXJpYWxpemVyLCAnc3RvcmUnLCB0aGlzKTsKICAgICAgX3NlcmlhbGl6ZXJDYWNoZVtub3JtYWxpemVkTW9kZWxOYW1lXSA9IHNlcmlhbGl6ZXI7CiAgICAgIF9zZXJpYWxpemVyQ2FjaGVbJy1kZWZhdWx0J10gPSBzZXJpYWxpemVyOwogICAgICByZXR1cm4gc2VyaWFsaXplcjsKICAgIH07CgogICAgX3Byb3RvLndpbGxEZXN0cm95ID0gZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIF9FbWJlclNlcnZpY2UucHJvdG90eXBlLndpbGxEZXN0cm95LmNhbGwodGhpcyk7CgogICAgICB0aGlzLnJlY29yZEFycmF5TWFuYWdlci5kZXN0cm95KCk7IC8vIENoZWNrIGlmIHdlIG5lZWQgdG8gbnVsbCB0aGlzIG91dAogICAgICAvLyB0aGlzLl9hZGFwdGVyQ2FjaGUgPSBudWxsOwogICAgICAvLyB0aGlzLl9zZXJpYWxpemVyQ2FjaGUgPSBudWxsOwoKICAgICAgaWRlbnRpZmllckNhY2hlRm9yKHRoaXMpLmRlc3Ryb3koKTsKICAgICAgdGhpcy51bmxvYWRBbGwoKTsKICAgIH07CgogICAgX3Byb3RvLl91cGRhdGVSZWxhdGlvbnNoaXBTdGF0ZSA9IGZ1bmN0aW9uIF91cGRhdGVSZWxhdGlvbnNoaXBTdGF0ZShyZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIF90aGlzOCA9IHRoaXM7CgogICAgICBpZiAodGhpcy5fdXBkYXRlZFJlbGF0aW9uc2hpcHMucHVzaChyZWxhdGlvbnNoaXApICE9PSAxKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9iYWNrYnVybmVyLmpvaW4oZnVuY3Rpb24gKCkgewogICAgICAgIF90aGlzOC5fYmFja2J1cm5lci5zY2hlZHVsZSgnc3luY1JlbGF0aW9uc2hpcHMnLCBfdGhpczgsIF90aGlzOC5fZmx1c2hVcGRhdGVkUmVsYXRpb25zaGlwcyk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8uX2ZsdXNoVXBkYXRlZFJlbGF0aW9uc2hpcHMgPSBmdW5jdGlvbiBfZmx1c2hVcGRhdGVkUmVsYXRpb25zaGlwcygpIHsKICAgICAgdmFyIHVwZGF0ZWQgPSB0aGlzLl91cGRhdGVkUmVsYXRpb25zaGlwczsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gdXBkYXRlZC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICB1cGRhdGVkW2ldLmZsdXNoQ2Fub25pY2FsKCk7CiAgICAgIH0KCiAgICAgIHVwZGF0ZWQubGVuZ3RoID0gMDsKICAgIH07CgogICAgX3Byb3RvLl91cGRhdGVJbnRlcm5hbE1vZGVsID0gZnVuY3Rpb24gX3VwZGF0ZUludGVybmFsTW9kZWwoaW50ZXJuYWxNb2RlbCkgewogICAgICBpZiAodGhpcy5fdXBkYXRlZEludGVybmFsTW9kZWxzLnB1c2goaW50ZXJuYWxNb2RlbCkgIT09IDEpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGVtYmVyUnVuJDIuc2NoZWR1bGUoJ2FjdGlvbnMnLCB0aGlzLCB0aGlzLl9mbHVzaFVwZGF0ZWRJbnRlcm5hbE1vZGVscyk7CiAgICB9OwoKICAgIF9wcm90by5fZmx1c2hVcGRhdGVkSW50ZXJuYWxNb2RlbHMgPSBmdW5jdGlvbiBfZmx1c2hVcGRhdGVkSW50ZXJuYWxNb2RlbHMoKSB7CiAgICAgIHZhciB1cGRhdGVkID0gdGhpcy5fdXBkYXRlZEludGVybmFsTW9kZWxzOwoKICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSB1cGRhdGVkLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICAgIHVwZGF0ZWRbaV0uX3RyaWdnZXJEZWZlcnJlZFRyaWdnZXJzKCk7CiAgICAgIH0KCiAgICAgIHVwZGF0ZWQubGVuZ3RoID0gMDsKICAgIH07CgogICAgX2NyZWF0ZUNsYXNzJDcoQ29yZVN0b3JlLCBbewogICAgICBrZXk6ICJpZGVudGlmaWVyQ2FjaGUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKCiAgICAgICAgcmV0dXJuIGlkZW50aWZpZXJDYWNoZUZvcih0aGlzKTsKICAgICAgfQogICAgfV0pOwoKICAgIHJldHVybiBDb3JlU3RvcmU7CiAgfShFbWJlci5TZXJ2aWNlKTsKCiAgRW1iZXIuZGVmaW5lUHJvcGVydHkoQ29yZVN0b3JlLnByb3RvdHlwZSwgJ2RlZmF1bHRBZGFwdGVyJywgRW1iZXIuY29tcHV0ZWQoJ2FkYXB0ZXInLCBmdW5jdGlvbiAoKSB7CiAgICB2YXIgYWRhcHRlciA9IHRoaXMuYWRhcHRlciB8fCAnLWpzb24tYXBpJzsKICAgIHJldHVybiB0aGlzLmFkYXB0ZXJGb3IoYWRhcHRlcik7CiAgfSkpOwoKICBmdW5jdGlvbiBfY29tbWl0KGFkYXB0ZXIsIHN0b3JlLCBvcGVyYXRpb24sIHNuYXBzaG90KSB7CiAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IHNuYXBzaG90Ll9pbnRlcm5hbE1vZGVsOwogICAgdmFyIG1vZGVsTmFtZSA9IHNuYXBzaG90Lm1vZGVsTmFtZTsKICAgIHZhciBtb2RlbENsYXNzID0gc3RvcmUubW9kZWxGb3IobW9kZWxOYW1lKTsKICAgIHZhciBwcm9taXNlID0gRW1iZXIuUlNWUC5Qcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIGFkYXB0ZXJbb3BlcmF0aW9uXShzdG9yZSwgbW9kZWxDbGFzcywgc25hcHNob3QpOwogICAgfSk7CiAgICB2YXIgc2VyaWFsaXplciA9IHN0b3JlLnNlcmlhbGl6ZXJGb3IobW9kZWxOYW1lKTsKICAgIHZhciBsYWJlbCA9ICJEUzogRXh0cmFjdCBhbmQgbm90aWZ5IGFib3V0ICIgKyBvcGVyYXRpb24gKyAiIGNvbXBsZXRpb24gb2YgIiArIGludGVybmFsTW9kZWw7CiAgICBwcm9taXNlID0gZ3VhcmREZXN0cm95ZWRTdG9yZShwcm9taXNlLCBzdG9yZSwgbGFiZWwpOwogICAgcHJvbWlzZSA9IF9ndWFyZChwcm9taXNlLCBfYmluZChfb2JqZWN0SXNBbGl2ZSwgaW50ZXJuYWxNb2RlbCkpOwogICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAoYWRhcHRlclBheWxvYWQpIHsKICAgICAgLyoKICAgICAgTm90ZSB0byBmdXR1cmUgc3BlbHVua2VycyBob3BpbmcgdG8gb3B0aW1pemUuCiAgICAgIFdlIHJlbHkgb24gdGhpcyBgcnVuYCB0byBjcmVhdGUgYSBydW4gbG9vcCBpZiBuZWVkZWQKICAgICAgdGhhdCBgc3RvcmUuX3B1c2hgIGFuZCBgc3RvcmUuZGlkU2F2ZVJlY29yZGAgd2lsbCBib3RoIHNoYXJlLgogICAgICAgV2UgdXNlIGBqb2luYCBiZWNhdXNlIGl0IGlzIG9mdGVuIHRoZSBjYXNlIHRoYXQgd2UKICAgICAgaGF2ZSBhbiBvdXRlciBydW4gbG9vcCBhdmFpbGFibGUgc3RpbGwgZnJvbSB0aGUgZmlyc3QKICAgICAgY2FsbCB0byBgc3RvcmUuX3B1c2hgOwogICAgICAqLwogICAgICBzdG9yZS5fYmFja2J1cm5lci5qb2luKGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgcGF5bG9hZCwgZGF0YSwgc2lkZWxvYWRlZDsKCiAgICAgICAgaWYgKGFkYXB0ZXJQYXlsb2FkKSB7CiAgICAgICAgICBwYXlsb2FkID0gbm9ybWFsaXplUmVzcG9uc2VIZWxwZXIoc2VyaWFsaXplciwgc3RvcmUsIG1vZGVsQ2xhc3MsIGFkYXB0ZXJQYXlsb2FkLCBzbmFwc2hvdC5pZCwgb3BlcmF0aW9uKTsKCiAgICAgICAgICBpZiAocGF5bG9hZC5pbmNsdWRlZCkgewogICAgICAgICAgICBzaWRlbG9hZGVkID0gcGF5bG9hZC5pbmNsdWRlZDsKICAgICAgICAgIH0KCiAgICAgICAgICBkYXRhID0gcGF5bG9hZC5kYXRhOwogICAgICAgIH0KCiAgICAgICAgc3RvcmUuZGlkU2F2ZVJlY29yZChpbnRlcm5hbE1vZGVsLCB7CiAgICAgICAgICBkYXRhOiBkYXRhCiAgICAgICAgfSwgb3BlcmF0aW9uKTsgLy8gc2VlbXMgcmlza3ksIGJ1dCBpZiB0aGUgdGVzdHMgcGFzcyBtaWdodCBiZSBmaW5lPwoKICAgICAgICBpZiAoc2lkZWxvYWRlZCkgewogICAgICAgICAgc3RvcmUuX3B1c2goewogICAgICAgICAgICBkYXRhOiBudWxsLAogICAgICAgICAgICBpbmNsdWRlZDogc2lkZWxvYWRlZAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKCiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsOwogICAgfSwgZnVuY3Rpb24gKGVycm9yKSB7CiAgICAgIGlmIChlcnJvciAmJiBlcnJvci5pc0FkYXB0ZXJFcnJvciA9PT0gdHJ1ZSAmJiBlcnJvci5jb2RlID09PSAnSW52YWxpZEVycm9yJykgewogICAgICAgIHZhciBwYXJzZWRFcnJvcnM7CgogICAgICAgIGlmICh0eXBlb2Ygc2VyaWFsaXplci5leHRyYWN0RXJyb3JzID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICBwYXJzZWRFcnJvcnMgPSBzZXJpYWxpemVyLmV4dHJhY3RFcnJvcnMoc3RvcmUsIG1vZGVsQ2xhc3MsIGVycm9yLCBzbmFwc2hvdC5pZCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHBhcnNlZEVycm9ycyA9IGVycm9yc0FycmF5VG9IYXNoKGVycm9yLmVycm9ycyk7CiAgICAgICAgfQoKICAgICAgICBzdG9yZS5yZWNvcmRXYXNJbnZhbGlkKGludGVybmFsTW9kZWwsIHBhcnNlZEVycm9ycywgZXJyb3IpOwogICAgICB9IGVsc2UgewogICAgICAgIHN0b3JlLnJlY29yZFdhc0Vycm9yKGludGVybmFsTW9kZWwsIGVycm9yKTsKICAgICAgfQoKICAgICAgdGhyb3cgZXJyb3I7CiAgICB9LCBsYWJlbCk7CiAgfQoKICB2YXIgSEFTX01PREVMX1BBQ0tBR0UkMSA9IHJlcXVpcmUuaGFzKCdAZW1iZXItZGF0YS9tb2RlbCcpOwoKICB2YXIgX01vZGVsJDE7CgogIGZ1bmN0aW9uIGdldE1vZGVsJDEoKSB7CiAgICBpZiAoSEFTX01PREVMX1BBQ0tBR0UkMSkgewogICAgICBfTW9kZWwkMSA9IF9Nb2RlbCQxIHx8IHJlcXVpcmVfX2RlZmF1bHQoJ0BlbWJlci1kYXRhL21vZGVsJykuZGVmYXVsdDsKICAgIH0KCiAgICByZXR1cm4gX01vZGVsJDE7CiAgfQoKICB2YXIgRFNNb2RlbFNjaGVtYURlZmluaXRpb25TZXJ2aWNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRFNNb2RlbFNjaGVtYURlZmluaXRpb25TZXJ2aWNlKHN0b3JlKSB7CiAgICAgIHRoaXMuc3RvcmUgPSBzdG9yZTsKICAgICAgdGhpcy5fbW9kZWxGYWN0b3J5Q2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9yZWxhdGlvbnNoaXBzRGVmQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9hdHRyaWJ1dGVzRGVmQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgfSAvLyBGb2xsb3dpbmcgdGhlIGV4aXN0aW5nIFJEIGltcGxlbWVudGF0aW9uCgoKICAgIHZhciBfcHJvdG8gPSBEU01vZGVsU2NoZW1hRGVmaW5pdGlvblNlcnZpY2UucHJvdG90eXBlOwoKICAgIF9wcm90by5hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvciA9IGZ1bmN0aW9uIGF0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKGlkZW50aWZpZXIpIHsKICAgICAgdmFyIG1vZGVsTmFtZSwgYXR0cmlidXRlczsKCiAgICAgIGlmICh0eXBlb2YgaWRlbnRpZmllciA9PT0gJ3N0cmluZycpIHsKICAgICAgICBtb2RlbE5hbWUgPSBpZGVudGlmaWVyOwogICAgICB9IGVsc2UgewogICAgICAgIG1vZGVsTmFtZSA9IGlkZW50aWZpZXIudHlwZTsKICAgICAgfQoKICAgICAgYXR0cmlidXRlcyA9IHRoaXMuX2F0dHJpYnV0ZXNEZWZDYWNoZVttb2RlbE5hbWVdOwoKICAgICAgaWYgKGF0dHJpYnV0ZXMgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhciBtb2RlbENsYXNzID0gdGhpcy5zdG9yZS5tb2RlbEZvcihtb2RlbE5hbWUpOwogICAgICAgIHZhciBhdHRyaWJ1dGVNYXAgPSBFbWJlci5nZXQobW9kZWxDbGFzcywgJ2F0dHJpYnV0ZXMnKTsKICAgICAgICBhdHRyaWJ1dGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICBhdHRyaWJ1dGVNYXAuZm9yRWFjaChmdW5jdGlvbiAobWV0YSwgbmFtZSkgewogICAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZXNbbmFtZV0gPSBtZXRhOwogICAgICAgIH0pOwogICAgICAgIHRoaXMuX2F0dHJpYnV0ZXNEZWZDYWNoZVttb2RlbE5hbWVdID0gYXR0cmlidXRlczsKICAgICAgfQoKICAgICAgcmV0dXJuIGF0dHJpYnV0ZXM7CiAgICB9IC8vIEZvbGxvd2luZyB0aGUgZXhpc3RpbmcgUkQgaW1wbGVtZW50YXRpb24KICAgIDsKCiAgICBfcHJvdG8ucmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IgPSBmdW5jdGlvbiByZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcihpZGVudGlmaWVyKSB7CiAgICAgIHZhciBtb2RlbE5hbWUsIHJlbGF0aW9uc2hpcHM7CgogICAgICBpZiAodHlwZW9mIGlkZW50aWZpZXIgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgbW9kZWxOYW1lID0gaWRlbnRpZmllcjsKICAgICAgfSBlbHNlIHsKICAgICAgICBtb2RlbE5hbWUgPSBpZGVudGlmaWVyLnR5cGU7CiAgICAgIH0KCiAgICAgIHJlbGF0aW9uc2hpcHMgPSB0aGlzLl9yZWxhdGlvbnNoaXBzRGVmQ2FjaGVbbW9kZWxOYW1lXTsKCiAgICAgIGlmIChyZWxhdGlvbnNoaXBzID09PSB1bmRlZmluZWQpIHsKICAgICAgICB2YXIgbW9kZWxDbGFzcyA9IHRoaXMuc3RvcmUubW9kZWxGb3IobW9kZWxOYW1lKTsKICAgICAgICByZWxhdGlvbnNoaXBzID0gRW1iZXIuZ2V0KG1vZGVsQ2xhc3MsICdyZWxhdGlvbnNoaXBzT2JqZWN0JykgfHwgbnVsbDsKICAgICAgICB0aGlzLl9yZWxhdGlvbnNoaXBzRGVmQ2FjaGVbbW9kZWxOYW1lXSA9IHJlbGF0aW9uc2hpcHM7CiAgICAgIH0KCiAgICAgIHJldHVybiByZWxhdGlvbnNoaXBzOwogICAgfTsKCiAgICBfcHJvdG8uZG9lc1R5cGVFeGlzdCA9IGZ1bmN0aW9uIGRvZXNUeXBlRXhpc3QobW9kZWxOYW1lKSB7CiAgICAgIHZhciBub3JtYWxpemVkTW9kZWxOYW1lID0gbm9ybWFsaXplTW9kZWxOYW1lKG1vZGVsTmFtZSk7CiAgICAgIHZhciBmYWN0b3J5ID0gZ2V0TW9kZWxGYWN0b3J5KHRoaXMuc3RvcmUsIHRoaXMuX21vZGVsRmFjdG9yeUNhY2hlLCBub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIGZhY3RvcnkgIT09IG51bGw7CiAgICB9OwoKICAgIHJldHVybiBEU01vZGVsU2NoZW1hRGVmaW5pdGlvblNlcnZpY2U7CiAgfSgpOwogIC8qKgogICAqCiAgICogQHBhcmFtIHN0b3JlCiAgICogQHBhcmFtIGNhY2hlIG1vZGVsRmFjdG9yeUNhY2hlCiAgICogQHBhcmFtIG5vcm1hbGl6ZWRNb2RlbE5hbWUgYWxyZWFkeSBub3JtYWxpemVkIG1vZGVsTmFtZQogICAqIEByZXR1cm4geyp9CiAgICovCgogIGZ1bmN0aW9uIGdldE1vZGVsRmFjdG9yeShzdG9yZSwgY2FjaGUsIG5vcm1hbGl6ZWRNb2RlbE5hbWUpIHsKICAgIHZhciBmYWN0b3J5ID0gY2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV07CgogICAgaWYgKCFmYWN0b3J5KSB7CiAgICAgIGZhY3RvcnkgPSBfbG9va3VwTW9kZWxGYWN0b3J5KHN0b3JlLCBub3JtYWxpemVkTW9kZWxOYW1lKTsKCiAgICAgIGlmICghZmFjdG9yeSkgewogICAgICAgIC8vU3VwcG9ydCBsb29raW5nIHVwIG1peGlucyBhcyBiYXNlIHR5cGVzIGZvciBwb2x5bW9ycGhpYyByZWxhdGlvbnNoaXBzCiAgICAgICAgZmFjdG9yeSA9IF9tb2RlbEZvck1peGluKHN0b3JlLCBub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgfQoKICAgICAgaWYgKCFmYWN0b3J5KSB7CiAgICAgICAgLy8gd2UgZG9uJ3QgY2FjaGUgbWlzc2VzIGluIGNhc2Ugc29tZW9uZSB3YW50cyB0byByZWdpc3RlciBhIG1pc3NpbmcgbW9kZWwKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIGtsYXNzID0gZmFjdG9yeS5jbGFzczsgLy8gYXNzZXJ0KGAnJHtpbnNwZWN0KGtsYXNzKX0nIGRvZXMgbm90IGFwcGVhciB0byBiZSBhbiBlbWJlci1kYXRhIG1vZGVsYCwga2xhc3MuaXNNb2RlbCk7CiAgICAgIC8vIFRPRE86IGRlcHJlY2F0ZSB0aGlzCgogICAgICBpZiAoa2xhc3MuaXNNb2RlbCkgewogICAgICAgIHZhciBoYXNPd25Nb2RlbE5hbWVTZXQgPSBrbGFzcy5tb2RlbE5hbWUgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGtsYXNzLCAnbW9kZWxOYW1lJyk7CgogICAgICAgIGlmICghaGFzT3duTW9kZWxOYW1lU2V0KSB7CiAgICAgICAgICBrbGFzcy5tb2RlbE5hbWUgPSBub3JtYWxpemVkTW9kZWxOYW1lOwogICAgICAgIH0KICAgICAgfQoKICAgICAgY2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV0gPSBmYWN0b3J5OwogICAgfQoKICAgIHJldHVybiBmYWN0b3J5OwogIH0KICBmdW5jdGlvbiBfbG9va3VwTW9kZWxGYWN0b3J5KHN0b3JlLCBub3JtYWxpemVkTW9kZWxOYW1lKSB7CiAgICB2YXIgb3duZXIgPSBFbWJlci5nZXRPd25lcihzdG9yZSk7CiAgICByZXR1cm4gb3duZXIuZmFjdG9yeUZvcigibW9kZWw6IiArIG5vcm1hbGl6ZWRNb2RlbE5hbWUpOwogIH0KICAvKgogICAgICBJbiBjYXNlIHNvbWVvbmUgZGVmaW5lZCBhIHJlbGF0aW9uc2hpcCB0byBhIG1peGluLCBmb3IgZXhhbXBsZToKICAgICAgYGBgCiAgICAgICAgbGV0IENvbW1lbnQgPSBNb2RlbC5leHRlbmQoewogICAgICAgICAgb3duZXI6IGJlbG9uZ3NUbygnY29tbWVudGFibGUnLiB7IHBvbHltb3JwaGljOiB0cnVlIH0pCiAgICAgICAgfSk7CiAgICAgICAgbGV0IENvbW1lbnRhYmxlID0gRW1iZXIuTWl4aW4uY3JlYXRlKHsKICAgICAgICAgIGNvbW1lbnRzOiBoYXNNYW55KCdjb21tZW50JykKICAgICAgICB9KTsKICAgICAgYGBgCiAgICAgIHdlIHdhbnQgdG8gbG9vayB1cCBhIENvbW1lbnRhYmxlIGNsYXNzIHdoaWNoIGhhcyBhbGwgdGhlIG5lY2Vzc2FyeQogICAgICByZWxhdGlvbnNoaXAgbWV0YWRhdGEuIFRodXMsIHdlIGxvb2sgdXAgdGhlIG1peGluIGFuZCBjcmVhdGUgYSBtb2NrCiAgICAgIE1vZGVsLCBzbyB3ZSBjYW4gYWNjZXNzIHRoZSByZWxhdGlvbnNoaXAgQ1BzIG9mIHRoZSBtaXhpbiAoYGNvbW1lbnRzYCkKICAgICAgaW4gdGhpcyBjYXNlCiAgICAqLwoKICBmdW5jdGlvbiBfbW9kZWxGb3JNaXhpbihzdG9yZSwgbm9ybWFsaXplZE1vZGVsTmFtZSkgewogICAgaWYgKEhBU19NT0RFTF9QQUNLQUdFJDEpIHsKICAgICAgdmFyIG93bmVyID0gRW1iZXIuZ2V0T3duZXIoc3RvcmUpOwogICAgICB2YXIgTWF5YmVNaXhpbiA9IG93bmVyLmZhY3RvcnlGb3IoIm1peGluOiIgKyBub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgdmFyIG1peGluID0gTWF5YmVNaXhpbiAmJiBNYXliZU1peGluLmNsYXNzOwoKICAgICAgaWYgKG1peGluKSB7CiAgICAgICAgdmFyIE1vZGVsRm9yTWl4aW4gPSBnZXRNb2RlbCQxKCkuZXh0ZW5kKG1peGluKTsKICAgICAgICBNb2RlbEZvck1peGluLnJlb3BlbkNsYXNzKHsKICAgICAgICAgIF9faXNNaXhpbjogdHJ1ZSwKICAgICAgICAgIF9fbWl4aW46IG1peGluCiAgICAgICAgfSk7IC8vQ2FjaGUgdGhlIGNsYXNzIGFzIGEgbW9kZWwKCiAgICAgICAgb3duZXIucmVnaXN0ZXIoJ21vZGVsOicgKyBub3JtYWxpemVkTW9kZWxOYW1lLCBNb2RlbEZvck1peGluKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9sb29rdXBNb2RlbEZhY3Rvcnkoc3RvcmUsIG5vcm1hbGl6ZWRNb2RlbE5hbWUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gbm90aWZ5Q2hhbmdlcyhpZGVudGlmaWVyLCB2YWx1ZSwgcmVjb3JkLCBzdG9yZSkgewogICAgaWYgKHZhbHVlID09PSAnYXR0cmlidXRlcycpIHsKICAgICAgcmVjb3JkLmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24gKGtleSkgewogICAgICAgIHZhciBjdXJyZW50VmFsdWUgPSBFbWJlci5jYWNoZUZvcihyZWNvcmQsIGtleSk7CgogICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gc3RvcmUuX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShpZGVudGlmaWVyKTsKCiAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSAhPT0gaW50ZXJuYWxNb2RlbC5fcmVjb3JkRGF0YS5nZXRBdHRyKGtleSkpIHsKICAgICAgICAgIHJlY29yZC5ub3RpZnlQcm9wZXJ0eUNoYW5nZShrZXkpOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAncmVsYXRpb25zaGlwcycpIHsKICAgICAgcmVjb3JkLmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24gKGtleSwgbWV0YSkgewogICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gc3RvcmUuX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShpZGVudGlmaWVyKTsKCiAgICAgICAgaWYgKG1ldGEua2luZCA9PT0gJ2JlbG9uZ3NUbycpIHsKICAgICAgICAgIHJlY29yZC5ub3RpZnlQcm9wZXJ0eUNoYW5nZShrZXkpOwogICAgICAgIH0gZWxzZSBpZiAobWV0YS5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgICAgIGlmIChtZXRhLm9wdGlvbnMuYXN5bmMpIHsKICAgICAgICAgICAgcmVjb3JkLm5vdGlmeVByb3BlcnR5Q2hhbmdlKGtleSk7CiAgICAgICAgICAgIGludGVybmFsTW9kZWwuaGFzTWFueVJlbW92YWxDaGVjayhrZXkpOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChpbnRlcm5hbE1vZGVsLl9tYW55QXJyYXlDYWNoZVtrZXldKSB7CiAgICAgICAgICAgIGludGVybmFsTW9kZWwuX21hbnlBcnJheUNhY2hlW2tleV0ucmV0cmlldmVMYXRlc3QoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gJ2Vycm9ycycpIHsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBzdG9yZS5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlKGlkZW50aWZpZXIpOyAvL1RPRE8gZ3VhcmQKCgogICAgICB2YXIgZXJyb3JzID0gaW50ZXJuYWxNb2RlbC5fcmVjb3JkRGF0YS5nZXRFcnJvcnMoaWRlbnRpZmllcik7CgogICAgICByZWNvcmQuaW52YWxpZEVycm9yc0NoYW5nZWQoZXJyb3JzKTsKICAgIH0gZWxzZSBpZiAodmFsdWUgPT09ICdzdGF0ZScpIHsKICAgICAgcmVjb3JkLm5vdGlmeVByb3BlcnR5Q2hhbmdlKCdpc05ldycpOwogICAgICByZWNvcmQubm90aWZ5UHJvcGVydHlDaGFuZ2UoJ2lzRGVsZXRlZCcpOwogICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gJ2lkZW50aXR5JykgewogICAgICByZWNvcmQubm90aWZ5UHJvcGVydHlDaGFuZ2UoJ2lkJyk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZSQ0KHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcy5wcm90b3R5cGUpOyBzdWJDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBzdWJDbGFzczsgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfQogIC8qKgogICAgVGhlIHN0b3JlIHNlcnZpY2UgY29udGFpbnMgYWxsIG9mIHRoZSBkYXRhIGZvciByZWNvcmRzIGxvYWRlZCBmcm9tIHRoZSBzZXJ2ZXIuCiAgICBJdCBpcyBhbHNvIHJlc3BvbnNpYmxlIGZvciBjcmVhdGluZyBpbnN0YW5jZXMgb2YgYE1vZGVsYCB0aGF0IHdyYXAKICAgIHRoZSBpbmRpdmlkdWFsIGRhdGEgZm9yIGEgcmVjb3JkLCBzbyB0aGF0IHRoZXkgY2FuIGJlIGJvdW5kIHRvIGluIHlvdXIKICAgIEhhbmRsZWJhcnMgdGVtcGxhdGVzLgoKICAgIEJ5IGRlZmF1bHQsIGFwcGxpY2F0aW9ucyB3aWxsIGhhdmUgYSBzaW5nbGUgYFN0b3JlYCBzZXJ2aWNlIHRoYXQgaXMKICAgIGF1dG9tYXRpY2FsbHkgY3JlYXRlZC4KCiAgICBUaGUgc3RvcmUgY2FuIGJlIGN1c3RvbWl6ZWQgYnkgZXh0ZW5kaW5nIHRoZSBzZXJ2aWNlIGluIHRoZSBmb2xsb3dpbmcgbWFubmVyOgoKICAgIGBgYGFwcC9zZXJ2aWNlcy9zdG9yZS5qcwogICAgaW1wb3J0IFN0b3JlIGZyb20gJ0BlbWJlci1kYXRhL3N0b3JlJzsKCiAgICBleHBvcnQgZGVmYXVsdCBjbGFzcyBNeVN0b3JlIGV4dGVuZHMgU3RvcmUge30KICAgIGBgYAoKICAgIFlvdSBjYW4gcmV0cmlldmUgbW9kZWxzIGZyb20gdGhlIHN0b3JlIGluIHNldmVyYWwgd2F5cy4gVG8gcmV0cmlldmUgYSByZWNvcmQKICAgIGZvciBhIHNwZWNpZmljIGlkLCB1c2UgdGhlIGBTdG9yZWAncyBgZmluZFJlY29yZCgpYCBtZXRob2Q6CgogICAgYGBgamF2YXNjcmlwdAogICAgc3RvcmUuZmluZFJlY29yZCgncGVyc29uJywgMTIzKS50aGVuKGZ1bmN0aW9uIChwZXJzb24pIHsKICAgIH0pOwogICAgYGBgCgogICAgQnkgZGVmYXVsdCwgdGhlIHN0b3JlIHdpbGwgdGFsayB0byB5b3VyIGJhY2tlbmQgdXNpbmcgYSBzdGFuZGFyZAogICAgUkVTVCBtZWNoYW5pc20uIFlvdSBjYW4gY3VzdG9taXplIGhvdyB0aGUgc3RvcmUgdGFsa3MgdG8geW91cgogICAgYmFja2VuZCBieSBzcGVjaWZ5aW5nIGEgY3VzdG9tIGFkYXB0ZXI6CgogICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgRFMgZnJvbSAnZW1iZXItZGF0YSc7CgogICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlci5leHRlbmQoewogICAgfSk7CiAgICBgYGAKCiAgICBZb3UgY2FuIGxlYXJuIG1vcmUgYWJvdXQgd3JpdGluZyBhIGN1c3RvbSBhZGFwdGVyIGJ5IHJlYWRpbmcgdGhlIGBBZGFwdGVyYAogICAgZG9jdW1lbnRhdGlvbi4KCiAgICAjIyMgU3RvcmUgY3JlYXRlUmVjb3JkKCkgdnMuIHB1c2goKSB2cy4gcHVzaFBheWxvYWQoKQoKICAgIFRoZSBzdG9yZSBwcm92aWRlcyBtdWx0aXBsZSB3YXlzIHRvIGNyZWF0ZSBuZXcgcmVjb3JkIG9iamVjdHMuIFRoZXkgaGF2ZQogICAgc29tZSBzdWJ0bGUgZGlmZmVyZW5jZXMgaW4gdGhlaXIgdXNlIHdoaWNoIGFyZSBkZXRhaWxlZCBiZWxvdzoKCiAgICBbY3JlYXRlUmVjb3JkXShTdG9yZS9tZXRob2RzL2NyZWF0ZVJlY29yZD9hbmNob3I9Y3JlYXRlUmVjb3JkKSBpcyB1c2VkIGZvciBjcmVhdGluZyBuZXcKICAgIHJlY29yZHMgb24gdGhlIGNsaWVudCBzaWRlLiBUaGlzIHdpbGwgcmV0dXJuIGEgbmV3IHJlY29yZCBpbiB0aGUKICAgIGBjcmVhdGVkLnVuY29tbWl0dGVkYCBzdGF0ZS4gSW4gb3JkZXIgdG8gcGVyc2lzdCB0aGlzIHJlY29yZCB0byB0aGUKICAgIGJhY2tlbmQsIHlvdSB3aWxsIG5lZWQgdG8gY2FsbCBgcmVjb3JkLnNhdmUoKWAuCgogICAgW3B1c2hdKFN0b3JlL21ldGhvZHMvcHVzaD9hbmNob3I9cHVzaCkgaXMgdXNlZCB0byBub3RpZnkgRW1iZXIgRGF0YSdzIHN0b3JlIG9mIG5ldyBvcgogICAgdXBkYXRlZCByZWNvcmRzIHRoYXQgZXhpc3QgaW4gdGhlIGJhY2tlbmQuIFRoaXMgd2lsbCByZXR1cm4gYSByZWNvcmQKICAgIGluIHRoZSBgbG9hZGVkLnNhdmVkYCBzdGF0ZS4gVGhlIHByaW1hcnkgdXNlLWNhc2UgZm9yIGBzdG9yZSNwdXNoYCBpcwogICAgdG8gbm90aWZ5IEVtYmVyIERhdGEgYWJvdXQgcmVjb3JkIHVwZGF0ZXMgKGZ1bGwgb3IgcGFydGlhbCkgdGhhdCBoYXBwZW4KICAgIG91dHNpZGUgb2YgdGhlIG5vcm1hbCBhZGFwdGVyIG1ldGhvZHMgKGZvciBleGFtcGxlCiAgICBbU1NFXShodHRwOi8vZGV2LnczLm9yZy9odG1sNS9ldmVudHNvdXJjZS8pIG9yIFtXZWIKICAgIFNvY2tldHNdKGh0dHA6Ly93d3cudzMub3JnL1RSLzIwMDkvV0Qtd2Vic29ja2V0cy0yMDA5MTIyMi8pKS4KCiAgICBbcHVzaFBheWxvYWRdKFN0b3JlL21ldGhvZHMvcHVzaFBheWxvYWQ/YW5jaG9yPXB1c2hQYXlsb2FkKSBpcyBhIGNvbnZlbmllbmNlIHdyYXBwZXIgZm9yCiAgICBgc3RvcmUjcHVzaGAgdGhhdCB3aWxsIGRlc2VyaWFsaXplIHBheWxvYWRzIGlmIHRoZQogICAgU2VyaWFsaXplciBpbXBsZW1lbnRzIGEgYHB1c2hQYXlsb2FkYCBtZXRob2QuCgogICAgTm90ZTogV2hlbiBjcmVhdGluZyBhIG5ldyByZWNvcmQgdXNpbmcgYW55IG9mIHRoZSBhYm92ZSBtZXRob2RzCiAgICBFbWJlciBEYXRhIHdpbGwgdXBkYXRlIGBSZWNvcmRBcnJheWBzIHN1Y2ggYXMgdGhvc2UgcmV0dXJuZWQgYnkKICAgIGBzdG9yZSNwZWVrQWxsKClgIG9yIGBzdG9yZSNmaW5kQWxsKClgLiBUaGlzIG1lYW5zIGFueQogICAgZGF0YSBiaW5kaW5ncyBvciBjb21wdXRlZCBwcm9wZXJ0aWVzIHRoYXQgZGVwZW5kIG9uIHRoZSBSZWNvcmRBcnJheQogICAgd2lsbCBhdXRvbWF0aWNhbGx5IGJlIHN5bmNlZCB0byBpbmNsdWRlIHRoZSBuZXcgb3IgdXBkYXRlZCByZWNvcmQKICAgIHZhbHVlcy4KCiAgICBAY2xhc3MgU3RvcmUKICAgIEBtYWluIEBlbWJlci1kYXRhL3N0b3JlCiAgICBAZXh0ZW5kcyBFbWJlci5TZXJ2aWNlCiAgKi8KCiAgdmFyIFN0b3JlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Db3JlU3RvcmUpIHsKICAgIF9pbmhlcml0c0xvb3NlJDQoU3RvcmUsIF9Db3JlU3RvcmUpOwoKICAgIGZ1bmN0aW9uIFN0b3JlKCkgewogICAgICB2YXIgX3RoaXM7CgogICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICBfdGhpcyA9IF9Db3JlU3RvcmUuY2FsbC5hcHBseShfQ29yZVN0b3JlLCBbdGhpc10uY29uY2F0KGFyZ3MpKSB8fCB0aGlzOwogICAgICBfdGhpcy5fbW9kZWxGYWN0b3J5Q2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBfdGhpcy5fcmVsYXRpb25zaGlwc0RlZkNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgX3RoaXMuX2F0dHJpYnV0ZXNEZWZDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gU3RvcmUucHJvdG90eXBlOwoKICAgIF9wcm90by5pbnN0YW50aWF0ZVJlY29yZCA9IGZ1bmN0aW9uIGluc3RhbnRpYXRlUmVjb3JkKGlkZW50aWZpZXIsIGNyZWF0ZVJlY29yZEFyZ3MsIHJlY29yZERhdGFGb3IsIG5vdGlmaWNhdGlvbk1hbmFnZXIpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICB2YXIgbW9kZWxOYW1lID0gaWRlbnRpZmllci50eXBlOwoKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSB0aGlzLl9pbnRlcm5hbE1vZGVsRm9yUmVzb3VyY2UoaWRlbnRpZmllcik7CgogICAgICB2YXIgY3JlYXRlT3B0aW9ucyA9IHsKICAgICAgICBzdG9yZTogdGhpcywKICAgICAgICBfaW50ZXJuYWxNb2RlbDogaW50ZXJuYWxNb2RlbCwKICAgICAgICBjdXJyZW50U3RhdGU6IGludGVybmFsTW9kZWwuY3VycmVudFN0YXRlLAogICAgICAgIGNvbnRhaW5lcjogbnVsbAogICAgICB9OwogICAgICBFbWJlci5hc3NpZ24oY3JlYXRlT3B0aW9ucywgY3JlYXRlUmVjb3JkQXJncyk7IC8vIGVuc3VyZSB0aGF0IGBnZXRPd25lcih0aGlzKWAgd29ya3MgaW5zaWRlIGEgbW9kZWwgaW5zdGFuY2UKCiAgICAgIEVtYmVyLnNldE93bmVyKGNyZWF0ZU9wdGlvbnMsIEVtYmVyLmdldE93bmVyKHRoaXMpKTsKICAgICAgZGVsZXRlIGNyZWF0ZU9wdGlvbnMuY29udGFpbmVyOwoKICAgICAgdmFyIHJlY29yZCA9IHRoaXMuX21vZGVsRmFjdG9yeUZvcihtb2RlbE5hbWUpLmNyZWF0ZShjcmVhdGVPcHRpb25zKTsgLy90b2RvIG9wdGltaXplCgoKICAgICAgbm90aWZpY2F0aW9uTWFuYWdlci5zdWJzY3JpYmUoaWRlbnRpZmllciwgZnVuY3Rpb24gKGlkZW50aWZpZXIsIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIG5vdGlmeUNoYW5nZXMoaWRlbnRpZmllciwgdmFsdWUsIHJlY29yZCwgX3RoaXMyKTsKICAgICAgfSk7CiAgICAgIHJldHVybiByZWNvcmQ7CiAgICB9OwoKICAgIF9wcm90by50ZWFyZG93blJlY29yZCA9IGZ1bmN0aW9uIHRlYXJkb3duUmVjb3JkKHJlY29yZCkgewogICAgICByZWNvcmQuZGVzdHJveSgpOwogICAgfQogICAgLyoqCiAgICBSZXR1cm5zIHRoZSBtb2RlbCBjbGFzcyBmb3IgdGhlIHBhcnRpY3VsYXIgYG1vZGVsTmFtZWAuCiAgICAgVGhlIGNsYXNzIG9mIGEgbW9kZWwgbWlnaHQgYmUgdXNlZnVsIGlmIHlvdSB3YW50IHRvIGdldCBhIGxpc3Qgb2YgYWxsIHRoZQogICAgcmVsYXRpb25zaGlwIG5hbWVzIG9mIHRoZSBtb2RlbCwgc2VlCiAgICBbYHJlbGF0aW9uc2hpcE5hbWVzYF0oL2VtYmVyLWRhdGEvcmVsZWFzZS9jbGFzc2VzL01vZGVsP2FuY2hvcj1yZWxhdGlvbnNoaXBOYW1lcykKICAgIGZvciBleGFtcGxlLgogICAgIEBtZXRob2QgbW9kZWxGb3IKICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgIEByZXR1cm4ge01vZGVsfQogICAgICAqLwogICAgOwoKICAgIF9wcm90by5tb2RlbEZvciA9IGZ1bmN0aW9uIG1vZGVsRm9yKG1vZGVsTmFtZSkgewoKICAgICAgdmFyIG1heWJlRmFjdG9yeSA9IHRoaXMuX21vZGVsRmFjdG9yeUZvcihtb2RlbE5hbWUpOyAvLyBmb3IgZmFjdG9yRm9yIGZhY3RvcnkvY2xhc3Mgc3BsaXQKCgogICAgICB2YXIga2xhc3MgPSBtYXliZUZhY3RvcnkuY2xhc3MgPyBtYXliZUZhY3RvcnkuY2xhc3MgOiBtYXliZUZhY3Rvcnk7CgogICAgICBpZiAoIWtsYXNzLmlzTW9kZWwpIHsKICAgICAgICByZXR1cm4gbmV3IFNoaW1Nb2RlbENsYXNzKHRoaXMsIG1vZGVsTmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGtsYXNzOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fbW9kZWxGYWN0b3J5Rm9yID0gZnVuY3Rpb24gX21vZGVsRmFjdG9yeUZvcihtb2RlbE5hbWUpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgdmFyIGZhY3RvcnkgPSBnZXRNb2RlbEZhY3RvcnkodGhpcywgdGhpcy5fbW9kZWxGYWN0b3J5Q2FjaGUsIG5vcm1hbGl6ZWRNb2RlbE5hbWUpOwoKICAgICAgaWYgKGZhY3RvcnkgPT09IG51bGwpIHsKICAgICAgICB0aHJvdyBuZXcgRW1iZXIuRXJyb3IoIk5vIG1vZGVsIHdhcyBmb3VuZCBmb3IgJyIgKyBub3JtYWxpemVkTW9kZWxOYW1lICsgIiciKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGZhY3Rvcnk7CiAgICB9CiAgICAvKgogICAgUmV0dXJucyB3aGV0aGVyIGEgTW9kZWxDbGFzcyBleGlzdHMgZm9yIGEgZ2l2ZW4gbW9kZWxOYW1lCiAgICBUaGlzIGV4aXN0cyBmb3IgbGVnYWN5IHN1cHBvcnQgZm9yIHRoZSBSRVNUU2VyaWFsaXplciwKICAgIHdoaWNoIGR1ZSB0byBob3cgaXQgbXVzdCBndWVzcyB3aGV0aGVyIGEga2V5IGlzIGEgbW9kZWwKICAgIG11c3QgcXVlcnkgZm9yIHdoZXRoZXIgYSBtYXRjaCBleGlzdHMuCiAgICAgV2Ugc2hvdWxkIGludmVzdGlnYXRlIGFuIFJGQyB0byBtYWtlIHRoaXMgcHVibGljIG9yIHJlbW92aW5nCiAgICB0aGlzIHJlcXVpcmVtZW50LgogICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5faGFzTW9kZWxGb3IgPSBmdW5jdGlvbiBfaGFzTW9kZWxGb3IobW9kZWxOYW1lKSB7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UoKS5kb2VzVHlwZUV4aXN0KG1vZGVsTmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgICB2YXIgZmFjdG9yeSA9IGdldE1vZGVsRmFjdG9yeSh0aGlzLCB0aGlzLl9tb2RlbEZhY3RvcnlDYWNoZSwgbm9ybWFsaXplZE1vZGVsTmFtZSk7CiAgICAgICAgcmV0dXJuIGZhY3RvcnkgIT09IG51bGw7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9yZWxhdGlvbnNoaXBNZXRhRm9yID0gZnVuY3Rpb24gX3JlbGF0aW9uc2hpcE1ldGFGb3IobW9kZWxOYW1lLCBpZCwga2V5KSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICByZXR1cm4gdGhpcy5fcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IobW9kZWxOYW1lKVtrZXldOwogICAgICB9IGVsc2UgewogICAgICAgIHZhciBtb2RlbENsYXNzID0gdGhpcy5tb2RlbEZvcihtb2RlbE5hbWUpOwogICAgICAgIHZhciByZWxhdGlvbnNoaXBzQnlOYW1lID0gRW1iZXIuZ2V0KG1vZGVsQ2xhc3MsICdyZWxhdGlvbnNoaXBzQnlOYW1lJyk7CiAgICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcHNCeU5hbWUuZ2V0KGtleSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvciA9IGZ1bmN0aW9uIF9hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvcihtb2RlbE5hbWUsIGlkZW50aWZpZXIpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgIGlmIChpZGVudGlmaWVyKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5nZXRTY2hlbWFEZWZpbml0aW9uU2VydmljZSgpLmF0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKGlkZW50aWZpZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5nZXRTY2hlbWFEZWZpbml0aW9uU2VydmljZSgpLmF0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKG1vZGVsTmFtZSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHZhciBhdHRyaWJ1dGVzID0gdGhpcy5fYXR0cmlidXRlc0RlZkNhY2hlW21vZGVsTmFtZV07CgogICAgICAgIGlmIChhdHRyaWJ1dGVzID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHZhciBtb2RlbENsYXNzID0gdGhpcy5tb2RlbEZvcihtb2RlbE5hbWUpOwogICAgICAgICAgdmFyIGF0dHJpYnV0ZU1hcCA9IEVtYmVyLmdldChtb2RlbENsYXNzLCAnYXR0cmlidXRlcycpOwogICAgICAgICAgYXR0cmlidXRlcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgICBhdHRyaWJ1dGVNYXAuZm9yRWFjaChmdW5jdGlvbiAobWV0YSwgbmFtZSkgewogICAgICAgICAgICByZXR1cm4gYXR0cmlidXRlc1tuYW1lXSA9IG1ldGE7CiAgICAgICAgICB9KTsKICAgICAgICAgIHRoaXMuX2F0dHJpYnV0ZXNEZWZDYWNoZVttb2RlbE5hbWVdID0gYXR0cmlidXRlczsKICAgICAgICB9CgogICAgICAgIHJldHVybiBhdHRyaWJ1dGVzOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IgPSBmdW5jdGlvbiBfcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IobW9kZWxOYW1lLCBpZGVudGlmaWVyKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICBpZiAoaWRlbnRpZmllcikgewogICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UoKS5yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcihpZGVudGlmaWVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UoKS5yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcihtb2RlbE5hbWUpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgcmVsYXRpb25zaGlwcyA9IHRoaXMuX3JlbGF0aW9uc2hpcHNEZWZDYWNoZVttb2RlbE5hbWVdOwoKICAgICAgICBpZiAocmVsYXRpb25zaGlwcyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YXIgbW9kZWxDbGFzcyA9IHRoaXMubW9kZWxGb3IobW9kZWxOYW1lKTsKICAgICAgICAgIHJlbGF0aW9uc2hpcHMgPSBFbWJlci5nZXQobW9kZWxDbGFzcywgJ3JlbGF0aW9uc2hpcHNPYmplY3QnKSB8fCBudWxsOwogICAgICAgICAgdGhpcy5fcmVsYXRpb25zaGlwc0RlZkNhY2hlW21vZGVsTmFtZV0gPSByZWxhdGlvbnNoaXBzOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcHM7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmdldFNjaGVtYURlZmluaXRpb25TZXJ2aWNlID0gZnVuY3Rpb24gZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UoKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICBpZiAoIXRoaXMuX3NjaGVtYURlZmluaXRpb25TZXJ2aWNlKSB7CiAgICAgICAgICB0aGlzLl9zY2hlbWFEZWZpbml0aW9uU2VydmljZSA9IG5ldyBEU01vZGVsU2NoZW1hRGVmaW5pdGlvblNlcnZpY2UodGhpcyk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fc2NoZW1hRGVmaW5pdGlvblNlcnZpY2U7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgJ3NjaGVtYSBzZXJ2aWNlIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gY3VzdG9tIG1vZGVsIGNsYXNzIGZlYXR1cmUgZmxhZyBpcyBvbic7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIFN0b3JlOwogIH0oQ29yZVN0b3JlKTsKCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXMkOCh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgidmFsdWUiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfQoKICBmdW5jdGlvbiBfY3JlYXRlQ2xhc3MkOChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDgoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQ4KENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfQoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwogIGZ1bmN0aW9uIHR5cGVGb3JSZWxhdGlvbnNoaXBNZXRhKG1ldGEpIHsKICAgIHZhciBtb2RlbE5hbWU7CiAgICBtb2RlbE5hbWUgPSBtZXRhLnR5cGUgfHwgbWV0YS5rZXk7CiAgICBtb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKCiAgICBpZiAobWV0YS5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgbW9kZWxOYW1lID0gZW1iZXJJbmZsZWN0b3Iuc2luZ3VsYXJpemUobW9kZWxOYW1lKTsKICAgIH0KCiAgICByZXR1cm4gbW9kZWxOYW1lOwogIH0KCiAgZnVuY3Rpb24gc2hvdWxkRmluZEludmVyc2UocmVsYXRpb25zaGlwTWV0YSkgewogICAgdmFyIG9wdGlvbnMgPSByZWxhdGlvbnNoaXBNZXRhLm9wdGlvbnM7CiAgICByZXR1cm4gIShvcHRpb25zICYmIG9wdGlvbnMuaW52ZXJzZSA9PT0gbnVsbCk7CiAgfQoKICB2YXIgUmVsYXRpb25zaGlwRGVmaW5pdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJlbGF0aW9uc2hpcERlZmluaXRpb24obWV0YSkgewogICAgICB0aGlzLm1ldGEgPSBtZXRhOwogICAgICB0aGlzW0JSQU5EX1NZTUJPTF0gPSB2b2lkIDA7CiAgICAgIHRoaXMuX3R5cGUgPSAnJzsKICAgICAgdGhpcy5fX2ludmVyc2VLZXkgPSAnJzsKICAgICAgdGhpcy5fX2ludmVyc2VJc0FzeW5jID0gdHJ1ZTsKICAgICAgdGhpcy5fX2hhc0NhbGN1bGF0ZWRJbnZlcnNlID0gZmFsc2U7CiAgICAgIHRoaXMucGFyZW50TW9kZWxOYW1lID0gdm9pZCAwOwogICAgICB0aGlzLmludmVyc2UgPSB2b2lkIDA7CiAgICAgIHRoaXMuaW52ZXJzZUlzQXN5bmMgPSB2b2lkIDA7CiAgICAgIHRoaXMucGFyZW50TW9kZWxOYW1lID0gbWV0YS5wYXJlbnRNb2RlbE5hbWU7CiAgICB9CgogICAgdmFyIF9wcm90byA9IFJlbGF0aW9uc2hpcERlZmluaXRpb24ucHJvdG90eXBlOwoKICAgIF9wcm90by5faW52ZXJzZUtleSA9IGZ1bmN0aW9uIF9pbnZlcnNlS2V5KHN0b3JlLCBtb2RlbENsYXNzKSB7CiAgICAgIGlmICh0aGlzLl9faGFzQ2FsY3VsYXRlZEludmVyc2UgPT09IGZhbHNlKSB7CiAgICAgICAgdGhpcy5fY2FsY3VsYXRlSW52ZXJzZShzdG9yZSwgbW9kZWxDbGFzcyk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLl9faW52ZXJzZUtleTsKICAgIH07CgogICAgX3Byb3RvLl9pbnZlcnNlSXNBc3luYyA9IGZ1bmN0aW9uIF9pbnZlcnNlSXNBc3luYyhzdG9yZSwgbW9kZWxDbGFzcykgewogICAgICBpZiAodGhpcy5fX2hhc0NhbGN1bGF0ZWRJbnZlcnNlID09PSBmYWxzZSkgewogICAgICAgIHRoaXMuX2NhbGN1bGF0ZUludmVyc2Uoc3RvcmUsIG1vZGVsQ2xhc3MpOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fX2ludmVyc2VJc0FzeW5jOwogICAgfTsKCiAgICBfcHJvdG8uX2NhbGN1bGF0ZUludmVyc2UgPSBmdW5jdGlvbiBfY2FsY3VsYXRlSW52ZXJzZShzdG9yZSwgbW9kZWxDbGFzcykgewogICAgICB0aGlzLl9faGFzQ2FsY3VsYXRlZEludmVyc2UgPSB0cnVlOwogICAgICB2YXIgaW52ZXJzZUtleSwgaW52ZXJzZUlzQXN5bmM7CiAgICAgIHZhciBpbnZlcnNlID0gbnVsbDsKCiAgICAgIGlmIChzaG91bGRGaW5kSW52ZXJzZSh0aGlzLm1ldGEpKSB7CiAgICAgICAgaW52ZXJzZSA9IG1vZGVsQ2xhc3MuaW52ZXJzZUZvcih0aGlzLmtleSwgc3RvcmUpOwogICAgICB9CgogICAgICBpZiAoaW52ZXJzZSkgewogICAgICAgIGludmVyc2VLZXkgPSBpbnZlcnNlLm5hbWU7CiAgICAgICAgaW52ZXJzZUlzQXN5bmMgPSBpc0ludmVyc2VBc3luYyhpbnZlcnNlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpbnZlcnNlS2V5ID0gbnVsbDsKICAgICAgICBpbnZlcnNlSXNBc3luYyA9IGZhbHNlOwogICAgICB9CgogICAgICB0aGlzLl9faW52ZXJzZUtleSA9IGludmVyc2VLZXk7CiAgICAgIHRoaXMuX19pbnZlcnNlSXNBc3luYyA9IGludmVyc2VJc0FzeW5jOwogICAgfTsKCiAgICBfY3JlYXRlQ2xhc3MkOChSZWxhdGlvbnNoaXBEZWZpbml0aW9uLCBbewogICAgICBrZXk6ICJrZXkiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5tZXRhLmtleTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJraW5kIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMubWV0YS5raW5kOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInR5cGUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fdHlwZSkgewogICAgICAgICAgcmV0dXJuIHRoaXMuX3R5cGU7CiAgICAgICAgfQoKICAgICAgICB0aGlzLl90eXBlID0gdHlwZUZvclJlbGF0aW9uc2hpcE1ldGEodGhpcy5tZXRhKTsKICAgICAgICByZXR1cm4gdGhpcy5fdHlwZTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJvcHRpb25zIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMubWV0YS5vcHRpb25zOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogIm5hbWUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5tZXRhLm5hbWU7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gUmVsYXRpb25zaGlwRGVmaW5pdGlvbjsKICB9KCk7CgogIGZ1bmN0aW9uIGlzSW52ZXJzZUFzeW5jKG1ldGEpIHsKICAgIHZhciBpbnZlcnNlQXN5bmMgPSBtZXRhLm9wdGlvbnMgJiYgbWV0YS5vcHRpb25zLmFzeW5jOwogICAgcmV0dXJuIHR5cGVvZiBpbnZlcnNlQXN5bmMgPT09ICd1bmRlZmluZWQnID8gdHJ1ZSA6IGludmVyc2VBc3luYzsKICB9CgogIGZ1bmN0aW9uIHJlbGF0aW9uc2hpcEZyb21NZXRhKG1ldGEpIHsKICAgIHJldHVybiBuZXcgUmVsYXRpb25zaGlwRGVmaW5pdGlvbihtZXRhKTsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIHZhciByZWxhdGlvbnNoaXBzRGVzY3JpcHRvciA9IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgIHZhciBtYXAgPSBuZXcgTWFwKCk7CiAgICB2YXIgcmVsYXRpb25zaGlwc0J5TmFtZSA9IEVtYmVyLmdldCh0aGlzLCAncmVsYXRpb25zaGlwc0J5TmFtZScpOyAvLyBMb29wIHRocm91Z2ggZWFjaCBjb21wdXRlZCBwcm9wZXJ0eSBvbiB0aGUgY2xhc3MKCiAgICByZWxhdGlvbnNoaXBzQnlOYW1lLmZvckVhY2goZnVuY3Rpb24gKGRlc2MpIHsKICAgICAgdmFyIHR5cGUgPSBkZXNjLnR5cGU7CgogICAgICBpZiAoIW1hcC5oYXModHlwZSkpIHsKICAgICAgICBtYXAuc2V0KHR5cGUsIFtdKTsKICAgICAgfQoKICAgICAgbWFwLmdldCh0eXBlKS5wdXNoKGRlc2MpOwogICAgfSk7CiAgICByZXR1cm4gbWFwOwogIH0pLnJlYWRPbmx5KCk7CiAgdmFyIHJlbGF0ZWRUeXBlc0Rlc2NyaXB0b3IgPSBFbWJlci5jb21wdXRlZChmdW5jdGlvbiAoKSB7CgogICAgdmFyIHBhcmVudE1vZGVsTmFtZSA9IHRoaXMubW9kZWxOYW1lOwogICAgdmFyIHR5cGVzID0gRW1iZXIuQSgpOyAvLyBMb29wIHRocm91Z2ggZWFjaCBjb21wdXRlZCBwcm9wZXJ0eSBvbiB0aGUgY2xhc3MsCiAgICAvLyBhbmQgY3JlYXRlIGFuIGFycmF5IG9mIHRoZSB1bmlxdWUgdHlwZXMgaW52b2x2ZWQKICAgIC8vIGluIHJlbGF0aW9uc2hpcHMKCiAgICB0aGlzLmVhY2hDb21wdXRlZFByb3BlcnR5KGZ1bmN0aW9uIChuYW1lLCBtZXRhKSB7CiAgICAgIGlmIChtZXRhLmlzUmVsYXRpb25zaGlwKSB7CiAgICAgICAgbWV0YS5rZXkgPSBuYW1lOwogICAgICAgIHZhciBtb2RlbE5hbWUgPSB0eXBlRm9yUmVsYXRpb25zaGlwTWV0YShtZXRhKTsKCiAgICAgICAgaWYgKCF0eXBlcy5pbmNsdWRlcyhtb2RlbE5hbWUpKSB7CiAgICAgICAgICB0eXBlcy5wdXNoKG1vZGVsTmFtZSk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICAgIHJldHVybiB0eXBlczsKICB9KS5yZWFkT25seSgpOwogIHZhciByZWxhdGlvbnNoaXBzT2JqZWN0RGVzY3JpcHRvciA9IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgIHZhciByZWxhdGlvbnNoaXBzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHZhciBtb2RlbE5hbWUgPSB0aGlzLm1vZGVsTmFtZTsKICAgIHRoaXMuZWFjaENvbXB1dGVkUHJvcGVydHkoZnVuY3Rpb24gKG5hbWUsIG1ldGEpIHsKICAgICAgaWYgKG1ldGEuaXNSZWxhdGlvbnNoaXApIHsKICAgICAgICBtZXRhLmtleSA9IG5hbWU7CiAgICAgICAgbWV0YS5uYW1lID0gbmFtZTsKICAgICAgICBtZXRhLnBhcmVudE1vZGVsTmFtZSA9IG1vZGVsTmFtZTsKICAgICAgICByZWxhdGlvbnNoaXBzW25hbWVdID0gcmVsYXRpb25zaGlwRnJvbU1ldGEobWV0YSk7CiAgICAgIH0KICAgIH0pOwogICAgcmV0dXJuIHJlbGF0aW9uc2hpcHM7CiAgfSk7CiAgdmFyIHJlbGF0aW9uc2hpcHNCeU5hbWVEZXNjcmlwdG9yID0gRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgdmFyIG1hcCA9IG5ldyBNYXAoKTsKICAgIHZhciByZWxzID0gRW1iZXIuZ2V0KHRoaXMsICdyZWxhdGlvbnNoaXBzT2JqZWN0Jyk7CiAgICB2YXIgcmVsYXRpb25zaGlwcyA9IE9iamVjdC5rZXlzKHJlbHMpOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVsYXRpb25zaGlwcy5sZW5ndGg7IGkrKykgewogICAgICB2YXIga2V5ID0gcmVsYXRpb25zaGlwc1tpXTsKICAgICAgdmFyIHZhbHVlID0gcmVsc1trZXldOwogICAgICBtYXAuc2V0KHZhbHVlLmtleSwgdmFsdWUpOwogICAgfQoKICAgIHJldHVybiBtYXA7CiAgfSkucmVhZE9ubHkoKTsKCiAgZXhwb3J0cy5BZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXkgPSBBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXk7CiAgZXhwb3J0cy5EZXByZWNhdGVkRXZlbnRlZCA9IERlcHJlY2F0ZWRFdmVudGVkOwogIGV4cG9ydHMuRXJyb3JzID0gZXJyb3JzOwogIGV4cG9ydHMuSW50ZXJuYWxNb2RlbCA9IEludGVybmFsTW9kZWw7CiAgZXhwb3J0cy5NYW55QXJyYXkgPSBNYW55QXJyYXk7CiAgZXhwb3J0cy5Qcm9taXNlQXJyYXkgPSBQcm9taXNlQXJyYXk7CiAgZXhwb3J0cy5Qcm9taXNlTWFueUFycmF5ID0gUHJvbWlzZU1hbnlBcnJheTsKICBleHBvcnRzLlByb21pc2VPYmplY3QgPSBQcm9taXNlT2JqZWN0OwogIGV4cG9ydHMuUmVjb3JkQXJyYXkgPSBSZWNvcmRBcnJheTsKICBleHBvcnRzLlJlY29yZEFycmF5TWFuYWdlciA9IFJlY29yZEFycmF5TWFuYWdlcjsKICBleHBvcnRzLlJlY29yZERhdGFTdG9yZVdyYXBwZXIgPSBSZWNvcmREYXRhU3RvcmVXcmFwcGVyOwogIGV4cG9ydHMuUm9vdFN0YXRlID0gUm9vdFN0YXRlJDE7CiAgZXhwb3J0cy5TbmFwc2hvdCA9IFNuYXBzaG90OwogIGV4cG9ydHMuU25hcHNob3RSZWNvcmRBcnJheSA9IFNuYXBzaG90UmVjb3JkQXJyYXk7CiAgZXhwb3J0cy5TdG9yZSA9IFN0b3JlOwogIGV4cG9ydHMuX2JpbmQgPSBfYmluZDsKICBleHBvcnRzLl9ndWFyZCA9IF9ndWFyZDsKICBleHBvcnRzLl9vYmplY3RJc0FsaXZlID0gX29iamVjdElzQWxpdmU7CiAgZXhwb3J0cy5jb2VyY2VJZCA9IGNvZXJjZUlkOwogIGV4cG9ydHMuZGlmZkFycmF5ID0gZGlmZkFycmF5OwogIGV4cG9ydHMuZXJyb3JzQXJyYXlUb0hhc2ggPSBlcnJvcnNBcnJheVRvSGFzaDsKICBleHBvcnRzLmVycm9yc0hhc2hUb0FycmF5ID0gZXJyb3JzSGFzaFRvQXJyYXk7CiAgZXhwb3J0cy5ndWFyZERlc3Ryb3llZFN0b3JlID0gZ3VhcmREZXN0cm95ZWRTdG9yZTsKICBleHBvcnRzLmlkZW50aWZpZXJDYWNoZUZvciA9IGlkZW50aWZpZXJDYWNoZUZvcjsKICBleHBvcnRzLm5vcm1hbGl6ZU1vZGVsTmFtZSA9IG5vcm1hbGl6ZU1vZGVsTmFtZTsKICBleHBvcnRzLnJlY29yZERhdGFGb3IgPSByZWNvcmREYXRhRm9yOwogIGV4cG9ydHMucmVjb3JkSWRlbnRpZmllckZvciA9IHJlY29yZElkZW50aWZpZXJGb3I7CiAgZXhwb3J0cy5yZWxhdGVkVHlwZXNEZXNjcmlwdG9yID0gcmVsYXRlZFR5cGVzRGVzY3JpcHRvcjsKICBleHBvcnRzLnJlbGF0aW9uc2hpcHNCeU5hbWVEZXNjcmlwdG9yID0gcmVsYXRpb25zaGlwc0J5TmFtZURlc2NyaXB0b3I7CiAgZXhwb3J0cy5yZWxhdGlvbnNoaXBzRGVzY3JpcHRvciA9IHJlbGF0aW9uc2hpcHNEZXNjcmlwdG9yOwogIGV4cG9ydHMucmVsYXRpb25zaGlwc09iamVjdERlc2NyaXB0b3IgPSByZWxhdGlvbnNoaXBzT2JqZWN0RGVzY3JpcHRvcjsKICBleHBvcnRzLnNldElkZW50aWZpZXJGb3JnZXRNZXRob2QgPSBzZXRJZGVudGlmaWVyRm9yZ2V0TWV0aG9kOwogIGV4cG9ydHMuc2V0SWRlbnRpZmllckdlbmVyYXRpb25NZXRob2QgPSBzZXRJZGVudGlmaWVyR2VuZXJhdGlvbk1ldGhvZDsKICBleHBvcnRzLnNldElkZW50aWZpZXJSZXNldE1ldGhvZCA9IHNldElkZW50aWZpZXJSZXNldE1ldGhvZDsKICBleHBvcnRzLnNldElkZW50aWZpZXJVcGRhdGVNZXRob2QgPSBzZXRJZGVudGlmaWVyVXBkYXRlTWV0aG9kOwogIGV4cG9ydHMudXBncmFkZUZvckludGVybmFsID0gdXBncmFkZUZvckludGVybmFsOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pOwoKfSk7Cgo7ZGVmaW5lKCJAZW1iZXItZGF0YS9zdG9yZS9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9zdG9yZS8tcHJpdmF0ZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9wcml2YXRlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJkZWZhdWx0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUuU3RvcmU7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAibm9ybWFsaXplTW9kZWxOYW1lIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUubm9ybWFsaXplTW9kZWxOYW1lOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInNldElkZW50aWZpZXJHZW5lcmF0aW9uTWV0aG9kIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUuc2V0SWRlbnRpZmllckdlbmVyYXRpb25NZXRob2Q7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0SWRlbnRpZmllclVwZGF0ZU1ldGhvZCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9wcml2YXRlLnNldElkZW50aWZpZXJVcGRhdGVNZXRob2Q7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0SWRlbnRpZmllckZvcmdldE1ldGhvZCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9wcml2YXRlLnNldElkZW50aWZpZXJGb3JnZXRNZXRob2Q7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0SWRlbnRpZmllclJlc2V0TWV0aG9kIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUuc2V0SWRlbnRpZmllclJlc2V0TWV0aG9kOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInJlY29yZElkZW50aWZpZXJGb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJpdmF0ZS5yZWNvcmRJZGVudGlmaWVyRm9yOwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgnQGVtYmVyL29yZGVyZWQtc2V0L2luZGV4JywgWydleHBvcnRzJ10sIGZ1bmN0aW9uIChleHBvcnRzKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwoKICBmdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7CiAgICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgewogICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24iKTsKICAgIH0KICB9CgogIHZhciBORUVEU19DVVNUT01fT1JERVJFRF9TRVQgPSB0cnVlOwoKICB2YXIgT3JkZXJlZFNldCA9IHZvaWQgMDsKCiAgaWYgKE5FRURTX0NVU1RPTV9PUkRFUkVEX1NFVCkgewogICAgLyoqCiAgICBAY2xhc3MgT3JkZXJlZFNldAogICAgQGNvbnN0cnVjdG9yCiAgICAqLwogICAgT3JkZXJlZFNldCA9IGZ1bmN0aW9uICgpIHsKICAgICAgZnVuY3Rpb24gT3JkZXJlZFNldCgpIHsKICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgT3JkZXJlZFNldCk7CgogICAgICAgIHRoaXMuY2xlYXIoKTsKICAgICAgfQoKICAgICAgLyoqCiAgICAgIEBtZXRob2QgY3JlYXRlCiAgICAgIEBzdGF0aWMKICAgICAgQHJldHVybiB7T3JkZXJlZFNldH0KICAgICAgKi8KCgogICAgICBPcmRlcmVkU2V0LmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgICB2YXIgQ29uc3RydWN0b3IgPSB0aGlzOwogICAgICAgIHJldHVybiBuZXcgQ29uc3RydWN0b3IoKTsKICAgICAgfTsKCiAgICAgIE9yZGVyZWRTZXQucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7CiAgICAgICAgdGhpcy5wcmVzZW5jZVNldCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgdGhpcy5saXN0ID0gW107CiAgICAgICAgdGhpcy5zaXplID0gMDsKICAgICAgfTsKCiAgICAgIE9yZGVyZWRTZXQucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uIGFkZChvYmosIF9ndWlkKSB7CiAgICAgICAgdmFyIGd1aWQgPSBfZ3VpZCB8fCBFbWJlci5ndWlkRm9yKG9iaik7CiAgICAgICAgdmFyIHByZXNlbmNlU2V0ID0gdGhpcy5wcmVzZW5jZVNldDsKICAgICAgICB2YXIgbGlzdCA9IHRoaXMubGlzdDsKCiAgICAgICAgaWYgKHByZXNlbmNlU2V0W2d1aWRdICE9PSB0cnVlKSB7CiAgICAgICAgICBwcmVzZW5jZVNldFtndWlkXSA9IHRydWU7CiAgICAgICAgICB0aGlzLnNpemUgPSBsaXN0LnB1c2gob2JqKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9OwoKICAgICAgT3JkZXJlZFNldC5wcm90b3R5cGUuZGVsZXRlID0gZnVuY3Rpb24gX2RlbGV0ZShvYmosIF9ndWlkKSB7CiAgICAgICAgdmFyIGd1aWQgPSBfZ3VpZCB8fCBFbWJlci5ndWlkRm9yKG9iaik7CiAgICAgICAgdmFyIHByZXNlbmNlU2V0ID0gdGhpcy5wcmVzZW5jZVNldDsKICAgICAgICB2YXIgbGlzdCA9IHRoaXMubGlzdDsKCiAgICAgICAgaWYgKHByZXNlbmNlU2V0W2d1aWRdID09PSB0cnVlKSB7CiAgICAgICAgICBkZWxldGUgcHJlc2VuY2VTZXRbZ3VpZF07CiAgICAgICAgICB2YXIgaW5kZXggPSBsaXN0LmluZGV4T2Yob2JqKTsKICAgICAgICAgIGlmIChpbmRleCA+IC0xKSB7CiAgICAgICAgICAgIGxpc3Quc3BsaWNlKGluZGV4LCAxKTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuc2l6ZSA9IGxpc3QubGVuZ3RoOwogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH07CgogICAgICBPcmRlcmVkU2V0LnByb3RvdHlwZS5pc0VtcHR5ID0gZnVuY3Rpb24gaXNFbXB0eSgpIHsKICAgICAgICByZXR1cm4gdGhpcy5zaXplID09PSAwOwogICAgICB9OwoKICAgICAgT3JkZXJlZFNldC5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24gaGFzKG9iaikgewogICAgICAgIGlmICh0aGlzLnNpemUgPT09IDApIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CgogICAgICAgIHZhciBndWlkID0gRW1iZXIuZ3VpZEZvcihvYmopOwogICAgICAgIHZhciBwcmVzZW5jZVNldCA9IHRoaXMucHJlc2VuY2VTZXQ7CgogICAgICAgIHJldHVybiBwcmVzZW5jZVNldFtndWlkXSA9PT0gdHJ1ZTsKICAgICAgfTsKCiAgICAgIE9yZGVyZWRTZXQucHJvdG90eXBlLmZvckVhY2ggPSBmdW5jdGlvbiBmb3JFYWNoKGZuIC8qLCAuLi50aGlzQXJnKi8pIHsKICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgZm4gPT09ICdmdW5jdGlvbicpICYmIEVtYmVyLmFzc2VydChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZm4pICsgJyBpcyBub3QgYSBmdW5jdGlvbicsIHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJykpOwoKCiAgICAgICAgaWYgKHRoaXMuc2l6ZSA9PT0gMCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgdmFyIGxpc3QgPSB0aGlzLmxpc3Q7CgogICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyKSB7CiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgZm4uY2FsbChhcmd1bWVudHNbMV0sIGxpc3RbaV0pOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgbGlzdC5sZW5ndGg7IF9pKyspIHsKICAgICAgICAgICAgZm4obGlzdFtfaV0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfTsKCiAgICAgIE9yZGVyZWRTZXQucHJvdG90eXBlLnRvQXJyYXkgPSBmdW5jdGlvbiB0b0FycmF5KCkgewogICAgICAgIHJldHVybiB0aGlzLmxpc3Quc2xpY2UoKTsKICAgICAgfTsKCiAgICAgIE9yZGVyZWRTZXQucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiBjb3B5KCkgewogICAgICAgIHZhciBDb25zdHJ1Y3RvciA9IHRoaXMuY29uc3RydWN0b3I7CiAgICAgICAgdmFyIHNldCA9IG5ldyBDb25zdHJ1Y3RvcigpOwoKICAgICAgICBzZXQucHJlc2VuY2VTZXQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwoKICAgICAgICBmb3IgKHZhciBwcm9wIGluIHRoaXMucHJlc2VuY2VTZXQpIHsKICAgICAgICAgIC8vIGhhc093blByb3BlcnkgaXMgbm90IG5lZWRlZCBiZWNhdXNlIG9iaiBpcyBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgc2V0LnByZXNlbmNlU2V0W3Byb3BdID0gdGhpcy5wcmVzZW5jZVNldFtwcm9wXTsKICAgICAgICB9CgogICAgICAgIHNldC5saXN0ID0gdGhpcy50b0FycmF5KCk7CiAgICAgICAgc2V0LnNpemUgPSB0aGlzLnNpemU7CgogICAgICAgIHJldHVybiBzZXQ7CiAgICAgIH07CgogICAgICByZXR1cm4gT3JkZXJlZFNldDsKICAgIH0oKTsKICB9IGVsc2UgewogICAgT3JkZXJlZFNldCA9IEVtYmVyLl9fT3JkZXJlZFNldF9fIHx8IEVtYmVyLk9yZGVyZWRTZXQ7CiAgfQoKICBleHBvcnRzLmRlZmF1bHQgPSBPcmRlcmVkU2V0Owp9KTsKO2RlZmluZSgnZW1iZXItY2xpLWFwcC12ZXJzaW9uL2luaXRpYWxpemVyLWZhY3RvcnknLCBbJ2V4cG9ydHMnXSwgZnVuY3Rpb24gKGV4cG9ydHMpIHsKICAndXNlIHN0cmljdCc7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgZXhwb3J0cy5kZWZhdWx0ID0gaW5pdGlhbGl6ZXJGYWN0b3J5OwogIHZhciBsaWJyYXJpZXMgPSBFbWJlci5saWJyYXJpZXM7CiAgZnVuY3Rpb24gaW5pdGlhbGl6ZXJGYWN0b3J5KG5hbWUsIHZlcnNpb24pIHsKICAgIHZhciByZWdpc3RlcmVkID0gZmFsc2U7CgogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgaWYgKCFyZWdpc3RlcmVkICYmIG5hbWUgJiYgdmVyc2lvbikgewogICAgICAgIHZhciBhcHBOYW1lID0gRW1iZXIuU3RyaW5nLmNsYXNzaWZ5KG5hbWUpOwogICAgICAgIGxpYnJhcmllcy5yZWdpc3RlcihhcHBOYW1lLCB2ZXJzaW9uKTsKICAgICAgICByZWdpc3RlcmVkID0gdHJ1ZTsKICAgICAgfQogICAgfTsKICB9Cn0pOwo7ZGVmaW5lKCJlbWJlci1jbGktYXBwLXZlcnNpb24vdXRpbHMvcmVnZXhwIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChleHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIHZhciB2ZXJzaW9uUmVnRXhwID0gZXhwb3J0cy52ZXJzaW9uUmVnRXhwID0gL1xkK1suXVxkK1suXVxkKy87IC8vIE1hdGNoIGFueSBudW1iZXIgb2YgMyBzZWN0aW9ucyBvZiBkaWdpdHMgc2VwYXJhdGVkIGJ5IC4KICB2YXIgdmVyc2lvbkV4dGVuZGVkUmVnRXhwID0gZXhwb3J0cy52ZXJzaW9uRXh0ZW5kZWRSZWdFeHAgPSAvXGQrWy5dXGQrWy5dXGQrLVthLXpdKihbLl1cZCspPy87IC8vIE1hdGNoIHRoZSBhYm92ZSBidXQgYWxzbyBoeXBoZW4gZm9sbG93ZWQgYnkgYW55IG51bWJlciBvZiBsb3dlcmNhc2UgbGV0dGVycywgdGhlbiBvcHRpb25hbGx5IHBlcmlvZCBhbmQgZGlnaXRzCiAgdmFyIHNoYVJlZ0V4cCA9IGV4cG9ydHMuc2hhUmVnRXhwID0gL1thLXpcZF17OH0kLzsgLy8gTWF0Y2ggOCBsb3dlcmNhc2UgbGV0dGVycyBhbmQgZGlnaXRzLCBhdCB0aGUgZW5kIG9mIHRoZSBzdHJpbmcgb25seSAodG8gYXZvaWQgbWF0Y2hpbmcgd2l0aCB2ZXJzaW9uIGV4dGVuZGVkIHBhcnQpCn0pOwo7ZGVmaW5lKCdlbWJlci1kYXRhLy1wcml2YXRlJywgWydleHBvcnRzJywgJ0BlbWJlci1kYXRhL3N0b3JlLy1wcml2YXRlJywgJ0BlbWJlci1kYXRhL3N0b3JlJywgJ2VtYmVyLWRhdGEvdmVyc2lvbicsICdAZW1iZXItZGF0YS9yZWNvcmQtZGF0YS8tcHJpdmF0ZSddLCBmdW5jdGlvbiAoZXhwb3J0cywgUHJpdmF0ZSwgc3RvcmUsIFZFUlNJT04sIFByaXZhdGUkMSkgeyAndXNlIHN0cmljdCc7CgogIHN0b3JlID0gc3RvcmUgJiYgc3RvcmUuaGFzT3duUHJvcGVydHkoJ2RlZmF1bHQnKSA/IHN0b3JlWydkZWZhdWx0J10gOiBzdG9yZTsKICBWRVJTSU9OID0gVkVSU0lPTiAmJiBWRVJTSU9OLmhhc093blByb3BlcnR5KCdkZWZhdWx0JykgPyBWRVJTSU9OWydkZWZhdWx0J10gOiBWRVJTSU9OOwoKICAvKioKICAgKiBAcHJvcGVydHkgVkVSU0lPTgogICAqIEBwdWJsaWMKICAgKiBAc3RhdGljCiAgICogQGZvciBAZW1iZXItZGF0YQogICAqLwoKICB2YXIgRFMgPSBFbWJlci5OYW1lc3BhY2UuY3JlYXRlKHsKICAgIFZFUlNJT046IFZFUlNJT04sCiAgICBuYW1lOiAnRFMnCiAgfSk7CgogIGlmIChFbWJlci5saWJyYXJpZXMpIHsKICAgIEVtYmVyLmxpYnJhcmllcy5yZWdpc3RlckNvcmVMaWJyYXJ5KCdFbWJlciBEYXRhJywgVkVSU0lPTik7CiAgfQoKICBmdW5jdGlvbiBmZWF0dXJlSXNFbmFibGVkKCkgewogICAgcmV0dXJuIEVtYmVyLkZFQVRVUkVTLmlzRW5hYmxlZC5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cyk7CiAgfQoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ0FkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheScsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIFByaXZhdGUuQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnRXJyb3JzJywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5FcnJvcnM7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdJbnRlcm5hbE1vZGVsJywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5JbnRlcm5hbE1vZGVsOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnTWFueUFycmF5JywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5NYW55QXJyYXk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdQcm9taXNlQXJyYXknLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLlByb21pc2VBcnJheTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ1Byb21pc2VNYW55QXJyYXknLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLlByb21pc2VNYW55QXJyYXk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdQcm9taXNlT2JqZWN0JywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5Qcm9taXNlT2JqZWN0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnUmVjb3JkQXJyYXknLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLlJlY29yZEFycmF5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnUmVjb3JkQXJyYXlNYW5hZ2VyJywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5SZWNvcmRBcnJheU1hbmFnZXI7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdSb290U3RhdGUnLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLlJvb3RTdGF0ZTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ1NuYXBzaG90JywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5TbmFwc2hvdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ1NuYXBzaG90UmVjb3JkQXJyYXknLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLlNuYXBzaG90UmVjb3JkQXJyYXk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdjb2VyY2VJZCcsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIFByaXZhdGUuY29lcmNlSWQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdub3JtYWxpemVNb2RlbE5hbWUnLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLm5vcm1hbGl6ZU1vZGVsTmFtZTsKICAgIH0KICB9KTsKICBleHBvcnRzLlN0b3JlID0gc3RvcmU7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdSZWNvcmREYXRhJywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZSQxLlJlY29yZERhdGE7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdSZWxhdGlvbnNoaXAnLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlJDEuUmVsYXRpb25zaGlwOwogICAgfQogIH0pOwogIGV4cG9ydHMuRFMgPSBEUzsKICBleHBvcnRzLmlzRW5hYmxlZCA9IGZlYXR1cmVJc0VuYWJsZWQ7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7Cgp9KTsKCjtkZWZpbmUoImVtYmVyLWRhdGEvYWRhcHRlciIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9hZGFwdGVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2FkYXB0ZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlZmF1bHQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYWRhcHRlci5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9hZGFwdGVycy9lcnJvcnMiLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvYWRhcHRlci9lcnJvciJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lcnJvcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQWJvcnRFcnJvciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9lcnJvci5BYm9ydEVycm9yOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkFkYXB0ZXJFcnJvciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9lcnJvci5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkNvbmZsaWN0RXJyb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZXJyb3IuQ29uZmxpY3RFcnJvcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJGb3JiaWRkZW5FcnJvciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9lcnJvci5Gb3JiaWRkZW5FcnJvcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJJbnZhbGlkRXJyb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZXJyb3IuSW52YWxpZEVycm9yOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIk5vdEZvdW5kRXJyb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZXJyb3IuTm90Rm91bmRFcnJvcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJTZXJ2ZXJFcnJvciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9lcnJvci5TZXJ2ZXJFcnJvcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJUaW1lb3V0RXJyb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZXJyb3IuVGltZW91dEVycm9yOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIlVuYXV0aG9yaXplZEVycm9yIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2Vycm9yLlVuYXV0aG9yaXplZEVycm9yOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImVycm9yc0FycmF5VG9IYXNoIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2Vycm9yLmVycm9yc0FycmF5VG9IYXNoOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImVycm9yc0hhc2hUb0FycmF5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2Vycm9yLmVycm9yc0hhc2hUb0FycmF5OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9hZGFwdGVycy9qc29uLWFwaSIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9hZGFwdGVyL2pzb24tYXBpIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2pzb25BcGkpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlZmF1bHQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfanNvbkFwaS5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9hZGFwdGVycy9yZXN0IiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9yZXN0KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJkZWZhdWx0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3Jlc3QuZGVmYXVsdDsKICAgIH0KICB9KTsKfSk7CjtkZWZpbmUoImVtYmVyLWRhdGEvYXR0ciIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9tb2RlbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tb2RlbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZGVmYXVsdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9tb2RlbC5hdHRyOwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9pbmRleCIsIFsiZXhwb3J0cyIsICJlbWJlci1kYXRhL3N0b3JlIiwgIkBlbWJlci1kYXRhL3N0b3JlIiwgIkBlbWJlci1kYXRhL2RlYnVnIiwgImVtYmVyLWRhdGEvLXByaXZhdGUiLCAiZW1iZXItaW5mbGVjdG9yIiwgImVtYmVyLWRhdGEvc2V0dXAtY29udGFpbmVyIiwgImVtYmVyLWRhdGEvaW5pdGlhbGl6ZS1zdG9yZS1zZXJ2aWNlIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvdHJhbnNmb3JtIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvLXByaXZhdGUiLCAiQGVtYmVyLWRhdGEvYWRhcHRlciIsICJAZW1iZXItZGF0YS9hZGFwdGVyL2pzb24tYXBpIiwgIkBlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCIsICJAZW1iZXItZGF0YS9hZGFwdGVyL2Vycm9yIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIiLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uLWFwaSIsICJAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24iLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0IiwgIkBlbWJlci1kYXRhL21vZGVsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3N0b3JlLCBfc3RvcmUyLCBfZGVidWcsIF9wcml2YXRlLCBfZW1iZXJJbmZsZWN0b3IsIF9zZXR1cENvbnRhaW5lciwgX2luaXRpYWxpemVTdG9yZVNlcnZpY2UsIF90cmFuc2Zvcm0sIF9wcml2YXRlMiwgX2FkYXB0ZXIsIF9qc29uQXBpLCBfcmVzdCwgX2Vycm9yLCBfc2VyaWFsaXplciwgX2pzb25BcGkyLCBfanNvbiwgX3Jlc3QyLCBfbW9kZWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIGlmIChFbWJlci5WRVJTSU9OLm1hdGNoKC9eMVwuKFswLTldfDFbMC0yXSlcLi8pKSB7CiAgICB0aHJvdyBuZXcgRW1iZXIuRXJyb3IoJ0VtYmVyIERhdGEgcmVxdWlyZXMgYXQgbGVhc3QgRW1iZXIgMS4xMy4wLCBidXQgeW91IGhhdmUgJyArIEVtYmVyLlZFUlNJT04gKyAnLiBQbGVhc2UgdXBncmFkZSB5b3VyIHZlcnNpb24gb2YgRW1iZXIsIHRoZW4gdXBncmFkZSBFbWJlciBEYXRhLicpOwogIH0KCiAgX3ByaXZhdGUuRFMuU3RvcmUgPSBfc3RvcmUuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5Qcm9taXNlQXJyYXkgPSBfcHJpdmF0ZS5Qcm9taXNlQXJyYXk7CiAgX3ByaXZhdGUuRFMuUHJvbWlzZU9iamVjdCA9IF9wcml2YXRlLlByb21pc2VPYmplY3Q7CiAgX3ByaXZhdGUuRFMuUHJvbWlzZU1hbnlBcnJheSA9IF9wcml2YXRlLlByb21pc2VNYW55QXJyYXk7CiAgX3ByaXZhdGUuRFMuTW9kZWwgPSBfbW9kZWwuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5Sb290U3RhdGUgPSBfcHJpdmF0ZS5Sb290U3RhdGU7CiAgX3ByaXZhdGUuRFMuYXR0ciA9IF9tb2RlbC5hdHRyOwogIF9wcml2YXRlLkRTLkVycm9ycyA9IF9wcml2YXRlLkVycm9yczsKICBfcHJpdmF0ZS5EUy5JbnRlcm5hbE1vZGVsID0gX3ByaXZhdGUuSW50ZXJuYWxNb2RlbDsKICBfcHJpdmF0ZS5EUy5TbmFwc2hvdCA9IF9wcml2YXRlLlNuYXBzaG90OwogIF9wcml2YXRlLkRTLkFkYXB0ZXIgPSBfYWRhcHRlci5kZWZhdWx0OwogIF9wcml2YXRlLkRTLkFkYXB0ZXJFcnJvciA9IF9lcnJvci5kZWZhdWx0OwogIF9wcml2YXRlLkRTLkludmFsaWRFcnJvciA9IF9lcnJvci5JbnZhbGlkRXJyb3I7CiAgX3ByaXZhdGUuRFMuVGltZW91dEVycm9yID0gX2Vycm9yLlRpbWVvdXRFcnJvcjsKICBfcHJpdmF0ZS5EUy5BYm9ydEVycm9yID0gX2Vycm9yLkFib3J0RXJyb3I7CiAgX3ByaXZhdGUuRFMuVW5hdXRob3JpemVkRXJyb3IgPSBfZXJyb3IuVW5hdXRob3JpemVkRXJyb3I7CiAgX3ByaXZhdGUuRFMuRm9yYmlkZGVuRXJyb3IgPSBfZXJyb3IuRm9yYmlkZGVuRXJyb3I7CiAgX3ByaXZhdGUuRFMuTm90Rm91bmRFcnJvciA9IF9lcnJvci5Ob3RGb3VuZEVycm9yOwogIF9wcml2YXRlLkRTLkNvbmZsaWN0RXJyb3IgPSBfZXJyb3IuQ29uZmxpY3RFcnJvcjsKICBfcHJpdmF0ZS5EUy5TZXJ2ZXJFcnJvciA9IF9lcnJvci5TZXJ2ZXJFcnJvcjsKICBfcHJpdmF0ZS5EUy5lcnJvcnNIYXNoVG9BcnJheSA9IF9lcnJvci5lcnJvcnNIYXNoVG9BcnJheTsKICBfcHJpdmF0ZS5EUy5lcnJvcnNBcnJheVRvSGFzaCA9IF9lcnJvci5lcnJvcnNBcnJheVRvSGFzaDsKICBfcHJpdmF0ZS5EUy5TZXJpYWxpemVyID0gX3NlcmlhbGl6ZXIuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5EZWJ1Z0FkYXB0ZXIgPSBfZGVidWcuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5SZWNvcmRBcnJheSA9IF9wcml2YXRlLlJlY29yZEFycmF5OwogIF9wcml2YXRlLkRTLkFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheSA9IF9wcml2YXRlLkFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheTsKICBfcHJpdmF0ZS5EUy5NYW55QXJyYXkgPSBfcHJpdmF0ZS5NYW55QXJyYXk7CiAgX3ByaXZhdGUuRFMuUmVjb3JkQXJyYXlNYW5hZ2VyID0gX3ByaXZhdGUuUmVjb3JkQXJyYXlNYW5hZ2VyOwogIF9wcml2YXRlLkRTLlJFU1RBZGFwdGVyID0gX3Jlc3QuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5CdWlsZFVSTE1peGluID0gX2FkYXB0ZXIuQnVpbGRVUkxNaXhpbjsKICBfcHJpdmF0ZS5EUy5SRVNUU2VyaWFsaXplciA9IF9yZXN0Mi5kZWZhdWx0OwogIF9wcml2YXRlLkRTLkpTT05TZXJpYWxpemVyID0gX2pzb24uZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5KU09OQVBJQWRhcHRlciA9IF9qc29uQXBpLmRlZmF1bHQ7CiAgX3ByaXZhdGUuRFMuSlNPTkFQSVNlcmlhbGl6ZXIgPSBfanNvbkFwaTIuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5UcmFuc2Zvcm0gPSBfdHJhbnNmb3JtLmRlZmF1bHQ7CiAgX3ByaXZhdGUuRFMuRGF0ZVRyYW5zZm9ybSA9IF9wcml2YXRlMi5EYXRlVHJhbnNmb3JtOwogIF9wcml2YXRlLkRTLlN0cmluZ1RyYW5zZm9ybSA9IF9wcml2YXRlMi5TdHJpbmdUcmFuc2Zvcm07CiAgX3ByaXZhdGUuRFMuTnVtYmVyVHJhbnNmb3JtID0gX3ByaXZhdGUyLk51bWJlclRyYW5zZm9ybTsKICBfcHJpdmF0ZS5EUy5Cb29sZWFuVHJhbnNmb3JtID0gX3ByaXZhdGUyLkJvb2xlYW5UcmFuc2Zvcm07CiAgX3ByaXZhdGUuRFMuRW1iZWRkZWRSZWNvcmRzTWl4aW4gPSBfcmVzdDIuRW1iZWRkZWRSZWNvcmRzTWl4aW47CiAgX3ByaXZhdGUuRFMuYmVsb25nc1RvID0gX21vZGVsLmJlbG9uZ3NUbzsKICBfcHJpdmF0ZS5EUy5oYXNNYW55ID0gX21vZGVsLmhhc01hbnk7CiAgX3ByaXZhdGUuRFMuUmVsYXRpb25zaGlwID0gX3ByaXZhdGUuUmVsYXRpb25zaGlwOwogIF9wcml2YXRlLkRTLl9zZXR1cENvbnRhaW5lciA9IF9zZXR1cENvbnRhaW5lci5kZWZhdWx0OwogIF9wcml2YXRlLkRTLl9pbml0aWFsaXplU3RvcmVTZXJ2aWNlID0gX2luaXRpYWxpemVTdG9yZVNlcnZpY2UuZGVmYXVsdDsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX3ByaXZhdGUuRFMsICdub3JtYWxpemVNb2RlbE5hbWUnLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgd3JpdGFibGU6IGZhbHNlLAogICAgY29uZmlndXJhYmxlOiBmYWxzZSwKICAgIHZhbHVlOiBfc3RvcmUyLm5vcm1hbGl6ZU1vZGVsTmFtZQogIH0pOwogIHZhciBfZGVmYXVsdCA9IF9wcml2YXRlLkRTOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CjtkZWZpbmUoImVtYmVyLWRhdGEvaW5pdGlhbGl6ZS1zdG9yZS1zZXJ2aWNlIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IGluaXRpYWxpemVTdG9yZVNlcnZpY2U7CgogIC8qCiAgICBDb25maWd1cmVzIGEgcmVnaXN0cnkgZm9yIHVzZSB3aXRoIGFuIEVtYmVyLURhdGEKICAgIHN0b3JlLgogIAogICAgQG1ldGhvZCBpbml0aWFsaXplU3RvcmVTZXJ2aWNlCiAgICBAcGFyYW0ge0VtYmVyLkFwcGxpY2F0aW9uSW5zdGFuY2UgfCBFbWJlci5FbmdpbmVJbnN0YW5jZX0gaW5zdGFuY2UKICAqLwogIGZ1bmN0aW9uIGluaXRpYWxpemVTdG9yZVNlcnZpY2UoaW5zdGFuY2UpIHsKICAgIC8vIGluc3RhbmNlLmxvb2t1cCBzdXBwb3J0cyBFbWJlciAyLjEgYW5kIGhpZ2hlcgogICAgLy8gaW5zdGFuY2UuY29udGFpbmVyIHN1cHBvcnRzIEVtYmVyIDEuMTEgLSAyLjAKICAgIHZhciBjb250YWluZXIgPSBpbnN0YW5jZS5sb29rdXAgPyBpbnN0YW5jZSA6IGluc3RhbmNlLmNvbnRhaW5lcjsgLy8gRWFnZXJseSBnZW5lcmF0ZSB0aGUgc3RvcmUgc28gZGVmYXVsdFN0b3JlIGlzIHBvcHVsYXRlZC4KCiAgICBjb250YWluZXIubG9va3VwKCdzZXJ2aWNlOnN0b3JlJyk7CiAgfQp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9tb2RlbCIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9tb2RlbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tb2RlbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZGVmYXVsdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9tb2RlbC5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9yZWxhdGlvbnNoaXBzIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL21vZGVsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21vZGVsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJiZWxvbmdzVG8iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbW9kZWwuYmVsb25nc1RvOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImhhc01hbnkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbW9kZWwuaGFzTWFueTsKICAgIH0KICB9KTsKfSk7CjtkZWZpbmUoImVtYmVyLWRhdGEvc2VyaWFsaXplciIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9zZXJpYWxpemVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3NlcmlhbGl6ZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlZmF1bHQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfc2VyaWFsaXplci5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9zZXJpYWxpemVycy9lbWJlZGRlZC1yZWNvcmRzLW1peGluIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9yZXN0KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJkZWZhdWx0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3Jlc3QuRW1iZWRkZWRSZWNvcmRzTWl4aW47CiAgICB9CiAgfSk7Cn0pOwo7ZGVmaW5lKCJlbWJlci1kYXRhL3NlcmlhbGl6ZXJzL2pzb24tYXBpIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbi1hcGkiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfanNvbkFwaSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZGVmYXVsdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9qc29uQXBpLmRlZmF1bHQ7CiAgICB9CiAgfSk7Cn0pOwo7ZGVmaW5lKCJlbWJlci1kYXRhL3NlcmlhbGl6ZXJzL2pzb24iLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2pzb24pIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlZmF1bHQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfanNvbi5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9zZXJpYWxpemVycy9yZXN0IiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9yZXN0KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJkZWZhdWx0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3Jlc3QuZGVmYXVsdDsKICAgIH0KICB9KTsKfSk7CjtkZWZpbmUoImVtYmVyLWRhdGEvc2V0dXAtY29udGFpbmVyIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3N0b3JlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3N0b3JlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gc2V0dXBDb250YWluZXI7CgogIGZ1bmN0aW9uIGluaXRpYWxpemVTdG9yZShhcHBsaWNhdGlvbikgewogICAgLy8gd2UgY2FuIGp1c3QgdXNlIHJlZ2lzdGVyT3B0aW9uc0ZvclR5cGUgd2hlbiB3ZSBubyBsb25nZXIKICAgIC8vIHN1cHBvcnQgKGRlcHJlY2F0ZWQpIHZlcnNpb25zIG9mIEBlbWJlci90ZXN0LWhlbHBlcnMKICAgIC8vIFdlJ3JlIGlzc3VpbmcgYSAicHJpdmF0ZS1hcGkiIGRlcHJlY2F0aW9uIGZvciB1c2VycyBvZiB0aGUKICAgIC8vIGRlcHJlY2F0ZWQgQGVtYmVyL3Rlc3QtaGVscGVycyB2ZXJzaW9ucywgYnV0IHdpbGwga2VlcAogICAgLy8gdGhpcyBmb3IgYXMgbG9uZyBhcyB1bnRpbCA0LjAgYXMgbmVlZGVkCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICAmJiAhYXBwbGljYXRpb24ucmVnaXN0ZXJPcHRpb25zRm9yVHlwZSkgewogICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgRW1iZXIuZGVwcmVjYXRlKCJEZXByZWNhdGVkIHRlc3Qgc3ludGF4IHVzYWdlIGRldGVjdGVkIVxuXG5cdCIgKyAiVGhpcyB0ZXN0IHJlbGllcyBvbiBhIGRlcHJlY2F0ZWQgdGVzdCBzZXR1cCB0aGF0IGlzIG5vIGxvbmdlciBzdXBwb3J0ZWQgYnkgRW1iZXJEYXRhLiIgKyAiIFRvIHJlc29sdmUgdGhpcyB5b3Ugd2lsbCBuZWVkIHRvIGJlIG9uIGEgcmVjZW50IHZlcnNpb24gb2YgQGVtYmVyL3Rlc3QtaGVscGVycyIgKyAiIEFORCB5b3VyIHRlc3RzIG11c3QgdXNlIGBzZXRBcHBsaWNhdGlvbigpYCBpbnN0ZWFkIG9mIGBzZXRSZXNvbHZlcigpYCBhbmQiICsgIiBgbW9kdWxlKClgIHdpdGggYHNldHVwKlRlc3QoKWBpbnN0ZWFkIG9mIGBtb2R1bGVGb3IqKClgLiIsIGZhbHNlLCB7CiAgICAgICAgaWQ6ICdlbWJlci1kYXRhOmxlZ2FjeS10ZXN0LWhlbHBlci1zdXBwb3J0JywKICAgICAgICB1bnRpbDogJzMuMTcnCiAgICAgIH0pKTsKICAgICAgYXBwbGljYXRpb24ub3B0aW9uc0ZvclR5cGUoJ3NlcmlhbGl6ZXInLCB7CiAgICAgICAgc2luZ2xldG9uOiBmYWxzZQogICAgICB9KTsKICAgICAgYXBwbGljYXRpb24ub3B0aW9uc0ZvclR5cGUoJ2FkYXB0ZXInLCB7CiAgICAgICAgc2luZ2xldG9uOiBmYWxzZQogICAgICB9KTsKCiAgICAgIGlmICghYXBwbGljYXRpb24uaGFzKCdzZXJ2aWNlOnN0b3JlJykpIHsKICAgICAgICBhcHBsaWNhdGlvbi5yZWdpc3Rlcignc2VydmljZTpzdG9yZScsIF9zdG9yZS5kZWZhdWx0KTsKICAgICAgfQoKICAgICAgcmV0dXJuOwogICAgfQoKICAgIGFwcGxpY2F0aW9uLnJlZ2lzdGVyT3B0aW9uc0ZvclR5cGUoJ3NlcmlhbGl6ZXInLCB7CiAgICAgIHNpbmdsZXRvbjogZmFsc2UKICAgIH0pOwogICAgYXBwbGljYXRpb24ucmVnaXN0ZXJPcHRpb25zRm9yVHlwZSgnYWRhcHRlcicsIHsKICAgICAgc2luZ2xldG9uOiBmYWxzZQogICAgfSk7CgogICAgaWYgKCFhcHBsaWNhdGlvbi5oYXNSZWdpc3RyYXRpb24oJ3NlcnZpY2U6c3RvcmUnKSkgewogICAgICBhcHBsaWNhdGlvbi5yZWdpc3Rlcignc2VydmljZTpzdG9yZScsIF9zdG9yZS5kZWZhdWx0KTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGluaXRpYWxpemVTdG9yZUluamVjdGlvbnMoYXBwbGljYXRpb24pIHsKICAgIHZhciBpbmplY3QgPSBhcHBsaWNhdGlvbi5pbmplY3QgfHwgYXBwbGljYXRpb24uaW5qZWN0aW9uOwogICAgaW5qZWN0LmNhbGwoYXBwbGljYXRpb24sICdjb250cm9sbGVyJywgJ3N0b3JlJywgJ3NlcnZpY2U6c3RvcmUnKTsKICAgIGluamVjdC5jYWxsKGFwcGxpY2F0aW9uLCAncm91dGUnLCAnc3RvcmUnLCAnc2VydmljZTpzdG9yZScpOwogIH0KCiAgZnVuY3Rpb24gc2V0dXBDb250YWluZXIoYXBwbGljYXRpb24pIHsKICAgIGluaXRpYWxpemVTdG9yZUluamVjdGlvbnMoYXBwbGljYXRpb24pOwogICAgaW5pdGlhbGl6ZVN0b3JlKGFwcGxpY2F0aW9uKTsKICB9Cn0pOwo7ZGVmaW5lKCJlbWJlci1kYXRhL3N0b3JlIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3N0b3JlIiwgIkBlbWJlci1kYXRhL3JlY29yZC1kYXRhLy1wcml2YXRlIiwgIkBlbWJlci1kYXRhL3N0b3JlLy1wcml2YXRlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3N0b3JlLCBfcHJpdmF0ZSwgX3ByaXZhdGUyKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZShzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MucHJvdG90eXBlKTsgc3ViQ2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gc3ViQ2xhc3M7IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH0KCiAgdmFyIERlZmF1bHRTdG9yZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfU3RvcmUpIHsKICAgIF9pbmhlcml0c0xvb3NlKERlZmF1bHRTdG9yZSwgX1N0b3JlKTsKCiAgICBmdW5jdGlvbiBEZWZhdWx0U3RvcmUoKSB7CiAgICAgIHJldHVybiBfU3RvcmUuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBEZWZhdWx0U3RvcmUucHJvdG90eXBlOwoKICAgIF9wcm90by5jcmVhdGVSZWNvcmREYXRhRm9yID0gZnVuY3Rpb24gY3JlYXRlUmVjb3JkRGF0YUZvcihtb2RlbE5hbWUsIGlkLCBjbGllbnRJZCwgc3RvcmVXcmFwcGVyKSB7CiAgICAgIGlmICh0cnVlCiAgICAgIC8qIElERU5USUZJRVJTICovCiAgICAgICkgewogICAgICAgIHZhciBpZGVudGlmaWVyID0gKDAsIF9wcml2YXRlMi5pZGVudGlmaWVyQ2FjaGVGb3IpKHRoaXMpLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcih7CiAgICAgICAgICB0eXBlOiBtb2RlbE5hbWUsCiAgICAgICAgICBpZDogaWQsCiAgICAgICAgICBsaWQ6IGNsaWVudElkCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIG5ldyBfcHJpdmF0ZS5SZWNvcmREYXRhKGlkZW50aWZpZXIsIHN0b3JlV3JhcHBlcik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyBfcHJpdmF0ZS5SZWNvcmREYXRhKG1vZGVsTmFtZSwgaWQsIGNsaWVudElkLCBzdG9yZVdyYXBwZXIpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBEZWZhdWx0U3RvcmU7CiAgfShfc3RvcmUuZGVmYXVsdCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBEZWZhdWx0U3RvcmU7Cn0pOwo7ZGVmaW5lKCJlbWJlci1kYXRhL3RyYW5zZm9ybSIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9zZXJpYWxpemVyL3RyYW5zZm9ybSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF90cmFuc2Zvcm0pIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlZmF1bHQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfdHJhbnNmb3JtLmRlZmF1bHQ7CiAgICB9CiAgfSk7Cn0pOwo7ZGVmaW5lKCJlbWJlci1kYXRhL3ZlcnNpb24iLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwogIHZhciBfZGVmYXVsdCA9ICIzLjE1LjAtYWxwaGEuMSI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKO2RlZmluZSgnZW1iZXItaW5mbGVjdG9yL2luZGV4JywgWydleHBvcnRzJywgJ2VtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtJywgJ2VtYmVyLWluZmxlY3Rvci9saWIvZXh0L3N0cmluZyddLCBmdW5jdGlvbiAoZXhwb3J0cywgX3N5c3RlbSkgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLmRlZmF1bHRSdWxlcyA9IGV4cG9ydHMuc2luZ3VsYXJpemUgPSBleHBvcnRzLnBsdXJhbGl6ZSA9IHVuZGVmaW5lZDsKCgogIF9zeXN0ZW0uSW5mbGVjdG9yLmRlZmF1bHRSdWxlcyA9IF9zeXN0ZW0uZGVmYXVsdFJ1bGVzOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICdJbmZsZWN0b3InLCB7CiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgRW1iZXIuZGVwcmVjYXRlKCdFbWJlci5JbmZsZWN0b3IgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGV4cGxpY2l0bHk6IGltcG9ydCBJbmZsZWN0b3IgZnJvbSBcJ2VtYmVyLWluZmxlY3RvclwnOycsIGZhbHNlLCB7CiAgICAgICAgaWQ6ICdlbWJlci1pbmZsZWN0b3IuZ2xvYmFscycsCiAgICAgICAgdW50aWw6ICczLjAuMCcKICAgICAgfSk7CgogICAgICByZXR1cm4gX3N5c3RlbS5JbmZsZWN0b3I7CiAgICB9CiAgfSwgeyBjb25maWd1cmFibGU6IHRydWUgfSk7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFbWJlci5TdHJpbmcsICdzaW5ndWxhcml6ZScsIHsKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICBFbWJlci5kZXByZWNhdGUoJ0VtYmVyLlN0cmluZy5zaW5ndWxhcml6ZSgpIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSBleHBsaWNpdGx5OiBpbXBvcnQgeyBzaW5ndWxhcml6ZSB9IGZyb20gXCdlbWJlci1pbmZsZWN0b3JcJzsnLCBmYWxzZSwgewogICAgICAgIGlkOiAnZW1iZXItaW5mbGVjdG9yLmdsb2JhbHMnLAogICAgICAgIHVudGlsOiAnMy4wLjAnCiAgICAgIH0pOwoKICAgICAgcmV0dXJuIF9zeXN0ZW0uc2luZ3VsYXJpemU7CiAgICB9CiAgfSwgeyBjb25maWd1cmFibGU6IHRydWUgfSk7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFbWJlci5TdHJpbmcsICdwbHVyYWxpemUnLCB7CiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgRW1iZXIuZGVwcmVjYXRlKCdFbWJlci5TdHJpbmcucGx1cmFsaXplKCkgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGV4cGxpY2l0bHk6IGltcG9ydCB7IHBsdXJhbGl6ZSB9IGZyb20gXCdlbWJlci1pbmZsZWN0b3JcJzsnLCBmYWxzZSwgewogICAgICAgIGlkOiAnZW1iZXItaW5mbGVjdG9yLmdsb2JhbHMnLAogICAgICAgIHVudGlsOiAnMy4wLjAnCiAgICAgIH0pOwoKICAgICAgcmV0dXJuIF9zeXN0ZW0ucGx1cmFsaXplOwogICAgfQogIH0sIHsgY29uZmlndXJhYmxlOiB0cnVlIH0pOwoKICBleHBvcnRzLmRlZmF1bHQgPSBfc3lzdGVtLkluZmxlY3RvcjsKICBleHBvcnRzLnBsdXJhbGl6ZSA9IF9zeXN0ZW0ucGx1cmFsaXplOwogIGV4cG9ydHMuc2luZ3VsYXJpemUgPSBfc3lzdGVtLnNpbmd1bGFyaXplOwogIGV4cG9ydHMuZGVmYXVsdFJ1bGVzID0gX3N5c3RlbS5kZWZhdWx0UnVsZXM7Cn0pOwo7ZGVmaW5lKCdlbWJlci1pbmZsZWN0b3IvbGliL2V4dC9zdHJpbmcnLCBbJ2VtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtL3N0cmluZyddLCBmdW5jdGlvbiAoX3N0cmluZykgewogICd1c2Ugc3RyaWN0JzsKCiAgaWYgKEVtYmVyLkVOVi5FWFRFTkRfUFJPVE9UWVBFUyA9PT0gdHJ1ZSB8fCBFbWJlci5FTlYuRVhURU5EX1BST1RPVFlQRVMuU3RyaW5nKSB7CiAgICAvKioKICAgICAgU2VlIHt7I2Nyb3NzTGluayAiRW1iZXIuU3RyaW5nL3BsdXJhbGl6ZSJ9fXt7L2Nyb3NzTGlua319CiAgICAgICBAbWV0aG9kIHBsdXJhbGl6ZQogICAgICBAZm9yIFN0cmluZwogICAgKi8KICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShTdHJpbmcucHJvdG90eXBlLCAncGx1cmFsaXplJywgewogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBFbWJlci5kZXByZWNhdGUoJ1N0cmluZy5wcm90b3R5cGUucGx1cmFsaXplKCkgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGV4cGxpY2l0bHk6IGltcG9ydCB7IHBsdXJhbGl6ZSB9IGZyb20gXCdlbWJlci1pbmZsZWN0b3JcJzsnLCBmYWxzZSwgewogICAgICAgICAgaWQ6ICdlbWJlci1pbmZsZWN0b3IuZ2xvYmFscycsCiAgICAgICAgICB1bnRpbDogJzMuMC4wJwogICAgICAgIH0pOwoKICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuICgwLCBfc3RyaW5nLnBsdXJhbGl6ZSkodGhpcyk7CiAgICAgICAgfTsKICAgICAgfQogICAgfSwgeyBjb25maWd1cmFibGU6IHRydWUgfSk7CgogICAgLyoqCiAgICAgIFNlZSB7eyNjcm9zc0xpbmsgIkVtYmVyLlN0cmluZy9zaW5ndWxhcml6ZSJ9fXt7L2Nyb3NzTGlua319CiAgICAgICBAbWV0aG9kIHNpbmd1bGFyaXplCiAgICAgIEBmb3IgU3RyaW5nCiAgICAqLwogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFN0cmluZy5wcm90b3R5cGUsICdzaW5ndWxhcml6ZScsIHsKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgRW1iZXIuZGVwcmVjYXRlKCdTdHJpbmcucHJvdG90eXBlLnNpbmd1bGFyaXplKCkgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGV4cGxpY2l0bHk6IGltcG9ydCB7IHNpbmd1bGFyaXplIH0gZnJvbSBcJ2VtYmVyLWluZmxlY3RvclwnOycsIGZhbHNlLCB7CiAgICAgICAgICBpZDogJ2VtYmVyLWluZmxlY3Rvci5nbG9iYWxzJywKICAgICAgICAgIHVudGlsOiAnMy4wLjAnCiAgICAgICAgfSk7CgogICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gKDAsIF9zdHJpbmcuc2luZ3VsYXJpemUpKHRoaXMpOwogICAgICAgIH07CiAgICAgIH0KICAgIH0sIHsgY29uZmlndXJhYmxlOiB0cnVlIH0pOwogIH0KfSk7CjtkZWZpbmUoJ2VtYmVyLWluZmxlY3Rvci9saWIvaGVscGVycy9wbHVyYWxpemUnLCBbJ2V4cG9ydHMnLCAnZW1iZXItaW5mbGVjdG9yJywgJ2VtYmVyLWluZmxlY3Rvci9saWIvdXRpbHMvbWFrZS1oZWxwZXInXSwgZnVuY3Rpb24gKGV4cG9ydHMsIF9lbWJlckluZmxlY3RvciwgX21ha2VIZWxwZXIpIHsKICAndXNlIHN0cmljdCc7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CgogIGZ1bmN0aW9uIF90b0NvbnN1bWFibGVBcnJheShhcnIpIHsKICAgIGlmIChBcnJheS5pc0FycmF5KGFycikpIHsKICAgICAgZm9yICh2YXIgaSA9IDAsIGFycjIgPSBBcnJheShhcnIubGVuZ3RoKTsgaSA8IGFyci5sZW5ndGg7IGkrKykgewogICAgICAgIGFycjJbaV0gPSBhcnJbaV07CiAgICAgIH0KCiAgICAgIHJldHVybiBhcnIyOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIEFycmF5LmZyb20oYXJyKTsKICAgIH0KICB9CgogIGV4cG9ydHMuZGVmYXVsdCA9ICgwLCBfbWFrZUhlbHBlci5kZWZhdWx0KShmdW5jdGlvbiAocGFyYW1zLCBoYXNoKSB7CiAgICB2YXIgZnVsbFBhcmFtcyA9IG5ldyAoRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQuYXBwbHkoQXJyYXksIFtudWxsXS5jb25jYXQoX3RvQ29uc3VtYWJsZUFycmF5KHBhcmFtcykpKSkoKTsKCiAgICBpZiAoZnVsbFBhcmFtcy5sZW5ndGggPT09IDIpIHsKICAgICAgZnVsbFBhcmFtcy5wdXNoKHsgd2l0aG91dENvdW50OiBoYXNoWyJ3aXRob3V0LWNvdW50Il0gfSk7CiAgICB9CgogICAgcmV0dXJuIF9lbWJlckluZmxlY3Rvci5wbHVyYWxpemUuYXBwbHkodW5kZWZpbmVkLCBfdG9Db25zdW1hYmxlQXJyYXkoZnVsbFBhcmFtcykpOwogIH0pOwp9KTsKO2RlZmluZSgnZW1iZXItaW5mbGVjdG9yL2xpYi9oZWxwZXJzL3Npbmd1bGFyaXplJywgWydleHBvcnRzJywgJ2VtYmVyLWluZmxlY3RvcicsICdlbWJlci1pbmZsZWN0b3IvbGliL3V0aWxzL21ha2UtaGVscGVyJ10sIGZ1bmN0aW9uIChleHBvcnRzLCBfZW1iZXJJbmZsZWN0b3IsIF9tYWtlSGVscGVyKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIGV4cG9ydHMuZGVmYXVsdCA9ICgwLCBfbWFrZUhlbHBlci5kZWZhdWx0KShmdW5jdGlvbiAocGFyYW1zKSB7CiAgICByZXR1cm4gKDAsIF9lbWJlckluZmxlY3Rvci5zaW5ndWxhcml6ZSkocGFyYW1zWzBdKTsKICB9KTsKfSk7CjtkZWZpbmUoImVtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtIiwgWyJleHBvcnRzIiwgImVtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtL2luZmxlY3RvciIsICJlbWJlci1pbmZsZWN0b3IvbGliL3N5c3RlbS9zdHJpbmciLCAiZW1iZXItaW5mbGVjdG9yL2xpYi9zeXN0ZW0vaW5mbGVjdGlvbnMiXSwgZnVuY3Rpb24gKGV4cG9ydHMsIF9pbmZsZWN0b3IsIF9zdHJpbmcsIF9pbmZsZWN0aW9ucykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLmRlZmF1bHRSdWxlcyA9IGV4cG9ydHMucGx1cmFsaXplID0gZXhwb3J0cy5zaW5ndWxhcml6ZSA9IGV4cG9ydHMuSW5mbGVjdG9yID0gdW5kZWZpbmVkOwoKCiAgX2luZmxlY3Rvci5kZWZhdWx0LmluZmxlY3RvciA9IG5ldyBfaW5mbGVjdG9yLmRlZmF1bHQoX2luZmxlY3Rpb25zLmRlZmF1bHQpOwoKICBleHBvcnRzLkluZmxlY3RvciA9IF9pbmZsZWN0b3IuZGVmYXVsdDsKICBleHBvcnRzLnNpbmd1bGFyaXplID0gX3N0cmluZy5zaW5ndWxhcml6ZTsKICBleHBvcnRzLnBsdXJhbGl6ZSA9IF9zdHJpbmcucGx1cmFsaXplOwogIGV4cG9ydHMuZGVmYXVsdFJ1bGVzID0gX2luZmxlY3Rpb25zLmRlZmF1bHQ7Cn0pOwo7ZGVmaW5lKCdlbWJlci1pbmZsZWN0b3IvbGliL3N5c3RlbS9pbmZsZWN0aW9ucycsIFsnZXhwb3J0cyddLCBmdW5jdGlvbiAoZXhwb3J0cykgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLmRlZmF1bHQgPSB7CiAgICBwbHVyYWxzOiBbWy8kLywgJ3MnXSwgWy9zJC9pLCAncyddLCBbL14oYXh8dGVzdClpcyQvaSwgJyQxZXMnXSwgWy8ob2N0b3B8dmlyKXVzJC9pLCAnJDFpJ10sIFsvKG9jdG9wfHZpcilpJC9pLCAnJDFpJ10sIFsvKGFsaWFzfHN0YXR1c3xib251cykkL2ksICckMWVzJ10sIFsvKGJ1KXMkL2ksICckMXNlcyddLCBbLyhidWZmYWx8dG9tYXQpbyQvaSwgJyQxb2VzJ10sIFsvKFt0aV0pdW0kL2ksICckMWEnXSwgWy8oW3RpXSlhJC9pLCAnJDFhJ10sIFsvc2lzJC9pLCAnc2VzJ10sIFsvKD86KFteZl0pZmV8KFtscl0pZikkL2ksICckMSQydmVzJ10sIFsvKGhpdmUpJC9pLCAnJDFzJ10sIFsvKFteYWVpb3V5XXxxdSl5JC9pLCAnJDFpZXMnXSwgWy8oeHxjaHxzc3xzaCkkL2ksICckMWVzJ10sIFsvKG1hdHJ8dmVydHxpbmQpKD86aXh8ZXgpJC9pLCAnJDFpY2VzJ10sIFsvXihtfGwpb3VzZSQvaSwgJyQxaWNlJ10sIFsvXihtfGwpaWNlJC9pLCAnJDFpY2UnXSwgWy9eKG94KSQvaSwgJyQxZW4nXSwgWy9eKG94ZW4pJC9pLCAnJDEnXSwgWy8ocXVpeikkL2ksICckMXplcyddXSwKCiAgICBzaW5ndWxhcjogW1svcyQvaSwgJyddLCBbLyhzcykkL2ksICckMSddLCBbLyhuKWV3cyQvaSwgJyQxZXdzJ10sIFsvKFt0aV0pYSQvaSwgJyQxdW0nXSwgWy8oKGEpbmFseXwoYilhfChkKWlhZ25vfChwKWFyZW50aGV8KHApcm9nbm98KHMpeW5vcHwodCloZSkoc2lzfHNlcykkL2ksICckMXNpcyddLCBbLyheYW5hbHkpKHNpc3xzZXMpJC9pLCAnJDFzaXMnXSwgWy8oW15mXSl2ZXMkL2ksICckMWZlJ10sIFsvKGhpdmUpcyQvaSwgJyQxJ10sIFsvKHRpdmUpcyQvaSwgJyQxJ10sIFsvKFtscl0pdmVzJC9pLCAnJDFmJ10sIFsvKFteYWVpb3V5XXxxdSlpZXMkL2ksICckMXknXSwgWy8ocyllcmllcyQvaSwgJyQxZXJpZXMnXSwgWy8obSlvdmllcyQvaSwgJyQxb3ZpZSddLCBbLyh4fGNofHNzfHNoKWVzJC9pLCAnJDEnXSwgWy9eKG18bClpY2UkL2ksICckMW91c2UnXSwgWy8oYnVzKShlcyk/JC9pLCAnJDEnXSwgWy8obyllcyQvaSwgJyQxJ10sIFsvKHNob2UpcyQvaSwgJyQxJ10sIFsvKGNyaXN8dGVzdCkoaXN8ZXMpJC9pLCAnJDFpcyddLCBbL14oYSl4W2llXXMkL2ksICckMXhpcyddLCBbLyhvY3RvcHx2aXIpKHVzfGkpJC9pLCAnJDF1cyddLCBbLyhhbGlhc3xzdGF0dXN8Ym9udXMpKGVzKT8kL2ksICckMSddLCBbL14ob3gpZW4vaSwgJyQxJ10sIFsvKHZlcnR8aW5kKWljZXMkL2ksICckMWV4J10sIFsvKG1hdHIpaWNlcyQvaSwgJyQxaXgnXSwgWy8ocXVpeil6ZXMkL2ksICckMSddLCBbLyhkYXRhYmFzZSlzJC9pLCAnJDEnXV0sCgogICAgaXJyZWd1bGFyUGFpcnM6IFtbJ3BlcnNvbicsICdwZW9wbGUnXSwgWydtYW4nLCAnbWVuJ10sIFsnY2hpbGQnLCAnY2hpbGRyZW4nXSwgWydzZXgnLCAnc2V4ZXMnXSwgWydtb3ZlJywgJ21vdmVzJ10sIFsnY293JywgJ2tpbmUnXSwgWyd6b21iaWUnLCAnem9tYmllcyddXSwKCiAgICB1bmNvdW50YWJsZTogWydlcXVpcG1lbnQnLCAnaW5mb3JtYXRpb24nLCAncmljZScsICdtb25leScsICdzcGVjaWVzJywgJ3NlcmllcycsICdmaXNoJywgJ3NoZWVwJywgJ2plYW5zJywgJ3BvbGljZSddCiAgfTsKfSk7CjtkZWZpbmUoJ2VtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtL2luZmxlY3RvcicsIFsnZXhwb3J0cyddLCBmdW5jdGlvbiAoZXhwb3J0cykgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKCgogIHZhciBCTEFOS19SRUdFWCA9IC9eXHMqJC87CiAgdmFyIExBU1RfV09SRF9EQVNIRURfUkVHRVggPSAvKFtcdy8tXStbXy9ccy1dKShbYS16XGRdKyQpLzsKICB2YXIgTEFTVF9XT1JEX0NBTUVMSVpFRF9SRUdFWCA9IC8oW1x3L1xzLV0rKShbQS1aXVthLXpcZF0qJCkvOwogIHZhciBDQU1FTElaRURfUkVHRVggPSAvW0EtWl1bYS16XGRdKiQvOwoKICBmdW5jdGlvbiBsb2FkVW5jb3VudGFibGUocnVsZXMsIHVuY291bnRhYmxlKSB7CiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gdW5jb3VudGFibGUubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgcnVsZXMudW5jb3VudGFibGVbdW5jb3VudGFibGVbaV0udG9Mb3dlckNhc2UoKV0gPSB0cnVlOwogICAgfQogIH0KCiAgZnVuY3Rpb24gbG9hZElycmVndWxhcihydWxlcywgaXJyZWd1bGFyUGFpcnMpIHsKICAgIHZhciBwYWlyID0gdm9pZCAwOwoKICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBpcnJlZ3VsYXJQYWlycy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBwYWlyID0gaXJyZWd1bGFyUGFpcnNbaV07CgogICAgICAvL3BsdXJhbGl6aW5nCiAgICAgIHJ1bGVzLmlycmVndWxhcltwYWlyWzBdLnRvTG93ZXJDYXNlKCldID0gcGFpclsxXTsKICAgICAgcnVsZXMuaXJyZWd1bGFyW3BhaXJbMV0udG9Mb3dlckNhc2UoKV0gPSBwYWlyWzFdOwoKICAgICAgLy9zaW5ndWxhcml6aW5nCiAgICAgIHJ1bGVzLmlycmVndWxhckludmVyc2VbcGFpclsxXS50b0xvd2VyQ2FzZSgpXSA9IHBhaXJbMF07CiAgICAgIHJ1bGVzLmlycmVndWxhckludmVyc2VbcGFpclswXS50b0xvd2VyQ2FzZSgpXSA9IHBhaXJbMF07CiAgICB9CiAgfQoKICAvKioKICAgIEluZmxlY3Rvci5FbWJlciBwcm92aWRlcyBhIG1lY2hhbmlzbSBmb3Igc3VwcGx5aW5nIGluZmxlY3Rpb24gcnVsZXMgZm9yIHlvdXIKICAgIGFwcGxpY2F0aW9uLiBFbWJlciBpbmNsdWRlcyBhIGRlZmF1bHQgc2V0IG9mIGluZmxlY3Rpb24gcnVsZXMsIGFuZCBwcm92aWRlcyBhbgogICAgQVBJIGZvciBwcm92aWRpbmcgYWRkaXRpb25hbCBydWxlcy4KICAKICAgIEV4YW1wbGVzOgogIAogICAgQ3JlYXRpbmcgYW4gaW5mbGVjdG9yIHdpdGggbm8gcnVsZXMuCiAgCiAgICBgYGBqcwogICAgdmFyIGluZmxlY3RvciA9IG5ldyBFbWJlci5JbmZsZWN0b3IoKTsKICAgIGBgYAogIAogICAgQ3JlYXRpbmcgYW4gaW5mbGVjdG9yIHdpdGggdGhlIGRlZmF1bHQgZW1iZXIgcnVsZXNldC4KICAKICAgIGBgYGpzCiAgICB2YXIgaW5mbGVjdG9yID0gbmV3IEVtYmVyLkluZmxlY3RvcihFbWJlci5JbmZsZWN0b3IuZGVmYXVsdFJ1bGVzKTsKICAKICAgIGluZmxlY3Rvci5wbHVyYWxpemUoJ2NvdycpOyAvLz0+ICdraW5lJwogICAgaW5mbGVjdG9yLnNpbmd1bGFyaXplKCdraW5lJyk7IC8vPT4gJ2NvdycKICAgIGBgYAogIAogICAgQ3JlYXRpbmcgYW4gaW5mbGVjdG9yIGFuZCBhZGRpbmcgcnVsZXMgbGF0ZXIuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICB2YXIgaW5mbGVjdG9yID0gRW1iZXIuSW5mbGVjdG9yLmluZmxlY3RvcjsKICAKICAgIGluZmxlY3Rvci5wbHVyYWxpemUoJ2FkdmljZScpOyAvLyA9PiAnYWR2aWNlcycKICAgIGluZmxlY3Rvci51bmNvdW50YWJsZSgnYWR2aWNlJyk7CiAgICBpbmZsZWN0b3IucGx1cmFsaXplKCdhZHZpY2UnKTsgLy8gPT4gJ2FkdmljZScKICAKICAgIGluZmxlY3Rvci5wbHVyYWxpemUoJ2Zvcm11bGEnKTsgLy8gPT4gJ2Zvcm11bGFzJwogICAgaW5mbGVjdG9yLmlycmVndWxhcignZm9ybXVsYScsICdmb3JtdWxhZScpOwogICAgaW5mbGVjdG9yLnBsdXJhbGl6ZSgnZm9ybXVsYScpOyAvLyA9PiAnZm9ybXVsYWUnCiAgCiAgICAvLyB5b3Ugd291bGQgbm90IG5lZWQgdG8gYWRkIHRoZXNlIGFzIHRoZXkgYXJlIHRoZSBkZWZhdWx0IHJ1bGVzCiAgICBpbmZsZWN0b3IucGx1cmFsKC8kLywgJ3MnKTsKICAgIGluZmxlY3Rvci5zaW5ndWxhcigvcyQvaSwgJycpOwogICAgYGBgCiAgCiAgICBDcmVhdGluZyBhbiBpbmZsZWN0b3Igd2l0aCBhIG5vbmRlZmF1bHQgcnVsZXNldC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIHZhciBydWxlcyA9IHsKICAgICAgcGx1cmFsczogIFsKICAgICAgICBbIC8kLywgJ3MnIF0KICAgICAgXSwKICAgICAgc2luZ3VsYXI6IFsKICAgICAgICBbIC9ccyQvLCAnJyBdCiAgICAgIF0sCiAgICAgIGlycmVndWxhclBhaXJzOiBbCiAgICAgICAgWyAnY293JywgJ2tpbmUnIF0KICAgICAgXSwKICAgICAgdW5jb3VudGFibGU6IFsgJ2Zpc2gnIF0KICAgIH07CiAgCiAgICB2YXIgaW5mbGVjdG9yID0gbmV3IEVtYmVyLkluZmxlY3RvcihydWxlcyk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBJbmZsZWN0b3IKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAqLwogIGZ1bmN0aW9uIEluZmxlY3RvcihydWxlU2V0KSB7CiAgICBydWxlU2V0ID0gcnVsZVNldCB8fCB7fTsKICAgIHJ1bGVTZXQudW5jb3VudGFibGUgPSBydWxlU2V0LnVuY291bnRhYmxlIHx8IG1ha2VEaWN0aW9uYXJ5KCk7CiAgICBydWxlU2V0LmlycmVndWxhclBhaXJzID0gcnVsZVNldC5pcnJlZ3VsYXJQYWlycyB8fCBtYWtlRGljdGlvbmFyeSgpOwoKICAgIHZhciBydWxlcyA9IHRoaXMucnVsZXMgPSB7CiAgICAgIHBsdXJhbHM6IHJ1bGVTZXQucGx1cmFscyB8fCBbXSwKICAgICAgc2luZ3VsYXI6IHJ1bGVTZXQuc2luZ3VsYXIgfHwgW10sCiAgICAgIGlycmVndWxhcjogbWFrZURpY3Rpb25hcnkoKSwKICAgICAgaXJyZWd1bGFySW52ZXJzZTogbWFrZURpY3Rpb25hcnkoKSwKICAgICAgdW5jb3VudGFibGU6IG1ha2VEaWN0aW9uYXJ5KCkKICAgIH07CgogICAgbG9hZFVuY291bnRhYmxlKHJ1bGVzLCBydWxlU2V0LnVuY291bnRhYmxlKTsKICAgIGxvYWRJcnJlZ3VsYXIocnVsZXMsIHJ1bGVTZXQuaXJyZWd1bGFyUGFpcnMpOwoKICAgIHRoaXMuZW5hYmxlQ2FjaGUoKTsKICB9CgogIGlmICghT2JqZWN0LmNyZWF0ZSAmJiAhT2JqZWN0LmNyZWF0ZShudWxsKS5oYXNPd25Qcm9wZXJ0eSkgewogICAgdGhyb3cgbmV3IEVycm9yKCJUaGlzIGJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBPYmplY3QuY3JlYXRlKG51bGwpLCBwbGVhc2UgcG9seWZpbCB3aXRoIGVzNS1zaGFtOiBodHRwOi8vZ2l0LmlvL3lCVTJyZyIpOwogIH0KCiAgZnVuY3Rpb24gbWFrZURpY3Rpb25hcnkoKSB7CiAgICB2YXIgY2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgY2FjaGVbJ19kaWN0J10gPSBudWxsOwogICAgZGVsZXRlIGNhY2hlWydfZGljdCddOwogICAgcmV0dXJuIGNhY2hlOwogIH0KCiAgSW5mbGVjdG9yLnByb3RvdHlwZSA9IHsKICAgIGVuYWJsZUNhY2hlOiBmdW5jdGlvbiBlbmFibGVDYWNoZSgpIHsKICAgICAgdGhpcy5wdXJnZUNhY2hlKCk7CgogICAgICB0aGlzLnNpbmd1bGFyaXplID0gZnVuY3Rpb24gKHdvcmQpIHsKICAgICAgICB0aGlzLl9jYWNoZVVzZWQgPSB0cnVlOwogICAgICAgIHJldHVybiB0aGlzLl9zQ2FjaGVbd29yZF0gfHwgKHRoaXMuX3NDYWNoZVt3b3JkXSA9IHRoaXMuX3Npbmd1bGFyaXplKHdvcmQpKTsKICAgICAgfTsKCiAgICAgIHRoaXMucGx1cmFsaXplID0gZnVuY3Rpb24gKG51bWJlck9yV29yZCwgd29yZCkgewogICAgICAgIHZhciBvcHRpb25zID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiB7fTsKCiAgICAgICAgdGhpcy5fY2FjaGVVc2VkID0gdHJ1ZTsKICAgICAgICB2YXIgY2FjaGVLZXkgPSBbbnVtYmVyT3JXb3JkLCB3b3JkLCBvcHRpb25zLndpdGhvdXRDb3VudF07CiAgICAgICAgcmV0dXJuIHRoaXMuX3BDYWNoZVtjYWNoZUtleV0gfHwgKHRoaXMuX3BDYWNoZVtjYWNoZUtleV0gPSB0aGlzLl9wbHVyYWxpemUobnVtYmVyT3JXb3JkLCB3b3JkLCBvcHRpb25zKSk7CiAgICAgIH07CiAgICB9LAogICAgcHVyZ2VDYWNoZTogZnVuY3Rpb24gcHVyZ2VDYWNoZSgpIHsKICAgICAgdGhpcy5fY2FjaGVVc2VkID0gZmFsc2U7CiAgICAgIHRoaXMuX3NDYWNoZSA9IG1ha2VEaWN0aW9uYXJ5KCk7CiAgICAgIHRoaXMuX3BDYWNoZSA9IG1ha2VEaWN0aW9uYXJ5KCk7CiAgICB9LAogICAgZGlzYWJsZUNhY2hlOiBmdW5jdGlvbiBkaXNhYmxlQ2FjaGUoKSB7CiAgICAgIHRoaXMuX3NDYWNoZSA9IG51bGw7CiAgICAgIHRoaXMuX3BDYWNoZSA9IG51bGw7CiAgICAgIHRoaXMuc2luZ3VsYXJpemUgPSBmdW5jdGlvbiAod29yZCkgewogICAgICAgIHJldHVybiB0aGlzLl9zaW5ndWxhcml6ZSh3b3JkKTsKICAgICAgfTsKCiAgICAgIHRoaXMucGx1cmFsaXplID0gZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiB0aGlzLl9wbHVyYWxpemUuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgICAgfTsKICAgIH0sCiAgICBwbHVyYWw6IGZ1bmN0aW9uIHBsdXJhbChyZWdleCwgc3RyaW5nKSB7CiAgICAgIGlmICh0aGlzLl9jYWNoZVVzZWQpIHsKICAgICAgICB0aGlzLnB1cmdlQ2FjaGUoKTsKICAgICAgfQogICAgICB0aGlzLnJ1bGVzLnBsdXJhbHMucHVzaChbcmVnZXgsIHN0cmluZy50b0xvd2VyQ2FzZSgpXSk7CiAgICB9LAogICAgc2luZ3VsYXI6IGZ1bmN0aW9uIHNpbmd1bGFyKHJlZ2V4LCBzdHJpbmcpIHsKICAgICAgaWYgKHRoaXMuX2NhY2hlVXNlZCkgewogICAgICAgIHRoaXMucHVyZ2VDYWNoZSgpOwogICAgICB9CiAgICAgIHRoaXMucnVsZXMuc2luZ3VsYXIucHVzaChbcmVnZXgsIHN0cmluZy50b0xvd2VyQ2FzZSgpXSk7CiAgICB9LAogICAgdW5jb3VudGFibGU6IGZ1bmN0aW9uIHVuY291bnRhYmxlKHN0cmluZykgewogICAgICBpZiAodGhpcy5fY2FjaGVVc2VkKSB7CiAgICAgICAgdGhpcy5wdXJnZUNhY2hlKCk7CiAgICAgIH0KICAgICAgbG9hZFVuY291bnRhYmxlKHRoaXMucnVsZXMsIFtzdHJpbmcudG9Mb3dlckNhc2UoKV0pOwogICAgfSwKICAgIGlycmVndWxhcjogZnVuY3Rpb24gaXJyZWd1bGFyKHNpbmd1bGFyLCBwbHVyYWwpIHsKICAgICAgaWYgKHRoaXMuX2NhY2hlVXNlZCkgewogICAgICAgIHRoaXMucHVyZ2VDYWNoZSgpOwogICAgICB9CiAgICAgIGxvYWRJcnJlZ3VsYXIodGhpcy5ydWxlcywgW1tzaW5ndWxhciwgcGx1cmFsXV0pOwogICAgfSwKICAgIHBsdXJhbGl6ZTogZnVuY3Rpb24gcGx1cmFsaXplKCkgewogICAgICByZXR1cm4gdGhpcy5fcGx1cmFsaXplLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAogICAgX3BsdXJhbGl6ZTogZnVuY3Rpb24gX3BsdXJhbGl6ZSh3b3JkT3JDb3VudCwgd29yZCkgewogICAgICB2YXIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDoge307CgogICAgICBpZiAod29yZCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW5mbGVjdCh3b3JkT3JDb3VudCwgdGhpcy5ydWxlcy5wbHVyYWxzLCB0aGlzLnJ1bGVzLmlycmVndWxhcik7CiAgICAgIH0KCiAgICAgIGlmIChwYXJzZUZsb2F0KHdvcmRPckNvdW50KSAhPT0gMSkgewogICAgICAgIHdvcmQgPSB0aGlzLmluZmxlY3Qod29yZCwgdGhpcy5ydWxlcy5wbHVyYWxzLCB0aGlzLnJ1bGVzLmlycmVndWxhcik7CiAgICAgIH0KCiAgICAgIHJldHVybiBvcHRpb25zLndpdGhvdXRDb3VudCA/IHdvcmQgOiB3b3JkT3JDb3VudCArICcgJyArIHdvcmQ7CiAgICB9LAogICAgc2luZ3VsYXJpemU6IGZ1bmN0aW9uIHNpbmd1bGFyaXplKHdvcmQpIHsKICAgICAgcmV0dXJuIHRoaXMuX3Npbmd1bGFyaXplKHdvcmQpOwogICAgfSwKICAgIF9zaW5ndWxhcml6ZTogZnVuY3Rpb24gX3Npbmd1bGFyaXplKHdvcmQpIHsKICAgICAgcmV0dXJuIHRoaXMuaW5mbGVjdCh3b3JkLCB0aGlzLnJ1bGVzLnNpbmd1bGFyLCB0aGlzLnJ1bGVzLmlycmVndWxhckludmVyc2UpOwogICAgfSwKICAgIGluZmxlY3Q6IGZ1bmN0aW9uIGluZmxlY3Qod29yZCwgdHlwZVJ1bGVzLCBpcnJlZ3VsYXIpIHsKICAgICAgdmFyIGluZmxlY3Rpb24gPSB2b2lkIDAsCiAgICAgICAgICBzdWJzdGl0dXRpb24gPSB2b2lkIDAsCiAgICAgICAgICByZXN1bHQgPSB2b2lkIDAsCiAgICAgICAgICBsb3dlcmNhc2UgPSB2b2lkIDAsCiAgICAgICAgICB3b3JkU3BsaXQgPSB2b2lkIDAsCiAgICAgICAgICBsYXN0V29yZCA9IHZvaWQgMCwKICAgICAgICAgIGlzQmxhbmsgPSB2b2lkIDAsCiAgICAgICAgICBpc0NhbWVsaXplZCA9IHZvaWQgMCwKICAgICAgICAgIHJ1bGUgPSB2b2lkIDAsCiAgICAgICAgICBpc1VuY291bnRhYmxlID0gdm9pZCAwOwoKICAgICAgaXNCbGFuayA9ICF3b3JkIHx8IEJMQU5LX1JFR0VYLnRlc3Qod29yZCk7CiAgICAgIGlzQ2FtZWxpemVkID0gQ0FNRUxJWkVEX1JFR0VYLnRlc3Qod29yZCk7CgogICAgICBpZiAoaXNCbGFuaykgewogICAgICAgIHJldHVybiB3b3JkOwogICAgICB9CgogICAgICBsb3dlcmNhc2UgPSB3b3JkLnRvTG93ZXJDYXNlKCk7CiAgICAgIHdvcmRTcGxpdCA9IExBU1RfV09SRF9EQVNIRURfUkVHRVguZXhlYyh3b3JkKSB8fCBMQVNUX1dPUkRfQ0FNRUxJWkVEX1JFR0VYLmV4ZWMod29yZCk7CgogICAgICBpZiAod29yZFNwbGl0KSB7CiAgICAgICAgbGFzdFdvcmQgPSB3b3JkU3BsaXRbMl0udG9Mb3dlckNhc2UoKTsKICAgICAgfQoKICAgICAgaXNVbmNvdW50YWJsZSA9IHRoaXMucnVsZXMudW5jb3VudGFibGVbbG93ZXJjYXNlXSB8fCB0aGlzLnJ1bGVzLnVuY291bnRhYmxlW2xhc3RXb3JkXTsKCiAgICAgIGlmIChpc1VuY291bnRhYmxlKSB7CiAgICAgICAgcmV0dXJuIHdvcmQ7CiAgICAgIH0KCiAgICAgIGZvciAocnVsZSBpbiBpcnJlZ3VsYXIpIHsKICAgICAgICBpZiAobG93ZXJjYXNlLm1hdGNoKHJ1bGUgKyAiJCIpKSB7CiAgICAgICAgICBzdWJzdGl0dXRpb24gPSBpcnJlZ3VsYXJbcnVsZV07CgogICAgICAgICAgaWYgKGlzQ2FtZWxpemVkICYmIGlycmVndWxhcltsYXN0V29yZF0pIHsKICAgICAgICAgICAgc3Vic3RpdHV0aW9uID0gRW1iZXIuU3RyaW5nLmNhcGl0YWxpemUoc3Vic3RpdHV0aW9uKTsKICAgICAgICAgICAgcnVsZSA9IEVtYmVyLlN0cmluZy5jYXBpdGFsaXplKHJ1bGUpOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiB3b3JkLnJlcGxhY2UobmV3IFJlZ0V4cChydWxlLCAnaScpLCBzdWJzdGl0dXRpb24pOwogICAgICAgIH0KICAgICAgfQoKICAgICAgZm9yICh2YXIgaSA9IHR5cGVSdWxlcy5sZW5ndGgsIG1pbiA9IDA7IGkgPiBtaW47IGktLSkgewogICAgICAgIGluZmxlY3Rpb24gPSB0eXBlUnVsZXNbaSAtIDFdOwogICAgICAgIHJ1bGUgPSBpbmZsZWN0aW9uWzBdOwoKICAgICAgICBpZiAocnVsZS50ZXN0KHdvcmQpKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGluZmxlY3Rpb24gPSBpbmZsZWN0aW9uIHx8IFtdOwoKICAgICAgcnVsZSA9IGluZmxlY3Rpb25bMF07CiAgICAgIHN1YnN0aXR1dGlvbiA9IGluZmxlY3Rpb25bMV07CgogICAgICByZXN1bHQgPSB3b3JkLnJlcGxhY2UocnVsZSwgc3Vic3RpdHV0aW9uKTsKCiAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9CiAgfTsKCiAgZXhwb3J0cy5kZWZhdWx0ID0gSW5mbGVjdG9yOwp9KTsKO2RlZmluZSgnZW1iZXItaW5mbGVjdG9yL2xpYi9zeXN0ZW0vc3RyaW5nJywgWydleHBvcnRzJywgJ2VtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtL2luZmxlY3RvciddLCBmdW5jdGlvbiAoZXhwb3J0cywgX2luZmxlY3RvcikgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLnNpbmd1bGFyaXplID0gZXhwb3J0cy5wbHVyYWxpemUgPSB1bmRlZmluZWQ7CgoKICBmdW5jdGlvbiBwbHVyYWxpemUoKSB7CiAgICB2YXIgX0luZmxlY3RvciRpbmZsZWN0b3I7CgogICAgcmV0dXJuIChfSW5mbGVjdG9yJGluZmxlY3RvciA9IF9pbmZsZWN0b3IuZGVmYXVsdC5pbmZsZWN0b3IpLnBsdXJhbGl6ZS5hcHBseShfSW5mbGVjdG9yJGluZmxlY3RvciwgYXJndW1lbnRzKTsKICB9CgogIGZ1bmN0aW9uIHNpbmd1bGFyaXplKHdvcmQpIHsKICAgIHJldHVybiBfaW5mbGVjdG9yLmRlZmF1bHQuaW5mbGVjdG9yLnNpbmd1bGFyaXplKHdvcmQpOwogIH0KCiAgZXhwb3J0cy5wbHVyYWxpemUgPSBwbHVyYWxpemU7CiAgZXhwb3J0cy5zaW5ndWxhcml6ZSA9IHNpbmd1bGFyaXplOwp9KTsKO2RlZmluZSgnZW1iZXItaW5mbGVjdG9yL2xpYi91dGlscy9tYWtlLWhlbHBlcicsIFsnZXhwb3J0cyddLCBmdW5jdGlvbiAoZXhwb3J0cykgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLmRlZmF1bHQgPSBtYWtlSGVscGVyOwogIGZ1bmN0aW9uIG1ha2VIZWxwZXIoaGVscGVyRnVuY3Rpb24pIHsKICAgIGlmIChFbWJlci5IZWxwZXIpIHsKICAgICAgcmV0dXJuIEVtYmVyLkhlbHBlci5oZWxwZXIoaGVscGVyRnVuY3Rpb24pOwogICAgfQogICAgaWYgKEVtYmVyLkhUTUxCYXJzKSB7CiAgICAgIHJldHVybiBFbWJlci5IVE1MQmFycy5tYWtlQm91bmRIZWxwZXIoaGVscGVyRnVuY3Rpb24pOwogICAgfQogICAgcmV0dXJuIEVtYmVyLkhhbmRsZWJhcnMubWFrZUJvdW5kSGVscGVyKGhlbHBlckZ1bmN0aW9uKTsKICB9Cn0pOwo7ZGVmaW5lKCJlbWJlci1sb2FkLWluaXRpYWxpemVycy9pbmRleCIsIFsiZXhwb3J0cyIsICJyZXF1aXJlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3JlcXVpcmUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSBsb2FkSW5pdGlhbGl6ZXJzOwoKICBmdW5jdGlvbiByZXNvbHZlSW5pdGlhbGl6ZXIobW9kdWxlTmFtZSkgewogICAgdmFyIG1vZHVsZSA9ICgwLCBfcmVxdWlyZS5kZWZhdWx0KShtb2R1bGVOYW1lLCBudWxsLCBudWxsLCB0cnVlKTsKCiAgICBpZiAoIW1vZHVsZSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IobW9kdWxlTmFtZSArICcgbXVzdCBleHBvcnQgYW4gaW5pdGlhbGl6ZXIuJyk7CiAgICB9CgogICAgdmFyIGluaXRpYWxpemVyID0gbW9kdWxlWydkZWZhdWx0J107CgogICAgaWYgKCFpbml0aWFsaXplci5uYW1lKSB7CiAgICAgIGluaXRpYWxpemVyLm5hbWUgPSBtb2R1bGVOYW1lLnNsaWNlKG1vZHVsZU5hbWUubGFzdEluZGV4T2YoJy8nKSArIDEpOwogICAgfQoKICAgIHJldHVybiBpbml0aWFsaXplcjsKICB9CgogIGZ1bmN0aW9uIHJlZ2lzdGVySW5pdGlhbGl6ZXJzKGFwcCwgbW9kdWxlTmFtZXMpIHsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW9kdWxlTmFtZXMubGVuZ3RoOyBpKyspIHsKICAgICAgYXBwLmluaXRpYWxpemVyKHJlc29sdmVJbml0aWFsaXplcihtb2R1bGVOYW1lc1tpXSkpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gcmVnaXN0ZXJJbnN0YW5jZUluaXRpYWxpemVycyhhcHAsIG1vZHVsZU5hbWVzKSB7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vZHVsZU5hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgIGFwcC5pbnN0YW5jZUluaXRpYWxpemVyKHJlc29sdmVJbml0aWFsaXplcihtb2R1bGVOYW1lc1tpXSkpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gX2VuZHNXaXRoKHN0ciwgc3VmZml4KSB7CiAgICByZXR1cm4gc3RyLmluZGV4T2Yoc3VmZml4LCBzdHIubGVuZ3RoIC0gc3VmZml4Lmxlbmd0aCkgIT09IC0xOwogIH0KICAvKioKICAgKiBDb25maWd1cmUgeW91ciBhcHBsaWNhdGlvbiBhcyBpdCBib290cwogICAqLwoKCiAgZnVuY3Rpb24gbG9hZEluaXRpYWxpemVycyhhcHAsIHByZWZpeCkgewogICAgdmFyIGluaXRpYWxpemVyUHJlZml4ID0gcHJlZml4ICsgJy9pbml0aWFsaXplcnMvJzsKICAgIHZhciBpbnN0YW5jZUluaXRpYWxpemVyUHJlZml4ID0gcHJlZml4ICsgJy9pbnN0YW5jZS1pbml0aWFsaXplcnMvJzsKICAgIHZhciBpbml0aWFsaXplcnMgPSBbXTsKICAgIHZhciBpbnN0YW5jZUluaXRpYWxpemVycyA9IFtdOyAvLyB0aGlzIGlzIDIgcGFzcyBiZWNhdXNlIGdlbmVyYWxseSB0aGUgZmlyc3QgcGFzcyBpcyB0aGUgcHJvYmxlbQogICAgLy8gYW5kIGlzIHJlZHVjZWQsIGFuZCByZXNvbHZlSW5pdGlhbGl6ZXIgaGFzIHBvdGVudGlhbCB0byBkZW9wdAoKICAgIHZhciBtb2R1bGVOYW1lcyA9IE9iamVjdC5rZXlzKHNlbGYucmVxdWlyZWpzLl9lYWtfc2Vlbik7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb2R1bGVOYW1lcy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgbW9kdWxlTmFtZSA9IG1vZHVsZU5hbWVzW2ldOwoKICAgICAgaWYgKG1vZHVsZU5hbWUubGFzdEluZGV4T2YoaW5pdGlhbGl6ZXJQcmVmaXgsIDApID09PSAwKSB7CiAgICAgICAgaWYgKCFfZW5kc1dpdGgobW9kdWxlTmFtZSwgJy10ZXN0JykpIHsKICAgICAgICAgIGluaXRpYWxpemVycy5wdXNoKG1vZHVsZU5hbWUpOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChtb2R1bGVOYW1lLmxhc3RJbmRleE9mKGluc3RhbmNlSW5pdGlhbGl6ZXJQcmVmaXgsIDApID09PSAwKSB7CiAgICAgICAgaWYgKCFfZW5kc1dpdGgobW9kdWxlTmFtZSwgJy10ZXN0JykpIHsKICAgICAgICAgIGluc3RhbmNlSW5pdGlhbGl6ZXJzLnB1c2gobW9kdWxlTmFtZSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgcmVnaXN0ZXJJbml0aWFsaXplcnMoYXBwLCBpbml0aWFsaXplcnMpOwogICAgcmVnaXN0ZXJJbnN0YW5jZUluaXRpYWxpemVycyhhcHAsIGluc3RhbmNlSW5pdGlhbGl6ZXJzKTsKICB9Cn0pOwo7LyoKICogVGhpcyBpcyBhIHN0dWIgZmlsZSwgaXQgbXVzdCBiZSBvbiBkaXNrIGIvYyBiYWJlbC1wbHVnaW4tZGVidWctbWFjcm9zCiAqIGRvZXMgbm90IHN0cmlwIHRoZSBtb2R1bGUgcmVxdWlyZSB3aGVuIHRoZSB0cmFuc3BpbGVkIHZhcmlhYmxlIHVzYWdlIGlzCiAqIHN0cmlwcGVkLgogKi8KZGVmaW5lKCJlbWJlci1yZXNvbHZlci9mZWF0dXJlcyIsIFtdLCBmdW5jdGlvbiAoKSB7CiAgInVzZSBzdHJpY3QiOwp9KTsKO2RlZmluZSgnZW1iZXItcmVzb2x2ZXIvaW5kZXgnLCBbJ2V4cG9ydHMnLCAnZW1iZXItcmVzb2x2ZXIvcmVzb2x2ZXJzL2NsYXNzaWMnXSwgZnVuY3Rpb24gKGV4cG9ydHMsIF9jbGFzc2ljKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnZGVmYXVsdCcsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIF9jbGFzc2ljLmRlZmF1bHQ7CiAgICB9CiAgfSk7Cn0pOwo7ZGVmaW5lKCdlbWJlci1yZXNvbHZlci9yZXNvbHZlcicsIFsnZXhwb3J0cycsICdlbWJlci1yZXNvbHZlci9yZXNvbHZlcnMvY2xhc3NpYyddLCBmdW5jdGlvbiAoZXhwb3J0cywgX2NsYXNzaWMpIHsKICAndXNlIHN0cmljdCc7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdkZWZhdWx0JywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gX2NsYXNzaWMuZGVmYXVsdDsKICAgIH0KICB9KTsKfSk7CjtkZWZpbmUoJ2VtYmVyLXJlc29sdmVyL3Jlc29sdmVycy9jbGFzc2ljL2NvbnRhaW5lci1kZWJ1Zy1hZGFwdGVyJywgWydleHBvcnRzJywgJ2VtYmVyLXJlc29sdmVyL3Jlc29sdmVycy9jbGFzc2ljL2luZGV4J10sIGZ1bmN0aW9uIChleHBvcnRzLCBfaW5kZXgpIHsKICAndXNlIHN0cmljdCc7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CgoKICBmdW5jdGlvbiBnZXRQb2QodHlwZSwga2V5LCBwcmVmaXgpIHsKICAgIHZhciBtYXRjaCA9IGtleS5tYXRjaChuZXcgUmVnRXhwKCdeLz8nICsgcHJlZml4ICsgJy8oLispLycgKyB0eXBlICsgJyQnKSk7CiAgICBpZiAobWF0Y2ggIT09IG51bGwpIHsKICAgICAgcmV0dXJuIG1hdGNoWzFdOwogICAgfQogIH0KCiAgLyoKICAgKiBUaGlzIG1vZHVsZSBkZWZpbmVzIGEgc3ViY2xhc3Mgb2YgRW1iZXIuQ29udGFpbmVyRGVidWdBZGFwdGVyIHRoYXQgYWRkcwogICAqIHN1cHBvcnQgZm9yIHJlc29sdmluZyBmcm9tIG1vZHVsZXMuCiAgICoKICAgKi8KICBleHBvcnRzLmRlZmF1bHQgPSBFbWJlci5Db250YWluZXJEZWJ1Z0FkYXB0ZXIuZXh0ZW5kKHsKICAgIF9tb2R1bGVSZWdpc3RyeTogbnVsbCwKCiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgaWYgKCF0aGlzLl9tb2R1bGVSZWdpc3RyeSkgewogICAgICAgIHRoaXMuX21vZHVsZVJlZ2lzdHJ5ID0gbmV3IF9pbmRleC5Nb2R1bGVSZWdpc3RyeSgpOwogICAgICB9CiAgICB9LAoKCiAgICAvKioKICAgICAgICBUaGUgY29udGFpbmVyIG9mIHRoZSBhcHBsaWNhdGlvbiBiZWluZyBkZWJ1Z2dlZC4KICAgICAgICBUaGlzIHByb3BlcnR5IHdpbGwgYmUgaW5qZWN0ZWQKICAgICAgICBvbiBjcmVhdGlvbi4KICAgICAgICAgQHByb3BlcnR5IGNvbnRhaW5lcgogICAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgICAqLwoKICAgIC8qKgogICAgICAgIFRoZSByZXNvbHZlciBpbnN0YW5jZSBvZiB0aGUgYXBwbGljYXRpb24KICAgICAgICBiZWluZyBkZWJ1Z2dlZC4gVGhpcyBwcm9wZXJ0eSB3aWxsIGJlIGluamVjdGVkCiAgICAgICAgb24gY3JlYXRpb24uCiAgICAgICAgIEBwcm9wZXJ0eSByZXNvbHZlcgogICAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgICAqLwoKICAgIC8qKgogICAgICAgIFJldHVybnMgdHJ1ZSBpZiBpdCBpcyBwb3NzaWJsZSB0byBjYXRhbG9nIGEgbGlzdCBvZiBhdmFpbGFibGUKICAgICAgICBjbGFzc2VzIGluIHRoZSByZXNvbHZlciBmb3IgYSBnaXZlbiB0eXBlLgogICAgICAgICBAbWV0aG9kIGNhbkNhdGFsb2dFbnRyaWVzQnlUeXBlCiAgICAgICAgQHBhcmFtIHtzdHJpbmd9IHR5cGUgVGhlIHR5cGUuIGUuZy4gIm1vZGVsIiwgImNvbnRyb2xsZXIiLCAicm91dGUiCiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gd2hldGhlciBhIGxpc3QgaXMgYXZhaWxhYmxlIGZvciB0aGlzIHR5cGUuCiAgICAgICAgKi8KICAgIGNhbkNhdGFsb2dFbnRyaWVzQnlUeXBlOiBmdW5jdGlvbiBjYW5DYXRhbG9nRW50cmllc0J5VHlwZSh0eXBlKSB7CiAgICAgIGlmICh0eXBlID09PSAnbW9kZWwnKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKCiAgICAvKioKICAgICAgICBSZXR1cm5zIHRoZSBhdmFpbGFibGUgY2xhc3NlcyBhIGdpdmVuIHR5cGUuCiAgICAgICAgIEBtZXRob2QgY2F0YWxvZ0VudHJpZXNCeVR5cGUKICAgICAgICBAcGFyYW0ge3N0cmluZ30gdHlwZSBUaGUgdHlwZS4gZS5nLiAibW9kZWwiLCAiY29udHJvbGxlciIsICJyb3V0ZSIKICAgICAgICBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2YgY2xhc3Nlcy4KICAgICAgICAqLwogICAgY2F0YWxvZ0VudHJpZXNCeVR5cGU6IGZ1bmN0aW9uIGNhdGFsb2dFbnRyaWVzQnlUeXBlKHR5cGUpIHsKICAgICAgdmFyIG1vZHVsZU5hbWVzID0gdGhpcy5fbW9kdWxlUmVnaXN0cnkubW9kdWxlTmFtZXMoKTsKICAgICAgdmFyIHR5cGVzID0gRW1iZXIuQSgpOwoKICAgICAgdmFyIHByZWZpeCA9IHRoaXMubmFtZXNwYWNlLm1vZHVsZVByZWZpeDsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gbW9kdWxlTmFtZXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgdmFyIGtleSA9IG1vZHVsZU5hbWVzW2ldOwoKICAgICAgICBpZiAoa2V5LmluZGV4T2YodHlwZSkgIT09IC0xKSB7CiAgICAgICAgICAvLyBDaGVjayBpZiBpdCdzIGEgcG9kIG1vZHVsZQogICAgICAgICAgdmFyIG5hbWUgPSBnZXRQb2QodHlwZSwga2V5LCB0aGlzLm5hbWVzcGFjZS5wb2RNb2R1bGVQcmVmaXggfHwgcHJlZml4KTsKICAgICAgICAgIGlmICghbmFtZSkgewogICAgICAgICAgICAvLyBOb3QgcG9kCiAgICAgICAgICAgIG5hbWUgPSBrZXkuc3BsaXQodHlwZSArICdzLycpLnBvcCgpOwoKICAgICAgICAgICAgLy8gU3VwcG9ydCBmb3IgZGlmZmVyZW50IHByZWZpeCAoc3VjaCBhcyBlbWJlci1jbGkgYWRkb25zKS4KICAgICAgICAgICAgLy8gVW5jb21tZW50IHRoZSBjb2RlIGJlbG93IHdoZW4KICAgICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2VtYmVyLWNsaS9lbWJlci1yZXNvbHZlci9wdWxsLzgwIGlzIG1lcmdlZC4KCiAgICAgICAgICAgIC8vbGV0IG1hdGNoID0ga2V5Lm1hdGNoKCdeLz8oLispLycgKyB0eXBlKTsKICAgICAgICAgICAgLy9pZiAobWF0Y2ggJiYgbWF0Y2hbMV0gIT09IHByZWZpeCkgewogICAgICAgICAgICAvLyBEaWZmZXJlbnQgcHJlZml4IHN1Y2ggYXMgYW4gYWRkb24KICAgICAgICAgICAgLy9uYW1lID0gbWF0Y2hbMV0gKyAnQCcgKyBuYW1lOwogICAgICAgICAgICAvL30KICAgICAgICAgIH0KICAgICAgICAgIHR5cGVzLmFkZE9iamVjdChuYW1lKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHR5cGVzOwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgnZW1iZXItcmVzb2x2ZXIvcmVzb2x2ZXJzL2NsYXNzaWMvaW5kZXgnLCBbJ2V4cG9ydHMnLCAnZW1iZXItcmVzb2x2ZXIvdXRpbHMvY2xhc3MtZmFjdG9yeScsICdlbWJlci1yZXNvbHZlci91dGlscy9tYWtlLWRpY3Rpb25hcnknXSwgZnVuY3Rpb24gKGV4cG9ydHMsIF9jbGFzc0ZhY3RvcnksIF9tYWtlRGljdGlvbmFyeSkgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLk1vZHVsZVJlZ2lzdHJ5ID0gdW5kZWZpbmVkOwoKICBmdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7CiAgICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgewogICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24iKTsKICAgIH0KICB9CgogIGlmICh0eXBlb2YgcmVxdWlyZWpzLmVudHJpZXMgPT09ICd1bmRlZmluZWQnKSB7CiAgICByZXF1aXJlanMuZW50cmllcyA9IHJlcXVpcmVqcy5fZWFrX3NlZW47CiAgfQoKICB2YXIgTW9kdWxlUmVnaXN0cnkgPSBleHBvcnRzLk1vZHVsZVJlZ2lzdHJ5ID0gZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gTW9kdWxlUmVnaXN0cnkoZW50cmllcykgewogICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgTW9kdWxlUmVnaXN0cnkpOwoKICAgICAgdGhpcy5fZW50cmllcyA9IGVudHJpZXMgfHwgcmVxdWlyZWpzLmVudHJpZXM7CiAgICB9CgogICAgTW9kdWxlUmVnaXN0cnkucHJvdG90eXBlLm1vZHVsZU5hbWVzID0gZnVuY3Rpb24gbW9kdWxlTmFtZXMoKSB7CiAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl9lbnRyaWVzKTsKICAgIH07CgogICAgTW9kdWxlUmVnaXN0cnkucHJvdG90eXBlLmhhcyA9IGZ1bmN0aW9uIGhhcyhtb2R1bGVOYW1lKSB7CiAgICAgIHJldHVybiBtb2R1bGVOYW1lIGluIHRoaXMuX2VudHJpZXM7CiAgICB9OwoKICAgIE1vZHVsZVJlZ2lzdHJ5LnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiBnZXQobW9kdWxlTmFtZSkgewogICAgICByZXR1cm4gcmVxdWlyZShtb2R1bGVOYW1lKTsKICAgIH07CgogICAgcmV0dXJuIE1vZHVsZVJlZ2lzdHJ5OwogIH0oKTsKCiAgLyoqCiAgICogVGhpcyBtb2R1bGUgZGVmaW5lcyBhIHN1YmNsYXNzIG9mIEVtYmVyLkRlZmF1bHRSZXNvbHZlciB0aGF0IGFkZHMgdHdvCiAgICogaW1wb3J0YW50IGZlYXR1cmVzOgogICAqCiAgICogIDEpIFRoZSByZXNvbHZlciBtYWtlcyB0aGUgY29udGFpbmVyIGF3YXJlIG9mIGVzNiBtb2R1bGVzIHZpYSB0aGUgQU1ECiAgICogICAgIG91dHB1dC4gVGhlIGxvYWRlcidzIF9tb2R1bGVFbnRyaWVzIGlzIGNvbnN1bHRlZCBzbyB0aGF0IGNsYXNzZXMgY2FuIGJlCiAgICogICAgIHJlc29sdmVkIGRpcmVjdGx5IHZpYSB0aGUgbW9kdWxlIGxvYWRlciwgd2l0aG91dCBuZWVkaW5nIGEgbWFudWFsCiAgICogICAgIGBpbXBvcnRgLgogICAqICAyKSBpcyBhYmxlIHRvIHByb3ZpZGUgaW5qZWN0aW9ucyB0byBjbGFzc2VzIHRoYXQgaW1wbGVtZW50IGBleHRlbmRgCiAgICogICAgIChhcyBpcyB0eXBpY2FsIHdpdGggRW1iZXIpLgogICAqLwoKICBmdW5jdGlvbiBwYXJzZU5hbWUoZnVsbE5hbWUpIHsKICAgIGlmIChmdWxsTmFtZS5wYXJzZWROYW1lID09PSB0cnVlKSB7CiAgICAgIHJldHVybiBmdWxsTmFtZTsKICAgIH0KCiAgICB2YXIgcHJlZml4ID0gdm9pZCAwLAogICAgICAgIHR5cGUgPSB2b2lkIDAsCiAgICAgICAgbmFtZSA9IHZvaWQgMDsKICAgIHZhciBmdWxsTmFtZVBhcnRzID0gZnVsbE5hbWUuc3BsaXQoJ0AnKTsKCiAgICBpZiAoZnVsbE5hbWVQYXJ0cy5sZW5ndGggPT09IDIpIHsKICAgICAgdmFyIHByZWZpeFBhcnRzID0gZnVsbE5hbWVQYXJ0c1swXS5zcGxpdCgnOicpOwoKICAgICAgaWYgKHByZWZpeFBhcnRzLmxlbmd0aCA9PT0gMikgewogICAgICAgIGlmIChwcmVmaXhQYXJ0c1sxXS5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHR5cGUgPSBwcmVmaXhQYXJ0c1swXTsKICAgICAgICAgIG5hbWUgPSAnQCcgKyBmdWxsTmFtZVBhcnRzWzFdOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBwcmVmaXggPSBwcmVmaXhQYXJ0c1sxXTsKICAgICAgICAgIHR5cGUgPSBwcmVmaXhQYXJ0c1swXTsKICAgICAgICAgIG5hbWUgPSBmdWxsTmFtZVBhcnRzWzFdOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgbmFtZVBhcnRzID0gZnVsbE5hbWVQYXJ0c1sxXS5zcGxpdCgnOicpOwoKICAgICAgICBwcmVmaXggPSBmdWxsTmFtZVBhcnRzWzBdOwogICAgICAgIHR5cGUgPSBuYW1lUGFydHNbMF07CiAgICAgICAgbmFtZSA9IG5hbWVQYXJ0c1sxXTsKICAgICAgfQoKICAgICAgaWYgKHR5cGUgPT09ICd0ZW1wbGF0ZScgJiYgcHJlZml4Lmxhc3RJbmRleE9mKCdjb21wb25lbnRzLycsIDApID09PSAwKSB7CiAgICAgICAgbmFtZSA9ICdjb21wb25lbnRzLycgKyBuYW1lOwogICAgICAgIHByZWZpeCA9IHByZWZpeC5zbGljZSgxMSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGZ1bGxOYW1lUGFydHMgPSBmdWxsTmFtZS5zcGxpdCgnOicpOwogICAgICB0eXBlID0gZnVsbE5hbWVQYXJ0c1swXTsKICAgICAgbmFtZSA9IGZ1bGxOYW1lUGFydHNbMV07CiAgICB9CgogICAgdmFyIGZ1bGxOYW1lV2l0aG91dFR5cGUgPSBuYW1lOwogICAgdmFyIG5hbWVzcGFjZSA9IEVtYmVyLmdldCh0aGlzLCAnbmFtZXNwYWNlJyk7CiAgICB2YXIgcm9vdCA9IG5hbWVzcGFjZTsKCiAgICByZXR1cm4gewogICAgICBwYXJzZWROYW1lOiB0cnVlLAogICAgICBmdWxsTmFtZTogZnVsbE5hbWUsCiAgICAgIHByZWZpeDogcHJlZml4IHx8IHRoaXMucHJlZml4KHsgdHlwZTogdHlwZSB9KSwKICAgICAgdHlwZTogdHlwZSwKICAgICAgZnVsbE5hbWVXaXRob3V0VHlwZTogZnVsbE5hbWVXaXRob3V0VHlwZSwKICAgICAgbmFtZTogbmFtZSwKICAgICAgcm9vdDogcm9vdCwKICAgICAgcmVzb2x2ZU1ldGhvZE5hbWU6ICJyZXNvbHZlIiArIEVtYmVyLlN0cmluZy5jbGFzc2lmeSh0eXBlKQogICAgfTsKICB9CgogIGZ1bmN0aW9uIHJlc29sdmVPdGhlcihwYXJzZWROYW1lKSB7CiAgICAoZmFsc2UgJiYgISh0aGlzLm5hbWVzcGFjZS5tb2R1bGVQcmVmaXgpICYmIEVtYmVyLmFzc2VydCgnYG1vZHVsZVByZWZpeGAgbXVzdCBiZSBkZWZpbmVkJywgdGhpcy5uYW1lc3BhY2UubW9kdWxlUHJlZml4KSk7CgoKICAgIHZhciBub3JtYWxpemVkTW9kdWxlTmFtZSA9IHRoaXMuZmluZE1vZHVsZU5hbWUocGFyc2VkTmFtZSk7CgogICAgaWYgKG5vcm1hbGl6ZWRNb2R1bGVOYW1lKSB7CiAgICAgIHZhciBkZWZhdWx0RXhwb3J0ID0gdGhpcy5fZXh0cmFjdERlZmF1bHRFeHBvcnQobm9ybWFsaXplZE1vZHVsZU5hbWUsIHBhcnNlZE5hbWUpOwoKICAgICAgaWYgKGRlZmF1bHRFeHBvcnQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcignIEV4cGVjdGVkIHRvIGZpbmQ6IFwnJyArIHBhcnNlZE5hbWUuZnVsbE5hbWUgKyAnXCcgd2l0aGluIFwnJyArIG5vcm1hbGl6ZWRNb2R1bGVOYW1lICsgJ1wnIGJ1dCBnb3QgXCd1bmRlZmluZWRcJy4gRGlkIHlvdSBmb3JnZXQgdG8gXCdleHBvcnQgZGVmYXVsdFwnIHdpdGhpbiBcJycgKyBub3JtYWxpemVkTW9kdWxlTmFtZSArICdcJz8nKTsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuc2hvdWxkV3JhcEluQ2xhc3NGYWN0b3J5KGRlZmF1bHRFeHBvcnQsIHBhcnNlZE5hbWUpKSB7CiAgICAgICAgZGVmYXVsdEV4cG9ydCA9ICgwLCBfY2xhc3NGYWN0b3J5LmRlZmF1bHQpKGRlZmF1bHRFeHBvcnQpOwogICAgICB9CgogICAgICByZXR1cm4gZGVmYXVsdEV4cG9ydDsKICAgIH0KICB9CgogIHZhciBSZXNvbHZlciA9IEVtYmVyLk9iamVjdC5leHRlbmQoewogICAgcmVzb2x2ZU90aGVyOiByZXNvbHZlT3RoZXIsCiAgICBwYXJzZU5hbWU6IHBhcnNlTmFtZSwKICAgIHBsdXJhbGl6ZWRUeXBlczogbnVsbCwKICAgIG1vZHVsZVJlZ2lzdHJ5OiBudWxsLAoKICAgIG1ha2VUb1N0cmluZzogZnVuY3Rpb24gbWFrZVRvU3RyaW5nKGZhY3RvcnksIGZ1bGxOYW1lKSB7CiAgICAgIHJldHVybiAnJyArIHRoaXMubmFtZXNwYWNlLm1vZHVsZVByZWZpeCArICdAJyArIGZ1bGxOYW1lICsgJzonOwogICAgfSwKICAgIHNob3VsZFdyYXBJbkNsYXNzRmFjdG9yeTogZnVuY3Rpb24gc2hvdWxkV3JhcEluQ2xhc3NGYWN0b3J5KCkgLyogbW9kdWxlLCBwYXJzZWROYW1lICovewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9LAogICAgaW5pdDogZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgdGhpcy5fc3VwZXIoKTsKICAgICAgdGhpcy5tb2R1bGVCYXNlZFJlc29sdmVyID0gdHJ1ZTsKCiAgICAgIGlmICghdGhpcy5fbW9kdWxlUmVnaXN0cnkpIHsKICAgICAgICB0aGlzLl9tb2R1bGVSZWdpc3RyeSA9IG5ldyBNb2R1bGVSZWdpc3RyeSgpOwogICAgICB9CgogICAgICB0aGlzLl9ub3JtYWxpemVDYWNoZSA9ICgwLCBfbWFrZURpY3Rpb25hcnkuZGVmYXVsdCkoKTsKCiAgICAgIHRoaXMucGx1cmFsaXplZFR5cGVzID0gdGhpcy5wbHVyYWxpemVkVHlwZXMgfHwgKDAsIF9tYWtlRGljdGlvbmFyeS5kZWZhdWx0KSgpOwoKICAgICAgaWYgKCF0aGlzLnBsdXJhbGl6ZWRUeXBlcy5jb25maWcpIHsKICAgICAgICB0aGlzLnBsdXJhbGl6ZWRUeXBlcy5jb25maWcgPSAnY29uZmlnJzsKICAgICAgfQogICAgICB0aGlzLl9kZXByZWNhdGVkUG9kTW9kdWxlUHJlZml4ID0gZmFsc2U7CiAgICB9LAogICAgbm9ybWFsaXplOiBmdW5jdGlvbiBub3JtYWxpemUoZnVsbE5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXMuX25vcm1hbGl6ZUNhY2hlW2Z1bGxOYW1lXSB8fCAodGhpcy5fbm9ybWFsaXplQ2FjaGVbZnVsbE5hbWVdID0gdGhpcy5fbm9ybWFsaXplKGZ1bGxOYW1lKSk7CiAgICB9LAogICAgcmVzb2x2ZTogZnVuY3Rpb24gcmVzb2x2ZShmdWxsTmFtZSkgewogICAgICB2YXIgcGFyc2VkTmFtZSA9IHRoaXMucGFyc2VOYW1lKGZ1bGxOYW1lKTsKICAgICAgdmFyIHJlc29sdmVNZXRob2ROYW1lID0gcGFyc2VkTmFtZS5yZXNvbHZlTWV0aG9kTmFtZTsKICAgICAgdmFyIHJlc29sdmVkID0gdm9pZCAwOwoKICAgICAgaWYgKHR5cGVvZiB0aGlzW3Jlc29sdmVNZXRob2ROYW1lXSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIHJlc29sdmVkID0gdGhpc1tyZXNvbHZlTWV0aG9kTmFtZV0ocGFyc2VkTmFtZSk7CiAgICAgIH0KCiAgICAgIGlmIChyZXNvbHZlZCA9PSBudWxsKSB7CiAgICAgICAgcmVzb2x2ZWQgPSB0aGlzLnJlc29sdmVPdGhlcihwYXJzZWROYW1lKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlc29sdmVkOwogICAgfSwKICAgIF9ub3JtYWxpemU6IGZ1bmN0aW9uIF9ub3JtYWxpemUoZnVsbE5hbWUpIHsKICAgICAgLy8gQSkgQ29udmVydCB1bmRlcnNjb3JlcyB0byBkYXNoZXMKICAgICAgLy8gQikgQ29udmVydCBjYW1lbENhc2UgdG8gZGFzaC1jYXNlLCBleGNlcHQgZm9yIGNvbXBvbmVudHMgKHRoZWlyCiAgICAgIC8vICAgIHRlbXBsYXRlcykgYW5kIGhlbHBlcnMgd2hlcmUgd2Ugd2FudCB0byBhdm9pZCBzaGFkb3dpbmcgY2FtZWxDYXNlCiAgICAgIC8vICAgIGV4cHJlc3Npb25zCiAgICAgIC8vIEMpIHJlcGxhY2UgYC5gIHdpdGggYC9gIGluIG9yZGVyIHRvIG1ha2UgbmVzdGVkIGNvbnRyb2xsZXJzIHdvcmsgaW4gdGhlIGZvbGxvd2luZyBjYXNlcwogICAgICAvLyAgICAgIDEuIGBuZWVkczogWydwb3N0cy9wb3N0J11gCiAgICAgIC8vICAgICAgMi4gYHt7cmVuZGVyICJwb3N0cy9wb3N0In19YAogICAgICAvLyAgICAgIDMuIGB0aGlzLnJlbmRlcigncG9zdHMvcG9zdCcpYCBmcm9tIFJvdXRlCgogICAgICB2YXIgc3BsaXQgPSBmdWxsTmFtZS5zcGxpdCgnOicpOwogICAgICBpZiAoc3BsaXQubGVuZ3RoID4gMSkgewogICAgICAgIHZhciB0eXBlID0gc3BsaXRbMF07CgogICAgICAgIGlmICh0eXBlID09PSAnY29tcG9uZW50JyB8fCB0eXBlID09PSAnaGVscGVyJyB8fCB0eXBlID09PSAndGVtcGxhdGUnICYmIHNwbGl0WzFdLmluZGV4T2YoJ2NvbXBvbmVudHMvJykgPT09IDApIHsKICAgICAgICAgIHJldHVybiB0eXBlICsgJzonICsgc3BsaXRbMV0ucmVwbGFjZSgvXy9nLCAnLScpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdHlwZSArICc6JyArIEVtYmVyLlN0cmluZy5kYXNoZXJpemUoc3BsaXRbMV0ucmVwbGFjZSgvXC4vZywgJy8nKSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBmdWxsTmFtZTsKICAgICAgfQogICAgfSwKICAgIHBsdXJhbGl6ZTogZnVuY3Rpb24gcGx1cmFsaXplKHR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMucGx1cmFsaXplZFR5cGVzW3R5cGVdIHx8ICh0aGlzLnBsdXJhbGl6ZWRUeXBlc1t0eXBlXSA9IHR5cGUgKyAncycpOwogICAgfSwKICAgIHBvZEJhc2VkTG9va3VwV2l0aFByZWZpeDogZnVuY3Rpb24gcG9kQmFzZWRMb29rdXBXaXRoUHJlZml4KHBvZFByZWZpeCwgcGFyc2VkTmFtZSkgewogICAgICB2YXIgZnVsbE5hbWVXaXRob3V0VHlwZSA9IHBhcnNlZE5hbWUuZnVsbE5hbWVXaXRob3V0VHlwZTsKCiAgICAgIGlmIChwYXJzZWROYW1lLnR5cGUgPT09ICd0ZW1wbGF0ZScpIHsKICAgICAgICBmdWxsTmFtZVdpdGhvdXRUeXBlID0gZnVsbE5hbWVXaXRob3V0VHlwZS5yZXBsYWNlKC9eY29tcG9uZW50c1wvLywgJycpOwogICAgICB9CgogICAgICByZXR1cm4gcG9kUHJlZml4ICsgJy8nICsgZnVsbE5hbWVXaXRob3V0VHlwZSArICcvJyArIHBhcnNlZE5hbWUudHlwZTsKICAgIH0sCiAgICBwb2RCYXNlZE1vZHVsZU5hbWU6IGZ1bmN0aW9uIHBvZEJhc2VkTW9kdWxlTmFtZShwYXJzZWROYW1lKSB7CiAgICAgIHZhciBwb2RQcmVmaXggPSB0aGlzLm5hbWVzcGFjZS5wb2RNb2R1bGVQcmVmaXggfHwgdGhpcy5uYW1lc3BhY2UubW9kdWxlUHJlZml4OwoKICAgICAgcmV0dXJuIHRoaXMucG9kQmFzZWRMb29rdXBXaXRoUHJlZml4KHBvZFByZWZpeCwgcGFyc2VkTmFtZSk7CiAgICB9LAogICAgcG9kQmFzZWRDb21wb25lbnRzSW5TdWJkaXI6IGZ1bmN0aW9uIHBvZEJhc2VkQ29tcG9uZW50c0luU3ViZGlyKHBhcnNlZE5hbWUpIHsKICAgICAgdmFyIHBvZFByZWZpeCA9IHRoaXMubmFtZXNwYWNlLnBvZE1vZHVsZVByZWZpeCB8fCB0aGlzLm5hbWVzcGFjZS5tb2R1bGVQcmVmaXg7CiAgICAgIHBvZFByZWZpeCA9IHBvZFByZWZpeCArICcvY29tcG9uZW50cyc7CgogICAgICBpZiAocGFyc2VkTmFtZS50eXBlID09PSAnY29tcG9uZW50JyB8fCAvXmNvbXBvbmVudHMvLnRlc3QocGFyc2VkTmFtZS5mdWxsTmFtZVdpdGhvdXRUeXBlKSkgewogICAgICAgIHJldHVybiB0aGlzLnBvZEJhc2VkTG9va3VwV2l0aFByZWZpeChwb2RQcmVmaXgsIHBhcnNlZE5hbWUpOwogICAgICB9CiAgICB9LAogICAgcmVzb2x2ZUVuZ2luZTogZnVuY3Rpb24gcmVzb2x2ZUVuZ2luZShwYXJzZWROYW1lKSB7CiAgICAgIHZhciBlbmdpbmVOYW1lID0gcGFyc2VkTmFtZS5mdWxsTmFtZVdpdGhvdXRUeXBlOwogICAgICB2YXIgZW5naW5lTW9kdWxlID0gZW5naW5lTmFtZSArICcvZW5naW5lJzsKCiAgICAgIGlmICh0aGlzLl9tb2R1bGVSZWdpc3RyeS5oYXMoZW5naW5lTW9kdWxlKSkgewogICAgICAgIHJldHVybiB0aGlzLl9leHRyYWN0RGVmYXVsdEV4cG9ydChlbmdpbmVNb2R1bGUpOwogICAgICB9CiAgICB9LAogICAgcmVzb2x2ZVJvdXRlTWFwOiBmdW5jdGlvbiByZXNvbHZlUm91dGVNYXAocGFyc2VkTmFtZSkgewogICAgICB2YXIgZW5naW5lTmFtZSA9IHBhcnNlZE5hbWUuZnVsbE5hbWVXaXRob3V0VHlwZTsKICAgICAgdmFyIGVuZ2luZVJvdXRlc01vZHVsZSA9IGVuZ2luZU5hbWUgKyAnL3JvdXRlcyc7CgogICAgICBpZiAodGhpcy5fbW9kdWxlUmVnaXN0cnkuaGFzKGVuZ2luZVJvdXRlc01vZHVsZSkpIHsKICAgICAgICB2YXIgcm91dGVNYXAgPSB0aGlzLl9leHRyYWN0RGVmYXVsdEV4cG9ydChlbmdpbmVSb3V0ZXNNb2R1bGUpOwoKICAgICAgICAoZmFsc2UgJiYgIShyb3V0ZU1hcC5pc1JvdXRlTWFwKSAmJiBFbWJlci5hc3NlcnQoJ1RoZSByb3V0ZSBtYXAgZm9yICcgKyBlbmdpbmVOYW1lICsgJyBzaG91bGQgYmUgd3JhcHBlZCBieSBcJ2J1aWxkUm91dGVzXCcgYmVmb3JlIGV4cG9ydGluZy4nLCByb3V0ZU1hcC5pc1JvdXRlTWFwKSk7CgoKICAgICAgICByZXR1cm4gcm91dGVNYXA7CiAgICAgIH0KICAgIH0sCiAgICByZXNvbHZlVGVtcGxhdGU6IGZ1bmN0aW9uIHJlc29sdmVUZW1wbGF0ZShwYXJzZWROYW1lKSB7CiAgICAgIHZhciByZXNvbHZlZCA9IHRoaXMucmVzb2x2ZU90aGVyKHBhcnNlZE5hbWUpOwogICAgICBpZiAocmVzb2x2ZWQgPT0gbnVsbCkgewogICAgICAgIHJlc29sdmVkID0gRW1iZXIuVEVNUExBVEVTW3BhcnNlZE5hbWUuZnVsbE5hbWVXaXRob3V0VHlwZV07CiAgICAgIH0KICAgICAgcmV0dXJuIHJlc29sdmVkOwogICAgfSwKICAgIG1haW5Nb2R1bGVOYW1lOiBmdW5jdGlvbiBtYWluTW9kdWxlTmFtZShwYXJzZWROYW1lKSB7CiAgICAgIGlmIChwYXJzZWROYW1lLmZ1bGxOYW1lV2l0aG91dFR5cGUgPT09ICdtYWluJykgewogICAgICAgIC8vIGlmIHJvdXRlcjptYWluIG9yIGFkYXB0ZXI6bWFpbiBsb29rIGZvciBhIG1vZHVsZSB3aXRoIGp1c3QgdGhlIHR5cGUgZmlyc3QKICAgICAgICByZXR1cm4gcGFyc2VkTmFtZS5wcmVmaXggKyAnLycgKyBwYXJzZWROYW1lLnR5cGU7CiAgICAgIH0KICAgIH0sCiAgICBkZWZhdWx0TW9kdWxlTmFtZTogZnVuY3Rpb24gZGVmYXVsdE1vZHVsZU5hbWUocGFyc2VkTmFtZSkgewogICAgICByZXR1cm4gcGFyc2VkTmFtZS5wcmVmaXggKyAnLycgKyB0aGlzLnBsdXJhbGl6ZShwYXJzZWROYW1lLnR5cGUpICsgJy8nICsgcGFyc2VkTmFtZS5mdWxsTmFtZVdpdGhvdXRUeXBlOwogICAgfSwKICAgIG5lc3RlZENvbG9jYXRpb25Db21wb25lbnRNb2R1bGVOYW1lOiBmdW5jdGlvbiBuZXN0ZWRDb2xvY2F0aW9uQ29tcG9uZW50TW9kdWxlTmFtZShwYXJzZWROYW1lKSB7CiAgICAgIGlmIChwYXJzZWROYW1lLnR5cGUgPT09ICdjb21wb25lbnQnKSB7CiAgICAgICAgcmV0dXJuIHBhcnNlZE5hbWUucHJlZml4ICsgJy8nICsgdGhpcy5wbHVyYWxpemUocGFyc2VkTmFtZS50eXBlKSArICcvJyArIHBhcnNlZE5hbWUuZnVsbE5hbWVXaXRob3V0VHlwZSArICcvaW5kZXgnOwogICAgICB9CiAgICB9LAogICAgcHJlZml4OiBmdW5jdGlvbiBwcmVmaXgocGFyc2VkTmFtZSkgewogICAgICB2YXIgdG1wUHJlZml4ID0gdGhpcy5uYW1lc3BhY2UubW9kdWxlUHJlZml4OwoKICAgICAgaWYgKHRoaXMubmFtZXNwYWNlW3BhcnNlZE5hbWUudHlwZSArICdQcmVmaXgnXSkgewogICAgICAgIHRtcFByZWZpeCA9IHRoaXMubmFtZXNwYWNlW3BhcnNlZE5hbWUudHlwZSArICdQcmVmaXgnXTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRtcFByZWZpeDsKICAgIH0sCgoKICAgIC8qKgogICAgICBBIGxpc3Rpbmcgb2YgZnVuY3Rpb25zIHRvIHRlc3QgZm9yIG1vZHVsZU5hbWUncyBiYXNlZCBvbiB0aGUgcHJvdmlkZWQKICAgICBgcGFyc2VkTmFtZWAuIFRoaXMgYWxsb3dzIGVhc3kgY3VzdG9taXphdGlvbiBvZiBhZGRpdGlvbmFsIG1vZHVsZSBiYXNlZAogICAgIGxvb2t1cCBwYXR0ZXJucy4KICAgICAgQHByb3BlcnR5IG1vZHVsZU5hbWVMb29rdXBQYXR0ZXJucwogICAgIEByZXR1cm5zIHtFbWJlci5BcnJheX0KICAgICAqLwogICAgbW9kdWxlTmFtZUxvb2t1cFBhdHRlcm5zOiBFbWJlci5jb21wdXRlZChmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBbdGhpcy5wb2RCYXNlZE1vZHVsZU5hbWUsIHRoaXMucG9kQmFzZWRDb21wb25lbnRzSW5TdWJkaXIsIHRoaXMubWFpbk1vZHVsZU5hbWUsIHRoaXMuZGVmYXVsdE1vZHVsZU5hbWUsIHRoaXMubmVzdGVkQ29sb2NhdGlvbkNvbXBvbmVudE1vZHVsZU5hbWVdOwogICAgfSkucmVhZE9ubHkoKSwKCiAgICBmaW5kTW9kdWxlTmFtZTogZnVuY3Rpb24gZmluZE1vZHVsZU5hbWUocGFyc2VkTmFtZSwgbG9nZ2luZ0Rpc2FibGVkKSB7CiAgICAgIHZhciBtb2R1bGVOYW1lTG9va3VwUGF0dGVybnMgPSB0aGlzLmdldCgnbW9kdWxlTmFtZUxvb2t1cFBhdHRlcm5zJyk7CiAgICAgIHZhciBtb2R1bGVOYW1lID0gdm9pZCAwOwoKICAgICAgZm9yICh2YXIgaW5kZXggPSAwLCBsZW5ndGggPSBtb2R1bGVOYW1lTG9va3VwUGF0dGVybnMubGVuZ3RoOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykgewogICAgICAgIHZhciBpdGVtID0gbW9kdWxlTmFtZUxvb2t1cFBhdHRlcm5zW2luZGV4XTsKCiAgICAgICAgdmFyIHRtcE1vZHVsZU5hbWUgPSBpdGVtLmNhbGwodGhpcywgcGFyc2VkTmFtZSk7CgogICAgICAgIC8vIGFsbG93IHRyZWF0IGFsbCBkYXNoZWQgYW5kIGFsbCB1bmRlcnNjb3JlZCBhcyB0aGUgc2FtZSB0aGluZwogICAgICAgIC8vIHN1cHBvcnRzIGNvbXBvbmVudHMgd2l0aCBkYXNoZXMgYW5kIG90aGVyIHN0dWZmIHdpdGggdW5kZXJzY29yZXMuCiAgICAgICAgaWYgKHRtcE1vZHVsZU5hbWUpIHsKICAgICAgICAgIHRtcE1vZHVsZU5hbWUgPSB0aGlzLmNob29zZU1vZHVsZU5hbWUodG1wTW9kdWxlTmFtZSwgcGFyc2VkTmFtZSk7CiAgICAgICAgfQoKICAgICAgICBpZiAodG1wTW9kdWxlTmFtZSAmJiB0aGlzLl9tb2R1bGVSZWdpc3RyeS5oYXModG1wTW9kdWxlTmFtZSkpIHsKICAgICAgICAgIG1vZHVsZU5hbWUgPSB0bXBNb2R1bGVOYW1lOwogICAgICAgIH0KCiAgICAgICAgaWYgKCFsb2dnaW5nRGlzYWJsZWQpIHsKICAgICAgICAgIHRoaXMuX2xvZ0xvb2t1cChtb2R1bGVOYW1lLCBwYXJzZWROYW1lLCB0bXBNb2R1bGVOYW1lKTsKICAgICAgICB9CgogICAgICAgIGlmIChtb2R1bGVOYW1lKSB7CiAgICAgICAgICByZXR1cm4gbW9kdWxlTmFtZTsKICAgICAgICB9CiAgICAgIH0KICAgIH0sCiAgICBjaG9vc2VNb2R1bGVOYW1lOiBmdW5jdGlvbiBjaG9vc2VNb2R1bGVOYW1lKG1vZHVsZU5hbWUsIHBhcnNlZE5hbWUpIHsKICAgICAgdmFyIHVuZGVyc2NvcmVkTW9kdWxlTmFtZSA9IEVtYmVyLlN0cmluZy51bmRlcnNjb3JlKG1vZHVsZU5hbWUpOwoKICAgICAgaWYgKG1vZHVsZU5hbWUgIT09IHVuZGVyc2NvcmVkTW9kdWxlTmFtZSAmJiB0aGlzLl9tb2R1bGVSZWdpc3RyeS5oYXMobW9kdWxlTmFtZSkgJiYgdGhpcy5fbW9kdWxlUmVnaXN0cnkuaGFzKHVuZGVyc2NvcmVkTW9kdWxlTmFtZSkpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBbWJpZ3VvdXMgbW9kdWxlIG5hbWVzOiBcJycgKyBtb2R1bGVOYW1lICsgJ1wnIGFuZCBcJycgKyB1bmRlcnNjb3JlZE1vZHVsZU5hbWUgKyAnXCcnKTsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuX21vZHVsZVJlZ2lzdHJ5Lmhhcyhtb2R1bGVOYW1lKSkgewogICAgICAgIHJldHVybiBtb2R1bGVOYW1lOwogICAgICB9IGVsc2UgaWYgKHRoaXMuX21vZHVsZVJlZ2lzdHJ5Lmhhcyh1bmRlcnNjb3JlZE1vZHVsZU5hbWUpKSB7CiAgICAgICAgcmV0dXJuIHVuZGVyc2NvcmVkTW9kdWxlTmFtZTsKICAgICAgfQogICAgICAvLyB3b3JrYXJvdW5kIGZvciBkYXNoZXJpemVkIHBhcnRpYWxzOgogICAgICAvLyBzb21ldGhpbmcvc29tZXRoaW5nLy1zb21ldGhpbmcgPT4gc29tZXRoaW5nL3NvbWV0aGluZy9fc29tZXRoaW5nCiAgICAgIHZhciBwYXJ0aWFsaXplZE1vZHVsZU5hbWUgPSBtb2R1bGVOYW1lLnJlcGxhY2UoL1wvLShbXi9dKikkLywgJy9fJDEnKTsKCiAgICAgIGlmICh0aGlzLl9tb2R1bGVSZWdpc3RyeS5oYXMocGFydGlhbGl6ZWRNb2R1bGVOYW1lKSkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiBFbWJlci5kZXByZWNhdGUoJ01vZHVsZXMgc2hvdWxkIG5vdCBjb250YWluIHVuZGVyc2NvcmVzLiAnICsgJ0F0dGVtcHRlZCB0byBsb29rdXAgIicgKyBtb2R1bGVOYW1lICsgJyIgd2hpY2ggJyArICd3YXMgbm90IGZvdW5kLiBQbGVhc2UgcmVuYW1lICInICsgcGFydGlhbGl6ZWRNb2R1bGVOYW1lICsgJyIgJyArICd0byAiJyArIG1vZHVsZU5hbWUgKyAnIiBpbnN0ZWFkLicsIGZhbHNlLCB7IGlkOiAnZW1iZXItcmVzb2x2ZXIudW5kZXJzY29yZWQtbW9kdWxlcycsIHVudGlsOiAnMy4wLjAnIH0pKTsKCgogICAgICAgIHJldHVybiBwYXJ0aWFsaXplZE1vZHVsZU5hbWU7CiAgICAgIH0KCiAgICAgIGlmIChmYWxzZSkgewogICAgICAgIHZhciBpc0NhbWVsQ2FzZUhlbHBlciA9IHBhcnNlZE5hbWUudHlwZSA9PT0gJ2hlbHBlcicgJiYgL1thLXpdK1tBLVpdKy8udGVzdChtb2R1bGVOYW1lKTsKICAgICAgICBpZiAoaXNDYW1lbENhc2VIZWxwZXIpIHsKICAgICAgICAgIHRoaXMuX2NhbWVsQ2FzZUhlbHBlcldhcm5lZE5hbWVzID0gdGhpcy5fY2FtZWxDYXNlSGVscGVyV2FybmVkTmFtZXMgfHwgW107CiAgICAgICAgICB2YXIgYWxyZWFkeVdhcm5lZCA9IHRoaXMuX2NhbWVsQ2FzZUhlbHBlcldhcm5lZE5hbWVzLmluZGV4T2YocGFyc2VkTmFtZS5mdWxsTmFtZSkgPiAtMTsKICAgICAgICAgIGlmICghYWxyZWFkeVdhcm5lZCAmJiB0aGlzLl9tb2R1bGVSZWdpc3RyeS5oYXMoRW1iZXIuU3RyaW5nLmRhc2hlcml6ZShtb2R1bGVOYW1lKSkpIHsKICAgICAgICAgICAgdGhpcy5fY2FtZWxDYXNlSGVscGVyV2FybmVkTmFtZXMucHVzaChwYXJzZWROYW1lLmZ1bGxOYW1lKTsKICAgICAgICAgICAgKGZhbHNlICYmIEVtYmVyLndhcm4oJ0F0dGVtcHRlZCB0byBsb29rdXAgIicgKyBwYXJzZWROYW1lLmZ1bGxOYW1lICsgJyIgd2hpY2ggJyArICd3YXMgbm90IGZvdW5kLiBJbiBwcmV2aW91cyB2ZXJzaW9ucyBvZiBlbWJlci1yZXNvbHZlciwgYSBidWcgd291bGQgaGF2ZSAnICsgJ2NhdXNlZCB0aGUgbW9kdWxlIGF0ICInICsgRW1iZXIuU3RyaW5nLmRhc2hlcml6ZShtb2R1bGVOYW1lKSArICciIHRvIGJlICcgKyAncmV0dXJuZWQgZm9yIHRoaXMgY2FtZWwgY2FzZSBoZWxwZXIgbmFtZS4gVGhpcyBoYXMgYmVlbiBmaXhlZC4gJyArICdVc2UgdGhlIGRhc2hlcml6ZWQgbmFtZSB0byByZXNvbHZlIHRoZSBtb2R1bGUgdGhhdCB3b3VsZCBoYXZlIGJlZW4gJyArICdyZXR1cm5lZCBpbiBwcmV2aW91cyB2ZXJzaW9ucy4nLCBmYWxzZSwgeyBpZDogJ2VtYmVyLXJlc29sdmVyLmNhbWVsY2FzZS1oZWxwZXItbmFtZXMnLCB1bnRpbDogJzMuMC4wJyB9KSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9LAogICAgbG9va3VwRGVzY3JpcHRpb246IGZ1bmN0aW9uIGxvb2t1cERlc2NyaXB0aW9uKGZ1bGxOYW1lKSB7CiAgICAgIHZhciBwYXJzZWROYW1lID0gdGhpcy5wYXJzZU5hbWUoZnVsbE5hbWUpOwoKICAgICAgdmFyIG1vZHVsZU5hbWUgPSB0aGlzLmZpbmRNb2R1bGVOYW1lKHBhcnNlZE5hbWUsIHRydWUpOwoKICAgICAgcmV0dXJuIG1vZHVsZU5hbWU7CiAgICB9LAogICAgX2xvZ0xvb2t1cDogZnVuY3Rpb24gX2xvZ0xvb2t1cChmb3VuZCwgcGFyc2VkTmFtZSwgZGVzY3JpcHRpb24pIHsKICAgICAgaWYgKCFFbWJlci5FTlYuTE9HX01PRFVMRV9SRVNPTFZFUiAmJiAhcGFyc2VkTmFtZS5yb290LkxPR19SRVNPTFZFUikgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIHBhZGRpbmcgPSB2b2lkIDA7CiAgICAgIHZhciBzeW1ib2wgPSBmb3VuZCA/ICdb4pyTXScgOiAnWyBdJzsKCiAgICAgIGlmIChwYXJzZWROYW1lLmZ1bGxOYW1lLmxlbmd0aCA+IDYwKSB7CiAgICAgICAgcGFkZGluZyA9ICcuJzsKICAgICAgfSBlbHNlIHsKICAgICAgICBwYWRkaW5nID0gbmV3IEFycmF5KDYwIC0gcGFyc2VkTmFtZS5mdWxsTmFtZS5sZW5ndGgpLmpvaW4oJy4nKTsKICAgICAgfQoKICAgICAgaWYgKCFkZXNjcmlwdGlvbikgewogICAgICAgIGRlc2NyaXB0aW9uID0gdGhpcy5sb29rdXBEZXNjcmlwdGlvbihwYXJzZWROYW1lKTsKICAgICAgfQoKICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqLwogICAgICBpZiAoY29uc29sZSAmJiBjb25zb2xlLmluZm8pIHsKICAgICAgICBjb25zb2xlLmluZm8oc3ltYm9sLCBwYXJzZWROYW1lLmZ1bGxOYW1lLCBwYWRkaW5nLCBkZXNjcmlwdGlvbik7CiAgICAgIH0KICAgIH0sCiAgICBrbm93bkZvclR5cGU6IGZ1bmN0aW9uIGtub3duRm9yVHlwZSh0eXBlKSB7CiAgICAgIHZhciBtb2R1bGVLZXlzID0gdGhpcy5fbW9kdWxlUmVnaXN0cnkubW9kdWxlTmFtZXMoKTsKCiAgICAgIHZhciBpdGVtcyA9ICgwLCBfbWFrZURpY3Rpb25hcnkuZGVmYXVsdCkoKTsKICAgICAgZm9yICh2YXIgaW5kZXggPSAwLCBsZW5ndGggPSBtb2R1bGVLZXlzLmxlbmd0aDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHsKICAgICAgICB2YXIgbW9kdWxlTmFtZSA9IG1vZHVsZUtleXNbaW5kZXhdOwogICAgICAgIHZhciBmdWxsbmFtZSA9IHRoaXMudHJhbnNsYXRlVG9Db250YWluZXJGdWxsbmFtZSh0eXBlLCBtb2R1bGVOYW1lKTsKCiAgICAgICAgaWYgKGZ1bGxuYW1lKSB7CiAgICAgICAgICBpdGVtc1tmdWxsbmFtZV0gPSB0cnVlOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGl0ZW1zOwogICAgfSwKICAgIHRyYW5zbGF0ZVRvQ29udGFpbmVyRnVsbG5hbWU6IGZ1bmN0aW9uIHRyYW5zbGF0ZVRvQ29udGFpbmVyRnVsbG5hbWUodHlwZSwgbW9kdWxlTmFtZSkgewogICAgICB2YXIgcHJlZml4ID0gdGhpcy5wcmVmaXgoeyB0eXBlOiB0eXBlIH0pOwoKICAgICAgLy8gTm90ZTogdXNpbmcgc3RyaW5nIG1hbmlwdWxhdGlvbiBoZXJlIHJhdGhlciB0aGFuIHJlZ2V4ZXMgZm9yIGJldHRlciBwZXJmb3JtYW5jZS4KICAgICAgLy8gcG9kIG1vZHVsZXMKICAgICAgLy8gJ14nICsgcHJlZml4ICsgJy8oLispLycgKyB0eXBlICsgJyQnCiAgICAgIHZhciBwb2RQcmVmaXggPSBwcmVmaXggKyAnLyc7CiAgICAgIHZhciBwb2RTdWZmaXggPSAnLycgKyB0eXBlOwogICAgICB2YXIgc3RhcnQgPSBtb2R1bGVOYW1lLmluZGV4T2YocG9kUHJlZml4KTsKICAgICAgdmFyIGVuZCA9IG1vZHVsZU5hbWUuaW5kZXhPZihwb2RTdWZmaXgpOwoKICAgICAgaWYgKHN0YXJ0ID09PSAwICYmIGVuZCA9PT0gbW9kdWxlTmFtZS5sZW5ndGggLSBwb2RTdWZmaXgubGVuZ3RoICYmIG1vZHVsZU5hbWUubGVuZ3RoID4gcG9kUHJlZml4Lmxlbmd0aCArIHBvZFN1ZmZpeC5sZW5ndGgpIHsKICAgICAgICByZXR1cm4gdHlwZSArICc6JyArIG1vZHVsZU5hbWUuc2xpY2Uoc3RhcnQgKyBwb2RQcmVmaXgubGVuZ3RoLCBlbmQpOwogICAgICB9CgogICAgICAvLyBub24tcG9kIG1vZHVsZXMKICAgICAgLy8gJ14nICsgcHJlZml4ICsgJy8nICsgcGx1cmFsaXplZFR5cGUgKyAnLyguKykkJwogICAgICB2YXIgcGx1cmFsaXplZFR5cGUgPSB0aGlzLnBsdXJhbGl6ZSh0eXBlKTsKICAgICAgdmFyIG5vblBvZFByZWZpeCA9IHByZWZpeCArICcvJyArIHBsdXJhbGl6ZWRUeXBlICsgJy8nOwoKICAgICAgaWYgKG1vZHVsZU5hbWUuaW5kZXhPZihub25Qb2RQcmVmaXgpID09PSAwICYmIG1vZHVsZU5hbWUubGVuZ3RoID4gbm9uUG9kUHJlZml4Lmxlbmd0aCkgewogICAgICAgIHJldHVybiB0eXBlICsgJzonICsgbW9kdWxlTmFtZS5zbGljZShub25Qb2RQcmVmaXgubGVuZ3RoKTsKICAgICAgfQogICAgfSwKICAgIF9leHRyYWN0RGVmYXVsdEV4cG9ydDogZnVuY3Rpb24gX2V4dHJhY3REZWZhdWx0RXhwb3J0KG5vcm1hbGl6ZWRNb2R1bGVOYW1lKSB7CiAgICAgIHZhciBtb2R1bGUgPSByZXF1aXJlKG5vcm1hbGl6ZWRNb2R1bGVOYW1lLCBudWxsLCBudWxsLCB0cnVlIC8qIGZvcmNlIHN5bmMgKi8pOwoKICAgICAgaWYgKG1vZHVsZSAmJiBtb2R1bGVbJ2RlZmF1bHQnXSkgewogICAgICAgIG1vZHVsZSA9IG1vZHVsZVsnZGVmYXVsdCddOwogICAgICB9CgogICAgICByZXR1cm4gbW9kdWxlOwogICAgfQogIH0pOwoKICBSZXNvbHZlci5yZW9wZW5DbGFzcyh7CiAgICBtb2R1bGVCYXNlZFJlc29sdmVyOiB0cnVlCiAgfSk7CgogIGV4cG9ydHMuZGVmYXVsdCA9IFJlc29sdmVyOwp9KTsKO2RlZmluZSgnZW1iZXItcmVzb2x2ZXIvdXRpbHMvY2xhc3MtZmFjdG9yeScsIFsnZXhwb3J0cyddLCBmdW5jdGlvbiAoZXhwb3J0cykgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLmRlZmF1bHQgPSBjbGFzc0ZhY3Rvcnk7CiAgZnVuY3Rpb24gY2xhc3NGYWN0b3J5KGtsYXNzKSB7CiAgICByZXR1cm4gewogICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShpbmplY3Rpb25zKSB7CiAgICAgICAgaWYgKHR5cGVvZiBrbGFzcy5leHRlbmQgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIHJldHVybiBrbGFzcy5leHRlbmQoaW5qZWN0aW9ucyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBrbGFzczsKICAgICAgICB9CiAgICAgIH0KICAgIH07CiAgfQp9KTsKO2RlZmluZSgnZW1iZXItcmVzb2x2ZXIvdXRpbHMvbWFrZS1kaWN0aW9uYXJ5JywgWydleHBvcnRzJ10sIGZ1bmN0aW9uIChleHBvcnRzKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIGV4cG9ydHMuZGVmYXVsdCA9IG1ha2VEaWN0aW9uYXJ5OwogIGZ1bmN0aW9uIG1ha2VEaWN0aW9uYXJ5KCkgewogICAgdmFyIGNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGNhY2hlWydfZGljdCddID0gbnVsbDsKICAgIGRlbGV0ZSBjYWNoZVsnX2RpY3QnXTsKICAgIHJldHVybiBjYWNoZTsKICB9Cn0pOwo7ZGVmaW5lKCJlbWJlci10ZXN0LXdhaXRlcnMvYnVpbGQtd2FpdGVyIiwgWyJleHBvcnRzIiwgImVtYmVyLXRlc3Qtd2FpdGVycyIsICJlbWJlci10ZXN0LXdhaXRlcnMvbm9vcC10ZXN0LXdhaXRlciJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlclRlc3RXYWl0ZXJzLCBfbm9vcFRlc3RXYWl0ZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSBidWlsZFdhaXRlcjsKCiAgLyoqCiAgICogQnVpbGRzIGFuZCByZXR1cm5zIGEgdGVzdCB3YWl0ZXIuIFRoZSB0eXBlIG9mIHRoZQogICAqIHJldHVybmVkIHdhaXRlciBpcyBkZXBlbmRlbnQgb24gd2hldGhlciB0aGUgYXBwIG9yCiAgICogYWRkb24gaXMgaW4gYERFQlVHYCBtb2RlIG9yIG5vdC4KICAgKgogICAqIEBwYXJhbSBuYW1lIHtzdHJpbmd9IFRoZSBuYW1lIG9mIHRoZSB0ZXN0IHdhaXRlcgogICAqIEByZXR1cm5zIHtJVGVzdFdhaXRlcn0KICAgKgogICAqIEBleGFtcGxlCiAgICoKICAgKiBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAqIGltcG9ydCB7IGJ1aWxkV2FpdGVyIH0gZnJvbSAnZW1iZXItdGVzdC13YWl0ZXJzJzsKICAgKgogICAqIGlmIChERUJVRykgewogICAqICAgbGV0IHdhaXRlciA9IGJ1aWxkV2FpdGVyKCdmcmllbmQtd2FpdGVyJyk7CiAgICogfQogICAqCiAgICogZXhwb3J0IGRlZmF1bHQgY2xhc3MgRnJpZW5keiBleHRlbmRzIENvbXBvbmVudCB7CiAgICogICBkaWRJbnNlcnRFbGVtZW50KCkgewogICAqICAgICBsZXQgdG9rZW4gPSB3YWl0ZXIuYmVnaW5Bc3luYyh0aGlzKTsKICAgKgogICAqICAgICBzb21lQXN5bmNXb3JrKCkudGhlbigoKSA9PiB7CiAgICogICAgICAgd2FpdGVyLmVuZEFzeW5jKHRva2VuKTsKICAgKiAgICAgfSk7CiAgICogICB9CiAgICogfQogICAqLwogIGZ1bmN0aW9uIGJ1aWxkV2FpdGVyKG5hbWUpIHsKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICByZXR1cm4gbmV3IF9lbWJlclRlc3RXYWl0ZXJzLlRlc3RXYWl0ZXIobmFtZSk7CiAgICB9CgogICAgcmV0dXJuIG5ldyBfbm9vcFRlc3RXYWl0ZXIuZGVmYXVsdChuYW1lKTsKICB9Cn0pOwo7ZGVmaW5lKCJlbWJlci10ZXN0LXdhaXRlcnMvaW5kZXgiLCBbImV4cG9ydHMiLCAiZW1iZXItdGVzdC13YWl0ZXJzL3dhaXRlci1tYW5hZ2VyIiwgImVtYmVyLXRlc3Qtd2FpdGVycy90ZXN0LXdhaXRlciIsICJlbWJlci10ZXN0LXdhaXRlcnMvYnVpbGQtd2FpdGVyIiwgImVtYmVyLXRlc3Qtd2FpdGVycy93YWl0LWZvci1wcm9taXNlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3dhaXRlck1hbmFnZXIsIF90ZXN0V2FpdGVyLCBfYnVpbGRXYWl0ZXIsIF93YWl0Rm9yUHJvbWlzZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAicmVnaXN0ZXIiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfd2FpdGVyTWFuYWdlci5yZWdpc3RlcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJ1bnJlZ2lzdGVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3dhaXRlck1hbmFnZXIudW5yZWdpc3RlcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRXYWl0ZXJzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3dhaXRlck1hbmFnZXIuZ2V0V2FpdGVyczsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfcmVzZXQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfd2FpdGVyTWFuYWdlci5fcmVzZXQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ2V0UGVuZGluZ1dhaXRlclN0YXRlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3dhaXRlck1hbmFnZXIuZ2V0UGVuZGluZ1dhaXRlclN0YXRlOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImhhc1BlbmRpbmdXYWl0ZXJzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3dhaXRlck1hbmFnZXIuaGFzUGVuZGluZ1dhaXRlcnM7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiVGVzdFdhaXRlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF90ZXN0V2FpdGVyLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiYnVpbGRXYWl0ZXIiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYnVpbGRXYWl0ZXIuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJ3YWl0Rm9yUHJvbWlzZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF93YWl0Rm9yUHJvbWlzZS5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItdGVzdC13YWl0ZXJzL25vb3AtdGVzdC13YWl0ZXIiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICBmdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbiIpOyB9IH0KCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoInZhbHVlIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0KCiAgZnVuY3Rpb24gX2NyZWF0ZUNsYXNzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH0KCiAgLyoqCiAgICogQSBjbGFzcyBwcm92aWRpbmcgYSBwcm9kdWN0aW9uLCBub29wIHJlcGxhY2VtZW50IGZvciB0aGUge1Rlc3RXYWl0ZXI8VD59IGNsYXNzLgogICAqCiAgICogQHB1YmxpYwogICAqIEBjbGFzcyBUZXN0V2FpdGVyPFQ+CiAgICovCiAgdmFyIE5vb3BUZXN0V2FpdGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gTm9vcFRlc3RXYWl0ZXIobmFtZSkgewogICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgTm9vcFRlc3RXYWl0ZXIpOwoKICAgICAgdGhpcy5uYW1lID0gbmFtZTsKICAgIH0KCiAgICBfY3JlYXRlQ2xhc3MoTm9vcFRlc3RXYWl0ZXIsIFt7CiAgICAgIGtleTogImJlZ2luQXN5bmMiLAogICAgICB2YWx1ZTogZnVuY3Rpb24gYmVnaW5Bc3luYygpIHsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJlbmRBc3luYyIsCiAgICAgIHZhbHVlOiBmdW5jdGlvbiBlbmRBc3luYygpIHt9CiAgICB9LCB7CiAgICAgIGtleTogIndhaXRVbnRpbCIsCiAgICAgIHZhbHVlOiBmdW5jdGlvbiB3YWl0VW50aWwoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiZGVidWdJbmZvIiwKICAgICAgdmFsdWU6IGZ1bmN0aW9uIGRlYnVnSW5mbygpIHsKICAgICAgICByZXR1cm4gW107CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gTm9vcFRlc3RXYWl0ZXI7CiAgfSgpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gTm9vcFRlc3RXYWl0ZXI7Cn0pOwo7ZGVmaW5lKCJlbWJlci10ZXN0LXdhaXRlcnMvdGVzdC13YWl0ZXIiLCBbImV4cG9ydHMiLCAiZW1iZXItdGVzdC13YWl0ZXJzL3dhaXRlci1tYW5hZ2VyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3dhaXRlck1hbmFnZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIGZ1bmN0aW9uIF90b0NvbnN1bWFibGVBcnJheShhcnIpIHsgcmV0dXJuIF9hcnJheVdpdGhvdXRIb2xlcyhhcnIpIHx8IF9pdGVyYWJsZVRvQXJyYXkoYXJyKSB8fCBfbm9uSXRlcmFibGVTcHJlYWQoKTsgfQoKICBmdW5jdGlvbiBfbm9uSXRlcmFibGVTcHJlYWQoKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoIkludmFsaWQgYXR0ZW1wdCB0byBzcHJlYWQgbm9uLWl0ZXJhYmxlIGluc3RhbmNlIik7IH0KCiAgZnVuY3Rpb24gX2l0ZXJhYmxlVG9BcnJheShpdGVyKSB7IGlmIChTeW1ib2wuaXRlcmF0b3IgaW4gT2JqZWN0KGl0ZXIpIHx8IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpdGVyKSA9PT0gIltvYmplY3QgQXJndW1lbnRzXSIpIHJldHVybiBBcnJheS5mcm9tKGl0ZXIpOyB9CgogIGZ1bmN0aW9uIF9hcnJheVdpdGhvdXRIb2xlcyhhcnIpIHsgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgeyBmb3IgKHZhciBpID0gMCwgYXJyMiA9IG5ldyBBcnJheShhcnIubGVuZ3RoKTsgaSA8IGFyci5sZW5ndGg7IGkrKykgeyBhcnIyW2ldID0gYXJyW2ldOyB9IHJldHVybiBhcnIyOyB9IH0KCiAgZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24iKTsgfSB9CgogIGZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyhDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIHZhciB0b2tlbiA9IDA7CgogIGZ1bmN0aW9uIGdldE5leHRUb2tlbigpIHsKICAgIHJldHVybiB0b2tlbisrOwogIH0KICAvKioKICAgKiBBIGNsYXNzIHByb3ZpZGluZyBjcmVhdGlvbiwgcmVnaXN0cmF0aW9uIGFuZCBhc3luYyB3YWl0aW5nIGZ1bmN0aW9uYWxpdHkuCiAgICoKICAgKiBAcHVibGljCiAgICogQGNsYXNzIFRlc3RXYWl0ZXI8VD4KICAgKi8KCgogIHZhciBUZXN0V2FpdGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgLyoqCiAgICAgKiBAcHVibGljCiAgICAgKiBAY29uc3RydWN0b3IKICAgICAqIEBwYXJhbSBuYW1lIHtXYWl0ZXJOYW1lfSB0aGUgbmFtZSBvZiB0aGUgdGVzdCB3YWl0ZXIKICAgICAqLwogICAgZnVuY3Rpb24gVGVzdFdhaXRlcihuYW1lLCBuZXh0VG9rZW4pIHsKICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFRlc3RXYWl0ZXIpOwoKICAgICAgdGhpcy5pc1JlZ2lzdGVyZWQgPSBmYWxzZTsKICAgICAgdGhpcy5pdGVtcyA9IG5ldyBNYXAoKTsKICAgICAgdGhpcy5uYW1lID0gbmFtZTsgLy8gQHRzLWlnbm9yZQoKICAgICAgdGhpcy5uZXh0VG9rZW4gPSBuZXh0VG9rZW4gfHwgZ2V0TmV4dFRva2VuOwogICAgfQogICAgLyoqCiAgICAgKiBXaWxsIHJlZ2lzdGVyIHRoZSB3YWl0ZXIsIGFsbG93aW5nIGl0IHRvIGJlIG9wdGVkIGluIHRvIHBhdXNpbmcgYXN5bmMKICAgICAqIG9wZXJhdGlvbnMgdW50aWwgdGhleSdyZSBjb21wbGV0ZWQgd2l0aGluIHlvdXIgdGVzdHMuIFlvdSBzaG91bGQgaW52b2tlCiAgICAgKiBpdCBhZnRlciBpbnN0YW50aWF0aW5nIHlvdXIgYFRlc3RXYWl0ZXJgIGluc3RhbmNlLgogICAgICoKICAgICAqICoqTm90ZSoqLCBpZiB5b3UgZm9yZ2V0IHRvIHJlZ2lzdGVyIHlvdXIgd2FpdGVyLCBpdCB3aWxsIGJlIHJlZ2lzdGVyZWQKICAgICAqIGZvciB5b3Ugb24gdGhlIGZpcnN0IGludm9jYXRpb24gb2YgYGJlZ2luQXN5bmNgLgogICAgICoKICAgICAqIEBwcml2YXRlCiAgICAgKiBAbWV0aG9kIHJlZ2lzdGVyCiAgICAgKi8KCgogICAgX2NyZWF0ZUNsYXNzKFRlc3RXYWl0ZXIsIFt7CiAgICAgIGtleTogInJlZ2lzdGVyIiwKICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlZ2lzdGVyKCkgewogICAgICAgIGlmICghdGhpcy5pc1JlZ2lzdGVyZWQpIHsKICAgICAgICAgICgwLCBfd2FpdGVyTWFuYWdlci5yZWdpc3RlcikodGhpcyk7CiAgICAgICAgICB0aGlzLmlzUmVnaXN0ZXJlZCA9IHRydWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBTaG91bGQgYmUgdXNlZCB0byBzaWduYWwgdGhlIGJlZ2lubmluZyBvZiBhbiBhc3luYyBvcGVyYXRpb24gdGhhdAogICAgICAgKiBpcyB0byBiZSB3YWl0ZWQgZm9yLiBJbnZvY2F0aW9uIG9mIHRoaXMgbWV0aG9kIHNob3VsZCBiZSBwYWlyZWQgd2l0aCBhIHN1YnNlcXVlbnQKICAgICAgICogYGVuZEFzeW5jYCBjYWxsIHRvIGluZGljYXRlIHRvIHRoZSB3YWl0ZXIgc3lzdGVtIHRoYXQgdGhlIGFzeW5jIG9wZXJhdGlvbiBpcyBjb21wbGV0ZWQuCiAgICAgICAqCiAgICAgICAqIEBwdWJsaWMKICAgICAgICogQG1ldGhvZCBiZWdpbkFzeW5jCiAgICAgICAqIEBwYXJhbSBpdGVtIHtUfSBUaGUgaXRlbSB0byByZWdpc3RlciBmb3Igd2FpdGluZwogICAgICAgKiBAcGFyYW0gbGFiZWwge3N0cmluZ30gQW4gb3B0aW9uYWwgbGFiZWwgdG8gaWRlbnRpZnkgdGhlIGl0ZW0KICAgICAgICovCgogICAgfSwgewogICAgICBrZXk6ICJiZWdpbkFzeW5jIiwKICAgICAgdmFsdWU6IGZ1bmN0aW9uIGJlZ2luQXN5bmMoKSB7CiAgICAgICAgdmFyIHRva2VuID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiB0aGlzLm5leHRUb2tlbigpOwogICAgICAgIHZhciBsYWJlbCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkOwogICAgICAgIHRoaXMucmVnaXN0ZXIoKTsKCiAgICAgICAgaWYgKHRoaXMuaXRlbXMuaGFzKHRva2VuKSkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJiZWdpbkFzeW5jIGNhbGxlZCBmb3IgIi5jb25jYXQodG9rZW4sICIgYnV0IGl0IGlzIGFscmVhZHkgcGVuZGluZy4iKSk7CiAgICAgICAgfQoKICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoKTsKICAgICAgICB0aGlzLml0ZW1zLnNldCh0b2tlbiwgewogICAgICAgICAgZ2V0IHN0YWNrKCkgewogICAgICAgICAgICByZXR1cm4gZXJyb3Iuc3RhY2s7CiAgICAgICAgICB9LAoKICAgICAgICAgIGxhYmVsOiBsYWJlbAogICAgICAgIH0pOwogICAgICAgIHJldHVybiB0b2tlbjsKICAgICAgfQogICAgICAvKioKICAgICAgICogU2hvdWxkIGJlIHVzZWQgdG8gc2lnbmFsIHRoZSBlbmQgb2YgYW4gYXN5bmMgb3BlcmF0aW9uLiBJbnZvY2F0aW9uIG9mIHRoaXMKICAgICAgICogbWV0aG9kIHNob3VsZCBiZSBwYWlyZWQgd2l0aCBhIHByZWNlZWRpbmcgYGJlZ2luQXN5bmNgIGNhbGwsIHdoaWNoIHdvdWxkIGluZGljYXRlIHRoZQogICAgICAgKiBiZWdpbm5pbmcgb2YgYW4gYXN5bmMgb3BlcmF0aW9uLgogICAgICAgKgogICAgICAgKiBAcHVibGljCiAgICAgICAqIEBtZXRob2QgZW5kQXN5bmMKICAgICAgICogQHBhcmFtIGl0ZW0ge1R9IFRoZSBpdGVtIHRvIHRoYXQgd2FzIHJlZ2lzdGVyZWQgZm9yIHdhaXRpbmcKICAgICAgICovCgogICAgfSwgewogICAgICBrZXk6ICJlbmRBc3luYyIsCiAgICAgIHZhbHVlOiBmdW5jdGlvbiBlbmRBc3luYyh0b2tlbikgewogICAgICAgIGlmICghdGhpcy5pdGVtcy5oYXModG9rZW4pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImVuZEFzeW5jIGNhbGxlZCBmb3IgIi5jb25jYXQodG9rZW4sICIgYnV0IGl0IGlzIG5vdCBjdXJyZW50bHkgcGVuZGluZy4iKSk7CiAgICAgICAgfQoKICAgICAgICB0aGlzLml0ZW1zLmRlbGV0ZSh0b2tlbik7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZWQgdG8gZGV0ZXJtaW5lIGlmIHRoZSB3YWl0ZXIgc3lzdGVtIHNob3VsZCBzdGlsbCB3YWl0IGZvciBhc3luYwogICAgICAgKiBvcGVyYXRpb25zIHRvIGNvbXBsZXRlLgogICAgICAgKgogICAgICAgKiBAcHVibGljCiAgICAgICAqIEBtZXRob2Qgd2FpdFVudGlsCiAgICAgICAqIEByZXR1cm5zIHtib29sZWFufQogICAgICAgKi8KCiAgICB9LCB7CiAgICAgIGtleTogIndhaXRVbnRpbCIsCiAgICAgIHZhbHVlOiBmdW5jdGlvbiB3YWl0VW50aWwoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaXRlbXMuc2l6ZSA9PT0gMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogUmV0dXJucyB0aGUgYGRlYnVnSW5mb2AgZm9yIGVhY2ggaXRlbSB0cmFja2luZyBhc3luYyBvcGVyYXRpb25zIGluIHRoaXMgd2FpdGVyLgogICAgICAgKgogICAgICAgKiBAcHVibGljCiAgICAgICAqIEBtZXRob2QgZGVidWdJbmZvCiAgICAgICAqIEByZXR1cm5zIHtJVGVzdFdhaXRlckRlYnVnSW5mb30KICAgICAgICovCgogICAgfSwgewogICAgICBrZXk6ICJkZWJ1Z0luZm8iLAogICAgICB2YWx1ZTogZnVuY3Rpb24gZGVidWdJbmZvKCkgewogICAgICAgIHJldHVybiBfdG9Db25zdW1hYmxlQXJyYXkodGhpcy5pdGVtcy52YWx1ZXMoKSk7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gVGVzdFdhaXRlcjsKICB9KCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBUZXN0V2FpdGVyOwp9KTsKO2RlZmluZSgiZW1iZXItdGVzdC13YWl0ZXJzL3R5cGVzL2luZGV4IiwgW10sIGZ1bmN0aW9uICgpIHsKICAidXNlIHN0cmljdCI7Cn0pOwo7ZGVmaW5lKCJlbWJlci10ZXN0LXdhaXRlcnMvd2FpdC1mb3ItcHJvbWlzZSIsIFsiZXhwb3J0cyIsICJlbWJlci10ZXN0LXdhaXRlcnMvdGVzdC13YWl0ZXIiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdGVzdFdhaXRlcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHdhaXRGb3JQcm9taXNlOwogIHZhciBQUk9NSVNFX1dBSVRFUiA9IG5ldyBfdGVzdFdhaXRlci5kZWZhdWx0KCdwcm9taXNlLXdhaXRlcicpOwogIC8qKgogICAqIEEgY29udmVuaWVudCB1dGlsaXR5IGZ1bmN0aW9uIHRvIHNpbXBsaWZ5IHdhaXRpbmcgZm9yIGEgcHJvbWlzZS4KICAgKgogICAqIEBwdWJsaWMKICAgKiBAcGFyYW0gcHJvbWlzZSB7UHJvbWlzZTxUPn0gVGhlIHByb21pc2UgdG8gdHJhY2sgYXN5bmMgb3BlcmF0aW9ucyBmb3IKICAgKiBAcGFyYW0gbGFiZWwge3N0cmluZ30gQW4gb3B0aW9uYWwgc3RyaW5nIHRvIGlkZW50aWZ5IHRoZSBwcm9taXNlCiAgICoKICAgKiBAZXhhbXBsZQogICAqCiAgICogaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgKiBpbXBvcnQgeyB3YWl0Rm9yUHJvbWlzZSB9IGZyb20gJ2VtYmVyLXRlc3Qtd2FpdGVycyc7CiAgICoKICAgKiBleHBvcnQgZGVmYXVsdCBjbGFzcyBGcmllbmR6IGV4dGVuZHMgQ29tcG9uZW50IHsKICAgKiAgIGRpZEluc2VydEVsZW1lbnQoKSB7CiAgICogICAgIHdhaXRGb3JQcm9taXNlKG5ldyBQcm9taXNlKHJlc29sdmUgPT4gewogICAqICAgICAgIGRvU29tZVdvcmsoKTsKICAgKiAgICAgICByZXNvbHZlKCk7CiAgICogICAgIH0pKTsKICAgKiAgIH0KICAgKiB9CiAgICovCgogIGZ1bmN0aW9uIHdhaXRGb3JQcm9taXNlKHByb21pc2UsIGxhYmVsKSB7CiAgICB2YXIgcmVzdWx0ID0gcHJvbWlzZTsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgUFJPTUlTRV9XQUlURVIuYmVnaW5Bc3luYyhwcm9taXNlLCBsYWJlbCk7CiAgICAgIHJlc3VsdCA9IHByb21pc2UudGhlbihmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgICBQUk9NSVNFX1dBSVRFUi5lbmRBc3luYyhwcm9taXNlKTsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0sIGZ1bmN0aW9uIChlcnJvcikgewogICAgICAgIFBST01JU0VfV0FJVEVSLmVuZEFzeW5jKHByb21pc2UpOwogICAgICAgIHRocm93IGVycm9yOwogICAgICB9KTsKICAgIH0KCiAgICByZXR1cm4gcmVzdWx0OwogIH0KfSk7CjtkZWZpbmUoImVtYmVyLXRlc3Qtd2FpdGVycy93YWl0ZXItbWFuYWdlciIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLnJlZ2lzdGVyID0gcmVnaXN0ZXI7CiAgX2V4cG9ydHMudW5yZWdpc3RlciA9IHVucmVnaXN0ZXI7CiAgX2V4cG9ydHMuZ2V0V2FpdGVycyA9IGdldFdhaXRlcnM7CiAgX2V4cG9ydHMuX3Jlc2V0ID0gX3Jlc2V0OwogIF9leHBvcnRzLmdldFBlbmRpbmdXYWl0ZXJTdGF0ZSA9IGdldFBlbmRpbmdXYWl0ZXJTdGF0ZTsKICBfZXhwb3J0cy5oYXNQZW5kaW5nV2FpdGVycyA9IGhhc1BlbmRpbmdXYWl0ZXJzOwoKICBmdW5jdGlvbiBfdG9Db25zdW1hYmxlQXJyYXkoYXJyKSB7IHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5KGFycikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7IH0KCiAgZnVuY3Rpb24gX25vbkl0ZXJhYmxlU3ByZWFkKCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJJbnZhbGlkIGF0dGVtcHQgdG8gc3ByZWFkIG5vbi1pdGVyYWJsZSBpbnN0YW5jZSIpOyB9CgogIGZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkoaXRlcikgeyBpZiAoU3ltYm9sLml0ZXJhdG9yIGluIE9iamVjdChpdGVyKSB8fCBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaXRlcikgPT09ICJbb2JqZWN0IEFyZ3VtZW50c10iKSByZXR1cm4gQXJyYXkuZnJvbShpdGVyKTsgfQoKICBmdW5jdGlvbiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB7IGlmIChBcnJheS5pc0FycmF5KGFycikpIHsgZm9yICh2YXIgaSA9IDAsIGFycjIgPSBuZXcgQXJyYXkoYXJyLmxlbmd0aCk7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHsgYXJyMltpXSA9IGFycltpXTsgfSByZXR1cm4gYXJyMjsgfSB9CgogIHZhciBXQUlURVJTID0gbmV3IE1hcCgpOwogIC8qKgogICAqIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggbGVnYWN5IHdhaXRlcnMgc3lzdGVtLgogICAqCiAgICogV2Ugd2FudCB0byBhbHdheXMgcmVnaXN0ZXIgYSB3YWl0ZXIgdXNpbmcgdGhlIGxlZ2FjeSB3YWl0ZXIgc3lzdGVtLCBhcyByaWdodAogICAqIG5vdyBpZiBjb25zdW1lcnMgYXJlIG5vdCBvbiB0aGUgcmlnaHQgdmVyc2lvbiBvZiBAZW1iZXIvdGVzdC1oZWxwZXJzLCB1c2luZwogICAqIHRoaXMgYWRkb24gd2lsbCByZXN1bHQgaW4gbm9uZSBvZiB0aGVzZSB3YWl0ZXJzIHdhaXRpbmcuCiAgICovCiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVtYmVyL25ldy1tb2R1bGUtaW1wb3J0cwoKICBpZiAoRW1iZXIuVGVzdCkgewogICAgRW1iZXIuVGVzdC5yZWdpc3RlcldhaXRlcihmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAhaGFzUGVuZGluZ1dhaXRlcnMoKTsKICAgIH0pOwogIH0KICAvKioKICAgKiBSZWdpc3RlcnMgYSB3YWl0ZXIuCiAgICoKICAgKiBAcHVibGljCiAgICogQHBhcmFtIHdhaXRlciB7SVdhaXRlcn0gQSB0ZXN0IHdhaXRlciBpbnN0YW5jZQogICAqLwoKCiAgZnVuY3Rpb24gcmVnaXN0ZXIod2FpdGVyKSB7CiAgICBXQUlURVJTLnNldCh3YWl0ZXIubmFtZSwgd2FpdGVyKTsKICB9CiAgLyoqCiAgICogVW5yZWdpc3RlcnMgYSB3YWl0ZXIuCiAgICoKICAgKiBAcHVibGljCiAgICogQHBhcmFtIHdhaXRlciB7SVdhaXRlcn0gQSB0ZXN0IHdhaXRlciBpbnN0YW5jZQogICAqLwoKCiAgZnVuY3Rpb24gdW5yZWdpc3Rlcih3YWl0ZXIpIHsKICAgIFdBSVRFUlMuZGVsZXRlKHdhaXRlci5uYW1lKTsKICB9CiAgLyoqCiAgICogR2V0cyBhbiBhcnJheSBvZiBhbGwgd2FpdGVycyBjdXJyZW50IHJlZ2lzdGVyZWQuCiAgICoKICAgKiBAcHVibGljCiAgICogQHJldHVybnMge0lXYWl0ZXJbXX0KICAgKi8KCgogIGZ1bmN0aW9uIGdldFdhaXRlcnMoKSB7CiAgICByZXR1cm4gX3RvQ29uc3VtYWJsZUFycmF5KFdBSVRFUlMudmFsdWVzKCkpOwogIH0KICAvKioKICAgKiBDbGVhcnMgYWxsIHdhaXRlcnMuCiAgICoKICAgKiBAcHVibGljCiAgICovCgoKICBmdW5jdGlvbiBfcmVzZXQoKSB7CiAgICBXQUlURVJTLmNsZWFyKCk7CiAgfQogIC8qKgogICAqIEdldHMgdGhlIGN1cnJlbnQgc3RhdGUgb2YgYWxsIHdhaXRlcnMuIEFueSB3YWl0ZXJzIHdob3NlCiAgICogYHdhaXRVbnRpbGAgbWV0aG9kIHJldHVybnMgZmFsc2Ugd2lsbCBiZSBjb25zaWRlcmVkIGBwZW5kaW5nYC4KICAgKgogICAqIEByZXR1cm5zIHtJUGVuZGluZ1dhaXRlclN0YXRlfSBBbiBvYmplY3QgY29udGFpbmluZyBhIGNvdW50IG9mIGFsbCB3YWl0ZXJzCiAgICogcGVuZGluZyBhbmQgYSBgd2FpdGVyc2Agb2JqZWN0IGNvbnRhaW5pbmcgdGhlIG5hbWUgb2YgYWxsIHBlbmRpbmcgd2FpdGVycwogICAqIGFuZCB0aGVpciBkZWJ1ZyBpbmZvLgogICAqLwoKCiAgZnVuY3Rpb24gZ2V0UGVuZGluZ1dhaXRlclN0YXRlKCkgewogICAgdmFyIHJlc3VsdCA9IHsKICAgICAgcGVuZGluZzogMCwKICAgICAgd2FpdGVyczoge30KICAgIH07CiAgICBXQUlURVJTLmZvckVhY2goZnVuY3Rpb24gKHdhaXRlcikgewogICAgICBpZiAoIXdhaXRlci53YWl0VW50aWwoKSkgewogICAgICAgIHJlc3VsdC5wZW5kaW5nKys7CiAgICAgICAgdmFyIGRlYnVnSW5mbyA9IHdhaXRlci5kZWJ1Z0luZm8oKTsKICAgICAgICByZXN1bHQud2FpdGVyc1t3YWl0ZXIubmFtZV0gPSBkZWJ1Z0luZm8gfHwgdHJ1ZTsKICAgICAgfQogICAgfSk7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICAvKioKICAgKiBEZXRlcm1pbmVzIGlmIHRoZXJlIGFyZSBhbnkgcGVuZGluZyB3YWl0ZXJzLgogICAqCiAgICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGVyZSBhcmUgcGVuZGluZyB3YWl0ZXJzLCBvdGhlcndpc2UgYGZhbHNlYC4KICAgKi8KCgogIGZ1bmN0aW9uIGhhc1BlbmRpbmdXYWl0ZXJzKCkgewogICAgdmFyIHN0YXRlID0gZ2V0UGVuZGluZ1dhaXRlclN0YXRlKCk7CiAgICByZXR1cm4gc3RhdGUucGVuZGluZyA+IDA7CiAgfQp9KTsKOwo=", + "compression": 0, + "text": "d2luZG93LkVtYmVyRU5WID0geyJGRUFUVVJFUyI6e30sIkVYVEVORF9QUk9UT1RZUEVTIjp7IkRhdGUiOmZhbHNlfSwiX0pRVUVSWV9JTlRFR1JBVElPTiI6ZmFsc2V9Owp2YXIgcnVubmluZ1Rlc3RzID0gZmFsc2U7CgoKCjt2YXIgbG9hZGVyLCBkZWZpbmUsIHJlcXVpcmVNb2R1bGUsIHJlcXVpcmUsIHJlcXVpcmVqczsKCihmdW5jdGlvbiAoZ2xvYmFsKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICBmdW5jdGlvbiBkaWN0KCkgewogICAgdmFyIG9iaiA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBvYmpbJ19fJ10gPSB1bmRlZmluZWQ7CiAgICBkZWxldGUgb2JqWydfXyddOwogICAgcmV0dXJuIG9iajsKICB9CgogIC8vIFNhdmUgb2ZmIHRoZSBvcmlnaW5hbCB2YWx1ZXMgb2YgdGhlc2UgZ2xvYmFscywgc28gd2UgY2FuIHJlc3RvcmUgdGhlbSBpZiBzb21lb25lIGFza3MgdXMgdG8KICB2YXIgb2xkR2xvYmFscyA9IHsKICAgIGxvYWRlcjogbG9hZGVyLAogICAgZGVmaW5lOiBkZWZpbmUsCiAgICByZXF1aXJlTW9kdWxlOiByZXF1aXJlTW9kdWxlLAogICAgcmVxdWlyZTogcmVxdWlyZSwKICAgIHJlcXVpcmVqczogcmVxdWlyZWpzCiAgfTsKCiAgcmVxdWlyZWpzID0gcmVxdWlyZSA9IHJlcXVpcmVNb2R1bGUgPSBmdW5jdGlvbiAoaWQpIHsKICAgIHZhciBwZW5kaW5nID0gW107CiAgICB2YXIgbW9kID0gZmluZE1vZHVsZShpZCwgJyhyZXF1aXJlKScsIHBlbmRpbmcpOwoKICAgIGZvciAodmFyIGkgPSBwZW5kaW5nLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgIHBlbmRpbmdbaV0uZXhwb3J0cygpOwogICAgfQoKICAgIHJldHVybiBtb2QubW9kdWxlLmV4cG9ydHM7CiAgfTsKCiAgbG9hZGVyID0gewogICAgbm9Db25mbGljdDogZnVuY3Rpb24gKGFsaWFzZXMpIHsKICAgICAgdmFyIG9sZE5hbWUsIG5ld05hbWU7CgogICAgICBmb3IgKG9sZE5hbWUgaW4gYWxpYXNlcykgewogICAgICAgIGlmIChhbGlhc2VzLmhhc093blByb3BlcnR5KG9sZE5hbWUpKSB7CiAgICAgICAgICBpZiAob2xkR2xvYmFscy5oYXNPd25Qcm9wZXJ0eShvbGROYW1lKSkgewogICAgICAgICAgICBuZXdOYW1lID0gYWxpYXNlc1tvbGROYW1lXTsKCiAgICAgICAgICAgIGdsb2JhbFtuZXdOYW1lXSA9IGdsb2JhbFtvbGROYW1lXTsKICAgICAgICAgICAgZ2xvYmFsW29sZE5hbWVdID0gb2xkR2xvYmFsc1tvbGROYW1lXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0sCiAgICAvLyBPcHRpb24gdG8gZW5hYmxlIG9yIGRpc2FibGUgdGhlIGdlbmVyYXRpb24gb2YgZGVmYXVsdCBleHBvcnRzCiAgICBtYWtlRGVmYXVsdEV4cG9ydDogdHJ1ZQogIH07CgogIHZhciByZWdpc3RyeSA9IGRpY3QoKTsKICB2YXIgc2VlbiA9IGRpY3QoKTsKCiAgdmFyIHV1aWQgPSAwOwoKICBmdW5jdGlvbiB1bnN1cHBvcnRlZE1vZHVsZShsZW5ndGgpIHsKICAgIHRocm93IG5ldyBFcnJvcignYW4gdW5zdXBwb3J0ZWQgbW9kdWxlIHdhcyBkZWZpbmVkLCBleHBlY3RlZCBgZGVmaW5lKGlkLCBkZXBzLCBtb2R1bGUpYCBpbnN0ZWFkIGdvdDogYCcgKyBsZW5ndGggKyAnYCBhcmd1bWVudHMgdG8gZGVmaW5lYCcpOwogIH0KCiAgdmFyIGRlZmF1bHREZXBzID0gWydyZXF1aXJlJywgJ2V4cG9ydHMnLCAnbW9kdWxlJ107CgogIGZ1bmN0aW9uIE1vZHVsZShpZCwgZGVwcywgY2FsbGJhY2ssIGFsaWFzKSB7CiAgICB0aGlzLnV1aWQgPSB1dWlkKys7CiAgICB0aGlzLmlkID0gaWQ7CiAgICB0aGlzLmRlcHMgPSAhZGVwcy5sZW5ndGggJiYgY2FsbGJhY2subGVuZ3RoID8gZGVmYXVsdERlcHMgOiBkZXBzOwogICAgdGhpcy5tb2R1bGUgPSB7IGV4cG9ydHM6IHt9IH07CiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7CiAgICB0aGlzLmhhc0V4cG9ydHNBc0RlcCA9IGZhbHNlOwogICAgdGhpcy5pc0FsaWFzID0gYWxpYXM7CiAgICB0aGlzLnJlaWZpZWQgPSBuZXcgQXJyYXkoZGVwcy5sZW5ndGgpOwoKICAgIC8qCiAgICAgICBFYWNoIG1vZHVsZSBub3JtYWxseSBwYXNzZXMgdGhyb3VnaCB0aGVzZSBzdGF0ZXMsIGluIG9yZGVyOgogICAgICAgICBuZXcgICAgICAgOiBpbml0aWFsIHN0YXRlCiAgICAgICAgIHBlbmRpbmcgICA6IHRoaXMgbW9kdWxlIGlzIHNjaGVkdWxlZCB0byBiZSBleGVjdXRlZAogICAgICAgICByZWlmeWluZyAgOiB0aGlzIG1vZHVsZSdzIGRlcGVuZGVuY2llcyBhcmUgYmVpbmcgZXhlY3V0ZWQKICAgICAgICAgcmVpZmllZCAgIDogdGhpcyBtb2R1bGUncyBkZXBlbmRlbmNpZXMgZmluaXNoZWQgZXhlY3V0aW5nIHN1Y2Nlc3NmdWxseQogICAgICAgICBlcnJvcmVkICAgOiB0aGlzIG1vZHVsZSdzIGRlcGVuZGVuY2llcyBmYWlsZWQgdG8gZXhlY3V0ZQogICAgICAgICBmaW5hbGl6ZWQgOiB0aGlzIG1vZHVsZSBleGVjdXRlZCBzdWNjZXNzZnVsbHkKICAgICAqLwogICAgdGhpcy5zdGF0ZSA9ICduZXcnOwogIH0KCiAgTW9kdWxlLnByb3RvdHlwZS5tYWtlRGVmYXVsdEV4cG9ydCA9IGZ1bmN0aW9uICgpIHsKICAgIHZhciBleHBvcnRzID0gdGhpcy5tb2R1bGUuZXhwb3J0czsKICAgIGlmIChleHBvcnRzICE9PSBudWxsICYmICh0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIGV4cG9ydHMgPT09ICdmdW5jdGlvbicpICYmIGV4cG9ydHNbJ2RlZmF1bHQnXSA9PT0gdW5kZWZpbmVkICYmIE9iamVjdC5pc0V4dGVuc2libGUoZXhwb3J0cykpIHsKICAgICAgZXhwb3J0c1snZGVmYXVsdCddID0gZXhwb3J0czsKICAgIH0KICB9OwoKICBNb2R1bGUucHJvdG90eXBlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7CiAgICAvLyBpZiBmaW5hbGl6ZWQsIHRoZXJlIGlzIG5vIHdvcmsgdG8gZG8uIElmIHJlaWZ5aW5nLCB0aGVyZSBpcyBhCiAgICAvLyBjaXJjdWxhciBkZXBlbmRlbmN5IHNvIHdlIG11c3QgcmV0dXJuIG91ciAocGFydGlhbCkgZXhwb3J0cy4KICAgIGlmICh0aGlzLnN0YXRlID09PSAnZmluYWxpemVkJyB8fCB0aGlzLnN0YXRlID09PSAncmVpZnlpbmcnKSB7CiAgICAgIHJldHVybiB0aGlzLm1vZHVsZS5leHBvcnRzOwogICAgfQoKCiAgICBpZiAobG9hZGVyLndyYXBNb2R1bGVzKSB7CiAgICAgIHRoaXMuY2FsbGJhY2sgPSBsb2FkZXIud3JhcE1vZHVsZXModGhpcy5pZCwgdGhpcy5jYWxsYmFjayk7CiAgICB9CgogICAgdGhpcy5yZWlmeSgpOwoKICAgIHZhciByZXN1bHQgPSB0aGlzLmNhbGxiYWNrLmFwcGx5KHRoaXMsIHRoaXMucmVpZmllZCk7CiAgICB0aGlzLnJlaWZpZWQubGVuZ3RoID0gMDsKICAgIHRoaXMuc3RhdGUgPSAnZmluYWxpemVkJzsKCiAgICBpZiAoISh0aGlzLmhhc0V4cG9ydHNBc0RlcCAmJiByZXN1bHQgPT09IHVuZGVmaW5lZCkpIHsKICAgICAgdGhpcy5tb2R1bGUuZXhwb3J0cyA9IHJlc3VsdDsKICAgIH0KICAgIGlmIChsb2FkZXIubWFrZURlZmF1bHRFeHBvcnQpIHsKICAgICAgdGhpcy5tYWtlRGVmYXVsdEV4cG9ydCgpOwogICAgfQogICAgcmV0dXJuIHRoaXMubW9kdWxlLmV4cG9ydHM7CiAgfTsKCiAgTW9kdWxlLnByb3RvdHlwZS51bnNlZSA9IGZ1bmN0aW9uICgpIHsKICAgIHRoaXMuc3RhdGUgPSAnbmV3JzsKICAgIHRoaXMubW9kdWxlID0geyBleHBvcnRzOiB7fSB9OwogIH07CgogIE1vZHVsZS5wcm90b3R5cGUucmVpZnkgPSBmdW5jdGlvbiAoKSB7CiAgICBpZiAodGhpcy5zdGF0ZSA9PT0gJ3JlaWZpZWQnKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuc3RhdGUgPSAncmVpZnlpbmcnOwogICAgdHJ5IHsKICAgICAgdGhpcy5yZWlmaWVkID0gdGhpcy5fcmVpZnkoKTsKICAgICAgdGhpcy5zdGF0ZSA9ICdyZWlmaWVkJzsKICAgIH0gZmluYWxseSB7CiAgICAgIGlmICh0aGlzLnN0YXRlID09PSAncmVpZnlpbmcnKSB7CiAgICAgICAgdGhpcy5zdGF0ZSA9ICdlcnJvcmVkJzsKICAgICAgfQogICAgfQogIH07CgogIE1vZHVsZS5wcm90b3R5cGUuX3JlaWZ5ID0gZnVuY3Rpb24gKCkgewogICAgdmFyIHJlaWZpZWQgPSB0aGlzLnJlaWZpZWQuc2xpY2UoKTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVpZmllZC5sZW5ndGg7IGkrKykgewogICAgICB2YXIgbW9kID0gcmVpZmllZFtpXTsKICAgICAgcmVpZmllZFtpXSA9IG1vZC5leHBvcnRzID8gbW9kLmV4cG9ydHMgOiBtb2QubW9kdWxlLmV4cG9ydHMoKTsKICAgIH0KICAgIHJldHVybiByZWlmaWVkOwogIH07CgogIE1vZHVsZS5wcm90b3R5cGUuZmluZERlcHMgPSBmdW5jdGlvbiAocGVuZGluZykgewogICAgaWYgKHRoaXMuc3RhdGUgIT09ICduZXcnKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB0aGlzLnN0YXRlID0gJ3BlbmRpbmcnOwoKICAgIHZhciBkZXBzID0gdGhpcy5kZXBzOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVwcy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgZGVwID0gZGVwc1tpXTsKICAgICAgdmFyIGVudHJ5ID0gdGhpcy5yZWlmaWVkW2ldID0geyBleHBvcnRzOiB1bmRlZmluZWQsIG1vZHVsZTogdW5kZWZpbmVkIH07CiAgICAgIGlmIChkZXAgPT09ICdleHBvcnRzJykgewogICAgICAgIHRoaXMuaGFzRXhwb3J0c0FzRGVwID0gdHJ1ZTsKICAgICAgICBlbnRyeS5leHBvcnRzID0gdGhpcy5tb2R1bGUuZXhwb3J0czsKICAgICAgfSBlbHNlIGlmIChkZXAgPT09ICdyZXF1aXJlJykgewogICAgICAgIGVudHJ5LmV4cG9ydHMgPSB0aGlzLm1ha2VSZXF1aXJlKCk7CiAgICAgIH0gZWxzZSBpZiAoZGVwID09PSAnbW9kdWxlJykgewogICAgICAgIGVudHJ5LmV4cG9ydHMgPSB0aGlzLm1vZHVsZTsKICAgICAgfSBlbHNlIHsKICAgICAgICBlbnRyeS5tb2R1bGUgPSBmaW5kTW9kdWxlKHJlc29sdmUoZGVwLCB0aGlzLmlkKSwgdGhpcy5pZCwgcGVuZGluZyk7CiAgICAgIH0KICAgIH0KICB9OwoKICBNb2R1bGUucHJvdG90eXBlLm1ha2VSZXF1aXJlID0gZnVuY3Rpb24gKCkgewogICAgdmFyIGlkID0gdGhpcy5pZDsKICAgIHZhciByID0gZnVuY3Rpb24gKGRlcCkgewogICAgICByZXR1cm4gcmVxdWlyZShyZXNvbHZlKGRlcCwgaWQpKTsKICAgIH07CiAgICByWydkZWZhdWx0J10gPSByOwogICAgci5tb2R1bGVJZCA9IGlkOwogICAgci5oYXMgPSBmdW5jdGlvbiAoZGVwKSB7CiAgICAgIHJldHVybiBoYXMocmVzb2x2ZShkZXAsIGlkKSk7CiAgICB9OwogICAgcmV0dXJuIHI7CiAgfTsKCiAgZGVmaW5lID0gZnVuY3Rpb24gKGlkLCBkZXBzLCBjYWxsYmFjaykgewogICAgdmFyIG1vZHVsZSA9IHJlZ2lzdHJ5W2lkXTsKCiAgICAvLyBJZiBhIG1vZHVsZSBmb3IgdGhpcyBpZCBoYXMgYWxyZWFkeSBiZWVuIGRlZmluZWQgYW5kIGlzIGluIGFueSBzdGF0ZQogICAgLy8gb3RoZXIgdGhhbiBgbmV3YCAobWVhbmluZyBpdCBoYXMgYmVlbiBvciBpcyBjdXJyZW50bHkgYmVpbmcgcmVxdWlyZWQpLAogICAgLy8gdGhlbiB3ZSByZXR1cm4gZWFybHkgdG8gYXZvaWQgcmVkZWZpbml0aW9uLgogICAgaWYgKG1vZHVsZSAmJiBtb2R1bGUuc3RhdGUgIT09ICduZXcnKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHsKICAgICAgdW5zdXBwb3J0ZWRNb2R1bGUoYXJndW1lbnRzLmxlbmd0aCk7CiAgICB9CgogICAgaWYgKCFBcnJheS5pc0FycmF5KGRlcHMpKSB7CiAgICAgIGNhbGxiYWNrID0gZGVwczsKICAgICAgZGVwcyA9IFtdOwogICAgfQoKICAgIGlmIChjYWxsYmFjayBpbnN0YW5jZW9mIEFsaWFzKSB7CiAgICAgIHJlZ2lzdHJ5W2lkXSA9IG5ldyBNb2R1bGUoY2FsbGJhY2suaWQsIGRlcHMsIGNhbGxiYWNrLCB0cnVlKTsKICAgIH0gZWxzZSB7CiAgICAgIHJlZ2lzdHJ5W2lkXSA9IG5ldyBNb2R1bGUoaWQsIGRlcHMsIGNhbGxiYWNrLCBmYWxzZSk7CiAgICB9CiAgfTsKCiAgZGVmaW5lLmV4cG9ydHMgPSBmdW5jdGlvbiAobmFtZSwgZGVmYXVsdEV4cG9ydCkgewogICAgdmFyIG1vZHVsZSA9IHJlZ2lzdHJ5W25hbWVdOwoKICAgIC8vIElmIGEgbW9kdWxlIGZvciB0aGlzIG5hbWUgaGFzIGFscmVhZHkgYmVlbiBkZWZpbmVkIGFuZCBpcyBpbiBhbnkgc3RhdGUKICAgIC8vIG90aGVyIHRoYW4gYG5ld2AgKG1lYW5pbmcgaXQgaGFzIGJlZW4gb3IgaXMgY3VycmVudGx5IGJlaW5nIHJlcXVpcmVkKSwKICAgIC8vIHRoZW4gd2UgcmV0dXJuIGVhcmx5IHRvIGF2b2lkIHJlZGVmaW5pdGlvbi4KICAgIGlmIChtb2R1bGUgJiYgbW9kdWxlLnN0YXRlICE9PSAnbmV3JykgewogICAgICByZXR1cm47CiAgICB9CgogICAgbW9kdWxlID0gbmV3IE1vZHVsZShuYW1lLCBbXSwgbm9vcCwgbnVsbCk7CiAgICBtb2R1bGUubW9kdWxlLmV4cG9ydHMgPSBkZWZhdWx0RXhwb3J0OwogICAgbW9kdWxlLnN0YXRlID0gJ2ZpbmFsaXplZCc7CiAgICByZWdpc3RyeVtuYW1lXSA9IG1vZHVsZTsKCiAgICByZXR1cm4gbW9kdWxlOwogIH07CgogIGZ1bmN0aW9uIG5vb3AoKSB7fQogIC8vIHdlIGRvbid0IHN1cHBvcnQgYWxsIG9mIEFNRAogIC8vIGRlZmluZS5hbWQgPSB7fTsKCiAgZnVuY3Rpb24gQWxpYXMoaWQpIHsKICAgIHRoaXMuaWQgPSBpZDsKICB9CgogIGRlZmluZS5hbGlhcyA9IGZ1bmN0aW9uIChpZCwgdGFyZ2V0KSB7CiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgewogICAgICByZXR1cm4gZGVmaW5lKHRhcmdldCwgbmV3IEFsaWFzKGlkKSk7CiAgICB9CgogICAgcmV0dXJuIG5ldyBBbGlhcyhpZCk7CiAgfTsKCiAgZnVuY3Rpb24gbWlzc2luZ01vZHVsZShpZCwgcmVmZXJyZXIpIHsKICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGZpbmQgbW9kdWxlIGAnICsgaWQgKyAnYCBpbXBvcnRlZCBmcm9tIGAnICsgcmVmZXJyZXIgKyAnYCcpOwogIH0KCiAgZnVuY3Rpb24gZmluZE1vZHVsZShpZCwgcmVmZXJyZXIsIHBlbmRpbmcpIHsKICAgIHZhciBtb2QgPSByZWdpc3RyeVtpZF0gfHwgcmVnaXN0cnlbaWQgKyAnL2luZGV4J107CgogICAgd2hpbGUgKG1vZCAmJiBtb2QuaXNBbGlhcykgewogICAgICBtb2QgPSByZWdpc3RyeVttb2QuaWRdIHx8IHJlZ2lzdHJ5W21vZC5pZCArICcvaW5kZXgnXTsKICAgIH0KCiAgICBpZiAoIW1vZCkgewogICAgICBtaXNzaW5nTW9kdWxlKGlkLCByZWZlcnJlcik7CiAgICB9CgogICAgaWYgKHBlbmRpbmcgJiYgbW9kLnN0YXRlICE9PSAncGVuZGluZycgJiYgbW9kLnN0YXRlICE9PSAnZmluYWxpemVkJykgewogICAgICBtb2QuZmluZERlcHMocGVuZGluZyk7CiAgICAgIHBlbmRpbmcucHVzaChtb2QpOwogICAgfQogICAgcmV0dXJuIG1vZDsKICB9CgogIGZ1bmN0aW9uIHJlc29sdmUoY2hpbGQsIGlkKSB7CiAgICBpZiAoY2hpbGQuY2hhckF0KDApICE9PSAnLicpIHsKICAgICAgcmV0dXJuIGNoaWxkOwogICAgfQoKCiAgICB2YXIgcGFydHMgPSBjaGlsZC5zcGxpdCgnLycpOwogICAgdmFyIG5hbWVQYXJ0cyA9IGlkLnNwbGl0KCcvJyk7CiAgICB2YXIgcGFyZW50QmFzZSA9IG5hbWVQYXJ0cy5zbGljZSgwLCAtMSk7CgogICAgZm9yICh2YXIgaSA9IDAsIGwgPSBwYXJ0cy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgdmFyIHBhcnQgPSBwYXJ0c1tpXTsKCiAgICAgIGlmIChwYXJ0ID09PSAnLi4nKSB7CiAgICAgICAgaWYgKHBhcmVudEJhc2UubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBhY2Nlc3MgcGFyZW50IG1vZHVsZSBvZiByb290Jyk7CiAgICAgICAgfQogICAgICAgIHBhcmVudEJhc2UucG9wKCk7CiAgICAgIH0gZWxzZSBpZiAocGFydCA9PT0gJy4nKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcGFyZW50QmFzZS5wdXNoKHBhcnQpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHBhcmVudEJhc2Uuam9pbignLycpOwogIH0KCiAgZnVuY3Rpb24gaGFzKGlkKSB7CiAgICByZXR1cm4gISEocmVnaXN0cnlbaWRdIHx8IHJlZ2lzdHJ5W2lkICsgJy9pbmRleCddKTsKICB9CgogIHJlcXVpcmVqcy5lbnRyaWVzID0gcmVxdWlyZWpzLl9lYWtfc2VlbiA9IHJlZ2lzdHJ5OwogIHJlcXVpcmVqcy5oYXMgPSBoYXM7CiAgcmVxdWlyZWpzLnVuc2VlID0gZnVuY3Rpb24gKGlkKSB7CiAgICBmaW5kTW9kdWxlKGlkLCAnKHVuc2VlKScsIGZhbHNlKS51bnNlZSgpOwogIH07CgogIHJlcXVpcmVqcy5jbGVhciA9IGZ1bmN0aW9uICgpIHsKICAgIHJlcXVpcmVqcy5lbnRyaWVzID0gcmVxdWlyZWpzLl9lYWtfc2VlbiA9IHJlZ2lzdHJ5ID0gZGljdCgpOwogICAgc2VlbiA9IGRpY3QoKTsKICB9OwoKICAvLyBUaGlzIGNvZGUgcHJpbWVzIHRoZSBKUyBlbmdpbmUgZm9yIGdvb2QgcGVyZm9ybWFuY2UgYnkgd2FybWluZyB0aGUKICAvLyBKSVQgY29tcGlsZXIgZm9yIHRoZXNlIGZ1bmN0aW9ucy4KICBkZWZpbmUoJ2ZvbycsIGZ1bmN0aW9uICgpIHt9KTsKICBkZWZpbmUoJ2Zvby9iYXInLCBbXSwgZnVuY3Rpb24gKCkge30pOwogIGRlZmluZSgnZm9vL2FzZGYnLCBbJ21vZHVsZScsICdleHBvcnRzJywgJ3JlcXVpcmUnXSwgZnVuY3Rpb24gKG1vZHVsZSwgZXhwb3J0cywgcmVxdWlyZSkgewogICAgaWYgKHJlcXVpcmUuaGFzKCdmb28vYmFyJykpIHsKICAgICAgcmVxdWlyZSgnZm9vL2JhcicpOwogICAgfQogIH0pOwogIGRlZmluZSgnZm9vL2JheicsIFtdLCBkZWZpbmUuYWxpYXMoJ2ZvbycpKTsKICBkZWZpbmUoJ2Zvby9xdXonLCBkZWZpbmUuYWxpYXMoJ2ZvbycpKTsKICBkZWZpbmUuYWxpYXMoJ2ZvbycsICdmb28vcXV4Jyk7CiAgZGVmaW5lKCdmb28vYmFyJywgWydmb28nLCAnLi9xdXonLCAnLi9iYXonLCAnLi9hc2RmJywgJy4vYmFyJywgJy4uL2ZvbyddLCBmdW5jdGlvbiAoKSB7fSk7CiAgZGVmaW5lKCdmb28vbWFpbicsIFsnZm9vL2JhciddLCBmdW5jdGlvbiAoKSB7fSk7CiAgZGVmaW5lLmV4cG9ydHMoJ2Zvby9leHBvcnRzJywge30pOwoKICByZXF1aXJlKCdmb28vZXhwb3J0cycpOwogIHJlcXVpcmUoJ2Zvby9tYWluJyk7CiAgcmVxdWlyZS51bnNlZSgnZm9vL2JhcicpOwoKICByZXF1aXJlanMuY2xlYXIoKTsKCiAgaWYgKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cykgewogICAgbW9kdWxlLmV4cG9ydHMgPSB7IHJlcXVpcmU6IHJlcXVpcmUsIGRlZmluZTogZGVmaW5lIH07CiAgfQp9KSh0aGlzKTsKOy8qKgogKiBDb3B5cmlnaHQgKGMpIDIwMTQsIEZhY2Vib29rLCBJbmMuCiAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiAqCiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIEJTRC1zdHlsZSBsaWNlbnNlIGZvdW5kIGluIHRoZQogKiBodHRwczovL3Jhdy5naXRodWIuY29tL2ZhY2Vib29rL3JlZ2VuZXJhdG9yL21hc3Rlci9MSUNFTlNFIGZpbGUuIEFuCiAqIGFkZGl0aW9uYWwgZ3JhbnQgb2YgcGF0ZW50IHJpZ2h0cyBjYW4gYmUgZm91bmQgaW4gdGhlIFBBVEVOVFMgZmlsZSBpbgogKiB0aGUgc2FtZSBkaXJlY3RvcnkuCiAqLwoKIShmdW5jdGlvbihnbG9iYWwpIHsKICAidXNlIHN0cmljdCI7CgogIHZhciBoYXNPd24gPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5OwogIHZhciB1bmRlZmluZWQ7IC8vIE1vcmUgY29tcHJlc3NpYmxlIHRoYW4gdm9pZCAwLgogIHZhciAkU3ltYm9sID0gdHlwZW9mIFN5bWJvbCA9PT0gImZ1bmN0aW9uIiA/IFN5bWJvbCA6IHt9OwogIHZhciBpdGVyYXRvclN5bWJvbCA9ICRTeW1ib2wuaXRlcmF0b3IgfHwgIkBAaXRlcmF0b3IiOwogIHZhciB0b1N0cmluZ1RhZ1N5bWJvbCA9ICRTeW1ib2wudG9TdHJpbmdUYWcgfHwgIkBAdG9TdHJpbmdUYWciOwoKICB2YXIgaW5Nb2R1bGUgPSB0eXBlb2YgbW9kdWxlID09PSAib2JqZWN0IjsKICB2YXIgcnVudGltZSA9IGdsb2JhbC5yZWdlbmVyYXRvclJ1bnRpbWU7CiAgaWYgKHJ1bnRpbWUpIHsKICAgIGlmIChpbk1vZHVsZSkgewogICAgICAvLyBJZiByZWdlbmVyYXRvclJ1bnRpbWUgaXMgZGVmaW5lZCBnbG9iYWxseSBhbmQgd2UncmUgaW4gYSBtb2R1bGUsCiAgICAgIC8vIG1ha2UgdGhlIGV4cG9ydHMgb2JqZWN0IGlkZW50aWNhbCB0byByZWdlbmVyYXRvclJ1bnRpbWUuCiAgICAgIG1vZHVsZS5leHBvcnRzID0gcnVudGltZTsKICAgIH0KICAgIC8vIERvbid0IGJvdGhlciBldmFsdWF0aW5nIHRoZSByZXN0IG9mIHRoaXMgZmlsZSBpZiB0aGUgcnVudGltZSB3YXMKICAgIC8vIGFscmVhZHkgZGVmaW5lZCBnbG9iYWxseS4KICAgIHJldHVybjsKICB9CgogIC8vIERlZmluZSB0aGUgcnVudGltZSBnbG9iYWxseSAoYXMgZXhwZWN0ZWQgYnkgZ2VuZXJhdGVkIGNvZGUpIGFzIGVpdGhlcgogIC8vIG1vZHVsZS5leHBvcnRzIChpZiB3ZSdyZSBpbiBhIG1vZHVsZSkgb3IgYSBuZXcsIGVtcHR5IG9iamVjdC4KICBydW50aW1lID0gZ2xvYmFsLnJlZ2VuZXJhdG9yUnVudGltZSA9IGluTW9kdWxlID8gbW9kdWxlLmV4cG9ydHMgOiB7fTsKCiAgZnVuY3Rpb24gd3JhcChpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCkgewogICAgLy8gSWYgb3V0ZXJGbiBwcm92aWRlZCBhbmQgb3V0ZXJGbi5wcm90b3R5cGUgaXMgYSBHZW5lcmF0b3IsIHRoZW4gb3V0ZXJGbi5wcm90b3R5cGUgaW5zdGFuY2VvZiBHZW5lcmF0b3IuCiAgICB2YXIgcHJvdG9HZW5lcmF0b3IgPSBvdXRlckZuICYmIG91dGVyRm4ucHJvdG90eXBlIGluc3RhbmNlb2YgR2VuZXJhdG9yID8gb3V0ZXJGbiA6IEdlbmVyYXRvcjsKICAgIHZhciBnZW5lcmF0b3IgPSBPYmplY3QuY3JlYXRlKHByb3RvR2VuZXJhdG9yLnByb3RvdHlwZSk7CiAgICB2YXIgY29udGV4dCA9IG5ldyBDb250ZXh0KHRyeUxvY3NMaXN0IHx8IFtdKTsKCiAgICAvLyBUaGUgLl9pbnZva2UgbWV0aG9kIHVuaWZpZXMgdGhlIGltcGxlbWVudGF0aW9ucyBvZiB0aGUgLm5leHQsCiAgICAvLyAudGhyb3csIGFuZCAucmV0dXJuIG1ldGhvZHMuCiAgICBnZW5lcmF0b3IuX2ludm9rZSA9IG1ha2VJbnZva2VNZXRob2QoaW5uZXJGbiwgc2VsZiwgY29udGV4dCk7CgogICAgcmV0dXJuIGdlbmVyYXRvcjsKICB9CiAgcnVudGltZS53cmFwID0gd3JhcDsKCiAgLy8gVHJ5L2NhdGNoIGhlbHBlciB0byBtaW5pbWl6ZSBkZW9wdGltaXphdGlvbnMuIFJldHVybnMgYSBjb21wbGV0aW9uCiAgLy8gcmVjb3JkIGxpa2UgY29udGV4dC50cnlFbnRyaWVzW2ldLmNvbXBsZXRpb24uIFRoaXMgaW50ZXJmYWNlIGNvdWxkCiAgLy8gaGF2ZSBiZWVuIChhbmQgd2FzIHByZXZpb3VzbHkpIGRlc2lnbmVkIHRvIHRha2UgYSBjbG9zdXJlIHRvIGJlCiAgLy8gaW52b2tlZCB3aXRob3V0IGFyZ3VtZW50cywgYnV0IGluIGFsbCB0aGUgY2FzZXMgd2UgY2FyZSBhYm91dCB3ZQogIC8vIGFscmVhZHkgaGF2ZSBhbiBleGlzdGluZyBtZXRob2Qgd2Ugd2FudCB0byBjYWxsLCBzbyB0aGVyZSdzIG5vIG5lZWQKICAvLyB0byBjcmVhdGUgYSBuZXcgZnVuY3Rpb24gb2JqZWN0LiBXZSBjYW4gZXZlbiBnZXQgYXdheSB3aXRoIGFzc3VtaW5nCiAgLy8gdGhlIG1ldGhvZCB0YWtlcyBleGFjdGx5IG9uZSBhcmd1bWVudCwgc2luY2UgdGhhdCBoYXBwZW5zIHRvIGJlIHRydWUKICAvLyBpbiBldmVyeSBjYXNlLCBzbyB3ZSBkb24ndCBoYXZlIHRvIHRvdWNoIHRoZSBhcmd1bWVudHMgb2JqZWN0LiBUaGUKICAvLyBvbmx5IGFkZGl0aW9uYWwgYWxsb2NhdGlvbiByZXF1aXJlZCBpcyB0aGUgY29tcGxldGlvbiByZWNvcmQsIHdoaWNoCiAgLy8gaGFzIGEgc3RhYmxlIHNoYXBlIGFuZCBzbyBob3BlZnVsbHkgc2hvdWxkIGJlIGNoZWFwIHRvIGFsbG9jYXRlLgogIGZ1bmN0aW9uIHRyeUNhdGNoKGZuLCBvYmosIGFyZykgewogICAgdHJ5IHsKICAgICAgcmV0dXJuIHsgdHlwZTogIm5vcm1hbCIsIGFyZzogZm4uY2FsbChvYmosIGFyZykgfTsKICAgIH0gY2F0Y2ggKGVycikgewogICAgICByZXR1cm4geyB0eXBlOiAidGhyb3ciLCBhcmc6IGVyciB9OwogICAgfQogIH0KCiAgdmFyIEdlblN0YXRlU3VzcGVuZGVkU3RhcnQgPSAic3VzcGVuZGVkU3RhcnQiOwogIHZhciBHZW5TdGF0ZVN1c3BlbmRlZFlpZWxkID0gInN1c3BlbmRlZFlpZWxkIjsKICB2YXIgR2VuU3RhdGVFeGVjdXRpbmcgPSAiZXhlY3V0aW5nIjsKICB2YXIgR2VuU3RhdGVDb21wbGV0ZWQgPSAiY29tcGxldGVkIjsKCiAgLy8gUmV0dXJuaW5nIHRoaXMgb2JqZWN0IGZyb20gdGhlIGlubmVyRm4gaGFzIHRoZSBzYW1lIGVmZmVjdCBhcwogIC8vIGJyZWFraW5nIG91dCBvZiB0aGUgZGlzcGF0Y2ggc3dpdGNoIHN0YXRlbWVudC4KICB2YXIgQ29udGludWVTZW50aW5lbCA9IHt9OwoKICAvLyBEdW1teSBjb25zdHJ1Y3RvciBmdW5jdGlvbnMgdGhhdCB3ZSB1c2UgYXMgdGhlIC5jb25zdHJ1Y3RvciBhbmQKICAvLyAuY29uc3RydWN0b3IucHJvdG90eXBlIHByb3BlcnRpZXMgZm9yIGZ1bmN0aW9ucyB0aGF0IHJldHVybiBHZW5lcmF0b3IKICAvLyBvYmplY3RzLiBGb3IgZnVsbCBzcGVjIGNvbXBsaWFuY2UsIHlvdSBtYXkgd2lzaCB0byBjb25maWd1cmUgeW91cgogIC8vIG1pbmlmaWVyIG5vdCB0byBtYW5nbGUgdGhlIG5hbWVzIG9mIHRoZXNlIHR3byBmdW5jdGlvbnMuCiAgZnVuY3Rpb24gR2VuZXJhdG9yKCkge30KICBmdW5jdGlvbiBHZW5lcmF0b3JGdW5jdGlvbigpIHt9CiAgZnVuY3Rpb24gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUoKSB7fQoKICB2YXIgR3AgPSBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZS5wcm90b3R5cGUgPSBHZW5lcmF0b3IucHJvdG90eXBlOwogIEdlbmVyYXRvckZ1bmN0aW9uLnByb3RvdHlwZSA9IEdwLmNvbnN0cnVjdG9yID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGU7CiAgR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUuY29uc3RydWN0b3IgPSBHZW5lcmF0b3JGdW5jdGlvbjsKICBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZVt0b1N0cmluZ1RhZ1N5bWJvbF0gPSBHZW5lcmF0b3JGdW5jdGlvbi5kaXNwbGF5TmFtZSA9ICJHZW5lcmF0b3JGdW5jdGlvbiI7CgogIC8vIEhlbHBlciBmb3IgZGVmaW5pbmcgdGhlIC5uZXh0LCAudGhyb3csIGFuZCAucmV0dXJuIG1ldGhvZHMgb2YgdGhlCiAgLy8gSXRlcmF0b3IgaW50ZXJmYWNlIGluIHRlcm1zIG9mIGEgc2luZ2xlIC5faW52b2tlIG1ldGhvZC4KICBmdW5jdGlvbiBkZWZpbmVJdGVyYXRvck1ldGhvZHMocHJvdG90eXBlKSB7CiAgICBbIm5leHQiLCAidGhyb3ciLCAicmV0dXJuIl0uZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHsKICAgICAgcHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbihhcmcpIHsKICAgICAgICByZXR1cm4gdGhpcy5faW52b2tlKG1ldGhvZCwgYXJnKTsKICAgICAgfTsKICAgIH0pOwogIH0KCiAgcnVudGltZS5pc0dlbmVyYXRvckZ1bmN0aW9uID0gZnVuY3Rpb24oZ2VuRnVuKSB7CiAgICB2YXIgY3RvciA9IHR5cGVvZiBnZW5GdW4gPT09ICJmdW5jdGlvbiIgJiYgZ2VuRnVuLmNvbnN0cnVjdG9yOwogICAgcmV0dXJuIGN0b3IKICAgICAgPyBjdG9yID09PSBHZW5lcmF0b3JGdW5jdGlvbiB8fAogICAgICAgIC8vIEZvciB0aGUgbmF0aXZlIEdlbmVyYXRvckZ1bmN0aW9uIGNvbnN0cnVjdG9yLCB0aGUgYmVzdCB3ZSBjYW4KICAgICAgICAvLyBkbyBpcyB0byBjaGVjayBpdHMgLm5hbWUgcHJvcGVydHkuCiAgICAgICAgKGN0b3IuZGlzcGxheU5hbWUgfHwgY3Rvci5uYW1lKSA9PT0gIkdlbmVyYXRvckZ1bmN0aW9uIgogICAgICA6IGZhbHNlOwogIH07CgogIHJ1bnRpbWUubWFyayA9IGZ1bmN0aW9uKGdlbkZ1bikgewogICAgaWYgKE9iamVjdC5zZXRQcm90b3R5cGVPZikgewogICAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YoZ2VuRnVuLCBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSk7CiAgICB9IGVsc2UgewogICAgICBnZW5GdW4uX19wcm90b19fID0gR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGU7CiAgICAgIGlmICghKHRvU3RyaW5nVGFnU3ltYm9sIGluIGdlbkZ1bikpIHsKICAgICAgICBnZW5GdW5bdG9TdHJpbmdUYWdTeW1ib2xdID0gIkdlbmVyYXRvckZ1bmN0aW9uIjsKICAgICAgfQogICAgfQogICAgZ2VuRnVuLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoR3ApOwogICAgcmV0dXJuIGdlbkZ1bjsKICB9OwoKICAvLyBXaXRoaW4gdGhlIGJvZHkgb2YgYW55IGFzeW5jIGZ1bmN0aW9uLCBgYXdhaXQgeGAgaXMgdHJhbnNmb3JtZWQgdG8KICAvLyBgeWllbGQgcmVnZW5lcmF0b3JSdW50aW1lLmF3cmFwKHgpYCwgc28gdGhhdCB0aGUgcnVudGltZSBjYW4gdGVzdAogIC8vIGB2YWx1ZSBpbnN0YW5jZW9mIEF3YWl0QXJndW1lbnRgIHRvIGRldGVybWluZSBpZiB0aGUgeWllbGRlZCB2YWx1ZSBpcwogIC8vIG1lYW50IHRvIGJlIGF3YWl0ZWQuIFNvbWUgbWF5IGNvbnNpZGVyIHRoZSBuYW1lIG9mIHRoaXMgbWV0aG9kIHRvbwogIC8vIGN1dGVzeSwgYnV0IHRoZXkgYXJlIGN1cm11ZGdlb25zLgogIHJ1bnRpbWUuYXdyYXAgPSBmdW5jdGlvbihhcmcpIHsKICAgIHJldHVybiBuZXcgQXdhaXRBcmd1bWVudChhcmcpOwogIH07CgogIGZ1bmN0aW9uIEF3YWl0QXJndW1lbnQoYXJnKSB7CiAgICB0aGlzLmFyZyA9IGFyZzsKICB9CgogIGZ1bmN0aW9uIEFzeW5jSXRlcmF0b3IoZ2VuZXJhdG9yKSB7CiAgICBmdW5jdGlvbiBpbnZva2UobWV0aG9kLCBhcmcsIHJlc29sdmUsIHJlamVjdCkgewogICAgICB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2goZ2VuZXJhdG9yW21ldGhvZF0sIGdlbmVyYXRvciwgYXJnKTsKICAgICAgaWYgKHJlY29yZC50eXBlID09PSAidGhyb3ciKSB7CiAgICAgICAgcmVqZWN0KHJlY29yZC5hcmcpOwogICAgICB9IGVsc2UgewogICAgICAgIHZhciByZXN1bHQgPSByZWNvcmQuYXJnOwogICAgICAgIHZhciB2YWx1ZSA9IHJlc3VsdC52YWx1ZTsKICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBBd2FpdEFyZ3VtZW50KSB7CiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHZhbHVlLmFyZykudGhlbihmdW5jdGlvbih2YWx1ZSkgewogICAgICAgICAgICBpbnZva2UoIm5leHQiLCB2YWx1ZSwgcmVzb2x2ZSwgcmVqZWN0KTsKICAgICAgICAgIH0sIGZ1bmN0aW9uKGVycikgewogICAgICAgICAgICBpbnZva2UoInRocm93IiwgZXJyLCByZXNvbHZlLCByZWplY3QpOwogICAgICAgICAgfSk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHZhbHVlKS50aGVuKGZ1bmN0aW9uKHVud3JhcHBlZCkgewogICAgICAgICAgLy8gV2hlbiBhIHlpZWxkZWQgUHJvbWlzZSBpcyByZXNvbHZlZCwgaXRzIGZpbmFsIHZhbHVlIGJlY29tZXMKICAgICAgICAgIC8vIHRoZSAudmFsdWUgb2YgdGhlIFByb21pc2U8e3ZhbHVlLGRvbmV9PiByZXN1bHQgZm9yIHRoZQogICAgICAgICAgLy8gY3VycmVudCBpdGVyYXRpb24uIElmIHRoZSBQcm9taXNlIGlzIHJlamVjdGVkLCBob3dldmVyLCB0aGUKICAgICAgICAgIC8vIHJlc3VsdCBmb3IgdGhpcyBpdGVyYXRpb24gd2lsbCBiZSByZWplY3RlZCB3aXRoIHRoZSBzYW1lCiAgICAgICAgICAvLyByZWFzb24uIE5vdGUgdGhhdCByZWplY3Rpb25zIG9mIHlpZWxkZWQgUHJvbWlzZXMgYXJlIG5vdAogICAgICAgICAgLy8gdGhyb3duIGJhY2sgaW50byB0aGUgZ2VuZXJhdG9yIGZ1bmN0aW9uLCBhcyBpcyB0aGUgY2FzZQogICAgICAgICAgLy8gd2hlbiBhbiBhd2FpdGVkIFByb21pc2UgaXMgcmVqZWN0ZWQuIFRoaXMgZGlmZmVyZW5jZSBpbgogICAgICAgICAgLy8gYmVoYXZpb3IgYmV0d2VlbiB5aWVsZCBhbmQgYXdhaXQgaXMgaW1wb3J0YW50LCBiZWNhdXNlIGl0CiAgICAgICAgICAvLyBhbGxvd3MgdGhlIGNvbnN1bWVyIHRvIGRlY2lkZSB3aGF0IHRvIGRvIHdpdGggdGhlIHlpZWxkZWQKICAgICAgICAgIC8vIHJlamVjdGlvbiAoc3dhbGxvdyBpdCBhbmQgY29udGludWUsIG1hbnVhbGx5IC50aHJvdyBpdCBiYWNrCiAgICAgICAgICAvLyBpbnRvIHRoZSBnZW5lcmF0b3IsIGFiYW5kb24gaXRlcmF0aW9uLCB3aGF0ZXZlcikuIFdpdGgKICAgICAgICAgIC8vIGF3YWl0LCBieSBjb250cmFzdCwgdGhlcmUgaXMgbm8gb3Bwb3J0dW5pdHkgdG8gZXhhbWluZSB0aGUKICAgICAgICAgIC8vIHJlamVjdGlvbiByZWFzb24gb3V0c2lkZSB0aGUgZ2VuZXJhdG9yIGZ1bmN0aW9uLCBzbyB0aGUKICAgICAgICAgIC8vIG9ubHkgb3B0aW9uIGlzIHRvIHRocm93IGl0IGZyb20gdGhlIGF3YWl0IGV4cHJlc3Npb24sIGFuZAogICAgICAgICAgLy8gbGV0IHRoZSBnZW5lcmF0b3IgZnVuY3Rpb24gaGFuZGxlIHRoZSBleGNlcHRpb24uCiAgICAgICAgICByZXN1bHQudmFsdWUgPSB1bndyYXBwZWQ7CiAgICAgICAgICByZXNvbHZlKHJlc3VsdCk7CiAgICAgICAgfSwgcmVqZWN0KTsKICAgICAgfQogICAgfQoKICAgIGlmICh0eXBlb2YgcHJvY2VzcyA9PT0gIm9iamVjdCIgJiYgcHJvY2Vzcy5kb21haW4pIHsKICAgICAgaW52b2tlID0gcHJvY2Vzcy5kb21haW4uYmluZChpbnZva2UpOwogICAgfQoKICAgIHZhciBwcmV2aW91c1Byb21pc2U7CgogICAgZnVuY3Rpb24gZW5xdWV1ZShtZXRob2QsIGFyZykgewogICAgICBmdW5jdGlvbiBjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZygpIHsKICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7CiAgICAgICAgICBpbnZva2UobWV0aG9kLCBhcmcsIHJlc29sdmUsIHJlamVjdCk7CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBwcmV2aW91c1Byb21pc2UgPQogICAgICAgIC8vIElmIGVucXVldWUgaGFzIGJlZW4gY2FsbGVkIGJlZm9yZSwgdGhlbiB3ZSB3YW50IHRvIHdhaXQgdW50aWwKICAgICAgICAvLyBhbGwgcHJldmlvdXMgUHJvbWlzZXMgaGF2ZSBiZWVuIHJlc29sdmVkIGJlZm9yZSBjYWxsaW5nIGludm9rZSwKICAgICAgICAvLyBzbyB0aGF0IHJlc3VsdHMgYXJlIGFsd2F5cyBkZWxpdmVyZWQgaW4gdGhlIGNvcnJlY3Qgb3JkZXIuIElmCiAgICAgICAgLy8gZW5xdWV1ZSBoYXMgbm90IGJlZW4gY2FsbGVkIGJlZm9yZSwgdGhlbiBpdCBpcyBpbXBvcnRhbnQgdG8KICAgICAgICAvLyBjYWxsIGludm9rZSBpbW1lZGlhdGVseSwgd2l0aG91dCB3YWl0aW5nIG9uIGEgY2FsbGJhY2sgdG8gZmlyZSwKICAgICAgICAvLyBzbyB0aGF0IHRoZSBhc3luYyBnZW5lcmF0b3IgZnVuY3Rpb24gaGFzIHRoZSBvcHBvcnR1bml0eSB0byBkbwogICAgICAgIC8vIGFueSBuZWNlc3Nhcnkgc2V0dXAgaW4gYSBwcmVkaWN0YWJsZSB3YXkuIFRoaXMgcHJlZGljdGFiaWxpdHkKICAgICAgICAvLyBpcyB3aHkgdGhlIFByb21pc2UgY29uc3RydWN0b3Igc3luY2hyb25vdXNseSBpbnZva2VzIGl0cwogICAgICAgIC8vIGV4ZWN1dG9yIGNhbGxiYWNrLCBhbmQgd2h5IGFzeW5jIGZ1bmN0aW9ucyBzeW5jaHJvbm91c2x5CiAgICAgICAgLy8gZXhlY3V0ZSBjb2RlIGJlZm9yZSB0aGUgZmlyc3QgYXdhaXQuIFNpbmNlIHdlIGltcGxlbWVudCBzaW1wbGUKICAgICAgICAvLyBhc3luYyBmdW5jdGlvbnMgaW4gdGVybXMgb2YgYXN5bmMgZ2VuZXJhdG9ycywgaXQgaXMgZXNwZWNpYWxseQogICAgICAgIC8vIGltcG9ydGFudCB0byBnZXQgdGhpcyByaWdodCwgZXZlbiB0aG91Z2ggaXQgcmVxdWlyZXMgY2FyZS4KICAgICAgICBwcmV2aW91c1Byb21pc2UgPyBwcmV2aW91c1Byb21pc2UudGhlbigKICAgICAgICAgIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnLAogICAgICAgICAgLy8gQXZvaWQgcHJvcGFnYXRpbmcgZmFpbHVyZXMgdG8gUHJvbWlzZXMgcmV0dXJuZWQgYnkgbGF0ZXIKICAgICAgICAgIC8vIGludm9jYXRpb25zIG9mIHRoZSBpdGVyYXRvci4KICAgICAgICAgIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnCiAgICAgICAgKSA6IGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKCk7CiAgICB9CgogICAgLy8gRGVmaW5lIHRoZSB1bmlmaWVkIGhlbHBlciBtZXRob2QgdGhhdCBpcyB1c2VkIHRvIGltcGxlbWVudCAubmV4dCwKICAgIC8vIC50aHJvdywgYW5kIC5yZXR1cm4gKHNlZSBkZWZpbmVJdGVyYXRvck1ldGhvZHMpLgogICAgdGhpcy5faW52b2tlID0gZW5xdWV1ZTsKICB9CgogIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhBc3luY0l0ZXJhdG9yLnByb3RvdHlwZSk7CgogIC8vIE5vdGUgdGhhdCBzaW1wbGUgYXN5bmMgZnVuY3Rpb25zIGFyZSBpbXBsZW1lbnRlZCBvbiB0b3Agb2YKICAvLyBBc3luY0l0ZXJhdG9yIG9iamVjdHM7IHRoZXkganVzdCByZXR1cm4gYSBQcm9taXNlIGZvciB0aGUgdmFsdWUgb2YKICAvLyB0aGUgZmluYWwgcmVzdWx0IHByb2R1Y2VkIGJ5IHRoZSBpdGVyYXRvci4KICBydW50aW1lLmFzeW5jID0gZnVuY3Rpb24oaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpIHsKICAgIHZhciBpdGVyID0gbmV3IEFzeW5jSXRlcmF0b3IoCiAgICAgIHdyYXAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpCiAgICApOwoKICAgIHJldHVybiBydW50aW1lLmlzR2VuZXJhdG9yRnVuY3Rpb24ob3V0ZXJGbikKICAgICAgPyBpdGVyIC8vIElmIG91dGVyRm4gaXMgYSBnZW5lcmF0b3IsIHJldHVybiB0aGUgZnVsbCBpdGVyYXRvci4KICAgICAgOiBpdGVyLm5leHQoKS50aGVuKGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAgICAgcmV0dXJuIHJlc3VsdC5kb25lID8gcmVzdWx0LnZhbHVlIDogaXRlci5uZXh0KCk7CiAgICAgICAgfSk7CiAgfTsKCiAgZnVuY3Rpb24gbWFrZUludm9rZU1ldGhvZChpbm5lckZuLCBzZWxmLCBjb250ZXh0KSB7CiAgICB2YXIgc3RhdGUgPSBHZW5TdGF0ZVN1c3BlbmRlZFN0YXJ0OwoKICAgIHJldHVybiBmdW5jdGlvbiBpbnZva2UobWV0aG9kLCBhcmcpIHsKICAgICAgaWYgKHN0YXRlID09PSBHZW5TdGF0ZUV4ZWN1dGluZykgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiR2VuZXJhdG9yIGlzIGFscmVhZHkgcnVubmluZyIpOwogICAgICB9CgogICAgICBpZiAoc3RhdGUgPT09IEdlblN0YXRlQ29tcGxldGVkKSB7CiAgICAgICAgaWYgKG1ldGhvZCA9PT0gInRocm93IikgewogICAgICAgICAgdGhyb3cgYXJnOwogICAgICAgIH0KCiAgICAgICAgLy8gQmUgZm9yZ2l2aW5nLCBwZXIgMjUuMy4zLjMuMyBvZiB0aGUgc3BlYzoKICAgICAgICAvLyBodHRwczovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtZ2VuZXJhdG9ycmVzdW1lCiAgICAgICAgcmV0dXJuIGRvbmVSZXN1bHQoKTsKICAgICAgfQoKICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICB2YXIgZGVsZWdhdGUgPSBjb250ZXh0LmRlbGVnYXRlOwogICAgICAgIGlmIChkZWxlZ2F0ZSkgewogICAgICAgICAgaWYgKG1ldGhvZCA9PT0gInJldHVybiIgfHwKICAgICAgICAgICAgICAobWV0aG9kID09PSAidGhyb3ciICYmIGRlbGVnYXRlLml0ZXJhdG9yW21ldGhvZF0gPT09IHVuZGVmaW5lZCkpIHsKICAgICAgICAgICAgLy8gQSByZXR1cm4gb3IgdGhyb3cgKHdoZW4gdGhlIGRlbGVnYXRlIGl0ZXJhdG9yIGhhcyBubyB0aHJvdwogICAgICAgICAgICAvLyBtZXRob2QpIGFsd2F5cyB0ZXJtaW5hdGVzIHRoZSB5aWVsZCogbG9vcC4KICAgICAgICAgICAgY29udGV4dC5kZWxlZ2F0ZSA9IG51bGw7CgogICAgICAgICAgICAvLyBJZiB0aGUgZGVsZWdhdGUgaXRlcmF0b3IgaGFzIGEgcmV0dXJuIG1ldGhvZCwgZ2l2ZSBpdCBhCiAgICAgICAgICAgIC8vIGNoYW5jZSB0byBjbGVhbiB1cC4KICAgICAgICAgICAgdmFyIHJldHVybk1ldGhvZCA9IGRlbGVnYXRlLml0ZXJhdG9yWyJyZXR1cm4iXTsKICAgICAgICAgICAgaWYgKHJldHVybk1ldGhvZCkgewogICAgICAgICAgICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChyZXR1cm5NZXRob2QsIGRlbGVnYXRlLml0ZXJhdG9yLCBhcmcpOwogICAgICAgICAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgICAgICAgICAgLy8gSWYgdGhlIHJldHVybiBtZXRob2QgdGhyZXcgYW4gZXhjZXB0aW9uLCBsZXQgdGhhdAogICAgICAgICAgICAgICAgLy8gZXhjZXB0aW9uIHByZXZhaWwgb3ZlciB0aGUgb3JpZ2luYWwgcmV0dXJuIG9yIHRocm93LgogICAgICAgICAgICAgICAgbWV0aG9kID0gInRocm93IjsKICAgICAgICAgICAgICAgIGFyZyA9IHJlY29yZC5hcmc7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChtZXRob2QgPT09ICJyZXR1cm4iKSB7CiAgICAgICAgICAgICAgLy8gQ29udGludWUgd2l0aCB0aGUgb3V0ZXIgcmV0dXJuLCBub3cgdGhhdCB0aGUgZGVsZWdhdGUKICAgICAgICAgICAgICAvLyBpdGVyYXRvciBoYXMgYmVlbiB0ZXJtaW5hdGVkLgogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgdmFyIHJlY29yZCA9IHRyeUNhdGNoKAogICAgICAgICAgICBkZWxlZ2F0ZS5pdGVyYXRvclttZXRob2RdLAogICAgICAgICAgICBkZWxlZ2F0ZS5pdGVyYXRvciwKICAgICAgICAgICAgYXJnCiAgICAgICAgICApOwoKICAgICAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDsKCiAgICAgICAgICAgIC8vIExpa2UgcmV0dXJuaW5nIGdlbmVyYXRvci50aHJvdyh1bmNhdWdodCksIGJ1dCB3aXRob3V0IHRoZQogICAgICAgICAgICAvLyBvdmVyaGVhZCBvZiBhbiBleHRyYSBmdW5jdGlvbiBjYWxsLgogICAgICAgICAgICBtZXRob2QgPSAidGhyb3ciOwogICAgICAgICAgICBhcmcgPSByZWNvcmQuYXJnOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KCiAgICAgICAgICAvLyBEZWxlZ2F0ZSBnZW5lcmF0b3IgcmFuIGFuZCBoYW5kbGVkIGl0cyBvd24gZXhjZXB0aW9ucyBzbwogICAgICAgICAgLy8gcmVnYXJkbGVzcyBvZiB3aGF0IHRoZSBtZXRob2Qgd2FzLCB3ZSBjb250aW51ZSBhcyBpZiBpdCBpcwogICAgICAgICAgLy8gIm5leHQiIHdpdGggYW4gdW5kZWZpbmVkIGFyZy4KICAgICAgICAgIG1ldGhvZCA9ICJuZXh0IjsKICAgICAgICAgIGFyZyA9IHVuZGVmaW5lZDsKCiAgICAgICAgICB2YXIgaW5mbyA9IHJlY29yZC5hcmc7CiAgICAgICAgICBpZiAoaW5mby5kb25lKSB7CiAgICAgICAgICAgIGNvbnRleHRbZGVsZWdhdGUucmVzdWx0TmFtZV0gPSBpbmZvLnZhbHVlOwogICAgICAgICAgICBjb250ZXh0Lm5leHQgPSBkZWxlZ2F0ZS5uZXh0TG9jOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RhdGUgPSBHZW5TdGF0ZVN1c3BlbmRlZFlpZWxkOwogICAgICAgICAgICByZXR1cm4gaW5mbzsKICAgICAgICAgIH0KCiAgICAgICAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDsKICAgICAgICB9CgogICAgICAgIGlmIChtZXRob2QgPT09ICJuZXh0IikgewogICAgICAgICAgLy8gU2V0dGluZyBjb250ZXh0Ll9zZW50IGZvciBsZWdhY3kgc3VwcG9ydCBvZiBCYWJlbCdzCiAgICAgICAgICAvLyBmdW5jdGlvbi5zZW50IGltcGxlbWVudGF0aW9uLgogICAgICAgICAgY29udGV4dC5zZW50ID0gY29udGV4dC5fc2VudCA9IGFyZzsKCiAgICAgICAgfSBlbHNlIGlmIChtZXRob2QgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgIGlmIChzdGF0ZSA9PT0gR2VuU3RhdGVTdXNwZW5kZWRTdGFydCkgewogICAgICAgICAgICBzdGF0ZSA9IEdlblN0YXRlQ29tcGxldGVkOwogICAgICAgICAgICB0aHJvdyBhcmc7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKGNvbnRleHQuZGlzcGF0Y2hFeGNlcHRpb24oYXJnKSkgewogICAgICAgICAgICAvLyBJZiB0aGUgZGlzcGF0Y2hlZCBleGNlcHRpb24gd2FzIGNhdWdodCBieSBhIGNhdGNoIGJsb2NrLAogICAgICAgICAgICAvLyB0aGVuIGxldCB0aGF0IGNhdGNoIGJsb2NrIGhhbmRsZSB0aGUgZXhjZXB0aW9uIG5vcm1hbGx5LgogICAgICAgICAgICBtZXRob2QgPSAibmV4dCI7CiAgICAgICAgICAgIGFyZyA9IHVuZGVmaW5lZDsKICAgICAgICAgIH0KCiAgICAgICAgfSBlbHNlIGlmIChtZXRob2QgPT09ICJyZXR1cm4iKSB7CiAgICAgICAgICBjb250ZXh0LmFicnVwdCgicmV0dXJuIiwgYXJnKTsKICAgICAgICB9CgogICAgICAgIHN0YXRlID0gR2VuU3RhdGVFeGVjdXRpbmc7CgogICAgICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChpbm5lckZuLCBzZWxmLCBjb250ZXh0KTsKICAgICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJub3JtYWwiKSB7CiAgICAgICAgICAvLyBJZiBhbiBleGNlcHRpb24gaXMgdGhyb3duIGZyb20gaW5uZXJGbiwgd2UgbGVhdmUgc3RhdGUgPT09CiAgICAgICAgICAvLyBHZW5TdGF0ZUV4ZWN1dGluZyBhbmQgbG9vcCBiYWNrIGZvciBhbm90aGVyIGludm9jYXRpb24uCiAgICAgICAgICBzdGF0ZSA9IGNvbnRleHQuZG9uZQogICAgICAgICAgICA/IEdlblN0YXRlQ29tcGxldGVkCiAgICAgICAgICAgIDogR2VuU3RhdGVTdXNwZW5kZWRZaWVsZDsKCiAgICAgICAgICB2YXIgaW5mbyA9IHsKICAgICAgICAgICAgdmFsdWU6IHJlY29yZC5hcmcsCiAgICAgICAgICAgIGRvbmU6IGNvbnRleHQuZG9uZQogICAgICAgICAgfTsKCiAgICAgICAgICBpZiAocmVjb3JkLmFyZyA9PT0gQ29udGludWVTZW50aW5lbCkgewogICAgICAgICAgICBpZiAoY29udGV4dC5kZWxlZ2F0ZSAmJiBtZXRob2QgPT09ICJuZXh0IikgewogICAgICAgICAgICAgIC8vIERlbGliZXJhdGVseSBmb3JnZXQgdGhlIGxhc3Qgc2VudCB2YWx1ZSBzbyB0aGF0IHdlIGRvbid0CiAgICAgICAgICAgICAgLy8gYWNjaWRlbnRhbGx5IHBhc3MgaXQgb24gdG8gdGhlIGRlbGVnYXRlLgogICAgICAgICAgICAgIGFyZyA9IHVuZGVmaW5lZDsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIGluZm87CiAgICAgICAgICB9CgogICAgICAgIH0gZWxzZSBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgIHN0YXRlID0gR2VuU3RhdGVDb21wbGV0ZWQ7CiAgICAgICAgICAvLyBEaXNwYXRjaCB0aGUgZXhjZXB0aW9uIGJ5IGxvb3BpbmcgYmFjayBhcm91bmQgdG8gdGhlCiAgICAgICAgICAvLyBjb250ZXh0LmRpc3BhdGNoRXhjZXB0aW9uKGFyZykgY2FsbCBhYm92ZS4KICAgICAgICAgIG1ldGhvZCA9ICJ0aHJvdyI7CiAgICAgICAgICBhcmcgPSByZWNvcmQuYXJnOwogICAgICAgIH0KICAgICAgfQogICAgfTsKICB9CgogIC8vIERlZmluZSBHZW5lcmF0b3IucHJvdG90eXBlLntuZXh0LHRocm93LHJldHVybn0gaW4gdGVybXMgb2YgdGhlCiAgLy8gdW5pZmllZCAuX2ludm9rZSBoZWxwZXIgbWV0aG9kLgogIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhHcCk7CgogIEdwW2l0ZXJhdG9yU3ltYm9sXSA9IGZ1bmN0aW9uKCkgewogICAgcmV0dXJuIHRoaXM7CiAgfTsKCiAgR3BbdG9TdHJpbmdUYWdTeW1ib2xdID0gIkdlbmVyYXRvciI7CgogIEdwLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7CiAgICByZXR1cm4gIltvYmplY3QgR2VuZXJhdG9yXSI7CiAgfTsKCiAgZnVuY3Rpb24gcHVzaFRyeUVudHJ5KGxvY3MpIHsKICAgIHZhciBlbnRyeSA9IHsgdHJ5TG9jOiBsb2NzWzBdIH07CgogICAgaWYgKDEgaW4gbG9jcykgewogICAgICBlbnRyeS5jYXRjaExvYyA9IGxvY3NbMV07CiAgICB9CgogICAgaWYgKDIgaW4gbG9jcykgewogICAgICBlbnRyeS5maW5hbGx5TG9jID0gbG9jc1syXTsKICAgICAgZW50cnkuYWZ0ZXJMb2MgPSBsb2NzWzNdOwogICAgfQoKICAgIHRoaXMudHJ5RW50cmllcy5wdXNoKGVudHJ5KTsKICB9CgogIGZ1bmN0aW9uIHJlc2V0VHJ5RW50cnkoZW50cnkpIHsKICAgIHZhciByZWNvcmQgPSBlbnRyeS5jb21wbGV0aW9uIHx8IHt9OwogICAgcmVjb3JkLnR5cGUgPSAibm9ybWFsIjsKICAgIGRlbGV0ZSByZWNvcmQuYXJnOwogICAgZW50cnkuY29tcGxldGlvbiA9IHJlY29yZDsKICB9CgogIGZ1bmN0aW9uIENvbnRleHQodHJ5TG9jc0xpc3QpIHsKICAgIC8vIFRoZSByb290IGVudHJ5IG9iamVjdCAoZWZmZWN0aXZlbHkgYSB0cnkgc3RhdGVtZW50IHdpdGhvdXQgYSBjYXRjaAogICAgLy8gb3IgYSBmaW5hbGx5IGJsb2NrKSBnaXZlcyB1cyBhIHBsYWNlIHRvIHN0b3JlIHZhbHVlcyB0aHJvd24gZnJvbQogICAgLy8gbG9jYXRpb25zIHdoZXJlIHRoZXJlIGlzIG5vIGVuY2xvc2luZyB0cnkgc3RhdGVtZW50LgogICAgdGhpcy50cnlFbnRyaWVzID0gW3sgdHJ5TG9jOiAicm9vdCIgfV07CiAgICB0cnlMb2NzTGlzdC5mb3JFYWNoKHB1c2hUcnlFbnRyeSwgdGhpcyk7CiAgICB0aGlzLnJlc2V0KHRydWUpOwogIH0KCiAgcnVudGltZS5rZXlzID0gZnVuY3Rpb24ob2JqZWN0KSB7CiAgICB2YXIga2V5cyA9IFtdOwogICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkgewogICAgICBrZXlzLnB1c2goa2V5KTsKICAgIH0KICAgIGtleXMucmV2ZXJzZSgpOwoKICAgIC8vIFJhdGhlciB0aGFuIHJldHVybmluZyBhbiBvYmplY3Qgd2l0aCBhIG5leHQgbWV0aG9kLCB3ZSBrZWVwCiAgICAvLyB0aGluZ3Mgc2ltcGxlIGFuZCByZXR1cm4gdGhlIG5leHQgZnVuY3Rpb24gaXRzZWxmLgogICAgcmV0dXJuIGZ1bmN0aW9uIG5leHQoKSB7CiAgICAgIHdoaWxlIChrZXlzLmxlbmd0aCkgewogICAgICAgIHZhciBrZXkgPSBrZXlzLnBvcCgpOwogICAgICAgIGlmIChrZXkgaW4gb2JqZWN0KSB7CiAgICAgICAgICBuZXh0LnZhbHVlID0ga2V5OwogICAgICAgICAgbmV4dC5kb25lID0gZmFsc2U7CiAgICAgICAgICByZXR1cm4gbmV4dDsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIFRvIGF2b2lkIGNyZWF0aW5nIGFuIGFkZGl0aW9uYWwgb2JqZWN0LCB3ZSBqdXN0IGhhbmcgdGhlIC52YWx1ZQogICAgICAvLyBhbmQgLmRvbmUgcHJvcGVydGllcyBvZmYgdGhlIG5leHQgZnVuY3Rpb24gb2JqZWN0IGl0c2VsZi4gVGhpcwogICAgICAvLyBhbHNvIGVuc3VyZXMgdGhhdCB0aGUgbWluaWZpZXIgd2lsbCBub3QgYW5vbnltaXplIHRoZSBmdW5jdGlvbi4KICAgICAgbmV4dC5kb25lID0gdHJ1ZTsKICAgICAgcmV0dXJuIG5leHQ7CiAgICB9OwogIH07CgogIGZ1bmN0aW9uIHZhbHVlcyhpdGVyYWJsZSkgewogICAgaWYgKGl0ZXJhYmxlKSB7CiAgICAgIHZhciBpdGVyYXRvck1ldGhvZCA9IGl0ZXJhYmxlW2l0ZXJhdG9yU3ltYm9sXTsKICAgICAgaWYgKGl0ZXJhdG9yTWV0aG9kKSB7CiAgICAgICAgcmV0dXJuIGl0ZXJhdG9yTWV0aG9kLmNhbGwoaXRlcmFibGUpOwogICAgICB9CgogICAgICBpZiAodHlwZW9mIGl0ZXJhYmxlLm5leHQgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICByZXR1cm4gaXRlcmFibGU7CiAgICAgIH0KCiAgICAgIGlmICghaXNOYU4oaXRlcmFibGUubGVuZ3RoKSkgewogICAgICAgIHZhciBpID0gLTEsIG5leHQgPSBmdW5jdGlvbiBuZXh0KCkgewogICAgICAgICAgd2hpbGUgKCsraSA8IGl0ZXJhYmxlLmxlbmd0aCkgewogICAgICAgICAgICBpZiAoaGFzT3duLmNhbGwoaXRlcmFibGUsIGkpKSB7CiAgICAgICAgICAgICAgbmV4dC52YWx1ZSA9IGl0ZXJhYmxlW2ldOwogICAgICAgICAgICAgIG5leHQuZG9uZSA9IGZhbHNlOwogICAgICAgICAgICAgIHJldHVybiBuZXh0OwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgbmV4dC52YWx1ZSA9IHVuZGVmaW5lZDsKICAgICAgICAgIG5leHQuZG9uZSA9IHRydWU7CgogICAgICAgICAgcmV0dXJuIG5leHQ7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIG5leHQubmV4dCA9IG5leHQ7CiAgICAgIH0KICAgIH0KCiAgICAvLyBSZXR1cm4gYW4gaXRlcmF0b3Igd2l0aCBubyB2YWx1ZXMuCiAgICByZXR1cm4geyBuZXh0OiBkb25lUmVzdWx0IH07CiAgfQogIHJ1bnRpbWUudmFsdWVzID0gdmFsdWVzOwoKICBmdW5jdGlvbiBkb25lUmVzdWx0KCkgewogICAgcmV0dXJuIHsgdmFsdWU6IHVuZGVmaW5lZCwgZG9uZTogdHJ1ZSB9OwogIH0KCiAgQ29udGV4dC5wcm90b3R5cGUgPSB7CiAgICBjb25zdHJ1Y3RvcjogQ29udGV4dCwKCiAgICByZXNldDogZnVuY3Rpb24oc2tpcFRlbXBSZXNldCkgewogICAgICB0aGlzLnByZXYgPSAwOwogICAgICB0aGlzLm5leHQgPSAwOwogICAgICAvLyBSZXNldHRpbmcgY29udGV4dC5fc2VudCBmb3IgbGVnYWN5IHN1cHBvcnQgb2YgQmFiZWwncwogICAgICAvLyBmdW5jdGlvbi5zZW50IGltcGxlbWVudGF0aW9uLgogICAgICB0aGlzLnNlbnQgPSB0aGlzLl9zZW50ID0gdW5kZWZpbmVkOwogICAgICB0aGlzLmRvbmUgPSBmYWxzZTsKICAgICAgdGhpcy5kZWxlZ2F0ZSA9IG51bGw7CgogICAgICB0aGlzLnRyeUVudHJpZXMuZm9yRWFjaChyZXNldFRyeUVudHJ5KTsKCiAgICAgIGlmICghc2tpcFRlbXBSZXNldCkgewogICAgICAgIGZvciAodmFyIG5hbWUgaW4gdGhpcykgewogICAgICAgICAgLy8gTm90IHN1cmUgYWJvdXQgdGhlIG9wdGltYWwgb3JkZXIgb2YgdGhlc2UgY29uZGl0aW9uczoKICAgICAgICAgIGlmIChuYW1lLmNoYXJBdCgwKSA9PT0gInQiICYmCiAgICAgICAgICAgICAgaGFzT3duLmNhbGwodGhpcywgbmFtZSkgJiYKICAgICAgICAgICAgICAhaXNOYU4oK25hbWUuc2xpY2UoMSkpKSB7CiAgICAgICAgICAgIHRoaXNbbmFtZV0gPSB1bmRlZmluZWQ7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9LAoKICAgIHN0b3A6IGZ1bmN0aW9uKCkgewogICAgICB0aGlzLmRvbmUgPSB0cnVlOwoKICAgICAgdmFyIHJvb3RFbnRyeSA9IHRoaXMudHJ5RW50cmllc1swXTsKICAgICAgdmFyIHJvb3RSZWNvcmQgPSByb290RW50cnkuY29tcGxldGlvbjsKICAgICAgaWYgKHJvb3RSZWNvcmQudHlwZSA9PT0gInRocm93IikgewogICAgICAgIHRocm93IHJvb3RSZWNvcmQuYXJnOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5ydmFsOwogICAgfSwKCiAgICBkaXNwYXRjaEV4Y2VwdGlvbjogZnVuY3Rpb24oZXhjZXB0aW9uKSB7CiAgICAgIGlmICh0aGlzLmRvbmUpIHsKICAgICAgICB0aHJvdyBleGNlcHRpb247CiAgICAgIH0KCiAgICAgIHZhciBjb250ZXh0ID0gdGhpczsKICAgICAgZnVuY3Rpb24gaGFuZGxlKGxvYywgY2F1Z2h0KSB7CiAgICAgICAgcmVjb3JkLnR5cGUgPSAidGhyb3ciOwogICAgICAgIHJlY29yZC5hcmcgPSBleGNlcHRpb247CiAgICAgICAgY29udGV4dC5uZXh0ID0gbG9jOwogICAgICAgIHJldHVybiAhIWNhdWdodDsKICAgICAgfQoKICAgICAgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgewogICAgICAgIHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTsKICAgICAgICB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbjsKCiAgICAgICAgaWYgKGVudHJ5LnRyeUxvYyA9PT0gInJvb3QiKSB7CiAgICAgICAgICAvLyBFeGNlcHRpb24gdGhyb3duIG91dHNpZGUgb2YgYW55IHRyeSBibG9jayB0aGF0IGNvdWxkIGhhbmRsZQogICAgICAgICAgLy8gaXQsIHNvIHNldCB0aGUgY29tcGxldGlvbiB2YWx1ZSBvZiB0aGUgZW50aXJlIGZ1bmN0aW9uIHRvCiAgICAgICAgICAvLyB0aHJvdyB0aGUgZXhjZXB0aW9uLgogICAgICAgICAgcmV0dXJuIGhhbmRsZSgiZW5kIik7CiAgICAgICAgfQoKICAgICAgICBpZiAoZW50cnkudHJ5TG9jIDw9IHRoaXMucHJldikgewogICAgICAgICAgdmFyIGhhc0NhdGNoID0gaGFzT3duLmNhbGwoZW50cnksICJjYXRjaExvYyIpOwogICAgICAgICAgdmFyIGhhc0ZpbmFsbHkgPSBoYXNPd24uY2FsbChlbnRyeSwgImZpbmFsbHlMb2MiKTsKCiAgICAgICAgICBpZiAoaGFzQ2F0Y2ggJiYgaGFzRmluYWxseSkgewogICAgICAgICAgICBpZiAodGhpcy5wcmV2IDwgZW50cnkuY2F0Y2hMb2MpIHsKICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlKGVudHJ5LmNhdGNoTG9jLCB0cnVlKTsKICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnByZXYgPCBlbnRyeS5maW5hbGx5TG9jKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5maW5hbGx5TG9jKTsKICAgICAgICAgICAgfQoKICAgICAgICAgIH0gZWxzZSBpZiAoaGFzQ2F0Y2gpIHsKICAgICAgICAgICAgaWYgKHRoaXMucHJldiA8IGVudHJ5LmNhdGNoTG9jKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5jYXRjaExvYywgdHJ1ZSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICB9IGVsc2UgaWYgKGhhc0ZpbmFsbHkpIHsKICAgICAgICAgICAgaWYgKHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHsKICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlKGVudHJ5LmZpbmFsbHlMb2MpOwogICAgICAgICAgICB9CgogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJ0cnkgc3RhdGVtZW50IHdpdGhvdXQgY2F0Y2ggb3IgZmluYWxseSIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfSwKCiAgICBhYnJ1cHQ6IGZ1bmN0aW9uKHR5cGUsIGFyZykgewogICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOwogICAgICAgIGlmIChlbnRyeS50cnlMb2MgPD0gdGhpcy5wcmV2ICYmCiAgICAgICAgICAgIGhhc093bi5jYWxsKGVudHJ5LCAiZmluYWxseUxvYyIpICYmCiAgICAgICAgICAgIHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHsKICAgICAgICAgIHZhciBmaW5hbGx5RW50cnkgPSBlbnRyeTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKGZpbmFsbHlFbnRyeSAmJgogICAgICAgICAgKHR5cGUgPT09ICJicmVhayIgfHwKICAgICAgICAgICB0eXBlID09PSAiY29udGludWUiKSAmJgogICAgICAgICAgZmluYWxseUVudHJ5LnRyeUxvYyA8PSBhcmcgJiYKICAgICAgICAgIGFyZyA8PSBmaW5hbGx5RW50cnkuZmluYWxseUxvYykgewogICAgICAgIC8vIElnbm9yZSB0aGUgZmluYWxseSBlbnRyeSBpZiBjb250cm9sIGlzIG5vdCBqdW1waW5nIHRvIGEKICAgICAgICAvLyBsb2NhdGlvbiBvdXRzaWRlIHRoZSB0cnkvY2F0Y2ggYmxvY2suCiAgICAgICAgZmluYWxseUVudHJ5ID0gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIHJlY29yZCA9IGZpbmFsbHlFbnRyeSA/IGZpbmFsbHlFbnRyeS5jb21wbGV0aW9uIDoge307CiAgICAgIHJlY29yZC50eXBlID0gdHlwZTsKICAgICAgcmVjb3JkLmFyZyA9IGFyZzsKCiAgICAgIGlmIChmaW5hbGx5RW50cnkpIHsKICAgICAgICB0aGlzLm5leHQgPSBmaW5hbGx5RW50cnkuZmluYWxseUxvYzsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLmNvbXBsZXRlKHJlY29yZCk7CiAgICAgIH0KCiAgICAgIHJldHVybiBDb250aW51ZVNlbnRpbmVsOwogICAgfSwKCiAgICBjb21wbGV0ZTogZnVuY3Rpb24ocmVjb3JkLCBhZnRlckxvYykgewogICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICB0aHJvdyByZWNvcmQuYXJnOwogICAgICB9CgogICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJicmVhayIgfHwKICAgICAgICAgIHJlY29yZC50eXBlID09PSAiY29udGludWUiKSB7CiAgICAgICAgdGhpcy5uZXh0ID0gcmVjb3JkLmFyZzsKICAgICAgfSBlbHNlIGlmIChyZWNvcmQudHlwZSA9PT0gInJldHVybiIpIHsKICAgICAgICB0aGlzLnJ2YWwgPSByZWNvcmQuYXJnOwogICAgICAgIHRoaXMubmV4dCA9ICJlbmQiOwogICAgICB9IGVsc2UgaWYgKHJlY29yZC50eXBlID09PSAibm9ybWFsIiAmJiBhZnRlckxvYykgewogICAgICAgIHRoaXMubmV4dCA9IGFmdGVyTG9jOwogICAgICB9CiAgICB9LAoKICAgIGZpbmlzaDogZnVuY3Rpb24oZmluYWxseUxvYykgewogICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOwogICAgICAgIGlmIChlbnRyeS5maW5hbGx5TG9jID09PSBmaW5hbGx5TG9jKSB7CiAgICAgICAgICB0aGlzLmNvbXBsZXRlKGVudHJ5LmNvbXBsZXRpb24sIGVudHJ5LmFmdGVyTG9jKTsKICAgICAgICAgIHJlc2V0VHJ5RW50cnkoZW50cnkpOwogICAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7CiAgICAgICAgfQogICAgICB9CiAgICB9LAoKICAgICJjYXRjaCI6IGZ1bmN0aW9uKHRyeUxvYykgewogICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOwogICAgICAgIGlmIChlbnRyeS50cnlMb2MgPT09IHRyeUxvYykgewogICAgICAgICAgdmFyIHJlY29yZCA9IGVudHJ5LmNvbXBsZXRpb247CiAgICAgICAgICBpZiAocmVjb3JkLnR5cGUgPT09ICJ0aHJvdyIpIHsKICAgICAgICAgICAgdmFyIHRocm93biA9IHJlY29yZC5hcmc7CiAgICAgICAgICAgIHJlc2V0VHJ5RW50cnkoZW50cnkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRocm93bjsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIFRoZSBjb250ZXh0LmNhdGNoIG1ldGhvZCBtdXN0IG9ubHkgYmUgY2FsbGVkIHdpdGggYSBsb2NhdGlvbgogICAgICAvLyBhcmd1bWVudCB0aGF0IGNvcnJlc3BvbmRzIHRvIGEga25vd24gY2F0Y2ggYmxvY2suCiAgICAgIHRocm93IG5ldyBFcnJvcigiaWxsZWdhbCBjYXRjaCBhdHRlbXB0Iik7CiAgICB9LAoKICAgIGRlbGVnYXRlWWllbGQ6IGZ1bmN0aW9uKGl0ZXJhYmxlLCByZXN1bHROYW1lLCBuZXh0TG9jKSB7CiAgICAgIHRoaXMuZGVsZWdhdGUgPSB7CiAgICAgICAgaXRlcmF0b3I6IHZhbHVlcyhpdGVyYWJsZSksCiAgICAgICAgcmVzdWx0TmFtZTogcmVzdWx0TmFtZSwKICAgICAgICBuZXh0TG9jOiBuZXh0TG9jCiAgICAgIH07CgogICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDsKICAgIH0KICB9Owp9KSgKICAvLyBBbW9uZyB0aGUgdmFyaW91cyB0cmlja3MgZm9yIG9idGFpbmluZyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsCiAgLy8gb2JqZWN0LCB0aGlzIHNlZW1zIHRvIGJlIHRoZSBtb3N0IHJlbGlhYmxlIHRlY2huaXF1ZSB0aGF0IGRvZXMgbm90CiAgLy8gdXNlIGluZGlyZWN0IGV2YWwgKHdoaWNoIHZpb2xhdGVzIENvbnRlbnQgU2VjdXJpdHkgUG9saWN5KS4KICB0eXBlb2YgZ2xvYmFsID09PSAib2JqZWN0IiA/IGdsb2JhbCA6CiAgdHlwZW9mIHdpbmRvdyA9PT0gIm9iamVjdCIgPyB3aW5kb3cgOgogIHR5cGVvZiBzZWxmID09PSAib2JqZWN0IiA/IHNlbGYgOiB0aGlzCik7Cgo7KGZ1bmN0aW9uKCkgewovKiEKICogQG92ZXJ2aWV3ICBFbWJlciAtIEphdmFTY3JpcHQgQXBwbGljYXRpb24gRnJhbWV3b3JrCiAqIEBjb3B5cmlnaHQgQ29weXJpZ2h0IDIwMTEtMjAxOSBUaWxkZSBJbmMuIGFuZCBjb250cmlidXRvcnMKICogICAgICAgICAgICBQb3J0aW9ucyBDb3B5cmlnaHQgMjAwNi0yMDExIFN0cm9iZSBJbmMuCiAqICAgICAgICAgICAgUG9ydGlvbnMgQ29weXJpZ2h0IDIwMDgtMjAxMSBBcHBsZSBJbmMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiAqIEBsaWNlbnNlICAgTGljZW5zZWQgdW5kZXIgTUlUIGxpY2Vuc2UKICogICAgICAgICAgICBTZWUgaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS9lbWJlcmpzL2VtYmVyLmpzL21hc3Rlci9MSUNFTlNFCiAqIEB2ZXJzaW9uICAgMy4xMy4zCiAqLwoKLypnbG9iYWxzIHByb2Nlc3MgKi8KdmFyIGRlZmluZSwgcmVxdWlyZSwgRW1iZXI7CgovLyBVc2VkIGluIEBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50L2xpYi9nbG9iYWwuanMKbWFpbkNvbnRleHQgPSB0aGlzOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmCgooZnVuY3Rpb24oKSB7CiAgZnVuY3Rpb24gbWlzc2luZ01vZHVsZShuYW1lLCByZWZlcnJlck5hbWUpIHsKICAgIGlmIChyZWZlcnJlck5hbWUpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgZmluZCBtb2R1bGUgJyArIG5hbWUgKyAnIHJlcXVpcmVkIGJ5OiAnICsgcmVmZXJyZXJOYW1lKTsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGZpbmQgbW9kdWxlICcgKyBuYW1lKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGludGVybmFsUmVxdWlyZShfbmFtZSwgcmVmZXJyZXJOYW1lKSB7CiAgICB2YXIgbmFtZSA9IF9uYW1lOwogICAgdmFyIG1vZCA9IHJlZ2lzdHJ5W25hbWVdOwoKICAgIGlmICghbW9kKSB7CiAgICAgIG5hbWUgPSBuYW1lICsgJy9pbmRleCc7CiAgICAgIG1vZCA9IHJlZ2lzdHJ5W25hbWVdOwogICAgfQoKICAgIHZhciBleHBvcnRzID0gc2VlbltuYW1lXTsKCiAgICBpZiAoZXhwb3J0cyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBleHBvcnRzOwogICAgfQoKICAgIGV4cG9ydHMgPSBzZWVuW25hbWVdID0ge307CgogICAgaWYgKCFtb2QpIHsKICAgICAgbWlzc2luZ01vZHVsZShfbmFtZSwgcmVmZXJyZXJOYW1lKTsKICAgIH0KCiAgICB2YXIgZGVwcyA9IG1vZC5kZXBzOwogICAgdmFyIGNhbGxiYWNrID0gbW9kLmNhbGxiYWNrOwogICAgdmFyIHJlaWZpZWQgPSBuZXcgQXJyYXkoZGVwcy5sZW5ndGgpOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVwcy5sZW5ndGg7IGkrKykgewogICAgICBpZiAoZGVwc1tpXSA9PT0gJ2V4cG9ydHMnKSB7CiAgICAgICAgcmVpZmllZFtpXSA9IGV4cG9ydHM7CiAgICAgIH0gZWxzZSBpZiAoZGVwc1tpXSA9PT0gJ3JlcXVpcmUnKSB7CiAgICAgICAgcmVpZmllZFtpXSA9IHJlcXVpcmU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmVpZmllZFtpXSA9IGludGVybmFsUmVxdWlyZShkZXBzW2ldLCBuYW1lKTsKICAgICAgfQogICAgfQoKICAgIGNhbGxiYWNrLmFwcGx5KHRoaXMsIHJlaWZpZWQpOwoKICAgIHJldHVybiBleHBvcnRzOwogIH0KCiAgdmFyIGlzTm9kZSA9CiAgICB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJyAmJgogICAgdHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmCiAgICB7fS50b1N0cmluZy5jYWxsKHByb2Nlc3MpID09PSAnW29iamVjdCBwcm9jZXNzXSc7CgogIGlmICghaXNOb2RlKSB7CiAgICBFbWJlciA9IHRoaXMuRW1iZXIgPSB0aGlzLkVtYmVyIHx8IHt9OwogIH0KCiAgaWYgKHR5cGVvZiBFbWJlciA9PT0gJ3VuZGVmaW5lZCcpIHsKICAgIEVtYmVyID0ge307CiAgfQoKICBpZiAodHlwZW9mIEVtYmVyLl9fbG9hZGVyID09PSAndW5kZWZpbmVkJykgewogICAgdmFyIHJlZ2lzdHJ5ID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHZhciBzZWVuID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKCiAgICBkZWZpbmUgPSBmdW5jdGlvbihuYW1lLCBkZXBzLCBjYWxsYmFjaykgewogICAgICB2YXIgdmFsdWUgPSB7fTsKCiAgICAgIGlmICghY2FsbGJhY2spIHsKICAgICAgICB2YWx1ZS5kZXBzID0gW107CiAgICAgICAgdmFsdWUuY2FsbGJhY2sgPSBkZXBzOwogICAgICB9IGVsc2UgewogICAgICAgIHZhbHVlLmRlcHMgPSBkZXBzOwogICAgICAgIHZhbHVlLmNhbGxiYWNrID0gY2FsbGJhY2s7CiAgICAgIH0KCiAgICAgIHJlZ2lzdHJ5W25hbWVdID0gdmFsdWU7CiAgICB9OwoKICAgIHJlcXVpcmUgPSBmdW5jdGlvbihuYW1lKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbFJlcXVpcmUobmFtZSwgbnVsbCk7CiAgICB9OwoKICAgIC8vIHNldHVwIGByZXF1aXJlYCBtb2R1bGUKICAgIHJlcXVpcmVbJ2RlZmF1bHQnXSA9IHJlcXVpcmU7CgogICAgcmVxdWlyZS5oYXMgPSBmdW5jdGlvbiByZWdpc3RyeUhhcyhtb2R1bGVOYW1lKSB7CiAgICAgIHJldHVybiBCb29sZWFuKHJlZ2lzdHJ5W21vZHVsZU5hbWVdKSB8fCBCb29sZWFuKHJlZ2lzdHJ5W21vZHVsZU5hbWUgKyAnL2luZGV4J10pOwogICAgfTsKCiAgICByZXF1aXJlLl9lYWtfc2VlbiA9IHJlZ2lzdHJ5OwoKICAgIEVtYmVyLl9fbG9hZGVyID0gewogICAgICBkZWZpbmU6IGRlZmluZSwKICAgICAgcmVxdWlyZTogcmVxdWlyZSwKICAgICAgcmVnaXN0cnk6IHJlZ2lzdHJ5LAogICAgfTsKICB9IGVsc2UgewogICAgZGVmaW5lID0gRW1iZXIuX19sb2FkZXIuZGVmaW5lOwogICAgcmVxdWlyZSA9IEVtYmVyLl9fbG9hZGVyLnJlcXVpcmU7CiAgfQp9KSgpOwoKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9icm93c2VyLWVudmlyb25tZW50L2luZGV4IiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuaGFzRE9NID0gX2V4cG9ydHMuaXNGaXJlZm94ID0gX2V4cG9ydHMuaXNDaHJvbWUgPSBfZXhwb3J0cy51c2VyQWdlbnQgPSBfZXhwb3J0cy5oaXN0b3J5ID0gX2V4cG9ydHMubG9jYXRpb24gPSBfZXhwb3J0cy53aW5kb3cgPSB2b2lkIDA7CiAgLy8gY2hlY2sgaWYgd2luZG93IGV4aXN0cyBhbmQgYWN0dWFsbHkgaXMgdGhlIGdsb2JhbAogIHZhciBoYXNEb20gPSB0eXBlb2Ygc2VsZiA9PT0gJ29iamVjdCcgJiYgc2VsZiAhPT0gbnVsbCAmJiBzZWxmLk9iamVjdCA9PT0gT2JqZWN0ICYmIHR5cGVvZiBXaW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHNlbGYuY29uc3RydWN0b3IgPT09IFdpbmRvdyAmJiB0eXBlb2YgZG9jdW1lbnQgPT09ICdvYmplY3QnICYmIGRvY3VtZW50ICE9PSBudWxsICYmIHNlbGYuZG9jdW1lbnQgPT09IGRvY3VtZW50ICYmIHR5cGVvZiBsb2NhdGlvbiA9PT0gJ29iamVjdCcgJiYgbG9jYXRpb24gIT09IG51bGwgJiYgc2VsZi5sb2NhdGlvbiA9PT0gbG9jYXRpb24gJiYgdHlwZW9mIGhpc3RvcnkgPT09ICdvYmplY3QnICYmIGhpc3RvcnkgIT09IG51bGwgJiYgc2VsZi5oaXN0b3J5ID09PSBoaXN0b3J5ICYmIHR5cGVvZiBuYXZpZ2F0b3IgPT09ICdvYmplY3QnICYmIG5hdmlnYXRvciAhPT0gbnVsbCAmJiBzZWxmLm5hdmlnYXRvciA9PT0gbmF2aWdhdG9yICYmIHR5cGVvZiBuYXZpZ2F0b3IudXNlckFnZW50ID09PSAnc3RyaW5nJzsKICBfZXhwb3J0cy5oYXNET00gPSBoYXNEb207CiAgdmFyIHdpbmRvdyA9IGhhc0RvbSA/IHNlbGYgOiBudWxsOwogIF9leHBvcnRzLndpbmRvdyA9IHdpbmRvdzsKICB2YXIgbG9jYXRpb24kMSA9IGhhc0RvbSA/IHNlbGYubG9jYXRpb24gOiBudWxsOwogIF9leHBvcnRzLmxvY2F0aW9uID0gbG9jYXRpb24kMTsKICB2YXIgaGlzdG9yeSQxID0gaGFzRG9tID8gc2VsZi5oaXN0b3J5IDogbnVsbDsKICBfZXhwb3J0cy5oaXN0b3J5ID0gaGlzdG9yeSQxOwogIHZhciB1c2VyQWdlbnQgPSBoYXNEb20gPyBzZWxmLm5hdmlnYXRvci51c2VyQWdlbnQgOiAnTHlueCAodGV4dG1vZGUpJzsKICBfZXhwb3J0cy51c2VyQWdlbnQgPSB1c2VyQWdlbnQ7CiAgdmFyIGlzQ2hyb21lID0gaGFzRG9tID8gQm9vbGVhbih3aW5kb3cuY2hyb21lKSAmJiAhd2luZG93Lm9wZXJhIDogZmFsc2U7CiAgX2V4cG9ydHMuaXNDaHJvbWUgPSBpc0Nocm9tZTsKICB2YXIgaXNGaXJlZm94ID0gaGFzRG9tID8gdHlwZW9mIEluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJyA6IGZhbHNlOwogIF9leHBvcnRzLmlzRmlyZWZveCA9IGlzRmlyZWZveDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvY29uc29sZS9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVidWcsIF9kZXByZWNhdGVkRmVhdHVyZXMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CiAgLy8gRGVsaXZlciBtZXNzYWdlIHRoYXQgdGhlIGZ1bmN0aW9uIGlzIGRlcHJlY2F0ZWQKICB2YXIgREVQUkVDQVRJT05fTUVTU0FHRSA9ICdVc2Ugb2YgRW1iZXIuTG9nZ2VyIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgYGNvbnNvbGVgIGZvciBsb2dnaW5nLic7CiAgdmFyIERFUFJFQ0FUSU9OX0lEID0gJ2VtYmVyLWNvbnNvbGUuZGVwcmVjYXRlLWxvZ2dlcic7CiAgdmFyIERFUFJFQ0FUSU9OX1VSTCA9ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY191c2UtY29uc29sZS1yYXRoZXItdGhhbi1lbWJlci1sb2dnZXInOwogIC8qKgogICAgIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIEluc2lkZSBFbWJlci1NZXRhbCwgc2ltcGx5IHVzZXMgdGhlIG1ldGhvZHMgZnJvbSBgaW1wb3J0cy5jb25zb2xlYC4KICAgIE92ZXJyaWRlIHRoaXMgdG8gcHJvdmlkZSBtb3JlIHJvYnVzdCBsb2dnaW5nIGZ1bmN0aW9uYWxpdHkuCiAgCiAgICBAY2xhc3MgTG9nZ2VyCiAgICBAZGVwcmVjYXRlZCBVc2UgJ2NvbnNvbGUnIGluc3RlYWQKICAKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEBwdWJsaWMKICAqLwoKICB2YXIgREVQUkVDQVRFRF9MT0dHRVI7CgogIGlmIChfZGVwcmVjYXRlZEZlYXR1cmVzLkxPR0dFUikgewogICAgREVQUkVDQVRFRF9MT0dHRVIgPSB7CiAgICAgIC8qKgogICAgICBMb2dzIHRoZSBhcmd1bWVudHMgdG8gdGhlIGNvbnNvbGUuCiAgICAgIFlvdSBjYW4gcGFzcyBhcyBtYW55IGFyZ3VtZW50cyBhcyB5b3Ugd2FudCBhbmQgdGhleSB3aWxsIGJlIGpvaW5lZCB0b2dldGhlciB3aXRoIGEgc3BhY2UuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHZhciBmb28gPSAxOwogICAgICBFbWJlci5Mb2dnZXIubG9nKCdsb2cgdmFsdWUgb2YgZm9vOicsIGZvbyk7CiAgICAgIC8vICJsb2cgdmFsdWUgb2YgZm9vOiAxIiB3aWxsIGJlIHByaW50ZWQgdG8gdGhlIGNvbnNvbGUKICAgICAgYGBgCiAgICAgIEBtZXRob2QgbG9nCiAgICAgIEBmb3IgRW1iZXIuTG9nZ2VyCiAgICAgIEBwYXJhbSB7Kn0gYXJndW1lbnRzCiAgICAgIEBwdWJsaWMKICAgICAgKi8KICAgICAgbG9nOiBmdW5jdGlvbiBsb2coKSB7CiAgICAgICAgdmFyIF9jb25zb2xlOwoKICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKERFUFJFQ0FUSU9OX01FU1NBR0UsIGZhbHNlLCB7CiAgICAgICAgICBpZDogREVQUkVDQVRJT05fSUQsCiAgICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICAgIHVybDogREVQUkVDQVRJT05fVVJMCiAgICAgICAgfSkpOwogICAgICAgIHJldHVybiAoX2NvbnNvbGUgPSBjb25zb2xlKS5sb2cuYXBwbHkoX2NvbnNvbGUsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tY29uc29sZQogICAgICB9LAoKICAgICAgLyoqCiAgICAgIFByaW50cyB0aGUgYXJndW1lbnRzIHRvIHRoZSBjb25zb2xlIHdpdGggYSB3YXJuaW5nIGljb24uCiAgICAgIFlvdSBjYW4gcGFzcyBhcyBtYW55IGFyZ3VtZW50cyBhcyB5b3Ugd2FudCBhbmQgdGhleSB3aWxsIGJlIGpvaW5lZCB0b2dldGhlciB3aXRoIGEgc3BhY2UuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIEVtYmVyLkxvZ2dlci53YXJuKCdTb21ldGhpbmcgaGFwcGVuZWQhJyk7CiAgICAgIC8vICJTb21ldGhpbmcgaGFwcGVuZWQhIiB3aWxsIGJlIHByaW50ZWQgdG8gdGhlIGNvbnNvbGUgd2l0aCBhIHdhcm5pbmcgaWNvbi4KICAgICAgYGBgCiAgICAgIEBtZXRob2Qgd2FybgogICAgICBAZm9yIEVtYmVyLkxvZ2dlcgogICAgICBAcGFyYW0geyp9IGFyZ3VtZW50cwogICAgICBAcHVibGljCiAgICAgICovCiAgICAgIHdhcm46IGZ1bmN0aW9uIHdhcm4oKSB7CiAgICAgICAgdmFyIF9jb25zb2xlMjsKCiAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKShERVBSRUNBVElPTl9NRVNTQUdFLCBmYWxzZSwgewogICAgICAgICAgaWQ6IERFUFJFQ0FUSU9OX0lELAogICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICB1cmw6IERFUFJFQ0FUSU9OX1VSTAogICAgICAgIH0pKTsKICAgICAgICByZXR1cm4gKF9jb25zb2xlMiA9IGNvbnNvbGUpLndhcm4uYXBwbHkoX2NvbnNvbGUyLCBhcmd1bWVudHMpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGUKICAgICAgfSwKCiAgICAgIC8qKgogICAgICBQcmludHMgdGhlIGFyZ3VtZW50cyB0byB0aGUgY29uc29sZSB3aXRoIGFuIGVycm9yIGljb24sIHJlZCB0ZXh0IGFuZCBhIHN0YWNrIHRyYWNlLgogICAgICBZb3UgY2FuIHBhc3MgYXMgbWFueSBhcmd1bWVudHMgYXMgeW91IHdhbnQgYW5kIHRoZXkgd2lsbCBiZSBqb2luZWQgdG9nZXRoZXIgd2l0aCBhIHNwYWNlLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBFbWJlci5Mb2dnZXIuZXJyb3IoJ0RhbmdlciEgRGFuZ2VyIScpOwogICAgICAvLyAiRGFuZ2VyISBEYW5nZXIhIiB3aWxsIGJlIHByaW50ZWQgdG8gdGhlIGNvbnNvbGUgaW4gcmVkIHRleHQuCiAgICAgIGBgYAogICAgICBAbWV0aG9kIGVycm9yCiAgICAgIEBmb3IgRW1iZXIuTG9nZ2VyCiAgICAgIEBwYXJhbSB7Kn0gYXJndW1lbnRzCiAgICAgIEBwdWJsaWMKICAgICAgKi8KICAgICAgZXJyb3I6IGZ1bmN0aW9uIGVycm9yKCkgewogICAgICAgIHZhciBfY29uc29sZTM7CgogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoREVQUkVDQVRJT05fTUVTU0FHRSwgZmFsc2UsIHsKICAgICAgICAgIGlkOiBERVBSRUNBVElPTl9JRCwKICAgICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgICAgdXJsOiBERVBSRUNBVElPTl9VUkwKICAgICAgICB9KSk7CiAgICAgICAgcmV0dXJuIChfY29uc29sZTMgPSBjb25zb2xlKS5lcnJvci5hcHBseShfY29uc29sZTMsIGFyZ3VtZW50cyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tY29uc29sZQogICAgICB9LAoKICAgICAgLyoqCiAgICAgIExvZ3MgdGhlIGFyZ3VtZW50cyB0byB0aGUgY29uc29sZS4KICAgICAgWW91IGNhbiBwYXNzIGFzIG1hbnkgYXJndW1lbnRzIGFzIHlvdSB3YW50IGFuZCB0aGV5IHdpbGwgYmUgam9pbmVkIHRvZ2V0aGVyIHdpdGggYSBzcGFjZS4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgdmFyIGZvbyA9IDE7CiAgICAgIEVtYmVyLkxvZ2dlci5pbmZvKCdsb2cgdmFsdWUgb2YgZm9vOicsIGZvbyk7CiAgICAgIC8vICJsb2cgdmFsdWUgb2YgZm9vOiAxIiB3aWxsIGJlIHByaW50ZWQgdG8gdGhlIGNvbnNvbGUKICAgICAgYGBgCiAgICAgIEBtZXRob2QgaW5mbwogICAgICBAZm9yIEVtYmVyLkxvZ2dlcgogICAgICBAcGFyYW0geyp9IGFyZ3VtZW50cwogICAgICBAcHVibGljCiAgICAgICovCiAgICAgIGluZm86IGZ1bmN0aW9uIGluZm8oKSB7CiAgICAgICAgdmFyIF9jb25zb2xlNDsKCiAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKShERVBSRUNBVElPTl9NRVNTQUdFLCBmYWxzZSwgewogICAgICAgICAgaWQ6IERFUFJFQ0FUSU9OX0lELAogICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICB1cmw6IERFUFJFQ0FUSU9OX1VSTAogICAgICAgIH0pKTsKICAgICAgICByZXR1cm4gKF9jb25zb2xlNCA9IGNvbnNvbGUpLmluZm8uYXBwbHkoX2NvbnNvbGU0LCBhcmd1bWVudHMpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGUKICAgICAgfSwKCiAgICAgIC8qKgogICAgICBMb2dzIHRoZSBhcmd1bWVudHMgdG8gdGhlIGNvbnNvbGUgaW4gYmx1ZSB0ZXh0LgogICAgICBZb3UgY2FuIHBhc3MgYXMgbWFueSBhcmd1bWVudHMgYXMgeW91IHdhbnQgYW5kIHRoZXkgd2lsbCBiZSBqb2luZWQgdG9nZXRoZXIgd2l0aCBhIHNwYWNlLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICB2YXIgZm9vID0gMTsKICAgICAgRW1iZXIuTG9nZ2VyLmRlYnVnKCdsb2cgdmFsdWUgb2YgZm9vOicsIGZvbyk7CiAgICAgIC8vICJsb2cgdmFsdWUgb2YgZm9vOiAxIiB3aWxsIGJlIHByaW50ZWQgdG8gdGhlIGNvbnNvbGUKICAgICAgYGBgCiAgICAgIEBtZXRob2QgZGVidWcKICAgICAgQGZvciBFbWJlci5Mb2dnZXIKICAgICAgQHBhcmFtIHsqfSBhcmd1bWVudHMKICAgICAgQHB1YmxpYwogICAgICAqLwogICAgICBkZWJ1ZzogZnVuY3Rpb24gZGVidWcoKSB7CiAgICAgICAgdmFyIF9jb25zb2xlNjsKCiAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKShERVBSRUNBVElPTl9NRVNTQUdFLCBmYWxzZSwgewogICAgICAgICAgaWQ6IERFUFJFQ0FUSU9OX0lELAogICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICB1cmw6IERFUFJFQ0FUSU9OX1VSTAogICAgICAgIH0pKTsKICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovCgogICAgICAgIGlmIChjb25zb2xlLmRlYnVnKSB7CiAgICAgICAgICB2YXIgX2NvbnNvbGU1OwoKICAgICAgICAgIHJldHVybiAoX2NvbnNvbGU1ID0gY29uc29sZSkuZGVidWcuYXBwbHkoX2NvbnNvbGU1LCBhcmd1bWVudHMpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIChfY29uc29sZTYgPSBjb25zb2xlKS5pbmZvLmFwcGx5KF9jb25zb2xlNiwgYXJndW1lbnRzKTsKICAgICAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWNvbnNvbGUgKi8KICAgICAgfSwKCiAgICAgIC8qKgogICAgICBJZiB0aGUgdmFsdWUgcGFzc2VkIGludG8gYEVtYmVyLkxvZ2dlci5hc3NlcnRgIGlzIG5vdCB0cnV0aHkgaXQgd2lsbCB0aHJvdyBhbiBlcnJvciB3aXRoIGEgc3RhY2sgdHJhY2UuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIEVtYmVyLkxvZ2dlci5hc3NlcnQodHJ1ZSk7IC8vIHVuZGVmaW5lZAogICAgICBFbWJlci5Mb2dnZXIuYXNzZXJ0KHRydWUgPT09IGZhbHNlKTsgLy8gVGhyb3dzIGFuIEFzc2VydGlvbiBmYWlsZWQgZXJyb3IuCiAgICAgIEVtYmVyLkxvZ2dlci5hc3NlcnQodHJ1ZSA9PT0gZmFsc2UsICdTb21ldGhpbmcgaW52YWxpZCcpOyAvLyBUaHJvd3MgYW4gQXNzZXJ0aW9uIGZhaWxlZCBlcnJvciB3aXRoIG1lc3NhZ2UuCiAgICAgIGBgYAogICAgICBAbWV0aG9kIGFzc2VydAogICAgICBAZm9yIEVtYmVyLkxvZ2dlcgogICAgICBAcGFyYW0ge0Jvb2xlYW59IGJvb2wgVmFsdWUgdG8gdGVzdAogICAgICBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBBc3NlcnRpb24gbWVzc2FnZSBvbiBmYWlsZWQKICAgICAgQHB1YmxpYwogICAgICAqLwogICAgICBhc3NlcnQ6IGZ1bmN0aW9uIGFzc2VydCgpIHsKICAgICAgICB2YXIgX2NvbnNvbGU3OwoKICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKERFUFJFQ0FUSU9OX01FU1NBR0UsIGZhbHNlLCB7CiAgICAgICAgICBpZDogREVQUkVDQVRJT05fSUQsCiAgICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICAgIHVybDogREVQUkVDQVRJT05fVVJMCiAgICAgICAgfSkpOwogICAgICAgIHJldHVybiAoX2NvbnNvbGU3ID0gY29uc29sZSkuYXNzZXJ0LmFwcGx5KF9jb25zb2xlNywgYXJndW1lbnRzKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlCiAgICAgIH0KICAgIH07CiAgfQoKICB2YXIgX2RlZmF1bHQgPSBERVBSRUNBVEVEX0xPR0dFUjsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL2NvbnRhaW5lci9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9vd25lciIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL3BvbHlmaWxscyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9vd25lciwgX3V0aWxzLCBfZGVidWcsIF9wb2x5ZmlsbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLnByaXZhdGl6ZSA9IHByaXZhdGl6ZTsKICBfZXhwb3J0cy5GQUNUT1JZX0ZPUiA9IF9leHBvcnRzLkNvbnRhaW5lciA9IF9leHBvcnRzLlJlZ2lzdHJ5ID0gdm9pZCAwOwogIHZhciBsZWFrVHJhY2tpbmc7CiAgdmFyIGNvbnRhaW5lcnM7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICAvLyByZXF1aXJlcyB2OAogICAgLy8gY2hyb21lIC0tanMtZmxhZ3M9Ii0tYWxsb3ctbmF0aXZlcy1zeW50YXggLS1leHBvc2UtZ2MiCiAgICAvLyBub2RlIC0tYWxsb3ctbmF0aXZlcy1zeW50YXggLS1leHBvc2UtZ2MKICAgIHRyeSB7CiAgICAgIGlmICh0eXBlb2YgZ2MgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICBsZWFrVHJhY2tpbmcgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAvLyBhdm9pZCBzeW50YXggZXJyb3JzIHdoZW4gLS1hbGxvdy1uYXRpdmVzLXN5bnRheCBub3QgcHJlc2VudAogICAgICAgICAgdmFyIEdldFdlYWtTZXRWYWx1ZXMgPSBuZXcgRnVuY3Rpb24oJ3dlYWtTZXQnLCAncmV0dXJuICVHZXRXZWFrU2V0VmFsdWVzKHdlYWtTZXQsIDApJyk7CiAgICAgICAgICBjb250YWluZXJzID0gbmV3IFdlYWtTZXQoKTsKICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIGhhc0NvbnRhaW5lcnM6IGZ1bmN0aW9uIGhhc0NvbnRhaW5lcnMoKSB7CiAgICAgICAgICAgICAgZ2MoKTsKICAgICAgICAgICAgICByZXR1cm4gR2V0V2Vha1NldFZhbHVlcyhjb250YWluZXJzKS5sZW5ndGggPiAwOwogICAgICAgICAgICB9LAogICAgICAgICAgICByZXNldDogZnVuY3Rpb24gcmVzZXQoKSB7CiAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IEdldFdlYWtTZXRWYWx1ZXMoY29udGFpbmVycyk7CgogICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmFsdWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBjb250YWluZXJzLmRlbGV0ZSh2YWx1ZXNbaV0pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfTsKICAgICAgICB9KCk7CiAgICAgIH0KICAgIH0gY2F0Y2ggKGUpIHsvLyBpZ25vcmUKICAgIH0KICB9CiAgLyoqCiAgIEEgY29udGFpbmVyIHVzZWQgdG8gaW5zdGFudGlhdGUgYW5kIGNhY2hlIG9iamVjdHMuCiAgCiAgIEV2ZXJ5IGBDb250YWluZXJgIG11c3QgYmUgYXNzb2NpYXRlZCB3aXRoIGEgYFJlZ2lzdHJ5YCwgd2hpY2ggaXMgcmVmZXJlbmNlZAogICB0byBkZXRlcm1pbmUgdGhlIGZhY3RvcnkgYW5kIG9wdGlvbnMgdGhhdCBzaG91bGQgYmUgdXNlZCB0byBpbnN0YW50aWF0ZQogICBvYmplY3RzLgogIAogICBUaGUgcHVibGljIEFQSSBmb3IgYENvbnRhaW5lcmAgaXMgc3RpbGwgaW4gZmx1eCBhbmQgc2hvdWxkIG5vdCBiZSBjb25zaWRlcmVkCiAgIHN0YWJsZS4KICAKICAgQHByaXZhdGUKICAgQGNsYXNzIENvbnRhaW5lcgogICAqLwoKCiAgdmFyIENvbnRhaW5lciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENvbnRhaW5lcihyZWdpc3RyeSwgb3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICB0aGlzLnJlZ2lzdHJ5ID0gcmVnaXN0cnk7CiAgICAgIHRoaXMub3duZXIgPSBvcHRpb25zLm93bmVyIHx8IG51bGw7CiAgICAgIHRoaXMuY2FjaGUgPSAoMCwgX3V0aWxzLmRpY3Rpb25hcnkpKG9wdGlvbnMuY2FjaGUgfHwgbnVsbCk7CiAgICAgIHRoaXMuZmFjdG9yeU1hbmFnZXJDYWNoZSA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkob3B0aW9ucy5mYWN0b3J5TWFuYWdlckNhY2hlIHx8IG51bGwpOwogICAgICB0aGlzLmlzRGVzdHJveWVkID0gZmFsc2U7CiAgICAgIHRoaXMuaXNEZXN0cm95aW5nID0gZmFsc2U7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgdGhpcy52YWxpZGF0aW9uQ2FjaGUgPSAoMCwgX3V0aWxzLmRpY3Rpb25hcnkpKG9wdGlvbnMudmFsaWRhdGlvbkNhY2hlIHx8IG51bGwpOwoKICAgICAgICBpZiAoY29udGFpbmVycyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBjb250YWluZXJzLmFkZCh0aGlzKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgIEBwcml2YXRlCiAgICAgQHByb3BlcnR5IHJlZ2lzdHJ5CiAgICAgQHR5cGUgUmVnaXN0cnkKICAgICBAc2luY2UgMS4xMS4wCiAgICAgKi8KCiAgICAvKioKICAgICBAcHJpdmF0ZQogICAgIEBwcm9wZXJ0eSBjYWNoZQogICAgIEB0eXBlIEluaGVyaXRpbmdEaWN0CiAgICAgKi8KCiAgICAvKioKICAgICBAcHJpdmF0ZQogICAgIEBwcm9wZXJ0eSB2YWxpZGF0aW9uQ2FjaGUKICAgICBAdHlwZSBJbmhlcml0aW5nRGljdAogICAgICovCgogICAgLyoqCiAgICAgR2l2ZW4gYSBmdWxsTmFtZSByZXR1cm4gYSBjb3JyZXNwb25kaW5nIGluc3RhbmNlLgogICAgICBUaGUgZGVmYXVsdCBiZWhhdmlvciBpcyBmb3IgbG9va3VwIHRvIHJldHVybiBhIHNpbmdsZXRvbiBpbnN0YW5jZS4KICAgICBUaGUgc2luZ2xldG9uIGlzIHNjb3BlZCB0byB0aGUgY29udGFpbmVyLCBhbGxvd2luZyBtdWx0aXBsZSBjb250YWluZXJzCiAgICAgdG8gYWxsIGhhdmUgdGhlaXIgb3duIGxvY2FsbHkgc2NvcGVkIHNpbmdsZXRvbnMuCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoKTsKICAgICBsZXQgY29udGFpbmVyID0gcmVnaXN0cnkuY29udGFpbmVyKCk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdhcGk6dHdpdHRlcicsIFR3aXR0ZXIpOwogICAgICBsZXQgdHdpdHRlciA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJyk7CiAgICAgIHR3aXR0ZXIgaW5zdGFuY2VvZiBUd2l0dGVyOyAvLyA9PiB0cnVlCiAgICAgIC8vIGJ5IGRlZmF1bHQgdGhlIGNvbnRhaW5lciB3aWxsIHJldHVybiBzaW5nbGV0b25zCiAgICAgbGV0IHR3aXR0ZXIyID0gY29udGFpbmVyLmxvb2t1cCgnYXBpOnR3aXR0ZXInKTsKICAgICB0d2l0dGVyMiBpbnN0YW5jZW9mIFR3aXR0ZXI7IC8vID0+IHRydWUKICAgICAgdHdpdHRlciA9PT0gdHdpdHRlcjI7IC8vPT4gdHJ1ZQogICAgIGBgYAogICAgICBJZiBzaW5nbGV0b25zIGFyZSBub3Qgd2FudGVkLCBhbiBvcHRpb25hbCBmbGFnIGNhbiBiZSBwcm92aWRlZCBhdCBsb29rdXAuCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoKTsKICAgICBsZXQgY29udGFpbmVyID0gcmVnaXN0cnkuY29udGFpbmVyKCk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdhcGk6dHdpdHRlcicsIFR3aXR0ZXIpOwogICAgICBsZXQgdHdpdHRlciA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJywgeyBzaW5nbGV0b246IGZhbHNlIH0pOwogICAgIGxldCB0d2l0dGVyMiA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJywgeyBzaW5nbGV0b246IGZhbHNlIH0pOwogICAgICB0d2l0dGVyID09PSB0d2l0dGVyMjsgLy89PiBmYWxzZQogICAgIGBgYAogICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2QgbG9va3VwCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXQogICAgIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5zb3VyY2VdIFRoZSBmdWxsbmFtZSBvZiB0aGUgcmVxdWVzdCBzb3VyY2UgKHVzZWQgZm9yIGxvY2FsIGxvb2t1cCkKICAgICBAcmV0dXJuIHthbnl9CiAgICAgKi8KCgogICAgdmFyIF9wcm90byA9IENvbnRhaW5lci5wcm90b3R5cGU7CgogICAgX3Byb3RvLmxvb2t1cCA9IGZ1bmN0aW9uIGxvb2t1cChmdWxsTmFtZSwgb3B0aW9ucykgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc0Rlc3Ryb3llZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdleHBlY3RlZCBjb250YWluZXIgbm90IHRvIGJlIGRlc3Ryb3llZCcsICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMucmVnaXN0cnkuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdmdWxsTmFtZSBtdXN0IGJlIGEgcHJvcGVyIGZ1bGwgbmFtZScsIHRoaXMucmVnaXN0cnkuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkpOwogICAgICByZXR1cm4gX2xvb2t1cCh0aGlzLCB0aGlzLnJlZ2lzdHJ5Lm5vcm1hbGl6ZShmdWxsTmFtZSksIG9wdGlvbnMpOwogICAgfQogICAgLyoqCiAgICAgQSBkZXB0aCBmaXJzdCB0cmF2ZXJzYWwsIGRlc3Ryb3lpbmcgdGhlIGNvbnRhaW5lciwgaXRzIGRlc2NlbmRhbnQgY29udGFpbmVycyBhbmQgYWxsCiAgICAgdGhlaXIgbWFuYWdlZCBvYmplY3RzLgogICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2QgZGVzdHJveQogICAgICovCiAgICA7CgogICAgX3Byb3RvLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICBkZXN0cm95RGVzdHJveWFibGVzKHRoaXMpOwogICAgICB0aGlzLmlzRGVzdHJveWluZyA9IHRydWU7CiAgICB9OwoKICAgIF9wcm90by5maW5hbGl6ZURlc3Ryb3kgPSBmdW5jdGlvbiBmaW5hbGl6ZURlc3Ryb3koKSB7CiAgICAgIHJlc2V0Q2FjaGUodGhpcyk7CiAgICAgIHRoaXMuaXNEZXN0cm95ZWQgPSB0cnVlOwogICAgfQogICAgLyoqCiAgICAgQ2xlYXIgZWl0aGVyIHRoZSBlbnRpcmUgY2FjaGUgb3IganVzdCB0aGUgY2FjaGUgZm9yIGEgcGFydGljdWxhciBrZXkuCiAgICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIHJlc2V0CiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lIG9wdGlvbmFsIGtleSB0byByZXNldDsgaWYgbWlzc2luZywgcmVzZXRzIGV2ZXJ5dGhpbmcKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoZnVsbE5hbWUpIHsKICAgICAgaWYgKHRoaXMuaXNEZXN0cm95ZWQpIHJldHVybjsKCiAgICAgIGlmIChmdWxsTmFtZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZGVzdHJveURlc3Ryb3lhYmxlcyh0aGlzKTsKICAgICAgICByZXNldENhY2hlKHRoaXMpOwogICAgICB9IGVsc2UgewogICAgICAgIHJlc2V0TWVtYmVyKHRoaXMsIHRoaXMucmVnaXN0cnkubm9ybWFsaXplKGZ1bGxOYW1lKSk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgIFJldHVybnMgYW4gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gcHJvdmlkZSBhbiBvd25lciB0byBhCiAgICAgbWFudWFsbHkgY3JlYXRlZCBpbnN0YW5jZS4KICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIG93bmVySW5qZWN0aW9uCiAgICAgQHJldHVybnMgeyBPYmplY3QgfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ub3duZXJJbmplY3Rpb24gPSBmdW5jdGlvbiBvd25lckluamVjdGlvbigpIHsKICAgICAgdmFyIF9yZWY7CgogICAgICByZXR1cm4gX3JlZiA9IHt9LCBfcmVmW19vd25lci5PV05FUl0gPSB0aGlzLm93bmVyLCBfcmVmOwogICAgfQogICAgLyoqCiAgICAgR2l2ZW4gYSBmdWxsTmFtZSwgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIGZhY3RvcnkuIFRoZSBjb25zdW1lciBvZiB0aGUgZmFjdG9yeQogICAgIGlzIHJlc3BvbnNpYmxlIGZvciB0aGUgZGVzdHJ1Y3Rpb24gb2YgYW55IGZhY3RvcnkgaW5zdGFuY2VzLCBhcyB0aGVyZSBpcyBubwogICAgIHdheSBmb3IgdGhlIGNvbnRhaW5lciB0byBlbnN1cmUgaW5zdGFuY2VzIGFyZSBkZXN0cm95ZWQgd2hlbiBpdCBpdHNlbGYgaXMKICAgICBkZXN0cm95ZWQuCiAgICAgIEBwdWJsaWMKICAgICBAbWV0aG9kIGZhY3RvcnlGb3IKICAgICBAcGFyYW0ge1N0cmluZ30gZnVsbE5hbWUKICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdCiAgICAgQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLnNvdXJjZV0gVGhlIGZ1bGxuYW1lIG9mIHRoZSByZXF1ZXN0IHNvdXJjZSAodXNlZCBmb3IgbG9jYWwgbG9va3VwKQogICAgIEByZXR1cm4ge2FueX0KICAgICAqLwogICAgOwoKICAgIF9wcm90by5mYWN0b3J5Rm9yID0gZnVuY3Rpb24gZmFjdG9yeUZvcihmdWxsTmFtZSwgb3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc0Rlc3Ryb3llZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdleHBlY3RlZCBjb250YWluZXIgbm90IHRvIGJlIGRlc3Ryb3llZCcsICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgIHZhciBub3JtYWxpemVkTmFtZSA9IHRoaXMucmVnaXN0cnkubm9ybWFsaXplKGZ1bGxOYW1lKTsKICAgICAgKGZhbHNlICYmICEodGhpcy5yZWdpc3RyeS5pc1ZhbGlkRnVsbE5hbWUobm9ybWFsaXplZE5hbWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2Z1bGxOYW1lIG11c3QgYmUgYSBwcm9wZXIgZnVsbCBuYW1lJywgdGhpcy5yZWdpc3RyeS5pc1ZhbGlkRnVsbE5hbWUobm9ybWFsaXplZE5hbWUpKSk7CiAgICAgIChmYWxzZSAmJiAhKGZhbHNlCiAgICAgIC8qIEVNQkVSX01PRFVMRV9VTklGSUNBVElPTiAqLwogICAgICB8fCAhb3B0aW9ucy5uYW1lc3BhY2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnRU1CRVJfTU9EVUxFX1VOSUZJQ0FUSU9OIG11c3QgYmUgZW5hYmxlZCB0byBwYXNzIGEgbmFtZXNwYWNlIG9wdGlvbiB0byBmYWN0b3J5Rm9yJywgZmFsc2UgfHwgIW9wdGlvbnMubmFtZXNwYWNlKSk7CgogICAgICBpZiAob3B0aW9ucy5zb3VyY2UgfHwgb3B0aW9ucy5uYW1lc3BhY2UpIHsKICAgICAgICBub3JtYWxpemVkTmFtZSA9IHRoaXMucmVnaXN0cnkuZXhwYW5kTG9jYWxMb29rdXAoZnVsbE5hbWUsIG9wdGlvbnMpOwoKICAgICAgICBpZiAoIW5vcm1hbGl6ZWROYW1lKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gX2ZhY3RvcnlGb3IodGhpcywgbm9ybWFsaXplZE5hbWUsIGZ1bGxOYW1lKTsKICAgIH07CgogICAgcmV0dXJuIENvbnRhaW5lcjsKICB9KCk7CgogIF9leHBvcnRzLkNvbnRhaW5lciA9IENvbnRhaW5lcjsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIENvbnRhaW5lci5fbGVha1RyYWNraW5nID0gbGVha1RyYWNraW5nOwogIH0KICAvKgogICAqIFdyYXAgYSBmYWN0b3J5IG1hbmFnZXIgaW4gYSBwcm94eSB3aGljaCB3aWxsIG5vdCBwZXJtaXQgcHJvcGVydGllcyB0byBiZQogICAqIHNldCBvbiB0aGUgbWFuYWdlci4KICAgKi8KCgogIGZ1bmN0aW9uIHdyYXBNYW5hZ2VySW5EZXByZWNhdGlvblByb3h5KG1hbmFnZXIpIHsKICAgIGlmIChfdXRpbHMuSEFTX05BVElWRV9QUk9YWSkgewogICAgICB2YXIgdmFsaWRhdG9yID0gewogICAgICAgIHNldDogZnVuY3Rpb24gc2V0KF9vYmosIHByb3ApIHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiWW91IGF0dGVtcHRlZCB0byBzZXQgXCIiICsgcHJvcCArICJcIiBvbiBhIGZhY3RvcnkgbWFuYWdlciBjcmVhdGVkIGJ5IGNvbnRhaW5lciNmYWN0b3J5Rm9yLiBBIGZhY3RvcnkgbWFuYWdlciBpcyBhIHJlYWQtb25seSBjb25zdHJ1Y3QuIik7CiAgICAgICAgfQogICAgICB9OyAvLyBOb3RlOgogICAgICAvLyBXZSBoYXZlIHRvIHByb3h5IGFjY2VzcyB0byB0aGUgbWFuYWdlciBoZXJlIHNvIHRoYXQgcHJpdmF0ZSBwcm9wZXJ0eQogICAgICAvLyBhY2Nlc3MgZG9lc24ndCBjYXVzZSB0aGUgYWJvdmUgZXJyb3JzIHRvIG9jY3VyLgoKICAgICAgdmFyIG0gPSBtYW5hZ2VyOwogICAgICB2YXIgcHJveGllZE1hbmFnZXIgPSB7CiAgICAgICAgY2xhc3M6IG0uY2xhc3MsCiAgICAgICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUocHJvcHMpIHsKICAgICAgICAgIHJldHVybiBtLmNyZWF0ZShwcm9wcyk7CiAgICAgICAgfQogICAgICB9OwogICAgICB2YXIgcHJveHkgPSBuZXcgUHJveHkocHJveGllZE1hbmFnZXIsIHZhbGlkYXRvcik7CiAgICAgIEZBQ1RPUllfRk9SLnNldChwcm94eSwgbWFuYWdlcik7CiAgICB9CgogICAgcmV0dXJuIG1hbmFnZXI7CiAgfQoKICBmdW5jdGlvbiBpc1NpbmdsZXRvbihjb250YWluZXIsIGZ1bGxOYW1lKSB7CiAgICByZXR1cm4gY29udGFpbmVyLnJlZ2lzdHJ5LmdldE9wdGlvbihmdWxsTmFtZSwgJ3NpbmdsZXRvbicpICE9PSBmYWxzZTsKICB9CgogIGZ1bmN0aW9uIGlzSW5zdGFudGlhdGFibGUoY29udGFpbmVyLCBmdWxsTmFtZSkgewogICAgcmV0dXJuIGNvbnRhaW5lci5yZWdpc3RyeS5nZXRPcHRpb24oZnVsbE5hbWUsICdpbnN0YW50aWF0ZScpICE9PSBmYWxzZTsKICB9CgogIGZ1bmN0aW9uIF9sb29rdXAoY29udGFpbmVyLCBmdWxsTmFtZSwgb3B0aW9ucykgewogICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICBvcHRpb25zID0ge307CiAgICB9CgogICAgKGZhbHNlICYmICEoZmFsc2UKICAgIC8qIEVNQkVSX01PRFVMRV9VTklGSUNBVElPTiAqLwogICAgfHwgIW9wdGlvbnMubmFtZXNwYWNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0VNQkVSX01PRFVMRV9VTklGSUNBVElPTiBtdXN0IGJlIGVuYWJsZWQgdG8gcGFzcyBhIG5hbWVzcGFjZSBvcHRpb24gdG8gbG9va3VwJywgZmFsc2UgfHwgIW9wdGlvbnMubmFtZXNwYWNlKSk7CiAgICB2YXIgbm9ybWFsaXplZE5hbWUgPSBmdWxsTmFtZTsKCiAgICBpZiAob3B0aW9ucy5zb3VyY2UgfHwgb3B0aW9ucy5uYW1lc3BhY2UpIHsKICAgICAgbm9ybWFsaXplZE5hbWUgPSBjb250YWluZXIucmVnaXN0cnkuZXhwYW5kTG9jYWxMb29rdXAoZnVsbE5hbWUsIG9wdGlvbnMpOwoKICAgICAgaWYgKCFub3JtYWxpemVkTmFtZSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgfQoKICAgIGlmIChvcHRpb25zLnNpbmdsZXRvbiAhPT0gZmFsc2UpIHsKICAgICAgdmFyIGNhY2hlZCA9IGNvbnRhaW5lci5jYWNoZVtub3JtYWxpemVkTmFtZV07CgogICAgICBpZiAoY2FjaGVkICE9PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gY2FjaGVkOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGluc3RhbnRpYXRlRmFjdG9yeShjb250YWluZXIsIG5vcm1hbGl6ZWROYW1lLCBmdWxsTmFtZSwgb3B0aW9ucyk7CiAgfQoKICBmdW5jdGlvbiBfZmFjdG9yeUZvcihjb250YWluZXIsIG5vcm1hbGl6ZWROYW1lLCBmdWxsTmFtZSkgewogICAgdmFyIGNhY2hlZCA9IGNvbnRhaW5lci5mYWN0b3J5TWFuYWdlckNhY2hlW25vcm1hbGl6ZWROYW1lXTsKCiAgICBpZiAoY2FjaGVkICE9PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuIGNhY2hlZDsKICAgIH0KCiAgICB2YXIgZmFjdG9yeSA9IGNvbnRhaW5lci5yZWdpc3RyeS5yZXNvbHZlKG5vcm1hbGl6ZWROYW1lKTsKCiAgICBpZiAoZmFjdG9yeSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICAmJiBmYWN0b3J5ICYmIHR5cGVvZiBmYWN0b3J5Ll9vbkxvb2t1cCA9PT0gJ2Z1bmN0aW9uJykgewogICAgICBmYWN0b3J5Ll9vbkxvb2t1cChmdWxsTmFtZSk7CiAgICB9CgogICAgdmFyIG1hbmFnZXIgPSBuZXcgRmFjdG9yeU1hbmFnZXIoY29udGFpbmVyLCBmYWN0b3J5LCBmdWxsTmFtZSwgbm9ybWFsaXplZE5hbWUpOwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBtYW5hZ2VyID0gd3JhcE1hbmFnZXJJbkRlcHJlY2F0aW9uUHJveHkobWFuYWdlcik7CiAgICB9CgogICAgY29udGFpbmVyLmZhY3RvcnlNYW5hZ2VyQ2FjaGVbbm9ybWFsaXplZE5hbWVdID0gbWFuYWdlcjsKICAgIHJldHVybiBtYW5hZ2VyOwogIH0KCiAgZnVuY3Rpb24gaXNTaW5nbGV0b25DbGFzcyhjb250YWluZXIsIGZ1bGxOYW1lLCBfcmVmMikgewogICAgdmFyIGluc3RhbnRpYXRlID0gX3JlZjIuaW5zdGFudGlhdGUsCiAgICAgICAgc2luZ2xldG9uID0gX3JlZjIuc2luZ2xldG9uOwogICAgcmV0dXJuIHNpbmdsZXRvbiAhPT0gZmFsc2UgJiYgIWluc3RhbnRpYXRlICYmIGlzU2luZ2xldG9uKGNvbnRhaW5lciwgZnVsbE5hbWUpICYmICFpc0luc3RhbnRpYXRhYmxlKGNvbnRhaW5lciwgZnVsbE5hbWUpOwogIH0KCiAgZnVuY3Rpb24gaXNTaW5nbGV0b25JbnN0YW5jZShjb250YWluZXIsIGZ1bGxOYW1lLCBfcmVmMykgewogICAgdmFyIGluc3RhbnRpYXRlID0gX3JlZjMuaW5zdGFudGlhdGUsCiAgICAgICAgc2luZ2xldG9uID0gX3JlZjMuc2luZ2xldG9uOwogICAgcmV0dXJuIHNpbmdsZXRvbiAhPT0gZmFsc2UgJiYgaW5zdGFudGlhdGUgIT09IGZhbHNlICYmIGlzU2luZ2xldG9uKGNvbnRhaW5lciwgZnVsbE5hbWUpICYmIGlzSW5zdGFudGlhdGFibGUoY29udGFpbmVyLCBmdWxsTmFtZSk7CiAgfQoKICBmdW5jdGlvbiBpc0ZhY3RvcnlDbGFzcyhjb250YWluZXIsIGZ1bGxuYW1lLCBfcmVmNCkgewogICAgdmFyIGluc3RhbnRpYXRlID0gX3JlZjQuaW5zdGFudGlhdGUsCiAgICAgICAgc2luZ2xldG9uID0gX3JlZjQuc2luZ2xldG9uOwogICAgcmV0dXJuIGluc3RhbnRpYXRlID09PSBmYWxzZSAmJiAoc2luZ2xldG9uID09PSBmYWxzZSB8fCAhaXNTaW5nbGV0b24oY29udGFpbmVyLCBmdWxsbmFtZSkpICYmICFpc0luc3RhbnRpYXRhYmxlKGNvbnRhaW5lciwgZnVsbG5hbWUpOwogIH0KCiAgZnVuY3Rpb24gaXNGYWN0b3J5SW5zdGFuY2UoY29udGFpbmVyLCBmdWxsTmFtZSwgX3JlZjUpIHsKICAgIHZhciBpbnN0YW50aWF0ZSA9IF9yZWY1Lmluc3RhbnRpYXRlLAogICAgICAgIHNpbmdsZXRvbiA9IF9yZWY1LnNpbmdsZXRvbjsKICAgIHJldHVybiBpbnN0YW50aWF0ZSAhPT0gZmFsc2UgJiYgKHNpbmdsZXRvbiAhPT0gZmFsc2UgfHwgaXNTaW5nbGV0b24oY29udGFpbmVyLCBmdWxsTmFtZSkpICYmIGlzSW5zdGFudGlhdGFibGUoY29udGFpbmVyLCBmdWxsTmFtZSk7CiAgfQoKICBmdW5jdGlvbiBpbnN0YW50aWF0ZUZhY3RvcnkoY29udGFpbmVyLCBub3JtYWxpemVkTmFtZSwgZnVsbE5hbWUsIG9wdGlvbnMpIHsKICAgIHZhciBmYWN0b3J5TWFuYWdlciA9IF9mYWN0b3J5Rm9yKGNvbnRhaW5lciwgbm9ybWFsaXplZE5hbWUsIGZ1bGxOYW1lKTsKCiAgICBpZiAoZmFjdG9yeU1hbmFnZXIgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm47CiAgICB9IC8vIFNvbWVDbGFzcyB7IHNpbmdsZXRvbjogdHJ1ZSwgaW5zdGFudGlhdGU6IHRydWUgfSB8IHsgc2luZ2xldG9uOiB0cnVlIH0gfCB7IGluc3RhbnRpYXRlOiB0cnVlIH0gfCB7fQogICAgLy8gQnkgZGVmYXVsdCBtYWpvcml0eSBvZiBvYmplY3RzIGZhbGwgaW50byB0aGlzIGNhc2UKCgogICAgaWYgKGlzU2luZ2xldG9uSW5zdGFuY2UoY29udGFpbmVyLCBmdWxsTmFtZSwgb3B0aW9ucykpIHsKICAgICAgcmV0dXJuIGNvbnRhaW5lci5jYWNoZVtub3JtYWxpemVkTmFtZV0gPSBmYWN0b3J5TWFuYWdlci5jcmVhdGUoKTsKICAgIH0gLy8gU29tZUNsYXNzIHsgc2luZ2xldG9uOiBmYWxzZSwgaW5zdGFudGlhdGU6IHRydWUgfQoKCiAgICBpZiAoaXNGYWN0b3J5SW5zdGFuY2UoY29udGFpbmVyLCBmdWxsTmFtZSwgb3B0aW9ucykpIHsKICAgICAgcmV0dXJuIGZhY3RvcnlNYW5hZ2VyLmNyZWF0ZSgpOwogICAgfSAvLyBTb21lQ2xhc3MgeyBzaW5nbGV0b246IHRydWUsIGluc3RhbnRpYXRlOiBmYWxzZSB9IHwgeyBpbnN0YW50aWF0ZTogZmFsc2UgfSB8IHsgc2luZ2xldG9uOiBmYWxzZSwgaW5zdGFudGlhdGlvbjogZmFsc2UgfQoKCiAgICBpZiAoaXNTaW5nbGV0b25DbGFzcyhjb250YWluZXIsIGZ1bGxOYW1lLCBvcHRpb25zKSB8fCBpc0ZhY3RvcnlDbGFzcyhjb250YWluZXIsIGZ1bGxOYW1lLCBvcHRpb25zKSkgewogICAgICByZXR1cm4gZmFjdG9yeU1hbmFnZXIuY2xhc3M7CiAgICB9CgogICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgY3JlYXRlIGZhY3RvcnknKTsKICB9CgogIGZ1bmN0aW9uIHByb2Nlc3NJbmplY3Rpb25zKGNvbnRhaW5lciwgaW5qZWN0aW9ucywgcmVzdWx0KSB7CiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgY29udGFpbmVyLnJlZ2lzdHJ5LnZhbGlkYXRlSW5qZWN0aW9ucyhpbmplY3Rpb25zKTsKICAgIH0KCiAgICB2YXIgaGFzaCA9IHJlc3VsdC5pbmplY3Rpb25zOwoKICAgIGlmIChoYXNoID09PSB1bmRlZmluZWQpIHsKICAgICAgaGFzaCA9IHJlc3VsdC5pbmplY3Rpb25zID0ge307CiAgICB9CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmplY3Rpb25zLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBfaW5qZWN0aW9ucyRpID0gaW5qZWN0aW9uc1tpXSwKICAgICAgICAgIHByb3BlcnR5ID0gX2luamVjdGlvbnMkaS5wcm9wZXJ0eSwKICAgICAgICAgIHNwZWNpZmllciA9IF9pbmplY3Rpb25zJGkuc3BlY2lmaWVyLAogICAgICAgICAgc291cmNlID0gX2luamVjdGlvbnMkaS5zb3VyY2U7CgogICAgICBpZiAoc291cmNlKSB7CiAgICAgICAgaGFzaFtwcm9wZXJ0eV0gPSBfbG9va3VwKGNvbnRhaW5lciwgc3BlY2lmaWVyLCB7CiAgICAgICAgICBzb3VyY2U6IHNvdXJjZQogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIGhhc2hbcHJvcGVydHldID0gX2xvb2t1cChjb250YWluZXIsIHNwZWNpZmllcik7CiAgICAgIH0KCiAgICAgIGlmICghcmVzdWx0LmlzRHluYW1pYykgewogICAgICAgIHJlc3VsdC5pc0R5bmFtaWMgPSAhaXNTaW5nbGV0b24oY29udGFpbmVyLCBzcGVjaWZpZXIpOwogICAgICB9CiAgICB9CiAgfQoKICBmdW5jdGlvbiBidWlsZEluamVjdGlvbnMoY29udGFpbmVyLCB0eXBlSW5qZWN0aW9ucywgaW5qZWN0aW9ucykgewogICAgdmFyIHJlc3VsdCA9IHsKICAgICAgaW5qZWN0aW9uczogdW5kZWZpbmVkLAogICAgICBpc0R5bmFtaWM6IGZhbHNlCiAgICB9OwoKICAgIGlmICh0eXBlSW5qZWN0aW9ucyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHByb2Nlc3NJbmplY3Rpb25zKGNvbnRhaW5lciwgdHlwZUluamVjdGlvbnMsIHJlc3VsdCk7CiAgICB9CgogICAgaWYgKGluamVjdGlvbnMgIT09IHVuZGVmaW5lZCkgewogICAgICBwcm9jZXNzSW5qZWN0aW9ucyhjb250YWluZXIsIGluamVjdGlvbnMsIHJlc3VsdCk7CiAgICB9CgogICAgcmV0dXJuIHJlc3VsdDsKICB9CgogIGZ1bmN0aW9uIGluamVjdGlvbnNGb3IoY29udGFpbmVyLCBmdWxsTmFtZSkgewogICAgdmFyIHJlZ2lzdHJ5ID0gY29udGFpbmVyLnJlZ2lzdHJ5OwoKICAgIHZhciBfZnVsbE5hbWUkc3BsaXQgPSBmdWxsTmFtZS5zcGxpdCgnOicpLAogICAgICAgIHR5cGUgPSBfZnVsbE5hbWUkc3BsaXRbMF07CgogICAgdmFyIHR5cGVJbmplY3Rpb25zID0gcmVnaXN0cnkuZ2V0VHlwZUluamVjdGlvbnModHlwZSk7CiAgICB2YXIgaW5qZWN0aW9ucyA9IHJlZ2lzdHJ5LmdldEluamVjdGlvbnMoZnVsbE5hbWUpOwogICAgcmV0dXJuIGJ1aWxkSW5qZWN0aW9ucyhjb250YWluZXIsIHR5cGVJbmplY3Rpb25zLCBpbmplY3Rpb25zKTsKICB9CgogIGZ1bmN0aW9uIGRlc3Ryb3lEZXN0cm95YWJsZXMoY29udGFpbmVyKSB7CiAgICB2YXIgY2FjaGUgPSBjb250YWluZXIuY2FjaGU7CiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGNhY2hlKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGtleSA9IGtleXNbaV07CiAgICAgIHZhciB2YWx1ZSA9IGNhY2hlW2tleV07CgogICAgICBpZiAodmFsdWUuZGVzdHJveSkgewogICAgICAgIHZhbHVlLmRlc3Ryb3koKTsKICAgICAgfQogICAgfQogIH0KCiAgZnVuY3Rpb24gcmVzZXRDYWNoZShjb250YWluZXIpIHsKICAgIGNvbnRhaW5lci5jYWNoZSA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CiAgICBjb250YWluZXIuZmFjdG9yeU1hbmFnZXJDYWNoZSA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CiAgfQoKICBmdW5jdGlvbiByZXNldE1lbWJlcihjb250YWluZXIsIGZ1bGxOYW1lKSB7CiAgICB2YXIgbWVtYmVyID0gY29udGFpbmVyLmNhY2hlW2Z1bGxOYW1lXTsKICAgIGRlbGV0ZSBjb250YWluZXIuZmFjdG9yeU1hbmFnZXJDYWNoZVtmdWxsTmFtZV07CgogICAgaWYgKG1lbWJlcikgewogICAgICBkZWxldGUgY29udGFpbmVyLmNhY2hlW2Z1bGxOYW1lXTsKCiAgICAgIGlmIChtZW1iZXIuZGVzdHJveSkgewogICAgICAgIG1lbWJlci5kZXN0cm95KCk7CiAgICAgIH0KICAgIH0KICB9CgogIHZhciBGQUNUT1JZX0ZPUiA9IG5ldyBXZWFrTWFwKCk7CiAgX2V4cG9ydHMuRkFDVE9SWV9GT1IgPSBGQUNUT1JZX0ZPUjsKCiAgdmFyIEZhY3RvcnlNYW5hZ2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRmFjdG9yeU1hbmFnZXIoY29udGFpbmVyLCBmYWN0b3J5LCBmdWxsTmFtZSwgbm9ybWFsaXplZE5hbWUpIHsKICAgICAgdGhpcy5jb250YWluZXIgPSBjb250YWluZXI7CiAgICAgIHRoaXMub3duZXIgPSBjb250YWluZXIub3duZXI7CiAgICAgIHRoaXMuY2xhc3MgPSBmYWN0b3J5OwogICAgICB0aGlzLmZ1bGxOYW1lID0gZnVsbE5hbWU7CiAgICAgIHRoaXMubm9ybWFsaXplZE5hbWUgPSBub3JtYWxpemVkTmFtZTsKICAgICAgdGhpcy5tYWRlVG9TdHJpbmcgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuaW5qZWN0aW9ucyA9IHVuZGVmaW5lZDsKICAgICAgRkFDVE9SWV9GT1Iuc2V0KHRoaXMsIHRoaXMpOwogICAgfQoKICAgIHZhciBfcHJvdG8yID0gRmFjdG9yeU1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzIudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgaWYgKHRoaXMubWFkZVRvU3RyaW5nID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLm1hZGVUb1N0cmluZyA9IHRoaXMuY29udGFpbmVyLnJlZ2lzdHJ5Lm1ha2VUb1N0cmluZyh0aGlzLmNsYXNzLCB0aGlzLmZ1bGxOYW1lKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMubWFkZVRvU3RyaW5nOwogICAgfTsKCiAgICBfcHJvdG8yLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShvcHRpb25zKSB7CiAgICAgIHZhciBpbmplY3Rpb25zQ2FjaGUgPSB0aGlzLmluamVjdGlvbnM7CgogICAgICBpZiAoaW5qZWN0aW9uc0NhY2hlID09PSB1bmRlZmluZWQpIHsKICAgICAgICB2YXIgX2luamVjdGlvbnNGb3IgPSBpbmplY3Rpb25zRm9yKHRoaXMuY29udGFpbmVyLCB0aGlzLm5vcm1hbGl6ZWROYW1lKSwKICAgICAgICAgICAgaW5qZWN0aW9ucyA9IF9pbmplY3Rpb25zRm9yLmluamVjdGlvbnMsCiAgICAgICAgICAgIGlzRHluYW1pYyA9IF9pbmplY3Rpb25zRm9yLmlzRHluYW1pYzsKCiAgICAgICAgaW5qZWN0aW9uc0NhY2hlID0gaW5qZWN0aW9uczsKCiAgICAgICAgaWYgKCFpc0R5bmFtaWMpIHsKICAgICAgICAgIHRoaXMuaW5qZWN0aW9ucyA9IGluamVjdGlvbnM7CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgcHJvcHMgPSBpbmplY3Rpb25zQ2FjaGU7CgogICAgICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcHJvcHMgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBpbmplY3Rpb25zQ2FjaGUsIG9wdGlvbnMpOwogICAgICB9CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgdmFyIGxhenlJbmplY3Rpb25zOwogICAgICAgIHZhciB2YWxpZGF0aW9uQ2FjaGUgPSB0aGlzLmNvbnRhaW5lci52YWxpZGF0aW9uQ2FjaGU7IC8vIEVuc3VyZSB0aGF0IGFsbCBsYXp5IGluamVjdGlvbnMgYXJlIHZhbGlkIGF0IGluc3RhbnRpYXRpb24gdGltZQoKICAgICAgICBpZiAoIXZhbGlkYXRpb25DYWNoZVt0aGlzLmZ1bGxOYW1lXSAmJiB0aGlzLmNsYXNzICYmIHR5cGVvZiB0aGlzLmNsYXNzLl9sYXp5SW5qZWN0aW9ucyA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgICAgbGF6eUluamVjdGlvbnMgPSB0aGlzLmNsYXNzLl9sYXp5SW5qZWN0aW9ucygpOwogICAgICAgICAgbGF6eUluamVjdGlvbnMgPSB0aGlzLmNvbnRhaW5lci5yZWdpc3RyeS5ub3JtYWxpemVJbmplY3Rpb25zSGFzaChsYXp5SW5qZWN0aW9ucyk7CiAgICAgICAgICB0aGlzLmNvbnRhaW5lci5yZWdpc3RyeS52YWxpZGF0ZUluamVjdGlvbnMobGF6eUluamVjdGlvbnMpOwogICAgICAgIH0KCiAgICAgICAgdmFsaWRhdGlvbkNhY2hlW3RoaXMuZnVsbE5hbWVdID0gdHJ1ZTsKICAgICAgfQoKICAgICAgaWYgKCF0aGlzLmNsYXNzLmNyZWF0ZSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiRmFpbGVkIHRvIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiAnIiArIHRoaXMubm9ybWFsaXplZE5hbWUgKyAiJy4gTW9zdCBsaWtlbHkgYW4gaW1wcm9wZXJseSBkZWZpbmVkIGNsYXNzIG9yIGFuIGludmFsaWQgbW9kdWxlIGV4cG9ydC4iKTsKICAgICAgfSAvLyByZXF1aXJlZCB0byBhbGxvdyBhY2Nlc3MgdG8gdGhpbmdzIGxpa2UKICAgICAgLy8gdGhlIGN1c3RvbWl6ZWQgdG9TdHJpbmcsIF9kZWJ1Z0NvbnRhaW5lcktleSwKICAgICAgLy8gb3duZXIsIGV0Yy4gd2l0aG91dCBhIGRvdWJsZSBleHRlbmQgYW5kIHdpdGhvdXQKICAgICAgLy8gbW9kaWZ5aW5nIHRoZSBvYmplY3RzIHByb3BlcnRpZXMKCgogICAgICBpZiAodHlwZW9mIHRoaXMuY2xhc3MuX2luaXRGYWN0b3J5ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgdGhpcy5jbGFzcy5faW5pdEZhY3RvcnkodGhpcyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gaW4gdGhlIG5vbi1FbWJlck9iamVjdCBjYXNlIHdlIG5lZWQgdG8gc3RpbGwgc2V0T3duZXIKICAgICAgICAvLyB0aGlzIGlzIHJlcXVpcmVkIGZvciBzdXBwb3J0aW5nIGdsaW1tZXIgZW52aXJvbm1lbnQgYW5kCiAgICAgICAgLy8gdGVtcGxhdGUgaW5zdGFudGlhdGlvbiB3aGljaCByZWx5IGhlYXZpbHkgb24KICAgICAgICAvLyBgb3B0aW9uc1tPV05FUl1gIGJlaW5nIHBhc3NlZCBpbnRvIGBjcmVhdGVgCiAgICAgICAgLy8gVE9ETzogY2xlYW4gdGhpcyB1cCwgYW5kIHJlbW92ZSBpbiBmdXR1cmUgdmVyc2lvbnMKICAgICAgICBpZiAob3B0aW9ucyA9PT0gdW5kZWZpbmVkIHx8IHByb3BzID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIC8vIGF2b2lkIG11dGF0aW5nIGBwcm9wc2AgaGVyZSBzaW5jZSB0aGV5IGFyZSB0aGUgY2FjaGVkIGluamVjdGlvbnMKICAgICAgICAgIHByb3BzID0gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgcHJvcHMpOwogICAgICAgIH0KCiAgICAgICAgKDAsIF9vd25lci5zZXRPd25lcikocHJvcHMsIHRoaXMub3duZXIpOwogICAgICB9CgogICAgICB2YXIgaW5zdGFuY2UgPSB0aGlzLmNsYXNzLmNyZWF0ZShwcm9wcyk7CiAgICAgIEZBQ1RPUllfRk9SLnNldChpbnN0YW5jZSwgdGhpcyk7CiAgICAgIHJldHVybiBpbnN0YW5jZTsKICAgIH07CgogICAgcmV0dXJuIEZhY3RvcnlNYW5hZ2VyOwogIH0oKTsKCiAgdmFyIFZBTElEX0ZVTExfTkFNRV9SRUdFWFAgPSAvXlteOl0rOlteOl0rJC87CiAgLyoqCiAgIEEgcmVnaXN0cnkgdXNlZCB0byBzdG9yZSBmYWN0b3J5IGFuZCBvcHRpb24gaW5mb3JtYXRpb24ga2V5ZWQKICAgYnkgdHlwZS4KICAKICAgQSBgUmVnaXN0cnlgIHN0b3JlcyB0aGUgZmFjdG9yeSBhbmQgb3B0aW9uIGluZm9ybWF0aW9uIG5lZWRlZCBieSBhCiAgIGBDb250YWluZXJgIHRvIGluc3RhbnRpYXRlIGFuZCBjYWNoZSBvYmplY3RzLgogIAogICBUaGUgQVBJIGZvciBgUmVnaXN0cnlgIGlzIHN0aWxsIGluIGZsdXggYW5kIHNob3VsZCBub3QgYmUgY29uc2lkZXJlZCBzdGFibGUuCiAgCiAgIEBwcml2YXRlCiAgIEBjbGFzcyBSZWdpc3RyeQogICBAc2luY2UgMS4xMS4wCiAgKi8KCiAgdmFyIFJlZ2lzdHJ5ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUmVnaXN0cnkob3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICB0aGlzLmZhbGxiYWNrID0gb3B0aW9ucy5mYWxsYmFjayB8fCBudWxsOwogICAgICB0aGlzLnJlc29sdmVyID0gb3B0aW9ucy5yZXNvbHZlciB8fCBudWxsOwogICAgICB0aGlzLnJlZ2lzdHJhdGlvbnMgPSAoMCwgX3V0aWxzLmRpY3Rpb25hcnkpKG9wdGlvbnMucmVnaXN0cmF0aW9ucyB8fCBudWxsKTsKICAgICAgdGhpcy5fdHlwZUluamVjdGlvbnMgPSAoMCwgX3V0aWxzLmRpY3Rpb25hcnkpKG51bGwpOwogICAgICB0aGlzLl9pbmplY3Rpb25zID0gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgICAgdGhpcy5fbG9jYWxMb29rdXBDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHRoaXMuX25vcm1hbGl6ZUNhY2hlID0gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgICAgdGhpcy5fcmVzb2x2ZUNhY2hlID0gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgICAgdGhpcy5fZmFpbFNldCA9IG5ldyBTZXQoKTsKICAgICAgdGhpcy5fb3B0aW9ucyA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CiAgICAgIHRoaXMuX3R5cGVPcHRpb25zID0gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgIH0KICAgIC8qKgogICAgIEEgYmFja3VwIHJlZ2lzdHJ5IGZvciByZXNvbHZpbmcgcmVnaXN0cmF0aW9ucyB3aGVuIG5vIG1hdGNoZXMgY2FuIGJlIGZvdW5kLgogICAgICAgIEBwcml2YXRlCiAgICAgQHByb3BlcnR5IGZhbGxiYWNrCiAgICAgQHR5cGUgUmVnaXN0cnkKICAgICAqLwoKICAgIC8qKgogICAgIEFuIG9iamVjdCB0aGF0IGhhcyBhIGByZXNvbHZlYCBtZXRob2QgdGhhdCByZXNvbHZlcyBhIG5hbWUuCiAgICAgICAgQHByaXZhdGUKICAgICBAcHJvcGVydHkgcmVzb2x2ZXIKICAgICBAdHlwZSBSZXNvbHZlcgogICAgICovCgogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICBAcHJvcGVydHkgcmVnaXN0cmF0aW9ucwogICAgIEB0eXBlIEluaGVyaXRpbmdEaWN0CiAgICAgKi8KCiAgICAvKioKICAgICBAcHJpdmF0ZQogICAgICAgIEBwcm9wZXJ0eSBfdHlwZUluamVjdGlvbnMKICAgICBAdHlwZSBJbmhlcml0aW5nRGljdAogICAgICovCgogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICAgICBAcHJvcGVydHkgX2luamVjdGlvbnMKICAgICBAdHlwZSBJbmhlcml0aW5nRGljdAogICAgICovCgogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICAgICBAcHJvcGVydHkgX25vcm1hbGl6ZUNhY2hlCiAgICAgQHR5cGUgSW5oZXJpdGluZ0RpY3QKICAgICAqLwoKICAgIC8qKgogICAgIEBwcml2YXRlCiAgICAgICAgQHByb3BlcnR5IF9yZXNvbHZlQ2FjaGUKICAgICBAdHlwZSBJbmhlcml0aW5nRGljdAogICAgICovCgogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICAgICBAcHJvcGVydHkgX29wdGlvbnMKICAgICBAdHlwZSBJbmhlcml0aW5nRGljdAogICAgICovCgogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICAgICBAcHJvcGVydHkgX3R5cGVPcHRpb25zCiAgICAgQHR5cGUgSW5oZXJpdGluZ0RpY3QKICAgICAqLwoKICAgIC8qKgogICAgIENyZWF0ZXMgYSBjb250YWluZXIgYmFzZWQgb24gdGhpcyByZWdpc3RyeS4KICAgICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2QgY29udGFpbmVyCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICBAcmV0dXJuIHtDb250YWluZXJ9IGNyZWF0ZWQgY29udGFpbmVyCiAgICAgKi8KCgogICAgdmFyIF9wcm90bzMgPSBSZWdpc3RyeS5wcm90b3R5cGU7CgogICAgX3Byb3RvMy5jb250YWluZXIgPSBmdW5jdGlvbiBjb250YWluZXIob3B0aW9ucykgewogICAgICByZXR1cm4gbmV3IENvbnRhaW5lcih0aGlzLCBvcHRpb25zKTsKICAgIH0KICAgIC8qKgogICAgIFJlZ2lzdGVycyBhIGZhY3RvcnkgZm9yIGxhdGVyIGluamVjdGlvbi4KICAgICAgICBFeGFtcGxlOgogICAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoKTsKICAgICAgICByZWdpc3RyeS5yZWdpc3RlcignbW9kZWw6dXNlcicsIFBlcnNvbiwge3NpbmdsZXRvbjogZmFsc2UgfSk7CiAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJ2ZydWl0OmZhdm9yaXRlJywgT3JhbmdlKTsKICAgICByZWdpc3RyeS5yZWdpc3RlcignY29tbXVuaWNhdGlvbjptYWluJywgRW1haWwsIHtzaW5nbGV0b246IGZhbHNlfSk7CiAgICAgYGBgCiAgICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIHJlZ2lzdGVyCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHBhcmFtIHtGdW5jdGlvbn0gZmFjdG9yeQogICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zLnJlZ2lzdGVyID0gZnVuY3Rpb24gcmVnaXN0ZXIoZnVsbE5hbWUsIGZhY3RvcnksIG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgfQoKICAgICAgKGZhbHNlICYmICEodGhpcy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2Z1bGxOYW1lIG11c3QgYmUgYSBwcm9wZXIgZnVsbCBuYW1lJywgdGhpcy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSk7CiAgICAgIChmYWxzZSAmJiAhKGZhY3RvcnkgIT09IHVuZGVmaW5lZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJBdHRlbXB0aW5nIHRvIHJlZ2lzdGVyIGFuIHVua25vd24gZmFjdG9yeTogJyIgKyBmdWxsTmFtZSArICInIiwgZmFjdG9yeSAhPT0gdW5kZWZpbmVkKSk7CiAgICAgIHZhciBub3JtYWxpemVkTmFtZSA9IHRoaXMubm9ybWFsaXplKGZ1bGxOYW1lKTsKICAgICAgKGZhbHNlICYmICEoIXRoaXMuX3Jlc29sdmVDYWNoZVtub3JtYWxpemVkTmFtZV0pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IHJlLXJlZ2lzdGVyOiAnIiArIGZ1bGxOYW1lICsgIicsIGFzIGl0IGhhcyBhbHJlYWR5IGJlZW4gcmVzb2x2ZWQuIiwgIXRoaXMuX3Jlc29sdmVDYWNoZVtub3JtYWxpemVkTmFtZV0pKTsKCiAgICAgIHRoaXMuX2ZhaWxTZXQuZGVsZXRlKG5vcm1hbGl6ZWROYW1lKTsKCiAgICAgIHRoaXMucmVnaXN0cmF0aW9uc1tub3JtYWxpemVkTmFtZV0gPSBmYWN0b3J5OwogICAgICB0aGlzLl9vcHRpb25zW25vcm1hbGl6ZWROYW1lXSA9IG9wdGlvbnM7CiAgICB9CiAgICAvKioKICAgICBVbnJlZ2lzdGVyIGEgZnVsbE5hbWUKICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJ21vZGVsOnVzZXInLCBVc2VyKTsKICAgICAgICByZWdpc3RyeS5yZXNvbHZlKCdtb2RlbDp1c2VyJykuY3JlYXRlKCkgaW5zdGFuY2VvZiBVc2VyIC8vPT4gdHJ1ZQogICAgICAgIHJlZ2lzdHJ5LnVucmVnaXN0ZXIoJ21vZGVsOnVzZXInKQogICAgIHJlZ2lzdHJ5LnJlc29sdmUoJ21vZGVsOnVzZXInKSA9PT0gdW5kZWZpbmVkIC8vPT4gdHJ1ZQogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCB1bnJlZ2lzdGVyCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zLnVucmVnaXN0ZXIgPSBmdW5jdGlvbiB1bnJlZ2lzdGVyKGZ1bGxOYW1lKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdmdWxsTmFtZSBtdXN0IGJlIGEgcHJvcGVyIGZ1bGwgbmFtZScsIHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkpOwogICAgICB2YXIgbm9ybWFsaXplZE5hbWUgPSB0aGlzLm5vcm1hbGl6ZShmdWxsTmFtZSk7CiAgICAgIHRoaXMuX2xvY2FsTG9va3VwQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBkZWxldGUgdGhpcy5yZWdpc3RyYXRpb25zW25vcm1hbGl6ZWROYW1lXTsKICAgICAgZGVsZXRlIHRoaXMuX3Jlc29sdmVDYWNoZVtub3JtYWxpemVkTmFtZV07CiAgICAgIGRlbGV0ZSB0aGlzLl9vcHRpb25zW25vcm1hbGl6ZWROYW1lXTsKCiAgICAgIHRoaXMuX2ZhaWxTZXQuZGVsZXRlKG5vcm1hbGl6ZWROYW1lKTsKICAgIH0KICAgIC8qKgogICAgIEdpdmVuIGEgZnVsbE5hbWUgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIGZhY3RvcnkuCiAgICAgICAgQnkgZGVmYXVsdCBgcmVzb2x2ZWAgd2lsbCByZXRyaWV2ZSB0aGUgZmFjdG9yeSBmcm9tCiAgICAgdGhlIHJlZ2lzdHJ5LgogICAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoKTsKICAgICByZWdpc3RyeS5yZWdpc3RlcignYXBpOnR3aXR0ZXInLCBUd2l0dGVyKTsKICAgICAgICByZWdpc3RyeS5yZXNvbHZlKCdhcGk6dHdpdHRlcicpIC8vID0+IFR3aXR0ZXIKICAgICBgYGAKICAgICAgICBPcHRpb25hbGx5IHRoZSByZWdpc3RyeSBjYW4gYmUgcHJvdmlkZWQgd2l0aCBhIGN1c3RvbSByZXNvbHZlci4KICAgICBJZiBwcm92aWRlZCwgYHJlc29sdmVgIHdpbGwgZmlyc3QgcHJvdmlkZSB0aGUgY3VzdG9tIHJlc29sdmVyCiAgICAgdGhlIG9wcG9ydHVuaXR5IHRvIHJlc29sdmUgdGhlIGZ1bGxOYW1lLCBvdGhlcndpc2UgaXQgd2lsbCBmYWxsYmFjawogICAgIHRvIHRoZSByZWdpc3RyeS4KICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgcmVnaXN0cnkucmVzb2x2ZXIgPSBmdW5jdGlvbihmdWxsTmFtZSkgewogICAgICAgIC8vIGxvb2t1cCB2aWEgdGhlIG1vZHVsZSBzeXN0ZW0gb2YgY2hvaWNlCiAgICAgIH07CiAgICAgICAgLy8gdGhlIHR3aXR0ZXIgZmFjdG9yeSBpcyBhZGRlZCB0byB0aGUgbW9kdWxlIHN5c3RlbQogICAgIHJlZ2lzdHJ5LnJlc29sdmUoJ2FwaTp0d2l0dGVyJykgLy8gPT4gVHdpdHRlcgogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCByZXNvbHZlCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXQogICAgIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5zb3VyY2VdIHRoZSBmdWxsbmFtZSBvZiB0aGUgcmVxdWVzdCBzb3VyY2UgKHVzZWQgZm9yIGxvY2FsIGxvb2t1cHMpCiAgICAgQHJldHVybiB7RnVuY3Rpb259IGZ1bGxOYW1lJ3MgZmFjdG9yeQogICAgICovCiAgICA7CgogICAgX3Byb3RvMy5yZXNvbHZlID0gZnVuY3Rpb24gcmVzb2x2ZShmdWxsTmFtZSwgb3B0aW9ucykgewogICAgICB2YXIgZmFjdG9yeSA9IF9yZXNvbHZlKHRoaXMsIHRoaXMubm9ybWFsaXplKGZ1bGxOYW1lKSwgb3B0aW9ucyk7CgogICAgICBpZiAoZmFjdG9yeSA9PT0gdW5kZWZpbmVkICYmIHRoaXMuZmFsbGJhY2sgIT09IG51bGwpIHsKICAgICAgICB2YXIgX3RoaXMkZmFsbGJhY2s7CgogICAgICAgIGZhY3RvcnkgPSAoX3RoaXMkZmFsbGJhY2sgPSB0aGlzLmZhbGxiYWNrKS5yZXNvbHZlLmFwcGx5KF90aGlzJGZhbGxiYWNrLCBhcmd1bWVudHMpOwogICAgICB9CgogICAgICByZXR1cm4gZmFjdG9yeTsKICAgIH0KICAgIC8qKgogICAgIEEgaG9vayB0aGF0IGNhbiBiZSB1c2VkIHRvIGRlc2NyaWJlIGhvdyB0aGUgcmVzb2x2ZXIgd2lsbAogICAgIGF0dGVtcHQgdG8gZmluZCB0aGUgZmFjdG9yeS4KICAgICAgICBGb3IgZXhhbXBsZSwgdGhlIGRlZmF1bHQgRW1iZXIgYC5kZXNjcmliZWAgcmV0dXJucyB0aGUgZnVsbAogICAgIGNsYXNzIG5hbWUgKGluY2x1ZGluZyBuYW1lc3BhY2UpIHdoZXJlIEVtYmVyJ3MgcmVzb2x2ZXIgZXhwZWN0cwogICAgIHRvIGZpbmQgdGhlIGBmdWxsTmFtZWAuCiAgICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIGRlc2NyaWJlCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHJldHVybiB7c3RyaW5nfSBkZXNjcmliZWQgZnVsbE5hbWUKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMuZGVzY3JpYmUgPSBmdW5jdGlvbiBkZXNjcmliZShmdWxsTmFtZSkgewogICAgICBpZiAodGhpcy5yZXNvbHZlciAhPT0gbnVsbCAmJiB0aGlzLnJlc29sdmVyLmxvb2t1cERlc2NyaXB0aW9uKSB7CiAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZXIubG9va3VwRGVzY3JpcHRpb24oZnVsbE5hbWUpOwogICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2sgIT09IG51bGwpIHsKICAgICAgICByZXR1cm4gdGhpcy5mYWxsYmFjay5kZXNjcmliZShmdWxsTmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGZ1bGxOYW1lOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICBBIGhvb2sgdG8gZW5hYmxlIGN1c3RvbSBmdWxsTmFtZSBub3JtYWxpemF0aW9uIGJlaGF2aW9yCiAgICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIG5vcm1hbGl6ZUZ1bGxOYW1lCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHJldHVybiB7c3RyaW5nfSBub3JtYWxpemVkIGZ1bGxOYW1lCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zLm5vcm1hbGl6ZUZ1bGxOYW1lID0gZnVuY3Rpb24gbm9ybWFsaXplRnVsbE5hbWUoZnVsbE5hbWUpIHsKICAgICAgaWYgKHRoaXMucmVzb2x2ZXIgIT09IG51bGwgJiYgdGhpcy5yZXNvbHZlci5ub3JtYWxpemUpIHsKICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlci5ub3JtYWxpemUoZnVsbE5hbWUpOwogICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2sgIT09IG51bGwpIHsKICAgICAgICByZXR1cm4gdGhpcy5mYWxsYmFjay5ub3JtYWxpemVGdWxsTmFtZShmdWxsTmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGZ1bGxOYW1lOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICBOb3JtYWxpemUgYSBmdWxsTmFtZSBiYXNlZCBvbiB0aGUgYXBwbGljYXRpb24ncyBjb252ZW50aW9ucwogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBub3JtYWxpemUKICAgICBAcGFyYW0ge1N0cmluZ30gZnVsbE5hbWUKICAgICBAcmV0dXJuIHtzdHJpbmd9IG5vcm1hbGl6ZWQgZnVsbE5hbWUKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMubm9ybWFsaXplID0gZnVuY3Rpb24gbm9ybWFsaXplKGZ1bGxOYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLl9ub3JtYWxpemVDYWNoZVtmdWxsTmFtZV0gfHwgKHRoaXMuX25vcm1hbGl6ZUNhY2hlW2Z1bGxOYW1lXSA9IHRoaXMubm9ybWFsaXplRnVsbE5hbWUoZnVsbE5hbWUpKTsKICAgIH0KICAgIC8qKgogICAgIEBtZXRob2QgbWFrZVRvU3RyaW5nCiAgICAgICAgQHByaXZhdGUKICAgICBAcGFyYW0ge2FueX0gZmFjdG9yeQogICAgIEBwYXJhbSB7c3RyaW5nfSBmdWxsTmFtZQogICAgIEByZXR1cm4ge2Z1bmN0aW9ufSB0b1N0cmluZyBmdW5jdGlvbgogICAgICovCiAgICA7CgogICAgX3Byb3RvMy5tYWtlVG9TdHJpbmcgPSBmdW5jdGlvbiBtYWtlVG9TdHJpbmcoZmFjdG9yeSwgZnVsbE5hbWUpIHsKICAgICAgaWYgKHRoaXMucmVzb2x2ZXIgIT09IG51bGwgJiYgdGhpcy5yZXNvbHZlci5tYWtlVG9TdHJpbmcpIHsKICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlci5tYWtlVG9TdHJpbmcoZmFjdG9yeSwgZnVsbE5hbWUpOwogICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2sgIT09IG51bGwpIHsKICAgICAgICByZXR1cm4gdGhpcy5mYWxsYmFjay5tYWtlVG9TdHJpbmcoZmFjdG9yeSwgZnVsbE5hbWUpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBmYWN0b3J5LnRvU3RyaW5nKCk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgIEdpdmVuIGEgZnVsbE5hbWUgY2hlY2sgaWYgdGhlIGNvbnRhaW5lciBpcyBhd2FyZSBvZiBpdHMgZmFjdG9yeQogICAgIG9yIHNpbmdsZXRvbiBpbnN0YW5jZS4KICAgICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2QgaGFzCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXQogICAgIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5zb3VyY2VdIHRoZSBmdWxsbmFtZSBvZiB0aGUgcmVxdWVzdCBzb3VyY2UgKHVzZWQgZm9yIGxvY2FsIGxvb2t1cHMpCiAgICAgQHJldHVybiB7Qm9vbGVhbn0KICAgICAqLwogICAgOwoKICAgIF9wcm90bzMuaGFzID0gZnVuY3Rpb24gaGFzKGZ1bGxOYW1lLCBvcHRpb25zKSB7CiAgICAgIGlmICghdGhpcy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CgogICAgICB2YXIgc291cmNlID0gb3B0aW9ucyAmJiBvcHRpb25zLnNvdXJjZSAmJiB0aGlzLm5vcm1hbGl6ZShvcHRpb25zLnNvdXJjZSk7CiAgICAgIHZhciBuYW1lc3BhY2UgPSBvcHRpb25zICYmIG9wdGlvbnMubmFtZXNwYWNlIHx8IHVuZGVmaW5lZDsKICAgICAgcmV0dXJuIF9oYXModGhpcywgdGhpcy5ub3JtYWxpemUoZnVsbE5hbWUpLCBzb3VyY2UsIG5hbWVzcGFjZSk7CiAgICB9CiAgICAvKioKICAgICBBbGxvdyByZWdpc3RlcmluZyBvcHRpb25zIGZvciBhbGwgZmFjdG9yaWVzIG9mIGEgdHlwZS4KICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgbGV0IGNvbnRhaW5lciA9IHJlZ2lzdHJ5LmNvbnRhaW5lcigpOwogICAgICAgIC8vIGlmIGFsbCBvZiB0eXBlIGBjb25uZWN0aW9uYCBtdXN0IG5vdCBiZSBzaW5nbGV0b25zCiAgICAgcmVnaXN0cnkub3B0aW9uc0ZvclR5cGUoJ2Nvbm5lY3Rpb24nLCB7IHNpbmdsZXRvbjogZmFsc2UgfSk7CiAgICAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJ2Nvbm5lY3Rpb246dHdpdHRlcicsIFR3aXR0ZXJDb25uZWN0aW9uKTsKICAgICByZWdpc3RyeS5yZWdpc3RlcignY29ubmVjdGlvbjpmYWNlYm9vaycsIEZhY2Vib29rQ29ubmVjdGlvbik7CiAgICAgICAgbGV0IHR3aXR0ZXIgPSBjb250YWluZXIubG9va3VwKCdjb25uZWN0aW9uOnR3aXR0ZXInKTsKICAgICBsZXQgdHdpdHRlcjIgPSBjb250YWluZXIubG9va3VwKCdjb25uZWN0aW9uOnR3aXR0ZXInKTsKICAgICAgICB0d2l0dGVyID09PSB0d2l0dGVyMjsgLy8gPT4gZmFsc2UKICAgICAgICBsZXQgZmFjZWJvb2sgPSBjb250YWluZXIubG9va3VwKCdjb25uZWN0aW9uOmZhY2Vib29rJyk7CiAgICAgbGV0IGZhY2Vib29rMiA9IGNvbnRhaW5lci5sb29rdXAoJ2Nvbm5lY3Rpb246ZmFjZWJvb2snKTsKICAgICAgICBmYWNlYm9vayA9PT0gZmFjZWJvb2syOyAvLyA9PiBmYWxzZQogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBvcHRpb25zRm9yVHlwZQogICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMub3B0aW9uc0ZvclR5cGUgPSBmdW5jdGlvbiBvcHRpb25zRm9yVHlwZSh0eXBlLCBvcHRpb25zKSB7CiAgICAgIHRoaXMuX3R5cGVPcHRpb25zW3R5cGVdID0gb3B0aW9uczsKICAgIH07CgogICAgX3Byb3RvMy5nZXRPcHRpb25zRm9yVHlwZSA9IGZ1bmN0aW9uIGdldE9wdGlvbnNGb3JUeXBlKHR5cGUpIHsKICAgICAgdmFyIG9wdGlvbnNGb3JUeXBlID0gdGhpcy5fdHlwZU9wdGlvbnNbdHlwZV07CgogICAgICBpZiAob3B0aW9uc0ZvclR5cGUgPT09IHVuZGVmaW5lZCAmJiB0aGlzLmZhbGxiYWNrICE9PSBudWxsKSB7CiAgICAgICAgb3B0aW9uc0ZvclR5cGUgPSB0aGlzLmZhbGxiYWNrLmdldE9wdGlvbnNGb3JUeXBlKHR5cGUpOwogICAgICB9CgogICAgICByZXR1cm4gb3B0aW9uc0ZvclR5cGU7CiAgICB9CiAgICAvKioKICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2Qgb3B0aW9ucwogICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZQogICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zLm9wdGlvbnMgPSBmdW5jdGlvbiBvcHRpb25zKGZ1bGxOYW1lLCBfb3B0aW9ucykgewogICAgICB2YXIgbm9ybWFsaXplZE5hbWUgPSB0aGlzLm5vcm1hbGl6ZShmdWxsTmFtZSk7CiAgICAgIHRoaXMuX29wdGlvbnNbbm9ybWFsaXplZE5hbWVdID0gX29wdGlvbnM7CiAgICB9OwoKICAgIF9wcm90bzMuZ2V0T3B0aW9ucyA9IGZ1bmN0aW9uIGdldE9wdGlvbnMoZnVsbE5hbWUpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWROYW1lID0gdGhpcy5ub3JtYWxpemUoZnVsbE5hbWUpOwogICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuX29wdGlvbnNbbm9ybWFsaXplZE5hbWVdOwoKICAgICAgaWYgKG9wdGlvbnMgPT09IHVuZGVmaW5lZCAmJiB0aGlzLmZhbGxiYWNrICE9PSBudWxsKSB7CiAgICAgICAgb3B0aW9ucyA9IHRoaXMuZmFsbGJhY2suZ2V0T3B0aW9ucyhmdWxsTmFtZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBvcHRpb25zOwogICAgfTsKCiAgICBfcHJvdG8zLmdldE9wdGlvbiA9IGZ1bmN0aW9uIGdldE9wdGlvbihmdWxsTmFtZSwgb3B0aW9uTmFtZSkgewogICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuX29wdGlvbnNbZnVsbE5hbWVdOwoKICAgICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zW29wdGlvbk5hbWVdICE9PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gb3B0aW9uc1tvcHRpb25OYW1lXTsKICAgICAgfQoKICAgICAgdmFyIHR5cGUgPSBmdWxsTmFtZS5zcGxpdCgnOicpWzBdOwogICAgICBvcHRpb25zID0gdGhpcy5fdHlwZU9wdGlvbnNbdHlwZV07CgogICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zW29wdGlvbk5hbWVdICE9PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gb3B0aW9uc1tvcHRpb25OYW1lXTsKICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrICE9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZmFsbGJhY2suZ2V0T3B0aW9uKGZ1bGxOYW1lLCBvcHRpb25OYW1lKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH0KICAgIC8qKgogICAgIFVzZWQgb25seSB2aWEgYGluamVjdGlvbmAuCiAgICAgICAgUHJvdmlkZXMgYSBzcGVjaWFsaXplZCBmb3JtIG9mIGluamVjdGlvbiwgc3BlY2lmaWNhbGx5IGVuYWJsaW5nCiAgICAgYWxsIG9iamVjdHMgb2Ygb25lIHR5cGUgdG8gYmUgaW5qZWN0ZWQgd2l0aCBhIHJlZmVyZW5jZSB0byBhbm90aGVyCiAgICAgb2JqZWN0LgogICAgICAgIEZvciBleGFtcGxlLCBwcm92aWRlZCBlYWNoIG9iamVjdCBvZiB0eXBlIGBjb250cm9sbGVyYCBuZWVkZWQgYSBgcm91dGVyYC4KICAgICBvbmUgd291bGQgZG8gdGhlIGZvbGxvd2luZzoKICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgbGV0IGNvbnRhaW5lciA9IHJlZ2lzdHJ5LmNvbnRhaW5lcigpOwogICAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdyb3V0ZXI6bWFpbicsIFJvdXRlcik7CiAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJ2NvbnRyb2xsZXI6dXNlcicsIFVzZXJDb250cm9sbGVyKTsKICAgICByZWdpc3RyeS5yZWdpc3RlcignY29udHJvbGxlcjpwb3N0JywgUG9zdENvbnRyb2xsZXIpOwogICAgICAgIHJlZ2lzdHJ5LnR5cGVJbmplY3Rpb24oJ2NvbnRyb2xsZXInLCAncm91dGVyJywgJ3JvdXRlcjptYWluJyk7CiAgICAgICAgbGV0IHVzZXIgPSBjb250YWluZXIubG9va3VwKCdjb250cm9sbGVyOnVzZXInKTsKICAgICBsZXQgcG9zdCA9IGNvbnRhaW5lci5sb29rdXAoJ2NvbnRyb2xsZXI6cG9zdCcpOwogICAgICAgIHVzZXIucm91dGVyIGluc3RhbmNlb2YgUm91dGVyOyAvLz0+IHRydWUKICAgICBwb3N0LnJvdXRlciBpbnN0YW5jZW9mIFJvdXRlcjsgLy89PiB0cnVlCiAgICAgICAgLy8gYm90aCBjb250cm9sbGVycyBzaGFyZSB0aGUgc2FtZSByb3V0ZXIKICAgICB1c2VyLnJvdXRlciA9PT0gcG9zdC5yb3V0ZXI7IC8vPT4gdHJ1ZQogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCB0eXBlSW5qZWN0aW9uCiAgICAgQHBhcmFtIHtTdHJpbmd9IHR5cGUKICAgICBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHkKICAgICBAcGFyYW0ge1N0cmluZ30gZnVsbE5hbWUKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMudHlwZUluamVjdGlvbiA9IGZ1bmN0aW9uIHR5cGVJbmplY3Rpb24odHlwZSwgcHJvcGVydHksIGZ1bGxOYW1lKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdmdWxsTmFtZSBtdXN0IGJlIGEgcHJvcGVyIGZ1bGwgbmFtZScsIHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGZ1bGxOYW1lKSkpOwogICAgICB2YXIgZnVsbE5hbWVUeXBlID0gZnVsbE5hbWUuc3BsaXQoJzonKVswXTsKICAgICAgKGZhbHNlICYmICEoZnVsbE5hbWVUeXBlICE9PSB0eXBlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkNhbm5vdCBpbmplY3QgYSAnIiArIGZ1bGxOYW1lICsgIicgb24gb3RoZXIgIiArIHR5cGUgKyAiKHMpLiIsIGZ1bGxOYW1lVHlwZSAhPT0gdHlwZSkpOwogICAgICB2YXIgaW5qZWN0aW9ucyA9IHRoaXMuX3R5cGVJbmplY3Rpb25zW3R5cGVdIHx8ICh0aGlzLl90eXBlSW5qZWN0aW9uc1t0eXBlXSA9IFtdKTsKICAgICAgaW5qZWN0aW9ucy5wdXNoKHsKICAgICAgICBwcm9wZXJ0eTogcHJvcGVydHksCiAgICAgICAgc3BlY2lmaWVyOiBmdWxsTmFtZQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgIERlZmluZXMgaW5qZWN0aW9uIHJ1bGVzLgogICAgICAgIFRoZXNlIHJ1bGVzIGFyZSB1c2VkIHRvIGluamVjdCBkZXBlbmRlbmNpZXMgb250byBvYmplY3RzIHdoZW4gdGhleQogICAgIGFyZSBpbnN0YW50aWF0ZWQuCiAgICAgICAgVHdvIGZvcm1zIG9mIGluamVjdGlvbnMgYXJlIHBvc3NpYmxlOgogICAgICAgICogSW5qZWN0aW5nIG9uZSBmdWxsTmFtZSBvbiBhbm90aGVyIGZ1bGxOYW1lCiAgICAgKiBJbmplY3Rpbmcgb25lIGZ1bGxOYW1lIG9uIGEgdHlwZQogICAgICAgIEV4YW1wbGU6CiAgICAgICAgYGBgamF2YXNjcmlwdAogICAgIGxldCByZWdpc3RyeSA9IG5ldyBSZWdpc3RyeSgpOwogICAgIGxldCBjb250YWluZXIgPSByZWdpc3RyeS5jb250YWluZXIoKTsKICAgICAgICByZWdpc3RyeS5yZWdpc3Rlcignc291cmNlOm1haW4nLCBTb3VyY2UpOwogICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdtb2RlbDp1c2VyJywgVXNlcik7CiAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJ21vZGVsOnBvc3QnLCBQb3N0KTsKICAgICAgICAvLyBpbmplY3Rpbmcgb25lIGZ1bGxOYW1lIG9uIGFub3RoZXIgZnVsbE5hbWUKICAgICAvLyBlZy4gZWFjaCB1c2VyIG1vZGVsIGdldHMgYSBwb3N0IG1vZGVsCiAgICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdtb2RlbDp1c2VyJywgJ3Bvc3QnLCAnbW9kZWw6cG9zdCcpOwogICAgICAgIC8vIGluamVjdGluZyBvbmUgZnVsbE5hbWUgb24gYW5vdGhlciB0eXBlCiAgICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdtb2RlbCcsICdzb3VyY2UnLCAnc291cmNlOm1haW4nKTsKICAgICAgICBsZXQgdXNlciA9IGNvbnRhaW5lci5sb29rdXAoJ21vZGVsOnVzZXInKTsKICAgICBsZXQgcG9zdCA9IGNvbnRhaW5lci5sb29rdXAoJ21vZGVsOnBvc3QnKTsKICAgICAgICB1c2VyLnNvdXJjZSBpbnN0YW5jZW9mIFNvdXJjZTsgLy89PiB0cnVlCiAgICAgcG9zdC5zb3VyY2UgaW5zdGFuY2VvZiBTb3VyY2U7IC8vPT4gdHJ1ZQogICAgICAgIHVzZXIucG9zdCBpbnN0YW5jZW9mIFBvc3Q7IC8vPT4gdHJ1ZQogICAgICAgIC8vIGFuZCBib3RoIG1vZGVscyBzaGFyZSB0aGUgc2FtZSBzb3VyY2UKICAgICB1c2VyLnNvdXJjZSA9PT0gcG9zdC5zb3VyY2U7IC8vPT4gdHJ1ZQogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBpbmplY3Rpb24KICAgICBAcGFyYW0ge1N0cmluZ30gZmFjdG9yeU5hbWUKICAgICBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHkKICAgICBAcGFyYW0ge1N0cmluZ30gaW5qZWN0aW9uTmFtZQogICAgICovCiAgICA7CgogICAgX3Byb3RvMy5pbmplY3Rpb24gPSBmdW5jdGlvbiBpbmplY3Rpb24oZnVsbE5hbWUsIHByb3BlcnR5LCBpbmplY3Rpb25OYW1lKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGluamVjdGlvbk5hbWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkludmFsaWQgaW5qZWN0aW9uTmFtZSwgZXhwZWN0ZWQ6ICd0eXBlOm5hbWUnIGdvdDogIiArIGluamVjdGlvbk5hbWUsIHRoaXMuaXNWYWxpZEZ1bGxOYW1lKGluamVjdGlvbk5hbWUpKSk7CiAgICAgIHZhciBub3JtYWxpemVkSW5qZWN0aW9uTmFtZSA9IHRoaXMubm9ybWFsaXplKGluamVjdGlvbk5hbWUpOwoKICAgICAgaWYgKGZ1bGxOYW1lLmluZGV4T2YoJzonKSA9PT0gLTEpIHsKICAgICAgICByZXR1cm4gdGhpcy50eXBlSW5qZWN0aW9uKGZ1bGxOYW1lLCBwcm9wZXJ0eSwgbm9ybWFsaXplZEluamVjdGlvbk5hbWUpOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISh0aGlzLmlzVmFsaWRGdWxsTmFtZShmdWxsTmFtZSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnZnVsbE5hbWUgbXVzdCBiZSBhIHByb3BlciBmdWxsIG5hbWUnLCB0aGlzLmlzVmFsaWRGdWxsTmFtZShmdWxsTmFtZSkpKTsKICAgICAgdmFyIG5vcm1hbGl6ZWROYW1lID0gdGhpcy5ub3JtYWxpemUoZnVsbE5hbWUpOwogICAgICB2YXIgaW5qZWN0aW9ucyA9IHRoaXMuX2luamVjdGlvbnNbbm9ybWFsaXplZE5hbWVdIHx8ICh0aGlzLl9pbmplY3Rpb25zW25vcm1hbGl6ZWROYW1lXSA9IFtdKTsKICAgICAgaW5qZWN0aW9ucy5wdXNoKHsKICAgICAgICBwcm9wZXJ0eTogcHJvcGVydHksCiAgICAgICAgc3BlY2lmaWVyOiBub3JtYWxpemVkSW5qZWN0aW9uTmFtZQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBrbm93bkZvclR5cGUKICAgICBAcGFyYW0ge1N0cmluZ30gdHlwZSB0aGUgdHlwZSB0byBpdGVyYXRlIG92ZXIKICAgICovCiAgICA7CgogICAgX3Byb3RvMy5rbm93bkZvclR5cGUgPSBmdW5jdGlvbiBrbm93bkZvclR5cGUodHlwZSkgewogICAgICB2YXIgbG9jYWxLbm93biA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CiAgICAgIHZhciByZWdpc3RlcmVkTmFtZXMgPSBPYmplY3Qua2V5cyh0aGlzLnJlZ2lzdHJhdGlvbnMpOwoKICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IHJlZ2lzdGVyZWROYW1lcy5sZW5ndGg7IGluZGV4KyspIHsKICAgICAgICB2YXIgZnVsbE5hbWUgPSByZWdpc3RlcmVkTmFtZXNbaW5kZXhdOwogICAgICAgIHZhciBpdGVtVHlwZSA9IGZ1bGxOYW1lLnNwbGl0KCc6JylbMF07CgogICAgICAgIGlmIChpdGVtVHlwZSA9PT0gdHlwZSkgewogICAgICAgICAgbG9jYWxLbm93bltmdWxsTmFtZV0gPSB0cnVlOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdmFyIGZhbGxiYWNrS25vd24sIHJlc29sdmVyS25vd247CgogICAgICBpZiAodGhpcy5mYWxsYmFjayAhPT0gbnVsbCkgewogICAgICAgIGZhbGxiYWNrS25vd24gPSB0aGlzLmZhbGxiYWNrLmtub3duRm9yVHlwZSh0eXBlKTsKICAgICAgfQoKICAgICAgaWYgKHRoaXMucmVzb2x2ZXIgIT09IG51bGwgJiYgdGhpcy5yZXNvbHZlci5rbm93bkZvclR5cGUpIHsKICAgICAgICByZXNvbHZlcktub3duID0gdGhpcy5yZXNvbHZlci5rbm93bkZvclR5cGUodHlwZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBmYWxsYmFja0tub3duLCBsb2NhbEtub3duLCByZXNvbHZlcktub3duKTsKICAgIH07CgogICAgX3Byb3RvMy5pc1ZhbGlkRnVsbE5hbWUgPSBmdW5jdGlvbiBpc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpIHsKICAgICAgcmV0dXJuIFZBTElEX0ZVTExfTkFNRV9SRUdFWFAudGVzdChmdWxsTmFtZSk7CiAgICB9OwoKICAgIF9wcm90bzMuZ2V0SW5qZWN0aW9ucyA9IGZ1bmN0aW9uIGdldEluamVjdGlvbnMoZnVsbE5hbWUpIHsKICAgICAgdmFyIGluamVjdGlvbnMgPSB0aGlzLl9pbmplY3Rpb25zW2Z1bGxOYW1lXTsKCiAgICAgIGlmICh0aGlzLmZhbGxiYWNrICE9PSBudWxsKSB7CiAgICAgICAgdmFyIGZhbGxiYWNrSW5qZWN0aW9ucyA9IHRoaXMuZmFsbGJhY2suZ2V0SW5qZWN0aW9ucyhmdWxsTmFtZSk7CgogICAgICAgIGlmIChmYWxsYmFja0luamVjdGlvbnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgaW5qZWN0aW9ucyA9IGluamVjdGlvbnMgPT09IHVuZGVmaW5lZCA/IGZhbGxiYWNrSW5qZWN0aW9ucyA6IGluamVjdGlvbnMuY29uY2F0KGZhbGxiYWNrSW5qZWN0aW9ucyk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gaW5qZWN0aW9uczsKICAgIH07CgogICAgX3Byb3RvMy5nZXRUeXBlSW5qZWN0aW9ucyA9IGZ1bmN0aW9uIGdldFR5cGVJbmplY3Rpb25zKHR5cGUpIHsKICAgICAgdmFyIGluamVjdGlvbnMgPSB0aGlzLl90eXBlSW5qZWN0aW9uc1t0eXBlXTsKCiAgICAgIGlmICh0aGlzLmZhbGxiYWNrICE9PSBudWxsKSB7CiAgICAgICAgdmFyIGZhbGxiYWNrSW5qZWN0aW9ucyA9IHRoaXMuZmFsbGJhY2suZ2V0VHlwZUluamVjdGlvbnModHlwZSk7CgogICAgICAgIGlmIChmYWxsYmFja0luamVjdGlvbnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgaW5qZWN0aW9ucyA9IGluamVjdGlvbnMgPT09IHVuZGVmaW5lZCA/IGZhbGxiYWNrSW5qZWN0aW9ucyA6IGluamVjdGlvbnMuY29uY2F0KGZhbGxiYWNrSW5qZWN0aW9ucyk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gaW5qZWN0aW9uczsKICAgIH0KICAgIC8qKgogICAgIEdpdmVuIGEgZnVsbE5hbWUgYW5kIGEgc291cmNlIGZ1bGxOYW1lIHJldHVybnMgdGhlIGZ1bGx5IHJlc29sdmVkCiAgICAgZnVsbE5hbWUuIFVzZWQgdG8gYWxsb3cgZm9yIGxvY2FsIGxvb2t1cC4KICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgICAgLy8gdGhlIHR3aXR0ZXIgZmFjdG9yeSBpcyBhZGRlZCB0byB0aGUgbW9kdWxlIHN5c3RlbQogICAgIHJlZ2lzdHJ5LmV4cGFuZExvY2FsTG9va3VwKCdjb21wb25lbnQ6cG9zdC10aXRsZScsIHsgc291cmNlOiAndGVtcGxhdGU6cG9zdCcgfSkgLy8gPT4gY29tcG9uZW50OnBvc3QvcG9zdC10aXRsZQogICAgIGBgYAogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBleHBhbmRMb2NhbExvb2t1cAogICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZQogICAgIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10KICAgICBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuc291cmNlXSB0aGUgZnVsbG5hbWUgb2YgdGhlIHJlcXVlc3Qgc291cmNlICh1c2VkIGZvciBsb2NhbCBsb29rdXBzKQogICAgIEByZXR1cm4ge1N0cmluZ30gZnVsbE5hbWUKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMuZXhwYW5kTG9jYWxMb29rdXAgPSBmdW5jdGlvbiBleHBhbmRMb2NhbExvb2t1cChmdWxsTmFtZSwgb3B0aW9ucykgewogICAgICBpZiAodGhpcy5yZXNvbHZlciAhPT0gbnVsbCAmJiB0aGlzLnJlc29sdmVyLmV4cGFuZExvY2FsTG9va3VwKSB7CiAgICAgICAgKGZhbHNlICYmICEodGhpcy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2Z1bGxOYW1lIG11c3QgYmUgYSBwcm9wZXIgZnVsbCBuYW1lJywgdGhpcy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSk7CiAgICAgICAgKGZhbHNlICYmICEoIW9wdGlvbnMuc291cmNlIHx8IHRoaXMuaXNWYWxpZEZ1bGxOYW1lKG9wdGlvbnMuc291cmNlKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdvcHRpb25zLnNvdXJjZSBtdXN0IGJlIGEgcHJvcGVyIGZ1bGwgbmFtZScsICFvcHRpb25zLnNvdXJjZSB8fCB0aGlzLmlzVmFsaWRGdWxsTmFtZShvcHRpb25zLnNvdXJjZSkpKTsKICAgICAgICB2YXIgbm9ybWFsaXplZEZ1bGxOYW1lID0gdGhpcy5ub3JtYWxpemUoZnVsbE5hbWUpOwogICAgICAgIHZhciBub3JtYWxpemVkU291cmNlID0gdGhpcy5ub3JtYWxpemUob3B0aW9ucy5zb3VyY2UpOwogICAgICAgIHJldHVybiBfZXhwYW5kTG9jYWxMb29rdXAodGhpcywgbm9ybWFsaXplZEZ1bGxOYW1lLCBub3JtYWxpemVkU291cmNlLCBvcHRpb25zLm5hbWVzcGFjZSk7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5mYWxsYmFjayAhPT0gbnVsbCkgewogICAgICAgIHJldHVybiB0aGlzLmZhbGxiYWNrLmV4cGFuZExvY2FsTG9va3VwKGZ1bGxOYW1lLCBvcHRpb25zKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gUmVnaXN0cnk7CiAgfSgpOwoKICBfZXhwb3J0cy5SZWdpc3RyeSA9IFJlZ2lzdHJ5OwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgdmFyIHByb3RvID0gUmVnaXN0cnkucHJvdG90eXBlOwoKICAgIHByb3RvLm5vcm1hbGl6ZUluamVjdGlvbnNIYXNoID0gZnVuY3Rpb24gKGhhc2gpIHsKICAgICAgdmFyIGluamVjdGlvbnMgPSBbXTsKCiAgICAgIGZvciAodmFyIGtleSBpbiBoYXNoKSB7CiAgICAgICAgaWYgKGhhc2guaGFzT3duUHJvcGVydHkoa2V5KSkgewogICAgICAgICAgdmFyIF9oYXNoJGtleSA9IGhhc2hba2V5XSwKICAgICAgICAgICAgICBzcGVjaWZpZXIgPSBfaGFzaCRrZXkuc3BlY2lmaWVyLAogICAgICAgICAgICAgIHNvdXJjZSA9IF9oYXNoJGtleS5zb3VyY2UsCiAgICAgICAgICAgICAgbmFtZXNwYWNlID0gX2hhc2gka2V5Lm5hbWVzcGFjZTsKICAgICAgICAgIChmYWxzZSAmJiAhKHRoaXMuaXNWYWxpZEZ1bGxOYW1lKHNwZWNpZmllcikpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiRXhwZWN0ZWQgYSBwcm9wZXIgZnVsbCBuYW1lLCBnaXZlbiAnIiArIHNwZWNpZmllciArICInIiwgdGhpcy5pc1ZhbGlkRnVsbE5hbWUoc3BlY2lmaWVyKSkpOwogICAgICAgICAgaW5qZWN0aW9ucy5wdXNoKHsKICAgICAgICAgICAgcHJvcGVydHk6IGtleSwKICAgICAgICAgICAgc3BlY2lmaWVyOiBzcGVjaWZpZXIsCiAgICAgICAgICAgIHNvdXJjZTogc291cmNlLAogICAgICAgICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gaW5qZWN0aW9uczsKICAgIH07CgogICAgcHJvdG8udmFsaWRhdGVJbmplY3Rpb25zID0gZnVuY3Rpb24gKGluamVjdGlvbnMpIHsKICAgICAgaWYgKCFpbmplY3Rpb25zKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluamVjdGlvbnMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgX2luamVjdGlvbnMkaTIgPSBpbmplY3Rpb25zW2ldLAogICAgICAgICAgICBzcGVjaWZpZXIgPSBfaW5qZWN0aW9ucyRpMi5zcGVjaWZpZXIsCiAgICAgICAgICAgIHNvdXJjZSA9IF9pbmplY3Rpb25zJGkyLnNvdXJjZSwKICAgICAgICAgICAgbmFtZXNwYWNlID0gX2luamVjdGlvbnMkaTIubmFtZXNwYWNlOwogICAgICAgIChmYWxzZSAmJiAhKHRoaXMuaGFzKHNwZWNpZmllciwgewogICAgICAgICAgc291cmNlOiBzb3VyY2UsCiAgICAgICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZQogICAgICAgIH0pKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF0dGVtcHRpbmcgdG8gaW5qZWN0IGFuIHVua25vd24gaW5qZWN0aW9uOiAnIiArIHNwZWNpZmllciArICInIiwgdGhpcy5oYXMoc3BlY2lmaWVyLCB7CiAgICAgICAgICBzb3VyY2U6IHNvdXJjZSwKICAgICAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlCiAgICAgICAgfSkpKTsKICAgICAgfQogICAgfTsKICB9CgogIGZ1bmN0aW9uIF9leHBhbmRMb2NhbExvb2t1cChyZWdpc3RyeSwgbm9ybWFsaXplZE5hbWUsIG5vcm1hbGl6ZWRTb3VyY2UsIG5hbWVzcGFjZSkgewogICAgdmFyIGNhY2hlID0gcmVnaXN0cnkuX2xvY2FsTG9va3VwQ2FjaGU7CiAgICB2YXIgbm9ybWFsaXplZE5hbWVDYWNoZSA9IGNhY2hlW25vcm1hbGl6ZWROYW1lXTsKCiAgICBpZiAoIW5vcm1hbGl6ZWROYW1lQ2FjaGUpIHsKICAgICAgbm9ybWFsaXplZE5hbWVDYWNoZSA9IGNhY2hlW25vcm1hbGl6ZWROYW1lXSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB9CgogICAgdmFyIGNhY2hlS2V5ID0gbmFtZXNwYWNlIHx8IG5vcm1hbGl6ZWRTb3VyY2U7CiAgICB2YXIgY2FjaGVkID0gbm9ybWFsaXplZE5hbWVDYWNoZVtjYWNoZUtleV07CgogICAgaWYgKGNhY2hlZCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBjYWNoZWQ7CiAgICB9CgogICAgdmFyIGV4cGFuZGVkID0gcmVnaXN0cnkucmVzb2x2ZXIuZXhwYW5kTG9jYWxMb29rdXAobm9ybWFsaXplZE5hbWUsIG5vcm1hbGl6ZWRTb3VyY2UsIG5hbWVzcGFjZSk7CiAgICByZXR1cm4gbm9ybWFsaXplZE5hbWVDYWNoZVtjYWNoZUtleV0gPSBleHBhbmRlZDsKICB9CgogIGZ1bmN0aW9uIF9yZXNvbHZlKHJlZ2lzdHJ5LCBfbm9ybWFsaXplZE5hbWUsIG9wdGlvbnMpIHsKICAgIHZhciBub3JtYWxpemVkTmFtZSA9IF9ub3JtYWxpemVkTmFtZTsgLy8gd2hlbiBgc291cmNlYCBpcyBwcm92aWRlZCBleHBhbmQgbm9ybWFsaXplZE5hbWUKICAgIC8vIGFuZCBzb3VyY2UgaW50byB0aGUgZnVsbCBub3JtYWxpemVkTmFtZQoKICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQgJiYgKG9wdGlvbnMuc291cmNlIHx8IG9wdGlvbnMubmFtZXNwYWNlKSkgewogICAgICBub3JtYWxpemVkTmFtZSA9IHJlZ2lzdHJ5LmV4cGFuZExvY2FsTG9va3VwKF9ub3JtYWxpemVkTmFtZSwgb3B0aW9ucyk7CgogICAgICBpZiAoIW5vcm1hbGl6ZWROYW1lKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICB9CgogICAgdmFyIGNhY2hlZCA9IHJlZ2lzdHJ5Ll9yZXNvbHZlQ2FjaGVbbm9ybWFsaXplZE5hbWVdOwoKICAgIGlmIChjYWNoZWQgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gY2FjaGVkOwogICAgfQoKICAgIGlmIChyZWdpc3RyeS5fZmFpbFNldC5oYXMobm9ybWFsaXplZE5hbWUpKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgcmVzb2x2ZWQ7CgogICAgaWYgKHJlZ2lzdHJ5LnJlc29sdmVyKSB7CiAgICAgIHJlc29sdmVkID0gcmVnaXN0cnkucmVzb2x2ZXIucmVzb2x2ZShub3JtYWxpemVkTmFtZSk7CiAgICB9CgogICAgaWYgKHJlc29sdmVkID09PSB1bmRlZmluZWQpIHsKICAgICAgcmVzb2x2ZWQgPSByZWdpc3RyeS5yZWdpc3RyYXRpb25zW25vcm1hbGl6ZWROYW1lXTsKICAgIH0KCiAgICBpZiAocmVzb2x2ZWQgPT09IHVuZGVmaW5lZCkgewogICAgICByZWdpc3RyeS5fZmFpbFNldC5hZGQobm9ybWFsaXplZE5hbWUpOwogICAgfSBlbHNlIHsKICAgICAgcmVnaXN0cnkuX3Jlc29sdmVDYWNoZVtub3JtYWxpemVkTmFtZV0gPSByZXNvbHZlZDsKICAgIH0KCiAgICByZXR1cm4gcmVzb2x2ZWQ7CiAgfQoKICBmdW5jdGlvbiBfaGFzKHJlZ2lzdHJ5LCBmdWxsTmFtZSwgc291cmNlLCBuYW1lc3BhY2UpIHsKICAgIHJldHVybiByZWdpc3RyeS5yZXNvbHZlKGZ1bGxOYW1lLCB7CiAgICAgIHNvdXJjZTogc291cmNlLAogICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZQogICAgfSkgIT09IHVuZGVmaW5lZDsKICB9CgogIHZhciBwcml2YXRlTmFtZXMgPSAoMCwgX3V0aWxzLmRpY3Rpb25hcnkpKG51bGwpOwogIHZhciBwcml2YXRlU3VmZml4ID0gKCIiICsgTWF0aC5yYW5kb20oKSArIERhdGUubm93KCkpLnJlcGxhY2UoJy4nLCAnJyk7CgogIGZ1bmN0aW9uIHByaXZhdGl6ZShfcmVmNikgewogICAgdmFyIGZ1bGxOYW1lID0gX3JlZjZbMF07CiAgICB2YXIgbmFtZSA9IHByaXZhdGVOYW1lc1tmdWxsTmFtZV07CgogICAgaWYgKG5hbWUpIHsKICAgICAgcmV0dXJuIG5hbWU7CiAgICB9CgogICAgdmFyIF9mdWxsTmFtZSRzcGxpdDIgPSBmdWxsTmFtZS5zcGxpdCgnOicpLAogICAgICAgIHR5cGUgPSBfZnVsbE5hbWUkc3BsaXQyWzBdLAogICAgICAgIHJhd05hbWUgPSBfZnVsbE5hbWUkc3BsaXQyWzFdOwoKICAgIHJldHVybiBwcml2YXRlTmFtZXNbZnVsbE5hbWVdID0gKDAsIF91dGlscy5pbnRlcm4pKHR5cGUgKyAiOiIgKyByYXdOYW1lICsgIi0iICsgcHJpdmF0ZVN1ZmZpeCk7CiAgfQogIC8qCiAgUHVibGljIEFQSSBmb3IgdGhlIGNvbnRhaW5lciBpcyBzdGlsbCBpbiBmbHV4LgogIFRoZSBwdWJsaWMgQVBJLCBzcGVjaWZpZWQgb24gdGhlIGFwcGxpY2F0aW9uIG5hbWVzcGFjZSBzaG91bGQgYmUgY29uc2lkZXJlZCB0aGUgc3RhYmxlIEFQSS4KICAvLyBAbW9kdWxlIGNvbnRhaW5lcgogICAgQHByaXZhdGUKICAqLwoKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvZW52aXJvbm1lbnQvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVwcmVjYXRlZEZlYXR1cmVzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5nZXRMb29rdXAgPSBnZXRMb29rdXA7CiAgX2V4cG9ydHMuc2V0TG9va3VwID0gc2V0TG9va3VwOwogIF9leHBvcnRzLmdldEVOViA9IGdldEVOVjsKICBfZXhwb3J0cy5FTlYgPSBfZXhwb3J0cy5jb250ZXh0ID0gX2V4cG9ydHMuZ2xvYmFsID0gdm9pZCAwOwoKICAvLyBmcm9tIGxvZGFzaCB0byBjYXRjaCBmYWtlIGdsb2JhbHMKICBmdW5jdGlvbiBjaGVja0dsb2JhbCh2YWx1ZSkgewogICAgcmV0dXJuIHZhbHVlICYmIHZhbHVlLk9iamVjdCA9PT0gT2JqZWN0ID8gdmFsdWUgOiB1bmRlZmluZWQ7CiAgfSAvLyBlbGVtZW50IGlkcyBjYW4gcnVpbiBnbG9iYWwgbWlzcyBjaGVja3MKCgogIGZ1bmN0aW9uIGNoZWNrRWxlbWVudElkU2hhZG93aW5nKHZhbHVlKSB7CiAgICByZXR1cm4gdmFsdWUgJiYgdmFsdWUubm9kZVR5cGUgPT09IHVuZGVmaW5lZCA/IHZhbHVlIDogdW5kZWZpbmVkOwogIH0gLy8gZXhwb3J0IHJlYWwgZ2xvYmFsCgoKICB2YXIgZ2xvYmFsJDEgPSBjaGVja0dsb2JhbChjaGVja0VsZW1lbnRJZFNoYWRvd2luZyh0eXBlb2YgZ2xvYmFsID09PSAnb2JqZWN0JyAmJiBnbG9iYWwpKSB8fCBjaGVja0dsb2JhbCh0eXBlb2Ygc2VsZiA9PT0gJ29iamVjdCcgJiYgc2VsZikgfHwgY2hlY2tHbG9iYWwodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgJiYgd2luZG93KSB8fCB0eXBlb2YgbWFpbkNvbnRleHQgIT09ICd1bmRlZmluZWQnICYmIG1haW5Db250ZXh0IHx8IC8vIHNldCBiZWZvcmUgc3RyaWN0IG1vZGUgaW4gRW1iZXIgbG9hZGVyL3dyYXBwZXIKICBuZXcgRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTsgLy8gZXZhbCBvdXRzaWRlIG9mIHN0cmljdCBtb2RlCgogIF9leHBvcnRzLmdsb2JhbCA9IGdsb2JhbCQxOwoKICB2YXIgY29udGV4dCA9IGZ1bmN0aW9uIChnbG9iYWwsIEVtYmVyKSB7CiAgICByZXR1cm4gRW1iZXIgPT09IHVuZGVmaW5lZCA/IHsKICAgICAgaW1wb3J0czogZ2xvYmFsLAogICAgICBleHBvcnRzOiBnbG9iYWwsCiAgICAgIGxvb2t1cDogZ2xvYmFsCiAgICB9IDogewogICAgICAvLyBpbXBvcnQgalF1ZXJ5CiAgICAgIGltcG9ydHM6IEVtYmVyLmltcG9ydHMgfHwgZ2xvYmFsLAogICAgICAvLyBleHBvcnQgRW1iZXIKICAgICAgZXhwb3J0czogRW1iZXIuZXhwb3J0cyB8fCBnbG9iYWwsCiAgICAgIC8vIHNlYXJjaCBmb3IgTmFtZXNwYWNlcwogICAgICBsb29rdXA6IEVtYmVyLmxvb2t1cCB8fCBnbG9iYWwKICAgIH07CiAgfShnbG9iYWwkMSwgZ2xvYmFsJDEuRW1iZXIpOwoKICBfZXhwb3J0cy5jb250ZXh0ID0gY29udGV4dDsKCiAgZnVuY3Rpb24gZ2V0TG9va3VwKCkgewogICAgcmV0dXJuIGNvbnRleHQubG9va3VwOwogIH0KCiAgZnVuY3Rpb24gc2V0TG9va3VwKHZhbHVlKSB7CiAgICBjb250ZXh0Lmxvb2t1cCA9IHZhbHVlOwogIH0KICAvKioKICAgIFRoZSBoYXNoIG9mIGVudmlyb25tZW50IHZhcmlhYmxlcyB1c2VkIHRvIGNvbnRyb2wgdmFyaW91cyBjb25maWd1cmF0aW9uCiAgICBzZXR0aW5ncy4gVG8gc3BlY2lmeSB5b3VyIG93biBvciBvdmVycmlkZSBkZWZhdWx0IHNldHRpbmdzLCBhZGQgdGhlCiAgICBkZXNpcmVkIHByb3BlcnRpZXMgdG8gYSBnbG9iYWwgaGFzaCBuYW1lZCBgRW1iZXJFTlZgIChvciBgRU5WYCBmb3IKICAgIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggZWFybGllciB2ZXJzaW9ucyBvZiBFbWJlcikuIFRoZSBgRW1iZXJFTlZgCiAgICBoYXNoIG11c3QgYmUgY3JlYXRlZCBiZWZvcmUgbG9hZGluZyBFbWJlci4KICAKICAgIEBjbGFzcyBFbWJlckVOVgogICAgQHR5cGUgT2JqZWN0CiAgICBAcHVibGljCiAgKi8KCgogIHZhciBFTlYgPSB7CiAgICBFTkFCTEVfT1BUSU9OQUxfRkVBVFVSRVM6IGZhbHNlLAoKICAgIC8qKgogICAgICBEZXRlcm1pbmVzIHdoZXRoZXIgRW1iZXIgc2hvdWxkIGFkZCB0byBgQXJyYXlgLCBgRnVuY3Rpb25gLCBhbmQgYFN0cmluZ2AKICAgICAgbmF0aXZlIG9iamVjdCBwcm90b3R5cGVzLCBhIGZldyBleHRyYSBtZXRob2RzIGluIG9yZGVyIHRvIHByb3ZpZGUgYSBtb3JlCiAgICAgIGZyaWVuZGx5IEFQSS4KICAgICAgICAgV2UgZ2VuZXJhbGx5IHJlY29tbWVuZCBsZWF2aW5nIHRoaXMgb3B0aW9uIHNldCB0byB0cnVlIGhvd2V2ZXIsIGlmIHlvdSBuZWVkCiAgICAgIHRvIHR1cm4gaXQgb2ZmLCB5b3UgY2FuIGFkZCB0aGUgY29uZmlndXJhdGlvbiBwcm9wZXJ0eQogICAgICBgRVhURU5EX1BST1RPVFlQRVNgIHRvIGBFbWJlckVOVmAgYW5kIHNldCBpdCB0byBgZmFsc2VgLgogICAgICAgICBOb3RlLCB3aGVuIGRpc2FibGVkICh0aGUgZGVmYXVsdCBjb25maWd1cmF0aW9uIGZvciBFbWJlciBBZGRvbnMpLCB5b3Ugd2lsbAogICAgICBpbnN0ZWFkIGhhdmUgdG8gYWNjZXNzIGFsbCBtZXRob2RzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgRW1iZXIKICAgICAgbmFtZXNwYWNlLgogICAgICAgICBAcHJvcGVydHkgRVhURU5EX1BST1RPVFlQRVMKICAgICAgQHR5cGUgQm9vbGVhbgogICAgICBAZGVmYXVsdCB0cnVlCiAgICAgIEBmb3IgRW1iZXJFTlYKICAgICAgQHB1YmxpYwogICAgKi8KICAgIEVYVEVORF9QUk9UT1RZUEVTOiB7CiAgICAgIEFycmF5OiB0cnVlLAogICAgICBGdW5jdGlvbjogdHJ1ZSwKICAgICAgU3RyaW5nOiB0cnVlCiAgICB9LAoKICAgIC8qKgogICAgICBUaGUgYExPR19TVEFDS1RSQUNFX09OX0RFUFJFQ0FUSU9OYCBwcm9wZXJ0eSwgd2hlbiB0cnVlLCB0ZWxscyBFbWJlciB0byBsb2cKICAgICAgYSBmdWxsIHN0YWNrIHRyYWNlIGR1cmluZyBkZXByZWNhdGlvbiB3YXJuaW5ncy4KICAgICAgICAgQHByb3BlcnR5IExPR19TVEFDS1RSQUNFX09OX0RFUFJFQ0FUSU9OCiAgICAgIEB0eXBlIEJvb2xlYW4KICAgICAgQGRlZmF1bHQgdHJ1ZQogICAgICBAZm9yIEVtYmVyRU5WCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBMT0dfU1RBQ0tUUkFDRV9PTl9ERVBSRUNBVElPTjogdHJ1ZSwKCiAgICAvKioKICAgICAgVGhlIGBMT0dfVkVSU0lPTmAgcHJvcGVydHksIHdoZW4gdHJ1ZSwgdGVsbHMgRW1iZXIgdG8gbG9nIHZlcnNpb25zIG9mIGFsbAogICAgICBkZXBlbmRlbnQgbGlicmFyaWVzIGluIHVzZS4KICAgICAgICAgQHByb3BlcnR5IExPR19WRVJTSU9OCiAgICAgIEB0eXBlIEJvb2xlYW4KICAgICAgQGRlZmF1bHQgdHJ1ZQogICAgICBAZm9yIEVtYmVyRU5WCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBMT0dfVkVSU0lPTjogdHJ1ZSwKICAgIFJBSVNFX09OX0RFUFJFQ0FUSU9OOiBmYWxzZSwKICAgIFNUUlVDVFVSRURfUFJPRklMRTogZmFsc2UsCgogICAgLyoqCiAgICAgIFdoZXRoZXIgdG8gaW5zZXJ0IGEgYDxkaXYgY2xhc3M9ImVtYmVyLXZpZXciIC8+YCB3cmFwcGVyIGFyb3VuZCB0aGUKICAgICAgYXBwbGljYXRpb24gdGVtcGxhdGUuIFNlZSBSRkMgIzI4MC4KICAgICAgICAgVGhpcyBpcyBub3QgaW50ZW5kZWQgdG8gYmUgc2V0IGRpcmVjdGx5LCBhcyB0aGUgaW1wbGVtZW50YXRpb24gbWF5IGNoYW5nZSBpbgogICAgICB0aGUgZnV0dXJlLiBVc2UgYEBlbWJlci9vcHRpb25hbC1mZWF0dXJlc2AgaW5zdGVhZC4KICAgICAgICAgQHByb3BlcnR5IF9BUFBMSUNBVElPTl9URU1QTEFURV9XUkFQUEVSCiAgICAgIEBmb3IgRW1iZXJFTlYKICAgICAgQHR5cGUgQm9vbGVhbgogICAgICBAZGVmYXVsdCB0cnVlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX0FQUExJQ0FUSU9OX1RFTVBMQVRFX1dSQVBQRVI6IHRydWUsCgogICAgLyoqCiAgICAgIFdoZXRoZXIgdG8gdXNlIEdsaW1tZXIgQ29tcG9uZW50IHNlbWFudGljcyAoYXMgb3Bwb3NlZCB0byB0aGUgY2xhc3NpYyAiQ3VybHkiCiAgICAgIGNvbXBvbmVudHMgc2VtYW50aWNzKSBmb3IgdGVtcGxhdGUtb25seSBjb21wb25lbnRzLiBTZWUgUkZDICMyNzguCiAgICAgICAgIFRoaXMgaXMgbm90IGludGVuZGVkIHRvIGJlIHNldCBkaXJlY3RseSwgYXMgdGhlIGltcGxlbWVudGF0aW9uIG1heSBjaGFuZ2UgaW4KICAgICAgdGhlIGZ1dHVyZS4gVXNlIGBAZW1iZXIvb3B0aW9uYWwtZmVhdHVyZXNgIGluc3RlYWQuCiAgICAgICAgIEBwcm9wZXJ0eSBfVEVNUExBVEVfT05MWV9HTElNTUVSX0NPTVBPTkVOVFMKICAgICAgQGZvciBFbWJlckVOVgogICAgICBAdHlwZSBCb29sZWFuCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX1RFTVBMQVRFX09OTFlfR0xJTU1FUl9DT01QT05FTlRTOiBmYWxzZSwKCiAgICAvKioKICAgICAgV2hldGhlciB0aGUgYXBwIGlzIHVzaW5nIGpRdWVyeS4gU2VlIFJGQyAjMjk0LgogICAgICAgICBUaGlzIGlzIG5vdCBpbnRlbmRlZCB0byBiZSBzZXQgZGlyZWN0bHksIGFzIHRoZSBpbXBsZW1lbnRhdGlvbiBtYXkgY2hhbmdlIGluCiAgICAgIHRoZSBmdXR1cmUuIFVzZSBgQGVtYmVyL29wdGlvbmFsLWZlYXR1cmVzYCBpbnN0ZWFkLgogICAgICAgICBAcHJvcGVydHkgX0pRVUVSWV9JTlRFR1JBVElPTgogICAgICBAZm9yIEVtYmVyRU5WCiAgICAgIEB0eXBlIEJvb2xlYW4KICAgICAgQGRlZmF1bHQgdHJ1ZQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9KUVVFUllfSU5URUdSQVRJT046IHRydWUsCgogICAgLyoqCiAgICAgIFdoZXRoZXIgdGhlIGFwcCBkZWZhdWx0cyB0byB1c2luZyBhc3luYyBvYnNlcnZlcnMuCiAgICAgICAgIFRoaXMgaXMgbm90IGludGVuZGVkIHRvIGJlIHNldCBkaXJlY3RseSwgYXMgdGhlIGltcGxlbWVudGF0aW9uIG1heSBjaGFuZ2UgaW4KICAgICAgdGhlIGZ1dHVyZS4gVXNlIGBAZW1iZXIvb3B0aW9uYWwtZmVhdHVyZXNgIGluc3RlYWQuCiAgICAgICAgIEBwcm9wZXJ0eSBfREVGQVVMVF9BU1lOQ19PQlNFUlZFUlMKICAgICAgQGZvciBFbWJlckVOVgogICAgICBAdHlwZSBCb29sZWFuCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX0RFRkFVTFRfQVNZTkNfT0JTRVJWRVJTOiBmYWxzZSwKCiAgICAvKioKICAgICAgQ29udHJvbHMgdGhlIG1heGltdW0gbnVtYmVyIG9mIHNjaGVkdWxlZCByZXJlbmRlcnMgd2l0aG91dCAic2V0dGxpbmciLiBJbiBnZW5lcmFsLAogICAgICBhcHBsaWNhdGlvbnMgc2hvdWxkIG5vdCBuZWVkIHRvIG1vZGlmeSB0aGlzIGVudmlyb25tZW50IHZhcmlhYmxlLCBidXQgcGxlYXNlCiAgICAgIG9wZW4gYW4gaXNzdWUgc28gdGhhdCB3ZSBjYW4gZGV0ZXJtaW5lIGlmIGEgYmV0dGVyIGRlZmF1bHQgdmFsdWUgaXMgbmVlZGVkLgogICAgICAgICBAcHJvcGVydHkgX1JFUkVOREVSX0xPT1BfTElNSVQKICAgICAgQGZvciBFbWJlckVOVgogICAgICBAdHlwZSBudW1iZXIKICAgICAgQGRlZmF1bHQgMTAwMAogICAgICBAcHJpdmF0ZQogICAgICovCiAgICBfUkVSRU5ERVJfTE9PUF9MSU1JVDogMTAwMCwKICAgIEVNQkVSX0xPQURfSE9PS1M6IHt9LAogICAgRkVBVFVSRVM6IHt9CiAgfTsKICBfZXhwb3J0cy5FTlYgPSBFTlY7CgogIChmdW5jdGlvbiAoRW1iZXJFTlYpIHsKICAgIGlmICh0eXBlb2YgRW1iZXJFTlYgIT09ICdvYmplY3QnIHx8IEVtYmVyRU5WID09PSBudWxsKSByZXR1cm47CgogICAgZm9yICh2YXIgZmxhZyBpbiBFbWJlckVOVikgewogICAgICBpZiAoIUVtYmVyRU5WLmhhc093blByb3BlcnR5KGZsYWcpIHx8IGZsYWcgPT09ICdFWFRFTkRfUFJPVE9UWVBFUycgfHwgZmxhZyA9PT0gJ0VNQkVSX0xPQURfSE9PS1MnKSBjb250aW51ZTsKICAgICAgdmFyIGRlZmF1bHRWYWx1ZSA9IEVOVltmbGFnXTsKCiAgICAgIGlmIChkZWZhdWx0VmFsdWUgPT09IHRydWUpIHsKICAgICAgICBFTlZbZmxhZ10gPSBFbWJlckVOVltmbGFnXSAhPT0gZmFsc2U7CiAgICAgIH0gZWxzZSBpZiAoZGVmYXVsdFZhbHVlID09PSBmYWxzZSkgewogICAgICAgIEVOVltmbGFnXSA9IEVtYmVyRU5WW2ZsYWddID09PSB0cnVlOwogICAgICB9CiAgICB9CgogICAgdmFyIEVYVEVORF9QUk9UT1RZUEVTID0gRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVM7CgogICAgaWYgKEVYVEVORF9QUk9UT1RZUEVTICE9PSB1bmRlZmluZWQpIHsKICAgICAgaWYgKHR5cGVvZiBFWFRFTkRfUFJPVE9UWVBFUyA9PT0gJ29iamVjdCcgJiYgRVhURU5EX1BST1RPVFlQRVMgIT09IG51bGwpIHsKICAgICAgICBFTlYuRVhURU5EX1BST1RPVFlQRVMuU3RyaW5nID0gRVhURU5EX1BST1RPVFlQRVMuU3RyaW5nICE9PSBmYWxzZTsKCiAgICAgICAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuRlVOQ1RJT05fUFJPVE9UWVBFX0VYVEVOU0lPTlMpIHsKICAgICAgICAgIEVOVi5FWFRFTkRfUFJPVE9UWVBFUy5GdW5jdGlvbiA9IEVYVEVORF9QUk9UT1RZUEVTLkZ1bmN0aW9uICE9PSBmYWxzZTsKICAgICAgICB9CgogICAgICAgIEVOVi5FWFRFTkRfUFJPVE9UWVBFUy5BcnJheSA9IEVYVEVORF9QUk9UT1RZUEVTLkFycmF5ICE9PSBmYWxzZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgaXNFbmFibGVkID0gRVhURU5EX1BST1RPVFlQRVMgIT09IGZhbHNlOwogICAgICAgIEVOVi5FWFRFTkRfUFJPVE9UWVBFUy5TdHJpbmcgPSBpc0VuYWJsZWQ7CgogICAgICAgIGlmIChfZGVwcmVjYXRlZEZlYXR1cmVzLkZVTkNUSU9OX1BST1RPVFlQRV9FWFRFTlNJT05TKSB7CiAgICAgICAgICBFTlYuRVhURU5EX1BST1RPVFlQRVMuRnVuY3Rpb24gPSBpc0VuYWJsZWQ7CiAgICAgICAgfQoKICAgICAgICBFTlYuRVhURU5EX1BST1RPVFlQRVMuQXJyYXkgPSBpc0VuYWJsZWQ7CiAgICAgIH0KICAgIH0gLy8gVE9ETyB0aGlzIGRvZXMgbm90IHNlZW0gdG8gYmUgdXNlZCBieSBhbnl0aGluZywKICAgIC8vICAgICAgY2FuIHdlIHJlbW92ZSBpdD8gZG8gd2UgbmVlZCB0byBkZXByZWNhdGUgaXQ/CgoKICAgIHZhciBFTUJFUl9MT0FEX0hPT0tTID0gRW1iZXJFTlYuRU1CRVJfTE9BRF9IT09LUzsKCiAgICBpZiAodHlwZW9mIEVNQkVSX0xPQURfSE9PS1MgPT09ICdvYmplY3QnICYmIEVNQkVSX0xPQURfSE9PS1MgIT09IG51bGwpIHsKICAgICAgZm9yICh2YXIgaG9va05hbWUgaW4gRU1CRVJfTE9BRF9IT09LUykgewogICAgICAgIGlmICghRU1CRVJfTE9BRF9IT09LUy5oYXNPd25Qcm9wZXJ0eShob29rTmFtZSkpIGNvbnRpbnVlOwogICAgICAgIHZhciBob29rcyA9IEVNQkVSX0xPQURfSE9PS1NbaG9va05hbWVdOwoKICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShob29rcykpIHsKICAgICAgICAgIEVOVi5FTUJFUl9MT0FEX0hPT0tTW2hvb2tOYW1lXSA9IGhvb2tzLmZpbHRlcihmdW5jdGlvbiAoaG9vaykgewogICAgICAgICAgICByZXR1cm4gdHlwZW9mIGhvb2sgPT09ICdmdW5jdGlvbic7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KCiAgICB2YXIgRkVBVFVSRVMgPSBFbWJlckVOVi5GRUFUVVJFUzsKCiAgICBpZiAodHlwZW9mIEZFQVRVUkVTID09PSAnb2JqZWN0JyAmJiBGRUFUVVJFUyAhPT0gbnVsbCkgewogICAgICBmb3IgKHZhciBmZWF0dXJlIGluIEZFQVRVUkVTKSB7CiAgICAgICAgaWYgKCFGRUFUVVJFUy5oYXNPd25Qcm9wZXJ0eShmZWF0dXJlKSkgY29udGludWU7CiAgICAgICAgRU5WLkZFQVRVUkVTW2ZlYXR1cmVdID0gRkVBVFVSRVNbZmVhdHVyZV0gPT09IHRydWU7CiAgICAgIH0KICAgIH0KICB9KShnbG9iYWwkMS5FbWJlckVOViB8fCBnbG9iYWwkMS5FTlYpOwoKICBmdW5jdGlvbiBnZXRFTlYoKSB7CiAgICByZXR1cm4gRU5WOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvZXJyb3ItaGFuZGxpbmcvaW5kZXgiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5nZXRPbmVycm9yID0gZ2V0T25lcnJvcjsKICBfZXhwb3J0cy5zZXRPbmVycm9yID0gc2V0T25lcnJvcjsKICBfZXhwb3J0cy5nZXREaXNwYXRjaE92ZXJyaWRlID0gZ2V0RGlzcGF0Y2hPdmVycmlkZTsKICBfZXhwb3J0cy5zZXREaXNwYXRjaE92ZXJyaWRlID0gc2V0RGlzcGF0Y2hPdmVycmlkZTsKICBfZXhwb3J0cy5vbkVycm9yVGFyZ2V0ID0gdm9pZCAwOwogIHZhciBvbmVycm9yOwogIHZhciBvbkVycm9yVGFyZ2V0ID0gewogICAgZ2V0IG9uZXJyb3IoKSB7CiAgICAgIHJldHVybiBvbmVycm9yOwogICAgfQoKICB9OyAvLyBFbWJlci5vbmVycm9yIGdldHRlcgoKICBfZXhwb3J0cy5vbkVycm9yVGFyZ2V0ID0gb25FcnJvclRhcmdldDsKCiAgZnVuY3Rpb24gZ2V0T25lcnJvcigpIHsKICAgIHJldHVybiBvbmVycm9yOwogIH0gLy8gRW1iZXIub25lcnJvciBzZXR0ZXIKCgogIGZ1bmN0aW9uIHNldE9uZXJyb3IoaGFuZGxlcikgewogICAgb25lcnJvciA9IGhhbmRsZXI7CiAgfQoKICB2YXIgZGlzcGF0Y2hPdmVycmlkZTsgLy8gYWxsb3dzIHRlc3RpbmcgYWRhcHRlciB0byBvdmVycmlkZSBkaXNwYXRjaAoKICBmdW5jdGlvbiBnZXREaXNwYXRjaE92ZXJyaWRlKCkgewogICAgcmV0dXJuIGRpc3BhdGNoT3ZlcnJpZGU7CiAgfQoKICBmdW5jdGlvbiBzZXREaXNwYXRjaE92ZXJyaWRlKGhhbmRsZXIpIHsKICAgIGRpc3BhdGNoT3ZlcnJpZGUgPSBoYW5kbGVyOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvZXh0ZW5zaW9uLXN1cHBvcnQvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZXh0ZW5zaW9uLXN1cHBvcnQvbGliL2RhdGFfYWRhcHRlciIsICJAZW1iZXIvLWludGVybmFscy9leHRlbnNpb24tc3VwcG9ydC9saWIvY29udGFpbmVyX2RlYnVnX2FkYXB0ZXIiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGF0YV9hZGFwdGVyLCBfY29udGFpbmVyX2RlYnVnX2FkYXB0ZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkRhdGFBZGFwdGVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2RhdGFfYWRhcHRlci5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkNvbnRhaW5lckRlYnVnQWRhcHRlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb250YWluZXJfZGVidWdfYWRhcHRlci5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9leHRlbnNpb24tc3VwcG9ydC9saWIvY29udGFpbmVyX2RlYnVnX2FkYXB0ZXIiLCBbImV4cG9ydHMiLCAiQGVtYmVyL3N0cmluZyIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3N0cmluZywgX3J1bnRpbWUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgQGVtYmVyL2RlYnVnCiAgKi8KCiAgLyoqCiAgICBUaGUgYENvbnRhaW5lckRlYnVnQWRhcHRlcmAgaGVscHMgdGhlIGNvbnRhaW5lciBhbmQgcmVzb2x2ZXIgaW50ZXJmYWNlCiAgICB3aXRoIHRvb2xzIHRoYXQgZGVidWcgRW1iZXIgc3VjaCBhcyB0aGUKICAgIFtFbWJlciBJbnNwZWN0b3JdKGh0dHBzOi8vZ2l0aHViLmNvbS9lbWJlcmpzL2VtYmVyLWluc3BlY3RvcikKICAgIGZvciBDaHJvbWUgYW5kIEZpcmVmb3guCiAgCiAgICBUaGlzIGNsYXNzIGNhbiBiZSBleHRlbmRlZCBieSBhIGN1c3RvbSByZXNvbHZlciBpbXBsZW1lbnRlcgogICAgdG8gb3ZlcnJpZGUgc29tZSBvZiB0aGUgbWV0aG9kcyB3aXRoIGxpYnJhcnktc3BlY2lmaWMgY29kZS4KICAKICAgIFRoZSBtZXRob2RzIGxpa2VseSB0byBiZSBvdmVycmlkZGVuIGFyZToKICAKICAgICogYGNhbkNhdGFsb2dFbnRyaWVzQnlUeXBlYAogICAgKiBgY2F0YWxvZ0VudHJpZXNCeVR5cGVgCiAgCiAgICBUaGUgYWRhcHRlciB3aWxsIG5lZWQgdG8gYmUgcmVnaXN0ZXJlZAogICAgaW4gdGhlIGFwcGxpY2F0aW9uJ3MgY29udGFpbmVyIGFzIGBjb250YWluZXItZGVidWctYWRhcHRlcjptYWluYC4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBBcHBsaWNhdGlvbi5pbml0aWFsaXplcih7CiAgICAgIG5hbWU6ICJjb250YWluZXJEZWJ1Z0FkYXB0ZXIiLAogIAogICAgICBpbml0aWFsaXplKGFwcGxpY2F0aW9uKSB7CiAgICAgICAgYXBwbGljYXRpb24ucmVnaXN0ZXIoJ2NvbnRhaW5lci1kZWJ1Zy1hZGFwdGVyOm1haW4nLCByZXF1aXJlKCdhcHAvY29udGFpbmVyLWRlYnVnLWFkYXB0ZXInKSk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBAY2xhc3MgQ29udGFpbmVyRGVidWdBZGFwdGVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHNpbmNlIDEuNS4wCiAgICBAcHVibGljCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfcnVudGltZS5PYmplY3QuZXh0ZW5kKHsKICAgIC8qKgogICAgICBUaGUgcmVzb2x2ZXIgaW5zdGFuY2Ugb2YgdGhlIGFwcGxpY2F0aW9uCiAgICAgIGJlaW5nIGRlYnVnZ2VkLiBUaGlzIHByb3BlcnR5IHdpbGwgYmUgaW5qZWN0ZWQKICAgICAgb24gY3JlYXRpb24uCiAgICAgICBAcHJvcGVydHkgcmVzb2x2ZXIKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwogICAgcmVzb2x2ZXI6IG51bGwsCgogICAgLyoqCiAgICAgIFJldHVybnMgdHJ1ZSBpZiBpdCBpcyBwb3NzaWJsZSB0byBjYXRhbG9nIGEgbGlzdCBvZiBhdmFpbGFibGUKICAgICAgY2xhc3NlcyBpbiB0aGUgcmVzb2x2ZXIgZm9yIGEgZ2l2ZW4gdHlwZS4KICAgICAgIEBtZXRob2QgY2FuQ2F0YWxvZ0VudHJpZXNCeVR5cGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IHR5cGUgVGhlIHR5cGUuIGUuZy4gIm1vZGVsIiwgImNvbnRyb2xsZXIiLCAicm91dGUiLgogICAgICBAcmV0dXJuIHtib29sZWFufSB3aGV0aGVyIGEgbGlzdCBpcyBhdmFpbGFibGUgZm9yIHRoaXMgdHlwZS4KICAgICAgQHB1YmxpYwogICAgKi8KICAgIGNhbkNhdGFsb2dFbnRyaWVzQnlUeXBlOiBmdW5jdGlvbiBjYW5DYXRhbG9nRW50cmllc0J5VHlwZSh0eXBlKSB7CiAgICAgIGlmICh0eXBlID09PSAnbW9kZWwnIHx8IHR5cGUgPT09ICd0ZW1wbGF0ZScpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIHJldHVybiB0cnVlOwogICAgfSwKCiAgICAvKioKICAgICAgUmV0dXJucyB0aGUgYXZhaWxhYmxlIGNsYXNzZXMgYSBnaXZlbiB0eXBlLgogICAgICAgQG1ldGhvZCBjYXRhbG9nRW50cmllc0J5VHlwZQogICAgICBAcGFyYW0ge1N0cmluZ30gdHlwZSBUaGUgdHlwZS4gZS5nLiAibW9kZWwiLCAiY29udHJvbGxlciIsICJyb3V0ZSIuCiAgICAgIEByZXR1cm4ge0FycmF5fSBBbiBhcnJheSBvZiBzdHJpbmdzLgogICAgICBAcHVibGljCiAgICAqLwogICAgY2F0YWxvZ0VudHJpZXNCeVR5cGU6IGZ1bmN0aW9uIGNhdGFsb2dFbnRyaWVzQnlUeXBlKHR5cGUpIHsKICAgICAgdmFyIG5hbWVzcGFjZXMgPSAoMCwgX3J1bnRpbWUuQSkoX3J1bnRpbWUuTmFtZXNwYWNlLk5BTUVTUEFDRVMpOwogICAgICB2YXIgdHlwZXMgPSAoMCwgX3J1bnRpbWUuQSkoKTsKICAgICAgdmFyIHR5cGVTdWZmaXhSZWdleCA9IG5ldyBSZWdFeHAoKDAsIF9zdHJpbmcuY2xhc3NpZnkpKHR5cGUpICsgIiQiKTsKICAgICAgbmFtZXNwYWNlcy5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lc3BhY2UpIHsKICAgICAgICBmb3IgKHZhciBrZXkgaW4gbmFtZXNwYWNlKSB7CiAgICAgICAgICBpZiAoIW5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQoKICAgICAgICAgIGlmICh0eXBlU3VmZml4UmVnZXgudGVzdChrZXkpKSB7CiAgICAgICAgICAgIHZhciBrbGFzcyA9IG5hbWVzcGFjZVtrZXldOwoKICAgICAgICAgICAgaWYgKCgwLCBfcnVudGltZS50eXBlT2YpKGtsYXNzKSA9PT0gJ2NsYXNzJykgewogICAgICAgICAgICAgIHR5cGVzLnB1c2goKDAsIF9zdHJpbmcuZGFzaGVyaXplKShrZXkucmVwbGFjZSh0eXBlU3VmZml4UmVnZXgsICcnKSkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIHR5cGVzOwogICAgfQogIH0pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL2V4dGVuc2lvbi1zdXBwb3J0L2xpYi9kYXRhX2FkYXB0ZXIiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvb3duZXIiLCAiQGVtYmVyL3J1bmxvb3AiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL3N0cmluZyIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX293bmVyLCBfcnVubG9vcCwgX21ldGFsLCBfc3RyaW5nLCBfcnVudGltZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvZGVidWcKICAqLwoKICAvKioKICAgIFRoZSBgRGF0YUFkYXB0ZXJgIGhlbHBzIGEgZGF0YSBwZXJzaXN0ZW5jZSBsaWJyYXJ5CiAgICBpbnRlcmZhY2Ugd2l0aCB0b29scyB0aGF0IGRlYnVnIEVtYmVyIHN1Y2gKICAgIGFzIHRoZSBbRW1iZXIgSW5zcGVjdG9yXShodHRwczovL2dpdGh1Yi5jb20vZW1iZXJqcy9lbWJlci1pbnNwZWN0b3IpCiAgICBmb3IgQ2hyb21lIGFuZCBGaXJlZm94LgogIAogICAgVGhpcyBjbGFzcyB3aWxsIGJlIGV4dGVuZGVkIGJ5IGEgcGVyc2lzdGVuY2UgbGlicmFyeQogICAgd2hpY2ggd2lsbCBvdmVycmlkZSBzb21lIG9mIHRoZSBtZXRob2RzIHdpdGgKICAgIGxpYnJhcnktc3BlY2lmaWMgY29kZS4KICAKICAgIFRoZSBtZXRob2RzIGxpa2VseSB0byBiZSBvdmVycmlkZGVuIGFyZToKICAKICAgICogYGdldEZpbHRlcnNgCiAgICAqIGBkZXRlY3RgCiAgICAqIGBjb2x1bW5zRm9yVHlwZWAKICAgICogYGdldFJlY29yZHNgCiAgICAqIGBnZXRSZWNvcmRDb2x1bW5WYWx1ZXNgCiAgICAqIGBnZXRSZWNvcmRLZXl3b3Jkc2AKICAgICogYGdldFJlY29yZEZpbHRlclZhbHVlc2AKICAgICogYGdldFJlY29yZENvbG9yYAogICAgKiBgb2JzZXJ2ZVJlY29yZGAKICAKICAgIFRoZSBhZGFwdGVyIHdpbGwgbmVlZCB0byBiZSByZWdpc3RlcmVkCiAgICBpbiB0aGUgYXBwbGljYXRpb24ncyBjb250YWluZXIgYXMgYGRhdGFBZGFwdGVyOm1haW5gLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIEFwcGxpY2F0aW9uLmluaXRpYWxpemVyKHsKICAgICAgbmFtZTogImRhdGEtYWRhcHRlciIsCiAgCiAgICAgIGluaXRpYWxpemU6IGZ1bmN0aW9uKGFwcGxpY2F0aW9uKSB7CiAgICAgICAgYXBwbGljYXRpb24ucmVnaXN0ZXIoJ2RhdGEtYWRhcHRlcjptYWluJywgRFMuRGF0YUFkYXB0ZXIpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQGNsYXNzIERhdGFBZGFwdGVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHB1YmxpYwogICovCiAgdmFyIF9kZWZhdWx0ID0gX3J1bnRpbWUuT2JqZWN0LmV4dGVuZCh7CiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgdGhpcy5yZWxlYXNlTWV0aG9kcyA9ICgwLCBfcnVudGltZS5BKSgpOwogICAgfSwKCiAgICAvKioKICAgICAgVGhlIGNvbnRhaW5lci1kZWJ1Zy1hZGFwdGVyIHdoaWNoIGlzIHVzZWQKICAgICAgdG8gbGlzdCBhbGwgbW9kZWxzLgogICAgICAgQHByb3BlcnR5IGNvbnRhaW5lckRlYnVnQWRhcHRlcgogICAgICBAZGVmYXVsdCB1bmRlZmluZWQKICAgICAgQHNpbmNlIDEuNS4wCiAgICAgIEBwdWJsaWMKICAgICoqLwogICAgY29udGFpbmVyRGVidWdBZGFwdGVyOiB1bmRlZmluZWQsCgogICAgLyoqCiAgICAgIFRoZSBudW1iZXIgb2YgYXR0cmlidXRlcyB0byBzZW5kCiAgICAgIGFzIGNvbHVtbnMuIChFbm91Z2ggdG8gbWFrZSB0aGUgcmVjb3JkCiAgICAgIGlkZW50aWZpYWJsZSkuCiAgICAgICBAcHJpdmF0ZQogICAgICBAcHJvcGVydHkgYXR0cmlidXRlTGltaXQKICAgICAgQGRlZmF1bHQgMwogICAgICBAc2luY2UgMS4zLjAKICAgICovCiAgICBhdHRyaWJ1dGVMaW1pdDogMywKCiAgICAvKioKICAgICAgIEVtYmVyIERhdGEgPiB2MS4wLjAtYmV0YS4xOAogICAgICAgcmVxdWlyZXMgc3RyaW5nIG1vZGVsIG5hbWVzIHRvIGJlIHBhc3NlZAogICAgICAgYXJvdW5kIGluc3RlYWQgb2YgdGhlIGFjdHVhbCBmYWN0b3JpZXMuCiAgICAgICAgVGhpcyBpcyBhIHN0YW1wIGZvciB0aGUgRW1iZXIgSW5zcGVjdG9yCiAgICAgICB0byBkaWZmZXJlbnRpYXRlIGJldHdlZW4gdGhlIHZlcnNpb25zCiAgICAgICB0byBiZSBhYmxlIHRvIHN1cHBvcnQgb2xkZXIgdmVyc2lvbnMgdG9vLgogICAgICAgIEBwdWJsaWMKICAgICAgIEBwcm9wZXJ0eSBhY2NlcHRzTW9kZWxOYW1lCiAgICAgKi8KICAgIGFjY2VwdHNNb2RlbE5hbWU6IHRydWUsCgogICAgLyoqCiAgICAgIFN0b3JlcyBhbGwgbWV0aG9kcyB0aGF0IGNsZWFyIG9ic2VydmVycy4KICAgICAgVGhlc2UgbWV0aG9kcyB3aWxsIGJlIGNhbGxlZCBvbiBkZXN0cnVjdGlvbi4KICAgICAgIEBwcml2YXRlCiAgICAgIEBwcm9wZXJ0eSByZWxlYXNlTWV0aG9kcwogICAgICBAc2luY2UgMS4zLjAKICAgICovCiAgICByZWxlYXNlTWV0aG9kczogKDAsIF9ydW50aW1lLkEpKCksCgogICAgLyoqCiAgICAgIFNwZWNpZmllcyBob3cgcmVjb3JkcyBjYW4gYmUgZmlsdGVyZWQuCiAgICAgIFJlY29yZHMgcmV0dXJuZWQgd2lsbCBuZWVkIHRvIGhhdmUgYSBgZmlsdGVyVmFsdWVzYAogICAgICBwcm9wZXJ0eSB3aXRoIGEga2V5IGZvciBldmVyeSBuYW1lIGluIHRoZSByZXR1cm5lZCBhcnJheS4KICAgICAgIEBwdWJsaWMKICAgICAgQG1ldGhvZCBnZXRGaWx0ZXJzCiAgICAgIEByZXR1cm4ge0FycmF5fSBMaXN0IG9mIG9iamVjdHMgZGVmaW5pbmcgZmlsdGVycy4KICAgICAgIFRoZSBvYmplY3Qgc2hvdWxkIGhhdmUgYSBgbmFtZWAgYW5kIGBkZXNjYCBwcm9wZXJ0eS4KICAgICovCiAgICBnZXRGaWx0ZXJzOiBmdW5jdGlvbiBnZXRGaWx0ZXJzKCkgewogICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBGZXRjaCB0aGUgbW9kZWwgdHlwZXMgYW5kIG9ic2VydmUgdGhlbSBmb3IgY2hhbmdlcy4KICAgICAgIEBwdWJsaWMKICAgICAgQG1ldGhvZCB3YXRjaE1vZGVsVHlwZXMKICAgICAgIEBwYXJhbSB7RnVuY3Rpb259IHR5cGVzQWRkZWQgQ2FsbGJhY2sgdG8gY2FsbCB0byBhZGQgdHlwZXMuCiAgICAgIFRha2VzIGFuIGFycmF5IG9mIG9iamVjdHMgY29udGFpbmluZyB3cmFwcGVkIHR5cGVzIChyZXR1cm5lZCBmcm9tIGB3cmFwTW9kZWxUeXBlYCkuCiAgICAgICBAcGFyYW0ge0Z1bmN0aW9ufSB0eXBlc1VwZGF0ZWQgQ2FsbGJhY2sgdG8gY2FsbCB3aGVuIGEgdHlwZSBoYXMgY2hhbmdlZC4KICAgICAgVGFrZXMgYW4gYXJyYXkgb2Ygb2JqZWN0cyBjb250YWluaW5nIHdyYXBwZWQgdHlwZXMuCiAgICAgICBAcmV0dXJuIHtGdW5jdGlvbn0gTWV0aG9kIHRvIGNhbGwgdG8gcmVtb3ZlIGFsbCBvYnNlcnZlcnMKICAgICovCiAgICB3YXRjaE1vZGVsVHlwZXM6IGZ1bmN0aW9uIHdhdGNoTW9kZWxUeXBlcyh0eXBlc0FkZGVkLCB0eXBlc1VwZGF0ZWQpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHZhciBtb2RlbFR5cGVzID0gdGhpcy5nZXRNb2RlbFR5cGVzKCk7CiAgICAgIHZhciByZWxlYXNlTWV0aG9kcyA9ICgwLCBfcnVudGltZS5BKSgpOwogICAgICB2YXIgdHlwZXNUb1NlbmQ7CiAgICAgIHR5cGVzVG9TZW5kID0gbW9kZWxUeXBlcy5tYXAoZnVuY3Rpb24gKHR5cGUpIHsKICAgICAgICB2YXIga2xhc3MgPSB0eXBlLmtsYXNzOwoKICAgICAgICB2YXIgd3JhcHBlZCA9IF90aGlzLndyYXBNb2RlbFR5cGUoa2xhc3MsIHR5cGUubmFtZSk7CgogICAgICAgIHJlbGVhc2VNZXRob2RzLnB1c2goX3RoaXMub2JzZXJ2ZU1vZGVsVHlwZSh0eXBlLm5hbWUsIHR5cGVzVXBkYXRlZCkpOwogICAgICAgIHJldHVybiB3cmFwcGVkOwogICAgICB9KTsKICAgICAgdHlwZXNBZGRlZCh0eXBlc1RvU2VuZCk7CgogICAgICB2YXIgcmVsZWFzZSA9IGZ1bmN0aW9uIHJlbGVhc2UoKSB7CiAgICAgICAgcmVsZWFzZU1ldGhvZHMuZm9yRWFjaChmdW5jdGlvbiAoZm4pIHsKICAgICAgICAgIHJldHVybiBmbigpOwogICAgICAgIH0pOwoKICAgICAgICBfdGhpcy5yZWxlYXNlTWV0aG9kcy5yZW1vdmVPYmplY3QocmVsZWFzZSk7CiAgICAgIH07CgogICAgICB0aGlzLnJlbGVhc2VNZXRob2RzLnB1c2hPYmplY3QocmVsZWFzZSk7CiAgICAgIHJldHVybiByZWxlYXNlOwogICAgfSwKICAgIF9uYW1lVG9DbGFzczogZnVuY3Rpb24gX25hbWVUb0NsYXNzKHR5cGUpIHsKICAgICAgaWYgKHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJykgewogICAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICAgIHZhciBGYWN0b3J5ID0gb3duZXIuZmFjdG9yeUZvcigibW9kZWw6IiArIHR5cGUpOwogICAgICAgIHR5cGUgPSBGYWN0b3J5ICYmIEZhY3RvcnkuY2xhc3M7CiAgICAgIH0KCiAgICAgIHJldHVybiB0eXBlOwogICAgfSwKCiAgICAvKioKICAgICAgRmV0Y2ggdGhlIHJlY29yZHMgb2YgYSBnaXZlbiB0eXBlIGFuZCBvYnNlcnZlIHRoZW0gZm9yIGNoYW5nZXMuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2Qgd2F0Y2hSZWNvcmRzCiAgICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lIFRoZSBtb2RlbCBuYW1lLgogICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gcmVjb3Jkc0FkZGVkIENhbGxiYWNrIHRvIGNhbGwgdG8gYWRkIHJlY29yZHMuCiAgICAgIFRha2VzIGFuIGFycmF5IG9mIG9iamVjdHMgY29udGFpbmluZyB3cmFwcGVkIHJlY29yZHMuCiAgICAgIFRoZSBvYmplY3Qgc2hvdWxkIGhhdmUgdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzOgogICAgICAgIGNvbHVtblZhbHVlczoge09iamVjdH0gVGhlIGtleSBhbmQgdmFsdWUgb2YgYSB0YWJsZSBjZWxsLgogICAgICAgIG9iamVjdDoge09iamVjdH0gVGhlIGFjdHVhbCByZWNvcmQgb2JqZWN0LgogICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gcmVjb3Jkc1VwZGF0ZWQgQ2FsbGJhY2sgdG8gY2FsbCB3aGVuIGEgcmVjb3JkIGhhcyBjaGFuZ2VkLgogICAgICBUYWtlcyBhbiBhcnJheSBvZiBvYmplY3RzIGNvbnRhaW5pbmcgd3JhcHBlZCByZWNvcmRzLgogICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gcmVjb3Jkc1JlbW92ZWQgQ2FsbGJhY2sgdG8gY2FsbCB3aGVuIGEgcmVjb3JkIGhhcyByZW1vdmVkLgogICAgICBUYWtlcyB0aGUgZm9sbG93aW5nIHBhcmFtZXRlcnM6CiAgICAgICAgaW5kZXg6IFRoZSBhcnJheSBpbmRleCB3aGVyZSB0aGUgcmVjb3JkcyB3ZXJlIHJlbW92ZWQuCiAgICAgICAgY291bnQ6IFRoZSBudW1iZXIgb2YgcmVjb3JkcyByZW1vdmVkLgogICAgICAgQHJldHVybiB7RnVuY3Rpb259IE1ldGhvZCB0byBjYWxsIHRvIHJlbW92ZSBhbGwgb2JzZXJ2ZXJzLgogICAgKi8KICAgIHdhdGNoUmVjb3JkczogZnVuY3Rpb24gd2F0Y2hSZWNvcmRzKG1vZGVsTmFtZSwgcmVjb3Jkc0FkZGVkLCByZWNvcmRzVXBkYXRlZCwgcmVjb3Jkc1JlbW92ZWQpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICB2YXIgcmVsZWFzZU1ldGhvZHMgPSAoMCwgX3J1bnRpbWUuQSkoKTsKCiAgICAgIHZhciBrbGFzcyA9IHRoaXMuX25hbWVUb0NsYXNzKG1vZGVsTmFtZSk7CgogICAgICB2YXIgcmVjb3JkcyA9IHRoaXMuZ2V0UmVjb3JkcyhrbGFzcywgbW9kZWxOYW1lKTsKCiAgICAgIHZhciBfcmVsZWFzZTsKCiAgICAgIGZ1bmN0aW9uIHJlY29yZFVwZGF0ZWQodXBkYXRlZFJlY29yZCkgewogICAgICAgIHJlY29yZHNVcGRhdGVkKFt1cGRhdGVkUmVjb3JkXSk7CiAgICAgIH0KCiAgICAgIHZhciByZWNvcmRzVG9TZW5kID0gcmVjb3Jkcy5tYXAoZnVuY3Rpb24gKHJlY29yZCkgewogICAgICAgIHJlbGVhc2VNZXRob2RzLnB1c2goX3RoaXMyLm9ic2VydmVSZWNvcmQocmVjb3JkLCByZWNvcmRVcGRhdGVkKSk7CiAgICAgICAgcmV0dXJuIF90aGlzMi53cmFwUmVjb3JkKHJlY29yZCk7CiAgICAgIH0pOwoKICAgICAgdmFyIGNvbnRlbnREaWRDaGFuZ2UgPSBmdW5jdGlvbiBjb250ZW50RGlkQ2hhbmdlKGFycmF5LCBpZHgsIHJlbW92ZWRDb3VudCwgYWRkZWRDb3VudCkgewogICAgICAgIGZvciAodmFyIGkgPSBpZHg7IGkgPCBpZHggKyBhZGRlZENvdW50OyBpKyspIHsKICAgICAgICAgIHZhciByZWNvcmQgPSAoMCwgX21ldGFsLm9iamVjdEF0KShhcnJheSwgaSk7CgogICAgICAgICAgdmFyIHdyYXBwZWQgPSBfdGhpczIud3JhcFJlY29yZChyZWNvcmQpOwoKICAgICAgICAgIHJlbGVhc2VNZXRob2RzLnB1c2goX3RoaXMyLm9ic2VydmVSZWNvcmQocmVjb3JkLCByZWNvcmRVcGRhdGVkKSk7CiAgICAgICAgICByZWNvcmRzQWRkZWQoW3dyYXBwZWRdKTsKICAgICAgICB9CgogICAgICAgIGlmIChyZW1vdmVkQ291bnQpIHsKICAgICAgICAgIHJlY29yZHNSZW1vdmVkKGlkeCwgcmVtb3ZlZENvdW50KTsKICAgICAgICB9CiAgICAgIH07CgogICAgICB2YXIgb2JzZXJ2ZXIgPSB7CiAgICAgICAgZGlkQ2hhbmdlOiBjb250ZW50RGlkQ2hhbmdlLAogICAgICAgIHdpbGxDaGFuZ2U6IGZ1bmN0aW9uIHdpbGxDaGFuZ2UoKSB7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH07CiAgICAgICgwLCBfbWV0YWwuYWRkQXJyYXlPYnNlcnZlcikocmVjb3JkcywgdGhpcywgb2JzZXJ2ZXIpOwoKICAgICAgX3JlbGVhc2UgPSBmdW5jdGlvbiByZWxlYXNlKCkgewogICAgICAgIHJlbGVhc2VNZXRob2RzLmZvckVhY2goZnVuY3Rpb24gKGZuKSB7CiAgICAgICAgICByZXR1cm4gZm4oKTsKICAgICAgICB9KTsKICAgICAgICAoMCwgX21ldGFsLnJlbW92ZUFycmF5T2JzZXJ2ZXIpKHJlY29yZHMsIF90aGlzMiwgb2JzZXJ2ZXIpOwoKICAgICAgICBfdGhpczIucmVsZWFzZU1ldGhvZHMucmVtb3ZlT2JqZWN0KF9yZWxlYXNlKTsKICAgICAgfTsKCiAgICAgIHJlY29yZHNBZGRlZChyZWNvcmRzVG9TZW5kKTsKICAgICAgdGhpcy5yZWxlYXNlTWV0aG9kcy5wdXNoT2JqZWN0KF9yZWxlYXNlKTsKICAgICAgcmV0dXJuIF9yZWxlYXNlOwogICAgfSwKCiAgICAvKioKICAgICAgQ2xlYXIgYWxsIG9ic2VydmVycyBiZWZvcmUgZGVzdHJ1Y3Rpb24KICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCB3aWxsRGVzdHJveQogICAgKi8KICAgIHdpbGxEZXN0cm95OiBmdW5jdGlvbiB3aWxsRGVzdHJveSgpIHsKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIHRoaXMucmVsZWFzZU1ldGhvZHMuZm9yRWFjaChmdW5jdGlvbiAoZm4pIHsKICAgICAgICByZXR1cm4gZm4oKTsKICAgICAgfSk7CiAgICB9LAoKICAgIC8qKgogICAgICBEZXRlY3Qgd2hldGhlciBhIGNsYXNzIGlzIGEgbW9kZWwuCiAgICAgICBUZXN0IHRoYXQgYWdhaW5zdCB0aGUgbW9kZWwgY2xhc3MKICAgICAgb2YgeW91ciBwZXJzaXN0ZW5jZSBsaWJyYXJ5LgogICAgICAgQHB1YmxpYwogICAgICBAbWV0aG9kIGRldGVjdAogICAgICBAcmV0dXJuIGJvb2xlYW4gV2hldGhlciB0aGUgY2xhc3MgaXMgYSBtb2RlbCBjbGFzcyBvciBub3QuCiAgICAqLwogICAgZGV0ZWN0OiBmdW5jdGlvbiBkZXRlY3QoKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0sCgogICAgLyoqCiAgICAgIEdldCB0aGUgY29sdW1ucyBmb3IgYSBnaXZlbiBtb2RlbCB0eXBlLgogICAgICAgQHB1YmxpYwogICAgICBAbWV0aG9kIGNvbHVtbnNGb3JUeXBlCiAgICAgIEByZXR1cm4ge0FycmF5fSBBbiBhcnJheSBvZiBjb2x1bW5zIG9mIHRoZSBmb2xsb3dpbmcgZm9ybWF0OgogICAgICAgbmFtZToge1N0cmluZ30gVGhlIG5hbWUgb2YgdGhlIGNvbHVtbi4KICAgICAgIGRlc2M6IHtTdHJpbmd9IEh1bWFuaXplZCBkZXNjcmlwdGlvbiAod2hhdCB3b3VsZCBzaG93IGluIGEgdGFibGUgY29sdW1uIG5hbWUpLgogICAgKi8KICAgIGNvbHVtbnNGb3JUeXBlOiBmdW5jdGlvbiBjb2x1bW5zRm9yVHlwZSgpIHsKICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5BKSgpOwogICAgfSwKCiAgICAvKioKICAgICAgQWRkcyBvYnNlcnZlcnMgdG8gYSBtb2RlbCB0eXBlIGNsYXNzLgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBvYnNlcnZlTW9kZWxUeXBlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUgVGhlIG1vZGVsIHR5cGUgbmFtZS4KICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gdHlwZXNVcGRhdGVkIENhbGxlZCB3aGVuIGEgdHlwZSBpcyBtb2RpZmllZC4KICAgICAgQHJldHVybiB7RnVuY3Rpb259IFRoZSBmdW5jdGlvbiB0byBjYWxsIHRvIHJlbW92ZSBvYnNlcnZlcnMuCiAgICAqLwogICAgb2JzZXJ2ZU1vZGVsVHlwZTogZnVuY3Rpb24gb2JzZXJ2ZU1vZGVsVHlwZShtb2RlbE5hbWUsIHR5cGVzVXBkYXRlZCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHZhciBrbGFzcyA9IHRoaXMuX25hbWVUb0NsYXNzKG1vZGVsTmFtZSk7CgogICAgICB2YXIgcmVjb3JkcyA9IHRoaXMuZ2V0UmVjb3JkcyhrbGFzcywgbW9kZWxOYW1lKTsKCiAgICAgIGZ1bmN0aW9uIG9uQ2hhbmdlKCkgewogICAgICAgIHR5cGVzVXBkYXRlZChbdGhpcy53cmFwTW9kZWxUeXBlKGtsYXNzLCBtb2RlbE5hbWUpXSk7CiAgICAgIH0KCiAgICAgIHZhciBvYnNlcnZlciA9IHsKICAgICAgICBkaWRDaGFuZ2U6IGZ1bmN0aW9uIGRpZENoYW5nZShhcnJheSwgaWR4LCByZW1vdmVkQ291bnQsIGFkZGVkQ291bnQpIHsKICAgICAgICAgIC8vIE9ubHkgcmUtZmV0Y2ggcmVjb3JkcyBpZiB0aGUgcmVjb3JkIGNvdW50IGNoYW5nZWQKICAgICAgICAgIC8vICh3aGljaCBpcyBhbGwgd2UgY2FyZSBhYm91dCBhcyBmYXIgYXMgbW9kZWwgdHlwZXMgYXJlIGNvbmNlcm5lZCkuCiAgICAgICAgICBpZiAocmVtb3ZlZENvdW50ID4gMCB8fCBhZGRlZENvdW50ID4gMCkgewogICAgICAgICAgICAoMCwgX3J1bmxvb3Auc2NoZWR1bGVPbmNlKSgnYWN0aW9ucycsIHRoaXMsIG9uQ2hhbmdlKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIHdpbGxDaGFuZ2U6IGZ1bmN0aW9uIHdpbGxDaGFuZ2UoKSB7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9CiAgICAgIH07CiAgICAgICgwLCBfbWV0YWwuYWRkQXJyYXlPYnNlcnZlcikocmVjb3JkcywgdGhpcywgb2JzZXJ2ZXIpOwoKICAgICAgdmFyIHJlbGVhc2UgPSBmdW5jdGlvbiByZWxlYXNlKCkgewogICAgICAgIHJldHVybiAoMCwgX21ldGFsLnJlbW92ZUFycmF5T2JzZXJ2ZXIpKHJlY29yZHMsIF90aGlzMywgb2JzZXJ2ZXIpOwogICAgICB9OwoKICAgICAgcmV0dXJuIHJlbGVhc2U7CiAgICB9LAoKICAgIC8qKgogICAgICBXcmFwcyBhIGdpdmVuIG1vZGVsIHR5cGUgYW5kIG9ic2VydmVzIGNoYW5nZXMgdG8gaXQuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHdyYXBNb2RlbFR5cGUKICAgICAgQHBhcmFtIHtDbGFzc30ga2xhc3MgQSBtb2RlbCBjbGFzcy4KICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZSBOYW1lIG9mIHRoZSBjbGFzcy4KICAgICAgQHJldHVybiB7T2JqZWN0fSBDb250YWlucyB0aGUgd3JhcHBlZCB0eXBlIGFuZCB0aGUgZnVuY3Rpb24gdG8gcmVtb3ZlIG9ic2VydmVycwogICAgICBGb3JtYXQ6CiAgICAgICAgdHlwZToge09iamVjdH0gVGhlIHdyYXBwZWQgdHlwZS4KICAgICAgICAgIFRoZSB3cmFwcGVkIHR5cGUgaGFzIHRoZSBmb2xsb3dpbmcgZm9ybWF0OgogICAgICAgICAgICBuYW1lOiB7U3RyaW5nfSBUaGUgbmFtZSBvZiB0aGUgdHlwZS4KICAgICAgICAgICAgY291bnQ6IHtJbnRlZ2VyfSBUaGUgbnVtYmVyIG9mIHJlY29yZHMgYXZhaWxhYmxlLgogICAgICAgICAgICBjb2x1bW5zOiB7Q29sdW1uc30gQW4gYXJyYXkgb2YgY29sdW1ucyB0byBkZXNjcmliZSB0aGUgcmVjb3JkLgogICAgICAgICAgICBvYmplY3Q6IHtDbGFzc30gVGhlIGFjdHVhbCBNb2RlbCB0eXBlIGNsYXNzLgogICAgICAgIHJlbGVhc2U6IHtGdW5jdGlvbn0gVGhlIGZ1bmN0aW9uIHRvIHJlbW92ZSBvYnNlcnZlcnMuCiAgICAqLwogICAgd3JhcE1vZGVsVHlwZTogZnVuY3Rpb24gd3JhcE1vZGVsVHlwZShrbGFzcywgbmFtZSkgewogICAgICB2YXIgcmVjb3JkcyA9IHRoaXMuZ2V0UmVjb3JkcyhrbGFzcywgbmFtZSk7CiAgICAgIHZhciB0eXBlVG9TZW5kOwogICAgICB0eXBlVG9TZW5kID0gewogICAgICAgIG5hbWU6IG5hbWUsCiAgICAgICAgY291bnQ6ICgwLCBfbWV0YWwuZ2V0KShyZWNvcmRzLCAnbGVuZ3RoJyksCiAgICAgICAgY29sdW1uczogdGhpcy5jb2x1bW5zRm9yVHlwZShrbGFzcyksCiAgICAgICAgb2JqZWN0OiBrbGFzcwogICAgICB9OwogICAgICByZXR1cm4gdHlwZVRvU2VuZDsKICAgIH0sCgogICAgLyoqCiAgICAgIEZldGNoZXMgYWxsIG1vZGVscyBkZWZpbmVkIGluIHRoZSBhcHBsaWNhdGlvbi4KICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZ2V0TW9kZWxUeXBlcwogICAgICBAcmV0dXJuIHtBcnJheX0gQXJyYXkgb2YgbW9kZWwgdHlwZXMuCiAgICAqLwogICAgZ2V0TW9kZWxUeXBlczogZnVuY3Rpb24gZ2V0TW9kZWxUeXBlcygpIHsKICAgICAgdmFyIF90aGlzNCA9IHRoaXM7CgogICAgICB2YXIgY29udGFpbmVyRGVidWdBZGFwdGVyID0gdGhpcy5nZXQoJ2NvbnRhaW5lckRlYnVnQWRhcHRlcicpOwogICAgICB2YXIgdHlwZXM7CgogICAgICBpZiAoY29udGFpbmVyRGVidWdBZGFwdGVyLmNhbkNhdGFsb2dFbnRyaWVzQnlUeXBlKCdtb2RlbCcpKSB7CiAgICAgICAgdHlwZXMgPSBjb250YWluZXJEZWJ1Z0FkYXB0ZXIuY2F0YWxvZ0VudHJpZXNCeVR5cGUoJ21vZGVsJyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdHlwZXMgPSB0aGlzLl9nZXRPYmplY3RzT25OYW1lc3BhY2VzKCk7CiAgICAgIH0gLy8gTmV3IGFkYXB0ZXJzIHJldHVybiBzdHJpbmdzIGluc3RlYWQgb2YgY2xhc3Nlcy4KCgogICAgICB0eXBlcyA9ICgwLCBfcnVudGltZS5BKSh0eXBlcykubWFwKGZ1bmN0aW9uIChuYW1lKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGtsYXNzOiBfdGhpczQuX25hbWVUb0NsYXNzKG5hbWUpLAogICAgICAgICAgbmFtZTogbmFtZQogICAgICAgIH07CiAgICAgIH0pOwogICAgICB0eXBlcyA9ICgwLCBfcnVudGltZS5BKSh0eXBlcykuZmlsdGVyKGZ1bmN0aW9uICh0eXBlKSB7CiAgICAgICAgcmV0dXJuIF90aGlzNC5kZXRlY3QodHlwZS5rbGFzcyk7CiAgICAgIH0pOwogICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKHR5cGVzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIExvb3BzIG92ZXIgYWxsIG5hbWVzcGFjZXMgYW5kIGFsbCBvYmplY3RzCiAgICAgIGF0dGFjaGVkIHRvIHRoZW0uCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9nZXRPYmplY3RzT25OYW1lc3BhY2VzCiAgICAgIEByZXR1cm4ge0FycmF5fSBBcnJheSBvZiBtb2RlbCB0eXBlIHN0cmluZ3MuCiAgICAqLwogICAgX2dldE9iamVjdHNPbk5hbWVzcGFjZXM6IGZ1bmN0aW9uIF9nZXRPYmplY3RzT25OYW1lc3BhY2VzKCkgewogICAgICB2YXIgX3RoaXM1ID0gdGhpczsKCiAgICAgIHZhciBuYW1lc3BhY2VzID0gKDAsIF9ydW50aW1lLkEpKF9ydW50aW1lLk5hbWVzcGFjZS5OQU1FU1BBQ0VTKTsKICAgICAgdmFyIHR5cGVzID0gKDAsIF9ydW50aW1lLkEpKCk7CiAgICAgIG5hbWVzcGFjZXMuZm9yRWFjaChmdW5jdGlvbiAobmFtZXNwYWNlKSB7CiAgICAgICAgZm9yICh2YXIga2V5IGluIG5hbWVzcGFjZSkgewogICAgICAgICAgaWYgKCFuYW1lc3BhY2UuaGFzT3duUHJvcGVydHkoa2V5KSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0gLy8gRXZlbiB0aG91Z2ggd2Ugd2lsbCBmaWx0ZXIgYWdhaW4gaW4gYGdldE1vZGVsVHlwZXNgLAogICAgICAgICAgLy8gd2Ugc2hvdWxkIG5vdCBjYWxsIGBsb29rdXBGYWN0b3J5YCBvbiBub24tbW9kZWxzCgoKICAgICAgICAgIGlmICghX3RoaXM1LmRldGVjdChuYW1lc3BhY2Vba2V5XSkpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CgogICAgICAgICAgdmFyIG5hbWUgPSAoMCwgX3N0cmluZy5kYXNoZXJpemUpKGtleSk7CiAgICAgICAgICB0eXBlcy5wdXNoKG5hbWUpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiB0eXBlczsKICAgIH0sCgogICAgLyoqCiAgICAgIEZldGNoZXMgYWxsIGxvYWRlZCByZWNvcmRzIGZvciBhIGdpdmVuIHR5cGUuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgZ2V0UmVjb3JkcwogICAgICBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2YgcmVjb3Jkcy4KICAgICAgIFRoaXMgYXJyYXkgd2lsbCBiZSBvYnNlcnZlZCBmb3IgY2hhbmdlcywKICAgICAgIHNvIGl0IHNob3VsZCB1cGRhdGUgd2hlbiBuZXcgcmVjb3JkcyBhcmUgYWRkZWQvcmVtb3ZlZC4KICAgICovCiAgICBnZXRSZWNvcmRzOiBmdW5jdGlvbiBnZXRSZWNvcmRzKCkgewogICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBXcmFwcyBhIHJlY29yZCBhbmQgb2JzZXJ2ZXJzIGNoYW5nZXMgdG8gaXQuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHdyYXBSZWNvcmQKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlY29yZCBUaGUgcmVjb3JkIGluc3RhbmNlLgogICAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSB3cmFwcGVkIHJlY29yZC4gRm9ybWF0OgogICAgICBjb2x1bW5WYWx1ZXM6IHtBcnJheX0KICAgICAgc2VhcmNoS2V5d29yZHM6IHtBcnJheX0KICAgICovCiAgICB3cmFwUmVjb3JkOiBmdW5jdGlvbiB3cmFwUmVjb3JkKHJlY29yZCkgewogICAgICB2YXIgcmVjb3JkVG9TZW5kID0gewogICAgICAgIG9iamVjdDogcmVjb3JkCiAgICAgIH07CiAgICAgIHJlY29yZFRvU2VuZC5jb2x1bW5WYWx1ZXMgPSB0aGlzLmdldFJlY29yZENvbHVtblZhbHVlcyhyZWNvcmQpOwogICAgICByZWNvcmRUb1NlbmQuc2VhcmNoS2V5d29yZHMgPSB0aGlzLmdldFJlY29yZEtleXdvcmRzKHJlY29yZCk7CiAgICAgIHJlY29yZFRvU2VuZC5maWx0ZXJWYWx1ZXMgPSB0aGlzLmdldFJlY29yZEZpbHRlclZhbHVlcyhyZWNvcmQpOwogICAgICByZWNvcmRUb1NlbmQuY29sb3IgPSB0aGlzLmdldFJlY29yZENvbG9yKHJlY29yZCk7CiAgICAgIHJldHVybiByZWNvcmRUb1NlbmQ7CiAgICB9LAoKICAgIC8qKgogICAgICBHZXRzIHRoZSB2YWx1ZXMgZm9yIGVhY2ggY29sdW1uLgogICAgICAgQHB1YmxpYwogICAgICBAbWV0aG9kIGdldFJlY29yZENvbHVtblZhbHVlcwogICAgICBAcmV0dXJuIHtPYmplY3R9IEtleXMgc2hvdWxkIG1hdGNoIGNvbHVtbiBuYW1lcyBkZWZpbmVkCiAgICAgIGJ5IHRoZSBtb2RlbCB0eXBlLgogICAgKi8KICAgIGdldFJlY29yZENvbHVtblZhbHVlczogZnVuY3Rpb24gZ2V0UmVjb3JkQ29sdW1uVmFsdWVzKCkgewogICAgICByZXR1cm4ge307CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIGtleXdvcmRzIHRvIG1hdGNoIHdoZW4gc2VhcmNoaW5nIHJlY29yZHMuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgZ2V0UmVjb3JkS2V5d29yZHMKICAgICAgQHJldHVybiB7QXJyYXl9IFJlbGV2YW50IGtleXdvcmRzIGZvciBzZWFyY2guCiAgICAqLwogICAgZ2V0UmVjb3JkS2V5d29yZHM6IGZ1bmN0aW9uIGdldFJlY29yZEtleXdvcmRzKCkgewogICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSB2YWx1ZXMgb2YgZmlsdGVycyBkZWZpbmVkIGJ5IGBnZXRGaWx0ZXJzYC4KICAgICAgIEBwdWJsaWMKICAgICAgQG1ldGhvZCBnZXRSZWNvcmRGaWx0ZXJWYWx1ZXMKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlY29yZCBUaGUgcmVjb3JkIGluc3RhbmNlLgogICAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSBmaWx0ZXIgdmFsdWVzLgogICAgKi8KICAgIGdldFJlY29yZEZpbHRlclZhbHVlczogZnVuY3Rpb24gZ2V0UmVjb3JkRmlsdGVyVmFsdWVzKCkgewogICAgICByZXR1cm4ge307CiAgICB9LAoKICAgIC8qKgogICAgICBFYWNoIHJlY29yZCBjYW4gaGF2ZSBhIGNvbG9yIHRoYXQgcmVwcmVzZW50cyBpdHMgc3RhdGUuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgZ2V0UmVjb3JkQ29sb3IKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlY29yZCBUaGUgcmVjb3JkIGluc3RhbmNlCiAgICAgIEByZXR1cm4ge1N0cmluZ30gVGhlIHJlY29yZHMgY29sb3IuCiAgICAgICAgUG9zc2libGUgb3B0aW9uczogYmxhY2ssIHJlZCwgYmx1ZSwgZ3JlZW4uCiAgICAqLwogICAgZ2V0UmVjb3JkQ29sb3I6IGZ1bmN0aW9uIGdldFJlY29yZENvbG9yKCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0sCgogICAgLyoqCiAgICAgIE9ic2VydmVzIGFsbCByZWxldmFudCBwcm9wZXJ0aWVzIGFuZCByZS1zZW5kcyB0aGUgd3JhcHBlZCByZWNvcmQKICAgICAgd2hlbiBhIGNoYW5nZSBvY2N1cnMuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2Qgb2JzZXJ2ZXJSZWNvcmQKICAgICAgQHJldHVybiB7RnVuY3Rpb259IFRoZSBmdW5jdGlvbiB0byBjYWxsIHRvIHJlbW92ZSBhbGwgb2JzZXJ2ZXJzLgogICAgKi8KICAgIG9ic2VydmVSZWNvcmQ6IGZ1bmN0aW9uIG9ic2VydmVSZWNvcmQoKSB7CiAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7fTsKICAgIH0KICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9nbGltbWVyL2luZGV4IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvY29udGFpbmVyIiwgIkBnbGltbWVyL29wY29kZS1jb21waWxlciIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9ydW5sb29wIiwgIkBnbGltbWVyL3JlZmVyZW5jZSIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciLCAiQGdsaW1tZXIvcnVudGltZSIsICJAZ2xpbW1lci91dGlsIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzIiwgIkBlbWJlci8taW50ZXJuYWxzL2Jyb3dzZXItZW52aXJvbm1lbnQiLCAiQGVtYmVyL2luc3RydW1lbnRhdGlvbiIsICJAZW1iZXIvc2VydmljZSIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCIsICJAZW1iZXIvc3RyaW5nIiwgIkBnbGltbWVyL3dpcmUtZm9ybWF0IiwgInJzdnAiLCAiQGdsaW1tZXIvbm9kZSIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nIiwgIkBlbWJlci9jb21wb25lbnQvdGVtcGxhdGUtb25seSIsICJAZW1iZXIvZGVwcmVjYXRlZC1mZWF0dXJlcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfcG9seWZpbGxzLCBfY29udGFpbmVyLCBfb3Bjb2RlQ29tcGlsZXIsIF9ydW50aW1lLCBfdXRpbHMsIF9ydW5sb29wLCBfcmVmZXJlbmNlLCBfbWV0YWwsIF9kZWJ1ZywgX3J1bnRpbWUyLCBfdXRpbCwgX293bmVyLCBfdmlld3MsIF9icm93c2VyRW52aXJvbm1lbnQsIF9pbnN0cnVtZW50YXRpb24sIF9zZXJ2aWNlLCBfZW52aXJvbm1lbnQyLCBfc3RyaW5nLCBfd2lyZUZvcm1hdCwgX3JzdnAsIF9ub2RlLCBfcm91dGluZywgX3RlbXBsYXRlT25seSwgX2RlcHJlY2F0ZWRGZWF0dXJlcykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMudGVtcGxhdGUgPSB0ZW1wbGF0ZTsKICBfZXhwb3J0cy5oZWxwZXIgPSBoZWxwZXI7CiAgX2V4cG9ydHMuZXNjYXBlRXhwcmVzc2lvbiA9IGVzY2FwZUV4cHJlc3Npb247CiAgX2V4cG9ydHMuaHRtbFNhZmUgPSBodG1sU2FmZTsKICBfZXhwb3J0cy5pc0hUTUxTYWZlID0gaXNIVE1MU2FmZTsKICBfZXhwb3J0cy5fcmVzZXRSZW5kZXJlcnMgPSBfcmVzZXRSZW5kZXJlcnM7CiAgX2V4cG9ydHMucmVuZGVyU2V0dGxlZCA9IHJlbmRlclNldHRsZWQ7CiAgX2V4cG9ydHMuZ2V0VGVtcGxhdGUgPSBnZXRUZW1wbGF0ZTsKICBfZXhwb3J0cy5zZXRUZW1wbGF0ZSA9IHNldFRlbXBsYXRlOwogIF9leHBvcnRzLmhhc1RlbXBsYXRlID0gaGFzVGVtcGxhdGU7CiAgX2V4cG9ydHMuZ2V0VGVtcGxhdGVzID0gZ2V0VGVtcGxhdGVzOwogIF9leHBvcnRzLnNldFRlbXBsYXRlcyA9IHNldFRlbXBsYXRlczsKICBfZXhwb3J0cy5zZXR1cEVuZ2luZVJlZ2lzdHJ5ID0gc2V0dXBFbmdpbmVSZWdpc3RyeTsKICBfZXhwb3J0cy5zZXR1cEFwcGxpY2F0aW9uUmVnaXN0cnkgPSBzZXR1cEFwcGxpY2F0aW9uUmVnaXN0cnk7CiAgX2V4cG9ydHMuX3JlZ2lzdGVyTWFjcm9zID0gcmVnaXN0ZXJNYWNyb3M7CiAgX2V4cG9ydHMuaXRlcmFibGVGb3IgPSBfaXRlcmFibGVGb3I7CiAgX2V4cG9ydHMuY2FwYWJpbGl0aWVzID0gY2FwYWJpbGl0aWVzOwogIF9leHBvcnRzLnNldENvbXBvbmVudE1hbmFnZXIgPSBzZXRDb21wb25lbnRNYW5hZ2VyOwogIF9leHBvcnRzLmdldENvbXBvbmVudE1hbmFnZXIgPSBnZXRDb21wb25lbnRNYW5hZ2VyOwogIF9leHBvcnRzLnNldE1vZGlmaWVyTWFuYWdlciA9IHNldE1vZGlmaWVyTWFuYWdlcjsKICBfZXhwb3J0cy5nZXRNb2RpZmllck1hbmFnZXIgPSBnZXRNb2RpZmllck1hbmFnZXI7CiAgX2V4cG9ydHMubW9kaWZpZXJDYXBhYmlsaXRpZXMgPSBjYXBhYmlsaXRpZXMkMTsKICBfZXhwb3J0cy5zZXRDb21wb25lbnRUZW1wbGF0ZSA9IHNldENvbXBvbmVudFRlbXBsYXRlOwogIF9leHBvcnRzLmdldENvbXBvbmVudFRlbXBsYXRlID0gZ2V0Q29tcG9uZW50VGVtcGxhdGU7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiRE9NQ2hhbmdlcyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9ydW50aW1lMi5ET01DaGFuZ2VzOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkRPTVRyZWVDb25zdHJ1Y3Rpb24iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcnVudGltZTIuRE9NVHJlZUNvbnN0cnVjdGlvbjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJpc1NlcmlhbGl6YXRpb25GaXJzdE5vZGUiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcnVudGltZTIuaXNTZXJpYWxpemF0aW9uRmlyc3ROb2RlOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIk5vZGVET01UcmVlQ29uc3RydWN0aW9uIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX25vZGUuTm9kZURPTVRyZWVDb25zdHJ1Y3Rpb247CiAgICB9CiAgfSk7CiAgX2V4cG9ydHMuT3V0bGV0VmlldyA9IF9leHBvcnRzLkRlYnVnU3RhY2sgPSBfZXhwb3J0cy5JTlZPS0UgPSBfZXhwb3J0cy5VcGRhdGFibGVSZWZlcmVuY2UgPSBfZXhwb3J0cy5BYnN0cmFjdENvbXBvbmVudE1hbmFnZXIgPSBfZXhwb3J0cy5fZXhwZXJpbWVudGFsTWFjcm9zID0gX2V4cG9ydHMuSW50ZXJhY3RpdmVSZW5kZXJlciA9IF9leHBvcnRzLkluZXJ0UmVuZGVyZXIgPSBfZXhwb3J0cy5SZW5kZXJlciA9IF9leHBvcnRzLlNhZmVTdHJpbmcgPSBfZXhwb3J0cy5FbnZpcm9ubWVudCA9IF9leHBvcnRzLkhlbHBlciA9IF9leHBvcnRzLlJPT1RfUkVGID0gX2V4cG9ydHMuQ29tcG9uZW50ID0gX2V4cG9ydHMuTGlua0NvbXBvbmVudCA9IF9leHBvcnRzLlRleHRBcmVhID0gX2V4cG9ydHMuVGV4dEZpZWxkID0gX2V4cG9ydHMuQ2hlY2tib3ggPSBfZXhwb3J0cy50ZW1wbGF0ZUNhY2hlQ291bnRlcnMgPSBfZXhwb3J0cy5Sb290VGVtcGxhdGUgPSB2b2lkIDA7CgogIHZhciBfQ29yZVZpZXckZXh0ZW5kOwoKICBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3QxMCgpIHsKICAgIHZhciBkYXRhID0gKDAsIF9lbWJlckJhYmVsLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlKShbImNvbXBvbmVudDotZGVmYXVsdCJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3QxMCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDEwKCkgewogICAgICByZXR1cm4gZGF0YTsKICAgIH07CgogICAgcmV0dXJuIGRhdGE7CiAgfQoKICBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3Q5KCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsidGVtcGxhdGUtY29tcGlsZXI6bWFpbiJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3Q5ID0gZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0OSgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0OCgpIHsKICAgIHZhciBkYXRhID0gKDAsIF9lbWJlckJhYmVsLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlKShbInRlbXBsYXRlLWNvbXBpbGVyOm1haW4iXSk7CgogICAgX3RlbXBsYXRlT2JqZWN0OCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDgoKSB7CiAgICAgIHJldHVybiBkYXRhOwogICAgfTsKCiAgICByZXR1cm4gZGF0YTsKICB9CgogIGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDcoKSB7CiAgICB2YXIgZGF0YSA9ICgwLCBfZW1iZXJCYWJlbC50YWdnZWRUZW1wbGF0ZUxpdGVyYWxMb29zZSkoWyJ0ZW1wbGF0ZTpjb21wb25lbnRzLy1kZWZhdWx0Il0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdDcgPSBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3Q3KCkgewogICAgICByZXR1cm4gZGF0YTsKICAgIH07CgogICAgcmV0dXJuIGRhdGE7CiAgfQoKICBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3Q2KCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsidGVtcGxhdGU6LXJvb3QiXSk7CgogICAgX3RlbXBsYXRlT2JqZWN0NiA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDYoKSB7CiAgICAgIHJldHVybiBkYXRhOwogICAgfTsKCiAgICByZXR1cm4gZGF0YTsKICB9CgogIGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDUoKSB7CiAgICB2YXIgZGF0YSA9ICgwLCBfZW1iZXJCYWJlbC50YWdnZWRUZW1wbGF0ZUxpdGVyYWxMb29zZSkoWyJ0ZW1wbGF0ZTotcm9vdCJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3Q1ID0gZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0NSgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0NCgpIHsKICAgIHZhciBkYXRhID0gKDAsIF9lbWJlckJhYmVsLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlKShbImNvbXBvbmVudDotZGVmYXVsdCJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3Q0ID0gZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0NCgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0MygpIHsKICAgIHZhciBkYXRhID0gKDAsIF9lbWJlckJhYmVsLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlKShbInRlbXBsYXRlOmNvbXBvbmVudHMvLWRlZmF1bHQiXSk7CgogICAgX3RlbXBsYXRlT2JqZWN0MyA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDMoKSB7CiAgICAgIHJldHVybiBkYXRhOwogICAgfTsKCiAgICByZXR1cm4gZGF0YTsKICB9CgogIGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdDIoKSB7CiAgICB2YXIgZGF0YSA9ICgwLCBfZW1iZXJCYWJlbC50YWdnZWRUZW1wbGF0ZUxpdGVyYWxMb29zZSkoWyJ0ZW1wbGF0ZTpjb21wb25lbnRzLy1kZWZhdWx0Il0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdDIgPSBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3QyKCkgewogICAgICByZXR1cm4gZGF0YTsKICAgIH07CgogICAgcmV0dXJuIGRhdGE7CiAgfQoKICBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3QoKSB7CiAgICB2YXIgZGF0YSA9ICgwLCBfZW1iZXJCYWJlbC50YWdnZWRUZW1wbGF0ZUxpdGVyYWxMb29zZSkoWyJ0ZW1wbGF0ZS1jb21waWxlcjptYWluIl0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdCgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gaXNUZW1wbGF0ZUZhY3RvcnkodGVtcGxhdGUpIHsKICAgIHJldHVybiB0eXBlb2YgdGVtcGxhdGUgPT09ICdmdW5jdGlvbic7CiAgfQoKICB2YXIgY291bnRlcnMgPSB7CiAgICBjYWNoZUhpdDogMCwKICAgIGNhY2hlTWlzczogMAogIH07CiAgX2V4cG9ydHMudGVtcGxhdGVDYWNoZUNvdW50ZXJzID0gY291bnRlcnM7CiAgdmFyIFRFTVBMQVRFX0NPTVBJTEVSX01BSU4gPSAoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdCgpKTsKCiAgZnVuY3Rpb24gdGVtcGxhdGUoanNvbikgewogICAgdmFyIGdsaW1tZXJGYWN0b3J5ID0gKDAsIF9vcGNvZGVDb21waWxlci50ZW1wbGF0ZUZhY3RvcnkpKGpzb24pOwogICAgdmFyIGNhY2hlID0gbmV3IFdlYWtNYXAoKTsKCiAgICB2YXIgZmFjdG9yeSA9IGZ1bmN0aW9uIGZhY3Rvcnkob3duZXIpIHsKICAgICAgdmFyIHJlc3VsdCA9IGNhY2hlLmdldChvd25lcik7CgogICAgICBpZiAocmVzdWx0ID09PSB1bmRlZmluZWQpIHsKICAgICAgICBjb3VudGVycy5jYWNoZU1pc3MrKzsKICAgICAgICB2YXIgY29tcGlsZXIgPSBvd25lci5sb29rdXAoVEVNUExBVEVfQ09NUElMRVJfTUFJTik7CiAgICAgICAgcmVzdWx0ID0gZ2xpbW1lckZhY3RvcnkuY3JlYXRlKGNvbXBpbGVyLCB7CiAgICAgICAgICBvd25lcjogb3duZXIKICAgICAgICB9KTsKICAgICAgICBjYWNoZS5zZXQob3duZXIsIHJlc3VsdCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY291bnRlcnMuY2FjaGVIaXQrKzsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH07CgogICAgZmFjdG9yeS5fX2lkID0gZ2xpbW1lckZhY3RvcnkuaWQ7CiAgICBmYWN0b3J5Ll9fbWV0YSA9IGdsaW1tZXJGYWN0b3J5Lm1ldGE7CiAgICByZXR1cm4gZmFjdG9yeTsKICB9CgogIHZhciBSb290VGVtcGxhdGUgPSB0ZW1wbGF0ZSh7CiAgICAiaWQiOiAiaGpoeFVvcnUiLAogICAgImJsb2NrIjogIntcInN5bWJvbHNcIjpbXSxcInN0YXRlbWVudHNcIjpbWzEsWzI4LFwiY29tcG9uZW50XCIsW1syMywwLFtdXV0sbnVsbF0sZmFsc2VdXSxcImhhc0V2YWxcIjpmYWxzZX0iLAogICAgIm1ldGEiOiB7CiAgICAgICJtb2R1bGVOYW1lIjogInBhY2thZ2VzL0BlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIvbGliL3RlbXBsYXRlcy9yb290LmhicyIKICAgIH0KICB9KTsKICAvKioKICBAbW9kdWxlIEBlbWJlci9jb21wb25lbnQKICAqLwoKICBfZXhwb3J0cy5Sb290VGVtcGxhdGUgPSBSb290VGVtcGxhdGU7CiAgdmFyIFJFQ09NUFVURV9UQUcgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ1JFQ09NUFVURV9UQUcnKTsKCiAgZnVuY3Rpb24gaXNIZWxwZXJGYWN0b3J5KGhlbHBlcikgewogICAgcmV0dXJuIHR5cGVvZiBoZWxwZXIgPT09ICdvYmplY3QnICYmIGhlbHBlciAhPT0gbnVsbCAmJiBoZWxwZXIuY2xhc3MgJiYgaGVscGVyLmNsYXNzLmlzSGVscGVyRmFjdG9yeTsKICB9CgogIGZ1bmN0aW9uIGlzU2ltcGxlSGVscGVyKGhlbHBlcikgewogICAgcmV0dXJuIGhlbHBlci5kZXN0cm95ID09PSB1bmRlZmluZWQ7CiAgfQogIC8qKgogICAgRW1iZXIgSGVscGVycyBhcmUgZnVuY3Rpb25zIHRoYXQgY2FuIGNvbXB1dGUgdmFsdWVzLCBhbmQgYXJlIHVzZWQgaW4gdGVtcGxhdGVzLgogICAgRm9yIGV4YW1wbGUsIHRoaXMgY29kZSBjYWxscyBhIGhlbHBlciBuYW1lZCBgZm9ybWF0LWN1cnJlbmN5YDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxkaXY+e3tmb3JtYXQtY3VycmVuY3kgY2VudHMgY3VycmVuY3k9IiQifX08L2Rpdj4KICAgIGBgYAogIAogICAgQWRkaXRpb25hbGx5IGEgaGVscGVyIGNhbiBiZSBjYWxsZWQgYXMgYSBuZXN0ZWQgaGVscGVyIChzb21ldGltZXMgY2FsbGVkIGEKICAgIHN1YmV4cHJlc3Npb24pLiBJbiB0aGlzIGV4YW1wbGUsIHRoZSBjb21wdXRlZCB2YWx1ZSBvZiBhIGhlbHBlciBpcyBwYXNzZWQKICAgIHRvIGEgY29tcG9uZW50IG5hbWVkIGBzaG93LW1vbmV5YDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7c2hvdy1tb25leSBhbW91bnQ9KGZvcm1hdC1jdXJyZW5jeSBjZW50cyBjdXJyZW5jeT0iJCIpfX0KICAgIGBgYAogIAogICAgSGVscGVycyBkZWZpbmVkIHVzaW5nIGEgY2xhc3MgbXVzdCBwcm92aWRlIGEgYGNvbXB1dGVgIGZ1bmN0aW9uLiBGb3IgZXhhbXBsZToKICAKICAgIGBgYGFwcC9oZWxwZXJzL2Zvcm1hdC1jdXJyZW5jeS5qcwogICAgaW1wb3J0IEhlbHBlciBmcm9tICdAZW1iZXIvY29tcG9uZW50L2hlbHBlcic7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBIZWxwZXIuZXh0ZW5kKHsKICAgICAgY29tcHV0ZShbY2VudHNdLCB7IGN1cnJlbmN5IH0pIHsKICAgICAgICByZXR1cm4gYCR7Y3VycmVuY3l9JHtjZW50cyAqIDAuMDF9YDsKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIEVhY2ggdGltZSB0aGUgaW5wdXQgdG8gYSBoZWxwZXIgY2hhbmdlcywgdGhlIGBjb21wdXRlYCBmdW5jdGlvbiB3aWxsIGJlCiAgICBjYWxsZWQgYWdhaW4uCiAgCiAgICBBcyBpbnN0YW5jZXMsIHRoZXNlIGhlbHBlcnMgYWxzbyBoYXZlIGFjY2VzcyB0byB0aGUgY29udGFpbmVyIGFuZCB3aWxsIGFjY2VwdAogICAgaW5qZWN0ZWQgZGVwZW5kZW5jaWVzLgogIAogICAgQWRkaXRpb25hbGx5LCBjbGFzcyBoZWxwZXJzIGNhbiBjYWxsIGByZWNvbXB1dGVgIHRvIGZvcmNlIGEgbmV3IGNvbXB1dGF0aW9uLgogIAogICAgQGNsYXNzIEhlbHBlcgogICAgQHB1YmxpYwogICAgQHNpbmNlIDEuMTMuMAogICovCgoKICB2YXIgSGVscGVyID0gX3J1bnRpbWUuRnJhbWV3b3JrT2JqZWN0LmV4dGVuZCh7CiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgdGhpc1tSRUNPTVBVVEVfVEFHXSA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVRhZykoKTsKICAgIH0sCgogICAgLyoqCiAgICAgIE9uIGEgY2xhc3MtYmFzZWQgaGVscGVyLCBpdCBtYXkgYmUgdXNlZnVsIHRvIGZvcmNlIGEgcmVjb21wdXRhdGlvbiBvZiB0aGF0CiAgICAgIGhlbHBlcnMgdmFsdWUuIFRoaXMgaXMgYWtpbiB0byBgcmVyZW5kZXJgIG9uIGEgY29tcG9uZW50LgogICAgICAgICBGb3IgZXhhbXBsZSwgdGhpcyBjb21wb25lbnQgd2lsbCByZXJlbmRlciB3aGVuIHRoZSBgY3VycmVudFVzZXJgIG9uIGEKICAgICAgc2Vzc2lvbiBzZXJ2aWNlIGNoYW5nZXM6CiAgICAgICAgIGBgYGFwcC9oZWxwZXJzL2N1cnJlbnQtdXNlci1lbWFpbC5qcwogICAgICBpbXBvcnQgSGVscGVyIGZyb20gJ0BlbWJlci9jb21wb25lbnQvaGVscGVyJwogICAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJwogICAgICBpbXBvcnQgeyBvYnNlcnZlciB9IGZyb20gJ0BlbWJlci9vYmplY3QnCiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IEhlbHBlci5leHRlbmQoewogICAgICAgIHNlc3Npb246IHNlcnZpY2UoKSwKICAgICAgICBvbk5ld1VzZXI6IG9ic2VydmVyKCdzZXNzaW9uLmN1cnJlbnRVc2VyJywgZnVuY3Rpb24oKSB7CiAgICAgICAgICB0aGlzLnJlY29tcHV0ZSgpOwogICAgICAgIH0pLAogICAgICAgIGNvbXB1dGUoKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5nZXQoJ3Nlc3Npb24uY3VycmVudFVzZXIuZW1haWwnKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCByZWNvbXB1dGUKICAgICAgQHB1YmxpYwogICAgICBAc2luY2UgMS4xMy4wCiAgICAqLwogICAgcmVjb21wdXRlOiBmdW5jdGlvbiByZWNvbXB1dGUoKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICAoMCwgX3J1bmxvb3Auam9pbikoZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiAoMCwgX3JlZmVyZW5jZS5kaXJ0eSkoX3RoaXNbUkVDT01QVVRFX1RBR10pOwogICAgICB9KTsKICAgIH0KICB9KTsKCiAgX2V4cG9ydHMuSGVscGVyID0gSGVscGVyOwogIEhlbHBlci5pc0hlbHBlckZhY3RvcnkgPSB0cnVlOwogIHsKICAgICgwLCBfcnVudGltZS5zZXRGcmFtZXdvcmtDbGFzcykoSGVscGVyKTsKICB9CgogIHZhciBXcmFwcGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gV3JhcHBlcihjb21wdXRlKSB7CiAgICAgIHRoaXMuY29tcHV0ZSA9IGNvbXB1dGU7CiAgICAgIHRoaXMuaXNIZWxwZXJGYWN0b3J5ID0gdHJ1ZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gV3JhcHBlci5wcm90b3R5cGU7CgogICAgX3Byb3RvLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgLy8gbmVlZHMgbmV3IGluc3RhbmNlIG9yIHdpbGwgbGVhayBjb250YWluZXJzCiAgICAgIHJldHVybiB7CiAgICAgICAgY29tcHV0ZTogdGhpcy5jb21wdXRlCiAgICAgIH07CiAgICB9OwoKICAgIHJldHVybiBXcmFwcGVyOwogIH0oKTsKICAvKioKICAgIEluIG1hbnkgY2FzZXMsIHRoZSBjZXJlbW9ueSBvZiBhIGZ1bGwgYEhlbHBlcmAgY2xhc3MgaXMgbm90IHJlcXVpcmVkLgogICAgVGhlIGBoZWxwZXJgIG1ldGhvZCBjcmVhdGUgcHVyZS1mdW5jdGlvbiBoZWxwZXJzIHdpdGhvdXQgaW5zdGFuY2VzLiBGb3IKICAgIGV4YW1wbGU6CiAgCiAgICBgYGBhcHAvaGVscGVycy9mb3JtYXQtY3VycmVuY3kuanMKICAgIGltcG9ydCB7IGhlbHBlciB9IGZyb20gJ0BlbWJlci9jb21wb25lbnQvaGVscGVyJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IGhlbHBlcihmdW5jdGlvbihwYXJhbXMsIGhhc2gpIHsKICAgICAgbGV0IGNlbnRzID0gcGFyYW1zWzBdOwogICAgICBsZXQgY3VycmVuY3kgPSBoYXNoLmN1cnJlbmN5OwogICAgICByZXR1cm4gYCR7Y3VycmVuY3l9JHtjZW50cyAqIDAuMDF9YDsKICAgIH0pOwogICAgYGBgCiAgCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBoZWxwZXIgVGhlIGhlbHBlciBmdW5jdGlvbgogICAgQG1ldGhvZCBoZWxwZXIKICAgIEBmb3IgQGVtYmVyL2NvbXBvbmVudC9oZWxwZXIKICAgIEBwdWJsaWMKICAgIEBzaW5jZSAxLjEzLjAKICAqLwoKCiAgZnVuY3Rpb24gaGVscGVyKGhlbHBlckZuKSB7CiAgICByZXR1cm4gbmV3IFdyYXBwZXIoaGVscGVyRm4pOwogIH0KCiAgZnVuY3Rpb24gX3RvQm9vbChwcmVkaWNhdGUpIHsKICAgIGlmICgoMCwgX3J1bnRpbWUuaXNBcnJheSkocHJlZGljYXRlKSkgewogICAgICByZXR1cm4gcHJlZGljYXRlLmxlbmd0aCAhPT0gMDsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBCb29sZWFuKHByZWRpY2F0ZSk7CiAgICB9CiAgfQoKICB2YXIgVVBEQVRFID0gKDAsIF91dGlscy5zeW1ib2wpKCdVUERBVEUnKTsKICB2YXIgSU5WT0tFID0gKDAsIF91dGlscy5zeW1ib2wpKCdJTlZPS0UnKTsKICBfZXhwb3J0cy5JTlZPS0UgPSBJTlZPS0U7CiAgdmFyIEFDVElPTiA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnQUNUSU9OJyk7CgogIHZhciBFbWJlclBhdGhSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBFbWJlclBhdGhSZWZlcmVuY2UoKSB7fQoKICAgIHZhciBfcHJvdG8yID0gRW1iZXJQYXRoUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yLmdldCA9IGZ1bmN0aW9uIGdldChrZXkpIHsKICAgICAgcmV0dXJuIFByb3BlcnR5UmVmZXJlbmNlLmNyZWF0ZSh0aGlzLCBrZXkpOwogICAgfTsKCiAgICByZXR1cm4gRW1iZXJQYXRoUmVmZXJlbmNlOwogIH0oKTsKCiAgdmFyIENhY2hlZFJlZmVyZW5jZSQxID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9FbWJlclBhdGhSZWZlcmVuY2UpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDYWNoZWRSZWZlcmVuY2UkMSwgX0VtYmVyUGF0aFJlZmVyZW5jZSk7CgogICAgZnVuY3Rpb24gQ2FjaGVkUmVmZXJlbmNlJDEoKSB7CiAgICAgIHZhciBfdGhpczI7CgogICAgICBfdGhpczIgPSBfRW1iZXJQYXRoUmVmZXJlbmNlLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXMyLmxhc3RSZXZpc2lvbiA9IG51bGw7CiAgICAgIF90aGlzMi5sYXN0VmFsdWUgPSBudWxsOwogICAgICByZXR1cm4gX3RoaXMyOwogICAgfQoKICAgIHZhciBfcHJvdG8zID0gQ2FjaGVkUmVmZXJlbmNlJDEucHJvdG90eXBlOwoKICAgIF9wcm90bzMudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgdmFyIHRhZyA9IHRoaXMudGFnLAogICAgICAgICAgbGFzdFJldmlzaW9uID0gdGhpcy5sYXN0UmV2aXNpb24sCiAgICAgICAgICBsYXN0VmFsdWUgPSB0aGlzLmxhc3RWYWx1ZTsKCiAgICAgIGlmIChsYXN0UmV2aXNpb24gPT09IG51bGwgfHwgISgwLCBfcmVmZXJlbmNlLnZhbGlkYXRlKSh0YWcsIGxhc3RSZXZpc2lvbikpIHsKICAgICAgICBsYXN0VmFsdWUgPSB0aGlzLmxhc3RWYWx1ZSA9IHRoaXMuY29tcHV0ZSgpOwogICAgICAgIHRoaXMubGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKHRhZyk7CiAgICAgIH0KCiAgICAgIHJldHVybiBsYXN0VmFsdWU7CiAgICB9OwoKICAgIHJldHVybiBDYWNoZWRSZWZlcmVuY2UkMTsKICB9KEVtYmVyUGF0aFJlZmVyZW5jZSk7CgogIHZhciBSb290UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Db25zdFJlZmVyZW5jZSkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFJvb3RSZWZlcmVuY2UsIF9Db25zdFJlZmVyZW5jZSk7CgogICAgZnVuY3Rpb24gUm9vdFJlZmVyZW5jZSh2YWx1ZSQkMSkgewogICAgICB2YXIgX3RoaXMzOwoKICAgICAgX3RoaXMzID0gX0NvbnN0UmVmZXJlbmNlLmNhbGwodGhpcywgdmFsdWUkJDEpIHx8IHRoaXM7CiAgICAgIF90aGlzMy5jaGlsZHJlbiA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHJldHVybiBfdGhpczM7CiAgICB9CgogICAgUm9vdFJlZmVyZW5jZS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUodmFsdWUkJDEpIHsKICAgICAgcmV0dXJuIHZhbHVlVG9SZWYodmFsdWUkJDEpOwogICAgfTsKCiAgICB2YXIgX3Byb3RvNCA9IFJvb3RSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzQuZ2V0ID0gZnVuY3Rpb24gZ2V0KHByb3BlcnR5S2V5KSB7CiAgICAgIHZhciByZWYgPSB0aGlzLmNoaWxkcmVuW3Byb3BlcnR5S2V5XTsKCiAgICAgIGlmIChyZWYgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJlZiA9IHRoaXMuY2hpbGRyZW5bcHJvcGVydHlLZXldID0gbmV3IFJvb3RQcm9wZXJ0eVJlZmVyZW5jZSh0aGlzLmlubmVyLCBwcm9wZXJ0eUtleSk7CiAgICAgIH0KCiAgICAgIHJldHVybiByZWY7CiAgICB9OwoKICAgIHJldHVybiBSb290UmVmZXJlbmNlOwogIH0oX3JlZmVyZW5jZS5Db25zdFJlZmVyZW5jZSk7CgogIHZhciBUd29XYXlGbHVzaERldGVjdGlvblRhZzsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIFR3b1dheUZsdXNoRGV0ZWN0aW9uVGFnID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uICgpIHsKICAgICAgZnVuY3Rpb24gVHdvV2F5Rmx1c2hEZXRlY3Rpb25UYWcodGFnLCBrZXksIHJlZikgewogICAgICAgIHRoaXMudGFnID0gdGFnOwogICAgICAgIHRoaXMua2V5ID0ga2V5OwogICAgICAgIHRoaXMucmVmID0gcmVmOwogICAgICB9CgogICAgICBUd29XYXlGbHVzaERldGVjdGlvblRhZy5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUodGFnLCBrZXksIHJlZikgewogICAgICAgIHJldHVybiBuZXcgVHdvV2F5Rmx1c2hEZXRlY3Rpb25UYWcodGFnLCBrZXksIHJlZik7CiAgICAgIH07CgogICAgICB2YXIgX3Byb3RvNSA9IFR3b1dheUZsdXNoRGV0ZWN0aW9uVGFnLnByb3RvdHlwZTsKCiAgICAgIF9wcm90bzVbX3JlZmVyZW5jZS5DT01QVVRFXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gdGhpcy50YWdbX3JlZmVyZW5jZS5DT01QVVRFXSgpOwogICAgICB9OwoKICAgICAgX3Byb3RvNS5kaWRDb21wdXRlID0gZnVuY3Rpb24gZGlkQ29tcHV0ZShwYXJlbnQpIHsKICAgICAgICAoMCwgX21ldGFsLmRpZFJlbmRlcikocGFyZW50LCB0aGlzLmtleSwgdGhpcy5yZWYpOwogICAgICB9OwoKICAgICAgcmV0dXJuIFR3b1dheUZsdXNoRGV0ZWN0aW9uVGFnOwogICAgfSgpOwogIH0KCiAgdmFyIFByb3BlcnR5UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9DYWNoZWRSZWZlcmVuY2UkKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUHJvcGVydHlSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UkKTsKCiAgICBmdW5jdGlvbiBQcm9wZXJ0eVJlZmVyZW5jZSgpIHsKICAgICAgcmV0dXJuIF9DYWNoZWRSZWZlcmVuY2UkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICBQcm9wZXJ0eVJlZmVyZW5jZS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUocGFyZW50UmVmZXJlbmNlLCBwcm9wZXJ0eUtleSkgewogICAgICBpZiAoKDAsIF9yZWZlcmVuY2UuaXNDb25zdCkocGFyZW50UmVmZXJlbmNlKSkgewogICAgICAgIHJldHVybiB2YWx1ZUtleVRvUmVmKHBhcmVudFJlZmVyZW5jZS52YWx1ZSgpLCBwcm9wZXJ0eUtleSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyBOZXN0ZWRQcm9wZXJ0eVJlZmVyZW5jZShwYXJlbnRSZWZlcmVuY2UsIHByb3BlcnR5S2V5KTsKICAgICAgfQogICAgfTsKCiAgICB2YXIgX3Byb3RvNiA9IFByb3BlcnR5UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG82LmdldCA9IGZ1bmN0aW9uIGdldChrZXkpIHsKICAgICAgcmV0dXJuIG5ldyBOZXN0ZWRQcm9wZXJ0eVJlZmVyZW5jZSh0aGlzLCBrZXkpOwogICAgfTsKCiAgICByZXR1cm4gUHJvcGVydHlSZWZlcmVuY2U7CiAgfShDYWNoZWRSZWZlcmVuY2UkMSk7CgogIHZhciBSb290UHJvcGVydHlSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1Byb3BlcnR5UmVmZXJlbmNlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUm9vdFByb3BlcnR5UmVmZXJlbmNlLCBfUHJvcGVydHlSZWZlcmVuY2UpOwoKICAgIGZ1bmN0aW9uIFJvb3RQcm9wZXJ0eVJlZmVyZW5jZShwYXJlbnRWYWx1ZSwgcHJvcGVydHlLZXkpIHsKICAgICAgdmFyIF90aGlzNDsKCiAgICAgIF90aGlzNCA9IF9Qcm9wZXJ0eVJlZmVyZW5jZS5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzNC5wYXJlbnRWYWx1ZSA9IHBhcmVudFZhbHVlOwogICAgICBfdGhpczQucHJvcGVydHlLZXkgPSBwcm9wZXJ0eUtleTsKICAgICAgewogICAgICAgIF90aGlzNC5wcm9wZXJ0eVRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgfQoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIF90aGlzNC50YWcgPSBUd29XYXlGbHVzaERldGVjdGlvblRhZy5jcmVhdGUoX3RoaXM0LnByb3BlcnR5VGFnLCBwcm9wZXJ0eUtleSwgKDAsIF9lbWJlckJhYmVsLmFzc2VydFRoaXNJbml0aWFsaXplZCkoX3RoaXM0KSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgX3RoaXM0LnRhZyA9IF90aGlzNC5wcm9wZXJ0eVRhZzsKICAgICAgfQoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICYmICF0cnVlCiAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICApIHsKICAgICAgICAgICgwLCBfbWV0YWwud2F0Y2hLZXkpKHBhcmVudFZhbHVlLCBwcm9wZXJ0eUtleSk7CiAgICAgICAgfQoKICAgICAgcmV0dXJuIF90aGlzNDsKICAgIH0KCiAgICB2YXIgX3Byb3RvNyA9IFJvb3RQcm9wZXJ0eVJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNy5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgdmFyIHBhcmVudFZhbHVlID0gdGhpcy5wYXJlbnRWYWx1ZSwKICAgICAgICAgIHByb3BlcnR5S2V5ID0gdGhpcy5wcm9wZXJ0eUtleTsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICB0aGlzLnRhZy5kaWRDb21wdXRlKHBhcmVudFZhbHVlKTsKICAgICAgfQoKICAgICAgdmFyIHJldDsKICAgICAgewogICAgICAgIHZhciB0YWcgPSAoMCwgX21ldGFsLnRyYWNrKShmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXQgPSAoMCwgX21ldGFsLmdldCkocGFyZW50VmFsdWUsIHByb3BlcnR5S2V5KTsKICAgICAgICB9KTsKICAgICAgICAoMCwgX21ldGFsLmNvbnN1bWUpKHRhZyk7CiAgICAgICAgKDAsIF9yZWZlcmVuY2UudXBkYXRlKSh0aGlzLnByb3BlcnR5VGFnLCB0YWcpOwogICAgICB9CiAgICAgIHJldHVybiByZXQ7CiAgICB9OwoKICAgIF9wcm90bzdbVVBEQVRFXSA9IGZ1bmN0aW9uICh2YWx1ZSQkMSkgewogICAgICAoMCwgX21ldGFsLnNldCkodGhpcy5wYXJlbnRWYWx1ZSwgdGhpcy5wcm9wZXJ0eUtleSwgdmFsdWUkJDEpOwogICAgfTsKCiAgICByZXR1cm4gUm9vdFByb3BlcnR5UmVmZXJlbmNlOwogIH0oUHJvcGVydHlSZWZlcmVuY2UpOwoKICB2YXIgTmVzdGVkUHJvcGVydHlSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1Byb3BlcnR5UmVmZXJlbmNlMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE5lc3RlZFByb3BlcnR5UmVmZXJlbmNlLCBfUHJvcGVydHlSZWZlcmVuY2UyKTsKCiAgICBmdW5jdGlvbiBOZXN0ZWRQcm9wZXJ0eVJlZmVyZW5jZShwYXJlbnRSZWZlcmVuY2UsIHByb3BlcnR5S2V5KSB7CiAgICAgIHZhciBfdGhpczU7CgogICAgICBfdGhpczUgPSBfUHJvcGVydHlSZWZlcmVuY2UyLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXM1LnBhcmVudFJlZmVyZW5jZSA9IHBhcmVudFJlZmVyZW5jZTsKICAgICAgX3RoaXM1LnByb3BlcnR5S2V5ID0gcHJvcGVydHlLZXk7CiAgICAgIHZhciBwYXJlbnRSZWZlcmVuY2VUYWcgPSBwYXJlbnRSZWZlcmVuY2UudGFnOwogICAgICB2YXIgcHJvcGVydHlUYWcgPSBfdGhpczUucHJvcGVydHlUYWcgPSAoMCwgX3JlZmVyZW5jZS5jcmVhdGVVcGRhdGFibGVUYWcpKCk7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgdmFyIHRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFtwYXJlbnRSZWZlcmVuY2VUYWcsIHByb3BlcnR5VGFnXSk7CiAgICAgICAgX3RoaXM1LnRhZyA9IFR3b1dheUZsdXNoRGV0ZWN0aW9uVGFnLmNyZWF0ZSh0YWcsIHByb3BlcnR5S2V5LCAoMCwgX2VtYmVyQmFiZWwuYXNzZXJ0VGhpc0luaXRpYWxpemVkKShfdGhpczUpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBfdGhpczUudGFnID0gKDAsIF9yZWZlcmVuY2UuY29tYmluZSkoW3BhcmVudFJlZmVyZW5jZVRhZywgcHJvcGVydHlUYWddKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF90aGlzNTsKICAgIH0KCiAgICB2YXIgX3Byb3RvOCA9IE5lc3RlZFByb3BlcnR5UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG84LmNvbXB1dGUgPSBmdW5jdGlvbiBjb21wdXRlKCkgewogICAgICB2YXIgcGFyZW50UmVmZXJlbmNlID0gdGhpcy5wYXJlbnRSZWZlcmVuY2UsCiAgICAgICAgICBwcm9wZXJ0eVRhZyA9IHRoaXMucHJvcGVydHlUYWcsCiAgICAgICAgICBwcm9wZXJ0eUtleSA9IHRoaXMucHJvcGVydHlLZXk7CgogICAgICB2YXIgX3BhcmVudFZhbHVlID0gcGFyZW50UmVmZXJlbmNlLnZhbHVlKCk7CgogICAgICB2YXIgcGFyZW50VmFsdWVUeXBlID0gdHlwZW9mIF9wYXJlbnRWYWx1ZTsKCiAgICAgIGlmIChwYXJlbnRWYWx1ZVR5cGUgPT09ICdzdHJpbmcnICYmIHByb3BlcnR5S2V5ID09PSAnbGVuZ3RoJykgewogICAgICAgIHJldHVybiBfcGFyZW50VmFsdWUubGVuZ3RoOwogICAgICB9CgogICAgICBpZiAocGFyZW50VmFsdWVUeXBlID09PSAnb2JqZWN0JyAmJiBfcGFyZW50VmFsdWUgIT09IG51bGwgfHwgcGFyZW50VmFsdWVUeXBlID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgdmFyIHBhcmVudFZhbHVlID0gX3BhcmVudFZhbHVlOwoKICAgICAgICBpZiAoZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICYmICF0cnVlCiAgICAgICAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgICAgICAgKSB7CiAgICAgICAgICAgICgwLCBfbWV0YWwud2F0Y2hLZXkpKHBhcmVudFZhbHVlLCBwcm9wZXJ0eUtleSk7CiAgICAgICAgICB9CgogICAgICAgIGlmIChmYWxzZQogICAgICAgIC8qIERFQlVHICovCiAgICAgICAgKSB7CiAgICAgICAgICB0aGlzLnRhZy5kaWRDb21wdXRlKHBhcmVudFZhbHVlKTsKICAgICAgICB9CgogICAgICAgIHZhciByZXQ7CiAgICAgICAgewogICAgICAgICAgdmFyIHRhZyA9ICgwLCBfbWV0YWwudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgcmV0ID0gKDAsIF9tZXRhbC5nZXQpKHBhcmVudFZhbHVlLCBwcm9wZXJ0eUtleSk7CiAgICAgICAgICB9KTsKICAgICAgICAgICgwLCBfbWV0YWwuY29uc3VtZSkodGFnKTsKICAgICAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkocHJvcGVydHlUYWcsIHRhZyk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG84W1VQREFURV0gPSBmdW5jdGlvbiAodmFsdWUkJDEpIHsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMucGFyZW50UmVmZXJlbmNlLnZhbHVlKCkKICAgICAgLyogbGV0IHRoZSBvdGhlciBzaWRlIGhhbmRsZSB0aGUgZXJyb3IgKi8KICAgICAgLCB0aGlzLnByb3BlcnR5S2V5LCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIHJldHVybiBOZXN0ZWRQcm9wZXJ0eVJlZmVyZW5jZTsKICB9KFByb3BlcnR5UmVmZXJlbmNlKTsKCiAgdmFyIFVwZGF0YWJsZVJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW1iZXJQYXRoUmVmZXJlbmNlMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFVwZGF0YWJsZVJlZmVyZW5jZSwgX0VtYmVyUGF0aFJlZmVyZW5jZTIpOwoKICAgIGZ1bmN0aW9uIFVwZGF0YWJsZVJlZmVyZW5jZSh2YWx1ZSQkMSkgewogICAgICB2YXIgX3RoaXM2OwoKICAgICAgX3RoaXM2ID0gX0VtYmVyUGF0aFJlZmVyZW5jZTIuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczYudGFnID0gKDAsIF9yZWZlcmVuY2UuY3JlYXRlVGFnKSgpOwogICAgICBfdGhpczYuX3ZhbHVlID0gdmFsdWUkJDE7CiAgICAgIHJldHVybiBfdGhpczY7CiAgICB9CgogICAgdmFyIF9wcm90bzkgPSBVcGRhdGFibGVSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzkudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX3ZhbHVlOwogICAgfTsKCiAgICBfcHJvdG85LnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZSh2YWx1ZSQkMSkgewogICAgICB2YXIgX3ZhbHVlID0gdGhpcy5fdmFsdWU7CgogICAgICBpZiAodmFsdWUkJDEgIT09IF92YWx1ZSkgewogICAgICAgICgwLCBfcmVmZXJlbmNlLmRpcnR5KSh0aGlzLnRhZyk7CiAgICAgICAgdGhpcy5fdmFsdWUgPSB2YWx1ZSQkMTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gVXBkYXRhYmxlUmVmZXJlbmNlOwogIH0oRW1iZXJQYXRoUmVmZXJlbmNlKTsKCiAgX2V4cG9ydHMuVXBkYXRhYmxlUmVmZXJlbmNlID0gVXBkYXRhYmxlUmVmZXJlbmNlOwoKICB2YXIgQ29uZGl0aW9uYWxSZWZlcmVuY2UkMSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ29uZGl0aW9uYWxSZWZlcmVuY2UpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDb25kaXRpb25hbFJlZmVyZW5jZSQxLCBfQ29uZGl0aW9uYWxSZWZlcmVuY2UpOwoKICAgIENvbmRpdGlvbmFsUmVmZXJlbmNlJDEuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHJlZmVyZW5jZSkgewogICAgICBpZiAoKDAsIF9yZWZlcmVuY2UuaXNDb25zdCkocmVmZXJlbmNlKSkgewogICAgICAgIHZhciB2YWx1ZSQkMSA9IHJlZmVyZW5jZS52YWx1ZSgpOwoKICAgICAgICBpZiAoISgwLCBfdXRpbHMuaXNQcm94eSkodmFsdWUkJDEpKSB7CiAgICAgICAgICByZXR1cm4gX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUoX3RvQm9vbCh2YWx1ZSQkMSkpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIG5ldyBDb25kaXRpb25hbFJlZmVyZW5jZSQxKHJlZmVyZW5jZSk7CiAgICB9OwoKICAgIGZ1bmN0aW9uIENvbmRpdGlvbmFsUmVmZXJlbmNlJDEocmVmZXJlbmNlKSB7CiAgICAgIHZhciBfdGhpczc7CgogICAgICBfdGhpczcgPSBfQ29uZGl0aW9uYWxSZWZlcmVuY2UuY2FsbCh0aGlzLCByZWZlcmVuY2UpIHx8IHRoaXM7CiAgICAgIF90aGlzNy5vYmplY3RUYWcgPSAoMCwgX3JlZmVyZW5jZS5jcmVhdGVVcGRhdGFibGVUYWcpKCk7CiAgICAgIF90aGlzNy50YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShbcmVmZXJlbmNlLnRhZywgX3RoaXM3Lm9iamVjdFRhZ10pOwogICAgICByZXR1cm4gX3RoaXM3OwogICAgfQoKICAgIHZhciBfcHJvdG8xMCA9IENvbmRpdGlvbmFsUmVmZXJlbmNlJDEucHJvdG90eXBlOwoKICAgIF9wcm90bzEwLnRvQm9vbCA9IGZ1bmN0aW9uIHRvQm9vbChwcmVkaWNhdGUpIHsKICAgICAgaWYgKCgwLCBfdXRpbHMuaXNQcm94eSkocHJlZGljYXRlKSkgewogICAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkodGhpcy5vYmplY3RUYWcsICgwLCBfbWV0YWwudGFnRm9yUHJvcGVydHkpKHByZWRpY2F0ZSwgJ2lzVHJ1dGh5JykpOwogICAgICAgIHJldHVybiBCb29sZWFuKCgwLCBfbWV0YWwuZ2V0KShwcmVkaWNhdGUsICdpc1RydXRoeScpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHRoaXMub2JqZWN0VGFnLCAoMCwgX21ldGFsLnRhZ0ZvcikocHJlZGljYXRlKSk7CiAgICAgICAgcmV0dXJuIF90b0Jvb2wocHJlZGljYXRlKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gQ29uZGl0aW9uYWxSZWZlcmVuY2UkMTsKICB9KF9ydW50aW1lMi5Db25kaXRpb25hbFJlZmVyZW5jZSk7CgogIHZhciBTaW1wbGVIZWxwZXJSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NhY2hlZFJlZmVyZW5jZSQyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoU2ltcGxlSGVscGVyUmVmZXJlbmNlLCBfQ2FjaGVkUmVmZXJlbmNlJDIpOwoKICAgIGZ1bmN0aW9uIFNpbXBsZUhlbHBlclJlZmVyZW5jZShoZWxwZXIkJDEsIGFyZ3MpIHsKICAgICAgdmFyIF90aGlzODsKCiAgICAgIF90aGlzOCA9IF9DYWNoZWRSZWZlcmVuY2UkMi5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzOC5oZWxwZXIgPSBoZWxwZXIkJDE7CiAgICAgIF90aGlzOC5hcmdzID0gYXJnczsKICAgICAgdmFyIGNvbXB1dGVUYWcgPSBfdGhpczguY29tcHV0ZVRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgX3RoaXM4LnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFthcmdzLnRhZywgY29tcHV0ZVRhZ10pOwogICAgICByZXR1cm4gX3RoaXM4OwogICAgfQoKICAgIFNpbXBsZUhlbHBlclJlZmVyZW5jZS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoaGVscGVyJCQxLCBhcmdzKSB7CiAgICAgIGlmICgoMCwgX3JlZmVyZW5jZS5pc0NvbnN0KShhcmdzKSkgewogICAgICAgIHZhciBwb3NpdGlvbmFsID0gYXJncy5wb3NpdGlvbmFsLAogICAgICAgICAgICBuYW1lZCA9IGFyZ3MubmFtZWQ7CiAgICAgICAgdmFyIHBvc2l0aW9uYWxWYWx1ZSA9IHBvc2l0aW9uYWwudmFsdWUoKTsKICAgICAgICB2YXIgbmFtZWRWYWx1ZSA9IG5hbWVkLnZhbHVlKCk7CgogICAgICAgIGlmIChmYWxzZQogICAgICAgIC8qIERFQlVHICovCiAgICAgICAgKSB7CiAgICAgICAgICAoMCwgX2RlYnVnLmRlYnVnRnJlZXplKShwb3NpdGlvbmFsVmFsdWUpOwogICAgICAgICAgKDAsIF9kZWJ1Zy5kZWJ1Z0ZyZWV6ZSkobmFtZWRWYWx1ZSk7CiAgICAgICAgfQoKICAgICAgICB2YXIgcmVzdWx0ID0gaGVscGVyJCQxKHBvc2l0aW9uYWxWYWx1ZSwgbmFtZWRWYWx1ZSk7CiAgICAgICAgcmV0dXJuIHZhbHVlVG9SZWYocmVzdWx0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbmV3IFNpbXBsZUhlbHBlclJlZmVyZW5jZShoZWxwZXIkJDEsIGFyZ3MpOwogICAgICB9CiAgICB9OwoKICAgIHZhciBfcHJvdG8xMSA9IFNpbXBsZUhlbHBlclJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMTEuY29tcHV0ZSA9IGZ1bmN0aW9uIGNvbXB1dGUoKSB7CiAgICAgIHZhciBoZWxwZXIkJDEgPSB0aGlzLmhlbHBlciwKICAgICAgICAgIGNvbXB1dGVUYWcgPSB0aGlzLmNvbXB1dGVUYWcsCiAgICAgICAgICBfdGhpcyRhcmdzID0gdGhpcy5hcmdzLAogICAgICAgICAgcG9zaXRpb25hbCA9IF90aGlzJGFyZ3MucG9zaXRpb25hbCwKICAgICAgICAgIG5hbWVkID0gX3RoaXMkYXJncy5uYW1lZDsKICAgICAgdmFyIHBvc2l0aW9uYWxWYWx1ZSA9IHBvc2l0aW9uYWwudmFsdWUoKTsKICAgICAgdmFyIG5hbWVkVmFsdWUgPSBuYW1lZC52YWx1ZSgpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgICgwLCBfZGVidWcuZGVidWdGcmVlemUpKHBvc2l0aW9uYWxWYWx1ZSk7CiAgICAgICAgKDAsIF9kZWJ1Zy5kZWJ1Z0ZyZWV6ZSkobmFtZWRWYWx1ZSk7CiAgICAgIH0KCiAgICAgIHZhciBjb21wdXRlZFZhbHVlOwogICAgICB2YXIgY29tYmluZWRUcmFja2luZ1RhZyA9ICgwLCBfbWV0YWwudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gY29tcHV0ZWRWYWx1ZSA9IGhlbHBlciQkMShwb3NpdGlvbmFsVmFsdWUsIG5hbWVkVmFsdWUpOwogICAgICB9KTsKICAgICAgKDAsIF9yZWZlcmVuY2UudXBkYXRlKShjb21wdXRlVGFnLCBjb21iaW5lZFRyYWNraW5nVGFnKTsKICAgICAgcmV0dXJuIGNvbXB1dGVkVmFsdWU7CiAgICB9OwoKICAgIHJldHVybiBTaW1wbGVIZWxwZXJSZWZlcmVuY2U7CiAgfShDYWNoZWRSZWZlcmVuY2UkMSk7CgogIHZhciBDbGFzc0Jhc2VkSGVscGVyUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9DYWNoZWRSZWZlcmVuY2UkMykgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKENsYXNzQmFzZWRIZWxwZXJSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UkMyk7CgogICAgZnVuY3Rpb24gQ2xhc3NCYXNlZEhlbHBlclJlZmVyZW5jZShpbnN0YW5jZSwgYXJncykgewogICAgICB2YXIgX3RoaXM5OwoKICAgICAgX3RoaXM5ID0gX0NhY2hlZFJlZmVyZW5jZSQzLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXM5Lmluc3RhbmNlID0gaW5zdGFuY2U7CiAgICAgIF90aGlzOS5hcmdzID0gYXJnczsKICAgICAgdmFyIGNvbXB1dGVUYWcgPSBfdGhpczkuY29tcHV0ZVRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgX3RoaXM5LnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFtpbnN0YW5jZVtSRUNPTVBVVEVfVEFHXSwgYXJncy50YWcsIGNvbXB1dGVUYWddKTsKICAgICAgcmV0dXJuIF90aGlzOTsKICAgIH0KCiAgICBDbGFzc0Jhc2VkSGVscGVyUmVmZXJlbmNlLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShpbnN0YW5jZSwgYXJncykgewogICAgICByZXR1cm4gbmV3IENsYXNzQmFzZWRIZWxwZXJSZWZlcmVuY2UoaW5zdGFuY2UsIGFyZ3MpOwogICAgfTsKCiAgICB2YXIgX3Byb3RvMTIgPSBDbGFzc0Jhc2VkSGVscGVyUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xMi5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgdmFyIGluc3RhbmNlID0gdGhpcy5pbnN0YW5jZSwKICAgICAgICAgIGNvbXB1dGVUYWcgPSB0aGlzLmNvbXB1dGVUYWcsCiAgICAgICAgICBfdGhpcyRhcmdzMiA9IHRoaXMuYXJncywKICAgICAgICAgIHBvc2l0aW9uYWwgPSBfdGhpcyRhcmdzMi5wb3NpdGlvbmFsLAogICAgICAgICAgbmFtZWQgPSBfdGhpcyRhcmdzMi5uYW1lZDsKICAgICAgdmFyIHBvc2l0aW9uYWxWYWx1ZSA9IHBvc2l0aW9uYWwudmFsdWUoKTsKICAgICAgdmFyIG5hbWVkVmFsdWUgPSBuYW1lZC52YWx1ZSgpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgICgwLCBfZGVidWcuZGVidWdGcmVlemUpKHBvc2l0aW9uYWxWYWx1ZSk7CiAgICAgICAgKDAsIF9kZWJ1Zy5kZWJ1Z0ZyZWV6ZSkobmFtZWRWYWx1ZSk7CiAgICAgIH0KCiAgICAgIHZhciBjb21wdXRlZFZhbHVlOwogICAgICB2YXIgY29tYmluZWRUcmFja2luZ1RhZyA9ICgwLCBfbWV0YWwudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gY29tcHV0ZWRWYWx1ZSA9IGluc3RhbmNlLmNvbXB1dGUocG9zaXRpb25hbFZhbHVlLCBuYW1lZFZhbHVlKTsKICAgICAgfSk7CiAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkoY29tcHV0ZVRhZywgY29tYmluZWRUcmFja2luZ1RhZyk7CiAgICAgIHJldHVybiBjb21wdXRlZFZhbHVlOwogICAgfTsKCiAgICByZXR1cm4gQ2xhc3NCYXNlZEhlbHBlclJlZmVyZW5jZTsKICB9KENhY2hlZFJlZmVyZW5jZSQxKTsKCiAgdmFyIEludGVybmFsSGVscGVyUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9DYWNoZWRSZWZlcmVuY2UkNCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEludGVybmFsSGVscGVyUmVmZXJlbmNlLCBfQ2FjaGVkUmVmZXJlbmNlJDQpOwoKICAgIGZ1bmN0aW9uIEludGVybmFsSGVscGVyUmVmZXJlbmNlKGhlbHBlciQkMSwgYXJncykgewogICAgICB2YXIgX3RoaXMxMDsKCiAgICAgIF90aGlzMTAgPSBfQ2FjaGVkUmVmZXJlbmNlJDQuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczEwLmhlbHBlciA9IGhlbHBlciQkMTsKICAgICAgX3RoaXMxMC5hcmdzID0gYXJnczsKICAgICAgX3RoaXMxMC50YWcgPSBhcmdzLnRhZzsKICAgICAgcmV0dXJuIF90aGlzMTA7CiAgICB9CgogICAgdmFyIF9wcm90bzEzID0gSW50ZXJuYWxIZWxwZXJSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzEzLmNvbXB1dGUgPSBmdW5jdGlvbiBjb21wdXRlKCkgewogICAgICB2YXIgaGVscGVyJCQxID0gdGhpcy5oZWxwZXIsCiAgICAgICAgICBhcmdzID0gdGhpcy5hcmdzOwogICAgICByZXR1cm4gaGVscGVyJCQxKGFyZ3MpOwogICAgfTsKCiAgICByZXR1cm4gSW50ZXJuYWxIZWxwZXJSZWZlcmVuY2U7CiAgfShDYWNoZWRSZWZlcmVuY2UkMSk7CgogIHZhciBVbmJvdW5kUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Db25zdFJlZmVyZW5jZTIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShVbmJvdW5kUmVmZXJlbmNlLCBfQ29uc3RSZWZlcmVuY2UyKTsKCiAgICBmdW5jdGlvbiBVbmJvdW5kUmVmZXJlbmNlKCkgewogICAgICByZXR1cm4gX0NvbnN0UmVmZXJlbmNlMi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgVW5ib3VuZFJlZmVyZW5jZS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUodmFsdWUkJDEpIHsKICAgICAgcmV0dXJuIHZhbHVlVG9SZWYodmFsdWUkJDEsIGZhbHNlKTsKICAgIH07CgogICAgdmFyIF9wcm90bzE0ID0gVW5ib3VuZFJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMTQuZ2V0ID0gZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICByZXR1cm4gdmFsdWVUb1JlZih0aGlzLmlubmVyW2tleV0sIGZhbHNlKTsKICAgIH07CgogICAgcmV0dXJuIFVuYm91bmRSZWZlcmVuY2U7CiAgfShfcmVmZXJlbmNlLkNvbnN0UmVmZXJlbmNlKTsKCiAgdmFyIFJlYWRvbmx5UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9DYWNoZWRSZWZlcmVuY2UkNSkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFJlYWRvbmx5UmVmZXJlbmNlLCBfQ2FjaGVkUmVmZXJlbmNlJDUpOwoKICAgIGZ1bmN0aW9uIFJlYWRvbmx5UmVmZXJlbmNlKGlubmVyKSB7CiAgICAgIHZhciBfdGhpczExOwoKICAgICAgX3RoaXMxMSA9IF9DYWNoZWRSZWZlcmVuY2UkNS5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMTEuaW5uZXIgPSBpbm5lcjsKICAgICAgX3RoaXMxMS50YWcgPSBpbm5lci50YWc7CiAgICAgIHJldHVybiBfdGhpczExOwogICAgfQoKICAgIHZhciBfcHJvdG8xNSA9IFJlYWRvbmx5UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xNS5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuaW5uZXIudmFsdWUoKTsKICAgIH07CgogICAgX3Byb3RvMTUuZ2V0ID0gZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICByZXR1cm4gdGhpcy5pbm5lci5nZXQoa2V5KTsKICAgIH07CgogICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShSZWFkb25seVJlZmVyZW5jZSwgW3sKICAgICAga2V5OiBJTlZPS0UsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmlubmVyW0lOVk9LRV07CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBSZWFkb25seVJlZmVyZW5jZTsKICB9KENhY2hlZFJlZmVyZW5jZSQxKTsKCiAgZnVuY3Rpb24gcmVmZXJlbmNlRnJvbVBhcnRzKHJvb3QsIHBhcnRzKSB7CiAgICB2YXIgcmVmZXJlbmNlID0gcm9vdDsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHJlZmVyZW5jZSA9IHJlZmVyZW5jZS5nZXQocGFydHNbaV0pOwogICAgfQoKICAgIHJldHVybiByZWZlcmVuY2U7CiAgfQoKICBmdW5jdGlvbiBpc09iamVjdCh2YWx1ZSQkMSkgewogICAgcmV0dXJuIHZhbHVlJCQxICE9PSBudWxsICYmIHR5cGVvZiB2YWx1ZSQkMSA9PT0gJ29iamVjdCc7CiAgfQoKICBmdW5jdGlvbiBpc0Z1bmN0aW9uKHZhbHVlJCQxKSB7CiAgICByZXR1cm4gdHlwZW9mIHZhbHVlJCQxID09PSAnZnVuY3Rpb24nOwogIH0KCiAgZnVuY3Rpb24gaXNQcmltaXRpdmUodmFsdWUkJDEpIHsKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZSQkMTsKICAgICAgcmV0dXJuIHZhbHVlJCQxID09PSB1bmRlZmluZWQgfHwgdmFsdWUkJDEgPT09IG51bGwgfHwgdHlwZSA9PT0gJ2Jvb2xlYW4nIHx8IHR5cGUgPT09ICdudW1iZXInIHx8IHR5cGUgPT09ICdzdHJpbmcnOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgfQoKICBmdW5jdGlvbiB2YWx1ZVRvUmVmKHZhbHVlJCQxLCBib3VuZCkgewogICAgaWYgKGJvdW5kID09PSB2b2lkIDApIHsKICAgICAgYm91bmQgPSB0cnVlOwogICAgfQoKICAgIGlmIChpc09iamVjdCh2YWx1ZSQkMSkpIHsKICAgICAgLy8gcm9vdCBvZiBpbnRlcm9wIHdpdGggZW1iZXIgb2JqZWN0cwogICAgICByZXR1cm4gYm91bmQgPyBuZXcgUm9vdFJlZmVyZW5jZSh2YWx1ZSQkMSkgOiBuZXcgVW5ib3VuZFJlZmVyZW5jZSh2YWx1ZSQkMSk7CiAgICB9IGVsc2UgaWYgKGlzRnVuY3Rpb24odmFsdWUkJDEpKSB7CiAgICAgIC8vIGVtYmVyIGRvZXNuJ3QgZG8gb2JzZXJ2aW5nIHdpdGggZnVuY3Rpb25zCiAgICAgIHJldHVybiBuZXcgVW5ib3VuZFJlZmVyZW5jZSh2YWx1ZSQkMSk7CiAgICB9IGVsc2UgaWYgKGlzUHJpbWl0aXZlKHZhbHVlJCQxKSkgewogICAgICByZXR1cm4gX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUodmFsdWUkJDEpOwogICAgfSBlbHNlIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZSQkMTsKICAgICAgdmFyIG91dHB1dDsKCiAgICAgIHRyeSB7CiAgICAgICAgb3V0cHV0ID0gU3RyaW5nKHZhbHVlJCQxKTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIG91dHB1dCA9IG51bGw7CiAgICAgIH0KCiAgICAgIGlmIChvdXRwdXQpIHsKICAgICAgICB0aHJvdyAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJbQlVHXSBVbmV4cGVjdGVkICIgKyB0eXBlICsgIiAoIiArIG91dHB1dCArICIpIik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiW0JVR10gVW5leHBlY3RlZCAiICsgdHlwZSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHZhbHVlS2V5VG9SZWYodmFsdWUkJDEsIGtleSkgewogICAgaWYgKGlzT2JqZWN0KHZhbHVlJCQxKSkgewogICAgICAvLyByb290IG9mIGludGVyb3Agd2l0aCBlbWJlciBvYmplY3RzCiAgICAgIHJldHVybiBuZXcgUm9vdFByb3BlcnR5UmVmZXJlbmNlKHZhbHVlJCQxLCBrZXkpOwogICAgfSBlbHNlIGlmIChpc0Z1bmN0aW9uKHZhbHVlJCQxKSkgewogICAgICAvLyBlbWJlciBkb2Vzbid0IGRvIG9ic2VydmluZyB3aXRoIGZ1bmN0aW9ucwogICAgICByZXR1cm4gbmV3IFVuYm91bmRSZWZlcmVuY2UodmFsdWUkJDFba2V5XSk7CiAgICB9IGVsc2UgaWYgKGlzUHJpbWl0aXZlKHZhbHVlJCQxKSkgewogICAgICByZXR1cm4gX3J1bnRpbWUyLlVOREVGSU5FRF9SRUZFUkVOQ0U7CiAgICB9IGVsc2UgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgKSB7CiAgICAgIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlJCQxOwogICAgICB2YXIgb3V0cHV0OwoKICAgICAgdHJ5IHsKICAgICAgICBvdXRwdXQgPSBTdHJpbmcodmFsdWUkJDEpOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgb3V0cHV0ID0gbnVsbDsKICAgICAgfQoKICAgICAgaWYgKG91dHB1dCkgewogICAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIltCVUddIFVuZXhwZWN0ZWQgIiArIHR5cGUgKyAiICgiICsgb3V0cHV0ICsgIikiKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aHJvdyAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJbQlVHXSBVbmV4cGVjdGVkICIgKyB0eXBlKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdGhyb3cgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgpOwogICAgfQogIH0KCiAgdmFyIERJUlRZX1RBRyA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnRElSVFlfVEFHJyk7CiAgdmFyIEFSR1MgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ0FSR1MnKTsKICB2YXIgUk9PVF9SRUYgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ1JPT1RfUkVGJyk7CiAgX2V4cG9ydHMuUk9PVF9SRUYgPSBST09UX1JFRjsKICB2YXIgSVNfRElTUEFUQ0hJTkdfQVRUUlMgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ0lTX0RJU1BBVENISU5HX0FUVFJTJyk7CiAgdmFyIEhBU19CTE9DSyA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnSEFTX0JMT0NLJyk7CiAgdmFyIEJPVU5EUyA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnQk9VTkRTJyk7CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvY29tcG9uZW50CiAgKi8KCiAgLyoqCiAgICBBIGNvbXBvbmVudCBpcyBhbiBpc29sYXRlZCBwaWVjZSBvZiBVSSwgcmVwcmVzZW50ZWQgYnkgYSB0ZW1wbGF0ZSBhbmQgYW4KICAgIG9wdGlvbmFsIGNsYXNzLiBXaGVuIGEgY29tcG9uZW50IGhhcyBhIGNsYXNzLCBpdHMgdGVtcGxhdGUncyBgdGhpc2AgdmFsdWUKICAgIGlzIGFuIGluc3RhbmNlIG9mIHRoZSBjb21wb25lbnQgY2xhc3MuCiAgCiAgICAjIyBUZW1wbGF0ZS1vbmx5IENvbXBvbmVudHMKICAKICAgIFRoZSBzaW1wbGVzdCB3YXkgdG8gY3JlYXRlIGEgY29tcG9uZW50IGlzIHRvIGNyZWF0ZSBhIHRlbXBsYXRlIGZpbGUgaW4KICAgIGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHNgLiBGb3IgZXhhbXBsZSwgaWYgeW91IG5hbWUgYSB0ZW1wbGF0ZQogICAgYGFwcC90ZW1wbGF0ZXMvY29tcG9uZW50cy9wZXJzb24tcHJvZmlsZS5oYnNgOgogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmhicwogICAgPGgxPnt7QHBlcnNvbi5uYW1lfX08L2gxPgogICAgPGltZyBzcmM9e3tAcGVyc29uLmF2YXRhcn19PgogICAgPHAgY2xhc3M9J3NpZ25hdHVyZSc+e3tAcGVyc29uLnNpZ25hdHVyZX19PC9wPgogICAgYGBgCiAgCiAgICBZb3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBgPFBlcnNvblByb2ZpbGUgLz5gIHRvIGludm9rZSB0aGlzIGNvbXBvbmVudCBlbHNld2hlcmUKICAgIGluIHlvdXIgYXBwbGljYXRpb246CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2FwcGxpY2F0aW9uLmhicwogICAgPFBlcnNvblByb2ZpbGUgQHBlcnNvbj17e3RoaXMuY3VycmVudFVzZXJ9fSAvPgogICAgYGBgCiAgCiAgICBOb3RlIHRoYXQgY29tcG9uZW50IG5hbWVzIGFyZSBjYXBpdGFsaXplZCBoZXJlIGluIG9yZGVyIHRvIGRpc3Rpbmd1aXNoIHRoZW0KICAgIGZyb20gcmVndWxhciBIVE1MIGVsZW1lbnRzLCBidXQgdGhleSBhcmUgZGFzaGVyaXplZCBpbiB0aGUgZmlsZSBzeXN0ZW0uCiAgCiAgICBXaGlsZSB0aGUgYW5nbGUgYnJhY2tldCBpbnZvY2F0aW9uIGZvcm0gaXMgZ2VuZXJhbGx5IHByZWZlcnJlZCwgaXQgaXMgYWxzbwogICAgcG9zc2libGUgdG8gaW52b2tlIHRoZSBzYW1lIGNvbXBvbmVudCB3aXRoIHRoZSBge3twZXJzb24tcHJvZmlsZX19YCBzeW50YXg6CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2FwcGxpY2F0aW9uLmhicwogICAge3twZXJzb24tcHJvZmlsZSBwZXJzb249dGhpcy5jdXJyZW50VXNlcn19CiAgICBgYGAKICAKICAgIE5vdGUgdGhhdCB3aXRoIHRoaXMgc3ludGF4LCB5b3UgdXNlIGRhc2hlcyBpbiB0aGUgY29tcG9uZW50IG5hbWUgYW5kCiAgICBhcmd1bWVudHMgYXJlIHBhc3NlZCB3aXRob3V0IHRoZSBgQGAgc2lnbi4KICAKICAgIEluIGJvdGggY2FzZXMsIEVtYmVyIHdpbGwgcmVuZGVyIHRoZSBjb250ZW50IG9mIHRoZSBjb21wb25lbnQgdGVtcGxhdGUgd2UKICAgIGNyZWF0ZWQgYWJvdmUuIFRoZSBlbmQgcmVzdWx0IHdpbGwgYmUgc29tZXRoaW5nIGxpa2UgdGhpczoKICAKICAgIGBgYGh0bWwKICAgIDxoMT5Ub21zdGVyPC9oMT4KICAgIDxpbWcgc3JjPSJodHRwczovL2VtYmVyanMuY29tL3RvbXN0ZXIuanBnIj4KICAgIDxwIGNsYXNzPSdzaWduYXR1cmUnPk91dCBvZiBvZmZpY2UgdGhpcyB3ZWVrPC9wPgogICAgYGBgCiAgCiAgICAjIyBGaWxlIFN5c3RlbSBOZXN0aW5nCiAgCiAgICBDb21wb25lbnRzIGNhbiBiZSBuZXN0ZWQgaW5zaWRlIHN1Yi1mb2xkZXJzIGZvciBsb2dpY2FsIGdyb3VwcGluZy4gRm9yCiAgICBleGFtcGxlLCBpZiB3ZSBwbGFjZWQgb3VyIHRlbXBsYXRlIGluCiAgICBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL3BlcnNvbi9zaG9ydC1wcm9maWxlLmhic2AsIHdlIGNhbiBpbnZva2UgaXQgYXMKICAgIGA8UGVyc29uOjpTaG9ydFByb2ZpbGUgLz5gOgogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9hcHBsaWNhdGlvbi5oYnMKICAgIDxQZXJzb246OlNob3J0UHJvZmlsZSBAcGVyc29uPXt7dGhpcy5jdXJyZW50VXNlcn19IC8+CiAgICBgYGAKICAKICAgIE9yIGVxdWl2YWxlbnRseSwgYHt7cGVyc29uL3Nob3J0LXByb2ZpbGV9fWA6CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2FwcGxpY2F0aW9uLmhicwogICAge3twZXJzb24vc2hvcnQtcHJvZmlsZSBwZXJzb249dGhpcy5jdXJyZW50VXNlcn19CiAgICBgYGAKICAKICAgICMjIFlpZWxkaW5nIENvbnRlbnRzCiAgCiAgICBZb3UgY2FuIHVzZSBgeWllbGRgIGluc2lkZSBhIHRlbXBsYXRlIHRvIGluY2x1ZGUgdGhlICoqY29udGVudHMqKiBvZiBhbnkgYmxvY2sKICAgIGF0dGFjaGVkIHRvIHRoZSBjb21wb25lbnQuIFRoZSBibG9jayB3aWxsIGJlIGV4ZWN1dGVkIGluIGl0cyBvcmlnaW5hbCBjb250ZXh0OgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPFBlcnNvblByb2ZpbGUgQHBlcnNvbj17e3RoaXMuY3VycmVudFVzZXJ9fT4KICAgICAgPHA+QWRtaW4gbW9kZTwvcD4KICAgICAge3shIEV4ZWN1dGVkIGluIHRoZSBjdXJyZW50IGNvbnRleHQuIH19CiAgICA8L1BlcnNvblByb2ZpbGU+CiAgICBgYGAKICAKICAgIG9yCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7eyNwZXJzb24tcHJvZmlsZSBwZXJzb249dGhpcy5jdXJyZW50VXNlcn19CiAgICAgIDxwPkFkbWluIG1vZGU8L3A+CiAgICAgIHt7ISBFeGVjdXRlZCBpbiB0aGUgY3VycmVudCBjb250ZXh0LiB9fQogICAge3svcGVyc29uLXByb2ZpbGV9fQogICAgYGBgCiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvcGVyc29uLXByb2ZpbGUuaGJzCiAgICA8aDE+e3tAcGVyc29uLm5hbWV9fTwvaDE+CiAgICB7e3lpZWxkfX0KICAgIGBgYAogIAogICAgIyMgQ3VzdG9taXppbmcgQ29tcG9uZW50cyBXaXRoIEphdmFTY3JpcHQKICAKICAgIElmIHlvdSB3YW50IHRvIGN1c3RvbWl6ZSB0aGUgY29tcG9uZW50IGluIG9yZGVyIHRvIGhhbmRsZSBldmVudHMsIHRyYW5zZm9ybQogICAgYXJndW1lbnRzIG9yIG1haW50YWluIGludGVybmFsIHN0YXRlLCB5b3UgaW1wbGVtZW50IGEgc3ViY2xhc3Mgb2YgYENvbXBvbmVudGAuCiAgCiAgICBPbmUgZXhhbXBsZSBpcyB0byBhZGQgY29tcHV0ZWQgcHJvcGVydGllcyB0byB5b3VyIGNvbXBvbmVudDoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGRpc3BsYXlOYW1lOiBjb21wdXRlZCgncGVyc29uLnRpdGxlJywgJ3BlcnNvbi5maXJzdE5hbWUnLCAncGVyc29uLmxhc3ROYW1lJywgZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IHsgdGl0bGUsIGZpcnN0TmFtZSwgbGFzdE5hbWUgfSA9IHRoaXM7CiAgCiAgICAgICAgaWYgKHRpdGxlKSB7CiAgICAgICAgICByZXR1cm4gYCR7dGl0bGV9ICR7bGFzdE5hbWV9YDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIGAke2ZpcnN0TmFtZX0gJHtsYXN0TmFtZX1gOwogICAgICAgIH0KICAgICAgfSkKICAgIH0pOwogICAgYGBgCiAgCiAgICBBbmQgdGhlbiB1c2UgaXQgaW4gdGhlIGNvbXBvbmVudCdzIHRlbXBsYXRlOgogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmhicwogICAgPGgxPnt7dGhpcy5kaXNwbGF5TmFtZX19PC9oMT4KICAgIHt7eWllbGR9fQogICAgYGBgCiAgCiAgICAjIyBDdXN0b21pemluZyBhIENvbXBvbmVudCdzIEhUTUwgRWxlbWVudCBpbiBKYXZhU2NyaXB0CiAgCiAgICAjIyMgSFRNTCBUYWcKICAKICAgIFRoZSBkZWZhdWx0IEhUTUwgdGFnIG5hbWUgdXNlZCBmb3IgYSBjb21wb25lbnQncyBIVE1MIHJlcHJlc2VudGF0aW9uIGlzIGBkaXZgLgogICAgVGhpcyBjYW4gYmUgY3VzdG9taXplZCBieSBzZXR0aW5nIHRoZSBgdGFnTmFtZWAgcHJvcGVydHkuCiAgCiAgICBDb25zaWRlciB0aGUgZm9sbG93aW5nIGNvbXBvbmVudCBjbGFzczoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL2VtcGhhc2l6ZWQtcGFyYWdyYXBoLmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIHRhZ05hbWU6ICdlbScKICAgIH0pOwogICAgYGBgCiAgCiAgICBXaGVuIGludm9rZWQsIHRoaXMgY29tcG9uZW50IHdvdWxkIHByb2R1Y2Ugb3V0cHV0IHRoYXQgbG9va3Mgc29tZXRoaW5nIGxpa2UKICAgIHRoaXM6CiAgCiAgICBgYGBodG1sCiAgICA8ZW0gaWQ9ImVtYmVyMSIgY2xhc3M9ImVtYmVyLXZpZXciPjwvZW0+CiAgICBgYGAKICAKICAgICMjIyBIVE1MIGBjbGFzc2AgQXR0cmlidXRlCiAgCiAgICBUaGUgSFRNTCBgY2xhc3NgIGF0dHJpYnV0ZSBvZiBhIGNvbXBvbmVudCdzIHRhZyBjYW4gYmUgc2V0IGJ5IHByb3ZpZGluZyBhCiAgICBgY2xhc3NOYW1lc2AgcHJvcGVydHkgdGhhdCBpcyBzZXQgdG8gYW4gYXJyYXkgb2Ygc3RyaW5nczoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGFzc05hbWVzOiBbJ215LWNsYXNzJywgJ215LW90aGVyLWNsYXNzJ10KICAgIH0pOwogICAgYGBgCiAgCiAgICBJbnZva2luZyB0aGlzIGNvbXBvbmVudCB3aWxsIHByb2R1Y2Ugb3V0cHV0IHRoYXQgbG9va3MgbGlrZSB0aGlzOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyBteS1jbGFzcyBteS1vdGhlci1jbGFzcyI+PC9kaXY+CiAgICBgYGAKICAKICAgIGBjbGFzc2AgYXR0cmlidXRlIHZhbHVlcyBjYW4gYWxzbyBiZSBzZXQgYnkgcHJvdmlkaW5nIGEgYGNsYXNzTmFtZUJpbmRpbmdzYAogICAgcHJvcGVydHkgc2V0IHRvIGFuIGFycmF5IG9mIHByb3BlcnRpZXMgbmFtZXMgZm9yIHRoZSBjb21wb25lbnQuIFRoZSByZXR1cm4KICAgIHZhbHVlIG9mIHRoZXNlIHByb3BlcnRpZXMgd2lsbCBiZSBhZGRlZCBhcyBwYXJ0IG9mIHRoZSB2YWx1ZSBmb3IgdGhlCiAgICBjb21wb25lbnRzJ3MgYGNsYXNzYCBhdHRyaWJ1dGUuIFRoZXNlIHByb3BlcnRpZXMgY2FuIGJlIGNvbXB1dGVkIHByb3BlcnRpZXM6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS13aWRnZXQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGNsYXNzTmFtZXM6IFsnbXktY2xhc3MnLCAnbXktb3RoZXItY2xhc3MnXSwKICAgICAgY2xhc3NOYW1lQmluZGluZ3M6IFsncHJvcGVydHlBJywgJ3Byb3BlcnR5QiddLAogIAogICAgICBwcm9wZXJ0eUE6ICdmcm9tLWEnLAogICAgICBwcm9wZXJ0eUI6IGNvbXB1dGVkKGZ1bmN0aW9uKCkgewogICAgICAgIGlmIChzb21lTG9naWMpIHsgcmV0dXJuICdmcm9tLWInOyB9CiAgICAgIH0pCiAgICB9KTsKICAgIGBgYAogIAogICAgSW52b2tpbmcgdGhpcyBjb21wb25lbnQgd2lsbCBwcm9kdWNlIEhUTUwgdGhhdCBsb29rcyBsaWtlOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyBteS1jbGFzcyBteS1vdGhlci1jbGFzcyBmcm9tLWEgZnJvbS1iIj48L2Rpdj4KICAgIGBgYAogIAogICAgTm90ZSB0aGF0IGBjbGFzc05hbWVzYCBhbmQgYGNsYXNzTmFtZUJpbmRpbmdzYCBpcyBpbiBhZGRpdGlvbiB0byB0aGUgYGNsYXNzYAogICAgYXR0cmlidXRlIHBhc3NlZCB3aXRoIHRoZSBhbmdsZSBicmFja2V0IGludm9jYXRpb24gc3ludGF4LiBUaGVyZWZvcmUsIGlmIHRoaXMKICAgIGNvbXBvbmVudCB3YXMgaW52b2tlZCBsaWtlIHNvOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPE15V2lkZ2V0IGNsYXNzPSJmcm9tLWludm9jYXRpb24iIC8+CiAgICBgYGAKICAKICAgIFRoZSByZXN1bHRpbmcgSFRNTCB3aWxsIGxvb2sgc2ltaWxhciB0byB0aGlzOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZnJvbS1pbnZvY2F0aW9uIGVtYmVyLXZpZXcgbXktY2xhc3MgbXktb3RoZXItY2xhc3MgZnJvbS1hIGZyb20tYiI+PC9kaXY+CiAgICBgYGAKICAKICAgIElmIHRoZSB2YWx1ZSBvZiBhIGNsYXNzIG5hbWUgYmluZGluZyByZXR1cm5zIGEgYm9vbGVhbiB0aGUgcHJvcGVydHkgbmFtZQogICAgaXRzZWxmIHdpbGwgYmUgdXNlZCBhcyB0aGUgY2xhc3MgbmFtZSBpZiB0aGUgcHJvcGVydHkgaXMgdHJ1ZS4gVGhlIGNsYXNzIG5hbWUKICAgIHdpbGwgbm90IGJlIGFkZGVkIGlmIHRoZSB2YWx1ZSBpcyBgZmFsc2VgIG9yIGB1bmRlZmluZWRgLgogIAogICAgYGBgYXBwL2NvbXBvbmVudHMvbXktd2lkZ2V0LmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGNsYXNzTmFtZUJpbmRpbmdzOiBbJ2hvdmVyZWQnXSwKICAKICAgICAgaG92ZXJlZDogdHJ1ZQogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDxkaXYgaWQ9ImVtYmVyMSIgY2xhc3M9ImVtYmVyLXZpZXcgaG92ZXJlZCI+PC9kaXY+CiAgICBgYGAKICAKICAgICMjIyBDdXN0b20gQ2xhc3MgTmFtZXMgZm9yIEJvb2xlYW4gVmFsdWVzCiAgCiAgICBXaGVuIHVzaW5nIGJvb2xlYW4gY2xhc3MgbmFtZSBiaW5kaW5ncyB5b3UgY2FuIHN1cHBseSBhIHN0cmluZyB2YWx1ZSBvdGhlcgogICAgdGhhbiB0aGUgcHJvcGVydHkgbmFtZSBmb3IgdXNlIGFzIHRoZSBgY2xhc3NgIEhUTUwgYXR0cmlidXRlIGJ5IGFwcGVuZGluZyB0aGUKICAgIHByZWZlcnJlZCB2YWx1ZSBhZnRlciBhICI6IiBjaGFyYWN0ZXIgd2hlbiBkZWZpbmluZyB0aGUgYmluZGluZzoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGFzc05hbWVCaW5kaW5nczogWydhd2Vzb21lOnNvLXZlcnktY29vbCddLAogIAogICAgICBhd2Vzb21lOiB0cnVlCiAgICB9KTsKICAgIGBgYAogIAogICAgSW52b2tpbmcgdGhpcyBjb21wb25lbnQgd2lsbCBwcm9kdWNlIEhUTUwgdGhhdCBsb29rcyBsaWtlOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyBzby12ZXJ5LWNvb2wiPjwvZGl2PgogICAgYGBgCiAgCiAgICBCb29sZWFuIHZhbHVlIGNsYXNzIG5hbWUgYmluZGluZ3Mgd2hvc2UgcHJvcGVydHkgbmFtZXMgYXJlIGluIGEKICAgIGNhbWVsQ2FzZS1zdHlsZSBmb3JtYXQgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gYSBkYXNoZXJpemVkIGZvcm1hdDoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGFzc05hbWVCaW5kaW5nczogWydpc1VyZ2VudCddLAogIAogICAgICBpc1VyZ2VudDogdHJ1ZQogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDxkaXYgaWQ9ImVtYmVyMSIgY2xhc3M9ImVtYmVyLXZpZXcgaXMtdXJnZW50Ij48L2Rpdj4KICAgIGBgYAogIAogICAgQ2xhc3MgbmFtZSBiaW5kaW5ncyBjYW4gYWxzbyByZWZlciB0byBvYmplY3QgdmFsdWVzIHRoYXQgYXJlIGZvdW5kIGJ5CiAgICB0cmF2ZXJzaW5nIGEgcGF0aCByZWxhdGl2ZSB0byB0aGUgY29tcG9uZW50IGl0c2VsZjoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGFzc05hbWVCaW5kaW5nczogWydtZXNzYWdlcy5lbXB0eSddLAogIAogICAgICBtZXNzYWdlczogRW1iZXJPYmplY3QuY3JlYXRlKHsKICAgICAgICBlbXB0eTogdHJ1ZQogICAgICB9KQogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDxkaXYgaWQ9ImVtYmVyMSIgY2xhc3M9ImVtYmVyLXZpZXcgZW1wdHkiPjwvZGl2PgogICAgYGBgCiAgCiAgICBJZiB5b3Ugd2FudCB0byBhZGQgYSBjbGFzcyBuYW1lIGZvciBhIHByb3BlcnR5IHdoaWNoIGV2YWx1YXRlcyB0byB0cnVlIGFuZAogICAgYW5kIGEgZGlmZmVyZW50IGNsYXNzIG5hbWUgaWYgaXQgZXZhbHVhdGVzIHRvIGZhbHNlLCB5b3UgY2FuIHBhc3MgYSBiaW5kaW5nCiAgICBsaWtlIHRoaXM6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS13aWRnZXQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgY2xhc3NOYW1lQmluZGluZ3M6IFsnaXNFbmFibGVkOmVuYWJsZWQ6ZGlzYWJsZWQnXSwKICAgICAgaXNFbmFibGVkOiB0cnVlCiAgICB9KTsKICAgIGBgYAogIAogICAgSW52b2tpbmcgdGhpcyBjb21wb25lbnQgd2lsbCBwcm9kdWNlIEhUTUwgdGhhdCBsb29rcyBsaWtlOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyBlbmFibGVkIj48L2Rpdj4KICAgIGBgYAogIAogICAgV2hlbiBpc0VuYWJsZWQgaXMgYGZhbHNlYCwgdGhlIHJlc3VsdGluZyBIVE1MIHJlcHJlc2VudGF0aW9uIGxvb2tzIGxpa2UgdGhpczoKICAKICAgIGBgYGh0bWwKICAgIDxkaXYgaWQ9ImVtYmVyMSIgY2xhc3M9ImVtYmVyLXZpZXcgZGlzYWJsZWQiPjwvZGl2PgogICAgYGBgCiAgCiAgICBUaGlzIHN5bnRheCBvZmZlcnMgdGhlIGNvbnZlbmllbmNlIHRvIGFkZCBhIGNsYXNzIGlmIGEgcHJvcGVydHkgaXMgYGZhbHNlYDoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIC8vIEFwcGxpZXMgbm8gY2xhc3Mgd2hlbiBpc0VuYWJsZWQgaXMgdHJ1ZSBhbmQgY2xhc3MgJ2Rpc2FibGVkJyB3aGVuIGlzRW5hYmxlZCBpcyBmYWxzZQogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGNsYXNzTmFtZUJpbmRpbmdzOiBbJ2lzRW5hYmxlZDo6ZGlzYWJsZWQnXSwKICAgICAgaXNFbmFibGVkOiB0cnVlCiAgICB9KTsKICAgIGBgYAogIAogICAgSW52b2tpbmcgdGhpcyBjb21wb25lbnQgd2hlbiB0aGUgYGlzRW5hYmxlZGAgcHJvcGVydHkgaXMgdHJ1ZSB3aWxsIHByb2R1Y2UKICAgIEhUTUwgdGhhdCBsb29rcyBsaWtlOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyI+PC9kaXY+CiAgICBgYGAKICAKICAgIEludm9raW5nIGl0IHdoZW4gdGhlIGBpc0VuYWJsZWRgIHByb3BlcnR5IG9uIHRoZSBjb21wb25lbnQgaXMgYGZhbHNlYCB3aWxsCiAgICBwcm9kdWNlIEhUTUwgdGhhdCBsb29rcyBsaWtlOgogIAogICAgYGBgaHRtbAogICAgPGRpdiBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyBkaXNhYmxlZCI+PC9kaXY+CiAgICBgYGAKICAKICAgIFVwZGF0ZXMgdG8gdGhlIHZhbHVlIG9mIGEgY2xhc3MgbmFtZSBiaW5kaW5nIHdpbGwgcmVzdWx0IGluIGF1dG9tYXRpYyB1cGRhdGUKICAgIG9mIHRoZSAgSFRNTCBgY2xhc3NgIGF0dHJpYnV0ZSBpbiB0aGUgY29tcG9uZW50J3MgcmVuZGVyZWQgSFRNTAogICAgcmVwcmVzZW50YXRpb24uIElmIHRoZSB2YWx1ZSBiZWNvbWVzIGBmYWxzZWAgb3IgYHVuZGVmaW5lZGAgdGhlIGNsYXNzIG5hbWUKICAgIHdpbGwgYmUgcmVtb3ZlZC4KICAKICAgIEJvdGggYGNsYXNzTmFtZXNgIGFuZCBgY2xhc3NOYW1lQmluZGluZ3NgIGFyZSBjb25jYXRlbmF0ZWQgcHJvcGVydGllcy4gU2VlCiAgICBbRW1iZXJPYmplY3RdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvRW1iZXJPYmplY3QpIGRvY3VtZW50YXRpb24gZm9yIG1vcmUKICAgIGluZm9ybWF0aW9uIGFib3V0IGNvbmNhdGVuYXRlZCBwcm9wZXJ0aWVzLgogIAogICAgIyMjIE90aGVyIEhUTUwgQXR0cmlidXRlcwogIAogICAgVGhlIEhUTUwgYXR0cmlidXRlIHNlY3Rpb24gb2YgYSBjb21wb25lbnQncyB0YWcgY2FuIGJlIHNldCBieSBwcm92aWRpbmcgYW4KICAgIGBhdHRyaWJ1dGVCaW5kaW5nc2AgcHJvcGVydHkgc2V0IHRvIGFuIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIG9uIHRoZSBjb21wb25lbnQuCiAgICBUaGUgcmV0dXJuIHZhbHVlIG9mIHRoZXNlIHByb3BlcnRpZXMgd2lsbCBiZSB1c2VkIGFzIHRoZSB2YWx1ZSBvZiB0aGUgY29tcG9uZW50J3MKICAgIEhUTUwgYXNzb2NpYXRlZCBhdHRyaWJ1dGU6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1hbmNob3IuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgdGFnTmFtZTogJ2EnLAogICAgICBhdHRyaWJ1dGVCaW5kaW5nczogWydocmVmJ10sCiAgCiAgICAgIGhyZWY6ICdodHRwOi8vZ29vZ2xlLmNvbScKICAgIH0pOwogICAgYGBgCiAgCiAgICBJbnZva2luZyB0aGlzIGNvbXBvbmVudCB3aWxsIHByb2R1Y2UgSFRNTCB0aGF0IGxvb2tzIGxpa2U6CiAgCiAgICBgYGBodG1sCiAgICA8YSBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyIgaHJlZj0iaHR0cDovL2dvb2dsZS5jb20iPjwvYT4KICAgIGBgYAogIAogICAgT25lIHByb3BlcnR5IGNhbiBiZSBtYXBwZWQgb24gdG8gYW5vdGhlciBieSBwbGFjaW5nIGEgIjoiIGJldHdlZW4KICAgIHRoZSBzb3VyY2UgcHJvcGVydHkgYW5kIHRoZSBkZXN0aW5hdGlvbiBwcm9wZXJ0eToKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LWFuY2hvci5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICB0YWdOYW1lOiAnYScsCiAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ3VybDpocmVmJ10sCiAgCiAgICAgIHVybDogJ2h0dHA6Ly9nb29nbGUuY29tJwogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDxhIGlkPSJlbWJlcjEiIGNsYXNzPSJlbWJlci12aWV3IiBocmVmPSJodHRwOi8vZ29vZ2xlLmNvbSI+PC9hPgogICAgYGBgCiAgCiAgICBIVE1MIGF0dHJpYnV0ZXMgcGFzc2VkIHdpdGggYW5nbGUgYnJhY2tldCBpbnZvY2F0aW9ucyB3aWxsIHRha2UgcHJlY2VkZW5jZQogICAgb3ZlciB0aG9zZSBzcGVjaWZpZWQgaW4gYGF0dHJpYnV0ZUJpbmRpbmdzYC4gVGhlcmVmb3JlLCBpZiB0aGlzIGNvbXBvbmVudCB3YXMKICAgIGludm9rZWQgbGlrZSBzbzoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxNeUFuY2hvciBocmVmPSJodHRwOi8vYmluZy5jb20iIEB1cmw9Imh0dHA6Ly9nb29nbGUuY29tIiAvPgogICAgYGBgCiAgCiAgICBUaGUgcmVzdWx0aW5nIEhUTUwgd2lsbCBsb29rcyBsaWtlIHRoaXM6CiAgCiAgICBgYGBodG1sCiAgICA8YSBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyIgaHJlZj0iaHR0cDovL2JpbmcuY29tIj48L2E+CiAgICBgYGAKICAKICAgIE5vdGUgdGhhdCB0aGUgYGhyZWZgIGF0dHJpYnV0ZSBpcyB1bHRpbWF0ZWx5IHNldCB0byBgaHR0cDovL2JpbmcuY29tYCwKICAgIGRlc3BpdGUgaXQgaGF2aW5nIGF0dHJpYnV0ZSBiaW5pZG5nIHRvIHRoZSBgdXJsYCBwcm9wZXJ0eSwgd2hpY2ggd2FzCiAgICBzZXQgdG8gYGh0dHA6Ly9nb29nbGUuY29tYC4KICAKICAgIE5hbWVzcGFjZWQgYXR0cmlidXRlcyAoZS5nLiBgeGxpbms6aHJlZmApIGFyZSBzdXBwb3J0ZWQsIGJ1dCBoYXZlIHRvIGJlCiAgICBtYXBwZWQsIHNpbmNlIGA6YCBpcyBub3QgYSB2YWxpZCBjaGFyYWN0ZXIgZm9yIHByb3BlcnRpZXMgaW4gSmF2YXNjcmlwdDoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXVzZS5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICB0YWdOYW1lOiAndXNlJywKICAgICAgYXR0cmlidXRlQmluZGluZ3M6IFsneGxpbmtIcmVmOnhsaW5rOmhyZWYnXSwKICAKICAgICAgeGxpbmtIcmVmOiAnI3RyaWFuZ2xlJwogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDx1c2UgeGxpbms6aHJlZj0iI3RyaWFuZ2xlIj48L3VzZT4KICAgIGBgYAogIAogICAgSWYgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgbW9uaXRvcmVkIGJ5IGBhdHRyaWJ1dGVCaW5kaW5nc2AgaXMgYSBib29sZWFuLCB0aGUKICAgIGF0dHJpYnV0ZSB3aWxsIGJlIHByZXNlbnQgb3IgYWJzZW50IGRlcGVuZGluZyBvbiB0aGUgdmFsdWU6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS10ZXh0LWlucHV0LmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIHRhZ05hbWU6ICdpbnB1dCcsCiAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ2Rpc2FibGVkJ10sCiAgCiAgICAgIGRpc2FibGVkOiBmYWxzZQogICAgfSk7CiAgICBgYGAKICAKICAgIEludm9raW5nIHRoaXMgY29tcG9uZW50IHdpbGwgcHJvZHVjZSBIVE1MIHRoYXQgbG9va3MgbGlrZToKICAKICAgIGBgYGh0bWwKICAgIDxpbnB1dCBpZD0iZW1iZXIxIiBjbGFzcz0iZW1iZXItdmlldyIgLz4KICAgIGBgYAogIAogICAgYGF0dHJpYnV0ZUJpbmRpbmdzYCBjYW4gcmVmZXIgdG8gY29tcHV0ZWQgcHJvcGVydGllczoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXRleHQtaW5wdXQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIHRhZ05hbWU6ICdpbnB1dCcsCiAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ2Rpc2FibGVkJ10sCiAgCiAgICAgIGRpc2FibGVkOiBjb21wdXRlZChmdW5jdGlvbigpIHsKICAgICAgICBpZiAoc29tZUxvZ2ljKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgfSkKICAgIH0pOwogICAgYGBgCiAgCiAgICBUbyBwcmV2ZW50IHNldHRpbmcgYW4gYXR0cmlidXRlIGFsdG9nZXRoZXIsIHVzZSBgbnVsbGAgb3IgYHVuZGVmaW5lZGAgYXMgdGhlCiAgICB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgdXNlZCBpbiBgYXR0cmlidXRlQmluZGluZ3NgOgogIAogICAgYGBgYXBwL2NvbXBvbmVudHMvbXktdGV4dC1pbnB1dC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICB0YWdOYW1lOiAnZm9ybScsCiAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ25vdmFsaWRhdGUnXSwKICAgICAgbm92YWxpZGF0ZTogbnVsbAogICAgfSk7CiAgICBgYGAKICAKICAgIFVwZGF0ZXMgdG8gdGhlIHByb3BlcnR5IG9mIGFuIGF0dHJpYnV0ZSBiaW5kaW5nIHdpbGwgcmVzdWx0IGluIGF1dG9tYXRpYwogICAgdXBkYXRlIG9mIHRoZSAgSFRNTCBhdHRyaWJ1dGUgaW4gdGhlIGNvbXBvbmVudCdzIEhUTUwgb3V0cHV0LgogIAogICAgYGF0dHJpYnV0ZUJpbmRpbmdzYCBpcyBhIGNvbmNhdGVuYXRlZCBwcm9wZXJ0eS4gU2VlCiAgICBbRW1iZXJPYmplY3RdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvRW1iZXJPYmplY3QpIGRvY3VtZW50YXRpb24gZm9yIG1vcmUKICAgIGluZm9ybWF0aW9uIGFib3V0IGNvbmNhdGVuYXRlZCBwcm9wZXJ0aWVzLgogIAogICAgIyMgTGF5b3V0cwogIAogICAgVGhlIGBsYXlvdXRgIHByb3BlcnR5IGNhbiBiZSB1c2VkIHRvIGR5bmFtaWNhbGx5IHNwZWNpZnkgYSB0ZW1wbGF0ZSBhc3NvY2lhdGVkCiAgICB3aXRoIGEgY29tcG9uZW50IGNsYXNzLCBpbnN0ZWFkIG9mIHJlbHlpbmcgb24gRW1iZXIgdG8gbGluayB0b2dldGhlciBhCiAgICBjb21wb25lbnQgY2xhc3MgYW5kIGEgdGVtcGxhdGUgYmFzZWQgb24gZmlsZSBuYW1lcy4KICAKICAgIEluIGdlbmVyYWwsIGFwcGxpY2F0aW9ucyBzaG91bGQgbm90IHVzZSB0aGlzIGZlYXR1cmUsIGJ1dCBpdCdzIGNvbW1vbmx5IHVzZWQKICAgIGluIGFkZG9ucyBmb3IgaGlzdG9yaWNhbCByZWFzb25zLgogIAogICAgVGhlIGBsYXlvdXRgIHByb3BlcnR5IHNob3VsZCBiZSBzZXQgdG8gdGhlIGRlZmF1bHQgZXhwb3J0IG9mIGEgdGVtcGxhdGUKICAgIG1vZHVsZSwgd2hpY2ggaXMgdGhlIG5hbWUgb2YgYSB0ZW1wbGF0ZSBmaWxlIHdpdGhvdXQgdGhlIGAuaGJzYCBleHRlbnNpb24uCiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvcGVyc29uLXByb2ZpbGUuaGJzCiAgICA8aDE+UGVyc29uJ3MgVGl0bGU8L2gxPgogICAgPGRpdiBjbGFzcz0nZGV0YWlscyc+e3t5aWVsZH19PC9kaXY+CiAgICBgYGAKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmpzCiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIGltcG9ydCBsYXlvdXQgZnJvbSAnLi4vdGVtcGxhdGVzL2NvbXBvbmVudHMvcGVyc29uLXByb2ZpbGUnOwogIAogICAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICBsYXlvdXQKICAgICAgfSk7CiAgICBgYGAKICAKICAgIElmIHlvdSBpbnZva2UgdGhlIGNvbXBvbmVudDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxQZXJzb25Qcm9maWxlPgogICAgICA8aDI+Q2hpZWYgQmFza2V0IFdlYXZlcjwvaDI+CiAgICAgIDxoMz5GaXNoZXJtYW4gSW5kdXN0cmllczwvaDM+CiAgICA8L1BlcnNvblByb2ZpbGU+CiAgICBgYGAKICAKICAgIG9yCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7eyNwZXJzb24tcHJvZmlsZX19CiAgICAgIDxoMj5DaGllZiBCYXNrZXQgV2VhdmVyPC9oMj4KICAgICAgPGgzPkZpc2hlcm1hbiBJbmR1c3RyaWVzPC9oMz4KICAgIHt7L3BlcnNvbi1wcm9maWxlfX0KICAgIGBgYAogIAogICAgSXQgd2lsbCByZXN1bHQgaW4gdGhlIGZvbGxvd2luZyBIVE1MIG91dHB1dDoKICAKICAgIGBgYGh0bWwKICAgIDxoMT5QZXJzb24ncyBUaXRsZTwvaDE+CiAgICAgIDxkaXYgY2xhc3M9ImRldGFpbHMiPgogICAgICA8aDI+Q2hpZWYgQmFza2V0IFdlYXZlcjwvaDI+CiAgICAgIDxoMz5GaXNoZXJtYW4gSW5kdXN0cmllczwvaDM+CiAgICA8L2Rpdj4KICAgIGBgYAogIAogICAgIyMgSGFuZGxpbmcgQnJvd3NlciBFdmVudHMKICAKICAgIENvbXBvbmVudHMgY2FuIHJlc3BvbmQgdG8gdXNlci1pbml0aWF0ZWQgZXZlbnRzIGluIG9uZSBvZiB0aHJlZSB3YXlzOiBwYXNzaW5nCiAgICBhY3Rpb25zIHdpdGggYW5nbGUgYnJhY2tldCBpbnZvY2F0aW9uLCBhZGRpbmcgZXZlbnQgaGFuZGxlciBtZXRob2RzIHRvIHRoZQogICAgY29tcG9uZW50J3MgY2xhc3MsIG9yIGFkZGluZyBhY3Rpb25zIHRvIHRoZSBjb21wb25lbnQncyB0ZW1wbGF0ZS4KICAKICAgICMjIyBQYXNzaW5nIEFjdGlvbnMgV2l0aCBBbmdsZSBCcmFja2V0IEludm9hdGlvbgogIAogICAgRm9yIG9uZS1vZmYgZXZlbnRzIHNwZWNpZmljIHRvIHBhcnRpY3VsYXIgaW5zdGFuY2Ugb2YgYSBjb21wb25lbnQsIGl0IGlzIHBvc3NpYmxlCiAgICB0byBwYXNzIGFjdGlvbnMgdG8gdGhlIGNvbXBvbmVudCdzIGVsZW1lbnQgdXNpbmcgYW5nbGUgYnJhY2tldCBpbnZvYXRpb24gc3ludGF4LgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPE15V2lkZ2V0IHt7YWN0aW9uICdmaXJzdFdpZGdldENsaWNrZWQnfX0gLz4KICAKICAgIDxNeVdpZGdldCB7e2FjdGlvbiAnc2Vjb25kV2lkZ2V0Q2xpY2tlZCd9fSAvPgogICAgYGBgCiAgCiAgICBJbiB0aGlzIGNhc2UsIHdoZW4gdGhlIGZpcnN0IGNvbXBvbmVudCBpcyBjbGlja2VkIG9uLCBFbWJlciB3aWxsIGludm9rZSB0aGUKICAgIGBmaXJzdFdpZGdldENsaWNrZWRgIGFjdGlvbi4gV2hlbiB0aGUgc2Vjb25kIGNvbXBvbmVudCBpcyBjbGlja2VkIG9uLCBFbWJlcgogICAgd2lsbCBpbnZva2UgdGhlIGBzZWNvbmRXaWRnZXRDbGlja2VkYCBhY3Rpb24gaW5zdGVhZC4KICAKICAgIEJlc2lkZXMgYHt7YWN0aW9ufX1gLCBpdCBpcyBhbHNvIHBvc3NpYmxlIHRvIHBhc3MgYW55IGFyYml0cmFyeSBlbGVtZW50IG1vZGlmaWVycwogICAgdXNpbmcgdGhlIGFuZ2xlIGJyYWNrZXQgaW52b2NhdGlvbiBzeW50YXguCiAgCiAgICAjIyMgRXZlbnQgSGFuZGxlciBNZXRob2RzCiAgCiAgICBDb21wb25lbnRzIGNhbiBhbHNvIHJlc3BvbmQgdG8gdXNlci1pbml0aWF0ZWQgZXZlbnRzIGJ5IGltcGxlbWVudGluZyBhIG1ldGhvZAogICAgdGhhdCBtYXRjaGVzIHRoZSBldmVudCBuYW1lLiBUaGlzIGFwcHJvYWNoIGlzIGFwcHJvcGlhdGUgd2hlbiB0aGUgc2FtZSBldmVudAogICAgc2hvdWxkIGJlIGhhbmRsZWQgYnkgYWxsIGluc3RhbmNlcyBvZiB0aGUgc2FtZSBjb21wb25lbnQuCiAgCiAgICBBbiBldmVudCBvYmplY3Qgd2lsbCBiZSBwYXNzZWQgYXMgdGhlIGFyZ3VtZW50IHRvIHRoZSBldmVudCBoYW5kbGVyIG1ldGhvZC4KICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LXdpZGdldC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGljayhldmVudCkgewogICAgICAgIC8vIGBldmVudC50YXJnZXRgIGlzIGVpdGhlciB0aGUgY29tcG9uZW50J3MgZWxlbWVudCBvciBvbmUgb2YgaXRzIGNoaWxkcmVuCiAgICAgICAgbGV0IHRhZyA9IGV2ZW50LnRhcmdldC50YWdOYW1lLnRvTG93ZXJDYXNlKCk7CiAgICAgICAgY29uc29sZS5sb2coJ2NsaWNrZWQgb24gYSBgPCR7dGFnfT5gIEhUTUwgZWxlbWVudCEnKTsKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIEluIHRoaXMgZXhhbXBsZSwgd2hlbmV2ZXIgdGhlIHVzZXIgY2xpY2tlZCBhbnl3aGVyZSBpbnNpZGUgdGhlIGNvbXBvbmVudCwgaXQKICAgIHdpbGwgbG9nIGEgbWVzc2FnZSB0byB0aGUgY29uc29sZS4KICAKICAgIEl0IGlzIHBvc3NpYmxlIHRvIGhhbmRsZSBldmVudCB0eXBlcyBvdGhlciB0aGFuIGBjbGlja2AgYnkgaW1wbGVtZW50aW5nIHRoZQogICAgZm9sbG93aW5nIGV2ZW50IGhhbmRsZXIgbWV0aG9kcy4gSW4gYWRkaXRpb24sIGN1c3RvbSBldmVudHMgY2FuIGJlIHJlZ2lzdGVyZWQKICAgIGJ5IHVzaW5nIGBBcHBsaWNhdGlvbi5jdXN0b21FdmVudHNgLgogIAogICAgVG91Y2ggZXZlbnRzOgogIAogICAgKiBgdG91Y2hTdGFydGAKICAgICogYHRvdWNoTW92ZWAKICAgICogYHRvdWNoRW5kYAogICAgKiBgdG91Y2hDYW5jZWxgCiAgCiAgICBLZXlib2FyZCBldmVudHM6CiAgCiAgICAqIGBrZXlEb3duYAogICAgKiBga2V5VXBgCiAgICAqIGBrZXlQcmVzc2AKICAKICAgIE1vdXNlIGV2ZW50czoKICAKICAgICogYG1vdXNlRG93bmAKICAgICogYG1vdXNlVXBgCiAgICAqIGBjb250ZXh0TWVudWAKICAgICogYGNsaWNrYAogICAgKiBgZG91YmxlQ2xpY2tgCiAgICAqIGBmb2N1c0luYAogICAgKiBgZm9jdXNPdXRgCiAgCiAgICBGb3JtIGV2ZW50czoKICAKICAgICogYHN1Ym1pdGAKICAgICogYGNoYW5nZWAKICAgICogYGZvY3VzSW5gCiAgICAqIGBmb2N1c091dGAKICAgICogYGlucHV0YAogIAogICAgRHJhZyBhbmQgZHJvcCBldmVudHM6CiAgCiAgICAqIGBkcmFnU3RhcnRgCiAgICAqIGBkcmFnYAogICAgKiBgZHJhZ0VudGVyYAogICAgKiBgZHJhZ0xlYXZlYAogICAgKiBgZHJhZ092ZXJgCiAgICAqIGBkcmFnRW5kYAogICAgKiBgZHJvcGAKICAKICAgICMjIyBge3thY3Rpb259fWAgSGVscGVyCiAgCiAgICBJbnN0ZWFkIG9mIGhhbmRsaW5nIGFsbCBldmVudHMgb2YgYSBwYXJ0aWN1bGFyIHR5cGUgYW55d2hlcmUgaW5zaWRlIHRoZQogICAgY29tcG9uZW50J3MgZWxlbWVudCwgeW91IG1heSBpbnN0ZWFkIHdhbnQgdG8gbGltaXQgaXQgdG8gYSBwYXJ0aWN1bGFyCiAgICBlbGVtZW50IGluIHRoZSBjb21wb25lbnQncyB0ZW1wbGF0ZS4gSW4gdGhpcyBjYXNlLCBpdCB3b3VsZCBiZSBtb3JlCiAgICBjb252ZW5pZW50IHRvIGltcGxlbWVudCBhbiBhY3Rpb24gaW5zdGVhZC4KICAKICAgIEZvciBleGFtcGxlLCB5b3UgY291bGQgaW1wbGVtZW50IHRoZSBhY3Rpb24gYGhlbGxvYCBmb3IgdGhlIGBwZXJzb24tcHJvZmlsZWAKICAgIGNvbXBvbmVudDoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGFjdGlvbnM6IHsKICAgICAgICBoZWxsbyhuYW1lKSB7CiAgICAgICAgICBjb25zb2xlLmxvZygiSGVsbG8iLCBuYW1lKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBBbmQgdGhlbiB1c2UgaXQgaW4gdGhlIGNvbXBvbmVudCdzIHRlbXBsYXRlOgogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL3BlcnNvbi1wcm9maWxlLmhicwogICAgPGgxPnt7QHBlcnNvbi5uYW1lfX08L2gxPgogIAogICAgPGJ1dHRvbiB7e2FjdGlvbiAnaGVsbG8nIEBwZXJzb24ubmFtZX19PgogICAgICBTYXkgSGVsbG8gdG8ge3tAcGVyc29uLm5hbWV9fQogICAgPC9idXR0b24+CiAgICBgYGAKICAKICAgIFdoZW4gdGhlIHVzZXIgY2xpY2tzIHRoZSBidXR0b24sIEVtYmVyIHdpbGwgaW52b2tlIHRoZSBgaGVsbG9gIGFjdGlvbiwKICAgIHBhc3NpbmcgaW4gdGhlIGN1cnJlbnQgdmFsdWUgb2YgYEBwZXJzb24ubmFtZWAgYXMgYW4gYXJndW1lbnQuCiAgCiAgICBTZWUgW0VtYmVyLlRlbXBsYXRlcy5oZWxwZXJzLmFjdGlvbl0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9FbWJlci5UZW1wbGF0ZXMuaGVscGVycy9tZXRob2RzL2FjdGlvbj9hbmNob3I9YWN0aW9uKS4KICAKICAgIEBjbGFzcyBDb21wb25lbnQKICAgIEBleHRlbmRzIEVtYmVyLkNvcmVWaWV3CiAgICBAdXNlcyBFbWJlci5UYXJnZXRBY3Rpb25TdXBwb3J0CiAgICBAdXNlcyBFbWJlci5DbGFzc05hbWVzU3VwcG9ydAogICAgQHVzZXMgRW1iZXIuQWN0aW9uU3VwcG9ydAogICAgQHVzZXMgRW1iZXIuVmlld01peGluCiAgICBAdXNlcyBFbWJlci5WaWV3U3RhdGVTdXBwb3J0CiAgICBAcHVibGljCiAgKi8KCiAgdmFyIENvbXBvbmVudCA9IF92aWV3cy5Db3JlVmlldy5leHRlbmQoX3ZpZXdzLkNoaWxkVmlld3NTdXBwb3J0LCBfdmlld3MuVmlld1N0YXRlU3VwcG9ydCwgX3ZpZXdzLkNsYXNzTmFtZXNTdXBwb3J0LCBfcnVudGltZS5UYXJnZXRBY3Rpb25TdXBwb3J0LCBfdmlld3MuQWN0aW9uU3VwcG9ydCwgX3ZpZXdzLlZpZXdNaXhpbiwgKF9Db3JlVmlldyRleHRlbmQgPSB7CiAgICBpc0NvbXBvbmVudDogdHJ1ZSwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzW0lTX0RJU1BBVENISU5HX0FUVFJTXSA9IGZhbHNlOwogICAgICB0aGlzW0RJUlRZX1RBR10gPSAoMCwgX3JlZmVyZW5jZS5jcmVhdGVUYWcpKCk7CiAgICAgIHRoaXNbUk9PVF9SRUZdID0gbmV3IFJvb3RSZWZlcmVuY2UodGhpcyk7CiAgICAgIHRoaXNbQk9VTkRTXSA9IG51bGw7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgJiYgdGhpcy5yZW5kZXJlci5fZGVzdGluZWRGb3JET00gJiYgdGhpcy50YWdOYW1lID09PSAnJykgewogICAgICAgIHZhciBldmVudE5hbWVzID0gW107CiAgICAgICAgdmFyIGV2ZW50RGlzcGF0Y2hlciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpLmxvb2t1cCgnZXZlbnRfZGlzcGF0Y2hlcjptYWluJyk7CiAgICAgICAgdmFyIGV2ZW50cyA9IGV2ZW50RGlzcGF0Y2hlciAmJiBldmVudERpc3BhdGNoZXIuX2ZpbmFsRXZlbnRzIHx8IHt9OyAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6Zm9yaW4KCiAgICAgICAgZm9yICh2YXIga2V5IGluIGV2ZW50cykgewogICAgICAgICAgdmFyIG1ldGhvZE5hbWUgPSBldmVudHNba2V5XTsKCiAgICAgICAgICBpZiAodHlwZW9mIHRoaXNbbWV0aG9kTmFtZV0gPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgICAgZXZlbnROYW1lcy5wdXNoKG1ldGhvZE5hbWUpOwogICAgICAgICAgfQogICAgICAgIH0gLy8gSWYgaW4gYSB0YWdsZXNzIGNvbXBvbmVudCwgYXNzZXJ0IHRoYXQgbm8gZXZlbnQgaGFuZGxlcnMgYXJlIGRlZmluZWQKCgogICAgICAgIChmYWxzZSAmJiAhKCFldmVudE5hbWVzLmxlbmd0aCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoCiAgICAgICAgIllvdSBjYW4gbm90IGRlZmluZSBgIiArIGV2ZW50TmFtZXMgKyAiYCBmdW5jdGlvbihzKSB0byBoYW5kbGUgRE9NIGV2ZW50IGluIHRoZSBgIiArIHRoaXMgKyAiYCB0YWdsZXNzIGNvbXBvbmVudCBzaW5jZSBpdCBkb2Vzbid0IGhhdmUgYW55IERPTSBlbGVtZW50LiIsICFldmVudE5hbWVzLmxlbmd0aCkpOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISh0aGlzLm1vdXNlRW50ZXIgPT09IHVuZGVmaW5lZCkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCJVc2luZyBgbW91c2VFbnRlcmAgZXZlbnQgaGFuZGxlciBtZXRob2RzIGluIGNvbXBvbmVudHMgaGFzIGJlZW4gZGVwcmVjYXRlZC4iLCB0aGlzLm1vdXNlRW50ZXIgPT09IHVuZGVmaW5lZCwgewogICAgICAgIGlkOiAnZW1iZXItdmlld3MuZXZlbnQtZGlzcGF0Y2hlci5tb3VzZWVudGVyLWxlYXZlLW1vdmUnLAogICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2NvbXBvbmVudC1tb3VzZWVudGVyLWxlYXZlLW1vdmUnCiAgICAgIH0pKTsKICAgICAgKGZhbHNlICYmICEodGhpcy5tb3VzZUxlYXZlID09PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgiVXNpbmcgYG1vdXNlTGVhdmVgIGV2ZW50IGhhbmRsZXIgbWV0aG9kcyBpbiBjb21wb25lbnRzIGhhcyBiZWVuIGRlcHJlY2F0ZWQuIiwgdGhpcy5tb3VzZUxlYXZlID09PSB1bmRlZmluZWQsIHsKICAgICAgICBpZDogJ2VtYmVyLXZpZXdzLmV2ZW50LWRpc3BhdGNoZXIubW91c2VlbnRlci1sZWF2ZS1tb3ZlJywKICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY19jb21wb25lbnQtbW91c2VlbnRlci1sZWF2ZS1tb3ZlJwogICAgICB9KSk7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMubW91c2VNb3ZlID09PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgiVXNpbmcgYG1vdXNlTW92ZWAgZXZlbnQgaGFuZGxlciBtZXRob2RzIGluIGNvbXBvbmVudHMgaGFzIGJlZW4gZGVwcmVjYXRlZC4iLCB0aGlzLm1vdXNlTW92ZSA9PT0gdW5kZWZpbmVkLCB7CiAgICAgICAgaWQ6ICdlbWJlci12aWV3cy5ldmVudC1kaXNwYXRjaGVyLm1vdXNlZW50ZXItbGVhdmUtbW92ZScsCiAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfY29tcG9uZW50LW1vdXNlZW50ZXItbGVhdmUtbW92ZScKICAgICAgfSkpOwogICAgfSwKICAgIHJlcmVuZGVyOiBmdW5jdGlvbiByZXJlbmRlcigpIHsKICAgICAgKDAsIF9yZWZlcmVuY2UuZGlydHkpKHRoaXNbRElSVFlfVEFHXSk7CgogICAgICB0aGlzLl9zdXBlcigpOwogICAgfQogIH0sIF9Db3JlVmlldyRleHRlbmRbX21ldGFsLlBST1BFUlRZX0RJRF9DSEFOR0VdID0gZnVuY3Rpb24gKGtleSkgewogICAgaWYgKHRoaXNbSVNfRElTUEFUQ0hJTkdfQVRUUlNdKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgYXJncyA9IHRoaXNbQVJHU107CiAgICB2YXIgcmVmZXJlbmNlID0gYXJncyAhPT0gdW5kZWZpbmVkID8gYXJnc1trZXldIDogdW5kZWZpbmVkOwoKICAgIGlmIChyZWZlcmVuY2UgIT09IHVuZGVmaW5lZCAmJiByZWZlcmVuY2VbVVBEQVRFXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJlZmVyZW5jZVtVUERBVEVdKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBrZXkpKTsKICAgIH0KICB9LCBfQ29yZVZpZXckZXh0ZW5kLmdldEF0dHIgPSBmdW5jdGlvbiBnZXRBdHRyKGtleSkgewogICAgLy8gVE9ETyBJbnRpbWF0ZSBBUEkgc2hvdWxkIGJlIGRlcHJlY2F0ZWQKICAgIHJldHVybiB0aGlzLmdldChrZXkpOwogIH0sIF9Db3JlVmlldyRleHRlbmQucmVhZERPTUF0dHIgPSBmdW5jdGlvbiByZWFkRE9NQXR0cihuYW1lKSB7CiAgICAvLyBUT0RPIHJldmlzaXQgdGhpcwogICAgdmFyIF9lbGVtZW50ID0gKDAsIF92aWV3cy5nZXRWaWV3RWxlbWVudCkodGhpcyk7CgogICAgKGZhbHNlICYmICEoX2VsZW1lbnQgIT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IGNhbGwgYHJlYWRET01BdHRyYCBvbiAiICsgdGhpcyArICIgd2hpY2ggZG9lcyBub3QgaGF2ZSBhbiBlbGVtZW50IiwgX2VsZW1lbnQgIT09IG51bGwpKTsKICAgIHZhciBlbGVtZW50ID0gX2VsZW1lbnQ7CiAgICB2YXIgaXNTVkcgPSBlbGVtZW50Lm5hbWVzcGFjZVVSSSA9PT0gX3J1bnRpbWUyLlNWR19OQU1FU1BBQ0U7CgogICAgdmFyIF9ub3JtYWxpemVQcm9wZXJ0eSA9ICgwLCBfcnVudGltZTIubm9ybWFsaXplUHJvcGVydHkpKGVsZW1lbnQsIG5hbWUpLAogICAgICAgIHR5cGUgPSBfbm9ybWFsaXplUHJvcGVydHkudHlwZSwKICAgICAgICBub3JtYWxpemVkID0gX25vcm1hbGl6ZVByb3BlcnR5Lm5vcm1hbGl6ZWQ7CgogICAgaWYgKGlzU1ZHIHx8IHR5cGUgPT09ICdhdHRyJykgewogICAgICByZXR1cm4gZWxlbWVudC5nZXRBdHRyaWJ1dGUobm9ybWFsaXplZCk7CiAgICB9CgogICAgcmV0dXJuIGVsZW1lbnRbbm9ybWFsaXplZF07CiAgfSwgX0NvcmVWaWV3JGV4dGVuZC5kaWRSZWNlaXZlQXR0cnMgPSBmdW5jdGlvbiBkaWRSZWNlaXZlQXR0cnMoKSB7fSwgX0NvcmVWaWV3JGV4dGVuZC5kaWRSZW5kZXIgPSBmdW5jdGlvbiBkaWRSZW5kZXIoKSB7fSwgX0NvcmVWaWV3JGV4dGVuZC53aWxsUmVuZGVyID0gZnVuY3Rpb24gd2lsbFJlbmRlcigpIHt9LCBfQ29yZVZpZXckZXh0ZW5kLmRpZFVwZGF0ZUF0dHJzID0gZnVuY3Rpb24gZGlkVXBkYXRlQXR0cnMoKSB7fSwgX0NvcmVWaWV3JGV4dGVuZC53aWxsVXBkYXRlID0gZnVuY3Rpb24gd2lsbFVwZGF0ZSgpIHt9LCBfQ29yZVZpZXckZXh0ZW5kLmRpZFVwZGF0ZSA9IGZ1bmN0aW9uIGRpZFVwZGF0ZSgpIHt9LCBfQ29yZVZpZXckZXh0ZW5kKSk7CgogIF9leHBvcnRzLkNvbXBvbmVudCA9IENvbXBvbmVudDsKCiAgQ29tcG9uZW50LnRvU3RyaW5nID0gZnVuY3Rpb24gKCkgewogICAgcmV0dXJuICdAZW1iZXIvY29tcG9uZW50JzsKICB9OwoKICBDb21wb25lbnQucmVvcGVuQ2xhc3MoewogICAgaXNDb21wb25lbnRGYWN0b3J5OiB0cnVlLAogICAgcG9zaXRpb25hbFBhcmFtczogW10KICB9KTsKICB7CiAgICAoMCwgX3J1bnRpbWUuc2V0RnJhbWV3b3JrQ2xhc3MpKENvbXBvbmVudCk7CiAgfQogIHZhciBsYXlvdXQgPSB0ZW1wbGF0ZSh7CiAgICAiaWQiOiAiaHZ0c3o3UkYiLAogICAgImJsb2NrIjogIntcInN5bWJvbHNcIjpbXSxcInN0YXRlbWVudHNcIjpbXSxcImhhc0V2YWxcIjpmYWxzZX0iLAogICAgIm1ldGEiOiB7CiAgICAgICJtb2R1bGVOYW1lIjogInBhY2thZ2VzL0BlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIvbGliL3RlbXBsYXRlcy9lbXB0eS5oYnMiCiAgICB9CiAgfSk7CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvY29tcG9uZW50CiAgKi8KCiAgLyoqCiAgICBUaGUgaW50ZXJuYWwgY2xhc3MgdXNlZCB0byBjcmVhdGUgdGV4dCBpbnB1dHMgd2hlbiB0aGUgYHt7aW5wdXR9fWAKICAgIGhlbHBlciBpcyB1c2VkIHdpdGggYHR5cGVgIG9mIGBjaGVja2JveGAuCiAgCiAgICBTZWUgW0VtYmVyLlRlbXBsYXRlcy5oZWxwZXJzLmlucHV0XSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0VtYmVyLlRlbXBsYXRlcy5oZWxwZXJzL21ldGhvZHMvaW5wdXQ/YW5jaG9yPWlucHV0KSAgZm9yIHVzYWdlIGRldGFpbHMuCiAgCiAgICAjIyBEaXJlY3QgbWFuaXB1bGF0aW9uIG9mIGBjaGVja2VkYAogIAogICAgVGhlIGBjaGVja2VkYCBhdHRyaWJ1dGUgb2YgYW4gYENoZWNrYm94YCBvYmplY3Qgc2hvdWxkIGFsd2F5cyBiZSBzZXQKICAgIHRocm91Z2ggdGhlIEVtYmVyIG9iamVjdCBvciBieSBpbnRlcmFjdGluZyB3aXRoIGl0cyByZW5kZXJlZCBlbGVtZW50CiAgICByZXByZXNlbnRhdGlvbiB2aWEgdGhlIG1vdXNlLCBrZXlib2FyZCwgb3IgdG91Y2guIFVwZGF0aW5nIHRoZSB2YWx1ZSBvZiB0aGUKICAgIGNoZWNrYm94IHZpYSBqUXVlcnkgd2lsbCByZXN1bHQgaW4gdGhlIGNoZWNrZWQgdmFsdWUgb2YgdGhlIG9iamVjdCBhbmQgaXRzCiAgICBlbGVtZW50IGxvc2luZyBzeW5jaHJvbml6YXRpb24uCiAgCiAgICAjIyBMYXlvdXQgYW5kIExheW91dE5hbWUgcHJvcGVydGllcwogIAogICAgQmVjYXVzZSBIVE1MIGBpbnB1dGAgZWxlbWVudHMgYXJlIHNlbGYgY2xvc2luZyBgbGF5b3V0YCBhbmQgYGxheW91dE5hbWVgCiAgICBwcm9wZXJ0aWVzIHdpbGwgbm90IGJlIGFwcGxpZWQuCiAgCiAgICBAY2xhc3MgQ2hlY2tib3gKICAgIEBleHRlbmRzIENvbXBvbmVudAogICAgQHB1YmxpYwogICovCgogIHZhciBDaGVja2JveCA9IENvbXBvbmVudC5leHRlbmQoewogICAgbGF5b3V0OiBsYXlvdXQsCgogICAgLyoqCiAgICAgIEJ5IGRlZmF1bHQsIHRoaXMgY29tcG9uZW50IHdpbGwgYWRkIHRoZSBgZW1iZXItY2hlY2tib3hgIGNsYXNzIHRvIHRoZSBjb21wb25lbnQncyBlbGVtZW50LgogICAgICAgICBAcHJvcGVydHkgY2xhc3NOYW1lcwogICAgICBAdHlwZSBBcnJheSB8IFN0cmluZwogICAgICBAZGVmYXVsdCBbJ2VtYmVyLWNoZWNrYm94J10KICAgICAgQHB1YmxpYwogICAgICovCiAgICBjbGFzc05hbWVzOiBbJ2VtYmVyLWNoZWNrYm94J10sCiAgICB0YWdOYW1lOiAnaW5wdXQnLAoKICAgIC8qKgogICAgICBCeSBkZWZhdWx0IHRoaXMgY29tcG9uZW50IHdpbGwgZm9yd2FyZCBhIG51bWJlciBvZiBhcmd1bWVudHMgdG8gYXR0cmlidXRlcyBvbiB0aGUgdGhlCiAgICAgIGNvbXBvbmVudCdzIGVsZW1lbnQ6CiAgICAgICAgICogaW5kZXRlcm1pbmF0ZQogICAgICAqIGRpc2FibGVkCiAgICAgICogdGFiaW5kZXgKICAgICAgKiBuYW1lCiAgICAgICogYXV0b2ZvY3VzCiAgICAgICogcmVxdWlyZWQKICAgICAgKiBmb3JtCiAgICAgICAgIFdoZW4gaW52b2tlZCB3aXRoIGN1cmx5IGJyYWNlcywgdGhpcyBpcyB0aGUgZXhoYXVzdGl2ZSBsaXN0IG9mIEhUTUwgYXR0cmlidXRlcyB5b3UgY2FuCiAgICAgIGN1c3RvbWl6ZSAoaS5lLiBge3tpbnB1dCB0eXBlPSJjaGVja2JveCIgZGlzYWJsZWQ9dHJ1ZX19YCkuCiAgICAgICAgIFdoZW4gaW52b2tlZCB3aXRoIGFuZ2xlIGJyYWNrZXQgaW52b2NhdGlvbiwgdGhpcyBsaXN0IGlzIGlycmVsZXZhbnQsIGJlY2F1c2UgeW91IGNhbiB1c2UgSFRNTAogICAgICBhdHRyaWJ1dGUgc3ludGF4IHRvIGN1c3RvbWl6ZSB0aGUgZWxlbWVudCAoaS5lLgogICAgICBgPElucHV0IEB0eXBlPSJjaGVja2JveCIgZGlzYWJsZWQgZGF0YS1jdXN0b209ImN1c3RvbSB2YWx1ZSIgLz5gKS4gSG93ZXZlciwgYEB0eXBlYCBhbmQKICAgICAgYEBjaGVja2VkYCBtdXN0IGJlIHBhc3NlZCBhcyBuYW1lZCBhcmd1bWVudHMsIG5vdCBhdHRyaWJ1dGVzLgogICAgICAgICBAcHJvcGVydHkgYXR0cmlidXRlQmluZGluZ3MKICAgICAgQHR5cGUgQXJyYXkgfCBTdHJpbmcKICAgICAgQGRlZmF1bHQgWyd0eXBlJywgJ2NoZWNrZWQnLCAnaW5kZXRlcm1pbmF0ZScsICdkaXNhYmxlZCcsICd0YWJpbmRleCcsICduYW1lJywgJ2F1dG9mb2N1cycsICdyZXF1aXJlZCcsICdmb3JtJ10KICAgICAgQHB1YmxpYwogICAgKi8KICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ3R5cGUnLCAnY2hlY2tlZCcsICdpbmRldGVybWluYXRlJywgJ2Rpc2FibGVkJywgJ3RhYmluZGV4JywgJ25hbWUnLCAnYXV0b2ZvY3VzJywgJ3JlcXVpcmVkJywgJ2Zvcm0nXSwKCiAgICAvKioKICAgICAgU2V0cyB0aGUgYHR5cGVgIGF0dHJpYnV0ZSBvZiB0aGUgYENoZWNrYm94YCdzIGVsZW1lbnQKICAgICAgICAgQHByb3BlcnR5IGRpc2FibGVkCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgIEBwcml2YXRlCiAgICAgKi8KICAgIHR5cGU6ICdjaGVja2JveCcsCgogICAgLyoqCiAgICAgIFNldHMgdGhlIGBkaXNhYmxlZGAgYXR0cmlidXRlIG9mIHRoZSBgQ2hlY2tib3hgJ3MgZWxlbWVudAogICAgICAgICBAcHJvcGVydHkgZGlzYWJsZWQKICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgQHB1YmxpYwogICAgICovCiAgICBkaXNhYmxlZDogZmFsc2UsCgogICAgLyoqCiAgICAgIENvcnJlc3BvbmRzIHRvIHRoZSBgaW5kZXRlcm1pbmF0ZWAgcHJvcGVydHkgb2YgdGhlIGBDaGVja2JveGAncyBlbGVtZW50CiAgICAgICAgIEBwcm9wZXJ0eSBkaXNhYmxlZAogICAgICBAZGVmYXVsdCBmYWxzZQogICAgICBAcHVibGljCiAgICAgKi8KICAgIGluZGV0ZXJtaW5hdGU6IGZhbHNlLAoKICAgIC8qKgogICAgICBXaGVuZXZlciB0aGUgY2hlY2tib3ggaXMgaW5zZXJ0ZWQgaW50byB0aGUgRE9NLCBwZXJmb3JtIGluaXRpYWxpemF0aW9uIHN0ZXBzLCB3aGljaCBpbmNsdWRlCiAgICAgIHNldHRpbmcgdGhlIGluZGV0ZXJtaW5hdGUgcHJvcGVydHkgaWYgbmVlZGVkLgogICAgICAgICBJZiB0aGlzIG1ldGhvZCBpcyBvdmVycmlkZGVuLCBgc3VwZXJgIG11c3QgYmUgY2FsbGVkLgogICAgICAgICBAbWV0aG9kCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgZGlkSW5zZXJ0RWxlbWVudDogZnVuY3Rpb24gZGlkSW5zZXJ0RWxlbWVudCgpIHsKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIHRoaXMuZWxlbWVudC5pbmRldGVybWluYXRlID0gQm9vbGVhbih0aGlzLmluZGV0ZXJtaW5hdGUpOwogICAgfSwKCiAgICAvKioKICAgICAgV2hlbmV2ZXIgdGhlIGBjaGFuZ2VgIGV2ZW50IGlzIGZpcmVkIG9uIHRoZSBjaGVja2JveCwgdXBkYXRlIGl0cyBgY2hlY2tlZGAgcHJvcGVydHkgdG8gcmVmbGVjdAogICAgICB3aGV0aGVyIHRoZSBjaGVja2JveCBpcyBjaGVja2VkLgogICAgICAgICBJZiB0aGlzIG1ldGhvZCBpcyBvdmVycmlkZGVuLCBgc3VwZXJgIG11c3QgYmUgY2FsbGVkLgogICAgICAgICBAbWV0aG9kCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgY2hhbmdlOiBmdW5jdGlvbiBjaGFuZ2UoKSB7CiAgICAgICgwLCBfbWV0YWwuc2V0KSh0aGlzLCAnY2hlY2tlZCcsIHRoaXMuZWxlbWVudC5jaGVja2VkKTsKICAgIH0KICB9KTsKICBfZXhwb3J0cy5DaGVja2JveCA9IENoZWNrYm94OwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgdmFyIFVOU0VUID0ge307CiAgICBDaGVja2JveC5yZW9wZW4oewogICAgICB2YWx1ZTogVU5TRVQsCiAgICAgIGRpZFJlY2VpdmVBdHRyczogZnVuY3Rpb24gZGlkUmVjZWl2ZUF0dHJzKCkgewogICAgICAgIHRoaXMuX3N1cGVyKCk7CgogICAgICAgIChmYWxzZSAmJiAhKCEodGhpcy50eXBlID09PSAnY2hlY2tib3gnICYmIHRoaXMudmFsdWUgIT09IFVOU0VUKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJgPElucHV0IEB0eXBlPSdjaGVja2JveCcgQHZhbHVlPXt7Li4ufX0gLz5gIGlzIG5vdCBzdXBwb3J0ZWQ7ICIgKyAicGxlYXNlIHVzZSBgPElucHV0IEB0eXBlPSdjaGVja2JveCcgQGNoZWNrZWQ9e3suLi59fSAvPmAgaW5zdGVhZC4iLCAhKHRoaXMudHlwZSA9PT0gJ2NoZWNrYm94JyAmJiB0aGlzLnZhbHVlICE9PSBVTlNFVCkpKTsKICAgICAgfQogICAgfSk7CiAgfQoKICBDaGVja2JveC50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHsKICAgIHJldHVybiAnQGVtYmVyL2NvbXBvbmVudC9jaGVja2JveCc7CiAgfTsKICAvKioKICBAbW9kdWxlIEBlbWJlci9jb21wb25lbnQKICAqLwoKCiAgdmFyIGlucHV0VHlwZXMgPSBfYnJvd3NlckVudmlyb25tZW50Lmhhc0RPTSA/IE9iamVjdC5jcmVhdGUobnVsbCkgOiBudWxsOwoKICBmdW5jdGlvbiBjYW5TZXRUeXBlT2ZJbnB1dCh0eXBlKSB7CiAgICAvLyBpZiBydW5uaW5nIGluIG91dHNpZGUgb2YgYSBicm93c2VyIGFsd2F5cyByZXR1cm4KICAgIC8vIHRoZSBvcmlnaW5hbCB0eXBlCiAgICBpZiAoIV9icm93c2VyRW52aXJvbm1lbnQuaGFzRE9NKSB7CiAgICAgIHJldHVybiBCb29sZWFuKHR5cGUpOwogICAgfQoKICAgIGlmICh0eXBlIGluIGlucHV0VHlwZXMpIHsKICAgICAgcmV0dXJuIGlucHV0VHlwZXNbdHlwZV07CiAgICB9CgogICAgdmFyIGlucHV0VHlwZVRlc3RFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKTsKCiAgICB0cnkgewogICAgICBpbnB1dFR5cGVUZXN0RWxlbWVudC50eXBlID0gdHlwZTsKICAgIH0gY2F0Y2ggKGUpIHsvLyBpZ25vcmVkCiAgICB9CgogICAgcmV0dXJuIGlucHV0VHlwZXNbdHlwZV0gPSBpbnB1dFR5cGVUZXN0RWxlbWVudC50eXBlID09PSB0eXBlOwogIH0KICAvKioKICAgIFRoZSBpbnRlcm5hbCBjbGFzcyB1c2VkIHRvIGNyZWF0ZSB0ZXh0IGlucHV0cyB3aGVuIHRoZSBgSW5wdXRgIGNvbXBvbmVudCBpcyB1c2VkIHdpdGggYHR5cGVgIG9mIGB0ZXh0YC4KICAKICAgIFNlZSBbRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMuSW5wdXRdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMvbWV0aG9kcy9JbnB1dD9hbmNob3I9SW5wdXQpIGZvciB1c2FnZSBkZXRhaWxzLgogIAogICAgIyMgTGF5b3V0IGFuZCBMYXlvdXROYW1lIHByb3BlcnRpZXMKICAKICAgIEJlY2F1c2UgSFRNTCBgaW5wdXRgIGVsZW1lbnRzIGFyZSBzZWxmIGNsb3NpbmcgYGxheW91dGAgYW5kIGBsYXlvdXROYW1lYAogICAgcHJvcGVydGllcyB3aWxsIG5vdCBiZSBhcHBsaWVkLgogIAogICAgQGNsYXNzIFRleHRGaWVsZAogICAgQGV4dGVuZHMgQ29tcG9uZW50CiAgICBAdXNlcyBFbWJlci5UZXh0U3VwcG9ydAogICAgQHB1YmxpYwogICovCgoKICB2YXIgVGV4dEZpZWxkID0gQ29tcG9uZW50LmV4dGVuZChfdmlld3MuVGV4dFN1cHBvcnQsIHsKICAgIGxheW91dDogbGF5b3V0LAoKICAgIC8qKgogICAgICBCeSBkZWZhdWx0LCB0aGlzIGNvbXBvbmVudCB3aWxsIGFkZCB0aGUgYGVtYmVyLXRleHQtZmllbGRgIGNsYXNzIHRvIHRoZSBjb21wb25lbnQncyBlbGVtZW50LgogICAgICAgICBAcHJvcGVydHkgY2xhc3NOYW1lcwogICAgICBAdHlwZSBBcnJheSB8IFN0cmluZwogICAgICBAZGVmYXVsdCBbJ2VtYmVyLXRleHQtZmllbGQnXQogICAgICBAcHVibGljCiAgICAgKi8KICAgIGNsYXNzTmFtZXM6IFsnZW1iZXItdGV4dC1maWVsZCddLAogICAgdGFnTmFtZTogJ2lucHV0JywKCiAgICAvKioKICAgICAgQnkgZGVmYXVsdCB0aGlzIGNvbXBvbmVudCB3aWxsIGZvcndhcmQgYSBudW1iZXIgb2YgYXJndW1lbnRzIHRvIGF0dHJpYnV0ZXMgb24gdGhlIHRoZQogICAgICBjb21wb25lbnQncyBlbGVtZW50OgogICAgICAgICAqIGFjY2VwdAogICAgICAqIGF1dG9jb21wbGV0ZQogICAgICAqIGF1dG9zYXZlCiAgICAgICogZGlyCiAgICAgICogZm9ybWFjdGlvbgogICAgICAqIGZvcm1lbmN0eXBlCiAgICAgICogZm9ybW1ldGhvZAogICAgICAqIGZvcm1ub3ZhbGlkYXRlCiAgICAgICogZm9ybXRhcmdldAogICAgICAqIGhlaWdodAogICAgICAqIGlucHV0bW9kZQogICAgICAqIGxhbmcKICAgICAgKiBsaXN0CiAgICAgICogdHlwZQogICAgICAqIG1heAogICAgICAqIG1pbgogICAgICAqIG11bHRpcGxlCiAgICAgICogbmFtZQogICAgICAqIHBhdHRlcm4KICAgICAgKiBzaXplCiAgICAgICogc3RlcAogICAgICAqIHZhbHVlCiAgICAgICogd2lkdGgKICAgICAgICAgV2hlbiBpbnZva2VkIHdpdGggYHt7aW5wdXQgdHlwZT0idGV4dCJ9fWAsIHlvdSBjYW4gb25seSBjdXN0b21pemUgdGhlc2UgYXR0cmlidXRlcy4gV2hlbiBpbnZva2VkCiAgICAgIHdpdGggYDxJbnB1dCBAdHlwZT0idGV4dCIgLz5gLCB5b3UgY2FuIGp1c3QgdXNlIEhUTUwgYXR0cmlidXRlcyBkaXJlY3RseS4KICAgICAgICAgQHByb3BlcnR5IGF0dHJpYnV0ZUJpbmRpbmdzCiAgICAgIEB0eXBlIEFycmF5IHwgU3RyaW5nCiAgICAgIEBkZWZhdWx0IFsnYWNjZXB0JywgJ2F1dG9jb21wbGV0ZScsICdhdXRvc2F2ZScsICdkaXInLCAnZm9ybWFjdGlvbicsICdmb3JtZW5jdHlwZScsICdmb3JtbWV0aG9kJywgJ2Zvcm1ub3ZhbGlkYXRlJywgJ2Zvcm10YXJnZXQnLCAnaGVpZ2h0JywgJ2lucHV0bW9kZScsICdsYW5nJywgJ2xpc3QnLCAndHlwZScsICdtYXgnLCAnbWluJywgJ211bHRpcGxlJywgJ25hbWUnLCAncGF0dGVybicsICdzaXplJywgJ3N0ZXAnLCAndmFsdWUnLCAnd2lkdGgnXQogICAgICBAcHVibGljCiAgICAqLwogICAgYXR0cmlidXRlQmluZGluZ3M6IFsnYWNjZXB0JywgJ2F1dG9jb21wbGV0ZScsICdhdXRvc2F2ZScsICdkaXInLCAnZm9ybWFjdGlvbicsICdmb3JtZW5jdHlwZScsICdmb3JtbWV0aG9kJywgJ2Zvcm1ub3ZhbGlkYXRlJywgJ2Zvcm10YXJnZXQnLCAnaGVpZ2h0JywgJ2lucHV0bW9kZScsICdsYW5nJywgJ2xpc3QnLCAndHlwZScsICdtYXgnLCAnbWluJywgJ211bHRpcGxlJywgJ25hbWUnLCAncGF0dGVybicsICdzaXplJywgJ3N0ZXAnLCAndmFsdWUnLCAnd2lkdGgnXSwKCiAgICAvKioKICAgICAgQXMgdGhlIHVzZXIgaW5wdXRzIHRleHQsIHRoaXMgcHJvcGVydHkgaXMgdXBkYXRlZCB0byByZWZsZWN0IHRoZSBgdmFsdWVgIHByb3BlcnR5IG9mIHRoZSBIVE1MCiAgICAgIGVsZW1lbnQuCiAgICAgICAgIEBwcm9wZXJ0eSB2YWx1ZQogICAgICBAdHlwZSBTdHJpbmcKICAgICAgQGRlZmF1bHQgIiIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHZhbHVlOiAnJywKCiAgICAvKioKICAgICAgVGhlIGB0eXBlYCBhdHRyaWJ1dGUgb2YgdGhlIGlucHV0IGVsZW1lbnQuCiAgICAgICAgIEBwcm9wZXJ0eSB0eXBlCiAgICAgIEB0eXBlIFN0cmluZwogICAgICBAZGVmYXVsdCAidGV4dCIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHR5cGU6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKHsKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuICd0ZXh0JzsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoX2tleSwgdmFsdWUkJDEpIHsKICAgICAgICB2YXIgdHlwZSA9ICd0ZXh0JzsKCiAgICAgICAgaWYgKGNhblNldFR5cGVPZklucHV0KHZhbHVlJCQxKSkgewogICAgICAgICAgdHlwZSA9IHZhbHVlJCQxOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHR5cGU7CiAgICAgIH0KICAgIH0pLAoKICAgIC8qKgogICAgICBUaGUgYHNpemVgIG9mIHRoZSB0ZXh0IGZpZWxkIGluIGNoYXJhY3RlcnMuCiAgICAgICAgIEBwcm9wZXJ0eSBzaXplCiAgICAgIEB0eXBlIFN0cmluZwogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBzaXplOiBudWxsLAoKICAgIC8qKgogICAgICBUaGUgYHBhdHRlcm5gIGF0dHJpYnV0ZSBvZiBpbnB1dCBlbGVtZW50LgogICAgICAgICBAcHJvcGVydHkgcGF0dGVybgogICAgICBAdHlwZSBTdHJpbmcKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwogICAgcGF0dGVybjogbnVsbCwKCiAgICAvKioKICAgICAgVGhlIGBtaW5gIGF0dHJpYnV0ZSBvZiBpbnB1dCBlbGVtZW50IHVzZWQgd2l0aCBgdHlwZT0ibnVtYmVyImAgb3IgYHR5cGU9InJhbmdlImAuCiAgICAgICAgIEBwcm9wZXJ0eSBtaW4KICAgICAgQHR5cGUgU3RyaW5nCiAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgQHNpbmNlIDEuNC4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBtaW46IG51bGwsCgogICAgLyoqCiAgICAgIFRoZSBgbWF4YCBhdHRyaWJ1dGUgb2YgaW5wdXQgZWxlbWVudCB1c2VkIHdpdGggYHR5cGU9Im51bWJlciJgIG9yIGB0eXBlPSJyYW5nZSJgLgogICAgICAgICBAcHJvcGVydHkgbWF4CiAgICAgIEB0eXBlIFN0cmluZwogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBzaW5jZSAxLjQuMAogICAgICBAcHVibGljCiAgICAqLwogICAgbWF4OiBudWxsCiAgfSk7CiAgX2V4cG9ydHMuVGV4dEZpZWxkID0gVGV4dEZpZWxkOwoKICBUZXh0RmllbGQudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7CiAgICByZXR1cm4gJ0BlbWJlci9jb21wb25lbnQvdGV4dC1maWVsZCc7CiAgfTsKICAvKioKICBAbW9kdWxlIEBlbWJlci9jb21wb25lbnQKICAqLwoKICAvKioKICAgIFRoZSBgVGV4dGFyZWFgIGNvbXBvbmVudCBpbnNlcnRzIGEgbmV3IGluc3RhbmNlIG9mIGA8dGV4dGFyZWE+YCB0YWcgaW50byB0aGUgdGVtcGxhdGUuCiAgCiAgICBUaGUgYEB2YWx1ZWAgYXJndW1lbnQgcHJvdmlkZXMgdGhlIGNvbnRlbnQgb2YgdGhlIGA8dGV4dGFyZWE+YC4KICAKICAgIFRoaXMgdGVtcGxhdGU6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8VGV4dGFyZWEgQHZhbHVlPSJBIGJ1bmNoIG9mIHRleHQiIC8+CiAgICBgYGAKICAKICAgIFdvdWxkIHJlc3VsdCBpbiB0aGUgZm9sbG93aW5nIEhUTUw6CiAgCiAgICBgYGBodG1sCiAgICA8dGV4dGFyZWEgY2xhc3M9ImVtYmVyLXRleHQtYXJlYSI+CiAgICAgIEEgYnVuY2ggb2YgdGV4dAogICAgPC90ZXh0YXJlYT4KICAgIGBgYAogIAogICAgVGhlIGBAdmFsdWVgIGFyZ3VtZW50IGlzIHR3by13YXkgYm91bmQuIElmIHRoZSB1c2VyIHR5cGVzIHRleHQgaW50byB0aGUgdGV4dGFyZWEsIHRoZSBgQHZhbHVlYAogICAgYXJndW1lbnQgaXMgdXBkYXRlZC4gSWYgdGhlIGBAdmFsdWVgIGFyZ3VtZW50IGlzIHVwZGF0ZWQsIHRoZSB0ZXh0IGluIHRoZSB0ZXh0YXJlYSBpcyB1cGRhdGVkLgogIAogICAgSW4gdGhlIGZvbGxvd2luZyBleGFtcGxlLCB0aGUgYHdyaXR0ZW5Xb3Jkc2AgcHJvcGVydHkgb24gdGhlIGNvbXBvbmVudCB3aWxsIGJlIHVwZGF0ZWQgYXMgdGhlIHVzZXIKICAgIHR5cGVzICdMb3RzIG9mIHRleHQnIGludG8gdGhlIHRleHQgYXJlYSBvZiB0aGVpciBicm93c2VyJ3Mgd2luZG93LgogIAogICAgYGBgYXBwL2NvbXBvbmVudHMvd29yZC1lZGl0b3IuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGdsaW1tZXIvY29tcG9uZW50JzsKICAgIGltcG9ydCB7IHRyYWNrZWQgfSBmcm9tICdAZ2xpbW1lci90cmFja2luZyc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBjbGFzcyBleHRlbmRzIENvbXBvbmVudCB7CiAgICAgIEB0cmFja2VkIHdyaXR0ZW5Xb3JkcyA9ICJMb3RzIG9mIHRleHQgdGhhdCBJUyBib3VuZCI7CiAgICB9CiAgICBgYGAKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxUZXh0YXJlYSBAdmFsdWU9e3t3cml0dGVuV29yZHN9fSAvPgogICAgYGBgCiAgCiAgICBXb3VsZCByZXN1bHQgaW4gdGhlIGZvbGxvd2luZyBIVE1MOgogIAogICAgYGBgaHRtbAogICAgPHRleHRhcmVhIGNsYXNzPSJlbWJlci10ZXh0LWFyZWEiPgogICAgICBMb3RzIG9mIHRleHQgdGhhdCBJUyBib3VuZAogICAgPC90ZXh0YXJlYT4KICAgIGBgYAogIAogICAgSWYgeW91IHdhbnRlZCBhIG9uZSB3YXkgYmluZGluZywgeW91IGNvdWxkIHVzZSB0aGUgYDx0ZXh0YXJlYT5gIGVsZW1lbnQgZGlyZWN0bHksIGFuZCB1c2UgdGhlCiAgICBgdmFsdWVgIERPTSBwcm9wZXJ0eSBhbmQgdGhlIGBpbnB1dGAgZXZlbnQuCiAgCiAgICAjIyMgQWN0aW9ucwogIAogICAgVGhlIGBUZXh0YXJlYWAgY29tcG9uZW50IHRha2VzIGEgbnVtYmVyIG9mIGFyZ3VtZW50cyB3aXRoIGNhbGxiYWNrcyB0aGF0IGFyZSBpbnZva2VkIGluCiAgICByZXNwb25zZSB0byB1c2VyIGV2ZW50cy4KICAKICAgICogYGVudGVyYAogICAgKiBgaW5zZXJ0LW5ld2xpbmVgCiAgICAqIGBlc2NhcGUtcHJlc3NgCiAgICAqIGBmb2N1cy1pbmAKICAgICogYGZvY3VzLW91dGAKICAgICogYGtleS1wcmVzc2AKICAKICAgIFRoZXNlIGNhbGxiYWNrcyBhcmUgcGFzc2VkIHRvIGBUZXh0YXJlYWAgbGlrZSB0aGlzOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPFRleHRhcmVhIEB2YWx1ZT17e3RoaXMuc2VhcmNoV29yZH19IEBlbnRlcj17e3RoaXMucXVlcnl9fSAvPgogICAgYGBgCiAgCiAgICAjIyBDbGFzc2ljIEludm9jYXRpb24gU3ludGF4CiAgCiAgICBUaGUgYFRleHRhcmVhYCBjb21wb25lbnQgY2FuIGFsc28gYmUgaW52b2tlZCB1c2luZyBjdXJseSBicmFjZXMsIGp1c3QgbGlrZSBhbnkgb3RoZXIgRW1iZXIKICAgIGNvbXBvbmVudC4KICAKICAgIEZvciBleGFtcGxlLCB0aGlzIGlzIGFuIGludm9jYXRpb24gdXNpbmcgYW5nbGUtYnJhY2tldCBub3RhdGlvbjoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxUZXh0YXJlYSBAdmFsdWU9e3t0aGlzLnNlYXJjaFdvcmR9fSBAZW50ZXI9e3t0aGlzLnF1ZXJ5fX0gLz4KICAgIGBgYAogIAogICAgWW91IGNvdWxkIGFjY29tcGxpc2ggdGhlIHNhbWUgdGhpbmcgdXNpbmcgY2xhc3NpYyBpbnZvY2F0aW9uOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3t0ZXh0YXJlYSB2YWx1ZT10aGlzLnNlYXJjaFdvcmQgZW50ZXI9dGhpcy5xdWVyeX19CiAgICBgYGAKICAKICAgIFRoZSBtYWluIGRpZmZlcmVuY2UgaXMgdGhhdCBhbmdsZS1icmFja2V0IGludm9jYXRpb24gc3VwcG9ydHMgYW55IEhUTUwgYXR0cmlidXRlIHVzaW5nIEhUTUwKICAgIGF0dHJpYnV0ZSBzeW50YXgsIGJlY2F1c2UgYXR0cmlidXRlcyBhbmQgYXJndW1lbnRzIGhhdmUgZGlmZmVyZW50IHN5bnRheCB3aGVuIHVzaW5nIGFuZ2xlLWJyYWNrZXQKICAgIGludm9jYXRpb24uIEN1cmx5IGJyYWNlIGludm9jYXRpb24sIG9uIHRoZSBvdGhlciBoYW5kLCBvbmx5IGhhcyBhIHNpbmdsZSBzeW50YXggZm9yIGFyZ3VtZW50cywKICAgIGFuZCBjb21wb25lbnRzIG11c3QgbWFudWFsbHkgbWFwIGF0dHJpYnV0ZXMgb250byBjb21wb25lbnQgYXJndW1lbnRzLgogIAogICAgV2hlbiB1c2luZyBjbGFzc2ljIGludm9jYXRpb24gd2l0aCBge3t0ZXh0YXJlYX19YCwgb25seSB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMgYXJlIG1hcHBlZCBvbnRvCiAgICBhcmd1bWVudHM6CiAgCiAgICAqIHJvd3MKICAgICogY29scwogICAgKiBuYW1lCiAgICAqIHNlbGVjdGlvbkVuZAogICAgKiBzZWxlY3Rpb25TdGFydAogICAgKiBhdXRvY29tcGxldGUKICAgICogd3JhcAogICAgKiBsYW5nCiAgICAqIGRpcgogICAgKiB2YWx1ZQogIAogICAgIyMgQ2xhc3NpYyBgbGF5b3V0YCBhbmQgYGxheW91dE5hbWVgIHByb3BlcnRpZXMKICAKICAgIEJlY2F1c2UgSFRNTCBgdGV4dGFyZWFgIGVsZW1lbnRzIGRvIG5vdCBjb250YWluIGlubmVyIEhUTUwgdGhlIGBsYXlvdXRgIGFuZAogICAgYGxheW91dE5hbWVgIHByb3BlcnRpZXMgd2lsbCBub3QgYmUgYXBwbGllZC4KICAKICAgIEBtZXRob2QgVGV4dGFyZWEKICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMKICAgIEBzZWUge1RleHRBcmVhfQogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgU2VlIEVtYmVyLlRlbXBsYXRlcy5jb21wb25lbnRzLlRleHRhcmVhLgogIAogICAgQG1ldGhvZCB0ZXh0YXJlYQogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHNlZSB7RW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMudGV4dGFyZWF9CiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBUaGUgaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gdXNlZCBmb3IgYFRleHRhcmVhYCBpbnZvY2F0aW9ucy4KICAKICAgIEBjbGFzcyBUZXh0QXJlYQogICAgQGV4dGVuZHMgQ29tcG9uZW50CiAgICBAc2VlIHtFbWJlci5UZW1wbGF0ZXMuY29tcG9uZW50cy5UZXh0YXJlYX0KICAgIEB1c2VzIEVtYmVyLlRleHRTdXBwb3J0CiAgICBAcHVibGljCiAgKi8KCgogIHZhciBUZXh0QXJlYSA9IENvbXBvbmVudC5leHRlbmQoX3ZpZXdzLlRleHRTdXBwb3J0LCB7CiAgICBjbGFzc05hbWVzOiBbJ2VtYmVyLXRleHQtYXJlYSddLAogICAgbGF5b3V0OiBsYXlvdXQsCiAgICB0YWdOYW1lOiAndGV4dGFyZWEnLAogICAgYXR0cmlidXRlQmluZGluZ3M6IFsncm93cycsICdjb2xzJywgJ25hbWUnLCAnc2VsZWN0aW9uRW5kJywgJ3NlbGVjdGlvblN0YXJ0JywgJ2F1dG9jb21wbGV0ZScsICd3cmFwJywgJ2xhbmcnLCAnZGlyJywgJ3ZhbHVlJ10sCiAgICByb3dzOiBudWxsLAogICAgY29sczogbnVsbAogIH0pOwogIF9leHBvcnRzLlRleHRBcmVhID0gVGV4dEFyZWE7CgogIFRleHRBcmVhLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkgewogICAgcmV0dXJuICdAZW1iZXIvY29tcG9uZW50L3RleHQtYXJlYSc7CiAgfTsKCiAgdmFyIGxheW91dCQxID0gdGVtcGxhdGUoewogICAgImlkIjogImdpVE54K29wIiwKICAgICJibG9jayI6ICJ7XCJzeW1ib2xzXCI6W1wiJmRlZmF1bHRcIl0sXCJzdGF0ZW1lbnRzXCI6W1s0LFwiaWZcIixbWzI1LDFdXSxudWxsLHtcInN0YXRlbWVudHNcIjpbWzE0LDFdXSxcInBhcmFtZXRlcnNcIjpbXX0se1wic3RhdGVtZW50c1wiOltbMSxbMjMsMCxbXCJsaW5rVGl0bGVcIl1dLGZhbHNlXV0sXCJwYXJhbWV0ZXJzXCI6W119XV0sXCJoYXNFdmFsXCI6ZmFsc2V9IiwKICAgICJtZXRhIjogewogICAgICAibW9kdWxlTmFtZSI6ICJwYWNrYWdlcy9AZW1iZXIvLWludGVybmFscy9nbGltbWVyL2xpYi90ZW1wbGF0ZXMvbGluay10by5oYnMiCiAgICB9CiAgfSk7CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIHZhciBMaW5rQ29tcG9uZW50OwogIHsKICAgIC8qKgogICAgICBUaGUgYExpbmtUb2AgY29tcG9uZW50IHJlbmRlcnMgYSBsaW5rIHRvIHRoZSBzdXBwbGllZCBgcm91dGVOYW1lYCBwYXNzaW5nIGFuIG9wdGlvbmFsbHkKICAgICAgc3VwcGxpZWQgbW9kZWwgdG8gdGhlIHJvdXRlIGFzIGl0cyBgbW9kZWxgIGNvbnRleHQgb2YgdGhlIHJvdXRlLiBUaGUgYmxvY2sgZm9yIGBMaW5rVG9gCiAgICAgIGJlY29tZXMgdGhlIGNvbnRlbnRzIG9mIHRoZSByZW5kZXJlZCBlbGVtZW50OgogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIDxMaW5rVG8gQHJvdXRlPSdwaG90b0dhbGxlcnknPgogICAgICAgIEdyZWF0IEhhbXN0ZXIgUGhvdG9zCiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgVGhpcyB3aWxsIHJlc3VsdCBpbjoKICAgICAgICAgYGBgaHRtbAogICAgICA8YSBocmVmPSIvaGFtc3Rlci1waG90b3MiPgogICAgICAgIEdyZWF0IEhhbXN0ZXIgUGhvdG9zCiAgICAgIDwvYT4KICAgICAgYGBgCiAgICAgICAgICMjIyBEaXNhYmxpbmcgdGhlIGBMaW5rVG9gIGNvbXBvbmVudAogICAgICAgICBUaGUgYExpbmtUb2AgY29tcG9uZW50IGNhbiBiZSBkaXNhYmxlZCBieSB1c2luZyB0aGUgYGRpc2FibGVkYCBhcmd1bWVudC4gQSBkaXNhYmxlZCBsaW5rCiAgICAgIGRvZXNuJ3QgcmVzdWx0IGluIGEgdHJhbnNpdGlvbiB3aGVuIGFjdGl2YXRlZCwgYW5kIGFkZHMgdGhlIGBkaXNhYmxlZGAgY2xhc3MgdG8gdGhlIGA8YT5gCiAgICAgIGVsZW1lbnQuCiAgICAgICAgIChUaGUgY2xhc3MgbmFtZSB0byBhcHBseSB0byB0aGUgZWxlbWVudCBjYW4gYmUgb3ZlcnJpZGRlbiBieSB1c2luZyB0aGUgYGRpc2FibGVkQ2xhc3NgCiAgICAgIGFyZ3VtZW50KQogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIDxMaW5rVG8gQHJvdXRlPSdwaG90b0dhbGxlcnknIEBkaXNhYmxlZD17e3RydWV9fT4KICAgICAgICBHcmVhdCBIYW1zdGVyIFBob3RvcwogICAgICA8L0xpbmtUbz4KICAgICAgYGBgCiAgICAgICAgICMjIyBIYW5kbGluZyBgaHJlZmAKICAgICAgICAgYDxMaW5rVG8+YCB3aWxsIHVzZSB5b3VyIGFwcGxpY2F0aW9uJ3MgUm91dGVyIHRvIGZpbGwgdGhlIGVsZW1lbnQncyBgaHJlZmAgcHJvcGVydHkgd2l0aCBhIFVSTAogICAgICB0aGF0IG1hdGNoZXMgdGhlIHBhdGggdG8gdGhlIHN1cHBsaWVkIGByb3V0ZU5hbWVgLgogICAgICAgICAjIyMgSGFuZGxpbmcgY3VycmVudCByb3V0ZQogICAgICAgICBUaGUgYExpbmtUb2AgY29tcG9uZW50IHdpbGwgYXBwbHkgYSBDU1MgY2xhc3MgbmFtZSBvZiAnYWN0aXZlJyB3aGVuIHRoZSBhcHBsaWNhdGlvbidzIGN1cnJlbnQKICAgICAgcm91dGUgbWF0Y2hlcyB0aGUgc3VwcGxpZWQgcm91dGVOYW1lLiBGb3IgZXhhbXBsZSwgaWYgdGhlIGFwcGxpY2F0aW9uJ3MgY3VycmVudCByb3V0ZSBpcwogICAgICAncGhvdG9HYWxsZXJ5LnJlY2VudCcsIHRoZW4gdGhlIGZvbGxvd2luZyBpbnZvY2F0aW9uIG9mIGBMaW5rVG9gOgogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIDxMaW5rVG8gQHJvdXRlPSdwaG90b0dhbGxlcnkucmVjZW50Jz4KICAgICAgICBHcmVhdCBIYW1zdGVyIFBob3RvcwogICAgICA8L0xpbmtUbz4KICAgICAgYGBgCiAgICAgICAgIHdpbGwgcmVzdWx0IGluCiAgICAgICAgIGBgYGh0bWwKICAgICAgPGEgaHJlZj0iL2hhbXN0ZXItcGhvdG9zL3RoaXMtd2VlayIgY2xhc3M9ImFjdGl2ZSI+CiAgICAgICAgR3JlYXQgSGFtc3RlciBQaG90b3MKICAgICAgPC9hPgogICAgICBgYGAKICAgICAgICAgVGhlIENTUyBjbGFzcyB1c2VkIGZvciBhY3RpdmUgY2xhc3NlcyBjYW4gYmUgY3VzdG9taXplZCBieSBwYXNzaW5nIGFuIGBhY3RpdmVDbGFzc2AgYXJndW1lbnQ6CiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPExpbmtUbyBAcm91dGU9J3Bob3RvR2FsbGVyeS5yZWNlbnQnIEBhY3RpdmVDbGFzcz0iY3VycmVudC11cmwiPgogICAgICAgIEdyZWF0IEhhbXN0ZXIgUGhvdG9zCiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgYGBgaHRtbAogICAgICA8YSBocmVmPSIvaGFtc3Rlci1waG90b3MvdGhpcy13ZWVrIiBjbGFzcz0iY3VycmVudC11cmwiPgogICAgICAgIEdyZWF0IEhhbXN0ZXIgUGhvdG9zCiAgICAgIDwvYT4KICAgICAgYGBgCiAgICAgICAgICMjIyBLZWVwaW5nIGEgbGluayBhY3RpdmUgZm9yIG90aGVyIHJvdXRlcwogICAgICAgICBJZiB5b3UgbmVlZCBhIGxpbmsgdG8gYmUgJ2FjdGl2ZScgZXZlbiB3aGVuIGl0IGRvZXNuJ3QgbWF0Y2ggdGhlIGN1cnJlbnQgcm91dGUsIHlvdSBjYW4gdXNlIHRoZQogICAgICBgY3VycmVudC13aGVuYCBhcmd1bWVudC4KICAgICAgICAgYGBgaGFuZGxlYmFycwogICAgICA8TGlua1RvIEByb3V0ZT0ncGhvdG9HYWxsZXJ5JyBAY3VycmVudC13aGVuPSdwaG90b3MnPgogICAgICAgIFBob3RvIEdhbGxlcnkKICAgICAgPC9MaW5rVG8+CiAgICAgIGBgYAogICAgICAgICBUaGlzIG1heSBiZSBoZWxwZnVsIGZvciBrZWVwaW5nIGxpbmtzIGFjdGl2ZSBmb3I6CiAgICAgICAgICogbm9uLW5lc3RlZCByb3V0ZXMgdGhhdCBhcmUgbG9naWNhbGx5IHJlbGF0ZWQKICAgICAgKiBzb21lIHNlY29uZGFyeSBtZW51IGFwcHJvYWNoZXMKICAgICAgKiAndG9wIG5hdmlnYXRpb24nIHdpdGggJ3N1YiBuYXZpZ2F0aW9uJyBzY2VuYXJpb3MKICAgICAgICAgQSBsaW5rIHdpbGwgYmUgYWN0aXZlIGlmIGBjdXJyZW50LXdoZW5gIGlzIGB0cnVlYCBvciB0aGUgY3VycmVudAogICAgICByb3V0ZSBpcyB0aGUgcm91dGUgdGhpcyBsaW5rIHdvdWxkIHRyYW5zaXRpb24gdG8uCiAgICAgICAgIFRvIG1hdGNoIG11bHRpcGxlIHJvdXRlcyAnc3BhY2Utc2VwYXJhdGUnIHRoZSByb3V0ZXM6CiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPExpbmtUbyBAcm91dGU9J2dhbGxlcnknIEBjdXJyZW50LXdoZW49J3Bob3RvcyBkcmF3aW5ncyBwYWludGluZ3MnPgogICAgICAgIEFydCBHYWxsZXJ5CiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgIyMjIFN1cHBseWluZyBhIG1vZGVsCiAgICAgICAgIEFuIG9wdGlvbmFsIGBtb2RlbGAgYXJndW1lbnQgY2FuIGJlIHVzZWQgZm9yIHJvdXRlcyB3aG9zZQogICAgICBwYXRocyBjb250YWluIGR5bmFtaWMgc2VnbWVudHMuIFRoaXMgYXJndW1lbnQgd2lsbCBiZWNvbWUKICAgICAgdGhlIG1vZGVsIGNvbnRleHQgb2YgdGhlIGxpbmtlZCByb3V0ZToKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoInBob3RvR2FsbGVyeSIsIHtwYXRoOiAiaGFtc3Rlci1waG90b3MvOnBob3RvX2lkIn0pOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPExpbmtUbyBAcm91dGU9J3Bob3RvR2FsbGVyeScgQG1vZGVsPXt7dGhpcy5hUGhvdG99fT4KICAgICAgICB7e2FQaG90by50aXRsZX19CiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgYGBgaHRtbAogICAgICA8YSBocmVmPSIvaGFtc3Rlci1waG90b3MvNDIiPgogICAgICAgIFRvbXN0ZXIKICAgICAgPC9hPgogICAgICBgYGAKICAgICAgICAgIyMjIFN1cHBseWluZyBtdWx0aXBsZSBtb2RlbHMKICAgICAgICAgRm9yIGRlZXAtbGlua2luZyB0byByb3V0ZSBwYXRocyB0aGF0IGNvbnRhaW4gbXVsdGlwbGUKICAgICAgZHluYW1pYyBzZWdtZW50cywgdGhlIGBtb2RlbHNgIGFyZ3VtZW50IGNhbiBiZSB1c2VkLgogICAgICAgICBBcyB0aGUgcm91dGVyIHRyYW5zaXRpb25zIHRocm91Z2ggdGhlIHJvdXRlIHBhdGgsIGVhY2gKICAgICAgc3VwcGxpZWQgbW9kZWwgYXJndW1lbnQgd2lsbCBiZWNvbWUgdGhlIGNvbnRleHQgZm9yIHRoZQogICAgICByb3V0ZSB3aXRoIHRoZSBkeW5hbWljIHNlZ21lbnRzOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgicGhvdG9HYWxsZXJ5IiwgeyBwYXRoOiAiaGFtc3Rlci1waG90b3MvOnBob3RvX2lkIiB9LCBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMucm91dGUoImNvbW1lbnQiLCB7cGF0aDogImNvbW1lbnRzLzpjb21tZW50X2lkIn0pOwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIFRoaXMgYXJndW1lbnQgd2lsbCBiZWNvbWUgdGhlIG1vZGVsIGNvbnRleHQgb2YgdGhlIGxpbmtlZCByb3V0ZToKICAgICAgICAgYGBgaGFuZGxlYmFycwogICAgICA8TGlua1RvIEByb3V0ZT0ncGhvdG9HYWxsZXJ5LmNvbW1lbnQnIEBtb2RlbHM9e3thcnJheSB0aGlzLmFQaG90byB0aGlzLmNvbW1lbnR9fT4KICAgICAgICB7e2NvbW1lbnQuYm9keX19CiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgYGBgaHRtbAogICAgICA8YSBocmVmPSIvaGFtc3Rlci1waG90b3MvNDIvY29tbWVudHMvNzE4Ij4KICAgICAgICBBKysrIHdvdWxkIHNudWdnbGUgYWdhaW4uCiAgICAgIDwvYT4KICAgICAgYGBgCiAgICAgICAgICMjIyBTdXBwbHlpbmcgYW4gZXhwbGljaXQgZHluYW1pYyBzZWdtZW50IHZhbHVlCiAgICAgICAgIElmIHlvdSBkb24ndCBoYXZlIGEgbW9kZWwgb2JqZWN0IGF2YWlsYWJsZSB0byBwYXNzIHRvIGBMaW5rVG9gLAogICAgICBhbiBvcHRpb25hbCBzdHJpbmcgb3IgaW50ZWdlciBhcmd1bWVudCBjYW4gYmUgcGFzc2VkIGZvciByb3V0ZXMgd2hvc2UKICAgICAgcGF0aHMgY29udGFpbiBkeW5hbWljIHNlZ21lbnRzLiBUaGlzIGFyZ3VtZW50IHdpbGwgYmVjb21lIHRoZSB2YWx1ZQogICAgICBvZiB0aGUgZHluYW1pYyBzZWdtZW50OgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgicGhvdG9HYWxsZXJ5IiwgeyBwYXRoOiAiaGFtc3Rlci1waG90b3MvOnBob3RvX2lkIiB9KTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIDxMaW5rVG8gQHJvdXRlPSdwaG90b0dhbGxlcnknIEBtb2RlbD17e2FQaG90b0lkfX0+CiAgICAgICAge3t0aGlzLmFQaG90by50aXRsZX19CiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgYGBgaHRtbAogICAgICA8YSBocmVmPSIvaGFtc3Rlci1waG90b3MvNDIiPgogICAgICAgIFRvbXN0ZXIKICAgICAgPC9hPgogICAgICBgYGAKICAgICAgICAgV2hlbiB0cmFuc2l0aW9uaW5nIGludG8gdGhlIGxpbmtlZCByb3V0ZSwgdGhlIGBtb2RlbGAgaG9vayB3aWxsCiAgICAgIGJlIHRyaWdnZXJlZCB3aXRoIHBhcmFtZXRlcnMgaW5jbHVkaW5nIHRoaXMgcGFzc2VkIGlkZW50aWZpZXIuCiAgICAgICAgICMjIyBBbGxvd2luZyBEZWZhdWx0IEFjdGlvbgogICAgICAgICBCeSBkZWZhdWx0IHRoZSBgPExpbmtUbz5gIGNvbXBvbmVudCBwcmV2ZW50cyB0aGUgZGVmYXVsdCBicm93c2VyIGFjdGlvbiBieSBjYWxsaW5nCiAgICAgIGBwcmV2ZW50RGVmYXVsdCgpYCB0byBhdm9pZCByZWxvYWRpbmcgdGhlIGJyb3dzZXIgcGFnZS4KICAgICAgICAgSWYgeW91IG5lZWQgdG8gdHJpZ2dlciBhIGZ1bGwgYnJvd3NlciByZWxvYWQgcGFzcyBgQHByZXZlbnREZWZhdWx0PXt7ZmFsc2V9fWA6CiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPExpbmtUbyBAcm91dGU9J3Bob3RvR2FsbGVyeScgQG1vZGVsPXt7dGhpcy5hUGhvdG9JZH19IEBwcmV2ZW50RGVmYXVsdD17e2ZhbHNlfX0+CiAgICAgICAge3t0aGlzLmFQaG90b0lkLnRpdGxlfX0KICAgICAgPC9MaW5rVG8+CiAgICAgIGBgYAogICAgICAgICAjIyMgU3VwcGx5aW5nIGEgYHRhZ05hbWVgCiAgICAgICAgIEJ5IGRlZmF1bHQgYDxMaW5rVG8+YCByZW5kZXJzIGFuIGA8YT5gIGVsZW1lbnQuIFRoaXMgY2FuIGJlIG92ZXJyaWRkZW4gZm9yIGEgc2luZ2xlIHVzZSBvZgogICAgICBgPExpbmtUbz5gIGJ5IHN1cHBseWluZyBhIGB0YWdOYW1lYCBhcmd1bWVudDoKICAgICAgICAgYGBgaGFuZGxlYmFycwogICAgICA8TGlua1RvIEByb3V0ZT0ncGhvdG9HYWxsZXJ5JyBAdGFnTmFtZT0nbGknPgogICAgICAgIEdyZWF0IEhhbXN0ZXIgUGhvdG9zCiAgICAgIDwvTGlua1RvPgogICAgICBgYGAKICAgICAgICAgVGhpcyBwcm9kdWNlczoKICAgICAgICAgYGBgaHRtbAogICAgICA8bGk+CiAgICAgICAgR3JlYXQgSGFtc3RlciBQaG90b3MKICAgICAgPC9saT4KICAgICAgYGBgCiAgICAgICAgIEluIGdlbmVyYWwsIHRoaXMgaXMgbm90IHJlY29tbWVuZGVkLiBJbnN0ZWFkLCB5b3UgY2FuIHVzZSB0aGUgYHRyYW5zaXRpb24tdG9gIGhlbHBlciB0b2dldGhlcgogICAgICB3aXRoIGEgY2xpY2sgZXZlbnQgaGFuZGxlciBvbiB0aGUgSFRNTCB0YWcgb2YgeW91ciBjaG9vc2luZy4KICAgICAgICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuY29tcG9uZW50cwogICAgICBAbWV0aG9kIExpbmtUbwogICAgICBAc2VlIHtMaW5rQ29tcG9uZW50fQogICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBAbW9kdWxlIEBlbWJlci9yb3V0aW5nCiAgICAqLwoKICAgIC8qKgogICAgICBTZWUgW0VtYmVyLlRlbXBsYXRlcy5jb21wb25lbnRzLkxpbmtUb10oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9FbWJlci5UZW1wbGF0ZXMuY29tcG9uZW50cy9tZXRob2RzL2lucHV0P2FuY2hvcj1MaW5rVG8pLgogICAgICAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICAgIEBtZXRob2QgbGluay10bwogICAgICBAc2VlIHtFbWJlci5UZW1wbGF0ZXMuY29tcG9uZW50cy5MaW5rVG99CiAgICAgIEBwdWJsaWMKICAgICoqLwoKICAgIC8qKgogICAgICBgTGlua0NvbXBvbmVudGAgaXMgdGhlIGludGVybmFsIGNvbXBvbmVudCBpbnZva2VkIHdpdGggYDxMaW5rVG8+YCBvciBge3tsaW5rLXRvfX1gLgogICAgICAgICBAY2xhc3MgTGlua0NvbXBvbmVudAogICAgICBAZXh0ZW5kcyBDb21wb25lbnQKICAgICAgQHNlZSB7RW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMuTGlua1RvfQogICAgICBAcHVibGljCiAgICAqKi8KICAgIHZhciBVTkRFRklORUQgPSBPYmplY3QuZnJlZXplKHsKICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uIHRvU3RyaW5nKCkgewogICAgICAgIHJldHVybiAnVU5ERUZJTkVEJzsKICAgICAgfQogICAgfSk7CiAgICB2YXIgRU1QVFlfUVVFUllfUEFSQU1TID0gT2JqZWN0LmZyZWV6ZSh7fSk7CiAgICBMaW5rQ29tcG9uZW50ID0gQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGxheW91dDogbGF5b3V0JDEsCiAgICAgIHRhZ05hbWU6ICdhJywKCiAgICAgIC8qKgogICAgICAgIEBwcm9wZXJ0eSByb3V0ZQogICAgICAgIEBjYXRlZ29yeSBFTUJFUl9HTElNTUVSX0FOR0xFX0JSQUNLRVRfQlVJTFRfSU5TCiAgICAgICAgQHB1YmxpYwogICAgICAqLwogICAgICByb3V0ZTogVU5ERUZJTkVELAoKICAgICAgLyoqCiAgICAgICAgQHByb3BlcnR5IG1vZGVsCiAgICAgICAgQGNhdGVnb3J5IEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMKICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgIG1vZGVsOiBVTkRFRklORUQsCgogICAgICAvKioKICAgICAgICBAcHJvcGVydHkgbW9kZWxzCiAgICAgICAgQGNhdGVnb3J5IEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMKICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgIG1vZGVsczogVU5ERUZJTkVELAoKICAgICAgLyoqCiAgICAgICAgQHByb3BlcnR5IHF1ZXJ5CiAgICAgICAgQGNhdGVnb3J5IEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMKICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgIHF1ZXJ5OiBVTkRFRklORUQsCgogICAgICAvKioKICAgICAgICBVc2VkIHRvIGRldGVybWluZSB3aGVuIHRoaXMgYExpbmtDb21wb25lbnRgIGlzIGFjdGl2ZS4KICAgICAgICAgICAgIEBwcm9wZXJ0eSBjdXJyZW50LXdoZW4KICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgICdjdXJyZW50LXdoZW4nOiBudWxsLAoKICAgICAgLyoqCiAgICAgICAgU2V0cyB0aGUgYHRpdGxlYCBhdHRyaWJ1dGUgb2YgdGhlIGBMaW5rQ29tcG9uZW50YCdzIEhUTUwgZWxlbWVudC4KICAgICAgICAgICAgIEBwcm9wZXJ0eSB0aXRsZQogICAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgICBAcHVibGljCiAgICAgICoqLwogICAgICB0aXRsZTogbnVsbCwKCiAgICAgIC8qKgogICAgICAgIFNldHMgdGhlIGByZWxgIGF0dHJpYnV0ZSBvZiB0aGUgYExpbmtDb21wb25lbnRgJ3MgSFRNTCBlbGVtZW50LgogICAgICAgICAgICAgQHByb3BlcnR5IHJlbAogICAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgICBAcHVibGljCiAgICAgICoqLwogICAgICByZWw6IG51bGwsCgogICAgICAvKioKICAgICAgICBTZXRzIHRoZSBgdGFiaW5kZXhgIGF0dHJpYnV0ZSBvZiB0aGUgYExpbmtDb21wb25lbnRgJ3MgSFRNTCBlbGVtZW50LgogICAgICAgICAgICAgQHByb3BlcnR5IHRhYmluZGV4CiAgICAgICAgQGRlZmF1bHQgbnVsbAogICAgICAgIEBwdWJsaWMKICAgICAgKiovCiAgICAgIHRhYmluZGV4OiBudWxsLAoKICAgICAgLyoqCiAgICAgICAgU2V0cyB0aGUgYHRhcmdldGAgYXR0cmlidXRlIG9mIHRoZSBgTGlua0NvbXBvbmVudGAncyBIVE1MIGVsZW1lbnQuCiAgICAgICAgICAgICBAc2luY2UgMS44LjAKICAgICAgICBAcHJvcGVydHkgdGFyZ2V0CiAgICAgICAgQGRlZmF1bHQgbnVsbAogICAgICAgIEBwdWJsaWMKICAgICAgKiovCiAgICAgIHRhcmdldDogbnVsbCwKCiAgICAgIC8qKgogICAgICAgIFRoZSBDU1MgY2xhc3MgdG8gYXBwbHkgdG8gYExpbmtDb21wb25lbnRgJ3MgZWxlbWVudCB3aGVuIGl0cyBgYWN0aXZlYAogICAgICAgIHByb3BlcnR5IGlzIGB0cnVlYC4KICAgICAgICAgICAgIEBwcm9wZXJ0eSBhY3RpdmVDbGFzcwogICAgICAgIEB0eXBlIFN0cmluZwogICAgICAgIEBkZWZhdWx0IGFjdGl2ZQogICAgICAgIEBwdWJsaWMKICAgICAgKiovCiAgICAgIGFjdGl2ZUNsYXNzOiAnYWN0aXZlJywKCiAgICAgIC8qKgogICAgICAgIFRoZSBDU1MgY2xhc3MgdG8gYXBwbHkgdG8gYExpbmtDb21wb25lbnRgJ3MgZWxlbWVudCB3aGVuIGl0cyBgbG9hZGluZ2AKICAgICAgICBwcm9wZXJ0eSBpcyBgdHJ1ZWAuCiAgICAgICAgICAgICBAcHJvcGVydHkgbG9hZGluZ0NsYXNzCiAgICAgICAgQHR5cGUgU3RyaW5nCiAgICAgICAgQGRlZmF1bHQgbG9hZGluZwogICAgICAgIEBwcml2YXRlCiAgICAgICoqLwogICAgICBsb2FkaW5nQ2xhc3M6ICdsb2FkaW5nJywKCiAgICAgIC8qKgogICAgICAgIFRoZSBDU1MgY2xhc3MgdG8gYXBwbHkgdG8gYSBgTGlua0NvbXBvbmVudGAncyBlbGVtZW50IHdoZW4gaXRzIGBkaXNhYmxlZGAKICAgICAgICBwcm9wZXJ0eSBpcyBgdHJ1ZWAuCiAgICAgICAgICAgICBAcHJvcGVydHkgZGlzYWJsZWRDbGFzcwogICAgICAgIEB0eXBlIFN0cmluZwogICAgICAgIEBkZWZhdWx0IGRpc2FibGVkCiAgICAgICAgQHByaXZhdGUKICAgICAgKiovCiAgICAgIGRpc2FibGVkQ2xhc3M6ICdkaXNhYmxlZCcsCgogICAgICAvKioKICAgICAgICBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlIGBMaW5rQ29tcG9uZW50YCB3aWxsIHRyaWdnZXIgcm91dGluZyB2aWEKICAgICAgICB0aGUgYHJlcGxhY2VXaXRoYCByb3V0aW5nIHN0cmF0ZWd5LgogICAgICAgICAgICAgQHByb3BlcnR5IHJlcGxhY2UKICAgICAgICBAdHlwZSBCb29sZWFuCiAgICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgICBAcHVibGljCiAgICAgICoqLwogICAgICByZXBsYWNlOiBmYWxzZSwKCiAgICAgIC8qKgogICAgICAgIEJ5IGRlZmF1bHQgdGhpcyBjb21wb25lbnQgd2lsbCBmb3J3YXJkIGBocmVmYCwgYHRpdGxlYCwgYHJlbGAsIGB0YWJpbmRleGAsIGFuZCBgdGFyZ2V0YAogICAgICAgIGFyZ3VtZW50cyB0byBhdHRyaWJ1dGVzIG9uIHRoZSBjb21wb25lbnQncyBlbGVtZW50LiBXaGVuIGludm9rZWQgd2l0aCBge3tsaW5rLXRvfX1gLCB5b3UgY2FuCiAgICAgICAgb25seSBjdXN0b21pemUgdGhlc2UgYXR0cmlidXRlcy4gV2hlbiBpbnZva2VkIHdpdGggYDxMaW5rVG8+YCwgeW91IGNhbiBqdXN0IHVzZSBIVE1MCiAgICAgICAgYXR0cmlidXRlcyBkaXJlY3RseS4KICAgICAgICAgICAgIEBwcm9wZXJ0eSBhdHRyaWJ1dGVCaW5kaW5ncwogICAgICAgIEB0eXBlIEFycmF5IHwgU3RyaW5nCiAgICAgICAgQGRlZmF1bHQgWyd0aXRsZScsICdyZWwnLCAndGFiaW5kZXgnLCAndGFyZ2V0J10KICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ2hyZWYnLCAndGl0bGUnLCAncmVsJywgJ3RhYmluZGV4JywgJ3RhcmdldCddLAoKICAgICAgLyoqCiAgICAgICAgQnkgZGVmYXVsdCB0aGlzIGNvbXBvbmVudCB3aWxsIHNldCBjbGFzc2VzIG9uIGl0cyBlbGVtZW50IHdoZW4gYW55IG9mIHRoZSBmb2xsb3dpbmcgYXJndW1lbnRzCiAgICAgICAgYXJlIHRydXRoeToKICAgICAgICAgICAgICogYWN0aXZlCiAgICAgICAgKiBsb2FkaW5nCiAgICAgICAgKiBkaXNhYmxlZAogICAgICAgICAgICAgV2hlbiB0aGVzZSBhcmd1bWVudHMgYXJlIHRydXRoeSwgYSBjbGFzcyB3aXRoIHRoZSBzYW1lIG5hbWUgd2lsbCBiZSBzZXQgb24gdGhlIGVsZW1lbnQuIFdoZW4KICAgICAgICBmYWxzeSwgdGhlIGFzc29jaWF0ZWQgY2xhc3Mgd2lsbCBub3QgYmUgb24gdGhlIGVsZW1lbnQuCiAgICAgICAgICAgICBAcHJvcGVydHkgY2xhc3NOYW1lQmluZGluZ3MKICAgICAgICBAdHlwZSBBcnJheQogICAgICAgIEBkZWZhdWx0IFsnYWN0aXZlJywgJ2xvYWRpbmcnLCAnZGlzYWJsZWQnLCAnZW1iZXItdHJhbnNpdGlvbmluZy1pbicsICdlbWJlci10cmFuc2l0aW9uaW5nLW91dCddCiAgICAgICAgQHB1YmxpYwogICAgICAqLwogICAgICBjbGFzc05hbWVCaW5kaW5nczogWydhY3RpdmUnLCAnbG9hZGluZycsICdkaXNhYmxlZCcsICd0cmFuc2l0aW9uaW5nSW4nLCAndHJhbnNpdGlvbmluZ091dCddLAoKICAgICAgLyoqCiAgICAgICAgQnkgZGVmYXVsdCB0aGlzIGNvbXBvbmVudCByZXNwb25kcyB0byB0aGUgYGNsaWNrYCBldmVudC4gV2hlbiB0aGUgY29tcG9uZW50IGVsZW1lbnQgaXMgYW4KICAgICAgICBgPGE+YCBlbGVtZW50LCBhY3RpdmF0aW5nIHRoZSBsaW5rIGluIGFub3RoZXIgd2F5LCBzdWNoIGFzIHVzaW5nIHRoZSBrZXlib2FyZCwgdHJpZ2dlcnMgdGhlCiAgICAgICAgY2xpY2sgZXZlbnQuCiAgICAgICAgICAgICBAcHJvcGVydHkgZXZlbnROYW1lCiAgICAgICAgQHR5cGUgU3RyaW5nCiAgICAgICAgQGRlZmF1bHQgY2xpY2sKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBldmVudE5hbWU6ICdjbGljaycsCiAgICAgIC8vIHRoaXMgaXMgZG9jJ2VkIGhlcmUgc28gaXQgc2hvd3MgdXAgaW4gdGhlIGV2ZW50cwogICAgICAvLyBzZWN0aW9uIG9mIHRoZSBBUEkgZG9jdW1lbnRhdGlvbiwgd2hpY2ggaXMgd2hlcmUKICAgICAgLy8gcGVvcGxlIHdpbGwgbGlrZWx5IGdvIGxvb2tpbmcgZm9yIGl0LgoKICAgICAgLyoqCiAgICAgICAgVHJpZ2dlcnMgdGhlIGBMaW5rQ29tcG9uZW50YCdzIHJvdXRpbmcgYmVoYXZpb3IuIElmCiAgICAgICAgYGV2ZW50TmFtZWAgaXMgY2hhbmdlZCB0byBhIHZhbHVlIG90aGVyIHRoYW4gYGNsaWNrYAogICAgICAgIHRoZSByb3V0aW5nIGJlaGF2aW9yIHdpbGwgdHJpZ2dlciBvbiB0aGF0IGN1c3RvbSBldmVudAogICAgICAgIGluc3RlYWQuCiAgICAgICAgICAgICBAZXZlbnQgY2xpY2sKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwoKICAgICAgLyoqCiAgICAgICAgQW4gb3ZlcnJpZGFibGUgbWV0aG9kIGNhbGxlZCB3aGVuIGBMaW5rQ29tcG9uZW50YCBvYmplY3RzIGFyZSBpbnN0YW50aWF0ZWQuCiAgICAgICAgICAgICBFeGFtcGxlOgogICAgICAgICAgICAgYGBgYXBwL2NvbXBvbmVudHMvbXktbGluay5qcwogICAgICAgIGltcG9ydCBMaW5rQ29tcG9uZW50IGZyb20gJ0BlbWJlci9yb3V0aW5nL2xpbmstY29tcG9uZW50JzsKICAgICAgICAgICAgIGV4cG9ydCBkZWZhdWx0IExpbmtDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICAgIGluaXQoKSB7CiAgICAgICAgICAgIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cyk7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdFdmVudCBpcyAnICsgdGhpcy5nZXQoJ2V2ZW50TmFtZScpKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgICBgYGAKICAgICAgICAgICAgIE5PVEU6IElmIHlvdSBkbyBvdmVycmlkZSBgaW5pdGAgZm9yIGEgZnJhbWV3b3JrIGNsYXNzIGxpa2UgYENvbXBvbmVudGAsCiAgICAgICAgYmUgc3VyZSB0byBjYWxsIGB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpYCBpbiB5b3VyCiAgICAgICAgYGluaXRgIGRlY2xhcmF0aW9uISBJZiB5b3UgZG9uJ3QsIEVtYmVyIG1heSBub3QgaGF2ZSBhbiBvcHBvcnR1bml0eSB0bwogICAgICAgIGRvIGltcG9ydGFudCBzZXR1cCB3b3JrLCBhbmQgeW91J2xsIHNlZSBzdHJhbmdlIGJlaGF2aW9yIGluIHlvdXIKICAgICAgICBhcHBsaWNhdGlvbi4KICAgICAgICAgICAgIEBtZXRob2QgaW5pdAogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsgLy8gTWFwIGRlc2lyZWQgZXZlbnQgbmFtZSB0byBpbnZva2UgZnVuY3Rpb24KCgogICAgICAgIHZhciBldmVudE5hbWUgPSB0aGlzLmV2ZW50TmFtZTsKICAgICAgICB0aGlzLm9uKGV2ZW50TmFtZSwgdGhpcywgdGhpcy5faW52b2tlKTsKICAgICAgfSwKICAgICAgX3JvdXRpbmc6ICgwLCBfc2VydmljZS5pbmplY3QpKCctcm91dGluZycpLAogICAgICBfY3VycmVudFJvdXRlOiAoMCwgX21ldGFsLmFsaWFzKSgnX3JvdXRpbmcuY3VycmVudFJvdXRlTmFtZScpLAogICAgICBfY3VycmVudFJvdXRlclN0YXRlOiAoMCwgX21ldGFsLmFsaWFzKSgnX3JvdXRpbmcuY3VycmVudFN0YXRlJyksCiAgICAgIF90YXJnZXRSb3V0ZXJTdGF0ZTogKDAsIF9tZXRhbC5hbGlhcykoJ19yb3V0aW5nLnRhcmdldFN0YXRlJyksCiAgICAgIF9yb3V0ZTogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ3JvdXRlJywgJ19jdXJyZW50Um91dGVyU3RhdGUnLCBmdW5jdGlvbiBjb21wdXRlTGlua1RvQ29tcG9uZW50Um91dGUoKSB7CiAgICAgICAgdmFyIHJvdXRlID0gdGhpcy5yb3V0ZTsKICAgICAgICByZXR1cm4gcm91dGUgPT09IFVOREVGSU5FRCA/IHRoaXMuX2N1cnJlbnRSb3V0ZSA6IHJvdXRlOwogICAgICB9KSwKICAgICAgX21vZGVsczogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ21vZGVsJywgJ21vZGVscycsIGZ1bmN0aW9uIGNvbXB1dGVMaW5rVG9Db21wb25lbnRNb2RlbHMoKSB7CiAgICAgICAgdmFyIG1vZGVsID0gdGhpcy5tb2RlbCwKICAgICAgICAgICAgbW9kZWxzID0gdGhpcy5tb2RlbHM7CiAgICAgICAgKGZhbHNlICYmICEobW9kZWwgPT09IFVOREVGSU5FRCB8fCBtb2RlbHMgPT09IFVOREVGSU5FRCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgY2Fubm90IHByb3ZpZGUgYm90aCB0aGUgYEBtb2RlbGAgYW5kIGBAbW9kZWxzYCBhcmd1bWVudHMgdG8gdGhlIDxMaW5rVG8+IGNvbXBvbmVudC4nLCBtb2RlbCA9PT0gVU5ERUZJTkVEIHx8IG1vZGVscyA9PT0gVU5ERUZJTkVEKSk7CgogICAgICAgIGlmIChtb2RlbCAhPT0gVU5ERUZJTkVEKSB7CiAgICAgICAgICByZXR1cm4gW21vZGVsXTsKICAgICAgICB9IGVsc2UgaWYgKG1vZGVscyAhPT0gVU5ERUZJTkVEKSB7CiAgICAgICAgICAoZmFsc2UgJiYgIShBcnJheS5pc0FycmF5KG1vZGVscykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnVGhlIGBAbW9kZWxzYCBhcmd1bWVudCBtdXN0IGJlIGFuIGFycmF5LicsIEFycmF5LmlzQXJyYXkobW9kZWxzKSkpOwogICAgICAgICAgcmV0dXJuIG1vZGVsczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIFtdOwogICAgICAgIH0KICAgICAgfSksCiAgICAgIF9xdWVyeTogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ3F1ZXJ5JywgZnVuY3Rpb24gY29tcHV0ZUxpbmtUb0NvbXBvbmVudFF1ZXJ5KCkgewogICAgICAgIHZhciBxdWVyeSA9IHRoaXMucXVlcnk7CgogICAgICAgIGlmIChxdWVyeSA9PT0gVU5ERUZJTkVEKSB7CiAgICAgICAgICByZXR1cm4gRU1QVFlfUVVFUllfUEFSQU1TOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgcXVlcnkpOwogICAgICAgIH0KICAgICAgfSksCgogICAgICAvKioKICAgICAgICBBY2Nlc3NlZCBhcyBhIGNsYXNzbmFtZSBiaW5kaW5nIHRvIGFwcGx5IHRoZSBjb21wb25lbnQncyBgZGlzYWJsZWRDbGFzc2AKICAgICAgICBDU1MgYGNsYXNzYCB0byB0aGUgZWxlbWVudCB3aGVuIHRoZSBsaW5rIGlzIGRpc2FibGVkLgogICAgICAgICAgICAgV2hlbiBgdHJ1ZWAsIGludGVyYWN0aW9ucyB3aXRoIHRoZSBlbGVtZW50IHdpbGwgbm90IHRyaWdnZXIgcm91dGUgY2hhbmdlcy4KICAgICAgICBAcHJvcGVydHkgZGlzYWJsZWQKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBkaXNhYmxlZDogKDAsIF9tZXRhbC5jb21wdXRlZCkoewogICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KF9rZXkpIHsKICAgICAgICAgIC8vIGFsd2F5cyByZXR1cm5zIGZhbHNlIGZvciBgZ2V0YCBiZWNhdXNlIChkdWUgdG8gdGhlIGBzZXRgIGp1c3QgYmVsb3cpCiAgICAgICAgICAvLyB0aGUgY2FjaGVkIHJldHVybiB2YWx1ZSBmcm9tIHRoZSBzZXQgd2lsbCBwcmV2ZW50IHRoaXMgZ2V0dGVyIGZyb20gX2V2ZXJfCiAgICAgICAgICAvLyBiZWluZyBjYWxsZWQgYWZ0ZXIgYSBzZXQgaGFzIG9jY3VyZWQKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9LAogICAgICAgIHNldDogZnVuY3Rpb24gc2V0KF9rZXksIHZhbHVlJCQxKSB7CiAgICAgICAgICB0aGlzLl9pc0Rpc2FibGVkID0gdmFsdWUkJDE7CiAgICAgICAgICByZXR1cm4gdmFsdWUkJDEgPyB0aGlzLmRpc2FibGVkQ2xhc3MgOiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0pLAoKICAgICAgLyoqCiAgICAgICAgQWNjZXNzZWQgYXMgYSBjbGFzc25hbWUgYmluZGluZyB0byBhcHBseSB0aGUgY29tcG9uZW50J3MgYGFjdGl2ZUNsYXNzYAogICAgICAgIENTUyBgY2xhc3NgIHRvIHRoZSBlbGVtZW50IHdoZW4gdGhlIGxpbmsgaXMgYWN0aXZlLgogICAgICAgICAgICAgVGhpcyBjb21wb25lbnQgaXMgY29uc2lkZXJlZCBhY3RpdmUgd2hlbiBpdHMgYGN1cnJlbnRXaGVuYCBwcm9wZXJ0eSBpcyBgdHJ1ZWAKICAgICAgICBvciB0aGUgYXBwbGljYXRpb24ncyBjdXJyZW50IHJvdXRlIGlzIHRoZSByb3V0ZSB0aGlzIGNvbXBvbmVudCB3b3VsZCB0cmlnZ2VyCiAgICAgICAgdHJhbnNpdGlvbnMgaW50by4KICAgICAgICAgICAgIFRoZSBgY3VycmVudFdoZW5gIHByb3BlcnR5IGNhbiBtYXRjaCBhZ2FpbnN0IG11bHRpcGxlIHJvdXRlcyBieSBzZXBhcmF0aW5nCiAgICAgICAgcm91dGUgbmFtZXMgdXNpbmcgdGhlIGAgYCAoc3BhY2UpIGNoYXJhY3Rlci4KICAgICAgICAgICAgIEBwcm9wZXJ0eSBhY3RpdmUKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBhY3RpdmU6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKCdhY3RpdmVDbGFzcycsICdfYWN0aXZlJywgZnVuY3Rpb24gY29tcHV0ZUxpbmtUb0NvbXBvbmVudEFjdGl2ZUNsYXNzKCkgewogICAgICAgIHJldHVybiB0aGlzLl9hY3RpdmUgPyB0aGlzLmFjdGl2ZUNsYXNzIDogZmFsc2U7CiAgICAgIH0pLAogICAgICBfYWN0aXZlOiAoMCwgX21ldGFsLmNvbXB1dGVkKSgnX2N1cnJlbnRSb3V0ZXJTdGF0ZScsICdfcm91dGUnLCAnX21vZGVscycsICdfcXVlcnknLCAnbG9hZGluZycsICdjdXJyZW50LXdoZW4nLCBmdW5jdGlvbiBjb21wdXRlTGlua1RvQ29tcG9uZW50QWN0aXZlKCkgewogICAgICAgIHZhciBzdGF0ZSA9IHRoaXMuX2N1cnJlbnRSb3V0ZXJTdGF0ZTsKCiAgICAgICAgaWYgKHN0YXRlKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5faXNBY3RpdmUoc3RhdGUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9KSwKICAgICAgd2lsbEJlQWN0aXZlOiAoMCwgX21ldGFsLmNvbXB1dGVkKSgnX2N1cnJlbnRSb3V0ZXJTdGF0ZScsICdfdGFyZ2V0Um91dGVyU3RhdGUnLCAnX3JvdXRlJywgJ19tb2RlbHMnLCAnX3F1ZXJ5JywgJ2xvYWRpbmcnLCAnY3VycmVudC13aGVuJywgZnVuY3Rpb24gY29tcHV0ZUxpbmtUb0NvbXBvbmVudFdpbGxCZUFjdGl2ZSgpIHsKICAgICAgICB2YXIgY3VycmVudCA9IHRoaXMuX2N1cnJlbnRSb3V0ZXJTdGF0ZSwKICAgICAgICAgICAgdGFyZ2V0ID0gdGhpcy5fdGFyZ2V0Um91dGVyU3RhdGU7CgogICAgICAgIGlmIChjdXJyZW50ID09PSB0YXJnZXQpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9pc0FjdGl2ZSh0YXJnZXQpOwogICAgICB9KSwKICAgICAgX2lzQWN0aXZlOiBmdW5jdGlvbiBfaXNBY3RpdmUocm91dGVyU3RhdGUpIHsKICAgICAgICBpZiAodGhpcy5sb2FkaW5nKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICB2YXIgY3VycmVudFdoZW4gPSB0aGlzWydjdXJyZW50LXdoZW4nXTsKCiAgICAgICAgaWYgKHR5cGVvZiBjdXJyZW50V2hlbiA9PT0gJ2Jvb2xlYW4nKSB7CiAgICAgICAgICByZXR1cm4gY3VycmVudFdoZW47CiAgICAgICAgfQoKICAgICAgICB2YXIgaXNDdXJyZW50V2hlblNwZWNpZmllZCA9IEJvb2xlYW4oY3VycmVudFdoZW4pOwoKICAgICAgICBpZiAoaXNDdXJyZW50V2hlblNwZWNpZmllZCkgewogICAgICAgICAgY3VycmVudFdoZW4gPSBjdXJyZW50V2hlbi5zcGxpdCgnICcpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjdXJyZW50V2hlbiA9IFt0aGlzLl9yb3V0ZV07CiAgICAgICAgfQoKICAgICAgICB2YXIgbW9kZWxzID0gdGhpcy5fbW9kZWxzLAogICAgICAgICAgICBxdWVyeSA9IHRoaXMuX3F1ZXJ5LAogICAgICAgICAgICByb3V0aW5nID0gdGhpcy5fcm91dGluZzsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjdXJyZW50V2hlbi5sZW5ndGg7IGkrKykgewogICAgICAgICAgaWYgKHJvdXRpbmcuaXNBY3RpdmVGb3JSb3V0ZShtb2RlbHMsIHF1ZXJ5LCBjdXJyZW50V2hlbltpXSwgcm91dGVyU3RhdGUsIGlzQ3VycmVudFdoZW5TcGVjaWZpZWQpKSB7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9LAogICAgICB0cmFuc2l0aW9uaW5nSW46ICgwLCBfbWV0YWwuY29tcHV0ZWQpKCdfYWN0aXZlJywgJ3dpbGxCZUFjdGl2ZScsIGZ1bmN0aW9uIGNvbXB1dGVMaW5rVG9Db21wb25lbnRUcmFuc2l0aW9uaW5nSW4oKSB7CiAgICAgICAgaWYgKHRoaXMud2lsbEJlQWN0aXZlID09PSB0cnVlICYmICF0aGlzLl9hY3RpdmUpIHsKICAgICAgICAgIHJldHVybiAnZW1iZXItdHJhbnNpdGlvbmluZy1pbic7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0pLAogICAgICB0cmFuc2l0aW9uaW5nT3V0OiAoMCwgX21ldGFsLmNvbXB1dGVkKSgnX2FjdGl2ZScsICd3aWxsQmVBY3RpdmUnLCBmdW5jdGlvbiBjb21wdXRlTGlua1RvQ29tcG9uZW50VHJhbnNpdGlvbmluZ091dCgpIHsKICAgICAgICBpZiAodGhpcy53aWxsQmVBY3RpdmUgPT09IGZhbHNlICYmIHRoaXMuX2FjdGl2ZSkgewogICAgICAgICAgcmV0dXJuICdlbWJlci10cmFuc2l0aW9uaW5nLW91dCc7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0pLAoKICAgICAgLyoqCiAgICAgICAgRXZlbnQgaGFuZGxlciB0aGF0IGludm9rZXMgdGhlIGxpbmssIGFjdGl2YXRpbmcgdGhlIGFzc29jaWF0ZWQgcm91dGUuCiAgICAgICAgICAgICBAbWV0aG9kIF9pbnZva2UKICAgICAgICBAcGFyYW0ge0V2ZW50fSBldmVudAogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIF9pbnZva2U6IGZ1bmN0aW9uIF9pbnZva2UoZXZlbnQpIHsKICAgICAgICBpZiAoISgwLCBfdmlld3MuaXNTaW1wbGVDbGljaykoZXZlbnQpKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CgogICAgICAgIHZhciBidWJibGVzID0gdGhpcy5idWJibGVzLAogICAgICAgICAgICBwcmV2ZW50RGVmYXVsdCA9IHRoaXMucHJldmVudERlZmF1bHQ7CiAgICAgICAgdmFyIHRhcmdldCA9IHRoaXMuZWxlbWVudC50YXJnZXQ7CiAgICAgICAgdmFyIGlzU2VsZiA9ICF0YXJnZXQgfHwgdGFyZ2V0ID09PSAnX3NlbGYnOwoKICAgICAgICBpZiAocHJldmVudERlZmF1bHQgIT09IGZhbHNlICYmIGlzU2VsZikgewogICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsKICAgICAgICB9CgogICAgICAgIGlmIChidWJibGVzID09PSBmYWxzZSkgewogICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7CiAgICAgICAgfQoKICAgICAgICBpZiAodGhpcy5faXNEaXNhYmxlZCkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgaWYgKHRoaXMubG9hZGluZykgewogICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aAogICAgICAgICAgKGZhbHNlICYmICgwLCBfZGVidWcud2FybikoJ1RoaXMgbGluayBpcyBpbiBhbiBpbmFjdGl2ZSBsb2FkaW5nIHN0YXRlIGJlY2F1c2UgYXQgbGVhc3Qgb25lIG9mIGl0cyBtb2RlbHMgJyArICdjdXJyZW50bHkgaGFzIGEgbnVsbC91bmRlZmluZWQgdmFsdWUsIG9yIHRoZSBwcm92aWRlZCByb3V0ZSBuYW1lIGlzIGludmFsaWQuJywgZmFsc2UsIHsKICAgICAgICAgICAgaWQ6ICdlbWJlci1nbGltbWVyLmxpbmstdG8uaW5hY3RpdmUtbG9hZGluZy1zdGF0ZScKICAgICAgICAgIH0pKTsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CgogICAgICAgIGlmICghaXNTZWxmKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICB2YXIgcm91dGVOYW1lID0gdGhpcy5fcm91dGUsCiAgICAgICAgICAgIG1vZGVscyA9IHRoaXMuX21vZGVscywKICAgICAgICAgICAgcXVlcnlQYXJhbXMgPSB0aGlzLl9xdWVyeSwKICAgICAgICAgICAgc2hvdWxkUmVwbGFjZSA9IHRoaXMucmVwbGFjZTsKICAgICAgICB2YXIgcGF5bG9hZCA9IHsKICAgICAgICAgIHF1ZXJ5UGFyYW1zOiBxdWVyeVBhcmFtcywKICAgICAgICAgIHJvdXRlTmFtZTogcm91dGVOYW1lCiAgICAgICAgfTsKICAgICAgICAoMCwgX2luc3RydW1lbnRhdGlvbi5mbGFnZ2VkSW5zdHJ1bWVudCkoJ2ludGVyYWN0aW9uLmxpbmstdG8nLCBwYXlsb2FkLCB0aGlzLl9nZW5lcmF0ZVRyYW5zaXRpb24ocGF5bG9hZCwgcm91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zLCBzaG91bGRSZXBsYWNlKSk7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9LAogICAgICBfZ2VuZXJhdGVUcmFuc2l0aW9uOiBmdW5jdGlvbiBfZ2VuZXJhdGVUcmFuc2l0aW9uKHBheWxvYWQsIHF1YWxpZmllZFJvdXRlTmFtZSwgbW9kZWxzLCBxdWVyeVBhcmFtcywgc2hvdWxkUmVwbGFjZSkgewogICAgICAgIHZhciByb3V0aW5nID0gdGhpcy5fcm91dGluZzsKICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgICAgcGF5bG9hZC50cmFuc2l0aW9uID0gcm91dGluZy50cmFuc2l0aW9uVG8ocXVhbGlmaWVkUm91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zLCBzaG91bGRSZXBsYWNlKTsKICAgICAgICB9OwogICAgICB9LAoKICAgICAgLyoqCiAgICAgICAgU2V0cyB0aGUgZWxlbWVudCdzIGBocmVmYCBhdHRyaWJ1dGUgdG8gdGhlIHVybCBmb3IKICAgICAgICB0aGUgYExpbmtDb21wb25lbnRgJ3MgdGFyZ2V0ZWQgcm91dGUuCiAgICAgICAgICAgICBJZiB0aGUgYExpbmtDb21wb25lbnRgJ3MgYHRhZ05hbWVgIGlzIGNoYW5nZWQgdG8gYSB2YWx1ZSBvdGhlcgogICAgICAgIHRoYW4gYGFgLCB0aGlzIHByb3BlcnR5IHdpbGwgYmUgaWdub3JlZC4KICAgICAgICAgICAgIEBwcm9wZXJ0eSBocmVmCiAgICAgICAgQHByaXZhdGUKICAgICAgKi8KICAgICAgaHJlZjogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ19jdXJyZW50Um91dGVyU3RhdGUnLCAnX3JvdXRlJywgJ19tb2RlbHMnLCAnX3F1ZXJ5JywgJ3RhZ05hbWUnLCAnbG9hZGluZycsICdsb2FkaW5nSHJlZicsIGZ1bmN0aW9uIGNvbXB1dGVMaW5rVG9Db21wb25lbnRIcmVmKCkgewogICAgICAgIGlmICh0aGlzLnRhZ05hbWUgIT09ICdhJykgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgaWYgKHRoaXMubG9hZGluZykgewogICAgICAgICAgcmV0dXJuIHRoaXMubG9hZGluZ0hyZWY7CiAgICAgICAgfQoKICAgICAgICB2YXIgcm91dGUgPSB0aGlzLl9yb3V0ZSwKICAgICAgICAgICAgbW9kZWxzID0gdGhpcy5fbW9kZWxzLAogICAgICAgICAgICBxdWVyeSA9IHRoaXMuX3F1ZXJ5LAogICAgICAgICAgICByb3V0aW5nID0gdGhpcy5fcm91dGluZzsKCiAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgIC8qCiAgICAgICAgICAgKiBVbmZvcnR1bmF0ZWx5LCB0byBnZXQgZGVjZW50IGVycm9yIG1lc3NhZ2VzLCB3ZSBuZWVkIHRvIGRvIHRoaXMuCiAgICAgICAgICAgKiBJbiBzb21lIGZ1dHVyZSBzdGF0ZSB3ZSBzaG91bGQgYmUgYWJsZSB0byB1c2UgYSAiZmVhdHVyZSBmbGFnIgogICAgICAgICAgICogd2hpY2ggYWxsb3dzIHVzIHRvIHN0cmlwIHRoaXMgd2l0aG91dCBuZWVkaW5nIHRvIGNhbGwgaXQgdHdpY2UuCiAgICAgICAgICAgKgogICAgICAgICAgICogaWYgKGlzRGVidWdCdWlsZCgpKSB7CiAgICAgICAgICAgKiAgIC8vIERvIHRoZSB1c2VmdWwgZGVidWcgdGhpbmcsIHByb2JhYmx5IGluY2x1ZGluZyB0cnkvY2F0Y2guCiAgICAgICAgICAgKiB9IGVsc2UgewogICAgICAgICAgICogICAvLyBEbyB0aGUgcGVyZm9ybWFudCB0aGluZy4KICAgICAgICAgICAqIH0KICAgICAgICAgICAqLwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcmV0dXJuIHJvdXRpbmcuZ2VuZXJhdGVVUkwocm91dGUsIG1vZGVscywgcXVlcnkpOwogICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoCiAgICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBhdHRlbXB0ZWQgdG8gZ2VuZXJhdGUgYSBsaW5rIGZvciB0aGUgXCIiICsgdGhpcy5yb3V0ZSArICJcIiByb3V0ZSwgYnV0IGRpZCBub3QgIiArICJwYXNzIHRoZSBtb2RlbHMgcmVxdWlyZWQgZm9yIGdlbmVyYXRpbmcgaXRzIGR5bmFtaWMgc2VnbWVudHMuICIgKyBlLm1lc3NhZ2UpKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHJvdXRpbmcuZ2VuZXJhdGVVUkwocm91dGUsIG1vZGVscywgcXVlcnkpOwogICAgICAgIH0KICAgICAgfSksCiAgICAgIGxvYWRpbmc6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKCdfcm91dGUnLCAnX21vZGVsc0FyZUxvYWRlZCcsICdsb2FkaW5nQ2xhc3MnLCBmdW5jdGlvbiBjb21wdXRlTGlua1RvQ29tcG9uZW50TG9hZGluZygpIHsKICAgICAgICB2YXIgcm91dGUgPSB0aGlzLl9yb3V0ZSwKICAgICAgICAgICAgbG9hZGVkID0gdGhpcy5fbW9kZWxzQXJlTG9hZGVkOwoKICAgICAgICBpZiAoIWxvYWRlZCB8fCByb3V0ZSA9PT0gbnVsbCB8fCByb3V0ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5sb2FkaW5nQ2xhc3M7CiAgICAgICAgfQogICAgICB9KSwKICAgICAgX21vZGVsc0FyZUxvYWRlZDogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ19tb2RlbHMnLCBmdW5jdGlvbiBjb21wdXRlTGlua1RvQ29tcG9uZW50TW9kZWxzQXJlTG9hZGVkKCkgewogICAgICAgIHZhciBtb2RlbHMgPSB0aGlzLl9tb2RlbHM7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW9kZWxzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICB2YXIgbW9kZWwgPSBtb2RlbHNbaV07CgogICAgICAgICAgaWYgKG1vZGVsID09PSBudWxsIHx8IG1vZGVsID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0pLAoKICAgICAgLyoqCiAgICAgICAgVGhlIGRlZmF1bHQgaHJlZiB2YWx1ZSB0byB1c2Ugd2hpbGUgYSBsaW5rLXRvIGlzIGxvYWRpbmcuCiAgICAgICAgT25seSBhcHBsaWVzIHdoZW4gdGFnTmFtZSBpcyAnYScKICAgICAgICAgICAgIEBwcm9wZXJ0eSBsb2FkaW5nSHJlZgogICAgICAgIEB0eXBlIFN0cmluZwogICAgICAgIEBkZWZhdWx0ICMKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBsb2FkaW5nSHJlZjogJyMnLAogICAgICBkaWRSZWNlaXZlQXR0cnM6IGZ1bmN0aW9uIGRpZFJlY2VpdmVBdHRycygpIHsKICAgICAgICB2YXIgZGlzYWJsZWRXaGVuID0gdGhpcy5kaXNhYmxlZFdoZW47CgogICAgICAgIGlmIChkaXNhYmxlZFdoZW4gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdGhpcy5zZXQoJ2Rpc2FibGVkJywgZGlzYWJsZWRXaGVuKTsKICAgICAgICB9CgogICAgICAgIHZhciBwYXJhbXMgPSB0aGlzLnBhcmFtczsKCiAgICAgICAgaWYgKCFwYXJhbXMgfHwgcGFyYW1zLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgKGZhbHNlICYmICEoISh0aGlzLnJvdXRlID09PSBVTkRFRklORUQgJiYgdGhpcy5tb2RlbCA9PT0gVU5ERUZJTkVEICYmIHRoaXMubW9kZWxzID09PSBVTkRFRklORUQgJiYgdGhpcy5xdWVyeSA9PT0gVU5ERUZJTkVEKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgbXVzdCBwcm92aWRlIGF0IGxlYXN0IG9uZSBvZiB0aGUgYEByb3V0ZWAsIGBAbW9kZWxgLCBgQG1vZGVsc2Agb3IgYEBxdWVyeWAgYXJndW1lbnQgdG8gYDxMaW5rVG8+YC4nLCAhKHRoaXMucm91dGUgPT09IFVOREVGSU5FRCAmJiB0aGlzLm1vZGVsID09PSBVTkRFRklORUQgJiYgdGhpcy5tb2RlbHMgPT09IFVOREVGSU5FRCAmJiB0aGlzLnF1ZXJ5ID09PSBVTkRFRklORUQpKSk7CgogICAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICAgJiYgdGhpcy5xdWVyeSA9PT0gVU5ERUZJTkVEKSB7CiAgICAgICAgICAgIHZhciBtb2RlbHMgPSB0aGlzLl9tb2RlbHM7CiAgICAgICAgICAgIHZhciBsYXN0TW9kZWwgPSBtb2RlbHMubGVuZ3RoID4gMCAmJiBtb2RlbHNbbW9kZWxzLmxlbmd0aCAtIDFdOwogICAgICAgICAgICAoZmFsc2UgJiYgISghKGxhc3RNb2RlbCAmJiBsYXN0TW9kZWwuaXNRdWVyeVBhcmFtcykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnVGhlIGAocXVlcnktcGFyYW1zKWAgaGVscGVyIGNhbiBvbmx5IGJlIHVzZWQgd2hlbiBpbnZva2luZyB0aGUgYHt7bGluay10b319YCBjb21wb25lbnQuJywgIShsYXN0TW9kZWwgJiYgbGFzdE1vZGVsLmlzUXVlcnlQYXJhbXMpKSk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgcGFyYW1zID0gcGFyYW1zLnNsaWNlKCk7IC8vIFByb2Nlc3MgdGhlIHBvc2l0aW9uYWwgYXJndW1lbnRzLCBpbiBvcmRlci4KICAgICAgICAvLyAxLiBJbmxpbmUgbGluayB0aXRsZSBjb21lcyBmaXJzdCwgaWYgcHJlc2VudC4KCiAgICAgICAgaWYgKCF0aGlzW0hBU19CTE9DS10pIHsKICAgICAgICAgIHRoaXMuc2V0KCdsaW5rVGl0bGUnLCBwYXJhbXMuc2hpZnQoKSk7CiAgICAgICAgfSAvLyAyLiBUaGUgbGFzdCBhcmd1bWVudCBpcyBwb3NzaWJseSB0aGUgYHF1ZXJ5YCBvYmplY3QuCgoKICAgICAgICB2YXIgcXVlcnlQYXJhbXMgPSBwYXJhbXNbcGFyYW1zLmxlbmd0aCAtIDFdOwoKICAgICAgICBpZiAocXVlcnlQYXJhbXMgJiYgcXVlcnlQYXJhbXMuaXNRdWVyeVBhcmFtcykgewogICAgICAgICAgdGhpcy5zZXQoJ3F1ZXJ5JywgcGFyYW1zLnBvcCgpLnZhbHVlcyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuc2V0KCdxdWVyeScsIFVOREVGSU5FRCk7CiAgICAgICAgfSAvLyAzLiBJZiB0aGVyZSBpcyBhIGByb3V0ZWAsIGl0IGlzIG5vdyBhdCBpbmRleCAwLgoKCiAgICAgICAgaWYgKHBhcmFtcy5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHRoaXMuc2V0KCdyb3V0ZScsIFVOREVGSU5FRCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuc2V0KCdyb3V0ZScsIHBhcmFtcy5zaGlmdCgpKTsKICAgICAgICB9IC8vIDQuIEFueSByZW1haW5pbmcgaW5kaWNlcyAoaWYgYW55KSBhcmUgYG1vZGVsc2AuCgoKICAgICAgICB0aGlzLnNldCgnbW9kZWwnLCBVTkRFRklORUQpOwogICAgICAgIHRoaXMuc2V0KCdtb2RlbHMnLCBwYXJhbXMpOwogICAgICB9CiAgICB9KTsKCiAgICBMaW5rQ29tcG9uZW50LnRvU3RyaW5nID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gJ0BlbWJlci9yb3V0aW5nL2xpbmstY29tcG9uZW50JzsKICAgIH07CgogICAgTGlua0NvbXBvbmVudC5yZW9wZW5DbGFzcyh7CiAgICAgIHBvc2l0aW9uYWxQYXJhbXM6ICdwYXJhbXMnCiAgICB9KTsKICB9CiAgdmFyIExpbmtUb0NvbXBvbmVudCA9IExpbmtDb21wb25lbnQ7IC8vIEB0cy1jaGVjawoKICBfZXhwb3J0cy5MaW5rQ29tcG9uZW50ID0gTGlua1RvQ29tcG9uZW50OwogIHZhciBEZWJ1Z1N0YWNrOwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgdmFyIEVsZW1lbnQgPSBmdW5jdGlvbiBFbGVtZW50KG5hbWUpIHsKICAgICAgdGhpcy5uYW1lID0gbmFtZTsKICAgIH07CgogICAgdmFyIFRlbXBsYXRlRWxlbWVudCA9CiAgICAvKiNfX1BVUkVfXyovCiAgICBmdW5jdGlvbiAoX0VsZW1lbnQpIHsKICAgICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFRlbXBsYXRlRWxlbWVudCwgX0VsZW1lbnQpOwoKICAgICAgZnVuY3Rpb24gVGVtcGxhdGVFbGVtZW50KCkgewogICAgICAgIHJldHVybiBfRWxlbWVudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICAgIH0KCiAgICAgIHJldHVybiBUZW1wbGF0ZUVsZW1lbnQ7CiAgICB9KEVsZW1lbnQpOwoKICAgIHZhciBFbmdpbmVFbGVtZW50ID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uIChfRWxlbWVudDIpIHsKICAgICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEVuZ2luZUVsZW1lbnQsIF9FbGVtZW50Mik7CgogICAgICBmdW5jdGlvbiBFbmdpbmVFbGVtZW50KCkgewogICAgICAgIHJldHVybiBfRWxlbWVudDIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICB9CgogICAgICByZXR1cm4gRW5naW5lRWxlbWVudDsKICAgIH0oRWxlbWVudCk7IC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1zaGFkb3dlZC12YXJpYWJsZQoKCiAgICBEZWJ1Z1N0YWNrID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uICgpIHsKICAgICAgZnVuY3Rpb24gRGVidWdTdGFjaygpIHsKICAgICAgICB0aGlzLl9zdGFjayA9IFtdOwogICAgICB9CgogICAgICB2YXIgX3Byb3RvMTYgPSBEZWJ1Z1N0YWNrLnByb3RvdHlwZTsKCiAgICAgIF9wcm90bzE2LnB1c2ggPSBmdW5jdGlvbiBwdXNoKG5hbWUpIHsKICAgICAgICB0aGlzLl9zdGFjay5wdXNoKG5ldyBUZW1wbGF0ZUVsZW1lbnQobmFtZSkpOwogICAgICB9OwoKICAgICAgX3Byb3RvMTYucHVzaEVuZ2luZSA9IGZ1bmN0aW9uIHB1c2hFbmdpbmUobmFtZSkgewogICAgICAgIHRoaXMuX3N0YWNrLnB1c2gobmV3IEVuZ2luZUVsZW1lbnQobmFtZSkpOwogICAgICB9OwoKICAgICAgX3Byb3RvMTYucG9wID0gZnVuY3Rpb24gcG9wKCkgewogICAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5fc3RhY2sucG9wKCk7CgogICAgICAgIGlmIChlbGVtZW50KSB7CiAgICAgICAgICByZXR1cm4gZWxlbWVudC5uYW1lOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIF9wcm90bzE2LnBlZWsgPSBmdW5jdGlvbiBwZWVrKCkgewogICAgICAgIHZhciB0ZW1wbGF0ZSA9IHRoaXMuX2N1cnJlbnRUZW1wbGF0ZSgpOwoKICAgICAgICB2YXIgZW5naW5lID0gdGhpcy5fY3VycmVudEVuZ2luZSgpOwoKICAgICAgICBpZiAoZW5naW5lKSB7CiAgICAgICAgICByZXR1cm4gIlwiIiArIHRlbXBsYXRlICsgIlwiIChpbiBcIiIgKyBlbmdpbmUgKyAiXCIpIjsKICAgICAgICB9IGVsc2UgaWYgKHRlbXBsYXRlKSB7CiAgICAgICAgICByZXR1cm4gIlwiIiArIHRlbXBsYXRlICsgIlwiIjsKICAgICAgICB9CiAgICAgIH07CgogICAgICBfcHJvdG8xNi5fY3VycmVudFRlbXBsYXRlID0gZnVuY3Rpb24gX2N1cnJlbnRUZW1wbGF0ZSgpIHsKICAgICAgICByZXR1cm4gdGhpcy5fZ2V0Q3VycmVudEJ5VHlwZShUZW1wbGF0ZUVsZW1lbnQpOwogICAgICB9OwoKICAgICAgX3Byb3RvMTYuX2N1cnJlbnRFbmdpbmUgPSBmdW5jdGlvbiBfY3VycmVudEVuZ2luZSgpIHsKICAgICAgICByZXR1cm4gdGhpcy5fZ2V0Q3VycmVudEJ5VHlwZShFbmdpbmVFbGVtZW50KTsKICAgICAgfTsKCiAgICAgIF9wcm90bzE2Ll9nZXRDdXJyZW50QnlUeXBlID0gZnVuY3Rpb24gX2dldEN1cnJlbnRCeVR5cGUodHlwZSkgewogICAgICAgIGZvciAodmFyIGkgPSB0aGlzLl9zdGFjay5sZW5ndGg7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgICB2YXIgZWxlbWVudCA9IHRoaXMuX3N0YWNrW2ldOwoKICAgICAgICAgIGlmIChlbGVtZW50IGluc3RhbmNlb2YgdHlwZSkgewogICAgICAgICAgICByZXR1cm4gZWxlbWVudC5uYW1lOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfTsKCiAgICAgIHJldHVybiBEZWJ1Z1N0YWNrOwogICAgfSgpOwogIH0KCiAgdmFyIERlYnVnU3RhY2skMSA9IERlYnVnU3RhY2s7CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgVGhlIGB7eyNlYWNofX1gIGhlbHBlciBsb29wcyBvdmVyIGVsZW1lbnRzIGluIGEgY29sbGVjdGlvbi4gSXQgaXMgYW4gZXh0ZW5zaW9uCiAgICBvZiB0aGUgYmFzZSBIYW5kbGViYXJzIGB7eyNlYWNofX1gIGhlbHBlci4KICAKICAgIFRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIGB7eyNlYWNofX1gIGlzIHRvIHlpZWxkIGl0cyBpbm5lciBibG9jayBvbmNlIGZvciBldmVyeQogICAgaXRlbSBpbiBhbiBhcnJheSBwYXNzaW5nIHRoZSBpdGVtIGFzIHRoZSBmaXJzdCBibG9jayBwYXJhbWV0ZXIuCiAgCiAgICBBc3N1bWluZyB0aGUgYEBkZXZlbG9wZXJzYCBhcmd1bWVudCBjb250YWlucyB0aGlzIGFycmF5OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgW3sgbmFtZTogJ1llaHVkYScgfSx7IG5hbWU6ICdUb20nIH0sIHsgbmFtZTogJ1BhdWwnIH1dOwogICAgYGBgCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8dWw+CiAgICAgIHt7I2VhY2ggQGRldmVsb3BlcnMgYXMgfHBlcnNvbnx9fQogICAgICAgIDxsaT5IZWxsbywge3twZXJzb24ubmFtZX19ITwvbGk+CiAgICAgIHt7L2VhY2h9fQogICAgPC91bD4KICAgIGBgYAogIAogICAgVGhlIHNhbWUgcnVsZXMgYXBwbHkgdG8gYXJyYXlzIG9mIHByaW1pdGl2ZXMuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBbJ1llaHVkYScsICdUb20nLCAnUGF1bCddCiAgICBgYGAKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDx1bD4KICAgICAge3sjZWFjaCBAZGV2ZWxvcGVyTmFtZXMgYXMgfG5hbWV8fX0KICAgICAgICA8bGk+SGVsbG8sIHt7bmFtZX19ITwvbGk+CiAgICAgIHt7L2VhY2h9fQogICAgPC91bD4KICAgIGBgYAogIAogICAgRHVyaW5nIGl0ZXJhdGlvbiwgdGhlIGluZGV4IG9mIGVhY2ggaXRlbSBpbiB0aGUgYXJyYXkgaXMgcHJvdmlkZWQgYXMgYSBzZWNvbmQgYmxvY2sKICAgIHBhcmFtZXRlci4KICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDx1bD4KICAgICAge3sjZWFjaCBAZGV2ZWxvcGVycyBhcyB8cGVyc29uIGluZGV4fH19CiAgICAgICAgPGxpPkhlbGxvLCB7e3BlcnNvbi5uYW1lfX0hIFlvdSdyZSBudW1iZXIge3tpbmRleH19IGluIGxpbmU8L2xpPgogICAgICB7ey9lYWNofX0KICAgIDwvdWw+CiAgICBgYGAKICAKICAgICMjIyBTcGVjaWZ5aW5nIEtleXMKICAKICAgIEluIG9yZGVyIHRvIGltcHJvdmUgcmVuZGVyaW5nIHNwZWVkLCBFbWJlciB3aWxsIHRyeSB0byByZXVzZSB0aGUgRE9NIGVsZW1lbnRzCiAgICB3aGVyZSBwb3NzaWJsZS4gU3BlY2lmaWNhbGx5LCBpZiB0aGUgc2FtZSBpdGVtIGlzIHByZXNlbnQgaW4gdGhlIGFycmF5IGJvdGgKICAgIGJlZm9yZSBhbmQgYWZ0ZXIgdGhlIGNoYW5nZSwgaXRzIERPTSBvdXRwdXQgd2lsbCBiZSByZXVzZWQuCiAgCiAgICBUaGUgYGtleWAgb3B0aW9uIGlzIHVzZWQgdG8gdGVsbCBFbWJlciBob3cgdG8gZGV0ZXJtaW5lIGlmIHRoZSBpdGVtcyBpbiB0aGUKICAgIGFycmF5IGJlaW5nIGl0ZXJhdGVkIG92ZXIgd2l0aCBge3sjZWFjaH19YCBoYXMgY2hhbmdlZCBiZXR3ZWVuIHJlbmRlcnMuIEJ5CiAgICBkZWZhdWx0IHRoZSBpdGVtJ3Mgb2JqZWN0IGlkZW50aXR5IGlzIHVzZWQuCiAgCiAgICBUaGlzIGlzIHVzdWFsbHkgc3VmZmljaWVudCwgc28gaW4gbW9zdCBjYXNlcywgdGhlIGBrZXlgIG9wdGlvbiBpcyBzaW1wbHkgbm90CiAgICBuZWVkZWQuIEhvd2V2ZXIsIGluIHNvbWUgcmFyZSBjYXNlcywgdGhlIG9iamVjdHMnIGlkZW50aXRpZXMgbWF5IGNoYW5nZSBldmVuCiAgICB0aG91Z2ggdGhleSByZXByZXNlbnQgdGhlIHNhbWUgdW5kZXJseWluZyBkYXRhLgogIAogICAgRm9yIGV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBwZW9wbGUubWFwKHBlcnNvbiA9PiB7CiAgICAgIHJldHVybiB7IC4uLnBlcnNvbiwgdHlwZTogJ2RldmVsb3BlcicgfTsKICAgIH0pOwogICAgYGBgCiAgCiAgICBJbiB0aGlzIGNhc2UsIGVhY2ggdGltZSB0aGUgYHBlb3BsZWAgYXJyYXkgaXMgYG1hcGAtZWQgb3ZlciwgaXQgd2lsbCBwcm9kdWNlCiAgICBhbiBuZXcgYXJyYXkgd2l0aCBjb21wbGV0ZWx5IGRpZmZlcmVudCBvYmplY3RzIGJldHdlZW4gcmVuZGVycy4gSW4gdGhlc2UgY2FzZXMsCiAgICB5b3UgY2FuIGhlbHAgRW1iZXIgZGV0ZXJtaW5lIGhvdyB0aGVzZSBvYmplY3RzIHJlbGF0ZWQgdG8gZWFjaCBvdGhlciB3aXRoIHRoZQogICAgYGtleWAgb3B0aW9uOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPHVsPgogICAgICB7eyNlYWNoIEBkZXZlbG9wZXJzIGtleT0ibmFtZSIgYXMgfHBlcnNvbnx9fQogICAgICAgIDxsaT5IZWxsbywge3twZXJzb24ubmFtZX19ITwvbGk+CiAgICAgIHt7L2VhY2h9fQogICAgPC91bD4KICAgIGBgYAogIAogICAgQnkgZG9pbmcgc28sIEVtYmVyIHdpbGwgdXNlIHRoZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgc3BlY2lmaWVkIChgcGVyc29uLm5hbWVgCiAgICBpbiB0aGUgZXhhbXBsZSkgdG8gZmluZCBhICJtYXRjaCIgZnJvbSB0aGUgcHJldmlvdXMgcmVuZGVyLiBUaGF0IGlzLCBpZiBFbWJlcgogICAgaGFzIHByZXZpb3VzbHkgc2VlbiBhbiBvYmplY3QgZnJvbSB0aGUgYEBkZXZlbG9wZXJzYCBhcnJheSB3aXRoIGEgbWF0Y2hpbmcKICAgIG5hbWUsIGl0cyBET00gZWxlbWVudHMgd2lsbCBiZSByZS11c2VkLgogIAogICAgIyMjIHt7ZWxzZX19IGNvbmRpdGlvbgogIAogICAgYHt7I2VhY2h9fWAgY2FuIGhhdmUgYSBtYXRjaGluZyBge3tlbHNlfX1gLiBUaGUgY29udGVudHMgb2YgdGhpcyBibG9jayB3aWxsIHJlbmRlcgogICAgaWYgdGhlIGNvbGxlY3Rpb24gaXMgZW1wdHkuCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8dWw+CiAgICAgIHt7I2VhY2ggQGRldmVsb3BlcnMgYXMgfHBlcnNvbnx9fQogICAgICAgIDxsaT57e3BlcnNvbi5uYW1lfX0gaXMgYXZhaWxhYmxlITwvbGk+CiAgICAgIHt7ZWxzZX19CiAgICAgICAgPGxpPlNvcnJ5LCBub2JvZHkgaXMgYXZhaWxhYmxlIGZvciB0aGlzIHRhc2suPC9saT4KICAgICAge3svZWFjaH19CiAgICA8L3VsPgogICAgYGBgCiAgCiAgICBAbWV0aG9kIGVhY2gKICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwdWJsaWMKICAgKi8KCiAgLyoqCiAgICBUaGUgYHt7ZWFjaC1pbn19YCBoZWxwZXIgbG9vcHMgb3ZlciBwcm9wZXJ0aWVzIG9uIGFuIG9iamVjdC4KICAKICAgIEZvciBleGFtcGxlLCBpZiB0aGUgYEB1c2VyYCBhcmd1bWVudCBjb250YWlucyB0aGlzIG9iamVjdDoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIHsKICAgICAgIm5hbWUiOiAiU2hlbGx5IFNhaWxzIiwKICAgICAgImFnZSI6IDQyCiAgICB9CiAgICBgYGAKICAKICAgIFRoaXMgdGVtcGxhdGUgd291bGQgZGlzcGxheSBhbGwgcHJvcGVydGllcyBvbiB0aGUgYEB1c2VyYAogICAgb2JqZWN0IGluIGEgbGlzdDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDx1bD4KICAgIHt7I2VhY2gtaW4gQHVzZXIgYXMgfGtleSB2YWx1ZXx9fQogICAgICA8bGk+e3trZXl9fToge3t2YWx1ZX19PC9saT4KICAgIHt7L2VhY2gtaW59fQogICAgPC91bD4KICAgIGBgYAogIAogICAgT3V0cHV0dGluZyB0aGVpciBuYW1lIGFuZCBhZ2UuCiAgCiAgICBAbWV0aG9kIGVhY2gtaW4KICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwdWJsaWMKICAgIEBzaW5jZSAyLjEuMAogICovCgogIF9leHBvcnRzLkRlYnVnU3RhY2sgPSBEZWJ1Z1N0YWNrJDE7CiAgdmFyIEVBQ0hfSU5fUkVGRVJFTkNFID0gKDAsIF91dGlscy5zeW1ib2wpKCdFQUNIX0lOJyk7CgogIHZhciBFYWNoSW5SZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBFYWNoSW5SZWZlcmVuY2UoaW5uZXIpIHsKICAgICAgdGhpcy5pbm5lciA9IGlubmVyOwogICAgICB0aGlzLnRhZyA9IGlubmVyLnRhZzsKICAgICAgdGhpc1tFQUNIX0lOX1JFRkVSRU5DRV0gPSB0cnVlOwogICAgfQoKICAgIHZhciBfcHJvdG8xNyA9IEVhY2hJblJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMTcudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuaW5uZXIudmFsdWUoKTsKICAgIH07CgogICAgX3Byb3RvMTcuZ2V0ID0gZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICByZXR1cm4gdGhpcy5pbm5lci5nZXQoa2V5KTsKICAgIH07CgogICAgcmV0dXJuIEVhY2hJblJlZmVyZW5jZTsKICB9KCk7CgogIGZ1bmN0aW9uIGlzRWFjaEluKHJlZikgewogICAgcmV0dXJuIHJlZiAhPT0gbnVsbCAmJiB0eXBlb2YgcmVmID09PSAnb2JqZWN0JyAmJiByZWZbRUFDSF9JTl9SRUZFUkVOQ0VdOwogIH0KCiAgZnVuY3Rpb24gZWFjaEluKF92bSwgYXJncykgewogICAgcmV0dXJuIG5ldyBFYWNoSW5SZWZlcmVuY2UoYXJncy5wb3NpdGlvbmFsLmF0KDApKTsKICB9CgogIHZhciBJVEVSQVRPUl9LRVlfR1VJRCA9ICdiZTI3Nzc1Ny1iYmJlLTQ2MjAtOWZjYi0yMTNlZjQzM2NjYTInOwoKICBmdW5jdGlvbiBfaXRlcmFibGVGb3IocmVmLCBrZXlQYXRoKSB7CiAgICBpZiAoaXNFYWNoSW4ocmVmKSkgewogICAgICByZXR1cm4gbmV3IEVhY2hJbkl0ZXJhYmxlKHJlZiwga2V5UGF0aCB8fCAnQGtleScpOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG5ldyBFYWNoSXRlcmFibGUocmVmLCBrZXlQYXRoIHx8ICdAaWRlbnRpdHknKTsKICAgIH0KICB9CgogIHZhciBCb3VuZGVkSXRlcmF0b3IgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBCb3VuZGVkSXRlcmF0b3IobGVuZ3RoLCBrZXlGb3IpIHsKICAgICAgdGhpcy5sZW5ndGggPSBsZW5ndGg7CiAgICAgIHRoaXMua2V5Rm9yID0ga2V5Rm9yOwogICAgICB0aGlzLnBvc2l0aW9uID0gMDsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTggPSBCb3VuZGVkSXRlcmF0b3IucHJvdG90eXBlOwoKICAgIF9wcm90bzE4LmlzRW1wdHkgPSBmdW5jdGlvbiBpc0VtcHR5KCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9OwoKICAgIF9wcm90bzE4Lm1lbW9Gb3IgPSBmdW5jdGlvbiBtZW1vRm9yKHBvc2l0aW9uKSB7CiAgICAgIHJldHVybiBwb3NpdGlvbjsKICAgIH07CgogICAgX3Byb3RvMTgubmV4dCA9IGZ1bmN0aW9uIG5leHQoKSB7CiAgICAgIHZhciBsZW5ndGggPSB0aGlzLmxlbmd0aCwKICAgICAgICAgIGtleUZvciA9IHRoaXMua2V5Rm9yLAogICAgICAgICAgcG9zaXRpb24gPSB0aGlzLnBvc2l0aW9uOwoKICAgICAgaWYgKHBvc2l0aW9uID49IGxlbmd0aCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgdmFsdWUkJDEgPSB0aGlzLnZhbHVlRm9yKHBvc2l0aW9uKTsKICAgICAgdmFyIG1lbW8gPSB0aGlzLm1lbW9Gb3IocG9zaXRpb24pOwogICAgICB2YXIga2V5ID0ga2V5Rm9yKHZhbHVlJCQxLCBtZW1vLCBwb3NpdGlvbik7CiAgICAgIHRoaXMucG9zaXRpb24rKzsKICAgICAgcmV0dXJuIHsKICAgICAgICBrZXk6IGtleSwKICAgICAgICB2YWx1ZTogdmFsdWUkJDEsCiAgICAgICAgbWVtbzogbWVtbwogICAgICB9OwogICAgfTsKCiAgICByZXR1cm4gQm91bmRlZEl0ZXJhdG9yOwogIH0oKTsKCiAgdmFyIEFycmF5SXRlcmF0b3IgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0JvdW5kZWRJdGVyYXRvcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEFycmF5SXRlcmF0b3IsIF9Cb3VuZGVkSXRlcmF0b3IpOwoKICAgIGZ1bmN0aW9uIEFycmF5SXRlcmF0b3IoYXJyYXksIGxlbmd0aCwga2V5Rm9yKSB7CiAgICAgIHZhciBfdGhpczEyOwoKICAgICAgX3RoaXMxMiA9IF9Cb3VuZGVkSXRlcmF0b3IuY2FsbCh0aGlzLCBsZW5ndGgsIGtleUZvcikgfHwgdGhpczsKICAgICAgX3RoaXMxMi5hcnJheSA9IGFycmF5OwogICAgICByZXR1cm4gX3RoaXMxMjsKICAgIH0KCiAgICBBcnJheUl0ZXJhdG9yLmZyb20gPSBmdW5jdGlvbiBmcm9tKGFycmF5LCBrZXlGb3IpIHsKICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDsKCiAgICAgIGlmIChsZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gRU1QVFlfSVRFUkFUT1I7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyB0aGlzKGFycmF5LCBsZW5ndGgsIGtleUZvcik7CiAgICAgIH0KICAgIH07CgogICAgQXJyYXlJdGVyYXRvci5mcm9tRm9yRWFjaGFibGUgPSBmdW5jdGlvbiBmcm9tRm9yRWFjaGFibGUob2JqZWN0LCBrZXlGb3IpIHsKICAgICAgdmFyIGFycmF5ID0gW107CiAgICAgIG9iamVjdC5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgICAgcmV0dXJuIGFycmF5LnB1c2goaXRlbSk7CiAgICAgIH0pOwogICAgICByZXR1cm4gdGhpcy5mcm9tKGFycmF5LCBrZXlGb3IpOwogICAgfTsKCiAgICB2YXIgX3Byb3RvMTkgPSBBcnJheUl0ZXJhdG9yLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xOS52YWx1ZUZvciA9IGZ1bmN0aW9uIHZhbHVlRm9yKHBvc2l0aW9uKSB7CiAgICAgIHJldHVybiB0aGlzLmFycmF5W3Bvc2l0aW9uXTsKICAgIH07CgogICAgcmV0dXJuIEFycmF5SXRlcmF0b3I7CiAgfShCb3VuZGVkSXRlcmF0b3IpOwoKICB2YXIgRW1iZXJBcnJheUl0ZXJhdG9yID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Cb3VuZGVkSXRlcmF0b3IyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRW1iZXJBcnJheUl0ZXJhdG9yLCBfQm91bmRlZEl0ZXJhdG9yMik7CgogICAgZnVuY3Rpb24gRW1iZXJBcnJheUl0ZXJhdG9yKGFycmF5LCBsZW5ndGgsIGtleUZvcikgewogICAgICB2YXIgX3RoaXMxMzsKCiAgICAgIF90aGlzMTMgPSBfQm91bmRlZEl0ZXJhdG9yMi5jYWxsKHRoaXMsIGxlbmd0aCwga2V5Rm9yKSB8fCB0aGlzOwogICAgICBfdGhpczEzLmFycmF5ID0gYXJyYXk7CiAgICAgIHJldHVybiBfdGhpczEzOwogICAgfQoKICAgIEVtYmVyQXJyYXlJdGVyYXRvci5mcm9tID0gZnVuY3Rpb24gZnJvbShhcnJheSwga2V5Rm9yKSB7CiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7CgogICAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIEVNUFRZX0lURVJBVE9SOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBuZXcgdGhpcyhhcnJheSwgbGVuZ3RoLCBrZXlGb3IpOwogICAgICB9CiAgICB9OwoKICAgIHZhciBfcHJvdG8yMCA9IEVtYmVyQXJyYXlJdGVyYXRvci5wcm90b3R5cGU7CgogICAgX3Byb3RvMjAudmFsdWVGb3IgPSBmdW5jdGlvbiB2YWx1ZUZvcihwb3NpdGlvbikgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5vYmplY3RBdCkodGhpcy5hcnJheSwgcG9zaXRpb24pOwogICAgfTsKCiAgICByZXR1cm4gRW1iZXJBcnJheUl0ZXJhdG9yOwogIH0oQm91bmRlZEl0ZXJhdG9yKTsKCiAgdmFyIE9iamVjdEl0ZXJhdG9yID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Cb3VuZGVkSXRlcmF0b3IzKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoT2JqZWN0SXRlcmF0b3IsIF9Cb3VuZGVkSXRlcmF0b3IzKTsKCiAgICBmdW5jdGlvbiBPYmplY3RJdGVyYXRvcihrZXlzLCB2YWx1ZXMsIGxlbmd0aCwga2V5Rm9yKSB7CiAgICAgIHZhciBfdGhpczE0OwoKICAgICAgX3RoaXMxNCA9IF9Cb3VuZGVkSXRlcmF0b3IzLmNhbGwodGhpcywgbGVuZ3RoLCBrZXlGb3IpIHx8IHRoaXM7CiAgICAgIF90aGlzMTQua2V5cyA9IGtleXM7CiAgICAgIF90aGlzMTQudmFsdWVzID0gdmFsdWVzOwogICAgICByZXR1cm4gX3RoaXMxNDsKICAgIH0KCiAgICBPYmplY3RJdGVyYXRvci5mcm9tSW5kZXhhYmxlID0gZnVuY3Rpb24gZnJvbUluZGV4YWJsZShvYmosIGtleUZvcikgewogICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7CiAgICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDsKCiAgICAgIGlmIChsZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gRU1QVFlfSVRFUkFUT1I7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIHZhbHVlcyA9IFtdOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICB2YXIgdmFsdWUkJDEgPSB2b2lkIDA7CiAgICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTsKICAgICAgICAgIHZhbHVlJCQxID0gb2JqW2tleV07IC8vIEFkZCB0aGUgdGFnIG9mIHRoZSByZXR1cm5lZCB2YWx1ZSBpZiBpdCBpcyBhbiBhcnJheSwgc2luY2UgYXJyYXlzCiAgICAgICAgICAvLyBzaG91bGQgYWx3YXlzIGNhdXNlIHVwZGF0ZXMgaWYgdGhleSBhcmUgY29uc3VtZWQgYW5kIHRoZW4gY2hhbmdlZAoKICAgICAgICAgIGlmICh0cnVlCiAgICAgICAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICAgICAgICYmICgwLCBfbWV0YWwuaXNUcmFja2luZykoKSkgewogICAgICAgICAgICAoMCwgX21ldGFsLmNvbnN1bWUpKCgwLCBfbWV0YWwudGFnRm9yUHJvcGVydHkpKG9iaiwga2V5KSk7CgogICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSQkMSkgfHwgKDAsIF91dGlscy5pc0VtYmVyQXJyYXkpKHZhbHVlJCQxKSkgewogICAgICAgICAgICAgICgwLCBfbWV0YWwuY29uc3VtZSkoKDAsIF9tZXRhbC50YWdGb3JQcm9wZXJ0eSkodmFsdWUkJDEsICdbXScpKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQoKICAgICAgICAgIHZhbHVlcy5wdXNoKHZhbHVlJCQxKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBuZXcgdGhpcyhrZXlzLCB2YWx1ZXMsIGxlbmd0aCwga2V5Rm9yKTsKICAgICAgfQogICAgfTsKCiAgICBPYmplY3RJdGVyYXRvci5mcm9tRm9yRWFjaGFibGUgPSBmdW5jdGlvbiBmcm9tRm9yRWFjaGFibGUob2JqLCBrZXlGb3IpIHsKICAgICAgdmFyIF9hcmd1bWVudHMgPSBhcmd1bWVudHM7CiAgICAgIHZhciBrZXlzID0gW107CiAgICAgIHZhciB2YWx1ZXMgPSBbXTsKICAgICAgdmFyIGxlbmd0aCA9IDA7CiAgICAgIHZhciBpc01hcExpa2UgPSBmYWxzZTsKICAgICAgb2JqLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlJCQxLCBrZXkpIHsKICAgICAgICBpc01hcExpa2UgPSBpc01hcExpa2UgfHwgX2FyZ3VtZW50cy5sZW5ndGggPj0gMjsKCiAgICAgICAgaWYgKGlzTWFwTGlrZSkgewogICAgICAgICAga2V5cy5wdXNoKGtleSk7CiAgICAgICAgfQoKICAgICAgICB2YWx1ZXMucHVzaCh2YWx1ZSQkMSk7CiAgICAgICAgbGVuZ3RoKys7CiAgICAgIH0pOwoKICAgICAgaWYgKGxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybiBFTVBUWV9JVEVSQVRPUjsKICAgICAgfSBlbHNlIGlmIChpc01hcExpa2UpIHsKICAgICAgICByZXR1cm4gbmV3IHRoaXMoa2V5cywgdmFsdWVzLCBsZW5ndGgsIGtleUZvcik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyBBcnJheUl0ZXJhdG9yKHZhbHVlcywgbGVuZ3RoLCBrZXlGb3IpOwogICAgICB9CiAgICB9OwoKICAgIHZhciBfcHJvdG8yMSA9IE9iamVjdEl0ZXJhdG9yLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yMS52YWx1ZUZvciA9IGZ1bmN0aW9uIHZhbHVlRm9yKHBvc2l0aW9uKSB7CiAgICAgIHJldHVybiB0aGlzLnZhbHVlc1twb3NpdGlvbl07CiAgICB9OwoKICAgIF9wcm90bzIxLm1lbW9Gb3IgPSBmdW5jdGlvbiBtZW1vRm9yKHBvc2l0aW9uKSB7CiAgICAgIHJldHVybiB0aGlzLmtleXNbcG9zaXRpb25dOwogICAgfTsKCiAgICByZXR1cm4gT2JqZWN0SXRlcmF0b3I7CiAgfShCb3VuZGVkSXRlcmF0b3IpOwoKICB2YXIgTmF0aXZlSXRlcmF0b3IgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBOYXRpdmVJdGVyYXRvcihpdGVyYWJsZSwgcmVzdWx0LCBrZXlGb3IpIHsKICAgICAgdGhpcy5pdGVyYWJsZSA9IGl0ZXJhYmxlOwogICAgICB0aGlzLnJlc3VsdCA9IHJlc3VsdDsKICAgICAgdGhpcy5rZXlGb3IgPSBrZXlGb3I7CiAgICAgIHRoaXMucG9zaXRpb24gPSAwOwogICAgfQoKICAgIE5hdGl2ZUl0ZXJhdG9yLmZyb20gPSBmdW5jdGlvbiBmcm9tKGl0ZXJhYmxlLCBrZXlGb3IpIHsKICAgICAgdmFyIGl0ZXJhdG9yID0gaXRlcmFibGVbU3ltYm9sLml0ZXJhdG9yXSgpOwogICAgICB2YXIgcmVzdWx0ID0gaXRlcmF0b3IubmV4dCgpOwogICAgICB2YXIgdmFsdWUkJDEgPSByZXN1bHQudmFsdWUsCiAgICAgICAgICBkb25lID0gcmVzdWx0LmRvbmU7CgogICAgICBpZiAoZG9uZSkgewogICAgICAgIHJldHVybiBFTVBUWV9JVEVSQVRPUjsKICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHZhbHVlJCQxKSAmJiB2YWx1ZSQkMS5sZW5ndGggPT09IDIpIHsKICAgICAgICByZXR1cm4gbmV3IHRoaXMoaXRlcmF0b3IsIHJlc3VsdCwga2V5Rm9yKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbmV3IEFycmF5TGlrZU5hdGl2ZUl0ZXJhdG9yKGl0ZXJhdG9yLCByZXN1bHQsIGtleUZvcik7CiAgICAgIH0KICAgIH07CgogICAgdmFyIF9wcm90bzIyID0gTmF0aXZlSXRlcmF0b3IucHJvdG90eXBlOwoKICAgIF9wcm90bzIyLmlzRW1wdHkgPSBmdW5jdGlvbiBpc0VtcHR5KCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9OwoKICAgIF9wcm90bzIyLm5leHQgPSBmdW5jdGlvbiBuZXh0KCkgewogICAgICB2YXIgaXRlcmFibGUgPSB0aGlzLml0ZXJhYmxlLAogICAgICAgICAgcmVzdWx0ID0gdGhpcy5yZXN1bHQsCiAgICAgICAgICBwb3NpdGlvbiA9IHRoaXMucG9zaXRpb24sCiAgICAgICAgICBrZXlGb3IgPSB0aGlzLmtleUZvcjsKCiAgICAgIGlmIChyZXN1bHQuZG9uZSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgdmFsdWUkJDEgPSB0aGlzLnZhbHVlRm9yKHJlc3VsdCwgcG9zaXRpb24pOwogICAgICB2YXIgbWVtbyA9IHRoaXMubWVtb0ZvcihyZXN1bHQsIHBvc2l0aW9uKTsKICAgICAgdmFyIGtleSA9IGtleUZvcih2YWx1ZSQkMSwgbWVtbywgcG9zaXRpb24pOwogICAgICB0aGlzLnBvc2l0aW9uKys7CiAgICAgIHRoaXMucmVzdWx0ID0gaXRlcmFibGUubmV4dCgpOwogICAgICByZXR1cm4gewogICAgICAgIGtleToga2V5LAogICAgICAgIHZhbHVlOiB2YWx1ZSQkMSwKICAgICAgICBtZW1vOiBtZW1vCiAgICAgIH07CiAgICB9OwoKICAgIHJldHVybiBOYXRpdmVJdGVyYXRvcjsKICB9KCk7CgogIHZhciBBcnJheUxpa2VOYXRpdmVJdGVyYXRvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfTmF0aXZlSXRlcmF0b3IpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShBcnJheUxpa2VOYXRpdmVJdGVyYXRvciwgX05hdGl2ZUl0ZXJhdG9yKTsKCiAgICBmdW5jdGlvbiBBcnJheUxpa2VOYXRpdmVJdGVyYXRvcigpIHsKICAgICAgcmV0dXJuIF9OYXRpdmVJdGVyYXRvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzIzID0gQXJyYXlMaWtlTmF0aXZlSXRlcmF0b3IucHJvdG90eXBlOwoKICAgIF9wcm90bzIzLnZhbHVlRm9yID0gZnVuY3Rpb24gdmFsdWVGb3IocmVzdWx0KSB7CiAgICAgIHJldHVybiByZXN1bHQudmFsdWU7CiAgICB9OwoKICAgIF9wcm90bzIzLm1lbW9Gb3IgPSBmdW5jdGlvbiBtZW1vRm9yKF9yZXN1bHQsIHBvc2l0aW9uKSB7CiAgICAgIHJldHVybiBwb3NpdGlvbjsKICAgIH07CgogICAgcmV0dXJuIEFycmF5TGlrZU5hdGl2ZUl0ZXJhdG9yOwogIH0oTmF0aXZlSXRlcmF0b3IpOwoKICB2YXIgTWFwTGlrZU5hdGl2ZUl0ZXJhdG9yID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9OYXRpdmVJdGVyYXRvcjIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShNYXBMaWtlTmF0aXZlSXRlcmF0b3IsIF9OYXRpdmVJdGVyYXRvcjIpOwoKICAgIGZ1bmN0aW9uIE1hcExpa2VOYXRpdmVJdGVyYXRvcigpIHsKICAgICAgcmV0dXJuIF9OYXRpdmVJdGVyYXRvcjIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8yNCA9IE1hcExpa2VOYXRpdmVJdGVyYXRvci5wcm90b3R5cGU7CgogICAgX3Byb3RvMjQudmFsdWVGb3IgPSBmdW5jdGlvbiB2YWx1ZUZvcihyZXN1bHQpIHsKICAgICAgcmV0dXJuIHJlc3VsdC52YWx1ZVsxXTsKICAgIH07CgogICAgX3Byb3RvMjQubWVtb0ZvciA9IGZ1bmN0aW9uIG1lbW9Gb3IocmVzdWx0KSB7CiAgICAgIHJldHVybiByZXN1bHQudmFsdWVbMF07CiAgICB9OwoKICAgIHJldHVybiBNYXBMaWtlTmF0aXZlSXRlcmF0b3I7CiAgfShOYXRpdmVJdGVyYXRvcik7CgogIHZhciBFTVBUWV9JVEVSQVRPUiA9IHsKICAgIGlzRW1wdHk6IGZ1bmN0aW9uIGlzRW1wdHkoKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSwKICAgIG5leHQ6IGZ1bmN0aW9uIG5leHQoKSB7CiAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0Nhbm5vdCBjYWxsIG5leHQoKSBvbiBhbiBlbXB0eSBpdGVyYXRvcicpKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgfTsKCiAgdmFyIEVhY2hJbkl0ZXJhYmxlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRWFjaEluSXRlcmFibGUocmVmLCBrZXlQYXRoKSB7CiAgICAgIHRoaXMucmVmID0gcmVmOwogICAgICB0aGlzLmtleVBhdGggPSBrZXlQYXRoOwogICAgICB0aGlzLnZhbHVlVGFnID0gKDAsIF9yZWZlcmVuY2UuY3JlYXRlVXBkYXRhYmxlVGFnKSgpOwogICAgICB0aGlzLnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFtyZWYudGFnLCB0aGlzLnZhbHVlVGFnXSk7CiAgICB9CgogICAgdmFyIF9wcm90bzI1ID0gRWFjaEluSXRlcmFibGUucHJvdG90eXBlOwoKICAgIF9wcm90bzI1Lml0ZXJhdGUgPSBmdW5jdGlvbiBpdGVyYXRlKCkgewogICAgICB2YXIgcmVmID0gdGhpcy5yZWYsCiAgICAgICAgICB2YWx1ZVRhZyA9IHRoaXMudmFsdWVUYWc7CiAgICAgIHZhciBpdGVyYWJsZSA9IHJlZi52YWx1ZSgpOwogICAgICB2YXIgdGFnID0gKDAsIF9tZXRhbC50YWdGb3IpKGl0ZXJhYmxlKTsKCiAgICAgIGlmICgoMCwgX3V0aWxzLmlzUHJveHkpKGl0ZXJhYmxlKSkgewogICAgICAgIC8vIHRoaXMgaXMgYmVjYXVzZSB0aGUgZWFjaC1pbiBkb2Vzbid0IGFjdHVhbGx5IGdldChwcm94eSwgJ2tleScpIGJ1dCBieXBhc3NlcyBpdAogICAgICAgIC8vIGFuZCB0aGUgcHJveHkncyB0YWcgaXMgbGF6eSB1cGRhdGVkIG9uIGFjY2VzcwogICAgICAgIGl0ZXJhYmxlID0gKDAsIF9ydW50aW1lLl9jb250ZW50Rm9yKShpdGVyYWJsZSk7CiAgICAgIH0KCiAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkodmFsdWVUYWcsIHRhZyk7CgogICAgICBpZiAoIWlzSW5kZXhhYmxlKGl0ZXJhYmxlKSkgewogICAgICAgIHJldHVybiBFTVBUWV9JVEVSQVRPUjsKICAgICAgfQoKICAgICAgaWYgKEFycmF5LmlzQXJyYXkoaXRlcmFibGUpIHx8ICgwLCBfdXRpbHMuaXNFbWJlckFycmF5KShpdGVyYWJsZSkpIHsKICAgICAgICByZXR1cm4gT2JqZWN0SXRlcmF0b3IuZnJvbUluZGV4YWJsZShpdGVyYWJsZSwgdGhpcy5rZXlGb3IodHJ1ZSkpOwogICAgICB9IGVsc2UgaWYgKF91dGlscy5IQVNfTkFUSVZFX1NZTUJPTCAmJiBpc05hdGl2ZUl0ZXJhYmxlKGl0ZXJhYmxlKSkgewogICAgICAgIHJldHVybiBNYXBMaWtlTmF0aXZlSXRlcmF0b3IuZnJvbShpdGVyYWJsZSwgdGhpcy5rZXlGb3IoKSk7CiAgICAgIH0gZWxzZSBpZiAoaGFzRm9yRWFjaChpdGVyYWJsZSkpIHsKICAgICAgICByZXR1cm4gT2JqZWN0SXRlcmF0b3IuZnJvbUZvckVhY2hhYmxlKGl0ZXJhYmxlLCB0aGlzLmtleUZvcigpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gT2JqZWN0SXRlcmF0b3IuZnJvbUluZGV4YWJsZShpdGVyYWJsZSwgdGhpcy5rZXlGb3IodHJ1ZSkpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzI1LnZhbHVlUmVmZXJlbmNlRm9yID0gZnVuY3Rpb24gdmFsdWVSZWZlcmVuY2VGb3IoaXRlbSkgewogICAgICByZXR1cm4gbmV3IFVwZGF0YWJsZVJlZmVyZW5jZShpdGVtLnZhbHVlKTsKICAgIH07CgogICAgX3Byb3RvMjUudXBkYXRlVmFsdWVSZWZlcmVuY2UgPSBmdW5jdGlvbiB1cGRhdGVWYWx1ZVJlZmVyZW5jZShyZWYsIGl0ZW0pIHsKICAgICAgcmVmLnVwZGF0ZShpdGVtLnZhbHVlKTsKICAgIH07CgogICAgX3Byb3RvMjUubWVtb1JlZmVyZW5jZUZvciA9IGZ1bmN0aW9uIG1lbW9SZWZlcmVuY2VGb3IoaXRlbSkgewogICAgICByZXR1cm4gbmV3IFVwZGF0YWJsZVJlZmVyZW5jZShpdGVtLm1lbW8pOwogICAgfTsKCiAgICBfcHJvdG8yNS51cGRhdGVNZW1vUmVmZXJlbmNlID0gZnVuY3Rpb24gdXBkYXRlTWVtb1JlZmVyZW5jZShyZWYsIGl0ZW0pIHsKICAgICAgcmVmLnVwZGF0ZShpdGVtLm1lbW8pOwogICAgfTsKCiAgICBfcHJvdG8yNS5rZXlGb3IgPSBmdW5jdGlvbiBrZXlGb3IoaGFzVW5pcXVlS2V5cykgewogICAgICBpZiAoaGFzVW5pcXVlS2V5cyA9PT0gdm9pZCAwKSB7CiAgICAgICAgaGFzVW5pcXVlS2V5cyA9IGZhbHNlOwogICAgICB9CgogICAgICB2YXIga2V5UGF0aCA9IHRoaXMua2V5UGF0aDsKCiAgICAgIHN3aXRjaCAoa2V5UGF0aCkgewogICAgICAgIGNhc2UgJ0BrZXknOgogICAgICAgICAgcmV0dXJuIGhhc1VuaXF1ZUtleXMgPyBPYmplY3RLZXkgOiBVbmlxdWUoTWFwS2V5KTsKCiAgICAgICAgY2FzZSAnQGluZGV4JzoKICAgICAgICAgIHJldHVybiBJbmRleDsKCiAgICAgICAgY2FzZSAnQGlkZW50aXR5JzoKICAgICAgICAgIHJldHVybiBVbmlxdWUoSWRlbnRpdHkpOwoKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgKGZhbHNlICYmICEoa2V5UGF0aFswXSAhPT0gJ0AnKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkludmFsaWQga2V5OiAiICsga2V5UGF0aCwga2V5UGF0aFswXSAhPT0gJ0AnKSk7CiAgICAgICAgICByZXR1cm4gVW5pcXVlKEtleVBhdGgoa2V5UGF0aCkpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBFYWNoSW5JdGVyYWJsZTsKICB9KCk7CgogIHZhciBFYWNoSXRlcmFibGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBFYWNoSXRlcmFibGUocmVmLCBrZXlQYXRoKSB7CiAgICAgIHRoaXMucmVmID0gcmVmOwogICAgICB0aGlzLmtleVBhdGggPSBrZXlQYXRoOwogICAgICB0aGlzLnZhbHVlVGFnID0gKDAsIF9yZWZlcmVuY2UuY3JlYXRlVXBkYXRhYmxlVGFnKSgpOwogICAgICB0aGlzLnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFtyZWYudGFnLCB0aGlzLnZhbHVlVGFnXSk7CiAgICB9CgogICAgdmFyIF9wcm90bzI2ID0gRWFjaEl0ZXJhYmxlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yNi5pdGVyYXRlID0gZnVuY3Rpb24gaXRlcmF0ZSgpIHsKICAgICAgdmFyIHJlZiA9IHRoaXMucmVmLAogICAgICAgICAgdmFsdWVUYWcgPSB0aGlzLnZhbHVlVGFnOwogICAgICB2YXIgaXRlcmFibGUgPSByZWYudmFsdWUoKTsKICAgICAgKDAsIF9yZWZlcmVuY2UudXBkYXRlKSh2YWx1ZVRhZywgKDAsIF9tZXRhbC50YWdGb3JQcm9wZXJ0eSkoaXRlcmFibGUsICdbXScpKTsKCiAgICAgIGlmIChpdGVyYWJsZSA9PT0gbnVsbCB8fCB0eXBlb2YgaXRlcmFibGUgIT09ICdvYmplY3QnKSB7CiAgICAgICAgcmV0dXJuIEVNUFRZX0lURVJBVE9SOwogICAgICB9CgogICAgICB2YXIga2V5Rm9yID0gdGhpcy5rZXlGb3IoKTsKCiAgICAgIGlmIChBcnJheS5pc0FycmF5KGl0ZXJhYmxlKSkgewogICAgICAgIHJldHVybiBBcnJheUl0ZXJhdG9yLmZyb20oaXRlcmFibGUsIGtleUZvcik7CiAgICAgIH0gZWxzZSBpZiAoKDAsIF91dGlscy5pc0VtYmVyQXJyYXkpKGl0ZXJhYmxlKSkgewogICAgICAgIHJldHVybiBFbWJlckFycmF5SXRlcmF0b3IuZnJvbShpdGVyYWJsZSwga2V5Rm9yKTsKICAgICAgfSBlbHNlIGlmIChfdXRpbHMuSEFTX05BVElWRV9TWU1CT0wgJiYgaXNOYXRpdmVJdGVyYWJsZShpdGVyYWJsZSkpIHsKICAgICAgICByZXR1cm4gQXJyYXlMaWtlTmF0aXZlSXRlcmF0b3IuZnJvbShpdGVyYWJsZSwga2V5Rm9yKTsKICAgICAgfSBlbHNlIGlmIChoYXNGb3JFYWNoKGl0ZXJhYmxlKSkgewogICAgICAgIHJldHVybiBBcnJheUl0ZXJhdG9yLmZyb21Gb3JFYWNoYWJsZShpdGVyYWJsZSwga2V5Rm9yKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRU1QVFlfSVRFUkFUT1I7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMjYudmFsdWVSZWZlcmVuY2VGb3IgPSBmdW5jdGlvbiB2YWx1ZVJlZmVyZW5jZUZvcihpdGVtKSB7CiAgICAgIHJldHVybiBuZXcgVXBkYXRhYmxlUmVmZXJlbmNlKGl0ZW0udmFsdWUpOwogICAgfTsKCiAgICBfcHJvdG8yNi51cGRhdGVWYWx1ZVJlZmVyZW5jZSA9IGZ1bmN0aW9uIHVwZGF0ZVZhbHVlUmVmZXJlbmNlKHJlZiwgaXRlbSkgewogICAgICByZWYudXBkYXRlKGl0ZW0udmFsdWUpOwogICAgfTsKCiAgICBfcHJvdG8yNi5tZW1vUmVmZXJlbmNlRm9yID0gZnVuY3Rpb24gbWVtb1JlZmVyZW5jZUZvcihpdGVtKSB7CiAgICAgIHJldHVybiBuZXcgVXBkYXRhYmxlUmVmZXJlbmNlKGl0ZW0ubWVtbyk7CiAgICB9OwoKICAgIF9wcm90bzI2LnVwZGF0ZU1lbW9SZWZlcmVuY2UgPSBmdW5jdGlvbiB1cGRhdGVNZW1vUmVmZXJlbmNlKHJlZiwgaXRlbSkgewogICAgICByZWYudXBkYXRlKGl0ZW0ubWVtbyk7CiAgICB9OwoKICAgIF9wcm90bzI2LmtleUZvciA9IGZ1bmN0aW9uIGtleUZvcigpIHsKICAgICAgdmFyIGtleVBhdGggPSB0aGlzLmtleVBhdGg7CgogICAgICBzd2l0Y2ggKGtleVBhdGgpIHsKICAgICAgICBjYXNlICdAaW5kZXgnOgogICAgICAgICAgcmV0dXJuIEluZGV4OwoKICAgICAgICBjYXNlICdAaWRlbnRpdHknOgogICAgICAgICAgcmV0dXJuIFVuaXF1ZShJZGVudGl0eSk7CgogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAoZmFsc2UgJiYgIShrZXlQYXRoWzBdICE9PSAnQCcpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiSW52YWxpZCBrZXk6ICIgKyBrZXlQYXRoLCBrZXlQYXRoWzBdICE9PSAnQCcpKTsKICAgICAgICAgIHJldHVybiBVbmlxdWUoS2V5UGF0aChrZXlQYXRoKSk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEVhY2hJdGVyYWJsZTsKICB9KCk7CgogIGZ1bmN0aW9uIGhhc0ZvckVhY2godmFsdWUkJDEpIHsKICAgIHJldHVybiB0eXBlb2YgdmFsdWUkJDFbJ2ZvckVhY2gnXSA9PT0gJ2Z1bmN0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGlzTmF0aXZlSXRlcmFibGUodmFsdWUkJDEpIHsKICAgIHJldHVybiB0eXBlb2YgdmFsdWUkJDFbU3ltYm9sLml0ZXJhdG9yXSA9PT0gJ2Z1bmN0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGlzSW5kZXhhYmxlKHZhbHVlJCQxKSB7CiAgICByZXR1cm4gdmFsdWUkJDEgIT09IG51bGwgJiYgKHR5cGVvZiB2YWx1ZSQkMSA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIHZhbHVlJCQxID09PSAnZnVuY3Rpb24nKTsKICB9IC8vIFBvc2l0aW9uIGluIGFuIGFycmF5IGlzIGd1YXJlbnRlZWQgdG8gYmUgdW5pcXVlCgoKICBmdW5jdGlvbiBJbmRleChfdmFsdWUsIF9tZW1vLCBwb3NpdGlvbikgewogICAgcmV0dXJuIFN0cmluZyhwb3NpdGlvbik7CiAgfSAvLyBPYmplY3Qua2V5cyguLi4pIGlzIGd1YXJlbnRlZWQgdG8gYmUgc3RyaW5ncyBhbmQgdW5pcXVlCgoKICBmdW5jdGlvbiBPYmplY3RLZXkoX3ZhbHVlLCBtZW1vKSB7CiAgICByZXR1cm4gbWVtbzsKICB9IC8vIE1hcCBrZXlzIGNhbiBiZSBhbnkgb2JqZWN0cwoKCiAgZnVuY3Rpb24gTWFwS2V5KF92YWx1ZSwgbWVtbykgewogICAgcmV0dXJuIElkZW50aXR5KG1lbW8pOwogIH0KCiAgZnVuY3Rpb24gSWRlbnRpdHkodmFsdWUkJDEpIHsKICAgIHN3aXRjaCAodHlwZW9mIHZhbHVlJCQxKSB7CiAgICAgIGNhc2UgJ3N0cmluZyc6CiAgICAgICAgcmV0dXJuIHZhbHVlJCQxOwoKICAgICAgY2FzZSAnbnVtYmVyJzoKICAgICAgICByZXR1cm4gU3RyaW5nKHZhbHVlJCQxKTsKCiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuICgwLCBfdXRpbHMuZ3VpZEZvcikodmFsdWUkJDEpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gS2V5UGF0aChrZXlQYXRoKSB7CiAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiBTdHJpbmcoKDAsIF9tZXRhbC5nZXQpKHZhbHVlJCQxLCBrZXlQYXRoKSk7CiAgICB9OwogIH0KCiAgZnVuY3Rpb24gVW5pcXVlKGZ1bmMpIHsKICAgIHZhciBzZWVuID0ge307CiAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlJCQxLCBtZW1vLCBwb3NpdGlvbikgewogICAgICB2YXIga2V5ID0gZnVuYyh2YWx1ZSQkMSwgbWVtbywgcG9zaXRpb24pOwogICAgICB2YXIgY291bnQgPSBzZWVuW2tleV07CgogICAgICBpZiAoY291bnQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHNlZW5ba2V5XSA9IDA7CiAgICAgICAgcmV0dXJuIGtleTsKICAgICAgfSBlbHNlIHsKICAgICAgICBzZWVuW2tleV0gPSArK2NvdW50OwogICAgICAgIHJldHVybiAiIiArIGtleSArIElURVJBVE9SX0tFWV9HVUlEICsgY291bnQ7CiAgICAgIH0KICAgIH07CiAgfQogIC8qKgogIEBtb2R1bGUgQGVtYmVyL3RlbXBsYXRlCiAgKi8KCgogIHZhciBTYWZlU3RyaW5nID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gU2FmZVN0cmluZyhzdHJpbmcpIHsKICAgICAgdGhpcy5zdHJpbmcgPSBzdHJpbmc7CiAgICB9CgogICAgdmFyIF9wcm90bzI3ID0gU2FmZVN0cmluZy5wcm90b3R5cGU7CgogICAgX3Byb3RvMjcudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuICIiICsgdGhpcy5zdHJpbmc7CiAgICB9OwoKICAgIF9wcm90bzI3LnRvSFRNTCA9IGZ1bmN0aW9uIHRvSFRNTCgpIHsKICAgICAgcmV0dXJuIHRoaXMudG9TdHJpbmcoKTsKICAgIH07CgogICAgcmV0dXJuIFNhZmVTdHJpbmc7CiAgfSgpOwoKICBfZXhwb3J0cy5TYWZlU3RyaW5nID0gU2FmZVN0cmluZzsKICB2YXIgZXNjYXBlID0gewogICAgJyYnOiAnJmFtcDsnLAogICAgJzwnOiAnJmx0OycsCiAgICAnPic6ICcmZ3Q7JywKICAgICciJzogJyZxdW90OycsCiAgICAiJyI6ICcmI3gyNzsnLAogICAgJ2AnOiAnJiN4NjA7JywKICAgICc9JzogJyYjeDNEOycKICB9OwogIHZhciBwb3NzaWJsZSA9IC9bJjw+IidgPV0vOwogIHZhciBiYWRDaGFycyA9IC9bJjw+IidgPV0vZzsKCiAgZnVuY3Rpb24gZXNjYXBlQ2hhcihjaHIpIHsKICAgIHJldHVybiBlc2NhcGVbY2hyXTsKICB9CgogIGZ1bmN0aW9uIGVzY2FwZUV4cHJlc3Npb24oc3RyaW5nKSB7CiAgICBpZiAodHlwZW9mIHN0cmluZyAhPT0gJ3N0cmluZycpIHsKICAgICAgLy8gZG9uJ3QgZXNjYXBlIFNhZmVTdHJpbmdzLCBzaW5jZSB0aGV5J3JlIGFscmVhZHkgc2FmZQogICAgICBpZiAoc3RyaW5nICYmIHN0cmluZy50b0hUTUwpIHsKICAgICAgICByZXR1cm4gc3RyaW5nLnRvSFRNTCgpOwogICAgICB9IGVsc2UgaWYgKHN0cmluZyA9PT0gbnVsbCB8fCBzdHJpbmcgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiAnJzsKICAgICAgfSBlbHNlIGlmICghc3RyaW5nKSB7CiAgICAgICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpOwogICAgICB9IC8vIEZvcmNlIGEgc3RyaW5nIGNvbnZlcnNpb24gYXMgdGhpcyB3aWxsIGJlIGRvbmUgYnkgdGhlIGFwcGVuZCByZWdhcmRsZXNzIGFuZAogICAgICAvLyB0aGUgcmVnZXggdGVzdCB3aWxsIGRvIHRoaXMgdHJhbnNwYXJlbnRseSBiZWhpbmQgdGhlIHNjZW5lcywgY2F1c2luZyBpc3N1ZXMgaWYKICAgICAgLy8gYW4gb2JqZWN0J3MgdG8gc3RyaW5nIGhhcyBlc2NhcGVkIGNoYXJhY3RlcnMgaW4gaXQuCgoKICAgICAgc3RyaW5nID0gU3RyaW5nKHN0cmluZyk7CiAgICB9CgogICAgaWYgKCFwb3NzaWJsZS50ZXN0KHN0cmluZykpIHsKICAgICAgcmV0dXJuIHN0cmluZzsKICAgIH0KCiAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoYmFkQ2hhcnMsIGVzY2FwZUNoYXIpOwogIH0KICAvKioKICAgIE1hcmsgYSBzdHJpbmcgYXMgc2FmZSBmb3IgdW5lc2NhcGVkIG91dHB1dCB3aXRoIEVtYmVyIHRlbXBsYXRlcy4gSWYgeW91CiAgICByZXR1cm4gSFRNTCBmcm9tIGEgaGVscGVyLCB1c2UgdGhpcyBmdW5jdGlvbiB0bwogICAgZW5zdXJlIEVtYmVyJ3MgcmVuZGVyaW5nIGxheWVyIGRvZXMgbm90IGVzY2FwZSB0aGUgSFRNTC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGh0bWxTYWZlIH0gZnJvbSAnQGVtYmVyL3RlbXBsYXRlJzsKICAKICAgIGh0bWxTYWZlKCc8ZGl2PnNvbWVTdHJpbmc8L2Rpdj4nKQogICAgYGBgCiAgCiAgICBAbWV0aG9kIGh0bWxTYWZlCiAgICBAZm9yIEBlbWJlci90ZW1wbGF0ZQogICAgQHN0YXRpYwogICAgQHJldHVybiB7U2FmZVN0cmluZ30gQSBzdHJpbmcgdGhhdCB3aWxsIG5vdCBiZSBIVE1MIGVzY2FwZWQgYnkgSGFuZGxlYmFycy4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gaHRtbFNhZmUoc3RyKSB7CiAgICBpZiAoc3RyID09PSBudWxsIHx8IHN0ciA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHN0ciA9ICcnOwogICAgfSBlbHNlIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJykgewogICAgICBzdHIgPSBTdHJpbmcoc3RyKTsKICAgIH0KCiAgICByZXR1cm4gbmV3IFNhZmVTdHJpbmcoc3RyKTsKICB9CiAgLyoqCiAgICBEZXRlY3RzIGlmIGEgc3RyaW5nIHdhcyBkZWNvcmF0ZWQgdXNpbmcgYGh0bWxTYWZlYC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGh0bWxTYWZlLCBpc0hUTUxTYWZlIH0gZnJvbSAnQGVtYmVyL3RlbXBsYXRlJzsKICAKICAgIHZhciBwbGFpblN0cmluZyA9ICdwbGFpbiBzdHJpbmcnLAogICAgICAgIHNhZmVTdHJpbmcgPSBodG1sU2FmZSgnPGRpdj5zb21lVmFsdWU8L2Rpdj4nKTsKICAKICAgIGlzSFRNTFNhZmUocGxhaW5TdHJpbmcpOyAvLyBmYWxzZQogICAgaXNIVE1MU2FmZShzYWZlU3RyaW5nKTsgIC8vIHRydWUKICAgIGBgYAogIAogICAgQG1ldGhvZCBpc0hUTUxTYWZlCiAgICBAZm9yIEBlbWJlci90ZW1wbGF0ZQogICAgQHN0YXRpYwogICAgQHJldHVybiB7Qm9vbGVhbn0gYHRydWVgIGlmIHRoZSBzdHJpbmcgd2FzIGRlY29yYXRlZCB3aXRoIGBodG1sU2FmZWAsIGBmYWxzZWAgb3RoZXJ3aXNlLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpc0hUTUxTYWZlKHN0cikgewogICAgcmV0dXJuIHN0ciAhPT0gbnVsbCAmJiB0eXBlb2Ygc3RyID09PSAnb2JqZWN0JyAmJiB0eXBlb2Ygc3RyLnRvSFRNTCA9PT0gJ2Z1bmN0aW9uJzsKICB9CiAgLyogZ2xvYmFscyBtb2R1bGUsIFVSTCAqLwoKCiAgdmFyIG5vZGVVUkw7CiAgdmFyIHBhcnNpbmdOb2RlOwoKICBmdW5jdGlvbiBpbnN0YWxsUHJvdG9jb2xGb3JVUkwoZW52aXJvbm1lbnQpIHsKICAgIHZhciBwcm90b2NvbDsKCiAgICBpZiAoX2Jyb3dzZXJFbnZpcm9ubWVudC5oYXNET00pIHsKICAgICAgcHJvdG9jb2wgPSBicm93c2VyUHJvdG9jb2xGb3JVUkwuY2FsbChlbnZpcm9ubWVudCwgJ2Zvb2JhcjpiYXonKTsKICAgIH0gLy8gVGVzdCB0byBzZWUgaWYgb3VyIERPTSBpbXBsZW1lbnRhdGlvbiBwYXJzZXMKICAgIC8vIGFuZCBub3JtYWxpemVzIFVSTHMuCgoKICAgIGlmIChwcm90b2NvbCA9PT0gJ2Zvb2JhcjonKSB7CiAgICAgIC8vIFN3YXAgaW4gdGhlIG1ldGhvZCB0aGF0IGRvZXNuJ3QgZG8gdGhpcyB0ZXN0IG5vdyB0aGF0CiAgICAgIC8vIHdlIGtub3cgaXQgd29ya3MuCiAgICAgIGVudmlyb25tZW50LnByb3RvY29sRm9yVVJMID0gYnJvd3NlclByb3RvY29sRm9yVVJMOwogICAgfSBlbHNlIGlmICh0eXBlb2YgVVJMID09PSAnb2JqZWN0JykgewogICAgICAvLyBVUkwgZ2xvYmFsbHkgcHJvdmlkZWQsIGxpa2VseSBmcm9tIEZhc3RCb290J3Mgc2FuZGJveAogICAgICBub2RlVVJMID0gVVJMOwogICAgICBlbnZpcm9ubWVudC5wcm90b2NvbEZvclVSTCA9IG5vZGVQcm90b2NvbEZvclVSTDsKICAgIH0gZWxzZSBpZiAodHlwZW9mIG1vZHVsZSAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtb2R1bGUucmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAvLyBPdGhlcndpc2UsIHdlIG5lZWQgdG8gZmFsbCBiYWNrIHRvIG91ciBvd24gVVJMIHBhcnNpbmcuCiAgICAgIC8vIEdsb2JhbCBgcmVxdWlyZWAgaXMgc2hhZG93ZWQgYnkgRW1iZXIncyBsb2FkZXIgc28gd2UgaGF2ZSB0byB1c2UgdGhlIGZ1bGx5CiAgICAgIC8vIHF1YWxpZmllZCBgbW9kdWxlLnJlcXVpcmVgLgogICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tcmVxdWlyZS1pbXBvcnRzCiAgICAgIG5vZGVVUkwgPSBtb2R1bGUucmVxdWlyZSgndXJsJyk7CiAgICAgIGVudmlyb25tZW50LnByb3RvY29sRm9yVVJMID0gbm9kZVByb3RvY29sRm9yVVJMOwogICAgfSBlbHNlIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgZmluZCB2YWxpZCBVUkwgcGFyc2luZyBtZWNoYW5pc20gZm9yIFVSTCBTYW5pdGl6YXRpb24nKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGJyb3dzZXJQcm90b2NvbEZvclVSTCh1cmwpIHsKICAgIGlmICghcGFyc2luZ05vZGUpIHsKICAgICAgcGFyc2luZ05vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7CiAgICB9CgogICAgcGFyc2luZ05vZGUuaHJlZiA9IHVybDsKICAgIHJldHVybiBwYXJzaW5nTm9kZS5wcm90b2NvbDsKICB9CgogIGZ1bmN0aW9uIG5vZGVQcm90b2NvbEZvclVSTCh1cmwpIHsKICAgIHZhciBwcm90b2NvbCA9IG51bGw7CgogICAgaWYgKHR5cGVvZiB1cmwgPT09ICdzdHJpbmcnKSB7CiAgICAgIHByb3RvY29sID0gbm9kZVVSTC5wYXJzZSh1cmwpLnByb3RvY29sOwogICAgfQoKICAgIHJldHVybiBwcm90b2NvbCA9PT0gbnVsbCA/ICc6JyA6IHByb3RvY29sOwogIH0KCiAgdmFyIEVudmlyb25tZW50JDEgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Vudmlyb25tZW50KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRW52aXJvbm1lbnQkMSwgX0Vudmlyb25tZW50KTsKCiAgICBmdW5jdGlvbiBFbnZpcm9ubWVudCQxKGluamVjdGlvbnMpIHsKICAgICAgdmFyIF90aGlzMTU7CgogICAgICBfdGhpczE1ID0gX0Vudmlyb25tZW50LmNhbGwodGhpcywgaW5qZWN0aW9ucykgfHwgdGhpczsKICAgICAgX3RoaXMxNS5pblRyYW5zYWN0aW9uID0gZmFsc2U7CiAgICAgIF90aGlzMTUub3duZXIgPSBpbmplY3Rpb25zW19vd25lci5PV05FUl07CiAgICAgIF90aGlzMTUuaXNJbnRlcmFjdGl2ZSA9IF90aGlzMTUub3duZXIubG9va3VwKCctZW52aXJvbm1lbnQ6bWFpbicpLmlzSW50ZXJhY3RpdmU7IC8vIGNhbiBiZSByZW1vdmVkIG9uY2UgaHR0cHM6Ly9naXRodWIuY29tL3RpbGRlaW8vZ2xpbW1lci9wdWxsLzMwNSBsYW5kcwoKICAgICAgX3RoaXMxNS5kZXN0cm95ZWRDb21wb25lbnRzID0gW107CiAgICAgIGluc3RhbGxQcm90b2NvbEZvclVSTCgoMCwgX2VtYmVyQmFiZWwuYXNzZXJ0VGhpc0luaXRpYWxpemVkKShfdGhpczE1KSk7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgX3RoaXMxNS5kZWJ1Z1N0YWNrID0gbmV3IERlYnVnU3RhY2skMSgpOwogICAgICB9CgogICAgICByZXR1cm4gX3RoaXMxNTsKICAgIH0KCiAgICBFbnZpcm9ubWVudCQxLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShvcHRpb25zKSB7CiAgICAgIHJldHVybiBuZXcgdGhpcyhvcHRpb25zKTsKICAgIH0gLy8gdGhpcyBnZXRzIGNsb2JiZXJlZCBieSBpbnN0YWxsUGxhdGZvcm1TcGVjaWZpY1Byb3RvY29sRm9yVVJMCiAgICAvLyBpdCByZWFsbHkgc2hvdWxkIGp1c3QgZGVsZWdhdGUgdG8gYSBwbGF0Zm9ybSBzcGVjaWZpYyBpbmplY3Rpb24KICAgIDsKCiAgICB2YXIgX3Byb3RvMjggPSBFbnZpcm9ubWVudCQxLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yOC5wcm90b2NvbEZvclVSTCA9IGZ1bmN0aW9uIHByb3RvY29sRm9yVVJMKHMpIHsKICAgICAgcmV0dXJuIHM7CiAgICB9OwoKICAgIF9wcm90bzI4LnRvQ29uZGl0aW9uYWxSZWZlcmVuY2UgPSBmdW5jdGlvbiB0b0NvbmRpdGlvbmFsUmVmZXJlbmNlKHJlZmVyZW5jZSkgewogICAgICByZXR1cm4gQ29uZGl0aW9uYWxSZWZlcmVuY2UkMS5jcmVhdGUocmVmZXJlbmNlKTsKICAgIH07CgogICAgX3Byb3RvMjguaXRlcmFibGVGb3IgPSBmdW5jdGlvbiBpdGVyYWJsZUZvcihyZWYsIGtleSkgewogICAgICByZXR1cm4gX2l0ZXJhYmxlRm9yKHJlZiwga2V5KTsKICAgIH07CgogICAgX3Byb3RvMjguc2NoZWR1bGVJbnN0YWxsTW9kaWZpZXIgPSBmdW5jdGlvbiBzY2hlZHVsZUluc3RhbGxNb2RpZmllcihtb2RpZmllciwgbWFuYWdlcikgewogICAgICBpZiAodGhpcy5pc0ludGVyYWN0aXZlKSB7CiAgICAgICAgX0Vudmlyb25tZW50LnByb3RvdHlwZS5zY2hlZHVsZUluc3RhbGxNb2RpZmllci5jYWxsKHRoaXMsIG1vZGlmaWVyLCBtYW5hZ2VyKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8yOC5zY2hlZHVsZVVwZGF0ZU1vZGlmaWVyID0gZnVuY3Rpb24gc2NoZWR1bGVVcGRhdGVNb2RpZmllcihtb2RpZmllciwgbWFuYWdlcikgewogICAgICBpZiAodGhpcy5pc0ludGVyYWN0aXZlKSB7CiAgICAgICAgX0Vudmlyb25tZW50LnByb3RvdHlwZS5zY2hlZHVsZVVwZGF0ZU1vZGlmaWVyLmNhbGwodGhpcywgbW9kaWZpZXIsIG1hbmFnZXIpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzI4LmRpZERlc3Ryb3kgPSBmdW5jdGlvbiBkaWREZXN0cm95KGRlc3Ryb3lhYmxlKSB7CiAgICAgIGRlc3Ryb3lhYmxlLmRlc3Ryb3koKTsKICAgIH07CgogICAgX3Byb3RvMjguYmVnaW4gPSBmdW5jdGlvbiBiZWdpbigpIHsKICAgICAgdGhpcy5pblRyYW5zYWN0aW9uID0gdHJ1ZTsKCiAgICAgIF9FbnZpcm9ubWVudC5wcm90b3R5cGUuYmVnaW4uY2FsbCh0aGlzKTsKICAgIH07CgogICAgX3Byb3RvMjguY29tbWl0ID0gZnVuY3Rpb24gY29tbWl0KCkgewogICAgICB2YXIgZGVzdHJveWVkQ29tcG9uZW50cyA9IHRoaXMuZGVzdHJveWVkQ29tcG9uZW50czsKICAgICAgdGhpcy5kZXN0cm95ZWRDb21wb25lbnRzID0gW107IC8vIGNvbXBvbmVudHMgcXVldWVkIGZvciBkZXN0cnVjdGlvbiBtdXN0IGJlIGRlc3Ryb3llZCBiZWZvcmUgZmlyaW5nCiAgICAgIC8vIGBkaWRDcmVhdGVgIHRvIHByZXZlbnQgZXJyb3JzIHdoZW4gcmVtb3ZpbmcgYW5kIGFkZGluZyBhIGNvbXBvbmVudAogICAgICAvLyB3aXRoIHRoZSBzYW1lIG5hbWUgKHdvdWxkIHRocm93IGFuIGVycm9yIHdoZW4gYWRkZWQgdG8gdmlldyByZWdpc3RyeSkKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVzdHJveWVkQ29tcG9uZW50cy5sZW5ndGg7IGkrKykgewogICAgICAgIGRlc3Ryb3llZENvbXBvbmVudHNbaV0uZGVzdHJveSgpOwogICAgICB9CgogICAgICB0cnkgewogICAgICAgIF9FbnZpcm9ubWVudC5wcm90b3R5cGUuY29tbWl0LmNhbGwodGhpcyk7CiAgICAgIH0gZmluYWxseSB7CiAgICAgICAgdGhpcy5pblRyYW5zYWN0aW9uID0gZmFsc2U7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEVudmlyb25tZW50JDE7CiAgfShfcnVudGltZTIuRW52aXJvbm1lbnQpOwoKICBfZXhwb3J0cy5FbnZpcm9ubWVudCA9IEVudmlyb25tZW50JDE7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICB2YXIgU3R5bGVBdHRyaWJ1dGVNYW5hZ2VyID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uIChfU2ltcGxlRHluYW1pY0F0dHJpYnUpIHsKICAgICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFN0eWxlQXR0cmlidXRlTWFuYWdlciwgX1NpbXBsZUR5bmFtaWNBdHRyaWJ1KTsKCiAgICAgIGZ1bmN0aW9uIFN0eWxlQXR0cmlidXRlTWFuYWdlcigpIHsKICAgICAgICByZXR1cm4gX1NpbXBsZUR5bmFtaWNBdHRyaWJ1LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgICAgfQoKICAgICAgdmFyIF9wcm90bzI5ID0gU3R5bGVBdHRyaWJ1dGVNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICAgIF9wcm90bzI5LnNldCA9IGZ1bmN0aW9uIHNldChkb20sIHZhbHVlJCQxLCBlbnYpIHsKICAgICAgICAoZmFsc2UgJiYgKDAsIF9kZWJ1Zy53YXJuKSgoMCwgX3ZpZXdzLmNvbnN0cnVjdFN0eWxlRGVwcmVjYXRpb25NZXNzYWdlKSh2YWx1ZSQkMSksIGZ1bmN0aW9uICgpIHsKICAgICAgICAgIGlmICh2YWx1ZSQkMSA9PT0gbnVsbCB8fCB2YWx1ZSQkMSA9PT0gdW5kZWZpbmVkIHx8IGlzSFRNTFNhZmUodmFsdWUkJDEpKSB7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9KCksIHsKICAgICAgICAgIGlkOiAnZW1iZXItaHRtbGJhcnMuc3R5bGUteHNzLXdhcm5pbmcnCiAgICAgICAgfSkpOwoKICAgICAgICBfU2ltcGxlRHluYW1pY0F0dHJpYnUucHJvdG90eXBlLnNldC5jYWxsKHRoaXMsIGRvbSwgdmFsdWUkJDEsIGVudik7CiAgICAgIH07CgogICAgICBfcHJvdG8yOS51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUodmFsdWUkJDEsIGVudikgewogICAgICAgIChmYWxzZSAmJiAoMCwgX2RlYnVnLndhcm4pKCgwLCBfdmlld3MuY29uc3RydWN0U3R5bGVEZXByZWNhdGlvbk1lc3NhZ2UpKHZhbHVlJCQxKSwgZnVuY3Rpb24gKCkgewogICAgICAgICAgaWYgKHZhbHVlJCQxID09PSBudWxsIHx8IHZhbHVlJCQxID09PSB1bmRlZmluZWQgfHwgaXNIVE1MU2FmZSh2YWx1ZSQkMSkpIHsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0oKSwgewogICAgICAgICAgaWQ6ICdlbWJlci1odG1sYmFycy5zdHlsZS14c3Mtd2FybmluZycKICAgICAgICB9KSk7CgogICAgICAgIF9TaW1wbGVEeW5hbWljQXR0cmlidS5wcm90b3R5cGUudXBkYXRlLmNhbGwodGhpcywgdmFsdWUkJDEsIGVudik7CiAgICAgIH07CgogICAgICByZXR1cm4gU3R5bGVBdHRyaWJ1dGVNYW5hZ2VyOwogICAgfShfcnVudGltZTIuU2ltcGxlRHluYW1pY0F0dHJpYnV0ZSk7CgogICAgRW52aXJvbm1lbnQkMS5wcm90b3R5cGUuYXR0cmlidXRlRm9yID0gZnVuY3Rpb24gKGVsZW1lbnQsIGF0dHJpYnV0ZSwgaXNUcnVzdGluZywgbmFtZXNwYWNlKSB7CiAgICAgIGlmIChhdHRyaWJ1dGUgPT09ICdzdHlsZScgJiYgIWlzVHJ1c3RpbmcpIHsKICAgICAgICByZXR1cm4gbmV3IFN0eWxlQXR0cmlidXRlTWFuYWdlcih7CiAgICAgICAgICBlbGVtZW50OiBlbGVtZW50LAogICAgICAgICAgbmFtZTogYXR0cmlidXRlLAogICAgICAgICAgbmFtZXNwYWNlOiBuYW1lc3BhY2UKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9ydW50aW1lMi5FbnZpcm9ubWVudC5wcm90b3R5cGUuYXR0cmlidXRlRm9yLmNhbGwodGhpcywgZWxlbWVudCwgYXR0cmlidXRlLCBpc1RydXN0aW5nLCBuYW1lc3BhY2UpOwogICAgfTsKICB9IC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTptYXgtbGluZS1sZW5ndGgKICAvLyBodHRwczovL2dpdGh1Yi5jb20vZ2xpbW1lcmpzL2dsaW1tZXItdm0vYmxvYi92MC4yNC4wLWJldGEuNC9wYWNrYWdlcy8lNDBnbGltbWVyL3J1bnRpbWUvbGliL2NvbXBvbmVudC9pbnRlcmZhY2VzLnRzI0wyMQoKCiAgdmFyIEFic3RyYWN0TWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEFic3RyYWN0TWFuYWdlcigpIHsKICAgICAgdGhpcy5kZWJ1Z1N0YWNrID0gdW5kZWZpbmVkOwogICAgfQoKICAgIHZhciBfcHJvdG8zMCA9IEFic3RyYWN0TWFuYWdlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMzAucHJlcGFyZUFyZ3MgPSBmdW5jdGlvbiBwcmVwYXJlQXJncyhfc3RhdGUsIF9hcmdzKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfTsKCiAgICBfcHJvdG8zMC5kaWRDcmVhdGVFbGVtZW50ID0gZnVuY3Rpb24gZGlkQ3JlYXRlRWxlbWVudChfY29tcG9uZW50LCBfZWxlbWVudCwgX29wZXJhdGlvbnMpIHt9IC8vIG5vb3AKICAgIC8vIGluaGVyaXRvcnMgc2hvdWxkIGFsc28gY2FsbCBgdGhpcy5kZWJ1Z1N0YWNrLnBvcCgpYCB0bwogICAgLy8gZW5zdXJlIHRoZSByZXJlbmRlcmluZyBhc3NlcnRpb24gbWVzc2FnZXMgYXJlIHByb3Blcmx5CiAgICAvLyBtYWludGFpbmVkCiAgICA7CgogICAgX3Byb3RvMzAuZGlkUmVuZGVyTGF5b3V0ID0gZnVuY3Rpb24gZGlkUmVuZGVyTGF5b3V0KF9jb21wb25lbnQsIF9ib3VuZHMpIHsvLyBub29wCiAgICB9OwoKICAgIF9wcm90bzMwLmRpZENyZWF0ZSA9IGZ1bmN0aW9uIGRpZENyZWF0ZShfYnVja2V0KSB7fSAvLyBub29wCiAgICAvLyBpbmhlcml0b3JzIHNob3VsZCBhbHNvIGNhbGwgYHRoaXMuX3B1c2hUb0RlYnVnU3RhY2tgCiAgICAvLyB0byBlbnN1cmUgdGhlIHJlcmVuZGVyaW5nIGFzc2VydGlvbiBtZXNzYWdlcyBhcmUKICAgIC8vIHByb3Blcmx5IG1haW50YWluZWQKICAgIDsKCiAgICBfcHJvdG8zMC51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoX2J1Y2tldCwgX2R5bmFtaWNTY29wZSkge30gLy8gbm9vcAogICAgLy8gaW5oZXJpdG9ycyBzaG91bGQgYWxzbyBjYWxsIGB0aGlzLmRlYnVnU3RhY2sucG9wKClgIHRvCiAgICAvLyBlbnN1cmUgdGhlIHJlcmVuZGVyaW5nIGFzc2VydGlvbiBtZXNzYWdlcyBhcmUgcHJvcGVybHkKICAgIC8vIG1haW50YWluZWQKICAgIDsKCiAgICBfcHJvdG8zMC5kaWRVcGRhdGVMYXlvdXQgPSBmdW5jdGlvbiBkaWRVcGRhdGVMYXlvdXQoX2J1Y2tldCwgX2JvdW5kcykgey8vIG5vb3AKICAgIH07CgogICAgX3Byb3RvMzAuZGlkVXBkYXRlID0gZnVuY3Rpb24gZGlkVXBkYXRlKF9idWNrZXQpIHsvLyBub29wCiAgICB9OwoKICAgIHJldHVybiBBYnN0cmFjdE1hbmFnZXI7CiAgfSgpOwoKICBfZXhwb3J0cy5BYnN0cmFjdENvbXBvbmVudE1hbmFnZXIgPSBBYnN0cmFjdE1hbmFnZXI7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICBBYnN0cmFjdE1hbmFnZXIucHJvdG90eXBlLl9wdXNoVG9EZWJ1Z1N0YWNrID0gZnVuY3Rpb24gKG5hbWUsIGVudmlyb25tZW50KSB7CiAgICAgIHRoaXMuZGVidWdTdGFjayA9IGVudmlyb25tZW50LmRlYnVnU3RhY2s7CiAgICAgIHRoaXMuZGVidWdTdGFjay5wdXNoKG5hbWUpOwogICAgfTsKCiAgICBBYnN0cmFjdE1hbmFnZXIucHJvdG90eXBlLl9wdXNoRW5naW5lVG9EZWJ1Z1N0YWNrID0gZnVuY3Rpb24gKG5hbWUsIGVudmlyb25tZW50KSB7CiAgICAgIHRoaXMuZGVidWdTdGFjayA9IGVudmlyb25tZW50LmRlYnVnU3RhY2s7CiAgICAgIHRoaXMuZGVidWdTdGFjay5wdXNoRW5naW5lKG5hbWUpOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIGluc3RydW1lbnRhdGlvblBheWxvYWQoZGVmKSB7CiAgICByZXR1cm4gewogICAgICBvYmplY3Q6IGRlZi5uYW1lICsgIjoiICsgZGVmLm91dGxldAogICAgfTsKICB9CgogIHZhciBDQVBBQklMSVRJRVMgPSB7CiAgICBkeW5hbWljTGF5b3V0OiBmYWxzZSwKICAgIGR5bmFtaWNUYWc6IGZhbHNlLAogICAgcHJlcGFyZUFyZ3M6IGZhbHNlLAogICAgY3JlYXRlQXJnczogZmFsc2UsCiAgICBhdHRyaWJ1dGVIb29rOiBmYWxzZSwKICAgIGVsZW1lbnRIb29rOiBmYWxzZSwKICAgIGNyZWF0ZUNhbGxlcjogdHJ1ZSwKICAgIGR5bmFtaWNTY29wZTogdHJ1ZSwKICAgIHVwZGF0ZUhvb2s6IGZhbHNlLAogICAgY3JlYXRlSW5zdGFuY2U6IHRydWUKICB9OwoKICB2YXIgT3V0bGV0Q29tcG9uZW50TWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQWJzdHJhY3RNYW5hZ2VyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoT3V0bGV0Q29tcG9uZW50TWFuYWdlciwgX0Fic3RyYWN0TWFuYWdlcik7CgogICAgZnVuY3Rpb24gT3V0bGV0Q29tcG9uZW50TWFuYWdlcigpIHsKICAgICAgcmV0dXJuIF9BYnN0cmFjdE1hbmFnZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8zMSA9IE91dGxldENvbXBvbmVudE1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzMxLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShlbnZpcm9ubWVudCwgZGVmaW5pdGlvbiwgX2FyZ3MsIGR5bmFtaWNTY29wZSkgewogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgdGhpcy5fcHVzaFRvRGVidWdTdGFjaygidGVtcGxhdGU6IiArIGRlZmluaXRpb24udGVtcGxhdGUucmVmZXJyZXIubW9kdWxlTmFtZSwgZW52aXJvbm1lbnQpOwogICAgICB9CgogICAgICBkeW5hbWljU2NvcGUub3V0bGV0U3RhdGUgPSBkZWZpbml0aW9uLnJlZjsKICAgICAgdmFyIGNvbnRyb2xsZXIgPSBkZWZpbml0aW9uLmNvbnRyb2xsZXI7CiAgICAgIHZhciBzZWxmID0gY29udHJvbGxlciA9PT0gdW5kZWZpbmVkID8gX3J1bnRpbWUyLlVOREVGSU5FRF9SRUZFUkVOQ0UgOiBuZXcgUm9vdFJlZmVyZW5jZShjb250cm9sbGVyKTsKICAgICAgcmV0dXJuIHsKICAgICAgICBzZWxmOiBzZWxmLAogICAgICAgIGZpbmFsaXplOiAoMCwgX2luc3RydW1lbnRhdGlvbi5faW5zdHJ1bWVudFN0YXJ0KSgncmVuZGVyLm91dGxldCcsIGluc3RydW1lbnRhdGlvblBheWxvYWQsIGRlZmluaXRpb24pCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzMxLmdldExheW91dCA9IGZ1bmN0aW9uIGdldExheW91dChfcmVmLCBfcmVzb2x2ZXIpIHsKICAgICAgdmFyIHRlbXBsYXRlID0gX3JlZi50ZW1wbGF0ZTsKICAgICAgLy8gVGhlIHJvdXRlciBoYXMgYWxyZWFkeSByZXNvbHZlZCB0aGUgdGVtcGxhdGUKICAgICAgdmFyIGxheW91dCA9IHRlbXBsYXRlLmFzTGF5b3V0KCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiBsYXlvdXQuY29tcGlsZSgpLAogICAgICAgIHN5bWJvbFRhYmxlOiBsYXlvdXQuc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvMzEuZ2V0Q2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gZ2V0Q2FwYWJpbGl0aWVzKCkgewogICAgICByZXR1cm4gQ0FQQUJJTElUSUVTOwogICAgfTsKCiAgICBfcHJvdG8zMS5nZXRTZWxmID0gZnVuY3Rpb24gZ2V0U2VsZihfcmVmMikgewogICAgICB2YXIgc2VsZiA9IF9yZWYyLnNlbGY7CiAgICAgIHJldHVybiBzZWxmOwogICAgfTsKCiAgICBfcHJvdG8zMS5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoKSB7CiAgICAgIC8vIGFuIG91dGxldCBoYXMgbm8gaG9va3MKICAgICAgcmV0dXJuIF9yZWZlcmVuY2UuQ09OU1RBTlRfVEFHOwogICAgfTsKCiAgICBfcHJvdG8zMS5kaWRSZW5kZXJMYXlvdXQgPSBmdW5jdGlvbiBkaWRSZW5kZXJMYXlvdXQoc3RhdGUpIHsKICAgICAgc3RhdGUuZmluYWxpemUoKTsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICB0aGlzLmRlYnVnU3RhY2sucG9wKCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMzEuZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3IoKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfTsKCiAgICByZXR1cm4gT3V0bGV0Q29tcG9uZW50TWFuYWdlcjsKICB9KEFic3RyYWN0TWFuYWdlcik7CgogIHZhciBPVVRMRVRfTUFOQUdFUiA9IG5ldyBPdXRsZXRDb21wb25lbnRNYW5hZ2VyKCk7CgogIHZhciBPdXRsZXRDb21wb25lbnREZWZpbml0aW9uID0gZnVuY3Rpb24gT3V0bGV0Q29tcG9uZW50RGVmaW5pdGlvbihzdGF0ZSwgbWFuYWdlcikgewogICAgaWYgKG1hbmFnZXIgPT09IHZvaWQgMCkgewogICAgICBtYW5hZ2VyID0gT1VUTEVUX01BTkFHRVI7CiAgICB9CgogICAgdGhpcy5zdGF0ZSA9IHN0YXRlOwogICAgdGhpcy5tYW5hZ2VyID0gbWFuYWdlcjsKICB9OwoKICBmdW5jdGlvbiBjcmVhdGVSb290T3V0bGV0KG91dGxldFZpZXcpIHsKICAgIGlmIChfZW52aXJvbm1lbnQyLkVOVi5fQVBQTElDQVRJT05fVEVNUExBVEVfV1JBUFBFUikgewogICAgICB2YXIgV1JBUFBFRF9DQVBBQklMSVRJRVMgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBDQVBBQklMSVRJRVMsIHsKICAgICAgICBkeW5hbWljVGFnOiB0cnVlLAogICAgICAgIGVsZW1lbnRIb29rOiB0cnVlCiAgICAgIH0pOwoKICAgICAgdmFyIFdyYXBwZWRPdXRsZXRDb21wb25lbnRNYW5hZ2VyID0KICAgICAgLyojX19QVVJFX18qLwogICAgICBmdW5jdGlvbiAoX091dGxldENvbXBvbmVudE1hbmFnKSB7CiAgICAgICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFdyYXBwZWRPdXRsZXRDb21wb25lbnRNYW5hZ2VyLCBfT3V0bGV0Q29tcG9uZW50TWFuYWcpOwoKICAgICAgICBmdW5jdGlvbiBXcmFwcGVkT3V0bGV0Q29tcG9uZW50TWFuYWdlcigpIHsKICAgICAgICAgIHJldHVybiBfT3V0bGV0Q29tcG9uZW50TWFuYWcuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICAgIH0KCiAgICAgICAgdmFyIF9wcm90bzMyID0gV3JhcHBlZE91dGxldENvbXBvbmVudE1hbmFnZXIucHJvdG90eXBlOwoKICAgICAgICBfcHJvdG8zMi5nZXRUYWdOYW1lID0gZnVuY3Rpb24gZ2V0VGFnTmFtZShfY29tcG9uZW50KSB7CiAgICAgICAgICByZXR1cm4gJ2Rpdic7CiAgICAgICAgfTsKCiAgICAgICAgX3Byb3RvMzIuZ2V0TGF5b3V0ID0gZnVuY3Rpb24gZ2V0TGF5b3V0KHN0YXRlKSB7CiAgICAgICAgICAvLyBUaGUgcm91dGVyIGhhcyBhbHJlYWR5IHJlc29sdmVkIHRoZSB0ZW1wbGF0ZQogICAgICAgICAgdmFyIHRlbXBsYXRlID0gc3RhdGUudGVtcGxhdGU7CiAgICAgICAgICB2YXIgbGF5b3V0ID0gdGVtcGxhdGUuYXNXcmFwcGVkTGF5b3V0KCk7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBoYW5kbGU6IGxheW91dC5jb21waWxlKCksCiAgICAgICAgICAgIHN5bWJvbFRhYmxlOiBsYXlvdXQuc3ltYm9sVGFibGUKICAgICAgICAgIH07CiAgICAgICAgfTsKCiAgICAgICAgX3Byb3RvMzIuZ2V0Q2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gZ2V0Q2FwYWJpbGl0aWVzKCkgewogICAgICAgICAgcmV0dXJuIFdSQVBQRURfQ0FQQUJJTElUSUVTOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzMyLmRpZENyZWF0ZUVsZW1lbnQgPSBmdW5jdGlvbiBkaWRDcmVhdGVFbGVtZW50KGNvbXBvbmVudCwgZWxlbWVudCwgX29wZXJhdGlvbnMpIHsKICAgICAgICAgIC8vIHRvIGFkZCBHVUlEIGlkIGFuZCBjbGFzcwogICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ2VtYmVyLXZpZXcnKTsKICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdpZCcsICgwLCBfdXRpbHMuZ3VpZEZvcikoY29tcG9uZW50KSk7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIFdyYXBwZWRPdXRsZXRDb21wb25lbnRNYW5hZ2VyOwogICAgICB9KE91dGxldENvbXBvbmVudE1hbmFnZXIpOwoKICAgICAgdmFyIFdSQVBQRURfT1VUTEVUX01BTkFHRVIgPSBuZXcgV3JhcHBlZE91dGxldENvbXBvbmVudE1hbmFnZXIoKTsKICAgICAgcmV0dXJuIG5ldyBPdXRsZXRDb21wb25lbnREZWZpbml0aW9uKG91dGxldFZpZXcuc3RhdGUsIFdSQVBQRURfT1VUTEVUX01BTkFHRVIpOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG5ldyBPdXRsZXRDb21wb25lbnREZWZpbml0aW9uKG91dGxldFZpZXcuc3RhdGUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gTk9PUCgpIHt9CiAgLyoqCiAgICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBSZXByZXNlbnRzIHRoZSBpbnRlcm5hbCBzdGF0ZSBvZiB0aGUgY29tcG9uZW50LgogIAogICAgQGNsYXNzIENvbXBvbmVudFN0YXRlQnVja2V0CiAgICBAcHJpdmF0ZQogICovCgoKICB2YXIgQ29tcG9uZW50U3RhdGVCdWNrZXQgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDb21wb25lbnRTdGF0ZUJ1Y2tldChlbnZpcm9ubWVudCwgY29tcG9uZW50LCBhcmdzLCBmaW5hbGl6ZXIsIGhhc1dyYXBwZWRFbGVtZW50KSB7CiAgICAgIHRoaXMuZW52aXJvbm1lbnQgPSBlbnZpcm9ubWVudDsKICAgICAgdGhpcy5jb21wb25lbnQgPSBjb21wb25lbnQ7CiAgICAgIHRoaXMuYXJncyA9IGFyZ3M7CiAgICAgIHRoaXMuZmluYWxpemVyID0gZmluYWxpemVyOwogICAgICB0aGlzLmhhc1dyYXBwZWRFbGVtZW50ID0gaGFzV3JhcHBlZEVsZW1lbnQ7CiAgICAgIHRoaXMuY2xhc3NSZWYgPSBudWxsOwogICAgICB0aGlzLmNsYXNzUmVmID0gbnVsbDsKICAgICAgdGhpcy5hcmdzUmV2aXNpb24gPSBhcmdzID09PSBudWxsID8gMCA6ICgwLCBfcmVmZXJlbmNlLnZhbHVlKShhcmdzLnRhZyk7CiAgICB9CgogICAgdmFyIF9wcm90bzMzID0gQ29tcG9uZW50U3RhdGVCdWNrZXQucHJvdG90eXBlOwoKICAgIF9wcm90bzMzLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICB2YXIgY29tcG9uZW50ID0gdGhpcy5jb21wb25lbnQsCiAgICAgICAgICBlbnZpcm9ubWVudCA9IHRoaXMuZW52aXJvbm1lbnQ7CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCd3aWxsRGVzdHJveUVsZW1lbnQnKTsKICAgICAgICBjb21wb25lbnQudHJpZ2dlcignd2lsbENsZWFyUmVuZGVyJyk7CiAgICAgICAgdmFyIGVsZW1lbnQgPSAoMCwgX3ZpZXdzLmdldFZpZXdFbGVtZW50KShjb21wb25lbnQpOwoKICAgICAgICBpZiAoZWxlbWVudCkgewogICAgICAgICAgKDAsIF92aWV3cy5jbGVhckVsZW1lbnRWaWV3KShlbGVtZW50KTsKICAgICAgICAgICgwLCBfdmlld3MuY2xlYXJWaWV3RWxlbWVudCkoY29tcG9uZW50KTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGVudmlyb25tZW50LmRlc3Ryb3llZENvbXBvbmVudHMucHVzaChjb21wb25lbnQpOwogICAgfTsKCiAgICBfcHJvdG8zMy5maW5hbGl6ZSA9IGZ1bmN0aW9uIGZpbmFsaXplKCkgewogICAgICB2YXIgZmluYWxpemVyID0gdGhpcy5maW5hbGl6ZXI7CiAgICAgIGZpbmFsaXplcigpOwogICAgICB0aGlzLmZpbmFsaXplciA9IE5PT1A7CiAgICB9OwoKICAgIHJldHVybiBDb21wb25lbnRTdGF0ZUJ1Y2tldDsKICB9KCk7CgogIGZ1bmN0aW9uIHJlZmVyZW5jZUZvcktleShjb21wb25lbnQsIGtleSkgewogICAgcmV0dXJuIGNvbXBvbmVudFtST09UX1JFRl0uZ2V0KGtleSk7CiAgfQoKICBmdW5jdGlvbiByZWZlcmVuY2VGb3JQYXJ0cyhjb21wb25lbnQsIHBhcnRzKSB7CiAgICB2YXIgaXNBdHRycyA9IHBhcnRzWzBdID09PSAnYXR0cnMnOyAvLyBUT0RPIGRlcHJlY2F0ZSB0aGlzCgogICAgaWYgKGlzQXR0cnMpIHsKICAgICAgcGFydHMuc2hpZnQoKTsKCiAgICAgIGlmIChwYXJ0cy5sZW5ndGggPT09IDEpIHsKICAgICAgICByZXR1cm4gcmVmZXJlbmNlRm9yS2V5KGNvbXBvbmVudCwgcGFydHNbMF0pOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJlZmVyZW5jZUZyb21QYXJ0cyhjb21wb25lbnRbUk9PVF9SRUZdLCBwYXJ0cyk7CiAgfSAvLyBUT0RPIHdlIHNob3VsZCBwcm9iYWJseSBkbyB0aGlzIHRyYW5zZm9ybSBhdCBidWlsZCB0aW1lCgoKICBmdW5jdGlvbiB3cmFwQ29tcG9uZW50Q2xhc3NBdHRyaWJ1dGUoaGFzaCkgewogICAgaWYgKGhhc2ggPT09IG51bGwpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBrZXlzID0gaGFzaFswXSwKICAgICAgICB2YWx1ZXMgPSBoYXNoWzFdOwogICAgdmFyIGluZGV4ID0ga2V5cyA9PT0gbnVsbCA/IC0xIDoga2V5cy5pbmRleE9mKCdjbGFzcycpOwoKICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgdmFyIHZhbHVlJCQxID0gdmFsdWVzW2luZGV4XTsKCiAgICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZSQkMSkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciB0eXBlID0gdmFsdWUkJDFbMF07CgogICAgICBpZiAodHlwZSA9PT0gX3dpcmVGb3JtYXQuT3BzLkdldCB8fCB0eXBlID09PSBfd2lyZUZvcm1hdC5PcHMuTWF5YmVMb2NhbCkgewogICAgICAgIHZhciBwYXRoID0gdmFsdWUkJDFbdmFsdWUkJDEubGVuZ3RoIC0gMV07CiAgICAgICAgdmFyIHByb3BOYW1lID0gcGF0aFtwYXRoLmxlbmd0aCAtIDFdOwogICAgICAgIHZhbHVlc1tpbmRleF0gPSBbX3dpcmVGb3JtYXQuT3BzLkhlbHBlciwgJy1jbGFzcycsIFt2YWx1ZSQkMSwgcHJvcE5hbWVdLCBudWxsXTsKICAgICAgfQogICAgfQogIH0KCiAgdmFyIEF0dHJpYnV0ZUJpbmRpbmcgPSB7CiAgICBwYXJzZTogZnVuY3Rpb24gcGFyc2UobWljcm9zeW50YXgpIHsKICAgICAgdmFyIGNvbG9uSW5kZXggPSBtaWNyb3N5bnRheC5pbmRleE9mKCc6Jyk7CgogICAgICBpZiAoY29sb25JbmRleCA9PT0gLTEpIHsKICAgICAgICAoZmFsc2UgJiYgIShtaWNyb3N5bnRheCAhPT0gJ2NsYXNzJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgY2Fubm90IHVzZSBjbGFzcyBhcyBhbiBhdHRyaWJ1dGVCaW5kaW5nLCB1c2UgY2xhc3NOYW1lQmluZGluZ3MgaW5zdGVhZC4nLCBtaWNyb3N5bnRheCAhPT0gJ2NsYXNzJykpOwogICAgICAgIHJldHVybiBbbWljcm9zeW50YXgsIG1pY3Jvc3ludGF4LCB0cnVlXTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgcHJvcCA9IG1pY3Jvc3ludGF4LnN1YnN0cmluZygwLCBjb2xvbkluZGV4KTsKICAgICAgICB2YXIgYXR0cmlidXRlID0gbWljcm9zeW50YXguc3Vic3RyaW5nKGNvbG9uSW5kZXggKyAxKTsKICAgICAgICAoZmFsc2UgJiYgIShhdHRyaWJ1dGUgIT09ICdjbGFzcycpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGNhbm5vdCB1c2UgY2xhc3MgYXMgYW4gYXR0cmlidXRlQmluZGluZywgdXNlIGNsYXNzTmFtZUJpbmRpbmdzIGluc3RlYWQuJywgYXR0cmlidXRlICE9PSAnY2xhc3MnKSk7CiAgICAgICAgcmV0dXJuIFtwcm9wLCBhdHRyaWJ1dGUsIGZhbHNlXTsKICAgICAgfQogICAgfSwKICAgIGluc3RhbGw6IGZ1bmN0aW9uIGluc3RhbGwoX2VsZW1lbnQsIGNvbXBvbmVudCwgcGFyc2VkLCBvcGVyYXRpb25zKSB7CiAgICAgIHZhciBwcm9wID0gcGFyc2VkWzBdLAogICAgICAgICAgYXR0cmlidXRlID0gcGFyc2VkWzFdLAogICAgICAgICAgaXNTaW1wbGUgPSBwYXJzZWRbMl07CgogICAgICBpZiAoYXR0cmlidXRlID09PSAnaWQnKSB7CiAgICAgICAgdmFyIGVsZW1lbnRJZCA9ICgwLCBfbWV0YWwuZ2V0KShjb21wb25lbnQsIHByb3ApOwoKICAgICAgICBpZiAoZWxlbWVudElkID09PSB1bmRlZmluZWQgfHwgZWxlbWVudElkID09PSBudWxsKSB7CiAgICAgICAgICBlbGVtZW50SWQgPSBjb21wb25lbnQuZWxlbWVudElkOwogICAgICAgIH0KCiAgICAgICAgZWxlbWVudElkID0gX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUoZWxlbWVudElkKTsKICAgICAgICBvcGVyYXRpb25zLnNldEF0dHJpYnV0ZSgnaWQnLCBlbGVtZW50SWQsIHRydWUsIG51bGwpOyAvLyBvcGVyYXRpb25zLmFkZFN0YXRpY0F0dHJpYnV0ZShlbGVtZW50LCAnaWQnLCBlbGVtZW50SWQpOwoKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBpc1BhdGggPSBwcm9wLmluZGV4T2YoJy4nKSA+IC0xOwogICAgICB2YXIgcmVmZXJlbmNlID0gaXNQYXRoID8gcmVmZXJlbmNlRm9yUGFydHMoY29tcG9uZW50LCBwcm9wLnNwbGl0KCcuJykpIDogcmVmZXJlbmNlRm9yS2V5KGNvbXBvbmVudCwgcHJvcCk7CiAgICAgIChmYWxzZSAmJiAhKCEoaXNTaW1wbGUgJiYgaXNQYXRoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJJbGxlZ2FsIGF0dHJpYnV0ZUJpbmRpbmc6ICciICsgcHJvcCArICInIGlzIG5vdCBhIHZhbGlkIGF0dHJpYnV0ZSBuYW1lLiIsICEoaXNTaW1wbGUgJiYgaXNQYXRoKSkpOwoKICAgICAgaWYgKGF0dHJpYnV0ZSA9PT0gJ3N0eWxlJykgewogICAgICAgIHJlZmVyZW5jZSA9IG5ldyBTdHlsZUJpbmRpbmdSZWZlcmVuY2UocmVmZXJlbmNlLCByZWZlcmVuY2VGb3JLZXkoY29tcG9uZW50LCAnaXNWaXNpYmxlJykpOwogICAgICB9CgogICAgICBvcGVyYXRpb25zLnNldEF0dHJpYnV0ZShhdHRyaWJ1dGUsIHJlZmVyZW5jZSwgZmFsc2UsIG51bGwpOyAvLyBvcGVyYXRpb25zLmFkZER5bmFtaWNBdHRyaWJ1dGUoZWxlbWVudCwgYXR0cmlidXRlLCByZWZlcmVuY2UsIGZhbHNlKTsKICAgIH0KICB9OwogIHZhciBESVNQTEFZX05PTkUgPSAnZGlzcGxheTogbm9uZTsnOwogIHZhciBTQUZFX0RJU1BMQVlfTk9ORSA9IGh0bWxTYWZlKERJU1BMQVlfTk9ORSk7CgogIHZhciBTdHlsZUJpbmRpbmdSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NhY2hlZFJlZmVyZW5jZSkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFN0eWxlQmluZGluZ1JlZmVyZW5jZSwgX0NhY2hlZFJlZmVyZW5jZSk7CgogICAgZnVuY3Rpb24gU3R5bGVCaW5kaW5nUmVmZXJlbmNlKGlubmVyLCBpc1Zpc2libGUpIHsKICAgICAgdmFyIF90aGlzMTY7CgogICAgICBfdGhpczE2ID0gX0NhY2hlZFJlZmVyZW5jZS5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMTYuaW5uZXIgPSBpbm5lcjsKICAgICAgX3RoaXMxNi5pc1Zpc2libGUgPSBpc1Zpc2libGU7CiAgICAgIF90aGlzMTYudGFnID0gKDAsIF9yZWZlcmVuY2UuY29tYmluZSkoW2lubmVyLnRhZywgaXNWaXNpYmxlLnRhZ10pOwogICAgICByZXR1cm4gX3RoaXMxNjsKICAgIH0KCiAgICB2YXIgX3Byb3RvMzQgPSBTdHlsZUJpbmRpbmdSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzM0LmNvbXB1dGUgPSBmdW5jdGlvbiBjb21wdXRlKCkgewogICAgICB2YXIgdmFsdWUkJDEgPSB0aGlzLmlubmVyLnZhbHVlKCk7CiAgICAgIHZhciBpc1Zpc2libGUgPSB0aGlzLmlzVmlzaWJsZS52YWx1ZSgpOwoKICAgICAgaWYgKGlzVmlzaWJsZSAhPT0gZmFsc2UpIHsKICAgICAgICByZXR1cm4gdmFsdWUkJDE7CiAgICAgIH0gZWxzZSBpZiAoIXZhbHVlJCQxKSB7CiAgICAgICAgcmV0dXJuIFNBRkVfRElTUExBWV9OT05FOwogICAgICB9IGVsc2UgewogICAgICAgIHZhciBzdHlsZSA9IHZhbHVlJCQxICsgJyAnICsgRElTUExBWV9OT05FOwogICAgICAgIHJldHVybiBpc0hUTUxTYWZlKHZhbHVlJCQxKSA/IGh0bWxTYWZlKHN0eWxlKSA6IHN0eWxlOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBTdHlsZUJpbmRpbmdSZWZlcmVuY2U7CiAgfShfcmVmZXJlbmNlLkNhY2hlZFJlZmVyZW5jZSk7CgogIHZhciBJc1Zpc2libGVCaW5kaW5nID0gewogICAgaW5zdGFsbDogZnVuY3Rpb24gaW5zdGFsbChfZWxlbWVudCwgY29tcG9uZW50LCBvcGVyYXRpb25zKSB7CiAgICAgIG9wZXJhdGlvbnMuc2V0QXR0cmlidXRlKCdzdHlsZScsICgwLCBfcmVmZXJlbmNlLm1hcCkocmVmZXJlbmNlRm9yS2V5KGNvbXBvbmVudCwgJ2lzVmlzaWJsZScpLCB0aGlzLm1hcFN0eWxlVmFsdWUpLCBmYWxzZSwgbnVsbCk7IC8vIC8vIHRoZSB1cHN0cmVhbSB0eXBlIGZvciBhZGREeW5hbWljQXR0cmlidXRlJ3MgYHZhbHVlYCBhcmd1bWVudAogICAgICAvLyAvLyBhcHBlYXJzIHRvIGJlIGluY29ycmVjdC4gSXQgaXMgY3VycmVudGx5IGEgUmVmZXJlbmNlPHN0cmluZz4sIEkKICAgICAgLy8gLy8gdGhpbmsgaXQgc2hvdWxkIGJlIGEgUmVmZXJlbmNlPHN0cmluZ3xudWxsPi4KICAgICAgLy8gb3BlcmF0aW9ucy5hZGREeW5hbWljQXR0cmlidXRlKGVsZW1lbnQsICdzdHlsZScsIHJlZiBhcyBhbnkgYXMgUmVmZXJlbmNlPHN0cmluZz4sIGZhbHNlKTsKICAgIH0sCiAgICBtYXBTdHlsZVZhbHVlOiBmdW5jdGlvbiBtYXBTdHlsZVZhbHVlKGlzVmlzaWJsZSkgewogICAgICByZXR1cm4gaXNWaXNpYmxlID09PSBmYWxzZSA/IFNBRkVfRElTUExBWV9OT05FIDogbnVsbDsKICAgIH0KICB9OwogIHZhciBDbGFzc05hbWVCaW5kaW5nID0gewogICAgaW5zdGFsbDogZnVuY3Rpb24gaW5zdGFsbChfZWxlbWVudCwgY29tcG9uZW50LCBtaWNyb3N5bnRheCwgb3BlcmF0aW9ucykgewogICAgICB2YXIgX21pY3Jvc3ludGF4JHNwbGl0ID0gbWljcm9zeW50YXguc3BsaXQoJzonKSwKICAgICAgICAgIHByb3AgPSBfbWljcm9zeW50YXgkc3BsaXRbMF0sCiAgICAgICAgICB0cnV0aHkgPSBfbWljcm9zeW50YXgkc3BsaXRbMV0sCiAgICAgICAgICBmYWxzeSA9IF9taWNyb3N5bnRheCRzcGxpdFsyXTsKCiAgICAgIHZhciBpc1N0YXRpYyA9IHByb3AgPT09ICcnOwoKICAgICAgaWYgKGlzU3RhdGljKSB7CiAgICAgICAgb3BlcmF0aW9ucy5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUodHJ1dGh5KSwgdHJ1ZSwgbnVsbCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIGlzUGF0aCA9IHByb3AuaW5kZXhPZignLicpID4gLTE7CiAgICAgICAgdmFyIHBhcnRzID0gaXNQYXRoID8gcHJvcC5zcGxpdCgnLicpIDogW107CiAgICAgICAgdmFyIHZhbHVlJCQxID0gaXNQYXRoID8gcmVmZXJlbmNlRm9yUGFydHMoY29tcG9uZW50LCBwYXJ0cykgOiByZWZlcmVuY2VGb3JLZXkoY29tcG9uZW50LCBwcm9wKTsKICAgICAgICB2YXIgcmVmOwoKICAgICAgICBpZiAodHJ1dGh5ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJlZiA9IG5ldyBTaW1wbGVDbGFzc05hbWVCaW5kaW5nUmVmZXJlbmNlKHZhbHVlJCQxLCBpc1BhdGggPyBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXSA6IHByb3ApOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZWYgPSBuZXcgQ29sb25DbGFzc05hbWVCaW5kaW5nUmVmZXJlbmNlKHZhbHVlJCQxLCB0cnV0aHksIGZhbHN5KTsKICAgICAgICB9CgogICAgICAgIG9wZXJhdGlvbnMuc2V0QXR0cmlidXRlKCdjbGFzcycsIHJlZiwgZmFsc2UsIG51bGwpOyAvLyAvLyB0aGUgdXBzdHJlYW0gdHlwZSBmb3IgYWRkRHluYW1pY0F0dHJpYnV0ZSdzIGB2YWx1ZWAgYXJndW1lbnQKICAgICAgICAvLyAvLyBhcHBlYXJzIHRvIGJlIGluY29ycmVjdC4gSXQgaXMgY3VycmVudGx5IGEgUmVmZXJlbmNlPHN0cmluZz4sIEkKICAgICAgICAvLyAvLyB0aGluayBpdCBzaG91bGQgYmUgYSBSZWZlcmVuY2U8c3RyaW5nfG51bGw+LgogICAgICAgIC8vIG9wZXJhdGlvbnMuYWRkRHluYW1pY0F0dHJpYnV0ZShlbGVtZW50LCAnY2xhc3MnLCByZWYgYXMgYW55IGFzIFJlZmVyZW5jZTxzdHJpbmc+LCBmYWxzZSk7CiAgICAgIH0KICAgIH0KICB9OwoKICB2YXIgU2ltcGxlQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ2FjaGVkUmVmZXJlbmNlMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFNpbXBsZUNsYXNzTmFtZUJpbmRpbmdSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UyKTsKCiAgICBmdW5jdGlvbiBTaW1wbGVDbGFzc05hbWVCaW5kaW5nUmVmZXJlbmNlKGlubmVyLCBwYXRoKSB7CiAgICAgIHZhciBfdGhpczE3OwoKICAgICAgX3RoaXMxNyA9IF9DYWNoZWRSZWZlcmVuY2UyLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXMxNy5pbm5lciA9IGlubmVyOwogICAgICBfdGhpczE3LnBhdGggPSBwYXRoOwogICAgICBfdGhpczE3LnRhZyA9IGlubmVyLnRhZzsKICAgICAgX3RoaXMxNy5pbm5lciA9IGlubmVyOwogICAgICBfdGhpczE3LnBhdGggPSBwYXRoOwogICAgICBfdGhpczE3LmRhc2hlcml6ZWRQYXRoID0gbnVsbDsKICAgICAgcmV0dXJuIF90aGlzMTc7CiAgICB9CgogICAgdmFyIF9wcm90bzM1ID0gU2ltcGxlQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMzUuY29tcHV0ZSA9IGZ1bmN0aW9uIGNvbXB1dGUoKSB7CiAgICAgIHZhciB2YWx1ZSQkMSA9IHRoaXMuaW5uZXIudmFsdWUoKTsKCiAgICAgIGlmICh2YWx1ZSQkMSA9PT0gdHJ1ZSkgewogICAgICAgIHZhciBwYXRoID0gdGhpcy5wYXRoLAogICAgICAgICAgICBkYXNoZXJpemVkUGF0aCA9IHRoaXMuZGFzaGVyaXplZFBhdGg7CiAgICAgICAgcmV0dXJuIGRhc2hlcml6ZWRQYXRoIHx8ICh0aGlzLmRhc2hlcml6ZWRQYXRoID0gKDAsIF9zdHJpbmcuZGFzaGVyaXplKShwYXRoKSk7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUkJDEgfHwgdmFsdWUkJDEgPT09IDApIHsKICAgICAgICByZXR1cm4gU3RyaW5nKHZhbHVlJCQxKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gU2ltcGxlQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZTsKICB9KF9yZWZlcmVuY2UuQ2FjaGVkUmVmZXJlbmNlKTsKCiAgdmFyIENvbG9uQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ2FjaGVkUmVmZXJlbmNlMykgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKENvbG9uQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZSwgX0NhY2hlZFJlZmVyZW5jZTMpOwoKICAgIGZ1bmN0aW9uIENvbG9uQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZShpbm5lciwgdHJ1dGh5LCBmYWxzeSkgewogICAgICB2YXIgX3RoaXMxODsKCiAgICAgIGlmICh0cnV0aHkgPT09IHZvaWQgMCkgewogICAgICAgIHRydXRoeSA9IG51bGw7CiAgICAgIH0KCiAgICAgIGlmIChmYWxzeSA9PT0gdm9pZCAwKSB7CiAgICAgICAgZmFsc3kgPSBudWxsOwogICAgICB9CgogICAgICBfdGhpczE4ID0gX0NhY2hlZFJlZmVyZW5jZTMuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczE4LmlubmVyID0gaW5uZXI7CiAgICAgIF90aGlzMTgudHJ1dGh5ID0gdHJ1dGh5OwogICAgICBfdGhpczE4LmZhbHN5ID0gZmFsc3k7CiAgICAgIF90aGlzMTgudGFnID0gaW5uZXIudGFnOwogICAgICByZXR1cm4gX3RoaXMxODsKICAgIH0KCiAgICB2YXIgX3Byb3RvMzYgPSBDb2xvbkNsYXNzTmFtZUJpbmRpbmdSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzM2LmNvbXB1dGUgPSBmdW5jdGlvbiBjb21wdXRlKCkgewogICAgICB2YXIgaW5uZXIgPSB0aGlzLmlubmVyLAogICAgICAgICAgdHJ1dGh5ID0gdGhpcy50cnV0aHksCiAgICAgICAgICBmYWxzeSA9IHRoaXMuZmFsc3k7CiAgICAgIHJldHVybiBpbm5lci52YWx1ZSgpID8gdHJ1dGh5IDogZmFsc3k7CiAgICB9OwoKICAgIHJldHVybiBDb2xvbkNsYXNzTmFtZUJpbmRpbmdSZWZlcmVuY2U7CiAgfShfcmVmZXJlbmNlLkNhY2hlZFJlZmVyZW5jZSk7IC8vIGlucHV0cyBuZWVkZWQgYnkgQ3VybHlDb21wb25lbnRzIChhdHRycyBhbmQgcHJvcHMsIHdpdGggbXV0YWJsZQogIC8vIGNlbGxzLCBldGMpLgoKCiAgZnVuY3Rpb24gcHJvY2Vzc0NvbXBvbmVudEFyZ3MobmFtZWRBcmdzKSB7CiAgICB2YXIga2V5cyA9IG5hbWVkQXJncy5uYW1lczsKICAgIHZhciBhdHRycyA9IG5hbWVkQXJncy52YWx1ZSgpOwogICAgdmFyIHByb3BzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHZhciBhcmdzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHByb3BzW0FSR1NdID0gYXJnczsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIG5hbWUgPSBrZXlzW2ldOwogICAgICB2YXIgcmVmID0gbmFtZWRBcmdzLmdldChuYW1lKTsKICAgICAgdmFyIHZhbHVlJCQxID0gYXR0cnNbbmFtZV07CgogICAgICBpZiAodHlwZW9mIHZhbHVlJCQxID09PSAnZnVuY3Rpb24nICYmIHZhbHVlJCQxW0FDVElPTl0pIHsKICAgICAgICBhdHRyc1tuYW1lXSA9IHZhbHVlJCQxOwogICAgICB9IGVsc2UgaWYgKHJlZltVUERBVEVdKSB7CiAgICAgICAgYXR0cnNbbmFtZV0gPSBuZXcgTXV0YWJsZUNlbGwocmVmLCB2YWx1ZSQkMSk7CiAgICAgIH0KCiAgICAgIGFyZ3NbbmFtZV0gPSByZWY7CiAgICAgIHByb3BzW25hbWVdID0gdmFsdWUkJDE7CiAgICB9CgogICAgcHJvcHMuYXR0cnMgPSBhdHRyczsKICAgIHJldHVybiBwcm9wczsKICB9CgogIHZhciBSRUYgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ1JFRicpOwoKICB2YXIgTXV0YWJsZUNlbGwgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBNdXRhYmxlQ2VsbChyZWYsIHZhbHVlJCQxKSB7CiAgICAgIHRoaXNbX3ZpZXdzLk1VVEFCTEVfQ0VMTF0gPSB0cnVlOwogICAgICB0aGlzW1JFRl0gPSByZWY7CiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZSQkMTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMzcgPSBNdXRhYmxlQ2VsbC5wcm90b3R5cGU7CgogICAgX3Byb3RvMzcudXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKHZhbCkgewogICAgICB0aGlzW1JFRl1bVVBEQVRFXSh2YWwpOwogICAgfTsKCiAgICByZXR1cm4gTXV0YWJsZUNlbGw7CiAgfSgpOwoKICBmdW5jdGlvbiBhbGlhc0lkVG9FbGVtZW50SWQoYXJncywgcHJvcHMpIHsKICAgIGlmIChhcmdzLm5hbWVkLmhhcygnaWQnKSkgewogICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoCiAgICAgIChmYWxzZSAmJiAhKCFhcmdzLm5hbWVkLmhhcygnZWxlbWVudElkJykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGNhbm5vdCBpbnZva2UgYSBjb21wb25lbnQgd2l0aCBib3RoICdpZCcgYW5kICdlbGVtZW50SWQnIGF0IHRoZSBzYW1lIHRpbWUuIiwgIWFyZ3MubmFtZWQuaGFzKCdlbGVtZW50SWQnKSkpOwogICAgICBwcm9wcy5lbGVtZW50SWQgPSBwcm9wcy5pZDsKICAgIH0KICB9IC8vIFdlIG11c3QgdHJhdmVyc2UgdGhlIGF0dHJpYnV0ZUJpbmRpbmdzIGluIHJldmVyc2Uga2VlcGluZyB0cmFjayBvZgogIC8vIHdoYXQgaGFzIGFscmVhZHkgYmVlbiBhcHBsaWVkLiBUaGlzIGlzIGVzc2VudGlhbGx5IHJlZmluaW5nIHRoZSBjb25jYXRlbmF0ZWQKICAvLyBwcm9wZXJ0aWVzIGFwcGx5aW5nIHJpZ2h0IHRvIGxlZnQuCgoKICBmdW5jdGlvbiBhcHBseUF0dHJpYnV0ZUJpbmRpbmdzKGVsZW1lbnQsIGF0dHJpYnV0ZUJpbmRpbmdzLCBjb21wb25lbnQsIG9wZXJhdGlvbnMpIHsKICAgIHZhciBzZWVuID0gW107CiAgICB2YXIgaSA9IGF0dHJpYnV0ZUJpbmRpbmdzLmxlbmd0aCAtIDE7CgogICAgd2hpbGUgKGkgIT09IC0xKSB7CiAgICAgIHZhciBiaW5kaW5nID0gYXR0cmlidXRlQmluZGluZ3NbaV07CiAgICAgIHZhciBwYXJzZWQgPSBBdHRyaWJ1dGVCaW5kaW5nLnBhcnNlKGJpbmRpbmcpOwogICAgICB2YXIgYXR0cmlidXRlID0gcGFyc2VkWzFdOwoKICAgICAgaWYgKHNlZW4uaW5kZXhPZihhdHRyaWJ1dGUpID09PSAtMSkgewogICAgICAgIHNlZW4ucHVzaChhdHRyaWJ1dGUpOwogICAgICAgIEF0dHJpYnV0ZUJpbmRpbmcuaW5zdGFsbChlbGVtZW50LCBjb21wb25lbnQsIHBhcnNlZCwgb3BlcmF0aW9ucyk7CiAgICAgIH0KCiAgICAgIGktLTsKICAgIH0KCiAgICBpZiAoc2Vlbi5pbmRleE9mKCdpZCcpID09PSAtMSkgewogICAgICB2YXIgaWQkJDEgPSBjb21wb25lbnQuZWxlbWVudElkID8gY29tcG9uZW50LmVsZW1lbnRJZCA6ICgwLCBfdXRpbHMuZ3VpZEZvcikoY29tcG9uZW50KTsKICAgICAgb3BlcmF0aW9ucy5zZXRBdHRyaWJ1dGUoJ2lkJywgX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUoaWQkJDEpLCBmYWxzZSwgbnVsbCk7CiAgICB9CgogICAgaWYgKHNlZW4uaW5kZXhPZignc3R5bGUnKSA9PT0gLTEpIHsKICAgICAgSXNWaXNpYmxlQmluZGluZy5pbnN0YWxsKGVsZW1lbnQsIGNvbXBvbmVudCwgb3BlcmF0aW9ucyk7CiAgICB9CiAgfQoKICB2YXIgREVGQVVMVF9MQVlPVVQgPSAoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdDIoKSk7CiAgdmFyIEVNUFRZX1BPU0lUSU9OQUxfQVJHUyA9IFtdOwogICgwLCBfZGVidWcuZGVidWdGcmVlemUpKEVNUFRZX1BPU0lUSU9OQUxfQVJHUyk7CgogIHZhciBDdXJseUNvbXBvbmVudE1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Fic3RyYWN0TWFuYWdlcjIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDdXJseUNvbXBvbmVudE1hbmFnZXIsIF9BYnN0cmFjdE1hbmFnZXIyKTsKCiAgICBmdW5jdGlvbiBDdXJseUNvbXBvbmVudE1hbmFnZXIoKSB7CiAgICAgIHJldHVybiBfQWJzdHJhY3RNYW5hZ2VyMi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzM4ID0gQ3VybHlDb21wb25lbnRNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zOC5nZXRMYXlvdXQgPSBmdW5jdGlvbiBnZXRMYXlvdXQoc3RhdGUsIF9yZXNvbHZlcikgewogICAgICByZXR1cm4gewogICAgICAgIC8vIFRPRE8gZml4CiAgICAgICAgaGFuZGxlOiBzdGF0ZS5oYW5kbGUsCiAgICAgICAgc3ltYm9sVGFibGU6IHN0YXRlLnN5bWJvbFRhYmxlCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzM4LnRlbXBsYXRlRm9yID0gZnVuY3Rpb24gdGVtcGxhdGVGb3IoY29tcG9uZW50KSB7CiAgICAgIHZhciBsYXlvdXQgPSBjb21wb25lbnQubGF5b3V0LAogICAgICAgICAgbGF5b3V0TmFtZSA9IGNvbXBvbmVudC5sYXlvdXROYW1lOwogICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKShjb21wb25lbnQpOwogICAgICB2YXIgZmFjdG9yeTsKCiAgICAgIGlmIChsYXlvdXQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGlmIChsYXlvdXROYW1lICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHZhciBfZmFjdG9yeSA9IG93bmVyLmxvb2t1cCgidGVtcGxhdGU6IiArIGxheW91dE5hbWUpOwoKICAgICAgICAgIChmYWxzZSAmJiAhKF9mYWN0b3J5ICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiTGF5b3V0IGAiICsgbGF5b3V0TmFtZSArICJgIG5vdCBmb3VuZCEiLCBfZmFjdG9yeSAhPT0gdW5kZWZpbmVkKSk7CiAgICAgICAgICBmYWN0b3J5ID0gX2ZhY3Rvcnk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGZhY3RvcnkgPSBvd25lci5sb29rdXAoREVGQVVMVF9MQVlPVVQpOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChpc1RlbXBsYXRlRmFjdG9yeShsYXlvdXQpKSB7CiAgICAgICAgZmFjdG9yeSA9IGxheW91dDsKICAgICAgfSBlbHNlIHsKICAgICAgICAvLyB3ZSB3ZXJlIHByb3ZpZGVkIGFuIGluc3RhbmNlIGFscmVhZHkKICAgICAgICByZXR1cm4gbGF5b3V0OwogICAgICB9CgogICAgICByZXR1cm4gZmFjdG9yeShvd25lcik7CiAgICB9OwoKICAgIF9wcm90bzM4LmdldER5bmFtaWNMYXlvdXQgPSBmdW5jdGlvbiBnZXREeW5hbWljTGF5b3V0KF9yZWYzKSB7CiAgICAgIHZhciBjb21wb25lbnQgPSBfcmVmMy5jb21wb25lbnQ7CiAgICAgIHZhciB0ZW1wbGF0ZSQkMSA9IHRoaXMudGVtcGxhdGVGb3IoY29tcG9uZW50KTsKICAgICAgdmFyIGxheW91dCA9IHRlbXBsYXRlJCQxLmFzV3JhcHBlZExheW91dCgpOwogICAgICByZXR1cm4gewogICAgICAgIGhhbmRsZTogbGF5b3V0LmNvbXBpbGUoKSwKICAgICAgICBzeW1ib2xUYWJsZTogbGF5b3V0LnN5bWJvbFRhYmxlCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzM4LmdldFRhZ05hbWUgPSBmdW5jdGlvbiBnZXRUYWdOYW1lKHN0YXRlKSB7CiAgICAgIHZhciBjb21wb25lbnQgPSBzdGF0ZS5jb21wb25lbnQsCiAgICAgICAgICBoYXNXcmFwcGVkRWxlbWVudCA9IHN0YXRlLmhhc1dyYXBwZWRFbGVtZW50OwoKICAgICAgaWYgKCFoYXNXcmFwcGVkRWxlbWVudCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICByZXR1cm4gY29tcG9uZW50ICYmIGNvbXBvbmVudC50YWdOYW1lIHx8ICdkaXYnOwogICAgfTsKCiAgICBfcHJvdG8zOC5nZXRDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiBnZXRDYXBhYmlsaXRpZXMoc3RhdGUpIHsKICAgICAgcmV0dXJuIHN0YXRlLmNhcGFiaWxpdGllczsKICAgIH07CgogICAgX3Byb3RvMzgucHJlcGFyZUFyZ3MgPSBmdW5jdGlvbiBwcmVwYXJlQXJncyhzdGF0ZSwgYXJncykgewogICAgICBpZiAoYXJncy5uYW1lZC5oYXMoJ19fQVJHU19fJykpIHsKICAgICAgICB2YXIgX19hcmdzX18gPSBhcmdzLm5hbWVkLmdldCgnX19BUkdTX18nKS52YWx1ZSgpOwoKICAgICAgICB2YXIgcHJlcGFyZWQgPSB7CiAgICAgICAgICBwb3NpdGlvbmFsOiBFTVBUWV9QT1NJVElPTkFMX0FSR1MsCiAgICAgICAgICBuYW1lZDogKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgYXJncy5uYW1lZC5jYXB0dXJlKCkubWFwLCBfX2FyZ3NfXykKICAgICAgICB9OwoKICAgICAgICBpZiAoZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICkgewogICAgICAgICAgZGVsZXRlIHByZXBhcmVkLm5hbWVkLl9fQVJHU19fOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHByZXBhcmVkOwogICAgICB9CgogICAgICB2YXIgcG9zaXRpb25hbFBhcmFtcyA9IHN0YXRlLkNvbXBvbmVudENsYXNzLmNsYXNzLnBvc2l0aW9uYWxQYXJhbXM7IC8vIGVhcmx5IGV4aXRzCgogICAgICBpZiAocG9zaXRpb25hbFBhcmFtcyA9PT0gdW5kZWZpbmVkIHx8IHBvc2l0aW9uYWxQYXJhbXMgPT09IG51bGwgfHwgYXJncy5wb3NpdGlvbmFsLmxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgbmFtZWQ7CgogICAgICBpZiAodHlwZW9mIHBvc2l0aW9uYWxQYXJhbXMgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgdmFyIF9uYW1lZDsKCiAgICAgICAgKGZhbHNlICYmICEoIWFyZ3MubmFtZWQuaGFzKHBvc2l0aW9uYWxQYXJhbXMpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3Qgc3BlY2lmeSBwb3NpdGlvbmFsIHBhcmFtZXRlcnMgYW5kIHRoZSBoYXNoIGFyZ3VtZW50IGAiICsgcG9zaXRpb25hbFBhcmFtcyArICJgLiIsICFhcmdzLm5hbWVkLmhhcyhwb3NpdGlvbmFsUGFyYW1zKSkpOwogICAgICAgIG5hbWVkID0gKF9uYW1lZCA9IHt9LCBfbmFtZWRbcG9zaXRpb25hbFBhcmFtc10gPSBhcmdzLnBvc2l0aW9uYWwuY2FwdHVyZSgpLCBfbmFtZWQpOwogICAgICAgICgwLCBfcG9seWZpbGxzLmFzc2lnbikobmFtZWQsIGFyZ3MubmFtZWQuY2FwdHVyZSgpLm1hcCk7CiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShwb3NpdGlvbmFsUGFyYW1zKSAmJiBwb3NpdGlvbmFsUGFyYW1zLmxlbmd0aCA+IDApIHsKICAgICAgICB2YXIgY291bnQgPSBNYXRoLm1pbihwb3NpdGlvbmFsUGFyYW1zLmxlbmd0aCwgYXJncy5wb3NpdGlvbmFsLmxlbmd0aCk7CiAgICAgICAgbmFtZWQgPSB7fTsKICAgICAgICAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKG5hbWVkLCBhcmdzLm5hbWVkLmNhcHR1cmUoKS5tYXApOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgICAgIHZhciBuYW1lID0gcG9zaXRpb25hbFBhcmFtc1tpXTsKICAgICAgICAgIChmYWxzZSAmJiAhKCFhcmdzLm5hbWVkLmhhcyhuYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgY2Fubm90IHNwZWNpZnkgYm90aCBhIHBvc2l0aW9uYWwgcGFyYW0gKGF0IHBvc2l0aW9uICIgKyBpICsgIikgYW5kIHRoZSBoYXNoIGFyZ3VtZW50IGAiICsgbmFtZSArICJgLiIsICFhcmdzLm5hbWVkLmhhcyhuYW1lKSkpOwogICAgICAgICAgbmFtZWRbbmFtZV0gPSBhcmdzLnBvc2l0aW9uYWwuYXQoaSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICByZXR1cm4gewogICAgICAgIHBvc2l0aW9uYWw6IF91dGlsLkVNUFRZX0FSUkFZLAogICAgICAgIG5hbWVkOiBuYW1lZAogICAgICB9OwogICAgfQogICAgLyoKICAgICAqIFRoaXMgaG9vayBpcyByZXNwb25zaWJsZSBmb3IgYWN0dWFsbHkgaW5zdGFudGlhdGluZyB0aGUgY29tcG9uZW50IGluc3RhbmNlLgogICAgICogSXQgYWxzbyBpcyB3aGVyZSB3ZSBwZXJmb3JtIGFkZGl0aW9uYWwgYm9va2tlZXBpbmcgdG8gc3VwcG9ydCBsZWdhY3kKICAgICAqIGZlYXR1cmVzIGxpa2UgZXhwb3NlZCBieSB2aWV3IG1peGlucyBsaWtlIENoaWxkVmlld1N1cHBvcnQsIEFjdGlvblN1cHBvcnQsCiAgICAgKiBldGMuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zOC5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoZW52aXJvbm1lbnQsIHN0YXRlLCBhcmdzLCBkeW5hbWljU2NvcGUsIGNhbGxlclNlbGZSZWYsIGhhc0Jsb2NrKSB7CiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICB0aGlzLl9wdXNoVG9EZWJ1Z1N0YWNrKCJjb21wb25lbnQ6IiArIHN0YXRlLm5hbWUsIGVudmlyb25tZW50KTsKICAgICAgfSAvLyBHZXQgdGhlIG5lYXJlc3QgY29uY3JldGUgY29tcG9uZW50IGluc3RhbmNlIGZyb20gdGhlIHNjb3BlLiAiVmlydHVhbCIKICAgICAgLy8gY29tcG9uZW50cyB3aWxsIGJlIHNraXBwZWQuCgoKICAgICAgdmFyIHBhcmVudFZpZXcgPSBkeW5hbWljU2NvcGUudmlldzsgLy8gR2V0IHRoZSBFbWJlci5Db21wb25lbnQgc3ViY2xhc3MgdG8gaW5zdGFudGlhdGUgZm9yIHRoaXMgY29tcG9uZW50LgoKICAgICAgdmFyIGZhY3RvcnkgPSBzdGF0ZS5Db21wb25lbnRDbGFzczsgLy8gQ2FwdHVyZSB0aGUgYXJndW1lbnRzLCB3aGljaCB0ZWxscyBHbGltbWVyIHRvIGdpdmUgdXMgb3VyIG93biwgc3RhYmxlCiAgICAgIC8vIGNvcHkgb2YgdGhlIEFyZ3VtZW50cyBvYmplY3QgdGhhdCBpcyBzYWZlIHRvIGhvbGQgb24gdG8gYmV0d2VlbiByZW5kZXJzLgoKICAgICAgdmFyIGNhcHR1cmVkQXJncyA9IGFyZ3MubmFtZWQuY2FwdHVyZSgpOwogICAgICB2YXIgcHJvcHMgPSBwcm9jZXNzQ29tcG9uZW50QXJncyhjYXB0dXJlZEFyZ3MpOyAvLyBBbGlhcyBgaWRgIGFyZ3VtZW50IHRvIGBlbGVtZW50SWRgIHByb3BlcnR5IG9uIHRoZSBjb21wb25lbnQgaW5zdGFuY2UuCgogICAgICBhbGlhc0lkVG9FbGVtZW50SWQoYXJncywgcHJvcHMpOyAvLyBTZXQgY29tcG9uZW50IGluc3RhbmNlJ3MgcGFyZW50VmlldyBwcm9wZXJ0eSB0byBwb2ludCB0byBuZWFyZXN0IGNvbmNyZXRlCiAgICAgIC8vIGNvbXBvbmVudC4KCiAgICAgIHByb3BzLnBhcmVudFZpZXcgPSBwYXJlbnRWaWV3OyAvLyBTZXQgd2hldGhlciB0aGlzIGNvbXBvbmVudCB3YXMgaW52b2tlZCB3aXRoIGEgYmxvY2sKICAgICAgLy8gKGB7eyNteS1jb21wb25lbnR9fXt7L215LWNvbXBvbmVudH19YCkgb3Igd2l0aG91dCBvbmUKICAgICAgLy8gKGB7e215LWNvbXBvbmVudH19YCkuCgogICAgICBwcm9wc1tIQVNfQkxPQ0tdID0gaGFzQmxvY2s7IC8vIFNhdmUgdGhlIGN1cnJlbnQgYHRoaXNgIGNvbnRleHQgb2YgdGhlIHRlbXBsYXRlIGFzIHRoZSBjb21wb25lbnQncwogICAgICAvLyBgX3RhcmdldGAsIHNvIGJ1YmJsZWQgYWN0aW9ucyBhcmUgcm91dGVkIHRvIHRoZSByaWdodCBwbGFjZS4KCiAgICAgIHByb3BzLl90YXJnZXQgPSBjYWxsZXJTZWxmUmVmLnZhbHVlKCk7IC8vIHN0YXRpYyBsYXlvdXQgYXNzZXJ0cyBDdXJyaWVkRGVmaW5pdGlvbgoKICAgICAgaWYgKHN0YXRlLnRlbXBsYXRlKSB7CiAgICAgICAgcHJvcHMubGF5b3V0ID0gc3RhdGUudGVtcGxhdGU7CiAgICAgIH0gLy8gTm93IHRoYXQgd2UndmUgYnVpbHQgdXAgYWxsIG9mIHRoZSBwcm9wZXJ0aWVzIHRvIHNldCBvbiB0aGUgY29tcG9uZW50IGluc3RhbmNlLAogICAgICAvLyBhY3R1YWxseSBjcmVhdGUgaXQuCgoKICAgICAgdmFyIGNvbXBvbmVudCA9IGZhY3RvcnkuY3JlYXRlKHByb3BzKTsKICAgICAgdmFyIGZpbmFsaXplciA9ICgwLCBfaW5zdHJ1bWVudGF0aW9uLl9pbnN0cnVtZW50U3RhcnQpKCdyZW5kZXIuY29tcG9uZW50JywgaW5pdGlhbFJlbmRlckluc3RydW1lbnREZXRhaWxzLCBjb21wb25lbnQpOyAvLyBXZSBiZWNvbWUgdGhlIG5ldyBwYXJlbnRWaWV3IGZvciBkb3duc3RyZWFtIGNvbXBvbmVudHMsIHNvIHNhdmUgb3VyCiAgICAgIC8vIGNvbXBvbmVudCBvZmYgb24gdGhlIGR5bmFtaWMgc2NvcGUuCgogICAgICBkeW5hbWljU2NvcGUudmlldyA9IGNvbXBvbmVudDsgLy8gVW5sZXNzIHdlJ3JlIHRoZSByb290IGNvbXBvbmVudCwgd2UgbmVlZCB0byBhZGQgb3Vyc2VsdmVzIHRvIG91ciBwYXJlbnQKICAgICAgLy8gY29tcG9uZW50J3MgY2hpbGRWaWV3cyBhcnJheS4KCiAgICAgIGlmIChwYXJlbnRWaWV3ICE9PSBudWxsICYmIHBhcmVudFZpZXcgIT09IHVuZGVmaW5lZCkgewogICAgICAgICgwLCBfdmlld3MuYWRkQ2hpbGRWaWV3KShwYXJlbnRWaWV3LCBjb21wb25lbnQpOwogICAgICB9CgogICAgICBjb21wb25lbnQudHJpZ2dlcignZGlkUmVjZWl2ZUF0dHJzJyk7CiAgICAgIHZhciBoYXNXcmFwcGVkRWxlbWVudCA9IGNvbXBvbmVudC50YWdOYW1lICE9PSAnJzsgLy8gV2UgdXN1YWxseSBkbyB0aGlzIGluIHRoZSBgZGlkQ3JlYXRlRWxlbWVudGAsIGJ1dCB0aGF0IGhvb2sgZG9lc24ndCBmaXJlIGZvciB0YWdsZXNzIGNvbXBvbmVudHMKCiAgICAgIGlmICghaGFzV3JhcHBlZEVsZW1lbnQpIHsKICAgICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgICAgY29tcG9uZW50LnRyaWdnZXIoJ3dpbGxSZW5kZXInKTsKICAgICAgICB9CgogICAgICAgIGNvbXBvbmVudC5fdHJhbnNpdGlvblRvKCdoYXNFbGVtZW50Jyk7CgogICAgICAgIGlmIChlbnZpcm9ubWVudC5pc0ludGVyYWN0aXZlKSB7CiAgICAgICAgICBjb21wb25lbnQudHJpZ2dlcignd2lsbEluc2VydEVsZW1lbnQnKTsKICAgICAgICB9CiAgICAgIH0gLy8gVHJhY2sgYWRkaXRpb25hbCBsaWZlY3ljbGUgbWV0YWRhdGEgYWJvdXQgdGhpcyBjb21wb25lbnQgaW4gYSBzdGF0ZSBidWNrZXQuCiAgICAgIC8vIEVzc2VudGlhbGx5IHdlJ3JlIHNhdmluZyBvZmYgYWxsIHRoZSBzdGF0ZSB3ZSdsbCBuZWVkIGluIHRoZSBmdXR1cmUuCgoKICAgICAgdmFyIGJ1Y2tldCA9IG5ldyBDb21wb25lbnRTdGF0ZUJ1Y2tldChlbnZpcm9ubWVudCwgY29tcG9uZW50LCBjYXB0dXJlZEFyZ3MsIGZpbmFsaXplciwgaGFzV3JhcHBlZEVsZW1lbnQpOwoKICAgICAgaWYgKGFyZ3MubmFtZWQuaGFzKCdjbGFzcycpKSB7CiAgICAgICAgYnVja2V0LmNsYXNzUmVmID0gYXJncy5uYW1lZC5nZXQoJ2NsYXNzJyk7CiAgICAgIH0KCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICBwcm9jZXNzQ29tcG9uZW50SW5pdGlhbGl6YXRpb25Bc3NlcnRpb25zKGNvbXBvbmVudCwgcHJvcHMpOwogICAgICB9CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSAmJiBoYXNXcmFwcGVkRWxlbWVudCkgewogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCd3aWxsUmVuZGVyJyk7CiAgICAgIH0KCiAgICAgIHJldHVybiBidWNrZXQ7CiAgICB9OwoKICAgIF9wcm90bzM4LmdldFNlbGYgPSBmdW5jdGlvbiBnZXRTZWxmKF9yZWY0KSB7CiAgICAgIHZhciBjb21wb25lbnQgPSBfcmVmNC5jb21wb25lbnQ7CiAgICAgIHJldHVybiBjb21wb25lbnRbUk9PVF9SRUZdOwogICAgfTsKCiAgICBfcHJvdG8zOC5kaWRDcmVhdGVFbGVtZW50ID0gZnVuY3Rpb24gZGlkQ3JlYXRlRWxlbWVudChfcmVmNSwgZWxlbWVudCwgb3BlcmF0aW9ucykgewogICAgICB2YXIgY29tcG9uZW50ID0gX3JlZjUuY29tcG9uZW50LAogICAgICAgICAgY2xhc3NSZWYgPSBfcmVmNS5jbGFzc1JlZiwKICAgICAgICAgIGVudmlyb25tZW50ID0gX3JlZjUuZW52aXJvbm1lbnQ7CiAgICAgICgwLCBfdmlld3Muc2V0Vmlld0VsZW1lbnQpKGNvbXBvbmVudCwgZWxlbWVudCk7CiAgICAgICgwLCBfdmlld3Muc2V0RWxlbWVudFZpZXcpKGVsZW1lbnQsIGNvbXBvbmVudCk7CiAgICAgIHZhciBhdHRyaWJ1dGVCaW5kaW5ncyA9IGNvbXBvbmVudC5hdHRyaWJ1dGVCaW5kaW5ncywKICAgICAgICAgIGNsYXNzTmFtZXMgPSBjb21wb25lbnQuY2xhc3NOYW1lcywKICAgICAgICAgIGNsYXNzTmFtZUJpbmRpbmdzID0gY29tcG9uZW50LmNsYXNzTmFtZUJpbmRpbmdzOwoKICAgICAgaWYgKGF0dHJpYnV0ZUJpbmRpbmdzICYmIGF0dHJpYnV0ZUJpbmRpbmdzLmxlbmd0aCkgewogICAgICAgIGFwcGx5QXR0cmlidXRlQmluZGluZ3MoZWxlbWVudCwgYXR0cmlidXRlQmluZGluZ3MsIGNvbXBvbmVudCwgb3BlcmF0aW9ucyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIGlkJCQxID0gY29tcG9uZW50LmVsZW1lbnRJZCA/IGNvbXBvbmVudC5lbGVtZW50SWQgOiAoMCwgX3V0aWxzLmd1aWRGb3IpKGNvbXBvbmVudCk7CiAgICAgICAgb3BlcmF0aW9ucy5zZXRBdHRyaWJ1dGUoJ2lkJywgX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUoaWQkJDEpLCBmYWxzZSwgbnVsbCk7CiAgICAgICAgSXNWaXNpYmxlQmluZGluZy5pbnN0YWxsKGVsZW1lbnQsIGNvbXBvbmVudCwgb3BlcmF0aW9ucyk7CiAgICAgIH0KCiAgICAgIGlmIChjbGFzc1JlZikgewogICAgICAgIHZhciByZWYgPSBuZXcgU2ltcGxlQ2xhc3NOYW1lQmluZGluZ1JlZmVyZW5jZShjbGFzc1JlZiwgY2xhc3NSZWZbJ3Byb3BlcnR5S2V5J10pOwogICAgICAgIG9wZXJhdGlvbnMuc2V0QXR0cmlidXRlKCdjbGFzcycsIHJlZiwgZmFsc2UsIG51bGwpOwogICAgICB9CgogICAgICBpZiAoY2xhc3NOYW1lcyAmJiBjbGFzc05hbWVzLmxlbmd0aCkgewogICAgICAgIGNsYXNzTmFtZXMuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkgewogICAgICAgICAgb3BlcmF0aW9ucy5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgX3J1bnRpbWUyLlByaW1pdGl2ZVJlZmVyZW5jZS5jcmVhdGUobmFtZSksIGZhbHNlLCBudWxsKTsKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgaWYgKGNsYXNzTmFtZUJpbmRpbmdzICYmIGNsYXNzTmFtZUJpbmRpbmdzLmxlbmd0aCkgewogICAgICAgIGNsYXNzTmFtZUJpbmRpbmdzLmZvckVhY2goZnVuY3Rpb24gKGJpbmRpbmcpIHsKICAgICAgICAgIENsYXNzTmFtZUJpbmRpbmcuaW5zdGFsbChlbGVtZW50LCBjb21wb25lbnQsIGJpbmRpbmcsIG9wZXJhdGlvbnMpOwogICAgICAgIH0pOwogICAgICB9CgogICAgICBvcGVyYXRpb25zLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCBfcnVudGltZTIuUHJpbWl0aXZlUmVmZXJlbmNlLmNyZWF0ZSgnZW1iZXItdmlldycpLCBmYWxzZSwgbnVsbCk7CgogICAgICBpZiAoJ2FyaWFSb2xlJyBpbiBjb21wb25lbnQpIHsKICAgICAgICBvcGVyYXRpb25zLnNldEF0dHJpYnV0ZSgncm9sZScsIHJlZmVyZW5jZUZvcktleShjb21wb25lbnQsICdhcmlhUm9sZScpLCBmYWxzZSwgbnVsbCk7CiAgICAgIH0KCiAgICAgIGNvbXBvbmVudC5fdHJhbnNpdGlvblRvKCdoYXNFbGVtZW50Jyk7CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCd3aWxsSW5zZXJ0RWxlbWVudCcpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzM4LmRpZFJlbmRlckxheW91dCA9IGZ1bmN0aW9uIGRpZFJlbmRlckxheW91dChidWNrZXQsIGJvdW5kcykgewogICAgICBidWNrZXQuY29tcG9uZW50W0JPVU5EU10gPSBib3VuZHM7CiAgICAgIGJ1Y2tldC5maW5hbGl6ZSgpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuZGVidWdTdGFjay5wb3AoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zOC5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoX3JlZjYpIHsKICAgICAgdmFyIGFyZ3MgPSBfcmVmNi5hcmdzLAogICAgICAgICAgY29tcG9uZW50ID0gX3JlZjYuY29tcG9uZW50OwogICAgICByZXR1cm4gYXJncyA/ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFthcmdzLnRhZywgY29tcG9uZW50W0RJUlRZX1RBR11dKSA6IGNvbXBvbmVudFtESVJUWV9UQUddOwogICAgfTsKCiAgICBfcHJvdG8zOC5kaWRDcmVhdGUgPSBmdW5jdGlvbiBkaWRDcmVhdGUoX3JlZjcpIHsKICAgICAgdmFyIGNvbXBvbmVudCA9IF9yZWY3LmNvbXBvbmVudCwKICAgICAgICAgIGVudmlyb25tZW50ID0gX3JlZjcuZW52aXJvbm1lbnQ7CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIGNvbXBvbmVudC5fdHJhbnNpdGlvblRvKCdpbkRPTScpOwoKICAgICAgICBjb21wb25lbnQudHJpZ2dlcignZGlkSW5zZXJ0RWxlbWVudCcpOwogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCdkaWRSZW5kZXInKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zOC51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoYnVja2V0KSB7CiAgICAgIHZhciBjb21wb25lbnQgPSBidWNrZXQuY29tcG9uZW50LAogICAgICAgICAgYXJncyA9IGJ1Y2tldC5hcmdzLAogICAgICAgICAgYXJnc1JldmlzaW9uID0gYnVja2V0LmFyZ3NSZXZpc2lvbiwKICAgICAgICAgIGVudmlyb25tZW50ID0gYnVja2V0LmVudmlyb25tZW50OwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuX3B1c2hUb0RlYnVnU3RhY2soY29tcG9uZW50Ll9kZWJ1Z0NvbnRhaW5lcktleSwgZW52aXJvbm1lbnQpOwogICAgICB9CgogICAgICBidWNrZXQuZmluYWxpemVyID0gKDAsIF9pbnN0cnVtZW50YXRpb24uX2luc3RydW1lbnRTdGFydCkoJ3JlbmRlci5jb21wb25lbnQnLCByZXJlbmRlckluc3RydW1lbnREZXRhaWxzLCBjb21wb25lbnQpOwoKICAgICAgaWYgKGFyZ3MgJiYgISgwLCBfcmVmZXJlbmNlLnZhbGlkYXRlKShhcmdzLnRhZywgYXJnc1JldmlzaW9uKSkgewogICAgICAgIHZhciBwcm9wcyA9IHByb2Nlc3NDb21wb25lbnRBcmdzKGFyZ3MpOwogICAgICAgIGJ1Y2tldC5hcmdzUmV2aXNpb24gPSAoMCwgX3JlZmVyZW5jZS52YWx1ZSkoYXJncy50YWcpOwogICAgICAgIGNvbXBvbmVudFtJU19ESVNQQVRDSElOR19BVFRSU10gPSB0cnVlOwogICAgICAgIGNvbXBvbmVudC5zZXRQcm9wZXJ0aWVzKHByb3BzKTsKICAgICAgICBjb21wb25lbnRbSVNfRElTUEFUQ0hJTkdfQVRUUlNdID0gZmFsc2U7CiAgICAgICAgY29tcG9uZW50LnRyaWdnZXIoJ2RpZFVwZGF0ZUF0dHJzJyk7CiAgICAgICAgY29tcG9uZW50LnRyaWdnZXIoJ2RpZFJlY2VpdmVBdHRycycpOwogICAgICB9CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCd3aWxsVXBkYXRlJyk7CiAgICAgICAgY29tcG9uZW50LnRyaWdnZXIoJ3dpbGxSZW5kZXInKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zOC5kaWRVcGRhdGVMYXlvdXQgPSBmdW5jdGlvbiBkaWRVcGRhdGVMYXlvdXQoYnVja2V0KSB7CiAgICAgIGJ1Y2tldC5maW5hbGl6ZSgpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuZGVidWdTdGFjay5wb3AoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zOC5kaWRVcGRhdGUgPSBmdW5jdGlvbiBkaWRVcGRhdGUoX3JlZjgpIHsKICAgICAgdmFyIGNvbXBvbmVudCA9IF9yZWY4LmNvbXBvbmVudCwKICAgICAgICAgIGVudmlyb25tZW50ID0gX3JlZjguZW52aXJvbm1lbnQ7CgogICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCdkaWRVcGRhdGUnKTsKICAgICAgICBjb21wb25lbnQudHJpZ2dlcignZGlkUmVuZGVyJyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMzguZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3Ioc3RhdGVCdWNrZXQpIHsKICAgICAgcmV0dXJuIHN0YXRlQnVja2V0OwogICAgfTsKCiAgICByZXR1cm4gQ3VybHlDb21wb25lbnRNYW5hZ2VyOwogIH0oQWJzdHJhY3RNYW5hZ2VyKTsKCiAgZnVuY3Rpb24gcHJvY2Vzc0NvbXBvbmVudEluaXRpYWxpemF0aW9uQXNzZXJ0aW9ucyhjb21wb25lbnQsIHByb3BzKSB7CiAgICAoZmFsc2UgJiYgIShmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBjbGFzc05hbWVCaW5kaW5ncyA9IGNvbXBvbmVudC5jbGFzc05hbWVCaW5kaW5nczsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2xhc3NOYW1lQmluZGluZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgYmluZGluZyA9IGNsYXNzTmFtZUJpbmRpbmdzW2ldOwoKICAgICAgICBpZiAodHlwZW9mIGJpbmRpbmcgIT09ICdzdHJpbmcnIHx8IGJpbmRpbmcubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0oKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJjbGFzc05hbWVCaW5kaW5ncyBtdXN0IGJlIG5vbi1lbXB0eSBzdHJpbmdzOiAiICsgY29tcG9uZW50LCBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBjbGFzc05hbWVCaW5kaW5ncyA9IGNvbXBvbmVudC5jbGFzc05hbWVCaW5kaW5nczsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2xhc3NOYW1lQmluZGluZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgYmluZGluZyA9IGNsYXNzTmFtZUJpbmRpbmdzW2ldOwoKICAgICAgICBpZiAodHlwZW9mIGJpbmRpbmcgIT09ICdzdHJpbmcnIHx8IGJpbmRpbmcubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0oKSkpOwogICAgKGZhbHNlICYmICEoZnVuY3Rpb24gKCkgewogICAgICB2YXIgY2xhc3NOYW1lQmluZGluZ3MgPSBjb21wb25lbnQuY2xhc3NOYW1lQmluZGluZ3M7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNsYXNzTmFtZUJpbmRpbmdzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGJpbmRpbmcgPSBjbGFzc05hbWVCaW5kaW5nc1tpXTsKCiAgICAgICAgaWYgKGJpbmRpbmcuc3BsaXQoJyAnKS5sZW5ndGggPiAxKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0oKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJjbGFzc05hbWVCaW5kaW5ncyBtdXN0IG5vdCBoYXZlIHNwYWNlcyBpbiB0aGVtOiAiICsgY29tcG9uZW50LCBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBjbGFzc05hbWVCaW5kaW5ncyA9IGNvbXBvbmVudC5jbGFzc05hbWVCaW5kaW5nczsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2xhc3NOYW1lQmluZGluZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgYmluZGluZyA9IGNsYXNzTmFtZUJpbmRpbmdzW2ldOwoKICAgICAgICBpZiAoYmluZGluZy5zcGxpdCgnICcpLmxlbmd0aCA+IDEpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiB0cnVlOwogICAgfSgpKSk7CiAgICAoZmFsc2UgJiYgIShjb21wb25lbnQudGFnTmFtZSAhPT0gJycgfHwgIWNvbXBvbmVudC5jbGFzc05hbWVCaW5kaW5ncyB8fCBjb21wb25lbnQuY2xhc3NOYW1lQmluZGluZ3MubGVuZ3RoID09PSAwKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3QgdXNlIGBjbGFzc05hbWVCaW5kaW5nc2Agb24gYSB0YWctbGVzcyBjb21wb25lbnQ6ICIgKyBjb21wb25lbnQsIGNvbXBvbmVudC50YWdOYW1lICE9PSAnJyB8fCAhY29tcG9uZW50LmNsYXNzTmFtZUJpbmRpbmdzIHx8IGNvbXBvbmVudC5jbGFzc05hbWVCaW5kaW5ncy5sZW5ndGggPT09IDApKTsKICAgIChmYWxzZSAmJiAhKGNvbXBvbmVudC50YWdOYW1lICE9PSAnJyB8fCBwcm9wcy5pZCA9PT0gY29tcG9uZW50LmVsZW1lbnRJZCB8fCAhY29tcG9uZW50LmVsZW1lbnRJZCAmJiBjb21wb25lbnQuZWxlbWVudElkICE9PSAnJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgY2Fubm90IHVzZSBgZWxlbWVudElkYCBvbiBhIHRhZy1sZXNzIGNvbXBvbmVudDogIiArIGNvbXBvbmVudCwgY29tcG9uZW50LnRhZ05hbWUgIT09ICcnIHx8IHByb3BzLmlkID09PSBjb21wb25lbnQuZWxlbWVudElkIHx8ICFjb21wb25lbnQuZWxlbWVudElkICYmIGNvbXBvbmVudC5lbGVtZW50SWQgIT09ICcnKSk7CiAgICAoZmFsc2UgJiYgIShjb21wb25lbnQudGFnTmFtZSAhPT0gJycgfHwgIWNvbXBvbmVudC5hdHRyaWJ1dGVCaW5kaW5ncyB8fCBjb21wb25lbnQuYXR0cmlidXRlQmluZGluZ3MubGVuZ3RoID09PSAwKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3QgdXNlIGBhdHRyaWJ1dGVCaW5kaW5nc2Agb24gYSB0YWctbGVzcyBjb21wb25lbnQ6ICIgKyBjb21wb25lbnQsIGNvbXBvbmVudC50YWdOYW1lICE9PSAnJyB8fCAhY29tcG9uZW50LmF0dHJpYnV0ZUJpbmRpbmdzIHx8IGNvbXBvbmVudC5hdHRyaWJ1dGVCaW5kaW5ncy5sZW5ndGggPT09IDApKTsKICB9CgogIGZ1bmN0aW9uIGluaXRpYWxSZW5kZXJJbnN0cnVtZW50RGV0YWlscyhjb21wb25lbnQpIHsKICAgIHJldHVybiBjb21wb25lbnQuaW5zdHJ1bWVudERldGFpbHMoewogICAgICBpbml0aWFsUmVuZGVyOiB0cnVlCiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHJlcmVuZGVySW5zdHJ1bWVudERldGFpbHMoY29tcG9uZW50KSB7CiAgICByZXR1cm4gY29tcG9uZW50Lmluc3RydW1lbnREZXRhaWxzKHsKICAgICAgaW5pdGlhbFJlbmRlcjogZmFsc2UKICAgIH0pOwogIH0KCiAgdmFyIENVUkxZX0NBUEFCSUxJVElFUyA9IHsKICAgIGR5bmFtaWNMYXlvdXQ6IHRydWUsCiAgICBkeW5hbWljVGFnOiB0cnVlLAogICAgcHJlcGFyZUFyZ3M6IHRydWUsCiAgICBjcmVhdGVBcmdzOiB0cnVlLAogICAgYXR0cmlidXRlSG9vazogdHJ1ZSwKICAgIGVsZW1lbnRIb29rOiB0cnVlLAogICAgY3JlYXRlQ2FsbGVyOiB0cnVlLAogICAgZHluYW1pY1Njb3BlOiB0cnVlLAogICAgdXBkYXRlSG9vazogdHJ1ZSwKICAgIGNyZWF0ZUluc3RhbmNlOiB0cnVlCiAgfTsKICB2YXIgQ1VSTFlfQ09NUE9ORU5UX01BTkFHRVIgPSBuZXcgQ3VybHlDb21wb25lbnRNYW5hZ2VyKCk7CgogIHZhciBDdXJseUNvbXBvbmVudERlZmluaXRpb24gPSAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc2hhZG93ZWQtdmFyaWFibGUKICBmdW5jdGlvbiBDdXJseUNvbXBvbmVudERlZmluaXRpb24obmFtZSwgQ29tcG9uZW50Q2xhc3MsIGhhbmRsZSwgdGVtcGxhdGUkJDEsIGFyZ3MpIHsKICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICB0aGlzLkNvbXBvbmVudENsYXNzID0gQ29tcG9uZW50Q2xhc3M7CiAgICB0aGlzLmhhbmRsZSA9IGhhbmRsZTsKICAgIHRoaXMudGVtcGxhdGUgPSB0ZW1wbGF0ZSQkMTsKICAgIHRoaXMubWFuYWdlciA9IENVUkxZX0NPTVBPTkVOVF9NQU5BR0VSOwogICAgdmFyIGxheW91dCA9IHRlbXBsYXRlJCQxICYmIHRlbXBsYXRlJCQxLmFzTGF5b3V0KCk7CiAgICB2YXIgc3ltYm9sVGFibGUgPSBsYXlvdXQgPyBsYXlvdXQuc3ltYm9sVGFibGUgOiB1bmRlZmluZWQ7CiAgICB0aGlzLnN5bWJvbFRhYmxlID0gc3ltYm9sVGFibGU7CiAgICB0aGlzLnRlbXBsYXRlID0gdGVtcGxhdGUkJDE7CiAgICB0aGlzLmFyZ3MgPSBhcmdzOwogICAgdGhpcy5zdGF0ZSA9IHsKICAgICAgbmFtZTogbmFtZSwKICAgICAgQ29tcG9uZW50Q2xhc3M6IENvbXBvbmVudENsYXNzLAogICAgICBoYW5kbGU6IGhhbmRsZSwKICAgICAgdGVtcGxhdGU6IHRlbXBsYXRlJCQxLAogICAgICBjYXBhYmlsaXRpZXM6IENVUkxZX0NBUEFCSUxJVElFUywKICAgICAgc3ltYm9sVGFibGU6IHN5bWJvbFRhYmxlCiAgICB9OwogIH07CgogIHZhciBSb290Q29tcG9uZW50TWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ3VybHlDb21wb25lbnRNYW5hZ2UpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShSb290Q29tcG9uZW50TWFuYWdlciwgX0N1cmx5Q29tcG9uZW50TWFuYWdlKTsKCiAgICBmdW5jdGlvbiBSb290Q29tcG9uZW50TWFuYWdlcihjb21wb25lbnQpIHsKICAgICAgdmFyIF90aGlzMTk7CgogICAgICBfdGhpczE5ID0gX0N1cmx5Q29tcG9uZW50TWFuYWdlLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXMxOS5jb21wb25lbnQgPSBjb21wb25lbnQ7CiAgICAgIHJldHVybiBfdGhpczE5OwogICAgfQoKICAgIHZhciBfcHJvdG8zOSA9IFJvb3RDb21wb25lbnRNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zOS5nZXRMYXlvdXQgPSBmdW5jdGlvbiBnZXRMYXlvdXQoX3N0YXRlKSB7CiAgICAgIHZhciB0ZW1wbGF0ZSA9IHRoaXMudGVtcGxhdGVGb3IodGhpcy5jb21wb25lbnQpOwogICAgICB2YXIgbGF5b3V0ID0gdGVtcGxhdGUuYXNXcmFwcGVkTGF5b3V0KCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiBsYXlvdXQuY29tcGlsZSgpLAogICAgICAgIHN5bWJvbFRhYmxlOiBsYXlvdXQuc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvMzkuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKGVudmlyb25tZW50LCBfc3RhdGUsIF9hcmdzLCBkeW5hbWljU2NvcGUpIHsKICAgICAgdmFyIGNvbXBvbmVudCA9IHRoaXMuY29tcG9uZW50OwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuX3B1c2hUb0RlYnVnU3RhY2soY29tcG9uZW50Ll9kZWJ1Z0NvbnRhaW5lcktleSwgZW52aXJvbm1lbnQpOwogICAgICB9CgogICAgICB2YXIgZmluYWxpemVyID0gKDAsIF9pbnN0cnVtZW50YXRpb24uX2luc3RydW1lbnRTdGFydCkoJ3JlbmRlci5jb21wb25lbnQnLCBpbml0aWFsUmVuZGVySW5zdHJ1bWVudERldGFpbHMsIGNvbXBvbmVudCk7CiAgICAgIGR5bmFtaWNTY29wZS52aWV3ID0gY29tcG9uZW50OwogICAgICB2YXIgaGFzV3JhcHBlZEVsZW1lbnQgPSBjb21wb25lbnQudGFnTmFtZSAhPT0gJyc7IC8vIFdlIHVzdWFsbHkgZG8gdGhpcyBpbiB0aGUgYGRpZENyZWF0ZUVsZW1lbnRgLCBidXQgdGhhdCBob29rIGRvZXNuJ3QgZmlyZSBmb3IgdGFnbGVzcyBjb21wb25lbnRzCgogICAgICBpZiAoIWhhc1dyYXBwZWRFbGVtZW50KSB7CiAgICAgICAgaWYgKGVudmlyb25tZW50LmlzSW50ZXJhY3RpdmUpIHsKICAgICAgICAgIGNvbXBvbmVudC50cmlnZ2VyKCd3aWxsUmVuZGVyJyk7CiAgICAgICAgfQoKICAgICAgICBjb21wb25lbnQuX3RyYW5zaXRpb25UbygnaGFzRWxlbWVudCcpOwoKICAgICAgICBpZiAoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgICAgY29tcG9uZW50LnRyaWdnZXIoJ3dpbGxJbnNlcnRFbGVtZW50Jyk7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgcHJvY2Vzc0NvbXBvbmVudEluaXRpYWxpemF0aW9uQXNzZXJ0aW9ucyhjb21wb25lbnQsIHt9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5ldyBDb21wb25lbnRTdGF0ZUJ1Y2tldChlbnZpcm9ubWVudCwgY29tcG9uZW50LCBudWxsLCBmaW5hbGl6ZXIsIGhhc1dyYXBwZWRFbGVtZW50KTsKICAgIH07CgogICAgcmV0dXJuIFJvb3RDb21wb25lbnRNYW5hZ2VyOwogIH0oQ3VybHlDb21wb25lbnRNYW5hZ2VyKTsgLy8gUk9PVCBpcyB0aGUgdG9wLWxldmVsIHRlbXBsYXRlIGl0IGhhcyBub3RoaW5nIGJ1dCBvbmUgeWllbGQuCiAgLy8gaXQgaXMgc3VwcG9zZWQgdG8gaGF2ZSBhIGR1bW15IGVsZW1lbnQKCgogIHZhciBST09UX0NBUEFCSUxJVElFUyA9IHsKICAgIGR5bmFtaWNMYXlvdXQ6IGZhbHNlLAogICAgZHluYW1pY1RhZzogdHJ1ZSwKICAgIHByZXBhcmVBcmdzOiBmYWxzZSwKICAgIGNyZWF0ZUFyZ3M6IGZhbHNlLAogICAgYXR0cmlidXRlSG9vazogdHJ1ZSwKICAgIGVsZW1lbnRIb29rOiB0cnVlLAogICAgY3JlYXRlQ2FsbGVyOiB0cnVlLAogICAgZHluYW1pY1Njb3BlOiB0cnVlLAogICAgdXBkYXRlSG9vazogdHJ1ZSwKICAgIGNyZWF0ZUluc3RhbmNlOiB0cnVlCiAgfTsKCiAgdmFyIFJvb3RDb21wb25lbnREZWZpbml0aW9uID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUm9vdENvbXBvbmVudERlZmluaXRpb24oY29tcG9uZW50KSB7CiAgICAgIHRoaXMuY29tcG9uZW50ID0gY29tcG9uZW50OwogICAgICB2YXIgbWFuYWdlciA9IG5ldyBSb290Q29tcG9uZW50TWFuYWdlcihjb21wb25lbnQpOwogICAgICB0aGlzLm1hbmFnZXIgPSBtYW5hZ2VyOwoKICAgICAgdmFyIGZhY3RvcnkgPSBfY29udGFpbmVyLkZBQ1RPUllfRk9SLmdldChjb21wb25lbnQpOwoKICAgICAgdGhpcy5zdGF0ZSA9IHsKICAgICAgICBuYW1lOiBmYWN0b3J5LmZ1bGxOYW1lLnNsaWNlKDEwKSwKICAgICAgICBjYXBhYmlsaXRpZXM6IFJPT1RfQ0FQQUJJTElUSUVTLAogICAgICAgIENvbXBvbmVudENsYXNzOiBmYWN0b3J5LAogICAgICAgIGhhbmRsZTogbnVsbAogICAgICB9OwogICAgfQoKICAgIHZhciBfcHJvdG80MCA9IFJvb3RDb21wb25lbnREZWZpbml0aW9uLnByb3RvdHlwZTsKCiAgICBfcHJvdG80MC5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoX3JlZjkpIHsKICAgICAgdmFyIGNvbXBvbmVudCA9IF9yZWY5LmNvbXBvbmVudDsKICAgICAgcmV0dXJuIGNvbXBvbmVudFtESVJUWV9UQUddOwogICAgfTsKCiAgICByZXR1cm4gUm9vdENvbXBvbmVudERlZmluaXRpb247CiAgfSgpOwoKICB2YXIgRHluYW1pY1Njb3BlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRHluYW1pY1Njb3BlKHZpZXcsIG91dGxldFN0YXRlKSB7CiAgICAgIHRoaXMudmlldyA9IHZpZXc7CiAgICAgIHRoaXMub3V0bGV0U3RhdGUgPSBvdXRsZXRTdGF0ZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDEgPSBEeW5hbWljU2NvcGUucHJvdG90eXBlOwoKICAgIF9wcm90bzQxLmNoaWxkID0gZnVuY3Rpb24gY2hpbGQoKSB7CiAgICAgIHJldHVybiBuZXcgRHluYW1pY1Njb3BlKHRoaXMudmlldywgdGhpcy5vdXRsZXRTdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzQxLmdldCA9IGZ1bmN0aW9uIGdldChrZXkpIHsKICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aAogICAgICAoZmFsc2UgJiYgIShrZXkgPT09ICdvdXRsZXRTdGF0ZScpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVXNpbmcgYC1nZXQtZHluYW1pYy1zY29wZWAgaXMgb25seSBzdXBwb3J0ZWQgZm9yIGBvdXRsZXRTdGF0ZWAgKHlvdSB1c2VkIGAiICsga2V5ICsgImApLiIsIGtleSA9PT0gJ291dGxldFN0YXRlJykpOwogICAgICByZXR1cm4gdGhpcy5vdXRsZXRTdGF0ZTsKICAgIH07CgogICAgX3Byb3RvNDEuc2V0ID0gZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUkJDEpIHsKICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aAogICAgICAoZmFsc2UgJiYgIShrZXkgPT09ICdvdXRsZXRTdGF0ZScpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVXNpbmcgYC13aXRoLWR5bmFtaWMtc2NvcGVgIGlzIG9ubHkgc3VwcG9ydGVkIGZvciBgb3V0bGV0U3RhdGVgICh5b3UgdXNlZCBgIiArIGtleSArICJgKS4iLCBrZXkgPT09ICdvdXRsZXRTdGF0ZScpKTsKICAgICAgdGhpcy5vdXRsZXRTdGF0ZSA9IHZhbHVlJCQxOwogICAgICByZXR1cm4gdmFsdWUkJDE7CiAgICB9OwoKICAgIHJldHVybiBEeW5hbWljU2NvcGU7CiAgfSgpOwoKICB2YXIgUm9vdFN0YXRlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUm9vdFN0YXRlKHJvb3QsIGVudiwgdGVtcGxhdGUsIHNlbGYsIHBhcmVudEVsZW1lbnQsIGR5bmFtaWNTY29wZSwgYnVpbGRlcikgewogICAgICB2YXIgX3RoaXMyMCA9IHRoaXM7CgogICAgICAoZmFsc2UgJiYgISh0ZW1wbGF0ZSAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3QgcmVuZGVyIGAiICsgc2VsZi52YWx1ZSgpICsgImAgd2l0aG91dCBhIHRlbXBsYXRlLiIsIHRlbXBsYXRlICE9PSB1bmRlZmluZWQpKTsKICAgICAgdGhpcy5pZCA9ICgwLCBfdmlld3MuZ2V0Vmlld0lkKShyb290KTsKICAgICAgdGhpcy5lbnYgPSBlbnY7CiAgICAgIHRoaXMucm9vdCA9IHJvb3Q7CiAgICAgIHRoaXMucmVzdWx0ID0gdW5kZWZpbmVkOwogICAgICB0aGlzLnNob3VsZFJlZmx1c2ggPSBmYWxzZTsKICAgICAgdGhpcy5kZXN0cm95ZWQgPSBmYWxzZTsKICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMgPSB7CiAgICAgICAgYWx3YXlzUmV2YWxpZGF0ZTogZmFsc2UKICAgICAgfTsKCiAgICAgIHRoaXMucmVuZGVyID0gZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBsYXlvdXQgPSB0ZW1wbGF0ZS5hc0xheW91dCgpOwogICAgICAgIHZhciBoYW5kbGUgPSBsYXlvdXQuY29tcGlsZSgpOwogICAgICAgIHZhciBpdGVyYXRvciA9ICgwLCBfcnVudGltZTIucmVuZGVyTWFpbikobGF5b3V0Wydjb21waWxlciddLnByb2dyYW0sIGVudiwgc2VsZiwgZHluYW1pY1Njb3BlLCBidWlsZGVyKGVudiwgewogICAgICAgICAgZWxlbWVudDogcGFyZW50RWxlbWVudCwKICAgICAgICAgIG5leHRTaWJsaW5nOiBudWxsCiAgICAgICAgfSksIGhhbmRsZSk7CiAgICAgICAgdmFyIGl0ZXJhdG9yUmVzdWx0OwoKICAgICAgICBkbyB7CiAgICAgICAgICBpdGVyYXRvclJlc3VsdCA9IGl0ZXJhdG9yLm5leHQoKTsKICAgICAgICB9IHdoaWxlICghaXRlcmF0b3JSZXN1bHQuZG9uZSk7CgogICAgICAgIHZhciByZXN1bHQgPSBfdGhpczIwLnJlc3VsdCA9IGl0ZXJhdG9yUmVzdWx0LnZhbHVlOyAvLyBvdmVycmlkZSAucmVuZGVyIGZ1bmN0aW9uIGFmdGVyIGluaXRpYWwgcmVuZGVyCgogICAgICAgIF90aGlzMjAucmVuZGVyID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuIHJlc3VsdC5yZXJlbmRlcihvcHRpb25zKTsKICAgICAgICB9OwogICAgICB9OwogICAgfQoKICAgIHZhciBfcHJvdG80MiA9IFJvb3RTdGF0ZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNDIuaXNGb3IgPSBmdW5jdGlvbiBpc0Zvcihwb3NzaWJsZVJvb3QpIHsKICAgICAgcmV0dXJuIHRoaXMucm9vdCA9PT0gcG9zc2libGVSb290OwogICAgfTsKCiAgICBfcHJvdG80Mi5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdmFyIHJlc3VsdCA9IHRoaXMucmVzdWx0LAogICAgICAgICAgZW52ID0gdGhpcy5lbnY7CiAgICAgIHRoaXMuZGVzdHJveWVkID0gdHJ1ZTsKICAgICAgdGhpcy5lbnYgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMucm9vdCA9IG51bGw7CiAgICAgIHRoaXMucmVzdWx0ID0gdW5kZWZpbmVkOwogICAgICB0aGlzLnJlbmRlciA9IHVuZGVmaW5lZDsKCiAgICAgIGlmIChyZXN1bHQpIHsKICAgICAgICAvKgogICAgICAgICBIYW5kbGVzIHRoZXNlIHNjZW5hcmlvczoKICAgICAgICAgICAgICAgICogV2hlbiByb290cyBhcmUgcmVtb3ZlZCBkdXJpbmcgc3RhbmRhcmQgcmVuZGVyaW5nIHByb2Nlc3MsIGEgdHJhbnNhY3Rpb24gZXhpc3RzIGFscmVhZHkKICAgICAgICAgICBgLmJlZ2luKClgIC8gYC5jb21taXQoKWAgYXJlIG5vdCBuZWVkZWQuCiAgICAgICAgICogV2hlbiByb290cyBhcmUgYmVpbmcgZGVzdHJveWVkIG1hbnVhbGx5IChgY29tcG9uZW50LmFwcGVuZCgpOyBjb21wb25lbnQuZGVzdHJveSgpIGNhc2UpLCBubwogICAgICAgICAgIHRyYW5zYWN0aW9uIGV4aXN0cyBhbHJlYWR5LgogICAgICAgICAqIFdoZW4gcm9vdHMgYXJlIGJlaW5nIGRlc3Ryb3llZCBkdXJpbmcgYFJlbmRlcmVyI2Rlc3Ryb3lgLCBubyB0cmFuc2FjdGlvbiBleGlzdHMKICAgICAgICAgICAgICAgICovCiAgICAgICAgdmFyIG5lZWRzVHJhbnNhY3Rpb24gPSAhZW52LmluVHJhbnNhY3Rpb247CgogICAgICAgIGlmIChuZWVkc1RyYW5zYWN0aW9uKSB7CiAgICAgICAgICBlbnYuYmVnaW4oKTsKICAgICAgICB9CgogICAgICAgIHRyeSB7CiAgICAgICAgICByZXN1bHQuZGVzdHJveSgpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBpZiAobmVlZHNUcmFuc2FjdGlvbikgewogICAgICAgICAgICBlbnYuY29tbWl0KCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBSb290U3RhdGU7CiAgfSgpOwoKICB2YXIgcmVuZGVyZXJzID0gW107CgogIGZ1bmN0aW9uIF9yZXNldFJlbmRlcmVycygpIHsKICAgIHJlbmRlcmVycy5sZW5ndGggPSAwOwogIH0KCiAgZnVuY3Rpb24gcmVnaXN0ZXIocmVuZGVyZXIpIHsKICAgIChmYWxzZSAmJiAhKHJlbmRlcmVycy5pbmRleE9mKHJlbmRlcmVyKSA9PT0gLTEpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IHJlZ2lzdGVyIHRoZSBzYW1lIHJlbmRlcmVyIHR3aWNlJywgcmVuZGVyZXJzLmluZGV4T2YocmVuZGVyZXIpID09PSAtMSkpOwogICAgcmVuZGVyZXJzLnB1c2gocmVuZGVyZXIpOwogIH0KCiAgZnVuY3Rpb24gZGVyZWdpc3RlcihyZW5kZXJlcikgewogICAgdmFyIGluZGV4ID0gcmVuZGVyZXJzLmluZGV4T2YocmVuZGVyZXIpOwogICAgKGZhbHNlICYmICEoaW5kZXggIT09IC0xKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0Nhbm5vdCBkZXJlZ2lzdGVyIHVua25vd24gdW5yZWdpc3RlcmVkIHJlbmRlcmVyJywgaW5kZXggIT09IC0xKSk7CiAgICByZW5kZXJlcnMuc3BsaWNlKGluZGV4LCAxKTsKICB9CgogIGZ1bmN0aW9uIGxvb3BCZWdpbigpIHsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVuZGVyZXJzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHJlbmRlcmVyc1tpXS5fc2NoZWR1bGVSZXZhbGlkYXRlKCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBLKCkgewogICAgLyogbm9vcCAqLwogIH0KCiAgdmFyIHJlbmRlclNldHRsZWREZWZlcnJlZCA9IG51bGw7CiAgLyoKICAgIFJldHVybnMgYSBwcm9taXNlIHdoaWNoIHdpbGwgcmVzb2x2ZSB3aGVuIHJlbmRlcmluZyBoYXMgc2V0dGxlZC4gU2V0dGxlZCBpbgogICAgdGhpcyBjb250ZXh0IGlzIGRlZmluZWQgYXMgd2hlbiBhbGwgb2YgdGhlIHRhZ3MgaW4gdXNlIGFyZSAiY3VycmVudCIgKGUuZy4KICAgIGByZW5kZXJlcnMuZXZlcnkociA9PiByLl9pc1ZhbGlkKCkpYCkuIFdoZW4gdGhpcyBpcyBjaGVja2VkIGF0IHRoZSBfZW5kXyBvZgogICAgdGhlIHJ1biBsb29wLCB0aGlzIGVzc2VudGlhbGx5IGd1YXJhbnRlZXMgdGhhdCBhbGwgcmVuZGVyaW5nIGlzIGNvbXBsZXRlZC4KICAKICAgIEBtZXRob2QgcmVuZGVyU2V0dGxlZAogICAgQHJldHVybnMge1Byb21pc2U8dm9pZD59IGEgcHJvbWlzZSB3aGljaCBmdWxmaWxscyB3aGVuIHJlbmRlcmluZyBoYXMgc2V0dGxlZAogICovCgogIGZ1bmN0aW9uIHJlbmRlclNldHRsZWQoKSB7CiAgICBpZiAocmVuZGVyU2V0dGxlZERlZmVycmVkID09PSBudWxsKSB7CiAgICAgIHJlbmRlclNldHRsZWREZWZlcnJlZCA9IF9yc3ZwLmRlZmF1bHQuZGVmZXIoKTsgLy8gaWYgdGhlcmUgaXMgbm8gY3VycmVudCBydW5sb29wLCB0aGUgcHJvbWlzZSBjcmVhdGVkIGFib3ZlIHdpbGwgbm90IGhhdmUKICAgICAgLy8gYSBjaGFuY2UgdG8gcmVzb2x2ZSAoYmVjYXVzZSBpdHMgcmVzb2x2ZWQgaW4gYmFja2J1cm5lcidzICJlbmQiIGV2ZW50KQoKICAgICAgaWYgKCEoMCwgX3J1bmxvb3AuZ2V0Q3VycmVudFJ1bkxvb3ApKCkpIHsKICAgICAgICAvLyBlbnN1cmUgYSBydW5sb29wIGhhcyBiZWVuIGtpY2tlZCBvZmYKICAgICAgICBfcnVubG9vcC5iYWNrYnVybmVyLnNjaGVkdWxlKCdhY3Rpb25zJywgbnVsbCwgSyk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcmVuZGVyU2V0dGxlZERlZmVycmVkLnByb21pc2U7CiAgfQoKICBmdW5jdGlvbiByZXNvbHZlUmVuZGVyUHJvbWlzZSgpIHsKICAgIGlmIChyZW5kZXJTZXR0bGVkRGVmZXJyZWQgIT09IG51bGwpIHsKICAgICAgdmFyIHJlc29sdmUgPSByZW5kZXJTZXR0bGVkRGVmZXJyZWQucmVzb2x2ZTsKICAgICAgcmVuZGVyU2V0dGxlZERlZmVycmVkID0gbnVsbDsKCiAgICAgIF9ydW5sb29wLmJhY2tidXJuZXIuam9pbihudWxsLCByZXNvbHZlKTsKICAgIH0KICB9CgogIHZhciBsb29wcyA9IDA7CgogIGZ1bmN0aW9uIGxvb3BFbmQoKSB7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbmRlcmVycy5sZW5ndGg7IGkrKykgewogICAgICBpZiAoIXJlbmRlcmVyc1tpXS5faXNWYWxpZCgpKSB7CiAgICAgICAgaWYgKGxvb3BzID4gX2Vudmlyb25tZW50Mi5FTlYuX1JFUkVOREVSX0xPT1BfTElNSVQpIHsKICAgICAgICAgIGxvb3BzID0gMDsgLy8gVE9ETzogZG8gc29tZXRoaW5nIGJldHRlcgoKICAgICAgICAgIHJlbmRlcmVyc1tpXS5kZXN0cm95KCk7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2luZmluaXRlIHJlbmRlcmluZyBpbnZhbGlkYXRpb24gZGV0ZWN0ZWQnKTsKICAgICAgICB9CgogICAgICAgIGxvb3BzKys7CiAgICAgICAgcmV0dXJuIF9ydW5sb29wLmJhY2tidXJuZXIuam9pbihudWxsLCBLKTsKICAgICAgfQogICAgfQoKICAgIGxvb3BzID0gMDsKICAgIHJlc29sdmVSZW5kZXJQcm9taXNlKCk7CiAgfQoKICBfcnVubG9vcC5iYWNrYnVybmVyLm9uKCdiZWdpbicsIGxvb3BCZWdpbik7CgogIF9ydW5sb29wLmJhY2tidXJuZXIub24oJ2VuZCcsIGxvb3BFbmQpOwoKICB2YXIgUmVuZGVyZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBSZW5kZXJlcihlbnYsIHJvb3RUZW1wbGF0ZSwgdmlld1JlZ2lzdHJ5LCBkZXN0aW5lZEZvckRPTSwgYnVpbGRlcikgewogICAgICBpZiAoZGVzdGluZWRGb3JET00gPT09IHZvaWQgMCkgewogICAgICAgIGRlc3RpbmVkRm9yRE9NID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIGlmIChidWlsZGVyID09PSB2b2lkIDApIHsKICAgICAgICBidWlsZGVyID0gX3J1bnRpbWUyLmNsaWVudEJ1aWxkZXI7CiAgICAgIH0KCiAgICAgIHRoaXMuX2VudiA9IGVudjsKICAgICAgdGhpcy5fcm9vdFRlbXBsYXRlID0gcm9vdFRlbXBsYXRlKGVudi5vd25lcik7CiAgICAgIHRoaXMuX3ZpZXdSZWdpc3RyeSA9IHZpZXdSZWdpc3RyeTsKICAgICAgdGhpcy5fZGVzdGluZWRGb3JET00gPSBkZXN0aW5lZEZvckRPTTsKICAgICAgdGhpcy5fZGVzdHJveWVkID0gZmFsc2U7CiAgICAgIHRoaXMuX3Jvb3RzID0gW107CiAgICAgIHRoaXMuX2xhc3RSZXZpc2lvbiA9IC0xOwogICAgICB0aGlzLl9pc1JlbmRlcmluZ1Jvb3RzID0gZmFsc2U7CiAgICAgIHRoaXMuX3JlbW92ZWRSb290cyA9IFtdOwogICAgICB0aGlzLl9idWlsZGVyID0gYnVpbGRlcjsKICAgIH0gLy8gcmVuZGVyZXIgSE9PS1MKCgogICAgdmFyIF9wcm90bzQzID0gUmVuZGVyZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzQzLmFwcGVuZE91dGxldFZpZXcgPSBmdW5jdGlvbiBhcHBlbmRPdXRsZXRWaWV3KHZpZXcsIHRhcmdldCkgewogICAgICB2YXIgZGVmaW5pdGlvbiA9IGNyZWF0ZVJvb3RPdXRsZXQodmlldyk7CgogICAgICB0aGlzLl9hcHBlbmREZWZpbml0aW9uKHZpZXcsICgwLCBfcnVudGltZTIuY3VycnkpKGRlZmluaXRpb24pLCB0YXJnZXQpOwogICAgfTsKCiAgICBfcHJvdG80My5hcHBlbmRUbyA9IGZ1bmN0aW9uIGFwcGVuZFRvKHZpZXcsIHRhcmdldCkgewogICAgICB2YXIgZGVmaW5pdGlvbiA9IG5ldyBSb290Q29tcG9uZW50RGVmaW5pdGlvbih2aWV3KTsKCiAgICAgIHRoaXMuX2FwcGVuZERlZmluaXRpb24odmlldywgKDAsIF9ydW50aW1lMi5jdXJyeSkoZGVmaW5pdGlvbiksIHRhcmdldCk7CiAgICB9OwoKICAgIF9wcm90bzQzLl9hcHBlbmREZWZpbml0aW9uID0gZnVuY3Rpb24gX2FwcGVuZERlZmluaXRpb24ocm9vdCwgZGVmaW5pdGlvbiwgdGFyZ2V0KSB7CiAgICAgIHZhciBzZWxmID0gbmV3IFVuYm91bmRSZWZlcmVuY2UoZGVmaW5pdGlvbik7CiAgICAgIHZhciBkeW5hbWljU2NvcGUgPSBuZXcgRHluYW1pY1Njb3BlKG51bGwsIF9ydW50aW1lMi5VTkRFRklORURfUkVGRVJFTkNFKTsKICAgICAgdmFyIHJvb3RTdGF0ZSA9IG5ldyBSb290U3RhdGUocm9vdCwgdGhpcy5fZW52LCB0aGlzLl9yb290VGVtcGxhdGUsIHNlbGYsIHRhcmdldCwgZHluYW1pY1Njb3BlLCB0aGlzLl9idWlsZGVyKTsKCiAgICAgIHRoaXMuX3JlbmRlclJvb3Qocm9vdFN0YXRlKTsKICAgIH07CgogICAgX3Byb3RvNDMucmVyZW5kZXIgPSBmdW5jdGlvbiByZXJlbmRlcigpIHsKICAgICAgdGhpcy5fc2NoZWR1bGVSZXZhbGlkYXRlKCk7CiAgICB9OwoKICAgIF9wcm90bzQzLnJlZ2lzdGVyID0gZnVuY3Rpb24gcmVnaXN0ZXIodmlldykgewogICAgICB2YXIgaWQgPSAoMCwgX3ZpZXdzLmdldFZpZXdJZCkodmlldyk7CiAgICAgIChmYWxzZSAmJiAhKCF0aGlzLl92aWV3UmVnaXN0cnlbaWRdKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0F0dGVtcHRlZCB0byByZWdpc3RlciBhIHZpZXcgd2l0aCBhbiBpZCBhbHJlYWR5IGluIHVzZTogJyArIGlkLCAhdGhpcy5fdmlld1JlZ2lzdHJ5W2lkXSkpOwogICAgICB0aGlzLl92aWV3UmVnaXN0cnlbaWRdID0gdmlldzsKICAgIH07CgogICAgX3Byb3RvNDMudW5yZWdpc3RlciA9IGZ1bmN0aW9uIHVucmVnaXN0ZXIodmlldykgewogICAgICBkZWxldGUgdGhpcy5fdmlld1JlZ2lzdHJ5WygwLCBfdmlld3MuZ2V0Vmlld0lkKSh2aWV3KV07CiAgICB9OwoKICAgIF9wcm90bzQzLnJlbW92ZSA9IGZ1bmN0aW9uIHJlbW92ZSh2aWV3KSB7CiAgICAgIHZpZXcuX3RyYW5zaXRpb25UbygnZGVzdHJveWluZycpOwoKICAgICAgdGhpcy5jbGVhbnVwUm9vdEZvcih2aWV3KTsKCiAgICAgIGlmICh0aGlzLl9kZXN0aW5lZEZvckRPTSkgewogICAgICAgIHZpZXcudHJpZ2dlcignZGlkRGVzdHJveUVsZW1lbnQnKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG80My5jbGVhbnVwUm9vdEZvciA9IGZ1bmN0aW9uIGNsZWFudXBSb290Rm9yKHZpZXcpIHsKICAgICAgLy8gbm8gbmVlZCB0byBjbGVhbnVwIHJvb3RzIGlmIHdlIGhhdmUgYWxyZWFkeSBiZWVuIGRlc3Ryb3llZAogICAgICBpZiAodGhpcy5fZGVzdHJveWVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgcm9vdHMgPSB0aGlzLl9yb290czsgLy8gdHJhdmVyc2UgaW4gcmV2ZXJzZSBzbyB3ZSBjYW4gcmVtb3ZlIGl0ZW1zCiAgICAgIC8vIHdpdGhvdXQgbXVja2luZyB1cCB0aGUgaW5kZXgKCiAgICAgIHZhciBpID0gdGhpcy5fcm9vdHMubGVuZ3RoOwoKICAgICAgd2hpbGUgKGktLSkgewogICAgICAgIHZhciByb290ID0gcm9vdHNbaV07CgogICAgICAgIGlmIChyb290LmlzRm9yKHZpZXcpKSB7CiAgICAgICAgICByb290LmRlc3Ryb3koKTsKICAgICAgICAgIHJvb3RzLnNwbGljZShpLCAxKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNDMuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIGlmICh0aGlzLl9kZXN0cm95ZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuX2Rlc3Ryb3llZCA9IHRydWU7CgogICAgICB0aGlzLl9jbGVhckFsbFJvb3RzKCk7CiAgICB9OwoKICAgIF9wcm90bzQzLmdldEJvdW5kcyA9IGZ1bmN0aW9uIGdldEJvdW5kcyh2aWV3KSB7CiAgICAgIHZhciBib3VuZHMgPSB2aWV3W0JPVU5EU107CiAgICAgIHZhciBwYXJlbnRFbGVtZW50ID0gYm91bmRzLnBhcmVudEVsZW1lbnQoKTsKICAgICAgdmFyIGZpcnN0Tm9kZSA9IGJvdW5kcy5maXJzdE5vZGUoKTsKICAgICAgdmFyIGxhc3ROb2RlID0gYm91bmRzLmxhc3ROb2RlKCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgcGFyZW50RWxlbWVudDogcGFyZW50RWxlbWVudCwKICAgICAgICBmaXJzdE5vZGU6IGZpcnN0Tm9kZSwKICAgICAgICBsYXN0Tm9kZTogbGFzdE5vZGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvNDMuY3JlYXRlRWxlbWVudCA9IGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodGFnTmFtZSkgewogICAgICByZXR1cm4gdGhpcy5fZW52LmdldEFwcGVuZE9wZXJhdGlvbnMoKS5jcmVhdGVFbGVtZW50KHRhZ05hbWUpOwogICAgfTsKCiAgICBfcHJvdG80My5fcmVuZGVyUm9vdCA9IGZ1bmN0aW9uIF9yZW5kZXJSb290KHJvb3QpIHsKICAgICAgdmFyIHJvb3RzID0gdGhpcy5fcm9vdHM7CiAgICAgIHJvb3RzLnB1c2gocm9vdCk7CgogICAgICBpZiAocm9vdHMubGVuZ3RoID09PSAxKSB7CiAgICAgICAgcmVnaXN0ZXIodGhpcyk7CiAgICAgIH0KCiAgICAgIHRoaXMuX3JlbmRlclJvb3RzVHJhbnNhY3Rpb24oKTsKICAgIH07CgogICAgX3Byb3RvNDMuX3JlbmRlclJvb3RzID0gZnVuY3Rpb24gX3JlbmRlclJvb3RzKCkgewogICAgICB2YXIgcm9vdHMgPSB0aGlzLl9yb290cywKICAgICAgICAgIGVudiA9IHRoaXMuX2VudiwKICAgICAgICAgIHJlbW92ZWRSb290cyA9IHRoaXMuX3JlbW92ZWRSb290czsKICAgICAgdmFyIGdsb2JhbFNob3VsZFJlZmx1c2ggPSBmYWxzZTsKICAgICAgdmFyIGluaXRpYWxSb290c0xlbmd0aDsKCiAgICAgIGRvIHsKICAgICAgICBlbnYuYmVnaW4oKTsKCiAgICAgICAgdHJ5IHsKICAgICAgICAgIC8vIGVuc3VyZSB0aGF0IGZvciB0aGUgZmlyc3QgaXRlcmF0aW9uIG9mIHRoZSBsb29wCiAgICAgICAgICAvLyBlYWNoIHJvb3QgaXMgcHJvY2Vzc2VkCiAgICAgICAgICBpbml0aWFsUm9vdHNMZW5ndGggPSByb290cy5sZW5ndGg7CiAgICAgICAgICBnbG9iYWxTaG91bGRSZWZsdXNoID0gZmFsc2U7CgogICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb290cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICB2YXIgcm9vdCA9IHJvb3RzW2ldOwoKICAgICAgICAgICAgaWYgKHJvb3QuZGVzdHJveWVkKSB7CiAgICAgICAgICAgICAgLy8gYWRkIHRvIHRoZSBsaXN0IG9mIHJvb3RzIHRvIGJlIHJlbW92ZWQKICAgICAgICAgICAgICAvLyB0aGV5IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIGB0aGlzLl9yb290c2AgbGF0ZXIKICAgICAgICAgICAgICByZW1vdmVkUm9vdHMucHVzaChyb290KTsgLy8gc2tpcCBvdmVyIHJvb3RzIHRoYXQgaGF2ZSBiZWVuIG1hcmtlZCBhcyBkZXN0cm95ZWQKCiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHZhciBzaG91bGRSZWZsdXNoID0gcm9vdC5zaG91bGRSZWZsdXNoOyAvLyB3aGVuIHByb2Nlc3Npbmcgbm9uLWluaXRpYWwgcmVmbHVzaCBsb29wcywKICAgICAgICAgICAgLy8gZG8gbm90IHByb2Nlc3MgbW9yZSByb290cyB0aGFuIG5lZWRlZAoKICAgICAgICAgICAgaWYgKGkgPj0gaW5pdGlhbFJvb3RzTGVuZ3RoICYmICFzaG91bGRSZWZsdXNoKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHJvb3Qub3B0aW9ucy5hbHdheXNSZXZhbGlkYXRlID0gc2hvdWxkUmVmbHVzaDsgLy8gdHJhY2sgc2hvdWxkUmVmbHVzaCBiYXNlZCBvbiB0aGlzIHJvb3RzIHJlbmRlciByZXN1bHQKCiAgICAgICAgICAgIHNob3VsZFJlZmx1c2ggPSByb290LnNob3VsZFJlZmx1c2ggPSAoMCwgX21ldGFsLnJ1bkluVHJhbnNhY3Rpb24pKHJvb3QsICdyZW5kZXInKTsgLy8gZ2xvYmFsU2hvdWxkUmVmbHVzaCBzaG91bGQgYmUgYHRydWVgIGlmICphbnkqIG9mCiAgICAgICAgICAgIC8vIHRoZSByb290cyBuZWVkIHRvIHJlZmx1c2gKCiAgICAgICAgICAgIGdsb2JhbFNob3VsZFJlZmx1c2ggPSBnbG9iYWxTaG91bGRSZWZsdXNoIHx8IHNob3VsZFJlZmx1c2g7CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5fbGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKF9yZWZlcmVuY2UuQ1VSUkVOVF9UQUcpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICBlbnYuY29tbWl0KCk7CiAgICAgICAgfQogICAgICB9IHdoaWxlIChnbG9iYWxTaG91bGRSZWZsdXNoIHx8IHJvb3RzLmxlbmd0aCA+IGluaXRpYWxSb290c0xlbmd0aCk7IC8vIHJlbW92ZSBhbnkgcm9vdHMgdGhhdCB3ZXJlIGRlc3Ryb3llZCBkdXJpbmcgdGhpcyB0cmFuc2FjdGlvbgoKCiAgICAgIHdoaWxlIChyZW1vdmVkUm9vdHMubGVuZ3RoKSB7CiAgICAgICAgdmFyIF9yb290ID0gcmVtb3ZlZFJvb3RzLnBvcCgpOwoKICAgICAgICB2YXIgcm9vdEluZGV4ID0gcm9vdHMuaW5kZXhPZihfcm9vdCk7CiAgICAgICAgcm9vdHMuc3BsaWNlKHJvb3RJbmRleCwgMSk7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLl9yb290cy5sZW5ndGggPT09IDApIHsKICAgICAgICBkZXJlZ2lzdGVyKHRoaXMpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQzLl9yZW5kZXJSb290c1RyYW5zYWN0aW9uID0gZnVuY3Rpb24gX3JlbmRlclJvb3RzVHJhbnNhY3Rpb24oKSB7CiAgICAgIGlmICh0aGlzLl9pc1JlbmRlcmluZ1Jvb3RzKSB7CiAgICAgICAgLy8gY3VycmVudGx5IHJlbmRlcmluZyByb290cywgYSBuZXcgcm9vdCB3YXMgYWRkZWQgYW5kIHdpbGwKICAgICAgICAvLyBiZSBwcm9jZXNzZWQgYnkgdGhlIGV4aXN0aW5nIF9yZW5kZXJSb290cyBpbnZvY2F0aW9uCiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIHVzZWQgdG8gcHJldmVudCBjYWxsaW5nIF9yZW5kZXJSb290cyBhZ2FpbiAoc2VlIGFib3ZlKQogICAgICAvLyB3aGlsZSB3ZSBhcmUgYWN0aXZlbHkgcmVuZGVyaW5nIHJvb3RzCgoKICAgICAgdGhpcy5faXNSZW5kZXJpbmdSb290cyA9IHRydWU7CiAgICAgIHZhciBjb21wbGV0ZWRXaXRob3V0RXJyb3IgPSBmYWxzZTsKCiAgICAgIHRyeSB7CiAgICAgICAgdGhpcy5fcmVuZGVyUm9vdHMoKTsKCiAgICAgICAgY29tcGxldGVkV2l0aG91dEVycm9yID0gdHJ1ZTsKICAgICAgfSBmaW5hbGx5IHsKICAgICAgICBpZiAoIWNvbXBsZXRlZFdpdGhvdXRFcnJvcikgewogICAgICAgICAgdGhpcy5fbGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKF9yZWZlcmVuY2UuQ1VSUkVOVF9UQUcpOwoKICAgICAgICAgIGlmICh0aGlzLl9lbnYuaW5UcmFuc2FjdGlvbiA9PT0gdHJ1ZSkgewogICAgICAgICAgICB0aGlzLl9lbnYuY29tbWl0KCk7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB0aGlzLl9pc1JlbmRlcmluZ1Jvb3RzID0gZmFsc2U7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNDMuX2NsZWFyQWxsUm9vdHMgPSBmdW5jdGlvbiBfY2xlYXJBbGxSb290cygpIHsKICAgICAgdmFyIHJvb3RzID0gdGhpcy5fcm9vdHM7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvb3RzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIHJvb3QgPSByb290c1tpXTsKICAgICAgICByb290LmRlc3Ryb3koKTsKICAgICAgfQoKICAgICAgdGhpcy5fcmVtb3ZlZFJvb3RzLmxlbmd0aCA9IDA7CiAgICAgIHRoaXMuX3Jvb3RzID0gW107IC8vIGlmIHJvb3RzIHdlcmUgcHJlc2VudCBiZWZvcmUgZGVzdHJveWluZwogICAgICAvLyBkZXJlZ2lzdGVyIHRoaXMgcmVuZGVyZXIgaW5zdGFuY2UKCiAgICAgIGlmIChyb290cy5sZW5ndGgpIHsKICAgICAgICBkZXJlZ2lzdGVyKHRoaXMpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQzLl9zY2hlZHVsZVJldmFsaWRhdGUgPSBmdW5jdGlvbiBfc2NoZWR1bGVSZXZhbGlkYXRlKCkgewogICAgICBfcnVubG9vcC5iYWNrYnVybmVyLnNjaGVkdWxlT25jZSgncmVuZGVyJywgdGhpcywgdGhpcy5fcmV2YWxpZGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzQzLl9pc1ZhbGlkID0gZnVuY3Rpb24gX2lzVmFsaWQoKSB7CiAgICAgIHJldHVybiB0aGlzLl9kZXN0cm95ZWQgfHwgdGhpcy5fcm9vdHMubGVuZ3RoID09PSAwIHx8ICgwLCBfcmVmZXJlbmNlLnZhbGlkYXRlKShfcmVmZXJlbmNlLkNVUlJFTlRfVEFHLCB0aGlzLl9sYXN0UmV2aXNpb24pOwogICAgfTsKCiAgICBfcHJvdG80My5fcmV2YWxpZGF0ZSA9IGZ1bmN0aW9uIF9yZXZhbGlkYXRlKCkgewogICAgICBpZiAodGhpcy5faXNWYWxpZCgpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9yZW5kZXJSb290c1RyYW5zYWN0aW9uKCk7CiAgICB9OwoKICAgIHJldHVybiBSZW5kZXJlcjsKICB9KCk7CgogIF9leHBvcnRzLlJlbmRlcmVyID0gUmVuZGVyZXI7CgogIHZhciBJbmVydFJlbmRlcmVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9SZW5kZXJlcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEluZXJ0UmVuZGVyZXIsIF9SZW5kZXJlcik7CgogICAgZnVuY3Rpb24gSW5lcnRSZW5kZXJlcigpIHsKICAgICAgcmV0dXJuIF9SZW5kZXJlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgSW5lcnRSZW5kZXJlci5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoX3JlZjEwKSB7CiAgICAgIHZhciBlbnYgPSBfcmVmMTAuZW52LAogICAgICAgICAgcm9vdFRlbXBsYXRlID0gX3JlZjEwLnJvb3RUZW1wbGF0ZSwKICAgICAgICAgIF92aWV3UmVnaXN0cnkgPSBfcmVmMTAuX3ZpZXdSZWdpc3RyeSwKICAgICAgICAgIGJ1aWxkZXIgPSBfcmVmMTAuYnVpbGRlcjsKICAgICAgcmV0dXJuIG5ldyB0aGlzKGVudiwgcm9vdFRlbXBsYXRlLCBfdmlld1JlZ2lzdHJ5LCBmYWxzZSwgYnVpbGRlcik7CiAgICB9OwoKICAgIHZhciBfcHJvdG80NCA9IEluZXJ0UmVuZGVyZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzQ0LmdldEVsZW1lbnQgPSBmdW5jdGlvbiBnZXRFbGVtZW50KF92aWV3KSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignQWNjZXNzaW5nIGB0aGlzLmVsZW1lbnRgIGlzIG5vdCBhbGxvd2VkIGluIG5vbi1pbnRlcmFjdGl2ZSBlbnZpcm9ubWVudHMgKHN1Y2ggYXMgRmFzdEJvb3QpLicpOwogICAgfTsKCiAgICByZXR1cm4gSW5lcnRSZW5kZXJlcjsKICB9KFJlbmRlcmVyKTsKCiAgX2V4cG9ydHMuSW5lcnRSZW5kZXJlciA9IEluZXJ0UmVuZGVyZXI7CgogIHZhciBJbnRlcmFjdGl2ZVJlbmRlcmVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9SZW5kZXJlcjIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShJbnRlcmFjdGl2ZVJlbmRlcmVyLCBfUmVuZGVyZXIyKTsKCiAgICBmdW5jdGlvbiBJbnRlcmFjdGl2ZVJlbmRlcmVyKCkgewogICAgICByZXR1cm4gX1JlbmRlcmVyMi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgSW50ZXJhY3RpdmVSZW5kZXJlci5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoX3JlZjExKSB7CiAgICAgIHZhciBlbnYgPSBfcmVmMTEuZW52LAogICAgICAgICAgcm9vdFRlbXBsYXRlID0gX3JlZjExLnJvb3RUZW1wbGF0ZSwKICAgICAgICAgIF92aWV3UmVnaXN0cnkgPSBfcmVmMTEuX3ZpZXdSZWdpc3RyeSwKICAgICAgICAgIGJ1aWxkZXIgPSBfcmVmMTEuYnVpbGRlcjsKICAgICAgcmV0dXJuIG5ldyB0aGlzKGVudiwgcm9vdFRlbXBsYXRlLCBfdmlld1JlZ2lzdHJ5LCB0cnVlLCBidWlsZGVyKTsKICAgIH07CgogICAgdmFyIF9wcm90bzQ1ID0gSW50ZXJhY3RpdmVSZW5kZXJlci5wcm90b3R5cGU7CgogICAgX3Byb3RvNDUuZ2V0RWxlbWVudCA9IGZ1bmN0aW9uIGdldEVsZW1lbnQodmlldykgewogICAgICByZXR1cm4gKDAsIF92aWV3cy5nZXRWaWV3RWxlbWVudCkodmlldyk7CiAgICB9OwoKICAgIHJldHVybiBJbnRlcmFjdGl2ZVJlbmRlcmVyOwogIH0oUmVuZGVyZXIpOwoKICBfZXhwb3J0cy5JbnRlcmFjdGl2ZVJlbmRlcmVyID0gSW50ZXJhY3RpdmVSZW5kZXJlcjsKICB2YXIgVEVNUExBVEVTID0ge307CgogIGZ1bmN0aW9uIHNldFRlbXBsYXRlcyh0ZW1wbGF0ZXMpIHsKICAgIFRFTVBMQVRFUyA9IHRlbXBsYXRlczsKICB9CgogIGZ1bmN0aW9uIGdldFRlbXBsYXRlcygpIHsKICAgIHJldHVybiBURU1QTEFURVM7CiAgfQoKICBmdW5jdGlvbiBnZXRUZW1wbGF0ZShuYW1lKSB7CiAgICBpZiAoVEVNUExBVEVTLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIHJldHVybiBURU1QTEFURVNbbmFtZV07CiAgICB9CiAgfQoKICBmdW5jdGlvbiBoYXNUZW1wbGF0ZShuYW1lKSB7CiAgICByZXR1cm4gVEVNUExBVEVTLmhhc093blByb3BlcnR5KG5hbWUpOwogIH0KCiAgZnVuY3Rpb24gc2V0VGVtcGxhdGUobmFtZSwgdGVtcGxhdGUpIHsKICAgIHJldHVybiBURU1QTEFURVNbbmFtZV0gPSB0ZW1wbGF0ZTsKICB9CgogIHZhciBJbnRlcm5hbENvbXBvbmVudERlZmluaXRpb24gPSBmdW5jdGlvbiBJbnRlcm5hbENvbXBvbmVudERlZmluaXRpb24obWFuYWdlciwgQ29tcG9uZW50Q2xhc3MsIGxheW91dCkgewogICAgdGhpcy5tYW5hZ2VyID0gbWFuYWdlcjsKICAgIHRoaXMuc3RhdGUgPSB7CiAgICAgIENvbXBvbmVudENsYXNzOiBDb21wb25lbnRDbGFzcywKICAgICAgbGF5b3V0OiBsYXlvdXQKICAgIH07CiAgfTsKCiAgdmFyIEludGVybmFsTWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQWJzdHJhY3RNYW5hZ2VyMykgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEludGVybmFsTWFuYWdlciwgX0Fic3RyYWN0TWFuYWdlcjMpOwoKICAgIGZ1bmN0aW9uIEludGVybmFsTWFuYWdlcihvd25lcikgewogICAgICB2YXIgX3RoaXMyMTsKCiAgICAgIF90aGlzMjEgPSBfQWJzdHJhY3RNYW5hZ2VyMy5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMjEub3duZXIgPSBvd25lcjsKICAgICAgcmV0dXJuIF90aGlzMjE7CiAgICB9CgogICAgdmFyIF9wcm90bzQ2ID0gSW50ZXJuYWxNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG80Ni5nZXRMYXlvdXQgPSBmdW5jdGlvbiBnZXRMYXlvdXQoX3JlZjEyKSB7CiAgICAgIHZhciBfbGF5b3V0ID0gX3JlZjEyLmxheW91dDsKCiAgICAgIHZhciBsYXlvdXQgPSBfbGF5b3V0LmFzTGF5b3V0KCk7CgogICAgICByZXR1cm4gewogICAgICAgIGhhbmRsZTogbGF5b3V0LmNvbXBpbGUoKSwKICAgICAgICBzeW1ib2xUYWJsZTogbGF5b3V0LnN5bWJvbFRhYmxlCiAgICAgIH07CiAgICB9OwoKICAgIHJldHVybiBJbnRlcm5hbE1hbmFnZXI7CiAgfShBYnN0cmFjdE1hbmFnZXIpOwoKICB2YXIgQ0FQQUJJTElUSUVTJDEgPSB7CiAgICBkeW5hbWljTGF5b3V0OiBmYWxzZSwKICAgIGR5bmFtaWNUYWc6IGZhbHNlLAogICAgcHJlcGFyZUFyZ3M6IHRydWUsCiAgICBjcmVhdGVBcmdzOiB0cnVlLAogICAgYXR0cmlidXRlSG9vazogZmFsc2UsCiAgICBlbGVtZW50SG9vazogZmFsc2UsCiAgICBjcmVhdGVDYWxsZXI6IHRydWUsCiAgICBkeW5hbWljU2NvcGU6IGZhbHNlLAogICAgdXBkYXRlSG9vazogdHJ1ZSwKICAgIGNyZWF0ZUluc3RhbmNlOiB0cnVlCiAgfTsKICB2YXIgRU1QVFlfUE9TSVRJT05BTF9BUkdTJDEgPSBbXTsKICAoMCwgX2RlYnVnLmRlYnVnRnJlZXplKShFTVBUWV9QT1NJVElPTkFMX0FSR1MkMSk7CgogIHZhciBJbnB1dENvbXBvbmVudE1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0ludGVybmFsTWFuYWdlcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKElucHV0Q29tcG9uZW50TWFuYWdlciwgX0ludGVybmFsTWFuYWdlcik7CgogICAgZnVuY3Rpb24gSW5wdXRDb21wb25lbnRNYW5hZ2VyKCkgewogICAgICByZXR1cm4gX0ludGVybmFsTWFuYWdlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzQ3ID0gSW5wdXRDb21wb25lbnRNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG80Ny5nZXRDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiBnZXRDYXBhYmlsaXRpZXMoKSB7CiAgICAgIHJldHVybiBDQVBBQklMSVRJRVMkMTsKICAgIH07CgogICAgX3Byb3RvNDcucHJlcGFyZUFyZ3MgPSBmdW5jdGlvbiBwcmVwYXJlQXJncyhfc3RhdGUsIGFyZ3MpIHsKICAgICAgKGZhbHNlICYmICEoYXJncy5wb3NpdGlvbmFsLmxlbmd0aCA9PT0gMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgYDxJbnB1dCAvPmAgY29tcG9uZW50IGRvZXMgbm90IHRha2UgYW55IHBvc2l0aW9uYWwgYXJndW1lbnRzJywgYXJncy5wb3NpdGlvbmFsLmxlbmd0aCA9PT0gMCkpOwogICAgICB2YXIgX19BUkdTX18gPSBhcmdzLm5hbWVkLmNhcHR1cmUoKS5tYXA7CiAgICAgIHJldHVybiB7CiAgICAgICAgcG9zaXRpb25hbDogRU1QVFlfUE9TSVRJT05BTF9BUkdTJDEsCiAgICAgICAgbmFtZWQ6IHsKICAgICAgICAgIF9fQVJHU19fOiBuZXcgUm9vdFJlZmVyZW5jZShfX0FSR1NfXyksCiAgICAgICAgICB0eXBlOiBhcmdzLm5hbWVkLmdldCgndHlwZScpCiAgICAgICAgfQogICAgICB9OwogICAgfTsKCiAgICBfcHJvdG80Ny5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoX2VudiwgX3JlZjEzLCBhcmdzLCBfZHluYW1pY1Njb3BlLCBjYWxsZXIpIHsKICAgICAgdmFyIENvbXBvbmVudENsYXNzID0gX3JlZjEzLkNvbXBvbmVudENsYXNzOwogICAgICAoZmFsc2UgJiYgISgoMCwgX3JlZmVyZW5jZS5pc0NvbnN0KShjYWxsZXIpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2NhbGxlciBtdXN0IGJlIGNvbnN0JywgKDAsIF9yZWZlcmVuY2UuaXNDb25zdCkoY2FsbGVyKSkpOwogICAgICB2YXIgdHlwZSA9IGFyZ3MubmFtZWQuZ2V0KCd0eXBlJyk7CiAgICAgIHZhciBpbnN0YW5jZSA9IENvbXBvbmVudENsYXNzLmNyZWF0ZSh7CiAgICAgICAgY2FsbGVyOiBjYWxsZXIudmFsdWUoKSwKICAgICAgICB0eXBlOiB0eXBlLnZhbHVlKCkKICAgICAgfSk7CiAgICAgIHJldHVybiB7CiAgICAgICAgdHlwZTogdHlwZSwKICAgICAgICBpbnN0YW5jZTogaW5zdGFuY2UKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvNDcuZ2V0U2VsZiA9IGZ1bmN0aW9uIGdldFNlbGYoX3JlZjE0KSB7CiAgICAgIHZhciBpbnN0YW5jZSA9IF9yZWYxNC5pbnN0YW5jZTsKICAgICAgcmV0dXJuIG5ldyBSb290UmVmZXJlbmNlKGluc3RhbmNlKTsKICAgIH07CgogICAgX3Byb3RvNDcuZ2V0VGFnID0gZnVuY3Rpb24gZ2V0VGFnKCkgewogICAgICByZXR1cm4gX3JlZmVyZW5jZS5DT05TVEFOVF9UQUc7CiAgICB9OwoKICAgIF9wcm90bzQ3LnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZShfcmVmMTUpIHsKICAgICAgdmFyIHR5cGUgPSBfcmVmMTUudHlwZSwKICAgICAgICAgIGluc3RhbmNlID0gX3JlZjE1Lmluc3RhbmNlOwogICAgICAoMCwgX21ldGFsLnNldCkoaW5zdGFuY2UsICd0eXBlJywgdHlwZS52YWx1ZSgpKTsKICAgIH07CgogICAgX3Byb3RvNDcuZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3IoX3JlZjE2KSB7CiAgICAgIHZhciBpbnN0YW5jZSA9IF9yZWYxNi5pbnN0YW5jZTsKICAgICAgcmV0dXJuIGluc3RhbmNlOwogICAgfTsKCiAgICByZXR1cm4gSW5wdXRDb21wb25lbnRNYW5hZ2VyOwogIH0oSW50ZXJuYWxNYW5hZ2VyKTsKCiAgdmFyIElucHV0Q29tcG9uZW50TWFuYWdlckZhY3RvcnkgPSBmdW5jdGlvbiBJbnB1dENvbXBvbmVudE1hbmFnZXJGYWN0b3J5KG93bmVyKSB7CiAgICByZXR1cm4gbmV3IElucHV0Q29tcG9uZW50TWFuYWdlcihvd25lcik7CiAgfTsKCiAgdmFyIE1BTkFHRVJTID0gbmV3IFdlYWtNYXAoKTsKICB2YXIgZ2V0UHJvdG90eXBlT2YgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Y7CgogIGZ1bmN0aW9uIHNldE1hbmFnZXIod3JhcHBlciwgb2JqKSB7CiAgICBNQU5BR0VSUy5zZXQob2JqLCB3cmFwcGVyKTsKICAgIHJldHVybiBvYmo7CiAgfQoKICBmdW5jdGlvbiBnZXRNYW5hZ2VyKG9iaikgewogICAgdmFyIHBvaW50ZXIgPSBvYmo7CgogICAgd2hpbGUgKHBvaW50ZXIgIT09IHVuZGVmaW5lZCAmJiBwb2ludGVyICE9PSBudWxsKSB7CiAgICAgIHZhciBtYW5hZ2VyID0gTUFOQUdFUlMuZ2V0KHBvaW50ZXIpOwoKICAgICAgaWYgKG1hbmFnZXIgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBtYW5hZ2VyOwogICAgICB9CgogICAgICBwb2ludGVyID0gZ2V0UHJvdG90eXBlT2YocG9pbnRlcik7CiAgICB9CgogICAgcmV0dXJuIG51bGw7CiAgfQogIC8qKgogIEBtb2R1bGUgQGVtYmVyL2NvbXBvbmVudAogICovCgoKICB2YXIgSW5wdXQ7CiAgewogICAgLyoqCiAgICAgIFNlZSBbRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMuSW5wdXRdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMvbWV0aG9kcy9JbnB1dD9hbmNob3I9SW5wdXQpLgogICAgICAgICBAbWV0aG9kIGlucHV0CiAgICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgICAgQHBhcmFtIHtIYXNofSBvcHRpb25zCiAgICAgIEBwdWJsaWMKICAgICAqLwoKICAgIC8qKgogICAgICBUaGUgYElucHV0YCBjb21wb25lbnQgbGV0cyB5b3UgY3JlYXRlIGFuIEhUTUwgYDxpbnB1dD5gIGVsZW1lbnQuCiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPElucHV0IEB2YWx1ZT0iOTg3IiAvPgogICAgICBgYGAKICAgICAgICAgY3JlYXRlcyBhbiBgPGlucHV0PmAgZWxlbWVudCB3aXRoIGB0eXBlPSJ0ZXh0ImAgYW5kIHZhbHVlIHNldCB0byA5ODcuCiAgICAgICAgICMjIyBUZXh0IGZpZWxkCiAgICAgICAgIElmIG5vIGB0eXBlYCBhcmd1bWVudCBpcyBzcGVjaWZpZWQsIGEgZGVmYXVsdCBvZiB0eXBlICd0ZXh0JyBpcyB1c2VkLgogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIFNlYXJjaDoKICAgICAgPElucHV0IEB2YWx1ZT17e3RoaXMuc2VhcmNoV29yZH19PgogICAgICBgYGAKICAgICAgICAgSW4gdGhpcyBleGFtcGxlLCB0aGUgaW5pdGlhbCB2YWx1ZSBpbiB0aGUgYDxpbnB1dD5gIHdpbGwgYmUgc2V0IHRvIHRoZSB2YWx1ZSBvZgogICAgICBgdGhpcy5zZWFyY2hXb3JkYC4gSWYgdGhlIHVzZXIgY2hhbmdlcyB0aGUgdGV4dCwgdGhlIHZhbHVlIG9mIGB0aGlzLnNlYXJjaFdvcmRgIHdpbGwgYWxzbyBiZQogICAgICB1cGRhdGVkLgogICAgICAgICAjIyMgQWN0aW9ucwogICAgICAgICBUaGUgYElucHV0YCBjb21wb25lbnQgdGFrZXMgYSBudW1iZXIgb2YgYXJndW1lbnRzIHdpdGggY2FsbGJhY2tzIHRoYXQgYXJlIGludm9rZWQgaW4gcmVzcG9uc2UgdG8KICAgICAgdXNlciBldmVudHMuCiAgICAgICAgICogYGVudGVyYAogICAgICAqIGBpbnNlcnQtbmV3bGluZWAKICAgICAgKiBgZXNjYXBlLXByZXNzYAogICAgICAqIGBmb2N1cy1pbmAKICAgICAgKiBgZm9jdXMtb3V0YAogICAgICAqIGBrZXktcHJlc3NgCiAgICAgICogYGtleS11cGAKICAgICAgICAgVGhlc2UgY2FsbGJhY2tzIGFyZSBwYXNzZWQgdG8gYElucHV0YCBsaWtlIHRoaXM6CiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgPElucHV0IEB2YWx1ZT17e3RoaXMuc2VhcmNoV29yZH19IEBlbnRlcj17e3RoaXMucXVlcnl9fSAvPgogICAgICBgYGAKICAgICAgICAgIyMjIGA8aW5wdXQ+YCBIVE1MIEF0dHJpYnV0ZXMgdG8gQXZvaWQKICAgICAgICAgSW4gbW9zdCBjYXNlcywgaWYgeW91IHdhbnQgdG8gcGFzcyBhbiBhdHRyaWJ1dGUgdG8gdGhlIHVuZGVybHlpbmcgSFRNTCBgPGlucHV0PmAgZWxlbWVudCwgeW91CiAgICAgIGNhbiBwYXNzIHRoZSBhdHRyaWJ1dGUgZGlyZWN0bHksIGp1c3QgbGlrZSBhbnkgb3RoZXIgRW1iZXIgY29tcG9uZW50LgogICAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIDxJbnB1dCBAdHlwZT0idGV4dCIgc2l6ZT0iMTAiIC8+CiAgICAgIGBgYAogICAgICAgICBJbiB0aGlzIGV4YW1wbGUsIHRoZSBgc2l6ZWAgYXR0cmlidXRlIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgdW5kZXJseWluZyBgPGlucHV0PmAgZWxlbWVudCBpbiB0aGUKICAgICAgb3V0cHV0dGVkIEhUTUwuCiAgICAgICAgIEhvd2V2ZXIsIHRoZXJlIGFyZSBhIGZldyBhdHRyaWJ1dGVzIHdoZXJlIHlvdSAqKm11c3QqKiB1c2UgdGhlIGBAYCB2ZXJzaW9uLgogICAgICAgICAqIGBAdHlwZWA6IFRoaXMgYXJndW1lbnQgaXMgdXNlZCB0byBjb250cm9sIHdoaWNoIEVtYmVyIGNvbXBvbmVudCBpcyB1c2VkIHVuZGVyIHRoZSBob29kCiAgICAgICogYEB2YWx1ZWA6IFRoZSBgQHZhbHVlYCBhcmd1bWVudCBpbnN0YWxscyBhIHR3by13YXkgYmluZGluZyBvbnRvIHRoZSBlbGVtZW50LiBJZiB5b3Ugd2FudGVkIGEKICAgICAgICBvbmUtd2F5IGJpbmRpbmcsIHVzZSBgPGlucHV0PmAgd2l0aCB0aGUgYHZhbHVlYCBwcm9wZXJ0eSBhbmQgdGhlIGBpbnB1dGAgZXZlbnQgaW5zdGVhZC4KICAgICAgKiBgQGNoZWNrZWRgIChmb3IgY2hlY2tib3hlcyk6IGxpa2UgYEB2YWx1ZWAsIHRoZSBgQGNoZWNrZWRgIGFyZ3VtZW50IGluc3RhbGxzIGEgdHdvLXdheSBiaW5kaW5nCiAgICAgICAgb250byB0aGUgZWxlbWVudC4gSWYgeW91IHdhbnRlZCBhIG9uZS13YXkgYmluZGluZywgdXNlIGA8aW5wdXQgdHlwZT0iY2hlY2tib3giPmAgd2l0aAogICAgICAgIGBjaGVja2VkYCBhbmQgdGhlIGBpbnB1dGAgZXZlbnQgaW5zdGVhZC4KICAgICAgICAgIyMjIEV4dGVuZGluZyBgVGV4dEZpZWxkYAogICAgICAgICBJbnRlcm5hbGx5LCBgPElucHV0IEB0eXBlPSJ0ZXh0IiAvPmAgY3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBgVGV4dEZpZWxkYCwgcGFzc2luZyBhcmd1bWVudHMgZnJvbQogICAgICB0aGUgaGVscGVyIHRvIGBUZXh0RmllbGRgJ3MgYGNyZWF0ZWAgbWV0aG9kLiBTdWJjbGFzc2luZyBgVGV4dEZpZWxkYCBpcyBzdXBwb3J0ZWQgYnV0IG5vdAogICAgICByZWNvbW1lbmRlZC4KICAgICAgICAgU2VlIFtUZXh0RmllbGRdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvVGV4dEZpZWxkKQogICAgICAgICAjIyMgQ2hlY2tib3gKICAgICAgICAgVG8gY3JlYXRlIGFuIGA8aW5wdXQgdHlwZT0iY2hlY2tib3giPmA6CiAgICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAgRW1iZXJpemUgRXZlcnl0aGluZzoKICAgICAgPElucHV0IEB0eXBlPSJjaGVja2JveCIgQGNoZWNrZWQ9e3t0aGlzLmlzRW1iZXJpemVkfX0gbmFtZT0iaXNFbWJlcml6ZWQiIC8+CiAgICAgIGBgYAogICAgICAgICBUaGlzIHdpbGwgYmluZCB0aGUgY2hlY2tlZCBzdGF0ZSBvZiB0aGlzIGNoZWNrYm94IHRvIHRoZSB2YWx1ZSBvZiBgaXNFbWJlcml6ZWRgIC0tIGlmIGVpdGhlciBvbmUKICAgICAgY2hhbmdlcywgaXQgd2lsbCBiZSByZWZsZWN0ZWQgaW4gdGhlIG90aGVyLgogICAgICAgICAjIyMgRXh0ZW5kaW5nIGBDaGVja2JveGAKICAgICAgICAgSW50ZXJuYWxseSwgYDxJbnB1dCBAdHlwZT0iY2hlY2tib3giIC8+YCBjcmVhdGVzIGFuIGluc3RhbmNlIG9mIGBDaGVja2JveGAuIFN1YmNsYXNzaW5nCiAgICAgIGBUZXh0RmllbGRgIGlzIHN1cHBvcnRlZCBidXQgbm90IHJlY29tbWVuZGVkLgogICAgICAgICBTZWUgW0NoZWNrYm94XSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0NoZWNrYm94KQogICAgICAgICBAbWV0aG9kIElucHV0CiAgICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmNvbXBvbmVudHMKICAgICAgQHNlZSB7VGV4dEZpZWxkfQogICAgICBAc2VlIHtDaGVja2JveH0KICAgICAgQHBhcmFtIHtIYXNofSBvcHRpb25zCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBJbnB1dCA9IF9ydW50aW1lLk9iamVjdC5leHRlbmQoewogICAgICBpc0NoZWNrYm94OiAoMCwgX21ldGFsLmNvbXB1dGVkKSgndHlwZScsIGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gdGhpcy50eXBlID09PSAnY2hlY2tib3gnOwogICAgICB9KQogICAgfSk7CiAgICBzZXRNYW5hZ2VyKHsKICAgICAgZmFjdG9yeTogSW5wdXRDb21wb25lbnRNYW5hZ2VyRmFjdG9yeSwKICAgICAgaW50ZXJuYWw6IHRydWUsCiAgICAgIHR5cGU6ICdjb21wb25lbnQnCiAgICB9LCBJbnB1dCk7CgogICAgSW5wdXQudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAnQGVtYmVyL2NvbXBvbmVudC9pbnB1dCc7CiAgICB9OwogIH0KICB2YXIgSW5wdXQkMSA9IElucHV0OyAvLy88cmVmZXJlbmNlIHBhdGg9Ii4vc2ltcGxlLWRvbS5kLnRzIiAvPgoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBDYWxscyBbU3RyaW5nLmxvY10oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9TdHJpbmcvbWV0aG9kcy9sb2M/YW5jaG9yPWxvYykgd2l0aCB0aGUKICAgIHByb3ZpZGVkIHN0cmluZy4gVGhpcyBpcyBhIGNvbnZlbmllbnQgd2F5IHRvIGxvY2FsaXplIHRleHQgd2l0aGluIGEgdGVtcGxhdGUuCiAgICBGb3IgZXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIEVtYmVyLlNUUklOR1MgPSB7CiAgICAgICdfd2VsY29tZV8nOiAnQm9uam91cicKICAgIH07CiAgICBgYGAKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxkaXYgY2xhc3M9J21lc3NhZ2UnPgogICAgICB7e2xvYyAnX3dlbGNvbWVfJ319CiAgICA8L2Rpdj4KICAgIGBgYAogIAogICAgYGBgaHRtbAogICAgPGRpdiBjbGFzcz0nbWVzc2FnZSc+CiAgICAgIEJvbmpvdXIKICAgIDwvZGl2PgogICAgYGBgCiAgCiAgICBTZWUgW1N0cmluZy5sb2NdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvU3RyaW5nL21ldGhvZHMvbG9jP2FuY2hvcj1sb2MpIGZvciBob3cgdG8KICAgIHNldCB1cCBsb2NhbGl6ZWQgc3RyaW5nIHJlZmVyZW5jZXMuCiAgCiAgICBAbWV0aG9kIGxvYwogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHBhcmFtIHtTdHJpbmd9IHN0ciBUaGUgc3RyaW5nIHRvIGZvcm1hdC4KICAgIEBzZWUge1N0cmluZyNsb2N9CiAgICBAcHVibGljCiAgKi8KCiAgdmFyIGxvYyQxID0gaGVscGVyKGZ1bmN0aW9uIChwYXJhbXMpIHsKICAgIHJldHVybiBfc3RyaW5nLmxvYy5hcHBseShudWxsLCBwYXJhbXMKICAgIC8qIGxldCB0aGUgb3RoZXIgc2lkZSBoYW5kbGUgZXJyb3JzICovCiAgICApOwogIH0pOwoKICB2YXIgQ29tcGlsZVRpbWVMb29rdXAgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDb21waWxlVGltZUxvb2t1cChyZXNvbHZlcikgewogICAgICB0aGlzLnJlc29sdmVyID0gcmVzb2x2ZXI7CiAgICB9CgogICAgdmFyIF9wcm90bzQ4ID0gQ29tcGlsZVRpbWVMb29rdXAucHJvdG90eXBlOwoKICAgIF9wcm90bzQ4LmdldENhcGFiaWxpdGllcyA9IGZ1bmN0aW9uIGdldENhcGFiaWxpdGllcyhoYW5kbGUpIHsKICAgICAgdmFyIGRlZmluaXRpb24gPSB0aGlzLnJlc29sdmVyLnJlc29sdmUoaGFuZGxlKTsKICAgICAgdmFyIG1hbmFnZXIgPSBkZWZpbml0aW9uLm1hbmFnZXIsCiAgICAgICAgICBzdGF0ZSA9IGRlZmluaXRpb24uc3RhdGU7CiAgICAgIHJldHVybiBtYW5hZ2VyLmdldENhcGFiaWxpdGllcyhzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzQ4LmdldExheW91dCA9IGZ1bmN0aW9uIGdldExheW91dChoYW5kbGUpIHsKICAgICAgdmFyIF90aGlzJHJlc29sdmVyJHJlc29sdiA9IHRoaXMucmVzb2x2ZXIucmVzb2x2ZShoYW5kbGUpLAogICAgICAgICAgbWFuYWdlciA9IF90aGlzJHJlc29sdmVyJHJlc29sdi5tYW5hZ2VyLAogICAgICAgICAgc3RhdGUgPSBfdGhpcyRyZXNvbHZlciRyZXNvbHYuc3RhdGU7CgogICAgICB2YXIgY2FwYWJpbGl0aWVzID0gbWFuYWdlci5nZXRDYXBhYmlsaXRpZXMoc3RhdGUpOwoKICAgICAgaWYgKGNhcGFiaWxpdGllcy5keW5hbWljTGF5b3V0KSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KCiAgICAgIHZhciBpbnZvY2F0aW9uID0gbWFuYWdlci5nZXRMYXlvdXQoc3RhdGUsIHRoaXMucmVzb2x2ZXIpOwogICAgICByZXR1cm4gewogICAgICAgIC8vIFRPRE86IHRoaXMgc2VlbXMgd2VpcmQsIGl0IGFscmVhZHkgaXMgY29tcGlsZWQKICAgICAgICBjb21waWxlOiBmdW5jdGlvbiBjb21waWxlKCkgewogICAgICAgICAgcmV0dXJuIGludm9jYXRpb24uaGFuZGxlOwogICAgICAgIH0sCiAgICAgICAgc3ltYm9sVGFibGU6IGludm9jYXRpb24uc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvNDgubG9va3VwSGVscGVyID0gZnVuY3Rpb24gbG9va3VwSGVscGVyKG5hbWUsIHJlZmVycmVyKSB7CiAgICAgIHJldHVybiB0aGlzLnJlc29sdmVyLmxvb2t1cEhlbHBlcihuYW1lLCByZWZlcnJlcik7CiAgICB9OwoKICAgIF9wcm90bzQ4Lmxvb2t1cE1vZGlmaWVyID0gZnVuY3Rpb24gbG9va3VwTW9kaWZpZXIobmFtZSwgcmVmZXJyZXIpIHsKICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZXIubG9va3VwTW9kaWZpZXIobmFtZSwgcmVmZXJyZXIpOwogICAgfTsKCiAgICBfcHJvdG80OC5sb29rdXBDb21wb25lbnREZWZpbml0aW9uID0gZnVuY3Rpb24gbG9va3VwQ29tcG9uZW50RGVmaW5pdGlvbihuYW1lLCByZWZlcnJlcikgewogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlci5sb29rdXBDb21wb25lbnRIYW5kbGUobmFtZSwgcmVmZXJyZXIpOwogICAgfTsKCiAgICBfcHJvdG80OC5sb29rdXBQYXJ0aWFsID0gZnVuY3Rpb24gbG9va3VwUGFydGlhbChuYW1lLCByZWZlcnJlcikgewogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlci5sb29rdXBQYXJ0aWFsKG5hbWUsIHJlZmVycmVyKTsKICAgIH07CgogICAgcmV0dXJuIENvbXBpbGVUaW1lTG9va3VwOwogIH0oKTsKCiAgdmFyIENBUEFCSUxJVElFUyQyID0gewogICAgZHluYW1pY0xheW91dDogZmFsc2UsCiAgICBkeW5hbWljVGFnOiBmYWxzZSwKICAgIHByZXBhcmVBcmdzOiBmYWxzZSwKICAgIGNyZWF0ZUFyZ3M6IHRydWUsCiAgICBhdHRyaWJ1dGVIb29rOiBmYWxzZSwKICAgIGVsZW1lbnRIb29rOiBmYWxzZSwKICAgIGNyZWF0ZUNhbGxlcjogZmFsc2UsCiAgICBkeW5hbWljU2NvcGU6IHRydWUsCiAgICB1cGRhdGVIb29rOiB0cnVlLAogICAgY3JlYXRlSW5zdGFuY2U6IHRydWUKICB9OwoKICBmdW5jdGlvbiBjYXBhYmlsaXRpZXMobWFuYWdlckFQSSwgb3B0aW9ucykgewogICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICBvcHRpb25zID0ge307CiAgICB9CgogICAgKGZhbHNlICYmICEobWFuYWdlckFQSSA9PT0gJzMuNCcgfHwgbWFuYWdlckFQSSA9PT0gJzMuMTMnKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0ludmFsaWQgY29tcG9uZW50IG1hbmFnZXIgY29tcGF0aWJpbGl0eSBzcGVjaWZpZWQnLCBtYW5hZ2VyQVBJID09PSAnMy40JyB8fCBtYW5hZ2VyQVBJID09PSAnMy4xMycpKTsKICAgIHZhciB1cGRhdGVIb29rID0gdHJ1ZTsKICAgIHsKICAgICAgdXBkYXRlSG9vayA9IG1hbmFnZXJBUEkgPT09ICczLjEzJyA/IEJvb2xlYW4ob3B0aW9ucy51cGRhdGVIb29rKSA6IHRydWU7CiAgICB9CiAgICByZXR1cm4gewogICAgICBhc3luY0xpZmVDeWNsZUNhbGxiYWNrczogQm9vbGVhbihvcHRpb25zLmFzeW5jTGlmZWN5Y2xlQ2FsbGJhY2tzKSwKICAgICAgZGVzdHJ1Y3RvcjogQm9vbGVhbihvcHRpb25zLmRlc3RydWN0b3IpLAogICAgICB1cGRhdGVIb29rOiB1cGRhdGVIb29rCiAgICB9OwogIH0KCiAgZnVuY3Rpb24gaGFzQXN5bmNMaWZlQ3ljbGVDYWxsYmFja3MoZGVsZWdhdGUpIHsKICAgIHJldHVybiBkZWxlZ2F0ZS5jYXBhYmlsaXRpZXMuYXN5bmNMaWZlQ3ljbGVDYWxsYmFja3M7CiAgfQoKICBmdW5jdGlvbiBoYXNVcGRhdGVIb29rKGRlbGVnYXRlKSB7CiAgICByZXR1cm4gZGVsZWdhdGUuY2FwYWJpbGl0aWVzLnVwZGF0ZUhvb2s7CiAgfQoKICBmdW5jdGlvbiBoYXNBc3luY1VwZGF0ZUhvb2soZGVsZWdhdGUpIHsKICAgIHJldHVybiBoYXNBc3luY0xpZmVDeWNsZUNhbGxiYWNrcyhkZWxlZ2F0ZSkgJiYgaGFzVXBkYXRlSG9vayhkZWxlZ2F0ZSk7CiAgfQoKICBmdW5jdGlvbiBoYXNEZXN0cnVjdG9ycyhkZWxlZ2F0ZSkgewogICAgcmV0dXJuIGRlbGVnYXRlLmNhcGFiaWxpdGllcy5kZXN0cnVjdG9yOwogIH0KICAvKioKICAgIFRoZSBDdXN0b21Db21wb25lbnRNYW5hZ2VyIGFsbG93cyBhZGRvbnMgdG8gcHJvdmlkZSBjdXN0b20gY29tcG9uZW50CiAgICBpbXBsZW1lbnRhdGlvbnMgdGhhdCBpbnRlZ3JhdGUgc2VhbWxlc3NseSBpbnRvIEVtYmVyLiBUaGlzIGlzIGFjY29tcGxpc2hlZAogICAgdGhyb3VnaCBhIGRlbGVnYXRlLCByZWdpc3RlcmVkIHdpdGggdGhlIGN1c3RvbSBjb21wb25lbnQgbWFuYWdlciwgd2hpY2gKICAgIGltcGxlbWVudHMgYSBzZXQgb2YgaG9va3MgdGhhdCBkZXRlcm1pbmUgY29tcG9uZW50IGJlaGF2aW9yLgogIAogICAgVG8gY3JlYXRlIGEgY3VzdG9tIGNvbXBvbmVudCBtYW5hZ2VyLCBpbnN0YW50aWF0ZSBhIG5ldyBDdXN0b21Db21wb25lbnRNYW5hZ2VyCiAgICBjbGFzcyBhbmQgcGFzcyB0aGUgZGVsZWdhdGUgYXMgdGhlIGZpcnN0IGFyZ3VtZW50OgogIAogICAgYGBganMKICAgIGxldCBtYW5hZ2VyID0gbmV3IEN1c3RvbUNvbXBvbmVudE1hbmFnZXIoewogICAgICAvLyAuLi5kZWxlZ2F0ZSBpbXBsZW1lbnRhdGlvbi4uLgogICAgfSk7CiAgICBgYGAKICAKICAgICMjIERlbGVnYXRlIEhvb2tzCiAgCiAgICBUaHJvdWdob3V0IHRoZSBsaWZlY3ljbGUgb2YgYSBjb21wb25lbnQsIHRoZSBjb21wb25lbnQgbWFuYWdlciB3aWxsIGludm9rZQogICAgZGVsZWdhdGUgaG9va3MgdGhhdCBhcmUgcmVzcG9uc2libGUgZm9yIHN1cmZhY2luZyB0aG9zZSBsaWZlY3ljbGUgY2hhbmdlcyB0bwogICAgdGhlIGVuZCBkZXZlbG9wZXIuCiAgCiAgICAqIGBjcmVhdGUoKWAgLSBpbnZva2VkIHdoZW4gYSBuZXcgaW5zdGFuY2Ugb2YgYSBjb21wb25lbnQgc2hvdWxkIGJlIGNyZWF0ZWQKICAgICogYHVwZGF0ZSgpYCAtIGludm9rZWQgd2hlbiB0aGUgYXJndW1lbnRzIHBhc3NlZCB0byBhIGNvbXBvbmVudCBjaGFuZ2UKICAgICogYGdldENvbnRleHQoKWAgLSByZXR1cm5zIHRoZSBvYmplY3QgdGhhdCBzaG91bGQgYmUKICAqLwoKCiAgdmFyIEN1c3RvbUNvbXBvbmVudE1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Fic3RyYWN0TWFuYWdlcjQpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDdXN0b21Db21wb25lbnRNYW5hZ2VyLCBfQWJzdHJhY3RNYW5hZ2VyNCk7CgogICAgZnVuY3Rpb24gQ3VzdG9tQ29tcG9uZW50TWFuYWdlcigpIHsKICAgICAgcmV0dXJuIF9BYnN0cmFjdE1hbmFnZXI0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDkgPSBDdXN0b21Db21wb25lbnRNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG80OS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoX2VudiwgZGVmaW5pdGlvbiwgYXJncykgewogICAgICB2YXIgZGVsZWdhdGUgPSBkZWZpbml0aW9uLmRlbGVnYXRlOwogICAgICB2YXIgY2FwdHVyZWRBcmdzID0gYXJncy5jYXB0dXJlKCk7CiAgICAgIHZhciB2YWx1ZSQkMTsKICAgICAgdmFyIG5hbWVkQXJnc1Byb3h5ID0ge307CiAgICAgIHsKICAgICAgICBpZiAoX3V0aWxzLkhBU19OQVRJVkVfUFJPWFkpIHsKICAgICAgICAgIHZhciBoYW5kbGVyID0gewogICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldChfdGFyZ2V0LCBwcm9wKSB7CiAgICAgICAgICAgICAgaWYgKGNhcHR1cmVkQXJncy5uYW1lZC5oYXMocHJvcCkpIHsKICAgICAgICAgICAgICAgIHZhciByZWYgPSBjYXB0dXJlZEFyZ3MubmFtZWQuZ2V0KHByb3ApOwogICAgICAgICAgICAgICAgKDAsIF9tZXRhbC5jb25zdW1lKShyZWYudGFnKTsKICAgICAgICAgICAgICAgIHJldHVybiByZWYudmFsdWUoKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGhhczogZnVuY3Rpb24gaGFzKF90YXJnZXQsIHByb3ApIHsKICAgICAgICAgICAgICByZXR1cm4gY2FwdHVyZWRBcmdzLm5hbWVkLmhhcyhwcm9wKTsKICAgICAgICAgICAgfSwKICAgICAgICAgICAgb3duS2V5czogZnVuY3Rpb24gb3duS2V5cyhfdGFyZ2V0KSB7CiAgICAgICAgICAgICAgcmV0dXJuIGNhcHR1cmVkQXJncy5uYW1lZC5uYW1lczsKICAgICAgICAgICAgfSwKICAgICAgICAgICAgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOiBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoX3RhcmdldCwgcHJvcCkgewogICAgICAgICAgICAgIChmYWxzZSAmJiAhKGNhcHR1cmVkQXJncy5uYW1lZC5oYXMocHJvcCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYXJncyBwcm94aWVzIGRvIG5vdCBoYXZlIHJlYWwgcHJvcGVydHkgZGVzY3JpcHRvcnMsIHNvIHlvdSBzaG91bGQgbmV2ZXIgbmVlZCB0byBjYWxsIGdldE93blByb3BlcnR5RGVzY3JpcHRvciB5b3Vyc2VsZi4gVGhpcyBjb2RlIGV4aXN0cyBmb3IgZW51bWVyYWJpbGl0eSwgc3VjaCBhcyBpbiBmb3ItaW4gbG9vcHMgYW5kIE9iamVjdC5rZXlzKCknLCBjYXB0dXJlZEFyZ3MubmFtZWQuaGFzKHByb3ApKSk7CiAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUKICAgICAgICAgICAgICB9OwogICAgICAgICAgICB9CiAgICAgICAgICB9OwoKICAgICAgICAgIGlmIChmYWxzZQogICAgICAgICAgLyogREVCVUcgKi8KICAgICAgICAgICkgewogICAgICAgICAgICBoYW5kbGVyLnNldCA9IGZ1bmN0aW9uIChfdGFyZ2V0LCBwcm9wKSB7CiAgICAgICAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byBzZXQgIiArIGRlZmluaXRpb24uQ29tcG9uZW50Q2xhc3MuY2xhc3MgKyAiIyIgKyBTdHJpbmcocHJvcCkgKyAiIG9uIGEgY29tcG9uZW50cyBhcmd1bWVudHMuIENvbXBvbmVudCBhcmd1bWVudHMgYXJlIGltbXV0YWJsZSBhbmQgY2Fubm90IGJlIHVwZGF0ZWQgZGlyZWN0bHksIHRoZXkgYWx3YXlzIHJlcHJlc2VudCB0aGUgdmFsdWVzIHRoYXQgYXJlIHBhc3NlZCB0byB5b3VyIGNvbXBvbmVudC4gSWYgeW91IHdhbnQgdG8gc2V0IGRlZmF1bHQgdmFsdWVzLCB5b3Ugc2hvdWxkIHVzZSBhIGdldHRlciBpbnN0ZWFkIikpOwogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfTsKICAgICAgICAgIH0KCiAgICAgICAgICBuYW1lZEFyZ3NQcm94eSA9IG5ldyBQcm94eShuYW1lZEFyZ3NQcm94eSwgaGFuZGxlcik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNhcHR1cmVkQXJncy5uYW1lZC5uYW1lcy5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7CiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShuYW1lZEFyZ3NQcm94eSwgbmFtZSwgewogICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgICAgICAgICAgdmFyIHJlZiA9IGNhcHR1cmVkQXJncy5uYW1lZC5nZXQobmFtZSk7CiAgICAgICAgICAgICAgICAoMCwgX21ldGFsLmNvbnN1bWUpKHJlZi50YWcpOwogICAgICAgICAgICAgICAgcmV0dXJuIHJlZi52YWx1ZSgpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIF9tZXRhbC5BUkdTX1BST1hZX1RBR1Muc2V0KG5hbWVkQXJnc1Byb3h5LCBjYXB0dXJlZEFyZ3MubmFtZWQpOwoKICAgICAgICB2YWx1ZSQkMSA9IHsKICAgICAgICAgIG5hbWVkOiBuYW1lZEFyZ3NQcm94eSwKICAgICAgICAgIHBvc2l0aW9uYWw6IGNhcHR1cmVkQXJncy5wb3NpdGlvbmFsLnZhbHVlKCkKICAgICAgICB9OwogICAgICB9CiAgICAgIHZhciBjb21wb25lbnQgPSBkZWxlZ2F0ZS5jcmVhdGVDb21wb25lbnQoZGVmaW5pdGlvbi5Db21wb25lbnRDbGFzcy5jbGFzcywgdmFsdWUkJDEpOwogICAgICByZXR1cm4gbmV3IEN1c3RvbUNvbXBvbmVudFN0YXRlKGRlbGVnYXRlLCBjb21wb25lbnQsIGNhcHR1cmVkQXJncywgbmFtZWRBcmdzUHJveHkpOwogICAgfTsKCiAgICBfcHJvdG80OS51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoX3JlZjE3KSB7CiAgICAgIHZhciBkZWxlZ2F0ZSA9IF9yZWYxNy5kZWxlZ2F0ZSwKICAgICAgICAgIGNvbXBvbmVudCA9IF9yZWYxNy5jb21wb25lbnQsCiAgICAgICAgICBhcmdzID0gX3JlZjE3LmFyZ3MsCiAgICAgICAgICBuYW1lZEFyZ3NQcm94eSA9IF9yZWYxNy5uYW1lZEFyZ3NQcm94eTsKICAgICAgdmFyIHZhbHVlJCQxOwogICAgICB7CiAgICAgICAgdmFsdWUkJDEgPSB7CiAgICAgICAgICBuYW1lZDogbmFtZWRBcmdzUHJveHksCiAgICAgICAgICBwb3NpdGlvbmFsOiBhcmdzLnBvc2l0aW9uYWwudmFsdWUoKQogICAgICAgIH07CiAgICAgIH0KCiAgICAgIGlmIChoYXNVcGRhdGVIb29rKGRlbGVnYXRlKSkgewogICAgICAgIGRlbGVnYXRlLnVwZGF0ZUNvbXBvbmVudChjb21wb25lbnQsIHZhbHVlJCQxKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG80OS5kaWRDcmVhdGUgPSBmdW5jdGlvbiBkaWRDcmVhdGUoX3JlZjE4KSB7CiAgICAgIHZhciBkZWxlZ2F0ZSA9IF9yZWYxOC5kZWxlZ2F0ZSwKICAgICAgICAgIGNvbXBvbmVudCA9IF9yZWYxOC5jb21wb25lbnQ7CgogICAgICBpZiAoaGFzQXN5bmNMaWZlQ3ljbGVDYWxsYmFja3MoZGVsZWdhdGUpKSB7CiAgICAgICAgZGVsZWdhdGUuZGlkQ3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNDkuZGlkVXBkYXRlID0gZnVuY3Rpb24gZGlkVXBkYXRlKF9yZWYxOSkgewogICAgICB2YXIgZGVsZWdhdGUgPSBfcmVmMTkuZGVsZWdhdGUsCiAgICAgICAgICBjb21wb25lbnQgPSBfcmVmMTkuY29tcG9uZW50OwoKICAgICAgaWYgKGhhc0FzeW5jVXBkYXRlSG9vayhkZWxlZ2F0ZSkpIHsKICAgICAgICBkZWxlZ2F0ZS5kaWRVcGRhdGVDb21wb25lbnQoY29tcG9uZW50KTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG80OS5nZXRDb250ZXh0ID0gZnVuY3Rpb24gZ2V0Q29udGV4dChfcmVmMjApIHsKICAgICAgdmFyIGRlbGVnYXRlID0gX3JlZjIwLmRlbGVnYXRlLAogICAgICAgICAgY29tcG9uZW50ID0gX3JlZjIwLmNvbXBvbmVudDsKICAgICAgZGVsZWdhdGUuZ2V0Q29udGV4dChjb21wb25lbnQpOwogICAgfTsKCiAgICBfcHJvdG80OS5nZXRTZWxmID0gZnVuY3Rpb24gZ2V0U2VsZihfcmVmMjEpIHsKICAgICAgdmFyIGRlbGVnYXRlID0gX3JlZjIxLmRlbGVnYXRlLAogICAgICAgICAgY29tcG9uZW50ID0gX3JlZjIxLmNvbXBvbmVudDsKICAgICAgcmV0dXJuIFJvb3RSZWZlcmVuY2UuY3JlYXRlKGRlbGVnYXRlLmdldENvbnRleHQoY29tcG9uZW50KSk7CiAgICB9OwoKICAgIF9wcm90bzQ5LmdldERlc3RydWN0b3IgPSBmdW5jdGlvbiBnZXREZXN0cnVjdG9yKHN0YXRlKSB7CiAgICAgIGlmIChoYXNEZXN0cnVjdG9ycyhzdGF0ZS5kZWxlZ2F0ZSkpIHsKICAgICAgICByZXR1cm4gc3RhdGU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNDkuZ2V0Q2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gZ2V0Q2FwYWJpbGl0aWVzKF9yZWYyMikgewogICAgICB2YXIgZGVsZWdhdGUgPSBfcmVmMjIuZGVsZWdhdGU7CiAgICAgIHJldHVybiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBDQVBBQklMSVRJRVMkMiwgewogICAgICAgIHVwZGF0ZUhvb2s6IGRlbGVnYXRlLmNhcGFiaWxpdGllcy51cGRhdGVIb29rCiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG80OS5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoX3JlZjIzKSB7CiAgICAgIHZhciBhcmdzID0gX3JlZjIzLmFyZ3M7CiAgICAgIHJldHVybiBhcmdzLnRhZzsKICAgIH07CgogICAgX3Byb3RvNDkuZGlkUmVuZGVyTGF5b3V0ID0gZnVuY3Rpb24gZGlkUmVuZGVyTGF5b3V0KCkge307CgogICAgX3Byb3RvNDkuZ2V0TGF5b3V0ID0gZnVuY3Rpb24gZ2V0TGF5b3V0KHN0YXRlKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiBzdGF0ZS50ZW1wbGF0ZS5hc0xheW91dCgpLmNvbXBpbGUoKSwKICAgICAgICBzeW1ib2xUYWJsZTogc3RhdGUuc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgcmV0dXJuIEN1c3RvbUNvbXBvbmVudE1hbmFnZXI7CiAgfShBYnN0cmFjdE1hbmFnZXIpOwoKICB2YXIgQ1VTVE9NX0NPTVBPTkVOVF9NQU5BR0VSID0gbmV3IEN1c3RvbUNvbXBvbmVudE1hbmFnZXIoKTsKICAvKioKICAgKiBTdG9yZXMgaW50ZXJuYWwgc3RhdGUgYWJvdXQgYSBjb21wb25lbnQgaW5zdGFuY2UgYWZ0ZXIgaXQncyBiZWVuIGNyZWF0ZWQuCiAgICovCgogIHZhciBDdXN0b21Db21wb25lbnRTdGF0ZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEN1c3RvbUNvbXBvbmVudFN0YXRlKGRlbGVnYXRlLCBjb21wb25lbnQsIGFyZ3MsIG5hbWVkQXJnc1Byb3h5KSB7CiAgICAgIHRoaXMuZGVsZWdhdGUgPSBkZWxlZ2F0ZTsKICAgICAgdGhpcy5jb21wb25lbnQgPSBjb21wb25lbnQ7CiAgICAgIHRoaXMuYXJncyA9IGFyZ3M7CiAgICAgIHRoaXMubmFtZWRBcmdzUHJveHkgPSBuYW1lZEFyZ3NQcm94eTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTAgPSBDdXN0b21Db21wb25lbnRTdGF0ZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNTAuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHZhciBkZWxlZ2F0ZSA9IHRoaXMuZGVsZWdhdGUsCiAgICAgICAgICBjb21wb25lbnQgPSB0aGlzLmNvbXBvbmVudDsKCiAgICAgIGlmIChoYXNEZXN0cnVjdG9ycyhkZWxlZ2F0ZSkpIHsKICAgICAgICBkZWxlZ2F0ZS5kZXN0cm95Q29tcG9uZW50KGNvbXBvbmVudCk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEN1c3RvbUNvbXBvbmVudFN0YXRlOwogIH0oKTsKCiAgdmFyIEN1c3RvbU1hbmFnZXJEZWZpbml0aW9uID0gZnVuY3Rpb24gQ3VzdG9tTWFuYWdlckRlZmluaXRpb24obmFtZSwgQ29tcG9uZW50Q2xhc3MsIGRlbGVnYXRlLCB0ZW1wbGF0ZSkgewogICAgdGhpcy5uYW1lID0gbmFtZTsKICAgIHRoaXMuQ29tcG9uZW50Q2xhc3MgPSBDb21wb25lbnRDbGFzczsKICAgIHRoaXMuZGVsZWdhdGUgPSBkZWxlZ2F0ZTsKICAgIHRoaXMudGVtcGxhdGUgPSB0ZW1wbGF0ZTsKICAgIHRoaXMubWFuYWdlciA9IENVU1RPTV9DT01QT05FTlRfTUFOQUdFUjsKICAgIHZhciBsYXlvdXQgPSB0ZW1wbGF0ZS5hc0xheW91dCgpOwogICAgdmFyIHN5bWJvbFRhYmxlID0gbGF5b3V0LnN5bWJvbFRhYmxlOwogICAgdGhpcy5zeW1ib2xUYWJsZSA9IHN5bWJvbFRhYmxlOwogICAgdGhpcy5zdGF0ZSA9IHsKICAgICAgbmFtZTogbmFtZSwKICAgICAgQ29tcG9uZW50Q2xhc3M6IENvbXBvbmVudENsYXNzLAogICAgICB0ZW1wbGF0ZTogdGVtcGxhdGUsCiAgICAgIHN5bWJvbFRhYmxlOiBzeW1ib2xUYWJsZSwKICAgICAgZGVsZWdhdGU6IGRlbGVnYXRlCiAgICB9OwogIH07CgogIHZhciBDQVBBQklMSVRJRVMkMyA9IHsKICAgIGR5bmFtaWNMYXlvdXQ6IGZhbHNlLAogICAgZHluYW1pY1RhZzogZmFsc2UsCiAgICBwcmVwYXJlQXJnczogZmFsc2UsCiAgICBjcmVhdGVBcmdzOiBmYWxzZSwKICAgIGF0dHJpYnV0ZUhvb2s6IGZhbHNlLAogICAgZWxlbWVudEhvb2s6IGZhbHNlLAogICAgY3JlYXRlQ2FsbGVyOiBmYWxzZSwKICAgIGR5bmFtaWNTY29wZTogZmFsc2UsCiAgICB1cGRhdGVIb29rOiBmYWxzZSwKICAgIGNyZWF0ZUluc3RhbmNlOiB0cnVlCiAgfTsKCiAgdmFyIFRlbXBsYXRlT25seUNvbXBvbmVudE1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Fic3RyYWN0TWFuYWdlcjUpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShUZW1wbGF0ZU9ubHlDb21wb25lbnRNYW5hZ2VyLCBfQWJzdHJhY3RNYW5hZ2VyNSk7CgogICAgZnVuY3Rpb24gVGVtcGxhdGVPbmx5Q29tcG9uZW50TWFuYWdlcigpIHsKICAgICAgcmV0dXJuIF9BYnN0cmFjdE1hbmFnZXI1LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTEgPSBUZW1wbGF0ZU9ubHlDb21wb25lbnRNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG81MS5nZXRMYXlvdXQgPSBmdW5jdGlvbiBnZXRMYXlvdXQodGVtcGxhdGUpIHsKICAgICAgdmFyIGxheW91dCA9IHRlbXBsYXRlLmFzTGF5b3V0KCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiBsYXlvdXQuY29tcGlsZSgpLAogICAgICAgIHN5bWJvbFRhYmxlOiBsYXlvdXQuc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvNTEuZ2V0Q2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gZ2V0Q2FwYWJpbGl0aWVzKCkgewogICAgICByZXR1cm4gQ0FQQUJJTElUSUVTJDM7CiAgICB9OwoKICAgIF9wcm90bzUxLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9OwoKICAgIF9wcm90bzUxLmdldFNlbGYgPSBmdW5jdGlvbiBnZXRTZWxmKCkgewogICAgICByZXR1cm4gX3J1bnRpbWUyLk5VTExfUkVGRVJFTkNFOwogICAgfTsKCiAgICBfcHJvdG81MS5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoKSB7CiAgICAgIHJldHVybiBfcmVmZXJlbmNlLkNPTlNUQU5UX1RBRzsKICAgIH07CgogICAgX3Byb3RvNTEuZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3IoKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfTsKCiAgICByZXR1cm4gVGVtcGxhdGVPbmx5Q29tcG9uZW50TWFuYWdlcjsKICB9KEFic3RyYWN0TWFuYWdlcik7CgogIHZhciBNQU5BR0VSID0gbmV3IFRlbXBsYXRlT25seUNvbXBvbmVudE1hbmFnZXIoKTsKCiAgdmFyIFRlbXBsYXRlT25seUNvbXBvbmVudERlZmluaXRpb24gPSBmdW5jdGlvbiBUZW1wbGF0ZU9ubHlDb21wb25lbnREZWZpbml0aW9uKHN0YXRlKSB7CiAgICB0aGlzLnN0YXRlID0gc3RhdGU7CiAgICB0aGlzLm1hbmFnZXIgPSBNQU5BR0VSOwogIH07CgogIHZhciBoZWxwZXIkMTsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIHZhciBDb21wb25lbnRBc3NlcnRpb25SZWZlcmVuY2UgPQogICAgLyojX19QVVJFX18qLwogICAgZnVuY3Rpb24gKCkgewogICAgICBmdW5jdGlvbiBDb21wb25lbnRBc3NlcnRpb25SZWZlcmVuY2UoY29tcG9uZW50LCBtZXNzYWdlKSB7CiAgICAgICAgdGhpcy5jb21wb25lbnQgPSBjb21wb25lbnQ7CiAgICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTsKICAgICAgICB0aGlzLnRhZyA9IGNvbXBvbmVudC50YWc7CiAgICAgIH0KCiAgICAgIHZhciBfcHJvdG81MiA9IENvbXBvbmVudEFzc2VydGlvblJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgICBfcHJvdG81Mi52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgIHZhciB2YWx1ZSQkMSA9IHRoaXMuY29tcG9uZW50LnZhbHVlKCk7CiAgICAgICAgKGZhbHNlICYmICEodHlwZW9mIHZhbHVlJCQxICE9PSAnc3RyaW5nJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMubWVzc2FnZSwgdHlwZW9mIHZhbHVlJCQxICE9PSAnc3RyaW5nJykpOwogICAgICAgIHJldHVybiB2YWx1ZSQkMTsKICAgICAgfTsKCiAgICAgIF9wcm90bzUyLmdldCA9IGZ1bmN0aW9uIGdldChwcm9wZXJ0eSkgewogICAgICAgIHJldHVybiB0aGlzLmNvbXBvbmVudC5nZXQocHJvcGVydHkpOwogICAgICB9OwoKICAgICAgcmV0dXJuIENvbXBvbmVudEFzc2VydGlvblJlZmVyZW5jZTsKICAgIH0oKTsKCiAgICBoZWxwZXIkMSA9IGZ1bmN0aW9uIGhlbHBlciQxKF92bSwgYXJncykgewogICAgICByZXR1cm4gbmV3IENvbXBvbmVudEFzc2VydGlvblJlZmVyZW5jZShhcmdzLnBvc2l0aW9uYWwuYXQoMCksIGFyZ3MucG9zaXRpb25hbC5hdCgxKS52YWx1ZSgpKTsKICAgIH07CiAgfSBlbHNlIHsKICAgIGhlbHBlciQxID0gZnVuY3Rpb24gaGVscGVyJDEoX3ZtLCBhcmdzKSB7CiAgICAgIHJldHVybiBhcmdzLnBvc2l0aW9uYWwuYXQoMCk7CiAgICB9OwogIH0KCiAgdmFyIGNvbXBvbmVudEFzc2VydGlvbkhlbHBlciA9IGhlbHBlciQxOwoKICBmdW5jdGlvbiBjbGFzc0hlbHBlcihfcmVmMjQpIHsKICAgIHZhciBwb3NpdGlvbmFsID0gX3JlZjI0LnBvc2l0aW9uYWw7CiAgICB2YXIgcGF0aCA9IHBvc2l0aW9uYWwuYXQoMCk7CiAgICB2YXIgYXJncyA9IHBvc2l0aW9uYWwubGVuZ3RoOwogICAgdmFyIHZhbHVlJCQxID0gcGF0aC52YWx1ZSgpOwoKICAgIGlmICh2YWx1ZSQkMSA9PT0gdHJ1ZSkgewogICAgICBpZiAoYXJncyA+IDEpIHsKICAgICAgICByZXR1cm4gKDAsIF9zdHJpbmcuZGFzaGVyaXplKShwb3NpdGlvbmFsLmF0KDEpLnZhbHVlKCkpOwogICAgICB9CgogICAgICByZXR1cm4gbnVsbDsKICAgIH0KCiAgICBpZiAodmFsdWUkJDEgPT09IGZhbHNlKSB7CiAgICAgIGlmIChhcmdzID4gMikgewogICAgICAgIHJldHVybiAoMCwgX3N0cmluZy5kYXNoZXJpemUpKHBvc2l0aW9uYWwuYXQoMikudmFsdWUoKSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBudWxsOwogICAgfQoKICAgIHJldHVybiB2YWx1ZSQkMTsKICB9CgogIGZ1bmN0aW9uIGNsYXNzSGVscGVyJDEoX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gbmV3IEludGVybmFsSGVscGVyUmVmZXJlbmNlKGNsYXNzSGVscGVyLCBhcmdzLmNhcHR1cmUoKSk7CiAgfQoKICBmdW5jdGlvbiBpbnB1dFR5cGVIZWxwZXIoX3JlZjI1KSB7CiAgICB2YXIgcG9zaXRpb25hbCA9IF9yZWYyNS5wb3NpdGlvbmFsOwogICAgdmFyIHR5cGUgPSBwb3NpdGlvbmFsLmF0KDApLnZhbHVlKCk7CgogICAgaWYgKHR5cGUgPT09ICdjaGVja2JveCcpIHsKICAgICAgcmV0dXJuICctY2hlY2tib3gnOwogICAgfQoKICAgIHJldHVybiAnLXRleHQtZmllbGQnOwogIH0KCiAgZnVuY3Rpb24gaW5wdXRUeXBlSGVscGVyJDEoX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gbmV3IEludGVybmFsSGVscGVyUmVmZXJlbmNlKGlucHV0VHlwZUhlbHBlciwgYXJncy5jYXB0dXJlKCkpOwogIH0KCiAgZnVuY3Rpb24gbm9ybWFsaXplQ2xhc3MoX3JlZjI2KSB7CiAgICB2YXIgcG9zaXRpb25hbCA9IF9yZWYyNi5wb3NpdGlvbmFsOwogICAgdmFyIGNsYXNzTmFtZVBhcnRzID0gcG9zaXRpb25hbC5hdCgwKS52YWx1ZSgpLnNwbGl0KCcuJyk7CiAgICB2YXIgY2xhc3NOYW1lID0gY2xhc3NOYW1lUGFydHNbY2xhc3NOYW1lUGFydHMubGVuZ3RoIC0gMV07CiAgICB2YXIgdmFsdWUkJDEgPSBwb3NpdGlvbmFsLmF0KDEpLnZhbHVlKCk7CgogICAgaWYgKHZhbHVlJCQxID09PSB0cnVlKSB7CiAgICAgIHJldHVybiAoMCwgX3N0cmluZy5kYXNoZXJpemUpKGNsYXNzTmFtZSk7CiAgICB9IGVsc2UgaWYgKCF2YWx1ZSQkMSAmJiB2YWx1ZSQkMSAhPT0gMCkgewogICAgICByZXR1cm4gJyc7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gU3RyaW5nKHZhbHVlJCQxKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIG5vcm1hbGl6ZUNsYXNzSGVscGVyKF92bSwgYXJncykgewogICAgcmV0dXJuIG5ldyBJbnRlcm5hbEhlbHBlclJlZmVyZW5jZShub3JtYWxpemVDbGFzcywgYXJncy5jYXB0dXJlKCkpOwogIH0KICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBUaGUgYHt7YWN0aW9ufX1gIGhlbHBlciBwcm92aWRlcyBhIHdheSB0byBwYXNzIHRyaWdnZXJzIGZvciBiZWhhdmlvciAodXN1YWxseQogICAganVzdCBhIGZ1bmN0aW9uKSBiZXR3ZWVuIGNvbXBvbmVudHMsIGFuZCBpbnRvIGNvbXBvbmVudHMgZnJvbSBjb250cm9sbGVycy4KICAKICAgICMjIyBQYXNzaW5nIGZ1bmN0aW9ucyB3aXRoIHRoZSBhY3Rpb24gaGVscGVyCiAgCiAgICBUaGVyZSBhcmUgdGhyZWUgY29udGV4dHMgYW4gYWN0aW9uIGhlbHBlciBjYW4gYmUgdXNlZCBpbi4gVGhlIGZpcnN0IHR3bwogICAgY29udGV4dHMgdG8gZGlzY3VzcyBhcmUgYXR0cmlidXRlIGNvbnRleHQsIGFuZCBIYW5kbGViYXJzIHZhbHVlIGNvbnRleHQuCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7eyEgQW4gZXhhbXBsZSBvZiBhdHRyaWJ1dGUgY29udGV4dCB9fQogICAgPGRpdiBvbmNsaWNrPXt7YWN0aW9uICJzYXZlIn19PjwvZGl2PgogICAge3shIEV4YW1wbGVzIG9mIEhhbmRsZWJhcnMgdmFsdWUgY29udGV4dCB9fQogICAge3tpbnB1dCBvbi1pbnB1dD0oYWN0aW9uICJzYXZlIil9fQogICAge3t5aWVsZCAoYWN0aW9uICJyZWZyZXNoRGF0YSIpIGFuZEFub3RoZXJQYXJhbX19CiAgICBgYGAKICAKICAgIEluIHRoZXNlIGNvbnRleHRzLAogICAgdGhlIGhlbHBlciBpcyBjYWxsZWQgYSAiY2xvc3VyZSBhY3Rpb24iIGhlbHBlci4gSXRzIGJlaGF2aW9yIGlzIHNpbXBsZToKICAgIElmIHBhc3NlZCBhIGZ1bmN0aW9uIG5hbWUsIHJlYWQgdGhhdCBmdW5jdGlvbiBvZmYgdGhlIGBhY3Rpb25zYCBwcm9wZXJ0eQogICAgb2YgdGhlIGN1cnJlbnQgY29udGV4dC4gT25jZSB0aGF0IGZ1bmN0aW9uIGlzIHJlYWQsIG9yIGltbWVkaWF0ZWx5IGlmIGEgZnVuY3Rpb24gd2FzCiAgICBwYXNzZWQsIGNyZWF0ZSBhIGNsb3N1cmUgb3ZlciB0aGF0IGZ1bmN0aW9uIGFuZCBhbnkgYXJndW1lbnRzLgogICAgVGhlIHJlc3VsdGluZyB2YWx1ZSBvZiBhbiBhY3Rpb24gaGVscGVyIHVzZWQgdGhpcyB3YXkgaXMgc2ltcGx5IGEgZnVuY3Rpb24uCiAgCiAgICBGb3IgZXhhbXBsZSwgaW4gdGhlIGF0dHJpYnV0ZSBjb250ZXh0OgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3shIEFuIGV4YW1wbGUgb2YgYXR0cmlidXRlIGNvbnRleHQgfX0KICAgIDxkaXYgb25jbGljaz17e2FjdGlvbiAic2F2ZSJ9fT48L2Rpdj4KICAgIGBgYAogIAogICAgVGhlIHJlc3VsdGluZyB0ZW1wbGF0ZSByZW5kZXIgbG9naWMgd291bGQgYmU6CiAgCiAgICBgYGBqcwogICAgdmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgdmFyIGFjdGlvbkZ1bmN0aW9uID0gKGZ1bmN0aW9uKGNvbnRleHQpewogICAgICByZXR1cm4gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIGNvbnRleHQuYWN0aW9ucy5zYXZlLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7CiAgICAgIH07CiAgICB9KShjb250ZXh0KTsKICAgIGRpdi5vbmNsaWNrID0gYWN0aW9uRnVuY3Rpb247CiAgICBgYGAKICAKICAgIFRodXMgd2hlbiB0aGUgZGl2IGlzIGNsaWNrZWQsIHRoZSBhY3Rpb24gb24gdGhhdCBjb250ZXh0IGlzIGNhbGxlZC4KICAgIEJlY2F1c2UgdGhlIGBhY3Rpb25GdW5jdGlvbmAgaXMganVzdCBhIGZ1bmN0aW9uLCBjbG9zdXJlIGFjdGlvbnMgY2FuIGJlCiAgICBwYXNzZWQgYmV0d2VlbiBjb21wb25lbnRzIGFuZCBzdGlsbCBleGVjdXRlIGluIHRoZSBjb3JyZWN0IGNvbnRleHQuCiAgCiAgICBIZXJlIGlzIGFuIGV4YW1wbGUgYWN0aW9uIGhhbmRsZXIgb24gYSBjb21wb25lbnQ6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgYWN0aW9uczogewogICAgICAgIHNhdmUoKSB7CiAgICAgICAgICB0aGlzLmdldCgnbW9kZWwnKS5zYXZlKCk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQWN0aW9ucyBhcmUgYWx3YXlzIGxvb2tlZCB1cCBvbiB0aGUgYGFjdGlvbnNgIHByb3BlcnR5IG9mIHRoZSBjdXJyZW50IGNvbnRleHQuCiAgICBUaGlzIGF2b2lkcyBjb2xsaXNpb25zIGluIHRoZSBuYW1pbmcgb2YgY29tbW9uIGFjdGlvbnMsIHN1Y2ggYXMgYGRlc3Ryb3lgLgogICAgVHdvIG9wdGlvbnMgY2FuIGJlIHBhc3NlZCB0byB0aGUgYGFjdGlvbmAgaGVscGVyIHdoZW4gaXQgaXMgdXNlZCBpbiB0aGlzIHdheS4KICAKICAgICogYHRhcmdldD1zb21lUHJvcGVydHlgIHdpbGwgbG9vayB0byBgc29tZVByb3BlcnR5YCBpbnN0ZWFkIG9mIHRoZSBjdXJyZW50CiAgICAgIGNvbnRleHQgZm9yIHRoZSBgYWN0aW9uc2AgaGFzaC4gVGhpcyBjYW4gYmUgdXNlZnVsIHdoZW4gdGFyZ2V0aW5nIGEKICAgICAgc2VydmljZSBmb3IgYWN0aW9ucy4KICAgICogYHZhbHVlPSJ0YXJnZXQudmFsdWUiYCB3aWxsIHJlYWQgdGhlIHBhdGggYHRhcmdldC52YWx1ZWAgb2ZmIHRoZSBmaXJzdAogICAgICBhcmd1bWVudCB0byB0aGUgYWN0aW9uIHdoZW4gaXQgaXMgY2FsbGVkIGFuZCByZXdyaXRlIHRoZSBmaXJzdCBhcmd1bWVudAogICAgICB0byBiZSB0aGF0IHZhbHVlLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIGF0dGFjaGluZyBhY3Rpb25zIHRvIGV2ZW50IGxpc3RlbmVycy4KICAKICAgICMjIyBJbnZva2luZyBhbiBhY3Rpb24KICAKICAgIENsb3N1cmUgYWN0aW9ucyBjdXJyeSBib3RoIHRoZWlyIHNjb3BlIGFuZCBhbnkgYXJndW1lbnRzLiBXaGVuIGludm9rZWQsIGFueQogICAgYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlIGFkZGVkIHRvIHRoZSBhbHJlYWR5IGN1cnJpZWQgbGlzdC4KICAgIEFjdGlvbnMgc2hvdWxkIGJlIGludm9rZWQgdXNpbmcgdGhlIFtzZW5kQWN0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0NvbXBvbmVudC9tZXRob2RzL3NlbmRBY3Rpb24/YW5jaG9yPXNlbmRBY3Rpb24pCiAgICBtZXRob2QuIFRoZSBmaXJzdCBhcmd1bWVudCB0byBgc2VuZEFjdGlvbmAgaXMgdGhlIGFjdGlvbiB0byBiZSBjYWxsZWQsIGFuZAogICAgYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlIHBhc3NlZCB0byB0aGUgYWN0aW9uIGZ1bmN0aW9uLiBUaGlzIGhhcyBpbnRlcmVzdGluZwogICAgcHJvcGVydGllcyBjb21iaW5lZCB3aXRoIGN1cnJ5aW5nIG9mIGFyZ3VtZW50cy4gRm9yIGV4YW1wbGU6CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvbXktY29tcG9uZW50LmhicwogICAge3tpbnB1dCBvbi1pbnB1dD0oYWN0aW9uIChhY3Rpb24gJ3NldE5hbWUnIG1vZGVsKSB2YWx1ZT0idGFyZ2V0LnZhbHVlIil9fQogICAgYGBgCiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgYWN0aW9uczogewogICAgICAgIHNldE5hbWUobW9kZWwsIG5hbWUpIHsKICAgICAgICAgIG1vZGVsLnNldCgnbmFtZScsIG5hbWUpOwogICAgICAgIH0KICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIFRoZSBmaXJzdCBhcmd1bWVudCAoYG1vZGVsYCkgd2FzIGN1cnJpZWQgb3ZlciwgYW5kIHRoZSBydW4tdGltZSBhcmd1bWVudCAoYGV2ZW50YCkKICAgIGJlY29tZXMgYSBzZWNvbmQgYXJndW1lbnQuIEFjdGlvbiBjYWxscyBjYW4gYmUgbmVzdGVkIHRoaXMgd2F5IGJlY2F1c2UgZWFjaCBzaW1wbHkKICAgIHJldHVybnMgYSBmdW5jdGlvbi4gQW55IGZ1bmN0aW9uIGNhbiBiZSBwYXNzZWQgdG8gdGhlIGB7e2FjdGlvbn19YCBoZWxwZXIsIGluY2x1ZGluZwogICAgb3RoZXIgYWN0aW9ucy4KICAKICAgIEFjdGlvbnMgaW52b2tlZCB3aXRoIGBzZW5kQWN0aW9uYCBoYXZlIHRoZSBzYW1lIGN1cnJ5aW5nIGJlaGF2aW9yIGFzIGRlbW9uc3RyYXRlZAogICAgd2l0aCBgb24taW5wdXRgIGFib3ZlLiBGb3IgZXhhbXBsZToKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LWlucHV0LmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGFjdGlvbnM6IHsKICAgICAgICBzZXROYW1lKG1vZGVsLCBuYW1lKSB7CiAgICAgICAgICBtb2RlbC5zZXQoJ25hbWUnLCBuYW1lKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8TXlJbnB1dCBAc3VibWl0PXt7YWN0aW9uICdzZXROYW1lJyB0aGlzLm1vZGVsfX0gLz4KICAgIGBgYAogICAgb3IKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7bXktaW5wdXQgc3VibWl0PShhY3Rpb24gJ3NldE5hbWUnIG1vZGVsKX19CiAgICBgYGAKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LWNvbXBvbmVudC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGljaygpIHsKICAgICAgICAvLyBOb3RlIHRoYXQgbW9kZWwgaXMgbm90IHBhc3NlZCwgaXQgd2FzIGN1cnJpZWQgaW4gdGhlIHRlbXBsYXRlCiAgICAgICAgdGhpcy5zZW5kQWN0aW9uKCdzdWJtaXQnLCAnYm9iJyk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICAjIyMgQXR0YWNoaW5nIGFjdGlvbnMgdG8gRE9NIGVsZW1lbnRzCiAgCiAgICBUaGUgdGhpcmQgY29udGV4dCBvZiB0aGUgYHt7YWN0aW9ufX1gIGhlbHBlciBjYW4gYmUgY2FsbGVkICJlbGVtZW50IHNwYWNlIi4KICAgIEZvciBleGFtcGxlOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3shIEFuIGV4YW1wbGUgb2YgZWxlbWVudCBzcGFjZSB9fQogICAgPGRpdiB7e2FjdGlvbiAic2F2ZSJ9fT48L2Rpdj4KICAgIGBgYAogIAogICAgVXNlZCB0aGlzIHdheSwgdGhlIGB7e2FjdGlvbn19YCBoZWxwZXIgcHJvdmlkZXMgYSB1c2VmdWwgc2hvcnRjdXQgZm9yCiAgICByZWdpc3RlcmluZyBhbiBIVE1MIGVsZW1lbnQgaW4gYSB0ZW1wbGF0ZSBmb3IgYSBzaW5nbGUgRE9NIGV2ZW50IGFuZAogICAgZm9yd2FyZGluZyB0aGF0IGludGVyYWN0aW9uIHRvIHRoZSB0ZW1wbGF0ZSdzIGNvbnRleHQgKGNvbnRyb2xsZXIgb3IgY29tcG9uZW50KS4KICAgIElmIHRoZSBjb250ZXh0IG9mIGEgdGVtcGxhdGUgaXMgYSBjb250cm9sbGVyLCBhY3Rpb25zIHVzZWQgdGhpcyB3YXkgd2lsbAogICAgYnViYmxlIHRvIHJvdXRlcyB3aGVuIHRoZSBjb250cm9sbGVyIGRvZXMgbm90IGltcGxlbWVudCB0aGUgc3BlY2lmaWVkIGFjdGlvbi4KICAgIE9uY2UgYW4gYWN0aW9uIGhpdHMgYSByb3V0ZSwgaXQgd2lsbCBidWJibGUgdGhyb3VnaCB0aGUgcm91dGUgaGllcmFyY2h5LgogIAogICAgIyMjIEV2ZW50IFByb3BhZ2F0aW9uCiAgCiAgICBge3thY3Rpb259fWAgaGVscGVycyBjYWxsZWQgaW4gZWxlbWVudCBzcGFjZSBjYW4gY29udHJvbCBldmVudCBidWJibGluZy4gTm90ZQogICAgdGhhdCB0aGUgY2xvc3VyZSBzdHlsZSBhY3Rpb25zIGNhbm5vdC4KICAKICAgIEV2ZW50cyB0cmlnZ2VyZWQgdGhyb3VnaCB0aGUgYWN0aW9uIGhlbHBlciB3aWxsIGF1dG9tYXRpY2FsbHkgaGF2ZQogICAgYC5wcmV2ZW50RGVmYXVsdCgpYCBjYWxsZWQgb24gdGhlbS4gWW91IGRvIG5vdCBuZWVkIHRvIGRvIHNvIGluIHlvdXIgZXZlbnQKICAgIGhhbmRsZXJzLiBJZiB5b3UgbmVlZCB0byBhbGxvdyBldmVudCBwcm9wYWdhdGlvbiAodG8gaGFuZGxlIGZpbGUgaW5wdXRzIGZvcgogICAgZXhhbXBsZSkgeW91IGNhbiBzdXBwbHkgdGhlIGBwcmV2ZW50RGVmYXVsdD1mYWxzZWAgb3B0aW9uIHRvIHRoZSBge3thY3Rpb259fWAgaGVscGVyOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPGRpdiB7e2FjdGlvbiAic2F5SGVsbG8iIHByZXZlbnREZWZhdWx0PWZhbHNlfX0+CiAgICAgIDxpbnB1dCB0eXBlPSJmaWxlIiAvPgogICAgICA8aW5wdXQgdHlwZT0iY2hlY2tib3giIC8+CiAgICA8L2Rpdj4KICAgIGBgYAogIAogICAgVG8gZGlzYWJsZSBidWJibGluZywgcGFzcyBgYnViYmxlcz1mYWxzZWAgdG8gdGhlIGhlbHBlcjoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxidXR0b24ge3thY3Rpb24gJ2VkaXQnIHBvc3QgYnViYmxlcz1mYWxzZX19PkVkaXQ8L2J1dHRvbj4KICAgIGBgYAogIAogICAgVG8gZGlzYWJsZSBidWJibGluZyB3aXRoIGNsb3N1cmUgc3R5bGUgYWN0aW9ucyB5b3UgbXVzdCBjcmVhdGUgeW91ciBvd24KICAgIHdyYXBwZXIgaGVscGVyIHRoYXQgbWFrZXMgdXNlIG9mIGBldmVudC5zdG9wUHJvcGFnYXRpb24oKWA6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8ZGl2IG9uY2xpY2s9e3tkaXNhYmxlLWJ1YmJsaW5nIChhY3Rpb24gInNheUhlbGxvIil9fT5IZWxsbzwvZGl2PgogICAgYGBgCiAgCiAgICBgYGBhcHAvaGVscGVycy9kaXNhYmxlLWJ1YmJsaW5nLmpzCiAgICBpbXBvcnQgeyBoZWxwZXIgfSBmcm9tICdAZW1iZXIvY29tcG9uZW50L2hlbHBlcic7CiAgCiAgICBleHBvcnQgZnVuY3Rpb24gZGlzYWJsZUJ1YmJsaW5nKFthY3Rpb25dKSB7CiAgICAgIHJldHVybiBmdW5jdGlvbihldmVudCkgewogICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOwogICAgICAgIHJldHVybiBhY3Rpb24oZXZlbnQpOwogICAgICB9OwogICAgfQogICAgZXhwb3J0IGRlZmF1bHQgaGVscGVyKGRpc2FibGVCdWJibGluZyk7CiAgICBgYGAKICAKICAgIElmIHlvdSBuZWVkIHRoZSBkZWZhdWx0IGhhbmRsZXIgdG8gdHJpZ2dlciB5b3Ugc2hvdWxkIGVpdGhlciByZWdpc3RlciB5b3VyCiAgICBvd24gZXZlbnQgaGFuZGxlciwgb3IgdXNlIGV2ZW50IG1ldGhvZHMgb24geW91ciB2aWV3IGNsYXNzLiBTZWUKICAgIFsiUmVzcG9uZGluZyB0byBCcm93c2VyIEV2ZW50cyJdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvQ29tcG9uZW50KQogICAgaW4gdGhlIGRvY3VtZW50YXRpb24gZm9yIGBDb21wb25lbnRgIGZvciBtb3JlIGluZm9ybWF0aW9uLgogIAogICAgIyMjIFNwZWNpZnlpbmcgRE9NIGV2ZW50IHR5cGUKICAKICAgIGB7e2FjdGlvbn19YCBoZWxwZXJzIGNhbGxlZCBpbiBlbGVtZW50IHNwYWNlIGNhbiBzcGVjaWZ5IGFuIGV2ZW50IHR5cGUuCiAgICBCeSBkZWZhdWx0IHRoZSBge3thY3Rpb259fWAgaGVscGVyIHJlZ2lzdGVycyBmb3IgRE9NIGBjbGlja2AgZXZlbnRzLiBZb3UgY2FuCiAgICBzdXBwbHkgYW4gYG9uYCBvcHRpb24gdG8gdGhlIGhlbHBlciB0byBzcGVjaWZ5IGEgZGlmZmVyZW50IERPTSBldmVudCBuYW1lOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPGRpdiB7e2FjdGlvbiAiYW5BY3Rpb25OYW1lIiBvbj0iZG91YmxlQ2xpY2sifX0+CiAgICAgIGNsaWNrIG1lCiAgICA8L2Rpdj4KICAgIGBgYAogIAogICAgU2VlIFsiRXZlbnQgTmFtZXMiXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0NvbXBvbmVudCkgZm9yIGEgbGlzdCBvZgogICAgYWNjZXB0YWJsZSBET00gZXZlbnQgbmFtZXMuCiAgCiAgICAjIyMgU3BlY2lmeWluZyB3aGl0ZWxpc3RlZCBtb2RpZmllciBrZXlzCiAgCiAgICBge3thY3Rpb259fWAgaGVscGVycyBjYWxsZWQgaW4gZWxlbWVudCBzcGFjZSBjYW4gc3BlY2lmeSBtb2RpZmllciBrZXlzLgogICAgQnkgZGVmYXVsdCB0aGUgYHt7YWN0aW9ufX1gIGhlbHBlciB3aWxsIGlnbm9yZSBjbGljayBldmVudHMgd2l0aCBwcmVzc2VkIG1vZGlmaWVyCiAgICBrZXlzLiBZb3UgY2FuIHN1cHBseSBhbiBgYWxsb3dlZEtleXNgIG9wdGlvbiB0byBzcGVjaWZ5IHdoaWNoIGtleXMgc2hvdWxkIG5vdCBiZSBpZ25vcmVkLgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPGRpdiB7e2FjdGlvbiAiYW5BY3Rpb25OYW1lIiBhbGxvd2VkS2V5cz0iYWx0In19PgogICAgICBjbGljayBtZQogICAgPC9kaXY+CiAgICBgYGAKICAKICAgIFRoaXMgd2F5IHRoZSBhY3Rpb24gd2lsbCBmaXJlIHdoZW4gY2xpY2tpbmcgd2l0aCB0aGUgYWx0IGtleSBwcmVzc2VkIGRvd24uCiAgICBBbHRlcm5hdGl2ZWx5LCBzdXBwbHkgImFueSIgdG8gdGhlIGBhbGxvd2VkS2V5c2Agb3B0aW9uIHRvIGFjY2VwdCBhbnkgY29tYmluYXRpb24gb2YgbW9kaWZpZXIga2V5cy4KICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxkaXYge3thY3Rpb24gImFuQWN0aW9uTmFtZSIgYWxsb3dlZEtleXM9ImFueSJ9fT4KICAgICAgY2xpY2sgbWUgd2l0aCBhbnkga2V5IHByZXNzZWQKICAgIDwvZGl2PgogICAgYGBgCiAgCiAgICAjIyMgU3BlY2lmeWluZyBhIFRhcmdldAogIAogICAgQSBgdGFyZ2V0YCBvcHRpb24gY2FuIGJlIHByb3ZpZGVkIHRvIHRoZSBoZWxwZXIgdG8gY2hhbmdlCiAgICB3aGljaCBvYmplY3Qgd2lsbCByZWNlaXZlIHRoZSBtZXRob2QgY2FsbC4gVGhpcyBvcHRpb24gbXVzdCBiZSBhIHBhdGgKICAgIHRvIGFuIG9iamVjdCwgYWNjZXNzaWJsZSBpbiB0aGUgY3VycmVudCBjb250ZXh0OgogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9hcHBsaWNhdGlvbi5oYnMKICAgIDxkaXYge3thY3Rpb24gImFuQWN0aW9uTmFtZSIgdGFyZ2V0PXNvbWVTZXJ2aWNlfX0+CiAgICAgIGNsaWNrIG1lCiAgICA8L2Rpdj4KICAgIGBgYAogIAogICAgYGBgYXBwL2NvbnRyb2xsZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgQ29udHJvbGxlciBmcm9tICdAZW1iZXIvY29udHJvbGxlcic7CiAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbnRyb2xsZXIuZXh0ZW5kKHsKICAgICAgc29tZVNlcnZpY2U6IHNlcnZpY2UoKQogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgYWN0aW9uCiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGFjdGlvbihfdm0sIGFyZ3MpIHsKICAgIHZhciBuYW1lZCA9IGFyZ3MubmFtZWQsCiAgICAgICAgcG9zaXRpb25hbCA9IGFyZ3MucG9zaXRpb25hbDsKICAgIHZhciBjYXB0dXJlZEFyZ3MgPSBwb3NpdGlvbmFsLmNhcHR1cmUoKTsgLy8gVGhlIGZpcnN0IHR3byBhcmd1bWVudCBzbG90cyBhcmUgcmVzZXJ2ZWQuCiAgICAvLyBwb3NbMF0gaXMgdGhlIGNvbnRleHQgKG9yIGB0aGlzYCkKICAgIC8vIHBvc1sxXSBpcyB0aGUgYWN0aW9uIG5hbWUgb3IgZnVuY3Rpb24KICAgIC8vIEFueXRoaW5nIGVsc2UgaXMgYW4gYWN0aW9uIGFyZ3VtZW50LgoKICAgIHZhciBfY2FwdHVyZWRBcmdzJHJlZmVyZW4gPSBjYXB0dXJlZEFyZ3MucmVmZXJlbmNlcywKICAgICAgICBjb250ZXh0ID0gX2NhcHR1cmVkQXJncyRyZWZlcmVuWzBdLAogICAgICAgIGFjdGlvbiA9IF9jYXB0dXJlZEFyZ3MkcmVmZXJlblsxXSwKICAgICAgICByZXN0QXJncyA9IF9jYXB0dXJlZEFyZ3MkcmVmZXJlbi5zbGljZSgyKTsgLy8gVE9ETzogSXMgdGhlcmUgYSBiZXR0ZXIgd2F5IG9mIGRvaW5nIHRoaXM/CgoKICAgIHZhciBkZWJ1Z0tleSA9IGFjdGlvbi5wcm9wZXJ0eUtleTsKICAgIHZhciB0YXJnZXQgPSBuYW1lZC5oYXMoJ3RhcmdldCcpID8gbmFtZWQuZ2V0KCd0YXJnZXQnKSA6IGNvbnRleHQ7CiAgICB2YXIgcHJvY2Vzc0FyZ3MgPSBtYWtlQXJnc1Byb2Nlc3NvcihuYW1lZC5oYXMoJ3ZhbHVlJykgJiYgbmFtZWQuZ2V0KCd2YWx1ZScpLCByZXN0QXJncyk7CiAgICB2YXIgZm47CgogICAgaWYgKHR5cGVvZiBhY3Rpb25bSU5WT0tFXSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICBmbiA9IG1ha2VDbG9zdXJlQWN0aW9uKGFjdGlvbiwgYWN0aW9uLCBhY3Rpb25bSU5WT0tFXSwgcHJvY2Vzc0FyZ3MsIGRlYnVnS2V5KTsKICAgIH0gZWxzZSBpZiAoKDAsIF9yZWZlcmVuY2UuaXNDb25zdCkodGFyZ2V0KSAmJiAoMCwgX3JlZmVyZW5jZS5pc0NvbnN0KShhY3Rpb24pKSB7CiAgICAgIGZuID0gbWFrZUNsb3N1cmVBY3Rpb24oY29udGV4dC52YWx1ZSgpLCB0YXJnZXQudmFsdWUoKSwgYWN0aW9uLnZhbHVlKCksIHByb2Nlc3NBcmdzLCBkZWJ1Z0tleSk7CiAgICB9IGVsc2UgewogICAgICBmbiA9IG1ha2VEeW5hbWljQ2xvc3VyZUFjdGlvbihjb250ZXh0LnZhbHVlKCksIHRhcmdldCwgYWN0aW9uLCBwcm9jZXNzQXJncywgZGVidWdLZXkpOwogICAgfQoKICAgIGZuW0FDVElPTl0gPSB0cnVlOwogICAgcmV0dXJuIG5ldyBVbmJvdW5kUmVmZXJlbmNlKGZuKTsKICB9CgogIGZ1bmN0aW9uIE5PT1AkMShhcmdzKSB7CiAgICByZXR1cm4gYXJnczsKICB9CgogIGZ1bmN0aW9uIG1ha2VBcmdzUHJvY2Vzc29yKHZhbHVlUGF0aFJlZiwgYWN0aW9uQXJnc1JlZikgewogICAgdmFyIG1lcmdlQXJnczsKCiAgICBpZiAoYWN0aW9uQXJnc1JlZi5sZW5ndGggPiAwKSB7CiAgICAgIG1lcmdlQXJncyA9IGZ1bmN0aW9uIG1lcmdlQXJncyhhcmdzKSB7CiAgICAgICAgcmV0dXJuIGFjdGlvbkFyZ3NSZWYubWFwKGZ1bmN0aW9uIChyZWYpIHsKICAgICAgICAgIHJldHVybiByZWYudmFsdWUoKTsKICAgICAgICB9KS5jb25jYXQoYXJncyk7CiAgICAgIH07CiAgICB9CgogICAgdmFyIHJlYWRWYWx1ZTsKCiAgICBpZiAodmFsdWVQYXRoUmVmKSB7CiAgICAgIHJlYWRWYWx1ZSA9IGZ1bmN0aW9uIHJlYWRWYWx1ZShhcmdzKSB7CiAgICAgICAgdmFyIHZhbHVlUGF0aCA9IHZhbHVlUGF0aFJlZi52YWx1ZSgpOwoKICAgICAgICBpZiAodmFsdWVQYXRoICYmIGFyZ3MubGVuZ3RoID4gMCkgewogICAgICAgICAgYXJnc1swXSA9ICgwLCBfbWV0YWwuZ2V0KShhcmdzWzBdLCB2YWx1ZVBhdGgpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGFyZ3M7CiAgICAgIH07CiAgICB9CgogICAgaWYgKG1lcmdlQXJncyAmJiByZWFkVmFsdWUpIHsKICAgICAgcmV0dXJuIGZ1bmN0aW9uIChhcmdzKSB7CiAgICAgICAgcmV0dXJuIHJlYWRWYWx1ZShtZXJnZUFyZ3MoYXJncykpOwogICAgICB9OwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG1lcmdlQXJncyB8fCByZWFkVmFsdWUgfHwgTk9PUCQxOwogICAgfQogIH0KCiAgZnVuY3Rpb24gbWFrZUR5bmFtaWNDbG9zdXJlQWN0aW9uKGNvbnRleHQsIHRhcmdldFJlZiwgYWN0aW9uUmVmLCBwcm9jZXNzQXJncywgZGVidWdLZXkpIHsKICAgIC8vIFdlIGRvbid0IGFsbG93IHVuZGVmaW5lZC9udWxsIHZhbHVlcywgc28gdGhpcyBjcmVhdGVzIGEgdGhyb3ctYXdheSBhY3Rpb24gdG8gdHJpZ2dlciB0aGUgYXNzZXJ0aW9ucwogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgKSB7CiAgICAgIG1ha2VDbG9zdXJlQWN0aW9uKGNvbnRleHQsIHRhcmdldFJlZi52YWx1ZSgpLCBhY3Rpb25SZWYudmFsdWUoKSwgcHJvY2Vzc0FyZ3MsIGRlYnVnS2V5KTsKICAgIH0KCiAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gbWFrZUNsb3N1cmVBY3Rpb24oY29udGV4dCwgdGFyZ2V0UmVmLnZhbHVlKCksIGFjdGlvblJlZi52YWx1ZSgpLCBwcm9jZXNzQXJncywgZGVidWdLZXkpLmFwcGx5KHZvaWQgMCwgYXJndW1lbnRzKTsKICAgIH07CiAgfQoKICBmdW5jdGlvbiBtYWtlQ2xvc3VyZUFjdGlvbihjb250ZXh0LCB0YXJnZXQsIGFjdGlvbiwgcHJvY2Vzc0FyZ3MsIGRlYnVnS2V5KSB7CiAgICB2YXIgc2VsZjsKICAgIHZhciBmbjsKICAgIChmYWxzZSAmJiAhKGFjdGlvbiAhPT0gdW5kZWZpbmVkICYmIGFjdGlvbiAhPT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJBY3Rpb24gcGFzc2VkIGlzIG51bGwgb3IgdW5kZWZpbmVkIGluIChhY3Rpb24pIGZyb20gIiArIHRhcmdldCArICIuIiwgYWN0aW9uICE9PSB1bmRlZmluZWQgJiYgYWN0aW9uICE9PSBudWxsKSk7CgogICAgaWYgKHR5cGVvZiBhY3Rpb25bSU5WT0tFXSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICBzZWxmID0gYWN0aW9uOwogICAgICBmbiA9IGFjdGlvbltJTlZPS0VdOwogICAgfSBlbHNlIHsKICAgICAgdmFyIHR5cGVvZkFjdGlvbiA9IHR5cGVvZiBhY3Rpb247CgogICAgICBpZiAodHlwZW9mQWN0aW9uID09PSAnc3RyaW5nJykgewogICAgICAgIHNlbGYgPSB0YXJnZXQ7CiAgICAgICAgZm4gPSB0YXJnZXQuYWN0aW9ucyAmJiB0YXJnZXQuYWN0aW9uc1thY3Rpb25dOwogICAgICAgIChmYWxzZSAmJiAhKGZuKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkFuIGFjdGlvbiBuYW1lZCAnIiArIGFjdGlvbiArICInIHdhcyBub3QgZm91bmQgaW4gIiArIHRhcmdldCwgZm4pKTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2ZBY3Rpb24gPT09ICdmdW5jdGlvbicpIHsKICAgICAgICBzZWxmID0gY29udGV4dDsKICAgICAgICBmbiA9IGFjdGlvbjsKICAgICAgfSBlbHNlIHsKICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoCiAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQW4gYWN0aW9uIGNvdWxkIG5vdCBiZSBtYWRlIGZvciBgIiArIChkZWJ1Z0tleSB8fCBhY3Rpb24pICsgImAgaW4gIiArIHRhcmdldCArICIuIFBsZWFzZSBjb25maXJtIHRoYXQgeW91IGFyZSB1c2luZyBlaXRoZXIgYSBxdW90ZWQgYWN0aW9uIG5hbWUgKGkuZS4gYChhY3Rpb24gJyIgKyAoZGVidWdLZXkgfHwgJ215QWN0aW9uJykgKyAiJylgKSBvciBhIGZ1bmN0aW9uIGF2YWlsYWJsZSBpbiAiICsgdGFyZ2V0ICsgIi4iLCBmYWxzZSkpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkyID0gMDsgX2tleTIgPCBfbGVuOyBfa2V5MisrKSB7CiAgICAgICAgYXJnc1tfa2V5Ml0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICB9CgogICAgICB2YXIgcGF5bG9hZCA9IHsKICAgICAgICB0YXJnZXQ6IHNlbGYsCiAgICAgICAgYXJnczogYXJncywKICAgICAgICBsYWJlbDogJ0BnbGltbWVyL2Nsb3N1cmUtYWN0aW9uJwogICAgICB9OwogICAgICByZXR1cm4gKDAsIF9pbnN0cnVtZW50YXRpb24uZmxhZ2dlZEluc3RydW1lbnQpKCdpbnRlcmFjdGlvbi5lbWJlci1hY3Rpb24nLCBwYXlsb2FkLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIF9ydW5sb29wLmpvaW4uYXBwbHkodm9pZCAwLCBbc2VsZiwgZm5dLmNvbmNhdChwcm9jZXNzQXJncyhhcmdzKSkpOwogICAgICB9KTsKICAgIH07CiAgfQogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgICBVc2UgdGhlIGB7e2FycmF5fX1gIGhlbHBlciB0byBjcmVhdGUgYW4gYXJyYXkgdG8gcGFzcyBhcyBhbiBvcHRpb24gdG8geW91cgogICAgIGNvbXBvbmVudHMuCiAgCiAgICAgYGBgaGFuZGxlYmFycwogICAgIDxNeUNvbXBvbmVudCBAcGVvcGxlPXt7YXJyYXkKICAgICAgICdUb20gRGFkZScKICAgICAgICdZZWh1ZGEgS2F0eicKICAgICAgIHRoaXMubXlPdGhlclBlcnNvbn19CiAgICAgLz4KICAgICBgYGAKICAgICAgb3IKICAgICBgYGBoYW5kbGViYXJzCiAgICAge3tteS1jb21wb25lbnQgcGVvcGxlPShhcnJheQogICAgICAgJ1RvbSBEYWRlJwogICAgICAgJ1llaHVkYSBLYXR6JwogICAgICAgdGhpcy5teU90aGVyUGVyc29uKQogICAgIH19CiAgICAgYGBgCiAgCiAgICAgV291bGQgcmVzdWx0IGluIGFuIG9iamVjdCBzdWNoIGFzOgogIAogICAgIGBgYGpzCiAgICAgWydUb20gRGF0ZScsICdZZWh1ZGEgS2F0eicsIHRoaXMuZ2V0KCdteU90aGVyUGVyc29uJyldCiAgICAgYGBgCiAgCiAgICAgV2hlcmUgdGhlIDNyZCBpdGVtIGluIHRoZSBhcnJheSBpcyBib3VuZCB0byB1cGRhdGVzIG9mIHRoZSBgbXlPdGhlclBlcnNvbmAgcHJvcGVydHkuCiAgCiAgICAgQG1ldGhvZCBhcnJheQogICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgICBAcGFyYW0ge0FycmF5fSBvcHRpb25zCiAgICAgQHJldHVybiB7QXJyYXl9IEFycmF5CiAgICAgQHNpbmNlIDMuOC4wCiAgICAgQHB1YmxpYwogICAqLwoKCiAgZnVuY3Rpb24gYXJyYXkoX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gYXJncy5wb3NpdGlvbmFsLmNhcHR1cmUoKTsKICB9CgogIHZhciBpc0VtcHR5ID0gZnVuY3Rpb24gaXNFbXB0eSh2YWx1ZSQkMSkgewogICAgcmV0dXJuIHZhbHVlJCQxID09PSBudWxsIHx8IHZhbHVlJCQxID09PSB1bmRlZmluZWQgfHwgdHlwZW9mIHZhbHVlJCQxLnRvU3RyaW5nICE9PSAnZnVuY3Rpb24nOwogIH07CgogIHZhciBub3JtYWxpemVUZXh0VmFsdWUgPSBmdW5jdGlvbiBub3JtYWxpemVUZXh0VmFsdWUodmFsdWUkJDEpIHsKICAgIGlmIChpc0VtcHR5KHZhbHVlJCQxKSkgewogICAgICByZXR1cm4gJyc7CiAgICB9CgogICAgcmV0dXJuIFN0cmluZyh2YWx1ZSQkMSk7CiAgfTsKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBDb25jYXRlbmF0ZXMgdGhlIGdpdmVuIGFyZ3VtZW50cyBpbnRvIGEgc3RyaW5nLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7c29tZS1jb21wb25lbnQgbmFtZT0oY29uY2F0IGZpcnN0TmFtZSAiICIgbGFzdE5hbWUpfX0KICAKICAgIHt7ISB3b3VsZCBwYXNzIG5hbWU9IjxmaXJzdCBuYW1lIHZhbHVlPiA8bGFzdCBuYW1lIHZhbHVlPiIgdG8gdGhlIGNvbXBvbmVudH19CiAgICBgYGAKICAKICAgIG9yIGZvciBhbmdsZSBicmFja2V0IGludm9jYXRpb24sIHlvdSBhY3R1YWxseSBkb24ndCBuZWVkIGNvbmNhdCBhdCBhbGwuCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8U29tZUNvbXBvbmVudCBAbmFtZT0ie3tmaXJzdE5hbWV9fSB7e2xhc3ROYW1lfX0iIC8+CiAgICBgYGAKICAKICAgIEBwdWJsaWMKICAgIEBtZXRob2QgY29uY2F0CiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAc2luY2UgMS4xMy4wCiAgKi8KCgogIGZ1bmN0aW9uIGNvbmNhdChfcmVmMjcpIHsKICAgIHZhciBwb3NpdGlvbmFsID0gX3JlZjI3LnBvc2l0aW9uYWw7CiAgICByZXR1cm4gcG9zaXRpb25hbC52YWx1ZSgpLm1hcChub3JtYWxpemVUZXh0VmFsdWUpLmpvaW4oJycpOwogIH0KCiAgZnVuY3Rpb24gY29uY2F0JDEoX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gbmV3IEludGVybmFsSGVscGVyUmVmZXJlbmNlKGNvbmNhdCwgYXJncy5jYXB0dXJlKCkpOwogIH0KCiAgZnVuY3Rpb24gYnVpbGRVbnRvdWNoYWJsZVRoaXMoc291cmNlKSB7CiAgICB2YXIgY29udGV4dCA9IG51bGw7CgogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgJiYgX3V0aWxzLkhBU19OQVRJVkVfUFJPWFkpIHsKICAgICAgdmFyIGFzc2VydE9uUHJvcGVydHkgPSBmdW5jdGlvbiBhc3NlcnRPblByb3BlcnR5KHByb3BlcnR5KSB7CiAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGFjY2Vzc2VkIGB0aGlzLiIgKyBTdHJpbmcocHJvcGVydHkpICsgImAgZnJvbSBhIGZ1bmN0aW9uIHBhc3NlZCB0byB0aGUgIiArIHNvdXJjZSArICIsIGJ1dCB0aGUgZnVuY3Rpb24gaXRzZWxmIHdhcyBub3QgYm91bmQgdG8gYSB2YWxpZCBgdGhpc2AgY29udGV4dC4gQ29uc2lkZXIgdXBkYXRpbmcgdG8gdXNhZ2Ugb2YgYEBhY3Rpb25gLiIpKTsKICAgICAgfTsKCiAgICAgIGNvbnRleHQgPSBuZXcgUHJveHkoe30sIHsKICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldChfdGFyZ2V0LCBwcm9wZXJ0eSkgewogICAgICAgICAgYXNzZXJ0T25Qcm9wZXJ0eShwcm9wZXJ0eSk7CiAgICAgICAgfSwKICAgICAgICBzZXQ6IGZ1bmN0aW9uIHNldChfdGFyZ2V0LCBwcm9wZXJ0eSkgewogICAgICAgICAgYXNzZXJ0T25Qcm9wZXJ0eShwcm9wZXJ0eSk7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfSwKICAgICAgICBoYXM6IGZ1bmN0aW9uIGhhcyhfdGFyZ2V0LCBwcm9wZXJ0eSkgewogICAgICAgICAgYXNzZXJ0T25Qcm9wZXJ0eShwcm9wZXJ0eSk7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KCiAgICByZXR1cm4gY29udGV4dDsKICB9CgogIHZhciBjb250ZXh0ID0gYnVpbGRVbnRvdWNoYWJsZVRoaXMoJ2BmbmAgaGVscGVyJyk7CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgVGhlIGBmbmAgaGVscGVyIGFsbG93cyB5b3UgdG8gZW5zdXJlIGEgZnVuY3Rpb24gdGhhdCB5b3UgYXJlIHBhc3Npbmcgb2ZmCiAgICB0byBhbm90aGVyIGNvbXBvbmVudCwgaGVscGVyLCBvciBtb2RpZmllciBoYXMgYWNjZXNzIHRvIGFyZ3VtZW50cyB0aGF0IGFyZQogICAgYXZhaWxhYmxlIGluIHRoZSB0ZW1wbGF0ZS4KICAKICAgIEZvciBleGFtcGxlLCBpZiB5b3UgaGF2ZSBhbiBgZWFjaGAgaGVscGVyIGxvb3Bpbmcgb3ZlciBhIG51bWJlciBvZiBpdGVtcywgeW91CiAgICBtYXkgbmVlZCB0byBwYXNzIGEgZnVuY3Rpb24gdGhhdCBleHBlY3RzIHRvIHJlY2VpdmUgdGhlIGl0ZW0gYXMgYW4gYXJndW1lbnQKICAgIHRvIGEgY29tcG9uZW50IGludm9rZWQgd2l0aGluIHRoZSBsb29wLiBIZXJlJ3MgaG93IHlvdSBjb3VsZCB1c2UgdGhlIGBmbmAKICAgIGhlbHBlciB0byBwYXNzIGJvdGggdGhlIGZ1bmN0aW9uIGFuZCBpdHMgYXJndW1lbnRzIHRvZ2V0aGVyOgogIAogICAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvaXRlbXMtbGlzdGluZy5oYnMKICAgIHt7I2VhY2ggQGl0ZW1zIGFzIHxpdGVtfH19CiAgICAgIDxEaXNwbGF5SXRlbSBAaXRlbT1pdGVtIEBzZWxlY3Q9e3tmbiB0aGlzLmhhbmRsZVNlbGVjdGVkIGl0ZW19fSAvPgogICAge3svZWFjaH19CiAgICBgYGAKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL2l0ZW1zLWxpc3QuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGdsaW1tZXIvY29tcG9uZW50JzsKICAgIGltcG9ydCB7IGFjdGlvbiB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgY2xhc3MgSXRlbXNMaXN0IGV4dGVuZHMgQ29tcG9uZW50IHsKICAgICAgQGFjdGlvbgogICAgICBoYW5kbGVTZWxlY3RlZChpdGVtKSB7CiAgICAgICAgLy8gLi4uc25pcC4uLgogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIEluIHRoaXMgY2FzZSB0aGUgYGRpc3BsYXktaXRlbWAgY29tcG9uZW50IHdpbGwgcmVjZWl2ZSBhIG5vcm1hbCBmdW5jdGlvbgogICAgdGhhdCBpdCBjYW4gaW52b2tlLiBXaGVuIGl0IGludm9rZXMgdGhlIGZ1bmN0aW9uLCB0aGUgYGhhbmRsZVNlbGVjdGVkYAogICAgZnVuY3Rpb24gd2lsbCByZWNlaXZlIHRoZSBgaXRlbWAgYW5kIGFueSBhcmd1bWVudHMgcGFzc2VkLCB0aGFua3MgdG8gdGhlCiAgICBgZm5gIGhlbHBlci4KICAKICAgIExldCdzIHRha2UgbG9vayBhdCB3aGF0IHRoYXQgbWVhbnMgaW4gYSBjb3VwbGUgY2lyY3Vtc3RhbmNlczoKICAKICAgIC0gV2hlbiBpbnZva2VkIGFzIGB0aGlzLmFyZ3Muc2VsZWN0KClgIHRoZSBgaGFuZGxlU2VsZWN0ZWRgIGZ1bmN0aW9uIHdpbGwKICAgICAgcmVjZWl2ZSB0aGUgYGl0ZW1gIGZyb20gdGhlIGxvb3AgYXMgaXRzIGZpcnN0IGFuZCBvbmx5IGFyZ3VtZW50LgogICAgLSBXaGVuIGludm9rZWQgYXMgYHRoaXMuYXJncy5zZWxlY3QoJ2ZvbycpYCB0aGUgYGhhbmRsZVNlbGVjdGVkYCBmdW5jdGlvbgogICAgICB3aWxsIHJlY2VpdmUgdGhlIGBpdGVtYCBmcm9tIHRoZSBsb29wIGFzIGl0cyBmaXJzdCBhcmd1bWVudCBhbmQgdGhlCiAgICAgIHN0cmluZyBgJ2ZvbydgIGFzIGl0cyBzZWNvbmQgYXJndW1lbnQuCiAgCiAgICBJbiB0aGUgZXhhbXBsZSBhYm92ZSwgd2UgdXNlZCBgQGFjdGlvbmAgdG8gZW5zdXJlIHRoYXQgYGhhbmRsZVNlbGVjdGVkYCBpcwogICAgcHJvcGVybHkgYm91bmQgdG8gdGhlIGBpdGVtcy1saXN0YCwgYnV0IGxldCdzIGV4cGxvcmUgd2hhdCBoYXBwZW5zIGlmIHdlCiAgICBsZWZ0IG91dCBgQGFjdGlvbmA6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9pdGVtcy1saXN0LmpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BnbGltbWVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBjbGFzcyBJdGVtc0xpc3QgZXh0ZW5kcyBDb21wb25lbnQgewogICAgICBoYW5kbGVTZWxlY3RlZChpdGVtKSB7CiAgICAgICAgLy8gLi4uc25pcC4uLgogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIEluIHRoaXMgZXhhbXBsZSwgd2hlbiBgaGFuZGxlU2VsZWN0ZWRgIGlzIGludm9rZWQgaW5zaWRlIHRoZSBgZGlzcGxheS1pdGVtYAogICAgY29tcG9uZW50LCBpdCB3aWxsICoqbm90KiogaGF2ZSBhY2Nlc3MgdG8gdGhlIGNvbXBvbmVudCBpbnN0YW5jZS4gSW4gb3RoZXIKICAgIHdvcmRzLCBpdCB3aWxsIGhhdmUgbm8gYHRoaXNgIGNvbnRleHQsIHNvIHBsZWFzZSBtYWtlIHN1cmUgeW91ciBmdW5jdGlvbnMKICAgIGFyZSBib3VuZCAodmlhIGBAYWN0aW9uYCBvciBvdGhlciBtZWFucykgYmVmb3JlIHBhc3NpbmcgaW50byBgZm5gIQogIAogICAgU2VlIGFsc28gW3BhcnRpYWwgYXBwbGljYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BhcnRpYWxfYXBwbGljYXRpb24pLgogIAogICAgQG1ldGhvZCBmbgogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHB1YmxpYwogICAgQHNpbmNlIDMuMTEuMAogICovCgogIGZ1bmN0aW9uIGZuSGVscGVyKF9yZWYyOCkgewogICAgdmFyIHBvc2l0aW9uYWwgPSBfcmVmMjgucG9zaXRpb25hbDsKICAgIHZhciBjYWxsYmFja1JlZiA9IHBvc2l0aW9uYWwuYXQoMCk7CgogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgJiYgdHlwZW9mIGNhbGxiYWNrUmVmW0lOVk9LRV0gIT09ICdmdW5jdGlvbicpIHsKICAgICAgdmFyIGNhbGxiYWNrID0gY2FsbGJhY2tSZWYudmFsdWUoKTsKICAgICAgKGZhbHNlICYmICEodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBtdXN0IHBhc3MgYSBmdW5jdGlvbiBhcyB0aGUgYGZuYCBoZWxwZXJzIGZpcnN0IGFyZ3VtZW50LCB5b3UgcGFzc2VkICIgKyBjYWxsYmFjaywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICB9CgogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIF9wb3NpdGlvbmFsJHZhbHVlID0gcG9zaXRpb25hbC52YWx1ZSgpLAogICAgICAgICAgZm4gPSBfcG9zaXRpb25hbCR2YWx1ZVswXSwKICAgICAgICAgIGFyZ3MgPSBfcG9zaXRpb25hbCR2YWx1ZS5zbGljZSgxKTsKCiAgICAgIGZvciAodmFyIF9sZW4yID0gYXJndW1lbnRzLmxlbmd0aCwgaW52b2NhdGlvbkFyZ3MgPSBuZXcgQXJyYXkoX2xlbjIpLCBfa2V5MyA9IDA7IF9rZXkzIDwgX2xlbjI7IF9rZXkzKyspIHsKICAgICAgICBpbnZvY2F0aW9uQXJnc1tfa2V5M10gPSBhcmd1bWVudHNbX2tleTNdOwogICAgICB9CgogICAgICBpZiAodHlwZW9mIGNhbGxiYWNrUmVmW0lOVk9LRV0gPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAvLyByZWZlcmVuY2VzIHdpdGggdGhlIElOVk9LRSBzeW1ib2wgZXhwZWN0IHRoZSBmdW5jdGlvbiBiZWhpbmQKICAgICAgICAvLyB0aGUgc3ltYm9sIHRvIGJlIGJvdW5kIHRvIHRoZSByZWZlcmVuY2UKICAgICAgICByZXR1cm4gY2FsbGJhY2tSZWZbSU5WT0tFXS5hcHBseShjYWxsYmFja1JlZiwgYXJncy5jb25jYXQoaW52b2NhdGlvbkFyZ3MpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gZm5bJ2NhbGwnXS5hcHBseShmbiwgW2NvbnRleHRdLmNvbmNhdChhcmdzLCBpbnZvY2F0aW9uQXJncykpOwogICAgICB9CiAgICB9OwogIH0KCiAgZnVuY3Rpb24gZm4oX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gbmV3IEludGVybmFsSGVscGVyUmVmZXJlbmNlKGZuSGVscGVyLCBhcmdzLmNhcHR1cmUoKSk7CiAgfQogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIER5bmFtaWNhbGx5IGxvb2sgdXAgYSBwcm9wZXJ0eSBvbiBhbiBvYmplY3QuIFRoZSBzZWNvbmQgYXJndW1lbnQgdG8gYHt7Z2V0fX1gCiAgICBzaG91bGQgaGF2ZSBhIHN0cmluZyB2YWx1ZSwgYWx0aG91Z2ggaXQgY2FuIGJlIGJvdW5kLgogIAogICAgRm9yIGV4YW1wbGUsIHRoZXNlIHR3byB1c2FnZXMgYXJlIGVxdWl2YWxlbnQ6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e3BlcnNvbi5oZWlnaHR9fQogICAge3tnZXQgcGVyc29uICJoZWlnaHQifX0KICAgIGBgYAogIAogICAgSWYgdGhlcmUgd2VyZSBzZXZlcmFsIGZhY3RzIGFib3V0IGEgcGVyc29uLCB0aGUgYHt7Z2V0fX1gIGhlbHBlciBjYW4gZHluYW1pY2FsbHkKICAgIHBpY2sgb25lOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3tnZXQgcGVyc29uIGZhY3ROYW1lfX0KICAgIGBgYAogIAogICAgRm9yIGEgbW9yZSBjb21wbGV4IGV4YW1wbGUsIHRoaXMgdGVtcGxhdGUgd291bGQgYWxsb3cgdGhlIHVzZXIgdG8gc3dpdGNoCiAgICBiZXR3ZWVuIHNob3dpbmcgdGhlIHVzZXIncyBoZWlnaHQgYW5kIHdlaWdodCB3aXRoIGEgY2xpY2s6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e2dldCBwZXJzb24gZmFjdE5hbWV9fQogICAgPGJ1dHRvbiB7e2FjdGlvbiAoZm4gKG11dCBmYWN0TmFtZSkpICJoZWlnaHQifX0+U2hvdyBoZWlnaHQ8L2J1dHRvbj4KICAgIDxidXR0b24ge3thY3Rpb24gKGZuIChtdXQgZmFjdE5hbWUpKSAid2VpZ2h0In19PlNob3cgd2VpZ2h0PC9idXR0b24+CiAgICBgYGAKICAKICAgIFRoZSBge3tnZXR9fWAgaGVscGVyIGNhbiBhbHNvIHJlc3BlY3QgbXV0YWJsZSB2YWx1ZXMgaXRzZWxmLiBGb3IgZXhhbXBsZToKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7aW5wdXQgdmFsdWU9KG11dCAoZ2V0IHBlcnNvbiBmYWN0TmFtZSkpIHR5cGU9InRleHQifX0KICAgIDxidXR0b24ge3thY3Rpb24gKGZuIChtdXQgZmFjdE5hbWUpKSAiaGVpZ2h0In19PlNob3cgaGVpZ2h0PC9idXR0b24+CiAgICA8YnV0dG9uIHt7YWN0aW9uIChmbiAobXV0IGZhY3ROYW1lKSkgIndlaWdodCJ9fT5TaG93IHdlaWdodDwvYnV0dG9uPgogICAgYGBgCiAgCiAgICBXb3VsZCBhbGxvdyB0aGUgdXNlciB0byBzd2FwIHdoYXQgZmFjdCBpcyBiZWluZyBkaXNwbGF5ZWQsIGFuZCBhbHNvIGVkaXQKICAgIHRoYXQgZmFjdCB2aWEgYSB0d28td2F5IG11dGFibGUgYmluZGluZy4KICAKICAgIEBwdWJsaWMKICAgIEBtZXRob2QgZ2V0CiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAc2luY2UgMi4xLjAKICAgKi8KCgogIGZ1bmN0aW9uIGdldCQxKF92bSwgYXJncykgewogICAgcmV0dXJuIEdldEhlbHBlclJlZmVyZW5jZS5jcmVhdGUoYXJncy5wb3NpdGlvbmFsLmF0KDApLCBhcmdzLnBvc2l0aW9uYWwuYXQoMSkpOwogIH0KCiAgZnVuY3Rpb24gcmVmZXJlbmNlRnJvbVBhdGgoc291cmNlLCBwYXRoKSB7CiAgICB2YXIgaW5uZXJSZWZlcmVuY2U7CgogICAgaWYgKHBhdGggPT09IHVuZGVmaW5lZCB8fCBwYXRoID09PSBudWxsIHx8IHBhdGggPT09ICcnKSB7CiAgICAgIGlubmVyUmVmZXJlbmNlID0gX3J1bnRpbWUyLk5VTExfUkVGRVJFTkNFOwogICAgfSBlbHNlIGlmICh0eXBlb2YgcGF0aCA9PT0gJ3N0cmluZycgJiYgcGF0aC5pbmRleE9mKCcuJykgPiAtMSkgewogICAgICBpbm5lclJlZmVyZW5jZSA9IHJlZmVyZW5jZUZyb21QYXJ0cyhzb3VyY2UsIHBhdGguc3BsaXQoJy4nKSk7CiAgICB9IGVsc2UgewogICAgICBpbm5lclJlZmVyZW5jZSA9IHNvdXJjZS5nZXQocGF0aCk7CiAgICB9CgogICAgcmV0dXJuIGlubmVyUmVmZXJlbmNlOwogIH0KCiAgdmFyIEdldEhlbHBlclJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ2FjaGVkUmVmZXJlbmNlJDYpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShHZXRIZWxwZXJSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UkNik7CgogICAgR2V0SGVscGVyUmVmZXJlbmNlLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShzb3VyY2VSZWZlcmVuY2UsIHBhdGhSZWZlcmVuY2UpIHsKICAgICAgaWYgKCgwLCBfcmVmZXJlbmNlLmlzQ29uc3QpKHBhdGhSZWZlcmVuY2UpKSB7CiAgICAgICAgdmFyIHBhdGggPSBwYXRoUmVmZXJlbmNlLnZhbHVlKCk7CiAgICAgICAgcmV0dXJuIHJlZmVyZW5jZUZyb21QYXRoKHNvdXJjZVJlZmVyZW5jZSwgcGF0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyBHZXRIZWxwZXJSZWZlcmVuY2Uoc291cmNlUmVmZXJlbmNlLCBwYXRoUmVmZXJlbmNlKTsKICAgICAgfQogICAgfTsKCiAgICBmdW5jdGlvbiBHZXRIZWxwZXJSZWZlcmVuY2Uoc291cmNlUmVmZXJlbmNlLCBwYXRoUmVmZXJlbmNlKSB7CiAgICAgIHZhciBfdGhpczIyOwoKICAgICAgX3RoaXMyMiA9IF9DYWNoZWRSZWZlcmVuY2UkNi5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMjIuc291cmNlUmVmZXJlbmNlID0gc291cmNlUmVmZXJlbmNlOwogICAgICBfdGhpczIyLnBhdGhSZWZlcmVuY2UgPSBwYXRoUmVmZXJlbmNlOwogICAgICBfdGhpczIyLmxhc3RQYXRoID0gbnVsbDsKICAgICAgX3RoaXMyMi5pbm5lclJlZmVyZW5jZSA9IF9ydW50aW1lMi5OVUxMX1JFRkVSRU5DRTsKICAgICAgdmFyIGlubmVyVGFnID0gX3RoaXMyMi5pbm5lclRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgX3RoaXMyMi50YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShbc291cmNlUmVmZXJlbmNlLnRhZywgcGF0aFJlZmVyZW5jZS50YWcsIGlubmVyVGFnXSk7CiAgICAgIHJldHVybiBfdGhpczIyOwogICAgfQoKICAgIHZhciBfcHJvdG81MyA9IEdldEhlbHBlclJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNTMuY29tcHV0ZSA9IGZ1bmN0aW9uIGNvbXB1dGUoKSB7CiAgICAgIHZhciBsYXN0UGF0aCA9IHRoaXMubGFzdFBhdGgsCiAgICAgICAgICBpbm5lclJlZmVyZW5jZSA9IHRoaXMuaW5uZXJSZWZlcmVuY2UsCiAgICAgICAgICBpbm5lclRhZyA9IHRoaXMuaW5uZXJUYWc7CiAgICAgIHZhciBwYXRoID0gdGhpcy5wYXRoUmVmZXJlbmNlLnZhbHVlKCk7CgogICAgICBpZiAocGF0aCAhPT0gbGFzdFBhdGgpIHsKICAgICAgICBpbm5lclJlZmVyZW5jZSA9IHJlZmVyZW5jZUZyb21QYXRoKHRoaXMuc291cmNlUmVmZXJlbmNlLCBwYXRoKTsKICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKGlubmVyVGFnLCBpbm5lclJlZmVyZW5jZS50YWcpOwogICAgICAgIHRoaXMuaW5uZXJSZWZlcmVuY2UgPSBpbm5lclJlZmVyZW5jZTsKICAgICAgICB0aGlzLmxhc3RQYXRoID0gcGF0aDsKICAgICAgfQoKICAgICAgcmV0dXJuIGlubmVyUmVmZXJlbmNlLnZhbHVlKCk7CiAgICB9OwoKICAgIF9wcm90bzUzW1VQREFURV0gPSBmdW5jdGlvbiAodmFsdWUkJDEpIHsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMuc291cmNlUmVmZXJlbmNlLnZhbHVlKCksIHRoaXMucGF0aFJlZmVyZW5jZS52YWx1ZSgpLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIHJldHVybiBHZXRIZWxwZXJSZWZlcmVuY2U7CiAgfShDYWNoZWRSZWZlcmVuY2UkMSk7CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgIFVzZSB0aGUgYHt7aGFzaH19YCBoZWxwZXIgdG8gY3JlYXRlIGEgaGFzaCB0byBwYXNzIGFzIGFuIG9wdGlvbiB0byB5b3VyCiAgICAgY29tcG9uZW50cy4gVGhpcyBpcyBzcGVjaWFsbHkgdXNlZnVsIGZvciBjb250ZXh0dWFsIGNvbXBvbmVudHMgd2hlcmUgeW91IGNhbgogICAgIGp1c3QgeWllbGQgYSBoYXNoOgogIAogICAgIGBgYGhhbmRsZWJhcnMKICAgICB7e3lpZWxkIChoYXNoCiAgICAgICAgbmFtZT0nU2FyYWgnCiAgICAgICAgdGl0bGU9b2ZmaWNlCiAgICAgKX19CiAgICAgYGBgCiAgCiAgICAgV291bGQgcmVzdWx0IGluIGFuIG9iamVjdCBzdWNoIGFzOgogIAogICAgIGBgYGpzCiAgICAgeyBuYW1lOiAnU2FyYWgnLCB0aXRsZTogdGhpcy5nZXQoJ29mZmljZScpIH0KICAgICBgYGAKICAKICAgICBXaGVyZSB0aGUgYHRpdGxlYCBpcyBib3VuZCB0byB1cGRhdGVzIG9mIHRoZSBgb2ZmaWNlYCBwcm9wZXJ0eS4KICAKICAgICBOb3RlIHRoYXQgdGhlIGhhc2ggaXMgYW4gZW1wdHkgb2JqZWN0IHdpdGggbm8gcHJvdG90eXBlIGNoYWluLCB0aGVyZWZvcmUKICAgICBjb21tb24gbWV0aG9kcyBsaWtlIGB0b1N0cmluZ2AgYXJlIG5vdCBhdmFpbGFibGUgaW4gdGhlIHJlc3VsdGluZyBoYXNoLgogICAgIElmIHlvdSBuZWVkIHRvIHVzZSBzdWNoIGEgbWV0aG9kLCB5b3UgY2FuIHVzZSB0aGUgYGNhbGxgIG9yIGBhcHBseWAKICAgICBhcHByb2FjaDoKICAKICAgICBgYGBqcwogICAgIGZ1bmN0aW9uIHRvU3RyaW5nKG9iaikgewogICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuYXBwbHkob2JqKTsKICAgICB9CiAgICAgYGBgCiAgCiAgICAgQG1ldGhvZCBoYXNoCiAgICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgQHJldHVybiB7T2JqZWN0fSBIYXNoCiAgICAgQHNpbmNlIDIuMy4wCiAgICAgQHB1YmxpYwogICAqLwoKCiAgZnVuY3Rpb24gaGFzaChfdm0sIGFyZ3MpIHsKICAgIHJldHVybiBhcmdzLm5hbWVkLmNhcHR1cmUoKTsKICB9CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgoKICB2YXIgQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NhY2hlZFJlZmVyZW5jZSQ3KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UkNyk7CgogICAgQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKF9jb25kUmVmLCB0cnV0aHlSZWYsIGZhbHN5UmVmKSB7CiAgICAgIHZhciBjb25kUmVmID0gQ29uZGl0aW9uYWxSZWZlcmVuY2UkMS5jcmVhdGUoX2NvbmRSZWYpOwoKICAgICAgaWYgKCgwLCBfcmVmZXJlbmNlLmlzQ29uc3QpKGNvbmRSZWYpKSB7CiAgICAgICAgcmV0dXJuIGNvbmRSZWYudmFsdWUoKSA/IHRydXRoeVJlZiA6IGZhbHN5UmVmOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBuZXcgQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UoY29uZFJlZiwgdHJ1dGh5UmVmLCBmYWxzeVJlZik7CiAgICAgIH0KICAgIH07CgogICAgZnVuY3Rpb24gQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UoY29uZCwgdHJ1dGh5LCBmYWxzeSkgewogICAgICB2YXIgX3RoaXMyMzsKCiAgICAgIF90aGlzMjMgPSBfQ2FjaGVkUmVmZXJlbmNlJDcuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczIzLmJyYW5jaFRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgX3RoaXMyMy50YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShbY29uZC50YWcsIF90aGlzMjMuYnJhbmNoVGFnXSk7CiAgICAgIF90aGlzMjMuY29uZCA9IGNvbmQ7CiAgICAgIF90aGlzMjMudHJ1dGh5ID0gdHJ1dGh5OwogICAgICBfdGhpczIzLmZhbHN5ID0gZmFsc3k7CiAgICAgIHJldHVybiBfdGhpczIzOwogICAgfQoKICAgIHZhciBfcHJvdG81NCA9IENvbmRpdGlvbmFsSGVscGVyUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG81NC5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgdmFyIGJyYW5jaCA9IHRoaXMuY29uZC52YWx1ZSgpID8gdGhpcy50cnV0aHkgOiB0aGlzLmZhbHN5OwogICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHRoaXMuYnJhbmNoVGFnLCBicmFuY2gudGFnKTsKICAgICAgcmV0dXJuIGJyYW5jaC52YWx1ZSgpOwogICAgfTsKCiAgICByZXR1cm4gQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2U7CiAgfShDYWNoZWRSZWZlcmVuY2UkMSk7CiAgLyoqCiAgICBUaGUgYGlmYCBoZWxwZXIgYWxsb3dzIHlvdSB0byBjb25kaXRpb25hbGx5IHJlbmRlciBvbmUgb2YgdHdvIGJyYW5jaGVzLAogICAgZGVwZW5kaW5nIG9uIHRoZSAidHJ1dGhpbmVzcyIgb2YgYSBwcm9wZXJ0eS4KICAgIEZvciBleGFtcGxlIHRoZSBmb2xsb3dpbmcgdmFsdWVzIGFyZSBhbGwgZmFsc2V5OiBgZmFsc2VgLCBgdW5kZWZpbmVkYCwgYG51bGxgLCBgIiJgLCBgMGAsIGBOYU5gIG9yIGFuIGVtcHR5IGFycmF5LgogIAogICAgVGhpcyBoZWxwZXIgaGFzIHR3byBmb3JtcywgYmxvY2sgYW5kIGlubGluZS4KICAKICAgICMjIEJsb2NrIGZvcm0KICAKICAgIFlvdSBjYW4gdXNlIHRoZSBibG9jayBmb3JtIG9mIGBpZmAgdG8gY29uZGl0aW9uYWxseSByZW5kZXIgYSBzZWN0aW9uIG9mIHRoZSB0ZW1wbGF0ZS4KICAKICAgIFRvIHVzZSBpdCwgcGFzcyB0aGUgY29uZGl0aW9uYWwgdmFsdWUgdG8gdGhlIGBpZmAgaGVscGVyLAogICAgdXNpbmcgdGhlIGJsb2NrIGZvcm0gdG8gd3JhcCB0aGUgc2VjdGlvbiBvZiB0ZW1wbGF0ZSB5b3Ugd2FudCB0byBjb25kaXRpb25hbGx5IHJlbmRlci4KICAgIExpa2Ugc286CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7eyEgd2lsbCBub3QgcmVuZGVyIGlmIGZvbyBpcyBmYWxzZXl9fQogICAge3sjaWYgZm9vfX0KICAgICAgV2VsY29tZSB0byB0aGUge3tmb28uYmFyfX0KICAgIHt7L2lmfX0KICAgIGBgYAogIAogICAgWW91IGNhbiBhbHNvIHNwZWNpZnkgYSB0ZW1wbGF0ZSB0byBzaG93IGlmIHRoZSBwcm9wZXJ0eSBpcyBmYWxzZXkgYnkgdXNpbmcKICAgIHRoZSBgZWxzZWAgaGVscGVyLgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3shIGlzIGl0IHJhaW5pbmcgb3V0c2lkZT99fQogICAge3sjaWYgaXNSYWluaW5nfX0KICAgICAgWWVzLCBncmFiIGFuIHVtYnJlbGxhIQogICAge3tlbHNlfX0KICAgICAgTm8sIGl0J3MgbG92ZWx5IG91dHNpZGUhCiAgICB7ey9pZn19CiAgICBgYGAKICAKICAgIFlvdSBhcmUgYWxzbyBhYmxlIHRvIGNvbWJpbmUgYGVsc2VgIGFuZCBgaWZgIGhlbHBlcnMgdG8gY3JlYXRlIG1vcmUgY29tcGxleAogICAgY29uZGl0aW9uYWwgbG9naWMuCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7eyNpZiBpc01vcm5pbmd9fQogICAgICBHb29kIG1vcm5pbmcKICAgIHt7ZWxzZSBpZiBpc0FmdGVybm9vbn19CiAgICAgIEdvb2QgYWZ0ZXJub29uCiAgICB7e2Vsc2V9fQogICAgICBHb29kIG5pZ2h0CiAgICB7ey9pZn19CiAgICBgYGAKICAKICAgICMjIElubGluZSBmb3JtCiAgCiAgICBUaGUgaW5saW5lIGBpZmAgaGVscGVyIGNvbmRpdGlvbmFsbHkgcmVuZGVycyBhIHNpbmdsZSBwcm9wZXJ0eSBvciBzdHJpbmcuCiAgCiAgICBJbiB0aGlzIGZvcm0sIHRoZSBgaWZgIGhlbHBlciByZWNlaXZlcyB0aHJlZSBhcmd1bWVudHMsIHRoZSBjb25kaXRpb25hbCB2YWx1ZSwKICAgIHRoZSB2YWx1ZSB0byByZW5kZXIgd2hlbiB0cnV0aHksIGFuZCB0aGUgdmFsdWUgdG8gcmVuZGVyIHdoZW4gZmFsc2V5LgogIAogICAgRm9yIGV4YW1wbGUsIGlmIGB1c2VMb25nR3JlZXRpbmdgIGlzIHRydXRoeSwgdGhlIGZvbGxvd2luZzoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7aWYgdXNlTG9uZ0dyZWV0aW5nICJIZWxsbyIgIkhpIn19IEFsZXgKICAgIGBgYAogIAogICAgV2lsbCByZW5kZXI6CiAgCiAgICBgYGBodG1sCiAgICBIZWxsbyBBbGV4CiAgICBgYGAKICAKICAgICMjIyBOZXN0ZWQgYGlmYAogIAogICAgWW91IGNhbiB1c2UgdGhlIGBpZmAgaGVscGVyIGluc2lkZSBhbm90aGVyIGhlbHBlciBhcyBhIG5lc3RlZCBoZWxwZXI6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8U29tZUNvbXBvbmVudCBAaGVpZ2h0PXt7aWYgaXNCaWcgIjEwMCIgIjEwIn19IC8+CiAgICBgYGAKICAKICAgIG9yCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e3NvbWUtY29tcG9uZW50IGhlaWdodD0oaWYgaXNCaWcgIjEwMCIgIjEwIil9fQogICAgYGBgCiAgCiAgICBPbmUgZGV0YWlsIHRvIGtlZXAgaW4gbWluZCBpcyB0aGF0IGJvdGggYnJhbmNoZXMgb2YgdGhlIGBpZmAgaGVscGVyIHdpbGwgYmUgZXZhbHVhdGVkLAogICAgc28gaWYgeW91IGhhdmUgYHt7aWYgY29uZGl0aW9uICJmb28iIChleHBlbnNpdmUtb3BlcmF0aW9uICJiYXIiKWAsCiAgICBgZXhwZW5zaXZlLW9wZXJhdGlvbmAgd2lsbCBhbHdheXMgY2FsY3VsYXRlLgogIAogICAgQG1ldGhvZCBpZgogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpbmxpbmVJZihfdm0sIF9yZWYyOSkgewogICAgdmFyIHBvc2l0aW9uYWwgPSBfcmVmMjkucG9zaXRpb25hbDsKICAgIChmYWxzZSAmJiAhKHBvc2l0aW9uYWwubGVuZ3RoID09PSAzIHx8IHBvc2l0aW9uYWwubGVuZ3RoID09PSAyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBpbmxpbmUgZm9ybSBvZiB0aGUgYGlmYCBoZWxwZXIgZXhwZWN0cyB0d28gb3IgdGhyZWUgYXJndW1lbnRzLCBlLmcuICcgKyAnYHt7aWYgdHJpYWxFeHBpcmVkICJFeHBpcmVkIiBleHBpcnlEYXRlfX1gLicsIHBvc2l0aW9uYWwubGVuZ3RoID09PSAzIHx8IHBvc2l0aW9uYWwubGVuZ3RoID09PSAyKSk7CiAgICByZXR1cm4gQ29uZGl0aW9uYWxIZWxwZXJSZWZlcmVuY2UuY3JlYXRlKHBvc2l0aW9uYWwuYXQoMCksIHBvc2l0aW9uYWwuYXQoMSksIHBvc2l0aW9uYWwuYXQoMikpOwogIH0KICAvKioKICAgIFRoZSBgdW5sZXNzYCBoZWxwZXIgaXMgdGhlIGludmVyc2Ugb2YgdGhlIGBpZmAgaGVscGVyLiBJdCBkaXNwbGF5cyBpZiBhIHZhbHVlCiAgICBpcyBmYWxzZXkgKCJub3QgdHJ1ZSIgb3IgImlzIGZhbHNlIikuIEV4YW1wbGUgdmFsdWVzIHRoYXQgd2lsbCBkaXNwbGF5IHdpdGgKICAgIGB1bmxlc3NgOiBgZmFsc2VgLCBgdW5kZWZpbmVkYCwgYG51bGxgLCBgIiJgLCBgMGAsIGBOYU5gIG9yIGFuIGVtcHR5IGFycmF5LgogIAogICAgIyMgSW5saW5lIGZvcm0KICAKICAgIFRoZSBpbmxpbmUgYHVubGVzc2AgaGVscGVyIGNvbmRpdGlvbmFsbHkgcmVuZGVycyBhIHNpbmdsZSBwcm9wZXJ0eSBvciBzdHJpbmcuCiAgICBUaGlzIGhlbHBlciBhY3RzIGxpa2UgYSB0ZXJuYXJ5IG9wZXJhdG9yLiBJZiB0aGUgZmlyc3QgcHJvcGVydHkgaXMgZmFsc3ksCiAgICB0aGUgc2Vjb25kIGFyZ3VtZW50IHdpbGwgYmUgZGlzcGxheWVkLCBvdGhlcndpc2UsIHRoZSB0aGlyZCBhcmd1bWVudCB3aWxsIGJlCiAgICBkaXNwbGF5ZWQKICAKICAgIEZvciBleGFtcGxlLCBpZiBgdXNlTG9uZ0dyZWV0aW5nYCBpcyBmYWxzZSBiZWxvdzoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7dW5sZXNzIHVzZUxvbmdHcmVldGluZyAiSGkiICJIZWxsbyJ9fSBCZW4KICAgIGBgYAogIAogICAgVGhlbiBpdCB3aWxsIGRpc3BsYXk6CiAgCiAgICBgYGBodG1sCiAgICBIaQogICAgYGBgCiAgCiAgICBZb3UgY2FuIHVzZSB0aGUgYHVubGVzc2AgaGVscGVyIGluc2lkZSBhbm90aGVyIGhlbHBlciBhcyBhIHN1YmV4cHJlc3Npb24uCiAgICBJZiBpc0JpZyBpcyBub3QgdHJ1ZSwgaXQgd2lsbCBzZXQgdGhlIGhlaWdodCB0byAxMDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7ISBJZiBpc0JpZyBpcyBub3QgdHJ1ZSwgaXQgd2lsbCBzZXQgdGhlIGhlaWdodCB0byAxMC59fQogICAgPFNvbWVDb21wb25lbnQgQGhlaWdodD17e3VubGVzcyBpc0JpZyAiMTAiICIxMDAifX0gLz4KICAgIGBgYAogIAogICAgb3IKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7c29tZS1jb21wb25lbnQgaGVpZ2h0PSh1bmxlc3MgaXNCaWcgIjEwIiAiMTAwIil9fQogICAgYGBgCiAgCiAgICAjIyBCbG9jayBmb3JtCiAgCiAgICBMaWtlIHRoZSBgaWZgIGhlbHBlciwgYHVubGVzc2AgaGVscGVyIGFsc28gaGFzIGEgYmxvY2sgZm9ybS4KICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7ISBJZiBncmVldGluZ3MgYXJlIGZvdW5kLCB0aGUgdGV4dCBiZWxvdyB3aWxsIG5vdCByZW5kZXIufX0KICAgIHt7I3VubGVzcyBncmVldGluZ3N9fQogICAgICBObyBncmVldGluZ3Mgd2VyZSBmb3VuZC4gV2h5IG5vdCBzZXQgb25lPwogICAge3svdW5sZXNzfX0KICAgIGBgYAogIAogICAgWW91IGNhbiBhbHNvIHVzZSBhbiBgZWxzZWAgaGVscGVyIHdpdGggdGhlIGB1bmxlc3NgIGJsb2NrLiBUaGUKICAgIGBlbHNlYCB3aWxsIGRpc3BsYXkgaWYgdGhlIHZhbHVlIGlzIHRydXRoeS4KICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7ISBJcyB0aGUgdXNlciBsb2dnZWQgaW4/fX0KICAgIHt7I3VubGVzcyB1c2VyRGF0YX19CiAgICAgIFBsZWFzZSBsb2dpbi4KICAgIHt7ZWxzZX19CiAgICAgIFdlbGNvbWUgYmFjayEKICAgIHt7L3VubGVzc319CiAgICBgYGAKICAKICAgIElmIGB1c2VyRGF0YWAgaXMgZmFsc2UsIHVuZGVmaW5lZCwgbnVsbCwgb3IgZW1wdHkgaW4gdGhlIGFib3ZlIGV4YW1wbGUsCiAgICB0aGVuIGl0IHdpbGwgcmVuZGVyOgogIAogICAgYGBgaHRtbAogICAgUGxlYXNlIGxvZ2luLgogICAgYGBgCiAgCiAgICBAbWV0aG9kIHVubGVzcwogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpbmxpbmVVbmxlc3MoX3ZtLCBfcmVmMzApIHsKICAgIHZhciBwb3NpdGlvbmFsID0gX3JlZjMwLnBvc2l0aW9uYWw7CiAgICAoZmFsc2UgJiYgIShwb3NpdGlvbmFsLmxlbmd0aCA9PT0gMyB8fCBwb3NpdGlvbmFsLmxlbmd0aCA9PT0gMikgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgaW5saW5lIGZvcm0gb2YgdGhlIGB1bmxlc3NgIGhlbHBlciBleHBlY3RzIHR3byBvciB0aHJlZSBhcmd1bWVudHMsIGUuZy4gJyArICdge3t1bmxlc3MgaXNGaXJzdExvZ2luICJXZWxjb21lIGJhY2shIn19YC4nLCBwb3NpdGlvbmFsLmxlbmd0aCA9PT0gMyB8fCBwb3NpdGlvbmFsLmxlbmd0aCA9PT0gMikpOwogICAgcmV0dXJuIENvbmRpdGlvbmFsSGVscGVyUmVmZXJlbmNlLmNyZWF0ZShwb3NpdGlvbmFsLmF0KDApLCBwb3NpdGlvbmFsLmF0KDIpLCBwb3NpdGlvbmFsLmF0KDEpKTsKICB9CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgYGxvZ2AgYWxsb3dzIHlvdSB0byBvdXRwdXQgdGhlIHZhbHVlIG9mIHZhcmlhYmxlcyBpbiB0aGUgY3VycmVudCByZW5kZXJpbmcKICAgIGNvbnRleHQuIGBsb2dgIGFsc28gYWNjZXB0cyBwcmltaXRpdmUgdHlwZXMgc3VjaCBhcyBzdHJpbmdzIG9yIG51bWJlcnMuCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e2xvZyAibXlWYXJpYWJsZToiIG15VmFyaWFibGUgfX0KICAgIGBgYAogIAogICAgQG1ldGhvZCBsb2cKICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwYXJhbSB7QXJyYXl9IHBhcmFtcwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBsb2coX3JlZjMxKSB7CiAgICB2YXIgX2NvbnNvbGU7CgogICAgdmFyIHBvc2l0aW9uYWwgPSBfcmVmMzEucG9zaXRpb25hbDsKCiAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovCiAgICAoX2NvbnNvbGUgPSBjb25zb2xlKS5sb2cuYXBwbHkoX2NvbnNvbGUsIHBvc2l0aW9uYWwudmFsdWUoKSk7CiAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWNvbnNvbGUgKi8KCiAgfQoKICBmdW5jdGlvbiBsb2ckMShfdm0sIGFyZ3MpIHsKICAgIHJldHVybiBuZXcgSW50ZXJuYWxIZWxwZXJSZWZlcmVuY2UobG9nLCBhcmdzLmNhcHR1cmUoKSk7CiAgfQogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIFRoZSBgbXV0YCBoZWxwZXIgbGV0cyB5b3UgX19jbGVhcmx5IHNwZWNpZnlfXyB0aGF0IGEgY2hpbGQgYENvbXBvbmVudGAgY2FuIHVwZGF0ZSB0aGUKICAgIChtdXRhYmxlKSB2YWx1ZSBwYXNzZWQgdG8gaXQsIHdoaWNoIHdpbGwgX19jaGFuZ2UgdGhlIHZhbHVlIG9mIHRoZSBwYXJlbnQgY29tcG9uZW50X18uCiAgCiAgICBUbyBzcGVjaWZ5IHRoYXQgYSBwYXJhbWV0ZXIgaXMgbXV0YWJsZSwgd2hlbiBpbnZva2luZyB0aGUgY2hpbGQgYENvbXBvbmVudGA6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8TXlDaGlsZCBAY2hpbGRDbGlja0NvdW50PXt7Zm4gKG11dCB0b3RhbENsaWNrcyl9fSAvPgogICAgYGBgCiAgCiAgICAgb3IKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7bXktY2hpbGQgY2hpbGRDbGlja0NvdW50PShtdXQgdG90YWxDbGlja3MpfX0KICAgIGBgYAogIAogICAgVGhlIGNoaWxkIGBDb21wb25lbnRgIGNhbiB0aGVuIG1vZGlmeSB0aGUgcGFyZW50J3MgdmFsdWUganVzdCBieSBtb2RpZnlpbmcgaXRzIG93bgogICAgcHJvcGVydHk6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICAvLyBteS1jaGlsZC5qcwogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGNsaWNrKCkgewogICAgICAgIHRoaXMuaW5jcmVtZW50UHJvcGVydHkoJ2NoaWxkQ2xpY2tDb3VudCcpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgTm90ZSB0aGF0IGZvciBjdXJseSBjb21wb25lbnRzIChge3tteS1jb21wb25lbnR9fWApIHRoZSBiaW5kaW5ncyBhcmUgYWxyZWFkeSBtdXRhYmxlLAogICAgbWFraW5nIHRoZSBgbXV0YCB1bm5lY2Vzc2FyeS4KICAKICAgIEFkZGl0aW9uYWxseSwgdGhlIGBtdXRgIGhlbHBlciBjYW4gYmUgY29tYmluZWQgd2l0aCB0aGUgYGZuYCBoZWxwZXIgdG8KICAgIG11dGF0ZSBhIHZhbHVlLiBGb3IgZXhhbXBsZToKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIDxNeUNoaWxkIEBjaGlsZENsaWNrQ291bnQ9e3t0aGlzLnRvdGFsQ2xpY2tzfX0gQGNsaWNrLWNvdW50LWNoYW5nZT17e2ZuIChtdXQgdG90YWxDbGlja3MpKX19IC8+CiAgICBgYGAKICAKICAgIG9yCiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e215LWNoaWxkIGNoaWxkQ2xpY2tDb3VudD10b3RhbENsaWNrcyBjbGljay1jb3VudC1jaGFuZ2U9KGZuIChtdXQgdG90YWxDbGlja3MpKX19CiAgICBgYGAKICAKICAgIFRoZSBjaGlsZCBgQ29tcG9uZW50YCB3b3VsZCBpbnZva2UgdGhlIGZ1bmN0aW9uIHdpdGggdGhlIG5ldyBjbGljayB2YWx1ZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIC8vIG15LWNoaWxkLmpzCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgY2xpY2soKSB7CiAgICAgICAgdGhpcy5nZXQoJ2NsaWNrLWNvdW50LWNoYW5nZScpKHRoaXMuZ2V0KCdjaGlsZENsaWNrQ291bnQnKSArIDEpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgVGhlIGBtdXRgIGhlbHBlciBjaGFuZ2VzIHRoZSBgdG90YWxDbGlja3NgIHZhbHVlIHRvIHdoYXQgd2FzIHByb3ZpZGVkIGFzIHRoZSBgZm5gIGFyZ3VtZW50LgogIAogICAgVGhlIGBtdXRgIGhlbHBlciwgd2hlbiB1c2VkIHdpdGggYGZuYCwgd2lsbCByZXR1cm4gYSBmdW5jdGlvbiB0aGF0CiAgICBzZXRzIHRoZSB2YWx1ZSBwYXNzZWQgdG8gYG11dGAgdG8gaXRzIGZpcnN0IGFyZ3VtZW50LiBBcyBhbiBleGFtcGxlLCB3ZSBjYW4gY3JlYXRlIGEKICAgIGJ1dHRvbiB0aGF0IGluY3JlbWVudHMgYSB2YWx1ZSBwYXNzaW5nIHRoZSB2YWx1ZSBkaXJlY3RseSB0byB0aGUgYGZuYDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7ISBpbmMgaGVscGVyIGlzIG5vdCBwcm92aWRlZCBieSBFbWJlciB9fQogICAgPGJ1dHRvbiBvbmNsaWNrPXt7Zm4gKG11dCBjb3VudCkgKGluYyBjb3VudCl9fT4KICAgICAgSW5jcmVtZW50IGNvdW50CiAgICA8L2J1dHRvbj4KICAgIGBgYAogIAogICAgWW91IGNhbiBhbHNvIHVzZSB0aGUgYHZhbHVlYCBvcHRpb246CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICA8aW5wdXQgdmFsdWU9e3tuYW1lfX0gb25pbnB1dD17e2ZuIChtdXQgbmFtZSkgdmFsdWU9InRhcmdldC52YWx1ZSJ9fT4KICAgIGBgYAogIAogICAgQG1ldGhvZCBtdXQKICAgIEBwYXJhbSB7T2JqZWN0fSBbYXR0cl0gdGhlICJ0d28td2F5IiBhdHRyaWJ1dGUgdGhhdCBjYW4gYmUgbW9kaWZpZWQuCiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAcHVibGljCiAgKi8KCgogIHZhciBNVVRfUkVGRVJFTkNFID0gKDAsIF91dGlscy5zeW1ib2wpKCdNVVQnKTsKICB2YXIgU09VUkNFID0gKDAsIF91dGlscy5zeW1ib2wpKCdTT1VSQ0UnKTsKCiAgZnVuY3Rpb24gaXNNdXQocmVmKSB7CiAgICByZXR1cm4gcmVmICYmIHJlZltNVVRfUkVGRVJFTkNFXTsKICB9CgogIGZ1bmN0aW9uIHVuTXV0KHJlZikgewogICAgcmV0dXJuIHJlZltTT1VSQ0VdIHx8IHJlZjsKICB9CgogIGZ1bmN0aW9uIG11dChfdm0sIGFyZ3MpIHsKICAgIHZhciByYXdSZWYgPSBhcmdzLnBvc2l0aW9uYWwuYXQoMCk7CgogICAgaWYgKGlzTXV0KHJhd1JlZikpIHsKICAgICAgcmV0dXJuIHJhd1JlZjsKICAgIH0gLy8gVE9ETzogSW1wcm92ZSB0aGlzIGVycm9yIG1lc3NhZ2UuIFRoaXMgY292ZXJzIGF0IGxlYXN0IHR3byBkaXN0aW5jdAogICAgLy8gY2FzZXM6CiAgICAvLwogICAgLy8gMS4gKG11dCAibm90IGEgcGF0aCIpIOKAkyBwYXNzaW5nIGEgbGl0ZXJhbCwgcmVzdWx0IGZyb20gYSBoZWxwZXIKICAgIC8vICAgIGludm9jYXRpb24sIGV0YwogICAgLy8KICAgIC8vIDIuIChtdXQgcmVjZWl2ZWRWYWx1ZSkg4oCTIHBhc3NpbmcgYSB2YWx1ZSByZWNlaXZlZCBmcm9tIHRoZSBjYWxsZXIKICAgIC8vICAgIHRoYXQgd2FzIG9yaWdpbmFsbHkgZGVyaXZlZCBmcm9tIGEgbGl0ZXJhbCwgcmVzdWx0IGZyb20gYSBoZWxwZXIKICAgIC8vICAgIGludm9jYXRpb24sIGV0YwogICAgLy8KICAgIC8vIFRoaXMgbWVzc2FnZSBpcyBhbHJpZ2h0IGZvciB0aGUgZmlyc3QgY2FzZSwgYnV0IGNvdWxkIGJlIHF1aXRlCiAgICAvLyBjb25mdXNpbmcgZm9yIHRoZSBzZWNvbmQgY2FzZS4KCgogICAgKGZhbHNlICYmICEocmF3UmVmW1VQREFURV0pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGNhbiBvbmx5IHBhc3MgYSBwYXRoIHRvIG11dCcsIHJhd1JlZltVUERBVEVdKSk7CiAgICB2YXIgd3JhcHBlZFJlZiA9IE9iamVjdC5jcmVhdGUocmF3UmVmKTsKICAgIHdyYXBwZWRSZWZbU09VUkNFXSA9IHJhd1JlZjsKICAgIHdyYXBwZWRSZWZbSU5WT0tFXSA9IHJhd1JlZltVUERBVEVdOwogICAgd3JhcHBlZFJlZltNVVRfUkVGRVJFTkNFXSA9IHRydWU7CiAgICByZXR1cm4gd3JhcHBlZFJlZjsKICB9CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgVGhpcyBpcyBhIGhlbHBlciB0byBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggdGhlIGxpbmstdG8gaGVscGVyLgogICAgSXQgd2lsbCBzdXBwbHkgdXJsIHF1ZXJ5IHBhcmFtZXRlcnMgdG8gdGhlIHRhcmdldCByb3V0ZS4KICAKICAgIEV4YW1wbGUKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7I2xpbmstdG8gJ3Bvc3RzJyAocXVlcnktcGFyYW1zIGRpcmVjdGlvbj0iYXNjIil9fVNvcnR7ey9saW5rLXRvfX0KICAgIGBgYAogIAogICAgQG1ldGhvZCBxdWVyeS1wYXJhbXMKICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwYXJhbSB7T2JqZWN0fSBoYXNoIHRha2VzIGEgaGFzaCBvZiBxdWVyeSBwYXJhbWV0ZXJzCiAgICBAcmV0dXJuIHtPYmplY3R9IEEgYFF1ZXJ5UGFyYW1zYCBvYmplY3QgZm9yIGB7e2xpbmstdG99fWAKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gcXVlcnlQYXJhbXMoX3JlZjMyKSB7CiAgICB2YXIgcG9zaXRpb25hbCA9IF9yZWYzMi5wb3NpdGlvbmFsLAogICAgICAgIG5hbWVkID0gX3JlZjMyLm5hbWVkOwogICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aAogICAgKGZhbHNlICYmICEocG9zaXRpb25hbC52YWx1ZSgpLmxlbmd0aCA9PT0gMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgYHF1ZXJ5LXBhcmFtc2AgaGVscGVyIG9ubHkgYWNjZXB0cyBoYXNoIHBhcmFtZXRlcnMsIGUuZy4gKHF1ZXJ5LXBhcmFtcyBxdWVyeVBhcmFtUHJvcGVydHlOYW1lPSdmb28nKSBhcyBvcHBvc2VkIHRvIGp1c3QgKHF1ZXJ5LXBhcmFtcyAnZm9vJykiLCBwb3NpdGlvbmFsLnZhbHVlKCkubGVuZ3RoID09PSAwKSk7CiAgICByZXR1cm4gbmV3IF9yb3V0aW5nLlF1ZXJ5UGFyYW1zKCgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIG5hbWVkLnZhbHVlKCkpKTsKICB9CgogIGZ1bmN0aW9uIHF1ZXJ5UGFyYW1zJDEoX3ZtLCBhcmdzKSB7CiAgICByZXR1cm4gbmV3IEludGVybmFsSGVscGVyUmVmZXJlbmNlKHF1ZXJ5UGFyYW1zLCBhcmdzLmNhcHR1cmUoKSk7CiAgfQogIC8qKgogICAgVGhlIGByZWFkb25seWAgaGVscGVyIGxldCdzIHlvdSBzcGVjaWZ5IHRoYXQgYSBiaW5kaW5nIGlzIG9uZS13YXkgb25seSwKICAgIGluc3RlYWQgb2YgdHdvLXdheS4KICAgIFdoZW4geW91IHBhc3MgYSBgcmVhZG9ubHlgIGJpbmRpbmcgZnJvbSBhbiBvdXRlciBjb250ZXh0IChlLmcuIHBhcmVudCBjb21wb25lbnQpLAogICAgdG8gdG8gYW4gaW5uZXIgY29udGV4dCAoZS5nLiBjaGlsZCBjb21wb25lbnQpLCB5b3UgYXJlIHNheWluZyB0aGF0IGNoYW5naW5nIHRoYXQKICAgIHByb3BlcnR5IGluIHRoZSBpbm5lciBjb250ZXh0IGRvZXMgbm90IGNoYW5nZSB0aGUgdmFsdWUgaW4gdGhlIG91dGVyIGNvbnRleHQuCiAgCiAgICBUbyBzcGVjaWZ5IHRoYXQgYSBiaW5kaW5nIGlzIHJlYWQtb25seSwgd2hlbiBpbnZva2luZyB0aGUgY2hpbGQgYENvbXBvbmVudGA6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1wYXJlbnQuanMKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICB0b3RhbENsaWNrczogMwogICAgfSk7CiAgICBgYGAKICAKICAgIGBgYGFwcC90ZW1wbGF0ZXMvY29tcG9uZW50cy9teS1wYXJlbnQuaGJzCiAgICB7e2xvZyB0b3RhbENsaWNrc319IC8vIC0+IDMKICAgIDxNeUNoaWxkIEBjaGlsZENsaWNrQ291bnQ9e3tyZWFkb25seSB0b3RhbENsaWNrc319IC8+CiAgICBgYGAKICAgIGBgYAogICAge3tteS1jaGlsZCBjaGlsZENsaWNrQ291bnQ9KHJlYWRvbmx5IHRvdGFsQ2xpY2tzKX19CiAgICBgYGAKICAKICAgIE5vdywgd2hlbiB5b3UgdXBkYXRlIGBjaGlsZENsaWNrQ291bnRgOgogIAogICAgYGBgYXBwL2NvbXBvbmVudHMvbXktY2hpbGQuanMKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGljaygpIHsKICAgICAgICB0aGlzLmluY3JlbWVudFByb3BlcnR5KCdjaGlsZENsaWNrQ291bnQnKTsKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIFRoZSB2YWx1ZSB1cGRhdGVzIGluIHRoZSBjaGlsZCBjb21wb25lbnQsIGJ1dCBub3QgdGhlIHBhcmVudCBjb21wb25lbnQ6CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvbXktY2hpbGQuaGJzCiAgICB7e2xvZyBjaGlsZENsaWNrQ291bnR9fSAvLy0+IDQKICAgIGBgYAogIAogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL215LXBhcmVudC5oYnMKICAgIHt7bG9nIHRvdGFsQ2xpY2tzfX0gLy8tPiAzCiAgICA8TXlDaGlsZCBAY2hpbGRDbGlja0NvdW50PXt7cmVhZG9ubHkgdG90YWxDbGlja3N9fSAvPgogICAgYGBgCiAgICBvcgogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL215LXBhcmVudC5oYnMKICAgIHt7bG9nIHRvdGFsQ2xpY2tzfX0gLy8tPiAzCiAgICB7e215LWNoaWxkIGNoaWxkQ2xpY2tDb3VudD0ocmVhZG9ubHkgdG90YWxDbGlja3MpfX0KICAgIGBgYAogIAogICAgIyMjIE9iamVjdHMgYW5kIEFycmF5cwogIAogICAgV2hlbiBwYXNzaW5nIGEgcHJvcGVydHkgdGhhdCBpcyBhIGNvbXBsZXggb2JqZWN0IChlLmcuIG9iamVjdCwgYXJyYXkpIGluc3RlYWQgb2YgYSBwcmltaXRpdmUgb2JqZWN0IChlLmcuIG51bWJlciwgc3RyaW5nKSwKICAgIG9ubHkgdGhlIHJlZmVyZW5jZSB0byB0aGUgb2JqZWN0IGlzIHByb3RlY3RlZCB1c2luZyB0aGUgcmVhZG9ubHkgaGVscGVyLgogICAgVGhpcyBtZWFucyB0aGF0IHlvdSBjYW4gY2hhbmdlIHByb3BlcnRpZXMgb2YgdGhlIG9iamVjdCBib3RoIG9uIHRoZSBwYXJlbnQgY29tcG9uZW50LCBhcyB3ZWxsIGFzIHRoZSBjaGlsZCBjb21wb25lbnQuCiAgICBUaGUgYHJlYWRvbmx5YCBiaW5kaW5nIGJlaGF2ZXMgc2ltaWxhciB0byB0aGUgYGNvbnN0YCBrZXl3b3JkIGluIEphdmFTY3JpcHQuCiAgCiAgICBMZXQncyBsb29rIGF0IGFuIGV4YW1wbGU6CiAgCiAgICBGaXJzdCBsZXQncyBzZXQgdXAgdGhlIHBhcmVudCBjb21wb25lbnQ6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1wYXJlbnQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgY2xpY2tzOiBudWxsLAogIAogICAgICBpbml0KCkgewogICAgICAgIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cyk7CiAgICAgICAgdGhpcy5zZXQoJ2NsaWNrcycsIHsgdG90YWw6IDMgfSk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvbXktcGFyZW50LmhicwogICAge3tsb2cgY2xpY2tzLnRvdGFsfX0gLy8tPiAzCiAgICA8TXlDaGlsZCBAY2hpbGRDbGlja3M9e3tyZWFkb25seSBjbGlja3N9fSAvPgogICAgYGBgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvbXktcGFyZW50LmhicwogICAge3tsb2cgY2xpY2tzLnRvdGFsfX0gLy8tPiAzCiAgICB7e215LWNoaWxkIGNoaWxkQ2xpY2tzPShyZWFkb25seSBjbGlja3MpfX0KICAgIGBgYAogIAogICAgTm93LCBpZiB5b3UgdXBkYXRlIHRoZSBgdG90YWxgIHByb3BlcnR5IG9mIGBjaGlsZENsaWNrc2A6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jaGlsZC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBjbGljaygpIHsKICAgICAgICB0aGlzLmdldCgnY2xpY2tzJykuaW5jcmVtZW50UHJvcGVydHkoJ3RvdGFsJyk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBZb3Ugd2lsbCBzZWUgdGhlIGZvbGxvd2luZyBoYXBwZW46CiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvbXktcGFyZW50LmhicwogICAge3tsb2cgY2xpY2tzLnRvdGFsfX0gLy8tPiA0CiAgICA8TXlDaGlsZCBAY2hpbGRDbGlja3M9e3tyZWFkb25seSBjbGlja3N9fSAvPgogICAgYGBgCiAgICBvcgogICAgYGBgYXBwL3RlbXBsYXRlcy9jb21wb25lbnRzL215LXBhcmVudC5oYnMKICAgIHt7bG9nIGNsaWNrcy50b3RhbH19IC8vLT4gNAogICAge3tteS1jaGlsZCBjaGlsZENsaWNrcz0ocmVhZG9ubHkgY2xpY2tzKX19CiAgICBgYGAKICAKICAgIGBgYGFwcC90ZW1wbGF0ZXMvY29tcG9uZW50cy9teS1jaGlsZC5oYnMKICAgIHt7bG9nIGNoaWxkQ2xpY2tzLnRvdGFsfX0gLy8tPiA0CiAgICBgYGAKICAKICAgIEBtZXRob2QgcmVhZG9ubHkKICAgIEBwYXJhbSB7T2JqZWN0fSBbYXR0cl0gdGhlIHJlYWQtb25seSBhdHRyaWJ1dGUuCiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAcHJpdmF0ZQogICovCgoKICBmdW5jdGlvbiByZWFkb25seShfdm0sIGFyZ3MpIHsKICAgIHZhciByZWYgPSB1bk11dChhcmdzLnBvc2l0aW9uYWwuYXQoMCkpOwogICAgcmV0dXJuIG5ldyBSZWFkb25seVJlZmVyZW5jZShyZWYpOwogIH0KICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBUaGUgYHt7dW5ib3VuZH19YCBoZWxwZXIgZGlzY29ubmVjdHMgdGhlIG9uZS13YXkgYmluZGluZyBvZiBhIHByb3BlcnR5LAogICAgZXNzZW50aWFsbHkgZnJlZXppbmcgaXRzIHZhbHVlIGF0IHRoZSBtb21lbnQgb2YgcmVuZGVyaW5nLiBGb3IgZXhhbXBsZSwKICAgIGluIHRoaXMgZXhhbXBsZSB0aGUgZGlzcGxheSBvZiB0aGUgdmFyaWFibGUgYG5hbWVgIHdpbGwgbm90IGNoYW5nZSBldmVuCiAgICBpZiBpdCBpcyBzZXQgd2l0aCBhIG5ldyB2YWx1ZToKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7dW5ib3VuZCBuYW1lfX0KICAgIGBgYAogIAogICAgTGlrZSBhbnkgaGVscGVyLCB0aGUgYHVuYm91bmRgIGhlbHBlciBjYW4gYWNjZXB0IGEgbmVzdGVkIGhlbHBlciBleHByZXNzaW9uLgogICAgVGhpcyBhbGxvd3MgZm9yIGN1c3RvbSBoZWxwZXJzIHRvIGJlIHJlbmRlcmVkIHVuYm91bmQ6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e3VuYm91bmQgKHNvbWUtY3VzdG9tLWhlbHBlcil9fQogICAge3t1bmJvdW5kIChjYXBpdGFsaXplIG5hbWUpfX0KICAgIHt7ISBZb3UgY2FuIHVzZSBhbnkgaGVscGVyLCBpbmNsdWRpbmcgdW5ib3VuZCwgaW4gYSBuZXN0ZWQgZXhwcmVzc2lvbiB9fQogICAge3tjYXBpdGFsaXplICh1bmJvdW5kIG5hbWUpfX0KICAgIGBgYAogIAogICAgVGhlIGB1bmJvdW5kYCBoZWxwZXIgb25seSBhY2NlcHRzIGEgc2luZ2xlIGFyZ3VtZW50LCBhbmQgaXQgcmV0dXJuIGFuCiAgICB1bmJvdW5kIHZhbHVlLgogIAogICAgQG1ldGhvZCB1bmJvdW5kCiAgICBAZm9yIEVtYmVyLlRlbXBsYXRlcy5oZWxwZXJzCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIHVuYm91bmQoX3ZtLCBhcmdzKSB7CiAgICAoZmFsc2UgJiYgIShhcmdzLnBvc2l0aW9uYWwubGVuZ3RoID09PSAxICYmIGFyZ3MubmFtZWQubGVuZ3RoID09PSAwKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ3VuYm91bmQgaGVscGVyIGNhbm5vdCBiZSBjYWxsZWQgd2l0aCBtdWx0aXBsZSBwYXJhbXMgb3IgaGFzaCBwYXJhbXMnLCBhcmdzLnBvc2l0aW9uYWwubGVuZ3RoID09PSAxICYmIGFyZ3MubmFtZWQubGVuZ3RoID09PSAwKSk7CiAgICByZXR1cm4gVW5ib3VuZFJlZmVyZW5jZS5jcmVhdGUoYXJncy5wb3NpdGlvbmFsLmF0KDApLnZhbHVlKCkpOwogIH0KCiAgdmFyIE1PRElGSUVSUyA9IFsnYWx0JywgJ3NoaWZ0JywgJ21ldGEnLCAnY3RybCddOwogIHZhciBQT0lOVEVSX0VWRU5UX1RZUEVfUkVHRVggPSAvXmNsaWNrfG1vdXNlfHRvdWNoLzsKCiAgZnVuY3Rpb24gaXNBbGxvd2VkRXZlbnQoZXZlbnQsIGFsbG93ZWRLZXlzKSB7CiAgICBpZiAoYWxsb3dlZEtleXMgPT09IG51bGwgfHwgYWxsb3dlZEtleXMgPT09IHVuZGVmaW5lZCkgewogICAgICBpZiAoUE9JTlRFUl9FVkVOVF9UWVBFX1JFR0VYLnRlc3QoZXZlbnQudHlwZSkpIHsKICAgICAgICByZXR1cm4gKDAsIF92aWV3cy5pc1NpbXBsZUNsaWNrKShldmVudCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYWxsb3dlZEtleXMgPSAnJzsKICAgICAgfQogICAgfQoKICAgIGlmIChhbGxvd2VkS2V5cy5pbmRleE9mKCdhbnknKSA+PSAwKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgTU9ESUZJRVJTLmxlbmd0aDsgaSsrKSB7CiAgICAgIGlmIChldmVudFtNT0RJRklFUlNbaV0gKyAnS2V5J10gJiYgYWxsb3dlZEtleXMuaW5kZXhPZihNT0RJRklFUlNbaV0pID09PSAtMSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiB0cnVlOwogIH0KCiAgdmFyIEFjdGlvbkhlbHBlciA9IHsKICAgIC8vIHJlZ2lzdGVyZWRBY3Rpb25zIGlzIHJlLWV4cG9ydGVkIGZvciBjb21wYXRpYmlsaXR5IHdpdGggb2xkZXIgcGx1Z2lucwogICAgLy8gdGhhdCB3ZXJlIHVzaW5nIHRoaXMgdW5kb2N1bWVudGVkIEFQSS4KICAgIHJlZ2lzdGVyZWRBY3Rpb25zOiBfdmlld3MuQWN0aW9uTWFuYWdlci5yZWdpc3RlcmVkQWN0aW9ucywKICAgIHJlZ2lzdGVyQWN0aW9uOiBmdW5jdGlvbiByZWdpc3RlckFjdGlvbihhY3Rpb25TdGF0ZSkgewogICAgICB2YXIgYWN0aW9uSWQgPSBhY3Rpb25TdGF0ZS5hY3Rpb25JZDsKICAgICAgX3ZpZXdzLkFjdGlvbk1hbmFnZXIucmVnaXN0ZXJlZEFjdGlvbnNbYWN0aW9uSWRdID0gYWN0aW9uU3RhdGU7CiAgICAgIHJldHVybiBhY3Rpb25JZDsKICAgIH0sCiAgICB1bnJlZ2lzdGVyQWN0aW9uOiBmdW5jdGlvbiB1bnJlZ2lzdGVyQWN0aW9uKGFjdGlvblN0YXRlKSB7CiAgICAgIHZhciBhY3Rpb25JZCA9IGFjdGlvblN0YXRlLmFjdGlvbklkOwogICAgICBkZWxldGUgX3ZpZXdzLkFjdGlvbk1hbmFnZXIucmVnaXN0ZXJlZEFjdGlvbnNbYWN0aW9uSWRdOwogICAgfQogIH07CgogIHZhciBBY3Rpb25TdGF0ZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEFjdGlvblN0YXRlKGVsZW1lbnQsIGFjdGlvbklkLCBhY3Rpb25OYW1lLCBhY3Rpb25BcmdzLCBuYW1lZEFyZ3MsIHBvc2l0aW9uYWxBcmdzLCBpbXBsaWNpdFRhcmdldCwgZG9tLCB0YWcpIHsKICAgICAgdGhpcy5lbGVtZW50ID0gZWxlbWVudDsKICAgICAgdGhpcy5hY3Rpb25JZCA9IGFjdGlvbklkOwogICAgICB0aGlzLmFjdGlvbk5hbWUgPSBhY3Rpb25OYW1lOwogICAgICB0aGlzLmFjdGlvbkFyZ3MgPSBhY3Rpb25BcmdzOwogICAgICB0aGlzLm5hbWVkQXJncyA9IG5hbWVkQXJnczsKICAgICAgdGhpcy5wb3NpdGlvbmFsID0gcG9zaXRpb25hbEFyZ3M7CiAgICAgIHRoaXMuaW1wbGljaXRUYXJnZXQgPSBpbXBsaWNpdFRhcmdldDsKICAgICAgdGhpcy5kb20gPSBkb207CiAgICAgIHRoaXMuZXZlbnROYW1lID0gdGhpcy5nZXRFdmVudE5hbWUoKTsKICAgICAgdGhpcy50YWcgPSB0YWc7CiAgICB9CgogICAgdmFyIF9wcm90bzU1ID0gQWN0aW9uU3RhdGUucHJvdG90eXBlOwoKICAgIF9wcm90bzU1LmdldEV2ZW50TmFtZSA9IGZ1bmN0aW9uIGdldEV2ZW50TmFtZSgpIHsKICAgICAgcmV0dXJuIHRoaXMubmFtZWRBcmdzLmdldCgnb24nKS52YWx1ZSgpIHx8ICdjbGljayc7CiAgICB9OwoKICAgIF9wcm90bzU1LmdldEFjdGlvbkFyZ3MgPSBmdW5jdGlvbiBnZXRBY3Rpb25BcmdzKCkgewogICAgICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KHRoaXMuYWN0aW9uQXJncy5sZW5ndGgpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmFjdGlvbkFyZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICByZXN1bHRbaV0gPSB0aGlzLmFjdGlvbkFyZ3NbaV0udmFsdWUoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH07CgogICAgX3Byb3RvNTUuZ2V0VGFyZ2V0ID0gZnVuY3Rpb24gZ2V0VGFyZ2V0KCkgewogICAgICB2YXIgaW1wbGljaXRUYXJnZXQgPSB0aGlzLmltcGxpY2l0VGFyZ2V0LAogICAgICAgICAgbmFtZWRBcmdzID0gdGhpcy5uYW1lZEFyZ3M7CiAgICAgIHZhciB0YXJnZXQ7CgogICAgICBpZiAobmFtZWRBcmdzLmhhcygndGFyZ2V0JykpIHsKICAgICAgICB0YXJnZXQgPSBuYW1lZEFyZ3MuZ2V0KCd0YXJnZXQnKS52YWx1ZSgpOwogICAgICB9IGVsc2UgewogICAgICAgIHRhcmdldCA9IGltcGxpY2l0VGFyZ2V0LnZhbHVlKCk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0YXJnZXQ7CiAgICB9OwoKICAgIF9wcm90bzU1LmhhbmRsZXIgPSBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50KSB7CiAgICAgIHZhciBfdGhpczI0ID0gdGhpczsKCiAgICAgIHZhciBhY3Rpb25OYW1lID0gdGhpcy5hY3Rpb25OYW1lLAogICAgICAgICAgbmFtZWRBcmdzID0gdGhpcy5uYW1lZEFyZ3M7CiAgICAgIHZhciBidWJibGVzID0gbmFtZWRBcmdzLmdldCgnYnViYmxlcycpOwogICAgICB2YXIgcHJldmVudERlZmF1bHQgPSBuYW1lZEFyZ3MuZ2V0KCdwcmV2ZW50RGVmYXVsdCcpOwogICAgICB2YXIgYWxsb3dlZEtleXMgPSBuYW1lZEFyZ3MuZ2V0KCdhbGxvd2VkS2V5cycpOwogICAgICB2YXIgdGFyZ2V0ID0gdGhpcy5nZXRUYXJnZXQoKTsKICAgICAgdmFyIHNob3VsZEJ1YmJsZSA9IGJ1YmJsZXMudmFsdWUoKSAhPT0gZmFsc2U7CgogICAgICBpZiAoIWlzQWxsb3dlZEV2ZW50KGV2ZW50LCBhbGxvd2VkS2V5cy52YWx1ZSgpKSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICBpZiAocHJldmVudERlZmF1bHQudmFsdWUoKSAhPT0gZmFsc2UpIHsKICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOwogICAgICB9CgogICAgICBpZiAoIXNob3VsZEJ1YmJsZSkgewogICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOwogICAgICB9CgogICAgICAoMCwgX3J1bmxvb3Auam9pbikoZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBhcmdzID0gX3RoaXMyNC5nZXRBY3Rpb25BcmdzKCk7CgogICAgICAgIHZhciBwYXlsb2FkID0gewogICAgICAgICAgYXJnczogYXJncywKICAgICAgICAgIHRhcmdldDogdGFyZ2V0LAogICAgICAgICAgbmFtZTogbnVsbAogICAgICAgIH07CgogICAgICAgIGlmICh0eXBlb2YgYWN0aW9uTmFtZVtJTlZPS0VdID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICAoMCwgX2luc3RydW1lbnRhdGlvbi5mbGFnZ2VkSW5zdHJ1bWVudCkoJ2ludGVyYWN0aW9uLmVtYmVyLWFjdGlvbicsIHBheWxvYWQsIGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgYWN0aW9uTmFtZVtJTlZPS0VdLmFwcGx5KGFjdGlvbk5hbWUsIGFyZ3MpOwogICAgICAgICAgfSk7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAodHlwZW9mIGFjdGlvbk5hbWUgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgICgwLCBfaW5zdHJ1bWVudGF0aW9uLmZsYWdnZWRJbnN0cnVtZW50KSgnaW50ZXJhY3Rpb24uZW1iZXItYWN0aW9uJywgcGF5bG9hZCwgZnVuY3Rpb24gKCkgewogICAgICAgICAgICBhY3Rpb25OYW1lLmFwcGx5KHRhcmdldCwgYXJncyk7CiAgICAgICAgICB9KTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHBheWxvYWQubmFtZSA9IGFjdGlvbk5hbWU7CgogICAgICAgIGlmICh0YXJnZXQuc2VuZCkgewogICAgICAgICAgKDAsIF9pbnN0cnVtZW50YXRpb24uZmxhZ2dlZEluc3RydW1lbnQpKCdpbnRlcmFjdGlvbi5lbWJlci1hY3Rpb24nLCBwYXlsb2FkLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIHRhcmdldC5zZW5kLmFwcGx5KHRhcmdldCwgW2FjdGlvbk5hbWVdLmNvbmNhdChhcmdzKSk7CiAgICAgICAgICB9KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgKGZhbHNlICYmICEodHlwZW9mIHRhcmdldFthY3Rpb25OYW1lXSA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgYWN0aW9uICciICsgYWN0aW9uTmFtZSArICInIGRpZCBub3QgZXhpc3Qgb24gIiArIHRhcmdldCwgdHlwZW9mIHRhcmdldFthY3Rpb25OYW1lXSA9PT0gJ2Z1bmN0aW9uJykpOwogICAgICAgICAgKDAsIF9pbnN0cnVtZW50YXRpb24uZmxhZ2dlZEluc3RydW1lbnQpKCdpbnRlcmFjdGlvbi5lbWJlci1hY3Rpb24nLCBwYXlsb2FkLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIHRhcmdldFthY3Rpb25OYW1lXS5hcHBseSh0YXJnZXQsIGFyZ3MpOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIHNob3VsZEJ1YmJsZTsKICAgIH07CgogICAgX3Byb3RvNTUuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIEFjdGlvbkhlbHBlci51bnJlZ2lzdGVyQWN0aW9uKHRoaXMpOwogICAgfTsKCiAgICByZXR1cm4gQWN0aW9uU3RhdGU7CiAgfSgpOyAvLyBpbXBsZW1lbnRzIE1vZGlmaWVyTWFuYWdlcjxBY3Rpb24+CgoKICB2YXIgQWN0aW9uTW9kaWZpZXJNYW5hZ2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQWN0aW9uTW9kaWZpZXJNYW5hZ2VyKCkge30KCiAgICB2YXIgX3Byb3RvNTYgPSBBY3Rpb25Nb2RpZmllck1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzU2LmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShlbGVtZW50LCBfc3RhdGUsIGFyZ3MsIF9keW5hbWljU2NvcGUsIGRvbSkgewogICAgICB2YXIgX2FyZ3MkY2FwdHVyZSA9IGFyZ3MuY2FwdHVyZSgpLAogICAgICAgICAgbmFtZWQgPSBfYXJncyRjYXB0dXJlLm5hbWVkLAogICAgICAgICAgcG9zaXRpb25hbCA9IF9hcmdzJGNhcHR1cmUucG9zaXRpb25hbCwKICAgICAgICAgIHRhZyA9IF9hcmdzJGNhcHR1cmUudGFnOwoKICAgICAgdmFyIGltcGxpY2l0VGFyZ2V0OwogICAgICB2YXIgYWN0aW9uTmFtZTsKICAgICAgdmFyIGFjdGlvbk5hbWVSZWY7CgogICAgICBpZiAocG9zaXRpb25hbC5sZW5ndGggPiAxKSB7CiAgICAgICAgaW1wbGljaXRUYXJnZXQgPSBwb3NpdGlvbmFsLmF0KDApOwogICAgICAgIGFjdGlvbk5hbWVSZWYgPSBwb3NpdGlvbmFsLmF0KDEpOwoKICAgICAgICBpZiAoYWN0aW9uTmFtZVJlZltJTlZPS0VdKSB7CiAgICAgICAgICBhY3Rpb25OYW1lID0gYWN0aW9uTmFtZVJlZjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFyIGFjdGlvbkxhYmVsID0gYWN0aW9uTmFtZVJlZi5wcm9wZXJ0eUtleTsKICAgICAgICAgIGFjdGlvbk5hbWUgPSBhY3Rpb25OYW1lUmVmLnZhbHVlKCk7CiAgICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGFjdGlvbk5hbWUgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IHNwZWNpZmllZCBhIHF1b3RlbGVzcyBwYXRoLCBgJyArIGFjdGlvbkxhYmVsICsgJ2AsIHRvIHRoZSAnICsgJ3t7YWN0aW9ufX0gaGVscGVyIHdoaWNoIGRpZCBub3QgcmVzb2x2ZSB0byBhbiBhY3Rpb24gbmFtZSAoYSAnICsgJ3N0cmluZykuIFBlcmhhcHMgeW91IG1lYW50IHRvIHVzZSBhIHF1b3RlZCBhY3Rpb25OYW1lPyAoZS5nLiAnICsgJ3t7YWN0aW9uICInICsgYWN0aW9uTGFiZWwgKyAnIn19KS4nLCB0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGFjdGlvbk5hbWUgPT09ICdmdW5jdGlvbicpKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciBhY3Rpb25BcmdzID0gW107IC8vIFRoZSBmaXJzdCB0d28gYXJndW1lbnRzIGFyZSAoMSkgYHRoaXNgIGFuZCAoMikgdGhlIGFjdGlvbiBuYW1lLgogICAgICAvLyBFdmVyeXRoaW5nIGVsc2UgaXMgYSBwYXJhbS4KCiAgICAgIGZvciAodmFyIGkgPSAyOyBpIDwgcG9zaXRpb25hbC5sZW5ndGg7IGkrKykgewogICAgICAgIGFjdGlvbkFyZ3MucHVzaChwb3NpdGlvbmFsLmF0KGkpKTsKICAgICAgfQoKICAgICAgdmFyIGFjdGlvbklkID0gKDAsIF91dGlscy51dWlkKSgpOwogICAgICB2YXIgYWN0aW9uU3RhdGUgPSBuZXcgQWN0aW9uU3RhdGUoZWxlbWVudCwgYWN0aW9uSWQsIGFjdGlvbk5hbWUsIGFjdGlvbkFyZ3MsIG5hbWVkLCBwb3NpdGlvbmFsLCBpbXBsaWNpdFRhcmdldCwgZG9tLCB0YWcpOwogICAgICAoZmFsc2UgJiYgIShhY3Rpb25TdGF0ZS5ldmVudE5hbWUgIT09ICdtb3VzZUVudGVyJyAmJiBhY3Rpb25TdGF0ZS5ldmVudE5hbWUgIT09ICdtb3VzZUxlYXZlJyAmJiBhY3Rpb25TdGF0ZS5ldmVudE5hbWUgIT09ICdtb3VzZU1vdmUnKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIlVzaW5nIHRoZSBge3thY3Rpb259fWAgbW9kaWZpZXIgd2l0aCBgIiArIGFjdGlvblN0YXRlLmV2ZW50TmFtZSArICJgIGV2ZW50cyBoYXMgYmVlbiBkZXByZWNhdGVkLiIsIGFjdGlvblN0YXRlLmV2ZW50TmFtZSAhPT0gJ21vdXNlRW50ZXInICYmIGFjdGlvblN0YXRlLmV2ZW50TmFtZSAhPT0gJ21vdXNlTGVhdmUnICYmIGFjdGlvblN0YXRlLmV2ZW50TmFtZSAhPT0gJ21vdXNlTW92ZScsIHsKICAgICAgICBpZDogJ2VtYmVyLXZpZXdzLmV2ZW50LWRpc3BhdGNoZXIubW91c2VlbnRlci1sZWF2ZS1tb3ZlJywKICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY19hY3Rpb24tbW91c2VlbnRlci1sZWF2ZS1tb3ZlJwogICAgICB9KSk7CiAgICAgIHJldHVybiBhY3Rpb25TdGF0ZTsKICAgIH07CgogICAgX3Byb3RvNTYuaW5zdGFsbCA9IGZ1bmN0aW9uIGluc3RhbGwoYWN0aW9uU3RhdGUpIHsKICAgICAgdmFyIGRvbSA9IGFjdGlvblN0YXRlLmRvbSwKICAgICAgICAgIGVsZW1lbnQgPSBhY3Rpb25TdGF0ZS5lbGVtZW50LAogICAgICAgICAgYWN0aW9uSWQgPSBhY3Rpb25TdGF0ZS5hY3Rpb25JZDsKICAgICAgQWN0aW9uSGVscGVyLnJlZ2lzdGVyQWN0aW9uKGFjdGlvblN0YXRlKTsKICAgICAgZG9tLnNldEF0dHJpYnV0ZShlbGVtZW50LCAnZGF0YS1lbWJlci1hY3Rpb24nLCAnJyk7CiAgICAgIGRvbS5zZXRBdHRyaWJ1dGUoZWxlbWVudCwgImRhdGEtZW1iZXItYWN0aW9uLSIgKyBhY3Rpb25JZCwgYWN0aW9uSWQpOwogICAgfTsKCiAgICBfcHJvdG81Ni51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoYWN0aW9uU3RhdGUpIHsKICAgICAgdmFyIHBvc2l0aW9uYWwgPSBhY3Rpb25TdGF0ZS5wb3NpdGlvbmFsOwogICAgICB2YXIgYWN0aW9uTmFtZVJlZiA9IHBvc2l0aW9uYWwuYXQoMSk7CgogICAgICBpZiAoIWFjdGlvbk5hbWVSZWZbSU5WT0tFXSkgewogICAgICAgIGFjdGlvblN0YXRlLmFjdGlvbk5hbWUgPSBhY3Rpb25OYW1lUmVmLnZhbHVlKCk7CiAgICAgIH0KCiAgICAgIGFjdGlvblN0YXRlLmV2ZW50TmFtZSA9IGFjdGlvblN0YXRlLmdldEV2ZW50TmFtZSgpOwogICAgfTsKCiAgICBfcHJvdG81Ni5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoYWN0aW9uU3RhdGUpIHsKICAgICAgcmV0dXJuIGFjdGlvblN0YXRlLnRhZzsKICAgIH07CgogICAgX3Byb3RvNTYuZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3IobW9kaWZpZXIpIHsKICAgICAgcmV0dXJuIG1vZGlmaWVyOwogICAgfTsKCiAgICByZXR1cm4gQWN0aW9uTW9kaWZpZXJNYW5hZ2VyOwogIH0oKTsKCiAgZnVuY3Rpb24gY2FwYWJpbGl0aWVzJDEobWFuYWdlckFQSSwgb3B0aW9uYWxGZWF0dXJlcykgewogICAgaWYgKG9wdGlvbmFsRmVhdHVyZXMgPT09IHZvaWQgMCkgewogICAgICBvcHRpb25hbEZlYXR1cmVzID0ge307CiAgICB9CgogICAgaWYgKG1hbmFnZXJBUEkgIT09ICczLjEzJykgewogICAgICBtYW5hZ2VyQVBJID0gJzMuMTMnOwogICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdNb2RpZmllciBtYW5hZ2VyIGNhcGFiaWxpdGllcyBub3cgcmVxdWlyZSB5b3UgdG8gcGFzcyBhIHZhbGlkIHZlcnNpb24gd2hlbiBiZWluZyBnZW5lcmF0ZWQuIFZhbGlkIHZlcnNpb25zIGluY2x1ZGU6IDMuMTMnLCBmYWxzZSwgewogICAgICAgIHVudGlsOiAnMy4xNy4wJywKICAgICAgICBpZDogJ2ltcGxpY2l0LW1vZGlmaWVyLW1hbmFnZXItY2FwYWJpbGl0aWVzJwogICAgICB9KSk7CiAgICB9CgogICAgKGZhbHNlICYmICEobWFuYWdlckFQSSA9PT0gJzMuMTMnKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0ludmFsaWQgbW9kaWZpZXIgbWFuYWdlciBjb21wYXRpYmlsaXR5IHNwZWNpZmllZCcsIG1hbmFnZXJBUEkgPT09ICczLjEzJykpOwogICAgcmV0dXJuIHsKICAgICAgZGlzYWJsZUF1dG9UcmFja2luZzogQm9vbGVhbihvcHRpb25hbEZlYXR1cmVzLmRpc2FibGVBdXRvVHJhY2tpbmcpCiAgICB9OwogIH0KCiAgdmFyIEN1c3RvbU1vZGlmaWVyRGVmaW5pdGlvbiA9IGZ1bmN0aW9uIEN1c3RvbU1vZGlmaWVyRGVmaW5pdGlvbihuYW1lLCBNb2RpZmllckNsYXNzLCBkZWxlZ2F0ZSwgaXNJbnRlcmFjdGl2ZSkgewogICAgdGhpcy5uYW1lID0gbmFtZTsKICAgIHRoaXMuTW9kaWZpZXJDbGFzcyA9IE1vZGlmaWVyQ2xhc3M7CiAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7CiAgICB0aGlzLnN0YXRlID0gewogICAgICBNb2RpZmllckNsYXNzOiBNb2RpZmllckNsYXNzLAogICAgICBuYW1lOiBuYW1lLAogICAgICBkZWxlZ2F0ZTogZGVsZWdhdGUKICAgIH07CiAgICB0aGlzLm1hbmFnZXIgPSBpc0ludGVyYWN0aXZlID8gQ1VTVE9NX0lOVEVSQUNUSVZFX01PRElGSUVSX01BTkFHRVIgOiBDVVNUT01fTk9OX0lOVEVSQUNUSVZFX01PRElGSUVSX01BTkFHRVI7CiAgfTsKCiAgdmFyIEN1c3RvbU1vZGlmaWVyU3RhdGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDdXN0b21Nb2RpZmllclN0YXRlKGVsZW1lbnQsIGRlbGVnYXRlLCBtb2RpZmllciwgYXJncykgewogICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50OwogICAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7CiAgICAgIHRoaXMubW9kaWZpZXIgPSBtb2RpZmllcjsKICAgICAgdGhpcy5hcmdzID0gYXJnczsKICAgICAgdGhpcy50YWcgPSAoMCwgX3JlZmVyZW5jZS5jcmVhdGVVcGRhdGFibGVUYWcpKCk7CiAgICB9CgogICAgdmFyIF9wcm90bzU3ID0gQ3VzdG9tTW9kaWZpZXJTdGF0ZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNTcuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHZhciBkZWxlZ2F0ZSA9IHRoaXMuZGVsZWdhdGUsCiAgICAgICAgICBtb2RpZmllciA9IHRoaXMubW9kaWZpZXIsCiAgICAgICAgICBhcmdzID0gdGhpcy5hcmdzOwogICAgICBkZWxlZ2F0ZS5kZXN0cm95TW9kaWZpZXIobW9kaWZpZXIsIGFyZ3MudmFsdWUoKSk7CiAgICB9OwoKICAgIHJldHVybiBDdXN0b21Nb2RpZmllclN0YXRlOwogIH0oKTsKICAvKioKICAgIFRoZSBDdXN0b21Nb2RpZmllck1hbmFnZXIgYWxsb3dzIGFkZG9ucyB0byBwcm92aWRlIGN1c3RvbSBtb2RpZmllcgogICAgaW1wbGVtZW50YXRpb25zIHRoYXQgaW50ZWdyYXRlIHNlYW1sZXNzbHkgaW50byBFbWJlci4gVGhpcyBpcyBhY2NvbXBsaXNoZWQKICAgIHRocm91Z2ggYSBkZWxlZ2F0ZSwgcmVnaXN0ZXJlZCB3aXRoIHRoZSBjdXN0b20gbW9kaWZpZXIgbWFuYWdlciwgd2hpY2gKICAgIGltcGxlbWVudHMgYSBzZXQgb2YgaG9va3MgdGhhdCBkZXRlcm1pbmUgbW9kaWZpZXIgYmVoYXZpb3IuCiAgICBUbyBjcmVhdGUgYSBjdXN0b20gbW9kaWZpZXIgbWFuYWdlciwgaW5zdGFudGlhdGUgYSBuZXcgQ3VzdG9tTW9kaWZpZXJNYW5hZ2VyCiAgICBjbGFzcyBhbmQgcGFzcyB0aGUgZGVsZWdhdGUgYXMgdGhlIGZpcnN0IGFyZ3VtZW50OgogIAogICAgYGBganMKICAgIGxldCBtYW5hZ2VyID0gbmV3IEN1c3RvbU1vZGlmaWVyTWFuYWdlcih7CiAgICAgIC8vIC4uLmRlbGVnYXRlIGltcGxlbWVudGF0aW9uLi4uCiAgICB9KTsKICAgIGBgYAogIAogICAgIyMgRGVsZWdhdGUgSG9va3MKICAKICAgIFRocm91Z2hvdXQgdGhlIGxpZmVjeWNsZSBvZiBhIG1vZGlmaWVyLCB0aGUgbW9kaWZpZXIgbWFuYWdlciB3aWxsIGludm9rZQogICAgZGVsZWdhdGUgaG9va3MgdGhhdCBhcmUgcmVzcG9uc2libGUgZm9yIHN1cmZhY2luZyB0aG9zZSBsaWZlY3ljbGUgY2hhbmdlcyB0bwogICAgdGhlIGVuZCBkZXZlbG9wZXIuCiAgICAqIGBjcmVhdGVNb2RpZmllcigpYCAtIGludm9rZWQgd2hlbiBhIG5ldyBpbnN0YW5jZSBvZiBhIG1vZGlmaWVyIHNob3VsZCBiZSBjcmVhdGVkCiAgICAqIGBpbnN0YWxsTW9kaWZpZXIoKWAgLSBpbnZva2VkIHdoZW4gdGhlIG1vZGlmaWVyIGlzIGluc3RhbGxlZCBvbiB0aGUgZWxlbWVudAogICAgKiBgdXBkYXRlTW9kaWZpZXIoKWAgLSBpbnZva2VkIHdoZW4gdGhlIGFyZ3VtZW50cyBwYXNzZWQgdG8gYSBtb2RpZmllciBjaGFuZ2UKICAgICogYGRlc3Ryb3lNb2RpZmllcigpYCAtIGludm9rZWQgd2hlbiB0aGUgbW9kaWZpZXIgaXMgYWJvdXQgdG8gYmUgZGVzdHJveWVkCiAgKi8KCgogIHZhciBJbnRlcmFjdGl2ZUN1c3RvbU1vZGlmaWVyTWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEludGVyYWN0aXZlQ3VzdG9tTW9kaWZpZXJNYW5hZ2VyKCkge30KCiAgICB2YXIgX3Byb3RvNTggPSBJbnRlcmFjdGl2ZUN1c3RvbU1vZGlmaWVyTWFuYWdlci5wcm90b3R5cGU7CgogICAgX3Byb3RvNTguY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKGVsZW1lbnQsIGRlZmluaXRpb24sIGFyZ3MpIHsKICAgICAgdmFyIGRlbGVnYXRlID0gZGVmaW5pdGlvbi5kZWxlZ2F0ZSwKICAgICAgICAgIE1vZGlmaWVyQ2xhc3MgPSBkZWZpbml0aW9uLk1vZGlmaWVyQ2xhc3M7CiAgICAgIHZhciBjYXB0dXJlZEFyZ3MgPSBhcmdzLmNhcHR1cmUoKTsKICAgICAgdmFyIGluc3RhbmNlID0gZGVmaW5pdGlvbi5kZWxlZ2F0ZS5jcmVhdGVNb2RpZmllcihNb2RpZmllckNsYXNzLCBjYXB0dXJlZEFyZ3MudmFsdWUoKSk7CgogICAgICBpZiAoZGVsZWdhdGUuY2FwYWJpbGl0aWVzID09PSB1bmRlZmluZWQpIHsKICAgICAgICBkZWxlZ2F0ZS5jYXBhYmlsaXRpZXMgPSBjYXBhYmlsaXRpZXMkMSgnMy4xMycpOwogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoJ0N1c3RvbSBtb2RpZmllciBtYW5hZ2VycyBtdXN0IGRlZmluZSB0aGVpciBjYXBhYmlsaXRpZXMgdXNpbmcgdGhlIGNhcGFiaWxpdGllcygpIGhlbHBlciBmdW5jdGlvbicsIGZhbHNlLCB7CiAgICAgICAgICB1bnRpbDogJzMuMTcuMCcsCiAgICAgICAgICBpZDogJ2ltcGxpY2l0LW1vZGlmaWVyLW1hbmFnZXItY2FwYWJpbGl0aWVzJwogICAgICAgIH0pKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5ldyBDdXN0b21Nb2RpZmllclN0YXRlKGVsZW1lbnQsIGRlbGVnYXRlLCBpbnN0YW5jZSwgY2FwdHVyZWRBcmdzKTsKICAgIH07CgogICAgX3Byb3RvNTguZ2V0VGFnID0gZnVuY3Rpb24gZ2V0VGFnKF9yZWYzMykgewogICAgICB2YXIgYXJncyA9IF9yZWYzMy5hcmdzLAogICAgICAgICAgdGFnID0gX3JlZjMzLnRhZzsKICAgICAgcmV0dXJuICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKFt0YWcsIGFyZ3MudGFnXSk7CiAgICB9OwoKICAgIF9wcm90bzU4Lmluc3RhbGwgPSBmdW5jdGlvbiBpbnN0YWxsKHN0YXRlKSB7CiAgICAgIHZhciBlbGVtZW50ID0gc3RhdGUuZWxlbWVudCwKICAgICAgICAgIGFyZ3MgPSBzdGF0ZS5hcmdzLAogICAgICAgICAgZGVsZWdhdGUgPSBzdGF0ZS5kZWxlZ2F0ZSwKICAgICAgICAgIG1vZGlmaWVyID0gc3RhdGUubW9kaWZpZXIsCiAgICAgICAgICB0YWcgPSBzdGF0ZS50YWc7CiAgICAgIHZhciBjYXBhYmlsaXRpZXMgPSBkZWxlZ2F0ZS5jYXBhYmlsaXRpZXM7CgogICAgICBpZiAoY2FwYWJpbGl0aWVzLmRpc2FibGVBdXRvVHJhY2tpbmcgPT09IHRydWUpIHsKICAgICAgICAoMCwgX21ldGFsLnVudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBkZWxlZ2F0ZS5pbnN0YWxsTW9kaWZpZXIobW9kaWZpZXIsIGVsZW1lbnQsIGFyZ3MudmFsdWUoKSk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIGNvbWJpbmVkVHJhY2tpbmdUYWcgPSAoMCwgX21ldGFsLnRyYWNrKShmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gZGVsZWdhdGUuaW5zdGFsbE1vZGlmaWVyKG1vZGlmaWVyLCBlbGVtZW50LCBhcmdzLnZhbHVlKCkpOwogICAgICAgIH0pOwogICAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkodGFnLCBjb21iaW5lZFRyYWNraW5nVGFnKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG81OC51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoc3RhdGUpIHsKICAgICAgdmFyIGFyZ3MgPSBzdGF0ZS5hcmdzLAogICAgICAgICAgZGVsZWdhdGUgPSBzdGF0ZS5kZWxlZ2F0ZSwKICAgICAgICAgIG1vZGlmaWVyID0gc3RhdGUubW9kaWZpZXIsCiAgICAgICAgICB0YWcgPSBzdGF0ZS50YWc7CiAgICAgIHZhciBjYXBhYmlsaXRpZXMgPSBkZWxlZ2F0ZS5jYXBhYmlsaXRpZXM7CgogICAgICBpZiAoY2FwYWJpbGl0aWVzLmRpc2FibGVBdXRvVHJhY2tpbmcgPT09IHRydWUpIHsKICAgICAgICAoMCwgX21ldGFsLnVudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBkZWxlZ2F0ZS51cGRhdGVNb2RpZmllcihtb2RpZmllciwgYXJncy52YWx1ZSgpKTsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgY29tYmluZWRUcmFja2luZ1RhZyA9ICgwLCBfbWV0YWwudHJhY2spKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBkZWxlZ2F0ZS51cGRhdGVNb2RpZmllcihtb2RpZmllciwgYXJncy52YWx1ZSgpKTsKICAgICAgICB9KTsKICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHRhZywgY29tYmluZWRUcmFja2luZ1RhZyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNTguZ2V0RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIGdldERlc3RydWN0b3Ioc3RhdGUpIHsKICAgICAgcmV0dXJuIHN0YXRlOwogICAgfTsKCiAgICByZXR1cm4gSW50ZXJhY3RpdmVDdXN0b21Nb2RpZmllck1hbmFnZXI7CiAgfSgpOwoKICB2YXIgTm9uSW50ZXJhY3RpdmVDdXN0b21Nb2RpZmllck1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBOb25JbnRlcmFjdGl2ZUN1c3RvbU1vZGlmaWVyTWFuYWdlcigpIHt9CgogICAgdmFyIF9wcm90bzU5ID0gTm9uSW50ZXJhY3RpdmVDdXN0b21Nb2RpZmllck1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzU5LmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9OwoKICAgIF9wcm90bzU5LmdldFRhZyA9IGZ1bmN0aW9uIGdldFRhZygpIHsKICAgICAgcmV0dXJuIF9yZWZlcmVuY2UuQ09OU1RBTlRfVEFHOwogICAgfTsKCiAgICBfcHJvdG81OS5pbnN0YWxsID0gZnVuY3Rpb24gaW5zdGFsbCgpIHt9OwoKICAgIF9wcm90bzU5LnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZSgpIHt9OwoKICAgIF9wcm90bzU5LmdldERlc3RydWN0b3IgPSBmdW5jdGlvbiBnZXREZXN0cnVjdG9yKCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH07CgogICAgcmV0dXJuIE5vbkludGVyYWN0aXZlQ3VzdG9tTW9kaWZpZXJNYW5hZ2VyOwogIH0oKTsKCiAgdmFyIENVU1RPTV9JTlRFUkFDVElWRV9NT0RJRklFUl9NQU5BR0VSID0gbmV3IEludGVyYWN0aXZlQ3VzdG9tTW9kaWZpZXJNYW5hZ2VyKCk7CiAgdmFyIENVU1RPTV9OT05fSU5URVJBQ1RJVkVfTU9ESUZJRVJfTUFOQUdFUiA9IG5ldyBOb25JbnRlcmFjdGl2ZUN1c3RvbU1vZGlmaWVyTWFuYWdlcigpOwogIHZhciB1bnRvdWNoYWJsZUNvbnRleHQgPSBidWlsZFVudG91Y2hhYmxlVGhpcygnYG9uYCBtb2RpZmllcicpOwogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKgogICAgSW50ZXJuZXQgRXhwbG9yZXIgMTEgZG9lcyBub3Qgc3VwcG9ydCBgb25jZWAgYW5kIGFsc28gZG9lcyBub3Qgc3VwcG9ydAogICAgcGFzc2luZyBgZXZlbnRPcHRpb25zYC4gSW4gc29tZSBzaXR1YXRpb25zIGl0IHRoZW4gdGhyb3dzIGEgd2VpcmQgc2NyaXB0CiAgICBlcnJvciwgbGlrZToKICAKICAgIGBgYAogICAgQ291bGQgbm90IGNvbXBsZXRlIHRoZSBvcGVyYXRpb24gZHVlIHRvIGVycm9yIDgwMDIwMTAxCiAgICBgYGAKICAKICAgIFRoaXMgZmxhZyBkZXRlcm1pbmVzLCB3aGV0aGVyIGB7IG9uY2U6IHRydWUgfWAgYW5kIHRodXMgYWxzbyBldmVudCBvcHRpb25zIGluCiAgICBnZW5lcmFsIGFyZSBzdXBwb3J0ZWQuCiAgKi8KCiAgdmFyIFNVUFBPUlRTX0VWRU5UX09QVElPTlMgPSBmdW5jdGlvbiAoKSB7CiAgICB0cnkgewogICAgICB2YXIgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIHZhciBjb3VudGVyID0gMDsKICAgICAgZGl2LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBjb3VudGVyKys7CiAgICAgIH0sIHsKICAgICAgICBvbmNlOiB0cnVlCiAgICAgIH0pOwogICAgICB2YXIgZXZlbnQ7CgogICAgICBpZiAodHlwZW9mIEV2ZW50ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgZXZlbnQgPSBuZXcgRXZlbnQoJ2NsaWNrJyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnRXZlbnQnKTsKICAgICAgICBldmVudC5pbml0RXZlbnQoJ2NsaWNrJywgdHJ1ZSwgdHJ1ZSk7CiAgICAgIH0KCiAgICAgIGRpdi5kaXNwYXRjaEV2ZW50KGV2ZW50KTsKICAgICAgZGl2LmRpc3BhdGNoRXZlbnQoZXZlbnQpOwogICAgICByZXR1cm4gY291bnRlciA9PT0gMTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9KCk7CgogIHZhciBPbk1vZGlmaWVyU3RhdGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBPbk1vZGlmaWVyU3RhdGUoZWxlbWVudCwgYXJncykgewogICAgICB0aGlzLnNob3VsZFVwZGF0ZSA9IHRydWU7CiAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7CiAgICAgIHRoaXMuYXJncyA9IGFyZ3M7CiAgICAgIHRoaXMudGFnID0gYXJncy50YWc7CiAgICB9CgogICAgdmFyIF9wcm90bzYwID0gT25Nb2RpZmllclN0YXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG82MC51cGRhdGVGcm9tQXJncyA9IGZ1bmN0aW9uIHVwZGF0ZUZyb21BcmdzKCkgewogICAgICB2YXIgYXJncyA9IHRoaXMuYXJnczsKCiAgICAgIHZhciBfYXJncyRuYW1lZCR2YWx1ZSA9IGFyZ3MubmFtZWQudmFsdWUoKSwKICAgICAgICAgIG9uY2UgPSBfYXJncyRuYW1lZCR2YWx1ZS5vbmNlLAogICAgICAgICAgcGFzc2l2ZSA9IF9hcmdzJG5hbWVkJHZhbHVlLnBhc3NpdmUsCiAgICAgICAgICBjYXB0dXJlID0gX2FyZ3MkbmFtZWQkdmFsdWUuY2FwdHVyZTsKCiAgICAgIGlmIChvbmNlICE9PSB0aGlzLm9uY2UpIHsKICAgICAgICB0aGlzLm9uY2UgPSBvbmNlOwogICAgICAgIHRoaXMuc2hvdWxkVXBkYXRlID0gdHJ1ZTsKICAgICAgfQoKICAgICAgaWYgKHBhc3NpdmUgIT09IHRoaXMucGFzc2l2ZSkgewogICAgICAgIHRoaXMucGFzc2l2ZSA9IHBhc3NpdmU7CiAgICAgICAgdGhpcy5zaG91bGRVcGRhdGUgPSB0cnVlOwogICAgICB9CgogICAgICBpZiAoY2FwdHVyZSAhPT0gdGhpcy5jYXB0dXJlKSB7CiAgICAgICAgdGhpcy5jYXB0dXJlID0gY2FwdHVyZTsKICAgICAgICB0aGlzLnNob3VsZFVwZGF0ZSA9IHRydWU7CiAgICAgIH0KCiAgICAgIHZhciBvcHRpb25zOwoKICAgICAgaWYgKG9uY2UgfHwgcGFzc2l2ZSB8fCBjYXB0dXJlKSB7CiAgICAgICAgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyA9IHsKICAgICAgICAgIG9uY2U6IG9uY2UsCiAgICAgICAgICBwYXNzaXZlOiBwYXNzaXZlLAogICAgICAgICAgY2FwdHVyZTogY2FwdHVyZQogICAgICAgIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5vcHRpb25zID0gdW5kZWZpbmVkOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgIShhcmdzLnBvc2l0aW9uYWwuYXQoMCkgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYXJncy5wb3NpdGlvbmFsLmF0KDApLnZhbHVlKCkgPT09ICdzdHJpbmcnKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBtdXN0IHBhc3MgYSB2YWxpZCBET00gZXZlbnQgbmFtZSBhcyB0aGUgZmlyc3QgYXJndW1lbnQgdG8gdGhlIGBvbmAgbW9kaWZpZXInLCBhcmdzLnBvc2l0aW9uYWwuYXQoMCkgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYXJncy5wb3NpdGlvbmFsLmF0KDApLnZhbHVlKCkgPT09ICdzdHJpbmcnKSk7CiAgICAgIHZhciBldmVudE5hbWUgPSBhcmdzLnBvc2l0aW9uYWwuYXQoMCkudmFsdWUoKTsKCiAgICAgIGlmIChldmVudE5hbWUgIT09IHRoaXMuZXZlbnROYW1lKSB7CiAgICAgICAgdGhpcy5ldmVudE5hbWUgPSBldmVudE5hbWU7CiAgICAgICAgdGhpcy5zaG91bGRVcGRhdGUgPSB0cnVlOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgIShhcmdzLnBvc2l0aW9uYWwuYXQoMSkgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYXJncy5wb3NpdGlvbmFsLmF0KDEpLnZhbHVlKCkgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IG11c3QgcGFzcyBhIGZ1bmN0aW9uIGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgdG8gdGhlIGBvbmAgbW9kaWZpZXInLCBhcmdzLnBvc2l0aW9uYWwuYXQoMSkgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYXJncy5wb3NpdGlvbmFsLmF0KDEpLnZhbHVlKCkgPT09ICdmdW5jdGlvbicpKTsKICAgICAgdmFyIHVzZXJQcm92aWRlZENhbGxiYWNrID0gYXJncy5wb3NpdGlvbmFsLmF0KDEpLnZhbHVlKCk7CgogICAgICBpZiAodXNlclByb3ZpZGVkQ2FsbGJhY2sgIT09IHRoaXMudXNlclByb3ZpZGVkQ2FsbGJhY2spIHsKICAgICAgICB0aGlzLnVzZXJQcm92aWRlZENhbGxiYWNrID0gdXNlclByb3ZpZGVkQ2FsbGJhY2s7CiAgICAgICAgdGhpcy5zaG91bGRVcGRhdGUgPSB0cnVlOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgIShhcmdzLnBvc2l0aW9uYWwubGVuZ3RoID09PSAyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW4gb25seSBwYXNzIHR3byBwb3NpdGlvbmFsIGFyZ3VtZW50cyAoZXZlbnQgbmFtZSBhbmQgY2FsbGJhY2spIHRvIHRoZSBgb25gIG1vZGlmaWVyLCBidXQgeW91IHByb3ZpZGVkICIgKyBhcmdzLnBvc2l0aW9uYWwubGVuZ3RoICsgIi4gQ29uc2lkZXIgdXNpbmcgdGhlIGBmbmAgaGVscGVyIHRvIHByb3ZpZGUgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gdGhlIGBvbmAgY2FsbGJhY2suIiwgYXJncy5wb3NpdGlvbmFsLmxlbmd0aCA9PT0gMikpOwogICAgICB2YXIgbmVlZHNDdXN0b21DYWxsYmFjayA9IFNVUFBPUlRTX0VWRU5UX09QVElPTlMgPT09IGZhbHNlICYmIG9uY2UgfHwKICAgICAgLyogbmVlZHMgbWFudWFsIG9uY2UgaW1wbGVtZW50YXRpb24gKi8KICAgICAgZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgJiYgcGFzc2l2ZQogICAgICAvKiBuZWVkcyBwYXNzaXZlIGVuZm9yY2VtZW50ICovCiAgICAgIDsKCiAgICAgIGlmICh0aGlzLnNob3VsZFVwZGF0ZSkgewogICAgICAgIGlmIChuZWVkc0N1c3RvbUNhbGxiYWNrKSB7CiAgICAgICAgICB2YXIgY2FsbGJhY2sgPSB0aGlzLmNhbGxiYWNrID0gZnVuY3Rpb24gKGV2ZW50KSB7CiAgICAgICAgICAgIGlmIChmYWxzZQogICAgICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICAgICAmJiBwYXNzaXZlKSB7CiAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgbWFya2VkIHRoaXMgbGlzdGVuZXIgYXMgJ3Bhc3NpdmUnLCBtZWFuaW5nIHRoYXQgeW91IG11c3Qgbm90IGNhbGwgJ2V2ZW50LnByZXZlbnREZWZhdWx0KCknOiBcblxuIiArIHVzZXJQcm92aWRlZENhbGxiYWNrKSk7CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaWYgKCFTVVBQT1JUU19FVkVOVF9PUFRJT05TICYmIG9uY2UpIHsKICAgICAgICAgICAgICByZW1vdmVFdmVudExpc3RlbmVyKHRoaXMsIGV2ZW50TmFtZSwgY2FsbGJhY2ssIG9wdGlvbnMpOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gdXNlclByb3ZpZGVkQ2FsbGJhY2suY2FsbCh1bnRvdWNoYWJsZUNvbnRleHQsIGV2ZW50KTsKICAgICAgICAgIH07CiAgICAgICAgfSBlbHNlIGlmIChmYWxzZQogICAgICAgIC8qIERFQlVHICovCiAgICAgICAgKSB7CiAgICAgICAgICAvLyBwcmV2ZW50IHRoZSBjYWxsYmFjayBmcm9tIGJlaW5nIGJvdW5kIHRvIHRoZSBlbGVtZW50CiAgICAgICAgICB0aGlzLmNhbGxiYWNrID0gdXNlclByb3ZpZGVkQ2FsbGJhY2suYmluZCh1bnRvdWNoYWJsZUNvbnRleHQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLmNhbGxiYWNrID0gdXNlclByb3ZpZGVkQ2FsbGJhY2s7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzYwLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICB2YXIgZWxlbWVudCA9IHRoaXMuZWxlbWVudCwKICAgICAgICAgIGV2ZW50TmFtZSA9IHRoaXMuZXZlbnROYW1lLAogICAgICAgICAgY2FsbGJhY2sgPSB0aGlzLmNhbGxiYWNrLAogICAgICAgICAgb3B0aW9ucyA9IHRoaXMub3B0aW9uczsKICAgICAgcmVtb3ZlRXZlbnRMaXN0ZW5lcihlbGVtZW50LCBldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKTsKICAgIH07CgogICAgcmV0dXJuIE9uTW9kaWZpZXJTdGF0ZTsKICB9KCk7CgogIHZhciBhZGRzID0gMDsKICB2YXIgcmVtb3ZlcyA9IDA7CgogIGZ1bmN0aW9uIHJlbW92ZUV2ZW50TGlzdGVuZXIoZWxlbWVudCwgZXZlbnROYW1lLCBjYWxsYmFjaywgb3B0aW9ucykgewogICAgcmVtb3ZlcysrOwoKICAgIGlmIChTVVBQT1JUU19FVkVOVF9PUFRJT05TKSB7CiAgICAgIC8vIHdoZW4gb3B0aW9ucyBhcmUgc3VwcG9ydGVkLCB1c2UgdGhlbSBhY3Jvc3MgdGhlIGJvYXJkCiAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKTsKICAgIH0gZWxzZSBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMuY2FwdHVyZSkgewogICAgICAvLyB1c2VkIG9ubHkgaW4gdGhlIGZvbGxvd2luZyBjYXNlOgogICAgICAvLwogICAgICAvLyBgeyBvbmNlOiB0cnVlIHwgZmFsc2UsIHBhc3NpdmU6IHRydWUgfCBmYWxzZSwgY2FwdHVyZTogdHJ1ZSB9CiAgICAgIC8vCiAgICAgIC8vIGBvbmNlYCBpcyBoYW5kbGVkIHZpYSBhIGN1c3RvbSBjYWxsYmFjayB0aGF0IHJlbW92ZXMgYWZ0ZXIgZmlyc3QKICAgICAgLy8gaW52b2NhdGlvbiBzbyB3ZSBvbmx5IGNhcmUgYWJvdXQgY2FwdHVyZSBoZXJlIGFzIGEgYm9vbGVhbgogICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBjYWxsYmFjaywgdHJ1ZSk7CiAgICB9IGVsc2UgewogICAgICAvLyB1c2VkIG9ubHkgaW4gdGhlIGZvbGxvd2luZyBjYXNlczoKICAgICAgLy8KICAgICAgLy8gKiB3aGVyZSB0aGVyZSBpcyBubyBvcHRpb25zCiAgICAgIC8vICogYHsgb25jZTogdHJ1ZSB8IGZhbHNlLCBwYXNzaXZlOiB0cnVlIHwgZmFsc2UsIGNhcHR1cmU6IGZhbHNlIH0KICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2spOwogICAgfQogIH0KCiAgZnVuY3Rpb24gYWRkRXZlbnRMaXN0ZW5lcihlbGVtZW50LCBldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKSB7CiAgICBhZGRzKys7CgogICAgaWYgKFNVUFBPUlRTX0VWRU5UX09QVElPTlMpIHsKICAgICAgLy8gd2hlbiBvcHRpb25zIGFyZSBzdXBwb3J0ZWQsIHVzZSB0aGVtIGFjcm9zcyB0aGUgYm9hcmQKICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG9wdGlvbnMpOwogICAgfSBlbHNlIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5jYXB0dXJlKSB7CiAgICAgIC8vIHVzZWQgb25seSBpbiB0aGUgZm9sbG93aW5nIGNhc2U6CiAgICAgIC8vCiAgICAgIC8vIGB7IG9uY2U6IHRydWUgfCBmYWxzZSwgcGFzc2l2ZTogdHJ1ZSB8IGZhbHNlLCBjYXB0dXJlOiB0cnVlIH0KICAgICAgLy8KICAgICAgLy8gYG9uY2VgIGlzIGhhbmRsZWQgdmlhIGEgY3VzdG9tIGNhbGxiYWNrIHRoYXQgcmVtb3ZlcyBhZnRlciBmaXJzdAogICAgICAvLyBpbnZvY2F0aW9uIHNvIHdlIG9ubHkgY2FyZSBhYm91dCBjYXB0dXJlIGhlcmUgYXMgYSBib29sZWFuCiAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCB0cnVlKTsKICAgIH0gZWxzZSB7CiAgICAgIC8vIHVzZWQgb25seSBpbiB0aGUgZm9sbG93aW5nIGNhc2VzOgogICAgICAvLwogICAgICAvLyAqIHdoZXJlIHRoZXJlIGlzIG5vIG9wdGlvbnMKICAgICAgLy8gKiBgeyBvbmNlOiB0cnVlIHwgZmFsc2UsIHBhc3NpdmU6IHRydWUgfCBmYWxzZSwgY2FwdHVyZTogZmFsc2UgfQogICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBjYWxsYmFjayk7CiAgICB9CiAgfQogIC8qKgogICAgVGhlIGB7e29ufX1gIG1vZGlmaWVyIGxldHMgeW91IGVhc2lseSBhZGQgZXZlbnQgbGlzdGVuZXJzIChpdCB1c2VzCiAgICBbRXZlbnRUYXJnZXQuYWRkRXZlbnRMaXN0ZW5lcl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0V2ZW50VGFyZ2V0L2FkZEV2ZW50TGlzdGVuZXIpCiAgICBpbnRlcm5hbGx5KS4KICAKICAgIEZvciBleGFtcGxlLCBpZiB5b3UnZCBsaWtlIHRvIHJ1biBhIGZ1bmN0aW9uIG9uIHlvdXIgY29tcG9uZW50IHdoZW4gYSBgPGJ1dHRvbj5gCiAgICBpbiB0aGUgY29tcG9uZW50cyB0ZW1wbGF0ZSBpcyBjbGlja2VkIHlvdSBtaWdodCBkbyBzb21ldGhpbmcgbGlrZToKICAKICAgIGBgYGFwcC90ZW1wbGF0ZXMvY29tcG9uZW50cy9saWtlLXBvc3QuaGJzCiAgICA8YnV0dG9uIHt7b24gJ2NsaWNrJyB0aGlzLnNhdmVMaWtlfX0+TGlrZSB0aGlzIHBvc3QhPC9idXR0b24+CiAgICBgYGAKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL2xpa2UtcG9zdC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZ2xpbW1lci9jb21wb25lbnQnOwogICAgaW1wb3J0IHsgYWN0aW9uIH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBjbGFzcyBMaWtlUG9zdENvbXBvbmVudCBleHRlbmRzIENvbXBvbmVudCB7CiAgICAgIEBhY3Rpb24KICAgICAgc2F2ZUxpa2UoKSB7CiAgICAgICAgLy8gc29tZW9uZSBsaWtlcyB5b3VyIHBvc3QhCiAgICAgICAgLy8gYmV0dGVyIHNlbmQgYSByZXF1ZXN0IG9mZiB0byB5b3VyIHNlcnZlci4uLgogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgICMjIyBBcmd1bWVudHMKICAKICAgIGB7e29ufX1gIGFjY2VwdHMgdHdvIHBvc2l0aW9uYWwgYXJndW1lbnRzLCBhbmQgYSBmZXcgbmFtZWQgYXJndW1lbnRzLgogIAogICAgVGhlIHBvc2l0aW9uYWwgYXJndW1lbnRzIGFyZToKICAKICAgIC0gYGV2ZW50YCAtLSB0aGUgbmFtZSB0byB1c2Ugd2hlbiBjYWxsaW5nIGBhZGRFdmVudExpc3RlbmVyYAogICAgLSBgY2FsbGJhY2tgIC0tIHRoZSBmdW5jdGlvbiB0byBiZSBwYXNzZWQgdG8gYGFkZEV2ZW50TGlzdGVuZXJgCiAgCiAgICBUaGUgbmFtZWQgYXJndW1lbnRzIGFyZToKICAKICAgIC0gY2FwdHVyZSAtLSBhIGB0cnVlYCB2YWx1ZSBpbmRpY2F0ZXMgdGhhdCBldmVudHMgb2YgdGhpcyB0eXBlIHdpbGwgYmUgZGlzcGF0Y2hlZAogICAgICB0byB0aGUgcmVnaXN0ZXJlZCBsaXN0ZW5lciBiZWZvcmUgYmVpbmcgZGlzcGF0Y2hlZCB0byBhbnkgRXZlbnRUYXJnZXQgYmVuZWF0aCBpdAogICAgICBpbiB0aGUgRE9NIHRyZWUuCiAgICAtIG9uY2UgLS0gaW5kaWNhdGVzIHRoYXQgdGhlIGxpc3RlbmVyIHNob3VsZCBiZSBpbnZva2VkIGF0IG1vc3Qgb25jZSBhZnRlciBiZWluZwogICAgICBhZGRlZC4gSWYgdHJ1ZSwgdGhlIGxpc3RlbmVyIHdvdWxkIGJlIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZCB3aGVuIGludm9rZWQuCiAgICAtIHBhc3NpdmUgLS0gaWYgYHRydWVgLCBpbmRpY2F0ZXMgdGhhdCB0aGUgZnVuY3Rpb24gc3BlY2lmaWVkIGJ5IGxpc3RlbmVyIHdpbGwgbmV2ZXIKICAgICAgY2FsbCBwcmV2ZW50RGVmYXVsdCgpLiBJZiBhIHBhc3NpdmUgbGlzdGVuZXIgZG9lcyBjYWxsIHByZXZlbnREZWZhdWx0KCksIHRoZSB1c2VyCiAgICAgIGFnZW50IHdpbGwgZG8gbm90aGluZyBvdGhlciB0aGFuIGdlbmVyYXRlIGEgY29uc29sZSB3YXJuaW5nLiBTZWUKICAgICAgW0ltcHJvdmluZyBzY3JvbGxpbmcgcGVyZm9ybWFuY2Ugd2l0aCBwYXNzaXZlIGxpc3RlbmVyc10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0V2ZW50VGFyZ2V0L2FkZEV2ZW50TGlzdGVuZXIjSW1wcm92aW5nX3Njcm9sbGluZ19wZXJmb3JtYW5jZV93aXRoX3Bhc3NpdmVfbGlzdGVuZXJzKQogICAgICB0byBsZWFybiBtb3JlLgogIAogICAgVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHBhc3NlZCB0byBge3tvbn19YCB3aWxsIHJlY2VpdmUgYW55IGFyZ3VtZW50cyB0aGF0IGFyZSBwYXNzZWQKICAgIHRvIHRoZSBldmVudCBoYW5kbGVyLiBNb3N0IGNvbW1vbmx5IHRoaXMgd291bGQgYmUgdGhlIGBldmVudGAgaXRzZWxmLgogIAogICAgSWYgeW91IHdvdWxkIGxpa2UgdG8gcGFzcyBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byB0aGUgZnVuY3Rpb24geW91IHNob3VsZCB1c2UKICAgIHRoZSBge3tmbn19YCBoZWxwZXIuCiAgCiAgICBGb3IgZXhhbXBsZSwgaW4gb3VyIGV4YW1wbGUgY2FzZSBhYm92ZSBpZiB5b3UnZCBsaWtlIHRvIHBhc3MgaW4gdGhlIHBvc3QgdGhhdAogICAgd2FzIGJlaW5nIGxpa2VkIHdoZW4gdGhlIGJ1dHRvbiBpcyBjbGlja2VkIHlvdSBjb3VsZCBkbyBzb21ldGhpbmcgbGlrZToKICAKICAgIGBgYGFwcC90ZW1wbGF0ZXMvY29tcG9uZW50cy9saWtlLXBvc3QuanMKICAgIDxidXR0b24ge3tvbiAnY2xpY2snIChmbiB0aGlzLnNhdmVMaWtlIEBwb3N0KX19Pkxpa2UgdGhpcyBwb3N0ITwvYnV0dG9uPgogICAgYGBgCiAgCiAgICBJbiB0aGlzIGNhc2UsIHRoZSBgc2F2ZUxpa2VgIGZ1bmN0aW9uIHdpbGwgcmVjZWl2ZSB0d28gYXJndW1lbnRzOiB0aGUgY2xpY2sgZXZlbnQKICAgIGFuZCB0aGUgdmFsdWUgb2YgYEBwb3N0YC4KICAKICAgICMjIyBGdW5jdGlvbiBDb250ZXh0CiAgCiAgICBJbiB0aGUgZXhhbXBsZSBhYm92ZSwgd2UgdXNlZCBgQGFjdGlvbmAgdG8gZW5zdXJlIHRoYXQgYGxpa2VQb3N0YCBpcwogICAgcHJvcGVybHkgYm91bmQgdG8gdGhlIGBpdGVtcy1saXN0YCwgYnV0IGxldCdzIGV4cGxvcmUgd2hhdCBoYXBwZW5zIGlmIHdlCiAgICBsZWZ0IG91dCBgQGFjdGlvbmA6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9saWtlLXBvc3QuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGdsaW1tZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IGNsYXNzIExpa2VQb3N0Q29tcG9uZW50IGV4dGVuZHMgQ29tcG9uZW50IHsKICAgICAgc2F2ZUxpa2UoKSB7CiAgICAgICAgLy8gLi4uc25pcC4uLgogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIEluIHRoaXMgZXhhbXBsZSwgd2hlbiB0aGUgYnV0dG9uIGlzIGNsaWNrZWQgYHNhdmVMaWtlYCB3aWxsIGJlIGludm9rZWQsCiAgICBpdCB3aWxsICoqbm90KiogaGF2ZSBhY2Nlc3MgdG8gdGhlIGNvbXBvbmVudCBpbnN0YW5jZS4gSW4gb3RoZXIKICAgIHdvcmRzLCBpdCB3aWxsIGhhdmUgbm8gYHRoaXNgIGNvbnRleHQsIHNvIHBsZWFzZSBtYWtlIHN1cmUgeW91ciBmdW5jdGlvbnMKICAgIGFyZSBib3VuZCAodmlhIGBAYWN0aW9uYCBvciBvdGhlciBtZWFucykgYmVmb3JlIHBhc3NpbmcgaW50byBgb25gIQogIAogICAgQG1ldGhvZCBvbgogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHB1YmxpYwogICAgQHNpbmNlIDMuMTEuMAogICovCgoKICB2YXIgT25Nb2RpZmllck1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBPbk1vZGlmaWVyTWFuYWdlcihpc0ludGVyYWN0aXZlKSB7CiAgICAgIHRoaXMuU1VQUE9SVFNfRVZFTlRfT1BUSU9OUyA9IFNVUFBPUlRTX0VWRU5UX09QVElPTlM7CiAgICAgIHRoaXMuaXNJbnRlcmFjdGl2ZSA9IGlzSW50ZXJhY3RpdmU7CiAgICB9CgogICAgdmFyIF9wcm90bzYxID0gT25Nb2RpZmllck1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzYxLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShlbGVtZW50LCBfc3RhdGUsIGFyZ3MpIHsKICAgICAgaWYgKCF0aGlzLmlzSW50ZXJhY3RpdmUpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIGNhcHR1cmVkQXJncyA9IGFyZ3MuY2FwdHVyZSgpOwogICAgICByZXR1cm4gbmV3IE9uTW9kaWZpZXJTdGF0ZShlbGVtZW50LCBjYXB0dXJlZEFyZ3MpOwogICAgfTsKCiAgICBfcHJvdG82MS5nZXRUYWcgPSBmdW5jdGlvbiBnZXRUYWcoc3RhdGUpIHsKICAgICAgaWYgKHN0YXRlID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIF9yZWZlcmVuY2UuQ09OU1RBTlRfVEFHOwogICAgICB9CgogICAgICByZXR1cm4gc3RhdGUudGFnOwogICAgfTsKCiAgICBfcHJvdG82MS5pbnN0YWxsID0gZnVuY3Rpb24gaW5zdGFsbChzdGF0ZSkgewogICAgICBpZiAoc3RhdGUgPT09IG51bGwpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHN0YXRlLnVwZGF0ZUZyb21BcmdzKCk7CiAgICAgIHZhciBlbGVtZW50ID0gc3RhdGUuZWxlbWVudCwKICAgICAgICAgIGV2ZW50TmFtZSA9IHN0YXRlLmV2ZW50TmFtZSwKICAgICAgICAgIGNhbGxiYWNrID0gc3RhdGUuY2FsbGJhY2ssCiAgICAgICAgICBvcHRpb25zID0gc3RhdGUub3B0aW9uczsKICAgICAgYWRkRXZlbnRMaXN0ZW5lcihlbGVtZW50LCBldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKTsKICAgICAgc3RhdGUuc2hvdWxkVXBkYXRlID0gZmFsc2U7CiAgICB9OwoKICAgIF9wcm90bzYxLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZShzdGF0ZSkgewogICAgICBpZiAoc3RhdGUgPT09IG51bGwpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gLy8gc3Rhc2ggcHJpb3Igc3RhdGUgZm9yIGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIKCgogICAgICB2YXIgZWxlbWVudCA9IHN0YXRlLmVsZW1lbnQsCiAgICAgICAgICBldmVudE5hbWUgPSBzdGF0ZS5ldmVudE5hbWUsCiAgICAgICAgICBjYWxsYmFjayA9IHN0YXRlLmNhbGxiYWNrLAogICAgICAgICAgb3B0aW9ucyA9IHN0YXRlLm9wdGlvbnM7CiAgICAgIHN0YXRlLnVwZGF0ZUZyb21BcmdzKCk7CgogICAgICBpZiAoIXN0YXRlLnNob3VsZFVwZGF0ZSkgewogICAgICAgIHJldHVybjsKICAgICAgfSAvLyB1c2UgcHJpb3Igc3RhdGUgdmFsdWVzIGZvciByZW1vdmFsCgoKICAgICAgcmVtb3ZlRXZlbnRMaXN0ZW5lcihlbGVtZW50LCBldmVudE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zKTsgLy8gcmVhZCB1cGRhdGVkIHZhbHVlcyBmcm9tIHRoZSBzdGF0ZSBvYmplY3QKCiAgICAgIGFkZEV2ZW50TGlzdGVuZXIoc3RhdGUuZWxlbWVudCwgc3RhdGUuZXZlbnROYW1lLCBzdGF0ZS5jYWxsYmFjaywgc3RhdGUub3B0aW9ucyk7CiAgICAgIHN0YXRlLnNob3VsZFVwZGF0ZSA9IGZhbHNlOwogICAgfTsKCiAgICBfcHJvdG82MS5nZXREZXN0cnVjdG9yID0gZnVuY3Rpb24gZ2V0RGVzdHJ1Y3RvcihzdGF0ZSkgewogICAgICByZXR1cm4gc3RhdGU7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoT25Nb2RpZmllck1hbmFnZXIsIFt7CiAgICAgIGtleTogImNvdW50ZXJzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGFkZHM6IGFkZHMsCiAgICAgICAgICByZW1vdmVzOiByZW1vdmVzCiAgICAgICAgfTsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIE9uTW9kaWZpZXJNYW5hZ2VyOwogIH0oKTsKCiAgZnVuY3Rpb24gaGFzaFRvQXJncyhoYXNoKSB7CiAgICBpZiAoaGFzaCA9PT0gbnVsbCkgcmV0dXJuIG51bGw7CiAgICB2YXIgbmFtZXMgPSBoYXNoWzBdLm1hcChmdW5jdGlvbiAoa2V5KSB7CiAgICAgIHJldHVybiAiQCIgKyBrZXk7CiAgICB9KTsKICAgIHJldHVybiBbbmFtZXMsIGhhc2hbMV1dOwogIH0KICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICAgIFRoZSBgbGV0YCBoZWxwZXIgcmVjZWl2ZXMgb25lIG9yIG1vcmUgcG9zaXRpb25hbCBhcmd1bWVudHMgYW5kIHlpZWxkcwogICAgICB0aGVtIG91dCBhcyBibG9jayBwYXJhbXMuCiAgCiAgICAgIFRoaXMgYWxsb3dzIHRoZSBkZXZlbG9wZXIgdG8gaW50cm9kdWNlIHNob3J0ZXIgbmFtZXMgZm9yIGNlcnRhaW4gY29tcHV0YXRpb25zCiAgICAgIGluIHRoZSB0ZW1wbGF0ZS4KICAKICAgICAgVGhpcyBpcyBlc3BlY2lhbGx5IHVzZWZ1bCBpZiB5b3UgYXJlIHBhc3NpbmcgcHJvcGVydGllcyB0byBhIGNvbXBvbmVudAogICAgICB0aGF0IHJlY2VpdmVzIGEgbG90IG9mIG9wdGlvbnMgYW5kIHlvdSB3YW50IHRvIGNsZWFuIHVwIHRoZSBpbnZvY2F0aW9uLgogIAogICAgICBGb3IgdGhlIGZvbGxvd2luZyBleGFtcGxlLCB0aGUgdGVtcGxhdGUgcmVjZWl2ZXMgYSBgcG9zdGAgb2JqZWN0IHdpdGgKICAgICAgYGNvbnRlbnRgIGFuZCBgdGl0bGVgIHByb3BlcnRpZXMuCiAgCiAgICAgIFdlIGFyZSBnb2luZyB0byBjYWxsIHRoZSBgbXktcG9zdGAgY29tcG9uZW50LCBwYXNzaW5nIGEgdGl0bGUgd2hpY2ggaXMKICAgICAgdGhlIHRpdGxlIG9mIHRoZSBwb3N0IHN1ZmZpeGVkIHdpdGggdGhlIG5hbWUgb2YgdGhlIGJsb2csIHRoZSBjb250ZW50CiAgICAgIG9mIHRoZSBwb3N0LCBhbmQgYSBzZXJpZXMgb2Ygb3B0aW9ucyBkZWZpbmVkIGluLXBsYWNlLgogIAogICAgICBgYGBoYW5kbGViYXJzCiAgICAgIHt7I2xldAogICAgICAgICAgKGNvbmNhdCBwb3N0LnRpdGxlICcgfCBUaGUgRW1iZXIuanMgQmxvZycpCiAgICAgICAgICBwb3N0LmNvbnRlbnQKICAgICAgICAgIChoYXNoCiAgICAgICAgICAgIHRoZW1lPSJoaWdoLWNvbnRyYXN0IgogICAgICAgICAgICBlbmFibGVDb21tZW50cz10cnVlCiAgICAgICAgICApCiAgICAgICAgICBhcyB8dGl0bGUgY29udGVudCBvcHRpb25zfAogICAgICB9fQogICAgICAgIDxNeVBvc3QgQHRpdGxlPXt7dGl0bGV9fSBAY29udGVudD17e2NvbnRlbnR9fSBAb3B0aW9ucz17e29wdGlvbnN9fSAvPgogICAgICB7ey9sZXR9fQogICAgYGBgCiAgIG9yCiAgICBgYGBoYW5kbGViYXJzCiAgICAgIHt7I2xldAogICAgICAgICAgKGNvbmNhdCBwb3N0LnRpdGxlICcgfCBUaGUgRW1iZXIuanMgQmxvZycpCiAgICAgICAgICBwb3N0LmNvbnRlbnQKICAgICAgICAgIChoYXNoCiAgICAgICAgICAgIHRoZW1lPSJoaWdoLWNvbnRyYXN0IgogICAgICAgICAgICBlbmFibGVDb21tZW50cz10cnVlCiAgICAgICAgICApCiAgICAgICAgICBhcyB8dGl0bGUgY29udGVudCBvcHRpb25zfAogICAgICB9fQogICAgICAgIHt7bXktcG9zdCB0aXRsZT10aXRsZSBjb250ZW50PWNvbnRlbnQgb3B0aW9ucz1vcHRpb25zfX0KICAgICAge3svbGV0fX0KICAgIGBgYAogIAogICAgQG1ldGhvZCBsZXQKICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gYmxvY2tMZXRNYWNybyhwYXJhbXMsIF9oYXNoLCB0ZW1wbGF0ZSwgX2ludmVyc2UsIGJ1aWxkZXIpIHsKICAgIGlmICh0ZW1wbGF0ZSAhPT0gbnVsbCkgewogICAgICBpZiAocGFyYW1zICE9PSBudWxsKSB7CiAgICAgICAgYnVpbGRlci5jb21waWxlUGFyYW1zKHBhcmFtcyk7CiAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNCbG9jayh0ZW1wbGF0ZSwgcGFyYW1zLmxlbmd0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWModGVtcGxhdGUpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHRydWU7CiAgfQoKICB2YXIgQ0FQQUJJTElUSUVTJDQgPSB7CiAgICBkeW5hbWljTGF5b3V0OiB0cnVlLAogICAgZHluYW1pY1RhZzogZmFsc2UsCiAgICBwcmVwYXJlQXJnczogZmFsc2UsCiAgICBjcmVhdGVBcmdzOiBmYWxzZSwKICAgIGF0dHJpYnV0ZUhvb2s6IGZhbHNlLAogICAgZWxlbWVudEhvb2s6IGZhbHNlLAogICAgY3JlYXRlQ2FsbGVyOiB0cnVlLAogICAgZHluYW1pY1Njb3BlOiB0cnVlLAogICAgdXBkYXRlSG9vazogdHJ1ZSwKICAgIGNyZWF0ZUluc3RhbmNlOiB0cnVlCiAgfTsKCiAgdmFyIE1vdW50TWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQWJzdHJhY3RNYW5hZ2VyNikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE1vdW50TWFuYWdlciwgX0Fic3RyYWN0TWFuYWdlcjYpOwoKICAgIGZ1bmN0aW9uIE1vdW50TWFuYWdlcigpIHsKICAgICAgcmV0dXJuIF9BYnN0cmFjdE1hbmFnZXI2LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjIgPSBNb3VudE1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzYyLmdldER5bmFtaWNMYXlvdXQgPSBmdW5jdGlvbiBnZXREeW5hbWljTGF5b3V0KHN0YXRlLCBfKSB7CiAgICAgIHZhciB0ZW1wbGF0ZUZhY3RvcnkkJDEgPSBzdGF0ZS5lbmdpbmUubG9va3VwKCd0ZW1wbGF0ZTphcHBsaWNhdGlvbicpOwogICAgICB2YXIgdGVtcGxhdGUgPSB0ZW1wbGF0ZUZhY3RvcnkkJDEoc3RhdGUuZW5naW5lKTsKICAgICAgdmFyIGxheW91dCA9IHRlbXBsYXRlLmFzTGF5b3V0KCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiBsYXlvdXQuY29tcGlsZSgpLAogICAgICAgIHN5bWJvbFRhYmxlOiBsYXlvdXQuc3ltYm9sVGFibGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvNjIuZ2V0Q2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gZ2V0Q2FwYWJpbGl0aWVzKCkgewogICAgICByZXR1cm4gQ0FQQUJJTElUSUVTJDQ7CiAgICB9OwoKICAgIF9wcm90bzYyLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShlbnZpcm9ubWVudCwgc3RhdGUpIHsKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuX3B1c2hFbmdpbmVUb0RlYnVnU3RhY2soImVuZ2luZToiICsgc3RhdGUubmFtZSwgZW52aXJvbm1lbnQpOwogICAgICB9IC8vIFRPRE8KICAgICAgLy8gbW91bnQgaXMgYSBydW50aW1lIGhlbHBlciwgdGhpcyBzaG91bGRuJ3QgdXNlIGR5bmFtaWMgbGF5b3V0CiAgICAgIC8vIHdlIHNob3VsZCByZXNvbHZlIHRoZSBlbmdpbmUgYXBwIHRlbXBsYXRlIGluIHRoZSBoZWxwZXIKICAgICAgLy8gaXQgYWxzbyBzaG91bGQgdXNlIHRoZSBvd25lciB0aGF0IGxvb2tlZCB1cCB0aGUgbW91bnQgaGVscGVyLgoKCiAgICAgIHZhciBlbmdpbmUgPSBlbnZpcm9ubWVudC5vd25lci5idWlsZENoaWxkRW5naW5lSW5zdGFuY2Uoc3RhdGUubmFtZSk7CiAgICAgIGVuZ2luZS5ib290KCk7CiAgICAgIHZhciBhcHBsaWNhdGlvbkZhY3RvcnkgPSBlbmdpbmUuZmFjdG9yeUZvcigiY29udHJvbGxlcjphcHBsaWNhdGlvbiIpOwogICAgICB2YXIgY29udHJvbGxlckZhY3RvcnkgPSBhcHBsaWNhdGlvbkZhY3RvcnkgfHwgKDAsIF9yb3V0aW5nLmdlbmVyYXRlQ29udHJvbGxlckZhY3RvcnkpKGVuZ2luZSwgJ2FwcGxpY2F0aW9uJyk7CiAgICAgIHZhciBjb250cm9sbGVyOwogICAgICB2YXIgc2VsZjsKICAgICAgdmFyIGJ1Y2tldDsKICAgICAgdmFyIHRhZzsKICAgICAgdmFyIG1vZGVsUmVmID0gc3RhdGUubW9kZWxSZWY7CgogICAgICBpZiAobW9kZWxSZWYgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGNvbnRyb2xsZXIgPSBjb250cm9sbGVyRmFjdG9yeS5jcmVhdGUoKTsKICAgICAgICBzZWxmID0gbmV3IFJvb3RSZWZlcmVuY2UoY29udHJvbGxlcik7CiAgICAgICAgdGFnID0gX3JlZmVyZW5jZS5DT05TVEFOVF9UQUc7CiAgICAgICAgYnVja2V0ID0gewogICAgICAgICAgZW5naW5lOiBlbmdpbmUsCiAgICAgICAgICBjb250cm9sbGVyOiBjb250cm9sbGVyLAogICAgICAgICAgc2VsZjogc2VsZiwKICAgICAgICAgIHRhZzogdGFnCiAgICAgICAgfTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgbW9kZWwgPSBtb2RlbFJlZi52YWx1ZSgpOwogICAgICAgIHZhciBtb2RlbFJldiA9ICgwLCBfcmVmZXJlbmNlLnZhbHVlKShtb2RlbFJlZi50YWcpOwogICAgICAgIGNvbnRyb2xsZXIgPSBjb250cm9sbGVyRmFjdG9yeS5jcmVhdGUoewogICAgICAgICAgbW9kZWw6IG1vZGVsCiAgICAgICAgfSk7CiAgICAgICAgc2VsZiA9IG5ldyBSb290UmVmZXJlbmNlKGNvbnRyb2xsZXIpOwogICAgICAgIHRhZyA9IG1vZGVsUmVmLnRhZzsKICAgICAgICBidWNrZXQgPSB7CiAgICAgICAgICBlbmdpbmU6IGVuZ2luZSwKICAgICAgICAgIGNvbnRyb2xsZXI6IGNvbnRyb2xsZXIsCiAgICAgICAgICBzZWxmOiBzZWxmLAogICAgICAgICAgdGFnOiB0YWcsCiAgICAgICAgICBtb2RlbFJlZjogbW9kZWxSZWYsCiAgICAgICAgICBtb2RlbFJldjogbW9kZWxSZXYKICAgICAgICB9OwogICAgICB9CgogICAgICByZXR1cm4gYnVja2V0OwogICAgfTsKCiAgICBfcHJvdG82Mi5nZXRTZWxmID0gZnVuY3Rpb24gZ2V0U2VsZihfcmVmMzQpIHsKICAgICAgdmFyIHNlbGYgPSBfcmVmMzQuc2VsZjsKICAgICAgcmV0dXJuIHNlbGY7CiAgICB9OwoKICAgIF9wcm90bzYyLmdldFRhZyA9IGZ1bmN0aW9uIGdldFRhZyhzdGF0ZSkgewogICAgICByZXR1cm4gc3RhdGUudGFnOwogICAgfTsKCiAgICBfcHJvdG82Mi5nZXREZXN0cnVjdG9yID0gZnVuY3Rpb24gZ2V0RGVzdHJ1Y3RvcihfcmVmMzUpIHsKICAgICAgdmFyIGVuZ2luZSA9IF9yZWYzNS5lbmdpbmU7CiAgICAgIHJldHVybiBlbmdpbmU7CiAgICB9OwoKICAgIF9wcm90bzYyLmRpZFJlbmRlckxheW91dCA9IGZ1bmN0aW9uIGRpZFJlbmRlckxheW91dCgpIHsKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHRoaXMuZGVidWdTdGFjay5wb3AoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG82Mi51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoYnVja2V0KSB7CiAgICAgIHZhciBjb250cm9sbGVyID0gYnVja2V0LmNvbnRyb2xsZXIsCiAgICAgICAgICBtb2RlbFJlZiA9IGJ1Y2tldC5tb2RlbFJlZiwKICAgICAgICAgIG1vZGVsUmV2ID0gYnVja2V0Lm1vZGVsUmV2OwoKICAgICAgaWYgKCEoMCwgX3JlZmVyZW5jZS52YWxpZGF0ZSkobW9kZWxSZWYudGFnLCBtb2RlbFJldikpIHsKICAgICAgICB2YXIgbW9kZWwgPSBtb2RlbFJlZi52YWx1ZSgpOwogICAgICAgIGJ1Y2tldC5tb2RlbFJldiA9ICgwLCBfcmVmZXJlbmNlLnZhbHVlKShtb2RlbFJlZi50YWcpOwogICAgICAgIGNvbnRyb2xsZXIuc2V0KCdtb2RlbCcsIG1vZGVsKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gTW91bnRNYW5hZ2VyOwogIH0oQWJzdHJhY3RNYW5hZ2VyKTsKCiAgdmFyIE1PVU5UX01BTkFHRVIgPSBuZXcgTW91bnRNYW5hZ2VyKCk7CgogIHZhciBNb3VudERlZmluaXRpb24gPSBmdW5jdGlvbiBNb3VudERlZmluaXRpb24obmFtZSwgbW9kZWxSZWYpIHsKICAgIHRoaXMubWFuYWdlciA9IE1PVU5UX01BTkFHRVI7CiAgICB0aGlzLnN0YXRlID0gewogICAgICBuYW1lOiBuYW1lLAogICAgICBtb2RlbFJlZjogbW9kZWxSZWYKICAgIH07CiAgfTsKCiAgZnVuY3Rpb24gbW91bnRIZWxwZXIodm0sIGFyZ3MpIHsKICAgIHZhciBlbnYgPSB2bS5lbnY7CiAgICB2YXIgbmFtZVJlZiA9IGFyZ3MucG9zaXRpb25hbC5hdCgwKTsKICAgIHZhciBtb2RlbFJlZiA9IGFyZ3MubmFtZWQuaGFzKCdtb2RlbCcpID8gYXJncy5uYW1lZC5nZXQoJ21vZGVsJykgOiB1bmRlZmluZWQ7CiAgICByZXR1cm4gbmV3IER5bmFtaWNFbmdpbmVSZWZlcmVuY2UobmFtZVJlZiwgZW52LCBtb2RlbFJlZik7CiAgfQogIC8qKgogICAgVGhlIGB7e21vdW50fX1gIGhlbHBlciBsZXRzIHlvdSBlbWJlZCBhIHJvdXRlbGVzcyBlbmdpbmUgaW4gYSB0ZW1wbGF0ZS4KICAgIE1vdW50aW5nIGFuIGVuZ2luZSB3aWxsIGNhdXNlIGFuIGluc3RhbmNlIHRvIGJlIGJvb3RlZCBhbmQgaXRzIGBhcHBsaWNhdGlvbmAKICAgIHRlbXBsYXRlIHRvIGJlIHJlbmRlcmVkLgogIAogICAgRm9yIGV4YW1wbGUsIHRoZSBmb2xsb3dpbmcgdGVtcGxhdGUgbW91bnRzIHRoZSBgZW1iZXItY2hhdGAgZW5naW5lOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3shIGFwcGxpY2F0aW9uLmhicyB9fQogICAge3ttb3VudCAiZW1iZXItY2hhdCJ9fQogICAgYGBgCiAgCiAgICBBZGRpdGlvbmFsbHksIHlvdSBjYW4gYWxzbyBwYXNzIGluIGEgYG1vZGVsYCBhcmd1bWVudCB0aGF0IHdpbGwgYmUKICAgIHNldCBhcyB0aGUgZW5naW5lcyBtb2RlbC4gVGhpcyBjYW4gYmUgYW4gZXhpc3Rpbmcgb2JqZWN0OgogIAogICAgYGBgCiAgICA8ZGl2PgogICAgICB7e21vdW50ICdhZG1pbicgbW9kZWw9dXNlclNldHRpbmdzfX0KICAgIDwvZGl2PgogICAgYGBgCiAgCiAgICBPciBhbiBpbmxpbmUgYGhhc2hgLCBhbmQgeW91IGNhbiBldmVuIHBhc3MgY29tcG9uZW50czoKICAKICAgIGBgYAogICAgPGRpdj4KICAgICAgPGgxPkFwcGxpY2F0aW9uIHRlbXBsYXRlITwvaDE+CiAgICAgIHt7bW91bnQgJ2FkbWluJyBtb2RlbD0oaGFzaAogICAgICAgICAgdGl0bGU9J1NlY3JldCBBZG1pbicKICAgICAgICAgIHNpZ25JbkJ1dHRvbj0oY29tcG9uZW50ICdzaWduLWluLWJ1dHRvbicpCiAgICAgICl9fQogICAgPC9kaXY+CiAgICBgYGAKICAKICAgIEBtZXRob2QgbW91bnQKICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIGVuZ2luZSB0byBtb3VudC4KICAgIEBwYXJhbSB7T2JqZWN0fSBbbW9kZWxdIE9iamVjdCB0aGF0IHdpbGwgYmUgc2V0IGFzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgbW9kZWwgb2YgdGhlIGVuZ2luZS4KICAgIEBmb3IgRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbW91bnRNYWNybyhfbmFtZSwgcGFyYW1zLCBoYXNoLCBidWlsZGVyKSB7CiAgICAoZmFsc2UgJiYgIShwYXJhbXMubGVuZ3RoID09PSAxKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW4gb25seSBwYXNzIGEgc2luZ2xlIHBvc2l0aW9uYWwgYXJndW1lbnQgdG8gdGhlIHt7bW91bnR9fSBoZWxwZXIsIGUuZy4ge3ttb3VudCAiY2hhdC1lbmdpbmUifX0uJywgcGFyYW1zLmxlbmd0aCA9PT0gMSkpOwogICAgdmFyIGV4cHIgPSBbX3dpcmVGb3JtYXQuT3BzLkhlbHBlciwgJy1tb3VudCcsIHBhcmFtcyB8fCBbXSwgaGFzaF07CiAgICBidWlsZGVyLmR5bmFtaWNDb21wb25lbnQoZXhwciwgbnVsbCwgW10sIG51bGwsIGZhbHNlLCBudWxsLCBudWxsKTsKICAgIHJldHVybiB0cnVlOwogIH0KCiAgdmFyIER5bmFtaWNFbmdpbmVSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBEeW5hbWljRW5naW5lUmVmZXJlbmNlKG5hbWVSZWYsIGVudiwgbW9kZWxSZWYpIHsKICAgICAgdGhpcy50YWcgPSBuYW1lUmVmLnRhZzsKICAgICAgdGhpcy5uYW1lUmVmID0gbmFtZVJlZjsKICAgICAgdGhpcy5tb2RlbFJlZiA9IG1vZGVsUmVmOwogICAgICB0aGlzLmVudiA9IGVudjsKICAgICAgdGhpcy5fbGFzdE5hbWUgPSBudWxsOwogICAgICB0aGlzLl9sYXN0RGVmID0gbnVsbDsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjMgPSBEeW5hbWljRW5naW5lUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG82My52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICB2YXIgZW52ID0gdGhpcy5lbnYsCiAgICAgICAgICBuYW1lUmVmID0gdGhpcy5uYW1lUmVmLAogICAgICAgICAgbW9kZWxSZWYgPSB0aGlzLm1vZGVsUmVmOwogICAgICB2YXIgbmFtZSA9IG5hbWVSZWYudmFsdWUoKTsKCiAgICAgIGlmICh0eXBlb2YgbmFtZSA9PT0gJ3N0cmluZycpIHsKICAgICAgICBpZiAodGhpcy5fbGFzdE5hbWUgPT09IG5hbWUpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9sYXN0RGVmOwogICAgICAgIH0KCiAgICAgICAgKGZhbHNlICYmICEoZW52Lm93bmVyLmhhc1JlZ2lzdHJhdGlvbigiZW5naW5lOiIgKyBuYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgdXNlZCBge3ttb3VudCAnIiArIG5hbWUgKyAiJ319YCwgYnV0IHRoZSBlbmdpbmUgJyIgKyBuYW1lICsgIicgY2FuIG5vdCBiZSBmb3VuZC4iLCBlbnYub3duZXIuaGFzUmVnaXN0cmF0aW9uKCJlbmdpbmU6IiArIG5hbWUpKSk7CgogICAgICAgIGlmICghZW52Lm93bmVyLmhhc1JlZ2lzdHJhdGlvbigiZW5naW5lOiIgKyBuYW1lKSkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQoKICAgICAgICB0aGlzLl9sYXN0TmFtZSA9IG5hbWU7CiAgICAgICAgdGhpcy5fbGFzdERlZiA9ICgwLCBfcnVudGltZTIuY3VycnkpKG5ldyBNb3VudERlZmluaXRpb24obmFtZSwgbW9kZWxSZWYpKTsKICAgICAgICByZXR1cm4gdGhpcy5fbGFzdERlZjsKICAgICAgfSBlbHNlIHsKICAgICAgICAoZmFsc2UgJiYgIShuYW1lID09PSBudWxsIHx8IG5hbWUgPT09IHVuZGVmaW5lZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJJbnZhbGlkIGVuZ2luZSBuYW1lICciICsgbmFtZSArICInIHNwZWNpZmllZCwgZW5naW5lIG5hbWUgbXVzdCBiZSBlaXRoZXIgYSBzdHJpbmcsIG51bGwgb3IgdW5kZWZpbmVkLiIsIG5hbWUgPT09IG51bGwgfHwgbmFtZSA9PT0gdW5kZWZpbmVkKSk7CiAgICAgICAgdGhpcy5fbGFzdERlZiA9IG51bGw7CiAgICAgICAgdGhpcy5fbGFzdE5hbWUgPSBudWxsOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzYzLmdldCA9IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9ydW50aW1lMi5VTkRFRklORURfUkVGRVJFTkNFOwogICAgfTsKCiAgICByZXR1cm4gRHluYW1pY0VuZ2luZVJlZmVyZW5jZTsKICB9KCk7CiAgLyoqCiAgICogUmVwcmVzZW50cyB0aGUgcm9vdCBvdXRsZXQuCiAgICovCgoKICB2YXIgUm9vdE91dGxldFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJvb3RPdXRsZXRSZWZlcmVuY2Uob3V0bGV0U3RhdGUpIHsKICAgICAgdGhpcy5vdXRsZXRTdGF0ZSA9IG91dGxldFN0YXRlOwogICAgICB0aGlzLnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVRhZykoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjQgPSBSb290T3V0bGV0UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG82NC5nZXQgPSBmdW5jdGlvbiBnZXQoa2V5KSB7CiAgICAgIHJldHVybiBuZXcgUGF0aFJlZmVyZW5jZSh0aGlzLCBrZXkpOwogICAgfTsKCiAgICBfcHJvdG82NC52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICByZXR1cm4gdGhpcy5vdXRsZXRTdGF0ZTsKICAgIH07CgogICAgX3Byb3RvNjQudXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKHN0YXRlKSB7CiAgICAgIHRoaXMub3V0bGV0U3RhdGUub3V0bGV0cy5tYWluID0gc3RhdGU7CiAgICAgICgwLCBfcmVmZXJlbmNlLmRpcnR5KSh0aGlzLnRhZyk7CiAgICB9OwoKICAgIHJldHVybiBSb290T3V0bGV0UmVmZXJlbmNlOwogIH0oKTsKICAvKioKICAgKiBSZXByZXNlbnRzIHRoZSBjb25uZWN0ZWQgb3V0bGV0LgogICAqLwoKCiAgdmFyIE91dGxldFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIE91dGxldFJlZmVyZW5jZShwYXJlbnRTdGF0ZVJlZiwgb3V0bGV0TmFtZVJlZikgewogICAgICB0aGlzLnBhcmVudFN0YXRlUmVmID0gcGFyZW50U3RhdGVSZWY7CiAgICAgIHRoaXMub3V0bGV0TmFtZVJlZiA9IG91dGxldE5hbWVSZWY7CiAgICAgIHRoaXMudGFnID0gKDAsIF9yZWZlcmVuY2UuY29tYmluZSkoW3BhcmVudFN0YXRlUmVmLnRhZywgb3V0bGV0TmFtZVJlZi50YWddKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjUgPSBPdXRsZXRSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzY1LnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHZhciBvdXRsZXRTdGF0ZSA9IHRoaXMucGFyZW50U3RhdGVSZWYudmFsdWUoKTsKICAgICAgdmFyIG91dGxldHMgPSBvdXRsZXRTdGF0ZSA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogb3V0bGV0U3RhdGUub3V0bGV0czsKICAgICAgcmV0dXJuIG91dGxldHMgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IG91dGxldHNbdGhpcy5vdXRsZXROYW1lUmVmLnZhbHVlKCldOwogICAgfTsKCiAgICBfcHJvdG82NS5nZXQgPSBmdW5jdGlvbiBnZXQoa2V5KSB7CiAgICAgIHJldHVybiBuZXcgUGF0aFJlZmVyZW5jZSh0aGlzLCBrZXkpOwogICAgfTsKCiAgICByZXR1cm4gT3V0bGV0UmVmZXJlbmNlOwogIH0oKTsKICAvKioKICAgKiBPdXRsZXQgc3RhdGUgaXMgZGlydGllZCBmcm9tIHJvb3QuCiAgICogVGhpcyBqdXN0IHVzaW5nIHRoZSBwYXJlbnQgdGFnIGZvciBkaXJ0aW5lc3MuCiAgICovCgoKICB2YXIgUGF0aFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFBhdGhSZWZlcmVuY2UocGFyZW50LCBrZXkpIHsKICAgICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7CiAgICAgIHRoaXMua2V5ID0ga2V5OwogICAgICB0aGlzLnRhZyA9IHBhcmVudC50YWc7CiAgICB9CgogICAgdmFyIF9wcm90bzY2ID0gUGF0aFJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNjYuZ2V0ID0gZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICByZXR1cm4gbmV3IFBhdGhSZWZlcmVuY2UodGhpcywga2V5KTsKICAgIH07CgogICAgX3Byb3RvNjYudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgdmFyIHBhcmVudCA9IHRoaXMucGFyZW50LnZhbHVlKCk7CiAgICAgIHJldHVybiBwYXJlbnQgJiYgcGFyZW50W3RoaXMua2V5XTsKICAgIH07CgogICAgcmV0dXJuIFBhdGhSZWZlcmVuY2U7CiAgfSgpOwogIC8qKgogICAgVGhlIGB7e291dGxldH19YCBoZWxwZXIgbGV0cyB5b3Ugc3BlY2lmeSB3aGVyZSBhIGNoaWxkIHJvdXRlIHdpbGwgcmVuZGVyIGluCiAgICB5b3VyIHRlbXBsYXRlLiBBbiBpbXBvcnRhbnQgdXNlIG9mIHRoZSBge3tvdXRsZXR9fWAgaGVscGVyIGlzIGluIHlvdXIKICAgIGFwcGxpY2F0aW9uJ3MgYGFwcGxpY2F0aW9uLmhic2AgZmlsZToKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7ISBhcHAvdGVtcGxhdGVzL2FwcGxpY2F0aW9uLmhicyB9fQogICAgPCEtLSBoZWFkZXIgY29udGVudCBnb2VzIGhlcmUsIGFuZCB3aWxsIGFsd2F5cyBkaXNwbGF5IC0tPgogICAgPE15SGVhZGVyIC8+CiAgICA8ZGl2IGNsYXNzPSJteS1keW5hbWljLWNvbnRlbnQiPgogICAgICA8IS0tIHRoaXMgY29udGVudCB3aWxsIGNoYW5nZSBiYXNlZCBvbiB0aGUgY3VycmVudCByb3V0ZSwgd2hpY2ggZGVwZW5kcyBvbiB0aGUgY3VycmVudCBVUkwgLS0+CiAgICAgIHt7b3V0bGV0fX0KICAgIDwvZGl2PgogICAgPCEtLSBmb290ZXIgY29udGVudCBnb2VzIGhlcmUsIGFuZCB3aWxsIGFsd2F5cyBkaXNwbGF5IC0tPgogICAgPE15Rm9vdGVyIC8+CiAgICBgYGAKICAKICAgIFlvdSBtYXkgYWxzbyBzcGVjaWZ5IGEgbmFtZSBmb3IgdGhlIGB7e291dGxldH19YCwgd2hpY2ggaXMgdXNlZnVsIHdoZW4gdXNpbmcgbW9yZSB0aGFuIG9uZQogICAgYHt7b3V0bGV0fX1gIGluIGEgdGVtcGxhdGU6CiAgCiAgICBgYGBoYW5kbGViYXJzCiAgICB7e291dGxldCAibWVudSJ9fQogICAge3tvdXRsZXQgInNpZGViYXIifX0KICAgIHt7b3V0bGV0ICJtYWluIn19CiAgICBgYGAKICAKICAgIFlvdXIgcm91dGVzIGNhbiB0aGVuIHJlbmRlciBpbnRvIGEgc3BlY2lmaWMgb25lIG9mIHRoZXNlIGBvdXRsZXRgcyBieSBzcGVjaWZ5aW5nIHRoZSBgb3V0bGV0YAogICAgYXR0cmlidXRlIGluIHlvdXIgYHJlbmRlclRlbXBsYXRlYCBmdW5jdGlvbjoKICAKICAgIGBgYGFwcC9yb3V0ZXMvbWVudS5qcwogICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgIHJlbmRlclRlbXBsYXRlKCkgewogICAgICAgIHRoaXMucmVuZGVyKHsgb3V0bGV0OiAnbWVudScgfSk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBTZWUgdGhlIFtyb3V0aW5nIGd1aWRlXShodHRwczovL2d1aWRlcy5lbWJlcmpzLmNvbS9yZWxlYXNlL3JvdXRpbmcvcmVuZGVyaW5nLWEtdGVtcGxhdGUvKSBmb3IgbW9yZQogICAgaW5mb3JtYXRpb24gb24gaG93IHlvdXIgYHJvdXRlYCBpbnRlcmFjdHMgd2l0aCB0aGUgYHt7b3V0bGV0fX1gIGhlbHBlci4KICAgIE5vdGU6IFlvdXIgY29udGVudCBfX3dpbGwgbm90IHJlbmRlcl9fIGlmIHRoZXJlIGlzbid0IGFuIGB7e291dGxldH19YCBmb3IgaXQuCiAgCiAgICBAbWV0aG9kIG91dGxldAogICAgQHBhcmFtIHtTdHJpbmd9IFtuYW1lXQogICAgQGZvciBFbWJlci5UZW1wbGF0ZXMuaGVscGVycwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBvdXRsZXRIZWxwZXIodm0sIGFyZ3MpIHsKICAgIHZhciBzY29wZSA9IHZtLmR5bmFtaWNTY29wZSgpOwogICAgdmFyIG5hbWVSZWY7CgogICAgaWYgKGFyZ3MucG9zaXRpb25hbC5sZW5ndGggPT09IDApIHsKICAgICAgbmFtZVJlZiA9IG5ldyBfcmVmZXJlbmNlLkNvbnN0UmVmZXJlbmNlKCdtYWluJyk7CiAgICB9IGVsc2UgewogICAgICBuYW1lUmVmID0gYXJncy5wb3NpdGlvbmFsLmF0KDApOwogICAgfQoKICAgIHJldHVybiBuZXcgT3V0bGV0Q29tcG9uZW50UmVmZXJlbmNlKG5ldyBPdXRsZXRSZWZlcmVuY2Uoc2NvcGUub3V0bGV0U3RhdGUsIG5hbWVSZWYpKTsKICB9CgogIGZ1bmN0aW9uIG91dGxldE1hY3JvKF9uYW1lLCBwYXJhbXMsIGhhc2gsIGJ1aWxkZXIpIHsKICAgIHZhciBleHByID0gW193aXJlRm9ybWF0Lk9wcy5IZWxwZXIsICctb3V0bGV0JywgcGFyYW1zIHx8IFtdLCBoYXNoXTsKICAgIGJ1aWxkZXIuZHluYW1pY0NvbXBvbmVudChleHByLCBudWxsLCBbXSwgbnVsbCwgZmFsc2UsIG51bGwsIG51bGwpOwogICAgcmV0dXJuIHRydWU7CiAgfQoKICB2YXIgT3V0bGV0Q29tcG9uZW50UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gT3V0bGV0Q29tcG9uZW50UmVmZXJlbmNlKG91dGxldFJlZikgewogICAgICB0aGlzLm91dGxldFJlZiA9IG91dGxldFJlZjsKICAgICAgdGhpcy5kZWZpbml0aW9uID0gbnVsbDsKICAgICAgdGhpcy5sYXN0U3RhdGUgPSBudWxsOyAvLyBUaGUgcm91dGVyIGFsd2F5cyBkaXJ0aWVzIHRoZSByb290IHN0YXRlLgoKICAgICAgdGhpcy50YWcgPSBvdXRsZXRSZWYudGFnOwogICAgfQoKICAgIHZhciBfcHJvdG82NyA9IE91dGxldENvbXBvbmVudFJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNjcudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgdmFyIHN0YXRlID0gc3RhdGVGb3IodGhpcy5vdXRsZXRSZWYpOwoKICAgICAgaWYgKHZhbGlkYXRlJDEoc3RhdGUsIHRoaXMubGFzdFN0YXRlKSkgewogICAgICAgIHJldHVybiB0aGlzLmRlZmluaXRpb247CiAgICAgIH0KCiAgICAgIHRoaXMubGFzdFN0YXRlID0gc3RhdGU7CiAgICAgIHZhciBkZWZpbml0aW9uID0gbnVsbDsKCiAgICAgIGlmIChzdGF0ZSAhPT0gbnVsbCkgewogICAgICAgIGRlZmluaXRpb24gPSAoMCwgX3J1bnRpbWUyLmN1cnJ5KShuZXcgT3V0bGV0Q29tcG9uZW50RGVmaW5pdGlvbihzdGF0ZSkpOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5kZWZpbml0aW9uID0gZGVmaW5pdGlvbjsKICAgIH07CgogICAgX3Byb3RvNjcuZ2V0ID0gZnVuY3Rpb24gZ2V0KF9rZXkpIHsKICAgICAgcmV0dXJuIF9ydW50aW1lMi5VTkRFRklORURfUkVGRVJFTkNFOwogICAgfTsKCiAgICByZXR1cm4gT3V0bGV0Q29tcG9uZW50UmVmZXJlbmNlOwogIH0oKTsKCiAgZnVuY3Rpb24gc3RhdGVGb3IocmVmKSB7CiAgICB2YXIgb3V0bGV0ID0gcmVmLnZhbHVlKCk7CiAgICBpZiAob3V0bGV0ID09PSB1bmRlZmluZWQpIHJldHVybiBudWxsOwogICAgdmFyIHJlbmRlciA9IG91dGxldC5yZW5kZXI7CiAgICBpZiAocmVuZGVyID09PSB1bmRlZmluZWQpIHJldHVybiBudWxsOwogICAgdmFyIHRlbXBsYXRlJCQxID0gcmVuZGVyLnRlbXBsYXRlOwogICAgaWYgKHRlbXBsYXRlJCQxID09PSB1bmRlZmluZWQpIHJldHVybiBudWxsOyAvLyB0aGlzIGd1YXJkIGNhbiBiZSByZW1vdmVkIG9uY2UgQGVtYmVyL3Rlc3QtaGVscGVyc0AxLjYuMCBoYXMgImFnZWQgb3V0IgogICAgLy8gYW5kIGlzIG5vIGxvbmdlciBjb25zaWRlcmVkIHN1cHBvcnRlZAoKICAgIGlmIChpc1RlbXBsYXRlRmFjdG9yeSh0ZW1wbGF0ZSQkMSkpIHsKICAgICAgdGVtcGxhdGUkJDEgPSB0ZW1wbGF0ZSQkMShyZW5kZXIub3duZXIpOwogICAgfQoKICAgIHJldHVybiB7CiAgICAgIHJlZjogcmVmLAogICAgICBuYW1lOiByZW5kZXIubmFtZSwKICAgICAgb3V0bGV0OiByZW5kZXIub3V0bGV0LAogICAgICB0ZW1wbGF0ZTogdGVtcGxhdGUkJDEsCiAgICAgIGNvbnRyb2xsZXI6IHJlbmRlci5jb250cm9sbGVyCiAgICB9OwogIH0KCiAgZnVuY3Rpb24gdmFsaWRhdGUkMShzdGF0ZSwgbGFzdFN0YXRlKSB7CiAgICBpZiAoc3RhdGUgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIGxhc3RTdGF0ZSA9PT0gbnVsbDsKICAgIH0KCiAgICBpZiAobGFzdFN0YXRlID09PSBudWxsKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICByZXR1cm4gc3RhdGUudGVtcGxhdGUgPT09IGxhc3RTdGF0ZS50ZW1wbGF0ZSAmJiBzdGF0ZS5jb250cm9sbGVyID09PSBsYXN0U3RhdGUuY29udHJvbGxlcjsKICB9CgogIGZ1bmN0aW9uIHJlZmluZUlubGluZVN5bnRheChuYW1lLCBwYXJhbXMsIGhhc2gsIGJ1aWxkZXIpIHsKICAgIChmYWxzZSAmJiAhKCEoYnVpbGRlci5jb21waWxlclsncmVzb2x2ZXInXVsncmVzb2x2ZXInXVsnYnVpbHRJbkhlbHBlcnMnXVtuYW1lXSAmJiBidWlsZGVyLnJlZmVycmVyLm93bmVyLmhhc1JlZ2lzdHJhdGlvbigiaGVscGVyOiIgKyBuYW1lKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byBvdmVyd3JpdGUgdGhlIGJ1aWx0LWluIGhlbHBlciBcIiIgKyBuYW1lICsgIlwiIHdoaWNoIGlzIG5vdCBhbGxvd2VkLiBQbGVhc2UgcmVuYW1lIHRoZSBoZWxwZXIuIiwgIShidWlsZGVyLmNvbXBpbGVyWydyZXNvbHZlciddWydyZXNvbHZlciddWydidWlsdEluSGVscGVycyddW25hbWVdICYmIGJ1aWxkZXIucmVmZXJyZXIub3duZXIuaGFzUmVnaXN0cmF0aW9uKCJoZWxwZXI6IiArIG5hbWUpKSkpOwogICAgdmFyIGhhbmRsZSA9IGJ1aWxkZXIuY29tcGlsZXJbJ3Jlc29sdmVyJ10ubG9va3VwQ29tcG9uZW50RGVmaW5pdGlvbihuYW1lLCBidWlsZGVyLnJlZmVycmVyKTsKCiAgICBpZiAoaGFuZGxlICE9PSBudWxsKSB7CiAgICAgIGJ1aWxkZXIuY29tcG9uZW50LnN0YXRpYyhoYW5kbGUsIFtwYXJhbXMgPT09IG51bGwgPyBbXSA6IHBhcmFtcywgaGFzaFRvQXJncyhoYXNoKSwgbnVsbCwgbnVsbF0pOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICBmdW5jdGlvbiByZWZpbmVCbG9ja1N5bnRheChuYW1lLCBwYXJhbXMsIGhhc2gsIHRlbXBsYXRlLCBpbnZlcnNlLCBidWlsZGVyKSB7CiAgICB2YXIgaGFuZGxlID0gYnVpbGRlci5jb21waWxlclsncmVzb2x2ZXInXS5sb29rdXBDb21wb25lbnREZWZpbml0aW9uKG5hbWUsIGJ1aWxkZXIucmVmZXJyZXIpOwoKICAgIGlmIChoYW5kbGUgIT09IG51bGwpIHsKICAgICAgd3JhcENvbXBvbmVudENsYXNzQXR0cmlidXRlKGhhc2gpOwogICAgICBidWlsZGVyLmNvbXBvbmVudC5zdGF0aWMoaGFuZGxlLCBbcGFyYW1zLCBoYXNoVG9BcmdzKGhhc2gpLCB0ZW1wbGF0ZSwgaW52ZXJzZV0pOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICAoZmFsc2UgJiYgIShidWlsZGVyLnJlZmVycmVyLm93bmVyLmhhc1JlZ2lzdHJhdGlvbigiaGVscGVyOiIgKyBuYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJBIGNvbXBvbmVudCBvciBoZWxwZXIgbmFtZWQgXCIiICsgbmFtZSArICJcIiBjb3VsZCBub3QgYmUgZm91bmQiLCBidWlsZGVyLnJlZmVycmVyLm93bmVyLmhhc1JlZ2lzdHJhdGlvbigiaGVscGVyOiIgKyBuYW1lKSkpOwogICAgKGZhbHNlICYmICEoIWZ1bmN0aW9uICgpIHsKICAgICAgdmFyIHJlc29sdmVyID0gYnVpbGRlci5jb21waWxlclsncmVzb2x2ZXInXVsncmVzb2x2ZXInXTsKICAgICAgdmFyIF9idWlsZGVyJHJlZmVycmVyID0gYnVpbGRlci5yZWZlcnJlciwKICAgICAgICAgIG93bmVyID0gX2J1aWxkZXIkcmVmZXJyZXIub3duZXIsCiAgICAgICAgICBtb2R1bGVOYW1lID0gX2J1aWxkZXIkcmVmZXJyZXIubW9kdWxlTmFtZTsKCiAgICAgIGlmIChuYW1lID09PSAnY29tcG9uZW50JyB8fCByZXNvbHZlclsnYnVpbHRJbkhlbHBlcnMnXVtuYW1lXSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICB2YXIgb3B0aW9ucyA9IHsKICAgICAgICBzb3VyY2U6ICJ0ZW1wbGF0ZToiICsgbW9kdWxlTmFtZQogICAgICB9OwogICAgICByZXR1cm4gb3duZXIuaGFzUmVnaXN0cmF0aW9uKCJoZWxwZXI6IiArIG5hbWUsIG9wdGlvbnMpIHx8IG93bmVyLmhhc1JlZ2lzdHJhdGlvbigiaGVscGVyOiIgKyBuYW1lKTsKICAgIH0oKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJIZWxwZXJzIG1heSBub3QgYmUgdXNlZCBpbiB0aGUgYmxvY2sgZm9ybSwgZm9yIGV4YW1wbGUge3sjIiArIG5hbWUgKyAifX17ey8iICsgbmFtZSArICJ9fS4gUGxlYXNlIHVzZSBhIGNvbXBvbmVudCwgb3IgYWx0ZXJuYXRpdmVseSB1c2UgdGhlIGhlbHBlciBpbiBjb21iaW5hdGlvbiB3aXRoIGEgYnVpbHQtaW4gRW1iZXIgaGVscGVyLCBmb3IgZXhhbXBsZSB7eyNpZiAoIiArIG5hbWUgKyAiKX19e3svaWZ9fS4iLCAhZnVuY3Rpb24gKCkgewogICAgICB2YXIgcmVzb2x2ZXIgPSBidWlsZGVyLmNvbXBpbGVyWydyZXNvbHZlciddWydyZXNvbHZlciddOwogICAgICB2YXIgX2J1aWxkZXIkcmVmZXJyZXIgPSBidWlsZGVyLnJlZmVycmVyLAogICAgICAgICAgb3duZXIgPSBfYnVpbGRlciRyZWZlcnJlci5vd25lciwKICAgICAgICAgIG1vZHVsZU5hbWUgPSBfYnVpbGRlciRyZWZlcnJlci5tb2R1bGVOYW1lOwoKICAgICAgaWYgKG5hbWUgPT09ICdjb21wb25lbnQnIHx8IHJlc29sdmVyWydidWlsdEluSGVscGVycyddW25hbWVdKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KCiAgICAgIHZhciBvcHRpb25zID0gewogICAgICAgIHNvdXJjZTogInRlbXBsYXRlOiIgKyBtb2R1bGVOYW1lCiAgICAgIH07CiAgICAgIHJldHVybiBvd25lci5oYXNSZWdpc3RyYXRpb24oImhlbHBlcjoiICsgbmFtZSwgb3B0aW9ucykgfHwgb3duZXIuaGFzUmVnaXN0cmF0aW9uKCJoZWxwZXI6IiArIG5hbWUpOwogICAgfSgpKSk7CiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICB2YXIgZXhwZXJpbWVudGFsTWFjcm9zID0gW107IC8vIFRoaXMgaXMgYSBwcml2YXRlIEFQSSB0byBhbGxvdyBmb3IgZXhwZXJpbWVudGFsIG1hY3JvcwogIC8vIHRvIGJlIGNyZWF0ZWQgaW4gdXNlciBzcGFjZS4gUmVnaXN0ZXJpbmcgYSBtYWNybyBzaG91bGQKICAvLyBzaG91bGQgYmUgZG9uZSBpbiBhbiBpbml0aWFsaXplci4KCiAgX2V4cG9ydHMuX2V4cGVyaW1lbnRhbE1hY3JvcyA9IGV4cGVyaW1lbnRhbE1hY3JvczsKCiAgZnVuY3Rpb24gcmVnaXN0ZXJNYWNyb3MobWFjcm8pIHsKICAgIGV4cGVyaW1lbnRhbE1hY3Jvcy5wdXNoKG1hY3JvKTsKICB9CgogIGZ1bmN0aW9uIHBvcHVsYXRlTWFjcm9zKG1hY3JvcykgewogICAgdmFyIGlubGluZXMgPSBtYWNyb3MuaW5saW5lcywKICAgICAgICBibG9ja3MgPSBtYWNyb3MuYmxvY2tzOwogICAgaW5saW5lcy5hZGQoJ291dGxldCcsIG91dGxldE1hY3JvKTsKICAgIGlubGluZXMuYWRkKCdtb3VudCcsIG1vdW50TWFjcm8pOwogICAgaW5saW5lcy5hZGRNaXNzaW5nKHJlZmluZUlubGluZVN5bnRheCk7CiAgICBibG9ja3MuYWRkKCdsZXQnLCBibG9ja0xldE1hY3JvKTsKICAgIGJsb2Nrcy5hZGRNaXNzaW5nKHJlZmluZUJsb2NrU3ludGF4KTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV4cGVyaW1lbnRhbE1hY3Jvcy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgbWFjcm8gPSBleHBlcmltZW50YWxNYWNyb3NbaV07CiAgICAgIG1hY3JvKGJsb2NrcywgaW5saW5lcyk7CiAgICB9CgogICAgcmV0dXJuIHsKICAgICAgYmxvY2tzOiBibG9ja3MsCiAgICAgIGlubGluZXM6IGlubGluZXMKICAgIH07CiAgfQoKICB2YXIgVEVNUExBVEVTJDEgPSBuZXcgV2Vha01hcCgpOwogIHZhciBnZXRQcm90b3R5cGVPZiQxID0gT2JqZWN0LmdldFByb3RvdHlwZU9mOwoKICBmdW5jdGlvbiBzZXRDb21wb25lbnRUZW1wbGF0ZShmYWN0b3J5LCBvYmopIHsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gbnVsbCAmJiAodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IGNhbGwgYHNldENvbXBvbmVudFRlbXBsYXRlYCBvbiBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKG9iaikgKyAiYCIsIG9iaiAhPT0gbnVsbCAmJiAodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykpKTsKICAgIChmYWxzZSAmJiAhKCFURU1QTEFURVMkMS5oYXMob2JqKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJDYW5ub3QgY2FsbCBgc2V0Q29tcG9uZW50VGVtcGxhdGVgIG11bHRpcGxlIHRpbWVzIG9uIHRoZSBzYW1lIGNsYXNzIChgIiArIG9iaiArICJgKSIsICFURU1QTEFURVMkMS5oYXMob2JqKSkpOwogICAgVEVNUExBVEVTJDEuc2V0KG9iaiwgZmFjdG9yeSk7CiAgICByZXR1cm4gb2JqOwogIH0KCiAgZnVuY3Rpb24gZ2V0Q29tcG9uZW50VGVtcGxhdGUob2JqKSB7CiAgICB2YXIgcG9pbnRlciA9IG9iajsKCiAgICB3aGlsZSAocG9pbnRlciAhPT0gdW5kZWZpbmVkICYmIHBvaW50ZXIgIT09IG51bGwpIHsKICAgICAgdmFyIF90ZW1wbGF0ZSA9IFRFTVBMQVRFUyQxLmdldChwb2ludGVyKTsKCiAgICAgIGlmIChfdGVtcGxhdGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBfdGVtcGxhdGU7CiAgICAgIH0KCiAgICAgIHBvaW50ZXIgPSBnZXRQcm90b3R5cGVPZiQxKHBvaW50ZXIpOwogICAgfQoKICAgIHJldHVybiBudWxsOwogIH0KCiAgZnVuY3Rpb24gc2V0TW9kaWZpZXJNYW5hZ2VyKGZhY3RvcnksIG9iaikgewogICAgcmV0dXJuIHNldE1hbmFnZXIoewogICAgICBmYWN0b3J5OiBmYWN0b3J5LAogICAgICBpbnRlcm5hbDogZmFsc2UsCiAgICAgIHR5cGU6ICdtb2RpZmllcicKICAgIH0sIG9iaik7CiAgfQoKICBmdW5jdGlvbiBnZXRNb2RpZmllck1hbmFnZXIob2JqKSB7CiAgICB2YXIgd3JhcHBlciA9IGdldE1hbmFnZXIob2JqKTsKCiAgICBpZiAod3JhcHBlciAmJiAhd3JhcHBlci5pbnRlcm5hbCAmJiB3cmFwcGVyLnR5cGUgPT09ICdtb2RpZmllcicpIHsKICAgICAgcmV0dXJuIHdyYXBwZXIuZmFjdG9yeTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBpbnN0cnVtZW50YXRpb25QYXlsb2FkJDEobmFtZSkgewogICAgcmV0dXJuIHsKICAgICAgb2JqZWN0OiAiY29tcG9uZW50OiIgKyBuYW1lCiAgICB9OwogIH0KCiAgZnVuY3Rpb24gbWFrZU9wdGlvbnMobW9kdWxlTmFtZSwgbmFtZXNwYWNlKSB7CiAgICByZXR1cm4gewogICAgICBzb3VyY2U6IG1vZHVsZU5hbWUgIT09IHVuZGVmaW5lZCA/ICJ0ZW1wbGF0ZToiICsgbW9kdWxlTmFtZSA6IHVuZGVmaW5lZCwKICAgICAgbmFtZXNwYWNlOiBuYW1lc3BhY2UKICAgIH07CiAgfQoKICBmdW5jdGlvbiBjb21wb25lbnRGb3IobmFtZSwgb3duZXIsIG9wdGlvbnMpIHsKICAgIHZhciBmdWxsTmFtZSA9ICJjb21wb25lbnQ6IiArIG5hbWU7CiAgICByZXR1cm4gb3duZXIuZmFjdG9yeUZvcihmdWxsTmFtZSwgb3B0aW9ucykgfHwgbnVsbDsKICB9CgogIGZ1bmN0aW9uIGxheW91dEZvcihuYW1lLCBvd25lciwgb3B0aW9ucykgewogICAgdmFyIHRlbXBsYXRlRnVsbE5hbWUgPSAidGVtcGxhdGU6Y29tcG9uZW50cy8iICsgbmFtZTsKICAgIHJldHVybiBvd25lci5sb29rdXAodGVtcGxhdGVGdWxsTmFtZSwgb3B0aW9ucykgfHwgbnVsbDsKICB9CgogIGZ1bmN0aW9uIGxvb2t1cENvbXBvbmVudFBhaXIob3duZXIsIG5hbWUsIG9wdGlvbnMpIHsKICAgIHZhciBjb21wb25lbnQgPSBjb21wb25lbnRGb3IobmFtZSwgb3duZXIsIG9wdGlvbnMpOwogICAgewogICAgICBpZiAoY29tcG9uZW50ICE9PSBudWxsICYmIGNvbXBvbmVudC5jbGFzcyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdmFyIF9sYXlvdXQyID0gZ2V0Q29tcG9uZW50VGVtcGxhdGUoY29tcG9uZW50LmNsYXNzKTsKCiAgICAgICAgaWYgKF9sYXlvdXQyICE9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBjb21wb25lbnQ6IGNvbXBvbmVudCwKICAgICAgICAgICAgbGF5b3V0OiBfbGF5b3V0MgogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHZhciBsYXlvdXQgPSBsYXlvdXRGb3IobmFtZSwgb3duZXIsIG9wdGlvbnMpOwoKICAgIGlmIChjb21wb25lbnQgPT09IG51bGwgJiYgbGF5b3V0ID09PSBudWxsKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBjb21wb25lbnQ6IGNvbXBvbmVudCwKICAgICAgICBsYXlvdXQ6IGxheW91dAogICAgICB9OwogICAgfQogIH0KCiAgZnVuY3Rpb24gbG9va3VwQ29tcG9uZW50KG93bmVyLCBuYW1lLCBvcHRpb25zKSB7CiAgICBpZiAob3B0aW9ucy5zb3VyY2UgfHwgb3B0aW9ucy5uYW1lc3BhY2UpIHsKICAgICAgdmFyIHBhaXIgPSBsb29rdXBDb21wb25lbnRQYWlyKG93bmVyLCBuYW1lLCBvcHRpb25zKTsKCiAgICAgIGlmIChwYWlyICE9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIHBhaXI7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gbG9va3VwQ29tcG9uZW50UGFpcihvd25lciwgbmFtZSk7CiAgfQoKICB2YXIgQlVJTFRJTlNfSEVMUEVSUyA9IHsKICAgIGlmOiBpbmxpbmVJZiwKICAgIGFjdGlvbjogYWN0aW9uLAogICAgYXJyYXk6IGFycmF5LAogICAgY29uY2F0OiBjb25jYXQkMSwKICAgIGdldDogZ2V0JDEsCiAgICBoYXNoOiBoYXNoLAogICAgbG9nOiBsb2ckMSwKICAgIG11dDogbXV0LAogICAgJ3F1ZXJ5LXBhcmFtcyc6IHF1ZXJ5UGFyYW1zJDEsCiAgICByZWFkb25seTogcmVhZG9ubHksCiAgICB1bmJvdW5kOiB1bmJvdW5kLAogICAgdW5sZXNzOiBpbmxpbmVVbmxlc3MsCiAgICAnLWNsYXNzJzogY2xhc3NIZWxwZXIkMSwKICAgICctZWFjaC1pbic6IGVhY2hJbiwKICAgICctaW5wdXQtdHlwZSc6IGlucHV0VHlwZUhlbHBlciQxLAogICAgJy1ub3JtYWxpemUtY2xhc3MnOiBub3JtYWxpemVDbGFzc0hlbHBlciwKICAgICctZ2V0LWR5bmFtaWMtdmFyJzogX3J1bnRpbWUyLmdldER5bmFtaWNWYXIsCiAgICAnLW1vdW50JzogbW91bnRIZWxwZXIsCiAgICAnLW91dGxldCc6IG91dGxldEhlbHBlciwKICAgICctYXNzZXJ0LWltcGxpY2l0LWNvbXBvbmVudC1oZWxwZXItYXJndW1lbnQnOiBjb21wb25lbnRBc3NlcnRpb25IZWxwZXIsCiAgICBmbjogdW5kZWZpbmVkCiAgfTsKICB7CiAgICBCVUlMVElOU19IRUxQRVJTLmZuID0gZm47CiAgfQoKICB2YXIgUnVudGltZVJlc29sdmVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUnVudGltZVJlc29sdmVyKGlzSW50ZXJhY3RpdmUpIHsKICAgICAgdGhpcy5oYW5kbGVzID0gW3VuZGVmaW5lZF07CiAgICAgIHRoaXMub2JqVG9IYW5kbGUgPSBuZXcgV2Vha01hcCgpOwogICAgICB0aGlzLmJ1aWx0SW5IZWxwZXJzID0gQlVJTFRJTlNfSEVMUEVSUzsKICAgICAgdGhpcy5jb21wb25lbnREZWZpbml0aW9uQ2FjaGUgPSBuZXcgTWFwKCk7CiAgICAgIHRoaXMuY29tcG9uZW50RGVmaW5pdGlvbkNvdW50ID0gMDsKICAgICAgdGhpcy5oZWxwZXJEZWZpbml0aW9uQ291bnQgPSAwOwogICAgICB2YXIgbWFjcm9zID0gbmV3IF9vcGNvZGVDb21waWxlci5NYWNyb3MoKTsKICAgICAgcG9wdWxhdGVNYWNyb3MobWFjcm9zKTsKICAgICAgdGhpcy5jb21waWxlciA9IG5ldyBfb3Bjb2RlQ29tcGlsZXIuTGF6eUNvbXBpbGVyKG5ldyBDb21waWxlVGltZUxvb2t1cCh0aGlzKSwgdGhpcywgbWFjcm9zKTsKICAgICAgdGhpcy5pc0ludGVyYWN0aXZlID0gaXNJbnRlcmFjdGl2ZTsKICAgICAgdGhpcy5idWlsdEluTW9kaWZpZXJzID0gewogICAgICAgIGFjdGlvbjogewogICAgICAgICAgbWFuYWdlcjogbmV3IEFjdGlvbk1vZGlmaWVyTWFuYWdlcigpLAogICAgICAgICAgc3RhdGU6IG51bGwKICAgICAgICB9LAogICAgICAgIG9uOiB7CiAgICAgICAgICBtYW5hZ2VyOiBuZXcgT25Nb2RpZmllck1hbmFnZXIoaXNJbnRlcmFjdGl2ZSksCiAgICAgICAgICBzdGF0ZTogbnVsbAogICAgICAgIH0KICAgICAgfTsKICAgIH0KICAgIC8qKiogIElSdW50aW1lUmVzb2x2ZXIgKioqLwoKICAgIC8qKgogICAgICogcHVibGljIGNvbXBvbmVudERlZkhhbmRsZUNvdW50ID0gMDsKICAgICAqIENhbGxlZCB3aGlsZSBleGVjdXRpbmcgQXBwZW5kIE9wLlB1c2hEeW5hbWljQ29tcG9uZW50TWFuYWdlciBpZiBzdHJpbmcKICAgICAqLwoKCiAgICB2YXIgX3Byb3RvNjggPSBSdW50aW1lUmVzb2x2ZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzY4Lmxvb2t1cENvbXBvbmVudERlZmluaXRpb24gPSBmdW5jdGlvbiBsb29rdXBDb21wb25lbnREZWZpbml0aW9uKG5hbWUsIG1ldGEpIHsKICAgICAgdmFyIGhhbmRsZSA9IHRoaXMubG9va3VwQ29tcG9uZW50SGFuZGxlKG5hbWUsIG1ldGEpOwoKICAgICAgaWYgKGhhbmRsZSA9PT0gbnVsbCkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkNvdWxkIG5vdCBmaW5kIGNvbXBvbmVudCBuYW1lZCBcIiIgKyBuYW1lICsgIlwiIChubyBjb21wb25lbnQgb3IgdGVtcGxhdGUgd2l0aCB0aGF0IG5hbWUgd2FzIGZvdW5kKSIpKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZShoYW5kbGUpOwogICAgfTsKCiAgICBfcHJvdG82OC5sb29rdXBDb21wb25lbnRIYW5kbGUgPSBmdW5jdGlvbiBsb29rdXBDb21wb25lbnRIYW5kbGUobmFtZSwgbWV0YSkgewogICAgICB2YXIgbmV4dEhhbmRsZSA9IHRoaXMuaGFuZGxlcy5sZW5ndGg7CiAgICAgIHZhciBoYW5kbGUgPSB0aGlzLmhhbmRsZSh0aGlzLl9sb29rdXBDb21wb25lbnREZWZpbml0aW9uKG5hbWUsIG1ldGEpKTsKICAgICAgKGZhbHNlICYmICEoISh0cnVlCiAgICAgIC8qIEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMgKi8KICAgICAgJiYgbmFtZSA9PT0gJ3RleHQtYXJlYScgJiYgaGFuZGxlID09PSBudWxsKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdDb3VsZCBub3QgZmluZCBjb21wb25lbnQgYDxUZXh0QXJlYSAvPmAgKGRpZCB5b3UgbWVhbiBgPFRleHRhcmVhIC8+YD8pJywgISh0cnVlICYmIG5hbWUgPT09ICd0ZXh0LWFyZWEnICYmIGhhbmRsZSA9PT0gbnVsbCkpKTsKCiAgICAgIGlmIChuZXh0SGFuZGxlID09PSBoYW5kbGUpIHsKICAgICAgICB0aGlzLmNvbXBvbmVudERlZmluaXRpb25Db3VudCsrOwogICAgICB9CgogICAgICByZXR1cm4gaGFuZGxlOwogICAgfQogICAgLyoqCiAgICAgKiBDYWxsZWQgYnkgUnVudGltZUNvbnN0YW50cyB0byBsb29rdXAgdW5yZXNvbHZlZCBoYW5kbGVzLgogICAgICovCiAgICA7CgogICAgX3Byb3RvNjgucmVzb2x2ZSA9IGZ1bmN0aW9uIHJlc29sdmUoaGFuZGxlKSB7CiAgICAgIHJldHVybiB0aGlzLmhhbmRsZXNbaGFuZGxlXTsKICAgIH0gLy8gRW5kIElSdW50aW1lUmVzb2x2ZXIKCiAgICAvKioKICAgICAqIENhbGxlZCBieSBDb21waWxlVGltZUxvb2t1cCBjb21waWxpbmcgVW5rbm93biBvciBIZWxwZXIgT3BDb2RlCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG82OC5sb29rdXBIZWxwZXIgPSBmdW5jdGlvbiBsb29rdXBIZWxwZXIobmFtZSwgbWV0YSkgewogICAgICB2YXIgbmV4dEhhbmRsZSA9IHRoaXMuaGFuZGxlcy5sZW5ndGg7CgogICAgICB2YXIgaGVscGVyJCQxID0gdGhpcy5fbG9va3VwSGVscGVyKG5hbWUsIG1ldGEpOwoKICAgICAgaWYgKGhlbHBlciQkMSAhPT0gbnVsbCkgewogICAgICAgIHZhciBoYW5kbGUgPSB0aGlzLmhhbmRsZShoZWxwZXIkJDEpOwoKICAgICAgICBpZiAobmV4dEhhbmRsZSA9PT0gaGFuZGxlKSB7CiAgICAgICAgICB0aGlzLmhlbHBlckRlZmluaXRpb25Db3VudCsrOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGhhbmRsZTsKICAgICAgfQoKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICAvKioKICAgICAqIENhbGxlZCBieSBDb21waWxlVGltZUxvb2t1cCBjb21waWxpbmcgdGhlCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG82OC5sb29rdXBNb2RpZmllciA9IGZ1bmN0aW9uIGxvb2t1cE1vZGlmaWVyKG5hbWUsIG1ldGEpIHsKICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlKHRoaXMuX2xvb2t1cE1vZGlmaWVyKG5hbWUsIG1ldGEpKTsKICAgIH0KICAgIC8qKgogICAgICogQ2FsbGVkIGJ5IENvbXBpbGVUaW1lTG9va3VwIHRvIGxvb2t1cCBwYXJ0aWFsCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG82OC5sb29rdXBQYXJ0aWFsID0gZnVuY3Rpb24gbG9va3VwUGFydGlhbChuYW1lLCBtZXRhKSB7CiAgICAgIHZhciBwYXJ0aWFsID0gdGhpcy5fbG9va3VwUGFydGlhbChuYW1lLCBtZXRhKTsKCiAgICAgIHJldHVybiB0aGlzLmhhbmRsZShwYXJ0aWFsKTsKICAgIH0gLy8gZW5kIENvbXBpbGVUaW1lTG9va3VwCiAgICAvLyBuZWVkZWQgZm9yIGxhenkgY29tcGlsZSB0aW1lIGxvb2t1cAogICAgOwoKICAgIF9wcm90bzY4LmhhbmRsZSA9IGZ1bmN0aW9uIGhhbmRsZShvYmopIHsKICAgICAgaWYgKG9iaiA9PT0gdW5kZWZpbmVkIHx8IG9iaiA9PT0gbnVsbCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgaGFuZGxlID0gdGhpcy5vYmpUb0hhbmRsZS5nZXQob2JqKTsKCiAgICAgIGlmIChoYW5kbGUgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGhhbmRsZSA9IHRoaXMuaGFuZGxlcy5wdXNoKG9iaikgLSAxOwogICAgICAgIHRoaXMub2JqVG9IYW5kbGUuc2V0KG9iaiwgaGFuZGxlKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGhhbmRsZTsKICAgIH07CgogICAgX3Byb3RvNjguX2xvb2t1cEhlbHBlciA9IGZ1bmN0aW9uIF9sb29rdXBIZWxwZXIoX25hbWUsIG1ldGEpIHsKICAgICAgdmFyIGhlbHBlciQkMSA9IHRoaXMuYnVpbHRJbkhlbHBlcnNbX25hbWVdOwoKICAgICAgaWYgKGhlbHBlciQkMSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIGhlbHBlciQkMTsKICAgICAgfQoKICAgICAgdmFyIG93bmVyID0gbWV0YS5vd25lciwKICAgICAgICAgIG1vZHVsZU5hbWUgPSBtZXRhLm1vZHVsZU5hbWU7CiAgICAgIHZhciBuYW1lID0gX25hbWU7CiAgICAgIHZhciBuYW1lc3BhY2UgPSB1bmRlZmluZWQ7CiAgICAgIHZhciBvcHRpb25zID0gbWFrZU9wdGlvbnMobW9kdWxlTmFtZSwgbmFtZXNwYWNlKTsKICAgICAgdmFyIGZhY3RvcnkgPSBvd25lci5mYWN0b3J5Rm9yKCJoZWxwZXI6IiArIG5hbWUsIG9wdGlvbnMpIHx8IG93bmVyLmZhY3RvcnlGb3IoImhlbHBlcjoiICsgbmFtZSk7CgogICAgICBpZiAoIWlzSGVscGVyRmFjdG9yeShmYWN0b3J5KSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICByZXR1cm4gZnVuY3Rpb24gKHZtLCBhcmdzKSB7CiAgICAgICAgdmFyIGhlbHBlciQkMSA9IGZhY3RvcnkuY3JlYXRlKCk7CgogICAgICAgIGlmIChpc1NpbXBsZUhlbHBlcihoZWxwZXIkJDEpKSB7CiAgICAgICAgICByZXR1cm4gU2ltcGxlSGVscGVyUmVmZXJlbmNlLmNyZWF0ZShoZWxwZXIkJDEuY29tcHV0ZSwgYXJncy5jYXB0dXJlKCkpOwogICAgICAgIH0KCiAgICAgICAgdm0ubmV3RGVzdHJveWFibGUoaGVscGVyJCQxKTsKICAgICAgICByZXR1cm4gQ2xhc3NCYXNlZEhlbHBlclJlZmVyZW5jZS5jcmVhdGUoaGVscGVyJCQxLCBhcmdzLmNhcHR1cmUoKSk7CiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzY4Ll9sb29rdXBQYXJ0aWFsID0gZnVuY3Rpb24gX2xvb2t1cFBhcnRpYWwobmFtZSwgbWV0YSkgewogICAgICB2YXIgdGVtcGxhdGVGYWN0b3J5JCQxID0gKDAsIF92aWV3cy5sb29rdXBQYXJ0aWFsKShuYW1lLCBtZXRhLm93bmVyKTsKICAgICAgdmFyIHRlbXBsYXRlID0gdGVtcGxhdGVGYWN0b3J5JCQxKG1ldGEub3duZXIpOwogICAgICByZXR1cm4gbmV3IF9vcGNvZGVDb21waWxlci5QYXJ0aWFsRGVmaW5pdGlvbihuYW1lLCB0ZW1wbGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzY4Ll9sb29rdXBNb2RpZmllciA9IGZ1bmN0aW9uIF9sb29rdXBNb2RpZmllcihuYW1lLCBtZXRhKSB7CiAgICAgIHZhciBidWlsdGluID0gdGhpcy5idWlsdEluTW9kaWZpZXJzW25hbWVdOwoKICAgICAgaWYgKGJ1aWx0aW4gPT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhciBvd25lciA9IG1ldGEub3duZXI7CiAgICAgICAgdmFyIG1vZGlmaWVyID0gb3duZXIuZmFjdG9yeUZvcigibW9kaWZpZXI6IiArIG5hbWUpOwoKICAgICAgICBpZiAobW9kaWZpZXIgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdmFyIG1hbmFnZXJGYWN0b3J5ID0gZ2V0TW9kaWZpZXJNYW5hZ2VyKG1vZGlmaWVyLmNsYXNzKTsKICAgICAgICAgIHZhciBtYW5hZ2VyID0gbWFuYWdlckZhY3Rvcnkob3duZXIpOwogICAgICAgICAgcmV0dXJuIG5ldyBDdXN0b21Nb2RpZmllckRlZmluaXRpb24obmFtZSwgbW9kaWZpZXIsIG1hbmFnZXIsIHRoaXMuaXNJbnRlcmFjdGl2ZSk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gYnVpbHRpbjsKICAgIH07CgogICAgX3Byb3RvNjguX3BhcnNlTmFtZUZvck5hbWVzcGFjZSA9IGZ1bmN0aW9uIF9wYXJzZU5hbWVGb3JOYW1lc3BhY2UoX25hbWUpIHsKICAgICAgdmFyIG5hbWUgPSBfbmFtZTsKICAgICAgdmFyIG5hbWVzcGFjZSA9IHVuZGVmaW5lZDsKCiAgICAgIHZhciBuYW1lc3BhY2VEZWxpbWl0ZXJPZmZzZXQgPSBfbmFtZS5pbmRleE9mKCc6OicpOwoKICAgICAgaWYgKG5hbWVzcGFjZURlbGltaXRlck9mZnNldCAhPT0gLTEpIHsKICAgICAgICBuYW1lID0gX25hbWUuc2xpY2UobmFtZXNwYWNlRGVsaW1pdGVyT2Zmc2V0ICsgMik7CiAgICAgICAgbmFtZXNwYWNlID0gX25hbWUuc2xpY2UoMCwgbmFtZXNwYWNlRGVsaW1pdGVyT2Zmc2V0KTsKICAgICAgfQoKICAgICAgcmV0dXJuIHsKICAgICAgICBuYW1lOiBuYW1lLAogICAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzY4Ll9sb29rdXBDb21wb25lbnREZWZpbml0aW9uID0gZnVuY3Rpb24gX2xvb2t1cENvbXBvbmVudERlZmluaXRpb24oX25hbWUsIF9yZWYzNikgewogICAgICB2YXIgbW9kdWxlTmFtZSA9IF9yZWYzNi5tb2R1bGVOYW1lLAogICAgICAgICAgb3duZXIgPSBfcmVmMzYub3duZXI7CiAgICAgIChmYWxzZSAmJiAhKHRydWUKICAgICAgLyogRU1CRVJfR0xJTU1FUl9BTkdMRV9CUkFDS0VUX0JVSUxUX0lOUyAqLwogICAgICB8fCBfbmFtZSAhPT0gJ3RleHRhcmVhJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdJbnZva2luZyBge3t0ZXh0YXJlYX19YCB1c2luZyBhbmdsZSBicmFja2V0IHN5bnRheCBvciBgY29tcG9uZW50YCBoZWxwZXIgaXMgbm90IHlldCBzdXBwb3J0ZWQuJywgdHJ1ZSB8fCBfbmFtZSAhPT0gJ3RleHRhcmVhJykpOwogICAgICAoZmFsc2UgJiYgISh0cnVlCiAgICAgIC8qIEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMgKi8KICAgICAgfHwgX25hbWUgIT09ICdpbnB1dCcpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnSW52b2tpbmcgYHt7aW5wdXR9fWAgdXNpbmcgYW5nbGUgYnJhY2tldCBzeW50YXggb3IgYGNvbXBvbmVudGAgaGVscGVyIGlzIG5vdCB5ZXQgc3VwcG9ydGVkLicsIHRydWUgfHwgX25hbWUgIT09ICdpbnB1dCcpKTsKICAgICAgdmFyIG5hbWUgPSBfbmFtZTsKICAgICAgdmFyIG5hbWVzcGFjZSA9IHVuZGVmaW5lZDsKICAgICAgdmFyIHBhaXIgPSBsb29rdXBDb21wb25lbnQob3duZXIsIG5hbWUsIG1ha2VPcHRpb25zKG1vZHVsZU5hbWUsIG5hbWVzcGFjZSkpOwoKICAgICAgaWYgKHBhaXIgPT09IG51bGwpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIGxheW91dCA9IG51bGw7CiAgICAgIHZhciBrZXk7CgogICAgICBpZiAocGFpci5jb21wb25lbnQgPT09IG51bGwpIHsKICAgICAgICBrZXkgPSBsYXlvdXQgPSBwYWlyLmxheW91dChvd25lcik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAga2V5ID0gcGFpci5jb21wb25lbnQ7CiAgICAgIH0KCiAgICAgIHZhciBjYWNoZWRDb21wb25lbnREZWZpbml0aW9uID0gdGhpcy5jb21wb25lbnREZWZpbml0aW9uQ2FjaGUuZ2V0KGtleSk7CgogICAgICBpZiAoY2FjaGVkQ29tcG9uZW50RGVmaW5pdGlvbiAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIGNhY2hlZENvbXBvbmVudERlZmluaXRpb247CiAgICAgIH0KCiAgICAgIGlmIChsYXlvdXQgPT09IG51bGwgJiYgcGFpci5sYXlvdXQgIT09IG51bGwpIHsKICAgICAgICBsYXlvdXQgPSBwYWlyLmxheW91dChvd25lcik7CiAgICAgIH0KCiAgICAgIHZhciBmaW5hbGl6ZXIgPSAoMCwgX2luc3RydW1lbnRhdGlvbi5faW5zdHJ1bWVudFN0YXJ0KSgncmVuZGVyLmdldENvbXBvbmVudERlZmluaXRpb24nLCBpbnN0cnVtZW50YXRpb25QYXlsb2FkJDEsIG5hbWUpOwogICAgICB2YXIgZGVmaW5pdGlvbiA9IG51bGw7CgogICAgICBpZiAocGFpci5jb21wb25lbnQgPT09IG51bGwpIHsKICAgICAgICBpZiAoX2Vudmlyb25tZW50Mi5FTlYuX1RFTVBMQVRFX09OTFlfR0xJTU1FUl9DT01QT05FTlRTKSB7CiAgICAgICAgICBkZWZpbml0aW9uID0gbmV3IFRlbXBsYXRlT25seUNvbXBvbmVudERlZmluaXRpb24obGF5b3V0KTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAodHJ1ZQogICAgICAvKiBFTUJFUl9HTElNTUVSX1NFVF9DT01QT05FTlRfVEVNUExBVEUgKi8KICAgICAgJiYgKDAsIF90ZW1wbGF0ZU9ubHkuaXNUZW1wbGF0ZU9ubHlDb21wb25lbnQpKHBhaXIuY29tcG9uZW50LmNsYXNzKSkgewogICAgICAgIGRlZmluaXRpb24gPSBuZXcgVGVtcGxhdGVPbmx5Q29tcG9uZW50RGVmaW5pdGlvbihsYXlvdXQpOwogICAgICB9CgogICAgICBpZiAocGFpci5jb21wb25lbnQgIT09IG51bGwpIHsKICAgICAgICAoZmFsc2UgJiYgIShwYWlyLmNvbXBvbmVudC5jbGFzcyAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIm1pc3NpbmcgY29tcG9uZW50IGNsYXNzICIgKyBuYW1lLCBwYWlyLmNvbXBvbmVudC5jbGFzcyAhPT0gdW5kZWZpbmVkKSk7CiAgICAgICAgdmFyIENvbXBvbmVudENsYXNzID0gcGFpci5jb21wb25lbnQuY2xhc3M7CiAgICAgICAgdmFyIHdyYXBwZXIgPSBnZXRNYW5hZ2VyKENvbXBvbmVudENsYXNzKTsKCiAgICAgICAgaWYgKHdyYXBwZXIgIT09IG51bGwgJiYgd3JhcHBlci50eXBlID09PSAnY29tcG9uZW50JykgewogICAgICAgICAgdmFyIGZhY3RvcnkgPSB3cmFwcGVyLmZhY3Rvcnk7CgogICAgICAgICAgaWYgKHdyYXBwZXIuaW50ZXJuYWwpIHsKICAgICAgICAgICAgKGZhbHNlICYmICEocGFpci5sYXlvdXQgIT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgibWlzc2luZyBsYXlvdXQgZm9yIGludGVybmFsIGNvbXBvbmVudCAiICsgbmFtZSwgcGFpci5sYXlvdXQgIT09IG51bGwpKTsKICAgICAgICAgICAgZGVmaW5pdGlvbiA9IG5ldyBJbnRlcm5hbENvbXBvbmVudERlZmluaXRpb24oZmFjdG9yeShvd25lciksIENvbXBvbmVudENsYXNzLCBsYXlvdXQpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZGVmaW5pdGlvbiA9IG5ldyBDdXN0b21NYW5hZ2VyRGVmaW5pdGlvbihuYW1lLCBwYWlyLmNvbXBvbmVudCwgZmFjdG9yeShvd25lciksIGxheW91dCAhPT0gbnVsbCA/IGxheW91dCA6IG93bmVyLmxvb2t1cCgoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdDMoKSkpKG93bmVyKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoZGVmaW5pdGlvbiA9PT0gbnVsbCkgewogICAgICAgIGRlZmluaXRpb24gPSBuZXcgQ3VybHlDb21wb25lbnREZWZpbml0aW9uKG5hbWUsIHBhaXIuY29tcG9uZW50IHx8IG93bmVyLmZhY3RvcnlGb3IoKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3Q0KCkpKSwgbnVsbCwgbGF5b3V0KTsKICAgICAgfQoKICAgICAgZmluYWxpemVyKCk7CiAgICAgIHRoaXMuY29tcG9uZW50RGVmaW5pdGlvbkNhY2hlLnNldChrZXksIGRlZmluaXRpb24pOwogICAgICByZXR1cm4gZGVmaW5pdGlvbjsKICAgIH07CgogICAgcmV0dXJuIFJ1bnRpbWVSZXNvbHZlcjsKICB9KCk7CgogIHZhciBUZW1wbGF0ZUNvbXBpbGVyID0gewogICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUoX3JlZjM3KSB7CiAgICAgIHZhciBlbnZpcm9ubWVudCA9IF9yZWYzNy5lbnZpcm9ubWVudDsKICAgICAgcmV0dXJuIG5ldyBSdW50aW1lUmVzb2x2ZXIoZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZSkuY29tcGlsZXI7CiAgICB9CiAgfTsKICB2YXIgQ29tcG9uZW50VGVtcGxhdGUgPSB0ZW1wbGF0ZSh7CiAgICAiaWQiOiAiY2hmUWNIODMiLAogICAgImJsb2NrIjogIntcInN5bWJvbHNcIjpbXCImZGVmYXVsdFwiXSxcInN0YXRlbWVudHNcIjpbWzE0LDFdXSxcImhhc0V2YWxcIjpmYWxzZX0iLAogICAgIm1ldGEiOiB7CiAgICAgICJtb2R1bGVOYW1lIjogInBhY2thZ2VzL0BlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIvbGliL3RlbXBsYXRlcy9jb21wb25lbnQuaGJzIgogICAgfQogIH0pOwogIHZhciBJbnB1dFRlbXBsYXRlID0gdGVtcGxhdGUoewogICAgImlkIjogIk5XWnpMU0lJIiwKICAgICJibG9jayI6ICJ7XCJzeW1ib2xzXCI6W1wiQ2hlY2tib3hcIixcIlRleHRGaWVsZFwiLFwiQF9fQVJHU19fXCIsXCImYXR0cnNcIl0sXCJzdGF0ZW1lbnRzXCI6W1s0LFwibGV0XCIsW1syOCxcImNvbXBvbmVudFwiLFtcIi1jaGVja2JveFwiXSxudWxsXSxbMjgsXCJjb21wb25lbnRcIixbXCItdGV4dC1maWVsZFwiXSxudWxsXV0sbnVsbCx7XCJzdGF0ZW1lbnRzXCI6W1s0LFwiaWZcIixbWzIzLDAsW1wiaXNDaGVja2JveFwiXV1dLG51bGwse1wic3RhdGVtZW50c1wiOltbNixbMjMsMSxbXV0sW1sxMyw0XV0sW1tcIkB0YXJnZXRcIixcIkBfX0FSR1NfX1wiXSxbWzIzLDAsW1wiY2FsbGVyXCJdXSxbMjMsMyxbXV1dXV1dLFwicGFyYW1ldGVyc1wiOltdfSx7XCJzdGF0ZW1lbnRzXCI6W1s2LFsyMywyLFtdXSxbWzEzLDRdXSxbW1wiQHRhcmdldFwiLFwiQF9fQVJHU19fXCJdLFtbMjMsMCxbXCJjYWxsZXJcIl1dLFsyMywzLFtdXV1dXV0sXCJwYXJhbWV0ZXJzXCI6W119XV0sXCJwYXJhbWV0ZXJzXCI6WzEsMl19LG51bGxdXSxcImhhc0V2YWxcIjpmYWxzZX0iLAogICAgIm1ldGEiOiB7CiAgICAgICJtb2R1bGVOYW1lIjogInBhY2thZ2VzL0BlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIvbGliL3RlbXBsYXRlcy9pbnB1dC5oYnMiCiAgICB9CiAgfSk7CiAgdmFyIE91dGxldFRlbXBsYXRlID0gdGVtcGxhdGUoewogICAgImlkIjogImZmQUw2SERsIiwKICAgICJibG9jayI6ICJ7XCJzeW1ib2xzXCI6W10sXCJzdGF0ZW1lbnRzXCI6W1sxLFsyMixcIm91dGxldFwiXSxmYWxzZV1dLFwiaGFzRXZhbFwiOmZhbHNlfSIsCiAgICAibWV0YSI6IHsKICAgICAgIm1vZHVsZU5hbWUiOiAicGFja2FnZXMvQGVtYmVyLy1pbnRlcm5hbHMvZ2xpbW1lci9saWIvdGVtcGxhdGVzL291dGxldC5oYnMiCiAgICB9CiAgfSk7CiAgdmFyIFRPUF9MRVZFTF9OQU1FID0gJy10b3AtbGV2ZWwnOwogIHZhciBUT1BfTEVWRUxfT1VUTEVUID0gJ21haW4nOwoKICB2YXIgT3V0bGV0VmlldyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIE91dGxldFZpZXcoX2Vudmlyb25tZW50LCByZW5kZXJlciwgb3duZXIsIHRlbXBsYXRlKSB7CiAgICAgIHRoaXMuX2Vudmlyb25tZW50ID0gX2Vudmlyb25tZW50OwogICAgICB0aGlzLnJlbmRlcmVyID0gcmVuZGVyZXI7CiAgICAgIHRoaXMub3duZXIgPSBvd25lcjsKICAgICAgdGhpcy50ZW1wbGF0ZSA9IHRlbXBsYXRlOwogICAgICB2YXIgcmVmID0gdGhpcy5yZWYgPSBuZXcgUm9vdE91dGxldFJlZmVyZW5jZSh7CiAgICAgICAgb3V0bGV0czogewogICAgICAgICAgbWFpbjogdW5kZWZpbmVkCiAgICAgICAgfSwKICAgICAgICByZW5kZXI6IHsKICAgICAgICAgIG93bmVyOiBvd25lciwKICAgICAgICAgIGludG86IHVuZGVmaW5lZCwKICAgICAgICAgIG91dGxldDogVE9QX0xFVkVMX09VVExFVCwKICAgICAgICAgIG5hbWU6IFRPUF9MRVZFTF9OQU1FLAogICAgICAgICAgY29udHJvbGxlcjogdW5kZWZpbmVkLAogICAgICAgICAgdGVtcGxhdGU6IHRlbXBsYXRlCiAgICAgICAgfQogICAgICB9KTsKICAgICAgdGhpcy5zdGF0ZSA9IHsKICAgICAgICByZWY6IHJlZiwKICAgICAgICBuYW1lOiBUT1BfTEVWRUxfTkFNRSwKICAgICAgICBvdXRsZXQ6IFRPUF9MRVZFTF9PVVRMRVQsCiAgICAgICAgdGVtcGxhdGU6IHRlbXBsYXRlLAogICAgICAgIGNvbnRyb2xsZXI6IHVuZGVmaW5lZAogICAgICB9OwogICAgfQoKICAgIE91dGxldFZpZXcuZXh0ZW5kID0gZnVuY3Rpb24gZXh0ZW5kKGluamVjdGlvbnMpIHsKICAgICAgcmV0dXJuICgKICAgICAgICAvKiNfX1BVUkVfXyovCiAgICAgICAgZnVuY3Rpb24gKF9PdXRsZXRWaWV3KSB7CiAgICAgICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoX2NsYXNzLCBfT3V0bGV0Vmlldyk7CgogICAgICAgICAgZnVuY3Rpb24gX2NsYXNzKCkgewogICAgICAgICAgICByZXR1cm4gX091dGxldFZpZXcuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICAgICAgfQoKICAgICAgICAgIF9jbGFzcy5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUob3B0aW9ucykgewogICAgICAgICAgICBpZiAob3B0aW9ucykgewogICAgICAgICAgICAgIHJldHVybiBfT3V0bGV0Vmlldy5jcmVhdGUuY2FsbCh0aGlzLCAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBpbmplY3Rpb25zLCBvcHRpb25zKSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmV0dXJuIF9PdXRsZXRWaWV3LmNyZWF0ZS5jYWxsKHRoaXMsIGluamVjdGlvbnMpOwogICAgICAgICAgICB9CiAgICAgICAgICB9OwoKICAgICAgICAgIHJldHVybiBfY2xhc3M7CiAgICAgICAgfShPdXRsZXRWaWV3KQogICAgICApOwogICAgfTsKCiAgICBPdXRsZXRWaWV3LnJlb3BlbkNsYXNzID0gZnVuY3Rpb24gcmVvcGVuQ2xhc3MoaW5qZWN0aW9ucykgewogICAgICAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHRoaXMsIGluamVjdGlvbnMpOwogICAgfTsKCiAgICBPdXRsZXRWaWV3LmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShvcHRpb25zKSB7CiAgICAgIHZhciBfZW52aXJvbm1lbnQgPSBvcHRpb25zLl9lbnZpcm9ubWVudCwKICAgICAgICAgIHJlbmRlcmVyID0gb3B0aW9ucy5yZW5kZXJlciwKICAgICAgICAgIHRlbXBsYXRlRmFjdG9yeSQkMSA9IG9wdGlvbnMudGVtcGxhdGU7CiAgICAgIHZhciBvd25lciA9IG9wdGlvbnNbX293bmVyLk9XTkVSXTsKICAgICAgdmFyIHRlbXBsYXRlID0gdGVtcGxhdGVGYWN0b3J5JCQxKG93bmVyKTsKICAgICAgcmV0dXJuIG5ldyBPdXRsZXRWaWV3KF9lbnZpcm9ubWVudCwgcmVuZGVyZXIsIG93bmVyLCB0ZW1wbGF0ZSk7CiAgICB9OwoKICAgIHZhciBfcHJvdG82OSA9IE91dGxldFZpZXcucHJvdG90eXBlOwoKICAgIF9wcm90bzY5LmFwcGVuZFRvID0gZnVuY3Rpb24gYXBwZW5kVG8oc2VsZWN0b3IpIHsKICAgICAgdmFyIHRhcmdldDsKCiAgICAgIGlmICh0aGlzLl9lbnZpcm9ubWVudC5oYXNET00pIHsKICAgICAgICB0YXJnZXQgPSB0eXBlb2Ygc2VsZWN0b3IgPT09ICdzdHJpbmcnID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3RvcikgOiBzZWxlY3RvcjsKICAgICAgfSBlbHNlIHsKICAgICAgICB0YXJnZXQgPSBzZWxlY3RvcjsKICAgICAgfQoKICAgICAgKDAsIF9ydW5sb29wLnNjaGVkdWxlKSgncmVuZGVyJywgdGhpcy5yZW5kZXJlciwgJ2FwcGVuZE91dGxldFZpZXcnLCB0aGlzLCB0YXJnZXQpOwogICAgfTsKCiAgICBfcHJvdG82OS5yZXJlbmRlciA9IGZ1bmN0aW9uIHJlcmVuZGVyKCkgewogICAgICAvKiovCiAgICB9OwoKICAgIF9wcm90bzY5LnNldE91dGxldFN0YXRlID0gZnVuY3Rpb24gc2V0T3V0bGV0U3RhdGUoc3RhdGUpIHsKICAgICAgdGhpcy5yZWYudXBkYXRlKHN0YXRlKTsKICAgIH07CgogICAgX3Byb3RvNjkuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIC8qKi8KICAgIH07CgogICAgcmV0dXJuIE91dGxldFZpZXc7CiAgfSgpOwoKICBfZXhwb3J0cy5PdXRsZXRWaWV3ID0gT3V0bGV0VmlldzsKCiAgZnVuY3Rpb24gc2V0dXBBcHBsaWNhdGlvblJlZ2lzdHJ5KHJlZ2lzdHJ5KSB7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3NlcnZpY2U6LWdsaW1tZXItZW52aXJvbm1lbnQnLCAnYXBwZW5kT3BlcmF0aW9ucycsICdzZXJ2aWNlOi1kb20tdHJlZS1jb25zdHJ1Y3Rpb24nKTsKICAgIHJlZ2lzdHJ5LmluamVjdGlvbigncmVuZGVyZXInLCAnZW52JywgJ3NlcnZpY2U6LWdsaW1tZXItZW52aXJvbm1lbnQnKTsgLy8gYmVjYXVzZSB3ZSBhcmUgdXNpbmcgaW5qZWN0aW9ucyB3ZSBjYW4ndCB1c2UgaW5zdGFudGlhdGUgZmFsc2UKICAgIC8vIHdlIG5lZWQgdG8gdXNlIGJpbmQoKSB0byBjb3B5IHRoZSBmdW5jdGlvbiBzbyBmYWN0b3J5IGZvcgogICAgLy8gYXNzb2NpYXRpb24gd29uJ3QgbGVhawoKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdzZXJ2aWNlOi1kb20tYnVpbGRlcicsIHsKICAgICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUoX3JlZjM4KSB7CiAgICAgICAgdmFyIGJvb3RPcHRpb25zID0gX3JlZjM4LmJvb3RPcHRpb25zOwogICAgICAgIHZhciBfcmVuZGVyTW9kZSA9IGJvb3RPcHRpb25zLl9yZW5kZXJNb2RlOwoKICAgICAgICBzd2l0Y2ggKF9yZW5kZXJNb2RlKSB7CiAgICAgICAgICBjYXNlICdzZXJpYWxpemUnOgogICAgICAgICAgICByZXR1cm4gX25vZGUuc2VyaWFsaXplQnVpbGRlci5iaW5kKG51bGwpOwoKICAgICAgICAgIGNhc2UgJ3JlaHlkcmF0ZSc6CiAgICAgICAgICAgIHJldHVybiBfcnVudGltZTIucmVoeWRyYXRpb25CdWlsZGVyLmJpbmQobnVsbCk7CgogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgcmV0dXJuIF9ydW50aW1lMi5jbGllbnRCdWlsZGVyLmJpbmQobnVsbCk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICAgIHJlZ2lzdHJ5LmluamVjdGlvbignc2VydmljZTotZG9tLWJ1aWxkZXInLCAnYm9vdE9wdGlvbnMnLCAnLWVudmlyb25tZW50Om1haW4nKTsKICAgIHJlZ2lzdHJ5LmluamVjdGlvbigncmVuZGVyZXInLCAnYnVpbGRlcicsICdzZXJ2aWNlOi1kb20tYnVpbGRlcicpOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3Q1KCkpLCBSb290VGVtcGxhdGUpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdyZW5kZXJlcicsICdyb290VGVtcGxhdGUnLCAoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdDYoKSkpOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ3JlbmRlcmVyOi1kb20nLCBJbnRlcmFjdGl2ZVJlbmRlcmVyKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdyZW5kZXJlcjotaW5lcnQnLCBJbmVydFJlbmRlcmVyKTsKCiAgICBpZiAoX2Jyb3dzZXJFbnZpcm9ubWVudC5oYXNET00pIHsKICAgICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdzZXJ2aWNlOi1nbGltbWVyLWVudmlyb25tZW50JywgJ3VwZGF0ZU9wZXJhdGlvbnMnLCAnc2VydmljZTotZG9tLWNoYW5nZXMnKTsKICAgIH0KCiAgICByZWdpc3RyeS5yZWdpc3Rlcignc2VydmljZTotZG9tLWNoYW5nZXMnLCB7CiAgICAgIGNyZWF0ZTogZnVuY3Rpb24gY3JlYXRlKF9yZWYzOSkgewogICAgICAgIHZhciBkb2N1bWVudCA9IF9yZWYzOS5kb2N1bWVudDsKICAgICAgICByZXR1cm4gbmV3IF9ydW50aW1lMi5ET01DaGFuZ2VzKGRvY3VtZW50KTsKICAgICAgfQogICAgfSk7CiAgICByZWdpc3RyeS5yZWdpc3Rlcignc2VydmljZTotZG9tLXRyZWUtY29uc3RydWN0aW9uJywgewogICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShfcmVmNDApIHsKICAgICAgICB2YXIgZG9jdW1lbnQgPSBfcmVmNDAuZG9jdW1lbnQ7CiAgICAgICAgdmFyIEltcGxlbWVudGF0aW9uID0gX2Jyb3dzZXJFbnZpcm9ubWVudC5oYXNET00gPyBfcnVudGltZTIuRE9NVHJlZUNvbnN0cnVjdGlvbiA6IF9ub2RlLk5vZGVET01UcmVlQ29uc3RydWN0aW9uOwogICAgICAgIHJldHVybiBuZXcgSW1wbGVtZW50YXRpb24oZG9jdW1lbnQpOwogICAgICB9CiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHNldHVwRW5naW5lUmVnaXN0cnkocmVnaXN0cnkpIHsKICAgIHJlZ2lzdHJ5Lm9wdGlvbnNGb3JUeXBlKCd0ZW1wbGF0ZScsIHsKICAgICAgaW5zdGFudGlhdGU6IGZhbHNlCiAgICB9KTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCd2aWV3Oi1vdXRsZXQnLCBPdXRsZXRWaWV3KTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCd0ZW1wbGF0ZTotb3V0bGV0JywgT3V0bGV0VGVtcGxhdGUpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCd2aWV3Oi1vdXRsZXQnLCAndGVtcGxhdGUnLCAndGVtcGxhdGU6LW91dGxldCcpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdzZXJ2aWNlOi1kb20tY2hhbmdlcycsICdkb2N1bWVudCcsICdzZXJ2aWNlOi1kb2N1bWVudCcpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdzZXJ2aWNlOi1kb20tdHJlZS1jb25zdHJ1Y3Rpb24nLCAnZG9jdW1lbnQnLCAnc2VydmljZTotZG9jdW1lbnQnKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCgwLCBfY29udGFpbmVyLnByaXZhdGl6ZSkoX3RlbXBsYXRlT2JqZWN0NygpKSwgQ29tcG9uZW50VGVtcGxhdGUpOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ3NlcnZpY2U6LWdsaW1tZXItZW52aXJvbm1lbnQnLCBFbnZpcm9ubWVudCQxKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCgwLCBfY29udGFpbmVyLnByaXZhdGl6ZSkoX3RlbXBsYXRlT2JqZWN0OCgpKSwgVGVtcGxhdGVDb21waWxlcik7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3Q5KCkpLCAnZW52aXJvbm1lbnQnLCAnLWVudmlyb25tZW50Om1haW4nKTsKICAgIHJlZ2lzdHJ5Lm9wdGlvbnNGb3JUeXBlKCdoZWxwZXInLCB7CiAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgfSk7CiAgICByZWdpc3RyeS5yZWdpc3RlcignaGVscGVyOmxvYycsIGxvYyQxKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdjb21wb25lbnQ6LXRleHQtZmllbGQnLCBUZXh0RmllbGQpOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ2NvbXBvbmVudDotY2hlY2tib3gnLCBDaGVja2JveCk7CiAgICByZWdpc3RyeS5yZWdpc3RlcignY29tcG9uZW50OmxpbmstdG8nLCBMaW5rVG9Db21wb25lbnQpOwogICAgewogICAgICByZWdpc3RyeS5yZWdpc3RlcignY29tcG9uZW50OmlucHV0JywgSW5wdXQkMSk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCd0ZW1wbGF0ZTpjb21wb25lbnRzL2lucHV0JywgSW5wdXRUZW1wbGF0ZSk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdjb21wb25lbnQ6dGV4dGFyZWEnLCBUZXh0QXJlYSk7CiAgICB9CgogICAgaWYgKCFfZW52aXJvbm1lbnQyLkVOVi5fVEVNUExBVEVfT05MWV9HTElNTUVSX0NPTVBPTkVOVFMpIHsKICAgICAgcmVnaXN0cnkucmVnaXN0ZXIoKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3QxMCgpKSwgQ29tcG9uZW50KTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHNldENvbXBvbmVudE1hbmFnZXIoc3RyaW5nT3JGdW5jdGlvbiwgb2JqKSB7CiAgICB2YXIgZmFjdG9yeTsKCiAgICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5DT01QT05FTlRfTUFOQUdFUl9TVFJJTkdfTE9PS1VQICYmIHR5cGVvZiBzdHJpbmdPckZ1bmN0aW9uID09PSAnc3RyaW5nJykgewogICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdQYXNzaW5nIHRoZSBuYW1lIG9mIHRoZSBjb21wb25lbnQgbWFuYWdlciB0byAic2V0dXBDb21wb25lbnRNYW5hZ2VyIiBpcyBkZXByZWNhdGVkLiBQbGVhc2UgcGFzcyBhIGZ1bmN0aW9uIHRoYXQgcHJvZHVjZXMgYW4gaW5zdGFuY2Ugb2YgdGhlIG1hbmFnZXIuJywgZmFsc2UsIHsKICAgICAgICBpZDogJ2RlcHJlY2F0ZS1zdHJpbmctYmFzZWQtY29tcG9uZW50LW1hbmFnZXInLAogICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngvI3RvY19jb21wb25lbnQtbWFuYWdlci1zdHJpbmctbG9va3VwJwogICAgICB9KSk7CgogICAgICBmYWN0b3J5ID0gZnVuY3Rpb24gZmFjdG9yeShvd25lcikgewogICAgICAgIHJldHVybiBvd25lci5sb29rdXAoImNvbXBvbmVudC1tYW5hZ2VyOiIgKyBzdHJpbmdPckZ1bmN0aW9uKTsKICAgICAgfTsKICAgIH0gZWxzZSB7CiAgICAgIGZhY3RvcnkgPSBzdHJpbmdPckZ1bmN0aW9uOwogICAgfQoKICAgIHJldHVybiBzZXRNYW5hZ2VyKHsKICAgICAgZmFjdG9yeTogZmFjdG9yeSwKICAgICAgaW50ZXJuYWw6IGZhbHNlLAogICAgICB0eXBlOiAnY29tcG9uZW50JwogICAgfSwgb2JqKTsKICB9CgogIGZ1bmN0aW9uIGdldENvbXBvbmVudE1hbmFnZXIob2JqKSB7CiAgICB2YXIgd3JhcHBlciA9IGdldE1hbmFnZXIob2JqKTsKCiAgICBpZiAod3JhcHBlciAmJiAhd3JhcHBlci5pbnRlcm5hbCAmJiB3cmFwcGVyLnR5cGUgPT09ICdjb21wb25lbnQnKSB7CiAgICAgIHJldHVybiB3cmFwcGVyLmZhY3Rvcnk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogIH0KICAvKioKICAgIFtHbGltbWVyXShodHRwczovL2dpdGh1Yi5jb20vdGlsZGVpby9nbGltbWVyKSBpcyBhIHRlbXBsYXRpbmcgZW5naW5lIHVzZWQgYnkgRW1iZXIuanMgdGhhdCBpcyBjb21wYXRpYmxlIHdpdGggYSBzdWJzZXQgb2YgdGhlIFtIYW5kbGViYXJzXShodHRwOi8vaGFuZGxlYmFyc2pzLmNvbS8pIHN5bnRheC4KICAKICAgICMjIyBTaG93aW5nIGEgcHJvcGVydHkKICAKICAgIFRlbXBsYXRlcyBtYW5hZ2UgdGhlIGZsb3cgb2YgYW4gYXBwbGljYXRpb24ncyBVSSwgYW5kIGRpc3BsYXkgc3RhdGUgKHRocm91Z2gKICAgIHRoZSBET00pIHRvIGEgdXNlci4gRm9yIGV4YW1wbGUsIGdpdmVuIGEgY29tcG9uZW50IHdpdGggdGhlIHByb3BlcnR5ICJuYW1lIiwKICAgIHRoYXQgY29tcG9uZW50J3MgdGVtcGxhdGUgY2FuIHVzZSB0aGUgbmFtZSBpbiBzZXZlcmFsIHdheXM6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9wZXJzb24tcHJvZmlsZS5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICBuYW1lOiAnSmlsbCcKICAgIH0pOwogICAgYGBgCiAgCiAgICBgYGBhcHAvdGVtcGxhdGVzL2NvbXBvbmVudHMvcGVyc29uLXByb2ZpbGUuaGJzCiAgICB7e25hbWV9fQogICAgPGRpdj57e25hbWV9fTwvZGl2PgogICAgPHNwYW4gZGF0YS1uYW1lPXt7bmFtZX19Pjwvc3Bhbj4KICAgIGBgYAogIAogICAgQW55IHRpbWUgdGhlICJuYW1lIiBwcm9wZXJ0eSBvbiB0aGUgY29tcG9uZW50IGNoYW5nZXMsIHRoZSBET00gd2lsbCBiZQogICAgdXBkYXRlZC4KICAKICAgIFByb3BlcnRpZXMgY2FuIGJlIGNoYWluZWQgYXMgd2VsbDoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgIHt7YVVzZXJNb2RlbC5uYW1lfX0KICAgIDxkaXY+e3tsaXN0T2ZVc2Vycy5maXJzdE9iamVjdC5uYW1lfX08L2Rpdj4KICAgIGBgYAogIAogICAgIyMjIFVzaW5nIEVtYmVyIGhlbHBlcnMKICAKICAgIFdoZW4gY29udGVudCBpcyBwYXNzZWQgaW4gbXVzdGFjaGVzIGB7e319YCwgRW1iZXIgd2lsbCBmaXJzdCB0cnkgdG8gZmluZCBhIGhlbHBlcgogICAgb3IgY29tcG9uZW50IHdpdGggdGhhdCBuYW1lLiBGb3IgZXhhbXBsZSwgdGhlIGBpZmAgaGVscGVyOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3tpZiBuYW1lICJJIGhhdmUgYSBuYW1lIiAiSSBoYXZlIG5vIG5hbWUifX0KICAgIDxzcGFuIGRhdGEtaGFzLW5hbWU9e3tpZiBuYW1lIHRydWV9fT48L3NwYW4+CiAgICBgYGAKICAKICAgIFRoZSByZXR1cm5lZCB2YWx1ZSBpcyBwbGFjZWQgd2hlcmUgdGhlIGB7e319YCBpcyBjYWxsZWQuIFRoZSBhYm92ZSBzdHlsZSBpcwogICAgY2FsbGVkICJpbmxpbmUiLiBBIHNlY29uZCBzdHlsZSBvZiBoZWxwZXIgdXNhZ2UgaXMgY2FsbGVkICJibG9jayIuIEZvciBleGFtcGxlOgogIAogICAgYGBgaGFuZGxlYmFycwogICAge3sjaWYgbmFtZX19CiAgICBJIGhhdmUgYSBuYW1lCiAgICB7e2Vsc2V9fQogICAgSSBoYXZlIG5vIG5hbWUKICAgIHt7L2lmfX0KICAgIGBgYAogIAogICAgVGhlIGJsb2NrIGZvcm0gb2YgaGVscGVycyBhbGxvd3MgeW91IHRvIGNvbnRyb2wgaG93IHRoZSBVSSBpcyBjcmVhdGVkIGJhc2VkCiAgICBvbiB0aGUgdmFsdWVzIG9mIHByb3BlcnRpZXMuCiAgICBBIHRoaXJkIGZvcm0gb2YgaGVscGVyIGlzIGNhbGxlZCAibmVzdGVkIi4gRm9yIGV4YW1wbGUgaGVyZSB0aGUgY29uY2F0CiAgICBoZWxwZXIgd2lsbCBhZGQgIiBEb2UiIHRvIGEgZGlzcGxheWVkIG5hbWUgaWYgdGhlIHBlcnNvbiBoYXMgbm8gbGFzdCBuYW1lOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgPHNwYW4gZGF0YS1uYW1lPXt7Y29uY2F0IGZpcnN0TmFtZSAoCiAgICBpZiBsYXN0TmFtZSAoY29uY2F0ICIgIiBsYXN0TmFtZSkgIkRvZSIKICAgICl9fT48L3NwYW4+CiAgICBgYGAKICAKICAgIEVtYmVyJ3MgYnVpbHQtaW4gaGVscGVycyBhcmUgZGVzY3JpYmVkIHVuZGVyIHRoZSBbRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnNdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvRW1iZXIuVGVtcGxhdGVzLmhlbHBlcnMpCiAgICBuYW1lc3BhY2UuIERvY3VtZW50YXRpb24gb24gY3JlYXRpbmcgY3VzdG9tIGhlbHBlcnMgY2FuIGJlIGZvdW5kIHVuZGVyCiAgICBbaGVscGVyXSgvZW1iZXIvcmVsZWFzZS9mdW5jdGlvbnMvQGVtYmVyJTJGY29tcG9uZW50JTJGaGVscGVyL2hlbHBlcikgKG9yCiAgICB1bmRlciBbSGVscGVyXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0hlbHBlcikgaWYgYSBoZWxwZXIgcmVxdWlyZXMgYWNjZXNzIHRvCiAgICBkZXBlbmRlbmN5IGluamVjdGlvbikuCiAgCiAgICAjIyMgSW52b2tpbmcgYSBDb21wb25lbnQKICAKICAgIEVtYmVyIGNvbXBvbmVudHMgcmVwcmVzZW50IHN0YXRlIHRvIHRoZSBVSSBvZiBhbiBhcHBsaWNhdGlvbi4gRnVydGhlcgogICAgcmVhZGluZyBvbiBjb21wb25lbnRzIGNhbiBiZSBmb3VuZCB1bmRlciBbQ29tcG9uZW50XSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0NvbXBvbmVudCkuCiAgCiAgICBAbW9kdWxlIEBlbWJlci9jb21wb25lbnQKICAgIEBtYWluIEBlbWJlci9jb21wb25lbnQKICAgIEBwdWJsaWMKICAgKi8KCn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL21ldGEvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YS9saWIvbWV0YSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJjb3VudGVycyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9tZXRhLmNvdW50ZXJzOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlbGV0ZU1ldGEiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbWV0YS5kZWxldGVNZXRhOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIk1ldGEiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbWV0YS5NZXRhOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIm1ldGEiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbWV0YS5tZXRhOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInBlZWtNZXRhIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX21ldGEucGVla01ldGE7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0TWV0YSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9tZXRhLnNldE1ldGE7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiVU5ERUZJTkVEIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX21ldGEuVU5ERUZJTkVEOwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9tZXRhL2xpYi9tZXRhIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZ2xpbW1lci9yZWZlcmVuY2UiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX3V0aWxzLCBfZGVidWcsIF9yZWZlcmVuY2UpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLnNldE1ldGEgPSBzZXRNZXRhOwogIF9leHBvcnRzLnBlZWtNZXRhID0gcGVla01ldGE7CiAgX2V4cG9ydHMuZGVsZXRlTWV0YSA9IGRlbGV0ZU1ldGE7CiAgX2V4cG9ydHMuY291bnRlcnMgPSBfZXhwb3J0cy5tZXRhID0gX2V4cG9ydHMuTWV0YSA9IF9leHBvcnRzLlVOREVGSU5FRCA9IHZvaWQgMDsKICB2YXIgb2JqZWN0UHJvdG90eXBlID0gT2JqZWN0LnByb3RvdHlwZTsKICB2YXIgY291bnRlcnM7CiAgX2V4cG9ydHMuY291bnRlcnMgPSBjb3VudGVyczsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIF9leHBvcnRzLmNvdW50ZXJzID0gY291bnRlcnMgPSB7CiAgICAgIHBlZWtDYWxsczogMCwKICAgICAgcGVla1Byb3RvdHlwZVdhbGtzOiAwLAogICAgICBzZXRDYWxsczogMCwKICAgICAgZGVsZXRlQ2FsbHM6IDAsCiAgICAgIG1ldGFDYWxsczogMCwKICAgICAgbWV0YUluc3RhbnRpYXRlZDogMCwKICAgICAgbWF0Y2hpbmdMaXN0ZW5lcnNDYWxsczogMCwKICAgICAgb2JzZXJ2ZXJFdmVudHNDYWxsczogMCwKICAgICAgYWRkVG9MaXN0ZW5lcnNDYWxsczogMCwKICAgICAgcmVtb3ZlRnJvbUxpc3RlbmVyc0NhbGxzOiAwLAogICAgICByZW1vdmVBbGxMaXN0ZW5lcnNDYWxsczogMCwKICAgICAgbGlzdGVuZXJzSW5oZXJpdGVkOiAwLAogICAgICBsaXN0ZW5lcnNGbGF0dGVuZWQ6IDAsCiAgICAgIHBhcmVudExpc3RlbmVyc1VzZWQ6IDAsCiAgICAgIGZsYXR0ZW5lZExpc3RlbmVyc0NhbGxzOiAwLAogICAgICByZW9wZW5zQWZ0ZXJGbGF0dGVuOiAwLAogICAgICByZWFkYWJsZUxhenlDaGFpbnNDYWxsczogMCwKICAgICAgd3JpdGFibGVMYXp5Q2hhaW5zQ2FsbHM6IDAKICAgIH07CiAgfQogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKCiAgdmFyIFVOREVGSU5FRCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgndW5kZWZpbmVkJyk7CiAgX2V4cG9ydHMuVU5ERUZJTkVEID0gVU5ERUZJTkVEOwogIHZhciBjdXJyZW50TGlzdGVuZXJWZXJzaW9uID0gMTsKCiAgdmFyIE1ldGEgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBNZXRhKG9iaikgewogICAgICB0aGlzLl9saXN0ZW5lcnNWZXJzaW9uID0gMTsKICAgICAgdGhpcy5faW5oZXJpdGVkRW5kID0gLTE7CiAgICAgIHRoaXMuX2ZsYXR0ZW5lZFZlcnNpb24gPSAwOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGNvdW50ZXJzLm1ldGFJbnN0YW50aWF0ZWQrKzsKICAgICAgICB0aGlzLl92YWx1ZXMgPSB1bmRlZmluZWQ7CiAgICAgIH0KCiAgICAgIHRoaXMuX3BhcmVudCA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5fZGVzY3JpcHRvcnMgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuX3dhdGNoaW5nID0gdW5kZWZpbmVkOwogICAgICB0aGlzLl9taXhpbnMgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuX2RlcHMgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuX2NoYWluV2F0Y2hlcnMgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuX2NoYWlucyA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5fdGFnID0gdW5kZWZpbmVkOwogICAgICB0aGlzLl90YWdzID0gdW5kZWZpbmVkOyAvLyBpbml0aWFsIHZhbHVlIGZvciBhbGwgZmxhZ3MgcmlnaHQgbm93IGlzIGZhbHNlCiAgICAgIC8vIHNlZSBGTEFHUyBjb25zdCBmb3IgZGV0YWlsZWQgbGlzdCBvZiBmbGFncyB1c2VkCgogICAgICB0aGlzLl9mbGFncyA9IDAKICAgICAgLyogTk9ORSAqLwogICAgICA7IC8vIHVzZWQgb25seSBpbnRlcm5hbGx5CgogICAgICB0aGlzLnNvdXJjZSA9IG9iajsKICAgICAgdGhpcy5wcm90byA9IG9iai5jb25zdHJ1Y3RvciA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogb2JqLmNvbnN0cnVjdG9yLnByb3RvdHlwZTsKICAgICAgdGhpcy5fbGlzdGVuZXJzID0gdW5kZWZpbmVkOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBNZXRhLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uc2V0SW5pdGlhbGl6aW5nID0gZnVuY3Rpb24gc2V0SW5pdGlhbGl6aW5nKCkgewogICAgICB0aGlzLl9mbGFncyB8PSA4CiAgICAgIC8qIElOSVRJQUxJWklORyAqLwogICAgICA7CiAgICB9OwoKICAgIF9wcm90by51bnNldEluaXRpYWxpemluZyA9IGZ1bmN0aW9uIHVuc2V0SW5pdGlhbGl6aW5nKCkgewogICAgICB0aGlzLl9mbGFncyBePSA4CiAgICAgIC8qIElOSVRJQUxJWklORyAqLwogICAgICA7CiAgICB9OwoKICAgIF9wcm90by5pc0luaXRpYWxpemluZyA9IGZ1bmN0aW9uIGlzSW5pdGlhbGl6aW5nKCkgewogICAgICByZXR1cm4gdGhpcy5faGFzRmxhZyg4CiAgICAgIC8qIElOSVRJQUxJWklORyAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8uaXNQcm90b3R5cGVNZXRhID0gZnVuY3Rpb24gaXNQcm90b3R5cGVNZXRhKG9iaikgewogICAgICByZXR1cm4gdGhpcy5wcm90byA9PT0gdGhpcy5zb3VyY2UgJiYgdGhpcy5zb3VyY2UgPT09IG9iajsKICAgIH07CgogICAgX3Byb3RvLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICBpZiAodGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5zZXRNZXRhRGVzdHJveWVkKCk7IC8vIHJlbW92ZSBjaGFpbldhdGNoZXJzIHRvIHJlbW92ZSBjaXJjdWxhciByZWZlcmVuY2VzIHRoYXQgd291bGQgcHJldmVudCBHQwoKICAgICAgdmFyIGNoYWlucyA9IHRoaXMucmVhZGFibGVDaGFpbnMoKTsKCiAgICAgIGlmIChjaGFpbnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGNoYWlucy5kZXN0cm95KCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmlzU291cmNlRGVzdHJveWluZyA9IGZ1bmN0aW9uIGlzU291cmNlRGVzdHJveWluZygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2hhc0ZsYWcoMQogICAgICAvKiBTT1VSQ0VfREVTVFJPWUlORyAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8uc2V0U291cmNlRGVzdHJveWluZyA9IGZ1bmN0aW9uIHNldFNvdXJjZURlc3Ryb3lpbmcoKSB7CiAgICAgIHRoaXMuX2ZsYWdzIHw9IDEKICAgICAgLyogU09VUkNFX0RFU1RST1lJTkcgKi8KICAgICAgOwogICAgfTsKCiAgICBfcHJvdG8uaXNTb3VyY2VEZXN0cm95ZWQgPSBmdW5jdGlvbiBpc1NvdXJjZURlc3Ryb3llZCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2hhc0ZsYWcoMgogICAgICAvKiBTT1VSQ0VfREVTVFJPWUVEICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90by5zZXRTb3VyY2VEZXN0cm95ZWQgPSBmdW5jdGlvbiBzZXRTb3VyY2VEZXN0cm95ZWQoKSB7CiAgICAgIHRoaXMuX2ZsYWdzIHw9IDIKICAgICAgLyogU09VUkNFX0RFU1RST1lFRCAqLwogICAgICA7CiAgICB9OwoKICAgIF9wcm90by5pc01ldGFEZXN0cm95ZWQgPSBmdW5jdGlvbiBpc01ldGFEZXN0cm95ZWQoKSB7CiAgICAgIHJldHVybiB0aGlzLl9oYXNGbGFnKDQKICAgICAgLyogTUVUQV9ERVNUUk9ZRUQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvLnNldE1ldGFEZXN0cm95ZWQgPSBmdW5jdGlvbiBzZXRNZXRhRGVzdHJveWVkKCkgewogICAgICB0aGlzLl9mbGFncyB8PSA0CiAgICAgIC8qIE1FVEFfREVTVFJPWUVEICovCiAgICAgIDsKICAgIH07CgogICAgX3Byb3RvLl9oYXNGbGFnID0gZnVuY3Rpb24gX2hhc0ZsYWcoZmxhZykgewogICAgICByZXR1cm4gKHRoaXMuX2ZsYWdzICYgZmxhZykgPT09IGZsYWc7CiAgICB9OwoKICAgIF9wcm90by5fZ2V0T3JDcmVhdGVPd25NYXAgPSBmdW5jdGlvbiBfZ2V0T3JDcmVhdGVPd25NYXAoa2V5KSB7CiAgICAgIHJldHVybiB0aGlzW2tleV0gfHwgKHRoaXNba2V5XSA9IE9iamVjdC5jcmVhdGUobnVsbCkpOwogICAgfTsKCiAgICBfcHJvdG8uX2dldE9yQ3JlYXRlT3duU2V0ID0gZnVuY3Rpb24gX2dldE9yQ3JlYXRlT3duU2V0KGtleSkgewogICAgICByZXR1cm4gdGhpc1trZXldIHx8ICh0aGlzW2tleV0gPSBuZXcgU2V0KCkpOwogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRJbmhlcml0ZWQxID0gZnVuY3Rpb24gX2ZpbmRJbmhlcml0ZWQxKGtleSkgewogICAgICB2YXIgcG9pbnRlciA9IHRoaXM7CgogICAgICB3aGlsZSAocG9pbnRlciAhPT0gbnVsbCkgewogICAgICAgIHZhciBtYXAgPSBwb2ludGVyW2tleV07CgogICAgICAgIGlmIChtYXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcmV0dXJuIG1hcDsKICAgICAgICB9CgogICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRJbmhlcml0ZWQyID0gZnVuY3Rpb24gX2ZpbmRJbmhlcml0ZWQyKGtleSwgc3Via2V5KSB7CiAgICAgIHZhciBwb2ludGVyID0gdGhpczsKCiAgICAgIHdoaWxlIChwb2ludGVyICE9PSBudWxsKSB7CiAgICAgICAgdmFyIG1hcCA9IHBvaW50ZXJba2V5XTsKCiAgICAgICAgaWYgKG1hcCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YXIgdmFsdWUgPSBtYXBbc3Via2V5XTsKCiAgICAgICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwb2ludGVyID0gcG9pbnRlci5wYXJlbnQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9maW5kSW5oZXJpdGVkMyA9IGZ1bmN0aW9uIF9maW5kSW5oZXJpdGVkMyhrZXksIHN1YmtleSwgc3Vic3Via2V5KSB7CiAgICAgIHZhciBwb2ludGVyID0gdGhpczsKCiAgICAgIHdoaWxlIChwb2ludGVyICE9PSBudWxsKSB7CiAgICAgICAgdmFyIG1hcCA9IHBvaW50ZXJba2V5XTsKCiAgICAgICAgaWYgKG1hcCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YXIgc3VibWFwID0gbWFwW3N1YmtleV07CgogICAgICAgICAgaWYgKHN1Ym1hcCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHZhciB2YWx1ZSA9IHN1Ym1hcFtzdWJzdWJrZXldOwoKICAgICAgICAgICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRJbmhlcml0ZWRNYXAgPSBmdW5jdGlvbiBfZmluZEluaGVyaXRlZE1hcChrZXksIHN1YmtleSkgewogICAgICB2YXIgcG9pbnRlciA9IHRoaXM7CgogICAgICB3aGlsZSAocG9pbnRlciAhPT0gbnVsbCkgewogICAgICAgIHZhciBtYXAgPSBwb2ludGVyW2tleV07CgogICAgICAgIGlmIChtYXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdmFyIHZhbHVlID0gbWFwLmdldChzdWJrZXkpOwoKICAgICAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2hhc0luSW5oZXJpdGVkU2V0ID0gZnVuY3Rpb24gX2hhc0luSW5oZXJpdGVkU2V0KGtleSwgdmFsdWUpIHsKICAgICAgdmFyIHBvaW50ZXIgPSB0aGlzOwoKICAgICAgd2hpbGUgKHBvaW50ZXIgIT09IG51bGwpIHsKICAgICAgICB2YXIgc2V0ID0gcG9pbnRlcltrZXldOwoKICAgICAgICBpZiAoc2V0ICE9PSB1bmRlZmluZWQgJiYgc2V0Lmhhcyh2YWx1ZSkpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgcG9pbnRlciA9IHBvaW50ZXIucGFyZW50OwogICAgICB9CgogICAgICByZXR1cm4gZmFsc2U7CiAgICB9IC8vIEltcGxlbWVudHMgYSBtZW1iZXIgdGhhdCBwcm92aWRlcyBhIGxhemlseSBjcmVhdGVkIG1hcCBvZiBtYXBzLAogICAgLy8gd2l0aCBpbmhlcml0YW5jZSBhdCBib3RoIGxldmVscy4KICAgIDsKCiAgICBfcHJvdG8ud3JpdGVEZXBzID0gZnVuY3Rpb24gd3JpdGVEZXBzKHN1YmtleSwgaXRlbWtleSwgY291bnQpIHsKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNNZXRhRGVzdHJveWVkKCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSh0aGlzLmlzTWV0YURlc3Ryb3llZCgpID8gIkNhbm5vdCBtb2RpZnkgZGVwZW5kZW50IGtleXMgZm9yIGAiICsgaXRlbWtleSArICJgIG9uIGAiICsgKDAsIF91dGlscy50b1N0cmluZykodGhpcy5zb3VyY2UpICsgImAgYWZ0ZXIgaXQgaGFzIGJlZW4gZGVzdHJveWVkLiIgOiAnJywgIXRoaXMuaXNNZXRhRGVzdHJveWVkKCkpKTsKCiAgICAgIHZhciBvdXRlck1hcCA9IHRoaXMuX2dldE9yQ3JlYXRlT3duTWFwKCdfZGVwcycpOwoKICAgICAgdmFyIGlubmVyTWFwID0gb3V0ZXJNYXBbc3Via2V5XTsKCiAgICAgIGlmIChpbm5lck1hcCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgaW5uZXJNYXAgPSBvdXRlck1hcFtzdWJrZXldID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgfQoKICAgICAgaW5uZXJNYXBbaXRlbWtleV0gPSBjb3VudDsKICAgIH07CgogICAgX3Byb3RvLnBlZWtEZXBzID0gZnVuY3Rpb24gcGVla0RlcHMoc3Via2V5LCBpdGVta2V5KSB7CiAgICAgIHZhciB2YWwgPSB0aGlzLl9maW5kSW5oZXJpdGVkMygnX2RlcHMnLCBzdWJrZXksIGl0ZW1rZXkpOwoKICAgICAgcmV0dXJuIHZhbCA9PT0gdW5kZWZpbmVkID8gMCA6IHZhbDsKICAgIH07CgogICAgX3Byb3RvLmhhc0RlcHMgPSBmdW5jdGlvbiBoYXNEZXBzKHN1YmtleSkgewogICAgICB2YXIgdmFsID0gdGhpcy5fZmluZEluaGVyaXRlZDIoJ19kZXBzJywgc3Via2V5KTsKCiAgICAgIHJldHVybiB2YWwgIT09IHVuZGVmaW5lZDsKICAgIH07CgogICAgX3Byb3RvLmZvckVhY2hJbkRlcHMgPSBmdW5jdGlvbiBmb3JFYWNoSW5EZXBzKHN1YmtleSwgZm4pIHsKICAgICAgdmFyIHBvaW50ZXIgPSB0aGlzOwogICAgICB2YXIgc2VlbjsKCiAgICAgIHdoaWxlIChwb2ludGVyICE9PSBudWxsKSB7CiAgICAgICAgdmFyIG1hcCA9IHBvaW50ZXIuX2RlcHM7CgogICAgICAgIGlmIChtYXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdmFyIGlubmVyTWFwID0gbWFwW3N1YmtleV07CgogICAgICAgICAgaWYgKGlubmVyTWFwICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgc2VlbiA9IHNlZW4gPT09IHVuZGVmaW5lZCA/IG5ldyBTZXQoKSA6IHNlZW47CgogICAgICAgICAgICBmb3IgKHZhciBpbm5lcktleSBpbiBpbm5lck1hcCkgewogICAgICAgICAgICAgIGlmICghc2Vlbi5oYXMoaW5uZXJLZXkpKSB7CiAgICAgICAgICAgICAgICBzZWVuLmFkZChpbm5lcktleSk7CgogICAgICAgICAgICAgICAgaWYgKGlubmVyTWFwW2lubmVyS2V5XSA+IDApIHsKICAgICAgICAgICAgICAgICAgZm4oaW5uZXJLZXkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcG9pbnRlciA9IHBvaW50ZXIucGFyZW50OwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by53cml0YWJsZVRhZ3MgPSBmdW5jdGlvbiB3cml0YWJsZVRhZ3MoKSB7CiAgICAgIHJldHVybiB0aGlzLl9nZXRPckNyZWF0ZU93bk1hcCgnX3RhZ3MnKTsKICAgIH07CgogICAgX3Byb3RvLnJlYWRhYmxlVGFncyA9IGZ1bmN0aW9uIHJlYWRhYmxlVGFncygpIHsKICAgICAgcmV0dXJuIHRoaXMuX3RhZ3M7CiAgICB9OwoKICAgIF9wcm90by53cml0YWJsZVRhZyA9IGZ1bmN0aW9uIHdyaXRhYmxlVGFnKCkgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMuaXNNZXRhRGVzdHJveWVkKCkgPyAiQ2Fubm90IGNyZWF0ZSBhIG5ldyB0YWcgZm9yIGAiICsgKDAsIF91dGlscy50b1N0cmluZykodGhpcy5zb3VyY2UpICsgImAgYWZ0ZXIgaXQgaGFzIGJlZW4gZGVzdHJveWVkLiIgOiAnJywgIXRoaXMuaXNNZXRhRGVzdHJveWVkKCkpKTsKICAgICAgdmFyIHJldCA9IHRoaXMuX3RhZzsKCiAgICAgIGlmIChyZXQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldCA9IHRoaXMuX3RhZyA9ICgwLCBfcmVmZXJlbmNlLmNyZWF0ZVVwZGF0YWJsZVRhZykoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJldDsKICAgIH07CgogICAgX3Byb3RvLnJlYWRhYmxlVGFnID0gZnVuY3Rpb24gcmVhZGFibGVUYWcoKSB7CiAgICAgIHJldHVybiB0aGlzLl90YWc7CiAgICB9OwoKICAgIF9wcm90by53cml0YWJsZUxhenlDaGFpbnNGb3IgPSBmdW5jdGlvbiB3cml0YWJsZUxhenlDaGFpbnNGb3Ioa2V5KSB7CiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICBjb3VudGVycy53cml0YWJsZUxhenlDaGFpbnNDYWxscysrOwogICAgICB9CgogICAgICB2YXIgbGF6eUNoYWlucyA9IHRoaXMuX2dldE9yQ3JlYXRlT3duTWFwKCdfbGF6eUNoYWlucycpOwoKICAgICAgaWYgKCEoa2V5IGluIGxhenlDaGFpbnMpKSB7CiAgICAgICAgbGF6eUNoYWluc1trZXldID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGxhenlDaGFpbnNba2V5XTsKICAgIH07CgogICAgX3Byb3RvLnJlYWRhYmxlTGF6eUNoYWluc0ZvciA9IGZ1bmN0aW9uIHJlYWRhYmxlTGF6eUNoYWluc0ZvcihrZXkpIHsKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGNvdW50ZXJzLnJlYWRhYmxlTGF6eUNoYWluc0NhbGxzKys7CiAgICAgIH0KCiAgICAgIHZhciBsYXp5Q2hhaW5zID0gdGhpcy5fbGF6eUNoYWluczsKCiAgICAgIGlmIChsYXp5Q2hhaW5zICE9PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gbGF6eUNoYWluc1trZXldOwogICAgICB9CgogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfTsKCiAgICBfcHJvdG8ud3JpdGFibGVDaGFpbldhdGNoZXJzID0gZnVuY3Rpb24gd3JpdGFibGVDaGFpbldhdGNoZXJzKGNyZWF0ZSkgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMuaXNNZXRhRGVzdHJveWVkKCkgPyAiQ2Fubm90IGNyZWF0ZSBhIG5ldyBjaGFpbiB3YXRjaGVyIGZvciBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKHRoaXMuc291cmNlKSArICJgIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CiAgICAgIHZhciByZXQgPSB0aGlzLl9jaGFpbldhdGNoZXJzOwoKICAgICAgaWYgKHJldCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0ID0gdGhpcy5fY2hhaW5XYXRjaGVycyA9IGNyZWF0ZSh0aGlzLnNvdXJjZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiByZXQ7CiAgICB9OwoKICAgIF9wcm90by5yZWFkYWJsZUNoYWluV2F0Y2hlcnMgPSBmdW5jdGlvbiByZWFkYWJsZUNoYWluV2F0Y2hlcnMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9jaGFpbldhdGNoZXJzOwogICAgfTsKCiAgICBfcHJvdG8ud3JpdGFibGVDaGFpbnMgPSBmdW5jdGlvbiB3cml0YWJsZUNoYWlucyhjcmVhdGUpIHsKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNNZXRhRGVzdHJveWVkKCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSh0aGlzLmlzTWV0YURlc3Ryb3llZCgpID8gIkNhbm5vdCBjcmVhdGUgYSBuZXcgY2hhaW5zIGZvciBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKHRoaXMuc291cmNlKSArICJgIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CiAgICAgIHZhciByZXQgPSB0aGlzLl9jaGFpbnM7CgogICAgICBpZiAocmV0ID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLl9jaGFpbnMgPSByZXQgPSBjcmVhdGUodGhpcy5zb3VyY2UpOwogICAgICAgIHZhciBwYXJlbnQgPSB0aGlzLnBhcmVudDsKCiAgICAgICAgaWYgKHBhcmVudCAhPT0gbnVsbCkgewogICAgICAgICAgdmFyIHBhcmVudENoYWlucyA9IHBhcmVudC53cml0YWJsZUNoYWlucyhjcmVhdGUpOwogICAgICAgICAgcGFyZW50Q2hhaW5zLmNvcHlUbyhyZXQpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHJldDsKICAgIH07CgogICAgX3Byb3RvLnJlYWRhYmxlQ2hhaW5zID0gZnVuY3Rpb24gcmVhZGFibGVDaGFpbnMoKSB7CiAgICAgIHJldHVybiB0aGlzLl9maW5kSW5oZXJpdGVkMSgnX2NoYWlucycpOwogICAgfTsKCiAgICBfcHJvdG8ud3JpdGVXYXRjaGluZyA9IGZ1bmN0aW9uIHdyaXRlV2F0Y2hpbmcoc3Via2V5LCB2YWx1ZSkgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMuaXNNZXRhRGVzdHJveWVkKCkgPyAiQ2Fubm90IHVwZGF0ZSB3YXRjaGVycyBmb3IgYCIgKyBzdWJrZXkgKyAiYCBvbiBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKHRoaXMuc291cmNlKSArICJgIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CgogICAgICB2YXIgbWFwID0gdGhpcy5fZ2V0T3JDcmVhdGVPd25NYXAoJ193YXRjaGluZycpOwoKICAgICAgbWFwW3N1YmtleV0gPSB2YWx1ZTsKICAgIH07CgogICAgX3Byb3RvLnBlZWtXYXRjaGluZyA9IGZ1bmN0aW9uIHBlZWtXYXRjaGluZyhzdWJrZXkpIHsKICAgICAgdmFyIGNvdW50ID0gdGhpcy5fZmluZEluaGVyaXRlZDIoJ193YXRjaGluZycsIHN1YmtleSk7CgogICAgICByZXR1cm4gY291bnQgPT09IHVuZGVmaW5lZCA/IDAgOiBjb3VudDsKICAgIH07CgogICAgX3Byb3RvLmFkZE1peGluID0gZnVuY3Rpb24gYWRkTWl4aW4obWl4aW4pIHsKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNNZXRhRGVzdHJveWVkKCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSh0aGlzLmlzTWV0YURlc3Ryb3llZCgpID8gIkNhbm5vdCBhZGQgbWl4aW5zIG9mIGAiICsgKDAsIF91dGlscy50b1N0cmluZykobWl4aW4pICsgImAgb24gYCIgKyAoMCwgX3V0aWxzLnRvU3RyaW5nKSh0aGlzLnNvdXJjZSkgKyAiYCBjYWxsIGFkZE1peGluIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CgogICAgICB2YXIgc2V0ID0gdGhpcy5fZ2V0T3JDcmVhdGVPd25TZXQoJ19taXhpbnMnKTsKCiAgICAgIHNldC5hZGQobWl4aW4pOwogICAgfTsKCiAgICBfcHJvdG8uaGFzTWl4aW4gPSBmdW5jdGlvbiBoYXNNaXhpbihtaXhpbikgewogICAgICByZXR1cm4gdGhpcy5faGFzSW5Jbmhlcml0ZWRTZXQoJ19taXhpbnMnLCBtaXhpbik7CiAgICB9OwoKICAgIF9wcm90by5mb3JFYWNoTWl4aW5zID0gZnVuY3Rpb24gZm9yRWFjaE1peGlucyhmbikgewogICAgICB2YXIgcG9pbnRlciA9IHRoaXM7CiAgICAgIHZhciBzZWVuOwoKICAgICAgd2hpbGUgKHBvaW50ZXIgIT09IG51bGwpIHsKICAgICAgICB2YXIgc2V0ID0gcG9pbnRlci5fbWl4aW5zOwoKICAgICAgICBpZiAoc2V0ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHNlZW4gPSBzZWVuID09PSB1bmRlZmluZWQgPyBuZXcgU2V0KCkgOiBzZWVuOyAvLyBUT0RPIGNsZWFudXAgdHlwaW5nIGhlcmUKCiAgICAgICAgICBzZXQuZm9yRWFjaChmdW5jdGlvbiAobWl4aW4pIHsKICAgICAgICAgICAgaWYgKCFzZWVuLmhhcyhtaXhpbikpIHsKICAgICAgICAgICAgICBzZWVuLmFkZChtaXhpbik7CiAgICAgICAgICAgICAgZm4obWl4aW4pOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ud3JpdGVEZXNjcmlwdG9ycyA9IGZ1bmN0aW9uIHdyaXRlRGVzY3JpcHRvcnMoc3Via2V5LCB2YWx1ZSkgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMuaXNNZXRhRGVzdHJveWVkKCkgPyAiQ2Fubm90IHVwZGF0ZSBkZXNjcmlwdG9ycyBmb3IgYCIgKyBzdWJrZXkgKyAiYCBvbiBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKHRoaXMuc291cmNlKSArICJgIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CiAgICAgIHZhciBtYXAgPSB0aGlzLl9kZXNjcmlwdG9ycyB8fCAodGhpcy5fZGVzY3JpcHRvcnMgPSBuZXcgTWFwKCkpOwogICAgICBtYXAuc2V0KHN1YmtleSwgdmFsdWUpOwogICAgfTsKCiAgICBfcHJvdG8ucGVla0Rlc2NyaXB0b3JzID0gZnVuY3Rpb24gcGVla0Rlc2NyaXB0b3JzKHN1YmtleSkgewogICAgICB2YXIgcG9zc2libGVEZXNjID0gdGhpcy5fZmluZEluaGVyaXRlZE1hcCgnX2Rlc2NyaXB0b3JzJywgc3Via2V5KTsKCiAgICAgIHJldHVybiBwb3NzaWJsZURlc2MgPT09IFVOREVGSU5FRCA/IHVuZGVmaW5lZCA6IHBvc3NpYmxlRGVzYzsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZURlc2NyaXB0b3JzID0gZnVuY3Rpb24gcmVtb3ZlRGVzY3JpcHRvcnMoc3Via2V5KSB7CiAgICAgIHRoaXMud3JpdGVEZXNjcmlwdG9ycyhzdWJrZXksIFVOREVGSU5FRCk7CiAgICB9OwoKICAgIF9wcm90by5mb3JFYWNoRGVzY3JpcHRvcnMgPSBmdW5jdGlvbiBmb3JFYWNoRGVzY3JpcHRvcnMoZm4pIHsKICAgICAgdmFyIHBvaW50ZXIgPSB0aGlzOwogICAgICB2YXIgc2VlbjsKCiAgICAgIHdoaWxlIChwb2ludGVyICE9PSBudWxsKSB7CiAgICAgICAgdmFyIG1hcCA9IHBvaW50ZXIuX2Rlc2NyaXB0b3JzOwoKICAgICAgICBpZiAobWFwICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHNlZW4gPSBzZWVuID09PSB1bmRlZmluZWQgPyBuZXcgU2V0KCkgOiBzZWVuOwogICAgICAgICAgbWFwLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHsKICAgICAgICAgICAgaWYgKCFzZWVuLmhhcyhrZXkpKSB7CiAgICAgICAgICAgICAgc2Vlbi5hZGQoa2V5KTsKCiAgICAgICAgICAgICAgaWYgKHZhbHVlICE9PSBVTkRFRklORUQpIHsKICAgICAgICAgICAgICAgIGZuKGtleSwgdmFsdWUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfQoKICAgICAgICBwb2ludGVyID0gcG9pbnRlci5wYXJlbnQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmFkZFRvTGlzdGVuZXJzID0gZnVuY3Rpb24gYWRkVG9MaXN0ZW5lcnMoZXZlbnROYW1lLCB0YXJnZXQsIG1ldGhvZCwgb25jZSwgc3luYykgewogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgY291bnRlcnMuYWRkVG9MaXN0ZW5lcnNDYWxscysrOwogICAgICB9CgogICAgICB0aGlzLnB1c2hMaXN0ZW5lcihldmVudE5hbWUsIHRhcmdldCwgbWV0aG9kLCBvbmNlID8gMQogICAgICAvKiBPTkNFICovCiAgICAgIDogMAogICAgICAvKiBBREQgKi8KICAgICAgLCBzeW5jKTsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUZyb21MaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVGcm9tTGlzdGVuZXJzKGV2ZW50TmFtZSwgdGFyZ2V0LCBtZXRob2QpIHsKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGNvdW50ZXJzLnJlbW92ZUZyb21MaXN0ZW5lcnNDYWxscysrOwogICAgICB9CgogICAgICB0aGlzLnB1c2hMaXN0ZW5lcihldmVudE5hbWUsIHRhcmdldCwgbWV0aG9kLCAyCiAgICAgIC8qIFJFTU9WRSAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8ucHVzaExpc3RlbmVyID0gZnVuY3Rpb24gcHVzaExpc3RlbmVyKGV2ZW50LCB0YXJnZXQsIG1ldGhvZCwga2luZCwgc3luYykgewogICAgICBpZiAoc3luYyA9PT0gdm9pZCAwKSB7CiAgICAgICAgc3luYyA9IGZhbHNlOwogICAgICB9CgogICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy53cml0YWJsZUxpc3RlbmVycygpOwogICAgICB2YXIgaSA9IGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnMsIGV2ZW50LCB0YXJnZXQsIG1ldGhvZCk7IC8vIHJlbW92ZSBpZiBmb3VuZCBsaXN0ZW5lciB3YXMgaW5oZXJpdGVkCgogICAgICBpZiAoaSAhPT0gLTEgJiYgaSA8IHRoaXMuX2luaGVyaXRlZEVuZCkgewogICAgICAgIGxpc3RlbmVycy5zcGxpY2UoaSwgMSk7CiAgICAgICAgdGhpcy5faW5oZXJpdGVkRW5kLS07CiAgICAgICAgaSA9IC0xOwogICAgICB9IC8vIGlmIG5vdCBmb3VuZCwgcHVzaC4gTm90ZSB0aGF0IHdlIG11c3QgYWx3YXlzIHB1c2ggaWYgYSBsaXN0ZW5lciBpcyBub3QKICAgICAgLy8gZm91bmQsIGV2ZW4gaW4gdGhlIGNhc2Ugb2YgYSBmdW5jdGlvbiBsaXN0ZW5lciByZW1vdmUsIGJlY2F1c2Ugd2UgbWF5IGJlCiAgICAgIC8vIGF0dGVtcHRpbmcgdG8gYWRkIG9yIHJlbW92ZSBsaXN0ZW5lcnMgX2JlZm9yZV8gZmxhdHRlbmluZyBoYXMgb2NjdXJlZC4KCgogICAgICBpZiAoaSA9PT0gLTEpIHsKICAgICAgICAoZmFsc2UgJiYgISghKHRoaXMuaXNQcm90b3R5cGVNZXRhKHRoaXMuc291cmNlKSAmJiB0eXBlb2YgbWV0aG9kID09PSAnZnVuY3Rpb24nKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgY2Fubm90IGFkZCBmdW5jdGlvbiBsaXN0ZW5lcnMgdG8gcHJvdG90eXBlcy4gQ29udmVydCB0aGUgbGlzdGVuZXIgdG8gYSBzdHJpbmcgbGlzdGVuZXIsIG9yIGFkZCBpdCB0byB0aGUgaW5zdGFuY2UgaW5zdGVhZC4nLCAhKHRoaXMuaXNQcm90b3R5cGVNZXRhKHRoaXMuc291cmNlKSAmJiB0eXBlb2YgbWV0aG9kID09PSAnZnVuY3Rpb24nKSkpOwogICAgICAgIChmYWxzZSAmJiAhKCEoIXRoaXMuaXNQcm90b3R5cGVNZXRhKHRoaXMuc291cmNlKSAmJiB0eXBlb2YgbWV0aG9kID09PSAnZnVuY3Rpb24nICYmIGtpbmQgPT09IDIKICAgICAgICAvKiBSRU1PVkUgKi8KICAgICAgICApKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gcmVtb3ZlIGEgZnVuY3Rpb24gbGlzdGVuZXIgd2hpY2ggZGlkIG5vdCBleGlzdCBvbiB0aGUgaW5zdGFuY2UsIHdoaWNoIG1lYW5zIHlvdSBtYXkgaGF2ZSBhdHRlbXB0ZWQgdG8gcmVtb3ZlIGl0IGJlZm9yZSBpdCB3YXMgYWRkZWQuJywgISghdGhpcy5pc1Byb3RvdHlwZU1ldGEodGhpcy5zb3VyY2UpICYmIHR5cGVvZiBtZXRob2QgPT09ICdmdW5jdGlvbicgJiYga2luZCA9PT0gMikpKTsKICAgICAgICBsaXN0ZW5lcnMucHVzaCh7CiAgICAgICAgICBldmVudDogZXZlbnQsCiAgICAgICAgICB0YXJnZXQ6IHRhcmdldCwKICAgICAgICAgIG1ldGhvZDogbWV0aG9kLAogICAgICAgICAga2luZDoga2luZCwKICAgICAgICAgIHN5bmM6IHN5bmMKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07IC8vIElmIHRoZSBsaXN0ZW5lciBpcyBvdXIgb3duIGxpc3RlbmVyIGFuZCB3ZSBhcmUgdHJ5aW5nIHRvIHJlbW92ZSBpdCwgd2UKICAgICAgICAvLyB3YW50IHRvIHNwbGljZSBpdCBvdXQgZW50aXJlbHkgc28gd2UgZG9uJ3QgaG9sZCBvbnRvIGEgcmVmZXJlbmNlLgoKICAgICAgICBpZiAoa2luZCA9PT0gMgogICAgICAgIC8qIFJFTU9WRSAqLwogICAgICAgICYmIGxpc3RlbmVyLmtpbmQgIT09IDIKICAgICAgICAvKiBSRU1PVkUgKi8KICAgICAgICApIHsKICAgICAgICAgICAgbGlzdGVuZXJzLnNwbGljZShpLCAxKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAoZmFsc2UgJiYgISghKGxpc3RlbmVyLmtpbmQgPT09IDAKICAgICAgICAgIC8qIEFERCAqLwogICAgICAgICAgJiYga2luZCA9PT0gMAogICAgICAgICAgLyogQUREICovCiAgICAgICAgICAmJiBsaXN0ZW5lci5zeW5jICE9PSBzeW5jKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgYXR0ZW1wdGVkIHRvIGFkZCBhbiBvYnNlcnZlciBmb3IgdGhlIHNhbWUgbWV0aG9kIG9uICciICsgZXZlbnQuc3BsaXQoJzonKVswXSArICInIHR3aWNlIHRvICIgKyB0YXJnZXQgKyAiIGFzIGJvdGggc3luYyBhbmQgYXN5bmMuIE9ic2VydmVycyBtdXN0IGJlIGVpdGhlciBzeW5jIG9yIGFzeW5jLCB0aGV5IGNhbm5vdCBiZSBib3RoLiBUaGlzIGlzIGxpa2VseSBhIG1pc3Rha2UsIHlvdSBzaG91bGQgZWl0aGVyIHJlbW92ZSB0aGUgY29kZSB0aGF0IGFkZGVkIHRoZSBvYnNlcnZlciBhIHNlY29uZCB0aW1lLCBvciB1cGRhdGUgaXQgdG8gYWx3YXlzIGJlIHN5bmMgb3IgYXN5bmMuIFRoZSBtZXRob2Qgd2FzICIgKyBtZXRob2QgKyAiLiIsICEobGlzdGVuZXIua2luZCA9PT0gMCAmJiBraW5kID09PSAwICYmIGxpc3RlbmVyLnN5bmMgIT09IHN5bmMpKSk7IC8vIHVwZGF0ZSBvd24gbGlzdGVuZXIKCiAgICAgICAgICBsaXN0ZW5lci5raW5kID0ga2luZDsKICAgICAgICAgIGxpc3RlbmVyLnN5bmMgPSBzeW5jOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ud3JpdGFibGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiB3cml0YWJsZUxpc3RlbmVycygpIHsKICAgICAgLy8gQ2hlY2sgaWYgd2UgbmVlZCB0byBpbnZhbGlkYXRlIGFuZCByZWZsYXR0ZW4uIFdlIG5lZWQgdG8gZG8gdGhpcyBpZiB3ZQogICAgICAvLyBoYXZlIGFscmVhZHkgZmxhdHRlbmVkIChmbGF0dGVuZWQgdmVyc2lvbiBpcyB0aGUgY3VycmVudCB2ZXJzaW9uKSBhbmQKICAgICAgLy8gd2UgYXJlIGVpdGhlciB3cml0aW5nIHRvIGEgcHJvdG90eXBlIG1ldGEgT1Igd2UgaGF2ZSBuZXZlciBpbmhlcml0ZWQsIGFuZAogICAgICAvLyBtYXkgaGF2ZSBjYWNoZWQgdGhlIHBhcmVudCdzIGxpc3RlbmVycy4KICAgICAgaWYgKHRoaXMuX2ZsYXR0ZW5lZFZlcnNpb24gPT09IGN1cnJlbnRMaXN0ZW5lclZlcnNpb24gJiYgKHRoaXMuc291cmNlID09PSB0aGlzLnByb3RvIHx8IHRoaXMuX2luaGVyaXRlZEVuZCA9PT0gLTEpKSB7CiAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgIGNvdW50ZXJzLnJlb3BlbnNBZnRlckZsYXR0ZW4rKzsKICAgICAgICB9CgogICAgICAgIGN1cnJlbnRMaXN0ZW5lclZlcnNpb24rKzsKICAgICAgfSAvLyBJbmhlcml0ZWQgZW5kIGhhcyBub3QgYmVlbiBzZXQsIHRoZW4gd2UgaGF2ZSBuZXZlciBjcmVhdGVkIG91ciBvd24KICAgICAgLy8gbGlzdGVuZXJzLCBidXQgbWF5IGhhdmUgY2FjaGVkIHRoZSBwYXJlbnQncwoKCiAgICAgIGlmICh0aGlzLl9pbmhlcml0ZWRFbmQgPT09IC0xKSB7CiAgICAgICAgdGhpcy5faW5oZXJpdGVkRW5kID0gMDsKICAgICAgICB0aGlzLl9saXN0ZW5lcnMgPSBbXTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuX2xpc3RlbmVyczsKICAgIH0KICAgIC8qKgogICAgICBGbGF0dGVuaW5nIGlzIGJhc2VkIG9uIGEgZ2xvYmFsIHJldmlzaW9uIGNvdW50ZXIuIElmIHRoZSByZXZpc2lvbiBoYXMKICAgICAgYnVtcGVkIGl0IG1lYW5zIHRoYXQgc29tZXdoZXJlIGluIGEgY2xhc3MgaW5oZXJpdGFuY2UgY2hhaW4gc29tZXRoaW5nIGhhcwogICAgICBjaGFuZ2VkLCBzbyB3ZSBuZWVkIHRvIHJlZmxhdHRlbiBldmVyeXRoaW5nLiBUaGlzIGNhbiBvbmx5IGhhcHBlbiBpZjoKICAgICAgICAgMS4gQSBtZXRhIGhhcyBiZWVuIGZsYXR0ZW5lZCAobGlzdGVuZXIgaGFzIGJlZW4gY2FsbGVkKQogICAgICAyLiBUaGUgbWV0YSBpcyBhIHByb3RvdHlwZSBtZXRhIHdpdGggY2hpbGRyZW4gd2hvIGhhdmUgaW5oZXJpdGVkIGl0cwogICAgICAgICBsaXN0ZW5lcnMKICAgICAgMy4gQSBuZXcgbGlzdGVuZXIgaXMgc3Vic2VxdWVudGx5IGFkZGVkIHRvIHRoZSBtZXRhIChlLmcuIHZpYSBgLnJlb3BlbigpYCkKICAgICAgICAgVGhpcyBpcyBhIHZlcnkgcmFyZSBvY2N1cmVuY2UsIHNvIHdoaWxlIHRoZSBjb3VudGVyIGlzIGdsb2JhbCBpdCBzaG91bGRuJ3QKICAgICAgYmUgdXBkYXRlZCB2ZXJ5IG9mdGVuIGluIHByYWN0aWNlLgogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZmxhdHRlbmVkTGlzdGVuZXJzID0gZnVuY3Rpb24gZmxhdHRlbmVkTGlzdGVuZXJzKCkgewogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgY291bnRlcnMuZmxhdHRlbmVkTGlzdGVuZXJzQ2FsbHMrKzsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuX2ZsYXR0ZW5lZFZlcnNpb24gPCBjdXJyZW50TGlzdGVuZXJWZXJzaW9uKSB7CiAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgIGNvdW50ZXJzLmxpc3RlbmVyc0ZsYXR0ZW5lZCsrOwogICAgICAgIH0KCiAgICAgICAgdmFyIHBhcmVudCA9IHRoaXMucGFyZW50OwoKICAgICAgICBpZiAocGFyZW50ICE9PSBudWxsKSB7CiAgICAgICAgICAvLyBjb21wdXRlCiAgICAgICAgICB2YXIgcGFyZW50TGlzdGVuZXJzID0gcGFyZW50LmZsYXR0ZW5lZExpc3RlbmVycygpOwoKICAgICAgICAgIGlmIChwYXJlbnRMaXN0ZW5lcnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBpZiAodGhpcy5fbGlzdGVuZXJzID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAvLyBJZiB0aGlzIGluc3RhbmNlIGRvZXNuJ3QgaGF2ZSBhbnkgb2YgaXRzIG93biBsaXN0ZW5lcnMgKHdyaXRhYmxlTGlzdGVuZXJzCiAgICAgICAgICAgICAgLy8gaGFzIG5ldmVyIGJlZW4gY2FsbGVkKSB0aGVuIHdlIGRvbid0IG5lZWQgdG8gZG8gYW55IGZsYXR0ZW5pbmcsIHJldHVybgogICAgICAgICAgICAgIC8vIHRoZSBwYXJlbnQncyBsaXN0ZW5lcnMgaW5zdGVhZC4KICAgICAgICAgICAgICBpZiAoZmFsc2UKICAgICAgICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICAgICAgICkgewogICAgICAgICAgICAgICAgY291bnRlcnMucGFyZW50TGlzdGVuZXJzVXNlZCsrOwogICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgdGhpcy5fbGlzdGVuZXJzID0gcGFyZW50TGlzdGVuZXJzOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnM7CgogICAgICAgICAgICAgIGlmICh0aGlzLl9pbmhlcml0ZWRFbmQgPiAwKSB7CiAgICAgICAgICAgICAgICBsaXN0ZW5lcnMuc3BsaWNlKDAsIHRoaXMuX2luaGVyaXRlZEVuZCk7CiAgICAgICAgICAgICAgICB0aGlzLl9pbmhlcml0ZWRFbmQgPSAwOwogICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJlbnRMaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIHZhciBsaXN0ZW5lciA9IHBhcmVudExpc3RlbmVyc1tpXTsKICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnMsIGxpc3RlbmVyLmV2ZW50LCBsaXN0ZW5lci50YXJnZXQsIGxpc3RlbmVyLm1ldGhvZCk7CgogICAgICAgICAgICAgICAgaWYgKGluZGV4ID09PSAtMSkgewogICAgICAgICAgICAgICAgICBpZiAoZmFsc2UKICAgICAgICAgICAgICAgICAgLyogREVCVUcgKi8KICAgICAgICAgICAgICAgICAgKSB7CiAgICAgICAgICAgICAgICAgICAgY291bnRlcnMubGlzdGVuZXJzSW5oZXJpdGVkKys7CiAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgIGxpc3RlbmVycy51bnNoaWZ0KGxpc3RlbmVyKTsKICAgICAgICAgICAgICAgICAgdGhpcy5faW5oZXJpdGVkRW5kKys7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB0aGlzLl9mbGF0dGVuZWRWZXJzaW9uID0gY3VycmVudExpc3RlbmVyVmVyc2lvbjsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuX2xpc3RlbmVyczsKICAgIH07CgogICAgX3Byb3RvLm1hdGNoaW5nTGlzdGVuZXJzID0gZnVuY3Rpb24gbWF0Y2hpbmdMaXN0ZW5lcnMoZXZlbnROYW1lKSB7CiAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmZsYXR0ZW5lZExpc3RlbmVycygpOwogICAgICB2YXIgcmVzdWx0OwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGNvdW50ZXJzLm1hdGNoaW5nTGlzdGVuZXJzQ2FsbHMrKzsKICAgICAgfQoKICAgICAgaWYgKGxpc3RlbmVycyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxpc3RlbmVycy5sZW5ndGg7IGluZGV4KyspIHsKICAgICAgICAgIHZhciBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpbmRleF07IC8vIFJFTU9WRSBsaXN0ZW5lcnMgYXJlIHBsYWNlaG9sZGVycyB0aGF0IHRlbGwgdXMgbm90IHRvCiAgICAgICAgICAvLyBpbmhlcml0LCBzbyB0aGV5IG5ldmVyIG1hdGNoLiBPbmx5IEFERCBhbmQgT05DRSBjYW4gbWF0Y2guCgogICAgICAgICAgaWYgKGxpc3RlbmVyLmV2ZW50ID09PSBldmVudE5hbWUgJiYgKGxpc3RlbmVyLmtpbmQgPT09IDAKICAgICAgICAgIC8qIEFERCAqLwogICAgICAgICAgfHwgbGlzdGVuZXIua2luZCA9PT0gMQogICAgICAgICAgLyogT05DRSAqLwogICAgICAgICAgKSkgewogICAgICAgICAgICBpZiAocmVzdWx0ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAvLyB3ZSBjcmVhdGUgdGhpcyBhcnJheSBvbmx5IGFmdGVyIHdlJ3ZlIGZvdW5kIGEgbGlzdGVuZXIgdGhhdAogICAgICAgICAgICAgIC8vIG1hdGNoZXMgdG8gYXZvaWQgYWxsb2NhdGlvbnMgd2hlbiBubyBtYXRjaGVzIGFyZSBmb3VuZC4KICAgICAgICAgICAgICByZXN1bHQgPSBbXTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgcmVzdWx0LnB1c2gobGlzdGVuZXIudGFyZ2V0LCBsaXN0ZW5lci5tZXRob2QsIGxpc3RlbmVyLmtpbmQgPT09IDEKICAgICAgICAgICAgLyogT05DRSAqLwogICAgICAgICAgICApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH07CgogICAgX3Byb3RvLm9ic2VydmVyRXZlbnRzID0gZnVuY3Rpb24gb2JzZXJ2ZXJFdmVudHMoKSB7CiAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmZsYXR0ZW5lZExpc3RlbmVycygpOwogICAgICB2YXIgcmVzdWx0OwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGNvdW50ZXJzLm9ic2VydmVyRXZlbnRzQ2FsbHMrKzsKICAgICAgfQoKICAgICAgaWYgKGxpc3RlbmVycyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxpc3RlbmVycy5sZW5ndGg7IGluZGV4KyspIHsKICAgICAgICAgIHZhciBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpbmRleF07IC8vIFJFTU9WRSBsaXN0ZW5lcnMgYXJlIHBsYWNlaG9sZGVycyB0aGF0IHRlbGwgdXMgbm90IHRvCiAgICAgICAgICAvLyBpbmhlcml0LCBzbyB0aGV5IG5ldmVyIG1hdGNoLiBPbmx5IEFERCBhbmQgT05DRSBjYW4gbWF0Y2guCgogICAgICAgICAgaWYgKChsaXN0ZW5lci5raW5kID09PSAwCiAgICAgICAgICAvKiBBREQgKi8KICAgICAgICAgIHx8IGxpc3RlbmVyLmtpbmQgPT09IDEKICAgICAgICAgIC8qIE9OQ0UgKi8KICAgICAgICAgICkgJiYgbGlzdGVuZXIuZXZlbnQuaW5kZXhPZignOmNoYW5nZScpICE9PSAtMSkgewogICAgICAgICAgICBpZiAocmVzdWx0ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAvLyB3ZSBjcmVhdGUgdGhpcyBhcnJheSBvbmx5IGFmdGVyIHdlJ3ZlIGZvdW5kIGEgbGlzdGVuZXIgdGhhdAogICAgICAgICAgICAgIC8vIG1hdGNoZXMgdG8gYXZvaWQgYWxsb2NhdGlvbnMgd2hlbiBubyBtYXRjaGVzIGFyZSBmb3VuZC4KICAgICAgICAgICAgICByZXN1bHQgPSBbXTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgcmVzdWx0LnB1c2gobGlzdGVuZXIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH07CgogICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShNZXRhLCBbewogICAgICBrZXk6ICJwYXJlbnQiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICB2YXIgcGFyZW50ID0gdGhpcy5fcGFyZW50OwoKICAgICAgICBpZiAocGFyZW50ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHZhciBwcm90byA9IGdldFByb3RvdHlwZU9mKHRoaXMuc291cmNlKTsKICAgICAgICAgIHRoaXMuX3BhcmVudCA9IHBhcmVudCA9IHByb3RvID09PSBudWxsIHx8IHByb3RvID09PSBvYmplY3RQcm90b3R5cGUgPyBudWxsIDogbWV0YShwcm90byk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcGFyZW50OwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gTWV0YTsKICB9KCk7CgogIF9leHBvcnRzLk1ldGEgPSBNZXRhOwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgTWV0YS5wcm90b3R5cGUud3JpdGVWYWx1ZXMgPSBmdW5jdGlvbiAoc3Via2V5LCB2YWx1ZSkgewogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc01ldGFEZXN0cm95ZWQoKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKHRoaXMuaXNNZXRhRGVzdHJveWVkKCkgPyAiQ2Fubm90IHNldCB0aGUgdmFsdWUgb2YgYCIgKyBzdWJrZXkgKyAiYCBvbiBgIiArICgwLCBfdXRpbHMudG9TdHJpbmcpKHRoaXMuc291cmNlKSArICJgIGFmdGVyIGl0IGhhcyBiZWVuIGRlc3Ryb3llZC4iIDogJycsICF0aGlzLmlzTWV0YURlc3Ryb3llZCgpKSk7CgogICAgICB2YXIgbWFwID0gdGhpcy5fZ2V0T3JDcmVhdGVPd25NYXAoJ192YWx1ZXMnKTsKCiAgICAgIG1hcFtzdWJrZXldID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IFVOREVGSU5FRCA6IHZhbHVlOwogICAgfTsKCiAgICBNZXRhLnByb3RvdHlwZS5wZWVrVmFsdWVzID0gZnVuY3Rpb24gKGtleSkgewogICAgICB2YXIgdmFsID0gdGhpcy5fZmluZEluaGVyaXRlZDIoJ192YWx1ZXMnLCBrZXkpOwoKICAgICAgcmV0dXJuIHZhbCA9PT0gVU5ERUZJTkVEID8gdW5kZWZpbmVkIDogdmFsOwogICAgfTsKCiAgICBNZXRhLnByb3RvdHlwZS5kZWxldGVGcm9tVmFsdWVzID0gZnVuY3Rpb24gKGtleSkgewogICAgICBkZWxldGUgdGhpcy5fZ2V0T3JDcmVhdGVPd25NYXAoJ192YWx1ZXMnKVtrZXldOwogICAgfTsKCiAgICBNZXRhLnByb3RvdHlwZS5yZWFkSW5oZXJpdGVkVmFsdWUgPSBmdW5jdGlvbiAoa2V5KSB7CiAgICAgIHJldHVybiB0aGlzLl9maW5kSW5oZXJpdGVkMignX3ZhbHVlcycsIGtleSk7CiAgICB9OwoKICAgIE1ldGEucHJvdG90eXBlLndyaXRlVmFsdWUgPSBmdW5jdGlvbiAob2JqLCBrZXksIHZhbHVlKSB7CiAgICAgIHZhciBkZXNjcmlwdG9yID0gKDAsIF91dGlscy5sb29rdXBEZXNjcmlwdG9yKShvYmosIGtleSk7CiAgICAgIHZhciBpc01hbmRhdG9yeVNldHRlciA9IGRlc2NyaXB0b3IgIT09IG51bGwgJiYgZGVzY3JpcHRvci5zZXQgJiYgZGVzY3JpcHRvci5zZXQuaXNNYW5kYXRvcnlTZXR0ZXI7CgogICAgICBpZiAoaXNNYW5kYXRvcnlTZXR0ZXIpIHsKICAgICAgICB0aGlzLndyaXRlVmFsdWVzKGtleSwgdmFsdWUpOwogICAgICB9IGVsc2UgewogICAgICAgIG9ialtrZXldID0gdmFsdWU7CiAgICAgIH0KICAgIH07CiAgfQoKICB2YXIgZ2V0UHJvdG90eXBlT2YgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Y7CiAgdmFyIG1ldGFTdG9yZSA9IG5ldyBXZWFrTWFwKCk7CgogIGZ1bmN0aW9uIHNldE1ldGEob2JqLCBtZXRhKSB7CiAgICAoZmFsc2UgJiYgIShvYmogIT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IGNhbGwgYHNldE1ldGFgIG9uIG51bGwnLCBvYmogIT09IG51bGwpKTsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0Nhbm5vdCBjYWxsIGBzZXRNZXRhYCBvbiB1bmRlZmluZWQnLCBvYmogIT09IHVuZGVmaW5lZCkpOwogICAgKGZhbHNlICYmICEodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJDYW5ub3QgY2FsbCBgc2V0TWV0YWAgb24gIiArIHR5cGVvZiBvYmosIHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpKTsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgY291bnRlcnMuc2V0Q2FsbHMrKzsKICAgIH0KCiAgICBtZXRhU3RvcmUuc2V0KG9iaiwgbWV0YSk7CiAgfQoKICBmdW5jdGlvbiBwZWVrTWV0YShvYmopIHsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdDYW5ub3QgY2FsbCBgcGVla01ldGFgIG9uIG51bGwnLCBvYmogIT09IG51bGwpKTsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0Nhbm5vdCBjYWxsIGBwZWVrTWV0YWAgb24gdW5kZWZpbmVkJywgb2JqICE9PSB1bmRlZmluZWQpKTsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IGNhbGwgYHBlZWtNZXRhYCBvbiAiICsgdHlwZW9mIG9iaiwgdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykpOwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBjb3VudGVycy5wZWVrQ2FsbHMrKzsKICAgIH0KCiAgICB2YXIgbWV0YSA9IG1ldGFTdG9yZS5nZXQob2JqKTsKCiAgICBpZiAobWV0YSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBtZXRhOwogICAgfQoKICAgIHZhciBwb2ludGVyID0gZ2V0UHJvdG90eXBlT2Yob2JqKTsKCiAgICB3aGlsZSAocG9pbnRlciAhPT0gbnVsbCkgewogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgY291bnRlcnMucGVla1Byb3RvdHlwZVdhbGtzKys7CiAgICAgIH0KCiAgICAgIG1ldGEgPSBtZXRhU3RvcmUuZ2V0KHBvaW50ZXIpOwoKICAgICAgaWYgKG1ldGEgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGlmIChtZXRhLnByb3RvICE9PSBwb2ludGVyKSB7CiAgICAgICAgICAvLyBUaGUgbWV0YSB3YXMgYSBwcm90b3R5cGUgbWV0YSB3aGljaCB3YXMgbm90IG1hcmtlZCBhcyBpbml0aWFsaXppbmcuCiAgICAgICAgICAvLyBUaGlzIGNhbiBoYXBwZW4gd2hlbiBhIHByb3RvdHlwZSBjaGFpbiB3YXMgY3JlYXRlZCBtYW51YWxseSB2aWEKICAgICAgICAgIC8vIE9iamVjdC5jcmVhdGUoKSBhbmQgdGhlIHNvdXJjZSBvYmplY3QgZG9lcyBub3QgaGF2ZSBhIGNvbnN0cnVjdG9yLgogICAgICAgICAgbWV0YS5wcm90byA9IHBvaW50ZXI7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gbWV0YTsKICAgICAgfQoKICAgICAgcG9pbnRlciA9IGdldFByb3RvdHlwZU9mKHBvaW50ZXIpOwogICAgfQoKICAgIHJldHVybiBudWxsOwogIH0KICAvKioKICAgIFRlYXJzIGRvd24gdGhlIG1ldGEgb24gYW4gb2JqZWN0IHNvIHRoYXQgaXQgY2FuIGJlIGdhcmJhZ2UgY29sbGVjdGVkLgogICAgTXVsdGlwbGUgY2FsbHMgd2lsbCBoYXZlIG5vIGVmZmVjdC4KICAKICAgIEBtZXRob2QgZGVsZXRlTWV0YQogICAgQGZvciBFbWJlcgogICAgQHBhcmFtIHtPYmplY3R9IG9iaiAgdGhlIG9iamVjdCB0byBkZXN0cm95CiAgICBAcmV0dXJuIHt2b2lkfQogICAgQHByaXZhdGUKICAqLwoKCiAgZnVuY3Rpb24gZGVsZXRlTWV0YShvYmopIHsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdDYW5ub3QgY2FsbCBgZGVsZXRlTWV0YWAgb24gbnVsbCcsIG9iaiAhPT0gbnVsbCkpOwogICAgKGZhbHNlICYmICEob2JqICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IGNhbGwgYGRlbGV0ZU1ldGFgIG9uIHVuZGVmaW5lZCcsIG9iaiAhPT0gdW5kZWZpbmVkKSk7CiAgICAoZmFsc2UgJiYgISh0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyB8fCB0eXBlb2Ygb2JqID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkNhbm5vdCBjYWxsIGBkZWxldGVNZXRhYCBvbiAiICsgdHlwZW9mIG9iaiwgdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykpOwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBjb3VudGVycy5kZWxldGVDYWxscysrOwogICAgfQoKICAgIHZhciBtZXRhID0gcGVla01ldGEob2JqKTsKCiAgICBpZiAobWV0YSAhPT0gbnVsbCkgewogICAgICBtZXRhLmRlc3Ryb3koKTsKICAgIH0KICB9CiAgLyoqCiAgICBSZXRyaWV2ZXMgdGhlIG1ldGEgaGFzaCBmb3IgYW4gb2JqZWN0LiBJZiBgd3JpdGFibGVgIGlzIHRydWUgZW5zdXJlcyB0aGUKICAgIGhhc2ggaXMgd3JpdGFibGUgZm9yIHRoaXMgb2JqZWN0IGFzIHdlbGwuCiAgCiAgICBUaGUgbWV0YSBvYmplY3QgY29udGFpbnMgaW5mb3JtYXRpb24gYWJvdXQgY29tcHV0ZWQgcHJvcGVydHkgZGVzY3JpcHRvcnMgYXMKICAgIHdlbGwgYXMgYW55IHdhdGNoZWQgcHJvcGVydGllcyBhbmQgb3RoZXIgaW5mb3JtYXRpb24uIFlvdSBnZW5lcmFsbHkgd2lsbAogICAgbm90IGFjY2VzcyB0aGlzIGluZm9ybWF0aW9uIGRpcmVjdGx5IGJ1dCBpbnN0ZWFkIHdvcmsgd2l0aCBoaWdoZXIgbGV2ZWwKICAgIG1ldGhvZHMgdGhhdCBtYW5pcHVsYXRlIHRoaXMgaGFzaCBpbmRpcmVjdGx5LgogIAogICAgQG1ldGhvZCBtZXRhCiAgICBAZm9yIEVtYmVyCiAgICBAcHJpdmF0ZQogIAogICAgQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIHJldHJpZXZlIG1ldGEgZm9yCiAgICBAcGFyYW0ge0Jvb2xlYW59IFt3cml0YWJsZT10cnVlXSBQYXNzIGBmYWxzZWAgaWYgeW91IGRvIG5vdCBpbnRlbmQgdG8gbW9kaWZ5CiAgICAgIHRoZSBtZXRhIGhhc2gsIGFsbG93aW5nIHRoZSBtZXRob2QgdG8gYXZvaWQgbWFraW5nIGFuIHVubmVjZXNzYXJ5IGNvcHkuCiAgICBAcmV0dXJuIHtPYmplY3R9IHRoZSBtZXRhIGhhc2ggZm9yIGFuIG9iamVjdAogICovCgoKICB2YXIgbWV0YSA9IGZ1bmN0aW9uIG1ldGEob2JqKSB7CiAgICAoZmFsc2UgJiYgIShvYmogIT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IGNhbGwgYG1ldGFgIG9uIG51bGwnLCBvYmogIT09IG51bGwpKTsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0Nhbm5vdCBjYWxsIGBtZXRhYCBvbiB1bmRlZmluZWQnLCBvYmogIT09IHVuZGVmaW5lZCkpOwogICAgKGZhbHNlICYmICEodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJDYW5ub3QgY2FsbCBgbWV0YWAgb24gIiArIHR5cGVvZiBvYmosIHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpKTsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgY291bnRlcnMubWV0YUNhbGxzKys7CiAgICB9CgogICAgdmFyIG1heWJlTWV0YSA9IHBlZWtNZXRhKG9iaik7IC8vIHJlbW92ZSB0aGlzIGNvZGUsIGluLWZhdm9yIG9mIGV4cGxpY2l0IHBhcmVudAoKICAgIGlmIChtYXliZU1ldGEgIT09IG51bGwgJiYgbWF5YmVNZXRhLnNvdXJjZSA9PT0gb2JqKSB7CiAgICAgIHJldHVybiBtYXliZU1ldGE7CiAgICB9CgogICAgdmFyIG5ld01ldGEgPSBuZXcgTWV0YShvYmopOwogICAgc2V0TWV0YShvYmosIG5ld01ldGEpOwogICAgcmV0dXJuIG5ld01ldGE7CiAgfTsKCiAgX2V4cG9ydHMubWV0YSA9IG1ldGE7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICBtZXRhLl9jb3VudGVycyA9IGNvdW50ZXJzOwogIH0KCiAgZnVuY3Rpb24gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVycywgZXZlbnQsIHRhcmdldCwgbWV0aG9kKSB7CiAgICBmb3IgKHZhciBpID0gbGlzdGVuZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgIHZhciBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXTsKCiAgICAgIGlmIChsaXN0ZW5lci5ldmVudCA9PT0gZXZlbnQgJiYgbGlzdGVuZXIudGFyZ2V0ID09PSB0YXJnZXQgJiYgbGlzdGVuZXIubWV0aG9kID09PSBtZXRob2QpIHsKICAgICAgICByZXR1cm4gaTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiAtMTsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL21ldGFsL2luZGV4IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YSIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL3J1bmxvb3AiLCAiQGdsaW1tZXIvcmVmZXJlbmNlIiwgIkBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50IiwgIkBlbWJlci9lcnJvciIsICJlbWJlci92ZXJzaW9uIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2VtYmVyQmFiZWwsIF9wb2x5ZmlsbHMsIF9tZXRhMiwgX3V0aWxzLCBfZGVidWcsIF9ydW5sb29wLCBfcmVmZXJlbmNlLCBfZW52aXJvbm1lbnQsIF9lcnJvciwgX3ZlcnNpb24sIF9kZXByZWNhdGVkRmVhdHVyZXMsIF9vd25lcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuY29tcHV0ZWQgPSBjb21wdXRlZDsKICBfZXhwb3J0cy5pc0NvbXB1dGVkID0gaXNDb21wdXRlZDsKICBfZXhwb3J0cy5nZXRDYWNoZUZvciA9IGdldENhY2hlRm9yOwogIF9leHBvcnRzLmdldENhY2hlZFZhbHVlRm9yID0gZ2V0Q2FjaGVkVmFsdWVGb3I7CiAgX2V4cG9ydHMucGVla0NhY2hlRm9yID0gcGVla0NhY2hlRm9yOwogIF9leHBvcnRzLmFsaWFzID0gYWxpYXM7CiAgX2V4cG9ydHMuZGVwcmVjYXRlUHJvcGVydHkgPSBkZXByZWNhdGVQcm9wZXJ0eTsKICBfZXhwb3J0cy5fZ2V0UGF0aCA9IF9nZXRQYXRoOwogIF9leHBvcnRzLmdldCA9IF9nZXQyOwogIF9leHBvcnRzLmdldFdpdGhEZWZhdWx0ID0gZ2V0V2l0aERlZmF1bHQ7CiAgX2V4cG9ydHMuc2V0ID0gX3NldDI7CiAgX2V4cG9ydHMudHJ5U2V0ID0gdHJ5U2V0OwogIF9leHBvcnRzLm9iamVjdEF0ID0gb2JqZWN0QXQ7CiAgX2V4cG9ydHMucmVwbGFjZSA9IHJlcGxhY2U7CiAgX2V4cG9ydHMucmVwbGFjZUluTmF0aXZlQXJyYXkgPSByZXBsYWNlSW5OYXRpdmVBcnJheTsKICBfZXhwb3J0cy5hZGRBcnJheU9ic2VydmVyID0gYWRkQXJyYXlPYnNlcnZlcjsKICBfZXhwb3J0cy5yZW1vdmVBcnJheU9ic2VydmVyID0gcmVtb3ZlQXJyYXlPYnNlcnZlcjsKICBfZXhwb3J0cy5hcnJheUNvbnRlbnRXaWxsQ2hhbmdlID0gYXJyYXlDb250ZW50V2lsbENoYW5nZTsKICBfZXhwb3J0cy5hcnJheUNvbnRlbnREaWRDaGFuZ2UgPSBhcnJheUNvbnRlbnREaWRDaGFuZ2U7CiAgX2V4cG9ydHMuZWFjaFByb3h5Rm9yID0gZWFjaFByb3h5Rm9yOwogIF9leHBvcnRzLmVhY2hQcm94eUFycmF5V2lsbENoYW5nZSA9IGVhY2hQcm94eUFycmF5V2lsbENoYW5nZTsKICBfZXhwb3J0cy5lYWNoUHJveHlBcnJheURpZENoYW5nZSA9IGVhY2hQcm94eUFycmF5RGlkQ2hhbmdlOwogIF9leHBvcnRzLmFkZExpc3RlbmVyID0gYWRkTGlzdGVuZXI7CiAgX2V4cG9ydHMuaGFzTGlzdGVuZXJzID0gaGFzTGlzdGVuZXJzOwogIF9leHBvcnRzLm9uID0gb247CiAgX2V4cG9ydHMucmVtb3ZlTGlzdGVuZXIgPSByZW1vdmVMaXN0ZW5lcjsKICBfZXhwb3J0cy5zZW5kRXZlbnQgPSBzZW5kRXZlbnQ7CiAgX2V4cG9ydHMuaXNOb25lID0gaXNOb25lOwogIF9leHBvcnRzLmlzRW1wdHkgPSBpc0VtcHR5OwogIF9leHBvcnRzLmlzQmxhbmsgPSBpc0JsYW5rOwogIF9leHBvcnRzLmlzUHJlc2VudCA9IGlzUHJlc2VudDsKICBfZXhwb3J0cy5iZWdpblByb3BlcnR5Q2hhbmdlcyA9IGJlZ2luUHJvcGVydHlDaGFuZ2VzOwogIF9leHBvcnRzLmNoYW5nZVByb3BlcnRpZXMgPSBjaGFuZ2VQcm9wZXJ0aWVzOwogIF9leHBvcnRzLmVuZFByb3BlcnR5Q2hhbmdlcyA9IGVuZFByb3BlcnR5Q2hhbmdlczsKICBfZXhwb3J0cy5ub3RpZnlQcm9wZXJ0eUNoYW5nZSA9IG5vdGlmeVByb3BlcnR5Q2hhbmdlOwogIF9leHBvcnRzLm92ZXJyaWRlQ2hhaW5zID0gb3ZlcnJpZGVDaGFpbnM7CiAgX2V4cG9ydHMuZGVmaW5lUHJvcGVydHkgPSBkZWZpbmVQcm9wZXJ0eTsKICBfZXhwb3J0cy5pc0VsZW1lbnREZXNjcmlwdG9yID0gaXNFbGVtZW50RGVzY3JpcHRvcjsKICBfZXhwb3J0cy5uYXRpdmVEZXNjRGVjb3JhdG9yID0gbmF0aXZlRGVzY0RlY29yYXRvcjsKICBfZXhwb3J0cy5kZXNjcmlwdG9yRm9yRGVjb3JhdG9yID0gZGVzY3JpcHRvckZvckRlY29yYXRvcjsKICBfZXhwb3J0cy5kZXNjcmlwdG9yRm9yUHJvcGVydHkgPSBkZXNjcmlwdG9yRm9yUHJvcGVydHk7CiAgX2V4cG9ydHMuaXNDbGFzc2ljRGVjb3JhdG9yID0gaXNDbGFzc2ljRGVjb3JhdG9yOwogIF9leHBvcnRzLnNldENsYXNzaWNEZWNvcmF0b3IgPSBzZXRDbGFzc2ljRGVjb3JhdG9yOwogIF9leHBvcnRzLndhdGNoS2V5ID0gd2F0Y2hLZXk7CiAgX2V4cG9ydHMudW53YXRjaEtleSA9IHVud2F0Y2hLZXk7CiAgX2V4cG9ydHMuZmluaXNoQ2hhaW5zID0gZmluaXNoQ2hhaW5zOwogIF9leHBvcnRzLnJlbW92ZUNoYWluV2F0Y2hlciA9IHJlbW92ZUNoYWluV2F0Y2hlcjsKICBfZXhwb3J0cy5nZXRDaGFpblRhZ3NGb3JLZXkgPSBnZXRDaGFpblRhZ3NGb3JLZXk7CiAgX2V4cG9ydHMud2F0Y2hQYXRoID0gd2F0Y2hQYXRoOwogIF9leHBvcnRzLnVud2F0Y2hQYXRoID0gdW53YXRjaFBhdGg7CiAgX2V4cG9ydHMuaXNXYXRjaGluZyA9IGlzV2F0Y2hpbmc7CiAgX2V4cG9ydHMudW53YXRjaCA9IHVud2F0Y2g7CiAgX2V4cG9ydHMud2F0Y2ggPSB3YXRjaDsKICBfZXhwb3J0cy53YXRjaGVyQ291bnQgPSB3YXRjaGVyQ291bnQ7CiAgX2V4cG9ydHMuZ2V0UHJvcGVydGllcyA9IGdldFByb3BlcnRpZXM7CiAgX2V4cG9ydHMuc2V0UHJvcGVydGllcyA9IHNldFByb3BlcnRpZXM7CiAgX2V4cG9ydHMuZXhwYW5kUHJvcGVydGllcyA9IGV4cGFuZFByb3BlcnRpZXM7CiAgX2V4cG9ydHMuYWRkT2JzZXJ2ZXIgPSBhZGRPYnNlcnZlcjsKICBfZXhwb3J0cy5hY3RpdmF0ZU9ic2VydmVyID0gYWN0aXZhdGVPYnNlcnZlcjsKICBfZXhwb3J0cy5yZW1vdmVPYnNlcnZlciA9IHJlbW92ZU9ic2VydmVyOwogIF9leHBvcnRzLmZsdXNoQXN5bmNPYnNlcnZlcnMgPSBmbHVzaEFzeW5jT2JzZXJ2ZXJzOwogIF9leHBvcnRzLm1peGluID0gbWl4aW47CiAgX2V4cG9ydHMub2JzZXJ2ZXIgPSBvYnNlcnZlcjsKICBfZXhwb3J0cy5hcHBseU1peGluID0gYXBwbHlNaXhpbjsKICBfZXhwb3J0cy5pbmplY3QgPSBpbmplY3Q7CiAgX2V4cG9ydHMudGFnRm9yUHJvcGVydHkgPSB0YWdGb3JQcm9wZXJ0eTsKICBfZXhwb3J0cy50YWdGb3IgPSB0YWdGb3I7CiAgX2V4cG9ydHMubWFya09iamVjdEFzRGlydHkgPSBtYXJrT2JqZWN0QXNEaXJ0eTsKICBfZXhwb3J0cy5jb25zdW1lID0gY29uc3VtZTsKICBfZXhwb3J0cy50cmFja2VkID0gdHJhY2tlZDsKICBfZXhwb3J0cy50cmFjayA9IHRyYWNrOwogIF9leHBvcnRzLnVudHJhY2sgPSB1bnRyYWNrOwogIF9leHBvcnRzLmlzVHJhY2tpbmcgPSBpc1RyYWNraW5nOwogIF9leHBvcnRzLmFkZE5hbWVzcGFjZSA9IGFkZE5hbWVzcGFjZTsKICBfZXhwb3J0cy5jbGFzc1RvU3RyaW5nID0gY2xhc3NUb1N0cmluZzsKICBfZXhwb3J0cy5maW5kTmFtZXNwYWNlID0gZmluZE5hbWVzcGFjZTsKICBfZXhwb3J0cy5maW5kTmFtZXNwYWNlcyA9IGZpbmROYW1lc3BhY2VzOwogIF9leHBvcnRzLnByb2Nlc3NOYW1lc3BhY2UgPSBwcm9jZXNzTmFtZXNwYWNlOwogIF9leHBvcnRzLnByb2Nlc3NBbGxOYW1lc3BhY2VzID0gcHJvY2Vzc0FsbE5hbWVzcGFjZXM7CiAgX2V4cG9ydHMucmVtb3ZlTmFtZXNwYWNlID0gcmVtb3ZlTmFtZXNwYWNlOwogIF9leHBvcnRzLmlzTmFtZXNwYWNlU2VhcmNoRGlzYWJsZWQgPSBpc1NlYXJjaERpc2FibGVkOwogIF9leHBvcnRzLnNldE5hbWVzcGFjZVNlYXJjaERpc2FibGVkID0gc2V0U2VhcmNoRGlzYWJsZWQ7CiAgX2V4cG9ydHMuTkFNRVNQQUNFU19CWV9JRCA9IF9leHBvcnRzLk5BTUVTUEFDRVMgPSBfZXhwb3J0cy5UcmFja2VyID0gX2V4cG9ydHMuYXNzZXJ0Tm90UmVuZGVyZWQgPSBfZXhwb3J0cy5kaWRSZW5kZXIgPSBfZXhwb3J0cy5ydW5JblRyYW5zYWN0aW9uID0gX2V4cG9ydHMuVU5LTk9XTl9QUk9QRVJUWV9UQUcgPSBfZXhwb3J0cy5ERUJVR19JTkpFQ1RJT05fRlVOQ1RJT05TID0gX2V4cG9ydHMuYWxpYXNNZXRob2QgPSBfZXhwb3J0cy5NaXhpbiA9IF9leHBvcnRzLkxpYnJhcmllcyA9IF9leHBvcnRzLmxpYnJhcmllcyA9IF9leHBvcnRzLkFSR1NfUFJPWFlfVEFHUyA9IF9leHBvcnRzLkNoYWluTm9kZSA9IF9leHBvcnRzLlBST1BFUlRZX0RJRF9DSEFOR0UgPSBfZXhwb3J0cy5QUk9YWV9DT05URU5UID0gX2V4cG9ydHMuQ29tcHV0ZWRQcm9wZXJ0eSA9IF9leHBvcnRzLl9nbG9iYWxzQ29tcHV0ZWQgPSB2b2lkIDA7CiAgdmFyIENPTVBVVEVEX1BST1BFUlRZX0NBQ0hFRF9WQUxVRVMgPSBuZXcgV2Vha01hcCgpOwogIHZhciBDT01QVVRFRF9QUk9QRVJUWV9MQVNUX1JFVklTSU9OID0gbmV3IFdlYWtNYXAoKTsKCiAgZnVuY3Rpb24gZ2V0Q2FjaGVGb3Iob2JqKSB7CiAgICB2YXIgY2FjaGUgPSBDT01QVVRFRF9QUk9QRVJUWV9DQUNIRURfVkFMVUVTLmdldChvYmopOwoKICAgIGlmIChjYWNoZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGNhY2hlID0gbmV3IE1hcCgpOwogICAgICBDT01QVVRFRF9QUk9QRVJUWV9DQUNIRURfVkFMVUVTLnNldChvYmosIGNhY2hlKTsKICAgIH0KCiAgICByZXR1cm4gY2FjaGU7CiAgfQogIC8qKgogICAgUmV0dXJucyB0aGUgY2FjaGVkIHZhbHVlIGZvciBhIHByb3BlcnR5LCBpZiBvbmUgZXhpc3RzLgogICAgVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBwZWVraW5nIGF0IHRoZSB2YWx1ZSBvZiBhIGNvbXB1dGVkCiAgICBwcm9wZXJ0eSB0aGF0IGlzIGdlbmVyYXRlZCBsYXppbHksIHdpdGhvdXQgYWNjaWRlbnRhbGx5IGNhdXNpbmcKICAgIGl0IHRvIGJlIGNyZWF0ZWQuCiAgCiAgICBAbWV0aG9kIGNhY2hlRm9yCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvaW50ZXJuYWxzCiAgICBAcGFyYW0ge09iamVjdH0gb2JqIHRoZSBvYmplY3Qgd2hvc2UgcHJvcGVydHkgeW91IHdhbnQgdG8gY2hlY2sKICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkgdGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHdob3NlIGNhY2hlZCB2YWx1ZSB5b3Ugd2FudAogICAgICB0byByZXR1cm4KICAgIEByZXR1cm4ge09iamVjdH0gdGhlIGNhY2hlZCB2YWx1ZQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBnZXRDYWNoZWRWYWx1ZUZvcihvYmosIGtleSkgewogICAgdmFyIGNhY2hlID0gQ09NUFVURURfUFJPUEVSVFlfQ0FDSEVEX1ZBTFVFUy5nZXQob2JqKTsKCiAgICBpZiAoY2FjaGUgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gY2FjaGUuZ2V0KGtleSk7CiAgICB9CiAgfQoKICB2YXIgc2V0TGFzdFJldmlzaW9uRm9yOwogIHZhciBnZXRMYXN0UmV2aXNpb25Gb3I7CiAgewogICAgc2V0TGFzdFJldmlzaW9uRm9yID0gZnVuY3Rpb24gc2V0TGFzdFJldmlzaW9uRm9yKG9iaiwga2V5LCByZXZpc2lvbikgewogICAgICB2YXIgY2FjaGUgPSBDT01QVVRFRF9QUk9QRVJUWV9MQVNUX1JFVklTSU9OLmdldChvYmopOwoKICAgICAgaWYgKGNhY2hlID09PSB1bmRlZmluZWQpIHsKICAgICAgICBjYWNoZSA9IG5ldyBNYXAoKTsKICAgICAgICBDT01QVVRFRF9QUk9QRVJUWV9MQVNUX1JFVklTSU9OLnNldChvYmosIGNhY2hlKTsKICAgICAgfQoKICAgICAgY2FjaGUuc2V0KGtleSwgcmV2aXNpb24pOwogICAgfTsKCiAgICBnZXRMYXN0UmV2aXNpb25Gb3IgPSBmdW5jdGlvbiBnZXRMYXN0UmV2aXNpb25Gb3Iob2JqLCBrZXkpIHsKICAgICAgdmFyIGNhY2hlID0gQ09NUFVURURfUFJPUEVSVFlfTEFTVF9SRVZJU0lPTi5nZXQob2JqKTsKCiAgICAgIGlmIChjYWNoZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIHJldmlzaW9uID0gY2FjaGUuZ2V0KGtleSk7CiAgICAgICAgcmV0dXJuIHJldmlzaW9uID09PSB1bmRlZmluZWQgPyAwIDogcmV2aXNpb247CiAgICAgIH0KICAgIH07CiAgfQoKICBmdW5jdGlvbiBwZWVrQ2FjaGVGb3Iob2JqKSB7CiAgICByZXR1cm4gQ09NUFVURURfUFJPUEVSVFlfQ0FDSEVEX1ZBTFVFUy5nZXQob2JqKTsKICB9CgogIHZhciBFQUNIX1BST1hJRVMgPSBuZXcgV2Vha01hcCgpOwoKICBmdW5jdGlvbiBlYWNoUHJveHlBcnJheVdpbGxDaGFuZ2UoYXJyYXksIGlkeCwgcmVtb3ZlZENudCwgYWRkZWRDbnQpIHsKICAgIHZhciBlYWNoUHJveHkgPSBFQUNIX1BST1hJRVMuZ2V0KGFycmF5KTsKCiAgICBpZiAoZWFjaFByb3h5ICE9PSB1bmRlZmluZWQpIHsKICAgICAgZWFjaFByb3h5LmFycmF5V2lsbENoYW5nZShhcnJheSwgaWR4LCByZW1vdmVkQ250LCBhZGRlZENudCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBlYWNoUHJveHlBcnJheURpZENoYW5nZShhcnJheSwgaWR4LCByZW1vdmVkQ250LCBhZGRlZENudCkgewogICAgdmFyIGVhY2hQcm94eSA9IEVBQ0hfUFJPWElFUy5nZXQoYXJyYXkpOwoKICAgIGlmIChlYWNoUHJveHkgIT09IHVuZGVmaW5lZCkgewogICAgICBlYWNoUHJveHkuYXJyYXlEaWRDaGFuZ2UoYXJyYXksIGlkeCwgcmVtb3ZlZENudCwgYWRkZWRDbnQpOwogICAgfQogIH0KICAvKioKICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwoKICAvKgogICAgVGhlIGV2ZW50IHN5c3RlbSB1c2VzIGEgc2VyaWVzIG9mIG5lc3RlZCBoYXNoZXMgdG8gc3RvcmUgbGlzdGVuZXJzIG9uIGFuCiAgICBvYmplY3QuIFdoZW4gYSBsaXN0ZW5lciBpcyByZWdpc3RlcmVkLCBvciB3aGVuIGFuIGV2ZW50IGFycml2ZXMsIHRoZXNlCiAgICBoYXNoZXMgYXJlIGNvbnN1bHRlZCB0byBkZXRlcm1pbmUgd2hpY2ggdGFyZ2V0IGFuZCBhY3Rpb24gcGFpciB0byBpbnZva2UuCiAgCiAgICBUaGUgaGFzaGVzIGFyZSBzdG9yZWQgaW4gdGhlIG9iamVjdCdzIG1ldGEgaGFzaCwgYW5kIGxvb2sgbGlrZSB0aGlzOgogIAogICAgICAgIC8vIE9iamVjdCdzIG1ldGEgaGFzaAogICAgICAgIHsKICAgICAgICAgIGxpc3RlbmVyczogeyAgICAgICAvLyB2YXJpYWJsZSBuYW1lOiBgbGlzdGVuZXJTZXRgCiAgICAgICAgICAgICJmb286Y2hhbmdlIjogWyAvLyB2YXJpYWJsZSBuYW1lOiBgYWN0aW9uc2AKICAgICAgICAgICAgICB0YXJnZXQsIG1ldGhvZCwgb25jZQogICAgICAgICAgICBdCiAgICAgICAgICB9CiAgICAgICAgfQogIAogICovCgogIC8qKgogICAgQWRkIGFuIGV2ZW50IGxpc3RlbmVyCiAgCiAgICBAbWV0aG9kIGFkZExpc3RlbmVyCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvZXZlbnRzCiAgICBAcGFyYW0gb2JqCiAgICBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lCiAgICBAcGFyYW0ge09iamVjdHxGdW5jdGlvbn0gdGFyZ2V0IEEgdGFyZ2V0IG9iamVjdCBvciBhIGZ1bmN0aW9uCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIEEgZnVuY3Rpb24gb3IgdGhlIG5hbWUgb2YgYSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgb24gYHRhcmdldGAKICAgIEBwYXJhbSB7Qm9vbGVhbn0gb25jZSBBIGZsYWcgd2hldGhlciBhIGZ1bmN0aW9uIHNob3VsZCBvbmx5IGJlIGNhbGxlZCBvbmNlCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGFkZExpc3RlbmVyKG9iaiwgZXZlbnROYW1lLCB0YXJnZXQsIG1ldGhvZCwgb25jZSwgc3luYykgewogICAgaWYgKHN5bmMgPT09IHZvaWQgMCkgewogICAgICBzeW5jID0gdHJ1ZTsKICAgIH0KCiAgICAoZmFsc2UgJiYgIShCb29sZWFuKG9iaikgJiYgQm9vbGVhbihldmVudE5hbWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBtdXN0IHBhc3MgYXQgbGVhc3QgYW4gb2JqZWN0IGFuZCBldmVudCBuYW1lIHRvIGFkZExpc3RlbmVyJywgQm9vbGVhbihvYmopICYmIEJvb2xlYW4oZXZlbnROYW1lKSkpOwoKICAgIGlmICghbWV0aG9kICYmICdmdW5jdGlvbicgPT09IHR5cGVvZiB0YXJnZXQpIHsKICAgICAgbWV0aG9kID0gdGFyZ2V0OwogICAgICB0YXJnZXQgPSBudWxsOwogICAgfQoKICAgICgwLCBfbWV0YTIubWV0YSkob2JqKS5hZGRUb0xpc3RlbmVycyhldmVudE5hbWUsIHRhcmdldCwgbWV0aG9kLCBvbmNlID09PSB0cnVlLCBzeW5jKTsKICB9CiAgLyoqCiAgICBSZW1vdmUgYW4gZXZlbnQgbGlzdGVuZXIKICAKICAgIEFyZ3VtZW50cyBzaG91bGQgbWF0Y2ggdGhvc2UgcGFzc2VkIHRvIGBhZGRMaXN0ZW5lcmAuCiAgCiAgICBAbWV0aG9kIHJlbW92ZUxpc3RlbmVyCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvZXZlbnRzCiAgICBAcGFyYW0gb2JqCiAgICBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lCiAgICBAcGFyYW0ge09iamVjdHxGdW5jdGlvbn0gdGFyZ2V0IEEgdGFyZ2V0IG9iamVjdCBvciBhIGZ1bmN0aW9uCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIEEgZnVuY3Rpb24gb3IgdGhlIG5hbWUgb2YgYSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgb24gYHRhcmdldGAKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIob2JqLCBldmVudE5hbWUsIHRhcmdldE9yRnVuY3Rpb24sIGZ1bmN0aW9uT3JOYW1lKSB7CiAgICAoZmFsc2UgJiYgIShCb29sZWFuKG9iaikgJiYgQm9vbGVhbihldmVudE5hbWUpICYmICh0eXBlb2YgdGFyZ2V0T3JGdW5jdGlvbiA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgdGFyZ2V0T3JGdW5jdGlvbiA9PT0gJ29iamVjdCcgJiYgQm9vbGVhbihmdW5jdGlvbk9yTmFtZSkpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBtdXN0IHBhc3MgYXQgbGVhc3QgYW4gb2JqZWN0LCBldmVudCBuYW1lLCBhbmQgbWV0aG9kIG9yIHRhcmdldCBhbmQgbWV0aG9kL21ldGhvZCBuYW1lIHRvIHJlbW92ZUxpc3RlbmVyJywgQm9vbGVhbihvYmopICYmIEJvb2xlYW4oZXZlbnROYW1lKSAmJiAodHlwZW9mIHRhcmdldE9yRnVuY3Rpb24gPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIHRhcmdldE9yRnVuY3Rpb24gPT09ICdvYmplY3QnICYmIEJvb2xlYW4oZnVuY3Rpb25Pck5hbWUpKSkpOwogICAgdmFyIHRhcmdldCwgbWV0aG9kOwoKICAgIGlmICh0eXBlb2YgdGFyZ2V0T3JGdW5jdGlvbiA9PT0gJ29iamVjdCcpIHsKICAgICAgdGFyZ2V0ID0gdGFyZ2V0T3JGdW5jdGlvbjsKICAgICAgbWV0aG9kID0gZnVuY3Rpb25Pck5hbWU7CiAgICB9IGVsc2UgewogICAgICB0YXJnZXQgPSBudWxsOwogICAgICBtZXRob2QgPSB0YXJnZXRPckZ1bmN0aW9uOwogICAgfQoKICAgIHZhciBtID0gKDAsIF9tZXRhMi5tZXRhKShvYmopOwogICAgbS5yZW1vdmVGcm9tTGlzdGVuZXJzKGV2ZW50TmFtZSwgdGFyZ2V0LCBtZXRob2QpOwogIH0KICAvKioKICAgIFNlbmQgYW4gZXZlbnQuIFRoZSBleGVjdXRpb24gb2Ygc3VzcGVuZGVkIGxpc3RlbmVycwogICAgaXMgc2tpcHBlZCwgYW5kIG9uY2UgbGlzdGVuZXJzIGFyZSByZW1vdmVkLiBBIGxpc3RlbmVyIHdpdGhvdXQKICAgIGEgdGFyZ2V0IGlzIGV4ZWN1dGVkIG9uIHRoZSBwYXNzZWQgb2JqZWN0LiBJZiBhbiBhcnJheSBvZiBhY3Rpb25zCiAgICBpcyBub3QgcGFzc2VkLCB0aGUgYWN0aW9ucyBzdG9yZWQgb24gdGhlIHBhc3NlZCBvYmplY3QgYXJlIGludm9rZWQuCiAgCiAgICBAbWV0aG9kIHNlbmRFdmVudAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2V2ZW50cwogICAgQHBhcmFtIG9iagogICAgQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZQogICAgQHBhcmFtIHtBcnJheX0gcGFyYW1zIE9wdGlvbmFsIHBhcmFtZXRlcnMgZm9yIGVhY2ggbGlzdGVuZXIuCiAgICBAcmV0dXJuIHtCb29sZWFufSBpZiB0aGUgZXZlbnQgd2FzIGRlbGl2ZXJlZCB0byBvbmUgb3IgbW9yZSBhY3Rpb25zCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIHNlbmRFdmVudChvYmosIGV2ZW50TmFtZSwgcGFyYW1zLCBhY3Rpb25zLCBfbWV0YSkgewogICAgaWYgKGFjdGlvbnMgPT09IHVuZGVmaW5lZCkgewogICAgICB2YXIgbWV0YSQkMSA9IF9tZXRhID09PSB1bmRlZmluZWQgPyAoMCwgX21ldGEyLnBlZWtNZXRhKShvYmopIDogX21ldGE7CiAgICAgIGFjdGlvbnMgPSB0eXBlb2YgbWV0YSQkMSA9PT0gJ29iamVjdCcgJiYgbWV0YSQkMSAhPT0gbnVsbCA/IG1ldGEkJDEubWF0Y2hpbmdMaXN0ZW5lcnMoZXZlbnROYW1lKSA6IHVuZGVmaW5lZDsKICAgIH0KCiAgICBpZiAoYWN0aW9ucyA9PT0gdW5kZWZpbmVkIHx8IGFjdGlvbnMubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICBmb3IgKHZhciBpID0gYWN0aW9ucy5sZW5ndGggLSAzOyBpID49IDA7IGkgLT0gMykgewogICAgICAvLyBsb29waW5nIGluIHJldmVyc2UgZm9yIG9uY2UgbGlzdGVuZXJzCiAgICAgIHZhciB0YXJnZXQgPSBhY3Rpb25zW2ldOwogICAgICB2YXIgbWV0aG9kID0gYWN0aW9uc1tpICsgMV07CiAgICAgIHZhciBvbmNlID0gYWN0aW9uc1tpICsgMl07CgogICAgICBpZiAoIW1ldGhvZCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICBpZiAob25jZSkgewogICAgICAgIHJlbW92ZUxpc3RlbmVyKG9iaiwgZXZlbnROYW1lLCB0YXJnZXQsIG1ldGhvZCk7CiAgICAgIH0KCiAgICAgIGlmICghdGFyZ2V0KSB7CiAgICAgICAgdGFyZ2V0ID0gb2JqOwogICAgICB9CgogICAgICBpZiAoJ3N0cmluZycgPT09IHR5cGVvZiBtZXRob2QpIHsKICAgICAgICBtZXRob2QgPSB0YXJnZXRbbWV0aG9kXTsKICAgICAgfQoKICAgICAgbWV0aG9kLmFwcGx5KHRhcmdldCwgcGFyYW1zKTsKICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCBoYXNMaXN0ZW5lcnMKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9ldmVudHMKICAgIEBwYXJhbSBvYmoKICAgIEBwYXJhbSB7U3RyaW5nfSBldmVudE5hbWUKICAgIEByZXR1cm4ge0Jvb2xlYW59IGlmIGBvYmpgIGhhcyBsaXN0ZW5lcnMgZm9yIGV2ZW50IGBldmVudE5hbWVgCiAgKi8KCgogIGZ1bmN0aW9uIGhhc0xpc3RlbmVycyhvYmosIGV2ZW50TmFtZSkgewogICAgdmFyIG1ldGEkJDEgPSAoMCwgX21ldGEyLnBlZWtNZXRhKShvYmopOwoKICAgIGlmIChtZXRhJCQxID09PSBudWxsKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICB2YXIgbWF0Y2hlZCA9IG1ldGEkJDEubWF0Y2hpbmdMaXN0ZW5lcnMoZXZlbnROYW1lKTsKICAgIHJldHVybiBtYXRjaGVkICE9PSB1bmRlZmluZWQgJiYgbWF0Y2hlZC5sZW5ndGggPiAwOwogIH0KICAvKioKICAgIERlZmluZSBhIHByb3BlcnR5IGFzIGEgZnVuY3Rpb24gdGhhdCBzaG91bGQgYmUgZXhlY3V0ZWQgd2hlbgogICAgYSBzcGVjaWZpZWQgZXZlbnQgb3IgZXZlbnRzIGFyZSB0cmlnZ2VyZWQuCiAgCiAgICBgYGAgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgb24gfSBmcm9tICdAZW1iZXIvb2JqZWN0L2V2ZW50ZWQnOwogICAgaW1wb3J0IHsgc2VuZEV2ZW50IH0gZnJvbSAnQGVtYmVyL29iamVjdC9ldmVudHMnOwogIAogICAgbGV0IEpvYiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGxvZ0NvbXBsZXRlZDogb24oJ2NvbXBsZXRlZCcsIGZ1bmN0aW9uKCkgewogICAgICAgIGNvbnNvbGUubG9nKCdKb2IgY29tcGxldGVkIScpOwogICAgICB9KQogICAgfSk7CiAgCiAgICBsZXQgam9iID0gSm9iLmNyZWF0ZSgpOwogIAogICAgc2VuZEV2ZW50KGpvYiwgJ2NvbXBsZXRlZCcpOyAvLyBMb2dzICdKb2IgY29tcGxldGVkIScKICAgYGBgCiAgCiAgICBAbWV0aG9kIG9uCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvZXZlbnRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZXMqCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jCiAgICBAcmV0dXJuIHtGdW5jdGlvbn0gdGhlIGxpc3RlbmVyIGZ1bmN0aW9uLCBwYXNzZWQgYXMgbGFzdCBhcmd1bWVudCB0byBvbiguLi4pCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIG9uKCkgewogICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkyID0gMDsgX2tleTIgPCBfbGVuOyBfa2V5MisrKSB7CiAgICAgIGFyZ3NbX2tleTJdID0gYXJndW1lbnRzW19rZXkyXTsKICAgIH0KCiAgICB2YXIgZnVuYyA9IGFyZ3MucG9wKCk7CiAgICB2YXIgZXZlbnRzID0gYXJnczsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBmdW5jID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ29uIGV4cGVjdHMgZnVuY3Rpb24gYXMgbGFzdCBhcmd1bWVudCcsIHR5cGVvZiBmdW5jID09PSAnZnVuY3Rpb24nKSk7CiAgICAoZmFsc2UgJiYgIShldmVudHMubGVuZ3RoID4gMCAmJiBldmVudHMuZXZlcnkoZnVuY3Rpb24gKHApIHsKICAgICAgcmV0dXJuIHR5cGVvZiBwID09PSAnc3RyaW5nJyAmJiBwLmxlbmd0aCA+IDA7CiAgICB9KSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdvbiBjYWxsZWQgd2l0aG91dCB2YWxpZCBldmVudCBuYW1lcycsIGV2ZW50cy5sZW5ndGggPiAwICYmIGV2ZW50cy5ldmVyeShmdW5jdGlvbiAocCkgewogICAgICByZXR1cm4gdHlwZW9mIHAgPT09ICdzdHJpbmcnICYmIHAubGVuZ3RoID4gMDsKICAgIH0pKSk7CiAgICAoMCwgX3V0aWxzLnNldExpc3RlbmVycykoZnVuYywgZXZlbnRzKTsKICAgIHJldHVybiBmdW5jOwogIH0KCiAgdmFyIEFGVEVSX09CU0VSVkVSUyA9ICc6Y2hhbmdlJzsKCiAgZnVuY3Rpb24gY2hhbmdlRXZlbnQoa2V5TmFtZSkgewogICAgcmV0dXJuIGtleU5hbWUgKyBBRlRFUl9PQlNFUlZFUlM7CiAgfQoKICB2YXIgREVDT1JBVE9SX0RFU0NSSVBUT1JfTUFQID0gbmV3IFdlYWtNYXAoKTsKICAvKioKICAgIFJldHVybnMgdGhlIENQIGRlc2NyaXB0b3IgYXNzb2NhaXRlZCB3aXRoIGBvYmpgIGFuZCBga2V5TmFtZWAsIGlmIGFueS4KICAKICAgIEBtZXRob2QgZGVzY3JpcHRvckZvclByb3BlcnR5CiAgICBAcGFyYW0ge09iamVjdH0gb2JqIHRoZSBvYmplY3QgdG8gY2hlY2sKICAgIEBwYXJhbSB7U3RyaW5nfSBrZXlOYW1lIHRoZSBrZXkgdG8gY2hlY2sKICAgIEByZXR1cm4ge0Rlc2NyaXB0b3J9CiAgICBAcHJpdmF0ZQogICovCgogIGZ1bmN0aW9uIGRlc2NyaXB0b3JGb3JQcm9wZXJ0eShvYmosIGtleU5hbWUsIF9tZXRhKSB7CiAgICAoZmFsc2UgJiYgIShvYmogIT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IGNhbGwgYGRlc2NyaXB0b3JGb3JQcm9wZXJ0eWAgb24gbnVsbCcsIG9iaiAhPT0gbnVsbCkpOwogICAgKGZhbHNlICYmICEob2JqICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ2Fubm90IGNhbGwgYGRlc2NyaXB0b3JGb3JQcm9wZXJ0eWAgb24gdW5kZWZpbmVkJywgb2JqICE9PSB1bmRlZmluZWQpKTsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IGNhbGwgYGRlc2NyaXB0b3JGb3JQcm9wZXJ0eWAgb24gIiArIHR5cGVvZiBvYmosIHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpKTsKICAgIHZhciBtZXRhJCQxID0gX21ldGEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaikgOiBfbWV0YTsKCiAgICBpZiAobWV0YSQkMSAhPT0gbnVsbCkgewogICAgICByZXR1cm4gbWV0YSQkMS5wZWVrRGVzY3JpcHRvcnMoa2V5TmFtZSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKGRlYykgewogICAgcmV0dXJuIERFQ09SQVRPUl9ERVNDUklQVE9SX01BUC5nZXQoZGVjKTsKICB9CiAgLyoqCiAgICBDaGVjayB3aGV0aGVyIGEgdmFsdWUgaXMgYSBkZWNvcmF0b3IKICAKICAgIEBtZXRob2QgaXNDbGFzc2ljRGVjb3JhdG9yCiAgICBAcGFyYW0ge2FueX0gcG9zc2libGVEZXNjIHRoZSB2YWx1ZSB0byBjaGVjawogICAgQHJldHVybiB7Ym9vbGVhbn0KICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIGlzQ2xhc3NpY0RlY29yYXRvcihkZWMpIHsKICAgIHJldHVybiBkZWMgIT09IG51bGwgJiYgZGVjICE9PSB1bmRlZmluZWQgJiYgREVDT1JBVE9SX0RFU0NSSVBUT1JfTUFQLmhhcyhkZWMpOwogIH0KICAvKioKICAgIFNldCBhIHZhbHVlIGFzIGEgZGVjb3JhdG9yCiAgCiAgICBAbWV0aG9kIHNldENsYXNzaWNEZWNvcmF0b3IKICAgIEBwYXJhbSB7ZnVuY3Rpb259IGRlY29yYXRvciB0aGUgdmFsdWUgdG8gbWFyayBhcyBhIGRlY29yYXRvcgogICAgQHByaXZhdGUKICAqLwoKCiAgZnVuY3Rpb24gc2V0Q2xhc3NpY0RlY29yYXRvcihkZWMsIHZhbHVlJCQxKSB7CiAgICBpZiAodmFsdWUkJDEgPT09IHZvaWQgMCkgewogICAgICB2YWx1ZSQkMSA9IHRydWU7CiAgICB9CgogICAgREVDT1JBVE9SX0RFU0NSSVBUT1JfTUFQLnNldChkZWMsIHZhbHVlJCQxKTsKICB9CgogIHZhciBmaXJzdERvdEluZGV4Q2FjaGUgPSBuZXcgX3V0aWxzLkNhY2hlKDEwMDAsIGZ1bmN0aW9uIChrZXkpIHsKICAgIHJldHVybiBrZXkuaW5kZXhPZignLicpOwogIH0pOwoKICBmdW5jdGlvbiBpc1BhdGgocGF0aCkgewogICAgcmV0dXJuIHR5cGVvZiBwYXRoID09PSAnc3RyaW5nJyAmJiBmaXJzdERvdEluZGV4Q2FjaGUuZ2V0KHBhdGgpICE9PSAtMTsKICB9CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KICAvLyBERUZJTklORyBQUk9QRVJUSUVTIEFQSQogIC8vCgoKICBmdW5jdGlvbiBNQU5EQVRPUllfU0VUVEVSX0ZVTkNUSU9OKG5hbWUpIHsKICAgIGZ1bmN0aW9uIFNFVFRFUl9GVU5DVElPTih2YWx1ZSQkMSkgewogICAgICB2YXIgbSA9ICgwLCBfbWV0YTIucGVla01ldGEpKHRoaXMpOwoKICAgICAgaWYgKG0uaXNJbml0aWFsaXppbmcoKSB8fCBtLmlzUHJvdG90eXBlTWV0YSh0aGlzKSkgewogICAgICAgIG0ud3JpdGVWYWx1ZXMobmFtZSwgdmFsdWUkJDEpOwogICAgICB9IGVsc2UgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBtdXN0IHVzZSBzZXQoKSB0byBzZXQgdGhlIGAiICsgbmFtZSArICJgIHByb3BlcnR5IChvZiAiICsgdGhpcyArICIpIHRvIGAiICsgdmFsdWUkJDEgKyAiYC4iLCBmYWxzZSkpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuICgwLCBfcG9seWZpbGxzLmFzc2lnbikoU0VUVEVSX0ZVTkNUSU9OLCB7CiAgICAgIGlzTWFuZGF0b3J5U2V0dGVyOiB0cnVlCiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIERFRkFVTFRfR0VUVEVSX0ZVTkNUSU9OKG5hbWUpIHsKICAgIHJldHVybiBmdW5jdGlvbiBHRVRURVJfRlVOQ1RJT04oKSB7CiAgICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkodGhpcyk7CgogICAgICBpZiAobWV0YSQkMSAhPT0gbnVsbCkgewogICAgICAgIHJldHVybiBtZXRhJCQxLnBlZWtWYWx1ZXMobmFtZSk7CiAgICAgIH0KICAgIH07CiAgfQoKICBmdW5jdGlvbiBJTkhFUklUSU5HX0dFVFRFUl9GVU5DVElPTihuYW1lKSB7CiAgICBmdW5jdGlvbiBJR0VUVEVSX0ZVTkNUSU9OKCkgewogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKHRoaXMpOwogICAgICB2YXIgdmFsOwoKICAgICAgaWYgKG1ldGEkJDEgIT09IG51bGwpIHsKICAgICAgICB2YWwgPSBtZXRhJCQxLnJlYWRJbmhlcml0ZWRWYWx1ZShuYW1lKTsKCiAgICAgICAgaWYgKHZhbCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YXIgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcyk7CiAgICAgICAgICB2YWwgPSBwcm90byA9PT0gbnVsbCA/IHVuZGVmaW5lZCA6IHByb3RvW25hbWVdOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB2YWwgPSB2YWwgPT09IF9tZXRhMi5VTkRFRklORUQgPyB1bmRlZmluZWQgOiB2YWw7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdmFsOwogICAgfQoKICAgIHJldHVybiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKElHRVRURVJfRlVOQ1RJT04sIHsKICAgICAgaXNJbmhlcml0aW5nR2V0dGVyOiB0cnVlCiAgICB9KTsKICB9CiAgLyoqCiAgICBOT1RFOiBUaGlzIGlzIGEgbG93LWxldmVsIG1ldGhvZCB1c2VkIGJ5IG90aGVyIHBhcnRzIG9mIHRoZSBBUEkuIFlvdSBhbG1vc3QKICAgIG5ldmVyIHdhbnQgdG8gY2FsbCB0aGlzIG1ldGhvZCBkaXJlY3RseS4gSW5zdGVhZCB5b3Ugc2hvdWxkIHVzZQogICAgYG1peGluKClgIHRvIGRlZmluZSBuZXcgcHJvcGVydGllcy4KICAKICAgIERlZmluZXMgYSBwcm9wZXJ0eSBvbiBhbiBvYmplY3QuIFRoaXMgbWV0aG9kIHdvcmtzIG11Y2ggbGlrZSB0aGUgRVM1CiAgICBgT2JqZWN0LmRlZmluZVByb3BlcnR5KClgIG1ldGhvZCBleGNlcHQgdGhhdCBpdCBjYW4gYWxzbyBhY2NlcHQgY29tcHV0ZWQKICAgIHByb3BlcnRpZXMgYW5kIG90aGVyIHNwZWNpYWwgZGVzY3JpcHRvcnMuCiAgCiAgICBOb3JtYWxseSB0aGlzIG1ldGhvZCB0YWtlcyBvbmx5IHRocmVlIHBhcmFtZXRlcnMuIEhvd2V2ZXIgaWYgeW91IHBhc3MgYW4KICAgIGluc3RhbmNlIG9mIGBEZXNjcmlwdG9yYCBhcyB0aGUgdGhpcmQgcGFyYW0gdGhlbiB5b3UgY2FuIHBhc3MgYW4KICAgIG9wdGlvbmFsIHZhbHVlIGFzIHRoZSBmb3VydGggcGFyYW1ldGVyLiBUaGlzIGlzIG9mdGVuIG1vcmUgZWZmaWNpZW50IHRoYW4KICAgIGNyZWF0aW5nIG5ldyBkZXNjcmlwdG9yIGhhc2hlcyBmb3IgZWFjaCBwcm9wZXJ0eS4KICAKICAgICMjIEV4YW1wbGVzCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBkZWZpbmVQcm9wZXJ0eSwgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIC8vIEVTNSBjb21wYXRpYmxlIG1vZGUKICAgIGRlZmluZVByb3BlcnR5KGNvbnRhY3QsICdmaXJzdE5hbWUnLCB7CiAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICBjb25maWd1cmFibGU6IGZhbHNlLAogICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICB2YWx1ZTogJ0NoYXJsZXMnCiAgICB9KTsKICAKICAgIC8vIGRlZmluZSBhIHNpbXBsZSBwcm9wZXJ0eQogICAgZGVmaW5lUHJvcGVydHkoY29udGFjdCwgJ2xhc3ROYW1lJywgdW5kZWZpbmVkLCAnSm9sbGV5Jyk7CiAgCiAgICAvLyBkZWZpbmUgYSBjb21wdXRlZCBwcm9wZXJ0eQogICAgZGVmaW5lUHJvcGVydHkoY29udGFjdCwgJ2Z1bGxOYW1lJywgY29tcHV0ZWQoJ2ZpcnN0TmFtZScsICdsYXN0TmFtZScsIGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gdGhpcy5maXJzdE5hbWUrJyAnK3RoaXMubGFzdE5hbWU7CiAgICB9KSk7CiAgICBgYGAKICAKICAgIEBwdWJsaWMKICAgIEBtZXRob2QgZGVmaW5lUHJvcGVydHkKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdAogICAgQHBhcmFtIHtPYmplY3R9IG9iaiB0aGUgb2JqZWN0IHRvIGRlZmluZSB0aGlzIHByb3BlcnR5IG9uLiBUaGlzIG1heSBiZSBhIHByb3RvdHlwZS4KICAgIEBwYXJhbSB7U3RyaW5nfSBrZXlOYW1lIHRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eQogICAgQHBhcmFtIHtEZXNjcmlwdG9yfSBbZGVzY10gYW4gaW5zdGFuY2Ugb2YgYERlc2NyaXB0b3JgICh0eXBpY2FsbHkgYQogICAgICBjb21wdXRlZCBwcm9wZXJ0eSkgb3IgYW4gRVM1IGRlc2NyaXB0b3IuCiAgICAgIFlvdSBtdXN0IHByb3ZpZGUgdGhpcyBvciBgZGF0YWAgYnV0IG5vdCBib3RoLgogICAgQHBhcmFtIHsqfSBbZGF0YV0gc29tZXRoaW5nIG90aGVyIHRoYW4gYSBkZXNjcmlwdG9yLCB0aGF0IHdpbGwKICAgICAgYmVjb21lIHRoZSBleHBsaWNpdCB2YWx1ZSBvZiB0aGlzIHByb3BlcnR5LgogICovCgoKICBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShvYmosIGtleU5hbWUsIGRlc2MsIGRhdGEsIG1ldGEkJDEpIHsKICAgIGlmIChtZXRhJCQxID09PSB1bmRlZmluZWQpIHsKICAgICAgbWV0YSQkMSA9ICgwLCBfbWV0YTIubWV0YSkob2JqKTsKICAgIH0KCiAgICB2YXIgd2F0Y2hpbmcgPSBtZXRhJCQxLnBlZWtXYXRjaGluZyhrZXlOYW1lKSA+IDA7CiAgICB2YXIgcHJldmlvdXNEZXNjID0gZGVzY3JpcHRvckZvclByb3BlcnR5KG9iaiwga2V5TmFtZSwgbWV0YSQkMSk7CiAgICB2YXIgd2FzRGVzY3JpcHRvciA9IHByZXZpb3VzRGVzYyAhPT0gdW5kZWZpbmVkOwoKICAgIGlmICh3YXNEZXNjcmlwdG9yKSB7CiAgICAgIHByZXZpb3VzRGVzYy50ZWFyZG93bihvYmosIGtleU5hbWUsIG1ldGEkJDEpOwogICAgfSAvLyB1c2VkIHRvIHRyYWNrIGlmIHRoZSB0aGUgcHJvcGVydHkgYmVpbmcgZGVmaW5lZCBiZSBlbnVtZXJhYmxlCgoKICAgIHZhciBlbnVtZXJhYmxlID0gdHJ1ZTsgLy8gRW1iZXIuTmF0aXZlQXJyYXkgaXMgYSBub3JtYWwgRW1iZXIuTWl4aW4gdGhhdCB3ZSBtaXggaW50byBgQXJyYXkucHJvdG90eXBlYCB3aGVuIHByb3RvdHlwZSBleHRlbnNpb25zIGFyZSBlbmFibGVkCiAgICAvLyBtdXRhdGluZyBhIG5hdGl2ZSBvYmplY3QgcHJvdG90eXBlIGxpa2UgdGhpcyBzaG91bGQgX25vdF8gcmVzdWx0IGluIGVudW1lcmFibGUgcHJvcGVydGllcyBiZWluZyBhZGRlZCAob3Igd2UgaGF2ZSBzaWduaWZpY2FudAogICAgLy8gaXNzdWVzIHdpdGggdGhpbmdzIGxpa2UgZGVlcCBlcXVhbGl0eSBjaGVja3MgZnJvbSB0ZXN0IGZyYW1ld29ya3MsIG9yIHRoaW5ncyBsaWtlIGpRdWVyeS5leHRlbmQodHJ1ZSwgW10sIFtdKSkuCiAgICAvLwogICAgLy8gdGhpcyBpcyBhIGhhY2ssIGFuZCB3ZSBzaG91bGQgc3RvcCBtdXRhdGluZyB0aGUgYXJyYXkgcHJvdG90eXBlIGJ5IGRlZmF1bHQg8J+YqwoKICAgIGlmIChvYmogPT09IEFycmF5LnByb3RvdHlwZSkgewogICAgICBlbnVtZXJhYmxlID0gZmFsc2U7CiAgICB9CgogICAgdmFyIHZhbHVlJCQxOwoKICAgIGlmIChpc0NsYXNzaWNEZWNvcmF0b3IoZGVzYykpIHsKICAgICAgdmFyIHByb3BlcnR5RGVzYzsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICBwcm9wZXJ0eURlc2MgPSBkZXNjKG9iaiwga2V5TmFtZSwgdW5kZWZpbmVkLCBtZXRhJCQxLCB0cnVlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBwcm9wZXJ0eURlc2MgPSBkZXNjKG9iaiwga2V5TmFtZSwgdW5kZWZpbmVkLCBtZXRhJCQxKTsKICAgICAgfQoKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwga2V5TmFtZSwgcHJvcGVydHlEZXNjKTsgLy8gcGFzcyB0aGUgZGVjb3JhdG9yIGZ1bmN0aW9uIGZvcndhcmQgZm9yIGJhY2t3YXJkcyBjb21wYXQKCiAgICAgIHZhbHVlJCQxID0gZGVzYzsKICAgIH0gZWxzZSBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkIHx8IGRlc2MgPT09IG51bGwpIHsKICAgICAgdmFsdWUkJDEgPSBkYXRhOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICYmIHdhdGNoaW5nKSB7CiAgICAgICAgbWV0YSQkMS53cml0ZVZhbHVlcyhrZXlOYW1lLCBkYXRhKTsKICAgICAgICB2YXIgZGVmYXVsdERlc2NyaXB0b3IgPSB7CiAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgICBlbnVtZXJhYmxlOiBlbnVtZXJhYmxlLAogICAgICAgICAgc2V0OiBNQU5EQVRPUllfU0VUVEVSX0ZVTkNUSU9OKGtleU5hbWUpLAogICAgICAgICAgZ2V0OiBERUZBVUxUX0dFVFRFUl9GVU5DVElPTihrZXlOYW1lKQogICAgICAgIH07CiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwga2V5TmFtZSwgZGVmYXVsdERlc2NyaXB0b3IpOwogICAgICB9IGVsc2UgaWYgKHdhc0Rlc2NyaXB0b3IgfHwgZW51bWVyYWJsZSA9PT0gZmFsc2UpIHsKICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCB7CiAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgICBlbnVtZXJhYmxlOiBlbnVtZXJhYmxlLAogICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICB2YWx1ZTogdmFsdWUkJDEKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAodHJ1ZQogICAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICAgICYmIGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgICgwLCBfdXRpbHMuc2V0V2l0aE1hbmRhdG9yeVNldHRlcikob2JqLCBrZXlOYW1lLCBkYXRhKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgb2JqW2tleU5hbWVdID0gZGF0YTsKICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhbHVlJCQxID0gZGVzYzsgLy8gZmFsbGJhY2sgdG8gRVM1CgogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCBkZXNjKTsKICAgIH0gLy8gaWYga2V5IGlzIGJlaW5nIHdhdGNoZWQsIG92ZXJyaWRlIGNoYWlucyB0aGF0CiAgICAvLyB3ZXJlIGluaXRpYWxpemVkIHdpdGggdGhlIHByb3RvdHlwZQoKCiAgICB7CiAgICAgIGlmICghbWV0YSQkMS5pc1Byb3RvdHlwZU1ldGEob2JqKSkgewogICAgICAgIHJldmFsaWRhdGVPYnNlcnZlcnMob2JqKTsKICAgICAgfQogICAgfSAvLyBUaGUgYHZhbHVlYCBwYXNzZWQgdG8gdGhlIGBkaWREZWZpbmVQcm9wZXJ0eWAgaG9vayBpcwogICAgLy8gZWl0aGVyIHRoZSBkZXNjcmlwdG9yIG9yIGRhdGEsIHdoaWNoZXZlciB3YXMgcGFzc2VkLgoKICAgIGlmICh0eXBlb2Ygb2JqLmRpZERlZmluZVByb3BlcnR5ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIG9iai5kaWREZWZpbmVQcm9wZXJ0eShvYmosIGtleU5hbWUsIHZhbHVlJCQxKTsKICAgIH0KICB9CgogIHZhciBoYW5kbGVNYW5kYXRvcnlTZXR0ZXI7CgogIGZ1bmN0aW9uIHdhdGNoS2V5KG9iaiwga2V5TmFtZSwgX21ldGEpIHsKICAgIHZhciBtZXRhJCQxID0gX21ldGEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIubWV0YSkob2JqKSA6IF9tZXRhOwogICAgdmFyIGNvdW50ID0gbWV0YSQkMS5wZWVrV2F0Y2hpbmcoa2V5TmFtZSk7CiAgICBtZXRhJCQxLndyaXRlV2F0Y2hpbmcoa2V5TmFtZSwgY291bnQgKyAxKTsKCiAgICBpZiAoY291bnQgPT09IDApIHsKICAgICAgLy8gYWN0aXZhdGUgd2F0Y2hpbmcgZmlyc3QgdGltZQogICAgICB2YXIgcG9zc2libGVEZXNjID0gZGVzY3JpcHRvckZvclByb3BlcnR5KG9iaiwga2V5TmFtZSwgbWV0YSQkMSk7CgogICAgICBpZiAocG9zc2libGVEZXNjICE9PSB1bmRlZmluZWQgJiYgcG9zc2libGVEZXNjLndpbGxXYXRjaCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcG9zc2libGVEZXNjLndpbGxXYXRjaChvYmosIGtleU5hbWUsIG1ldGEkJDEpOwogICAgICB9CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgLy8gTk9URTogdGhpcyBpcyBkcm9wcGVkIGZvciBwcm9kICsgbWluaWZpZWQgYnVpbGRzCiAgICAgICAgaGFuZGxlTWFuZGF0b3J5U2V0dGVyKG1ldGEkJDEsIG9iaiwga2V5TmFtZSk7CiAgICAgIH0KICAgIH0KICB9CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICB2YXIgX2hhc093blByb3BlcnR5ID0gZnVuY3Rpb24gX2hhc093blByb3BlcnR5KG9iaiwga2V5KSB7CiAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpOwogICAgfTsKCiAgICB2YXIgX3Byb3BlcnR5SXNFbnVtZXJhYmxlID0gZnVuY3Rpb24gX3Byb3BlcnR5SXNFbnVtZXJhYmxlKG9iaiwga2V5KSB7CiAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwob2JqLCBrZXkpOwogICAgfTsgLy8gRnV0dXJlIHRyYXZlbGVyLCBhbHRob3VnaCB0aGlzIGNvZGUgbG9va3Mgc2NhcnkuIEl0IG1lcmVseSBleGlzdHMgaW4KICAgIC8vIGRldmVsb3BtZW50IHRvIGFpZCBpbiBkZXZlbG9wbWVudCBhc2VydGlvbnMuIFByb2R1Y3Rpb24gYnVpbGRzIG9mCiAgICAvLyBlbWJlciBzdHJpcCB0aGlzIGVudGlyZSBibG9jayBvdXQKCgogICAgaGFuZGxlTWFuZGF0b3J5U2V0dGVyID0gZnVuY3Rpb24gaGFuZGxlTWFuZGF0b3J5U2V0dGVyKG0sIG9iaiwga2V5TmFtZSkgewogICAgICB2YXIgZGVzY3JpcHRvciA9ICgwLCBfdXRpbHMubG9va3VwRGVzY3JpcHRvcikob2JqLCBrZXlOYW1lKTsKICAgICAgdmFyIGhhc0Rlc2NyaXB0b3IgPSBkZXNjcmlwdG9yICE9PSBudWxsOwogICAgICB2YXIgcG9zc2libGVEZXNjID0gaGFzRGVzY3JpcHRvciAmJiBkZXNjcmlwdG9yLnZhbHVlOwoKICAgICAgaWYgKGlzQ2xhc3NpY0RlY29yYXRvcihwb3NzaWJsZURlc2MpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgY29uZmlndXJhYmxlID0gaGFzRGVzY3JpcHRvciA/IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlIDogdHJ1ZTsKICAgICAgdmFyIGlzV3JpdGFibGUgPSBoYXNEZXNjcmlwdG9yID8gZGVzY3JpcHRvci53cml0YWJsZSA6IHRydWU7CiAgICAgIHZhciBoYXNWYWx1ZSA9IGhhc0Rlc2NyaXB0b3IgPyAndmFsdWUnIGluIGRlc2NyaXB0b3IgOiB0cnVlOyAvLyB0aGlzIHggaW4gWSBkZW9wdHMsIHNvIGtlZXBpbmcgaXQgaW4gdGhpcyBmdW5jdGlvbiBpcyBiZXR0ZXI7CgogICAgICBpZiAoY29uZmlndXJhYmxlICYmIGlzV3JpdGFibGUgJiYgaGFzVmFsdWUgJiYga2V5TmFtZSBpbiBvYmopIHsKICAgICAgICB2YXIgZGVzYyA9IHsKICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICAgIHNldDogTUFOREFUT1JZX1NFVFRFUl9GVU5DVElPTihrZXlOYW1lKSwKICAgICAgICAgIGVudW1lcmFibGU6IF9wcm9wZXJ0eUlzRW51bWVyYWJsZShvYmosIGtleU5hbWUpLAogICAgICAgICAgZ2V0OiB1bmRlZmluZWQKICAgICAgICB9OwoKICAgICAgICBpZiAoX2hhc093blByb3BlcnR5KG9iaiwga2V5TmFtZSkpIHsKICAgICAgICAgIG0ud3JpdGVWYWx1ZXMoa2V5TmFtZSwgb2JqW2tleU5hbWVdKTsKICAgICAgICAgIGRlc2MuZ2V0ID0gREVGQVVMVF9HRVRURVJfRlVOQ1RJT04oa2V5TmFtZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGRlc2MuZ2V0ID0gSU5IRVJJVElOR19HRVRURVJfRlVOQ1RJT04oa2V5TmFtZSk7CiAgICAgICAgfQoKICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCBkZXNjKTsKICAgICAgfQogICAgfTsKICB9CgogIGZ1bmN0aW9uIHVud2F0Y2hLZXkob2JqLCBrZXlOYW1lLCBfbWV0YSkgewogICAgdmFyIG1ldGEkJDEgPSBfbWV0YSA9PT0gdW5kZWZpbmVkID8gKDAsIF9tZXRhMi5wZWVrTWV0YSkob2JqKSA6IF9tZXRhOyAvLyBkbyBub3RoaW5nIG9mIHRoaXMgb2JqZWN0IGhhcyBhbHJlYWR5IGJlZW4gZGVzdHJveWVkCgogICAgaWYgKG1ldGEkJDEgPT09IG51bGwgfHwgbWV0YSQkMS5pc1NvdXJjZURlc3Ryb3llZCgpKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgY291bnQgPSBtZXRhJCQxLnBlZWtXYXRjaGluZyhrZXlOYW1lKTsKCiAgICBpZiAoY291bnQgPT09IDEpIHsKICAgICAgbWV0YSQkMS53cml0ZVdhdGNoaW5nKGtleU5hbWUsIDApOwogICAgICB2YXIgcG9zc2libGVEZXNjID0gZGVzY3JpcHRvckZvclByb3BlcnR5KG9iaiwga2V5TmFtZSwgbWV0YSQkMSk7CiAgICAgIHZhciBpc0Rlc2NyaXB0b3IgPSBwb3NzaWJsZURlc2MgIT09IHVuZGVmaW5lZDsKCiAgICAgIGlmIChpc0Rlc2NyaXB0b3IgJiYgcG9zc2libGVEZXNjLmRpZFVud2F0Y2ggIT09IHVuZGVmaW5lZCkgewogICAgICAgIHBvc3NpYmxlRGVzYy5kaWRVbndhdGNoKG9iaiwga2V5TmFtZSwgbWV0YSQkMSk7CiAgICAgIH0KCiAgICAgIGlmICh0eXBlb2Ygb2JqLmRpZFVud2F0Y2hQcm9wZXJ0eSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIG9iai5kaWRVbndhdGNoUHJvcGVydHkoa2V5TmFtZSk7CiAgICAgIH0KCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICAvLyBJdCBpcyB0cnVlLCB0aGUgZm9sbG93aW5nIGNvZGUgbG9va3MgcXVpdGUgV0FULiBCdXQgaGF2ZSBubyBmZWFyLCBJdAogICAgICAgIC8vIGV4aXN0cyBwdXJlbHkgdG8gaW1wcm92ZSBkZXZlbG9wbWVudCBlcmdvbm9taWNzIGFuZCBpcyByZW1vdmVkIGZyb20KICAgICAgICAvLyBlbWJlci5taW4uanMgYW5kIGVtYmVyLnByb2QuanMgYnVpbGRzLgogICAgICAgIC8vCiAgICAgICAgLy8gU29tZSBmdXJ0aGVyIGNvbnRleHQ6IE9uY2UgYSBwcm9wZXJ0eSBpcyB3YXRjaGVkIGJ5IGVtYmVyLCBieXBhc3NpbmcgYHNldGAKICAgICAgICAvLyBmb3IgbXV0YXRpb24sIHdpbGwgYnlwYXNzIG9ic2VydmF0aW9uLiBUaGlzIGNvZGUgZXhpc3RzIHRvIGFzc2VydCB3aGVuCiAgICAgICAgLy8gdGhhdCBvY2N1cnMsIGFuZCBhdHRlbXB0IHRvIHByb3ZpZGUgbW9yZSBoZWxwZnVsIGZlZWRiYWNrLiBUaGUgYWx0ZXJuYXRpdmUKICAgICAgICAvLyBpcyB0cmlja3kgdG8gZGVidWcgcGFydGlhbGx5IG9ic2VydmFibGUgcHJvcGVydGllcy4KICAgICAgICBpZiAoIWlzRGVzY3JpcHRvciAmJiBrZXlOYW1lIGluIG9iaikgewogICAgICAgICAgdmFyIG1heWJlTWFuZGF0b3J5RGVzY3JpcHRvciA9ICgwLCBfdXRpbHMubG9va3VwRGVzY3JpcHRvcikob2JqLCBrZXlOYW1lKTsKCiAgICAgICAgICBpZiAobWF5YmVNYW5kYXRvcnlEZXNjcmlwdG9yICYmIG1heWJlTWFuZGF0b3J5RGVzY3JpcHRvci5zZXQgJiYgbWF5YmVNYW5kYXRvcnlEZXNjcmlwdG9yLnNldC5pc01hbmRhdG9yeVNldHRlcikgewogICAgICAgICAgICBpZiAobWF5YmVNYW5kYXRvcnlEZXNjcmlwdG9yLmdldCAmJiBtYXliZU1hbmRhdG9yeURlc2NyaXB0b3IuZ2V0LmlzSW5oZXJpdGluZ0dldHRlcikgewogICAgICAgICAgICAgIHZhciBwb3NzaWJsZVZhbHVlID0gbWV0YSQkMS5yZWFkSW5oZXJpdGVkVmFsdWUoa2V5TmFtZSk7CgogICAgICAgICAgICAgIGlmIChwb3NzaWJsZVZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgIGRlbGV0ZSBvYmpba2V5TmFtZV07CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCB7CiAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgIGVudW1lcmFibGU6IE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChvYmosIGtleU5hbWUpLAogICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgIHZhbHVlOiBtZXRhJCQxLnBlZWtWYWx1ZXMoa2V5TmFtZSkKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIG1ldGEkJDEuZGVsZXRlRnJvbVZhbHVlcyhrZXlOYW1lKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoY291bnQgPiAxKSB7CiAgICAgIG1ldGEkJDEud3JpdGVXYXRjaGluZyhrZXlOYW1lLCBjb3VudCAtIDEpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZWFjaFByb3h5Rm9yKGFycmF5KSB7CiAgICB2YXIgZWFjaFByb3h5ID0gRUFDSF9QUk9YSUVTLmdldChhcnJheSk7CgogICAgaWYgKGVhY2hQcm94eSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGVhY2hQcm94eSA9IG5ldyBFYWNoUHJveHkoYXJyYXkpOwogICAgICBFQUNIX1BST1hJRVMuc2V0KGFycmF5LCBlYWNoUHJveHkpOwogICAgfQoKICAgIHJldHVybiBlYWNoUHJveHk7CiAgfQoKICB2YXIgRWFjaFByb3h5ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRWFjaFByb3h5KGNvbnRlbnQpIHsKICAgICAgdGhpcy5fY29udGVudCA9IGNvbnRlbnQ7CiAgICAgIHRoaXMuX2tleXMgPSB1bmRlZmluZWQ7CiAgICAgICgwLCBfbWV0YTIubWV0YSkodGhpcyk7CiAgICB9IC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KICAgIC8vIEFSUkFZIENIQU5HRVMKICAgIC8vIEludm9rZXMgd2hlbmV2ZXIgdGhlIGNvbnRlbnQgYXJyYXkgaXRzZWxmIGNoYW5nZXMuCgoKICAgIHZhciBfcHJvdG8gPSBFYWNoUHJveHkucHJvdG90eXBlOwoKICAgIF9wcm90by5hcnJheVdpbGxDaGFuZ2UgPSBmdW5jdGlvbiBhcnJheVdpbGxDaGFuZ2UoY29udGVudCwgaWR4LCByZW1vdmVkQ250CiAgICAvKiwgYWRkZWRDbnQgKi8KICAgICkgewogICAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzCiAgICAgIHZhciBrZXlzID0gdGhpcy5fa2V5czsKCiAgICAgIGlmICgha2V5cykgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIGxpbSA9IHJlbW92ZWRDbnQgPiAwID8gaWR4ICsgcmVtb3ZlZENudCA6IC0xOwoKICAgICAgaWYgKGxpbSA+IDApIHsKICAgICAgICBmb3IgKHZhciBrZXkgaW4ga2V5cykgewogICAgICAgICAgcmVtb3ZlT2JzZXJ2ZXJGb3JDb250ZW50S2V5KGNvbnRlbnQsIGtleSwgdGhpcywgaWR4LCBsaW0pOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uYXJyYXlEaWRDaGFuZ2UgPSBmdW5jdGlvbiBhcnJheURpZENoYW5nZShjb250ZW50LCBpZHgsIF9yZW1vdmVkQ250LCBhZGRlZENudCkgewogICAgICB2YXIga2V5cyA9IHRoaXMuX2tleXM7CgogICAgICBpZiAoIWtleXMpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBsaW0gPSBhZGRlZENudCA+IDAgPyBpZHggKyBhZGRlZENudCA6IC0xOwogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKHRoaXMpOwoKICAgICAgZm9yICh2YXIga2V5IGluIGtleXMpIHsKICAgICAgICBpZiAobGltID4gMCkgewogICAgICAgICAgYWRkT2JzZXJ2ZXJGb3JDb250ZW50S2V5KGNvbnRlbnQsIGtleSwgdGhpcywgaWR4LCBsaW0pOwogICAgICAgIH0KCiAgICAgICAgbm90aWZ5UHJvcGVydHlDaGFuZ2UodGhpcywga2V5LCBtZXRhJCQxKTsKICAgICAgfQogICAgfSAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uCiAgICAvLyBMSVNURU4gRk9SIE5FVyBPQlNFUlZFUlMgQU5EIE9USEVSIEVWRU5UIExJU1RFTkVSUwogICAgLy8gU3RhcnQgbW9uaXRvcmluZyBrZXlzIGJhc2VkIG9uIHdobyBpcyBsaXN0ZW5pbmcuLi4KICAgIDsKCiAgICBfcHJvdG8ud2lsbFdhdGNoUHJvcGVydHkgPSBmdW5jdGlvbiB3aWxsV2F0Y2hQcm9wZXJ0eShwcm9wZXJ0eSkgewogICAgICB0aGlzLmJlZ2luT2JzZXJ2aW5nQ29udGVudEtleShwcm9wZXJ0eSk7CiAgICB9OwoKICAgIF9wcm90by5kaWRVbndhdGNoUHJvcGVydHkgPSBmdW5jdGlvbiBkaWRVbndhdGNoUHJvcGVydHkocHJvcGVydHkpIHsKICAgICAgdGhpcy5zdG9wT2JzZXJ2aW5nQ29udGVudEtleShwcm9wZXJ0eSk7CiAgICB9IC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KICAgIC8vIENPTlRFTlQgS0VZIE9CU0VSVklORwogICAgLy8gQWN0dWFsIHdhdGNoIGtleXMgb24gdGhlIHNvdXJjZSBjb250ZW50LgogICAgOwoKICAgIF9wcm90by5iZWdpbk9ic2VydmluZ0NvbnRlbnRLZXkgPSBmdW5jdGlvbiBiZWdpbk9ic2VydmluZ0NvbnRlbnRLZXkoa2V5TmFtZSkgewogICAgICB2YXIga2V5cyA9IHRoaXMuX2tleXM7CgogICAgICBpZiAoa2V5cyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAga2V5cyA9IHRoaXMuX2tleXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB9CgogICAgICBpZiAoIWtleXNba2V5TmFtZV0pIHsKICAgICAgICBrZXlzW2tleU5hbWVdID0gMTsKICAgICAgICB2YXIgY29udGVudCA9IHRoaXMuX2NvbnRlbnQ7CiAgICAgICAgdmFyIGxlbiA9IGNvbnRlbnQubGVuZ3RoOwogICAgICAgIGFkZE9ic2VydmVyRm9yQ29udGVudEtleShjb250ZW50LCBrZXlOYW1lLCB0aGlzLCAwLCBsZW4pOwogICAgICB9IGVsc2UgewogICAgICAgIGtleXNba2V5TmFtZV0rKzsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uc3RvcE9ic2VydmluZ0NvbnRlbnRLZXkgPSBmdW5jdGlvbiBzdG9wT2JzZXJ2aW5nQ29udGVudEtleShrZXlOYW1lKSB7CiAgICAgIHZhciBrZXlzID0gdGhpcy5fa2V5czsKCiAgICAgIGlmIChrZXlzICE9PSB1bmRlZmluZWQgJiYga2V5c1trZXlOYW1lXSA+IDAgJiYgLS1rZXlzW2tleU5hbWVdIDw9IDApIHsKICAgICAgICB2YXIgY29udGVudCA9IHRoaXMuX2NvbnRlbnQ7CiAgICAgICAgdmFyIGxlbiA9IGNvbnRlbnQubGVuZ3RoOwogICAgICAgIHJlbW92ZU9ic2VydmVyRm9yQ29udGVudEtleShjb250ZW50LCBrZXlOYW1lLCB0aGlzLCAwLCBsZW4pOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5jb250ZW50S2V5RGlkQ2hhbmdlID0gZnVuY3Rpb24gY29udGVudEtleURpZENoYW5nZShfb2JqLCBrZXlOYW1lKSB7CiAgICAgIG5vdGlmeVByb3BlcnR5Q2hhbmdlKHRoaXMsIGtleU5hbWUpOwogICAgfTsKCiAgICByZXR1cm4gRWFjaFByb3h5OwogIH0oKTsKCiAgZnVuY3Rpb24gYWRkT2JzZXJ2ZXJGb3JDb250ZW50S2V5KGNvbnRlbnQsIGtleU5hbWUsIHByb3h5LCBpZHgsIGxvYykgewogICAgd2hpbGUgKC0tbG9jID49IGlkeCkgewogICAgICB2YXIgaXRlbSA9IG9iamVjdEF0KGNvbnRlbnQsIGxvYyk7CgogICAgICBpZiAoaXRlbSkgewogICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBpdGVtID09PSAnb2JqZWN0JykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJXaGVuIHVzaW5nIEBlYWNoIHRvIG9ic2VydmUgdGhlIGFycmF5IGAiICsgY29udGVudC50b1N0cmluZygpICsgImAsIHRoZSBhcnJheSBtdXN0IHJldHVybiBhbiBvYmplY3QiLCB0eXBlb2YgaXRlbSA9PT0gJ29iamVjdCcpKTsKICAgICAgICBhZGRPYnNlcnZlcihpdGVtLCBrZXlOYW1lLCBwcm94eSwgJ2NvbnRlbnRLZXlEaWRDaGFuZ2UnKTsKICAgICAgfQogICAgfQogIH0KCiAgZnVuY3Rpb24gcmVtb3ZlT2JzZXJ2ZXJGb3JDb250ZW50S2V5KGNvbnRlbnQsIGtleU5hbWUsIHByb3h5LCBpZHgsIGxvYykgewogICAgd2hpbGUgKC0tbG9jID49IGlkeCkgewogICAgICB2YXIgaXRlbSA9IG9iamVjdEF0KGNvbnRlbnQsIGxvYyk7CgogICAgICBpZiAoaXRlbSkgewogICAgICAgIHJlbW92ZU9ic2VydmVyKGl0ZW0sIGtleU5hbWUsIHByb3h5LCAnY29udGVudEtleURpZENoYW5nZScpOwogICAgICB9CiAgICB9CiAgfQoKICB2YXIgVU5LTk9XTl9QUk9QRVJUWV9UQUcgPSAoMCwgX3V0aWxzLnN5bWJvbCkoJ1VOS05PV05fUFJPUEVSVFlfVEFHJyk7CiAgX2V4cG9ydHMuVU5LTk9XTl9QUk9QRVJUWV9UQUcgPSBVTktOT1dOX1BST1BFUlRZX1RBRzsKCiAgZnVuY3Rpb24gdGFnRm9yUHJvcGVydHkob2JqZWN0LCBwcm9wZXJ0eUtleSwgX21ldGEpIHsKICAgIHZhciBvYmplY3RUeXBlID0gdHlwZW9mIG9iamVjdDsKCiAgICBpZiAob2JqZWN0VHlwZSAhPT0gJ2Z1bmN0aW9uJyAmJiAob2JqZWN0VHlwZSAhPT0gJ29iamVjdCcgfHwgb2JqZWN0ID09PSBudWxsKSkgewogICAgICByZXR1cm4gX3JlZmVyZW5jZS5DT05TVEFOVF9UQUc7CiAgICB9CgogICAgdmFyIG1ldGEkJDEgPSBfbWV0YSA9PT0gdW5kZWZpbmVkID8gKDAsIF9tZXRhMi5tZXRhKShvYmplY3QpIDogX21ldGE7CiAgICB7CiAgICAgIGlmICghKHByb3BlcnR5S2V5IGluIG9iamVjdCkgJiYgdHlwZW9mIG9iamVjdFtVTktOT1dOX1BST1BFUlRZX1RBR10gPT09ICdmdW5jdGlvbicpIHsKICAgICAgICByZXR1cm4gb2JqZWN0W1VOS05PV05fUFJPUEVSVFlfVEFHXShwcm9wZXJ0eUtleSk7CiAgICAgIH0KICAgIH0KICAgIHZhciB0YWdzID0gbWV0YSQkMS53cml0YWJsZVRhZ3MoKTsKICAgIHZhciB0YWcgPSB0YWdzW3Byb3BlcnR5S2V5XTsKCiAgICBpZiAodGFnKSB7CiAgICAgIHJldHVybiB0YWc7CiAgICB9CgogICAgewogICAgICB2YXIgbmV3VGFnID0gKDAsIF9yZWZlcmVuY2UuY3JlYXRlVXBkYXRhYmxlVGFnKSgpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIHsKICAgICAgICAgICgwLCBfdXRpbHMuc2V0dXBNYW5kYXRvcnlTZXR0ZXIpKG9iamVjdCwgcHJvcGVydHlLZXkpOwogICAgICAgIH0KICAgICAgICBuZXdUYWcuX3Byb3BlcnR5S2V5ID0gcHJvcGVydHlLZXk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0YWdzW3Byb3BlcnR5S2V5XSA9IG5ld1RhZzsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHRhZ0ZvcihvYmplY3QsIF9tZXRhKSB7CiAgICBpZiAodHlwZW9mIG9iamVjdCA9PT0gJ29iamVjdCcgJiYgb2JqZWN0ICE9PSBudWxsKSB7CiAgICAgIHZhciBtZXRhJCQxID0gX21ldGEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIubWV0YSkob2JqZWN0KSA6IF9tZXRhOwoKICAgICAgaWYgKCFtZXRhJCQxLmlzTWV0YURlc3Ryb3llZCgpKSB7CiAgICAgICAgcmV0dXJuIG1ldGEkJDEud3JpdGFibGVUYWcoKTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBfcmVmZXJlbmNlLkNPTlNUQU5UX1RBRzsKICB9CgogIGZ1bmN0aW9uIG1hcmtPYmplY3RBc0RpcnR5KG9iaiwgcHJvcGVydHlLZXksIF9tZXRhKSB7CiAgICB2YXIgbWV0YSQkMSA9IF9tZXRhID09PSB1bmRlZmluZWQgPyAoMCwgX21ldGEyLm1ldGEpKG9iaikgOiBfbWV0YTsKICAgIHZhciBvYmplY3RUYWcgPSBtZXRhJCQxLnJlYWRhYmxlVGFnKCk7CgogICAgaWYgKG9iamVjdFRhZyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICgwLCBfcmVmZXJlbmNlLmRpcnR5KShvYmplY3RUYWcpOwogICAgfQoKICAgIHZhciB0YWdzID0gbWV0YSQkMS5yZWFkYWJsZVRhZ3MoKTsKICAgIHZhciBwcm9wZXJ0eVRhZyA9IHRhZ3MgIT09IHVuZGVmaW5lZCA/IHRhZ3NbcHJvcGVydHlLZXldIDogdW5kZWZpbmVkOwoKICAgIGlmIChwcm9wZXJ0eVRhZyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICgwLCBfcmVmZXJlbmNlLmRpcnR5KShwcm9wZXJ0eVRhZyk7CiAgICB9CgogICAgaWYgKG9iamVjdFRhZyAhPT0gdW5kZWZpbmVkIHx8IHByb3BlcnR5VGFnICE9PSB1bmRlZmluZWQpIHsKICAgICAgZW5zdXJlUnVubG9vcCgpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZW5zdXJlUnVubG9vcCgpIHsKICAgIF9ydW5sb29wLmJhY2tidXJuZXIuZW5zdXJlSW5zdGFuY2UoKTsKICB9CgogIGZ1bmN0aW9uIGlzRWxlbWVudERlc2NyaXB0b3IoYXJncykgewogICAgdmFyIG1heWJlVGFyZ2V0ID0gYXJnc1swXSwKICAgICAgICBtYXliZUtleSA9IGFyZ3NbMV0sCiAgICAgICAgbWF5YmVEZXNjID0gYXJnc1syXTsKICAgIHJldHVybiAoLy8gRW5zdXJlIHdlIGhhdmUgdGhlIHJpZ2h0IG51bWJlciBvZiBhcmdzCiAgICAgIGFyZ3MubGVuZ3RoID09PSAzICYmICggLy8gTWFrZSBzdXJlIHRoZSB0YXJnZXQgaXMgYSBjbGFzcyBvciBvYmplY3QgKHByb3RvdHlwZSkKICAgICAgdHlwZW9mIG1heWJlVGFyZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBtYXliZVRhcmdldCA9PT0gJ29iamVjdCcgJiYgbWF5YmVUYXJnZXQgIT09IG51bGwpICYmIC8vIE1ha2Ugc3VyZSB0aGUga2V5IGlzIGEgc3RyaW5nCiAgICAgIHR5cGVvZiBtYXliZUtleSA9PT0gJ3N0cmluZycgJiYgKCAvLyBNYWtlIHN1cmUgdGhlIGRlc2NyaXB0b3IgaXMgdGhlIHJpZ2h0IHNoYXBlCiAgICAgIHR5cGVvZiBtYXliZURlc2MgPT09ICdvYmplY3QnICYmIG1heWJlRGVzYyAhPT0gbnVsbCAmJiAnZW51bWVyYWJsZScgaW4gbWF5YmVEZXNjICYmICdjb25maWd1cmFibGUnIGluIG1heWJlRGVzYyB8fCAvLyBUUyBjb21wYXRpYmlsaXR5CiAgICAgIG1heWJlRGVzYyA9PT0gdW5kZWZpbmVkKQogICAgKTsKICB9IC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KICAvLyBERVBFTkRFTlQgS0VZUwogIC8vCgoKICBmdW5jdGlvbiBhZGREZXBlbmRlbnRLZXlzKGRlc2MsIG9iaiwga2V5TmFtZSwgbWV0YSQkMSkgewogICAgLy8gdGhlIGRlc2NyaXB0b3IgaGFzIGEgbGlzdCBvZiBkZXBlbmRlbnQga2V5cywgc28KICAgIC8vIGFkZCBhbGwgb2YgaXRzIGRlcGVuZGVudCBrZXlzLgogICAgdmFyIGRlcEtleXMgPSBkZXNjLl9kZXBlbmRlbnRLZXlzOwoKICAgIGlmIChkZXBLZXlzID09PSBudWxsIHx8IGRlcEtleXMgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm47CiAgICB9CgogICAgZm9yICh2YXIgaWR4ID0gMDsgaWR4IDwgZGVwS2V5cy5sZW5ndGg7IGlkeCsrKSB7CiAgICAgIHZhciBkZXBLZXkgPSBkZXBLZXlzW2lkeF07IC8vIEluY3JlbWVudCB0aGUgbnVtYmVyIG9mIHRpbWVzIGRlcEtleSBkZXBlbmRzIG9uIGtleU5hbWUuCgogICAgICBtZXRhJCQxLndyaXRlRGVwcyhkZXBLZXksIGtleU5hbWUsIG1ldGEkJDEucGVla0RlcHMoZGVwS2V5LCBrZXlOYW1lKSArIDEpOyAvLyBXYXRjaCB0aGUgZGVwS2V5CgogICAgICB3YXRjaChvYmosIGRlcEtleSwgbWV0YSQkMSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiByZW1vdmVEZXBlbmRlbnRLZXlzKGRlc2MsIG9iaiwga2V5TmFtZSwgbWV0YSQkMSkgewogICAgLy8gdGhlIGRlc2NyaXB0b3IgaGFzIGEgbGlzdCBvZiBkZXBlbmRlbnQga2V5cywgc28KICAgIC8vIHJlbW92ZSBhbGwgb2YgaXRzIGRlcGVuZGVudCBrZXlzLgogICAgdmFyIGRlcEtleXMgPSBkZXNjLl9kZXBlbmRlbnRLZXlzOwoKICAgIGlmIChkZXBLZXlzID09PSBudWxsIHx8IGRlcEtleXMgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm47CiAgICB9CgogICAgZm9yICh2YXIgaWR4ID0gMDsgaWR4IDwgZGVwS2V5cy5sZW5ndGg7IGlkeCsrKSB7CiAgICAgIHZhciBkZXBLZXkgPSBkZXBLZXlzW2lkeF07IC8vIERlY3JlbWVudCB0aGUgbnVtYmVyIG9mIHRpbWVzIGRlcEtleSBkZXBlbmRzIG9uIGtleU5hbWUuCgogICAgICBtZXRhJCQxLndyaXRlRGVwcyhkZXBLZXksIGtleU5hbWUsIG1ldGEkJDEucGVla0RlcHMoZGVwS2V5LCBrZXlOYW1lKSAtIDEpOyAvLyBVbndhdGNoIHRoZSBkZXBLZXkKCiAgICAgIHVud2F0Y2gob2JqLCBkZXBLZXksIG1ldGEkJDEpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gbmF0aXZlRGVzY0RlY29yYXRvcihwcm9wZXJ0eURlc2MpIHsKICAgIHZhciBkZWNvcmF0b3IgPSBmdW5jdGlvbiBkZWNvcmF0b3IoKSB7CiAgICAgIHJldHVybiBwcm9wZXJ0eURlc2M7CiAgICB9OwoKICAgIHNldENsYXNzaWNEZWNvcmF0b3IoZGVjb3JhdG9yKTsKICAgIHJldHVybiBkZWNvcmF0b3I7CiAgfQogIC8qKgogICAgT2JqZWN0cyBvZiB0aGlzIHR5cGUgY2FuIGltcGxlbWVudCBhbiBpbnRlcmZhY2UgdG8gcmVzcG9uZCB0byByZXF1ZXN0cyB0bwogICAgZ2V0IGFuZCBzZXQuIFRoZSBkZWZhdWx0IGltcGxlbWVudGF0aW9uIGhhbmRsZXMgc2ltcGxlIHByb3BlcnRpZXMuCiAgCiAgICBAY2xhc3MgRGVzY3JpcHRvcgogICAgQHByaXZhdGUKICAqLwoKCiAgdmFyIENvbXB1dGVkRGVzY3JpcHRvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENvbXB1dGVkRGVzY3JpcHRvcigpIHsKICAgICAgdGhpcy5lbnVtZXJhYmxlID0gdHJ1ZTsKICAgICAgdGhpcy5jb25maWd1cmFibGUgPSB0cnVlOwogICAgICB0aGlzLl9kZXBlbmRlbnRLZXlzID0gdW5kZWZpbmVkOwogICAgICB0aGlzLl9tZXRhID0gdW5kZWZpbmVkOwogICAgfQoKICAgIHZhciBfcHJvdG8yID0gQ29tcHV0ZWREZXNjcmlwdG9yLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yLnNldHVwID0gZnVuY3Rpb24gc2V0dXAoX29iaiwga2V5TmFtZSwgX3Byb3BlcnR5RGVzYywgbWV0YSQkMSkgewogICAgICBtZXRhJCQxLndyaXRlRGVzY3JpcHRvcnMoa2V5TmFtZSwgdGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzIudGVhcmRvd24gPSBmdW5jdGlvbiB0ZWFyZG93bihfb2JqLCBrZXlOYW1lLCBtZXRhJCQxKSB7CiAgICAgIG1ldGEkJDEucmVtb3ZlRGVzY3JpcHRvcnMoa2V5TmFtZSk7CiAgICB9OwoKICAgIHJldHVybiBDb21wdXRlZERlc2NyaXB0b3I7CiAgfSgpOwoKICBmdW5jdGlvbiBERVNDUklQVE9SX0dFVFRFUl9GVU5DVElPTihuYW1lLCBkZXNjcmlwdG9yKSB7CiAgICByZXR1cm4gZnVuY3Rpb24gQ1BHRVRURVJfRlVOQ1RJT04oKSB7CiAgICAgIHJldHVybiBkZXNjcmlwdG9yLmdldCh0aGlzLCBuYW1lKTsKICAgIH07CiAgfQoKICBmdW5jdGlvbiBERVNDUklQVE9SX1NFVFRFUl9GVU5DVElPTihuYW1lLCBkZXNjcmlwdG9yKSB7CiAgICB2YXIgZnVuYyA9IGZ1bmN0aW9uIENQU0VUVEVSX0ZVTkNUSU9OKHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiBkZXNjcmlwdG9yLnNldCh0aGlzLCBuYW1lLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIENQX1NFVFRFUl9GVU5DUy5hZGQoZnVuYyk7CiAgICByZXR1cm4gZnVuYzsKICB9CgogIHZhciBDUF9TRVRURVJfRlVOQ1MgPSBuZXcgX3BvbHlmaWxscy5fV2Vha1NldCgpOwoKICBmdW5jdGlvbiBtYWtlQ29tcHV0ZWREZWNvcmF0b3IoZGVzYywgRGVjb3JhdG9yQ2xhc3MpIHsKICAgIHZhciBkZWNvcmF0b3IgPSBmdW5jdGlvbiBDT01QVVRFRF9ERUNPUkFUT1IodGFyZ2V0LCBrZXksIHByb3BlcnR5RGVzYywgbWF5YmVNZXRhLCBpc0NsYXNzaWNEZWNvcmF0b3IkJDEpIHsKICAgICAgKGZhbHNlICYmICEodHJ1ZQogICAgICAvKiBFTUJFUl9OQVRJVkVfREVDT1JBVE9SX1NVUFBPUlQgKi8KICAgICAgfHwgaXNDbGFzc2ljRGVjb3JhdG9yJCQxKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ05hdGl2ZSBkZWNvcmF0b3JzIGFyZSBub3QgZW5hYmxlZCB3aXRob3V0IHRoZSBFTUJFUl9OQVRJVkVfREVDT1JBVE9SX1NVUFBPUlQgZmxhZycsIHRydWUgfHwgaXNDbGFzc2ljRGVjb3JhdG9yJCQxKSk7CiAgICAgIChmYWxzZSAmJiAhKGlzQ2xhc3NpY0RlY29yYXRvciQkMSB8fCAhcHJvcGVydHlEZXNjIHx8ICFwcm9wZXJ0eURlc2MuZ2V0IHx8IHByb3BlcnR5RGVzYy5nZXQudG9TdHJpbmcoKS5pbmRleE9mKCdDUEdFVFRFUl9GVU5DVElPTicpID09PSAtMSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJPbmx5IG9uZSBjb21wdXRlZCBwcm9wZXJ0eSBkZWNvcmF0b3IgY2FuIGJlIGFwcGxpZWQgdG8gYSBjbGFzcyBmaWVsZCBvciBhY2Nlc3NvciwgYnV0ICciICsga2V5ICsgIicgd2FzIGRlY29yYXRlZCB0d2ljZS4gWW91IG1heSBoYXZlIGFkZGVkIHRoZSBkZWNvcmF0b3IgdG8gYm90aCBhIGdldHRlciBhbmQgc2V0dGVyLCB3aGljaCBpcyB1bmVjZXNzYXJ5LiIsIGlzQ2xhc3NpY0RlY29yYXRvciQkMSB8fCAhcHJvcGVydHlEZXNjIHx8ICFwcm9wZXJ0eURlc2MuZ2V0IHx8IHByb3BlcnR5RGVzYy5nZXQudG9TdHJpbmcoKS5pbmRleE9mKCdDUEdFVFRFUl9GVU5DVElPTicpID09PSAtMSkpOwogICAgICB2YXIgbWV0YSQkMSA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDMgPyAoMCwgX21ldGEyLm1ldGEpKHRhcmdldCkgOiBtYXliZU1ldGE7CiAgICAgIGRlc2Muc2V0dXAodGFyZ2V0LCBrZXksIHByb3BlcnR5RGVzYywgbWV0YSQkMSk7CiAgICAgIHZhciBjb21wdXRlZERlc2MgPSB7CiAgICAgICAgZW51bWVyYWJsZTogZGVzYy5lbnVtZXJhYmxlLAogICAgICAgIGNvbmZpZ3VyYWJsZTogZGVzYy5jb25maWd1cmFibGUsCiAgICAgICAgZ2V0OiBERVNDUklQVE9SX0dFVFRFUl9GVU5DVElPTihrZXksIGRlc2MpCiAgICAgIH07CiAgICAgIHsKICAgICAgICBjb21wdXRlZERlc2Muc2V0ID0gREVTQ1JJUFRPUl9TRVRURVJfRlVOQ1RJT04oa2V5LCBkZXNjKTsKICAgICAgfQogICAgICByZXR1cm4gY29tcHV0ZWREZXNjOwogICAgfTsKCiAgICBzZXRDbGFzc2ljRGVjb3JhdG9yKGRlY29yYXRvciwgZGVzYyk7CiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YoZGVjb3JhdG9yLCBEZWNvcmF0b3JDbGFzcy5wcm90b3R5cGUpOwogICAgcmV0dXJuIGRlY29yYXRvcjsKICB9CiAgLyoqCiAgICBBbiBvYmplY3QgdGhhdCB0aGF0IHRyYWNrcyBAdHJhY2tlZCBwcm9wZXJ0aWVzIHRoYXQgd2VyZSBjb25zdW1lZC4KICAKICAgIEBwcml2YXRlCiAgKi8KCgogIHZhciBUcmFja2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gVHJhY2tlcigpIHsKICAgICAgdGhpcy50YWdzID0gbmV3IFNldCgpOwogICAgICB0aGlzLmxhc3QgPSBudWxsOwogICAgfQoKICAgIHZhciBfcHJvdG8zID0gVHJhY2tlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMy5hZGQgPSBmdW5jdGlvbiBhZGQodGFnKSB7CiAgICAgIHRoaXMudGFncy5hZGQodGFnKTsKICAgICAgdGhpcy5sYXN0ID0gdGFnOwogICAgfTsKCiAgICBfcHJvdG8zLmNvbWJpbmUgPSBmdW5jdGlvbiBjb21iaW5lKCkgewogICAgICBpZiAodGhpcy50YWdzLnNpemUgPT09IDApIHsKICAgICAgICByZXR1cm4gX3JlZmVyZW5jZS5DT05TVEFOVF9UQUc7CiAgICAgIH0gZWxzZSBpZiAodGhpcy50YWdzLnNpemUgPT09IDEpIHsKICAgICAgICByZXR1cm4gdGhpcy5sYXN0OwogICAgICB9IGVsc2UgewogICAgICAgIHZhciB0YWdzID0gW107CiAgICAgICAgdGhpcy50YWdzLmZvckVhY2goZnVuY3Rpb24gKHRhZykgewogICAgICAgICAgcmV0dXJuIHRhZ3MucHVzaCh0YWcpOwogICAgICAgIH0pOwogICAgICAgIHJldHVybiAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKSh0YWdzKTsKICAgICAgfQogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKFRyYWNrZXIsIFt7CiAgICAgIGtleTogInNpemUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy50YWdzLnNpemU7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBUcmFja2VyOwogIH0oKTsKCiAgX2V4cG9ydHMuVHJhY2tlciA9IFRyYWNrZXI7CgogIGZ1bmN0aW9uIHRyYWNrZWQoKSB7CiAgICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjIpLCBfa2V5MyA9IDA7IF9rZXkzIDwgX2xlbjI7IF9rZXkzKyspIHsKICAgICAgYXJnc1tfa2V5M10gPSBhcmd1bWVudHNbX2tleTNdOwogICAgfQoKICAgIChmYWxzZSAmJiAhKCEoaXNFbGVtZW50RGVzY3JpcHRvcihhcmdzLnNsaWNlKDAsIDMpKSAmJiBhcmdzLmxlbmd0aCA9PT0gNSAmJiBhcmdzWzRdID09PSB0cnVlKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJAdHJhY2tlZCBjYW4gb25seSBiZSB1c2VkIGRpcmVjdGx5IGFzIGEgbmF0aXZlIGRlY29yYXRvci4gSWYgeW91J3JlIHVzaW5nIHRyYWNrZWQgaW4gY2xhc3NpYyBjbGFzc2VzLCBhZGQgcGFyZW50aGVzaXMgdG8gY2FsbCBpdCBsaWtlIGEgZnVuY3Rpb246IHRyYWNrZWQoKSIsICEoaXNFbGVtZW50RGVzY3JpcHRvcihhcmdzLnNsaWNlKDAsIDMpKSAmJiBhcmdzLmxlbmd0aCA9PT0gNSAmJiBhcmdzWzRdID09PSB0cnVlKSkpOwoKICAgIGlmICghaXNFbGVtZW50RGVzY3JpcHRvcihhcmdzKSkgewogICAgICB2YXIgcHJvcGVydHlEZXNjID0gYXJnc1swXTsKICAgICAgKGZhbHNlICYmICEoYXJncy5sZW5ndGggPT09IDAgfHwgdHlwZW9mIHByb3BlcnR5RGVzYyA9PT0gJ29iamVjdCcgJiYgcHJvcGVydHlEZXNjICE9PSBudWxsKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoInRyYWNrZWQoKSBtYXkgb25seSByZWNlaXZlIGFuIG9wdGlvbnMgb2JqZWN0IGNvbnRhaW5pbmcgJ3ZhbHVlJyBvciAnaW5pdGlhbGl6ZXInLCByZWNlaXZlZCAiICsgcHJvcGVydHlEZXNjLCBhcmdzLmxlbmd0aCA9PT0gMCB8fCB0eXBlb2YgcHJvcGVydHlEZXNjID09PSAnb2JqZWN0JyAmJiBwcm9wZXJ0eURlc2MgIT09IG51bGwpKTsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICAmJiBwcm9wZXJ0eURlc2MpIHsKICAgICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHByb3BlcnR5RGVzYyk7CiAgICAgICAgKGZhbHNlICYmICEoa2V5cy5sZW5ndGggPD0gMSAmJiAoa2V5c1swXSA9PT0gdW5kZWZpbmVkIHx8IGtleXNbMF0gPT09ICd2YWx1ZScgfHwga2V5c1swXSA9PT0gJ2luaXRpYWxpemVyJykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIG9wdGlvbnMgb2JqZWN0IHBhc3NlZCB0byB0cmFja2VkKCkgbWF5IG9ubHkgY29udGFpbiBhICd2YWx1ZScgb3IgJ2luaXRpYWxpemVyJyBwcm9wZXJ0eSwgbm90IGJvdGguIFJlY2VpdmVkOiBbIiArIGtleXMgKyAiXSIsIGtleXMubGVuZ3RoIDw9IDEgJiYgKGtleXNbMF0gPT09IHVuZGVmaW5lZCB8fCBrZXlzWzBdID09PSAndmFsdWUnIHx8IGtleXNbMF0gPT09ICdpbml0aWFsaXplcicpKSk7CiAgICAgICAgKGZhbHNlICYmICEoISgnaW5pdGlhbGl6ZXInIGluIHByb3BlcnR5RGVzYykgfHwgdHlwZW9mIHByb3BlcnR5RGVzYy5pbml0aWFsaXplciA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgaW5pdGlhbGl6ZXIgcGFzc2VkIHRvIHRyYWNrZWQgbXVzdCBiZSBhIGZ1bmN0aW9uLiBSZWNlaXZlZCAiICsgcHJvcGVydHlEZXNjLmluaXRpYWxpemVyLCAhKCdpbml0aWFsaXplcicgaW4gcHJvcGVydHlEZXNjKSB8fCB0eXBlb2YgcHJvcGVydHlEZXNjLmluaXRpYWxpemVyID09PSAnZnVuY3Rpb24nKSk7CiAgICAgIH0KCiAgICAgIHZhciBpbml0aWFsaXplciA9IHByb3BlcnR5RGVzYyA/IHByb3BlcnR5RGVzYy5pbml0aWFsaXplciA6IHVuZGVmaW5lZDsKICAgICAgdmFyIHZhbHVlJCQxID0gcHJvcGVydHlEZXNjID8gcHJvcGVydHlEZXNjLnZhbHVlIDogdW5kZWZpbmVkOwoKICAgICAgdmFyIGRlY29yYXRvciA9IGZ1bmN0aW9uIGRlY29yYXRvcih0YXJnZXQsIGtleSwgX2Rlc2MsIF9tZXRhLCBpc0NsYXNzaWNEZWNvcmF0b3IkJDEpIHsKICAgICAgICAoZmFsc2UgJiYgIShpc0NsYXNzaWNEZWNvcmF0b3IkJDEpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byBzZXQgYSBkZWZhdWx0IHZhbHVlIGZvciAiICsga2V5ICsgIiB3aXRoIHRoZSBAdHJhY2tlZCh7IHZhbHVlOiAnZGVmYXVsdCcgfSkgc3ludGF4LiBZb3UgY2FuIG9ubHkgdXNlIHRoaXMgc3ludGF4IHdpdGggY2xhc3NpYyBjbGFzc2VzLiBGb3IgbmF0aXZlIGNsYXNzZXMsIHlvdSBjYW4gdXNlIGNsYXNzIGluaXRpYWxpemVyczogQHRyYWNrZWQgZmllbGQgPSAnZGVmYXVsdCc7IiwgaXNDbGFzc2ljRGVjb3JhdG9yJCQxKSk7CiAgICAgICAgdmFyIGZpZWxkRGVzYyA9IHsKICAgICAgICAgIGluaXRpYWxpemVyOiBpbml0aWFsaXplciB8fCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIHJldHVybiB2YWx1ZSQkMTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHJldHVybiBkZXNjcmlwdG9yRm9yRmllbGQoW3RhcmdldCwga2V5LCBmaWVsZERlc2NdKTsKICAgICAgfTsKCiAgICAgIHNldENsYXNzaWNEZWNvcmF0b3IoZGVjb3JhdG9yKTsKICAgICAgcmV0dXJuIGRlY29yYXRvcjsKICAgIH0KCiAgICAoZmFsc2UgJiYgIShCb29sZWFuKHRydWUKICAgIC8qIEVNQkVSX05BVElWRV9ERUNPUkFUT1JfU1VQUE9SVCAqLwogICAgKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdOYXRpdmUgZGVjb3JhdG9ycyBhcmUgbm90IGVuYWJsZWQgd2l0aG91dCB0aGUgRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUIGZsYWcnLCBCb29sZWFuKHRydWUpKSk7CiAgICByZXR1cm4gZGVzY3JpcHRvckZvckZpZWxkKGFyZ3MpOwogIH0KCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIC8vIE5vcm1hbGx5IHRoaXMgaXNuJ3QgYSBjbGFzc2ljIGRlY29yYXRvciwgYnV0IHdlIHdhbnQgdG8gdGhyb3cgYSBoZWxwZnVsCiAgICAvLyBlcnJvciBpbiBkZXZlbG9wbWVudCBzbyB3ZSBuZWVkIGl0IHRvIHRyZWF0IGl0IGxpa2Ugb25lCiAgICBzZXRDbGFzc2ljRGVjb3JhdG9yKHRyYWNrZWQpOwogIH0KCiAgZnVuY3Rpb24gZGVzY3JpcHRvckZvckZpZWxkKF9yZWYpIHsKICAgIHZhciBfdGFyZ2V0ID0gX3JlZlswXSwKICAgICAgICBrZXkgPSBfcmVmWzFdLAogICAgICAgIGRlc2MgPSBfcmVmWzJdOwogICAgKGZhbHNlICYmICEoIWRlc2MgfHwgIWRlc2MudmFsdWUgJiYgIWRlc2MuZ2V0ICYmICFkZXNjLnNldCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAdHJhY2tlZCBvbiAiICsga2V5ICsgIiwgYnV0IHRoYXQgZWxlbWVudCBpcyBub3QgYSBjbGFzcyBmaWVsZC4gQHRyYWNrZWQgaXMgb25seSB1c2FibGUgb24gY2xhc3MgZmllbGRzLiBOYXRpdmUgZ2V0dGVycyBhbmQgc2V0dGVycyB3aWxsIGF1dG90cmFjayBhZGQgYW55IHRyYWNrZWQgZmllbGRzIHRoZXkgZW5jb3VudGVyLCBzbyB0aGVyZSBpcyBubyBuZWVkIG1hcmsgZ2V0dGVycyBhbmQgc2V0dGVycyB3aXRoIEB0cmFja2VkLiIsICFkZXNjIHx8ICFkZXNjLnZhbHVlICYmICFkZXNjLmdldCAmJiAhZGVzYy5zZXQpKTsKICAgIHZhciBpbml0aWFsaXplciA9IGRlc2MgPyBkZXNjLmluaXRpYWxpemVyIDogdW5kZWZpbmVkOwogICAgdmFyIHZhbHVlcyA9IG5ldyBXZWFrTWFwKCk7CiAgICB2YXIgaGFzSW5pdGlhbGl6ZXIgPSB0eXBlb2YgaW5pdGlhbGl6ZXIgPT09ICdmdW5jdGlvbic7CiAgICByZXR1cm4gewogICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBwcm9wZXJ0eVRhZyA9IHRhZ0ZvclByb3BlcnR5KHRoaXMsIGtleSk7CiAgICAgICAgaWYgKENVUlJFTlRfVFJBQ0tFUikgQ1VSUkVOVF9UUkFDS0VSLmFkZChwcm9wZXJ0eVRhZyk7CiAgICAgICAgdmFyIHZhbHVlJCQxOyAvLyBJZiB0aGUgZmllbGQgaGFzIG5ldmVyIGJlZW4gaW5pdGlhbGl6ZWQsIHdlIHNob3VsZCBpbml0aWFsaXplIGl0CgogICAgICAgIGlmIChoYXNJbml0aWFsaXplciAmJiAhdmFsdWVzLmhhcyh0aGlzKSkgewogICAgICAgICAgdmFsdWUkJDEgPSBpbml0aWFsaXplci5jYWxsKHRoaXMpOwogICAgICAgICAgdmFsdWVzLnNldCh0aGlzLCB2YWx1ZSQkMSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhbHVlJCQxID0gdmFsdWVzLmdldCh0aGlzKTsKICAgICAgICB9IC8vIEFkZCB0aGUgdGFnIG9mIHRoZSByZXR1cm5lZCB2YWx1ZSBpZiBpdCBpcyBhbiBhcnJheSwgc2luY2UgYXJyYXlzCiAgICAgICAgLy8gc2hvdWxkIGFsd2F5cyBjYXVzZSB1cGRhdGVzIGlmIHRoZXkgYXJlIGNvbnN1bWVkIGFuZCB0aGVuIGNoYW5nZWQKCgogICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlJCQxKSB8fCAoMCwgX3V0aWxzLmlzRW1iZXJBcnJheSkodmFsdWUkJDEpKSB7CiAgICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHByb3BlcnR5VGFnLCB0YWdGb3JQcm9wZXJ0eSh2YWx1ZSQkMSwgJ1tdJykpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHZhbHVlJCQxOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldChuZXdWYWx1ZSkgewogICAgICAgIG1hcmtPYmplY3RBc0RpcnR5KHRoaXMsIGtleSk7CiAgICAgICAgdmFsdWVzLnNldCh0aGlzLCBuZXdWYWx1ZSk7CgogICAgICAgIGlmIChwcm9wZXJ0eURpZENoYW5nZSAhPT0gbnVsbCkgewogICAgICAgICAgcHJvcGVydHlEaWRDaGFuZ2UoKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CiAgfQogIC8qKgogICAgQHByaXZhdGUKICAKICAgIFdoZW5ldmVyIGEgdHJhY2tlZCBjb21wdXRlZCBwcm9wZXJ0eSBpcyBlbnRlcmVkLCB0aGUgY3VycmVudCB0cmFja2VyIGlzCiAgICBzYXZlZCBvZmYgYW5kIGEgbmV3IHRyYWNrZXIgaXMgcmVwbGFjZWQuCiAgCiAgICBBbnkgdHJhY2tlZCBwcm9wZXJ0aWVzIGNvbnN1bWVkIGFyZSBhZGRlZCB0byB0aGUgY3VycmVudCB0cmFja2VyLgogIAogICAgV2hlbiBhIHRyYWNrZWQgY29tcHV0ZWQgcHJvcGVydHkgaXMgZXhpdGVkLCB0aGUgdHJhY2tlcidzIHRhZ3MgYXJlCiAgICBjb21iaW5lZCBhbmQgYWRkZWQgdG8gdGhlIHBhcmVudCB0cmFja2VyLgogIAogICAgVGhlIGNvbnNlcXVlbmNlIGlzIHRoYXQgZWFjaCB0cmFja2VkIGNvbXB1dGVkIHByb3BlcnR5IGhhcyBhIHRhZwogICAgdGhhdCBjb3JyZXNwb25kcyB0byB0aGUgdHJhY2tlZCBwcm9wZXJ0aWVzIGNvbnN1bWVkIGluc2lkZSBvZgogICAgaXRzZWxmLCBpbmNsdWRpbmcgY2hpbGQgdHJhY2tlZCBjb21wdXRlZCBwcm9wZXJ0aWVzLgogICovCgoKICB2YXIgQ1VSUkVOVF9UUkFDS0VSID0gbnVsbDsKCiAgZnVuY3Rpb24gdHJhY2soY2FsbGJhY2spIHsKICAgIHZhciBwYXJlbnQgPSBDVVJSRU5UX1RSQUNLRVI7CiAgICB2YXIgY3VycmVudCA9IG5ldyBUcmFja2VyKCk7CiAgICBDVVJSRU5UX1RSQUNLRVIgPSBjdXJyZW50OwoKICAgIHRyeSB7CiAgICAgIGNhbGxiYWNrKCk7CiAgICB9IGZpbmFsbHkgewogICAgICBDVVJSRU5UX1RSQUNLRVIgPSBwYXJlbnQ7CiAgICB9CgogICAgcmV0dXJuIGN1cnJlbnQuY29tYmluZSgpOwogIH0KCiAgZnVuY3Rpb24gY29uc3VtZSh0YWcpIHsKICAgIGlmIChDVVJSRU5UX1RSQUNLRVIgIT09IG51bGwpIHsKICAgICAgQ1VSUkVOVF9UUkFDS0VSLmFkZCh0YWcpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gaXNUcmFja2luZygpIHsKICAgIHJldHVybiBDVVJSRU5UX1RSQUNLRVIgIT09IG51bGw7CiAgfQoKICBmdW5jdGlvbiB1bnRyYWNrKGNhbGxiYWNrKSB7CiAgICB2YXIgcGFyZW50ID0gQ1VSUkVOVF9UUkFDS0VSOwogICAgQ1VSUkVOVF9UUkFDS0VSID0gbnVsbDsKCiAgICB0cnkgewogICAgICBjYWxsYmFjaygpOwogICAgfSBmaW5hbGx5IHsKICAgICAgQ1VSUkVOVF9UUkFDS0VSID0gcGFyZW50OwogICAgfQogIH0KCiAgdmFyIHByb3BlcnR5RGlkQ2hhbmdlID0gbnVsbDsKICAvKioKICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwoKICB2YXIgUFJPWFlfQ09OVEVOVCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnUFJPWFlfQ09OVEVOVCcpOwogIF9leHBvcnRzLlBST1hZX0NPTlRFTlQgPSBQUk9YWV9DT05URU5UOwogIHZhciBnZXRQb3NzaWJsZU1hbmRhdG9yeVByb3h5VmFsdWU7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgJiYgX3V0aWxzLkhBU19OQVRJVkVfUFJPWFkpIHsKICAgIGdldFBvc3NpYmxlTWFuZGF0b3J5UHJveHlWYWx1ZSA9IGZ1bmN0aW9uIGdldFBvc3NpYmxlTWFuZGF0b3J5UHJveHlWYWx1ZShvYmosIGtleU5hbWUpIHsKICAgICAgdmFyIGNvbnRlbnQgPSBvYmpbUFJPWFlfQ09OVEVOVF07CgogICAgICBpZiAoY29udGVudCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIG9ialtrZXlOYW1lXTsKICAgICAgfSBlbHNlIHsKICAgICAgICAvKiBnbG9iYWwgUmVmbGVjdCAqLwogICAgICAgIHJldHVybiBSZWZsZWN0LmdldChjb250ZW50LCBrZXlOYW1lLCBvYmopOwogICAgICB9CiAgICB9OwogIH0gLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogIC8vIEdFVCBBTkQgU0VUCiAgLy8KICAvLyBJZiB3ZSBhcmUgb24gYSBwbGF0Zm9ybSB0aGF0IHN1cHBvcnRzIGFjY2Vzc29ycyB3ZSBjYW4gdXNlIHRob3NlLgogIC8vIE90aGVyd2lzZSBzaW11bGF0ZSBhY2Nlc3NvcnMgYnkgbG9va2luZyB1cCB0aGUgcHJvcGVydHkgZGlyZWN0bHkgb24gdGhlCiAgLy8gb2JqZWN0LgoKICAvKioKICAgIEdldHMgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgb24gYW4gb2JqZWN0LiBJZiB0aGUgcHJvcGVydHkgaXMgY29tcHV0ZWQsCiAgICB0aGUgZnVuY3Rpb24gd2lsbCBiZSBpbnZva2VkLiBJZiB0aGUgcHJvcGVydHkgaXMgbm90IGRlZmluZWQgYnV0IHRoZQogICAgb2JqZWN0IGltcGxlbWVudHMgdGhlIGB1bmtub3duUHJvcGVydHlgIG1ldGhvZCB0aGVuIHRoYXQgd2lsbCBiZSBpbnZva2VkLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZ2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBnZXQob2JqLCAibmFtZSIpOwogICAgYGBgCiAgCiAgICBJZiB5b3UgcGxhbiB0byBydW4gb24gSUU4IGFuZCBvbGRlciBicm93c2VycyB0aGVuIHlvdSBzaG91bGQgdXNlIHRoaXMKICAgIG1ldGhvZCBhbnl0aW1lIHlvdSB3YW50IHRvIHJldHJpZXZlIGEgcHJvcGVydHkgb24gYW4gb2JqZWN0IHRoYXQgeW91IGRvbid0CiAgICBrbm93IGZvciBzdXJlIGlzIHByaXZhdGUuIChQcm9wZXJ0aWVzIGJlZ2lubmluZyB3aXRoIGFuIHVuZGVyc2NvcmUgJ18nCiAgICBhcmUgY29uc2lkZXJlZCBwcml2YXRlLikKICAKICAgIE9uIGFsbCBuZXdlciBicm93c2VycywgeW91IG9ubHkgbmVlZCB0byB1c2UgdGhpcyBtZXRob2QgdG8gcmV0cmlldmUKICAgIHByb3BlcnRpZXMgaWYgdGhlIHByb3BlcnR5IG1pZ2h0IG5vdCBiZSBkZWZpbmVkIG9uIHRoZSBvYmplY3QgYW5kIHlvdSB3YW50CiAgICB0byByZXNwZWN0IHRoZSBgdW5rbm93blByb3BlcnR5YCBoYW5kbGVyLiBPdGhlcndpc2UgeW91IGNhbiBpZ25vcmUgdGhpcwogICAgbWV0aG9kLgogIAogICAgTm90ZSB0aGF0IGlmIHRoZSBvYmplY3QgaXRzZWxmIGlzIGB1bmRlZmluZWRgLCB0aGlzIG1ldGhvZCB3aWxsIHRocm93CiAgICBhbiBlcnJvci4KICAKICAgIEBtZXRob2QgZ2V0CiAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byByZXRyaWV2ZSBmcm9tLgogICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIHByb3BlcnR5IGtleSB0byByZXRyaWV2ZQogICAgQHJldHVybiB7T2JqZWN0fSB0aGUgcHJvcGVydHkgdmFsdWUgb3IgYG51bGxgLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBfZ2V0MihvYmosIGtleU5hbWUpIHsKICAgIChmYWxzZSAmJiAhKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiR2V0IG11c3QgYmUgY2FsbGVkIHdpdGggdHdvIGFyZ3VtZW50czsgYW4gb2JqZWN0IGFuZCBhIHByb3BlcnR5IGtleSIsIGFyZ3VtZW50cy5sZW5ndGggPT09IDIpKTsKICAgIChmYWxzZSAmJiAhKG9iaiAhPT0gdW5kZWZpbmVkICYmIG9iaiAhPT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJDYW5ub3QgY2FsbCBnZXQgd2l0aCAnIiArIGtleU5hbWUgKyAiJyBvbiBhbiB1bmRlZmluZWQgb2JqZWN0LiIsIG9iaiAhPT0gdW5kZWZpbmVkICYmIG9iaiAhPT0gbnVsbCkpOwogICAgKGZhbHNlICYmICEodHlwZW9mIGtleU5hbWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBrZXlOYW1lID09PSAnbnVtYmVyJyAmJiAhaXNOYU4oa2V5TmFtZSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIGtleSBwcm92aWRlZCB0byBnZXQgbXVzdCBiZSBhIHN0cmluZyBvciBudW1iZXIsIHlvdSBwYXNzZWQgIiArIGtleU5hbWUsIHR5cGVvZiBrZXlOYW1lID09PSAnc3RyaW5nJyB8fCB0eXBlb2Yga2V5TmFtZSA9PT0gJ251bWJlcicgJiYgIWlzTmFOKGtleU5hbWUpKSk7CiAgICAoZmFsc2UgJiYgISh0eXBlb2Yga2V5TmFtZSAhPT0gJ3N0cmluZycgfHwga2V5TmFtZS5sYXN0SW5kZXhPZigndGhpcy4nLCAwKSAhPT0gMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCIndGhpcycgaW4gcGF0aHMgaXMgbm90IHN1cHBvcnRlZCIsIHR5cGVvZiBrZXlOYW1lICE9PSAnc3RyaW5nJyB8fCBrZXlOYW1lLmxhc3RJbmRleE9mKCd0aGlzLicsIDApICE9PSAwKSk7CiAgICB2YXIgdHlwZSA9IHR5cGVvZiBvYmo7CiAgICB2YXIgaXNPYmplY3QgPSB0eXBlID09PSAnb2JqZWN0JzsKICAgIHZhciBpc0Z1bmN0aW9uID0gdHlwZSA9PT0gJ2Z1bmN0aW9uJzsKICAgIHZhciBpc09iamVjdExpa2UgPSBpc09iamVjdCB8fCBpc0Z1bmN0aW9uOwoKICAgIGlmIChpc1BhdGgoa2V5TmFtZSkpIHsKICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSA/IF9nZXRQYXRoKG9iaiwga2V5TmFtZSkgOiB1bmRlZmluZWQ7CiAgICB9CgogICAgdmFyIHZhbHVlJCQxOwoKICAgIGlmIChpc09iamVjdExpa2UpIHsKICAgICAgdmFyIHRyYWNraW5nID0gaXNUcmFja2luZygpOwogICAgICB7CiAgICAgICAgaWYgKHRyYWNraW5nKSB7CiAgICAgICAgICBjb25zdW1lKHRhZ0ZvclByb3BlcnR5KG9iaiwga2V5TmFtZSkpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICYmIF91dGlscy5IQVNfTkFUSVZFX1BST1hZKSB7CiAgICAgICAgdmFsdWUkJDEgPSBnZXRQb3NzaWJsZU1hbmRhdG9yeVByb3h5VmFsdWUob2JqLCBrZXlOYW1lKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YWx1ZSQkMSA9IG9ialtrZXlOYW1lXTsKICAgICAgfSAvLyBBZGQgdGhlIHRhZyBvZiB0aGUgcmV0dXJuZWQgdmFsdWUgaWYgaXQgaXMgYW4gYXJyYXksIHNpbmNlIGFycmF5cwogICAgICAvLyBzaG91bGQgYWx3YXlzIGNhdXNlIHVwZGF0ZXMgaWYgdGhleSBhcmUgY29uc3VtZWQgYW5kIHRoZW4gY2hhbmdlZAoKCiAgICAgIGlmICh0cnVlCiAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICAmJiB0cmFja2luZyAmJiAoQXJyYXkuaXNBcnJheSh2YWx1ZSQkMSkgfHwgKDAsIF91dGlscy5pc0VtYmVyQXJyYXkpKHZhbHVlJCQxKSkpIHsKICAgICAgICBjb25zdW1lKHRhZ0ZvclByb3BlcnR5KHZhbHVlJCQxLCAnW10nKSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhbHVlJCQxID0gb2JqW2tleU5hbWVdOwogICAgfQoKICAgIGlmICh2YWx1ZSQkMSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmIChpc09iamVjdCAmJiAhKGtleU5hbWUgaW4gb2JqKSAmJiB0eXBlb2Ygb2JqLnVua25vd25Qcm9wZXJ0eSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIHJldHVybiBvYmoudW5rbm93blByb3BlcnR5KGtleU5hbWUpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHZhbHVlJCQxOwogIH0KCiAgZnVuY3Rpb24gX2dldFBhdGgocm9vdCwgcGF0aCkgewogICAgdmFyIG9iaiA9IHJvb3Q7CiAgICB2YXIgcGFydHMgPSB0eXBlb2YgcGF0aCA9PT0gJ3N0cmluZycgPyBwYXRoLnNwbGl0KCcuJykgOiBwYXRoOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHsKICAgICAgaWYgKG9iaiA9PT0gdW5kZWZpbmVkIHx8IG9iaiA9PT0gbnVsbCB8fCBvYmouaXNEZXN0cm95ZWQpIHsKICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgICB9CgogICAgICBvYmogPSBfZ2V0MihvYmosIHBhcnRzW2ldKTsKICAgIH0KCiAgICByZXR1cm4gb2JqOwogIH0KICAvKioKICAgIFJldHJpZXZlcyB0aGUgdmFsdWUgb2YgYSBwcm9wZXJ0eSBmcm9tIGFuIE9iamVjdCwgb3IgYSBkZWZhdWx0IHZhbHVlIGluIHRoZQogICAgY2FzZSB0aGF0IHRoZSBwcm9wZXJ0eSByZXR1cm5zIGB1bmRlZmluZWRgLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZ2V0V2l0aERlZmF1bHQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGdldFdpdGhEZWZhdWx0KHBlcnNvbiwgJ2xhc3ROYW1lJywgJ0RvZScpOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGdldFdpdGhEZWZhdWx0CiAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byByZXRyaWV2ZSBmcm9tLgogICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIHJldHJpZXZlCiAgICBAcGFyYW0ge09iamVjdH0gZGVmYXVsdFZhbHVlIFRoZSB2YWx1ZSB0byByZXR1cm4gaWYgdGhlIHByb3BlcnR5IHZhbHVlIGlzIHVuZGVmaW5lZAogICAgQHJldHVybiB7T2JqZWN0fSBUaGUgcHJvcGVydHkgdmFsdWUgb3IgdGhlIGRlZmF1bHRWYWx1ZS4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZ2V0V2l0aERlZmF1bHQocm9vdCwga2V5LCBkZWZhdWx0VmFsdWUpIHsKICAgIHZhciB2YWx1ZSQkMSA9IF9nZXQyKHJvb3QsIGtleSk7CgogICAgaWYgKHZhbHVlJCQxID09PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKICAgIH0KCiAgICByZXR1cm4gdmFsdWUkJDE7CiAgfQoKICBmdW5jdGlvbiBpc09iamVjdChvYmopIHsKICAgIHJldHVybiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiBvYmogIT09IG51bGw7CiAgfQoKICBmdW5jdGlvbiBpc1ZvbGF0aWxlKG9iaiwga2V5TmFtZSwgbWV0YSQkMSkgewogICAgdmFyIGRlc2MgPSBkZXNjcmlwdG9yRm9yUHJvcGVydHkob2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgIHJldHVybiAhKGRlc2MgIT09IHVuZGVmaW5lZCAmJiBkZXNjLl92b2xhdGlsZSA9PT0gZmFsc2UpOwogIH0KCiAgdmFyIENoYWluV2F0Y2hlcnMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDaGFpbldhdGNoZXJzKCkgewogICAgICAvLyBjaGFpbiBub2RlcyB0aGF0IHJlZmVyZW5jZSBhIGtleSBpbiB0aGlzIG9iaiBieSBrZXkKICAgICAgLy8gd2Ugb25seSBjcmVhdGUgQ2hhaW5XYXRjaGVycyB3aGVuIHdlIGFyZSBnb2luZyB0byBhZGQgdGhlbQogICAgICAvLyBzbyBjcmVhdGUgdGhpcyB1cGZyb250CiAgICAgIHRoaXMuY2hhaW5zID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNCA9IENoYWluV2F0Y2hlcnMucHJvdG90eXBlOwoKICAgIF9wcm90bzQuYWRkID0gZnVuY3Rpb24gYWRkKGtleSwgbm9kZSkgewogICAgICB2YXIgbm9kZXMgPSB0aGlzLmNoYWluc1trZXldOwoKICAgICAgaWYgKG5vZGVzID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLmNoYWluc1trZXldID0gW25vZGVdOwogICAgICB9IGVsc2UgewogICAgICAgIG5vZGVzLnB1c2gobm9kZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNC5yZW1vdmUgPSBmdW5jdGlvbiByZW1vdmUoa2V5LCBub2RlKSB7CiAgICAgIHZhciBub2RlcyA9IHRoaXMuY2hhaW5zW2tleV07CgogICAgICBpZiAobm9kZXMgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGlmIChub2Rlc1tpXSA9PT0gbm9kZSkgewogICAgICAgICAgICBub2Rlcy5zcGxpY2UoaSwgMSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG80LmhhcyA9IGZ1bmN0aW9uIGhhcyhrZXksIG5vZGUpIHsKICAgICAgdmFyIG5vZGVzID0gdGhpcy5jaGFpbnNba2V5XTsKCiAgICAgIGlmIChub2RlcyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgaWYgKG5vZGVzW2ldID09PSBub2RlKSB7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfTsKCiAgICBfcHJvdG80LnJldmFsaWRhdGVBbGwgPSBmdW5jdGlvbiByZXZhbGlkYXRlQWxsKCkgewogICAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5jaGFpbnMpIHsKICAgICAgICB0aGlzLm5vdGlmeShrZXksIHRydWUsIHVuZGVmaW5lZCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNC5yZXZhbGlkYXRlID0gZnVuY3Rpb24gcmV2YWxpZGF0ZShrZXkpIHsKICAgICAgdGhpcy5ub3RpZnkoa2V5LCB0cnVlLCB1bmRlZmluZWQpOwogICAgfSAvLyBrZXk6IHRoZSBzdHJpbmcga2V5IHRoYXQgaXMgcGFydCBvZiBhIHBhdGggY2hhbmdlZAogICAgLy8gcmV2YWxpZGF0ZTogYm9vbGVhbjsgdGhlIGNoYWlucyB0aGF0IGFyZSB3YXRjaGluZyB0aGlzIHZhbHVlIHNob3VsZCByZXZhbGlkYXRlCiAgICAvLyBjYWxsYmFjazogZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGNhbGxlZCB3aXRoIHRoZSBvYmplY3QgYW5kIHBhdGggdGhhdAogICAgLy8gICAgICAgICAgIHdpbGwgYmUvYXJlIGludmFsaWRhdGVkIGJ5IHRoaXMga2V5IGNoYW5nZSwgZGVwZW5kaW5nIG9uCiAgICAvLyAgICAgICAgICAgd2hldGhlciB0aGUgcmV2YWxpZGF0ZSBmbGFnIGlzIHBhc3NlZAogICAgOwoKICAgIF9wcm90bzQubm90aWZ5ID0gZnVuY3Rpb24gbm90aWZ5KGtleSwgcmV2YWxpZGF0ZSwgY2FsbGJhY2spIHsKICAgICAgdmFyIG5vZGVzID0gdGhpcy5jaGFpbnNba2V5XTsKCiAgICAgIGlmIChub2RlcyA9PT0gdW5kZWZpbmVkIHx8IG5vZGVzLmxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIGFmZmVjdGVkID0gdW5kZWZpbmVkOwoKICAgICAgaWYgKGNhbGxiYWNrICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBhZmZlY3RlZCA9IFtdOwogICAgICB9CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgbm9kZXNbaV0ubm90aWZ5KHJldmFsaWRhdGUsIGFmZmVjdGVkKTsKICAgICAgfQoKICAgICAgaWYgKGNhbGxiYWNrID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gLy8gd2UgZ2F0aGVyIGNhbGxiYWNrcyBzbyB3ZSBkb24ndCBub3RpZnkgdGhlbSBkdXJpbmcgcmV2YWxpZGF0aW9uCgoKICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGFmZmVjdGVkLmxlbmd0aDsgX2kgKz0gMikgewogICAgICAgIHZhciBvYmogPSBhZmZlY3RlZFtfaV07CiAgICAgICAgdmFyIHBhdGggPSBhZmZlY3RlZFtfaSArIDFdOwogICAgICAgIGNhbGxiYWNrKG9iaiwgcGF0aCk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIENoYWluV2F0Y2hlcnM7CiAgfSgpOwoKICBmdW5jdGlvbiBtYWtlQ2hhaW5XYXRjaGVyKCkgewogICAgcmV0dXJuIG5ldyBDaGFpbldhdGNoZXJzKCk7CiAgfQoKICBmdW5jdGlvbiBtYWtlQ2hhaW5Ob2RlKG9iaikgewogICAgcmV0dXJuIG5ldyBDaGFpbk5vZGUobnVsbCwgbnVsbCwgb2JqKTsKICB9CgogIGZ1bmN0aW9uIGFkZENoYWluV2F0Y2hlcihvYmosIGtleU5hbWUsIG5vZGUpIHsKICAgIHZhciBtID0gKDAsIF9tZXRhMi5tZXRhKShvYmopOwogICAgbS53cml0YWJsZUNoYWluV2F0Y2hlcnMobWFrZUNoYWluV2F0Y2hlcikuYWRkKGtleU5hbWUsIG5vZGUpOwogICAgd2F0Y2hLZXkob2JqLCBrZXlOYW1lLCBtKTsKICB9CgogIGZ1bmN0aW9uIHJlbW92ZUNoYWluV2F0Y2hlcihvYmosIGtleU5hbWUsIG5vZGUsIF9tZXRhKSB7CiAgICBpZiAoIWlzT2JqZWN0KG9iaikpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBtZXRhJCQxID0gX21ldGEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaikgOiBfbWV0YTsKCiAgICBpZiAobWV0YSQkMSA9PT0gbnVsbCB8fCBtZXRhJCQxLmlzU291cmNlRGVzdHJveWluZygpIHx8IG1ldGEkJDEuaXNNZXRhRGVzdHJveWVkKCkgfHwgbWV0YSQkMS5yZWFkYWJsZUNoYWluV2F0Y2hlcnMoKSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybjsKICAgIH0gLy8gbWFrZSBtZXRhIHdyaXRhYmxlCgoKICAgIG1ldGEkJDEgPSAoMCwgX21ldGEyLm1ldGEpKG9iaik7CiAgICBtZXRhJCQxLnJlYWRhYmxlQ2hhaW5XYXRjaGVycygpLnJlbW92ZShrZXlOYW1lLCBub2RlKTsKICAgIHVud2F0Y2hLZXkob2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICB9CgogIHZhciBOT0RFX1NUQUNLID0gW107CgogIGZ1bmN0aW9uIGRlc3Ryb3lSb290KHJvb3QpIHsKICAgIHB1c2hDaGlsZHJlbihyb290KTsKCiAgICB3aGlsZSAoTk9ERV9TVEFDSy5sZW5ndGggPiAwKSB7CiAgICAgIHZhciBub2RlID0gTk9ERV9TVEFDSy5wb3AoKTsKICAgICAgcHVzaENoaWxkcmVuKG5vZGUpOwogICAgICBkZXN0cm95T25lKG5vZGUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZGVzdHJveU9uZShub2RlKSB7CiAgICBpZiAobm9kZS5pc1dhdGNoaW5nKSB7CiAgICAgIHJlbW92ZUNoYWluV2F0Y2hlcihub2RlLm9iamVjdCwgbm9kZS5rZXksIG5vZGUpOwogICAgICBub2RlLmlzV2F0Y2hpbmcgPSBmYWxzZTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHB1c2hDaGlsZHJlbihub2RlKSB7CiAgICB2YXIgbm9kZXMgPSBub2RlLmNoYWluczsKCiAgICBpZiAobm9kZXMgIT09IHVuZGVmaW5lZCkgewogICAgICBmb3IgKHZhciBrZXkgaW4gbm9kZXMpIHsKICAgICAgICBpZiAobm9kZXNba2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBOT0RFX1NUQUNLLnB1c2gobm9kZXNba2V5XSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfSAvLyBBIENoYWluTm9kZSB3YXRjaGVzIGEgc2luZ2xlIGtleSBvbiBhbiBvYmplY3QuIElmIHlvdSBwcm92aWRlIGEgc3RhcnRpbmcKICAvLyB2YWx1ZSBmb3IgdGhlIGtleSB0aGVuIHRoZSBub2RlIHdvbid0IGFjdHVhbGx5IHdhdGNoIGl0LiBGb3IgYSByb290IG5vZGUKICAvLyBwYXNzIG51bGwgZm9yIHBhcmVudCBhbmQga2V5IGFuZCBvYmplY3QgZm9yIHZhbHVlLgoKCiAgdmFyIENoYWluTm9kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENoYWluTm9kZShwYXJlbnQsIGtleSwgdmFsdWUkJDEpIHsKICAgICAgdGhpcy5wYXRocyA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5pc1dhdGNoaW5nID0gZmFsc2U7CiAgICAgIHRoaXMuY2hhaW5zID0gdW5kZWZpbmVkOwogICAgICB0aGlzLm9iamVjdCA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5jb3VudCA9IDA7CiAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50OwogICAgICB0aGlzLmtleSA9IGtleTsKICAgICAgdGhpcy5jb250ZW50ID0gdmFsdWUkJDE7IC8vIEl0IGlzIGZhbHNlIGZvciB0aGUgcm9vdCBvZiBhIGNoYWluIChiZWNhdXNlIHdlIGhhdmUgbm8gcGFyZW50KQoKICAgICAgdmFyIGlzV2F0Y2hpbmcgPSB0aGlzLmlzV2F0Y2hpbmcgPSBwYXJlbnQgIT09IG51bGw7CgogICAgICBpZiAoaXNXYXRjaGluZykgewogICAgICAgIHZhciBwYXJlbnRWYWx1ZSA9IHBhcmVudC52YWx1ZSgpOwoKICAgICAgICBpZiAoaXNPYmplY3QocGFyZW50VmFsdWUpKSB7CiAgICAgICAgICB0aGlzLm9iamVjdCA9IHBhcmVudFZhbHVlOwogICAgICAgICAgYWRkQ2hhaW5XYXRjaGVyKHBhcmVudFZhbHVlLCBrZXksIHRoaXMpOwogICAgICAgIH0KICAgICAgfQogICAgfQoKICAgIHZhciBfcHJvdG81ID0gQ2hhaW5Ob2RlLnByb3RvdHlwZTsKCiAgICBfcHJvdG81LnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIGlmICh0aGlzLmNvbnRlbnQgPT09IHVuZGVmaW5lZCAmJiB0aGlzLmlzV2F0Y2hpbmcpIHsKICAgICAgICB2YXIgb2JqID0gdGhpcy5wYXJlbnQudmFsdWUoKTsKICAgICAgICB0aGlzLmNvbnRlbnQgPSBsYXp5R2V0KG9iaiwgdGhpcy5rZXkpOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5jb250ZW50OwogICAgfTsKCiAgICBfcHJvdG81LmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICAvLyBjaGVjayBpZiByb290CiAgICAgIGlmICh0aGlzLnBhcmVudCA9PT0gbnVsbCkgewogICAgICAgIGRlc3Ryb3lSb290KHRoaXMpOwogICAgICB9IGVsc2UgewogICAgICAgIGRlc3Ryb3lPbmUodGhpcyk7CiAgICAgIH0KICAgIH0gLy8gY29waWVzIGEgdG9wIGxldmVsIG9iamVjdCBvbmx5CiAgICA7CgogICAgX3Byb3RvNS5jb3B5VG8gPSBmdW5jdGlvbiBjb3B5VG8odGFyZ2V0KSB7CiAgICAgIHZhciBwYXRocyA9IHRoaXMucGF0aHM7CgogICAgICBpZiAocGF0aHMgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhciBwYXRoOwoKICAgICAgICBmb3IgKHBhdGggaW4gcGF0aHMpIHsKICAgICAgICAgIGlmIChwYXRoc1twYXRoXSA+IDApIHsKICAgICAgICAgICAgdGFyZ2V0LmFkZChwYXRoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0gLy8gY2FsbGVkIG9uIHRoZSByb290IG5vZGUgb2YgYSBjaGFpbiB0byBzZXR1cCB3YXRjaGVycyBvbiB0aGUgc3BlY2lmaWVkCiAgICAvLyBwYXRoLgogICAgOwoKICAgIF9wcm90bzUuYWRkID0gZnVuY3Rpb24gYWRkKHBhdGgpIHsKICAgICAgdmFyIHBhdGhzID0gdGhpcy5wYXRocyB8fCAodGhpcy5wYXRocyA9IHt9KTsKICAgICAgcGF0aHNbcGF0aF0gPSAocGF0aHNbcGF0aF0gfHwgMCkgKyAxOwogICAgICB2YXIgdGFpbHMgPSBwYXRoLnNwbGl0KCcuJyk7CiAgICAgIHRoaXMuY2hhaW4odGFpbHMuc2hpZnQoKSwgdGFpbHMpOwogICAgfSAvLyBjYWxsZWQgb24gdGhlIHJvb3Qgbm9kZSBvZiBhIGNoYWluIHRvIHRlYXJkb3duIHdhdGNoZXIgb24gdGhlIHNwZWNpZmllZAogICAgLy8gcGF0aAogICAgOwoKICAgIF9wcm90bzUucmVtb3ZlID0gZnVuY3Rpb24gcmVtb3ZlKHBhdGgpIHsKICAgICAgdmFyIHBhdGhzID0gdGhpcy5wYXRoczsKCiAgICAgIGlmIChwYXRocyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAocGF0aHNbcGF0aF0gPiAwKSB7CiAgICAgICAgcGF0aHNbcGF0aF0tLTsKICAgICAgfQoKICAgICAgdmFyIHRhaWxzID0gcGF0aC5zcGxpdCgnLicpOwogICAgICB0aGlzLnVuY2hhaW4odGFpbHMuc2hpZnQoKSwgdGFpbHMpOwogICAgfTsKCiAgICBfcHJvdG81LmNoYWluID0gZnVuY3Rpb24gY2hhaW4oa2V5LCB0YWlscykgewogICAgICB2YXIgY2hhaW5zID0gdGhpcy5jaGFpbnM7CgogICAgICBpZiAoY2hhaW5zID09PSB1bmRlZmluZWQpIHsKICAgICAgICBjaGFpbnMgPSB0aGlzLmNoYWlucyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIH0KCiAgICAgIHZhciBub2RlID0gY2hhaW5zW2tleV07CgogICAgICBpZiAobm9kZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgbm9kZSA9IGNoYWluc1trZXldID0gbmV3IENoYWluTm9kZSh0aGlzLCBrZXksIHVuZGVmaW5lZCk7CiAgICAgIH0KCiAgICAgIG5vZGUuY291bnQrKzsgLy8gY291bnQgY2hhaW5zLi4uCiAgICAgIC8vIGNoYWluIHJlc3Qgb2YgcGF0aCBpZiB0aGVyZSBpcyBvbmUKCiAgICAgIGlmICh0YWlscy5sZW5ndGggPiAwKSB7CiAgICAgICAgbm9kZS5jaGFpbih0YWlscy5zaGlmdCgpLCB0YWlscyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNS51bmNoYWluID0gZnVuY3Rpb24gdW5jaGFpbihrZXksIHRhaWxzKSB7CiAgICAgIHZhciBjaGFpbnMgPSB0aGlzLmNoYWluczsKICAgICAgdmFyIG5vZGUgPSBjaGFpbnNba2V5XTsgLy8gdW5jaGFpbiByZXN0IG9mIHBhdGggZmlyc3QuLi4KCiAgICAgIGlmICh0YWlscy5sZW5ndGggPiAwKSB7CiAgICAgICAgbm9kZS51bmNoYWluKHRhaWxzLnNoaWZ0KCksIHRhaWxzKTsKICAgICAgfSAvLyBkZWxldGUgbm9kZSBpZiBuZWVkZWQuCgoKICAgICAgbm9kZS5jb3VudC0tOwoKICAgICAgaWYgKG5vZGUuY291bnQgPD0gMCkgewogICAgICAgIGNoYWluc1tub2RlLmtleV0gPSB1bmRlZmluZWQ7CiAgICAgICAgbm9kZS5kZXN0cm95KCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNS5ub3RpZnkgPSBmdW5jdGlvbiBub3RpZnkocmV2YWxpZGF0ZSwgYWZmZWN0ZWQpIHsKICAgICAgaWYgKHJldmFsaWRhdGUgJiYgdGhpcy5pc1dhdGNoaW5nKSB7CiAgICAgICAgdmFyIHBhcmVudFZhbHVlID0gdGhpcy5wYXJlbnQudmFsdWUoKTsKCiAgICAgICAgaWYgKHBhcmVudFZhbHVlICE9PSB0aGlzLm9iamVjdCkgewogICAgICAgICAgcmVtb3ZlQ2hhaW5XYXRjaGVyKHRoaXMub2JqZWN0LCB0aGlzLmtleSwgdGhpcyk7CgogICAgICAgICAgaWYgKGlzT2JqZWN0KHBhcmVudFZhbHVlKSkgewogICAgICAgICAgICB0aGlzLm9iamVjdCA9IHBhcmVudFZhbHVlOwogICAgICAgICAgICBhZGRDaGFpbldhdGNoZXIocGFyZW50VmFsdWUsIHRoaXMua2V5LCB0aGlzKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRoaXMub2JqZWN0ID0gdW5kZWZpbmVkOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgdGhpcy5jb250ZW50ID0gdW5kZWZpbmVkOwogICAgICB9IC8vIHRoZW4gbm90aWZ5IGNoYWlucy4uLgoKCiAgICAgIHZhciBjaGFpbnMgPSB0aGlzLmNoYWluczsKCiAgICAgIGlmIChjaGFpbnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhciBub2RlOwoKICAgICAgICBmb3IgKHZhciBrZXkgaW4gY2hhaW5zKSB7CiAgICAgICAgICBub2RlID0gY2hhaW5zW2tleV07CgogICAgICAgICAgaWYgKG5vZGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBub2RlLm5vdGlmeShyZXZhbGlkYXRlLCBhZmZlY3RlZCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoYWZmZWN0ZWQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLnBhcmVudCAhPT0gbnVsbCkgewogICAgICAgIHRoaXMucGFyZW50LnBvcHVsYXRlQWZmZWN0ZWQodGhpcy5rZXksIDEsIGFmZmVjdGVkKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG81LnBvcHVsYXRlQWZmZWN0ZWQgPSBmdW5jdGlvbiBwb3B1bGF0ZUFmZmVjdGVkKHBhdGgsIGRlcHRoLCBhZmZlY3RlZCkgewogICAgICBpZiAodGhpcy5rZXkpIHsKICAgICAgICBwYXRoID0gdGhpcy5rZXkgKyAiLiIgKyBwYXRoOwogICAgICB9CgogICAgICBpZiAodGhpcy5wYXJlbnQgIT09IG51bGwpIHsKICAgICAgICB0aGlzLnBhcmVudC5wb3B1bGF0ZUFmZmVjdGVkKHBhdGgsIGRlcHRoICsgMSwgYWZmZWN0ZWQpOwogICAgICB9IGVsc2UgaWYgKGRlcHRoID4gMSkgewogICAgICAgIGFmZmVjdGVkLnB1c2godGhpcy52YWx1ZSgpLCBwYXRoKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gQ2hhaW5Ob2RlOwogIH0oKTsKCiAgX2V4cG9ydHMuQ2hhaW5Ob2RlID0gQ2hhaW5Ob2RlOwoKICBmdW5jdGlvbiBsYXp5R2V0KG9iaiwga2V5KSB7CiAgICBpZiAoIWlzT2JqZWN0KG9iaikpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkob2JqKTsgLy8gY2hlY2sgaWYgb2JqZWN0IG1lYW50IG9ubHkgdG8gYmUgYSBwcm90b3R5cGUKCiAgICBpZiAobWV0YSQkMSAhPT0gbnVsbCAmJiBtZXRhJCQxLnByb3RvID09PSBvYmopIHsKICAgICAgcmV0dXJuOwogICAgfSAvLyBVc2UgYGdldGAgaWYgdGhlIHJldHVybiB2YWx1ZSBpcyBhbiBFYWNoUHJveHkgb3IgYW4gdW5jYWNoZWFibGUgdmFsdWUuCgoKICAgIGlmIChrZXkgPT09ICdAZWFjaCcpIHsKICAgICAgcmV0dXJuIGVhY2hQcm94eUZvcihvYmopOwogICAgfSBlbHNlIGlmIChpc1ZvbGF0aWxlKG9iaiwga2V5LCBtZXRhJCQxKSkgewogICAgICByZXR1cm4gX2dldDIob2JqLCBrZXkpOyAvLyBPdGhlcndpc2UgYXR0ZW1wdCB0byBnZXQgdGhlIGNhY2hlZCB2YWx1ZSBvZiB0aGUgY29tcHV0ZWQgcHJvcGVydHkKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBnZXRDYWNoZWRWYWx1ZUZvcihvYmosIGtleSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBmaW5pc2hDaGFpbnMobWV0YSQkMSkgewogICAgLy8gZmluaXNoIGFueSBjdXJyZW50IGNoYWlucyBub2RlIHdhdGNoZXJzIHRoYXQgcmVmZXJlbmNlIG9iagogICAgdmFyIGNoYWluV2F0Y2hlcnMgPSBtZXRhJCQxLnJlYWRhYmxlQ2hhaW5XYXRjaGVycygpOwoKICAgIGlmIChjaGFpbldhdGNoZXJzICE9PSB1bmRlZmluZWQpIHsKICAgICAgY2hhaW5XYXRjaGVycy5yZXZhbGlkYXRlQWxsKCk7CiAgICB9IC8vIGVuc3VyZSB0aGF0IGlmIHdlIGhhdmUgaW5oZXJpdGVkIGFueSBjaGFpbnMgdGhleSBoYXZlIGJlZW4KICAgIC8vIGNvcGllZCBvbnRvIG91ciBvd24gbWV0YS4KCgogICAgaWYgKG1ldGEkJDEucmVhZGFibGVDaGFpbnMoKSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIG1ldGEkJDEud3JpdGFibGVDaGFpbnMobWFrZUNoYWluTm9kZSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiB3YXRjaFBhdGgob2JqLCBrZXlQYXRoLCBtZXRhJCQxKSB7CiAgICB2YXIgbSA9IG1ldGEkJDEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIubWV0YSkob2JqKSA6IG1ldGEkJDE7CiAgICB2YXIgY291bnRlciA9IG0ucGVla1dhdGNoaW5nKGtleVBhdGgpOwogICAgbS53cml0ZVdhdGNoaW5nKGtleVBhdGgsIGNvdW50ZXIgKyAxKTsKCiAgICBpZiAoY291bnRlciA9PT0gMCkgewogICAgICAvLyBhY3RpdmF0ZSB3YXRjaGluZyBmaXJzdCB0aW1lCiAgICAgIG0ud3JpdGFibGVDaGFpbnMobWFrZUNoYWluTm9kZSkuYWRkKGtleVBhdGgpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gdW53YXRjaFBhdGgob2JqLCBrZXlQYXRoLCBtZXRhJCQxKSB7CiAgICB2YXIgbSA9IG1ldGEkJDEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaikgOiBtZXRhJCQxOwoKICAgIGlmIChtID09PSBudWxsKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgY291bnRlciA9IG0ucGVla1dhdGNoaW5nKGtleVBhdGgpOwoKICAgIGlmIChjb3VudGVyID4gMCkgewogICAgICBtLndyaXRlV2F0Y2hpbmcoa2V5UGF0aCwgY291bnRlciAtIDEpOwoKICAgICAgaWYgKGNvdW50ZXIgPT09IDEpIHsKICAgICAgICBtLndyaXRhYmxlQ2hhaW5zKG1ha2VDaGFpbk5vZGUpLnJlbW92ZShrZXlQYXRoKTsKICAgICAgfQogICAgfQogIH0KICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBTdGFydHMgd2F0Y2hpbmcgYSBwcm9wZXJ0eSBvbiBhbiBvYmplY3QuIFdoZW5ldmVyIHRoZSBwcm9wZXJ0eSBjaGFuZ2VzLAogICAgaW52b2tlcyBgRW1iZXIubm90aWZ5UHJvcGVydHlDaGFuZ2VgLiBUaGlzIGlzIHRoZSBwcmltaXRpdmUgdXNlZCBieSBvYnNlcnZlcnMKICAgIGFuZCBkZXBlbmRlbnQga2V5czsgdXN1YWxseSB5b3Ugd2lsbCBuZXZlciBjYWxsIHRoaXMgbWV0aG9kIGRpcmVjdGx5IGJ1dCBpbnN0ZWFkCiAgICB1c2UgaGlnaGVyIGxldmVsIG1ldGhvZHMgbGlrZSBgYWRkT2JzZXJ2ZXIoKWAuCiAgCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCB3YXRjaAogICAgQGZvciBFbWJlcgogICAgQHBhcmFtIG9iagogICAgQHBhcmFtIHtTdHJpbmd9IGtleVBhdGgKICAgIEBwYXJhbSB7T2JqZWN0fSBtZXRhCiAgKi8KCgogIGZ1bmN0aW9uIHdhdGNoKG9iaiwga2V5UGF0aCwgbWV0YSQkMSkgewogICAgaWYgKGlzUGF0aChrZXlQYXRoKSkgewogICAgICB3YXRjaFBhdGgob2JqLCBrZXlQYXRoLCBtZXRhJCQxKTsKICAgIH0gZWxzZSB7CiAgICAgIHdhdGNoS2V5KG9iaiwga2V5UGF0aCwgbWV0YSQkMSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBpc1dhdGNoaW5nKG9iaiwga2V5KSB7CiAgICByZXR1cm4gd2F0Y2hlckNvdW50KG9iaiwga2V5KSA+IDA7CiAgfQoKICBmdW5jdGlvbiB3YXRjaGVyQ291bnQob2JqLCBrZXkpIHsKICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkob2JqKTsKICAgIHJldHVybiBtZXRhJCQxICE9PSBudWxsICYmIG1ldGEkJDEucGVla1dhdGNoaW5nKGtleSkgfHwgMDsKICB9CiAgLyoqCiAgICBTdG9wcyB3YXRjaGluZyBhIHByb3BlcnR5IG9uIGFuIG9iamVjdC4gVXN1YWxseSB5b3Ugd2lsbCBuZXZlciBjYWxsIHRoaXMgbWV0aG9kIGRpcmVjdGx5IGJ1dCBpbnN0ZWFkCiAgICB1c2UgaGlnaGVyIGxldmVsIG1ldGhvZHMgbGlrZSBgcmVtb3ZlT2JzZXJ2ZXIoKWAuCiAgCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCB1bndhdGNoCiAgICBAZm9yIEVtYmVyCiAgICBAcGFyYW0gb2JqCiAgICBAcGFyYW0ge1N0cmluZ30ga2V5UGF0aAogICAgQHBhcmFtIHtPYmplY3R9IG1ldGEKICAqLwoKCiAgZnVuY3Rpb24gdW53YXRjaChvYmosIGtleVBhdGgsIG1ldGEkJDEpIHsKICAgIGlmIChpc1BhdGgoa2V5UGF0aCkpIHsKICAgICAgdW53YXRjaFBhdGgob2JqLCBrZXlQYXRoLCBtZXRhJCQxKTsKICAgIH0gZWxzZSB7CiAgICAgIHVud2F0Y2hLZXkob2JqLCBrZXlQYXRoLCBtZXRhJCQxKTsKICAgIH0KICB9CgogIHZhciBTWU5DX0RFRkFVTFQgPSAhX2Vudmlyb25tZW50LkVOVi5fREVGQVVMVF9BU1lOQ19PQlNFUlZFUlM7CiAgdmFyIFNZTkNfT0JTRVJWRVJTID0gbmV3IE1hcCgpOwogIHZhciBBU1lOQ19PQlNFUlZFUlMgPSBuZXcgTWFwKCk7CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KCiAgLyoqCiAgICBAbWV0aG9kIGFkZE9ic2VydmVyCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3Qvb2JzZXJ2ZXJzCiAgICBAcGFyYW0gb2JqCiAgICBAcGFyYW0ge1N0cmluZ30gcGF0aAogICAgQHBhcmFtIHtPYmplY3R8RnVuY3Rpb259IHRhcmdldAogICAgQHBhcmFtIHtGdW5jdGlvbnxTdHJpbmd9IFttZXRob2RdCiAgICBAcHVibGljCiAgKi8KCiAgZnVuY3Rpb24gYWRkT2JzZXJ2ZXIob2JqLCBwYXRoLCB0YXJnZXQsIG1ldGhvZCwgc3luYykgewogICAgaWYgKHN5bmMgPT09IHZvaWQgMCkgewogICAgICBzeW5jID0gU1lOQ19ERUZBVUxUOwogICAgfQoKICAgIHZhciBldmVudE5hbWUgPSBjaGFuZ2VFdmVudChwYXRoKTsKICAgIGFkZExpc3RlbmVyKG9iaiwgZXZlbnROYW1lLCB0YXJnZXQsIG1ldGhvZCwgZmFsc2UsIHN5bmMpOwogICAgewogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaik7CgogICAgICBpZiAobWV0YSQkMSA9PT0gbnVsbCB8fCAhKG1ldGEkJDEuaXNQcm90b3R5cGVNZXRhKG9iaikgfHwgbWV0YSQkMS5pc0luaXRpYWxpemluZygpKSkgewogICAgICAgIGFjdGl2YXRlT2JzZXJ2ZXIob2JqLCBldmVudE5hbWUsIHN5bmMpOwogICAgICB9CiAgICB9CiAgfQogIC8qKgogICAgQG1ldGhvZCByZW1vdmVPYnNlcnZlcgogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L29ic2VydmVycwogICAgQHBhcmFtIG9iagogICAgQHBhcmFtIHtTdHJpbmd9IHBhdGgKICAgIEBwYXJhbSB7T2JqZWN0fEZ1bmN0aW9ufSB0YXJnZXQKICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBbbWV0aG9kXQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiByZW1vdmVPYnNlcnZlcihvYmosIHBhdGgsIHRhcmdldCwgbWV0aG9kLCBzeW5jKSB7CiAgICBpZiAoc3luYyA9PT0gdm9pZCAwKSB7CiAgICAgIHN5bmMgPSBTWU5DX0RFRkFVTFQ7CiAgICB9CgogICAgdmFyIGV2ZW50TmFtZSA9IGNoYW5nZUV2ZW50KHBhdGgpOwogICAgewogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaik7CgogICAgICBpZiAobWV0YSQkMSA9PT0gbnVsbCB8fCAhKG1ldGEkJDEuaXNQcm90b3R5cGVNZXRhKG9iaikgfHwgbWV0YSQkMS5pc0luaXRpYWxpemluZygpKSkgewogICAgICAgIGRlYWN0aXZhdGVPYnNlcnZlcihvYmosIGV2ZW50TmFtZSwgc3luYyk7CiAgICAgIH0KICAgIH0KICAgIHJlbW92ZUxpc3RlbmVyKG9iaiwgZXZlbnROYW1lLCB0YXJnZXQsIG1ldGhvZCk7CiAgfQoKICBmdW5jdGlvbiBnZXRPckNyZWF0ZUFjdGl2ZU9ic2VydmVyc0Zvcih0YXJnZXQsIHN5bmMpIHsKICAgIHZhciBvYnNlcnZlck1hcCA9IHN5bmMgPT09IHRydWUgPyBTWU5DX09CU0VSVkVSUyA6IEFTWU5DX09CU0VSVkVSUzsKCiAgICBpZiAoIW9ic2VydmVyTWFwLmhhcyh0YXJnZXQpKSB7CiAgICAgIG9ic2VydmVyTWFwLnNldCh0YXJnZXQsIG5ldyBNYXAoKSk7CiAgICB9CgogICAgcmV0dXJuIG9ic2VydmVyTWFwLmdldCh0YXJnZXQpOwogIH0KCiAgZnVuY3Rpb24gYWN0aXZhdGVPYnNlcnZlcih0YXJnZXQsIGV2ZW50TmFtZSwgc3luYykgewogICAgaWYgKHN5bmMgPT09IHZvaWQgMCkgewogICAgICBzeW5jID0gZmFsc2U7CiAgICB9CgogICAgdmFyIGFjdGl2ZU9ic2VydmVycyA9IGdldE9yQ3JlYXRlQWN0aXZlT2JzZXJ2ZXJzRm9yKHRhcmdldCwgc3luYyk7CgogICAgaWYgKGFjdGl2ZU9ic2VydmVycy5oYXMoZXZlbnROYW1lKSkgewogICAgICBhY3RpdmVPYnNlcnZlcnMuZ2V0KGV2ZW50TmFtZSkuY291bnQrKzsKICAgIH0gZWxzZSB7CiAgICAgIHZhciBfZXZlbnROYW1lJHNwbGl0ID0gZXZlbnROYW1lLnNwbGl0KCc6JyksCiAgICAgICAgICBwYXRoID0gX2V2ZW50TmFtZSRzcGxpdFswXTsKCiAgICAgIHZhciB0YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShnZXRDaGFpblRhZ3NGb3JLZXkodGFyZ2V0LCBwYXRoKSk7CiAgICAgIGFjdGl2ZU9ic2VydmVycy5zZXQoZXZlbnROYW1lLCB7CiAgICAgICAgY291bnQ6IDEsCiAgICAgICAgcGF0aDogcGF0aCwKICAgICAgICB0YWc6IHRhZywKICAgICAgICBsYXN0UmV2aXNpb246ICgwLCBfcmVmZXJlbmNlLnZhbHVlKSh0YWcpLAogICAgICAgIHN1c3BlbmRlZDogZmFsc2UKICAgICAgfSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBkZWFjdGl2YXRlT2JzZXJ2ZXIodGFyZ2V0LCBldmVudE5hbWUsIHN5bmMpIHsKICAgIGlmIChzeW5jID09PSB2b2lkIDApIHsKICAgICAgc3luYyA9IGZhbHNlOwogICAgfQoKICAgIHZhciBvYnNlcnZlck1hcCA9IHN5bmMgPT09IHRydWUgPyBTWU5DX09CU0VSVkVSUyA6IEFTWU5DX09CU0VSVkVSUzsKICAgIHZhciBhY3RpdmVPYnNlcnZlcnMgPSBvYnNlcnZlck1hcC5nZXQodGFyZ2V0KTsKCiAgICBpZiAoYWN0aXZlT2JzZXJ2ZXJzICE9PSB1bmRlZmluZWQpIHsKICAgICAgdmFyIF9vYnNlcnZlciA9IGFjdGl2ZU9ic2VydmVycy5nZXQoZXZlbnROYW1lKTsKCiAgICAgIF9vYnNlcnZlci5jb3VudC0tOwoKICAgICAgaWYgKF9vYnNlcnZlci5jb3VudCA9PT0gMCkgewogICAgICAgIGFjdGl2ZU9ic2VydmVycy5kZWxldGUoZXZlbnROYW1lKTsKCiAgICAgICAgaWYgKGFjdGl2ZU9ic2VydmVycy5zaXplID09PSAwKSB7CiAgICAgICAgICBvYnNlcnZlck1hcC5kZWxldGUodGFyZ2V0KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgLyoqCiAgICogUHJpbWFyaWx5IHVzZWQgZm9yIGNhc2VzIHdoZXJlIHdlIGFyZSByZWRlZmluaW5nIGEgY2xhc3MsIGUuZy4gbWl4aW5zL3Jlb3BlbgogICAqIGJlaW5nIGFwcGxpZWQgbGF0ZXIuIFJldmFsaWRhdGVzIGFsbCB0aGUgb2JzZXJ2ZXJzLCByZXNldHRpbmcgdGhlaXIgdGFncy4KICAgKgogICAqIEBwcml2YXRlCiAgICogQHBhcmFtIHRhcmdldAogICAqLwoKCiAgZnVuY3Rpb24gcmV2YWxpZGF0ZU9ic2VydmVycyh0YXJnZXQpIHsKICAgIGlmIChBU1lOQ19PQlNFUlZFUlMuaGFzKHRhcmdldCkpIHsKICAgICAgQVNZTkNfT0JTRVJWRVJTLmdldCh0YXJnZXQpLmZvckVhY2goZnVuY3Rpb24gKG9ic2VydmVyKSB7CiAgICAgICAgb2JzZXJ2ZXIudGFnID0gKDAsIF9yZWZlcmVuY2UuY29tYmluZSkoZ2V0Q2hhaW5UYWdzRm9yS2V5KHRhcmdldCwgb2JzZXJ2ZXIucGF0aCkpOwogICAgICAgIG9ic2VydmVyLmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlLnZhbHVlKShvYnNlcnZlci50YWcpOwogICAgICB9KTsKICAgIH0KCiAgICBpZiAoU1lOQ19PQlNFUlZFUlMuaGFzKHRhcmdldCkpIHsKICAgICAgU1lOQ19PQlNFUlZFUlMuZ2V0KHRhcmdldCkuZm9yRWFjaChmdW5jdGlvbiAob2JzZXJ2ZXIpIHsKICAgICAgICBvYnNlcnZlci50YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShnZXRDaGFpblRhZ3NGb3JLZXkodGFyZ2V0LCBvYnNlcnZlci5wYXRoKSk7CiAgICAgICAgb2JzZXJ2ZXIubGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKG9ic2VydmVyLnRhZyk7CiAgICAgIH0pOwogICAgfQogIH0KCiAgdmFyIGxhc3RLbm93blJldmlzaW9uID0gMDsKCiAgZnVuY3Rpb24gZmx1c2hBc3luY09ic2VydmVycyhzaG91bGRTY2hlZHVsZSkgewogICAgaWYgKHNob3VsZFNjaGVkdWxlID09PSB2b2lkIDApIHsKICAgICAgc2hvdWxkU2NoZWR1bGUgPSB0cnVlOwogICAgfQoKICAgIGlmIChsYXN0S25vd25SZXZpc2lvbiA9PT0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKF9yZWZlcmVuY2UuQ1VSUkVOVF9UQUcpKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBsYXN0S25vd25SZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlLnZhbHVlKShfcmVmZXJlbmNlLkNVUlJFTlRfVEFHKTsKICAgIEFTWU5DX09CU0VSVkVSUy5mb3JFYWNoKGZ1bmN0aW9uIChhY3RpdmVPYnNlcnZlcnMsIHRhcmdldCkgewogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKHRhcmdldCk7CgogICAgICBpZiAobWV0YSQkMSAmJiAobWV0YSQkMS5pc1NvdXJjZURlc3Ryb3lpbmcoKSB8fCBtZXRhJCQxLmlzTWV0YURlc3Ryb3llZCgpKSkgewogICAgICAgIEFTWU5DX09CU0VSVkVSUy5kZWxldGUodGFyZ2V0KTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGFjdGl2ZU9ic2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChvYnNlcnZlciwgZXZlbnROYW1lKSB7CiAgICAgICAgaWYgKCEoMCwgX3JlZmVyZW5jZS52YWxpZGF0ZSkob2JzZXJ2ZXIudGFnLCBvYnNlcnZlci5sYXN0UmV2aXNpb24pKSB7CiAgICAgICAgICB2YXIgc2VuZE9ic2VydmVyID0gZnVuY3Rpb24gc2VuZE9ic2VydmVyKCkgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIHNlbmRFdmVudCh0YXJnZXQsIGV2ZW50TmFtZSwgW3RhcmdldCwgb2JzZXJ2ZXIucGF0aF0pOwogICAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICAgIG9ic2VydmVyLnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKGdldENoYWluVGFnc0ZvcktleSh0YXJnZXQsIG9ic2VydmVyLnBhdGgpKTsKICAgICAgICAgICAgICBvYnNlcnZlci5sYXN0UmV2aXNpb24gPSAoMCwgX3JlZmVyZW5jZS52YWx1ZSkob2JzZXJ2ZXIudGFnKTsKICAgICAgICAgICAgfQogICAgICAgICAgfTsKCiAgICAgICAgICBpZiAoc2hvdWxkU2NoZWR1bGUpIHsKICAgICAgICAgICAgKDAsIF9ydW5sb29wLnNjaGVkdWxlKSgnYWN0aW9ucycsIHNlbmRPYnNlcnZlcik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzZW5kT2JzZXJ2ZXIoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgfSk7CiAgfQoKICBmdW5jdGlvbiBmbHVzaFN5bmNPYnNlcnZlcnMoKSB7CiAgICAvLyBXaGVuIGZsdXNoaW5nIHN5bmNocm9ub3VzIG9ic2VydmVycywgd2Uga25vdyB0aGF0IHNvbWV0aGluZyBoYXMgY2hhbmdlZCAod2UKICAgIC8vIG9ubHkgZG8gdGhpcyBkdXJpbmcgYSBub3RpZnlQcm9wZXJ0eUNoYW5nZSksIHNvIHRoZXJlJ3Mgbm8gcmVhc29uIHRvIGNoZWNrCiAgICAvLyBhIGdsb2JhbCByZXZpc2lvbi4KICAgIFNZTkNfT0JTRVJWRVJTLmZvckVhY2goZnVuY3Rpb24gKGFjdGl2ZU9ic2VydmVycywgdGFyZ2V0KSB7CiAgICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkodGFyZ2V0KTsKCiAgICAgIGlmIChtZXRhJCQxICYmIChtZXRhJCQxLmlzU291cmNlRGVzdHJveWluZygpIHx8IG1ldGEkJDEuaXNNZXRhRGVzdHJveWVkKCkpKSB7CiAgICAgICAgU1lOQ19PQlNFUlZFUlMuZGVsZXRlKHRhcmdldCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBhY3RpdmVPYnNlcnZlcnMuZm9yRWFjaChmdW5jdGlvbiAob2JzZXJ2ZXIsIGV2ZW50TmFtZSkgewogICAgICAgIGlmICghb2JzZXJ2ZXIuc3VzcGVuZGVkICYmICEoMCwgX3JlZmVyZW5jZS52YWxpZGF0ZSkob2JzZXJ2ZXIudGFnLCBvYnNlcnZlci5sYXN0UmV2aXNpb24pKSB7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBvYnNlcnZlci5zdXNwZW5kZWQgPSB0cnVlOwogICAgICAgICAgICBzZW5kRXZlbnQodGFyZ2V0LCBldmVudE5hbWUsIFt0YXJnZXQsIG9ic2VydmVyLnBhdGhdKTsKICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIG9ic2VydmVyLnRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKGdldENoYWluVGFnc0ZvcktleSh0YXJnZXQsIG9ic2VydmVyLnBhdGgpKTsKICAgICAgICAgICAgb2JzZXJ2ZXIubGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UudmFsdWUpKG9ic2VydmVyLnRhZyk7CiAgICAgICAgICAgIG9ic2VydmVyLnN1c3BlbmRlZCA9IGZhbHNlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHNldE9ic2VydmVyU3VzcGVuZGVkKHRhcmdldCwgcHJvcGVydHksIHN1c3BlbmRlZCkgewogICAgdmFyIGFjdGl2ZU9ic2VydmVycyA9IFNZTkNfT0JTRVJWRVJTLmdldCh0YXJnZXQpOwoKICAgIGlmICghYWN0aXZlT2JzZXJ2ZXJzKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgb2JzZXJ2ZXIgPSBhY3RpdmVPYnNlcnZlcnMuZ2V0KGNoYW5nZUV2ZW50KHByb3BlcnR5KSk7CgogICAgaWYgKG9ic2VydmVyKSB7CiAgICAgIG9ic2VydmVyLnN1c3BlbmRlZCA9IHN1c3BlbmRlZDsKICAgIH0KICB9CgogIHZhciBydW5JblRyYW5zYWN0aW9uOwogIF9leHBvcnRzLnJ1bkluVHJhbnNhY3Rpb24gPSBydW5JblRyYW5zYWN0aW9uOwogIHZhciBkaWRSZW5kZXI7CiAgX2V4cG9ydHMuZGlkUmVuZGVyID0gZGlkUmVuZGVyOwogIHZhciBhc3NlcnROb3RSZW5kZXJlZDsgLy8gZGV0ZWN0LWJhY2t0cmFja2luZy1yZXJlbmRlciBieSBkZWZhdWx0IGlzIGRlYnVnIGJ1aWxkIG9ubHkKCiAgX2V4cG9ydHMuYXNzZXJ0Tm90UmVuZGVyZWQgPSBhc3NlcnROb3RSZW5kZXJlZDsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIC8vIHRoZXJlIGFyZSAyIHN0YXRlcwogICAgLy8gREVCVUcKICAgIC8vIHRyYWNrcyBsYXN0UmVmIGFuZCBsYXN0UmVuZGVyZWRJbiBwZXIgcmVuZGVyZWQgb2JqZWN0IGFuZCBrZXkgZHVyaW5nIGEgdHJhbnNhY3Rpb24KICAgIC8vIHJlbGVhc2UgZXZlcnl0aGluZyB2aWEgbm9ybWFsIHdlYWttYXAgc2VtYW50aWNzIGJ5IGp1c3QgZGVyZWZlbmNpbmcgdGhlIHdlYWttYXAKICAgIC8vIFJFTEVBU0UKICAgIC8vIHRyYWNrcyB0cmFuc2FjdGlvbklkIHBlciByZW5kZXJlZCBvYmplY3QgYW5kIGtleSBkdXJpbmcgYSB0cmFuc2FjdGlvbgogICAgLy8gcmVsZWFzZSBldmVyeXRoaW5nIHZpYSBub3JtYWwgd2Vha21hcCBzZW1hbnRpY3MgYnkganVzdCBkZXJlZmVuY2luZyB0aGUgd2Vha21hcAogICAgdmFyIFRyYW5zYWN0aW9uUnVubmVyID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uICgpIHsKICAgICAgZnVuY3Rpb24gVHJhbnNhY3Rpb25SdW5uZXIoKSB7CiAgICAgICAgdGhpcy50cmFuc2FjdGlvbklkID0gMDsKICAgICAgICB0aGlzLmluVHJhbnNhY3Rpb24gPSBmYWxzZTsKICAgICAgICB0aGlzLnNob3VsZFJlZmx1c2ggPSBmYWxzZTsKICAgICAgICB0aGlzLndlYWtNYXAgPSBuZXcgV2Vha01hcCgpOwoKICAgICAgICBpZiAoZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICkgewogICAgICAgICAgLy8gdHJhY2sgdGVtcGxhdGVzCiAgICAgICAgICB0aGlzLmRlYnVnU3RhY2sgPSB1bmRlZmluZWQ7CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgX3Byb3RvNiA9IFRyYW5zYWN0aW9uUnVubmVyLnByb3RvdHlwZTsKCiAgICAgIF9wcm90bzYucnVuSW5UcmFuc2FjdGlvbiA9IGZ1bmN0aW9uIHJ1bkluVHJhbnNhY3Rpb24oY29udGV4dCQkMSwgbWV0aG9kTmFtZSkgewogICAgICAgIHRoaXMuYmVmb3JlKGNvbnRleHQkJDEpOwoKICAgICAgICB0cnkgewogICAgICAgICAgY29udGV4dCQkMVttZXRob2ROYW1lXSgpOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICB0aGlzLmFmdGVyKCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5zaG91bGRSZWZsdXNoOwogICAgICB9OwoKICAgICAgX3Byb3RvNi5kaWRSZW5kZXIgPSBmdW5jdGlvbiBkaWRSZW5kZXIob2JqZWN0LCBrZXksIHJlZmVyZW5jZSkgewogICAgICAgIGlmICghdGhpcy5pblRyYW5zYWN0aW9uKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAoZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICkgewogICAgICAgICAgdGhpcy5zZXRLZXkob2JqZWN0LCBrZXksIHsKICAgICAgICAgICAgbGFzdFJlZjogcmVmZXJlbmNlLAogICAgICAgICAgICBsYXN0UmVuZGVyZWRJbjogdGhpcy5kZWJ1Z1N0YWNrLnBlZWsoKQogICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuc2V0S2V5KG9iamVjdCwga2V5LCB0aGlzLnRyYW5zYWN0aW9uSWQpOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIF9wcm90bzYuYXNzZXJ0Tm90UmVuZGVyZWQgPSBmdW5jdGlvbiBhc3NlcnROb3RSZW5kZXJlZChvYmplY3QsIGtleSkgewogICAgICAgIGlmICghdGhpcy5pblRyYW5zYWN0aW9uKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAodGhpcy5oYXNSZW5kZXJlZChvYmplY3QsIGtleSkpIHsKICAgICAgICAgIGlmIChmYWxzZQogICAgICAgICAgLyogREVCVUcgKi8KICAgICAgICAgICkgewogICAgICAgICAgICB2YXIgX3RoaXMkZ2V0S2V5ID0gdGhpcy5nZXRLZXkob2JqZWN0LCBrZXkpLAogICAgICAgICAgICAgICAgbGFzdFJlZiA9IF90aGlzJGdldEtleS5sYXN0UmVmLAogICAgICAgICAgICAgICAgbGFzdFJlbmRlcmVkSW4gPSBfdGhpcyRnZXRLZXkubGFzdFJlbmRlcmVkSW47CgogICAgICAgICAgICB2YXIgY3VycmVudGx5SW4gPSB0aGlzLmRlYnVnU3RhY2sucGVlaygpOwogICAgICAgICAgICB2YXIgcGFydHMgPSBbXTsKICAgICAgICAgICAgdmFyIGxhYmVsOwoKICAgICAgICAgICAgaWYgKGxhc3RSZWYgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIHdoaWxlIChsYXN0UmVmICYmIGxhc3RSZWYucHJvcGVydHlLZXkpIHsKICAgICAgICAgICAgICAgIHBhcnRzLnVuc2hpZnQobGFzdFJlZi5wcm9wZXJ0eUtleSk7CiAgICAgICAgICAgICAgICBsYXN0UmVmID0gbGFzdFJlZi5wYXJlbnRSZWZlcmVuY2U7CiAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICBsYWJlbCA9IHBhcnRzLmpvaW4oJy4nKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBsYWJlbCA9ICd0aGUgc2FtZSB2YWx1ZSc7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBtb2RpZmllZCBcIiIgKyBsYWJlbCArICJcIiB0d2ljZSBvbiAiICsgb2JqZWN0ICsgIiBpbiBhIHNpbmdsZSByZW5kZXIuIEl0IHdhcyByZW5kZXJlZCBpbiAiICsgbGFzdFJlbmRlcmVkSW4gKyAiIGFuZCBtb2RpZmllZCBpbiAiICsgY3VycmVudGx5SW4gKyAiLiBUaGlzIHdhcyB1bnJlbGlhYmxlIGFuZCBzbG93IGluIEVtYmVyIDEueCBhbmQgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZC4gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lbWJlcmpzL2VtYmVyLmpzL2lzc3Vlcy8xMzk0OCBmb3IgbW9yZSBkZXRhaWxzLiIsIGZhbHNlKSk7CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5zaG91bGRSZWZsdXNoID0gdHJ1ZTsKICAgICAgICB9CiAgICAgIH07CgogICAgICBfcHJvdG82Lmhhc1JlbmRlcmVkID0gZnVuY3Rpb24gaGFzUmVuZGVyZWQob2JqZWN0LCBrZXkpIHsKICAgICAgICBpZiAoIXRoaXMuaW5UcmFuc2FjdGlvbikgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgIHJldHVybiB0aGlzLmdldEtleShvYmplY3QsIGtleSkgIT09IHVuZGVmaW5lZDsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLmdldEtleShvYmplY3QsIGtleSkgPT09IHRoaXMudHJhbnNhY3Rpb25JZDsKICAgICAgfTsKCiAgICAgIF9wcm90bzYuYmVmb3JlID0gZnVuY3Rpb24gYmVmb3JlKGNvbnRleHQkJDEpIHsKICAgICAgICB0aGlzLmluVHJhbnNhY3Rpb24gPSB0cnVlOwogICAgICAgIHRoaXMuc2hvdWxkUmVmbHVzaCA9IGZhbHNlOwoKICAgICAgICBpZiAoZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICkgewogICAgICAgICAgdGhpcy5kZWJ1Z1N0YWNrID0gY29udGV4dCQkMS5lbnYuZGVidWdTdGFjazsKICAgICAgICB9CiAgICAgIH07CgogICAgICBfcHJvdG82LmFmdGVyID0gZnVuY3Rpb24gYWZ0ZXIoKSB7CiAgICAgICAgdGhpcy50cmFuc2FjdGlvbklkKys7CiAgICAgICAgdGhpcy5pblRyYW5zYWN0aW9uID0gZmFsc2U7CgogICAgICAgIGlmIChmYWxzZQogICAgICAgIC8qIERFQlVHICovCiAgICAgICAgKSB7CiAgICAgICAgICB0aGlzLmRlYnVnU3RhY2sgPSB1bmRlZmluZWQ7CiAgICAgICAgfQoKICAgICAgICB0aGlzLmNsZWFyT2JqZWN0TWFwKCk7CiAgICAgIH07CgogICAgICBfcHJvdG82LmNyZWF0ZU1hcCA9IGZ1bmN0aW9uIGNyZWF0ZU1hcChvYmplY3QpIHsKICAgICAgICB2YXIgbWFwID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICB0aGlzLndlYWtNYXAuc2V0KG9iamVjdCwgbWFwKTsKICAgICAgICByZXR1cm4gbWFwOwogICAgICB9OwoKICAgICAgX3Byb3RvNi5nZXRPckNyZWF0ZU1hcCA9IGZ1bmN0aW9uIGdldE9yQ3JlYXRlTWFwKG9iamVjdCkgewogICAgICAgIHZhciBtYXAgPSB0aGlzLndlYWtNYXAuZ2V0KG9iamVjdCk7CgogICAgICAgIGlmIChtYXAgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgbWFwID0gdGhpcy5jcmVhdGVNYXAob2JqZWN0KTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBtYXA7CiAgICAgIH07CgogICAgICBfcHJvdG82LnNldEtleSA9IGZ1bmN0aW9uIHNldEtleShvYmplY3QsIGtleSwgdmFsdWUkJDEpIHsKICAgICAgICB2YXIgbWFwID0gdGhpcy5nZXRPckNyZWF0ZU1hcChvYmplY3QpOwogICAgICAgIG1hcFtrZXldID0gdmFsdWUkJDE7CiAgICAgIH07CgogICAgICBfcHJvdG82LmdldEtleSA9IGZ1bmN0aW9uIGdldEtleShvYmplY3QsIGtleSkgewogICAgICAgIHZhciBtYXAgPSB0aGlzLndlYWtNYXAuZ2V0KG9iamVjdCk7CgogICAgICAgIGlmIChtYXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcmV0dXJuIG1hcFtrZXldOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIF9wcm90bzYuY2xlYXJPYmplY3RNYXAgPSBmdW5jdGlvbiBjbGVhck9iamVjdE1hcCgpIHsKICAgICAgICB0aGlzLndlYWtNYXAgPSBuZXcgV2Vha01hcCgpOwogICAgICB9OwoKICAgICAgcmV0dXJuIFRyYW5zYWN0aW9uUnVubmVyOwogICAgfSgpOwoKICAgIHZhciBydW5uZXIgPSBuZXcgVHJhbnNhY3Rpb25SdW5uZXIoKTsKCiAgICBfZXhwb3J0cy5ydW5JblRyYW5zYWN0aW9uID0gcnVuSW5UcmFuc2FjdGlvbiA9IGZ1bmN0aW9uIHJ1bkluVHJhbnNhY3Rpb24oKSB7CiAgICAgIHJldHVybiBydW5uZXIucnVuSW5UcmFuc2FjdGlvbi5hcHBseShydW5uZXIsIGFyZ3VtZW50cyk7CiAgICB9OwoKICAgIF9leHBvcnRzLmRpZFJlbmRlciA9IGRpZFJlbmRlciA9IGZ1bmN0aW9uIGRpZFJlbmRlcigpIHsKICAgICAgcmV0dXJuIHJ1bm5lci5kaWRSZW5kZXIuYXBwbHkocnVubmVyLCBhcmd1bWVudHMpOwogICAgfTsKCiAgICBfZXhwb3J0cy5hc3NlcnROb3RSZW5kZXJlZCA9IGFzc2VydE5vdFJlbmRlcmVkID0gZnVuY3Rpb24gYXNzZXJ0Tm90UmVuZGVyZWQoKSB7CiAgICAgIHJldHVybiBydW5uZXIuYXNzZXJ0Tm90UmVuZGVyZWQuYXBwbHkocnVubmVyLCBhcmd1bWVudHMpOwogICAgfTsKICB9IGVsc2UgewogICAgLy8gaW4gcHJvZHVjdGlvbiBkbyBub3RoaW5nIHRvIGRldGVjdCByZWZsdXNoZXMKICAgIF9leHBvcnRzLnJ1bkluVHJhbnNhY3Rpb24gPSBydW5JblRyYW5zYWN0aW9uID0gZnVuY3Rpb24gcnVuSW5UcmFuc2FjdGlvbihjb250ZXh0JCQxLCBtZXRob2ROYW1lKSB7CiAgICAgIGNvbnRleHQkJDFbbWV0aG9kTmFtZV0oKTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfTsKICB9CiAgLyoqCiAgIEBtb2R1bGUgZW1iZXIKICAgQHByaXZhdGUKICAgKi8KCgogIHZhciBQUk9QRVJUWV9ESURfQ0hBTkdFID0gKDAsIF91dGlscy5zeW1ib2wpKCdQUk9QRVJUWV9ESURfQ0hBTkdFJyk7CiAgX2V4cG9ydHMuUFJPUEVSVFlfRElEX0NIQU5HRSA9IFBST1BFUlRZX0RJRF9DSEFOR0U7CiAgdmFyIGRlZmVycmVkID0gMDsKICAvKioKICAgIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGp1c3QgYWZ0ZXIgYW4gb2JqZWN0IHByb3BlcnR5IGhhcyBjaGFuZ2VkLgogICAgSXQgd2lsbCBub3RpZnkgYW55IG9ic2VydmVycyBhbmQgY2xlYXIgY2FjaGVzIGFtb25nIG90aGVyIHRoaW5ncy4KICAKICAgIE5vcm1hbGx5IHlvdSB3aWxsIG5vdCBuZWVkIHRvIGNhbGwgdGhpcyBtZXRob2QgZGlyZWN0bHkgYnV0IGlmIGZvciBzb21lCiAgICByZWFzb24geW91IGNhbid0IGRpcmVjdGx5IHdhdGNoIGEgcHJvcGVydHkgeW91IGNhbiBpbnZva2UgdGhpcyBtZXRob2QKICAgIG1hbnVhbGx5LgogIAogICAgQG1ldGhvZCBub3RpZnlQcm9wZXJ0eUNoYW5nZQogICAgQGZvciBAZW1iZXIvb2JqZWN0CiAgICBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3Qgd2l0aCB0aGUgcHJvcGVydHkgdGhhdCB3aWxsIGNoYW5nZQogICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIHByb3BlcnR5IGtleSAob3IgcGF0aCkgdGhhdCB3aWxsIGNoYW5nZS4KICAgIEBwYXJhbSB7TWV0YX0gbWV0YSBUaGUgb2JqZWN0cyBtZXRhLgogICAgQHJldHVybiB7dm9pZH0KICAgIEBzaW5jZSAzLjEuMAogICAgQHB1YmxpYwogICovCgogIGZ1bmN0aW9uIG5vdGlmeVByb3BlcnR5Q2hhbmdlKG9iaiwga2V5TmFtZSwgX21ldGEpIHsKICAgIHZhciBtZXRhJCQxID0gX21ldGEgPT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaikgOiBfbWV0YTsKCiAgICBpZiAobWV0YSQkMSAhPT0gbnVsbCAmJiAobWV0YSQkMS5pc0luaXRpYWxpemluZygpIHx8IG1ldGEkJDEuaXNQcm90b3R5cGVNZXRhKG9iaikpKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAobWV0YSQkMSAhPT0gbnVsbCkgewogICAgICBtYXJrT2JqZWN0QXNEaXJ0eShvYmosIGtleU5hbWUsIG1ldGEkJDEpOwogICAgfQoKICAgIGlmICh0cnVlCiAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICYmIGRlZmVycmVkIDw9IDApIHsKICAgICAgZmx1c2hTeW5jT2JzZXJ2ZXJzKCk7CiAgICB9CgogICAgaWYgKFBST1BFUlRZX0RJRF9DSEFOR0UgaW4gb2JqKSB7CiAgICAgIG9ialtQUk9QRVJUWV9ESURfQ0hBTkdFXShrZXlOYW1lKTsKICAgIH0KCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgYXNzZXJ0Tm90UmVuZGVyZWQob2JqLCBrZXlOYW1lKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIG92ZXJyaWRlQ2hhaW5zKF9vYmosIGtleU5hbWUsIG1ldGEkJDEpIHsKICAgIHZhciBjaGFpbldhdGNoZXJzID0gbWV0YSQkMS5yZWFkYWJsZUNoYWluV2F0Y2hlcnMoKTsKCiAgICBpZiAoY2hhaW5XYXRjaGVycyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGNoYWluV2F0Y2hlcnMucmV2YWxpZGF0ZShrZXlOYW1lKTsKICAgIH0KICB9CiAgLyoqCiAgICBAbWV0aG9kIGJlZ2luUHJvcGVydHlDaGFuZ2VzCiAgICBAY2hhaW5hYmxlCiAgICBAcHJpdmF0ZQogICovCgoKICBmdW5jdGlvbiBiZWdpblByb3BlcnR5Q2hhbmdlcygpIHsKICAgIGRlZmVycmVkKys7CiAgfQogIC8qKgogICAgQG1ldGhvZCBlbmRQcm9wZXJ0eUNoYW5nZXMKICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIGVuZFByb3BlcnR5Q2hhbmdlcygpIHsKICAgIGRlZmVycmVkLS07CgogICAgaWYgKGRlZmVycmVkIDw9IDApIHsKICAgICAgewogICAgICAgIGZsdXNoU3luY09ic2VydmVycygpOwogICAgICB9CiAgICB9CiAgfQogIC8qKgogICAgTWFrZSBhIHNlcmllcyBvZiBwcm9wZXJ0eSBjaGFuZ2VzIHRvZ2V0aGVyIGluIGFuCiAgICBleGNlcHRpb24tc2FmZSB3YXkuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBFbWJlci5jaGFuZ2VQcm9wZXJ0aWVzKGZ1bmN0aW9uKCkgewogICAgICBvYmoxLnNldCgnZm9vJywgbWF5Qmxvd1VwV2hlblNldCk7CiAgICAgIG9iajIuc2V0KCdiYXInLCBiYXopOwogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgY2hhbmdlUHJvcGVydGllcwogICAgQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sKICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIGNoYW5nZVByb3BlcnRpZXMoY2FsbGJhY2spIHsKICAgIGJlZ2luUHJvcGVydHlDaGFuZ2VzKCk7CgogICAgdHJ5IHsKICAgICAgY2FsbGJhY2soKTsKICAgIH0gZmluYWxseSB7CiAgICAgIGVuZFByb3BlcnR5Q2hhbmdlcygpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gYXJyYXlDb250ZW50V2lsbENoYW5nZShhcnJheSwgc3RhcnRJZHgsIHJlbW92ZUFtdCwgYWRkQW10KSB7CiAgICAvLyBpZiBubyBhcmdzIGFyZSBwYXNzZWQgYXNzdW1lIGV2ZXJ5dGhpbmcgY2hhbmdlcwogICAgaWYgKHN0YXJ0SWR4ID09PSB1bmRlZmluZWQpIHsKICAgICAgc3RhcnRJZHggPSAwOwogICAgICByZW1vdmVBbXQgPSBhZGRBbXQgPSAtMTsKICAgIH0gZWxzZSB7CiAgICAgIGlmIChyZW1vdmVBbXQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJlbW92ZUFtdCA9IC0xOwogICAgICB9CgogICAgICBpZiAoYWRkQW10ID09PSB1bmRlZmluZWQpIHsKICAgICAgICBhZGRBbXQgPSAtMTsKICAgICAgfQogICAgfQoKICAgIHNlbmRFdmVudChhcnJheSwgJ0BhcnJheTpiZWZvcmUnLCBbYXJyYXksIHN0YXJ0SWR4LCByZW1vdmVBbXQsIGFkZEFtdF0pOwogICAgcmV0dXJuIGFycmF5OwogIH0KCiAgZnVuY3Rpb24gYXJyYXlDb250ZW50RGlkQ2hhbmdlKGFycmF5LCBzdGFydElkeCwgcmVtb3ZlQW10LCBhZGRBbXQpIHsKICAgIC8vIGlmIG5vIGFyZ3MgYXJlIHBhc3NlZCBhc3N1bWUgZXZlcnl0aGluZyBjaGFuZ2VzCiAgICBpZiAoc3RhcnRJZHggPT09IHVuZGVmaW5lZCkgewogICAgICBzdGFydElkeCA9IDA7CiAgICAgIHJlbW92ZUFtdCA9IGFkZEFtdCA9IC0xOwogICAgfSBlbHNlIHsKICAgICAgaWYgKHJlbW92ZUFtdCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmVtb3ZlQW10ID0gLTE7CiAgICAgIH0KCiAgICAgIGlmIChhZGRBbXQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGFkZEFtdCA9IC0xOwogICAgICB9CiAgICB9CgogICAgdmFyIG1ldGEkJDEgPSAoMCwgX21ldGEyLnBlZWtNZXRhKShhcnJheSk7CgogICAgaWYgKGFkZEFtdCA8IDAgfHwgcmVtb3ZlQW10IDwgMCB8fCBhZGRBbXQgLSByZW1vdmVBbXQgIT09IDApIHsKICAgICAgbm90aWZ5UHJvcGVydHlDaGFuZ2UoYXJyYXksICdsZW5ndGgnLCBtZXRhJCQxKTsKICAgIH0KCiAgICBub3RpZnlQcm9wZXJ0eUNoYW5nZShhcnJheSwgJ1tdJywgbWV0YSQkMSk7CiAgICBzZW5kRXZlbnQoYXJyYXksICdAYXJyYXk6Y2hhbmdlJywgW2FycmF5LCBzdGFydElkeCwgcmVtb3ZlQW10LCBhZGRBbXRdKTsKICAgIHZhciBjYWNoZSA9IHBlZWtDYWNoZUZvcihhcnJheSk7CgogICAgaWYgKGNhY2hlICE9PSB1bmRlZmluZWQpIHsKICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDsKICAgICAgdmFyIGFkZGVkQW1vdW50ID0gYWRkQW10ID09PSAtMSA/IDAgOiBhZGRBbXQ7CiAgICAgIHZhciByZW1vdmVkQW1vdW50ID0gcmVtb3ZlQW10ID09PSAtMSA/IDAgOiByZW1vdmVBbXQ7CiAgICAgIHZhciBkZWx0YSA9IGFkZGVkQW1vdW50IC0gcmVtb3ZlZEFtb3VudDsKICAgICAgdmFyIHByZXZpb3VzTGVuZ3RoID0gbGVuZ3RoIC0gZGVsdGE7CiAgICAgIHZhciBub3JtYWxTdGFydElkeCA9IHN0YXJ0SWR4IDwgMCA/IHByZXZpb3VzTGVuZ3RoICsgc3RhcnRJZHggOiBzdGFydElkeDsKCiAgICAgIGlmIChjYWNoZS5oYXMoJ2ZpcnN0T2JqZWN0JykgJiYgbm9ybWFsU3RhcnRJZHggPT09IDApIHsKICAgICAgICBub3RpZnlQcm9wZXJ0eUNoYW5nZShhcnJheSwgJ2ZpcnN0T2JqZWN0JywgbWV0YSQkMSk7CiAgICAgIH0KCiAgICAgIGlmIChjYWNoZS5oYXMoJ2xhc3RPYmplY3QnKSkgewogICAgICAgIHZhciBwcmV2aW91c0xhc3RJbmRleCA9IHByZXZpb3VzTGVuZ3RoIC0gMTsKICAgICAgICB2YXIgbGFzdEFmZmVjdGVkSW5kZXggPSBub3JtYWxTdGFydElkeCArIHJlbW92ZWRBbW91bnQ7CgogICAgICAgIGlmIChwcmV2aW91c0xhc3RJbmRleCA8IGxhc3RBZmZlY3RlZEluZGV4KSB7CiAgICAgICAgICBub3RpZnlQcm9wZXJ0eUNoYW5nZShhcnJheSwgJ2xhc3RPYmplY3QnLCBtZXRhJCQxKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gYXJyYXk7CiAgfQoKICB2YXIgRU1QVFlfQVJSQVkgPSBPYmplY3QuZnJlZXplKFtdKTsKCiAgZnVuY3Rpb24gb2JqZWN0QXQoYXJyYXksIGluZGV4KSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheShhcnJheSkpIHsKICAgICAgcmV0dXJuIGFycmF5W2luZGV4XTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBhcnJheS5vYmplY3RBdChpbmRleCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiByZXBsYWNlKGFycmF5LCBzdGFydCwgZGVsZXRlQ291bnQsIGl0ZW1zKSB7CiAgICBpZiAoaXRlbXMgPT09IHZvaWQgMCkgewogICAgICBpdGVtcyA9IEVNUFRZX0FSUkFZOwogICAgfQoKICAgIGlmIChBcnJheS5pc0FycmF5KGFycmF5KSkgewogICAgICByZXBsYWNlSW5OYXRpdmVBcnJheShhcnJheSwgc3RhcnQsIGRlbGV0ZUNvdW50LCBpdGVtcyk7CiAgICB9IGVsc2UgewogICAgICBhcnJheS5yZXBsYWNlKHN0YXJ0LCBkZWxldGVDb3VudCwgaXRlbXMpOwogICAgfQogIH0KCiAgdmFyIENIVU5LX1NJWkUgPSA2MDAwMDsgLy8gVG8gYXZvaWQgb3ZlcmZsb3dpbmcgdGhlIHN0YWNrLCB3ZSBzcGxpY2UgdXAgdG8gQ0hVTktfU0laRSBpdGVtcyBhdCBhIHRpbWUuCiAgLy8gU2VlIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD01NjU4OCBmb3IgbW9yZSBkZXRhaWxzLgoKICBmdW5jdGlvbiByZXBsYWNlSW5OYXRpdmVBcnJheShhcnJheSwgc3RhcnQsIGRlbGV0ZUNvdW50LCBpdGVtcykgewogICAgYXJyYXlDb250ZW50V2lsbENoYW5nZShhcnJheSwgc3RhcnQsIGRlbGV0ZUNvdW50LCBpdGVtcy5sZW5ndGgpOwoKICAgIGlmIChpdGVtcy5sZW5ndGggPD0gQ0hVTktfU0laRSkgewogICAgICBhcnJheS5zcGxpY2UuYXBwbHkoYXJyYXksIFtzdGFydCwgZGVsZXRlQ291bnRdLmNvbmNhdChpdGVtcykpOwogICAgfSBlbHNlIHsKICAgICAgYXJyYXkuc3BsaWNlKHN0YXJ0LCBkZWxldGVDb3VudCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgaSArPSBDSFVOS19TSVpFKSB7CiAgICAgICAgdmFyIGNodW5rID0gaXRlbXMuc2xpY2UoaSwgaSArIENIVU5LX1NJWkUpOwogICAgICAgIGFycmF5LnNwbGljZS5hcHBseShhcnJheSwgW3N0YXJ0ICsgaSwgMF0uY29uY2F0KGNodW5rKSk7CiAgICAgIH0KICAgIH0KCiAgICBhcnJheUNvbnRlbnREaWRDaGFuZ2UoYXJyYXksIHN0YXJ0LCBkZWxldGVDb3VudCwgaXRlbXMubGVuZ3RoKTsKICB9CgogIGZ1bmN0aW9uIGFycmF5T2JzZXJ2ZXJzSGVscGVyKG9iaiwgdGFyZ2V0LCBvcHRzLCBvcGVyYXRpb24sIG5vdGlmeSkgewogICAgdmFyIHdpbGxDaGFuZ2UgPSBvcHRzICYmIG9wdHMud2lsbENoYW5nZSB8fCAnYXJyYXlXaWxsQ2hhbmdlJzsKICAgIHZhciBkaWRDaGFuZ2UgPSBvcHRzICYmIG9wdHMuZGlkQ2hhbmdlIHx8ICdhcnJheURpZENoYW5nZSc7CgogICAgdmFyIGhhc09ic2VydmVycyA9IF9nZXQyKG9iaiwgJ2hhc0FycmF5T2JzZXJ2ZXJzJyk7CgogICAgb3BlcmF0aW9uKG9iaiwgJ0BhcnJheTpiZWZvcmUnLCB0YXJnZXQsIHdpbGxDaGFuZ2UpOwogICAgb3BlcmF0aW9uKG9iaiwgJ0BhcnJheTpjaGFuZ2UnLCB0YXJnZXQsIGRpZENoYW5nZSk7CgogICAgaWYgKGhhc09ic2VydmVycyA9PT0gbm90aWZ5KSB7CiAgICAgIG5vdGlmeVByb3BlcnR5Q2hhbmdlKG9iaiwgJ2hhc0FycmF5T2JzZXJ2ZXJzJyk7CiAgICB9CgogICAgcmV0dXJuIG9iajsKICB9CgogIGZ1bmN0aW9uIGFkZEFycmF5T2JzZXJ2ZXIoYXJyYXksIHRhcmdldCwgb3B0cykgewogICAgcmV0dXJuIGFycmF5T2JzZXJ2ZXJzSGVscGVyKGFycmF5LCB0YXJnZXQsIG9wdHMsIGFkZExpc3RlbmVyLCBmYWxzZSk7CiAgfQoKICBmdW5jdGlvbiByZW1vdmVBcnJheU9ic2VydmVyKGFycmF5LCB0YXJnZXQsIG9wdHMpIHsKICAgIHJldHVybiBhcnJheU9ic2VydmVyc0hlbHBlcihhcnJheSwgdGFyZ2V0LCBvcHRzLCByZW1vdmVMaXN0ZW5lciwgdHJ1ZSk7CiAgfQoKICB2YXIgQVJHU19QUk9YWV9UQUdTID0gbmV3IFdlYWtNYXAoKTsKICBfZXhwb3J0cy5BUkdTX1BST1hZX1RBR1MgPSBBUkdTX1BST1hZX1RBR1M7CgogIGZ1bmN0aW9uIGZpbmlzaExhenlDaGFpbnMob2JqLCBrZXksIHZhbHVlJCQxKSB7CiAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaik7CiAgICB2YXIgbGF6eVRhZ3MgPSBtZXRhJCQxICE9PSBudWxsID8gbWV0YSQkMS5yZWFkYWJsZUxhenlDaGFpbnNGb3Ioa2V5KSA6IHVuZGVmaW5lZDsKCiAgICBpZiAobGF6eVRhZ3MgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKHZhbHVlJCQxID09PSBudWxsIHx8IHR5cGVvZiB2YWx1ZSQkMSAhPT0gJ29iamVjdCcgJiYgdHlwZW9mIHZhbHVlJCQxICE9PSAnZnVuY3Rpb24nKSB7CiAgICAgIGZvciAodmFyIHBhdGggaW4gbGF6eVRhZ3MpIHsKICAgICAgICBkZWxldGUgbGF6eVRhZ3NbcGF0aF07CiAgICAgIH0KCiAgICAgIHJldHVybjsKICAgIH0KCiAgICBmb3IgKHZhciBfcGF0aCBpbiBsYXp5VGFncykgewogICAgICB2YXIgdGFnID0gbGF6eVRhZ3NbX3BhdGhdOwogICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHRhZywgKDAsIF9yZWZlcmVuY2UuY29tYmluZSkoZ2V0Q2hhaW5UYWdzRm9yS2V5KHZhbHVlJCQxLCBfcGF0aCkpKTsKICAgICAgZGVsZXRlIGxhenlUYWdzW19wYXRoXTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGdldENoYWluVGFnc0ZvcktleXMob2JqLCBrZXlzKSB7CiAgICB2YXIgY2hhaW5UYWdzID0gW107CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgIGNoYWluVGFncy5wdXNoLmFwcGx5KGNoYWluVGFncywgZ2V0Q2hhaW5UYWdzRm9yS2V5KG9iaiwga2V5c1tpXSkpOwogICAgfQoKICAgIHJldHVybiBjaGFpblRhZ3M7CiAgfQoKICBmdW5jdGlvbiBnZXRDaGFpblRhZ3NGb3JLZXkob2JqLCBwYXRoKSB7CiAgICB2YXIgY2hhaW5UYWdzID0gW107CiAgICB2YXIgY3VycmVudCA9IG9iajsKICAgIHZhciBwYXRoTGVuZ3RoID0gcGF0aC5sZW5ndGg7CiAgICB2YXIgc2VnbWVudEVuZCA9IC0xOyAvLyBwcmV2ZW50IGNsb3N1cmVzCgogICAgdmFyIHNlZ21lbnQsIGRlc2NyaXB0b3I7IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zdGFudC1jb25kaXRpb24KCiAgICB3aGlsZSAodHJ1ZSkgewogICAgICB2YXIgY3VycmVudFR5cGUgPSB0eXBlb2YgY3VycmVudDsKCiAgICAgIGlmIChjdXJyZW50ID09PSBudWxsIHx8IGN1cnJlbnRUeXBlICE9PSAnb2JqZWN0JyAmJiBjdXJyZW50VHlwZSAhPT0gJ2Z1bmN0aW9uJykgewogICAgICAgIC8vIHdlJ3ZlIGhpdCB0aGUgZW5kIG9mIHRoZSBjaGFpbiBmb3Igbm93LCBicmVhayBvdXQKICAgICAgICBicmVhazsKICAgICAgfQoKICAgICAgdmFyIGxhc3RTZWdtZW50RW5kID0gc2VnbWVudEVuZCArIDE7CiAgICAgIHNlZ21lbnRFbmQgPSBwYXRoLmluZGV4T2YoJy4nLCBsYXN0U2VnbWVudEVuZCk7CgogICAgICBpZiAoc2VnbWVudEVuZCA9PT0gLTEpIHsKICAgICAgICBzZWdtZW50RW5kID0gcGF0aExlbmd0aDsKICAgICAgfQoKICAgICAgc2VnbWVudCA9IHBhdGguc2xpY2UobGFzdFNlZ21lbnRFbmQsIHNlZ21lbnRFbmQpOyAvLyBJZiB0aGUgc2VnbWVudCBpcyBhbiBAZWFjaCwgd2UgY2FuIHByb2Nlc3MgaXQgYW5kIHRoZW4gYnJlYWsKCiAgICAgIGlmIChzZWdtZW50ID09PSAnQGVhY2gnICYmIHNlZ21lbnRFbmQgIT09IHBhdGhMZW5ndGgpIHsKICAgICAgICBsYXN0U2VnbWVudEVuZCA9IHNlZ21lbnRFbmQgKyAxOwogICAgICAgIHNlZ21lbnRFbmQgPSBwYXRoLmluZGV4T2YoJy4nLCBsYXN0U2VnbWVudEVuZCk7IC8vIFRoZXJlIHNob3VsZCBiZSBleGFjdGx5IG9uZSBzZWdtZW50IGFmdGVyIGFuIGBAZWFjaGAgKGkuZS4gYEBlYWNoLmZvb2AsIG5vdCBgQGVhY2guZm9vLmJhcmApCgogICAgICAgIChmYWxzZSAmJiAhKHNlZ21lbnRFbmQgPT09IC0xKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIldoZW4gdXNpbmcgQGVhY2ggaW4gYSBkZXBlbmRlbnQta2V5IG9yIGFuIG9ic2VydmVyLCAiICsgInlvdSBjYW4gb25seSBjaGFpbiBvbmUgcHJvcGVydHkgbGV2ZWwgZGVlcCBhZnRlciAiICsgKCJ0aGUgQGVhY2guIFRoYXQgaXMsIGAiICsgcGF0aC5zbGljZSgwLCBzZWdtZW50RW5kKSArICJgICIpICsgKCJpcyBhbGxvd2VkIGJ1dCBgIiArIHBhdGggKyAiYCAod2hpY2ggaXMgd2hhdCB5b3UgcGFzc2VkKSAiKSArICJpcyBub3QuXG5cbiIgKyAiVGhpcyB3YXMgbmV2ZXIgc3VwcG9ydGVkLiBDdXJyZW50bHksIHRoZSBleHRyYSBzZWdtZW50cyAiICsgKCJhcmUgc2lsZW50bHkgaWdub3JlZCwgaS5lLiBgIiArIHBhdGggKyAiYCBiZWhhdmVzIGV4YWN0bHkgIikgKyAoInRoZSBzYW1lIGFzIGAiICsgcGF0aC5zbGljZSgwLCBzZWdtZW50RW5kKSArICJgLiAiKSArICJJbiB0aGUgZnV0dXJlLCB0aGlzIHdpbGwgdGhyb3cgYW4gZXJyb3IuXG5cbiIgKyAiSWYgdGhlIGN1cnJlbnQgYmVoYXZpb3IgaXMgYWNjZXB0YWJsZSBmb3IgeW91ciB1c2UgY2FzZSwgIiArICJwbGVhc2UgcmVtb3ZlIHRoZSBleHRyYW5lb3VzIHNlZ21lbnRzIGJ5IGNoYW5naW5nIHlvdXIgIiArICgia2V5IHRvIGAiICsgcGF0aC5zbGljZSgwLCBzZWdtZW50RW5kKSArICJgLiAiKSArICJPdGhlcndpc2UsIHBsZWFzZSBjcmVhdGUgYW4gaW50ZXJtZWRpYXJ5IGNvbXB1dGVkIHByb3BlcnR5ICIgKyAib3Igc3dpdGNoIHRvIHVzaW5nIHRyYWNrZWQgcHJvcGVydGllcy4iLCBzZWdtZW50RW5kID09PSAtMSwgewogICAgICAgICAgdW50aWw6ICczLjE3LjAnLAogICAgICAgICAgaWQ6ICdlbWJlci1tZXRhbC5jb21wdXRlZC1kZWVwLWVhY2gnCiAgICAgICAgfSkpOwogICAgICAgIHZhciBhcnJMZW5ndGggPSBjdXJyZW50Lmxlbmd0aDsKCiAgICAgICAgaWYgKHR5cGVvZiBhcnJMZW5ndGggIT09ICdudW1iZXInIHx8IC8vIFRPRE86IHNob3VsZCB0aGUgc2Vjb25kIHRlc3QgYmUgYGlzRW1iZXJBcnJheWAgaW5zdGVhZD8KICAgICAgICAhKEFycmF5LmlzQXJyYXkoY3VycmVudCkgfHwgJ29iamVjdEF0JyBpbiBjdXJyZW50KSkgewogICAgICAgICAgLy8gSWYgdGhlIGN1cnJlbnQgb2JqZWN0IGlzbid0IGFuIGFycmF5LCB0aGVyZSdzIG5vdGhpbmcgZWxzZSB0byBkbywKICAgICAgICAgIC8vIHdlIGRvbid0IHdhdGNoIGluZGl2aWR1YWwgcHJvcGVydGllcy4gQnJlYWsgb3V0IG9mIHRoZSBsb29wLgogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSBlbHNlIGlmIChhcnJMZW5ndGggPT09IDApIHsKICAgICAgICAgIC8vIEZhc3QgcGF0aCBmb3IgZW1wdHkgYXJyYXlzCiAgICAgICAgICBjaGFpblRhZ3MucHVzaCh0YWdGb3JQcm9wZXJ0eShjdXJyZW50LCAnW10nKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIGlmIChzZWdtZW50RW5kID09PSAtMSkgewogICAgICAgICAgc2VnbWVudCA9IHBhdGguc2xpY2UobGFzdFNlZ21lbnRFbmQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBEZXByZWNhdGVkLCByZW1vdmUgb25jZSB3ZSB0dXJuIHRoZSBkZXByZWNhdGlvbiBpbnRvIGFuIGFzc2VydGlvbgogICAgICAgICAgc2VnbWVudCA9IHBhdGguc2xpY2UobGFzdFNlZ21lbnRFbmQsIHNlZ21lbnRFbmQpOwogICAgICAgIH0gLy8gUHVzaCB0aGUgdGFncyBmb3IgZWFjaCBpdGVtJ3MgcHJvcGVydHkKCgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyTGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHZhciBpdGVtID0gb2JqZWN0QXQoY3VycmVudCwgaSk7CiAgICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgaXRlbSA9PT0gJ29iamVjdCcpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiV2hlbiB1c2luZyBAZWFjaCB0byBvYnNlcnZlIHRoZSBhcnJheSBgIiArIGN1cnJlbnQudG9TdHJpbmcoKSArICJgLCB0aGUgaXRlbXMgaW4gdGhlIGFycmF5IG11c3QgYmUgb2JqZWN0cyIsIHR5cGVvZiBpdGVtID09PSAnb2JqZWN0JykpOwogICAgICAgICAgY2hhaW5UYWdzLnB1c2godGFnRm9yUHJvcGVydHkoaXRlbSwgc2VnbWVudCkpOwogICAgICAgIH0gLy8gUHVzaCB0aGUgdGFnIGZvciB0aGUgYXJyYXkgbGVuZ3RoIGl0c2VsZgoKCiAgICAgICAgY2hhaW5UYWdzLnB1c2godGFnRm9yUHJvcGVydHkoY3VycmVudCwgJ1tdJykpOwogICAgICAgIGJyZWFrOwogICAgICB9IC8vIElmIHRoZSBzZWdtZW50IGlzIGxpbmtpbmcgdG8gYW4gYXJncyBwcm94eSwgd2UgbmVlZCB0byBtYW51YWxseSBhY2Nlc3MKICAgICAgLy8gdGhlIHRhZ3MgZm9yIHRoZSBhcmdzLCBzaW5jZSB0aGV5IGFyZSBkaXJlY3QgcmVmZXJlbmNlcyBhbmQgZG9uJ3QgaGF2ZSBhCiAgICAgIC8vIHRhZ0ZvclByb3BlcnR5LiBXZSB0aGVuIGNvbnRpbnVlIGNoYWluaW5nIGxpa2Ugbm9ybWFsIGFmdGVyIGl0LCBzaW5jZQogICAgICAvLyB5b3UgY291bGQgY2hhaW4gb2ZmIGFuIGFyZyBpZiBpdCB3ZXJlIGFuIG9iamVjdCwgZm9yIGluc3RhbmNlLgoKCiAgICAgIGlmIChzZWdtZW50ID09PSAnYXJncycgJiYgQVJHU19QUk9YWV9UQUdTLmhhcyhjdXJyZW50LmFyZ3MpKSB7CiAgICAgICAgKGZhbHNlICYmICEoc2VnbWVudEVuZCAhPT0gcGF0aExlbmd0aCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJXaGVuIHdhdGNoaW5nIHRoZSAnYXJncycgb24gYSBHbGltbWVyQ29tcG9uZW50LCB5b3UgbXVzdCB3YXRjaCBhIHZhbHVlIG9uIHRoZSBhcmdzLiBZb3UgY2Fubm90IHdhdGNoIHRoZSBvYmplY3QgaXRzZWxmLCBhcyBpdCBuZXZlciBjaGFuZ2VzLiIsIHNlZ21lbnRFbmQgIT09IHBhdGhMZW5ndGgpKTsKICAgICAgICBsYXN0U2VnbWVudEVuZCA9IHNlZ21lbnRFbmQgKyAxOwogICAgICAgIHNlZ21lbnRFbmQgPSBwYXRoLmluZGV4T2YoJy4nLCBsYXN0U2VnbWVudEVuZCk7CgogICAgICAgIGlmIChzZWdtZW50RW5kID09PSAtMSkgewogICAgICAgICAgc2VnbWVudEVuZCA9IHBhdGhMZW5ndGg7CiAgICAgICAgfQoKICAgICAgICBzZWdtZW50ID0gcGF0aC5zbGljZShsYXN0U2VnbWVudEVuZCwgc2VnbWVudEVuZCk7CiAgICAgICAgdmFyIG5hbWVkQXJncyA9IEFSR1NfUFJPWFlfVEFHUy5nZXQoY3VycmVudC5hcmdzKTsKICAgICAgICB2YXIgcmVmID0gbmFtZWRBcmdzLmdldChzZWdtZW50KTsKICAgICAgICBjaGFpblRhZ3MucHVzaChyZWYudGFnKTsgLy8gV2Ugc3RpbGwgbmVlZCB0byBicmVhayBpZiB3ZSdyZSBhdCB0aGUgZW5kIG9mIHRoZSBwYXRoLgoKICAgICAgICBpZiAoc2VnbWVudEVuZCA9PT0gcGF0aExlbmd0aCkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSAvLyBPdGhlcndpc2UsIHNldCB0aGUgY3VycmVudCB2YWx1ZSBhbmQgdGhlbiBjb250aW51ZSB0byB0aGUgbmV4dCBzZWdtZW50CgoKICAgICAgICBjdXJyZW50ID0gcmVmLnZhbHVlKCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0gLy8gVE9ETzogQXNzZXJ0IHRoYXQgY3VycmVudFtzZWdtZW50XSBpc24ndCBhbiB1bmRlY29yYXRlZCwgbm9uLU1BTkRBVE9SWV9TRVRURVIvZGVwZW5kZW50S2V5Q29tcGF0IGdldHRlcgoKCiAgICAgIHZhciBwcm9wZXJ0eVRhZyA9IHRhZ0ZvclByb3BlcnR5KGN1cnJlbnQsIHNlZ21lbnQpOwogICAgICBkZXNjcmlwdG9yID0gZGVzY3JpcHRvckZvclByb3BlcnR5KGN1cnJlbnQsIHNlZ21lbnQpOwogICAgICBjaGFpblRhZ3MucHVzaChwcm9wZXJ0eVRhZyk7IC8vIElmIHRoZSBrZXkgd2FzIGFuIGFsaWFzLCB3ZSBzaG91bGQgYWx3YXlzIGdldCB0aGUgbmV4dCB2YWx1ZSBpbiBvcmRlciB0bwogICAgICAvLyBib290c3RyYXAgdGhlIGFsaWFzLiBUaGlzIGlzIGJlY2F1c2UgYWxpYXNlcywgdW5saWtlIG90aGVyIENQcywgc2hvdWxkCiAgICAgIC8vIGFsd2F5cyBiZSBpbiBzeW5jIHdpdGggdGhlIGFsaWFzZWQgdmFsdWUuCgogICAgICBpZiAoZGVzY3JpcHRvciAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBkZXNjcmlwdG9yLmFsdEtleSA9PT0gJ3N0cmluZycpIHsKICAgICAgICBjdXJyZW50ID0gY3VycmVudFtzZWdtZW50XTsgLy8gV2Ugc3RpbGwgbmVlZCB0byBicmVhayBpZiB3ZSdyZSBhdCB0aGUgZW5kIG9mIHRoZSBwYXRoLgoKICAgICAgICBpZiAoc2VnbWVudEVuZCA9PT0gcGF0aExlbmd0aCkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSAvLyBPdGhlcndpc2UsIGNvbnRpbnVlIHRvIHByb2Nlc3MgdGhlIG5leHQgc2VnbWVudAoKCiAgICAgICAgY29udGludWU7CiAgICAgIH0gLy8gSWYgd2UncmUgYXQgdGhlIGVuZCBvZiB0aGUgcGF0aCwgcHJvY2Vzc2luZyB0aGUgbGFzdCBzZWdtZW50LCBhbmQgaXQncwogICAgICAvLyBub3QgYW4gYWxpYXMsIHdlIHNob3VsZCBfbm90XyBnZXQgdGhlIGxhc3QgdmFsdWUsIHNpbmNlIHdlIGFscmVhZHkgaGF2ZQogICAgICAvLyBpdHMgdGFnLiBUaGVyZSdzIG5vIHJlYXNvbiB0byBhY2Nlc3MgaXQgYW5kIGRvIG1vcmUgd29yay4KCgogICAgICBpZiAoc2VnbWVudEVuZCA9PT0gcGF0aExlbmd0aCkgewogICAgICAgIGJyZWFrOwogICAgICB9CgogICAgICBpZiAoZGVzY3JpcHRvciA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgLy8gSWYgdGhlIGRlc2NyaXB0b3IgaXMgdW5kZWZpbmVkLCB0aGVuIGl0cyBhIG5vcm1hbCBwcm9wZXJ0eSwgc28gd2Ugc2hvdWxkCiAgICAgICAgLy8gbG9va3VwIHRoZSB2YWx1ZSB0byBjaGFpbiBvZmYgb2YgbGlrZSBub3JtYWwuCiAgICAgICAgaWYgKCEoc2VnbWVudCBpbiBjdXJyZW50KSAmJiB0eXBlb2YgY3VycmVudC51bmtub3duUHJvcGVydHkgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIGN1cnJlbnQgPSBjdXJyZW50LnVua25vd25Qcm9wZXJ0eShzZWdtZW50KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY3VycmVudCA9IGN1cnJlbnRbc2VnbWVudF07CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIC8vIElmIHRoZSBkZXNjcmlwdG9yIGlzIGRlZmluZWQsIHRoZW4gaXRzIGEgbm9ybWFsIENQIChub3QgYW4gYWxpYXMsIHdoaWNoCiAgICAgICAgLy8gd291bGQgaGF2ZSBiZWVuIGhhbmRsZWQgZWFybGllcikuIFdlIGdldCB0aGUgbGFzdCByZXZpc2lvbiB0byBjaGVjayBpZgogICAgICAgIC8vIHRoZSBDUCBpcyBzdGlsbCB2YWxpZCwgYW5kIGlmIHNvIHdlIHVzZSB0aGUgY2FjaGVkIHZhbHVlLiBJZiBub3QsIHRoZW4KICAgICAgICAvLyB3ZSBjcmVhdGUgYSBsYXp5IGNoYWluIGxvb2t1cCwgYW5kIHRoZSBuZXh0IHRpbWUgdGhlIENQIGlzIGNhbHVjdWxhdGVkLAogICAgICAgIC8vIGl0IHdpbGwgdXBkYXRlIHRoYXQgbGF6eSBjaGFpbi4KICAgICAgICB2YXIgbGFzdFJldmlzaW9uID0gZ2V0TGFzdFJldmlzaW9uRm9yKGN1cnJlbnQsIHNlZ21lbnQpOwoKICAgICAgICBpZiAoKDAsIF9yZWZlcmVuY2UudmFsaWRhdGUpKHByb3BlcnR5VGFnLCBsYXN0UmV2aXNpb24pKSB7CiAgICAgICAgICBjdXJyZW50ID0gcGVla0NhY2hlRm9yKGN1cnJlbnQpLmdldChzZWdtZW50KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFyIGxhenlDaGFpbnMgPSAoMCwgX21ldGEyLm1ldGEpKGN1cnJlbnQpLndyaXRhYmxlTGF6eUNoYWluc0ZvcihzZWdtZW50KTsKICAgICAgICAgIHZhciByZXN0ID0gcGF0aC5zdWJzdHIoc2VnbWVudEVuZCArIDEpOwogICAgICAgICAgdmFyIHBsYWNlaG9sZGVyVGFnID0gbGF6eUNoYWluc1tyZXN0XTsKCiAgICAgICAgICBpZiAocGxhY2Vob2xkZXJUYWcgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBwbGFjZWhvbGRlclRhZyA9IGxhenlDaGFpbnNbcmVzdF0gPSAoMCwgX3JlZmVyZW5jZS5jcmVhdGVVcGRhdGFibGVUYWcpKCk7CiAgICAgICAgICB9CgogICAgICAgICAgY2hhaW5UYWdzLnB1c2gocGxhY2Vob2xkZXJUYWcpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGNoYWluVGFnczsKICB9CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KCgogIHZhciBFTkRfV0lUSF9FQUNIX1JFR0VYID0gL1wuQGVhY2gkLzsKICAvKioKICAgIEV4cGFuZHMgYHBhdHRlcm5gLCBpbnZva2luZyBgY2FsbGJhY2tgIGZvciBlYWNoIGV4cGFuc2lvbi4KICAKICAgIFRoZSBvbmx5IHBhdHRlcm4gc3VwcG9ydGVkIGlzIGJyYWNlLWV4cGFuc2lvbiwgYW55dGhpbmcgZWxzZSB3aWxsIGJlIHBhc3NlZAogICAgb25jZSB0byBgY2FsbGJhY2tgIGRpcmVjdGx5LgogIAogICAgRXhhbXBsZQogIAogICAgYGBganMKICAgIGltcG9ydCB7IGV4cGFuZFByb3BlcnRpZXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGZ1bmN0aW9uIGVjaG8oYXJnKXsgY29uc29sZS5sb2coYXJnKTsgfQogIAogICAgZXhwYW5kUHJvcGVydGllcygnZm9vLmJhcicsIGVjaG8pOyAgICAgICAgICAgICAgLy89PiAnZm9vLmJhcicKICAgIGV4cGFuZFByb3BlcnRpZXMoJ3tmb28sYmFyfScsIGVjaG8pOyAgICAgICAgICAgIC8vPT4gJ2ZvbycsICdiYXInCiAgICBleHBhbmRQcm9wZXJ0aWVzKCdmb28ue2JhcixiYXp9JywgZWNobyk7ICAgICAgICAvLz0+ICdmb28uYmFyJywgJ2Zvby5iYXonCiAgICBleHBhbmRQcm9wZXJ0aWVzKCd7Zm9vLGJhcn0uYmF6JywgZWNobyk7ICAgICAgICAvLz0+ICdmb28uYmF6JywgJ2Jhci5iYXonCiAgICBleHBhbmRQcm9wZXJ0aWVzKCdmb28ue2JhcixiYXp9LltdJywgZWNobykgICAgICAvLz0+ICdmb28uYmFyLltdJywgJ2Zvby5iYXouW10nCiAgICBleHBhbmRQcm9wZXJ0aWVzKCd7Zm9vLGJhcn0ue3NwYW0sZWdnc30nLCBlY2hvKSAvLz0+ICdmb28uc3BhbScsICdmb28uZWdncycsICdiYXIuc3BhbScsICdiYXIuZWdncycKICAgIGV4cGFuZFByb3BlcnRpZXMoJ3tmb299LmJhci57YmF6fScpICAgICAgICAgICAgIC8vPT4gJ2Zvby5iYXIuYmF6JwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGV4cGFuZFByb3BlcnRpZXMKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHB1YmxpYwogICAgQHBhcmFtIHtTdHJpbmd9IHBhdHRlcm4gVGhlIHByb3BlcnR5IHBhdHRlcm4gdG8gZXhwYW5kLgogICAgQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGNhbGxiYWNrIHRvIGludm9rZS4gIEl0IGlzIGludm9rZWQgb25jZSBwZXIKICAgIGV4cGFuc2lvbiwgYW5kIGlzIHBhc3NlZCB0aGUgZXhwYW5zaW9uLgogICovCgogIGZ1bmN0aW9uIGV4cGFuZFByb3BlcnRpZXMocGF0dGVybiwgY2FsbGJhY2spIHsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBwYXR0ZXJuID09PSAnc3RyaW5nJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJBIGNvbXB1dGVkIHByb3BlcnR5IGtleSBtdXN0IGJlIGEgc3RyaW5nLCB5b3UgcGFzc2VkICIgKyB0eXBlb2YgcGF0dGVybiArICIgIiArIHBhdHRlcm4sIHR5cGVvZiBwYXR0ZXJuID09PSAnc3RyaW5nJykpOwogICAgKGZhbHNlICYmICEocGF0dGVybi5pbmRleE9mKCcgJykgPT09IC0xKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0JyYWNlIGV4cGFuZGVkIHByb3BlcnRpZXMgY2Fubm90IGNvbnRhaW4gc3BhY2VzLCBlLmcuICJ1c2VyLntmaXJzdE5hbWUsIGxhc3ROYW1lfSIgc2hvdWxkIGJlICJ1c2VyLntmaXJzdE5hbWUsbGFzdE5hbWV9IicsIHBhdHRlcm4uaW5kZXhPZignICcpID09PSAtMSkpOyAvLyByZWdleCB0byBsb29rIGZvciBkb3VibGUgb3BlbiwgZG91YmxlIGNsb3NlLCBvciB1bmNsb3NlZCBicmFjZXMKCiAgICAoZmFsc2UgJiYgIShwYXR0ZXJuLm1hdGNoKC9ce1tefXtdKlx7fFx9W159e10qXH18XHtbXn1dKiQvZykgPT09IG51bGwpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQnJhY2UgZXhwYW5kZWQgcHJvcGVydGllcyBoYXZlIHRvIGJlIGJhbGFuY2VkIGFuZCBjYW5ub3QgYmUgbmVzdGVkLCBwYXR0ZXJuOiAiICsgcGF0dGVybiwgcGF0dGVybi5tYXRjaCgvXHtbXn17XSpce3xcfVtefXtdKlx9fFx7W159XSokL2cpID09PSBudWxsKSk7CiAgICB2YXIgc3RhcnQgPSBwYXR0ZXJuLmluZGV4T2YoJ3snKTsKCiAgICBpZiAoc3RhcnQgPCAwKSB7CiAgICAgIGNhbGxiYWNrKHBhdHRlcm4ucmVwbGFjZShFTkRfV0lUSF9FQUNIX1JFR0VYLCAnLltdJykpOwogICAgfSBlbHNlIHsKICAgICAgZGl2ZSgnJywgcGF0dGVybiwgc3RhcnQsIGNhbGxiYWNrKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGRpdmUocHJlZml4LCBwYXR0ZXJuLCBzdGFydCwgY2FsbGJhY2spIHsKICAgIHZhciBlbmQgPSBwYXR0ZXJuLmluZGV4T2YoJ30nKSwKICAgICAgICBpID0gMCwKICAgICAgICBuZXdTdGFydCwKICAgICAgICBhcnJheUxlbmd0aDsKICAgIHZhciB0ZW1wQXJyID0gcGF0dGVybi5zdWJzdHJpbmcoc3RhcnQgKyAxLCBlbmQpLnNwbGl0KCcsJyk7CiAgICB2YXIgYWZ0ZXIgPSBwYXR0ZXJuLnN1YnN0cmluZyhlbmQgKyAxKTsKICAgIHByZWZpeCA9IHByZWZpeCArIHBhdHRlcm4uc3Vic3RyaW5nKDAsIHN0YXJ0KTsKICAgIGFycmF5TGVuZ3RoID0gdGVtcEFyci5sZW5ndGg7CgogICAgd2hpbGUgKGkgPCBhcnJheUxlbmd0aCkgewogICAgICBuZXdTdGFydCA9IGFmdGVyLmluZGV4T2YoJ3snKTsKCiAgICAgIGlmIChuZXdTdGFydCA8IDApIHsKICAgICAgICBjYWxsYmFjaygocHJlZml4ICsgdGVtcEFycltpKytdICsgYWZ0ZXIpLnJlcGxhY2UoRU5EX1dJVEhfRUFDSF9SRUdFWCwgJy5bXScpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBkaXZlKHByZWZpeCArIHRlbXBBcnJbaSsrXSwgYWZ0ZXIsIG5ld1N0YXJ0LCBjYWxsYmFjayk7CiAgICAgIH0KICAgIH0KICB9CiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL29iamVjdAogICovCgogIC8qKgogICAgU2V0cyB0aGUgdmFsdWUgb2YgYSBwcm9wZXJ0eSBvbiBhbiBvYmplY3QsIHJlc3BlY3RpbmcgY29tcHV0ZWQgcHJvcGVydGllcwogICAgYW5kIG5vdGlmeWluZyBvYnNlcnZlcnMgYW5kIG90aGVyIGxpc3RlbmVycyBvZiB0aGUgY2hhbmdlLgogICAgSWYgdGhlIHNwZWNpZmllZCBwcm9wZXJ0eSBpcyBub3QgZGVmaW5lZCBvbiB0aGUgb2JqZWN0IGFuZCB0aGUgb2JqZWN0CiAgICBpbXBsZW1lbnRzIHRoZSBgc2V0VW5rbm93blByb3BlcnR5YCBtZXRob2QsIHRoZW4gaW5zdGVhZCBvZiBzZXR0aW5nIHRoZQogICAgdmFsdWUgb2YgdGhlIHByb3BlcnR5IG9uIHRoZSBvYmplY3QsIGl0cyBgc2V0VW5rbm93blByb3BlcnR5YCBoYW5kbGVyCiAgICB3aWxsIGJlIGludm9rZWQgd2l0aCB0aGUgdHdvIHBhcmFtZXRlcnMgYGtleU5hbWVgIGFuZCBgdmFsdWVgLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBzZXQob2JqLCAibmFtZSIsIHZhbHVlKTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBzZXQKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdAogICAgQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIG1vZGlmeS4KICAgIEBwYXJhbSB7U3RyaW5nfSBrZXlOYW1lIFRoZSBwcm9wZXJ0eSBrZXkgdG8gc2V0CiAgICBAcGFyYW0ge09iamVjdH0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldAogICAgQHJldHVybiB7T2JqZWN0fSB0aGUgcGFzc2VkIHZhbHVlLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBfc2V0MihvYmosIGtleU5hbWUsIHZhbHVlJCQxLCB0b2xlcmFudCkgewogICAgKGZhbHNlICYmICEoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyB8fCBhcmd1bWVudHMubGVuZ3RoID09PSA0KSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIlNldCBtdXN0IGJlIGNhbGxlZCB3aXRoIHRocmVlIG9yIGZvdXIgYXJndW1lbnRzOyBhbiBvYmplY3QsIGEgcHJvcGVydHkga2V5LCBhIHZhbHVlIGFuZCB0b2xlcmFudCB0cnVlL2ZhbHNlIiwgYXJndW1lbnRzLmxlbmd0aCA9PT0gMyB8fCBhcmd1bWVudHMubGVuZ3RoID09PSA0KSk7CiAgICAoZmFsc2UgJiYgIShvYmogJiYgdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJDYW5ub3QgY2FsbCBzZXQgd2l0aCAnIiArIGtleU5hbWUgKyAiJyBvbiBhbiB1bmRlZmluZWQgb2JqZWN0LiIsIG9iaiAmJiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyB8fCB0eXBlb2Ygb2JqID09PSAnZnVuY3Rpb24nKSk7CiAgICAoZmFsc2UgJiYgISh0eXBlb2Yga2V5TmFtZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGtleU5hbWUgPT09ICdudW1iZXInICYmICFpc05hTihrZXlOYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUga2V5IHByb3ZpZGVkIHRvIHNldCBtdXN0IGJlIGEgc3RyaW5nIG9yIG51bWJlciwgeW91IHBhc3NlZCAiICsga2V5TmFtZSwgdHlwZW9mIGtleU5hbWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBrZXlOYW1lID09PSAnbnVtYmVyJyAmJiAhaXNOYU4oa2V5TmFtZSkpKTsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBrZXlOYW1lICE9PSAnc3RyaW5nJyB8fCBrZXlOYW1lLmxhc3RJbmRleE9mKCd0aGlzLicsIDApICE9PSAwKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIid0aGlzJyBpbiBwYXRocyBpcyBub3Qgc3VwcG9ydGVkIiwgdHlwZW9mIGtleU5hbWUgIT09ICdzdHJpbmcnIHx8IGtleU5hbWUubGFzdEluZGV4T2YoJ3RoaXMuJywgMCkgIT09IDApKTsKCiAgICBpZiAob2JqLmlzRGVzdHJveWVkKSB7CiAgICAgIChmYWxzZSAmJiAhKHRvbGVyYW50KSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoImNhbGxpbmcgc2V0IG9uIGRlc3Ryb3llZCBvYmplY3Q6ICIgKyAoMCwgX3V0aWxzLnRvU3RyaW5nKShvYmopICsgIi4iICsga2V5TmFtZSArICIgPSAiICsgKDAsIF91dGlscy50b1N0cmluZykodmFsdWUkJDEpLCB0b2xlcmFudCkpOwogICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKGlzUGF0aChrZXlOYW1lKSkgewogICAgICByZXR1cm4gc2V0UGF0aChvYmosIGtleU5hbWUsIHZhbHVlJCQxLCB0b2xlcmFudCk7CiAgICB9CgogICAgdmFyIG1ldGEkJDEgPSAoMCwgX21ldGEyLnBlZWtNZXRhKShvYmopOwogICAgewogICAgICB2YXIgZGVzY3JpcHRvciA9ICgwLCBfdXRpbHMubG9va3VwRGVzY3JpcHRvcikob2JqLCBrZXlOYW1lKTsKICAgICAgdmFyIHNldHRlciA9IGRlc2NyaXB0b3IgPT09IG51bGwgPyB1bmRlZmluZWQgOiBkZXNjcmlwdG9yLnNldDsKCiAgICAgIGlmIChzZXR0ZXIgIT09IHVuZGVmaW5lZCAmJiBDUF9TRVRURVJfRlVOQ1MuaGFzKHNldHRlcikpIHsKICAgICAgICBvYmpba2V5TmFtZV0gPSB2YWx1ZSQkMTsKICAgICAgICByZXR1cm4gdmFsdWUkJDE7CiAgICAgIH0KICAgIH0KICAgIHZhciBjdXJyZW50VmFsdWU7CgogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgJiYgX3V0aWxzLkhBU19OQVRJVkVfUFJPWFkpIHsKICAgICAgY3VycmVudFZhbHVlID0gZ2V0UG9zc2libGVNYW5kYXRvcnlQcm94eVZhbHVlKG9iaiwga2V5TmFtZSk7CiAgICB9IGVsc2UgewogICAgICBjdXJyZW50VmFsdWUgPSBvYmpba2V5TmFtZV07CiAgICB9CgogICAgaWYgKGN1cnJlbnRWYWx1ZSA9PT0gdW5kZWZpbmVkICYmICdvYmplY3QnID09PSB0eXBlb2Ygb2JqICYmICEoa2V5TmFtZSBpbiBvYmopICYmIHR5cGVvZiBvYmouc2V0VW5rbm93blByb3BlcnR5ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIC8qIHVua25vd24gcHJvcGVydHkgKi8KICAgICAgb2JqLnNldFVua25vd25Qcm9wZXJ0eShrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgICB9IGVsc2UgewogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgewogICAgICAgICAgKDAsIF91dGlscy5zZXRXaXRoTWFuZGF0b3J5U2V0dGVyKShvYmosIGtleU5hbWUsIHZhbHVlJCQxKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgb2JqW2tleU5hbWVdID0gdmFsdWUkJDE7CiAgICAgIH0KCiAgICAgIGlmIChjdXJyZW50VmFsdWUgIT09IHZhbHVlJCQxKSB7CiAgICAgICAgbm90aWZ5UHJvcGVydHlDaGFuZ2Uob2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiB2YWx1ZSQkMTsKICB9CgogIGZ1bmN0aW9uIHNldFBhdGgocm9vdCwgcGF0aCwgdmFsdWUkJDEsIHRvbGVyYW50KSB7CiAgICB2YXIgcGFydHMgPSBwYXRoLnNwbGl0KCcuJyk7CiAgICB2YXIga2V5TmFtZSA9IHBhcnRzLnBvcCgpOwogICAgKGZhbHNlICYmICEoa2V5TmFtZS50cmltKCkubGVuZ3RoID4gMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdQcm9wZXJ0eSBzZXQgZmFpbGVkOiBZb3UgcGFzc2VkIGFuIGVtcHR5IHBhdGgnLCBrZXlOYW1lLnRyaW0oKS5sZW5ndGggPiAwKSk7CgogICAgdmFyIG5ld1Jvb3QgPSBfZ2V0UGF0aChyb290LCBwYXJ0cyk7CgogICAgaWYgKG5ld1Jvb3QgIT09IG51bGwgJiYgbmV3Um9vdCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBfc2V0MihuZXdSb290LCBrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgICB9IGVsc2UgaWYgKCF0b2xlcmFudCkgewogICAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIlByb3BlcnR5IHNldCBmYWlsZWQ6IG9iamVjdCBpbiBwYXRoIFwiIiArIHBhcnRzLmpvaW4oJy4nKSArICJcIiBjb3VsZCBub3QgYmUgZm91bmQuIik7CiAgICB9CiAgfQogIC8qKgogICAgRXJyb3ItdG9sZXJhbnQgZm9ybSBvZiBgc2V0YC4gV2lsbCBub3QgYmxvdyB1cCBpZiBhbnkgcGFydCBvZiB0aGUKICAgIGNoYWluIGlzIGB1bmRlZmluZWRgLCBgbnVsbGAsIG9yIGRlc3Ryb3llZC4KICAKICAgIFRoaXMgaXMgcHJpbWFyaWx5IHVzZWQgd2hlbiBzeW5jaW5nIGJpbmRpbmdzLCB3aGljaCBtYXkgdHJ5IHRvIHVwZGF0ZSBhZnRlcgogICAgYW4gb2JqZWN0IGhhcyBiZWVuIGRlc3Ryb3llZC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHRyeVNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgbGV0IG9iaiA9IHsgbmFtZTogIlpvZXkiIH07CiAgICB0cnlTZXQob2JqLCAiY29udGFjdHMudHdpdHRlciIsICJAZW1iZXJqcyIpOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHRyeVNldAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0CiAgICBAcGFyYW0ge09iamVjdH0gcm9vdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS4KICAgIEBwYXJhbSB7U3RyaW5nfSBwYXRoIFRoZSBwcm9wZXJ0eSBwYXRoIHRvIHNldAogICAgQHBhcmFtIHtPYmplY3R9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gdHJ5U2V0KHJvb3QsIHBhdGgsIHZhbHVlJCQxKSB7CiAgICByZXR1cm4gX3NldDIocm9vdCwgcGF0aCwgdmFsdWUkJDEsIHRydWUpOwogIH0KICAvKioKICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwoKCiAgdmFyIERFRVBfRUFDSF9SRUdFWCA9IC9cLkBlYWNoXC5bXi5dK1wuLzsKCiAgZnVuY3Rpb24gbm9vcCgpIHt9CiAgLyoqCiAgICBgQGNvbXB1dGVkYCBpcyBhIGRlY29yYXRvciB0aGF0IHR1cm5zIGEgSmF2YVNjcmlwdCBnZXR0ZXIgYW5kIHNldHRlciBpbnRvIGEKICAgIGNvbXB1dGVkIHByb3BlcnR5LCB3aGljaCBpcyBhIF9jYWNoZWQsIHRyYWNrYWJsZSB2YWx1ZV8uIEJ5IGRlZmF1bHQgdGhlIGdldHRlcgogICAgd2lsbCBvbmx5IGJlIGNhbGxlZCBvbmNlIGFuZCB0aGUgcmVzdWx0IHdpbGwgYmUgY2FjaGVkLiBZb3UgY2FuIHNwZWNpZnkKICAgIHZhcmlvdXMgcHJvcGVydGllcyB0aGF0IHlvdXIgY29tcHV0ZWQgcHJvcGVydHkgZGVwZW5kcyBvbi4gVGhpcyB3aWxsIGZvcmNlIHRoZQogICAgY2FjaGVkIHJlc3VsdCB0byBiZSBjbGVhcmVkIGlmIHRoZSBkZXBlbmRlbmNpZXMgYXJlIG1vZGlmaWVkLCBhbmQgbGF6aWx5IHJlY29tcHV0ZWQgdGhlIG5leHQgdGltZSBzb21ldGhpbmcgYXNrcyBmb3IgaXQuCiAgCiAgICBJbiB0aGUgZm9sbG93aW5nIGV4YW1wbGUgd2UgZGVjb3JhdGUgYSBnZXR0ZXIgLSBgZnVsbE5hbWVgIC0gIGJ5IGNhbGxpbmcKICAgIGBjb21wdXRlZGAgd2l0aCB0aGUgcHJvcGVydHkgZGVwZW5kZW5jaWVzIChgZmlyc3ROYW1lYCBhbmQgYGxhc3ROYW1lYCkgYXMKICAgIGFyZ3VtZW50cy4gVGhlIGBmdWxsTmFtZWAgZ2V0dGVyIHdpbGwgYmUgY2FsbGVkIG9uY2UgKHJlZ2FyZGxlc3Mgb2YgaG93IG1hbnkKICAgIHRpbWVzIGl0IGlzIGFjY2Vzc2VkKSBhcyBsb25nIGFzIGl0cyBkZXBlbmRlbmNpZXMgZG8gbm90IGNoYW5nZS4gT25jZQogICAgYGZpcnN0TmFtZWAgb3IgYGxhc3ROYW1lYCBhcmUgdXBkYXRlZCBhbnkgZnV0dXJlIGNhbGxzIHRvIGBmdWxsTmFtZWAgd2lsbAogICAgaW5jb3Jwb3JhdGUgdGhlIG5ldyB2YWx1ZXMsIGFuZCBhbnkgd2F0Y2hlcnMgb2YgdGhlIHZhbHVlIHN1Y2ggYXMgdGVtcGxhdGVzCiAgICB3aWxsIGJlIHVwZGF0ZWQ6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBjb21wdXRlZCwgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgCiAgICBjbGFzcyBQZXJzb24gewogICAgICBjb25zdHJ1Y3RvcihmaXJzdE5hbWUsIGxhc3ROYW1lKSB7CiAgICAgICAgc2V0KHRoaXMsICdmaXJzdE5hbWUnLCBmaXJzdE5hbWUpOwogICAgICAgIHNldCh0aGlzLCAnbGFzdE5hbWUnLCBsYXN0TmFtZSk7CiAgICAgIH0KICAKICAgICAgQGNvbXB1dGVkKCdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnKQogICAgICBnZXQgZnVsbE5hbWUoKSB7CiAgICAgICAgcmV0dXJuIGAke3RoaXMuZmlyc3ROYW1lfSAke3RoaXMubGFzdE5hbWV9YDsKICAgICAgfQogICAgfSk7CiAgCiAgICBsZXQgdG9tID0gbmV3IFBlcnNvbignVG9tJywgJ0RhbGUnKTsKICAKICAgIHRvbS5mdWxsTmFtZTsgLy8gJ1RvbSBEYWxlJwogICAgYGBgCiAgCiAgICBZb3UgY2FuIGFsc28gcHJvdmlkZSBhIHNldHRlciwgd2hpY2ggd2lsbCBiZSB1c2VkIHdoZW4gdXBkYXRpbmcgdGhlIGNvbXB1dGVkCiAgICBwcm9wZXJ0eS4gRW1iZXIncyBgc2V0YCBmdW5jdGlvbiBtdXN0IGJlIHVzZWQgdG8gdXBkYXRlIHRoZSBwcm9wZXJ0eQogICAgc2luY2UgaXQgd2lsbCBhbHNvIG5vdGlmeSBvYnNlcnZlcnMgb2YgdGhlIHByb3BlcnR5OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgY29tcHV0ZWQsIHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgY2xhc3MgUGVyc29uIHsKICAgICAgY29uc3RydWN0b3IoZmlyc3ROYW1lLCBsYXN0TmFtZSkgewogICAgICAgIHNldCh0aGlzLCAnZmlyc3ROYW1lJywgZmlyc3ROYW1lKTsKICAgICAgICBzZXQodGhpcywgJ2xhc3ROYW1lJywgbGFzdE5hbWUpOwogICAgICB9CiAgCiAgICAgIEBjb21wdXRlZCgnZmlyc3ROYW1lJywgJ2xhc3ROYW1lJykKICAgICAgZ2V0IGZ1bGxOYW1lKCkgewogICAgICAgIHJldHVybiBgJHt0aGlzLmZpcnN0TmFtZX0gJHt0aGlzLmxhc3ROYW1lfWA7CiAgICAgIH0KICAKICAgICAgc2V0IGZ1bGxOYW1lKHZhbHVlKSB7CiAgICAgICAgbGV0IFtmaXJzdE5hbWUsIGxhc3ROYW1lXSA9IHZhbHVlLnNwbGl0KCcgJyk7CiAgCiAgICAgICAgc2V0KHRoaXMsICdmaXJzdE5hbWUnLCBmaXJzdE5hbWUpOwogICAgICAgIHNldCh0aGlzLCAnbGFzdE5hbWUnLCBsYXN0TmFtZSk7CiAgICAgIH0KICAgIH0pOwogIAogICAgbGV0IHBlcnNvbiA9IG5ldyBQZXJzb24oKTsKICAKICAgIHNldChwZXJzb24sICdmdWxsTmFtZScsICdQZXRlciBXYWdlbmV0Jyk7CiAgICBwZXJzb24uZmlyc3ROYW1lOyAvLyAnUGV0ZXInCiAgICBwZXJzb24ubGFzdE5hbWU7ICAvLyAnV2FnZW5ldCcKICAgIGBgYAogIAogICAgWW91IGNhbiBhbHNvIHBhc3MgYSBnZXR0ZXIgZnVuY3Rpb24gb3Igb2JqZWN0IHdpdGggYGdldGAgYW5kIGBzZXRgIGZ1bmN0aW9ucwogICAgYXMgdGhlIGxhc3QgYXJndW1lbnQgdG8gdGhlIGNvbXB1dGVkIGRlY29yYXRvci4gVGhpcyBhbGxvd3MgeW91IHRvIGRlZmluZQogICAgY29tcHV0ZWQgcHJvcGVydHkgX21hY3Jvc186CiAgCiAgICBgYGBqcwogICAgaW1wb3J0IHsgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGZ1bmN0aW9uIGpvaW4oLi4ua2V5cykgewogICAgICByZXR1cm4gY29tcHV0ZWQoLi4ua2V5cywgZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIGtleXMubWFwKGtleSA9PiB0aGlzW2tleV0pLmpvaW4oJyAnKTsKICAgICAgfSk7CiAgICB9CiAgCiAgICBjbGFzcyBQZXJzb24gewogICAgICBAam9pbignZmlyc3ROYW1lJywgJ2xhc3ROYW1lJykKICAgICAgZnVsbE5hbWU7CiAgICB9CiAgICBgYGAKICAKICAgIE5vdGUgdGhhdCB3aGVuIGRlZmluZWQgdGhpcyB3YXksIGdldHRlcnMgYW5kIHNldHRlcnMgcmVjZWl2ZSB0aGUgX2tleV8gb2YgdGhlCiAgICBwcm9wZXJ0eSB0aGV5IGFyZSBkZWNvcmF0aW5nIGFzIHRoZSBmaXJzdCBhcmd1bWVudC4gU2V0dGVycyByZWNlaXZlIHRoZSB2YWx1ZQogICAgdGhleSBhcmUgc2V0dGluZyB0byBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IGluc3RlYWQuIEFkZGl0aW9uYWxseSwgc2V0dGVycyBtdXN0CiAgICBfcmV0dXJuXyB0aGUgdmFsdWUgdGhhdCBzaG91bGQgYmUgY2FjaGVkOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgY29tcHV0ZWQsIHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZnVuY3Rpb24gZnVsbE5hbWVNYWNybyhmaXJzdE5hbWVLZXksIGxhc3ROYW1lS2V5KSB7CiAgICAgIHJldHVybiBjb21wdXRlZChmaXJzdE5hbWVLZXksIGxhc3ROYW1lS2V5LCB7CiAgICAgICAgZ2V0KCkgewogICAgICAgICAgcmV0dXJuIGAke3RoaXNbZmlyc3ROYW1lS2V5XX0gJHt0aGlzW2xhc3ROYW1lS2V5XX1gOwogICAgICAgIH0KICAKICAgICAgICBzZXQoa2V5LCB2YWx1ZSkgewogICAgICAgICAgbGV0IFtmaXJzdE5hbWUsIGxhc3ROYW1lXSA9IHZhbHVlLnNwbGl0KCcgJyk7CiAgCiAgICAgICAgICBzZXQodGhpcywgZmlyc3ROYW1lS2V5LCBmaXJzdE5hbWUpOwogICAgICAgICAgc2V0KHRoaXMsIGxhc3ROYW1lS2V5LCBsYXN0TmFtZSk7CiAgCiAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICAKICAgIGNsYXNzIFBlcnNvbiB7CiAgICAgIGNvbnN0cnVjdG9yKGZpcnN0TmFtZSwgbGFzdE5hbWUpIHsKICAgICAgICBzZXQodGhpcywgJ2ZpcnN0TmFtZScsIGZpcnN0TmFtZSk7CiAgICAgICAgc2V0KHRoaXMsICdsYXN0TmFtZScsIGxhc3ROYW1lKTsKICAgICAgfQogIAogICAgICBAZnVsbE5hbWVNYWNybyBmdWxsTmFtZTsKICAgIH0pOwogIAogICAgbGV0IHBlcnNvbiA9IG5ldyBQZXJzb24oKTsKICAKICAgIHNldChwZXJzb24sICdmdWxsTmFtZScsICdQZXRlciBXYWdlbmV0Jyk7CiAgICBwZXJzb24uZmlyc3ROYW1lOyAvLyAnUGV0ZXInCiAgICBwZXJzb24ubGFzdE5hbWU7ICAvLyAnV2FnZW5ldCcKICAgIGBgYAogIAogICAgQ29tcHV0ZWQgcHJvcGVydGllcyBjYW4gYWxzbyBiZSB1c2VkIGluIGNsYXNzaWMgY2xhc3Nlcy4gVG8gZG8gdGhpcywgd2UKICAgIHByb3ZpZGUgdGhlIGdldHRlciBhbmQgc2V0dGVyIGFzIHRoZSBsYXN0IGFyZ3VtZW50IGxpa2Ugd2Ugd291bGQgZm9yIGEgbWFjcm8sCiAgICBhbmQgd2UgYXNzaWduIGl0IHRvIGEgcHJvcGVydHkgb24gdGhlIGNsYXNzIGRlZmluaXRpb24uIFRoaXMgaXMgYW4gX2Fub255bW91c18KICAgIGNvbXB1dGVkIG1hY3JvOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IGNvbXB1dGVkLCBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGxldCBQZXJzb24gPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAvLyB0aGVzZSB3aWxsIGJlIHN1cHBsaWVkIGJ5IGBjcmVhdGVgCiAgICAgIGZpcnN0TmFtZTogbnVsbCwKICAgICAgbGFzdE5hbWU6IG51bGwsCiAgCiAgICAgIGZ1bGxOYW1lOiBjb21wdXRlZCgnZmlyc3ROYW1lJywgJ2xhc3ROYW1lJywgewogICAgICAgIGdldCgpIHsKICAgICAgICAgIHJldHVybiBgJHt0aGlzLmZpcnN0TmFtZX0gJHt0aGlzLmxhc3ROYW1lfWA7CiAgICAgICAgfQogIAogICAgICAgIHNldChrZXksIHZhbHVlKSB7CiAgICAgICAgICBsZXQgW2ZpcnN0TmFtZSwgbGFzdE5hbWVdID0gdmFsdWUuc3BsaXQoJyAnKTsKICAKICAgICAgICAgIHNldCh0aGlzLCAnZmlyc3ROYW1lJywgZmlyc3ROYW1lKTsKICAgICAgICAgIHNldCh0aGlzLCAnbGFzdE5hbWUnLCBsYXN0TmFtZSk7CiAgCiAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgfQogICAgICB9KQogICAgfSk7CiAgCiAgICBsZXQgdG9tID0gUGVyc29uLmNyZWF0ZSh7CiAgICAgIGZpcnN0TmFtZTogJ1RvbScsCiAgICAgIGxhc3ROYW1lOiAnRGFsZScKICAgIH0pOwogIAogICAgdG9tLmdldCgnZnVsbE5hbWUnKSAvLyAnVG9tIERhbGUnCiAgICBgYGAKICAKICAgIFlvdSBjYW4gb3ZlcndyaXRlIGNvbXB1dGVkIHByb3BlcnR5IHdpdGhvdXQgc2V0dGVycyB3aXRoIGEgbm9ybWFsIHByb3BlcnR5IChubwogICAgbG9uZ2VyIGNvbXB1dGVkKSB0aGF0IHdvbid0IGNoYW5nZSBpZiBkZXBlbmRlbmNpZXMgY2hhbmdlLiBZb3UgY2FuIGFsc28gbWFyawogICAgY29tcHV0ZWQgcHJvcGVydHkgYXMgYC5yZWFkT25seSgpYCBhbmQgYmxvY2sgYWxsIGF0dGVtcHRzIHRvIHNldCBpdC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGNvbXB1dGVkLCBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGNsYXNzIFBlcnNvbiB7CiAgICAgIGNvbnN0cnVjdG9yKGZpcnN0TmFtZSwgbGFzdE5hbWUpIHsKICAgICAgICBzZXQodGhpcywgJ2ZpcnN0TmFtZScsIGZpcnN0TmFtZSk7CiAgICAgICAgc2V0KHRoaXMsICdsYXN0TmFtZScsIGxhc3ROYW1lKTsKICAgICAgfQogIAogICAgICBAY29tcHV0ZWQoJ2ZpcnN0TmFtZScsICdsYXN0TmFtZScpLnJlYWRPbmx5KCkKICAgICAgZ2V0IGZ1bGxOYW1lKCkgewogICAgICAgIHJldHVybiBgJHt0aGlzLmZpcnN0TmFtZX0gJHt0aGlzLmxhc3ROYW1lfWA7CiAgICAgIH0KICAgIH0pOwogIAogICAgbGV0IHBlcnNvbiA9IG5ldyBQZXJzb24oKTsKICAgIHBlcnNvbi5zZXQoJ2Z1bGxOYW1lJywgJ1BldGVyIFdhZ2VuZXQnKTsgLy8gVW5jYXVnaHQgRXJyb3I6IENhbm5vdCBzZXQgcmVhZC1vbmx5IHByb3BlcnR5ICJmdWxsTmFtZSIgb24gb2JqZWN0OiA8KC4uLik6ZW1iZXJYWFg+CiAgICBgYGAKICAKICAgIEFkZGl0aW9uYWwgcmVzb3VyY2VzOgogICAgLSBbRGVjb3JhdG9ycyBSRkNdKGh0dHBzOi8vZ2l0aHViLmNvbS9lbWJlcmpzL3JmY3MvYmxvYi9tYXN0ZXIvdGV4dC8wNDA4LWRlY29yYXRvcnMubWQpCiAgICAtIFtOZXcgQ1Agc3ludGF4IFJGQ10oaHR0cHM6Ly9naXRodWIuY29tL2VtYmVyanMvcmZjcy9ibG9iL21hc3Rlci90ZXh0LzAwMTEtaW1wcm92ZWQtY3Atc3ludGF4Lm1kKQogICAgLSBbTmV3IGNvbXB1dGVkIHN5bnRheCBleHBsYWluZWQgaW4gIkVtYmVyIDEuMTIgcmVsZWFzZWQiIF0oaHR0cHM6Ly9lbWJlcmpzLmNvbS9ibG9nLzIwMTUvMDUvMTMvZW1iZXItMS0xMi1yZWxlYXNlZC5odG1sI3RvY19uZXctY29tcHV0ZWQtc3ludGF4KQogIAogICAgQGNsYXNzIENvbXB1dGVkUHJvcGVydHkKICAgIEBwdWJsaWMKICAqLwoKCiAgdmFyIENvbXB1dGVkUHJvcGVydHkgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NvbXB1dGVkRGVzY3JpcHRvcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKENvbXB1dGVkUHJvcGVydHksIF9Db21wdXRlZERlc2NyaXB0b3IpOwoKICAgIGZ1bmN0aW9uIENvbXB1dGVkUHJvcGVydHkoYXJncykgewogICAgICB2YXIgX3RoaXM7CgogICAgICBfdGhpcyA9IF9Db21wdXRlZERlc2NyaXB0b3IuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpcy5fdm9sYXRpbGUgPSBmYWxzZTsKICAgICAgX3RoaXMuX3JlYWRPbmx5ID0gZmFsc2U7CiAgICAgIF90aGlzLl9zdXNwZW5kZWQgPSB1bmRlZmluZWQ7CiAgICAgIF90aGlzLl9oYXNDb25maWcgPSBmYWxzZTsKICAgICAgX3RoaXMuX2dldHRlciA9IHVuZGVmaW5lZDsKICAgICAgX3RoaXMuX3NldHRlciA9IHVuZGVmaW5lZDsKICAgICAgdmFyIG1heWJlQ29uZmlnID0gYXJnc1thcmdzLmxlbmd0aCAtIDFdOwoKICAgICAgaWYgKHR5cGVvZiBtYXliZUNvbmZpZyA9PT0gJ2Z1bmN0aW9uJyB8fCBtYXliZUNvbmZpZyAhPT0gbnVsbCAmJiB0eXBlb2YgbWF5YmVDb25maWcgPT09ICdvYmplY3QnKSB7CiAgICAgICAgX3RoaXMuX2hhc0NvbmZpZyA9IHRydWU7CiAgICAgICAgdmFyIGNvbmZpZyA9IGFyZ3MucG9wKCk7CgogICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICAoZmFsc2UgJiYgISghaXNDbGFzc2ljRGVjb3JhdG9yKGNvbmZpZykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byBwYXNzIGEgY29tcHV0ZWQgcHJvcGVydHkgaW5zdGFuY2UgdG8gY29tcHV0ZWQoKS4gQ29tcHV0ZWQgcHJvcGVydHkgaW5zdGFuY2VzIGFyZSBkZWNvcmF0b3IgZnVuY3Rpb25zLCBhbmQgY2Fubm90IGJlIHBhc3NlZCB0byBjb21wdXRlZCgpIGJlY2F1c2UgdGhleSBjYW5ub3QgYmUgdHVybmVkIGludG8gZGVjb3JhdG9ycyB0d2ljZSIsICFpc0NsYXNzaWNEZWNvcmF0b3IoY29uZmlnKSkpOwogICAgICAgICAgX3RoaXMuX2dldHRlciA9IGNvbmZpZzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFyIG9iamVjdENvbmZpZyA9IGNvbmZpZzsKICAgICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBvYmplY3RDb25maWcgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KG9iamVjdENvbmZpZykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnY29tcHV0ZWQgZXhwZWN0cyBhIGZ1bmN0aW9uIG9yIGFuIG9iamVjdCBhcyBsYXN0IGFyZ3VtZW50LicsIHR5cGVvZiBvYmplY3RDb25maWcgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KG9iamVjdENvbmZpZykpKTsKICAgICAgICAgIChmYWxzZSAmJiAhKE9iamVjdC5rZXlzKG9iamVjdENvbmZpZykuZXZlcnkoZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgICByZXR1cm4ga2V5ID09PSAnZ2V0JyB8fCBrZXkgPT09ICdzZXQnOwogICAgICAgICAgfSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ29uZmlnIG9iamVjdCBwYXNzZWQgdG8gY29tcHV0ZWQgY2FuIG9ubHkgY29udGFpbiBgZ2V0YCBhbmQgYHNldGAga2V5cy4nLCBPYmplY3Qua2V5cyhvYmplY3RDb25maWcpLmV2ZXJ5KGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgICAgcmV0dXJuIGtleSA9PT0gJ2dldCcgfHwga2V5ID09PSAnc2V0JzsKICAgICAgICAgIH0pKSk7CiAgICAgICAgICAoZmFsc2UgJiYgIShCb29sZWFuKG9iamVjdENvbmZpZy5nZXQpIHx8IEJvb2xlYW4ob2JqZWN0Q29uZmlnLnNldCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ29tcHV0ZWQgcHJvcGVydGllcyBtdXN0IHJlY2VpdmUgYSBnZXR0ZXIgb3IgYSBzZXR0ZXIsIHlvdSBwYXNzZWQgbm9uZS4nLCBCb29sZWFuKG9iamVjdENvbmZpZy5nZXQpIHx8IEJvb2xlYW4ob2JqZWN0Q29uZmlnLnNldCkpKTsKICAgICAgICAgIF90aGlzLl9nZXR0ZXIgPSBvYmplY3RDb25maWcuZ2V0IHx8IG5vb3A7CiAgICAgICAgICBfdGhpcy5fc2V0dGVyID0gb2JqZWN0Q29uZmlnLnNldDsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChhcmdzLmxlbmd0aCA+IDApIHsKICAgICAgICB2YXIgX3RoaXMyOwoKICAgICAgICAoX3RoaXMyID0gX3RoaXMpLl9wcm9wZXJ0eS5hcHBseShfdGhpczIsIGFyZ3MpOwogICAgICB9CgogICAgICByZXR1cm4gX3RoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzcgPSBDb21wdXRlZFByb3BlcnR5LnByb3RvdHlwZTsKCiAgICBfcHJvdG83LnNldHVwID0gZnVuY3Rpb24gc2V0dXAob2JqLCBrZXlOYW1lLCBwcm9wZXJ0eURlc2MsIG1ldGEkJDEpIHsKICAgICAgX0NvbXB1dGVkRGVzY3JpcHRvci5wcm90b3R5cGUuc2V0dXAuY2FsbCh0aGlzLCBvYmosIGtleU5hbWUsIHByb3BlcnR5RGVzYywgbWV0YSQkMSk7CgogICAgICAoZmFsc2UgJiYgISghKHByb3BlcnR5RGVzYyAmJiB0eXBlb2YgcHJvcGVydHlEZXNjLnZhbHVlID09PSAnZnVuY3Rpb24nKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJAY29tcHV0ZWQgY2FuIG9ubHkgYmUgdXNlZCBvbiBhY2Nlc3NvcnMgb3IgZmllbGRzLCBhdHRlbXB0ZWQgdG8gdXNlIGl0IHdpdGggIiArIGtleU5hbWUgKyAiIGJ1dCB0aGF0IHdhcyBhIG1ldGhvZC4gVHJ5IGNvbnZlcnRpbmcgaXQgdG8gYSBnZXR0ZXIgKGUuZy4gYGdldCAiICsga2V5TmFtZSArICIoKSB7fWApIiwgIShwcm9wZXJ0eURlc2MgJiYgdHlwZW9mIHByb3BlcnR5RGVzYy52YWx1ZSA9PT0gJ2Z1bmN0aW9uJykpKTsKICAgICAgKGZhbHNlICYmICEoIXByb3BlcnR5RGVzYyB8fCAhcHJvcGVydHlEZXNjLmluaXRpYWxpemVyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkBjb21wdXRlZCBjYW4gb25seSBiZSB1c2VkIG9uIGVtcHR5IGZpZWxkcy4gIiArIGtleU5hbWUgKyAiIGhhcyBhbiBpbml0aWFsIHZhbHVlIChlLmcuIGAiICsga2V5TmFtZSArICIgPSBzb21lVmFsdWVgKSIsICFwcm9wZXJ0eURlc2MgfHwgIXByb3BlcnR5RGVzYy5pbml0aWFsaXplcikpOwogICAgICAoZmFsc2UgJiYgISghKHRoaXMuX2hhc0NvbmZpZyAmJiBwcm9wZXJ0eURlc2MgJiYgKHR5cGVvZiBwcm9wZXJ0eURlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBwcm9wZXJ0eURlc2Muc2V0ID09PSAnZnVuY3Rpb24nKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQXR0ZW1wdGVkIHRvIGFwcGx5IGEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCBhbHJlYWR5IGhhcyBhIGdldHRlci9zZXR0ZXIgdG8gYSAiICsga2V5TmFtZSArICIsIGJ1dCBpdCBpcyBhIG1ldGhvZCBvciBhbiBhY2Nlc3Nvci4gSWYgeW91IHBhc3NlZCBAY29tcHV0ZWQgYSBmdW5jdGlvbiBvciBnZXR0ZXIvc2V0dGVyIChlLmcuIGBAY29tcHV0ZWQoeyBnZXQoKSB7IC4uLiB9IH0pYCksIHRoZW4gaXQgbXVzdCBiZSBhcHBsaWVkIHRvIGEgZmllbGQiLCAhKHRoaXMuX2hhc0NvbmZpZyAmJiBwcm9wZXJ0eURlc2MgJiYgKHR5cGVvZiBwcm9wZXJ0eURlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBwcm9wZXJ0eURlc2Muc2V0ID09PSAnZnVuY3Rpb24nKSkpKTsKCiAgICAgIGlmICh0aGlzLl9oYXNDb25maWcgPT09IGZhbHNlKSB7CiAgICAgICAgKGZhbHNlICYmICEocHJvcGVydHlEZXNjICYmICh0eXBlb2YgcHJvcGVydHlEZXNjLmdldCA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgcHJvcGVydHlEZXNjLnNldCA9PT0gJ2Z1bmN0aW9uJykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQXR0ZW1wdGVkIHRvIHVzZSBAY29tcHV0ZWQgb24gIiArIGtleU5hbWUgKyAiLCBidXQgaXQgZGlkIG5vdCBoYXZlIGEgZ2V0dGVyIG9yIGEgc2V0dGVyLiBZb3UgbXVzdCBlaXRoZXIgcGFzcyBhIGdldCBhIGZ1bmN0aW9uIG9yIGdldHRlci9zZXR0ZXIgdG8gQGNvbXB1dGVkIGRpcmVjdGx5IChlLmcuIGBAY29tcHV0ZWQoeyBnZXQoKSB7IC4uLiB9IH0pYCkgb3IgYXBwbHkgQGNvbXB1dGVkIGRpcmVjdGx5IHRvIGEgZ2V0dGVyL3NldHRlciIsIHByb3BlcnR5RGVzYyAmJiAodHlwZW9mIHByb3BlcnR5RGVzYy5nZXQgPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIHByb3BlcnR5RGVzYy5zZXQgPT09ICdmdW5jdGlvbicpKSk7CiAgICAgICAgdmFyIF9nZXQgPSBwcm9wZXJ0eURlc2MuZ2V0LAogICAgICAgICAgICBzZXQkJDEgPSBwcm9wZXJ0eURlc2Muc2V0OwoKICAgICAgICBpZiAoX2dldCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB0aGlzLl9nZXR0ZXIgPSBfZ2V0OwogICAgICAgIH0KCiAgICAgICAgaWYgKHNldCQkMSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB0aGlzLl9zZXR0ZXIgPSBmdW5jdGlvbiBzZXR0ZXJXcmFwcGVyKF9rZXksIHZhbHVlJCQxKSB7CiAgICAgICAgICAgIHZhciByZXQgPSBzZXQkJDEuY2FsbCh0aGlzLCB2YWx1ZSQkMSk7CgogICAgICAgICAgICBpZiAoX2dldCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiByZXQgPT09ICd1bmRlZmluZWQnID8gX2dldC5jYWxsKHRoaXMpIDogcmV0OwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBDYWxsIG9uIGEgY29tcHV0ZWQgcHJvcGVydHkgdG8gc2V0IGl0IGludG8gbm9uLWNhY2hlZCBtb2RlLiBXaGVuIGluIHRoaXMKICAgICAgbW9kZSB0aGUgY29tcHV0ZWQgcHJvcGVydHkgd2lsbCBub3QgYXV0b21hdGljYWxseSBjYWNoZSB0aGUgcmV0dXJuIHZhbHVlLgogICAgICBJdCBhbHNvIGRvZXMgbm90IGF1dG9tYXRpY2FsbHkgZmlyZSBhbnkgY2hhbmdlIGV2ZW50cy4gWW91IG11c3QgbWFudWFsbHkgbm90aWZ5CiAgICAgIGFueSBjaGFuZ2VzIGlmIHlvdSB3YW50IHRvIG9ic2VydmUgdGhpcyBwcm9wZXJ0eS4KICAgICAgRGVwZW5kZW5jeSBrZXlzIGhhdmUgbm8gZWZmZWN0IG9uIHZvbGF0aWxlIHByb3BlcnRpZXMgYXMgdGhleSBhcmUgZm9yIGNhY2hlCiAgICAgIGludmFsaWRhdGlvbiBhbmQgbm90aWZpY2F0aW9uIHdoZW4gY2FjaGVkIHZhbHVlIGlzIGludmFsaWRhdGVkLgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICBsZXQgb3V0c2lkZVNlcnZpY2UgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAgIHZhbHVlOiBjb21wdXRlZChmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiBPdXRzaWRlU2VydmljZS5nZXRWYWx1ZSgpOwogICAgICAgIH0pLnZvbGF0aWxlKCkKICAgICAgfSkuY3JlYXRlKCk7CiAgICAgIGBgYAogICAgICBAbWV0aG9kIHZvbGF0aWxlCiAgICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IHRoaXMKICAgICAgQGNoYWluYWJsZQogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90bzcudm9sYXRpbGUgPSBmdW5jdGlvbiB2b2xhdGlsZSgpIHsKICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgnU2V0dGluZyBhIGNvbXB1dGVkIHByb3BlcnR5IGFzIHZvbGF0aWxlIGhhcyBiZWVuIGRlcHJlY2F0ZWQuIEluc3RlYWQsIGNvbnNpZGVyIHVzaW5nIGEgbmF0aXZlIGdldHRlciB3aXRoIG5hdGl2ZSBjbGFzcyBzeW50YXguJywgZmFsc2UsIHsKICAgICAgICBpZDogJ2NvbXB1dGVkLXByb3BlcnR5LnZvbGF0aWxlJywKICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY19jb21wdXRlZC1wcm9wZXJ0eS12b2xhdGlsZScKICAgICAgfSkpOwogICAgICB0aGlzLl92b2xhdGlsZSA9IHRydWU7CiAgICB9CiAgICAvKioKICAgICAgQ2FsbCBvbiBhIGNvbXB1dGVkIHByb3BlcnR5IHRvIHNldCBpdCBpbnRvIHJlYWQtb25seSBtb2RlLiBXaGVuIGluIHRoaXMKICAgICAgbW9kZSB0aGUgY29tcHV0ZWQgcHJvcGVydHkgd2lsbCB0aHJvdyBhbiBlcnJvciB3aGVuIHNldC4KICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgRW1iZXJPYmplY3QsIHsgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgbGV0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgICAgZ3VpZDogY29tcHV0ZWQoZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gJ2d1aWQtZ3VpZC1ndWlkJzsKICAgICAgICB9KS5yZWFkT25seSgpCiAgICAgIH0pOwogICAgICBsZXQgcGVyc29uID0gUGVyc29uLmNyZWF0ZSgpOwogICAgICBwZXJzb24uc2V0KCdndWlkJywgJ25ldy1ndWlkJyk7IC8vIHdpbGwgdGhyb3cgYW4gZXhjZXB0aW9uCiAgICAgIGBgYAogICAgICBAbWV0aG9kIHJlYWRPbmx5CiAgICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IHRoaXMKICAgICAgQGNoYWluYWJsZQogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90bzcucmVhZE9ubHkgPSBmdW5jdGlvbiByZWFkT25seSgpIHsKICAgICAgdGhpcy5fcmVhZE9ubHkgPSB0cnVlOwogICAgICAoZmFsc2UgJiYgISghKHRoaXMuX3JlYWRPbmx5ICYmIHRoaXMuX3NldHRlciAmJiB0aGlzLl9zZXR0ZXIgIT09IHRoaXMuX2dldHRlcikpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnQ29tcHV0ZWQgcHJvcGVydGllcyB0aGF0IGRlZmluZSBhIHNldHRlciB1c2luZyB0aGUgbmV3IHN5bnRheCBjYW5ub3QgYmUgcmVhZC1vbmx5JywgISh0aGlzLl9yZWFkT25seSAmJiB0aGlzLl9zZXR0ZXIgJiYgdGhpcy5fc2V0dGVyICE9PSB0aGlzLl9nZXR0ZXIpKSk7CiAgICB9CiAgICAvKioKICAgICAgU2V0cyB0aGUgZGVwZW5kZW50IGtleXMgb24gdGhpcyBjb21wdXRlZCBwcm9wZXJ0eS4gUGFzcyBhbnkgbnVtYmVyIG9mCiAgICAgIGFyZ3VtZW50cyBjb250YWluaW5nIGtleSBwYXRocyB0aGF0IHRoaXMgY29tcHV0ZWQgcHJvcGVydHkgZGVwZW5kcyBvbi4KICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgRW1iZXJPYmplY3QsIHsgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgbGV0IFByZXNpZGVudCA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgICAgZnVsbE5hbWU6IGNvbXB1dGVkKCdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnLCBmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiB0aGlzLmdldCgnZmlyc3ROYW1lJykgKyAnICcgKyB0aGlzLmdldCgnbGFzdE5hbWUnKTsKICAgICAgICAgIC8vIFRlbGwgRW1iZXIgdGhhdCB0aGlzIGNvbXB1dGVkIHByb3BlcnR5IGRlcGVuZHMgb24gZmlyc3ROYW1lCiAgICAgICAgICAvLyBhbmQgbGFzdE5hbWUKICAgICAgICB9KQogICAgICB9KTsKICAgICAgbGV0IHByZXNpZGVudCA9IFByZXNpZGVudC5jcmVhdGUoewogICAgICAgIGZpcnN0TmFtZTogJ0JhcmFjaycsCiAgICAgICAgbGFzdE5hbWU6ICdPYmFtYScKICAgICAgfSk7CiAgICAgIHByZXNpZGVudC5nZXQoJ2Z1bGxOYW1lJyk7IC8vICdCYXJhY2sgT2JhbWEnCiAgICAgIGBgYAogICAgICBAbWV0aG9kIHByb3BlcnR5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBwYXRoKiB6ZXJvIG9yIG1vcmUgcHJvcGVydHkgcGF0aHMKICAgICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gdGhpcwogICAgICBAY2hhaW5hYmxlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvNy5wcm9wZXJ0eSA9IGZ1bmN0aW9uIHByb3BlcnR5KCkgewogICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdTZXR0aW5nIGRlcGVuZGVuY3kga2V5cyB1c2luZyB0aGUgYC5wcm9wZXJ0eSgpYCBtb2RpZmllciBoYXMgYmVlbiBkZXByZWNhdGVkLiBQYXNzIHRoZSBkZXBlbmRlbmN5IGtleXMgZGlyZWN0bHkgdG8gY29tcHV0ZWQgYXMgYXJndW1lbnRzIGluc3RlYWQuIElmIHlvdSBhcmUgdXNpbmcgYC5wcm9wZXJ0eSgpYCBvbiBhIGNvbXB1dGVkIHByb3BlcnR5IG1hY3JvLCBjb25zaWRlciByZWZhY3RvcmluZyB5b3VyIG1hY3JvIHRvIHJlY2VpdmUgYWRkaXRpb25hbCBkZXBlbmRlbnQga2V5cyBpbiBpdHMgaW5pdGlhbCBkZWNsYXJhdGlvbi4nLCBmYWxzZSwgewogICAgICAgIGlkOiAnY29tcHV0ZWQtcHJvcGVydHkucHJvcGVydHknLAogICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2NvbXB1dGVkLXByb3BlcnR5LXByb3BlcnR5JwogICAgICB9KSk7CgogICAgICB0aGlzLl9wcm9wZXJ0eS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfTsKCiAgICBfcHJvdG83Ll9wcm9wZXJ0eSA9IGZ1bmN0aW9uIF9wcm9wZXJ0eSgpIHsKICAgICAgdmFyIGFyZ3MgPSBbXTsKCiAgICAgIGZ1bmN0aW9uIGFkZEFyZyhwcm9wZXJ0eSkgewogICAgICAgIChmYWxzZSAmJiAoMCwgX2RlYnVnLndhcm4pKCJEZXBlbmRlbnQga2V5cyBjb250YWluaW5nIEBlYWNoIG9ubHkgd29yayBvbmUgbGV2ZWwgZGVlcC4gIiArICgiWW91IHVzZWQgdGhlIGtleSBcIiIgKyBwcm9wZXJ0eSArICJcIiB3aGljaCBpcyBpbnZhbGlkLiAiKSArICJQbGVhc2UgY3JlYXRlIGFuIGludGVybWVkaWFyeSBjb21wdXRlZCBwcm9wZXJ0eS4iLCBERUVQX0VBQ0hfUkVHRVgudGVzdChwcm9wZXJ0eSkgPT09IGZhbHNlLCB7CiAgICAgICAgICBpZDogJ2VtYmVyLW1ldGFsLmNvbXB1dGVkLWRlZXAtZWFjaCcKICAgICAgICB9KSk7CiAgICAgICAgYXJncy5wdXNoKHByb3BlcnR5KTsKICAgICAgfQoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsKICAgICAgICBleHBhbmRQcm9wZXJ0aWVzKGkgPCAwIHx8IGFyZ3VtZW50cy5sZW5ndGggPD0gaSA/IHVuZGVmaW5lZCA6IGFyZ3VtZW50c1tpXSwgYWRkQXJnKTsKICAgICAgfQoKICAgICAgdGhpcy5fZGVwZW5kZW50S2V5cyA9IGFyZ3M7CiAgICB9CiAgICAvKioKICAgICAgSW4gc29tZSBjYXNlcywgeW91IG1heSB3YW50IHRvIGFubm90YXRlIGNvbXB1dGVkIHByb3BlcnRpZXMgd2l0aCBhZGRpdGlvbmFsCiAgICAgIG1ldGFkYXRhIGFib3V0IGhvdyB0aGV5IGZ1bmN0aW9uIG9yIHdoYXQgdmFsdWVzIHRoZXkgb3BlcmF0ZSBvbi4gRm9yIGV4YW1wbGUsCiAgICAgIGNvbXB1dGVkIHByb3BlcnR5IGZ1bmN0aW9ucyBtYXkgY2xvc2Ugb3ZlciB2YXJpYWJsZXMgdGhhdCBhcmUgdGhlbiBubyBsb25nZXIKICAgICAgYXZhaWxhYmxlIGZvciBpbnRyb3NwZWN0aW9uLgogICAgICBZb3UgY2FuIHBhc3MgYSBoYXNoIG9mIHRoZXNlIHZhbHVlcyB0byBhIGNvbXB1dGVkIHByb3BlcnR5IGxpa2UgdGhpczoKICAgICAgYGBgCiAgICAgIGltcG9ydCB7IGNvbXB1dGVkIH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgIGltcG9ydCBQZXJzb24gZnJvbSAnbXktYXBwL3V0aWxzL3BlcnNvbic7CiAgICAgIHBlcnNvbjogY29tcHV0ZWQoZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IHBlcnNvbklkID0gdGhpcy5nZXQoJ3BlcnNvbklkJyk7CiAgICAgICAgcmV0dXJuIFBlcnNvbi5jcmVhdGUoeyBpZDogcGVyc29uSWQgfSk7CiAgICAgIH0pLm1ldGEoeyB0eXBlOiBQZXJzb24gfSkKICAgICAgYGBgCiAgICAgIFRoZSBoYXNoIHRoYXQgeW91IHBhc3MgdG8gdGhlIGBtZXRhKClgIGZ1bmN0aW9uIHdpbGwgYmUgc2F2ZWQgb24gdGhlCiAgICAgIGNvbXB1dGVkIHByb3BlcnR5IGRlc2NyaXB0b3IgdW5kZXIgdGhlIGBfbWV0YWAga2V5LiBFbWJlciBydW50aW1lCiAgICAgIGV4cG9zZXMgYSBwdWJsaWMgQVBJIGZvciByZXRyaWV2aW5nIHRoZXNlIHZhbHVlcyBmcm9tIGNsYXNzZXMsCiAgICAgIHZpYSB0aGUgYG1ldGFGb3JQcm9wZXJ0eSgpYCBmdW5jdGlvbi4KICAgICAgQG1ldGhvZCBtZXRhCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBtZXRhCiAgICAgIEBjaGFpbmFibGUKICAgICAgQHB1YmxpYwogICAgKi8KICAgIC8vIGludmFsaWRhdGUgY2FjaGUgd2hlbiBDUCBrZXkgY2hhbmdlcwogICAgOwoKICAgIF9wcm90bzcuZGlkQ2hhbmdlID0gZnVuY3Rpb24gZGlkQ2hhbmdlKG9iaiwga2V5TmFtZSkgewogICAgICAvLyBfc3VzcGVuZGVkIGlzIHNldCB2aWEgYSBDUC5zZXQgdG8gZW5zdXJlIHdlIGRvbid0IGNsZWFyCiAgICAgIC8vIHRoZSBjYWNoZWQgdmFsdWUgc2V0IGJ5IHRoZSBzZXR0ZXIKICAgICAgaWYgKHRoaXMuX3ZvbGF0aWxlIHx8IHRoaXMuX3N1c3BlbmRlZCA9PT0gb2JqKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIGRvbid0IGNyZWF0ZSBvYmplY3RzIGp1c3QgdG8gaW52YWxpZGF0ZQoKCiAgICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkob2JqKTsKCiAgICAgIGlmIChtZXRhJCQxID09PSBudWxsIHx8IG1ldGEkJDEuc291cmNlICE9PSBvYmopIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBjYWNoZSA9IHBlZWtDYWNoZUZvcihvYmopOwoKICAgICAgaWYgKGNhY2hlICE9PSB1bmRlZmluZWQgJiYgY2FjaGUuZGVsZXRlKGtleU5hbWUpKSB7CiAgICAgICAgcmVtb3ZlRGVwZW5kZW50S2V5cyh0aGlzLCBvYmosIGtleU5hbWUsIG1ldGEkJDEpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzcuZ2V0ID0gZnVuY3Rpb24gZ2V0KG9iaiwga2V5TmFtZSkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIGlmICh0aGlzLl92b2xhdGlsZSkgewogICAgICAgIHJldHVybiB0aGlzLl9nZXR0ZXIuY2FsbChvYmosIGtleU5hbWUpOwogICAgICB9CgogICAgICB2YXIgY2FjaGUgPSBnZXRDYWNoZUZvcihvYmopOwogICAgICB7CiAgICAgICAgdmFyIHByb3BlcnR5VGFnID0gdGFnRm9yUHJvcGVydHkob2JqLCBrZXlOYW1lKTsKICAgICAgICB2YXIgcmV0OwoKICAgICAgICBpZiAoY2FjaGUuaGFzKGtleU5hbWUpICYmICgwLCBfcmVmZXJlbmNlLnZhbGlkYXRlKShwcm9wZXJ0eVRhZywgZ2V0TGFzdFJldmlzaW9uRm9yKG9iaiwga2V5TmFtZSkpKSB7CiAgICAgICAgICByZXQgPSBjYWNoZS5nZXQoa2V5TmFtZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vIEZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSwgd2Ugb25seSB0aHJvdyBpZiB0aGUgQ1AgaGFzIGFueSBkZXBlbmRlbmNpZXMuIENQcyB3aXRob3V0IGRlcGVuZGVuY2llcwogICAgICAgICAgLy8gc2hvdWxkIGJlIGFsbG93ZWQsIGV2ZW4gYWZ0ZXIgdGhlIG9iamVjdCBoYXMgYmVlbiBkZXN0cm95ZWQsIHdoaWNoIGlzIHdoeSB3ZSBjaGVjayBfZGVwZW5kZW50S2V5cy4KICAgICAgICAgIChmYWxzZSAmJiAhKHRoaXMuX2RlcGVuZGVudEtleXMgPT09IHVuZGVmaW5lZCB8fCAhKDAsIF9tZXRhMi5tZXRhKShvYmopLmlzTWV0YURlc3Ryb3llZCgpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF0dGVtcHRlZCB0byBhY2Nlc3MgdGhlIGNvbXB1dGVkICIgKyBvYmogKyAiLiIgKyBrZXlOYW1lICsgIiBvbiBhIGRlc3Ryb3llZCBvYmplY3QsIHdoaWNoIGlzIG5vdCBhbGxvd2VkIiwgdGhpcy5fZGVwZW5kZW50S2V5cyA9PT0gdW5kZWZpbmVkIHx8ICEoMCwgX21ldGEyLm1ldGEpKG9iaikuaXNNZXRhRGVzdHJveWVkKCkpKTsKICAgICAgICAgIHZhciB1cHN0cmVhbVRhZyA9IHVuZGVmaW5lZDsKCiAgICAgICAgICBpZiAodGhpcy5fYXV0byA9PT0gdHJ1ZSkgewogICAgICAgICAgICB1cHN0cmVhbVRhZyA9IHRyYWNrKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICByZXQgPSBfdGhpczMuX2dldHRlci5jYWxsKG9iaiwga2V5TmFtZSk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgLy8gQ3JlYXRlIGEgdHJhY2tlciB0aGF0IGFic29yYnMgYW55IHRyYWNrYWJsZSBhY3Rpb25zIGluc2lkZSB0aGUgQ1AKICAgICAgICAgICAgdW50cmFjayhmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgcmV0ID0gX3RoaXMzLl9nZXR0ZXIuY2FsbChvYmosIGtleU5hbWUpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAodGhpcy5fZGVwZW5kZW50S2V5cyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHZhciB0YWcgPSAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShnZXRDaGFpblRhZ3NGb3JLZXlzKG9iaiwgdGhpcy5fZGVwZW5kZW50S2V5cykpOwogICAgICAgICAgICB1cHN0cmVhbVRhZyA9IHVwc3RyZWFtVGFnID09PSB1bmRlZmluZWQgPyB0YWcgOiAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShbdXBzdHJlYW1UYWcsIHRhZ10pOwogICAgICAgICAgfQoKICAgICAgICAgIGlmICh1cHN0cmVhbVRhZyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICgwLCBfcmVmZXJlbmNlLnVwZGF0ZSkocHJvcGVydHlUYWcsIHVwc3RyZWFtVGFnKTsKICAgICAgICAgIH0KCiAgICAgICAgICBzZXRMYXN0UmV2aXNpb25Gb3Iob2JqLCBrZXlOYW1lLCAoMCwgX3JlZmVyZW5jZS52YWx1ZSkocHJvcGVydHlUYWcpKTsKICAgICAgICAgIGNhY2hlLnNldChrZXlOYW1lLCByZXQpOwogICAgICAgICAgZmluaXNoTGF6eUNoYWlucyhvYmosIGtleU5hbWUsIHJldCk7CiAgICAgICAgfQoKICAgICAgICBjb25zdW1lKHByb3BlcnR5VGFnKTsgLy8gQWRkIHRoZSB0YWcgb2YgdGhlIHJldHVybmVkIHZhbHVlIGlmIGl0IGlzIGFuIGFycmF5LCBzaW5jZSBhcnJheXMKICAgICAgICAvLyBzaG91bGQgYWx3YXlzIGNhdXNlIHVwZGF0ZXMgaWYgdGhleSBhcmUgY29uc3VtZWQgYW5kIHRoZW4gY2hhbmdlZAoKICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShyZXQpIHx8ICgwLCBfdXRpbHMuaXNFbWJlckFycmF5KShyZXQpKSB7CiAgICAgICAgICBjb25zdW1lKHRhZ0ZvclByb3BlcnR5KHJldCwgJ1tdJykpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG83LnNldCA9IGZ1bmN0aW9uIHNldChvYmosIGtleU5hbWUsIHZhbHVlJCQxKSB7CiAgICAgIGlmICh0aGlzLl9yZWFkT25seSkgewogICAgICAgIHRoaXMuX3Rocm93UmVhZE9ubHlFcnJvcihvYmosIGtleU5hbWUpOwogICAgICB9CgogICAgICBpZiAoIXRoaXMuX3NldHRlcikgewogICAgICAgIHJldHVybiB0aGlzLmNsb2JiZXJTZXQob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLl92b2xhdGlsZSkgewogICAgICAgIHJldHVybiB0aGlzLnZvbGF0aWxlU2V0KG9iaiwga2V5TmFtZSwgdmFsdWUkJDEpOwogICAgICB9CgogICAgICB7CiAgICAgICAgdmFyIHJldDsKCiAgICAgICAgdHJ5IHsKICAgICAgICAgIGJlZ2luUHJvcGVydHlDaGFuZ2VzKCk7CiAgICAgICAgICByZXQgPSB0aGlzLl9zZXQob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgICAgICAgICBmaW5pc2hMYXp5Q2hhaW5zKG9iaiwga2V5TmFtZSwgcmV0KTsKICAgICAgICAgIHZhciBwcm9wZXJ0eVRhZyA9IHRhZ0ZvclByb3BlcnR5KG9iaiwga2V5TmFtZSk7CgogICAgICAgICAgaWYgKHRoaXMuX2RlcGVuZGVudEtleXMgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHByb3BlcnR5VGFnLCAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShnZXRDaGFpblRhZ3NGb3JLZXlzKG9iaiwgdGhpcy5fZGVwZW5kZW50S2V5cykpKTsKICAgICAgICAgIH0KCiAgICAgICAgICBzZXRMYXN0UmV2aXNpb25Gb3Iob2JqLCBrZXlOYW1lLCAoMCwgX3JlZmVyZW5jZS52YWx1ZSkocHJvcGVydHlUYWcpKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgZW5kUHJvcGVydHlDaGFuZ2VzKCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzcuX3Rocm93UmVhZE9ubHlFcnJvciA9IGZ1bmN0aW9uIF90aHJvd1JlYWRPbmx5RXJyb3Iob2JqLCBrZXlOYW1lKSB7CiAgICAgIHRocm93IG5ldyBfZXJyb3IuZGVmYXVsdCgiQ2Fubm90IHNldCByZWFkLW9ubHkgcHJvcGVydHkgXCIiICsga2V5TmFtZSArICJcIiBvbiBvYmplY3Q6ICIgKyAoMCwgX3V0aWxzLmluc3BlY3QpKG9iaikpOwogICAgfTsKCiAgICBfcHJvdG83LmNsb2JiZXJTZXQgPSBmdW5jdGlvbiBjbG9iYmVyU2V0KG9iaiwga2V5TmFtZSwgdmFsdWUkJDEpIHsKICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgiVGhlICIgKyAoMCwgX3V0aWxzLnRvU3RyaW5nKShvYmopICsgIiMiICsga2V5TmFtZSArICIgY29tcHV0ZWQgcHJvcGVydHkgd2FzIGp1c3Qgb3ZlcnJpZGVuLiBUaGlzIHJlbW92ZXMgdGhlIGNvbXB1dGVkIHByb3BlcnR5IGFuZCByZXBsYWNlcyBpdCB3aXRoIGEgcGxhaW4gdmFsdWUsIGFuZCBoYXMgYmVlbiBkZXByZWNhdGVkLiBJZiB5b3Ugd2FudCB0aGlzIGJlaGF2aW9yLCBjb25zaWRlciBkZWZpbmluZyBhIHNldHRlciB3aGljaCBkb2VzIGl0IG1hbnVhbGx5LiIsIGZhbHNlLCB7CiAgICAgICAgaWQ6ICdjb21wdXRlZC1wcm9wZXJ0eS5vdmVycmlkZScsCiAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfY29tcHV0ZWQtcHJvcGVydHktb3ZlcnJpZGUnCiAgICAgIH0pKTsKICAgICAgdmFyIGNhY2hlZFZhbHVlID0gZ2V0Q2FjaGVkVmFsdWVGb3Iob2JqLCBrZXlOYW1lKTsKICAgICAgZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCBudWxsLCBjYWNoZWRWYWx1ZSk7CgogICAgICBfc2V0MihvYmosIGtleU5hbWUsIHZhbHVlJCQxKTsKCiAgICAgIHJldHVybiB2YWx1ZSQkMTsKICAgIH07CgogICAgX3Byb3RvNy52b2xhdGlsZVNldCA9IGZ1bmN0aW9uIHZvbGF0aWxlU2V0KG9iaiwga2V5TmFtZSwgdmFsdWUkJDEpIHsKICAgICAgcmV0dXJuIHRoaXMuX3NldHRlci5jYWxsKG9iaiwga2V5TmFtZSwgdmFsdWUkJDEpOwogICAgfTsKCiAgICBfcHJvdG83LnNldFdpdGhTdXNwZW5kID0gZnVuY3Rpb24gc2V0V2l0aFN1c3BlbmQob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSkgewogICAgICB2YXIgb2xkU3VzcGVuZGVkID0gdGhpcy5fc3VzcGVuZGVkOwogICAgICB0aGlzLl9zdXNwZW5kZWQgPSBvYmo7CgogICAgICB0cnkgewogICAgICAgIHJldHVybiB0aGlzLl9zZXQob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgICAgIH0gZmluYWxseSB7CiAgICAgICAgdGhpcy5fc3VzcGVuZGVkID0gb2xkU3VzcGVuZGVkOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzcuX3NldCA9IGZ1bmN0aW9uIF9zZXQob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSkgewogICAgICB2YXIgY2FjaGUgPSBnZXRDYWNoZUZvcihvYmopOwogICAgICB2YXIgaGFkQ2FjaGVkVmFsdWUgPSBjYWNoZS5oYXMoa2V5TmFtZSk7CiAgICAgIHZhciBjYWNoZWRWYWx1ZSA9IGNhY2hlLmdldChrZXlOYW1lKTsKICAgICAgdmFyIHJldDsKICAgICAgewogICAgICAgIHNldE9ic2VydmVyU3VzcGVuZGVkKG9iaiwga2V5TmFtZSwgdHJ1ZSk7CgogICAgICAgIHRyeSB7CiAgICAgICAgICByZXQgPSB0aGlzLl9zZXR0ZXIuY2FsbChvYmosIGtleU5hbWUsIHZhbHVlJCQxLCBjYWNoZWRWYWx1ZSk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIHNldE9ic2VydmVyU3VzcGVuZGVkKG9iaiwga2V5TmFtZSwgZmFsc2UpOwogICAgICAgIH0KICAgICAgfSAvLyBhbGxvd3Mgc2V0dGVyIHRvIHJldHVybiB0aGUgc2FtZSB2YWx1ZSB0aGF0IGlzIGNhY2hlZCBhbHJlYWR5CgogICAgICBpZiAoaGFkQ2FjaGVkVmFsdWUgJiYgY2FjaGVkVmFsdWUgPT09IHJldCkgewogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0KCiAgICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5tZXRhKShvYmopOwogICAgICBjYWNoZS5zZXQoa2V5TmFtZSwgcmV0KTsKICAgICAgbm90aWZ5UHJvcGVydHlDaGFuZ2Uob2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgICAgcmV0dXJuIHJldDsKICAgIH0KICAgIC8qIGNhbGxlZCBiZWZvcmUgcHJvcGVydHkgaXMgb3ZlcnJpZGRlbiAqLwogICAgOwoKICAgIF9wcm90bzcudGVhcmRvd24gPSBmdW5jdGlvbiB0ZWFyZG93bihvYmosIGtleU5hbWUsIG1ldGEkJDEpIHsKICAgICAgaWYgKCF0aGlzLl92b2xhdGlsZSkgewogICAgICAgIHZhciBjYWNoZSA9IHBlZWtDYWNoZUZvcihvYmopOwoKICAgICAgICBpZiAoY2FjaGUgIT09IHVuZGVmaW5lZCAmJiBjYWNoZS5kZWxldGUoa2V5TmFtZSkpIHsKICAgICAgICAgIHJlbW92ZURlcGVuZGVudEtleXModGhpcywgb2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIF9Db21wdXRlZERlc2NyaXB0b3IucHJvdG90eXBlLnRlYXJkb3duLmNhbGwodGhpcywgb2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgIH07CgogICAgcmV0dXJuIENvbXB1dGVkUHJvcGVydHk7CiAgfShDb21wdXRlZERlc2NyaXB0b3IpOwoKICBfZXhwb3J0cy5Db21wdXRlZFByb3BlcnR5ID0gQ29tcHV0ZWRQcm9wZXJ0eTsKICB7CiAgICBDb21wdXRlZFByb3BlcnR5LnByb3RvdHlwZS5hdXRvID0gZnVuY3Rpb24gKCkgewogICAgICB0aGlzLl9hdXRvID0gdHJ1ZTsKICAgIH07CiAgfSAvLyBUT0RPOiBUaGlzIGNsYXNzIGNhbiBiZSBzdmVsdGVkIG9uY2UgYG1ldGFgIGhhcyBiZWVuIGRlcHJlY2F0ZWQKCiAgdmFyIENvbXB1dGVkRGVjb3JhdG9ySW1wbCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRnVuY3Rpb24pIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDb21wdXRlZERlY29yYXRvckltcGwsIF9GdW5jdGlvbik7CgogICAgZnVuY3Rpb24gQ29tcHV0ZWREZWNvcmF0b3JJbXBsKCkgewogICAgICByZXR1cm4gX0Z1bmN0aW9uLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvOCA9IENvbXB1dGVkRGVjb3JhdG9ySW1wbC5wcm90b3R5cGU7CgogICAgX3Byb3RvOC5yZWFkT25seSA9IGZ1bmN0aW9uIHJlYWRPbmx5KCkgewogICAgICBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKHRoaXMpLnJlYWRPbmx5KCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICBfcHJvdG84LnZvbGF0aWxlID0gZnVuY3Rpb24gdm9sYXRpbGUoKSB7CiAgICAgIGRlc2NyaXB0b3JGb3JEZWNvcmF0b3IodGhpcykudm9sYXRpbGUoKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9OwoKICAgIF9wcm90bzgucHJvcGVydHkgPSBmdW5jdGlvbiBwcm9wZXJ0eSgpIHsKICAgICAgdmFyIF9kZXNjcmlwdG9yRm9yRGVjb3JhdDsKCiAgICAgIChfZGVzY3JpcHRvckZvckRlY29yYXQgPSBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKHRoaXMpKS5wcm9wZXJ0eS5hcHBseShfZGVzY3JpcHRvckZvckRlY29yYXQsIGFyZ3VtZW50cyk7CgogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgX3Byb3RvOC5tZXRhID0gZnVuY3Rpb24gbWV0YShtZXRhJCQxKSB7CiAgICAgIHZhciBwcm9wID0gZGVzY3JpcHRvckZvckRlY29yYXRvcih0aGlzKTsKCiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIHByb3AuX21ldGEgfHwge307CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcHJvcC5fbWV0YSA9IG1ldGEkJDE7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgIH0gLy8gVE9ETzogUmVtb3ZlIHRoaXMgd2hlbiB3ZSBjYW4gcHJvdmlkZSBhbHRlcm5hdGl2ZXMgaW4gdGhlIGVjb3N5c3RlbSB0bwogICAgLy8gYWRkb25zIHN1Y2ggYXMgZW1iZXItbWFjcm8taGVscGVycyB0aGF0IHVzZSBpdC4KICAgIDsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKENvbXB1dGVkRGVjb3JhdG9ySW1wbCwgW3sKICAgICAga2V5OiAiX2dldHRlciIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKHRoaXMpLl9nZXR0ZXI7CiAgICAgIH0gLy8gVE9ETzogUmVmYWN0b3IgdGhpcywgdGhpcyBpcyBhbiBpbnRlcm5hbCBBUEkgb25seQoKICAgIH0sIHsKICAgICAga2V5OiAiZW51bWVyYWJsZSIsCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHZhbHVlJCQxKSB7CiAgICAgICAgZGVzY3JpcHRvckZvckRlY29yYXRvcih0aGlzKS5lbnVtZXJhYmxlID0gdmFsdWUkJDE7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBDb21wdXRlZERlY29yYXRvckltcGw7CiAgfSgoMCwgX2VtYmVyQmFiZWwud3JhcE5hdGl2ZVN1cGVyKShGdW5jdGlvbikpOwoKICBmdW5jdGlvbiBjb21wdXRlZCgpIHsKICAgIGZvciAodmFyIF9sZW4zID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuMyksIF9rZXk0ID0gMDsgX2tleTQgPCBfbGVuMzsgX2tleTQrKykgewogICAgICBhcmdzW19rZXk0XSA9IGFyZ3VtZW50c1tfa2V5NF07CiAgICB9CgogICAgKGZhbHNlICYmICEoIShpc0VsZW1lbnREZXNjcmlwdG9yKGFyZ3Muc2xpY2UoMCwgMykpICYmIGFyZ3MubGVuZ3RoID09PSA1ICYmIGFyZ3NbNF0gPT09IHRydWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkBjb21wdXRlZCBjYW4gb25seSBiZSB1c2VkIGRpcmVjdGx5IGFzIGEgbmF0aXZlIGRlY29yYXRvci4gSWYgeW91J3JlIHVzaW5nIHRyYWNrZWQgaW4gY2xhc3NpYyBjbGFzc2VzLCBhZGQgcGFyZW50aGVzaXMgdG8gY2FsbCBpdCBsaWtlIGEgZnVuY3Rpb246IGNvbXB1dGVkKCkiLCAhKGlzRWxlbWVudERlc2NyaXB0b3IoYXJncy5zbGljZSgwLCAzKSkgJiYgYXJncy5sZW5ndGggPT09IDUgJiYgYXJnc1s0XSA9PT0gdHJ1ZSkpKTsKCiAgICBpZiAoaXNFbGVtZW50RGVzY3JpcHRvcihhcmdzKSkgewogICAgICAoZmFsc2UgJiYgIShCb29sZWFuKHRydWUKICAgICAgLyogRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUICovCiAgICAgICkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnTmF0aXZlIGRlY29yYXRvcnMgYXJlIG5vdCBlbmFibGVkIHdpdGhvdXQgdGhlIEVNQkVSX05BVElWRV9ERUNPUkFUT1JfU1VQUE9SVCBmbGFnLiBJZiB5b3UgYXJlIHVzaW5nIGNvbXB1dGVkIGluIGEgY2xhc3NpYyBjbGFzcywgYWRkIHBhcmVudGhlc2lzIHRvIGl0OiBjb21wdXRlZCgpJywgQm9vbGVhbih0cnVlKSkpOwogICAgICB2YXIgZGVjb3JhdG9yID0gbWFrZUNvbXB1dGVkRGVjb3JhdG9yKG5ldyBDb21wdXRlZFByb3BlcnR5KFtdKSwgQ29tcHV0ZWREZWNvcmF0b3JJbXBsKTsKICAgICAgcmV0dXJuIGRlY29yYXRvcihhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdKTsKICAgIH0KCiAgICByZXR1cm4gbWFrZUNvbXB1dGVkRGVjb3JhdG9yKG5ldyBDb21wdXRlZFByb3BlcnR5KGFyZ3MpLCBDb21wdXRlZERlY29yYXRvckltcGwpOwogIH0KICAvKioKICAgIEFsbG93cyBjaGVja2luZyBpZiBhIGdpdmVuIHByb3BlcnR5IG9uIGFuIG9iamVjdCBpcyBhIGNvbXB1dGVkIHByb3BlcnR5LiBGb3IgdGhlIG1vc3QgcGFydCwKICAgIHRoaXMgZG9lc24ndCBtYXR0ZXIgKHlvdSB3b3VsZCBub3JtYWxseSBqdXN0IGFjY2VzcyB0aGUgcHJvcGVydHkgZGlyZWN0bHkgYW5kIHVzZSBpdHMgdmFsdWUpLAogICAgYnV0IGZvciBzb21lIHRvb2xpbmcgc3BlY2lmaWMgc2NlbmFyaW9zIChlLmcuIHRoZSBlbWJlci1pbnNwZWN0b3IpIGl0IGlzIGltcG9ydGFudCB0bwogICAgZGlmZmVyZW50aWF0ZSBpZiBhIHByb3BlcnR5IGlzIGEgY29tcHV0ZWQgcHJvcGVydHkgb3IgYSAibm9ybWFsIiBwcm9wZXJ0eS4KICAKICAgIFRoaXMgd2lsbCB3b3JrIG9uIGVpdGhlciBhIGNsYXNzJ3MgcHJvdG90eXBlIG9yIGFuIGluc3RhbmNlIGl0c2VsZi4KICAKICAgIEBzdGF0aWMKICAgIEBtZXRob2QgaXNDb21wdXRlZAogICAgQGZvciBAZW1iZXIvZGVidWcKICAgIEBwcml2YXRlCiAgICovCgoKICBmdW5jdGlvbiBpc0NvbXB1dGVkKG9iaiwga2V5KSB7CiAgICByZXR1cm4gQm9vbGVhbihkZXNjcmlwdG9yRm9yUHJvcGVydHkob2JqLCBrZXkpKTsKICB9CgogIHZhciBfZ2xvYmFsc0NvbXB1dGVkID0gY29tcHV0ZWQuYmluZChudWxsKTsKCiAgX2V4cG9ydHMuX2dsb2JhbHNDb21wdXRlZCA9IF9nbG9iYWxzQ29tcHV0ZWQ7CiAgdmFyIENPTlNVTUVEID0gT2JqZWN0LmZyZWV6ZSh7fSk7CgogIGZ1bmN0aW9uIGFsaWFzKGFsdEtleSkgewogICAgKGZhbHNlICYmICEoIWlzRWxlbWVudERlc2NyaXB0b3IoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGFsaWFzIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgYWx0S2V5YCBwYXJhbWV0ZXInLCAhaXNFbGVtZW50RGVzY3JpcHRvcihBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIG1ha2VDb21wdXRlZERlY29yYXRvcihuZXcgQWxpYXNlZFByb3BlcnR5KGFsdEtleSksIEFsaWFzRGVjb3JhdG9ySW1wbCk7CiAgfSAvLyBUT0RPOiBUaGlzIGNsYXNzIGNhbiBiZSBzdmVsdGVkIG9uY2UgYG1ldGFgIGhhcyBiZWVuIGRlcHJlY2F0ZWQKCgogIHZhciBBbGlhc0RlY29yYXRvckltcGwgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Z1bmN0aW9uMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEFsaWFzRGVjb3JhdG9ySW1wbCwgX0Z1bmN0aW9uMik7CgogICAgZnVuY3Rpb24gQWxpYXNEZWNvcmF0b3JJbXBsKCkgewogICAgICByZXR1cm4gX0Z1bmN0aW9uMi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzkgPSBBbGlhc0RlY29yYXRvckltcGwucHJvdG90eXBlOwoKICAgIF9wcm90bzkucmVhZE9ubHkgPSBmdW5jdGlvbiByZWFkT25seSgpIHsKICAgICAgZGVzY3JpcHRvckZvckRlY29yYXRvcih0aGlzKS5yZWFkT25seSgpOwogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgX3Byb3RvOS5vbmVXYXkgPSBmdW5jdGlvbiBvbmVXYXkoKSB7CiAgICAgIGRlc2NyaXB0b3JGb3JEZWNvcmF0b3IodGhpcykub25lV2F5KCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICBfcHJvdG85Lm1ldGEgPSBmdW5jdGlvbiBtZXRhKG1ldGEkJDEpIHsKICAgICAgdmFyIHByb3AgPSBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKHRoaXMpOwoKICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gcHJvcC5fbWV0YSB8fCB7fTsKICAgICAgfSBlbHNlIHsKICAgICAgICBwcm9wLl9tZXRhID0gbWV0YSQkMTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gQWxpYXNEZWNvcmF0b3JJbXBsOwogIH0oKDAsIF9lbWJlckJhYmVsLndyYXBOYXRpdmVTdXBlcikoRnVuY3Rpb24pKTsKCiAgdmFyIEFsaWFzZWRQcm9wZXJ0eSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ29tcHV0ZWREZXNjcmlwdG9yMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEFsaWFzZWRQcm9wZXJ0eSwgX0NvbXB1dGVkRGVzY3JpcHRvcjIpOwoKICAgIGZ1bmN0aW9uIEFsaWFzZWRQcm9wZXJ0eShhbHRLZXkpIHsKICAgICAgdmFyIF90aGlzNDsKCiAgICAgIF90aGlzNCA9IF9Db21wdXRlZERlc2NyaXB0b3IyLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXM0LmFsdEtleSA9IGFsdEtleTsKICAgICAgcmV0dXJuIF90aGlzNDsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTAgPSBBbGlhc2VkUHJvcGVydHkucHJvdG90eXBlOwoKICAgIF9wcm90bzEwLnNldHVwID0gZnVuY3Rpb24gc2V0dXAob2JqLCBrZXlOYW1lLCBwcm9wZXJ0eURlc2MsIG1ldGEkJDEpIHsKICAgICAgKGZhbHNlICYmICEodGhpcy5hbHRLZXkgIT09IGtleU5hbWUpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiU2V0dGluZyBhbGlhcyAnIiArIGtleU5hbWUgKyAiJyBvbiBzZWxmIiwgdGhpcy5hbHRLZXkgIT09IGtleU5hbWUpKTsKCiAgICAgIF9Db21wdXRlZERlc2NyaXB0b3IyLnByb3RvdHlwZS5zZXR1cC5jYWxsKHRoaXMsIG9iaiwga2V5TmFtZSwgcHJvcGVydHlEZXNjLCBtZXRhJCQxKTsKICAgIH07CgogICAgX3Byb3RvMTAudGVhcmRvd24gPSBmdW5jdGlvbiB0ZWFyZG93bihvYmosIGtleU5hbWUsIG1ldGEkJDEpIHsKICAgICAgX0NvbXB1dGVkRGVzY3JpcHRvcjIucHJvdG90eXBlLnRlYXJkb3duLmNhbGwodGhpcywgb2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgIH07CgogICAgX3Byb3RvMTAud2lsbFdhdGNoID0gZnVuY3Rpb24gd2lsbFdhdGNoKG9iaiwga2V5TmFtZSwgbWV0YSQkMSkge307CgogICAgX3Byb3RvMTAuZ2V0ID0gZnVuY3Rpb24gZ2V0KG9iaiwga2V5TmFtZSkgewogICAgICB2YXIgX3RoaXM1ID0gdGhpczsKCiAgICAgIHZhciByZXQ7CiAgICAgIHsKICAgICAgICB2YXIgcHJvcGVydHlUYWcgPSB0YWdGb3JQcm9wZXJ0eShvYmosIGtleU5hbWUpOyAvLyBXZSBkb24ndCB1c2UgdGhlIHRhZyBzaW5jZSBDUHMgYXJlIG5vdCBhdXRvbWF0aWMsIHdlIGp1c3Qgd2FudCB0byBhdm9pZAogICAgICAgIC8vIGFueXRoaW5nIHRyYWNraW5nIHdoaWxlIHdlIGdldCB0aGUgYWx0S2V5CgogICAgICAgIHVudHJhY2soZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0ID0gX2dldDIob2JqLCBfdGhpczUuYWx0S2V5KTsKICAgICAgICB9KTsKICAgICAgICB2YXIgbGFzdFJldmlzaW9uID0gZ2V0TGFzdFJldmlzaW9uRm9yKG9iaiwga2V5TmFtZSk7CgogICAgICAgIGlmICghKDAsIF9yZWZlcmVuY2UudmFsaWRhdGUpKHByb3BlcnR5VGFnLCBsYXN0UmV2aXNpb24pKSB7CiAgICAgICAgICAoMCwgX3JlZmVyZW5jZS51cGRhdGUpKHByb3BlcnR5VGFnLCAoMCwgX3JlZmVyZW5jZS5jb21iaW5lKShnZXRDaGFpblRhZ3NGb3JLZXkob2JqLCB0aGlzLmFsdEtleSkpKTsKICAgICAgICAgIHNldExhc3RSZXZpc2lvbkZvcihvYmosIGtleU5hbWUsICgwLCBfcmVmZXJlbmNlLnZhbHVlKShwcm9wZXJ0eVRhZykpOwogICAgICAgICAgZmluaXNoTGF6eUNoYWlucyhvYmosIGtleU5hbWUsIHJldCk7CiAgICAgICAgfQoKICAgICAgICBjb25zdW1lKHByb3BlcnR5VGFnKTsKICAgICAgfQogICAgICByZXR1cm4gcmV0OwogICAgfTsKCiAgICBfcHJvdG8xMC51bmNvbnN1bWUgPSBmdW5jdGlvbiB1bmNvbnN1bWUob2JqLCBrZXlOYW1lLCBtZXRhJCQxKSB7CiAgICAgIHZhciB3YXNDb25zdW1lZCA9IGdldENhY2hlZFZhbHVlRm9yKG9iaiwga2V5TmFtZSkgPT09IENPTlNVTUVEOwoKICAgICAgaWYgKHdhc0NvbnN1bWVkIHx8IG1ldGEkJDEucGVla1dhdGNoaW5nKGtleU5hbWUpID4gMCkgewogICAgICAgIHJlbW92ZURlcGVuZGVudEtleXModGhpcywgb2JqLCBrZXlOYW1lLCBtZXRhJCQxKTsKICAgICAgfQoKICAgICAgaWYgKHdhc0NvbnN1bWVkKSB7CiAgICAgICAgZ2V0Q2FjaGVGb3Iob2JqKS5kZWxldGUoa2V5TmFtZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTAuY29uc3VtZSA9IGZ1bmN0aW9uIGNvbnN1bWUob2JqLCBrZXlOYW1lLCBtZXRhJCQxKSB7CiAgICAgIHZhciBjYWNoZSA9IGdldENhY2hlRm9yKG9iaik7CgogICAgICBpZiAoY2FjaGUuZ2V0KGtleU5hbWUpICE9PSBDT05TVU1FRCkgewogICAgICAgIGNhY2hlLnNldChrZXlOYW1lLCBDT05TVU1FRCk7CiAgICAgICAgYWRkRGVwZW5kZW50S2V5cyh0aGlzLCBvYmosIGtleU5hbWUsIG1ldGEkJDEpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzEwLnNldCA9IGZ1bmN0aW9uIHNldChvYmosIF9rZXlOYW1lLCB2YWx1ZSQkMSkgewogICAgICByZXR1cm4gX3NldDIob2JqLCB0aGlzLmFsdEtleSwgdmFsdWUkJDEpOwogICAgfTsKCiAgICBfcHJvdG8xMC5yZWFkT25seSA9IGZ1bmN0aW9uIHJlYWRPbmx5KCkgewogICAgICB0aGlzLnNldCA9IEFsaWFzZWRQcm9wZXJ0eV9yZWFkT25seVNldDsKICAgIH07CgogICAgX3Byb3RvMTAub25lV2F5ID0gZnVuY3Rpb24gb25lV2F5KCkgewogICAgICB0aGlzLnNldCA9IEFsaWFzZWRQcm9wZXJ0eV9vbmVXYXlTZXQ7CiAgICB9OwoKICAgIHJldHVybiBBbGlhc2VkUHJvcGVydHk7CiAgfShDb21wdXRlZERlc2NyaXB0b3IpOwoKICBmdW5jdGlvbiBBbGlhc2VkUHJvcGVydHlfcmVhZE9ubHlTZXQob2JqLCBrZXlOYW1lKSB7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzCiAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIkNhbm5vdCBzZXQgcmVhZC1vbmx5IHByb3BlcnR5ICciICsga2V5TmFtZSArICInIG9uIG9iamVjdDogIiArICgwLCBfdXRpbHMuaW5zcGVjdCkob2JqKSk7CiAgfQoKICBmdW5jdGlvbiBBbGlhc2VkUHJvcGVydHlfb25lV2F5U2V0KG9iaiwga2V5TmFtZSwgdmFsdWUkJDEpIHsKICAgIGRlZmluZVByb3BlcnR5KG9iaiwga2V5TmFtZSwgbnVsbCk7CiAgICByZXR1cm4gX3NldDIob2JqLCBrZXlOYW1lLCB2YWx1ZSQkMSk7CiAgfQogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIFVzZWQgaW50ZXJuYWxseSB0byBhbGxvdyBjaGFuZ2luZyBwcm9wZXJ0aWVzIGluIGEgYmFja3dhcmRzIGNvbXBhdGlibGUgd2F5LCBhbmQgcHJpbnQgYSBoZWxwZnVsCiAgICBkZXByZWNhdGlvbiB3YXJuaW5nLgogIAogICAgQG1ldGhvZCBkZXByZWNhdGVQcm9wZXJ0eQogICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGFkZCB0aGUgZGVwcmVjYXRlZCBwcm9wZXJ0eSB0by4KICAgIEBwYXJhbSB7U3RyaW5nfSBkZXByZWNhdGVkS2V5IFRoZSBwcm9wZXJ0eSB0byBhZGQgKGFuZCBwcmludCBkZXByZWNhdGlvbiB3YXJuaW5ncyB1cG9uIGFjY2Vzc2luZykuCiAgICBAcGFyYW0ge1N0cmluZ30gbmV3S2V5IFRoZSBwcm9wZXJ0eSB0aGF0IHdpbGwgYmUgYWxpYXNlZC4KICAgIEBwcml2YXRlCiAgICBAc2luY2UgMS43LjAKICAqLwoKCiAgZnVuY3Rpb24gZGVwcmVjYXRlUHJvcGVydHkob2JqZWN0LCBkZXByZWNhdGVkS2V5LCBuZXdLZXksIG9wdGlvbnMpIHsKICAgIGZ1bmN0aW9uIF9kZXByZWNhdGUoKSB7CiAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIlVzYWdlIG9mIGAiICsgZGVwcmVjYXRlZEtleSArICJgIGlzIGRlcHJlY2F0ZWQsIHVzZSBgIiArIG5ld0tleSArICJgIGluc3RlYWQuIiwgZmFsc2UsIG9wdGlvbnMpKTsKICAgIH0KCiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqZWN0LCBkZXByZWNhdGVkS2V5LCB7CiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgZW51bWVyYWJsZTogZmFsc2UsCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHZhbHVlJCQxKSB7CiAgICAgICAgX2RlcHJlY2F0ZSgpOwoKICAgICAgICBfc2V0Mih0aGlzLCBuZXdLZXksIHZhbHVlJCQxKTsKICAgICAgfSwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgX2RlcHJlY2F0ZSgpOwoKICAgICAgICByZXR1cm4gX2dldDIodGhpcywgbmV3S2V5KTsKICAgICAgfQogICAgfSk7CiAgfQogIC8qKgogICBAbW9kdWxlIEBlbWJlci91dGlscwogICovCgogIC8qKgogICAgUmV0dXJucyB0cnVlIGlmIHRoZSBwYXNzZWQgdmFsdWUgaXMgbnVsbCBvciB1bmRlZmluZWQuIFRoaXMgYXZvaWRzIGVycm9ycwogICAgZnJvbSBKU0xpbnQgY29tcGxhaW5pbmcgYWJvdXQgdXNlIG9mID09LCB3aGljaCBjYW4gYmUgdGVjaG5pY2FsbHkKICAgIGNvbmZ1c2luZy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGlzTm9uZSgpOyAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNOb25lKG51bGwpOyAgICAgICAgICAvLyB0cnVlCiAgICBpc05vbmUodW5kZWZpbmVkKTsgICAgIC8vIHRydWUKICAgIGlzTm9uZSgnJyk7ICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzTm9uZShbXSk7ICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzTm9uZShmdW5jdGlvbigpIHt9KTsgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQG1ldGhvZCBpc05vbmUKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL3V0aWxzCiAgICBAcGFyYW0ge09iamVjdH0gb2JqIFZhbHVlIHRvIHRlc3QKICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGlzTm9uZShvYmopIHsKICAgIHJldHVybiBvYmogPT09IG51bGwgfHwgb2JqID09PSB1bmRlZmluZWQ7CiAgfQogIC8qKgogICBAbW9kdWxlIEBlbWJlci91dGlscwogICovCgogIC8qKgogICAgVmVyaWZpZXMgdGhhdCBhIHZhbHVlIGlzIGBudWxsYCBvciBgdW5kZWZpbmVkYCwgYW4gZW1wdHkgc3RyaW5nLCBvciBhbiBlbXB0eQogICAgYXJyYXkuCiAgCiAgICBDb25zdHJhaW5zIHRoZSBydWxlcyBvbiBgaXNOb25lYCBieSByZXR1cm5pbmcgdHJ1ZSBmb3IgZW1wdHkgc3RyaW5ncyBhbmQKICAgIGVtcHR5IGFycmF5cy4KICAKICAgIElmIHRoZSB2YWx1ZSBpcyBhbiBvYmplY3Qgd2l0aCBhIGBzaXplYCBwcm9wZXJ0eSBvZiB0eXBlIG51bWJlciwgaXQgaXMgdXNlZAogICAgdG8gY2hlY2sgZW1wdGluZXNzLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaXNFbXB0eSgpOyAgICAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eShudWxsKTsgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eSh1bmRlZmluZWQpOyAgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eSgnJyk7ICAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eShbXSk7ICAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eSh7IHNpemU6IDB9KTsgICAgICAgLy8gdHJ1ZQogICAgaXNFbXB0eSh7fSk7ICAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzRW1wdHkoJ0FkYW0gSGF3a2lucycpOyAgIC8vIGZhbHNlCiAgICBpc0VtcHR5KFswLDEsMl0pOyAgICAgICAgICAvLyBmYWxzZQogICAgaXNFbXB0eSgnXG5cdCcpOyAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzRW1wdHkoJyAgJyk7ICAgICAgICAgICAgIC8vIGZhbHNlCiAgICBpc0VtcHR5KHsgc2l6ZTogMSB9KSAgICAgICAvLyBmYWxzZQogICAgaXNFbXB0eSh7IHNpemU6ICgpID0+IDAgfSkgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQG1ldGhvZCBpc0VtcHR5CiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci91dGlscwogICAgQHBhcmFtIHtPYmplY3R9IG9iaiBWYWx1ZSB0byB0ZXN0CiAgICBAcmV0dXJuIHtCb29sZWFufQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpc0VtcHR5KG9iaikgewogICAgdmFyIG5vbmUgPSBvYmogPT09IG51bGwgfHwgb2JqID09PSB1bmRlZmluZWQ7CgogICAgaWYgKG5vbmUpIHsKICAgICAgcmV0dXJuIG5vbmU7CiAgICB9CgogICAgaWYgKHR5cGVvZiBvYmouc2l6ZSA9PT0gJ251bWJlcicpIHsKICAgICAgcmV0dXJuICFvYmouc2l6ZTsKICAgIH0KCiAgICB2YXIgb2JqZWN0VHlwZSA9IHR5cGVvZiBvYmo7CgogICAgaWYgKG9iamVjdFR5cGUgPT09ICdvYmplY3QnKSB7CiAgICAgIHZhciBzaXplID0gX2dldDIob2JqLCAnc2l6ZScpOwoKICAgICAgaWYgKHR5cGVvZiBzaXplID09PSAnbnVtYmVyJykgewogICAgICAgIHJldHVybiAhc2l6ZTsKICAgICAgfQogICAgfQoKICAgIGlmICh0eXBlb2Ygb2JqLmxlbmd0aCA9PT0gJ251bWJlcicgJiYgb2JqZWN0VHlwZSAhPT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gIW9iai5sZW5ndGg7CiAgICB9CgogICAgaWYgKG9iamVjdFR5cGUgPT09ICdvYmplY3QnKSB7CiAgICAgIHZhciBsZW5ndGggPSBfZ2V0MihvYmosICdsZW5ndGgnKTsKCiAgICAgIGlmICh0eXBlb2YgbGVuZ3RoID09PSAnbnVtYmVyJykgewogICAgICAgIHJldHVybiAhbGVuZ3RoOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGZhbHNlOwogIH0KICAvKioKICAgQG1vZHVsZSBAZW1iZXIvdXRpbHMKICAqLwoKICAvKioKICAgIEEgdmFsdWUgaXMgYmxhbmsgaWYgaXQgaXMgZW1wdHkgb3IgYSB3aGl0ZXNwYWNlIHN0cmluZy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGlzQmxhbmsgfSBmcm9tICdAZW1iZXIvdXRpbHMnOwogIAogICAgaXNCbGFuaygpOyAgICAgICAgICAgICAgICAvLyB0cnVlCiAgICBpc0JsYW5rKG51bGwpOyAgICAgICAgICAgIC8vIHRydWUKICAgIGlzQmxhbmsodW5kZWZpbmVkKTsgICAgICAgLy8gdHJ1ZQogICAgaXNCbGFuaygnJyk7ICAgICAgICAgICAgICAvLyB0cnVlCiAgICBpc0JsYW5rKFtdKTsgICAgICAgICAgICAgIC8vIHRydWUKICAgIGlzQmxhbmsoJ1xuXHQnKTsgICAgICAgICAgLy8gdHJ1ZQogICAgaXNCbGFuaygnICAnKTsgICAgICAgICAgICAvLyB0cnVlCiAgICBpc0JsYW5rKHt9KTsgICAgICAgICAgICAgIC8vIGZhbHNlCiAgICBpc0JsYW5rKCdcblx0IEhlbGxvJyk7ICAgIC8vIGZhbHNlCiAgICBpc0JsYW5rKCdIZWxsbyB3b3JsZCcpOyAgIC8vIGZhbHNlCiAgICBpc0JsYW5rKFsxLDIsM10pOyAgICAgICAgIC8vIGZhbHNlCiAgICBgYGAKICAKICAgIEBtZXRob2QgaXNCbGFuawogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvdXRpbHMKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVmFsdWUgdG8gdGVzdAogICAgQHJldHVybiB7Qm9vbGVhbn0KICAgIEBzaW5jZSAxLjUuMAogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpc0JsYW5rKG9iaikgewogICAgcmV0dXJuIGlzRW1wdHkob2JqKSB8fCB0eXBlb2Ygb2JqID09PSAnc3RyaW5nJyAmJiAvXFMvLnRlc3Qob2JqKSA9PT0gZmFsc2U7CiAgfQogIC8qKgogICBAbW9kdWxlIEBlbWJlci91dGlscwogICovCgogIC8qKgogICAgQSB2YWx1ZSBpcyBwcmVzZW50IGlmIGl0IG5vdCBgaXNCbGFua2AuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpc1ByZXNlbnQoKTsgICAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzUHJlc2VudChudWxsKTsgICAgICAgICAgICAvLyBmYWxzZQogICAgaXNQcmVzZW50KHVuZGVmaW5lZCk7ICAgICAgIC8vIGZhbHNlCiAgICBpc1ByZXNlbnQoJycpOyAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzUHJlc2VudCgnICAnKTsgICAgICAgICAgICAvLyBmYWxzZQogICAgaXNQcmVzZW50KCdcblx0Jyk7ICAgICAgICAgIC8vIGZhbHNlCiAgICBpc1ByZXNlbnQoW10pOyAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGlzUHJlc2VudCh7IGxlbmd0aDogMCB9KTsgICAvLyBmYWxzZQogICAgaXNQcmVzZW50KGZhbHNlKTsgICAgICAgICAgIC8vIHRydWUKICAgIGlzUHJlc2VudCh0cnVlKTsgICAgICAgICAgICAvLyB0cnVlCiAgICBpc1ByZXNlbnQoJ3N0cmluZycpOyAgICAgICAgLy8gdHJ1ZQogICAgaXNQcmVzZW50KDApOyAgICAgICAgICAgICAgIC8vIHRydWUKICAgIGlzUHJlc2VudChmdW5jdGlvbigpIHt9KTsgICAvLyB0cnVlCiAgICBpc1ByZXNlbnQoe30pOyAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNQcmVzZW50KCdcblx0IEhlbGxvJyk7ICAgIC8vIHRydWUKICAgIGlzUHJlc2VudChbMSwgMiwgM10pOyAgICAgICAvLyB0cnVlCiAgICBgYGAKICAKICAgIEBtZXRob2QgaXNQcmVzZW50CiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci91dGlscwogICAgQHBhcmFtIHtPYmplY3R9IG9iaiBWYWx1ZSB0byB0ZXN0CiAgICBAcmV0dXJuIHtCb29sZWFufQogICAgQHNpbmNlIDEuOC4wCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGlzUHJlc2VudChvYmopIHsKICAgIHJldHVybiAhaXNCbGFuayhvYmopOwogIH0KICAvKioKICAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgSGVscGVyIGNsYXNzIHRoYXQgYWxsb3dzIHlvdSB0byByZWdpc3RlciB5b3VyIGxpYnJhcnkgd2l0aCBFbWJlci4KICAKICAgIFNpbmdsZXRvbiBjcmVhdGVkIGF0IGBFbWJlci5saWJyYXJpZXNgLgogIAogICAgQGNsYXNzIExpYnJhcmllcwogICAgQGNvbnN0cnVjdG9yCiAgICBAcHJpdmF0ZQogICovCgoKICB2YXIgTGlicmFyaWVzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gTGlicmFyaWVzKCkgewogICAgICB0aGlzLl9yZWdpc3RyeSA9IFtdOwogICAgICB0aGlzLl9jb3JlTGliSW5kZXggPSAwOwogICAgfQoKICAgIHZhciBfcHJvdG8xMSA9IExpYnJhcmllcy5wcm90b3R5cGU7CgogICAgX3Byb3RvMTEuX2dldExpYnJhcnlCeU5hbWUgPSBmdW5jdGlvbiBfZ2V0TGlicmFyeUJ5TmFtZShuYW1lKSB7CiAgICAgIHZhciBsaWJzID0gdGhpcy5fcmVnaXN0cnk7CiAgICAgIHZhciBjb3VudCA9IGxpYnMubGVuZ3RoOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgICAgaWYgKGxpYnNbaV0ubmFtZSA9PT0gbmFtZSkgewogICAgICAgICAgcmV0dXJuIGxpYnNbaV07CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfTsKCiAgICBfcHJvdG8xMS5yZWdpc3RlciA9IGZ1bmN0aW9uIHJlZ2lzdGVyKG5hbWUsIHZlcnNpb24sIGlzQ29yZUxpYnJhcnkpIHsKICAgICAgdmFyIGluZGV4ID0gdGhpcy5fcmVnaXN0cnkubGVuZ3RoOwoKICAgICAgaWYgKCF0aGlzLl9nZXRMaWJyYXJ5QnlOYW1lKG5hbWUpKSB7CiAgICAgICAgaWYgKGlzQ29yZUxpYnJhcnkpIHsKICAgICAgICAgIGluZGV4ID0gdGhpcy5fY29yZUxpYkluZGV4Kys7CiAgICAgICAgfQoKICAgICAgICB0aGlzLl9yZWdpc3RyeS5zcGxpY2UoaW5kZXgsIDAsIHsKICAgICAgICAgIG5hbWU6IG5hbWUsCiAgICAgICAgICB2ZXJzaW9uOiB2ZXJzaW9uCiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgKGZhbHNlICYmICgwLCBfZGVidWcud2FybikoIkxpYnJhcnkgXCIiICsgbmFtZSArICJcIiBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgd2l0aCBFbWJlci4iLCBmYWxzZSwgewogICAgICAgICAgaWQ6ICdlbWJlci1tZXRhbC5saWJyYXJpZXMtcmVnaXN0ZXInCiAgICAgICAgfSkpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzExLnJlZ2lzdGVyQ29yZUxpYnJhcnkgPSBmdW5jdGlvbiByZWdpc3RlckNvcmVMaWJyYXJ5KG5hbWUsIHZlcnNpb24pIHsKICAgICAgdGhpcy5yZWdpc3RlcihuYW1lLCB2ZXJzaW9uLCB0cnVlKTsKICAgIH07CgogICAgX3Byb3RvMTEuZGVSZWdpc3RlciA9IGZ1bmN0aW9uIGRlUmVnaXN0ZXIobmFtZSkgewogICAgICB2YXIgbGliID0gdGhpcy5fZ2V0TGlicmFyeUJ5TmFtZShuYW1lKTsKCiAgICAgIHZhciBpbmRleDsKCiAgICAgIGlmIChsaWIpIHsKICAgICAgICBpbmRleCA9IHRoaXMuX3JlZ2lzdHJ5LmluZGV4T2YobGliKTsKCiAgICAgICAgdGhpcy5fcmVnaXN0cnkuc3BsaWNlKGluZGV4LCAxKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gTGlicmFyaWVzOwogIH0oKTsKCiAgX2V4cG9ydHMuTGlicmFyaWVzID0gTGlicmFyaWVzOwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgTGlicmFyaWVzLnByb3RvdHlwZS5sb2dWZXJzaW9ucyA9IGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGxpYnMgPSB0aGlzLl9yZWdpc3RyeTsKICAgICAgdmFyIG5hbWVMZW5ndGhzID0gbGlicy5tYXAoZnVuY3Rpb24gKGl0ZW0pIHsKICAgICAgICByZXR1cm4gX2dldDIoaXRlbSwgJ25hbWUubGVuZ3RoJyk7CiAgICAgIH0pOwogICAgICB2YXIgbWF4TmFtZUxlbmd0aCA9IE1hdGgubWF4LmFwcGx5KG51bGwsIG5hbWVMZW5ndGhzKTsKICAgICAgKDAsIF9kZWJ1Zy5kZWJ1ZykoJy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0nKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGlicy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBsaWIgPSBsaWJzW2ldOwogICAgICAgIHZhciBzcGFjZXMgPSBuZXcgQXJyYXkobWF4TmFtZUxlbmd0aCAtIGxpYi5uYW1lLmxlbmd0aCArIDEpLmpvaW4oJyAnKTsKICAgICAgICAoMCwgX2RlYnVnLmRlYnVnKShbbGliLm5hbWUsIHNwYWNlcywgJyA6ICcsIGxpYi52ZXJzaW9uXS5qb2luKCcnKSk7CiAgICAgIH0KCiAgICAgICgwLCBfZGVidWcuZGVidWcpKCctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJyk7CiAgICB9OwogIH0KCiAgdmFyIExJQlJBUklFUyA9IG5ldyBMaWJyYXJpZXMoKTsKICBfZXhwb3J0cy5saWJyYXJpZXMgPSBMSUJSQVJJRVM7CiAgTElCUkFSSUVTLnJlZ2lzdGVyQ29yZUxpYnJhcnkoJ0VtYmVyJywgX3ZlcnNpb24uZGVmYXVsdCk7CiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL29iamVjdAogICovCgogIC8qKgogICAgVG8gZ2V0IG11bHRpcGxlIHByb3BlcnRpZXMgYXQgb25jZSwgY2FsbCBgZ2V0UHJvcGVydGllc2AKICAgIHdpdGggYW4gb2JqZWN0IGZvbGxvd2VkIGJ5IGEgbGlzdCBvZiBzdHJpbmdzIG9yIGFuIGFycmF5OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZ2V0UHJvcGVydGllcyB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZ2V0UHJvcGVydGllcyhyZWNvcmQsICdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnLCAnemlwQ29kZScpOwogICAgLy8geyBmaXJzdE5hbWU6ICdKb2huJywgbGFzdE5hbWU6ICdEb2UnLCB6aXBDb2RlOiAnMTAwMTEnIH0KICAgIGBgYAogIAogICAgaXMgZXF1aXZhbGVudCB0bzoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGdldFByb3BlcnRpZXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGdldFByb3BlcnRpZXMocmVjb3JkLCBbJ2ZpcnN0TmFtZScsICdsYXN0TmFtZScsICd6aXBDb2RlJ10pOwogICAgLy8geyBmaXJzdE5hbWU6ICdKb2huJywgbGFzdE5hbWU6ICdEb2UnLCB6aXBDb2RlOiAnMTAwMTEnIH0KICAgIGBgYAogIAogICAgQG1ldGhvZCBnZXRQcm9wZXJ0aWVzCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmoKICAgIEBwYXJhbSB7U3RyaW5nLi4ufEFycmF5fSBsaXN0IG9mIGtleXMgdG8gZ2V0CiAgICBAcmV0dXJuIHtPYmplY3R9CiAgICBAcHVibGljCiAgKi8KCiAgZnVuY3Rpb24gZ2V0UHJvcGVydGllcyhvYmosIGtleXMpIHsKICAgIHZhciByZXQgPSB7fTsKICAgIHZhciBwcm9wZXJ0eU5hbWVzID0gYXJndW1lbnRzOwogICAgdmFyIGkgPSAxOwoKICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmIEFycmF5LmlzQXJyYXkoa2V5cykpIHsKICAgICAgaSA9IDA7CiAgICAgIHByb3BlcnR5TmFtZXMgPSBhcmd1bWVudHNbMV07CiAgICB9CgogICAgZm9yICg7IGkgPCBwcm9wZXJ0eU5hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHJldFtwcm9wZXJ0eU5hbWVzW2ldXSA9IF9nZXQyKG9iaiwgcHJvcGVydHlOYW1lc1tpXSk7CiAgICB9CgogICAgcmV0dXJuIHJldDsKICB9CiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL29iamVjdAogICovCgogIC8qKgogICAgU2V0IGEgbGlzdCBvZiBwcm9wZXJ0aWVzIG9uIGFuIG9iamVjdC4gVGhlc2UgcHJvcGVydGllcyBhcmUgc2V0IGluc2lkZQogICAgYSBzaW5nbGUgYGJlZ2luUHJvcGVydHlDaGFuZ2VzYCBhbmQgYGVuZFByb3BlcnR5Q2hhbmdlc2AgYmF0Y2gsIHNvCiAgICBvYnNlcnZlcnMgd2lsbCBiZSBidWZmZXJlZC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGxldCBhbk9iamVjdCA9IEVtYmVyT2JqZWN0LmNyZWF0ZSgpOwogIAogICAgYW5PYmplY3Quc2V0UHJvcGVydGllcyh7CiAgICAgIGZpcnN0TmFtZTogJ1N0YW5sZXknLAogICAgICBsYXN0TmFtZTogJ1N0dWFydCcsCiAgICAgIGFnZTogMjEKICAgIH0pOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHNldFByb3BlcnRpZXMKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdAogICAgQHBhcmFtIG9iagogICAgQHBhcmFtIHtPYmplY3R9IHByb3BlcnRpZXMKICAgIEByZXR1cm4gcHJvcGVydGllcwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBzZXRQcm9wZXJ0aWVzKG9iaiwgcHJvcGVydGllcykgewogICAgaWYgKHByb3BlcnRpZXMgPT09IG51bGwgfHwgdHlwZW9mIHByb3BlcnRpZXMgIT09ICdvYmplY3QnKSB7CiAgICAgIHJldHVybiBwcm9wZXJ0aWVzOwogICAgfQoKICAgIGNoYW5nZVByb3BlcnRpZXMoZnVuY3Rpb24gKCkgewogICAgICB2YXIgcHJvcHMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKTsKICAgICAgdmFyIHByb3BlcnR5TmFtZTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsKICAgICAgICBwcm9wZXJ0eU5hbWUgPSBwcm9wc1tpXTsKCiAgICAgICAgX3NldDIob2JqLCBwcm9wZXJ0eU5hbWUsIHByb3BlcnRpZXNbcHJvcGVydHlOYW1lXSk7CiAgICAgIH0KICAgIH0pOwogICAgcmV0dXJuIHByb3BlcnRpZXM7CiAgfSAvLyBtb3ZlIGludG8gaXRzIG93biBwYWNrYWdlCiAgLy8gaXQgaXMgbmVlZGVkIGJ5IE1peGluIGZvciBjbGFzc1RvU3RyaW5nCiAgLy8gbWF5YmUgbW92ZSBpdCBpbnRvIGVudmlyb25tZW50CgoKICB2YXIgaGFzT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5OwogIHZhciBzZWFyY2hEaXNhYmxlZCA9IGZhbHNlOwogIHZhciBmbGFncyA9IHsKICAgIF9zZXQ6IDAsCiAgICBfdW5wcm9jZXNzZWROYW1lc3BhY2VzOiBmYWxzZSwKCiAgICBnZXQgdW5wcm9jZXNzZWROYW1lc3BhY2VzKCkgewogICAgICByZXR1cm4gdGhpcy5fdW5wcm9jZXNzZWROYW1lc3BhY2VzOwogICAgfSwKCiAgICBzZXQgdW5wcm9jZXNzZWROYW1lc3BhY2VzKHYpIHsKICAgICAgdGhpcy5fc2V0Kys7CiAgICAgIHRoaXMuX3VucHJvY2Vzc2VkTmFtZXNwYWNlcyA9IHY7CiAgICB9CgogIH07CiAgdmFyIHVucHJvY2Vzc2VkTWl4aW5zID0gZmFsc2U7CiAgdmFyIE5BTUVTUEFDRVMgPSBbXTsKICBfZXhwb3J0cy5OQU1FU1BBQ0VTID0gTkFNRVNQQUNFUzsKICB2YXIgTkFNRVNQQUNFU19CWV9JRCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgX2V4cG9ydHMuTkFNRVNQQUNFU19CWV9JRCA9IE5BTUVTUEFDRVNfQllfSUQ7CgogIGZ1bmN0aW9uIGFkZE5hbWVzcGFjZShuYW1lc3BhY2UpIHsKICAgIGZsYWdzLnVucHJvY2Vzc2VkTmFtZXNwYWNlcyA9IHRydWU7CiAgICBOQU1FU1BBQ0VTLnB1c2gobmFtZXNwYWNlKTsKICB9CgogIGZ1bmN0aW9uIHJlbW92ZU5hbWVzcGFjZShuYW1lc3BhY2UpIHsKICAgIHZhciBuYW1lID0gKDAsIF91dGlscy5nZXROYW1lKShuYW1lc3BhY2UpOwogICAgZGVsZXRlIE5BTUVTUEFDRVNfQllfSURbbmFtZV07CiAgICBOQU1FU1BBQ0VTLnNwbGljZShOQU1FU1BBQ0VTLmluZGV4T2YobmFtZXNwYWNlKSwgMSk7CgogICAgaWYgKG5hbWUgaW4gX2Vudmlyb25tZW50LmNvbnRleHQubG9va3VwICYmIG5hbWVzcGFjZSA9PT0gX2Vudmlyb25tZW50LmNvbnRleHQubG9va3VwW25hbWVdKSB7CiAgICAgIF9lbnZpcm9ubWVudC5jb250ZXh0Lmxvb2t1cFtuYW1lXSA9IHVuZGVmaW5lZDsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGZpbmROYW1lc3BhY2VzKCkgewogICAgaWYgKCFmbGFncy51bnByb2Nlc3NlZE5hbWVzcGFjZXMpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBsb29rdXAgPSBfZW52aXJvbm1lbnQuY29udGV4dC5sb29rdXA7CiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGxvb2t1cCk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBrZXkgPSBrZXlzW2ldOyAvLyBPbmx5IHByb2Nlc3MgZW50aXRpZXMgdGhhdCBzdGFydCB3aXRoIHVwcGVyY2FzZSBBLVoKCiAgICAgIGlmICghaXNVcHBlcmNhc2Uoa2V5LmNoYXJDb2RlQXQoMCkpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIHZhciBvYmogPSB0cnlJc05hbWVzcGFjZShsb29rdXAsIGtleSk7CgogICAgICBpZiAob2JqKSB7CiAgICAgICAgKDAsIF91dGlscy5zZXROYW1lKShvYmosIGtleSk7CiAgICAgIH0KICAgIH0KICB9CgogIGZ1bmN0aW9uIGZpbmROYW1lc3BhY2UobmFtZSkgewogICAgaWYgKCFzZWFyY2hEaXNhYmxlZCkgewogICAgICBwcm9jZXNzQWxsTmFtZXNwYWNlcygpOwogICAgfQoKICAgIHJldHVybiBOQU1FU1BBQ0VTX0JZX0lEW25hbWVdOwogIH0KCiAgZnVuY3Rpb24gcHJvY2Vzc05hbWVzcGFjZShuYW1lc3BhY2UpIHsKICAgIF9wcm9jZXNzTmFtZXNwYWNlKFtuYW1lc3BhY2UudG9TdHJpbmcoKV0sIG5hbWVzcGFjZSwgbmV3IFNldCgpKTsKICB9CgogIGZ1bmN0aW9uIHByb2Nlc3NBbGxOYW1lc3BhY2VzKCkgewogICAgdmFyIHVucHJvY2Vzc2VkTmFtZXNwYWNlcyA9IGZsYWdzLnVucHJvY2Vzc2VkTmFtZXNwYWNlczsKCiAgICBpZiAodW5wcm9jZXNzZWROYW1lc3BhY2VzKSB7CiAgICAgIGZpbmROYW1lc3BhY2VzKCk7CiAgICAgIGZsYWdzLnVucHJvY2Vzc2VkTmFtZXNwYWNlcyA9IGZhbHNlOwogICAgfQoKICAgIGlmICh1bnByb2Nlc3NlZE5hbWVzcGFjZXMgfHwgdW5wcm9jZXNzZWRNaXhpbnMpIHsKICAgICAgdmFyIG5hbWVzcGFjZXMgPSBOQU1FU1BBQ0VTOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lc3BhY2VzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgcHJvY2Vzc05hbWVzcGFjZShuYW1lc3BhY2VzW2ldKTsKICAgICAgfQoKICAgICAgdW5wcm9jZXNzZWRNaXhpbnMgPSBmYWxzZTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGNsYXNzVG9TdHJpbmcoKSB7CiAgICB2YXIgbmFtZSA9ICgwLCBfdXRpbHMuZ2V0TmFtZSkodGhpcyk7CgogICAgaWYgKG5hbWUgIT09IHZvaWQgMCkgewogICAgICByZXR1cm4gbmFtZTsKICAgIH0KCiAgICBuYW1lID0gY2FsY3VsYXRlVG9TdHJpbmcodGhpcyk7CiAgICAoMCwgX3V0aWxzLnNldE5hbWUpKHRoaXMsIG5hbWUpOwogICAgcmV0dXJuIG5hbWU7CiAgfQoKICBmdW5jdGlvbiBpc1NlYXJjaERpc2FibGVkKCkgewogICAgcmV0dXJuIHNlYXJjaERpc2FibGVkOwogIH0KCiAgZnVuY3Rpb24gc2V0U2VhcmNoRGlzYWJsZWQoZmxhZykgewogICAgc2VhcmNoRGlzYWJsZWQgPSBCb29sZWFuKGZsYWcpOwogIH0KCiAgZnVuY3Rpb24gc2V0VW5wcm9jZXNzZWRNaXhpbnMoKSB7CiAgICB1bnByb2Nlc3NlZE1peGlucyA9IHRydWU7CiAgfQoKICBmdW5jdGlvbiBfcHJvY2Vzc05hbWVzcGFjZShwYXRocywgcm9vdCwgc2VlbikgewogICAgdmFyIGlkeCA9IHBhdGhzLmxlbmd0aDsKICAgIHZhciBpZCA9IHBhdGhzLmpvaW4oJy4nKTsKICAgIE5BTUVTUEFDRVNfQllfSURbaWRdID0gcm9vdDsKICAgICgwLCBfdXRpbHMuc2V0TmFtZSkocm9vdCwgaWQpOyAvLyBMb29wIG92ZXIgYWxsIG9mIHRoZSBrZXlzIGluIHRoZSBuYW1lc3BhY2UsIGxvb2tpbmcgZm9yIGNsYXNzZXMKCiAgICBmb3IgKHZhciBrZXkgaW4gcm9vdCkgewogICAgICBpZiAoIWhhc093blByb3BlcnR5LmNhbGwocm9vdCwga2V5KSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICB2YXIgb2JqID0gcm9vdFtrZXldOyAvLyBJZiB3ZSBhcmUgcHJvY2Vzc2luZyB0aGUgYEVtYmVyYCBuYW1lc3BhY2UsIGZvciBleGFtcGxlLCB0aGUKICAgICAgLy8gYHBhdGhzYCB3aWxsIHN0YXJ0IHdpdGggYFsiRW1iZXIiXWAuIEV2ZXJ5IGl0ZXJhdGlvbiB0aHJvdWdoCiAgICAgIC8vIHRoZSBsb29wIHdpbGwgdXBkYXRlIHRoZSAqKnNlY29uZCoqIGVsZW1lbnQgb2YgdGhpcyBsaXN0IHdpdGgKICAgICAgLy8gdGhlIGtleSwgc28gcHJvY2Vzc2luZyBgRW1iZXIuVmlld2Agd2lsbCBtYWtlIHRoZSBBcnJheQogICAgICAvLyBgWydFbWJlcicsICdWaWV3J11gLgoKICAgICAgcGF0aHNbaWR4XSA9IGtleTsgLy8gSWYgd2UgaGF2ZSBmb3VuZCBhbiB1bnByb2Nlc3NlZCBjbGFzcwoKICAgICAgaWYgKG9iaiAmJiBvYmoudG9TdHJpbmcgPT09IGNsYXNzVG9TdHJpbmcgJiYgKDAsIF91dGlscy5nZXROYW1lKShvYmopID09PSB2b2lkIDApIHsKICAgICAgICAvLyBSZXBsYWNlIHRoZSBjbGFzcycgYHRvU3RyaW5nYCB3aXRoIHRoZSBkb3Qtc2VwYXJhdGVkIHBhdGgKICAgICAgICAoMCwgX3V0aWxzLnNldE5hbWUpKG9iaiwgcGF0aHMuam9pbignLicpKTsgLy8gU3VwcG9ydCBuZXN0ZWQgbmFtZXNwYWNlcwogICAgICB9IGVsc2UgaWYgKG9iaiAmJiBvYmouaXNOYW1lc3BhY2UpIHsKICAgICAgICAvLyBTa2lwIGFsaWFzZWQgbmFtZXNwYWNlcwogICAgICAgIGlmIChzZWVuLmhhcyhvYmopKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIHNlZW4uYWRkKG9iaik7IC8vIFByb2Nlc3MgdGhlIGNoaWxkIG5hbWVzcGFjZQoKICAgICAgICBfcHJvY2Vzc05hbWVzcGFjZShwYXRocywgb2JqLCBzZWVuKTsKICAgICAgfQogICAgfQoKICAgIHBhdGhzLmxlbmd0aCA9IGlkeDsgLy8gY3V0IG91dCBsYXN0IGl0ZW0KICB9CgogIGZ1bmN0aW9uIGlzVXBwZXJjYXNlKGNvZGUpIHsKICAgIHJldHVybiBjb2RlID49IDY1ICYmIGNvZGUgPD0gOTAgLy8gQQogICAgOyAvLyBaCiAgfQoKICBmdW5jdGlvbiB0cnlJc05hbWVzcGFjZShsb29rdXAsIHByb3ApIHsKICAgIHRyeSB7CiAgICAgIHZhciBvYmogPSBsb29rdXBbcHJvcF07CiAgICAgIHJldHVybiAob2JqICE9PSBudWxsICYmIHR5cGVvZiBvYmogPT09ICdvYmplY3QnIHx8IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbicpICYmIG9iai5pc05hbWVzcGFjZSAmJiBvYmo7CiAgICB9IGNhdGNoIChlKSB7Ly8gY29udGludWUKICAgIH0KICB9CgogIGZ1bmN0aW9uIGNhbGN1bGF0ZVRvU3RyaW5nKHRhcmdldCkgewogICAgdmFyIHN0cjsKCiAgICBpZiAoIXNlYXJjaERpc2FibGVkKSB7CiAgICAgIHByb2Nlc3NBbGxOYW1lc3BhY2VzKCk7CiAgICAgIHN0ciA9ICgwLCBfdXRpbHMuZ2V0TmFtZSkodGFyZ2V0KTsKCiAgICAgIGlmIChzdHIgIT09IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzdHI7CiAgICAgIH0KCiAgICAgIHZhciBzdXBlcmNsYXNzID0gdGFyZ2V0OwoKICAgICAgZG8gewogICAgICAgIHN1cGVyY2xhc3MgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yoc3VwZXJjbGFzcyk7CgogICAgICAgIGlmIChzdXBlcmNsYXNzID09PSBGdW5jdGlvbi5wcm90b3R5cGUgfHwgc3VwZXJjbGFzcyA9PT0gT2JqZWN0LnByb3RvdHlwZSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICBzdHIgPSAoMCwgX3V0aWxzLmdldE5hbWUpKHRhcmdldCk7CgogICAgICAgIGlmIChzdHIgIT09IHZvaWQgMCkgewogICAgICAgICAgc3RyID0gIihzdWJjbGFzcyBvZiAiICsgc3RyICsgIikiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9IHdoaWxlIChzdHIgPT09IHZvaWQgMCk7CiAgICB9CgogICAgcmV0dXJuIHN0ciB8fCAnKHVua25vd24pJzsKICB9CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KCgogIHZhciBhX2NvbmNhdCA9IEFycmF5LnByb3RvdHlwZS5jb25jYXQ7CiAgdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5OwoKICBmdW5jdGlvbiBpc01ldGhvZChvYmopIHsKICAgIHJldHVybiAnZnVuY3Rpb24nID09PSB0eXBlb2Ygb2JqICYmIG9iai5pc01ldGhvZCAhPT0gZmFsc2UgJiYgb2JqICE9PSBCb29sZWFuICYmIG9iaiAhPT0gT2JqZWN0ICYmIG9iaiAhPT0gTnVtYmVyICYmIG9iaiAhPT0gQXJyYXkgJiYgb2JqICE9PSBEYXRlICYmIG9iaiAhPT0gU3RyaW5nOwogIH0KCiAgZnVuY3Rpb24gaXNBY2Nlc3NvcihkZXNjKSB7CiAgICByZXR1cm4gdHlwZW9mIGRlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBkZXNjLnNldCA9PT0gJ2Z1bmN0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGV4dHJhY3RBY2Nlc3NvcnMocHJvcGVydGllcykgewogICAgaWYgKHByb3BlcnRpZXMgIT09IHVuZGVmaW5lZCkgewogICAgICB2YXIgZGVzY3JpcHRvcnMgPSAoMCwgX3V0aWxzLmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMpKHByb3BlcnRpZXMpOwogICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGRlc2NyaXB0b3JzKTsKICAgICAgdmFyIGhhc0FjY2Vzc29ycyA9IGtleXMuc29tZShmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgcmV0dXJuIGlzQWNjZXNzb3IoZGVzY3JpcHRvcnNba2V5XSk7CiAgICAgIH0pOwoKICAgICAgaWYgKGhhc0FjY2Vzc29ycykgewogICAgICAgIHZhciBleHRyYWN0ZWQgPSB7fTsKICAgICAgICBrZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgdmFyIGRlc2NyaXB0b3IgPSBkZXNjcmlwdG9yc1trZXldOwoKICAgICAgICAgIGlmIChpc0FjY2Vzc29yKGRlc2NyaXB0b3IpKSB7CiAgICAgICAgICAgIGV4dHJhY3RlZFtrZXldID0gbmF0aXZlRGVzY0RlY29yYXRvcihkZXNjcmlwdG9yKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dHJhY3RlZFtrZXldID0gcHJvcGVydGllc1trZXldOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBleHRyYWN0ZWQ7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcHJvcGVydGllczsKICB9CgogIHZhciBDT05USU5VRSA9IHt9OwoKICBmdW5jdGlvbiBtaXhpblByb3BlcnRpZXMobWl4aW5zTWV0YSwgbWl4aW4pIHsKICAgIGlmIChtaXhpbiBpbnN0YW5jZW9mIE1peGluKSB7CiAgICAgIGlmIChtaXhpbnNNZXRhLmhhc01peGluKG1peGluKSkgewogICAgICAgIHJldHVybiBDT05USU5VRTsKICAgICAgfQoKICAgICAgbWl4aW5zTWV0YS5hZGRNaXhpbihtaXhpbik7CiAgICAgIHJldHVybiBtaXhpbi5wcm9wZXJ0aWVzOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG1peGluOyAvLyBhcHBseSBhbm9ueW1vdXMgbWl4aW4gcHJvcGVydGllcwogICAgfQogIH0KCiAgZnVuY3Rpb24gY29uY2F0ZW5hdGVkTWl4aW5Qcm9wZXJ0aWVzKGNvbmNhdFByb3AsIHByb3BzLCB2YWx1ZXMsIGJhc2UpIHsKICAgIC8vIHJlc2V0IGJlZm9yZSBhZGRpbmcgZWFjaCBuZXcgbWl4aW4gdG8gcGlja3VwIGNvbmNhdHMgZnJvbSBwcmV2aW91cwogICAgdmFyIGNvbmNhdHMgPSB2YWx1ZXNbY29uY2F0UHJvcF0gfHwgYmFzZVtjb25jYXRQcm9wXTsKCiAgICBpZiAocHJvcHNbY29uY2F0UHJvcF0pIHsKICAgICAgY29uY2F0cyA9IGNvbmNhdHMgPyBhX2NvbmNhdC5jYWxsKGNvbmNhdHMsIHByb3BzW2NvbmNhdFByb3BdKSA6IHByb3BzW2NvbmNhdFByb3BdOwogICAgfQoKICAgIHJldHVybiBjb25jYXRzOwogIH0KCiAgZnVuY3Rpb24gZ2l2ZURlY29yYXRvclN1cGVyKG1ldGEkJDEsIGtleSwgZGVjb3JhdG9yLCB2YWx1ZXMsIGRlc2NzLCBiYXNlKSB7CiAgICB2YXIgcHJvcGVydHkgPSBkZXNjcmlwdG9yRm9yRGVjb3JhdG9yKGRlY29yYXRvcik7CiAgICB2YXIgc3VwZXJQcm9wZXJ0eTsKCiAgICBpZiAoIShwcm9wZXJ0eSBpbnN0YW5jZW9mIENvbXB1dGVkUHJvcGVydHkpIHx8IHByb3BlcnR5Ll9nZXR0ZXIgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gZGVjb3JhdG9yOwogICAgfSAvLyBDb21wdXRlZCBwcm9wZXJ0aWVzIG92ZXJyaWRlIG1ldGhvZHMsIGFuZCBkbyBub3QgY2FsbCBzdXBlciB0byB0aGVtCgoKICAgIGlmICh2YWx1ZXNba2V5XSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIC8vIEZpbmQgdGhlIG9yaWdpbmFsIGRlc2NyaXB0b3IgaW4gYSBwYXJlbnQgbWl4aW4KICAgICAgc3VwZXJQcm9wZXJ0eSA9IGRlc2NyaXB0b3JGb3JEZWNvcmF0b3IoZGVzY3Nba2V5XSk7CiAgICB9IC8vIElmIHdlIGRpZG4ndCBmaW5kIHRoZSBvcmlnaW5hbCBkZXNjcmlwdG9yIGluIGEgcGFyZW50IG1peGluLCBmaW5kCiAgICAvLyBpdCBvbiB0aGUgb3JpZ2luYWwgb2JqZWN0LgoKCiAgICBpZiAoIXN1cGVyUHJvcGVydHkpIHsKICAgICAgc3VwZXJQcm9wZXJ0eSA9IGRlc2NyaXB0b3JGb3JQcm9wZXJ0eShiYXNlLCBrZXksIG1ldGEkJDEpOwogICAgfQoKICAgIGlmIChzdXBlclByb3BlcnR5ID09PSB1bmRlZmluZWQgfHwgIShzdXBlclByb3BlcnR5IGluc3RhbmNlb2YgQ29tcHV0ZWRQcm9wZXJ0eSkpIHsKICAgICAgcmV0dXJuIGRlY29yYXRvcjsKICAgIH0KCiAgICB2YXIgZ2V0ID0gKDAsIF91dGlscy53cmFwKShwcm9wZXJ0eS5fZ2V0dGVyLCBzdXBlclByb3BlcnR5Ll9nZXR0ZXIpOwogICAgdmFyIHNldDsKCiAgICBpZiAoc3VwZXJQcm9wZXJ0eS5fc2V0dGVyKSB7CiAgICAgIGlmIChwcm9wZXJ0eS5fc2V0dGVyKSB7CiAgICAgICAgc2V0ID0gKDAsIF91dGlscy53cmFwKShwcm9wZXJ0eS5fc2V0dGVyLCBzdXBlclByb3BlcnR5Ll9zZXR0ZXIpOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIElmIHRoZSBzdXBlciBwcm9wZXJ0eSBoYXMgYSBzZXR0ZXIsIHdlIGRlZmF1bHQgdG8gdXNpbmcgaXQgbm8gbWF0dGVyIHdoYXQuCiAgICAgICAgLy8gVGhpcyBpcyBjbGVhcmx5IHZlcnkgYnJva2VuIGFuZCB3ZWlyZCwgYnV0IGl0J3Mgd2hhdCB3YXMgaGVyZSBzbyB3ZSBoYXZlCiAgICAgICAgLy8gdG8ga2VlcCBpdCB1bnRpbCB0aGUgbmV4dCBtYWpvciBhdCBsZWFzdC4KICAgICAgICAvLwogICAgICAgIC8vIFRPRE86IEFkZCBhIGRlcHJlY2F0aW9uIGhlcmUuCiAgICAgICAgc2V0ID0gc3VwZXJQcm9wZXJ0eS5fc2V0dGVyOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBzZXQgPSBwcm9wZXJ0eS5fc2V0dGVyOwogICAgfSAvLyBvbmx5IGNyZWF0ZSBhIG5ldyBDUCBpZiB3ZSBtdXN0CgoKICAgIGlmIChnZXQgIT09IHByb3BlcnR5Ll9nZXR0ZXIgfHwgc2V0ICE9PSBwcm9wZXJ0eS5fc2V0dGVyKSB7CiAgICAgIC8vIFNpbmNlIG11bHRpcGxlIG1peGlucyBtYXkgaW5oZXJpdCBmcm9tIHRoZSBzYW1lIHBhcmVudCwgd2UgbmVlZAogICAgICAvLyB0byBjbG9uZSB0aGUgY29tcHV0ZWQgcHJvcGVydHkgc28gdGhhdCBvdGhlciBtaXhpbnMgZG8gbm90IHJlY2VpdmUKICAgICAgLy8gdGhlIHdyYXBwZWQgdmVyc2lvbi4KICAgICAgdmFyIG5ld1Byb3BlcnR5ID0gT2JqZWN0LmNyZWF0ZShwcm9wZXJ0eSk7CiAgICAgIG5ld1Byb3BlcnR5Ll9nZXR0ZXIgPSBnZXQ7CiAgICAgIG5ld1Byb3BlcnR5Ll9zZXR0ZXIgPSBzZXQ7CiAgICAgIHJldHVybiBtYWtlQ29tcHV0ZWREZWNvcmF0b3IobmV3UHJvcGVydHksIENvbXB1dGVkUHJvcGVydHkpOwogICAgfQoKICAgIHJldHVybiBkZWNvcmF0b3I7CiAgfQoKICBmdW5jdGlvbiBnaXZlTWV0aG9kU3VwZXIob2JqLCBrZXksIG1ldGhvZCwgdmFsdWVzLCBkZXNjcykgewogICAgLy8gTWV0aG9kcyBvdmVyd3JpdGUgY29tcHV0ZWQgcHJvcGVydGllcywgYW5kIGRvIG5vdCBjYWxsIHN1cGVyIHRvIHRoZW0uCiAgICBpZiAoZGVzY3Nba2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBtZXRob2Q7CiAgICB9IC8vIEZpbmQgdGhlIG9yaWdpbmFsIG1ldGhvZCBpbiBhIHBhcmVudCBtaXhpbgoKCiAgICB2YXIgc3VwZXJNZXRob2QgPSB2YWx1ZXNba2V5XTsgLy8gSWYgd2UgZGlkbid0IGZpbmQgdGhlIG9yaWdpbmFsIHZhbHVlIGluIGEgcGFyZW50IG1peGluLCBmaW5kIGl0IGluCiAgICAvLyB0aGUgb3JpZ2luYWwgb2JqZWN0CgogICAgaWYgKHN1cGVyTWV0aG9kID09PSB1bmRlZmluZWQgJiYgZGVzY3JpcHRvckZvclByb3BlcnR5KG9iaiwga2V5KSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHN1cGVyTWV0aG9kID0gb2JqW2tleV07CiAgICB9IC8vIE9ubHkgd3JhcCB0aGUgbmV3IG1ldGhvZCBpZiB0aGUgb3JpZ2luYWwgbWV0aG9kIHdhcyBhIGZ1bmN0aW9uCgoKICAgIGlmICh0eXBlb2Ygc3VwZXJNZXRob2QgPT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuICgwLCBfdXRpbHMud3JhcCkobWV0aG9kLCBzdXBlck1ldGhvZCk7CiAgICB9CgogICAgcmV0dXJuIG1ldGhvZDsKICB9CgogIGZ1bmN0aW9uIGFwcGx5Q29uY2F0ZW5hdGVkUHJvcGVydGllcyhvYmosIGtleSwgdmFsdWUkJDEsIHZhbHVlcykgewogICAgdmFyIGJhc2VWYWx1ZSA9IHZhbHVlc1trZXldIHx8IG9ialtrZXldOwogICAgdmFyIHJldCA9ICgwLCBfdXRpbHMubWFrZUFycmF5KShiYXNlVmFsdWUpLmNvbmNhdCgoMCwgX3V0aWxzLm1ha2VBcnJheSkodmFsdWUkJDEpKTsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgLy8gaXQgaXMgcG9zc2libGUgdG8gdXNlIGNvbmNhdGVuYXRlZFByb3BlcnRpZXMgd2l0aCBzdHJpbmdzICh3aGljaCBjYW5ub3QgYmUgZnJvemVuKQogICAgICAvLyBvbmx5IGZyZWV6ZSBvYmplY3RzLi4uCiAgICAgIGlmICh0eXBlb2YgcmV0ID09PSAnb2JqZWN0JyAmJiByZXQgIT09IG51bGwpIHsKICAgICAgICAvLyBwcmV2ZW50IG11dGF0aW5nIGBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzYCBhcnJheSBhZnRlciBpdCBpcyBhcHBsaWVkCiAgICAgICAgT2JqZWN0LmZyZWV6ZShyZXQpOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJldDsKICB9CgogIGZ1bmN0aW9uIGFwcGx5TWVyZ2VkUHJvcGVydGllcyhvYmosIGtleSwgdmFsdWUkJDEsIHZhbHVlcykgewogICAgdmFyIGJhc2VWYWx1ZSA9IHZhbHVlc1trZXldIHx8IG9ialtrZXldOwogICAgKGZhbHNlICYmICEoIWlzQXJyYXkodmFsdWUkJDEpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBwYXNzZWQgaW4gYCIgKyBKU09OLnN0cmluZ2lmeSh2YWx1ZSQkMSkgKyAiYCBhcyB0aGUgdmFsdWUgZm9yIGAiICsga2V5ICsgImAgYnV0IGAiICsga2V5ICsgImAgY2Fubm90IGJlIGFuIEFycmF5IiwgIWlzQXJyYXkodmFsdWUkJDEpKSk7CgogICAgaWYgKCFiYXNlVmFsdWUpIHsKICAgICAgcmV0dXJuIHZhbHVlJCQxOwogICAgfQoKICAgIHZhciBuZXdCYXNlID0gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgYmFzZVZhbHVlKTsKICAgIHZhciBoYXNGdW5jdGlvbiA9IGZhbHNlOwoKICAgIGZvciAodmFyIHByb3AgaW4gdmFsdWUkJDEpIHsKICAgICAgaWYgKCF2YWx1ZSQkMS5oYXNPd25Qcm9wZXJ0eShwcm9wKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICB2YXIgcHJvcFZhbHVlID0gdmFsdWUkJDFbcHJvcF07CgogICAgICBpZiAoaXNNZXRob2QocHJvcFZhbHVlKSkgewogICAgICAgIC8vIFRPRE86IHN1cHBvcnQgZm9yIENvbXB1dGVkIFByb3BlcnRpZXMsIGV0Yz8KICAgICAgICBoYXNGdW5jdGlvbiA9IHRydWU7CiAgICAgICAgbmV3QmFzZVtwcm9wXSA9IGdpdmVNZXRob2RTdXBlcihvYmosIHByb3AsIHByb3BWYWx1ZSwgYmFzZVZhbHVlLCB7fSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmV3QmFzZVtwcm9wXSA9IHByb3BWYWx1ZTsKICAgICAgfQogICAgfQoKICAgIGlmIChoYXNGdW5jdGlvbikgewogICAgICBuZXdCYXNlLl9zdXBlciA9IF91dGlscy5ST09UOwogICAgfQoKICAgIHJldHVybiBuZXdCYXNlOwogIH0KCiAgZnVuY3Rpb24gYWRkTm9ybWFsaXplZFByb3BlcnR5KGJhc2UsIGtleSwgdmFsdWUkJDEsIG1ldGEkJDEsIGRlc2NzLCB2YWx1ZXMsIGNvbmNhdHMsIG1lcmdpbmdzKSB7CiAgICBpZiAoaXNDbGFzc2ljRGVjb3JhdG9yKHZhbHVlJCQxKSkgewogICAgICAvLyBXcmFwIGRlc2NyaXB0b3IgZnVuY3Rpb24gdG8gaW1wbGVtZW50IF9zdXBlcigpIGlmIG5lZWRlZAogICAgICBkZXNjc1trZXldID0gZ2l2ZURlY29yYXRvclN1cGVyKG1ldGEkJDEsIGtleSwgdmFsdWUkJDEsIHZhbHVlcywgZGVzY3MsIGJhc2UpOwogICAgICB2YWx1ZXNba2V5XSA9IHVuZGVmaW5lZDsKICAgIH0gZWxzZSB7CiAgICAgIGlmIChjb25jYXRzICYmIGNvbmNhdHMuaW5kZXhPZihrZXkpID49IDAgfHwga2V5ID09PSAnY29uY2F0ZW5hdGVkUHJvcGVydGllcycgfHwga2V5ID09PSAnbWVyZ2VkUHJvcGVydGllcycpIHsKICAgICAgICB2YWx1ZSQkMSA9IGFwcGx5Q29uY2F0ZW5hdGVkUHJvcGVydGllcyhiYXNlLCBrZXksIHZhbHVlJCQxLCB2YWx1ZXMpOwogICAgICB9IGVsc2UgaWYgKG1lcmdpbmdzICYmIG1lcmdpbmdzLmluZGV4T2Yoa2V5KSA+IC0xKSB7CiAgICAgICAgdmFsdWUkJDEgPSBhcHBseU1lcmdlZFByb3BlcnRpZXMoYmFzZSwga2V5LCB2YWx1ZSQkMSwgdmFsdWVzKTsKICAgICAgfSBlbHNlIGlmIChpc01ldGhvZCh2YWx1ZSQkMSkpIHsKICAgICAgICB2YWx1ZSQkMSA9IGdpdmVNZXRob2RTdXBlcihiYXNlLCBrZXksIHZhbHVlJCQxLCB2YWx1ZXMsIGRlc2NzKTsKICAgICAgfQoKICAgICAgZGVzY3Nba2V5XSA9IHVuZGVmaW5lZDsKICAgICAgdmFsdWVzW2tleV0gPSB2YWx1ZSQkMTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIG1lcmdlTWl4aW5zKG1peGlucywgbWV0YSQkMSwgZGVzY3MsIHZhbHVlcywgYmFzZSwga2V5cykgewogICAgdmFyIGN1cnJlbnRNaXhpbiwgcHJvcHMsIGtleSwgY29uY2F0cywgbWVyZ2luZ3M7CgogICAgZnVuY3Rpb24gcmVtb3ZlS2V5cyhrZXlOYW1lKSB7CiAgICAgIGRlbGV0ZSBkZXNjc1trZXlOYW1lXTsKICAgICAgZGVsZXRlIHZhbHVlc1trZXlOYW1lXTsKICAgIH0KCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1peGlucy5sZW5ndGg7IGkrKykgewogICAgICBjdXJyZW50TWl4aW4gPSBtaXhpbnNbaV07CiAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBjdXJyZW50TWl4aW4gPT09ICdvYmplY3QnICYmIGN1cnJlbnRNaXhpbiAhPT0gbnVsbCAmJiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoY3VycmVudE1peGluKSAhPT0gJ1tvYmplY3QgQXJyYXldJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJFeHBlY3RlZCBoYXNoIG9yIE1peGluIGluc3RhbmNlLCBnb3QgIiArIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChjdXJyZW50TWl4aW4pLCB0eXBlb2YgY3VycmVudE1peGluID09PSAnb2JqZWN0JyAmJiBjdXJyZW50TWl4aW4gIT09IG51bGwgJiYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGN1cnJlbnRNaXhpbikgIT09ICdbb2JqZWN0IEFycmF5XScpKTsKICAgICAgcHJvcHMgPSBtaXhpblByb3BlcnRpZXMobWV0YSQkMSwgY3VycmVudE1peGluKTsKCiAgICAgIGlmIChwcm9wcyA9PT0gQ09OVElOVUUpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQoKICAgICAgaWYgKHByb3BzKSB7CiAgICAgICAgLy8gcmVtb3ZlIHdpbGxNZXJnZU1peGluIGFmdGVyIDMuNCBhcyBpdCB3YXMgdXNlZCBmb3IgX2FjdGlvbnMKICAgICAgICBpZiAoYmFzZS53aWxsTWVyZ2VNaXhpbikgewogICAgICAgICAgYmFzZS53aWxsTWVyZ2VNaXhpbihwcm9wcyk7CiAgICAgICAgfQoKICAgICAgICBjb25jYXRzID0gY29uY2F0ZW5hdGVkTWl4aW5Qcm9wZXJ0aWVzKCdjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzJywgcHJvcHMsIHZhbHVlcywgYmFzZSk7CiAgICAgICAgbWVyZ2luZ3MgPSBjb25jYXRlbmF0ZWRNaXhpblByb3BlcnRpZXMoJ21lcmdlZFByb3BlcnRpZXMnLCBwcm9wcywgdmFsdWVzLCBiYXNlKTsKCiAgICAgICAgZm9yIChrZXkgaW4gcHJvcHMpIHsKICAgICAgICAgIGlmICghcHJvcHMuaGFzT3duUHJvcGVydHkoa2V5KSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KCiAgICAgICAgICBrZXlzLnB1c2goa2V5KTsKICAgICAgICAgIGFkZE5vcm1hbGl6ZWRQcm9wZXJ0eShiYXNlLCBrZXksIHByb3BzW2tleV0sIG1ldGEkJDEsIGRlc2NzLCB2YWx1ZXMsIGNvbmNhdHMsIG1lcmdpbmdzKTsKICAgICAgICB9IC8vIG1hbnVhbGx5IGNvcHkgdG9TdHJpbmcoKSBiZWNhdXNlIHNvbWUgSlMgZW5naW5lcyBkbyBub3QgZW51bWVyYXRlIGl0CgoKICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoJ3RvU3RyaW5nJykpIHsKICAgICAgICAgIGJhc2UudG9TdHJpbmcgPSBwcm9wcy50b1N0cmluZzsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY3VycmVudE1peGluLm1peGlucykgewogICAgICAgIG1lcmdlTWl4aW5zKGN1cnJlbnRNaXhpbi5taXhpbnMsIG1ldGEkJDEsIGRlc2NzLCB2YWx1ZXMsIGJhc2UsIGtleXMpOwoKICAgICAgICBpZiAoY3VycmVudE1peGluLl93aXRob3V0KSB7CiAgICAgICAgICBjdXJyZW50TWl4aW4uX3dpdGhvdXQuZm9yRWFjaChyZW1vdmVLZXlzKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CgogIHZhciBmb2xsb3dNZXRob2RBbGlhczsKCiAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuQUxJQVNfTUVUSE9EKSB7CiAgICBmb2xsb3dNZXRob2RBbGlhcyA9IGZ1bmN0aW9uIGZvbGxvd01ldGhvZEFsaWFzKG9iaiwgYWxpYXMsIGRlc2NzLCB2YWx1ZXMpIHsKICAgICAgdmFyIGFsdEtleSA9IGFsaWFzLm1ldGhvZE5hbWU7CiAgICAgIHZhciBwb3NzaWJsZURlc2M7CiAgICAgIHZhciBkZXNjID0gZGVzY3NbYWx0S2V5XTsKICAgICAgdmFyIHZhbHVlJCQxID0gdmFsdWVzW2FsdEtleV07CgogICAgICBpZiAoZGVzYyAhPT0gdW5kZWZpbmVkIHx8IHZhbHVlJCQxICE9PSB1bmRlZmluZWQpIHsvLyBkbyBub3RoaW5nCiAgICAgIH0gZWxzZSBpZiAoKHBvc3NpYmxlRGVzYyA9IGRlc2NyaXB0b3JGb3JQcm9wZXJ0eShvYmosIGFsdEtleSkpICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBkZXNjID0gcG9zc2libGVEZXNjOwogICAgICAgIHZhbHVlJCQxID0gdW5kZWZpbmVkOwogICAgICB9IGVsc2UgewogICAgICAgIGRlc2MgPSB1bmRlZmluZWQ7CiAgICAgICAgdmFsdWUkJDEgPSBvYmpbYWx0S2V5XTsKICAgICAgfQoKICAgICAgcmV0dXJuIHsKICAgICAgICBkZXNjOiBkZXNjLAogICAgICAgIHZhbHVlOiB2YWx1ZSQkMQogICAgICB9OwogICAgfTsKICB9CgogIGZ1bmN0aW9uIHVwZGF0ZU9ic2VydmVyc0FuZExpc3RlbmVycyhvYmosIGtleSwgZm4sIGFkZCkgewogICAgdmFyIG9ic2VydmVycyA9ICgwLCBfdXRpbHMuZ2V0T2JzZXJ2ZXJzKShmbik7CiAgICB2YXIgbGlzdGVuZXJzID0gKDAsIF91dGlscy5nZXRMaXN0ZW5lcnMpKGZuKTsKCiAgICBpZiAob2JzZXJ2ZXJzICE9PSB1bmRlZmluZWQpIHsKICAgICAgdmFyIHVwZGF0ZU9ic2VydmVyID0gYWRkID8gYWRkT2JzZXJ2ZXIgOiByZW1vdmVPYnNlcnZlcjsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JzZXJ2ZXJzLnBhdGhzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdXBkYXRlT2JzZXJ2ZXIob2JqLCBvYnNlcnZlcnMucGF0aHNbaV0sIG51bGwsIGtleSwgb2JzZXJ2ZXJzLnN5bmMpOwogICAgICB9CiAgICB9CgogICAgaWYgKGxpc3RlbmVycyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHZhciB1cGRhdGVMaXN0ZW5lciA9IGFkZCA/IGFkZExpc3RlbmVyIDogcmVtb3ZlTGlzdGVuZXI7CgogICAgICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBsaXN0ZW5lcnMubGVuZ3RoOyBfaTIrKykgewogICAgICAgIHVwZGF0ZUxpc3RlbmVyKG9iaiwgbGlzdGVuZXJzW19pMl0sIG51bGwsIGtleSk7CiAgICAgIH0KICAgIH0KICB9CgogIGZ1bmN0aW9uIHJlcGxhY2VPYnNlcnZlcnNBbmRMaXN0ZW5lcnMob2JqLCBrZXksIHByZXYsIG5leHQpIHsKICAgIGlmICh0eXBlb2YgcHJldiA9PT0gJ2Z1bmN0aW9uJykgewogICAgICB1cGRhdGVPYnNlcnZlcnNBbmRMaXN0ZW5lcnMob2JqLCBrZXksIHByZXYsIGZhbHNlKTsKICAgIH0KCiAgICBpZiAodHlwZW9mIG5leHQgPT09ICdmdW5jdGlvbicpIHsKICAgICAgdXBkYXRlT2JzZXJ2ZXJzQW5kTGlzdGVuZXJzKG9iaiwga2V5LCBuZXh0LCB0cnVlKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGFwcGx5TWl4aW4ob2JqLCBtaXhpbnMpIHsKICAgIHZhciBkZXNjcyA9IHt9OwogICAgdmFyIHZhbHVlcyA9IHt9OwogICAgdmFyIG1ldGEkJDEgPSAoMCwgX21ldGEyLm1ldGEpKG9iaik7CiAgICB2YXIga2V5cyA9IFtdOwogICAgdmFyIGtleSwgdmFsdWUkJDEsIGRlc2M7CiAgICBvYmouX3N1cGVyID0gX3V0aWxzLlJPT1Q7IC8vIEdvIHRocm91Z2ggYWxsIG1peGlucyBhbmQgaGFzaGVzIHBhc3NlZCBpbiwgYW5kOgogICAgLy8KICAgIC8vICogSGFuZGxlIGNvbmNhdGVuYXRlZCBwcm9wZXJ0aWVzCiAgICAvLyAqIEhhbmRsZSBtZXJnZWQgcHJvcGVydGllcwogICAgLy8gKiBTZXQgdXAgX3N1cGVyIHdyYXBwaW5nIGlmIG5lY2Vzc2FyeQogICAgLy8gKiBTZXQgdXAgY29tcHV0ZWQgcHJvcGVydHkgZGVzY3JpcHRvcnMKICAgIC8vICogQ29weWluZyBgdG9TdHJpbmdgIGluIGJyb2tlbiBicm93c2VycwoKICAgIG1lcmdlTWl4aW5zKG1peGlucywgbWV0YSQkMSwgZGVzY3MsIHZhbHVlcywgb2JqLCBrZXlzKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgICAga2V5ID0ga2V5c1tpXTsKCiAgICAgIGlmIChrZXkgPT09ICdjb25zdHJ1Y3RvcicgfHwgIXZhbHVlcy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIGRlc2MgPSBkZXNjc1trZXldOwogICAgICB2YWx1ZSQkMSA9IHZhbHVlc1trZXldOwoKICAgICAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuQUxJQVNfTUVUSE9EKSB7CiAgICAgICAgd2hpbGUgKHZhbHVlJCQxICYmIHZhbHVlJCQxIGluc3RhbmNlb2YgQWxpYXNJbXBsKSB7CiAgICAgICAgICB2YXIgZm9sbG93ZWQgPSBmb2xsb3dNZXRob2RBbGlhcyhvYmosIHZhbHVlJCQxLCBkZXNjcywgdmFsdWVzKTsKICAgICAgICAgIGRlc2MgPSBmb2xsb3dlZC5kZXNjOwogICAgICAgICAgdmFsdWUkJDEgPSBmb2xsb3dlZC52YWx1ZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChkZXNjID09PSB1bmRlZmluZWQgJiYgdmFsdWUkJDEgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICBpZiAoZGVzY3JpcHRvckZvclByb3BlcnR5KG9iaiwga2V5KSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmVwbGFjZU9ic2VydmVyc0FuZExpc3RlbmVycyhvYmosIGtleSwgbnVsbCwgdmFsdWUkJDEpOwogICAgICB9IGVsc2UgewogICAgICAgIHJlcGxhY2VPYnNlcnZlcnNBbmRMaXN0ZW5lcnMob2JqLCBrZXksIG9ialtrZXldLCB2YWx1ZSQkMSk7CiAgICAgIH0KCiAgICAgIGRlZmluZVByb3BlcnR5KG9iaiwga2V5LCBkZXNjLCB2YWx1ZSQkMSwgbWV0YSQkMSk7CiAgICB9CgogICAgcmV0dXJuIG9iajsKICB9CiAgLyoqCiAgICBAbWV0aG9kIG1peGluCiAgICBAcGFyYW0gb2JqCiAgICBAcGFyYW0gbWl4aW5zKgogICAgQHJldHVybiBvYmoKICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIG1peGluKG9iaikgewogICAgZm9yICh2YXIgX2xlbjQgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW40ID4gMSA/IF9sZW40IC0gMSA6IDApLCBfa2V5NSA9IDE7IF9rZXk1IDwgX2xlbjQ7IF9rZXk1KyspIHsKICAgICAgYXJnc1tfa2V5NSAtIDFdID0gYXJndW1lbnRzW19rZXk1XTsKICAgIH0KCiAgICBhcHBseU1peGluKG9iaiwgYXJncyk7CiAgICByZXR1cm4gb2JqOwogIH0KICAvKioKICAgIFRoZSBgTWl4aW5gIGNsYXNzIGFsbG93cyB5b3UgdG8gY3JlYXRlIG1peGlucywgd2hvc2UgcHJvcGVydGllcyBjYW4gYmUKICAgIGFkZGVkIHRvIG90aGVyIGNsYXNzZXMuIEZvciBpbnN0YW5jZSwKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBNaXhpbiBmcm9tICdAZW1iZXIvb2JqZWN0L21peGluJzsKICAKICAgIGNvbnN0IEVkaXRhYmxlTWl4aW4gPSBNaXhpbi5jcmVhdGUoewogICAgICBlZGl0KCkgewogICAgICAgIGNvbnNvbGUubG9nKCdzdGFydGluZyB0byBlZGl0Jyk7CiAgICAgICAgdGhpcy5zZXQoJ2lzRWRpdGluZycsIHRydWUpOwogICAgICB9LAogICAgICBpc0VkaXRpbmc6IGZhbHNlCiAgICB9KTsKICAgIGBgYAogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IEVkaXRhYmxlTWl4aW4gZnJvbSAnLi4vbWl4aW5zL2VkaXRhYmxlJzsKICAKICAgIC8vIE1peCBtaXhpbnMgaW50byBjbGFzc2VzIGJ5IHBhc3NpbmcgdGhlbSBhcyB0aGUgZmlyc3QgYXJndW1lbnRzIHRvCiAgICAvLyBgLmV4dGVuZC5gCiAgICBjb25zdCBDb21tZW50ID0gRW1iZXJPYmplY3QuZXh0ZW5kKEVkaXRhYmxlTWl4aW4sIHsKICAgICAgcG9zdDogbnVsbAogICAgfSk7CiAgCiAgICBsZXQgY29tbWVudCA9IENvbW1lbnQuY3JlYXRlKHsKICAgICAgcG9zdDogc29tZVBvc3QKICAgIH0pOwogIAogICAgY29tbWVudC5lZGl0KCk7IC8vIG91dHB1dHMgJ3N0YXJ0aW5nIHRvIGVkaXQnCiAgICBgYGAKICAKICAgIE5vdGUgdGhhdCBNaXhpbnMgYXJlIGNyZWF0ZWQgd2l0aCBgTWl4aW4uY3JlYXRlYCwgbm90CiAgICBgTWl4aW4uZXh0ZW5kYC4KICAKICAgIE5vdGUgdGhhdCBtaXhpbnMgZXh0ZW5kIGEgY29uc3RydWN0b3IncyBwcm90b3R5cGUgc28gYXJyYXlzIGFuZCBvYmplY3QgbGl0ZXJhbHMKICAgIGRlZmluZWQgYXMgcHJvcGVydGllcyB3aWxsIGJlIHNoYXJlZCBhbW9uZ3N0IG9iamVjdHMgdGhhdCBpbXBsZW1lbnQgdGhlIG1peGluLgogICAgSWYgeW91IHdhbnQgdG8gZGVmaW5lIGEgcHJvcGVydHkgaW4gYSBtaXhpbiB0aGF0IGlzIG5vdCBzaGFyZWQsIHlvdSBjYW4gZGVmaW5lCiAgICBpdCBlaXRoZXIgYXMgYSBjb21wdXRlZCBwcm9wZXJ0eSBvciBoYXZlIGl0IGJlIGNyZWF0ZWQgb24gaW5pdGlhbGl6YXRpb24gb2YgdGhlIG9iamVjdC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIC8vIGZpbHRlcnMgYXJyYXkgd2lsbCBiZSBzaGFyZWQgYW1vbmdzdCBhbnkgb2JqZWN0IGltcGxlbWVudGluZyBtaXhpbgogICAgaW1wb3J0IE1peGluIGZyb20gJ0BlbWJlci9vYmplY3QvbWl4aW4nOwogICAgaW1wb3J0IHsgQSB9IGZyb20gJ0BlbWJlci9hcnJheSc7CiAgCiAgICBjb25zdCBGaWx0ZXJhYmxlTWl4aW4gPSBNaXhpbi5jcmVhdGUoewogICAgICBmaWx0ZXJzOiBBKCkKICAgIH0pOwogICAgYGBgCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgTWl4aW4gZnJvbSAnQGVtYmVyL29iamVjdC9taXhpbic7CiAgICBpbXBvcnQgeyBBIH0gZnJvbSAnQGVtYmVyL2FycmF5JzsKICAgIGltcG9ydCB7IGNvbXB1dGVkIH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgCiAgICAvLyBmaWx0ZXJzIHdpbGwgYmUgYSBzZXBhcmF0ZSBhcnJheSBmb3IgZXZlcnkgb2JqZWN0IGltcGxlbWVudGluZyB0aGUgbWl4aW4KICAgIGNvbnN0IEZpbHRlcmFibGVNaXhpbiA9IE1peGluLmNyZWF0ZSh7CiAgICAgIGZpbHRlcnM6IGNvbXB1dGVkKGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBBKCk7CiAgICAgIH0pCiAgICB9KTsKICAgIGBgYAogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IE1peGluIGZyb20gJ0BlbWJlci9vYmplY3QvbWl4aW4nOwogICAgaW1wb3J0IHsgQSB9IGZyb20gJ0BlbWJlci9hcnJheSc7CiAgCiAgICAvLyBmaWx0ZXJzIHdpbGwgYmUgY3JlYXRlZCBhcyBhIHNlcGFyYXRlIGFycmF5IGR1cmluZyB0aGUgb2JqZWN0J3MgaW5pdGlhbGl6YXRpb24KICAgIGNvbnN0IEZpbHRlcmFibGUgPSBNaXhpbi5jcmVhdGUoewogICAgICBmaWx0ZXJzOiBudWxsLAogIAogICAgICBpbml0KCkgewogICAgICAgIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cyk7CiAgICAgICAgdGhpcy5zZXQoImZpbHRlcnMiLCBBKCkpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQGNsYXNzIE1peGluCiAgICBAcHVibGljCiAgKi8KCgogIHZhciBNaXhpbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIE1peGluKG1peGlucywgcHJvcGVydGllcykgewogICAgICB0aGlzLnByb3BlcnRpZXMgPSBleHRyYWN0QWNjZXNzb3JzKHByb3BlcnRpZXMpOwogICAgICB0aGlzLm1peGlucyA9IGJ1aWxkTWl4aW5zQXJyYXkobWl4aW5zKTsKICAgICAgdGhpcy5vd25lckNvbnN0cnVjdG9yID0gdW5kZWZpbmVkOwogICAgICB0aGlzLl93aXRob3V0ID0gdW5kZWZpbmVkOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIC8qCiAgICAgICAgICBJbiBkZWJ1ZyBidWlsZHMsIHdlIHNlYWwgbWl4aW5zIHRvIGhlbHAgYXZvaWQgcGVyZm9ybWFuY2UgcGl0ZmFsbHMuCiAgICAgICAgICAgICAgICAgSW4gSUUxMSB0aGVyZSBpcyBhIHF1aXJrIHRoYXQgcHJldmVudHMgc2VhbGVkIG9iamVjdHMgZnJvbSBiZWluZyBhZGRlZAogICAgICAgICAgdG8gYSBXZWFrTWFwLiBVbmZvcnR1bmF0ZWx5LCB0aGUgbWl4aW4gc3lzdGVtIGN1cnJlbnRseSByZWxpZXMgb24KICAgICAgICAgIHdlYWsgbWFwcyBpbiBgZ3VpZEZvcmAsIHNvIHdlIG5lZWQgdG8gcHJpbWUgdGhlIGd1aWQgY2FjaGUgd2VhayBtYXAuCiAgICAgICAgKi8KICAgICAgICAoMCwgX3V0aWxzLmd1aWRGb3IpKHRoaXMpOwogICAgICAgIE9iamVjdC5zZWFsKHRoaXMpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgQG1ldGhvZCBjcmVhdGUKICAgICAgQGZvciBAZW1iZXIvb2JqZWN0L21peGluCiAgICAgIEBzdGF0aWMKICAgICAgQHBhcmFtIGFyZ3VtZW50cyoKICAgICAgQHB1YmxpYwogICAgKi8KCgogICAgTWl4aW4uY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKCkgewogICAgICAvLyBFUzZUT0RPOiB0aGlzIHJlbGllcyBvbiBhIGdsb2JhbCBzdGF0ZT8KICAgICAgc2V0VW5wcm9jZXNzZWRNaXhpbnMoKTsKICAgICAgdmFyIE0gPSB0aGlzOwoKICAgICAgZm9yICh2YXIgX2xlbjUgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW41KSwgX2tleTYgPSAwOyBfa2V5NiA8IF9sZW41OyBfa2V5NisrKSB7CiAgICAgICAgYXJnc1tfa2V5Nl0gPSBhcmd1bWVudHNbX2tleTZdOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IE0oYXJncywgdW5kZWZpbmVkKTsKICAgIH0gLy8gcmV0dXJucyB0aGUgbWl4aW5zIGN1cnJlbnRseSBhcHBsaWVkIHRvIHRoZSBzcGVjaWZpZWQgb2JqZWN0CiAgICAvLyBUT0RPOiBNYWtlIGBtaXhpbmAKICAgIDsKCiAgICBNaXhpbi5taXhpbnMgPSBmdW5jdGlvbiBtaXhpbnMob2JqKSB7CiAgICAgIHZhciBtZXRhJCQxID0gKDAsIF9tZXRhMi5wZWVrTWV0YSkob2JqKTsKICAgICAgdmFyIHJldCA9IFtdOwoKICAgICAgaWYgKG1ldGEkJDEgPT09IG51bGwpIHsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9CgogICAgICBtZXRhJCQxLmZvckVhY2hNaXhpbnMoZnVuY3Rpb24gKGN1cnJlbnRNaXhpbikgewogICAgICAgIC8vIHNraXAgcHJpbWl0aXZlIG1peGlucyBzaW5jZSB0aGVzZSBhcmUgYWx3YXlzIGFub255bW91cwogICAgICAgIGlmICghY3VycmVudE1peGluLnByb3BlcnRpZXMpIHsKICAgICAgICAgIHJldC5wdXNoKGN1cnJlbnRNaXhpbik7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIHJldDsKICAgIH0KICAgIC8qKgogICAgICBAbWV0aG9kIHJlb3BlbgogICAgICBAcGFyYW0gYXJndW1lbnRzKgogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICB2YXIgX3Byb3RvMTIgPSBNaXhpbi5wcm90b3R5cGU7CgogICAgX3Byb3RvMTIucmVvcGVuID0gZnVuY3Rpb24gcmVvcGVuKCkgewogICAgICBmb3IgKHZhciBfbGVuNiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjYpLCBfa2V5NyA9IDA7IF9rZXk3IDwgX2xlbjY7IF9rZXk3KyspIHsKICAgICAgICBhcmdzW19rZXk3XSA9IGFyZ3VtZW50c1tfa2V5N107CiAgICAgIH0KCiAgICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgaWYgKHRoaXMucHJvcGVydGllcykgewogICAgICAgIHZhciBjdXJyZW50TWl4aW4gPSBuZXcgTWl4aW4odW5kZWZpbmVkLCB0aGlzLnByb3BlcnRpZXMpOwogICAgICAgIHRoaXMucHJvcGVydGllcyA9IHVuZGVmaW5lZDsKICAgICAgICB0aGlzLm1peGlucyA9IFtjdXJyZW50TWl4aW5dOwogICAgICB9IGVsc2UgaWYgKCF0aGlzLm1peGlucykgewogICAgICAgIHRoaXMubWl4aW5zID0gW107CiAgICAgIH0KCiAgICAgIHRoaXMubWl4aW5zID0gdGhpcy5taXhpbnMuY29uY2F0KGJ1aWxkTWl4aW5zQXJyYXkoYXJncykpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0KICAgIC8qKgogICAgICBAbWV0aG9kIGFwcGx5CiAgICAgIEBwYXJhbSBvYmoKICAgICAgQHJldHVybiBhcHBsaWVkIG9iamVjdAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8xMi5hcHBseSA9IGZ1bmN0aW9uIGFwcGx5KG9iaikgewogICAgICByZXR1cm4gYXBwbHlNaXhpbihvYmosIFt0aGlzXSk7CiAgICB9OwoKICAgIF9wcm90bzEyLmFwcGx5UGFydGlhbCA9IGZ1bmN0aW9uIGFwcGx5UGFydGlhbChvYmopIHsKICAgICAgcmV0dXJuIGFwcGx5TWl4aW4ob2JqLCBbdGhpc10pOwogICAgfQogICAgLyoqCiAgICAgIEBtZXRob2QgZGV0ZWN0CiAgICAgIEBwYXJhbSBvYmoKICAgICAgQHJldHVybiB7Qm9vbGVhbn0KICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvMTIuZGV0ZWN0ID0gZnVuY3Rpb24gZGV0ZWN0KG9iaikgewogICAgICBpZiAodHlwZW9mIG9iaiAhPT0gJ29iamVjdCcgfHwgb2JqID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CgogICAgICBpZiAob2JqIGluc3RhbmNlb2YgTWl4aW4pIHsKICAgICAgICByZXR1cm4gX2RldGVjdChvYmosIHRoaXMpOwogICAgICB9CgogICAgICB2YXIgbWV0YSQkMSA9ICgwLCBfbWV0YTIucGVla01ldGEpKG9iaik7CgogICAgICBpZiAobWV0YSQkMSA9PT0gbnVsbCkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgcmV0dXJuIG1ldGEkJDEuaGFzTWl4aW4odGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzEyLndpdGhvdXQgPSBmdW5jdGlvbiB3aXRob3V0KCkgewogICAgICB2YXIgcmV0ID0gbmV3IE1peGluKFt0aGlzXSk7CgogICAgICBmb3IgKHZhciBfbGVuNyA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjcpLCBfa2V5OCA9IDA7IF9rZXk4IDwgX2xlbjc7IF9rZXk4KyspIHsKICAgICAgICBhcmdzW19rZXk4XSA9IGFyZ3VtZW50c1tfa2V5OF07CiAgICAgIH0KCiAgICAgIHJldC5fd2l0aG91dCA9IGFyZ3M7CiAgICAgIHJldHVybiByZXQ7CiAgICB9OwoKICAgIF9wcm90bzEyLmtleXMgPSBmdW5jdGlvbiBrZXlzKCkgewogICAgICByZXR1cm4gX2tleXModGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzEyLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiAnKHVua25vd24gbWl4aW4pJzsKICAgIH07CgogICAgcmV0dXJuIE1peGluOwogIH0oKTsKCiAgX2V4cG9ydHMuTWl4aW4gPSBNaXhpbjsKCiAgZnVuY3Rpb24gYnVpbGRNaXhpbnNBcnJheShtaXhpbnMpIHsKICAgIHZhciBsZW5ndGggPSBtaXhpbnMgJiYgbWl4aW5zLmxlbmd0aCB8fCAwOwogICAgdmFyIG0gPSB1bmRlZmluZWQ7CgogICAgaWYgKGxlbmd0aCA+IDApIHsKICAgICAgbSA9IG5ldyBBcnJheShsZW5ndGgpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgIHZhciB4ID0gbWl4aW5zW2ldOwogICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiB4ID09PSAnb2JqZWN0JyAmJiB4ICE9PSBudWxsICYmIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KSAhPT0gJ1tvYmplY3QgQXJyYXldJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJFeHBlY3RlZCBoYXNoIG9yIE1peGluIGluc3RhbmNlLCBnb3QgIiArIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KSwgdHlwZW9mIHggPT09ICdvYmplY3QnICYmIHggIT09IG51bGwgJiYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHgpICE9PSAnW29iamVjdCBBcnJheV0nKSk7CgogICAgICAgIGlmICh4IGluc3RhbmNlb2YgTWl4aW4pIHsKICAgICAgICAgIG1baV0gPSB4OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBtW2ldID0gbmV3IE1peGluKHVuZGVmaW5lZCwgeCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgcmV0dXJuIG07CiAgfQoKICBNaXhpbi5wcm90b3R5cGUudG9TdHJpbmcgPSBjbGFzc1RvU3RyaW5nOwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgT2JqZWN0LnNlYWwoTWl4aW4ucHJvdG90eXBlKTsKICB9CgogIGZ1bmN0aW9uIF9kZXRlY3QoY3VyTWl4aW4sIHRhcmdldE1peGluLCBzZWVuKSB7CiAgICBpZiAoc2VlbiA9PT0gdm9pZCAwKSB7CiAgICAgIHNlZW4gPSBuZXcgU2V0KCk7CiAgICB9CgogICAgaWYgKHNlZW4uaGFzKGN1ck1peGluKSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgc2Vlbi5hZGQoY3VyTWl4aW4pOwoKICAgIGlmIChjdXJNaXhpbiA9PT0gdGFyZ2V0TWl4aW4pIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgdmFyIG1peGlucyA9IGN1ck1peGluLm1peGluczsKCiAgICBpZiAobWl4aW5zKSB7CiAgICAgIHJldHVybiBtaXhpbnMuc29tZShmdW5jdGlvbiAobWl4aW4pIHsKICAgICAgICByZXR1cm4gX2RldGVjdChtaXhpbiwgdGFyZ2V0TWl4aW4sIHNlZW4pOwogICAgICB9KTsKICAgIH0KCiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICBmdW5jdGlvbiBfa2V5cyhtaXhpbiwgcmV0LCBzZWVuKSB7CiAgICBpZiAocmV0ID09PSB2b2lkIDApIHsKICAgICAgcmV0ID0gbmV3IFNldCgpOwogICAgfQoKICAgIGlmIChzZWVuID09PSB2b2lkIDApIHsKICAgICAgc2VlbiA9IG5ldyBTZXQoKTsKICAgIH0KCiAgICBpZiAoc2Vlbi5oYXMobWl4aW4pKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBzZWVuLmFkZChtaXhpbik7CgogICAgaWYgKG1peGluLnByb3BlcnRpZXMpIHsKICAgICAgdmFyIHByb3BzID0gT2JqZWN0LmtleXMobWl4aW4ucHJvcGVydGllcyk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgcmV0LmFkZChwcm9wc1tpXSk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAobWl4aW4ubWl4aW5zKSB7CiAgICAgIG1peGluLm1peGlucy5mb3JFYWNoKGZ1bmN0aW9uICh4KSB7CiAgICAgICAgcmV0dXJuIF9rZXlzKHgsIHJldCwgc2Vlbik7CiAgICAgIH0pOwogICAgfQoKICAgIHJldHVybiByZXQ7CiAgfQoKICB2YXIgQWxpYXNJbXBsOwoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5BTElBU19NRVRIT0QpIHsKICAgIEFsaWFzSW1wbCA9IGZ1bmN0aW9uIEFsaWFzSW1wbChtZXRob2ROYW1lKSB7CiAgICAgIHRoaXMubWV0aG9kTmFtZSA9IG1ldGhvZE5hbWU7CiAgICB9OwogIH0KICAvKioKICAgIE1ha2VzIGEgbWV0aG9kIGF2YWlsYWJsZSB2aWEgYW4gYWRkaXRpb25hbCBuYW1lLgogIAogICAgYGBgYXBwL3V0aWxzL3BlcnNvbi5qcwogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7CiAgICAgIGFsaWFzTWV0aG9kCiAgICB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgbmFtZSgpIHsKICAgICAgICByZXR1cm4gJ1RvbWh1ZGEgS2F0emRhbGUnOwogICAgICB9LAogICAgICBtb25pa2VyOiBhbGlhc01ldGhvZCgnbmFtZScpCiAgICB9KTsKICAgIGBgYAogIAogICAgYGBgamF2YXNjcmlwdAogICAgbGV0IGdvb2RHdXkgPSBQZXJzb24uY3JlYXRlKCk7CiAgCiAgICBnb29kR3V5Lm5hbWUoKTsgICAgLy8gJ1RvbWh1ZGEgS2F0emRhbGUnCiAgICBnb29kR3V5Lm1vbmlrZXIoKTsgLy8gJ1RvbWh1ZGEgS2F0emRhbGUnCiAgICBgYGAKICAKICAgIEBtZXRob2QgYWxpYXNNZXRob2QKICAgIEBzdGF0aWMKICAgIEBkZXByZWNhdGVkIFVzZSBhIHNoYXJlZCB1dGlsaXR5IG1ldGhvZCBpbnN0ZWFkCiAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgIEBwYXJhbSB7U3RyaW5nfSBtZXRob2ROYW1lIG5hbWUgb2YgdGhlIG1ldGhvZCB0byBhbGlhcwogICAgQHB1YmxpYwogICovCgoKICB2YXIgYWxpYXNNZXRob2Q7CiAgX2V4cG9ydHMuYWxpYXNNZXRob2QgPSBhbGlhc01ldGhvZDsKCiAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuQUxJQVNfTUVUSE9EKSB7CiAgICBfZXhwb3J0cy5hbGlhc01ldGhvZCA9IGFsaWFzTWV0aG9kID0gZnVuY3Rpb24gYWxpYXNNZXRob2QobWV0aG9kTmFtZSkgewogICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCJZb3UgYXR0ZW1wdGVkIHRvIGFsaWFzICciICsgbWV0aG9kTmFtZSArICIsIGJ1dCBhbGlhc01ldGhvZCBoYXMgYmVlbiBkZXByZWNhdGVkLiBDb25zaWRlciBleHRyYWN0aW5nIHRoZSBtZXRob2QgaW50byBhIHNoYXJlZCB1dGlsaXR5IGZ1bmN0aW9uLiIsIGZhbHNlLCB7CiAgICAgICAgaWQ6ICdvYmplY3QuYWxpYXMtbWV0aG9kJywKICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY19vYmplY3QtYWxpYXMtbWV0aG9kJwogICAgICB9KSk7CiAgICAgIHJldHVybiBuZXcgQWxpYXNJbXBsKG1ldGhvZE5hbWUpOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIG9ic2VydmVyKCkgewogICAgZm9yICh2YXIgX2xlbjggPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW44KSwgX2tleTkgPSAwOyBfa2V5OSA8IF9sZW44OyBfa2V5OSsrKSB7CiAgICAgIGFyZ3NbX2tleTldID0gYXJndW1lbnRzW19rZXk5XTsKICAgIH0KCiAgICB2YXIgZnVuY09yRGVmID0gYXJncy5wb3AoKTsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBmdW5jT3JEZWYgPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIGZ1bmNPckRlZiA9PT0gJ29iamVjdCcgJiYgZnVuY09yRGVmICE9PSBudWxsKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ29ic2VydmVyIG11c3QgYmUgcHJvdmlkZWQgYSBmdW5jdGlvbiBvciBhbiBvYnNlcnZlciBkZWZpbml0aW9uJywgdHlwZW9mIGZ1bmNPckRlZiA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgZnVuY09yRGVmID09PSAnb2JqZWN0JyAmJiBmdW5jT3JEZWYgIT09IG51bGwpKTsKICAgIHZhciBmdW5jLCBkZXBlbmRlbnRLZXlzLCBzeW5jOwoKICAgIGlmICh0eXBlb2YgZnVuY09yRGVmID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIGZ1bmMgPSBmdW5jT3JEZWY7CiAgICAgIGRlcGVuZGVudEtleXMgPSBhcmdzOwogICAgICBzeW5jID0gIV9lbnZpcm9ubWVudC5FTlYuX0RFRkFVTFRfQVNZTkNfT0JTRVJWRVJTOwogICAgfSBlbHNlIHsKICAgICAgZnVuYyA9IGZ1bmNPckRlZi5mbjsKICAgICAgZGVwZW5kZW50S2V5cyA9IGZ1bmNPckRlZi5kZXBlbmRlbnRLZXlzOwogICAgICBzeW5jID0gZnVuY09yRGVmLnN5bmM7CiAgICB9CgogICAgKGZhbHNlICYmICEodHlwZW9mIGZ1bmMgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnb2JzZXJ2ZXIgY2FsbGVkIHdpdGhvdXQgYSBmdW5jdGlvbicsIHR5cGVvZiBmdW5jID09PSAnZnVuY3Rpb24nKSk7CiAgICAoZmFsc2UgJiYgIShBcnJheS5pc0FycmF5KGRlcGVuZGVudEtleXMpICYmIGRlcGVuZGVudEtleXMubGVuZ3RoID4gMCAmJiBkZXBlbmRlbnRLZXlzLmV2ZXJ5KGZ1bmN0aW9uIChwKSB7CiAgICAgIHJldHVybiB0eXBlb2YgcCA9PT0gJ3N0cmluZycgJiYgQm9vbGVhbihwLmxlbmd0aCk7CiAgICB9KSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdvYnNlcnZlciBjYWxsZWQgd2l0aG91dCB2YWxpZCBwYXRoJywgQXJyYXkuaXNBcnJheShkZXBlbmRlbnRLZXlzKSAmJiBkZXBlbmRlbnRLZXlzLmxlbmd0aCA+IDAgJiYgZGVwZW5kZW50S2V5cy5ldmVyeShmdW5jdGlvbiAocCkgewogICAgICByZXR1cm4gdHlwZW9mIHAgPT09ICdzdHJpbmcnICYmIEJvb2xlYW4ocC5sZW5ndGgpOwogICAgfSkpKTsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBzeW5jID09PSAnYm9vbGVhbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnb2JzZXJ2ZXIgY2FsbGVkIHdpdGhvdXQgc3luYycsIHR5cGVvZiBzeW5jID09PSAnYm9vbGVhbicpKTsKICAgIHZhciBwYXRocyA9IFtdOwoKICAgIHZhciBhZGRXYXRjaGVkUHJvcGVydHkgPSBmdW5jdGlvbiBhZGRXYXRjaGVkUHJvcGVydHkocGF0aCkgewogICAgICByZXR1cm4gcGF0aHMucHVzaChwYXRoKTsKICAgIH07CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkZXBlbmRlbnRLZXlzLmxlbmd0aDsgKytpKSB7CiAgICAgIGV4cGFuZFByb3BlcnRpZXMoZGVwZW5kZW50S2V5c1tpXSwgYWRkV2F0Y2hlZFByb3BlcnR5KTsKICAgIH0KCiAgICAoMCwgX3V0aWxzLnNldE9ic2VydmVycykoZnVuYywgewogICAgICBwYXRoczogcGF0aHMsCiAgICAgIHN5bmM6IHN5bmMKICAgIH0pOwogICAgcmV0dXJuIGZ1bmM7CiAgfQoKICB2YXIgREVCVUdfSU5KRUNUSU9OX0ZVTkNUSU9OUzsKICBfZXhwb3J0cy5ERUJVR19JTkpFQ1RJT05fRlVOQ1RJT05TID0gREVCVUdfSU5KRUNUSU9OX0ZVTkNUSU9OUzsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIF9leHBvcnRzLkRFQlVHX0lOSkVDVElPTl9GVU5DVElPTlMgPSBERUJVR19JTkpFQ1RJT05fRlVOQ1RJT05TID0gbmV3IFdlYWtNYXAoKTsKICB9CgogIGZ1bmN0aW9uIGluamVjdCh0eXBlKSB7CiAgICAoZmFsc2UgJiYgISh0eXBlb2YgdHlwZSA9PT0gJ3N0cmluZycpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYSBzdHJpbmcgdHlwZSBtdXN0IGJlIHByb3ZpZGVkIHRvIGluamVjdCcsIHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJykpOwoKICAgIGZvciAodmFyIF9sZW45ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuOSA+IDEgPyBfbGVuOSAtIDEgOiAwKSwgX2tleTEwID0gMTsgX2tleTEwIDwgX2xlbjk7IF9rZXkxMCsrKSB7CiAgICAgIGFyZ3NbX2tleTEwIC0gMV0gPSBhcmd1bWVudHNbX2tleTEwXTsKICAgIH0KCiAgICB2YXIgY2FsbGVkQXNEZWNvcmF0b3IgPSBpc0VsZW1lbnREZXNjcmlwdG9yKGFyZ3MpOwogICAgdmFyIHNvdXJjZSwgbmFtZXNwYWNlOwogICAgdmFyIG5hbWUgPSBjYWxsZWRBc0RlY29yYXRvciA/IHVuZGVmaW5lZCA6IGFyZ3NbMF07CiAgICB2YXIgb3B0aW9ucyA9IGNhbGxlZEFzRGVjb3JhdG9yID8gdW5kZWZpbmVkIDogYXJnc1sxXTsKCiAgICB2YXIgZ2V0SW5qZWN0aW9uID0gZnVuY3Rpb24gZ2V0SW5qZWN0aW9uKHByb3BlcnR5TmFtZSkgewogICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKSB8fCB0aGlzLmNvbnRhaW5lcjsgLy8gZmFsbGJhY2sgdG8gYGNvbnRhaW5lcmAgZm9yIGJhY2t3YXJkcyBjb21wYXQKCiAgICAgIChmYWxzZSAmJiAhKEJvb2xlYW4ob3duZXIpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF0dGVtcHRpbmcgdG8gbG9va3VwIGFuIGluamVjdGVkIHByb3BlcnR5IG9uIGFuIG9iamVjdCB3aXRob3V0IGEgY29udGFpbmVyLCBlbnN1cmUgdGhhdCB0aGUgb2JqZWN0IHdhcyBpbnN0YW50aWF0ZWQgdmlhIGEgY29udGFpbmVyLiIsIEJvb2xlYW4ob3duZXIpKSk7CiAgICAgIHJldHVybiBvd25lci5sb29rdXAodHlwZSArICI6IiArIChuYW1lIHx8IHByb3BlcnR5TmFtZSksIHsKICAgICAgICBzb3VyY2U6IHNvdXJjZSwKICAgICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZQogICAgICB9KTsKICAgIH07CgogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgKSB7CiAgICAgIERFQlVHX0lOSkVDVElPTl9GVU5DVElPTlMuc2V0KGdldEluamVjdGlvbiwgewogICAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlLAogICAgICAgIHNvdXJjZTogc291cmNlLAogICAgICAgIHR5cGU6IHR5cGUsCiAgICAgICAgbmFtZTogbmFtZQogICAgICB9KTsKICAgIH0KCiAgICB2YXIgZGVjb3JhdG9yID0gY29tcHV0ZWQoewogICAgICBnZXQ6IGdldEluamVjdGlvbiwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5TmFtZSwgdmFsdWUkJDEpIHsKICAgICAgICBkZWZpbmVQcm9wZXJ0eSh0aGlzLCBrZXlOYW1lLCBudWxsLCB2YWx1ZSQkMSk7CiAgICAgIH0KICAgIH0pOwoKICAgIGlmIChjYWxsZWRBc0RlY29yYXRvcikgewogICAgICAoZmFsc2UgJiYgIShCb29sZWFuKHRydWUKICAgICAgLyogRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUICovCiAgICAgICkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnTmF0aXZlIGRlY29yYXRvcnMgYXJlIG5vdCBlbmFibGVkIHdpdGhvdXQgdGhlIEVNQkVSX05BVElWRV9ERUNPUkFUT1JfU1VQUE9SVCBmbGFnLiBJZiB5b3UgYXJlIHVzaW5nIGluamVjdCBpbiBhIGNsYXNzaWMgY2xhc3MsIGFkZCBwYXJlbnRoZXNpcyB0byBpdDogaW5qZWN0KCknLCBCb29sZWFuKHRydWUpKSk7CiAgICAgIHJldHVybiBkZWNvcmF0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gZGVjb3JhdG9yOwogICAgfQogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvb3duZXIvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdXRpbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmdldE93bmVyID0gZ2V0T3duZXI7CiAgX2V4cG9ydHMuc2V0T3duZXIgPSBzZXRPd25lcjsKICBfZXhwb3J0cy5PV05FUiA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvYXBwbGljYXRpb24KICAqLwogIHZhciBPV05FUiA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnT1dORVInKTsKICAvKioKICAgIEZyYW1ld29yayBvYmplY3RzIGluIGFuIEVtYmVyIGFwcGxpY2F0aW9uIChjb21wb25lbnRzLCBzZXJ2aWNlcywgcm91dGVzLCBldGMuKQogICAgYXJlIGNyZWF0ZWQgdmlhIGEgZmFjdG9yeSBhbmQgZGVwZW5kZW5jeSBpbmplY3Rpb24gc3lzdGVtLiBFYWNoIG9mIHRoZXNlCiAgICBvYmplY3RzIGlzIHRoZSByZXNwb25zaWJpbGl0eSBvZiBhbiAib3duZXIiLCB3aGljaCBoYW5kbGVkIGl0cwogICAgaW5zdGFudGlhdGlvbiBhbmQgbWFuYWdlcyBpdHMgbGlmZXRpbWUuCiAgCiAgICBgZ2V0T3duZXJgIGZldGNoZXMgdGhlIG93bmVyIG9iamVjdCByZXNwb25zaWJsZSBmb3IgYW4gaW5zdGFuY2UuIFRoaXMgY2FuCiAgICBiZSB1c2VkIHRvIGxvb2t1cCBvciByZXNvbHZlIG90aGVyIGNsYXNzIGluc3RhbmNlcywgb3IgcmVnaXN0ZXIgbmV3IGZhY3RvcmllcwogICAgaW50byB0aGUgb3duZXIuCiAgCiAgICBGb3IgZXhhbXBsZSwgdGhpcyBjb21wb25lbnQgZHluYW1pY2FsbHkgbG9va3MgdXAgYSBzZXJ2aWNlIGJhc2VkIG9uIHRoZQogICAgYGF1ZGlvVHlwZWAgcGFzc2VkIGFzIGFuIGF0dHJpYnV0ZToKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL3BsYXktYXVkaW8uanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgZ2V0T3duZXIgfSBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogIAogICAgLy8gVXNhZ2U6CiAgICAvLwogICAgLy8gICB7e3BsYXktYXVkaW8gYXVkaW9UeXBlPW1vZGVsLmF1ZGlvVHlwZSBhdWRpb0ZpbGU9bW9kZWwuZmlsZX19CiAgICAvLwogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGF1ZGlvU2VydmljZTogY29tcHV0ZWQoJ2F1ZGlvVHlwZScsIGZ1bmN0aW9uKCkgewogICAgICAgIGxldCBvd25lciA9IGdldE93bmVyKHRoaXMpOwogICAgICAgIHJldHVybiBvd25lci5sb29rdXAoYHNlcnZpY2U6JHt0aGlzLmdldCgnYXVkaW9UeXBlJyl9YCk7CiAgICAgIH0pLAogIAogICAgICBjbGljaygpIHsKICAgICAgICBsZXQgcGxheWVyID0gdGhpcy5nZXQoJ2F1ZGlvU2VydmljZScpOwogICAgICAgIHBsYXllci5wbGF5KHRoaXMuZ2V0KCdhdWRpb0ZpbGUnKSk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGdldE93bmVyCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9hcHBsaWNhdGlvbgogICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdCBBbiBvYmplY3Qgd2l0aCBhbiBvd25lci4KICAgIEByZXR1cm4ge09iamVjdH0gQW4gb3duZXIgb2JqZWN0LgogICAgQHNpbmNlIDIuMy4wCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMuT1dORVIgPSBPV05FUjsKCiAgZnVuY3Rpb24gZ2V0T3duZXIob2JqZWN0KSB7CiAgICByZXR1cm4gb2JqZWN0W09XTkVSXTsKICB9CiAgLyoqCiAgICBgc2V0T3duZXJgIGZvcmNlcyBhIG5ldyBvd25lciBvbiBhIGdpdmVuIG9iamVjdCBpbnN0YW5jZS4gVGhpcyBpcyBwcmltYXJpbHkKICAgIHVzZWZ1bCBpbiBzb21lIHRlc3RpbmcgY2FzZXMuCiAgCiAgICBAbWV0aG9kIHNldE93bmVyCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9hcHBsaWNhdGlvbgogICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdCBBbiBvYmplY3QgaW5zdGFuY2UuCiAgICBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBuZXcgb3duZXIgb2JqZWN0IG9mIHRoZSBvYmplY3QgaW5zdGFuY2UuCiAgICBAc2luY2UgMi4zLjAKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gc2V0T3duZXIob2JqZWN0LCBvd25lcikgewogICAgb2JqZWN0W09XTkVSXSA9IG93bmVyOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9leHQvY29udHJvbGxlciIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9sb2NhdGlvbi9hcGkiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vbm9uZV9sb2NhdGlvbiIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9sb2NhdGlvbi9oYXNoX2xvY2F0aW9uIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL2hpc3RvcnlfbG9jYXRpb24iLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vYXV0b19sb2NhdGlvbiIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vZ2VuZXJhdGVfY29udHJvbGxlciIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vY29udHJvbGxlcl9mb3IiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL2RzbCIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vcm91dGVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3N5c3RlbS9yb3V0ZSIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vcXVlcnlfcGFyYW1zIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3NlcnZpY2VzL3JvdXRpbmciLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc2VydmljZXMvcm91dGVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3N5c3RlbS9jYWNoZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9jb250cm9sbGVyLCBfYXBpLCBfbm9uZV9sb2NhdGlvbiwgX2hhc2hfbG9jYXRpb24sIF9oaXN0b3J5X2xvY2F0aW9uLCBfYXV0b19sb2NhdGlvbiwgX2dlbmVyYXRlX2NvbnRyb2xsZXIsIF9jb250cm9sbGVyX2ZvciwgX2RzbCwgX3JvdXRlciwgX3JvdXRlLCBfcXVlcnlfcGFyYW1zLCBfcm91dGluZywgX3JvdXRlcjIsIF9jYWNoZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiTG9jYXRpb24iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXBpLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiTm9uZUxvY2F0aW9uIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX25vbmVfbG9jYXRpb24uZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJIYXNoTG9jYXRpb24iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfaGFzaF9sb2NhdGlvbi5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkhpc3RvcnlMb2NhdGlvbiIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9oaXN0b3J5X2xvY2F0aW9uLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQXV0b0xvY2F0aW9uIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2F1dG9fbG9jYXRpb24uZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZW5lcmF0ZUNvbnRyb2xsZXIiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZ2VuZXJhdGVfY29udHJvbGxlci5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImdlbmVyYXRlQ29udHJvbGxlckZhY3RvcnkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZ2VuZXJhdGVfY29udHJvbGxlci5nZW5lcmF0ZUNvbnRyb2xsZXJGYWN0b3J5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImNvbnRyb2xsZXJGb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29udHJvbGxlcl9mb3IuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJSb3V0ZXJEU0wiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZHNsLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiUm91dGVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JvdXRlci5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIlJvdXRlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JvdXRlLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiUXVlcnlQYXJhbXMiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcXVlcnlfcGFyYW1zLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiUm91dGluZ1NlcnZpY2UiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcm91dGluZy5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIlJvdXRlclNlcnZpY2UiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcm91dGVyMi5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkJ1Y2tldENhY2hlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NhY2hlLmRlZmF1bHQ7CiAgICB9CiAgfSk7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2V4dC9jb250cm9sbGVyIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci9jb250cm9sbGVyL2xpYi9jb250cm9sbGVyX21peGluIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3V0aWxzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21ldGFsLCBfY29udHJvbGxlcl9taXhpbiwgX3V0aWxzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KICBfY29udHJvbGxlcl9taXhpbi5kZWZhdWx0LnJlb3Blbih7CiAgICBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzOiBbJ3F1ZXJ5UGFyYW1zJ10sCgogICAgLyoqCiAgICAgIERlZmluZXMgd2hpY2ggcXVlcnkgcGFyYW1ldGVycyB0aGUgY29udHJvbGxlciBhY2NlcHRzLgogICAgICBJZiB5b3UgZ2l2ZSB0aGUgbmFtZXMgYFsnY2F0ZWdvcnknLCdwYWdlJ11gIGl0IHdpbGwgYmluZAogICAgICB0aGUgdmFsdWVzIG9mIHRoZXNlIHF1ZXJ5IHBhcmFtZXRlcnMgdG8gdGhlIHZhcmlhYmxlcwogICAgICBgdGhpcy5jYXRlZ29yeWAgYW5kIGB0aGlzLnBhZ2VgLgogICAgICBCeSBkZWZhdWx0LCBFbWJlciBjb2VyY2VzIHF1ZXJ5IHBhcmFtZXRlciB2YWx1ZXMgdXNpbmcgYHRvZ2dsZVByb3BlcnR5YC4KICAgICAgVGhpcyBiZWhhdmlvciBtYXkgbGVhZCB0byB1bmV4cGVjdGVkIHJlc3VsdHMuCiAgICAgIEF2YWlsYWJsZSBxdWVyeVBhcmFtIHR5cGVzOiBgYm9vbGVhbmAsIGBudW1iZXJgLCBgYXJyYXlgLgogICAgICBJZiBxdWVyeSBwYXJhbSB0eXBlIG5vdCBzcGVjaWZpZWQsIGl0IHdpbGwgYmUgYHN0cmluZ2AuCiAgICAgIFRvIGV4cGxpY2l0bHkgY29uZmlndXJlIGEgcXVlcnkgcGFyYW1ldGVyIHByb3BlcnR5IHNvIGl0IGNvZXJjZXMgYXMgZXhwZWN0ZWQsIHlvdSBtdXN0IGRlZmluZSBhIHR5cGUgcHJvcGVydHk6CiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgICBxdWVyeVBhcmFtczogW3sKICAgICAgICAgIGNhdGVnb3J5OiB7CiAgICAgICAgICAgIHR5cGU6ICdib29sZWFuJwogICAgICAgICAgfQogICAgICAgIH1dCiAgICAgIGBgYAogICAgICBAZm9yIEVtYmVyLkNvbnRyb2xsZXJNaXhpbgogICAgICBAcHJvcGVydHkgcXVlcnlQYXJhbXMKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHF1ZXJ5UGFyYW1zOiBudWxsLAoKICAgIC8qKgogICAgIFRoaXMgcHJvcGVydHkgaXMgdXBkYXRlZCB0byB2YXJpb3VzIGRpZmZlcmVudCBjYWxsYmFjayBmdW5jdGlvbnMgZGVwZW5kaW5nIG9uCiAgICAgdGhlIGN1cnJlbnQgInN0YXRlIiBvZiB0aGUgYmFja2luZyByb3V0ZS4gSXQgaXMgdXNlZCBieQogICAgIGBDb250cm9sbGVyLnByb3RvdHlwZS5fcXBDaGFuZ2VkYC4KICAgICAgICBUaGUgbWV0aG9kcyBiYWNraW5nIGVhY2ggc3RhdGUgY2FuIGJlIGZvdW5kIGluIHRoZSBgUm91dGUucHJvdG90eXBlLl9xcGAgY29tcHV0ZWQKICAgICBwcm9wZXJ0eSByZXR1cm4gdmFsdWUgKHRoZSBgLnN0YXRlc2AgcHJvcGVydHkpLiBUaGUgY3VycmVudCB2YWx1ZXMgYXJlIGxpc3RlZCBoZXJlIGZvcgogICAgIHRoZSBzYW5pdHkgb2YgZnV0dXJlIHRyYXZlbGVyczoKICAgICAgICAqIGBpbmFjdGl2ZWAgLSBUaGlzIHN0YXRlIGlzIHVzZWQgd2hlbiB0aGlzIGNvbnRyb2xsZXIgaW5zdGFuY2UgaXMgbm90IHBhcnQgb2YgdGhlIGFjdGl2ZQogICAgICAgcm91dGUgaGllcmFyY2h5LiBTZXQgaW4gYFJvdXRlLnByb3RvdHlwZS5fcmVzZXRgIChhIGByb3V0ZXIuanNgIG1pY3JvbGliIGhvb2spIGFuZAogICAgICAgYFJvdXRlLnByb3RvdHlwZS5hY3Rpb25zLmZpbmFsaXplUXVlcnlQYXJhbUNoYW5nZWAuCiAgICAgKiBgYWN0aXZlYCAtIFRoaXMgc3RhdGUgaXMgdXNlZCB3aGVuIHRoaXMgY29udHJvbGxlciBpbnN0YW5jZSBpcyBwYXJ0IG9mIHRoZSBhY3RpdmUKICAgICAgIHJvdXRlIGhpZXJhcmNoeS4gU2V0IGluIGBSb3V0ZS5wcm90b3R5cGUuYWN0aW9ucy5maW5hbGl6ZVF1ZXJ5UGFyYW1DaGFuZ2VgLgogICAgICogYGFsbG93T3ZlcnJpZGVzYCAtIFRoaXMgc3RhdGUgaXMgdXNlZCBpbiBgUm91dGUucHJvdG90eXBlLnNldHVwYCAoYHJvdXRlLmpzYCBtaWNyb2xpYiBob29rKS4KICAgICAgICAgQG1ldGhvZCBfcXBEZWxlZ2F0ZQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9xcERlbGVnYXRlOiBudWxsLAoKICAgIC8qKgogICAgIER1cmluZyBgUm91dGUjc2V0dXBgIG9ic2VydmVycyBhcmUgY3JlYXRlZCB0byBpbnZva2UgdGhpcyBtZXRob2QKICAgICB3aGVuIGFueSBvZiB0aGUgcXVlcnkgcGFyYW1zIGRlY2xhcmVkIGluIGBDb250cm9sbGVyI3F1ZXJ5UGFyYW1zYCBwcm9wZXJ0eQogICAgIGFyZSBjaGFuZ2VkLgogICAgICAgIFdoZW4gaW52b2tlZCB0aGlzIG1ldGhvZCB1c2VzIHRoZSBjdXJyZW50bHkgYWN0aXZlIHF1ZXJ5IHBhcmFtIHVwZGF0ZSBkZWxlZ2F0ZQogICAgIChzZWUgYENvbnRyb2xsZXIucHJvdG90eXBlLl9xcERlbGVnYXRlYCBmb3IgZGV0YWlscykgYW5kIGludm9rZXMgaXQgd2l0aAogICAgIHRoZSBRUCBrZXkvdmFsdWUgYmVpbmcgY2hhbmdlZC4KICAgICAgICAgQG1ldGhvZCBfcXBDaGFuZ2VkCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX3FwQ2hhbmdlZDogZnVuY3Rpb24gX3FwQ2hhbmdlZChjb250cm9sbGVyLCBfcHJvcCkgewogICAgICB2YXIgZG90SW5kZXggPSBfcHJvcC5pbmRleE9mKCcuW10nKTsKCiAgICAgIHZhciBwcm9wID0gZG90SW5kZXggPT09IC0xID8gX3Byb3AgOiBfcHJvcC5zbGljZSgwLCBkb3RJbmRleCk7CiAgICAgIHZhciBkZWxlZ2F0ZSA9IGNvbnRyb2xsZXIuX3FwRGVsZWdhdGU7CiAgICAgIHZhciB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KShjb250cm9sbGVyLCBwcm9wKTsKICAgICAgZGVsZWdhdGUocHJvcCwgdmFsdWUpOwogICAgfSwKCiAgICAvKioKICAgICAgVHJhbnNpdGlvbiB0aGUgYXBwbGljYXRpb24gaW50byBhbm90aGVyIHJvdXRlLiBUaGUgcm91dGUgbWF5CiAgICAgIGJlIGVpdGhlciBhIHNpbmdsZSByb3V0ZSBvciByb3V0ZSBwYXRoOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGFDb250cm9sbGVyLnRyYW5zaXRpb25Ub1JvdXRlKCdibG9nUG9zdHMnKTsKICAgICAgYUNvbnRyb2xsZXIudHJhbnNpdGlvblRvUm91dGUoJ2Jsb2dQb3N0cy5yZWNlbnRFbnRyaWVzJyk7CiAgICAgIGBgYAogICAgICAgICBPcHRpb25hbGx5IHN1cHBseSBhIG1vZGVsIGZvciB0aGUgcm91dGUgaW4gcXVlc3Rpb24uIFRoZSBtb2RlbAogICAgICB3aWxsIGJlIHNlcmlhbGl6ZWQgaW50byB0aGUgVVJMIHVzaW5nIHRoZSBgc2VyaWFsaXplYCBob29rIG9mCiAgICAgIHRoZSByb3V0ZToKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBhQ29udHJvbGxlci50cmFuc2l0aW9uVG9Sb3V0ZSgnYmxvZ1Bvc3QnLCBhUG9zdCk7CiAgICAgIGBgYAogICAgICAgICBJZiBhIGxpdGVyYWwgaXMgcGFzc2VkIChzdWNoIGFzIGEgbnVtYmVyIG9yIGEgc3RyaW5nKSwgaXQgd2lsbAogICAgICBiZSB0cmVhdGVkIGFzIGFuIGlkZW50aWZpZXIgaW5zdGVhZC4gSW4gdGhpcyBjYXNlLCB0aGUgYG1vZGVsYAogICAgICBob29rIG9mIHRoZSByb3V0ZSB3aWxsIGJlIHRyaWdnZXJlZDoKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBhQ29udHJvbGxlci50cmFuc2l0aW9uVG9Sb3V0ZSgnYmxvZ1Bvc3QnLCAxKTsKICAgICAgYGBgCiAgICAgICAgIE11bHRpcGxlIG1vZGVscyB3aWxsIGJlIGFwcGxpZWQgbGFzdCB0byBmaXJzdCByZWN1cnNpdmVseSB1cCB0aGUKICAgICAgcm91dGUgdHJlZS4KICAgICAgICAgYGBgYXBwL3JvdXRlci5qcwogICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoJ2Jsb2dQb3N0JywgeyBwYXRoOiAnOmJsb2dQb3N0SWQnIH0sIGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhpcy5yb3V0ZSgnYmxvZ0NvbW1lbnQnLCB7IHBhdGg6ICc6YmxvZ0NvbW1lbnRJZCcsIHJlc2V0TmFtZXNwYWNlOiB0cnVlIH0pOwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgYUNvbnRyb2xsZXIudHJhbnNpdGlvblRvUm91dGUoJ2Jsb2dDb21tZW50JywgYVBvc3QsIGFDb21tZW50KTsKICAgICAgYUNvbnRyb2xsZXIudHJhbnNpdGlvblRvUm91dGUoJ2Jsb2dDb21tZW50JywgMSwgMTMpOwogICAgICBgYGAKICAgICAgICAgSXQgaXMgYWxzbyBwb3NzaWJsZSB0byBwYXNzIGEgVVJMIChhIHN0cmluZyB0aGF0IHN0YXJ0cyB3aXRoIGEKICAgICAgYC9gKS4KICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBhQ29udHJvbGxlci50cmFuc2l0aW9uVG9Sb3V0ZSgnLycpOwogICAgICBhQ29udHJvbGxlci50cmFuc2l0aW9uVG9Sb3V0ZSgnL2Jsb2cvcG9zdC8xL2NvbW1lbnQvMTMnKTsKICAgICAgYUNvbnRyb2xsZXIudHJhbnNpdGlvblRvUm91dGUoJy9ibG9nL3Bvc3RzP3NvcnQ9dGl0bGUnKTsKICAgICAgYGBgCiAgICAgICAgIEFuIG9wdGlvbnMgaGFzaCB3aXRoIGEgYHF1ZXJ5UGFyYW1zYCBwcm9wZXJ0eSBtYXkgYmUgcHJvdmlkZWQgYXMKICAgICAgdGhlIGZpbmFsIGFyZ3VtZW50IHRvIGFkZCBxdWVyeSBwYXJhbWV0ZXJzIHRvIHRoZSBkZXN0aW5hdGlvbiBVUkwuCiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgYUNvbnRyb2xsZXIudHJhbnNpdGlvblRvUm91dGUoJ2Jsb2dQb3N0JywgMSwgewogICAgICAgIHF1ZXJ5UGFyYW1zOiB7IHNob3dDb21tZW50czogJ3RydWUnIH0KICAgICAgfSk7CiAgICAgICAgIC8vIGlmIHlvdSBqdXN0IHdhbnQgdG8gdHJhbnNpdGlvbiB0aGUgcXVlcnkgcGFyYW1ldGVycyB3aXRob3V0IGNoYW5naW5nIHRoZSByb3V0ZQogICAgICBhQ29udHJvbGxlci50cmFuc2l0aW9uVG9Sb3V0ZSh7IHF1ZXJ5UGFyYW1zOiB7IHNvcnQ6ICdkYXRlJyB9IH0pOwogICAgICBgYGAKICAgICAgICAgU2VlIGFsc28gW3JlcGxhY2VSb3V0ZV0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9FbWJlci5Db250cm9sbGVyTWl4aW4vbWV0aG9kcy9yZXBsYWNlUm91dGU/YW5jaG9yPXJlcGxhY2VSb3V0ZSkuCiAgICAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZSBvciBhIFVSTAogICAgICBAcGFyYW0gey4uLk9iamVjdH0gbW9kZWxzIHRoZSBtb2RlbChzKSBvciBpZGVudGlmaWVyKHMpIHRvIGJlIHVzZWQKICAgICAgICB3aGlsZSB0cmFuc2l0aW9uaW5nIHRvIHRoZSByb3V0ZS4KICAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBvcHRpb25hbCBoYXNoIHdpdGggYSBxdWVyeVBhcmFtcyBwcm9wZXJ0eQogICAgICAgIGNvbnRhaW5pbmcgYSBtYXBwaW5nIG9mIHF1ZXJ5IHBhcmFtZXRlcnMKICAgICAgQGZvciBFbWJlci5Db250cm9sbGVyTWl4aW4KICAgICAgQG1ldGhvZCB0cmFuc2l0aW9uVG9Sb3V0ZQogICAgICBAcHVibGljCiAgICAqLwogICAgdHJhbnNpdGlvblRvUm91dGU6IGZ1bmN0aW9uIHRyYW5zaXRpb25Ub1JvdXRlKCkgewogICAgICAvLyB0YXJnZXQgbWF5IGJlIGVpdGhlciBhbm90aGVyIGNvbnRyb2xsZXIgb3IgYSByb3V0ZXIKICAgICAgdmFyIHRhcmdldCA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAndGFyZ2V0Jyk7CiAgICAgIHZhciBtZXRob2QgPSB0YXJnZXQudHJhbnNpdGlvblRvUm91dGUgfHwgdGFyZ2V0LnRyYW5zaXRpb25UbzsKCiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgIHJldHVybiBtZXRob2QuYXBwbHkodGFyZ2V0LCAoMCwgX3V0aWxzLnByZWZpeFJvdXRlTmFtZUFyZykodGhpcywgYXJncykpOwogICAgfSwKCiAgICAvKioKICAgICAgVHJhbnNpdGlvbiBpbnRvIGFub3RoZXIgcm91dGUgd2hpbGUgcmVwbGFjaW5nIHRoZSBjdXJyZW50IFVSTCwgaWYgcG9zc2libGUuCiAgICAgIFRoaXMgd2lsbCByZXBsYWNlIHRoZSBjdXJyZW50IGhpc3RvcnkgZW50cnkgaW5zdGVhZCBvZiBhZGRpbmcgYSBuZXcgb25lLgogICAgICBCZXNpZGUgdGhhdCwgaXQgaXMgaWRlbnRpY2FsIHRvIGB0cmFuc2l0aW9uVG9Sb3V0ZWAgaW4gYWxsIG90aGVyIHJlc3BlY3RzLgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGFDb250cm9sbGVyLnJlcGxhY2VSb3V0ZSgnYmxvZ1Bvc3RzJyk7CiAgICAgIGFDb250cm9sbGVyLnJlcGxhY2VSb3V0ZSgnYmxvZ1Bvc3RzLnJlY2VudEVudHJpZXMnKTsKICAgICAgYGBgCiAgICAgICAgIE9wdGlvbmFsbHkgc3VwcGx5IGEgbW9kZWwgZm9yIHRoZSByb3V0ZSBpbiBxdWVzdGlvbi4gVGhlIG1vZGVsCiAgICAgIHdpbGwgYmUgc2VyaWFsaXplZCBpbnRvIHRoZSBVUkwgdXNpbmcgdGhlIGBzZXJpYWxpemVgIGhvb2sgb2YKICAgICAgdGhlIHJvdXRlOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGFDb250cm9sbGVyLnJlcGxhY2VSb3V0ZSgnYmxvZ1Bvc3QnLCBhUG9zdCk7CiAgICAgIGBgYAogICAgICAgICBJZiBhIGxpdGVyYWwgaXMgcGFzc2VkIChzdWNoIGFzIGEgbnVtYmVyIG9yIGEgc3RyaW5nKSwgaXQgd2lsbAogICAgICBiZSB0cmVhdGVkIGFzIGFuIGlkZW50aWZpZXIgaW5zdGVhZC4gSW4gdGhpcyBjYXNlLCB0aGUgYG1vZGVsYAogICAgICBob29rIG9mIHRoZSByb3V0ZSB3aWxsIGJlIHRyaWdnZXJlZDoKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBhQ29udHJvbGxlci5yZXBsYWNlUm91dGUoJ2Jsb2dQb3N0JywgMSk7CiAgICAgIGBgYAogICAgICAgICBNdWx0aXBsZSBtb2RlbHMgd2lsbCBiZSBhcHBsaWVkIGxhc3QgdG8gZmlyc3QgcmVjdXJzaXZlbHkgdXAgdGhlCiAgICAgIHJvdXRlIHRyZWUuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdibG9nUG9zdCcsIHsgcGF0aDogJzpibG9nUG9zdElkJyB9LCBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMucm91dGUoJ2Jsb2dDb21tZW50JywgeyBwYXRoOiAnOmJsb2dDb21tZW50SWQnLCByZXNldE5hbWVzcGFjZTogdHJ1ZSB9KTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBgYGAKICAgICAgYUNvbnRyb2xsZXIucmVwbGFjZVJvdXRlKCdibG9nQ29tbWVudCcsIGFQb3N0LCBhQ29tbWVudCk7CiAgICAgIGFDb250cm9sbGVyLnJlcGxhY2VSb3V0ZSgnYmxvZ0NvbW1lbnQnLCAxLCAxMyk7CiAgICAgIGBgYAogICAgICAgICBJdCBpcyBhbHNvIHBvc3NpYmxlIHRvIHBhc3MgYSBVUkwgKGEgc3RyaW5nIHRoYXQgc3RhcnRzIHdpdGggYQogICAgICBgL2ApLgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGFDb250cm9sbGVyLnJlcGxhY2VSb3V0ZSgnLycpOwogICAgICBhQ29udHJvbGxlci5yZXBsYWNlUm91dGUoJy9ibG9nL3Bvc3QvMS9jb21tZW50LzEzJyk7CiAgICAgIGBgYAogICAgICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSB0aGUgbmFtZSBvZiB0aGUgcm91dGUgb3IgYSBVUkwKICAgICAgQHBhcmFtIHsuLi5PYmplY3R9IG1vZGVscyB0aGUgbW9kZWwocykgb3IgaWRlbnRpZmllcihzKSB0byBiZSB1c2VkCiAgICAgIHdoaWxlIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICBAZm9yIEVtYmVyLkNvbnRyb2xsZXJNaXhpbgogICAgICBAbWV0aG9kIHJlcGxhY2VSb3V0ZQogICAgICBAcHVibGljCiAgICAqLwogICAgcmVwbGFjZVJvdXRlOiBmdW5jdGlvbiByZXBsYWNlUm91dGUoKSB7CiAgICAgIC8vIHRhcmdldCBtYXkgYmUgZWl0aGVyIGFub3RoZXIgY29udHJvbGxlciBvciBhIHJvdXRlcgogICAgICB2YXIgdGFyZ2V0ID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICd0YXJnZXQnKTsKICAgICAgdmFyIG1ldGhvZCA9IHRhcmdldC5yZXBsYWNlUm91dGUgfHwgdGFyZ2V0LnJlcGxhY2VXaXRoOwoKICAgICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4yKSwgX2tleTIgPSAwOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7CiAgICAgICAgYXJnc1tfa2V5Ml0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICB9CgogICAgICByZXR1cm4gbWV0aG9kLmFwcGx5KHRhcmdldCwgKDAsIF91dGlscy5wcmVmaXhSb3V0ZU5hbWVBcmcpKHRoaXMsIGFyZ3MpKTsKICAgIH0KICB9KTsKCiAgdmFyIF9kZWZhdWx0ID0gX2NvbnRyb2xsZXJfbWl4aW4uZGVmYXVsdDsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL2FwaSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZGVidWciXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVidWcpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgQGVtYmVyL3JvdXRpbmcKICAqLwoKICAvKioKICAgIExvY2F0aW9uIHJldHVybnMgYW4gaW5zdGFuY2Ugb2YgdGhlIGNvcnJlY3QgaW1wbGVtZW50YXRpb24gb2YKICAgIHRoZSBgbG9jYXRpb25gIEFQSS4KICAKICAgICMjIEltcGxlbWVudGF0aW9ucwogIAogICAgWW91IGNhbiBwYXNzIGFuIGltcGxlbWVudGF0aW9uIG5hbWUgKGBoYXNoYCwgYGhpc3RvcnlgLCBgbm9uZWAsIGBhdXRvYCkgdG8gZm9yY2UgYQogICAgcGFydGljdWxhciBpbXBsZW1lbnRhdGlvbiB0byBiZSB1c2VkIGluIHlvdXIgYXBwbGljYXRpb24uCiAgCiAgICBTZWUgW0hhc2hMb2NhdGlvbl0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9IYXNoTG9jYXRpb24pLgogICAgU2VlIFtIaXN0b3J5TG9jYXRpb25dKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvSGlzdG9yeUxvY2F0aW9uKS4KICAgIFNlZSBbTm9uZUxvY2F0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL05vbmVMb2NhdGlvbikuCiAgICBTZWUgW0F1dG9Mb2NhdGlvbl0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9BdXRvTG9jYXRpb24pLgogIAogICAgIyMgTG9jYXRpb24gQVBJCiAgCiAgICBFYWNoIGxvY2F0aW9uIGltcGxlbWVudGF0aW9uIG11c3QgcHJvdmlkZSB0aGUgZm9sbG93aW5nIG1ldGhvZHM6CiAgCiAgICAqIGltcGxlbWVudGF0aW9uOiByZXR1cm5zIHRoZSBzdHJpbmcgbmFtZSB1c2VkIHRvIHJlZmVyZW5jZSB0aGUgaW1wbGVtZW50YXRpb24uCiAgICAqIGdldFVSTDogcmV0dXJucyB0aGUgY3VycmVudCBVUkwuCiAgICAqIHNldFVSTChwYXRoKTogc2V0cyB0aGUgY3VycmVudCBVUkwuCiAgICAqIHJlcGxhY2VVUkwocGF0aCk6IHJlcGxhY2UgdGhlIGN1cnJlbnQgVVJMIChvcHRpb25hbCkuCiAgICAqIG9uVXBkYXRlVVJMKGNhbGxiYWNrKTogdHJpZ2dlcnMgdGhlIGNhbGxiYWNrIHdoZW4gdGhlIFVSTCBjaGFuZ2VzLgogICAgKiBmb3JtYXRVUkwodXJsKTogZm9ybWF0cyBgdXJsYCB0byBiZSBwbGFjZWQgaW50byBgaHJlZmAgYXR0cmlidXRlLgogICAgKiBkZXRlY3QoKSAob3B0aW9uYWwpOiBpbnN0cnVjdHMgdGhlIGxvY2F0aW9uIHRvIGRvIGFueSBmZWF0dXJlIGRldGVjdGlvbgogICAgICAgIG5lY2Vzc2FyeS4gSWYgdGhlIGxvY2F0aW9uIG5lZWRzIHRvIHJlZGlyZWN0IHRvIGEgZGlmZmVyZW50IFVSTCwgaXQKICAgICAgICBjYW4gY2FuY2VsIHJvdXRpbmcgYnkgc2V0dGluZyB0aGUgYGNhbmNlbFJvdXRlclNldHVwYCBwcm9wZXJ0eSBvbiBpdHNlbGYKICAgICAgICB0byBgZmFsc2VgLgogIAogICAgQ2FsbGluZyBzZXRVUkwgb3IgcmVwbGFjZVVSTCB3aWxsIG5vdCB0cmlnZ2VyIG9uVXBkYXRlVVJMIGNhbGxiYWNrcy4KICAKICAgICMjIEN1c3RvbSBpbXBsZW1lbnRhdGlvbgogIAogICAgRW1iZXIgc2NhbnMgYGFwcC9sb2NhdGlvbnMvKmAgZm9yIGV4dGVuZGluZyB0aGUgTG9jYXRpb24gQVBJLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBIaXN0b3J5TG9jYXRpb24gZnJvbSAnQGVtYmVyL3JvdXRpbmcvaGlzdG9yeS1sb2NhdGlvbic7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBjbGFzcyBNeUhpc3RvcnkgewogICAgICBpbXBsZW1lbnRhdGlvbjogJ215LWN1c3RvbS1oaXN0b3J5JywKICAgICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgdGhpcy5faGlzdG9yeSA9IEhpc3RvcnlMb2NhdGlvbi5jcmVhdGUoLi4uYXJndW1lbnRzKTsKICAgICAgfQogICAgICBjcmVhdGUoKSB7CiAgICAgICAgcmV0dXJuIG5ldyB0aGlzKC4uLmFyZ3VtZW50cyk7CiAgICAgIH0KICAgICAgcHVzaFN0YXRlKHBhdGgpIHsKICAgICAgICAgdGhpcy5faGlzdG9yeS5wdXNoU3RhdGUocGF0aCk7CiAgICAgIH0KICAgIH0KICAgIGBgYAogIAogICAgQGNsYXNzIExvY2F0aW9uCiAgICBAcHJpdmF0ZQogICovCiAgdmFyIF9kZWZhdWx0ID0gewogICAgLyoqCiAgICAgVGhpcyBpcyBkZXByZWNhdGVkIGluIGZhdm9yIG9mIHVzaW5nIHRoZSBjb250YWluZXIgdG8gbG9va3VwIHRoZSBsb2NhdGlvbgogICAgIGltcGxlbWVudGF0aW9uIGFzIGRlc2lyZWQuCiAgICAgICAgRm9yIGV4YW1wbGU6CiAgICAgICAgYGBgamF2YXNjcmlwdAogICAgIC8vIEdpdmVuIGEgbG9jYXRpb24gcmVnaXN0ZXJlZCBhcyBmb2xsb3dzOgogICAgIGNvbnRhaW5lci5yZWdpc3RlcignbG9jYXRpb246aGlzdG9yeS10ZXN0JywgSGlzdG9yeVRlc3RMb2NhdGlvbik7CiAgICAgICAgLy8gWW91IGNvdWxkIGNyZWF0ZSBhIG5ldyBpbnN0YW5jZSB2aWE6CiAgICAgY29udGFpbmVyLmxvb2t1cCgnbG9jYXRpb246aGlzdG9yeS10ZXN0Jyk7CiAgICAgYGBgCiAgICAgICAgIEBtZXRob2QgY3JlYXRlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgIEByZXR1cm4ge09iamVjdH0gYW4gaW5zdGFuY2Ugb2YgYW4gaW1wbGVtZW50YXRpb24gb2YgdGhlIGBsb2NhdGlvbmAgQVBJCiAgICAgIEBkZXByZWNhdGVkIFVzZSB0aGUgY29udGFpbmVyIHRvIGxvb2t1cCB0aGUgbG9jYXRpb24gaW1wbGVtZW50YXRpb24gdGhhdCB5b3UKICAgICAgbmVlZC4KICAgICAgQHByaXZhdGUKICAgICovCiAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShvcHRpb25zKSB7CiAgICAgIHZhciBpbXBsZW1lbnRhdGlvbiA9IG9wdGlvbnMgJiYgb3B0aW9ucy5pbXBsZW1lbnRhdGlvbjsKICAgICAgKGZhbHNlICYmICEoQm9vbGVhbihpbXBsZW1lbnRhdGlvbikpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiTG9jYXRpb24uY3JlYXRlOiB5b3UgbXVzdCBzcGVjaWZ5IGEgJ2ltcGxlbWVudGF0aW9uJyBvcHRpb24iLCBCb29sZWFuKGltcGxlbWVudGF0aW9uKSkpOwogICAgICB2YXIgaW1wbGVtZW50YXRpb25DbGFzcyA9IHRoaXMuaW1wbGVtZW50YXRpb25zW2ltcGxlbWVudGF0aW9uXTsKICAgICAgKGZhbHNlICYmICEoQm9vbGVhbihpbXBsZW1lbnRhdGlvbkNsYXNzKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJMb2NhdGlvbi5jcmVhdGU6ICIgKyBpbXBsZW1lbnRhdGlvbiArICIgaXMgbm90IGEgdmFsaWQgaW1wbGVtZW50YXRpb24iLCBCb29sZWFuKGltcGxlbWVudGF0aW9uQ2xhc3MpKSk7CiAgICAgIHJldHVybiBpbXBsZW1lbnRhdGlvbkNsYXNzLmNyZWF0ZS5hcHBseShpbXBsZW1lbnRhdGlvbkNsYXNzLCBhcmd1bWVudHMpOwogICAgfSwKICAgIGltcGxlbWVudGF0aW9uczoge30KICB9OwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vYXV0b19sb2NhdGlvbiIsIFsiZXhwb3J0cyIsICJlbWJlci1iYWJlbCIsICJAZW1iZXIvLWludGVybmFscy9icm93c2VyLWVudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL3V0aWwiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX2Jyb3dzZXJFbnZpcm9ubWVudCwgX21ldGFsLCBfb3duZXIsIF9ydW50aW1lLCBfdXRpbHMsIF9kZWJ1ZywgX3V0aWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmdldEhpc3RvcnlQYXRoID0gZ2V0SGlzdG9yeVBhdGg7CiAgX2V4cG9ydHMuZ2V0SGFzaFBhdGggPSBnZXRIYXNoUGF0aDsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIEBlbWJlci9yb3V0aW5nCiAgKi8KCiAgLyoqCiAgICBBdXRvTG9jYXRpb24gd2lsbCBzZWxlY3QgdGhlIGJlc3QgbG9jYXRpb24gb3B0aW9uIGJhc2VkIG9mZiBicm93c2VyCiAgICBzdXBwb3J0IHdpdGggdGhlIHByaW9yaXR5IG9yZGVyOiBoaXN0b3J5LCBoYXNoLCBub25lLgogIAogICAgQ2xlYW4gcHVzaFN0YXRlIHBhdGhzIGFjY2Vzc2VkIGJ5IGhhc2hjaGFuZ2Utb25seSBicm93c2VycyB3aWxsIGJlIHJlZGlyZWN0ZWQKICAgIHRvIHRoZSBoYXNoLWVxdWl2YWxlbnQgYW5kIHZpY2UgdmVyc2Egc28gZnV0dXJlIHRyYW5zaXRpb25zIGFyZSBjb25zaXN0ZW50LgogIAogICAgS2VlcCBpbiBtaW5kIHRoYXQgc2luY2Ugc29tZSBvZiB5b3VyIHVzZXJzIHdpbGwgdXNlIGBIaXN0b3J5TG9jYXRpb25gLCB5b3VyCiAgICBzZXJ2ZXIgbXVzdCBzZXJ2ZSB0aGUgRW1iZXIgYXBwIGF0IGFsbCB0aGUgcm91dGVzIHlvdSBkZWZpbmUuCiAgCiAgICBCcm93c2VycyB0aGF0IHN1cHBvcnQgdGhlIGBoaXN0b3J5YCBBUEkgd2lsbCB1c2UgYEhpc3RvcnlMb2NhdGlvbmAsIHRob3NlIHRoYXQKICAgIGRvIG5vdCwgYnV0IHN0aWxsIHN1cHBvcnQgdGhlIGBoYXNoY2hhbmdlYCBldmVudCB3aWxsIHVzZSBgSGFzaExvY2F0aW9uYCwgYW5kCiAgICBpbiB0aGUgcmFyZSBjYXNlIG5laXRoZXIgaXMgc3VwcG9ydGVkIHdpbGwgdXNlIGBOb25lTG9jYXRpb25gLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgIHRoaXMucm91dGUoJ3Bvc3RzJywgZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgnbmV3Jyk7CiAgICAgIH0pOwogICAgfSk7CiAgCiAgICBSb3V0ZXIucmVvcGVuKHsKICAgICAgbG9jYXRpb246ICdhdXRvJwogICAgfSk7CiAgICBgYGAKICAKICAgIFRoaXMgd2lsbCByZXN1bHQgaW4gYSBwb3N0cy5uZXcgdXJsIG9mIGAvcG9zdHMvbmV3YCBmb3IgbW9kZXJuIGJyb3dzZXJzIHRoYXQKICAgIHN1cHBvcnQgdGhlIGBoaXN0b3J5YCBhcGkgb3IgYC8jL3Bvc3RzL25ld2AgZm9yIG9sZGVyIG9uZXMsIGxpa2UgSW50ZXJuZXQKICAgIEV4cGxvcmVyIDkgYW5kIGJlbG93LgogIAogICAgV2hlbiBhIHVzZXIgdmlzaXRzIGEgbGluayB0byB5b3VyIGFwcGxpY2F0aW9uLCB0aGV5IHdpbGwgYmUgYXV0b21hdGljYWxseQogICAgdXBncmFkZWQgb3IgZG93bmdyYWRlZCB0byB0aGUgYXBwcm9wcmlhdGUgYExvY2F0aW9uYCBjbGFzcywgd2l0aCB0aGUgVVJMCiAgICB0cmFuc2Zvcm1lZCBhY2NvcmRpbmdseSwgaWYgbmVlZGVkLgogIAogICAgS2VlcCBpbiBtaW5kIHRoYXQgc2luY2Ugc29tZSBvZiB5b3VyIHVzZXJzIHdpbGwgdXNlIGBIaXN0b3J5TG9jYXRpb25gLCB5b3VyCiAgICBzZXJ2ZXIgbXVzdCBzZXJ2ZSB0aGUgRW1iZXIgYXBwIGF0IGFsbCB0aGUgcm91dGVzIHlvdSBkZWZpbmUuCiAgCiAgICBAY2xhc3MgQXV0b0xvY2F0aW9uCiAgICBAc3RhdGljCiAgICBAcHJvdGVjdGVkCiAgKi8KICB2YXIgQXV0b0xvY2F0aW9uID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9FbWJlck9iamVjdCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEF1dG9Mb2NhdGlvbiwgX0VtYmVyT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBBdXRvTG9jYXRpb24oKSB7CiAgICAgIHZhciBfdGhpczsKCiAgICAgIF90aGlzID0gX0VtYmVyT2JqZWN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgICAgX3RoaXMuaW1wbGVtZW50YXRpb24gPSAnYXV0byc7CiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KICAgIC8qKgogICAgIENhbGxlZCBieSB0aGUgcm91dGVyIHRvIGluc3RydWN0IHRoZSBsb2NhdGlvbiB0byBkbyBhbnkgZmVhdHVyZSBkZXRlY3Rpb24KICAgICBuZWNlc3NhcnkuIEluIHRoZSBjYXNlIG9mIEF1dG9Mb2NhdGlvbiwgd2UgZGV0ZWN0IHdoZXRoZXIgdG8gdXNlIGhpc3RvcnkKICAgICBvciBoYXNoIGNvbmNyZXRlIGltcGxlbWVudGF0aW9ucy4KICAgICAgICBAcHJpdmF0ZQogICAgKi8KCgogICAgdmFyIF9wcm90byA9IEF1dG9Mb2NhdGlvbi5wcm90b3R5cGU7CgogICAgX3Byb3RvLmRldGVjdCA9IGZ1bmN0aW9uIGRldGVjdCgpIHsKICAgICAgdmFyIHJvb3RVUkwgPSB0aGlzLnJvb3RVUkw7CiAgICAgIChmYWxzZSAmJiAhKHJvb3RVUkwuY2hhckF0KHJvb3RVUkwubGVuZ3RoIC0gMSkgPT09ICcvJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdyb290VVJMIG11c3QgZW5kIHdpdGggYSB0cmFpbGluZyBmb3J3YXJkIHNsYXNoIGUuZy4gIi9hcHAvIicsIHJvb3RVUkwuY2hhckF0KHJvb3RVUkwubGVuZ3RoIC0gMSkgPT09ICcvJykpOwogICAgICB2YXIgaW1wbGVtZW50YXRpb24gPSBkZXRlY3RJbXBsZW1lbnRhdGlvbih7CiAgICAgICAgbG9jYXRpb246IHRoaXMubG9jYXRpb24sCiAgICAgICAgaGlzdG9yeTogdGhpcy5oaXN0b3J5LAogICAgICAgIHVzZXJBZ2VudDogdGhpcy51c2VyQWdlbnQsCiAgICAgICAgcm9vdFVSTDogcm9vdFVSTCwKICAgICAgICBkb2N1bWVudE1vZGU6IHRoaXMuZG9jdW1lbnRNb2RlLAogICAgICAgIGdsb2JhbDogdGhpcy5nbG9iYWwKICAgICAgfSk7CgogICAgICBpZiAoaW1wbGVtZW50YXRpb24gPT09IGZhbHNlKSB7CiAgICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdjYW5jZWxSb3V0ZXJTZXR1cCcsIHRydWUpOwogICAgICAgIGltcGxlbWVudGF0aW9uID0gJ25vbmUnOwogICAgICB9CgogICAgICB2YXIgY29uY3JldGUgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKS5sb29rdXAoImxvY2F0aW9uOiIgKyBpbXBsZW1lbnRhdGlvbik7CiAgICAgIChmYWxzZSAmJiAhKGNvbmNyZXRlICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ291bGQgbm90IGZpbmQgbG9jYXRpb24gJyIgKyBpbXBsZW1lbnRhdGlvbiArICInLiIsIGNvbmNyZXRlICE9PSB1bmRlZmluZWQpKTsKICAgICAgKDAsIF9tZXRhbC5zZXQpKGNvbmNyZXRlLCAncm9vdFVSTCcsIHJvb3RVUkwpOwogICAgICAoMCwgX21ldGFsLnNldCkodGhpcywgJ2NvbmNyZXRlSW1wbGVtZW50YXRpb24nLCBjb25jcmV0ZSk7CiAgICB9OwoKICAgIF9wcm90by53aWxsRGVzdHJveSA9IGZ1bmN0aW9uIHdpbGxEZXN0cm95KCkgewogICAgICB2YXIgY29uY3JldGVJbXBsZW1lbnRhdGlvbiA9IHRoaXMuY29uY3JldGVJbXBsZW1lbnRhdGlvbjsKCiAgICAgIGlmIChjb25jcmV0ZUltcGxlbWVudGF0aW9uKSB7CiAgICAgICAgY29uY3JldGVJbXBsZW1lbnRhdGlvbi5kZXN0cm95KCk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEF1dG9Mb2NhdGlvbjsKICB9KF9ydW50aW1lLk9iamVjdCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBBdXRvTG9jYXRpb247CiAgQXV0b0xvY2F0aW9uLnJlb3Blbih7CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgV2lsbCBiZSBwcmUtcGVuZGVkIHRvIHBhdGggdXBvbiBzdGF0ZSBjaGFuZ2UuCiAgICAgICAgIEBzaW5jZSAxLjUuMQogICAgICBAcHJvcGVydHkgcm9vdFVSTAogICAgICBAZGVmYXVsdCAnLycKICAgICovCiAgICByb290VVJMOiAnLycsCiAgICBpbml0U3RhdGU6IGRlbGVnYXRlVG9Db25jcmV0ZUltcGxlbWVudGF0aW9uKCdpbml0U3RhdGUnKSwKICAgIGdldFVSTDogZGVsZWdhdGVUb0NvbmNyZXRlSW1wbGVtZW50YXRpb24oJ2dldFVSTCcpLAogICAgc2V0VVJMOiBkZWxlZ2F0ZVRvQ29uY3JldGVJbXBsZW1lbnRhdGlvbignc2V0VVJMJyksCiAgICByZXBsYWNlVVJMOiBkZWxlZ2F0ZVRvQ29uY3JldGVJbXBsZW1lbnRhdGlvbigncmVwbGFjZVVSTCcpLAogICAgb25VcGRhdGVVUkw6IGRlbGVnYXRlVG9Db25jcmV0ZUltcGxlbWVudGF0aW9uKCdvblVwZGF0ZVVSTCcpLAogICAgZm9ybWF0VVJMOiBkZWxlZ2F0ZVRvQ29uY3JldGVJbXBsZW1lbnRhdGlvbignZm9ybWF0VVJMJyksCgogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgICAgIFRoZSBicm93c2VyJ3MgYGxvY2F0aW9uYCBvYmplY3QuIFRoaXMgaXMgdHlwaWNhbGx5IGVxdWl2YWxlbnQgdG8KICAgICAgYHdpbmRvdy5sb2NhdGlvbmAsIGJ1dCBtYXkgYmUgb3ZlcnJpZGRlbiBmb3IgdGVzdGluZy4KICAgICAgICAgQHByb3BlcnR5IGxvY2F0aW9uCiAgICAgIEBkZWZhdWx0IGVudmlyb25tZW50LmxvY2F0aW9uCiAgICAqLwogICAgbG9jYXRpb246IF9icm93c2VyRW52aXJvbm1lbnQubG9jYXRpb24sCgogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgICAgIFRoZSBicm93c2VyJ3MgYGhpc3RvcnlgIG9iamVjdC4gVGhpcyBpcyB0eXBpY2FsbHkgZXF1aXZhbGVudCB0bwogICAgICBgd2luZG93Lmhpc3RvcnlgLCBidXQgbWF5IGJlIG92ZXJyaWRkZW4gZm9yIHRlc3RpbmcuCiAgICAgICAgIEBzaW5jZSAxLjUuMQogICAgICBAcHJvcGVydHkgaGlzdG9yeQogICAgICBAZGVmYXVsdCBlbnZpcm9ubWVudC5oaXN0b3J5CiAgICAqLwogICAgaGlzdG9yeTogX2Jyb3dzZXJFbnZpcm9ubWVudC5oaXN0b3J5LAoKICAgIC8qKgogICAgIEBwcml2YXRlCiAgICAgICAgVGhlIHVzZXIgYWdlbnQncyBnbG9iYWwgdmFyaWFibGUuIEluIGJyb3dzZXJzLCB0aGlzIHdpbGwgYmUgYHdpbmRvd2AuCiAgICAgICAgQHNpbmNlIDEuMTEKICAgICBAcHJvcGVydHkgZ2xvYmFsCiAgICAgQGRlZmF1bHQgd2luZG93CiAgICAqLwogICAgZ2xvYmFsOiBfYnJvd3NlckVudmlyb25tZW50LndpbmRvdywKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgVGhlIGJyb3dzZXIncyBgdXNlckFnZW50YC4gVGhpcyBpcyB0eXBpY2FsbHkgZXF1aXZhbGVudCB0bwogICAgICBgbmF2aWdhdG9yLnVzZXJBZ2VudGAsIGJ1dCBtYXkgYmUgb3ZlcnJpZGRlbiBmb3IgdGVzdGluZy4KICAgICAgICAgQHNpbmNlIDEuNS4xCiAgICAgIEBwcm9wZXJ0eSB1c2VyQWdlbnQKICAgICAgQGRlZmF1bHQgZW52aXJvbm1lbnQuaGlzdG9yeQogICAgKi8KICAgIHVzZXJBZ2VudDogX2Jyb3dzZXJFbnZpcm9ubWVudC51c2VyQWdlbnQsCgogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgICAgIFRoaXMgcHJvcGVydHkgaXMgdXNlZCBieSB0aGUgcm91dGVyIHRvIGtub3cgd2hldGhlciB0byBjYW5jZWwgdGhlIHJvdXRpbmcKICAgICAgc2V0dXAgcHJvY2Vzcywgd2hpY2ggaXMgbmVlZGVkIHdoaWxlIHdlIHJlZGlyZWN0IHRoZSBicm93c2VyLgogICAgICAgICBAc2luY2UgMS41LjEKICAgICAgQHByb3BlcnR5IGNhbmNlbFJvdXRlclNldHVwCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAqLwogICAgY2FuY2VsUm91dGVyU2V0dXA6IGZhbHNlCiAgfSk7CgogIGZ1bmN0aW9uIGRlbGVnYXRlVG9Db25jcmV0ZUltcGxlbWVudGF0aW9uKG1ldGhvZE5hbWUpIHsKICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBjb25jcmV0ZUltcGxlbWVudGF0aW9uID0gdGhpcy5jb25jcmV0ZUltcGxlbWVudGF0aW9uOwogICAgICAoZmFsc2UgJiYgIShCb29sZWFuKGNvbmNyZXRlSW1wbGVtZW50YXRpb24pKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF1dG9Mb2NhdGlvbidzIGRldGVjdCgpIG1ldGhvZCBzaG91bGQgYmUgY2FsbGVkIGJlZm9yZSBjYWxsaW5nIGFueSBvdGhlciBob29rcy4iLCBCb29sZWFuKGNvbmNyZXRlSW1wbGVtZW50YXRpb24pKSk7CgogICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICByZXR1cm4gKDAsIF91dGlscy50cnlJbnZva2UpKGNvbmNyZXRlSW1wbGVtZW50YXRpb24sIG1ldGhvZE5hbWUsIGFyZ3MpOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIGRldGVjdEltcGxlbWVudGF0aW9uKG9wdGlvbnMpIHsKICAgIHZhciBsb2NhdGlvbiA9IG9wdGlvbnMubG9jYXRpb24sCiAgICAgICAgdXNlckFnZW50ID0gb3B0aW9ucy51c2VyQWdlbnQsCiAgICAgICAgaGlzdG9yeSA9IG9wdGlvbnMuaGlzdG9yeSwKICAgICAgICBkb2N1bWVudE1vZGUgPSBvcHRpb25zLmRvY3VtZW50TW9kZSwKICAgICAgICBnbG9iYWwgPSBvcHRpb25zLmdsb2JhbCwKICAgICAgICByb290VVJMID0gb3B0aW9ucy5yb290VVJMOwogICAgdmFyIGltcGxlbWVudGF0aW9uID0gJ25vbmUnOwogICAgdmFyIGNhbmNlbFJvdXRlclNldHVwID0gZmFsc2U7CiAgICB2YXIgY3VycmVudFBhdGggPSAoMCwgX3V0aWwuZ2V0RnVsbFBhdGgpKGxvY2F0aW9uKTsKCiAgICBpZiAoKDAsIF91dGlsLnN1cHBvcnRzSGlzdG9yeSkodXNlckFnZW50LCBoaXN0b3J5KSkgewogICAgICB2YXIgaGlzdG9yeVBhdGggPSBnZXRIaXN0b3J5UGF0aChyb290VVJMLCBsb2NhdGlvbik7IC8vIElmIHRoZSBicm93c2VyIHN1cHBvcnRzIGhpc3RvcnkgYW5kIHdlIGhhdmUgYSBoaXN0b3J5IHBhdGgsIHdlIGNhbiB1c2UKICAgICAgLy8gdGhlIGhpc3RvcnkgbG9jYXRpb24gd2l0aCBubyByZWRpcmVjdHMuCgogICAgICBpZiAoY3VycmVudFBhdGggPT09IGhpc3RvcnlQYXRoKSB7CiAgICAgICAgaW1wbGVtZW50YXRpb24gPSAnaGlzdG9yeSc7CiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFBhdGguc3Vic3RyKDAsIDIpID09PSAnLyMnKSB7CiAgICAgICAgaGlzdG9yeS5yZXBsYWNlU3RhdGUoewogICAgICAgICAgcGF0aDogaGlzdG9yeVBhdGgKICAgICAgICB9LCAnJywgaGlzdG9yeVBhdGgpOwogICAgICAgIGltcGxlbWVudGF0aW9uID0gJ2hpc3RvcnknOwogICAgICB9IGVsc2UgewogICAgICAgIGNhbmNlbFJvdXRlclNldHVwID0gdHJ1ZTsKICAgICAgICAoMCwgX3V0aWwucmVwbGFjZVBhdGgpKGxvY2F0aW9uLCBoaXN0b3J5UGF0aCk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoKDAsIF91dGlsLnN1cHBvcnRzSGFzaENoYW5nZSkoZG9jdW1lbnRNb2RlLCBnbG9iYWwpKSB7CiAgICAgIHZhciBoYXNoUGF0aCA9IGdldEhhc2hQYXRoKHJvb3RVUkwsIGxvY2F0aW9uKTsgLy8gQmUgc3VyZSB3ZSdyZSB1c2luZyBhIGhhc2hlZCBwYXRoLCBvdGhlcndpc2UgbGV0J3Mgc3dpdGNoIG92ZXIgaXQgdG8gc28KICAgICAgLy8gd2Ugc3RhcnQgb2ZmIGNsZWFuIGFuZCBjb25zaXN0ZW50LiBXZSdsbCBjb3VudCBhbiBpbmRleCBwYXRoIHdpdGggbm8KICAgICAgLy8gaGFzaCBhcyAiZ29vZCBlbm91Z2giIGFzIHdlbGwuCgogICAgICBpZiAoY3VycmVudFBhdGggPT09IGhhc2hQYXRoIHx8IGN1cnJlbnRQYXRoID09PSAnLycgJiYgaGFzaFBhdGggPT09ICcvIy8nKSB7CiAgICAgICAgaW1wbGVtZW50YXRpb24gPSAnaGFzaCc7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gT3VyIFVSTCBpc24ndCBpbiB0aGUgZXhwZWN0ZWQgaGFzaC1zdXBwb3J0ZWQgZm9ybWF0LCBzbyB3ZSB3YW50IHRvCiAgICAgICAgLy8gY2FuY2VsIHRoZSByb3V0ZXIgc2V0dXAgYW5kIHJlcGxhY2UgdGhlIFVSTCB0byBzdGFydCBvZmYgY2xlYW4KICAgICAgICBjYW5jZWxSb3V0ZXJTZXR1cCA9IHRydWU7CiAgICAgICAgKDAsIF91dGlsLnJlcGxhY2VQYXRoKShsb2NhdGlvbiwgaGFzaFBhdGgpOwogICAgICB9CiAgICB9CgogICAgaWYgKGNhbmNlbFJvdXRlclNldHVwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICByZXR1cm4gaW1wbGVtZW50YXRpb247CiAgfQogIC8qKgogICAgQHByaXZhdGUKICAKICAgIFJldHVybnMgdGhlIGN1cnJlbnQgcGF0aCBhcyBpdCBzaG91bGQgYXBwZWFyIGZvciBIaXN0b3J5TG9jYXRpb24gc3VwcG9ydGVkCiAgICBicm93c2Vycy4gVGhpcyBtYXkgdmVyeSB3ZWxsIGRpZmZlciBmcm9tIHRoZSByZWFsIGN1cnJlbnQgcGF0aCAoZS5nLiBpZiBpdAogICAgc3RhcnRzIG9mZiBhcyBhIGhhc2hlZCBVUkwpCiAgKi8KCgogIGZ1bmN0aW9uIGdldEhpc3RvcnlQYXRoKHJvb3RVUkwsIGxvY2F0aW9uKSB7CiAgICB2YXIgcGF0aCA9ICgwLCBfdXRpbC5nZXRQYXRoKShsb2NhdGlvbik7CiAgICB2YXIgaGFzaCA9ICgwLCBfdXRpbC5nZXRIYXNoKShsb2NhdGlvbik7CiAgICB2YXIgcXVlcnkgPSAoMCwgX3V0aWwuZ2V0UXVlcnkpKGxvY2F0aW9uKTsKICAgIHZhciByb290VVJMSW5kZXggPSBwYXRoLmluZGV4T2Yocm9vdFVSTCk7CiAgICB2YXIgcm91dGVIYXNoLCBoYXNoUGFydHM7CiAgICAoZmFsc2UgJiYgIShyb290VVJMSW5kZXggPT09IDApICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiUGF0aCAiICsgcGF0aCArICIgZG9lcyBub3Qgc3RhcnQgd2l0aCB0aGUgcHJvdmlkZWQgcm9vdFVSTCAiICsgcm9vdFVSTCwgcm9vdFVSTEluZGV4ID09PSAwKSk7IC8vIEJ5IGNvbnZlbnRpb24sIEVtYmVyLmpzIHJvdXRlcyB1c2luZyBIYXNoTG9jYXRpb24gYXJlIHJlcXVpcmVkIHRvIHN0YXJ0CiAgICAvLyB3aXRoIGAjL2AuIEFueXRoaW5nIGVsc2Ugc2hvdWxkIE5PVCBiZSBjb25zaWRlcmVkIGEgcm91dGUgYW5kIHNob3VsZAogICAgLy8gYmUgcGFzc2VkIHN0cmFpZ2h0IHRocm91Z2gsIHdpdGhvdXQgdHJhbnNmb3JtYXRpb24uCgogICAgaWYgKGhhc2guc3Vic3RyKDAsIDIpID09PSAnIy8nKSB7CiAgICAgIC8vIFRoZXJlIGNvdWxkIGJlIGV4dHJhIGhhc2ggc2VnbWVudHMgYWZ0ZXIgdGhlIHJvdXRlCiAgICAgIGhhc2hQYXJ0cyA9IGhhc2guc3Vic3RyKDEpLnNwbGl0KCcjJyk7IC8vIFRoZSBmaXJzdCBvbmUgaXMgYWx3YXlzIHRoZSByb3V0ZSB1cmwKCiAgICAgIHJvdXRlSGFzaCA9IGhhc2hQYXJ0cy5zaGlmdCgpOyAvLyBJZiB0aGUgcGF0aCBhbHJlYWR5IGhhcyBhIHRyYWlsaW5nIHNsYXNoLCByZW1vdmUgdGhlIG9uZQogICAgICAvLyBmcm9tIHRoZSBoYXNoZWQgcm91dGUgc28gd2UgZG9uJ3QgZG91YmxlIHVwLgoKICAgICAgaWYgKHBhdGguY2hhckF0KHBhdGgubGVuZ3RoIC0gMSkgPT09ICcvJykgewogICAgICAgIHJvdXRlSGFzaCA9IHJvdXRlSGFzaC5zdWJzdHIoMSk7CiAgICAgIH0gLy8gVGhpcyBpcyB0aGUgImV4cGVjdGVkIiBmaW5hbCBvcmRlcgoKCiAgICAgIHBhdGggKz0gcm91dGVIYXNoICsgcXVlcnk7CgogICAgICBpZiAoaGFzaFBhcnRzLmxlbmd0aCkgewogICAgICAgIHBhdGggKz0gIiMiICsgaGFzaFBhcnRzLmpvaW4oJyMnKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgcGF0aCArPSBxdWVyeSArIGhhc2g7CiAgICB9CgogICAgcmV0dXJuIHBhdGg7CiAgfQogIC8qKgogICAgQHByaXZhdGUKICAKICAgIFJldHVybnMgdGhlIGN1cnJlbnQgcGF0aCBhcyBpdCBzaG91bGQgYXBwZWFyIGZvciBIYXNoTG9jYXRpb24gc3VwcG9ydGVkCiAgICBicm93c2Vycy4gVGhpcyBtYXkgdmVyeSB3ZWxsIGRpZmZlciBmcm9tIHRoZSByZWFsIGN1cnJlbnQgcGF0aC4KICAKICAgIEBtZXRob2QgX2dldEhhc2hQYXRoCiAgKi8KCgogIGZ1bmN0aW9uIGdldEhhc2hQYXRoKHJvb3RVUkwsIGxvY2F0aW9uKSB7CiAgICB2YXIgcGF0aCA9IHJvb3RVUkw7CiAgICB2YXIgaGlzdG9yeVBhdGggPSBnZXRIaXN0b3J5UGF0aChyb290VVJMLCBsb2NhdGlvbik7CiAgICB2YXIgcm91dGVQYXRoID0gaGlzdG9yeVBhdGguc3Vic3RyKHJvb3RVUkwubGVuZ3RoKTsKCiAgICBpZiAocm91dGVQYXRoICE9PSAnJykgewogICAgICBpZiAocm91dGVQYXRoWzBdICE9PSAnLycpIHsKICAgICAgICByb3V0ZVBhdGggPSAiLyIgKyByb3V0ZVBhdGg7CiAgICAgIH0KCiAgICAgIHBhdGggKz0gIiMiICsgcm91dGVQYXRoOwogICAgfQoKICAgIHJldHVybiBwYXRoOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vaGFzaF9sb2NhdGlvbiIsIFsiZXhwb3J0cyIsICJlbWJlci1iYWJlbCIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIiwgIkBlbWJlci9ydW5sb29wIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL3V0aWwiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX21ldGFsLCBfcnVudGltZSwgX3J1bmxvb3AsIF91dGlsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIEBlbWJlci9yb3V0aW5nCiAgKi8KCiAgLyoqCiAgICBgSGFzaExvY2F0aW9uYCBpbXBsZW1lbnRzIHRoZSBsb2NhdGlvbiBBUEkgdXNpbmcgdGhlIGJyb3dzZXIncwogICAgaGFzaC4gQXQgcHJlc2VudCwgaXQgcmVsaWVzIG9uIGEgYGhhc2hjaGFuZ2VgIGV2ZW50IGV4aXN0aW5nIGluIHRoZQogICAgYnJvd3Nlci4KICAKICAgIFVzaW5nIGBIYXNoTG9jYXRpb25gIHJlc3VsdHMgaW4gVVJMcyB3aXRoIGEgYCNgIChoYXNoIHNpZ24pIHNlcGFyYXRpbmcgdGhlCiAgICBzZXJ2ZXIgc2lkZSBVUkwgcG9ydGlvbiBvZiB0aGUgVVJMIGZyb20gdGhlIHBvcnRpb24gdGhhdCBpcyB1c2VkIGJ5IEVtYmVyLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgIHRoaXMucm91dGUoJ3Bvc3RzJywgZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgnbmV3Jyk7CiAgICAgIH0pOwogICAgfSk7CiAgCiAgICBSb3V0ZXIucmVvcGVuKHsKICAgICAgbG9jYXRpb246ICdoYXNoJwogICAgfSk7CiAgICBgYGAKICAKICAgIFRoaXMgd2lsbCByZXN1bHQgaW4gYSBwb3N0cy5uZXcgdXJsIG9mIGAvIy9wb3N0cy9uZXdgLgogIAogICAgQGNsYXNzIEhhc2hMb2NhdGlvbgogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAgIEBwcm90ZWN0ZWQKICAqLwogIHZhciBIYXNoTG9jYXRpb24gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0VtYmVyT2JqZWN0KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoSGFzaExvY2F0aW9uLCBfRW1iZXJPYmplY3QpOwoKICAgIGZ1bmN0aW9uIEhhc2hMb2NhdGlvbigpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfRW1iZXJPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpcy5pbXBsZW1lbnRhdGlvbiA9ICdoYXNoJzsKICAgICAgcmV0dXJuIF90aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBIYXNoTG9jYXRpb24ucHJvdG90eXBlOwoKICAgIF9wcm90by5pbml0ID0gZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdsb2NhdGlvbicsIHRoaXMuX2xvY2F0aW9uIHx8IHdpbmRvdy5sb2NhdGlvbik7CiAgICAgIHRoaXMuX2hhc2hjaGFuZ2VIYW5kbGVyID0gdW5kZWZpbmVkOwogICAgfQogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgICAgIFJldHVybnMgbm9ybWFsaXplZCBsb2NhdGlvbi5oYXNoCiAgICAgICAgIEBzaW5jZSAxLjUuMQogICAgICBAbWV0aG9kIGdldEhhc2gKICAgICovCiAgICA7CgogICAgX3Byb3RvLmdldEhhc2ggPSBmdW5jdGlvbiBnZXRIYXNoKCkgewogICAgICByZXR1cm4gKDAsIF91dGlsLmdldEhhc2gpKHRoaXMubG9jYXRpb24pOwogICAgfQogICAgLyoqCiAgICAgIFJldHVybnMgdGhlIG5vcm1hbGl6ZWQgVVJMLCBjb25zdHJ1Y3RlZCBmcm9tIGBsb2NhdGlvbi5oYXNoYC4KICAgICAgICAgZS5nLiBgIy9mb29gID0+IGAvZm9vYCBhcyB3ZWxsIGFzIGAjL2ZvbyNiYXJgID0+IGAvZm9vI2JhcmAuCiAgICAgICAgIEJ5IGNvbnZlbnRpb24sIGhhc2hlZCBwYXRocyBtdXN0IGJlZ2luIHdpdGggYSBmb3J3YXJkIHNsYXNoLCBvdGhlcndpc2UgdGhleQogICAgICBhcmUgbm90IHRyZWF0ZWQgYXMgYSBwYXRoIHNvIHdlIGNhbiBkaXN0aW5ndWlzaCBpbnRlbnQuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZ2V0VVJMCiAgICAqLwogICAgOwoKICAgIF9wcm90by5nZXRVUkwgPSBmdW5jdGlvbiBnZXRVUkwoKSB7CiAgICAgIHZhciBvcmlnaW5hbFBhdGggPSB0aGlzLmdldEhhc2goKS5zdWJzdHIoMSk7CiAgICAgIHZhciBvdXRQYXRoID0gb3JpZ2luYWxQYXRoOwoKICAgICAgaWYgKG91dFBhdGhbMF0gIT09ICcvJykgewogICAgICAgIG91dFBhdGggPSAnLyc7IC8vIE9ubHkgYWRkIHRoZSAjIGlmIHRoZSBwYXRoIGlzbid0IGVtcHR5LgogICAgICAgIC8vIFdlIGRvIE5PVCB3YW50IGAvI2Agc2luY2UgdGhlIGFtcGVyc2FuZAogICAgICAgIC8vIGlzIG9ubHkgaW5jbHVkZWQgKGNvbnZlbnRpb25hbGx5KSB3aGVuCiAgICAgICAgLy8gdGhlIGxvY2F0aW9uLmhhc2ggaGFzIGEgdmFsdWUKCiAgICAgICAgaWYgKG9yaWdpbmFsUGF0aCkgewogICAgICAgICAgb3V0UGF0aCArPSAiIyIgKyBvcmlnaW5hbFBhdGg7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gb3V0UGF0aDsKICAgIH0KICAgIC8qKgogICAgICBTZXQgdGhlIGBsb2NhdGlvbi5oYXNoYCBhbmQgcmVtZW1iZXJzIHdoYXQgd2FzIHNldC4gVGhpcyBwcmV2ZW50cwogICAgICBgb25VcGRhdGVVUkxgIGNhbGxiYWNrcyBmcm9tIHRyaWdnZXJpbmcgd2hlbiB0aGUgaGFzaCB3YXMgc2V0IGJ5CiAgICAgIGBIYXNoTG9jYXRpb25gLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHNldFVSTAogICAgICBAcGFyYW0gcGF0aCB7U3RyaW5nfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uc2V0VVJMID0gZnVuY3Rpb24gc2V0VVJMKHBhdGgpIHsKICAgICAgdGhpcy5sb2NhdGlvbi5oYXNoID0gcGF0aDsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdsYXN0U2V0VVJMJywgcGF0aCk7CiAgICB9CiAgICAvKioKICAgICAgVXNlcyBsb2NhdGlvbi5yZXBsYWNlIHRvIHVwZGF0ZSB0aGUgdXJsIHdpdGhvdXQgYSBwYWdlIHJlbG9hZAogICAgICBvciBoaXN0b3J5IG1vZGlmaWNhdGlvbi4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCByZXBsYWNlVVJMCiAgICAgIEBwYXJhbSBwYXRoIHtTdHJpbmd9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5yZXBsYWNlVVJMID0gZnVuY3Rpb24gcmVwbGFjZVVSTChwYXRoKSB7CiAgICAgIHRoaXMubG9jYXRpb24ucmVwbGFjZSgiIyIgKyBwYXRoKTsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdsYXN0U2V0VVJMJywgcGF0aCk7CiAgICB9CiAgICAvKioKICAgICAgUmVnaXN0ZXIgYSBjYWxsYmFjayB0byBiZSBpbnZva2VkIHdoZW4gdGhlIGhhc2ggY2hhbmdlcy4gVGhlc2UKICAgICAgY2FsbGJhY2tzIHdpbGwgZXhlY3V0ZSB3aGVuIHRoZSB1c2VyIHByZXNzZXMgdGhlIGJhY2sgb3IgZm9yd2FyZAogICAgICBidXR0b24sIGJ1dCBub3QgYWZ0ZXIgYHNldFVSTGAgaXMgaW52b2tlZC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBvblVwZGF0ZVVSTAogICAgICBAcGFyYW0gY2FsbGJhY2sge0Z1bmN0aW9ufQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ub25VcGRhdGVVUkwgPSBmdW5jdGlvbiBvblVwZGF0ZVVSTChjYWxsYmFjaykgewogICAgICB0aGlzLl9yZW1vdmVFdmVudExpc3RlbmVyKCk7CgogICAgICB0aGlzLl9oYXNoY2hhbmdlSGFuZGxlciA9ICgwLCBfcnVubG9vcC5iaW5kKSh0aGlzLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIHBhdGggPSB0aGlzLmdldFVSTCgpOwoKICAgICAgICBpZiAodGhpcy5sYXN0U2V0VVJMID09PSBwYXRoKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICAoMCwgX21ldGFsLnNldCkodGhpcywgJ2xhc3RTZXRVUkwnLCBudWxsKTsKICAgICAgICBjYWxsYmFjayhwYXRoKTsKICAgICAgfSk7CiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdoYXNoY2hhbmdlJywgdGhpcy5faGFzaGNoYW5nZUhhbmRsZXIpOwogICAgfQogICAgLyoqCiAgICAgIEdpdmVuIGEgVVJMLCBmb3JtYXRzIGl0IHRvIGJlIHBsYWNlZCBpbnRvIHRoZSBwYWdlIGFzIHBhcnQKICAgICAgb2YgYW4gZWxlbWVudCdzIGBocmVmYCBhdHRyaWJ1dGUuCiAgICAgICAgIFRoaXMgaXMgdXNlZCwgZm9yIGV4YW1wbGUsIHdoZW4gdXNpbmcgdGhlIHt7YWN0aW9ufX0gaGVscGVyCiAgICAgIHRvIGdlbmVyYXRlIGEgVVJMIGJhc2VkIG9uIGFuIGV2ZW50LgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGZvcm1hdFVSTAogICAgICBAcGFyYW0gdXJsIHtTdHJpbmd9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5mb3JtYXRVUkwgPSBmdW5jdGlvbiBmb3JtYXRVUkwodXJsKSB7CiAgICAgIHJldHVybiAiIyIgKyB1cmw7CiAgICB9CiAgICAvKioKICAgICAgQ2xlYW5zIHVwIHRoZSBIYXNoTG9jYXRpb24gZXZlbnQgbGlzdGVuZXIuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2Qgd2lsbERlc3Ryb3kKICAgICovCiAgICA7CgogICAgX3Byb3RvLndpbGxEZXN0cm95ID0gZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3JlbW92ZUV2ZW50TGlzdGVuZXIoKTsKICAgIH07CgogICAgX3Byb3RvLl9yZW1vdmVFdmVudExpc3RlbmVyID0gZnVuY3Rpb24gX3JlbW92ZUV2ZW50TGlzdGVuZXIoKSB7CiAgICAgIGlmICh0aGlzLl9oYXNoY2hhbmdlSGFuZGxlcikgewogICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdoYXNoY2hhbmdlJywgdGhpcy5faGFzaGNoYW5nZUhhbmRsZXIpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBIYXNoTG9jYXRpb247CiAgfShfcnVudGltZS5PYmplY3QpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gSGFzaExvY2F0aW9uOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9sb2NhdGlvbi9oaXN0b3J5X2xvY2F0aW9uIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vdXRpbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfbWV0YWwsIF9ydW50aW1lLCBfdXRpbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvcm91dGluZwogICovCiAgdmFyIHBvcHN0YXRlRmlyZWQgPSBmYWxzZTsKCiAgZnVuY3Rpb24gX3V1aWQoKSB7CiAgICByZXR1cm4gJ3h4eHh4eHh4LXh4eHgtNHh4eC15eHh4LXh4eHh4eHh4eHh4eCcucmVwbGFjZSgvW3h5XS9nLCBmdW5jdGlvbiAoYykgewogICAgICB2YXIgciwgdjsKICAgICAgciA9IE1hdGgucmFuZG9tKCkgKiAxNiB8IDA7CiAgICAgIHYgPSBjID09PSAneCcgPyByIDogciAmIDMgfCA4OwogICAgICByZXR1cm4gdi50b1N0cmluZygxNik7CiAgICB9KTsKICB9CiAgLyoqCiAgICBIaXN0b3J5TG9jYXRpb24gaW1wbGVtZW50cyB0aGUgbG9jYXRpb24gQVBJIHVzaW5nIHRoZSBicm93c2VyJ3MKICAgIGhpc3RvcnkucHVzaFN0YXRlIEFQSS4KICAKICAgIFVzaW5nIGBIaXN0b3J5TG9jYXRpb25gIHJlc3VsdHMgaW4gVVJMcyB0aGF0IGFyZSBpbmRpc3Rpbmd1aXNoYWJsZSBmcm9tIGEKICAgIHN0YW5kYXJkIFVSTC4gVGhpcyByZWxpZXMgdXBvbiB0aGUgYnJvd3NlcidzIGBoaXN0b3J5YCBBUEkuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgYXBwL3JvdXRlci5qcwogICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgdGhpcy5yb3V0ZSgncG9zdHMnLCBmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCduZXcnKTsKICAgICAgfSk7CiAgICB9KTsKICAKICAgIFJvdXRlci5yZW9wZW4oewogICAgICBsb2NhdGlvbjogJ2hpc3RvcnknCiAgICB9KTsKICAgIGBgYAogIAogICAgVGhpcyB3aWxsIHJlc3VsdCBpbiBhIHBvc3RzLm5ldyB1cmwgb2YgYC9wb3N0cy9uZXdgLgogIAogICAgS2VlcCBpbiBtaW5kIHRoYXQgeW91ciBzZXJ2ZXIgbXVzdCBzZXJ2ZSB0aGUgRW1iZXIgYXBwIGF0IGFsbCB0aGUgcm91dGVzIHlvdQogICAgZGVmaW5lLgogIAogICAgQGNsYXNzIEhpc3RvcnlMb2NhdGlvbgogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAgIEBwcm90ZWN0ZWQKICAqLwoKCiAgdmFyIEhpc3RvcnlMb2NhdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW1iZXJPYmplY3QpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShIaXN0b3J5TG9jYXRpb24sIF9FbWJlck9iamVjdCk7CgogICAgZnVuY3Rpb24gSGlzdG9yeUxvY2F0aW9uKCkgewogICAgICB2YXIgX3RoaXM7CgogICAgICBfdGhpcyA9IF9FbWJlck9iamVjdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICAgIF90aGlzLmltcGxlbWVudGF0aW9uID0gJ2hpc3RvcnknOwogICAgICAvKioKICAgICAgICBXaWxsIGJlIHByZS1wZW5kZWQgdG8gcGF0aCB1cG9uIHN0YXRlIGNoYW5nZQogICAgICAgICAgICAgICBAcHJvcGVydHkgcm9vdFVSTAogICAgICAgIEBkZWZhdWx0ICcvJwogICAgICAgIEBwcml2YXRlCiAgICAgICovCgogICAgICBfdGhpcy5yb290VVJMID0gJy8nOwogICAgICByZXR1cm4gX3RoaXM7CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgUmV0dXJucyBub3JtYWxpemVkIGxvY2F0aW9uLmhhc2gKICAgICAgICAgQG1ldGhvZCBnZXRIYXNoCiAgICAqLwoKCiAgICB2YXIgX3Byb3RvID0gSGlzdG9yeUxvY2F0aW9uLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uZ2V0SGFzaCA9IGZ1bmN0aW9uIGdldEhhc2goKSB7CiAgICAgIHJldHVybiAoMCwgX3V0aWwuZ2V0SGFzaCkodGhpcy5sb2NhdGlvbik7CiAgICB9OwoKICAgIF9wcm90by5pbml0ID0gZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIHZhciBiYXNlID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignYmFzZScpOwogICAgICB2YXIgYmFzZVVSTCA9ICcnOwoKICAgICAgaWYgKGJhc2UpIHsKICAgICAgICBiYXNlVVJMID0gYmFzZS5nZXRBdHRyaWJ1dGUoJ2hyZWYnKTsKICAgICAgfQoKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdiYXNlVVJMJywgYmFzZVVSTCk7CiAgICAgICgwLCBfbWV0YWwuc2V0KSh0aGlzLCAnbG9jYXRpb24nLCB0aGlzLmxvY2F0aW9uIHx8IHdpbmRvdy5sb2NhdGlvbik7CiAgICAgIHRoaXMuX3BvcHN0YXRlSGFuZGxlciA9IHVuZGVmaW5lZDsKICAgIH0KICAgIC8qKgogICAgICBVc2VkIHRvIHNldCBzdGF0ZSBvbiBmaXJzdCBjYWxsIHRvIHNldFVSTAogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGluaXRTdGF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uaW5pdFN0YXRlID0gZnVuY3Rpb24gaW5pdFN0YXRlKCkgewogICAgICB2YXIgaGlzdG9yeSA9IHRoaXMuaGlzdG9yeSB8fCB3aW5kb3cuaGlzdG9yeTsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdoaXN0b3J5JywgaGlzdG9yeSk7CgogICAgICBpZiAoaGlzdG9yeSAmJiAnc3RhdGUnIGluIGhpc3RvcnkpIHsKICAgICAgICB0aGlzLnN1cHBvcnRzSGlzdG9yeSA9IHRydWU7CiAgICAgIH0KCiAgICAgIHZhciBzdGF0ZSA9IHRoaXMuZ2V0U3RhdGUoKTsKICAgICAgdmFyIHBhdGggPSB0aGlzLmZvcm1hdFVSTCh0aGlzLmdldFVSTCgpKTsKCiAgICAgIGlmIChzdGF0ZSAmJiBzdGF0ZS5wYXRoID09PSBwYXRoKSB7CiAgICAgICAgLy8gcHJlc2VydmUgZXhpc3Rpbmcgc3RhdGUKICAgICAgICAvLyB1c2VkIGZvciB3ZWJraXQgd29ya2Fyb3VuZCwgc2luY2UgdGhlcmUgd2lsbCBiZSBubyBpbml0aWFsIHBvcHN0YXRlIGV2ZW50CiAgICAgICAgdGhpcy5fcHJldmlvdXNVUkwgPSB0aGlzLmdldFVSTCgpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMucmVwbGFjZVN0YXRlKHBhdGgpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgUmV0dXJucyB0aGUgY3VycmVudCBgbG9jYXRpb24ucGF0aG5hbWVgIHdpdGhvdXQgYHJvb3RVUkxgIG9yIGBiYXNlVVJMYAogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGdldFVSTAogICAgICBAcmV0dXJuIHVybCB7U3RyaW5nfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZ2V0VVJMID0gZnVuY3Rpb24gZ2V0VVJMKCkgewogICAgICB2YXIgbG9jYXRpb24gPSB0aGlzLmxvY2F0aW9uLAogICAgICAgICAgcm9vdFVSTCA9IHRoaXMucm9vdFVSTCwKICAgICAgICAgIGJhc2VVUkwgPSB0aGlzLmJhc2VVUkw7CiAgICAgIHZhciBwYXRoID0gbG9jYXRpb24ucGF0aG5hbWU7IC8vIHJlbW92ZSB0cmFpbGluZyBzbGFzaGVzIGlmIHRoZXkgZXhpc3RzCgogICAgICByb290VVJMID0gcm9vdFVSTC5yZXBsYWNlKC9cLyQvLCAnJyk7CiAgICAgIGJhc2VVUkwgPSBiYXNlVVJMLnJlcGxhY2UoL1wvJC8sICcnKTsgLy8gcmVtb3ZlIGJhc2VVUkwgYW5kIHJvb3RVUkwgZnJvbSBzdGFydCBvZiBwYXRoCgogICAgICB2YXIgdXJsID0gcGF0aC5yZXBsYWNlKG5ldyBSZWdFeHAoIl4iICsgYmFzZVVSTCArICIoPz0vfCQpIiksICcnKS5yZXBsYWNlKG5ldyBSZWdFeHAoIl4iICsgcm9vdFVSTCArICIoPz0vfCQpIiksICcnKS5yZXBsYWNlKC9cL1wvL2csICcvJyk7IC8vIHJlbW92ZSBleHRyYSBzbGFzaGVzCgogICAgICB2YXIgc2VhcmNoID0gbG9jYXRpb24uc2VhcmNoIHx8ICcnOwogICAgICB1cmwgKz0gc2VhcmNoICsgdGhpcy5nZXRIYXNoKCk7CiAgICAgIHJldHVybiB1cmw7CiAgICB9CiAgICAvKioKICAgICAgVXNlcyBgaGlzdG9yeS5wdXNoU3RhdGVgIHRvIHVwZGF0ZSB0aGUgdXJsIHdpdGhvdXQgYSBwYWdlIHJlbG9hZC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBzZXRVUkwKICAgICAgQHBhcmFtIHBhdGgge1N0cmluZ30KICAgICovCiAgICA7CgogICAgX3Byb3RvLnNldFVSTCA9IGZ1bmN0aW9uIHNldFVSTChwYXRoKSB7CiAgICAgIHZhciBzdGF0ZSA9IHRoaXMuZ2V0U3RhdGUoKTsKICAgICAgcGF0aCA9IHRoaXMuZm9ybWF0VVJMKHBhdGgpOwoKICAgICAgaWYgKCFzdGF0ZSB8fCBzdGF0ZS5wYXRoICE9PSBwYXRoKSB7CiAgICAgICAgdGhpcy5wdXNoU3RhdGUocGF0aCk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBVc2VzIGBoaXN0b3J5LnJlcGxhY2VTdGF0ZWAgdG8gdXBkYXRlIHRoZSB1cmwgd2l0aG91dCBhIHBhZ2UgcmVsb2FkCiAgICAgIG9yIGhpc3RvcnkgbW9kaWZpY2F0aW9uLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHJlcGxhY2VVUkwKICAgICAgQHBhcmFtIHBhdGgge1N0cmluZ30KICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlcGxhY2VVUkwgPSBmdW5jdGlvbiByZXBsYWNlVVJMKHBhdGgpIHsKICAgICAgdmFyIHN0YXRlID0gdGhpcy5nZXRTdGF0ZSgpOwogICAgICBwYXRoID0gdGhpcy5mb3JtYXRVUkwocGF0aCk7CgogICAgICBpZiAoIXN0YXRlIHx8IHN0YXRlLnBhdGggIT09IHBhdGgpIHsKICAgICAgICB0aGlzLnJlcGxhY2VTdGF0ZShwYXRoKTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgIEdldCB0aGUgY3VycmVudCBgaGlzdG9yeS5zdGF0ZWAuIENoZWNrcyBmb3IgaWYgYSBwb2x5ZmlsbCBpcwogICAgICByZXF1aXJlZCBhbmQgaWYgc28gZmV0Y2hlcyB0aGlzLl9oaXN0b3J5U3RhdGUuIFRoZSBzdGF0ZSByZXR1cm5lZAogICAgICBmcm9tIGdldFN0YXRlIG1heSBiZSBudWxsIGlmIGFuIGlmcmFtZSBoYXMgY2hhbmdlZCBhIHdpbmRvdydzCiAgICAgIGhpc3RvcnkuCiAgICAgICAgIFRoZSBvYmplY3QgcmV0dXJuZWQgd2lsbCBjb250YWluIGEgYHBhdGhgIGZvciB0aGUgZ2l2ZW4gc3RhdGUgYXMgd2VsbAogICAgICBhcyBhIHVuaXF1ZSBzdGF0ZSBgaWRgLiBUaGUgc3RhdGUgaW5kZXggd2lsbCBhbGxvdyB0aGUgYXBwIHRvIGRpc3Rpbmd1aXNoCiAgICAgIGJldHdlZW4gdHdvIHN0YXRlcyB3aXRoIHNpbWlsYXIgcGF0aHMgYnV0IHNob3VsZCBiZSB1bmlxdWUgZnJvbSBvbmUgYW5vdGhlci4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBnZXRTdGF0ZQogICAgICBAcmV0dXJuIHN0YXRlIHtPYmplY3R9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5nZXRTdGF0ZSA9IGZ1bmN0aW9uIGdldFN0YXRlKCkgewogICAgICBpZiAodGhpcy5zdXBwb3J0c0hpc3RvcnkpIHsKICAgICAgICByZXR1cm4gdGhpcy5oaXN0b3J5LnN0YXRlOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5faGlzdG9yeVN0YXRlOwogICAgfQogICAgLyoqCiAgICAgUHVzaGVzIGEgbmV3IHN0YXRlLgogICAgICAgIEBwcml2YXRlCiAgICAgQG1ldGhvZCBwdXNoU3RhdGUKICAgICBAcGFyYW0gcGF0aCB7U3RyaW5nfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucHVzaFN0YXRlID0gZnVuY3Rpb24gcHVzaFN0YXRlKHBhdGgpIHsKICAgICAgdmFyIHN0YXRlID0gewogICAgICAgIHBhdGg6IHBhdGgsCiAgICAgICAgdXVpZDogX3V1aWQoKQogICAgICB9OwogICAgICB0aGlzLmhpc3RvcnkucHVzaFN0YXRlKHN0YXRlLCBudWxsLCBwYXRoKTsKICAgICAgdGhpcy5faGlzdG9yeVN0YXRlID0gc3RhdGU7IC8vIHVzZWQgZm9yIHdlYmtpdCB3b3JrYXJvdW5kCgogICAgICB0aGlzLl9wcmV2aW91c1VSTCA9IHRoaXMuZ2V0VVJMKCk7CiAgICB9CiAgICAvKioKICAgICBSZXBsYWNlcyB0aGUgY3VycmVudCBzdGF0ZS4KICAgICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2QgcmVwbGFjZVN0YXRlCiAgICAgQHBhcmFtIHBhdGgge1N0cmluZ30KICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlcGxhY2VTdGF0ZSA9IGZ1bmN0aW9uIHJlcGxhY2VTdGF0ZShwYXRoKSB7CiAgICAgIHZhciBzdGF0ZSA9IHsKICAgICAgICBwYXRoOiBwYXRoLAogICAgICAgIHV1aWQ6IF91dWlkKCkKICAgICAgfTsKICAgICAgdGhpcy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShzdGF0ZSwgbnVsbCwgcGF0aCk7CiAgICAgIHRoaXMuX2hpc3RvcnlTdGF0ZSA9IHN0YXRlOyAvLyB1c2VkIGZvciB3ZWJraXQgd29ya2Fyb3VuZAoKICAgICAgdGhpcy5fcHJldmlvdXNVUkwgPSB0aGlzLmdldFVSTCgpOwogICAgfQogICAgLyoqCiAgICAgIFJlZ2lzdGVyIGEgY2FsbGJhY2sgdG8gYmUgaW52b2tlZCB3aGVuZXZlciB0aGUgYnJvd3NlcgogICAgICBoaXN0b3J5IGNoYW5nZXMsIGluY2x1ZGluZyB1c2luZyBmb3J3YXJkIGFuZCBiYWNrIGJ1dHRvbnMuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2Qgb25VcGRhdGVVUkwKICAgICAgQHBhcmFtIGNhbGxiYWNrIHtGdW5jdGlvbn0KICAgICovCiAgICA7CgogICAgX3Byb3RvLm9uVXBkYXRlVVJMID0gZnVuY3Rpb24gb25VcGRhdGVVUkwoY2FsbGJhY2spIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICB0aGlzLl9yZW1vdmVFdmVudExpc3RlbmVyKCk7CgogICAgICB0aGlzLl9wb3BzdGF0ZUhhbmRsZXIgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgLy8gSWdub3JlIGluaXRpYWwgcGFnZSBsb2FkIHBvcHN0YXRlIGV2ZW50IGluIENocm9tZQogICAgICAgIGlmICghcG9wc3RhdGVGaXJlZCkgewogICAgICAgICAgcG9wc3RhdGVGaXJlZCA9IHRydWU7CgogICAgICAgICAgaWYgKF90aGlzMi5nZXRVUkwoKSA9PT0gX3RoaXMyLl9wcmV2aW91c1VSTCkgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBjYWxsYmFjayhfdGhpczIuZ2V0VVJMKCkpOwogICAgICB9OwoKICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgdGhpcy5fcG9wc3RhdGVIYW5kbGVyKTsKICAgIH0KICAgIC8qKgogICAgICBVc2VkIHdoZW4gdXNpbmcgYHt7YWN0aW9ufX1gIGhlbHBlci4gIFRoZSB1cmwgaXMgYWx3YXlzIGFwcGVuZGVkIHRvIHRoZSByb290VVJMLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGZvcm1hdFVSTAogICAgICBAcGFyYW0gdXJsIHtTdHJpbmd9CiAgICAgIEByZXR1cm4gZm9ybWF0dGVkIHVybCB7U3RyaW5nfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZm9ybWF0VVJMID0gZnVuY3Rpb24gZm9ybWF0VVJMKHVybCkgewogICAgICB2YXIgcm9vdFVSTCA9IHRoaXMucm9vdFVSTCwKICAgICAgICAgIGJhc2VVUkwgPSB0aGlzLmJhc2VVUkw7CgogICAgICBpZiAodXJsICE9PSAnJykgewogICAgICAgIC8vIHJlbW92ZSB0cmFpbGluZyBzbGFzaGVzIGlmIHRoZXkgZXhpc3RzCiAgICAgICAgcm9vdFVSTCA9IHJvb3RVUkwucmVwbGFjZSgvXC8kLywgJycpOwogICAgICAgIGJhc2VVUkwgPSBiYXNlVVJMLnJlcGxhY2UoL1wvJC8sICcnKTsKICAgICAgfSBlbHNlIGlmIChiYXNlVVJMWzBdID09PSAnLycgJiYgcm9vdFVSTFswXSA9PT0gJy8nKSB7CiAgICAgICAgLy8gaWYgYmFzZVVSTCBhbmQgcm9vdFVSTCBib3RoIHN0YXJ0IHdpdGggYSBzbGFzaAogICAgICAgIC8vIC4uLiByZW1vdmUgdHJhaWxpbmcgc2xhc2ggZnJvbSBiYXNlVVJMIGlmIGl0IGV4aXN0cwogICAgICAgIGJhc2VVUkwgPSBiYXNlVVJMLnJlcGxhY2UoL1wvJC8sICcnKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGJhc2VVUkwgKyByb290VVJMICsgdXJsOwogICAgfQogICAgLyoqCiAgICAgIENsZWFucyB1cCB0aGUgSGlzdG9yeUxvY2F0aW9uIGV2ZW50IGxpc3RlbmVyLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHdpbGxEZXN0cm95CiAgICAqLwogICAgOwoKICAgIF9wcm90by53aWxsRGVzdHJveSA9IGZ1bmN0aW9uIHdpbGxEZXN0cm95KCkgewogICAgICB0aGlzLl9yZW1vdmVFdmVudExpc3RlbmVyKCk7CiAgICB9OwoKICAgIF9wcm90by5fcmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIF9yZW1vdmVFdmVudExpc3RlbmVyKCkgewogICAgICBpZiAodGhpcy5fcG9wc3RhdGVIYW5kbGVyKSB7CiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgdGhpcy5fcG9wc3RhdGVIYW5kbGVyKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gSGlzdG9yeUxvY2F0aW9uOwogIH0oX3J1bnRpbWUuT2JqZWN0KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IEhpc3RvcnlMb2NhdGlvbjsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvbG9jYXRpb24vbm9uZV9sb2NhdGlvbiIsIFsiZXhwb3J0cyIsICJlbWJlci1iYWJlbCIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIiwgIkBlbWJlci9kZWJ1ZyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfbWV0YWwsIF9ydW50aW1lLCBfZGVidWcpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgQGVtYmVyL3JvdXRpbmcKICAqLwoKICAvKioKICAgIE5vbmVMb2NhdGlvbiBkb2VzIG5vdCBpbnRlcmFjdCB3aXRoIHRoZSBicm93c2VyLiBJdCBpcyB1c2VmdWwgZm9yCiAgICB0ZXN0aW5nLCBvciB3aGVuIHlvdSBuZWVkIHRvIG1hbmFnZSBzdGF0ZSB3aXRoIHlvdXIgUm91dGVyLCBidXQgdGVtcG9yYXJpbHkKICAgIGRvbid0IHdhbnQgaXQgdG8gbXVjayB3aXRoIHRoZSBVUkwgKGZvciBleGFtcGxlIHdoZW4geW91IGVtYmVkIHlvdXIKICAgIGFwcGxpY2F0aW9uIGluIGEgbGFyZ2VyIHBhZ2UpLgogIAogICAgVXNpbmcgYE5vbmVMb2NhdGlvbmAgY2F1c2VzIEVtYmVyIHRvIG5vdCBzdG9yZSB0aGUgYXBwbGljYXRpb25zIFVSTCBzdGF0ZQogICAgaW4gdGhlIGFjdHVhbCBVUkwuIFRoaXMgaXMgZ2VuZXJhbGx5IHVzZWQgZm9yIHRlc3RpbmcgcHVycG9zZXMsIGFuZCBpcyBvbmUKICAgIG9mIHRoZSBjaGFuZ2VzIG1hZGUgd2hlbiBjYWxsaW5nIGBBcHAuc2V0dXBGb3JUZXN0aW5nKClgLgogIAogICAgQGNsYXNzIE5vbmVMb2NhdGlvbgogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAgIEBwcm90ZWN0ZWQKICAqLwogIHZhciBOb25lTG9jYXRpb24gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0VtYmVyT2JqZWN0KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTm9uZUxvY2F0aW9uLCBfRW1iZXJPYmplY3QpOwoKICAgIGZ1bmN0aW9uIE5vbmVMb2NhdGlvbigpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfRW1iZXJPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpcy5pbXBsZW1lbnRhdGlvbiA9ICdub25lJzsKICAgICAgcmV0dXJuIF90aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBOb25lTG9jYXRpb24ucHJvdG90eXBlOwoKICAgIF9wcm90by5kZXRlY3QgPSBmdW5jdGlvbiBkZXRlY3QoKSB7CiAgICAgIHZhciByb290VVJMID0gdGhpcy5yb290VVJMOwogICAgICAoZmFsc2UgJiYgIShyb290VVJMLmNoYXJBdChyb290VVJMLmxlbmd0aCAtIDEpID09PSAnLycpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgncm9vdFVSTCBtdXN0IGVuZCB3aXRoIGEgdHJhaWxpbmcgZm9yd2FyZCBzbGFzaCBlLmcuICIvYXBwLyInLCByb290VVJMLmNoYXJBdChyb290VVJMLmxlbmd0aCAtIDEpID09PSAnLycpKTsKICAgIH0KICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSBjdXJyZW50IHBhdGggd2l0aG91dCBgcm9vdFVSTGAuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZ2V0VVJMCiAgICAgIEByZXR1cm4ge1N0cmluZ30gcGF0aAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZ2V0VVJMID0gZnVuY3Rpb24gZ2V0VVJMKCkgewogICAgICB2YXIgcGF0aCA9IHRoaXMucGF0aCwKICAgICAgICAgIHJvb3RVUkwgPSB0aGlzLnJvb3RVUkw7IC8vIHJlbW92ZSB0cmFpbGluZyBzbGFzaGVzIGlmIHRoZXkgZXhpc3RzCgogICAgICByb290VVJMID0gcm9vdFVSTC5yZXBsYWNlKC9cLyQvLCAnJyk7IC8vIHJlbW92ZSByb290VVJMIGZyb20gdXJsCgogICAgICByZXR1cm4gcGF0aC5yZXBsYWNlKG5ldyBSZWdFeHAoIl4iICsgcm9vdFVSTCArICIoPz0vfCQpIiksICcnKTsKICAgIH0KICAgIC8qKgogICAgICBTZXQgdGhlIHBhdGggYW5kIHJlbWVtYmVycyB3aGF0IHdhcyBzZXQuIFVzaW5nIHRoaXMgbWV0aG9kCiAgICAgIHRvIGNoYW5nZSB0aGUgcGF0aCB3aWxsIG5vdCBpbnZva2UgdGhlIGB1cGRhdGVVUkxgIGNhbGxiYWNrLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHNldFVSTAogICAgICBAcGFyYW0gcGF0aCB7U3RyaW5nfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uc2V0VVJMID0gZnVuY3Rpb24gc2V0VVJMKHBhdGgpIHsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRoaXMsICdwYXRoJywgcGF0aCk7CiAgICB9CiAgICAvKioKICAgICAgUmVnaXN0ZXIgYSBjYWxsYmFjayB0byBiZSBpbnZva2VkIHdoZW4gdGhlIHBhdGggY2hhbmdlcy4gVGhlc2UKICAgICAgY2FsbGJhY2tzIHdpbGwgZXhlY3V0ZSB3aGVuIHRoZSB1c2VyIHByZXNzZXMgdGhlIGJhY2sgb3IgZm9yd2FyZAogICAgICBidXR0b24sIGJ1dCBub3QgYWZ0ZXIgYHNldFVSTGAgaXMgaW52b2tlZC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBvblVwZGF0ZVVSTAogICAgICBAcGFyYW0gY2FsbGJhY2sge0Z1bmN0aW9ufQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ub25VcGRhdGVVUkwgPSBmdW5jdGlvbiBvblVwZGF0ZVVSTChjYWxsYmFjaykgewogICAgICB0aGlzLnVwZGF0ZUNhbGxiYWNrID0gY2FsbGJhY2s7CiAgICB9CiAgICAvKioKICAgICAgU2V0cyB0aGUgcGF0aCBhbmQgY2FsbHMgdGhlIGB1cGRhdGVVUkxgIGNhbGxiYWNrLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGhhbmRsZVVSTAogICAgICBAcGFyYW0gdXJsIHtTdHJpbmd9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5oYW5kbGVVUkwgPSBmdW5jdGlvbiBoYW5kbGVVUkwodXJsKSB7CiAgICAgICgwLCBfbWV0YWwuc2V0KSh0aGlzLCAncGF0aCcsIHVybCk7CiAgICAgIHRoaXMudXBkYXRlQ2FsbGJhY2sodXJsKTsKICAgIH0KICAgIC8qKgogICAgICBHaXZlbiBhIFVSTCwgZm9ybWF0cyBpdCB0byBiZSBwbGFjZWQgaW50byB0aGUgcGFnZSBhcyBwYXJ0CiAgICAgIG9mIGFuIGVsZW1lbnQncyBgaHJlZmAgYXR0cmlidXRlLgogICAgICAgICBUaGlzIGlzIHVzZWQsIGZvciBleGFtcGxlLCB3aGVuIHVzaW5nIHRoZSB7e2FjdGlvbn19IGhlbHBlcgogICAgICB0byBnZW5lcmF0ZSBhIFVSTCBiYXNlZCBvbiBhbiBldmVudC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBmb3JtYXRVUkwKICAgICAgQHBhcmFtIHVybCB7U3RyaW5nfQogICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZm9ybWF0VVJMID0gZnVuY3Rpb24gZm9ybWF0VVJMKHVybCkgewogICAgICB2YXIgcm9vdFVSTCA9IHRoaXMucm9vdFVSTDsKCiAgICAgIGlmICh1cmwgIT09ICcnKSB7CiAgICAgICAgLy8gcmVtb3ZlIHRyYWlsaW5nIHNsYXNoZXMgaWYgdGhleSBleGlzdHMKICAgICAgICByb290VVJMID0gcm9vdFVSTC5yZXBsYWNlKC9cLyQvLCAnJyk7CiAgICAgIH0KCiAgICAgIHJldHVybiByb290VVJMICsgdXJsOwogICAgfTsKCiAgICByZXR1cm4gTm9uZUxvY2F0aW9uOwogIH0oX3J1bnRpbWUuT2JqZWN0KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IE5vbmVMb2NhdGlvbjsKICBOb25lTG9jYXRpb24ucmVvcGVuKHsKICAgIHBhdGg6ICcnLAoKICAgIC8qKgogICAgICBXaWxsIGJlIHByZS1wZW5kZWQgdG8gcGF0aC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQHByb3BlcnR5IHJvb3RVUkwKICAgICAgQGRlZmF1bHQgJy8nCiAgICAqLwogICAgcm9vdFVSTDogJy8nCiAgfSk7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL3V0aWwiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5nZXRQYXRoID0gZ2V0UGF0aDsKICBfZXhwb3J0cy5nZXRRdWVyeSA9IGdldFF1ZXJ5OwogIF9leHBvcnRzLmdldEhhc2ggPSBnZXRIYXNoOwogIF9leHBvcnRzLmdldEZ1bGxQYXRoID0gZ2V0RnVsbFBhdGg7CiAgX2V4cG9ydHMuZ2V0T3JpZ2luID0gZ2V0T3JpZ2luOwogIF9leHBvcnRzLnN1cHBvcnRzSGFzaENoYW5nZSA9IHN1cHBvcnRzSGFzaENoYW5nZTsKICBfZXhwb3J0cy5zdXBwb3J0c0hpc3RvcnkgPSBzdXBwb3J0c0hpc3Rvcnk7CiAgX2V4cG9ydHMucmVwbGFjZVBhdGggPSByZXBsYWNlUGF0aDsKCiAgLyoqCiAgICBAcHJpdmF0ZQogIAogICAgUmV0dXJucyB0aGUgY3VycmVudCBgbG9jYXRpb24ucGF0aG5hbWVgLCBub3JtYWxpemVkIGZvciBJRSBpbmNvbnNpc3RlbmNpZXMuCiAgKi8KICBmdW5jdGlvbiBnZXRQYXRoKGxvY2F0aW9uKSB7CiAgICB2YXIgcGF0aG5hbWUgPSBsb2NhdGlvbi5wYXRobmFtZTsgLy8gVmFyaW91cyB2ZXJzaW9ucyBvZiBJRS9PcGVyYSBkb24ndCBhbHdheXMgcmV0dXJuIGEgbGVhZGluZyBzbGFzaAoKICAgIGlmIChwYXRobmFtZVswXSAhPT0gJy8nKSB7CiAgICAgIHBhdGhuYW1lID0gIi8iICsgcGF0aG5hbWU7CiAgICB9CgogICAgcmV0dXJuIHBhdGhuYW1lOwogIH0KICAvKioKICAgIEBwcml2YXRlCiAgCiAgICBSZXR1cm5zIHRoZSBjdXJyZW50IGBsb2NhdGlvbi5zZWFyY2hgLgogICovCgoKICBmdW5jdGlvbiBnZXRRdWVyeShsb2NhdGlvbikgewogICAgcmV0dXJuIGxvY2F0aW9uLnNlYXJjaDsKICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogIAogICAgUmV0dXJucyB0aGUgaGFzaCBvciBlbXB0eSBzdHJpbmcKICAqLwoKCiAgZnVuY3Rpb24gZ2V0SGFzaChsb2NhdGlvbikgewogICAgaWYgKGxvY2F0aW9uLmhhc2ggIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gbG9jYXRpb24uaGFzaC5zdWJzdHIoMCk7CiAgICB9CgogICAgcmV0dXJuICcnOwogIH0KCiAgZnVuY3Rpb24gZ2V0RnVsbFBhdGgobG9jYXRpb24pIHsKICAgIHJldHVybiBnZXRQYXRoKGxvY2F0aW9uKSArIGdldFF1ZXJ5KGxvY2F0aW9uKSArIGdldEhhc2gobG9jYXRpb24pOwogIH0KCiAgZnVuY3Rpb24gZ2V0T3JpZ2luKGxvY2F0aW9uKSB7CiAgICB2YXIgb3JpZ2luID0gbG9jYXRpb24ub3JpZ2luOyAvLyBPbGRlciBicm93c2VycywgZXNwZWNpYWxseSBJRSwgZG9uJ3QgaGF2ZSBvcmlnaW4KCiAgICBpZiAoIW9yaWdpbikgewogICAgICBvcmlnaW4gPSBsb2NhdGlvbi5wcm90b2NvbCArICIvLyIgKyBsb2NhdGlvbi5ob3N0bmFtZTsKCiAgICAgIGlmIChsb2NhdGlvbi5wb3J0KSB7CiAgICAgICAgb3JpZ2luICs9ICI6IiArIGxvY2F0aW9uLnBvcnQ7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gb3JpZ2luOwogIH0KICAvKgogICAgYGRvY3VtZW50TW9kZWAgb25seSBleGlzdCBpbiBJbnRlcm5ldCBFeHBsb3JlciwgYW5kIGl0J3MgdGVzdGVkIGJlY2F1c2UgSUU4IHJ1bm5pbmcgaW4KICAgIElFNyBjb21wYXRpYmlsaXR5IG1vZGUgY2xhaW1zIHRvIHN1cHBvcnQgYG9uaGFzaGNoYW5nZWAgYnV0IGFjdHVhbGx5IGRvZXMgbm90LgogIAogICAgYGdsb2JhbGAgaXMgYW4gb2JqZWN0IHRoYXQgbWF5IGhhdmUgYW4gYG9uaGFzaGNoYW5nZWAgcHJvcGVydHkuCiAgCiAgICBAcHJpdmF0ZQogICAgQGZ1bmN0aW9uIHN1cHBvcnRzSGFzaENoYW5nZQogICovCgoKICBmdW5jdGlvbiBzdXBwb3J0c0hhc2hDaGFuZ2UoZG9jdW1lbnRNb2RlLCBnbG9iYWwpIHsKICAgIHJldHVybiBnbG9iYWwgJiYgJ29uaGFzaGNoYW5nZScgaW4gZ2xvYmFsICYmIChkb2N1bWVudE1vZGUgPT09IHVuZGVmaW5lZCB8fCBkb2N1bWVudE1vZGUgPiA3KTsKICB9CiAgLyoKICAgIGB1c2VyQWdlbnRgIGlzIGEgdXNlciBhZ2VudCBzdHJpbmcuIFdlIHVzZSB1c2VyIGFnZW50IHRlc3RpbmcgaGVyZSwgYmVjYXVzZQogICAgdGhlIHN0b2NrIEFuZHJvaWQgYnJvd3NlciBpcyBrbm93biB0byBoYXZlIGJ1Z2d5IHZlcnNpb25zIG9mIHRoZSBIaXN0b3J5IEFQSSwKICAgIGluIHNvbWUgQW5kcm9pZCB2ZXJzaW9ucy4KICAKICAgIEBwcml2YXRlCiAgICBAZnVuY3Rpb24gc3VwcG9ydHNIaXN0b3J5CiAgKi8KCgogIGZ1bmN0aW9uIHN1cHBvcnRzSGlzdG9yeSh1c2VyQWdlbnQsIGhpc3RvcnkpIHsKICAgIC8vIEJvb3N0ZWQgZnJvbSBNb2Rlcm5penI6IGh0dHBzOi8vZ2l0aHViLmNvbS9Nb2Rlcm5penIvTW9kZXJuaXpyL2Jsb2IvbWFzdGVyL2ZlYXR1cmUtZGV0ZWN0cy9oaXN0b3J5LmpzCiAgICAvLyBUaGUgc3RvY2sgYnJvd3NlciBvbiBBbmRyb2lkIDIuMiAmIDIuMywgYW5kIDQuMC54IHJldHVybnMgcG9zaXRpdmUgb24gaGlzdG9yeSBzdXBwb3J0CiAgICAvLyBVbmZvcnR1bmF0ZWx5IHN1cHBvcnQgaXMgcmVhbGx5IGJ1Z2d5IGFuZCB0aGVyZSBpcyBubyBjbGVhbiB3YXkgdG8gZGV0ZWN0CiAgICAvLyB0aGVzZSBidWdzLCBzbyB3ZSBmYWxsIGJhY2sgdG8gYSB1c2VyIGFnZW50IHNuaWZmIDooCiAgICAvLyBXZSBvbmx5IHdhbnQgQW5kcm9pZCAyIGFuZCA0LjAsIHN0b2NrIGJyb3dzZXIsIGFuZCBub3QgQ2hyb21lIHdoaWNoIGlkZW50aWZpZXMKICAgIC8vIGl0c2VsZiBhcyAnTW9iaWxlIFNhZmFyaScgYXMgd2VsbCwgbm9yIFdpbmRvd3MgUGhvbmUuCiAgICBpZiAoKHVzZXJBZ2VudC5pbmRleE9mKCdBbmRyb2lkIDIuJykgIT09IC0xIHx8IHVzZXJBZ2VudC5pbmRleE9mKCdBbmRyb2lkIDQuMCcpICE9PSAtMSkgJiYgdXNlckFnZW50LmluZGV4T2YoJ01vYmlsZSBTYWZhcmknKSAhPT0gLTEgJiYgdXNlckFnZW50LmluZGV4T2YoJ0Nocm9tZScpID09PSAtMSAmJiB1c2VyQWdlbnQuaW5kZXhPZignV2luZG93cyBQaG9uZScpID09PSAtMSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgcmV0dXJuIEJvb2xlYW4oaGlzdG9yeSAmJiAncHVzaFN0YXRlJyBpbiBoaXN0b3J5KTsKICB9CiAgLyoqCiAgICBSZXBsYWNlcyB0aGUgY3VycmVudCBsb2NhdGlvbiwgbWFraW5nIHN1cmUgd2UgZXhwbGljaXRseSBpbmNsdWRlIHRoZSBvcmlnaW4KICAgIHRvIHByZXZlbnQgcmVkaXJlY3RpbmcgdG8gYSBkaWZmZXJlbnQgb3JpZ2luLgogIAogICAgQHByaXZhdGUKICAqLwoKCiAgZnVuY3Rpb24gcmVwbGFjZVBhdGgobG9jYXRpb24sIHBhdGgpIHsKICAgIGxvY2F0aW9uLnJlcGxhY2UoZ2V0T3JpZ2luKGxvY2F0aW9uKSArIHBhdGgpOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc2VydmljZXMvcm91dGVyIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci9vYmplY3QvY29tcHV0ZWQiLCAiQGVtYmVyL3NlcnZpY2UiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvdXRpbHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX3J1bnRpbWUsIF9kZWJ1ZywgX2NvbXB1dGVkLCBfc2VydmljZSwgX3V0aWxzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwogIHZhciBmcmVlemVSb3V0ZUluZm87CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICBmcmVlemVSb3V0ZUluZm8gPSBmdW5jdGlvbiBmcmVlemVSb3V0ZUluZm8odHJhbnNpdGlvbikgewogICAgICBpZiAodHJhbnNpdGlvbi5mcm9tICE9PSBudWxsICYmICFPYmplY3QuaXNGcm96ZW4odHJhbnNpdGlvbi5mcm9tKSkgewogICAgICAgIE9iamVjdC5mcmVlemUodHJhbnNpdGlvbi5mcm9tKTsKICAgICAgfQoKICAgICAgaWYgKHRyYW5zaXRpb24udG8gIT09IG51bGwgJiYgIU9iamVjdC5pc0Zyb3plbih0cmFuc2l0aW9uLnRvKSkgewogICAgICAgIE9iamVjdC5mcmVlemUodHJhbnNpdGlvbi50byk7CiAgICAgIH0KICAgIH07CiAgfQoKICBmdW5jdGlvbiBjbGVhblVSTCh1cmwsIHJvb3RVUkwpIHsKICAgIGlmIChyb290VVJMID09PSAnLycpIHsKICAgICAgcmV0dXJuIHVybDsKICAgIH0KCiAgICByZXR1cm4gdXJsLnN1YnN0cihyb290VVJMLmxlbmd0aCwgdXJsLmxlbmd0aCk7CiAgfQogIC8qKgogICAgIFRoZSBSb3V0ZXIgc2VydmljZSBpcyB0aGUgcHVibGljIEFQSSB0aGF0IHByb3ZpZGVzIGFjY2VzcyB0byB0aGUgcm91dGVyLgogIAogICAgIFRoZSBpbW1lZGlhdGUgYmVuZWZpdCBvZiB0aGUgUm91dGVyIHNlcnZpY2UgaXMgdGhhdCB5b3UgY2FuIGluamVjdCBpdCBpbnRvIGNvbXBvbmVudHMsCiAgICAgZ2l2aW5nIHRoZW0gYSBmcmllbmRseSB3YXkgdG8gaW5pdGlhdGUgdHJhbnNpdGlvbnMgYW5kIGFzayBxdWVzdGlvbnMgYWJvdXQgdGhlIGN1cnJlbnQKICAgICBnbG9iYWwgcm91dGVyIHN0YXRlLgogIAogICAgIEluIHRoaXMgZXhhbXBsZSwgdGhlIFJvdXRlciBzZXJ2aWNlIGlzIGluamVjdGVkIGludG8gYSBjb21wb25lbnQgdG8gaW5pdGlhdGUgYSB0cmFuc2l0aW9uCiAgICAgdG8gYSBkZWRpY2F0ZWQgcm91dGU6CiAgICAgYGBgamF2YXNjcmlwdAogICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgaW1wb3J0IHsgaW5qZWN0IGFzIHNlcnZpY2UgfSBmcm9tICdAZW1iZXIvc2VydmljZSc7CiAgCiAgICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICByb3V0ZXI6IHNlcnZpY2UoKSwKICAKICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgbmV4dCgpIHsKICAgICAgICAgICB0aGlzLnJvdXRlci50cmFuc2l0aW9uVG8oJ290aGVyLnJvdXRlJyk7CiAgICAgICAgIH0KICAgICAgIH0KICAgICB9KTsKICAgICBgYGAKICAKICAgICBMaWtlIGFueSBzZXJ2aWNlLCBpdCBjYW4gYWxzbyBiZSBpbmplY3RlZCBpbnRvIGhlbHBlcnMsIHJvdXRlcywgZXRjLgogIAogICAgIEBwdWJsaWMKICAgICBAZXh0ZW5kcyBTZXJ2aWNlCiAgICAgQGNsYXNzIFJvdXRlclNlcnZpY2UKICAgKi8KCgogIHZhciBSb3V0ZXJTZXJ2aWNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9TZXJ2aWNlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUm91dGVyU2VydmljZSwgX1NlcnZpY2UpOwoKICAgIGZ1bmN0aW9uIFJvdXRlclNlcnZpY2UoKSB7CiAgICAgIHJldHVybiBfU2VydmljZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90byA9IFJvdXRlclNlcnZpY2UucHJvdG90eXBlOwoKICAgIF9wcm90by5pbml0ID0gZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIF9TZXJ2aWNlLnByb3RvdHlwZS5pbml0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzLl9yb3V0ZXIub24oJ3JvdXRlV2lsbENoYW5nZScsIGZ1bmN0aW9uICh0cmFuc2l0aW9uKSB7CiAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgLyogREVCVUcgKi8KICAgICAgICApIHsKICAgICAgICAgIGZyZWV6ZVJvdXRlSW5mbyh0cmFuc2l0aW9uKTsKICAgICAgICB9CgogICAgICAgIF90aGlzLnRyaWdnZXIoJ3JvdXRlV2lsbENoYW5nZScsIHRyYW5zaXRpb24pOwogICAgICB9KTsKCiAgICAgIHRoaXMuX3JvdXRlci5vbigncm91dGVEaWRDaGFuZ2UnLCBmdW5jdGlvbiAodHJhbnNpdGlvbikgewogICAgICAgIGlmIChmYWxzZQogICAgICAgIC8qIERFQlVHICovCiAgICAgICAgKSB7CiAgICAgICAgICBmcmVlemVSb3V0ZUluZm8odHJhbnNpdGlvbik7CiAgICAgICAgfQoKICAgICAgICBfdGhpcy50cmlnZ2VyKCdyb3V0ZURpZENoYW5nZScsIHRyYW5zaXRpb24pOwogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICAgVHJhbnNpdGlvbiB0aGUgYXBwbGljYXRpb24gaW50byBhbm90aGVyIHJvdXRlLiBUaGUgcm91dGUgbWF5CiAgICAgICBiZSBlaXRoZXIgYSBzaW5nbGUgcm91dGUgb3Igcm91dGUgcGF0aDoKICAgICAgICAgIFNlZSBbdHJhbnNpdGlvblRvXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1JvdXRlL21ldGhvZHMvdHJhbnNpdGlvblRvP2FuY2hvcj10cmFuc2l0aW9uVG8pIGZvciBtb3JlIGluZm8uCiAgICAgICAgICBDYWxsaW5nIGB0cmFuc2l0aW9uVG9gIGZyb20gdGhlIFJvdXRlciBzZXJ2aWNlIHdpbGwgY2F1c2UgZGVmYXVsdCBxdWVyeSBwYXJhbWV0ZXIgdmFsdWVzIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBVUkwuCiAgICAgICBUaGlzIGJlaGF2aW9yIGlzIGRpZmZlcmVudCBmcm9tIGNhbGxpbmcgYHRyYW5zaXRpb25Ub2Agb24gYSByb3V0ZSBvciBgdHJhbnNpdGlvblRvUm91dGVgIG9uIGEgY29udHJvbGxlci4KICAgICAgIFNlZSB0aGUgW1JvdXRlciBTZXJ2aWNlIFJGQ10oaHR0cHM6Ly9naXRodWIuY29tL2VtYmVyanMvcmZjcy9ibG9iL21hc3Rlci90ZXh0LzAwOTUtcm91dGVyLXNlcnZpY2UubWQjcXVlcnktcGFyYW1ldGVyLXNlbWFudGljcykgZm9yIG1vcmUgaW5mby4KICAgICAgICAgIEluIHRoZSBmb2xsb3dpbmcgZXhhbXBsZSB3ZSB1c2UgdGhlIFJvdXRlciBzZXJ2aWNlIHRvIG5hdmlnYXRlIHRvIGEgcm91dGUgd2l0aCBhCiAgICAgICBzcGVjaWZpYyBtb2RlbCBmcm9tIGEgQ29tcG9uZW50LgogICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgIGltcG9ydCB7IGluamVjdCBhcyBzZXJ2aWNlIH0gZnJvbSAnQGVtYmVyL3NlcnZpY2UnOwogICAgICAgICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgIHJvdXRlcjogc2VydmljZSgpLAogICAgICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICAgZ29Ub0NvbW1lbnRzKHBvc3QpIHsKICAgICAgICAgICAgIHRoaXMucm91dGVyLnRyYW5zaXRpb25UbygnY29tbWVudHMnLCBwb3N0KTsKICAgICAgICAgICB9CiAgICAgICAgIH0KICAgICAgIH0pOwogICAgICAgYGBgCiAgICAgICAgICBAbWV0aG9kIHRyYW5zaXRpb25UbwogICAgICAgQHBhcmFtIHtTdHJpbmd9IHJvdXRlTmFtZU9yVXJsIHRoZSBuYW1lIG9mIHRoZSByb3V0ZSBvciBhIFVSTAogICAgICAgQHBhcmFtIHsuLi5PYmplY3R9IG1vZGVscyB0aGUgbW9kZWwocykgb3IgaWRlbnRpZmllcihzKSB0byBiZSB1c2VkIHdoaWxlCiAgICAgICAgIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBvcHRpb25hbCBoYXNoIHdpdGggYSBxdWVyeVBhcmFtcyBwcm9wZXJ0eQogICAgICAgICBjb250YWluaW5nIGEgbWFwcGluZyBvZiBxdWVyeSBwYXJhbWV0ZXJzCiAgICAgICBAcmV0dXJuIHtUcmFuc2l0aW9ufSB0aGUgdHJhbnNpdGlvbiBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoaXMKICAgICAgICAgYXR0ZW1wdGVkIHRyYW5zaXRpb24KICAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by50cmFuc2l0aW9uVG8gPSBmdW5jdGlvbiB0cmFuc2l0aW9uVG8oKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgIGlmICgoMCwgX3V0aWxzLnJlc2VtYmxlc1VSTCkoYXJnc1swXSkpIHsKICAgICAgICByZXR1cm4gdGhpcy5fcm91dGVyLl9kb1VSTFRyYW5zaXRpb24oJ3RyYW5zaXRpb25UbycsIGFyZ3NbMF0pOwogICAgICB9CgogICAgICB2YXIgX2V4dHJhY3RSb3V0ZUFyZ3MgPSAoMCwgX3V0aWxzLmV4dHJhY3RSb3V0ZUFyZ3MpKGFyZ3MpLAogICAgICAgICAgcm91dGVOYW1lID0gX2V4dHJhY3RSb3V0ZUFyZ3Mucm91dGVOYW1lLAogICAgICAgICAgbW9kZWxzID0gX2V4dHJhY3RSb3V0ZUFyZ3MubW9kZWxzLAogICAgICAgICAgcXVlcnlQYXJhbXMgPSBfZXh0cmFjdFJvdXRlQXJncy5xdWVyeVBhcmFtczsKCiAgICAgIHZhciB0cmFuc2l0aW9uID0gdGhpcy5fcm91dGVyLl9kb1RyYW5zaXRpb24ocm91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zLCB0cnVlKTsKCiAgICAgIHRyYW5zaXRpb25bJ19rZWVwRGVmYXVsdFF1ZXJ5UGFyYW1WYWx1ZXMnXSA9IHRydWU7CiAgICAgIHJldHVybiB0cmFuc2l0aW9uOwogICAgfQogICAgLyoqCiAgICAgICBUcmFuc2l0aW9uIGludG8gYW5vdGhlciByb3V0ZSB3aGlsZSByZXBsYWNpbmcgdGhlIGN1cnJlbnQgVVJMLCBpZiBwb3NzaWJsZS4KICAgICAgIFRoZSByb3V0ZSBtYXkgYmUgZWl0aGVyIGEgc2luZ2xlIHJvdXRlIG9yIHJvdXRlIHBhdGg6CiAgICAgICAgICBTZWUgW3JlcGxhY2VXaXRoXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1JvdXRlL21ldGhvZHMvcmVwbGFjZVdpdGg/YW5jaG9yPXJlcGxhY2VXaXRoKSBmb3IgbW9yZSBpbmZvLgogICAgICAgICAgQ2FsbGluZyBgcmVwbGFjZVdpdGhgIGZyb20gdGhlIFJvdXRlciBzZXJ2aWNlIHdpbGwgY2F1c2UgZGVmYXVsdCBxdWVyeSBwYXJhbWV0ZXIgdmFsdWVzIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBVUkwuCiAgICAgICBUaGlzIGJlaGF2aW9yIGlzIGRpZmZlcmVudCBmcm9tIGNhbGxpbmcgYHJlcGxhY2VXaXRoYCBvbiBhIHJvdXRlLgogICAgICAgU2VlIHRoZSBbUm91dGVyIFNlcnZpY2UgUkZDXShodHRwczovL2dpdGh1Yi5jb20vZW1iZXJqcy9yZmNzL2Jsb2IvbWFzdGVyL3RleHQvMDA5NS1yb3V0ZXItc2VydmljZS5tZCNxdWVyeS1wYXJhbWV0ZXItc2VtYW50aWNzKSBmb3IgbW9yZSBpbmZvLgogICAgICAgICAgVXNhZ2UgZXhhbXBsZToKICAgICAgICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgICBiZWZvcmVNb2RlbCgpIHsKICAgICAgICAgICBpZiAoIWF1dGhvcml6ZWQoKSl7CiAgICAgICAgICAgICB0aGlzLnJlcGxhY2VXaXRoKCd1bmF1dGhvcml6ZWQnKTsKICAgICAgICAgICB9CiAgICAgICAgIH0KICAgICAgIH0pOwogICAgICAgYGBgCiAgICAgICAgICBAbWV0aG9kIHJlcGxhY2VXaXRoCiAgICAgICBAcGFyYW0ge1N0cmluZ30gcm91dGVOYW1lT3JVcmwgdGhlIG5hbWUgb2YgdGhlIHJvdXRlIG9yIGEgVVJMCiAgICAgICBAcGFyYW0gey4uLk9iamVjdH0gbW9kZWxzIHRoZSBtb2RlbChzKSBvciBpZGVudGlmaWVyKHMpIHRvIGJlIHVzZWQgd2hpbGUKICAgICAgICAgdHJhbnNpdGlvbmluZyB0byB0aGUgcm91dGUuCiAgICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIG9wdGlvbmFsIGhhc2ggd2l0aCBhIHF1ZXJ5UGFyYW1zIHByb3BlcnR5CiAgICAgICAgIGNvbnRhaW5pbmcgYSBtYXBwaW5nIG9mIHF1ZXJ5IHBhcmFtZXRlcnMKICAgICAgIEByZXR1cm4ge1RyYW5zaXRpb259IHRoZSB0cmFuc2l0aW9uIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhpcwogICAgICAgICBhdHRlbXB0ZWQgdHJhbnNpdGlvbgogICAgICAgQHB1YmxpYwogICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlcGxhY2VXaXRoID0gZnVuY3Rpb24gcmVwbGFjZVdpdGgoKQogICAgLyogcm91dGVOYW1lT3JVcmwsIC4uLm1vZGVscywgb3B0aW9ucyAqLwogICAgewogICAgICByZXR1cm4gdGhpcy50cmFuc2l0aW9uVG8uYXBwbHkodGhpcywgYXJndW1lbnRzKS5tZXRob2QoJ3JlcGxhY2UnKTsKICAgIH0KICAgIC8qKgogICAgICBHZW5lcmF0ZSBhIFVSTCBiYXNlZCBvbiB0aGUgc3VwcGxpZWQgcm91dGUgbmFtZSBhbmQgb3B0aW9uYWxseSBhIG1vZGVsLiBUaGUKICAgICAgVVJMIGlzIHJldHVybmVkIGFzIGEgc3RyaW5nIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGFueSBwdXJwb3NlLgogICAgICAgICBJbiB0aGlzIGV4YW1wbGUsIHRoZSBVUkwgZm9yIHRoZSBgYXV0aG9yLmJvb2tzYCByb3V0ZSBmb3IgYSBnaXZlbiBhdXRob3IKICAgICAgaXMgY29waWVkIHRvIHRoZSBjbGlwYm9hcmQuCiAgICAgICAgIGBgYGFwcC9jb21wb25lbnRzL2NvcHktbGluay5qcwogICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICBpbXBvcnQge2luamVjdCBhcyBzZXJ2aWNlfSBmcm9tICdAZW1iZXIvc2VydmljZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICAgIHJvdXRlcjogc2VydmljZSgncm91dGVyJyksCiAgICAgICAgY2xpcGJvYXJkOiBzZXJ2aWNlKCdjbGlwYm9hcmQnKQogICAgICAgICAgIC8vIFByb3ZpZGVkIGluIHRoZSB0ZW1wbGF0ZQogICAgICAgIC8vIHsgaWQ6ICd0b21zdGVyJywgbmFtZTogJ1RvbXN0ZXInIH0KICAgICAgICBhdXRob3I6IG51bGwsCiAgICAgICAgICAgY29weUJvb2tzVVJMKCkgewogICAgICAgICAgaWYgKHRoaXMuYXV0aG9yKSB7CiAgICAgICAgICAgIGNvbnN0IHVybCA9IHRoaXMucm91dGVyLnVybEZvcignYXV0aG9yLmJvb2tzJywgdGhpcy5hdXRob3IpOwogICAgICAgICAgICB0aGlzLmNsaXBib2FyZC5zZXQodXJsKTsKICAgICAgICAgICAgLy8gQ2xpcGJvYXJkIG5vdyBoYXMgL2F1dGhvci90b21zdGVyL2Jvb2tzCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIEp1c3QgbGlrZSB3aXRoIGB0cmFuc2l0aW9uVG9gIGFuZCBgcmVwbGFjZVdpdGhgLCBgdXJsRm9yYCBjYW4gYWxzbyBoYW5kbGUKICAgICAgcXVlcnkgcGFyYW1ldGVycy4KICAgICAgICAgYGBgYXBwL2NvbXBvbmVudHMvY29weS1saW5rLmpzCiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIGltcG9ydCB7aW5qZWN0IGFzIHNlcnZpY2V9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgcm91dGVyOiBzZXJ2aWNlKCdyb3V0ZXInKSwKICAgICAgICBjbGlwYm9hcmQ6IHNlcnZpY2UoJ2NsaXBib2FyZCcpCiAgICAgICAgICAgLy8gUHJvdmlkZWQgaW4gdGhlIHRlbXBsYXRlCiAgICAgICAgLy8geyBpZDogJ3RvbXN0ZXInLCBuYW1lOiAnVG9tc3RlcicgfQogICAgICAgIGF1dGhvcjogbnVsbCwKICAgICAgICAgICBjb3B5T25seUVtYmVyQm9va3NVUkwoKSB7CiAgICAgICAgICBpZiAodGhpcy5hdXRob3IpIHsKICAgICAgICAgICAgY29uc3QgdXJsID0gdGhpcy5yb3V0ZXIudXJsRm9yKCdhdXRob3IuYm9va3MnLCB0aGlzLmF1dGhvciwgewogICAgICAgICAgICAgIHF1ZXJ5UGFyYW1zOiB7IGZpbHRlcjogJ2VtYmVyanMnIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHRoaXMuY2xpcGJvYXJkLnNldCh1cmwpOwogICAgICAgICAgICAvLyBDbGlwYm9hcmQgbm93IGhhcyAvYXV0aG9yL3RvbXN0ZXIvYm9va3M/ZmlsdGVyPWVtYmVyanMKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgIEBtZXRob2QgdXJsRm9yCiAgICAgICBAcGFyYW0ge1N0cmluZ30gcm91dGVOYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZQogICAgICAgQHBhcmFtIHsuLi5PYmplY3R9IG1vZGVscyB0aGUgbW9kZWwocykgb3IgaWRlbnRpZmllcihzKSB0byBiZSB1c2VkIHdoaWxlCiAgICAgICAgIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBvcHRpb25hbCBoYXNoIHdpdGggYSBxdWVyeVBhcmFtcyBwcm9wZXJ0eQogICAgICAgICBjb250YWluaW5nIGEgbWFwcGluZyBvZiBxdWVyeSBwYXJhbWV0ZXJzCiAgICAgICBAcmV0dXJuIHtTdHJpbmd9IHRoZSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBnZW5lcmF0ZWQgVVJMCiAgICAgICBAcHVibGljCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8udXJsRm9yID0gZnVuY3Rpb24gdXJsRm9yKHJvdXRlTmFtZSkgewogICAgICB2YXIgX3RoaXMkX3JvdXRlcjsKCiAgICAgIGZvciAodmFyIF9sZW4yID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuMiA+IDEgPyBfbGVuMiAtIDEgOiAwKSwgX2tleTIgPSAxOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7CiAgICAgICAgYXJnc1tfa2V5MiAtIDFdID0gYXJndW1lbnRzW19rZXkyXTsKICAgICAgfQoKICAgICAgcmV0dXJuIChfdGhpcyRfcm91dGVyID0gdGhpcy5fcm91dGVyKS5nZW5lcmF0ZS5hcHBseShfdGhpcyRfcm91dGVyLCBbcm91dGVOYW1lXS5jb25jYXQoYXJncykpOwogICAgfQogICAgLyoqCiAgICAgICBEZXRlcm1pbmVzIHdoZXRoZXIgYSByb3V0ZSBpcyBhY3RpdmUuCiAgICAgICAgICBAbWV0aG9kIGlzQWN0aXZlCiAgICAgICBAcGFyYW0ge1N0cmluZ30gcm91dGVOYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZQogICAgICAgQHBhcmFtIHsuLi5PYmplY3R9IG1vZGVscyB0aGUgbW9kZWwocykgb3IgaWRlbnRpZmllcihzKSB0byBiZSB1c2VkIHdoaWxlCiAgICAgICAgIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBvcHRpb25hbCBoYXNoIHdpdGggYSBxdWVyeVBhcmFtcyBwcm9wZXJ0eQogICAgICAgICBjb250YWluaW5nIGEgbWFwcGluZyBvZiBxdWVyeSBwYXJhbWV0ZXJzCiAgICAgICBAcmV0dXJuIHtib29sZWFufSB0cnVlIGlmIHRoZSBwcm92aWRlZCByb3V0ZU5hbWUvbW9kZWxzL3F1ZXJ5UGFyYW1zIGFyZSBhY3RpdmUKICAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by5pc0FjdGl2ZSA9IGZ1bmN0aW9uIGlzQWN0aXZlKCkgewogICAgICBmb3IgKHZhciBfbGVuMyA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjMpLCBfa2V5MyA9IDA7IF9rZXkzIDwgX2xlbjM7IF9rZXkzKyspIHsKICAgICAgICBhcmdzW19rZXkzXSA9IGFyZ3VtZW50c1tfa2V5M107CiAgICAgIH0KCiAgICAgIHZhciBfZXh0cmFjdFJvdXRlQXJnczIgPSAoMCwgX3V0aWxzLmV4dHJhY3RSb3V0ZUFyZ3MpKGFyZ3MpLAogICAgICAgICAgcm91dGVOYW1lID0gX2V4dHJhY3RSb3V0ZUFyZ3MyLnJvdXRlTmFtZSwKICAgICAgICAgIG1vZGVscyA9IF9leHRyYWN0Um91dGVBcmdzMi5tb2RlbHMsCiAgICAgICAgICBxdWVyeVBhcmFtcyA9IF9leHRyYWN0Um91dGVBcmdzMi5xdWVyeVBhcmFtczsKCiAgICAgIHZhciByb3V0ZXJNaWNyb2xpYiA9IHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWI7CgogICAgICBpZiAoIXJvdXRlck1pY3JvbGliLmlzQWN0aXZlSW50ZW50KHJvdXRlTmFtZSwgbW9kZWxzKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgdmFyIGhhc1F1ZXJ5UGFyYW1zID0gT2JqZWN0LmtleXMocXVlcnlQYXJhbXMpLmxlbmd0aCA+IDA7CgogICAgICBpZiAoaGFzUXVlcnlQYXJhbXMpIHsKICAgICAgICB0aGlzLl9yb3V0ZXIuX3ByZXBhcmVRdWVyeVBhcmFtcyhyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMsIHRydWUKICAgICAgICAvKiBmcm9tUm91dGVyU2VydmljZSAqLwogICAgICAgICk7CgogICAgICAgIHJldHVybiAoMCwgX3V0aWxzLnNoYWxsb3dFcXVhbCkocXVlcnlQYXJhbXMsIHJvdXRlck1pY3JvbGliLnN0YXRlLnF1ZXJ5UGFyYW1zKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICAvKioKICAgICAgIFRha2VzIGEgc3RyaW5nIFVSTCBhbmQgcmV0dXJucyBhIGBSb3V0ZUluZm9gIGZvciB0aGUgbGVhZm1vc3Qgcm91dGUgcmVwcmVzZW50ZWQKICAgICAgIGJ5IHRoZSBVUkwuIFJldHVybnMgYG51bGxgIGlmIHRoZSBVUkwgaXMgbm90IHJlY29nbml6ZWQuIFRoaXMgbWV0aG9kIGV4cGVjdHMgdG8KICAgICAgIHJlY2VpdmUgdGhlIGFjdHVhbCBVUkwgYXMgc2VlbiBieSB0aGUgYnJvd3NlciBpbmNsdWRpbmcgdGhlIGFwcCdzIGByb290VVJMYC4KICAgICAgICAgIFNlZSBbUm91dGVJbmZvXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1JvdXRlSW5mbykgZm9yIG1vcmUgaW5mby4KICAgICAgICAgIEluIHRoZSBmb2xsb3dpbmcgZXhhbXBsZSBgcmVjb2duaXplYCBpcyB1c2VkIHRvIHZlcmlmeSBpZiBhIHBhdGggYmVsb25ncyB0byBvdXIKICAgICAgIGFwcGxpY2F0aW9uIGJlZm9yZSB0cmFuc2l0aW9uaW5nIHRvIGl0LgogICAgICAgICAgYGBgCiAgICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICAgaW1wb3J0IHsgaW5qZWN0IGFzIHNlcnZpY2UgfSBmcm9tICdAZW1iZXIvc2VydmljZSc7CiAgICAgICAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICAgcm91dGVyOiBzZXJ2aWNlKCksCiAgICAgICAgIHBhdGg6ICcvJywKICAgICAgICAgICAgY2xpY2soKSB7CiAgICAgICAgICAgaWYodGhpcy5yb3V0ZXIucmVjb2duaXplKHRoaXMucGF0aCkpIHsKICAgICAgICAgICAgIHRoaXMucm91dGVyLnRyYW5zaXRpb25Ubyh0aGlzLnBhdGgpOwogICAgICAgICAgIH0KICAgICAgICAgfQogICAgICAgfSk7CiAgICAgICBgYGAKICAgICAgICAgICBAbWV0aG9kIHJlY29nbml6ZQogICAgICAgIEBwYXJhbSB7U3RyaW5nfSB1cmwKICAgICAgICBAcHVibGljCiAgICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlY29nbml6ZSA9IGZ1bmN0aW9uIHJlY29nbml6ZSh1cmwpIHsKICAgICAgKGZhbHNlICYmICEodXJsLmluZGV4T2YodGhpcy5yb290VVJMKSA9PT0gMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgbXVzdCBwYXNzIGEgdXJsIHRoYXQgYmVnaW5zIHdpdGggdGhlIGFwcGxpY2F0aW9uJ3Mgcm9vdFVSTCBcIiIgKyB0aGlzLnJvb3RVUkwgKyAiXCIiLCB1cmwuaW5kZXhPZih0aGlzLnJvb3RVUkwpID09PSAwKSk7CiAgICAgIHZhciBpbnRlcm5hbFVSTCA9IGNsZWFuVVJMKHVybCwgdGhpcy5yb290VVJMKTsKICAgICAgcmV0dXJuIHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWIucmVjb2duaXplKGludGVybmFsVVJMKTsKICAgIH0KICAgIC8qKgogICAgICBUYWtlcyBhIHN0cmluZyBVUkwgYW5kIHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYQogICAgICBgUm91dGVJbmZvV2l0aEF0dHJpYnV0ZXNgIGZvciB0aGUgbGVhZm1vc3Qgcm91dGUgcmVwcmVzZW50ZWQgYnkgdGhlIFVSTC4KICAgICAgVGhlIHByb21pc2UgcmVqZWN0cyBpZiB0aGUgVVJMIGlzIG5vdCByZWNvZ25pemVkIG9yIGFuIHVuaGFuZGxlZCBleGNlcHRpb24KICAgICAgaXMgZW5jb3VudGVyZWQuIFRoaXMgbWV0aG9kIGV4cGVjdHMgdG8gcmVjZWl2ZSB0aGUgYWN0dWFsIFVSTCBhcyBzZWVuIGJ5CiAgICAgIHRoZSBicm93c2VyIGluY2x1ZGluZyB0aGUgYXBwJ3MgYHJvb3RVUkxgLgogICAgICAgICAgIEBtZXRob2QgcmVjb2duaXplQW5kTG9hZAogICAgICAgIEBwYXJhbSB7U3RyaW5nfSB1cmwKICAgICAgICBAcHVibGljCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVjb2duaXplQW5kTG9hZCA9IGZ1bmN0aW9uIHJlY29nbml6ZUFuZExvYWQodXJsKSB7CiAgICAgIChmYWxzZSAmJiAhKHVybC5pbmRleE9mKHRoaXMucm9vdFVSTCkgPT09IDApICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IG11c3QgcGFzcyBhIHVybCB0aGF0IGJlZ2lucyB3aXRoIHRoZSBhcHBsaWNhdGlvbidzIHJvb3RVUkwgXCIiICsgdGhpcy5yb290VVJMICsgIlwiIiwgdXJsLmluZGV4T2YodGhpcy5yb290VVJMKSA9PT0gMCkpOwogICAgICB2YXIgaW50ZXJuYWxVUkwgPSBjbGVhblVSTCh1cmwsIHRoaXMucm9vdFVSTCk7CiAgICAgIHJldHVybiB0aGlzLl9yb3V0ZXIuX3JvdXRlck1pY3JvbGliLnJlY29nbml6ZUFuZExvYWQoaW50ZXJuYWxVUkwpOwogICAgfTsKCiAgICByZXR1cm4gUm91dGVyU2VydmljZTsKICB9KF9zZXJ2aWNlLmRlZmF1bHQpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gUm91dGVyU2VydmljZTsKICBSb3V0ZXJTZXJ2aWNlLnJlb3BlbihfcnVudGltZS5FdmVudGVkLCB7CiAgICAvKioKICAgICAgIE5hbWUgb2YgdGhlIGN1cnJlbnQgcm91dGUuCiAgICAgICAgICBUaGlzIHByb3BlcnR5IHJlcHJlc2VudHMgdGhlIGxvZ2ljYWwgbmFtZSBvZiB0aGUgcm91dGUsCiAgICAgICB3aGljaCBpcyBjb21tYSBzZXBhcmF0ZWQuCiAgICAgICBGb3IgdGhlIGZvbGxvd2luZyByb3V0ZXI6CiAgICAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgICB0aGlzLnJvdXRlKCdhYm91dCcpOwogICAgICAgICB0aGlzLnJvdXRlKCdibG9nJywgZnVuY3Rpb24gKCkgewogICAgICAgICAgIHRoaXMucm91dGUoJ3Bvc3QnLCB7IHBhdGg6ICc6cG9zdF9pZCcgfSk7CiAgICAgICAgIH0pOwogICAgICAgfSk7CiAgICAgICBgYGAKICAgICAgICAgIEl0IHdpbGwgcmV0dXJuOgogICAgICAgICAgKiBgaW5kZXhgIHdoZW4geW91IHZpc2l0IGAvYAogICAgICAgKiBgYWJvdXRgIHdoZW4geW91IHZpc2l0IGAvYWJvdXRgCiAgICAgICAqIGBibG9nLmluZGV4YCB3aGVuIHlvdSB2aXNpdCBgL2Jsb2dgCiAgICAgICAqIGBibG9nLnBvc3RgIHdoZW4geW91IHZpc2l0IGAvYmxvZy9zb21lLXBvc3QtaWRgCiAgICAgICAgICBAcHJvcGVydHkgY3VycmVudFJvdXRlTmFtZQogICAgICAgQHR5cGUgU3RyaW5nCiAgICAgICBAcHVibGljCiAgICAgKi8KICAgIGN1cnJlbnRSb3V0ZU5hbWU6ICgwLCBfY29tcHV0ZWQucmVhZE9ubHkpKCdfcm91dGVyLmN1cnJlbnRSb3V0ZU5hbWUnKSwKCiAgICAvKioKICAgICAgIEN1cnJlbnQgVVJMIGZvciB0aGUgYXBwbGljYXRpb24uCiAgICAgICAgIFRoaXMgcHJvcGVydHkgcmVwcmVzZW50cyB0aGUgVVJMIHBhdGggZm9yIHRoaXMgcm91dGUuCiAgICAgIEZvciB0aGUgZm9sbG93aW5nIHJvdXRlcjoKICAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgIHRoaXMucm91dGUoJ2Fib3V0Jyk7CiAgICAgICAgIHRoaXMucm91dGUoJ2Jsb2cnLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgdGhpcy5yb3V0ZSgncG9zdCcsIHsgcGF0aDogJzpwb3N0X2lkJyB9KTsKICAgICAgICAgfSk7CiAgICAgICB9KTsKICAgICAgIGBgYAogICAgICAgICAgSXQgd2lsbCByZXR1cm46CiAgICAgICAgICAqIGAvYCB3aGVuIHlvdSB2aXNpdCBgL2AKICAgICAgICogYC9hYm91dGAgd2hlbiB5b3UgdmlzaXQgYC9hYm91dGAKICAgICAgICogYC9ibG9nYCB3aGVuIHlvdSB2aXNpdCBgL2Jsb2dgCiAgICAgICAqIGAvYmxvZy9zb21lLXBvc3QtaWRgIHdoZW4geW91IHZpc2l0IGAvYmxvZy9zb21lLXBvc3QtaWRgCiAgICAgICAgICBAcHJvcGVydHkgY3VycmVudFVSTAogICAgICAgQHR5cGUgU3RyaW5nCiAgICAgICBAcHVibGljCiAgICAgKi8KICAgIGN1cnJlbnRVUkw6ICgwLCBfY29tcHV0ZWQucmVhZE9ubHkpKCdfcm91dGVyLmN1cnJlbnRVUkwnKSwKCiAgICAvKioKICAgICAgVGhlIGBsb2NhdGlvbmAgcHJvcGVydHkgcmV0dXJucyB3aGF0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBgbG9jYXRpb25gIEFQSQogICAgICB5b3VyIGFwcGxpY2F0aW9uIGlzIHVzaW5nLCB3aGljaCBkZXRlcm1pbmVzIHdoYXQgdHlwZSBvZiBVUkwgaXMgYmVpbmcgdXNlZC4KICAgICAgICAgU2VlIFtMb2NhdGlvbl0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9Mb2NhdGlvbikgZm9yIG1vcmUgaW5mb3JtYXRpb24uCiAgICAgICAgIFRvIGZvcmNlIGEgcGFydGljdWxhciBgbG9jYXRpb25gIEFQSSBpbXBsZW1lbnRhdGlvbiB0byBiZSB1c2VkIGluIHlvdXIKICAgICAgYXBwbGljYXRpb24geW91IGNhbiBzZXQgYSBsb2NhdGlvbiB0eXBlIG9uIHlvdXIgYGNvbmZpZy9lbnZpcm9ubWVudGAuCiAgICAgIEZvciBleGFtcGxlLCB0byBzZXQgdGhlIGBoaXN0b3J5YCB0eXBlOgogICAgICAgICBgYGBjb25maWcvZW52aXJvbm1lbnQuanMKICAgICAgJ3VzZSBzdHJpY3QnOwogICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGVudmlyb25tZW50KSB7CiAgICAgICAgbGV0IEVOViA9IHsKICAgICAgICAgIG1vZHVsZVByZWZpeDogJ3JvdXRlci1zZXJ2aWNlJywKICAgICAgICAgIGVudmlyb25tZW50LAogICAgICAgICAgcm9vdFVSTDogJy8nLAogICAgICAgICAgbG9jYXRpb25UeXBlOiAnaGlzdG9yeScsCiAgICAgICAgICAuLi4KICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICAgIFRoZSBmb2xsb3dpbmcgbG9jYXRpb24gdHlwZXMgYXJlIGF2YWlsYWJsZSBieSBkZWZhdWx0OgogICAgICBgYXV0b2AsIGBoYXNoYCwgYGhpc3RvcnlgLCBgbm9uZWAuCiAgICAgICAgIFNlZSBbSGFzaExvY2F0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0hhc2hMb2NhdGlvbikuCiAgICAgIFNlZSBbSGlzdG9yeUxvY2F0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0hpc3RvcnlMb2NhdGlvbikuCiAgICAgIFNlZSBbTm9uZUxvY2F0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL05vbmVMb2NhdGlvbikuCiAgICAgIFNlZSBbQXV0b0xvY2F0aW9uXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0F1dG9Mb2NhdGlvbikuCiAgICAgICAgIEBwcm9wZXJ0eSBsb2NhdGlvbgogICAgICBAZGVmYXVsdCAnaGFzaCcKICAgICAgQHNlZSB7TG9jYXRpb259CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBsb2NhdGlvbjogKDAsIF9jb21wdXRlZC5yZWFkT25seSkoJ19yb3V0ZXIubG9jYXRpb24nKSwKCiAgICAvKioKICAgICAgVGhlIGByb290VVJMYCBwcm9wZXJ0eSByZXByZXNlbnRzIHRoZSBVUkwgb2YgdGhlIHJvb3Qgb2YKICAgICAgdGhlIGFwcGxpY2F0aW9uLCAnLycgYnkgZGVmYXVsdC4KICAgICAgVGhpcyBwcmVmaXggaXMgYXNzdW1lZCBvbiBhbGwgcm91dGVzIGRlZmluZWQgb24gdGhpcyBhcHAuCiAgICAgICAgIElmIHlvdSBjaGFuZ2UgdGhlIGByb290VVJMYCBpbiB5b3VyIGVudmlyb25tZW50IGNvbmZpZ3VyYXRpb24KICAgICAgbGlrZSBzbzoKICAgICAgICAgYGBgY29uZmlnL2Vudmlyb25tZW50LmpzCiAgICAgICd1c2Ugc3RyaWN0JzsKICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihlbnZpcm9ubWVudCkgewogICAgICAgIGxldCBFTlYgPSB7CiAgICAgICAgICBtb2R1bGVQcmVmaXg6ICdyb3V0ZXItc2VydmljZScsCiAgICAgICAgICBlbnZpcm9ubWVudCwKICAgICAgICAgIHJvb3RVUkw6ICcvbXktcm9vdCcsCiAgICAgICAg4oCmCiAgICAgICAgfQogICAgICBdCiAgICAgIGBgYAogICAgICAgICBUaGlzIHByb3BlcnR5IHdpbGwgcmV0dXJuIGAvbXktcm9vdGAuCiAgICAgICAgIEBwcm9wZXJ0eSByb290VVJMCiAgICAgIEBkZWZhdWx0ICcvJwogICAgICBAcHVibGljCiAgICAqLwogICAgcm9vdFVSTDogKDAsIF9jb21wdXRlZC5yZWFkT25seSkoJ19yb3V0ZXIucm9vdFVSTCcpLAoKICAgIC8qKgogICAgICBUaGUgYGN1cnJlbnRSb3V0ZWAgcHJvcGVydHkgY29udGFpbnMgbWV0YWRhdGEgYWJvdXQgdGhlIGN1cnJlbnQgbGVhZiByb3V0ZS4KICAgICAgSXQgcmV0dXJucyBhIGBSb3V0ZUluZm9gIG9iamVjdCB0aGF0IGhhcyBpbmZvcm1hdGlvbiBsaWtlIHRoZSByb3V0ZSBuYW1lLAogICAgICBwYXJhbXMsIHF1ZXJ5IHBhcmFtcyBhbmQgbW9yZS4KICAgICAgICAgU2VlIFtSb3V0ZUluZm9dKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvUm91dGVJbmZvKSBmb3IgbW9yZSBpbmZvLgogICAgICAgICBUaGlzIHByb3BlcnR5IGlzIGd1YXJhbnRlZWQgdG8gY2hhbmdlIHdoZW5ldmVyIGEgcm91dGUgdHJhbnNpdGlvbgogICAgICBoYXBwZW5zIChldmVuIHdoZW4gdGhhdCB0cmFuc2l0aW9uIG9ubHkgY2hhbmdlcyBwYXJhbWV0ZXJzCiAgICAgIGFuZCBkb2Vzbid0IGNoYW5nZSB0aGUgYWN0aXZlIHJvdXRlKS4KICAgICAgICAgVXNhZ2UgZXhhbXBsZToKICAgICAgYGBgYXBwL2NvbXBvbmVudHMvaGVhZGVyLmpzCiAgICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAgICAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICAgICAgcm91dGVyOiBzZXJ2aWNlKCksCiAgICAgICAgICAgICBpc0NoaWxkUm91dGU6IGNvbXB1dGVkLm5vdEVtcHR5KCdyb3V0ZXIuY3VycmVudFJvdXRlLmNoaWxkJykKICAgICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgICBAcHJvcGVydHkgY3VycmVudFJvdXRlCiAgICAgICBAdHlwZSBSb3V0ZUluZm8KICAgICAgIEBwdWJsaWMKICAgICAqLwogICAgY3VycmVudFJvdXRlOiAoMCwgX2NvbXB1dGVkLnJlYWRPbmx5KSgnX3JvdXRlci5jdXJyZW50Um91dGUnKQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zZXJ2aWNlcy9yb3V0aW5nIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci9vYmplY3QvY29tcHV0ZWQiLCAiQGVtYmVyL3BvbHlmaWxscyIsICJAZW1iZXIvc2VydmljZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfY29tcHV0ZWQsIF9wb2x5ZmlsbHMsIF9zZXJ2aWNlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBUaGUgUm91dGluZyBzZXJ2aWNlIGlzIHVzZWQgYnkgTGlua0NvbXBvbmVudCwgYW5kIHByb3ZpZGVzIGZhY2lsaXRpZXMgZm9yCiAgICB0aGUgY29tcG9uZW50L3ZpZXcgbGF5ZXIgdG8gaW50ZXJhY3Qgd2l0aCB0aGUgcm91dGVyLgogIAogICAgVGhpcyBpcyBhIHByaXZhdGUgc2VydmljZSBmb3IgaW50ZXJuYWwgdXNhZ2Ugb25seS4gRm9yIHB1YmxpYyB1c2FnZSwKICAgIHJlZmVyIHRvIHRoZSBgUm91dGVyYCBzZXJ2aWNlLgogIAogICAgQHByaXZhdGUKICAgIEBjbGFzcyBSb3V0aW5nU2VydmljZQogICovCiAgdmFyIFJvdXRpbmdTZXJ2aWNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9TZXJ2aWNlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUm91dGluZ1NlcnZpY2UsIF9TZXJ2aWNlKTsKCiAgICBmdW5jdGlvbiBSb3V0aW5nU2VydmljZSgpIHsKICAgICAgcmV0dXJuIF9TZXJ2aWNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gUm91dGluZ1NlcnZpY2UucHJvdG90eXBlOwoKICAgIF9wcm90by5oYXNSb3V0ZSA9IGZ1bmN0aW9uIGhhc1JvdXRlKHJvdXRlTmFtZSkgewogICAgICByZXR1cm4gdGhpcy5yb3V0ZXIuaGFzUm91dGUocm91dGVOYW1lKTsKICAgIH07CgogICAgX3Byb3RvLnRyYW5zaXRpb25UbyA9IGZ1bmN0aW9uIHRyYW5zaXRpb25Ubyhyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMsIHNob3VsZFJlcGxhY2UpIHsKICAgICAgdmFyIHRyYW5zaXRpb24gPSB0aGlzLnJvdXRlci5fZG9UcmFuc2l0aW9uKHJvdXRlTmFtZSwgbW9kZWxzLCBxdWVyeVBhcmFtcyk7CgogICAgICBpZiAoc2hvdWxkUmVwbGFjZSkgewogICAgICAgIHRyYW5zaXRpb24ubWV0aG9kKCdyZXBsYWNlJyk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0cmFuc2l0aW9uOwogICAgfTsKCiAgICBfcHJvdG8ubm9ybWFsaXplUXVlcnlQYXJhbXMgPSBmdW5jdGlvbiBub3JtYWxpemVRdWVyeVBhcmFtcyhyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMpIHsKICAgICAgdGhpcy5yb3V0ZXIuX3ByZXBhcmVRdWVyeVBhcmFtcyhyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMpOwogICAgfTsKCiAgICBfcHJvdG8uZ2VuZXJhdGVVUkwgPSBmdW5jdGlvbiBnZW5lcmF0ZVVSTChyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMpIHsKICAgICAgdmFyIHJvdXRlciA9IHRoaXMucm91dGVyOyAvLyByZXR1cm4gZWFybHkgd2hlbiB0aGUgcm91dGVyIG1pY3JvbGliIGlzIG5vdCBwcmVzZW50LCB3aGljaCBpcyB0aGUgY2FzZSBmb3Ige3tsaW5rLXRvfX0gaW4gaW50ZWdyYXRpb24gdGVzdHMKCiAgICAgIGlmICghcm91dGVyLl9yb3V0ZXJNaWNyb2xpYikgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIHZpc2libGVRdWVyeVBhcmFtcyA9IHt9OwoKICAgICAgaWYgKHF1ZXJ5UGFyYW1zKSB7CiAgICAgICAgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh2aXNpYmxlUXVlcnlQYXJhbXMsIHF1ZXJ5UGFyYW1zKTsKICAgICAgICB0aGlzLm5vcm1hbGl6ZVF1ZXJ5UGFyYW1zKHJvdXRlTmFtZSwgbW9kZWxzLCB2aXNpYmxlUXVlcnlQYXJhbXMpOwogICAgICB9CgogICAgICByZXR1cm4gcm91dGVyLmdlbmVyYXRlLmFwcGx5KHJvdXRlciwgW3JvdXRlTmFtZV0uY29uY2F0KG1vZGVscywgW3sKICAgICAgICBxdWVyeVBhcmFtczogdmlzaWJsZVF1ZXJ5UGFyYW1zCiAgICAgIH1dKSk7CiAgICB9OwoKICAgIF9wcm90by5pc0FjdGl2ZUZvclJvdXRlID0gZnVuY3Rpb24gaXNBY3RpdmVGb3JSb3V0ZShjb250ZXh0cywgcXVlcnlQYXJhbXMsIHJvdXRlTmFtZSwgcm91dGVyU3RhdGUsIGlzQ3VycmVudFdoZW5TcGVjaWZpZWQpIHsKICAgICAgdmFyIGhhbmRsZXJzID0gdGhpcy5yb3V0ZXIuX3JvdXRlck1pY3JvbGliLnJlY29nbml6ZXIuaGFuZGxlcnNGb3Iocm91dGVOYW1lKTsKCiAgICAgIHZhciBsZWFmTmFtZSA9IGhhbmRsZXJzW2hhbmRsZXJzLmxlbmd0aCAtIDFdLmhhbmRsZXI7CiAgICAgIHZhciBtYXhpbXVtQ29udGV4dHMgPSBudW1iZXJPZkNvbnRleHRzQWNjZXB0ZWRCeUhhbmRsZXIocm91dGVOYW1lLCBoYW5kbGVycyk7IC8vIE5PVEU6IGFueSB1Z2xpbmVzcyBpbiB0aGUgY2FsY3VsYXRpb24gb2YgYWN0aXZlbmVzcyBpcyBsYXJnZWx5CiAgICAgIC8vIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHdlIHN1cHBvcnQgYXV0b21hdGljIG5vcm1hbGl6aW5nIG9mCiAgICAgIC8vIGByZXNvdXJjZWAgLT4gYHJlc291cmNlLmluZGV4YCwgZXZlbiB0aG91Z2ggdGhlcmUgbWlnaHQgYmUKICAgICAgLy8gZHluYW1pYyBzZWdtZW50cyAvIHF1ZXJ5IHBhcmFtcyBkZWZpbmVkIG9uIGByZXNvdXJjZS5pbmRleGAKICAgICAgLy8gd2hpY2ggY29tcGxpY2F0ZXMgKGFuZCBtYWtlcyBzb21ld2hhdCBhbWJpZ3VvdXMpIHRoZSBjYWxjdWxhdGlvbgogICAgICAvLyBvZiBhY3RpdmVuZXNzIGZvciBsaW5rcyB0aGF0IGxpbmsgdG8gYHJlc291cmNlYCBpbnN0ZWFkIG9mCiAgICAgIC8vIGRpcmVjdGx5IHRvIGByZXNvdXJjZS5pbmRleGAuCiAgICAgIC8vIGlmIHdlIGRvbid0IGhhdmUgZW5vdWdoIGNvbnRleHRzIHJldmVydCBiYWNrIHRvIGZ1bGwgcm91dGUgbmFtZQogICAgICAvLyB0aGlzIGlzIGJlY2F1c2UgdGhlIGxlYWYgcm91dGUgd2lsbCB1c2Ugb25lIG9mIHRoZSBjb250ZXh0cwoKICAgICAgaWYgKGNvbnRleHRzLmxlbmd0aCA+IG1heGltdW1Db250ZXh0cykgewogICAgICAgIHJvdXRlTmFtZSA9IGxlYWZOYW1lOwogICAgICB9CgogICAgICByZXR1cm4gcm91dGVyU3RhdGUuaXNBY3RpdmVJbnRlbnQocm91dGVOYW1lLCBjb250ZXh0cywgcXVlcnlQYXJhbXMsICFpc0N1cnJlbnRXaGVuU3BlY2lmaWVkKTsKICAgIH07CgogICAgcmV0dXJuIFJvdXRpbmdTZXJ2aWNlOwogIH0oX3NlcnZpY2UuZGVmYXVsdCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBSb3V0aW5nU2VydmljZTsKICBSb3V0aW5nU2VydmljZS5yZW9wZW4oewogICAgdGFyZ2V0U3RhdGU6ICgwLCBfY29tcHV0ZWQucmVhZE9ubHkpKCdyb3V0ZXIudGFyZ2V0U3RhdGUnKSwKICAgIGN1cnJlbnRTdGF0ZTogKDAsIF9jb21wdXRlZC5yZWFkT25seSkoJ3JvdXRlci5jdXJyZW50U3RhdGUnKSwKICAgIGN1cnJlbnRSb3V0ZU5hbWU6ICgwLCBfY29tcHV0ZWQucmVhZE9ubHkpKCdyb3V0ZXIuY3VycmVudFJvdXRlTmFtZScpLAogICAgY3VycmVudFBhdGg6ICgwLCBfY29tcHV0ZWQucmVhZE9ubHkpKCdyb3V0ZXIuY3VycmVudFBhdGgnKQogIH0pOwoKICBmdW5jdGlvbiBudW1iZXJPZkNvbnRleHRzQWNjZXB0ZWRCeUhhbmRsZXIoaGFuZGxlck5hbWUsIGhhbmRsZXJJbmZvcykgewogICAgdmFyIHJlcSA9IDA7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYW5kbGVySW5mb3MubGVuZ3RoOyBpKyspIHsKICAgICAgcmVxICs9IGhhbmRsZXJJbmZvc1tpXS5uYW1lcy5sZW5ndGg7CgogICAgICBpZiAoaGFuZGxlckluZm9zW2ldLmhhbmRsZXIgPT09IGhhbmRsZXJOYW1lKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcmVxOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL2NhY2hlIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgICBBIHR3by10aWVyZWQgY2FjaGUgd2l0aCBzdXBwb3J0IGZvciBmYWxsYmFjayB2YWx1ZXMgd2hlbiBkb2luZyBsb29rdXBzLgogICAgVXNlcyAiYnVja2V0cyIgYW5kIHRoZW4gImtleXMiIHRvIGNhY2hlIHZhbHVlcy4KICAKICAgIEBwcml2YXRlCiAgICBAY2xhc3MgQnVja2V0Q2FjaGUKICAqLwogIHZhciBCdWNrZXRDYWNoZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEJ1Y2tldENhY2hlKCkgewogICAgICB0aGlzLmNhY2hlID0gbmV3IE1hcCgpOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBCdWNrZXRDYWNoZS5wcm90b3R5cGU7CgogICAgX3Byb3RvLmhhcyA9IGZ1bmN0aW9uIGhhcyhidWNrZXRLZXkpIHsKICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuaGFzKGJ1Y2tldEtleSk7CiAgICB9OwoKICAgIF9wcm90by5zdGFzaCA9IGZ1bmN0aW9uIHN0YXNoKGJ1Y2tldEtleSwga2V5LCB2YWx1ZSkgewogICAgICB2YXIgYnVja2V0ID0gdGhpcy5jYWNoZS5nZXQoYnVja2V0S2V5KTsKCiAgICAgIGlmIChidWNrZXQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGJ1Y2tldCA9IG5ldyBNYXAoKTsKICAgICAgICB0aGlzLmNhY2hlLnNldChidWNrZXRLZXksIGJ1Y2tldCk7CiAgICAgIH0KCiAgICAgIGJ1Y2tldC5zZXQoa2V5LCB2YWx1ZSk7CiAgICB9OwoKICAgIF9wcm90by5sb29rdXAgPSBmdW5jdGlvbiBsb29rdXAoYnVja2V0S2V5LCBwcm9wLCBkZWZhdWx0VmFsdWUpIHsKICAgICAgaWYgKCF0aGlzLmhhcyhidWNrZXRLZXkpKSB7CiAgICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKICAgICAgfQoKICAgICAgdmFyIGJ1Y2tldCA9IHRoaXMuY2FjaGUuZ2V0KGJ1Y2tldEtleSk7CgogICAgICBpZiAoYnVja2V0Lmhhcyhwcm9wKSkgewogICAgICAgIHJldHVybiBidWNrZXQuZ2V0KHByb3ApOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEJ1Y2tldENhY2hlOwogIH0oKTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IEJ1Y2tldENhY2hlOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vY29udHJvbGxlcl9mb3IiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gY29udHJvbGxlckZvcjsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgRmluZHMgYSBjb250cm9sbGVyIGluc3RhbmNlLgogIAogICAgQGZvciBFbWJlcgogICAgQG1ldGhvZCBjb250cm9sbGVyRm9yCiAgICBAcHJpdmF0ZQogICovCiAgZnVuY3Rpb24gY29udHJvbGxlckZvcihjb250YWluZXIsIGNvbnRyb2xsZXJOYW1lLCBsb29rdXBPcHRpb25zKSB7CiAgICByZXR1cm4gY29udGFpbmVyLmxvb2t1cCgiY29udHJvbGxlcjoiICsgY29udHJvbGxlck5hbWUsIGxvb2t1cE9wdGlvbnMpOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL2RzbCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL3BvbHlmaWxscyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9kZWJ1ZywgX3BvbHlmaWxscykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKICB2YXIgdXVpZCA9IDA7CgogIGZ1bmN0aW9uIGlzQ2FsbGJhY2sodmFsdWUpIHsKICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbic7CiAgfQoKICBmdW5jdGlvbiBpc09wdGlvbnModmFsdWUpIHsKICAgIHJldHVybiB2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnOwogIH0KCiAgdmFyIERTTEltcGwgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBEU0xJbXBsKG5hbWUsIG9wdGlvbnMpIHsKICAgICAgaWYgKG5hbWUgPT09IHZvaWQgMCkgewogICAgICAgIG5hbWUgPSBudWxsOwogICAgICB9CgogICAgICB0aGlzLmV4cGxpY2l0SW5kZXggPSBmYWxzZTsKICAgICAgdGhpcy5wYXJlbnQgPSBuYW1lOwogICAgICB0aGlzLmVuYWJsZUxvYWRpbmdTdWJzdGF0ZXMgPSBCb29sZWFuKG9wdGlvbnMgJiYgb3B0aW9ucy5lbmFibGVMb2FkaW5nU3Vic3RhdGVzKTsKICAgICAgdGhpcy5tYXRjaGVzID0gW107CiAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7CiAgICB9CgogICAgdmFyIF9wcm90byA9IERTTEltcGwucHJvdG90eXBlOwoKICAgIF9wcm90by5yb3V0ZSA9IGZ1bmN0aW9uIHJvdXRlKG5hbWUsIF9vcHRpb25zLCBfY2FsbGJhY2spIHsKICAgICAgdmFyIG9wdGlvbnM7CiAgICAgIHZhciBjYWxsYmFjayA9IG51bGw7CiAgICAgIHZhciBkdW1teUVycm9yUm91dGUgPSAiL191bnVzZWRfZHVtbXlfZXJyb3JfcGF0aF9yb3V0ZV8iICsgbmFtZSArICIvOmVycm9yIjsKCiAgICAgIGlmIChpc0NhbGxiYWNrKF9vcHRpb25zKSkgewogICAgICAgIChmYWxzZSAmJiAhKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnVW5leHBlY3RlZCBhcmd1bWVudHMnLCBhcmd1bWVudHMubGVuZ3RoID09PSAyKSk7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICAgIGNhbGxiYWNrID0gX29wdGlvbnM7CiAgICAgIH0gZWxzZSBpZiAoaXNDYWxsYmFjayhfY2FsbGJhY2spKSB7CiAgICAgICAgKGZhbHNlICYmICEoYXJndW1lbnRzLmxlbmd0aCA9PT0gMykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdVbmV4cGVjdGVkIGFyZ3VtZW50cycsIGFyZ3VtZW50cy5sZW5ndGggPT09IDMpKTsKICAgICAgICAoZmFsc2UgJiYgIShpc09wdGlvbnMoX29wdGlvbnMpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1VuZXhwZWN0ZWQgYXJndW1lbnRzJywgaXNPcHRpb25zKF9vcHRpb25zKSkpOwogICAgICAgIG9wdGlvbnMgPSBfb3B0aW9uczsKICAgICAgICBjYWxsYmFjayA9IF9jYWxsYmFjazsKICAgICAgfSBlbHNlIHsKICAgICAgICBvcHRpb25zID0gX29wdGlvbnMgfHwge307CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKGZ1bmN0aW9uICgpIHsKICAgICAgICBpZiAob3B0aW9ucy5vdmVycmlkZU5hbWVBc3NlcnRpb24gPT09IHRydWUpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIFsnYmFzaWMnLCAnYXBwbGljYXRpb24nXS5pbmRleE9mKG5hbWUpID09PSAtMTsKICAgICAgfSgpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIiciICsgbmFtZSArICInIGNhbm5vdCBiZSB1c2VkIGFzIGEgcm91dGUgbmFtZS4iLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgaWYgKG9wdGlvbnMub3ZlcnJpZGVOYW1lQXNzZXJ0aW9uID09PSB0cnVlKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBbJ2Jhc2ljJywgJ2FwcGxpY2F0aW9uJ10uaW5kZXhPZihuYW1lKSA9PT0gLTE7CiAgICAgIH0oKSkpOwogICAgICAoZmFsc2UgJiYgIShuYW1lLmluZGV4T2YoJzonKSA9PT0gLTEpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiJyIgKyBuYW1lICsgIicgaXMgbm90IGEgdmFsaWQgcm91dGUgbmFtZS4gSXQgY2Fubm90IGNvbnRhaW4gYSAnOicuIFlvdSBtYXkgd2FudCB0byB1c2UgdGhlICdwYXRoJyBvcHRpb24gaW5zdGVhZC4iLCBuYW1lLmluZGV4T2YoJzonKSA9PT0gLTEpKTsKCiAgICAgIGlmICh0aGlzLmVuYWJsZUxvYWRpbmdTdWJzdGF0ZXMpIHsKICAgICAgICBjcmVhdGVSb3V0ZSh0aGlzLCBuYW1lICsgIl9sb2FkaW5nIiwgewogICAgICAgICAgcmVzZXROYW1lc3BhY2U6IG9wdGlvbnMucmVzZXROYW1lc3BhY2UKICAgICAgICB9KTsKICAgICAgICBjcmVhdGVSb3V0ZSh0aGlzLCBuYW1lICsgIl9lcnJvciIsIHsKICAgICAgICAgIHJlc2V0TmFtZXNwYWNlOiBvcHRpb25zLnJlc2V0TmFtZXNwYWNlLAogICAgICAgICAgcGF0aDogZHVtbXlFcnJvclJvdXRlCiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIGlmIChjYWxsYmFjaykgewogICAgICAgIHZhciBmdWxsTmFtZSA9IGdldEZ1bGxOYW1lKHRoaXMsIG5hbWUsIG9wdGlvbnMucmVzZXROYW1lc3BhY2UpOwogICAgICAgIHZhciBkc2wgPSBuZXcgRFNMSW1wbChmdWxsTmFtZSwgdGhpcy5vcHRpb25zKTsKICAgICAgICBjcmVhdGVSb3V0ZShkc2wsICdsb2FkaW5nJyk7CiAgICAgICAgY3JlYXRlUm91dGUoZHNsLCAnZXJyb3InLCB7CiAgICAgICAgICBwYXRoOiBkdW1teUVycm9yUm91dGUKICAgICAgICB9KTsKICAgICAgICBjYWxsYmFjay5jYWxsKGRzbCk7CiAgICAgICAgY3JlYXRlUm91dGUodGhpcywgbmFtZSwgb3B0aW9ucywgZHNsLmdlbmVyYXRlKCkpOwogICAgICB9IGVsc2UgewogICAgICAgIGNyZWF0ZVJvdXRlKHRoaXMsIG5hbWUsIG9wdGlvbnMpOwogICAgICB9CiAgICB9CiAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWR1cGUtY2xhc3MtbWVtYmVycyAqLwogICAgOwoKICAgIF9wcm90by5wdXNoID0gZnVuY3Rpb24gcHVzaCh1cmwsIG5hbWUsIGNhbGxiYWNrLCBzZXJpYWxpemUpIHsKICAgICAgdmFyIHBhcnRzID0gbmFtZS5zcGxpdCgnLicpOwoKICAgICAgaWYgKHRoaXMub3B0aW9ucy5lbmdpbmVJbmZvKSB7CiAgICAgICAgdmFyIGxvY2FsRnVsbE5hbWUgPSBuYW1lLnNsaWNlKHRoaXMub3B0aW9ucy5lbmdpbmVJbmZvLmZ1bGxOYW1lLmxlbmd0aCArIDEpOwogICAgICAgIHZhciByb3V0ZUluZm8gPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHsKICAgICAgICAgIGxvY2FsRnVsbE5hbWU6IGxvY2FsRnVsbE5hbWUKICAgICAgICB9LCB0aGlzLm9wdGlvbnMuZW5naW5lSW5mbyk7CgogICAgICAgIGlmIChzZXJpYWxpemUpIHsKICAgICAgICAgIHJvdXRlSW5mby5zZXJpYWxpemVNZXRob2QgPSBzZXJpYWxpemU7CiAgICAgICAgfQoKICAgICAgICB0aGlzLm9wdGlvbnMuYWRkUm91dGVGb3JFbmdpbmUobmFtZSwgcm91dGVJbmZvKTsKICAgICAgfSBlbHNlIGlmIChzZXJpYWxpemUpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkRlZmluaW5nIGEgcm91dGUgc2VyaWFsaXplciBvbiByb3V0ZSAnIiArIG5hbWUgKyAiJyBvdXRzaWRlIGFuIEVuZ2luZSBpcyBub3QgYWxsb3dlZC4iKTsKICAgICAgfQoKICAgICAgaWYgKHVybCA9PT0gJycgfHwgdXJsID09PSAnLycgfHwgcGFydHNbcGFydHMubGVuZ3RoIC0gMV0gPT09ICdpbmRleCcpIHsKICAgICAgICB0aGlzLmV4cGxpY2l0SW5kZXggPSB0cnVlOwogICAgICB9CgogICAgICB0aGlzLm1hdGNoZXMucHVzaCh1cmwsIG5hbWUsIGNhbGxiYWNrKTsKICAgIH07CgogICAgX3Byb3RvLmdlbmVyYXRlID0gZnVuY3Rpb24gZ2VuZXJhdGUoKSB7CiAgICAgIHZhciBkc2xNYXRjaGVzID0gdGhpcy5tYXRjaGVzOwoKICAgICAgaWYgKCF0aGlzLmV4cGxpY2l0SW5kZXgpIHsKICAgICAgICB0aGlzLnJvdXRlKCdpbmRleCcsIHsKICAgICAgICAgIHBhdGg6ICcvJwogICAgICAgIH0pOwogICAgICB9CgogICAgICByZXR1cm4gZnVuY3Rpb24gKG1hdGNoKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkc2xNYXRjaGVzLmxlbmd0aDsgaSArPSAzKSB7CiAgICAgICAgICBtYXRjaChkc2xNYXRjaGVzW2ldKS50byhkc2xNYXRjaGVzW2kgKyAxXSwgZHNsTWF0Y2hlc1tpICsgMl0pOwogICAgICAgIH0KICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvLm1vdW50ID0gZnVuY3Rpb24gbW91bnQoX25hbWUsIG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgfQoKICAgICAgdmFyIGVuZ2luZVJvdXRlTWFwID0gdGhpcy5vcHRpb25zLnJlc29sdmVSb3V0ZU1hcChfbmFtZSk7CiAgICAgIHZhciBuYW1lID0gX25hbWU7CgogICAgICBpZiAob3B0aW9ucy5hcykgewogICAgICAgIG5hbWUgPSBvcHRpb25zLmFzOwogICAgICB9CgogICAgICB2YXIgZnVsbE5hbWUgPSBnZXRGdWxsTmFtZSh0aGlzLCBuYW1lLCBvcHRpb25zLnJlc2V0TmFtZXNwYWNlKTsKICAgICAgdmFyIGVuZ2luZUluZm8gPSB7CiAgICAgICAgbmFtZTogX25hbWUsCiAgICAgICAgaW5zdGFuY2VJZDogdXVpZCsrLAogICAgICAgIG1vdW50UG9pbnQ6IGZ1bGxOYW1lLAogICAgICAgIGZ1bGxOYW1lOiBmdWxsTmFtZQogICAgICB9OwogICAgICB2YXIgcGF0aCA9IG9wdGlvbnMucGF0aDsKCiAgICAgIGlmICh0eXBlb2YgcGF0aCAhPT0gJ3N0cmluZycpIHsKICAgICAgICBwYXRoID0gIi8iICsgbmFtZTsKICAgICAgfQoKICAgICAgdmFyIGNhbGxiYWNrOwogICAgICB2YXIgZHVtbXlFcnJvclJvdXRlID0gIi9fdW51c2VkX2R1bW15X2Vycm9yX3BhdGhfcm91dGVfIiArIG5hbWUgKyAiLzplcnJvciI7CgogICAgICBpZiAoZW5naW5lUm91dGVNYXApIHsKICAgICAgICB2YXIgc2hvdWxkUmVzZXRFbmdpbmVJbmZvID0gZmFsc2U7CiAgICAgICAgdmFyIG9sZEVuZ2luZUluZm8gPSB0aGlzLm9wdGlvbnMuZW5naW5lSW5mbzsKCiAgICAgICAgaWYgKG9sZEVuZ2luZUluZm8pIHsKICAgICAgICAgIHNob3VsZFJlc2V0RW5naW5lSW5mbyA9IHRydWU7CiAgICAgICAgICB0aGlzLm9wdGlvbnMuZW5naW5lSW5mbyA9IGVuZ2luZUluZm87CiAgICAgICAgfQoKICAgICAgICB2YXIgb3B0aW9uc0ZvckNoaWxkID0gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7CiAgICAgICAgICBlbmdpbmVJbmZvOiBlbmdpbmVJbmZvCiAgICAgICAgfSwgdGhpcy5vcHRpb25zKTsKICAgICAgICB2YXIgY2hpbGREU0wgPSBuZXcgRFNMSW1wbChmdWxsTmFtZSwgb3B0aW9uc0ZvckNoaWxkKTsKICAgICAgICBjcmVhdGVSb3V0ZShjaGlsZERTTCwgJ2xvYWRpbmcnKTsKICAgICAgICBjcmVhdGVSb3V0ZShjaGlsZERTTCwgJ2Vycm9yJywgewogICAgICAgICAgcGF0aDogZHVtbXlFcnJvclJvdXRlCiAgICAgICAgfSk7CiAgICAgICAgZW5naW5lUm91dGVNYXAuY2xhc3MuY2FsbChjaGlsZERTTCk7CiAgICAgICAgY2FsbGJhY2sgPSBjaGlsZERTTC5nZW5lcmF0ZSgpOwoKICAgICAgICBpZiAoc2hvdWxkUmVzZXRFbmdpbmVJbmZvKSB7CiAgICAgICAgICB0aGlzLm9wdGlvbnMuZW5naW5lSW5mbyA9IG9sZEVuZ2luZUluZm87CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgbG9jYWxGdWxsTmFtZSA9ICdhcHBsaWNhdGlvbic7CiAgICAgIHZhciByb3V0ZUluZm8gPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHsKICAgICAgICBsb2NhbEZ1bGxOYW1lOiBsb2NhbEZ1bGxOYW1lCiAgICAgIH0sIGVuZ2luZUluZm8pOwoKICAgICAgaWYgKHRoaXMuZW5hYmxlTG9hZGluZ1N1YnN0YXRlcykgewogICAgICAgIC8vIFRoZXNlIHZhbHVlcyBhcmUgaW1wb3J0YW50IHRvIHJlZ2lzdGVyIHRoZSBsb2FkaW5nIHJvdXRlcyB1bmRlciB0aGVpcgogICAgICAgIC8vIHByb3BlciBuYW1lcyBmb3IgdGhlIFJvdXRlciBhbmQgd2l0aGluIHRoZSBFbmdpbmUncyByZWdpc3RyeS4KICAgICAgICB2YXIgc3Vic3RhdGVOYW1lID0gbmFtZSArICJfbG9hZGluZyI7CiAgICAgICAgdmFyIF9sb2NhbEZ1bGxOYW1lID0gImFwcGxpY2F0aW9uX2xvYWRpbmciOwoKICAgICAgICB2YXIgX3JvdXRlSW5mbyA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoewogICAgICAgICAgbG9jYWxGdWxsTmFtZTogX2xvY2FsRnVsbE5hbWUKICAgICAgICB9LCBlbmdpbmVJbmZvKTsKCiAgICAgICAgY3JlYXRlUm91dGUodGhpcywgc3Vic3RhdGVOYW1lLCB7CiAgICAgICAgICByZXNldE5hbWVzcGFjZTogb3B0aW9ucy5yZXNldE5hbWVzcGFjZQogICAgICAgIH0pOwogICAgICAgIHRoaXMub3B0aW9ucy5hZGRSb3V0ZUZvckVuZ2luZShzdWJzdGF0ZU5hbWUsIF9yb3V0ZUluZm8pOwogICAgICAgIHN1YnN0YXRlTmFtZSA9IG5hbWUgKyAiX2Vycm9yIjsKICAgICAgICBfbG9jYWxGdWxsTmFtZSA9ICJhcHBsaWNhdGlvbl9lcnJvciI7CiAgICAgICAgX3JvdXRlSW5mbyA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoewogICAgICAgICAgbG9jYWxGdWxsTmFtZTogX2xvY2FsRnVsbE5hbWUKICAgICAgICB9LCBlbmdpbmVJbmZvKTsKICAgICAgICBjcmVhdGVSb3V0ZSh0aGlzLCBzdWJzdGF0ZU5hbWUsIHsKICAgICAgICAgIHJlc2V0TmFtZXNwYWNlOiBvcHRpb25zLnJlc2V0TmFtZXNwYWNlLAogICAgICAgICAgcGF0aDogZHVtbXlFcnJvclJvdXRlCiAgICAgICAgfSk7CiAgICAgICAgdGhpcy5vcHRpb25zLmFkZFJvdXRlRm9yRW5naW5lKHN1YnN0YXRlTmFtZSwgX3JvdXRlSW5mbyk7CiAgICAgIH0KCiAgICAgIHRoaXMub3B0aW9ucy5hZGRSb3V0ZUZvckVuZ2luZShmdWxsTmFtZSwgcm91dGVJbmZvKTsKICAgICAgdGhpcy5wdXNoKHBhdGgsIGZ1bGxOYW1lLCBjYWxsYmFjayk7CiAgICB9OwoKICAgIHJldHVybiBEU0xJbXBsOwogIH0oKTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IERTTEltcGw7CgogIGZ1bmN0aW9uIGNhbk5lc3QoZHNsKSB7CiAgICByZXR1cm4gZHNsLnBhcmVudCAhPT0gJ2FwcGxpY2F0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGdldEZ1bGxOYW1lKGRzbCwgbmFtZSwgcmVzZXROYW1lc3BhY2UpIHsKICAgIGlmIChjYW5OZXN0KGRzbCkgJiYgcmVzZXROYW1lc3BhY2UgIT09IHRydWUpIHsKICAgICAgcmV0dXJuIGRzbC5wYXJlbnQgKyAiLiIgKyBuYW1lOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG5hbWU7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBjcmVhdGVSb3V0ZShkc2wsIG5hbWUsIG9wdGlvbnMsIGNhbGxiYWNrKSB7CiAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgIG9wdGlvbnMgPSB7fTsKICAgIH0KCiAgICB2YXIgZnVsbE5hbWUgPSBnZXRGdWxsTmFtZShkc2wsIG5hbWUsIG9wdGlvbnMucmVzZXROYW1lc3BhY2UpOwoKICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5wYXRoICE9PSAnc3RyaW5nJykgewogICAgICBvcHRpb25zLnBhdGggPSAiLyIgKyBuYW1lOwogICAgfQoKICAgIGRzbC5wdXNoKG9wdGlvbnMucGF0aCwgZnVsbE5hbWUsIGNhbGxiYWNrLCBvcHRpb25zLnNlcmlhbGl6ZSk7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vZW5naW5lcyIsIFtdLCBmdW5jdGlvbiAoKSB7CiAgInVzZSBzdHJpY3QiOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vZ2VuZXJhdGVfY29udHJvbGxlciIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwsIF9kZWJ1ZykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZ2VuZXJhdGVDb250cm9sbGVyRmFjdG9yeSA9IGdlbmVyYXRlQ29udHJvbGxlckZhY3Rvcnk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IGdlbmVyYXRlQ29udHJvbGxlcjsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgR2VuZXJhdGVzIGEgY29udHJvbGxlciBmYWN0b3J5CiAgCiAgICBAZm9yIEVtYmVyCiAgICBAbWV0aG9kIGdlbmVyYXRlQ29udHJvbGxlckZhY3RvcnkKICAgIEBwcml2YXRlCiAgKi8KICBmdW5jdGlvbiBnZW5lcmF0ZUNvbnRyb2xsZXJGYWN0b3J5KG93bmVyLCBjb250cm9sbGVyTmFtZSkgewogICAgdmFyIEZhY3RvcnkgPSBvd25lci5mYWN0b3J5Rm9yKCdjb250cm9sbGVyOmJhc2ljJykuY2xhc3M7CiAgICBGYWN0b3J5ID0gRmFjdG9yeS5leHRlbmQoewogICAgICB0b1N0cmluZzogZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgICAgcmV0dXJuICIoZ2VuZXJhdGVkICIgKyBjb250cm9sbGVyTmFtZSArICIgY29udHJvbGxlcikiOwogICAgICB9CiAgICB9KTsKICAgIHZhciBmdWxsTmFtZSA9ICJjb250cm9sbGVyOiIgKyBjb250cm9sbGVyTmFtZTsKICAgIG93bmVyLnJlZ2lzdGVyKGZ1bGxOYW1lLCBGYWN0b3J5KTsKICAgIHJldHVybiBvd25lci5mYWN0b3J5Rm9yKGZ1bGxOYW1lKTsKICB9CiAgLyoqCiAgICBHZW5lcmF0ZXMgYW5kIGluc3RhbnRpYXRlcyBhIGNvbnRyb2xsZXIgZXh0ZW5kaW5nIGZyb20gYGNvbnRyb2xsZXI6YmFzaWNgCiAgICBpZiBwcmVzZW50LCBvciBgQ29udHJvbGxlcmAgaWYgbm90LgogIAogICAgQGZvciBFbWJlcgogICAgQG1ldGhvZCBnZW5lcmF0ZUNvbnRyb2xsZXIKICAgIEBwcml2YXRlCiAgICBAc2luY2UgMS4zLjAKICAqLwoKCiAgZnVuY3Rpb24gZ2VuZXJhdGVDb250cm9sbGVyKG93bmVyLCBjb250cm9sbGVyTmFtZSkgewogICAgZ2VuZXJhdGVDb250cm9sbGVyRmFjdG9yeShvd25lciwgY29udHJvbGxlck5hbWUpOwogICAgdmFyIGZ1bGxOYW1lID0gImNvbnRyb2xsZXI6IiArIGNvbnRyb2xsZXJOYW1lOwogICAgdmFyIGluc3RhbmNlID0gb3duZXIubG9va3VwKGZ1bGxOYW1lKTsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgaWYgKCgwLCBfbWV0YWwuZ2V0KShpbnN0YW5jZSwgJ25hbWVzcGFjZS5MT0dfQUNUSVZFX0dFTkVSQVRJT04nKSkgewogICAgICAgICgwLCBfZGVidWcuaW5mbykoImdlbmVyYXRlZCAtPiAiICsgZnVsbE5hbWUsIHsKICAgICAgICAgIGZ1bGxOYW1lOiBmdWxsTmFtZQogICAgICAgIH0pOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGluc3RhbmNlOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL3F1ZXJ5X3BhcmFtcyIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIHZhciBRdWVyeVBhcmFtcyA9IGZ1bmN0aW9uIFF1ZXJ5UGFyYW1zKHZhbHVlcykgewogICAgaWYgKHZhbHVlcyA9PT0gdm9pZCAwKSB7CiAgICAgIHZhbHVlcyA9IG51bGw7CiAgICB9CgogICAgdGhpcy5pc1F1ZXJ5UGFyYW1zID0gdHJ1ZTsKICAgIHRoaXMudmFsdWVzID0gdmFsdWVzOwogIH07CgogIF9leHBvcnRzLmRlZmF1bHQgPSBRdWVyeVBhcmFtczsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL3JvdXRlLWluZm8iLCBbXSwgZnVuY3Rpb24gKCkgewogICJ1c2Ugc3RyaWN0IjsKICAvKioKICAgIEEgYFJvdXRlSW5mb1dpdGhBdHRyaWJ1dGVzYCBpcyBhbiBvYmplY3QgdGhhdCBjb250YWlucwogICAgbWV0YWRhdGEsIGluY2x1ZGluZyB0aGUgcmVzb2x2ZWQgdmFsdWUgZnJvbSB0aGUgcm91dGVzCiAgICBgbW9kZWxgIGhvb2suIExpa2UgYFJvdXRlSW5mb2AsIGEgYFJvdXRlSW5mb1dpdGhBdHRyaWJ1dGVzYAogICAgcmVwcmVzZW50cyBhIHNwZWNpZmljIHJvdXRlIHdpdGhpbiBhIFRyYW5zaXRpb24uCiAgICBJdCBpcyByZWFkLW9ubHkgYW5kIGludGVybmFsbHkgaW1tdXRhYmxlLiBJdCBpcyBhbHNvIG5vdAogICAgb2JzZXJ2YWJsZSwgYmVjYXVzZSBhIFRyYW5zaXRpb24gaW5zdGFuY2UgaXMgbmV2ZXIKICAgIGNoYW5nZWQgYWZ0ZXIgY3JlYXRpb24uCiAgCiAgICBAY2xhc3MgUm91dGVJbmZvV2l0aEF0dHJpYnV0ZXMKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSBkb3Qtc2VwYXJhdGVkLCBmdWxseS1xdWFsaWZpZWQgbmFtZSBvZiB0aGUKICAgIHJvdXRlLCBsaWtlICJwZW9wbGUuaW5kZXgiLgogICAgQHByb3BlcnR5IHtTdHJpbmd9IG5hbWUKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSBmaW5hbCBzZWdtZW50IG9mIHRoZSBmdWxseS1xdWFsaWZpZWQgbmFtZSBvZgogICAgdGhlIHJvdXRlLCBsaWtlICJpbmRleCIKICAgIEBwcm9wZXJ0eSB7U3RyaW5nfSBsb2NhbE5hbWUKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSB2YWx1ZXMgb2YgdGhlIHJvdXRlJ3MgcGFyYW1ldGVycy4gVGhlc2UgYXJlIHRoZQogICAgc2FtZSBwYXJhbXMgdGhhdCBhcmUgcmVjZWl2ZWQgYXMgYXJndW1lbnRzIHRvIHRoZQogICAgcm91dGUncyBtb2RlbCBob29rLiBDb250YWlucyBvbmx5IHRoZSBwYXJhbWV0ZXJzCiAgICB2YWxpZCBmb3IgdGhpcyByb3V0ZSwgaWYgYW55IChwYXJhbXMgZm9yIHBhcmVudCBvcgogICAgY2hpbGQgcm91dGVzIGFyZSBub3QgbWVyZ2VkKS4KICAgIEBwcm9wZXJ0eSB7T2JqZWN0fSBwYXJhbXMKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSBvcmRlcmVkIGxpc3Qgb2YgdGhlIG5hbWVzIG9mIHRoZSBwYXJhbXMKICAgIHJlcXVpcmVkIGZvciB0aGlzIHJvdXRlLiBJdCB3aWxsIGNvbnRhaW4gdGhlIHNhbWUKICAgIHN0cmluZ3MgYXMgYE9iamVjdC5rZXlzKHBhcmFtcylgLCBidXQgaGVyZSB0aGUgb3JkZXIKICAgIGlzIHNpZ25pZmljYW50LiBUaGlzIGFsbG93cyB1c2VycyB0byBjb3JyZWN0bHkgcGFzcwogICAgcGFyYW1zIGludG8gcm91dGVzIHByb2dyYW1tYXRpY2FsbHkuCiAgICBAcHJvcGVydHkge0FycmF5fSBwYXJhbU5hbWVzCiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBUaGUgdmFsdWVzIG9mIGFueSBxdWVyeVBhcmFtcyBvbiB0aGlzIHJvdXRlLgogICAgQHByb3BlcnR5IHtPYmplY3R9IHF1ZXJ5UGFyYW1zCiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBUaGlzIGlzIHRoZSByZXNvbHZlZCByZXR1cm4gdmFsdWUgZnJvbSB0aGUKICAgIHJvdXRlJ3MgbW9kZWwgaG9vay4KICAgIEBwcm9wZXJ0eSB7T2JqZWN0fEFycmF5fFN0cmluZ30gYXR0cmlidXRlcwogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgV2lsbCBjb250YWluIHRoZSByZXN1bHQgYFJvdXRlI2J1aWxkUm91dGVJbmZvTWV0YWRhdGFgCiAgICBmb3IgdGhlIGNvcnJlc3BvbmRpbmcgUm91dGUuCiAgICBAcHJvcGVydHkge0FueX0gbWV0YWRhdGEKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIEEgcmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgcm91dGUncyBSb3V0ZUluZm8uCiAgICBUaGlzIGNhbiBiZSB1c2VkIHRvIHRyYXZlcnNlIHVwd2FyZCB0byB0aGUgdG9wbW9zdAogICAgYFJvdXRlSW5mb2AuCiAgICBAcHJvcGVydHkge1JvdXRlSW5mb3xudWxsfSBwYXJlbnQKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIEEgcmVmZXJlbmNlIHRvIHRoZSBjaGlsZCByb3V0ZSdzIFJvdXRlSW5mby4KICAgIFRoaXMgY2FuIGJlIHVzZWQgdG8gdHJhdmVyc2UgZG93bndhcmQgdG8gdGhlCiAgICBsZWFmbW9zdCBgUm91dGVJbmZvYC4KICAgIEBwcm9wZXJ0eSB7Um91dGVJbmZvfG51bGx9IGNoaWxkCiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBBbGxvd3MgeW91IHRvIHRyYXZlcnNlIHRocm91Z2ggdGhlIGxpbmtlZCBsaXN0CiAgICBvZiBgUm91dGVJbmZvYHMgZnJvbSB0aGUgdG9wbW9zdCB0byBsZWFmbW9zdC4KICAgIFJldHVybnMgdGhlIGZpcnN0IGBSb3V0ZUluZm9gIGluIHRoZSBsaW5rZWQgbGlzdAogICAgZm9yIHdoaWNoIHRoZSBjYWxsYmFjayByZXR1cm5zIHRydWUuCiAgCiAgICAgIFRoaXMgbWV0aG9kIGlzIHNpbWlsYXIgdG8gdGhlIGBmaW5kKClgIG1ldGhvZAogICAgICBkZWZpbmVkIGluIEVDTUFTY3JpcHQgMjAxNS4KICAKICAgICAgVGhlIGNhbGxiYWNrIG1ldGhvZCB5b3UgcHJvdmlkZSBzaG91bGQgaGF2ZSB0aGUKICAgICAgZm9sbG93aW5nIHNpZ25hdHVyZSAoYWxsIHBhcmFtZXRlcnMgYXJlIG9wdGlvbmFsKToKICAKICAgICAgYGBgamF2YXNjcmlwdAogICAgICBmdW5jdGlvbihpdGVtLCBpbmRleCwgYXJyYXkpOwogICAgICBgYGAKICAKICAgICAgLSBgaXRlbWAgaXMgdGhlIGN1cnJlbnQgaXRlbSBpbiB0aGUgaXRlcmF0aW9uLgogICAgICAtIGBpbmRleGAgaXMgdGhlIGN1cnJlbnQgaW5kZXggaW4gdGhlIGl0ZXJhdGlvbi4KICAgICAgLSBgYXJyYXlgIGlzIHRoZSBhcnJheSBpdHNlbGYuCiAgCiAgICAgIEl0IHNob3VsZCByZXR1cm4gdGhlIGB0cnVlYCB0byBpbmNsdWRlIHRoZSBpdGVtIGluCiAgICAgIHRoZSByZXN1bHRzLCBgZmFsc2VgIG90aGVyd2lzZS4KICAKICAgICAgTm90ZSB0aGF0IGluIGFkZGl0aW9uIHRvIGEgY2FsbGJhY2ssIHlvdSBjYW4gYWxzbwogICAgICBwYXNzIGFuIG9wdGlvbmFsIHRhcmdldCBvYmplY3QgdGhhdCB3aWxsIGJlIHNldCBhcwogICAgICBgdGhpc2Agb24gdGhlIGNvbnRleHQuCiAgCiAgICBAbWV0aG9kIGZpbmQKICAgIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIHRoZSBjYWxsYmFjayB0byBleGVjdXRlCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldCpdIG9wdGlvbmFsIHRhcmdldCB0byB1c2UKICAgIEByZXR1cm5zIHtPYmplY3R9IEZvdW5kIGl0ZW0gb3IgdW5kZWZpbmVkCiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBBIFJvdXRlSW5mbyBpcyBhbiBvYmplY3QgdGhhdCBjb250YWlucyBtZXRhZGF0YQogICAgYWJvdXQgYSBzcGVjaWZpYyByb3V0ZSB3aXRoaW4gYSBUcmFuc2l0aW9uLiBJdCBpcwogICAgcmVhZC1vbmx5IGFuZCBpbnRlcm5hbGx5IGltbXV0YWJsZS4gSXQgaXMgYWxzbyBub3QKICAgIG9ic2VydmFibGUsIGJlY2F1c2UgYSBUcmFuc2l0aW9uIGluc3RhbmNlIGlzIG5ldmVyCiAgICBjaGFuZ2VkIGFmdGVyIGNyZWF0aW9uLgogIAogICAgQGNsYXNzIFJvdXRlSW5mbwogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgVGhlIGRvdC1zZXBhcmF0ZWQsIGZ1bGx5LXF1YWxpZmllZCBuYW1lIG9mIHRoZQogICAgcm91dGUsIGxpa2UgInBlb3BsZS5pbmRleCIuCiAgICBAcHJvcGVydHkge1N0cmluZ30gbmFtZQogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgVGhlIGZpbmFsIHNlZ21lbnQgb2YgdGhlIGZ1bGx5LXF1YWxpZmllZCBuYW1lIG9mCiAgICB0aGUgcm91dGUsIGxpa2UgImluZGV4IgogICAgQHByb3BlcnR5IHtTdHJpbmd9IGxvY2FsTmFtZQogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgVGhlIHZhbHVlcyBvZiB0aGUgcm91dGUncyBwYXJhbWV0ZXJzLiBUaGVzZSBhcmUgdGhlCiAgICBzYW1lIHBhcmFtcyB0aGF0IGFyZSByZWNlaXZlZCBhcyBhcmd1bWVudHMgdG8gdGhlCiAgICByb3V0ZSdzIGBtb2RlbGAgaG9vay4gQ29udGFpbnMgb25seSB0aGUgcGFyYW1ldGVycwogICAgdmFsaWQgZm9yIHRoaXMgcm91dGUsIGlmIGFueSAocGFyYW1zIGZvciBwYXJlbnQgb3IKICAgIGNoaWxkIHJvdXRlcyBhcmUgbm90IG1lcmdlZCkuCiAgICBAcHJvcGVydHkge09iamVjdH0gcGFyYW1zCiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgICBUaGUgb3JkZXJlZCBsaXN0IG9mIHRoZSBuYW1lcyBvZiB0aGUgcGFyYW1zCiAgICByZXF1aXJlZCBmb3IgdGhpcyByb3V0ZS4gSXQgd2lsbCBjb250YWluIHRoZSBzYW1lCiAgICBzdHJpbmdzIGFzIE9iamVjdC5rZXlzKHBhcmFtcyksIGJ1dCBoZXJlIHRoZSBvcmRlcgogICAgaXMgc2lnbmlmaWNhbnQuIFRoaXMgYWxsb3dzIHVzZXJzIHRvIGNvcnJlY3RseSBwYXNzCiAgICBwYXJhbXMgaW50byByb3V0ZXMgcHJvZ3JhbW1hdGljYWxseS4KICAgIEBwcm9wZXJ0eSB7QXJyYXl9IHBhcmFtTmFtZXMKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSB2YWx1ZXMgb2YgYW55IHF1ZXJ5UGFyYW1zIG9uIHRoaXMgcm91dGUuCiAgICBAcHJvcGVydHkge09iamVjdH0gcXVlcnlQYXJhbXMKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIEEgcmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgcm91dGUncyBgUm91dGVJbmZvYC4KICAgIFRoaXMgY2FuIGJlIHVzZWQgdG8gdHJhdmVyc2UgdXB3YXJkIHRvIHRoZSB0b3Btb3N0CiAgICBgUm91dGVJbmZvYC4KICAgIEBwcm9wZXJ0eSB7Um91dGVJbmZvfG51bGx9IHBhcmVudAogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgQSByZWZlcmVuY2UgdG8gdGhlIGNoaWxkIHJvdXRlJ3MgYFJvdXRlSW5mb2AuCiAgICBUaGlzIGNhbiBiZSB1c2VkIHRvIHRyYXZlcnNlIGRvd253YXJkIHRvIHRoZQogICAgbGVhZm1vc3QgYFJvdXRlSW5mb2AuCiAgICBAcHJvcGVydHkge1JvdXRlSW5mb3xudWxsfSBjaGlsZAogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgQWxsb3dzIHlvdSB0byB0cmF2ZXJzZSB0aHJvdWdoIHRoZSBsaW5rZWQgbGlzdAogICAgb2YgYFJvdXRlSW5mb2BzIGZyb20gdGhlIHRvcG1vc3QgdG8gbGVhZm1vc3QuCiAgICBSZXR1cm5zIHRoZSBmaXJzdCBgUm91dGVJbmZvYCBpbiB0aGUgbGlua2VkIGxpc3QKICAgIGZvciB3aGljaCB0aGUgY2FsbGJhY2sgcmV0dXJucyB0cnVlLgogIAogICAgICBUaGlzIG1ldGhvZCBpcyBzaW1pbGFyIHRvIHRoZSBgZmluZCgpYCBtZXRob2QKICAgICAgZGVmaW5lZCBpbiBFQ01BU2NyaXB0IDIwMTUuCiAgCiAgICAgIFRoZSBjYWxsYmFjayBtZXRob2QgeW91IHByb3ZpZGUgc2hvdWxkIGhhdmUgdGhlCiAgICAgIGZvbGxvd2luZyBzaWduYXR1cmUgKGFsbCBwYXJhbWV0ZXJzIGFyZSBvcHRpb25hbCk6CiAgCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgZnVuY3Rpb24oaXRlbSwgaW5kZXgsIGFycmF5KTsKICAgICAgYGBgCiAgCiAgICAgIC0gYGl0ZW1gIGlzIHRoZSBjdXJyZW50IGl0ZW0gaW4gdGhlIGl0ZXJhdGlvbi4KICAgICAgLSBgaW5kZXhgIGlzIHRoZSBjdXJyZW50IGluZGV4IGluIHRoZSBpdGVyYXRpb24uCiAgICAgIC0gYGFycmF5YCBpcyB0aGUgYXJyYXkgaXRzZWxmLgogIAogICAgICBJdCBzaG91bGQgcmV0dXJuIHRoZSBgdHJ1ZWAgdG8gaW5jbHVkZSB0aGUgaXRlbSBpbgogICAgICB0aGUgcmVzdWx0cywgYGZhbHNlYCBvdGhlcndpc2UuCiAgCiAgICAgIE5vdGUgdGhhdCBpbiBhZGRpdGlvbiB0byBhIGNhbGxiYWNrLCB5b3UgY2FuIGFsc28KICAgICAgcGFzcyBhbiBvcHRpb25hbCB0YXJnZXQgb2JqZWN0IHRoYXQgd2lsbCBiZSBzZXQgYXMKICAgICAgYHRoaXNgIG9uIHRoZSBjb250ZXh0LgogIAogICAgQG1ldGhvZCBmaW5kCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayB0aGUgY2FsbGJhY2sgdG8gZXhlY3V0ZQogICAgQHBhcmFtIHtPYmplY3R9IFt0YXJnZXQqXSBvcHRpb25hbCB0YXJnZXQgdG8gdXNlCiAgICBAcmV0dXJucyB7T2JqZWN0fSBGb3VuZCBpdGVtIG9yIHVuZGVmaW5lZAogICAgQHB1YmxpYwogICovCn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3N5c3RlbS9yb3V0ZSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvcG9seWZpbGxzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIiwgIkBlbWJlci9vYmplY3QvY29tcGF0IiwgIkBlbWJlci9ydW5sb29wIiwgIkBlbWJlci9zdHJpbmciLCAicm91dGVyX2pzIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3V0aWxzIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3N5c3RlbS9nZW5lcmF0ZV9jb250cm9sbGVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3BvbHlmaWxscywgX2VtYmVyQmFiZWwsIF9tZXRhbCwgX293bmVyLCBfcnVudGltZSwgX3V0aWxzLCBfZGVidWcsIF9kZXByZWNhdGVkRmVhdHVyZXMsIF9jb21wYXQsIF9ydW5sb29wLCBfc3RyaW5nLCBfcm91dGVyX2pzLCBfdXRpbHMyLCBfZ2VuZXJhdGVfY29udHJvbGxlcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdFNlcmlhbGl6ZSA9IGRlZmF1bHRTZXJpYWxpemU7CiAgX2V4cG9ydHMuaGFzRGVmYXVsdFNlcmlhbGl6ZSA9IGhhc0RlZmF1bHRTZXJpYWxpemU7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9leHBvcnRzLlJPVVRFUl9FVkVOVF9ERVBSRUNBVElPTlMgPSBfZXhwb3J0cy5ST1VURV9DT05ORUNUSU9OUyA9IHZvaWQgMDsKICB2YXIgUk9VVEVfQ09OTkVDVElPTlMgPSBuZXcgV2Vha01hcCgpOwogIF9leHBvcnRzLlJPVVRFX0NPTk5FQ1RJT05TID0gUk9VVEVfQ09OTkVDVElPTlM7CgogIGZ1bmN0aW9uIGRlZmF1bHRTZXJpYWxpemUobW9kZWwsIHBhcmFtcykgewogICAgaWYgKHBhcmFtcy5sZW5ndGggPCAxIHx8ICFtb2RlbCkgewogICAgICByZXR1cm47CiAgICB9CgogICAgdmFyIG9iamVjdCA9IHt9OwoKICAgIGlmIChwYXJhbXMubGVuZ3RoID09PSAxKSB7CiAgICAgIHZhciBuYW1lID0gcGFyYW1zWzBdOwoKICAgICAgaWYgKG5hbWUgaW4gbW9kZWwpIHsKICAgICAgICBvYmplY3RbbmFtZV0gPSAoMCwgX21ldGFsLmdldCkobW9kZWwsIG5hbWUpOwogICAgICB9IGVsc2UgaWYgKC9faWQkLy50ZXN0KG5hbWUpKSB7CiAgICAgICAgb2JqZWN0W25hbWVdID0gKDAsIF9tZXRhbC5nZXQpKG1vZGVsLCAnaWQnKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgb2JqZWN0ID0gKDAsIF9tZXRhbC5nZXRQcm9wZXJ0aWVzKShtb2RlbCwgcGFyYW1zKTsKICAgIH0KCiAgICByZXR1cm4gb2JqZWN0OwogIH0KCiAgZnVuY3Rpb24gaGFzRGVmYXVsdFNlcmlhbGl6ZShyb3V0ZSkgewogICAgcmV0dXJuIHJvdXRlLnNlcmlhbGl6ZSA9PT0gZGVmYXVsdFNlcmlhbGl6ZTsKICB9CiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvcm91dGluZwogICovCgogIC8qKgogICAgVGhlIGBSb3V0ZWAgY2xhc3MgaXMgdXNlZCB0byBkZWZpbmUgaW5kaXZpZHVhbCByb3V0ZXMuIFJlZmVyIHRvCiAgICB0aGUgW3JvdXRpbmcgZ3VpZGVdKGh0dHBzOi8vZ3VpZGVzLmVtYmVyanMuY29tL3JlbGVhc2Uvcm91dGluZy8pIGZvciBkb2N1bWVudGF0aW9uLgogIAogICAgQGNsYXNzIFJvdXRlCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHVzZXMgQWN0aW9uSGFuZGxlcgogICAgQHVzZXMgRXZlbnRlZAogICAgQHNpbmNlIDEuMC4wCiAgICBAcHVibGljCiAgKi8KCgogIHZhciBSb3V0ZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW1iZXJPYmplY3QpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShSb3V0ZSwgX0VtYmVyT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBSb3V0ZSgpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfRW1iZXJPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpcy5jb250ZXh0ID0ge307CiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KICAgIC8qKgogICAgICBUaGUgbmFtZSBvZiB0aGUgcm91dGUsIGRvdC1kZWxpbWl0ZWQuCiAgICAgICAgIEZvciBleGFtcGxlLCBhIHJvdXRlIGZvdW5kIGF0IGBhcHAvcm91dGVzL3Bvc3RzL3Bvc3QuanNgIHdpbGwgaGF2ZQogICAgICBhIGByb3V0ZU5hbWVgIG9mIGBwb3N0cy5wb3N0YC4KICAgICAgICAgQHByb3BlcnR5IHJvdXRlTmFtZQogICAgICBAZm9yIFJvdXRlCiAgICAgIEB0eXBlIFN0cmluZwogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgVGhlIG5hbWUgb2YgdGhlIHJvdXRlLCBkb3QtZGVsaW1pdGVkLCBpbmNsdWRpbmcgdGhlIGVuZ2luZSBwcmVmaXgKICAgICAgaWYgYXBwbGljYWJsZS4KICAgICAgICAgRm9yIGV4YW1wbGUsIGEgcm91dGUgZm91bmQgYXQgYGFkZG9uL3JvdXRlcy9wb3N0cy9wb3N0LmpzYCB3aXRoaW4gYW4KICAgICAgZW5naW5lIG5hbWVkIGBhZG1pbmAgd2lsbCBoYXZlIGEgYGZ1bGxSb3V0ZU5hbWVgIG9mIGBhZG1pbi5wb3N0cy5wb3N0YC4KICAgICAgICAgQHByb3BlcnR5IGZ1bGxSb3V0ZU5hbWUKICAgICAgQGZvciBSb3V0ZQogICAgICBAdHlwZSBTdHJpbmcKICAgICAgQHNpbmNlIDIuMTAuMAogICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBTZXRzIHRoZSBuYW1lIGZvciB0aGlzIHJvdXRlLCBpbmNsdWRpbmcgYSBmdWxseSByZXNvbHZlZCBuYW1lIGZvciByb3V0ZXMKICAgICAgaW5zaWRlIGVuZ2luZXMuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX3NldFJvdXRlTmFtZQogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZQogICAgKi8KCgogICAgdmFyIF9wcm90byA9IFJvdXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uX3NldFJvdXRlTmFtZSA9IGZ1bmN0aW9uIF9zZXRSb3V0ZU5hbWUobmFtZSkgewogICAgICB0aGlzLnJvdXRlTmFtZSA9IG5hbWU7CiAgICAgIHRoaXMuZnVsbFJvdXRlTmFtZSA9IGdldEVuZ2luZVJvdXRlTmFtZSgoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKSwgbmFtZSk7CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgQG1ldGhvZCBfc3Rhc2hOYW1lcwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3N0YXNoTmFtZXMgPSBmdW5jdGlvbiBfc3Rhc2hOYW1lcyhyb3V0ZUluZm8sIGR5bmFtaWNQYXJlbnQpIHsKICAgICAgaWYgKHRoaXMuX25hbWVzKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgbmFtZXMgPSB0aGlzLl9uYW1lcyA9IHJvdXRlSW5mb1snX25hbWVzJ107CgogICAgICBpZiAoIW5hbWVzLmxlbmd0aCkgewogICAgICAgIHJvdXRlSW5mbyA9IGR5bmFtaWNQYXJlbnQ7CiAgICAgICAgbmFtZXMgPSByb3V0ZUluZm8gJiYgcm91dGVJbmZvWydfbmFtZXMnXSB8fCBbXTsKICAgICAgfQoKICAgICAgdmFyIHFwcyA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnX3FwLnFwcycpOwogICAgICB2YXIgbmFtZVBhdGhzID0gbmV3IEFycmF5KG5hbWVzLmxlbmd0aCk7CgogICAgICBmb3IgKHZhciBhID0gMDsgYSA8IG5hbWVzLmxlbmd0aDsgKythKSB7CiAgICAgICAgbmFtZVBhdGhzW2FdID0gcm91dGVJbmZvLm5hbWUgKyAiLiIgKyBuYW1lc1thXTsKICAgICAgfQoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBxcHMubGVuZ3RoOyArK2kpIHsKICAgICAgICB2YXIgcXAgPSBxcHNbaV07CgogICAgICAgIGlmIChxcC5zY29wZSA9PT0gJ21vZGVsJykgewogICAgICAgICAgcXAucGFydHMgPSBuYW1lUGF0aHM7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgQHByb3BlcnR5IF9hY3RpdmVRUENoYW5nZWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9hY3RpdmVRUENoYW5nZWQgPSBmdW5jdGlvbiBfYWN0aXZlUVBDaGFuZ2VkKHFwLCB2YWx1ZSkgewogICAgICB0aGlzLl9yb3V0ZXIuX2FjdGl2ZVFQQ2hhbmdlZChxcC5zY29wZWRQcm9wZXJ0eU5hbWUsIHZhbHVlKTsKICAgIH0KICAgIC8qKgogICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF91cGRhdGluZ1FQQ2hhbmdlZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3VwZGF0aW5nUVBDaGFuZ2VkID0gZnVuY3Rpb24gX3VwZGF0aW5nUVBDaGFuZ2VkKHFwKSB7CiAgICAgIHRoaXMuX3JvdXRlci5fdXBkYXRpbmdRUENoYW5nZWQocXAudXJsS2V5KTsKICAgIH0KICAgIC8qKgogICAgICBSZXR1cm5zIGEgaGFzaCBjb250YWluaW5nIHRoZSBwYXJhbWV0ZXJzIG9mIGFuIGFuY2VzdG9yIHJvdXRlLgogICAgICAgICBZb3UgbWF5IG5vdGljZSB0aGF0IGB0aGlzLnBhcmFtc0ZvcmAgc29tZXRpbWVzIHdvcmtzIHdoZW4gcmVmZXJyaW5nIHRvIGEKICAgICAgY2hpbGQgcm91dGUsIGJ1dCB0aGlzIGJlaGF2aW9yIHNob3VsZCBub3QgYmUgcmVsaWVkIHVwb24gYXMgb25seSBhbmNlc3RvcgogICAgICByb3V0ZXMgYXJlIGNlcnRhaW4gdG8gYmUgbG9hZGVkIGluIHRpbWUuCiAgICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlci5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdtZW1iZXInLCB7IHBhdGg6ICc6bmFtZScgfSwgZnVuY3Rpb24oKSB7CiAgICAgICAgICB0aGlzLnJvdXRlKCdpbnRlcmVzdCcsIHsgcGF0aDogJzppbnRlcmVzdCcgfSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9tZW1iZXIuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBxdWVyeVBhcmFtczogewogICAgICAgICAgbWVtYmVyUXA6IHsgcmVmcmVzaE1vZGVsOiB0cnVlIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9tZW1iZXIvaW50ZXJlc3QuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBxdWVyeVBhcmFtczogewogICAgICAgICAgaW50ZXJlc3RRcDogeyByZWZyZXNoTW9kZWw6IHRydWUgfQogICAgICAgIH0sCiAgICAgICAgICAgbW9kZWwoKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5wYXJhbXNGb3IoJ21lbWJlcicpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBJZiB3ZSB2aXNpdCBgL3R1cmluZy9tYXRocz9tZW1iZXJRcD1tZW1iZXImaW50ZXJlc3RRcD1pbnRlcmVzdGAgdGhlIG1vZGVsIGZvcgogICAgICB0aGUgYG1lbWJlci5pbnRlcmVzdGAgcm91dGUgaXMgYSBoYXNoIHdpdGg6CiAgICAgICAgICogYG5hbWVgOiBgdHVyaW5nYAogICAgICAqIGBtZW1iZXJRcGA6IGBtZW1iZXJgCiAgICAgICAgIEBtZXRob2QgcGFyYW1zRm9yCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lCiAgICAgIEByZXR1cm4ge09iamVjdH0gaGFzaCBjb250YWluaW5nIHRoZSBwYXJhbWV0ZXJzIG9mIHRoZSByb3V0ZSBgbmFtZWAKICAgICAgQHNpbmNlIDEuNC4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLnBhcmFtc0ZvciA9IGZ1bmN0aW9uIHBhcmFtc0ZvcihuYW1lKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgdmFyIHJvdXRlID0gKDAsIF9vd25lci5nZXRPd25lcikodGhpcykubG9va3VwKCJyb3V0ZToiICsgbmFtZSk7CgogICAgICBpZiAocm91dGUgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiB7fTsKICAgICAgfQoKICAgICAgdmFyIHRyYW5zaXRpb24gPSB0aGlzLl9yb3V0ZXIuX3JvdXRlck1pY3JvbGliLmFjdGl2ZVRyYW5zaXRpb247CiAgICAgIHZhciBzdGF0ZSA9IHRyYW5zaXRpb24gPyB0cmFuc2l0aW9uW19yb3V0ZXJfanMuU1RBVEVfU1lNQk9MXSA6IHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWIuc3RhdGU7CiAgICAgIHZhciBmdWxsTmFtZSA9IHJvdXRlLmZ1bGxSb3V0ZU5hbWU7CiAgICAgIHZhciBwYXJhbXMgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBzdGF0ZS5wYXJhbXNbZnVsbE5hbWVdKTsKICAgICAgdmFyIHF1ZXJ5UGFyYW1zID0gZ2V0UXVlcnlQYXJhbXNGb3Iocm91dGUsIHN0YXRlKTsKICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHF1ZXJ5UGFyYW1zKS5yZWR1Y2UoZnVuY3Rpb24gKHBhcmFtcywga2V5KSB7CiAgICAgICAgKGZhbHNlICYmICEoIXBhcmFtc1trZXldKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIlRoZSByb3V0ZSAnIiArIF90aGlzMi5yb3V0ZU5hbWUgKyAiJyBoYXMgYm90aCBhIGR5bmFtaWMgc2VnbWVudCBhbmQgcXVlcnkgcGFyYW0gd2l0aCBuYW1lICciICsga2V5ICsgIicuIFBsZWFzZSByZW5hbWUgb25lIHRvIGF2b2lkIGNvbGxpc2lvbnMuIiwgIXBhcmFtc1trZXldKSk7CiAgICAgICAgcGFyYW1zW2tleV0gPSBxdWVyeVBhcmFtc1trZXldOwogICAgICAgIHJldHVybiBwYXJhbXM7CiAgICAgIH0sIHBhcmFtcyk7CiAgICB9CiAgICAvKioKICAgICAgU2VyaWFsaXplcyB0aGUgcXVlcnkgcGFyYW1ldGVyIGtleQogICAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZVF1ZXJ5UGFyYW1LZXkKICAgICAgQHBhcmFtIHtTdHJpbmd9IGNvbnRyb2xsZXJQcm9wZXJ0eU5hbWUKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLnNlcmlhbGl6ZVF1ZXJ5UGFyYW1LZXkgPSBmdW5jdGlvbiBzZXJpYWxpemVRdWVyeVBhcmFtS2V5KGNvbnRyb2xsZXJQcm9wZXJ0eU5hbWUpIHsKICAgICAgcmV0dXJuIGNvbnRyb2xsZXJQcm9wZXJ0eU5hbWU7CiAgICB9CiAgICAvKioKICAgICAgU2VyaWFsaXplcyB2YWx1ZSBvZiB0aGUgcXVlcnkgcGFyYW1ldGVyIGJhc2VkIG9uIGRlZmF1bHRWYWx1ZVR5cGUKICAgICAgICAgQG1ldGhvZCBzZXJpYWxpemVRdWVyeVBhcmFtCiAgICAgIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZQogICAgICBAcGFyYW0ge1N0cmluZ30gdXJsS2V5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBkZWZhdWx0VmFsdWVUeXBlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5zZXJpYWxpemVRdWVyeVBhcmFtID0gZnVuY3Rpb24gc2VyaWFsaXplUXVlcnlQYXJhbSh2YWx1ZSwgX3VybEtleSwgZGVmYXVsdFZhbHVlVHlwZSkgewogICAgICAvLyB1cmxLZXkgaXNuJ3QgdXNlZCBoZXJlLCBidXQgYW55b25lIG92ZXJyaWRpbmcKICAgICAgLy8gY2FuIHVzZSBpdCB0byBwcm92aWRlIHNlcmlhbGl6YXRpb24gc3BlY2lmaWMKICAgICAgLy8gdG8gYSBjZXJ0YWluIHF1ZXJ5IHBhcmFtLgogICAgICByZXR1cm4gdGhpcy5fcm91dGVyLl9zZXJpYWxpemVRdWVyeVBhcmFtKHZhbHVlLCBkZWZhdWx0VmFsdWVUeXBlKTsKICAgIH0KICAgIC8qKgogICAgICBEZXNlcmlhbGl6ZXMgdmFsdWUgb2YgdGhlIHF1ZXJ5IHBhcmFtZXRlciBiYXNlZCBvbiBkZWZhdWx0VmFsdWVUeXBlCiAgICAgICAgIEBtZXRob2QgZGVzZXJpYWxpemVRdWVyeVBhcmFtCiAgICAgIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZQogICAgICBAcGFyYW0ge1N0cmluZ30gdXJsS2V5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBkZWZhdWx0VmFsdWVUeXBlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5kZXNlcmlhbGl6ZVF1ZXJ5UGFyYW0gPSBmdW5jdGlvbiBkZXNlcmlhbGl6ZVF1ZXJ5UGFyYW0odmFsdWUsIF91cmxLZXksIGRlZmF1bHRWYWx1ZVR5cGUpIHsKICAgICAgLy8gdXJsS2V5IGlzbid0IHVzZWQgaGVyZSwgYnV0IGFueW9uZSBvdmVycmlkaW5nCiAgICAgIC8vIGNhbiB1c2UgaXQgdG8gcHJvdmlkZSBkZXNlcmlhbGl6YXRpb24gc3BlY2lmaWMKICAgICAgLy8gdG8gYSBjZXJ0YWluIHF1ZXJ5IHBhcmFtLgogICAgICByZXR1cm4gdGhpcy5fcm91dGVyLl9kZXNlcmlhbGl6ZVF1ZXJ5UGFyYW0odmFsdWUsIGRlZmF1bHRWYWx1ZVR5cGUpOwogICAgfQogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgICAgIEBwcm9wZXJ0eSBfb3B0aW9uc0ZvclF1ZXJ5UGFyYW0KICAgICovCiAgICA7CgogICAgX3Byb3RvLl9vcHRpb25zRm9yUXVlcnlQYXJhbSA9IGZ1bmN0aW9uIF9vcHRpb25zRm9yUXVlcnlQYXJhbShxcCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICJxdWVyeVBhcmFtcy4iICsgcXAudXJsS2V5KSB8fCAoMCwgX21ldGFsLmdldCkodGhpcywgInF1ZXJ5UGFyYW1zLiIgKyBxcC5wcm9wKSB8fCB7fTsKICAgIH0KICAgIC8qKgogICAgICBBIGhvb2sgeW91IGNhbiB1c2UgdG8gcmVzZXQgY29udHJvbGxlciB2YWx1ZXMgZWl0aGVyIHdoZW4gdGhlIG1vZGVsCiAgICAgIGNoYW5nZXMgb3IgdGhlIHJvdXRlIGlzIGV4aXRpbmcuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvYXJ0aWNsZXMuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICByZXNldENvbnRyb2xsZXIoY29udHJvbGxlciwgaXNFeGl0aW5nLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICBpZiAoaXNFeGl0aW5nICYmIHRyYW5zaXRpb24udGFyZ2V0TmFtZSAhPT0gJ2Vycm9yJykgewogICAgICAgICAgICBjb250cm9sbGVyLnNldCgncGFnZScsIDEpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHJlc2V0Q29udHJvbGxlcgogICAgICBAcGFyYW0ge0NvbnRyb2xsZXJ9IGNvbnRyb2xsZXIgaW5zdGFuY2UKICAgICAgQHBhcmFtIHtCb29sZWFufSBpc0V4aXRpbmcKICAgICAgQHBhcmFtIHtPYmplY3R9IHRyYW5zaXRpb24KICAgICAgQHNpbmNlIDEuNy4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc2V0Q29udHJvbGxlciA9IGZ1bmN0aW9uIHJlc2V0Q29udHJvbGxlcihfY29udHJvbGxlciwgX2lzRXhpdGluZywgX3RyYW5zaXRpb24pIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgQG1ldGhvZCBleGl0CiAgICAqLwogICAgOwoKICAgIF9wcm90by5leGl0ID0gZnVuY3Rpb24gZXhpdCgpIHsKICAgICAgdGhpcy5kZWFjdGl2YXRlKCk7CiAgICAgIHRoaXMudHJpZ2dlcignZGVhY3RpdmF0ZScpOwogICAgICB0aGlzLnRlYXJkb3duVmlld3MoKTsKICAgIH0KICAgIC8qKgogICAgICBAcHJpdmF0ZQogICAgICAgICBAbWV0aG9kIF9pbnRlcm5hbFJlc2V0CiAgICAgIEBzaW5jZSAzLjYuMAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX2ludGVybmFsUmVzZXQgPSBmdW5jdGlvbiBfaW50ZXJuYWxSZXNldChpc0V4aXRpbmcsIHRyYW5zaXRpb24pIHsKICAgICAgdmFyIGNvbnRyb2xsZXIgPSB0aGlzLmNvbnRyb2xsZXI7CiAgICAgIGNvbnRyb2xsZXIuX3FwRGVsZWdhdGUgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ19xcC5zdGF0ZXMuaW5hY3RpdmUnKTsKICAgICAgdGhpcy5yZXNldENvbnRyb2xsZXIoY29udHJvbGxlciwgaXNFeGl0aW5nLCB0cmFuc2l0aW9uKTsKICAgIH0KICAgIC8qKgogICAgICBAcHJpdmF0ZQogICAgICAgICBAbWV0aG9kIGVudGVyCiAgICAqLwogICAgOwoKICAgIF9wcm90by5lbnRlciA9IGZ1bmN0aW9uIGVudGVyKCkgewogICAgICBST1VURV9DT05ORUNUSU9OUy5zZXQodGhpcywgW10pOwogICAgICB0aGlzLmFjdGl2YXRlKCk7CiAgICAgIHRoaXMudHJpZ2dlcignYWN0aXZhdGUnKTsKICAgIH0KICAgIC8qKgogICAgICBUaGUgYHdpbGxUcmFuc2l0aW9uYCBhY3Rpb24gaXMgZmlyZWQgYXQgdGhlIGJlZ2lubmluZyBvZiBhbnkKICAgICAgYXR0ZW1wdGVkIHRyYW5zaXRpb24gd2l0aCBhIGBUcmFuc2l0aW9uYCBvYmplY3QgYXMgdGhlIHNvbGUKICAgICAgYXJndW1lbnQuIFRoaXMgYWN0aW9uIGNhbiBiZSB1c2VkIGZvciBhYm9ydGluZywgcmVkaXJlY3RpbmcsCiAgICAgIG9yIGRlY29yYXRpbmcgdGhlIHRyYW5zaXRpb24gZnJvbSB0aGUgY3VycmVudGx5IGFjdGl2ZSByb3V0ZXMuCiAgICAgICAgIEEgZ29vZCBleGFtcGxlIGlzIHByZXZlbnRpbmcgbmF2aWdhdGlvbiB3aGVuIGEgZm9ybSBpcwogICAgICBoYWxmLWZpbGxlZCBvdXQ6CiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvY29udGFjdC1mb3JtLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgd2lsbFRyYW5zaXRpb24odHJhbnNpdGlvbikgewogICAgICAgICAgICBpZiAodGhpcy5jb250cm9sbGVyLmdldCgndXNlckhhc0VudGVyZWREYXRhJykpIHsKICAgICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZGlzcGxheU5hdmlnYXRpb25Db25maXJtKCk7CiAgICAgICAgICAgICAgdHJhbnNpdGlvbi5hYm9ydCgpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIFlvdSBjYW4gYWxzbyByZWRpcmVjdCBlbHNld2hlcmUgYnkgY2FsbGluZwogICAgICBgdGhpcy50cmFuc2l0aW9uVG8oJ2Vsc2V3aGVyZScpYCBmcm9tIHdpdGhpbiBgd2lsbFRyYW5zaXRpb25gLgogICAgICBOb3RlIHRoYXQgYHdpbGxUcmFuc2l0aW9uYCB3aWxsIG5vdCBiZSBmaXJlZCBmb3IgdGhlCiAgICAgIHJlZGlyZWN0aW5nIGB0cmFuc2l0aW9uVG9gLCBzaW5jZSBgd2lsbFRyYW5zaXRpb25gIGRvZXNuJ3QKICAgICAgZmlyZSB3aGVuIHRoZXJlIGlzIGFscmVhZHkgYSB0cmFuc2l0aW9uIHVuZGVyd2F5LiBJZiB5b3Ugd2FudAogICAgICBzdWJzZXF1ZW50IGB3aWxsVHJhbnNpdGlvbmAgYWN0aW9ucyB0byBmaXJlIGZvciB0aGUgcmVkaXJlY3RpbmcKICAgICAgdHJhbnNpdGlvbiwgeW91IG11c3QgZmlyc3QgZXhwbGljaXRseSBjYWxsCiAgICAgIGB0cmFuc2l0aW9uLmFib3J0KClgLgogICAgICAgICBUbyBhbGxvdyB0aGUgYHdpbGxUcmFuc2l0aW9uYCBldmVudCB0byBjb250aW51ZSBidWJibGluZyB0byB0aGUgcGFyZW50CiAgICAgIHJvdXRlLCB1c2UgYHJldHVybiB0cnVlO2AuIFdoZW4gdGhlIGB3aWxsVHJhbnNpdGlvbmAgbWV0aG9kIGhhcyBhCiAgICAgIHJldHVybiB2YWx1ZSBvZiBgdHJ1ZWAgdGhlbiB0aGUgcGFyZW50IHJvdXRlJ3MgYHdpbGxUcmFuc2l0aW9uYCBtZXRob2QKICAgICAgd2lsbCBiZSBmaXJlZCwgZW5hYmxpbmcgImJ1YmJsaW5nIiBiZWhhdmlvciBmb3IgdGhlIGV2ZW50LgogICAgICAgICBAZXZlbnQgd2lsbFRyYW5zaXRpb24KICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBUaGUgYGRpZFRyYW5zaXRpb25gIGFjdGlvbiBpcyBmaXJlZCBhZnRlciBhIHRyYW5zaXRpb24gaGFzCiAgICAgIHN1Y2Nlc3NmdWxseSBiZWVuIGNvbXBsZXRlZC4gVGhpcyBvY2N1cnMgYWZ0ZXIgdGhlIG5vcm1hbCBtb2RlbAogICAgICBob29rcyAoYGJlZm9yZU1vZGVsYCwgYG1vZGVsYCwgYGFmdGVyTW9kZWxgLCBgc2V0dXBDb250cm9sbGVyYCkKICAgICAgaGF2ZSByZXNvbHZlZC4gVGhlIGBkaWRUcmFuc2l0aW9uYCBhY3Rpb24gaGFzIG5vIGFyZ3VtZW50cywKICAgICAgaG93ZXZlciwgaXQgY2FuIGJlIHVzZWZ1bCBmb3IgdHJhY2tpbmcgcGFnZSB2aWV3cyBvciByZXNldHRpbmcKICAgICAgc3RhdGUgb24gdGhlIGNvbnRyb2xsZXIuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvbG9naW4uanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBkaWRUcmFuc2l0aW9uKCkgewogICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZ2V0KCdlcnJvcnMuYmFzZScpLmNsZWFyKCk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOyAvLyBCdWJibGUgdGhlIGRpZFRyYW5zaXRpb24gZXZlbnQKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQGV2ZW50IGRpZFRyYW5zaXRpb24KICAgICAgQHNpbmNlIDEuMi4wCiAgICAgIEBwdWJsaWMKICAgICovCgogICAgLyoqCiAgICAgIFRoZSBgbG9hZGluZ2AgYWN0aW9uIGlzIGZpcmVkIG9uIHRoZSByb3V0ZSB3aGVuIGEgcm91dGUncyBgbW9kZWxgCiAgICAgIGhvb2sgcmV0dXJucyBhIHByb21pc2UgdGhhdCBpcyBub3QgYWxyZWFkeSByZXNvbHZlZC4gVGhlIGN1cnJlbnQKICAgICAgYFRyYW5zaXRpb25gIG9iamVjdCBpcyB0aGUgZmlyc3QgcGFyYW1ldGVyIGFuZCB0aGUgcm91dGUgdGhhdAogICAgICB0cmlnZ2VyZWQgdGhlIGxvYWRpbmcgZXZlbnQgaXMgdGhlIHNlY29uZCBwYXJhbWV0ZXIuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBsb2FkaW5nKHRyYW5zaXRpb24sIHJvdXRlKSB7CiAgICAgICAgICAgIGxldCBjb250cm9sbGVyID0gdGhpcy5jb250cm9sbGVyRm9yKCdmb28nKTsKICAgICAgICAgICAgY29udHJvbGxlci5zZXQoJ2N1cnJlbnRseUxvYWRpbmcnLCB0cnVlKTsKICAgICAgICAgICAgICAgdHJhbnNpdGlvbi5maW5hbGx5KGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIGNvbnRyb2xsZXIuc2V0KCdjdXJyZW50bHlMb2FkaW5nJywgZmFsc2UpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQGV2ZW50IGxvYWRpbmcKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEBwYXJhbSB7Um91dGV9IHJvdXRlIFRoZSByb3V0ZSB0aGF0IHRyaWdnZXJlZCB0aGUgbG9hZGluZyBldmVudAogICAgICBAc2luY2UgMS4yLjAKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgV2hlbiBhdHRlbXB0aW5nIHRvIHRyYW5zaXRpb24gaW50byBhIHJvdXRlLCBhbnkgb2YgdGhlIGhvb2tzCiAgICAgIG1heSByZXR1cm4gYSBwcm9taXNlIHRoYXQgcmVqZWN0cywgYXQgd2hpY2ggcG9pbnQgYW4gYGVycm9yYAogICAgICBhY3Rpb24gd2lsbCBiZSBmaXJlZCBvbiB0aGUgcGFydGlhbGx5LWVudGVyZWQgcm91dGVzLCBhbGxvd2luZwogICAgICBmb3IgcGVyLXJvdXRlIGVycm9yIGhhbmRsaW5nIGxvZ2ljLCBvciBzaGFyZWQgZXJyb3IgaGFuZGxpbmcKICAgICAgbG9naWMgZGVmaW5lZCBvbiBhIHBhcmVudCByb3V0ZS4KICAgICAgICAgSGVyZSBpcyBhbiBleGFtcGxlIG9mIGFuIGVycm9yIGhhbmRsZXIgdGhhdCB3aWxsIGJlIGludm9rZWQKICAgICAgZm9yIHJlamVjdGVkIHByb21pc2VzIGZyb20gdGhlIHZhcmlvdXMgaG9va3Mgb24gdGhlIHJvdXRlLAogICAgICBhcyB3ZWxsIGFzIGFueSB1bmhhbmRsZWQgZXJyb3JzIGZyb20gY2hpbGQgcm91dGVzOgogICAgICAgICBgYGBhcHAvcm91dGVzL2FkbWluLmpzCiAgICAgIGltcG9ydCB7IHJlamVjdCB9IGZyb20gJ3JzdnAnOwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGJlZm9yZU1vZGVsKCkgewogICAgICAgICAgcmV0dXJuIHJlamVjdCgnYmFkIHRoaW5ncyEnKTsKICAgICAgICB9LAogICAgICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIGVycm9yKGVycm9yLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICAgIC8vIEFzc3VtaW5nIHdlIGdvdCBoZXJlIGR1ZSB0byB0aGUgZXJyb3IgaW4gYGJlZm9yZU1vZGVsYCwKICAgICAgICAgICAgLy8gd2UgY2FuIGV4cGVjdCB0aGF0IGVycm9yID09PSAiYmFkIHRoaW5ncyEiLAogICAgICAgICAgICAvLyBidXQgYSBwcm9taXNlIG1vZGVsIHJlamVjdGluZyB3b3VsZCBhbHNvCiAgICAgICAgICAgIC8vIGNhbGwgdGhpcyBob29rLCBhcyB3b3VsZCBhbnkgZXJyb3JzIGVuY291bnRlcmVkCiAgICAgICAgICAgIC8vIGluIGBhZnRlck1vZGVsYC4KICAgICAgICAgICAgICAgLy8gVGhlIGBlcnJvcmAgaG9vayBpcyBhbHNvIHByb3ZpZGVkIHRoZSBmYWlsZWQKICAgICAgICAgICAgLy8gYHRyYW5zaXRpb25gLCB3aGljaCBjYW4gYmUgc3RvcmVkIGFuZCBsYXRlcgogICAgICAgICAgICAvLyBgLnJldHJ5KClgZCBpZiBkZXNpcmVkLgogICAgICAgICAgICAgICB0aGlzLnRyYW5zaXRpb25UbygnbG9naW4nKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgYGVycm9yYCBhY3Rpb25zIHRoYXQgYnViYmxlIHVwIGFsbCB0aGUgd2F5IHRvIGBBcHBsaWNhdGlvblJvdXRlYAogICAgICB3aWxsIGZpcmUgYSBkZWZhdWx0IGVycm9yIGhhbmRsZXIgdGhhdCBsb2dzIHRoZSBlcnJvci4gWW91IGNhbgogICAgICBzcGVjaWZ5IHlvdXIgb3duIGdsb2JhbCBkZWZhdWx0IGVycm9yIGhhbmRsZXIgYnkgb3ZlcnJpZGluZyB0aGUKICAgICAgYGVycm9yYCBoYW5kbGVyIG9uIGBBcHBsaWNhdGlvblJvdXRlYDoKICAgICAgICAgYGBgYXBwL3JvdXRlcy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIGVycm9yKGVycm9yLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICAgIHRoaXMuY29udHJvbGxlckZvcignYmFubmVyJykuZGlzcGxheUVycm9yKGVycm9yLm1lc3NhZ2UpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICBAZXZlbnQgZXJyb3IKICAgICAgQHBhcmFtIHtFcnJvcn0gZXJyb3IKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBUaGlzIGV2ZW50IGlzIHRyaWdnZXJlZCB3aGVuIHRoZSByb3V0ZXIgZW50ZXJzIHRoZSByb3V0ZS4gSXQgaXMKICAgICAgbm90IGV4ZWN1dGVkIHdoZW4gdGhlIG1vZGVsIGZvciB0aGUgcm91dGUgY2hhbmdlcy4KICAgICAgICAgYGBgYXBwL3JvdXRlcy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgeyBvbiB9IGZyb20gJ0BlbWJlci9vYmplY3QvZXZlbnRlZCc7CiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgY29sbGVjdEFuYWx5dGljczogb24oJ2FjdGl2YXRlJywgZnVuY3Rpb24oKXsKICAgICAgICAgIGNvbGxlY3RBbmFseXRpY3MoKTsKICAgICAgICB9KQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIEBldmVudCBhY3RpdmF0ZQogICAgICBAc2luY2UgMS45LjAKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgVGhpcyBldmVudCBpcyB0cmlnZ2VyZWQgd2hlbiB0aGUgcm91dGVyIGNvbXBsZXRlbHkgZXhpdHMgdGhpcwogICAgICByb3V0ZS4gSXQgaXMgbm90IGV4ZWN1dGVkIHdoZW4gdGhlIG1vZGVsIGZvciB0aGUgcm91dGUgY2hhbmdlcy4KICAgICAgICAgYGBgYXBwL3JvdXRlcy9pbmRleC5qcwogICAgICBpbXBvcnQgeyBvbiB9IGZyb20gJ0BlbWJlci9vYmplY3QvZXZlbnRlZCc7CiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgdHJhY2tQYWdlTGVhdmVBbmFseXRpY3M6IG9uKCdkZWFjdGl2YXRlJywgZnVuY3Rpb24oKXsKICAgICAgICAgIHRyYWNrUGFnZUxlYXZlQW5hbHl0aWNzKCk7CiAgICAgICAgfSkKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAZXZlbnQgZGVhY3RpdmF0ZQogICAgICBAc2luY2UgMS45LjAKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgVGhpcyBob29rIGlzIGV4ZWN1dGVkIHdoZW4gdGhlIHJvdXRlciBjb21wbGV0ZWx5IGV4aXRzIHRoaXMgcm91dGUuIEl0IGlzCiAgICAgIG5vdCBleGVjdXRlZCB3aGVuIHRoZSBtb2RlbCBmb3IgdGhlIHJvdXRlIGNoYW5nZXMuCiAgICAgICAgIEBtZXRob2QgZGVhY3RpdmF0ZQogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZGVhY3RpdmF0ZSA9IGZ1bmN0aW9uIGRlYWN0aXZhdGUoKSB7fQogICAgLyoqCiAgICAgIFRoaXMgaG9vayBpcyBleGVjdXRlZCB3aGVuIHRoZSByb3V0ZXIgZW50ZXJzIHRoZSByb3V0ZS4gSXQgaXMgbm90IGV4ZWN1dGVkCiAgICAgIHdoZW4gdGhlIG1vZGVsIGZvciB0aGUgcm91dGUgY2hhbmdlcy4KICAgICAgICAgQG1ldGhvZCBhY3RpdmF0ZQogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uYWN0aXZhdGUgPSBmdW5jdGlvbiBhY3RpdmF0ZSgpIHt9CiAgICAvKioKICAgICAgVHJhbnNpdGlvbiB0aGUgYXBwbGljYXRpb24gaW50byBhbm90aGVyIHJvdXRlLiBUaGUgcm91dGUgbWF5CiAgICAgIGJlIGVpdGhlciBhIHNpbmdsZSByb3V0ZSBvciByb3V0ZSBwYXRoOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCdibG9nUG9zdHMnKTsKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ2Jsb2dQb3N0cy5yZWNlbnRFbnRyaWVzJyk7CiAgICAgIGBgYAogICAgICAgICBPcHRpb25hbGx5IHN1cHBseSBhIG1vZGVsIGZvciB0aGUgcm91dGUgaW4gcXVlc3Rpb24uIFRoZSBtb2RlbAogICAgICB3aWxsIGJlIHNlcmlhbGl6ZWQgaW50byB0aGUgVVJMIHVzaW5nIHRoZSBgc2VyaWFsaXplYCBob29rIG9mCiAgICAgIHRoZSByb3V0ZToKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICB0aGlzLnRyYW5zaXRpb25UbygnYmxvZ1Bvc3QnLCBhUG9zdCk7CiAgICAgIGBgYAogICAgICAgICBJZiBhIGxpdGVyYWwgaXMgcGFzc2VkIChzdWNoIGFzIGEgbnVtYmVyIG9yIGEgc3RyaW5nKSwgaXQgd2lsbAogICAgICBiZSB0cmVhdGVkIGFzIGFuIGlkZW50aWZpZXIgaW5zdGVhZC4gSW4gdGhpcyBjYXNlLCB0aGUgYG1vZGVsYAogICAgICBob29rIG9mIHRoZSByb3V0ZSB3aWxsIGJlIHRyaWdnZXJlZDoKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICB0aGlzLnRyYW5zaXRpb25UbygnYmxvZ1Bvc3QnLCAxKTsKICAgICAgYGBgCiAgICAgICAgIE11bHRpcGxlIG1vZGVscyB3aWxsIGJlIGFwcGxpZWQgbGFzdCB0byBmaXJzdCByZWN1cnNpdmVseSB1cCB0aGUKICAgICAgcm91dGUgdHJlZS4KICAgICAgICAgYGBgYXBwL3JvdXRlcy5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdibG9nUG9zdCcsIHsgcGF0aDonOmJsb2dQb3N0SWQnIH0sIGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhpcy5yb3V0ZSgnYmxvZ0NvbW1lbnQnLCB7IHBhdGg6ICc6YmxvZ0NvbW1lbnRJZCcgfSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCdibG9nQ29tbWVudCcsIGFQb3N0LCBhQ29tbWVudCk7CiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCdibG9nQ29tbWVudCcsIDEsIDEzKTsKICAgICAgYGBgCiAgICAgICAgIEl0IGlzIGFsc28gcG9zc2libGUgdG8gcGFzcyBhIFVSTCAoYSBzdHJpbmcgdGhhdCBzdGFydHMgd2l0aCBhCiAgICAgIGAvYCkuCiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJy8nKTsKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJy9ibG9nL3Bvc3QvMS9jb21tZW50LzEzJyk7CiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCcvYmxvZy9wb3N0cz9zb3J0PXRpdGxlJyk7CiAgICAgIGBgYAogICAgICAgICBBbiBvcHRpb25zIGhhc2ggd2l0aCBhIGBxdWVyeVBhcmFtc2AgcHJvcGVydHkgbWF5IGJlIHByb3ZpZGVkIGFzCiAgICAgIHRoZSBmaW5hbCBhcmd1bWVudCB0byBhZGQgcXVlcnkgcGFyYW1ldGVycyB0byB0aGUgZGVzdGluYXRpb24gVVJMLgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCdibG9nUG9zdCcsIDEsIHsKICAgICAgICBxdWVyeVBhcmFtczogeyBzaG93Q29tbWVudHM6ICd0cnVlJyB9CiAgICAgIH0pOwogICAgICAgICAvLyBpZiB5b3UganVzdCB3YW50IHRvIHRyYW5zaXRpb24gdGhlIHF1ZXJ5IHBhcmFtZXRlcnMgd2l0aG91dCBjaGFuZ2luZyB0aGUgcm91dGUKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oeyBxdWVyeVBhcmFtczogeyBzb3J0OiAnZGF0ZScgfSB9KTsKICAgICAgYGBgCiAgICAgICAgIFNlZSBhbHNvIFtyZXBsYWNlV2l0aF0oI21ldGhvZF9yZXBsYWNlV2l0aCkuCiAgICAgICAgIFNpbXBsZSBUcmFuc2l0aW9uIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlcy5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdpbmRleCcpOwogICAgICAgIHRoaXMucm91dGUoJ3NlY3JldCcpOwogICAgICAgIHRoaXMucm91dGUoJ2ZvdXJPaEZvdXInLCB7IHBhdGg6ICcqOicgfSk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL2luZGV4LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIG1vdmVUb1NlY3JldChjb250ZXh0KSB7CiAgICAgICAgICAgIGlmIChhdXRob3JpemVkKCkpIHsKICAgICAgICAgICAgICB0aGlzLnRyYW5zaXRpb25Ubygnc2VjcmV0JywgY29udGV4dCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ2ZvdXJPaEZvdXInKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBUcmFuc2l0aW9uIHRvIGEgbmVzdGVkIHJvdXRlCiAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgLy8gLi4uCiAgICAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgnYXJ0aWNsZXMnLCB7IHBhdGg6ICcvYXJ0aWNsZXMnIH0sIGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhpcy5yb3V0ZSgnbmV3Jyk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL2luZGV4LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgdHJhbnNpdGlvblRvTmV3QXJ0aWNsZSgpIHsKICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ2FydGljbGVzLm5ldycpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBNdWx0aXBsZSBNb2RlbHMgRXhhbXBsZQogICAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgIC8vIC4uLgogICAgICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoJ2luZGV4Jyk7CiAgICAgICAgICAgdGhpcy5yb3V0ZSgnYnJlYWtmYXN0JywgeyBwYXRoOiAnOmJyZWFrZmFzdElkJyB9LCBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMucm91dGUoJ2NlcmVhbCcsIHsgcGF0aDogJzpjZXJlYWxJZCcgfSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL2luZGV4LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgbW92ZVRvQ2hvY29sYXRlQ2VyZWFsKCkgewogICAgICAgICAgICBsZXQgY2VyZWFsID0geyBjZXJlYWxJZDogJ0Nob2NvbGF0ZVl1bW1pbmVzcycgfTsKICAgICAgICAgICAgbGV0IGJyZWFrZmFzdCA9IHsgYnJlYWtmYXN0SWQ6ICdDZXJlYWxBbmRNaWxrJyB9OwogICAgICAgICAgICAgICB0aGlzLnRyYW5zaXRpb25UbygnYnJlYWtmYXN0LmNlcmVhbCcsIGJyZWFrZmFzdCwgY2VyZWFsKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgTmVzdGVkIFJvdXRlIHdpdGggUXVlcnkgU3RyaW5nIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlcy5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdmcnVpdHMnLCBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMucm91dGUoJ2FwcGxlcycpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9pbmRleC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHRyYW5zaXRpb25Ub0FwcGxlcygpIHsKICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ2ZydWl0cy5hcHBsZXMnLCB7IHF1ZXJ5UGFyYW1zOiB7IGNvbG9yOiAncmVkJyB9IH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHRyYW5zaXRpb25UbwogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSB0aGUgbmFtZSBvZiB0aGUgcm91dGUgb3IgYSBVUkwKICAgICAgQHBhcmFtIHsuLi5PYmplY3R9IG1vZGVscyB0aGUgbW9kZWwocykgb3IgaWRlbnRpZmllcihzKSB0byBiZSB1c2VkIHdoaWxlCiAgICAgICAgdHJhbnNpdGlvbmluZyB0byB0aGUgcm91dGUuCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gb3B0aW9uYWwgaGFzaCB3aXRoIGEgcXVlcnlQYXJhbXMgcHJvcGVydHkKICAgICAgICBjb250YWluaW5nIGEgbWFwcGluZyBvZiBxdWVyeSBwYXJhbWV0ZXJzCiAgICAgIEByZXR1cm4ge1RyYW5zaXRpb259IHRoZSB0cmFuc2l0aW9uIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhpcwogICAgICAgIGF0dGVtcHRlZCB0cmFuc2l0aW9uCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by50cmFuc2l0aW9uVG8gPSBmdW5jdGlvbiB0cmFuc2l0aW9uVG8oKSB7CiAgICAgIHZhciBfdGhpcyRfcm91dGVyOwoKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgICAgfQoKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFycwogICAgICByZXR1cm4gKF90aGlzJF9yb3V0ZXIgPSB0aGlzLl9yb3V0ZXIpLnRyYW5zaXRpb25Uby5hcHBseShfdGhpcyRfcm91dGVyLCAoMCwgX3V0aWxzMi5wcmVmaXhSb3V0ZU5hbWVBcmcpKHRoaXMsIGFyZ3MpKTsKICAgIH0KICAgIC8qKgogICAgICBQZXJmb3JtIGEgc3luY2hyb25vdXMgdHJhbnNpdGlvbiBpbnRvIGFub3RoZXIgcm91dGUgd2l0aG91dCBhdHRlbXB0aW5nCiAgICAgIHRvIHJlc29sdmUgcHJvbWlzZXMsIHVwZGF0ZSB0aGUgVVJMLCBvciBhYm9ydCBhbnkgY3VycmVudGx5IGFjdGl2ZQogICAgICBhc3luY2hyb25vdXMgdHJhbnNpdGlvbnMgKGkuZS4gcmVndWxhciB0cmFuc2l0aW9ucyBjYXVzZWQgYnkKICAgICAgYHRyYW5zaXRpb25Ub2Agb3IgVVJMIGNoYW5nZXMpLgogICAgICAgICBUaGlzIG1ldGhvZCBpcyBoYW5keSBmb3IgcGVyZm9ybWluZyBpbnRlcm1lZGlhdGUgdHJhbnNpdGlvbnMgb24gdGhlCiAgICAgIHdheSB0byBhIGZpbmFsIGRlc3RpbmF0aW9uIHJvdXRlLCBhbmQgaXMgY2FsbGVkIGludGVybmFsbHkgYnkgdGhlCiAgICAgIGRlZmF1bHQgaW1wbGVtZW50YXRpb25zIG9mIHRoZSBgZXJyb3JgIGFuZCBgbG9hZGluZ2AgaGFuZGxlcnMuCiAgICAgICAgIEBtZXRob2QgaW50ZXJtZWRpYXRlVHJhbnNpdGlvblRvCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZQogICAgICBAcGFyYW0gey4uLk9iamVjdH0gbW9kZWxzIHRoZSBtb2RlbChzKSB0byBiZSB1c2VkIHdoaWxlIHRyYW5zaXRpb25pbmcKICAgICAgdG8gdGhlIHJvdXRlLgogICAgICBAc2luY2UgMS4yLjAKICAgICAgQHB1YmxpYwogICAgICovCiAgICA7CgogICAgX3Byb3RvLmludGVybWVkaWF0ZVRyYW5zaXRpb25UbyA9IGZ1bmN0aW9uIGludGVybWVkaWF0ZVRyYW5zaXRpb25UbygpIHsKICAgICAgdmFyIF90aGlzJF9yb3V0ZXIyOwoKICAgICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4yKSwgX2tleTIgPSAwOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7CiAgICAgICAgYXJnc1tfa2V5Ml0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICB9CgogICAgICB2YXIgX3ByZWZpeFJvdXRlTmFtZUFyZyA9ICgwLCBfdXRpbHMyLnByZWZpeFJvdXRlTmFtZUFyZykodGhpcywgYXJncyksCiAgICAgICAgICBuYW1lID0gX3ByZWZpeFJvdXRlTmFtZUFyZ1swXSwKICAgICAgICAgIHByZXBhcmVkQXJncyA9IF9wcmVmaXhSb3V0ZU5hbWVBcmcuc2xpY2UoMSk7CgogICAgICAoX3RoaXMkX3JvdXRlcjIgPSB0aGlzLl9yb3V0ZXIpLmludGVybWVkaWF0ZVRyYW5zaXRpb25Uby5hcHBseShfdGhpcyRfcm91dGVyMiwgW25hbWVdLmNvbmNhdChwcmVwYXJlZEFyZ3MpKTsKICAgIH0KICAgIC8qKgogICAgICBSZWZyZXNoIHRoZSBtb2RlbCBvbiB0aGlzIHJvdXRlIGFuZCBhbnkgY2hpbGQgcm91dGVzLCBmaXJpbmcgdGhlCiAgICAgIGBiZWZvcmVNb2RlbGAsIGBtb2RlbGAsIGFuZCBgYWZ0ZXJNb2RlbGAgaG9va3MgaW4gYSBzaW1pbGFyIGZhc2hpb24KICAgICAgdG8gaG93IHJvdXRlcyBhcmUgZW50ZXJlZCB3aGVuIHRyYW5zaXRpb25pbmcgaW4gZnJvbSBvdGhlciByb3V0ZS4KICAgICAgVGhlIGN1cnJlbnQgcm91dGUgcGFyYW1zIChlLmcuIGBhcnRpY2xlX2lkYCkgd2lsbCBiZSBwYXNzZWQgaW4KICAgICAgdG8gdGhlIHJlc3BlY3RpdmUgbW9kZWwgaG9va3MsIGFuZCBpZiBhIGRpZmZlcmVudCBtb2RlbCBpcyByZXR1cm5lZCwKICAgICAgYHNldHVwQ29udHJvbGxlcmAgYW5kIGFzc29jaWF0ZWQgcm91dGUgaG9va3Mgd2lsbCByZS1maXJlIGFzIHdlbGwuCiAgICAgICAgIEFuIGV4YW1wbGUgdXNhZ2Ugb2YgdGhpcyBtZXRob2QgaXMgcmUtcXVlcnlpbmcgdGhlIHNlcnZlciBmb3IgdGhlCiAgICAgIGxhdGVzdCBpbmZvcm1hdGlvbiB1c2luZyB0aGUgc2FtZSBwYXJhbWV0ZXJzIGFzIHdoZW4gdGhlIHJvdXRlCiAgICAgIHdhcyBmaXJzdCBlbnRlcmVkLgogICAgICAgICBOb3RlIHRoYXQgdGhpcyB3aWxsIGNhdXNlIGBtb2RlbGAgaG9va3MgdG8gZmlyZSBldmVuIG9uIHJvdXRlcwogICAgICB0aGF0IHdlcmUgcHJvdmlkZWQgYSBtb2RlbCBvYmplY3Qgd2hlbiB0aGUgcm91dGUgd2FzIGluaXRpYWxseQogICAgICBlbnRlcmVkLgogICAgICAgICBAbWV0aG9kIHJlZnJlc2gKICAgICAgQHJldHVybiB7VHJhbnNpdGlvbn0gdGhlIHRyYW5zaXRpb24gb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGlzCiAgICAgICAgYXR0ZW1wdGVkIHRyYW5zaXRpb24KICAgICAgQHNpbmNlIDEuNC4wCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by5yZWZyZXNoID0gZnVuY3Rpb24gcmVmcmVzaCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWIucmVmcmVzaCh0aGlzKTsKICAgIH0KICAgIC8qKgogICAgICBUcmFuc2l0aW9uIGludG8gYW5vdGhlciByb3V0ZSB3aGlsZSByZXBsYWNpbmcgdGhlIGN1cnJlbnQgVVJMLCBpZiBwb3NzaWJsZS4KICAgICAgVGhpcyB3aWxsIHJlcGxhY2UgdGhlIGN1cnJlbnQgaGlzdG9yeSBlbnRyeSBpbnN0ZWFkIG9mIGFkZGluZyBhIG5ldyBvbmUuCiAgICAgIEJlc2lkZSB0aGF0LCBpdCBpcyBpZGVudGljYWwgdG8gYHRyYW5zaXRpb25Ub2AgaW4gYWxsIG90aGVyIHJlc3BlY3RzLiBTZWUKICAgICAgJ3RyYW5zaXRpb25UbycgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIG11bHRpcGxlIG1vZGVscy4KICAgICAgICAgRXhhbXBsZQogICAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgIC8vIC4uLgogICAgICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoJ2luZGV4Jyk7CiAgICAgICAgdGhpcy5yb3V0ZSgnc2VjcmV0Jyk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL3NlY3JldC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFmdGVyTW9kZWwoKSB7CiAgICAgICAgICBpZiAoIWF1dGhvcml6ZWQoKSl7CiAgICAgICAgICAgIHRoaXMucmVwbGFjZVdpdGgoJ2luZGV4Jyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIEBtZXRob2QgcmVwbGFjZVdpdGgKICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIHJvdXRlIG9yIGEgVVJMCiAgICAgIEBwYXJhbSB7Li4uT2JqZWN0fSBtb2RlbHMgdGhlIG1vZGVsKHMpIG9yIGlkZW50aWZpZXIocykgdG8gYmUgdXNlZCB3aGlsZQogICAgICAgIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIG9wdGlvbmFsIGhhc2ggd2l0aCBhIHF1ZXJ5UGFyYW1zIHByb3BlcnR5CiAgICAgICAgY29udGFpbmluZyBhIG1hcHBpbmcgb2YgcXVlcnkgcGFyYW1ldGVycwogICAgICBAcmV0dXJuIHtUcmFuc2l0aW9ufSB0aGUgdHJhbnNpdGlvbiBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoaXMKICAgICAgICBhdHRlbXB0ZWQgdHJhbnNpdGlvbgogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVwbGFjZVdpdGggPSBmdW5jdGlvbiByZXBsYWNlV2l0aCgpIHsKICAgICAgdmFyIF90aGlzJF9yb3V0ZXIzOwoKICAgICAgZm9yICh2YXIgX2xlbjMgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4zKSwgX2tleTMgPSAwOyBfa2V5MyA8IF9sZW4zOyBfa2V5MysrKSB7CiAgICAgICAgYXJnc1tfa2V5M10gPSBhcmd1bWVudHNbX2tleTNdOwogICAgICB9CgogICAgICByZXR1cm4gKF90aGlzJF9yb3V0ZXIzID0gdGhpcy5fcm91dGVyKS5yZXBsYWNlV2l0aC5hcHBseShfdGhpcyRfcm91dGVyMywgKDAsIF91dGlsczIucHJlZml4Um91dGVOYW1lQXJnKSh0aGlzLCBhcmdzKSk7CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBob29rIGlzIHRoZSBlbnRyeSBwb2ludCBmb3Igcm91dGVyLmpzCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2Qgc2V0dXAKICAgICovCiAgICA7CgogICAgX3Byb3RvLnNldHVwID0gZnVuY3Rpb24gc2V0dXAoY29udGV4dCwgdHJhbnNpdGlvbikgewogICAgICB2YXIgY29udHJvbGxlck5hbWUgPSB0aGlzLmNvbnRyb2xsZXJOYW1lIHx8IHRoaXMucm91dGVOYW1lOwogICAgICB2YXIgZGVmaW5lZENvbnRyb2xsZXIgPSB0aGlzLmNvbnRyb2xsZXJGb3IoY29udHJvbGxlck5hbWUsIHRydWUpOwogICAgICB2YXIgY29udHJvbGxlcjsKCiAgICAgIGlmIChkZWZpbmVkQ29udHJvbGxlcikgewogICAgICAgIGNvbnRyb2xsZXIgPSBkZWZpbmVkQ29udHJvbGxlcjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb250cm9sbGVyID0gdGhpcy5nZW5lcmF0ZUNvbnRyb2xsZXIoY29udHJvbGxlck5hbWUpOwogICAgICB9IC8vIEFzc2lnbiB0aGUgcm91dGUncyBjb250cm9sbGVyIHNvIHRoYXQgaXQgY2FuIG1vcmUgZWFzaWx5IGJlCiAgICAgIC8vIHJlZmVyZW5jZWQgaW4gYWN0aW9uIGhhbmRsZXJzLiBTaWRlIGVmZmVjdHMuIFNpZGUgZWZmZWN0cyBldmVyeXdoZXJlLgoKCiAgICAgIGlmICghdGhpcy5jb250cm9sbGVyKSB7CiAgICAgICAgdmFyIHFwID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdfcXAnKTsKICAgICAgICB2YXIgcHJvcE5hbWVzID0gcXAgIT09IHVuZGVmaW5lZCA/ICgwLCBfbWV0YWwuZ2V0KShxcCwgJ3Byb3BlcnR5TmFtZXMnKSA6IFtdOwogICAgICAgIGFkZFF1ZXJ5UGFyYW1zT2JzZXJ2ZXJzKGNvbnRyb2xsZXIsIHByb3BOYW1lcyk7CiAgICAgICAgdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlcjsKICAgICAgfQoKICAgICAgdmFyIHF1ZXJ5UGFyYW1zID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdfcXAnKTsKICAgICAgdmFyIHN0YXRlcyA9IHF1ZXJ5UGFyYW1zLnN0YXRlczsKICAgICAgY29udHJvbGxlci5fcXBEZWxlZ2F0ZSA9IHN0YXRlcy5hbGxvd092ZXJyaWRlczsKCiAgICAgIGlmICh0cmFuc2l0aW9uKSB7CiAgICAgICAgLy8gVXBkYXRlIHRoZSBtb2RlbCBkZXAgdmFsdWVzIHVzZWQgdG8gY2FsY3VsYXRlIGNhY2hlIGtleXMuCiAgICAgICAgKDAsIF91dGlsczIuc3Rhc2hQYXJhbU5hbWVzKSh0aGlzLl9yb3V0ZXIsIHRyYW5zaXRpb25bX3JvdXRlcl9qcy5TVEFURV9TWU1CT0xdLnJvdXRlSW5mb3MpOwogICAgICAgIHZhciBjYWNoZSA9IHRoaXMuX2J1Y2tldENhY2hlOwogICAgICAgIHZhciBwYXJhbXMgPSB0cmFuc2l0aW9uW19yb3V0ZXJfanMuUEFSQU1TX1NZTUJPTF07CiAgICAgICAgdmFyIGFsbFBhcmFtcyA9IHF1ZXJ5UGFyYW1zLnByb3BlcnR5TmFtZXM7CiAgICAgICAgYWxsUGFyYW1zLmZvckVhY2goZnVuY3Rpb24gKHByb3ApIHsKICAgICAgICAgIHZhciBhUXAgPSBxdWVyeVBhcmFtcy5tYXBbcHJvcF07CiAgICAgICAgICBhUXAudmFsdWVzID0gcGFyYW1zOwogICAgICAgICAgdmFyIGNhY2hlS2V5ID0gKDAsIF91dGlsczIuY2FsY3VsYXRlQ2FjaGVLZXkpKGFRcC5yb3V0ZS5mdWxsUm91dGVOYW1lLCBhUXAucGFydHMsIGFRcC52YWx1ZXMpOwogICAgICAgICAgdmFyIHZhbHVlID0gY2FjaGUubG9va3VwKGNhY2hlS2V5LCBwcm9wLCBhUXAudW5kZWNvcmF0ZWREZWZhdWx0VmFsdWUpOwogICAgICAgICAgKDAsIF9tZXRhbC5zZXQpKGNvbnRyb2xsZXIsIHByb3AsIHZhbHVlKTsKICAgICAgICB9KTsKICAgICAgICB2YXIgcXBWYWx1ZXMgPSBnZXRRdWVyeVBhcmFtc0Zvcih0aGlzLCB0cmFuc2l0aW9uW19yb3V0ZXJfanMuU1RBVEVfU1lNQk9MXSk7CiAgICAgICAgKDAsIF9tZXRhbC5zZXRQcm9wZXJ0aWVzKShjb250cm9sbGVyLCBxcFZhbHVlcyk7CiAgICAgIH0KCiAgICAgIHRoaXMuc2V0dXBDb250cm9sbGVyKGNvbnRyb2xsZXIsIGNvbnRleHQsIHRyYW5zaXRpb24pOwoKICAgICAgaWYgKHRoaXMuX2Vudmlyb25tZW50Lm9wdGlvbnMuc2hvdWxkUmVuZGVyKSB7CiAgICAgICAgdGhpcy5yZW5kZXJUZW1wbGF0ZShjb250cm9sbGVyLCBjb250ZXh0KTsKICAgICAgfSAvLyBTZXR1cCBjYW4gY2F1c2UgY2hhbmdlcyB0byBRUHMgd2hpY2ggbmVlZCB0byBiZSBwcm9wb2dhdGVkIGltbWVkaWF0ZWx5IGluCiAgICAgIC8vIHNvbWUgc2l0dWF0aW9ucy4gRXZlbnR1YWxseSwgd2Ugc2hvdWxkIHdvcmsgb24gbWFraW5nIHRoZXNlIGFzeW5jIHNvbWVob3cuCgoKICAgICAgaWYgKHRydWUKICAgICAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgICAgICkgewogICAgICAgICAgKDAsIF9tZXRhbC5mbHVzaEFzeW5jT2JzZXJ2ZXJzKShmYWxzZSk7CiAgICAgICAgfQogICAgfQogICAgLyoKICAgICAgQ2FsbGVkIHdoZW4gYSBxdWVyeSBwYXJhbWV0ZXIgZm9yIHRoaXMgcm91dGUgY2hhbmdlcywgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIHRoZSByb3V0ZQogICAgICBpcyBjdXJyZW50bHkgcGFydCBvZiB0aGUgYWN0aXZlIHJvdXRlIGhpZXJhcmNoeS4gVGhpcyB3aWxsIHVwZGF0ZSB0aGUgcXVlcnkgcGFyYW1ldGVyJ3MKICAgICAgdmFsdWUgaW4gdGhlIGNhY2hlIHNvIGlmIHRoaXMgcm91dGUgYmVjb21lcyBhY3RpdmUsIHRoZSBjYWNoZSB2YWx1ZSBoYXMgYmVlbiB1cGRhdGVkLgogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3FwQ2hhbmdlZCA9IGZ1bmN0aW9uIF9xcENoYW5nZWQocHJvcCwgdmFsdWUsIHFwKSB7CiAgICAgIGlmICghcXApIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gLy8gVXBkYXRlIG1vZGVsLWRlcCBjYWNoZQoKCiAgICAgIHZhciBjYWNoZSA9IHRoaXMuX2J1Y2tldENhY2hlOwogICAgICB2YXIgY2FjaGVLZXkgPSAoMCwgX3V0aWxzMi5jYWxjdWxhdGVDYWNoZUtleSkocXAucm91dGUuZnVsbFJvdXRlTmFtZSwgcXAucGFydHMsIHFwLnZhbHVlcyk7CiAgICAgIGNhY2hlLnN0YXNoKGNhY2hlS2V5LCBwcm9wLCB2YWx1ZSk7CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBob29rIGlzIHRoZSBmaXJzdCBvZiB0aGUgcm91dGUgZW50cnkgdmFsaWRhdGlvbiBob29rcwogICAgICBjYWxsZWQgd2hlbiBhbiBhdHRlbXB0IGlzIG1hZGUgdG8gdHJhbnNpdGlvbiBpbnRvIGEgcm91dGUKICAgICAgb3Igb25lIG9mIGl0cyBjaGlsZHJlbi4gSXQgaXMgY2FsbGVkIGJlZm9yZSBgbW9kZWxgIGFuZAogICAgICBgYWZ0ZXJNb2RlbGAsIGFuZCBpcyBhcHByb3ByaWF0ZSBmb3IgY2FzZXMgd2hlbjoKICAgICAgICAgMSkgQSBkZWNpc2lvbiBjYW4gYmUgbWFkZSB0byByZWRpcmVjdCBlbHNld2hlcmUgd2l0aG91dAogICAgICAgICBuZWVkaW5nIHRvIHJlc29sdmUgdGhlIG1vZGVsIGZpcnN0LgogICAgICAyKSBBbnkgYXN5bmMgb3BlcmF0aW9ucyBuZWVkIHRvIG9jY3VyIGZpcnN0IGJlZm9yZSB0aGUKICAgICAgICAgbW9kZWwgaXMgYXR0ZW1wdGVkIHRvIGJlIHJlc29sdmVkLgogICAgICAgICBUaGlzIGhvb2sgaXMgcHJvdmlkZWQgdGhlIGN1cnJlbnQgYHRyYW5zaXRpb25gIGF0dGVtcHQKICAgICAgYXMgYSBwYXJhbWV0ZXIsIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGAuYWJvcnQoKWAgdGhlIHRyYW5zaXRpb24sCiAgICAgIHNhdmUgaXQgZm9yIGEgbGF0ZXIgYC5yZXRyeSgpYCwgb3IgcmV0cmlldmUgdmFsdWVzIHNldAogICAgICBvbiBpdCBmcm9tIGEgcHJldmlvdXMgaG9vay4gWW91IGNhbiBhbHNvIGp1c3QgY2FsbAogICAgICBgdGhpcy50cmFuc2l0aW9uVG9gIHRvIGFub3RoZXIgcm91dGUgdG8gaW1wbGljaXRseQogICAgICBhYm9ydCB0aGUgYHRyYW5zaXRpb25gLgogICAgICAgICBZb3UgY2FuIHJldHVybiBhIHByb21pc2UgZnJvbSB0aGlzIGhvb2sgdG8gcGF1c2UgdGhlCiAgICAgIHRyYW5zaXRpb24gdW50aWwgdGhlIHByb21pc2UgcmVzb2x2ZXMgKG9yIHJlamVjdHMpLiBUaGlzIGNvdWxkCiAgICAgIGJlIHVzZWZ1bCwgZm9yIGluc3RhbmNlLCBmb3IgcmV0cmlldmluZyBhc3luYyBjb2RlIGZyb20KICAgICAgdGhlIHNlcnZlciB0aGF0IGlzIHJlcXVpcmVkIHRvIGVudGVyIGEgcm91dGUuCiAgICAgICAgIEBtZXRob2QgYmVmb3JlTW9kZWwKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEByZXR1cm4ge2FueSB8IFByb21pc2U8YW55Pn0gaWYgdGhlIHZhbHVlIHJldHVybmVkIGZyb20gdGhpcyBob29rIGlzCiAgICAgICAgYSBwcm9taXNlLCB0aGUgdHJhbnNpdGlvbiB3aWxsIHBhdXNlIHVudGlsIHRoZSB0cmFuc2l0aW9uCiAgICAgICAgcmVzb2x2ZXMuIE90aGVyd2lzZSwgbm9uLXByb21pc2UgcmV0dXJuIHZhbHVlcyBhcmUgbm90CiAgICAgICAgdXRpbGl6ZWQgaW4gYW55IHdheS4KICAgICAgQHNpbmNlIDEuMC4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLmJlZm9yZU1vZGVsID0gZnVuY3Rpb24gYmVmb3JlTW9kZWwoKSB7fQogICAgLyoqCiAgICAgIFRoaXMgaG9vayBpcyBjYWxsZWQgYWZ0ZXIgdGhpcyByb3V0ZSdzIG1vZGVsIGhhcyByZXNvbHZlZC4KICAgICAgSXQgZm9sbG93cyBpZGVudGljYWwgYXN5bmMvcHJvbWlzZSBzZW1hbnRpY3MgdG8gYGJlZm9yZU1vZGVsYAogICAgICBidXQgaXMgcHJvdmlkZWQgdGhlIHJvdXRlJ3MgcmVzb2x2ZWQgbW9kZWwgaW4gYWRkaXRpb24gdG8KICAgICAgdGhlIGB0cmFuc2l0aW9uYCwgYW5kIGlzIHRoZXJlZm9yZSBzdWl0ZWQgdG8gcGVyZm9ybWluZwogICAgICBsb2dpYyB0aGF0IGNhbiBvbmx5IHRha2UgcGxhY2UgYWZ0ZXIgdGhlIG1vZGVsIGhhcyBhbHJlYWR5CiAgICAgIHJlc29sdmVkLgogICAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3RzLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWZ0ZXJNb2RlbChwb3N0cywgdHJhbnNpdGlvbikgewogICAgICAgICAgaWYgKHBvc3RzLmdldCgnbGVuZ3RoJykgPT09IDEpIHsKICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ3Bvc3Quc2hvdycsIHBvc3RzLmdldCgnZmlyc3RPYmplY3QnKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIFJlZmVyIHRvIGRvY3VtZW50YXRpb24gZm9yIGBiZWZvcmVNb2RlbGAgZm9yIGEgZGVzY3JpcHRpb24KICAgICAgb2YgdHJhbnNpdGlvbi1wYXVzaW5nIHNlbWFudGljcyB3aGVuIGEgcHJvbWlzZSBpcyByZXR1cm5lZAogICAgICBmcm9tIHRoaXMgaG9vay4KICAgICAgICAgQG1ldGhvZCBhZnRlck1vZGVsCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZXNvbHZlZE1vZGVsIHRoZSB2YWx1ZSByZXR1cm5lZCBmcm9tIGBtb2RlbGAsCiAgICAgICAgb3IgaXRzIHJlc29sdmVkIHZhbHVlIGlmIGl0IHdhcyBhIHByb21pc2UKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEByZXR1cm4ge2FueSB8IFByb21pc2U8YW55Pn0gaWYgdGhlIHZhbHVlIHJldHVybmVkIGZyb20gdGhpcyBob29rIGlzCiAgICAgICAgYSBwcm9taXNlLCB0aGUgdHJhbnNpdGlvbiB3aWxsIHBhdXNlIHVudGlsIHRoZSB0cmFuc2l0aW9uCiAgICAgICAgcmVzb2x2ZXMuIE90aGVyd2lzZSwgbm9uLXByb21pc2UgcmV0dXJuIHZhbHVlcyBhcmUgbm90CiAgICAgICAgdXRpbGl6ZWQgaW4gYW55IHdheS4KICAgICAgQHNpbmNlIDEuMC4wCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by5hZnRlck1vZGVsID0gZnVuY3Rpb24gYWZ0ZXJNb2RlbCgpIHt9CiAgICAvKioKICAgICAgQSBob29rIHlvdSBjYW4gaW1wbGVtZW50IHRvIG9wdGlvbmFsbHkgcmVkaXJlY3QgdG8gYW5vdGhlciByb3V0ZS4KICAgICAgICAgSWYgeW91IGNhbGwgYHRoaXMudHJhbnNpdGlvblRvYCBmcm9tIGluc2lkZSBvZiB0aGlzIGhvb2ssIHRoaXMgcm91dGUKICAgICAgd2lsbCBub3QgYmUgZW50ZXJlZCBpbiBmYXZvciBvZiB0aGUgb3RoZXIgaG9vay4KICAgICAgICAgYHJlZGlyZWN0YCBhbmQgYGFmdGVyTW9kZWxgIGJlaGF2ZSB2ZXJ5IHNpbWlsYXJseSBhbmQgYXJlCiAgICAgIGNhbGxlZCBhbG1vc3QgYXQgdGhlIHNhbWUgdGltZSwgYnV0IHRoZXkgaGF2ZSBhbiBpbXBvcnRhbnQKICAgICAgZGlzdGluY3Rpb24gaW4gdGhlIGNhc2UgdGhhdCwgZnJvbSBvbmUgb2YgdGhlc2UgaG9va3MsIGEKICAgICAgcmVkaXJlY3QgaW50byBhIGNoaWxkIHJvdXRlIG9mIHRoaXMgcm91dGUgb2NjdXJzOiByZWRpcmVjdHMKICAgICAgZnJvbSBgYWZ0ZXJNb2RlbGAgZXNzZW50aWFsbHkgaW52YWxpZGF0ZSB0aGUgY3VycmVudCBhdHRlbXB0CiAgICAgIHRvIGVudGVyIHRoaXMgcm91dGUsIGFuZCB3aWxsIHJlc3VsdCBpbiB0aGlzIHJvdXRlJ3MgYGJlZm9yZU1vZGVsYCwKICAgICAgYG1vZGVsYCwgYW5kIGBhZnRlck1vZGVsYCBob29rcyBiZWluZyBmaXJlZCBhZ2FpbiB3aXRoaW4KICAgICAgdGhlIG5ldywgcmVkaXJlY3RpbmcgdHJhbnNpdGlvbi4gUmVkaXJlY3RzIHRoYXQgb2NjdXIgd2l0aGluCiAgICAgIHRoZSBgcmVkaXJlY3RgIGhvb2ssIG9uIHRoZSBvdGhlciBoYW5kLCB3aWxsIF9ub3RfIGNhdXNlCiAgICAgIHRoZXNlIGhvb2tzIHRvIGJlIGZpcmVkIGFnYWluIHRoZSBzZWNvbmQgdGltZSBhcm91bmQ7IGluCiAgICAgIG90aGVyIHdvcmRzLCBieSB0aGUgdGltZSB0aGUgYHJlZGlyZWN0YCBob29rIGhhcyBiZWVuIGNhbGxlZCwKICAgICAgYm90aCB0aGUgcmVzb2x2ZWQgbW9kZWwgYW5kIGF0dGVtcHRlZCBlbnRyeSBpbnRvIHRoaXMgcm91dGUKICAgICAgYXJlIGNvbnNpZGVyZWQgdG8gYmUgZnVsbHkgdmFsaWRhdGVkLgogICAgICAgICBAbWV0aG9kIHJlZGlyZWN0CiAgICAgIEBwYXJhbSB7T2JqZWN0fSBtb2RlbCB0aGUgbW9kZWwgZm9yIHRoaXMgcm91dGUKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uIHRoZSB0cmFuc2l0aW9uIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIGN1cnJlbnQgdHJhbnNpdGlvbgogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVkaXJlY3QgPSBmdW5jdGlvbiByZWRpcmVjdCgpIHt9CiAgICAvKioKICAgICAgQ2FsbGVkIHdoZW4gdGhlIGNvbnRleHQgaXMgY2hhbmdlZCBieSByb3V0ZXIuanMuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgY29udGV4dERpZENoYW5nZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uY29udGV4dERpZENoYW5nZSA9IGZ1bmN0aW9uIGNvbnRleHREaWRDaGFuZ2UoKSB7CiAgICAgIHRoaXMuY3VycmVudE1vZGVsID0gdGhpcy5jb250ZXh0OwogICAgfQogICAgLyoqCiAgICAgIEEgaG9vayB5b3UgY2FuIGltcGxlbWVudCB0byBjb252ZXJ0IHRoZSBVUkwgaW50byB0aGUgbW9kZWwgZm9yCiAgICAgIHRoaXMgcm91dGUuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgLy8gLi4uCiAgICAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgncG9zdCcsIHsgcGF0aDogJy9wb3N0cy86cG9zdF9pZCcgfSk7CiAgICAgIH0pOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZXI7CiAgICAgIGBgYAogICAgICAgICBUaGUgbW9kZWwgZm9yIHRoZSBgcG9zdGAgcm91dGUgaXMgYHN0b3JlLmZpbmRSZWNvcmQoJ3Bvc3QnLCBwYXJhbXMucG9zdF9pZClgLgogICAgICAgICBCeSBkZWZhdWx0LCBpZiB5b3VyIHJvdXRlIGhhcyBhIGR5bmFtaWMgc2VnbWVudCBlbmRpbmcgaW4gYF9pZGA6CiAgICAgICAgICogVGhlIG1vZGVsIGNsYXNzIGlzIGRldGVybWluZWQgZnJvbSB0aGUgc2VnbWVudCAoYHBvc3RfaWRgJ3MKICAgICAgICBjbGFzcyBpcyBgQXBwLlBvc3RgKQogICAgICAqIFRoZSBmaW5kIG1ldGhvZCBpcyBjYWxsZWQgb24gdGhlIG1vZGVsIGNsYXNzIHdpdGggdGhlIHZhbHVlIG9mCiAgICAgICAgdGhlIGR5bmFtaWMgc2VnbWVudC4KICAgICAgICAgTm90ZSB0aGF0IGZvciByb3V0ZXMgd2l0aCBkeW5hbWljIHNlZ21lbnRzLCB0aGlzIGhvb2sgaXMgbm90IGFsd2F5cwogICAgICBleGVjdXRlZC4gSWYgdGhlIHJvdXRlIGlzIGVudGVyZWQgdGhyb3VnaCBhIHRyYW5zaXRpb24gKGUuZy4gd2hlbgogICAgICB1c2luZyB0aGUgYGxpbmstdG9gIEhhbmRsZWJhcnMgaGVscGVyIG9yIHRoZSBgdHJhbnNpdGlvblRvYCBtZXRob2QKICAgICAgb2Ygcm91dGVzKSwgYW5kIGEgbW9kZWwgY29udGV4dCBpcyBhbHJlYWR5IHByb3ZpZGVkIHRoaXMgaG9vawogICAgICBpcyBub3QgY2FsbGVkLgogICAgICAgICBBIG1vZGVsIGNvbnRleHQgZG9lcyBub3QgaW5jbHVkZSBhIHByaW1pdGl2ZSBzdHJpbmcgb3IgbnVtYmVyLAogICAgICB3aGljaCBkb2VzIGNhdXNlIHRoZSBtb2RlbCBob29rIHRvIGJlIGNhbGxlZC4KICAgICAgICAgUm91dGVzIHdpdGhvdXQgZHluYW1pYyBzZWdtZW50cyB3aWxsIGFsd2F5cyBleGVjdXRlIHRoZSBtb2RlbCBob29rLgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIC8vIG5vIGR5bmFtaWMgc2VnbWVudCwgbW9kZWwgaG9vayBhbHdheXMgY2FsbGVkCiAgICAgIHRoaXMudHJhbnNpdGlvblRvKCdwb3N0cycpOwogICAgICAgICAvLyBtb2RlbCBwYXNzZWQgaW4sIHNvIG1vZGVsIGhvb2sgbm90IGNhbGxlZAogICAgICB0aGVQb3N0ID0gc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIDEpOwogICAgICB0aGlzLnRyYW5zaXRpb25UbygncG9zdCcsIHRoZVBvc3QpOwogICAgICAgICAvLyBpbnRlZ2VyIHBhc3NlZCBpbiwgbW9kZWwgaG9vayBpcyBjYWxsZWQKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ3Bvc3QnLCAxKTsKICAgICAgICAgLy8gbW9kZWwgaWQgcGFzc2VkIGluLCBtb2RlbCBob29rIGlzIGNhbGxlZAogICAgICAvLyB1c2VmdWwgZm9yIGZvcmNpbmcgdGhlIGhvb2sgdG8gZXhlY3V0ZQogICAgICB0aGVQb3N0ID0gc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIDEpOwogICAgICB0aGlzLnRyYW5zaXRpb25UbygncG9zdCcsIHRoZVBvc3QuaWQpOwogICAgICBgYGAKICAgICAgICAgVGhpcyBob29rIGZvbGxvd3MgdGhlIGFzeW5jaHJvbm91cy9wcm9taXNlIHNlbWFudGljcwogICAgICBkZXNjcmliZWQgaW4gdGhlIGRvY3VtZW50YXRpb24gZm9yIGBiZWZvcmVNb2RlbGAuIEluIHBhcnRpY3VsYXIsCiAgICAgIGlmIGEgcHJvbWlzZSByZXR1cm5lZCBmcm9tIGBtb2RlbGAgZmFpbHMsIHRoZSBlcnJvciB3aWxsIGJlCiAgICAgIGhhbmRsZWQgYnkgdGhlIGBlcnJvcmAgaG9vayBvbiBgUm91dGVgLgogICAgICAgICBFeGFtcGxlCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIG1vZGVsKHBhcmFtcykgewogICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIHBhcmFtcy5wb3N0X2lkKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBtb2RlbAogICAgICBAcGFyYW0ge09iamVjdH0gcGFyYW1zIHRoZSBwYXJhbWV0ZXJzIGV4dHJhY3RlZCBmcm9tIHRoZSBVUkwKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9ufSB0cmFuc2l0aW9uCiAgICAgIEByZXR1cm4ge2FueSB8IFByb21pc2U8YW55Pn0gdGhlIG1vZGVsIGZvciB0aGlzIHJvdXRlLiBJZgogICAgICAgIGEgcHJvbWlzZSBpcyByZXR1cm5lZCwgdGhlIHRyYW5zaXRpb24gd2lsbCBwYXVzZSB1bnRpbAogICAgICAgIHRoZSBwcm9taXNlIHJlc29sdmVzLCBhbmQgdGhlIHJlc29sdmVkIHZhbHVlIG9mIHRoZSBwcm9taXNlCiAgICAgICAgd2lsbCBiZSB1c2VkIGFzIHRoZSBtb2RlbCBmb3IgdGhpcyByb3V0ZS4KICAgICAgQHNpbmNlIDEuMC4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLm1vZGVsID0gZnVuY3Rpb24gbW9kZWwocGFyYW1zLCB0cmFuc2l0aW9uKSB7CiAgICAgIHZhciBuYW1lLCBzYXdQYXJhbXMsIHZhbHVlOwogICAgICB2YXIgcXVlcnlQYXJhbXMgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ19xcC5tYXAnKTsKCiAgICAgIGZvciAodmFyIHByb3AgaW4gcGFyYW1zKSB7CiAgICAgICAgaWYgKHByb3AgPT09ICdxdWVyeVBhcmFtcycgfHwgcXVlcnlQYXJhbXMgJiYgcHJvcCBpbiBxdWVyeVBhcmFtcykgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICB2YXIgbWF0Y2ggPSBwcm9wLm1hdGNoKC9eKC4qKV9pZCQvKTsKCiAgICAgICAgaWYgKG1hdGNoICE9PSBudWxsKSB7CiAgICAgICAgICBuYW1lID0gbWF0Y2hbMV07CiAgICAgICAgICB2YWx1ZSA9IHBhcmFtc1twcm9wXTsKICAgICAgICB9CgogICAgICAgIHNhd1BhcmFtcyA9IHRydWU7CiAgICAgIH0KCiAgICAgIGlmICghbmFtZSkgewogICAgICAgIGlmIChzYXdQYXJhbXMpIHsKICAgICAgICAgIHJldHVybiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBwYXJhbXMpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAodHJhbnNpdGlvbi5yZXNvbHZlSW5kZXggPCAxKSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KCiAgICAgICAgICByZXR1cm4gdHJhbnNpdGlvbltfcm91dGVyX2pzLlNUQVRFX1NZTUJPTF0ucm91dGVJbmZvc1t0cmFuc2l0aW9uLnJlc29sdmVJbmRleCAtIDFdLmNvbnRleHQ7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5maW5kTW9kZWwobmFtZSwgdmFsdWUpOwogICAgfQogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZGVzZXJpYWxpemUKICAgICAgQHBhcmFtIHtPYmplY3R9IHBhcmFtcyB0aGUgcGFyYW1ldGVycyBleHRyYWN0ZWQgZnJvbSB0aGUgVVJMCiAgICAgIEBwYXJhbSB7VHJhbnNpdGlvbn0gdHJhbnNpdGlvbgogICAgICBAcmV0dXJuIHthbnkgfCBQcm9taXNlPGFueT59IHRoZSBtb2RlbCBmb3IgdGhpcyByb3V0ZS4KICAgICAgICAgUm91dGVyLmpzIGhvb2suCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZGVzZXJpYWxpemUgPSBmdW5jdGlvbiBkZXNlcmlhbGl6ZShfcGFyYW1zLCB0cmFuc2l0aW9uKSB7CiAgICAgIHJldHVybiB0aGlzLm1vZGVsKHRoaXMuX3BhcmFtc0Zvcih0aGlzLnJvdXRlTmFtZSwgX3BhcmFtcyksIHRyYW5zaXRpb24pOwogICAgfQogICAgLyoqCiAgICAgICAgIEBtZXRob2QgZmluZE1vZGVsCiAgICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlIHRoZSBtb2RlbCB0eXBlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZSB0aGUgdmFsdWUgcGFzc2VkIHRvIGZpbmQKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmZpbmRNb2RlbCA9IGZ1bmN0aW9uIGZpbmRNb2RlbCgpIHsKICAgICAgdmFyIF9nZXQ7CgogICAgICByZXR1cm4gKF9nZXQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ3N0b3JlJykpLmZpbmQuYXBwbHkoX2dldCwgYXJndW1lbnRzKTsKICAgIH0KICAgIC8qKgogICAgICBBIGhvb2sgeW91IGNhbiB1c2UgdG8gc2V0dXAgdGhlIGNvbnRyb2xsZXIgZm9yIHRoZSBjdXJyZW50IHJvdXRlLgogICAgICAgICBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgd2l0aCB0aGUgY29udHJvbGxlciBmb3IgdGhlIGN1cnJlbnQgcm91dGUgYW5kIHRoZQogICAgICBtb2RlbCBzdXBwbGllZCBieSB0aGUgYG1vZGVsYCBob29rLgogICAgICAgICBCeSBkZWZhdWx0LCB0aGUgYHNldHVwQ29udHJvbGxlcmAgaG9vayBzZXRzIHRoZSBgbW9kZWxgIHByb3BlcnR5IG9mCiAgICAgIHRoZSBjb250cm9sbGVyIHRvIHRoZSBzcGVjaWZpZWQgYG1vZGVsYCB3aGVuIGl0IGlzIG5vdCBgdW5kZWZpbmVkYC4KICAgICAgICAgSWYgeW91IGltcGxlbWVudCB0aGUgYHNldHVwQ29udHJvbGxlcmAgaG9vayBpbiB5b3VyIFJvdXRlLCBpdCB3aWxsCiAgICAgIHByZXZlbnQgdGhpcyBkZWZhdWx0IGJlaGF2aW9yLiBJZiB5b3Ugd2FudCB0byBwcmVzZXJ2ZSB0aGF0IGJlaGF2aW9yCiAgICAgIHdoZW4gaW1wbGVtZW50aW5nIHlvdXIgYHNldHVwQ29udHJvbGxlcmAgZnVuY3Rpb24sIG1ha2Ugc3VyZSB0byBjYWxsCiAgICAgIGBfc3VwZXJgOgogICAgICAgICBgYGBhcHAvcm91dGVzL3Bob3Rvcy5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIG1vZGVsKCkgewogICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZmluZEFsbCgncGhvdG8nKTsKICAgICAgICB9LAogICAgICAgICAgIHNldHVwQ29udHJvbGxlcihjb250cm9sbGVyLCBtb2RlbCkgewogICAgICAgICAgLy8gQ2FsbCBfc3VwZXIgZm9yIGRlZmF1bHQgYmVoYXZpb3IKICAgICAgICAgIHRoaXMuX3N1cGVyKGNvbnRyb2xsZXIsIG1vZGVsKTsKICAgICAgICAgIC8vIEltcGxlbWVudCB5b3VyIGN1c3RvbSBzZXR1cCBhZnRlcgogICAgICAgICAgdGhpcy5jb250cm9sbGVyRm9yKCdhcHBsaWNhdGlvbicpLnNldCgnc2hvd2luZ1Bob3RvcycsIHRydWUpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBUaGUgcHJvdmlkZWQgY29udHJvbGxlciB3aWxsIGJlIG9uZSByZXNvbHZlZCBiYXNlZCBvbiB0aGUgbmFtZQogICAgICBvZiB0aGlzIHJvdXRlLgogICAgICAgICBJZiBubyBleHBsaWNpdCBjb250cm9sbGVyIGlzIGRlZmluZWQsIEVtYmVyIHdpbGwgYXV0b21hdGljYWxseSBjcmVhdGUgb25lLgogICAgICAgICBBcyBhbiBleGFtcGxlLCBjb25zaWRlciB0aGUgcm91dGVyOgogICAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgIC8vIC4uLgogICAgICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoJ3Bvc3QnLCB7IHBhdGg6ICcvcG9zdHMvOnBvc3RfaWQnIH0pOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgRm9yIHRoZSBgcG9zdGAgcm91dGUsIGEgY29udHJvbGxlciBuYW1lZCBgQXBwLlBvc3RDb250cm9sbGVyYCB3b3VsZAogICAgICBiZSB1c2VkIGlmIGl0IGlzIGRlZmluZWQuIElmIGl0IGlzIG5vdCBkZWZpbmVkLCBhIGJhc2ljIGBDb250cm9sbGVyYAogICAgICBpbnN0YW5jZSB3b3VsZCBiZSB1c2VkLgogICAgICAgICBFeGFtcGxlCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIHNldHVwQ29udHJvbGxlcihjb250cm9sbGVyLCBtb2RlbCkgewogICAgICAgICAgY29udHJvbGxlci5zZXQoJ21vZGVsJywgbW9kZWwpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHNldHVwQ29udHJvbGxlcgogICAgICBAcGFyYW0ge0NvbnRyb2xsZXJ9IGNvbnRyb2xsZXIgaW5zdGFuY2UKICAgICAgQHBhcmFtIHtPYmplY3R9IG1vZGVsCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5zZXR1cENvbnRyb2xsZXIgPSBmdW5jdGlvbiBzZXR1cENvbnRyb2xsZXIoY29udHJvbGxlciwgY29udGV4dCwgX3RyYW5zaXRpb24pIHsKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFycwogICAgICBpZiAoY29udHJvbGxlciAmJiBjb250ZXh0ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAoMCwgX21ldGFsLnNldCkoY29udHJvbGxlciwgJ21vZGVsJywgY29udGV4dCk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSBjb250cm9sbGVyIG9mIHRoZSBjdXJyZW50IHJvdXRlLCBvciBhIHBhcmVudCAob3IgYW55IGFuY2VzdG9yKQogICAgICByb3V0ZSBpbiBhIHJvdXRlIGhpZXJhcmNoeS4KICAgICAgICAgVGhlIGNvbnRyb2xsZXIgaW5zdGFuY2UgbXVzdCBhbHJlYWR5IGhhdmUgYmVlbiBjcmVhdGVkLCBlaXRoZXIgdGhyb3VnaCBlbnRlcmluZyB0aGUKICAgICAgYXNzb2NpYXRlZCByb3V0ZSBvciB1c2luZyBgZ2VuZXJhdGVDb250cm9sbGVyYC4KICAgICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgc2V0dXBDb250cm9sbGVyKGNvbnRyb2xsZXIsIHBvc3QpIHsKICAgICAgICAgIHRoaXMuX3N1cGVyKGNvbnRyb2xsZXIsIHBvc3QpOwogICAgICAgICAgdGhpcy5jb250cm9sbGVyRm9yKCdwb3N0cycpLnNldCgnY3VycmVudFBvc3QnLCBwb3N0KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBjb250cm9sbGVyRm9yCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZSBvciBjb250cm9sbGVyCiAgICAgIEByZXR1cm4ge0NvbnRyb2xsZXJ9CiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5jb250cm9sbGVyRm9yID0gZnVuY3Rpb24gY29udHJvbGxlckZvcihuYW1lLCBfc2tpcEFzc2VydCkgewogICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKTsKICAgICAgdmFyIHJvdXRlID0gb3duZXIubG9va3VwKCJyb3V0ZToiICsgbmFtZSk7CgogICAgICBpZiAocm91dGUgJiYgcm91dGUuY29udHJvbGxlck5hbWUpIHsKICAgICAgICBuYW1lID0gcm91dGUuY29udHJvbGxlck5hbWU7CiAgICAgIH0KCiAgICAgIHZhciBjb250cm9sbGVyID0gb3duZXIubG9va3VwKCJjb250cm9sbGVyOiIgKyBuYW1lKTsgLy8gTk9URTogV2UncmUgc3BlY2lmaWNhbGx5IGNoZWNraW5nIHRoYXQgc2tpcEFzc2VydCBpcyB0cnVlLCBiZWNhdXNlIGFjY29yZGluZwogICAgICAvLyAgIHRvIHRoZSBvbGQgQVBJIHRoZSBzZWNvbmQgcGFyYW1ldGVyIHdhcyBtb2RlbC4gV2UgZG8gbm90IHdhbnQgcGVvcGxlIHdobwogICAgICAvLyAgIHBhc3NlZCBhIG1vZGVsIHRvIHNraXAgdGhlIGFzc2VydGlvbi4KCiAgICAgIChmYWxzZSAmJiAhKGNvbnRyb2xsZXIgIT09IHVuZGVmaW5lZCB8fCBfc2tpcEFzc2VydCA9PT0gdHJ1ZSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgY29udHJvbGxlciBuYW1lZCAnIiArIG5hbWUgKyAiJyBjb3VsZCBub3QgYmUgZm91bmQuIE1ha2Ugc3VyZSB0aGF0IHRoaXMgcm91dGUgZXhpc3RzIGFuZCBoYXMgYWxyZWFkeSBiZWVuIGVudGVyZWQgYXQgbGVhc3Qgb25jZS4gSWYgeW91IGFyZSBhY2Nlc3NpbmcgYSBjb250cm9sbGVyIG5vdCBhc3NvY2lhdGVkIHdpdGggYSByb3V0ZSwgbWFrZSBzdXJlIHRoZSBjb250cm9sbGVyIGNsYXNzIGlzIGV4cGxpY2l0bHkgZGVmaW5lZC4iLCBjb250cm9sbGVyICE9PSB1bmRlZmluZWQgfHwgX3NraXBBc3NlcnQgPT09IHRydWUpKTsKICAgICAgcmV0dXJuIGNvbnRyb2xsZXI7CiAgICB9CiAgICAvKioKICAgICAgR2VuZXJhdGVzIGEgY29udHJvbGxlciBmb3IgYSByb3V0ZS4KICAgICAgICAgRXhhbXBsZQogICAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3QuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBzZXR1cENvbnRyb2xsZXIoY29udHJvbGxlciwgcG9zdCkgewogICAgICAgICAgdGhpcy5fc3VwZXIoY29udHJvbGxlciwgcG9zdCk7CiAgICAgICAgICB0aGlzLmdlbmVyYXRlQ29udHJvbGxlcigncG9zdHMnKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBnZW5lcmF0ZUNvbnRyb2xsZXIKICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIGNvbnRyb2xsZXIKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmdlbmVyYXRlQ29udHJvbGxlciA9IGZ1bmN0aW9uIGdlbmVyYXRlQ29udHJvbGxlcihuYW1lKSB7CiAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICByZXR1cm4gKDAsIF9nZW5lcmF0ZV9jb250cm9sbGVyLmRlZmF1bHQpKG93bmVyLCBuYW1lKTsKICAgIH0KICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSByZXNvbHZlZCBtb2RlbCBvZiBhIHBhcmVudCAob3IgYW55IGFuY2VzdG9yKSByb3V0ZQogICAgICBpbiBhIHJvdXRlIGhpZXJhcmNoeS4gIER1cmluZyBhIHRyYW5zaXRpb24sIGFsbCByb3V0ZXMKICAgICAgbXVzdCByZXNvbHZlIGEgbW9kZWwgb2JqZWN0LCBhbmQgaWYgYSByb3V0ZQogICAgICBuZWVkcyBhY2Nlc3MgdG8gYSBwYXJlbnQgcm91dGUncyBtb2RlbCBpbiBvcmRlciB0bwogICAgICByZXNvbHZlIGEgbW9kZWwgKG9yIGp1c3QgcmV1c2UgdGhlIG1vZGVsIGZyb20gYSBwYXJlbnQpLAogICAgICBpdCBjYW4gY2FsbCBgdGhpcy5tb2RlbEZvcih0aGVOYW1lT2ZQYXJlbnRSb3V0ZSlgIHRvCiAgICAgIHJldHJpZXZlIGl0LiBJZiB0aGUgYW5jZXN0b3Igcm91dGUncyBtb2RlbCB3YXMgYSBwcm9taXNlLAogICAgICBpdHMgcmVzb2x2ZWQgcmVzdWx0IGlzIHJldHVybmVkLgogICAgICAgICBFeGFtcGxlCiAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgLy8gLi4uCiAgICAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgncG9zdCcsIHsgcGF0aDogJy9wb3N0cy86cG9zdF9pZCcgfSwgZnVuY3Rpb24oKSB7CiAgICAgICAgICB0aGlzLnJvdXRlKCdjb21tZW50cycpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0L2NvbW1lbnRzLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgbW9kZWwoKSB7CiAgICAgICAgICBsZXQgcG9zdCA9IHRoaXMubW9kZWxGb3IoJ3Bvc3QnKTsKICAgICAgICAgIHJldHVybiBwb3N0LmdldCgnY29tbWVudHMnKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBtb2RlbEZvcgogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSB0aGUgbmFtZSBvZiB0aGUgcm91dGUKICAgICAgQHJldHVybiB7T2JqZWN0fSB0aGUgbW9kZWwgb2JqZWN0CiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5tb2RlbEZvciA9IGZ1bmN0aW9uIG1vZGVsRm9yKF9uYW1lKSB7CiAgICAgIHZhciBuYW1lOwogICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKTsKICAgICAgdmFyIHRyYW5zaXRpb24gPSB0aGlzLl9yb3V0ZXIgJiYgdGhpcy5fcm91dGVyLl9yb3V0ZXJNaWNyb2xpYiA/IHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWIuYWN0aXZlVHJhbnNpdGlvbiA6IHVuZGVmaW5lZDsgLy8gT25seSBjaGFuZ2UgdGhlIHJvdXRlIG5hbWUgd2hlbiB0aGVyZSBpcyBhbiBhY3RpdmUgdHJhbnNpdGlvbi4KICAgICAgLy8gT3RoZXJ3aXNlLCB1c2UgdGhlIHBhc3NlZCBpbiByb3V0ZSBuYW1lLgoKICAgICAgaWYgKG93bmVyLnJvdXRhYmxlICYmIHRyYW5zaXRpb24gIT09IHVuZGVmaW5lZCkgewogICAgICAgIG5hbWUgPSBnZXRFbmdpbmVSb3V0ZU5hbWUob3duZXIsIF9uYW1lKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBuYW1lID0gX25hbWU7CiAgICAgIH0KCiAgICAgIHZhciByb3V0ZSA9IG93bmVyLmxvb2t1cCgicm91dGU6IiArIG5hbWUpOyAvLyBJZiB3ZSBhcmUgbWlkLXRyYW5zaXRpb24sIHdlIHdhbnQgdG8gdHJ5IGFuZCBsb29rIHVwCiAgICAgIC8vIHJlc29sdmVkIHBhcmVudCBjb250ZXh0cyBvbiB0aGUgY3VycmVudCB0cmFuc2l0aW9uRXZlbnQuCgogICAgICBpZiAodHJhbnNpdGlvbiAhPT0gdW5kZWZpbmVkICYmIHRyYW5zaXRpb24gIT09IG51bGwpIHsKICAgICAgICB2YXIgbW9kZWxMb29rdXBOYW1lID0gcm91dGUgJiYgcm91dGUucm91dGVOYW1lIHx8IG5hbWU7CgogICAgICAgIGlmICh0cmFuc2l0aW9uLnJlc29sdmVkTW9kZWxzLmhhc093blByb3BlcnR5KG1vZGVsTG9va3VwTmFtZSkpIHsKICAgICAgICAgIHJldHVybiB0cmFuc2l0aW9uLnJlc29sdmVkTW9kZWxzW21vZGVsTG9va3VwTmFtZV07CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gcm91dGUgJiYgcm91dGUuY3VycmVudE1vZGVsOwogICAgfQogICAgLyoqCiAgICAgIEEgaG9vayB5b3UgY2FuIHVzZSB0byByZW5kZXIgdGhlIHRlbXBsYXRlIGZvciB0aGUgY3VycmVudCByb3V0ZS4KICAgICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIHdpdGggdGhlIGNvbnRyb2xsZXIgZm9yIHRoZSBjdXJyZW50IHJvdXRlIGFuZCB0aGUKICAgICAgbW9kZWwgc3VwcGxpZWQgYnkgdGhlIGBtb2RlbGAgaG9vay4gQnkgZGVmYXVsdCwgaXQgcmVuZGVycyB0aGUgcm91dGUncwogICAgICB0ZW1wbGF0ZSwgY29uZmlndXJlZCB3aXRoIHRoZSBjb250cm9sbGVyIGZvciB0aGUgcm91dGUuCiAgICAgICAgIFRoaXMgbWV0aG9kIGNhbiBiZSBvdmVycmlkZGVuIHRvIHNldCB1cCBhbmQgcmVuZGVyIGFkZGl0aW9uYWwgb3IKICAgICAgYWx0ZXJuYXRpdmUgdGVtcGxhdGVzLgogICAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3RzLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgcmVuZGVyVGVtcGxhdGUoY29udHJvbGxlciwgbW9kZWwpIHsKICAgICAgICAgIGxldCBmYXZDb250cm9sbGVyID0gdGhpcy5jb250cm9sbGVyRm9yKCdmYXZvcml0ZVBvc3QnKTsKICAgICAgICAgICAgIC8vIFJlbmRlciB0aGUgYGZhdm9yaXRlUG9zdGAgdGVtcGxhdGUgaW50bwogICAgICAgICAgLy8gdGhlIG91dGxldCBgcG9zdHNgLCBhbmQgZGlzcGxheSB0aGUgYGZhdm9yaXRlUG9zdGAKICAgICAgICAgIC8vIGNvbnRyb2xsZXIuCiAgICAgICAgICB0aGlzLnJlbmRlcignZmF2b3JpdGVQb3N0JywgewogICAgICAgICAgICBvdXRsZXQ6ICdwb3N0cycsCiAgICAgICAgICAgIGNvbnRyb2xsZXI6IGZhdkNvbnRyb2xsZXIKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHJlbmRlclRlbXBsYXRlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBjb250cm9sbGVyIHRoZSByb3V0ZSdzIGNvbnRyb2xsZXIKICAgICAgQHBhcmFtIHtPYmplY3R9IG1vZGVsIHRoZSByb3V0ZSdzIG1vZGVsCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5yZW5kZXJUZW1wbGF0ZSA9IGZ1bmN0aW9uIHJlbmRlclRlbXBsYXRlKF9jb250cm9sbGVyLCBfbW9kZWwpIHsKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFycwogICAgICB0aGlzLnJlbmRlcigpOwogICAgfQogICAgLyoqCiAgICAgIGByZW5kZXJgIGlzIHVzZWQgdG8gcmVuZGVyIGEgdGVtcGxhdGUgaW50byBhIHJlZ2lvbiBvZiBhbm90aGVyIHRlbXBsYXRlCiAgICAgIChpbmRpY2F0ZWQgYnkgYW4gYHt7b3V0bGV0fX1gKS4gYHJlbmRlcmAgaXMgdXNlZCBib3RoIGR1cmluZyB0aGUgZW50cnkKICAgICAgcGhhc2Ugb2Ygcm91dGluZyAodmlhIHRoZSBgcmVuZGVyVGVtcGxhdGVgIGhvb2spIGFuZCBsYXRlciBpbiByZXNwb25zZSB0bwogICAgICB1c2VyIGludGVyYWN0aW9uLgogICAgICAgICBGb3IgZXhhbXBsZSwgZ2l2ZW4gdGhlIGZvbGxvd2luZyBtaW5pbWFsIHJvdXRlciBhbmQgdGVtcGxhdGVzOgogICAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgIC8vIC4uLgogICAgICAgICBSb3V0ZXIubWFwKGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMucm91dGUoJ3Bob3RvcycpOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgYGBgaGFuZGxlYmFycwogICAgICA8IS0tIGFwcGxpY2F0aW9uLmhicyAtLT4KICAgICAgPGRpdiBjbGFzcz0nc29tZXRoaW5nLWluLXRoZS1hcHAtaGJzJz4KICAgICAgICB7e291dGxldCAiYW5PdXRsZXROYW1lIn19CiAgICAgIDwvZGl2PgogICAgICBgYGAKICAgICAgICAgYGBgaGFuZGxlYmFycwogICAgICA8IS0tIHBob3Rvcy5oYnMgLS0+CiAgICAgIDxoMT5QaG90b3M8L2gxPgogICAgICBgYGAKICAgICAgICAgWW91IGNhbiByZW5kZXIgYHBob3Rvcy5oYnNgIGludG8gdGhlIGAiYW5PdXRsZXROYW1lImAgb3V0bGV0IG9mCiAgICAgIGBhcHBsaWNhdGlvbi5oYnNgIGJ5IGNhbGxpbmcgYHJlbmRlcmA6CiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIHJlbmRlclRlbXBsYXRlKCkgewogICAgICAgICAgdGhpcy5yZW5kZXIoJ3Bob3RvcycsIHsKICAgICAgICAgICAgaW50bzogJ2FwcGxpY2F0aW9uJywKICAgICAgICAgICAgb3V0bGV0OiAnYW5PdXRsZXROYW1lJwogICAgICAgICAgfSkKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgYHJlbmRlcmAgYWRkaXRpb25hbGx5IGFsbG93cyB5b3UgdG8gc3VwcGx5IHdoaWNoIGBjb250cm9sbGVyYCBhbmQKICAgICAgYG1vZGVsYCBvYmplY3RzIHNob3VsZCBiZSBsb2FkZWQgYW5kIGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVuZGVyZWQgdGVtcGxhdGUuCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdHMuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICByZW5kZXJUZW1wbGF0ZShjb250cm9sbGVyLCBtb2RlbCl7CiAgICAgICAgICB0aGlzLnJlbmRlcigncG9zdHMnLCB7ICAgIC8vIHRoZSB0ZW1wbGF0ZSB0byByZW5kZXIsIHJlZmVyZW5jZWQgYnkgbmFtZQogICAgICAgICAgICBpbnRvOiAnYXBwbGljYXRpb24nLCAgICAvLyB0aGUgdGVtcGxhdGUgdG8gcmVuZGVyIGludG8sIHJlZmVyZW5jZWQgYnkgbmFtZQogICAgICAgICAgICBvdXRsZXQ6ICdhbk91dGxldE5hbWUnLCAvLyB0aGUgb3V0bGV0IGluc2lkZSBgb3B0aW9ucy5pbnRvYCB0byByZW5kZXIgaW50by4KICAgICAgICAgICAgY29udHJvbGxlcjogJ3NvbWVDb250cm9sbGVyTmFtZScsIC8vIHRoZSBjb250cm9sbGVyIHRvIHVzZSBmb3IgdGhpcyB0ZW1wbGF0ZSwgcmVmZXJlbmNlZCBieSBuYW1lCiAgICAgICAgICAgIG1vZGVsOiBtb2RlbCAgICAgICAgICAgIC8vIHRoZSBtb2RlbCB0byBzZXQgb24gYG9wdGlvbnMuY29udHJvbGxlcmAuCiAgICAgICAgICB9KQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBUaGUgc3RyaW5nIHZhbHVlcyBwcm92aWRlZCBmb3IgdGhlIHRlbXBsYXRlIG5hbWUsIGFuZCBjb250cm9sbGVyCiAgICAgIHdpbGwgZXZlbnR1YWxseSBwYXNzIHRocm91Z2ggdG8gdGhlIHJlc29sdmVyIGZvciBsb29rdXAuIFNlZQogICAgICBSZXNvbHZlciBmb3IgaG93IHRoZXNlIGFyZSBtYXBwZWQgdG8gSmF2YVNjcmlwdCBvYmplY3RzIGluIHlvdXIKICAgICAgYXBwbGljYXRpb24uIFRoZSB0ZW1wbGF0ZSB0byByZW5kZXIgaW50byBuZWVkcyB0byBiZSByZWxhdGVkIHRvICBlaXRoZXIgdGhlCiAgICAgIGN1cnJlbnQgcm91dGUgb3Igb25lIG9mIGl0cyBhbmNlc3RvcnMuCiAgICAgICAgIE5vdCBhbGwgb3B0aW9ucyBuZWVkIHRvIGJlIHBhc3NlZCB0byBgcmVuZGVyYC4gRGVmYXVsdCB2YWx1ZXMgd2lsbCBiZSB1c2VkCiAgICAgIGJhc2VkIG9uIHRoZSBuYW1lIG9mIHRoZSByb3V0ZSBzcGVjaWZpZWQgaW4gdGhlIHJvdXRlciBvciB0aGUgUm91dGUncwogICAgICBgY29udHJvbGxlck5hbWVgIGFuZCBgdGVtcGxhdGVOYW1lYCBwcm9wZXJ0aWVzLgogICAgICAgICBGb3IgZXhhbXBsZToKICAgICAgICAgYGBgYXBwL3JvdXRlci5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdpbmRleCcpOwogICAgICAgIHRoaXMucm91dGUoJ3Bvc3QnLCB7IHBhdGg6ICcvcG9zdHMvOnBvc3RfaWQnIH0pOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgcmVuZGVyVGVtcGxhdGUoKSB7CiAgICAgICAgICB0aGlzLnJlbmRlcigpOyAvLyBhbGwgZGVmYXVsdHMgYXBwbHkKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgVGhlIG5hbWUgb2YgdGhlIHJvdXRlLCBkZWZpbmVkIGJ5IHRoZSByb3V0ZXIsIGlzIGBwb3N0YC4KICAgICAgICAgVGhlIGZvbGxvd2luZyBlcXVpdmFsZW50IGRlZmF1bHQgb3B0aW9ucyB3aWxsIGJlIGFwcGxpZWQgd2hlbgogICAgICB0aGUgUm91dGUgY2FsbHMgYHJlbmRlcmA6CiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgdGhpcy5yZW5kZXIoJ3Bvc3QnLCB7ICAvLyB0aGUgdGVtcGxhdGUgbmFtZSBhc3NvY2lhdGVkIHdpdGggJ3Bvc3QnIFJvdXRlCiAgICAgICAgaW50bzogJ2FwcGxpY2F0aW9uJywgLy8gdGhlIHBhcmVudCByb3V0ZSB0byAncG9zdCcgUm91dGUKICAgICAgICBvdXRsZXQ6ICdtYWluJywgICAgICAvLyB7e291dGxldH19IGFuZCB7e291dGxldCAnbWFpbid9fSBhcmUgc3lub255bW91cywKICAgICAgICBjb250cm9sbGVyOiAncG9zdCcsICAvLyB0aGUgY29udHJvbGxlciBhc3NvY2lhdGVkIHdpdGggdGhlICdwb3N0JyBSb3V0ZQogICAgICB9KQogICAgICBgYGAKICAgICAgICAgQnkgZGVmYXVsdCB0aGUgY29udHJvbGxlcidzIGBtb2RlbGAgd2lsbCBiZSB0aGUgcm91dGUncyBtb2RlbCwgc28gaXQgZG9lcyBub3QKICAgICAgbmVlZCB0byBiZSBwYXNzZWQgdW5sZXNzIHlvdSB3aXNoIHRvIGNoYW5nZSB3aGljaCBtb2RlbCBpcyBiZWluZyB1c2VkLgogICAgICAgICBAbWV0aG9kIHJlbmRlcgogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSB0aGUgbmFtZSBvZiB0aGUgdGVtcGxhdGUgdG8gcmVuZGVyCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gdGhlIG9wdGlvbnMKICAgICAgQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmludG9dIHRoZSB0ZW1wbGF0ZSB0byByZW5kZXIgaW50bywKICAgICAgICAgICAgICAgICAgICAgIHJlZmVyZW5jZWQgYnkgbmFtZS4gRGVmYXVsdHMgdG8gdGhlIHBhcmVudCB0ZW1wbGF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMub3V0bGV0XSB0aGUgb3V0bGV0IGluc2lkZSBgb3B0aW9ucy5pbnRvYCB0byByZW5kZXIgaW50by4KICAgICAgICAgICAgICAgICAgICAgIERlZmF1bHRzIHRvICdtYWluJwogICAgICBAcGFyYW0ge1N0cmluZ3xPYmplY3R9IFtvcHRpb25zLmNvbnRyb2xsZXJdIHRoZSBjb250cm9sbGVyIHRvIHVzZSBmb3IgdGhpcyB0ZW1wbGF0ZSwKICAgICAgICAgICAgICAgICAgICAgIHJlZmVyZW5jZWQgYnkgbmFtZSBvciBhcyBhIGNvbnRyb2xsZXIgaW5zdGFuY2UuIERlZmF1bHRzIHRvIHRoZSBSb3V0ZSdzIHBhaXJlZCBjb250cm9sbGVyCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5tb2RlbF0gdGhlIG1vZGVsIG9iamVjdCB0byBzZXQgb24gYG9wdGlvbnMuY29udHJvbGxlcmAuCiAgICAgICAgICAgICAgICAgICAgICBEZWZhdWx0cyB0byB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBSb3V0ZSdzIG1vZGVsIGhvb2sKICAgICAgQHNpbmNlIDEuMC4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlbmRlciA9IGZ1bmN0aW9uIHJlbmRlcihfbmFtZSwgb3B0aW9ucykgewogICAgICB2YXIgbmFtZTsKICAgICAgdmFyIGlzRGVmYXVsdFJlbmRlciA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDA7CgogICAgICBpZiAoIWlzRGVmYXVsdFJlbmRlcikgewogICAgICAgIGlmICh0eXBlb2YgX25hbWUgPT09ICdvYmplY3QnICYmICFvcHRpb25zKSB7CiAgICAgICAgICBuYW1lID0gdGhpcy50ZW1wbGF0ZU5hbWUgfHwgdGhpcy5yb3V0ZU5hbWU7CiAgICAgICAgICBvcHRpb25zID0gX25hbWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRW1wdHkpKF9uYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgbmFtZSBpbiB0aGUgZ2l2ZW4gYXJndW1lbnRzIGlzIHVuZGVmaW5lZCBvciBlbXB0eSBzdHJpbmcnLCAhKDAsIF9tZXRhbC5pc0VtcHR5KShfbmFtZSkpKTsKICAgICAgICAgIG5hbWUgPSBfbmFtZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciByZW5kZXJPcHRpb25zID0gYnVpbGRSZW5kZXJPcHRpb25zKHRoaXMsIGlzRGVmYXVsdFJlbmRlciwgbmFtZSwgb3B0aW9ucyk7CiAgICAgIFJPVVRFX0NPTk5FQ1RJT05TLmdldCh0aGlzKS5wdXNoKHJlbmRlck9wdGlvbnMpOwogICAgICAoMCwgX3J1bmxvb3Aub25jZSkodGhpcy5fcm91dGVyLCAnX3NldE91dGxldHMnKTsKICAgIH0KICAgIC8qKgogICAgICBEaXNjb25uZWN0cyBhIHZpZXcgdGhhdCBoYXMgYmVlbiByZW5kZXJlZCBpbnRvIGFuIG91dGxldC4KICAgICAgICAgWW91IG1heSBwYXNzIGFueSBvciBhbGwgb2YgdGhlIGZvbGxvd2luZyBvcHRpb25zIHRvIGBkaXNjb25uZWN0T3V0bGV0YDoKICAgICAgICAgKiBgb3V0bGV0YDogdGhlIG5hbWUgb2YgdGhlIG91dGxldCB0byBjbGVhciAoZGVmYXVsdDogJ21haW4nKQogICAgICAqIGBwYXJlbnRWaWV3YDogdGhlIG5hbWUgb2YgdGhlIHZpZXcgY29udGFpbmluZyB0aGUgb3V0bGV0IHRvIGNsZWFyCiAgICAgICAgIChkZWZhdWx0OiB0aGUgdmlldyByZW5kZXJlZCBieSB0aGUgcGFyZW50IHJvdXRlKQogICAgICAgICBFeGFtcGxlOgogICAgICAgICBgYGBhcHAvcm91dGVzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgc2hvd01vZGFsKGV2dCkgewogICAgICAgICAgICB0aGlzLnJlbmRlcihldnQubW9kYWxOYW1lLCB7CiAgICAgICAgICAgICAgb3V0bGV0OiAnbW9kYWwnLAogICAgICAgICAgICAgIGludG86ICdhcHBsaWNhdGlvbicKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9LAogICAgICAgICAgICAgaGlkZU1vZGFsKGV2dCkgewogICAgICAgICAgICB0aGlzLmRpc2Nvbm5lY3RPdXRsZXQoewogICAgICAgICAgICAgIG91dGxldDogJ21vZGFsJywKICAgICAgICAgICAgICBwYXJlbnRWaWV3OiAnYXBwbGljYXRpb24nCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBBbHRlcm5hdGl2ZWx5LCB5b3UgY2FuIHBhc3MgdGhlIGBvdXRsZXRgIG5hbWUgZGlyZWN0bHkgYXMgYSBzdHJpbmcuCiAgICAgICAgIEV4YW1wbGU6CiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBzaG93TW9kYWwoZXZ0KSB7CiAgICAgICAgICAgIC8vIC4uLgogICAgICAgICAgfSwKICAgICAgICAgIGhpZGVNb2RhbChldnQpIHsKICAgICAgICAgICAgdGhpcy5kaXNjb25uZWN0T3V0bGV0KCdtb2RhbCcpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBkaXNjb25uZWN0T3V0bGV0CiAgICAgIEBwYXJhbSB7T2JqZWN0fFN0cmluZ30gb3B0aW9ucyB0aGUgb3B0aW9ucyBoYXNoIG9yIG91dGxldCBuYW1lCiAgICAgIEBzaW5jZSAxLjAuMAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5kaXNjb25uZWN0T3V0bGV0ID0gZnVuY3Rpb24gZGlzY29ubmVjdE91dGxldChvcHRpb25zKSB7CiAgICAgIHZhciBvdXRsZXROYW1lOwogICAgICB2YXIgcGFyZW50VmlldzsKCiAgICAgIGlmIChvcHRpb25zKSB7CiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnc3RyaW5nJykgewogICAgICAgICAgb3V0bGV0TmFtZSA9IG9wdGlvbnM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG91dGxldE5hbWUgPSBvcHRpb25zLm91dGxldDsKICAgICAgICAgIHBhcmVudFZpZXcgPSBvcHRpb25zLnBhcmVudFZpZXcgPyBvcHRpb25zLnBhcmVudFZpZXcucmVwbGFjZSgvXC8vZywgJy4nKSA6IHVuZGVmaW5lZDsKICAgICAgICAgIChmYWxzZSAmJiAhKCEoJ291dGxldCcgaW4gb3B0aW9ucyAmJiBvcHRpb25zLm91dGxldCA9PT0gdW5kZWZpbmVkKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgcGFzc2VkIHVuZGVmaW5lZCBhcyB0aGUgb3V0bGV0IG5hbWUuJywgISgnb3V0bGV0JyBpbiBvcHRpb25zICYmIG9wdGlvbnMub3V0bGV0ID09PSB1bmRlZmluZWQpKSk7CiAgICAgICAgfQogICAgICB9CgogICAgICBvdXRsZXROYW1lID0gb3V0bGV0TmFtZSB8fCAnbWFpbic7CgogICAgICB0aGlzLl9kaXNjb25uZWN0T3V0bGV0KG91dGxldE5hbWUsIHBhcmVudFZpZXcpOwoKICAgICAgdmFyIHJvdXRlSW5mb3MgPSB0aGlzLl9yb3V0ZXIuX3JvdXRlck1pY3JvbGliLmN1cnJlbnRSb3V0ZUluZm9zOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3V0ZUluZm9zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgLy8gVGhpcyBub24tbG9jYWwgc3RhdGUgbXVuZ2luZyBpcyBzYWRseSBuZWNlc3NhcnkgdG8gbWFpbnRhaW4KICAgICAgICAvLyBiYWNrd2FyZCBjb21wYXRpYmlsaXR5IHdpdGggb3VyIGV4aXN0aW5nIHNlbWFudGljcywgd2hpY2ggYWxsb3cKICAgICAgICAvLyBhbnkgcm91dGUgdG8gZGlzY29ubmVjdE91dGxldCB0aGluZ3Mgb3JpZ2luYWxseSByZW5kZXJlZCBieSBhbnkKICAgICAgICAvLyBvdGhlciByb3V0ZS4gVGhpcyBzaG91bGQgYWxsIGdldCBjdXQgaW4gMi4wLgogICAgICAgIHJvdXRlSW5mb3NbaV0ucm91dGUuX2Rpc2Nvbm5lY3RPdXRsZXQob3V0bGV0TmFtZSwgcGFyZW50Vmlldyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9kaXNjb25uZWN0T3V0bGV0ID0gZnVuY3Rpb24gX2Rpc2Nvbm5lY3RPdXRsZXQob3V0bGV0TmFtZSwgcGFyZW50VmlldykgewogICAgICB2YXIgcGFyZW50ID0gcGFyZW50Um91dGUodGhpcyk7CgogICAgICBpZiAocGFyZW50ICYmIHBhcmVudFZpZXcgPT09IHBhcmVudC5yb3V0ZU5hbWUpIHsKICAgICAgICBwYXJlbnRWaWV3ID0gdW5kZWZpbmVkOwogICAgICB9CgogICAgICB2YXIgY29ubmVjdGlvbnMgPSBST1VURV9DT05ORUNUSU9OUy5nZXQodGhpcyk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbm5lY3Rpb25zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGNvbm5lY3Rpb24gPSBjb25uZWN0aW9uc1tpXTsKCiAgICAgICAgaWYgKGNvbm5lY3Rpb24ub3V0bGV0ID09PSBvdXRsZXROYW1lICYmIGNvbm5lY3Rpb24uaW50byA9PT0gcGFyZW50VmlldykgewogICAgICAgICAgLy8gVGhpcyBuZXV0ZXJzIHRoZSBkaXNjb25uZWN0ZWQgb3V0bGV0IHN1Y2ggdGhhdCBpdCBkb2Vzbid0CiAgICAgICAgICAvLyByZW5kZXIgYW55dGhpbmcsIGJ1dCBpdCBsZWF2ZXMgYW4gZW50cnkgaW4gdGhlIG91dGxldAogICAgICAgICAgLy8gaGllcmFyY2h5IHNvIHRoYXQgYW55IGV4aXN0aW5nIG90aGVyIHJlbmRlcnMgdGhhdCB0YXJnZXQgaXQKICAgICAgICAgIC8vIGRvbid0IHN1ZGRlbmx5IGJsb3cgdXAuIFRoZXkgd2lsbCBzdGlsbCBzdGljayB0aGVtc2VsdmVzCiAgICAgICAgICAvLyBpbnRvIGl0cyBvdXRsZXRzLCB3aGljaCB3b24ndCByZW5kZXIgYW55d2hlcmUuIEFsbCBvZiB0aGlzCiAgICAgICAgICAvLyBzdGF0ZWZ1bG5lc3Mgc2hvdWxkIGdldCB0aGUgbWFjaGV0ZSBpbiAyLjAuCiAgICAgICAgICBjb25uZWN0aW9uc1tpXSA9IHsKICAgICAgICAgICAgb3duZXI6IGNvbm5lY3Rpb24ub3duZXIsCiAgICAgICAgICAgIGludG86IGNvbm5lY3Rpb24uaW50bywKICAgICAgICAgICAgb3V0bGV0OiBjb25uZWN0aW9uLm91dGxldCwKICAgICAgICAgICAgbmFtZTogY29ubmVjdGlvbi5uYW1lLAogICAgICAgICAgICBjb250cm9sbGVyOiB1bmRlZmluZWQsCiAgICAgICAgICAgIHRlbXBsYXRlOiB1bmRlZmluZWQKICAgICAgICAgIH07CiAgICAgICAgICAoMCwgX3J1bmxvb3Aub25jZSkodGhpcy5fcm91dGVyLCAnX3NldE91dGxldHMnKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIFJPVVRFX0NPTk5FQ1RJT05TLnNldCh0aGlzLCBjb25uZWN0aW9ucyk7CiAgICB9OwoKICAgIF9wcm90by53aWxsRGVzdHJveSA9IGZ1bmN0aW9uIHdpbGxEZXN0cm95KCkgewogICAgICB0aGlzLnRlYXJkb3duVmlld3MoKTsKICAgIH0KICAgIC8qKgogICAgICBAcHJpdmF0ZQogICAgICAgICBAbWV0aG9kIHRlYXJkb3duVmlld3MKICAgICovCiAgICA7CgogICAgX3Byb3RvLnRlYXJkb3duVmlld3MgPSBmdW5jdGlvbiB0ZWFyZG93blZpZXdzKCkgewogICAgICB2YXIgY29ubmVjdGlvbnMgPSBST1VURV9DT05ORUNUSU9OUy5nZXQodGhpcyk7CgogICAgICBpZiAoY29ubmVjdGlvbnMgIT09IHVuZGVmaW5lZCAmJiBjb25uZWN0aW9ucy5sZW5ndGggPiAwKSB7CiAgICAgICAgUk9VVEVfQ09OTkVDVElPTlMuc2V0KHRoaXMsIFtdKTsKICAgICAgICAoMCwgX3J1bmxvb3Aub25jZSkodGhpcy5fcm91dGVyLCAnX3NldE91dGxldHMnKTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgIEFsbG93cyB5b3UgdG8gcHJvZHVjZSBjdXN0b20gbWV0YWRhdGEgZm9yIHRoZSByb3V0ZS4KICAgICAgVGhlIHJldHVybiB2YWx1ZSBvZiB0aGlzIG1ldGhvZCB3aWxsIGJlIGF0dGF0Y2hlZCB0bwogICAgICBpdHMgY29ycmVzcG9uZGluZyBSb3V0ZUluZm9XaXRoQXR0cmlidXRlcyBvYmVqY3QuCiAgICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0cy9pbmRleC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGJ1aWxkUm91dGVJbmZvTWV0YWRhdGEoKSB7CiAgICAgICAgICByZXR1cm4geyB0aXRsZTogJ1Bvc3RzIFBhZ2UnIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgYGBgYXBwL3JvdXRlcy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICByb3V0ZXI6IHNlcnZpY2UoJ3JvdXRlcicpLAogICAgICAgIGluaXQoKSB7CiAgICAgICAgICB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogICAgICAgICAgdGhpcy5yb3V0ZXIub24oJ3JvdXRlRGlkQ2hhbmdlJywgdHJhbnNpdGlvbiA9PiB7CiAgICAgICAgICAgIGRvY3VtZW50LnRpdGxlID0gdHJhbnNpdGlvbi50by5tZXRhZGF0YS50aXRsZTsKICAgICAgICAgICAgLy8gd291bGQgdXBkYXRlIGRvY3VtZW50J3MgdGl0bGUgdG8gIlBvc3RzIFBhZ2UiCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQHJldHVybiBhbnkKICAgICAqLwogICAgOwoKICAgIF9wcm90by5idWlsZFJvdXRlSW5mb01ldGFkYXRhID0gZnVuY3Rpb24gYnVpbGRSb3V0ZUluZm9NZXRhZGF0YSgpIHt9OwoKICAgIHJldHVybiBSb3V0ZTsKICB9KF9ydW50aW1lLk9iamVjdCk7CgogIFJvdXRlLnJlb3BlbkNsYXNzKHsKICAgIGlzUm91dGVGYWN0b3J5OiB0cnVlCiAgfSk7CgogIGZ1bmN0aW9uIHBhcmVudFJvdXRlKHJvdXRlKSB7CiAgICB2YXIgcm91dGVJbmZvID0gcm91dGVJbmZvRm9yKHJvdXRlLCByb3V0ZS5fcm91dGVyLl9yb3V0ZXJNaWNyb2xpYi5zdGF0ZS5yb3V0ZUluZm9zLCAtMSk7CiAgICByZXR1cm4gcm91dGVJbmZvICYmIHJvdXRlSW5mby5yb3V0ZTsKICB9CgogIGZ1bmN0aW9uIHJvdXRlSW5mb0Zvcihyb3V0ZSwgcm91dGVJbmZvcywgb2Zmc2V0KSB7CiAgICBpZiAob2Zmc2V0ID09PSB2b2lkIDApIHsKICAgICAgb2Zmc2V0ID0gMDsKICAgIH0KCiAgICBpZiAoIXJvdXRlSW5mb3MpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBjdXJyZW50OwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm91dGVJbmZvcy5sZW5ndGg7IGkrKykgewogICAgICBjdXJyZW50ID0gcm91dGVJbmZvc1tpXS5yb3V0ZTsKCiAgICAgIGlmIChjdXJyZW50ID09PSByb3V0ZSkgewogICAgICAgIHJldHVybiByb3V0ZUluZm9zW2kgKyBvZmZzZXRdOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuOwogIH0KCiAgZnVuY3Rpb24gYnVpbGRSZW5kZXJPcHRpb25zKHJvdXRlLCBpc0RlZmF1bHRSZW5kZXIsIF9uYW1lLCBvcHRpb25zKSB7CiAgICAoZmFsc2UgJiYgIShpc0RlZmF1bHRSZW5kZXIgfHwgIShvcHRpb25zICYmICdvdXRsZXQnIGluIG9wdGlvbnMgJiYgb3B0aW9ucy5vdXRsZXQgPT09IHVuZGVmaW5lZCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IHBhc3NlZCB1bmRlZmluZWQgYXMgdGhlIG91dGxldCBuYW1lLicsIGlzRGVmYXVsdFJlbmRlciB8fCAhKG9wdGlvbnMgJiYgJ291dGxldCcgaW4gb3B0aW9ucyAmJiBvcHRpb25zLm91dGxldCA9PT0gdW5kZWZpbmVkKSkpOwogICAgdmFyIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikocm91dGUpOwogICAgdmFyIG5hbWUsIHRlbXBsYXRlTmFtZSwgaW50bywgb3V0bGV0LCBtb2RlbDsKICAgIHZhciBjb250cm9sbGVyID0gdW5kZWZpbmVkOwoKICAgIGlmIChvcHRpb25zKSB7CiAgICAgIGludG8gPSBvcHRpb25zLmludG8gJiYgb3B0aW9ucy5pbnRvLnJlcGxhY2UoL1wvL2csICcuJyk7CiAgICAgIG91dGxldCA9IG9wdGlvbnMub3V0bGV0OwogICAgICBjb250cm9sbGVyID0gb3B0aW9ucy5jb250cm9sbGVyOwogICAgICBtb2RlbCA9IG9wdGlvbnMubW9kZWw7CiAgICB9CgogICAgb3V0bGV0ID0gb3V0bGV0IHx8ICdtYWluJzsKCiAgICBpZiAoaXNEZWZhdWx0UmVuZGVyKSB7CiAgICAgIG5hbWUgPSByb3V0ZS5yb3V0ZU5hbWU7CiAgICAgIHRlbXBsYXRlTmFtZSA9IHJvdXRlLnRlbXBsYXRlTmFtZSB8fCBuYW1lOwogICAgfSBlbHNlIHsKICAgICAgbmFtZSA9IF9uYW1lLnJlcGxhY2UoL1wvL2csICcuJyk7CiAgICAgIHRlbXBsYXRlTmFtZSA9IG5hbWU7CiAgICB9CgogICAgaWYgKGNvbnRyb2xsZXIgPT09IHVuZGVmaW5lZCkgewogICAgICBpZiAoaXNEZWZhdWx0UmVuZGVyKSB7CiAgICAgICAgY29udHJvbGxlciA9IHJvdXRlLmNvbnRyb2xsZXJOYW1lIHx8IG93bmVyLmxvb2t1cCgiY29udHJvbGxlcjoiICsgbmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29udHJvbGxlciA9IG93bmVyLmxvb2t1cCgiY29udHJvbGxlcjoiICsgbmFtZSkgfHwgcm91dGUuY29udHJvbGxlck5hbWUgfHwgcm91dGUucm91dGVOYW1lOwogICAgICB9CiAgICB9CgogICAgaWYgKHR5cGVvZiBjb250cm9sbGVyID09PSAnc3RyaW5nJykgewogICAgICB2YXIgY29udHJvbGxlck5hbWUgPSBjb250cm9sbGVyOwogICAgICBjb250cm9sbGVyID0gb3duZXIubG9va3VwKCJjb250cm9sbGVyOiIgKyBjb250cm9sbGVyTmFtZSk7CiAgICAgIChmYWxzZSAmJiAhKGlzRGVmYXVsdFJlbmRlciB8fCBjb250cm9sbGVyICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IHBhc3NlZCBgY29udHJvbGxlcjogJyIgKyBjb250cm9sbGVyTmFtZSArICInYCBpbnRvIHRoZSBgcmVuZGVyYCBtZXRob2QsIGJ1dCBubyBzdWNoIGNvbnRyb2xsZXIgY291bGQgYmUgZm91bmQuIiwgaXNEZWZhdWx0UmVuZGVyIHx8IGNvbnRyb2xsZXIgIT09IHVuZGVmaW5lZCkpOwogICAgfQoKICAgIGlmIChtb2RlbCkgewogICAgICBjb250cm9sbGVyLnNldCgnbW9kZWwnLCBtb2RlbCk7CiAgICB9CgogICAgdmFyIHRlbXBsYXRlID0gb3duZXIubG9va3VwKCJ0ZW1wbGF0ZToiICsgdGVtcGxhdGVOYW1lKTsKICAgIChmYWxzZSAmJiAhKGlzRGVmYXVsdFJlbmRlciB8fCB0ZW1wbGF0ZSAhPT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkNvdWxkIG5vdCBmaW5kIFwiIiArIHRlbXBsYXRlTmFtZSArICJcIiB0ZW1wbGF0ZSwgdmlldywgb3IgY29tcG9uZW50LiIsIGlzRGVmYXVsdFJlbmRlciB8fCB0ZW1wbGF0ZSAhPT0gdW5kZWZpbmVkKSk7CiAgICB2YXIgcGFyZW50OwoKICAgIGlmIChpbnRvICYmIChwYXJlbnQgPSBwYXJlbnRSb3V0ZShyb3V0ZSkpICYmIGludG8gPT09IHBhcmVudC5yb3V0ZU5hbWUpIHsKICAgICAgaW50byA9IHVuZGVmaW5lZDsKICAgIH0KCiAgICB2YXIgcmVuZGVyT3B0aW9ucyA9IHsKICAgICAgb3duZXI6IG93bmVyLAogICAgICBpbnRvOiBpbnRvLAogICAgICBvdXRsZXQ6IG91dGxldCwKICAgICAgbmFtZTogbmFtZSwKICAgICAgY29udHJvbGxlcjogY29udHJvbGxlciwKICAgICAgdGVtcGxhdGU6IHRlbXBsYXRlICE9PSB1bmRlZmluZWQgPyB0ZW1wbGF0ZShvd25lcikgOiByb3V0ZS5fdG9wTGV2ZWxWaWV3VGVtcGxhdGUob3duZXIpCiAgICB9OwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICB2YXIgTE9HX1ZJRVdfTE9PS1VQUyA9ICgwLCBfbWV0YWwuZ2V0KShyb3V0ZS5fcm91dGVyLCAnbmFtZXNwYWNlLkxPR19WSUVXX0xPT0tVUFMnKTsKCiAgICAgIGlmIChMT0dfVklFV19MT09LVVBTICYmICF0ZW1wbGF0ZSkgewogICAgICAgICgwLCBfZGVidWcuaW5mbykoIkNvdWxkIG5vdCBmaW5kIFwiIiArIG5hbWUgKyAiXCIgdGVtcGxhdGUuIE5vdGhpbmcgd2lsbCBiZSByZW5kZXJlZCIsIHsKICAgICAgICAgIGZ1bGxOYW1lOiAidGVtcGxhdGU6IiArIG5hbWUKICAgICAgICB9KTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiByZW5kZXJPcHRpb25zOwogIH0KCiAgZnVuY3Rpb24gZ2V0RnVsbFF1ZXJ5UGFyYW1zKHJvdXRlciwgc3RhdGUpIHsKICAgIGlmIChzdGF0ZVsnZnVsbFF1ZXJ5UGFyYW1zJ10pIHsKICAgICAgcmV0dXJuIHN0YXRlWydmdWxsUXVlcnlQYXJhbXMnXTsKICAgIH0KCiAgICBzdGF0ZVsnZnVsbFF1ZXJ5UGFyYW1zJ10gPSB7fTsKICAgICgwLCBfcG9seWZpbGxzLmFzc2lnbikoc3RhdGVbJ2Z1bGxRdWVyeVBhcmFtcyddLCBzdGF0ZS5xdWVyeVBhcmFtcyk7CgogICAgcm91dGVyLl9kZXNlcmlhbGl6ZVF1ZXJ5UGFyYW1zKHN0YXRlLnJvdXRlSW5mb3MsIHN0YXRlWydmdWxsUXVlcnlQYXJhbXMnXSk7CgogICAgcmV0dXJuIHN0YXRlWydmdWxsUXVlcnlQYXJhbXMnXTsKICB9CgogIGZ1bmN0aW9uIGdldFF1ZXJ5UGFyYW1zRm9yKHJvdXRlLCBzdGF0ZSkgewogICAgc3RhdGVbJ3F1ZXJ5UGFyYW1zRm9yJ10gPSBzdGF0ZVsncXVlcnlQYXJhbXNGb3InXSB8fCB7fTsKICAgIHZhciBuYW1lID0gcm91dGUuZnVsbFJvdXRlTmFtZTsKCiAgICBpZiAoc3RhdGVbJ3F1ZXJ5UGFyYW1zRm9yJ11bbmFtZV0pIHsKICAgICAgcmV0dXJuIHN0YXRlWydxdWVyeVBhcmFtc0ZvciddW25hbWVdOwogICAgfQoKICAgIHZhciBmdWxsUXVlcnlQYXJhbXMgPSBnZXRGdWxsUXVlcnlQYXJhbXMocm91dGUuX3JvdXRlciwgc3RhdGUpOwogICAgdmFyIHBhcmFtcyA9IHN0YXRlWydxdWVyeVBhcmFtc0ZvciddW25hbWVdID0ge307IC8vIENvcHkgb3ZlciBhbGwgdGhlIHF1ZXJ5IHBhcmFtcyBmb3IgdGhpcyByb3V0ZS9jb250cm9sbGVyIGludG8gcGFyYW1zIGhhc2guCgogICAgdmFyIHFwcyA9ICgwLCBfbWV0YWwuZ2V0KShyb3V0ZSwgJ19xcC5xcHMnKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHFwcy5sZW5ndGg7ICsraSkgewogICAgICAvLyBQdXQgZGVzZXJpYWxpemVkIHFwIG9uIHBhcmFtcyBoYXNoLgogICAgICB2YXIgcXAgPSBxcHNbaV07CiAgICAgIHZhciBxcFZhbHVlV2FzUGFzc2VkSW4gPSBxcC5wcm9wIGluIGZ1bGxRdWVyeVBhcmFtczsKICAgICAgcGFyYW1zW3FwLnByb3BdID0gcXBWYWx1ZVdhc1Bhc3NlZEluID8gZnVsbFF1ZXJ5UGFyYW1zW3FwLnByb3BdIDogY29weURlZmF1bHRWYWx1ZShxcC5kZWZhdWx0VmFsdWUpOwogICAgfQoKICAgIHJldHVybiBwYXJhbXM7CiAgfQoKICBmdW5jdGlvbiBjb3B5RGVmYXVsdFZhbHVlKHZhbHVlKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5BKSh2YWx1ZS5zbGljZSgpKTsKICAgIH0KCiAgICByZXR1cm4gdmFsdWU7CiAgfQogIC8qCiAgICBNZXJnZXMgYWxsIHF1ZXJ5IHBhcmFtZXRlcnMgZnJvbSBhIGNvbnRyb2xsZXIgd2l0aCB0aG9zZSBmcm9tCiAgICBhIHJvdXRlLCByZXR1cm5pbmcgYSBuZXcgb2JqZWN0IGFuZCBhdm9pZGluZyBhbnkgbXV0YXRpb25zIHRvCiAgICB0aGUgZXhpc3Rpbmcgb2JqZWN0cy4KICAqLwoKCiAgZnVuY3Rpb24gbWVyZ2VFYWNoUXVlcnlQYXJhbXMoY29udHJvbGxlclFQLCByb3V0ZVFQKSB7CiAgICB2YXIgcXBzID0ge307CiAgICB2YXIga2V5c0FscmVhZHlNZXJnZWRPclNraXBwYWJsZSA9IHsKICAgICAgZGVmYXVsdFZhbHVlOiB0cnVlLAogICAgICB0eXBlOiB0cnVlLAogICAgICBzY29wZTogdHJ1ZSwKICAgICAgYXM6IHRydWUKICAgIH07IC8vIGZpcnN0IGxvb3Agb3ZlciBhbGwgY29udHJvbGxlciBxcHMsIG1lcmdpbmcgdGhlbSB3aXRoIGFueSBtYXRjaGluZyByb3V0ZSBxcHMKICAgIC8vIGludG8gYSBuZXcgZW1wdHkgb2JqZWN0IHRvIGF2b2lkIG11dGF0aW5nLgoKICAgIGZvciAodmFyIGNxcE5hbWUgaW4gY29udHJvbGxlclFQKSB7CiAgICAgIGlmICghY29udHJvbGxlclFQLmhhc093blByb3BlcnR5KGNxcE5hbWUpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIHZhciBuZXdDb250cm9sbGVyUGFyYW1ldGVyQ29uZmlndXJhdGlvbiA9IHt9OwogICAgICAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKG5ld0NvbnRyb2xsZXJQYXJhbWV0ZXJDb25maWd1cmF0aW9uLCBjb250cm9sbGVyUVBbY3FwTmFtZV0sIHJvdXRlUVBbY3FwTmFtZV0pOwogICAgICBxcHNbY3FwTmFtZV0gPSBuZXdDb250cm9sbGVyUGFyYW1ldGVyQ29uZmlndXJhdGlvbjsgLy8gYWxsb3dzIHVzIHRvIHNraXAgdGhpcyBRUCB3aGVuIHdlIGNoZWNrIHJvdXRlIFFQcy4KCiAgICAgIGtleXNBbHJlYWR5TWVyZ2VkT3JTa2lwcGFibGVbY3FwTmFtZV0gPSB0cnVlOwogICAgfSAvLyBsb29wIG92ZXIgYWxsIHJvdXRlIHFwcywgc2tpcHBpbmcgdGhvc2UgdGhhdCB3ZXJlIG1lcmdlZCBpbiB0aGUgZmlyc3QgcGFzcwogICAgLy8gYmVjYXVzZSB0aGV5IGFsc28gYXBwZWFyIGluIGNvbnRyb2xsZXIgcXBzCgoKICAgIGZvciAodmFyIHJxcE5hbWUgaW4gcm91dGVRUCkgewogICAgICBpZiAoIXJvdXRlUVAuaGFzT3duUHJvcGVydHkocnFwTmFtZSkgfHwga2V5c0FscmVhZHlNZXJnZWRPclNraXBwYWJsZVtycXBOYW1lXSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICB2YXIgbmV3Um91dGVQYXJhbWV0ZXJDb25maWd1cmF0aW9uID0ge307CiAgICAgICgwLCBfcG9seWZpbGxzLmFzc2lnbikobmV3Um91dGVQYXJhbWV0ZXJDb25maWd1cmF0aW9uLCByb3V0ZVFQW3JxcE5hbWVdLCBjb250cm9sbGVyUVBbcnFwTmFtZV0pOwogICAgICBxcHNbcnFwTmFtZV0gPSBuZXdSb3V0ZVBhcmFtZXRlckNvbmZpZ3VyYXRpb247CiAgICB9CgogICAgcmV0dXJuIHFwczsKICB9CgogIGZ1bmN0aW9uIGFkZFF1ZXJ5UGFyYW1zT2JzZXJ2ZXJzKGNvbnRyb2xsZXIsIHByb3BOYW1lcykgewogICAgcHJvcE5hbWVzLmZvckVhY2goZnVuY3Rpb24gKHByb3ApIHsKICAgICAgaWYgKCgwLCBfbWV0YWwuZGVzY3JpcHRvckZvclByb3BlcnR5KShjb250cm9sbGVyLCBwcm9wKSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdmFyIGRlc2MgPSAoMCwgX3V0aWxzLmxvb2t1cERlc2NyaXB0b3IpKGNvbnRyb2xsZXIsIHByb3ApOwoKICAgICAgICBpZiAoZGVzYyAhPT0gbnVsbCAmJiAodHlwZW9mIGRlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBkZXNjLnNldCA9PT0gJ2Z1bmN0aW9uJykpIHsKICAgICAgICAgICgwLCBfbWV0YWwuZGVmaW5lUHJvcGVydHkpKGNvbnRyb2xsZXIsIHByb3AsICgwLCBfY29tcGF0LmRlcGVuZGVudEtleUNvbXBhdCkoewogICAgICAgICAgICBnZXQ6IGRlc2MuZ2V0LAogICAgICAgICAgICBzZXQ6IGRlc2Muc2V0CiAgICAgICAgICB9KSk7CiAgICAgICAgfQogICAgICB9CgogICAgICAoMCwgX21ldGFsLmFkZE9ic2VydmVyKShjb250cm9sbGVyLCBwcm9wICsgIi5bXSIsIGNvbnRyb2xsZXIsIGNvbnRyb2xsZXIuX3FwQ2hhbmdlZCwgZmFsc2UpOwogICAgfSk7CiAgfQoKICBmdW5jdGlvbiBnZXRFbmdpbmVSb3V0ZU5hbWUoZW5naW5lLCByb3V0ZU5hbWUpIHsKICAgIGlmIChlbmdpbmUucm91dGFibGUpIHsKICAgICAgdmFyIHByZWZpeCA9IGVuZ2luZS5tb3VudFBvaW50OwoKICAgICAgaWYgKHJvdXRlTmFtZSA9PT0gJ2FwcGxpY2F0aW9uJykgewogICAgICAgIHJldHVybiBwcmVmaXg7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHByZWZpeCArICIuIiArIHJvdXRlTmFtZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiByb3V0ZU5hbWU7CiAgfQogIC8qKgogICAgICBBIGhvb2sgeW91IGNhbiBpbXBsZW1lbnQgdG8gY29udmVydCB0aGUgcm91dGUncyBtb2RlbCBpbnRvIHBhcmFtZXRlcnMKICAgICAgZm9yIHRoZSBVUkwuCiAgCiAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgLy8gLi4uCiAgCiAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgncG9zdCcsIHsgcGF0aDogJy9wb3N0cy86cG9zdF9pZCcgfSk7CiAgICAgIH0pOwogIAogICAgICBgYGAKICAKICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0LmpzCiAgICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeSc7CiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgCiAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgbW9kZWwocGFyYW1zKSB7CiAgICAgICAgICAvLyB0aGUgc2VydmVyIHJldHVybnMgYHsgaWQ6IDEyIH1gCiAgICAgICAgICByZXR1cm4gJC5nZXRKU09OKCcvcG9zdHMvJyArIHBhcmFtcy5wb3N0X2lkKTsKICAgICAgICB9LAogIAogICAgICAgIHNlcmlhbGl6ZShtb2RlbCkgewogICAgICAgICAgLy8gdGhpcyB3aWxsIG1ha2UgdGhlIFVSTCBgL3Bvc3RzLzEyYAogICAgICAgICAgcmV0dXJuIHsgcG9zdF9pZDogbW9kZWwuaWQgfTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAKICAgICAgVGhlIGRlZmF1bHQgYHNlcmlhbGl6ZWAgbWV0aG9kIHdpbGwgaW5zZXJ0IHRoZSBtb2RlbCdzIGBpZGAgaW50byB0aGUKICAgICAgcm91dGUncyBkeW5hbWljIHNlZ21lbnQgKGluIHRoaXMgY2FzZSwgYDpwb3N0X2lkYCkgaWYgdGhlIHNlZ21lbnQgY29udGFpbnMgJ19pZCcuCiAgICAgIElmIHRoZSByb3V0ZSBoYXMgbXVsdGlwbGUgZHluYW1pYyBzZWdtZW50cyBvciBkb2VzIG5vdCBjb250YWluICdfaWQnLCBgc2VyaWFsaXplYAogICAgICB3aWxsIHJldHVybiBgZ2V0UHJvcGVydGllcyhtb2RlbCwgcGFyYW1zKWAKICAKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIHdoZW4gYHRyYW5zaXRpb25Ub2AgaXMgY2FsbGVkIHdpdGggYSBjb250ZXh0CiAgICAgIGluIG9yZGVyIHRvIHBvcHVsYXRlIHRoZSBVUkwuCiAgCiAgICAgIEBtZXRob2Qgc2VyaWFsaXplCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBtb2RlbCB0aGUgcm91dGVzIG1vZGVsCiAgICAgIEBwYXJhbSB7QXJyYXl9IHBhcmFtcyBhbiBBcnJheSBvZiBwYXJhbWV0ZXIgbmFtZXMgZm9yIHRoZSBjdXJyZW50CiAgICAgICAgcm91dGUgKGluIHRoZSBleGFtcGxlLCBgWydwb3N0X2lkJ11gLgogICAgICBAcmV0dXJuIHtPYmplY3R9IHRoZSBzZXJpYWxpemVkIHBhcmFtZXRlcnMKICAgICAgQHNpbmNlIDEuMC4wCiAgICAgIEBwdWJsaWMKICAgICovCgoKICBSb3V0ZS5wcm90b3R5cGUuc2VyaWFsaXplID0gZGVmYXVsdFNlcmlhbGl6ZTsKICBSb3V0ZS5yZW9wZW4oX3J1bnRpbWUuQWN0aW9uSGFuZGxlciwgX3J1bnRpbWUuRXZlbnRlZCwgewogICAgbWVyZ2VkUHJvcGVydGllczogWydxdWVyeVBhcmFtcyddLAoKICAgIC8qKgogICAgICBDb25maWd1cmF0aW9uIGhhc2ggZm9yIHRoaXMgcm91dGUncyBxdWVyeVBhcmFtcy4gVGhlIHBvc3NpYmxlCiAgICAgIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBhbmQgdGhlaXIgZGVmYXVsdHMgYXJlIGFzIGZvbGxvd3MKICAgICAgKGFzc3VtaW5nIGEgcXVlcnkgcGFyYW0gd2hvc2UgY29udHJvbGxlciBwcm9wZXJ0eSBpcyBgcGFnZWApOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHF1ZXJ5UGFyYW1zOiB7CiAgICAgICAgcGFnZTogewogICAgICAgICAgLy8gQnkgZGVmYXVsdCwgY29udHJvbGxlciBxdWVyeSBwYXJhbSBwcm9wZXJ0aWVzIGRvbid0CiAgICAgICAgICAvLyBjYXVzZSBhIGZ1bGwgdHJhbnNpdGlvbiB3aGVuIHRoZXkgYXJlIGNoYW5nZWQsIGJ1dAogICAgICAgICAgLy8gcmF0aGVyIG9ubHkgY2F1c2UgdGhlIFVSTCB0byB1cGRhdGUuIFNldHRpbmcKICAgICAgICAgIC8vIGByZWZyZXNoTW9kZWxgIHRvIHRydWUgd2lsbCBjYXVzZSBhbiAiaW4tcGxhY2UiCiAgICAgICAgICAvLyB0cmFuc2l0aW9uIHRvIG9jY3VyLCB3aGVyZWJ5IHRoZSBtb2RlbCBob29rcyBmb3IKICAgICAgICAgIC8vIHRoaXMgcm91dGUgKGFuZCBhbnkgY2hpbGQgcm91dGVzKSB3aWxsIHJlLWZpcmUsIGFsbG93aW5nCiAgICAgICAgICAvLyB5b3UgdG8gcmVsb2FkIG1vZGVscyAoZS5nLiwgZnJvbSB0aGUgc2VydmVyKSB1c2luZyB0aGUKICAgICAgICAgIC8vIHVwZGF0ZWQgcXVlcnkgcGFyYW0gdmFsdWVzLgogICAgICAgICAgcmVmcmVzaE1vZGVsOiBmYWxzZSwKICAgICAgICAgICAgIC8vIEJ5IGRlZmF1bHQsIGNoYW5nZXMgdG8gY29udHJvbGxlciBxdWVyeSBwYXJhbSBwcm9wZXJ0aWVzCiAgICAgICAgICAvLyBjYXVzZSB0aGUgVVJMIHRvIHVwZGF0ZSB2aWEgYHB1c2hTdGF0ZWAsIHdoaWNoIG1lYW5zIGFuCiAgICAgICAgICAvLyBpdGVtIHdpbGwgYmUgYWRkZWQgdG8gdGhlIGJyb3dzZXIncyBoaXN0b3J5LCBhbGxvd2luZwogICAgICAgICAgLy8geW91IHRvIHVzZSB0aGUgYmFjayBidXR0b24gdG8gcmVzdG9yZSB0aGUgYXBwIHRvIHRoZQogICAgICAgICAgLy8gcHJldmlvdXMgc3RhdGUgYmVmb3JlIHRoZSBxdWVyeSBwYXJhbSBwcm9wZXJ0eSB3YXMgY2hhbmdlZC4KICAgICAgICAgIC8vIFNldHRpbmcgYHJlcGxhY2VgIHRvIHRydWUgd2lsbCB1c2UgYHJlcGxhY2VTdGF0ZWAgKG9yIGl0cwogICAgICAgICAgLy8gaGFzaCBsb2NhdGlvbiBlcXVpdmFsZW50KSwgd2hpY2ggY2F1c2VzIG5vIGJyb3dzZXIgaGlzdG9yeQogICAgICAgICAgLy8gaXRlbSB0byBiZSBhZGRlZC4gVGhpcyBvcHRpb25zIG5hbWUgYW5kIGRlZmF1bHQgdmFsdWUgYXJlCiAgICAgICAgICAvLyB0aGUgc2FtZSBhcyB0aGUgYGxpbmstdG9gIGhlbHBlcidzIGByZXBsYWNlYCBvcHRpb24uCiAgICAgICAgICByZXBsYWNlOiBmYWxzZSwKICAgICAgICAgICAgIC8vIEJ5IGRlZmF1bHQsIHRoZSBxdWVyeSBwYXJhbSBVUkwga2V5IGlzIHRoZSBzYW1lIG5hbWUgYXMKICAgICAgICAgIC8vIHRoZSBjb250cm9sbGVyIHByb3BlcnR5IG5hbWUuIFVzZSBgYXNgIHRvIHNwZWNpZnkgYQogICAgICAgICAgLy8gZGlmZmVyZW50IFVSTCBrZXkuCiAgICAgICAgICBhczogJ3BhZ2UnCiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgICBAcHJvcGVydHkgcXVlcnlQYXJhbXMKICAgICAgQGZvciBSb3V0ZQogICAgICBAdHlwZSBPYmplY3QKICAgICAgQHNpbmNlIDEuNi4wCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBxdWVyeVBhcmFtczoge30sCgogICAgLyoqCiAgICAgIFRoZSBuYW1lIG9mIHRoZSB0ZW1wbGF0ZSB0byB1c2UgYnkgZGVmYXVsdCB3aGVuIHJlbmRlcmluZyB0aGlzIHJvdXRlcwogICAgICB0ZW1wbGF0ZS4KICAgICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0cy9saXN0LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgdGVtcGxhdGVOYW1lOiAncG9zdHMvbGlzdCcKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3RzL2luZGV4LmpzCiAgICAgIGltcG9ydCBQb3N0c0xpc3QgZnJvbSAnLi4vcG9zdHMvbGlzdCc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFBvc3RzTGlzdC5leHRlbmQoKTsKICAgICAgYGBgCiAgICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdHMvYXJjaGl2ZWQuanMKICAgICAgaW1wb3J0IFBvc3RzTGlzdCBmcm9tICcuLi9wb3N0cy9saXN0JzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUG9zdHNMaXN0LmV4dGVuZCgpOwogICAgICBgYGAKICAgICAgICAgQHByb3BlcnR5IHRlbXBsYXRlTmFtZQogICAgICBAdHlwZSBTdHJpbmcKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAc2luY2UgMS40LjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHRlbXBsYXRlTmFtZTogbnVsbCwKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgQHByb3BlcnR5IF9uYW1lcwogICAgKi8KICAgIF9uYW1lczogbnVsbCwKCiAgICAvKioKICAgICAgVGhlIG5hbWUgb2YgdGhlIGNvbnRyb2xsZXIgdG8gYXNzb2NpYXRlIHdpdGggdGhpcyByb3V0ZS4KICAgICAgICAgQnkgZGVmYXVsdCwgRW1iZXIgd2lsbCBsb29rdXAgYSByb3V0ZSdzIGNvbnRyb2xsZXIgdGhhdCBtYXRjaGVzIHRoZSBuYW1lCiAgICAgIG9mIHRoZSByb3V0ZSAoaS5lLiBgcG9zdHMubmV3YCkuIEhvd2V2ZXIsCiAgICAgIGlmIHlvdSB3b3VsZCBsaWtlIHRvIGRlZmluZSBhIHNwZWNpZmljIGNvbnRyb2xsZXIgdG8gdXNlLCB5b3UgY2FuIGRvIHNvCiAgICAgIHVzaW5nIHRoaXMgcHJvcGVydHkuCiAgICAgICAgIFRoaXMgaXMgdXNlZnVsIGluIG1hbnkgd2F5cywgYXMgdGhlIGNvbnRyb2xsZXIgc3BlY2lmaWVkIHdpbGwgYmU6CiAgICAgICAgICogcGFzc2VkIHRvIHRoZSBgc2V0dXBDb250cm9sbGVyYCBtZXRob2QuCiAgICAgICogdXNlZCBhcyB0aGUgY29udHJvbGxlciBmb3IgdGhlIHRlbXBsYXRlIGJlaW5nIHJlbmRlcmVkIGJ5IHRoZSByb3V0ZS4KICAgICAgKiByZXR1cm5lZCBmcm9tIGEgY2FsbCB0byBgY29udHJvbGxlckZvcmAgZm9yIHRoZSByb3V0ZS4KICAgICAgICAgQHByb3BlcnR5IGNvbnRyb2xsZXJOYW1lCiAgICAgIEB0eXBlIFN0cmluZwogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBzaW5jZSAxLjQuMAogICAgICBAcHVibGljCiAgICAqLwogICAgY29udHJvbGxlck5hbWU6IG51bGwsCgogICAgLyoqCiAgICAgIFN0b3JlIHByb3BlcnR5IHByb3ZpZGVzIGEgaG9vayBmb3IgZGF0YSBwZXJzaXN0ZW5jZSBsaWJyYXJpZXMgdG8gaW5qZWN0IHRoZW1zZWx2ZXMuCiAgICAgICAgIEJ5IGRlZmF1bHQsIHRoaXMgc3RvcmUgcHJvcGVydHkgcHJvdmlkZXMgdGhlIGV4YWN0IHNhbWUgZnVuY3Rpb25hbGl0eSBwcmV2aW91c2x5CiAgICAgIGluIHRoZSBtb2RlbCBob29rLgogICAgICAgICBDdXJyZW50bHksIHRoZSByZXF1aXJlZCBpbnRlcmZhY2UgaXM6CiAgICAgICAgIGBzdG9yZS5maW5kKG1vZGVsTmFtZSwgZmluZEFyZ3VtZW50cylgCiAgICAgICAgIEBwcm9wZXJ0eSBzdG9yZQogICAgICBAdHlwZSB7T2JqZWN0fQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIHN0b3JlOiAoMCwgX21ldGFsLmNvbXB1dGVkKSh7CiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICAgIHZhciByb3V0ZU5hbWUgPSB0aGlzLnJvdXRlTmFtZTsKICAgICAgICB2YXIgbmFtZXNwYWNlID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdfcm91dGVyLm5hbWVzcGFjZScpOwogICAgICAgIHJldHVybiB7CiAgICAgICAgICBmaW5kOiBmdW5jdGlvbiBmaW5kKG5hbWUsIHZhbHVlKSB7CiAgICAgICAgICAgIHZhciBtb2RlbENsYXNzID0gb3duZXIuZmFjdG9yeUZvcigibW9kZWw6IiArIG5hbWUpOwogICAgICAgICAgICAoZmFsc2UgJiYgIShCb29sZWFuKG1vZGVsQ2xhc3MpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSB1c2VkIHRoZSBkeW5hbWljIHNlZ21lbnQgIiArIG5hbWUgKyAiX2lkIGluIHlvdXIgcm91dGUgIiArIHJvdXRlTmFtZSArICIsIGJ1dCAiICsgbmFtZXNwYWNlICsgIi4iICsgKDAsIF9zdHJpbmcuY2xhc3NpZnkpKG5hbWUpICsgIiBkaWQgbm90IGV4aXN0IGFuZCB5b3UgZGlkIG5vdCBvdmVycmlkZSB5b3VyIHJvdXRlJ3MgYG1vZGVsYCBob29rLiIsIEJvb2xlYW4obW9kZWxDbGFzcykpKTsKCiAgICAgICAgICAgIGlmICghbW9kZWxDbGFzcykgewogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbW9kZWxDbGFzcyA9IG1vZGVsQ2xhc3MuY2xhc3M7CiAgICAgICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBtb2RlbENsYXNzLmZpbmQgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgoMCwgX3N0cmluZy5jbGFzc2lmeSkobmFtZSkgKyAiIGhhcyBubyBtZXRob2QgYGZpbmRgLiIsIHR5cGVvZiBtb2RlbENsYXNzLmZpbmQgPT09ICdmdW5jdGlvbicpKTsKICAgICAgICAgICAgcmV0dXJuIG1vZGVsQ2xhc3MuZmluZCh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5LCB2YWx1ZSkgewogICAgICAgICgwLCBfbWV0YWwuZGVmaW5lUHJvcGVydHkpKHRoaXMsIGtleSwgbnVsbCwgdmFsdWUpOwogICAgICB9CiAgICB9KSwKCiAgICAvKioKICAgICAgICBAcHJpdmF0ZQogICAgICAgICAgIEBwcm9wZXJ0eSBfcXAKICAgICAgKi8KICAgIF9xcDogKDAsIF9tZXRhbC5jb21wdXRlZCkoZnVuY3Rpb24gKCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHZhciBjb21iaW5lZFF1ZXJ5UGFyYW1ldGVyQ29uZmlndXJhdGlvbjsKICAgICAgdmFyIGNvbnRyb2xsZXJOYW1lID0gdGhpcy5jb250cm9sbGVyTmFtZSB8fCB0aGlzLnJvdXRlTmFtZTsKICAgICAgdmFyIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikodGhpcyk7CiAgICAgIHZhciBjb250cm9sbGVyID0gb3duZXIubG9va3VwKCJjb250cm9sbGVyOiIgKyBjb250cm9sbGVyTmFtZSk7CiAgICAgIHZhciBxdWVyeVBhcmFtZXRlckNvbmZpZ3VyYXRvbiA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAncXVlcnlQYXJhbXMnKTsKICAgICAgdmFyIGhhc1JvdXRlckRlZmluZWRRdWVyeVBhcmFtcyA9IE9iamVjdC5rZXlzKHF1ZXJ5UGFyYW1ldGVyQ29uZmlndXJhdG9uKS5sZW5ndGggPiAwOwoKICAgICAgaWYgKGNvbnRyb2xsZXIpIHsKICAgICAgICAvLyB0aGUgZGV2ZWxvcGVyIGhhcyBhdXRob3JlZCBhIGNvbnRyb2xsZXIgY2xhc3MgaW4gdGhlaXIgYXBwbGljYXRpb24gZm9yCiAgICAgICAgLy8gdGhpcyByb3V0ZSBmaW5kIGl0cyBxdWVyeSBwYXJhbXMgYW5kIG5vcm1hbGl6ZSB0aGVpciBvYmplY3Qgc2hhcGUgdGhlbQogICAgICAgIC8vIG1lcmdlIGluIHRoZSBxdWVyeSBwYXJhbXMgZm9yIHRoZSByb3V0ZS4gQXMgYSBtZXJnZWRQcm9wZXJ0eSwKICAgICAgICAvLyBSb3V0ZSNxdWVyeVBhcmFtcyBpcyBhbHdheXMgYXQgbGVhc3QgYHt9YAogICAgICAgIHZhciBjb250cm9sbGVyRGVmaW5lZFF1ZXJ5UGFyYW1ldGVyQ29uZmlndXJhdGlvbiA9ICgwLCBfbWV0YWwuZ2V0KShjb250cm9sbGVyLCAncXVlcnlQYXJhbXMnKSB8fCB7fTsKICAgICAgICB2YXIgbm9ybWFsaXplZENvbnRyb2xsZXJRdWVyeVBhcmFtZXRlckNvbmZpZ3VyYXRpb24gPSAoMCwgX3V0aWxzMi5ub3JtYWxpemVDb250cm9sbGVyUXVlcnlQYXJhbXMpKGNvbnRyb2xsZXJEZWZpbmVkUXVlcnlQYXJhbWV0ZXJDb25maWd1cmF0aW9uKTsKICAgICAgICBjb21iaW5lZFF1ZXJ5UGFyYW1ldGVyQ29uZmlndXJhdGlvbiA9IG1lcmdlRWFjaFF1ZXJ5UGFyYW1zKG5vcm1hbGl6ZWRDb250cm9sbGVyUXVlcnlQYXJhbWV0ZXJDb25maWd1cmF0aW9uLCBxdWVyeVBhcmFtZXRlckNvbmZpZ3VyYXRvbik7CiAgICAgIH0gZWxzZSBpZiAoaGFzUm91dGVyRGVmaW5lZFF1ZXJ5UGFyYW1zKSB7CiAgICAgICAgLy8gdGhlIGRldmVsb3BlciBoYXMgbm90IGRlZmluZWQgYSBjb250cm9sbGVyIGJ1dCAqaGFzKiBzdXBwbGllZCByb3V0ZSBxdWVyeSBwYXJhbXMuCiAgICAgICAgLy8gR2VuZXJhdGUgYSBjbGFzcyBmb3IgdGhlbSBzbyB3ZSBjYW4gbGF0ZXIgaW5zZXJ0IGRlZmF1bHQgdmFsdWVzCiAgICAgICAgY29udHJvbGxlciA9ICgwLCBfZ2VuZXJhdGVfY29udHJvbGxlci5kZWZhdWx0KShvd25lciwgY29udHJvbGxlck5hbWUpOwogICAgICAgIGNvbWJpbmVkUXVlcnlQYXJhbWV0ZXJDb25maWd1cmF0aW9uID0gcXVlcnlQYXJhbWV0ZXJDb25maWd1cmF0b247CiAgICAgIH0KCiAgICAgIHZhciBxcHMgPSBbXTsKICAgICAgdmFyIG1hcCA9IHt9OwogICAgICB2YXIgcHJvcGVydHlOYW1lcyA9IFtdOwoKICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gY29tYmluZWRRdWVyeVBhcmFtZXRlckNvbmZpZ3VyYXRpb24pIHsKICAgICAgICBpZiAoIWNvbWJpbmVkUXVlcnlQYXJhbWV0ZXJDb25maWd1cmF0aW9uLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfSAvLyB0byBzdXBwb3J0IHRoZSBkdWJpb3VzIGZlYXR1cmUgb2YgdXNpbmcgdW5rbm93blByb3BlcnR5CiAgICAgICAgLy8gb24gcXVlcnlQYXJhbXMgY29uZmlndXJhdGlvbgoKCiAgICAgICAgaWYgKHByb3BOYW1lID09PSAndW5rbm93blByb3BlcnR5JyB8fCBwcm9wTmFtZSA9PT0gJ19zdXBlcicpIHsKICAgICAgICAgIC8vIHBvc3NpYmxlIHRvZG86IGlzc3VlIGRlcHJlY2F0aW9uIHdhcm5pbmc/CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIHZhciBkZXNjID0gY29tYmluZWRRdWVyeVBhcmFtZXRlckNvbmZpZ3VyYXRpb25bcHJvcE5hbWVdOwogICAgICAgIHZhciBzY29wZSA9IGRlc2Muc2NvcGUgfHwgJ21vZGVsJzsKICAgICAgICB2YXIgcGFydHMgPSB2b2lkIDA7CgogICAgICAgIGlmIChzY29wZSA9PT0gJ2NvbnRyb2xsZXInKSB7CiAgICAgICAgICBwYXJ0cyA9IFtdOwogICAgICAgIH0KCiAgICAgICAgdmFyIHVybEtleSA9IGRlc2MuYXMgfHwgdGhpcy5zZXJpYWxpemVRdWVyeVBhcmFtS2V5KHByb3BOYW1lKTsKICAgICAgICB2YXIgZGVmYXVsdFZhbHVlID0gKDAsIF9tZXRhbC5nZXQpKGNvbnRyb2xsZXIsIHByb3BOYW1lKTsKICAgICAgICBkZWZhdWx0VmFsdWUgPSBjb3B5RGVmYXVsdFZhbHVlKGRlZmF1bHRWYWx1ZSk7CiAgICAgICAgdmFyIHR5cGUgPSBkZXNjLnR5cGUgfHwgKDAsIF9ydW50aW1lLnR5cGVPZikoZGVmYXVsdFZhbHVlKTsKICAgICAgICB2YXIgZGVmYXVsdFZhbHVlU2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplUXVlcnlQYXJhbShkZWZhdWx0VmFsdWUsIHVybEtleSwgdHlwZSk7CiAgICAgICAgdmFyIHNjb3BlZFByb3BlcnR5TmFtZSA9IGNvbnRyb2xsZXJOYW1lICsgIjoiICsgcHJvcE5hbWU7CiAgICAgICAgdmFyIHFwID0gewogICAgICAgICAgdW5kZWNvcmF0ZWREZWZhdWx0VmFsdWU6ICgwLCBfbWV0YWwuZ2V0KShjb250cm9sbGVyLCBwcm9wTmFtZSksCiAgICAgICAgICBkZWZhdWx0VmFsdWU6IGRlZmF1bHRWYWx1ZSwKICAgICAgICAgIHNlcmlhbGl6ZWREZWZhdWx0VmFsdWU6IGRlZmF1bHRWYWx1ZVNlcmlhbGl6ZWQsCiAgICAgICAgICBzZXJpYWxpemVkVmFsdWU6IGRlZmF1bHRWYWx1ZVNlcmlhbGl6ZWQsCiAgICAgICAgICB0eXBlOiB0eXBlLAogICAgICAgICAgdXJsS2V5OiB1cmxLZXksCiAgICAgICAgICBwcm9wOiBwcm9wTmFtZSwKICAgICAgICAgIHNjb3BlZFByb3BlcnR5TmFtZTogc2NvcGVkUHJvcGVydHlOYW1lLAogICAgICAgICAgY29udHJvbGxlck5hbWU6IGNvbnRyb2xsZXJOYW1lLAogICAgICAgICAgcm91dGU6IHRoaXMsCiAgICAgICAgICBwYXJ0czogcGFydHMsCiAgICAgICAgICB2YWx1ZXM6IG51bGwsCiAgICAgICAgICBzY29wZTogc2NvcGUKICAgICAgICB9OwogICAgICAgIG1hcFtwcm9wTmFtZV0gPSBtYXBbdXJsS2V5XSA9IG1hcFtzY29wZWRQcm9wZXJ0eU5hbWVdID0gcXA7CiAgICAgICAgcXBzLnB1c2gocXApOwogICAgICAgIHByb3BlcnR5TmFtZXMucHVzaChwcm9wTmFtZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB7CiAgICAgICAgcXBzOiBxcHMsCiAgICAgICAgbWFwOiBtYXAsCiAgICAgICAgcHJvcGVydHlOYW1lczogcHJvcGVydHlOYW1lcywKICAgICAgICBzdGF0ZXM6IHsKICAgICAgICAgIC8qCiAgICAgICAgICAgIENhbGxlZCB3aGVuIGEgcXVlcnkgcGFyYW1ldGVyIGNoYW5nZXMgaW4gdGhlIFVSTCwgdGhpcyByb3V0ZSBjYXJlcwogICAgICAgICAgICBhYm91dCB0aGF0IHF1ZXJ5IHBhcmFtZXRlciwgYnV0IHRoZSByb3V0ZSBpcyBub3QgY3VycmVudGx5CiAgICAgICAgICAgIGluIHRoZSBhY3RpdmUgcm91dGUgaGllcmFyY2h5LgogICAgICAgICAgKi8KICAgICAgICAgIGluYWN0aXZlOiBmdW5jdGlvbiBpbmFjdGl2ZShwcm9wLCB2YWx1ZSkgewogICAgICAgICAgICB2YXIgcXAgPSBtYXBbcHJvcF07CgogICAgICAgICAgICBfdGhpczMuX3FwQ2hhbmdlZChwcm9wLCB2YWx1ZSwgcXApOwogICAgICAgICAgfSwKCiAgICAgICAgICAvKgogICAgICAgICAgICBDYWxsZWQgd2hlbiBhIHF1ZXJ5IHBhcmFtZXRlciBjaGFuZ2VzIGluIHRoZSBVUkwsIHRoaXMgcm91dGUgY2FyZXMKICAgICAgICAgICAgYWJvdXQgdGhhdCBxdWVyeSBwYXJhbWV0ZXIsIGFuZCB0aGUgcm91dGUgaXMgY3VycmVudGx5CiAgICAgICAgICAgIGluIHRoZSBhY3RpdmUgcm91dGUgaGllcmFyY2h5LgogICAgICAgICAgKi8KICAgICAgICAgIGFjdGl2ZTogZnVuY3Rpb24gYWN0aXZlKHByb3AsIHZhbHVlKSB7CiAgICAgICAgICAgIHZhciBxcCA9IG1hcFtwcm9wXTsKCiAgICAgICAgICAgIF90aGlzMy5fcXBDaGFuZ2VkKHByb3AsIHZhbHVlLCBxcCk7CgogICAgICAgICAgICByZXR1cm4gX3RoaXMzLl9hY3RpdmVRUENoYW5nZWQocXAsIHZhbHVlKTsKICAgICAgICAgIH0sCgogICAgICAgICAgLyoKICAgICAgICAgICAgQ2FsbGVkIHdoZW4gYSB2YWx1ZSBvZiBhIHF1ZXJ5IHBhcmFtZXRlciB0aGlzIHJvdXRlIGhhbmRsZXMgY2hhbmdlcyBpbiBhIGNvbnRyb2xsZXIKICAgICAgICAgICAgYW5kIHRoZSByb3V0ZSBpcyBjdXJyZW50bHkgaW4gdGhlIGFjdGl2ZSByb3V0ZSBoaWVyYXJjaHkuCiAgICAgICAgICAqLwogICAgICAgICAgYWxsb3dPdmVycmlkZXM6IGZ1bmN0aW9uIGFsbG93T3ZlcnJpZGVzKHByb3AsIHZhbHVlKSB7CiAgICAgICAgICAgIHZhciBxcCA9IG1hcFtwcm9wXTsKCiAgICAgICAgICAgIF90aGlzMy5fcXBDaGFuZ2VkKHByb3AsIHZhbHVlLCBxcCk7CgogICAgICAgICAgICByZXR1cm4gX3RoaXMzLl91cGRhdGluZ1FQQ2hhbmdlZChxcCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9OwogICAgfSksCgogICAgLyoqCiAgICAgIFNlbmRzIGFuIGFjdGlvbiB0byB0aGUgcm91dGVyLCB3aGljaCB3aWxsIGRlbGVnYXRlIGl0IHRvIHRoZSBjdXJyZW50bHkKICAgICAgYWN0aXZlIHJvdXRlIGhpZXJhcmNoeSBwZXIgdGhlIGJ1YmJsaW5nIHJ1bGVzIGV4cGxhaW5lZCB1bmRlciBgYWN0aW9uc2AuCiAgICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlci5qcwogICAgICAvLyAuLi4KICAgICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLnJvdXRlKCdpbmRleCcpOwogICAgICB9KTsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGVyOwogICAgICBgYGAKICAgICAgICAgYGBgYXBwL3JvdXRlcy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHRyYWNrKGFyZykgewogICAgICAgICAgICBjb25zb2xlLmxvZyhhcmcsICd3YXMgY2xpY2tlZCcpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBgYGBhcHAvcm91dGVzL2luZGV4LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgdHJhY2tJZkRlYnVnKGFyZykgewogICAgICAgICAgICBpZiAoZGVidWcpIHsKICAgICAgICAgICAgICB0aGlzLnNlbmQoJ3RyYWNrJywgYXJnKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHNlbmQKICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIGFjdGlvbiB0byB0cmlnZ2VyCiAgICAgIEBwYXJhbSB7Li4uKn0gYXJncwogICAgICBAc2luY2UgMS4wLjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHNlbmQ6IGZ1bmN0aW9uIHNlbmQoKSB7CiAgICAgIGZvciAodmFyIF9sZW40ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuNCksIF9rZXk0ID0gMDsgX2tleTQgPCBfbGVuNDsgX2tleTQrKykgewogICAgICAgIGFyZ3NbX2tleTRdID0gYXJndW1lbnRzW19rZXk0XTsKICAgICAgfQoKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF0dGVtcHRlZCB0byBjYWxsIC5zZW5kKCkgd2l0aCB0aGUgYWN0aW9uICciICsgYXJnc1swXSArICInIG9uIHRoZSBkZXN0cm95ZWQgcm91dGUgJyIgKyB0aGlzLnJvdXRlTmFtZSArICInLiIsICF0aGlzLmlzRGVzdHJveWluZyAmJiAhdGhpcy5pc0Rlc3Ryb3llZCkpOwoKICAgICAgaWYgKHRoaXMuX3JvdXRlciAmJiB0aGlzLl9yb3V0ZXIuX3JvdXRlck1pY3JvbGliIHx8ICEoMCwgX2RlYnVnLmlzVGVzdGluZykoKSkgewogICAgICAgIHZhciBfdGhpcyRfcm91dGVyNDsKCiAgICAgICAgKF90aGlzJF9yb3V0ZXI0ID0gdGhpcy5fcm91dGVyKS5zZW5kLmFwcGx5KF90aGlzJF9yb3V0ZXI0LCBhcmdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgbmFtZSA9IGFyZ3Muc2hpZnQoKTsKICAgICAgICB2YXIgYWN0aW9uID0gdGhpcy5hY3Rpb25zW25hbWVdOwoKICAgICAgICBpZiAoYWN0aW9uKSB7CiAgICAgICAgICByZXR1cm4gYWN0aW9uLmFwcGx5KHRoaXMsIGFyZ3MpOwogICAgICAgIH0KICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgVGhlIGNvbnRyb2xsZXIgYXNzb2NpYXRlZCB3aXRoIHRoaXMgcm91dGUuCiAgICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3JvdXRlcy9mb3JtLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgd2lsbFRyYW5zaXRpb24odHJhbnNpdGlvbikgewogICAgICAgICAgICBpZiAodGhpcy5jb250cm9sbGVyLmdldCgndXNlckhhc0VudGVyZWREYXRhJykgJiYKICAgICAgICAgICAgICAgICFjb25maXJtKCdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gYWJhbmRvbiBwcm9ncmVzcz8nKSkgewogICAgICAgICAgICAgIHRyYW5zaXRpb24uYWJvcnQoKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAvLyBCdWJibGUgdGhlIGB3aWxsVHJhbnNpdGlvbmAgYWN0aW9uIHNvIHRoYXQKICAgICAgICAgICAgICAvLyBwYXJlbnQgcm91dGVzIGNhbiBkZWNpZGUgd2hldGhlciBvciBub3QgdG8gYWJvcnQuCiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQHByb3BlcnR5IGNvbnRyb2xsZXIKICAgICAgQHR5cGUgQ29udHJvbGxlcgogICAgICBAc2luY2UgMS42LjAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIGFjdGlvbnM6IHsKICAgICAgLyoqCiAgICAgIFRoaXMgYWN0aW9uIGlzIGNhbGxlZCB3aGVuIG9uZSBvciBtb3JlIHF1ZXJ5IHBhcmFtcyBoYXZlIGNoYW5nZWQuIEJ1YmJsZXMuCiAgICAgICAgICAgQG1ldGhvZCBxdWVyeVBhcmFtc0RpZENoYW5nZQogICAgICBAcGFyYW0gY2hhbmdlZCB7T2JqZWN0fSBLZXlzIGFyZSBuYW1lcyBvZiBxdWVyeSBwYXJhbXMgdGhhdCBoYXZlIGNoYW5nZWQuCiAgICAgIEBwYXJhbSB0b3RhbFByZXNlbnQge09iamVjdH0gS2V5cyBhcmUgbmFtZXMgb2YgcXVlcnkgcGFyYW1zIHRoYXQgYXJlIGN1cnJlbnRseSBzZXQuCiAgICAgIEBwYXJhbSByZW1vdmVkIHtPYmplY3R9IEtleXMgYXJlIG5hbWVzIG9mIHF1ZXJ5IHBhcmFtcyB0aGF0IGhhdmUgYmVlbiByZW1vdmVkLgogICAgICBAcmV0dXJucyB7Ym9vbGVhbn0KICAgICAgQHByaXZhdGUKICAgICAgKi8KICAgICAgcXVlcnlQYXJhbXNEaWRDaGFuZ2U6IGZ1bmN0aW9uIHF1ZXJ5UGFyYW1zRGlkQ2hhbmdlKGNoYW5nZWQsIF90b3RhbFByZXNlbnQsIHJlbW92ZWQpIHsKICAgICAgICB2YXIgcXBNYXAgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ19xcCcpLm1hcDsKICAgICAgICB2YXIgdG90YWxDaGFuZ2VkID0gT2JqZWN0LmtleXMoY2hhbmdlZCkuY29uY2F0KE9iamVjdC5rZXlzKHJlbW92ZWQpKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0b3RhbENoYW5nZWQubGVuZ3RoOyArK2kpIHsKICAgICAgICAgIHZhciBxcCA9IHFwTWFwW3RvdGFsQ2hhbmdlZFtpXV07CgogICAgICAgICAgaWYgKHFwICYmICgwLCBfbWV0YWwuZ2V0KSh0aGlzLl9vcHRpb25zRm9yUXVlcnlQYXJhbShxcCksICdyZWZyZXNoTW9kZWwnKSAmJiB0aGlzLl9yb3V0ZXIuY3VycmVudFN0YXRlKSB7CiAgICAgICAgICAgIHRoaXMucmVmcmVzaCgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9LAogICAgICBmaW5hbGl6ZVF1ZXJ5UGFyYW1DaGFuZ2U6IGZ1bmN0aW9uIGZpbmFsaXplUXVlcnlQYXJhbUNoYW5nZShwYXJhbXMsIGZpbmFsUGFyYW1zLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgaWYgKHRoaXMuZnVsbFJvdXRlTmFtZSAhPT0gJ2FwcGxpY2F0aW9uJykgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfSAvLyBUcmFuc2l0aW9uIG9iamVjdCBpcyBhYnNlbnQgZm9yIGludGVybWVkaWF0ZSB0cmFuc2l0aW9ucy4KCgogICAgICAgIGlmICghdHJhbnNpdGlvbikgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgdmFyIHJvdXRlSW5mb3MgPSB0cmFuc2l0aW9uW19yb3V0ZXJfanMuU1RBVEVfU1lNQk9MXS5yb3V0ZUluZm9zOwogICAgICAgIHZhciByb3V0ZXIgPSB0aGlzLl9yb3V0ZXI7CgogICAgICAgIHZhciBxcE1ldGEgPSByb3V0ZXIuX3F1ZXJ5UGFyYW1zRm9yKHJvdXRlSW5mb3MpOwoKICAgICAgICB2YXIgY2hhbmdlcyA9IHJvdXRlci5fcXBVcGRhdGVzOwogICAgICAgIHZhciBxcFVwZGF0ZWQgPSBmYWxzZTsKICAgICAgICB2YXIgcmVwbGFjZVVybDsKICAgICAgICAoMCwgX3V0aWxzMi5zdGFzaFBhcmFtTmFtZXMpKHJvdXRlciwgcm91dGVJbmZvcyk7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcXBNZXRhLnFwcy5sZW5ndGg7ICsraSkgewogICAgICAgICAgdmFyIHFwID0gcXBNZXRhLnFwc1tpXTsKICAgICAgICAgIHZhciByb3V0ZSA9IHFwLnJvdXRlOwogICAgICAgICAgdmFyIGNvbnRyb2xsZXIgPSByb3V0ZS5jb250cm9sbGVyOwogICAgICAgICAgdmFyIHByZXNlbnRLZXkgPSBxcC51cmxLZXkgaW4gcGFyYW1zICYmIHFwLnVybEtleTsgLy8gRG8gYSByZXZlcnNlIGxvb2t1cCB0byBzZWUgaWYgdGhlIGNoYW5nZWQgcXVlcnkKICAgICAgICAgIC8vIHBhcmFtIFVSTCBrZXkgY29ycmVzcG9uZHMgdG8gYSBRUCBwcm9wZXJ0eSBvbgogICAgICAgICAgLy8gdGhpcyBjb250cm9sbGVyLgoKICAgICAgICAgIHZhciB2YWx1ZSA9IHZvaWQgMCwKICAgICAgICAgICAgICBzdmFsdWUgPSB2b2lkIDA7CgogICAgICAgICAgaWYgKGNoYW5nZXMuaGFzKHFwLnVybEtleSkpIHsKICAgICAgICAgICAgLy8gVmFsdWUgdXBkYXRlZCBpbi9iZWZvcmUgc2V0dXBDb250cm9sbGVyCiAgICAgICAgICAgIHZhbHVlID0gKDAsIF9tZXRhbC5nZXQpKGNvbnRyb2xsZXIsIHFwLnByb3ApOwogICAgICAgICAgICBzdmFsdWUgPSByb3V0ZS5zZXJpYWxpemVRdWVyeVBhcmFtKHZhbHVlLCBxcC51cmxLZXksIHFwLnR5cGUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKHByZXNlbnRLZXkpIHsKICAgICAgICAgICAgICBzdmFsdWUgPSBwYXJhbXNbcHJlc2VudEtleV07CgogICAgICAgICAgICAgIGlmIChzdmFsdWUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgdmFsdWUgPSByb3V0ZS5kZXNlcmlhbGl6ZVF1ZXJ5UGFyYW0oc3ZhbHVlLCBxcC51cmxLZXksIHFwLnR5cGUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAvLyBObyBRUCBwcm92aWRlZDsgdXNlIGRlZmF1bHQgdmFsdWUuCiAgICAgICAgICAgICAgc3ZhbHVlID0gcXAuc2VyaWFsaXplZERlZmF1bHRWYWx1ZTsKICAgICAgICAgICAgICB2YWx1ZSA9IGNvcHlEZWZhdWx0VmFsdWUocXAuZGVmYXVsdFZhbHVlKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQoKICAgICAgICAgIGNvbnRyb2xsZXIuX3FwRGVsZWdhdGUgPSAoMCwgX21ldGFsLmdldCkocm91dGUsICdfcXAuc3RhdGVzLmluYWN0aXZlJyk7CiAgICAgICAgICB2YXIgdGhpc1F1ZXJ5UGFyYW1DaGFuZ2VkID0gc3ZhbHVlICE9PSBxcC5zZXJpYWxpemVkVmFsdWU7CgogICAgICAgICAgaWYgKHRoaXNRdWVyeVBhcmFtQ2hhbmdlZCkgewogICAgICAgICAgICBpZiAodHJhbnNpdGlvbi5xdWVyeVBhcmFtc09ubHkgJiYgcmVwbGFjZVVybCAhPT0gZmFsc2UpIHsKICAgICAgICAgICAgICB2YXIgb3B0aW9ucyA9IHJvdXRlLl9vcHRpb25zRm9yUXVlcnlQYXJhbShxcCk7CgogICAgICAgICAgICAgIHZhciByZXBsYWNlQ29uZmlnVmFsdWUgPSAoMCwgX21ldGFsLmdldCkob3B0aW9ucywgJ3JlcGxhY2UnKTsKCiAgICAgICAgICAgICAgaWYgKHJlcGxhY2VDb25maWdWYWx1ZSkgewogICAgICAgICAgICAgICAgcmVwbGFjZVVybCA9IHRydWU7CiAgICAgICAgICAgICAgfSBlbHNlIGlmIChyZXBsYWNlQ29uZmlnVmFsdWUgPT09IGZhbHNlKSB7CiAgICAgICAgICAgICAgICAvLyBFeHBsaWNpdCBwdXNoU3RhdGUgd2lucyBvdmVyIGFueSBvdGhlciByZXBsYWNlU3RhdGVzLgogICAgICAgICAgICAgICAgcmVwbGFjZVVybCA9IGZhbHNlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgKDAsIF9tZXRhbC5zZXQpKGNvbnRyb2xsZXIsIHFwLnByb3AsIHZhbHVlKTsKICAgICAgICAgICAgcXBVcGRhdGVkID0gdHJ1ZTsKICAgICAgICAgIH0gLy8gU3Rhc2ggY3VycmVudCBzZXJpYWxpemVkIHZhbHVlIG9mIGNvbnRyb2xsZXIuCgoKICAgICAgICAgIHFwLnNlcmlhbGl6ZWRWYWx1ZSA9IHN2YWx1ZTsKICAgICAgICAgIHZhciB0aGlzUXVlcnlQYXJhbUhhc0RlZmF1bHRWYWx1ZSA9IHFwLnNlcmlhbGl6ZWREZWZhdWx0VmFsdWUgPT09IHN2YWx1ZTsKCiAgICAgICAgICBpZiAoIXRoaXNRdWVyeVBhcmFtSGFzRGVmYXVsdFZhbHVlIHx8IHRyYW5zaXRpb24uX2tlZXBEZWZhdWx0UXVlcnlQYXJhbVZhbHVlcykgewogICAgICAgICAgICBmaW5hbFBhcmFtcy5wdXNoKHsKICAgICAgICAgICAgICB2YWx1ZTogc3ZhbHVlLAogICAgICAgICAgICAgIHZpc2libGU6IHRydWUsCiAgICAgICAgICAgICAga2V5OiBwcmVzZW50S2V5IHx8IHFwLnVybEtleQogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9IC8vIFNvbWUgUVBzIGhhdmUgYmVlbiB1cGRhdGVkLCBhbmQgdGhvc2UgY2hhbmdlcyBuZWVkIHRvIGJlIHByb3BvZ2F0ZWQKICAgICAgICAvLyBpbW1lZGlhdGVseS4gRXZlbnR1YWxseSwgd2Ugc2hvdWxkIHdvcmsgb24gbWFraW5nIHRoaXMgYXN5bmMgc29tZWhvdy4KCgogICAgICAgIGlmICh0cnVlCiAgICAgICAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgICAgICAgJiYgcXBVcGRhdGVkID09PSB0cnVlKSB7CiAgICAgICAgICAoMCwgX21ldGFsLmZsdXNoQXN5bmNPYnNlcnZlcnMpKGZhbHNlKTsKICAgICAgICB9CgogICAgICAgIGlmIChyZXBsYWNlVXJsKSB7CiAgICAgICAgICB0cmFuc2l0aW9uLm1ldGhvZCgncmVwbGFjZScpOwogICAgICAgIH0KCiAgICAgICAgcXBNZXRhLnFwcy5mb3JFYWNoKGZ1bmN0aW9uIChxcCkgewogICAgICAgICAgdmFyIHJvdXRlUXBNZXRhID0gKDAsIF9tZXRhbC5nZXQpKHFwLnJvdXRlLCAnX3FwJyk7CiAgICAgICAgICB2YXIgZmluYWxpemVkQ29udHJvbGxlciA9IHFwLnJvdXRlLmNvbnRyb2xsZXI7CiAgICAgICAgICBmaW5hbGl6ZWRDb250cm9sbGVyLl9xcERlbGVnYXRlID0gKDAsIF9tZXRhbC5nZXQpKHJvdXRlUXBNZXRhLCAnc3RhdGVzLmFjdGl2ZScpOwogICAgICAgIH0pOwoKICAgICAgICByb3V0ZXIuX3FwVXBkYXRlcy5jbGVhcigpOwoKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgIH0KICB9KTsKICB2YXIgUk9VVEVSX0VWRU5UX0RFUFJFQ0FUSU9OUzsKICBfZXhwb3J0cy5ST1VURVJfRVZFTlRfREVQUkVDQVRJT05TID0gUk9VVEVSX0VWRU5UX0RFUFJFQ0FUSU9OUzsKCiAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuUk9VVEVSX0VWRU5UUykgewogICAgX2V4cG9ydHMuUk9VVEVSX0VWRU5UX0RFUFJFQ0FUSU9OUyA9IFJPVVRFUl9FVkVOVF9ERVBSRUNBVElPTlMgPSB7CiAgICAgIG9uOiBmdW5jdGlvbiBvbihuYW1lKSB7CiAgICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgICAgdmFyIGhhc0RpZFRyYW5zaXRpb24gPSBuYW1lID09PSAnZGlkVHJhbnNpdGlvbic7CiAgICAgICAgdmFyIGhhc1dpbGxUcmFuc2l0aW9uID0gbmFtZSA9PT0gJ3dpbGxUcmFuc2l0aW9uJzsKCiAgICAgICAgaWYgKGhhc0RpZFRyYW5zaXRpb24pIHsKICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoJ1lvdSBhdHRlbXB0ZWQgdG8gbGlzdGVuIHRvIHRoZSAiZGlkVHJhbnNpdGlvbiIgZXZlbnQgd2hpY2ggaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGluamVjdCB0aGUgcm91dGVyIHNlcnZpY2UgYW5kIGxpc3RlbiB0byB0aGUgInJvdXRlRGlkQ2hhbmdlIiBldmVudC4nLCBmYWxzZSwgewogICAgICAgICAgICBpZDogJ2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJywKICAgICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJwogICAgICAgICAgfSkpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGhhc1dpbGxUcmFuc2l0aW9uKSB7CiAgICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdZb3UgYXR0ZW1wdGVkIHRvIGxpc3RlbiB0byB0aGUgIndpbGxUcmFuc2l0aW9uIiBldmVudCB3aGljaCBpcyBkZXByZWNhdGVkLiBQbGVhc2UgaW5qZWN0IHRoZSByb3V0ZXIgc2VydmljZSBhbmQgbGlzdGVuIHRvIHRoZSAicm91dGVXaWxsQ2hhbmdlIiBldmVudC4nLCBmYWxzZSwgewogICAgICAgICAgICBpZDogJ2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJywKICAgICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJwogICAgICAgICAgfSkpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKICAgIFJvdXRlLnJlb3BlbihST1VURVJfRVZFTlRfREVQUkVDQVRJT05TLCB7CiAgICAgIF9wYXJhbXNGb3I6IGZ1bmN0aW9uIF9wYXJhbXNGb3Iocm91dGVOYW1lLCBwYXJhbXMpIHsKICAgICAgICB2YXIgdHJhbnNpdGlvbiA9IHRoaXMuX3JvdXRlci5fcm91dGVyTWljcm9saWIuYWN0aXZlVHJhbnNpdGlvbjsKCiAgICAgICAgaWYgKHRyYW5zaXRpb24gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcmV0dXJuIHRoaXMucGFyYW1zRm9yKHJvdXRlTmFtZSk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcGFyYW1zOwogICAgICB9CiAgICB9KTsKICB9CgogIGlmICh0cnVlCiAgLyogRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCAqLwogICkgewogICAgICAoMCwgX3J1bnRpbWUuc2V0RnJhbWV3b3JrQ2xhc3MpKFJvdXRlKTsKICAgIH0KCiAgdmFyIF9kZWZhdWx0ID0gUm91dGU7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vcm91dGVyIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIiwgIkBlbWJlci9lcnJvciIsICJAZW1iZXIvcG9seWZpbGxzIiwgIkBlbWJlci9ydW5sb29wIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL2xvY2F0aW9uL2FwaSIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi91dGlscyIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vZHNsIiwgIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3N5c3RlbS9yb3V0ZSIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vcm91dGVyX3N0YXRlIiwgInJvdXRlcl9qcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfbWV0YWwsIF9vd25lciwgX3J1bnRpbWUsIF9kZWJ1ZywgX2RlcHJlY2F0ZWRGZWF0dXJlcywgX2Vycm9yMywgX3BvbHlmaWxscywgX3J1bmxvb3AsIF9hcGksIF91dGlscywgX2RzbCwgX3JvdXRlLCBfcm91dGVyX3N0YXRlLCBfcm91dGVyX2pzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy50cmlnZ2VyRXZlbnQgPSBfdHJpZ2dlckV2ZW50OwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIGZ1bmN0aW9uIGRlZmF1bHREaWRUcmFuc2l0aW9uKGluZm9zKSB7CiAgICB1cGRhdGVQYXRocyh0aGlzKTsKCiAgICB0aGlzLl9jYW5jZWxTbG93VHJhbnNpdGlvblRpbWVyKCk7CgogICAgdGhpcy5ub3RpZnlQcm9wZXJ0eUNoYW5nZSgndXJsJyk7CiAgICB0aGlzLnNldCgnY3VycmVudFN0YXRlJywgdGhpcy50YXJnZXRTdGF0ZSk7IC8vIFB1dCB0aGlzIGluIHRoZSBydW5sb29wIHNvIHVybCB3aWxsIGJlIGFjY3VyYXRlLiBTZWVtcwogICAgLy8gbGVzcyBzdXJwcmlzaW5nIHRoYW4gZGlkVHJhbnNpdGlvbiBiZWluZyBvdXQgb2Ygc3luYy4KCiAgICAoMCwgX3J1bmxvb3Aub25jZSkodGhpcywgdGhpcy50cmlnZ2VyLCAnZGlkVHJhbnNpdGlvbicpOwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBpZiAoKDAsIF9tZXRhbC5nZXQpKHRoaXMsICduYW1lc3BhY2UnKS5MT0dfVFJBTlNJVElPTlMpIHsKICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZQogICAgICAgIGNvbnNvbGUubG9nKCJUcmFuc2l0aW9uZWQgaW50byAnIiArIEVtYmVyUm91dGVyLl9yb3V0ZVBhdGgoaW5mb3MpICsgIiciKTsKICAgICAgfQogICAgfQogIH0KCiAgZnVuY3Rpb24gZGVmYXVsdFdpbGxUcmFuc2l0aW9uKG9sZEluZm9zLCBuZXdJbmZvcywgdHJhbnNpdGlvbikgewogICAgKDAsIF9ydW5sb29wLm9uY2UpKHRoaXMsIHRoaXMudHJpZ2dlciwgJ3dpbGxUcmFuc2l0aW9uJywgdHJhbnNpdGlvbik7CgogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgKSB7CiAgICAgIGlmICgoMCwgX21ldGFsLmdldCkodGhpcywgJ25hbWVzcGFjZScpLkxPR19UUkFOU0lUSU9OUykgewogICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlCiAgICAgICAgY29uc29sZS5sb2coIlByZXBhcmluZyB0byB0cmFuc2l0aW9uIGZyb20gJyIgKyBFbWJlclJvdXRlci5fcm91dGVQYXRoKG9sZEluZm9zKSArICInIHRvICciICsgRW1iZXJSb3V0ZXIuX3JvdXRlUGF0aChuZXdJbmZvcykgKyAiJyIpOwogICAgICB9CiAgICB9CiAgfQoKICBmdW5jdGlvbiBLKCkgewogICAgcmV0dXJuIHRoaXM7CiAgfQoKICB2YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7CiAgLyoqCiAgICBUaGUgYEVtYmVyUm91dGVyYCBjbGFzcyBtYW5hZ2VzIHRoZSBhcHBsaWNhdGlvbiBzdGF0ZSBhbmQgVVJMcy4gUmVmZXIgdG8KICAgIHRoZSBbcm91dGluZyBndWlkZV0oaHR0cHM6Ly9ndWlkZXMuZW1iZXJqcy5jb20vcmVsZWFzZS9yb3V0aW5nLykgZm9yIGRvY3VtZW50YXRpb24uCiAgCiAgICBAY2xhc3MgRW1iZXJSb3V0ZXIKICAgIEBleHRlbmRzIEVtYmVyT2JqZWN0CiAgICBAdXNlcyBFdmVudGVkCiAgICBAcHVibGljCiAgKi8KCiAgdmFyIEVtYmVyUm91dGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9FbWJlck9iamVjdCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEVtYmVyUm91dGVyLCBfRW1iZXJPYmplY3QpOwoKICAgIGZ1bmN0aW9uIEVtYmVyUm91dGVyKCkgewogICAgICB2YXIgX3RoaXM7CgogICAgICBfdGhpcyA9IF9FbWJlck9iamVjdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICAgIF90aGlzLmN1cnJlbnRVUkwgPSBudWxsOwogICAgICBfdGhpcy5jdXJyZW50Um91dGVOYW1lID0gbnVsbDsKICAgICAgX3RoaXMuY3VycmVudFBhdGggPSBudWxsOwogICAgICBfdGhpcy5jdXJyZW50Um91dGUgPSBudWxsOwogICAgICBfdGhpcy5fcXBDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIF90aGlzLl9xcFVwZGF0ZXMgPSBuZXcgU2V0KCk7CiAgICAgIF90aGlzLl9oYW5kbGVkRXJyb3JzID0gbmV3IFNldCgpOwogICAgICBfdGhpcy5fZW5naW5lSW5zdGFuY2VzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgX3RoaXMuX2VuZ2luZUluZm9CeVJvdXRlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgX3RoaXMuY3VycmVudFN0YXRlID0gbnVsbDsKICAgICAgX3RoaXMudGFyZ2V0U3RhdGUgPSBudWxsOwoKICAgICAgX3RoaXMuX3Jlc2V0UXVldWVkUXVlcnlQYXJhbWV0ZXJDaGFuZ2VzKCk7CgogICAgICByZXR1cm4gX3RoaXM7CiAgICB9CgogICAgdmFyIF9wcm90byA9IEVtYmVyUm91dGVyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uX2luaXRSb3V0ZXJKcyA9IGZ1bmN0aW9uIF9pbml0Um91dGVySnMoKSB7CiAgICAgIHZhciBsb2NhdGlvbiA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnbG9jYXRpb24nKTsKICAgICAgdmFyIHJvdXRlciA9IHRoaXM7CiAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICB2YXIgc2VlbiA9IE9iamVjdC5jcmVhdGUobnVsbCk7CgogICAgICB2YXIgUHJpdmF0ZVJvdXRlciA9CiAgICAgIC8qI19fUFVSRV9fKi8KICAgICAgZnVuY3Rpb24gKF9Sb3V0ZXIpIHsKICAgICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUHJpdmF0ZVJvdXRlciwgX1JvdXRlcik7CgogICAgICAgIGZ1bmN0aW9uIFByaXZhdGVSb3V0ZXIoKSB7CiAgICAgICAgICByZXR1cm4gX1JvdXRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICAgICAgfQoKICAgICAgICB2YXIgX3Byb3RvMiA9IFByaXZhdGVSb3V0ZXIucHJvdG90eXBlOwoKICAgICAgICBfcHJvdG8yLmdldFJvdXRlID0gZnVuY3Rpb24gZ2V0Um91dGUobmFtZSkgewogICAgICAgICAgdmFyIHJvdXRlTmFtZSA9IG5hbWU7CiAgICAgICAgICB2YXIgcm91dGVPd25lciA9IG93bmVyOwogICAgICAgICAgdmFyIGVuZ2luZUluZm8gPSByb3V0ZXIuX2VuZ2luZUluZm9CeVJvdXRlW3JvdXRlTmFtZV07CgogICAgICAgICAgaWYgKGVuZ2luZUluZm8pIHsKICAgICAgICAgICAgdmFyIGVuZ2luZUluc3RhbmNlID0gcm91dGVyLl9nZXRFbmdpbmVJbnN0YW5jZShlbmdpbmVJbmZvKTsKCiAgICAgICAgICAgIHJvdXRlT3duZXIgPSBlbmdpbmVJbnN0YW5jZTsKICAgICAgICAgICAgcm91dGVOYW1lID0gZW5naW5lSW5mby5sb2NhbEZ1bGxOYW1lOwogICAgICAgICAgfQoKICAgICAgICAgIHZhciBmdWxsUm91dGVOYW1lID0gInJvdXRlOiIgKyByb3V0ZU5hbWU7CiAgICAgICAgICB2YXIgcm91dGUgPSByb3V0ZU93bmVyLmxvb2t1cChmdWxsUm91dGVOYW1lKTsKCiAgICAgICAgICBpZiAoc2VlbltuYW1lXSkgewogICAgICAgICAgICByZXR1cm4gcm91dGU7CiAgICAgICAgICB9CgogICAgICAgICAgc2VlbltuYW1lXSA9IHRydWU7CgogICAgICAgICAgaWYgKCFyb3V0ZSkgewogICAgICAgICAgICB2YXIgRGVmYXVsdFJvdXRlID0gcm91dGVPd25lci5mYWN0b3J5Rm9yKCdyb3V0ZTpiYXNpYycpLmNsYXNzOwogICAgICAgICAgICByb3V0ZU93bmVyLnJlZ2lzdGVyKGZ1bGxSb3V0ZU5hbWUsIERlZmF1bHRSb3V0ZS5leHRlbmQoKSk7CiAgICAgICAgICAgIHJvdXRlID0gcm91dGVPd25lci5sb29rdXAoZnVsbFJvdXRlTmFtZSk7CgogICAgICAgICAgICBpZiAoZmFsc2UKICAgICAgICAgICAgLyogREVCVUcgKi8KICAgICAgICAgICAgKSB7CiAgICAgICAgICAgICAgaWYgKCgwLCBfbWV0YWwuZ2V0KShyb3V0ZXIsICduYW1lc3BhY2UuTE9HX0FDVElWRV9HRU5FUkFUSU9OJykpIHsKICAgICAgICAgICAgICAgICgwLCBfZGVidWcuaW5mbykoImdlbmVyYXRlZCAtPiAiICsgZnVsbFJvdXRlTmFtZSwgewogICAgICAgICAgICAgICAgICBmdWxsTmFtZTogZnVsbFJvdXRlTmFtZQogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgcm91dGUuX3NldFJvdXRlTmFtZShyb3V0ZU5hbWUpOwoKICAgICAgICAgIGlmIChlbmdpbmVJbmZvICYmICEoMCwgX3JvdXRlLmhhc0RlZmF1bHRTZXJpYWxpemUpKHJvdXRlKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RlZmluaW5nIGEgY3VzdG9tIHNlcmlhbGl6ZSBtZXRob2Qgb24gYW4gRW5naW5lIHJvdXRlIGlzIG5vdCBzdXBwb3J0ZWQuJyk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIHJvdXRlOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzIuZ2V0U2VyaWFsaXplciA9IGZ1bmN0aW9uIGdldFNlcmlhbGl6ZXIobmFtZSkgewogICAgICAgICAgdmFyIGVuZ2luZUluZm8gPSByb3V0ZXIuX2VuZ2luZUluZm9CeVJvdXRlW25hbWVdOyAvLyBJZiB0aGlzIGlzIG5vdCBhbiBFbmdpbmUgcm91dGUsIHdlIGZhbGwgYmFjayB0byB0aGUgaGFuZGxlciBmb3Igc2VyaWFsaXphdGlvbgoKICAgICAgICAgIGlmICghZW5naW5lSW5mbykgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIGVuZ2luZUluZm8uc2VyaWFsaXplTWV0aG9kIHx8IF9yb3V0ZS5kZWZhdWx0U2VyaWFsaXplOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzIudXBkYXRlVVJMID0gZnVuY3Rpb24gdXBkYXRlVVJMKHBhdGgpIHsKICAgICAgICAgICgwLCBfcnVubG9vcC5vbmNlKShmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIGxvY2F0aW9uLnNldFVSTChwYXRoKTsKICAgICAgICAgICAgKDAsIF9tZXRhbC5zZXQpKHJvdXRlciwgJ2N1cnJlbnRVUkwnLCBwYXRoKTsKICAgICAgICAgIH0pOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzIuZGlkVHJhbnNpdGlvbiA9IGZ1bmN0aW9uIGRpZFRyYW5zaXRpb24oaW5mb3MpIHsKICAgICAgICAgIGlmIChfZGVwcmVjYXRlZEZlYXR1cmVzLlJPVVRFUl9FVkVOVFMpIHsKICAgICAgICAgICAgaWYgKHJvdXRlci5kaWRUcmFuc2l0aW9uICE9PSBkZWZhdWx0RGlkVHJhbnNpdGlvbikgewogICAgICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoJ1lvdSBhdHRlbXB0ZWQgdG8gb3ZlcnJpZGUgdGhlICJkaWRUcmFuc2l0aW9uIiBtZXRob2Qgd2hpY2ggaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGluamVjdCB0aGUgcm91dGVyIHNlcnZpY2UgYW5kIGxpc3RlbiB0byB0aGUgInJvdXRlRGlkQ2hhbmdlIiBldmVudC4nLCBmYWxzZSwgewogICAgICAgICAgICAgICAgaWQ6ICdkZXByZWNhdGUtcm91dGVyLWV2ZW50cycsCiAgICAgICAgICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJwogICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQoKICAgICAgICAgIHJvdXRlci5kaWRUcmFuc2l0aW9uKGluZm9zKTsKICAgICAgICB9OwoKICAgICAgICBfcHJvdG8yLndpbGxUcmFuc2l0aW9uID0gZnVuY3Rpb24gd2lsbFRyYW5zaXRpb24ob2xkSW5mb3MsIG5ld0luZm9zLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5ST1VURVJfRVZFTlRTKSB7CiAgICAgICAgICAgIGlmIChyb3V0ZXIud2lsbFRyYW5zaXRpb24gIT09IGRlZmF1bHRXaWxsVHJhbnNpdGlvbikgewogICAgICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoJ1lvdSBhdHRlbXB0ZWQgdG8gb3ZlcnJpZGUgdGhlICJ3aWxsVHJhbnNpdGlvbiIgbWV0aG9kIHdoaWNoIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSBpbmplY3QgdGhlIHJvdXRlciBzZXJ2aWNlIGFuZCBsaXN0ZW4gdG8gdGhlICJyb3V0ZVdpbGxDaGFuZ2UiIGV2ZW50LicsIGZhbHNlLCB7CiAgICAgICAgICAgICAgICBpZDogJ2RlcHJlY2F0ZS1yb3V0ZXItZXZlbnRzJywKICAgICAgICAgICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfZGVwcmVjYXRlLXJvdXRlci1ldmVudHMnCiAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgcm91dGVyLndpbGxUcmFuc2l0aW9uKG9sZEluZm9zLCBuZXdJbmZvcywgdHJhbnNpdGlvbik7CiAgICAgICAgfTsKCiAgICAgICAgX3Byb3RvMi50cmlnZ2VyRXZlbnQgPSBmdW5jdGlvbiB0cmlnZ2VyRXZlbnQocm91dGVJbmZvcywgaWdub3JlRmFpbHVyZSwgbmFtZSwgYXJncykgewogICAgICAgICAgcmV0dXJuIF90cmlnZ2VyRXZlbnQuYmluZChyb3V0ZXIpKHJvdXRlSW5mb3MsIGlnbm9yZUZhaWx1cmUsIG5hbWUsIGFyZ3MpOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzIucm91dGVXaWxsQ2hhbmdlID0gZnVuY3Rpb24gcm91dGVXaWxsQ2hhbmdlKHRyYW5zaXRpb24pIHsKICAgICAgICAgIHJvdXRlci50cmlnZ2VyKCdyb3V0ZVdpbGxDaGFuZ2UnLCB0cmFuc2l0aW9uKTsKICAgICAgICB9OwoKICAgICAgICBfcHJvdG8yLnJvdXRlRGlkQ2hhbmdlID0gZnVuY3Rpb24gcm91dGVEaWRDaGFuZ2UodHJhbnNpdGlvbikgewogICAgICAgICAgcm91dGVyLnNldCgnY3VycmVudFJvdXRlJywgdHJhbnNpdGlvbi50byk7CiAgICAgICAgICAoMCwgX3J1bmxvb3Aub25jZSkoZnVuY3Rpb24gKCkgewogICAgICAgICAgICByb3V0ZXIudHJpZ2dlcigncm91dGVEaWRDaGFuZ2UnLCB0cmFuc2l0aW9uKTsKICAgICAgICAgIH0pOwogICAgICAgIH07CgogICAgICAgIF9wcm90bzIudHJhbnNpdGlvbkRpZEVycm9yID0gZnVuY3Rpb24gdHJhbnNpdGlvbkRpZEVycm9yKGVycm9yLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICBpZiAoZXJyb3Iud2FzQWJvcnRlZCB8fCB0cmFuc2l0aW9uLmlzQWJvcnRlZCkgewogICAgICAgICAgICAvLyBJZiB0aGUgZXJyb3Igd2FzIGEgdHJhbnNpdGlvbiBlcm9yciBvciB0aGUgdHJhbnNpdGlvbiBhYm9ydGVkCiAgICAgICAgICAgIC8vIGxvZyB0aGUgYWJvcnQuCiAgICAgICAgICAgIHJldHVybiAoMCwgX3JvdXRlcl9qcy5sb2dBYm9ydCkodHJhbnNpdGlvbik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvLyBPdGhlcndpc2UgdHJpZ2dlciB0aGUgImVycm9yIiBldmVudCB0byBhdHRlbXB0IGFuIGludGVybWVkaWF0ZQogICAgICAgICAgICAvLyB0cmFuc2l0aW9uIGludG8gYW4gZXJyb3Igc3Vic3RhdGUKICAgICAgICAgICAgdHJhbnNpdGlvbi50cmlnZ2VyKGZhbHNlLCAnZXJyb3InLCBlcnJvci5lcnJvciwgdHJhbnNpdGlvbiwgZXJyb3Iucm91dGUpOwoKICAgICAgICAgICAgaWYgKHJvdXRlci5faXNFcnJvckhhbmRsZWQoZXJyb3IuZXJyb3IpKSB7CiAgICAgICAgICAgICAgLy8gSWYgd2UgaGFuZGxlZCB0aGUgZXJyb3Igd2l0aCBhIHN1YnN0YXRlIGp1c3Qgcm9sbCB0aGUgc3RhdGUgYmFjayBvbgogICAgICAgICAgICAgIC8vIHRoZSB0cmFuc2l0aW9uIGFuZCBzZW5kIHRoZSAicm91dGVEaWRDaGFuZ2UiIGV2ZW50IGZvciBsYW5kaW5nIG9uCiAgICAgICAgICAgICAgLy8gdGhlIGVycm9yIHN1YnN0YXRlIGFuZCByZXR1cm4gdGhlIGVycm9yLgogICAgICAgICAgICAgIHRyYW5zaXRpb24ucm9sbGJhY2soKTsKICAgICAgICAgICAgICB0aGlzLnJvdXRlRGlkQ2hhbmdlKHRyYW5zaXRpb24pOwogICAgICAgICAgICAgIHJldHVybiBlcnJvci5lcnJvcjsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAvLyBJZiBpdCB3YXMgbm90IGhhbmRsZWQsIGFib3J0IHRoZSB0cmFuc2l0aW9uIGNvbXBsZXRlbHkgYW5kIHJldHVybgogICAgICAgICAgICAgIC8vIHRoZSBlcnJvci4KICAgICAgICAgICAgICB0cmFuc2l0aW9uLmFib3J0KCk7CiAgICAgICAgICAgICAgcmV0dXJuIGVycm9yLmVycm9yOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfTsKCiAgICAgICAgX3Byb3RvMi5fdHJpZ2dlcldpbGxDaGFuZ2VDb250ZXh0ID0gZnVuY3Rpb24gX3RyaWdnZXJXaWxsQ2hhbmdlQ29udGV4dCgpIHsKICAgICAgICAgIHJldHVybiByb3V0ZXI7CiAgICAgICAgfTsKCiAgICAgICAgX3Byb3RvMi5fdHJpZ2dlcldpbGxMZWF2ZSA9IGZ1bmN0aW9uIF90cmlnZ2VyV2lsbExlYXZlKCkgewogICAgICAgICAgcmV0dXJuIHJvdXRlcjsKICAgICAgICB9OwoKICAgICAgICBfcHJvdG8yLnJlcGxhY2VVUkwgPSBmdW5jdGlvbiByZXBsYWNlVVJMKHVybCkgewogICAgICAgICAgaWYgKGxvY2F0aW9uLnJlcGxhY2VVUkwpIHsKICAgICAgICAgICAgdmFyIGRvUmVwbGFjZVVSTCA9IGZ1bmN0aW9uIGRvUmVwbGFjZVVSTCgpIHsKICAgICAgICAgICAgICBsb2NhdGlvbi5yZXBsYWNlVVJMKHVybCk7CiAgICAgICAgICAgICAgKDAsIF9tZXRhbC5zZXQpKHJvdXRlciwgJ2N1cnJlbnRVUkwnLCB1cmwpOwogICAgICAgICAgICB9OwoKICAgICAgICAgICAgKDAsIF9ydW5sb29wLm9uY2UpKGRvUmVwbGFjZVVSTCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aGlzLnVwZGF0ZVVSTCh1cmwpOwogICAgICAgICAgfQogICAgICAgIH07CgogICAgICAgIHJldHVybiBQcml2YXRlUm91dGVyOwogICAgICB9KF9yb3V0ZXJfanMuZGVmYXVsdCk7CgogICAgICB2YXIgcm91dGVyTWljcm9saWIgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYiA9IG5ldyBQcml2YXRlUm91dGVyKCk7CiAgICAgIHZhciBkc2xDYWxsYmFja3MgPSB0aGlzLmNvbnN0cnVjdG9yLmRzbENhbGxiYWNrcyB8fCBbS107CgogICAgICB2YXIgZHNsID0gdGhpcy5fYnVpbGREU0woKTsKCiAgICAgIGRzbC5yb3V0ZSgnYXBwbGljYXRpb24nLCB7CiAgICAgICAgcGF0aDogJy8nLAogICAgICAgIHJlc2V0TmFtZXNwYWNlOiB0cnVlLAogICAgICAgIG92ZXJyaWRlTmFtZUFzc2VydGlvbjogdHJ1ZQogICAgICB9LCBmdW5jdGlvbiAoKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkc2xDYWxsYmFja3MubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGRzbENhbGxiYWNrc1tpXS5jYWxsKHRoaXMpOwogICAgICAgIH0KICAgICAgfSk7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgaWYgKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnbmFtZXNwYWNlLkxPR19UUkFOU0lUSU9OU19JTlRFUk5BTCcpKSB7CiAgICAgICAgICByb3V0ZXJNaWNyb2xpYi5sb2cgPSBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGUKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJvdXRlck1pY3JvbGliLm1hcChkc2wuZ2VuZXJhdGUoKSk7CiAgICB9OwoKICAgIF9wcm90by5fYnVpbGREU0wgPSBmdW5jdGlvbiBfYnVpbGREU0woKSB7CiAgICAgIHZhciBlbmFibGVMb2FkaW5nU3Vic3RhdGVzID0gdGhpcy5faGFzTW9kdWxlQmFzZWRSZXNvbHZlcigpOwoKICAgICAgdmFyIHJvdXRlciA9IHRoaXM7CiAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICB2YXIgb3B0aW9ucyA9IHsKICAgICAgICBlbmFibGVMb2FkaW5nU3Vic3RhdGVzOiBlbmFibGVMb2FkaW5nU3Vic3RhdGVzLAogICAgICAgIHJlc29sdmVSb3V0ZU1hcDogZnVuY3Rpb24gcmVzb2x2ZVJvdXRlTWFwKG5hbWUpIHsKICAgICAgICAgIHJldHVybiBvd25lci5mYWN0b3J5Rm9yKCJyb3V0ZS1tYXA6IiArIG5hbWUpOwogICAgICAgIH0sCiAgICAgICAgYWRkUm91dGVGb3JFbmdpbmU6IGZ1bmN0aW9uIGFkZFJvdXRlRm9yRW5naW5lKG5hbWUsIGVuZ2luZUluZm8pIHsKICAgICAgICAgIGlmICghcm91dGVyLl9lbmdpbmVJbmZvQnlSb3V0ZVtuYW1lXSkgewogICAgICAgICAgICByb3V0ZXIuX2VuZ2luZUluZm9CeVJvdXRlW25hbWVdID0gZW5naW5lSW5mbzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH07CiAgICAgIHJldHVybiBuZXcgX2RzbC5kZWZhdWx0KG51bGwsIG9wdGlvbnMpOwogICAgfQogICAgLyoKICAgICAgUmVzZXRzIGFsbCBwZW5kaW5nIHF1ZXJ5IHBhcmFtZXRlciBjaGFuZ2VzLgogICAgICBDYWxsZWQgYWZ0ZXIgdHJhbnNpdGlvbmluZyB0byBhIG5ldyByb3V0ZQogICAgICBiYXNlZCBvbiBxdWVyeSBwYXJhbWV0ZXIgY2hhbmdlcy4KICAgICovCiAgICA7CgogICAgX3Byb3RvLl9yZXNldFF1ZXVlZFF1ZXJ5UGFyYW1ldGVyQ2hhbmdlcyA9IGZ1bmN0aW9uIF9yZXNldFF1ZXVlZFF1ZXJ5UGFyYW1ldGVyQ2hhbmdlcygpIHsKICAgICAgdGhpcy5fcXVldWVkUVBDaGFuZ2VzID0ge307CiAgICB9OwoKICAgIF9wcm90by5faGFzTW9kdWxlQmFzZWRSZXNvbHZlciA9IGZ1bmN0aW9uIF9oYXNNb2R1bGVCYXNlZFJlc29sdmVyKCkgewogICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKTsKCiAgICAgIGlmICghb3duZXIpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIHZhciByZXNvbHZlciA9ICgwLCBfbWV0YWwuZ2V0KShvd25lciwgJ2FwcGxpY2F0aW9uLl9fcmVnaXN0cnlfXy5yZXNvbHZlci5tb2R1bGVCYXNlZFJlc29sdmVyJyk7CiAgICAgIHJldHVybiBCb29sZWFuKHJlc29sdmVyKTsKICAgIH0KICAgIC8qKgogICAgICBJbml0aWFsaXplcyB0aGUgY3VycmVudCByb3V0ZXIgaW5zdGFuY2UgYW5kIHNldHMgdXAgdGhlIGNoYW5nZSBoYW5kbGluZwogICAgICBldmVudCBsaXN0ZW5lcnMgdXNlZCBieSB0aGUgaW5zdGFuY2VzIGBsb2NhdGlvbmAgaW1wbGVtZW50YXRpb24uCiAgICAgICAgIEEgcHJvcGVydHkgbmFtZWQgYGluaXRpYWxVUkxgIHdpbGwgYmUgdXNlZCB0byBkZXRlcm1pbmUgdGhlIGluaXRpYWwgVVJMLgogICAgICBJZiBubyB2YWx1ZSBpcyBmb3VuZCBgL2Agd2lsbCBiZSB1c2VkLgogICAgICAgICBAbWV0aG9kIHN0YXJ0Um91dGluZwogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uc3RhcnRSb3V0aW5nID0gZnVuY3Rpb24gc3RhcnRSb3V0aW5nKCkgewogICAgICB2YXIgaW5pdGlhbFVSTCA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnaW5pdGlhbFVSTCcpOwoKICAgICAgaWYgKHRoaXMuc2V0dXBSb3V0ZXIoKSkgewogICAgICAgIGlmIChpbml0aWFsVVJMID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGluaXRpYWxVUkwgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2xvY2F0aW9uJykuZ2V0VVJMKCk7CiAgICAgICAgfQoKICAgICAgICB2YXIgaW5pdGlhbFRyYW5zaXRpb24gPSB0aGlzLmhhbmRsZVVSTChpbml0aWFsVVJMKTsKCiAgICAgICAgaWYgKGluaXRpYWxUcmFuc2l0aW9uICYmIGluaXRpYWxUcmFuc2l0aW9uLmVycm9yKSB7CiAgICAgICAgICB0aHJvdyBpbml0aWFsVHJhbnNpdGlvbi5lcnJvcjsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnNldHVwUm91dGVyID0gZnVuY3Rpb24gc2V0dXBSb3V0ZXIoKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgdGhpcy5fc2V0dXBMb2NhdGlvbigpOwoKICAgICAgdmFyIGxvY2F0aW9uID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdsb2NhdGlvbicpOyAvLyBBbGxvdyB0aGUgTG9jYXRpb24gY2xhc3MgdG8gY2FuY2VsIHRoZSByb3V0ZXIgc2V0dXAgd2hpbGUgaXQgcmVmcmVzaGVzCiAgICAgIC8vIHRoZSBwYWdlCgogICAgICBpZiAoKDAsIF9tZXRhbC5nZXQpKGxvY2F0aW9uLCAnY2FuY2VsUm91dGVyU2V0dXAnKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgdGhpcy5faW5pdFJvdXRlckpzKCk7CgogICAgICBsb2NhdGlvbi5vblVwZGF0ZVVSTChmdW5jdGlvbiAodXJsKSB7CiAgICAgICAgX3RoaXMyLmhhbmRsZVVSTCh1cmwpOwogICAgICB9KTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9OwoKICAgIF9wcm90by5fc2V0T3V0bGV0cyA9IGZ1bmN0aW9uIF9zZXRPdXRsZXRzKCkgewogICAgICAvLyBUaGlzIGlzIHRyaWdnZXJlZCBhc3luYyBkdXJpbmcgUm91dGUjd2lsbERlc3Ryb3kuCiAgICAgIC8vIElmIHRoZSByb3V0ZXIgaXMgYWxzbyBiZWluZyBkZXN0cm95ZWQgd2UgZG8gbm90IHdhbnQgdG8KICAgICAgLy8gdG8gY3JlYXRlIGFub3RoZXIgdGhpcy5fdG9wbGV2ZWxWaWV3IChhbmQgbGVhayB0aGUgcmVuZGVyZXIpCiAgICAgIGlmICh0aGlzLmlzRGVzdHJveWluZyB8fCB0aGlzLmlzRGVzdHJveWVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgcm91dGVJbmZvcyA9IHRoaXMuX3JvdXRlck1pY3JvbGliLmN1cnJlbnRSb3V0ZUluZm9zOwogICAgICB2YXIgcm91dGU7CiAgICAgIHZhciBkZWZhdWx0UGFyZW50U3RhdGU7CiAgICAgIHZhciBsaXZlUm91dGVzID0gbnVsbDsKCiAgICAgIGlmICghcm91dGVJbmZvcykgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3V0ZUluZm9zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgcm91dGUgPSByb3V0ZUluZm9zW2ldLnJvdXRlOwoKICAgICAgICB2YXIgY29ubmVjdGlvbnMgPSBfcm91dGUuUk9VVEVfQ09OTkVDVElPTlMuZ2V0KHJvdXRlKTsKCiAgICAgICAgdmFyIG93blN0YXRlID0gdm9pZCAwOwoKICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGNvbm5lY3Rpb25zLmxlbmd0aDsgaisrKSB7CiAgICAgICAgICB2YXIgYXBwZW5kZWQgPSBhcHBlbmRMaXZlUm91dGUobGl2ZVJvdXRlcywgZGVmYXVsdFBhcmVudFN0YXRlLCBjb25uZWN0aW9uc1tqXSk7CiAgICAgICAgICBsaXZlUm91dGVzID0gYXBwZW5kZWQubGl2ZVJvdXRlczsKCiAgICAgICAgICBpZiAoYXBwZW5kZWQub3duU3RhdGUucmVuZGVyLm5hbWUgPT09IHJvdXRlLnJvdXRlTmFtZSB8fCBhcHBlbmRlZC5vd25TdGF0ZS5yZW5kZXIub3V0bGV0ID09PSAnbWFpbicpIHsKICAgICAgICAgICAgb3duU3RhdGUgPSBhcHBlbmRlZC5vd25TdGF0ZTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmIChjb25uZWN0aW9ucy5sZW5ndGggPT09IDApIHsKICAgICAgICAgIG93blN0YXRlID0gcmVwcmVzZW50RW1wdHlSb3V0ZShsaXZlUm91dGVzLCBkZWZhdWx0UGFyZW50U3RhdGUsIHJvdXRlKTsKICAgICAgICB9CgogICAgICAgIGRlZmF1bHRQYXJlbnRTdGF0ZSA9IG93blN0YXRlOwogICAgICB9IC8vIHdoZW4gYSB0cmFuc2l0aW9uVG8gaGFwcGVucyBhZnRlciB0aGUgdmFsaWRhdGlvbiBwaGFzZQogICAgICAvLyBkdXJpbmcgdGhlIGluaXRpYWwgdHJhbnNpdGlvbiBfc2V0T3V0bGV0cyBpcyBjYWxsZWQKICAgICAgLy8gd2hlbiBubyByb3V0ZXMgYXJlIGFjdGl2ZS4gSG93ZXZlciwgaXQgd2lsbCBnZXQgY2FsbGVkCiAgICAgIC8vIGFnYWluIHdpdGggdGhlIGNvcnJlY3QgdmFsdWVzIGR1cmluZyB0aGUgbmV4dCB0dXJuIG9mCiAgICAgIC8vIHRoZSBydW5sb29wCgoKICAgICAgaWYgKCFsaXZlUm91dGVzKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAoIXRoaXMuX3RvcGxldmVsVmlldykgewogICAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwogICAgICAgIHZhciBPdXRsZXRWaWV3ID0gb3duZXIuZmFjdG9yeUZvcigndmlldzotb3V0bGV0Jyk7CiAgICAgICAgdGhpcy5fdG9wbGV2ZWxWaWV3ID0gT3V0bGV0Vmlldy5jcmVhdGUoKTsKCiAgICAgICAgdGhpcy5fdG9wbGV2ZWxWaWV3LnNldE91dGxldFN0YXRlKGxpdmVSb3V0ZXMpOwoKICAgICAgICB2YXIgaW5zdGFuY2UgPSBvd25lci5sb29rdXAoJy1hcHBsaWNhdGlvbi1pbnN0YW5jZTptYWluJyk7CiAgICAgICAgaW5zdGFuY2UuZGlkQ3JlYXRlUm9vdFZpZXcodGhpcy5fdG9wbGV2ZWxWaWV3KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLl90b3BsZXZlbFZpZXcuc2V0T3V0bGV0U3RhdGUobGl2ZVJvdXRlcyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmhhbmRsZVVSTCA9IGZ1bmN0aW9uIGhhbmRsZVVSTCh1cmwpIHsKICAgICAgLy8gVW50aWwgd2UgaGF2ZSBhbiBlbWJlci1pZGlvbWF0aWMgd2F5IG9mIGFjY2Vzc2luZyAjaGFzaGVzLCB3ZSBuZWVkIHRvCiAgICAgIC8vIHJlbW92ZSBpdCBiZWNhdXNlIHJvdXRlci5qcyBkb2Vzbid0IGtub3cgaG93IHRvIGhhbmRsZSBpdC4KICAgICAgdmFyIF91cmwgPSB1cmwuc3BsaXQoLyMoLispPy8pWzBdOwogICAgICByZXR1cm4gdGhpcy5fZG9VUkxUcmFuc2l0aW9uKCdoYW5kbGVVUkwnLCBfdXJsKTsKICAgIH07CgogICAgX3Byb3RvLl9kb1VSTFRyYW5zaXRpb24gPSBmdW5jdGlvbiBfZG9VUkxUcmFuc2l0aW9uKHJvdXRlckpzTWV0aG9kLCB1cmwpIHsKICAgICAgdmFyIHRyYW5zaXRpb24gPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYltyb3V0ZXJKc01ldGhvZF0odXJsIHx8ICcvJyk7CgogICAgICBkaWRCZWdpblRyYW5zaXRpb24odHJhbnNpdGlvbiwgdGhpcyk7CiAgICAgIHJldHVybiB0cmFuc2l0aW9uOwogICAgfQogICAgLyoqCiAgICAgIFRyYW5zaXRpb24gdGhlIGFwcGxpY2F0aW9uIGludG8gYW5vdGhlciByb3V0ZS4gVGhlIHJvdXRlIG1heQogICAgICBiZSBlaXRoZXIgYSBzaW5nbGUgcm91dGUgb3Igcm91dGUgcGF0aDoKICAgICAgICAgU2VlIFt0cmFuc2l0aW9uVG9dKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvUm91dGUvbWV0aG9kcy90cmFuc2l0aW9uVG8/YW5jaG9yPXRyYW5zaXRpb25UbykgZm9yIG1vcmUgaW5mby4KICAgICAgICAgQG1ldGhvZCB0cmFuc2l0aW9uVG8KICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIHJvdXRlIG9yIGEgVVJMCiAgICAgIEBwYXJhbSB7Li4uT2JqZWN0fSBtb2RlbHMgdGhlIG1vZGVsKHMpIG9yIGlkZW50aWZpZXIocykgdG8gYmUgdXNlZCB3aGlsZQogICAgICAgIHRyYW5zaXRpb25pbmcgdG8gdGhlIHJvdXRlLgogICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIG9wdGlvbmFsIGhhc2ggd2l0aCBhIHF1ZXJ5UGFyYW1zIHByb3BlcnR5CiAgICAgICAgY29udGFpbmluZyBhIG1hcHBpbmcgb2YgcXVlcnkgcGFyYW1ldGVycwogICAgICBAcmV0dXJuIHtUcmFuc2l0aW9ufSB0aGUgdHJhbnNpdGlvbiBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoaXMKICAgICAgICBhdHRlbXB0ZWQgdHJhbnNpdGlvbgogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by50cmFuc2l0aW9uVG8gPSBmdW5jdGlvbiB0cmFuc2l0aW9uVG8oKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgIGlmICgoMCwgX3V0aWxzLnJlc2VtYmxlc1VSTCkoYXJnc1swXSkpIHsKICAgICAgICAoZmFsc2UgJiYgISghdGhpcy5pc0Rlc3Ryb3lpbmcgJiYgIXRoaXMuaXNEZXN0cm95ZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQSB0cmFuc2l0aW9uIHdhcyBhdHRlbXB0ZWQgZnJvbSAnIiArIHRoaXMuY3VycmVudFJvdXRlTmFtZSArICInIHRvICciICsgYXJnc1swXSArICInIGJ1dCB0aGUgYXBwbGljYXRpb24gaW5zdGFuY2UgaGFzIGFscmVhZHkgYmVlbiBkZXN0cm95ZWQuIiwgIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgICAgcmV0dXJuIHRoaXMuX2RvVVJMVHJhbnNpdGlvbigndHJhbnNpdGlvblRvJywgYXJnc1swXSk7CiAgICAgIH0KCiAgICAgIHZhciBfZXh0cmFjdFJvdXRlQXJncyA9ICgwLCBfdXRpbHMuZXh0cmFjdFJvdXRlQXJncykoYXJncyksCiAgICAgICAgICByb3V0ZU5hbWUgPSBfZXh0cmFjdFJvdXRlQXJncy5yb3V0ZU5hbWUsCiAgICAgICAgICBtb2RlbHMgPSBfZXh0cmFjdFJvdXRlQXJncy5tb2RlbHMsCiAgICAgICAgICBxdWVyeVBhcmFtcyA9IF9leHRyYWN0Um91dGVBcmdzLnF1ZXJ5UGFyYW1zOwoKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkEgdHJhbnNpdGlvbiB3YXMgYXR0ZW1wdGVkIGZyb20gJyIgKyB0aGlzLmN1cnJlbnRSb3V0ZU5hbWUgKyAiJyB0byAnIiArIHJvdXRlTmFtZSArICInIGJ1dCB0aGUgYXBwbGljYXRpb24gaW5zdGFuY2UgaGFzIGFscmVhZHkgYmVlbiBkZXN0cm95ZWQuIiwgIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgIHJldHVybiB0aGlzLl9kb1RyYW5zaXRpb24ocm91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zKTsKICAgIH07CgogICAgX3Byb3RvLmludGVybWVkaWF0ZVRyYW5zaXRpb25UbyA9IGZ1bmN0aW9uIGludGVybWVkaWF0ZVRyYW5zaXRpb25UbyhuYW1lKSB7CiAgICAgIHZhciBfdGhpcyRfcm91dGVyTWljcm9saWI7CgogICAgICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjIgPiAxID8gX2xlbjIgLSAxIDogMCksIF9rZXkyID0gMTsgX2tleTIgPCBfbGVuMjsgX2tleTIrKykgewogICAgICAgIGFyZ3NbX2tleTIgLSAxXSA9IGFyZ3VtZW50c1tfa2V5Ml07CiAgICAgIH0KCiAgICAgIChfdGhpcyRfcm91dGVyTWljcm9saWIgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYikuaW50ZXJtZWRpYXRlVHJhbnNpdGlvblRvLmFwcGx5KF90aGlzJF9yb3V0ZXJNaWNyb2xpYiwgW25hbWVdLmNvbmNhdChhcmdzKSk7CgogICAgICB1cGRhdGVQYXRocyh0aGlzKTsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICB2YXIgaW5mb3MgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYi5jdXJyZW50Um91dGVJbmZvczsKCiAgICAgICAgaWYgKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnbmFtZXNwYWNlJykuTE9HX1RSQU5TSVRJT05TKSB7CiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZQogICAgICAgICAgY29uc29sZS5sb2coIkludGVybWVkaWF0ZS10cmFuc2l0aW9uZWQgaW50byAnIiArIEVtYmVyUm91dGVyLl9yb3V0ZVBhdGgoaW5mb3MpICsgIiciKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnJlcGxhY2VXaXRoID0gZnVuY3Rpb24gcmVwbGFjZVdpdGgoKSB7CiAgICAgIHJldHVybiB0aGlzLnRyYW5zaXRpb25Uby5hcHBseSh0aGlzLCBhcmd1bWVudHMpLm1ldGhvZCgncmVwbGFjZScpOwogICAgfTsKCiAgICBfcHJvdG8uZ2VuZXJhdGUgPSBmdW5jdGlvbiBnZW5lcmF0ZShuYW1lKSB7CiAgICAgIHZhciBfdGhpcyRfcm91dGVyTWljcm9saWIyOwoKICAgICAgZm9yICh2YXIgX2xlbjMgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4zID4gMSA/IF9sZW4zIC0gMSA6IDApLCBfa2V5MyA9IDE7IF9rZXkzIDwgX2xlbjM7IF9rZXkzKyspIHsKICAgICAgICBhcmdzW19rZXkzIC0gMV0gPSBhcmd1bWVudHNbX2tleTNdOwogICAgICB9CgogICAgICB2YXIgdXJsID0gKF90aGlzJF9yb3V0ZXJNaWNyb2xpYjIgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYikuZ2VuZXJhdGUuYXBwbHkoX3RoaXMkX3JvdXRlck1pY3JvbGliMiwgW25hbWVdLmNvbmNhdChhcmdzKSk7CgogICAgICByZXR1cm4gdGhpcy5sb2NhdGlvbi5mb3JtYXRVUkwodXJsKTsKICAgIH0KICAgIC8qKgogICAgICBEZXRlcm1pbmVzIGlmIHRoZSBzdXBwbGllZCByb3V0ZSBpcyBjdXJyZW50bHkgYWN0aXZlLgogICAgICAgICBAbWV0aG9kIGlzQWN0aXZlCiAgICAgIEBwYXJhbSByb3V0ZU5hbWUKICAgICAgQHJldHVybiB7Qm9vbGVhbn0KICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmlzQWN0aXZlID0gZnVuY3Rpb24gaXNBY3RpdmUocm91dGVOYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLl9yb3V0ZXJNaWNyb2xpYi5pc0FjdGl2ZShyb3V0ZU5hbWUpOwogICAgfQogICAgLyoqCiAgICAgIEFuIGFsdGVybmF0aXZlIGZvcm0gb2YgYGlzQWN0aXZlYCB0aGF0IGRvZXNuJ3QgcmVxdWlyZQogICAgICBtYW51YWwgY29uY2F0ZW5hdGlvbiBvZiB0aGUgYXJndW1lbnRzIGludG8gYSBzaW5nbGUKICAgICAgYXJyYXkuCiAgICAgICAgIEBtZXRob2QgaXNBY3RpdmVJbnRlbnQKICAgICAgQHBhcmFtIHJvdXRlTmFtZQogICAgICBAcGFyYW0gbW9kZWxzCiAgICAgIEBwYXJhbSBxdWVyeVBhcmFtcwogICAgICBAcmV0dXJuIHtCb29sZWFufQogICAgICBAcHJpdmF0ZQogICAgICBAc2luY2UgMS43LjAKICAgICovCiAgICA7CgogICAgX3Byb3RvLmlzQWN0aXZlSW50ZW50ID0gZnVuY3Rpb24gaXNBY3RpdmVJbnRlbnQocm91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zKSB7CiAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5pc0FjdGl2ZUludGVudChyb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMpOwogICAgfTsKCiAgICBfcHJvdG8uc2VuZCA9IGZ1bmN0aW9uIHNlbmQobmFtZSkgewogICAgICB2YXIgX3RoaXMkX3JvdXRlck1pY3JvbGliMzsKCiAgICAgIGZvciAodmFyIF9sZW40ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuNCA+IDEgPyBfbGVuNCAtIDEgOiAwKSwgX2tleTQgPSAxOyBfa2V5NCA8IF9sZW40OyBfa2V5NCsrKSB7CiAgICAgICAgYXJnc1tfa2V5NCAtIDFdID0gYXJndW1lbnRzW19rZXk0XTsKICAgICAgfQoKICAgICAgLypuYW1lLCBjb250ZXh0Ki8KICAgICAgKF90aGlzJF9yb3V0ZXJNaWNyb2xpYjMgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYikudHJpZ2dlci5hcHBseShfdGhpcyRfcm91dGVyTWljcm9saWIzLCBbbmFtZV0uY29uY2F0KGFyZ3MpKTsKICAgIH0KICAgIC8qKgogICAgICBEb2VzIHRoaXMgcm91dGVyIGluc3RhbmNlIGhhdmUgdGhlIGdpdmVuIHJvdXRlLgogICAgICAgICBAbWV0aG9kIGhhc1JvdXRlCiAgICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5oYXNSb3V0ZSA9IGZ1bmN0aW9uIGhhc1JvdXRlKHJvdXRlKSB7CiAgICAgIHJldHVybiB0aGlzLl9yb3V0ZXJNaWNyb2xpYi5oYXNSb3V0ZShyb3V0ZSk7CiAgICB9CiAgICAvKioKICAgICAgUmVzZXRzIHRoZSBzdGF0ZSBvZiB0aGUgcm91dGVyIGJ5IGNsZWFyaW5nIHRoZSBjdXJyZW50IHJvdXRlCiAgICAgIGhhbmRsZXJzIGFuZCBkZWFjdGl2YXRpbmcgdGhlbS4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCByZXNldAogICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoKSB7CiAgICAgIGlmICh0aGlzLl9yb3V0ZXJNaWNyb2xpYikgewogICAgICAgIHRoaXMuX3JvdXRlck1pY3JvbGliLnJlc2V0KCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLndpbGxEZXN0cm95ID0gZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIGlmICh0aGlzLl90b3BsZXZlbFZpZXcpIHsKICAgICAgICB0aGlzLl90b3BsZXZlbFZpZXcuZGVzdHJveSgpOwoKICAgICAgICB0aGlzLl90b3BsZXZlbFZpZXcgPSBudWxsOwogICAgICB9CgogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgdGhpcy5yZXNldCgpOwogICAgICB2YXIgaW5zdGFuY2VzID0gdGhpcy5fZW5naW5lSW5zdGFuY2VzOwoKICAgICAgZm9yICh2YXIgbmFtZSBpbiBpbnN0YW5jZXMpIHsKICAgICAgICBmb3IgKHZhciBpZCBpbiBpbnN0YW5jZXNbbmFtZV0pIHsKICAgICAgICAgICgwLCBfcnVubG9vcC5ydW4pKGluc3RhbmNlc1tuYW1lXVtpZF0sICdkZXN0cm95Jyk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKgogICAgICBDYWxsZWQgd2hlbiBhbiBhY3RpdmUgcm91dGUncyBxdWVyeSBwYXJhbWV0ZXIgaGFzIGNoYW5nZWQuCiAgICAgIFRoZXNlIGNoYW5nZXMgYXJlIGJhdGNoZWQgaW50byBhIHJ1bmxvb3AgcnVuIGFuZCB0cmlnZ2VyCiAgICAgIGEgc2luZ2xlIHRyYW5zaXRpb24uCiAgICAqLwogICAgOwoKICAgIF9wcm90by5fYWN0aXZlUVBDaGFuZ2VkID0gZnVuY3Rpb24gX2FjdGl2ZVFQQ2hhbmdlZChxdWVyeVBhcmFtZXRlck5hbWUsIG5ld1ZhbHVlKSB7CiAgICAgIHRoaXMuX3F1ZXVlZFFQQ2hhbmdlc1txdWVyeVBhcmFtZXRlck5hbWVdID0gbmV3VmFsdWU7CiAgICAgICgwLCBfcnVubG9vcC5vbmNlKSh0aGlzLCB0aGlzLl9maXJlUXVlcnlQYXJhbVRyYW5zaXRpb24pOwogICAgfTsKCiAgICBfcHJvdG8uX3VwZGF0aW5nUVBDaGFuZ2VkID0gZnVuY3Rpb24gX3VwZGF0aW5nUVBDaGFuZ2VkKHF1ZXJ5UGFyYW1ldGVyTmFtZSkgewogICAgICB0aGlzLl9xcFVwZGF0ZXMuYWRkKHF1ZXJ5UGFyYW1ldGVyTmFtZSk7CiAgICB9CiAgICAvKgogICAgICBUcmlnZ2VycyBhIHRyYW5zaXRpb24gdG8gYSByb3V0ZSBiYXNlZCBvbiBxdWVyeSBwYXJhbWV0ZXIgY2hhbmdlcy4KICAgICAgVGhpcyBpcyBjYWxsZWQgb25jZSBwZXIgcnVubG9vcCwgdG8gYmF0Y2ggY2hhbmdlcy4KICAgICAgICAgZS5nLgogICAgICAgICBpZiB0aGVzZSBtZXRob2RzIGFyZSBjYWxsZWQgaW4gc3VjY2Vzc2lvbjoKICAgICAgdGhpcy5fYWN0aXZlUVBDaGFuZ2VkKCdmb28nLCAnMTAnKTsKICAgICAgICAvLyByZXN1bHRzIGluIF9xdWV1ZWRRUENoYW5nZXMgPSB7IGZvbzogJzEwJyB9CiAgICAgIHRoaXMuX2FjdGl2ZVFQQ2hhbmdlZCgnYmFyJywgZmFsc2UpOwogICAgICAgIC8vIHJlc3VsdHMgaW4gX3F1ZXVlZFFQQ2hhbmdlcyA9IHsgZm9vOiAnMTAnLCBiYXI6IGZhbHNlIH0KICAgICAgICAgX3F1ZXVlZFFQQ2hhbmdlcyB3aWxsIHJlcHJlc2VudCBib3RoIG9mIHRoZXNlIGNoYW5nZXMKICAgICAgYW5kIHRoZSB0cmFuc2l0aW9uIHVzaW5nIGB0cmFuc2l0aW9uVG9gIHdpbGwgYmUgdHJpZ2dlcmVkCiAgICAgIG9uY2UuCiAgICAqLwogICAgOwoKICAgIF9wcm90by5fZmlyZVF1ZXJ5UGFyYW1UcmFuc2l0aW9uID0gZnVuY3Rpb24gX2ZpcmVRdWVyeVBhcmFtVHJhbnNpdGlvbigpIHsKICAgICAgdGhpcy50cmFuc2l0aW9uVG8oewogICAgICAgIHF1ZXJ5UGFyYW1zOiB0aGlzLl9xdWV1ZWRRUENoYW5nZXMKICAgICAgfSk7CgogICAgICB0aGlzLl9yZXNldFF1ZXVlZFF1ZXJ5UGFyYW1ldGVyQ2hhbmdlcygpOwogICAgfTsKCiAgICBfcHJvdG8uX3NldHVwTG9jYXRpb24gPSBmdW5jdGlvbiBfc2V0dXBMb2NhdGlvbigpIHsKICAgICAgdmFyIGxvY2F0aW9uID0gdGhpcy5sb2NhdGlvbjsKICAgICAgdmFyIHJvb3RVUkwgPSB0aGlzLnJvb3RVUkw7CiAgICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHRoaXMpOwoKICAgICAgaWYgKCdzdHJpbmcnID09PSB0eXBlb2YgbG9jYXRpb24gJiYgb3duZXIpIHsKICAgICAgICB2YXIgcmVzb2x2ZWRMb2NhdGlvbiA9IG93bmVyLmxvb2t1cCgibG9jYXRpb246IiArIGxvY2F0aW9uKTsKCiAgICAgICAgaWYgKHJlc29sdmVkTG9jYXRpb24gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgbG9jYXRpb24gPSAoMCwgX21ldGFsLnNldCkodGhpcywgJ2xvY2F0aW9uJywgcmVzb2x2ZWRMb2NhdGlvbik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vIEFsbG93IGZvciBkZXByZWNhdGVkIHJlZ2lzdHJhdGlvbiBvZiBjdXN0b20gbG9jYXRpb24gQVBJJ3MKICAgICAgICAgIHZhciBvcHRpb25zID0gewogICAgICAgICAgICBpbXBsZW1lbnRhdGlvbjogbG9jYXRpb24KICAgICAgICAgIH07CiAgICAgICAgICBsb2NhdGlvbiA9ICgwLCBfbWV0YWwuc2V0KSh0aGlzLCAnbG9jYXRpb24nLCBfYXBpLmRlZmF1bHQuY3JlYXRlKG9wdGlvbnMpKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChsb2NhdGlvbiAhPT0gbnVsbCAmJiB0eXBlb2YgbG9jYXRpb24gPT09ICdvYmplY3QnKSB7CiAgICAgICAgaWYgKHJvb3RVUkwpIHsKICAgICAgICAgICgwLCBfbWV0YWwuc2V0KShsb2NhdGlvbiwgJ3Jvb3RVUkwnLCByb290VVJMKTsKICAgICAgICB9IC8vIEFsbG93IHRoZSBsb2NhdGlvbiB0byBkbyBhbnkgZmVhdHVyZSBkZXRlY3Rpb24sIHN1Y2ggYXMgQXV0b0xvY2F0aW9uCiAgICAgICAgLy8gZGV0ZWN0aW5nIGhpc3Rvcnkgc3VwcG9ydC4gVGhpcyBnaXZlcyBpdCBhIGNoYW5jZSB0byBzZXQgaXRzCiAgICAgICAgLy8gYGNhbmNlbFJvdXRlclNldHVwYCBwcm9wZXJ0eSB3aGljaCBhYm9ydHMgcm91dGluZy4KCgogICAgICAgIGlmICh0eXBlb2YgbG9jYXRpb24uZGV0ZWN0ID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICBsb2NhdGlvbi5kZXRlY3QoKTsKICAgICAgICB9IC8vIGVuc3VyZSB0aGF0IGluaXRTdGF0ZSBpcyBjYWxsZWQgQUZURVIgdGhlIHJvb3RVUkwgaXMgc2V0IG9uCiAgICAgICAgLy8gdGhlIGxvY2F0aW9uIGluc3RhbmNlCgoKICAgICAgICBpZiAodHlwZW9mIGxvY2F0aW9uLmluaXRTdGF0ZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgICAgbG9jYXRpb24uaW5pdFN0YXRlKCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgU2VyaWFsaXplcyB0aGUgZ2l2ZW4gcXVlcnkgcGFyYW1zIGFjY29yZGluZyB0byB0aGVpciBRUCBtZXRhIGluZm9ybWF0aW9uLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9zZXJpYWxpemVRdWVyeVBhcmFtcwogICAgICBAcGFyYW0ge0FycnJheTxSb3V0ZUluZm8+fSByb3V0ZUluZm9zCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeVBhcmFtcwogICAgICBAcmV0dXJuIHtWb2lkfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3NlcmlhbGl6ZVF1ZXJ5UGFyYW1zID0gZnVuY3Rpb24gX3NlcmlhbGl6ZVF1ZXJ5UGFyYW1zKHJvdXRlSW5mb3MsIHF1ZXJ5UGFyYW1zKSB7CiAgICAgIHZhciBfdGhpczMgPSB0aGlzOwoKICAgICAgZm9yRWFjaFF1ZXJ5UGFyYW0odGhpcywgcm91dGVJbmZvcywgcXVlcnlQYXJhbXMsIGZ1bmN0aW9uIChrZXksIHZhbHVlLCBxcCkgewogICAgICAgIGlmIChxcCkgewogICAgICAgICAgZGVsZXRlIHF1ZXJ5UGFyYW1zW2tleV07CiAgICAgICAgICBxdWVyeVBhcmFtc1txcC51cmxLZXldID0gcXAucm91dGUuc2VyaWFsaXplUXVlcnlQYXJhbSh2YWx1ZSwgcXAudXJsS2V5LCBxcC50eXBlKTsKICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJldHVybjsgLy8gV2UgZG9uJ3Qgc2VyaWFsaXplIHVuZGVmaW5lZCB2YWx1ZXMKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcXVlcnlQYXJhbXNba2V5XSA9IF90aGlzMy5fc2VyaWFsaXplUXVlcnlQYXJhbSh2YWx1ZSwgKDAsIF9ydW50aW1lLnR5cGVPZikodmFsdWUpKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogICAgLyoqCiAgICAgIFNlcmlhbGl6ZXMgdGhlIHZhbHVlIG9mIGEgcXVlcnkgcGFyYW1ldGVyIGJhc2VkIG9uIGEgdHlwZQogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9zZXJpYWxpemVRdWVyeVBhcmFtCiAgICAgIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZQogICAgICBAcGFyYW0ge1N0cmluZ30gdHlwZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3NlcmlhbGl6ZVF1ZXJ5UGFyYW0gPSBmdW5jdGlvbiBfc2VyaWFsaXplUXVlcnlQYXJhbSh2YWx1ZSwgdHlwZSkgewogICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnYXJyYXknKSB7CiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlKTsKICAgICAgfQoKICAgICAgcmV0dXJuICIiICsgdmFsdWU7CiAgICB9CiAgICAvKioKICAgICAgRGVzZXJpYWxpemVzIHRoZSBnaXZlbiBxdWVyeSBwYXJhbXMgYWNjb3JkaW5nIHRvIHRoZWlyIFFQIG1ldGEgaW5mb3JtYXRpb24uCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX2Rlc2VyaWFsaXplUXVlcnlQYXJhbXMKICAgICAgQHBhcmFtIHtBcnJheTxSb3V0ZUluZm8+fSByb3V0ZUluZm9zCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeVBhcmFtcwogICAgICBAcmV0dXJuIHtWb2lkfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX2Rlc2VyaWFsaXplUXVlcnlQYXJhbXMgPSBmdW5jdGlvbiBfZGVzZXJpYWxpemVRdWVyeVBhcmFtcyhyb3V0ZUluZm9zLCBxdWVyeVBhcmFtcykgewogICAgICBmb3JFYWNoUXVlcnlQYXJhbSh0aGlzLCByb3V0ZUluZm9zLCBxdWVyeVBhcmFtcywgZnVuY3Rpb24gKGtleSwgdmFsdWUsIHFwKSB7CiAgICAgICAgLy8gSWYgd2UgZG9uJ3QgaGF2ZSBRUCBtZXRhIGluZm8gZm9yIGEgZ2l2ZW4ga2V5LCB0aGVuIHdlIGRvIG5vdGhpbmcKICAgICAgICAvLyBiZWNhdXNlIGFsbCB2YWx1ZXMgd2lsbCBiZSB0cmVhdGVkIGFzIHN0cmluZ3MKICAgICAgICBpZiAocXApIHsKICAgICAgICAgIGRlbGV0ZSBxdWVyeVBhcmFtc1trZXldOwogICAgICAgICAgcXVlcnlQYXJhbXNbcXAucHJvcF0gPSBxcC5yb3V0ZS5kZXNlcmlhbGl6ZVF1ZXJ5UGFyYW0odmFsdWUsIHFwLnVybEtleSwgcXAudHlwZSk7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICBEZXNlcmlhbGl6ZXMgdGhlIHZhbHVlIG9mIGEgcXVlcnkgcGFyYW1ldGVyIGJhc2VkIG9uIGEgZGVmYXVsdCB0eXBlCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX2Rlc2VyaWFsaXplUXVlcnlQYXJhbQogICAgICBAcGFyYW0ge09iamVjdH0gdmFsdWUKICAgICAgQHBhcmFtIHtTdHJpbmd9IGRlZmF1bHRUeXBlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5fZGVzZXJpYWxpemVRdWVyeVBhcmFtID0gZnVuY3Rpb24gX2Rlc2VyaWFsaXplUXVlcnlQYXJhbSh2YWx1ZSwgZGVmYXVsdFR5cGUpIHsKICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0gZWxzZSBpZiAoZGVmYXVsdFR5cGUgPT09ICdib29sZWFuJykgewogICAgICAgIHJldHVybiB2YWx1ZSA9PT0gJ3RydWUnOwogICAgICB9IGVsc2UgaWYgKGRlZmF1bHRUeXBlID09PSAnbnVtYmVyJykgewogICAgICAgIHJldHVybiBOdW1iZXIodmFsdWUpLnZhbHVlT2YoKTsKICAgICAgfSBlbHNlIGlmIChkZWZhdWx0VHlwZSA9PT0gJ2FycmF5JykgewogICAgICAgIHJldHVybiAoMCwgX3J1bnRpbWUuQSkoSlNPTi5wYXJzZSh2YWx1ZSkpOwogICAgICB9CgogICAgICByZXR1cm4gdmFsdWU7CiAgICB9CiAgICAvKioKICAgICAgUmVtb3ZlcyAocHJ1bmVzKSBhbnkgcXVlcnkgcGFyYW1zIHdpdGggZGVmYXVsdCB2YWx1ZXMgZnJvbSB0aGUgZ2l2ZW4gUVAKICAgICAgb2JqZWN0LiBEZWZhdWx0IHZhbHVlcyBhcmUgZGV0ZXJtaW5lZCBmcm9tIHRoZSBRUCBtZXRhIGluZm9ybWF0aW9uIHBlciBrZXkuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX3BydW5lRGVmYXVsdFF1ZXJ5UGFyYW1WYWx1ZXMKICAgICAgQHBhcmFtIHtBcnJheTxSb3V0ZUluZm8+fSByb3V0ZUluZm9zCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeVBhcmFtcwogICAgICBAcmV0dXJuIHtWb2lkfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3BydW5lRGVmYXVsdFF1ZXJ5UGFyYW1WYWx1ZXMgPSBmdW5jdGlvbiBfcHJ1bmVEZWZhdWx0UXVlcnlQYXJhbVZhbHVlcyhyb3V0ZUluZm9zLCBxdWVyeVBhcmFtcykgewogICAgICB2YXIgcXBzID0gdGhpcy5fcXVlcnlQYXJhbXNGb3Iocm91dGVJbmZvcyk7CgogICAgICBmb3IgKHZhciBrZXkgaW4gcXVlcnlQYXJhbXMpIHsKICAgICAgICB2YXIgcXAgPSBxcHMubWFwW2tleV07CgogICAgICAgIGlmIChxcCAmJiBxcC5zZXJpYWxpemVkRGVmYXVsdFZhbHVlID09PSBxdWVyeVBhcmFtc1trZXldKSB7CiAgICAgICAgICBkZWxldGUgcXVlcnlQYXJhbXNba2V5XTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9kb1RyYW5zaXRpb24gPSBmdW5jdGlvbiBfZG9UcmFuc2l0aW9uKF90YXJnZXRSb3V0ZU5hbWUsIG1vZGVscywgX3F1ZXJ5UGFyYW1zLCBfa2VlcERlZmF1bHRRdWVyeVBhcmFtVmFsdWVzKSB7CiAgICAgIHZhciBfdGhpcyRfcm91dGVyTWljcm9saWI0OwoKICAgICAgdmFyIHRhcmdldFJvdXRlTmFtZSA9IF90YXJnZXRSb3V0ZU5hbWUgfHwgKDAsIF91dGlscy5nZXRBY3RpdmVUYXJnZXROYW1lKSh0aGlzLl9yb3V0ZXJNaWNyb2xpYik7CgogICAgICAoZmFsc2UgJiYgIShCb29sZWFuKHRhcmdldFJvdXRlTmFtZSkgJiYgdGhpcy5fcm91dGVyTWljcm9saWIuaGFzUm91dGUodGFyZ2V0Um91dGVOYW1lKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgcm91dGUgIiArIHRhcmdldFJvdXRlTmFtZSArICIgd2FzIG5vdCBmb3VuZCIsIEJvb2xlYW4odGFyZ2V0Um91dGVOYW1lKSAmJiB0aGlzLl9yb3V0ZXJNaWNyb2xpYi5oYXNSb3V0ZSh0YXJnZXRSb3V0ZU5hbWUpKSk7CiAgICAgIHZhciBxdWVyeVBhcmFtcyA9IHt9OwoKICAgICAgdGhpcy5fcHJvY2Vzc0FjdGl2ZVRyYW5zaXRpb25RdWVyeVBhcmFtcyh0YXJnZXRSb3V0ZU5hbWUsIG1vZGVscywgcXVlcnlQYXJhbXMsIF9xdWVyeVBhcmFtcyk7CgogICAgICAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHF1ZXJ5UGFyYW1zLCBfcXVlcnlQYXJhbXMpOwoKICAgICAgdGhpcy5fcHJlcGFyZVF1ZXJ5UGFyYW1zKHRhcmdldFJvdXRlTmFtZSwgbW9kZWxzLCBxdWVyeVBhcmFtcywgQm9vbGVhbihfa2VlcERlZmF1bHRRdWVyeVBhcmFtVmFsdWVzKSk7CgogICAgICB2YXIgdHJhbnNpdGlvbiA9IChfdGhpcyRfcm91dGVyTWljcm9saWI0ID0gdGhpcy5fcm91dGVyTWljcm9saWIpLnRyYW5zaXRpb25Uby5hcHBseShfdGhpcyRfcm91dGVyTWljcm9saWI0LCBbdGFyZ2V0Um91dGVOYW1lXS5jb25jYXQobW9kZWxzLCBbewogICAgICAgIHF1ZXJ5UGFyYW1zOiBxdWVyeVBhcmFtcwogICAgICB9XSkpOwoKICAgICAgZGlkQmVnaW5UcmFuc2l0aW9uKHRyYW5zaXRpb24sIHRoaXMpOwogICAgICByZXR1cm4gdHJhbnNpdGlvbjsKICAgIH07CgogICAgX3Byb3RvLl9wcm9jZXNzQWN0aXZlVHJhbnNpdGlvblF1ZXJ5UGFyYW1zID0gZnVuY3Rpb24gX3Byb2Nlc3NBY3RpdmVUcmFuc2l0aW9uUXVlcnlQYXJhbXModGFyZ2V0Um91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zLCBfcXVlcnlQYXJhbXMpIHsKICAgICAgLy8gbWVyZ2UgaW4gYW55IHF1ZXJ5UGFyYW1zIGZyb20gdGhlIGFjdGl2ZSB0cmFuc2l0aW9uIHdoaWNoIGNvdWxkIGluY2x1ZGUKICAgICAgLy8gcXVlcnlQYXJhbXMgZnJvbSB0aGUgdXJsIG9uIGluaXRpYWwgbG9hZC4KICAgICAgaWYgKCF0aGlzLl9yb3V0ZXJNaWNyb2xpYi5hY3RpdmVUcmFuc2l0aW9uKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgdW5jaGFuZ2VkUVBzID0ge307CiAgICAgIHZhciBxcFVwZGF0ZXMgPSB0aGlzLl9xcFVwZGF0ZXM7CiAgICAgIHZhciBwYXJhbXMgPSB0aGlzLl9yb3V0ZXJNaWNyb2xpYi5hY3RpdmVUcmFuc2l0aW9uW19yb3V0ZXJfanMuUVVFUllfUEFSQU1TX1NZTUJPTF07CgogICAgICBmb3IgKHZhciBrZXkgaW4gcGFyYW1zKSB7CiAgICAgICAgaWYgKCFxcFVwZGF0ZXMuaGFzKGtleSkpIHsKICAgICAgICAgIHVuY2hhbmdlZFFQc1trZXldID0gcGFyYW1zW2tleV07CiAgICAgICAgfQogICAgICB9IC8vIFdlIG5lZWQgdG8gZnVsbHkgc2NvcGUgcXVlcnlQYXJhbXMgc28gdGhhdCB3ZSBjYW4gY3JlYXRlIG9uZSBvYmplY3QKICAgICAgLy8gdGhhdCByZXByZXNlbnRzIGJvdGggcGFzc2VkLWluIHF1ZXJ5UGFyYW1zIGFuZCBvbmVzIHRoYXQgYXJlbid0IGNoYW5nZWQKICAgICAgLy8gZnJvbSB0aGUgYWN0aXZlIHRyYW5zaXRpb24uCgoKICAgICAgdGhpcy5fZnVsbHlTY29wZVF1ZXJ5UGFyYW1zKHRhcmdldFJvdXRlTmFtZSwgbW9kZWxzLCBfcXVlcnlQYXJhbXMpOwoKICAgICAgdGhpcy5fZnVsbHlTY29wZVF1ZXJ5UGFyYW1zKHRhcmdldFJvdXRlTmFtZSwgbW9kZWxzLCB1bmNoYW5nZWRRUHMpOwoKICAgICAgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKShxdWVyeVBhcmFtcywgdW5jaGFuZ2VkUVBzKTsKICAgIH0KICAgIC8qKgogICAgICBQcmVwYXJlcyB0aGUgcXVlcnkgcGFyYW1zIGZvciBhIFVSTCBvciBUcmFuc2l0aW9uLiBSZXN0b3JlcyBhbnkgdW5kZWZpbmVkIFFQCiAgICAgIGtleXMvdmFsdWVzLCBzZXJpYWxpemVzIGFsbCB2YWx1ZXMsIGFuZCB0aGVuIHBydW5lcyBhbnkgZGVmYXVsdCB2YWx1ZXMuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX3ByZXBhcmVRdWVyeVBhcmFtcwogICAgICBAcGFyYW0ge1N0cmluZ30gdGFyZ2V0Um91dGVOYW1lCiAgICAgIEBwYXJhbSB7QXJyYXk8T2JqZWN0Pn0gbW9kZWxzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeVBhcmFtcwogICAgICBAcGFyYW0ge2Jvb2xlYW59IGtlZXBEZWZhdWx0UXVlcnlQYXJhbVZhbHVlcwogICAgICBAcmV0dXJuIHtWb2lkfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3ByZXBhcmVRdWVyeVBhcmFtcyA9IGZ1bmN0aW9uIF9wcmVwYXJlUXVlcnlQYXJhbXModGFyZ2V0Um91dGVOYW1lLCBtb2RlbHMsIHF1ZXJ5UGFyYW1zLCBfZnJvbVJvdXRlclNlcnZpY2UpIHsKICAgICAgdmFyIHN0YXRlID0gY2FsY3VsYXRlUG9zdFRyYW5zaXRpb25TdGF0ZSh0aGlzLCB0YXJnZXRSb3V0ZU5hbWUsIG1vZGVscyk7CgogICAgICB0aGlzLl9oeWRyYXRlVW5zdXBwbGllZFF1ZXJ5UGFyYW1zKHN0YXRlLCBxdWVyeVBhcmFtcywgQm9vbGVhbihfZnJvbVJvdXRlclNlcnZpY2UpKTsKCiAgICAgIHRoaXMuX3NlcmlhbGl6ZVF1ZXJ5UGFyYW1zKHN0YXRlLnJvdXRlSW5mb3MsIHF1ZXJ5UGFyYW1zKTsKCiAgICAgIGlmICghX2Zyb21Sb3V0ZXJTZXJ2aWNlKSB7CiAgICAgICAgdGhpcy5fcHJ1bmVEZWZhdWx0UXVlcnlQYXJhbVZhbHVlcyhzdGF0ZS5yb3V0ZUluZm9zLCBxdWVyeVBhcmFtcyk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSBtZXRhIGluZm9ybWF0aW9uIGZvciB0aGUgcXVlcnkgcGFyYW1zIG9mIGEgZ2l2ZW4gcm91dGUuIFRoaXMKICAgICAgd2lsbCBiZSBvdmVycmlkZGVuIHRvIGFsbG93IHN1cHBvcnQgZm9yIGxhenkgcm91dGVzLgogICAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9nZXRRUE1ldGEKICAgICAgQHBhcmFtIHtSb3V0ZUluZm99IHJvdXRlSW5mbwogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5fZ2V0UVBNZXRhID0gZnVuY3Rpb24gX2dldFFQTWV0YShyb3V0ZUluZm8pIHsKICAgICAgdmFyIHJvdXRlID0gcm91dGVJbmZvLnJvdXRlOwogICAgICByZXR1cm4gcm91dGUgJiYgKDAsIF9tZXRhbC5nZXQpKHJvdXRlLCAnX3FwJyk7CiAgICB9CiAgICAvKioKICAgICAgUmV0dXJucyBhIG1lcmdlZCBxdWVyeSBwYXJhbXMgbWV0YSBvYmplY3QgZm9yIGEgZ2l2ZW4gc2V0IG9mIHJvdXRlSW5mb3MuCiAgICAgIFVzZWZ1bCBmb3Iga25vd2luZyB3aGF0IHF1ZXJ5IHBhcmFtcyBhcmUgYXZhaWxhYmxlIGZvciBhIGdpdmVuIHJvdXRlIGhpZXJhcmNoeS4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBfcXVlcnlQYXJhbXNGb3IKICAgICAgQHBhcmFtIHtBcnJheTxSb3V0ZUluZm8+fSByb3V0ZUluZm9zCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICAqLwogICAgOwoKICAgIF9wcm90by5fcXVlcnlQYXJhbXNGb3IgPSBmdW5jdGlvbiBfcXVlcnlQYXJhbXNGb3Iocm91dGVJbmZvcykgewogICAgICB2YXIgcm91dGVJbmZvTGVuZ3RoID0gcm91dGVJbmZvcy5sZW5ndGg7CiAgICAgIHZhciBsZWFmUm91dGVOYW1lID0gcm91dGVJbmZvc1tyb3V0ZUluZm9MZW5ndGggLSAxXS5uYW1lOwogICAgICB2YXIgY2FjaGVkID0gdGhpcy5fcXBDYWNoZVtsZWFmUm91dGVOYW1lXTsKCiAgICAgIGlmIChjYWNoZWQgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBjYWNoZWQ7CiAgICAgIH0KCiAgICAgIHZhciBzaG91bGRDYWNoZSA9IHRydWU7CiAgICAgIHZhciBtYXAgPSB7fTsKICAgICAgdmFyIHFwcyA9IFtdOwogICAgICB2YXIgcXBzQnlVcmxLZXkgPSBmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICA/IHt9IDogbnVsbDsKICAgICAgdmFyIHFwTWV0YTsKICAgICAgdmFyIHFwOwogICAgICB2YXIgdXJsS2V5OwogICAgICB2YXIgcXBPdGhlcjsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm91dGVJbmZvTGVuZ3RoOyArK2kpIHsKICAgICAgICBxcE1ldGEgPSB0aGlzLl9nZXRRUE1ldGEocm91dGVJbmZvc1tpXSk7CgogICAgICAgIGlmICghcXBNZXRhKSB7CiAgICAgICAgICBzaG91bGRDYWNoZSA9IGZhbHNlOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfSAvLyBMb29wIG92ZXIgZWFjaCBRUCB0byBtYWtlIHN1cmUgd2UgZG9uJ3QgaGF2ZSBhbnkgY29sbGlzaW9ucyBieSB1cmxLZXkKCgogICAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBxcE1ldGEucXBzLmxlbmd0aDsgX2krKykgewogICAgICAgICAgcXAgPSBxcE1ldGEucXBzW19pXTsKCiAgICAgICAgICBpZiAoZmFsc2UKICAgICAgICAgIC8qIERFQlVHICovCiAgICAgICAgICApIHsKICAgICAgICAgICAgdXJsS2V5ID0gcXAudXJsS2V5OwogICAgICAgICAgICBxcE90aGVyID0gcXBzQnlVcmxLZXlbdXJsS2V5XTsKCiAgICAgICAgICAgIGlmIChxcE90aGVyICYmIHFwT3RoZXIuY29udHJvbGxlck5hbWUgIT09IHFwLmNvbnRyb2xsZXJOYW1lKSB7CiAgICAgICAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91J3JlIG5vdCBhbGxvd2VkIHRvIGhhdmUgbW9yZSB0aGFuIG9uZSBjb250cm9sbGVyIHByb3BlcnR5IG1hcCB0byB0aGUgc2FtZSBxdWVyeSBwYXJhbSBrZXksIGJ1dCBib3RoIGAiICsgcXBPdGhlci5zY29wZWRQcm9wZXJ0eU5hbWUgKyAiYCBhbmQgYCIgKyBxcC5zY29wZWRQcm9wZXJ0eU5hbWUgKyAiYCBtYXAgdG8gYCIgKyB1cmxLZXkgKyAiYC4gWW91IGNhbiBmaXggdGhpcyBieSBtYXBwaW5nIG9uZSBvZiB0aGUgY29udHJvbGxlciBwcm9wZXJ0aWVzIHRvIGEgZGlmZmVyZW50IHF1ZXJ5IHBhcmFtIGtleSB2aWEgdGhlIGBhc2AgY29uZmlnIG9wdGlvbiwgZS5nLiBgIiArIHFwT3RoZXIucHJvcCArICI6IHsgYXM6ICdvdGhlci0iICsgcXBPdGhlci5wcm9wICsgIicgfWAiLCBmYWxzZSkpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBxcHNCeVVybEtleVt1cmxLZXldID0gcXA7CiAgICAgICAgICB9CgogICAgICAgICAgcXBzLnB1c2gocXApOwogICAgICAgIH0KCiAgICAgICAgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKShtYXAsIHFwTWV0YS5tYXApOwogICAgICB9CgogICAgICB2YXIgZmluYWxRUE1ldGEgPSB7CiAgICAgICAgcXBzOiBxcHMsCiAgICAgICAgbWFwOiBtYXAKICAgICAgfTsKCiAgICAgIGlmIChzaG91bGRDYWNoZSkgewogICAgICAgIHRoaXMuX3FwQ2FjaGVbbGVhZlJvdXRlTmFtZV0gPSBmaW5hbFFQTWV0YTsKICAgICAgfQoKICAgICAgcmV0dXJuIGZpbmFsUVBNZXRhOwogICAgfQogICAgLyoqCiAgICAgIE1hcHMgYWxsIHF1ZXJ5IHBhcmFtIGtleXMgdG8gdGhlaXIgZnVsbHkgc2NvcGVkIHByb3BlcnR5IG5hbWUgb2YgdGhlIGZvcm0KICAgICAgYGNvbnRyb2xsZXJOYW1lOnByb3BOYW1lYC4KICAgICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBfZnVsbHlTY29wZVF1ZXJ5UGFyYW1zCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBsZWFmUm91dGVOYW1lCiAgICAgIEBwYXJhbSB7QXJyYXk8T2JqZWN0Pn0gY29udGV4dHMKICAgICAgQHBhcmFtIHtPYmplY3R9IHF1ZXJ5UGFyYW1zCiAgICAgIEByZXR1cm4ge1ZvaWR9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5fZnVsbHlTY29wZVF1ZXJ5UGFyYW1zID0gZnVuY3Rpb24gX2Z1bGx5U2NvcGVRdWVyeVBhcmFtcyhsZWFmUm91dGVOYW1lLCBjb250ZXh0cywgcXVlcnlQYXJhbXMpIHsKICAgICAgdmFyIHN0YXRlID0gY2FsY3VsYXRlUG9zdFRyYW5zaXRpb25TdGF0ZSh0aGlzLCBsZWFmUm91dGVOYW1lLCBjb250ZXh0cyk7CiAgICAgIHZhciByb3V0ZUluZm9zID0gc3RhdGUucm91dGVJbmZvczsKICAgICAgdmFyIHFwTWV0YTsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSByb3V0ZUluZm9zLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgICAgcXBNZXRhID0gdGhpcy5fZ2V0UVBNZXRhKHJvdXRlSW5mb3NbaV0pOwoKICAgICAgICBpZiAoIXFwTWV0YSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICB2YXIgcXAgPSB2b2lkIDA7CiAgICAgICAgdmFyIHByZXNlbnRQcm9wID0gdm9pZCAwOwoKICAgICAgICBmb3IgKHZhciBqID0gMCwgcXBMZW4gPSBxcE1ldGEucXBzLmxlbmd0aDsgaiA8IHFwTGVuOyArK2opIHsKICAgICAgICAgIHFwID0gcXBNZXRhLnFwc1tqXTsKICAgICAgICAgIHByZXNlbnRQcm9wID0gcXAucHJvcCBpbiBxdWVyeVBhcmFtcyAmJiBxcC5wcm9wIHx8IHFwLnNjb3BlZFByb3BlcnR5TmFtZSBpbiBxdWVyeVBhcmFtcyAmJiBxcC5zY29wZWRQcm9wZXJ0eU5hbWUgfHwgcXAudXJsS2V5IGluIHF1ZXJ5UGFyYW1zICYmIHFwLnVybEtleTsKCiAgICAgICAgICBpZiAocHJlc2VudFByb3ApIHsKICAgICAgICAgICAgaWYgKHByZXNlbnRQcm9wICE9PSBxcC5zY29wZWRQcm9wZXJ0eU5hbWUpIHsKICAgICAgICAgICAgICBxdWVyeVBhcmFtc1txcC5zY29wZWRQcm9wZXJ0eU5hbWVdID0gcXVlcnlQYXJhbXNbcHJlc2VudFByb3BdOwogICAgICAgICAgICAgIGRlbGV0ZSBxdWVyeVBhcmFtc1twcmVzZW50UHJvcF07CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBIeWRyYXRlcyAoYWRkcy9yZXN0b3JlcykgYW55IHF1ZXJ5IHBhcmFtcyB0aGF0IGhhdmUgcHJlLWV4aXN0aW5nIHZhbHVlcyBpbnRvCiAgICAgIHRoZSBnaXZlbiBxdWVyeVBhcmFtcyBoYXNoLiBUaGlzIGlzIHdoYXQgYWxsb3dzIHF1ZXJ5IHBhcmFtcyB0byBiZSAic3RpY2t5IgogICAgICBhbmQgcmVzdG9yZSB0aGVpciBsYXN0IGtub3duIHZhbHVlcyBmb3IgdGhlaXIgc2NvcGUuCiAgICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX2h5ZHJhdGVVbnN1cHBsaWVkUXVlcnlQYXJhbXMKICAgICAgQHBhcmFtIHtUcmFuc2l0aW9uU3RhdGV9IHN0YXRlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeVBhcmFtcwogICAgICBAcmV0dXJuIHtWb2lkfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX2h5ZHJhdGVVbnN1cHBsaWVkUXVlcnlQYXJhbXMgPSBmdW5jdGlvbiBfaHlkcmF0ZVVuc3VwcGxpZWRRdWVyeVBhcmFtcyhzdGF0ZSwgcXVlcnlQYXJhbXMsIF9mcm9tUm91dGVyU2VydmljZSkgewogICAgICB2YXIgcm91dGVJbmZvcyA9IHN0YXRlLnJvdXRlSW5mb3M7CiAgICAgIHZhciBhcHBDYWNoZSA9IHRoaXMuX2J1Y2tldENhY2hlOwogICAgICB2YXIgcXBNZXRhOwogICAgICB2YXIgcXA7CiAgICAgIHZhciBwcmVzZW50UHJvcDsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm91dGVJbmZvcy5sZW5ndGg7ICsraSkgewogICAgICAgIHFwTWV0YSA9IHRoaXMuX2dldFFQTWV0YShyb3V0ZUluZm9zW2ldKTsKCiAgICAgICAgaWYgKCFxcE1ldGEpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KCiAgICAgICAgZm9yICh2YXIgaiA9IDAsIHFwTGVuID0gcXBNZXRhLnFwcy5sZW5ndGg7IGogPCBxcExlbjsgKytqKSB7CiAgICAgICAgICBxcCA9IHFwTWV0YS5xcHNbal07CiAgICAgICAgICBwcmVzZW50UHJvcCA9IHFwLnByb3AgaW4gcXVlcnlQYXJhbXMgJiYgcXAucHJvcCB8fCBxcC5zY29wZWRQcm9wZXJ0eU5hbWUgaW4gcXVlcnlQYXJhbXMgJiYgcXAuc2NvcGVkUHJvcGVydHlOYW1lIHx8IHFwLnVybEtleSBpbiBxdWVyeVBhcmFtcyAmJiBxcC51cmxLZXk7CiAgICAgICAgICAoZmFsc2UgJiYgIShmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIGlmIChxcC51cmxLZXkgPT09IHByZXNlbnRQcm9wKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChfZnJvbVJvdXRlclNlcnZpY2UgJiYgcHJlc2VudFByb3AgIT09IGZhbHNlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgIH0oKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgcGFzc2VkIHRoZSBgIiArIHByZXNlbnRQcm9wICsgImAgcXVlcnkgcGFyYW1ldGVyIGR1cmluZyBhIHRyYW5zaXRpb24gaW50byAiICsgcXAucm91dGUucm91dGVOYW1lICsgIiwgcGxlYXNlIHVwZGF0ZSB0byAiICsgcXAudXJsS2V5LCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIGlmIChxcC51cmxLZXkgPT09IHByZXNlbnRQcm9wKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChfZnJvbVJvdXRlclNlcnZpY2UgJiYgcHJlc2VudFByb3AgIT09IGZhbHNlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgIH0oKSkpOwoKICAgICAgICAgIGlmIChwcmVzZW50UHJvcCkgewogICAgICAgICAgICBpZiAocHJlc2VudFByb3AgIT09IHFwLnNjb3BlZFByb3BlcnR5TmFtZSkgewogICAgICAgICAgICAgIHF1ZXJ5UGFyYW1zW3FwLnNjb3BlZFByb3BlcnR5TmFtZV0gPSBxdWVyeVBhcmFtc1twcmVzZW50UHJvcF07CiAgICAgICAgICAgICAgZGVsZXRlIHF1ZXJ5UGFyYW1zW3ByZXNlbnRQcm9wXTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdmFyIGNhY2hlS2V5ID0gKDAsIF91dGlscy5jYWxjdWxhdGVDYWNoZUtleSkocXAucm91dGUuZnVsbFJvdXRlTmFtZSwgcXAucGFydHMsIHN0YXRlLnBhcmFtcyk7CiAgICAgICAgICAgIHF1ZXJ5UGFyYW1zW3FwLnNjb3BlZFByb3BlcnR5TmFtZV0gPSBhcHBDYWNoZS5sb29rdXAoY2FjaGVLZXksIHFwLnByb3AsIHFwLmRlZmF1bHRWYWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fc2NoZWR1bGVMb2FkaW5nRXZlbnQgPSBmdW5jdGlvbiBfc2NoZWR1bGVMb2FkaW5nRXZlbnQodHJhbnNpdGlvbiwgb3JpZ2luUm91dGUpIHsKICAgICAgdGhpcy5fY2FuY2VsU2xvd1RyYW5zaXRpb25UaW1lcigpOwoKICAgICAgdGhpcy5fc2xvd1RyYW5zaXRpb25UaW1lciA9ICgwLCBfcnVubG9vcC5zY2hlZHVsZU9uY2UpKCdyb3V0ZXJUcmFuc2l0aW9ucycsIHRoaXMsICdfaGFuZGxlU2xvd1RyYW5zaXRpb24nLCB0cmFuc2l0aW9uLCBvcmlnaW5Sb3V0ZSk7CiAgICB9OwoKICAgIF9wcm90by5faGFuZGxlU2xvd1RyYW5zaXRpb24gPSBmdW5jdGlvbiBfaGFuZGxlU2xvd1RyYW5zaXRpb24odHJhbnNpdGlvbiwgb3JpZ2luUm91dGUpIHsKICAgICAgaWYgKCF0aGlzLl9yb3V0ZXJNaWNyb2xpYi5hY3RpdmVUcmFuc2l0aW9uKSB7CiAgICAgICAgLy8gRG9uJ3QgZmlyZSBhbiBldmVudCBpZiB3ZSd2ZSBzaW5jZSBtb3ZlZCBvbiBmcm9tCiAgICAgICAgLy8gdGhlIHRyYW5zaXRpb24gdGhhdCBwdXQgdXMgaW4gYSBsb2FkaW5nIHN0YXRlLgogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIHRhcmdldFN0YXRlID0gbmV3IF9yb3V0ZXJfc3RhdGUuZGVmYXVsdCh0aGlzLCB0aGlzLl9yb3V0ZXJNaWNyb2xpYiwgdGhpcy5fcm91dGVyTWljcm9saWIuYWN0aXZlVHJhbnNpdGlvbltfcm91dGVyX2pzLlNUQVRFX1NZTUJPTF0pOwogICAgICB0aGlzLnNldCgndGFyZ2V0U3RhdGUnLCB0YXJnZXRTdGF0ZSk7CiAgICAgIHRyYW5zaXRpb24udHJpZ2dlcih0cnVlLCAnbG9hZGluZycsIHRyYW5zaXRpb24sIG9yaWdpblJvdXRlKTsKICAgIH07CgogICAgX3Byb3RvLl9jYW5jZWxTbG93VHJhbnNpdGlvblRpbWVyID0gZnVuY3Rpb24gX2NhbmNlbFNsb3dUcmFuc2l0aW9uVGltZXIoKSB7CiAgICAgIGlmICh0aGlzLl9zbG93VHJhbnNpdGlvblRpbWVyKSB7CiAgICAgICAgKDAsIF9ydW5sb29wLmNhbmNlbCkodGhpcy5fc2xvd1RyYW5zaXRpb25UaW1lcik7CiAgICAgIH0KCiAgICAgIHRoaXMuX3Nsb3dUcmFuc2l0aW9uVGltZXIgPSBudWxsOwogICAgfSAvLyBUaGVzZSB0aHJlZSBoZWxwZXIgZnVuY3Rpb25zIGFyZSB1c2VkIHRvIGVuc3VyZSBlcnJvcnMgYXJlbid0CiAgICAvLyByZS1yYWlzZWQgaWYgdGhleSdyZSBoYW5kbGVkIGluIGEgcm91dGUncyBlcnJvciBhY3Rpb24uCiAgICA7CgogICAgX3Byb3RvLl9tYXJrRXJyb3JBc0hhbmRsZWQgPSBmdW5jdGlvbiBfbWFya0Vycm9yQXNIYW5kbGVkKGVycm9yKSB7CiAgICAgIHRoaXMuX2hhbmRsZWRFcnJvcnMuYWRkKGVycm9yKTsKICAgIH07CgogICAgX3Byb3RvLl9pc0Vycm9ySGFuZGxlZCA9IGZ1bmN0aW9uIF9pc0Vycm9ySGFuZGxlZChlcnJvcikgewogICAgICByZXR1cm4gdGhpcy5faGFuZGxlZEVycm9ycy5oYXMoZXJyb3IpOwogICAgfTsKCiAgICBfcHJvdG8uX2NsZWFySGFuZGxlZEVycm9yID0gZnVuY3Rpb24gX2NsZWFySGFuZGxlZEVycm9yKGVycm9yKSB7CiAgICAgIHRoaXMuX2hhbmRsZWRFcnJvcnMuZGVsZXRlKGVycm9yKTsKICAgIH07CgogICAgX3Byb3RvLl9nZXRFbmdpbmVJbnN0YW5jZSA9IGZ1bmN0aW9uIF9nZXRFbmdpbmVJbnN0YW5jZShfcmVmKSB7CiAgICAgIHZhciBuYW1lID0gX3JlZi5uYW1lLAogICAgICAgICAgaW5zdGFuY2VJZCA9IF9yZWYuaW5zdGFuY2VJZCwKICAgICAgICAgIG1vdW50UG9pbnQgPSBfcmVmLm1vdW50UG9pbnQ7CiAgICAgIHZhciBlbmdpbmVJbnN0YW5jZXMgPSB0aGlzLl9lbmdpbmVJbnN0YW5jZXM7CgogICAgICBpZiAoIWVuZ2luZUluc3RhbmNlc1tuYW1lXSkgewogICAgICAgIGVuZ2luZUluc3RhbmNlc1tuYW1lXSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIH0KCiAgICAgIHZhciBlbmdpbmVJbnN0YW5jZSA9IGVuZ2luZUluc3RhbmNlc1tuYW1lXVtpbnN0YW5jZUlkXTsKCiAgICAgIGlmICghZW5naW5lSW5zdGFuY2UpIHsKICAgICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh0aGlzKTsKICAgICAgICAoZmFsc2UgJiYgIShvd25lci5oYXNSZWdpc3RyYXRpb24oImVuZ2luZToiICsgbmFtZSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byBtb3VudCB0aGUgZW5naW5lICciICsgbmFtZSArICInIGluIHlvdXIgcm91dGVyIG1hcCwgYnV0IHRoZSBlbmdpbmUgY2FuIG5vdCBiZSBmb3VuZC4iLCBvd25lci5oYXNSZWdpc3RyYXRpb24oImVuZ2luZToiICsgbmFtZSkpKTsKICAgICAgICBlbmdpbmVJbnN0YW5jZSA9IG93bmVyLmJ1aWxkQ2hpbGRFbmdpbmVJbnN0YW5jZShuYW1lLCB7CiAgICAgICAgICByb3V0YWJsZTogdHJ1ZSwKICAgICAgICAgIG1vdW50UG9pbnQ6IG1vdW50UG9pbnQKICAgICAgICB9KTsKICAgICAgICBlbmdpbmVJbnN0YW5jZS5ib290KCk7CiAgICAgICAgZW5naW5lSW5zdGFuY2VzW25hbWVdW2luc3RhbmNlSWRdID0gZW5naW5lSW5zdGFuY2U7CiAgICAgIH0KCiAgICAgIHJldHVybiBlbmdpbmVJbnN0YW5jZTsKICAgIH07CgogICAgcmV0dXJuIEVtYmVyUm91dGVyOwogIH0oX3J1bnRpbWUuT2JqZWN0KTsKICAvKgogICAgSGVscGVyIGZ1bmN0aW9uIGZvciBpdGVyYXRpbmcgb3ZlciByb3V0ZXMgaW4gYSBzZXQgb2Ygcm91dGVJbmZvcyB0aGF0IGFyZQogICAgYXQgb3IgYWJvdmUgdGhlIGdpdmVuIG9yaWdpbiByb3V0ZS4gRXhhbXBsZTogaWYgYG9yaWdpblJvdXRlYCA9PT0gJ2Zvby5iYXInCiAgICBhbmQgdGhlIHJvdXRlSW5mb3MgZ2l2ZW4gd2VyZSBmb3IgJ2Zvby5iYXIuYmF6JywgdGhlbiB0aGUgZ2l2ZW4gY2FsbGJhY2sKICAgIHdpbGwgYmUgaW52b2tlZCB3aXRoIHRoZSByb3V0ZXMgZm9yICdmb28uYmFyJywgJ2ZvbycsIGFuZCAnYXBwbGljYXRpb24nCiAgICBpbmRpdmlkdWFsbHkuCiAgCiAgICBJZiB0aGUgY2FsbGJhY2sgcmV0dXJucyBhbnl0aGluZyBvdGhlciB0aGFuIGB0cnVlYCwgdGhlbiBpdGVyYXRpb24gd2lsbCBzdG9wLgogIAogICAgQHByaXZhdGUKICAgIEBwYXJhbSB7Um91dGV9IG9yaWdpblJvdXRlCiAgICBAcGFyYW0ge0FycmF5PFJvdXRlSW5mbz59IHJvdXRlSW5mb3MKICAgIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrCiAgICBAcmV0dXJuIHtWb2lkfQogICAqLwoKCiAgZnVuY3Rpb24gZm9yRWFjaFJvdXRlQWJvdmUocm91dGVJbmZvcywgY2FsbGJhY2spIHsKICAgIGZvciAodmFyIGkgPSByb3V0ZUluZm9zLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgIHZhciByb3V0ZUluZm8gPSByb3V0ZUluZm9zW2ldOwogICAgICB2YXIgcm91dGUgPSByb3V0ZUluZm8ucm91dGU7IC8vIHJvdXRlSW5mby5oYW5kbGVyIGJlaW5nIGB1bmRlZmluZWRgIGdlbmVyYWxseSBtZWFucyBlaXRoZXI6CiAgICAgIC8vCiAgICAgIC8vIDEuIGFuIGVycm9yIG9jY3VycmVkIGR1cmluZyBjcmVhdGlvbiBvZiB0aGUgcm91dGUgaW4gcXVlc3Rpb24KICAgICAgLy8gMi4gdGhlIHJvdXRlIGlzIGFjcm9zcyBhbiBhc3luYyBib3VuZGFyeSAoZS5nLiB3aXRoaW4gYW4gZW5naW5lKQogICAgICAvLwogICAgICAvLyBJbiBib3RoIG9mIHRoZXNlIGNhc2VzLCB3ZSBjYW5ub3QgaW52b2tlIHRoZSBjYWxsYmFjayBvbiB0aGF0IHNwZWNpZmljCiAgICAgIC8vIHJvdXRlLCBiZWNhdXNlIGl0IGp1c3QgZG9lc24ndCBleGlzdC4uLgoKICAgICAgaWYgKHJvdXRlID09PSB1bmRlZmluZWQpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQoKICAgICAgaWYgKGNhbGxiYWNrKHJvdXRlLCByb3V0ZUluZm8pICE9PSB0cnVlKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICB9CiAgfSAvLyBUaGVzZSBnZXQgaW52b2tlZCB3aGVuIGFuIGFjdGlvbiBidWJibGVzIGFib3ZlIEFwcGxpY2F0aW9uUm91dGUKICAvLyBhbmQgYXJlIG5vdCBtZWFudCB0byBiZSBvdmVycmlkYWJsZS4KCgogIHZhciBkZWZhdWx0QWN0aW9uSGFuZGxlcnMgPSB7CiAgICB3aWxsUmVzb2x2ZU1vZGVsOiBmdW5jdGlvbiB3aWxsUmVzb2x2ZU1vZGVsKF9yb3V0ZUluZm9zLCB0cmFuc2l0aW9uLCBvcmlnaW5Sb3V0ZSkgewogICAgICB0aGlzLl9zY2hlZHVsZUxvYWRpbmdFdmVudCh0cmFuc2l0aW9uLCBvcmlnaW5Sb3V0ZSk7CiAgICB9LAogICAgLy8gQXR0ZW1wdCB0byBmaW5kIGFuIGFwcHJvcHJpYXRlIGVycm9yIHJvdXRlIG9yIHN1YnN0YXRlIHRvIGVudGVyLgogICAgZXJyb3I6IGZ1bmN0aW9uIGVycm9yKHJvdXRlSW5mb3MsIF9lcnJvcjIsIHRyYW5zaXRpb24pIHsKICAgICAgdmFyIHJvdXRlciA9IHRoaXM7CiAgICAgIHZhciByb3V0ZUluZm9XaXRoRXJyb3IgPSByb3V0ZUluZm9zW3JvdXRlSW5mb3MubGVuZ3RoIC0gMV07CiAgICAgIGZvckVhY2hSb3V0ZUFib3ZlKHJvdXRlSW5mb3MsIGZ1bmN0aW9uIChyb3V0ZSwgcm91dGVJbmZvKSB7CiAgICAgICAgLy8gV2UgZG9uJ3QgY2hlY2sgdGhlIGxlYWYgbW9zdCByb3V0ZUluZm8gc2luY2UgdGhhdCB3b3VsZAogICAgICAgIC8vIHRlY2huaWNhbGx5IGJlIGJlbG93IHdoZXJlIHdlJ3JlIGF0IGluIHRoZSByb3V0ZSBoaWVyYXJjaHkuCiAgICAgICAgaWYgKHJvdXRlSW5mbyAhPT0gcm91dGVJbmZvV2l0aEVycm9yKSB7CiAgICAgICAgICAvLyBDaGVjayBmb3IgdGhlIGV4aXN0ZW5jZSBvZiBhbiAnZXJyb3InIHJvdXRlLgogICAgICAgICAgdmFyIGVycm9yUm91dGVOYW1lID0gZmluZFJvdXRlU3RhdGVOYW1lKHJvdXRlLCAnZXJyb3InKTsKCiAgICAgICAgICBpZiAoZXJyb3JSb3V0ZU5hbWUpIHsKICAgICAgICAgICAgcm91dGVyLl9tYXJrRXJyb3JBc0hhbmRsZWQoX2Vycm9yMik7CgogICAgICAgICAgICByb3V0ZXIuaW50ZXJtZWRpYXRlVHJhbnNpdGlvblRvKGVycm9yUm91dGVOYW1lLCBfZXJyb3IyKTsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgIH0gLy8gQ2hlY2sgZm9yIGFuICdlcnJvcicgc3Vic3RhdGUgcm91dGUKCgogICAgICAgIHZhciBlcnJvclN1YnN0YXRlTmFtZSA9IGZpbmRSb3V0ZVN1YnN0YXRlTmFtZShyb3V0ZSwgJ2Vycm9yJyk7CgogICAgICAgIGlmIChlcnJvclN1YnN0YXRlTmFtZSkgewogICAgICAgICAgcm91dGVyLl9tYXJrRXJyb3JBc0hhbmRsZWQoX2Vycm9yMik7CgogICAgICAgICAgcm91dGVyLmludGVybWVkaWF0ZVRyYW5zaXRpb25UbyhlcnJvclN1YnN0YXRlTmFtZSwgX2Vycm9yMik7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfSk7CiAgICAgIGxvZ0Vycm9yKF9lcnJvcjIsICJFcnJvciB3aGlsZSBwcm9jZXNzaW5nIHJvdXRlOiAiICsgdHJhbnNpdGlvbi50YXJnZXROYW1lKTsKICAgIH0sCiAgICAvLyBBdHRlbXB0IHRvIGZpbmQgYW4gYXBwcm9wcmlhdGUgbG9hZGluZyByb3V0ZSBvciBzdWJzdGF0ZSB0byBlbnRlci4KICAgIGxvYWRpbmc6IGZ1bmN0aW9uIGxvYWRpbmcocm91dGVJbmZvcywgdHJhbnNpdGlvbikgewogICAgICB2YXIgcm91dGVyID0gdGhpczsKICAgICAgdmFyIHJvdXRlSW5mb1dpdGhTbG93TG9hZGluZyA9IHJvdXRlSW5mb3Nbcm91dGVJbmZvcy5sZW5ndGggLSAxXTsKICAgICAgZm9yRWFjaFJvdXRlQWJvdmUocm91dGVJbmZvcywgZnVuY3Rpb24gKHJvdXRlLCByb3V0ZUluZm8pIHsKICAgICAgICAvLyBXZSBkb24ndCBjaGVjayB0aGUgbGVhZiBtb3N0IHJvdXRlSW5mb3Mgc2luY2UgdGhhdCB3b3VsZAogICAgICAgIC8vIHRlY2huaWNhbGx5IGJlIGJlbG93IHdoZXJlIHdlJ3JlIGF0IGluIHRoZSByb3V0ZSBoaWVyYXJjaHkuCiAgICAgICAgaWYgKHJvdXRlSW5mbyAhPT0gcm91dGVJbmZvV2l0aFNsb3dMb2FkaW5nKSB7CiAgICAgICAgICAvLyBDaGVjayBmb3IgdGhlIGV4aXN0ZW5jZSBvZiBhICdsb2FkaW5nJyByb3V0ZS4KICAgICAgICAgIHZhciBsb2FkaW5nUm91dGVOYW1lID0gZmluZFJvdXRlU3RhdGVOYW1lKHJvdXRlLCAnbG9hZGluZycpOwoKICAgICAgICAgIGlmIChsb2FkaW5nUm91dGVOYW1lKSB7CiAgICAgICAgICAgIHJvdXRlci5pbnRlcm1lZGlhdGVUcmFuc2l0aW9uVG8obG9hZGluZ1JvdXRlTmFtZSk7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICB9IC8vIENoZWNrIGZvciBsb2FkaW5nIHN1YnN0YXRlCgoKICAgICAgICB2YXIgbG9hZGluZ1N1YnN0YXRlTmFtZSA9IGZpbmRSb3V0ZVN1YnN0YXRlTmFtZShyb3V0ZSwgJ2xvYWRpbmcnKTsKCiAgICAgICAgaWYgKGxvYWRpbmdTdWJzdGF0ZU5hbWUpIHsKICAgICAgICAgIHJvdXRlci5pbnRlcm1lZGlhdGVUcmFuc2l0aW9uVG8obG9hZGluZ1N1YnN0YXRlTmFtZSk7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfSAvLyBEb24ndCBidWJibGUgYWJvdmUgcGl2b3Qgcm91dGUuCgoKICAgICAgICByZXR1cm4gdHJhbnNpdGlvbi5waXZvdEhhbmRsZXIgIT09IHJvdXRlOwogICAgICB9KTsKICAgIH0KICB9OwoKICBmdW5jdGlvbiBsb2dFcnJvcihfZXJyb3IsIGluaXRpYWxNZXNzYWdlKSB7CiAgICB2YXIgX2NvbnNvbGU7CgogICAgdmFyIGVycm9yQXJncyA9IFtdOwogICAgdmFyIGVycm9yOwoKICAgIGlmIChfZXJyb3IgJiYgdHlwZW9mIF9lcnJvciA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIF9lcnJvci5lcnJvclRocm93biA9PT0gJ29iamVjdCcpIHsKICAgICAgZXJyb3IgPSBfZXJyb3IuZXJyb3JUaHJvd247CiAgICB9IGVsc2UgewogICAgICBlcnJvciA9IF9lcnJvcjsKICAgIH0KCiAgICBpZiAoaW5pdGlhbE1lc3NhZ2UpIHsKICAgICAgZXJyb3JBcmdzLnB1c2goaW5pdGlhbE1lc3NhZ2UpOwogICAgfQoKICAgIGlmIChlcnJvcikgewogICAgICBpZiAoZXJyb3IubWVzc2FnZSkgewogICAgICAgIGVycm9yQXJncy5wdXNoKGVycm9yLm1lc3NhZ2UpOwogICAgICB9CgogICAgICBpZiAoZXJyb3Iuc3RhY2spIHsKICAgICAgICBlcnJvckFyZ3MucHVzaChlcnJvci5zdGFjayk7CiAgICAgIH0KCiAgICAgIGlmICh0eXBlb2YgZXJyb3IgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgZXJyb3JBcmdzLnB1c2goZXJyb3IpOwogICAgICB9CiAgICB9CgogICAgKF9jb25zb2xlID0gY29uc29sZSkuZXJyb3IuYXBwbHkoX2NvbnNvbGUsIGVycm9yQXJncyk7IC8vZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlCgogIH0KICAvKioKICAgIEZpbmRzIHRoZSBuYW1lIG9mIHRoZSBzdWJzdGF0ZSByb3V0ZSBpZiBpdCBleGlzdHMgZm9yIHRoZSBnaXZlbiByb3V0ZS4gQQogICAgc3Vic3RhdGUgcm91dGUgaXMgb2YgdGhlIGZvcm0gYHJvdXRlX3N0YXRlYCwgc3VjaCBhcyBgZm9vX2xvYWRpbmdgLgogIAogICAgQHByaXZhdGUKICAgIEBwYXJhbSB7Um91dGV9IHJvdXRlCiAgICBAcGFyYW0ge1N0cmluZ30gc3RhdGUKICAgIEByZXR1cm4ge1N0cmluZ30KICAqLwoKCiAgZnVuY3Rpb24gZmluZFJvdXRlU3Vic3RhdGVOYW1lKHJvdXRlLCBzdGF0ZSkgewogICAgdmFyIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikocm91dGUpOwogICAgdmFyIHJvdXRlTmFtZSA9IHJvdXRlLnJvdXRlTmFtZSwKICAgICAgICBmdWxsUm91dGVOYW1lID0gcm91dGUuZnVsbFJvdXRlTmFtZSwKICAgICAgICByb3V0ZXIgPSByb3V0ZS5fcm91dGVyOwogICAgdmFyIHN1YnN0YXRlTmFtZSA9IHJvdXRlTmFtZSArICJfIiArIHN0YXRlOwogICAgdmFyIHN1YnN0YXRlTmFtZUZ1bGwgPSBmdWxsUm91dGVOYW1lICsgIl8iICsgc3RhdGU7CiAgICByZXR1cm4gcm91dGVIYXNCZWVuRGVmaW5lZChvd25lciwgcm91dGVyLCBzdWJzdGF0ZU5hbWUsIHN1YnN0YXRlTmFtZUZ1bGwpID8gc3Vic3RhdGVOYW1lRnVsbCA6ICcnOwogIH0KICAvKioKICAgIEZpbmRzIHRoZSBuYW1lIG9mIHRoZSBzdGF0ZSByb3V0ZSBpZiBpdCBleGlzdHMgZm9yIHRoZSBnaXZlbiByb3V0ZS4gQSBzdGF0ZQogICAgcm91dGUgaXMgb2YgdGhlIGZvcm0gYHJvdXRlLnN0YXRlYCwgc3VjaCBhcyBgZm9vLmxvYWRpbmdgLiBQcm9wZXJseSBIYW5kbGVzCiAgICBgYXBwbGljYXRpb25gIG5hbWVkIHJvdXRlcy4KICAKICAgIEBwcml2YXRlCiAgICBAcGFyYW0ge1JvdXRlfSByb3V0ZQogICAgQHBhcmFtIHtTdHJpbmd9IHN0YXRlCiAgICBAcmV0dXJuIHtTdHJpbmd9CiAgKi8KCgogIGZ1bmN0aW9uIGZpbmRSb3V0ZVN0YXRlTmFtZShyb3V0ZSwgc3RhdGUpIHsKICAgIHZhciBvd25lciA9ICgwLCBfb3duZXIuZ2V0T3duZXIpKHJvdXRlKTsKICAgIHZhciByb3V0ZU5hbWUgPSByb3V0ZS5yb3V0ZU5hbWUsCiAgICAgICAgZnVsbFJvdXRlTmFtZSA9IHJvdXRlLmZ1bGxSb3V0ZU5hbWUsCiAgICAgICAgcm91dGVyID0gcm91dGUuX3JvdXRlcjsKICAgIHZhciBzdGF0ZU5hbWUgPSByb3V0ZU5hbWUgPT09ICdhcHBsaWNhdGlvbicgPyBzdGF0ZSA6IHJvdXRlTmFtZSArICIuIiArIHN0YXRlOwogICAgdmFyIHN0YXRlTmFtZUZ1bGwgPSBmdWxsUm91dGVOYW1lID09PSAnYXBwbGljYXRpb24nID8gc3RhdGUgOiBmdWxsUm91dGVOYW1lICsgIi4iICsgc3RhdGU7CiAgICByZXR1cm4gcm91dGVIYXNCZWVuRGVmaW5lZChvd25lciwgcm91dGVyLCBzdGF0ZU5hbWUsIHN0YXRlTmFtZUZ1bGwpID8gc3RhdGVOYW1lRnVsbCA6ICcnOwogIH0KICAvKioKICAgIERldGVybWluZXMgd2hldGhlciBvciBub3QgYSByb3V0ZSBoYXMgYmVlbiBkZWZpbmVkIGJ5IGNoZWNraW5nIHRoYXQgdGhlIHJvdXRlCiAgICBpcyBpbiB0aGUgUm91dGVyJ3MgbWFwIGFuZCB0aGUgb3duZXIgaGFzIGEgcmVnaXN0cmF0aW9uIGZvciB0aGF0IHJvdXRlLgogIAogICAgQHByaXZhdGUKICAgIEBwYXJhbSB7T3duZXJ9IG93bmVyCiAgICBAcGFyYW0ge1JvdXRlcn0gcm91dGVyCiAgICBAcGFyYW0ge1N0cmluZ30gbG9jYWxOYW1lCiAgICBAcGFyYW0ge1N0cmluZ30gZnVsbE5hbWUKICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgKi8KCgogIGZ1bmN0aW9uIHJvdXRlSGFzQmVlbkRlZmluZWQob3duZXIsIHJvdXRlciwgbG9jYWxOYW1lLCBmdWxsTmFtZSkgewogICAgdmFyIHJvdXRlckhhc1JvdXRlID0gcm91dGVyLmhhc1JvdXRlKGZ1bGxOYW1lKTsKICAgIHZhciBvd25lckhhc1JvdXRlID0gb3duZXIuaGFzUmVnaXN0cmF0aW9uKCJ0ZW1wbGF0ZToiICsgbG9jYWxOYW1lKSB8fCBvd25lci5oYXNSZWdpc3RyYXRpb24oInJvdXRlOiIgKyBsb2NhbE5hbWUpOwogICAgcmV0dXJuIHJvdXRlckhhc1JvdXRlICYmIG93bmVySGFzUm91dGU7CiAgfQoKICBmdW5jdGlvbiBfdHJpZ2dlckV2ZW50KHJvdXRlSW5mb3MsIGlnbm9yZUZhaWx1cmUsIG5hbWUsIGFyZ3MpIHsKICAgIGlmICghcm91dGVJbmZvcykgewogICAgICBpZiAoaWdub3JlRmFpbHVyZSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhyb3cgbmV3IF9lcnJvcjMuZGVmYXVsdCgiQ2FuJ3QgdHJpZ2dlciBhY3Rpb24gJyIgKyBuYW1lICsgIicgYmVjYXVzZSB5b3VyIGFwcCBoYXNuJ3QgZmluaXNoZWQgdHJhbnNpdGlvbmluZyBpbnRvIGl0cyBmaXJzdCByb3V0ZS4gVG8gdHJpZ2dlciBhbiBhY3Rpb24gb24gZGVzdGluYXRpb24gcm91dGVzIGR1cmluZyBhIHRyYW5zaXRpb24sIHlvdSBjYW4gY2FsbCBgLnNlbmQoKWAgb24gdGhlIGBUcmFuc2l0aW9uYCBvYmplY3QgcGFzc2VkIHRvIHRoZSBgbW9kZWwvYmVmb3JlTW9kZWwvYWZ0ZXJNb2RlbGAgaG9va3MuIik7CiAgICB9CgogICAgdmFyIGV2ZW50V2FzSGFuZGxlZCA9IGZhbHNlOwogICAgdmFyIHJvdXRlSW5mbywgaGFuZGxlciwgYWN0aW9uSGFuZGxlcjsKCiAgICBmb3IgKHZhciBpID0gcm91dGVJbmZvcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICByb3V0ZUluZm8gPSByb3V0ZUluZm9zW2ldOwogICAgICBoYW5kbGVyID0gcm91dGVJbmZvLnJvdXRlOwogICAgICBhY3Rpb25IYW5kbGVyID0gaGFuZGxlciAmJiBoYW5kbGVyLmFjdGlvbnMgJiYgaGFuZGxlci5hY3Rpb25zW25hbWVdOwoKICAgICAgaWYgKGFjdGlvbkhhbmRsZXIpIHsKICAgICAgICBpZiAoYWN0aW9uSGFuZGxlci5hcHBseShoYW5kbGVyLCBhcmdzKSA9PT0gdHJ1ZSkgewogICAgICAgICAgZXZlbnRXYXNIYW5kbGVkID0gdHJ1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgLy8gU2hvdWxkIG9ubHkgaGl0IGhlcmUgaWYgYSBub24tYnViYmxpbmcgZXJyb3IgYWN0aW9uIGlzIHRyaWdnZXJlZCBvbiBhIHJvdXRlLgogICAgICAgICAgaWYgKG5hbWUgPT09ICdlcnJvcicpIHsKICAgICAgICAgICAgaGFuZGxlci5fcm91dGVyLl9tYXJrRXJyb3JBc0hhbmRsZWQoYXJnc1swXSk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgfQogICAgfQoKICAgIHZhciBkZWZhdWx0SGFuZGxlciA9IGRlZmF1bHRBY3Rpb25IYW5kbGVyc1tuYW1lXTsKCiAgICBpZiAoZGVmYXVsdEhhbmRsZXIpIHsKICAgICAgZGVmYXVsdEhhbmRsZXIuYXBwbHkodGhpcywgW3JvdXRlSW5mb3NdLmNvbmNhdChhcmdzKSk7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoIWV2ZW50V2FzSGFuZGxlZCAmJiAhaWdub3JlRmFpbHVyZSkgewogICAgICB0aHJvdyBuZXcgX2Vycm9yMy5kZWZhdWx0KCJOb3RoaW5nIGhhbmRsZWQgdGhlIGFjdGlvbiAnIiArIG5hbWUgKyAiJy4gSWYgeW91IGRpZCBoYW5kbGUgdGhlIGFjdGlvbiwgdGhpcyBlcnJvciBjYW4gYmUgY2F1c2VkIGJ5IHJldHVybmluZyB0cnVlIGZyb20gYW4gYWN0aW9uIGhhbmRsZXIgaW4gYSBjb250cm9sbGVyLCBjYXVzaW5nIHRoZSBhY3Rpb24gdG8gYnViYmxlLiIpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gY2FsY3VsYXRlUG9zdFRyYW5zaXRpb25TdGF0ZShlbWJlclJvdXRlciwgbGVhZlJvdXRlTmFtZSwgY29udGV4dHMpIHsKICAgIHZhciBzdGF0ZSA9IGVtYmVyUm91dGVyLl9yb3V0ZXJNaWNyb2xpYi5hcHBseUludGVudChsZWFmUm91dGVOYW1lLCBjb250ZXh0cyk7CgogICAgdmFyIHJvdXRlSW5mb3MgPSBzdGF0ZS5yb3V0ZUluZm9zLAogICAgICAgIHBhcmFtcyA9IHN0YXRlLnBhcmFtczsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvdXRlSW5mb3MubGVuZ3RoOyArK2kpIHsKICAgICAgdmFyIHJvdXRlSW5mbyA9IHJvdXRlSW5mb3NbaV07IC8vIElmIHRoZSByb3V0ZUluZm8gaXMgbm90IHJlc29sdmVkLCB3ZSBzZXJpYWxpemUgdGhlIGNvbnRleHQgaW50byBwYXJhbXMKCiAgICAgIGlmICghcm91dGVJbmZvLmlzUmVzb2x2ZWQpIHsKICAgICAgICBwYXJhbXNbcm91dGVJbmZvLm5hbWVdID0gcm91dGVJbmZvLnNlcmlhbGl6ZShyb3V0ZUluZm8uY29udGV4dCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcGFyYW1zW3JvdXRlSW5mby5uYW1lXSA9IHJvdXRlSW5mby5wYXJhbXM7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gc3RhdGU7CiAgfQoKICBmdW5jdGlvbiB1cGRhdGVQYXRocyhyb3V0ZXIpIHsKICAgIHZhciBpbmZvcyA9IHJvdXRlci5fcm91dGVyTWljcm9saWIuY3VycmVudFJvdXRlSW5mb3M7CgogICAgaWYgKGluZm9zLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm47CiAgICB9CgogICAgdmFyIHBhdGggPSBFbWJlclJvdXRlci5fcm91dGVQYXRoKGluZm9zKTsKCiAgICB2YXIgY3VycmVudFJvdXRlTmFtZSA9IGluZm9zW2luZm9zLmxlbmd0aCAtIDFdLm5hbWU7CiAgICB2YXIgY3VycmVudFVSTCA9IHJvdXRlci5nZXQoJ2xvY2F0aW9uJykuZ2V0VVJMKCk7CiAgICAoMCwgX21ldGFsLnNldCkocm91dGVyLCAnY3VycmVudFBhdGgnLCBwYXRoKTsKICAgICgwLCBfbWV0YWwuc2V0KShyb3V0ZXIsICdjdXJyZW50Um91dGVOYW1lJywgY3VycmVudFJvdXRlTmFtZSk7CiAgICAoMCwgX21ldGFsLnNldCkocm91dGVyLCAnY3VycmVudFVSTCcsIGN1cnJlbnRVUkwpOwogICAgdmFyIGFwcENvbnRyb2xsZXIgPSAoMCwgX293bmVyLmdldE93bmVyKShyb3V0ZXIpLmxvb2t1cCgnY29udHJvbGxlcjphcHBsaWNhdGlvbicpOwoKICAgIGlmICghYXBwQ29udHJvbGxlcikgewogICAgICAvLyBhcHBDb250cm9sbGVyIG1pZ2h0IG5vdCBleGlzdCB3aGVuIHRvcC1sZXZlbCBsb2FkaW5nL2Vycm9yCiAgICAgIC8vIHN1YnN0YXRlcyBoYXZlIGJlZW4gZW50ZXJlZCBzaW5jZSBBcHBsaWNhdGlvblJvdXRlIGhhc24ndAogICAgICAvLyBhY3R1YWxseSBiZWVuIGVudGVyZWQgYXQgdGhhdCBwb2ludC4KICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmIChfZGVwcmVjYXRlZEZlYXR1cmVzLkFQUF9DVFJMX1JPVVRFUl9QUk9QUykgewogICAgICBpZiAoISgnY3VycmVudFBhdGgnIGluIGFwcENvbnRyb2xsZXIpKSB7CiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGFwcENvbnRyb2xsZXIsICdjdXJyZW50UGF0aCcsIHsKICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdBY2Nlc3NpbmcgYGN1cnJlbnRQYXRoYCBvbiBgY29udHJvbGxlcjphcHBsaWNhdGlvbmAgaXMgZGVwcmVjYXRlZCwgdXNlIHRoZSBgY3VycmVudFBhdGhgIHByb3BlcnR5IG9uIGBzZXJ2aWNlOnJvdXRlcmAgaW5zdGVhZC4nLCBmYWxzZSwgewogICAgICAgICAgICAgIGlkOiAnYXBwbGljYXRpb24tY29udHJvbGxlci5yb3V0ZXItcHJvcGVydGllcycsCiAgICAgICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfYXBwbGljYXRpb24tY29udHJvbGxlci1yb3V0ZXItcHJvcGVydGllcycKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHJvdXRlciwgJ2N1cnJlbnRQYXRoJyk7CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgICgwLCBfbWV0YWwubm90aWZ5UHJvcGVydHlDaGFuZ2UpKGFwcENvbnRyb2xsZXIsICdjdXJyZW50UGF0aCcpOwoKICAgICAgaWYgKCEoJ2N1cnJlbnRSb3V0ZU5hbWUnIGluIGFwcENvbnRyb2xsZXIpKSB7CiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGFwcENvbnRyb2xsZXIsICdjdXJyZW50Um91dGVOYW1lJywgewogICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoJ0FjY2Vzc2luZyBgY3VycmVudFJvdXRlTmFtZWAgb24gYGNvbnRyb2xsZXI6YXBwbGljYXRpb25gIGlzIGRlcHJlY2F0ZWQsIHVzZSB0aGUgYGN1cnJlbnRSb3V0ZU5hbWVgIHByb3BlcnR5IG9uIGBzZXJ2aWNlOnJvdXRlcmAgaW5zdGVhZC4nLCBmYWxzZSwgewogICAgICAgICAgICAgIGlkOiAnYXBwbGljYXRpb24tY29udHJvbGxlci5yb3V0ZXItcHJvcGVydGllcycsCiAgICAgICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfYXBwbGljYXRpb24tY29udHJvbGxlci1yb3V0ZXItcHJvcGVydGllcycKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHJvdXRlciwgJ2N1cnJlbnRSb3V0ZU5hbWUnKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQoKICAgICAgKDAsIF9tZXRhbC5ub3RpZnlQcm9wZXJ0eUNoYW5nZSkoYXBwQ29udHJvbGxlciwgJ2N1cnJlbnRSb3V0ZU5hbWUnKTsKICAgIH0KICB9CgogIEVtYmVyUm91dGVyLnJlb3BlbkNsYXNzKHsKICAgIC8qKgogICAgICBUaGUgYFJvdXRlci5tYXBgIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gZGVmaW5lIG1hcHBpbmdzIGZyb20gVVJMcyB0byByb3V0ZXMKICAgICAgaW4geW91ciBhcHBsaWNhdGlvbi4gVGhlc2UgbWFwcGluZ3MgYXJlIGRlZmluZWQgd2l0aGluIHRoZQogICAgICBzdXBwbGllZCBjYWxsYmFjayBmdW5jdGlvbiB1c2luZyBgdGhpcy5yb3V0ZWAuCiAgICAgICAgIFRoZSBmaXJzdCBwYXJhbWV0ZXIgaXMgdGhlIG5hbWUgb2YgdGhlIHJvdXRlIHdoaWNoIGlzIHVzZWQgYnkgZGVmYXVsdCBhcyB0aGUKICAgICAgcGF0aCBuYW1lIGFzIHdlbGwuCiAgICAgICAgIFRoZSBzZWNvbmQgcGFyYW1ldGVyIGlzIHRoZSBvcHRpb25hbCBvcHRpb25zIGhhc2guIEF2YWlsYWJsZSBvcHRpb25zIGFyZToKICAgICAgICAgICAqIGBwYXRoYDogYWxsb3dzIHlvdSB0byBwcm92aWRlIHlvdXIgb3duIHBhdGggYXMgd2VsbCBhcyBtYXJrIGR5bmFtaWMKICAgICAgICAgIHNlZ21lbnRzLgogICAgICAgICogYHJlc2V0TmFtZXNwYWNlYDogZmFsc2UgYnkgZGVmYXVsdDsgd2hlbiBuZXN0aW5nIHJvdXRlcywgZW1iZXIgd2lsbAogICAgICAgICAgY29tYmluZSB0aGUgcm91dGUgbmFtZXMgdG8gZm9ybSB0aGUgZnVsbHktcXVhbGlmaWVkIHJvdXRlIG5hbWUsIHdoaWNoIGlzCiAgICAgICAgICB1c2VkIHdpdGggYHt7bGluay10b319YCBvciBtYW51YWxseSB0cmFuc2l0aW9uaW5nIHRvIHJvdXRlcy4gU2V0dGluZwogICAgICAgICAgYHJlc2V0TmFtZXNwYWNlOiB0cnVlYCB3aWxsIGNhdXNlIHRoZSByb3V0ZSBub3QgdG8gaW5oZXJpdCBmcm9tIGl0cwogICAgICAgICAgcGFyZW50IHJvdXRlJ3MgbmFtZXMuIFRoaXMgaXMgaGFuZHkgZm9yIHByZXZlbnRpbmcgZXh0cmVtZWx5IGxvbmcgcm91dGUgbmFtZXMuCiAgICAgICAgICBLZWVwIGluIG1pbmQgdGhhdCB0aGUgYWN0dWFsIFVSTCBwYXRoIGJlaGF2aW9yIGlzIHN0aWxsIHJldGFpbmVkLgogICAgICAgICBUaGUgdGhpcmQgcGFyYW1ldGVyIGlzIGEgZnVuY3Rpb24sIHdoaWNoIGNhbiBiZSB1c2VkIHRvIG5lc3Qgcm91dGVzLgogICAgICBOZXN0ZWQgcm91dGVzLCBieSBkZWZhdWx0LCB3aWxsIGhhdmUgdGhlIHBhcmVudCByb3V0ZSB0cmVlJ3Mgcm91dGUgbmFtZSBhbmQKICAgICAgcGF0aCBwcmVwZW5kZWQgdG8gaXQncyBvd24uCiAgICAgICAgIGBgYGFwcC9yb3V0ZXIuanMKICAgICAgUm91dGVyLm1hcChmdW5jdGlvbigpewogICAgICAgIHRoaXMucm91dGUoJ3Bvc3QnLCB7IHBhdGg6ICcvcG9zdC86cG9zdF9pZCcgfSwgZnVuY3Rpb24oKSB7CiAgICAgICAgICB0aGlzLnJvdXRlKCdlZGl0Jyk7CiAgICAgICAgICB0aGlzLnJvdXRlKCdjb21tZW50cycsIHsgcmVzZXROYW1lc3BhY2U6IHRydWUgfSwgZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHRoaXMucm91dGUoJ25ldycpOwogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICAgQG1ldGhvZCBtYXAKICAgICAgQHBhcmFtIGNhbGxiYWNrCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBtYXA6IGZ1bmN0aW9uIG1hcChjYWxsYmFjaykgewogICAgICBpZiAoIXRoaXMuZHNsQ2FsbGJhY2tzKSB7CiAgICAgICAgdGhpcy5kc2xDYWxsYmFja3MgPSBbXTsKICAgICAgICB0aGlzLnJlb3BlbkNsYXNzKHsKICAgICAgICAgIGRzbENhbGxiYWNrczogdGhpcy5kc2xDYWxsYmFja3MKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgdGhpcy5kc2xDYWxsYmFja3MucHVzaChjYWxsYmFjayk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKICAgIF9yb3V0ZVBhdGg6IGZ1bmN0aW9uIF9yb3V0ZVBhdGgocm91dGVJbmZvcykgewogICAgICB2YXIgcGF0aCA9IFtdOyAvLyBXZSBoYXZlIHRvIGhhbmRsZSBjb2FsZXNjaW5nIHJlc291cmNlIG5hbWVzIHRoYXQKICAgICAgLy8gYXJlIHByZWZpeGVkIHdpdGggdGhlaXIgcGFyZW50J3MgbmFtZXMsIGUuZy4KICAgICAgLy8gWydmb28nLCAnZm9vLmJhci5iYXonXSA9PiAnZm9vLmJhci5iYXonLCBub3QgJ2Zvby5mb28uYmFyLmJheicKCiAgICAgIGZ1bmN0aW9uIGludGVyc2VjdGlvbk1hdGNoZXMoYTEsIGEyKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhMS5sZW5ndGg7ICsraSkgewogICAgICAgICAgaWYgKGExW2ldICE9PSBhMltpXSkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgdmFyIG5hbWUsIG5hbWVQYXJ0cywgb2xkTmFtZVBhcnRzOwoKICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCByb3V0ZUluZm9zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgbmFtZSA9IHJvdXRlSW5mb3NbaV0ubmFtZTsKICAgICAgICBuYW1lUGFydHMgPSBuYW1lLnNwbGl0KCcuJyk7CiAgICAgICAgb2xkTmFtZVBhcnRzID0gc2xpY2UuY2FsbChwYXRoKTsKCiAgICAgICAgd2hpbGUgKG9sZE5hbWVQYXJ0cy5sZW5ndGgpIHsKICAgICAgICAgIGlmIChpbnRlcnNlY3Rpb25NYXRjaGVzKG9sZE5hbWVQYXJ0cywgbmFtZVBhcnRzKSkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KCiAgICAgICAgICBvbGROYW1lUGFydHMuc2hpZnQoKTsKICAgICAgICB9CgogICAgICAgIHBhdGgucHVzaC5hcHBseShwYXRoLCBuYW1lUGFydHMuc2xpY2Uob2xkTmFtZVBhcnRzLmxlbmd0aCkpOwogICAgICB9CgogICAgICByZXR1cm4gcGF0aC5qb2luKCcuJyk7CiAgICB9CiAgfSk7CgogIGZ1bmN0aW9uIGRpZEJlZ2luVHJhbnNpdGlvbih0cmFuc2l0aW9uLCByb3V0ZXIpIHsKICAgIHZhciByb3V0ZXJTdGF0ZSA9IG5ldyBfcm91dGVyX3N0YXRlLmRlZmF1bHQocm91dGVyLCByb3V0ZXIuX3JvdXRlck1pY3JvbGliLCB0cmFuc2l0aW9uW19yb3V0ZXJfanMuU1RBVEVfU1lNQk9MXSk7CgogICAgaWYgKCFyb3V0ZXIuY3VycmVudFN0YXRlKSB7CiAgICAgIHJvdXRlci5zZXQoJ2N1cnJlbnRTdGF0ZScsIHJvdXRlclN0YXRlKTsKICAgIH0KCiAgICByb3V0ZXIuc2V0KCd0YXJnZXRTdGF0ZScsIHJvdXRlclN0YXRlKTsKICAgIHRyYW5zaXRpb24ucHJvbWlzZSA9IHRyYW5zaXRpb24uY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7CiAgICAgIGlmIChyb3V0ZXIuX2lzRXJyb3JIYW5kbGVkKGVycm9yKSkgewogICAgICAgIHJvdXRlci5fY2xlYXJIYW5kbGVkRXJyb3IoZXJyb3IpOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IGVycm9yOwogICAgICB9CiAgICB9LCAnVHJhbnNpdGlvbiBFcnJvcicpOwogIH0KCiAgZnVuY3Rpb24gZm9yRWFjaFF1ZXJ5UGFyYW0ocm91dGVyLCByb3V0ZUluZm9zLCBxdWVyeVBhcmFtcywgY2FsbGJhY2spIHsKICAgIHZhciBxcENhY2hlID0gcm91dGVyLl9xdWVyeVBhcmFtc0Zvcihyb3V0ZUluZm9zKTsKCiAgICBmb3IgKHZhciBrZXkgaW4gcXVlcnlQYXJhbXMpIHsKICAgICAgaWYgKCFxdWVyeVBhcmFtcy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIHZhciB2YWx1ZSA9IHF1ZXJ5UGFyYW1zW2tleV07CiAgICAgIHZhciBxcCA9IHFwQ2FjaGUubWFwW2tleV07CiAgICAgIGNhbGxiYWNrKGtleSwgdmFsdWUsIHFwKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGZpbmRMaXZlUm91dGUobGl2ZVJvdXRlcywgbmFtZSkgewogICAgaWYgKCFsaXZlUm91dGVzKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB2YXIgc3RhY2sgPSBbbGl2ZVJvdXRlc107CgogICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgdmFyIHRlc3QgPSBzdGFjay5zaGlmdCgpOwoKICAgICAgaWYgKHRlc3QucmVuZGVyLm5hbWUgPT09IG5hbWUpIHsKICAgICAgICByZXR1cm4gdGVzdDsKICAgICAgfQoKICAgICAgdmFyIG91dGxldHMgPSB0ZXN0Lm91dGxldHM7CgogICAgICBmb3IgKHZhciBvdXRsZXROYW1lIGluIG91dGxldHMpIHsKICAgICAgICBzdGFjay5wdXNoKG91dGxldHNbb3V0bGV0TmFtZV0pOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuOwogIH0KCiAgZnVuY3Rpb24gYXBwZW5kTGl2ZVJvdXRlKGxpdmVSb3V0ZXMsIGRlZmF1bHRQYXJlbnRTdGF0ZSwgcmVuZGVyT3B0aW9ucykgewogICAgdmFyIHRhcmdldDsKICAgIHZhciBteVN0YXRlID0gewogICAgICByZW5kZXI6IHJlbmRlck9wdGlvbnMsCiAgICAgIG91dGxldHM6IE9iamVjdC5jcmVhdGUobnVsbCksCiAgICAgIHdhc1VzZWQ6IGZhbHNlCiAgICB9OwoKICAgIGlmIChyZW5kZXJPcHRpb25zLmludG8pIHsKICAgICAgdGFyZ2V0ID0gZmluZExpdmVSb3V0ZShsaXZlUm91dGVzLCByZW5kZXJPcHRpb25zLmludG8pOwogICAgfSBlbHNlIHsKICAgICAgdGFyZ2V0ID0gZGVmYXVsdFBhcmVudFN0YXRlOwogICAgfQoKICAgIGlmICh0YXJnZXQpIHsKICAgICAgKDAsIF9tZXRhbC5zZXQpKHRhcmdldC5vdXRsZXRzLCByZW5kZXJPcHRpb25zLm91dGxldCwgbXlTdGF0ZSk7CiAgICB9IGVsc2UgewogICAgICBsaXZlUm91dGVzID0gbXlTdGF0ZTsKICAgIH0KCiAgICByZXR1cm4gewogICAgICBsaXZlUm91dGVzOiBsaXZlUm91dGVzLAogICAgICBvd25TdGF0ZTogbXlTdGF0ZQogICAgfTsKICB9CgogIGZ1bmN0aW9uIHJlcHJlc2VudEVtcHR5Um91dGUobGl2ZVJvdXRlcywgZGVmYXVsdFBhcmVudFN0YXRlLCByb3V0ZSkgewogICAgLy8gdGhlIHJvdXRlIGRpZG4ndCByZW5kZXIgYW55dGhpbmcKICAgIHZhciBhbHJlYWR5QXBwZW5kZWQgPSBmaW5kTGl2ZVJvdXRlKGxpdmVSb3V0ZXMsIHJvdXRlLnJvdXRlTmFtZSk7CgogICAgaWYgKGFscmVhZHlBcHBlbmRlZCkgewogICAgICAvLyBCdXQgc29tZSBvdGhlciByb3V0ZSBoYXMgYWxyZWFkeSByZW5kZXJlZCBvdXIgZGVmYXVsdAogICAgICAvLyB0ZW1wbGF0ZSwgc28gdGhhdCBiZWNvbWVzIHRoZSBkZWZhdWx0IHRhcmdldCBmb3IgYW55CiAgICAgIC8vIGNoaWxkcmVuIHdlIG1heSBoYXZlLgogICAgICByZXR1cm4gYWxyZWFkeUFwcGVuZGVkOwogICAgfSBlbHNlIHsKICAgICAgLy8gQ3JlYXRlIGFuIGVudHJ5IHRvIHJlcHJlc2VudCBvdXIgZGVmYXVsdCB0ZW1wbGF0ZSBuYW1lLAogICAgICAvLyBqdXN0IHNvIG90aGVyIHJvdXRlcyBjYW4gdGFyZ2V0IGl0IGFuZCBpbmhlcml0IGl0cyBwbGFjZQogICAgICAvLyBpbiB0aGUgb3V0bGV0IGhpZXJhcmNoeS4KICAgICAgZGVmYXVsdFBhcmVudFN0YXRlLm91dGxldHMubWFpbiA9IHsKICAgICAgICByZW5kZXI6IHsKICAgICAgICAgIG5hbWU6IHJvdXRlLnJvdXRlTmFtZSwKICAgICAgICAgIG91dGxldDogJ21haW4nCiAgICAgICAgfSwKICAgICAgICBvdXRsZXRzOiB7fQogICAgICB9OwogICAgICByZXR1cm4gZGVmYXVsdFBhcmVudFN0YXRlOwogICAgfQogIH0KCiAgRW1iZXJSb3V0ZXIucmVvcGVuKF9ydW50aW1lLkV2ZW50ZWQsIHsKICAgIC8qKgogICAgICBIYW5kbGVzIHVwZGF0aW5nIHRoZSBwYXRocyBhbmQgbm90aWZ5aW5nIGFueSBsaXN0ZW5lcnMgb2YgdGhlIFVSTAogICAgICBjaGFuZ2UuCiAgICAgICAgIFRyaWdnZXJzIHRoZSByb3V0ZXIgbGV2ZWwgYGRpZFRyYW5zaXRpb25gIGhvb2suCiAgICAgICAgIEZvciBleGFtcGxlLCB0byBub3RpZnkgZ29vZ2xlIGFuYWx5dGljcyB3aGVuIHRoZSByb3V0ZSBjaGFuZ2VzLAogICAgICB5b3UgY291bGQgdXNlIHRoaXMgaG9vay4gIChOb3RlOiByZXF1aXJlcyBhbHNvIGluY2x1ZGluZyBHQSBzY3JpcHRzLCBldGMuKQogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBjb25maWcgZnJvbSAnLi9jb25maWcvZW52aXJvbm1lbnQnOwogICAgICBpbXBvcnQgRW1iZXJSb3V0ZXIgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGVyJzsKICAgICAgaW1wb3J0IHsgaW5qZWN0IGFzIHNlcnZpY2UgfSBmcm9tICdAZW1iZXIvc2VydmljZSc7CiAgICAgICAgIGxldCBSb3V0ZXIgPSBFbWJlclJvdXRlci5leHRlbmQoewogICAgICAgIGxvY2F0aW9uOiBjb25maWcubG9jYXRpb25UeXBlLAogICAgICAgICAgIHJvdXRlcjogc2VydmljZSgpLAogICAgICAgICAgIGRpZFRyYW5zaXRpb246IGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICAgICAgIGdhKCdzZW5kJywgJ3BhZ2V2aWV3JywgewogICAgICAgICAgICBwYWdlOiB0aGlzLnJvdXRlci5jdXJyZW50VVJMLAogICAgICAgICAgICB0aXRsZTogdGhpcy5yb3V0ZXIuY3VycmVudFJvdXRlTmFtZSwKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIGRpZFRyYW5zaXRpb24KICAgICAgQHB1YmxpYwogICAgICBAc2luY2UgMS4yLjAKICAgICovCiAgICBkaWRUcmFuc2l0aW9uOiBkZWZhdWx0RGlkVHJhbnNpdGlvbiwKCiAgICAvKioKICAgICAgSGFuZGxlcyBub3RpZnlpbmcgYW55IGxpc3RlbmVycyBvZiBhbiBpbXBlbmRpbmcgVVJMCiAgICAgIGNoYW5nZS4KICAgICAgICAgVHJpZ2dlcnMgdGhlIHJvdXRlciBsZXZlbCBgd2lsbFRyYW5zaXRpb25gIGhvb2suCiAgICAgICAgIEBtZXRob2Qgd2lsbFRyYW5zaXRpb24KICAgICAgQHB1YmxpYwogICAgICBAc2luY2UgMS4xMS4wCiAgICAqLwogICAgd2lsbFRyYW5zaXRpb246IGRlZmF1bHRXaWxsVHJhbnNpdGlvbiwKCiAgICAvKioKICAgICBSZXByZXNlbnRzIHRoZSBVUkwgb2YgdGhlIHJvb3Qgb2YgdGhlIGFwcGxpY2F0aW9uLCBvZnRlbiAnLycuIFRoaXMgcHJlZml4IGlzCiAgICAgYXNzdW1lZCBvbiBhbGwgcm91dGVzIGRlZmluZWQgb24gdGhpcyByb3V0ZXIuCiAgICAgICAgQHByb3BlcnR5IHJvb3RVUkwKICAgICBAZGVmYXVsdCAnLycKICAgICBAcHVibGljCiAgICAqLwogICAgcm9vdFVSTDogJy8nLAoKICAgIC8qKgogICAgIFRoZSBgbG9jYXRpb25gIHByb3BlcnR5IGRldGVybWluZXMgdGhlIHR5cGUgb2YgVVJMJ3MgdGhhdCB5b3VyCiAgICAgYXBwbGljYXRpb24gd2lsbCB1c2UuCiAgICAgICAgVGhlIGZvbGxvd2luZyBsb2NhdGlvbiB0eXBlcyBhcmUgY3VycmVudGx5IGF2YWlsYWJsZToKICAgICAgICAqIGBoaXN0b3J5YCAtIHVzZSB0aGUgYnJvd3NlcidzIGhpc3RvcnkgQVBJIHRvIG1ha2UgdGhlIFVSTHMgbG9vayBqdXN0IGxpa2UgYW55IHN0YW5kYXJkIFVSTAogICAgICogYGhhc2hgIC0gdXNlIGAjYCB0byBzZXBhcmF0ZSB0aGUgc2VydmVyIHBhcnQgb2YgdGhlIFVSTCBmcm9tIHRoZSBFbWJlciBwYXJ0OiBgL2Jsb2cvIy9wb3N0cy9uZXdgCiAgICAgKiBgbm9uZWAgLSBkbyBub3Qgc3RvcmUgdGhlIEVtYmVyIFVSTCBpbiB0aGUgYWN0dWFsIGJyb3dzZXIgVVJMIChtYWlubHkgdXNlZCBmb3IgdGVzdGluZykKICAgICAqIGBhdXRvYCAtIHVzZSB0aGUgYmVzdCBvcHRpb24gYmFzZWQgb24gYnJvd3NlciBjYXBhYmlsaXRpZXM6IGBoaXN0b3J5YCBpZiBwb3NzaWJsZSwgdGhlbiBgaGFzaGAgaWYgcG9zc2libGUsIG90aGVyd2lzZSBgbm9uZWAKICAgICAgICBUaGlzIHZhbHVlIGlzIGRlZmF1bHRlZCB0byBgYXV0b2AgYnkgdGhlIGBsb2NhdGlvblR5cGVgIHNldHRpbmcgb2YgYC9jb25maWcvZW52aXJvbm1lbnQuanNgCiAgICAgICAgQHByb3BlcnR5IGxvY2F0aW9uCiAgICAgQGRlZmF1bHQgJ2hhc2gnCiAgICAgQHNlZSB7TG9jYXRpb259CiAgICAgQHB1YmxpYwogICAgKi8KICAgIGxvY2F0aW9uOiAnaGFzaCcsCgogICAgLyoqCiAgICAgUmVwcmVzZW50cyB0aGUgY3VycmVudCBVUkwuCiAgICAgICAgQHByb3BlcnR5IHVybAogICAgIEB0eXBlIHtTdHJpbmd9CiAgICAgQHByaXZhdGUKICAgICovCiAgICB1cmw6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGxvY2F0aW9uID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdsb2NhdGlvbicpOwoKICAgICAgaWYgKHR5cGVvZiBsb2NhdGlvbiA9PT0gJ3N0cmluZycpIHsKICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgICB9CgogICAgICByZXR1cm4gbG9jYXRpb24uZ2V0VVJMKCk7CiAgICB9KQogIH0pOwoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5ST1VURVJfRVZFTlRTKSB7CiAgICBFbWJlclJvdXRlci5yZW9wZW4oX3JvdXRlLlJPVVRFUl9FVkVOVF9ERVBSRUNBVElPTlMpOwogIH0KCiAgdmFyIF9kZWZhdWx0ID0gRW1iZXJSb3V0ZXI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nL2xpYi9zeXN0ZW0vcm91dGVyX3N0YXRlIiwgWyJleHBvcnRzIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvdXRpbHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfcG9seWZpbGxzLCBfdXRpbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIHZhciBSb3V0ZXJTdGF0ZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJvdXRlclN0YXRlKGVtYmVyUm91dGVyLCByb3V0ZXIsIHJvdXRlckpzU3RhdGUpIHsKICAgICAgdGhpcy5lbWJlclJvdXRlciA9IGVtYmVyUm91dGVyOwogICAgICB0aGlzLnJvdXRlciA9IHJvdXRlcjsKICAgICAgdGhpcy5yb3V0ZXJKc1N0YXRlID0gcm91dGVySnNTdGF0ZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gUm91dGVyU3RhdGUucHJvdG90eXBlOwoKICAgIF9wcm90by5pc0FjdGl2ZUludGVudCA9IGZ1bmN0aW9uIGlzQWN0aXZlSW50ZW50KHJvdXRlTmFtZSwgbW9kZWxzLCBxdWVyeVBhcmFtcywgcXVlcnlQYXJhbXNNdXN0TWF0Y2gpIHsKICAgICAgdmFyIHN0YXRlID0gdGhpcy5yb3V0ZXJKc1N0YXRlOwoKICAgICAgaWYgKCF0aGlzLnJvdXRlci5pc0FjdGl2ZUludGVudChyb3V0ZU5hbWUsIG1vZGVscywgdW5kZWZpbmVkLCBzdGF0ZSkpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIGlmIChxdWVyeVBhcmFtc011c3RNYXRjaCAmJiBPYmplY3Qua2V5cyhxdWVyeVBhcmFtcykubGVuZ3RoID4gMCkgewogICAgICAgIHZhciB2aXNpYmxlUXVlcnlQYXJhbXMgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBxdWVyeVBhcmFtcyk7CgogICAgICAgIHRoaXMuZW1iZXJSb3V0ZXIuX3ByZXBhcmVRdWVyeVBhcmFtcyhyb3V0ZU5hbWUsIG1vZGVscywgdmlzaWJsZVF1ZXJ5UGFyYW1zKTsKCiAgICAgICAgcmV0dXJuICgwLCBfdXRpbHMuc2hhbGxvd0VxdWFsKSh2aXNpYmxlUXVlcnlQYXJhbXMsIHN0YXRlLnF1ZXJ5UGFyYW1zKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRydWU7CiAgICB9OwoKICAgIHJldHVybiBSb3V0ZXJTdGF0ZTsKICB9KCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBSb3V0ZXJTdGF0ZTsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZy9saWIvc3lzdGVtL3RyYW5zaXRpb24iLCBbXSwgZnVuY3Rpb24gKCkgewogICJ1c2Ugc3RyaWN0IjsKICAvKioKICAgIEEgVHJhbnNpdGlvbiBpcyBhIHRoZW5uYWJsZSAoYSBwcm9taXNlLWxpa2Ugb2JqZWN0KSB0aGF0IHJlcHJlc2VudHMKICAgIGFuIGF0dGVtcHQgdG8gdHJhbnNpdGlvbiB0byBhbm90aGVyIHJvdXRlLiBJdCBjYW4gYmUgYWJvcnRlZCwgZWl0aGVyCiAgICBleHBsaWNpdGx5IHZpYSBgYWJvcnRgIG9yIGJ5IGF0dGVtcHRpbmcgYW5vdGhlciB0cmFuc2l0aW9uIHdoaWxlIGEKICAgIHByZXZpb3VzIG9uZSBpcyBzdGlsbCB1bmRlcndheS4gQW4gYWJvcnRlZCB0cmFuc2l0aW9uIGNhbiBhbHNvCiAgICBiZSBgcmV0cnkoKWBkIGxhdGVyLgogIAogICAgQGNsYXNzIFRyYW5zaXRpb24KICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFRoZSBUcmFuc2l0aW9uJ3MgaW50ZXJuYWwgcHJvbWlzZS4gQ2FsbGluZyBgLnRoZW5gIG9uIHRoaXMgcHJvcGVydHkKICAgIGlzIHRoYXQgc2FtZSBhcyBjYWxsaW5nIGAudGhlbmAgb24gdGhlIFRyYW5zaXRpb24gb2JqZWN0IGl0c2VsZiwgYnV0CiAgICB0aGlzIHByb3BlcnR5IGlzIGV4cG9zZWQgZm9yIHdoZW4geW91IHdhbnQgdG8gcGFzcyBhcm91bmQgYQogICAgVHJhbnNpdGlvbidzIHByb21pc2UsIGJ1dCBub3QgdGhlIFRyYW5zaXRpb24gb2JqZWN0IGl0c2VsZiwgc2luY2UKICAgIFRyYW5zaXRpb24gb2JqZWN0IGNhbiBiZSBleHRlcm5hbGx5IGBhYm9ydGBlZCwgd2hpbGUgdGhlIHByb21pc2UKICAgIGNhbm5vdC4KICAKICAgIEBwcm9wZXJ0eSBwcm9taXNlCiAgICBAdHlwZSB7T2JqZWN0fQogICAgQHB1YmxpYwogICAgKi8KCiAgLyoqCiAgICBDdXN0b20gc3RhdGUgY2FuIGJlIHN0b3JlZCBvbiBhIFRyYW5zaXRpb24ncyBgZGF0YWAgb2JqZWN0LgogICAgVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBkZWNvcmF0aW5nIGEgVHJhbnNpdGlvbiB3aXRoaW4gYW4gZWFybGllcgogICAgaG9vayBhbmQgc2hhcmVkIHdpdGggYSBsYXRlciBob29rLiBQcm9wZXJ0aWVzIHNldCBvbiBgZGF0YWAgd2lsbAogICAgYmUgY29waWVkIHRvIG5ldyB0cmFuc2l0aW9ucyBnZW5lcmF0ZWQgYnkgY2FsbGluZyBgcmV0cnlgIG9uIHRoaXMKICAgIHRyYW5zaXRpb24uCiAgCiAgICBAcHJvcGVydHkgZGF0YQogICAgQHR5cGUge09iamVjdH0KICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIEEgc3RhbmRhcmQgcHJvbWlzZSBob29rIHRoYXQgcmVzb2x2ZXMgaWYgdGhlIHRyYW5zaXRpb24KICAgIHN1Y2NlZWRzIGFuZCByZWplY3RzIGlmIGl0IGZhaWxzL3JlZGlyZWN0cy9hYm9ydHMuCiAgCiAgICBGb3J3YXJkcyB0byB0aGUgaW50ZXJuYWwgYHByb21pc2VgIHByb3BlcnR5IHdoaWNoIHlvdSBjYW4KICAgIHVzZSBpbiBzaXR1YXRpb25zIHdoZXJlIHlvdSB3YW50IHRvIHBhc3MgYXJvdW5kIGEgdGhlbm5hYmxlLAogICAgYnV0IG5vdCB0aGUgVHJhbnNpdGlvbiBpdHNlbGYuCiAgCiAgICBAbWV0aG9kIHRoZW4KICAgIEBwYXJhbSB7RnVuY3Rpb259IG9uRnVsZmlsbGVkCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGVkCiAgICBAcGFyYW0ge1N0cmluZ30gbGFiZWwgb3B0aW9uYWwgc3RyaW5nIGZvciBsYWJlbGluZyB0aGUgcHJvbWlzZS4KICAgIFVzZWZ1bCBmb3IgdG9vbGluZy4KICAgIEByZXR1cm4ge1Byb21pc2V9CiAgICBAcHVibGljCiAgKi8KCiAgLyoqCiAgCiAgICBGb3J3YXJkcyB0byB0aGUgaW50ZXJuYWwgYHByb21pc2VgIHByb3BlcnR5IHdoaWNoIHlvdSBjYW4KICAgIHVzZSBpbiBzaXR1YXRpb25zIHdoZXJlIHlvdSB3YW50IHRvIHBhc3MgYXJvdW5kIGEgdGhlbm5hYmxlLAogICAgYnV0IG5vdCB0aGUgVHJhbnNpdGlvbiBpdHNlbGYuCiAgCiAgICBAbWV0aG9kIGNhdGNoCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGlvbgogICAgQHBhcmFtIHtTdHJpbmd9IGxhYmVsIG9wdGlvbmFsIHN0cmluZyBmb3IgbGFiZWxpbmcgdGhlIHByb21pc2UuCiAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICBAcmV0dXJuIHtQcm9taXNlfQogICAgQHB1YmxpYwogICovCgogIC8qKgogIAogICAgRm9yd2FyZHMgdG8gdGhlIGludGVybmFsIGBwcm9taXNlYCBwcm9wZXJ0eSB3aGljaCB5b3UgY2FuCiAgICB1c2UgaW4gc2l0dWF0aW9ucyB3aGVyZSB5b3Ugd2FudCB0byBwYXNzIGFyb3VuZCBhIHRoZW5uYWJsZSwKICAgIGJ1dCBub3QgdGhlIFRyYW5zaXRpb24gaXRzZWxmLgogIAogICAgQG1ldGhvZCBmaW5hbGx5CiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgQHBhcmFtIHtTdHJpbmd9IGxhYmVsIG9wdGlvbmFsIHN0cmluZyBmb3IgbGFiZWxpbmcgdGhlIHByb21pc2UuCiAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICBAcmV0dXJuIHtQcm9taXNlfQogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgQWJvcnRzIHRoZSBUcmFuc2l0aW9uLiBOb3RlIHlvdSBjYW4gYWxzbyBpbXBsaWNpdGx5IGFib3J0IGEgdHJhbnNpdGlvbgogICAgYnkgaW5pdGlhdGluZyBhbm90aGVyIHRyYW5zaXRpb24gd2hpbGUgYSBwcmV2aW91cyBvbmUgaXMgdW5kZXJ3YXkuCiAgCiAgICBAbWV0aG9kIGFib3J0CiAgICBAcmV0dXJuIHtUcmFuc2l0aW9ufSB0aGlzIHRyYW5zaXRpb24KICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAKICAgIFJldHJpZXMgYSBwcmV2aW91c2x5LWFib3J0ZWQgdHJhbnNpdGlvbiAobWFraW5nIHN1cmUgdG8gYWJvcnQgdGhlCiAgICB0cmFuc2l0aW9uIGlmIGl0J3Mgc3RpbGwgYWN0aXZlKS4gUmV0dXJucyBhIG5ldyB0cmFuc2l0aW9uIHRoYXQKICAgIHJlcHJlc2VudHMgdGhlIG5ldyBhdHRlbXB0IHRvIHRyYW5zaXRpb24uCiAgCiAgICBAbWV0aG9kIHJldHJ5CiAgICBAcmV0dXJuIHtUcmFuc2l0aW9ufSBuZXcgdHJhbnNpdGlvbgogICAgQHB1YmxpYwogICAgKi8KCiAgLyoqCiAgCiAgICBTZXRzIHRoZSBVUkwtY2hhbmdpbmcgbWV0aG9kIHRvIGJlIGVtcGxveWVkIGF0IHRoZSBlbmQgb2YgYQogICAgc3VjY2Vzc2Z1bCB0cmFuc2l0aW9uLiBCeSBkZWZhdWx0LCBhIG5ldyBUcmFuc2l0aW9uIHdpbGwganVzdAogICAgdXNlIGB1cGRhdGVVUkxgLCBidXQgcGFzc2luZyAncmVwbGFjZScgdG8gdGhpcyBtZXRob2Qgd2lsbAogICAgY2F1c2UgdGhlIFVSTCB0byB1cGRhdGUgdXNpbmcgJ3JlcGxhY2VXaXRoJyBpbnN0ZWFkLiBPbWl0dGluZwogICAgYSBwYXJhbWV0ZXIgd2lsbCBkaXNhYmxlIHRoZSBVUkwgY2hhbmdlLCBhbGxvd2luZyBmb3IgdHJhbnNpdGlvbnMKICAgIHRoYXQgZG9uJ3QgdXBkYXRlIHRoZSBVUkwgYXQgY29tcGxldGlvbiAodGhpcyBpcyBhbHNvIHVzZWQgZm9yCiAgICBoYW5kbGVVUkwsIHNpbmNlIHRoZSBVUkwgaGFzIGFscmVhZHkgY2hhbmdlZCBiZWZvcmUgdGhlCiAgICB0cmFuc2l0aW9uIHRvb2sgcGxhY2UpLgogIAogICAgQG1ldGhvZCBtZXRob2QKICAgIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgdGhlIHR5cGUgb2YgVVJMLWNoYW5naW5nIG1ldGhvZCB0byB1c2UKICAgICAgYXQgdGhlIGVuZCBvZiBhIHRyYW5zaXRpb24uIEFjY2VwdGVkIHZhbHVlcyBhcmUgJ3JlcGxhY2UnLAogICAgICBmYWxzeSB2YWx1ZXMsIG9yIGFueSBvdGhlciBub24tZmFsc3kgdmFsdWUgKHdoaWNoIGlzCiAgICAgIGludGVycHJldGVkIGFzIGFuIHVwZGF0ZVVSTCB0cmFuc2l0aW9uKS4KICAKICAgIEByZXR1cm4ge1RyYW5zaXRpb259IHRoaXMgdHJhbnNpdGlvbgogICAgQHB1YmxpYwogICovCgogIC8qKgogIAogICAgRmlyZXMgYW4gZXZlbnQgb24gdGhlIGN1cnJlbnQgbGlzdCBvZiByZXNvbHZlZC9yZXNvbHZpbmcKICAgIGhhbmRsZXJzIHdpdGhpbiB0aGlzIHRyYW5zaXRpb24uIFVzZWZ1bCBmb3IgZmlyaW5nIGV2ZW50cwogICAgb24gcm91dGUgaGllcmFyY2hpZXMgdGhhdCBoYXZlbid0IGZ1bGx5IGJlZW4gZW50ZXJlZCB5ZXQuCiAgCiAgICBOb3RlOiBUaGlzIG1ldGhvZCBpcyBhbHNvIGFsaWFzZWQgYXMgYHNlbmRgCiAgCiAgICBAbWV0aG9kIHRyaWdnZXIKICAgIEBwYXJhbSB7Qm9vbGVhbn0gW2lnbm9yZUZhaWx1cmU9ZmFsc2VdIGEgYm9vbGVhbiBzcGVjaWZ5aW5nIHdoZXRoZXIgdW5oYW5kbGVkIGV2ZW50cyB0aHJvdyBhbiBlcnJvcgogICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGZpcmUKICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgKiBUaGlzIHByb3BlcnR5IGlzIGEgYFJvdXRlSW5mb2Agb2JqZWN0IHRoYXQgcmVwcmVzZW50cwogICAqIHdoZXJlIHRoZSByb3V0ZXIgaXMgdHJhbnNpdGlvbmluZyB0by4gSXQncyBpbXBvcnRhbnQKICAgKiB0byBub3RlIHRoYXQgYSBgUm91dGVJbmZvYCBpcyBhIGxpbmtlZCBsaXN0IGFuZCB0aGlzCiAgICogcHJvcGVydHkgcmVwcmVzZW50cyB0aGUgbGVhZm1vc3Qgcm91dGUuCiAgICogQHByb3BlcnR5IHtSb3V0ZUluZm98Um91dGVJbmZvV2l0aEF0dHJpYnV0ZXN9IHRvCiAgICogQHB1YmxpYwogICAqLwoKICAvKioKICAgKiBUaGlzIHByb3BlcnR5IGlzIGEgYFJvdXRlSW5mb2Agb2JqZWN0IHRoYXQgcmVwcmVzZW50cwogICAqIHdoZXJlIHRyYW5zaXRpb24gb3JpZ2luYXRlZCBmcm9tLiBJdCdzIGltcG9ydGFudAogICAqIHRvIG5vdGUgdGhhdCBhIGBSb3V0ZUluZm9gIGlzIGEgbGlua2VkIGxpc3QgYW5kIHRoaXMKICAgKiBwcm9wZXJ0eSByZXByZXNlbnRzIHRoZSBoZWFkIG5vZGUgb2YgdGhlIGxpc3QuCiAgICogSW4gdGhlIGNhc2Ugb2YgYW4gaW5pdGlhbCByZW5kZXIsIGBmcm9tYCB3aWxsIGJlIHNldCB0bwogICAqIGBudWxsYC4KICAgKiBAcHJvcGVydHkge1JvdXRlSW5mb1dpdGhBdHRyaWJ1dGVzfSBmcm9tCiAgICogQHB1YmxpYwogICAqLwoKICAvKioKICAgIFRyYW5zaXRpb25zIGFyZSBhYm9ydGVkIGFuZCB0aGVpciBwcm9taXNlcyByZWplY3RlZAogICAgd2hlbiByZWRpcmVjdHMgb2NjdXI7IHRoaXMgbWV0aG9kIHJldHVybnMgYSBwcm9taXNlCiAgICB0aGF0IHdpbGwgZm9sbG93IGFueSByZWRpcmVjdHMgdGhhdCBvY2N1ciBhbmQgZnVsZmlsbAogICAgd2l0aCB0aGUgdmFsdWUgZnVsZmlsbGVkIGJ5IGFueSByZWRpcmVjdGluZyB0cmFuc2l0aW9ucwogICAgdGhhdCBvY2N1ci4KICAKICAgIEBtZXRob2QgZm9sbG93UmVkaXJlY3RzCiAgICBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCBmdWxmaWxscyB3aXRoIHRoZSBzYW1lCiAgICAgIHZhbHVlIHRoYXQgdGhlIGZpbmFsIHJlZGlyZWN0aW5nIHRyYW5zaXRpb24gZnVsZmlsbHMgd2l0aAogICAgQHB1YmxpYwogICovCn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcvbGliL3V0aWxzIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci9lcnJvciIsICJAZW1iZXIvcG9seWZpbGxzIiwgInJvdXRlcl9qcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX293bmVyLCBfZXJyb3IsIF9wb2x5ZmlsbHMsIF9yb3V0ZXJfanMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmV4dHJhY3RSb3V0ZUFyZ3MgPSBleHRyYWN0Um91dGVBcmdzOwogIF9leHBvcnRzLmdldEFjdGl2ZVRhcmdldE5hbWUgPSBnZXRBY3RpdmVUYXJnZXROYW1lOwogIF9leHBvcnRzLnN0YXNoUGFyYW1OYW1lcyA9IHN0YXNoUGFyYW1OYW1lczsKICBfZXhwb3J0cy5jYWxjdWxhdGVDYWNoZUtleSA9IGNhbGN1bGF0ZUNhY2hlS2V5OwogIF9leHBvcnRzLm5vcm1hbGl6ZUNvbnRyb2xsZXJRdWVyeVBhcmFtcyA9IG5vcm1hbGl6ZUNvbnRyb2xsZXJRdWVyeVBhcmFtczsKICBfZXhwb3J0cy5yZXNlbWJsZXNVUkwgPSByZXNlbWJsZXNVUkw7CiAgX2V4cG9ydHMucHJlZml4Um91dGVOYW1lQXJnID0gcHJlZml4Um91dGVOYW1lQXJnOwogIF9leHBvcnRzLnNoYWxsb3dFcXVhbCA9IHNoYWxsb3dFcXVhbDsKICB2YXIgQUxMX1BFUklPRFNfUkVHRVggPSAvXC4vZzsKCiAgZnVuY3Rpb24gZXh0cmFjdFJvdXRlQXJncyhhcmdzKSB7CiAgICBhcmdzID0gYXJncy5zbGljZSgpOwogICAgdmFyIHBvc3NpYmxlUXVlcnlQYXJhbXMgPSBhcmdzW2FyZ3MubGVuZ3RoIC0gMV07CiAgICB2YXIgcXVlcnlQYXJhbXM7CgogICAgaWYgKHBvc3NpYmxlUXVlcnlQYXJhbXMgJiYgcG9zc2libGVRdWVyeVBhcmFtcy5oYXNPd25Qcm9wZXJ0eSgncXVlcnlQYXJhbXMnKSkgewogICAgICBxdWVyeVBhcmFtcyA9IGFyZ3MucG9wKCkucXVlcnlQYXJhbXM7CiAgICB9IGVsc2UgewogICAgICBxdWVyeVBhcmFtcyA9IHt9OwogICAgfQoKICAgIHZhciByb3V0ZU5hbWUgPSBhcmdzLnNoaWZ0KCk7CiAgICByZXR1cm4gewogICAgICByb3V0ZU5hbWU6IHJvdXRlTmFtZSwKICAgICAgbW9kZWxzOiBhcmdzLAogICAgICBxdWVyeVBhcmFtczogcXVlcnlQYXJhbXMKICAgIH07CiAgfQoKICBmdW5jdGlvbiBnZXRBY3RpdmVUYXJnZXROYW1lKHJvdXRlcikgewogICAgdmFyIHJvdXRlSW5mb3MgPSByb3V0ZXIuYWN0aXZlVHJhbnNpdGlvbiA/IHJvdXRlci5hY3RpdmVUcmFuc2l0aW9uW19yb3V0ZXJfanMuU1RBVEVfU1lNQk9MXS5yb3V0ZUluZm9zIDogcm91dGVyLnN0YXRlLnJvdXRlSW5mb3M7CiAgICByZXR1cm4gcm91dGVJbmZvc1tyb3V0ZUluZm9zLmxlbmd0aCAtIDFdLm5hbWU7CiAgfQoKICBmdW5jdGlvbiBzdGFzaFBhcmFtTmFtZXMocm91dGVyLCByb3V0ZUluZm9zKSB7CiAgICBpZiAocm91dGVJbmZvc1snX25hbWVzU3Rhc2hlZCddKSB7CiAgICAgIHJldHVybjsKICAgIH0gLy8gVGhpcyBoZWxwZXIgZXhpc3RzIGJlY2F1c2Ugcm91dGVyLmpzL3JvdXRlLXJlY29nbml6ZXIuanMgYXdrd2FyZGx5CiAgICAvLyBrZWVwcyBzZXBhcmF0ZSBhIHJvdXRlSW5mbydzIGxpc3Qgb2YgcGFyYW1ldGVyIG5hbWVzIGRlcGVuZGluZwogICAgLy8gb24gd2hldGhlciBhIFVSTCB0cmFuc2l0aW9uIG9yIG5hbWVkIHRyYW5zaXRpb24gaXMgaGFwcGVuaW5nLgogICAgLy8gSG9wZWZ1bGx5IHdlIGNhbiByZW1vdmUgdGhpcyBpbiB0aGUgZnV0dXJlLgoKCiAgICB2YXIgdGFyZ2V0Um91dGVOYW1lID0gcm91dGVJbmZvc1tyb3V0ZUluZm9zLmxlbmd0aCAtIDFdLm5hbWU7CgogICAgdmFyIHJlY29nSGFuZGxlcnMgPSByb3V0ZXIuX3JvdXRlck1pY3JvbGliLnJlY29nbml6ZXIuaGFuZGxlcnNGb3IodGFyZ2V0Um91dGVOYW1lKTsKCiAgICB2YXIgZHluYW1pY1BhcmVudDsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvdXRlSW5mb3MubGVuZ3RoOyArK2kpIHsKICAgICAgdmFyIHJvdXRlSW5mbyA9IHJvdXRlSW5mb3NbaV07CiAgICAgIHZhciBuYW1lcyA9IHJlY29nSGFuZGxlcnNbaV0ubmFtZXM7CgogICAgICBpZiAobmFtZXMubGVuZ3RoKSB7CiAgICAgICAgZHluYW1pY1BhcmVudCA9IHJvdXRlSW5mbzsKICAgICAgfQoKICAgICAgcm91dGVJbmZvWydfbmFtZXMnXSA9IG5hbWVzOwogICAgICB2YXIgcm91dGUgPSByb3V0ZUluZm8ucm91dGU7CgogICAgICByb3V0ZS5fc3Rhc2hOYW1lcyhyb3V0ZUluZm8sIGR5bmFtaWNQYXJlbnQpOwogICAgfQoKICAgIHJvdXRlSW5mb3NbJ19uYW1lc1N0YXNoZWQnXSA9IHRydWU7CiAgfQoKICBmdW5jdGlvbiBfY2FsY3VsYXRlQ2FjaGVWYWx1ZVByZWZpeChwcmVmaXgsIHBhcnQpIHsKICAgIC8vIGNhbGN1bGF0ZXMgdGhlIGRvdCBzZXBhcmF0ZWQgc2VjdGlvbnMgZnJvbSBwcmVmaXggdGhhdCBhcmUgYWxzbwogICAgLy8gYXQgdGhlIHN0YXJ0IG9mIHBhcnQgLSB3aGljaCBnaXZlcyB1cyB0aGUgcm91dGUgbmFtZQogICAgLy8gZ2l2ZW4gOiBwcmVmaXggPSBzaXRlLmFydGljbGUuY29tbWVudHMsIHBhcnQgPSBzaXRlLmFydGljbGUuaWQKICAgIC8vICAgICAgLSByZXR1cm5zOiBzaXRlLmFydGljbGUgKHVzZSBnZXQodmFsdWVzW3NpdGUuYXJ0aWNsZV0sICdpZCcpIHRvIGdldCB0aGUgZHluYW1pYyBwYXJ0IC0gdXNlZCBiZWxvdykKICAgIC8vIGdpdmVuIDogcHJlZml4ID0gc2l0ZS5hcnRpY2xlLCBwYXJ0ID0gc2l0ZS5hcnRpY2xlLmlkCiAgICAvLyAgICAgIC0gcmV0dXJuczogc2l0ZS5hcnRpY2xlLiAodXNlIGdldCh2YWx1ZXNbc2l0ZS5hcnRpY2xlXSwgJ2lkJykgdG8gZ2V0IHRoZSBkeW5hbWljIHBhcnQgLSB1c2VkIGJlbG93KQogICAgdmFyIHByZWZpeFBhcnRzID0gcHJlZml4LnNwbGl0KCcuJyk7CiAgICB2YXIgY3VyclByZWZpeCA9ICcnOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJlZml4UGFydHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGN1cnJQYXJ0ID0gcHJlZml4UGFydHMuc2xpY2UoMCwgaSArIDEpLmpvaW4oJy4nKTsKCiAgICAgIGlmIChwYXJ0LmluZGV4T2YoY3VyclBhcnQpICE9PSAwKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KCiAgICAgIGN1cnJQcmVmaXggPSBjdXJyUGFydDsKICAgIH0KCiAgICByZXR1cm4gY3VyclByZWZpeDsKICB9CiAgLyoKICAgIFN0b2xlbiBmcm9tIENvbnRyb2xsZXIKICAqLwoKCiAgZnVuY3Rpb24gY2FsY3VsYXRlQ2FjaGVLZXkocHJlZml4LCBwYXJ0cywgdmFsdWVzKSB7CiAgICBpZiAocGFydHMgPT09IHZvaWQgMCkgewogICAgICBwYXJ0cyA9IFtdOwogICAgfQoKICAgIHZhciBzdWZmaXhlcyA9ICcnOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyArK2kpIHsKICAgICAgdmFyIHBhcnQgPSBwYXJ0c1tpXTsKCiAgICAgIHZhciBjYWNoZVZhbHVlUHJlZml4ID0gX2NhbGN1bGF0ZUNhY2hlVmFsdWVQcmVmaXgocHJlZml4LCBwYXJ0KTsKCiAgICAgIHZhciB2YWx1ZSA9IHZvaWQgMDsKCiAgICAgIGlmICh2YWx1ZXMpIHsKICAgICAgICBpZiAoY2FjaGVWYWx1ZVByZWZpeCAmJiBjYWNoZVZhbHVlUHJlZml4IGluIHZhbHVlcykgewogICAgICAgICAgdmFyIHBhcnRSZW1vdmVkUHJlZml4ID0gcGFydC5pbmRleE9mKGNhY2hlVmFsdWVQcmVmaXgpID09PSAwID8gcGFydC5zdWJzdHIoY2FjaGVWYWx1ZVByZWZpeC5sZW5ndGggKyAxKSA6IHBhcnQ7CiAgICAgICAgICB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KSh2YWx1ZXNbY2FjaGVWYWx1ZVByZWZpeF0sIHBhcnRSZW1vdmVkUHJlZml4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFsdWUgPSAoMCwgX21ldGFsLmdldCkodmFsdWVzLCBwYXJ0KTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHN1ZmZpeGVzICs9ICI6OiIgKyBwYXJ0ICsgIjoiICsgdmFsdWU7CiAgICB9CgogICAgcmV0dXJuIHByZWZpeCArIHN1ZmZpeGVzLnJlcGxhY2UoQUxMX1BFUklPRFNfUkVHRVgsICctJyk7CiAgfQogIC8qCiAgICBDb250cm9sbGVyLWRlZmluZWQgcXVlcnkgcGFyYW1ldGVycyBjYW4gY29tZSBpbiB0aHJlZSBzaGFwZXM6CiAgCiAgICBBcnJheQogICAgICBxdWVyeVBhcmFtczogWydmb28nLCAnYmFyJ10KICAgIEFycmF5IG9mIHNpbXBsZSBvYmplY3RzIHdoZXJlIHZhbHVlIGlzIGFuIGFsaWFzCiAgICAgIHF1ZXJ5UGFyYW1zOiBbCiAgICAgICAgewogICAgICAgICAgJ2Zvbyc6ICdyZW5hbWVfZm9vX3RvX3RoaXMnCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAnYmFyJzogJ2NhbGxfYmFyX3RoaXNfaW5zdGVhZCcKICAgICAgICB9CiAgICAgIF0KICAgIEFycmF5IG9mIGZ1bGx5IGRlZmluZWQgb2JqZWN0cwogICAgICBxdWVyeVBhcmFtczogWwogICAgICAgIHsKICAgICAgICAgICdmb28nOiB7CiAgICAgICAgICAgIGFzOiAncmVuYW1lX2Zvb190b190aGlzJwogICAgICAgICAgfSwKICAgICAgICB9CiAgICAgICAgewogICAgICAgICAgJ2Jhcic6IHsKICAgICAgICAgICAgYXM6ICdjYWxsX2Jhcl90aGlzX2luc3RlYWQnLAogICAgICAgICAgICBzY29wZTogJ2NvbnRyb2xsZXInCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICBdCiAgCiAgICBUaGlzIGhlbHBlciBub3JtYWxpemVzIGFsbCB0aHJlZSBwb3NzaWJsZSBzdHlsZXMgaW50byB0aGUKICAgICdBcnJheSBvZiBmdWxseSBkZWZpbmVkIG9iamVjdHMnIHN0eWxlLgogICovCgoKICBmdW5jdGlvbiBub3JtYWxpemVDb250cm9sbGVyUXVlcnlQYXJhbXMocXVlcnlQYXJhbXMpIHsKICAgIHZhciBxcE1hcCA9IHt9OwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcXVlcnlQYXJhbXMubGVuZ3RoOyArK2kpIHsKICAgICAgYWNjdW11bGF0ZVF1ZXJ5UGFyYW1EZXNjcmlwdG9ycyhxdWVyeVBhcmFtc1tpXSwgcXBNYXApOwogICAgfQoKICAgIHJldHVybiBxcE1hcDsKICB9CgogIGZ1bmN0aW9uIGFjY3VtdWxhdGVRdWVyeVBhcmFtRGVzY3JpcHRvcnMoX2Rlc2MsIGFjY3VtKSB7CiAgICB2YXIgZGVzYyA9IF9kZXNjOwogICAgdmFyIHRtcDsKCiAgICBpZiAodHlwZW9mIGRlc2MgPT09ICdzdHJpbmcnKSB7CiAgICAgIHRtcCA9IHt9OwogICAgICB0bXBbZGVzY10gPSB7CiAgICAgICAgYXM6IG51bGwKICAgICAgfTsKICAgICAgZGVzYyA9IHRtcDsKICAgIH0KCiAgICBmb3IgKHZhciBrZXkgaW4gZGVzYykgewogICAgICBpZiAoIWRlc2MuaGFzT3duUHJvcGVydHkoa2V5KSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIHNpbmdsZURlc2MgPSBkZXNjW2tleV07CgogICAgICBpZiAodHlwZW9mIHNpbmdsZURlc2MgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgc2luZ2xlRGVzYyA9IHsKICAgICAgICAgIGFzOiBzaW5nbGVEZXNjCiAgICAgICAgfTsKICAgICAgfQoKICAgICAgdG1wID0gYWNjdW1ba2V5XSB8fCB7CiAgICAgICAgYXM6IG51bGwsCiAgICAgICAgc2NvcGU6ICdtb2RlbCcKICAgICAgfTsKICAgICAgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh0bXAsIHNpbmdsZURlc2MpOwogICAgICBhY2N1bVtrZXldID0gdG1wOwogICAgfQogIH0KICAvKgogICAgQ2hlY2sgaWYgYSByb3V0ZU5hbWUgcmVzZW1ibGVzIGEgdXJsIGluc3RlYWQKICAKICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIHJlc2VtYmxlc1VSTChzdHIpIHsKICAgIHJldHVybiB0eXBlb2Ygc3RyID09PSAnc3RyaW5nJyAmJiAoc3RyID09PSAnJyB8fCBzdHJbMF0gPT09ICcvJyk7CiAgfQogIC8qCiAgICBSZXR1cm5zIGFuIGFyZ3VtZW50cyBhcnJheSB3aGVyZSB0aGUgcm91dGUgbmFtZSBhcmcgaXMgcHJlZml4ZWQgYmFzZWQgb24gdGhlIG1vdW50IHBvaW50CiAgCiAgICBAcHJpdmF0ZQogICovCgoKICBmdW5jdGlvbiBwcmVmaXhSb3V0ZU5hbWVBcmcocm91dGUsIGFyZ3MpIHsKICAgIHZhciByb3V0ZU5hbWUgPSBhcmdzWzBdOwogICAgdmFyIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikocm91dGUpOwogICAgdmFyIHByZWZpeCA9IG93bmVyLm1vdW50UG9pbnQ7IC8vIG9ubHkgYWx0ZXIgdGhlIHJvdXRlTmFtZSBpZiBpdCdzIGFjdHVhbGx5IHJlZmVyZW5jaW5nIGEgcm91dGUuCgogICAgaWYgKG93bmVyLnJvdXRhYmxlICYmIHR5cGVvZiByb3V0ZU5hbWUgPT09ICdzdHJpbmcnKSB7CiAgICAgIGlmIChyZXNlbWJsZXNVUkwocm91dGVOYW1lKSkgewogICAgICAgIHRocm93IG5ldyBfZXJyb3IuZGVmYXVsdCgnUHJvZ3JhbW1hdGljIHRyYW5zaXRpb25zIGJ5IFVSTCBjYW5ub3QgYmUgdXNlZCB3aXRoaW4gYW4gRW5naW5lLiBQbGVhc2UgdXNlIHRoZSByb3V0ZSBuYW1lIGluc3RlYWQuJyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcm91dGVOYW1lID0gcHJlZml4ICsgIi4iICsgcm91dGVOYW1lOwogICAgICAgIGFyZ3NbMF0gPSByb3V0ZU5hbWU7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gYXJnczsKICB9CgogIGZ1bmN0aW9uIHNoYWxsb3dFcXVhbChhLCBiKSB7CiAgICB2YXIgazsKICAgIHZhciBhQ291bnQgPSAwOwogICAgdmFyIGJDb3VudCA9IDA7CgogICAgZm9yIChrIGluIGEpIHsKICAgICAgaWYgKGEuaGFzT3duUHJvcGVydHkoaykpIHsKICAgICAgICBpZiAoYVtrXSAhPT0gYltrXSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgYUNvdW50Kys7CiAgICAgIH0KICAgIH0KCiAgICBmb3IgKGsgaW4gYikgewogICAgICBpZiAoYi5oYXNPd25Qcm9wZXJ0eShrKSkgewogICAgICAgIGJDb3VudCsrOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGFDb3VudCA9PT0gYkNvdW50OwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vb2JqZWN0IiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9yZWdpc3RyeV9wcm94eSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvY29udGFpbmVyX3Byb3h5IiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL2NvcHkiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvY29tcGFyZSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9pcy1lcXVhbCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvYXJyYXkiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2NvbXBhcmFibGUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL25hbWVzcGFjZSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vYXJyYXlfcHJveHkiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL29iamVjdF9wcm94eSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vY29yZV9vYmplY3QiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2FjdGlvbl9oYW5kbGVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9jb3B5YWJsZSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvZW51bWVyYWJsZSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvLXByb3h5IiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9vYnNlcnZhYmxlIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9tdXRhYmxlX2VudW1lcmFibGUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL3RhcmdldF9hY3Rpb25fc3VwcG9ydCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvZXZlbnRlZCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvcHJvbWlzZV9wcm94eSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9leHQvcnN2cCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi90eXBlLW9mIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL2V4dC9mdW5jdGlvbiJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9vYmplY3QsIF9yZWdpc3RyeV9wcm94eSwgX2NvbnRhaW5lcl9wcm94eSwgX2NvcHksIF9jb21wYXJlLCBfaXNFcXVhbCwgX2FycmF5LCBfY29tcGFyYWJsZSwgX25hbWVzcGFjZSwgX2FycmF5X3Byb3h5LCBfb2JqZWN0X3Byb3h5LCBfY29yZV9vYmplY3QsIF9hY3Rpb25faGFuZGxlciwgX2NvcHlhYmxlLCBfZW51bWVyYWJsZSwgX3Byb3h5LCBfb2JzZXJ2YWJsZSwgX211dGFibGVfZW51bWVyYWJsZSwgX3RhcmdldF9hY3Rpb25fc3VwcG9ydCwgX2V2ZW50ZWQsIF9wcm9taXNlX3Byb3h5LCBfcnN2cCwgX3R5cGVPZiwgX2Z1bmN0aW9uKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJPYmplY3QiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfb2JqZWN0LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiRnJhbWV3b3JrT2JqZWN0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX29iamVjdC5GcmFtZXdvcmtPYmplY3Q7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiUmVnaXN0cnlQcm94eU1peGluIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZ2lzdHJ5X3Byb3h5LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQ29udGFpbmVyUHJveHlNaXhpbiIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb250YWluZXJfcHJveHkuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJjb3B5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvcHkuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJjb21wYXJlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXBhcmUuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJpc0VxdWFsIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2lzRXF1YWwuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJBcnJheSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9hcnJheS5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIk5hdGl2ZUFycmF5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2FycmF5Lk5hdGl2ZUFycmF5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkEiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXJyYXkuQTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJNdXRhYmxlQXJyYXkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXJyYXkuTXV0YWJsZUFycmF5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInJlbW92ZUF0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2FycmF5LnJlbW92ZUF0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInVuaXFCeSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9hcnJheS51bmlxQnk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiaXNBcnJheSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9hcnJheS5pc0FycmF5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkNvbXBhcmFibGUiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcGFyYWJsZS5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIk5hbWVzcGFjZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9uYW1lc3BhY2UuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJBcnJheVByb3h5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2FycmF5X3Byb3h5LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiT2JqZWN0UHJveHkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfb2JqZWN0X3Byb3h5LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQ29yZU9iamVjdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb3JlX29iamVjdC5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInNldEZyYW1ld29ya0NsYXNzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvcmVfb2JqZWN0LnNldEZyYW1ld29ya0NsYXNzOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkFjdGlvbkhhbmRsZXIiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYWN0aW9uX2hhbmRsZXIuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJDb3B5YWJsZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb3B5YWJsZS5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkVudW1lcmFibGUiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZW51bWVyYWJsZS5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9Qcm94eU1peGluIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3Byb3h5LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX2NvbnRlbnRGb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJveHkuY29udGVudEZvcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJPYnNlcnZhYmxlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX29ic2VydmFibGUuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJNdXRhYmxlRW51bWVyYWJsZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9tdXRhYmxlX2VudW1lcmFibGUuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJUYXJnZXRBY3Rpb25TdXBwb3J0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3RhcmdldF9hY3Rpb25fc3VwcG9ydC5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkV2ZW50ZWQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZXZlbnRlZC5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIlByb21pc2VQcm94eU1peGluIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3Byb21pc2VfcHJveHkuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJSU1ZQIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JzdnAuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJvbmVycm9yRGVmYXVsdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9yc3ZwLm9uZXJyb3JEZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInR5cGVPZiIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF90eXBlT2YudHlwZU9mOwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9jb21wYXJlIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL3R5cGUtb2YiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2NvbXBhcmFibGUiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdHlwZU9mLCBfY29tcGFyYWJsZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IGNvbXBhcmU7CiAgdmFyIFRZUEVfT1JERVIgPSB7CiAgICB1bmRlZmluZWQ6IDAsCiAgICBudWxsOiAxLAogICAgYm9vbGVhbjogMiwKICAgIG51bWJlcjogMywKICAgIHN0cmluZzogNCwKICAgIGFycmF5OiA1LAogICAgb2JqZWN0OiA2LAogICAgaW5zdGFuY2U6IDcsCiAgICBmdW5jdGlvbjogOCwKICAgIGNsYXNzOiA5LAogICAgZGF0ZTogMTAKICB9OyAvLwogIC8vIHRoZSBzcGFjZXNoaXAgb3BlcmF0b3IKICAvLwogIC8vICAgICAgICAgICAgICAgICAgICAgIGAuIF9fXwogIC8vICAgICAgICAgICAgICAgICAgICAgX18sJyBfX2AuICAgICAgICAgICAgICAgIF8uLi0tLS0uLi4uX19fXwogIC8vICAgICAgICAgX18uLi4tLS4nYGA7LiAgICwuICAgO2BgLS0uLl9fICAgICAuJyAgICAsLS5fICAgIF8uLScKICAvLyAgIF8uLi0nJy0tLS0tLS0nICAgYCcgICBgJyAgIGAnICAgICBPIGBgLScnLl8gICAoLDsnKSBfLCcKICAvLyAsJ19fX19fX19fX19fX19fX18gICAgICAgICAgICAgICAgICAgICAgICAgIFxgLS5fYC0nLCcKICAvLyAgYC5fICAgICAgICAgICAgICBgYGBgYGBgYGBgYC0tLS0tLS4uLl9fXyAgICctLi5fJy06CiAgLy8gICAgIGBgYC0tLi5fICAgICAgLC4gICAgICAgICAgICAgICAgICAgICBgYGBgLS0uLi5fX1wtLgogIC8vICAgICAgICAgICAgIGAuLS0uIGAtYCAiSU5GSU5JVFkgSVMgTEVTUyAgICAgX19fXyAgICB8ICB8YAogIC8vICAgICAgICAgICAgICAgYC4gYC4gICBUSEFOIEJFWU9ORCIgICAgICAgICwnYGBgYGAuICA7ICA7YAogIC8vICAgICAgICAgICAgICAgICBgLl9gLiAgICAgICAgX19fX19fX19fXyAgIGAuICAgICAgXCdfXy9gCiAgLy8gICAgICAgICAgICAgICAgICAgIGAtOi5fX19fXy9fX19fX18vX19fL19fX19gLiAgICAgXCAgYAogIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgIGAuXyAgICBgLiAgICBcCiAgLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGAuX19fX19fX19fYC0uICAgYC4gICBgLl9fXwogIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNTdCAgYC0tLS0tLSdgCgogIGZ1bmN0aW9uIHNwYWNlc2hpcChhLCBiKSB7CiAgICB2YXIgZGlmZiA9IGEgLSBiOwogICAgcmV0dXJuIChkaWZmID4gMCkgLSAoZGlmZiA8IDApOwogIH0KICAvKioKICAgQG1vZHVsZSBAZW1iZXIvdXRpbHMKICAqLwoKICAvKioKICAgQ29tcGFyZXMgdHdvIGphdmFzY3JpcHQgdmFsdWVzIGFuZCByZXR1cm5zOgogIAogICAgLSAtMSBpZiB0aGUgZmlyc3QgaXMgc21hbGxlciB0aGFuIHRoZSBzZWNvbmQsCiAgICAtIDAgaWYgYm90aCBhcmUgZXF1YWwsCiAgICAtIDEgaWYgdGhlIGZpcnN0IGlzIGdyZWF0ZXIgdGhhbiB0aGUgc2Vjb25kLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgY29tcGFyZSB9IGZyb20gJ0BlbWJlci91dGlscyc7CiAgCiAgICBjb21wYXJlKCdoZWxsbycsICdoZWxsbycpOyAgLy8gMAogICAgY29tcGFyZSgnYWJjJywgJ2RmZycpOyAgICAgIC8vIC0xCiAgICBjb21wYXJlKDIsIDEpOyAgICAgICAgICAgICAgLy8gMQogICAgYGBgCiAgCiAgIElmIHRoZSB0eXBlcyBvZiB0aGUgdHdvIG9iamVjdHMgYXJlIGRpZmZlcmVudCBwcmVjZWRlbmNlIG9jY3VycyBpbiB0aGUKICAgZm9sbG93aW5nIG9yZGVyLCB3aXRoIHR5cGVzIGVhcmxpZXIgaW4gdGhlIGxpc3QgY29uc2lkZXJlZCBgPGAgdHlwZXMKICAgbGF0ZXIgaW4gdGhlIGxpc3Q6CiAgCiAgICAtIHVuZGVmaW5lZAogICAgLSBudWxsCiAgICAtIGJvb2xlYW4KICAgIC0gbnVtYmVyCiAgICAtIHN0cmluZwogICAgLSBhcnJheQogICAgLSBvYmplY3QKICAgIC0gaW5zdGFuY2UKICAgIC0gZnVuY3Rpb24KICAgIC0gY2xhc3MKICAgIC0gZGF0ZQogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgY29tcGFyZSB9IGZyb20gJ0BlbWJlci91dGlscyc7CiAgCiAgICBjb21wYXJlKCdoZWxsbycsIDUwKTsgICAgICAgLy8gMQogICAgY29tcGFyZSg1MCwgJ2hlbGxvJyk7ICAgICAgIC8vIC0xCiAgICBgYGAKICAKICAgQG1ldGhvZCBjb21wYXJlCiAgIEBmb3IgQGVtYmVyL3V0aWxzCiAgIEBzdGF0aWMKICAgQHBhcmFtIHtPYmplY3R9IHYgRmlyc3QgdmFsdWUgdG8gY29tcGFyZQogICBAcGFyYW0ge09iamVjdH0gdyBTZWNvbmQgdmFsdWUgdG8gY29tcGFyZQogICBAcmV0dXJuIHtOdW1iZXJ9IC0xIGlmIHYgPCB3LCAwIGlmIHYgPSB3IGFuZCAxIGlmIHYgPiB3LgogICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGNvbXBhcmUodiwgdykgewogICAgaWYgKHYgPT09IHcpIHsKICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgdmFyIHR5cGUxID0gKDAsIF90eXBlT2YudHlwZU9mKSh2KTsKICAgIHZhciB0eXBlMiA9ICgwLCBfdHlwZU9mLnR5cGVPZikodyk7CgogICAgaWYgKHR5cGUxID09PSAnaW5zdGFuY2UnICYmIF9jb21wYXJhYmxlLmRlZmF1bHQuZGV0ZWN0KHYpICYmIHYuY29uc3RydWN0b3IuY29tcGFyZSkgewogICAgICByZXR1cm4gdi5jb25zdHJ1Y3Rvci5jb21wYXJlKHYsIHcpOwogICAgfQoKICAgIGlmICh0eXBlMiA9PT0gJ2luc3RhbmNlJyAmJiBfY29tcGFyYWJsZS5kZWZhdWx0LmRldGVjdCh3KSAmJiB3LmNvbnN0cnVjdG9yLmNvbXBhcmUpIHsKICAgICAgcmV0dXJuIHcuY29uc3RydWN0b3IuY29tcGFyZSh3LCB2KSAqIC0xOwogICAgfQoKICAgIHZhciByZXMgPSBzcGFjZXNoaXAoVFlQRV9PUkRFUlt0eXBlMV0sIFRZUEVfT1JERVJbdHlwZTJdKTsKCiAgICBpZiAocmVzICE9PSAwKSB7CiAgICAgIHJldHVybiByZXM7CiAgICB9IC8vIHR5cGVzIGFyZSBlcXVhbCAtIHNvIHdlIGhhdmUgdG8gY2hlY2sgdmFsdWVzIG5vdwoKCiAgICBzd2l0Y2ggKHR5cGUxKSB7CiAgICAgIGNhc2UgJ2Jvb2xlYW4nOgogICAgICBjYXNlICdudW1iZXInOgogICAgICAgIHJldHVybiBzcGFjZXNoaXAodiwgdyk7CgogICAgICBjYXNlICdzdHJpbmcnOgogICAgICAgIHJldHVybiBzcGFjZXNoaXAodi5sb2NhbGVDb21wYXJlKHcpLCAwKTsKCiAgICAgIGNhc2UgJ2FycmF5JzoKICAgICAgICB7CiAgICAgICAgICB2YXIgdkxlbiA9IHYubGVuZ3RoOwogICAgICAgICAgdmFyIHdMZW4gPSB3Lmxlbmd0aDsKICAgICAgICAgIHZhciBsZW4gPSBNYXRoLm1pbih2TGVuLCB3TGVuKTsKCiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgICAgICAgIHZhciByID0gY29tcGFyZSh2W2ldLCB3W2ldKTsKCiAgICAgICAgICAgIGlmIChyICE9PSAwKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHI7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gLy8gYWxsIGVsZW1lbnRzIGFyZSBlcXVhbCBub3cKICAgICAgICAgIC8vIHNob3J0ZXIgYXJyYXkgc2hvdWxkIGJlIG9yZGVyZWQgZmlyc3QKCgogICAgICAgICAgcmV0dXJuIHNwYWNlc2hpcCh2TGVuLCB3TGVuKTsKICAgICAgICB9CgogICAgICBjYXNlICdpbnN0YW5jZSc6CiAgICAgICAgaWYgKF9jb21wYXJhYmxlLmRlZmF1bHQuZGV0ZWN0KHYpKSB7CiAgICAgICAgICByZXR1cm4gdi5jb21wYXJlKHYsIHcpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIDA7CgogICAgICBjYXNlICdkYXRlJzoKICAgICAgICByZXR1cm4gc3BhY2VzaGlwKHYuZ2V0VGltZSgpLCB3LmdldFRpbWUoKSk7CgogICAgICBkZWZhdWx0OgogICAgICAgIHJldHVybiAwOwogICAgfQogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvY29weSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL29iamVjdCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvY29weWFibGUiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVidWcsIF9vYmplY3QsIF9jb3B5YWJsZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IGNvcHk7CgogIC8qKgogICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwogIGZ1bmN0aW9uIF9jb3B5KG9iaiwgZGVlcCwgc2VlbiwgY29waWVzKSB7CiAgICAvLyBwcmltaXRpdmUgZGF0YSB0eXBlcyBhcmUgaW1tdXRhYmxlLCBqdXN0IHJldHVybiB0aGVtLgogICAgaWYgKHR5cGVvZiBvYmogIT09ICdvYmplY3QnIHx8IG9iaiA9PT0gbnVsbCkgewogICAgICByZXR1cm4gb2JqOwogICAgfQoKICAgIHZhciByZXQsIGxvYzsgLy8gYXZvaWQgY3ljbGljYWwgbG9vcHMKCiAgICBpZiAoZGVlcCAmJiAobG9jID0gc2Vlbi5pbmRleE9mKG9iaikpID49IDApIHsKICAgICAgcmV0dXJuIGNvcGllc1tsb2NdOwogICAgfQoKICAgIGlmIChkZWVwKSB7CiAgICAgIHNlZW4ucHVzaChvYmopOwogICAgfSAvLyBJTVBPUlRBTlQ6IHRoaXMgc3BlY2lmaWMgdGVzdCB3aWxsIGRldGVjdCBhIG5hdGl2ZSBhcnJheSBvbmx5LiBBbnkgb3RoZXIKICAgIC8vIG9iamVjdCB3aWxsIG5lZWQgdG8gaW1wbGVtZW50IENvcHlhYmxlLgoKCiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7CiAgICAgIHJldCA9IG9iai5zbGljZSgpOwoKICAgICAgaWYgKGRlZXApIHsKICAgICAgICBjb3BpZXMucHVzaChyZXQpOwogICAgICAgIGxvYyA9IHJldC5sZW5ndGg7CgogICAgICAgIHdoaWxlICgtLWxvYyA+PSAwKSB7CiAgICAgICAgICByZXRbbG9jXSA9IF9jb3B5KHJldFtsb2NdLCBkZWVwLCBzZWVuLCBjb3BpZXMpOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIGlmIChfY29weWFibGUuZGVmYXVsdC5kZXRlY3Qob2JqKSkgewogICAgICByZXQgPSBvYmouY29weShkZWVwLCBzZWVuLCBjb3BpZXMpOwoKICAgICAgaWYgKGRlZXApIHsKICAgICAgICBjb3BpZXMucHVzaChyZXQpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKG9iaiBpbnN0YW5jZW9mIERhdGUpIHsKICAgICAgcmV0ID0gbmV3IERhdGUob2JqLmdldFRpbWUoKSk7CgogICAgICBpZiAoZGVlcCkgewogICAgICAgIGNvcGllcy5wdXNoKHJldCk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIChmYWxzZSAmJiAhKCEob2JqIGluc3RhbmNlb2YgX29iamVjdC5kZWZhdWx0KSB8fCBfY29weWFibGUuZGVmYXVsdC5kZXRlY3Qob2JqKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdDYW5ub3QgY2xvbmUgYW4gRW1iZXJPYmplY3QgdGhhdCBkb2VzIG5vdCBpbXBsZW1lbnQgQ29weWFibGUnLCAhKG9iaiBpbnN0YW5jZW9mIF9vYmplY3QuZGVmYXVsdCkgfHwgX2NvcHlhYmxlLmRlZmF1bHQuZGV0ZWN0KG9iaikpKTsKICAgICAgcmV0ID0ge307CgogICAgICBpZiAoZGVlcCkgewogICAgICAgIGNvcGllcy5wdXNoKHJldCk7CiAgICAgIH0KCiAgICAgIHZhciBrZXk7CgogICAgICBmb3IgKGtleSBpbiBvYmopIHsKICAgICAgICAvLyBzdXBwb3J0IE51bGwgcHJvdG90eXBlCiAgICAgICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9IC8vIFByZXZlbnRzIGJyb3dzZXJzIHRoYXQgZG9uJ3QgcmVzcGVjdCBub24tZW51bWVyYWJpbGl0eSBmcm9tCiAgICAgICAgLy8gY29weWluZyBpbnRlcm5hbCBFbWJlciBwcm9wZXJ0aWVzCgoKICAgICAgICBpZiAoa2V5LnN1YnN0cmluZygwLCAyKSA9PT0gJ19fJykgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICByZXRba2V5XSA9IGRlZXAgPyBfY29weShvYmpba2V5XSwgZGVlcCwgc2VlbiwgY29waWVzKSA6IG9ialtrZXldOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJldDsKICB9CiAgLyoqCiAgICBDcmVhdGVzIGEgc2hhbGxvdyBjb3B5IG9mIHRoZSBwYXNzZWQgb2JqZWN0LiBBIGRlZXAgY29weSBvZiB0aGUgb2JqZWN0IGlzCiAgICByZXR1cm5lZCBpZiB0aGUgb3B0aW9uYWwgYGRlZXBgIGFyZ3VtZW50IGlzIGB0cnVlYC4KICAKICAgIElmIHRoZSBwYXNzZWQgb2JqZWN0IGltcGxlbWVudHMgdGhlIGBDb3B5YWJsZWAgaW50ZXJmYWNlLCB0aGVuIHRoaXMKICAgIGZ1bmN0aW9uIHdpbGwgZGVsZWdhdGUgdG8gdGhlIG9iamVjdCdzIGBjb3B5KClgIG1ldGhvZCBhbmQgcmV0dXJuIHRoZQogICAgcmVzdWx0LiBTZWUgYENvcHlhYmxlYCBmb3IgZnVydGhlciBkZXRhaWxzLgogIAogICAgRm9yIHByaW1pdGl2ZSB2YWx1ZXMgKHdoaWNoIGFyZSBpbW11dGFibGUgaW4gSmF2YVNjcmlwdCksIHRoZSBwYXNzZWQgb2JqZWN0CiAgICBpcyBzaW1wbHkgcmV0dXJuZWQuCiAgCiAgICBAbWV0aG9kIGNvcHkKICAgIEBkZXByZWNhdGVkIFVzZSAnZW1iZXItY29weScgYWRkb24gaW5zdGVhZAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2ludGVybmFscwogICAgQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIGNsb25lCiAgICBAcGFyYW0ge0Jvb2xlYW59IFtkZWVwPWZhbHNlXSBJZiB0cnVlLCBhIGRlZXAgY29weSBvZiB0aGUgb2JqZWN0IGlzIG1hZGUuCiAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSBjb3BpZWQgb2JqZWN0CiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGNvcHkob2JqLCBkZWVwKSB7CiAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdVc2UgZW1iZXItY29weSBhZGRvbiBpbnN0ZWFkIG9mIGNvcHkgbWV0aG9kIGFuZCBDb3B5YWJsZSBtaXhpbi4nLCBmYWxzZSwgewogICAgICBpZDogJ2VtYmVyLXJ1bnRpbWUuZGVwcmVjYXRlLWNvcHktY29weWFibGUnLAogICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueC8jdG9jX2VtYmVyLXJ1bnRpbWUtZGVwcmVjYXRlLWNvcHktY29weWFibGUnCiAgICB9KSk7IC8vIGZhc3QgcGF0aHMKCiAgICBpZiAoJ29iamVjdCcgIT09IHR5cGVvZiBvYmogfHwgb2JqID09PSBudWxsKSB7CiAgICAgIHJldHVybiBvYmo7IC8vIGNhbid0IGNvcHkgcHJpbWl0aXZlcwogICAgfQoKICAgIGlmICghQXJyYXkuaXNBcnJheShvYmopICYmIF9jb3B5YWJsZS5kZWZhdWx0LmRldGVjdChvYmopKSB7CiAgICAgIHJldHVybiBvYmouY29weShkZWVwKTsKICAgIH0KCiAgICByZXR1cm4gX2NvcHkob2JqLCBkZWVwLCBkZWVwID8gW10gOiBudWxsLCBkZWVwID8gW10gOiBudWxsKTsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL2V4dC9mdW5jdGlvbiIsIFsiQGVtYmVyLy1pbnRlcm5hbHMvZW52aXJvbm1lbnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIl0sIGZ1bmN0aW9uIChfZW52aXJvbm1lbnQsIF9tZXRhbCwgX2RlYnVnLCBfZGVwcmVjYXRlZEZlYXR1cmVzKSB7CiAgInVzZSBzdHJpY3QiOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5GVU5DVElPTl9QUk9UT1RZUEVfRVhURU5TSU9OUyAmJiBfZW52aXJvbm1lbnQuRU5WLkVYVEVORF9QUk9UT1RZUEVTLkZ1bmN0aW9uKSB7CiAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhGdW5jdGlvbi5wcm90b3R5cGUsIHsKICAgICAgLyoqCiAgICAgICAgVGhlIGBwcm9wZXJ0eWAgZXh0ZW5zaW9uIG9mIEphdmFzY3JpcHQncyBGdW5jdGlvbiBwcm90b3R5cGUgaXMgYXZhaWxhYmxlCiAgICAgICAgd2hlbiBgRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVNgIG9yIGBFbWJlckVOVi5FWFRFTkRfUFJPVE9UWVBFUy5GdW5jdGlvbmAgaXMKICAgICAgICBgdHJ1ZWAsIHdoaWNoIGlzIHRoZSBkZWZhdWx0LgogICAgICAgICBDb21wdXRlZCBwcm9wZXJ0aWVzIGFsbG93IHlvdSB0byB0cmVhdCBhIGZ1bmN0aW9uIGxpa2UgYSBwcm9wZXJ0eToKICAgICAgICAgYGBgYXBwL3V0aWxzL3ByZXNpZGVudC5qcwogICAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICAgIGZpcnN0TmFtZTogJycsCiAgICAgICAgICBsYXN0TmFtZTogICcnLAogICAgICAgICAgIGZ1bGxOYW1lOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KCdmaXJzdE5hbWUnKSArICcgJyArIHRoaXMuZ2V0KCdsYXN0TmFtZScpOwogICAgICAgICAgfS5wcm9wZXJ0eSgpIC8vIENhbGwgdGhpcyBmbGFnIHRvIG1hcmsgdGhlIGZ1bmN0aW9uIGFzIGEgcHJvcGVydHkKICAgICAgICB9KTsKICAgICAgICBgYGAKICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICAgIGxldCBwcmVzaWRlbnQgPSBQcmVzaWRlbnQuY3JlYXRlKHsKICAgICAgICAgIGZpcnN0TmFtZTogJ0JhcmFjaycsCiAgICAgICAgICBsYXN0TmFtZTogJ09iYW1hJwogICAgICAgIH0pOwogICAgICAgICBwcmVzaWRlbnQuZ2V0KCdmdWxsTmFtZScpOyAvLyAnQmFyYWNrIE9iYW1hJwogICAgICAgIGBgYAogICAgICAgICBUcmVhdGluZyBhIGZ1bmN0aW9uIGxpa2UgYSBwcm9wZXJ0eSBpcyB1c2VmdWwgYmVjYXVzZSB0aGV5IGNhbiB3b3JrIHdpdGgKICAgICAgICBiaW5kaW5ncywganVzdCBsaWtlIGFueSBvdGhlciBwcm9wZXJ0eS4KICAgICAgICAgTWFueSBjb21wdXRlZCBwcm9wZXJ0aWVzIGhhdmUgZGVwZW5kZW5jaWVzIG9uIG90aGVyIHByb3BlcnRpZXMuIEZvcgogICAgICAgIGV4YW1wbGUsIGluIHRoZSBhYm92ZSBleGFtcGxlLCB0aGUgYGZ1bGxOYW1lYCBwcm9wZXJ0eSBkZXBlbmRzIG9uCiAgICAgICAgYGZpcnN0TmFtZWAgYW5kIGBsYXN0TmFtZWAgdG8gZGV0ZXJtaW5lIGl0cyB2YWx1ZS4gWW91IGNhbiB0ZWxsIEVtYmVyCiAgICAgICAgYWJvdXQgdGhlc2UgZGVwZW5kZW5jaWVzIGxpa2UgdGhpczoKICAgICAgICAgYGBgYXBwL3V0aWxzL3ByZXNpZGVudC5qcwogICAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgICAgZXhwb3J0IGRlZmF1bHQgRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICAgIGZpcnN0TmFtZTogJycsCiAgICAgICAgICBsYXN0TmFtZTogICcnLAogICAgICAgICAgIGZ1bGxOYW1lOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KCdmaXJzdE5hbWUnKSArICcgJyArIHRoaXMuZ2V0KCdsYXN0TmFtZScpOwogICAgICAgICAgICAgLy8gVGVsbCBFbWJlci5qcyB0aGF0IHRoaXMgY29tcHV0ZWQgcHJvcGVydHkgZGVwZW5kcyBvbiBmaXJzdE5hbWUKICAgICAgICAgICAgLy8gYW5kIGxhc3ROYW1lCiAgICAgICAgICB9LnByb3BlcnR5KCdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnKQogICAgICAgIH0pOwogICAgICAgIGBgYAogICAgICAgICBNYWtlIHN1cmUgeW91IGxpc3QgdGhlc2UgZGVwZW5kZW5jaWVzIHNvIEVtYmVyIGtub3dzIHdoZW4gdG8gdXBkYXRlCiAgICAgICAgYmluZGluZ3MgdGhhdCBjb25uZWN0IHRvIGEgY29tcHV0ZWQgcHJvcGVydHkuIENoYW5naW5nIGEgZGVwZW5kZW5jeQogICAgICAgIHdpbGwgbm90IGltbWVkaWF0ZWx5IHRyaWdnZXIgYW4gdXBkYXRlIG9mIHRoZSBjb21wdXRlZCBwcm9wZXJ0eSwgYnV0CiAgICAgICAgd2lsbCBpbnN0ZWFkIGNsZWFyIHRoZSBjYWNoZSBzbyB0aGF0IGl0IGlzIHVwZGF0ZWQgd2hlbiB0aGUgbmV4dCBgZ2V0YAogICAgICAgIGlzIGNhbGxlZCBvbiB0aGUgcHJvcGVydHkuCiAgICAgICAgIFNlZSBbQ29tcHV0ZWRQcm9wZXJ0eV0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9Db21wdXRlZFByb3BlcnR5KSwgW0BlbWJlci9vYmplY3QvY29tcHV0ZWRdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvQGVtYmVyJTJGb2JqZWN0JTJGY29tcHV0ZWQpLgogICAgICAgICBAbWV0aG9kIHByb3BlcnR5CiAgICAgICAgQGZvciBGdW5jdGlvbgogICAgICAgIEBwdWJsaWMKICAgICAgKi8KICAgICAgcHJvcGVydHk6IHsKICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsCiAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgiRnVuY3Rpb24gcHJvdG90eXBlIGV4dGVuc2lvbnMgaGF2ZSBiZWVuIGRlcHJlY2F0ZWQsIHBsZWFzZSBtaWdyYXRlIGZyb20gZnVuY3Rpb24oKXt9LnByb3BlcnR5KCdiYXInKSB0byBjb21wdXRlZCgnYmFyJywgZnVuY3Rpb24oKSB7fSkuIiwgZmFsc2UsIHsKICAgICAgICAgICAgaWQ6ICdmdW5jdGlvbi1wcm90b3R5cGUtZXh0ZW5zaW9ucy5wcm9wZXJ0eScsCiAgICAgICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgICAgICB1cmw6ICdodHRwczovL2RlcHJlY2F0aW9ucy5lbWJlcmpzLmNvbS92My54I3RvY19mdW5jdGlvbi1wcm90b3R5cGUtZXh0ZW5zaW9ucy1wcm9wZXJ0eScKICAgICAgICAgIH0pKTsKICAgICAgICAgIHJldHVybiBfbWV0YWwuY29tcHV0ZWQuYXBwbHkodm9pZCAwLCBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpLmNvbmNhdChbdGhpc10pKTsKICAgICAgICB9CiAgICAgIH0sCgogICAgICAvKioKICAgICAgICBUaGUgYG9ic2VydmVzYCBleHRlbnNpb24gb2YgSmF2YXNjcmlwdCdzIEZ1bmN0aW9uIHByb3RvdHlwZSBpcyBhdmFpbGFibGUKICAgICAgICB3aGVuIGBFbWJlckVOVi5FWFRFTkRfUFJPVE9UWVBFU2Agb3IgYEVtYmVyRU5WLkVYVEVORF9QUk9UT1RZUEVTLkZ1bmN0aW9uYCBpcwogICAgICAgIHRydWUsIHdoaWNoIGlzIHRoZSBkZWZhdWx0LgogICAgICAgICBZb3UgY2FuIG9ic2VydmUgcHJvcGVydHkgY2hhbmdlcyBzaW1wbHkgYnkgYWRkaW5nIHRoZSBgb2JzZXJ2ZXNgCiAgICAgICAgY2FsbCB0byB0aGUgZW5kIG9mIHlvdXIgbWV0aG9kIGRlY2xhcmF0aW9ucyBpbiBjbGFzc2VzIHRoYXQgeW91IHdyaXRlLgogICAgICAgIEZvciBleGFtcGxlOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgICBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAgICAgdmFsdWVPYnNlcnZlcjogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIC8vIEV4ZWN1dGVzIHdoZW5ldmVyIHRoZSAidmFsdWUiIHByb3BlcnR5IGNoYW5nZXMKICAgICAgICAgIH0ub2JzZXJ2ZXMoJ3ZhbHVlJykKICAgICAgICB9KTsKICAgICAgICBgYGAKICAgICAgICAgSW4gdGhlIGZ1dHVyZSB0aGlzIG1ldGhvZCBtYXkgYmVjb21lIGFzeW5jaHJvbm91cy4KICAgICAgICAgU2VlIGBvYnNlcnZlcmAuCiAgICAgICAgIEBtZXRob2Qgb2JzZXJ2ZXMKICAgICAgICBAZm9yIEZ1bmN0aW9uCiAgICAgICAgQHB1YmxpYwogICAgICAqLwogICAgICBvYnNlcnZlczogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCJGdW5jdGlvbiBwcm90b3R5cGUgZXh0ZW5zaW9ucyBoYXZlIGJlZW4gZGVwcmVjYXRlZCwgcGxlYXNlIG1pZ3JhdGUgZnJvbSBmdW5jdGlvbigpe30ub2JzZXJ2ZXMoJ2ZvbycpIHRvIG9ic2VydmVyKCdmb28nLCBmdW5jdGlvbigpIHt9KS4iLCBmYWxzZSwgewogICAgICAgICAgICBpZDogJ2Z1bmN0aW9uLXByb3RvdHlwZS1leHRlbnNpb25zLm9ic2VydmVzJywKICAgICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vZGVwcmVjYXRpb25zLmVtYmVyanMuY29tL3YzLngjdG9jX2Z1bmN0aW9uLXByb3RvdHlwZS1leHRlbnNpb25zLW9ic2VydmVzJwogICAgICAgICAgfSkpOwogICAgICAgICAgcmV0dXJuIF9tZXRhbC5vYnNlcnZlci5hcHBseSh2b2lkIDAsIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykuY29uY2F0KFt0aGlzXSkpOwogICAgICAgIH0KICAgICAgfSwKCiAgICAgIC8qKgogICAgICAgIFRoZSBgb25gIGV4dGVuc2lvbiBvZiBKYXZhc2NyaXB0J3MgRnVuY3Rpb24gcHJvdG90eXBlIGlzIGF2YWlsYWJsZQogICAgICAgIHdoZW4gYEVtYmVyRU5WLkVYVEVORF9QUk9UT1RZUEVTYCBvciBgRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVMuRnVuY3Rpb25gIGlzCiAgICAgICAgdHJ1ZSwgd2hpY2ggaXMgdGhlIGRlZmF1bHQuCiAgICAgICAgIFlvdSBjYW4gbGlzdGVuIGZvciBldmVudHMgc2ltcGx5IGJ5IGFkZGluZyB0aGUgYG9uYCBjYWxsIHRvIHRoZSBlbmQgb2YKICAgICAgICB5b3VyIG1ldGhvZCBkZWNsYXJhdGlvbnMgaW4gY2xhc3NlcyBvciBtaXhpbnMgdGhhdCB5b3Ugd3JpdGUuIEZvciBleGFtcGxlOgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgICAgaW1wb3J0IE1peGluIGZyb20gJ0BlbWJlci9taXhpbic7CiAgICAgICAgIE1peGluLmNyZWF0ZSh7CiAgICAgICAgICBkb1NvbWV0aGluZ1dpdGhFbGVtZW50OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgLy8gRXhlY3V0ZXMgd2hlbmV2ZXIgdGhlICJkaWRJbnNlcnRFbGVtZW50IiBldmVudCBmaXJlcwogICAgICAgICAgfS5vbignZGlkSW5zZXJ0RWxlbWVudCcpCiAgICAgICAgfSk7CiAgICAgICAgYGBgCiAgICAgICAgIFNlZSBgQGVtYmVyL29iamVjdC9ldmVudGVkL29uYC4KICAgICAgICAgQG1ldGhvZCBvbgogICAgICAgIEBmb3IgRnVuY3Rpb24KICAgICAgICBAcHVibGljCiAgICAgICovCiAgICAgIG9uOiB7CiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgIGVudW1lcmFibGU6IGZhbHNlLAogICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgIHZhbHVlOiBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIkZ1bmN0aW9uIHByb3RvdHlwZSBleHRlbnNpb25zIGhhdmUgYmVlbiBkZXByZWNhdGVkLCBwbGVhc2UgbWlncmF0ZSBmcm9tIGZ1bmN0aW9uKCl7fS5vbignZm9vJykgdG8gb24oJ2ZvbycsIGZ1bmN0aW9uKCkge30pLiIsIGZhbHNlLCB7CiAgICAgICAgICAgIGlkOiAnZnVuY3Rpb24tcHJvdG90eXBlLWV4dGVuc2lvbnMub24nLAogICAgICAgICAgICB1bnRpbDogJzQuMC4wJywKICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9kZXByZWNhdGlvbnMuZW1iZXJqcy5jb20vdjMueCN0b2NfZnVuY3Rpb24tcHJvdG90eXBlLWV4dGVuc2lvbnMtb24nCiAgICAgICAgICB9KSk7CiAgICAgICAgICByZXR1cm4gX21ldGFsLm9uLmFwcGx5KHZvaWQgMCwgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKS5jb25jYXQoW3RoaXNdKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL2V4dC9yc3ZwIiwgWyJleHBvcnRzIiwgInJzdnAiLCAiQGVtYmVyL3J1bmxvb3AiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZXJyb3ItaGFuZGxpbmciLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgUlNWUCwgX3J1bmxvb3AsIF9lcnJvckhhbmRsaW5nLCBfZGVidWcpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLm9uZXJyb3JEZWZhdWx0ID0gb25lcnJvckRlZmF1bHQ7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKICBSU1ZQLmNvbmZpZ3VyZSgnYXN5bmMnLCBmdW5jdGlvbiAoY2FsbGJhY2ssIHByb21pc2UpIHsKICAgIF9ydW5sb29wLmJhY2tidXJuZXIuc2NoZWR1bGUoJ2FjdGlvbnMnLCBudWxsLCBjYWxsYmFjaywgcHJvbWlzZSk7CiAgfSk7CiAgUlNWUC5jb25maWd1cmUoJ2FmdGVyJywgZnVuY3Rpb24gKGNiKSB7CiAgICBfcnVubG9vcC5iYWNrYnVybmVyLnNjaGVkdWxlKF9ydW5sb29wLl9yc3ZwRXJyb3JRdWV1ZSwgbnVsbCwgY2IpOwogIH0pOwogIFJTVlAub24oJ2Vycm9yJywgb25lcnJvckRlZmF1bHQpOwoKICBmdW5jdGlvbiBvbmVycm9yRGVmYXVsdChyZWFzb24pIHsKICAgIHZhciBlcnJvciA9IGVycm9yRm9yKHJlYXNvbik7CgogICAgaWYgKGVycm9yKSB7CiAgICAgIHZhciBvdmVycmlkZURpc3BhdGNoID0gKDAsIF9lcnJvckhhbmRsaW5nLmdldERpc3BhdGNoT3ZlcnJpZGUpKCk7CgogICAgICBpZiAob3ZlcnJpZGVEaXNwYXRjaCkgewogICAgICAgIG92ZXJyaWRlRGlzcGF0Y2goZXJyb3IpOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IGVycm9yOwogICAgICB9CiAgICB9CiAgfQoKICBmdW5jdGlvbiBlcnJvckZvcihyZWFzb24pIHsKICAgIGlmICghcmVhc29uKSByZXR1cm47CgogICAgaWYgKHJlYXNvbi5lcnJvclRocm93bikgewogICAgICByZXR1cm4gdW53cmFwRXJyb3JUaHJvd24ocmVhc29uKTsKICAgIH0KCiAgICBpZiAocmVhc29uLm5hbWUgPT09ICdVbnJlY29nbml6ZWRVUkxFcnJvcicpIHsKICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIFVSTCAnIiArIHJlYXNvbi5tZXNzYWdlICsgIicgZGlkIG5vdCBtYXRjaCBhbnkgcm91dGVzIGluIHlvdXIgYXBwbGljYXRpb24iLCBmYWxzZSkpOwogICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKHJlYXNvbi5uYW1lID09PSAnVHJhbnNpdGlvbkFib3J0ZWQnKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICByZXR1cm4gcmVhc29uOwogIH0KCiAgZnVuY3Rpb24gdW53cmFwRXJyb3JUaHJvd24ocmVhc29uKSB7CiAgICB2YXIgZXJyb3IgPSByZWFzb24uZXJyb3JUaHJvd247CgogICAgaWYgKHR5cGVvZiBlcnJvciA9PT0gJ3N0cmluZycpIHsKICAgICAgZXJyb3IgPSBuZXcgRXJyb3IoZXJyb3IpOwogICAgfQoKICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlcnJvciwgJ19fcmVhc29uX3dpdGhfZXJyb3JfdGhyb3duX18nLCB7CiAgICAgIHZhbHVlOiByZWFzb24sCiAgICAgIGVudW1lcmFibGU6IGZhbHNlCiAgICB9KTsKICAgIHJldHVybiBlcnJvcjsKICB9CgogIHZhciBfZGVmYXVsdCA9IFJTVlA7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9pcy1lcXVhbCIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSBpc0VxdWFsOwoKICAvKioKICAgQG1vZHVsZSBAZW1iZXIvdXRpbHMKICAqLwoKICAvKioKICAgIENvbXBhcmVzIHR3byBvYmplY3RzLCByZXR1cm5pbmcgdHJ1ZSBpZiB0aGV5IGFyZSBlcXVhbC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGlzRXF1YWwgfSBmcm9tICdAZW1iZXIvdXRpbHMnOwogIAogICAgaXNFcXVhbCgnaGVsbG8nLCAnaGVsbG8nKTsgICAgICAgICAgICAgICAgICAgLy8gdHJ1ZQogICAgaXNFcXVhbCgxLCAyKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGBgYAogIAogICAgYGlzRXF1YWxgIGlzIGEgbW9yZSBzcGVjaWZpYyBjb21wYXJpc29uIHRoYW4gYSB0cmlwbGUgZXF1YWwgY29tcGFyaXNvbi4KICAgIEl0IHdpbGwgY2FsbCB0aGUgYGlzRXF1YWxgIGluc3RhbmNlIG1ldGhvZCBvbiB0aGUgb2JqZWN0cyBiZWluZwogICAgY29tcGFyZWQsIGFsbG93aW5nIGZpbmVyIGNvbnRyb2wgb3ZlciB3aGVuIG9iamVjdHMgc2hvdWxkIGJlIGNvbnNpZGVyZWQKICAgIGVxdWFsIHRvIGVhY2ggb3RoZXIuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBpc0VxdWFsIH0gZnJvbSAnQGVtYmVyL3V0aWxzJzsKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGxldCBQZXJzb24gPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBpc0VxdWFsKG90aGVyKSB7IHJldHVybiB0aGlzLnNzbiA9PSBvdGhlci5zc247IH0KICAgIH0pOwogIAogICAgbGV0IHBlcnNvbkEgPSBQZXJzb24uY3JlYXRlKHtuYW1lOiAnTXVoYW1tYWQgQWxpJywgc3NuOiAnMTIzLTQ1LTY3ODknfSk7CiAgICBsZXQgcGVyc29uQiA9IFBlcnNvbi5jcmVhdGUoe25hbWU6ICdDYXNzaXVzIENsYXknLCBzc246ICcxMjMtNDUtNjc4OSd9KTsKICAKICAgIGlzRXF1YWwocGVyc29uQSwgcGVyc29uQik7IC8vIHRydWUKICAgIGBgYAogIAogICAgRHVlIHRvIHRoZSBleHBlbnNlIG9mIGFycmF5IGNvbXBhcmlzb25zLCBjb2xsZWN0aW9ucyB3aWxsIG5ldmVyIGJlIGVxdWFsIHRvCiAgICBlYWNoIG90aGVyIGV2ZW4gaWYgZWFjaCBvZiB0aGVpciBpdGVtcyBhcmUgZXF1YWwgdG8gZWFjaCBvdGhlci4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGlzRXF1YWwgfSBmcm9tICdAZW1iZXIvdXRpbHMnOwogIAogICAgaXNFcXVhbChbNCwgMl0sIFs0LCAyXSk7ICAgICAgICAgICAgICAgICAgICAgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQG1ldGhvZCBpc0VxdWFsCiAgICBAZm9yIEBlbWJlci91dGlscwogICAgQHN0YXRpYwogICAgQHBhcmFtIHtPYmplY3R9IGEgZmlyc3Qgb2JqZWN0IHRvIGNvbXBhcmUKICAgIEBwYXJhbSB7T2JqZWN0fSBiIHNlY29uZCBvYmplY3QgdG8gY29tcGFyZQogICAgQHJldHVybiB7Qm9vbGVhbn0KICAgIEBwdWJsaWMKICAqLwogIGZ1bmN0aW9uIGlzRXF1YWwoYSwgYikgewogICAgaWYgKGEgJiYgdHlwZW9mIGEuaXNFcXVhbCA9PT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gYS5pc0VxdWFsKGIpOwogICAgfQoKICAgIGlmIChhIGluc3RhbmNlb2YgRGF0ZSAmJiBiIGluc3RhbmNlb2YgRGF0ZSkgewogICAgICByZXR1cm4gYS5nZXRUaW1lKCkgPT09IGIuZ2V0VGltZSgpOwogICAgfQoKICAgIHJldHVybiBhID09PSBiOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zLy1wcm94eSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZ2xpbW1lci9yZWZlcmVuY2UiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YSwgX21ldGFsLCBfdXRpbHMsIF9kZWJ1ZywgX3JlZmVyZW5jZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuY29udGVudEZvciA9IGNvbnRlbnRGb3I7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgdmFyIF9NaXhpbiRjcmVhdGU7CgogIGZ1bmN0aW9uIGNvbnRlbnRGb3IocHJveHksIG0pIHsKICAgIHZhciBjb250ZW50ID0gKDAsIF9tZXRhbC5nZXQpKHByb3h5LCAnY29udGVudCcpOwogICAgdmFyIHRhZyA9IChtID09PSB1bmRlZmluZWQgPyAoMCwgX21ldGEubWV0YSkocHJveHkpIDogbSkucmVhZGFibGVUYWcoKTsKCiAgICBpZiAodGFnICE9PSB1bmRlZmluZWQpIHsKICAgICAgKDAsIF9yZWZlcmVuY2UudXBkYXRlKSh0YWcsICgwLCBfbWV0YWwudGFnRm9yKShjb250ZW50KSk7CiAgICB9CgogICAgcmV0dXJuIGNvbnRlbnQ7CiAgfQogIC8qKgogICAgYEVtYmVyLlByb3h5TWl4aW5gIGZvcndhcmRzIGFsbCBwcm9wZXJ0aWVzIG5vdCBkZWZpbmVkIGJ5IHRoZSBwcm94eSBpdHNlbGYKICAgIHRvIGEgcHJveGllZCBgY29udGVudGAgb2JqZWN0LiAgU2VlIE9iamVjdFByb3h5IGZvciBtb3JlIGRldGFpbHMuCiAgCiAgICBAY2xhc3MgUHJveHlNaXhpbgogICAgQG5hbWVzcGFjZSBFbWJlcgogICAgQHByaXZhdGUKICAqLwoKCiAgdmFyIF9kZWZhdWx0ID0gX21ldGFsLk1peGluLmNyZWF0ZSgoX01peGluJGNyZWF0ZSA9IHsKICAgIC8qKgogICAgICBUaGUgb2JqZWN0IHdob3NlIHByb3BlcnRpZXMgd2lsbCBiZSBmb3J3YXJkZWQuCiAgICAgICBAcHJvcGVydHkgY29udGVudAogICAgICBAdHlwZSB7dW5rbm93bn0KICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwogICAgY29udGVudDogbnVsbCwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAoMCwgX3V0aWxzLnNldFByb3h5KSh0aGlzKTsKICAgICAgdmFyIG0gPSAoMCwgX21ldGEubWV0YSkodGhpcyk7CiAgICAgIG0ud3JpdGFibGVUYWcoKTsKICAgIH0sCiAgICB3aWxsRGVzdHJveTogZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIHRoaXMuc2V0KCdjb250ZW50JywgbnVsbCk7CgogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfSwKICAgIGlzVHJ1dGh5OiAoMCwgX21ldGFsLmNvbXB1dGVkKSgnY29udGVudCcsIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIEJvb2xlYW4oKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdjb250ZW50JykpOwogICAgfSksCiAgICB3aWxsV2F0Y2hQcm9wZXJ0eTogZnVuY3Rpb24gd2lsbFdhdGNoUHJvcGVydHkoa2V5KSB7CiAgICAgIGlmICghdHJ1ZQogICAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICAgKSB7CiAgICAgICAgICB2YXIgY29udGVudEtleSA9ICJjb250ZW50LiIgKyBrZXk7CiAgICAgICAgICAoMCwgX21ldGFsLmFkZE9ic2VydmVyKSh0aGlzLCBjb250ZW50S2V5LCBudWxsLCAnX2NvbnRlbnRQcm9wZXJ0eURpZENoYW5nZScpOwogICAgICAgIH0KICAgIH0sCiAgICBkaWRVbndhdGNoUHJvcGVydHk6IGZ1bmN0aW9uIGRpZFVud2F0Y2hQcm9wZXJ0eShrZXkpIHsKICAgICAgaWYgKCF0cnVlCiAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICApIHsKICAgICAgICAgIHZhciBjb250ZW50S2V5ID0gImNvbnRlbnQuIiArIGtleTsKICAgICAgICAgICgwLCBfbWV0YWwucmVtb3ZlT2JzZXJ2ZXIpKHRoaXMsIGNvbnRlbnRLZXksIG51bGwsICdfY29udGVudFByb3BlcnR5RGlkQ2hhbmdlJyk7CiAgICAgICAgfQogICAgfSwKICAgIF9jb250ZW50UHJvcGVydHlEaWRDaGFuZ2U6IGZ1bmN0aW9uIF9jb250ZW50UHJvcGVydHlEaWRDaGFuZ2UoY29udGVudCwgY29udGVudEtleSkgewogICAgICB2YXIga2V5ID0gY29udGVudEtleS5zbGljZSg4KTsgLy8gcmVtb3ZlICJjb250ZW50LiIKCiAgICAgIGlmIChrZXkgaW4gdGhpcykgewogICAgICAgIHJldHVybjsKICAgICAgfSAvLyBpZiBzaGFkb3dlZCBpbiBwcm94eQoKCiAgICAgICgwLCBfbWV0YWwubm90aWZ5UHJvcGVydHlDaGFuZ2UpKHRoaXMsIGtleSk7CiAgICB9CiAgfSwgX01peGluJGNyZWF0ZVtfbWV0YWwuVU5LTk9XTl9QUk9QRVJUWV9UQUddID0gZnVuY3Rpb24gKGtleSkgewogICAgcmV0dXJuICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKCgwLCBfbWV0YWwuZ2V0Q2hhaW5UYWdzRm9yS2V5KSh0aGlzLCAiY29udGVudC4iICsga2V5KSk7CiAgfSwgX01peGluJGNyZWF0ZS51bmtub3duUHJvcGVydHkgPSBmdW5jdGlvbiB1bmtub3duUHJvcGVydHkoa2V5KSB7CiAgICB2YXIgY29udGVudCA9IGNvbnRlbnRGb3IodGhpcyk7CgogICAgaWYgKGNvbnRlbnQpIHsKICAgICAgcmV0dXJuICgwLCBfbWV0YWwuZ2V0KShjb250ZW50LCBrZXkpOwogICAgfQogIH0sIF9NaXhpbiRjcmVhdGUuc2V0VW5rbm93blByb3BlcnR5ID0gZnVuY3Rpb24gc2V0VW5rbm93blByb3BlcnR5KGtleSwgdmFsdWUpIHsKICAgIHZhciBtID0gKDAsIF9tZXRhLm1ldGEpKHRoaXMpOwoKICAgIGlmIChtLmlzSW5pdGlhbGl6aW5nKCkgfHwgbS5pc1Byb3RvdHlwZU1ldGEodGhpcykpIHsKICAgICAgLy8gaWYgbWFya2VkIGFzIHByb3RvdHlwZSBvciBvYmplY3QgaXMgaW5pdGlhbGl6aW5nIHRoZW4ganVzdAogICAgICAvLyBkZWZpbmVQcm9wZXJ0eSByYXRoZXIgdGhhbiBkZWxlZ2F0ZQogICAgICAoMCwgX21ldGFsLmRlZmluZVByb3BlcnR5KSh0aGlzLCBrZXksIG51bGwsIHZhbHVlKTsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQoKICAgIHZhciBjb250ZW50ID0gY29udGVudEZvcih0aGlzLCBtKTsKICAgIChmYWxzZSAmJiAhKGNvbnRlbnQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2Fubm90IGRlbGVnYXRlIHNldCgnIiArIGtleSArICInLCAiICsgdmFsdWUgKyAiKSB0byB0aGUgJ2NvbnRlbnQnIHByb3BlcnR5IG9mIG9iamVjdCBwcm94eSAiICsgdGhpcyArICI6IGl0cyAnY29udGVudCcgaXMgdW5kZWZpbmVkLiIsIGNvbnRlbnQpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLnNldCkoY29udGVudCwga2V5LCB2YWx1ZSk7CiAgfSwgX01peGluJGNyZWF0ZSkpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9hY3Rpb25faGFuZGxlciIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwsIF9kZWJ1ZykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgYEVtYmVyLkFjdGlvbkhhbmRsZXJgIGlzIGF2YWlsYWJsZSBvbiBzb21lIGZhbWlsaWFyIGNsYXNzZXMgaW5jbHVkaW5nCiAgICBgUm91dGVgLCBgQ29tcG9uZW50YCwgYW5kIGBDb250cm9sbGVyYC4KICAgIChJbnRlcm5hbGx5IHRoZSBtaXhpbiBpcyB1c2VkIGJ5IGBFbWJlci5Db3JlVmlld2AsIGBFbWJlci5Db250cm9sbGVyTWl4aW5gLAogICAgYW5kIGBSb3V0ZWAgYW5kIGF2YWlsYWJsZSB0byB0aGUgYWJvdmUgY2xhc3NlcyB0aHJvdWdoCiAgICBpbmhlcml0YW5jZS4pCiAgCiAgICBAY2xhc3MgQWN0aW9uSGFuZGxlcgogICAgQG5hbWVzcGFjZSBFbWJlcgogICAgQHByaXZhdGUKICAqLwogIHZhciBBY3Rpb25IYW5kbGVyID0gX21ldGFsLk1peGluLmNyZWF0ZSh7CiAgICBtZXJnZWRQcm9wZXJ0aWVzOiBbJ2FjdGlvbnMnXSwKCiAgICAvKioKICAgICAgVGhlIGNvbGxlY3Rpb24gb2YgZnVuY3Rpb25zLCBrZXllZCBieSBuYW1lLCBhdmFpbGFibGUgb24gdGhpcwogICAgICBgQWN0aW9uSGFuZGxlcmAgYXMgYWN0aW9uIHRhcmdldHMuCiAgICAgICBUaGVzZSBmdW5jdGlvbnMgd2lsbCBiZSBpbnZva2VkIHdoZW4gYSBtYXRjaGluZyBge3thY3Rpb259fWAgaXMgdHJpZ2dlcmVkCiAgICAgIGZyb20gd2l0aGluIGEgdGVtcGxhdGUgYW5kIHRoZSBhcHBsaWNhdGlvbidzIGN1cnJlbnQgcm91dGUgaXMgdGhpcyByb3V0ZS4KICAgICAgIEFjdGlvbnMgY2FuIGFsc28gYmUgaW52b2tlZCBmcm9tIG90aGVyIHBhcnRzIG9mIHlvdXIgYXBwbGljYXRpb24KICAgICAgdmlhIGBBY3Rpb25IYW5kbGVyI3NlbmRgLgogICAgICAgVGhlIGBhY3Rpb25zYCBoYXNoIHdpbGwgaW5oZXJpdCBhY3Rpb24gaGFuZGxlcnMgZnJvbQogICAgICB0aGUgYGFjdGlvbnNgIGhhc2ggZGVmaW5lZCBvbiBleHRlbmRlZCBwYXJlbnQgY2xhc3NlcwogICAgICBvciBtaXhpbnMgcmF0aGVyIHRoYW4ganVzdCByZXBsYWNlIHRoZSBlbnRpcmUgaGFzaCwgZS5nLjoKICAgICAgIGBgYGFwcC9taXhpbnMvY2FuLWRpc3BsYXktYmFubmVyLmpzCiAgICAgIGltcG9ydCBNaXhpbiBmcm9tICdAZW1iZXIvbWl4aW4nOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTWl4aW4uY3JlYXRlKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBkaXNwbGF5QmFubmVyKG1zZykgewogICAgICAgICAgICAvLyAuLi4KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIGBgYGFwcC9yb3V0ZXMvd2VsY29tZS5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICBpbXBvcnQgQ2FuRGlzcGxheUJhbm5lciBmcm9tICcuLi9taXhpbnMvY2FuLWRpc3BsYXktYmFubmVyJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZChDYW5EaXNwbGF5QmFubmVyLCB7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgcGxheU11c2ljKCkgewogICAgICAgICAgICAvLyAuLi4KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICAgLy8gYFdlbGNvbWVSb3V0ZWAsIHdoZW4gYWN0aXZlLCB3aWxsIGJlIGFibGUgdG8gcmVzcG9uZAogICAgICAvLyB0byBib3RoIGFjdGlvbnMsIHNpbmNlIHRoZSBhY3Rpb25zIGhhc2ggaXMgbWVyZ2VkIHJhdGhlcgogICAgICAvLyB0aGVuIHJlcGxhY2VkIHdoZW4gZXh0ZW5kaW5nIG1peGlucyAvIHBhcmVudCBjbGFzc2VzLgogICAgICB0aGlzLnNlbmQoJ2Rpc3BsYXlCYW5uZXInKTsKICAgICAgdGhpcy5zZW5kKCdwbGF5TXVzaWMnKTsKICAgICAgYGBgCiAgICAgICBXaXRoaW4gYSBDb250cm9sbGVyLCBSb3V0ZSBvciBDb21wb25lbnQncyBhY3Rpb24gaGFuZGxlciwKICAgICAgdGhlIHZhbHVlIG9mIHRoZSBgdGhpc2AgY29udGV4dCBpcyB0aGUgQ29udHJvbGxlciwgUm91dGUgb3IKICAgICAgQ29tcG9uZW50IG9iamVjdDoKICAgICAgIGBgYGFwcC9yb3V0ZXMvc29uZy5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBteUFjdGlvbigpIHsKICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyRm9yKCJzb25nIik7CiAgICAgICAgICAgIHRoaXMudHJhbnNpdGlvblRvKCJvdGhlci5yb3V0ZSIpOwogICAgICAgICAgICAuLi4KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEl0IGlzIGFsc28gcG9zc2libGUgdG8gY2FsbCBgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKWAgZnJvbSB3aXRoaW4gYW4KICAgICAgYWN0aW9uIGhhbmRsZXIgaWYgaXQgb3ZlcnJpZGVzIGEgaGFuZGxlciBkZWZpbmVkIG9uIGEgcGFyZW50CiAgICAgIGNsYXNzIG9yIG1peGluOgogICAgICAgVGFrZSBmb3IgZXhhbXBsZSB0aGUgZm9sbG93aW5nIHJvdXRlczoKICAgICAgIGBgYGFwcC9taXhpbnMvZGVidWctcm91dGUuanMKICAgICAgaW1wb3J0IE1peGluIGZyb20gJ0BlbWJlci9taXhpbic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBNaXhpbi5jcmVhdGUoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIGRlYnVnUm91dGVJbmZvcm1hdGlvbigpIHsKICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygiSXQncyBhLW1lLCBjb25zb2xlLmRlYnVnISIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgYXBwL3JvdXRlcy9hbm5veWluZy1kZWJ1Zy5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICBpbXBvcnQgRGVidWdSb3V0ZSBmcm9tICcuLi9taXhpbnMvZGVidWctcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKERlYnVnUm91dGUsIHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBkZWJ1Z1JvdXRlSW5mb3JtYXRpb24oKSB7CiAgICAgICAgICAgIC8vIGFsc28gY2FsbCB0aGUgZGVidWdSb3V0ZUluZm9ybWF0aW9uIG9mIG1peGVkIGluIERlYnVnUm91dGUKICAgICAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICAgICAgIC8vIHNob3cgYWRkaXRpb25hbCBhbm5veWFuY2UKICAgICAgICAgICAgd2luZG93LmFsZXJ0KC4uLik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAjIyBCdWJibGluZwogICAgICAgQnkgZGVmYXVsdCwgYW4gYWN0aW9uIHdpbGwgc3RvcCBidWJibGluZyBvbmNlIGEgaGFuZGxlciBkZWZpbmVkCiAgICAgIG9uIHRoZSBgYWN0aW9uc2AgaGFzaCBoYW5kbGVzIGl0LiBUbyBjb250aW51ZSBidWJibGluZyB0aGUgYWN0aW9uLAogICAgICB5b3UgbXVzdCByZXR1cm4gYHRydWVgIGZyb20gdGhlIGhhbmRsZXI6CiAgICAgICBgYGBhcHAvcm91dGVyLmpzCiAgICAgIFJvdXRlci5tYXAoZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5yb3V0ZSgiYWxidW0iLCBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMucm91dGUoInNvbmciKTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgYXBwL3JvdXRlcy9hbGJ1bS5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBzdGFydFBsYXlpbmc6IGZ1bmN0aW9uKCkgewogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgYXBwL3JvdXRlcy9hbGJ1bS1zb25nLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHN0YXJ0UGxheWluZygpIHsKICAgICAgICAgICAgLy8gLi4uCiAgICAgICAgICAgICBpZiAoYWN0aW9uU2hvdWxkQWxzb0JlVHJpZ2dlcmVkT25QYXJlbnRSb3V0ZSkgewogICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAcHJvcGVydHkgYWN0aW9ucwogICAgICBAdHlwZSBPYmplY3QKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBUcmlnZ2VycyBhIG5hbWVkIGFjdGlvbiBvbiB0aGUgYEFjdGlvbkhhbmRsZXJgLiBBbnkgcGFyYW1ldGVycwogICAgICBzdXBwbGllZCBhZnRlciB0aGUgYGFjdGlvbk5hbWVgIHN0cmluZyB3aWxsIGJlIHBhc3NlZCBhcyBhcmd1bWVudHMKICAgICAgdG8gdGhlIGFjdGlvbiB0YXJnZXQgZnVuY3Rpb24uCiAgICAgICBJZiB0aGUgYEFjdGlvbkhhbmRsZXJgIGhhcyBpdHMgYHRhcmdldGAgcHJvcGVydHkgc2V0LCBhY3Rpb25zIG1heQogICAgICBidWJibGUgdG8gdGhlIGB0YXJnZXRgLiBCdWJibGluZyBoYXBwZW5zIHdoZW4gYW4gYGFjdGlvbk5hbWVgIGNhbgogICAgICBub3QgYmUgZm91bmQgaW4gdGhlIGBBY3Rpb25IYW5kbGVyYCdzIGBhY3Rpb25zYCBoYXNoIG9yIGlmIHRoZQogICAgICBhY3Rpb24gdGFyZ2V0IGZ1bmN0aW9uIHJldHVybnMgYHRydWVgLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3JvdXRlcy93ZWxjb21lLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHBsYXlUaGVtZSgpIHsKICAgICAgICAgICAgdGhpcy5zZW5kKCdwbGF5TXVzaWMnLCAndGhlbWUubXAzJyk7CiAgICAgICAgICB9LAogICAgICAgICAgcGxheU11c2ljKHRyYWNrKSB7CiAgICAgICAgICAgIC8vIC4uLgogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZW5kCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBhY3Rpb25OYW1lIFRoZSBhY3Rpb24gdG8gdHJpZ2dlcgogICAgICBAcGFyYW0geyp9IGNvbnRleHQgYSBjb250ZXh0IHRvIHNlbmQgd2l0aCB0aGUgYWN0aW9uCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBzZW5kOiBmdW5jdGlvbiBzZW5kKGFjdGlvbk5hbWUpIHsKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5ID0gMTsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleSAtIDFdID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc0Rlc3Ryb3lpbmcgJiYgIXRoaXMuaXNEZXN0cm95ZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQXR0ZW1wdGVkIHRvIGNhbGwgLnNlbmQoKSB3aXRoIHRoZSBhY3Rpb24gJyIgKyBhY3Rpb25OYW1lICsgIicgb24gdGhlIGRlc3Ryb3llZCBvYmplY3QgJyIgKyB0aGlzICsgIicuIiwgIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSk7CgogICAgICBpZiAodGhpcy5hY3Rpb25zICYmIHRoaXMuYWN0aW9uc1thY3Rpb25OYW1lXSkgewogICAgICAgIHZhciBzaG91bGRCdWJibGUgPSB0aGlzLmFjdGlvbnNbYWN0aW9uTmFtZV0uYXBwbHkodGhpcywgYXJncykgPT09IHRydWU7CgogICAgICAgIGlmICghc2hvdWxkQnViYmxlKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgdGFyZ2V0ID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICd0YXJnZXQnKTsKCiAgICAgIGlmICh0YXJnZXQpIHsKICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgdGFyZ2V0LnNlbmQgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIGB0YXJnZXRgIGZvciAiICsgdGhpcyArICIgKCIgKyB0YXJnZXQgKyAiKSBkb2VzIG5vdCBoYXZlIGEgYHNlbmRgIG1ldGhvZCIsIHR5cGVvZiB0YXJnZXQuc2VuZCA9PT0gJ2Z1bmN0aW9uJykpOwogICAgICAgIHRhcmdldC5zZW5kLmFwcGx5KHRhcmdldCwgYXJndW1lbnRzKTsKICAgICAgfQogICAgfQogIH0pOwoKICB2YXIgX2RlZmF1bHQgPSBBY3Rpb25IYW5kbGVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2FycmF5IiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvZW51bWVyYWJsZSIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9jb21wYXJlIiwgIkBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9vYnNlcnZhYmxlIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9tdXRhYmxlX2VudW1lcmFibGUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvdHlwZS1vZiJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX3V0aWxzLCBfZGVidWcsIF9lbnVtZXJhYmxlLCBfY29tcGFyZSwgX2Vudmlyb25tZW50LCBfb2JzZXJ2YWJsZSwgX211dGFibGVfZW51bWVyYWJsZSwgX3R5cGVPZikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMudW5pcUJ5ID0gX3VuaXFCeTsKICBfZXhwb3J0cy5yZW1vdmVBdCA9IF9yZW1vdmVBdDsKICBfZXhwb3J0cy5pc0FycmF5ID0gaXNBcnJheTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2V4cG9ydHMuTXV0YWJsZUFycmF5ID0gX2V4cG9ydHMuTmF0aXZlQXJyYXkgPSBfZXhwb3J0cy5BID0gdm9pZCAwOwoKICB2YXIgX01peGluJGNyZWF0ZSwgX05hdGl2ZUFycmF5OwoKICB2YXIgRU1QVFlfQVJSQVkgPSBPYmplY3QuZnJlZXplKFtdKTsKCiAgdmFyIGlkZW50aXR5RnVuY3Rpb24gPSBmdW5jdGlvbiBpZGVudGl0eUZ1bmN0aW9uKGl0ZW0pIHsKICAgIHJldHVybiBpdGVtOwogIH07CgogIGZ1bmN0aW9uIF91bmlxQnkoYXJyYXksIGtleSkgewogICAgaWYgKGtleSA9PT0gdm9pZCAwKSB7CiAgICAgIGtleSA9IGlkZW50aXR5RnVuY3Rpb247CiAgICB9CgogICAgKGZhbHNlICYmICEoaXNBcnJheShhcnJheSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiZmlyc3QgYXJndW1lbnQgcGFzc2VkIHRvIGB1bmlxQnlgIHNob3VsZCBiZSBhcnJheSIsIGlzQXJyYXkoYXJyYXkpKSk7CgogICAgdmFyIHJldCA9IF9BMigpOwoKICAgIHZhciBzZWVuID0gbmV3IFNldCgpOwogICAgdmFyIGdldHRlciA9IHR5cGVvZiBrZXkgPT09ICdmdW5jdGlvbicgPyBrZXkgOiBmdW5jdGlvbiAoaXRlbSkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKGl0ZW0sIGtleSk7CiAgICB9OwogICAgYXJyYXkuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkgewogICAgICB2YXIgdmFsID0gZ2V0dGVyKGl0ZW0pOwoKICAgICAgaWYgKCFzZWVuLmhhcyh2YWwpKSB7CiAgICAgICAgc2Vlbi5hZGQodmFsKTsKICAgICAgICByZXQucHVzaChpdGVtKTsKICAgICAgfQogICAgfSk7CiAgICByZXR1cm4gcmV0OwogIH0KCiAgZnVuY3Rpb24gaXRlcihrZXksIHZhbHVlKSB7CiAgICB2YXIgdmFsdWVQcm92aWRlZCA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDI7CiAgICByZXR1cm4gdmFsdWVQcm92aWRlZCA/IGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgIHJldHVybiB2YWx1ZSA9PT0gKDAsIF9tZXRhbC5nZXQpKGl0ZW0sIGtleSk7CiAgICB9IDogZnVuY3Rpb24gKGl0ZW0pIHsKICAgICAgcmV0dXJuIEJvb2xlYW4oKDAsIF9tZXRhbC5nZXQpKGl0ZW0sIGtleSkpOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIGZpbmRJbmRleChhcnJheSwgcHJlZGljYXRlLCBzdGFydEF0KSB7CiAgICB2YXIgbGVuID0gYXJyYXkubGVuZ3RoOwoKICAgIGZvciAodmFyIGluZGV4ID0gc3RhcnRBdDsgaW5kZXggPCBsZW47IGluZGV4KyspIHsKICAgICAgdmFyIGl0ZW0gPSAoMCwgX21ldGFsLm9iamVjdEF0KShhcnJheSwgaW5kZXgpOwoKICAgICAgaWYgKHByZWRpY2F0ZShpdGVtLCBpbmRleCwgYXJyYXkpKSB7CiAgICAgICAgcmV0dXJuIGluZGV4OwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIC0xOwogIH0KCiAgZnVuY3Rpb24gX2ZpbmQoYXJyYXksIGNhbGxiYWNrLCB0YXJnZXQpIHsKICAgIHZhciBwcmVkaWNhdGUgPSBjYWxsYmFjay5iaW5kKHRhcmdldCk7CiAgICB2YXIgaW5kZXggPSBmaW5kSW5kZXgoYXJyYXksIHByZWRpY2F0ZSwgMCk7CiAgICByZXR1cm4gaW5kZXggPT09IC0xID8gdW5kZWZpbmVkIDogKDAsIF9tZXRhbC5vYmplY3RBdCkoYXJyYXksIGluZGV4KTsKICB9CgogIGZ1bmN0aW9uIF9hbnkoYXJyYXksIGNhbGxiYWNrLCB0YXJnZXQpIHsKICAgIHZhciBwcmVkaWNhdGUgPSBjYWxsYmFjay5iaW5kKHRhcmdldCk7CiAgICByZXR1cm4gZmluZEluZGV4KGFycmF5LCBwcmVkaWNhdGUsIDApICE9PSAtMTsKICB9CgogIGZ1bmN0aW9uIF9ldmVyeShhcnJheSwgY2FsbGJhY2ssIHRhcmdldCkgewogICAgdmFyIGNiID0gY2FsbGJhY2suYmluZCh0YXJnZXQpOwoKICAgIHZhciBwcmVkaWNhdGUgPSBmdW5jdGlvbiBwcmVkaWNhdGUoaXRlbSwgaW5kZXgsIGFycmF5KSB7CiAgICAgIHJldHVybiAhY2IoaXRlbSwgaW5kZXgsIGFycmF5KTsKICAgIH07CgogICAgcmV0dXJuIGZpbmRJbmRleChhcnJheSwgcHJlZGljYXRlLCAwKSA9PT0gLTE7CiAgfQoKICBmdW5jdGlvbiBfaW5kZXhPZihhcnJheSwgdmFsLCBzdGFydEF0LCB3aXRoTmFOQ2hlY2spIHsKICAgIGlmIChzdGFydEF0ID09PSB2b2lkIDApIHsKICAgICAgc3RhcnRBdCA9IDA7CiAgICB9CgogICAgdmFyIGxlbiA9IGFycmF5Lmxlbmd0aDsKCiAgICBpZiAoc3RhcnRBdCA8IDApIHsKICAgICAgc3RhcnRBdCArPSBsZW47CiAgICB9IC8vIFNhbWVWYWx1ZVplcm8gY29tcGFyaXNvbiAoTmFOICE9PSBOYU4pCgoKICAgIHZhciBwcmVkaWNhdGUgPSB3aXRoTmFOQ2hlY2sgJiYgdmFsICE9PSB2YWwgPyBmdW5jdGlvbiAoaXRlbSkgewogICAgICByZXR1cm4gaXRlbSAhPT0gaXRlbTsKICAgIH0gOiBmdW5jdGlvbiAoaXRlbSkgewogICAgICByZXR1cm4gaXRlbSA9PT0gdmFsOwogICAgfTsKICAgIHJldHVybiBmaW5kSW5kZXgoYXJyYXksIHByZWRpY2F0ZSwgc3RhcnRBdCk7CiAgfQoKICBmdW5jdGlvbiBfcmVtb3ZlQXQoYXJyYXksIGluZGV4LCBsZW4pIHsKICAgIGlmIChsZW4gPT09IHZvaWQgMCkgewogICAgICBsZW4gPSAxOwogICAgfQoKICAgIChmYWxzZSAmJiAhKGluZGV4ID4gLTEgJiYgaW5kZXggPCBhcnJheS5sZW5ndGgpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiYHJlbW92ZUF0YCBpbmRleCBwcm92aWRlZCBpcyBvdXQgb2YgcmFuZ2UiLCBpbmRleCA+IC0xICYmIGluZGV4IDwgYXJyYXkubGVuZ3RoKSk7CiAgICAoMCwgX21ldGFsLnJlcGxhY2UpKGFycmF5LCBpbmRleCwgbGVuLCBFTVBUWV9BUlJBWSk7CiAgICByZXR1cm4gYXJyYXk7CiAgfQoKICBmdW5jdGlvbiBfaW5zZXJ0QXQoYXJyYXksIGluZGV4LCBpdGVtKSB7CiAgICAoZmFsc2UgJiYgIShpbmRleCA+IC0xICYmIGluZGV4IDw9IGFycmF5Lmxlbmd0aCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJgaW5zZXJ0QXRgIGluZGV4IHByb3ZpZGVkIGlzIG91dCBvZiByYW5nZSIsIGluZGV4ID4gLTEgJiYgaW5kZXggPD0gYXJyYXkubGVuZ3RoKSk7CiAgICAoMCwgX21ldGFsLnJlcGxhY2UpKGFycmF5LCBpbmRleCwgMCwgW2l0ZW1dKTsKICAgIHJldHVybiBpdGVtOwogIH0KICAvKioKICAgIFJldHVybnMgdHJ1ZSBpZiB0aGUgcGFzc2VkIG9iamVjdCBpcyBhbiBhcnJheSBvciBBcnJheS1saWtlLgogIAogICAgT2JqZWN0cyBhcmUgY29uc2lkZXJlZCBBcnJheS1saWtlIGlmIGFueSBvZiB0aGUgZm9sbG93aW5nIGFyZSB0cnVlOgogIAogICAgICAtIHRoZSBvYmplY3QgaXMgYSBuYXRpdmUgQXJyYXkKICAgICAgLSB0aGUgb2JqZWN0IGhhcyBhbiBvYmplY3RBdCBwcm9wZXJ0eQogICAgICAtIHRoZSBvYmplY3QgaXMgYW4gT2JqZWN0LCBhbmQgaGFzIGEgbGVuZ3RoIHByb3BlcnR5CiAgCiAgICBVbmxpa2UgYHR5cGVPZmAgdGhpcyBtZXRob2QgcmV0dXJucyB0cnVlIGV2ZW4gaWYgdGhlIHBhc3NlZCBvYmplY3QgaXMKICAgIG5vdCBmb3JtYWxseSBhbiBhcnJheSBidXQgYXBwZWFycyB0byBiZSBhcnJheS1saWtlIChpLmUuIGltcGxlbWVudHMgYEFycmF5YCkKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGlzQXJyYXkgfSBmcm9tICdAZW1iZXIvYXJyYXknOwogICAgaW1wb3J0IEFycmF5UHJveHkgZnJvbSAnQGVtYmVyL2FycmF5L3Byb3h5JzsKICAKICAgIGlzQXJyYXkoKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZhbHNlCiAgICBpc0FycmF5KFtdKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0cnVlCiAgICBpc0FycmF5KEFycmF5UHJveHkuY3JlYXRlKHsgY29udGVudDogW10gfSkpOyAgICAvLyB0cnVlCiAgICBgYGAKICAKICAgIEBtZXRob2QgaXNBcnJheQogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvYXJyYXkKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byB0ZXN0CiAgICBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHRoZSBwYXNzZWQgb2JqZWN0IGlzIGFuIGFycmF5IG9yIEFycmF5LWxpa2UKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gaXNBcnJheShfb2JqKSB7CiAgICB2YXIgb2JqID0gX29iajsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICAmJiBfdXRpbHMuSEFTX05BVElWRV9QUk9YWSAmJiB0eXBlb2YgX29iaiA9PT0gJ29iamVjdCcgJiYgX29iaiAhPT0gbnVsbCkgewogICAgICB2YXIgcG9zc2libGVQcm94eUNvbnRlbnQgPSBfb2JqW19tZXRhbC5QUk9YWV9DT05URU5UXTsKCiAgICAgIGlmIChwb3NzaWJsZVByb3h5Q29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgb2JqID0gcG9zc2libGVQcm94eUNvbnRlbnQ7CiAgICAgIH0KICAgIH0KCiAgICBpZiAoIW9iaiB8fCBvYmouc2V0SW50ZXJ2YWwpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikgfHwgQXJyYXlNaXhpbi5kZXRlY3Qob2JqKSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICB2YXIgdHlwZSA9ICgwLCBfdHlwZU9mLnR5cGVPZikob2JqKTsKCiAgICBpZiAoJ2FycmF5JyA9PT0gdHlwZSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICB2YXIgbGVuZ3RoID0gb2JqLmxlbmd0aDsKCiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PT0gJ251bWJlcicgJiYgbGVuZ3RoID09PSBsZW5ndGggJiYgJ29iamVjdCcgPT09IHR5cGUpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgcmV0dXJuIGZhbHNlOwogIH0KICAvKgogICAgVGhpcyBhbGxvd3MgdXMgdG8gZGVmaW5lIGNvbXB1dGVkIHByb3BlcnRpZXMgdGhhdCBhcmUgbm90IGVudW1lcmFibGUuCiAgICBUaGUgcHJpbWFyeSByZWFzb24gdGhpcyBpcyBpbXBvcnRhbnQgaXMgdGhhdCB3aGVuIGBOYXRpdmVBcnJheWAgaXMKICAgIGFwcGxpZWQgdG8gYEFycmF5LnByb3RvdHlwZWAgd2UgbmVlZCB0byBlbnN1cmUgdGhhdCB3ZSBkbyBub3QgYWRkIF9hbnlfCiAgICBuZXcgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLgogICovCgoKICBmdW5jdGlvbiBub25FbnVtZXJhYmxlQ29tcHV0ZWQoKSB7CiAgICB2YXIgcHJvcGVydHkgPSBfbWV0YWwuY29tcHV0ZWQuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpOwoKICAgIHByb3BlcnR5LmVudW1lcmFibGUgPSBmYWxzZTsKICAgIHJldHVybiBwcm9wZXJ0eTsKICB9CgogIGZ1bmN0aW9uIG1hcEJ5KGtleSkgewogICAgcmV0dXJuIHRoaXMubWFwKGZ1bmN0aW9uIChuZXh0KSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkobmV4dCwga2V5KTsKICAgIH0pOwogIH0gLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogIC8vIEFSUkFZCiAgLy8KCiAgLyoqCiAgICBUaGlzIG1peGluIGltcGxlbWVudHMgT2JzZXJ2ZXItZnJpZW5kbHkgQXJyYXktbGlrZSBiZWhhdmlvci4gSXQgaXMgbm90IGEKICAgIGNvbmNyZXRlIGltcGxlbWVudGF0aW9uLCBidXQgaXQgY2FuIGJlIHVzZWQgdXAgYnkgb3RoZXIgY2xhc3NlcyB0aGF0IHdhbnQKICAgIHRvIGFwcGVhciBsaWtlIGFycmF5cy4KICAKICAgIEZvciBleGFtcGxlLCBBcnJheVByb3h5IGlzIGEgY29uY3JldGUgY2xhc3NlcyB0aGF0IGNhbgogICAgYmUgaW5zdGFudGlhdGVkIHRvIGltcGxlbWVudCBhcnJheS1saWtlIGJlaGF2aW9yLiBCb3RoIG9mIHRoZXNlIGNsYXNzZXMgdXNlCiAgICB0aGUgQXJyYXkgTWl4aW4gYnkgd2F5IG9mIHRoZSBNdXRhYmxlQXJyYXkgbWl4aW4sIHdoaWNoIGFsbG93cyBvYnNlcnZhYmxlCiAgICBjaGFuZ2VzIHRvIGJlIG1hZGUgdG8gdGhlIHVuZGVybHlpbmcgYXJyYXkuCiAgCiAgICBUaGlzIG1peGluIGRlZmluZXMgbWV0aG9kcyBzcGVjaWZpY2FsbHkgZm9yIGNvbGxlY3Rpb25zIHRoYXQgcHJvdmlkZQogICAgaW5kZXgtb3JkZXJlZCBhY2Nlc3MgdG8gdGhlaXIgY29udGVudHMuIFdoZW4geW91IGFyZSBkZXNpZ25pbmcgY29kZSB0aGF0CiAgICBuZWVkcyB0byBhY2NlcHQgYW55IGtpbmQgb2YgQXJyYXktbGlrZSBvYmplY3QsIHlvdSBzaG91bGQgdXNlIHRoZXNlIG1ldGhvZHMKICAgIGluc3RlYWQgb2YgQXJyYXkgcHJpbWl0aXZlcyBiZWNhdXNlIHRoZXNlIHdpbGwgcHJvcGVybHkgbm90aWZ5IG9ic2VydmVycyBvZgogICAgY2hhbmdlcyB0byB0aGUgYXJyYXkuCiAgCiAgICBBbHRob3VnaCB0aGVzZSBtZXRob2RzIGFyZSBlZmZpY2llbnQsIHRoZXkgZG8gYWRkIGEgbGF5ZXIgb2YgaW5kaXJlY3Rpb24gdG8KICAgIHlvdXIgYXBwbGljYXRpb24gc28gaXQgaXMgYSBnb29kIGlkZWEgdG8gdXNlIHRoZW0gb25seSB3aGVuIHlvdSBuZWVkIHRoZQogICAgZmxleGliaWxpdHkgb2YgdXNpbmcgYm90aCB0cnVlIEphdmFTY3JpcHQgYXJyYXlzIGFuZCAidmlydHVhbCIgYXJyYXlzIHN1Y2gKICAgIGFzIGNvbnRyb2xsZXJzIGFuZCBjb2xsZWN0aW9ucy4KICAKICAgIFlvdSBjYW4gdXNlIHRoZSBtZXRob2RzIGRlZmluZWQgaW4gdGhpcyBtb2R1bGUgdG8gYWNjZXNzIGFuZCBtb2RpZnkgYXJyYXkKICAgIGNvbnRlbnRzIGluIGEgS1ZPLWZyaWVuZGx5IHdheS4gWW91IGNhbiBhbHNvIGJlIG5vdGlmaWVkIHdoZW5ldmVyIHRoZQogICAgbWVtYmVyc2hpcCBvZiBhbiBhcnJheSBjaGFuZ2VzIGJ5IHVzaW5nIGAub2JzZXJ2ZXMoJ215QXJyYXkuW10nKWAuCiAgCiAgICBUbyBzdXBwb3J0IGBFbWJlckFycmF5YCBpbiB5b3VyIG93biBjbGFzcywgeW91IG11c3Qgb3ZlcnJpZGUgdHdvCiAgICBwcmltaXRpdmVzIHRvIHVzZSBpdDogYGxlbmd0aCgpYCBhbmQgYG9iamVjdEF0KClgLgogIAogICAgQGNsYXNzIEVtYmVyQXJyYXkKICAgIEB1c2VzIEVudW1lcmFibGUKICAgIEBzaW5jZSBFbWJlciAwLjkuMAogICAgQHB1YmxpYwogICovCgoKICB2YXIgQXJyYXlNaXhpbiA9IF9tZXRhbC5NaXhpbi5jcmVhdGUoX2VudW1lcmFibGUuZGVmYXVsdCwgKF9NaXhpbiRjcmVhdGUgPSB7fSwgX01peGluJGNyZWF0ZVtfdXRpbHMuRU1CRVJfQVJSQVldID0gdHJ1ZSwgX01peGluJGNyZWF0ZS5vYmplY3RzQXQgPSBmdW5jdGlvbiBvYmplY3RzQXQoaW5kZXhlcykgewogICAgdmFyIF90aGlzID0gdGhpczsKCiAgICByZXR1cm4gaW5kZXhlcy5tYXAoZnVuY3Rpb24gKGlkeCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5vYmplY3RBdCkoX3RoaXMsIGlkeCk7CiAgICB9KTsKICB9LCBfTWl4aW4kY3JlYXRlWydbXSddID0gbm9uRW51bWVyYWJsZUNvbXB1dGVkKHsKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH0sCiAgICBzZXQ6IGZ1bmN0aW9uIHNldChrZXksIHZhbHVlKSB7CiAgICAgIHRoaXMucmVwbGFjZSgwLCB0aGlzLmxlbmd0aCwgdmFsdWUpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0KICB9KSwgX01peGluJGNyZWF0ZS5maXJzdE9iamVjdCA9IG5vbkVudW1lcmFibGVDb21wdXRlZChmdW5jdGlvbiAoKSB7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5vYmplY3RBdCkodGhpcywgMCk7CiAgfSkucmVhZE9ubHkoKSwgX01peGluJGNyZWF0ZS5sYXN0T2JqZWN0ID0gbm9uRW51bWVyYWJsZUNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgIHJldHVybiAoMCwgX21ldGFsLm9iamVjdEF0KSh0aGlzLCB0aGlzLmxlbmd0aCAtIDEpOwogIH0pLnJlYWRPbmx5KCksIF9NaXhpbiRjcmVhdGUuc2xpY2UgPSBmdW5jdGlvbiBzbGljZShiZWdpbkluZGV4LCBlbmRJbmRleCkgewogICAgaWYgKGJlZ2luSW5kZXggPT09IHZvaWQgMCkgewogICAgICBiZWdpbkluZGV4ID0gMDsKICAgIH0KCiAgICB2YXIgcmV0ID0gX0EyKCk7CgogICAgdmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoOwoKICAgIGlmIChiZWdpbkluZGV4IDwgMCkgewogICAgICBiZWdpbkluZGV4ID0gbGVuZ3RoICsgYmVnaW5JbmRleDsKICAgIH0KCiAgICBpZiAoZW5kSW5kZXggPT09IHVuZGVmaW5lZCB8fCBlbmRJbmRleCA+IGxlbmd0aCkgewogICAgICBlbmRJbmRleCA9IGxlbmd0aDsKICAgIH0gZWxzZSBpZiAoZW5kSW5kZXggPCAwKSB7CiAgICAgIGVuZEluZGV4ID0gbGVuZ3RoICsgZW5kSW5kZXg7CiAgICB9CgogICAgd2hpbGUgKGJlZ2luSW5kZXggPCBlbmRJbmRleCkgewogICAgICByZXRbcmV0Lmxlbmd0aF0gPSAoMCwgX21ldGFsLm9iamVjdEF0KSh0aGlzLCBiZWdpbkluZGV4KyspOwogICAgfQoKICAgIHJldHVybiByZXQ7CiAgfSwgX01peGluJGNyZWF0ZS5pbmRleE9mID0gZnVuY3Rpb24gaW5kZXhPZihvYmplY3QsIHN0YXJ0QXQpIHsKICAgIHJldHVybiBfaW5kZXhPZih0aGlzLCBvYmplY3QsIHN0YXJ0QXQsIGZhbHNlKTsKICB9LCBfTWl4aW4kY3JlYXRlLmxhc3RJbmRleE9mID0gZnVuY3Rpb24gbGFzdEluZGV4T2Yob2JqZWN0LCBzdGFydEF0KSB7CiAgICB2YXIgbGVuID0gdGhpcy5sZW5ndGg7CgogICAgaWYgKHN0YXJ0QXQgPT09IHVuZGVmaW5lZCB8fCBzdGFydEF0ID49IGxlbikgewogICAgICBzdGFydEF0ID0gbGVuIC0gMTsKICAgIH0KCiAgICBpZiAoc3RhcnRBdCA8IDApIHsKICAgICAgc3RhcnRBdCArPSBsZW47CiAgICB9CgogICAgZm9yICh2YXIgaWR4ID0gc3RhcnRBdDsgaWR4ID49IDA7IGlkeC0tKSB7CiAgICAgIGlmICgoMCwgX21ldGFsLm9iamVjdEF0KSh0aGlzLCBpZHgpID09PSBvYmplY3QpIHsKICAgICAgICByZXR1cm4gaWR4OwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIC0xOwogIH0sIF9NaXhpbiRjcmVhdGUuYWRkQXJyYXlPYnNlcnZlciA9IGZ1bmN0aW9uIGFkZEFycmF5T2JzZXJ2ZXIodGFyZ2V0LCBvcHRzKSB7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5hZGRBcnJheU9ic2VydmVyKSh0aGlzLCB0YXJnZXQsIG9wdHMpOwogIH0sIF9NaXhpbiRjcmVhdGUucmVtb3ZlQXJyYXlPYnNlcnZlciA9IGZ1bmN0aW9uIHJlbW92ZUFycmF5T2JzZXJ2ZXIodGFyZ2V0LCBvcHRzKSB7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5yZW1vdmVBcnJheU9ic2VydmVyKSh0aGlzLCB0YXJnZXQsIG9wdHMpOwogIH0sIF9NaXhpbiRjcmVhdGUuaGFzQXJyYXlPYnNlcnZlcnMgPSBub25FbnVtZXJhYmxlQ29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgcmV0dXJuICgwLCBfbWV0YWwuaGFzTGlzdGVuZXJzKSh0aGlzLCAnQGFycmF5OmNoYW5nZScpIHx8ICgwLCBfbWV0YWwuaGFzTGlzdGVuZXJzKSh0aGlzLCAnQGFycmF5OmJlZm9yZScpOwogIH0pLCBfTWl4aW4kY3JlYXRlLmFycmF5Q29udGVudFdpbGxDaGFuZ2UgPSBmdW5jdGlvbiBhcnJheUNvbnRlbnRXaWxsQ2hhbmdlKHN0YXJ0SWR4LCByZW1vdmVBbXQsIGFkZEFtdCkgewogICAgcmV0dXJuICgwLCBfbWV0YWwuYXJyYXlDb250ZW50V2lsbENoYW5nZSkodGhpcywgc3RhcnRJZHgsIHJlbW92ZUFtdCwgYWRkQW10KTsKICB9LCBfTWl4aW4kY3JlYXRlLmFycmF5Q29udGVudERpZENoYW5nZSA9IGZ1bmN0aW9uIGFycmF5Q29udGVudERpZENoYW5nZShzdGFydElkeCwgcmVtb3ZlQW10LCBhZGRBbXQpIHsKICAgIHJldHVybiAoMCwgX21ldGFsLmFycmF5Q29udGVudERpZENoYW5nZSkodGhpcywgc3RhcnRJZHgsIHJlbW92ZUFtdCwgYWRkQW10KTsKICB9LCBfTWl4aW4kY3JlYXRlLmZvckVhY2ggPSBmdW5jdGlvbiBmb3JFYWNoKGNhbGxiYWNrLCB0YXJnZXQpIHsKICAgIGlmICh0YXJnZXQgPT09IHZvaWQgMCkgewogICAgICB0YXJnZXQgPSBudWxsOwogICAgfQoKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdgZm9yRWFjaGAgZXhwZWN0cyBhIGZ1bmN0aW9uIGFzIGZpcnN0IGFyZ3VtZW50LicsIHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykpOwogICAgdmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoOwoKICAgIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHsKICAgICAgdmFyIGl0ZW0gPSB0aGlzLm9iamVjdEF0KGluZGV4KTsKICAgICAgY2FsbGJhY2suY2FsbCh0YXJnZXQsIGl0ZW0sIGluZGV4LCB0aGlzKTsKICAgIH0KCiAgICByZXR1cm4gdGhpczsKICB9LCBfTWl4aW4kY3JlYXRlLmdldEVhY2ggPSBtYXBCeSwgX01peGluJGNyZWF0ZS5zZXRFYWNoID0gZnVuY3Rpb24gc2V0RWFjaChrZXksIHZhbHVlKSB7CiAgICByZXR1cm4gdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLnNldCkoaXRlbSwga2V5LCB2YWx1ZSk7CiAgICB9KTsKICB9LCBfTWl4aW4kY3JlYXRlLm1hcCA9IGZ1bmN0aW9uIG1hcChjYWxsYmFjaywgdGFyZ2V0KSB7CiAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgdGFyZ2V0ID0gbnVsbDsKICAgIH0KCiAgICAoZmFsc2UgJiYgISh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYG1hcGAgZXhwZWN0cyBhIGZ1bmN0aW9uIGFzIGZpcnN0IGFyZ3VtZW50LicsIHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykpOwoKICAgIHZhciByZXQgPSBfQTIoKTsKCiAgICB0aGlzLmZvckVhY2goZnVuY3Rpb24gKHgsIGlkeCwgaSkgewogICAgICByZXR1cm4gcmV0W2lkeF0gPSBjYWxsYmFjay5jYWxsKHRhcmdldCwgeCwgaWR4LCBpKTsKICAgIH0pOwogICAgcmV0dXJuIHJldDsKICB9LCBfTWl4aW4kY3JlYXRlLm1hcEJ5ID0gbWFwQnksIF9NaXhpbiRjcmVhdGUuZmlsdGVyID0gZnVuY3Rpb24gZmlsdGVyKGNhbGxiYWNrLCB0YXJnZXQpIHsKICAgIGlmICh0YXJnZXQgPT09IHZvaWQgMCkgewogICAgICB0YXJnZXQgPSBudWxsOwogICAgfQoKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdgZmlsdGVyYCBleHBlY3RzIGEgZnVuY3Rpb24gYXMgZmlyc3QgYXJndW1lbnQuJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CgogICAgdmFyIHJldCA9IF9BMigpOwoKICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbiAoeCwgaWR4LCBpKSB7CiAgICAgIGlmIChjYWxsYmFjay5jYWxsKHRhcmdldCwgeCwgaWR4LCBpKSkgewogICAgICAgIHJldC5wdXNoKHgpOwogICAgICB9CiAgICB9KTsKICAgIHJldHVybiByZXQ7CiAgfSwgX01peGluJGNyZWF0ZS5yZWplY3QgPSBmdW5jdGlvbiByZWplY3QoY2FsbGJhY2ssIHRhcmdldCkgewogICAgaWYgKHRhcmdldCA9PT0gdm9pZCAwKSB7CiAgICAgIHRhcmdldCA9IG51bGw7CiAgICB9CgogICAgKGZhbHNlICYmICEodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2ByZWplY3RgIGV4cGVjdHMgYSBmdW5jdGlvbiBhcyBmaXJzdCBhcmd1bWVudC4nLCB0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpKTsKICAgIHJldHVybiB0aGlzLmZpbHRlcihmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAhY2FsbGJhY2suYXBwbHkodGFyZ2V0LCBhcmd1bWVudHMpOwogICAgfSk7CiAgfSwgX01peGluJGNyZWF0ZS5maWx0ZXJCeSA9IGZ1bmN0aW9uIGZpbHRlckJ5KCkgewogICAgcmV0dXJuIHRoaXMuZmlsdGVyKGl0ZXIuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpKTsKICB9LCBfTWl4aW4kY3JlYXRlLnJlamVjdEJ5ID0gZnVuY3Rpb24gcmVqZWN0QnkoKSB7CiAgICByZXR1cm4gdGhpcy5yZWplY3QoaXRlci5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cykpOwogIH0sIF9NaXhpbiRjcmVhdGUuZmluZCA9IGZ1bmN0aW9uIGZpbmQoY2FsbGJhY2ssIHRhcmdldCkgewogICAgaWYgKHRhcmdldCA9PT0gdm9pZCAwKSB7CiAgICAgIHRhcmdldCA9IG51bGw7CiAgICB9CgogICAgKGZhbHNlICYmICEodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2BmaW5kYCBleHBlY3RzIGEgZnVuY3Rpb24gYXMgZmlyc3QgYXJndW1lbnQuJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICByZXR1cm4gX2ZpbmQodGhpcywgY2FsbGJhY2ssIHRhcmdldCk7CiAgfSwgX01peGluJGNyZWF0ZS5maW5kQnkgPSBmdW5jdGlvbiBmaW5kQnkoKSB7CiAgICByZXR1cm4gX2ZpbmQodGhpcywgaXRlci5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cykpOwogIH0sIF9NaXhpbiRjcmVhdGUuZXZlcnkgPSBmdW5jdGlvbiBldmVyeShjYWxsYmFjaywgdGFyZ2V0KSB7CiAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgdGFyZ2V0ID0gbnVsbDsKICAgIH0KCiAgICAoZmFsc2UgJiYgISh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYGV2ZXJ5YCBleHBlY3RzIGEgZnVuY3Rpb24gYXMgZmlyc3QgYXJndW1lbnQuJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICByZXR1cm4gX2V2ZXJ5KHRoaXMsIGNhbGxiYWNrLCB0YXJnZXQpOwogIH0sIF9NaXhpbiRjcmVhdGUuaXNFdmVyeSA9IGZ1bmN0aW9uIGlzRXZlcnkoKSB7CiAgICByZXR1cm4gX2V2ZXJ5KHRoaXMsIGl0ZXIuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpKTsKICB9LCBfTWl4aW4kY3JlYXRlLmFueSA9IGZ1bmN0aW9uIGFueShjYWxsYmFjaywgdGFyZ2V0KSB7CiAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgdGFyZ2V0ID0gbnVsbDsKICAgIH0KCiAgICAoZmFsc2UgJiYgISh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYGFueWAgZXhwZWN0cyBhIGZ1bmN0aW9uIGFzIGZpcnN0IGFyZ3VtZW50LicsIHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykpOwogICAgcmV0dXJuIF9hbnkodGhpcywgY2FsbGJhY2ssIHRhcmdldCk7CiAgfSwgX01peGluJGNyZWF0ZS5pc0FueSA9IGZ1bmN0aW9uIGlzQW55KCkgewogICAgcmV0dXJuIF9hbnkodGhpcywgaXRlci5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cykpOwogIH0sIF9NaXhpbiRjcmVhdGUucmVkdWNlID0gZnVuY3Rpb24gcmVkdWNlKGNhbGxiYWNrLCBpbml0aWFsVmFsdWUpIHsKICAgIChmYWxzZSAmJiAhKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdgcmVkdWNlYCBleHBlY3RzIGEgZnVuY3Rpb24gYXMgZmlyc3QgYXJndW1lbnQuJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICB2YXIgcmV0ID0gaW5pdGlhbFZhbHVlOwogICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtLCBpKSB7CiAgICAgIHJldCA9IGNhbGxiYWNrKHJldCwgaXRlbSwgaSwgdGhpcyk7CiAgICB9LCB0aGlzKTsKICAgIHJldHVybiByZXQ7CiAgfSwgX01peGluJGNyZWF0ZS5pbnZva2UgPSBmdW5jdGlvbiBpbnZva2UobWV0aG9kTmFtZSkgewogICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5ID0gMTsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICBhcmdzW19rZXkgLSAxXSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgIH0KCiAgICB2YXIgcmV0ID0gX0EyKCk7CgogICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgIHJldHVybiByZXQucHVzaCgoMCwgX3V0aWxzLnRyeUludm9rZSkoaXRlbSwgbWV0aG9kTmFtZSwgYXJncykpOwogICAgfSk7CiAgICByZXR1cm4gcmV0OwogIH0sIF9NaXhpbiRjcmVhdGUudG9BcnJheSA9IGZ1bmN0aW9uIHRvQXJyYXkoKSB7CiAgICByZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24gKGl0ZW0pIHsKICAgICAgcmV0dXJuIGl0ZW07CiAgICB9KTsKICB9LCBfTWl4aW4kY3JlYXRlLmNvbXBhY3QgPSBmdW5jdGlvbiBjb21wYWN0KCkgewogICAgcmV0dXJuIHRoaXMuZmlsdGVyKGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICByZXR1cm4gdmFsdWUgIT0gbnVsbDsKICAgIH0pOwogIH0sIF9NaXhpbiRjcmVhdGUuaW5jbHVkZXMgPSBmdW5jdGlvbiBpbmNsdWRlcyhvYmplY3QsIHN0YXJ0QXQpIHsKICAgIHJldHVybiBfaW5kZXhPZih0aGlzLCBvYmplY3QsIHN0YXJ0QXQsIHRydWUpICE9PSAtMTsKICB9LCBfTWl4aW4kY3JlYXRlLnNvcnRCeSA9IGZ1bmN0aW9uIHNvcnRCeSgpIHsKICAgIHZhciBzb3J0S2V5cyA9IGFyZ3VtZW50czsKICAgIHJldHVybiB0aGlzLnRvQXJyYXkoKS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc29ydEtleXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIga2V5ID0gc29ydEtleXNbaV07CiAgICAgICAgdmFyIHByb3BBID0gKDAsIF9tZXRhbC5nZXQpKGEsIGtleSk7CiAgICAgICAgdmFyIHByb3BCID0gKDAsIF9tZXRhbC5nZXQpKGIsIGtleSk7IC8vIHJldHVybiAxIG9yIC0xIGVsc2UgY29udGludWUgdG8gdGhlIG5leHQgc29ydEtleQoKICAgICAgICB2YXIgY29tcGFyZVZhbHVlID0gKDAsIF9jb21wYXJlLmRlZmF1bHQpKHByb3BBLCBwcm9wQik7CgogICAgICAgIGlmIChjb21wYXJlVmFsdWUpIHsKICAgICAgICAgIHJldHVybiBjb21wYXJlVmFsdWU7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gMDsKICAgIH0pOwogIH0sIF9NaXhpbiRjcmVhdGUudW5pcSA9IGZ1bmN0aW9uIHVuaXEoKSB7CiAgICByZXR1cm4gX3VuaXFCeSh0aGlzKTsKICB9LCBfTWl4aW4kY3JlYXRlLnVuaXFCeSA9IGZ1bmN0aW9uIHVuaXFCeShrZXkpIHsKICAgIHJldHVybiBfdW5pcUJ5KHRoaXMsIGtleSk7CiAgfSwgX01peGluJGNyZWF0ZS53aXRob3V0ID0gZnVuY3Rpb24gd2l0aG91dCh2YWx1ZSkgewogICAgaWYgKCF0aGlzLmluY2x1ZGVzKHZhbHVlKSkgewogICAgICByZXR1cm4gdGhpczsgLy8gbm90aGluZyB0byBkbwogICAgfSAvLyBTYW1lVmFsdWVaZXJvIGNvbXBhcmlzb24gKE5hTiAhPT0gTmFOKQoKCiAgICB2YXIgcHJlZGljYXRlID0gdmFsdWUgPT09IHZhbHVlID8gZnVuY3Rpb24gKGl0ZW0pIHsKICAgICAgcmV0dXJuIGl0ZW0gIT09IHZhbHVlOwogICAgfSA6IGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgIHJldHVybiBpdGVtID09PSBpdGVtOwogICAgfTsKICAgIHJldHVybiB0aGlzLmZpbHRlcihwcmVkaWNhdGUpOwogIH0sIF9NaXhpbiRjcmVhdGUpKTsKICAvKioKICAgIFRoaXMgbWl4aW4gZGVmaW5lcyB0aGUgQVBJIGZvciBtb2RpZnlpbmcgYXJyYXktbGlrZSBvYmplY3RzLiBUaGVzZSBtZXRob2RzCiAgICBjYW4gYmUgYXBwbGllZCBvbmx5IHRvIGEgY29sbGVjdGlvbiB0aGF0IGtlZXBzIGl0cyBpdGVtcyBpbiBhbiBvcmRlcmVkIHNldC4KICAgIEl0IGJ1aWxkcyB1cG9uIHRoZSBBcnJheSBtaXhpbiBhbmQgYWRkcyBtZXRob2RzIHRvIG1vZGlmeSB0aGUgYXJyYXkuCiAgICBPbmUgY29uY3JldGUgaW1wbGVtZW50YXRpb25zIG9mIHRoaXMgY2xhc3MgaW5jbHVkZSBBcnJheVByb3h5LgogIAogICAgSXQgaXMgaW1wb3J0YW50IHRvIHVzZSB0aGUgbWV0aG9kcyBpbiB0aGlzIGNsYXNzIHRvIG1vZGlmeSBhcnJheXMgc28gdGhhdAogICAgY2hhbmdlcyBhcmUgb2JzZXJ2YWJsZS4gVGhpcyBhbGxvd3MgdGhlIGJpbmRpbmcgc3lzdGVtIGluIEVtYmVyIHRvIGZ1bmN0aW9uCiAgICBjb3JyZWN0bHkuCiAgCiAgCiAgICBOb3RlIHRoYXQgYW4gQXJyYXkgY2FuIGNoYW5nZSBldmVuIGlmIGl0IGRvZXMgbm90IGltcGxlbWVudCB0aGlzIG1peGluLgogICAgRm9yIGV4YW1wbGUsIG9uZSBtaWdodCBpbXBsZW1lbnQgYSBTcGFyc2VBcnJheSB0aGF0IGNhbm5vdCBiZSBkaXJlY3RseQogICAgbW9kaWZpZWQsIGJ1dCBpZiBpdHMgdW5kZXJseWluZyBlbnVtZXJhYmxlIGNoYW5nZXMsIGl0IHdpbGwgY2hhbmdlIGFsc28uCiAgCiAgICBAY2xhc3MgTXV0YWJsZUFycmF5CiAgICBAdXNlcyBFbWJlckFycmF5CiAgICBAdXNlcyBNdXRhYmxlRW51bWVyYWJsZQogICAgQHB1YmxpYwogICovCgoKICB2YXIgTXV0YWJsZUFycmF5ID0gX21ldGFsLk1peGluLmNyZWF0ZShBcnJheU1peGluLCBfbXV0YWJsZV9lbnVtZXJhYmxlLmRlZmF1bHQsIHsKICAgIC8qKgogICAgICBfX1JlcXVpcmVkLl9fIFlvdSBtdXN0IGltcGxlbWVudCB0aGlzIG1ldGhvZCB0byBhcHBseSB0aGlzIG1peGluLgogICAgICAgVGhpcyBpcyBvbmUgb2YgdGhlIHByaW1pdGl2ZXMgeW91IG11c3QgaW1wbGVtZW50IHRvIHN1cHBvcnQgYEFycmF5YC4KICAgICAgWW91IHNob3VsZCByZXBsYWNlIGFtdCBvYmplY3RzIHN0YXJ0ZWQgYXQgaWR4IHdpdGggdGhlIG9iamVjdHMgaW4gdGhlCiAgICAgIHBhc3NlZCBhcnJheS4gWW91IHNob3VsZCBhbHNvIGNhbGwgYHRoaXMuYXJyYXlDb250ZW50RGlkQ2hhbmdlKClgCiAgICAgICBOb3RlIHRoYXQgdGhpcyBtZXRob2QgaXMgZXhwZWN0ZWQgdG8gdmFsaWRhdGUgdGhlIHR5cGUocykgb2Ygb2JqZWN0cyB0aGF0IGl0IGV4cGVjdHMuCiAgICAgICBAbWV0aG9kIHJlcGxhY2UKICAgICAgQHBhcmFtIHtOdW1iZXJ9IGlkeCBTdGFydGluZyBpbmRleCBpbiB0aGUgYXJyYXkgdG8gcmVwbGFjZS4gSWYKICAgICAgICBpZHggPj0gbGVuZ3RoLCB0aGVuIGFwcGVuZCB0byB0aGUgZW5kIG9mIHRoZSBhcnJheS4KICAgICAgQHBhcmFtIHtOdW1iZXJ9IGFtdCBOdW1iZXIgb2YgZWxlbWVudHMgdGhhdCBzaG91bGQgYmUgcmVtb3ZlZCBmcm9tCiAgICAgICAgdGhlIGFycmF5LCBzdGFydGluZyBhdCAqaWR4Ki4KICAgICAgQHBhcmFtIHtFbWJlckFycmF5fSBvYmplY3RzIEFuIGFycmF5IG9mIHplcm8gb3IgbW9yZSBvYmplY3RzIHRoYXQgc2hvdWxkIGJlCiAgICAgICAgaW5zZXJ0ZWQgaW50byB0aGUgYXJyYXkgYXQgKmlkeCoKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgUmVtb3ZlIGFsbCBlbGVtZW50cyBmcm9tIHRoZSBhcnJheS4gVGhpcyBpcyB1c2VmdWwgaWYgeW91CiAgICAgIHdhbnQgdG8gcmV1c2UgYW4gZXhpc3RpbmcgYXJyYXkgd2l0aG91dCBoYXZpbmcgdG8gcmVjcmVhdGUgaXQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjb2xvcnMgPSBbJ3JlZCcsICdncmVlbicsICdibHVlJ107CiAgICAgICBjb2xvcnMubGVuZ3RoOyAgLy8gMwogICAgICBjb2xvcnMuY2xlYXIoKTsgLy8gW10KICAgICAgY29sb3JzLmxlbmd0aDsgIC8vIDAKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGNsZWFyCiAgICAgIEByZXR1cm4ge0FycmF5fSBBbiBlbXB0eSBBcnJheS4KICAgICAgQHB1YmxpYwogICAgKi8KICAgIGNsZWFyOiBmdW5jdGlvbiBjbGVhcigpIHsKICAgICAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoOwoKICAgICAgaWYgKGxlbiA9PT0gMCkgewogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICB0aGlzLnJlcGxhY2UoMCwgbGVuLCBFTVBUWV9BUlJBWSk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgVGhpcyB3aWxsIHVzZSB0aGUgcHJpbWl0aXZlIGByZXBsYWNlKClgIG1ldGhvZCB0byBpbnNlcnQgYW4gb2JqZWN0IGF0IHRoZQogICAgICBzcGVjaWZpZWQgaW5kZXguCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjb2xvcnMgPSBbJ3JlZCcsICdncmVlbicsICdibHVlJ107CiAgICAgICBjb2xvcnMuaW5zZXJ0QXQoMiwgJ3llbGxvdycpOyAgLy8gWydyZWQnLCAnZ3JlZW4nLCAneWVsbG93JywgJ2JsdWUnXQogICAgICBjb2xvcnMuaW5zZXJ0QXQoNSwgJ29yYW5nZScpOyAgLy8gRXJyb3I6IEluZGV4IG91dCBvZiByYW5nZQogICAgICBgYGAKICAgICAgIEBtZXRob2QgaW5zZXJ0QXQKICAgICAgQHBhcmFtIHtOdW1iZXJ9IGlkeCBpbmRleCBvZiBpbnNlcnQgdGhlIG9iamVjdCBhdC4KICAgICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdCBvYmplY3QgdG8gaW5zZXJ0CiAgICAgIEByZXR1cm4ge0VtYmVyQXJyYXl9IHJlY2VpdmVyCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBpbnNlcnRBdDogZnVuY3Rpb24gaW5zZXJ0QXQoaWR4LCBvYmplY3QpIHsKICAgICAgX2luc2VydEF0KHRoaXMsIGlkeCwgb2JqZWN0KTsKCiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgUmVtb3ZlIGFuIG9iamVjdCBhdCB0aGUgc3BlY2lmaWVkIGluZGV4IHVzaW5nIHRoZSBgcmVwbGFjZSgpYCBwcmltaXRpdmUKICAgICAgbWV0aG9kLiBZb3UgY2FuIHBhc3MgZWl0aGVyIGEgc2luZ2xlIGluZGV4LCBvciBhIHN0YXJ0IGFuZCBhIGxlbmd0aC4KICAgICAgIElmIHlvdSBwYXNzIGEgc3RhcnQgYW5kIGxlbmd0aCB0aGF0IGlzIGJleW9uZCB0aGUKICAgICAgbGVuZ3RoIHRoaXMgbWV0aG9kIHdpbGwgdGhyb3cgYW4gYXNzZXJ0aW9uLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgY29sb3JzID0gWydyZWQnLCAnZ3JlZW4nLCAnYmx1ZScsICd5ZWxsb3cnLCAnb3JhbmdlJ107CiAgICAgICBjb2xvcnMucmVtb3ZlQXQoMCk7ICAgICAvLyBbJ2dyZWVuJywgJ2JsdWUnLCAneWVsbG93JywgJ29yYW5nZSddCiAgICAgIGNvbG9ycy5yZW1vdmVBdCgyLCAyKTsgIC8vIFsnZ3JlZW4nLCAnYmx1ZSddCiAgICAgIGNvbG9ycy5yZW1vdmVBdCg0LCAyKTsgIC8vIEVycm9yOiBJbmRleCBvdXQgb2YgcmFuZ2UKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHJlbW92ZUF0CiAgICAgIEBwYXJhbSB7TnVtYmVyfSBzdGFydCBpbmRleCwgc3RhcnQgb2YgcmFuZ2UKICAgICAgQHBhcmFtIHtOdW1iZXJ9IGxlbiBsZW5ndGggb2YgcGFzc2luZyByYW5nZQogICAgICBAcmV0dXJuIHtFbWJlckFycmF5fSByZWNlaXZlcgogICAgICBAcHVibGljCiAgICAqLwogICAgcmVtb3ZlQXQ6IGZ1bmN0aW9uIHJlbW92ZUF0KHN0YXJ0LCBsZW4pIHsKICAgICAgcmV0dXJuIF9yZW1vdmVBdCh0aGlzLCBzdGFydCwgbGVuKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFB1c2ggdGhlIG9iamVjdCBvbnRvIHRoZSBlbmQgb2YgdGhlIGFycmF5LiBXb3JrcyBqdXN0IGxpa2UgYHB1c2goKWAgYnV0IGl0CiAgICAgIGlzIEtWTy1jb21wbGlhbnQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjb2xvcnMgPSBbJ3JlZCcsICdncmVlbiddOwogICAgICAgY29sb3JzLnB1c2hPYmplY3QoJ2JsYWNrJyk7ICAgICAvLyBbJ3JlZCcsICdncmVlbicsICdibGFjayddCiAgICAgIGNvbG9ycy5wdXNoT2JqZWN0KFsneWVsbG93J10pOyAgLy8gWydyZWQnLCAnZ3JlZW4nLCBbJ3llbGxvdyddXQogICAgICBgYGAKICAgICAgIEBtZXRob2QgcHVzaE9iamVjdAogICAgICBAcGFyYW0geyp9IG9iaiBvYmplY3QgdG8gcHVzaAogICAgICBAcmV0dXJuIG9iamVjdCBzYW1lIG9iamVjdCBwYXNzZWQgYXMgYSBwYXJhbQogICAgICBAcHVibGljCiAgICAqLwogICAgcHVzaE9iamVjdDogZnVuY3Rpb24gcHVzaE9iamVjdChvYmopIHsKICAgICAgcmV0dXJuIF9pbnNlcnRBdCh0aGlzLCB0aGlzLmxlbmd0aCwgb2JqKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEFkZCB0aGUgb2JqZWN0cyBpbiB0aGUgcGFzc2VkIGFycmF5IHRvIHRoZSBlbmQgb2YgdGhlIGFycmF5LiBEZWZlcnMKICAgICAgbm90aWZ5aW5nIG9ic2VydmVycyBvZiB0aGUgY2hhbmdlIHVudGlsIGFsbCBvYmplY3RzIGFyZSBhZGRlZC4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IGNvbG9ycyA9IFsncmVkJ107CiAgICAgICBjb2xvcnMucHVzaE9iamVjdHMoWyd5ZWxsb3cnLCAnb3JhbmdlJ10pOyAgLy8gWydyZWQnLCAneWVsbG93JywgJ29yYW5nZSddCiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBwdXNoT2JqZWN0cwogICAgICBAcGFyYW0ge0VtYmVyQXJyYXl9IG9iamVjdHMgdGhlIG9iamVjdHMgdG8gYWRkCiAgICAgIEByZXR1cm4ge0VtYmVyQXJyYXl9IHJlY2VpdmVyCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBwdXNoT2JqZWN0czogZnVuY3Rpb24gcHVzaE9iamVjdHMob2JqZWN0cykgewogICAgICB0aGlzLnJlcGxhY2UodGhpcy5sZW5ndGgsIDAsIG9iamVjdHMpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCgogICAgLyoqCiAgICAgIFBvcCBvYmplY3QgZnJvbSBhcnJheSBvciBuaWwgaWYgbm9uZSBhcmUgbGVmdC4gV29ya3MganVzdCBsaWtlIGBwb3AoKWAgYnV0CiAgICAgIGl0IGlzIEtWTy1jb21wbGlhbnQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjb2xvcnMgPSBbJ3JlZCcsICdncmVlbicsICdibHVlJ107CiAgICAgICBjb2xvcnMucG9wT2JqZWN0KCk7ICAgLy8gJ2JsdWUnCiAgICAgIGNvbnNvbGUubG9nKGNvbG9ycyk7ICAvLyBbJ3JlZCcsICdncmVlbiddCiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBwb3BPYmplY3QKICAgICAgQHJldHVybiBvYmplY3QKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHBvcE9iamVjdDogZnVuY3Rpb24gcG9wT2JqZWN0KCkgewogICAgICB2YXIgbGVuID0gdGhpcy5sZW5ndGg7CgogICAgICBpZiAobGVuID09PSAwKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KCiAgICAgIHZhciByZXQgPSAoMCwgX21ldGFsLm9iamVjdEF0KSh0aGlzLCBsZW4gLSAxKTsKICAgICAgdGhpcy5yZW1vdmVBdChsZW4gLSAxLCAxKTsKICAgICAgcmV0dXJuIHJldDsKICAgIH0sCgogICAgLyoqCiAgICAgIFNoaWZ0IGFuIG9iamVjdCBmcm9tIHN0YXJ0IG9mIGFycmF5IG9yIG5pbCBpZiBub25lIGFyZSBsZWZ0LiBXb3JrcyBqdXN0CiAgICAgIGxpa2UgYHNoaWZ0KClgIGJ1dCBpdCBpcyBLVk8tY29tcGxpYW50LgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgY29sb3JzID0gWydyZWQnLCAnZ3JlZW4nLCAnYmx1ZSddOwogICAgICAgY29sb3JzLnNoaWZ0T2JqZWN0KCk7ICAvLyAncmVkJwogICAgICBjb25zb2xlLmxvZyhjb2xvcnMpOyAgIC8vIFsnZ3JlZW4nLCAnYmx1ZSddCiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzaGlmdE9iamVjdAogICAgICBAcmV0dXJuIG9iamVjdAogICAgICBAcHVibGljCiAgICAqLwogICAgc2hpZnRPYmplY3Q6IGZ1bmN0aW9uIHNoaWZ0T2JqZWN0KCkgewogICAgICBpZiAodGhpcy5sZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIHJldCA9ICgwLCBfbWV0YWwub2JqZWN0QXQpKHRoaXMsIDApOwogICAgICB0aGlzLnJlbW92ZUF0KDApOwogICAgICByZXR1cm4gcmV0OwogICAgfSwKCiAgICAvKioKICAgICAgVW5zaGlmdCBhbiBvYmplY3QgdG8gc3RhcnQgb2YgYXJyYXkuIFdvcmtzIGp1c3QgbGlrZSBgdW5zaGlmdCgpYCBidXQgaXQgaXMKICAgICAgS1ZPLWNvbXBsaWFudC4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IGNvbG9ycyA9IFsncmVkJ107CiAgICAgICBjb2xvcnMudW5zaGlmdE9iamVjdCgneWVsbG93Jyk7ICAgIC8vIFsneWVsbG93JywgJ3JlZCddCiAgICAgIGNvbG9ycy51bnNoaWZ0T2JqZWN0KFsnYmxhY2snXSk7ICAgLy8gW1snYmxhY2snXSwgJ3llbGxvdycsICdyZWQnXQogICAgICBgYGAKICAgICAgIEBtZXRob2QgdW5zaGlmdE9iamVjdAogICAgICBAcGFyYW0geyp9IG9iaiBvYmplY3QgdG8gdW5zaGlmdAogICAgICBAcmV0dXJuIG9iamVjdCBzYW1lIG9iamVjdCBwYXNzZWQgYXMgYSBwYXJhbQogICAgICBAcHVibGljCiAgICAqLwogICAgdW5zaGlmdE9iamVjdDogZnVuY3Rpb24gdW5zaGlmdE9iamVjdChvYmopIHsKICAgICAgcmV0dXJuIF9pbnNlcnRBdCh0aGlzLCAwLCBvYmopOwogICAgfSwKCiAgICAvKioKICAgICAgQWRkcyB0aGUgbmFtZWQgb2JqZWN0cyB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBhcnJheS4gRGVmZXJzIG5vdGlmeWluZwogICAgICBvYnNlcnZlcnMgdW50aWwgYWxsIG9iamVjdHMgaGF2ZSBiZWVuIGFkZGVkLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgY29sb3JzID0gWydyZWQnXTsKICAgICAgIGNvbG9ycy51bnNoaWZ0T2JqZWN0cyhbJ2JsYWNrJywgJ3doaXRlJ10pOyAgIC8vIFsnYmxhY2snLCAnd2hpdGUnLCAncmVkJ10KICAgICAgY29sb3JzLnVuc2hpZnRPYmplY3RzKCd5ZWxsb3cnKTsgLy8gVHlwZSBFcnJvcjogJ3VuZGVmaW5lZCcgaXMgbm90IGEgZnVuY3Rpb24KICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHVuc2hpZnRPYmplY3RzCiAgICAgIEBwYXJhbSB7RW51bWJlcmFibGV9IG9iamVjdHMgdGhlIG9iamVjdHMgdG8gYWRkCiAgICAgIEByZXR1cm4ge0VtYmVyQXJyYXl9IHJlY2VpdmVyCiAgICAgIEBwdWJsaWMKICAgICovCiAgICB1bnNoaWZ0T2JqZWN0czogZnVuY3Rpb24gdW5zaGlmdE9iamVjdHMob2JqZWN0cykgewogICAgICB0aGlzLnJlcGxhY2UoMCwgMCwgb2JqZWN0cyk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgUmV2ZXJzZSBvYmplY3RzIGluIHRoZSBhcnJheS4gV29ya3MganVzdCBsaWtlIGByZXZlcnNlKClgIGJ1dCBpdCBpcwogICAgICBLVk8tY29tcGxpYW50LgogICAgICAgQG1ldGhvZCByZXZlcnNlT2JqZWN0cwogICAgICBAcmV0dXJuIHtFbWJlckFycmF5fSByZWNlaXZlcgogICAgICAgQHB1YmxpYwogICAgKi8KICAgIHJldmVyc2VPYmplY3RzOiBmdW5jdGlvbiByZXZlcnNlT2JqZWN0cygpIHsKICAgICAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoOwoKICAgICAgaWYgKGxlbiA9PT0gMCkgewogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICB2YXIgb2JqZWN0cyA9IHRoaXMudG9BcnJheSgpLnJldmVyc2UoKTsKICAgICAgdGhpcy5yZXBsYWNlKDAsIGxlbiwgb2JqZWN0cyk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgUmVwbGFjZSBhbGwgdGhlIHJlY2VpdmVyJ3MgY29udGVudCB3aXRoIGNvbnRlbnQgb2YgdGhlIGFyZ3VtZW50LgogICAgICBJZiBhcmd1bWVudCBpcyBhbiBlbXB0eSBhcnJheSByZWNlaXZlciB3aWxsIGJlIGNsZWFyZWQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjb2xvcnMgPSBbJ3JlZCcsICdncmVlbicsICdibHVlJ107CiAgICAgICBjb2xvcnMuc2V0T2JqZWN0cyhbJ2JsYWNrJywgJ3doaXRlJ10pOyAgLy8gWydibGFjaycsICd3aGl0ZSddCiAgICAgIGNvbG9ycy5zZXRPYmplY3RzKFtdKTsgICAgICAgICAgICAgICAgICAvLyBbXQogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc2V0T2JqZWN0cwogICAgICBAcGFyYW0ge0VtYmVyQXJyYXl9IG9iamVjdHMgYXJyYXkgd2hvc2UgY29udGVudCB3aWxsIGJlIHVzZWQgZm9yIHJlcGxhY2luZwogICAgICAgICAgdGhlIGNvbnRlbnQgb2YgdGhlIHJlY2VpdmVyCiAgICAgIEByZXR1cm4ge0VtYmVyQXJyYXl9IHJlY2VpdmVyIHdpdGggdGhlIG5ldyBjb250ZW50CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBzZXRPYmplY3RzOiBmdW5jdGlvbiBzZXRPYmplY3RzKG9iamVjdHMpIHsKICAgICAgaWYgKG9iamVjdHMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuY2xlYXIoKTsKICAgICAgfQoKICAgICAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoOwogICAgICB0aGlzLnJlcGxhY2UoMCwgbGVuLCBvYmplY3RzKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgICBSZW1vdmUgYWxsIG9jY3VycmVuY2VzIG9mIGFuIG9iamVjdCBpbiB0aGUgYXJyYXkuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjaXRpZXMgPSBbJ0NoaWNhZ28nLCAnQmVybGluJywgJ0xpbWEnLCAnQ2hpY2FnbyddOwogICAgICAgY2l0aWVzLnJlbW92ZU9iamVjdCgnQ2hpY2FnbycpOyAgLy8gWydCZXJsaW4nLCAnTGltYSddCiAgICAgIGNpdGllcy5yZW1vdmVPYmplY3QoJ0xpbWEnKTsgICAgIC8vIFsnQmVybGluJ10KICAgICAgY2l0aWVzLnJlbW92ZU9iamVjdCgnVG9reW8nKSAgICAgLy8gWydCZXJsaW4nXQogICAgICBgYGAKICAgICAgIEBtZXRob2QgcmVtb3ZlT2JqZWN0CiAgICAgIEBwYXJhbSB7Kn0gb2JqIG9iamVjdCB0byByZW1vdmUKICAgICAgQHJldHVybiB7RW1iZXJBcnJheX0gcmVjZWl2ZXIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHJlbW92ZU9iamVjdDogZnVuY3Rpb24gcmVtb3ZlT2JqZWN0KG9iaikgewogICAgICB2YXIgbG9jID0gdGhpcy5sZW5ndGggfHwgMDsKCiAgICAgIHdoaWxlICgtLWxvYyA+PSAwKSB7CiAgICAgICAgdmFyIGN1ck9iamVjdCA9ICgwLCBfbWV0YWwub2JqZWN0QXQpKHRoaXMsIGxvYyk7CgogICAgICAgIGlmIChjdXJPYmplY3QgPT09IG9iaikgewogICAgICAgICAgdGhpcy5yZW1vdmVBdChsb2MpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgICBSZW1vdmVzIGVhY2ggb2JqZWN0IGluIHRoZSBwYXNzZWQgYXJyYXkgZnJvbSB0aGUgcmVjZWl2ZXIuCiAgICAgICBAbWV0aG9kIHJlbW92ZU9iamVjdHMKICAgICAgQHBhcmFtIHtFbWJlckFycmF5fSBvYmplY3RzIHRoZSBvYmplY3RzIHRvIHJlbW92ZQogICAgICBAcmV0dXJuIHtFbWJlckFycmF5fSByZWNlaXZlcgogICAgICBAcHVibGljCiAgICAqLwogICAgcmVtb3ZlT2JqZWN0czogZnVuY3Rpb24gcmVtb3ZlT2JqZWN0cyhvYmplY3RzKSB7CiAgICAgICgwLCBfbWV0YWwuYmVnaW5Qcm9wZXJ0eUNoYW5nZXMpKCk7CgogICAgICBmb3IgKHZhciBpID0gb2JqZWN0cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICAgIHRoaXMucmVtb3ZlT2JqZWN0KG9iamVjdHNbaV0pOwogICAgICB9CgogICAgICAoMCwgX21ldGFsLmVuZFByb3BlcnR5Q2hhbmdlcykoKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgICBQdXNoIHRoZSBvYmplY3Qgb250byB0aGUgZW5kIG9mIHRoZSBhcnJheSBpZiBpdCBpcyBub3QgYWxyZWFkeQogICAgICBwcmVzZW50IGluIHRoZSBhcnJheS4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IGNpdGllcyA9IFsnQ2hpY2FnbycsICdCZXJsaW4nXTsKICAgICAgIGNpdGllcy5hZGRPYmplY3QoJ0xpbWEnKTsgICAgLy8gWydDaGljYWdvJywgJ0JlcmxpbicsICdMaW1hJ10KICAgICAgY2l0aWVzLmFkZE9iamVjdCgnQmVybGluJyk7ICAvLyBbJ0NoaWNhZ28nLCAnQmVybGluJywgJ0xpbWEnXQogICAgICBgYGAKICAgICAgIEBtZXRob2QgYWRkT2JqZWN0CiAgICAgIEBwYXJhbSB7Kn0gb2JqIG9iamVjdCB0byBhZGQsIGlmIG5vdCBhbHJlYWR5IHByZXNlbnQKICAgICAgQHJldHVybiB7RW1iZXJBcnJheX0gcmVjZWl2ZXIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIGFkZE9iamVjdDogZnVuY3Rpb24gYWRkT2JqZWN0KG9iaikgewogICAgICB2YXIgaW5jbHVkZWQgPSB0aGlzLmluY2x1ZGVzKG9iaik7CgogICAgICBpZiAoIWluY2x1ZGVkKSB7CiAgICAgICAgdGhpcy5wdXNoT2JqZWN0KG9iaik7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgQWRkcyBlYWNoIG9iamVjdCBpbiB0aGUgcGFzc2VkIGFycmF5IHRvIHRoZSByZWNlaXZlci4KICAgICAgIEBtZXRob2QgYWRkT2JqZWN0cwogICAgICBAcGFyYW0ge0VtYmVyQXJyYXl9IG9iamVjdHMgdGhlIG9iamVjdHMgdG8gYWRkLgogICAgICBAcmV0dXJuIHtFbWJlckFycmF5fSByZWNlaXZlcgogICAgICBAcHVibGljCiAgICAqLwogICAgYWRkT2JqZWN0czogZnVuY3Rpb24gYWRkT2JqZWN0cyhvYmplY3RzKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgKDAsIF9tZXRhbC5iZWdpblByb3BlcnR5Q2hhbmdlcykoKTsKICAgICAgb2JqZWN0cy5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHsKICAgICAgICByZXR1cm4gX3RoaXMyLmFkZE9iamVjdChvYmopOwogICAgICB9KTsKICAgICAgKDAsIF9tZXRhbC5lbmRQcm9wZXJ0eUNoYW5nZXMpKCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfQogIH0pOwogIC8qKgogICAgQ3JlYXRlcyBhbiBgRW1iZXIuTmF0aXZlQXJyYXlgIGZyb20gYW4gQXJyYXktbGlrZSBvYmplY3QuCiAgICBEb2VzIG5vdCBtb2RpZnkgdGhlIG9yaWdpbmFsIG9iamVjdCdzIGNvbnRlbnRzLiBgQSgpYCBpcyBub3QgbmVlZGVkIGlmCiAgICBgRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVNgIGlzIGB0cnVlYCAodGhlIGRlZmF1bHQgdmFsdWUpLiBIb3dldmVyLAogICAgaXQgaXMgcmVjb21tZW5kZWQgdGhhdCB5b3UgdXNlIGBBKClgIHdoZW4gY3JlYXRpbmcgYWRkb25zIGZvcgogICAgZW1iZXIgb3Igd2hlbiB5b3UgY2FuIG5vdCBndWFyYW50ZWUgdGhhdCBgRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVNgCiAgICB3aWxsIGJlIGB0cnVlYC4KICAKICAgIEV4YW1wbGUKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL215LWNvbXBvbmVudC5qcwogICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgIGltcG9ydCB7IEEgfSBmcm9tICdAZW1iZXIvYXJyYXknOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIHRhZ05hbWU6ICd1bCcsCiAgICAgIGNsYXNzTmFtZXM6IFsncGFnaW5hdGlvbiddLAogIAogICAgICBpbml0KCkgewogICAgICAgIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cyk7CiAgCiAgICAgICAgaWYgKCF0aGlzLmdldCgnY29udGVudCcpKSB7CiAgICAgICAgICB0aGlzLnNldCgnY29udGVudCcsIEEoKSk7CiAgICAgICAgICB0aGlzLnNldCgnb3RoZXJDb250ZW50JywgQShbMSwyLDNdKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBBCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9hcnJheQogICAgQHJldHVybiB7RW1iZXIuTmF0aXZlQXJyYXl9CiAgICBAcHVibGljCiAgKi8KICAvLyBBZGQgRW1iZXIuQXJyYXkgdG8gQXJyYXkucHJvdG90eXBlLiBSZW1vdmUgbWV0aG9kcyB3aXRoIG5hdGl2ZQogIC8vIGltcGxlbWVudGF0aW9ucyBhbmQgc3VwcGx5IHNvbWUgbW9yZSBvcHRpbWl6ZWQgdmVyc2lvbnMgb2YgZ2VuZXJpYyBtZXRob2RzCiAgLy8gYmVjYXVzZSB0aGV5IGFyZSBzbyBjb21tb24uCgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIFRoZSBOYXRpdmVBcnJheSBtaXhpbiBjb250YWlucyB0aGUgcHJvcGVydGllcyBuZWVkZWQgdG8gbWFrZSB0aGUgbmF0aXZlCiAgICBBcnJheSBzdXBwb3J0IE11dGFibGVBcnJheSBhbmQgYWxsIG9mIGl0cyBkZXBlbmRlbnQgQVBJcy4gVW5sZXNzIHlvdQogICAgaGF2ZSBgRW1iZXJFTlYuRVhURU5EX1BST1RPVFlQRVNgIG9yIGBFbWJlckVOVi5FWFRFTkRfUFJPVE9UWVBFUy5BcnJheWAgc2V0IHRvCiAgICBmYWxzZSwgdGhpcyB3aWxsIGJlIGFwcGxpZWQgYXV0b21hdGljYWxseS4gT3RoZXJ3aXNlIHlvdSBjYW4gYXBwbHkgdGhlIG1peGluCiAgICBhdCBhbnl0aW1lIGJ5IGNhbGxpbmcgYEVtYmVyLk5hdGl2ZUFycmF5LmFwcGx5KEFycmF5LnByb3RvdHlwZSlgLgogIAogICAgQGNsYXNzIEVtYmVyLk5hdGl2ZUFycmF5CiAgICBAdXNlcyBNdXRhYmxlQXJyYXkKICAgIEB1c2VzIE9ic2VydmFibGUKICAgIEBwdWJsaWMKICAqLwoKCiAgX2V4cG9ydHMuTXV0YWJsZUFycmF5ID0gTXV0YWJsZUFycmF5OwoKICB2YXIgTmF0aXZlQXJyYXkgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKE11dGFibGVBcnJheSwgX29ic2VydmFibGUuZGVmYXVsdCwgewogICAgb2JqZWN0QXQ6IGZ1bmN0aW9uIG9iamVjdEF0KGlkeCkgewogICAgICByZXR1cm4gdGhpc1tpZHhdOwogICAgfSwKICAgIC8vIHByaW1pdGl2ZSBmb3IgYXJyYXkgc3VwcG9ydC4KICAgIHJlcGxhY2U6IGZ1bmN0aW9uIHJlcGxhY2Uoc3RhcnQsIGRlbGV0ZUNvdW50LCBpdGVtcykgewogICAgICBpZiAoaXRlbXMgPT09IHZvaWQgMCkgewogICAgICAgIGl0ZW1zID0gRU1QVFlfQVJSQVk7CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKEFycmF5LmlzQXJyYXkoaXRlbXMpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSB0aGlyZCBhcmd1bWVudCB0byByZXBsYWNlIG5lZWRzIHRvIGJlIGFuIGFycmF5LicsIEFycmF5LmlzQXJyYXkoaXRlbXMpKSk7CiAgICAgICgwLCBfbWV0YWwucmVwbGFjZUluTmF0aXZlQXJyYXkpKHRoaXMsIHN0YXJ0LCBkZWxldGVDb3VudCwgaXRlbXMpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0KICB9KTsgLy8gUmVtb3ZlIGFueSBtZXRob2RzIGltcGxlbWVudGVkIG5hdGl2ZWx5IHNvIHdlIGRvbid0IG92ZXJyaWRlIHRoZW0KCgogIF9leHBvcnRzLk5hdGl2ZUFycmF5ID0gTmF0aXZlQXJyYXk7CiAgdmFyIGlnbm9yZSA9IFsnbGVuZ3RoJ107CiAgTmF0aXZlQXJyYXkua2V5cygpLmZvckVhY2goZnVuY3Rpb24gKG1ldGhvZE5hbWUpIHsKICAgIGlmIChBcnJheS5wcm90b3R5cGVbbWV0aG9kTmFtZV0pIHsKICAgICAgaWdub3JlLnB1c2gobWV0aG9kTmFtZSk7CiAgICB9CiAgfSk7CiAgX2V4cG9ydHMuTmF0aXZlQXJyYXkgPSBOYXRpdmVBcnJheSA9IChfTmF0aXZlQXJyYXkgPSBOYXRpdmVBcnJheSkud2l0aG91dC5hcHBseShfTmF0aXZlQXJyYXksIGlnbm9yZSk7CgogIHZhciBfQTI7CgogIF9leHBvcnRzLkEgPSBfQTI7CgogIGlmIChfZW52aXJvbm1lbnQuRU5WLkVYVEVORF9QUk9UT1RZUEVTLkFycmF5KSB7CiAgICBOYXRpdmVBcnJheS5hcHBseShBcnJheS5wcm90b3R5cGUpOwoKICAgIF9leHBvcnRzLkEgPSBfQTIgPSBmdW5jdGlvbiBBKGFycikgewogICAgICAoZmFsc2UgJiYgISghKHRoaXMgaW5zdGFuY2VvZiBfQTIpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW5ub3QgY3JlYXRlIGFuIEVtYmVyIEFycmF5IHdpdGggYG5ldyBBKClgLCBwbGVhc2UgdXBkYXRlIHRvIGNhbGxpbmcgQSBhcyBhIGZ1bmN0aW9uOiBgQSgpYCcsICEodGhpcyBpbnN0YW5jZW9mIF9BMikpKTsKICAgICAgcmV0dXJuIGFyciB8fCBbXTsKICAgIH07CiAgfSBlbHNlIHsKICAgIF9leHBvcnRzLkEgPSBfQTIgPSBmdW5jdGlvbiBfQShhcnIpIHsKICAgICAgKGZhbHNlICYmICEoISh0aGlzIGluc3RhbmNlb2YgX0EyKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgY2Fubm90IGNyZWF0ZSBhbiBFbWJlciBBcnJheSB3aXRoIGBuZXcgQSgpYCwgcGxlYXNlIHVwZGF0ZSB0byBjYWxsaW5nIEEgYXMgYSBmdW5jdGlvbjogYEEoKWAnLCAhKHRoaXMgaW5zdGFuY2VvZiBfQTIpKSk7CgogICAgICBpZiAoIWFycikgewogICAgICAgIGFyciA9IFtdOwogICAgICB9CgogICAgICByZXR1cm4gQXJyYXlNaXhpbi5kZXRlY3QoYXJyKSA/IGFyciA6IE5hdGl2ZUFycmF5LmFwcGx5KGFycik7CiAgICB9OwogIH0KCiAgdmFyIF9kZWZhdWx0ID0gQXJyYXlNaXhpbjsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9jb21wYXJhYmxlIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21ldGFsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBJbXBsZW1lbnRzIHNvbWUgc3RhbmRhcmQgbWV0aG9kcyBmb3IgY29tcGFyaW5nIG9iamVjdHMuIEFkZCB0aGlzIG1peGluIHRvCiAgICBhbnkgY2xhc3MgeW91IGNyZWF0ZSB0aGF0IGNhbiBjb21wYXJlIGl0cyBpbnN0YW5jZXMuCiAgCiAgICBZb3Ugc2hvdWxkIGltcGxlbWVudCB0aGUgYGNvbXBhcmUoKWAgbWV0aG9kLgogIAogICAgQGNsYXNzIENvbXBhcmFibGUKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEBzaW5jZSBFbWJlciAwLjkKICAgIEBwcml2YXRlCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIC8qKgogICAgICBfX1JlcXVpcmVkLl9fIFlvdSBtdXN0IGltcGxlbWVudCB0aGlzIG1ldGhvZCB0byBhcHBseSB0aGlzIG1peGluLgogICAgICAgT3ZlcnJpZGUgdG8gcmV0dXJuIHRoZSByZXN1bHQgb2YgdGhlIGNvbXBhcmlzb24gb2YgdGhlIHR3byBwYXJhbWV0ZXJzLiBUaGUKICAgICAgY29tcGFyZSBtZXRob2Qgc2hvdWxkIHJldHVybjoKICAgICAgIC0gYC0xYCBpZiBgYSA8IGJgCiAgICAgIC0gYDBgIGlmIGBhID09IGJgCiAgICAgIC0gYDFgIGlmIGBhID4gYmAKICAgICAgIERlZmF1bHQgaW1wbGVtZW50YXRpb24gcmFpc2VzIGFuIGV4Y2VwdGlvbi4KICAgICAgIEBtZXRob2QgY29tcGFyZQogICAgICBAcGFyYW0gYSB7T2JqZWN0fSB0aGUgZmlyc3Qgb2JqZWN0IHRvIGNvbXBhcmUKICAgICAgQHBhcmFtIGIge09iamVjdH0gdGhlIHNlY29uZCBvYmplY3QgdG8gY29tcGFyZQogICAgICBAcmV0dXJuIHtOdW1iZXJ9IHRoZSByZXN1bHQgb2YgdGhlIGNvbXBhcmlzb24KICAgICAgQHByaXZhdGUKICAgICovCiAgICBjb21wYXJlOiBudWxsCiAgfSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2NvbnRhaW5lcl9wcm94eSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvcnVubG9vcCIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9ydW5sb29wLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIENvbnRhaW5lclByb3h5TWl4aW4gaXMgdXNlZCB0byBwcm92aWRlIHB1YmxpYyBhY2Nlc3MgdG8gc3BlY2lmaWMKICAgIGNvbnRhaW5lciBmdW5jdGlvbmFsaXR5LgogIAogICAgQGNsYXNzIENvbnRhaW5lclByb3h5TWl4aW4KICAgIEBwcml2YXRlCiAgKi8KICB2YXIgY29udGFpbmVyUHJveHlNaXhpbiA9IHsKICAgIC8qKgogICAgIFRoZSBjb250YWluZXIgc3RvcmVzIHN0YXRlLgogICAgICBAcHJpdmF0ZQogICAgIEBwcm9wZXJ0eSB7RW1iZXIuQ29udGFpbmVyfSBfX2NvbnRhaW5lcl9fCiAgICAgKi8KICAgIF9fY29udGFpbmVyX186IG51bGwsCgogICAgLyoqCiAgICAgUmV0dXJucyBhbiBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCB0byBwcm92aWRlIGFuIG93bmVyIHRvIGEKICAgICBtYW51YWxseSBjcmVhdGVkIGluc3RhbmNlLgogICAgICBFeGFtcGxlOgogICAgICBgYGAKICAgICBpbXBvcnQgeyBnZXRPd25lciB9IGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgIGxldCBvd25lciA9IGdldE93bmVyKHRoaXMpOwogICAgICBVc2VyLmNyZWF0ZSgKICAgICAgIG93bmVyLm93bmVySW5qZWN0aW9uKCksCiAgICAgICB7IHVzZXJuYW1lOiAncndqYmx1ZScgfQogICAgICkKICAgICBgYGAKICAgICAgQHB1YmxpYwogICAgIEBtZXRob2Qgb3duZXJJbmplY3Rpb24KICAgICBAc2luY2UgMi4zLjAKICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgb3duZXJJbmplY3Rpb246IGZ1bmN0aW9uIG93bmVySW5qZWN0aW9uKCkgewogICAgICByZXR1cm4gdGhpcy5fX2NvbnRhaW5lcl9fLm93bmVySW5qZWN0aW9uKCk7CiAgICB9LAoKICAgIC8qKgogICAgIEdpdmVuIGEgZnVsbE5hbWUgcmV0dXJuIGEgY29ycmVzcG9uZGluZyBpbnN0YW5jZS4KICAgICAgVGhlIGRlZmF1bHQgYmVoYXZpb3IgaXMgZm9yIGxvb2t1cCB0byByZXR1cm4gYSBzaW5nbGV0b24gaW5zdGFuY2UuCiAgICAgVGhlIHNpbmdsZXRvbiBpcyBzY29wZWQgdG8gdGhlIGNvbnRhaW5lciwgYWxsb3dpbmcgbXVsdGlwbGUgY29udGFpbmVycwogICAgIHRvIGFsbCBoYXZlIHRoZWlyIG93biBsb2NhbGx5IHNjb3BlZCBzaW5nbGV0b25zLgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHJlZ2lzdHJ5ID0gbmV3IFJlZ2lzdHJ5KCk7CiAgICAgbGV0IGNvbnRhaW5lciA9IHJlZ2lzdHJ5LmNvbnRhaW5lcigpOwogICAgICByZWdpc3RyeS5yZWdpc3RlcignYXBpOnR3aXR0ZXInLCBUd2l0dGVyKTsKICAgICAgbGV0IHR3aXR0ZXIgPSBjb250YWluZXIubG9va3VwKCdhcGk6dHdpdHRlcicpOwogICAgICB0d2l0dGVyIGluc3RhbmNlb2YgVHdpdHRlcjsgLy8gPT4gdHJ1ZQogICAgICAvLyBieSBkZWZhdWx0IHRoZSBjb250YWluZXIgd2lsbCByZXR1cm4gc2luZ2xldG9ucwogICAgIGxldCB0d2l0dGVyMiA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJyk7CiAgICAgdHdpdHRlcjIgaW5zdGFuY2VvZiBUd2l0dGVyOyAvLyA9PiB0cnVlCiAgICAgIHR3aXR0ZXIgPT09IHR3aXR0ZXIyOyAvLz0+IHRydWUKICAgICBgYGAKICAgICAgSWYgc2luZ2xldG9ucyBhcmUgbm90IHdhbnRlZCBhbiBvcHRpb25hbCBmbGFnIGNhbiBiZSBwcm92aWRlZCBhdCBsb29rdXAuCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoKTsKICAgICBsZXQgY29udGFpbmVyID0gcmVnaXN0cnkuY29udGFpbmVyKCk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdhcGk6dHdpdHRlcicsIFR3aXR0ZXIpOwogICAgICBsZXQgdHdpdHRlciA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJywgeyBzaW5nbGV0b246IGZhbHNlIH0pOwogICAgIGxldCB0d2l0dGVyMiA9IGNvbnRhaW5lci5sb29rdXAoJ2FwaTp0d2l0dGVyJywgeyBzaW5nbGV0b246IGZhbHNlIH0pOwogICAgICB0d2l0dGVyID09PSB0d2l0dGVyMjsgLy89PiBmYWxzZQogICAgIGBgYAogICAgICBAcHVibGljCiAgICAgQG1ldGhvZCBsb29rdXAKICAgICBAcGFyYW0ge1N0cmluZ30gZnVsbE5hbWUKICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgIEByZXR1cm4ge2FueX0KICAgICAqLwogICAgbG9va3VwOiBmdW5jdGlvbiBsb29rdXAoZnVsbE5hbWUsIG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMuX19jb250YWluZXJfXy5sb29rdXAoZnVsbE5hbWUsIG9wdGlvbnMpOwogICAgfSwKICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHZhciBjb250YWluZXIgPSB0aGlzLl9fY29udGFpbmVyX187CgogICAgICBpZiAoY29udGFpbmVyKSB7CiAgICAgICAgKDAsIF9ydW5sb29wLmpvaW4pKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIGNvbnRhaW5lci5kZXN0cm95KCk7CiAgICAgICAgICAoMCwgX3J1bmxvb3Auc2NoZWR1bGUpKCdkZXN0cm95JywgY29udGFpbmVyLCAnZmluYWxpemVEZXN0cm95Jyk7CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHRoaXMuX3N1cGVyKCk7CiAgICB9LAoKICAgIC8qKgogICAgR2l2ZW4gYSBmdWxsTmFtZSByZXR1cm4gYSBmYWN0b3J5IG1hbmFnZXIuCiAgICAgVGhpcyBtZXRob2QgcmV0dXJucyBhIG1hbmFnZXIgd2hpY2ggY2FuIGJlIHVzZWQgZm9yIGludHJvc3BlY3Rpb24gb2YgdGhlCiAgICBmYWN0b3J5J3MgY2xhc3Mgb3IgZm9yIHRoZSBjcmVhdGlvbiBvZiBmYWN0b3J5IGluc3RhbmNlcyB3aXRoIGluaXRpYWwKICAgIHByb3BlcnRpZXMuIFRoZSBtYW5hZ2VyIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllczoKICAgICAqIGBjbGFzc2AgLSBUaGUgcmVnaXN0ZXJlZCBvciByZXNvbHZlZCBjbGFzcy4KICAgICogYGNyZWF0ZWAgLSBBIGZ1bmN0aW9uIHRoYXQgd2lsbCBjcmVhdGUgYW4gaW5zdGFuY2Ugb2YgdGhlIGNsYXNzIHdpdGgKICAgICAgYW55IGRlcGVuZGVuY2llcyBpbmplY3RlZC4KICAgICBGb3IgZXhhbXBsZToKICAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBnZXRPd25lciB9IGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgbGV0IG93bmVyID0gZ2V0T3duZXIob3RoZXJJbnN0YW5jZSk7CiAgICAvLyB0aGUgb3duZXIgaXMgY29tbW9ubHkgdGhlIGBhcHBsaWNhdGlvbkluc3RhbmNlYCwgYW5kIGNhbiBiZSBhY2Nlc3NlZCB2aWEKICAgIC8vIGFuIGluc3RhbmNlIGluaXRpYWxpemVyLgogICAgIGxldCBmYWN0b3J5ID0gb3duZXIuZmFjdG9yeUZvcignc2VydmljZTpiZXNwb2tlJyk7CiAgICAgZmFjdG9yeS5jbGFzczsKICAgIC8vIFRoZSByZWdpc3RlcmVkIG9yIHJlc29sdmVkIGNsYXNzLiBGb3IgZXhhbXBsZSB3aGVuIHVzZWQgd2l0aCBhbiBFbWJlci1DTEkKICAgIC8vIGFwcCwgdGhpcyB3b3VsZCBiZSB0aGUgZGVmYXVsdCBleHBvcnQgZnJvbSBgYXBwL3NlcnZpY2VzL2Jlc3Bva2UuanNgLgogICAgIGxldCBpbnN0YW5jZSA9IGZhY3RvcnkuY3JlYXRlKHsKICAgICAgc29tZVByb3BlcnR5OiAnYW4gaW5pdGlhbCBwcm9wZXJ0eSB2YWx1ZScKICAgIH0pOwogICAgLy8gQ3JlYXRlIGFuIGluc3RhbmNlIHdpdGggYW55IGluamVjdGlvbnMgYW5kIHRoZSBwYXNzZWQgb3B0aW9ucyBhcwogICAgLy8gaW5pdGlhbCBwcm9wZXJ0aWVzLgogICAgYGBgCiAgICAgQW55IGluc3RhbmNlcyBjcmVhdGVkIHZpYSB0aGUgZmFjdG9yeSdzIGAuY3JlYXRlKClgIG1ldGhvZCAqbXVzdCogYmUgZGVzdHJveWVkCiAgICBtYW51YWxseSBieSB0aGUgY2FsbGVyIG9mIGAuY3JlYXRlKClgLiBUeXBpY2FsbHksIHRoaXMgaXMgZG9uZSBkdXJpbmcgdGhlIGNyZWF0aW5nCiAgICBvYmplY3RzIG93biBgZGVzdHJveWAgb3IgYHdpbGxEZXN0cm95YCBtZXRob2RzLgogICAgIEBwdWJsaWMKICAgIEBtZXRob2QgZmFjdG9yeUZvcgogICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgQHJldHVybiB7RmFjdG9yeU1hbmFnZXJ9CiAgICAqLwogICAgZmFjdG9yeUZvcjogZnVuY3Rpb24gZmFjdG9yeUZvcihmdWxsTmFtZSwgb3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fX2NvbnRhaW5lcl9fLmZhY3RvcnlGb3IoZnVsbE5hbWUsIG9wdGlvbnMpOwogICAgfQogIH07CgogIHZhciBfZGVmYXVsdCA9IF9tZXRhbC5NaXhpbi5jcmVhdGUoY29udGFpbmVyUHJveHlNaXhpbik7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2NvcHlhYmxlIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21ldGFsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgICBJbXBsZW1lbnRzIHNvbWUgc3RhbmRhcmQgbWV0aG9kcyBmb3IgY29weWluZyBhbiBvYmplY3QuIEFkZCB0aGlzIG1peGluIHRvCiAgICBhbnkgb2JqZWN0IHlvdSBjcmVhdGUgdGhhdCBjYW4gY3JlYXRlIGEgY29weSBvZiBpdHNlbGYuIFRoaXMgbWl4aW4gaXMKICAgIGFkZGVkIGF1dG9tYXRpY2FsbHkgdG8gdGhlIGJ1aWx0LWluIGFycmF5LgogIAogICAgWW91IHNob3VsZCBnZW5lcmFsbHkgaW1wbGVtZW50IHRoZSBgY29weSgpYCBtZXRob2QgdG8gcmV0dXJuIGEgY29weSBvZiB0aGUKICAgIHJlY2VpdmVyLgogIAogICAgQGNsYXNzIENvcHlhYmxlCiAgICBAbmFtZXNwYWNlIEVtYmVyCiAgICBAc2luY2UgRW1iZXIgMC45CiAgICBAZGVwcmVjYXRlZCBVc2UgJ2VtYmVyLWNvcHknIGFkZG9uIGluc3RlYWQKICAgIEBwcml2YXRlCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIC8qKgogICAgICBfX1JlcXVpcmVkLl9fIFlvdSBtdXN0IGltcGxlbWVudCB0aGlzIG1ldGhvZCB0byBhcHBseSB0aGlzIG1peGluLgogICAgICAgT3ZlcnJpZGUgdG8gcmV0dXJuIGEgY29weSBvZiB0aGUgcmVjZWl2ZXIuIERlZmF1bHQgaW1wbGVtZW50YXRpb24gcmFpc2VzCiAgICAgIGFuIGV4Y2VwdGlvbi4KICAgICAgIEBtZXRob2QgY29weQogICAgICBAcGFyYW0ge0Jvb2xlYW59IGRlZXAgaWYgYHRydWVgLCBhIGRlZXAgY29weSBvZiB0aGUgb2JqZWN0IHNob3VsZCBiZSBtYWRlCiAgICAgIEByZXR1cm4ge09iamVjdH0gY29weSBvZiByZWNlaXZlcgogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGNvcHk6IG51bGwKICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvZW51bWVyYWJsZSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvZW51bWVyYWJsZQogIEBwcml2YXRlCiAgKi8KCiAgLyoqCiAgICBUaGUgbWV0aG9kcyBpbiB0aGlzIG1peGluIGhhdmUgYmVlbiBtb3ZlZCB0byBbTXV0YWJsZUFycmF5XSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL011dGFibGVBcnJheSkuIFRoaXMgbWl4aW4gaGFzCiAgICBiZWVuIGludGVudGlvbmFsbHkgcHJlc2VydmVkIHRvIGF2b2lkIGJyZWFraW5nIEVudW1lcmFibGUuZGV0ZWN0IGNoZWNrcwogICAgdW50aWwgdGhlIGNvbW11bml0eSBtaWdyYXRlcyBhd2F5IGZyb20gdGhlbS4KICAKICAgIEBjbGFzcyBFbnVtZXJhYmxlCiAgICBAcHJpdmF0ZQogICovCiAgdmFyIF9kZWZhdWx0ID0gX21ldGFsLk1peGluLmNyZWF0ZSgpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy9ldmVudGVkIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21ldGFsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwoKICAvKioKICAgIFRoaXMgbWl4aW4gYWxsb3dzIGZvciBFbWJlciBvYmplY3RzIHRvIHN1YnNjcmliZSB0byBhbmQgZW1pdCBldmVudHMuCiAgCiAgICBgYGBhcHAvdXRpbHMvcGVyc29uLmpzCiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgRXZlbnRlZCBmcm9tICdAZW1iZXIvb2JqZWN0L2V2ZW50ZWQnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgRW1iZXJPYmplY3QuZXh0ZW5kKEV2ZW50ZWQsIHsKICAgICAgZ3JlZXQoKSB7CiAgICAgICAgLy8gLi4uCiAgICAgICAgdGhpcy50cmlnZ2VyKCdncmVldCcpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgYGBgamF2YXNjcmlwdAogICAgdmFyIHBlcnNvbiA9IFBlcnNvbi5jcmVhdGUoKTsKICAKICAgIHBlcnNvbi5vbignZ3JlZXQnLCBmdW5jdGlvbigpIHsKICAgICAgY29uc29sZS5sb2coJ091ciBwZXJzb24gaGFzIGdyZWV0ZWQnKTsKICAgIH0pOwogIAogICAgcGVyc29uLmdyZWV0KCk7CiAgCiAgICAvLyBvdXRwdXRzOiAnT3VyIHBlcnNvbiBoYXMgZ3JlZXRlZCcKICAgIGBgYAogIAogICAgWW91IGNhbiBhbHNvIGNoYWluIG11bHRpcGxlIGV2ZW50IHN1YnNjcmlwdGlvbnM6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBwZXJzb24ub24oJ2dyZWV0JywgZnVuY3Rpb24oKSB7CiAgICAgIGNvbnNvbGUubG9nKCdPdXIgcGVyc29uIGhhcyBncmVldGVkJyk7CiAgICB9KS5vbmUoJ2dyZWV0JywgZnVuY3Rpb24oKSB7CiAgICAgIGNvbnNvbGUubG9nKCdPZmZlciBvbmUtdGltZSBzcGVjaWFsJyk7CiAgICB9KS5vZmYoJ2V2ZW50JywgdGhpcywgZm9yZ2V0VGhpcyk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBFdmVudGVkCiAgICBAcHVibGljCiAgICovCiAgdmFyIF9kZWZhdWx0ID0gX21ldGFsLk1peGluLmNyZWF0ZSh7CiAgICAvKioKICAgICAgU3Vic2NyaWJlcyB0byBhIG5hbWVkIGV2ZW50IHdpdGggZ2l2ZW4gZnVuY3Rpb24uCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHBlcnNvbi5vbignZGlkTG9hZCcsIGZ1bmN0aW9uKCkgewogICAgICAgIC8vIGZpcmVkIG9uY2UgdGhlIHBlcnNvbiBoYXMgbG9hZGVkCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEFuIG9wdGlvbmFsIHRhcmdldCBjYW4gYmUgcGFzc2VkIGluIGFzIHRoZSAybmQgYXJndW1lbnQgdGhhdCB3aWxsCiAgICAgIGJlIHNldCBhcyB0aGUgInRoaXMiIGZvciB0aGUgY2FsbGJhY2suIFRoaXMgaXMgYSBnb29kIHdheSB0byBnaXZlIHlvdXIKICAgICAgZnVuY3Rpb24gYWNjZXNzIHRvIHRoZSBvYmplY3QgdHJpZ2dlcmluZyB0aGUgZXZlbnQuIFdoZW4gdGhlIHRhcmdldAogICAgICBwYXJhbWV0ZXIgaXMgdXNlZCB0aGUgY2FsbGJhY2sgbWV0aG9kIGJlY29tZXMgdGhlIHRoaXJkIGFyZ3VtZW50LgogICAgICAgQG1ldGhvZCBvbgogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQKICAgICAgQHBhcmFtIHtPYmplY3R9IFt0YXJnZXRdIFRoZSAidGhpcyIgYmluZGluZyBmb3IgdGhlIGNhbGxiYWNrCiAgICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBtZXRob2QgQSBmdW5jdGlvbiBvciB0aGUgbmFtZSBvZiBhIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBvbiBgdGFyZ2V0YAogICAgICBAcmV0dXJuIHRoaXMKICAgICAgQHB1YmxpYwogICAgKi8KICAgIG9uOiBmdW5jdGlvbiBvbihuYW1lLCB0YXJnZXQsIG1ldGhvZCkgewogICAgICAoMCwgX21ldGFsLmFkZExpc3RlbmVyKSh0aGlzLCBuYW1lLCB0YXJnZXQsIG1ldGhvZCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgU3Vic2NyaWJlcyBhIGZ1bmN0aW9uIHRvIGEgbmFtZWQgZXZlbnQgYW5kIHRoZW4gY2FuY2VscyB0aGUgc3Vic2NyaXB0aW9uCiAgICAgIGFmdGVyIHRoZSBmaXJzdCB0aW1lIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuIEl0IGlzIGdvb2QgdG8gdXNlIGBgb25lYGAgd2hlbgogICAgICB5b3Ugb25seSBjYXJlIGFib3V0IHRoZSBmaXJzdCB0aW1lIGFuIGV2ZW50IGhhcyB0YWtlbiBwbGFjZS4KICAgICAgIFRoaXMgZnVuY3Rpb24gdGFrZXMgYW4gb3B0aW9uYWwgMm5kIGFyZ3VtZW50IHRoYXQgd2lsbCBiZWNvbWUgdGhlICJ0aGlzIgogICAgICB2YWx1ZSBmb3IgdGhlIGNhbGxiYWNrLiBXaGVuIHRoZSB0YXJnZXQgcGFyYW1ldGVyIGlzIHVzZWQgdGhlIGNhbGxiYWNrIG1ldGhvZAogICAgICBiZWNvbWVzIHRoZSB0aGlyZCBhcmd1bWVudC4KICAgICAgIEBtZXRob2Qgb25lCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudAogICAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gVGhlICJ0aGlzIiBiaW5kaW5nIGZvciB0aGUgY2FsbGJhY2sKICAgICAgQHBhcmFtIHtGdW5jdGlvbnxTdHJpbmd9IG1ldGhvZCBBIGZ1bmN0aW9uIG9yIHRoZSBuYW1lIG9mIGEgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIG9uIGB0YXJnZXRgCiAgICAgIEByZXR1cm4gdGhpcwogICAgICBAcHVibGljCiAgICAqLwogICAgb25lOiBmdW5jdGlvbiBvbmUobmFtZSwgdGFyZ2V0LCBtZXRob2QpIHsKICAgICAgKDAsIF9tZXRhbC5hZGRMaXN0ZW5lcikodGhpcywgbmFtZSwgdGFyZ2V0LCBtZXRob2QsIHRydWUpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCgogICAgLyoqCiAgICAgIFRyaWdnZXJzIGEgbmFtZWQgZXZlbnQgZm9yIHRoZSBvYmplY3QuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cwogICAgICB3aWxsIGJlIHBhc3NlZCBhcyBwYXJhbWV0ZXJzIHRvIHRoZSBmdW5jdGlvbnMgdGhhdCBhcmUgc3Vic2NyaWJlZCB0byB0aGUKICAgICAgZXZlbnQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHBlcnNvbi5vbignZGlkRWF0JywgZnVuY3Rpb24oZm9vZCkgewogICAgICAgIGNvbnNvbGUubG9nKCdwZXJzb24gYXRlIHNvbWUgJyArIGZvb2QpOwogICAgICB9KTsKICAgICAgIHBlcnNvbi50cmlnZ2VyKCdkaWRFYXQnLCAnYnJvY2NvbGknKTsKICAgICAgIC8vIG91dHB1dHM6IHBlcnNvbiBhdGUgc29tZSBicm9jY29saQogICAgICBgYGAKICAgICAgQG1ldGhvZCB0cmlnZ2VyCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudAogICAgICBAcGFyYW0ge09iamVjdC4uLn0gYXJncyBPcHRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyBvbgogICAgICBAcHVibGljCiAgICAqLwogICAgdHJpZ2dlcjogZnVuY3Rpb24gdHJpZ2dlcihuYW1lKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4gPiAxID8gX2xlbiAtIDEgOiAwKSwgX2tleSA9IDE7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgICBhcmdzW19rZXkgLSAxXSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgICAgfQoKICAgICAgKDAsIF9tZXRhbC5zZW5kRXZlbnQpKHRoaXMsIG5hbWUsIGFyZ3MpOwogICAgfSwKCiAgICAvKioKICAgICAgQ2FuY2VscyBzdWJzY3JpcHRpb24gZm9yIGdpdmVuIG5hbWUsIHRhcmdldCwgYW5kIG1ldGhvZC4KICAgICAgIEBtZXRob2Qgb2ZmCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudAogICAgICBAcGFyYW0ge09iamVjdH0gdGFyZ2V0IFRoZSB0YXJnZXQgb2YgdGhlIHN1YnNjcmlwdGlvbgogICAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIFRoZSBmdW5jdGlvbiBvciB0aGUgbmFtZSBvZiBhIGZ1bmN0aW9uIG9mIHRoZSBzdWJzY3JpcHRpb24KICAgICAgQHJldHVybiB0aGlzCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBvZmY6IGZ1bmN0aW9uIG9mZihuYW1lLCB0YXJnZXQsIG1ldGhvZCkgewogICAgICAoMCwgX21ldGFsLnJlbW92ZUxpc3RlbmVyKSh0aGlzLCBuYW1lLCB0YXJnZXQsIG1ldGhvZCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgQ2hlY2tzIHRvIHNlZSBpZiBvYmplY3QgaGFzIGFueSBzdWJzY3JpcHRpb25zIGZvciBuYW1lZCBldmVudC4KICAgICAgIEBtZXRob2QgaGFzCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudAogICAgICBAcmV0dXJuIHtCb29sZWFufSBkb2VzIHRoZSBvYmplY3QgaGF2ZSBhIHN1YnNjcmlwdGlvbiBmb3IgZXZlbnQKICAgICAgQHB1YmxpYwogICAgICovCiAgICBoYXM6IGZ1bmN0aW9uIGhhcyhuYW1lKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmhhc0xpc3RlbmVycykodGhpcywgbmFtZSk7CiAgICB9CiAgfSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL211dGFibGVfZW51bWVyYWJsZSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvZW51bWVyYWJsZSIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbnVtZXJhYmxlLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIFRoZSBtZXRob2RzIGluIHRoaXMgbWl4aW4gaGF2ZSBiZWVuIG1vdmVkIHRvIE11dGFibGVBcnJheS4gVGhpcyBtaXhpbiBoYXMKICAgIGJlZW4gaW50ZW50aW9uYWxseSBwcmVzZXJ2ZWQgdG8gYXZvaWQgYnJlYWtpbmcgTXV0YWJsZUVudW1lcmFibGUuZGV0ZWN0CiAgICBjaGVja3MgdW50aWwgdGhlIGNvbW11bml0eSBtaWdyYXRlcyBhd2F5IGZyb20gdGhlbS4KICAKICAgIEBjbGFzcyBNdXRhYmxlRW51bWVyYWJsZQogICAgQG5hbWVzcGFjZSBFbWJlcgogICAgQHVzZXMgRW51bWVyYWJsZQogICAgQHByaXZhdGUKICAqLwogIHZhciBfZGVmYXVsdCA9IF9tZXRhbC5NaXhpbi5jcmVhdGUoX2VudW1lcmFibGUuZGVmYXVsdCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL29ic2VydmFibGUiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21ldGFsLCBfZGVidWcpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgQGVtYmVyL29iamVjdAogICovCgogIC8qKgogICAgIyMgT3ZlcnZpZXcKICAKICAgIFRoaXMgbWl4aW4gcHJvdmlkZXMgcHJvcGVydGllcyBhbmQgcHJvcGVydHkgb2JzZXJ2aW5nIGZ1bmN0aW9uYWxpdHksIGNvcmUKICAgIGZlYXR1cmVzIG9mIHRoZSBFbWJlciBvYmplY3QgbW9kZWwuCiAgCiAgICBQcm9wZXJ0aWVzIGFuZCBvYnNlcnZlcnMgYWxsb3cgb25lIG9iamVjdCB0byBvYnNlcnZlIGNoYW5nZXMgdG8gYQogICAgcHJvcGVydHkgb24gYW5vdGhlciBvYmplY3QuIFRoaXMgaXMgb25lIG9mIHRoZSBmdW5kYW1lbnRhbCB3YXlzIHRoYXQKICAgIG1vZGVscywgY29udHJvbGxlcnMgYW5kIHZpZXdzIGNvbW11bmljYXRlIHdpdGggZWFjaCBvdGhlciBpbiBhbiBFbWJlcgogICAgYXBwbGljYXRpb24uCiAgCiAgICBBbnkgb2JqZWN0IHRoYXQgaGFzIHRoaXMgbWl4aW4gYXBwbGllZCBjYW4gYmUgdXNlZCBpbiBvYnNlcnZlcgogICAgb3BlcmF0aW9ucy4gVGhhdCBpbmNsdWRlcyBgRW1iZXJPYmplY3RgIGFuZCBtb3N0IG9iamVjdHMgeW91IHdpbGwKICAgIGludGVyYWN0IHdpdGggYXMgeW91IHdyaXRlIHlvdXIgRW1iZXIgYXBwbGljYXRpb24uCiAgCiAgICBOb3RlIHRoYXQgeW91IHdpbGwgbm90IGdlbmVyYWxseSBhcHBseSB0aGlzIG1peGluIHRvIGNsYXNzZXMgeW91cnNlbGYsCiAgICBidXQgeW91IHdpbGwgdXNlIHRoZSBmZWF0dXJlcyBwcm92aWRlZCBieSB0aGlzIG1vZHVsZSBmcmVxdWVudGx5LCBzbyBpdAogICAgaXMgaW1wb3J0YW50IHRvIHVuZGVyc3RhbmQgaG93IHRvIHVzZSBpdC4KICAKICAgICMjIFVzaW5nIGBnZXQoKWAgYW5kIGBzZXQoKWAKICAKICAgIEJlY2F1c2Ugb2YgRW1iZXIncyBzdXBwb3J0IGZvciBiaW5kaW5ncyBhbmQgb2JzZXJ2ZXJzLCB5b3Ugd2lsbCBhbHdheXMKICAgIGFjY2VzcyBwcm9wZXJ0aWVzIHVzaW5nIHRoZSBnZXQgbWV0aG9kLCBhbmQgc2V0IHByb3BlcnRpZXMgdXNpbmcgdGhlCiAgICBzZXQgbWV0aG9kLiBUaGlzIGFsbG93cyB0aGUgb2JzZXJ2aW5nIG9iamVjdHMgdG8gYmUgbm90aWZpZWQgYW5kCiAgICBjb21wdXRlZCBwcm9wZXJ0aWVzIHRvIGJlIGhhbmRsZWQgcHJvcGVybHkuCiAgCiAgICBNb3JlIGRvY3VtZW50YXRpb24gYWJvdXQgYGdldGAgYW5kIGBzZXRgIGFyZSBiZWxvdy4KICAKICAgICMjIE9ic2VydmluZyBQcm9wZXJ0eSBDaGFuZ2VzCiAgCiAgICBZb3UgdHlwaWNhbGx5IG9ic2VydmUgcHJvcGVydHkgY2hhbmdlcyBzaW1wbHkgYnkgdXNpbmcgdGhlIGBvYnNlcnZlcmAKICAgIGZ1bmN0aW9uIGluIGNsYXNzZXMgdGhhdCB5b3Ugd3JpdGUuCiAgCiAgICBGb3IgZXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IG9ic2VydmVyIH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgCiAgICBFbWJlck9iamVjdC5leHRlbmQoewogICAgICB2YWx1ZU9ic2VydmVyOiBvYnNlcnZlcigndmFsdWUnLCBmdW5jdGlvbihzZW5kZXIsIGtleSwgdmFsdWUsIHJldikgewogICAgICAgIC8vIEV4ZWN1dGVzIHdoZW5ldmVyIHRoZSAidmFsdWUiIHByb3BlcnR5IGNoYW5nZXMKICAgICAgICAvLyBTZWUgdGhlIGFkZE9ic2VydmVyIG1ldGhvZCBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY2FsbGJhY2sgYXJndW1lbnRzCiAgICAgIH0pCiAgICB9KTsKICAgIGBgYAogIAogICAgQWx0aG91Z2ggdGhpcyBpcyB0aGUgbW9zdCBjb21tb24gd2F5IHRvIGFkZCBhbiBvYnNlcnZlciwgdGhpcyBjYXBhYmlsaXR5CiAgICBpcyBhY3R1YWxseSBidWlsdCBpbnRvIHRoZSBgRW1iZXJPYmplY3RgIGNsYXNzIG9uIHRvcCBvZiB0d28gbWV0aG9kcwogICAgZGVmaW5lZCBpbiB0aGlzIG1peGluOiBgYWRkT2JzZXJ2ZXJgIGFuZCBgcmVtb3ZlT2JzZXJ2ZXJgLiBZb3UgY2FuIHVzZQogICAgdGhlc2UgdHdvIG1ldGhvZHMgdG8gYWRkIGFuZCByZW1vdmUgb2JzZXJ2ZXJzIHlvdXJzZWxmIGlmIHlvdSBuZWVkIHRvCiAgICBkbyBzbyBhdCBydW50aW1lLgogIAogICAgVG8gYWRkIGFuIG9ic2VydmVyIGZvciBhIHByb3BlcnR5LCBjYWxsOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgb2JqZWN0LmFkZE9ic2VydmVyKCdwcm9wZXJ0eUtleScsIHRhcmdldE9iamVjdCwgdGFyZ2V0QWN0aW9uKQogICAgYGBgCiAgCiAgICBUaGlzIHdpbGwgY2FsbCB0aGUgYHRhcmdldEFjdGlvbmAgbWV0aG9kIG9uIHRoZSBgdGFyZ2V0T2JqZWN0YCB3aGVuZXZlcgogICAgdGhlIHZhbHVlIG9mIHRoZSBgcHJvcGVydHlLZXlgIGNoYW5nZXMuCiAgCiAgICBOb3RlIHRoYXQgaWYgYHByb3BlcnR5S2V5YCBpcyBhIGNvbXB1dGVkIHByb3BlcnR5LCB0aGUgb2JzZXJ2ZXIgd2lsbCBiZQogICAgY2FsbGVkIHdoZW4gYW55IG9mIHRoZSBwcm9wZXJ0eSBkZXBlbmRlbmNpZXMgYXJlIGNoYW5nZWQsIGV2ZW4gaWYgdGhlCiAgICByZXN1bHRpbmcgdmFsdWUgb2YgdGhlIGNvbXB1dGVkIHByb3BlcnR5IGlzIHVuY2hhbmdlZC4gVGhpcyBpcyBuZWNlc3NhcnkKICAgIGJlY2F1c2UgY29tcHV0ZWQgcHJvcGVydGllcyBhcmUgbm90IGNvbXB1dGVkIHVudGlsIGBnZXRgIGlzIGNhbGxlZC4KICAKICAgIEBjbGFzcyBPYnNlcnZhYmxlCiAgICBAcHVibGljCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIC8qKgogICAgICBSZXRyaWV2ZXMgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgZnJvbSB0aGUgb2JqZWN0LgogICAgICAgVGhpcyBtZXRob2QgaXMgdXN1YWxseSBzaW1pbGFyIHRvIHVzaW5nIGBvYmplY3Rba2V5TmFtZV1gIG9yIGBvYmplY3Qua2V5TmFtZWAsCiAgICAgIGhvd2V2ZXIgaXQgc3VwcG9ydHMgYm90aCBjb21wdXRlZCBwcm9wZXJ0aWVzIGFuZCB0aGUgdW5rbm93blByb3BlcnR5CiAgICAgIGhhbmRsZXIuCiAgICAgICBCZWNhdXNlIGBnZXRgIHVuaWZpZXMgdGhlIHN5bnRheCBmb3IgYWNjZXNzaW5nIGFsbCB0aGVzZSBraW5kcwogICAgICBvZiBwcm9wZXJ0aWVzLCBpdCBjYW4gbWFrZSBtYW55IHJlZmFjdG9yaW5ncyBlYXNpZXIsIHN1Y2ggYXMgcmVwbGFjaW5nIGEKICAgICAgc2ltcGxlIHByb3BlcnR5IHdpdGggYSBjb21wdXRlZCBwcm9wZXJ0eSwgb3IgdmljZSB2ZXJzYS4KICAgICAgICMjIyBDb21wdXRlZCBQcm9wZXJ0aWVzCiAgICAgICBDb21wdXRlZCBwcm9wZXJ0aWVzIGFyZSBtZXRob2RzIGRlZmluZWQgd2l0aCB0aGUgYHByb3BlcnR5YCBtb2RpZmllcgogICAgICBkZWNsYXJlZCBhdCB0aGUgZW5kLCBzdWNoIGFzOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgZnVsbE5hbWU6IGNvbXB1dGVkKCdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnLCBmdW5jdGlvbigpIHsKICAgICAgICByZXR1cm4gdGhpcy5nZXQoJ2ZpcnN0TmFtZScpICsgJyAnICsgdGhpcy5nZXQoJ2xhc3ROYW1lJyk7CiAgICAgIH0pCiAgICAgIGBgYAogICAgICAgV2hlbiB5b3UgY2FsbCBgZ2V0YCBvbiBhIGNvbXB1dGVkIHByb3BlcnR5LCB0aGUgZnVuY3Rpb24gd2lsbCBiZQogICAgICBjYWxsZWQgYW5kIHRoZSByZXR1cm4gdmFsdWUgd2lsbCBiZSByZXR1cm5lZCBpbnN0ZWFkIG9mIHRoZSBmdW5jdGlvbgogICAgICBpdHNlbGYuCiAgICAgICAjIyMgVW5rbm93biBQcm9wZXJ0aWVzCiAgICAgICBMaWtld2lzZSwgaWYgeW91IHRyeSB0byBjYWxsIGBnZXRgIG9uIGEgcHJvcGVydHkgd2hvc2UgdmFsdWUgaXMKICAgICAgYHVuZGVmaW5lZGAsIHRoZSBgdW5rbm93blByb3BlcnR5KClgIG1ldGhvZCB3aWxsIGJlIGNhbGxlZCBvbiB0aGUgb2JqZWN0LgogICAgICBJZiB0aGlzIG1ldGhvZCByZXR1cm5zIGFueSB2YWx1ZSBvdGhlciB0aGFuIGB1bmRlZmluZWRgLCBpdCB3aWxsIGJlIHJldHVybmVkCiAgICAgIGluc3RlYWQuIFRoaXMgYWxsb3dzIHlvdSB0byBpbXBsZW1lbnQgInZpcnR1YWwiIHByb3BlcnRpZXMgdGhhdCBhcmUKICAgICAgbm90IGRlZmluZWQgdXBmcm9udC4KICAgICAgIEBtZXRob2QgZ2V0CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBrZXlOYW1lIFRoZSBwcm9wZXJ0eSB0byByZXRyaWV2ZQogICAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSBwcm9wZXJ0eSB2YWx1ZSBvciB1bmRlZmluZWQuCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBnZXQ6IGZ1bmN0aW9uIGdldChrZXlOYW1lKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkodGhpcywga2V5TmFtZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBUbyBnZXQgdGhlIHZhbHVlcyBvZiBtdWx0aXBsZSBwcm9wZXJ0aWVzIGF0IG9uY2UsIGNhbGwgYGdldFByb3BlcnRpZXNgCiAgICAgIHdpdGggYSBsaXN0IG9mIHN0cmluZ3Mgb3IgYW4gYXJyYXk6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHJlY29yZC5nZXRQcm9wZXJ0aWVzKCdmaXJzdE5hbWUnLCAnbGFzdE5hbWUnLCAnemlwQ29kZScpOwogICAgICAvLyB7IGZpcnN0TmFtZTogJ0pvaG4nLCBsYXN0TmFtZTogJ0RvZScsIHppcENvZGU6ICcxMDAxMScgfQogICAgICBgYGAKICAgICAgIGlzIGVxdWl2YWxlbnQgdG86CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHJlY29yZC5nZXRQcm9wZXJ0aWVzKFsnZmlyc3ROYW1lJywgJ2xhc3ROYW1lJywgJ3ppcENvZGUnXSk7CiAgICAgIC8vIHsgZmlyc3ROYW1lOiAnSm9obicsIGxhc3ROYW1lOiAnRG9lJywgemlwQ29kZTogJzEwMDExJyB9CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBnZXRQcm9wZXJ0aWVzCiAgICAgIEBwYXJhbSB7U3RyaW5nLi4ufEFycmF5fSBsaXN0IG9mIGtleXMgdG8gZ2V0CiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICAgQHB1YmxpYwogICAgKi8KICAgIGdldFByb3BlcnRpZXM6IGZ1bmN0aW9uIGdldFByb3BlcnRpZXMoKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgIHJldHVybiBfbWV0YWwuZ2V0UHJvcGVydGllcy5hcHBseSh2b2lkIDAsIFt0aGlzXS5jb25jYXQoYXJncykpOwogICAgfSwKCiAgICAvKioKICAgICAgU2V0cyB0aGUgcHJvdmlkZWQga2V5IG9yIHBhdGggdG8gdGhlIHZhbHVlLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICByZWNvcmQuc2V0KCJrZXkiLCB2YWx1ZSk7CiAgICAgIGBgYAogICAgICAgVGhpcyBtZXRob2QgaXMgZ2VuZXJhbGx5IHZlcnkgc2ltaWxhciB0byBjYWxsaW5nIGBvYmplY3RbImtleSJdID0gdmFsdWVgIG9yCiAgICAgIGBvYmplY3Qua2V5ID0gdmFsdWVgLCBleGNlcHQgdGhhdCBpdCBwcm92aWRlcyBzdXBwb3J0IGZvciBjb21wdXRlZAogICAgICBwcm9wZXJ0aWVzLCB0aGUgYHNldFVua25vd25Qcm9wZXJ0eSgpYCBtZXRob2QgYW5kIHByb3BlcnR5IG9ic2VydmVycy4KICAgICAgICMjIyBDb21wdXRlZCBQcm9wZXJ0aWVzCiAgICAgICBJZiB5b3UgdHJ5IHRvIHNldCBhIHZhbHVlIG9uIGEga2V5IHRoYXQgaGFzIGEgY29tcHV0ZWQgcHJvcGVydHkgaGFuZGxlcgogICAgICBkZWZpbmVkIChzZWUgdGhlIGBnZXQoKWAgbWV0aG9kIGZvciBhbiBleGFtcGxlKSwgdGhlbiBgc2V0KClgIHdpbGwgY2FsbAogICAgICB0aGF0IG1ldGhvZCwgcGFzc2luZyBib3RoIHRoZSB2YWx1ZSBhbmQga2V5IGluc3RlYWQgb2Ygc2ltcGx5IGNoYW5naW5nCiAgICAgIHRoZSB2YWx1ZSBpdHNlbGYuIFRoaXMgaXMgdXNlZnVsIGZvciB0aG9zZSB0aW1lcyB3aGVuIHlvdSBuZWVkIHRvCiAgICAgIGltcGxlbWVudCBhIHByb3BlcnR5IHRoYXQgaXMgY29tcG9zZWQgb2Ygb25lIG9yIG1vcmUgbWVtYmVyCiAgICAgIHByb3BlcnRpZXMuCiAgICAgICAjIyMgVW5rbm93biBQcm9wZXJ0aWVzCiAgICAgICBJZiB5b3UgdHJ5IHRvIHNldCBhIHZhbHVlIG9uIGEga2V5IHRoYXQgaXMgdW5kZWZpbmVkIGluIHRoZSB0YXJnZXQKICAgICAgb2JqZWN0LCB0aGVuIHRoZSBgc2V0VW5rbm93blByb3BlcnR5KClgIGhhbmRsZXIgd2lsbCBiZSBjYWxsZWQgaW5zdGVhZC4gVGhpcwogICAgICBnaXZlcyB5b3UgYW4gb3Bwb3J0dW5pdHkgdG8gaW1wbGVtZW50IGNvbXBsZXggInZpcnR1YWwiIHByb3BlcnRpZXMgdGhhdAogICAgICBhcmUgbm90IHByZWRlZmluZWQgb24gdGhlIG9iamVjdC4gSWYgYHNldFVua25vd25Qcm9wZXJ0eSgpYCByZXR1cm5zCiAgICAgIHVuZGVmaW5lZCwgdGhlbiBgc2V0KClgIHdpbGwgc2ltcGx5IHNldCB0aGUgdmFsdWUgb24gdGhlIG9iamVjdC4KICAgICAgICMjIyBQcm9wZXJ0eSBPYnNlcnZlcnMKICAgICAgIEluIGFkZGl0aW9uIHRvIGNoYW5naW5nIHRoZSBwcm9wZXJ0eSwgYHNldCgpYCB3aWxsIGFsc28gcmVnaXN0ZXIgYSBwcm9wZXJ0eQogICAgICBjaGFuZ2Ugd2l0aCB0aGUgb2JqZWN0LiBVbmxlc3MgeW91IGhhdmUgcGxhY2VkIHRoaXMgY2FsbCBpbnNpZGUgb2YgYQogICAgICBgYmVnaW5Qcm9wZXJ0eUNoYW5nZXMoKWAgYW5kIGBlbmRQcm9wZXJ0eUNoYW5nZXMoKSxgIGFueSAibG9jYWwiIG9ic2VydmVycwogICAgICAoaS5lLiBvYnNlcnZlciBtZXRob2RzIGRlY2xhcmVkIG9uIHRoZSBzYW1lIG9iamVjdCksIHdpbGwgYmUgY2FsbGVkCiAgICAgIGltbWVkaWF0ZWx5LiBBbnkgInJlbW90ZSIgb2JzZXJ2ZXJzIChpLmUuIG9ic2VydmVyIG1ldGhvZHMgZGVjbGFyZWQgb24KICAgICAgYW5vdGhlciBvYmplY3QpIHdpbGwgYmUgcGxhY2VkIGluIGEgcXVldWUgYW5kIGNhbGxlZCBhdCBhIGxhdGVyIHRpbWUgaW4gYQogICAgICBjb2FsZXNjZWQgbWFubmVyLgogICAgICAgQG1ldGhvZCBzZXQKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIHByb3BlcnR5IHRvIHNldAogICAgICBAcGFyYW0ge09iamVjdH0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldCBvciBgbnVsbGAuCiAgICAgIEByZXR1cm4ge09iamVjdH0gVGhlIHBhc3NlZCB2YWx1ZQogICAgICBAcHVibGljCiAgICAqLwogICAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5TmFtZSwgdmFsdWUpIHsKICAgICAgcmV0dXJuICgwLCBfbWV0YWwuc2V0KSh0aGlzLCBrZXlOYW1lLCB2YWx1ZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBTZXRzIGEgbGlzdCBvZiBwcm9wZXJ0aWVzIGF0IG9uY2UuIFRoZXNlIHByb3BlcnRpZXMgYXJlIHNldCBpbnNpZGUKICAgICAgYSBzaW5nbGUgYGJlZ2luUHJvcGVydHlDaGFuZ2VzYCBhbmQgYGVuZFByb3BlcnR5Q2hhbmdlc2AgYmF0Y2gsIHNvCiAgICAgIG9ic2VydmVycyB3aWxsIGJlIGJ1ZmZlcmVkLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICByZWNvcmQuc2V0UHJvcGVydGllcyh7IGZpcnN0TmFtZTogJ0NoYXJsZXMnLCBsYXN0TmFtZTogJ0pvbGxleScgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXRQcm9wZXJ0aWVzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBoYXNoIHRoZSBoYXNoIG9mIGtleXMgYW5kIHZhbHVlcyB0byBzZXQKICAgICAgQHJldHVybiB7T2JqZWN0fSBUaGUgcGFzc2VkIGluIGhhc2gKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHNldFByb3BlcnRpZXM6IGZ1bmN0aW9uIHNldFByb3BlcnRpZXMoaGFzaCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5zZXRQcm9wZXJ0aWVzKSh0aGlzLCBoYXNoKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEJlZ2lucyBhIGdyb3VwaW5nIG9mIHByb3BlcnR5IGNoYW5nZXMuCiAgICAgICBZb3UgY2FuIHVzZSB0aGlzIG1ldGhvZCB0byBncm91cCBwcm9wZXJ0eSBjaGFuZ2VzIHNvIHRoYXQgbm90aWZpY2F0aW9ucwogICAgICB3aWxsIG5vdCBiZSBzZW50IHVudGlsIHRoZSBjaGFuZ2VzIGFyZSBmaW5pc2hlZC4gSWYgeW91IHBsYW4gdG8gbWFrZSBhCiAgICAgIGxhcmdlIG51bWJlciBvZiBjaGFuZ2VzIHRvIGFuIG9iamVjdCBhdCBvbmUgdGltZSwgeW91IHNob3VsZCBjYWxsIHRoaXMKICAgICAgbWV0aG9kIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGNoYW5nZXMgdG8gYmVnaW4gZGVmZXJyaW5nIGNoYW5nZQogICAgICBub3RpZmljYXRpb25zLiBXaGVuIHlvdSBhcmUgZG9uZSBtYWtpbmcgY2hhbmdlcywgY2FsbAogICAgICBgZW5kUHJvcGVydHlDaGFuZ2VzKClgIHRvIGRlbGl2ZXIgdGhlIGRlZmVycmVkIGNoYW5nZSBub3RpZmljYXRpb25zIGFuZCBlbmQKICAgICAgZGVmZXJyaW5nLgogICAgICAgQG1ldGhvZCBiZWdpblByb3BlcnR5Q2hhbmdlcwogICAgICBAcmV0dXJuIHtPYnNlcnZhYmxlfQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGJlZ2luUHJvcGVydHlDaGFuZ2VzOiBmdW5jdGlvbiBiZWdpblByb3BlcnR5Q2hhbmdlcygpIHsKICAgICAgKDAsIF9tZXRhbC5iZWdpblByb3BlcnR5Q2hhbmdlcykoKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgICBFbmRzIGEgZ3JvdXBpbmcgb2YgcHJvcGVydHkgY2hhbmdlcy4KICAgICAgIFlvdSBjYW4gdXNlIHRoaXMgbWV0aG9kIHRvIGdyb3VwIHByb3BlcnR5IGNoYW5nZXMgc28gdGhhdCBub3RpZmljYXRpb25zCiAgICAgIHdpbGwgbm90IGJlIHNlbnQgdW50aWwgdGhlIGNoYW5nZXMgYXJlIGZpbmlzaGVkLiBJZiB5b3UgcGxhbiB0byBtYWtlIGEKICAgICAgbGFyZ2UgbnVtYmVyIG9mIGNoYW5nZXMgdG8gYW4gb2JqZWN0IGF0IG9uZSB0aW1lLCB5b3Ugc2hvdWxkIGNhbGwKICAgICAgYGJlZ2luUHJvcGVydHlDaGFuZ2VzKClgIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGNoYW5nZXMgdG8gZGVmZXIgY2hhbmdlCiAgICAgIG5vdGlmaWNhdGlvbnMuIFdoZW4geW91IGFyZSBkb25lIG1ha2luZyBjaGFuZ2VzLCBjYWxsIHRoaXMgbWV0aG9kIHRvCiAgICAgIGRlbGl2ZXIgdGhlIGRlZmVycmVkIGNoYW5nZSBub3RpZmljYXRpb25zIGFuZCBlbmQgZGVmZXJyaW5nLgogICAgICAgQG1ldGhvZCBlbmRQcm9wZXJ0eUNoYW5nZXMKICAgICAgQHJldHVybiB7T2JzZXJ2YWJsZX0KICAgICAgQHByaXZhdGUKICAgICovCiAgICBlbmRQcm9wZXJ0eUNoYW5nZXM6IGZ1bmN0aW9uIGVuZFByb3BlcnR5Q2hhbmdlcygpIHsKICAgICAgKDAsIF9tZXRhbC5lbmRQcm9wZXJ0eUNoYW5nZXMpKCk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKCiAgICAvKioKICAgICAgTm90aWZ5IHRoZSBvYnNlcnZlciBzeXN0ZW0gdGhhdCBhIHByb3BlcnR5IGhhcyBqdXN0IGNoYW5nZWQuCiAgICAgICBTb21ldGltZXMgeW91IG5lZWQgdG8gY2hhbmdlIGEgdmFsdWUgZGlyZWN0bHkgb3IgaW5kaXJlY3RseSB3aXRob3V0CiAgICAgIGFjdHVhbGx5IGNhbGxpbmcgYGdldCgpYCBvciBgc2V0KClgIG9uIGl0LiBJbiB0aGlzIGNhc2UsIHlvdSBjYW4gdXNlIHRoaXMKICAgICAgbWV0aG9kIGluc3RlYWQuIENhbGxpbmcgdGhpcyBtZXRob2Qgd2lsbCBub3RpZnkgYWxsIG9ic2VydmVycyB0aGF0IHRoZQogICAgICBwcm9wZXJ0eSBoYXMgcG90ZW50aWFsbHkgY2hhbmdlZCB2YWx1ZS4KICAgICAgIEBtZXRob2Qgbm90aWZ5UHJvcGVydHlDaGFuZ2UKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIHByb3BlcnR5IGtleSB0byBiZSBub3RpZmllZCBhYm91dC4KICAgICAgQHJldHVybiB7T2JzZXJ2YWJsZX0KICAgICAgQHB1YmxpYwogICAgKi8KICAgIG5vdGlmeVByb3BlcnR5Q2hhbmdlOiBmdW5jdGlvbiBub3RpZnlQcm9wZXJ0eUNoYW5nZShrZXlOYW1lKSB7CiAgICAgICgwLCBfbWV0YWwubm90aWZ5UHJvcGVydHlDaGFuZ2UpKHRoaXMsIGtleU5hbWUpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCgogICAgLyoqCiAgICAgIEFkZHMgYW4gb2JzZXJ2ZXIgb24gYSBwcm9wZXJ0eS4KICAgICAgIFRoaXMgaXMgdGhlIGNvcmUgbWV0aG9kIHVzZWQgdG8gcmVnaXN0ZXIgYW4gb2JzZXJ2ZXIgZm9yIGEgcHJvcGVydHkuCiAgICAgICBPbmNlIHlvdSBjYWxsIHRoaXMgbWV0aG9kLCBhbnkgdGltZSB0aGUga2V5J3MgdmFsdWUgaXMgc2V0LCB5b3VyIG9ic2VydmVyCiAgICAgIHdpbGwgYmUgbm90aWZpZWQuIE5vdGUgdGhhdCB0aGUgb2JzZXJ2ZXJzIGFyZSB0cmlnZ2VyZWQgYW55IHRpbWUgdGhlCiAgICAgIHZhbHVlIGlzIHNldCwgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIGl0IGhhcyBhY3R1YWxseSBjaGFuZ2VkLiBZb3VyCiAgICAgIG9ic2VydmVyIHNob3VsZCBiZSBwcmVwYXJlZCB0byBoYW5kbGUgdGhhdC4KICAgICAgIFRoZXJlIGFyZSB0d28gY29tbW9uIGludm9jYXRpb24gcGF0dGVybnMgZm9yIGAuYWRkT2JzZXJ2ZXIoKWA6CiAgICAgICAtIFBhc3NpbmcgdHdvIGFyZ3VtZW50czoKICAgICAgICAtIHRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBvYnNlcnZlIChhcyBhIHN0cmluZykKICAgICAgICAtIHRoZSBmdW5jdGlvbiB0byBpbnZva2UgKGFuIGFjdHVhbCBmdW5jdGlvbikKICAgICAgLSBQYXNzaW5nIHRocmVlIGFyZ3VtZW50czoKICAgICAgICAtIHRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBvYnNlcnZlIChhcyBhIHN0cmluZykKICAgICAgICAtIHRoZSB0YXJnZXQgb2JqZWN0ICh3aWxsIGJlIHVzZWQgdG8gbG9vayB1cCBhbmQgaW52b2tlIGEKICAgICAgICAgIGZ1bmN0aW9uIG9uKQogICAgICAgIC0gdGhlIG5hbWUgb2YgdGhlIGZ1bmN0aW9uIHRvIGludm9rZSBvbiB0aGUgdGFyZ2V0IG9iamVjdAogICAgICAgICAgKGFzIGEgc3RyaW5nKS4KICAgICAgIGBgYGFwcC9jb21wb25lbnRzL215LWNvbXBvbmVudC5qcwogICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgaW5pdCgpIHsKICAgICAgICAgIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cyk7CiAgICAgICAgICAgLy8gdGhlIGZvbGxvd2luZyBhcmUgZXF1aXZhbGVudDoKICAgICAgICAgICAvLyB1c2luZyB0aHJlZSBhcmd1bWVudHMKICAgICAgICAgIHRoaXMuYWRkT2JzZXJ2ZXIoJ2ZvbycsIHRoaXMsICdmb29EaWRDaGFuZ2UnKTsKICAgICAgICAgICAvLyB1c2luZyB0d28gYXJndW1lbnRzCiAgICAgICAgICB0aGlzLmFkZE9ic2VydmVyKCdmb28nLCAoLi4uYXJncykgPT4gewogICAgICAgICAgICB0aGlzLmZvb0RpZENoYW5nZSguLi5hcmdzKTsKICAgICAgICAgIH0pOwogICAgICAgIH0sCiAgICAgICAgIGZvb0RpZENoYW5nZSgpIHsKICAgICAgICAgIC8vIHlvdXIgY3VzdG9tIGxvZ2ljIGNvZGUKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgICMjIyBPYnNlcnZlciBNZXRob2RzCiAgICAgICBPYnNlcnZlciBtZXRob2RzIGhhdmUgdGhlIGZvbGxvd2luZyBzaWduYXR1cmU6CiAgICAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICAgIGluaXQoKSB7CiAgICAgICAgICB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogICAgICAgICAgdGhpcy5hZGRPYnNlcnZlcignZm9vJywgdGhpcywgJ2Zvb0RpZENoYW5nZScpOwogICAgICAgIH0sCiAgICAgICAgIGZvb0RpZENoYW5nZShzZW5kZXIsIGtleSwgdmFsdWUsIHJldikgewogICAgICAgICAgLy8geW91ciBjb2RlCiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBUaGUgYHNlbmRlcmAgaXMgdGhlIG9iamVjdCB0aGF0IGNoYW5nZWQuIFRoZSBga2V5YCBpcyB0aGUgcHJvcGVydHkgdGhhdAogICAgICBjaGFuZ2VzLiBUaGUgYHZhbHVlYCBwcm9wZXJ0eSBpcyBjdXJyZW50bHkgcmVzZXJ2ZWQgYW5kIHVudXNlZC4gVGhlIGByZXZgCiAgICAgIGlzIHRoZSBsYXN0IHByb3BlcnR5IHJldmlzaW9uIG9mIHRoZSBvYmplY3Qgd2hlbiBpdCBjaGFuZ2VkLCB3aGljaCB5b3UgY2FuCiAgICAgIHVzZSB0byBkZXRlY3QgaWYgdGhlIGtleSB2YWx1ZSBoYXMgcmVhbGx5IGNoYW5nZWQgb3Igbm90LgogICAgICAgVXN1YWxseSB5b3Ugd2lsbCBub3QgbmVlZCB0aGUgdmFsdWUgb3IgcmV2aXNpb24gcGFyYW1ldGVycyBhdAogICAgICB0aGUgZW5kLiBJbiB0aGlzIGNhc2UsIGl0IGlzIGNvbW1vbiB0byB3cml0ZSBvYnNlcnZlciBtZXRob2RzIHRoYXQgdGFrZQogICAgICBvbmx5IGEgc2VuZGVyIGFuZCBrZXkgdmFsdWUgYXMgcGFyYW1ldGVycyBvciwgaWYgeW91IGFyZW4ndCBpbnRlcmVzdGVkIGluCiAgICAgIGFueSBvZiB0aGVzZSB2YWx1ZXMsIHRvIHdyaXRlIGFuIG9ic2VydmVyIHRoYXQgaGFzIG5vIHBhcmFtZXRlcnMgYXQgYWxsLgogICAgICAgQG1ldGhvZCBhZGRPYnNlcnZlcgogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5IFRoZSBrZXkgdG8gb2JzZXJ2ZQogICAgICBAcGFyYW0ge09iamVjdH0gdGFyZ2V0IFRoZSB0YXJnZXQgb2JqZWN0IHRvIGludm9rZQogICAgICBAcGFyYW0ge1N0cmluZ3xGdW5jdGlvbn0gbWV0aG9kIFRoZSBtZXRob2QgdG8gaW52b2tlCiAgICAgIEBwYXJhbSB7Qm9vbGVhbn0gYXN5bmMgV2hldGhlciB0aGUgb2JzZXJ2ZXIgaXMgYXN5bmMgb3Igbm90CiAgICAgIEByZXR1cm4ge09ic2VydmFibGV9CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBhZGRPYnNlcnZlcjogZnVuY3Rpb24gYWRkT2JzZXJ2ZXIoa2V5LCB0YXJnZXQsIG1ldGhvZCwgYXN5bmMpIHsKICAgICAgKDAsIF9tZXRhbC5hZGRPYnNlcnZlcikodGhpcywga2V5LCB0YXJnZXQsIG1ldGhvZCwgYXN5bmMpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCgogICAgLyoqCiAgICAgIFJlbW92ZSBhbiBvYnNlcnZlciB5b3UgaGF2ZSBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgb24gdGhpcyBvYmplY3QuIFBhc3MKICAgICAgdGhlIHNhbWUga2V5LCB0YXJnZXQsIGFuZCBtZXRob2QgeW91IHBhc3NlZCB0byBgYWRkT2JzZXJ2ZXIoKWAgYW5kIHlvdXIKICAgICAgdGFyZ2V0IHdpbGwgbm8gbG9uZ2VyIHJlY2VpdmUgbm90aWZpY2F0aW9ucy4KICAgICAgIEBtZXRob2QgcmVtb3ZlT2JzZXJ2ZXIKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleSBUaGUga2V5IHRvIG9ic2VydmUKICAgICAgQHBhcmFtIHtPYmplY3R9IHRhcmdldCBUaGUgdGFyZ2V0IG9iamVjdCB0byBpbnZva2UKICAgICAgQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IG1ldGhvZCBUaGUgbWV0aG9kIHRvIGludm9rZQogICAgICBAcGFyYW0ge0Jvb2xlYW59IGFzeW5jIFdoZXRoZXIgdGhlIG9ic2VydmVyIGlzIGFzeW5jIG9yIG5vdAogICAgICBAcmV0dXJuIHtPYnNlcnZhYmxlfQogICAgICBAcHVibGljCiAgICAqLwogICAgcmVtb3ZlT2JzZXJ2ZXI6IGZ1bmN0aW9uIHJlbW92ZU9ic2VydmVyKGtleSwgdGFyZ2V0LCBtZXRob2QsIGFzeW5jKSB7CiAgICAgICgwLCBfbWV0YWwucmVtb3ZlT2JzZXJ2ZXIpKHRoaXMsIGtleSwgdGFyZ2V0LCBtZXRob2QsIGFzeW5jKTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0IGN1cnJlbnRseSBoYXMgb2JzZXJ2ZXJzIHJlZ2lzdGVyZWQgZm9yIGEKICAgICAgcGFydGljdWxhciBrZXkuIFlvdSBjYW4gdXNlIHRoaXMgbWV0aG9kIHRvIHBvdGVudGlhbGx5IGRlZmVyIHBlcmZvcm1pbmcKICAgICAgYW4gZXhwZW5zaXZlIGFjdGlvbiB1bnRpbCBzb21lb25lIGJlZ2lucyBvYnNlcnZpbmcgYSBwYXJ0aWN1bGFyIHByb3BlcnR5CiAgICAgIG9uIHRoZSBvYmplY3QuCiAgICAgICBAbWV0aG9kIGhhc09ic2VydmVyRm9yCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkgS2V5IHRvIGNoZWNrCiAgICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgaGFzT2JzZXJ2ZXJGb3I6IGZ1bmN0aW9uIGhhc09ic2VydmVyRm9yKGtleSkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5oYXNMaXN0ZW5lcnMpKHRoaXMsIGtleSArICI6Y2hhbmdlIik7CiAgICB9LAoKICAgIC8qKgogICAgICBSZXRyaWV2ZXMgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHksIG9yIGEgZGVmYXVsdCB2YWx1ZSBpbiB0aGUgY2FzZSB0aGF0IHRoZQogICAgICBwcm9wZXJ0eSByZXR1cm5zIGB1bmRlZmluZWRgLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBwZXJzb24uZ2V0V2l0aERlZmF1bHQoJ2xhc3ROYW1lJywgJ0RvZScpOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZ2V0V2l0aERlZmF1bHQKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIHJldHJpZXZlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBkZWZhdWx0VmFsdWUgVGhlIHZhbHVlIHRvIHJldHVybiBpZiB0aGUgcHJvcGVydHkgdmFsdWUgaXMgdW5kZWZpbmVkCiAgICAgIEByZXR1cm4ge09iamVjdH0gVGhlIHByb3BlcnR5IHZhbHVlIG9yIHRoZSBkZWZhdWx0VmFsdWUuCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBnZXRXaXRoRGVmYXVsdDogZnVuY3Rpb24gZ2V0V2l0aERlZmF1bHQoa2V5TmFtZSwgZGVmYXVsdFZhbHVlKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldFdpdGhEZWZhdWx0KSh0aGlzLCBrZXlOYW1lLCBkZWZhdWx0VmFsdWUpOwogICAgfSwKCiAgICAvKioKICAgICAgU2V0IHRoZSB2YWx1ZSBvZiBhIHByb3BlcnR5IHRvIHRoZSBjdXJyZW50IHZhbHVlIHBsdXMgc29tZSBhbW91bnQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHBlcnNvbi5pbmNyZW1lbnRQcm9wZXJ0eSgnYWdlJyk7CiAgICAgIHRlYW0uaW5jcmVtZW50UHJvcGVydHkoJ3Njb3JlJywgMik7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBpbmNyZW1lbnRQcm9wZXJ0eQogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5TmFtZSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdG8gaW5jcmVtZW50CiAgICAgIEBwYXJhbSB7TnVtYmVyfSBpbmNyZW1lbnQgVGhlIGFtb3VudCB0byBpbmNyZW1lbnQgYnkuIERlZmF1bHRzIHRvIDEKICAgICAgQHJldHVybiB7TnVtYmVyfSBUaGUgbmV3IHByb3BlcnR5IHZhbHVlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBpbmNyZW1lbnRQcm9wZXJ0eTogZnVuY3Rpb24gaW5jcmVtZW50UHJvcGVydHkoa2V5TmFtZSwgaW5jcmVtZW50KSB7CiAgICAgIGlmIChpbmNyZW1lbnQgPT09IHZvaWQgMCkgewogICAgICAgIGluY3JlbWVudCA9IDE7CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKCFpc05hTihwYXJzZUZsb2F0KGluY3JlbWVudCkpICYmIGlzRmluaXRlKGluY3JlbWVudCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnTXVzdCBwYXNzIGEgbnVtZXJpYyB2YWx1ZSB0byBpbmNyZW1lbnRQcm9wZXJ0eScsICFpc05hTihwYXJzZUZsb2F0KGluY3JlbWVudCkpICYmIGlzRmluaXRlKGluY3JlbWVudCkpKTsKICAgICAgcmV0dXJuICgwLCBfbWV0YWwuc2V0KSh0aGlzLCBrZXlOYW1lLCAocGFyc2VGbG9hdCgoMCwgX21ldGFsLmdldCkodGhpcywga2V5TmFtZSkpIHx8IDApICsgaW5jcmVtZW50KTsKICAgIH0sCgogICAgLyoqCiAgICAgIFNldCB0aGUgdmFsdWUgb2YgYSBwcm9wZXJ0eSB0byB0aGUgY3VycmVudCB2YWx1ZSBtaW51cyBzb21lIGFtb3VudC4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgcGxheWVyLmRlY3JlbWVudFByb3BlcnR5KCdsaXZlcycpOwogICAgICBvcmMuZGVjcmVtZW50UHJvcGVydHkoJ2hlYWx0aCcsIDUpOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZGVjcmVtZW50UHJvcGVydHkKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUgVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIGRlY3JlbWVudAogICAgICBAcGFyYW0ge051bWJlcn0gZGVjcmVtZW50IFRoZSBhbW91bnQgdG8gZGVjcmVtZW50IGJ5LiBEZWZhdWx0cyB0byAxCiAgICAgIEByZXR1cm4ge051bWJlcn0gVGhlIG5ldyBwcm9wZXJ0eSB2YWx1ZQogICAgICBAcHVibGljCiAgICAqLwogICAgZGVjcmVtZW50UHJvcGVydHk6IGZ1bmN0aW9uIGRlY3JlbWVudFByb3BlcnR5KGtleU5hbWUsIGRlY3JlbWVudCkgewogICAgICBpZiAoZGVjcmVtZW50ID09PSB2b2lkIDApIHsKICAgICAgICBkZWNyZW1lbnQgPSAxOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISghaXNOYU4ocGFyc2VGbG9hdChkZWNyZW1lbnQpKSAmJiBpc0Zpbml0ZShkZWNyZW1lbnQpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ011c3QgcGFzcyBhIG51bWVyaWMgdmFsdWUgdG8gZGVjcmVtZW50UHJvcGVydHknLCAhaXNOYU4ocGFyc2VGbG9hdChkZWNyZW1lbnQpKSAmJiBpc0Zpbml0ZShkZWNyZW1lbnQpKSk7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLnNldCkodGhpcywga2V5TmFtZSwgKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBrZXlOYW1lKSB8fCAwKSAtIGRlY3JlbWVudCk7CiAgICB9LAoKICAgIC8qKgogICAgICBTZXQgdGhlIHZhbHVlIG9mIGEgYm9vbGVhbiBwcm9wZXJ0eSB0byB0aGUgb3Bwb3NpdGUgb2YgaXRzCiAgICAgIGN1cnJlbnQgdmFsdWUuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0YXJzaGlwLnRvZ2dsZVByb3BlcnR5KCd3YXJwRHJpdmVFbmdhZ2VkJyk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCB0b2dnbGVQcm9wZXJ0eQogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5TmFtZSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdG8gdG9nZ2xlCiAgICAgIEByZXR1cm4ge0Jvb2xlYW59IFRoZSBuZXcgcHJvcGVydHkgdmFsdWUKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHRvZ2dsZVByb3BlcnR5OiBmdW5jdGlvbiB0b2dnbGVQcm9wZXJ0eShrZXlOYW1lKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLnNldCkodGhpcywga2V5TmFtZSwgISgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBrZXlOYW1lKSk7CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSBjYWNoZWQgdmFsdWUgb2YgYSBjb21wdXRlZCBwcm9wZXJ0eSwgaWYgaXQgZXhpc3RzLgogICAgICBUaGlzIGFsbG93cyB5b3UgdG8gaW5zcGVjdCB0aGUgdmFsdWUgb2YgYSBjb21wdXRlZCBwcm9wZXJ0eQogICAgICB3aXRob3V0IGFjY2lkZW50YWxseSBpbnZva2luZyBpdCBpZiBpdCBpcyBpbnRlbmRlZCB0byBiZQogICAgICBnZW5lcmF0ZWQgbGF6aWx5LgogICAgICAgQG1ldGhvZCBjYWNoZUZvcgogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5TmFtZQogICAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSBjYWNoZWQgdmFsdWUgb2YgdGhlIGNvbXB1dGVkIHByb3BlcnR5LCBpZiBhbnkKICAgICAgQHB1YmxpYwogICAgKi8KICAgIGNhY2hlRm9yOiBmdW5jdGlvbiBjYWNoZUZvcihrZXlOYW1lKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldENhY2hlZFZhbHVlRm9yKSh0aGlzLCBrZXlOYW1lKTsKICAgIH0KICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvcHJvbWlzZV9wcm94eSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZXJyb3IiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwsIF9lcnJvcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci9vYmplY3QKICAqLwogIGZ1bmN0aW9uIHRhcChwcm94eSwgcHJvbWlzZSkgewogICAgKDAsIF9tZXRhbC5zZXRQcm9wZXJ0aWVzKShwcm94eSwgewogICAgICBpc0Z1bGZpbGxlZDogZmFsc2UsCiAgICAgIGlzUmVqZWN0ZWQ6IGZhbHNlCiAgICB9KTsKICAgIHJldHVybiBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgIGlmICghcHJveHkuaXNEZXN0cm95ZWQgJiYgIXByb3h5LmlzRGVzdHJveWluZykgewogICAgICAgICgwLCBfbWV0YWwuc2V0UHJvcGVydGllcykocHJveHksIHsKICAgICAgICAgIGNvbnRlbnQ6IHZhbHVlLAogICAgICAgICAgaXNGdWxmaWxsZWQ6IHRydWUKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICBpZiAoIXByb3h5LmlzRGVzdHJveWVkICYmICFwcm94eS5pc0Rlc3Ryb3lpbmcpIHsKICAgICAgICAoMCwgX21ldGFsLnNldFByb3BlcnRpZXMpKHByb3h5LCB7CiAgICAgICAgICByZWFzb246IHJlYXNvbiwKICAgICAgICAgIGlzUmVqZWN0ZWQ6IHRydWUKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgdGhyb3cgcmVhc29uOwogICAgfSwgJ0VtYmVyOiBQcm9taXNlUHJveHknKTsKICB9CiAgLyoqCiAgICBBIGxvdyBsZXZlbCBtaXhpbiBtYWtpbmcgT2JqZWN0UHJveHkgcHJvbWlzZS1hd2FyZS4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHJlc29sdmUgfSBmcm9tICdyc3ZwJzsKICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeSc7CiAgICBpbXBvcnQgT2JqZWN0UHJveHkgZnJvbSAnQGVtYmVyL29iamVjdC9wcm94eSc7CiAgICBpbXBvcnQgUHJvbWlzZVByb3h5TWl4aW4gZnJvbSAnQGVtYmVyL29iamVjdC9wcm9taXNlLXByb3h5LW1peGluJzsKICAKICAgIGxldCBPYmplY3RQcm9taXNlUHJveHkgPSBPYmplY3RQcm94eS5leHRlbmQoUHJvbWlzZVByb3h5TWl4aW4pOwogIAogICAgbGV0IHByb3h5ID0gT2JqZWN0UHJvbWlzZVByb3h5LmNyZWF0ZSh7CiAgICAgIHByb21pc2U6IHJlc29sdmUoJC5nZXRKU09OKCcvc29tZS9yZW1vdGUvZGF0YS5qc29uJykpCiAgICB9KTsKICAKICAgIHByb3h5LnRoZW4oZnVuY3Rpb24oanNvbil7CiAgICAgICAvLyB0aGUganNvbgogICAgfSwgZnVuY3Rpb24ocmVhc29uKSB7CiAgICAgICAvLyB0aGUgcmVhc29uIHdoeSB5b3UgaGF2ZSBubyBqc29uCiAgICB9KTsKICAgIGBgYAogIAogICAgdGhlIHByb3h5IGhhcyBiaW5kYWJsZSBhdHRyaWJ1dGVzIHdoaWNoCiAgICB0cmFjayB0aGUgcHJvbWlzZXMgbGlmZSBjeWNsZQogIAogICAgYGBgamF2YXNjcmlwdAogICAgcHJveHkuZ2V0KCdpc1BlbmRpbmcnKSAgIC8vPT4gdHJ1ZQogICAgcHJveHkuZ2V0KCdpc1NldHRsZWQnKSAgLy89PiBmYWxzZQogICAgcHJveHkuZ2V0KCdpc1JlamVjdGVkJykgIC8vPT4gZmFsc2UKICAgIHByb3h5LmdldCgnaXNGdWxmaWxsZWQnKSAvLz0+IGZhbHNlCiAgICBgYGAKICAKICAgIFdoZW4gdGhlICQuZ2V0SlNPTiBjb21wbGV0ZXMsIGFuZCB0aGUgcHJvbWlzZSBpcyBmdWxmaWxsZWQKICAgIHdpdGgganNvbiwgdGhlIGxpZmUgY3ljbGUgYXR0cmlidXRlcyB3aWxsIHVwZGF0ZSBhY2NvcmRpbmdseS4KICAgIE5vdGUgdGhhdCAkLmdldEpTT04gZG9lc24ndCByZXR1cm4gYW4gRUNNQSBzcGVjaWZpZWQgcHJvbWlzZSwKICAgIGl0IGlzIHVzZWZ1bCB0byB3cmFwIHRoaXMgd2l0aCBhbiBgUlNWUC5yZXNvbHZlYCBzbyB0aGF0IGl0IGJlaGF2ZXMKICAgIGFzIGEgc3BlYyBjb21wbGlhbnQgcHJvbWlzZS4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIHByb3h5LmdldCgnaXNQZW5kaW5nJykgICAvLz0+IGZhbHNlCiAgICBwcm94eS5nZXQoJ2lzU2V0dGxlZCcpICAgLy89PiB0cnVlCiAgICBwcm94eS5nZXQoJ2lzUmVqZWN0ZWQnKSAgLy89PiBmYWxzZQogICAgcHJveHkuZ2V0KCdpc0Z1bGZpbGxlZCcpIC8vPT4gdHJ1ZQogICAgYGBgCiAgCiAgICBBcyB0aGUgcHJveHkgaXMgYW4gT2JqZWN0UHJveHksIGFuZCB0aGUganNvbiBub3cgaXRzIGNvbnRlbnQsCiAgICBhbGwgdGhlIGpzb24gcHJvcGVydGllcyB3aWxsIGJlIGF2YWlsYWJsZSBkaXJlY3RseSBmcm9tIHRoZSBwcm94eS4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIC8vIEFzc3VtaW5nIHRoZSBmb2xsb3dpbmcganNvbjoKICAgIHsKICAgICAgZmlyc3ROYW1lOiAnU3RlZmFuJywKICAgICAgbGFzdE5hbWU6ICdQZW5uZXInCiAgICB9CiAgCiAgICAvLyBib3RoIHByb3BlcnRpZXMgd2lsbCBhY2Nlc3NpYmxlIG9uIHRoZSBwcm94eQogICAgcHJveHkuZ2V0KCdmaXJzdE5hbWUnKSAvLz0+ICdTdGVmYW4nCiAgICBwcm94eS5nZXQoJ2xhc3ROYW1lJykgIC8vPT4gJ1Blbm5lcicKICAgIGBgYAogIAogICAgQGNsYXNzIFByb21pc2VQcm94eU1peGluCiAgICBAcHVibGljCiAgKi8KCgogIHZhciBfZGVmYXVsdCA9IF9tZXRhbC5NaXhpbi5jcmVhdGUoewogICAgLyoqCiAgICAgIElmIHRoZSBwcm94aWVkIHByb21pc2UgaXMgcmVqZWN0ZWQgdGhpcyB3aWxsIGNvbnRhaW4gdGhlIHJlYXNvbgogICAgICBwcm92aWRlZC4KICAgICAgIEBwcm9wZXJ0eSByZWFzb24KICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwogICAgcmVhc29uOiBudWxsLAoKICAgIC8qKgogICAgICBPbmNlIHRoZSBwcm94aWVkIHByb21pc2UgaGFzIHNldHRsZWQgdGhpcyB3aWxsIGJlY29tZSBgZmFsc2VgLgogICAgICAgQHByb3BlcnR5IGlzUGVuZGluZwogICAgICBAZGVmYXVsdCB0cnVlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBpc1BlbmRpbmc6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKCdpc1NldHRsZWQnLCBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAhKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdpc1NldHRsZWQnKTsKICAgIH0pLnJlYWRPbmx5KCksCgogICAgLyoqCiAgICAgIE9uY2UgdGhlIHByb3hpZWQgcHJvbWlzZSBoYXMgc2V0dGxlZCB0aGlzIHdpbGwgYmVjb21lIGB0cnVlYC4KICAgICAgIEBwcm9wZXJ0eSBpc1NldHRsZWQKICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgQHB1YmxpYwogICAgKi8KICAgIGlzU2V0dGxlZDogKDAsIF9tZXRhbC5jb21wdXRlZCkoJ2lzUmVqZWN0ZWQnLCAnaXNGdWxmaWxsZWQnLCBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkodGhpcywgJ2lzUmVqZWN0ZWQnKSB8fCAoMCwgX21ldGFsLmdldCkodGhpcywgJ2lzRnVsZmlsbGVkJyk7CiAgICB9KS5yZWFkT25seSgpLAoKICAgIC8qKgogICAgICBXaWxsIGJlY29tZSBgdHJ1ZWAgaWYgdGhlIHByb3hpZWQgcHJvbWlzZSBpcyByZWplY3RlZC4KICAgICAgIEBwcm9wZXJ0eSBpc1JlamVjdGVkCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBpc1JlamVjdGVkOiBmYWxzZSwKCiAgICAvKioKICAgICAgV2lsbCBiZWNvbWUgYHRydWVgIGlmIHRoZSBwcm94aWVkIHByb21pc2UgaXMgZnVsZmlsbGVkLgogICAgICAgQHByb3BlcnR5IGlzRnVsZmlsbGVkCiAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBpc0Z1bGZpbGxlZDogZmFsc2UsCgogICAgLyoqCiAgICAgIFRoZSBwcm9taXNlIHdob3NlIGZ1bGZpbGxtZW50IHZhbHVlIGlzIGJlaW5nIHByb3hpZWQgYnkgdGhpcyBvYmplY3QuCiAgICAgICBUaGlzIHByb3BlcnR5IG11c3QgYmUgc3BlY2lmaWVkIHVwb24gY3JlYXRpb24sIGFuZCBzaG91bGQgbm90IGJlCiAgICAgIGNoYW5nZWQgb25jZSBjcmVhdGVkLgogICAgICAgRXhhbXBsZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IE9iamVjdFByb3h5IGZyb20gJ0BlbWJlci9vYmplY3QvcHJveHknOwogICAgICBpbXBvcnQgUHJvbWlzZVByb3h5TWl4aW4gZnJvbSAnQGVtYmVyL29iamVjdC9wcm9taXNlLXByb3h5LW1peGluJzsKICAgICAgIE9iamVjdFByb3h5LmV4dGVuZChQcm9taXNlUHJveHlNaXhpbikuY3JlYXRlKHsKICAgICAgICBwcm9taXNlOiA8dGhlbmFibGU+CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBwcm9taXNlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBwcm9taXNlOiAoMCwgX21ldGFsLmNvbXB1dGVkKSh7CiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHRocm93IG5ldyBfZXJyb3IuZGVmYXVsdCgiUHJvbWlzZVByb3h5J3MgcHJvbWlzZSBtdXN0IGJlIHNldCIpOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldChrZXksIHByb21pc2UpIHsKICAgICAgICByZXR1cm4gdGFwKHRoaXMsIHByb21pc2UpOwogICAgICB9CiAgICB9KSwKCiAgICAvKioKICAgICAgQW4gYWxpYXMgdG8gdGhlIHByb3hpZWQgcHJvbWlzZSdzIGB0aGVuYC4KICAgICAgIFNlZSBSU1ZQLlByb21pc2UudGhlbi4KICAgICAgIEBtZXRob2QgdGhlbgogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgICBAcmV0dXJuIHtSU1ZQLlByb21pc2V9CiAgICAgIEBwdWJsaWMKICAgICovCiAgICB0aGVuOiBwcm9taXNlQWxpYXMoJ3RoZW4nKSwKCiAgICAvKioKICAgICAgQW4gYWxpYXMgdG8gdGhlIHByb3hpZWQgcHJvbWlzZSdzIGBjYXRjaGAuCiAgICAgICBTZWUgUlNWUC5Qcm9taXNlLmNhdGNoLgogICAgICAgQG1ldGhvZCBjYXRjaAogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgICBAcmV0dXJuIHtSU1ZQLlByb21pc2V9CiAgICAgIEBzaW5jZSAxLjMuMAogICAgICBAcHVibGljCiAgICAqLwogICAgY2F0Y2g6IHByb21pc2VBbGlhcygnY2F0Y2gnKSwKCiAgICAvKioKICAgICAgQW4gYWxpYXMgdG8gdGhlIHByb3hpZWQgcHJvbWlzZSdzIGBmaW5hbGx5YC4KICAgICAgIFNlZSBSU1ZQLlByb21pc2UuZmluYWxseS4KICAgICAgIEBtZXRob2QgZmluYWxseQogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgICBAcmV0dXJuIHtSU1ZQLlByb21pc2V9CiAgICAgIEBzaW5jZSAxLjMuMAogICAgICBAcHVibGljCiAgICAqLwogICAgZmluYWxseTogcHJvbWlzZUFsaWFzKCdmaW5hbGx5JykKICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OwoKICBmdW5jdGlvbiBwcm9taXNlQWxpYXMobmFtZSkgewogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIHByb21pc2UgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ3Byb21pc2UnKTsKICAgICAgcmV0dXJuIHByb21pc2VbbmFtZV0uYXBwbHkocHJvbWlzZSwgYXJndW1lbnRzKTsKICAgIH07CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9taXhpbnMvcmVnaXN0cnlfcHJveHkiLCBbImV4cG9ydHMiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlYnVnLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIFJlZ2lzdHJ5UHJveHlNaXhpbiBpcyB1c2VkIHRvIHByb3ZpZGUgcHVibGljIGFjY2VzcyB0byBzcGVjaWZpYwogICAgcmVnaXN0cnkgZnVuY3Rpb25hbGl0eS4KICAKICAgIEBjbGFzcyBSZWdpc3RyeVByb3h5TWl4aW4KICAgIEBwcml2YXRlCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIF9fcmVnaXN0cnlfXzogbnVsbCwKCiAgICAvKioKICAgICBHaXZlbiBhIGZ1bGxOYW1lIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyBmYWN0b3J5LgogICAgICBAcHVibGljCiAgICAgQG1ldGhvZCByZXNvbHZlUmVnaXN0cmF0aW9uCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHJldHVybiB7RnVuY3Rpb259IGZ1bGxOYW1lJ3MgZmFjdG9yeQogICAgICovCiAgICByZXNvbHZlUmVnaXN0cmF0aW9uOiBmdW5jdGlvbiByZXNvbHZlUmVnaXN0cmF0aW9uKGZ1bGxOYW1lLCBvcHRpb25zKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMuX19yZWdpc3RyeV9fLmlzVmFsaWRGdWxsTmFtZShmdWxsTmFtZSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnZnVsbE5hbWUgbXVzdCBiZSBhIHByb3BlciBmdWxsIG5hbWUnLCB0aGlzLl9fcmVnaXN0cnlfXy5pc1ZhbGlkRnVsbE5hbWUoZnVsbE5hbWUpKSk7CiAgICAgIHJldHVybiB0aGlzLl9fcmVnaXN0cnlfXy5yZXNvbHZlKGZ1bGxOYW1lLCBvcHRpb25zKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFJlZ2lzdGVycyBhIGZhY3RvcnkgdGhhdCBjYW4gYmUgdXNlZCBmb3IgZGVwZW5kZW5jeSBpbmplY3Rpb24gKHdpdGgKICAgICAgYGluamVjdGApIG9yIGZvciBzZXJ2aWNlIGxvb2t1cC4gRWFjaCBmYWN0b3J5IGlzIHJlZ2lzdGVyZWQgd2l0aAogICAgICBhIGZ1bGwgbmFtZSBpbmNsdWRpbmcgdHdvIHBhcnRzOiBgdHlwZTpuYW1lYC4KICAgICAgIEEgc2ltcGxlIGV4YW1wbGU6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgICBsZXQgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKCk7CiAgICAgICBBcHAuT3JhbmdlID0gRW1iZXJPYmplY3QuZXh0ZW5kKCk7CiAgICAgIEFwcC5yZWdpc3RlcignZnJ1aXQ6ZmF2b3JpdGUnLCBBcHAuT3JhbmdlKTsKICAgICAgYGBgCiAgICAgICBFbWJlciB3aWxsIHJlc29sdmUgZmFjdG9yaWVzIGZyb20gdGhlIGBBcHBgIG5hbWVzcGFjZSBhdXRvbWF0aWNhbGx5LgogICAgICBGb3IgZXhhbXBsZSBgQXBwLkNhcnNDb250cm9sbGVyYCB3aWxsIGJlIGRpc2NvdmVyZWQgYW5kIHJldHVybmVkIGlmCiAgICAgIGFuIGFwcGxpY2F0aW9uIHJlcXVlc3RzIGBjb250cm9sbGVyOmNhcnNgLgogICAgICAgQW4gZXhhbXBsZSBvZiByZWdpc3RlcmluZyBhIGNvbnRyb2xsZXIgd2l0aCBhIG5vbi1zdGFuZGFyZCBuYW1lOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAgICAgaW1wb3J0IENvbnRyb2xsZXIgZnJvbSAnQGVtYmVyL2NvbnRyb2xsZXInOwogICAgICAgbGV0IEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSgpOwogICAgICBsZXQgU2Vzc2lvbiA9IENvbnRyb2xsZXIuZXh0ZW5kKCk7CiAgICAgICBBcHAucmVnaXN0ZXIoJ2NvbnRyb2xsZXI6c2Vzc2lvbicsIFNlc3Npb24pOwogICAgICAgLy8gVGhlIFNlc3Npb24gY29udHJvbGxlciBjYW4gbm93IGJlIHRyZWF0ZWQgbGlrZSBhIG5vcm1hbCBjb250cm9sbGVyLAogICAgICAvLyBkZXNwaXRlIGl0cyBub24tc3RhbmRhcmQgbmFtZS4KICAgICAgQXBwLkFwcGxpY2F0aW9uQ29udHJvbGxlciA9IENvbnRyb2xsZXIuZXh0ZW5kKHsKICAgICAgICBuZWVkczogWydzZXNzaW9uJ10KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgUmVnaXN0ZXJlZCBmYWN0b3JpZXMgYXJlICoqaW5zdGFudGlhdGVkKiogYnkgaGF2aW5nIGBjcmVhdGVgCiAgICAgIGNhbGxlZCBvbiB0aGVtLiBBZGRpdGlvbmFsbHkgdGhleSBhcmUgKipzaW5nbGV0b25zKiosIGVhY2ggdGltZQogICAgICB0aGV5IGFyZSBsb29rZWQgdXAgdGhleSByZXR1cm4gdGhlIHNhbWUgaW5zdGFuY2UuCiAgICAgICBTb21lIGV4YW1wbGVzIG1vZGlmeWluZyB0aGF0IGRlZmF1bHQgYmVoYXZpb3I6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgICBsZXQgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKCk7CiAgICAgICBBcHAuUGVyc29uID0gRW1iZXJPYmplY3QuZXh0ZW5kKCk7CiAgICAgIEFwcC5PcmFuZ2UgPSBFbWJlck9iamVjdC5leHRlbmQoKTsKICAgICAgQXBwLkVtYWlsID0gRW1iZXJPYmplY3QuZXh0ZW5kKCk7CiAgICAgIEFwcC5zZXNzaW9uID0gRW1iZXJPYmplY3QuY3JlYXRlKCk7CiAgICAgICBBcHAucmVnaXN0ZXIoJ21vZGVsOnVzZXInLCBBcHAuUGVyc29uLCB7IHNpbmdsZXRvbjogZmFsc2UgfSk7CiAgICAgIEFwcC5yZWdpc3RlcignZnJ1aXQ6ZmF2b3JpdGUnLCBBcHAuT3JhbmdlKTsKICAgICAgQXBwLnJlZ2lzdGVyKCdjb21tdW5pY2F0aW9uOm1haW4nLCBBcHAuRW1haWwsIHsgc2luZ2xldG9uOiBmYWxzZSB9KTsKICAgICAgQXBwLnJlZ2lzdGVyKCdzZXNzaW9uJywgQXBwLnNlc3Npb24sIHsgaW5zdGFudGlhdGU6IGZhbHNlIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgcmVnaXN0ZXIKICAgICAgQHBhcmFtICBmdWxsTmFtZSB7U3RyaW5nfSB0eXBlOm5hbWUgKGUuZy4sICdtb2RlbDp1c2VyJykKICAgICAgQHBhcmFtICBmYWN0b3J5IHthbnl9IChlLmcuLCBBcHAuUGVyc29uKQogICAgICBAcGFyYW0gIG9wdGlvbnMge09iamVjdH0gKG9wdGlvbmFsKSBkaXNhYmxlIGluc3RhbnRpYXRpb24gb3Igc2luZ2xldG9uIHVzYWdlCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgcmVnaXN0ZXI6IHJlZ2lzdHJ5QWxpYXMoJ3JlZ2lzdGVyJyksCgogICAgLyoqCiAgICAgVW5yZWdpc3RlciBhIGZhY3RvcnkuCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoKTsKICAgICBsZXQgVXNlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCgpOwogICAgIEFwcC5yZWdpc3RlcignbW9kZWw6dXNlcicsIFVzZXIpOwogICAgICBBcHAucmVzb2x2ZVJlZ2lzdHJhdGlvbignbW9kZWw6dXNlcicpLmNyZWF0ZSgpIGluc3RhbmNlb2YgVXNlciAvLz0+IHRydWUKICAgICAgQXBwLnVucmVnaXN0ZXIoJ21vZGVsOnVzZXInKQogICAgIEFwcC5yZXNvbHZlUmVnaXN0cmF0aW9uKCdtb2RlbDp1c2VyJykgPT09IHVuZGVmaW5lZCAvLz0+IHRydWUKICAgICBgYGAKICAgICAgQHB1YmxpYwogICAgIEBtZXRob2QgdW5yZWdpc3RlcgogICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZQogICAgICovCiAgICB1bnJlZ2lzdGVyOiByZWdpc3RyeUFsaWFzKCd1bnJlZ2lzdGVyJyksCgogICAgLyoqCiAgICAgQ2hlY2sgaWYgYSBmYWN0b3J5IGlzIHJlZ2lzdGVyZWQuCiAgICAgIEBwdWJsaWMKICAgICBAbWV0aG9kIGhhc1JlZ2lzdHJhdGlvbgogICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZQogICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICAgKi8KICAgIGhhc1JlZ2lzdHJhdGlvbjogcmVnaXN0cnlBbGlhcygnaGFzJyksCgogICAgLyoqCiAgICAgUmV0dXJuIGEgc3BlY2lmaWMgcmVnaXN0ZXJlZCBvcHRpb24gZm9yIGEgcGFydGljdWxhciBmYWN0b3J5LgogICAgICBAcHVibGljCiAgICAgQG1ldGhvZCByZWdpc3RlcmVkT3B0aW9uCiAgICAgQHBhcmFtICB7U3RyaW5nfSBmdWxsTmFtZQogICAgIEBwYXJhbSAge1N0cmluZ30gb3B0aW9uTmFtZQogICAgIEByZXR1cm4ge09iamVjdH0gb3B0aW9ucwogICAgICovCiAgICByZWdpc3RlcmVkT3B0aW9uOiByZWdpc3RyeUFsaWFzKCdnZXRPcHRpb24nKSwKCiAgICAvKioKICAgICBSZWdpc3RlciBvcHRpb25zIGZvciBhIHBhcnRpY3VsYXIgZmFjdG9yeS4KICAgICAgQHB1YmxpYwogICAgIEBtZXRob2QgcmVnaXN0ZXJPcHRpb25zCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAqLwogICAgcmVnaXN0ZXJPcHRpb25zOiByZWdpc3RyeUFsaWFzKCdvcHRpb25zJyksCgogICAgLyoqCiAgICAgUmV0dXJuIHJlZ2lzdGVyZWQgb3B0aW9ucyBmb3IgYSBwYXJ0aWN1bGFyIGZhY3RvcnkuCiAgICAgIEBwdWJsaWMKICAgICBAbWV0aG9kIHJlZ2lzdGVyZWRPcHRpb25zCiAgICAgQHBhcmFtICB7U3RyaW5nfSBmdWxsTmFtZQogICAgIEByZXR1cm4ge09iamVjdH0gb3B0aW9ucwogICAgICovCiAgICByZWdpc3RlcmVkT3B0aW9uczogcmVnaXN0cnlBbGlhcygnZ2V0T3B0aW9ucycpLAoKICAgIC8qKgogICAgIEFsbG93IHJlZ2lzdGVyaW5nIG9wdGlvbnMgZm9yIGFsbCBmYWN0b3JpZXMgb2YgYSB0eXBlLgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoKTsKICAgICBsZXQgYXBwSW5zdGFuY2UgPSBBcHAuYnVpbGRJbnN0YW5jZSgpOwogICAgICAvLyBpZiBhbGwgb2YgdHlwZSBgY29ubmVjdGlvbmAgbXVzdCBub3QgYmUgc2luZ2xldG9ucwogICAgIGFwcEluc3RhbmNlLnJlZ2lzdGVyT3B0aW9uc0ZvclR5cGUoJ2Nvbm5lY3Rpb24nLCB7IHNpbmdsZXRvbjogZmFsc2UgfSk7CiAgICAgIGFwcEluc3RhbmNlLnJlZ2lzdGVyKCdjb25uZWN0aW9uOnR3aXR0ZXInLCBUd2l0dGVyQ29ubmVjdGlvbik7CiAgICAgYXBwSW5zdGFuY2UucmVnaXN0ZXIoJ2Nvbm5lY3Rpb246ZmFjZWJvb2snLCBGYWNlYm9va0Nvbm5lY3Rpb24pOwogICAgICBsZXQgdHdpdHRlciA9IGFwcEluc3RhbmNlLmxvb2t1cCgnY29ubmVjdGlvbjp0d2l0dGVyJyk7CiAgICAgbGV0IHR3aXR0ZXIyID0gYXBwSW5zdGFuY2UubG9va3VwKCdjb25uZWN0aW9uOnR3aXR0ZXInKTsKICAgICAgdHdpdHRlciA9PT0gdHdpdHRlcjI7IC8vID0+IGZhbHNlCiAgICAgIGxldCBmYWNlYm9vayA9IGFwcEluc3RhbmNlLmxvb2t1cCgnY29ubmVjdGlvbjpmYWNlYm9vaycpOwogICAgIGxldCBmYWNlYm9vazIgPSBhcHBJbnN0YW5jZS5sb29rdXAoJ2Nvbm5lY3Rpb246ZmFjZWJvb2snKTsKICAgICAgZmFjZWJvb2sgPT09IGZhY2Vib29rMjsgLy8gPT4gZmFsc2UKICAgICBgYGAKICAgICAgQHB1YmxpYwogICAgIEBtZXRob2QgcmVnaXN0ZXJPcHRpb25zRm9yVHlwZQogICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAqLwogICAgcmVnaXN0ZXJPcHRpb25zRm9yVHlwZTogcmVnaXN0cnlBbGlhcygnb3B0aW9uc0ZvclR5cGUnKSwKCiAgICAvKioKICAgICBSZXR1cm4gdGhlIHJlZ2lzdGVyZWQgb3B0aW9ucyBmb3IgYWxsIGZhY3RvcmllcyBvZiBhIHR5cGUuCiAgICAgIEBwdWJsaWMKICAgICBAbWV0aG9kIHJlZ2lzdGVyZWRPcHRpb25zRm9yVHlwZQogICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlCiAgICAgQHJldHVybiB7T2JqZWN0fSBvcHRpb25zCiAgICAgKi8KICAgIHJlZ2lzdGVyZWRPcHRpb25zRm9yVHlwZTogcmVnaXN0cnlBbGlhcygnZ2V0T3B0aW9uc0ZvclR5cGUnKSwKCiAgICAvKioKICAgICAgRGVmaW5lIGEgZGVwZW5kZW5jeSBpbmplY3Rpb24gb250byBhIHNwZWNpZmljIGZhY3Rvcnkgb3IgYWxsIGZhY3RvcmllcwogICAgICBvZiBhIHR5cGUuCiAgICAgICBXaGVuIEVtYmVyIGluc3RhbnRpYXRlcyBhIGNvbnRyb2xsZXIsIHZpZXcsIG9yIG90aGVyIGZyYW1ld29yayBjb21wb25lbnQKICAgICAgaXQgY2FuIGF0dGFjaCBhIGRlcGVuZGVuY3kgdG8gdGhhdCBjb21wb25lbnQuIFRoaXMgaXMgb2Z0ZW4gdXNlZCB0bwogICAgICBwcm92aWRlIHNlcnZpY2VzIHRvIGEgc2V0IG9mIGZyYW1ld29yayBjb21wb25lbnRzLgogICAgICAgQW4gZXhhbXBsZSBvZiBwcm92aWRpbmcgYSBzZXNzaW9uIG9iamVjdCB0byBhbGwgY29udHJvbGxlcnM6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCB7IGFsaWFzIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICBpbXBvcnQgQ29udHJvbGxlciBmcm9tICdAZW1iZXIvY29udHJvbGxlcic7CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoKTsKICAgICAgbGV0IFNlc3Npb24gPSBFbWJlck9iamVjdC5leHRlbmQoeyBpc0F1dGhlbnRpY2F0ZWQ6IGZhbHNlIH0pOwogICAgICAgLy8gQSBmYWN0b3J5IG11c3QgYmUgcmVnaXN0ZXJlZCBiZWZvcmUgaXQgY2FuIGJlIGluamVjdGVkCiAgICAgIEFwcC5yZWdpc3Rlcignc2Vzc2lvbjptYWluJywgU2Vzc2lvbik7CiAgICAgICAvLyBJbmplY3QgJ3Nlc3Npb246bWFpbicgb250byBhbGwgZmFjdG9yaWVzIG9mIHRoZSB0eXBlICdjb250cm9sbGVyJwogICAgICAvLyB3aXRoIHRoZSBuYW1lICdzZXNzaW9uJwogICAgICBBcHAuaW5qZWN0KCdjb250cm9sbGVyJywgJ3Nlc3Npb24nLCAnc2Vzc2lvbjptYWluJyk7CiAgICAgICBBcHAuSW5kZXhDb250cm9sbGVyID0gQ29udHJvbGxlci5leHRlbmQoewogICAgICAgIGlzTG9nZ2VkSW46IGFsaWFzKCdzZXNzaW9uLmlzQXV0aGVudGljYXRlZCcpCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEluamVjdGlvbnMgY2FuIGFsc28gYmUgcGVyZm9ybWVkIG9uIHNwZWNpZmljIGZhY3Rvcmllcy4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgQXBwLmluamVjdCg8ZnVsbF9uYW1lIG9yIHR5cGU+LCA8cHJvcGVydHkgbmFtZT4sIDxmdWxsX25hbWU+KQogICAgICBBcHAuaW5qZWN0KCdyb3V0ZScsICdzb3VyY2UnLCAnc291cmNlOm1haW4nKQogICAgICBBcHAuaW5qZWN0KCdyb3V0ZTphcHBsaWNhdGlvbicsICdlbWFpbCcsICdtb2RlbDplbWFpbCcpCiAgICAgIGBgYAogICAgICAgSXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCBpbmplY3Rpb25zIGNhbiBvbmx5IGJlIHBlcmZvcm1lZCBvbgogICAgICBjbGFzc2VzIHRoYXQgYXJlIGluc3RhbnRpYXRlZCBieSBFbWJlciBpdHNlbGYuIEluc3RhbnRpYXRpbmcgYSBjbGFzcwogICAgICBkaXJlY3RseSAodmlhIGBjcmVhdGVgIG9yIGBuZXdgKSBieXBhc3NlcyB0aGUgZGVwZW5kZW5jeSBpbmplY3Rpb24KICAgICAgc3lzdGVtLgogICAgICAgQHB1YmxpYwogICAgICBAbWV0aG9kIGluamVjdAogICAgICBAcGFyYW0gIGZhY3RvcnlOYW1lT3JUeXBlIHtTdHJpbmd9CiAgICAgIEBwYXJhbSAgcHJvcGVydHkge1N0cmluZ30KICAgICAgQHBhcmFtICBpbmplY3Rpb25OYW1lIHtTdHJpbmd9CiAgICAqKi8KICAgIGluamVjdDogcmVnaXN0cnlBbGlhcygnaW5qZWN0aW9uJykKICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OwoKICBmdW5jdGlvbiByZWdpc3RyeUFsaWFzKG5hbWUpIHsKICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBfdGhpcyRfX3JlZ2lzdHJ5X187CgogICAgICByZXR1cm4gKF90aGlzJF9fcmVnaXN0cnlfXyA9IHRoaXMuX19yZWdpc3RyeV9fKVtuYW1lXS5hcHBseShfdGhpcyRfX3JlZ2lzdHJ5X18sIGFyZ3VtZW50cyk7CiAgICB9OwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL3RhcmdldF9hY3Rpb25fc3VwcG9ydCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW52aXJvbm1lbnQsIF9tZXRhbCwgX2RlYnVnKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KCiAgLyoqCiAgYEVtYmVyLlRhcmdldEFjdGlvblN1cHBvcnRgIGlzIGEgbWl4aW4gdGhhdCBjYW4gYmUgaW5jbHVkZWQgaW4gYSBjbGFzcwogIHRvIGFkZCBhIGB0cmlnZ2VyQWN0aW9uYCBtZXRob2Qgd2l0aCBzZW1hbnRpY3Mgc2ltaWxhciB0byB0aGUgSGFuZGxlYmFycwogIGB7e2FjdGlvbn19YCBoZWxwZXIuIEluIG5vcm1hbCBFbWJlciB1c2FnZSwgdGhlIGB7e2FjdGlvbn19YCBoZWxwZXIgaXMKICB1c3VhbGx5IHRoZSBiZXN0IGNob2ljZS4gVGhpcyBtaXhpbiBpcyBtb3N0IG9mdGVuIHVzZWZ1bCB3aGVuIHlvdSBhcmUKICBkb2luZyBtb3JlIGNvbXBsZXggZXZlbnQgaGFuZGxpbmcgaW4gQ29tcG9uZW50cy4KICAKICBAY2xhc3MgVGFyZ2V0QWN0aW9uU3VwcG9ydAogIEBuYW1lc3BhY2UgRW1iZXIKICBAZXh0ZW5kcyBNaXhpbgogIEBwcml2YXRlCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIHRhcmdldDogbnVsbCwKICAgIGFjdGlvbjogbnVsbCwKICAgIGFjdGlvbkNvbnRleHQ6IG51bGwsCiAgICBhY3Rpb25Db250ZXh0T2JqZWN0OiAoMCwgX21ldGFsLmNvbXB1dGVkKSgnYWN0aW9uQ29udGV4dCcsIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGFjdGlvbkNvbnRleHQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FjdGlvbkNvbnRleHQnKTsKCiAgICAgIGlmICh0eXBlb2YgYWN0aW9uQ29udGV4dCA9PT0gJ3N0cmluZycpIHsKICAgICAgICB2YXIgdmFsdWUgPSAoMCwgX21ldGFsLmdldCkodGhpcywgYWN0aW9uQ29udGV4dCk7CgogICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KShfZW52aXJvbm1lbnQuY29udGV4dC5sb29rdXAsIGFjdGlvbkNvbnRleHQpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBhY3Rpb25Db250ZXh0OwogICAgICB9CiAgICB9KSwKCiAgICAvKioKICAgIFNlbmQgYW4gYGFjdGlvbmAgd2l0aCBhbiBgYWN0aW9uQ29udGV4dGAgdG8gYSBgdGFyZ2V0YC4gVGhlIGFjdGlvbiwgYWN0aW9uQ29udGV4dAogICAgYW5kIHRhcmdldCB3aWxsIGJlIHJldHJpZXZlZCBmcm9tIHByb3BlcnRpZXMgb2YgdGhlIG9iamVjdC4gRm9yIGV4YW1wbGU6CiAgICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgYWxpYXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAgICBBcHAuU2F2ZUJ1dHRvblZpZXcgPSBFbWJlci5WaWV3LmV4dGVuZChFbWJlci5UYXJnZXRBY3Rpb25TdXBwb3J0LCB7CiAgICAgIHRhcmdldDogYWxpYXMoJ2NvbnRyb2xsZXInKSwKICAgICAgYWN0aW9uOiAnc2F2ZScsCiAgICAgIGFjdGlvbkNvbnRleHQ6IGFsaWFzKCdjb250ZXh0JyksCiAgICAgIGNsaWNrKCkgewogICAgICAgIHRoaXMudHJpZ2dlckFjdGlvbigpOyAvLyBTZW5kcyB0aGUgYHNhdmVgIGFjdGlvbiwgYWxvbmcgd2l0aCB0aGUgY3VycmVudCBjb250ZXh0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvIHRoZSBjdXJyZW50IGNvbnRyb2xsZXIKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAgICBUaGUgYHRhcmdldGAsIGBhY3Rpb25gLCBhbmQgYGFjdGlvbkNvbnRleHRgIGNhbiBiZSBwcm92aWRlZCBhcyBwcm9wZXJ0aWVzIG9mCiAgICBhbiBvcHRpb25hbCBvYmplY3QgYXJndW1lbnQgdG8gYHRyaWdnZXJBY3Rpb25gIGFzIHdlbGwuCiAgICAgYGBgamF2YXNjcmlwdAogICAgQXBwLlNhdmVCdXR0b25WaWV3ID0gRW1iZXIuVmlldy5leHRlbmQoRW1iZXIuVGFyZ2V0QWN0aW9uU3VwcG9ydCwgewogICAgICBjbGljaygpIHsKICAgICAgICB0aGlzLnRyaWdnZXJBY3Rpb24oewogICAgICAgICAgYWN0aW9uOiAnc2F2ZScsCiAgICAgICAgICB0YXJnZXQ6IHRoaXMuZ2V0KCdjb250cm9sbGVyJyksCiAgICAgICAgICBhY3Rpb25Db250ZXh0OiB0aGlzLmdldCgnY29udGV4dCcpCiAgICAgICAgfSk7IC8vIFNlbmRzIHRoZSBgc2F2ZWAgYWN0aW9uLCBhbG9uZyB3aXRoIHRoZSBjdXJyZW50IGNvbnRleHQKICAgICAgICAgICAgLy8gdG8gdGhlIGN1cnJlbnQgY29udHJvbGxlcgogICAgICB9CiAgICB9KTsKICAgIGBgYAogICAgIFRoZSBgYWN0aW9uQ29udGV4dGAgZGVmYXVsdHMgdG8gdGhlIG9iamVjdCB5b3UgYXJlIG1peGluZyBgVGFyZ2V0QWN0aW9uU3VwcG9ydGAgaW50by4KICAgIEJ1dCBgdGFyZ2V0YCBhbmQgYGFjdGlvbmAgbXVzdCBiZSBzcGVjaWZpZWQgZWl0aGVyIGFzIHByb3BlcnRpZXMgb3Igd2l0aCB0aGUgYXJndW1lbnQKICAgIHRvIGB0cmlnZ2VyQWN0aW9uYCwgb3IgYSBjb21iaW5hdGlvbjoKICAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBhbGlhcyB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogICAgIEFwcC5TYXZlQnV0dG9uVmlldyA9IEVtYmVyLlZpZXcuZXh0ZW5kKEVtYmVyLlRhcmdldEFjdGlvblN1cHBvcnQsIHsKICAgICAgdGFyZ2V0OiBhbGlhcygnY29udHJvbGxlcicpLAogICAgICBjbGljaygpIHsKICAgICAgICB0aGlzLnRyaWdnZXJBY3Rpb24oewogICAgICAgICAgYWN0aW9uOiAnc2F2ZScKICAgICAgICB9KTsgLy8gU2VuZHMgdGhlIGBzYXZlYCBhY3Rpb24sIGFsb25nIHdpdGggYSByZWZlcmVuY2UgdG8gYHRoaXNgLAogICAgICAgICAgICAvLyB0byB0aGUgY3VycmVudCBjb250cm9sbGVyCiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgICAgQG1ldGhvZCB0cmlnZ2VyQWN0aW9uCiAgICBAcGFyYW0gb3B0cyB7T2JqZWN0fSAob3B0aW9uYWwsIHdpdGggdGhlIG9wdGlvbmFsIGtleXMgYWN0aW9uLCB0YXJnZXQgYW5kL29yIGFjdGlvbkNvbnRleHQpCiAgICBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHRoZSBhY3Rpb24gd2FzIHNlbnQgc3VjY2Vzc2Z1bGx5IGFuZCBkaWQgbm90IHJldHVybiBmYWxzZQogICAgQHByaXZhdGUKICAgICovCiAgICB0cmlnZ2VyQWN0aW9uOiBmdW5jdGlvbiB0cmlnZ2VyQWN0aW9uKG9wdHMpIHsKICAgICAgaWYgKG9wdHMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdHMgPSB7fTsKICAgICAgfQoKICAgICAgdmFyIF9vcHRzID0gb3B0cywKICAgICAgICAgIGFjdGlvbiA9IF9vcHRzLmFjdGlvbiwKICAgICAgICAgIHRhcmdldCA9IF9vcHRzLnRhcmdldCwKICAgICAgICAgIGFjdGlvbkNvbnRleHQgPSBfb3B0cy5hY3Rpb25Db250ZXh0OwogICAgICBhY3Rpb24gPSBhY3Rpb24gfHwgKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdhY3Rpb24nKTsKICAgICAgdGFyZ2V0ID0gdGFyZ2V0IHx8IGdldFRhcmdldCh0aGlzKTsKCiAgICAgIGlmIChhY3Rpb25Db250ZXh0ID09PSB1bmRlZmluZWQpIHsKICAgICAgICBhY3Rpb25Db250ZXh0ID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdhY3Rpb25Db250ZXh0T2JqZWN0JykgfHwgdGhpczsKICAgICAgfQoKICAgICAgaWYgKHRhcmdldCAmJiBhY3Rpb24pIHsKICAgICAgICB2YXIgcmV0OwoKICAgICAgICBpZiAodGFyZ2V0LnNlbmQpIHsKICAgICAgICAgIHZhciBfdGFyZ2V0OwoKICAgICAgICAgIHJldCA9IChfdGFyZ2V0ID0gdGFyZ2V0KS5zZW5kLmFwcGx5KF90YXJnZXQsIFthY3Rpb25dLmNvbmNhdChhY3Rpb25Db250ZXh0KSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBfdGFyZ2V0MjsKCiAgICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgdGFyZ2V0W2FjdGlvbl0gPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIGFjdGlvbiAnIiArIGFjdGlvbiArICInIGRpZCBub3QgZXhpc3Qgb24gIiArIHRhcmdldCwgdHlwZW9mIHRhcmdldFthY3Rpb25dID09PSAnZnVuY3Rpb24nKSk7CiAgICAgICAgICByZXQgPSAoX3RhcmdldDIgPSB0YXJnZXQpW2FjdGlvbl0uYXBwbHkoX3RhcmdldDIsIFtdLmNvbmNhdChhY3Rpb25Db250ZXh0KSk7CiAgICAgICAgfQoKICAgICAgICBpZiAocmV0ICE9PSBmYWxzZSkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgfSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKCiAgZnVuY3Rpb24gZ2V0VGFyZ2V0KGluc3RhbmNlKSB7CiAgICB2YXIgdGFyZ2V0ID0gKDAsIF9tZXRhbC5nZXQpKGluc3RhbmNlLCAndGFyZ2V0Jyk7CgogICAgaWYgKHRhcmdldCkgewogICAgICBpZiAodHlwZW9mIHRhcmdldCA9PT0gJ3N0cmluZycpIHsKICAgICAgICB2YXIgdmFsdWUgPSAoMCwgX21ldGFsLmdldCkoaW5zdGFuY2UsIHRhcmdldCk7CgogICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KShfZW52aXJvbm1lbnQuY29udGV4dC5sb29rdXAsIHRhcmdldCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHRhcmdldDsKICAgICAgfQogICAgfQoKICAgIGlmIChpbnN0YW5jZS5fdGFyZ2V0KSB7CiAgICAgIHJldHVybiBpbnN0YW5jZS5fdGFyZ2V0OwogICAgfQoKICAgIHJldHVybiBudWxsOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL2FycmF5X3Byb3h5IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL3N5c3RlbS9vYmplY3QiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2FycmF5IiwgIkBlbWJlci9kZWJ1ZyIsICJAZ2xpbW1lci9yZWZlcmVuY2UiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX21ldGFsLCBfb2JqZWN0LCBfYXJyYXksIF9kZWJ1ZywgX3JlZmVyZW5jZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvYXJyYXkKICAqLwogIHZhciBBUlJBWV9PQlNFUlZFUl9NQVBQSU5HID0gewogICAgd2lsbENoYW5nZTogJ19hcnJhbmdlZENvbnRlbnRBcnJheVdpbGxDaGFuZ2UnLAogICAgZGlkQ2hhbmdlOiAnX2FycmFuZ2VkQ29udGVudEFycmF5RGlkQ2hhbmdlJwogIH07CiAgLyoqCiAgICBBbiBBcnJheVByb3h5IHdyYXBzIGFueSBvdGhlciBvYmplY3QgdGhhdCBpbXBsZW1lbnRzIGBBcnJheWAgYW5kL29yCiAgICBgTXV0YWJsZUFycmF5LGAgZm9yd2FyZGluZyBhbGwgcmVxdWVzdHMuIFRoaXMgbWFrZXMgaXQgdmVyeSB1c2VmdWwgZm9yCiAgICBhIG51bWJlciBvZiBiaW5kaW5nIHVzZSBjYXNlcyBvciBvdGhlciBjYXNlcyB3aGVyZSBiZWluZyBhYmxlIHRvIHN3YXAKICAgIG91dCB0aGUgdW5kZXJseWluZyBhcnJheSBpcyB1c2VmdWwuCiAgCiAgICBBIHNpbXBsZSBleGFtcGxlIG9mIHVzYWdlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgQSB9IGZyb20gJ0BlbWJlci9hcnJheSc7CiAgICBpbXBvcnQgQXJyYXlQcm94eSBmcm9tICdAZW1iZXIvYXJyYXkvcHJveHknOwogIAogICAgbGV0IHBldHMgPSBbJ2RvZycsICdjYXQnLCAnZmlzaCddOwogICAgbGV0IGFwID0gQXJyYXlQcm94eS5jcmVhdGUoeyBjb250ZW50OiBBKHBldHMpIH0pOwogIAogICAgYXAuZ2V0KCdmaXJzdE9iamVjdCcpOyAgICAgICAgICAgICAgICAgICAgICAgIC8vICdkb2cnCiAgICBhcC5zZXQoJ2NvbnRlbnQnLCBbJ2Ftb2ViYScsICdwYXJhbWVjaXVtJ10pOwogICAgYXAuZ2V0KCdmaXJzdE9iamVjdCcpOyAgICAgICAgICAgICAgICAgICAgICAgIC8vICdhbW9lYmEnCiAgICBgYGAKICAKICAgIFRoaXMgY2xhc3MgY2FuIGFsc28gYmUgdXNlZnVsIGFzIGEgbGF5ZXIgdG8gdHJhbnNmb3JtIHRoZSBjb250ZW50cyBvZgogICAgYW4gYXJyYXksIGFzIHRoZXkgYXJlIGFjY2Vzc2VkLiBUaGlzIGNhbiBiZSBkb25lIGJ5IG92ZXJyaWRpbmcKICAgIGBvYmplY3RBdENvbnRlbnRgOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgQSB9IGZyb20gJ0BlbWJlci9hcnJheSc7CiAgICBpbXBvcnQgQXJyYXlQcm94eSBmcm9tICdAZW1iZXIvYXJyYXkvcHJveHknOwogIAogICAgbGV0IHBldHMgPSBbJ2RvZycsICdjYXQnLCAnZmlzaCddOwogICAgbGV0IGFwID0gQXJyYXlQcm94eS5jcmVhdGUoewogICAgICAgIGNvbnRlbnQ6IEEocGV0cyksCiAgICAgICAgb2JqZWN0QXRDb250ZW50OiBmdW5jdGlvbihpZHgpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KCdjb250ZW50Jykub2JqZWN0QXQoaWR4KS50b1VwcGVyQ2FzZSgpOwogICAgICAgIH0KICAgIH0pOwogIAogICAgYXAuZ2V0KCdmaXJzdE9iamVjdCcpOyAvLyAuICdET0cnCiAgICBgYGAKICAKICAgIFdoZW4gb3ZlcnJpZGluZyB0aGlzIGNsYXNzLCBpdCBpcyBpbXBvcnRhbnQgdG8gcGxhY2UgdGhlIGNhbGwgdG8KICAgIGBfc3VwZXJgICphZnRlciogc2V0dGluZyBgY29udGVudGAgc28gdGhlIGludGVybmFsIG9ic2VydmVycyBoYXZlCiAgICBhIGNoYW5jZSB0byBmaXJlIHByb3Blcmx5OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgQSB9IGZyb20gJ0BlbWJlci9hcnJheSc7CiAgICBpbXBvcnQgQXJyYXlQcm94eSBmcm9tICdAZW1iZXIvYXJyYXkvcHJveHknOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQXJyYXlQcm94eS5leHRlbmQoewogICAgICBpbml0KCkgewogICAgICAgIHRoaXMuc2V0KCdjb250ZW50JywgQShbJ2RvZycsICdjYXQnLCAnZmlzaCddKSk7CiAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBBcnJheVByb3h5CiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHVzZXMgTXV0YWJsZUFycmF5CiAgICBAcHVibGljCiAgKi8KCiAgdmFyIEFycmF5UHJveHkgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0VtYmVyT2JqZWN0KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoQXJyYXlQcm94eSwgX0VtYmVyT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBBcnJheVByb3h5KCkgewogICAgICByZXR1cm4gX0VtYmVyT2JqZWN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gQXJyYXlQcm94eS5wcm90b3R5cGU7CgogICAgX3Byb3RvLmluaXQgPSBmdW5jdGlvbiBpbml0KCkgewogICAgICBfRW1iZXJPYmplY3QucHJvdG90eXBlLmluaXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgICAgLyoKICAgICAgICBgdGhpcy5fb2JqZWN0c0RpcnR5SW5kZXhgIGRldGVybWluZXMgd2hpY2ggaW5kZXhlcyBpbiB0aGUgYHRoaXMuX29iamVjdHNgCiAgICAgICAgY2FjaGUgYXJlIGRpcnR5LgogICAgICAgICBJZiBgdGhpcy5fb2JqZWN0c0RpcnR5SW5kZXggPT09IC0xYCB0aGVuIG5vIGluZGV4ZXMgYXJlIGRpcnR5LgogICAgICAgIE90aGVyd2lzZSwgYW4gaW5kZXggYGlgIGlzIGRpcnR5IGlmIGBpID49IHRoaXMuX29iamVjdHNEaXJ0eUluZGV4YC4KICAgICAgICAgQ2FsbGluZyBgb2JqZWN0QXRgIHdpdGggYSBkaXJ0eSBpbmRleCB3aWxsIGNhdXNlIHRoZSBgdGhpcy5fb2JqZWN0c2AKICAgICAgICBjYWNoZSB0byBiZSByZWNvbXB1dGVkLgogICAgICAqLwoKCiAgICAgIHRoaXMuX29iamVjdHNEaXJ0eUluZGV4ID0gMDsKICAgICAgdGhpcy5fb2JqZWN0cyA9IG51bGw7CiAgICAgIHRoaXMuX2xlbmd0aERpcnR5ID0gdHJ1ZTsKICAgICAgdGhpcy5fbGVuZ3RoID0gMDsKICAgICAgdGhpcy5fYXJyYW5nZWRDb250ZW50ID0gbnVsbDsKCiAgICAgIGlmICh0cnVlCiAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICApIHsKICAgICAgICAgIHRoaXMuX2FycmFuZ2VkQ29udGVudElzVXBkYXRpbmcgPSBmYWxzZTsKICAgICAgICAgIHRoaXMuX2FycmFuZ2VkQ29udGVudFRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKCgwLCBfbWV0YWwuZ2V0Q2hhaW5UYWdzRm9yS2V5KSh0aGlzLCAnYXJyYW5nZWRDb250ZW50JykpOwogICAgICAgICAgdGhpcy5fYXJyYW5nZWRDb250ZW50UmV2aXNpb24gPSAoMCwgX3JlZmVyZW5jZS52YWx1ZSkodGhpcy5fYXJyYW5nZWRDb250ZW50VGFnKTsKICAgICAgICB9CgogICAgICB0aGlzLl9hZGRBcnJhbmdlZENvbnRlbnRBcnJheU9ic2V2ZXIoKTsKICAgIH07CgogICAgX3Byb3RvLndpbGxEZXN0cm95ID0gZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3JlbW92ZUFycmFuZ2VkQ29udGVudEFycmF5T2JzZXZlcigpOwogICAgfQogICAgLyoqCiAgICAgIFRoZSBjb250ZW50IGFycmF5LiBNdXN0IGJlIGFuIG9iamVjdCB0aGF0IGltcGxlbWVudHMgYEFycmF5YCBhbmQvb3IKICAgICAgYE11dGFibGVBcnJheS5gCiAgICAgICBAcHJvcGVydHkgY29udGVudAogICAgICBAdHlwZSBFbWJlckFycmF5CiAgICAgIEBwdWJsaWMKICAgICovCgogICAgLyoqCiAgICAgIFNob3VsZCBhY3R1YWxseSByZXRyaWV2ZSB0aGUgb2JqZWN0IGF0IHRoZSBzcGVjaWZpZWQgaW5kZXggZnJvbSB0aGUKICAgICAgY29udGVudC4gWW91IGNhbiBvdmVycmlkZSB0aGlzIG1ldGhvZCBpbiBzdWJjbGFzc2VzIHRvIHRyYW5zZm9ybSB0aGUKICAgICAgY29udGVudCBpdGVtIHRvIHNvbWV0aGluZyBuZXcuCiAgICAgICBUaGlzIG1ldGhvZCB3aWxsIG9ubHkgYmUgY2FsbGVkIGlmIGNvbnRlbnQgaXMgbm9uLWBudWxsYC4KICAgICAgIEBtZXRob2Qgb2JqZWN0QXRDb250ZW50CiAgICAgIEBwYXJhbSB7TnVtYmVyfSBpZHggVGhlIGluZGV4IHRvIHJldHJpZXZlLgogICAgICBAcmV0dXJuIHtPYmplY3R9IHRoZSB2YWx1ZSBvciB1bmRlZmluZWQgaWYgbm9uZSBmb3VuZAogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIF9wcm90by5vYmplY3RBdENvbnRlbnQgPSBmdW5jdGlvbiBvYmplY3RBdENvbnRlbnQoaWR4KSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLm9iamVjdEF0KSgoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpLCBpZHgpOwogICAgfSAvLyBTZWUgYWRkaXRpb25hbCBkb2NzIGZvciBgcmVwbGFjZWAgZnJvbSBgTXV0YWJsZUFycmF5YDoKICAgIC8vIGh0dHBzOi8vYXBpLmVtYmVyanMuY29tL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9NdXRhYmxlQXJyYXkvbWV0aG9kcy9yZXBsYWNlP2FuY2hvcj1yZXBsYWNlCiAgICA7CgogICAgX3Byb3RvLnJlcGxhY2UgPSBmdW5jdGlvbiByZXBsYWNlKGlkeCwgYW10LCBvYmplY3RzKSB7CiAgICAgIChmYWxzZSAmJiAhKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnYXJyYW5nZWRDb250ZW50JykgPT09ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnY29udGVudCcpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ011dGF0aW5nIGFuIGFycmFuZ2VkIEFycmF5UHJveHkgaXMgbm90IGFsbG93ZWQnLCAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpID09PSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2NvbnRlbnQnKSkpOwogICAgICB0aGlzLnJlcGxhY2VDb250ZW50KGlkeCwgYW10LCBvYmplY3RzKTsKICAgIH0KICAgIC8qKgogICAgICBTaG91bGQgYWN0dWFsbHkgcmVwbGFjZSB0aGUgc3BlY2lmaWVkIG9iamVjdHMgb24gdGhlIGNvbnRlbnQgYXJyYXkuCiAgICAgIFlvdSBjYW4gb3ZlcnJpZGUgdGhpcyBtZXRob2QgaW4gc3ViY2xhc3NlcyB0byB0cmFuc2Zvcm0gdGhlIGNvbnRlbnQgaXRlbQogICAgICBpbnRvIHNvbWV0aGluZyBuZXcuCiAgICAgICBUaGlzIG1ldGhvZCB3aWxsIG9ubHkgYmUgY2FsbGVkIGlmIGNvbnRlbnQgaXMgbm9uLWBudWxsYC4KICAgICAgIEBtZXRob2QgcmVwbGFjZUNvbnRlbnQKICAgICAgQHBhcmFtIHtOdW1iZXJ9IGlkeCBUaGUgc3RhcnRpbmcgaW5kZXgKICAgICAgQHBhcmFtIHtOdW1iZXJ9IGFtdCBUaGUgbnVtYmVyIG9mIGl0ZW1zIHRvIHJlbW92ZSBmcm9tIHRoZSBjb250ZW50LgogICAgICBAcGFyYW0ge0VtYmVyQXJyYXl9IG9iamVjdHMgT3B0aW9uYWwgYXJyYXkgb2Ygb2JqZWN0cyB0byBpbnNlcnQgb3IgbnVsbCBpZiBubwogICAgICAgIG9iamVjdHMuCiAgICAgIEByZXR1cm4ge3ZvaWR9CiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlcGxhY2VDb250ZW50ID0gZnVuY3Rpb24gcmVwbGFjZUNvbnRlbnQoaWR4LCBhbXQsIG9iamVjdHMpIHsKICAgICAgKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdjb250ZW50JykucmVwbGFjZShpZHgsIGFtdCwgb2JqZWN0cyk7CiAgICB9IC8vIE92ZXJyaWRpbmcgb2JqZWN0QXQgaXMgbm90IHN1cHBvcnRlZC4KICAgIDsKCiAgICBfcHJvdG8ub2JqZWN0QXQgPSBmdW5jdGlvbiBvYmplY3RBdChpZHgpIHsKICAgICAgaWYgKHRydWUKICAgICAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgICAgICkgewogICAgICAgICAgdGhpcy5fcmV2YWxpZGF0ZSgpOwogICAgICAgIH0KCiAgICAgIGlmICh0aGlzLl9vYmplY3RzID09PSBudWxsKSB7CiAgICAgICAgdGhpcy5fb2JqZWN0cyA9IFtdOwogICAgICB9CgogICAgICBpZiAodGhpcy5fb2JqZWN0c0RpcnR5SW5kZXggIT09IC0xICYmIGlkeCA+PSB0aGlzLl9vYmplY3RzRGlydHlJbmRleCkgewogICAgICAgIHZhciBhcnJhbmdlZENvbnRlbnQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpOwoKICAgICAgICBpZiAoYXJyYW5nZWRDb250ZW50KSB7CiAgICAgICAgICB2YXIgbGVuZ3RoID0gdGhpcy5fb2JqZWN0cy5sZW5ndGggPSAoMCwgX21ldGFsLmdldCkoYXJyYW5nZWRDb250ZW50LCAnbGVuZ3RoJyk7CgogICAgICAgICAgZm9yICh2YXIgaSA9IHRoaXMuX29iamVjdHNEaXJ0eUluZGV4OyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgdGhpcy5fb2JqZWN0c1tpXSA9IHRoaXMub2JqZWN0QXRDb250ZW50KGkpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9vYmplY3RzLmxlbmd0aCA9IDA7CiAgICAgICAgfQoKICAgICAgICB0aGlzLl9vYmplY3RzRGlydHlJbmRleCA9IC0xOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fb2JqZWN0c1tpZHhdOwogICAgfSAvLyBPdmVycmlkaW5nIGxlbmd0aCBpcyBub3Qgc3VwcG9ydGVkLgogICAgOwoKICAgIF9wcm90b1tfbWV0YWwuUFJPUEVSVFlfRElEX0NIQU5HRV0gPSBmdW5jdGlvbiAoa2V5KSB7CiAgICAgIGlmICh0cnVlCiAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICApIHsKICAgICAgICAgIHRoaXMuX3JldmFsaWRhdGUoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgIGlmIChrZXkgPT09ICdhcnJhbmdlZENvbnRlbnQnKSB7CiAgICAgICAgICB0aGlzLl91cGRhdGVBcnJhbmdlZENvbnRlbnRBcnJheSgpOwogICAgICAgIH0gZWxzZSBpZiAoa2V5ID09PSAnY29udGVudCcpIHsKICAgICAgICAgIHRoaXMuX2ludmFsaWRhdGUoKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl91cGRhdGVBcnJhbmdlZENvbnRlbnRBcnJheSA9IGZ1bmN0aW9uIF91cGRhdGVBcnJhbmdlZENvbnRlbnRBcnJheSgpIHsKICAgICAgdmFyIG9sZExlbmd0aCA9IHRoaXMuX29iamVjdHMgPT09IG51bGwgPyAwIDogdGhpcy5fb2JqZWN0cy5sZW5ndGg7CiAgICAgIHZhciBhcnJhbmdlZENvbnRlbnQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpOwogICAgICB2YXIgbmV3TGVuZ3RoID0gYXJyYW5nZWRDb250ZW50ID8gKDAsIF9tZXRhbC5nZXQpKGFycmFuZ2VkQ29udGVudCwgJ2xlbmd0aCcpIDogMDsKCiAgICAgIHRoaXMuX3JlbW92ZUFycmFuZ2VkQ29udGVudEFycmF5T2JzZXZlcigpOwoKICAgICAgdGhpcy5hcnJheUNvbnRlbnRXaWxsQ2hhbmdlKDAsIG9sZExlbmd0aCwgbmV3TGVuZ3RoKTsKCiAgICAgIHRoaXMuX2ludmFsaWRhdGUoKTsKCiAgICAgIHRoaXMuYXJyYXlDb250ZW50RGlkQ2hhbmdlKDAsIG9sZExlbmd0aCwgbmV3TGVuZ3RoKTsKCiAgICAgIHRoaXMuX2FkZEFycmFuZ2VkQ29udGVudEFycmF5T2JzZXZlcigpOwogICAgfTsKCiAgICBfcHJvdG8uX2FkZEFycmFuZ2VkQ29udGVudEFycmF5T2JzZXZlciA9IGZ1bmN0aW9uIF9hZGRBcnJhbmdlZENvbnRlbnRBcnJheU9ic2V2ZXIoKSB7CiAgICAgIHZhciBhcnJhbmdlZENvbnRlbnQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpOwoKICAgICAgaWYgKGFycmFuZ2VkQ29udGVudCAmJiAhYXJyYW5nZWRDb250ZW50LmlzRGVzdHJveWVkKSB7CiAgICAgICAgKGZhbHNlICYmICEoYXJyYW5nZWRDb250ZW50ICE9PSB0aGlzKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkNhbid0IHNldCBBcnJheVByb3h5J3MgY29udGVudCB0byBpdHNlbGYiLCBhcnJhbmdlZENvbnRlbnQgIT09IHRoaXMpKTsKICAgICAgICAoZmFsc2UgJiYgISgoMCwgX2FycmF5LmlzQXJyYXkpKGFycmFuZ2VkQ29udGVudCkgfHwgYXJyYW5nZWRDb250ZW50LmlzRGVzdHJveWVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkFycmF5UHJveHkgZXhwZWN0cyBhbiBBcnJheSBvciBBcnJheVByb3h5LCBidXQgeW91IHBhc3NlZCAiICsgdHlwZW9mIGFycmFuZ2VkQ29udGVudCwgKDAsIF9hcnJheS5pc0FycmF5KShhcnJhbmdlZENvbnRlbnQpIHx8IGFycmFuZ2VkQ29udGVudC5pc0Rlc3Ryb3llZCkpOwogICAgICAgICgwLCBfbWV0YWwuYWRkQXJyYXlPYnNlcnZlcikoYXJyYW5nZWRDb250ZW50LCB0aGlzLCBBUlJBWV9PQlNFUlZFUl9NQVBQSU5HKTsKICAgICAgICB0aGlzLl9hcnJhbmdlZENvbnRlbnQgPSBhcnJhbmdlZENvbnRlbnQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9yZW1vdmVBcnJhbmdlZENvbnRlbnRBcnJheU9ic2V2ZXIgPSBmdW5jdGlvbiBfcmVtb3ZlQXJyYW5nZWRDb250ZW50QXJyYXlPYnNldmVyKCkgewogICAgICBpZiAodGhpcy5fYXJyYW5nZWRDb250ZW50KSB7CiAgICAgICAgKDAsIF9tZXRhbC5yZW1vdmVBcnJheU9ic2VydmVyKSh0aGlzLl9hcnJhbmdlZENvbnRlbnQsIHRoaXMsIEFSUkFZX09CU0VSVkVSX01BUFBJTkcpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fYXJyYW5nZWRDb250ZW50QXJyYXlXaWxsQ2hhbmdlID0gZnVuY3Rpb24gX2FycmFuZ2VkQ29udGVudEFycmF5V2lsbENoYW5nZSgpIHt9OwoKICAgIF9wcm90by5fYXJyYW5nZWRDb250ZW50QXJyYXlEaWRDaGFuZ2UgPSBmdW5jdGlvbiBfYXJyYW5nZWRDb250ZW50QXJyYXlEaWRDaGFuZ2UocHJveHksIGlkeCwgcmVtb3ZlZENudCwgYWRkZWRDbnQpIHsKICAgICAgdGhpcy5hcnJheUNvbnRlbnRXaWxsQ2hhbmdlKGlkeCwgcmVtb3ZlZENudCwgYWRkZWRDbnQpOwogICAgICB2YXIgZGlydHlJbmRleCA9IGlkeDsKCiAgICAgIGlmIChkaXJ0eUluZGV4IDwgMCkgewogICAgICAgIHZhciBsZW5ndGggPSAoMCwgX21ldGFsLmdldCkodGhpcy5fYXJyYW5nZWRDb250ZW50LCAnbGVuZ3RoJyk7CiAgICAgICAgZGlydHlJbmRleCArPSBsZW5ndGggKyByZW1vdmVkQ250IC0gYWRkZWRDbnQ7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLl9vYmplY3RzRGlydHlJbmRleCA9PT0gLTEgfHwgdGhpcy5fb2JqZWN0c0RpcnR5SW5kZXggPiBkaXJ0eUluZGV4KSB7CiAgICAgICAgdGhpcy5fb2JqZWN0c0RpcnR5SW5kZXggPSBkaXJ0eUluZGV4OwogICAgICB9CgogICAgICB0aGlzLl9sZW5ndGhEaXJ0eSA9IHRydWU7CiAgICAgIHRoaXMuYXJyYXlDb250ZW50RGlkQ2hhbmdlKGlkeCwgcmVtb3ZlZENudCwgYWRkZWRDbnQpOwogICAgfTsKCiAgICBfcHJvdG8uX2ludmFsaWRhdGUgPSBmdW5jdGlvbiBfaW52YWxpZGF0ZSgpIHsKICAgICAgdGhpcy5fb2JqZWN0c0RpcnR5SW5kZXggPSAwOwogICAgICB0aGlzLl9sZW5ndGhEaXJ0eSA9IHRydWU7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoQXJyYXlQcm94eSwgW3sKICAgICAga2V5OiAibGVuZ3RoIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRydWUKICAgICAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICAgICApIHsKICAgICAgICAgICAgdGhpcy5fcmV2YWxpZGF0ZSgpOwogICAgICAgICAgfQoKICAgICAgICBpZiAodGhpcy5fbGVuZ3RoRGlydHkpIHsKICAgICAgICAgIHZhciBhcnJhbmdlZENvbnRlbnQgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ2FycmFuZ2VkQ29udGVudCcpOwogICAgICAgICAgdGhpcy5fbGVuZ3RoID0gYXJyYW5nZWRDb250ZW50ID8gKDAsIF9tZXRhbC5nZXQpKGFycmFuZ2VkQ29udGVudCwgJ2xlbmd0aCcpIDogMDsKICAgICAgICAgIHRoaXMuX2xlbmd0aERpcnR5ID0gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fbGVuZ3RoOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSkgewogICAgICAgIHZhciBsZW5ndGggPSB0aGlzLmxlbmd0aDsKICAgICAgICB2YXIgcmVtb3ZlZENvdW50ID0gbGVuZ3RoIC0gdmFsdWU7CiAgICAgICAgdmFyIGFkZGVkOwoKICAgICAgICBpZiAocmVtb3ZlZENvdW50ID09PSAwKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfSBlbHNlIGlmIChyZW1vdmVkQ291bnQgPCAwKSB7CiAgICAgICAgICBhZGRlZCA9IG5ldyBBcnJheSgtcmVtb3ZlZENvdW50KTsKICAgICAgICAgIHJlbW92ZWRDb3VudCA9IDA7CiAgICAgICAgfQoKICAgICAgICB2YXIgY29udGVudCA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnY29udGVudCcpOwoKICAgICAgICBpZiAoY29udGVudCkgewogICAgICAgICAgKDAsIF9tZXRhbC5yZXBsYWNlKShjb250ZW50LCB2YWx1ZSwgcmVtb3ZlZENvdW50LCBhZGRlZCk7CgogICAgICAgICAgdGhpcy5faW52YWxpZGF0ZSgpOwogICAgICAgIH0KICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIEFycmF5UHJveHk7CiAgfShfb2JqZWN0LmRlZmF1bHQpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gQXJyYXlQcm94eTsKCiAgdmFyIF9yZXZhbGlkYXRlOwoKICBpZiAodHJ1ZQogIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICkgewogICAgICBfcmV2YWxpZGF0ZSA9IGZ1bmN0aW9uIF9yZXZhbGlkYXRlKCkgewogICAgICAgIGlmICghdGhpcy5fYXJyYW5nZWRDb250ZW50SXNVcGRhdGluZyAmJiAhKDAsIF9yZWZlcmVuY2UudmFsaWRhdGUpKHRoaXMuX2FycmFuZ2VkQ29udGVudFRhZywgdGhpcy5fYXJyYW5nZWRDb250ZW50UmV2aXNpb24pKSB7CiAgICAgICAgICB0aGlzLl9hcnJhbmdlZENvbnRlbnRJc1VwZGF0aW5nID0gdHJ1ZTsKCiAgICAgICAgICB0aGlzLl91cGRhdGVBcnJhbmdlZENvbnRlbnRBcnJheSgpOwoKICAgICAgICAgIHRoaXMuX2FycmFuZ2VkQ29udGVudElzVXBkYXRpbmcgPSBmYWxzZTsKICAgICAgICAgIHRoaXMuX2FycmFuZ2VkQ29udGVudFRhZyA9ICgwLCBfcmVmZXJlbmNlLmNvbWJpbmUpKCgwLCBfbWV0YWwuZ2V0Q2hhaW5UYWdzRm9yS2V5KSh0aGlzLCAnYXJyYW5nZWRDb250ZW50JykpOwogICAgICAgICAgdGhpcy5fYXJyYW5nZWRDb250ZW50UmV2aXNpb24gPSAoMCwgX3JlZmVyZW5jZS52YWx1ZSkodGhpcy5fYXJyYW5nZWRDb250ZW50VGFnKTsKICAgICAgICB9CiAgICAgIH07CiAgICB9CgogIEFycmF5UHJveHkucmVvcGVuKF9hcnJheS5NdXRhYmxlQXJyYXksIHsKICAgIC8qKgogICAgICBUaGUgYXJyYXkgdGhhdCB0aGUgcHJveHkgcHJldGVuZHMgdG8gYmUuIEluIHRoZSBkZWZhdWx0IGBBcnJheVByb3h5YAogICAgICBpbXBsZW1lbnRhdGlvbiwgdGhpcyBhbmQgYGNvbnRlbnRgIGFyZSB0aGUgc2FtZS4gU3ViY2xhc3NlcyBvZiBgQXJyYXlQcm94eWAKICAgICAgY2FuIG92ZXJyaWRlIHRoaXMgcHJvcGVydHkgdG8gcHJvdmlkZSB0aGluZ3MgbGlrZSBzb3J0aW5nIGFuZCBmaWx0ZXJpbmcuCiAgICAgICBAcHJvcGVydHkgYXJyYW5nZWRDb250ZW50CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBhcnJhbmdlZENvbnRlbnQ6ICgwLCBfbWV0YWwuYWxpYXMpKCdjb250ZW50JyksCiAgICBfcmV2YWxpZGF0ZTogX3JldmFsaWRhdGUKICB9KTsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL2NvcmVfb2JqZWN0IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL2NvbnRhaW5lciIsICJAZW1iZXIvLWludGVybmFscy9vd25lciIsICJAZW1iZXIvcG9seWZpbGxzIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9ydW5sb29wIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGEiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL2FjdGlvbl9oYW5kbGVyIiwgIkBlbWJlci9kZWJ1ZyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfY29udGFpbmVyLCBfb3duZXIsIF9wb2x5ZmlsbHMsIF91dGlscywgX3J1bmxvb3AsIF9tZXRhMiwgX21ldGFsLCBfYWN0aW9uX2hhbmRsZXIsIF9kZWJ1ZykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuc2V0RnJhbWV3b3JrQ2xhc3MgPSBzZXRGcmFtZXdvcmtDbGFzczsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyL29iamVjdAogICovCiAgdmFyIF9yZW9wZW4gPSBfbWV0YWwuTWl4aW4ucHJvdG90eXBlLnJlb3BlbjsKICB2YXIgd2FzQXBwbGllZCA9IG5ldyBfcG9seWZpbGxzLl9XZWFrU2V0KCk7CiAgdmFyIGZhY3RvcnlNYXAgPSBuZXcgV2Vha01hcCgpOwogIHZhciBwcm90b3R5cGVNaXhpbk1hcCA9IG5ldyBXZWFrTWFwKCk7CiAgdmFyIGluaXRDYWxsZWQgPSBmYWxzZQogIC8qIERFQlVHICovCiAgPyBuZXcgX3BvbHlmaWxscy5fV2Vha1NldCgpIDogdW5kZWZpbmVkOyAvLyBvbmx5IHVzZWQgaW4gZGVidWcgYnVpbGRzIHRvIGVuYWJsZSB0aGUgcHJveHkgdHJhcAoKICB2YXIgUEFTU0VEX0ZST01fQ1JFQVRFID0gZmFsc2UKICAvKiBERUJVRyAqLwogID8gKDAsIF91dGlscy5zeW1ib2wpKCdQQVNTRURfRlJPTV9DUkVBVEUnKSA6IHVuZGVmaW5lZDsKICB2YXIgRlJBTUVXT1JLX0NMQVNTRVMgPSB0cnVlCiAgLyogRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCAqLwogID8gKDAsIF91dGlscy5zeW1ib2wpKCdGUkFNRVdPUktfQ0xBU1MnKSA6IHVuZGVmaW5lZDsKCiAgZnVuY3Rpb24gc2V0RnJhbWV3b3JrQ2xhc3Moa2xhc3MpIHsKICAgIGtsYXNzW0ZSQU1FV09SS19DTEFTU0VTXSA9IHRydWU7CiAgfQoKICBmdW5jdGlvbiBpbml0aWFsaXplKG9iaiwgcHJvcGVydGllcykgewogICAgdmFyIG0gPSAoMCwgX21ldGEyLm1ldGEpKG9iaik7CgogICAgaWYgKHByb3BlcnRpZXMgIT09IHVuZGVmaW5lZCkgewogICAgICAoZmFsc2UgJiYgISh0eXBlb2YgcHJvcGVydGllcyA9PT0gJ29iamVjdCcgJiYgcHJvcGVydGllcyAhPT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdFbWJlck9iamVjdC5jcmVhdGUgb25seSBhY2NlcHRzIG9iamVjdHMuJywgdHlwZW9mIHByb3BlcnRpZXMgPT09ICdvYmplY3QnICYmIHByb3BlcnRpZXMgIT09IG51bGwpKTsKICAgICAgKGZhbHNlICYmICEoIShwcm9wZXJ0aWVzIGluc3RhbmNlb2YgX21ldGFsLk1peGluKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdFbWJlck9iamVjdC5jcmVhdGUgbm8gbG9uZ2VyIHN1cHBvcnRzIG1peGluZyBpbiBvdGhlciAnICsgJ2RlZmluaXRpb25zLCB1c2UgLmV4dGVuZCAmIC5jcmVhdGUgc2VwYXJhdGVseSBpbnN0ZWFkLicsICEocHJvcGVydGllcyBpbnN0YW5jZW9mIF9tZXRhbC5NaXhpbikpKTsKICAgICAgdmFyIGNvbmNhdGVuYXRlZFByb3BlcnRpZXMgPSBvYmouY29uY2F0ZW5hdGVkUHJvcGVydGllczsKICAgICAgdmFyIG1lcmdlZFByb3BlcnRpZXMgPSBvYmoubWVyZ2VkUHJvcGVydGllczsKICAgICAgdmFyIGhhc0NvbmNhdGVuYXRlZFByb3BzID0gY29uY2F0ZW5hdGVkUHJvcGVydGllcyAhPT0gdW5kZWZpbmVkICYmIGNvbmNhdGVuYXRlZFByb3BlcnRpZXMubGVuZ3RoID4gMDsKICAgICAgdmFyIGhhc01lcmdlZFByb3BzID0gbWVyZ2VkUHJvcGVydGllcyAhPT0gdW5kZWZpbmVkICYmIG1lcmdlZFByb3BlcnRpZXMubGVuZ3RoID4gMDsKICAgICAgdmFyIGtleU5hbWVzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleU5hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGtleU5hbWUgPSBrZXlOYW1lc1tpXTsKICAgICAgICB2YXIgdmFsdWUgPSBwcm9wZXJ0aWVzW2tleU5hbWVdOwogICAgICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzQ2xhc3NpY0RlY29yYXRvcikodmFsdWUpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0VtYmVyT2JqZWN0LmNyZWF0ZSBubyBsb25nZXIgc3VwcG9ydHMgZGVmaW5pbmcgY29tcHV0ZWQgJyArICdwcm9wZXJ0aWVzLiBEZWZpbmUgY29tcHV0ZWQgcHJvcGVydGllcyB1c2luZyBleHRlbmQoKSBvciByZW9wZW4oKSAnICsgJ2JlZm9yZSBjYWxsaW5nIGNyZWF0ZSgpLicsICEoMCwgX21ldGFsLmlzQ2xhc3NpY0RlY29yYXRvcikodmFsdWUpKSk7CiAgICAgICAgKGZhbHNlICYmICEoISh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicgJiYgdmFsdWUudG9TdHJpbmcoKS5pbmRleE9mKCcuX3N1cGVyJykgIT09IC0xKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdFbWJlck9iamVjdC5jcmVhdGUgbm8gbG9uZ2VyIHN1cHBvcnRzIGRlZmluaW5nIG1ldGhvZHMgdGhhdCBjYWxsIF9zdXBlci4nLCAhKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJyAmJiB2YWx1ZS50b1N0cmluZygpLmluZGV4T2YoJy5fc3VwZXInKSAhPT0gLTEpKSk7CiAgICAgICAgKGZhbHNlICYmICEoIShrZXlOYW1lID09PSAnYWN0aW9ucycgJiYgX2FjdGlvbl9oYW5kbGVyLmRlZmF1bHQuZGV0ZWN0KG9iaikpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2BhY3Rpb25zYCBtdXN0IGJlIHByb3ZpZGVkIGF0IGV4dGVuZCB0aW1lLCBub3QgYXQgY3JlYXRlIHRpbWUsICcgKyAnd2hlbiBFbWJlci5BY3Rpb25IYW5kbGVyIGlzIHVzZWQgKGkuZS4gdmlld3MsIGNvbnRyb2xsZXJzICYgcm91dGVzKS4nLCAhKGtleU5hbWUgPT09ICdhY3Rpb25zJyAmJiBfYWN0aW9uX2hhbmRsZXIuZGVmYXVsdC5kZXRlY3Qob2JqKSkpKTsKICAgICAgICB2YXIgcG9zc2libGVEZXNjID0gKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKG9iaiwga2V5TmFtZSwgbSk7CiAgICAgICAgdmFyIGlzRGVzY3JpcHRvciA9IHBvc3NpYmxlRGVzYyAhPT0gdW5kZWZpbmVkOwoKICAgICAgICBpZiAoIWlzRGVzY3JpcHRvcikgewogICAgICAgICAgdmFyIGJhc2VWYWx1ZSA9IG9ialtrZXlOYW1lXTsKCiAgICAgICAgICBpZiAoaGFzQ29uY2F0ZW5hdGVkUHJvcHMgJiYgY29uY2F0ZW5hdGVkUHJvcGVydGllcy5pbmRleE9mKGtleU5hbWUpID4gLTEpIHsKICAgICAgICAgICAgaWYgKGJhc2VWYWx1ZSkgewogICAgICAgICAgICAgIHZhbHVlID0gKDAsIF91dGlscy5tYWtlQXJyYXkpKGJhc2VWYWx1ZSkuY29uY2F0KHZhbHVlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB2YWx1ZSA9ICgwLCBfdXRpbHMubWFrZUFycmF5KSh2YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoaGFzTWVyZ2VkUHJvcHMgJiYgbWVyZ2VkUHJvcGVydGllcy5pbmRleE9mKGtleU5hbWUpID4gLTEpIHsKICAgICAgICAgICAgdmFsdWUgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBiYXNlVmFsdWUsIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmIChpc0Rlc2NyaXB0b3IpIHsKICAgICAgICAgIHBvc3NpYmxlRGVzYy5zZXQob2JqLCBrZXlOYW1lLCB2YWx1ZSk7CiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb2JqLnNldFVua25vd25Qcm9wZXJ0eSA9PT0gJ2Z1bmN0aW9uJyAmJiAhKGtleU5hbWUgaW4gb2JqKSkgewogICAgICAgICAgb2JqLnNldFVua25vd25Qcm9wZXJ0eShrZXlOYW1lLCB2YWx1ZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChmYWxzZQogICAgICAgICAgLyogREVCVUcgKi8KICAgICAgICAgICkgewogICAgICAgICAgICAoMCwgX21ldGFsLmRlZmluZVByb3BlcnR5KShvYmosIGtleU5hbWUsIG51bGwsIHZhbHVlLCBtKTsgLy8gc2V0dXAgbWFuZGF0b3J5IHNldHRlcgogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgb2JqW2tleU5hbWVdID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9IC8vIHVzaW5nIERFQlVHIGhlcmUgdG8gYXZvaWQgdGhlIGV4dHJhbmVvdXMgdmFyaWFibGUgd2hlbiBub3QgbmVlZGVkCgoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBpbml0Q2FsbGVkLmFkZChvYmopOwogICAgfQoKICAgIG9iai5pbml0KHByb3BlcnRpZXMpOwogICAgbS51bnNldEluaXRpYWxpemluZygpOwoKICAgIGlmICh0cnVlCiAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICkgewogICAgICAgIHZhciBvYnNlcnZlckV2ZW50cyA9IG0ub2JzZXJ2ZXJFdmVudHMoKTsKCiAgICAgICAgaWYgKG9ic2VydmVyRXZlbnRzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBvYnNlcnZlckV2ZW50cy5sZW5ndGg7IF9pKyspIHsKICAgICAgICAgICAgKDAsIF9tZXRhbC5hY3RpdmF0ZU9ic2VydmVyKShvYmosIG9ic2VydmVyRXZlbnRzW19pXS5ldmVudCwgb2JzZXJ2ZXJFdmVudHNbX2ldLnN5bmMpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgLy8gcmUtZW5hYmxlIGNoYWlucwogICAgICAoMCwgX21ldGFsLmZpbmlzaENoYWlucykobSk7CiAgICB9CgogICAgKDAsIF9tZXRhbC5zZW5kRXZlbnQpKG9iaiwgJ2luaXQnLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBtKTsKICB9CiAgLyoqCiAgICBgQ29yZU9iamVjdGAgaXMgdGhlIGJhc2UgY2xhc3MgZm9yIGFsbCBFbWJlciBjb25zdHJ1Y3RzLiBJdCBlc3RhYmxpc2hlcyBhCiAgICBjbGFzcyBzeXN0ZW0gYmFzZWQgb24gRW1iZXIncyBNaXhpbiBzeXN0ZW0sIGFuZCBwcm92aWRlcyB0aGUgYmFzaXMgZm9yIHRoZQogICAgRW1iZXIgT2JqZWN0IE1vZGVsLiBgQ29yZU9iamVjdGAgc2hvdWxkIGdlbmVyYWxseSBub3QgYmUgdXNlZCBkaXJlY3RseSwKICAgIGluc3RlYWQgeW91IHNob3VsZCB1c2UgYEVtYmVyT2JqZWN0YC4KICAKICAgICMjIFVzYWdlCiAgCiAgICBZb3UgY2FuIGRlZmluZSBhIGNsYXNzIGJ5IGV4dGVuZGluZyBmcm9tIGBDb3JlT2JqZWN0YCB1c2luZyB0aGUgYGV4dGVuZGAKICAgIG1ldGhvZDoKICAKICAgIGBgYGpzCiAgICBjb25zdCBQZXJzb24gPSBDb3JlT2JqZWN0LmV4dGVuZCh7CiAgICAgIG5hbWU6ICdUb21zdGVyJywKICAgIH0pOwogICAgYGBgCiAgCiAgICBGb3IgZGV0YWlsZWQgdXNhZ2UsIHNlZSB0aGUgW09iamVjdCBNb2RlbF0oaHR0cHM6Ly9ndWlkZXMuZW1iZXJqcy5jb20vcmVsZWFzZS9vYmplY3QtbW9kZWwvKQogICAgc2VjdGlvbiBvZiB0aGUgZ3VpZGVzLgogIAogICAgIyMgVXNhZ2Ugd2l0aCBOYXRpdmUgQ2xhc3NlcwogIAogICAgTmF0aXZlIEphdmFTY3JpcHQgYGNsYXNzYCBzeW50YXggY2FuIGJlIHVzZWQgdG8gZXh0ZW5kIGZyb20gYW55IGBDb3JlT2JqZWN0YAogICAgYmFzZWQgY2xhc3M6CiAgCiAgICBgYGBqcwogICAgY2xhc3MgUGVyc29uIGV4dGVuZHMgQ29yZU9iamVjdCB7CiAgICAgIGluaXQoKSB7CiAgICAgICAgc3VwZXIuaW5pdCguLi5hcmd1bWVudHMpOwogICAgICAgIHRoaXMubmFtZSA9ICdUb21zdGVyJzsKICAgICAgfQogICAgfQogICAgYGBgCiAgCiAgICBTb21lIG5vdGVzIGFib3V0IGBjbGFzc2AgdXNhZ2U6CiAgCiAgICAqIGBuZXdgIHN5bnRheCBpcyBub3QgY3VycmVudGx5IHN1cHBvcnRlZCB3aXRoIGNsYXNzZXMgdGhhdCBleHRlbmQgZnJvbQogICAgICBgRW1iZXJPYmplY3RgIG9yIGBDb3JlT2JqZWN0YC4gWW91IG11c3QgY29udGludWUgdG8gdXNlIHRoZSBgY3JlYXRlYCBtZXRob2QKICAgICAgd2hlbiBtYWtpbmcgbmV3IGluc3RhbmNlcyBvZiBjbGFzc2VzLCBldmVuIGlmIHRoZXkgYXJlIGRlZmluZWQgdXNpbmcgbmF0aXZlCiAgICAgIGNsYXNzIHN5bnRheC4gSWYgeW91IHdhbnQgdG8gdXNlIGBuZXdgIHN5bnRheCwgY29uc2lkZXIgY3JlYXRpbmcgY2xhc3NlcwogICAgICB3aGljaCBkbyBfbm90XyBleHRlbmQgZnJvbSBgRW1iZXJPYmplY3RgIG9yIGBDb3JlT2JqZWN0YC4gRW1iZXIgZmVhdHVyZXMsCiAgICAgIHN1Y2ggYXMgY29tcHV0ZWQgcHJvcGVydGllcyBhbmQgZGVjb3JhdG9ycywgd2lsbCBzdGlsbCB3b3JrIHdpdGggYmFzZS1sZXNzCiAgICAgIGNsYXNzZXMuCiAgICAqIEluc3RlYWQgb2YgdXNpbmcgYHRoaXMuX3N1cGVyKClgLCB5b3UgbXVzdCB1c2Ugc3RhbmRhcmQgYHN1cGVyYCBzeW50YXggaW4KICAgICAgbmF0aXZlIGNsYXNzZXMuIFNlZSB0aGUgW01ETiBkb2NzIG9uIGNsYXNzZXNdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0NsYXNzZXMjU3VwZXJfY2xhc3NfY2FsbHNfd2l0aF9zdXBlcikKICAgICAgZm9yIG1vcmUgZGV0YWlscy4KICAgICogTmF0aXZlIGNsYXNzZXMgc3VwcG9ydCB1c2luZyBbY29uc3RydWN0b3JzXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9DbGFzc2VzI0NvbnN0cnVjdG9yKQogICAgICB0byBzZXQgdXAgbmV3bHktY3JlYXRlZCBpbnN0YW5jZXMuIEVtYmVyIHVzZXMgdGhlc2UgdG8sIGFtb25nIG90aGVyIHRoaW5ncywKICAgICAgc3VwcG9ydCBmZWF0dXJlcyB0aGF0IG5lZWQgdG8gcmV0cmlldmUgb3RoZXIgZW50aXRpZXMgYnkgbmFtZSwgbGlrZSBTZXJ2aWNlCiAgICAgIGluamVjdGlvbiBhbmQgYGdldE93bmVyYC4gVG8gZW5zdXJlIHlvdXIgY3VzdG9tIGluc3RhbmNlIHNldHVwIGxvZ2ljIHRha2VzCiAgICAgIHBsYWNlIGFmdGVyIHRoaXMgaW1wb3J0YW50IHdvcmsgaXMgZG9uZSwgYXZvaWQgdXNpbmcgdGhlIGBjb25zdHJ1Y3RvcmAgaW4KICAgICAgZmF2b3Igb2YgYGluaXRgLgogICAgKiBQcm9wZXJ0aWVzIHBhc3NlZCB0byBgY3JlYXRlYCB3aWxsIGJlIGF2YWlsYWJsZSBvbiB0aGUgaW5zdGFuY2UgYnkgdGhlIHRpbWUKICAgICAgYGluaXRgIHJ1bnMsIHNvIGFueSBjb2RlIHRoYXQgcmVxdWlyZXMgdGhlc2UgdmFsdWVzIHNob3VsZCB3b3JrIGF0IHRoYXQKICAgICAgdGltZS4KICAgICogVXNpbmcgbmF0aXZlIGNsYXNzZXMsIGFuZCBzd2l0Y2hpbmcgYmFjayB0byB0aGUgb2xkIEVtYmVyIE9iamVjdCBtb2RlbCBpcwogICAgICBmdWxseSBzdXBwb3J0ZWQuCiAgCiAgICBAY2xhc3MgQ29yZU9iamVjdAogICAgQHB1YmxpYwogICovCgoKICB2YXIgQ29yZU9iamVjdCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIENvcmVPYmplY3QuX2luaXRGYWN0b3J5ID0gZnVuY3Rpb24gX2luaXRGYWN0b3J5KGZhY3RvcnkpIHsKICAgICAgZmFjdG9yeU1hcC5zZXQodGhpcywgZmFjdG9yeSk7CiAgICB9OwoKICAgIGZ1bmN0aW9uIENvcmVPYmplY3QocGFzc2VkRnJvbUNyZWF0ZSkgewogICAgICAvLyBwbHVjayBvZmYgZmFjdG9yeQogICAgICB2YXIgaW5pdEZhY3RvcnkgPSBmYWN0b3J5TWFwLmdldCh0aGlzLmNvbnN0cnVjdG9yKTsKCiAgICAgIGlmIChpbml0RmFjdG9yeSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZmFjdG9yeU1hcC5kZWxldGUodGhpcy5jb25zdHJ1Y3Rvcik7CgogICAgICAgIF9jb250YWluZXIuRkFDVE9SWV9GT1Iuc2V0KHRoaXMsIGluaXRGYWN0b3J5KTsKICAgICAgfSAvLyBwcmVwYXJlIHByb3RvdHlwZS4uLgoKCiAgICAgIHRoaXMuY29uc3RydWN0b3IucHJvdG8oKTsKICAgICAgdmFyIHNlbGYgPSB0aGlzOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICYmIF91dGlscy5IQVNfTkFUSVZFX1BST1hZICYmIHR5cGVvZiBzZWxmLnVua25vd25Qcm9wZXJ0eSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIHZhciBtZXNzYWdlRm9yID0gZnVuY3Rpb24gbWVzc2FnZUZvcihvYmosIHByb3BlcnR5KSB7CiAgICAgICAgICByZXR1cm4gIllvdSBhdHRlbXB0ZWQgdG8gYWNjZXNzIHRoZSBgIiArIFN0cmluZyhwcm9wZXJ0eSkgKyAiYCBwcm9wZXJ0eSAob2YgIiArIG9iaiArICIpLlxuIiArICJTaW5jZSBFbWJlciAzLjEsIHRoaXMgaXMgdXN1YWxseSBmaW5lIGFzIHlvdSBubyBsb25nZXIgbmVlZCB0byB1c2UgYC5nZXQoKWBcbiIgKyAidG8gYWNjZXNzIGNvbXB1dGVkIHByb3BlcnRpZXMuIEhvd2V2ZXIsIGluIHRoaXMgY2FzZSwgdGhlIG9iamVjdCBpbiBxdWVzdGlvblxuIiArICJpcyBhIHNwZWNpYWwga2luZCBvZiBFbWJlciBvYmplY3QgKGEgcHJveHkpLiBUaGVyZWZvcmUsIGl0IGlzIHN0aWxsIG5lY2Vzc2FyeVxuIiArICgidG8gdXNlIGAuZ2V0KCciICsgU3RyaW5nKHByb3BlcnR5KSArICInKWAgaW4gdGhpcyBjYXNlLlxuXG4iKSArICJJZiB5b3UgZW5jb3VudGVyZWQgdGhpcyBlcnJvciBiZWNhdXNlIG9mIHRoaXJkLXBhcnR5IGNvZGUgdGhhdCB5b3UgZG9uJ3QgY29udHJvbCxcbiIgKyAidGhlcmUgaXMgbW9yZSBpbmZvcm1hdGlvbiBhdCBodHRwczovL2dpdGh1Yi5jb20vZW1iZXJqcy9lbWJlci5qcy9pc3N1ZXMvMTYxNDgsIGFuZFxuIiArICJ5b3UgY2FuIGhlbHAgdXMgaW1wcm92ZSB0aGlzIGVycm9yIG1lc3NhZ2UgYnkgdGVsbGluZyB1cyBtb3JlIGFib3V0IHdoYXQgaGFwcGVuZWQgaW5cbiIgKyAidGhpcyBzaXR1YXRpb24uIjsKICAgICAgICB9OwogICAgICAgIC8qIGdsb2JhbHMgUHJveHkgUmVmbGVjdCAqLwoKCiAgICAgICAgc2VsZiA9IG5ldyBQcm94eSh0aGlzLCB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCh0YXJnZXQsIHByb3BlcnR5LCByZWNlaXZlcikgewogICAgICAgICAgICBpZiAocHJvcGVydHkgPT09IF9tZXRhbC5QUk9YWV9DT05URU5UKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRhcmdldDsKICAgICAgICAgICAgfSBlbHNlIGlmICggLy8gaW5pdCBjYWxsZWQgd2lsbCBiZSBzZXQgb24gdGhlIHByb3h5LCBub3QgdGhlIHRhcmdldCwgc28gZ2V0IHdpdGggdGhlIHJlY2VpdmVyCiAgICAgICAgICAgICFpbml0Q2FsbGVkLmhhcyhyZWNlaXZlcikgfHwgdHlwZW9mIHByb3BlcnR5ID09PSAnc3ltYm9sJyB8fCAoMCwgX3V0aWxzLmlzSW50ZXJuYWxTeW1ib2wpKHByb3BlcnR5KSB8fCBwcm9wZXJ0eSA9PT0gJ3RvSlNPTicgfHwgcHJvcGVydHkgPT09ICd0b1N0cmluZycgfHwgcHJvcGVydHkgPT09ICd0b1N0cmluZ0V4dGVuc2lvbicgfHwgcHJvcGVydHkgPT09ICdkaWREZWZpbmVQcm9wZXJ0eScgfHwgcHJvcGVydHkgPT09ICd3aWxsV2F0Y2hQcm9wZXJ0eScgfHwgcHJvcGVydHkgPT09ICdkaWRVbndhdGNoUHJvcGVydHknIHx8IHByb3BlcnR5ID09PSAnZGlkQWRkTGlzdGVuZXInIHx8IHByb3BlcnR5ID09PSAnZGlkUmVtb3ZlTGlzdGVuZXInIHx8IHByb3BlcnR5ID09PSAnaXNEZXNjcmlwdG9yJyB8fCBwcm9wZXJ0eSA9PT0gJ19vbkxvb2t1cCcgfHwgcHJvcGVydHkgaW4gdGFyZ2V0KSB7CiAgICAgICAgICAgICAgcmV0dXJuIFJlZmxlY3QuZ2V0KHRhcmdldCwgcHJvcGVydHksIHJlY2VpdmVyKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdmFyIHZhbHVlID0gdGFyZ2V0LnVua25vd25Qcm9wZXJ0eS5jYWxsKHJlY2VpdmVyLCBwcm9wZXJ0eSk7CgogICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICAgICAgKGZhbHNlICYmICEodmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gbnVsbCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKG1lc3NhZ2VGb3IocmVjZWl2ZXIsIHByb3BlcnR5KSwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gbnVsbCkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSk7CgogICAgICAgIF9jb250YWluZXIuRkFDVE9SWV9GT1Iuc2V0KHNlbGYsIGluaXRGYWN0b3J5KTsKICAgICAgfSAvLyBkaXNhYmxlIGNoYWlucwoKCiAgICAgIHZhciBtID0gKDAsIF9tZXRhMi5tZXRhKShzZWxmKTsKICAgICAgbS5zZXRJbml0aWFsaXppbmcoKTsKICAgICAgKGZhbHNlICYmICEoZnVuY3Rpb24gKCkgewogICAgICAgIGlmIChwYXNzZWRGcm9tQ3JlYXRlID09PSBQQVNTRURfRlJPTV9DUkVBVEUpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgaWYgKCF0cnVlCiAgICAgICAgLyogRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCAqLwogICAgICAgICkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CgogICAgICAgIGlmIChpbml0RmFjdG9yeSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICBpZiAocGFzc2VkRnJvbUNyZWF0ZSA9PT0gaW5pdEZhY3Rvcnkub3duZXIpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9KCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQW4gRW1iZXJPYmplY3QgYmFzZWQgY2xhc3MsICIgKyB0aGlzLmNvbnN0cnVjdG9yICsgIiwgd2FzIG5vdCBpbnN0YW50aWF0ZWQgY29ycmVjdGx5LiBZb3UgbWF5IGhhdmUgZWl0aGVyIHVzZWQgYG5ld2AgaW5zdGVhZCBvZiBgLmNyZWF0ZSgpYCwgb3Igbm90IHBhc3NlZCBhcmd1bWVudHMgdG8geW91ciBjYWxsIHRvIHN1cGVyIGluIHRoZSBjb25zdHJ1Y3RvcjogYHN1cGVyKC4uLmFyZ3VtZW50cylgLiBJZiB5b3UgYXJlIHRyeWluZyB0byB1c2UgYG5ld2AsIGNvbnNpZGVyIHVzaW5nIG5hdGl2ZSBjbGFzc2VzIHdpdGhvdXQgZXh0ZW5kaW5nIGZyb20gRW1iZXJPYmplY3QuIiwgZnVuY3Rpb24gKCkgewogICAgICAgIGlmIChwYXNzZWRGcm9tQ3JlYXRlID09PSBQQVNTRURfRlJPTV9DUkVBVEUpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgaWYgKCF0cnVlKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KCiAgICAgICAgaWYgKGluaXRGYWN0b3J5ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CgogICAgICAgIGlmIChwYXNzZWRGcm9tQ3JlYXRlID09PSBpbml0RmFjdG9yeS5vd25lcikgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0oKSkpOyAvLyBvbmx5IHJldHVybiB3aGVuIGluIGRlYnVnIGJ1aWxkcyBhbmQgYHNlbGZgIGlzIHRoZSBwcm94eSBjcmVhdGVkIGFib3ZlCgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgJiYgc2VsZiAhPT0gdGhpcykgewogICAgICAgIHJldHVybiBzZWxmOwogICAgICB9CiAgICB9CgogICAgdmFyIF9wcm90byA9IENvcmVPYmplY3QucHJvdG90eXBlOwoKICAgIF9wcm90by5yZW9wZW4gPSBmdW5jdGlvbiByZW9wZW4oKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgICgwLCBfbWV0YWwuYXBwbHlNaXhpbikodGhpcywgYXJncyk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfQogICAgLyoqCiAgICAgIEFuIG92ZXJyaWRhYmxlIG1ldGhvZCBjYWxsZWQgd2hlbiBvYmplY3RzIGFyZSBpbnN0YW50aWF0ZWQuIEJ5IGRlZmF1bHQsCiAgICAgIGRvZXMgbm90aGluZyB1bmxlc3MgaXQgaXMgb3ZlcnJpZGRlbiBkdXJpbmcgY2xhc3MgZGVmaW5pdGlvbi4KICAgICAgIEV4YW1wbGU6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgIGNvbnN0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgICAgaW5pdCgpIHsKICAgICAgICAgIGFsZXJ0KGBOYW1lIGlzICR7dGhpcy5nZXQoJ25hbWUnKX1gKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgbGV0IHN0ZXZlID0gUGVyc29uLmNyZWF0ZSh7CiAgICAgICAgbmFtZTogJ1N0ZXZlJwogICAgICB9KTsKICAgICAgIC8vIGFsZXJ0cyAnTmFtZSBpcyBTdGV2ZScuCiAgICAgIGBgYAogICAgICAgTk9URTogSWYgeW91IGRvIG92ZXJyaWRlIGBpbml0YCBmb3IgYSBmcmFtZXdvcmsgY2xhc3MgbGlrZSBgRW1iZXIuVmlld2AsCiAgICAgIGJlIHN1cmUgdG8gY2FsbCBgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKWAgaW4geW91cgogICAgICBgaW5pdGAgZGVjbGFyYXRpb24hIElmIHlvdSBkb24ndCwgRW1iZXIgbWF5IG5vdCBoYXZlIGFuIG9wcG9ydHVuaXR5IHRvCiAgICAgIGRvIGltcG9ydGFudCBzZXR1cCB3b3JrLCBhbmQgeW91J2xsIHNlZSBzdHJhbmdlIGJlaGF2aW9yIGluIHlvdXIKICAgICAgYXBwbGljYXRpb24uCiAgICAgICBAbWV0aG9kIGluaXQKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uaW5pdCA9IGZ1bmN0aW9uIGluaXQoKSB7fQogICAgLyoqCiAgICAgIERlZmluZXMgdGhlIHByb3BlcnRpZXMgdGhhdCB3aWxsIGJlIGNvbmNhdGVuYXRlZCBmcm9tIHRoZSBzdXBlcmNsYXNzCiAgICAgIChpbnN0ZWFkIG9mIG92ZXJyaWRkZW4pLgogICAgICAgQnkgZGVmYXVsdCwgd2hlbiB5b3UgZXh0ZW5kIGFuIEVtYmVyIGNsYXNzIGEgcHJvcGVydHkgZGVmaW5lZCBpbgogICAgICB0aGUgc3ViY2xhc3Mgb3ZlcnJpZGVzIGEgcHJvcGVydHkgd2l0aCB0aGUgc2FtZSBuYW1lIHRoYXQgaXMgZGVmaW5lZAogICAgICBpbiB0aGUgc3VwZXJjbGFzcy4gSG93ZXZlciwgdGhlcmUgYXJlIHNvbWUgY2FzZXMgd2hlcmUgaXQgaXMgcHJlZmVyYWJsZQogICAgICB0byBidWlsZCB1cCBhIHByb3BlcnR5J3MgdmFsdWUgYnkgY29tYmluaW5nIHRoZSBzdXBlcmNsYXNzJyBwcm9wZXJ0eQogICAgICB2YWx1ZSB3aXRoIHRoZSBzdWJjbGFzcycgdmFsdWUuIEFuIGV4YW1wbGUgb2YgdGhpcyBpbiB1c2Ugd2l0aGluIEVtYmVyCiAgICAgIGlzIHRoZSBgY2xhc3NOYW1lc2AgcHJvcGVydHkgb2YgYEVtYmVyLlZpZXdgLgogICAgICAgSGVyZSBpcyBzb21lIHNhbXBsZSBjb2RlIHNob3dpbmcgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBhIGNvbmNhdGVuYXRlZAogICAgICBwcm9wZXJ0eSBhbmQgYSBub3JtYWwgb25lOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgICBjb25zdCBCYXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAgIC8vIENvbmZpZ3VyZSB3aGljaCBwcm9wZXJ0aWVzIHRvIGNvbmNhdGVuYXRlCiAgICAgICAgY29uY2F0ZW5hdGVkUHJvcGVydGllczogWydjb25jYXRlbmF0ZWRQcm9wZXJ0eSddLAogICAgICAgICBzb21lTm9uQ29uY2F0ZW5hdGVkUHJvcGVydHk6IFsnYmFyJ10sCiAgICAgICAgY29uY2F0ZW5hdGVkUHJvcGVydHk6IFsnYmFyJ10KICAgICAgfSk7CiAgICAgICBjb25zdCBGb29CYXIgPSBCYXIuZXh0ZW5kKHsKICAgICAgICBzb21lTm9uQ29uY2F0ZW5hdGVkUHJvcGVydHk6IFsnZm9vJ10sCiAgICAgICAgY29uY2F0ZW5hdGVkUHJvcGVydHk6IFsnZm9vJ10KICAgICAgfSk7CiAgICAgICBsZXQgZm9vQmFyID0gRm9vQmFyLmNyZWF0ZSgpOwogICAgICBmb29CYXIuZ2V0KCdzb21lTm9uQ29uY2F0ZW5hdGVkUHJvcGVydHknKTsgLy8gWydmb28nXQogICAgICBmb29CYXIuZ2V0KCdjb25jYXRlbmF0ZWRQcm9wZXJ0eScpOyAvLyBbJ2JhcicsICdmb28nXQogICAgICBgYGAKICAgICAgIFRoaXMgYmVoYXZpb3IgZXh0ZW5kcyB0byBvYmplY3QgY3JlYXRpb24gYXMgd2VsbC4gQ29udGludWluZyB0aGUKICAgICAgYWJvdmUgZXhhbXBsZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IGZvb0JhciA9IEZvb0Jhci5jcmVhdGUoewogICAgICAgIHNvbWVOb25Db25jYXRlbmF0ZWRQcm9wZXJ0eTogWydiYXonXSwKICAgICAgICBjb25jYXRlbmF0ZWRQcm9wZXJ0eTogWydiYXonXQogICAgICB9KQogICAgICBmb29CYXIuZ2V0KCdzb21lTm9uQ29uY2F0ZW5hdGVkUHJvcGVydHknKTsgLy8gWydiYXonXQogICAgICBmb29CYXIuZ2V0KCdjb25jYXRlbmF0ZWRQcm9wZXJ0eScpOyAvLyBbJ2JhcicsICdmb28nLCAnYmF6J10KICAgICAgYGBgCiAgICAgICBBZGRpbmcgYSBzaW5nbGUgcHJvcGVydHkgdGhhdCBpcyBub3QgYW4gYXJyYXkgd2lsbCBqdXN0IGFkZCBpdCBpbiB0aGUgYXJyYXk6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBmb29CYXIgPSBGb29CYXIuY3JlYXRlKHsKICAgICAgICBjb25jYXRlbmF0ZWRQcm9wZXJ0eTogJ2JheicKICAgICAgfSkKICAgICAgdmlldy5nZXQoJ2NvbmNhdGVuYXRlZFByb3BlcnR5Jyk7IC8vIFsnYmFyJywgJ2ZvbycsICdiYXonXQogICAgICBgYGAKICAgICAgIFVzaW5nIHRoZSBgY29uY2F0ZW5hdGVkUHJvcGVydGllc2AgcHJvcGVydHksIHdlIGNhbiB0ZWxsIEVtYmVyIHRvIG1peCB0aGUKICAgICAgY29udGVudCBvZiB0aGUgcHJvcGVydGllcy4KICAgICAgIEluIGBDb21wb25lbnRgIHRoZSBgY2xhc3NOYW1lc2AsIGBjbGFzc05hbWVCaW5kaW5nc2AgYW5kCiAgICAgIGBhdHRyaWJ1dGVCaW5kaW5nc2AgcHJvcGVydGllcyBhcmUgY29uY2F0ZW5hdGVkLgogICAgICAgVGhpcyBmZWF0dXJlIGlzIGF2YWlsYWJsZSBmb3IgeW91IHRvIHVzZSB0aHJvdWdob3V0IHRoZSBFbWJlciBvYmplY3QgbW9kZWwsCiAgICAgIGFsdGhvdWdoIHR5cGljYWwgYXBwIGRldmVsb3BlcnMgYXJlIGxpa2VseSB0byB1c2UgaXQgaW5mcmVxdWVudGx5LiBTaW5jZQogICAgICBpdCBjaGFuZ2VzIGV4cGVjdGF0aW9ucyBhYm91dCBiZWhhdmlvciBvZiBwcm9wZXJ0aWVzLCB5b3Ugc2hvdWxkIHByb3Blcmx5CiAgICAgIGRvY3VtZW50IGl0cyB1c2FnZSBpbiBlYWNoIGluZGl2aWR1YWwgY29uY2F0ZW5hdGVkIHByb3BlcnR5ICh0byBub3QKICAgICAgbWlzbGVhZCB5b3VyIHVzZXJzIHRvIHRoaW5rIHRoZXkgY2FuIG92ZXJyaWRlIHRoZSBwcm9wZXJ0eSBpbiBhIHN1YmNsYXNzKS4KICAgICAgIEBwcm9wZXJ0eSBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzCiAgICAgIEB0eXBlIEFycmF5CiAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgRGVmaW5lcyB0aGUgcHJvcGVydGllcyB0aGF0IHdpbGwgYmUgbWVyZ2VkIGZyb20gdGhlIHN1cGVyY2xhc3MKICAgICAgKGluc3RlYWQgb2Ygb3ZlcnJpZGRlbikuCiAgICAgICBCeSBkZWZhdWx0LCB3aGVuIHlvdSBleHRlbmQgYW4gRW1iZXIgY2xhc3MgYSBwcm9wZXJ0eSBkZWZpbmVkIGluCiAgICAgIHRoZSBzdWJjbGFzcyBvdmVycmlkZXMgYSBwcm9wZXJ0eSB3aXRoIHRoZSBzYW1lIG5hbWUgdGhhdCBpcyBkZWZpbmVkCiAgICAgIGluIHRoZSBzdXBlcmNsYXNzLiBIb3dldmVyLCB0aGVyZSBhcmUgc29tZSBjYXNlcyB3aGVyZSBpdCBpcyBwcmVmZXJhYmxlCiAgICAgIHRvIGJ1aWxkIHVwIGEgcHJvcGVydHkncyB2YWx1ZSBieSBtZXJnaW5nIHRoZSBzdXBlcmNsYXNzIHByb3BlcnR5IHZhbHVlCiAgICAgIHdpdGggdGhlIHN1YmNsYXNzIHByb3BlcnR5J3MgdmFsdWUuIEFuIGV4YW1wbGUgb2YgdGhpcyBpbiB1c2Ugd2l0aGluIEVtYmVyCiAgICAgIGlzIHRoZSBgcXVlcnlQYXJhbXNgIHByb3BlcnR5IG9mIHJvdXRlcy4KICAgICAgIEhlcmUgaXMgc29tZSBzYW1wbGUgY29kZSBzaG93aW5nIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gYSBtZXJnZWQKICAgICAgcHJvcGVydHkgYW5kIGEgbm9ybWFsIG9uZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgY29uc3QgQmFyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICAvLyBDb25maWd1cmUgd2hpY2ggcHJvcGVydGllcyBhcmUgdG8gYmUgbWVyZ2VkCiAgICAgICAgbWVyZ2VkUHJvcGVydGllczogWydtZXJnZWRQcm9wZXJ0eSddLAogICAgICAgICBzb21lTm9uTWVyZ2VkUHJvcGVydHk6IHsKICAgICAgICAgIG5vbk1lcmdlZDogJ3N1cGVyY2xhc3MgdmFsdWUgb2Ygbm9uTWVyZ2VkJwogICAgICAgIH0sCiAgICAgICAgbWVyZ2VkUHJvcGVydHk6IHsKICAgICAgICAgIHBhZ2U6IHsgcmVwbGFjZTogZmFsc2UgfSwKICAgICAgICAgIGxpbWl0OiB7IHJlcGxhY2U6IHRydWUgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBjb25zdCBGb29CYXIgPSBCYXIuZXh0ZW5kKHsKICAgICAgICBzb21lTm9uTWVyZ2VkUHJvcGVydHk6IHsKICAgICAgICAgIGNvbXBsZXRlbHlOb25NZXJnZWQ6ICdzdWJjbGFzcyB2YWx1ZSBvZiBub25NZXJnZWQnCiAgICAgICAgfSwKICAgICAgICBtZXJnZWRQcm9wZXJ0eTogewogICAgICAgICAgbGltaXQ6IHsgcmVwbGFjZTogZmFsc2UgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBsZXQgZm9vQmFyID0gRm9vQmFyLmNyZWF0ZSgpOwogICAgICAgZm9vQmFyLmdldCgnc29tZU5vbk1lcmdlZFByb3BlcnR5Jyk7CiAgICAgIC8vID0+IHsgY29tcGxldGVseU5vbk1lcmdlZDogJ3N1YmNsYXNzIHZhbHVlIG9mIG5vbk1lcmdlZCcgfQogICAgICAvLwogICAgICAvLyBOb3RlIHRoZSBlbnRpcmUgb2JqZWN0LCBpbmNsdWRpbmcgdGhlIG5vbk1lcmdlZCBwcm9wZXJ0eSBvZgogICAgICAvLyB0aGUgc3VwZXJjbGFzcyBvYmplY3QsIGhhcyBiZWVuIHJlcGxhY2VkCiAgICAgICBmb29CYXIuZ2V0KCdtZXJnZWRQcm9wZXJ0eScpOwogICAgICAvLyA9PiB7CiAgICAgIC8vICAgcGFnZToge3JlcGxhY2U6IGZhbHNlfSwKICAgICAgLy8gICBsaW1pdDoge3JlcGxhY2U6IGZhbHNlfQogICAgICAvLyB9CiAgICAgIC8vCiAgICAgIC8vIE5vdGUgdGhlIHBhZ2UgcmVtYWlucyBmcm9tIHRoZSBzdXBlcmNsYXNzLCBhbmQgdGhlCiAgICAgIC8vIGBsaW1pdGAgcHJvcGVydHkncyB2YWx1ZSBvZiBgZmFsc2VgIGhhcyBiZWVuIG1lcmdlZCBmcm9tCiAgICAgIC8vIHRoZSBzdWJjbGFzcy4KICAgICAgYGBgCiAgICAgICBUaGlzIGJlaGF2aW9yIGlzIG5vdCBhdmFpbGFibGUgZHVyaW5nIG9iamVjdCBgY3JlYXRlYCBjYWxscy4gSXQgaXMgb25seQogICAgICBhdmFpbGFibGUgYXQgYGV4dGVuZGAgdGltZS4KICAgICAgIEluIGBSb3V0ZWAgdGhlIGBxdWVyeVBhcmFtc2AgcHJvcGVydHkgaXMgbWVyZ2VkLgogICAgICAgVGhpcyBmZWF0dXJlIGlzIGF2YWlsYWJsZSBmb3IgeW91IHRvIHVzZSB0aHJvdWdob3V0IHRoZSBFbWJlciBvYmplY3QgbW9kZWwsCiAgICAgIGFsdGhvdWdoIHR5cGljYWwgYXBwIGRldmVsb3BlcnMgYXJlIGxpa2VseSB0byB1c2UgaXQgaW5mcmVxdWVudGx5LiBTaW5jZQogICAgICBpdCBjaGFuZ2VzIGV4cGVjdGF0aW9ucyBhYm91dCBiZWhhdmlvciBvZiBwcm9wZXJ0aWVzLCB5b3Ugc2hvdWxkIHByb3Blcmx5CiAgICAgIGRvY3VtZW50IGl0cyB1c2FnZSBpbiBlYWNoIGluZGl2aWR1YWwgbWVyZ2VkIHByb3BlcnR5ICh0byBub3QKICAgICAgbWlzbGVhZCB5b3VyIHVzZXJzIHRvIHRoaW5rIHRoZXkgY2FuIG92ZXJyaWRlIHRoZSBwcm9wZXJ0eSBpbiBhIHN1YmNsYXNzKS4KICAgICAgIEBwcm9wZXJ0eSBtZXJnZWRQcm9wZXJ0aWVzCiAgICAgIEB0eXBlIEFycmF5CiAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgQHB1YmxpYwogICAgKi8KCiAgICAvKioKICAgICAgRGVzdHJveWVkIG9iamVjdCBwcm9wZXJ0eSBmbGFnLgogICAgICAgaWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAgdGhlIG9ic2VydmVycyBhbmQgYmluZGluZ3Mgd2VyZSBhbHJlYWR5CiAgICAgIHJlbW92ZWQgYnkgdGhlIGVmZmVjdCBvZiBjYWxsaW5nIHRoZSBgZGVzdHJveSgpYCBtZXRob2QuCiAgICAgICBAcHJvcGVydHkgaXNEZXN0cm95ZWQKICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICAvKioKICAgICAgRGVzdHJveXMgYW4gb2JqZWN0IGJ5IHNldHRpbmcgdGhlIGBpc0Rlc3Ryb3llZGAgZmxhZyBhbmQgcmVtb3ZpbmcgaXRzCiAgICAgIG1ldGFkYXRhLCB3aGljaCBlZmZlY3RpdmVseSBkZXN0cm95cyBvYnNlcnZlcnMgYW5kIGJpbmRpbmdzLgogICAgICAgSWYgeW91IHRyeSB0byBzZXQgYSBwcm9wZXJ0eSBvbiBhIGRlc3Ryb3llZCBvYmplY3QsIGFuIGV4Y2VwdGlvbiB3aWxsIGJlCiAgICAgIHJhaXNlZC4KICAgICAgIE5vdGUgdGhhdCBkZXN0cnVjdGlvbiBpcyBzY2hlZHVsZWQgZm9yIHRoZSBlbmQgb2YgdGhlIHJ1biBsb29wIGFuZCBkb2VzIG5vdAogICAgICBoYXBwZW4gaW1tZWRpYXRlbHkuICBJdCB3aWxsIHNldCBhbiBpc0Rlc3Ryb3lpbmcgZmxhZyBpbW1lZGlhdGVseS4KICAgICAgIEBtZXRob2QgZGVzdHJveQogICAgICBAcmV0dXJuIHtFbWJlck9iamVjdH0gcmVjZWl2ZXIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIF9wcm90by5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdmFyIG0gPSAoMCwgX21ldGEyLnBlZWtNZXRhKSh0aGlzKTsKCiAgICAgIGlmIChtLmlzU291cmNlRGVzdHJveWluZygpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBtLnNldFNvdXJjZURlc3Ryb3lpbmcoKTsKICAgICAgKDAsIF9ydW5sb29wLnNjaGVkdWxlKSgnYWN0aW9ucycsIHRoaXMsIHRoaXMud2lsbERlc3Ryb3kpOwogICAgICAoMCwgX3J1bmxvb3Auc2NoZWR1bGUpKCdkZXN0cm95JywgdGhpcywgdGhpcy5fc2NoZWR1bGVkRGVzdHJveSwgbSk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfQogICAgLyoqCiAgICAgIE92ZXJyaWRlIHRvIGltcGxlbWVudCB0ZWFyZG93bi4KICAgICAgIEBtZXRob2Qgd2lsbERlc3Ryb3kKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ud2lsbERlc3Ryb3kgPSBmdW5jdGlvbiB3aWxsRGVzdHJveSgpIHt9CiAgICAvKioKICAgICAgSW52b2tlZCBieSB0aGUgcnVuIGxvb3AgdG8gYWN0dWFsbHkgZGVzdHJveSB0aGUgb2JqZWN0LiBUaGlzIGlzCiAgICAgIHNjaGVkdWxlZCBmb3IgZXhlY3V0aW9uIGJ5IHRoZSBgZGVzdHJveWAgbWV0aG9kLgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBfc2NoZWR1bGVkRGVzdHJveQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3NjaGVkdWxlZERlc3Ryb3kgPSBmdW5jdGlvbiBfc2NoZWR1bGVkRGVzdHJveShtKSB7CiAgICAgIGlmIChtLmlzU291cmNlRGVzdHJveWVkKCkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgICgwLCBfbWV0YTIuZGVsZXRlTWV0YSkodGhpcyk7CiAgICAgIG0uc2V0U291cmNlRGVzdHJveWVkKCk7CiAgICB9CiAgICAvKioKICAgICAgUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiB3aGljaCBhdHRlbXB0cyB0byBwcm92aWRlIG1vcmUgaW5mb3JtYXRpb24KICAgICAgdGhhbiBKYXZhc2NyaXB0J3MgYHRvU3RyaW5nYCB0eXBpY2FsbHkgZG9lcywgaW4gYSBnZW5lcmljIHdheSBmb3IgYWxsIEVtYmVyCiAgICAgIG9iamVjdHMuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgIGNvbnN0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCgpOwogICAgICBwZXJzb24gPSBQZXJzb24uY3JlYXRlKCk7CiAgICAgIHBlcnNvbi50b1N0cmluZygpOyAvLz0+ICI8UGVyc29uOmVtYmVyMTAyND4iCiAgICAgIGBgYAogICAgICAgSWYgdGhlIG9iamVjdCdzIGNsYXNzIGlzIG5vdCBkZWZpbmVkIG9uIGFuIEVtYmVyIG5hbWVzcGFjZSwgaXQgd2lsbAogICAgICBpbmRpY2F0ZSBpdCBpcyBhIHN1YmNsYXNzIG9mIHRoZSByZWdpc3RlcmVkIHN1cGVyY2xhc3M6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGNvbnN0IFN0dWRlbnQgPSBQZXJzb24uZXh0ZW5kKCk7CiAgICAgIGxldCBzdHVkZW50ID0gU3R1ZGVudC5jcmVhdGUoKTsKICAgICAgc3R1ZGVudC50b1N0cmluZygpOyAvLz0+ICI8KHN1YmNsYXNzIG9mIFBlcnNvbik6ZW1iZXIxMDI1PiIKICAgICAgYGBgCiAgICAgICBJZiB0aGUgbWV0aG9kIGB0b1N0cmluZ0V4dGVuc2lvbmAgaXMgZGVmaW5lZCwgaXRzIHJldHVybiB2YWx1ZSB3aWxsIGJlCiAgICAgIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGNvbnN0IFRlYWNoZXIgPSBQZXJzb24uZXh0ZW5kKHsKICAgICAgICB0b1N0cmluZ0V4dGVuc2lvbigpIHsKICAgICAgICAgIHJldHVybiB0aGlzLmdldCgnZnVsbE5hbWUnKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICB0ZWFjaGVyID0gVGVhY2hlci5jcmVhdGUoKTsKICAgICAgdGVhY2hlci50b1N0cmluZygpOyAvLz0+ICI8VGVhY2hlcjplbWJlcjEwMjY6VG9tIERhbGU+IgogICAgICBgYGAKICAgICAgIEBtZXRob2QgdG9TdHJpbmcKICAgICAgQHJldHVybiB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24KICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8udG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgdmFyIGhhc1RvU3RyaW5nRXh0ZW5zaW9uID0gdHlwZW9mIHRoaXMudG9TdHJpbmdFeHRlbnNpb24gPT09ICdmdW5jdGlvbic7CiAgICAgIHZhciBleHRlbnNpb24gPSBoYXNUb1N0cmluZ0V4dGVuc2lvbiA/ICI6IiArIHRoaXMudG9TdHJpbmdFeHRlbnNpb24oKSA6ICcnOwogICAgICB2YXIgcmV0ID0gIjwiICsgKCgwLCBfdXRpbHMuZ2V0TmFtZSkodGhpcykgfHwgX2NvbnRhaW5lci5GQUNUT1JZX0ZPUi5nZXQodGhpcykgfHwgdGhpcy5jb25zdHJ1Y3Rvci50b1N0cmluZygpKSArICI6IiArICgwLCBfdXRpbHMuZ3VpZEZvcikodGhpcykgKyBleHRlbnNpb24gKyAiPiI7CiAgICAgIHJldHVybiByZXQ7CiAgICB9CiAgICAvKioKICAgICAgQ3JlYXRlcyBhIG5ldyBzdWJjbGFzcy4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgY29uc3QgUGVyc29uID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICBzYXkodGhpbmcpIHsKICAgICAgICAgIGFsZXJ0KHRoaW5nKTsKICAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBUaGlzIGRlZmluZXMgYSBuZXcgc3ViY2xhc3Mgb2YgRW1iZXJPYmplY3Q6IGBQZXJzb25gLiBJdCBjb250YWlucyBvbmUgbWV0aG9kOiBgc2F5KClgLgogICAgICAgWW91IGNhbiBhbHNvIGNyZWF0ZSBhIHN1YmNsYXNzIGZyb20gYW55IGV4aXN0aW5nIGNsYXNzIGJ5IGNhbGxpbmcgaXRzIGBleHRlbmQoKWAgbWV0aG9kLgogICAgICBGb3IgZXhhbXBsZSwgeW91IG1pZ2h0IHdhbnQgdG8gY3JlYXRlIGEgc3ViY2xhc3Mgb2YgRW1iZXIncyBidWlsdC1pbiBgQ29tcG9uZW50YCBjbGFzczoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgIGNvbnN0IFBlcnNvbkNvbXBvbmVudCA9IENvbXBvbmVudC5leHRlbmQoewogICAgICAgIHRhZ05hbWU6ICdsaScsCiAgICAgICAgY2xhc3NOYW1lQmluZGluZ3M6IFsnaXNBZG1pbmlzdHJhdG9yJ10KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgV2hlbiBkZWZpbmluZyBhIHN1YmNsYXNzLCB5b3UgY2FuIG92ZXJyaWRlIG1ldGhvZHMgYnV0IHN0aWxsIGFjY2VzcyB0aGUKICAgICAgaW1wbGVtZW50YXRpb24gb2YgeW91ciBwYXJlbnQgY2xhc3MgYnkgY2FsbGluZyB0aGUgc3BlY2lhbCBgX3N1cGVyKClgIG1ldGhvZDoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgY29uc3QgUGVyc29uID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICBzYXkodGhpbmcpIHsKICAgICAgICAgIGxldCBuYW1lID0gdGhpcy5nZXQoJ25hbWUnKTsKICAgICAgICAgIGFsZXJ0KGAke25hbWV9IHNheXM6ICR7dGhpbmd9YCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGNvbnN0IFNvbGRpZXIgPSBQZXJzb24uZXh0ZW5kKHsKICAgICAgICBzYXkodGhpbmcpIHsKICAgICAgICAgIHRoaXMuX3N1cGVyKGAke3RoaW5nfSwgc2lyIWApOwogICAgICAgIH0sCiAgICAgICAgbWFyY2gobnVtYmVyT2ZIb3VycykgewogICAgICAgICAgYWxlcnQoYCR7dGhpcy5nZXQoJ25hbWUnKX0gbWFyY2hlcyBmb3IgJHtudW1iZXJPZkhvdXJzfSBob3Vycy5gKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgbGV0IHllaHVkYSA9IFNvbGRpZXIuY3JlYXRlKHsKICAgICAgICBuYW1lOiAnWWVodWRhIEthdHonCiAgICAgIH0pOwogICAgICAgeWVodWRhLnNheSgnWWVzJyk7ICAvLyBhbGVydHMgIlllaHVkYSBLYXR6IHNheXM6IFllcywgc2lyISIKICAgICAgYGBgCiAgICAgICBUaGUgYGNyZWF0ZSgpYCBvbiBsaW5lICMxNyBjcmVhdGVzIGFuICppbnN0YW5jZSogb2YgdGhlIGBTb2xkaWVyYCBjbGFzcy4KICAgICAgVGhlIGBleHRlbmQoKWAgb24gbGluZSAjOCBjcmVhdGVzIGEgKnN1YmNsYXNzKiBvZiBgUGVyc29uYC4gQW55IGluc3RhbmNlCiAgICAgIG9mIHRoZSBgUGVyc29uYCBjbGFzcyB3aWxsICpub3QqIGhhdmUgdGhlIGBtYXJjaCgpYCBtZXRob2QuCiAgICAgICBZb3UgY2FuIGFsc28gcGFzcyBgTWl4aW5gIGNsYXNzZXMgdG8gYWRkIGFkZGl0aW9uYWwgcHJvcGVydGllcyB0byB0aGUgc3ViY2xhc3MuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgaW1wb3J0IE1peGluIGZyb20gJ0BlbWJlci9vYmplY3QvbWl4aW4nOwogICAgICAgY29uc3QgUGVyc29uID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICBzYXkodGhpbmcpIHsKICAgICAgICAgIGFsZXJ0KGAke3RoaXMuZ2V0KCduYW1lJyl9IHNheXM6ICR7dGhpbmd9YCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGNvbnN0IFNpbmdpbmdNaXhpbiA9IE1peGluLmNyZWF0ZSh7CiAgICAgICAgc2luZyh0aGluZykgewogICAgICAgICAgYWxlcnQoYCR7dGhpcy5nZXQoJ25hbWUnKX0gc2luZ3M6IGxhIGxhIGxhICR7dGhpbmd9YCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGNvbnN0IEJyb2Fkd2F5U3RhciA9IFBlcnNvbi5leHRlbmQoU2luZ2luZ01peGluLCB7CiAgICAgICAgZGFuY2UoKSB7CiAgICAgICAgICBhbGVydChgJHt0aGlzLmdldCgnbmFtZScpfSBkYW5jZXM6IHRhcCB0YXAgdGFwIHRhcCBgKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRoZSBgQnJvYWR3YXlTdGFyYCBjbGFzcyBjb250YWlucyB0aHJlZSBtZXRob2RzOiBgc2F5KClgLCBgc2luZygpYCwgYW5kIGBkYW5jZSgpYC4KICAgICAgIEBtZXRob2QgZXh0ZW5kCiAgICAgIEBzdGF0aWMKICAgICAgQGZvciBAZW1iZXIvb2JqZWN0CiAgICAgIEBwYXJhbSB7TWl4aW59IFttaXhpbnNdKiBPbmUgb3IgbW9yZSBNaXhpbiBjbGFzc2VzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBbYXJndW1lbnRzXSogT2JqZWN0IGNvbnRhaW5pbmcgdmFsdWVzIHRvIHVzZSB3aXRoaW4gdGhlIG5ldyBjbGFzcwogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIENvcmVPYmplY3QuZXh0ZW5kID0gZnVuY3Rpb24gZXh0ZW5kKCkgewogICAgICB2YXIgQ2xhc3MgPQogICAgICAvKiNfX1BVUkVfXyovCiAgICAgIGZ1bmN0aW9uIChfdGhpcykgewogICAgICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDbGFzcywgX3RoaXMpOwoKICAgICAgICBmdW5jdGlvbiBDbGFzcygpIHsKICAgICAgICAgIHJldHVybiBfdGhpcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gQ2xhc3M7CiAgICAgIH0odGhpcyk7CgogICAgICBfcmVvcGVuLmFwcGx5KENsYXNzLlByb3RvdHlwZU1peGluLCBhcmd1bWVudHMpOwoKICAgICAgcmV0dXJuIENsYXNzOwogICAgfQogICAgLyoqCiAgICAgIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgYSBjbGFzcy4gQWNjZXB0cyBlaXRoZXIgbm8gYXJndW1lbnRzLCBvciBhbiBvYmplY3QKICAgICAgY29udGFpbmluZyB2YWx1ZXMgdG8gaW5pdGlhbGl6ZSB0aGUgbmV3bHkgaW5zdGFudGlhdGVkIG9iamVjdCB3aXRoLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICAgICBjb25zdCBQZXJzb24gPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAgIGhlbGxvV29ybGQoKSB7CiAgICAgICAgICBhbGVydChgSGksIG15IG5hbWUgaXMgJHt0aGlzLmdldCgnbmFtZScpfWApOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBsZXQgdG9tID0gUGVyc29uLmNyZWF0ZSh7CiAgICAgICAgbmFtZTogJ1RvbSBEYWxlJwogICAgICB9KTsKICAgICAgIHRvbS5oZWxsb1dvcmxkKCk7IC8vIGFsZXJ0cyAiSGksIG15IG5hbWUgaXMgVG9tIERhbGUiLgogICAgICBgYGAKICAgICAgIGBjcmVhdGVgIHdpbGwgY2FsbCB0aGUgYGluaXRgIGZ1bmN0aW9uIGlmIGRlZmluZWQgZHVyaW5nCiAgICAgIGBBbnlPYmplY3QuZXh0ZW5kYAogICAgICAgSWYgbm8gYXJndW1lbnRzIGFyZSBwYXNzZWQgdG8gYGNyZWF0ZWAsIGl0IHdpbGwgbm90IHNldCB2YWx1ZXMgdG8gdGhlIG5ldwogICAgICBpbnN0YW5jZSBkdXJpbmcgaW5pdGlhbGl6YXRpb246CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBub05hbWUgPSBQZXJzb24uY3JlYXRlKCk7CiAgICAgIG5vTmFtZS5oZWxsb1dvcmxkKCk7IC8vIGFsZXJ0cyB1bmRlZmluZWQKICAgICAgYGBgCiAgICAgICBOT1RFOiBGb3IgcGVyZm9ybWFuY2UgcmVhc29ucywgeW91IGNhbm5vdCBkZWNsYXJlIG1ldGhvZHMgb3IgY29tcHV0ZWQKICAgICAgcHJvcGVydGllcyBkdXJpbmcgYGNyZWF0ZWAuIFlvdSBzaG91bGQgaW5zdGVhZCBkZWNsYXJlIG1ldGhvZHMgYW5kIGNvbXB1dGVkCiAgICAgIHByb3BlcnRpZXMgd2hlbiB1c2luZyBgZXh0ZW5kYC4KICAgICAgIEBtZXRob2QgY3JlYXRlCiAgICAgIEBmb3IgQGVtYmVyL29iamVjdAogICAgICBAc3RhdGljCiAgICAgIEBwYXJhbSBbYXJndW1lbnRzXSoKICAgICAgQHB1YmxpYwogICAgKi8KICAgIDsKCiAgICBDb3JlT2JqZWN0LmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wcywgZXh0cmEpIHsKICAgICAgdmFyIEMgPSB0aGlzOwogICAgICB2YXIgaW5zdGFuY2U7CgogICAgICBpZiAodHJ1ZQogICAgICAvKiBFTUJFUl9GUkFNRVdPUktfT0JKRUNUX09XTkVSX0FSR1VNRU5UICovCiAgICAgICYmIHRoaXNbRlJBTUVXT1JLX0NMQVNTRVNdKSB7CiAgICAgICAgdmFyIGluaXRGYWN0b3J5ID0gZmFjdG9yeU1hcC5nZXQodGhpcyk7CiAgICAgICAgdmFyIG93bmVyOwoKICAgICAgICBpZiAoaW5pdEZhY3RvcnkgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgb3duZXIgPSBpbml0RmFjdG9yeS5vd25lcjsKICAgICAgICB9IGVsc2UgaWYgKHByb3BzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikocHJvcHMpOwogICAgICAgIH0KCiAgICAgICAgaWYgKG93bmVyID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIC8vIGZhbGxiYWNrIHRvIHBhc3NpbmcgdGhlIHNwZWNpYWwgUEFTU0VEX0ZST01fQ1JFQVRFIHN5bWJvbAogICAgICAgICAgLy8gdG8gYXZvaWQgYW4gZXJyb3Igd2hlbiBmb2xrcyBjYWxsIHRoaW5ncyBsaWtlIENvbnRyb2xsZXIuZXh0ZW5kKCkuY3JlYXRlKCkKICAgICAgICAgIC8vIHdlIHNob3VsZCBkbyBhIHN1YnNlcXVlbnQgZGVwcmVjYXRpb24gcGFzcyB0byBlbnN1cmUgdGhpcyBpc24ndCBhbGxvd2VkCiAgICAgICAgICBvd25lciA9IFBBU1NFRF9GUk9NX0NSRUFURTsKICAgICAgICB9CgogICAgICAgIGluc3RhbmNlID0gbmV3IEMob3duZXIpOwogICAgICB9IGVsc2UgewogICAgICAgIGluc3RhbmNlID0gZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgID8gbmV3IEMoUEFTU0VEX0ZST01fQ1JFQVRFKSA6IG5ldyBDKCk7CiAgICAgIH0KCiAgICAgIGlmIChleHRyYSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgaW5pdGlhbGl6ZShpbnN0YW5jZSwgcHJvcHMpOwogICAgICB9IGVsc2UgewogICAgICAgIGluaXRpYWxpemUoaW5zdGFuY2UsIGZsYXR0ZW5Qcm9wcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGluc3RhbmNlOwogICAgfQogICAgLyoqCiAgICAgIEF1Z21lbnRzIGEgY29uc3RydWN0b3IncyBwcm90b3R5cGUgd2l0aCBhZGRpdGlvbmFsCiAgICAgIHByb3BlcnRpZXMgYW5kIGZ1bmN0aW9uczoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgY29uc3QgTXlPYmplY3QgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAgIG5hbWU6ICdhbiBvYmplY3QnCiAgICAgIH0pOwogICAgICAgbyA9IE15T2JqZWN0LmNyZWF0ZSgpOwogICAgICBvLmdldCgnbmFtZScpOyAvLyAnYW4gb2JqZWN0JwogICAgICAgTXlPYmplY3QucmVvcGVuKHsKICAgICAgICBzYXkobXNnKSB7CiAgICAgICAgICBjb25zb2xlLmxvZyhtc2cpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBvMiA9IE15T2JqZWN0LmNyZWF0ZSgpOwogICAgICBvMi5zYXkoJ2hlbGxvJyk7IC8vIGxvZ3MgImhlbGxvIgogICAgICAgby5zYXkoJ2dvb2RieWUnKTsgLy8gbG9ncyAiZ29vZGJ5ZSIKICAgICAgYGBgCiAgICAgICBUbyBhZGQgZnVuY3Rpb25zIGFuZCBwcm9wZXJ0aWVzIHRvIHRoZSBjb25zdHJ1Y3RvciBpdHNlbGYsCiAgICAgIHNlZSBgcmVvcGVuQ2xhc3NgCiAgICAgICBAbWV0aG9kIHJlb3BlbgogICAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgICAgQHN0YXRpYwogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIENvcmVPYmplY3QucmVvcGVuID0gZnVuY3Rpb24gcmVvcGVuKCkgewogICAgICB0aGlzLndpbGxSZW9wZW4oKTsKCiAgICAgIF9yZW9wZW4uYXBwbHkodGhpcy5Qcm90b3R5cGVNaXhpbiwgYXJndW1lbnRzKTsKCiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICBDb3JlT2JqZWN0LndpbGxSZW9wZW4gPSBmdW5jdGlvbiB3aWxsUmVvcGVuKCkgewogICAgICB2YXIgcCA9IHRoaXMucHJvdG90eXBlOwoKICAgICAgaWYgKHdhc0FwcGxpZWQuaGFzKHApKSB7CiAgICAgICAgd2FzQXBwbGllZC5kZWxldGUocCk7IC8vIElmIHRoZSBiYXNlIG1peGluIGFscmVhZHkgZXhpc3RzIGFuZCB3YXMgYXBwbGllZCwgY3JlYXRlIGEgbmV3IG1peGluIHRvCiAgICAgICAgLy8gbWFrZSBzdXJlIHRoYXQgaXQgZ2V0cyBwcm9wZXJseSBhcHBsaWVkLiBSZXVzaW5nIHRoZSBzYW1lIG1peGluIGFmdGVyCiAgICAgICAgLy8gdGhlIGZpcnN0IGBwcm90b2AgY2FsbCB3aWxsIGNhdXNlIGl0IHRvIGdldCBza2lwcGVkLgoKICAgICAgICBpZiAocHJvdG90eXBlTWl4aW5NYXAuaGFzKHRoaXMpKSB7CiAgICAgICAgICBwcm90b3R5cGVNaXhpbk1hcC5zZXQodGhpcywgX21ldGFsLk1peGluLmNyZWF0ZSh0aGlzLlByb3RvdHlwZU1peGluKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgQXVnbWVudHMgYSBjb25zdHJ1Y3RvcidzIG93biBwcm9wZXJ0aWVzIGFuZCBmdW5jdGlvbnM6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgIGNvbnN0IE15T2JqZWN0ID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgICBuYW1lOiAnYW4gb2JqZWN0JwogICAgICB9KTsKICAgICAgIE15T2JqZWN0LnJlb3BlbkNsYXNzKHsKICAgICAgICBjYW5CdWlsZDogZmFsc2UKICAgICAgfSk7CiAgICAgICBNeU9iamVjdC5jYW5CdWlsZDsgLy8gZmFsc2UKICAgICAgbyA9IE15T2JqZWN0LmNyZWF0ZSgpOwogICAgICBgYGAKICAgICAgIEluIG90aGVyIHdvcmRzLCB0aGlzIGNyZWF0ZXMgc3RhdGljIHByb3BlcnRpZXMgYW5kIGZ1bmN0aW9ucyBmb3IgdGhlIGNsYXNzLgogICAgICBUaGVzZSBhcmUgb25seSBhdmFpbGFibGUgb24gdGhlIGNsYXNzIGFuZCBub3Qgb24gYW55IGluc3RhbmNlIG9mIHRoYXQgY2xhc3MuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgICAgIGNvbnN0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgICAgbmFtZTogJycsCiAgICAgICAgc2F5SGVsbG8oKSB7CiAgICAgICAgICBhbGVydChgSGVsbG8uIE15IG5hbWUgaXMgJHt0aGlzLmdldCgnbmFtZScpfWApOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBQZXJzb24ucmVvcGVuQ2xhc3MoewogICAgICAgIHNwZWNpZXM6ICdIb21vIHNhcGllbnMnLAogICAgICAgICBjcmVhdGVQZXJzb24obmFtZSkgewogICAgICAgICAgcmV0dXJuIFBlcnNvbi5jcmVhdGUoeyBuYW1lIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICBsZXQgdG9tID0gUGVyc29uLmNyZWF0ZSh7CiAgICAgICAgbmFtZTogJ1RvbSBEYWxlJwogICAgICB9KTsKICAgICAgbGV0IHllaHVkYSA9IFBlcnNvbi5jcmVhdGVQZXJzb24oJ1llaHVkYSBLYXR6Jyk7CiAgICAgICB0b20uc2F5SGVsbG8oKTsgLy8gIkhlbGxvLiBNeSBuYW1lIGlzIFRvbSBEYWxlIgogICAgICB5ZWh1ZGEuc2F5SGVsbG8oKTsgLy8gIkhlbGxvLiBNeSBuYW1lIGlzIFllaHVkYSBLYXR6IgogICAgICBhbGVydChQZXJzb24uc3BlY2llcyk7IC8vICJIb21vIHNhcGllbnMiCiAgICAgIGBgYAogICAgICAgTm90ZSB0aGF0IGBzcGVjaWVzYCBhbmQgYGNyZWF0ZVBlcnNvbmAgYXJlICpub3QqIHZhbGlkIG9uIHRoZSBgdG9tYCBhbmQgYHllaHVkYWAKICAgICAgdmFyaWFibGVzLiBUaGV5IGFyZSBvbmx5IHZhbGlkIG9uIGBQZXJzb25gLgogICAgICAgVG8gYWRkIGZ1bmN0aW9ucyBhbmQgcHJvcGVydGllcyB0byBpbnN0YW5jZXMgb2YKICAgICAgYSBjb25zdHJ1Y3RvciBieSBleHRlbmRpbmcgdGhlIGNvbnN0cnVjdG9yJ3MgcHJvdG90eXBlCiAgICAgIHNlZSBgcmVvcGVuYAogICAgICAgQG1ldGhvZCByZW9wZW5DbGFzcwogICAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgICAgQHN0YXRpYwogICAgICBAcHVibGljCiAgICAqLwogICAgOwoKICAgIENvcmVPYmplY3QucmVvcGVuQ2xhc3MgPSBmdW5jdGlvbiByZW9wZW5DbGFzcygpIHsKICAgICAgKDAsIF9tZXRhbC5hcHBseU1peGluKSh0aGlzLCBhcmd1bWVudHMpOwogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgQ29yZU9iamVjdC5kZXRlY3QgPSBmdW5jdGlvbiBkZXRlY3Qob2JqKSB7CiAgICAgIGlmICgnZnVuY3Rpb24nICE9PSB0eXBlb2Ygb2JqKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CgogICAgICB3aGlsZSAob2JqKSB7CiAgICAgICAgaWYgKG9iaiA9PT0gdGhpcykgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBvYmogPSBvYmouc3VwZXJjbGFzczsKICAgICAgfQoKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfTsKCiAgICBDb3JlT2JqZWN0LmRldGVjdEluc3RhbmNlID0gZnVuY3Rpb24gZGV0ZWN0SW5zdGFuY2Uob2JqKSB7CiAgICAgIHJldHVybiBvYmogaW5zdGFuY2VvZiB0aGlzOwogICAgfQogICAgLyoqCiAgICAgIEluIHNvbWUgY2FzZXMsIHlvdSBtYXkgd2FudCB0byBhbm5vdGF0ZSBjb21wdXRlZCBwcm9wZXJ0aWVzIHdpdGggYWRkaXRpb25hbAogICAgICBtZXRhZGF0YSBhYm91dCBob3cgdGhleSBmdW5jdGlvbiBvciB3aGF0IHZhbHVlcyB0aGV5IG9wZXJhdGUgb24uIEZvcgogICAgICBleGFtcGxlLCBjb21wdXRlZCBwcm9wZXJ0eSBmdW5jdGlvbnMgbWF5IGNsb3NlIG92ZXIgdmFyaWFibGVzIHRoYXQgYXJlIHRoZW4KICAgICAgbm8gbG9uZ2VyIGF2YWlsYWJsZSBmb3IgaW50cm9zcGVjdGlvbi4KICAgICAgIFlvdSBjYW4gcGFzcyBhIGhhc2ggb2YgdGhlc2UgdmFsdWVzIHRvIGEgY29tcHV0ZWQgcHJvcGVydHkgbGlrZSB0aGlzOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgcGVyc29uOiBjb21wdXRlZChmdW5jdGlvbigpIHsKICAgICAgICBsZXQgcGVyc29uSWQgPSB0aGlzLmdldCgncGVyc29uSWQnKTsKICAgICAgICByZXR1cm4gUGVyc29uLmNyZWF0ZSh7IGlkOiBwZXJzb25JZCB9KTsKICAgICAgfSkubWV0YSh7IHR5cGU6IFBlcnNvbiB9KQogICAgICBgYGAKICAgICAgIE9uY2UgeW91J3ZlIGRvbmUgdGhpcywgeW91IGNhbiByZXRyaWV2ZSB0aGUgdmFsdWVzIHNhdmVkIHRvIHRoZSBjb21wdXRlZAogICAgICBwcm9wZXJ0eSBmcm9tIHlvdXIgY2xhc3MgbGlrZSB0aGlzOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBNeUNsYXNzLm1ldGFGb3JQcm9wZXJ0eSgncGVyc29uJyk7CiAgICAgIGBgYAogICAgICAgVGhpcyB3aWxsIHJldHVybiB0aGUgb3JpZ2luYWwgaGFzaCB0aGF0IHdhcyBwYXNzZWQgdG8gYG1ldGEoKWAuCiAgICAgICBAc3RhdGljCiAgICAgIEBtZXRob2QgbWV0YUZvclByb3BlcnR5CiAgICAgIEBwYXJhbSBrZXkge1N0cmluZ30gcHJvcGVydHkgbmFtZQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBDb3JlT2JqZWN0Lm1ldGFGb3JQcm9wZXJ0eSA9IGZ1bmN0aW9uIG1ldGFGb3JQcm9wZXJ0eShrZXkpIHsKICAgICAgdmFyIHByb3RvID0gdGhpcy5wcm90bygpOyAvLyBlbnN1cmUgcHJvdG90eXBlIGlzIGluaXRpYWxpemVkCgogICAgICB2YXIgcG9zc2libGVEZXNjID0gKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKHByb3RvLCBrZXkpOwogICAgICAoZmFsc2UgJiYgIShwb3NzaWJsZURlc2MgIT09IHVuZGVmaW5lZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJtZXRhRm9yUHJvcGVydHkoKSBjb3VsZCBub3QgZmluZCBhIGNvbXB1dGVkIHByb3BlcnR5IHdpdGgga2V5ICciICsga2V5ICsgIicuIiwgcG9zc2libGVEZXNjICE9PSB1bmRlZmluZWQpKTsKICAgICAgcmV0dXJuIHBvc3NpYmxlRGVzYy5fbWV0YSB8fCB7fTsKICAgIH0KICAgIC8qKgogICAgICBJdGVyYXRlIG92ZXIgZWFjaCBjb21wdXRlZCBwcm9wZXJ0eSBmb3IgdGhlIGNsYXNzLCBwYXNzaW5nIGl0cyBuYW1lCiAgICAgIGFuZCBhbnkgYXNzb2NpYXRlZCBtZXRhZGF0YSAoc2VlIGBtZXRhRm9yUHJvcGVydHlgKSB0byB0aGUgY2FsbGJhY2suCiAgICAgICBAc3RhdGljCiAgICAgIEBtZXRob2QgZWFjaENvbXB1dGVkUHJvcGVydHkKICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sKICAgICAgQHBhcmFtIHtPYmplY3R9IGJpbmRpbmcKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgQ29yZU9iamVjdC5lYWNoQ29tcHV0ZWRQcm9wZXJ0eSA9IGZ1bmN0aW9uIGVhY2hDb21wdXRlZFByb3BlcnR5KGNhbGxiYWNrLCBiaW5kaW5nKSB7CiAgICAgIGlmIChiaW5kaW5nID09PSB2b2lkIDApIHsKICAgICAgICBiaW5kaW5nID0gdGhpczsKICAgICAgfQoKICAgICAgdGhpcy5wcm90bygpOyAvLyBlbnN1cmUgcHJvdG90eXBlIGlzIGluaXRpYWxpemVkCgogICAgICB2YXIgZW1wdHkgPSB7fTsKICAgICAgKDAsIF9tZXRhMi5tZXRhKSh0aGlzLnByb3RvdHlwZSkuZm9yRWFjaERlc2NyaXB0b3JzKGZ1bmN0aW9uIChuYW1lLCBkZXNjcmlwdG9yKSB7CiAgICAgICAgaWYgKGRlc2NyaXB0b3IuZW51bWVyYWJsZSkgewogICAgICAgICAgdmFyIF9tZXRhID0gZGVzY3JpcHRvci5fbWV0YSB8fCBlbXB0eTsKCiAgICAgICAgICBjYWxsYmFjay5jYWxsKGJpbmRpbmcsIG5hbWUsIF9tZXRhKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfTsKCiAgICBDb3JlT2JqZWN0LnByb3RvID0gZnVuY3Rpb24gcHJvdG8oKSB7CiAgICAgIHZhciBwID0gdGhpcy5wcm90b3R5cGU7CgogICAgICBpZiAoIXdhc0FwcGxpZWQuaGFzKHApKSB7CiAgICAgICAgd2FzQXBwbGllZC5hZGQocCk7CiAgICAgICAgdmFyIHBhcmVudCA9IHRoaXMuc3VwZXJjbGFzczsKCiAgICAgICAgaWYgKHBhcmVudCkgewogICAgICAgICAgcGFyZW50LnByb3RvKCk7CiAgICAgICAgfSAvLyBJZiB0aGUgcHJvdG90eXBlIG1peGluIGV4aXN0cywgYXBwbHkgaXQuIEluIHRoZSBjYXNlIG9mIG5hdGl2ZSBjbGFzc2VzLAogICAgICAgIC8vIGl0IHdpbGwgbm90IGV4aXN0ICh1bmxlc3MgdGhlIGNsYXNzIGhhcyBiZWVuIHJlb3BlbmVkKS4KCgogICAgICAgIGlmIChwcm90b3R5cGVNaXhpbk1hcC5oYXModGhpcykpIHsKICAgICAgICAgIHRoaXMuUHJvdG90eXBlTWl4aW4uYXBwbHkocCk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gcDsKICAgIH07CgogICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShDb3JlT2JqZWN0LCBbewogICAgICBrZXk6ICJpc0Rlc3Ryb3llZCIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiAoMCwgX21ldGEyLnBlZWtNZXRhKSh0aGlzKS5pc1NvdXJjZURlc3Ryb3llZCgpOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3Qgc2V0IGAiICsgdGhpcyArICIuaXNEZXN0cm95ZWRgIGRpcmVjdGx5LCBwbGVhc2UgdXNlIGAuZGVzdHJveSgpYC4iLCBmYWxzZSkpOwogICAgICB9CiAgICAgIC8qKgogICAgICAgIERlc3RydWN0aW9uIHNjaGVkdWxlZCBmbGFnLiBUaGUgYGRlc3Ryb3koKWAgbWV0aG9kIGhhcyBiZWVuIGNhbGxlZC4KICAgICAgICAgVGhlIG9iamVjdCBzdGF5cyBpbnRhY3QgdW50aWwgdGhlIGVuZCBvZiB0aGUgcnVuIGxvb3AgYXQgd2hpY2ggcG9pbnQKICAgICAgICB0aGUgYGlzRGVzdHJveWVkYCBmbGFnIGlzIHNldC4KICAgICAgICAgQHByb3BlcnR5IGlzRGVzdHJveWluZwogICAgICAgIEBkZWZhdWx0IGZhbHNlCiAgICAgICAgQHB1YmxpYwogICAgICAqLwoKICAgIH0sIHsKICAgICAga2V5OiAiaXNEZXN0cm95aW5nIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuICgwLCBfbWV0YTIucGVla01ldGEpKHRoaXMpLmlzU291cmNlRGVzdHJveWluZygpOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3Qgc2V0IGAiICsgdGhpcyArICIuaXNEZXN0cm95aW5nYCBkaXJlY3RseSwgcGxlYXNlIHVzZSBgLmRlc3Ryb3koKWAuIiwgZmFsc2UpKTsKICAgICAgfQogICAgfV0sIFt7CiAgICAgIGtleTogIlByb3RvdHlwZU1peGluIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIHByb3RvdHlwZU1peGluID0gcHJvdG90eXBlTWl4aW5NYXAuZ2V0KHRoaXMpOwoKICAgICAgICBpZiAocHJvdG90eXBlTWl4aW4gPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcHJvdG90eXBlTWl4aW4gPSBfbWV0YWwuTWl4aW4uY3JlYXRlKCk7CiAgICAgICAgICBwcm90b3R5cGVNaXhpbi5vd25lckNvbnN0cnVjdG9yID0gdGhpczsKICAgICAgICAgIHByb3RvdHlwZU1peGluTWFwLnNldCh0aGlzLCBwcm90b3R5cGVNaXhpbik7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcHJvdG90eXBlTWl4aW47CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAic3VwZXJjbGFzcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBjID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHRoaXMpOwogICAgICAgIHJldHVybiBjICE9PSBGdW5jdGlvbi5wcm90b3R5cGUgPyBjIDogdW5kZWZpbmVkOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gQ29yZU9iamVjdDsKICB9KCk7CgogIENvcmVPYmplY3QudG9TdHJpbmcgPSBfbWV0YWwuY2xhc3NUb1N0cmluZzsKICAoMCwgX3V0aWxzLnNldE5hbWUpKENvcmVPYmplY3QsICdFbWJlci5Db3JlT2JqZWN0Jyk7CiAgQ29yZU9iamVjdC5pc0NsYXNzID0gdHJ1ZTsKICBDb3JlT2JqZWN0LmlzTWV0aG9kID0gZmFsc2U7CgogIGZ1bmN0aW9uIGZsYXR0ZW5Qcm9wcygpIHsKICAgIHZhciBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzID0gdGhpcy5jb25jYXRlbmF0ZWRQcm9wZXJ0aWVzLAogICAgICAgIG1lcmdlZFByb3BlcnRpZXMgPSB0aGlzLm1lcmdlZFByb3BlcnRpZXM7CiAgICB2YXIgaGFzQ29uY2F0ZW5hdGVkUHJvcHMgPSBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzICE9PSB1bmRlZmluZWQgJiYgY29uY2F0ZW5hdGVkUHJvcGVydGllcy5sZW5ndGggPiAwOwogICAgdmFyIGhhc01lcmdlZFByb3BzID0gbWVyZ2VkUHJvcGVydGllcyAhPT0gdW5kZWZpbmVkICYmIG1lcmdlZFByb3BlcnRpZXMubGVuZ3RoID4gMDsKICAgIHZhciBpbml0UHJvcGVydGllcyA9IHt9OwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBwcm9wZXJ0aWVzID0gaSA8IDAgfHwgYXJndW1lbnRzLmxlbmd0aCA8PSBpID8gdW5kZWZpbmVkIDogYXJndW1lbnRzW2ldOwogICAgICAoZmFsc2UgJiYgISghKHByb3BlcnRpZXMgaW5zdGFuY2VvZiBfbWV0YWwuTWl4aW4pKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ0VtYmVyT2JqZWN0LmNyZWF0ZSBubyBsb25nZXIgc3VwcG9ydHMgbWl4aW5nIGluIG90aGVyICcgKyAnZGVmaW5pdGlvbnMsIHVzZSAuZXh0ZW5kICYgLmNyZWF0ZSBzZXBhcmF0ZWx5IGluc3RlYWQuJywgIShwcm9wZXJ0aWVzIGluc3RhbmNlb2YgX21ldGFsLk1peGluKSkpOwogICAgICB2YXIga2V5TmFtZXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKTsKCiAgICAgIGZvciAodmFyIGogPSAwLCBrID0ga2V5TmFtZXMubGVuZ3RoOyBqIDwgazsgaisrKSB7CiAgICAgICAgdmFyIGtleU5hbWUgPSBrZXlOYW1lc1tqXTsKICAgICAgICB2YXIgdmFsdWUgPSBwcm9wZXJ0aWVzW2tleU5hbWVdOwoKICAgICAgICBpZiAoaGFzQ29uY2F0ZW5hdGVkUHJvcHMgJiYgY29uY2F0ZW5hdGVkUHJvcGVydGllcy5pbmRleE9mKGtleU5hbWUpID4gLTEpIHsKICAgICAgICAgIHZhciBiYXNlVmFsdWUgPSBpbml0UHJvcGVydGllc1trZXlOYW1lXTsKCiAgICAgICAgICBpZiAoYmFzZVZhbHVlKSB7CiAgICAgICAgICAgIHZhbHVlID0gKDAsIF91dGlscy5tYWtlQXJyYXkpKGJhc2VWYWx1ZSkuY29uY2F0KHZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHZhbHVlID0gKDAsIF91dGlscy5tYWtlQXJyYXkpKHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmIChoYXNNZXJnZWRQcm9wcyAmJiBtZXJnZWRQcm9wZXJ0aWVzLmluZGV4T2Yoa2V5TmFtZSkgPiAtMSkgewogICAgICAgICAgdmFyIF9iYXNlVmFsdWUgPSBpbml0UHJvcGVydGllc1trZXlOYW1lXTsKICAgICAgICAgIHZhbHVlID0gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgX2Jhc2VWYWx1ZSwgdmFsdWUpOwogICAgICAgIH0KCiAgICAgICAgaW5pdFByb3BlcnRpZXNba2V5TmFtZV0gPSB2YWx1ZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBpbml0UHJvcGVydGllczsKICB9CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICAvKioKICAgICAgUHJvdmlkZXMgbG9va3VwLXRpbWUgdHlwZSB2YWxpZGF0aW9uIGZvciBpbmplY3RlZCBwcm9wZXJ0aWVzLgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBfb25Mb29rdXAKICAgICovCiAgICBDb3JlT2JqZWN0Ll9vbkxvb2t1cCA9IGZ1bmN0aW9uIGluamVjdGVkUHJvcGVydHlBc3NlcnRpb24oZGVidWdDb250YWluZXJLZXkpIHsKICAgICAgdmFyIF9kZWJ1Z0NvbnRhaW5lcktleSRzcCA9IGRlYnVnQ29udGFpbmVyS2V5LnNwbGl0KCc6JyksCiAgICAgICAgICB0eXBlID0gX2RlYnVnQ29udGFpbmVyS2V5JHNwWzBdOwoKICAgICAgdmFyIHByb3RvID0gdGhpcy5wcm90bygpOwoKICAgICAgZm9yICh2YXIga2V5IGluIHByb3RvKSB7CiAgICAgICAgdmFyIGRlc2MgPSAoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JQcm9wZXJ0eSkocHJvdG8sIGtleSk7CgogICAgICAgIGlmIChkZXNjICYmIF9tZXRhbC5ERUJVR19JTkpFQ1RJT05fRlVOQ1RJT05TLmhhcyhkZXNjLl9nZXR0ZXIpKSB7CiAgICAgICAgICAoZmFsc2UgJiYgISh0eXBlID09PSAnY29udHJvbGxlcicgfHwgX21ldGFsLkRFQlVHX0lOSkVDVElPTl9GVU5DVElPTlMuZ2V0KGRlc2MuX2dldHRlcikudHlwZSAhPT0gJ2NvbnRyb2xsZXInKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkRlZmluaW5nIGAiICsga2V5ICsgImAgYXMgYW4gaW5qZWN0ZWQgY29udHJvbGxlciBwcm9wZXJ0eSBvbiBhIG5vbi1jb250cm9sbGVyIChgIiArIGRlYnVnQ29udGFpbmVyS2V5ICsgImApIGlzIG5vdCBhbGxvd2VkLiIsIHR5cGUgPT09ICdjb250cm9sbGVyJyB8fCBfbWV0YWwuREVCVUdfSU5KRUNUSU9OX0ZVTkNUSU9OUy5nZXQoZGVzYy5fZ2V0dGVyKS50eXBlICE9PSAnY29udHJvbGxlcicpKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CiAgICAvKioKICAgICAgUmV0dXJucyBhIGhhc2ggb2YgcHJvcGVydHkgbmFtZXMgYW5kIGNvbnRhaW5lciBuYW1lcyB0aGF0IGluamVjdGVkCiAgICAgIHByb3BlcnRpZXMgd2lsbCBsb29rdXAgb24gdGhlIGNvbnRhaW5lciBsYXppbHkuCiAgICAgICBAbWV0aG9kIF9sYXp5SW5qZWN0aW9ucwogICAgICBAcmV0dXJuIHtPYmplY3R9IEhhc2ggb2YgYWxsIGxhenkgaW5qZWN0ZWQgcHJvcGVydHkga2V5cyB0byBjb250YWluZXIgbmFtZXMKICAgICAgQHByaXZhdGUKICAgICovCgoKICAgIENvcmVPYmplY3QuX2xhenlJbmplY3Rpb25zID0gZnVuY3Rpb24gKCkgewogICAgICB2YXIgaW5qZWN0aW9ucyA9IHt9OwogICAgICB2YXIgcHJvdG8gPSB0aGlzLnByb3RvKCk7CiAgICAgIHZhciBrZXk7CiAgICAgIHZhciBkZXNjOwoKICAgICAgZm9yIChrZXkgaW4gcHJvdG8pIHsKICAgICAgICBkZXNjID0gKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKHByb3RvLCBrZXkpOwoKICAgICAgICBpZiAoZGVzYyAmJiBfbWV0YWwuREVCVUdfSU5KRUNUSU9OX0ZVTkNUSU9OUy5oYXMoZGVzYy5fZ2V0dGVyKSkgewogICAgICAgICAgdmFyIF9ERUJVR19JTkpFQ1RJT05fRlVOQyA9IF9tZXRhbC5ERUJVR19JTkpFQ1RJT05fRlVOQ1RJT05TLmdldChkZXNjLl9nZXR0ZXIpLAogICAgICAgICAgICAgIG5hbWVzcGFjZSA9IF9ERUJVR19JTkpFQ1RJT05fRlVOQy5uYW1lc3BhY2UsCiAgICAgICAgICAgICAgc291cmNlID0gX0RFQlVHX0lOSkVDVElPTl9GVU5DLnNvdXJjZSwKICAgICAgICAgICAgICB0eXBlID0gX0RFQlVHX0lOSkVDVElPTl9GVU5DLnR5cGUsCiAgICAgICAgICAgICAgbmFtZSA9IF9ERUJVR19JTkpFQ1RJT05fRlVOQy5uYW1lOwoKICAgICAgICAgIGluamVjdGlvbnNba2V5XSA9IHsKICAgICAgICAgICAgbmFtZXNwYWNlOiBuYW1lc3BhY2UsCiAgICAgICAgICAgIHNvdXJjZTogc291cmNlLAogICAgICAgICAgICBzcGVjaWZpZXI6IHR5cGUgKyAiOiIgKyAobmFtZSB8fCBrZXkpCiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGluamVjdGlvbnM7CiAgICB9OwogIH0KCiAgdmFyIF9kZWZhdWx0ID0gQ29yZU9iamVjdDsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL3N5c3RlbS9uYW1lc3BhY2UiLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL29iamVjdCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfbWV0YWwsIF91dGlscywgX29iamVjdCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCiAgLy8gUHJlbG9hZGVkIGludG8gbmFtZXNwYWNlcwoKICAvKioKICAgIEEgTmFtZXNwYWNlIGlzIGFuIG9iamVjdCB1c3VhbGx5IHVzZWQgdG8gY29udGFpbiBvdGhlciBvYmplY3RzIG9yIG1ldGhvZHMKICAgIHN1Y2ggYXMgYW4gYXBwbGljYXRpb24gb3IgZnJhbWV3b3JrLiBDcmVhdGUgYSBuYW1lc3BhY2UgYW55dGltZSB5b3Ugd2FudAogICAgdG8gZGVmaW5lIG9uZSBvZiB0aGVzZSBuZXcgY29udGFpbmVycy4KICAKICAgICMgRXhhbXBsZSBVc2FnZQogIAogICAgYGBgamF2YXNjcmlwdAogICAgTXlGcmFtZXdvcmsgPSBFbWJlci5OYW1lc3BhY2UuY3JlYXRlKHsKICAgICAgVkVSU0lPTjogJzEuMC4wJwogICAgfSk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBOYW1lc3BhY2UKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEBleHRlbmRzIEVtYmVyT2JqZWN0CiAgICBAcHVibGljCiAgKi8KICB2YXIgTmFtZXNwYWNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9FbWJlck9iamVjdCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE5hbWVzcGFjZSwgX0VtYmVyT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBOYW1lc3BhY2UoKSB7CiAgICAgIHJldHVybiBfRW1iZXJPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBOYW1lc3BhY2UucHJvdG90eXBlOwoKICAgIF9wcm90by5pbml0ID0gZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgKDAsIF9tZXRhbC5hZGROYW1lc3BhY2UpKHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG8udG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgdmFyIG5hbWUgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ25hbWUnKSB8fCAoMCwgX21ldGFsLmdldCkodGhpcywgJ21vZHVsZVByZWZpeCcpOwoKICAgICAgaWYgKG5hbWUpIHsKICAgICAgICByZXR1cm4gbmFtZTsKICAgICAgfQoKICAgICAgKDAsIF9tZXRhbC5maW5kTmFtZXNwYWNlcykoKTsKICAgICAgbmFtZSA9ICgwLCBfdXRpbHMuZ2V0TmFtZSkodGhpcyk7CgogICAgICBpZiAobmFtZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgbmFtZSA9ICgwLCBfdXRpbHMuZ3VpZEZvcikodGhpcyk7CiAgICAgICAgKDAsIF91dGlscy5zZXROYW1lKSh0aGlzLCBuYW1lKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5hbWU7CiAgICB9OwoKICAgIF9wcm90by5uYW1lQ2xhc3NlcyA9IGZ1bmN0aW9uIG5hbWVDbGFzc2VzKCkgewogICAgICAoMCwgX21ldGFsLnByb2Nlc3NOYW1lc3BhY2UpKHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG8uZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgICgwLCBfbWV0YWwucmVtb3ZlTmFtZXNwYWNlKSh0aGlzKTsKCiAgICAgIF9FbWJlck9iamVjdC5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpOwogICAgfTsKCiAgICByZXR1cm4gTmFtZXNwYWNlOwogIH0oX29iamVjdC5kZWZhdWx0KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IE5hbWVzcGFjZTsKICBOYW1lc3BhY2UucHJvdG90eXBlLmlzTmFtZXNwYWNlID0gdHJ1ZTsKICBOYW1lc3BhY2UuTkFNRVNQQUNFUyA9IF9tZXRhbC5OQU1FU1BBQ0VTOwogIE5hbWVzcGFjZS5OQU1FU1BBQ0VTX0JZX0lEID0gX21ldGFsLk5BTUVTUEFDRVNfQllfSUQ7CiAgTmFtZXNwYWNlLnByb2Nlc3NBbGwgPSBfbWV0YWwucHJvY2Vzc0FsbE5hbWVzcGFjZXM7CiAgTmFtZXNwYWNlLmJ5TmFtZSA9IF9tZXRhbC5maW5kTmFtZXNwYWNlOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vb2JqZWN0IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL2NvbnRhaW5lciIsICJAZW1iZXIvLWludGVybmFscy9vd25lciIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vY29yZV9vYmplY3QiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvbWl4aW5zL29ic2VydmFibGUiLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2VtYmVyQmFiZWwsIF9jb250YWluZXIsIF9vd25lciwgX3V0aWxzLCBfbWV0YWwsIF9jb3JlX29iamVjdCwgX29ic2VydmFibGUsIF9kZWJ1ZykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuRnJhbWV3b3JrT2JqZWN0ID0gX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KICB2YXIgaW5zdGFuY2VPd25lciA9IG5ldyBXZWFrTWFwKCk7CiAgLyoqCiAgICBgRW1iZXJPYmplY3RgIGlzIHRoZSBtYWluIGJhc2UgY2xhc3MgZm9yIGFsbCBFbWJlciBvYmplY3RzLiBJdCBpcyBhIHN1YmNsYXNzCiAgICBvZiBgQ29yZU9iamVjdGAgd2l0aCB0aGUgYE9ic2VydmFibGVgIG1peGluIGFwcGxpZWQuIEZvciBkZXRhaWxzLAogICAgc2VlIHRoZSBkb2N1bWVudGF0aW9uIGZvciBlYWNoIG9mIHRoZXNlLgogIAogICAgQGNsYXNzIEVtYmVyT2JqZWN0CiAgICBAZXh0ZW5kcyBDb3JlT2JqZWN0CiAgICBAdXNlcyBPYnNlcnZhYmxlCiAgICBAcHVibGljCiAgKi8KCiAgdmFyIEVtYmVyT2JqZWN0ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Db3JlT2JqZWN0KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRW1iZXJPYmplY3QsIF9Db3JlT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBFbWJlck9iamVjdCgpIHsKICAgICAgcmV0dXJuIF9Db3JlT2JqZWN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKEVtYmVyT2JqZWN0LCBbewogICAgICBrZXk6ICJfZGVidWdDb250YWluZXJLZXkiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICB2YXIgZmFjdG9yeSA9IF9jb250YWluZXIuRkFDVE9SWV9GT1IuZ2V0KHRoaXMpOwoKICAgICAgICByZXR1cm4gZmFjdG9yeSAhPT0gdW5kZWZpbmVkICYmIGZhY3RvcnkuZnVsbE5hbWU7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiBfb3duZXIuT1dORVIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBvd25lciA9IGluc3RhbmNlT3duZXIuZ2V0KHRoaXMpOwoKICAgICAgICBpZiAob3duZXIgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcmV0dXJuIG93bmVyOwogICAgICAgIH0KCiAgICAgICAgdmFyIGZhY3RvcnkgPSBfY29udGFpbmVyLkZBQ1RPUllfRk9SLmdldCh0aGlzKTsKCiAgICAgICAgcmV0dXJuIGZhY3RvcnkgIT09IHVuZGVmaW5lZCAmJiBmYWN0b3J5Lm93bmVyOwogICAgICB9IC8vIHdlIG5lZWQgYSBzZXR0ZXIgaGVyZSBsYXJnZWx5IHRvIHN1cHBvcnQKICAgICAgLy8gZm9sa3MgY2FsbGluZyBgb3duZXIub3duZXJJbmplY3Rpb24oKWAgQVBJCiAgICAgICwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQodmFsdWUpIHsKICAgICAgICBpbnN0YW5jZU93bmVyLnNldCh0aGlzLCB2YWx1ZSk7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBFbWJlck9iamVjdDsKICB9KF9jb3JlX29iamVjdC5kZWZhdWx0KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IEVtYmVyT2JqZWN0OwogICgwLCBfdXRpbHMuc2V0TmFtZSkoRW1iZXJPYmplY3QsICdFbWJlci5PYmplY3QnKTsKCiAgX29ic2VydmFibGUuZGVmYXVsdC5hcHBseShFbWJlck9iamVjdC5wcm90b3R5cGUpOwoKICB2YXIgRnJhbWV3b3JrT2JqZWN0OwogIF9leHBvcnRzLkZyYW1ld29ya09iamVjdCA9IEZyYW1ld29ya09iamVjdDsKCiAgaWYgKHRydWUKICAvKiBFTUJFUl9GUkFNRVdPUktfT0JKRUNUX09XTkVSX0FSR1VNRU5UICovCiAgKSB7CiAgICAgIF9leHBvcnRzLkZyYW1ld29ya09iamVjdCA9IEZyYW1ld29ya09iamVjdCA9CiAgICAgIC8qI19fUFVSRV9fKi8KICAgICAgZnVuY3Rpb24gKF9Db3JlT2JqZWN0MikgewogICAgICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShGcmFtZXdvcmtPYmplY3QsIF9Db3JlT2JqZWN0Mik7CiAgICAgICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShGcmFtZXdvcmtPYmplY3QsIFt7CiAgICAgICAgICBrZXk6ICJfZGVidWdDb250YWluZXJLZXkiLAogICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgICAgIHZhciBmYWN0b3J5ID0gX2NvbnRhaW5lci5GQUNUT1JZX0ZPUi5nZXQodGhpcyk7CgogICAgICAgICAgICByZXR1cm4gZmFjdG9yeSAhPT0gdW5kZWZpbmVkICYmIGZhY3RvcnkuZnVsbE5hbWU7CiAgICAgICAgICB9CiAgICAgICAgfV0pOwoKICAgICAgICBmdW5jdGlvbiBGcmFtZXdvcmtPYmplY3Qob3duZXIpIHsKICAgICAgICAgIHZhciBfdGhpczsKCiAgICAgICAgICBfdGhpcyA9IF9Db3JlT2JqZWN0Mi5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgICAgICAoMCwgX293bmVyLnNldE93bmVyKSgoMCwgX2VtYmVyQmFiZWwuYXNzZXJ0VGhpc0luaXRpYWxpemVkKShfdGhpcyksIG93bmVyKTsKICAgICAgICAgIHJldHVybiBfdGhpczsKICAgICAgICB9CgogICAgICAgIHJldHVybiBGcmFtZXdvcmtPYmplY3Q7CiAgICAgIH0oX2NvcmVfb2JqZWN0LmRlZmF1bHQpOwoKICAgICAgX29ic2VydmFibGUuZGVmYXVsdC5hcHBseShGcmFtZXdvcmtPYmplY3QucHJvdG90eXBlKTsKICAgIH0gZWxzZSB7CiAgICBfZXhwb3J0cy5GcmFtZXdvcmtPYmplY3QgPSBGcmFtZXdvcmtPYmplY3QgPQogICAgLyojX19QVVJFX18qLwogICAgZnVuY3Rpb24gKF9FbWJlck9iamVjdCkgewogICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRnJhbWV3b3JrT2JqZWN0LCBfRW1iZXJPYmplY3QpOwoKICAgICAgZnVuY3Rpb24gRnJhbWV3b3JrT2JqZWN0KCkgewogICAgICAgIHJldHVybiBfRW1iZXJPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICB9CgogICAgICByZXR1cm4gRnJhbWV3b3JrT2JqZWN0OwogICAgfShFbWJlck9iamVjdCk7CiAgfQoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgdmFyIElOSVRfV0FTX0NBTExFRCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnSU5JVF9XQVNfQ0FMTEVEJyk7CiAgICB2YXIgQVNTRVJUX0lOSVRfV0FTX0NBTExFRCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnQVNTRVJUX0lOSVRfV0FTX0NBTExFRCcpOwoKICAgIF9leHBvcnRzLkZyYW1ld29ya09iamVjdCA9IEZyYW1ld29ya09iamVjdCA9CiAgICAvKiNfX1BVUkVfXyovCiAgICBmdW5jdGlvbiAoX0VtYmVyT2JqZWN0MikgewogICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRGVidWdGcmFtZXdvcmtPYmplY3QsIF9FbWJlck9iamVjdDIpOwoKICAgICAgZnVuY3Rpb24gRGVidWdGcmFtZXdvcmtPYmplY3QoKSB7CiAgICAgICAgcmV0dXJuIF9FbWJlck9iamVjdDIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICB9CgogICAgICB2YXIgX3Byb3RvID0gRGVidWdGcmFtZXdvcmtPYmplY3QucHJvdG90eXBlOwoKICAgICAgX3Byb3RvLmluaXQgPSBmdW5jdGlvbiBpbml0KCkgewogICAgICAgIF9FbWJlck9iamVjdDIucHJvdG90eXBlLmluaXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgICAgdGhpc1tJTklUX1dBU19DQUxMRURdID0gdHJ1ZTsKICAgICAgfTsKCiAgICAgIF9wcm90b1tBU1NFUlRfSU5JVF9XQVNfQ0FMTEVEXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAoZmFsc2UgJiYgISh0aGlzW0lOSVRfV0FTX0NBTExFRF0pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IG11c3QgY2FsbCBgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTtgIHdoZW4gb3ZlcnJpZGluZyBgaW5pdGAgb24gYSBmcmFtZXdvcmsgb2JqZWN0LiBQbGVhc2UgdXBkYXRlICIgKyB0aGlzICsgIiB0byBjYWxsIGB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpO2AgZnJvbSBgaW5pdGAuIiwgdGhpc1tJTklUX1dBU19DQUxMRURdKSk7CiAgICAgIH07CgogICAgICByZXR1cm4gRGVidWdGcmFtZXdvcmtPYmplY3Q7CiAgICB9KEVtYmVyT2JqZWN0KTsKCiAgICAoMCwgX21ldGFsLmFkZExpc3RlbmVyKShGcmFtZXdvcmtPYmplY3QucHJvdG90eXBlLCAnaW5pdCcsIG51bGwsIEFTU0VSVF9JTklUX1dBU19DQUxMRUQpOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZS9saWIvc3lzdGVtL29iamVjdF9wcm94eSIsIFsiZXhwb3J0cyIsICJlbWJlci1iYWJlbCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi9zeXN0ZW0vb2JqZWN0IiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL21peGlucy8tcHJveHkiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX29iamVjdCwgX3Byb3h5KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgIGBPYmplY3RQcm94eWAgZm9yd2FyZHMgYWxsIHByb3BlcnRpZXMgbm90IGRlZmluZWQgYnkgdGhlIHByb3h5IGl0c2VsZgogICAgdG8gYSBwcm94aWVkIGBjb250ZW50YCBvYmplY3QuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgT2JqZWN0UHJveHkgZnJvbSAnQGVtYmVyL29iamVjdC9wcm94eSc7CiAgCiAgICBvYmplY3QgPSBFbWJlck9iamVjdC5jcmVhdGUoewogICAgICBuYW1lOiAnRm9vJwogICAgfSk7CiAgCiAgICBwcm94eSA9IE9iamVjdFByb3h5LmNyZWF0ZSh7CiAgICAgIGNvbnRlbnQ6IG9iamVjdAogICAgfSk7CiAgCiAgICAvLyBBY2Nlc3MgYW5kIGNoYW5nZSBleGlzdGluZyBwcm9wZXJ0aWVzCiAgICBwcm94eS5nZXQoJ25hbWUnKSAgICAgICAgICAvLyAnRm9vJwogICAgcHJveHkuc2V0KCduYW1lJywgJ0JhcicpOwogICAgb2JqZWN0LmdldCgnbmFtZScpICAgICAgICAgLy8gJ0JhcicKICAKICAgIC8vIENyZWF0ZSBuZXcgJ2Rlc2NyaXB0aW9uJyBwcm9wZXJ0eSBvbiBgb2JqZWN0YAogICAgcHJveHkuc2V0KCdkZXNjcmlwdGlvbicsICdGb28gaXMgYSB3aGl6Ym9vIGJheicpOwogICAgb2JqZWN0LmdldCgnZGVzY3JpcHRpb24nKSAgLy8gJ0ZvbyBpcyBhIHdoaXpib28gYmF6JwogICAgYGBgCiAgCiAgICBXaGlsZSBgY29udGVudGAgaXMgdW5zZXQsIHNldHRpbmcgYSBwcm9wZXJ0eSB0byBiZSBkZWxlZ2F0ZWQgd2lsbCB0aHJvdyBhbgogICAgRXJyb3IuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgT2JqZWN0UHJveHkgZnJvbSAnQGVtYmVyL29iamVjdC9wcm94eSc7CiAgCiAgICBwcm94eSA9IE9iamVjdFByb3h5LmNyZWF0ZSh7CiAgICAgIGNvbnRlbnQ6IG51bGwsCiAgICAgIGZsYWc6IG51bGwKICAgIH0pOwogICAgcHJveHkuc2V0KCdmbGFnJywgdHJ1ZSk7CiAgICBwcm94eS5nZXQoJ2ZsYWcnKTsgICAgICAgICAvLyB0cnVlCiAgICBwcm94eS5nZXQoJ2ZvbycpOyAgICAgICAgICAvLyB1bmRlZmluZWQKICAgIHByb3h5LnNldCgnZm9vJywgJ2RhdGEnKTsgIC8vIHRocm93cyBFcnJvcgogICAgYGBgCiAgCiAgICBEZWxlZ2F0ZWQgcHJvcGVydGllcyBjYW4gYmUgYm91bmQgdG8gYW5kIHdpbGwgY2hhbmdlIHdoZW4gY29udGVudCBpcyB1cGRhdGVkLgogIAogICAgQ29tcHV0ZWQgcHJvcGVydGllcyBvbiB0aGUgcHJveHkgaXRzZWxmIGNhbiBkZXBlbmQgb24gZGVsZWdhdGVkIHByb3BlcnRpZXMuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IE9iamVjdFByb3h5IGZyb20gJ0BlbWJlci9vYmplY3QvcHJveHknOwogIAogICAgUHJveHlXaXRoQ29tcHV0ZWRQcm9wZXJ0eSA9IE9iamVjdFByb3h5LmV4dGVuZCh7CiAgICAgIGZ1bGxOYW1lOiBjb21wdXRlZCgnZmlyc3ROYW1lJywgJ2xhc3ROYW1lJywgZnVuY3Rpb24oKSB7CiAgICAgICAgdmFyIGZpcnN0TmFtZSA9IHRoaXMuZ2V0KCdmaXJzdE5hbWUnKSwKICAgICAgICAgICAgbGFzdE5hbWUgPSB0aGlzLmdldCgnbGFzdE5hbWUnKTsKICAgICAgICBpZiAoZmlyc3ROYW1lICYmIGxhc3ROYW1lKSB7CiAgICAgICAgICByZXR1cm4gZmlyc3ROYW1lICsgJyAnICsgbGFzdE5hbWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmaXJzdE5hbWUgfHwgbGFzdE5hbWU7CiAgICAgIH0pCiAgICB9KTsKICAKICAgIHByb3h5ID0gUHJveHlXaXRoQ29tcHV0ZWRQcm9wZXJ0eS5jcmVhdGUoKTsKICAKICAgIHByb3h5LmdldCgnZnVsbE5hbWUnKTsgIC8vIHVuZGVmaW5lZAogICAgcHJveHkuc2V0KCdjb250ZW50JywgewogICAgICBmaXJzdE5hbWU6ICdUb20nLCBsYXN0TmFtZTogJ0RhbGUnCiAgICB9KTsgLy8gdHJpZ2dlcnMgcHJvcGVydHkgY2hhbmdlIGZvciBmdWxsTmFtZSBvbiBwcm94eQogIAogICAgcHJveHkuZ2V0KCdmdWxsTmFtZScpOyAgLy8gJ1RvbSBEYWxlJwogICAgYGBgCiAgCiAgICBAY2xhc3MgT2JqZWN0UHJveHkKICAgIEBleHRlbmRzIEVtYmVyT2JqZWN0CiAgICBAdXNlcyBFbWJlci5Qcm94eU1peGluCiAgICBAcHVibGljCiAgKi8KICB2YXIgT2JqZWN0UHJveHkgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0ZyYW1ld29ya09iamVjdCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE9iamVjdFByb3h5LCBfRnJhbWV3b3JrT2JqZWN0KTsKCiAgICBmdW5jdGlvbiBPYmplY3RQcm94eSgpIHsKICAgICAgcmV0dXJuIF9GcmFtZXdvcmtPYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHJldHVybiBPYmplY3RQcm94eTsKICB9KF9vYmplY3QuZGVmYXVsdCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBPYmplY3RQcm94eTsKICBPYmplY3RQcm94eS5Qcm90b3R5cGVNaXhpbi5yZW9wZW4oX3Byb3h5LmRlZmF1bHQpOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy9ydW50aW1lL2xpYi90eXBlLW9mIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUvbGliL3N5c3RlbS9jb3JlX29iamVjdCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9jb3JlX29iamVjdCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMudHlwZU9mID0gdHlwZU9mOwogIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KICAvLyBUWVBJTkcgJiBBUlJBWSBNRVNTQUdJTkcKICAvLwogIHZhciBUWVBFX01BUCA9IHsKICAgICdbb2JqZWN0IEJvb2xlYW5dJzogJ2Jvb2xlYW4nLAogICAgJ1tvYmplY3QgTnVtYmVyXSc6ICdudW1iZXInLAogICAgJ1tvYmplY3QgU3RyaW5nXSc6ICdzdHJpbmcnLAogICAgJ1tvYmplY3QgRnVuY3Rpb25dJzogJ2Z1bmN0aW9uJywKICAgICdbb2JqZWN0IEFycmF5XSc6ICdhcnJheScsCiAgICAnW29iamVjdCBEYXRlXSc6ICdkYXRlJywKICAgICdbb2JqZWN0IFJlZ0V4cF0nOiAncmVnZXhwJywKICAgICdbb2JqZWN0IE9iamVjdF0nOiAnb2JqZWN0JywKICAgICdbb2JqZWN0IEZpbGVMaXN0XSc6ICdmaWxlbGlzdCcKICB9OwogIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7CiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL3V0aWxzCiAgKi8KCiAgLyoqCiAgICBSZXR1cm5zIGEgY29uc2lzdGVudCB0eXBlIGZvciB0aGUgcGFzc2VkIG9iamVjdC4KICAKICAgIFVzZSB0aGlzIGluc3RlYWQgb2YgdGhlIGJ1aWx0LWluIGB0eXBlb2ZgIHRvIGdldCB0aGUgdHlwZSBvZiBhbiBpdGVtLgogICAgSXQgd2lsbCByZXR1cm4gdGhlIHNhbWUgcmVzdWx0IGFjcm9zcyBhbGwgYnJvd3NlcnMgYW5kIGluY2x1ZGVzIGEgYml0CiAgICBtb3JlIGRldGFpbC4gSGVyZSBpcyB3aGF0IHdpbGwgYmUgcmV0dXJuZWQ6CiAgCiAgICAgICAgfCBSZXR1cm4gVmFsdWUgIHwgTWVhbmluZyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfC0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18CiAgICAgICAgfCAnc3RyaW5nJyAgICAgIHwgU3RyaW5nIHByaW1pdGl2ZSBvciBTdHJpbmcgb2JqZWN0LiAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnbnVtYmVyJyAgICAgIHwgTnVtYmVyIHByaW1pdGl2ZSBvciBOdW1iZXIgb2JqZWN0LiAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnYm9vbGVhbicgICAgIHwgQm9vbGVhbiBwcmltaXRpdmUgb3IgQm9vbGVhbiBvYmplY3QuICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnbnVsbCcgICAgICAgIHwgTnVsbCB2YWx1ZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAndW5kZWZpbmVkJyAgIHwgVW5kZWZpbmVkIHZhbHVlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnZnVuY3Rpb24nICAgIHwgQSBmdW5jdGlvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnYXJyYXknICAgICAgIHwgQW4gaW5zdGFuY2Ugb2YgQXJyYXkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAncmVnZXhwJyAgICAgIHwgQW4gaW5zdGFuY2Ugb2YgUmVnRXhwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnZGF0ZScgICAgICAgIHwgQW4gaW5zdGFuY2Ugb2YgRGF0ZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnZmlsZWxpc3QnICAgIHwgQW4gaW5zdGFuY2Ugb2YgRmlsZUxpc3QgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnY2xhc3MnICAgICAgIHwgQW4gRW1iZXIgY2xhc3MgKGNyZWF0ZWQgdXNpbmcgRW1iZXJPYmplY3QuZXh0ZW5kKCkpICB8CiAgICAgICAgfCAnaW5zdGFuY2UnICAgIHwgQW4gRW1iZXIgb2JqZWN0IGluc3RhbmNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnZXJyb3InICAgICAgIHwgQW4gaW5zdGFuY2Ugb2YgdGhlIEVycm9yIG9iamVjdCAgICAgICAgICAgICAgICAgICAgICB8CiAgICAgICAgfCAnb2JqZWN0JyAgICAgIHwgQSBKYXZhU2NyaXB0IG9iamVjdCBub3QgaW5oZXJpdGluZyBmcm9tIEVtYmVyT2JqZWN0ICB8CiAgCiAgICBFeGFtcGxlczoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IEEgfSBmcm9tICdAZW1iZXIvYXJyYXknOwogICAgaW1wb3J0IHsgdHlwZU9mIH0gZnJvbSAnQGVtYmVyL3V0aWxzJzsKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIHR5cGVPZigpOyAgICAgICAgICAgICAgICAgICAgICAgLy8gJ3VuZGVmaW5lZCcKICAgIHR5cGVPZihudWxsKTsgICAgICAgICAgICAgICAgICAgLy8gJ251bGwnCiAgICB0eXBlT2YodW5kZWZpbmVkKTsgICAgICAgICAgICAgIC8vICd1bmRlZmluZWQnCiAgICB0eXBlT2YoJ21pY2hhZWwnKTsgICAgICAgICAgICAgIC8vICdzdHJpbmcnCiAgICB0eXBlT2YobmV3IFN0cmluZygnbWljaGFlbCcpKTsgIC8vICdzdHJpbmcnCiAgICB0eXBlT2YoMTAxKTsgICAgICAgICAgICAgICAgICAgIC8vICdudW1iZXInCiAgICB0eXBlT2YobmV3IE51bWJlcigxMDEpKTsgICAgICAgIC8vICdudW1iZXInCiAgICB0eXBlT2YodHJ1ZSk7ICAgICAgICAgICAgICAgICAgIC8vICdib29sZWFuJwogICAgdHlwZU9mKG5ldyBCb29sZWFuKHRydWUpKTsgICAgICAvLyAnYm9vbGVhbicKICAgIHR5cGVPZihBKTsgICAgICAgICAgICAgICAgICAgICAgLy8gJ2Z1bmN0aW9uJwogICAgdHlwZU9mKFsxLCAyLCA5MF0pOyAgICAgICAgICAgICAvLyAnYXJyYXknCiAgICB0eXBlT2YoL2FiYy8pOyAgICAgICAgICAgICAgICAgIC8vICdyZWdleHAnCiAgICB0eXBlT2YobmV3IERhdGUoKSk7ICAgICAgICAgICAgIC8vICdkYXRlJwogICAgdHlwZU9mKGV2ZW50LnRhcmdldC5maWxlcyk7ICAgICAvLyAnZmlsZWxpc3QnCiAgICB0eXBlT2YoRW1iZXJPYmplY3QuZXh0ZW5kKCkpOyAgIC8vICdjbGFzcycKICAgIHR5cGVPZihFbWJlck9iamVjdC5jcmVhdGUoKSk7ICAgLy8gJ2luc3RhbmNlJwogICAgdHlwZU9mKG5ldyBFcnJvcigndGVhbW9jaWwnKSk7ICAvLyAnZXJyb3InCiAgCiAgICAvLyAnbm9ybWFsJyBKYXZhU2NyaXB0IG9iamVjdAogICAgdHlwZU9mKHsgYTogJ2InIH0pOyAgICAgICAgICAgICAvLyAnb2JqZWN0JwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHR5cGVPZgogICAgQGZvciBAZW1iZXIvdXRpbHMKICAgIEBwYXJhbSB7T2JqZWN0fSBpdGVtIHRoZSBpdGVtIHRvIGNoZWNrCiAgICBAcmV0dXJuIHtTdHJpbmd9IHRoZSB0eXBlCiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgKi8KCiAgZnVuY3Rpb24gdHlwZU9mKGl0ZW0pIHsKICAgIGlmIChpdGVtID09PSBudWxsKSB7CiAgICAgIHJldHVybiAnbnVsbCc7CiAgICB9CgogICAgaWYgKGl0ZW0gPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gJ3VuZGVmaW5lZCc7CiAgICB9CgogICAgdmFyIHJldCA9IFRZUEVfTUFQW3RvU3RyaW5nLmNhbGwoaXRlbSldIHx8ICdvYmplY3QnOwoKICAgIGlmIChyZXQgPT09ICdmdW5jdGlvbicpIHsKICAgICAgaWYgKF9jb3JlX29iamVjdC5kZWZhdWx0LmRldGVjdChpdGVtKSkgewogICAgICAgIHJldCA9ICdjbGFzcyc7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAocmV0ID09PSAnb2JqZWN0JykgewogICAgICBpZiAoaXRlbSBpbnN0YW5jZW9mIEVycm9yKSB7CiAgICAgICAgcmV0ID0gJ2Vycm9yJzsKICAgICAgfSBlbHNlIGlmIChpdGVtIGluc3RhbmNlb2YgX2NvcmVfb2JqZWN0LmRlZmF1bHQpIHsKICAgICAgICByZXQgPSAnaW5zdGFuY2UnOwogICAgICB9IGVsc2UgaWYgKGl0ZW0gaW5zdGFuY2VvZiBEYXRlKSB7CiAgICAgICAgcmV0ID0gJ2RhdGUnOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHJldDsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzL2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3BvbHlmaWxscywgX2RlYnVnKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5zeW1ib2wgPSBzeW1ib2w7CiAgX2V4cG9ydHMuaXNJbnRlcm5hbFN5bWJvbCA9IGlzSW50ZXJuYWxTeW1ib2w7CiAgX2V4cG9ydHMuZGljdGlvbmFyeSA9IG1ha2VEaWN0aW9uYXJ5OwogIF9leHBvcnRzLnV1aWQgPSB1dWlkOwogIF9leHBvcnRzLmdlbmVyYXRlR3VpZCA9IGdlbmVyYXRlR3VpZDsKICBfZXhwb3J0cy5ndWlkRm9yID0gZ3VpZEZvcjsKICBfZXhwb3J0cy5pbnRlcm4gPSBpbnRlcm47CiAgX2V4cG9ydHMud3JhcCA9IHdyYXA7CiAgX2V4cG9ydHMuZ2V0T2JzZXJ2ZXJzID0gZ2V0T2JzZXJ2ZXJzOwogIF9leHBvcnRzLmdldExpc3RlbmVycyA9IGdldExpc3RlbmVyczsKICBfZXhwb3J0cy5zZXRPYnNlcnZlcnMgPSBzZXRPYnNlcnZlcnM7CiAgX2V4cG9ydHMuc2V0TGlzdGVuZXJzID0gc2V0TGlzdGVuZXJzOwogIF9leHBvcnRzLmluc3BlY3QgPSBpbnNwZWN0OwogIF9leHBvcnRzLmxvb2t1cERlc2NyaXB0b3IgPSBsb29rdXBEZXNjcmlwdG9yOwogIF9leHBvcnRzLmNhbkludm9rZSA9IGNhbkludm9rZTsKICBfZXhwb3J0cy50cnlJbnZva2UgPSB0cnlJbnZva2U7CiAgX2V4cG9ydHMubWFrZUFycmF5ID0gbWFrZUFycmF5OwogIF9leHBvcnRzLmdldE5hbWUgPSBnZXROYW1lOwogIF9leHBvcnRzLnNldE5hbWUgPSBzZXROYW1lOwogIF9leHBvcnRzLnRvU3RyaW5nID0gdG9TdHJpbmc7CiAgX2V4cG9ydHMuaXNQcm94eSA9IGlzUHJveHk7CiAgX2V4cG9ydHMuc2V0UHJveHkgPSBzZXRQcm94eTsKICBfZXhwb3J0cy5pc0VtYmVyQXJyYXkgPSBpc0VtYmVyQXJyYXk7CiAgX2V4cG9ydHMuc2V0V2l0aE1hbmRhdG9yeVNldHRlciA9IF9leHBvcnRzLnRlYXJkb3duTWFuZGF0b3J5U2V0dGVyID0gX2V4cG9ydHMuc2V0dXBNYW5kYXRvcnlTZXR0ZXIgPSBfZXhwb3J0cy5FTUJFUl9BUlJBWSA9IF9leHBvcnRzLkNhY2hlID0gX2V4cG9ydHMuSEFTX05BVElWRV9QUk9YWSA9IF9leHBvcnRzLkhBU19OQVRJVkVfU1lNQk9MID0gX2V4cG9ydHMuUk9PVCA9IF9leHBvcnRzLmNoZWNrSGFzU3VwZXIgPSBfZXhwb3J0cy5HVUlEX0tFWSA9IF9leHBvcnRzLmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMgPSB2b2lkIDA7CgogIC8qKgogICAgU3Ryb25nbHkgaGludCBydW50aW1lcyB0byBpbnRlcm4gdGhlIHByb3ZpZGVkIHN0cmluZy4KICAKICAgIFdoZW4gZG8gSSBuZWVkIHRvIHVzZSB0aGlzIGZ1bmN0aW9uPwogIAogICAgRm9yIHRoZSBtb3N0IHBhcnQsIG5ldmVyLiBQcmUtbWF0dXJlIG9wdGltaXphdGlvbiBpcyBiYWQsIGFuZCBvZnRlbiB0aGUKICAgIHJ1bnRpbWUgZG9lcyBleGFjdGx5IHdoYXQgeW91IG5lZWQgaXQgdG8sIGFuZCBtb3JlIG9mdGVuIHRoZSB0cmFkZS1vZmYgaXNuJ3QKICAgIHdvcnRoIGl0LgogIAogICAgV2h5PwogIAogICAgUnVudGltZXMgc3RvcmUgc3RyaW5ncyBpbiBhdCBsZWFzdCAyIGRpZmZlcmVudCByZXByZXNlbnRhdGlvbnM6CiAgICBSb3BlcyBhbmQgU3ltYm9scyAoaW50ZXJuZWQgc3RyaW5ncykuIFRoZSBSb3BlIHByb3ZpZGVzIGEgbWVtb3J5IGVmZmljaWVudAogICAgZGF0YS1zdHJ1Y3R1cmUgZm9yIHN0cmluZ3MgY3JlYXRlZCBmcm9tIGNvbmNhdGVuYXRpb24gb3Igc29tZSBvdGhlciBzdHJpbmcKICAgIG1hbmlwdWxhdGlvbiBsaWtlIHNwbGl0dGluZy4KICAKICAgIFVuZm9ydHVuYXRlbHkgY2hlY2tpbmcgZXF1YWxpdHkgb2YgZGlmZmVyZW50IHJvcGVzIGNhbiBiZSBxdWl0ZSBjb3N0bHkgYXMKICAgIHJ1bnRpbWVzIG11c3QgcmVzb3J0IHRvIGNsZXZlciBzdHJpbmcgY29tcGFyaXNvbiBhbGdvcml0aG1zLiBUaGVzZQogICAgYWxnb3JpdGhtcyB0eXBpY2FsbHkgY29zdCBpbiBwcm9wb3J0aW9uIHRvIHRoZSBsZW5ndGggb2YgdGhlIHN0cmluZy4KICAgIEx1Y2tpbHksIHRoaXMgaXMgd2hlcmUgdGhlIFN5bWJvbHMgKGludGVybmVkIHN0cmluZ3MpIHNoaW5lLiBBcyBTeW1ib2xzIGFyZQogICAgdW5pcXVlIGJ5IHRoZWlyIHN0cmluZyBjb250ZW50LCBlcXVhbGl0eSBjaGVja3MgY2FuIGJlIGRvbmUgYnkgcG9pbnRlcgogICAgY29tcGFyaXNvbi4KICAKICAgIEhvdyBkbyBJIGtub3cgaWYgbXkgc3RyaW5nIGlzIGEgcm9wZSBvciBzeW1ib2w/CiAgCiAgICBUeXBpY2FsbHkgKHdhcm5pbmcgZ2VuZXJhbCBzd2VlcGluZyBzdGF0ZW1lbnQsIGJ1dCB0cnV0aHkgaW4gcnVudGltZXMgYXQKICAgIHByZXNlbnQpIHN0YXRpYyBzdHJpbmdzIGNyZWF0ZWQgYXMgcGFydCBvZiB0aGUgSlMgc291cmNlIGFyZSBpbnRlcm5lZC4KICAgIFN0cmluZ3Mgb2Z0ZW4gdXNlZCBmb3IgY29tcGFyaXNvbnMgY2FuIGJlIGludGVybmVkIGF0IHJ1bnRpbWUgaWYgc29tZQogICAgY3JpdGVyaWEgYXJlIG1ldC4gIE9uZSBvZiB0aGVzZSBjcml0ZXJpYSBjYW4gYmUgdGhlIHNpemUgb2YgdGhlIGVudGlyZSByb3BlLgogICAgRm9yIGV4YW1wbGUsIGluIGNocm9tZSAzOCBhIHJvcGUgbG9uZ2VyIHRoZW4gMTIgY2hhcmFjdGVycyB3aWxsIG5vdAogICAgaW50ZXJuLCBub3Igd2lsbCBzZWdtZW50cyBvZiB0aGF0IHJvcGUuCiAgCiAgICBTb21lIG51bWJlcnM6IGh0dHA6Ly9qc3BlcmYuY29tL2V2YWwtdnMta2V5cy84CiAgCiAgICBLbm93biBUcmlja+KEogogIAogICAgQHByaXZhdGUKICAgIEByZXR1cm4ge1N0cmluZ30gaW50ZXJuZWQgdmVyc2lvbiBvZiB0aGUgcHJvdmlkZWQgc3RyaW5nCiAgKi8KICBmdW5jdGlvbiBpbnRlcm4oc3RyKSB7CiAgICB2YXIgb2JqID0ge307CiAgICBvYmpbc3RyXSA9IDE7CgogICAgZm9yICh2YXIga2V5IGluIG9iaikgewogICAgICBpZiAoa2V5ID09PSBzdHIpIHsKICAgICAgICByZXR1cm4ga2V5OwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHN0cjsKICB9CiAgLyoqCiAgICBSZXR1cm5zIHdoZXRoZXIgVHlwZSh2YWx1ZSkgaXMgT2JqZWN0LgogIAogICAgVXNlZnVsIGZvciBjaGVja2luZyB3aGV0aGVyIGEgdmFsdWUgaXMgYSB2YWxpZCBXZWFrTWFwIGtleS4KICAKICAgIFJlZnM6IGh0dHBzOi8vdGMzOS5naXRodWIuaW8vZWNtYTI2Mi8jc2VjLXR5cGVvZi1vcGVyYXRvci1ydW50aW1lLXNlbWFudGljcy1ldmFsdWF0aW9uCiAgICAgICAgICBodHRwczovL3RjMzkuZ2l0aHViLmlvL2VjbWEyNjIvI3NlYy13ZWFrbWFwLnByb3RvdHlwZS5zZXQKICAKICAgIEBwcml2YXRlCiAgICBAZnVuY3Rpb24gaXNPYmplY3QKICAqLwoKCiAgZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHsKICAgIHJldHVybiB2YWx1ZSAhPT0gbnVsbCAmJiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyB8fCB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpOwogIH0KICAvKioKICAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KCiAgLyoqCiAgIFByZXZpb3VzbHkgd2UgdXNlZCBgRW1iZXIuJC51dWlkYCwgaG93ZXZlciBgJC51dWlkYCBoYXMgYmVlbiByZW1vdmVkIGZyb20KICAgalF1ZXJ5IG1hc3Rlci4gV2UnbGwganVzdCBib290c3RyYXAgb3VyIG93biB1dWlkIG5vdy4KICAKICAgQHByaXZhdGUKICAgQHJldHVybiB7TnVtYmVyfSB0aGUgdXVpZAogICAqLwoKCiAgdmFyIF91dWlkID0gMDsKICAvKioKICAgR2VuZXJhdGVzIGEgdW5pdmVyc2FsbHkgdW5pcXVlIGlkZW50aWZpZXIuIFRoaXMgbWV0aG9kCiAgIGlzIHVzZWQgaW50ZXJuYWxseSBieSBFbWJlciBmb3IgYXNzaXN0aW5nIHdpdGgKICAgdGhlIGdlbmVyYXRpb24gb2YgR1VJRCdzIGFuZCBvdGhlciB1bmlxdWUgaWRlbnRpZmllcnMuCiAgCiAgIEBwdWJsaWMKICAgQHJldHVybiB7TnVtYmVyfSBbZGVzY3JpcHRpb25dCiAgICovCgogIGZ1bmN0aW9uIHV1aWQoKSB7CiAgICByZXR1cm4gKytfdXVpZDsKICB9CiAgLyoqCiAgIFByZWZpeCB1c2VkIGZvciBndWlkcyB0aHJvdWdoIG91dCBFbWJlci4KICAgQHByaXZhdGUKICAgQHByb3BlcnR5IEdVSURfUFJFRklYCiAgIEBmb3IgRW1iZXIKICAgQHR5cGUgU3RyaW5nCiAgIEBmaW5hbAogICAqLwoKCiAgdmFyIEdVSURfUFJFRklYID0gJ2VtYmVyJzsgLy8gVXNlZCBmb3IgZ3VpZCBnZW5lcmF0aW9uLi4uCgogIHZhciBPQkpFQ1RfR1VJRFMgPSBuZXcgV2Vha01hcCgpOwogIHZhciBOT05fT0JKRUNUX0dVSURTID0gbmV3IE1hcCgpOwogIC8qKgogICAgQSB1bmlxdWUga2V5IHVzZWQgdG8gYXNzaWduIGd1aWRzIGFuZCBvdGhlciBwcml2YXRlIG1ldGFkYXRhIHRvIG9iamVjdHMuCiAgICBJZiB5b3UgaW5zcGVjdCBhbiBvYmplY3QgaW4geW91ciBicm93c2VyIGRlYnVnZ2VyIHlvdSB3aWxsIG9mdGVuIHNlZSB0aGVzZS4KICAgIFRoZXkgY2FuIGJlIHNhZmVseSBpZ25vcmVkLgogIAogICAgT24gYnJvd3NlcnMgdGhhdCBzdXBwb3J0IGl0LCB0aGVzZSBwcm9wZXJ0aWVzIGFyZSBhZGRlZCB3aXRoIGVudW1lcmF0aW9uCiAgICBkaXNhYmxlZCBzbyB0aGV5IHdvbid0IHNob3cgdXAgd2hlbiB5b3UgaXRlcmF0ZSBvdmVyIHlvdXIgcHJvcGVydGllcy4KICAKICAgIEBwcml2YXRlCiAgICBAcHJvcGVydHkgR1VJRF9LRVkKICAgIEBmb3IgRW1iZXIKICAgIEB0eXBlIFN0cmluZwogICAgQGZpbmFsCiAgKi8KCiAgdmFyIEdVSURfS0VZID0gaW50ZXJuKCJfX2VtYmVyIiArIERhdGUubm93KCkpOwogIC8qKgogICAgR2VuZXJhdGVzIGEgbmV3IGd1aWQsIG9wdGlvbmFsbHkgc2F2aW5nIHRoZSBndWlkIHRvIHRoZSBvYmplY3QgdGhhdCB5b3UKICAgIHBhc3MgaW4uIFlvdSB3aWxsIHJhcmVseSBuZWVkIHRvIHVzZSB0aGlzIG1ldGhvZC4gSW5zdGVhZCB5b3Ugc2hvdWxkCiAgICBjYWxsIGBndWlkRm9yKG9iailgLCB3aGljaCByZXR1cm4gYW4gZXhpc3RpbmcgZ3VpZCBpZiBhdmFpbGFibGUuCiAgCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCBnZW5lcmF0ZUd1aWQKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9pbnRlcm5hbHMKICAgIEBwYXJhbSB7T2JqZWN0fSBbb2JqXSBPYmplY3QgdGhlIGd1aWQgd2lsbCBiZSB1c2VkIGZvci4gSWYgcGFzc2VkIGluLCB0aGUgZ3VpZCB3aWxsCiAgICAgIGJlIHNhdmVkIG9uIHRoZSBvYmplY3QgYW5kIHJldXNlZCB3aGVuZXZlciB5b3UgcGFzcyB0aGUgc2FtZSBvYmplY3QKICAgICAgYWdhaW4uCiAgCiAgICAgIElmIG5vIG9iamVjdCBpcyBwYXNzZWQsIGp1c3QgZ2VuZXJhdGUgYSBuZXcgZ3VpZC4KICAgIEBwYXJhbSB7U3RyaW5nfSBbcHJlZml4XSBQcmVmaXggdG8gcGxhY2UgaW4gZnJvbnQgb2YgdGhlIGd1aWQuIFVzZWZ1bCB3aGVuIHlvdSB3YW50IHRvCiAgICAgIHNlcGFyYXRlIHRoZSBndWlkIGludG8gc2VwYXJhdGUgbmFtZXNwYWNlcy4KICAgIEByZXR1cm4ge1N0cmluZ30gdGhlIGd1aWQKICAqLwoKICBfZXhwb3J0cy5HVUlEX0tFWSA9IEdVSURfS0VZOwoKICBmdW5jdGlvbiBnZW5lcmF0ZUd1aWQob2JqLCBwcmVmaXgpIHsKICAgIGlmIChwcmVmaXggPT09IHZvaWQgMCkgewogICAgICBwcmVmaXggPSBHVUlEX1BSRUZJWDsKICAgIH0KCiAgICB2YXIgZ3VpZCA9IHByZWZpeCArIHV1aWQoKTsKCiAgICBpZiAoaXNPYmplY3Qob2JqKSkgewogICAgICBPQkpFQ1RfR1VJRFMuc2V0KG9iaiwgZ3VpZCk7CiAgICB9CgogICAgcmV0dXJuIGd1aWQ7CiAgfQogIC8qKgogICAgUmV0dXJucyBhIHVuaXF1ZSBpZCBmb3IgdGhlIG9iamVjdC4gSWYgdGhlIG9iamVjdCBkb2VzIG5vdCB5ZXQgaGF2ZSBhIGd1aWQsCiAgICBvbmUgd2lsbCBiZSBhc3NpZ25lZCB0byBpdC4gWW91IGNhbiBjYWxsIHRoaXMgb24gYW55IG9iamVjdCwKICAgIGBFbWJlck9iamVjdGAtYmFzZWQgb3Igbm90LgogIAogICAgWW91IGNhbiBhbHNvIHVzZSB0aGlzIG1ldGhvZCBvbiBET00gRWxlbWVudCBvYmplY3RzLgogIAogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQG1ldGhvZCBndWlkRm9yCiAgICBAZm9yIEBlbWJlci9vYmplY3QvaW50ZXJuYWxzCiAgICBAcGFyYW0ge09iamVjdH0gb2JqIGFueSBvYmplY3QsIHN0cmluZywgbnVtYmVyLCBFbGVtZW50LCBvciBwcmltaXRpdmUKICAgIEByZXR1cm4ge1N0cmluZ30gdGhlIHVuaXF1ZSBndWlkIGZvciB0aGlzIGluc3RhbmNlLgogICovCgoKICBmdW5jdGlvbiBndWlkRm9yKHZhbHVlKSB7CiAgICB2YXIgZ3VpZDsKCiAgICBpZiAoaXNPYmplY3QodmFsdWUpKSB7CiAgICAgIGd1aWQgPSBPQkpFQ1RfR1VJRFMuZ2V0KHZhbHVlKTsKCiAgICAgIGlmIChndWlkID09PSB1bmRlZmluZWQpIHsKICAgICAgICBndWlkID0gR1VJRF9QUkVGSVggKyB1dWlkKCk7CiAgICAgICAgT0JKRUNUX0dVSURTLnNldCh2YWx1ZSwgZ3VpZCk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGd1aWQgPSBOT05fT0JKRUNUX0dVSURTLmdldCh2YWx1ZSk7CgogICAgICBpZiAoZ3VpZCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7CgogICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykgewogICAgICAgICAgZ3VpZCA9ICdzdCcgKyB1dWlkKCk7CiAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJykgewogICAgICAgICAgZ3VpZCA9ICdudScgKyB1dWlkKCk7CiAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnc3ltYm9sJykgewogICAgICAgICAgZ3VpZCA9ICdzeScgKyB1dWlkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGd1aWQgPSAnKCcgKyB2YWx1ZSArICcpJzsKICAgICAgICB9CgogICAgICAgIE5PTl9PQkpFQ1RfR1VJRFMuc2V0KHZhbHVlLCBndWlkKTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBndWlkOwogIH0KCiAgdmFyIEdFTkVSQVRFRF9TWU1CT0xTID0gW107CgogIGZ1bmN0aW9uIGlzSW50ZXJuYWxTeW1ib2wocG9zc2libGVTeW1ib2wpIHsKICAgIHJldHVybiBHRU5FUkFURURfU1lNQk9MUy5pbmRleE9mKHBvc3NpYmxlU3ltYm9sKSAhPT0gLTE7CiAgfQoKICBmdW5jdGlvbiBzeW1ib2woZGVidWdOYW1lKSB7CiAgICAvLyBUT0RPOiBJbnZlc3RpZ2F0ZSB1c2luZyBwbGF0Zm9ybSBzeW1ib2xzLCBidXQgd2UgZG8gbm90CiAgICAvLyB3YW50IHRvIHJlcXVpcmUgbm9uLWVudW1lcmFiaWxpdHkgZm9yIHRoaXMgQVBJLCB3aGljaAogICAgLy8gd291bGQgaW50cm9kdWNlIGEgbGFyZ2UgY29zdC4KICAgIHZhciBpZCA9IEdVSURfS0VZICsgTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogRGF0ZS5ub3coKSk7CiAgICB2YXIgc3ltYm9sID0gaW50ZXJuKCJfXyIgKyBkZWJ1Z05hbWUgKyBpZCArICJfXyIpOwogICAgR0VORVJBVEVEX1NZTUJPTFMucHVzaChzeW1ib2wpOwogICAgcmV0dXJuIHN5bWJvbDsKICB9IC8vIHRoZSBkZWxldGUgaXMgbWVhbnQgdG8gaGludCBhdCBydW50aW1lcyB0aGF0IHRoaXMgb2JqZWN0IHNob3VsZCByZW1haW4gaW4KICAvLyBkaWN0aW9uYXJ5IG1vZGUuIFRoaXMgaXMgY2xlYXJseSBhIHJ1bnRpbWUgc3BlY2lmaWMgaGFjaywgYnV0IGN1cnJlbnRseSBpdAogIC8vIGFwcGVhcnMgd29ydGh3aGlsZSBpbiBzb21lIHVzZWNhc2VzLiBQbGVhc2Ugbm90ZSwgdGhlc2UgZGVsZXRlcyBkbyBpbmNyZWFzZQogIC8vIHRoZSBjb3N0IG9mIGNyZWF0aW9uIGRyYW1hdGljYWxseSBvdmVyIGEgcGxhaW4gT2JqZWN0LmNyZWF0ZS4gQW5kIGFzIHRoaXMKICAvLyBvbmx5IG1ha2VzIHNlbnNlIGZvciBsb25nLWxpdmVkIGRpY3Rpb25hcmllcyB0aGF0IGFyZW4ndCBpbnN0YW50aWF0ZWQgb2Z0ZW4uCgoKICBmdW5jdGlvbiBtYWtlRGljdGlvbmFyeShwYXJlbnQpIHsKICAgIHZhciBkaWN0ID0gT2JqZWN0LmNyZWF0ZShwYXJlbnQpOwogICAgZGljdFsnX2RpY3QnXSA9IG51bGw7CiAgICBkZWxldGUgZGljdFsnX2RpY3QnXTsKICAgIHJldHVybiBkaWN0OwogIH0KCiAgdmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvcnM7CgogIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyAhPT0gdW5kZWZpbmVkKSB7CiAgICBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnM7CiAgfSBlbHNlIHsKICAgIGdldE93blByb3BlcnR5RGVzY3JpcHRvcnMgPSBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKG9iaikgewogICAgICB2YXIgZGVzY3JpcHRvcnMgPSB7fTsKICAgICAgT2JqZWN0LmtleXMob2JqKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICBkZXNjcmlwdG9yc1trZXldID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmosIGtleSk7CiAgICAgIH0pOwogICAgICByZXR1cm4gZGVzY3JpcHRvcnM7CiAgICB9OwogIH0KCiAgdmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvcnMkMSA9IGdldE93blByb3BlcnR5RGVzY3JpcHRvcnM7CiAgX2V4cG9ydHMuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyA9IGdldE93blByb3BlcnR5RGVzY3JpcHRvcnMkMTsKICB2YXIgSEFTX1NVUEVSX1BBVFRFUk4gPSAvXC4oX3N1cGVyfGNhbGxcKHRoaXN8YXBwbHlcKHRoaXMpLzsKICB2YXIgZm5Ub1N0cmluZyA9IEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZzsKCiAgdmFyIGNoZWNrSGFzU3VwZXIgPSBmdW5jdGlvbiAoKSB7CiAgICB2YXIgc291cmNlQXZhaWxhYmxlID0gZm5Ub1N0cmluZy5jYWxsKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9KS5pbmRleE9mKCdyZXR1cm4gdGhpcycpID4gLTE7CgogICAgaWYgKHNvdXJjZUF2YWlsYWJsZSkgewogICAgICByZXR1cm4gZnVuY3Rpb24gY2hlY2tIYXNTdXBlcihmdW5jKSB7CiAgICAgICAgcmV0dXJuIEhBU19TVVBFUl9QQVRURVJOLnRlc3QoZm5Ub1N0cmluZy5jYWxsKGZ1bmMpKTsKICAgICAgfTsKICAgIH0KCiAgICByZXR1cm4gZnVuY3Rpb24gY2hlY2tIYXNTdXBlcigpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9OwogIH0oKTsKCiAgX2V4cG9ydHMuY2hlY2tIYXNTdXBlciA9IGNoZWNrSGFzU3VwZXI7CiAgdmFyIEhBU19TVVBFUl9NQVAgPSBuZXcgV2Vha01hcCgpOwogIHZhciBST09UID0gT2JqZWN0LmZyZWV6ZShmdW5jdGlvbiAoKSB7fSk7CiAgX2V4cG9ydHMuUk9PVCA9IFJPT1Q7CiAgSEFTX1NVUEVSX01BUC5zZXQoUk9PVCwgZmFsc2UpOwoKICBmdW5jdGlvbiBoYXNTdXBlcihmdW5jKSB7CiAgICB2YXIgaGFzU3VwZXIgPSBIQVNfU1VQRVJfTUFQLmdldChmdW5jKTsKCiAgICBpZiAoaGFzU3VwZXIgPT09IHVuZGVmaW5lZCkgewogICAgICBoYXNTdXBlciA9IGNoZWNrSGFzU3VwZXIoZnVuYyk7CiAgICAgIEhBU19TVVBFUl9NQVAuc2V0KGZ1bmMsIGhhc1N1cGVyKTsKICAgIH0KCiAgICByZXR1cm4gaGFzU3VwZXI7CiAgfQoKICB2YXIgT0JTRVJWRVJTX01BUCA9IG5ldyBXZWFrTWFwKCk7CgogIGZ1bmN0aW9uIHNldE9ic2VydmVycyhmdW5jLCBvYnNlcnZlcnMpIHsKICAgIE9CU0VSVkVSU19NQVAuc2V0KGZ1bmMsIG9ic2VydmVycyk7CiAgfQoKICBmdW5jdGlvbiBnZXRPYnNlcnZlcnMoZnVuYykgewogICAgcmV0dXJuIE9CU0VSVkVSU19NQVAuZ2V0KGZ1bmMpOwogIH0KCiAgdmFyIExJU1RFTkVSU19NQVAgPSBuZXcgV2Vha01hcCgpOwoKICBmdW5jdGlvbiBzZXRMaXN0ZW5lcnMoZnVuYywgbGlzdGVuZXJzKSB7CiAgICBpZiAobGlzdGVuZXJzKSB7CiAgICAgIExJU1RFTkVSU19NQVAuc2V0KGZ1bmMsIGxpc3RlbmVycyk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBnZXRMaXN0ZW5lcnMoZnVuYykgewogICAgcmV0dXJuIExJU1RFTkVSU19NQVAuZ2V0KGZ1bmMpOwogIH0KCiAgdmFyIElTX1dSQVBQRURfRlVOQ1RJT05fU0VUID0gbmV3IF9wb2x5ZmlsbHMuX1dlYWtTZXQoKTsKICAvKioKICAgIFdyYXBzIHRoZSBwYXNzZWQgZnVuY3Rpb24gc28gdGhhdCBgdGhpcy5fc3VwZXJgIHdpbGwgcG9pbnQgdG8gdGhlIHN1cGVyRnVuYwogICAgd2hlbiB0aGUgZnVuY3Rpb24gaXMgaW52b2tlZC4gVGhpcyBpcyB0aGUgcHJpbWl0aXZlIHdlIHVzZSB0byBpbXBsZW1lbnQKICAgIGNhbGxzIHRvIHN1cGVyLgogIAogICAgQHByaXZhdGUKICAgIEBtZXRob2Qgd3JhcAogICAgQGZvciBFbWJlcgogICAgQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gY2FsbAogICAgQHBhcmFtIHtGdW5jdGlvbn0gc3VwZXJGdW5jIFRoZSBzdXBlciBmdW5jdGlvbi4KICAgIEByZXR1cm4ge0Z1bmN0aW9ufSB3cmFwcGVkIGZ1bmN0aW9uLgogICovCgogIGZ1bmN0aW9uIHdyYXAoZnVuYywgc3VwZXJGdW5jKSB7CiAgICBpZiAoIWhhc1N1cGVyKGZ1bmMpKSB7CiAgICAgIHJldHVybiBmdW5jOwogICAgfSAvLyBlbnN1cmUgYW4gdW53cmFwcGVkIHN1cGVyIHRoYXQgY2FsbHMgX3N1cGVyIGlzIHdyYXBwZWQgd2l0aCBhIHRlcm1pbmFsIF9zdXBlcgoKCiAgICBpZiAoIUlTX1dSQVBQRURfRlVOQ1RJT05fU0VULmhhcyhzdXBlckZ1bmMpICYmIGhhc1N1cGVyKHN1cGVyRnVuYykpIHsKICAgICAgcmV0dXJuIF93cmFwKGZ1bmMsIF93cmFwKHN1cGVyRnVuYywgUk9PVCkpOwogICAgfQoKICAgIHJldHVybiBfd3JhcChmdW5jLCBzdXBlckZ1bmMpOwogIH0KCiAgZnVuY3Rpb24gX3dyYXAoZnVuYywgc3VwZXJGdW5jKSB7CiAgICBmdW5jdGlvbiBzdXBlcldyYXBwZXIoKSB7CiAgICAgIHZhciBvcmlnID0gdGhpcy5fc3VwZXI7CiAgICAgIHRoaXMuX3N1cGVyID0gc3VwZXJGdW5jOwogICAgICB2YXIgcmV0ID0gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgICB0aGlzLl9zdXBlciA9IG9yaWc7CiAgICAgIHJldHVybiByZXQ7CiAgICB9CgogICAgSVNfV1JBUFBFRF9GVU5DVElPTl9TRVQuYWRkKHN1cGVyV3JhcHBlcik7CiAgICBzZXRPYnNlcnZlcnMoc3VwZXJXcmFwcGVyLCBnZXRPYnNlcnZlcnMoZnVuYykpOwogICAgc2V0TGlzdGVuZXJzKHN1cGVyV3JhcHBlciwgZ2V0TGlzdGVuZXJzKGZ1bmMpKTsKICAgIHJldHVybiBzdXBlcldyYXBwZXI7CiAgfQoKICB2YXIgb2JqZWN0VG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nOwogIHZhciBmdW5jdGlvblRvU3RyaW5nID0gRnVuY3Rpb24ucHJvdG90eXBlLnRvU3RyaW5nOwogIHZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheTsKICB2YXIgb2JqZWN0S2V5cyA9IE9iamVjdC5rZXlzOwogIHZhciBzdHJpbmdpZnkgPSBKU09OLnN0cmluZ2lmeTsKICB2YXIgTElTVF9MSU1JVCA9IDEwMDsKICB2YXIgREVQVEhfTElNSVQgPSA0OwogIHZhciBTQUZFX0tFWSA9IC9eW1x3JF0rJC87CiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL2RlYnVnCiAgKi8KCiAgLyoqCiAgICBDb252ZW5pZW5jZSBtZXRob2QgdG8gaW5zcGVjdCBhbiBvYmplY3QuIFRoaXMgbWV0aG9kIHdpbGwgYXR0ZW1wdCB0bwogICAgY29udmVydCB0aGUgb2JqZWN0IGludG8gYSB1c2VmdWwgc3RyaW5nIGRlc2NyaXB0aW9uLgogIAogICAgSXQgaXMgYSBwcmV0dHkgc2ltcGxlIGltcGxlbWVudGF0aW9uLiBJZiB5b3Ugd2FudCBzb21ldGhpbmcgbW9yZSByb2J1c3QsCiAgICB1c2Ugc29tZXRoaW5nIGxpa2UgSlNEdW1wOiBodHRwczovL2dpdGh1Yi5jb20vTlYvanNEdW1wCiAgCiAgICBAbWV0aG9kIGluc3BlY3QKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB5b3Ugd2FudCB0byBpbnNwZWN0LgogICAgQHJldHVybiB7U3RyaW5nfSBBIGRlc2NyaXB0aW9uIG9mIHRoZSBvYmplY3QKICAgIEBzaW5jZSAxLjQuMAogICAgQHByaXZhdGUKICAqLwoKICBmdW5jdGlvbiBpbnNwZWN0KG9iaikgewogICAgLy8gZGV0ZWN0IE5vZGUgdXRpbC5pbnNwZWN0IGNhbGwgaW5zcGVjdChkZXB0aDogbnVtYmVyLCBvcHRzOiBvYmplY3QpCiAgICBpZiAodHlwZW9mIG9iaiA9PT0gJ251bWJlcicgJiYgYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgewogICAgICByZXR1cm4gdGhpczsKICAgIH0KCiAgICByZXR1cm4gaW5zcGVjdFZhbHVlKG9iaiwgMCk7CiAgfQoKICBmdW5jdGlvbiBpbnNwZWN0VmFsdWUodmFsdWUsIGRlcHRoLCBzZWVuKSB7CiAgICB2YXIgdmFsdWVJc0FycmF5ID0gZmFsc2U7CgogICAgc3dpdGNoICh0eXBlb2YgdmFsdWUpIHsKICAgICAgY2FzZSAndW5kZWZpbmVkJzoKICAgICAgICByZXR1cm4gJ3VuZGVmaW5lZCc7CgogICAgICBjYXNlICdvYmplY3QnOgogICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkgcmV0dXJuICdudWxsJzsKCiAgICAgICAgaWYgKGlzQXJyYXkodmFsdWUpKSB7CiAgICAgICAgICB2YWx1ZUlzQXJyYXkgPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSAvLyBpcyB0b1N0cmluZyBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nIG9yIHVuZGVmaW5lZCB0aGVuIHRyYXZlcnNlCgoKICAgICAgICBpZiAodmFsdWUudG9TdHJpbmcgPT09IG9iamVjdFRvU3RyaW5nIHx8IHZhbHVlLnRvU3RyaW5nID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0gLy8gY3VzdG9tIHRvU3RyaW5nCgoKICAgICAgICByZXR1cm4gdmFsdWUudG9TdHJpbmcoKTsKCiAgICAgIGNhc2UgJ2Z1bmN0aW9uJzoKICAgICAgICByZXR1cm4gdmFsdWUudG9TdHJpbmcgPT09IGZ1bmN0aW9uVG9TdHJpbmcgPyB2YWx1ZS5uYW1lID8gIltGdW5jdGlvbjoiICsgdmFsdWUubmFtZSArICJdIiA6ICJbRnVuY3Rpb25dIiA6IHZhbHVlLnRvU3RyaW5nKCk7CgogICAgICBjYXNlICdzdHJpbmcnOgogICAgICAgIHJldHVybiBzdHJpbmdpZnkodmFsdWUpOwoKICAgICAgY2FzZSAnc3ltYm9sJzoKICAgICAgY2FzZSAnYm9vbGVhbic6CiAgICAgIGNhc2UgJ251bWJlcic6CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCk7CiAgICB9CgogICAgaWYgKHNlZW4gPT09IHVuZGVmaW5lZCkgewogICAgICBzZWVuID0gbmV3IF9wb2x5ZmlsbHMuX1dlYWtTZXQoKTsKICAgIH0gZWxzZSB7CiAgICAgIGlmIChzZWVuLmhhcyh2YWx1ZSkpIHJldHVybiAiW0NpcmN1bGFyXSI7CiAgICB9CgogICAgc2Vlbi5hZGQodmFsdWUpOwogICAgcmV0dXJuIHZhbHVlSXNBcnJheSA/IGluc3BlY3RBcnJheSh2YWx1ZSwgZGVwdGggKyAxLCBzZWVuKSA6IGluc3BlY3RPYmplY3QodmFsdWUsIGRlcHRoICsgMSwgc2Vlbik7CiAgfQoKICBmdW5jdGlvbiBpbnNwZWN0S2V5KGtleSkgewogICAgcmV0dXJuIFNBRkVfS0VZLnRlc3Qoa2V5KSA/IGtleSA6IHN0cmluZ2lmeShrZXkpOwogIH0KCiAgZnVuY3Rpb24gaW5zcGVjdE9iamVjdChvYmosIGRlcHRoLCBzZWVuKSB7CiAgICBpZiAoZGVwdGggPiBERVBUSF9MSU1JVCkgewogICAgICByZXR1cm4gJ1tPYmplY3RdJzsKICAgIH0KCiAgICB2YXIgcyA9ICd7JzsKICAgIHZhciBrZXlzID0gb2JqZWN0S2V5cyhvYmopOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgICBzICs9IGkgPT09IDAgPyAnICcgOiAnLCAnOwoKICAgICAgaWYgKGkgPj0gTElTVF9MSU1JVCkgewogICAgICAgIHMgKz0gIi4uLiAiICsgKGtleXMubGVuZ3RoIC0gTElTVF9MSU1JVCkgKyAiIG1vcmUga2V5cyI7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KCiAgICAgIHZhciBrZXkgPSBrZXlzW2ldOwogICAgICBzICs9IGluc3BlY3RLZXkoa2V5KSArICc6ICcgKyBpbnNwZWN0VmFsdWUob2JqW2tleV0sIGRlcHRoLCBzZWVuKTsKICAgIH0KCiAgICBzICs9ICcgfSc7CiAgICByZXR1cm4gczsKICB9CgogIGZ1bmN0aW9uIGluc3BlY3RBcnJheShhcnIsIGRlcHRoLCBzZWVuKSB7CiAgICBpZiAoZGVwdGggPiBERVBUSF9MSU1JVCkgewogICAgICByZXR1cm4gJ1tBcnJheV0nOwogICAgfQoKICAgIHZhciBzID0gJ1snOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7CiAgICAgIHMgKz0gaSA9PT0gMCA/ICcgJyA6ICcsICc7CgogICAgICBpZiAoaSA+PSBMSVNUX0xJTUlUKSB7CiAgICAgICAgcyArPSAiLi4uICIgKyAoYXJyLmxlbmd0aCAtIExJU1RfTElNSVQpICsgIiBtb3JlIGl0ZW1zIjsKICAgICAgICBicmVhazsKICAgICAgfQoKICAgICAgcyArPSBpbnNwZWN0VmFsdWUoYXJyW2ldLCBkZXB0aCwgc2Vlbik7CiAgICB9CgogICAgcyArPSAnIF0nOwogICAgcmV0dXJuIHM7CiAgfQoKICBmdW5jdGlvbiBsb29rdXBEZXNjcmlwdG9yKG9iaiwga2V5TmFtZSkgewogICAgdmFyIGN1cnJlbnQgPSBvYmo7CgogICAgZG8gewogICAgICB2YXIgZGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoY3VycmVudCwga2V5TmFtZSk7CgogICAgICBpZiAoZGVzY3JpcHRvciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIGRlc2NyaXB0b3I7CiAgICAgIH0KCiAgICAgIGN1cnJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoY3VycmVudCk7CiAgICB9IHdoaWxlIChjdXJyZW50ICE9PSBudWxsKTsKCiAgICByZXR1cm4gbnVsbDsKICB9CiAgLyoqCiAgICBDaGVja3MgdG8gc2VlIGlmIHRoZSBgbWV0aG9kTmFtZWAgZXhpc3RzIG9uIHRoZSBgb2JqYC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCBmb28gPSB7IGJhcjogZnVuY3Rpb24oKSB7IHJldHVybiAnYmFyJzsgfSwgYmF6OiBudWxsIH07CiAgCiAgICBFbWJlci5jYW5JbnZva2UoZm9vLCAnYmFyJyk7IC8vIHRydWUKICAgIEVtYmVyLmNhbkludm9rZShmb28sICdiYXonKTsgLy8gZmFsc2UKICAgIEVtYmVyLmNhbkludm9rZShmb28sICdiYXQnKTsgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQG1ldGhvZCBjYW5JbnZva2UKICAgIEBmb3IgRW1iZXIKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBjaGVjayBmb3IgdGhlIG1ldGhvZAogICAgQHBhcmFtIHtTdHJpbmd9IG1ldGhvZE5hbWUgVGhlIG1ldGhvZCBuYW1lIHRvIGNoZWNrIGZvcgogICAgQHJldHVybiB7Qm9vbGVhbn0KICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIGNhbkludm9rZShvYmosIG1ldGhvZE5hbWUpIHsKICAgIHJldHVybiBvYmogIT09IG51bGwgJiYgb2JqICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG9ialttZXRob2ROYW1lXSA9PT0gJ2Z1bmN0aW9uJzsKICB9CiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci91dGlscwogICovCgogIC8qKgogICAgQ2hlY2tzIHRvIHNlZSBpZiB0aGUgYG1ldGhvZE5hbWVgIGV4aXN0cyBvbiB0aGUgYG9iamAsCiAgICBhbmQgaWYgaXQgZG9lcywgaW52b2tlcyBpdCB3aXRoIHRoZSBhcmd1bWVudHMgcGFzc2VkLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgdHJ5SW52b2tlIH0gZnJvbSAnQGVtYmVyL3V0aWxzJzsKICAKICAgIGxldCBkID0gbmV3IERhdGUoJzAzLzE1LzIwMTMnKTsKICAKICAgIHRyeUludm9rZShkLCAnZ2V0VGltZScpOyAgICAgICAgICAgICAgLy8gMTM2MzMyMDAwMDAwMAogICAgdHJ5SW52b2tlKGQsICdzZXRGdWxsWWVhcicsIFsyMDE0XSk7ICAvLyAxMzk0ODU2MDAwMDAwCiAgICB0cnlJbnZva2UoZCwgJ25vU3VjaE1ldGhvZCcsIFsyMDE0XSk7IC8vIHVuZGVmaW5lZAogICAgYGBgCiAgCiAgICBAbWV0aG9kIHRyeUludm9rZQogICAgQGZvciBAZW1iZXIvdXRpbHMKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBjaGVjayBmb3IgdGhlIG1ldGhvZAogICAgQHBhcmFtIHtTdHJpbmd9IG1ldGhvZE5hbWUgVGhlIG1ldGhvZCBuYW1lIHRvIGNoZWNrIGZvcgogICAgQHBhcmFtIHtBcnJheX0gW2FyZ3NdIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kCiAgICBAcmV0dXJuIHsqfSB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBpbnZva2VkIG1ldGhvZCBvciB1bmRlZmluZWQgaWYgaXQgY2Fubm90IGJlIGludm9rZWQKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gdHJ5SW52b2tlKG9iaiwgbWV0aG9kTmFtZSwgYXJncykgewogICAgaWYgKGNhbkludm9rZShvYmosIG1ldGhvZE5hbWUpKSB7CiAgICAgIHZhciBtZXRob2QgPSBvYmpbbWV0aG9kTmFtZV07CiAgICAgIHJldHVybiBtZXRob2QuYXBwbHkob2JqLCBhcmdzKTsKICAgIH0KICB9CgogIHZhciBpc0FycmF5JDEgPSBBcnJheS5pc0FycmF5OwoKICBmdW5jdGlvbiBtYWtlQXJyYXkob2JqKSB7CiAgICBpZiAob2JqID09PSBudWxsIHx8IG9iaiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBbXTsKICAgIH0KCiAgICByZXR1cm4gaXNBcnJheSQxKG9iaikgPyBvYmogOiBbb2JqXTsKICB9CgogIHZhciBOQU1FUyA9IG5ldyBXZWFrTWFwKCk7CgogIGZ1bmN0aW9uIHNldE5hbWUob2JqLCBuYW1lKSB7CiAgICBpZiAoaXNPYmplY3Qob2JqKSkgTkFNRVMuc2V0KG9iaiwgbmFtZSk7CiAgfQoKICBmdW5jdGlvbiBnZXROYW1lKG9iaikgewogICAgcmV0dXJuIE5BTUVTLmdldChvYmopOwogIH0KCiAgdmFyIG9iamVjdFRvU3RyaW5nJDEgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nOwoKICBmdW5jdGlvbiBpc05vbmUob2JqKSB7CiAgICByZXR1cm4gb2JqID09PSBudWxsIHx8IG9iaiA9PT0gdW5kZWZpbmVkOwogIH0KICAvKgogICBBIGB0b1N0cmluZ2AgdXRpbCBmdW5jdGlvbiB0aGF0IHN1cHBvcnRzIG9iamVjdHMgd2l0aG91dCBhIGB0b1N0cmluZ2AKICAgbWV0aG9kLCBlLmcuIGFuIG9iamVjdCBjcmVhdGVkIHdpdGggYE9iamVjdC5jcmVhdGUobnVsbClgLgogICovCgoKICBmdW5jdGlvbiB0b1N0cmluZyhvYmopIHsKICAgIGlmICh0eXBlb2Ygb2JqID09PSAnc3RyaW5nJykgewogICAgICByZXR1cm4gb2JqOwogICAgfQoKICAgIGlmIChudWxsID09PSBvYmopIHJldHVybiAnbnVsbCc7CiAgICBpZiAodW5kZWZpbmVkID09PSBvYmopIHJldHVybiAndW5kZWZpbmVkJzsKCiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7CiAgICAgIC8vIFJlaW1wbGVtZW50IEFycmF5LnByb3RvdHlwZS5qb2luIGFjY29yZGluZyB0byBzcGVjICgyMi4xLjMuMTMpCiAgICAgIC8vIENoYW5naW5nIFRvU3RyaW5nKGVsZW1lbnQpIHdpdGggdGhpcyBzYWZlIHZlcnNpb24gb2YgVG9TdHJpbmcuCiAgICAgIHZhciByID0gJyc7CgogICAgICBmb3IgKHZhciBrID0gMDsgayA8IG9iai5sZW5ndGg7IGsrKykgewogICAgICAgIGlmIChrID4gMCkgewogICAgICAgICAgciArPSAnLCc7CiAgICAgICAgfQoKICAgICAgICBpZiAoIWlzTm9uZShvYmpba10pKSB7CiAgICAgICAgICByICs9IHRvU3RyaW5nKG9ialtrXSk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gcjsKICAgIH0KCiAgICBpZiAodHlwZW9mIG9iai50b1N0cmluZyA9PT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gb2JqLnRvU3RyaW5nKCk7CiAgICB9CgogICAgcmV0dXJuIG9iamVjdFRvU3RyaW5nJDEuY2FsbChvYmopOwogIH0KCiAgdmFyIEhBU19OQVRJVkVfU1lNQk9MID0gZnVuY3Rpb24gKCkgewogICAgaWYgKHR5cGVvZiBTeW1ib2wgIT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIHJldHVybiB0eXBlb2YgU3ltYm9sKCkgPT09ICdzeW1ib2wnOwogIH0oKTsKCiAgX2V4cG9ydHMuSEFTX05BVElWRV9TWU1CT0wgPSBIQVNfTkFUSVZFX1NZTUJPTDsKICB2YXIgSEFTX05BVElWRV9QUk9YWSA9IHR5cGVvZiBQcm94eSA9PT0gJ2Z1bmN0aW9uJzsKICBfZXhwb3J0cy5IQVNfTkFUSVZFX1BST1hZID0gSEFTX05BVElWRV9QUk9YWTsKICB2YXIgUFJPWElFUyA9IG5ldyBfcG9seWZpbGxzLl9XZWFrU2V0KCk7CgogIGZ1bmN0aW9uIGlzUHJveHkodmFsdWUpIHsKICAgIGlmIChpc09iamVjdCh2YWx1ZSkpIHsKICAgICAgcmV0dXJuIFBST1hJRVMuaGFzKHZhbHVlKTsKICAgIH0KCiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICBmdW5jdGlvbiBzZXRQcm94eShvYmplY3QpIHsKICAgIGlmIChpc09iamVjdChvYmplY3QpKSB7CiAgICAgIFBST1hJRVMuYWRkKG9iamVjdCk7CiAgICB9CiAgfQoKICB2YXIgQ2FjaGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDYWNoZShsaW1pdCwgZnVuYywgc3RvcmUpIHsKICAgICAgdGhpcy5saW1pdCA9IGxpbWl0OwogICAgICB0aGlzLmZ1bmMgPSBmdW5jOwogICAgICB0aGlzLnN0b3JlID0gc3RvcmU7CiAgICAgIHRoaXMuc2l6ZSA9IDA7CiAgICAgIHRoaXMubWlzc2VzID0gMDsKICAgICAgdGhpcy5oaXRzID0gMDsKICAgICAgdGhpcy5zdG9yZSA9IHN0b3JlIHx8IG5ldyBNYXAoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gQ2FjaGUucHJvdG90eXBlOwoKICAgIF9wcm90by5nZXQgPSBmdW5jdGlvbiBnZXQoa2V5KSB7CiAgICAgIGlmICh0aGlzLnN0b3JlLmhhcyhrZXkpKSB7CiAgICAgICAgdGhpcy5oaXRzKys7CiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZ2V0KGtleSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5taXNzZXMrKzsKICAgICAgICByZXR1cm4gdGhpcy5zZXQoa2V5LCB0aGlzLmZ1bmMoa2V5KSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnNldCA9IGZ1bmN0aW9uIHNldChrZXksIHZhbHVlKSB7CiAgICAgIGlmICh0aGlzLmxpbWl0ID4gdGhpcy5zaXplKSB7CiAgICAgICAgdGhpcy5zaXplKys7CiAgICAgICAgdGhpcy5zdG9yZS5zZXQoa2V5LCB2YWx1ZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH07CgogICAgX3Byb3RvLnB1cmdlID0gZnVuY3Rpb24gcHVyZ2UoKSB7CiAgICAgIHRoaXMuc3RvcmUuY2xlYXIoKTsKICAgICAgdGhpcy5zaXplID0gMDsKICAgICAgdGhpcy5oaXRzID0gMDsKICAgICAgdGhpcy5taXNzZXMgPSAwOwogICAgfTsKCiAgICByZXR1cm4gQ2FjaGU7CiAgfSgpOwoKICBfZXhwb3J0cy5DYWNoZSA9IENhY2hlOwogIHZhciBFTUJFUl9BUlJBWSA9IHN5bWJvbCgnRU1CRVJfQVJSQVknKTsKICBfZXhwb3J0cy5FTUJFUl9BUlJBWSA9IEVNQkVSX0FSUkFZOwoKICBmdW5jdGlvbiBpc0VtYmVyQXJyYXkob2JqKSB7CiAgICByZXR1cm4gb2JqICYmIG9ialtFTUJFUl9BUlJBWV07CiAgfQoKICB2YXIgc2V0dXBNYW5kYXRvcnlTZXR0ZXI7CiAgX2V4cG9ydHMuc2V0dXBNYW5kYXRvcnlTZXR0ZXIgPSBzZXR1cE1hbmRhdG9yeVNldHRlcjsKICB2YXIgdGVhcmRvd25NYW5kYXRvcnlTZXR0ZXI7CiAgX2V4cG9ydHMudGVhcmRvd25NYW5kYXRvcnlTZXR0ZXIgPSB0ZWFyZG93bk1hbmRhdG9yeVNldHRlcjsKICB2YXIgc2V0V2l0aE1hbmRhdG9yeVNldHRlcjsKICBfZXhwb3J0cy5zZXRXaXRoTWFuZGF0b3J5U2V0dGVyID0gc2V0V2l0aE1hbmRhdG9yeVNldHRlcjsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICAmJiB0cnVlCiAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgKSB7CiAgICAgIHZhciBNQU5EQVRPUllfU0VUVEVSUyA9IG5ldyBXZWFrTWFwKCk7CgogICAgICB2YXIgX3Byb3BlcnR5SXNFbnVtZXJhYmxlID0gZnVuY3Rpb24gX3Byb3BlcnR5SXNFbnVtZXJhYmxlKG9iaiwga2V5KSB7CiAgICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChvYmosIGtleSk7CiAgICAgIH07CgogICAgICBfZXhwb3J0cy5zZXR1cE1hbmRhdG9yeVNldHRlciA9IHNldHVwTWFuZGF0b3J5U2V0dGVyID0gZnVuY3Rpb24gc2V0dXBNYW5kYXRvcnlTZXR0ZXIob2JqLCBrZXlOYW1lKSB7CiAgICAgICAgdmFyIGRlc2MgPSBsb29rdXBEZXNjcmlwdG9yKG9iaiwga2V5TmFtZSkgfHwge307CgogICAgICAgIGlmIChkZXNjLmdldCB8fCBkZXNjLnNldCkgewogICAgICAgICAgLy8gaWYgaXQgaGFzIGEgZ2V0dGVyIG9yIHNldHRlciwgd2UgY2FuJ3QgaW5zdGFsbCB0aGUgbWFuZGF0b3J5IHNldHRlci4KICAgICAgICAgIC8vIG5hdGl2ZSBzZXR0ZXJzIGFyZSBhbGxvd2VkLCB3ZSBoYXZlIHRvIGFzc3VtZSB0aGF0IHRoZXkgd2lsbCByZXNvbHZlCiAgICAgICAgICAvLyB0byB0cmFja2VkIHByb3BlcnRpZXMuCiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZiAoZGVzYyAmJiAoIWRlc2MuY29uZmlndXJhYmxlIHx8ICFkZXNjLndyaXRhYmxlKSkgewogICAgICAgICAgLy8gaWYgaXQgaXNuJ3Qgd3JpdGFibGUgYW55d2F5cywgc28gd2Ugc2hvdWxkbid0IHByb3ZpZGUgdGhlIHNldHRlci4KICAgICAgICAgIC8vIGlmIGl0IGlzbid0IGNvbmZpZ3VyYWJsZSwgd2UgY2FuJ3Qgb3ZlcndyaXRlIGl0IGFueXdheXMuCiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICB2YXIgc2V0dGVycyA9IE1BTkRBVE9SWV9TRVRURVJTLmdldChvYmopOwoKICAgICAgICBpZiAoc2V0dGVycyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBzZXR0ZXJzID0ge307CiAgICAgICAgICBNQU5EQVRPUllfU0VUVEVSUy5zZXQob2JqLCBzZXR0ZXJzKTsKICAgICAgICB9CgogICAgICAgIGRlc2MuaGFkT3duUHJvcGVydHkgPSBPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleU5hbWUpOwogICAgICAgIHNldHRlcnNba2V5TmFtZV0gPSBkZXNjOwogICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleU5hbWUsIHsKICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICAgIGVudW1lcmFibGU6IF9wcm9wZXJ0eUlzRW51bWVyYWJsZShvYmosIGtleU5hbWUpLAogICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgICAgIGlmIChkZXNjLmdldCkgewogICAgICAgICAgICAgIHJldHVybiBkZXNjLmdldC5jYWxsKHRoaXMpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJldHVybiBkZXNjLnZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9LAogICAgICAgICAgc2V0OiBmdW5jdGlvbiBzZXQodmFsdWUpIHsKICAgICAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGF0dGVtcHRlZCB0byB1cGRhdGUgIiArIHRoaXMgKyAiLiIgKyBTdHJpbmcoa2V5TmFtZSkgKyAiIHRvIFwiIiArIFN0cmluZyh2YWx1ZSkgKyAiXCIsIGJ1dCBpdCBpcyBiZWluZyB0cmFja2VkIGJ5IGEgdHJhY2tpbmcgY29udGV4dCwgc3VjaCBhcyBhIHRlbXBsYXRlLCBjb21wdXRlZCBwcm9wZXJ0eSwgb3Igb2JzZXJ2ZXIuIEluIG9yZGVyIHRvIG1ha2Ugc3VyZSB0aGUgY29udGV4dCB1cGRhdGVzIHByb3Blcmx5LCB5b3UgbXVzdCBpbnZhbGlkYXRlIHRoZSBwcm9wZXJ0eSB3aGVuIHVwZGF0aW5nIGl0LiBZb3UgY2FuIG1hcmsgdGhlIHByb3BlcnR5IGFzIGBAdHJhY2tlZGAsIG9yIHVzZSBgQGVtYmVyL29iamVjdCNzZXRgIHRvIGRvIHRoaXMuIikpOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9OwoKICAgICAgX2V4cG9ydHMudGVhcmRvd25NYW5kYXRvcnlTZXR0ZXIgPSB0ZWFyZG93bk1hbmRhdG9yeVNldHRlciA9IGZ1bmN0aW9uIHRlYXJkb3duTWFuZGF0b3J5U2V0dGVyKG9iaiwga2V5TmFtZSkgewogICAgICAgIHZhciBzZXR0ZXJzID0gTUFOREFUT1JZX1NFVFRFUlMuZ2V0KG9iaik7CgogICAgICAgIGlmIChzZXR0ZXJzICE9PSB1bmRlZmluZWQgJiYgc2V0dGVyc1trZXlOYW1lXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXlOYW1lLCBzZXR0ZXJzW2tleU5hbWVdKTsKICAgICAgICAgIHNldHRlcnNba2V5TmFtZV0gPSB1bmRlZmluZWQ7CiAgICAgICAgfQogICAgICB9OwoKICAgICAgX2V4cG9ydHMuc2V0V2l0aE1hbmRhdG9yeVNldHRlciA9IHNldFdpdGhNYW5kYXRvcnlTZXR0ZXIgPSBmdW5jdGlvbiBzZXRXaXRoTWFuZGF0b3J5U2V0dGVyKG9iaiwga2V5TmFtZSwgdmFsdWUpIHsKICAgICAgICB2YXIgc2V0dGVycyA9IE1BTkRBVE9SWV9TRVRURVJTLmdldChvYmopOwoKICAgICAgICBpZiAoc2V0dGVycyAhPT0gdW5kZWZpbmVkICYmIHNldHRlcnNba2V5TmFtZV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdmFyIHNldHRlciA9IHNldHRlcnNba2V5TmFtZV07CgogICAgICAgICAgaWYgKHNldHRlci5zZXQpIHsKICAgICAgICAgICAgc2V0dGVyLnNldC5jYWxsKG9iaiwgdmFsdWUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc2V0dGVyLnZhbHVlID0gdmFsdWU7IC8vIElmIHRoZSBvYmplY3QgZGlkbid0IGhhdmUgb3duIHByb3BlcnR5IGJlZm9yZSwgaXQgd291bGQgaGF2ZSBjaGFuZ2VkCiAgICAgICAgICAgIC8vIHRoZSBlbnVtZXJhYmlsaXR5IGFmdGVyIHNldHRpbmcgdGhlIHZhbHVlIHRoZSBmaXJzdCB0aW1lLgoKICAgICAgICAgICAgaWYgKCFzZXR0ZXIuaGFkT3duUHJvcGVydHkpIHsKICAgICAgICAgICAgICB2YXIgZGVzYyA9IGxvb2t1cERlc2NyaXB0b3Iob2JqLCBrZXlOYW1lKTsKICAgICAgICAgICAgICBkZXNjLmVudW1lcmFibGUgPSB0cnVlOwogICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleU5hbWUsIGRlc2MpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9ialtrZXlOYW1lXSA9IHZhbHVlOwogICAgICAgIH0KICAgICAgfTsKICAgIH0KICAvKgogICBUaGlzIHBhY2thZ2Ugd2lsbCBiZSBlYWdlcmx5IHBhcnNlZCBhbmQgc2hvdWxkIGhhdmUgbm8gZGVwZW5kZW5jaWVzIG9uIGV4dGVybmFsCiAgIHBhY2thZ2VzLgogIAogICBJdCBpcyBpbnRlbmRlZCB0byBiZSB1c2VkIHRvIHNoYXJlIHV0aWxpdHkgbWV0aG9kcyB0aGF0IHdpbGwgYmUgbmVlZGVkCiAgIGJ5IGV2ZXJ5IEVtYmVyIGFwcGxpY2F0aW9uIChhbmQgaXMgKipub3QqKiBhIGR1bXBpbmcgZ3JvdW5kIG9mIHVzZWZ1bCB1dGlsaXRpZXMpLgogIAogICBVdGlsaXR5IG1ldGhvZHMgdGhhdCBhcmUgbmVlZGVkIGluIDwgODAlIG9mIGNhc2VzIHNob3VsZCBiZSBwbGFjZWQKICAgZWxzZXdoZXJlIChzbyB0aGV5IGNhbiBiZSBsYXppbHkgZXZhbHVhdGVkIC8gcGFyc2VkKS4KICAqLwoKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3N5c3RlbS9qcXVlcnkiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3N5c3RlbS91dGlscyIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2V2ZW50X2Rpc3BhdGNoZXIiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL2NvbXBvbmVudF9sb29rdXAiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL21peGlucy90ZXh0X3N1cHBvcnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL2NvcmVfdmlldyIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvbWl4aW5zL2NsYXNzX25hbWVzX3N1cHBvcnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL21peGlucy9jaGlsZF92aWV3c19zdXBwb3J0IiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9taXhpbnMvdmlld19zdGF0ZV9zdXBwb3J0IiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9taXhpbnMvdmlld19zdXBwb3J0IiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9taXhpbnMvYWN0aW9uX3N1cHBvcnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL2NvbXBhdC9hdHRycyIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2xvb2t1cF9wYXJ0aWFsIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vYWN0aW9uX21hbmFnZXIiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfanF1ZXJ5LCBfdXRpbHMsIF9ldmVudF9kaXNwYXRjaGVyLCBfY29tcG9uZW50X2xvb2t1cCwgX3RleHRfc3VwcG9ydCwgX2NvcmVfdmlldywgX2NsYXNzX25hbWVzX3N1cHBvcnQsIF9jaGlsZF92aWV3c19zdXBwb3J0LCBfdmlld19zdGF0ZV9zdXBwb3J0LCBfdmlld19zdXBwb3J0LCBfYWN0aW9uX3N1cHBvcnQsIF9hdHRycywgX2xvb2t1cF9wYXJ0aWFsLCBfYWN0aW9uX21hbmFnZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImpRdWVyeSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9qcXVlcnkualF1ZXJ5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImpRdWVyeURpc2FibGVkIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2pxdWVyeS5qUXVlcnlEaXNhYmxlZDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJhZGRDaGlsZFZpZXciLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfdXRpbHMuYWRkQ2hpbGRWaWV3OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImlzU2ltcGxlQ2xpY2siLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfdXRpbHMuaXNTaW1wbGVDbGljazsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRWaWV3Qm91bmRzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldFZpZXdCb3VuZHM7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ2V0Vmlld0NsaWVudFJlY3RzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldFZpZXdDbGllbnRSZWN0czsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRWaWV3Qm91bmRpbmdDbGllbnRSZWN0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldFZpZXdCb3VuZGluZ0NsaWVudFJlY3Q7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ2V0Um9vdFZpZXdzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldFJvb3RWaWV3czsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRDaGlsZFZpZXdzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldENoaWxkVmlld3M7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ2V0Vmlld0lkIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmdldFZpZXdJZDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRFbGVtZW50VmlldyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF91dGlscy5nZXRFbGVtZW50VmlldzsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRWaWV3RWxlbWVudCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF91dGlscy5nZXRWaWV3RWxlbWVudDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJzZXRFbGVtZW50VmlldyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF91dGlscy5zZXRFbGVtZW50VmlldzsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJzZXRWaWV3RWxlbWVudCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF91dGlscy5zZXRWaWV3RWxlbWVudDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJjbGVhckVsZW1lbnRWaWV3IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmNsZWFyRWxlbWVudFZpZXc7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiY2xlYXJWaWV3RWxlbWVudCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF91dGlscy5jbGVhclZpZXdFbGVtZW50OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImNvbnN0cnVjdFN0eWxlRGVwcmVjYXRpb25NZXNzYWdlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3V0aWxzLmNvbnN0cnVjdFN0eWxlRGVwcmVjYXRpb25NZXNzYWdlOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkV2ZW50RGlzcGF0Y2hlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9ldmVudF9kaXNwYXRjaGVyLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQ29tcG9uZW50TG9va3VwIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXBvbmVudF9sb29rdXAuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJUZXh0U3VwcG9ydCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF90ZXh0X3N1cHBvcnQuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJDb3JlVmlldyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb3JlX3ZpZXcuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJDbGFzc05hbWVzU3VwcG9ydCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jbGFzc19uYW1lc19zdXBwb3J0LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQ2hpbGRWaWV3c1N1cHBvcnQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY2hpbGRfdmlld3Nfc3VwcG9ydC5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIlZpZXdTdGF0ZVN1cHBvcnQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfdmlld19zdGF0ZV9zdXBwb3J0LmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiVmlld01peGluIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ZpZXdfc3VwcG9ydC5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkFjdGlvblN1cHBvcnQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYWN0aW9uX3N1cHBvcnQuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJNVVRBQkxFX0NFTEwiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXR0cnMuTVVUQUJMRV9DRUxMOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImxvb2t1cFBhcnRpYWwiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbG9va3VwX3BhcnRpYWwuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJoYXNQYXJ0aWFsIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2xvb2t1cF9wYXJ0aWFsLmhhc1BhcnRpYWw7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQWN0aW9uTWFuYWdlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9hY3Rpb25fbWFuYWdlci5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvY29tcGF0L2F0dHJzIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3V0aWxzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5NVVRBQkxFX0NFTEwgPSB2b2lkIDA7CiAgdmFyIE1VVEFCTEVfQ0VMTCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnTVVUQUJMRV9DRUxMJyk7CiAgX2V4cG9ydHMuTVVUQUJMRV9DRUxMID0gTVVUQUJMRV9DRUxMOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvY29tcGF0L2ZhbGxiYWNrLXZpZXctcmVnaXN0cnkiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdXRpbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIHZhciBfZGVmYXVsdCA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL2NvbXBvbmVudF9sb29rdXAiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9ydW50aW1lKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICB2YXIgX2RlZmF1bHQgPSBfcnVudGltZS5PYmplY3QuZXh0ZW5kKHsKICAgIGNvbXBvbmVudEZvcjogZnVuY3Rpb24gY29tcG9uZW50Rm9yKG5hbWUsIG93bmVyLCBvcHRpb25zKSB7CiAgICAgIHZhciBmdWxsTmFtZSA9ICJjb21wb25lbnQ6IiArIG5hbWU7CiAgICAgIHJldHVybiBvd25lci5mYWN0b3J5Rm9yKGZ1bGxOYW1lLCBvcHRpb25zKTsKICAgIH0sCiAgICBsYXlvdXRGb3I6IGZ1bmN0aW9uIGxheW91dEZvcihuYW1lLCBvd25lciwgb3B0aW9ucykgewogICAgICB2YXIgdGVtcGxhdGVGdWxsTmFtZSA9ICJ0ZW1wbGF0ZTpjb21wb25lbnRzLyIgKyBuYW1lOwogICAgICByZXR1cm4gb3duZXIubG9va3VwKHRlbXBsYXRlRnVsbE5hbWUsIG9wdGlvbnMpOwogICAgfQogIH0pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9taXhpbnMvYWN0aW9uX3N1cHBvcnQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9jb21wYXQvYXR0cnMiLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdXRpbHMsIF9tZXRhbCwgX2RlYnVnLCBfYXR0cnMsIF9kZXByZWNhdGVkRmVhdHVyZXMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICBAbW9kdWxlIGVtYmVyCiAgKi8KICB2YXIgbWl4aW5PYmogPSB7CiAgICBzZW5kOiBmdW5jdGlvbiBzZW5kKGFjdGlvbk5hbWUpIHsKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5ID0gMTsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleSAtIDFdID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISghdGhpcy5pc0Rlc3Ryb3lpbmcgJiYgIXRoaXMuaXNEZXN0cm95ZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQXR0ZW1wdGVkIHRvIGNhbGwgLnNlbmQoKSB3aXRoIHRoZSBhY3Rpb24gJyIgKyBhY3Rpb25OYW1lICsgIicgb24gdGhlIGRlc3Ryb3llZCBvYmplY3QgJyIgKyB0aGlzICsgIicuIiwgIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgIHZhciBhY3Rpb24gPSB0aGlzLmFjdGlvbnMgJiYgdGhpcy5hY3Rpb25zW2FjdGlvbk5hbWVdOwoKICAgICAgaWYgKGFjdGlvbikgewogICAgICAgIHZhciBzaG91bGRCdWJibGUgPSBhY3Rpb24uYXBwbHkodGhpcywgYXJncykgPT09IHRydWU7CgogICAgICAgIGlmICghc2hvdWxkQnViYmxlKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgdGFyZ2V0ID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICd0YXJnZXQnKTsKCiAgICAgIGlmICh0YXJnZXQpIHsKICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgdGFyZ2V0LnNlbmQgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIGB0YXJnZXRgIGZvciAiICsgdGhpcyArICIgKCIgKyB0YXJnZXQgKyAiKSBkb2VzIG5vdCBoYXZlIGEgYHNlbmRgIG1ldGhvZCIsIHR5cGVvZiB0YXJnZXQuc2VuZCA9PT0gJ2Z1bmN0aW9uJykpOwogICAgICAgIHRhcmdldC5zZW5kLmFwcGx5KHRhcmdldCwgYXJndW1lbnRzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAoZmFsc2UgJiYgIShhY3Rpb24pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgoMCwgX3V0aWxzLmluc3BlY3QpKHRoaXMpICsgIiBoYWQgbm8gYWN0aW9uIGhhbmRsZXIgZm9yOiAiICsgYWN0aW9uTmFtZSwgYWN0aW9uKSk7CiAgICAgIH0KICAgIH0KICB9OwoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5TRU5EX0FDVElPTikgewogICAgLyoqCiAgICAgIENhbGxzIGFuIGFjdGlvbiBwYXNzZWQgdG8gYSBjb21wb25lbnQuCiAgICAgICBGb3IgZXhhbXBsZSBhIGNvbXBvbmVudCBmb3IgcGxheWluZyBvciBwYXVzaW5nIG11c2ljIG1heSB0cmFuc2xhdGUgY2xpY2sgZXZlbnRzCiAgICAgIGludG8gYWN0aW9uIG5vdGlmaWNhdGlvbnMgb2YgInBsYXkiIG9yICJzdG9wIiBkZXBlbmRpbmcgb24gc29tZSBpbnRlcm5hbCBzdGF0ZQogICAgICBvZiB0aGUgY29tcG9uZW50OgogICAgICAgYGBgYXBwL2NvbXBvbmVudHMvcGxheS1idXR0b24uanMKICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICAgIGNsaWNrKCkgewogICAgICAgICAgaWYgKHRoaXMuZ2V0KCdpc1BsYXlpbmcnKSkgewogICAgICAgICAgICB0aGlzLnNlbmRBY3Rpb24oJ3BsYXknKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRoaXMuc2VuZEFjdGlvbignc3RvcCcpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVGhlIGFjdGlvbnMgInBsYXkiIGFuZCAic3RvcCIgbXVzdCBiZSBwYXNzZWQgdG8gdGhpcyBgcGxheS1idXR0b25gIGNvbXBvbmVudDoKICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAge3shIGFwcC90ZW1wbGF0ZXMvYXBwbGljYXRpb24uaGJzIH19CiAgICAgIHt7cGxheS1idXR0b24gcGxheT0oYWN0aW9uICJtdXNpY1N0YXJ0ZWQiKSBzdG9wPShhY3Rpb24gIm11c2ljU3RvcHBlZCIpfX0KICAgICAgYGBgCiAgICAgICBXaGVuIHRoZSBjb21wb25lbnQgcmVjZWl2ZXMgYSBicm93c2VyIGBjbGlja2AgZXZlbnQgaXQgdHJhbnNsYXRlIHRoaXMKICAgICAgaW50ZXJhY3Rpb24gaW50byBhcHBsaWNhdGlvbi1zcGVjaWZpYyBzZW1hbnRpY3MgKCJwbGF5IiBvciAic3RvcCIpIGFuZAogICAgICBjYWxscyB0aGUgc3BlY2lmaWVkIGFjdGlvbi4KICAgICAgIGBgYGFwcC9jb250cm9sbGVyL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBDb250cm9sbGVyIGZyb20gJ0BlbWJlci9jb250cm9sbGVyJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IENvbnRyb2xsZXIuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBtdXNpY1N0YXJ0ZWQoKSB7CiAgICAgICAgICAgIC8vIGNhbGxlZCB3aGVuIHRoZSBwbGF5IGJ1dHRvbiBpcyBjbGlja2VkCiAgICAgICAgICAgIC8vIGFuZCB0aGUgbXVzaWMgc3RhcnRlZCBwbGF5aW5nCiAgICAgICAgICB9LAogICAgICAgICAgbXVzaWNTdG9wcGVkKCkgewogICAgICAgICAgICAvLyBjYWxsZWQgd2hlbiB0aGUgcGxheSBidXR0b24gaXMgY2xpY2tlZAogICAgICAgICAgICAvLyBhbmQgdGhlIG11c2ljIHN0b3BwZWQgcGxheWluZwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgSWYgbm8gYWN0aW9uIGlzIHBhc3NlZCB0byBgc2VuZEFjdGlvbmAgYSBkZWZhdWx0IG5hbWUgb2YgImFjdGlvbiIKICAgICAgaXMgYXNzdW1lZC4KICAgICAgIGBgYGFwcC9jb21wb25lbnRzL25leHQtYnV0dG9uLmpzCiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICBjbGljaygpIHsKICAgICAgICAgIHRoaXMuc2VuZEFjdGlvbigpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgaGFuZGxlYmFycwogICAgICB7eyEgYXBwL3RlbXBsYXRlcy9hcHBsaWNhdGlvbi5oYnMgfX0KICAgICAge3tuZXh0LWJ1dHRvbiBhY3Rpb249KGFjdGlvbiAicGxheU5leHRTb25nSW5BbGJ1bSIpfX0KICAgICAgYGBgCiAgICAgICBgYGBhcHAvY29udHJvbGxlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IENvbnRyb2xsZXIgZnJvbSAnQGVtYmVyL2NvbnRyb2xsZXInOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQ29udHJvbGxlci5leHRlbmQoewogICAgICAgIGFjdGlvbnM6IHsKICAgICAgICAgIHBsYXlOZXh0U29uZ0luQWxidW0oKSB7CiAgICAgICAgICAgIC4uLgogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZW5kQWN0aW9uCiAgICAgIEBwYXJhbSBbYWN0aW9uXSB7U3RyaW5nfSB0aGUgYWN0aW9uIHRvIGNhbGwKICAgICAgQHBhcmFtIFtwYXJhbXNdIHsqfSBhcmd1bWVudHMgZm9yIHRoZSBhY3Rpb24KICAgICAgQHB1YmxpYwogICAgICBAZGVwcmVjYXRlZAogICAgKi8KICAgIHZhciBzZW5kQWN0aW9uID0gZnVuY3Rpb24gc2VuZEFjdGlvbihhY3Rpb24pIHsKICAgICAgKGZhbHNlICYmICEoIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkF0dGVtcHRlZCB0byBjYWxsIC5zZW5kQWN0aW9uKCkgd2l0aCB0aGUgYWN0aW9uICciICsgYWN0aW9uICsgIicgb24gdGhlIGRlc3Ryb3llZCBvYmplY3QgJyIgKyB0aGlzICsgIicuIiwgIXRoaXMuaXNEZXN0cm95aW5nICYmICF0aGlzLmlzRGVzdHJveWVkKSk7CiAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIllvdSBjYWxsZWQgIiArICgwLCBfdXRpbHMuaW5zcGVjdCkodGhpcykgKyAiLnNlbmRBY3Rpb24oIiArICh0eXBlb2YgYWN0aW9uID09PSAnc3RyaW5nJyA/ICJcIiIgKyBhY3Rpb24gKyAiXCIiIDogJycpICsgIikgYnV0IENvbXBvbmVudCNzZW5kQWN0aW9uIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgY2xvc3VyZSBhY3Rpb25zIGluc3RlYWQuIiwgZmFsc2UsIHsKICAgICAgICBpZDogJ2VtYmVyLWNvbXBvbmVudC5zZW5kLWFjdGlvbicsCiAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfZW1iZXItY29tcG9uZW50LXNlbmQtYWN0aW9uJwogICAgICB9KSk7CiAgICAgIHZhciBhY3Rpb25OYW1lOyAvLyBTZW5kIHRoZSBkZWZhdWx0IGFjdGlvbgoKICAgICAgaWYgKGFjdGlvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgYWN0aW9uID0gJ2FjdGlvbic7CiAgICAgIH0KCiAgICAgIGFjdGlvbk5hbWUgPSAoMCwgX21ldGFsLmdldCkodGhpcywgImF0dHJzLiIgKyBhY3Rpb24pIHx8ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBhY3Rpb24pOwogICAgICBhY3Rpb25OYW1lID0gdmFsaWRhdGVBY3Rpb24odGhpcywgYWN0aW9uTmFtZSk7IC8vIElmIG5vIGFjdGlvbiBuYW1lIGZvciB0aGF0IGFjdGlvbiBjb3VsZCBiZSBmb3VuZCwganVzdCBhYm9ydC4KCiAgICAgIGlmIChhY3Rpb25OYW1lID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGZvciAodmFyIF9sZW4yID0gYXJndW1lbnRzLmxlbmd0aCwgY29udGV4dHMgPSBuZXcgQXJyYXkoX2xlbjIgPiAxID8gX2xlbjIgLSAxIDogMCksIF9rZXkyID0gMTsgX2tleTIgPCBfbGVuMjsgX2tleTIrKykgewogICAgICAgIGNvbnRleHRzW19rZXkyIC0gMV0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICB9CgogICAgICBpZiAodHlwZW9mIGFjdGlvbk5hbWUgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICBhY3Rpb25OYW1lLmFwcGx5KHZvaWQgMCwgY29udGV4dHMpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMudHJpZ2dlckFjdGlvbih7CiAgICAgICAgICBhY3Rpb246IGFjdGlvbk5hbWUsCiAgICAgICAgICBhY3Rpb25Db250ZXh0OiBjb250ZXh0cwogICAgICAgIH0pOwogICAgICB9CiAgICB9OwoKICAgIHZhciB2YWxpZGF0ZUFjdGlvbiA9IGZ1bmN0aW9uIHZhbGlkYXRlQWN0aW9uKGNvbXBvbmVudCwgYWN0aW9uTmFtZSkgewogICAgICBpZiAoYWN0aW9uTmFtZSAmJiBhY3Rpb25OYW1lW19hdHRycy5NVVRBQkxFX0NFTExdKSB7CiAgICAgICAgYWN0aW9uTmFtZSA9IGFjdGlvbk5hbWUudmFsdWU7CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKGFjdGlvbk5hbWUgPT09IG51bGwgfHwgYWN0aW9uTmFtZSA9PT0gdW5kZWZpbmVkIHx8IHR5cGVvZiBhY3Rpb25OYW1lID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgZGVmYXVsdCBhY3Rpb24gd2FzIHRyaWdnZXJlZCBvbiB0aGUgY29tcG9uZW50ICIgKyBjb21wb25lbnQudG9TdHJpbmcoKSArICIsIGJ1dCB0aGUgYWN0aW9uIG5hbWUgKCIgKyBhY3Rpb25OYW1lICsgIikgd2FzIG5vdCBhIHN0cmluZy4iLCBhY3Rpb25OYW1lID09PSBudWxsIHx8IGFjdGlvbk5hbWUgPT09IHVuZGVmaW5lZCB8fCB0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGFjdGlvbk5hbWUgPT09ICdmdW5jdGlvbicpKTsKICAgICAgcmV0dXJuIGFjdGlvbk5hbWU7CiAgICB9OwoKICAgIG1peGluT2JqLnNlbmRBY3Rpb24gPSBzZW5kQWN0aW9uOwogIH0KICAvKioKICAgQGNsYXNzIEFjdGlvblN1cHBvcnQKICAgQG5hbWVzcGFjZSBFbWJlcgogICBAcHJpdmF0ZQogICovCgoKICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKG1peGluT2JqKTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvbWl4aW5zL2NoaWxkX3ZpZXdzX3N1cHBvcnQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3N5c3RlbS91dGlscyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX3V0aWxzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIGVtYmVyCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKHsKICAgIC8qKgogICAgICBBcnJheSBvZiBjaGlsZCB2aWV3cy4gWW91IHNob3VsZCBuZXZlciBlZGl0IHRoaXMgYXJyYXkgZGlyZWN0bHkuCiAgICAgICBAcHJvcGVydHkgY2hpbGRWaWV3cwogICAgICBAdHlwZSBBcnJheQogICAgICBAZGVmYXVsdCBbXQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGNoaWxkVmlld3M6ICgwLCBfbWV0YWwubmF0aXZlRGVzY0RlY29yYXRvcikoewogICAgICBjb25maWd1cmFibGU6IGZhbHNlLAogICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuICgwLCBfdXRpbHMuZ2V0Q2hpbGRWaWV3cykodGhpcyk7CiAgICAgIH0KICAgIH0pLAogICAgYXBwZW5kQ2hpbGQ6IGZ1bmN0aW9uIGFwcGVuZENoaWxkKHZpZXcpIHsKICAgICAgKDAsIF91dGlscy5hZGRDaGlsZFZpZXcpKHRoaXMsIHZpZXcpOwogICAgfQogIH0pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9taXhpbnMvY2xhc3NfbmFtZXNfc3VwcG9ydCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwsIF9kZWJ1ZykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCiAgdmFyIEVNUFRZX0FSUkFZID0gT2JqZWN0LmZyZWV6ZShbXSk7CiAgLyoqCiAgICBAY2xhc3MgQ2xhc3NOYW1lc1N1cHBvcnQKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEBwcml2YXRlCiAgKi8KCiAgdmFyIF9kZWZhdWx0ID0gX21ldGFsLk1peGluLmNyZWF0ZSh7CiAgICBjb25jYXRlbmF0ZWRQcm9wZXJ0aWVzOiBbJ2NsYXNzTmFtZXMnLCAnY2xhc3NOYW1lQmluZGluZ3MnXSwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAoZmFsc2UgJiYgISgoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JQcm9wZXJ0eSkodGhpcywgJ2NsYXNzTmFtZUJpbmRpbmdzJykgPT09IHVuZGVmaW5lZCAmJiBBcnJheS5pc0FycmF5KHRoaXMuY2xhc3NOYW1lQmluZGluZ3MpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIk9ubHkgYXJyYXlzIGFyZSBhbGxvd2VkIGZvciAnY2xhc3NOYW1lQmluZGluZ3MnIiwgKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKHRoaXMsICdjbGFzc05hbWVCaW5kaW5ncycpID09PSB1bmRlZmluZWQgJiYgQXJyYXkuaXNBcnJheSh0aGlzLmNsYXNzTmFtZUJpbmRpbmdzKSkpOwogICAgICAoZmFsc2UgJiYgISgoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JQcm9wZXJ0eSkodGhpcywgJ2NsYXNzTmFtZXMnKSA9PT0gdW5kZWZpbmVkICYmIEFycmF5LmlzQXJyYXkodGhpcy5jbGFzc05hbWVzKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJPbmx5IGFycmF5cyBvZiBzdGF0aWMgY2xhc3Mgc3RyaW5ncyBhcmUgYWxsb3dlZCBmb3IgJ2NsYXNzTmFtZXMnLiBGb3IgZHluYW1pYyBjbGFzc2VzLCB1c2UgJ2NsYXNzTmFtZUJpbmRpbmdzJy4iLCAoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JQcm9wZXJ0eSkodGhpcywgJ2NsYXNzTmFtZXMnKSA9PT0gdW5kZWZpbmVkICYmIEFycmF5LmlzQXJyYXkodGhpcy5jbGFzc05hbWVzKSkpOwogICAgfSwKCiAgICAvKioKICAgICAgU3RhbmRhcmQgQ1NTIGNsYXNzIG5hbWVzIHRvIGFwcGx5IHRvIHRoZSB2aWV3J3Mgb3V0ZXIgZWxlbWVudC4gVGhpcwogICAgICBwcm9wZXJ0eSBhdXRvbWF0aWNhbGx5IGluaGVyaXRzIGFueSBjbGFzcyBuYW1lcyBkZWZpbmVkIGJ5IHRoZSB2aWV3J3MKICAgICAgc3VwZXJjbGFzc2VzIGFzIHdlbGwuCiAgICAgICBAcHJvcGVydHkgY2xhc3NOYW1lcwogICAgICBAdHlwZSBBcnJheQogICAgICBAZGVmYXVsdCBbJ2VtYmVyLXZpZXcnXQogICAgICBAcHVibGljCiAgICAqLwogICAgY2xhc3NOYW1lczogRU1QVFlfQVJSQVksCgogICAgLyoqCiAgICAgIEEgbGlzdCBvZiBwcm9wZXJ0aWVzIG9mIHRoZSB2aWV3IHRvIGFwcGx5IGFzIGNsYXNzIG5hbWVzLiBJZiB0aGUgcHJvcGVydHkKICAgICAgaXMgYSBzdHJpbmcgdmFsdWUsIHRoZSB2YWx1ZSBvZiB0aGF0IHN0cmluZyB3aWxsIGJlIGFwcGxpZWQgYXMgYSBjbGFzcwogICAgICBuYW1lLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICAvLyBBcHBsaWVzIHRoZSAnaGlnaCcgY2xhc3MgdG8gdGhlIHZpZXcgZWxlbWVudAogICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICBjbGFzc05hbWVCaW5kaW5nczogWydwcmlvcml0eSddLAogICAgICAgIHByaW9yaXR5OiAnaGlnaCcKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgSWYgdGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSBpcyBhIEJvb2xlYW4sIHRoZSBuYW1lIG9mIHRoYXQgcHJvcGVydHkgaXMKICAgICAgYWRkZWQgYXMgYSBkYXNoZXJpemVkIGNsYXNzIG5hbWUuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIC8vIEFwcGxpZXMgdGhlICdpcy11cmdlbnQnIGNsYXNzIHRvIHRoZSB2aWV3IGVsZW1lbnQKICAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgY2xhc3NOYW1lQmluZGluZ3M6IFsnaXNVcmdlbnQnXSwKICAgICAgICBpc1VyZ2VudDogdHJ1ZQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBJZiB5b3Ugd291bGQgcHJlZmVyIHRvIHVzZSBhIGN1c3RvbSB2YWx1ZSBpbnN0ZWFkIG9mIHRoZSBkYXNoZXJpemVkCiAgICAgIHByb3BlcnR5IG5hbWUsIHlvdSBjYW4gcGFzcyBhIGJpbmRpbmcgbGlrZSB0aGlzOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICAvLyBBcHBsaWVzIHRoZSAndXJnZW50JyBjbGFzcyB0byB0aGUgdmlldyBlbGVtZW50CiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIENvbXBvbmVudC5leHRlbmQoewogICAgICAgIGNsYXNzTmFtZUJpbmRpbmdzOiBbJ2lzVXJnZW50OnVyZ2VudCddLAogICAgICAgIGlzVXJnZW50OiB0cnVlCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIElmIHlvdSB3b3VsZCBsaWtlIHRvIHNwZWNpZnkgYSBjbGFzcyB0aGF0IHNob3VsZCBvbmx5IGJlIGFkZGVkIHdoZW4gdGhlCiAgICAgIHByb3BlcnR5IGlzIGZhbHNlLCB5b3UgY2FuIGRlY2xhcmUgYSBiaW5kaW5nIGxpa2UgdGhpczoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgLy8gQXBwbGllcyB0aGUgJ2Rpc2FibGVkJyBjbGFzcyB0byB0aGUgdmlldyBlbGVtZW50CiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIENvbXBvbmVudC5leHRlbmQoewogICAgICAgIGNsYXNzTmFtZUJpbmRpbmdzOiBbJ2lzRW5hYmxlZDo6ZGlzYWJsZWQnXSwKICAgICAgICBpc0VuYWJsZWQ6IGZhbHNlCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRoaXMgbGlzdCBvZiBwcm9wZXJ0aWVzIGlzIGluaGVyaXRlZCBmcm9tIHRoZSBjb21wb25lbnQncyBzdXBlcmNsYXNzZXMgYXMgd2VsbC4KICAgICAgIEBwcm9wZXJ0eSBjbGFzc05hbWVCaW5kaW5ncwogICAgICBAdHlwZSBBcnJheQogICAgICBAZGVmYXVsdCBbXQogICAgICBAcHVibGljCiAgICAqLwogICAgY2xhc3NOYW1lQmluZGluZ3M6IEVNUFRZX0FSUkFZCiAgfSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL21peGlucy90ZXh0X3N1cHBvcnQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwsIF9ydW50aW1lLCBfZGVidWcsIF9kZXByZWNhdGVkRmVhdHVyZXMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwogIHZhciBLRVlfRVZFTlRTID0gewogICAgMTM6ICdpbnNlcnROZXdsaW5lJywKICAgIDI3OiAnY2FuY2VsJwogIH07CiAgLyoqCiAgICBgVGV4dFN1cHBvcnRgIGlzIGEgc2hhcmVkIG1peGluIHVzZWQgYnkgYm90aCBgVGV4dEZpZWxkYCBhbmQKICAgIGBUZXh0QXJlYWAuIGBUZXh0U3VwcG9ydGAgYWRkcyBhIG51bWJlciBvZiBtZXRob2RzIHRoYXQgYWxsb3cgeW91IHRvCiAgICBzcGVjaWZ5IGEgY29udHJvbGxlciBhY3Rpb24gdG8gaW52b2tlIHdoZW4gYSBjZXJ0YWluIGV2ZW50IGlzIGZpcmVkIG9uIHlvdXIKICAgIHRleHQgZmllbGQgb3IgdGV4dGFyZWEuIFRoZSBzcGVjaWZpZWQgY29udHJvbGxlciBhY3Rpb24gd291bGQgZ2V0IHRoZSBjdXJyZW50CiAgICB2YWx1ZSBvZiB0aGUgZmllbGQgcGFzc2VkIGluIGFzIHRoZSBvbmx5IGFyZ3VtZW50IHVubGVzcyB0aGUgdmFsdWUgb2YKICAgIHRoZSBmaWVsZCBpcyBlbXB0eS4gSW4gdGhhdCBjYXNlLCB0aGUgaW5zdGFuY2Ugb2YgdGhlIGZpZWxkIGl0c2VsZiBpcyBwYXNzZWQKICAgIGluIGFzIHRoZSBvbmx5IGFyZ3VtZW50LgogIAogICAgTGV0J3MgdXNlIHRoZSBwcmVzc2luZyBvZiB0aGUgZXNjYXBlIGtleSBhcyBhbiBleGFtcGxlLiBJZiB5b3Ugd2FudGVkIHRvCiAgICBpbnZva2UgYSBjb250cm9sbGVyIGFjdGlvbiB3aGVuIGEgdXNlciBwcmVzc2VzIHRoZSBlc2NhcGUga2V5IHdoaWxlIG9uIHlvdXIKICAgIGZpZWxkLCB5b3Ugd291bGQgdXNlIHRoZSBgZXNjYXBlLXByZXNzYCBhdHRyaWJ1dGUgb24geW91ciBmaWVsZCBsaWtlIHNvOgogIAogICAgYGBgaGFuZGxlYmFycwogICAgICB7eyEgYXBwbGljYXRpb24uaGJzfX0KICAKICAgICAge3tpbnB1dCBlc2NhcGUtcHJlc3M9J2FsZXJ0VXNlcid9fQogICAgYGBgCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICAgICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgICAgaW1wb3J0IENvbnRyb2xsZXIgZnJvbSAnQGVtYmVyL2NvbnRyb2xsZXInOwogICAgICAgIEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSgpOwogIAogICAgICAgIEFwcC5BcHBsaWNhdGlvbkNvbnRyb2xsZXIgPSBDb250cm9sbGVyLmV4dGVuZCh7CiAgICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICAgIGFsZXJ0VXNlcjogZnVuY3Rpb24gKCBjdXJyZW50VmFsdWUgKSB7CiAgICAgICAgICAgICAgYWxlcnQoICdlc2NhcGUgcHJlc3NlZCwgY3VycmVudCB2YWx1ZTogJyArIGN1cnJlbnRWYWx1ZSApOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICBgYGAKICAKICAgIFRoZSBmb2xsb3dpbmcgY2hhcnQgaXMgYSB2aXN1YWwgcmVwcmVzZW50YXRpb24gb2Ygd2hhdCB0YWtlcyBwbGFjZSB3aGVuIHRoZQogICAgZXNjYXBlIGtleSBpcyBwcmVzc2VkIGluIHRoaXMgc2NlbmFyaW86CiAgCiAgICBgYGAKICAgIFRoZSBUZW1wbGF0ZQogICAgKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICB8IGVzY2FwZS1wcmVzcz0nYWxlcnRVc2VyJyAgfAogICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgVGV4dFN1cHBvcnQgTWl4aW4KICAgICstLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rICAgICAgICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKwogICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBjYW5jZWwgbWV0aG9kICAgICAgICAgICAgICAgICB8CiAgICAgICAgIHwgICAgICBlc2NhcGUgYnV0dG9uIHByZXNzZWQgICAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKICAgICAgICAgKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+IHwgY2hlY2tzIGZvciB0aGUgYGVzY2FwZS1wcmVzc2AgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBhdHRyaWJ1dGUgYW5kIHB1bGxzIG91dCB0aGUgICB8CiAgICAgICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKyB8IGBhbGVydFVzZXJgIHZhbHVlICAgICAgICAgICAgIHwKICAgICAgICAgfCAgICAgYWN0aW9uIG5hbWUgJ2FsZXJ0VXNlcicgICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKwogICAgICAgICB8ICAgICBzZW50IHRvIGNvbnRyb2xsZXIKICAgICAgICAgdgogICAgQ29udHJvbGxlcgogICAgKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSArCiAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKICAgIHwgIGFjdGlvbnM6IHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAogICAgfCAgICAgYWxlcnRVc2VyOiBmdW5jdGlvbiggY3VycmVudFZhbHVlICl7ICB8CiAgICB8ICAgICAgIGFsZXJ0KCAndGhlIGVzYyBrZXkgd2FzIHByZXNzZWQhJyApIHwKICAgIHwgICAgIH0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAogICAgfCAgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CiAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKwogICAgYGBgCiAgCiAgICBIZXJlIGFyZSB0aGUgZXZlbnRzIHRoYXQgd2UgY3VycmVudGx5IHN1cHBvcnQgYWxvbmcgd2l0aCB0aGUgbmFtZSBvZiB0aGUKICAgIGF0dHJpYnV0ZSB5b3Ugd291bGQgbmVlZCB0byB1c2Ugb24geW91ciBmaWVsZC4gVG8gcmVpdGVyYXRlLCB5b3Ugd291bGQgdXNlIHRoZQogICAgYXR0cmlidXRlIG5hbWUgbGlrZSBzbzoKICAKICAgIGBgYGhhbmRsZWJhcnMKICAgICAge3tpbnB1dCBhdHRyaWJ1dGUtbmFtZT0nY29udHJvbGxlckFjdGlvbid9fQogICAgYGBgCiAgCiAgICBgYGAKICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tKwogICAgfCAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICB8CiAgICB8IGV2ZW50ICAgICAgICAgICAgICB8IGF0dHJpYnV0ZSBuYW1lIHwKICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tKwogICAgfCBuZXcgbGluZSBpbnNlcnRlZCAgfCBpbnNlcnQtbmV3bGluZSB8CiAgICB8ICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgIHwKICAgIHwgZW50ZXIga2V5IHByZXNzZWQgIHwgZW50ZXIgICAgICAgICAgfAogICAgfCAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICB8CiAgICB8IGNhbmNlbCBrZXkgcHJlc3NlZCB8IGVzY2FwZS1wcmVzcyAgIHwKICAgIHwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgfAogICAgfCBmb2N1c2luICAgICAgICAgICAgfCBmb2N1cy1pbiAgICAgICB8CiAgICB8ICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgIHwKICAgIHwgZm9jdXNvdXQgICAgICAgICAgIHwgZm9jdXMtb3V0ICAgICAgfAogICAgfCAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICB8CiAgICB8IGtleXByZXNzICAgICAgICAgICB8IGtleS1wcmVzcyAgICAgIHwKICAgIHwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgfAogICAgfCBrZXl1cCAgICAgICAgICAgICAgfCBrZXktdXAgICAgICAgICB8CiAgICB8ICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgIHwKICAgIHwga2V5ZG93biAgICAgICAgICAgIHwga2V5LWRvd24gICAgICAgfAogICAgKy0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0rCiAgICBgYGAKICAKICAgIEBjbGFzcyBUZXh0U3VwcG9ydAogICAgQG5hbWVzcGFjZSBFbWJlcgogICAgQHVzZXMgRW1iZXIuVGFyZ2V0QWN0aW9uU3VwcG9ydAogICAgQGV4dGVuZHMgTWl4aW4KICAgIEBwcml2YXRlCiAgKi8KCiAgdmFyIF9kZWZhdWx0ID0gX21ldGFsLk1peGluLmNyZWF0ZShfcnVudGltZS5UYXJnZXRBY3Rpb25TdXBwb3J0LCB7CiAgICB2YWx1ZTogJycsCiAgICBhdHRyaWJ1dGVCaW5kaW5nczogWydhdXRvY2FwaXRhbGl6ZScsICdhdXRvY29ycmVjdCcsICdhdXRvZm9jdXMnLCAnZGlzYWJsZWQnLCAnZm9ybScsICdtYXhsZW5ndGgnLCAnbWlubGVuZ3RoJywgJ3BsYWNlaG9sZGVyJywgJ3JlYWRvbmx5JywgJ3JlcXVpcmVkJywgJ3NlbGVjdGlvbkRpcmVjdGlvbicsICdzcGVsbGNoZWNrJywgJ3RhYmluZGV4JywgJ3RpdGxlJ10sCiAgICBwbGFjZWhvbGRlcjogbnVsbCwKICAgIGRpc2FibGVkOiBmYWxzZSwKICAgIG1heGxlbmd0aDogbnVsbCwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzLm9uKCdwYXN0ZScsIHRoaXMsIHRoaXMuX2VsZW1lbnRWYWx1ZURpZENoYW5nZSk7CiAgICAgIHRoaXMub24oJ2N1dCcsIHRoaXMsIHRoaXMuX2VsZW1lbnRWYWx1ZURpZENoYW5nZSk7CiAgICAgIHRoaXMub24oJ2lucHV0JywgdGhpcywgdGhpcy5fZWxlbWVudFZhbHVlRGlkQ2hhbmdlKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFdoZXRoZXIgdGhlIGBrZXlVcGAgZXZlbnQgdGhhdCB0cmlnZ2VycyBhbiBgYWN0aW9uYCB0byBiZSBzZW50IGNvbnRpbnVlcwogICAgICBwcm9wYWdhdGluZyB0byBvdGhlciB2aWV3cy4KICAgICAgIEJ5IGRlZmF1bHQsIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyB0aGUgcmV0dXJuIGtleSBvbiB0aGVpciBrZXlib2FyZCBhbmQKICAgICAgdGhlIHRleHQgZmllbGQgaGFzIGFuIGBhY3Rpb25gIHNldCwgdGhlIGFjdGlvbiB3aWxsIGJlIHNlbnQgdG8gdGhlIHZpZXcncwogICAgICBjb250cm9sbGVyIGFuZCB0aGUga2V5IGV2ZW50IHdpbGwgc3RvcCBwcm9wYWdhdGluZy4KICAgICAgIElmIHlvdSB3b3VsZCBsaWtlIHBhcmVudCB2aWV3cyB0byByZWNlaXZlIHRoZSBga2V5VXBgIGV2ZW50IGV2ZW4gYWZ0ZXIgYW4KICAgICAgYWN0aW9uIGhhcyBiZWVuIGRpc3BhdGNoZWQsIHNldCBgYnViYmxlc2AgdG8gdHJ1ZS4KICAgICAgIEBwcm9wZXJ0eSBidWJibGVzCiAgICAgIEB0eXBlIEJvb2xlYW4KICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgQHByaXZhdGUKICAgICovCiAgICBidWJibGVzOiBmYWxzZSwKICAgIGludGVycHJldEtleUV2ZW50czogZnVuY3Rpb24gaW50ZXJwcmV0S2V5RXZlbnRzKGV2ZW50KSB7CiAgICAgIHZhciBtYXAgPSBLRVlfRVZFTlRTOwogICAgICB2YXIgbWV0aG9kID0gbWFwW2V2ZW50LmtleUNvZGVdOwoKICAgICAgdGhpcy5fZWxlbWVudFZhbHVlRGlkQ2hhbmdlKCk7CgogICAgICBpZiAobWV0aG9kKSB7CiAgICAgICAgcmV0dXJuIHRoaXNbbWV0aG9kXShldmVudCk7CiAgICAgIH0KICAgIH0sCiAgICBfZWxlbWVudFZhbHVlRGlkQ2hhbmdlOiBmdW5jdGlvbiBfZWxlbWVudFZhbHVlRGlkQ2hhbmdlKCkgewogICAgICAoMCwgX21ldGFsLnNldCkodGhpcywgJ3ZhbHVlJywgdGhpcy5lbGVtZW50LnZhbHVlKTsKICAgIH0sCiAgICBjaGFuZ2U6IGZ1bmN0aW9uIGNoYW5nZShldmVudCkgewogICAgICB0aGlzLl9lbGVtZW50VmFsdWVEaWRDaGFuZ2UoZXZlbnQpOwogICAgfSwKCiAgICAvKioKICAgICAgQWxsb3dzIHlvdSB0byBzcGVjaWZ5IGEgY29udHJvbGxlciBhY3Rpb24gdG8gaW52b2tlIHdoZW4gZWl0aGVyIHRoZSBgZW50ZXJgCiAgICAgIGtleSBpcyBwcmVzc2VkIG9yLCBpbiB0aGUgY2FzZSBvZiB0aGUgZmllbGQgYmVpbmcgYSB0ZXh0YXJlYSwgd2hlbiBhIG5ld2xpbmUKICAgICAgaXMgaW5zZXJ0ZWQuIFRvIHVzZSB0aGlzIG1ldGhvZCwgZ2l2ZSB5b3VyIGZpZWxkIGFuIGBpbnNlcnQtbmV3bGluZWAKICAgICAgYXR0cmlidXRlLiBUaGUgdmFsdWUgb2YgdGhhdCBhdHRyaWJ1dGUgc2hvdWxkIGJlIHRoZSBuYW1lIG9mIHRoZSBhY3Rpb24KICAgICAgaW4geW91ciBjb250cm9sbGVyIHRoYXQgeW91IHdpc2ggdG8gaW52b2tlLgogICAgICAgRm9yIGFuIGV4YW1wbGUgb24gaG93IHRvIHVzZSB0aGUgYGluc2VydC1uZXdsaW5lYCBhdHRyaWJ1dGUsIHBsZWFzZQogICAgICByZWZlcmVuY2UgdGhlIGV4YW1wbGUgbmVhciB0aGUgdG9wIG9mIHRoaXMgZmlsZS4KICAgICAgIEBtZXRob2QgaW5zZXJ0TmV3bGluZQogICAgICBAcGFyYW0ge0V2ZW50fSBldmVudAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGluc2VydE5ld2xpbmU6IGZ1bmN0aW9uIGluc2VydE5ld2xpbmUoZXZlbnQpIHsKICAgICAgc2VuZEFjdGlvbignZW50ZXInLCB0aGlzLCBldmVudCk7CiAgICAgIHNlbmRBY3Rpb24oJ2luc2VydC1uZXdsaW5lJywgdGhpcywgZXZlbnQpOwogICAgfSwKCiAgICAvKioKICAgICAgQWxsb3dzIHlvdSB0byBzcGVjaWZ5IGEgY29udHJvbGxlciBhY3Rpb24gdG8gaW52b2tlIHdoZW4gdGhlIGVzY2FwZSBidXR0b24KICAgICAgaXMgcHJlc3NlZC4gVG8gdXNlIHRoaXMgbWV0aG9kLCBnaXZlIHlvdXIgZmllbGQgYW4gYGVzY2FwZS1wcmVzc2AKICAgICAgYXR0cmlidXRlLiBUaGUgdmFsdWUgb2YgdGhhdCBhdHRyaWJ1dGUgc2hvdWxkIGJlIHRoZSBuYW1lIG9mIHRoZSBhY3Rpb24KICAgICAgaW4geW91ciBjb250cm9sbGVyIHRoYXQgeW91IHdpc2ggdG8gaW52b2tlLgogICAgICAgRm9yIGFuIGV4YW1wbGUgb24gaG93IHRvIHVzZSB0aGUgYGVzY2FwZS1wcmVzc2AgYXR0cmlidXRlLCBwbGVhc2UgcmVmZXJlbmNlCiAgICAgIHRoZSBleGFtcGxlIG5lYXIgdGhlIHRvcCBvZiB0aGlzIGZpbGUuCiAgICAgICBAbWV0aG9kIGNhbmNlbAogICAgICBAcGFyYW0ge0V2ZW50fSBldmVudAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGNhbmNlbDogZnVuY3Rpb24gY2FuY2VsKGV2ZW50KSB7CiAgICAgIHNlbmRBY3Rpb24oJ2VzY2FwZS1wcmVzcycsIHRoaXMsIGV2ZW50KTsKICAgIH0sCgogICAgLyoqCiAgICAgIEFsbG93cyB5b3UgdG8gc3BlY2lmeSBhIGNvbnRyb2xsZXIgYWN0aW9uIHRvIGludm9rZSB3aGVuIGEgZmllbGQgcmVjZWl2ZXMKICAgICAgZm9jdXMuIFRvIHVzZSB0aGlzIG1ldGhvZCwgZ2l2ZSB5b3VyIGZpZWxkIGEgYGZvY3VzLWluYCBhdHRyaWJ1dGUuIFRoZSB2YWx1ZQogICAgICBvZiB0aGF0IGF0dHJpYnV0ZSBzaG91bGQgYmUgdGhlIG5hbWUgb2YgdGhlIGFjdGlvbiBpbiB5b3VyIGNvbnRyb2xsZXIKICAgICAgdGhhdCB5b3Ugd2lzaCB0byBpbnZva2UuCiAgICAgICBGb3IgYW4gZXhhbXBsZSBvbiBob3cgdG8gdXNlIHRoZSBgZm9jdXMtaW5gIGF0dHJpYnV0ZSwgcGxlYXNlIHJlZmVyZW5jZSB0aGUKICAgICAgZXhhbXBsZSBuZWFyIHRoZSB0b3Agb2YgdGhpcyBmaWxlLgogICAgICAgQG1ldGhvZCBmb2N1c0luCiAgICAgIEBwYXJhbSB7RXZlbnR9IGV2ZW50CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgZm9jdXNJbjogZnVuY3Rpb24gZm9jdXNJbihldmVudCkgewogICAgICBzZW5kQWN0aW9uKCdmb2N1cy1pbicsIHRoaXMsIGV2ZW50KTsKICAgIH0sCgogICAgLyoqCiAgICAgIEFsbG93cyB5b3UgdG8gc3BlY2lmeSBhIGNvbnRyb2xsZXIgYWN0aW9uIHRvIGludm9rZSB3aGVuIGEgZmllbGQgbG9zZXMKICAgICAgZm9jdXMuIFRvIHVzZSB0aGlzIG1ldGhvZCwgZ2l2ZSB5b3VyIGZpZWxkIGEgYGZvY3VzLW91dGAgYXR0cmlidXRlLiBUaGUgdmFsdWUKICAgICAgb2YgdGhhdCBhdHRyaWJ1dGUgc2hvdWxkIGJlIHRoZSBuYW1lIG9mIHRoZSBhY3Rpb24gaW4geW91ciBjb250cm9sbGVyCiAgICAgIHRoYXQgeW91IHdpc2ggdG8gaW52b2tlLgogICAgICAgRm9yIGFuIGV4YW1wbGUgb24gaG93IHRvIHVzZSB0aGUgYGZvY3VzLW91dGAgYXR0cmlidXRlLCBwbGVhc2UgcmVmZXJlbmNlIHRoZQogICAgICBleGFtcGxlIG5lYXIgdGhlIHRvcCBvZiB0aGlzIGZpbGUuCiAgICAgICBAbWV0aG9kIGZvY3VzT3V0CiAgICAgIEBwYXJhbSB7RXZlbnR9IGV2ZW50CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgZm9jdXNPdXQ6IGZ1bmN0aW9uIGZvY3VzT3V0KGV2ZW50KSB7CiAgICAgIHRoaXMuX2VsZW1lbnRWYWx1ZURpZENoYW5nZShldmVudCk7CgogICAgICBzZW5kQWN0aW9uKCdmb2N1cy1vdXQnLCB0aGlzLCBldmVudCk7CiAgICB9LAoKICAgIC8qKgogICAgICBBbGxvd3MgeW91IHRvIHNwZWNpZnkgYSBjb250cm9sbGVyIGFjdGlvbiB0byBpbnZva2Ugd2hlbiBhIGtleSBpcyBwcmVzc2VkLgogICAgICBUbyB1c2UgdGhpcyBtZXRob2QsIGdpdmUgeW91ciBmaWVsZCBhIGBrZXktcHJlc3NgIGF0dHJpYnV0ZS4gVGhlIHZhbHVlIG9mCiAgICAgIHRoYXQgYXR0cmlidXRlIHNob3VsZCBiZSB0aGUgbmFtZSBvZiB0aGUgYWN0aW9uIGluIHlvdXIgY29udHJvbGxlciB5b3UKICAgICAgdGhhdCB3aXNoIHRvIGludm9rZS4KICAgICAgIEZvciBhbiBleGFtcGxlIG9uIGhvdyB0byB1c2UgdGhlIGBrZXktcHJlc3NgIGF0dHJpYnV0ZSwgcGxlYXNlIHJlZmVyZW5jZSB0aGUKICAgICAgZXhhbXBsZSBuZWFyIHRoZSB0b3Agb2YgdGhpcyBmaWxlLgogICAgICAgQG1ldGhvZCBrZXlQcmVzcwogICAgICBAcGFyYW0ge0V2ZW50fSBldmVudAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGtleVByZXNzOiBmdW5jdGlvbiBrZXlQcmVzcyhldmVudCkgewogICAgICBzZW5kQWN0aW9uKCdrZXktcHJlc3MnLCB0aGlzLCBldmVudCk7CiAgICB9LAoKICAgIC8qKgogICAgICBBbGxvd3MgeW91IHRvIHNwZWNpZnkgYSBjb250cm9sbGVyIGFjdGlvbiB0byBpbnZva2Ugd2hlbiBhIGtleS11cCBldmVudCBpcwogICAgICBmaXJlZC4gVG8gdXNlIHRoaXMgbWV0aG9kLCBnaXZlIHlvdXIgZmllbGQgYSBga2V5LXVwYCBhdHRyaWJ1dGUuIFRoZSB2YWx1ZQogICAgICBvZiB0aGF0IGF0dHJpYnV0ZSBzaG91bGQgYmUgdGhlIG5hbWUgb2YgdGhlIGFjdGlvbiBpbiB5b3VyIGNvbnRyb2xsZXIKICAgICAgdGhhdCB5b3Ugd2lzaCB0byBpbnZva2UuCiAgICAgICBGb3IgYW4gZXhhbXBsZSBvbiBob3cgdG8gdXNlIHRoZSBga2V5LXVwYCBhdHRyaWJ1dGUsIHBsZWFzZSByZWZlcmVuY2UgdGhlCiAgICAgIGV4YW1wbGUgbmVhciB0aGUgdG9wIG9mIHRoaXMgZmlsZS4KICAgICAgIEBtZXRob2Qga2V5VXAKICAgICAgQHBhcmFtIHtFdmVudH0gZXZlbnQKICAgICAgQHByaXZhdGUKICAgICovCiAgICBrZXlVcDogZnVuY3Rpb24ga2V5VXAoZXZlbnQpIHsKICAgICAgdGhpcy5pbnRlcnByZXRLZXlFdmVudHMoZXZlbnQpOwogICAgICBzZW5kQWN0aW9uKCdrZXktdXAnLCB0aGlzLCBldmVudCk7CiAgICB9LAoKICAgIC8qKgogICAgICBBbGxvd3MgeW91IHRvIHNwZWNpZnkgYSBjb250cm9sbGVyIGFjdGlvbiB0byBpbnZva2Ugd2hlbiBhIGtleS1kb3duIGV2ZW50IGlzCiAgICAgIGZpcmVkLiBUbyB1c2UgdGhpcyBtZXRob2QsIGdpdmUgeW91ciBmaWVsZCBhIGBrZXktZG93bmAgYXR0cmlidXRlLiBUaGUgdmFsdWUKICAgICAgb2YgdGhhdCBhdHRyaWJ1dGUgc2hvdWxkIGJlIHRoZSBuYW1lIG9mIHRoZSBhY3Rpb24gaW4geW91ciBjb250cm9sbGVyIHRoYXQKICAgICAgeW91IHdpc2ggdG8gaW52b2tlLgogICAgICAgRm9yIGFuIGV4YW1wbGUgb24gaG93IHRvIHVzZSB0aGUgYGtleS1kb3duYCBhdHRyaWJ1dGUsIHBsZWFzZSByZWZlcmVuY2UgdGhlCiAgICAgIGV4YW1wbGUgbmVhciB0aGUgdG9wIG9mIHRoaXMgZmlsZS4KICAgICAgIEBtZXRob2Qga2V5RG93bgogICAgICBAcGFyYW0ge0V2ZW50fSBldmVudAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGtleURvd246IGZ1bmN0aW9uIGtleURvd24oZXZlbnQpIHsKICAgICAgc2VuZEFjdGlvbigna2V5LWRvd24nLCB0aGlzLCBldmVudCk7CiAgICB9CiAgfSk7IC8vIEluIHByaW5jaXBsZSwgdGhpcyBzaG91bGRuJ3QgYmUgbmVjZXNzYXJ5LCBidXQgdGhlIGxlZ2FjeQogIC8vIHNlbmRBY3Rpb24gc2VtYW50aWNzIGZvciBUZXh0RmllbGQgYXJlIGRpZmZlcmVudCBmcm9tCiAgLy8gdGhlIGNvbXBvbmVudCBzZW1hbnRpY3Mgc28gdGhpcyBtZXRob2Qgbm9ybWFsaXplcyB0aGVtLgoKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OwoKICBmdW5jdGlvbiBzZW5kQWN0aW9uKGV2ZW50TmFtZSwgdmlldywgZXZlbnQpIHsKICAgIHZhciBhY3Rpb25OYW1lID0gKDAsIF9tZXRhbC5nZXQpKHZpZXcsICJhdHRycy4iICsgZXZlbnROYW1lKSB8fCAoMCwgX21ldGFsLmdldCkodmlldywgZXZlbnROYW1lKTsKICAgIHZhciB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KSh2aWV3LCAndmFsdWUnKTsKCiAgICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5TRU5EX0FDVElPTiAmJiB0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ3N0cmluZycpIHsKICAgICAgdmFyIG1lc3NhZ2UgPSB0cnVlCiAgICAgIC8qIEVNQkVSX0dMSU1NRVJfQU5HTEVfQlJBQ0tFVF9CVUlMVF9JTlMgKi8KICAgICAgPyAiUGFzc2luZyBhY3Rpb25zIHRvIGNvbXBvbmVudHMgYXMgc3RyaW5ncyAobGlrZSBgPElucHV0IEAiICsgZXZlbnROYW1lICsgIj1cIiIgKyBhY3Rpb25OYW1lICsgIlwiIC8+YCkgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBjbG9zdXJlIGFjdGlvbnMgaW5zdGVhZCAoYDxJbnB1dCBAIiArIGV2ZW50TmFtZSArICI9e3thY3Rpb24gXCIiICsgYWN0aW9uTmFtZSArICJcIn19IC8+YCkuIiA6ICJQYXNzaW5nIGFjdGlvbnMgdG8gY29tcG9uZW50cyBhcyBzdHJpbmdzIChsaWtlIGB7e2lucHV0ICIgKyBldmVudE5hbWUgKyAiPVwiIiArIGFjdGlvbk5hbWUgKyAiXCJ9fWApIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgY2xvc3VyZSBhY3Rpb25zIGluc3RlYWQgKGB7e2lucHV0ICIgKyBldmVudE5hbWUgKyAiPShhY3Rpb24gXCIiICsgYWN0aW9uTmFtZSArICJcIil9fWApLiI7CiAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkobWVzc2FnZSwgZmFsc2UsIHsKICAgICAgICBpZDogJ2VtYmVyLWNvbXBvbmVudC5zZW5kLWFjdGlvbicsCiAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfZW1iZXItY29tcG9uZW50LXNlbmQtYWN0aW9uJwogICAgICB9KSk7CiAgICAgIHZpZXcudHJpZ2dlckFjdGlvbih7CiAgICAgICAgYWN0aW9uOiBhY3Rpb25OYW1lLAogICAgICAgIGFjdGlvbkNvbnRleHQ6IFt2YWx1ZSwgZXZlbnRdCiAgICAgIH0pOwogICAgfSBlbHNlIGlmICh0eXBlb2YgYWN0aW9uTmFtZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICBhY3Rpb25OYW1lKHZhbHVlLCBldmVudCk7CiAgICB9CgogICAgaWYgKGFjdGlvbk5hbWUgJiYgISgwLCBfbWV0YWwuZ2V0KSh2aWV3LCAnYnViYmxlcycpKSB7CiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOwogICAgfQogIH0KfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL21peGlucy92aWV3X3N0YXRlX3N1cHBvcnQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwogIHZhciBfZGVmYXVsdCA9IF9tZXRhbC5NaXhpbi5jcmVhdGUoewogICAgX3RyYW5zaXRpb25UbzogZnVuY3Rpb24gX3RyYW5zaXRpb25UbyhzdGF0ZSkgewogICAgICB2YXIgcHJpb3JTdGF0ZSA9IHRoaXMuX2N1cnJlbnRTdGF0ZTsKICAgICAgdmFyIGN1cnJlbnRTdGF0ZSA9IHRoaXMuX2N1cnJlbnRTdGF0ZSA9IHRoaXMuX3N0YXRlc1tzdGF0ZV07CiAgICAgIHRoaXMuX3N0YXRlID0gc3RhdGU7CgogICAgICBpZiAocHJpb3JTdGF0ZSAmJiBwcmlvclN0YXRlLmV4aXQpIHsKICAgICAgICBwcmlvclN0YXRlLmV4aXQodGhpcyk7CiAgICAgIH0KCiAgICAgIGlmIChjdXJyZW50U3RhdGUuZW50ZXIpIHsKICAgICAgICBjdXJyZW50U3RhdGUuZW50ZXIodGhpcyk7CiAgICAgIH0KICAgIH0KICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvbWl4aW5zL3ZpZXdfc3VwcG9ydCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyLy1pbnRlcm5hbHMvYnJvd3Nlci1lbnZpcm9ubWVudCIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL3V0aWxzIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vanF1ZXJ5IiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3V0aWxzLCBfbWV0YWwsIF9kZWJ1ZywgX2Jyb3dzZXJFbnZpcm9ubWVudCwgX3V0aWxzMiwgX2pxdWVyeSwgX2RlcHJlY2F0ZWRGZWF0dXJlcykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgZnVuY3Rpb24gSygpIHsKICAgIHJldHVybiB0aGlzOwogIH0KCiAgdmFyIG1peGluID0gewogICAgLyoqCiAgICAgQSBsaXN0IG9mIHByb3BlcnRpZXMgb2YgdGhlIHZpZXcgdG8gYXBwbHkgYXMgYXR0cmlidXRlcy4gSWYgdGhlIHByb3BlcnR5CiAgICAgaXMgYSBzdHJpbmcgdmFsdWUsIHRoZSB2YWx1ZSBvZiB0aGF0IHN0cmluZyB3aWxsIGJlIGFwcGxpZWQgYXMgdGhlIHZhbHVlCiAgICAgZm9yIGFuIGF0dHJpYnV0ZSBvZiB0aGUgcHJvcGVydHkncyBuYW1lLgogICAgICBUaGUgZm9sbG93aW5nIGV4YW1wbGUgY3JlYXRlcyBhIHRhZyBsaWtlIGA8ZGl2IHByaW9yaXR5PSJoaWdoIiAvPmAuCiAgICAgIGBgYGFwcC9jb21wb25lbnRzL215LWNvbXBvbmVudC5qcwogICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IENvbXBvbmVudC5leHRlbmQoewogICAgICAgIGF0dHJpYnV0ZUJpbmRpbmdzOiBbJ3ByaW9yaXR5J10sCiAgICAgICAgcHJpb3JpdHk6ICdoaWdoJwogICAgICB9KTsKICAgICBgYGAKICAgICAgSWYgdGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSBpcyBhIEJvb2xlYW4sIHRoZSBhdHRyaWJ1dGUgaXMgdHJlYXRlZCBhcwogICAgIGFuIEhUTUwgQm9vbGVhbiBhdHRyaWJ1dGUuIEl0IHdpbGwgYmUgcHJlc2VudCBpZiB0aGUgcHJvcGVydHkgaXMgYHRydWVgCiAgICAgYW5kIG9taXR0ZWQgaWYgdGhlIHByb3BlcnR5IGlzIGBmYWxzZWAuCiAgICAgIFRoZSBmb2xsb3dpbmcgZXhhbXBsZSBjcmVhdGVzIG1hcmt1cCBsaWtlIGA8ZGl2IHZpc2libGUgLz5gLgogICAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICBhdHRyaWJ1dGVCaW5kaW5nczogWyd2aXNpYmxlJ10sCiAgICAgICAgdmlzaWJsZTogdHJ1ZQogICAgICB9KTsKICAgICBgYGAKICAgICAgSWYgeW91IHdvdWxkIHByZWZlciB0byB1c2UgYSBjdXN0b20gdmFsdWUgaW5zdGVhZCBvZiB0aGUgcHJvcGVydHkgbmFtZSwKICAgICB5b3UgY2FuIGNyZWF0ZSB0aGUgc2FtZSBtYXJrdXAgYXMgdGhlIGxhc3QgZXhhbXBsZSB3aXRoIGEgYmluZGluZyBsaWtlCiAgICAgdGhpczoKICAgICAgYGBgYXBwL2NvbXBvbmVudHMvbXktY29tcG9uZW50LmpzCiAgICAgaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgYXR0cmlidXRlQmluZGluZ3M6IFsnaXNWaXNpYmxlOnZpc2libGUnXSwKICAgICAgICBpc1Zpc2libGU6IHRydWUKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIFRoaXMgbGlzdCBvZiBhdHRyaWJ1dGVzIGlzIGluaGVyaXRlZCBmcm9tIHRoZSBjb21wb25lbnQncyBzdXBlcmNsYXNzZXMsCiAgICAgYXMgd2VsbC4KICAgICAgQHByb3BlcnR5IGF0dHJpYnV0ZUJpbmRpbmdzCiAgICAgQHR5cGUgQXJyYXkKICAgICBAZGVmYXVsdCBbXQogICAgIEBwdWJsaWMKICAgICAqLwogICAgY29uY2F0ZW5hdGVkUHJvcGVydGllczogWydhdHRyaWJ1dGVCaW5kaW5ncyddLAogICAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogICAgLy8gVEVNUExBVEUgU1VQUE9SVAogICAgLy8KCiAgICAvKioKICAgICBSZXR1cm4gdGhlIG5lYXJlc3QgYW5jZXN0b3IgdGhhdCBpcyBhbiBpbnN0YW5jZSBvZiB0aGUgcHJvdmlkZWQKICAgICBjbGFzcyBvciBtaXhpbi4KICAgICAgQG1ldGhvZCBuZWFyZXN0T2ZUeXBlCiAgICAgQHBhcmFtIHtDbGFzcyxNaXhpbn0ga2xhc3MgU3ViY2xhc3Mgb2YgRW1iZXIuVmlldyAob3IgRW1iZXIuVmlldyBpdHNlbGYpLAogICAgIG9yIGFuIGluc3RhbmNlIG9mIE1peGluLgogICAgIEByZXR1cm4gRW1iZXIuVmlldwogICAgIEBkZXByZWNhdGVkIHVzZSBgeWllbGRgIGFuZCBjb250ZXh0dWFsIGNvbXBvbmVudHMgZm9yIGNvbXBvc2l0aW9uIGluc3RlYWQuCiAgICAgQHByaXZhdGUKICAgICAqLwogICAgbmVhcmVzdE9mVHlwZTogZnVuY3Rpb24gbmVhcmVzdE9mVHlwZShrbGFzcykgewogICAgICB2YXIgdmlldyA9IHRoaXMucGFyZW50VmlldzsKICAgICAgdmFyIGlzT2ZUeXBlID0ga2xhc3MgaW5zdGFuY2VvZiBfbWV0YWwuTWl4aW4gPyBmdW5jdGlvbiAodmlldykgewogICAgICAgIHJldHVybiBrbGFzcy5kZXRlY3Qodmlldyk7CiAgICAgIH0gOiBmdW5jdGlvbiAodmlldykgewogICAgICAgIHJldHVybiBrbGFzcy5kZXRlY3Qodmlldy5jb25zdHJ1Y3Rvcik7CiAgICAgIH07CgogICAgICB3aGlsZSAodmlldykgewogICAgICAgIGlmIChpc09mVHlwZSh2aWV3KSkgewogICAgICAgICAgcmV0dXJuIHZpZXc7CiAgICAgICAgfQoKICAgICAgICB2aWV3ID0gdmlldy5wYXJlbnRWaWV3OwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgIFJldHVybiB0aGUgbmVhcmVzdCBhbmNlc3RvciB0aGF0IGhhcyBhIGdpdmVuIHByb3BlcnR5LgogICAgICBAbWV0aG9kIG5lYXJlc3RXaXRoUHJvcGVydHkKICAgICBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHkgQSBwcm9wZXJ0eSBuYW1lCiAgICAgQHJldHVybiBFbWJlci5WaWV3CiAgICAgQGRlcHJlY2F0ZWQgdXNlIGB5aWVsZGAgYW5kIGNvbnRleHR1YWwgY29tcG9uZW50cyBmb3IgY29tcG9zaXRpb24gaW5zdGVhZC4KICAgICBAcHJpdmF0ZQogICAgICovCiAgICBuZWFyZXN0V2l0aFByb3BlcnR5OiBmdW5jdGlvbiBuZWFyZXN0V2l0aFByb3BlcnR5KHByb3BlcnR5KSB7CiAgICAgIHZhciB2aWV3ID0gdGhpcy5wYXJlbnRWaWV3OwoKICAgICAgd2hpbGUgKHZpZXcpIHsKICAgICAgICBpZiAocHJvcGVydHkgaW4gdmlldykgewogICAgICAgICAgcmV0dXJuIHZpZXc7CiAgICAgICAgfQoKICAgICAgICB2aWV3ID0gdmlldy5wYXJlbnRWaWV3OwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgIFJlbmRlcnMgdGhlIHZpZXcgYWdhaW4uIFRoaXMgd2lsbCB3b3JrIHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGUKICAgICB2aWV3IGlzIGFscmVhZHkgaW4gdGhlIERPTSBvciBub3QuIElmIHRoZSB2aWV3IGlzIGluIHRoZSBET00sIHRoZQogICAgIHJlbmRlcmluZyBwcm9jZXNzIHdpbGwgYmUgZGVmZXJyZWQgdG8gZ2l2ZSBiaW5kaW5ncyBhIGNoYW5jZQogICAgIHRvIHN5bmNocm9uaXplLgogICAgICBJZiBjaGlsZHJlbiB3ZXJlIGFkZGVkIGR1cmluZyB0aGUgcmVuZGVyaW5nIHByb2Nlc3MgdXNpbmcgYGFwcGVuZENoaWxkYCwKICAgICBgcmVyZW5kZXJgIHdpbGwgcmVtb3ZlIHRoZW0sIGJlY2F1c2UgdGhleSB3aWxsIGJlIGFkZGVkIGFnYWluCiAgICAgaWYgbmVlZGVkIGJ5IHRoZSBuZXh0IGByZW5kZXJgLgogICAgICBJbiBnZW5lcmFsLCBpZiB0aGUgZGlzcGxheSBvZiB5b3VyIHZpZXcgY2hhbmdlcywgeW91IHNob3VsZCBtb2RpZnkKICAgICB0aGUgRE9NIGVsZW1lbnQgZGlyZWN0bHkgaW5zdGVhZCBvZiBtYW51YWxseSBjYWxsaW5nIGByZXJlbmRlcmAsIHdoaWNoIGNhbgogICAgIGJlIHNsb3cuCiAgICAgIEBtZXRob2QgcmVyZW5kZXIKICAgICBAcHVibGljCiAgICAgKi8KICAgIHJlcmVuZGVyOiBmdW5jdGlvbiByZXJlbmRlcigpIHsKICAgICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRTdGF0ZS5yZXJlbmRlcih0aGlzKTsKICAgIH0sCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uCiAgICAvLyBFTEVNRU5UIFNVUFBPUlQKICAgIC8vCgogICAgLyoqCiAgICAgUmV0dXJucyB0aGUgY3VycmVudCBET00gZWxlbWVudCBmb3IgdGhlIHZpZXcuCiAgICAgICBAcHJvcGVydHkgZWxlbWVudAogICAgICBAdHlwZSBET01FbGVtZW50CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBlbGVtZW50OiAoMCwgX21ldGFsLm5hdGl2ZURlc2NEZWNvcmF0b3IpKHsKICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSwKICAgICAgZW51bWVyYWJsZTogZmFsc2UsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLnJlbmRlcmVyLmdldEVsZW1lbnQodGhpcyk7CiAgICAgIH0KICAgIH0pLAoKICAgIC8qKgogICAgIEFwcGVuZHMgdGhlIHZpZXcncyBlbGVtZW50IHRvIHRoZSBzcGVjaWZpZWQgcGFyZW50IGVsZW1lbnQuCiAgICAgIE5vdGUgdGhhdCB0aGlzIG1ldGhvZCBqdXN0IHNjaGVkdWxlcyB0aGUgdmlldyB0byBiZSBhcHBlbmRlZDsgdGhlIERPTQogICAgIGVsZW1lbnQgd2lsbCBub3QgYmUgYXBwZW5kZWQgdG8gdGhlIGdpdmVuIGVsZW1lbnQgdW50aWwgYWxsIGJpbmRpbmdzIGhhdmUKICAgICBmaW5pc2hlZCBzeW5jaHJvbml6aW5nLgogICAgICBUaGlzIGlzIG5vdCB0eXBpY2FsbHkgYSBmdW5jdGlvbiB0aGF0IHlvdSB3aWxsIG5lZWQgdG8gY2FsbCBkaXJlY3RseSB3aGVuCiAgICAgYnVpbGRpbmcgeW91ciBhcHBsaWNhdGlvbi4gSWYgeW91IGRvIG5lZWQgdG8gdXNlIGBhcHBlbmRUb2AsIGJlIHN1cmUgdGhhdAogICAgIHRoZSB0YXJnZXQgZWxlbWVudCB5b3UgYXJlIHByb3ZpZGluZyBpcyBhc3NvY2lhdGVkIHdpdGggYW4gYEFwcGxpY2F0aW9uYAogICAgIGFuZCBkb2VzIG5vdCBoYXZlIGFuIGFuY2VzdG9yIGVsZW1lbnQgdGhhdCBpcyBhc3NvY2lhdGVkIHdpdGggYW4gRW1iZXIgdmlldy4KICAgICAgQG1ldGhvZCBhcHBlbmRUbwogICAgIEBwYXJhbSB7U3RyaW5nfERPTUVsZW1lbnR8alF1ZXJ5fSBBIHNlbGVjdG9yLCBlbGVtZW50LCBIVE1MIHN0cmluZywgb3IgalF1ZXJ5IG9iamVjdAogICAgIEByZXR1cm4ge0VtYmVyLlZpZXd9IHJlY2VpdmVyCiAgICAgQHByaXZhdGUKICAgICAqLwogICAgYXBwZW5kVG86IGZ1bmN0aW9uIGFwcGVuZFRvKHNlbGVjdG9yKSB7CiAgICAgIHZhciB0YXJnZXQ7CgogICAgICBpZiAoX2Jyb3dzZXJFbnZpcm9ubWVudC5oYXNET00pIHsKICAgICAgICB0YXJnZXQgPSB0eXBlb2Ygc2VsZWN0b3IgPT09ICdzdHJpbmcnID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3RvcikgOiBzZWxlY3RvcjsKICAgICAgICAoZmFsc2UgJiYgISh0YXJnZXQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IHRyaWVkIHRvIGFwcGVuZCB0byAoIiArIHNlbGVjdG9yICsgIikgYnV0IHRoYXQgaXNuJ3QgaW4gdGhlIERPTSIsIHRhcmdldCkpOwogICAgICAgIChmYWxzZSAmJiAhKCEoMCwgX3V0aWxzMi5tYXRjaGVzKSh0YXJnZXQsICcuZW1iZXItdmlldycpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW5ub3QgYXBwZW5kIHRvIGFuIGV4aXN0aW5nIEVtYmVyLlZpZXcuJywgISgwLCBfdXRpbHMyLm1hdGNoZXMpKHRhcmdldCwgJy5lbWJlci12aWV3JykpKTsKICAgICAgICAoZmFsc2UgJiYgIShmdW5jdGlvbiAoKSB7CiAgICAgICAgICB2YXIgbm9kZSA9IHRhcmdldC5wYXJlbnROb2RlOwoKICAgICAgICAgIHdoaWxlIChub2RlKSB7CiAgICAgICAgICAgIGlmIChub2RlLm5vZGVUeXBlICE9PSA5ICYmICgwLCBfdXRpbHMyLm1hdGNoZXMpKG5vZGUsICcuZW1iZXItdmlldycpKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0oKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgY2Fubm90IGFwcGVuZCB0byBhbiBleGlzdGluZyBFbWJlci5WaWV3LicsIGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHZhciBub2RlID0gdGFyZ2V0LnBhcmVudE5vZGU7CgogICAgICAgICAgd2hpbGUgKG5vZGUpIHsKICAgICAgICAgICAgaWYgKG5vZGUubm9kZVR5cGUgIT09IDkgJiYgKDAsIF91dGlsczIubWF0Y2hlcykobm9kZSwgJy5lbWJlci12aWV3JykpIHsKICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIG5vZGUgPSBub2RlLnBhcmVudE5vZGU7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfSgpKSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGFyZ2V0ID0gc2VsZWN0b3I7CiAgICAgICAgKGZhbHNlICYmICEodHlwZW9mIHRhcmdldCAhPT0gJ3N0cmluZycpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IHRyaWVkIHRvIGFwcGVuZCB0byBhIHNlbGVjdG9yIHN0cmluZyAoIiArIHNlbGVjdG9yICsgIikgaW4gYW4gZW52aXJvbm1lbnQgd2l0aG91dCBqUXVlcnkiLCB0eXBlb2YgdGFyZ2V0ICE9PSAnc3RyaW5nJykpOwogICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBzZWxlY3Rvci5hcHBlbmRDaGlsZCA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgdHJpZWQgdG8gYXBwZW5kIHRvIGEgbm9uLUVsZW1lbnQgKCIgKyBzZWxlY3RvciArICIpIGluIGFuIGVudmlyb25tZW50IHdpdGhvdXQgalF1ZXJ5IiwgdHlwZW9mIHNlbGVjdG9yLmFwcGVuZENoaWxkID09PSAnZnVuY3Rpb24nKSk7CiAgICAgIH0KCiAgICAgIHRoaXMucmVuZGVyZXIuYXBwZW5kVG8odGhpcywgdGFyZ2V0KTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAoKICAgIC8qKgogICAgIEFwcGVuZHMgdGhlIHZpZXcncyBlbGVtZW50IHRvIHRoZSBkb2N1bWVudCBib2R5LiBJZiB0aGUgdmlldyBkb2VzCiAgICAgbm90IGhhdmUgYW4gSFRNTCByZXByZXNlbnRhdGlvbiB5ZXQKICAgICB0aGUgZWxlbWVudCB3aWxsIGJlIGdlbmVyYXRlZCBhdXRvbWF0aWNhbGx5LgogICAgICBJZiB5b3VyIGFwcGxpY2F0aW9uIHVzZXMgdGhlIGByb290RWxlbWVudGAgcHJvcGVydHksIHlvdSBtdXN0IGFwcGVuZAogICAgIHRoZSB2aWV3IHdpdGhpbiB0aGF0IGVsZW1lbnQuIFJlbmRlcmluZyB2aWV3cyBvdXRzaWRlIG9mIHRoZSBgcm9vdEVsZW1lbnRgCiAgICAgaXMgbm90IHN1cHBvcnRlZC4KICAgICAgTm90ZSB0aGF0IHRoaXMgbWV0aG9kIGp1c3Qgc2NoZWR1bGVzIHRoZSB2aWV3IHRvIGJlIGFwcGVuZGVkOyB0aGUgRE9NCiAgICAgZWxlbWVudCB3aWxsIG5vdCBiZSBhcHBlbmRlZCB0byB0aGUgZG9jdW1lbnQgYm9keSB1bnRpbCBhbGwgYmluZGluZ3MgaGF2ZQogICAgIGZpbmlzaGVkIHN5bmNocm9uaXppbmcuCiAgICAgIEBtZXRob2QgYXBwZW5kCiAgICAgQHJldHVybiB7RW1iZXIuVmlld30gcmVjZWl2ZXIKICAgICBAcHJpdmF0ZQogICAgICovCiAgICBhcHBlbmQ6IGZ1bmN0aW9uIGFwcGVuZCgpIHsKICAgICAgcmV0dXJuIHRoaXMuYXBwZW5kVG8oZG9jdW1lbnQuYm9keSk7CiAgICB9LAoKICAgIC8qKgogICAgIFRoZSBIVE1MIGBpZGAgb2YgdGhlIHZpZXcncyBlbGVtZW50IGluIHRoZSBET00uIFlvdSBjYW4gcHJvdmlkZSB0aGlzCiAgICAgdmFsdWUgeW91cnNlbGYgYnV0IGl0IG11c3QgYmUgdW5pcXVlIChqdXN0IGFzIGluIEhUTUwpOgogICAgICBgYGBoYW5kbGViYXJzCiAgICAge3tteS1jb21wb25lbnQgZWxlbWVudElkPSJhLXJlYWxseS1jb29sLWlkIn19CiAgICAgYGBgCiAgICAgIElmIG5vdCBtYW51YWxseSBzZXQgYSBkZWZhdWx0IHZhbHVlIHdpbGwgYmUgcHJvdmlkZWQgYnkgdGhlIGZyYW1ld29yay4KICAgICAgT25jZSByZW5kZXJlZCBhbiBlbGVtZW50J3MgYGVsZW1lbnRJZGAgaXMgY29uc2lkZXJlZCBpbW11dGFibGUgYW5kIHlvdQogICAgIHNob3VsZCBuZXZlciBjaGFuZ2UgaXQuIElmIHlvdSBuZWVkIHRvIGNvbXB1dGUgYSBkeW5hbWljIHZhbHVlIGZvciB0aGUKICAgICBgZWxlbWVudElkYCwgeW91IHNob3VsZCBkbyB0aGlzIHdoZW4gdGhlIGNvbXBvbmVudCBvciBlbGVtZW50IGlzIGJlaW5nCiAgICAgaW5zdGFudGlhdGVkOgogICAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICBleHBvcnQgZGVmYXVsdCBDb21wb25lbnQuZXh0ZW5kKHsKICAgICAgICBpbml0KCkgewogICAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICAgIGxldCBpbmRleCA9IHRoaXMuZ2V0KCdpbmRleCcpOwogICAgICAgICAgdGhpcy5zZXQoJ2VsZW1lbnRJZCcsICdjb21wb25lbnQtaWQnICsgaW5kZXgpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgYGBgCiAgICAgIEBwcm9wZXJ0eSBlbGVtZW50SWQKICAgICBAdHlwZSBTdHJpbmcKICAgICBAcHVibGljCiAgICAgKi8KICAgIGVsZW1lbnRJZDogbnVsbCwKCiAgICAvKioKICAgICBDYWxsZWQgd2hlbiBhIHZpZXcgaXMgZ29pbmcgdG8gaW5zZXJ0IGFuIGVsZW1lbnQgaW50byB0aGUgRE9NLgogICAgICBAZXZlbnQgd2lsbEluc2VydEVsZW1lbnQKICAgICBAcHVibGljCiAgICAgKi8KICAgIHdpbGxJbnNlcnRFbGVtZW50OiBLLAoKICAgIC8qKgogICAgIENhbGxlZCB3aGVuIHRoZSBlbGVtZW50IG9mIHRoZSB2aWV3IGhhcyBiZWVuIGluc2VydGVkIGludG8gdGhlIERPTS4KICAgICBPdmVycmlkZSB0aGlzIGZ1bmN0aW9uIHRvIGRvIGFueSBzZXQgdXAgdGhhdCByZXF1aXJlcyBhbiBlbGVtZW50CiAgICAgaW4gdGhlIGRvY3VtZW50IGJvZHkuCiAgICAgIFdoZW4gYSB2aWV3IGhhcyBjaGlsZHJlbiwgZGlkSW5zZXJ0RWxlbWVudCB3aWxsIGJlIGNhbGxlZCBvbiB0aGUKICAgICBjaGlsZCB2aWV3KHMpIGZpcnN0IGFuZCBvbiBpdHNlbGYgYWZ0ZXJ3YXJkcy4KICAgICAgQGV2ZW50IGRpZEluc2VydEVsZW1lbnQKICAgICBAcHVibGljCiAgICAgKi8KICAgIGRpZEluc2VydEVsZW1lbnQ6IEssCgogICAgLyoqCiAgICAgQ2FsbGVkIHdoZW4gdGhlIHZpZXcgaXMgYWJvdXQgdG8gcmVyZW5kZXIsIGJ1dCBiZWZvcmUgYW55dGhpbmcgaGFzCiAgICAgYmVlbiB0b3JuIGRvd24uIFRoaXMgaXMgYSBnb29kIG9wcG9ydHVuaXR5IHRvIHRlYXIgZG93biBhbnkgbWFudWFsCiAgICAgb2JzZXJ2ZXJzIHlvdSBoYXZlIGluc3RhbGxlZCBiYXNlZCBvbiB0aGUgRE9NIHN0YXRlCiAgICAgIEBldmVudCB3aWxsQ2xlYXJSZW5kZXIKICAgICBAcHVibGljCiAgICAgKi8KICAgIHdpbGxDbGVhclJlbmRlcjogSywKCiAgICAvKioKICAgICBZb3UgbXVzdCBjYWxsIGBkZXN0cm95YCBvbiBhIHZpZXcgdG8gZGVzdHJveSB0aGUgdmlldyAoYW5kIGFsbCBvZiBpdHMKICAgICBjaGlsZCB2aWV3cykuIFRoaXMgd2lsbCByZW1vdmUgdGhlIHZpZXcgZnJvbSBhbnkgcGFyZW50IG5vZGUsIHRoZW4gbWFrZQogICAgIHN1cmUgdGhhdCB0aGUgRE9NIGVsZW1lbnQgbWFuYWdlZCBieSB0aGUgdmlldyBjYW4gYmUgcmVsZWFzZWQgYnkgdGhlCiAgICAgbWVtb3J5IG1hbmFnZXIuCiAgICAgIEBtZXRob2QgZGVzdHJveQogICAgIEBwcml2YXRlCiAgICAgKi8KICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzLl9jdXJyZW50U3RhdGUuZGVzdHJveSh0aGlzKTsKICAgIH0sCgogICAgLyoqCiAgICAgQ2FsbGVkIHdoZW4gdGhlIGVsZW1lbnQgb2YgdGhlIHZpZXcgaXMgZ29pbmcgdG8gYmUgZGVzdHJveWVkLiBPdmVycmlkZQogICAgIHRoaXMgZnVuY3Rpb24gdG8gZG8gYW55IHRlYXJkb3duIHRoYXQgcmVxdWlyZXMgYW4gZWxlbWVudCwgbGlrZSByZW1vdmluZwogICAgIGV2ZW50IGxpc3RlbmVycy4KICAgICAgUGxlYXNlIG5vdGU6IGFueSBwcm9wZXJ0eSBjaGFuZ2VzIG1hZGUgZHVyaW5nIHRoaXMgZXZlbnQgd2lsbCBoYXZlIG5vCiAgICAgZWZmZWN0IG9uIG9iamVjdCBvYnNlcnZlcnMuCiAgICAgIEBldmVudCB3aWxsRGVzdHJveUVsZW1lbnQKICAgICBAcHVibGljCiAgICAgKi8KICAgIHdpbGxEZXN0cm95RWxlbWVudDogSywKCiAgICAvKioKICAgICBDYWxsZWQgYWZ0ZXIgdGhlIGVsZW1lbnQgb2YgdGhlIHZpZXcgaXMgZGVzdHJveWVkLgogICAgICBAZXZlbnQgd2lsbERlc3Ryb3lFbGVtZW50CiAgICAgQHB1YmxpYwogICAgICovCiAgICBkaWREZXN0cm95RWxlbWVudDogSywKCiAgICAvKioKICAgICBDYWxsZWQgd2hlbiB0aGUgcGFyZW50VmlldyBwcm9wZXJ0eSBoYXMgY2hhbmdlZC4KICAgICAgQGV2ZW50IHBhcmVudFZpZXdEaWRDaGFuZ2UKICAgICBAcHJpdmF0ZQogICAgICovCiAgICBwYXJlbnRWaWV3RGlkQ2hhbmdlOiBLLAogICAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogICAgLy8gU1RBTkRBUkQgUkVOREVSIFBST1BFUlRJRVMKICAgIC8vCgogICAgLyoqCiAgICAgVGFnIG5hbWUgZm9yIHRoZSB2aWV3J3Mgb3V0ZXIgZWxlbWVudC4gVGhlIHRhZyBuYW1lIGlzIG9ubHkgdXNlZCB3aGVuIGFuCiAgICAgZWxlbWVudCBpcyBmaXJzdCBjcmVhdGVkLiBJZiB5b3UgY2hhbmdlIHRoZSBgdGFnTmFtZWAgZm9yIGFuIGVsZW1lbnQsIHlvdQogICAgIG11c3QgZGVzdHJveSBhbmQgcmVjcmVhdGUgdGhlIHZpZXcgZWxlbWVudC4KICAgICAgQnkgZGVmYXVsdCwgdGhlIHJlbmRlciBidWZmZXIgd2lsbCB1c2UgYSBgPGRpdj5gIHRhZyBmb3Igdmlld3MuCiAgICAgIElmIHRoZSB0YWdOYW1lIGlzIGAnJ2AsIHRoZSB2aWV3IHdpbGwgYmUgdGFnbGVzcywgd2l0aCBubyBvdXRlciBlbGVtZW50LgogICAgIENvbXBvbmVudCBwcm9wZXJ0aWVzIHRoYXQgZGVwZW5kIG9uIHRoZSBwcmVzZW5jZSBvZiBhbiBvdXRlciBlbGVtZW50LCBzdWNoCiAgICAgYXMgYGNsYXNzTmFtZUJpbmRpbmdzYCBhbmQgYGF0dHJpYnV0ZUJpbmRpbmdzYCwgZG8gbm90IHdvcmsgd2l0aCB0YWdsZXNzCiAgICAgY29tcG9uZW50cy4gVGFnbGVzcyBjb21wb25lbnRzIGNhbm5vdCBpbXBsZW1lbnQgbWV0aG9kcyB0byBoYW5kbGUgZXZlbnRzLAogICAgIGFuZCBoYXZlIG5vIGFzc29jaWF0ZWQgalF1ZXJ5IG9iamVjdCB0byByZXR1cm4gd2l0aCBgJCgpYC4KICAgICAgQHByb3BlcnR5IHRhZ05hbWUKICAgICBAdHlwZSBTdHJpbmcKICAgICBAZGVmYXVsdCBudWxsCiAgICAgQHB1YmxpYwogICAgICovCiAgICAvLyBXZSBsZWF2ZSB0aGlzIG51bGwgYnkgZGVmYXVsdCBzbyB3ZSBjYW4gdGVsbCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuCiAgICAvLyB0aGUgZGVmYXVsdCBjYXNlIGFuZCBhIHVzZXItc3BlY2lmaWVkIHRhZy4KICAgIHRhZ05hbWU6IG51bGwsCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uCiAgICAvLyBDT1JFIERJU1BMQVkgTUVUSE9EUwogICAgLy8KCiAgICAvKioKICAgICBTZXR1cCBhIHZpZXcsIGJ1dCBkbyBub3QgZmluaXNoIHdha2luZyBpdCB1cC4KICAgICAgKiBjb25maWd1cmUgYGNoaWxkVmlld3NgCiAgICAgKiByZWdpc3RlciB0aGUgdmlldyB3aXRoIHRoZSBnbG9iYWwgdmlld3MgaGFzaCwgd2hpY2ggaXMgdXNlZCBmb3IgZXZlbnQKICAgICBkaXNwYXRjaAogICAgICBAbWV0aG9kIGluaXQKICAgICBAcHJpdmF0ZQogICAgICovCiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOyAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoCgoKICAgICAgKGZhbHNlICYmICEoKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKHRoaXMsICdlbGVtZW50SWQnKSA9PT0gdW5kZWZpbmVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3QgdXNlIGEgY29tcHV0ZWQgcHJvcGVydHkgZm9yIHRoZSBjb21wb25lbnQncyBgZWxlbWVudElkYCAoIiArIHRoaXMgKyAiKS4iLCAoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JQcm9wZXJ0eSkodGhpcywgJ2VsZW1lbnRJZCcpID09PSB1bmRlZmluZWQpKTsgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm1heC1saW5lLWxlbmd0aAoKICAgICAgKGZhbHNlICYmICEoKDAsIF9tZXRhbC5kZXNjcmlwdG9yRm9yUHJvcGVydHkpKHRoaXMsICd0YWdOYW1lJykgPT09IHVuZGVmaW5lZCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgY2Fubm90IHVzZSBhIGNvbXB1dGVkIHByb3BlcnR5IGZvciB0aGUgY29tcG9uZW50J3MgYHRhZ05hbWVgICgiICsgdGhpcyArICIpLiIsICgwLCBfbWV0YWwuZGVzY3JpcHRvckZvclByb3BlcnR5KSh0aGlzLCAndGFnTmFtZScpID09PSB1bmRlZmluZWQpKTsKCiAgICAgIGlmICghdGhpcy5lbGVtZW50SWQgJiYgdGhpcy50YWdOYW1lICE9PSAnJykgewogICAgICAgIHRoaXMuZWxlbWVudElkID0gKDAsIF91dGlscy5ndWlkRm9yKSh0aGlzKTsKICAgICAgfQoKICAgICAgKGZhbHNlICYmICEoIXRoaXMucmVuZGVyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1VzaW5nIGEgY3VzdG9tIGAucmVuZGVyYCBmdW5jdGlvbiBpcyBubyBsb25nZXIgc3VwcG9ydGVkLicsICF0aGlzLnJlbmRlcikpOwogICAgfSwKICAgIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KICAgIC8vIEVWRU5UIEhBTkRMSU5HCiAgICAvLwoKICAgIC8qKgogICAgIEhhbmRsZSBldmVudHMgZnJvbSBgRXZlbnREaXNwYXRjaGVyYAogICAgICBAbWV0aG9kIGhhbmRsZUV2ZW50CiAgICAgQHBhcmFtIGV2ZW50TmFtZSB7U3RyaW5nfQogICAgIEBwYXJhbSBldnQge0V2ZW50fQogICAgIEBwcml2YXRlCiAgICAgKi8KICAgIGhhbmRsZUV2ZW50OiBmdW5jdGlvbiBoYW5kbGVFdmVudChldmVudE5hbWUsIGV2dCkgewogICAgICByZXR1cm4gdGhpcy5fY3VycmVudFN0YXRlLmhhbmRsZUV2ZW50KHRoaXMsIGV2ZW50TmFtZSwgZXZ0KTsKICAgIH0KICB9OwoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5KUVVFUllfSU5URUdSQVRJT04pIHsKICAgIC8qKgogICAgIFJldHVybnMgYSBqUXVlcnkgb2JqZWN0IGZvciB0aGlzIHZpZXcncyBlbGVtZW50LiBJZiB5b3UgcGFzcyBpbiBhIHNlbGVjdG9yCiAgICAgc3RyaW5nLCB0aGlzIG1ldGhvZCB3aWxsIHJldHVybiBhIGpRdWVyeSBvYmplY3QsIHVzaW5nIHRoZSBjdXJyZW50IGVsZW1lbnQKICAgICBhcyBpdHMgYnVmZmVyLgogICAgICBGb3IgZXhhbXBsZSwgY2FsbGluZyBgdmlldy4kKCdsaScpYCB3aWxsIHJldHVybiBhIGpRdWVyeSBvYmplY3QgY29udGFpbmluZwogICAgIGFsbCBvZiB0aGUgYGxpYCBlbGVtZW50cyBpbnNpZGUgdGhlIERPTSBlbGVtZW50IG9mIHRoaXMgdmlldy4KICAgICAgQG1ldGhvZCAkCiAgICAgQHBhcmFtIHtTdHJpbmd9IFtzZWxlY3Rvcl0gYSBqUXVlcnktY29tcGF0aWJsZSBzZWxlY3RvciBzdHJpbmcKICAgICBAcmV0dXJuIHtqUXVlcnl9IHRoZSBqUXVlcnkgb2JqZWN0IGZvciB0aGUgRE9NIG5vZGUKICAgICBAcHVibGljCiAgICAgQGRlcHJlY2F0ZWQKICAgICAqLwogICAgbWl4aW4uJCA9IGZ1bmN0aW9uICQoc2VsKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMudGFnTmFtZSAhPT0gJycpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGNhbm5vdCBhY2Nlc3MgdGhpcy4kKCkgb24gYSBjb21wb25lbnQgd2l0aCBgdGFnTmFtZTogJydgIHNwZWNpZmllZC4iLCB0aGlzLnRhZ05hbWUgIT09ICcnKSk7CiAgICAgIChmYWxzZSAmJiAhKCFfanF1ZXJ5LmpRdWVyeURpc2FibGVkKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW5ub3QgYWNjZXNzIHRoaXMuJCgpIHdpdGggYGpRdWVyeWAgZGlzYWJsZWQuJywgIV9qcXVlcnkualF1ZXJ5RGlzYWJsZWQpKTsKICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgnVXNpbmcgdGhpcy4kKCkgaW4gYSBjb21wb25lbnQgaGFzIGJlZW4gZGVwcmVjYXRlZCwgY29uc2lkZXIgdXNpbmcgdGhpcy5lbGVtZW50JywgZmFsc2UsIHsKICAgICAgICBpZDogJ2VtYmVyLXZpZXdzLmN1cmx5LWNvbXBvbmVudHMuanF1ZXJ5LWVsZW1lbnQnLAogICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgIHVybDogJ2h0dHBzOi8vZW1iZXJqcy5jb20vZGVwcmVjYXRpb25zL3YzLngjdG9jX2pxdWVyeS1hcGlzJwogICAgICB9KSk7CgogICAgICBpZiAodGhpcy5lbGVtZW50KSB7CiAgICAgICAgcmV0dXJuIHNlbCA/ICgwLCBfanF1ZXJ5LmpRdWVyeSkoc2VsLCB0aGlzLmVsZW1lbnQpIDogKDAsIF9qcXVlcnkualF1ZXJ5KSh0aGlzLmVsZW1lbnQpOwogICAgICB9CiAgICB9OwogIH0KICAvKioKICAgQGNsYXNzIFZpZXdNaXhpbgogICBAbmFtZXNwYWNlIEVtYmVyCiAgIEBwcml2YXRlCiAgKi8KCgogIHZhciBfZGVmYXVsdCA9IF9tZXRhbC5NaXhpbi5jcmVhdGUobWl4aW4pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vYWN0aW9uX21hbmFnZXIiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gQWN0aW9uTWFuYWdlcjsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCiAgZnVuY3Rpb24gQWN0aW9uTWFuYWdlcigpIHt9CiAgLyoqCiAgICBHbG9iYWwgYWN0aW9uIGlkIGhhc2guCiAgCiAgICBAcHJpdmF0ZQogICAgQHByb3BlcnR5IHJlZ2lzdGVyZWRBY3Rpb25zCiAgICBAdHlwZSBPYmplY3QKICAqLwoKCiAgQWN0aW9uTWFuYWdlci5yZWdpc3RlcmVkQWN0aW9ucyA9IHt9Owp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2V2ZW50X2Rpc3BhdGNoZXIiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvb3duZXIiLCAiQGVtYmVyL3BvbHlmaWxscyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSIsICJAZW1iZXIvLWludGVybmFscy92aWV3cyIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2pxdWVyeSIsICJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2FjdGlvbl9tYW5hZ2VyIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vanF1ZXJ5X2V2ZW50X2RlcHJlY2F0aW9uIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vdXRpbHMiLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfb3duZXIsIF9wb2x5ZmlsbHMsIF9kZWJ1ZywgX21ldGFsLCBfcnVudGltZSwgX3ZpZXdzLCBfanF1ZXJ5LCBfYWN0aW9uX21hbmFnZXIsIF9qcXVlcnlfZXZlbnRfZGVwcmVjYXRpb24sIF91dGlscywgX2RlcHJlY2F0ZWRGZWF0dXJlcykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCiAgdmFyIFJPT1RfRUxFTUVOVF9DTEFTUyA9ICdlbWJlci1hcHBsaWNhdGlvbic7CiAgdmFyIFJPT1RfRUxFTUVOVF9TRUxFQ1RPUiA9ICIuIiArIFJPT1RfRUxFTUVOVF9DTEFTUzsKICB2YXIgRVZFTlRfTUFQID0gewogICAgbW91c2VlbnRlcjogJ21vdXNlb3ZlcicsCiAgICBtb3VzZWxlYXZlOiAnbW91c2VvdXQnCiAgfTsKICAvKioKICAgIGBFbWJlci5FdmVudERpc3BhdGNoZXJgIGhhbmRsZXMgZGVsZWdhdGluZyBicm93c2VyIGV2ZW50cyB0byB0aGVpcgogICAgY29ycmVzcG9uZGluZyBgRW1iZXIuVmlld3MuYCBGb3IgZXhhbXBsZSwgd2hlbiB5b3UgY2xpY2sgb24gYSB2aWV3LAogICAgYEVtYmVyLkV2ZW50RGlzcGF0Y2hlcmAgZW5zdXJlcyB0aGF0IHRoYXQgdmlldydzIGBtb3VzZURvd25gIG1ldGhvZCBnZXRzCiAgICBjYWxsZWQuCiAgCiAgICBAY2xhc3MgRXZlbnREaXNwYXRjaGVyCiAgICBAbmFtZXNwYWNlIEVtYmVyCiAgICBAcHJpdmF0ZQogICAgQGV4dGVuZHMgRW1iZXIuT2JqZWN0CiAgKi8KCiAgdmFyIF9kZWZhdWx0ID0gX3J1bnRpbWUuT2JqZWN0LmV4dGVuZCh7CiAgICAvKioKICAgICAgVGhlIHNldCBvZiBldmVudHMgbmFtZXMgKGFuZCBhc3NvY2lhdGVkIGhhbmRsZXIgZnVuY3Rpb24gbmFtZXMpIHRvIGJlIHNldHVwCiAgICAgIGFuZCBkaXNwYXRjaGVkIGJ5IHRoZSBgRXZlbnREaXNwYXRjaGVyYC4gTW9kaWZpY2F0aW9ucyB0byB0aGlzIGxpc3QgY2FuIGJlIGRvbmUKICAgICAgYXQgc2V0dXAgdGltZSwgZ2VuZXJhbGx5IHZpYSB0aGUgYEFwcGxpY2F0aW9uLmN1c3RvbUV2ZW50c2AgaGFzaC4KICAgICAgIFRvIGFkZCBuZXcgZXZlbnRzIHRvIGJlIGxpc3RlbmVkIHRvOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAgICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoewogICAgICAgIGN1c3RvbUV2ZW50czogewogICAgICAgICAgcGFzdGU6ICdwYXN0ZScKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRvIHByZXZlbnQgZGVmYXVsdCBldmVudHMgZnJvbSBiZWluZyBsaXN0ZW5lZCB0bzoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgICBsZXQgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKHsKICAgICAgICBjdXN0b21FdmVudHM6IHsKICAgICAgICAgIG1vdXNlZW50ZXI6IG51bGwsCiAgICAgICAgICBtb3VzZWxlYXZlOiBudWxsCiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgIEBwcm9wZXJ0eSBldmVudHMKICAgICAgQHR5cGUgT2JqZWN0CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgZXZlbnRzOiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHsKICAgICAgdG91Y2hzdGFydDogJ3RvdWNoU3RhcnQnLAogICAgICB0b3VjaG1vdmU6ICd0b3VjaE1vdmUnLAogICAgICB0b3VjaGVuZDogJ3RvdWNoRW5kJywKICAgICAgdG91Y2hjYW5jZWw6ICd0b3VjaENhbmNlbCcsCiAgICAgIGtleWRvd246ICdrZXlEb3duJywKICAgICAga2V5dXA6ICdrZXlVcCcsCiAgICAgIGtleXByZXNzOiAna2V5UHJlc3MnLAogICAgICBtb3VzZWRvd246ICdtb3VzZURvd24nLAogICAgICBtb3VzZXVwOiAnbW91c2VVcCcsCiAgICAgIGNvbnRleHRtZW51OiAnY29udGV4dE1lbnUnLAogICAgICBjbGljazogJ2NsaWNrJywKICAgICAgZGJsY2xpY2s6ICdkb3VibGVDbGljaycsCiAgICAgIGZvY3VzaW46ICdmb2N1c0luJywKICAgICAgZm9jdXNvdXQ6ICdmb2N1c091dCcsCiAgICAgIHN1Ym1pdDogJ3N1Ym1pdCcsCiAgICAgIGlucHV0OiAnaW5wdXQnLAogICAgICBjaGFuZ2U6ICdjaGFuZ2UnLAogICAgICBkcmFnc3RhcnQ6ICdkcmFnU3RhcnQnLAogICAgICBkcmFnOiAnZHJhZycsCiAgICAgIGRyYWdlbnRlcjogJ2RyYWdFbnRlcicsCiAgICAgIGRyYWdsZWF2ZTogJ2RyYWdMZWF2ZScsCiAgICAgIGRyYWdvdmVyOiAnZHJhZ092ZXInLAogICAgICBkcm9wOiAnZHJvcCcsCiAgICAgIGRyYWdlbmQ6ICdkcmFnRW5kJwogICAgfSwgX2RlcHJlY2F0ZWRGZWF0dXJlcy5NT1VTRV9FTlRFUl9MRUFWRV9NT1ZFX0VWRU5UUyA/IHsKICAgICAgbW91c2VlbnRlcjogJ21vdXNlRW50ZXInLAogICAgICBtb3VzZWxlYXZlOiAnbW91c2VMZWF2ZScsCiAgICAgIG1vdXNlbW92ZTogJ21vdXNlTW92ZScKICAgIH0gOiB7fSksCgogICAgLyoqCiAgICAgIFRoZSByb290IERPTSBlbGVtZW50IHRvIHdoaWNoIGV2ZW50IGxpc3RlbmVycyBzaG91bGQgYmUgYXR0YWNoZWQuIEV2ZW50CiAgICAgIGxpc3RlbmVycyB3aWxsIGJlIGF0dGFjaGVkIHRvIHRoZSBkb2N1bWVudCB1bmxlc3MgdGhpcyBpcyBvdmVycmlkZGVuLgogICAgICAgQ2FuIGJlIHNwZWNpZmllZCBhcyBhIERPTUVsZW1lbnQgb3IgYSBzZWxlY3RvciBzdHJpbmcuCiAgICAgICBUaGUgZGVmYXVsdCBib2R5IGlzIGEgc3RyaW5nIHNpbmNlIHRoaXMgbWF5IGJlIGV2YWx1YXRlZCBiZWZvcmUgZG9jdW1lbnQuYm9keQogICAgICBleGlzdHMgaW4gdGhlIERPTS4KICAgICAgIEBwcml2YXRlCiAgICAgIEBwcm9wZXJ0eSByb290RWxlbWVudAogICAgICBAdHlwZSBET01FbGVtZW50CiAgICAgIEBkZWZhdWx0ICdib2R5JwogICAgKi8KICAgIHJvb3RFbGVtZW50OiAnYm9keScsCiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgdGhpcy5fc3VwZXIoKTsKCiAgICAgIChmYWxzZSAmJiAhKGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKShfdGhpcyk7CiAgICAgICAgdmFyIGVudmlyb25tZW50ID0gb3duZXIubG9va3VwKCctZW52aXJvbm1lbnQ6bWFpbicpOwogICAgICAgIHJldHVybiBlbnZpcm9ubWVudC5pc0ludGVyYWN0aXZlOwogICAgICB9KCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnRXZlbnREaXNwYXRjaGVyIHNob3VsZCBuZXZlciBiZSBpbnN0YW50aWF0ZWQgaW4gZmFzdGJvb3QgbW9kZS4gUGxlYXNlIHJlcG9ydCB0aGlzIGFzIGFuIEVtYmVyIGJ1Zy4nLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIG93bmVyID0gKDAsIF9vd25lci5nZXRPd25lcikoX3RoaXMpOwogICAgICAgIHZhciBlbnZpcm9ubWVudCA9IG93bmVyLmxvb2t1cCgnLWVudmlyb25tZW50Om1haW4nKTsKICAgICAgICByZXR1cm4gZW52aXJvbm1lbnQuaXNJbnRlcmFjdGl2ZTsKICAgICAgfSgpKSk7CiAgICAgIHRoaXMuX2V2ZW50SGFuZGxlcnMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgfSwKCiAgICAvKioKICAgICAgU2V0cyB1cCBldmVudCBsaXN0ZW5lcnMgZm9yIHN0YW5kYXJkIGJyb3dzZXIgZXZlbnRzLgogICAgICAgVGhpcyB3aWxsIGJlIGNhbGxlZCBhZnRlciB0aGUgYnJvd3NlciBzZW5kcyBhIGBET01Db250ZW50UmVhZHlgIGV2ZW50LiBCeQogICAgICBkZWZhdWx0LCBpdCB3aWxsIHNldCB1cCBhbGwgb2YgdGhlIGxpc3RlbmVycyBvbiB0aGUgZG9jdW1lbnQgYm9keS4gSWYgeW91CiAgICAgIHdvdWxkIGxpa2UgdG8gcmVnaXN0ZXIgdGhlIGxpc3RlbmVycyBvbiBhIGRpZmZlcmVudCBlbGVtZW50LCBzZXQgdGhlIGV2ZW50CiAgICAgIGRpc3BhdGNoZXIncyBgcm9vdGAgcHJvcGVydHkuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHNldHVwCiAgICAgIEBwYXJhbSBhZGRlZEV2ZW50cyB7T2JqZWN0fQogICAgKi8KICAgIHNldHVwOiBmdW5jdGlvbiBzZXR1cChhZGRlZEV2ZW50cywgX3Jvb3RFbGVtZW50KSB7CiAgICAgIHZhciBldmVudHMgPSB0aGlzLl9maW5hbEV2ZW50cyA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAnZXZlbnRzJyksIGFkZGVkRXZlbnRzKTsKCiAgICAgIGlmIChfcm9vdEVsZW1lbnQgIT09IHVuZGVmaW5lZCAmJiBfcm9vdEVsZW1lbnQgIT09IG51bGwpIHsKICAgICAgICAoMCwgX21ldGFsLnNldCkodGhpcywgJ3Jvb3RFbGVtZW50JywgX3Jvb3RFbGVtZW50KTsKICAgICAgfQoKICAgICAgdmFyIHJvb3RFbGVtZW50U2VsZWN0b3IgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ3Jvb3RFbGVtZW50Jyk7CiAgICAgIHZhciByb290RWxlbWVudDsKCiAgICAgIGlmICghX2RlcHJlY2F0ZWRGZWF0dXJlcy5KUVVFUllfSU5URUdSQVRJT04gfHwgX2pxdWVyeS5qUXVlcnlEaXNhYmxlZCkgewogICAgICAgIGlmICh0eXBlb2Ygcm9vdEVsZW1lbnRTZWxlY3RvciAhPT0gJ3N0cmluZycpIHsKICAgICAgICAgIHJvb3RFbGVtZW50ID0gcm9vdEVsZW1lbnRTZWxlY3RvcjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcm9vdEVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHJvb3RFbGVtZW50U2VsZWN0b3IpOwogICAgICAgIH0KCiAgICAgICAgKGZhbHNlICYmICEoIXJvb3RFbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhST09UX0VMRU1FTlRfQ0xBU1MpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBjYW5ub3QgdXNlIHRoZSBzYW1lIHJvb3QgZWxlbWVudCAoIiArICgoMCwgX21ldGFsLmdldCkodGhpcywgJ3Jvb3RFbGVtZW50JykgfHwgcm9vdEVsZW1lbnQudGFnTmFtZSkgKyAiKSBtdWx0aXBsZSB0aW1lcyBpbiBhbiBFbWJlci5BcHBsaWNhdGlvbiIsICFyb290RWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoUk9PVF9FTEVNRU5UX0NMQVNTKSkpOwogICAgICAgIChmYWxzZSAmJiAhKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHZhciB0YXJnZXQgPSByb290RWxlbWVudC5wYXJlbnROb2RlOwoKICAgICAgICAgIGRvIHsKICAgICAgICAgICAgaWYgKHRhcmdldC5jbGFzc0xpc3QuY29udGFpbnMoUk9PVF9FTEVNRU5UX0NMQVNTKSkgewogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdGFyZ2V0ID0gdGFyZ2V0LnBhcmVudE5vZGU7CiAgICAgICAgICB9IHdoaWxlICh0YXJnZXQgJiYgdGFyZ2V0Lm5vZGVUeXBlID09PSAxKTsKCiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9KCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGNhbm5vdCBtYWtlIGEgbmV3IEVtYmVyLkFwcGxpY2F0aW9uIHVzaW5nIGEgcm9vdCBlbGVtZW50IHRoYXQgaXMgYSBkZXNjZW5kZW50IG9mIGFuIGV4aXN0aW5nIEVtYmVyLkFwcGxpY2F0aW9uJywgZnVuY3Rpb24gKCkgewogICAgICAgICAgdmFyIHRhcmdldCA9IHJvb3RFbGVtZW50LnBhcmVudE5vZGU7CgogICAgICAgICAgZG8gewogICAgICAgICAgICBpZiAodGFyZ2V0LmNsYXNzTGlzdC5jb250YWlucyhST09UX0VMRU1FTlRfQ0xBU1MpKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICB0YXJnZXQgPSB0YXJnZXQucGFyZW50Tm9kZTsKICAgICAgICAgIH0gd2hpbGUgKHRhcmdldCAmJiB0YXJnZXQubm9kZVR5cGUgPT09IDEpOwoKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0oKSkpOwogICAgICAgIChmYWxzZSAmJiAhKCFyb290RWxlbWVudC5xdWVyeVNlbGVjdG9yKFJPT1RfRUxFTUVOVF9TRUxFQ1RPUikpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGNhbm5vdCBtYWtlIGEgbmV3IEVtYmVyLkFwcGxpY2F0aW9uIHVzaW5nIGEgcm9vdCBlbGVtZW50IHRoYXQgaXMgYW4gYW5jZXN0b3Igb2YgYW4gZXhpc3RpbmcgRW1iZXIuQXBwbGljYXRpb24nLCAhcm9vdEVsZW1lbnQucXVlcnlTZWxlY3RvcihST09UX0VMRU1FTlRfU0VMRUNUT1IpKSk7CiAgICAgICAgcm9vdEVsZW1lbnQuY2xhc3NMaXN0LmFkZChST09UX0VMRU1FTlRfQ0xBU1MpOwogICAgICAgIChmYWxzZSAmJiAhKHJvb3RFbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhST09UX0VMRU1FTlRfQ0xBU1MpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIlVuYWJsZSB0byBhZGQgJyIgKyBST09UX0VMRU1FTlRfQ0xBU1MgKyAiJyBjbGFzcyB0byByb290IGVsZW1lbnQgKCIgKyAoKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdyb290RWxlbWVudCcpIHx8IHJvb3RFbGVtZW50LnRhZ05hbWUpICsgIikuIE1ha2Ugc3VyZSB5b3Ugc2V0IHJvb3RFbGVtZW50IHRvIHRoZSBib2R5IG9yIGFuIGVsZW1lbnQgaW4gdGhlIGJvZHkuIiwgcm9vdEVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKFJPT1RfRUxFTUVOVF9DTEFTUykpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByb290RWxlbWVudCA9ICgwLCBfanF1ZXJ5LmpRdWVyeSkocm9vdEVsZW1lbnRTZWxlY3Rvcik7CiAgICAgICAgKGZhbHNlICYmICEoIXJvb3RFbGVtZW50LmlzKFJPT1RfRUxFTUVOVF9TRUxFQ1RPUikpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiWW91IGNhbm5vdCB1c2UgdGhlIHNhbWUgcm9vdCBlbGVtZW50ICgiICsgKHJvb3RFbGVtZW50LnNlbGVjdG9yIHx8IHJvb3RFbGVtZW50WzBdLnRhZ05hbWUpICsgIikgbXVsdGlwbGUgdGltZXMgaW4gYW4gRW1iZXIuQXBwbGljYXRpb24iLCAhcm9vdEVsZW1lbnQuaXMoUk9PVF9FTEVNRU5UX1NFTEVDVE9SKSkpOwogICAgICAgIChmYWxzZSAmJiAhKCFyb290RWxlbWVudC5jbG9zZXN0KFJPT1RfRUxFTUVOVF9TRUxFQ1RPUikubGVuZ3RoKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW5ub3QgbWFrZSBhIG5ldyBFbWJlci5BcHBsaWNhdGlvbiB1c2luZyBhIHJvb3QgZWxlbWVudCB0aGF0IGlzIGEgZGVzY2VuZGVudCBvZiBhbiBleGlzdGluZyBFbWJlci5BcHBsaWNhdGlvbicsICFyb290RWxlbWVudC5jbG9zZXN0KFJPT1RfRUxFTUVOVF9TRUxFQ1RPUikubGVuZ3RoKSk7CiAgICAgICAgKGZhbHNlICYmICEoIXJvb3RFbGVtZW50LmZpbmQoUk9PVF9FTEVNRU5UX1NFTEVDVE9SKS5sZW5ndGgpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGNhbm5vdCBtYWtlIGEgbmV3IEVtYmVyLkFwcGxpY2F0aW9uIHVzaW5nIGEgcm9vdCBlbGVtZW50IHRoYXQgaXMgYW4gYW5jZXN0b3Igb2YgYW4gZXhpc3RpbmcgRW1iZXIuQXBwbGljYXRpb24nLCAhcm9vdEVsZW1lbnQuZmluZChST09UX0VMRU1FTlRfU0VMRUNUT1IpLmxlbmd0aCkpOwogICAgICAgIHJvb3RFbGVtZW50LmFkZENsYXNzKFJPT1RfRUxFTUVOVF9DTEFTUyk7CgogICAgICAgIGlmICghcm9vdEVsZW1lbnQuaXMoUk9PVF9FTEVNRU5UX1NFTEVDVE9SKSkgewogICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiVW5hYmxlIHRvIGFkZCAnIiArIFJPT1RfRUxFTUVOVF9DTEFTUyArICInIGNsYXNzIHRvIHJvb3QgZWxlbWVudCAoIiArIChyb290RWxlbWVudC5zZWxlY3RvciB8fCByb290RWxlbWVudFswXS50YWdOYW1lKSArICIpLiBNYWtlIHN1cmUgeW91IHNldCByb290RWxlbWVudCB0byB0aGUgYm9keSBvciBhbiBlbGVtZW50IGluIHRoZSBib2R5LiIpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgZm9yICh2YXIgZXZlbnQgaW4gZXZlbnRzKSB7CiAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShldmVudCkpIHsKICAgICAgICAgIHRoaXMuc2V0dXBIYW5kbGVyKHJvb3RFbGVtZW50LCBldmVudCwgZXZlbnRzW2V2ZW50XSk7CiAgICAgICAgfQogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgb24gdGhlIHJvb3RFbGVtZW50LiBJZiB0aGUgZ2l2ZW4gZXZlbnQgaXMKICAgICAgdHJpZ2dlcmVkLCB0aGUgcHJvdmlkZWQgZXZlbnQgaGFuZGxlciB3aWxsIGJlIHRyaWdnZXJlZCBvbiB0aGUgdGFyZ2V0IHZpZXcuCiAgICAgICBJZiB0aGUgdGFyZ2V0IHZpZXcgZG9lcyBub3QgaW1wbGVtZW50IHRoZSBldmVudCBoYW5kbGVyLCBvciBpZiB0aGUgaGFuZGxlcgogICAgICByZXR1cm5zIGBmYWxzZWAsIHRoZSBwYXJlbnQgdmlldyB3aWxsIGJlIGNhbGxlZC4gVGhlIGV2ZW50IHdpbGwgY29udGludWUgdG8KICAgICAgYnViYmxlIHRvIGVhY2ggc3VjY2Vzc2l2ZSBwYXJlbnQgdmlldyB1bnRpbCBpdCByZWFjaGVzIHRoZSB0b3AuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHNldHVwSGFuZGxlcgogICAgICBAcGFyYW0ge0VsZW1lbnR9IHJvb3RFbGVtZW50CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBldmVudCB0aGUgYnJvd3Nlci1vcmlnaW5hdGVkIGV2ZW50IHRvIGxpc3RlbiB0bwogICAgICBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lIHRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbCBvbiB0aGUgdmlldwogICAgKi8KICAgIHNldHVwSGFuZGxlcjogZnVuY3Rpb24gc2V0dXBIYW5kbGVyKHJvb3RFbGVtZW50LCBldmVudCwgZXZlbnROYW1lKSB7CiAgICAgIGlmIChldmVudE5hbWUgPT09IG51bGwpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGlmICghX2RlcHJlY2F0ZWRGZWF0dXJlcy5KUVVFUllfSU5URUdSQVRJT04gfHwgX2pxdWVyeS5qUXVlcnlEaXNhYmxlZCkgewogICAgICAgIHZhciB2aWV3SGFuZGxlciA9IGZ1bmN0aW9uIHZpZXdIYW5kbGVyKHRhcmdldCwgZXZlbnQpIHsKICAgICAgICAgIHZhciB2aWV3ID0gKDAsIF92aWV3cy5nZXRFbGVtZW50VmlldykodGFyZ2V0KTsKICAgICAgICAgIHZhciByZXN1bHQgPSB0cnVlOwoKICAgICAgICAgIGlmICh2aWV3KSB7CiAgICAgICAgICAgIHJlc3VsdCA9IHZpZXcuaGFuZGxlRXZlbnQoZXZlbnROYW1lLCBldmVudCk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9OwoKICAgICAgICB2YXIgYWN0aW9uSGFuZGxlciA9IGZ1bmN0aW9uIGFjdGlvbkhhbmRsZXIodGFyZ2V0LCBldmVudCkgewogICAgICAgICAgdmFyIGFjdGlvbklkID0gdGFyZ2V0LmdldEF0dHJpYnV0ZSgnZGF0YS1lbWJlci1hY3Rpb24nKTsKICAgICAgICAgIHZhciBhY3Rpb25zID0gX2FjdGlvbl9tYW5hZ2VyLmRlZmF1bHQucmVnaXN0ZXJlZEFjdGlvbnNbYWN0aW9uSWRdOyAvLyBJbiBHbGltbWVyMiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYW4gZW1wdHkgc3RyaW5nIGFuZCBhbiBhZGRpdGlvbmFsCiAgICAgICAgICAvLyBhdHRyaWJ1dGUgaXQgc2V0IGZvciBlYWNoIGFjdGlvbiBvbiBhIGdpdmVuIGVsZW1lbnQuIEluIHRoaXMgY2FzZSwgdGhlCiAgICAgICAgICAvLyBhdHRyaWJ1dGVzIG5lZWQgdG8gYmUgcmVhZCBzbyB0aGF0IGEgcHJvcGVyIHNldCBvZiBhY3Rpb24gaGFuZGxlcnMgY2FuCiAgICAgICAgICAvLyBiZSBjb2FsZXNjZWQuCgogICAgICAgICAgaWYgKGFjdGlvbklkID09PSAnJykgewogICAgICAgICAgICB2YXIgYXR0cmlidXRlcyA9IHRhcmdldC5hdHRyaWJ1dGVzOwogICAgICAgICAgICB2YXIgYXR0cmlidXRlQ291bnQgPSBhdHRyaWJ1dGVzLmxlbmd0aDsKICAgICAgICAgICAgYWN0aW9ucyA9IFtdOwoKICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhdHRyaWJ1dGVDb3VudDsgaSsrKSB7CiAgICAgICAgICAgICAgdmFyIGF0dHIgPSBhdHRyaWJ1dGVzLml0ZW0oaSk7CiAgICAgICAgICAgICAgdmFyIGF0dHJOYW1lID0gYXR0ci5uYW1lOwoKICAgICAgICAgICAgICBpZiAoYXR0ck5hbWUuaW5kZXhPZignZGF0YS1lbWJlci1hY3Rpb24tJykgPT09IDApIHsKICAgICAgICAgICAgICAgIGFjdGlvbnMgPSBhY3Rpb25zLmNvbmNhdChfYWN0aW9uX21hbmFnZXIuZGVmYXVsdC5yZWdpc3RlcmVkQWN0aW9uc1thdHRyLnZhbHVlXSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9IC8vIFdlIGhhdmUgdG8gY2hlY2sgZm9yIGFjdGlvbnMgaGVyZSBzaW5jZSBpbiBzb21lIGNhc2VzLCBqUXVlcnkgd2lsbCB0cmlnZ2VyCiAgICAgICAgICAvLyBhbiBldmVudCBvbiBgcmVtb3ZlQ2hpbGRgIChpLmUuIGZvY3Vzb3V0KSBhZnRlciB3ZSd2ZSBhbHJlYWR5IHRvcm4gZG93biB0aGUKICAgICAgICAgIC8vIGFjdGlvbiBoYW5kbGVycyBmb3IgdGhlIHZpZXcuCgoKICAgICAgICAgIGlmICghYWN0aW9ucykgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CgogICAgICAgICAgdmFyIHJlc3VsdCA9IHRydWU7CgogICAgICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGFjdGlvbnMubGVuZ3RoOyBpbmRleCsrKSB7CiAgICAgICAgICAgIHZhciBhY3Rpb24gPSBhY3Rpb25zW2luZGV4XTsKCiAgICAgICAgICAgIGlmIChhY3Rpb24gJiYgYWN0aW9uLmV2ZW50TmFtZSA9PT0gZXZlbnROYW1lKSB7CiAgICAgICAgICAgICAgLy8gcmV0dXJuIGZhbHNlIGlmIGFueSBvZiB0aGUgYWN0aW9uIGhhbmRsZXJzIHJldHVybnMgZmFsc2UKICAgICAgICAgICAgICByZXN1bHQgPSBhY3Rpb24uaGFuZGxlcihldmVudCkgJiYgcmVzdWx0OwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9OyAvLyBTcGVjaWFsIGhhbmRsaW5nIG9mIGV2ZW50cyB0aGF0IGRvbid0IGJ1YmJsZSAoZXZlbnQgZGVsZWdhdGlvbiBkb2VzIG5vdCB3b3JrKS4KICAgICAgICAvLyBNaW1pY3MgdGhlIHdheSB0aGlzIGlzIGhhbmRsZWQgaW4galF1ZXJ5LAogICAgICAgIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vanF1ZXJ5L2pxdWVyeS9ibG9iLzg5OWM1NmY2YWRhMjY4MjFlOGFmMTJkOWYzNWZhMDM5MTAwZTgzOGUvc3JjL2V2ZW50LmpzI0w2NjYtTDcwMAoKCiAgICAgICAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuTU9VU0VfRU5URVJfTEVBVkVfTU9WRV9FVkVOVFMgJiYgRVZFTlRfTUFQW2V2ZW50XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YXIgbWFwcGVkRXZlbnRUeXBlID0gRVZFTlRfTUFQW2V2ZW50XTsKICAgICAgICAgIHZhciBvcmlnRXZlbnRUeXBlID0gZXZlbnQ7CgogICAgICAgICAgdmFyIGNyZWF0ZUZha2VFdmVudCA9IGZ1bmN0aW9uIGNyZWF0ZUZha2VFdmVudChldmVudFR5cGUsIGV2ZW50KSB7CiAgICAgICAgICAgIHZhciBmYWtlRXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnTW91c2VFdmVudCcpOwogICAgICAgICAgICBmYWtlRXZlbnQuaW5pdE1vdXNlRXZlbnQoZXZlbnRUeXBlLCBmYWxzZSwgZmFsc2UsIGV2ZW50LnZpZXcsIGV2ZW50LmRldGFpbCwgZXZlbnQuc2NyZWVuWCwgZXZlbnQuc2NyZWVuWSwgZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSwgZXZlbnQuY3RybEtleSwgZXZlbnQuYWx0S2V5LCBldmVudC5zaGlmdEtleSwgZXZlbnQubWV0YUtleSwgZXZlbnQuYnV0dG9uLCBldmVudC5yZWxhdGVkVGFyZ2V0KTsgLy8gZmFrZSBldmVudC50YXJnZXQgYXMgd2UgZG9uJ3QgZGlzcGF0Y2ggdGhlIGV2ZW50CgogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZmFrZUV2ZW50LCAndGFyZ2V0JywgewogICAgICAgICAgICAgIHZhbHVlOiBldmVudC50YXJnZXQsCiAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgcmV0dXJuIGZha2VFdmVudDsKICAgICAgICAgIH07CgogICAgICAgICAgdmFyIGhhbmRsZU1hcHBlZEV2ZW50ID0gdGhpcy5fZXZlbnRIYW5kbGVyc1ttYXBwZWRFdmVudFR5cGVdID0gZnVuY3Rpb24gKGV2ZW50KSB7CiAgICAgICAgICAgIHZhciB0YXJnZXQgPSBldmVudC50YXJnZXQ7CiAgICAgICAgICAgIHZhciByZWxhdGVkID0gZXZlbnQucmVsYXRlZFRhcmdldDsKCiAgICAgICAgICAgIHdoaWxlICh0YXJnZXQgJiYgdGFyZ2V0Lm5vZGVUeXBlID09PSAxICYmIChyZWxhdGVkID09PSBudWxsIHx8IHJlbGF0ZWQgIT09IHRhcmdldCAmJiAhKDAsIF91dGlscy5jb250YWlucykodGFyZ2V0LCByZWxhdGVkKSkpIHsKICAgICAgICAgICAgICAvLyBtb3VzZUVudGVyL0xlYXZlIGRvbid0IGJ1YmJsZSwgc28gdGhlcmUgaXMgbm8gbG9naWMgdG8gcHJldmVudCBpdCBhcyB3aXRoIG90aGVyIGV2ZW50cwogICAgICAgICAgICAgIGlmICgoMCwgX3ZpZXdzLmdldEVsZW1lbnRWaWV3KSh0YXJnZXQpKSB7CiAgICAgICAgICAgICAgICB2aWV3SGFuZGxlcih0YXJnZXQsIGNyZWF0ZUZha2VFdmVudChvcmlnRXZlbnRUeXBlLCBldmVudCkpOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0Lmhhc0F0dHJpYnV0ZSgnZGF0YS1lbWJlci1hY3Rpb24nKSkgewogICAgICAgICAgICAgICAgYWN0aW9uSGFuZGxlcih0YXJnZXQsIGNyZWF0ZUZha2VFdmVudChvcmlnRXZlbnRUeXBlLCBldmVudCkpOwogICAgICAgICAgICAgIH0gLy8gc2VwYXJhdGUgbW91c2VFbnRlci9MZWF2ZSBldmVudHMgYXJlIGRpc3BhdGNoZWQgZm9yIGVhY2ggbGlzdGVuaW5nIGVsZW1lbnQKICAgICAgICAgICAgICAvLyB1bnRpbCB0aGUgZWxlbWVudCAocmVsYXRlZCkgaGFzIGJlZW4gcmVhY2hlZCB0aGF0IHRoZSBwb2ludGluZyBkZXZpY2UgZXhpdGVkIGZyb20vdG8KCgogICAgICAgICAgICAgIHRhcmdldCA9IHRhcmdldC5wYXJlbnROb2RlOwogICAgICAgICAgICB9CiAgICAgICAgICB9OwoKICAgICAgICAgIHJvb3RFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIobWFwcGVkRXZlbnRUeXBlLCBoYW5kbGVNYXBwZWRFdmVudCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBoYW5kbGVFdmVudCA9IHRoaXMuX2V2ZW50SGFuZGxlcnNbZXZlbnRdID0gZnVuY3Rpb24gKGV2ZW50KSB7CiAgICAgICAgICAgIHZhciB0YXJnZXQgPSBldmVudC50YXJnZXQ7CgogICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgaWYgKCgwLCBfdmlld3MuZ2V0RWxlbWVudFZpZXcpKHRhcmdldCkpIHsKICAgICAgICAgICAgICAgIGlmICh2aWV3SGFuZGxlcih0YXJnZXQsIGV2ZW50KSA9PT0gZmFsc2UpIHsKICAgICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsKICAgICAgICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChldmVudC5jYW5jZWxCdWJibGUgPT09IHRydWUpIHsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGFyZ2V0Lmhhc0F0dHJpYnV0ZSA9PT0gJ2Z1bmN0aW9uJyAmJiB0YXJnZXQuaGFzQXR0cmlidXRlKCdkYXRhLWVtYmVyLWFjdGlvbicpKSB7CiAgICAgICAgICAgICAgICBpZiAoYWN0aW9uSGFuZGxlcih0YXJnZXQsIGV2ZW50KSA9PT0gZmFsc2UpIHsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICB0YXJnZXQgPSB0YXJnZXQucGFyZW50Tm9kZTsKICAgICAgICAgICAgfSB3aGlsZSAodGFyZ2V0ICYmIHRhcmdldC5ub2RlVHlwZSA9PT0gMSk7CiAgICAgICAgICB9OwoKICAgICAgICAgIHJvb3RFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGhhbmRsZUV2ZW50KTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcm9vdEVsZW1lbnQub24oZXZlbnQgKyAiLmVtYmVyIiwgJy5lbWJlci12aWV3JywgZnVuY3Rpb24gKGV2dCkgewogICAgICAgICAgdmFyIHZpZXcgPSAoMCwgX3ZpZXdzLmdldEVsZW1lbnRWaWV3KSh0aGlzKTsKICAgICAgICAgIHZhciByZXN1bHQgPSB0cnVlOwoKICAgICAgICAgIGlmICh2aWV3KSB7CiAgICAgICAgICAgIHJlc3VsdCA9IHZpZXcuaGFuZGxlRXZlbnQoZXZlbnROYW1lLCAoMCwgX2pxdWVyeV9ldmVudF9kZXByZWNhdGlvbi5kZWZhdWx0KShldnQpKTsKICAgICAgICAgIH0KCiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0pOwogICAgICAgIHJvb3RFbGVtZW50Lm9uKGV2ZW50ICsgIi5lbWJlciIsICdbZGF0YS1lbWJlci1hY3Rpb25dJywgZnVuY3Rpb24gKGV2dCkgewogICAgICAgICAgdmFyIGF0dHJpYnV0ZXMgPSBldnQuY3VycmVudFRhcmdldC5hdHRyaWJ1dGVzOwogICAgICAgICAgdmFyIGhhbmRsZWRBY3Rpb25zID0gW107CiAgICAgICAgICBldnQgPSAoMCwgX2pxdWVyeV9ldmVudF9kZXByZWNhdGlvbi5kZWZhdWx0KShldnQpOwoKICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXR0cmlidXRlcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICB2YXIgYXR0ciA9IGF0dHJpYnV0ZXMuaXRlbShpKTsKICAgICAgICAgICAgdmFyIGF0dHJOYW1lID0gYXR0ci5uYW1lOwoKICAgICAgICAgICAgaWYgKGF0dHJOYW1lLmxhc3RJbmRleE9mKCdkYXRhLWVtYmVyLWFjdGlvbi0nLCAwKSAhPT0gLTEpIHsKICAgICAgICAgICAgICB2YXIgYWN0aW9uID0gX2FjdGlvbl9tYW5hZ2VyLmRlZmF1bHQucmVnaXN0ZXJlZEFjdGlvbnNbYXR0ci52YWx1ZV07IC8vIFdlIGhhdmUgdG8gY2hlY2sgZm9yIGFjdGlvbiBoZXJlIHNpbmNlIGluIHNvbWUgY2FzZXMsIGpRdWVyeSB3aWxsIHRyaWdnZXIKICAgICAgICAgICAgICAvLyBhbiBldmVudCBvbiBgcmVtb3ZlQ2hpbGRgIChpLmUuIGZvY3Vzb3V0KSBhZnRlciB3ZSd2ZSBhbHJlYWR5IHRvcm4gZG93biB0aGUKICAgICAgICAgICAgICAvLyBhY3Rpb24gaGFuZGxlcnMgZm9yIHRoZSB2aWV3LgoKICAgICAgICAgICAgICBpZiAoYWN0aW9uICYmIGFjdGlvbi5ldmVudE5hbWUgPT09IGV2ZW50TmFtZSAmJiBoYW5kbGVkQWN0aW9ucy5pbmRleE9mKGFjdGlvbikgPT09IC0xKSB7CiAgICAgICAgICAgICAgICBhY3Rpb24uaGFuZGxlcihldnQpOyAvLyBBY3Rpb24gaGFuZGxlcnMgY2FuIG11dGF0ZSBzdGF0ZSB3aGljaCBpbiB0dXJuIGNyZWF0ZXMgbmV3IGF0dHJpYnV0ZXMgb24gdGhlIGVsZW1lbnQuCiAgICAgICAgICAgICAgICAvLyBUaGlzIGVmZmVjdCBjb3VsZCBjYXVzZSB0aGUgYGRhdGEtZW1iZXItYWN0aW9uYCBhdHRyaWJ1dGUgdG8gc2hpZnQgZG93biBhbmQgYmUgaW52b2tlZCB0d2ljZS4KICAgICAgICAgICAgICAgIC8vIFRvIGF2b2lkIHRoaXMsIHdlIGtlZXAgdHJhY2sgb2Ygd2hpY2ggYWN0aW9ucyBoYXZlIGJlZW4gaGFuZGxlZC4KCiAgICAgICAgICAgICAgICBoYW5kbGVkQWN0aW9ucy5wdXNoKGFjdGlvbik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0sCiAgICBkZXN0cm95OiBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICB2YXIgcm9vdEVsZW1lbnRTZWxlY3RvciA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCAncm9vdEVsZW1lbnQnKTsKICAgICAgdmFyIHJvb3RFbGVtZW50OwoKICAgICAgaWYgKHJvb3RFbGVtZW50U2VsZWN0b3Iubm9kZVR5cGUpIHsKICAgICAgICByb290RWxlbWVudCA9IHJvb3RFbGVtZW50U2VsZWN0b3I7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcm9vdEVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHJvb3RFbGVtZW50U2VsZWN0b3IpOwogICAgICB9CgogICAgICBpZiAoIXJvb3RFbGVtZW50KSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAoIV9kZXByZWNhdGVkRmVhdHVyZXMuSlFVRVJZX0lOVEVHUkFUSU9OIHx8IF9qcXVlcnkualF1ZXJ5RGlzYWJsZWQpIHsKICAgICAgICBmb3IgKHZhciBldmVudCBpbiB0aGlzLl9ldmVudEhhbmRsZXJzKSB7CiAgICAgICAgICByb290RWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCB0aGlzLl9ldmVudEhhbmRsZXJzW2V2ZW50XSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgICgwLCBfanF1ZXJ5LmpRdWVyeSkocm9vdEVsZW1lbnRTZWxlY3Rvcikub2ZmKCcuZW1iZXInLCAnKionKTsKICAgICAgfQoKICAgICAgcm9vdEVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShST09UX0VMRU1FTlRfQ0xBU1MpOwogICAgICByZXR1cm4gdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0sCiAgICB0b1N0cmluZzogZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiAnKEV2ZW50RGlzcGF0Y2hlciknOwogICAgfQogIH0pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vanF1ZXJ5IiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL2Jyb3dzZXItZW52aXJvbm1lbnQiLCAiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW52aXJvbm1lbnQsIF9icm93c2VyRW52aXJvbm1lbnQsIF9kZXByZWNhdGVkRmVhdHVyZXMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmpRdWVyeURpc2FibGVkID0gX2V4cG9ydHMualF1ZXJ5ID0gdm9pZCAwOwogIHZhciBqUXVlcnk7CiAgX2V4cG9ydHMualF1ZXJ5ID0galF1ZXJ5OwogIHZhciBqUXVlcnlEaXNhYmxlZCA9ICFfZGVwcmVjYXRlZEZlYXR1cmVzLkpRVUVSWV9JTlRFR1JBVElPTiB8fCBfZW52aXJvbm1lbnQuRU5WLl9KUVVFUllfSU5URUdSQVRJT04gPT09IGZhbHNlOwogIF9leHBvcnRzLmpRdWVyeURpc2FibGVkID0galF1ZXJ5RGlzYWJsZWQ7CgogIGlmIChfZGVwcmVjYXRlZEZlYXR1cmVzLkpRVUVSWV9JTlRFR1JBVElPTiAmJiBfYnJvd3NlckVudmlyb25tZW50Lmhhc0RPTSkgewogICAgX2V4cG9ydHMualF1ZXJ5ID0galF1ZXJ5ID0gX2Vudmlyb25tZW50LmNvbnRleHQuaW1wb3J0cy5qUXVlcnk7CgogICAgaWYgKCFqUXVlcnlEaXNhYmxlZCAmJiBqUXVlcnkpIHsKICAgICAgaWYgKGpRdWVyeS5ldmVudC5hZGRQcm9wKSB7CiAgICAgICAgalF1ZXJ5LmV2ZW50LmFkZFByb3AoJ2RhdGFUcmFuc2ZlcicpOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIGh0dHA6Ly93d3cud2hhdHdnLm9yZy9zcGVjcy93ZWItYXBwcy9jdXJyZW50LXdvcmsvbXVsdGlwYWdlL2RuZC5odG1sI2RuZGV2ZW50cwogICAgICAgIFsnZHJhZ3N0YXJ0JywgJ2RyYWcnLCAnZHJhZ2VudGVyJywgJ2RyYWdsZWF2ZScsICdkcmFnb3ZlcicsICdkcm9wJywgJ2RyYWdlbmQnXS5mb3JFYWNoKGZ1bmN0aW9uIChldmVudE5hbWUpIHsKICAgICAgICAgIGpRdWVyeS5ldmVudC5maXhIb29rc1tldmVudE5hbWVdID0gewogICAgICAgICAgICBwcm9wczogWydkYXRhVHJhbnNmZXInXQogICAgICAgICAgfTsKICAgICAgICB9KTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgX2V4cG9ydHMualF1ZXJ5ID0galF1ZXJ5ID0gdW5kZWZpbmVkOwogICAgICBfZXhwb3J0cy5qUXVlcnlEaXNhYmxlZCA9IGpRdWVyeURpc2FibGVkID0gdHJ1ZTsKICAgIH0KICB9Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi9zeXN0ZW0vanF1ZXJ5X2V2ZW50X2RlcHJlY2F0aW9uIiwgWyJleHBvcnRzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvZGVwcmVjYXRlZC1mZWF0dXJlcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9kZWJ1ZywgX2Vudmlyb25tZW50LCBfdXRpbHMsIF9kZXByZWNhdGVkRmVhdHVyZXMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSBhZGRKUXVlcnlFdmVudERlcHJlY2F0aW9uOwoKICAvKiBnbG9iYWwgUHJveHkgKi8KICBmdW5jdGlvbiBhZGRKUXVlcnlFdmVudERlcHJlY2F0aW9uKGpxRXZlbnQpIHsKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICYmIF9kZXByZWNhdGVkRmVhdHVyZXMuSlFVRVJZX0lOVEVHUkFUSU9OICYmIF91dGlscy5IQVNfTkFUSVZFX1BST1hZKSB7CiAgICAgIHZhciBib3VuZEZ1bmN0aW9ucyA9IG5ldyBNYXAoKTsgLy8gd3JhcCB0aGUgalF1ZXJ5IGV2ZW50IGluIGEgUHJveHkgdG8gYWRkIHRoZSBkZXByZWNhdGlvbiBtZXNzYWdlIGZvciBvcmlnaW5hbEV2ZW50LCBhY2NvcmRpbmcgdG8gUkZDIzI5NAogICAgICAvLyB3ZSBuZWVkIGEgbmF0aXZlIFByb3h5IGhlcmUsIHNvIHdlIGNhbiBtYWtlIHN1cmUgdGhhdCB0aGUgaW50ZXJuYWwgdXNlIG9mIG9yaWdpbmFsRXZlbnQgaW4galF1ZXJ5IGl0c2VsZiBkb2VzCiAgICAgIC8vIG5vdCB0cmlnZ2VyIGEgZGVwcmVjYXRpb24KCiAgICAgIHJldHVybiBuZXcgUHJveHkoanFFdmVudCwgewogICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KHRhcmdldCwgbmFtZSkgewogICAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICAgIGNhc2UgJ29yaWdpbmFsRXZlbnQnOgogICAgICAgICAgICAgIChmYWxzZSAmJiAhKGZ1bmN0aW9uIChFbWJlckVOVikgewogICAgICAgICAgICAgICAgLy8gdGhpcyBkZXByZWNhdGlvbiBpcyBpbnRlbnRpb25hbGx5IGNoZWNraW5nIGBnbG9iYWwuRW1iZXJFTlZgIC8KICAgICAgICAgICAgICAgIC8vIGBnbG9iYWwuRU5WYCBzbyB0aGF0IHdlIGNhbiBlbnN1cmUgd2UgX29ubHlfIGRlcHJlY2F0ZSBpbiB0aGUKICAgICAgICAgICAgICAgIC8vIGNhc2Ugd2hlcmUgalF1ZXJ5IGludGVncmF0aW9uIGlzIGVuYWJsZWQgaW1wbGljaXRseSAoZS5nLgogICAgICAgICAgICAgICAgLy8gImRlZmF1bHRlZCIgdG8gZW5hYmxlZCkgYXMgb3Bwb3NlZCB0byB3aGVuIHRoZSB1c2VyIGV4cGxpY2l0bHkKICAgICAgICAgICAgICAgIC8vIG9wdHMgaW4gdG8gdXNpbmcgalF1ZXJ5CiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIEVtYmVyRU5WICE9PSAnb2JqZWN0JyB8fCBFbWJlckVOViA9PT0gbnVsbCkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgcmV0dXJuIEVtYmVyRU5WLl9KUVVFUllfSU5URUdSQVRJT04gPT09IHRydWU7CiAgICAgICAgICAgICAgfShfZW52aXJvbm1lbnQuZ2xvYmFsLkVtYmVyRU5WIHx8IF9lbnZpcm9ubWVudC5nbG9iYWwuRU5WKSkgJiYgKDAsIF9kZWJ1Zy5kZXByZWNhdGUpKCdBY2Nlc3NpbmcgalF1ZXJ5LkV2ZW50IHNwZWNpZmljIHByb3BlcnRpZXMgaXMgZGVwcmVjYXRlZC4gRWl0aGVyIHVzZSB0aGUgZW1iZXItanF1ZXJ5LWxlZ2FjeSBhZGRvbiB0byBub3JtYWxpemUgZXZlbnRzIHRvIG5hdGl2ZSBldmVudHMsIG9yIGV4cGxpY2l0bHkgb3B0IGludG8galF1ZXJ5IGludGVncmF0aW9uIHVzaW5nIEBlbWJlci9vcHRpb25hbC1mZWF0dXJlcy4nLCBmdW5jdGlvbiAoRW1iZXJFTlYpIHsKICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgRW1iZXJFTlYgIT09ICdvYmplY3QnIHx8IEVtYmVyRU5WID09PSBudWxsKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICByZXR1cm4gRW1iZXJFTlYuX0pRVUVSWV9JTlRFR1JBVElPTiA9PT0gdHJ1ZTsKICAgICAgICAgICAgICB9KF9lbnZpcm9ubWVudC5nbG9iYWwuRW1iZXJFTlYgfHwgX2Vudmlyb25tZW50Lmdsb2JhbC5FTlYpLCB7CiAgICAgICAgICAgICAgICBpZDogJ2VtYmVyLXZpZXdzLmV2ZW50LWRpc3BhdGNoZXIuanF1ZXJ5LWV2ZW50JywKICAgICAgICAgICAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9lbWJlcmpzLmNvbS9kZXByZWNhdGlvbnMvdjMueCN0b2NfanF1ZXJ5LWV2ZW50JwogICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICByZXR1cm4gdGFyZ2V0W25hbWVdOwogICAgICAgICAgICAvLyBwcm92aWRlIGFuIGVzY2FwZSBoYXRjaCBmb3IgZW1iZXItanF1ZXJ5LWxlZ2FjeSB0byBhY2Nlc3Mgb3JpZ2luYWxFdmVudCB3aXRob3V0IGEgZGVwcmVjYXRpb24KCiAgICAgICAgICAgIGNhc2UgJ19fb3JpZ2luYWxFdmVudCc6CiAgICAgICAgICAgICAgcmV0dXJuIHRhcmdldC5vcmlnaW5hbEV2ZW50OwoKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldFtuYW1lXSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgICAgICAgICAgLy8gY2FjaGUgZnVuY3Rpb25zIGZvciByZXVzZQogICAgICAgICAgICAgICAgaWYgKCFib3VuZEZ1bmN0aW9ucy5oYXMobmFtZSkpIHsKICAgICAgICAgICAgICAgICAgLy8gZm9yIGpRdWVyeS5FdmVudCBtZXRob2RzIGNhbGwgdGhlbSB3aXRoIGB0YXJnZXRgIGFzIHRoZSBgdGhpc2AgY29udGV4dCwgc28gdGhleSB3aWxsIGFjY2VzcwogICAgICAgICAgICAgICAgICAvLyBgb3JpZ2luYWxFdmVudGAgZnJvbSB0aGUgb3JpZ2luYWwgalF1ZXJ5IGV2ZW50LCBub3Qgb3VyIHByb3h5LCB0aHVzIG5vdCB0cmlnZ2VyIHRoZSBkZXByZWNhdGlvbgogICAgICAgICAgICAgICAgICBib3VuZEZ1bmN0aW9ucy5zZXQobmFtZSwgdGFyZ2V0W25hbWVdLmJpbmQodGFyZ2V0KSk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgcmV0dXJuIGJvdW5kRnVuY3Rpb25zLmdldChuYW1lKTsKICAgICAgICAgICAgICB9IC8vIHNhbWUgZm9yIGpRdWVyeSdzIGdldHRlciBmdW5jdGlvbnMgZm9yIHNpbXBsZSBwcm9wZXJ0aWVzCgoKICAgICAgICAgICAgICByZXR1cm4gdGFyZ2V0W25hbWVdOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICB9CgogICAgcmV0dXJuIGpxRXZlbnQ7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL2xvb2t1cF9wYXJ0aWFsIiwgWyJleHBvcnRzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvZXJyb3IiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVidWcsIF9lcnJvcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IGxvb2t1cFBhcnRpYWw7CiAgX2V4cG9ydHMuaGFzUGFydGlhbCA9IGhhc1BhcnRpYWw7CgogIGZ1bmN0aW9uIHBhcnNlVW5kZXJzY29yZWROYW1lKHRlbXBsYXRlTmFtZSkgewogICAgdmFyIG5hbWVQYXJ0cyA9IHRlbXBsYXRlTmFtZS5zcGxpdCgnLycpOwogICAgdmFyIGxhc3RQYXJ0ID0gbmFtZVBhcnRzW25hbWVQYXJ0cy5sZW5ndGggLSAxXTsKICAgIG5hbWVQYXJ0c1tuYW1lUGFydHMubGVuZ3RoIC0gMV0gPSAiXyIgKyBsYXN0UGFydDsKICAgIHJldHVybiBuYW1lUGFydHMuam9pbignLycpOwogIH0KCiAgZnVuY3Rpb24gbG9va3VwUGFydGlhbCh0ZW1wbGF0ZU5hbWUsIG93bmVyKSB7CiAgICBpZiAodGVtcGxhdGVOYW1lID09IG51bGwpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciB0ZW1wbGF0ZSA9IHRlbXBsYXRlRm9yKG93bmVyLCBwYXJzZVVuZGVyc2NvcmVkTmFtZSh0ZW1wbGF0ZU5hbWUpLCB0ZW1wbGF0ZU5hbWUpOwogICAgKGZhbHNlICYmICEoQm9vbGVhbih0ZW1wbGF0ZSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVW5hYmxlIHRvIGZpbmQgcGFydGlhbCB3aXRoIG5hbWUgXCIiICsgdGVtcGxhdGVOYW1lICsgIlwiIiwgQm9vbGVhbih0ZW1wbGF0ZSkpKTsKICAgIHJldHVybiB0ZW1wbGF0ZTsKICB9CgogIGZ1bmN0aW9uIGhhc1BhcnRpYWwobmFtZSwgb3duZXIpIHsKICAgIGlmICghb3duZXIpIHsKICAgICAgdGhyb3cgbmV3IF9lcnJvci5kZWZhdWx0KCdDb250YWluZXIgd2FzIG5vdCBmb3VuZCB3aGVuIGxvb2tpbmcgdXAgYSB2aWV3cyB0ZW1wbGF0ZS4gJyArICdUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBtYW51YWxseSBpbnN0YW50aWF0aW5nIGFuIEVtYmVyLlZpZXcuICcgKyAnU2VlOiBodHRwOi8vZ2l0LmlvL0VLUHBuQScpOwogICAgfQoKICAgIHJldHVybiBvd25lci5oYXNSZWdpc3RyYXRpb24oInRlbXBsYXRlOiIgKyBwYXJzZVVuZGVyc2NvcmVkTmFtZShuYW1lKSkgfHwgb3duZXIuaGFzUmVnaXN0cmF0aW9uKCJ0ZW1wbGF0ZToiICsgbmFtZSk7CiAgfQoKICBmdW5jdGlvbiB0ZW1wbGF0ZUZvcihvd25lciwgdW5kZXJzY29yZWQsIG5hbWUpIHsKICAgIGlmICghbmFtZSkgewogICAgICByZXR1cm47CiAgICB9CgogICAgKGZhbHNlICYmICEobmFtZS5pbmRleE9mKCcuJykgPT09IC0xKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoInRlbXBsYXRlTmFtZXMgYXJlIG5vdCBhbGxvd2VkIHRvIGNvbnRhaW4gcGVyaW9kczogIiArIG5hbWUsIG5hbWUuaW5kZXhPZignLicpID09PSAtMSkpOwoKICAgIGlmICghb3duZXIpIHsKICAgICAgdGhyb3cgbmV3IF9lcnJvci5kZWZhdWx0KCdDb250YWluZXIgd2FzIG5vdCBmb3VuZCB3aGVuIGxvb2tpbmcgdXAgYSB2aWV3cyB0ZW1wbGF0ZS4gJyArICdUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBtYW51YWxseSBpbnN0YW50aWF0aW5nIGFuIEVtYmVyLlZpZXcuICcgKyAnU2VlOiBodHRwOi8vZ2l0LmlvL0VLUHBuQScpOwogICAgfQoKICAgIHJldHVybiBvd25lci5sb29rdXAoInRlbXBsYXRlOiIgKyB1bmRlcnNjb3JlZCkgfHwgb3duZXIubG9va3VwKCJ0ZW1wbGF0ZToiICsgbmFtZSk7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvc3lzdGVtL3V0aWxzIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL293bmVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX293bmVyLCBfdXRpbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmlzU2ltcGxlQ2xpY2sgPSBpc1NpbXBsZUNsaWNrOwogIF9leHBvcnRzLmNvbnN0cnVjdFN0eWxlRGVwcmVjYXRpb25NZXNzYWdlID0gY29uc3RydWN0U3R5bGVEZXByZWNhdGlvbk1lc3NhZ2U7CiAgX2V4cG9ydHMuZ2V0Um9vdFZpZXdzID0gZ2V0Um9vdFZpZXdzOwogIF9leHBvcnRzLmdldFZpZXdJZCA9IGdldFZpZXdJZDsKICBfZXhwb3J0cy5nZXRFbGVtZW50VmlldyA9IGdldEVsZW1lbnRWaWV3OwogIF9leHBvcnRzLmdldFZpZXdFbGVtZW50ID0gZ2V0Vmlld0VsZW1lbnQ7CiAgX2V4cG9ydHMuc2V0RWxlbWVudFZpZXcgPSBzZXRFbGVtZW50VmlldzsKICBfZXhwb3J0cy5zZXRWaWV3RWxlbWVudCA9IHNldFZpZXdFbGVtZW50OwogIF9leHBvcnRzLmNsZWFyRWxlbWVudFZpZXcgPSBjbGVhckVsZW1lbnRWaWV3OwogIF9leHBvcnRzLmNsZWFyVmlld0VsZW1lbnQgPSBjbGVhclZpZXdFbGVtZW50OwogIF9leHBvcnRzLmdldENoaWxkVmlld3MgPSBnZXRDaGlsZFZpZXdzOwogIF9leHBvcnRzLmluaXRDaGlsZFZpZXdzID0gaW5pdENoaWxkVmlld3M7CiAgX2V4cG9ydHMuYWRkQ2hpbGRWaWV3ID0gYWRkQ2hpbGRWaWV3OwogIF9leHBvcnRzLmNvbGxlY3RDaGlsZFZpZXdzID0gY29sbGVjdENoaWxkVmlld3M7CiAgX2V4cG9ydHMuZ2V0Vmlld0JvdW5kcyA9IGdldFZpZXdCb3VuZHM7CiAgX2V4cG9ydHMuZ2V0Vmlld1JhbmdlID0gZ2V0Vmlld1JhbmdlOwogIF9leHBvcnRzLmdldFZpZXdDbGllbnRSZWN0cyA9IGdldFZpZXdDbGllbnRSZWN0czsKICBfZXhwb3J0cy5nZXRWaWV3Qm91bmRpbmdDbGllbnRSZWN0ID0gZ2V0Vmlld0JvdW5kaW5nQ2xpZW50UmVjdDsKICBfZXhwb3J0cy5tYXRjaGVzID0gbWF0Y2hlczsKICBfZXhwb3J0cy5jb250YWlucyA9IGNvbnRhaW5zOwogIF9leHBvcnRzLmVsTWF0Y2hlcyA9IHZvaWQgMDsKCiAgLyogZ2xvYmFscyBFbGVtZW50ICovCgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwogIGZ1bmN0aW9uIGlzU2ltcGxlQ2xpY2soZXZlbnQpIHsKICAgIHZhciBtb2RpZmllciA9IGV2ZW50LnNoaWZ0S2V5IHx8IGV2ZW50Lm1ldGFLZXkgfHwgZXZlbnQuYWx0S2V5IHx8IGV2ZW50LmN0cmxLZXk7CiAgICB2YXIgc2Vjb25kYXJ5Q2xpY2sgPSBldmVudC53aGljaCA+IDE7IC8vIElFOSBtYXkgcmV0dXJuIHVuZGVmaW5lZAoKICAgIHJldHVybiAhbW9kaWZpZXIgJiYgIXNlY29uZGFyeUNsaWNrOwogIH0KCiAgZnVuY3Rpb24gY29uc3RydWN0U3R5bGVEZXByZWNhdGlvbk1lc3NhZ2UoYWZmZWN0ZWRTdHlsZSkgewogICAgcmV0dXJuICcnICsgJ0JpbmRpbmcgc3R5bGUgYXR0cmlidXRlcyBtYXkgaW50cm9kdWNlIGNyb3NzLXNpdGUgc2NyaXB0aW5nIHZ1bG5lcmFiaWxpdGllczsgJyArICdwbGVhc2UgZW5zdXJlIHRoYXQgdmFsdWVzIGJlaW5nIGJvdW5kIGFyZSBwcm9wZXJseSBlc2NhcGVkLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgJyArICdpbmNsdWRpbmcgaG93IHRvIGRpc2FibGUgdGhpcyB3YXJuaW5nLCBzZWUgJyArICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92MS54LyN0b2NfYmluZGluZy1zdHlsZS1hdHRyaWJ1dGVzLiAnICsgJ1N0eWxlIGFmZmVjdGVkOiAiJyArIGFmZmVjdGVkU3R5bGUgKyAnIic7CiAgfQogIC8qKgogICAgQHByaXZhdGUKICAgIEBtZXRob2QgZ2V0Um9vdFZpZXdzCiAgICBAcGFyYW0ge09iamVjdH0gb3duZXIKICAqLwoKCiAgZnVuY3Rpb24gZ2V0Um9vdFZpZXdzKG93bmVyKSB7CiAgICB2YXIgcmVnaXN0cnkgPSBvd25lci5sb29rdXAoJy12aWV3LXJlZ2lzdHJ5Om1haW4nKTsKICAgIHZhciByb290Vmlld3MgPSBbXTsKICAgIE9iamVjdC5rZXlzKHJlZ2lzdHJ5KS5mb3JFYWNoKGZ1bmN0aW9uIChpZCkgewogICAgICB2YXIgdmlldyA9IHJlZ2lzdHJ5W2lkXTsKCiAgICAgIGlmICh2aWV3LnBhcmVudFZpZXcgPT09IG51bGwpIHsKICAgICAgICByb290Vmlld3MucHVzaCh2aWV3KTsKICAgICAgfQogICAgfSk7CiAgICByZXR1cm4gcm9vdFZpZXdzOwogIH0KICAvKioKICAgIEBwcml2YXRlCiAgICBAbWV0aG9kIGdldFZpZXdJZAogICAgQHBhcmFtIHtFbWJlci5WaWV3fSB2aWV3CiAgICovCgoKICBmdW5jdGlvbiBnZXRWaWV3SWQodmlldykgewogICAgaWYgKHZpZXcudGFnTmFtZSAhPT0gJycgJiYgdmlldy5lbGVtZW50SWQpIHsKICAgICAgcmV0dXJuIHZpZXcuZWxlbWVudElkOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuICgwLCBfdXRpbHMuZ3VpZEZvcikodmlldyk7CiAgICB9CiAgfQoKICB2YXIgRUxFTUVOVF9WSUVXID0gbmV3IFdlYWtNYXAoKTsKICB2YXIgVklFV19FTEVNRU5UID0gbmV3IFdlYWtNYXAoKTsKCiAgZnVuY3Rpb24gZ2V0RWxlbWVudFZpZXcoZWxlbWVudCkgewogICAgcmV0dXJuIEVMRU1FTlRfVklFVy5nZXQoZWxlbWVudCkgfHwgbnVsbDsKICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCBnZXRWaWV3RWxlbWVudAogICAgQHBhcmFtIHtFbWJlci5WaWV3fSB2aWV3CiAgICovCgoKICBmdW5jdGlvbiBnZXRWaWV3RWxlbWVudCh2aWV3KSB7CiAgICByZXR1cm4gVklFV19FTEVNRU5ULmdldCh2aWV3KSB8fCBudWxsOwogIH0KCiAgZnVuY3Rpb24gc2V0RWxlbWVudFZpZXcoZWxlbWVudCwgdmlldykgewogICAgRUxFTUVOVF9WSUVXLnNldChlbGVtZW50LCB2aWV3KTsKICB9CgogIGZ1bmN0aW9uIHNldFZpZXdFbGVtZW50KHZpZXcsIGVsZW1lbnQpIHsKICAgIFZJRVdfRUxFTUVOVC5zZXQodmlldywgZWxlbWVudCk7CiAgfSAvLyBUaGVzZSBhcmUgbm90IG5lZWRlZCBmb3IgR0MsIGJ1dCBmb3IgY29ycmVjdG5lc3MuIFdlIHdhbnQgdG8gYmUgYWJsZSB0bwogIC8vIG51bGwtb3V0IHRoZXNlIGxpbmtzIHdoaWxlIHRoZSBvYmplY3RzIGFyZSBzdGlsbCBsaXZlLiBTcGVjaWZpY2FsbHksIGluCiAgLy8gdGhpcyBjYXNlLCB3ZSB3YW50IHRvIHByZXZlbnQgYWNjZXNzIHRvIHRoZSBlbGVtZW50IChhbmQgdmljZSB2ZXJzZSkgZHVyaW5nCiAgLy8gZGVzdHJ1Y3Rpb24uCgoKICBmdW5jdGlvbiBjbGVhckVsZW1lbnRWaWV3KGVsZW1lbnQpIHsKICAgIEVMRU1FTlRfVklFVy5kZWxldGUoZWxlbWVudCk7CiAgfQoKICBmdW5jdGlvbiBjbGVhclZpZXdFbGVtZW50KHZpZXcpIHsKICAgIFZJRVdfRUxFTUVOVC5kZWxldGUodmlldyk7CiAgfQoKICB2YXIgQ0hJTERfVklFV19JRFMgPSBuZXcgV2Vha01hcCgpOwogIC8qKgogICAgQHByaXZhdGUKICAgIEBtZXRob2QgZ2V0Q2hpbGRWaWV3cwogICAgQHBhcmFtIHtFbWJlci5WaWV3fSB2aWV3CiAgKi8KCiAgZnVuY3Rpb24gZ2V0Q2hpbGRWaWV3cyh2aWV3KSB7CiAgICB2YXIgb3duZXIgPSAoMCwgX293bmVyLmdldE93bmVyKSh2aWV3KTsKICAgIHZhciByZWdpc3RyeSA9IG93bmVyLmxvb2t1cCgnLXZpZXctcmVnaXN0cnk6bWFpbicpOwogICAgcmV0dXJuIGNvbGxlY3RDaGlsZFZpZXdzKHZpZXcsIHJlZ2lzdHJ5KTsKICB9CgogIGZ1bmN0aW9uIGluaXRDaGlsZFZpZXdzKHZpZXcpIHsKICAgIHZhciBjaGlsZFZpZXdzID0gbmV3IFNldCgpOwogICAgQ0hJTERfVklFV19JRFMuc2V0KHZpZXcsIGNoaWxkVmlld3MpOwogICAgcmV0dXJuIGNoaWxkVmlld3M7CiAgfQoKICBmdW5jdGlvbiBhZGRDaGlsZFZpZXcocGFyZW50LCBjaGlsZCkgewogICAgdmFyIGNoaWxkVmlld3MgPSBDSElMRF9WSUVXX0lEUy5nZXQocGFyZW50KTsKCiAgICBpZiAoY2hpbGRWaWV3cyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGNoaWxkVmlld3MgPSBpbml0Q2hpbGRWaWV3cyhwYXJlbnQpOwogICAgfQoKICAgIGNoaWxkVmlld3MuYWRkKGdldFZpZXdJZChjaGlsZCkpOwogIH0KCiAgZnVuY3Rpb24gY29sbGVjdENoaWxkVmlld3ModmlldywgcmVnaXN0cnkpIHsKICAgIHZhciB2aWV3cyA9IFtdOwogICAgdmFyIGNoaWxkVmlld3MgPSBDSElMRF9WSUVXX0lEUy5nZXQodmlldyk7CgogICAgaWYgKGNoaWxkVmlld3MgIT09IHVuZGVmaW5lZCkgewogICAgICBjaGlsZFZpZXdzLmZvckVhY2goZnVuY3Rpb24gKGlkKSB7CiAgICAgICAgdmFyIHZpZXcgPSByZWdpc3RyeVtpZF07CgogICAgICAgIGlmICh2aWV3ICYmICF2aWV3LmlzRGVzdHJveWluZyAmJiAhdmlldy5pc0Rlc3Ryb3llZCkgewogICAgICAgICAgdmlld3MucHVzaCh2aWV3KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQoKICAgIHJldHVybiB2aWV3czsKICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogICAgQG1ldGhvZCBnZXRWaWV3Qm91bmRzCiAgICBAcGFyYW0ge0VtYmVyLlZpZXd9IHZpZXcKICAqLwoKCiAgZnVuY3Rpb24gZ2V0Vmlld0JvdW5kcyh2aWV3KSB7CiAgICByZXR1cm4gdmlldy5yZW5kZXJlci5nZXRCb3VuZHModmlldyk7CiAgfQogIC8qKgogICAgQHByaXZhdGUKICAgIEBtZXRob2QgZ2V0Vmlld1JhbmdlCiAgICBAcGFyYW0ge0VtYmVyLlZpZXd9IHZpZXcKICAqLwoKCiAgZnVuY3Rpb24gZ2V0Vmlld1JhbmdlKHZpZXcpIHsKICAgIHZhciBib3VuZHMgPSBnZXRWaWV3Qm91bmRzKHZpZXcpOwogICAgdmFyIHJhbmdlID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTsKICAgIHJhbmdlLnNldFN0YXJ0QmVmb3JlKGJvdW5kcy5maXJzdE5vZGUpOwogICAgcmFuZ2Uuc2V0RW5kQWZ0ZXIoYm91bmRzLmxhc3ROb2RlKTsKICAgIHJldHVybiByYW5nZTsKICB9CiAgLyoqCiAgICBgZ2V0Vmlld0NsaWVudFJlY3RzYCBwcm92aWRlcyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcG9zaXRpb24gb2YgdGhlIGJvcmRlcgogICAgYm94IGVkZ2VzIG9mIGEgdmlldyByZWxhdGl2ZSB0byB0aGUgdmlld3BvcnQuCiAgCiAgICBJdCBpcyBvbmx5IGludGVuZGVkIHRvIGJlIHVzZWQgYnkgZGV2ZWxvcG1lbnQgdG9vbHMgbGlrZSB0aGUgRW1iZXIgSW5zcGVjdG9yCiAgICBhbmQgbWF5IG5vdCB3b3JrIG9uIG9sZGVyIGJyb3dzZXJzLgogIAogICAgQHByaXZhdGUKICAgIEBtZXRob2QgZ2V0Vmlld0NsaWVudFJlY3RzCiAgICBAcGFyYW0ge0VtYmVyLlZpZXd9IHZpZXcKICAqLwoKCiAgZnVuY3Rpb24gZ2V0Vmlld0NsaWVudFJlY3RzKHZpZXcpIHsKICAgIHZhciByYW5nZSA9IGdldFZpZXdSYW5nZSh2aWV3KTsKICAgIHJldHVybiByYW5nZS5nZXRDbGllbnRSZWN0cygpOwogIH0KICAvKioKICAgIGBnZXRWaWV3Qm91bmRpbmdDbGllbnRSZWN0YCBwcm92aWRlcyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcG9zaXRpb24gb2YgdGhlCiAgICBib3VuZGluZyBib3JkZXIgYm94IGVkZ2VzIG9mIGEgdmlldyByZWxhdGl2ZSB0byB0aGUgdmlld3BvcnQuCiAgCiAgICBJdCBpcyBvbmx5IGludGVuZGVkIHRvIGJlIHVzZWQgYnkgZGV2ZWxvcG1lbnQgdG9vbHMgbGlrZSB0aGUgRW1iZXIgSW5zcGVjdG9yCiAgICBhbmQgbWF5IG5vdCB3b3JrIG9uIG9sZGVyIGJyb3dzZXJzLgogIAogICAgQHByaXZhdGUKICAgIEBtZXRob2QgZ2V0Vmlld0JvdW5kaW5nQ2xpZW50UmVjdAogICAgQHBhcmFtIHtFbWJlci5WaWV3fSB2aWV3CiAgKi8KCgogIGZ1bmN0aW9uIGdldFZpZXdCb3VuZGluZ0NsaWVudFJlY3QodmlldykgewogICAgdmFyIHJhbmdlID0gZ2V0Vmlld1JhbmdlKHZpZXcpOwogICAgcmV0dXJuIHJhbmdlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOwogIH0KICAvKioKICAgIERldGVybWluZXMgaWYgdGhlIGVsZW1lbnQgbWF0Y2hlcyB0aGUgc3BlY2lmaWVkIHNlbGVjdG9yLgogIAogICAgQHByaXZhdGUKICAgIEBtZXRob2QgbWF0Y2hlcwogICAgQHBhcmFtIHtET01FbGVtZW50fSBlbAogICAgQHBhcmFtIHtTdHJpbmd9IHNlbGVjdG9yCiAgKi8KCgogIHZhciBlbE1hdGNoZXMgPSB0eXBlb2YgRWxlbWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgKEVsZW1lbnQucHJvdG90eXBlLm1hdGNoZXMgfHwgRWxlbWVudC5wcm90b3R5cGUubWF0Y2hlc1NlbGVjdG9yIHx8IEVsZW1lbnQucHJvdG90eXBlLm1vek1hdGNoZXNTZWxlY3RvciB8fCBFbGVtZW50LnByb3RvdHlwZS5tc01hdGNoZXNTZWxlY3RvciB8fCBFbGVtZW50LnByb3RvdHlwZS5vTWF0Y2hlc1NlbGVjdG9yIHx8IEVsZW1lbnQucHJvdG90eXBlLndlYmtpdE1hdGNoZXNTZWxlY3Rvcik7CiAgX2V4cG9ydHMuZWxNYXRjaGVzID0gZWxNYXRjaGVzOwoKICBmdW5jdGlvbiBtYXRjaGVzKGVsLCBzZWxlY3RvcikgewogICAgcmV0dXJuIGVsTWF0Y2hlcy5jYWxsKGVsLCBzZWxlY3Rvcik7CiAgfQoKICBmdW5jdGlvbiBjb250YWlucyhhLCBiKSB7CiAgICBpZiAoYS5jb250YWlucyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBhLmNvbnRhaW5zKGIpOwogICAgfQoKICAgIHdoaWxlIChiID0gYi5wYXJlbnROb2RlKSB7CiAgICAgIGlmIChiID09PSBhKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gZmFsc2U7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvdmlld3MvY29yZV92aWV3IiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9ydW50aW1lLCBfc3RhdGVzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgIGBFbWJlci5Db3JlVmlld2AgaXMgYW4gYWJzdHJhY3QgY2xhc3MgdGhhdCBleGlzdHMgdG8gZ2l2ZSB2aWV3LWxpa2UgYmVoYXZpb3IKICAgIHRvIGJvdGggRW1iZXIncyBtYWluIHZpZXcgY2xhc3MgYENvbXBvbmVudGAgYW5kIG90aGVyIGNsYXNzZXMgdGhhdCBkb24ndCBuZWVkCiAgICB0aGUgZnVsbCBmdW5jdGlvbmFsaXR5IG9mIGBDb21wb25lbnRgLgogIAogICAgVW5sZXNzIHlvdSBoYXZlIHNwZWNpZmljIG5lZWRzIGZvciBgQ29yZVZpZXdgLCB5b3Ugd2lsbCB1c2UgYENvbXBvbmVudGAKICAgIGluIHlvdXIgYXBwbGljYXRpb25zLgogIAogICAgQGNsYXNzIENvcmVWaWV3CiAgICBAbmFtZXNwYWNlIEVtYmVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQGRlcHJlY2F0ZWQgVXNlIGBDb21wb25lbnRgIGluc3RlYWQuCiAgICBAdXNlcyBFdmVudGVkCiAgICBAdXNlcyBFbWJlci5BY3Rpb25IYW5kbGVyCiAgICBAcHJpdmF0ZQogICovCiAgdmFyIENvcmVWaWV3ID0gX3J1bnRpbWUuRnJhbWV3b3JrT2JqZWN0LmV4dGVuZChfcnVudGltZS5FdmVudGVkLCBfcnVudGltZS5BY3Rpb25IYW5kbGVyLCB7CiAgICBpc1ZpZXc6IHRydWUsCiAgICBfc3RhdGVzOiBfc3RhdGVzLmRlZmF1bHQsCiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgdGhpcy5fc3RhdGUgPSAncHJlUmVuZGVyJzsKICAgICAgdGhpcy5fY3VycmVudFN0YXRlID0gdGhpcy5fc3RhdGVzLnByZVJlbmRlcjsKCiAgICAgIGlmICghdGhpcy5yZW5kZXJlcikgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiQ2Fubm90IGluc3RhbnRpYXRlIGEgY29tcG9uZW50IHdpdGhvdXQgYSByZW5kZXJlci4gUGxlYXNlIGVuc3VyZSB0aGF0IHlvdSBhcmUgY3JlYXRpbmcgIiArIHRoaXMgKyAiIHdpdGggYSBwcm9wZXIgY29udGFpbmVyL3JlZ2lzdHJ5LiIpOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBJZiB0aGUgdmlldyBpcyBjdXJyZW50bHkgaW5zZXJ0ZWQgaW50byB0aGUgRE9NIG9mIGEgcGFyZW50IHZpZXcsIHRoaXMKICAgICAgcHJvcGVydHkgd2lsbCBwb2ludCB0byB0aGUgcGFyZW50IG9mIHRoZSB2aWV3LgogICAgICAgQHByb3BlcnR5IHBhcmVudFZpZXcKICAgICAgQHR5cGUgRW1iZXIuVmlldwogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgcGFyZW50VmlldzogbnVsbCwKICAgIGluc3RydW1lbnREZXRhaWxzOiBmdW5jdGlvbiBpbnN0cnVtZW50RGV0YWlscyhoYXNoKSB7CiAgICAgIGhhc2gub2JqZWN0ID0gdGhpcy50b1N0cmluZygpOwogICAgICBoYXNoLmNvbnRhaW5lcktleSA9IHRoaXMuX2RlYnVnQ29udGFpbmVyS2V5OwogICAgICBoYXNoLnZpZXcgPSB0aGlzOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0sCgogICAgLyoqCiAgICAgIE92ZXJyaWRlIHRoZSBkZWZhdWx0IGV2ZW50IGZpcmluZyBmcm9tIGBFdmVudGVkYCB0bwogICAgICBhbHNvIGNhbGwgbWV0aG9kcyB3aXRoIHRoZSBnaXZlbiBuYW1lLgogICAgICAgQG1ldGhvZCB0cmlnZ2VyCiAgICAgIEBwYXJhbSBuYW1lIHtTdHJpbmd9CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgdHJpZ2dlcjogZnVuY3Rpb24gdHJpZ2dlcihuYW1lKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4gPiAxID8gX2xlbiAtIDEgOiAwKSwgX2tleSA9IDE7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgICBhcmdzW19rZXkgLSAxXSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgICAgfQoKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIHZhciBtZXRob2QgPSB0aGlzW25hbWVdOwoKICAgICAgaWYgKHR5cGVvZiBtZXRob2QgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICByZXR1cm4gbWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3MpOwogICAgICB9CiAgICB9LAogICAgaGFzOiBmdW5jdGlvbiBoYXMobmFtZSkgewogICAgICByZXR1cm4gdHlwZW9mIHRoaXNbbmFtZV0gPT09ICdmdW5jdGlvbicgfHwgdGhpcy5fc3VwZXIobmFtZSk7CiAgICB9CiAgfSk7CgogIENvcmVWaWV3LnJlb3BlbkNsYXNzKHsKICAgIGlzVmlld0ZhY3Rvcnk6IHRydWUKICB9KTsKICB2YXIgX2RlZmF1bHQgPSBDb3JlVmlldzsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9wcmVfcmVuZGVyIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvaGFzX2VsZW1lbnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9pbl9kb20iLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9kZXN0cm95aW5nIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3ByZV9yZW5kZXIsIF9oYXNfZWxlbWVudCwgX2luX2RvbSwgX2Rlc3Ryb3lpbmcpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qCiAgICBEZXNjcmliZSBob3cgdGhlIHNwZWNpZmllZCBhY3Rpb25zIHNob3VsZCBiZWhhdmUgaW4gdGhlIHZhcmlvdXMKICAgIHN0YXRlcyB0aGF0IGEgdmlldyBjYW4gZXhpc3QgaW4uIFBvc3NpYmxlIHN0YXRlczoKICAKICAgICogcHJlUmVuZGVyOiB3aGVuIGEgdmlldyBpcyBmaXJzdCBpbnN0YW50aWF0ZWQsIGFuZCBhZnRlciBpdHMKICAgICAgZWxlbWVudCB3YXMgZGVzdHJveWVkLCBpdCBpcyBpbiB0aGUgcHJlUmVuZGVyIHN0YXRlCiAgICAqIGhhc0VsZW1lbnQ6IHRoZSBET00gcmVwcmVzZW50YXRpb24gb2YgdGhlIHZpZXcgaXMgY3JlYXRlZCwKICAgICAgYW5kIGlzIHJlYWR5IHRvIGJlIGluc2VydGVkCiAgICAqIGluRE9NOiBvbmNlIGEgdmlldyBoYXMgYmVlbiBpbnNlcnRlZCBpbnRvIHRoZSBET00gaXQgaXMgaW4KICAgICAgdGhlIGluRE9NIHN0YXRlLiBBIHZpZXcgc3BlbmRzIHRoZSB2YXN0IG1ham9yaXR5IG9mIGl0cwogICAgICBleGlzdGVuY2UgaW4gdGhpcyBzdGF0ZS4KICAgICogZGVzdHJveWVkOiBvbmNlIGEgdmlldyBoYXMgYmVlbiBkZXN0cm95ZWQgKHVzaW5nIHRoZSBkZXN0cm95CiAgICAgIG1ldGhvZCksIGl0IGlzIGluIHRoaXMgc3RhdGUuIE5vIGZ1cnRoZXIgYWN0aW9ucyBjYW4gYmUgaW52b2tlZAogICAgICBvbiBhIGRlc3Ryb3llZCB2aWV3LgogICovCiAgdmFyIHN0YXRlcyA9IE9iamVjdC5mcmVlemUoewogICAgcHJlUmVuZGVyOiBfcHJlX3JlbmRlci5kZWZhdWx0LAogICAgaW5ET006IF9pbl9kb20uZGVmYXVsdCwKICAgIGhhc0VsZW1lbnQ6IF9oYXNfZWxlbWVudC5kZWZhdWx0LAogICAgZGVzdHJveWluZzogX2Rlc3Ryb3lpbmcuZGVmYXVsdAogIH0pOwogIHZhciBfZGVmYXVsdCA9IHN0YXRlczsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvZGVmYXVsdCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZXJyb3IiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZXJyb3IpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CiAgdmFyIF9kZWZhdWx0ID0gewogICAgLy8gYXBwZW5kQ2hpbGQgaXMgb25seSBsZWdhbCB3aGlsZSByZW5kZXJpbmcgdGhlIGJ1ZmZlci4KICAgIGFwcGVuZENoaWxkOiBmdW5jdGlvbiBhcHBlbmRDaGlsZCgpIHsKICAgICAgdGhyb3cgbmV3IF9lcnJvci5kZWZhdWx0KCJZb3UgY2FuJ3QgdXNlIGFwcGVuZENoaWxkIG91dHNpZGUgb2YgdGhlIHJlbmRlcmluZyBwcm9jZXNzIik7CiAgICB9LAogICAgLy8gSGFuZGxlIGV2ZW50cyBmcm9tIGBFbWJlci5FdmVudERpc3BhdGNoZXJgCiAgICBoYW5kbGVFdmVudDogZnVuY3Rpb24gaGFuZGxlRXZlbnQoKSB7CiAgICAgIHJldHVybiB0cnVlOyAvLyBjb250aW51ZSBldmVudCBwcm9wYWdhdGlvbgogICAgfSwKICAgIHJlcmVuZGVyOiBmdW5jdGlvbiByZXJlbmRlcigpIHt9LAogICAgZGVzdHJveTogZnVuY3Rpb24gZGVzdHJveSgpIHt9CiAgfTsKCiAgdmFyIF9kZWZhdWx0MiA9IE9iamVjdC5mcmVlemUoX2RlZmF1bHQpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQyOwp9KTsKZGVmaW5lKCJAZW1iZXIvLWludGVybmFscy92aWV3cy9saWIvdmlld3Mvc3RhdGVzL2Rlc3Ryb3lpbmciLCBbImV4cG9ydHMiLCAiQGVtYmVyL3BvbHlmaWxscyIsICJAZW1iZXIvZXJyb3IiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9kZWZhdWx0Il0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3BvbHlmaWxscywgX2Vycm9yLCBfZGVmYXVsdDMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CiAgdmFyIGRlc3Ryb3lpbmcgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBfZGVmYXVsdDMuZGVmYXVsdCwgewogICAgYXBwZW5kQ2hpbGQ6IGZ1bmN0aW9uIGFwcGVuZENoaWxkKCkgewogICAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIllvdSBjYW4ndCBjYWxsIGFwcGVuZENoaWxkIG9uIGEgdmlldyBiZWluZyBkZXN0cm95ZWQiKTsKICAgIH0sCiAgICByZXJlbmRlcjogZnVuY3Rpb24gcmVyZW5kZXIoKSB7CiAgICAgIHRocm93IG5ldyBfZXJyb3IuZGVmYXVsdCgiWW91IGNhbid0IGNhbGwgcmVyZW5kZXIgb24gYSB2aWV3IGJlaW5nIGRlc3Ryb3llZCIpOwogICAgfQogIH0pOwoKICB2YXIgX2RlZmF1bHQyID0gT2JqZWN0LmZyZWV6ZShkZXN0cm95aW5nKTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0MjsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9oYXNfZWxlbWVudCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvcG9seWZpbGxzIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvZGVmYXVsdCIsICJAZW1iZXIvcnVubG9vcCIsICJAZW1iZXIvaW5zdHJ1bWVudGF0aW9uIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3BvbHlmaWxscywgX2RlZmF1bHQzLCBfcnVubG9vcCwgX2luc3RydW1lbnRhdGlvbikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKICB2YXIgaGFzRWxlbWVudCA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIF9kZWZhdWx0My5kZWZhdWx0LCB7CiAgICByZXJlbmRlcjogZnVuY3Rpb24gcmVyZW5kZXIodmlldykgewogICAgICB2aWV3LnJlbmRlcmVyLnJlcmVuZGVyKHZpZXcpOwogICAgfSwKICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3kodmlldykgewogICAgICB2aWV3LnJlbmRlcmVyLnJlbW92ZSh2aWV3KTsKICAgIH0sCiAgICAvLyBIYW5kbGUgZXZlbnRzIGZyb20gYEVtYmVyLkV2ZW50RGlzcGF0Y2hlcmAKICAgIGhhbmRsZUV2ZW50OiBmdW5jdGlvbiBoYW5kbGVFdmVudCh2aWV3LCBldmVudE5hbWUsIGV2ZW50KSB7CiAgICAgIGlmICh2aWV3LmhhcyhldmVudE5hbWUpKSB7CiAgICAgICAgLy8gSGFuZGxlciBzaG91bGQgYmUgYWJsZSB0byByZS1kaXNwYXRjaCBldmVudHMsIHNvIHdlIGRvbid0CiAgICAgICAgLy8gcHJldmVudERlZmF1bHQgb3Igc3RvcFByb3BhZ2F0aW9uLgogICAgICAgIHJldHVybiAoMCwgX2luc3RydW1lbnRhdGlvbi5mbGFnZ2VkSW5zdHJ1bWVudCkoImludGVyYWN0aW9uLiIgKyBldmVudE5hbWUsIHsKICAgICAgICAgIGV2ZW50OiBldmVudCwKICAgICAgICAgIHZpZXc6IHZpZXcKICAgICAgICB9LCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gKDAsIF9ydW5sb29wLmpvaW4pKHZpZXcsIHZpZXcudHJpZ2dlciwgZXZlbnROYW1lLCBldmVudCk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHRydWU7IC8vIGNvbnRpbnVlIGV2ZW50IHByb3BhZ2F0aW9uCiAgICAgIH0KICAgIH0KICB9KTsKCiAgdmFyIF9kZWZhdWx0MiA9IE9iamVjdC5mcmVlemUoaGFzRWxlbWVudCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDI7Cn0pOwpkZWZpbmUoIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvaW5fZG9tIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiQGVtYmVyL2Vycm9yIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvaGFzX2VsZW1lbnQiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdXRpbHMsIF9wb2x5ZmlsbHMsIF9lcnJvciwgX2hhc19lbGVtZW50KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwogIHZhciBpbkRPTSA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIF9oYXNfZWxlbWVudC5kZWZhdWx0LCB7CiAgICBlbnRlcjogZnVuY3Rpb24gZW50ZXIodmlldykgewogICAgICAvLyBSZWdpc3RlciB0aGUgdmlldyBmb3IgZXZlbnQgaGFuZGxpbmcuIFRoaXMgaGFzaCBpcyB1c2VkIGJ5CiAgICAgIC8vIEVtYmVyLkV2ZW50RGlzcGF0Y2hlciB0byBkaXNwYXRjaCBpbmNvbWluZyBldmVudHMuCiAgICAgIHZpZXcucmVuZGVyZXIucmVnaXN0ZXIodmlldyk7CgogICAgICBpZiAoZmFsc2UKICAgICAgLyogREVCVUcgKi8KICAgICAgKSB7CiAgICAgICAgdmFyIGVsZW1lbnRJZCA9IHZpZXcuZWxlbWVudElkOwoKICAgICAgICBpZiAodHJ1ZQogICAgICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgICAgICkgewogICAgICAgICAgICAoMCwgX3V0aWxzLnRlYXJkb3duTWFuZGF0b3J5U2V0dGVyKSh2aWV3LCAnZWxlbWVudElkJyk7CiAgICAgICAgICB9CgogICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh2aWV3LCAnZWxlbWVudElkJywgewogICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgICAgICByZXR1cm4gZWxlbWVudElkOwogICAgICAgICAgfSwKICAgICAgICAgIHNldDogZnVuY3Rpb24gc2V0KCkgewogICAgICAgICAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIkNoYW5naW5nIGEgdmlldydzIGVsZW1lbnRJZCBhZnRlciBjcmVhdGlvbiBpcyBub3QgYWxsb3dlZCIpOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CiAgICB9LAogICAgZXhpdDogZnVuY3Rpb24gZXhpdCh2aWV3KSB7CiAgICAgIHZpZXcucmVuZGVyZXIudW5yZWdpc3Rlcih2aWV3KTsKICAgIH0KICB9KTsKCiAgdmFyIF9kZWZhdWx0ID0gT2JqZWN0LmZyZWV6ZShpbkRPTSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MvbGliL3ZpZXdzL3N0YXRlcy9wcmVfcmVuZGVyIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzL2xpYi92aWV3cy9zdGF0ZXMvZGVmYXVsdCIsICJAZW1iZXIvcG9seWZpbGxzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlZmF1bHQzLCBfcG9seWZpbGxzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwogIHZhciBwcmVSZW5kZXIgPSAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBfZGVmYXVsdDMuZGVmYXVsdCk7CgogIHZhciBfZGVmYXVsdDIgPSBPYmplY3QuZnJlZXplKHByZVJlbmRlcik7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDI7Cn0pOwpkZWZpbmUoIkBlbWJlci9hcHBsaWNhdGlvbi9nbG9iYWxzLXJlc29sdmVyIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvc3RyaW5nIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyL2FwcGxpY2F0aW9uL2xpYi92YWxpZGF0ZS10eXBlIiwgIkBlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX3V0aWxzLCBfbWV0YWwsIF9kZWJ1ZywgX3N0cmluZywgX3J1bnRpbWUsIF92YWxpZGF0ZVR5cGUsIF9nbGltbWVyKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICBAbW9kdWxlIEBlbWJlci9hcHBsaWNhdGlvbgogICovCgogIC8qKgogICAgVGhlIERlZmF1bHRSZXNvbHZlciBkZWZpbmVzIHRoZSBkZWZhdWx0IGxvb2t1cCBydWxlcyB0byByZXNvbHZlCiAgICBjb250YWluZXIgbG9va3VwcyBiZWZvcmUgY29uc3VsdGluZyB0aGUgY29udGFpbmVyIGZvciByZWdpc3RlcmVkCiAgICBpdGVtczoKICAKICAgICogdGVtcGxhdGVzIGFyZSBsb29rZWQgdXAgb24gYEVtYmVyLlRFTVBMQVRFU2AKICAgICogb3RoZXIgbmFtZXMgYXJlIGxvb2tlZCB1cCBvbiB0aGUgYXBwbGljYXRpb24gYWZ0ZXIgY29udmVydGluZwogICAgICB0aGUgbmFtZS4gRm9yIGV4YW1wbGUsIGBjb250cm9sbGVyOnBvc3RgIGxvb2tzIHVwCiAgICAgIGBBcHAuUG9zdENvbnRyb2xsZXJgIGJ5IGRlZmF1bHQuCiAgICAqIHRoZXJlIGFyZSBzb21lIG51YW5jZXMgKHNlZSBleGFtcGxlcyBiZWxvdykKICAKICAgICMjIyBIb3cgUmVzb2x2aW5nIFdvcmtzCiAgCiAgICBUaGUgY29udGFpbmVyIGNhbGxzIHRoaXMgb2JqZWN0J3MgYHJlc29sdmVgIG1ldGhvZCB3aXRoIHRoZQogICAgYGZ1bGxOYW1lYCBhcmd1bWVudC4KICAKICAgIEl0IGZpcnN0IHBhcnNlcyB0aGUgZnVsbE5hbWUgaW50byBhbiBvYmplY3QgdXNpbmcgYHBhcnNlTmFtZWAuCiAgCiAgICBUaGVuIGl0IGNoZWNrcyBmb3IgdGhlIHByZXNlbmNlIG9mIGEgdHlwZS1zcGVjaWZpYyBpbnN0YW5jZQogICAgbWV0aG9kIG9mIHRoZSBmb3JtIGByZXNvbHZlW1R5cGVdYCBhbmQgY2FsbHMgaXQgaWYgaXQgZXhpc3RzLgogICAgRm9yIGV4YW1wbGUgaWYgaXQgd2FzIHJlc29sdmluZyAndGVtcGxhdGU6cG9zdCcsIGl0IHdvdWxkIGNhbGwKICAgIHRoZSBgcmVzb2x2ZVRlbXBsYXRlYCBtZXRob2QuCiAgCiAgICBJdHMgbGFzdCByZXNvcnQgaXMgdG8gY2FsbCB0aGUgYHJlc29sdmVPdGhlcmAgbWV0aG9kLgogIAogICAgVGhlIG1ldGhvZHMgb2YgdGhpcyBvYmplY3QgYXJlIGRlc2lnbmVkIHRvIGJlIGVhc3kgdG8gb3ZlcnJpZGUKICAgIGluIGEgc3ViY2xhc3MuIEZvciBleGFtcGxlLCB5b3UgY291bGQgZW5oYW5jZSBob3cgYSB0ZW1wbGF0ZQogICAgaXMgcmVzb2x2ZWQgbGlrZSBzbzoKICAKICAgIGBgYGFwcC9hcHAuanMKICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgaW1wb3J0IEdsb2JhbHNSZXNvbHZlciBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24vZ2xvYmFscy1yZXNvbHZlcic7CiAgCiAgICBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoewogICAgICBSZXNvbHZlcjogR2xvYmFsc1Jlc29sdmVyLmV4dGVuZCh7CiAgICAgICAgcmVzb2x2ZVRlbXBsYXRlKHBhcnNlZE5hbWUpIHsKICAgICAgICAgIGxldCByZXNvbHZlZFRlbXBsYXRlID0gdGhpcy5fc3VwZXIocGFyc2VkTmFtZSk7CiAgICAgICAgICBpZiAocmVzb2x2ZWRUZW1wbGF0ZSkgeyByZXR1cm4gcmVzb2x2ZWRUZW1wbGF0ZTsgfQogIAogICAgICAgICAgcmV0dXJuIEVtYmVyLlRFTVBMQVRFU1snbm90X2ZvdW5kJ107CiAgICAgICAgfQogICAgICB9KQogICAgfSk7CiAgICBgYGAKICAKICAgIFNvbWUgZXhhbXBsZXMgb2YgaG93IG5hbWVzIGFyZSByZXNvbHZlZDoKICAKICAgIGBgYHRleHQKICAgICd0ZW1wbGF0ZTpwb3N0JyAgICAgICAgICAgLy89PiBFbWJlci5URU1QTEFURVNbJ3Bvc3QnXQogICAgJ3RlbXBsYXRlOnBvc3RzL2J5bGluZScgICAvLz0+IEVtYmVyLlRFTVBMQVRFU1sncG9zdHMvYnlsaW5lJ10KICAgICd0ZW1wbGF0ZTpwb3N0cy5ieWxpbmUnICAgLy89PiBFbWJlci5URU1QTEFURVNbJ3Bvc3RzL2J5bGluZSddCiAgICAndGVtcGxhdGU6YmxvZ1Bvc3QnICAgICAgIC8vPT4gRW1iZXIuVEVNUExBVEVTWydibG9nLXBvc3QnXQogICAgJ2NvbnRyb2xsZXI6cG9zdCcgICAgICAgICAvLz0+IEFwcC5Qb3N0Q29udHJvbGxlcgogICAgJ2NvbnRyb2xsZXI6cG9zdHMuaW5kZXgnICAvLz0+IEFwcC5Qb3N0c0luZGV4Q29udHJvbGxlcgogICAgJ2NvbnRyb2xsZXI6YmxvZy9wb3N0JyAgICAvLz0+IEJsb2cuUG9zdENvbnRyb2xsZXIKICAgICdjb250cm9sbGVyOmJhc2ljJyAgICAgICAgLy89PiBDb250cm9sbGVyCiAgICAncm91dGU6cG9zdCcgICAgICAgICAgICAgIC8vPT4gQXBwLlBvc3RSb3V0ZQogICAgJ3JvdXRlOnBvc3RzLmluZGV4JyAgICAgICAvLz0+IEFwcC5Qb3N0c0luZGV4Um91dGUKICAgICdyb3V0ZTpibG9nL3Bvc3QnICAgICAgICAgLy89PiBCbG9nLlBvc3RSb3V0ZQogICAgJ3JvdXRlOmJhc2ljJyAgICAgICAgICAgICAvLz0+IFJvdXRlCiAgICAnZm9vOnBvc3QnICAgICAgICAgICAgICAgIC8vPT4gQXBwLlBvc3RGb28KICAgICdtb2RlbDpwb3N0JyAgICAgICAgICAgICAgLy89PiBBcHAuUG9zdAogICAgYGBgCiAgCiAgICBAY2xhc3MgR2xvYmFsc1Jlc29sdmVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHB1YmxpYwogICovCiAgdmFyIERlZmF1bHRSZXNvbHZlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW1iZXJPYmplY3QpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShEZWZhdWx0UmVzb2x2ZXIsIF9FbWJlck9iamVjdCk7CgogICAgZnVuY3Rpb24gRGVmYXVsdFJlc29sdmVyKCkgewogICAgICByZXR1cm4gX0VtYmVyT2JqZWN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICBEZWZhdWx0UmVzb2x2ZXIuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BzKSB7CiAgICAgIC8vIERPIE5PVCBSRU1PVkUgZXZlbiB0aG91Z2ggdGhpcyBkb2Vzbid0IGRvIGFueXRoaW5nCiAgICAgIC8vIFRoaXMgaXMgcmVxdWlyZWQgZm9yIGEgRmlyZUZveCA2MCsgSklUIGJ1ZyB3aXRoIG91ciB0ZXN0cy4KICAgICAgLy8gd2l0aG91dCBpdCwgY3JlYXRlKHByb3BzKSBpbiBvdXIgdGVzdHMgd291bGQgbG9zZSBwcm9wcyBvbiBhIGRlb3B0LgogICAgICByZXR1cm4gX0VtYmVyT2JqZWN0LmNyZWF0ZS5jYWxsKHRoaXMsIHByb3BzKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIHdpbGwgYmUgc2V0IHRvIHRoZSBBcHBsaWNhdGlvbiBpbnN0YW5jZSB3aGVuIGl0IGlzCiAgICAgIGNyZWF0ZWQuCiAgICAgICBAcHJvcGVydHkgbmFtZXNwYWNlCiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgdmFyIF9wcm90byA9IERlZmF1bHRSZXNvbHZlci5wcm90b3R5cGU7CgogICAgX3Byb3RvLmluaXQgPSBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9wYXJzZU5hbWVDYWNoZSA9ICgwLCBfdXRpbHMuZGljdGlvbmFyeSkobnVsbCk7CiAgICB9OwoKICAgIF9wcm90by5ub3JtYWxpemUgPSBmdW5jdGlvbiBub3JtYWxpemUoZnVsbE5hbWUpIHsKICAgICAgdmFyIF9mdWxsTmFtZSRzcGxpdCA9IGZ1bGxOYW1lLnNwbGl0KCc6JyksCiAgICAgICAgICB0eXBlID0gX2Z1bGxOYW1lJHNwbGl0WzBdLAogICAgICAgICAgbmFtZSA9IF9mdWxsTmFtZSRzcGxpdFsxXTsKCiAgICAgIChmYWxzZSAmJiAhKGZ1bGxOYW1lLnNwbGl0KCc6JykubGVuZ3RoID09PSAyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RyaWVkIHRvIG5vcm1hbGl6ZSBhIGNvbnRhaW5lciBuYW1lIHdpdGhvdXQgYSBjb2xvbiAoOikgaW4gaXQuICcgKyAnWW91IHByb2JhYmx5IHRyaWVkIHRvIGxvb2t1cCBhIG5hbWUgdGhhdCBkaWQgbm90IGNvbnRhaW4gYSB0eXBlLCAnICsgJ2EgY29sb24sIGFuZCBhIG5hbWUuIEEgcHJvcGVyIGxvb2t1cCBuYW1lIHdvdWxkIGJlIGB2aWV3OnBvc3RgLicsIGZ1bGxOYW1lLnNwbGl0KCc6JykubGVuZ3RoID09PSAyKSk7CgogICAgICBpZiAodHlwZSAhPT0gJ3RlbXBsYXRlJykgewogICAgICAgIHZhciByZXN1bHQgPSBuYW1lLnJlcGxhY2UoLyhcLnxffC0pLi9nLCBmdW5jdGlvbiAobSkgewogICAgICAgICAgcmV0dXJuIG0uY2hhckF0KDEpLnRvVXBwZXJDYXNlKCk7CiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIHR5cGUgKyAiOiIgKyByZXN1bHQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGZ1bGxOYW1lOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIHZpYSB0aGUgY29udGFpbmVyJ3MgcmVzb2x2ZXIgbWV0aG9kLgogICAgICBJdCBwYXJzZXMgdGhlIHByb3ZpZGVkIGBmdWxsTmFtZWAgYW5kIHRoZW4gbG9va3MgdXAgYW5kCiAgICAgIHJldHVybnMgdGhlIGFwcHJvcHJpYXRlIHRlbXBsYXRlIG9yIGNsYXNzLgogICAgICAgQG1ldGhvZCByZXNvbHZlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZSB0aGUgbG9va3VwIHN0cmluZwogICAgICBAcmV0dXJuIHtPYmplY3R9IHRoZSByZXNvbHZlZCBmYWN0b3J5CiAgICAgIEBwdWJsaWMKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc29sdmUgPSBmdW5jdGlvbiByZXNvbHZlKGZ1bGxOYW1lKSB7CiAgICAgIHZhciBwYXJzZWROYW1lID0gdGhpcy5wYXJzZU5hbWUoZnVsbE5hbWUpOwogICAgICB2YXIgcmVzb2x2ZU1ldGhvZE5hbWUgPSBwYXJzZWROYW1lLnJlc29sdmVNZXRob2ROYW1lOwogICAgICB2YXIgcmVzb2x2ZWQ7CgogICAgICBpZiAodGhpc1tyZXNvbHZlTWV0aG9kTmFtZV0pIHsKICAgICAgICByZXNvbHZlZCA9IHRoaXNbcmVzb2x2ZU1ldGhvZE5hbWVdKHBhcnNlZE5hbWUpOwogICAgICB9CgogICAgICByZXNvbHZlZCA9IHJlc29sdmVkIHx8IHRoaXMucmVzb2x2ZU90aGVyKHBhcnNlZE5hbWUpOwoKICAgICAgaWYgKGZhbHNlCiAgICAgIC8qIERFQlVHICovCiAgICAgICkgewogICAgICAgIGlmIChwYXJzZWROYW1lLnJvb3QgJiYgcGFyc2VkTmFtZS5yb290LkxPR19SRVNPTFZFUikgewogICAgICAgICAgdGhpcy5fbG9nTG9va3VwKHJlc29sdmVkLCBwYXJzZWROYW1lKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChyZXNvbHZlZCkgewogICAgICAgICgwLCBfdmFsaWRhdGVUeXBlLmRlZmF1bHQpKHJlc29sdmVkLCBwYXJzZWROYW1lKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlc29sdmVkOwogICAgfQogICAgLyoqCiAgICAgIENvbnZlcnQgdGhlIHN0cmluZyBuYW1lIG9mIHRoZSBmb3JtICd0eXBlOm5hbWUnIHRvCiAgICAgIGEgSmF2YXNjcmlwdCBvYmplY3Qgd2l0aCB0aGUgcGFyc2VkIGFzcGVjdHMgb2YgdGhlIG5hbWUKICAgICAgYnJva2VuIG91dC4KICAgICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZSB0aGUgbG9va3VwIHN0cmluZwogICAgICBAbWV0aG9kIHBhcnNlTmFtZQogICAgICBAcHJvdGVjdGVkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5wYXJzZU5hbWUgPSBmdW5jdGlvbiBwYXJzZU5hbWUoZnVsbE5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXMuX3BhcnNlTmFtZUNhY2hlW2Z1bGxOYW1lXSB8fCAodGhpcy5fcGFyc2VOYW1lQ2FjaGVbZnVsbE5hbWVdID0gdGhpcy5fcGFyc2VOYW1lKGZ1bGxOYW1lKSk7CiAgICB9OwoKICAgIF9wcm90by5fcGFyc2VOYW1lID0gZnVuY3Rpb24gX3BhcnNlTmFtZShmdWxsTmFtZSkgewogICAgICB2YXIgX2Z1bGxOYW1lJHNwbGl0MiA9IGZ1bGxOYW1lLnNwbGl0KCc6JyksCiAgICAgICAgICB0eXBlID0gX2Z1bGxOYW1lJHNwbGl0MlswXSwKICAgICAgICAgIGZ1bGxOYW1lV2l0aG91dFR5cGUgPSBfZnVsbE5hbWUkc3BsaXQyWzFdOwoKICAgICAgdmFyIG5hbWUgPSBmdWxsTmFtZVdpdGhvdXRUeXBlOwogICAgICB2YXIgbmFtZXNwYWNlID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICduYW1lc3BhY2UnKTsKICAgICAgdmFyIHJvb3QgPSBuYW1lc3BhY2U7CiAgICAgIHZhciBsYXN0U2xhc2hJbmRleCA9IG5hbWUubGFzdEluZGV4T2YoJy8nKTsKICAgICAgdmFyIGRpcm5hbWUgPSBsYXN0U2xhc2hJbmRleCAhPT0gLTEgPyBuYW1lLnNsaWNlKDAsIGxhc3RTbGFzaEluZGV4KSA6IG51bGw7CgogICAgICBpZiAodHlwZSAhPT0gJ3RlbXBsYXRlJyAmJiBsYXN0U2xhc2hJbmRleCAhPT0gLTEpIHsKICAgICAgICB2YXIgcGFydHMgPSBuYW1lLnNwbGl0KCcvJyk7CiAgICAgICAgbmFtZSA9IHBhcnRzW3BhcnRzLmxlbmd0aCAtIDFdOwogICAgICAgIHZhciBuYW1lc3BhY2VOYW1lID0gKDAsIF9zdHJpbmcuY2FwaXRhbGl6ZSkocGFydHMuc2xpY2UoMCwgLTEpLmpvaW4oJy4nKSk7CiAgICAgICAgcm9vdCA9ICgwLCBfbWV0YWwuZmluZE5hbWVzcGFjZSkobmFtZXNwYWNlTmFtZSk7CiAgICAgICAgKGZhbHNlICYmICEocm9vdCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJZb3UgYXJlIGxvb2tpbmcgZm9yIGEgIiArIG5hbWUgKyAiICIgKyB0eXBlICsgIiBpbiB0aGUgIiArIG5hbWVzcGFjZU5hbWUgKyAiIG5hbWVzcGFjZSwgYnV0IHRoZSBuYW1lc3BhY2UgY291bGQgbm90IGJlIGZvdW5kIiwgcm9vdCkpOwogICAgICB9CgogICAgICB2YXIgcmVzb2x2ZU1ldGhvZE5hbWUgPSBmdWxsTmFtZVdpdGhvdXRUeXBlID09PSAnbWFpbicgPyAnTWFpbicgOiAoMCwgX3N0cmluZy5jbGFzc2lmeSkodHlwZSk7CgogICAgICBpZiAoIShuYW1lICYmIHR5cGUpKSB7CiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiSW52YWxpZCBmdWxsTmFtZTogYCIgKyBmdWxsTmFtZSArICJgLCBtdXN0IGJlIG9mIHRoZSBmb3JtIGB0eXBlOm5hbWVgICIpOwogICAgICB9CgogICAgICByZXR1cm4gewogICAgICAgIGZ1bGxOYW1lOiBmdWxsTmFtZSwKICAgICAgICB0eXBlOiB0eXBlLAogICAgICAgIGZ1bGxOYW1lV2l0aG91dFR5cGU6IGZ1bGxOYW1lV2l0aG91dFR5cGUsCiAgICAgICAgZGlybmFtZTogZGlybmFtZSwKICAgICAgICBuYW1lOiBuYW1lLAogICAgICAgIHJvb3Q6IHJvb3QsCiAgICAgICAgcmVzb2x2ZU1ldGhvZE5hbWU6ICJyZXNvbHZlIiArIHJlc29sdmVNZXRob2ROYW1lCiAgICAgIH07CiAgICB9CiAgICAvKioKICAgICAgUmV0dXJucyBhIGh1bWFuLXJlYWRhYmxlIGRlc2NyaXB0aW9uIGZvciBhIGZ1bGxOYW1lLiBVc2VkIGJ5IHRoZQogICAgICBBcHBsaWNhdGlvbiBuYW1lc3BhY2UgaW4gYXNzZXJ0aW9ucyB0byBkZXNjcmliZSB0aGUKICAgICAgcHJlY2lzZSBuYW1lIG9mIHRoZSBjbGFzcyB0aGF0IEVtYmVyIGlzIGxvb2tpbmcgZm9yLCByYXRoZXIgdGhhbgogICAgICBjb250YWluZXIga2V5cy4KICAgICAgIEBwYXJhbSB7U3RyaW5nfSBmdWxsTmFtZSB0aGUgbG9va3VwIHN0cmluZwogICAgICBAbWV0aG9kIGxvb2t1cERlc2NyaXB0aW9uCiAgICAgIEBwcm90ZWN0ZWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLmxvb2t1cERlc2NyaXB0aW9uID0gZnVuY3Rpb24gbG9va3VwRGVzY3JpcHRpb24oZnVsbE5hbWUpIHsKICAgICAgdmFyIHBhcnNlZE5hbWUgPSB0aGlzLnBhcnNlTmFtZShmdWxsTmFtZSk7CiAgICAgIHZhciBkZXNjcmlwdGlvbjsKCiAgICAgIGlmIChwYXJzZWROYW1lLnR5cGUgPT09ICd0ZW1wbGF0ZScpIHsKICAgICAgICByZXR1cm4gInRlbXBsYXRlIGF0ICIgKyBwYXJzZWROYW1lLmZ1bGxOYW1lV2l0aG91dFR5cGUucmVwbGFjZSgvXC4vZywgJy8nKTsKICAgICAgfQoKICAgICAgZGVzY3JpcHRpb24gPSBwYXJzZWROYW1lLnJvb3QgKyAiLiIgKyAoMCwgX3N0cmluZy5jbGFzc2lmeSkocGFyc2VkTmFtZS5uYW1lKS5yZXBsYWNlKC9cLi9nLCAnJyk7CgogICAgICBpZiAocGFyc2VkTmFtZS50eXBlICE9PSAnbW9kZWwnKSB7CiAgICAgICAgZGVzY3JpcHRpb24gKz0gKDAsIF9zdHJpbmcuY2xhc3NpZnkpKHBhcnNlZE5hbWUudHlwZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBkZXNjcmlwdGlvbjsKICAgIH07CgogICAgX3Byb3RvLm1ha2VUb1N0cmluZyA9IGZ1bmN0aW9uIG1ha2VUb1N0cmluZyhmYWN0b3J5KSB7CiAgICAgIHJldHVybiBmYWN0b3J5LnRvU3RyaW5nKCk7CiAgICB9CiAgICAvKioKICAgICAgR2l2ZW4gYSBwYXJzZU5hbWUgb2JqZWN0IChvdXRwdXQgZnJvbSBgcGFyc2VOYW1lYCksIGFwcGx5CiAgICAgIHRoZSBjb252ZW50aW9ucyBleHBlY3RlZCBieSBgUm91dGVyYAogICAgICAgQHBhcmFtIHtPYmplY3R9IHBhcnNlZE5hbWUgYSBwYXJzZU5hbWUgb2JqZWN0IHdpdGggdGhlIHBhcnNlZAogICAgICAgIGZ1bGxOYW1lIGxvb2t1cCBzdHJpbmcKICAgICAgQG1ldGhvZCB1c2VSb3V0ZXJOYW1pbmcKICAgICAgQHByb3RlY3RlZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8udXNlUm91dGVyTmFtaW5nID0gZnVuY3Rpb24gdXNlUm91dGVyTmFtaW5nKHBhcnNlZE5hbWUpIHsKICAgICAgaWYgKHBhcnNlZE5hbWUubmFtZSA9PT0gJ2Jhc2ljJykgewogICAgICAgIHBhcnNlZE5hbWUubmFtZSA9ICcnOwogICAgICB9IGVsc2UgewogICAgICAgIHBhcnNlZE5hbWUubmFtZSA9IHBhcnNlZE5hbWUubmFtZS5yZXBsYWNlKC9cLi9nLCAnXycpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgTG9vayB1cCB0aGUgdGVtcGxhdGUgaW4gRW1iZXIuVEVNUExBVEVTCiAgICAgICBAcGFyYW0ge09iamVjdH0gcGFyc2VkTmFtZSBhIHBhcnNlTmFtZSBvYmplY3Qgd2l0aCB0aGUgcGFyc2VkCiAgICAgICAgZnVsbE5hbWUgbG9va3VwIHN0cmluZwogICAgICBAbWV0aG9kIHJlc29sdmVUZW1wbGF0ZQogICAgICBAcHJvdGVjdGVkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5yZXNvbHZlVGVtcGxhdGUgPSBmdW5jdGlvbiByZXNvbHZlVGVtcGxhdGUocGFyc2VkTmFtZSkgewogICAgICB2YXIgdGVtcGxhdGVOYW1lID0gcGFyc2VkTmFtZS5mdWxsTmFtZVdpdGhvdXRUeXBlLnJlcGxhY2UoL1wuL2csICcvJyk7CiAgICAgIHJldHVybiAoMCwgX2dsaW1tZXIuZ2V0VGVtcGxhdGUpKHRlbXBsYXRlTmFtZSkgfHwgKDAsIF9nbGltbWVyLmdldFRlbXBsYXRlKSgoMCwgX3N0cmluZy5kZWNhbWVsaXplKSh0ZW1wbGF0ZU5hbWUpKTsKICAgIH0KICAgIC8qKgogICAgICBMb29rdXAgdGhlIHZpZXcgdXNpbmcgYHJlc29sdmVPdGhlcmAKICAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXJzZWROYW1lIGEgcGFyc2VOYW1lIG9iamVjdCB3aXRoIHRoZSBwYXJzZWQKICAgICAgICBmdWxsTmFtZSBsb29rdXAgc3RyaW5nCiAgICAgIEBtZXRob2QgcmVzb2x2ZVZpZXcKICAgICAgQHByb3RlY3RlZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVzb2x2ZVZpZXcgPSBmdW5jdGlvbiByZXNvbHZlVmlldyhwYXJzZWROYW1lKSB7CiAgICAgIHRoaXMudXNlUm91dGVyTmFtaW5nKHBhcnNlZE5hbWUpOwogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlT3RoZXIocGFyc2VkTmFtZSk7CiAgICB9CiAgICAvKioKICAgICAgTG9va3VwIHRoZSBjb250cm9sbGVyIHVzaW5nIGByZXNvbHZlT3RoZXJgCiAgICAgICBAcGFyYW0ge09iamVjdH0gcGFyc2VkTmFtZSBhIHBhcnNlTmFtZSBvYmplY3Qgd2l0aCB0aGUgcGFyc2VkCiAgICAgICAgZnVsbE5hbWUgbG9va3VwIHN0cmluZwogICAgICBAbWV0aG9kIHJlc29sdmVDb250cm9sbGVyCiAgICAgIEBwcm90ZWN0ZWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc29sdmVDb250cm9sbGVyID0gZnVuY3Rpb24gcmVzb2x2ZUNvbnRyb2xsZXIocGFyc2VkTmFtZSkgewogICAgICB0aGlzLnVzZVJvdXRlck5hbWluZyhwYXJzZWROYW1lKTsKICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZU90aGVyKHBhcnNlZE5hbWUpOwogICAgfQogICAgLyoqCiAgICAgIExvb2t1cCB0aGUgcm91dGUgdXNpbmcgYHJlc29sdmVPdGhlcmAKICAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXJzZWROYW1lIGEgcGFyc2VOYW1lIG9iamVjdCB3aXRoIHRoZSBwYXJzZWQKICAgICAgICBmdWxsTmFtZSBsb29rdXAgc3RyaW5nCiAgICAgIEBtZXRob2QgcmVzb2x2ZVJvdXRlCiAgICAgIEBwcm90ZWN0ZWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlc29sdmVSb3V0ZSA9IGZ1bmN0aW9uIHJlc29sdmVSb3V0ZShwYXJzZWROYW1lKSB7CiAgICAgIHRoaXMudXNlUm91dGVyTmFtaW5nKHBhcnNlZE5hbWUpOwogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlT3RoZXIocGFyc2VkTmFtZSk7CiAgICB9CiAgICAvKioKICAgICAgTG9va3VwIHRoZSBtb2RlbCBvbiB0aGUgQXBwbGljYXRpb24gbmFtZXNwYWNlCiAgICAgICBAcGFyYW0ge09iamVjdH0gcGFyc2VkTmFtZSBhIHBhcnNlTmFtZSBvYmplY3Qgd2l0aCB0aGUgcGFyc2VkCiAgICAgICAgZnVsbE5hbWUgbG9va3VwIHN0cmluZwogICAgICBAbWV0aG9kIHJlc29sdmVNb2RlbAogICAgICBAcHJvdGVjdGVkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5yZXNvbHZlTW9kZWwgPSBmdW5jdGlvbiByZXNvbHZlTW9kZWwocGFyc2VkTmFtZSkgewogICAgICB2YXIgY2xhc3NOYW1lID0gKDAsIF9zdHJpbmcuY2xhc3NpZnkpKHBhcnNlZE5hbWUubmFtZSk7CiAgICAgIHZhciBmYWN0b3J5ID0gKDAsIF9tZXRhbC5nZXQpKHBhcnNlZE5hbWUucm9vdCwgY2xhc3NOYW1lKTsKICAgICAgcmV0dXJuIGZhY3Rvcnk7CiAgICB9CiAgICAvKioKICAgICAgTG9vayB1cCB0aGUgc3BlY2lmaWVkIG9iamVjdCAoZnJvbSBwYXJzZWROYW1lKSBvbiB0aGUgYXBwcm9wcmlhdGUKICAgICAgbmFtZXNwYWNlICh1c3VhbGx5IG9uIHRoZSBBcHBsaWNhdGlvbikKICAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXJzZWROYW1lIGEgcGFyc2VOYW1lIG9iamVjdCB3aXRoIHRoZSBwYXJzZWQKICAgICAgICBmdWxsTmFtZSBsb29rdXAgc3RyaW5nCiAgICAgIEBtZXRob2QgcmVzb2x2ZUhlbHBlcgogICAgICBAcHJvdGVjdGVkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5yZXNvbHZlSGVscGVyID0gZnVuY3Rpb24gcmVzb2x2ZUhlbHBlcihwYXJzZWROYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLnJlc29sdmVPdGhlcihwYXJzZWROYW1lKTsKICAgIH0KICAgIC8qKgogICAgICBMb29rIHVwIHRoZSBzcGVjaWZpZWQgb2JqZWN0IChmcm9tIHBhcnNlZE5hbWUpIG9uIHRoZSBhcHByb3ByaWF0ZQogICAgICBuYW1lc3BhY2UgKHVzdWFsbHkgb24gdGhlIEFwcGxpY2F0aW9uKQogICAgICAgQHBhcmFtIHtPYmplY3R9IHBhcnNlZE5hbWUgYSBwYXJzZU5hbWUgb2JqZWN0IHdpdGggdGhlIHBhcnNlZAogICAgICAgIGZ1bGxOYW1lIGxvb2t1cCBzdHJpbmcKICAgICAgQG1ldGhvZCByZXNvbHZlT3RoZXIKICAgICAgQHByb3RlY3RlZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVzb2x2ZU90aGVyID0gZnVuY3Rpb24gcmVzb2x2ZU90aGVyKHBhcnNlZE5hbWUpIHsKICAgICAgdmFyIGNsYXNzTmFtZSA9ICgwLCBfc3RyaW5nLmNsYXNzaWZ5KShwYXJzZWROYW1lLm5hbWUpICsgKDAsIF9zdHJpbmcuY2xhc3NpZnkpKHBhcnNlZE5hbWUudHlwZSk7CiAgICAgIHZhciBmYWN0b3J5ID0gKDAsIF9tZXRhbC5nZXQpKHBhcnNlZE5hbWUucm9vdCwgY2xhc3NOYW1lKTsKICAgICAgcmV0dXJuIGZhY3Rvcnk7CiAgICB9OwoKICAgIF9wcm90by5yZXNvbHZlTWFpbiA9IGZ1bmN0aW9uIHJlc29sdmVNYWluKHBhcnNlZE5hbWUpIHsKICAgICAgdmFyIGNsYXNzTmFtZSA9ICgwLCBfc3RyaW5nLmNsYXNzaWZ5KShwYXJzZWROYW1lLnR5cGUpOwogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHBhcnNlZE5hbWUucm9vdCwgY2xhc3NOYW1lKTsKICAgIH0KICAgIC8qKgogICAgICBVc2VkIHRvIGl0ZXJhdGUgYWxsIGl0ZW1zIG9mIGEgZ2l2ZW4gdHlwZS4KICAgICAgIEBtZXRob2Qga25vd25Gb3JUeXBlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlIHRoZSB0eXBlIHRvIHNlYXJjaCBmb3IKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmtub3duRm9yVHlwZSA9IGZ1bmN0aW9uIGtub3duRm9yVHlwZSh0eXBlKSB7CiAgICAgIHZhciBuYW1lc3BhY2UgPSAoMCwgX21ldGFsLmdldCkodGhpcywgJ25hbWVzcGFjZScpOwogICAgICB2YXIgc3VmZml4ID0gKDAsIF9zdHJpbmcuY2xhc3NpZnkpKHR5cGUpOwogICAgICB2YXIgdHlwZVJlZ2V4cCA9IG5ldyBSZWdFeHAoc3VmZml4ICsgIiQiKTsKICAgICAgdmFyIGtub3duID0gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgICAgdmFyIGtub3duS2V5cyA9IE9iamVjdC5rZXlzKG5hbWVzcGFjZSk7CgogICAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwga25vd25LZXlzLmxlbmd0aDsgaW5kZXgrKykgewogICAgICAgIHZhciBuYW1lID0ga25vd25LZXlzW2luZGV4XTsKCiAgICAgICAgaWYgKHR5cGVSZWdleHAudGVzdChuYW1lKSkgewogICAgICAgICAgdmFyIGNvbnRhaW5lck5hbWUgPSB0aGlzLnRyYW5zbGF0ZVRvQ29udGFpbmVyRnVsbG5hbWUodHlwZSwgbmFtZSk7CiAgICAgICAgICBrbm93bltjb250YWluZXJOYW1lXSA9IHRydWU7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4ga25vd247CiAgICB9CiAgICAvKioKICAgICAgQ29udmVydHMgcHJvdmlkZWQgbmFtZSBmcm9tIHRoZSBiYWNraW5nIG5hbWVzcGFjZSBpbnRvIGEgY29udGFpbmVyIGxvb2t1cCBuYW1lLgogICAgICAgRXhhbXBsZXM6CiAgICAgICAqIEFwcC5Gb29CYXJIZWxwZXIgLT4gaGVscGVyOmZvby1iYXIKICAgICAgKiBBcHAuVEhlbHBlciAtPiBoZWxwZXI6dAogICAgICAgQG1ldGhvZCB0cmFuc2xhdGVUb0NvbnRhaW5lckZ1bGxuYW1lCiAgICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by50cmFuc2xhdGVUb0NvbnRhaW5lckZ1bGxuYW1lID0gZnVuY3Rpb24gdHJhbnNsYXRlVG9Db250YWluZXJGdWxsbmFtZSh0eXBlLCBuYW1lKSB7CiAgICAgIHZhciBzdWZmaXggPSAoMCwgX3N0cmluZy5jbGFzc2lmeSkodHlwZSk7CiAgICAgIHZhciBuYW1lUHJlZml4ID0gbmFtZS5zbGljZSgwLCBzdWZmaXgubGVuZ3RoICogLTEpOwogICAgICB2YXIgZGFzaGVyaXplZE5hbWUgPSAoMCwgX3N0cmluZy5kYXNoZXJpemUpKG5hbWVQcmVmaXgpOwogICAgICByZXR1cm4gdHlwZSArICI6IiArIGRhc2hlcml6ZWROYW1lOwogICAgfTsKCiAgICByZXR1cm4gRGVmYXVsdFJlc29sdmVyOwogIH0oX3J1bnRpbWUuT2JqZWN0KTsKCiAgdmFyIF9kZWZhdWx0ID0gRGVmYXVsdFJlc29sdmVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIC8qKgogICAgICAgIEBtZXRob2QgX2xvZ0xvb2t1cAogICAgICAgIEBwYXJhbSB7Qm9vbGVhbn0gZm91bmQKICAgICAgICBAcGFyYW0ge09iamVjdH0gcGFyc2VkTmFtZQogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICBEZWZhdWx0UmVzb2x2ZXIucHJvdG90eXBlLl9sb2dMb29rdXAgPSBmdW5jdGlvbiAoZm91bmQsIHBhcnNlZE5hbWUpIHsKICAgICAgdmFyIHN5bWJvbCA9IGZvdW5kID8gJ1vinJNdJyA6ICdbIF0nOwogICAgICB2YXIgcGFkZGluZzsKCiAgICAgIGlmIChwYXJzZWROYW1lLmZ1bGxOYW1lLmxlbmd0aCA+IDYwKSB7CiAgICAgICAgcGFkZGluZyA9ICcuJzsKICAgICAgfSBlbHNlIHsKICAgICAgICBwYWRkaW5nID0gbmV3IEFycmF5KDYwIC0gcGFyc2VkTmFtZS5mdWxsTmFtZS5sZW5ndGgpLmpvaW4oJy4nKTsKICAgICAgfQoKICAgICAgKDAsIF9kZWJ1Zy5pbmZvKShzeW1ib2wsIHBhcnNlZE5hbWUuZnVsbE5hbWUsIHBhZGRpbmcsIHRoaXMubG9va3VwRGVzY3JpcHRpb24ocGFyc2VkTmFtZS5mdWxsTmFtZSkpOwogICAgfTsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci9hcHBsaWNhdGlvbi9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9vd25lciIsICJAZW1iZXIvYXBwbGljYXRpb24vbGliL2xhenlfbG9hZCIsICJAZW1iZXIvYXBwbGljYXRpb24vbGliL2FwcGxpY2F0aW9uIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX293bmVyLCBfbGF6eV9sb2FkLCBfYXBwbGljYXRpb24pIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImdldE93bmVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX293bmVyLmdldE93bmVyOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInNldE93bmVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX293bmVyLnNldE93bmVyOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIm9uTG9hZCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9sYXp5X2xvYWQub25Mb2FkOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInJ1bkxvYWRIb29rcyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9sYXp5X2xvYWQucnVuTG9hZEhvb2tzOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9sb2FkZWQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbGF6eV9sb2FkLl9sb2FkZWQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZGVmYXVsdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9hcHBsaWNhdGlvbi5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvYXBwbGljYXRpb24vaW5zdGFuY2UiLCBbImV4cG9ydHMiLCAiQGVtYmVyL3BvbHlmaWxscyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJAZW1iZXIvLWludGVybmFscy9icm93c2VyLWVudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzIiwgIkBlbWJlci9lbmdpbmUvaW5zdGFuY2UiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZ2xpbW1lciJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9wb2x5ZmlsbHMsIF9tZXRhbCwgZW52aXJvbm1lbnQsIF92aWV3cywgX2luc3RhbmNlLCBfZ2xpbW1lcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvYXBwbGljYXRpb24KICAqLwoKICAvKioKICAgIFRoZSBgQXBwbGljYXRpb25JbnN0YW5jZWAgZW5jYXBzdWxhdGVzIGFsbCBvZiB0aGUgc3RhdGVmdWwgYXNwZWN0cyBvZiBhCiAgICBydW5uaW5nIGBBcHBsaWNhdGlvbmAuCiAgCiAgICBBdCBhIGhpZ2gtbGV2ZWwsIHdlIGJyZWFrIGFwcGxpY2F0aW9uIGJvb3QgaW50byB0d28gZGlzdGluY3QgcGhhc2VzOgogIAogICAgKiBEZWZpbml0aW9uIHRpbWUsIHdoZXJlIGFsbCBvZiB0aGUgY2xhc3NlcywgdGVtcGxhdGVzLCBhbmQgb3RoZXIKICAgICAgZGVwZW5kZW5jaWVzIGFyZSBsb2FkZWQgKHR5cGljYWxseSBpbiB0aGUgYnJvd3NlcikuCiAgICAqIFJ1biB0aW1lLCB3aGVyZSB3ZSBiZWdpbiBleGVjdXRpbmcgdGhlIGFwcGxpY2F0aW9uIG9uY2UgZXZlcnl0aGluZwogICAgICBoYXMgbG9hZGVkLgogIAogICAgRGVmaW5pdGlvbiB0aW1lIGNhbiBiZSBleHBlbnNpdmUgYW5kIG9ubHkgbmVlZHMgdG8gaGFwcGVuIG9uY2Ugc2luY2UgaXQgaXMKICAgIGFuIGlkZW1wb3RlbnQgb3BlcmF0aW9uLiBGb3IgZXhhbXBsZSwgYmV0d2VlbiB0ZXN0IHJ1bnMgYW5kIEZhc3RCb290CiAgICByZXF1ZXN0cywgdGhlIGFwcGxpY2F0aW9uIHN0YXlzIHRoZSBzYW1lLiBJdCBpcyBvbmx5IHRoZSBzdGF0ZSB0aGF0IHdlIHdhbnQKICAgIHRvIHJlc2V0LgogIAogICAgVGhhdCBzdGF0ZSBpcyB3aGF0IHRoZSBgQXBwbGljYXRpb25JbnN0YW5jZWAgbWFuYWdlczogaXQgaXMgcmVzcG9uc2libGUgZm9yCiAgICBjcmVhdGluZyB0aGUgY29udGFpbmVyIHRoYXQgY29udGFpbnMgYWxsIGFwcGxpY2F0aW9uIHN0YXRlLCBhbmQgZGlzcG9zaW5nIG9mCiAgICBpdCBvbmNlIHRoZSBwYXJ0aWN1bGFyIHRlc3QgcnVuIG9yIEZhc3RCb290IHJlcXVlc3QgaGFzIGZpbmlzaGVkLgogIAogICAgQHB1YmxpYwogICAgQGNsYXNzIEFwcGxpY2F0aW9uSW5zdGFuY2UKICAgIEBleHRlbmRzIEVuZ2luZUluc3RhbmNlCiAgKi8KICB2YXIgQXBwbGljYXRpb25JbnN0YW5jZSA9IF9pbnN0YW5jZS5kZWZhdWx0LmV4dGVuZCh7CiAgICAvKioKICAgICAgVGhlIGBBcHBsaWNhdGlvbmAgZm9yIHdoaWNoIHRoaXMgaXMgYW4gaW5zdGFuY2UuCiAgICAgICBAcHJvcGVydHkge0FwcGxpY2F0aW9ufSBhcHBsaWNhdGlvbgogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGFwcGxpY2F0aW9uOiBudWxsLAoKICAgIC8qKgogICAgICBUaGUgRE9NIGV2ZW50cyBmb3Igd2hpY2ggdGhlIGV2ZW50IGRpc3BhdGNoZXIgc2hvdWxkIGxpc3Rlbi4KICAgICAgIEJ5IGRlZmF1bHQsIHRoZSBhcHBsaWNhdGlvbidzIGBFbWJlci5FdmVudERpc3BhdGNoZXJgIGxpc3RlbnMKICAgICAgZm9yIGEgc2V0IG9mIHN0YW5kYXJkIERPTSBldmVudHMsIHN1Y2ggYXMgYG1vdXNlZG93bmAgYW5kCiAgICAgIGBrZXl1cGAsIGFuZCBkZWxlZ2F0ZXMgdGhlbSB0byB5b3VyIGFwcGxpY2F0aW9uJ3MgYEVtYmVyLlZpZXdgCiAgICAgIGluc3RhbmNlcy4KICAgICAgIEBwcml2YXRlCiAgICAgIEBwcm9wZXJ0eSB7T2JqZWN0fSBjdXN0b21FdmVudHMKICAgICovCiAgICBjdXN0b21FdmVudHM6IG51bGwsCgogICAgLyoqCiAgICAgIFRoZSByb290IERPTSBlbGVtZW50IG9mIHRoZSBBcHBsaWNhdGlvbiBhcyBhbiBlbGVtZW50IG9yIGEKICAgICAgW2pRdWVyeS1jb21wYXRpYmxlIHNlbGVjdG9yCiAgICAgIHN0cmluZ10oaHR0cDovL2FwaS5qcXVlcnkuY29tL2NhdGVnb3J5L3NlbGVjdG9ycy8pLgogICAgICAgQHByaXZhdGUKICAgICAgQHByb3BlcnR5IHtTdHJpbmd8RE9NRWxlbWVudH0gcm9vdEVsZW1lbnQKICAgICovCiAgICByb290RWxlbWVudDogbnVsbCwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzLmFwcGxpY2F0aW9uLl93YXRjaEluc3RhbmNlKHRoaXMpOyAvLyBSZWdpc3RlciB0aGlzIGluc3RhbmNlIGluIHRoZSBwZXItaW5zdGFuY2UgcmVnaXN0cnkuCiAgICAgIC8vCiAgICAgIC8vIFdoeSBkbyB3ZSBuZWVkIHRvIHJlZ2lzdGVyIHRoZSBpbnN0YW5jZSBpbiB0aGUgZmlyc3QgcGxhY2U/CiAgICAgIC8vIEJlY2F1c2Ugd2UgbmVlZCBhIGdvb2Qgd2F5IGZvciB0aGUgcm9vdCByb3V0ZSAoYS5rLmEgQXBwbGljYXRpb25Sb3V0ZSkKICAgICAgLy8gdG8gbm90aWZ5IHVzIHdoZW4gaXQgaGFzIGNyZWF0ZWQgdGhlIHJvb3QtbW9zdCB2aWV3LiBUaGF0IHZpZXcgaXMgdGhlbgogICAgICAvLyBhcHBlbmRlZCB0byB0aGUgcm9vdEVsZW1lbnQsIGluIHRoZSBjYXNlIG9mIGFwcHMsIHRvIHRoZSBmaXh0dXJlIGhhcm5lc3MKICAgICAgLy8gaW4gdGVzdHMsIG9yIHJlbmRlcmVkIHRvIGEgc3RyaW5nIGluIHRoZSBjYXNlIG9mIEZhc3RCb290LgoKCiAgICAgIHRoaXMucmVnaXN0ZXIoJy1hcHBsaWNhdGlvbi1pbnN0YW5jZTptYWluJywgdGhpcywgewogICAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIE92ZXJyaWRlcyB0aGUgYmFzZSBgRW5naW5lSW5zdGFuY2UuX2Jvb3RTeW5jYCBtZXRob2Qgd2l0aCBjb25jZXJucyByZWxldmFudAogICAgICB0byBib290aW5nIGFwcGxpY2F0aW9uIChpbnN0ZWFkIG9mIGVuZ2luZSkgaW5zdGFuY2VzLgogICAgICAgVGhpcyBtZXRob2Qgc2hvdWxkIG9ubHkgY29udGFpbiBzeW5jaHJvbm91cyBib290IGNvbmNlcm5zLiBBc3luY2hyb25vdXMKICAgICAgYm9vdCBjb25jZXJucyBzaG91bGQgZXZlbnR1YWxseSBiZSBtb3ZlZCB0byB0aGUgYGJvb3RgIG1ldGhvZCwgd2hpY2gKICAgICAgcmV0dXJucyBhIHByb21pc2UuCiAgICAgICBVbnRpbCBhbGwgYm9vdCBjb2RlIGhhcyBiZWVuIG1hZGUgYXN5bmNocm9ub3VzLCB3ZSBuZWVkIHRvIGNvbnRpbnVlIHRvCiAgICAgIGV4cG9zZSB0aGlzIG1ldGhvZCBmb3IgdXNlICppbnRlcm5hbGx5KiBpbiBwbGFjZXMgd2hlcmUgd2UgbmVlZCB0byBib290IGFuCiAgICAgIGluc3RhbmNlIHN5bmNocm9ub3VzbHkuCiAgICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ib290U3luYzogZnVuY3Rpb24gX2Jvb3RTeW5jKG9wdGlvbnMpIHsKICAgICAgaWYgKHRoaXMuX2Jvb3RlZCkgewogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CgogICAgICBvcHRpb25zID0gbmV3IEJvb3RPcHRpb25zKG9wdGlvbnMpOwogICAgICB0aGlzLnNldHVwUmVnaXN0cnkob3B0aW9ucyk7CgogICAgICBpZiAob3B0aW9ucy5yb290RWxlbWVudCkgewogICAgICAgIHRoaXMucm9vdEVsZW1lbnQgPSBvcHRpb25zLnJvb3RFbGVtZW50OwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMucm9vdEVsZW1lbnQgPSB0aGlzLmFwcGxpY2F0aW9uLnJvb3RFbGVtZW50OwogICAgICB9CgogICAgICBpZiAob3B0aW9ucy5sb2NhdGlvbikgewogICAgICAgICgwLCBfbWV0YWwuc2V0KSh0aGlzLnJvdXRlciwgJ2xvY2F0aW9uJywgb3B0aW9ucy5sb2NhdGlvbik7CiAgICAgIH0KCiAgICAgIHRoaXMuYXBwbGljYXRpb24ucnVuSW5zdGFuY2VJbml0aWFsaXplcnModGhpcyk7CgogICAgICBpZiAob3B0aW9ucy5pc0ludGVyYWN0aXZlKSB7CiAgICAgICAgdGhpcy5zZXR1cEV2ZW50RGlzcGF0Y2hlcigpOwogICAgICB9CgogICAgICB0aGlzLl9ib290ZWQgPSB0cnVlOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCiAgICBzZXR1cFJlZ2lzdHJ5OiBmdW5jdGlvbiBzZXR1cFJlZ2lzdHJ5KG9wdGlvbnMpIHsKICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5zZXR1cFJlZ2lzdHJ5KHRoaXMuX19yZWdpc3RyeV9fLCBvcHRpb25zKTsKICAgIH0sCiAgICByb3V0ZXI6ICgwLCBfbWV0YWwuY29tcHV0ZWQpKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIHRoaXMubG9va3VwKCdyb3V0ZXI6bWFpbicpOwogICAgfSkucmVhZE9ubHkoKSwKCiAgICAvKioKICAgICAgVGhpcyBob29rIGlzIGNhbGxlZCBieSB0aGUgcm9vdC1tb3N0IFJvdXRlIChhLmsuYS4gdGhlIEFwcGxpY2F0aW9uUm91dGUpCiAgICAgIHdoZW4gaXQgaGFzIGZpbmlzaGVkIGNyZWF0aW5nIHRoZSByb290IFZpZXcuIEJ5IGRlZmF1bHQsIHdlIHNpbXBseSB0YWtlIHRoZQogICAgICB2aWV3IGFuZCBhcHBlbmQgaXQgdG8gdGhlIGByb290RWxlbWVudGAgc3BlY2lmaWVkIG9uIHRoZSBBcHBsaWNhdGlvbi4KICAgICAgIEluIGNhc2VzIGxpa2UgRmFzdEJvb3QgYW5kIHRlc3RpbmcsIHdlIGNhbiBvdmVycmlkZSB0aGlzIGhvb2sgYW5kIGltcGxlbWVudAogICAgICBjdXN0b20gYmVoYXZpb3IsIHN1Y2ggYXMgc2VyaWFsaXppbmcgdG8gYSBzdHJpbmcgYW5kIHNlbmRpbmcgb3ZlciBhbiBIVFRQCiAgICAgIHNvY2tldCByYXRoZXIgdGhhbiBhcHBlbmRpbmcgdG8gRE9NLgogICAgICAgQHBhcmFtIHZpZXcge0VtYmVyLlZpZXd9IHRoZSByb290LW1vc3QgdmlldwogICAgICBAZGVwcmVjYXRlZAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGRpZENyZWF0ZVJvb3RWaWV3OiBmdW5jdGlvbiBkaWRDcmVhdGVSb290Vmlldyh2aWV3KSB7CiAgICAgIHZpZXcuYXBwZW5kVG8odGhpcy5yb290RWxlbWVudCk7CiAgICB9LAoKICAgIC8qKgogICAgICBUZWxscyB0aGUgcm91dGVyIHRvIHN0YXJ0IHJvdXRpbmcuIFRoZSByb3V0ZXIgd2lsbCBhc2sgdGhlIGxvY2F0aW9uIGZvciB0aGUKICAgICAgY3VycmVudCBVUkwgb2YgdGhlIHBhZ2UgdG8gZGV0ZXJtaW5lIHRoZSBpbml0aWFsIFVSTCB0byBzdGFydCByb3V0aW5nIHRvLgogICAgICBUbyBzdGFydCB0aGUgYXBwIGF0IGEgc3BlY2lmaWMgVVJMLCBjYWxsIGBoYW5kbGVVUkxgIGluc3RlYWQuCiAgICAgICBAcHJpdmF0ZQogICAgKi8KICAgIHN0YXJ0Um91dGluZzogZnVuY3Rpb24gc3RhcnRSb3V0aW5nKCkgewogICAgICB0aGlzLnJvdXRlci5zdGFydFJvdXRpbmcoKTsKICAgICAgdGhpcy5fZGlkU2V0dXBSb3V0ZXIgPSB0cnVlOwogICAgfSwKCiAgICAvKioKICAgICAgU2V0cyB1cCB0aGUgcm91dGVyLCBpbml0aWFsaXppbmcgdGhlIGNoaWxkIHJvdXRlciBhbmQgY29uZmlndXJpbmcgdGhlCiAgICAgIGxvY2F0aW9uIGJlZm9yZSByb3V0aW5nIGJlZ2lucy4KICAgICAgIEJlY2F1c2Ugc2V0dXAgc2hvdWxkIG9ubHkgb2NjdXIgb25jZSwgbXVsdGlwbGUgY2FsbHMgdG8gYHNldHVwUm91dGVyYAogICAgICBiZXlvbmQgdGhlIGZpcnN0IGNhbGwgaGF2ZSBubyBlZmZlY3QuCiAgICAgIAogICAgICBUaGlzIGlzIGNvbW1vbmx5IHVzZWQgaW4gb3JkZXIgdG8gY29uZmlybSB0aGluZ3MgdGhhdCByZWx5IG9uIHRoZSByb3V0ZXIKICAgICAgYXJlIGZ1bmN0aW9uaW5nIHByb3Blcmx5IGZyb20gdGVzdHMgdGhhdCBhcmUgcHJpbWFyaWx5IHJlbmRlcmluZyByZWxhdGVkLgogICAgICAKICAgICAgRm9yIGV4YW1wbGUsIGZyb20gd2l0aGluIFtlbWJlci1xdW5pdF0oaHR0cHM6Ly9naXRodWIuY29tL2VtYmVyanMvZW1iZXItcXVuaXQpJ3MKICAgICAgYHNldHVwUmVuZGVyaW5nVGVzdGAgY2FsbGluZyBgdGhpcy5vd25lci5zZXR1cFJvdXRlcigpYCB3b3VsZCBhbGxvdyB0aGF0CiAgICAgIHJlbmRlcmluZyB0ZXN0IHRvIGNvbmZpcm0gdGhhdCBhbnkgYDxMaW5rVG8+PC9MaW5rVG8+YCdzIHRoYXQgYXJlIHJlbmRlcmVkCiAgICAgIGhhdmUgdGhlIGNvcnJlY3QgVVJMLgogICAgICAKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHNldHVwUm91dGVyOiBmdW5jdGlvbiBzZXR1cFJvdXRlcigpIHsKICAgICAgaWYgKHRoaXMuX2RpZFNldHVwUm91dGVyKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9kaWRTZXR1cFJvdXRlciA9IHRydWU7CiAgICAgIHRoaXMucm91dGVyLnNldHVwUm91dGVyKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBEaXJlY3RzIHRoZSByb3V0ZXIgdG8gcm91dGUgdG8gYSBwYXJ0aWN1bGFyIFVSTC4gVGhpcyBpcyB1c2VmdWwgaW4gdGVzdHMsCiAgICAgIGZvciBleGFtcGxlLCB0byB0ZWxsIHRoZSBhcHAgdG8gc3RhcnQgYXQgYSBwYXJ0aWN1bGFyIFVSTC4KICAgICAgIEBwYXJhbSB1cmwge1N0cmluZ30gdGhlIFVSTCB0aGUgcm91dGVyIHNob3VsZCByb3V0ZSB0bwogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGhhbmRsZVVSTDogZnVuY3Rpb24gaGFuZGxlVVJMKHVybCkgewogICAgICB0aGlzLnNldHVwUm91dGVyKCk7CiAgICAgIHJldHVybiB0aGlzLnJvdXRlci5oYW5kbGVVUkwodXJsKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgc2V0dXBFdmVudERpc3BhdGNoZXI6IGZ1bmN0aW9uIHNldHVwRXZlbnREaXNwYXRjaGVyKCkgewogICAgICB2YXIgZGlzcGF0Y2hlciA9IHRoaXMubG9va3VwKCdldmVudF9kaXNwYXRjaGVyOm1haW4nKTsKICAgICAgdmFyIGFwcGxpY2F0aW9uQ3VzdG9tRXZlbnRzID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMuYXBwbGljYXRpb24sICdjdXN0b21FdmVudHMnKTsKICAgICAgdmFyIGluc3RhbmNlQ3VzdG9tRXZlbnRzID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsICdjdXN0b21FdmVudHMnKTsKICAgICAgdmFyIGN1c3RvbUV2ZW50cyA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIGFwcGxpY2F0aW9uQ3VzdG9tRXZlbnRzLCBpbnN0YW5jZUN1c3RvbUV2ZW50cyk7CiAgICAgIGRpc3BhdGNoZXIuc2V0dXAoY3VzdG9tRXZlbnRzLCB0aGlzLnJvb3RFbGVtZW50KTsKICAgICAgcmV0dXJuIGRpc3BhdGNoZXI7CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIHRoZSBjdXJyZW50IFVSTCBvZiB0aGUgYXBwIGluc3RhbmNlLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdXIKICAgICAgYXBwIGRvZXMgbm90IHVwZGF0ZSB0aGUgYnJvd3NlcnMgVVJMIGJhciAoaS5lLiBpdCB1c2VzIHRoZSBgJ25vbmUnYAogICAgICBsb2NhdGlvbiBhZGFwdGVyKS4KICAgICAgIEBwdWJsaWMKICAgICAgQHJldHVybiB7U3RyaW5nfSB0aGUgY3VycmVudCBVUkwKICAgICovCiAgICBnZXRVUkw6IGZ1bmN0aW9uIGdldFVSTCgpIHsKICAgICAgcmV0dXJuIHRoaXMucm91dGVyLnVybDsKICAgIH0sCiAgICAvLyBgaW5zdGFuY2UudmlzaXQodXJsKWAgc2hvdWxkIGV2ZW50dWFsbHkgcmVwbGFjZSBgaW5zdGFuY2UuaGFuZGxlVVJMKClgOwogICAgLy8gdGhlIHRlc3QgaGVscGVycyBjYW4gcHJvYmFibHkgYmUgc3dpdGNoZWQgdG8gdXNlIHRoaXMgaW1wbGVtZW50YXRpb24gdG9vCgogICAgLyoqCiAgICAgIE5hdmlnYXRlIHRoZSBpbnN0YW5jZSB0byBhIHBhcnRpY3VsYXIgVVJMLiBUaGlzIGlzIHVzZWZ1bCBpbiB0ZXN0cywgZm9yCiAgICAgIGV4YW1wbGUsIG9yIHRvIHRlbGwgdGhlIGFwcCB0byBzdGFydCBhdCBhIHBhcnRpY3VsYXIgVVJMLiBUaGlzIG1ldGhvZAogICAgICByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGFwcCBpbnN0YW5jZSB3aGVuIHRoZSB0cmFuc2l0aW9uCiAgICAgIGlzIGNvbXBsZXRlLCBvciByZWplY3RzIGlmIHRoZSB0cmFuc2lvbiB3YXMgYWJvcnRlZCBkdWUgdG8gYW4gZXJyb3IuCiAgICAgICBAcHVibGljCiAgICAgIEBwYXJhbSB1cmwge1N0cmluZ30gdGhlIGRlc3RpbmF0aW9uIFVSTAogICAgICBAcmV0dXJuIHtQcm9taXNlPEFwcGxpY2F0aW9uSW5zdGFuY2U+fQogICAgKi8KICAgIHZpc2l0OiBmdW5jdGlvbiB2aXNpdCh1cmwpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHRoaXMuc2V0dXBSb3V0ZXIoKTsKCiAgICAgIHZhciBib290T3B0aW9ucyA9IHRoaXMuX19jb250YWluZXJfXy5sb29rdXAoJy1lbnZpcm9ubWVudDptYWluJyk7CgogICAgICB2YXIgcm91dGVyID0gdGhpcy5yb3V0ZXI7CgogICAgICB2YXIgaGFuZGxlVHJhbnNpdGlvblJlc29sdmUgPSBmdW5jdGlvbiBoYW5kbGVUcmFuc2l0aW9uUmVzb2x2ZSgpIHsKICAgICAgICBpZiAoIWJvb3RPcHRpb25zLm9wdGlvbnMuc2hvdWxkUmVuZGVyKSB7CiAgICAgICAgICAvLyBObyByZW5kZXJpbmcgaXMgbmVlZGVkLCBhbmQgcm91dGluZyBoYXMgY29tcGxldGVkLCBzaW1wbHkgcmV0dXJuLgogICAgICAgICAgcmV0dXJuIF90aGlzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBFbnN1cmUgdGhhdCB0aGUgdmlzaXQgcHJvbWlzZSByZXNvbHZlcyB3aGVuIGFsbCByZW5kZXJpbmcgaGFzIGNvbXBsZXRlZAogICAgICAgICAgcmV0dXJuICgwLCBfZ2xpbW1lci5yZW5kZXJTZXR0bGVkKSgpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgICByZXR1cm4gX3RoaXM7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH07CgogICAgICB2YXIgaGFuZGxlVHJhbnNpdGlvblJlamVjdCA9IGZ1bmN0aW9uIGhhbmRsZVRyYW5zaXRpb25SZWplY3QoZXJyb3IpIHsKICAgICAgICBpZiAoZXJyb3IuZXJyb3IpIHsKICAgICAgICAgIHRocm93IGVycm9yLmVycm9yOwogICAgICAgIH0gZWxzZSBpZiAoZXJyb3IubmFtZSA9PT0gJ1RyYW5zaXRpb25BYm9ydGVkJyAmJiByb3V0ZXIuX3JvdXRlck1pY3JvbGliLmFjdGl2ZVRyYW5zaXRpb24pIHsKICAgICAgICAgIHJldHVybiByb3V0ZXIuX3JvdXRlck1pY3JvbGliLmFjdGl2ZVRyYW5zaXRpb24udGhlbihoYW5kbGVUcmFuc2l0aW9uUmVzb2x2ZSwgaGFuZGxlVHJhbnNpdGlvblJlamVjdCk7CiAgICAgICAgfSBlbHNlIGlmIChlcnJvci5uYW1lID09PSAnVHJhbnNpdGlvbkFib3J0ZWQnKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IubWVzc2FnZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgIH0KICAgICAgfTsKCiAgICAgIHZhciBsb2NhdGlvbiA9ICgwLCBfbWV0YWwuZ2V0KShyb3V0ZXIsICdsb2NhdGlvbicpOyAvLyBLZWVwcyB0aGUgbG9jYXRpb24gYWRhcHRlcidzIGludGVybmFsIFVSTCBpbi1zeW5jCgogICAgICBsb2NhdGlvbi5zZXRVUkwodXJsKTsgLy8gZ2V0VVJMIHJldHVybnMgdGhlIHNldCB1cmwgd2l0aCB0aGUgcm9vdFVSTCBzdHJpcHBlZCBvZmYKCiAgICAgIHJldHVybiByb3V0ZXIuaGFuZGxlVVJMKGxvY2F0aW9uLmdldFVSTCgpKS50aGVuKGhhbmRsZVRyYW5zaXRpb25SZXNvbHZlLCBoYW5kbGVUcmFuc2l0aW9uUmVqZWN0KTsKICAgIH0sCiAgICB3aWxsRGVzdHJveTogZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICB0aGlzLmFwcGxpY2F0aW9uLl91bndhdGNoSW5zdGFuY2UodGhpcyk7CiAgICB9CiAgfSk7CgogIEFwcGxpY2F0aW9uSW5zdGFuY2UucmVvcGVuQ2xhc3MoewogICAgLyoqCiAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIHNldHVwUmVnaXN0cnkKICAgICBAcGFyYW0ge1JlZ2lzdHJ5fSByZWdpc3RyeQogICAgIEBwYXJhbSB7Qm9vdE9wdGlvbnN9IG9wdGlvbnMKICAgICovCiAgICBzZXR1cFJlZ2lzdHJ5OiBmdW5jdGlvbiBzZXR1cFJlZ2lzdHJ5KHJlZ2lzdHJ5LCBvcHRpb25zKSB7CiAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsKICAgICAgICBvcHRpb25zID0ge307CiAgICAgIH0KCiAgICAgIGlmICghb3B0aW9ucy50b0Vudmlyb25tZW50KSB7CiAgICAgICAgb3B0aW9ucyA9IG5ldyBCb290T3B0aW9ucyhvcHRpb25zKTsKICAgICAgfQoKICAgICAgcmVnaXN0cnkucmVnaXN0ZXIoJy1lbnZpcm9ubWVudDptYWluJywgb3B0aW9ucy50b0Vudmlyb25tZW50KCksIHsKICAgICAgICBpbnN0YW50aWF0ZTogZmFsc2UKICAgICAgfSk7CiAgICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdzZXJ2aWNlOi1kb2N1bWVudCcsIG9wdGlvbnMuZG9jdW1lbnQsIHsKICAgICAgICBpbnN0YW50aWF0ZTogZmFsc2UKICAgICAgfSk7CgogICAgICB0aGlzLl9zdXBlcihyZWdpc3RyeSwgb3B0aW9ucyk7CiAgICB9CiAgfSk7CiAgLyoqCiAgICBBIGxpc3Qgb2YgYm9vdC10aW1lIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgY3VzdG9taXppbmcgdGhlIGJlaGF2aW9yIG9mCiAgICBhbiBgQXBwbGljYXRpb25JbnN0YW5jZWAuCiAgCiAgICBUaGlzIGlzIGFuIGludGVyZmFjZSBjbGFzcyB0aGF0IGV4aXN0cyBwdXJlbHkgdG8gZG9jdW1lbnQgdGhlIGF2YWlsYWJsZQogICAgb3B0aW9uczsgeW91IGRvIG5vdCBuZWVkIHRvIGNvbnN0cnVjdCBpdCBtYW51YWxseS4gU2ltcGx5IHBhc3MgYSByZWd1bGFyCiAgICBKYXZhU2NyaXB0IG9iamVjdCBjb250YWluaW5nIHRoZSBkZXNpcmVkIG9wdGlvbnMgaW50byBtZXRob2RzIHRoYXQgcmVxdWlyZQogICAgb25lIG9mIHRoZXNlIG9wdGlvbnMgb2JqZWN0OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgTXlBcHAudmlzaXQoIi8iLCB7IGxvY2F0aW9uOiAibm9uZSIsIHJvb3RFbGVtZW50OiAiI2NvbnRhaW5lciIgfSk7CiAgICBgYGAKICAKICAgIE5vdCBhbGwgY29tYmluYXRpb25zIG9mIHRoZSBzdXBwb3J0ZWQgb3B0aW9ucyBhcmUgdmFsaWQuIFNlZSB0aGUgZG9jdW1lbnRhdGlvbgogICAgb24gYEFwcGxpY2F0aW9uI3Zpc2l0YCBmb3IgdGhlIHN1cHBvcnRlZCBjb25maWd1cmF0aW9ucy4KICAKICAgIEludGVybmFsLCBleHBlcmltZW50YWwgb3Igb3RoZXJ3aXNlIHVuc3RhYmxlIGZsYWdzIGFyZSBtYXJrZWQgYXMgcHJpdmF0ZS4KICAKICAgIEBjbGFzcyBCb290T3B0aW9ucwogICAgQG5hbWVzcGFjZSBBcHBsaWNhdGlvbkluc3RhbmNlCiAgICBAcHVibGljCiAgKi8KCiAgdmFyIEJvb3RPcHRpb25zID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQm9vdE9wdGlvbnMob3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICAvKioKICAgICAgICBQcm92aWRlIGEgc3BlY2lmaWMgaW5zdGFuY2Ugb2YgalF1ZXJ5LiBUaGlzIGlzIHVzZWZ1bCBpbiBjb25qdW5jdGlvbiB3aXRoCiAgICAgICAgdGhlIGBkb2N1bWVudGAgb3B0aW9uLCBhcyBpdCBhbGxvd3MgeW91IHRvIHVzZSBhIGNvcHkgb2YgYGpRdWVyeWAgdGhhdCBpcwogICAgICAgIGFwcHJvcHJpYXRlbHkgYm91bmQgdG8gdGhlIGZvcmVpZ24gYGRvY3VtZW50YCAoZS5nLiBhIGpzZG9tKS4KICAgICAgICAgVGhpcyBpcyBoaWdobHkgZXhwZXJpbWVudGFsIGFuZCBzdXBwb3J0IHZlcnkgaW5jb21wbGV0ZSBhdCB0aGUgbW9tZW50LgogICAgICAgICBAcHJvcGVydHkgalF1ZXJ5CiAgICAgICAgQHR5cGUgT2JqZWN0CiAgICAgICAgQGRlZmF1bHQgYXV0by1kZXRlY3RlZAogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIHRoaXMualF1ZXJ5ID0gX3ZpZXdzLmpRdWVyeTsgLy8gVGhpcyBkZWZhdWx0IGlzIG92ZXJyaWRhYmxlIGJlbG93CgogICAgICAvKioKICAgICAgICBJbnRlcmFjdGl2ZSBtb2RlOiB3aGV0aGVyIHdlIG5lZWQgdG8gc2V0IHVwIGV2ZW50IGRlbGVnYXRpb24gYW5kIGludm9rZQogICAgICAgIGxpZmVjeWNsZSBjYWxsYmFja3Mgb24gQ29tcG9uZW50cy4KICAgICAgICAgQHByb3BlcnR5IGlzSW50ZXJhY3RpdmUKICAgICAgICBAdHlwZSBib29sZWFuCiAgICAgICAgQGRlZmF1bHQgYXV0by1kZXRlY3RlZAogICAgICAgIEBwcml2YXRlCiAgICAgICovCgogICAgICB0aGlzLmlzSW50ZXJhY3RpdmUgPSBlbnZpcm9ubWVudC5oYXNET007IC8vIFRoaXMgZGVmYXVsdCBpcyBvdmVycmlkYWJsZSBiZWxvdwoKICAgICAgLyoqCiAgICAgICAgQHByb3BlcnR5IF9yZW5kZXJNb2RlCiAgICAgICAgQHR5cGUgc3RyaW5nCiAgICAgICAgQGRlZmF1bHQgZmFsc2UKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwoKICAgICAgdGhpcy5fcmVuZGVyTW9kZSA9IG9wdGlvbnMuX3JlbmRlck1vZGU7CiAgICAgIC8qKgogICAgICAgIFJ1biBpbiBhIGZ1bGwgYnJvd3NlciBlbnZpcm9ubWVudC4KICAgICAgICAgV2hlbiB0aGlzIGZsYWcgaXMgc2V0IHRvIGBmYWxzZWAsIGl0IHdpbGwgZGlzYWJsZSBtb3N0IGJyb3dzZXItc3BlY2lmaWMKICAgICAgICBhbmQgaW50ZXJhY3RpdmUgZmVhdHVyZXMuIFNwZWNpZmljYWxseToKICAgICAgICAgKiBJdCBkb2VzIG5vdCB1c2UgYGpRdWVyeWAgdG8gYXBwZW5kIHRoZSByb290IHZpZXc7IHRoZSBgcm9vdEVsZW1lbnRgCiAgICAgICAgICAoZWl0aGVyIHNwZWNpZmllZCBhcyBhIHN1YnNlcXVlbnQgb3B0aW9uIG9yIG9uIHRoZSBhcHBsaWNhdGlvbiBpdHNlbGYpCiAgICAgICAgICBtdXN0IGFscmVhZHkgYmUgYW4gYEVsZW1lbnRgIGluIHRoZSBnaXZlbiBgZG9jdW1lbnRgIChhcyBvcHBvc2VkIHRvIGEKICAgICAgICAgIHN0cmluZyBzZWxlY3RvcikuCiAgICAgICAgICogSXQgZG9lcyBub3Qgc2V0IHVwIGFuIGBFdmVudERpc3BhdGNoZXJgLgogICAgICAgICAqIEl0IGRvZXMgbm90IHJ1biBhbnkgYENvbXBvbmVudGAgbGlmZWN5Y2xlIGhvb2tzIChzdWNoIGFzIGBkaWRJbnNlcnRFbGVtZW50YCkuCiAgICAgICAgICogSXQgc2V0cyB0aGUgYGxvY2F0aW9uYCBvcHRpb24gdG8gYCJub25lImAuIChJZiB5b3Ugd291bGQgbGlrZSB0byB1c2UKICAgICAgICAgIHRoZSBsb2NhdGlvbiBhZGFwdGVyIHNwZWNpZmllZCBpbiB0aGUgYXBwJ3Mgcm91dGVyIGluc3RlYWQsIHlvdSBjYW4gYWxzbwogICAgICAgICAgc3BlY2lmeSBgeyBsb2NhdGlvbjogbnVsbCB9YCB0byBzcGVjaWZpY2FsbHkgb3B0LW91dC4pCiAgICAgICAgIEBwcm9wZXJ0eSBpc0Jyb3dzZXIKICAgICAgICBAdHlwZSBib29sZWFuCiAgICAgICAgQGRlZmF1bHQgYXV0by1kZXRlY3RlZAogICAgICAgIEBwdWJsaWMKICAgICAgKi8KCiAgICAgIGlmIChvcHRpb25zLmlzQnJvd3NlciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdGhpcy5pc0Jyb3dzZXIgPSBCb29sZWFuKG9wdGlvbnMuaXNCcm93c2VyKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLmlzQnJvd3NlciA9IGVudmlyb25tZW50Lmhhc0RPTTsKICAgICAgfQoKICAgICAgaWYgKCF0aGlzLmlzQnJvd3NlcikgewogICAgICAgIHRoaXMualF1ZXJ5ID0gbnVsbDsKICAgICAgICB0aGlzLmlzSW50ZXJhY3RpdmUgPSBmYWxzZTsKICAgICAgICB0aGlzLmxvY2F0aW9uID0gJ25vbmUnOwogICAgICB9CiAgICAgIC8qKgogICAgICAgIERpc2FibGUgcmVuZGVyaW5nIGNvbXBsZXRlbHkuCiAgICAgICAgIFdoZW4gdGhpcyBmbGFnIGlzIHNldCB0byBgZmFsc2VgLCBpdCB3aWxsIGRpc2FibGUgdGhlIGVudGlyZSByZW5kZXJpbmcKICAgICAgICBwaXBlbGluZS4gRXNzZW50aWFsbHksIHRoaXMgcHV0cyB0aGUgYXBwIGludG8gInJvdXRpbmctb25seSIgbW9kZS4gTm8KICAgICAgICB0ZW1wbGF0ZXMgd2lsbCBiZSByZW5kZXJlZCwgYW5kIG5vIENvbXBvbmVudHMgd2lsbCBiZSBjcmVhdGVkLgogICAgICAgICBAcHJvcGVydHkgc2hvdWxkUmVuZGVyCiAgICAgICAgQHR5cGUgYm9vbGVhbgogICAgICAgIEBkZWZhdWx0IHRydWUKICAgICAgICBAcHVibGljCiAgICAgICovCgoKICAgICAgaWYgKG9wdGlvbnMuc2hvdWxkUmVuZGVyICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLnNob3VsZFJlbmRlciA9IEJvb2xlYW4ob3B0aW9ucy5zaG91bGRSZW5kZXIpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuc2hvdWxkUmVuZGVyID0gdHJ1ZTsKICAgICAgfQoKICAgICAgaWYgKCF0aGlzLnNob3VsZFJlbmRlcikgewogICAgICAgIHRoaXMualF1ZXJ5ID0gbnVsbDsKICAgICAgICB0aGlzLmlzSW50ZXJhY3RpdmUgPSBmYWxzZTsKICAgICAgfQogICAgICAvKioKICAgICAgICBJZiBwcmVzZW50LCByZW5kZXIgaW50byB0aGUgZ2l2ZW4gYERvY3VtZW50YCBvYmplY3QgaW5zdGVhZCBvZiB0aGUKICAgICAgICBnbG9iYWwgYHdpbmRvdy5kb2N1bWVudGAgb2JqZWN0LgogICAgICAgICBJbiBwcmFjdGljZSwgdGhpcyBpcyBvbmx5IHVzZWZ1bCBpbiBub24tYnJvd3NlciBlbnZpcm9ubWVudCBvciBpbgogICAgICAgIG5vbi1pbnRlcmFjdGl2ZSBtb2RlLCBiZWNhdXNlIEVtYmVyJ3MgYGpRdWVyeWAgZGVwZW5kZW5jeSBpcwogICAgICAgIGltcGxpY2l0bHkgYm91bmQgdG8gdGhlIGN1cnJlbnQgZG9jdW1lbnQsIGNhdXNpbmcgZXZlbnQgZGVsZWdhdGlvbgogICAgICAgIHRvIG5vdCB3b3JrIHByb3Blcmx5IHdoZW4gdGhlIGFwcCBpcyByZW5kZXJlZCBpbnRvIGEgZm9yZWlnbgogICAgICAgIGRvY3VtZW50IG9iamVjdCAoc3VjaCBhcyBhbiBpZnJhbWUncyBgY29udGVudERvY3VtZW50YCkuCiAgICAgICAgIEluIG5vbi1icm93c2VyIG1vZGUsIHRoaXMgY291bGQgYmUgYSAiYERvY3VtZW50YC1saWtlIiBvYmplY3QgYXMKICAgICAgICBFbWJlciBvbmx5IGludGVyYWN0IHdpdGggYSBzbWFsbCBzdWJzZXQgb2YgdGhlIERPTSBBUEkgaW4gbm9uLQogICAgICAgIGludGVyYWN0aXZlIG1vZGUuIFdoaWxlIHRoZSBleGFjdCByZXF1aXJlbWVudHMgaGF2ZSBub3QgeWV0IGJlZW4KICAgICAgICBmb3JtYWxpemVkLCB0aGUgYFNpbXBsZURPTWAgbGlicmFyeSdzIGltcGxlbWVudGF0aW9uIGlzIGtub3duIHRvCiAgICAgICAgd29yay4KICAgICAgICAgQHByb3BlcnR5IGRvY3VtZW50CiAgICAgICAgQHR5cGUgRG9jdW1lbnQKICAgICAgICBAZGVmYXVsdCB0aGUgZ2xvYmFsIGBkb2N1bWVudGAgb2JqZWN0CiAgICAgICAgQHB1YmxpYwogICAgICAqLwoKCiAgICAgIGlmIChvcHRpb25zLmRvY3VtZW50KSB7CiAgICAgICAgdGhpcy5kb2N1bWVudCA9IG9wdGlvbnMuZG9jdW1lbnQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5kb2N1bWVudCA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgPyBkb2N1bWVudCA6IG51bGw7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAgSWYgcHJlc2VudCwgb3ZlcnJpZGVzIHRoZSBhcHBsaWNhdGlvbidzIGByb290RWxlbWVudGAgcHJvcGVydHkgb24KICAgICAgICB0aGUgaW5zdGFuY2UuIFRoaXMgaXMgdXNlZnVsIGZvciB0ZXN0aW5nIGVudmlyb25tZW50LCB3aGVyZSB5b3UKICAgICAgICBtaWdodCB3YW50IHRvIGFwcGVuZCB0aGUgcm9vdCB2aWV3IHRvIGEgZml4dHVyZSBhcmVhLgogICAgICAgICBJbiBub24tYnJvd3NlciBtb2RlLCBiZWNhdXNlIEVtYmVyIGRvZXMgbm90IGhhdmUgYWNjZXNzIHRvIGpRdWVyeSwKICAgICAgICB0aGlzIG9wdGlvbnMgbXVzdCBiZSBzcGVjaWZpZWQgYXMgYSBET00gYEVsZW1lbnRgIG9iamVjdCBpbnN0ZWFkIG9mCiAgICAgICAgYSBzZWxlY3RvciBzdHJpbmcuCiAgICAgICAgIFNlZSB0aGUgZG9jdW1lbnRhdGlvbiBvbiBgQXBwbGljYXRpb25gJ3MgYHJvb3RFbGVtZW50YCBmb3IKICAgICAgICBkZXRhaWxzLgogICAgICAgICBAcHJvcGVydHkgcm9vdEVsZW1lbnQKICAgICAgICBAdHlwZSBTdHJpbmd8RWxlbWVudAogICAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgICBAcHVibGljCiAgICAgICAqLwoKCiAgICAgIGlmIChvcHRpb25zLnJvb3RFbGVtZW50KSB7CiAgICAgICAgdGhpcy5yb290RWxlbWVudCA9IG9wdGlvbnMucm9vdEVsZW1lbnQ7CiAgICAgIH0gLy8gU2V0IHRoZXNlIG9wdGlvbnMgbGFzdCB0byBnaXZlIHRoZSB1c2VyIGEgY2hhbmNlIHRvIG92ZXJyaWRlIHRoZQogICAgICAvLyBkZWZhdWx0cyBmcm9tIHRoZSAiY29tYm8iIG9wdGlvbnMgbGlrZSBgaXNCcm93c2VyYCAoYWx0aG91Z2ggaW4KICAgICAgLy8gcHJhY3RpY2UsIHRoZSByZXN1bHRpbmcgY29tYmluYXRpb24gaXMgcHJvYmFibHkgaW52YWxpZCkKCiAgICAgIC8qKgogICAgICAgIElmIHByZXNlbnQsIG92ZXJyaWRlcyB0aGUgcm91dGVyJ3MgYGxvY2F0aW9uYCBwcm9wZXJ0eSB3aXRoIHRoaXMKICAgICAgICB2YWx1ZS4gVGhpcyBpcyB1c2VmdWwgZm9yIGVudmlyb25tZW50cyB3aGVyZSB0cnlpbmcgdG8gbW9kaWZ5IHRoZQogICAgICAgIFVSTCB3b3VsZCBiZSBpbmFwcHJvcHJpYXRlLgogICAgICAgICBAcHJvcGVydHkgbG9jYXRpb24KICAgICAgICBAdHlwZSBzdHJpbmcKICAgICAgICBAZGVmYXVsdCBudWxsCiAgICAgICAgQHB1YmxpYwogICAgICAqLwoKCiAgICAgIGlmIChvcHRpb25zLmxvY2F0aW9uICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLmxvY2F0aW9uID0gb3B0aW9ucy5sb2NhdGlvbjsKICAgICAgfQoKICAgICAgaWYgKG9wdGlvbnMualF1ZXJ5ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLmpRdWVyeSA9IG9wdGlvbnMualF1ZXJ5OwogICAgICB9CgogICAgICBpZiAob3B0aW9ucy5pc0ludGVyYWN0aXZlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLmlzSW50ZXJhY3RpdmUgPSBCb29sZWFuKG9wdGlvbnMuaXNJbnRlcmFjdGl2ZSk7CiAgICAgIH0KICAgIH0KCiAgICB2YXIgX3Byb3RvID0gQm9vdE9wdGlvbnMucHJvdG90eXBlOwoKICAgIF9wcm90by50b0Vudmlyb25tZW50ID0gZnVuY3Rpb24gdG9FbnZpcm9ubWVudCgpIHsKICAgICAgLy8gRG8gd2UgcmVhbGx5IHdhbnQgdG8gYXNzaWduIGFsbCBvZiB0aGlzIT8KICAgICAgdmFyIGVudiA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIGVudmlyb25tZW50KTsgLy8gRm9yIGNvbXBhdGliaWxpdHkgd2l0aCBleGlzdGluZyBjb2RlCgogICAgICBlbnYuaGFzRE9NID0gdGhpcy5pc0Jyb3dzZXI7CiAgICAgIGVudi5pc0ludGVyYWN0aXZlID0gdGhpcy5pc0ludGVyYWN0aXZlOwogICAgICBlbnYuX3JlbmRlck1vZGUgPSB0aGlzLl9yZW5kZXJNb2RlOwogICAgICBlbnYub3B0aW9ucyA9IHRoaXM7CiAgICAgIHJldHVybiBlbnY7CiAgICB9OwoKICAgIHJldHVybiBCb290T3B0aW9uczsKICB9KCk7CgogIHZhciBfZGVmYXVsdCA9IEFwcGxpY2F0aW9uSW5zdGFuY2U7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvYXBwbGljYXRpb24vbGliL2FwcGxpY2F0aW9uIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIiwgIkBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL2Jyb3dzZXItZW52aXJvbm1lbnQiLCAiQGVtYmVyL2RlYnVnIiwgIkBlbWJlci9ydW5sb29wIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci9hcHBsaWNhdGlvbi9saWIvbGF6eV9sb2FkIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdmlld3MiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcm91dGluZyIsICJAZW1iZXIvYXBwbGljYXRpb24vaW5zdGFuY2UiLCAiQGVtYmVyL2VuZ2luZSIsICJAZW1iZXIvLWludGVybmFscy9jb250YWluZXIiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZ2xpbW1lciIsICJAZW1iZXIvZGVwcmVjYXRlZC1mZWF0dXJlcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfdXRpbHMsIF9lbnZpcm9ubWVudCwgX2Jyb3dzZXJFbnZpcm9ubWVudCwgX2RlYnVnLCBfcnVubG9vcCwgX21ldGFsLCBfbGF6eV9sb2FkLCBfcnVudGltZSwgX3ZpZXdzLCBfcm91dGluZywgX2luc3RhbmNlLCBfZW5naW5lLCBfY29udGFpbmVyLCBfZ2xpbW1lciwgX2RlcHJlY2F0ZWRGZWF0dXJlcykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0KCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsiLWJ1Y2tldC1jYWNoZTptYWluIl0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdCgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgdmFyIGxpYnJhcmllc1JlZ2lzdGVyZWQgPSBmYWxzZTsKICAvKioKICAgIEFuIGluc3RhbmNlIG9mIGBBcHBsaWNhdGlvbmAgaXMgdGhlIHN0YXJ0aW5nIHBvaW50IGZvciBldmVyeSBFbWJlcgogICAgYXBwbGljYXRpb24uIEl0IGhlbHBzIHRvIGluc3RhbnRpYXRlLCBpbml0aWFsaXplIGFuZCBjb29yZGluYXRlIHRoZSBtYW55CiAgICBvYmplY3RzIHRoYXQgbWFrZSB1cCB5b3VyIGFwcC4KICAKICAgIEVhY2ggRW1iZXIgYXBwIGhhcyBvbmUgYW5kIG9ubHkgb25lIGBBcHBsaWNhdGlvbmAgb2JqZWN0LiBJbiBmYWN0LCB0aGUKICAgIHZlcnkgZmlyc3QgdGhpbmcgeW91IHNob3VsZCBkbyBpbiB5b3VyIGFwcGxpY2F0aW9uIGlzIGNyZWF0ZSB0aGUgaW5zdGFuY2U6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAKICAgIHdpbmRvdy5BcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoKTsKICAgIGBgYAogIAogICAgVHlwaWNhbGx5LCB0aGUgYXBwbGljYXRpb24gb2JqZWN0IGlzIHRoZSBvbmx5IGdsb2JhbCB2YXJpYWJsZS4gQWxsIG90aGVyCiAgICBjbGFzc2VzIGluIHlvdXIgYXBwIHNob3VsZCBiZSBwcm9wZXJ0aWVzIG9uIHRoZSBgQXBwbGljYXRpb25gIGluc3RhbmNlLAogICAgd2hpY2ggaGlnaGxpZ2h0cyBpdHMgZmlyc3Qgcm9sZTogYSBnbG9iYWwgbmFtZXNwYWNlLgogIAogICAgRm9yIGV4YW1wbGUsIGlmIHlvdSBkZWZpbmUgYSB2aWV3IGNsYXNzLCBpdCBtaWdodCBsb29rIGxpa2UgdGhpczoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogIAogICAgQXBwLk15VmlldyA9IEVtYmVyLlZpZXcuZXh0ZW5kKCk7CiAgICBgYGAKICAKICAgIEJ5IGRlZmF1bHQsIGNhbGxpbmcgYEFwcGxpY2F0aW9uLmNyZWF0ZSgpYCB3aWxsIGF1dG9tYXRpY2FsbHkgaW5pdGlhbGl6ZQogICAgeW91ciBhcHBsaWNhdGlvbiBieSBjYWxsaW5nIHRoZSBgQXBwbGljYXRpb24uaW5pdGlhbGl6ZSgpYCBtZXRob2QuIElmCiAgICB5b3UgbmVlZCB0byBkZWxheSBpbml0aWFsaXphdGlvbiwgeW91IGNhbiBjYWxsIHlvdXIgYXBwJ3MgYGRlZmVyUmVhZGluZXNzKClgCiAgICBtZXRob2QuIFdoZW4geW91IGFyZSByZWFkeSBmb3IgeW91ciBhcHAgdG8gYmUgaW5pdGlhbGl6ZWQsIGNhbGwgaXRzCiAgICBgYWR2YW5jZVJlYWRpbmVzcygpYCBtZXRob2QuCiAgCiAgICBZb3UgY2FuIGRlZmluZSBhIGByZWFkeWAgbWV0aG9kIG9uIHRoZSBgQXBwbGljYXRpb25gIGluc3RhbmNlLCB3aGljaAogICAgd2lsbCBiZSBydW4gYnkgRW1iZXIgd2hlbiB0aGUgYXBwbGljYXRpb24gaXMgaW5pdGlhbGl6ZWQuCiAgCiAgICBCZWNhdXNlIGBBcHBsaWNhdGlvbmAgaW5oZXJpdHMgZnJvbSBgRW1iZXIuTmFtZXNwYWNlYCwgYW55IGNsYXNzZXMKICAgIHlvdSBjcmVhdGUgd2lsbCBoYXZlIHVzZWZ1bCBzdHJpbmcgcmVwcmVzZW50YXRpb25zIHdoZW4gY2FsbGluZyBgdG9TdHJpbmcoKWAuCiAgICBTZWUgdGhlIGBFbWJlci5OYW1lc3BhY2VgIGRvY3VtZW50YXRpb24gZm9yIG1vcmUgaW5mb3JtYXRpb24uCiAgCiAgICBXaGlsZSB5b3UgY2FuIHRoaW5rIG9mIHlvdXIgYEFwcGxpY2F0aW9uYCBhcyBhIGNvbnRhaW5lciB0aGF0IGhvbGRzIHRoZQogICAgb3RoZXIgY2xhc3NlcyBpbiB5b3VyIGFwcGxpY2F0aW9uLCB0aGVyZSBhcmUgc2V2ZXJhbCBvdGhlciByZXNwb25zaWJpbGl0aWVzCiAgICBnb2luZyBvbiB1bmRlci10aGUtaG9vZCB0aGF0IHlvdSBtYXkgd2FudCB0byB1bmRlcnN0YW5kLgogIAogICAgIyMjIEV2ZW50IERlbGVnYXRpb24KICAKICAgIEVtYmVyIHVzZXMgYSB0ZWNobmlxdWUgY2FsbGVkIF9ldmVudCBkZWxlZ2F0aW9uXy4gVGhpcyBhbGxvd3MgdGhlIGZyYW1ld29yawogICAgdG8gc2V0IHVwIGEgZ2xvYmFsLCBzaGFyZWQgZXZlbnQgbGlzdGVuZXIgaW5zdGVhZCBvZiByZXF1aXJpbmcgZWFjaCB2aWV3IHRvCiAgICBkbyBpdCBtYW51YWxseS4gRm9yIGV4YW1wbGUsIGluc3RlYWQgb2YgZWFjaCB2aWV3IHJlZ2lzdGVyaW5nIGl0cyBvd24KICAgIGBtb3VzZWRvd25gIGxpc3RlbmVyIG9uIGl0cyBhc3NvY2lhdGVkIGVsZW1lbnQsIEVtYmVyIHNldHMgdXAgYSBgbW91c2Vkb3duYAogICAgbGlzdGVuZXIgb24gdGhlIGBib2R5YC4KICAKICAgIElmIGEgYG1vdXNlZG93bmAgZXZlbnQgb2NjdXJzLCBFbWJlciB3aWxsIGxvb2sgYXQgdGhlIHRhcmdldCBvZiB0aGUgZXZlbnQgYW5kCiAgICBzdGFydCB3YWxraW5nIHVwIHRoZSBET00gbm9kZSB0cmVlLCBmaW5kaW5nIGNvcnJlc3BvbmRpbmcgdmlld3MgYW5kIGludm9raW5nCiAgICB0aGVpciBgbW91c2VEb3duYCBtZXRob2QgYXMgaXQgZ29lcy4KICAKICAgIGBBcHBsaWNhdGlvbmAgaGFzIGEgbnVtYmVyIG9mIGRlZmF1bHQgZXZlbnRzIHRoYXQgaXQgbGlzdGVucyBmb3IsIGFzCiAgICB3ZWxsIGFzIGEgbWFwcGluZyBmcm9tIGxvd2VyY2FzZSBldmVudHMgdG8gY2FtZWwtY2FzZWQgdmlldyBtZXRob2QgbmFtZXMuIEZvcgogICAgZXhhbXBsZSwgdGhlIGBrZXlwcmVzc2AgZXZlbnQgY2F1c2VzIHRoZSBga2V5UHJlc3NgIG1ldGhvZCBvbiB0aGUgdmlldyB0byBiZQogICAgY2FsbGVkLCB0aGUgYGRibGNsaWNrYCBldmVudCBjYXVzZXMgYGRvdWJsZUNsaWNrYCB0byBiZSBjYWxsZWQsIGFuZCBzbyBvbi4KICAKICAgIElmIHRoZXJlIGlzIGEgYnViYmxpbmcgYnJvd3NlciBldmVudCB0aGF0IEVtYmVyIGRvZXMgbm90IGxpc3RlbiBmb3IgYnkKICAgIGRlZmF1bHQsIHlvdSBjYW4gc3BlY2lmeSBjdXN0b20gZXZlbnRzIGFuZCB0aGVpciBjb3JyZXNwb25kaW5nIHZpZXcgbWV0aG9kCiAgICBuYW1lcyBieSBzZXR0aW5nIHRoZSBhcHBsaWNhdGlvbidzIGBjdXN0b21FdmVudHNgIHByb3BlcnR5OgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgCiAgICBsZXQgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKHsKICAgICAgY3VzdG9tRXZlbnRzOiB7CiAgICAgICAgLy8gYWRkIHN1cHBvcnQgZm9yIHRoZSBwYXN0ZSBldmVudAogICAgICAgIHBhc3RlOiAncGFzdGUnCiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBUbyBwcmV2ZW50IEVtYmVyIGZyb20gc2V0dGluZyB1cCBhIGxpc3RlbmVyIGZvciBhIGRlZmF1bHQgZXZlbnQsCiAgICBzcGVjaWZ5IHRoZSBldmVudCBuYW1lIHdpdGggYSBgbnVsbGAgdmFsdWUgaW4gdGhlIGBjdXN0b21FdmVudHNgCiAgICBwcm9wZXJ0eToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogIAogICAgbGV0IEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSh7CiAgICAgIGN1c3RvbUV2ZW50czogewogICAgICAgIC8vIHByZXZlbnQgbGlzdGVuZXJzIGZvciBtb3VzZWVudGVyL21vdXNlbGVhdmUgZXZlbnRzCiAgICAgICAgbW91c2VlbnRlcjogbnVsbCwKICAgICAgICBtb3VzZWxlYXZlOiBudWxsCiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBCeSBkZWZhdWx0LCB0aGUgYXBwbGljYXRpb24gc2V0cyB1cCB0aGVzZSBldmVudCBsaXN0ZW5lcnMgb24gdGhlIGRvY3VtZW50CiAgICBib2R5LiBIb3dldmVyLCBpbiBjYXNlcyB3aGVyZSB5b3UgYXJlIGVtYmVkZGluZyBhbiBFbWJlciBhcHBsaWNhdGlvbiBpbnNpZGUKICAgIGFuIGV4aXN0aW5nIHBhZ2UsIHlvdSBtYXkgd2FudCBpdCB0byBzZXQgdXAgdGhlIGxpc3RlbmVycyBvbiBhbiBlbGVtZW50CiAgICBpbnNpZGUgdGhlIGJvZHkuCiAgCiAgICBGb3IgZXhhbXBsZSwgaWYgb25seSBldmVudHMgaW5zaWRlIGEgRE9NIGVsZW1lbnQgd2l0aCB0aGUgSUQgb2YgYGVtYmVyLWFwcGAKICAgIHNob3VsZCBiZSBkZWxlZ2F0ZWQsIHNldCB5b3VyIGFwcGxpY2F0aW9uJ3MgYHJvb3RFbGVtZW50YCBwcm9wZXJ0eToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogIAogICAgbGV0IEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSh7CiAgICAgIHJvb3RFbGVtZW50OiAnI2VtYmVyLWFwcCcKICAgIH0pOwogICAgYGBgCiAgCiAgICBUaGUgYHJvb3RFbGVtZW50YCBjYW4gYmUgZWl0aGVyIGEgRE9NIGVsZW1lbnQgb3IgYSBqUXVlcnktY29tcGF0aWJsZSBzZWxlY3RvcgogICAgc3RyaW5nLiBOb3RlIHRoYXQgKnZpZXdzIGFwcGVuZGVkIHRvIHRoZSBET00gb3V0c2lkZSB0aGUgcm9vdCBlbGVtZW50IHdpbGwKICAgIG5vdCByZWNlaXZlIGV2ZW50cy4qIElmIHlvdSBzcGVjaWZ5IGEgY3VzdG9tIHJvb3QgZWxlbWVudCwgbWFrZSBzdXJlIHlvdSBvbmx5CiAgICBhcHBlbmQgdmlld3MgaW5zaWRlIGl0IQogIAogICAgVG8gbGVhcm4gbW9yZSBhYm91dCB0aGUgZXZlbnRzIEVtYmVyIGNvbXBvbmVudHMgdXNlLCBzZWUKICAKICAgIFtjb21wb25lbnRzL2hhbmRsaW5nLWV2ZW50c10oaHR0cHM6Ly9ndWlkZXMuZW1iZXJqcy5jb20vcmVsZWFzZS9jb21wb25lbnRzL2hhbmRsaW5nLWV2ZW50cy8jdG9jX2V2ZW50LW5hbWVzKS4KICAKICAgICMjIyBJbml0aWFsaXplcnMKICAKICAgIExpYnJhcmllcyBvbiB0b3Agb2YgRW1iZXIgY2FuIGFkZCBpbml0aWFsaXplcnMsIGxpa2Ugc286CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAKICAgIEFwcGxpY2F0aW9uLmluaXRpYWxpemVyKHsKICAgICAgbmFtZTogJ2FwaS1hZGFwdGVyJywKICAKICAgICAgaW5pdGlhbGl6ZTogZnVuY3Rpb24oYXBwbGljYXRpb24pIHsKICAgICAgICBhcHBsaWNhdGlvbi5yZWdpc3RlcignYXBpLWFkYXB0ZXI6bWFpbicsIEFwaUFkYXB0ZXIpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgSW5pdGlhbGl6ZXJzIHByb3ZpZGUgYW4gb3Bwb3J0dW5pdHkgdG8gYWNjZXNzIHRoZSBpbnRlcm5hbCByZWdpc3RyeSwgd2hpY2gKICAgIG9yZ2FuaXplcyB0aGUgZGlmZmVyZW50IGNvbXBvbmVudHMgb2YgYW4gRW1iZXIgYXBwbGljYXRpb24uIEFkZGl0aW9uYWxseQogICAgdGhleSBwcm92aWRlIGEgY2hhbmNlIHRvIGFjY2VzcyB0aGUgaW5zdGFudGlhdGVkIGFwcGxpY2F0aW9uLiBCZXlvbmQKICAgIGJlaW5nIHVzZWQgZm9yIGxpYnJhcmllcywgaW5pdGlhbGl6ZXJzIGFyZSBhbHNvIGEgZ3JlYXQgd2F5IHRvIG9yZ2FuaXplCiAgICBkZXBlbmRlbmN5IGluamVjdGlvbiBvciBzZXR1cCBpbiB5b3VyIG93biBhcHBsaWNhdGlvbi4KICAKICAgICMjIyBSb3V0aW5nCiAgCiAgICBJbiBhZGRpdGlvbiB0byBjcmVhdGluZyB5b3VyIGFwcGxpY2F0aW9uJ3Mgcm91dGVyLCBgQXBwbGljYXRpb25gIGlzCiAgICBhbHNvIHJlc3BvbnNpYmxlIGZvciB0ZWxsaW5nIHRoZSByb3V0ZXIgd2hlbiB0byBzdGFydCByb3V0aW5nLiBUcmFuc2l0aW9ucwogICAgYmV0d2VlbiByb3V0ZXMgY2FuIGJlIGxvZ2dlZCB3aXRoIHRoZSBgTE9HX1RSQU5TSVRJT05TYCBmbGFnLCBhbmQgbW9yZQogICAgZGV0YWlsZWQgaW50cmEtdHJhbnNpdGlvbiBsb2dnaW5nIGNhbiBiZSBsb2dnZWQgd2l0aAogICAgdGhlIGBMT0dfVFJBTlNJVElPTlNfSU5URVJOQUxgIGZsYWc6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAKICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoewogICAgICBMT0dfVFJBTlNJVElPTlM6IHRydWUsIC8vIGJhc2ljIGxvZ2dpbmcgb2Ygc3VjY2Vzc2Z1bCB0cmFuc2l0aW9ucwogICAgICBMT0dfVFJBTlNJVElPTlNfSU5URVJOQUw6IHRydWUgLy8gZGV0YWlsZWQgbG9nZ2luZyBvZiBhbGwgcm91dGluZyBzdGVwcwogICAgfSk7CiAgICBgYGAKICAKICAgIEJ5IGRlZmF1bHQsIHRoZSByb3V0ZXIgd2lsbCBiZWdpbiB0cnlpbmcgdG8gdHJhbnNsYXRlIHRoZSBjdXJyZW50IFVSTCBpbnRvCiAgICBhcHBsaWNhdGlvbiBzdGF0ZSBvbmNlIHRoZSBicm93c2VyIGVtaXRzIHRoZSBgRE9NQ29udGVudFJlYWR5YCBldmVudC4gSWYgeW91CiAgICBuZWVkIHRvIGRlZmVyIHJvdXRpbmcsIHlvdSBjYW4gY2FsbCB0aGUgYXBwbGljYXRpb24ncyBgZGVmZXJSZWFkaW5lc3MoKWAKICAgIG1ldGhvZC4gT25jZSByb3V0aW5nIGNhbiBiZWdpbiwgY2FsbCB0aGUgYGFkdmFuY2VSZWFkaW5lc3MoKWAgbWV0aG9kLgogIAogICAgSWYgdGhlcmUgaXMgYW55IHNldHVwIHJlcXVpcmVkIGJlZm9yZSByb3V0aW5nIGJlZ2lucywgeW91IGNhbiBpbXBsZW1lbnQgYQogICAgYHJlYWR5KClgIG1ldGhvZCBvbiB5b3VyIGFwcCB0aGF0IHdpbGwgYmUgaW52b2tlZCBpbW1lZGlhdGVseSBiZWZvcmUgcm91dGluZwogICAgYmVnaW5zLgogIAogICAgQGNsYXNzIEFwcGxpY2F0aW9uCiAgICBAZXh0ZW5kcyBFbmdpbmUKICAgIEB1c2VzIFJlZ2lzdHJ5UHJveHlNaXhpbgogICAgQHB1YmxpYwogICovCgogIHZhciBBcHBsaWNhdGlvbiA9IF9lbmdpbmUuZGVmYXVsdC5leHRlbmQoewogICAgLyoqCiAgICAgIFRoZSByb290IERPTSBlbGVtZW50IG9mIHRoZSBBcHBsaWNhdGlvbi4gVGhpcyBjYW4gYmUgc3BlY2lmaWVkIGFzIGFuCiAgICAgIGVsZW1lbnQgb3IgYQogICAgICBbalF1ZXJ5LWNvbXBhdGlibGUgc2VsZWN0b3Igc3RyaW5nXShodHRwOi8vYXBpLmpxdWVyeS5jb20vY2F0ZWdvcnkvc2VsZWN0b3JzLykuCiAgICAgICBUaGlzIGlzIHRoZSBlbGVtZW50IHRoYXQgd2lsbCBiZSBwYXNzZWQgdG8gdGhlIEFwcGxpY2F0aW9uJ3MsCiAgICAgIGBldmVudERpc3BhdGNoZXJgLCB3aGljaCBzZXRzIHVwIHRoZSBsaXN0ZW5lcnMgZm9yIGV2ZW50IGRlbGVnYXRpb24uIEV2ZXJ5CiAgICAgIHZpZXcgaW4geW91ciBhcHBsaWNhdGlvbiBzaG91bGQgYmUgYSBjaGlsZCBvZiB0aGUgZWxlbWVudCB5b3Ugc3BlY2lmeSBoZXJlLgogICAgICAgQHByb3BlcnR5IHJvb3RFbGVtZW50CiAgICAgIEB0eXBlIERPTUVsZW1lbnQKICAgICAgQGRlZmF1bHQgJ2JvZHknCiAgICAgIEBwdWJsaWMKICAgICovCiAgICByb290RWxlbWVudDogJ2JvZHknLAoKICAgIC8qKgogICAgICBUaGUgYEVtYmVyLkV2ZW50RGlzcGF0Y2hlcmAgcmVzcG9uc2libGUgZm9yIGRlbGVnYXRpbmcgZXZlbnRzIHRvIHRoaXMKICAgICAgYXBwbGljYXRpb24ncyB2aWV3cy4KICAgICAgIFRoZSBldmVudCBkaXNwYXRjaGVyIGlzIGNyZWF0ZWQgYnkgdGhlIGFwcGxpY2F0aW9uIGF0IGluaXRpYWxpemF0aW9uIHRpbWUKICAgICAgYW5kIHNldHMgdXAgZXZlbnQgbGlzdGVuZXJzIG9uIHRoZSBET00gZWxlbWVudCBkZXNjcmliZWQgYnkgdGhlCiAgICAgIGFwcGxpY2F0aW9uJ3MgYHJvb3RFbGVtZW50YCBwcm9wZXJ0eS4KICAgICAgIFNlZSB0aGUgZG9jdW1lbnRhdGlvbiBmb3IgYEVtYmVyLkV2ZW50RGlzcGF0Y2hlcmAgZm9yIG1vcmUgaW5mb3JtYXRpb24uCiAgICAgICBAcHJvcGVydHkgZXZlbnREaXNwYXRjaGVyCiAgICAgIEB0eXBlIEVtYmVyLkV2ZW50RGlzcGF0Y2hlcgogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBwdWJsaWMKICAgICovCiAgICBldmVudERpc3BhdGNoZXI6IG51bGwsCgogICAgLyoqCiAgICAgIFRoZSBET00gZXZlbnRzIGZvciB3aGljaCB0aGUgZXZlbnQgZGlzcGF0Y2hlciBzaG91bGQgbGlzdGVuLgogICAgICAgQnkgZGVmYXVsdCwgdGhlIGFwcGxpY2F0aW9uJ3MgYEVtYmVyLkV2ZW50RGlzcGF0Y2hlcmAgbGlzdGVucwogICAgICBmb3IgYSBzZXQgb2Ygc3RhbmRhcmQgRE9NIGV2ZW50cywgc3VjaCBhcyBgbW91c2Vkb3duYCBhbmQKICAgICAgYGtleXVwYCwgYW5kIGRlbGVnYXRlcyB0aGVtIHRvIHlvdXIgYXBwbGljYXRpb24ncyBgRW1iZXIuVmlld2AKICAgICAgaW5zdGFuY2VzLgogICAgICAgSWYgeW91IHdvdWxkIGxpa2UgYWRkaXRpb25hbCBidWJibGluZyBldmVudHMgdG8gYmUgZGVsZWdhdGVkIHRvIHlvdXIKICAgICAgdmlld3MsIHNldCB5b3VyIGBBcHBsaWNhdGlvbmAncyBgY3VzdG9tRXZlbnRzYCBwcm9wZXJ0eQogICAgICB0byBhIGhhc2ggY29udGFpbmluZyB0aGUgRE9NIGV2ZW50IG5hbWUgYXMgdGhlIGtleSBhbmQgdGhlCiAgICAgIGNvcnJlc3BvbmRpbmcgdmlldyBtZXRob2QgbmFtZSBhcyB0aGUgdmFsdWUuIFNldHRpbmcgYW4gZXZlbnQgdG8KICAgICAgYSB2YWx1ZSBvZiBgbnVsbGAgd2lsbCBwcmV2ZW50IGEgZGVmYXVsdCBldmVudCBsaXN0ZW5lciBmcm9tIGJlaW5nCiAgICAgIGFkZGVkIGZvciB0aGF0IGV2ZW50LgogICAgICAgVG8gYWRkIG5ldyBldmVudHMgdG8gYmUgbGlzdGVuZWQgdG86CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICAgbGV0IEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSh7CiAgICAgICAgY3VzdG9tRXZlbnRzOiB7CiAgICAgICAgICAvLyBhZGQgc3VwcG9ydCBmb3IgdGhlIHBhc3RlIGV2ZW50CiAgICAgICAgICBwYXN0ZTogJ3Bhc3RlJwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVG8gcHJldmVudCBkZWZhdWx0IGV2ZW50cyBmcm9tIGJlaW5nIGxpc3RlbmVkIHRvOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgQXBwbGljYXRpb24gZnJvbSAnQGVtYmVyL2FwcGxpY2F0aW9uJzsKICAgICAgIGxldCBBcHAgPSBBcHBsaWNhdGlvbi5jcmVhdGUoewogICAgICAgIGN1c3RvbUV2ZW50czogewogICAgICAgICAgLy8gcmVtb3ZlIHN1cHBvcnQgZm9yIG1vdXNlZW50ZXIgLyBtb3VzZWxlYXZlIGV2ZW50cwogICAgICAgICAgbW91c2VlbnRlcjogbnVsbCwKICAgICAgICAgIG1vdXNlbGVhdmU6IG51bGwKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgQHByb3BlcnR5IGN1c3RvbUV2ZW50cwogICAgICBAdHlwZSBPYmplY3QKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHVibGljCiAgICAqLwogICAgY3VzdG9tRXZlbnRzOiBudWxsLAoKICAgIC8qKgogICAgICBXaGV0aGVyIHRoZSBhcHBsaWNhdGlvbiBzaG91bGQgYXV0b21hdGljYWxseSBzdGFydCByb3V0aW5nIGFuZCByZW5kZXIKICAgICAgdGVtcGxhdGVzIHRvIHRoZSBgcm9vdEVsZW1lbnRgIG9uIERPTSByZWFkeS4gV2hpbGUgZGVmYXVsdCBieSB0cnVlLAogICAgICBvdGhlciBlbnZpcm9ubWVudHMgc3VjaCBhcyBGYXN0Qm9vdCBvciBhIHRlc3RpbmcgaGFybmVzcyBjYW4gc2V0IHRoaXMKICAgICAgcHJvcGVydHkgdG8gYGZhbHNlYCBhbmQgY29udHJvbCB0aGUgcHJlY2lzZSB0aW1pbmcgYW5kIGJlaGF2aW9yIG9mIHRoZSBib290CiAgICAgIHByb2Nlc3MuCiAgICAgICBAcHJvcGVydHkgYXV0b2Jvb3QKICAgICAgQHR5cGUgQm9vbGVhbgogICAgICBAZGVmYXVsdCB0cnVlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgYXV0b2Jvb3Q6IHRydWUsCgogICAgLyoqCiAgICAgIFdoZXRoZXIgdGhlIGFwcGxpY2F0aW9uIHNob3VsZCBiZSBjb25maWd1cmVkIGZvciB0aGUgbGVnYWN5ICJnbG9iYWxzIG1vZGUiLgogICAgICBVbmRlciB0aGlzIG1vZGUsIHRoZSBBcHBsaWNhdGlvbiBvYmplY3Qgc2VydmVzIGFzIGEgZ2xvYmFsIG5hbWVzcGFjZSBmb3IgYWxsCiAgICAgIGNsYXNzZXMuCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgICAgbGV0IEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSh7CiAgICAgICAgLi4uCiAgICAgIH0pOwogICAgICAgQXBwLlJvdXRlci5yZW9wZW4oewogICAgICAgIGxvY2F0aW9uOiAnbm9uZScKICAgICAgfSk7CiAgICAgICBBcHAuUm91dGVyLm1hcCh7CiAgICAgICAgLi4uCiAgICAgIH0pOwogICAgICAgQXBwLk15Q29tcG9uZW50ID0gQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgICAgLi4uCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRoaXMgZmxhZyBhbHNvIGV4cG9zZXMgb3RoZXIgaW50ZXJuYWwgQVBJcyB0aGF0IGFzc3VtZXMgdGhlIGV4aXN0ZW5jZSBvZgogICAgICBhIHNwZWNpYWwgImRlZmF1bHQgaW5zdGFuY2UiLCBsaWtlIGBBcHAuX19jb250YWluZXJfXy5sb29rdXAoLi4uKWAuCiAgICAgICBUaGlzIG9wdGlvbiBpcyBjdXJyZW50bHkgbm90IGNvbmZpZ3VyYWJsZSwgaXRzIHZhbHVlIGlzIGRlcml2ZWQgZnJvbQogICAgICB0aGUgYGF1dG9ib290YCBmbGFnIOKAkyBkaXNhYmxpbmcgYGF1dG9ib290YCBhbHNvIGltcGxpZXMgb3B0aW5nLW91dCBvZgogICAgICBnbG9iYWxzIG1vZGUgc3VwcG9ydCwgYWx0aG91Z2ggdGhleSBhcmUgdWx0aW1hdGVseSBvcnRob2dvbmFsIGNvbmNlcm5zLgogICAgICAgU29tZSBvZiB0aGUgZ2xvYmFsIG1vZGVzIGZlYXR1cmVzIGFyZSBhbHJlYWR5IGRlcHJlY2F0ZWQgaW4gMS54LiBUaGUKICAgICAgZXhpc3RlbmNlIG9mIHRoaXMgZmxhZyBpcyB0byB1bnRhbmdsZSB0aGUgZ2xvYmFscyBtb2RlIGNvZGUgcGF0aHMgZnJvbQogICAgICB0aGUgYXV0b2Jvb3QgY29kZSBwYXRocywgc28gdGhhdCB0aGVzZSBsZWdhY3kgZmVhdHVyZXMgY2FuIGJlIHJldmlld2VkCiAgICAgIGZvciBkZXByZWNhdGlvbi9yZW1vdmFsIHNlcGFyYXRlbHkuCiAgICAgICBGb3JjaW5nIHRoZSAoYXV0b2Jvb3Q9dHJ1ZSwgX2dsb2JhbHNNb2RlPWZhbHNlKSBoZXJlIGFuZCBydW5uaW5nIHRoZSB0ZXN0cwogICAgICB3b3VsZCByZXZlYWwgYWxsIHRoZSBwbGFjZXMgd2hlcmUgd2UgYXJlIHN0aWxsIHJlbHlpbmcgb24gdGhlc2UgbGVnYWN5CiAgICAgIGJlaGF2aW9yIGludGVybmFsbHkgKG1vc3RseSBqdXN0IHRlc3RzKS4KICAgICAgIEBwcm9wZXJ0eSBfZ2xvYmFsc01vZGUKICAgICAgQHR5cGUgQm9vbGVhbgogICAgICBAZGVmYXVsdCB0cnVlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX2dsb2JhbHNNb2RlOiB0cnVlLAoKICAgIC8qKgogICAgICBBbiBhcnJheSBvZiBhcHBsaWNhdGlvbiBpbnN0YW5jZXMgY3JlYXRlZCBieSBgYnVpbGRJbnN0YW5jZSgpYC4gVXNlZAogICAgICBpbnRlcm5hbGx5IHRvIGVuc3VyZSB0aGF0IGFsbCBpbnN0YW5jZXMgZ2V0IGRlc3Ryb3llZC4KICAgICAgIEBwcm9wZXJ0eSBfYXBwbGljYXRpb25JbnN0YW5jZXMKICAgICAgQHR5cGUgQXJyYXkKICAgICAgQGRlZmF1bHQgbnVsbAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9hcHBsaWNhdGlvbkluc3RhbmNlczogbnVsbCwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnMKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIGlmICghdGhpcy4kKSB7CiAgICAgICAgdGhpcy4kID0gX3ZpZXdzLmpRdWVyeTsKICAgICAgfQoKICAgICAgcmVnaXN0ZXJMaWJyYXJpZXMoKTsKCiAgICAgIGlmIChmYWxzZQogICAgICAvKiBERUJVRyAqLwogICAgICApIHsKICAgICAgICBpZiAoX2Vudmlyb25tZW50LkVOVi5MT0dfVkVSU0lPTikgewogICAgICAgICAgLy8gd2Ugb25seSBuZWVkIHRvIHNlZSB0aGlzIG9uY2UgcGVyIEFwcGxpY2F0aW9uI2luaXQKICAgICAgICAgIF9lbnZpcm9ubWVudC5FTlYuTE9HX1ZFUlNJT04gPSBmYWxzZTsKCiAgICAgICAgICBfbWV0YWwubGlicmFyaWVzLmxvZ1ZlcnNpb25zKCk7CiAgICAgICAgfQogICAgICB9IC8vIFN0YXJ0IG9mZiB0aGUgbnVtYmVyIG9mIGRlZmVycmFscyBhdCAxLiBUaGlzIHdpbGwgYmUgZGVjcmVtZW50ZWQgYnkKICAgICAgLy8gdGhlIEFwcGxpY2F0aW9uJ3Mgb3duIGBib290YCBtZXRob2QuCgoKICAgICAgdGhpcy5fcmVhZGluZXNzRGVmZXJyYWxzID0gMTsKICAgICAgdGhpcy5fYm9vdGVkID0gZmFsc2U7CiAgICAgIHRoaXMuX2FwcGxpY2F0aW9uSW5zdGFuY2VzID0gbmV3IFNldCgpOwogICAgICB0aGlzLmF1dG9ib290ID0gdGhpcy5fZ2xvYmFsc01vZGUgPSBCb29sZWFuKHRoaXMuYXV0b2Jvb3QpOwoKICAgICAgaWYgKHRoaXMuX2dsb2JhbHNNb2RlKSB7CiAgICAgICAgdGhpcy5fcHJlcGFyZUZvckdsb2JhbHNNb2RlKCk7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmF1dG9ib290KSB7CiAgICAgICAgdGhpcy53YWl0Rm9yRE9NUmVhZHkoKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgQ3JlYXRlIGFuIEFwcGxpY2F0aW9uSW5zdGFuY2UgZm9yIHRoaXMgYXBwbGljYXRpb24uCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgYnVpbGRJbnN0YW5jZQogICAgICBAcmV0dXJuIHtBcHBsaWNhdGlvbkluc3RhbmNlfSB0aGUgYXBwbGljYXRpb24gaW5zdGFuY2UKICAgICovCiAgICBidWlsZEluc3RhbmNlOiBmdW5jdGlvbiBidWlsZEluc3RhbmNlKG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgfQoKICAgICAgb3B0aW9ucy5iYXNlID0gdGhpczsKICAgICAgb3B0aW9ucy5hcHBsaWNhdGlvbiA9IHRoaXM7CiAgICAgIHJldHVybiBfaW5zdGFuY2UuZGVmYXVsdC5jcmVhdGUob3B0aW9ucyk7CiAgICB9LAoKICAgIC8qKgogICAgICBTdGFydCB0cmFja2luZyBhbiBBcHBsaWNhdGlvbkluc3RhbmNlIGZvciB0aGlzIGFwcGxpY2F0aW9uLgogICAgICBVc2VkIHdoZW4gdGhlIEFwcGxpY2F0aW9uSW5zdGFuY2UgaXMgY3JlYXRlZC4KICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX3dhdGNoSW5zdGFuY2UKICAgICovCiAgICBfd2F0Y2hJbnN0YW5jZTogZnVuY3Rpb24gX3dhdGNoSW5zdGFuY2UoaW5zdGFuY2UpIHsKICAgICAgdGhpcy5fYXBwbGljYXRpb25JbnN0YW5jZXMuYWRkKGluc3RhbmNlKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFN0b3AgdHJhY2tpbmcgYW4gQXBwbGljYXRpb25JbnN0YW5jZSBmb3IgdGhpcyBhcHBsaWNhdGlvbi4KICAgICAgVXNlZCB3aGVuIHRoZSBBcHBsaWNhdGlvbkluc3RhbmNlIGlzIGFib3V0IHRvIGJlIGRlc3Ryb3llZC4KICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgX3Vud2F0Y2hJbnN0YW5jZQogICAgKi8KICAgIF91bndhdGNoSW5zdGFuY2U6IGZ1bmN0aW9uIF91bndhdGNoSW5zdGFuY2UoaW5zdGFuY2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2FwcGxpY2F0aW9uSW5zdGFuY2VzLmRlbGV0ZShpbnN0YW5jZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBFbmFibGUgdGhlIGxlZ2FjeSBnbG9iYWxzIG1vZGUgYnkgYWxsb3dpbmcgdGhpcyBhcHBsaWNhdGlvbiB0byBhY3QKICAgICAgYXMgYSBnbG9iYWwgbmFtZXNwYWNlLiBTZWUgdGhlIGRvY3Mgb24gdGhlIGBfZ2xvYmFsc01vZGVgIHByb3BlcnR5CiAgICAgIGZvciBkZXRhaWxzLgogICAgICAgTW9zdCBvZiB0aGVzZSBmZWF0dXJlcyBhcmUgYWxyZWFkeSBkZXByZWNhdGVkIGluIDEueCwgc28gd2UgY2FuCiAgICAgIHN0b3AgdXNpbmcgdGhlbSBpbnRlcm5hbGx5IGFuZCB0cnkgdG8gcmVtb3ZlIHRoZW0uCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9wcmVwYXJlRm9yR2xvYmFsc01vZGUKICAgICovCiAgICBfcHJlcGFyZUZvckdsb2JhbHNNb2RlOiBmdW5jdGlvbiBfcHJlcGFyZUZvckdsb2JhbHNNb2RlKCkgewogICAgICAvLyBDcmVhdGUgc3ViY2xhc3Mgb2YgUm91dGVyIGZvciB0aGlzIEFwcGxpY2F0aW9uIGluc3RhbmNlLgogICAgICAvLyBUaGlzIGlzIHRvIGVuc3VyZSB0aGF0IHNvbWVvbmUgcmVvcGVuaW5nIGBBcHAuUm91dGVyYCBkb2VzIG5vdAogICAgICAvLyB0YW1wZXIgd2l0aCB0aGUgZGVmYXVsdCBgUm91dGVyYC4KICAgICAgdGhpcy5Sb3V0ZXIgPSAodGhpcy5Sb3V0ZXIgfHwgX3JvdXRpbmcuUm91dGVyKS5leHRlbmQoKTsKCiAgICAgIHRoaXMuX2J1aWxkRGVwcmVjYXRlZEluc3RhbmNlKCk7CiAgICB9LAoKICAgIC8qCiAgICAgIEJ1aWxkIHRoZSBkZXByZWNhdGVkIGluc3RhbmNlIGZvciBsZWdhY3kgZ2xvYmFscyBtb2RlIHN1cHBvcnQuCiAgICAgIENhbGxlZCB3aGVuIGNyZWF0aW5nIGFuZCByZXNldHRpbmcgdGhlIGFwcGxpY2F0aW9uLgogICAgICAgVGhpcyBpcyBvcnRob2dvbmFsIHRvIGF1dG9ib290OiB0aGUgZGVwcmVjYXRlZCBpbnN0YW5jZSBuZWVkcyB0bwogICAgICBiZSBjcmVhdGVkIGF0IEFwcGxpY2F0aW9uIGNvbnN0cnVjdGlvbiAobm90IGJvb3QpIHRpbWUgdG8gZXhwb3NlCiAgICAgIEFwcC5fX2NvbnRhaW5lcl9fLiBJZiBhdXRvYm9vdCBzZWVzIHRoYXQgdGhpcyBpbnN0YW5jZSBleGlzdHMsCiAgICAgIGl0IHdpbGwgY29udGludWUgYm9vdGluZyBpdCB0byBhdm9pZCBkb2luZyB1bm5jZXNzYXJ5IHdvcmsgKGFzCiAgICAgIG9wcG9zZWQgdG8gYnVpbGRpbmcgYSBuZXcgaW5zdGFuY2UgYXQgYm9vdCB0aW1lKSwgYnV0IHRoZXkgYXJlCiAgICAgIG90aGVyd2lzZSB1bnJlbGF0ZWQuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIF9idWlsZERlcHJlY2F0ZWRJbnN0YW5jZQogICAgKi8KICAgIF9idWlsZERlcHJlY2F0ZWRJbnN0YW5jZTogZnVuY3Rpb24gX2J1aWxkRGVwcmVjYXRlZEluc3RhbmNlKCkgewogICAgICAvLyBCdWlsZCBhIGRlZmF1bHQgaW5zdGFuY2UKICAgICAgdmFyIGluc3RhbmNlID0gdGhpcy5idWlsZEluc3RhbmNlKCk7IC8vIExlZ2FjeSBzdXBwb3J0IGZvciBBcHAuX19jb250YWluZXJfXyBhbmQgb3RoZXIgZ2xvYmFsIG1ldGhvZHMKICAgICAgLy8gb24gQXBwIHRoYXQgcmVseSBvbiBhIHNpbmdsZSwgZGVmYXVsdCBpbnN0YW5jZS4KCiAgICAgIHRoaXMuX19kZXByZWNhdGVkSW5zdGFuY2VfXyA9IGluc3RhbmNlOwogICAgICB0aGlzLl9fY29udGFpbmVyX18gPSBpbnN0YW5jZS5fX2NvbnRhaW5lcl9fOwogICAgfSwKCiAgICAvKioKICAgICAgQXV0b21hdGljYWxseSBraWNrLW9mZiB0aGUgYm9vdCBwcm9jZXNzIGZvciB0aGUgYXBwbGljYXRpb24gb25jZSB0aGUKICAgICAgRE9NIGhhcyBiZWNvbWUgcmVhZHkuCiAgICAgICBUaGUgaW5pdGlhbGl6YXRpb24gaXRzZWxmIGlzIHNjaGVkdWxlZCBvbiB0aGUgYWN0aW9ucyBxdWV1ZSB3aGljaAogICAgICBlbnN1cmVzIHRoYXQgY29kZS1sb2FkaW5nIGZpbmlzaGVzIGJlZm9yZSBib290aW5nLgogICAgICAgSWYgeW91IGFyZSBhc3luY2hyb25vdXNseSBsb2FkaW5nIGNvZGUsIHlvdSBzaG91bGQgY2FsbCBgZGVmZXJSZWFkaW5lc3MoKWAKICAgICAgdG8gZGVmZXIgYm9vdGluZywgYW5kIHRoZW4gY2FsbCBgYWR2YW5jZVJlYWRpbmVzcygpYCBvbmNlIGFsbCBvZiB5b3VyIGNvZGUKICAgICAgaGFzIGZpbmlzaGVkIGxvYWRpbmcuCiAgICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIHdhaXRGb3JET01SZWFkeQogICAgKi8KICAgIHdhaXRGb3JET01SZWFkeTogZnVuY3Rpb24gd2FpdEZvckRPTVJlYWR5KCkgewogICAgICBpZiAoIXRoaXMuJCB8fCB0aGlzLiQuaXNSZWFkeSkgewogICAgICAgICgwLCBfcnVubG9vcC5zY2hlZHVsZSkoJ2FjdGlvbnMnLCB0aGlzLCAnZG9tUmVhZHknKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLiQoKS5yZWFkeSgoMCwgX3J1bmxvb3AuYmluZCkodGhpcywgJ2RvbVJlYWR5JykpOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBUaGlzIGlzIHRoZSBhdXRvYm9vdCBmbG93OgogICAgICAgMS4gQm9vdCB0aGUgYXBwIGJ5IGNhbGxpbmcgYHRoaXMuYm9vdCgpYAogICAgICAyLiBDcmVhdGUgYW4gaW5zdGFuY2UgKG9yIHVzZSB0aGUgYF9fZGVwcmVjYXRlZEluc3RhbmNlX19gIGluIGdsb2JhbHMgbW9kZSkKICAgICAgMy4gQm9vdCB0aGUgaW5zdGFuY2UgYnkgY2FsbGluZyBgaW5zdGFuY2UuYm9vdCgpYAogICAgICA0LiBJbnZva2UgdGhlIGBBcHAucmVhZHkoKWAgY2FsbGJhY2sKICAgICAgNS4gS2ljay1vZmYgcm91dGluZyBvbiB0aGUgaW5zdGFuY2UKICAgICAgIElkZWFsbHksIHRoaXMgaXMgYWxsIHdlIHdvdWxkIG5lZWQgdG8gZG86CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIF9hdXRvQm9vdCgpIHsKICAgICAgICB0aGlzLmJvb3QoKS50aGVuKCgpID0+IHsKICAgICAgICAgIGxldCBpbnN0YW5jZSA9ICh0aGlzLl9nbG9iYWxzTW9kZSkgPyB0aGlzLl9fZGVwcmVjYXRlZEluc3RhbmNlX18gOiB0aGlzLmJ1aWxkSW5zdGFuY2UoKTsKICAgICAgICAgIHJldHVybiBpbnN0YW5jZS5ib290KCk7CiAgICAgICAgfSkudGhlbigoaW5zdGFuY2UpID0+IHsKICAgICAgICAgIEFwcC5yZWFkeSgpOwogICAgICAgICAgaW5zdGFuY2Uuc3RhcnRSb3V0aW5nKCk7CiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBVbmZvcnR1bmF0ZWx5LCB3ZSBjYW5ub3QgYWN0dWFsbHkgd3JpdGUgdGhpcyBiZWNhdXNlIHdlIG5lZWQgdG8gcGFydGljaXBhdGUKICAgICAgaW4gdGhlICJzeW5jaHJvbm91cyIgYm9vdCBwcm9jZXNzLiBXaGlsZSB0aGUgY29kZSBhYm92ZSB3b3VsZCB3b3JrIGZpbmUgb24KICAgICAgdGhlIGluaXRpYWwgYm9vdCAoaS5lLiBET00gcmVhZHkpLCB3aGVuIGBBcHAucmVzZXQoKWAgaXMgY2FsbGVkLCB3ZSBuZWVkIHRvCiAgICAgIGJvb3QgYSBuZXcgaW5zdGFuY2Ugc3luY2hyb25vdXNseSAoc2VlIHRoZSBkb2N1bWVudGF0aW9uIG9uIGBfYm9vdFN5bmMoKWAKICAgICAgZm9yIGRldGFpbHMpLgogICAgICAgQmVjYXVzZSBvZiB0aGlzIHJlc3RyaWN0aW9uLCB0aGUgYWN0dWFsIGxvZ2ljIG9mIHRoaXMgbWV0aG9kIGlzIGxvY2F0ZWQKICAgICAgaW5zaWRlIGBkaWRCZWNvbWVSZWFkeSgpYC4KICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZG9tUmVhZHkKICAgICovCiAgICBkb21SZWFkeTogZnVuY3Rpb24gZG9tUmVhZHkoKSB7CiAgICAgIGlmICh0aGlzLmlzRGVzdHJveWVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9ib290U3luYygpOyAvLyBDb250aW51ZXMgdG8gYGRpZEJlY29tZVJlYWR5YAoKICAgIH0sCgogICAgLyoqCiAgICAgIFVzZSB0aGlzIHRvIGRlZmVyIHJlYWRpbmVzcyB1bnRpbCBzb21lIGNvbmRpdGlvbiBpcyB0cnVlLgogICAgICAgRXhhbXBsZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgICBsZXQgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKCk7CiAgICAgICBBcHAuZGVmZXJSZWFkaW5lc3MoKTsKICAgICAgIC8vICQgaXMgYSByZWZlcmVuY2UgdG8gdGhlIGpRdWVyeSBvYmplY3QvZnVuY3Rpb24KICAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5OwogICAgICAgJC5nZXRKU09OKCcvYXV0aC10b2tlbicsIGZ1bmN0aW9uKHRva2VuKSB7CiAgICAgICAgQXBwLnRva2VuID0gdG9rZW47CiAgICAgICAgQXBwLmFkdmFuY2VSZWFkaW5lc3MoKTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVGhpcyBhbGxvd3MgeW91IHRvIHBlcmZvcm0gYXN5bmNocm9ub3VzIHNldHVwIGxvZ2ljIGFuZCBkZWZlcgogICAgICBib290aW5nIHlvdXIgYXBwbGljYXRpb24gdW50aWwgdGhlIHNldHVwIGhhcyBmaW5pc2hlZC4KICAgICAgIEhvd2V2ZXIsIGlmIHRoZSBzZXR1cCByZXF1aXJlcyBhIGxvYWRpbmcgVUksIGl0IG1pZ2h0IGJlIGJldHRlcgogICAgICB0byB1c2UgdGhlIHJvdXRlciBmb3IgdGhpcyBwdXJwb3NlLgogICAgICAgQG1ldGhvZCBkZWZlclJlYWRpbmVzcwogICAgICBAcHVibGljCiAgICAqLwogICAgZGVmZXJSZWFkaW5lc3M6IGZ1bmN0aW9uIGRlZmVyUmVhZGluZXNzKCkgewogICAgICAoZmFsc2UgJiYgISh0aGlzIGluc3RhbmNlb2YgQXBwbGljYXRpb24pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IG11c3QgY2FsbCBkZWZlclJlYWRpbmVzcyBvbiBhbiBpbnN0YW5jZSBvZiBBcHBsaWNhdGlvbicsIHRoaXMgaW5zdGFuY2VvZiBBcHBsaWNhdGlvbikpOwogICAgICAoZmFsc2UgJiYgISh0aGlzLl9yZWFkaW5lc3NEZWZlcnJhbHMgPiAwKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBjYW5ub3QgZGVmZXIgcmVhZGluZXNzIHNpbmNlIHRoZSBgcmVhZHkoKWAgaG9vayBoYXMgYWxyZWFkeSBiZWVuIGNhbGxlZC4nLCB0aGlzLl9yZWFkaW5lc3NEZWZlcnJhbHMgPiAwKSk7CiAgICAgIHRoaXMuX3JlYWRpbmVzc0RlZmVycmFscysrOwogICAgfSwKCiAgICAvKioKICAgICAgQ2FsbCBgYWR2YW5jZVJlYWRpbmVzc2AgYWZ0ZXIgYW55IGFzeW5jaHJvbm91cyBzZXR1cCBsb2dpYyBoYXMgY29tcGxldGVkLgogICAgICBFYWNoIGNhbGwgdG8gYGRlZmVyUmVhZGluZXNzYCBtdXN0IGJlIG1hdGNoZWQgYnkgYSBjYWxsIHRvIGBhZHZhbmNlUmVhZGluZXNzYAogICAgICBvciB0aGUgYXBwbGljYXRpb24gd2lsbCBuZXZlciBiZWNvbWUgcmVhZHkgYW5kIHJvdXRpbmcgd2lsbCBub3QgYmVnaW4uCiAgICAgICBAbWV0aG9kIGFkdmFuY2VSZWFkaW5lc3MKICAgICAgQHNlZSB7QXBwbGljYXRpb24jZGVmZXJSZWFkaW5lc3N9CiAgICAgIEBwdWJsaWMKICAgICovCiAgICBhZHZhbmNlUmVhZGluZXNzOiBmdW5jdGlvbiBhZHZhbmNlUmVhZGluZXNzKCkgewogICAgICAoZmFsc2UgJiYgISh0aGlzIGluc3RhbmNlb2YgQXBwbGljYXRpb24pICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IG11c3QgY2FsbCBhZHZhbmNlUmVhZGluZXNzIG9uIGFuIGluc3RhbmNlIG9mIEFwcGxpY2F0aW9uJywgdGhpcyBpbnN0YW5jZW9mIEFwcGxpY2F0aW9uKSk7CiAgICAgIHRoaXMuX3JlYWRpbmVzc0RlZmVycmFscy0tOwoKICAgICAgaWYgKHRoaXMuX3JlYWRpbmVzc0RlZmVycmFscyA9PT0gMCkgewogICAgICAgICgwLCBfcnVubG9vcC5vbmNlKSh0aGlzLCB0aGlzLmRpZEJlY29tZVJlYWR5KTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgSW5pdGlhbGl6ZSB0aGUgYXBwbGljYXRpb24gYW5kIHJldHVybiBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBgQXBwbGljYXRpb25gCiAgICAgIG9iamVjdCB3aGVuIHRoZSBib290IHByb2Nlc3MgaXMgY29tcGxldGUuCiAgICAgICBSdW4gYW55IGFwcGxpY2F0aW9uIGluaXRpYWxpemVycyBhbmQgcnVuIHRoZSBhcHBsaWNhdGlvbiBsb2FkIGhvb2suIFRoZXNlIGhvb2tzIG1heQogICAgICBjaG9vc2UgdG8gZGVmZXIgcmVhZGluZXNzLiBGb3IgZXhhbXBsZSwgYW4gYXV0aGVudGljYXRpb24gaG9vayBtaWdodCB3YW50IHRvIGRlZmVyCiAgICAgIHJlYWRpbmVzcyB1bnRpbCB0aGUgYXV0aCB0b2tlbiBoYXMgYmVlbiByZXRyaWV2ZWQuCiAgICAgICBCeSBkZWZhdWx0LCB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgYXV0b21hdGljYWxseSBvbiAiRE9NIHJlYWR5IjsgaG93ZXZlciwgaWYgYXV0b2Jvb3QKICAgICAgaXMgZGlzYWJsZWQsIHRoaXMgaXMgYXV0b21hdGljYWxseSBjYWxsZWQgd2hlbiB0aGUgZmlyc3QgYXBwbGljYXRpb24gaW5zdGFuY2UgaXMKICAgICAgY3JlYXRlZCB2aWEgYHZpc2l0YC4KICAgICAgIEBwdWJsaWMKICAgICAgQG1ldGhvZCBib290CiAgICAgIEByZXR1cm4ge1Byb21pc2U8QXBwbGljYXRpb24sRXJyb3I+fQogICAgKi8KICAgIGJvb3Q6IGZ1bmN0aW9uIGJvb3QoKSB7CiAgICAgIGlmICh0aGlzLl9ib290UHJvbWlzZSkgewogICAgICAgIHJldHVybiB0aGlzLl9ib290UHJvbWlzZTsKICAgICAgfQoKICAgICAgdHJ5IHsKICAgICAgICB0aGlzLl9ib290U3luYygpOwogICAgICB9IGNhdGNoIChfKSB7Ly8gSWdub3JlIHRoZSBlcnJvcjogaW4gdGhlIGFzeW5jaHJvbm91cyBib290IHBhdGgsIHRoZSBlcnJvciBpcyBhbHJlYWR5IHJlZmxlY3RlZAogICAgICAgIC8vIGluIHRoZSBwcm9taXNlIHJlamVjdGlvbgogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fYm9vdFByb21pc2U7CiAgICB9LAoKICAgIC8qKgogICAgICBVbmZvcnR1bmF0ZWx5LCBhIGxvdCBvZiBleGlzdGluZyBjb2RlIGFzc3VtZXMgdGhlIGJvb3RpbmcgcHJvY2VzcyBpcwogICAgICAic3luY2hyb25vdXMiLiBTcGVjaWZpY2FsbHksIGEgbG90IG9mIHRlc3RzIGFzc3VtZXMgdGhlIGxhc3QgY2FsbCB0bwogICAgICBgYXBwLmFkdmFuY2VSZWFkaW5lc3MoKWAgb3IgYGFwcC5yZXNldCgpYCB3aWxsIHJlc3VsdCBpbiB0aGUgYXBwIGJlaW5nCiAgICAgIGZ1bGx5LWJvb3RlZCB3aGVuIHRoZSBjdXJyZW50IHJ1bmxvb3AgY29tcGxldGVzLgogICAgICAgV2Ugd291bGQgbGlrZSBuZXcgY29kZSAobGlrZSB0aGUgYHZpc2l0YCBBUEkpIHRvIHN0b3AgbWFraW5nIHRoaXMgYXNzdW1wdGlvbiwKICAgICAgc28gd2UgY3JlYXRlZCB0aGUgYXN5bmNocm9ub3VzIHZlcnNpb24gYWJvdmUgdGhhdCByZXR1cm5zIGEgcHJvbWlzZS4gQnV0IHVudGlsCiAgICAgIHdlIGhhdmUgbWlncmF0ZWQgYWxsIHRoZSBjb2RlLCB3ZSB3b3VsZCBoYXZlIHRvIGV4cG9zZSB0aGlzIG1ldGhvZCBmb3IgdXNlCiAgICAgICppbnRlcm5hbGx5KiBpbiBwbGFjZXMgd2hlcmUgd2UgbmVlZCB0byBib290IGFuIGFwcCAic3luY2hyb25vdXNseSIuCiAgICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ib290U3luYzogZnVuY3Rpb24gX2Jvb3RTeW5jKCkgewogICAgICBpZiAodGhpcy5fYm9vdGVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIEV2ZW4gdGhvdWdoIHRoaXMgcmV0dXJucyBzeW5jaHJvbm91c2x5LCB3ZSBzdGlsbCBuZWVkIHRvIG1ha2Ugc3VyZSB0aGUKICAgICAgLy8gYm9vdCBwcm9taXNlIGV4aXN0cyBmb3IgYm9vay1rZWVwaW5nIHB1cnBvc2VzOiBpZiBhbnl0aGluZyB3ZW50IHdyb25nIGluCiAgICAgIC8vIHRoZSBib290IHByb2Nlc3MsIHdlIG5lZWQgdG8gc3RvcmUgdGhlIGVycm9yIGFzIGEgcmVqZWN0aW9uIG9uIHRoZSBib290CiAgICAgIC8vIHByb21pc2Ugc28gdGhhdCBhIGZ1dHVyZSBjYWxsZXIgb2YgYGJvb3QoKWAgY2FuIHRlbGwgd2hhdCBmYWlsZWQuCgoKICAgICAgdmFyIGRlZmVyID0gdGhpcy5fYm9vdFJlc29sdmVyID0gX3J1bnRpbWUuUlNWUC5kZWZlcigpOwoKICAgICAgdGhpcy5fYm9vdFByb21pc2UgPSBkZWZlci5wcm9taXNlOwoKICAgICAgdHJ5IHsKICAgICAgICB0aGlzLnJ1bkluaXRpYWxpemVycygpOwogICAgICAgICgwLCBfbGF6eV9sb2FkLnJ1bkxvYWRIb29rcykoJ2FwcGxpY2F0aW9uJywgdGhpcyk7CiAgICAgICAgdGhpcy5hZHZhbmNlUmVhZGluZXNzKCk7IC8vIENvbnRpbnVlcyB0byBgZGlkQmVjb21lUmVhZHlgCiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgLy8gRm9yIHRoZSBhc3luY2hyb25vdXMgYm9vdCBwYXRoCiAgICAgICAgZGVmZXIucmVqZWN0KGVycm9yKTsgLy8gRm9yIHRoZSBzeW5jaHJvbm91cyBib290IHBhdGgKCiAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIFJlc2V0IHRoZSBhcHBsaWNhdGlvbi4gVGhpcyBpcyB0eXBpY2FsbHkgdXNlZCBvbmx5IGluIHRlc3RzLiBJdCBjbGVhbnMgdXAKICAgICAgdGhlIGFwcGxpY2F0aW9uIGluIHRoZSBmb2xsb3dpbmcgb3JkZXI6CiAgICAgICAxLiBEZWFjdGl2YXRlIGV4aXN0aW5nIHJvdXRlcwogICAgICAyLiBEZXN0cm95IGFsbCBvYmplY3RzIGluIHRoZSBjb250YWluZXIKICAgICAgMy4gQ3JlYXRlIGEgbmV3IGFwcGxpY2F0aW9uIGNvbnRhaW5lcgogICAgICA0LiBSZS1yb3V0ZSB0byB0aGUgZXhpc3RpbmcgdXJsCiAgICAgICBUeXBpY2FsIEV4YW1wbGU6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbiBmcm9tICdAZW1iZXIvYXBwbGljYXRpb24nOwogICAgICBsZXQgQXBwOwogICAgICAgcnVuKGZ1bmN0aW9uKCkgewogICAgICAgIEFwcCA9IEFwcGxpY2F0aW9uLmNyZWF0ZSgpOwogICAgICB9KTsKICAgICAgIG1vZHVsZSgnYWNjZXB0YW5jZSB0ZXN0JywgewogICAgICAgIHNldHVwOiBmdW5jdGlvbigpIHsKICAgICAgICAgIEFwcC5yZXNldCgpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICB0ZXN0KCdmaXJzdCB0ZXN0JywgZnVuY3Rpb24oKSB7CiAgICAgICAgLy8gQXBwIGlzIGZyZXNobHkgcmVzZXQKICAgICAgfSk7CiAgICAgICB0ZXN0KCdzZWNvbmQgdGVzdCcsIGZ1bmN0aW9uKCkgewogICAgICAgIC8vIEFwcCBpcyBhZ2FpbiBmcmVzaGx5IHJlc2V0CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEFkdmFuY2VkIEV4YW1wbGU6CiAgICAgICBPY2Nhc2lvbmFsbHkgeW91IG1heSB3YW50IHRvIHByZXZlbnQgdGhlIGFwcCBmcm9tIGluaXRpYWxpemluZyBkdXJpbmcKICAgICAgc2V0dXAuIFRoaXMgY291bGQgZW5hYmxlIGV4dHJhIGNvbmZpZ3VyYXRpb24sIG9yIGVuYWJsZSBhc3NlcnRpbmcgcHJpb3IKICAgICAgdG8gdGhlIGFwcCBiZWNvbWluZyByZWFkeS4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IEFwcGxpY2F0aW9uIGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgICAgIGxldCBBcHA7CiAgICAgICBydW4oZnVuY3Rpb24oKSB7CiAgICAgICAgQXBwID0gQXBwbGljYXRpb24uY3JlYXRlKCk7CiAgICAgIH0pOwogICAgICAgbW9kdWxlKCdhY2NlcHRhbmNlIHRlc3QnLCB7CiAgICAgICAgc2V0dXA6IGZ1bmN0aW9uKCkgewogICAgICAgICAgcnVuKGZ1bmN0aW9uKCkgewogICAgICAgICAgICBBcHAucmVzZXQoKTsKICAgICAgICAgICAgQXBwLmRlZmVyUmVhZGluZXNzKCk7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgdGVzdCgnZmlyc3QgdGVzdCcsIGZ1bmN0aW9uKCkgewogICAgICAgIG9rKHRydWUsICdzb21ldGhpbmcgYmVmb3JlIGFwcCBpcyBpbml0aWFsaXplZCcpOwogICAgICAgICBydW4oZnVuY3Rpb24oKSB7CiAgICAgICAgICBBcHAuYWR2YW5jZVJlYWRpbmVzcygpOwogICAgICAgIH0pOwogICAgICAgICBvayh0cnVlLCAnc29tZXRoaW5nIGFmdGVyIGFwcCBpcyBpbml0aWFsaXplZCcpOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHJlc2V0CiAgICAgIEBwdWJsaWMKICAgICovCiAgICByZXNldDogZnVuY3Rpb24gcmVzZXQoKSB7CiAgICAgIChmYWxzZSAmJiAhKHRoaXMuX2dsb2JhbHNNb2RlICYmIHRoaXMuYXV0b2Jvb3QpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQ2FsbGluZyByZXNldCgpIG9uIGluc3RhbmNlcyBvZiBgQXBwbGljYXRpb25gIGlzIG5vdFxuICAgICAgICAgICAgc3VwcG9ydGVkIHdoZW4gZ2xvYmFscyBtb2RlIGlzIGRpc2FibGVkOyBjYWxsIGB2aXNpdCgpYCB0b1xuICAgICAgICAgICAgY3JlYXRlIG5ldyBgQXBwbGljYXRpb25JbnN0YW5jZWBzIGFuZCBkaXNwb3NlIHRoZW1cbiAgICAgICAgICAgIHZpYSB0aGVpciBgZGVzdHJveSgpYCBtZXRob2QgaW5zdGVhZC4iLCB0aGlzLl9nbG9iYWxzTW9kZSAmJiB0aGlzLmF1dG9ib290KSk7CiAgICAgIHZhciBpbnN0YW5jZSA9IHRoaXMuX19kZXByZWNhdGVkSW5zdGFuY2VfXzsKICAgICAgdGhpcy5fcmVhZGluZXNzRGVmZXJyYWxzID0gMTsKICAgICAgdGhpcy5fYm9vdFByb21pc2UgPSBudWxsOwogICAgICB0aGlzLl9ib290UmVzb2x2ZXIgPSBudWxsOwogICAgICB0aGlzLl9ib290ZWQgPSBmYWxzZTsKCiAgICAgIGZ1bmN0aW9uIGhhbmRsZVJlc2V0KCkgewogICAgICAgICgwLCBfcnVubG9vcC5ydW4pKGluc3RhbmNlLCAnZGVzdHJveScpOwoKICAgICAgICB0aGlzLl9idWlsZERlcHJlY2F0ZWRJbnN0YW5jZSgpOwoKICAgICAgICAoMCwgX3J1bmxvb3Auc2NoZWR1bGUpKCdhY3Rpb25zJywgdGhpcywgJ19ib290U3luYycpOwogICAgICB9CgogICAgICAoMCwgX3J1bmxvb3Auam9pbikodGhpcywgaGFuZGxlUmVzZXQpOwogICAgfSwKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBkaWRCZWNvbWVSZWFkeQogICAgKi8KICAgIGRpZEJlY29tZVJlYWR5OiBmdW5jdGlvbiBkaWRCZWNvbWVSZWFkeSgpIHsKICAgICAgdHJ5IHsKICAgICAgICAvLyBUT0RPOiBJcyB0aGlzIHN0aWxsIG5lZWRlZCBmb3IgX2dsb2JhbHNNb2RlID0gZmFsc2U/CiAgICAgICAgaWYgKCEoMCwgX2RlYnVnLmlzVGVzdGluZykoKSkgewogICAgICAgICAgLy8gRWFnZXJseSBuYW1lIGFsbCBjbGFzc2VzIHRoYXQgYXJlIGFscmVhZHkgbG9hZGVkCiAgICAgICAgICAoMCwgX21ldGFsLnByb2Nlc3NBbGxOYW1lc3BhY2VzKSgpOwogICAgICAgICAgKDAsIF9tZXRhbC5zZXROYW1lc3BhY2VTZWFyY2hEaXNhYmxlZCkodHJ1ZSk7CiAgICAgICAgfSAvLyBTZWUgZG9jdW1lbnRhdGlvbiBvbiBgX2F1dG9ib290KClgIGZvciBkZXRhaWxzCgoKICAgICAgICBpZiAodGhpcy5hdXRvYm9vdCkgewogICAgICAgICAgdmFyIGluc3RhbmNlOwoKICAgICAgICAgIGlmICh0aGlzLl9nbG9iYWxzTW9kZSkgewogICAgICAgICAgICAvLyBJZiB3ZSBhbHJlYWR5IGhhdmUgdGhlIF9fZGVwcmVjYXRlZEluc3RhbmNlX18gbHlpbmcgYXJvdW5kLCBib290IGl0IHRvCiAgICAgICAgICAgIC8vIGF2b2lkIHVubmVjZXNzYXJ5IHdvcmsKICAgICAgICAgICAgaW5zdGFuY2UgPSB0aGlzLl9fZGVwcmVjYXRlZEluc3RhbmNlX187CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvLyBPdGhlcndpc2UsIGJ1aWxkIGFuIGluc3RhbmNlIGFuZCBib290IGl0LiBUaGlzIGlzIGN1cnJlbnRseSB1bnJlYWNoYWJsZSwKICAgICAgICAgICAgLy8gYmVjYXVzZSB3ZSBmb3JjZWQgX2dsb2JhbHNNb2RlIHRvID09PSBhdXRvYm9vdDsgYnV0IGhhdmluZyB0aGlzIGJyYW5jaAogICAgICAgICAgICAvLyBhbGxvd3MgdXMgdG8gbG9jYWxseSB0b2dnbGUgdGhhdCBmbGFnIGZvciB3ZWVkaW5nIG91dCBsZWdhY3kgZ2xvYmFscyBtb2RlCiAgICAgICAgICAgIC8vIGRlcGVuZGVuY2llcyBpbmRlcGVuZGVudGx5CiAgICAgICAgICAgIGluc3RhbmNlID0gdGhpcy5idWlsZEluc3RhbmNlKCk7CiAgICAgICAgICB9CgogICAgICAgICAgaW5zdGFuY2UuX2Jvb3RTeW5jKCk7IC8vIFRPRE86IEFwcC5yZWFkeSgpIGlzIG5vdCBjYWxsZWQgd2hlbiBhdXRvYm9vdCBpcyBkaXNhYmxlZCwgaXMgdGhpcyBjb3JyZWN0PwoKCiAgICAgICAgICB0aGlzLnJlYWR5KCk7CiAgICAgICAgICBpbnN0YW5jZS5zdGFydFJvdXRpbmcoKTsKICAgICAgICB9IC8vIEZvciB0aGUgYXN5bmNocm9ub3VzIGJvb3QgcGF0aAoKCiAgICAgICAgdGhpcy5fYm9vdFJlc29sdmVyLnJlc29sdmUodGhpcyk7IC8vIEZvciB0aGUgc3luY2hyb25vdXMgYm9vdCBwYXRoCgoKICAgICAgICB0aGlzLl9ib290ZWQgPSB0cnVlOwogICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgIC8vIEZvciB0aGUgYXN5bmNocm9ub3VzIGJvb3QgcGF0aAogICAgICAgIHRoaXMuX2Jvb3RSZXNvbHZlci5yZWplY3QoZXJyb3IpOyAvLyBGb3IgdGhlIHN5bmNocm9ub3VzIGJvb3QgcGF0aAoKCiAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIENhbGxlZCB3aGVuIHRoZSBBcHBsaWNhdGlvbiBoYXMgYmVjb21lIHJlYWR5LCBpbW1lZGlhdGVseSBiZWZvcmUgcm91dGluZwogICAgICBiZWdpbnMuIFRoZSBjYWxsIHdpbGwgYmUgZGVsYXllZCB1bnRpbCB0aGUgRE9NIGhhcyBiZWNvbWUgcmVhZHkuCiAgICAgICBAZXZlbnQgcmVhZHkKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHJlYWR5OiBmdW5jdGlvbiByZWFkeSgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9LAogICAgLy8gVGhpcyBtZXRob2QgbXVzdCBiZSBtb3ZlZCB0byB0aGUgYXBwbGljYXRpb24gaW5zdGFuY2Ugb2JqZWN0CiAgICB3aWxsRGVzdHJveTogZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAoMCwgX21ldGFsLnNldE5hbWVzcGFjZVNlYXJjaERpc2FibGVkKShmYWxzZSk7CiAgICAgIHRoaXMuX2Jvb3RlZCA9IGZhbHNlOwogICAgICB0aGlzLl9ib290UHJvbWlzZSA9IG51bGw7CiAgICAgIHRoaXMuX2Jvb3RSZXNvbHZlciA9IG51bGw7CgogICAgICBpZiAoX2xhenlfbG9hZC5fbG9hZGVkLmFwcGxpY2F0aW9uID09PSB0aGlzKSB7CiAgICAgICAgX2xhenlfbG9hZC5fbG9hZGVkLmFwcGxpY2F0aW9uID0gdW5kZWZpbmVkOwogICAgICB9CgogICAgICBpZiAodGhpcy5fYXBwbGljYXRpb25JbnN0YW5jZXMuc2l6ZSkgewogICAgICAgIHRoaXMuX2FwcGxpY2F0aW9uSW5zdGFuY2VzLmZvckVhY2goZnVuY3Rpb24gKGkpIHsKICAgICAgICAgIHJldHVybiBpLmRlc3Ryb3koKTsKICAgICAgICB9KTsKCiAgICAgICAgdGhpcy5fYXBwbGljYXRpb25JbnN0YW5jZXMuY2xlYXIoKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgQm9vdCBhIG5ldyBpbnN0YW5jZSBvZiBgQXBwbGljYXRpb25JbnN0YW5jZWAgZm9yIHRoZSBjdXJyZW50CiAgICAgIGFwcGxpY2F0aW9uIGFuZCBuYXZpZ2F0ZSBpdCB0byB0aGUgZ2l2ZW4gYHVybGAuIFJldHVybnMgYSBgUHJvbWlzZWAgdGhhdAogICAgICByZXNvbHZlcyB3aXRoIHRoZSBpbnN0YW5jZSB3aGVuIHRoZSBpbml0aWFsIHJvdXRpbmcgYW5kIHJlbmRlcmluZyBpcwogICAgICBjb21wbGV0ZSwgb3IgcmVqZWN0cyB3aXRoIGFueSBlcnJvciB0aGF0IG9jY3VycmVkIGR1cmluZyB0aGUgYm9vdCBwcm9jZXNzLgogICAgICAgV2hlbiBgYXV0b2Jvb3RgIGlzIGRpc2FibGVkLCBjYWxsaW5nIGB2aXNpdGAgd291bGQgZmlyc3QgY2F1c2UgdGhlCiAgICAgIGFwcGxpY2F0aW9uIHRvIGJvb3QsIHdoaWNoIHJ1bnMgdGhlIGFwcGxpY2F0aW9uIGluaXRpYWxpemVycy4KICAgICAgIFRoaXMgbWV0aG9kIGFsc28gdGFrZXMgYSBoYXNoIG9mIGJvb3QtdGltZSBjb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yCiAgICAgIGN1c3RvbWl6aW5nIHRoZSBpbnN0YW5jZSdzIGJlaGF2aW9yLiBTZWUgdGhlIGRvY3VtZW50YXRpb24gb24KICAgICAgYEFwcGxpY2F0aW9uSW5zdGFuY2UuQm9vdE9wdGlvbnNgIGZvciBkZXRhaWxzLgogICAgICAgYEFwcGxpY2F0aW9uSW5zdGFuY2UuQm9vdE9wdGlvbnNgIGlzIGFuIGludGVyZmFjZSBjbGFzcyB0aGF0IGV4aXN0cwogICAgICBwdXJlbHkgdG8gZG9jdW1lbnQgdGhlIGF2YWlsYWJsZSBvcHRpb25zOyB5b3UgZG8gbm90IG5lZWQgdG8gY29uc3RydWN0IGl0CiAgICAgIG1hbnVhbGx5LiBTaW1wbHkgcGFzcyBhIHJlZ3VsYXIgSmF2YVNjcmlwdCBvYmplY3QgY29udGFpbmluZyBvZiB0aGUKICAgICAgZGVzaXJlZCBvcHRpb25zOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBNeUFwcC52aXNpdCgiLyIsIHsgbG9jYXRpb246ICJub25lIiwgcm9vdEVsZW1lbnQ6ICIjY29udGFpbmVyIiB9KTsKICAgICAgYGBgCiAgICAgICAjIyMgU3VwcG9ydGVkIFNjZW5hcmlvcwogICAgICAgV2hpbGUgdGhlIGBCb290T3B0aW9uc2AgY2xhc3MgZXhwb3NlcyBhIGxhcmdlIG51bWJlciBvZiBrbm9icywgbm90IGFsbAogICAgICBjb21iaW5hdGlvbnMgb2YgdGhlbSBhcmUgdmFsaWQ7IGNlcnRhaW4gaW5jb21wYXRpYmxlIGNvbWJpbmF0aW9ucyBtaWdodAogICAgICByZXN1bHQgaW4gdW5leHBlY3RlZCBiZWhhdmlvci4KICAgICAgIEZvciBleGFtcGxlLCBib290aW5nIHRoZSBpbnN0YW5jZSBpbiB0aGUgZnVsbCBicm93c2VyIGVudmlyb25tZW50CiAgICAgIHdoaWxlIHNwZWNpZnlpbmcgYSBmb3JlaWduIGBkb2N1bWVudGAgb2JqZWN0IChlLmcuIGB7IGlzQnJvd3NlcjogdHJ1ZSwKICAgICAgZG9jdW1lbnQ6IGlmcmFtZS5jb250ZW50RG9jdW1lbnQgfWApIGRvZXMgbm90IHdvcmsgY29ycmVjdGx5IHRvZGF5LAogICAgICBsYXJnZWx5IGR1ZSB0byBFbWJlcidzIGpRdWVyeSBkZXBlbmRlbmN5LgogICAgICAgQ3VycmVudGx5LCB0aGVyZSBhcmUgdGhyZWUgb2ZmaWNpYWxseSBzdXBwb3J0ZWQgc2NlbmFyaW9zL2NvbmZpZ3VyYXRpb25zLgogICAgICBVc2FnZXMgb3V0c2lkZSBvZiB0aGVzZSBzY2VuYXJpb3MgYXJlIG5vdCBndWFyYW50ZWVkIHRvIHdvcmssIGJ1dCBwbGVhc2UKICAgICAgZmVlbCBmcmVlIHRvIGZpbGUgYnVnIHJlcG9ydHMgZG9jdW1lbnRpbmcgeW91ciBleHBlcmllbmNlIGFuZCBhbnkgaXNzdWVzCiAgICAgIHlvdSBlbmNvdW50ZXJlZCB0byBoZWxwIGV4cGFuZCBzdXBwb3J0LgogICAgICAgIyMjIyBCcm93c2VyIEFwcGxpY2F0aW9ucyAoTWFudWFsIEJvb3QpCiAgICAgICBUaGUgc2V0dXAgaXMgbGFyZ2VseSBzaW1pbGFyIHRvIGhvdyBFbWJlciB3b3JrcyBvdXQtb2YtdGhlLWJveC4gTm9ybWFsbHksCiAgICAgIEVtYmVyIHdpbGwgYm9vdCBhIGRlZmF1bHQgaW5zdGFuY2UgZm9yIHlvdXIgQXBwbGljYXRpb24gb24gIkRPTSByZWFkeSIuCiAgICAgIEhvd2V2ZXIsIHlvdSBjYW4gY3VzdG9taXplIHRoaXMgYmVoYXZpb3IgYnkgZGlzYWJsaW5nIGBhdXRvYm9vdGAuCiAgICAgICBGb3IgZXhhbXBsZSwgdGhpcyBhbGxvd3MgeW91IHRvIHJlbmRlciBhIG1pbml0dXJlIGRlbW8gb2YgeW91ciBhcHBsaWNhdGlvbgogICAgICBpbnRvIGEgc3BlY2lmaWMgYXJlYSBvbiB5b3VyIG1hcmtldGluZyB3ZWJzaXRlOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgTXlBcHAgZnJvbSAnbXktYXBwJzsKICAgICAgICQoZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IEFwcCA9IE15QXBwLmNyZWF0ZSh7IGF1dG9ib290OiBmYWxzZSB9KTsKICAgICAgICAgbGV0IG9wdGlvbnMgPSB7CiAgICAgICAgICAvLyBPdmVycmlkZSB0aGUgcm91dGVyJ3MgbG9jYXRpb24gYWRhcHRlciB0byBwcmV2ZW50IGl0IGZyb20gdXBkYXRpbmcKICAgICAgICAgIC8vIHRoZSBVUkwgaW4gdGhlIGFkZHJlc3MgYmFyCiAgICAgICAgICBsb2NhdGlvbjogJ25vbmUnLAogICAgICAgICAgIC8vIE92ZXJyaWRlIHRoZSBkZWZhdWx0IGByb290RWxlbWVudGAgb24gdGhlIGFwcCB0byByZW5kZXIgaW50byBhCiAgICAgICAgICAvLyBzcGVjaWZpYyBgZGl2YCBvbiB0aGUgcGFnZQogICAgICAgICAgcm9vdEVsZW1lbnQ6ICcjZGVtbycKICAgICAgICB9OwogICAgICAgICAvLyBTdGFydCB0aGUgYXBwIGF0IHRoZSBzcGVjaWFsIGRlbW8gVVJMCiAgICAgICAgQXBwLnZpc2l0KCcvZGVtbycsIG9wdGlvbnMpOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBPciBwZXJoYXBzIHlvdSBtaWdodCB3YW50IHRvIGJvb3QgdHdvIGluc3RhbmNlcyBvZiB5b3VyIGFwcCBvbiB0aGUgc2FtZQogICAgICBwYWdlIGZvciBhIHNwbGl0LXNjcmVlbiBtdWx0aXBsYXllciBleHBlcmllbmNlOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgTXlBcHAgZnJvbSAnbXktYXBwJzsKICAgICAgICQoZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IEFwcCA9IE15QXBwLmNyZWF0ZSh7IGF1dG9ib290OiBmYWxzZSB9KTsKICAgICAgICAgbGV0IHNlc3Npb25JZCA9IE15QXBwLmdlbmVyYXRlU2Vzc2lvbklEKCk7CiAgICAgICAgIGxldCBwbGF5ZXIxID0gQXBwLnZpc2l0KGAvbWF0Y2hlcy9qb2luP25hbWU9UGxheWVyKzEmc2Vzc2lvbj0ke3Nlc3Npb25JZH1gLCB7IHJvb3RFbGVtZW50OiAnI2xlZnQnLCBsb2NhdGlvbjogJ25vbmUnIH0pOwogICAgICAgIGxldCBwbGF5ZXIyID0gQXBwLnZpc2l0KGAvbWF0Y2hlcy9qb2luP25hbWU9UGxheWVyKzImc2Vzc2lvbj0ke3Nlc3Npb25JZH1gLCB7IHJvb3RFbGVtZW50OiAnI3JpZ2h0JywgbG9jYXRpb246ICdub25lJyB9KTsKICAgICAgICAgUHJvbWlzZS5hbGwoW3BsYXllcjEsIHBsYXllcjJdKS50aGVuKCgpID0+IHsKICAgICAgICAgIC8vIEJvdGggYXBwcyBoYXZlIGNvbXBsZXRlZCB0aGUgaW5pdGlhbCByZW5kZXIKICAgICAgICAgICQoJyNsb2FkaW5nJykuZmFkZU91dCgpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBEbyBub3RlIHRoYXQgZWFjaCBhcHAgaW5zdGFuY2UgbWFpbnRhaW5zIHRoZWlyIG93biByZWdpc3RyeS9jb250YWluZXIsIHNvCiAgICAgIHRoZXkgd2lsbCBydW4gaW4gY29tcGxldGUgaXNvbGF0aW9uIGJ5IGRlZmF1bHQuCiAgICAgICAjIyMjIFNlcnZlci1TaWRlIFJlbmRlcmluZyAoYWxzbyBrbm93biBhcyBGYXN0Qm9vdCkKICAgICAgIFRoaXMgc2V0dXAgYWxsb3dzIHlvdSB0byBydW4geW91ciBFbWJlciBhcHAgaW4gYSBzZXJ2ZXIgZW52aXJvbm1lbnQgdXNpbmcKICAgICAgTm9kZS5qcyBhbmQgcmVuZGVyIGl0cyBjb250ZW50IGludG8gc3RhdGljIEhUTUwgZm9yIFNFTyBwdXJwb3Nlcy4KICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgY29uc3QgSFRNTFNlcmlhbGl6ZXIgPSBuZXcgU2ltcGxlRE9NLkhUTUxTZXJpYWxpemVyKFNpbXBsZURPTS52b2lkTWFwKTsKICAgICAgIGZ1bmN0aW9uIHJlbmRlclVSTCh1cmwpIHsKICAgICAgICBsZXQgZG9tID0gbmV3IFNpbXBsZURPTS5Eb2N1bWVudCgpOwogICAgICAgIGxldCByb290RWxlbWVudCA9IGRvbS5ib2R5OwogICAgICAgIGxldCBvcHRpb25zID0geyBpc0Jyb3dzZXI6IGZhbHNlLCBkb2N1bWVudDogZG9tLCByb290RWxlbWVudDogcm9vdEVsZW1lbnQgfTsKICAgICAgICAgcmV0dXJuIE15QXBwLnZpc2l0KG9wdGlvbnMpLnRoZW4oaW5zdGFuY2UgPT4gewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcmV0dXJuIEhUTUxTZXJpYWxpemVyLnNlcmlhbGl6ZShyb290RWxlbWVudC5maXJzdENoaWxkKTsKICAgICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICAgIGluc3RhbmNlLmRlc3Ryb3koKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQogICAgICBgYGAKICAgICAgIEluIHRoaXMgc2NlbmFyaW8sIGJlY2F1c2UgRW1iZXIgZG9lcyBub3QgaGF2ZSBhY2Nlc3MgdG8gYSBnbG9iYWwgYGRvY3VtZW50YAogICAgICBvYmplY3QgaW4gdGhlIE5vZGUuanMgZW52aXJvbm1lbnQsIHlvdSBtdXN0IHByb3ZpZGUgb25lIGV4cGxpY2l0bHkuIEluIHByYWN0aWNlLAogICAgICBpbiB0aGUgbm9uLWJyb3dzZXIgZW52aXJvbm1lbnQsIHRoZSBzdGFuZC1pbiBgZG9jdW1lbnRgIG9iamVjdCBvbmx5IG5lZWRzIHRvCiAgICAgIGltcGxlbWVudCBhIGxpbWl0ZWQgc3Vic2V0IG9mIHRoZSBmdWxsIERPTSBBUEkuIFRoZSBgU2ltcGxlRE9NYCBsaWJyYXJ5IGlzIGtub3duCiAgICAgIHRvIHdvcmsuCiAgICAgICBTaW5jZSB0aGVyZSBpcyBubyBhY2Nlc3MgdG8galF1ZXJ5IGluIHRoZSBub24tYnJvd3NlciBlbnZpcm9ubWVudCwgeW91IG11c3QgYWxzbwogICAgICBzcGVjaWZ5IGEgRE9NIGBFbGVtZW50YCBvYmplY3QgaW4gdGhlIHNhbWUgYGRvY3VtZW50YCBmb3IgdGhlIGByb290RWxlbWVudGAgb3B0aW9uCiAgICAgIChhcyBvcHBvc2VkIHRvIGEgc2VsZWN0b3Igc3RyaW5nIGxpa2UgYCJib2R5ImApLgogICAgICAgU2VlIHRoZSBkb2N1bWVudGF0aW9uIG9uIHRoZSBgaXNCcm93c2VyYCwgYGRvY3VtZW50YCBhbmQgYHJvb3RFbGVtZW50YCBwcm9wZXJ0aWVzCiAgICAgIG9uIGBBcHBsaWNhdGlvbkluc3RhbmNlLkJvb3RPcHRpb25zYCBmb3IgZGV0YWlscy4KICAgICAgICMjIyMgU2VydmVyLVNpZGUgUmVzb3VyY2UgRGlzY292ZXJ5CiAgICAgICBUaGlzIHNldHVwIGFsbG93cyB5b3UgdG8gcnVuIHRoZSByb3V0aW5nIGxheWVyIG9mIHlvdXIgRW1iZXIgYXBwIGluIGEgc2VydmVyCiAgICAgIGVudmlyb25tZW50IHVzaW5nIE5vZGUuanMgYW5kIGNvbXBsZXRlbHkgZGlzYWJsZSByZW5kZXJpbmcuIFRoaXMgYWxsb3dzIHlvdQogICAgICB0byBzaW11bGF0ZSBhbmQgZGlzY292ZXIgdGhlIHJlc291cmNlcyAoaS5lLiBBSkFYIHJlcXVlc3RzKSBuZWVkZWQgdG8gZnVsZmlsbAogICAgICBhIGdpdmVuIHJlcXVlc3QgYW5kIGVhZ2VybHkgInB1c2giIHRoZXNlIHJlc291cmNlcyB0byB0aGUgY2xpZW50LgogICAgICAgYGBgYXBwL2luaXRpYWxpemVycy9uZXR3b3JrLXNlcnZpY2UuanMKICAgICAgaW1wb3J0IEJyb3dzZXJOZXR3b3JrU2VydmljZSBmcm9tICdhcHAvc2VydmljZXMvbmV0d29yay9icm93c2VyJzsKICAgICAgaW1wb3J0IE5vZGVOZXR3b3JrU2VydmljZSBmcm9tICdhcHAvc2VydmljZXMvbmV0d29yay9ub2RlJzsKICAgICAgIC8vIEluamVjdCBhIChoeXBvdGhldGljYWwpIHNlcnZpY2UgZm9yIGFic3RyYWN0aW5nIGFsbCBBSkFYIGNhbGxzIGFuZCB1c2UKICAgICAgLy8gdGhlIGFwcHJvcHJpYXRlIGltcGxlbWVudGF0aW9uIG9uIHRoZSBjbGllbnQvc2VydmVyLiBUaGlzIGFsc28gYWxsb3dzIHRoZQogICAgICAvLyBzZXJ2ZXIgdG8gbG9nIGFsbCB0aGUgQUpBWCBjYWxscyBtYWRlIGR1cmluZyBhIHBhcnRpY3VsYXIgcmVxdWVzdCBhbmQgdXNlCiAgICAgIC8vIHRoYXQgZm9yIHJlc291cmNlLWRpc2NvdmVyeSBwdXJwb3NlLgogICAgICAgZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemUoYXBwbGljYXRpb24pIHsKICAgICAgICBpZiAod2luZG93KSB7IC8vIGJyb3dzZXIKICAgICAgICAgIGFwcGxpY2F0aW9uLnJlZ2lzdGVyKCdzZXJ2aWNlOm5ldHdvcmsnLCBCcm93c2VyTmV0d29ya1NlcnZpY2UpOwogICAgICAgIH0gZWxzZSB7IC8vIG5vZGUKICAgICAgICAgIGFwcGxpY2F0aW9uLnJlZ2lzdGVyKCdzZXJ2aWNlOm5ldHdvcmsnLCBOb2RlTmV0d29ya1NlcnZpY2UpOwogICAgICAgIH0KICAgICAgICAgYXBwbGljYXRpb24uaW5qZWN0KCdyb3V0ZScsICduZXR3b3JrJywgJ3NlcnZpY2U6bmV0d29yaycpOwogICAgICB9OwogICAgICAgZXhwb3J0IGRlZmF1bHQgewogICAgICAgIG5hbWU6ICduZXR3b3JrLXNlcnZpY2UnLAogICAgICAgIGluaXRpYWxpemU6IGluaXRpYWxpemUKICAgICAgfTsKICAgICAgYGBgCiAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3QuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgIC8vIEFuIGV4YW1wbGUgb2YgaG93IHRoZSAoaHlwb3RoZXRpY2FsKSBzZXJ2aWNlIGlzIHVzZWQgaW4gcm91dGVzLgogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBtb2RlbChwYXJhbXMpIHsKICAgICAgICAgIHJldHVybiB0aGlzLm5ldHdvcmsuZmV0Y2goYC9hcGkvcG9zdHMvJHtwYXJhbXMucG9zdF9pZH0uanNvbmApOwogICAgICAgIH0sCiAgICAgICAgIGFmdGVyTW9kZWwocG9zdCkgewogICAgICAgICAgaWYgKHBvc3QuaXNFeHRlcm5hbENvbnRlbnQpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMubmV0d29yay5mZXRjaChgL2FwaS9leHRlcm5hbC8/dXJsPSR7cG9zdC5leHRlcm5hbFVSTH1gKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBwb3N0OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgamF2YXNjcmlwdAogICAgICAvLyBGaW5hbGx5LCBwdXQgYWxsIHRoZSBwaWVjZXMgdG9nZXRoZXIKICAgICAgIGZ1bmN0aW9uIGRpc2NvdmVyUmVzb3VyY2VzRm9yKHVybCkgewogICAgICAgIHJldHVybiBNeUFwcC52aXNpdCh1cmwsIHsgaXNCcm93c2VyOiBmYWxzZSwgc2hvdWxkUmVuZGVyOiBmYWxzZSB9KS50aGVuKGluc3RhbmNlID0+IHsKICAgICAgICAgIGxldCBuZXR3b3JrU2VydmljZSA9IGluc3RhbmNlLmxvb2t1cCgnc2VydmljZTpuZXR3b3JrJyk7CiAgICAgICAgICByZXR1cm4gbmV0d29ya1NlcnZpY2UucmVxdWVzdHM7IC8vID0+IHsgIi9hcGkvcG9zdHMvMTIzLmpzb24iOiAiLi4uIiB9CiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgdmlzaXQKICAgICAgQHBhcmFtIHVybCB7U3RyaW5nfSBUaGUgaW5pdGlhbCBVUkwgdG8gbmF2aWdhdGUgdG8KICAgICAgQHBhcmFtIG9wdGlvbnMge0FwcGxpY2F0aW9uSW5zdGFuY2UuQm9vdE9wdGlvbnN9CiAgICAgIEByZXR1cm4ge1Byb21pc2U8QXBwbGljYXRpb25JbnN0YW5jZSwgRXJyb3I+fQogICAgKi8KICAgIHZpc2l0OiBmdW5jdGlvbiB2aXNpdCh1cmwsIG9wdGlvbnMpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHJldHVybiB0aGlzLmJvb3QoKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgaW5zdGFuY2UgPSBfdGhpcy5idWlsZEluc3RhbmNlKCk7CgogICAgICAgIHJldHVybiBpbnN0YW5jZS5ib290KG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuIGluc3RhbmNlLnZpc2l0KHVybCk7CiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7CiAgICAgICAgICAoMCwgX3J1bmxvb3AucnVuKShpbnN0YW5jZSwgJ2Rlc3Ryb3knKTsKICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0KICB9KTsKCiAgQXBwbGljYXRpb24ucmVvcGVuQ2xhc3MoewogICAgLyoqCiAgICAgIFRoaXMgY3JlYXRlcyBhIHJlZ2lzdHJ5IHdpdGggdGhlIGRlZmF1bHQgRW1iZXIgbmFtaW5nIGNvbnZlbnRpb25zLgogICAgICAgSXQgYWxzbyBjb25maWd1cmVzIHRoZSByZWdpc3RyeToKICAgICAgICogcmVnaXN0ZXJlZCB2aWV3cyBhcmUgY3JlYXRlZCBldmVyeSB0aW1lIHRoZXkgYXJlIGxvb2tlZCB1cCAodGhleSBhcmUKICAgICAgICBub3Qgc2luZ2xldG9ucykKICAgICAgKiByZWdpc3RlcmVkIHRlbXBsYXRlcyBhcmUgbm90IGZhY3RvcmllczsgdGhlIHJlZ2lzdGVyZWQgdmFsdWUgaXMKICAgICAgICByZXR1cm5lZCBkaXJlY3RseS4KICAgICAgKiB0aGUgcm91dGVyIHJlY2VpdmVzIHRoZSBhcHBsaWNhdGlvbiBhcyBpdHMgYG5hbWVzcGFjZWAgcHJvcGVydHkKICAgICAgKiBhbGwgY29udHJvbGxlcnMgcmVjZWl2ZSB0aGUgcm91dGVyIGFzIHRoZWlyIGB0YXJnZXRgIGFuZCBgY29udHJvbGxlcnNgCiAgICAgICAgcHJvcGVydGllcwogICAgICAqIGFsbCBjb250cm9sbGVycyByZWNlaXZlIHRoZSBhcHBsaWNhdGlvbiBhcyB0aGVpciBgbmFtZXNwYWNlYCBwcm9wZXJ0eQogICAgICAqIHRoZSBhcHBsaWNhdGlvbiB2aWV3IHJlY2VpdmVzIHRoZSBhcHBsaWNhdGlvbiBjb250cm9sbGVyIGFzIGl0cwogICAgICAgIGBjb250cm9sbGVyYCBwcm9wZXJ0eQogICAgICAqIHRoZSBhcHBsaWNhdGlvbiB2aWV3IHJlY2VpdmVzIHRoZSBhcHBsaWNhdGlvbiB0ZW1wbGF0ZSBhcyBpdHMKICAgICAgICBgZGVmYXVsdFRlbXBsYXRlYCBwcm9wZXJ0eQogICAgICAgQG1ldGhvZCBidWlsZFJlZ2lzdHJ5CiAgICAgIEBzdGF0aWMKICAgICAgQHBhcmFtIHtBcHBsaWNhdGlvbn0gbmFtZXNwYWNlIHRoZSBhcHBsaWNhdGlvbiBmb3Igd2hpY2ggdG8KICAgICAgICBidWlsZCB0aGUgcmVnaXN0cnkKICAgICAgQHJldHVybiB7RW1iZXIuUmVnaXN0cnl9IHRoZSBidWlsdCByZWdpc3RyeQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGJ1aWxkUmVnaXN0cnk6IGZ1bmN0aW9uIGJ1aWxkUmVnaXN0cnkoKSB7CiAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnMKICAgICAgdmFyIHJlZ2lzdHJ5ID0gdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIGNvbW1vblNldHVwUmVnaXN0cnkocmVnaXN0cnkpOwogICAgICAoMCwgX2dsaW1tZXIuc2V0dXBBcHBsaWNhdGlvblJlZ2lzdHJ5KShyZWdpc3RyeSk7CiAgICAgIHJldHVybiByZWdpc3RyeTsKICAgIH0KICB9KTsKCiAgZnVuY3Rpb24gY29tbW9uU2V0dXBSZWdpc3RyeShyZWdpc3RyeSkgewogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ3JvdXRlcjptYWluJywgX3JvdXRpbmcuUm91dGVyLmV4dGVuZCgpKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCctdmlldy1yZWdpc3RyeTptYWluJywgewogICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgICByZXR1cm4gKDAsIF91dGlscy5kaWN0aW9uYXJ5KShudWxsKTsKICAgICAgfQogICAgfSk7CiAgICByZWdpc3RyeS5yZWdpc3Rlcigncm91dGU6YmFzaWMnLCBfcm91dGluZy5Sb3V0ZSk7CiAgICByZWdpc3RyeS5yZWdpc3RlcignZXZlbnRfZGlzcGF0Y2hlcjptYWluJywgX3ZpZXdzLkV2ZW50RGlzcGF0Y2hlcik7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3JvdXRlcjptYWluJywgJ25hbWVzcGFjZScsICdhcHBsaWNhdGlvbjptYWluJyk7CiAgICByZWdpc3RyeS5yZWdpc3RlcignbG9jYXRpb246YXV0bycsIF9yb3V0aW5nLkF1dG9Mb2NhdGlvbik7CiAgICByZWdpc3RyeS5yZWdpc3RlcignbG9jYXRpb246aGFzaCcsIF9yb3V0aW5nLkhhc2hMb2NhdGlvbik7CiAgICByZWdpc3RyeS5yZWdpc3RlcignbG9jYXRpb246aGlzdG9yeScsIF9yb3V0aW5nLkhpc3RvcnlMb2NhdGlvbik7CiAgICByZWdpc3RyeS5yZWdpc3RlcignbG9jYXRpb246bm9uZScsIF9yb3V0aW5nLk5vbmVMb2NhdGlvbik7CiAgICByZWdpc3RyeS5yZWdpc3RlcigoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdCgpKSwgewogICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgICByZXR1cm4gbmV3IF9yb3V0aW5nLkJ1Y2tldENhY2hlKCk7CiAgICAgIH0KICAgIH0pOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ3NlcnZpY2U6cm91dGVyJywgX3JvdXRpbmcuUm91dGVyU2VydmljZSk7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3NlcnZpY2U6cm91dGVyJywgJ19yb3V0ZXInLCAncm91dGVyOm1haW4nKTsKICB9CgogIGZ1bmN0aW9uIHJlZ2lzdGVyTGlicmFyaWVzKCkgewogICAgaWYgKCFsaWJyYXJpZXNSZWdpc3RlcmVkKSB7CiAgICAgIGxpYnJhcmllc1JlZ2lzdGVyZWQgPSB0cnVlOwoKICAgICAgaWYgKF9kZXByZWNhdGVkRmVhdHVyZXMuSlFVRVJZX0lOVEVHUkFUSU9OICYmIF9icm93c2VyRW52aXJvbm1lbnQuaGFzRE9NICYmICFfdmlld3MualF1ZXJ5RGlzYWJsZWQpIHsKICAgICAgICBfbWV0YWwubGlicmFyaWVzLnJlZ2lzdGVyQ29yZUxpYnJhcnkoJ2pRdWVyeScsICgwLCBfdmlld3MualF1ZXJ5KSgpLmpxdWVyeSk7CiAgICAgIH0KICAgIH0KICB9CgogIHZhciBfZGVmYXVsdCA9IEFwcGxpY2F0aW9uOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2FwcGxpY2F0aW9uL2xpYi9sYXp5X2xvYWQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZW52aXJvbm1lbnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvYnJvd3Nlci1lbnZpcm9ubWVudCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbnZpcm9ubWVudCwgX2Jyb3dzZXJFbnZpcm9ubWVudCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMub25Mb2FkID0gb25Mb2FkOwogIF9leHBvcnRzLnJ1bkxvYWRIb29rcyA9IHJ1bkxvYWRIb29rczsKICBfZXhwb3J0cy5fbG9hZGVkID0gdm9pZCAwOwoKICAvKmdsb2JhbHMgQ3VzdG9tRXZlbnQgKi8KCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci9hcHBsaWNhdGlvbgogICovCiAgdmFyIGxvYWRIb29rcyA9IF9lbnZpcm9ubWVudC5FTlYuRU1CRVJfTE9BRF9IT09LUyB8fCB7fTsKICB2YXIgbG9hZGVkID0ge307CiAgdmFyIF9sb2FkZWQgPSBsb2FkZWQ7CiAgLyoqCiAgICBEZXRlY3RzIHdoZW4gYSBzcGVjaWZpYyBwYWNrYWdlIG9mIEVtYmVyIChlLmcuICdBcHBsaWNhdGlvbicpCiAgICBoYXMgZnVsbHkgbG9hZGVkIGFuZCBpcyBhdmFpbGFibGUgZm9yIGV4dGVuc2lvbi4KICAKICAgIFRoZSBwcm92aWRlZCBgY2FsbGJhY2tgIHdpbGwgYmUgY2FsbGVkIHdpdGggdGhlIGBuYW1lYCBwYXNzZWQKICAgIHJlc29sdmVkIGZyb20gYSBzdHJpbmcgaW50byB0aGUgb2JqZWN0OgogIAogICAgYGBgIGphdmFzY3JpcHQKICAgIGltcG9ydCB7IG9uTG9hZCB9IGZyb20gJ0BlbWJlci9hcHBsaWNhdGlvbic7CiAgCiAgICBvbkxvYWQoJ0VtYmVyLkFwcGxpY2F0aW9uJyBmdW5jdGlvbihoYmFycykgewogICAgICBoYmFycy5yZWdpc3RlckhlbHBlciguLi4pOwogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2Qgb25Mb2FkCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9hcHBsaWNhdGlvbgogICAgQHBhcmFtIG5hbWUge1N0cmluZ30gbmFtZSBvZiBob29rCiAgICBAcGFyYW0gY2FsbGJhY2sge0Z1bmN0aW9ufSBjYWxsYmFjayB0byBiZSBjYWxsZWQKICAgIEBwcml2YXRlCiAgKi8KCiAgX2V4cG9ydHMuX2xvYWRlZCA9IF9sb2FkZWQ7CgogIGZ1bmN0aW9uIG9uTG9hZChuYW1lLCBjYWxsYmFjaykgewogICAgdmFyIG9iamVjdCA9IGxvYWRlZFtuYW1lXTsKICAgIGxvYWRIb29rc1tuYW1lXSA9IGxvYWRIb29rc1tuYW1lXSB8fCBbXTsKICAgIGxvYWRIb29rc1tuYW1lXS5wdXNoKGNhbGxiYWNrKTsKCiAgICBpZiAob2JqZWN0KSB7CiAgICAgIGNhbGxiYWNrKG9iamVjdCk7CiAgICB9CiAgfQogIC8qKgogICAgQ2FsbGVkIHdoZW4gYW4gRW1iZXIuanMgcGFja2FnZSAoZS5nIEFwcGxpY2F0aW9uKSBoYXMgZmluaXNoZWQKICAgIGxvYWRpbmcuIFRyaWdnZXJzIGFueSBjYWxsYmFja3MgcmVnaXN0ZXJlZCBmb3IgdGhpcyBldmVudC4KICAKICAgIEBtZXRob2QgcnVuTG9hZEhvb2tzCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9hcHBsaWNhdGlvbgogICAgQHBhcmFtIG5hbWUge1N0cmluZ30gbmFtZSBvZiBob29rCiAgICBAcGFyYW0gb2JqZWN0IHtPYmplY3R9IG9iamVjdCB0byBwYXNzIHRvIGNhbGxiYWNrcwogICAgQHByaXZhdGUKICAqLwoKCiAgZnVuY3Rpb24gcnVuTG9hZEhvb2tzKG5hbWUsIG9iamVjdCkgewogICAgbG9hZGVkW25hbWVdID0gb2JqZWN0OwoKICAgIGlmIChfYnJvd3NlckVudmlyb25tZW50LndpbmRvdyAmJiB0eXBlb2YgQ3VzdG9tRXZlbnQgPT09ICdmdW5jdGlvbicpIHsKICAgICAgdmFyIGV2ZW50ID0gbmV3IEN1c3RvbUV2ZW50KG5hbWUsIHsKICAgICAgICBkZXRhaWw6IG9iamVjdCwKICAgICAgICBuYW1lOiBuYW1lCiAgICAgIH0pOwoKICAgICAgX2Jyb3dzZXJFbnZpcm9ubWVudC53aW5kb3cuZGlzcGF0Y2hFdmVudChldmVudCk7CiAgICB9CgogICAgaWYgKGxvYWRIb29rc1tuYW1lXSkgewogICAgICBsb2FkSG9va3NbbmFtZV0uZm9yRWFjaChmdW5jdGlvbiAoY2FsbGJhY2spIHsKICAgICAgICByZXR1cm4gY2FsbGJhY2sob2JqZWN0KTsKICAgICAgfSk7CiAgICB9CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvYXBwbGljYXRpb24vbGliL3ZhbGlkYXRlLXR5cGUiLCBbImV4cG9ydHMiLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlYnVnKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdmFsaWRhdGVUeXBlOwogIHZhciBWQUxJREFURURfVFlQRVMgPSB7CiAgICByb3V0ZTogWydhc3NlcnQnLCAnaXNSb3V0ZUZhY3RvcnknLCAnRW1iZXIuUm91dGUnXSwKICAgIGNvbXBvbmVudDogWydkZXByZWNhdGUnLCAnaXNDb21wb25lbnRGYWN0b3J5JywgJ0VtYmVyLkNvbXBvbmVudCddLAogICAgdmlldzogWydkZXByZWNhdGUnLCAnaXNWaWV3RmFjdG9yeScsICdFbWJlci5WaWV3J10sCiAgICBzZXJ2aWNlOiBbJ2RlcHJlY2F0ZScsICdpc1NlcnZpY2VGYWN0b3J5JywgJ0VtYmVyLlNlcnZpY2UnXQogIH07CgogIGZ1bmN0aW9uIHZhbGlkYXRlVHlwZShyZXNvbHZlZFR5cGUsIHBhcnNlZE5hbWUpIHsKICAgIHZhciB2YWxpZGF0aW9uQXR0cmlidXRlcyA9IFZBTElEQVRFRF9UWVBFU1twYXJzZWROYW1lLnR5cGVdOwoKICAgIGlmICghdmFsaWRhdGlvbkF0dHJpYnV0ZXMpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBmYWN0b3J5RmxhZyA9IHZhbGlkYXRpb25BdHRyaWJ1dGVzWzFdLAogICAgICAgIGV4cGVjdGVkVHlwZSA9IHZhbGlkYXRpb25BdHRyaWJ1dGVzWzJdOwogICAgKGZhbHNlICYmICEoQm9vbGVhbihyZXNvbHZlZFR5cGVbZmFjdG9yeUZsYWddKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJFeHBlY3RlZCAiICsgcGFyc2VkTmFtZS5mdWxsTmFtZSArICIgdG8gcmVzb2x2ZSB0byBhbiAiICsgZXhwZWN0ZWRUeXBlICsgIiBidXQgIiArICgiaW5zdGVhZCBpdCB3YXMgIiArIHJlc29sdmVkVHlwZSArICIuIiksIEJvb2xlYW4ocmVzb2x2ZWRUeXBlW2ZhY3RvcnlGbGFnXSkpKTsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci9jYW5hcnktZmVhdHVyZXMvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZW52aXJvbm1lbnQiLCAiQGVtYmVyL3BvbHlmaWxscyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbnZpcm9ubWVudCwgX3BvbHlmaWxscykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuaXNFbmFibGVkID0gaXNFbmFibGVkOwogIF9leHBvcnRzLkVNQkVSX0dMSU1NRVJfU0VUX0NPTVBPTkVOVF9URU1QTEFURSA9IF9leHBvcnRzLkVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQgPSBfZXhwb3J0cy5FTUJFUl9DVVNUT01fQ09NUE9ORU5UX0FSR19QUk9YWSA9IF9leHBvcnRzLkVNQkVSX0dMSU1NRVJfRk5fSEVMUEVSID0gX2V4cG9ydHMuRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUID0gX2V4cG9ydHMuRU1CRVJfR0xJTU1FUl9BTkdMRV9CUkFDS0VUX0JVSUxUX0lOUyA9IF9leHBvcnRzLkVNQkVSX0dMSU1NRVJfRk9SV0FSRF9NT0RJRklFUlNfV0lUSF9TUExBVFRSSUJVVEVTID0gX2V4cG9ydHMuRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTID0gX2V4cG9ydHMuRU1CRVJfTU9EVUxFX1VOSUZJQ0FUSU9OID0gX2V4cG9ydHMuRU1CRVJfSU1QUk9WRURfSU5TVFJVTUVOVEFUSU9OID0gX2V4cG9ydHMuRU1CRVJfTElCUkFSSUVTX0lTUkVHSVNURVJFRCA9IF9leHBvcnRzLkZFQVRVUkVTID0gX2V4cG9ydHMuREVGQVVMVF9GRUFUVVJFUyA9IHZvaWQgMDsKCiAgLyoqCiAgICBTZXQgYEVtYmVyRU5WLkZFQVRVUkVTYCBpbiB5b3VyIGFwcGxpY2F0aW9uJ3MgYGNvbmZpZy9lbnZpcm9ubWVudC5qc2AgZmlsZQogICAgdG8gZW5hYmxlIGNhbmFyeSBmZWF0dXJlcyBpbiB5b3VyIGFwcGxpY2F0aW9uLgogIAogICAgU2VlIHRoZSBbZmVhdHVyZSBmbGFnIGd1aWRlXShodHRwczovL2d1aWRlcy5lbWJlcmpzLmNvbS9yZWxlYXNlL2NvbmZpZ3VyaW5nLWVtYmVyL2ZlYXR1cmUtZmxhZ3MvKQogICAgZm9yIG1vcmUgZGV0YWlscy4KICAKICAgIEBtb2R1bGUgQGVtYmVyL2NhbmFyeS1mZWF0dXJlcwogICAgQHB1YmxpYwogICovCiAgdmFyIERFRkFVTFRfRkVBVFVSRVMgPSB7CiAgICBFTUJFUl9MSUJSQVJJRVNfSVNSRUdJU1RFUkVEOiBmYWxzZSwKICAgIEVNQkVSX0lNUFJPVkVEX0lOU1RSVU1FTlRBVElPTjogZmFsc2UsCiAgICBFTUJFUl9NT0RVTEVfVU5JRklDQVRJT046IGZhbHNlLAogICAgRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTOiB0cnVlLAogICAgRU1CRVJfR0xJTU1FUl9GT1JXQVJEX01PRElGSUVSU19XSVRIX1NQTEFUVFJJQlVURVM6IHRydWUsCiAgICBFTUJFUl9HTElNTUVSX0FOR0xFX0JSQUNLRVRfQlVJTFRfSU5TOiB0cnVlLAogICAgRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUOiB0cnVlLAogICAgRU1CRVJfR0xJTU1FUl9GTl9IRUxQRVI6IHRydWUsCiAgICBFTUJFUl9DVVNUT01fQ09NUE9ORU5UX0FSR19QUk9YWTogdHJ1ZSwKICAgIEVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQ6IHRydWUsCiAgICBFTUJFUl9HTElNTUVSX1NFVF9DT01QT05FTlRfVEVNUExBVEU6IHRydWUKICB9OwogIC8qKgogICAgVGhlIGhhc2ggb2YgZW5hYmxlZCBDYW5hcnkgZmVhdHVyZXMuIEFkZCB0byB0aGlzLCBhbnkgY2FuYXJ5IGZlYXR1cmVzCiAgICBiZWZvcmUgY3JlYXRpbmcgeW91ciBhcHBsaWNhdGlvbi4KICAKICAgIEBjbGFzcyBGRUFUVVJFUwogICAgQHN0YXRpYwogICAgQHNpbmNlIDEuMS4wCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMuREVGQVVMVF9GRUFUVVJFUyA9IERFRkFVTFRfRkVBVFVSRVM7CiAgdmFyIEZFQVRVUkVTID0gKDAsIF9wb2x5ZmlsbHMuYXNzaWduKShERUZBVUxUX0ZFQVRVUkVTLCBfZW52aXJvbm1lbnQuRU5WLkZFQVRVUkVTKTsKICAvKioKICAgIERldGVybWluZSB3aGV0aGVyIHRoZSBzcGVjaWZpZWQgYGZlYXR1cmVgIGlzIGVuYWJsZWQuIFVzZWQgYnkgRW1iZXIncwogICAgYnVpbGQgdG9vbHMgdG8gZXhjbHVkZSBleHBlcmltZW50YWwgZmVhdHVyZXMgZnJvbSBiZXRhL3N0YWJsZSBidWlsZHMuCiAgCiAgICBZb3UgY2FuIGRlZmluZSB0aGUgZm9sbG93aW5nIGNvbmZpZ3VyYXRpb24gb3B0aW9uczoKICAKICAgICogYEVtYmVyRU5WLkVOQUJMRV9PUFRJT05BTF9GRUFUVVJFU2AgLSBlbmFibGUgYW55IGZlYXR1cmVzIHRoYXQgaGF2ZSBub3QgYmVlbiBleHBsaWNpdGx5CiAgICAgIGVuYWJsZWQvZGlzYWJsZWQuCiAgCiAgICBAbWV0aG9kIGlzRW5hYmxlZAogICAgQHBhcmFtIHtTdHJpbmd9IGZlYXR1cmUgVGhlIGZlYXR1cmUgdG8gY2hlY2sKICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICBAc2luY2UgMS4xLjAKICAgIEBwdWJsaWMKICAqLwoKICBfZXhwb3J0cy5GRUFUVVJFUyA9IEZFQVRVUkVTOwoKICBmdW5jdGlvbiBpc0VuYWJsZWQoZmVhdHVyZSkgewogICAgdmFyIGZlYXR1cmVWYWx1ZSA9IEZFQVRVUkVTW2ZlYXR1cmVdOwoKICAgIGlmIChmZWF0dXJlVmFsdWUgPT09IHRydWUgfHwgZmVhdHVyZVZhbHVlID09PSBmYWxzZSkgewogICAgICByZXR1cm4gZmVhdHVyZVZhbHVlOwogICAgfSBlbHNlIGlmIChfZW52aXJvbm1lbnQuRU5WLkVOQUJMRV9PUFRJT05BTF9GRUFUVVJFUykgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGZlYXR1cmVWYWx1ZSh2YWx1ZSkgewogICAgaWYgKF9lbnZpcm9ubWVudC5FTlYuRU5BQkxFX09QVElPTkFMX0ZFQVRVUkVTICYmIHZhbHVlID09PSBudWxsKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIHJldHVybiB2YWx1ZTsKICB9CgogIHZhciBFTUJFUl9MSUJSQVJJRVNfSVNSRUdJU1RFUkVEID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLkVNQkVSX0xJQlJBUklFU19JU1JFR0lTVEVSRUQpOwogIF9leHBvcnRzLkVNQkVSX0xJQlJBUklFU19JU1JFR0lTVEVSRUQgPSBFTUJFUl9MSUJSQVJJRVNfSVNSRUdJU1RFUkVEOwogIHZhciBFTUJFUl9JTVBST1ZFRF9JTlNUUlVNRU5UQVRJT04gPSBmZWF0dXJlVmFsdWUoRkVBVFVSRVMuRU1CRVJfSU1QUk9WRURfSU5TVFJVTUVOVEFUSU9OKTsKICBfZXhwb3J0cy5FTUJFUl9JTVBST1ZFRF9JTlNUUlVNRU5UQVRJT04gPSBFTUJFUl9JTVBST1ZFRF9JTlNUUlVNRU5UQVRJT047CiAgdmFyIEVNQkVSX01PRFVMRV9VTklGSUNBVElPTiA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5FTUJFUl9NT0RVTEVfVU5JRklDQVRJT04pOwogIF9leHBvcnRzLkVNQkVSX01PRFVMRV9VTklGSUNBVElPTiA9IEVNQkVSX01PRFVMRV9VTklGSUNBVElPTjsKICB2YXIgRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLkVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyk7CiAgX2V4cG9ydHMuRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTID0gRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTOwogIHZhciBFTUJFUl9HTElNTUVSX0ZPUldBUkRfTU9ESUZJRVJTX1dJVEhfU1BMQVRUUklCVVRFUyA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5FTUJFUl9HTElNTUVSX0ZPUldBUkRfTU9ESUZJRVJTX1dJVEhfU1BMQVRUUklCVVRFUyk7CiAgX2V4cG9ydHMuRU1CRVJfR0xJTU1FUl9GT1JXQVJEX01PRElGSUVSU19XSVRIX1NQTEFUVFJJQlVURVMgPSBFTUJFUl9HTElNTUVSX0ZPUldBUkRfTU9ESUZJRVJTX1dJVEhfU1BMQVRUUklCVVRFUzsKICB2YXIgRU1CRVJfR0xJTU1FUl9BTkdMRV9CUkFDS0VUX0JVSUxUX0lOUyA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5FTUJFUl9HTElNTUVSX0FOR0xFX0JSQUNLRVRfQlVJTFRfSU5TKTsKICBfZXhwb3J0cy5FTUJFUl9HTElNTUVSX0FOR0xFX0JSQUNLRVRfQlVJTFRfSU5TID0gRU1CRVJfR0xJTU1FUl9BTkdMRV9CUkFDS0VUX0JVSUxUX0lOUzsKICB2YXIgRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLkVNQkVSX05BVElWRV9ERUNPUkFUT1JfU1VQUE9SVCk7CiAgX2V4cG9ydHMuRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUID0gRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUOwogIHZhciBFTUJFUl9HTElNTUVSX0ZOX0hFTFBFUiA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5FTUJFUl9HTElNTUVSX0ZOX0hFTFBFUik7CiAgX2V4cG9ydHMuRU1CRVJfR0xJTU1FUl9GTl9IRUxQRVIgPSBFTUJFUl9HTElNTUVSX0ZOX0hFTFBFUjsKICB2YXIgRU1CRVJfQ1VTVE9NX0NPTVBPTkVOVF9BUkdfUFJPWFkgPSBmZWF0dXJlVmFsdWUoRkVBVFVSRVMuRU1CRVJfQ1VTVE9NX0NPTVBPTkVOVF9BUkdfUFJPWFkpOwogIF9leHBvcnRzLkVNQkVSX0NVU1RPTV9DT01QT05FTlRfQVJHX1BST1hZID0gRU1CRVJfQ1VTVE9NX0NPTVBPTkVOVF9BUkdfUFJPWFk7CiAgdmFyIEVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQgPSBmZWF0dXJlVmFsdWUoRkVBVFVSRVMuRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCk7CiAgX2V4cG9ydHMuRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCA9IEVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQ7CiAgdmFyIEVNQkVSX0dMSU1NRVJfU0VUX0NPTVBPTkVOVF9URU1QTEFURSA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5FTUJFUl9HTElNTUVSX1NFVF9DT01QT05FTlRfVEVNUExBVEUpOwogIF9leHBvcnRzLkVNQkVSX0dMSU1NRVJfU0VUX0NPTVBPTkVOVF9URU1QTEFURSA9IEVNQkVSX0dMSU1NRVJfU0VUX0NPTVBPTkVOVF9URU1QTEFURTsKfSk7CmRlZmluZSgiQGVtYmVyL2NvbXBvbmVudC9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9nbGltbWVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2dsaW1tZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkNvbXBvbmVudCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9nbGltbWVyLkNvbXBvbmVudDsKICAgIH0KICB9KTsKfSk7CmRlZmluZSgiQGVtYmVyL2NvbXBvbmVudC90ZW1wbGF0ZS1vbmx5IiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHRlbXBsYXRlT25seUNvbXBvbmVudDsKICBfZXhwb3J0cy5pc1RlbXBsYXRlT25seUNvbXBvbmVudCA9IGlzVGVtcGxhdGVPbmx5Q29tcG9uZW50OwogIF9leHBvcnRzLlRlbXBsYXRlT25seUNvbXBvbmVudCA9IHZvaWQgMDsKCiAgLy8gVGhpcyBpcyBvbmx5IGV4cG9ydGVkIGZvciB0eXBlcywgZG9uJ3QgdXNlIHRoaXMgY2xhc3MgZGlyZWN0bHkKICB2YXIgVGVtcGxhdGVPbmx5Q29tcG9uZW50ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gVGVtcGxhdGVPbmx5Q29tcG9uZW50KG1vZHVsZU5hbWUpIHsKICAgICAgaWYgKG1vZHVsZU5hbWUgPT09IHZvaWQgMCkgewogICAgICAgIG1vZHVsZU5hbWUgPSAnQGVtYmVyL2NvbXBvbmVudC90ZW1wbGF0ZS1vbmx5JzsKICAgICAgfQoKICAgICAgdGhpcy5tb2R1bGVOYW1lID0gbW9kdWxlTmFtZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gVGVtcGxhdGVPbmx5Q29tcG9uZW50LnByb3RvdHlwZTsKCiAgICBfcHJvdG8udG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgcmV0dXJuIHRoaXMubW9kdWxlTmFtZTsKICAgIH07CgogICAgcmV0dXJuIFRlbXBsYXRlT25seUNvbXBvbmVudDsKICB9KCk7CiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci9jb21wb25lbnQvdGVtcGxhdGUtb25seQogICAgQHB1YmxpYwogICovCgogIC8qKgogICAgVGhpcyB1dGlsaXR5IGZ1bmN0aW9uIGlzIHVzZWQgdG8gZGVjbGFyZSBhIGdpdmVuIGNvbXBvbmVudCBoYXMgbm8gYmFja2luZyBjbGFzcy4gV2hlbiB0aGUgcmVuZGVyaW5nIGVuZ2luZSBkZXRlY3RzIHRoaXMgaXQKICAgIGlzIGFibGUgdG8gcGVyZm9ybSBhIG51bWJlciBvZiBvcHRpbWl6YXRpb25zLiBUZW1wbGF0ZXMgdGhhdCBhcmUgYXNzb2NpYXRlZCB3aXRoIGB0ZW1wbGF0ZU9ubHkoKWAgd2lsbCBiZSByZW5kZXJlZCBfYXMgaXNfCiAgICB3aXRob3V0IGFkZGluZyBhIHdyYXBwaW5nIGA8ZGl2PmAgKG9yIGFueSBvZiB0aGUgb3RoZXIgZWxlbWVudCBjdXN0b21pemF0aW9uIGJlaGF2aW9ycyBvZiBbQGVtYmVyL2NvbXBvbmVudF0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9Db21wb25lbnQpKS4KICAgIFNwZWNpZmljYWxseSwgdGhpcyBtZWFucyB0aGF0IHRoZSB0ZW1wbGF0ZSB3aWxsIGJlIHJlbmRlcmVkIGFzICJvdXRlciBIVE1MIi4KICAKICAgIEluIGdlbmVyYWwsIHRoaXMgbWV0aG9kIHdpbGwgYmUgdXNlZCBieSBidWlsZCB0aW1lIHRvb2xpbmcgYW5kIHdvdWxkIG5vdCBiZSBkaXJlY3RseSB3cml0dGVuIGluIGFuIGFwcGxpY2F0aW9uLiBIb3dldmVyLAogICAgYXQgdGltZXMgaXQgbWF5IGJlIHVzZWZ1bCB0byB1c2UgZGlyZWN0bHkgdG8gbGV2ZXJhZ2UgdGhlICJvdXRlciBIVE1MIiBzZW1hbnRpY3MgbWVudGlvbmVkIGFib3ZlLiBGb3IgZXhhbXBsZSwgaWYgYW4gYWRkb24gd291bGQgbGlrZQogICAgdG8gdXNlIHRoZXNlIHNlbWFudGljcyBmb3IgaXRzIHRlbXBsYXRlcyBidXQgY2Fubm90IGJlIGNlcnRhaW4gaXQgd2lsbCBvbmx5IGJlIGNvbnN1bWVkIGJ5IGFwcGxpY2F0aW9ucyB0aGF0IGhhdmUgZW5hYmxlZCB0aGUKICAgIGB0ZW1wbGF0ZS1vbmx5LWdsaW1tZXItY29tcG9uZW50c2Agb3B0aW9uYWwgZmVhdHVyZS4KICAKICAgIEBleGFtcGxlCiAgCiAgICBgYGBqcwogICAgaW1wb3J0IHRlbXBsYXRlT25seSBmcm9tICdAZW1iZXIvY29tcG9uZW50L3RlbXBsYXRlLW9ubHknOwogIAogICAgZXhwb3J0IGRlZmF1bHQgdGVtcGxhdGVPbmx5KCk7CiAgICBgYGAKICAKICAgIEBwdWJsaWMKICAgIEBtZXRob2QgdGVtcGxhdGVPbmx5CiAgICBAcGFyYW0ge1N0cmluZ30gbW9kdWxlTmFtZSB0aGUgbW9kdWxlIG5hbWUgdGhhdCB0aGUgdGVtcGxhdGUgb25seSBjb21wb25lbnQgcmVwcmVzZW50cywgdGhpcyB3aWxsIGJlIHVzZWQgZm9yIGRlYnVnZ2luZyBwdXJwb3NlcwogICAgQGNhdGVnb3J5IEVNQkVSX0dMSU1NRVJfU0VUX0NPTVBPTkVOVF9URU1QTEFURQogICovCgoKICBfZXhwb3J0cy5UZW1wbGF0ZU9ubHlDb21wb25lbnQgPSBUZW1wbGF0ZU9ubHlDb21wb25lbnQ7CgogIGZ1bmN0aW9uIHRlbXBsYXRlT25seUNvbXBvbmVudChtb2R1bGVOYW1lKSB7CiAgICByZXR1cm4gbmV3IFRlbXBsYXRlT25seUNvbXBvbmVudChtb2R1bGVOYW1lKTsKICB9CgogIGZ1bmN0aW9uIGlzVGVtcGxhdGVPbmx5Q29tcG9uZW50KGNvbXBvbmVudCkgewogICAgcmV0dXJuIGNvbXBvbmVudCBpbnN0YW5jZW9mIFRlbXBsYXRlT25seUNvbXBvbmVudDsKICB9Cn0pOwpkZWZpbmUoIkBlbWJlci9jb250cm9sbGVyL2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL3J1bnRpbWUiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2NvbnRyb2xsZXIvbGliL2NvbnRyb2xsZXJfbWl4aW4iXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfcnVudGltZSwgX21ldGFsLCBfY29udHJvbGxlcl9taXhpbikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuaW5qZWN0ID0gaW5qZWN0OwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgQGVtYmVyL2NvbnRyb2xsZXIKICAqLwoKICAvKioKICAgIEBjbGFzcyBDb250cm9sbGVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHVzZXMgRW1iZXIuQ29udHJvbGxlck1peGluCiAgICBAcHVibGljCiAgKi8KICB2YXIgQ29udHJvbGxlciA9IF9ydW50aW1lLkZyYW1ld29ya09iamVjdC5leHRlbmQoX2NvbnRyb2xsZXJfbWl4aW4uZGVmYXVsdCk7CgogIGlmICh0cnVlCiAgLyogRU1CRVJfRlJBTUVXT1JLX09CSkVDVF9PV05FUl9BUkdVTUVOVCAqLwogICkgewogICAgICAoMCwgX3J1bnRpbWUuc2V0RnJhbWV3b3JrQ2xhc3MpKENvbnRyb2xsZXIpOwogICAgfQogIC8qKgogICAgQ3JlYXRlcyBhIHByb3BlcnR5IHRoYXQgbGF6aWx5IGxvb2tzIHVwIGFub3RoZXIgY29udHJvbGxlciBpbiB0aGUgY29udGFpbmVyLgogICAgQ2FuIG9ubHkgYmUgdXNlZCB3aGVuIGRlZmluaW5nIGFub3RoZXIgY29udHJvbGxlci4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBhcHAvY29udHJvbGxlcnMvcG9zdC5qcwogICAgaW1wb3J0IENvbnRyb2xsZXIsIHsKICAgICAgaW5qZWN0IGFzIGNvbnRyb2xsZXIKICAgIH0gZnJvbSAnQGVtYmVyL2NvbnRyb2xsZXInOwogIAogICAgZXhwb3J0IGRlZmF1bHQgY2xhc3MgUG9zdENvbnRyb2xsZXIgZXh0ZW5kcyBDb250cm9sbGVyIHsKICAgICAgQGNvbnRyb2xsZXIgcG9zdHM7CiAgICB9CiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGFwcC9jb250cm9sbGVycy9wb3N0LmpzCiAgICBpbXBvcnQgQ29udHJvbGxlciwgewogICAgICBpbmplY3QgYXMgY29udHJvbGxlcgogICAgfSBmcm9tICdAZW1iZXIvY29udHJvbGxlcic7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBDb250cm9sbGVyLmV4dGVuZCh7CiAgICAgIHBvc3RzOiBjb250cm9sbGVyKCkKICAgIH0pOwogICAgYGBgCiAgCiAgICBUaGlzIGV4YW1wbGUgd2lsbCBjcmVhdGUgYSBgcG9zdHNgIHByb3BlcnR5IG9uIHRoZSBgcG9zdGAgY29udHJvbGxlciB0aGF0CiAgICBsb29rcyB1cCB0aGUgYHBvc3RzYCBjb250cm9sbGVyIGluIHRoZSBjb250YWluZXIsIG1ha2luZyBpdCBlYXN5IHRvIHJlZmVyZW5jZQogICAgb3RoZXIgY29udHJvbGxlcnMuCiAgCiAgICBAbWV0aG9kIGluamVjdAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvY29udHJvbGxlcgogICAgQHNpbmNlIDEuMTAuMAogICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgKG9wdGlvbmFsKSBuYW1lIG9mIHRoZSBjb250cm9sbGVyIHRvIGluamVjdCwgZGVmYXVsdHMgdG8KICAgICAgICAgICB0aGUgcHJvcGVydHkncyBuYW1lCiAgICBAcmV0dXJuIHtDb21wdXRlZERlY29yYXRvcn0gaW5qZWN0aW9uIGRlY29yYXRvciBpbnN0YW5jZQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBpbmplY3QoKSB7CiAgICByZXR1cm4gX21ldGFsLmluamVjdC5hcHBseSh2b2lkIDAsIFsnY29udHJvbGxlciddLmNvbmNhdChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7CiAgfQoKICB2YXIgX2RlZmF1bHQgPSBDb250cm9sbGVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2NvbnRyb2xsZXIvbGliL2NvbnRyb2xsZXJfbWl4aW4iLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX3J1bnRpbWUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogIEBtb2R1bGUgZW1iZXIKICAqLwoKICAvKioKICAgIEBjbGFzcyBDb250cm9sbGVyTWl4aW4KICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEB1c2VzIEVtYmVyLkFjdGlvbkhhbmRsZXIKICAgIEBwcml2YXRlCiAgKi8KICB2YXIgX2RlZmF1bHQgPSBfbWV0YWwuTWl4aW4uY3JlYXRlKF9ydW50aW1lLkFjdGlvbkhhbmRsZXIsIHsKICAgIC8qIGR1Y2t0eXBlIGFzIGEgY29udHJvbGxlciAqLwogICAgaXNDb250cm9sbGVyOiB0cnVlLAoKICAgIC8qKgogICAgICBUaGUgb2JqZWN0IHRvIHdoaWNoIGFjdGlvbnMgZnJvbSB0aGUgdmlldyBzaG91bGQgYmUgc2VudC4KICAgICAgIEZvciBleGFtcGxlLCB3aGVuIGEgSGFuZGxlYmFycyB0ZW1wbGF0ZSB1c2VzIHRoZSBge3thY3Rpb259fWAgaGVscGVyLAogICAgICBpdCB3aWxsIGF0dGVtcHQgdG8gc2VuZCB0aGUgYWN0aW9uIHRvIHRoZSB2aWV3J3MgY29udHJvbGxlcidzIGB0YXJnZXRgLgogICAgICAgQnkgZGVmYXVsdCwgdGhlIHZhbHVlIG9mIHRoZSB0YXJnZXQgcHJvcGVydHkgaXMgc2V0IHRvIHRoZSByb3V0ZXIsIGFuZAogICAgICBpcyBpbmplY3RlZCB3aGVuIGEgY29udHJvbGxlciBpcyBpbnN0YW50aWF0ZWQuIFRoaXMgaW5qZWN0aW9uIGlzIGFwcGxpZWQKICAgICAgYXMgcGFydCBvZiB0aGUgYXBwbGljYXRpb24ncyBpbml0aWFsaXphdGlvbiBwcm9jZXNzLiBJbiBtb3N0IGNhc2VzIHRoZQogICAgICBgdGFyZ2V0YCBwcm9wZXJ0eSB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgc2V0IHRvIHRoZSBsb2dpY2FsIGNvbnN1bWVyIG9mCiAgICAgIGFjdGlvbnMgZm9yIHRoZSBjb250cm9sbGVyLgogICAgICAgQHByb3BlcnR5IHRhcmdldAogICAgICBAZGVmYXVsdCBudWxsCiAgICAgIEBwdWJsaWMKICAgICovCiAgICB0YXJnZXQ6IG51bGwsCiAgICBzdG9yZTogbnVsbCwKCiAgICAvKioKICAgICAgVGhlIGNvbnRyb2xsZXIncyBjdXJyZW50IG1vZGVsLiBXaGVuIHJldHJpZXZpbmcgb3IgbW9kaWZ5aW5nIGEgY29udHJvbGxlcidzCiAgICAgIG1vZGVsLCB0aGlzIHByb3BlcnR5IHNob3VsZCBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGBjb250ZW50YCBwcm9wZXJ0eS4KICAgICAgIEBwcm9wZXJ0eSBtb2RlbAogICAgICBAcHVibGljCiAgICAqLwogICAgbW9kZWw6IHRydWUKICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgPyAoMCwgX21ldGFsLnRyYWNrZWQpKCkgOiBudWxsCiAgfSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2RlYnVnL2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL2Jyb3dzZXItZW52aXJvbm1lbnQiLCAiQGVtYmVyL2Vycm9yIiwgIkBlbWJlci9kZWJ1Zy9saWIvZGVwcmVjYXRlIiwgIkBlbWJlci9kZWJ1Zy9saWIvdGVzdGluZyIsICJAZW1iZXIvZGVidWcvbGliL3dhcm4iXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfYnJvd3NlckVudmlyb25tZW50LCBfZXJyb3IsIF9kZXByZWNhdGUyLCBfdGVzdGluZywgX3dhcm4yKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJyZWdpc3RlckRlcHJlY2F0aW9uSGFuZGxlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9kZXByZWNhdGUyLnJlZ2lzdGVySGFuZGxlcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJpc1Rlc3RpbmciLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfdGVzdGluZy5pc1Rlc3Rpbmc7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0VGVzdGluZyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF90ZXN0aW5nLnNldFRlc3Rpbmc7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAicmVnaXN0ZXJXYXJuSGFuZGxlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF93YXJuMi5yZWdpc3RlckhhbmRsZXI7CiAgICB9CiAgfSk7CiAgX2V4cG9ydHMuX3dhcm5JZlVzaW5nU3RyaXBwZWRGZWF0dXJlRmxhZ3MgPSBfZXhwb3J0cy5nZXREZWJ1Z0Z1bmN0aW9uID0gX2V4cG9ydHMuc2V0RGVidWdGdW5jdGlvbiA9IF9leHBvcnRzLmRlcHJlY2F0ZUZ1bmMgPSBfZXhwb3J0cy5ydW5JbkRlYnVnID0gX2V4cG9ydHMuZGVidWdGcmVlemUgPSBfZXhwb3J0cy5kZWJ1Z1NlYWwgPSBfZXhwb3J0cy5kZXByZWNhdGUgPSBfZXhwb3J0cy5kZWJ1ZyA9IF9leHBvcnRzLndhcm4gPSBfZXhwb3J0cy5pbmZvID0gX2V4cG9ydHMuYXNzZXJ0ID0gdm9pZCAwOwoKICAvLyBUaGVzZSBhcmUgdGhlIGRlZmF1bHQgcHJvZHVjdGlvbiBidWlsZCB2ZXJzaW9uczoKICB2YXIgbm9vcCA9IGZ1bmN0aW9uIG5vb3AoKSB7fTsKCiAgdmFyIGFzc2VydCA9IG5vb3A7CiAgX2V4cG9ydHMuYXNzZXJ0ID0gYXNzZXJ0OwogIHZhciBpbmZvID0gbm9vcDsKICBfZXhwb3J0cy5pbmZvID0gaW5mbzsKICB2YXIgd2FybiA9IG5vb3A7CiAgX2V4cG9ydHMud2FybiA9IHdhcm47CiAgdmFyIGRlYnVnID0gbm9vcDsKICBfZXhwb3J0cy5kZWJ1ZyA9IGRlYnVnOwogIHZhciBkZXByZWNhdGUgPSBub29wOwogIF9leHBvcnRzLmRlcHJlY2F0ZSA9IGRlcHJlY2F0ZTsKICB2YXIgZGVidWdTZWFsID0gbm9vcDsKICBfZXhwb3J0cy5kZWJ1Z1NlYWwgPSBkZWJ1Z1NlYWw7CiAgdmFyIGRlYnVnRnJlZXplID0gbm9vcDsKICBfZXhwb3J0cy5kZWJ1Z0ZyZWV6ZSA9IGRlYnVnRnJlZXplOwogIHZhciBydW5JbkRlYnVnID0gbm9vcDsKICBfZXhwb3J0cy5ydW5JbkRlYnVnID0gcnVuSW5EZWJ1ZzsKICB2YXIgc2V0RGVidWdGdW5jdGlvbiA9IG5vb3A7CiAgX2V4cG9ydHMuc2V0RGVidWdGdW5jdGlvbiA9IHNldERlYnVnRnVuY3Rpb247CiAgdmFyIGdldERlYnVnRnVuY3Rpb24gPSBub29wOwogIF9leHBvcnRzLmdldERlYnVnRnVuY3Rpb24gPSBnZXREZWJ1Z0Z1bmN0aW9uOwoKICB2YXIgZGVwcmVjYXRlRnVuYyA9IGZ1bmN0aW9uIGRlcHJlY2F0ZUZ1bmMoKSB7CiAgICByZXR1cm4gYXJndW1lbnRzW2FyZ3VtZW50cy5sZW5ndGggLSAxXTsKICB9OwoKICBfZXhwb3J0cy5kZXByZWNhdGVGdW5jID0gZGVwcmVjYXRlRnVuYzsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIF9leHBvcnRzLnNldERlYnVnRnVuY3Rpb24gPSBzZXREZWJ1Z0Z1bmN0aW9uID0gZnVuY3Rpb24gc2V0RGVidWdGdW5jdGlvbih0eXBlLCBjYWxsYmFjaykgewogICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICBjYXNlICdhc3NlcnQnOgogICAgICAgICAgcmV0dXJuIF9leHBvcnRzLmFzc2VydCA9IGFzc2VydCA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdpbmZvJzoKICAgICAgICAgIHJldHVybiBfZXhwb3J0cy5pbmZvID0gaW5mbyA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICd3YXJuJzoKICAgICAgICAgIHJldHVybiBfZXhwb3J0cy53YXJuID0gd2FybiA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdkZWJ1Zyc6CiAgICAgICAgICByZXR1cm4gX2V4cG9ydHMuZGVidWcgPSBkZWJ1ZyA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdkZXByZWNhdGUnOgogICAgICAgICAgcmV0dXJuIF9leHBvcnRzLmRlcHJlY2F0ZSA9IGRlcHJlY2F0ZSA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdkZWJ1Z1NlYWwnOgogICAgICAgICAgcmV0dXJuIF9leHBvcnRzLmRlYnVnU2VhbCA9IGRlYnVnU2VhbCA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdkZWJ1Z0ZyZWV6ZSc6CiAgICAgICAgICByZXR1cm4gX2V4cG9ydHMuZGVidWdGcmVlemUgPSBkZWJ1Z0ZyZWV6ZSA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdydW5JbkRlYnVnJzoKICAgICAgICAgIHJldHVybiBfZXhwb3J0cy5ydW5JbkRlYnVnID0gcnVuSW5EZWJ1ZyA9IGNhbGxiYWNrOwoKICAgICAgICBjYXNlICdkZXByZWNhdGVGdW5jJzoKICAgICAgICAgIHJldHVybiBfZXhwb3J0cy5kZXByZWNhdGVGdW5jID0gZGVwcmVjYXRlRnVuYyA9IGNhbGxiYWNrOwogICAgICB9CiAgICB9OwoKICAgIF9leHBvcnRzLmdldERlYnVnRnVuY3Rpb24gPSBnZXREZWJ1Z0Z1bmN0aW9uID0gZnVuY3Rpb24gZ2V0RGVidWdGdW5jdGlvbih0eXBlKSB7CiAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgIGNhc2UgJ2Fzc2VydCc6CiAgICAgICAgICByZXR1cm4gYXNzZXJ0OwoKICAgICAgICBjYXNlICdpbmZvJzoKICAgICAgICAgIHJldHVybiBpbmZvOwoKICAgICAgICBjYXNlICd3YXJuJzoKICAgICAgICAgIHJldHVybiB3YXJuOwoKICAgICAgICBjYXNlICdkZWJ1Zyc6CiAgICAgICAgICByZXR1cm4gZGVidWc7CgogICAgICAgIGNhc2UgJ2RlcHJlY2F0ZSc6CiAgICAgICAgICByZXR1cm4gZGVwcmVjYXRlOwoKICAgICAgICBjYXNlICdkZWJ1Z1NlYWwnOgogICAgICAgICAgcmV0dXJuIGRlYnVnU2VhbDsKCiAgICAgICAgY2FzZSAnZGVidWdGcmVlemUnOgogICAgICAgICAgcmV0dXJuIGRlYnVnRnJlZXplOwoKICAgICAgICBjYXNlICdydW5JbkRlYnVnJzoKICAgICAgICAgIHJldHVybiBydW5JbkRlYnVnOwoKICAgICAgICBjYXNlICdkZXByZWNhdGVGdW5jJzoKICAgICAgICAgIHJldHVybiBkZXByZWNhdGVGdW5jOwogICAgICB9CiAgICB9OwogIH0KICAvKioKICBAbW9kdWxlIEBlbWJlci9kZWJ1ZwogICovCgoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgLyoqCiAgICAgIFZlcmlmeSB0aGF0IGEgY2VydGFpbiBleHBlY3RhdGlvbiBpcyBtZXQsIG9yIHRocm93IGEgZXhjZXB0aW9uIG90aGVyd2lzZS4KICAgICAgICAgVGhpcyBpcyB1c2VmdWwgZm9yIGNvbW11bmljYXRpbmcgYXNzdW1wdGlvbnMgaW4gdGhlIGNvZGUgdG8gb3RoZXIgaHVtYW4KICAgICAgcmVhZGVycyBhcyB3ZWxsIGFzIGNhdGNoaW5nIGJ1Z3MgdGhhdCBhY2NpZGVudGFsbHkgdmlvbGF0ZXMgdGhlc2UKICAgICAgZXhwZWN0YXRpb25zLgogICAgICAgICBBc3NlcnRpb25zIGFyZSByZW1vdmVkIGZyb20gcHJvZHVjdGlvbiBidWlsZHMsIHNvIHRoZXkgY2FuIGJlIGZyZWVseSBhZGRlZAogICAgICBmb3IgZG9jdW1lbnRhdGlvbiBhbmQgZGVidWdnaW5nIHB1cnBvc2VzIHdpdGhvdXQgd29ycmllcyBvZiBpbmN1cmluZyBhbnkKICAgICAgcGVyZm9ybWFuY2UgcGVuYWx0eS4gSG93ZXZlciwgYmVjYXVzZSBvZiB0aGF0LCB0aGV5IHNob3VsZCBub3QgYmUgdXNlZCBmb3IKICAgICAgY2hlY2tzIHRoYXQgY291bGQgcmVhc29uYWJseSBmYWlsIGR1cmluZyBub3JtYWwgdXNhZ2UuIEZ1cnRoZXJtb3JlLCBjYXJlCiAgICAgIHNob3VsZCBiZSB0YWtlbiB0byBhdm9pZCBhY2NpZGVudGFsbHkgcmVseWluZyBvbiBzaWRlLWVmZmVjdHMgcHJvZHVjZWQgZnJvbQogICAgICBldmFsdWF0aW5nIHRoZSBjb25kaXRpb24gaXRzZWxmLCBzaW5jZSB0aGUgY29kZSB3aWxsIG5vdCBydW4gaW4gcHJvZHVjdGlvbi4KICAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgeyBhc3NlcnQgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgICAvLyBUZXN0IGZvciB0cnV0aGluZXNzCiAgICAgIGFzc2VydCgnTXVzdCBwYXNzIGEgc3RyaW5nJywgdHlwZW9mIHN0ciA9PT0gJ3N0cmluZycpOwogICAgICAgICAvLyBGYWlsIHVuY29uZGl0aW9uYWxseQogICAgICBhc3NlcnQoJ1RoaXMgY29kZSBwYXRoIHNob3VsZCBuZXZlciBiZSBydW4nKTsKICAgICAgYGBgCiAgICAgICAgIEBtZXRob2QgYXNzZXJ0CiAgICAgIEBzdGF0aWMKICAgICAgQGZvciBAZW1iZXIvZGVidWcKICAgICAgQHBhcmFtIHtTdHJpbmd9IGRlc2NyaXB0aW9uIERlc2NyaWJlcyB0aGUgZXhwZWN0YXRpb24uIFRoaXMgd2lsbCBiZWNvbWUgdGhlCiAgICAgICAgdGV4dCBvZiB0aGUgRXJyb3IgdGhyb3duIGlmIHRoZSBhc3NlcnRpb24gZmFpbHMuCiAgICAgIEBwYXJhbSB7Qm9vbGVhbn0gY29uZGl0aW9uIE11c3QgYmUgdHJ1dGh5IGZvciB0aGUgYXNzZXJ0aW9uIHRvIHBhc3MuIElmCiAgICAgICAgZmFsc3ksIGFuIGV4Y2VwdGlvbiB3aWxsIGJlIHRocm93bi4KICAgICAgQHB1YmxpYwogICAgICBAc2luY2UgMS4wLjAKICAgICovCiAgICBzZXREZWJ1Z0Z1bmN0aW9uKCdhc3NlcnQnLCBmdW5jdGlvbiBhc3NlcnQoZGVzYywgdGVzdCkgewogICAgICBpZiAoIXRlc3QpIHsKICAgICAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIkFzc2VydGlvbiBGYWlsZWQ6ICIgKyBkZXNjKTsKICAgICAgfQogICAgfSk7CiAgICAvKioKICAgICAgRGlzcGxheSBhIGRlYnVnIG5vdGljZS4KICAgICAgICAgQ2FsbHMgdG8gdGhpcyBmdW5jdGlvbiBhcmUgcmVtb3ZlZCBmcm9tIHByb2R1Y3Rpb24gYnVpbGRzLCBzbyB0aGV5IGNhbiBiZQogICAgICBmcmVlbHkgYWRkZWQgZm9yIGRvY3VtZW50YXRpb24gYW5kIGRlYnVnZ2luZyBwdXJwb3NlcyB3aXRob3V0IHdvcnJpZXMgb2YKICAgICAgaW5jdXJpbmcgYW55IHBlcmZvcm1hbmNlIHBlbmFsdHkuCiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IHsgZGVidWcgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgICBkZWJ1ZygnSVwnbSBhIGRlYnVnIG5vdGljZSEnKTsKICAgICAgYGBgCiAgICAgICAgIEBtZXRob2QgZGVidWcKICAgICAgQGZvciBAZW1iZXIvZGVidWcKICAgICAgQHN0YXRpYwogICAgICBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBBIGRlYnVnIG1lc3NhZ2UgdG8gZGlzcGxheS4KICAgICAgQHB1YmxpYwogICAgKi8KCiAgICBzZXREZWJ1Z0Z1bmN0aW9uKCdkZWJ1ZycsIGZ1bmN0aW9uIGRlYnVnKG1lc3NhZ2UpIHsKICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqLwogICAgICBpZiAoY29uc29sZS5kZWJ1ZykgewogICAgICAgIGNvbnNvbGUuZGVidWcoIkRFQlVHOiAiICsgbWVzc2FnZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc29sZS5sb2coIkRFQlVHOiAiICsgbWVzc2FnZSk7CiAgICAgIH0KICAgICAgLyogZXNsaW50LWVuc2FibGUgbm8tY29uc29sZSAqLwoKICAgIH0pOwogICAgLyoqCiAgICAgIERpc3BsYXkgYW4gaW5mbyBub3RpY2UuCiAgICAgICAgIENhbGxzIHRvIHRoaXMgZnVuY3Rpb24gYXJlIHJlbW92ZWQgZnJvbSBwcm9kdWN0aW9uIGJ1aWxkcywgc28gdGhleSBjYW4gYmUKICAgICAgZnJlZWx5IGFkZGVkIGZvciBkb2N1bWVudGF0aW9uIGFuZCBkZWJ1Z2dpbmcgcHVycG9zZXMgd2l0aG91dCB3b3JyaWVzIG9mCiAgICAgIGluY3VyaW5nIGFueSBwZXJmb3JtYW5jZSBwZW5hbHR5LgogICAgICAgICBAbWV0aG9kIGluZm8KICAgICAgQHByaXZhdGUKICAgICovCgogICAgc2V0RGVidWdGdW5jdGlvbignaW5mbycsIGZ1bmN0aW9uIGluZm8oKSB7CiAgICAgIHZhciBfY29uc29sZTsKCiAgICAgIChfY29uc29sZSA9IGNvbnNvbGUpLmluZm8uYXBwbHkoX2NvbnNvbGUsIGFyZ3VtZW50cyk7CiAgICAgIC8qIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tY29uc29sZSAqLwoKICAgIH0pOwogICAgLyoqCiAgICAgQG1vZHVsZSBAZW1iZXIvZGVidWcKICAgICBAcHVibGljCiAgICAqLwoKICAgIC8qKgogICAgICBBbGlhcyBhbiBvbGQsIGRlcHJlY2F0ZWQgbWV0aG9kIHdpdGggaXRzIG5ldyBjb3VudGVycGFydC4KICAgICAgICAgRGlzcGxheSBhIGRlcHJlY2F0aW9uIHdhcm5pbmcgd2l0aCB0aGUgcHJvdmlkZWQgbWVzc2FnZSBhbmQgYSBzdGFjayB0cmFjZQogICAgICAoQ2hyb21lIGFuZCBGaXJlZm94IG9ubHkpIHdoZW4gdGhlIGFzc2lnbmVkIG1ldGhvZCBpcyBjYWxsZWQuCiAgICAgICAgIENhbGxzIHRvIHRoaXMgZnVuY3Rpb24gYXJlIHJlbW92ZWQgZnJvbSBwcm9kdWN0aW9uIGJ1aWxkcywgc28gdGhleSBjYW4gYmUKICAgICAgZnJlZWx5IGFkZGVkIGZvciBkb2N1bWVudGF0aW9uIGFuZCBkZWJ1Z2dpbmcgcHVycG9zZXMgd2l0aG91dCB3b3JyaWVzIG9mCiAgICAgIGluY3VyaW5nIGFueSBwZXJmb3JtYW5jZSBwZW5hbHR5LgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCB7IGRlcHJlY2F0ZUZ1bmMgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgICBFbWJlci5vbGRNZXRob2QgPSBkZXByZWNhdGVGdW5jKCdQbGVhc2UgdXNlIHRoZSBuZXcsIHVwZGF0ZWQgbWV0aG9kJywgb3B0aW9ucywgRW1iZXIubmV3TWV0aG9kKTsKICAgICAgYGBgCiAgICAgICAgIEBtZXRob2QgZGVwcmVjYXRlRnVuYwogICAgICBAc3RhdGljCiAgICAgIEBmb3IgQGVtYmVyL2RlYnVnCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIEEgZGVzY3JpcHRpb24gb2YgdGhlIGRlcHJlY2F0aW9uLgogICAgICBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIFRoZSBvcHRpb25zIG9iamVjdCBmb3IgYGRlcHJlY2F0ZWAuCiAgICAgIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIG5ldyBmdW5jdGlvbiBjYWxsZWQgdG8gcmVwbGFjZSBpdHMgZGVwcmVjYXRlZCBjb3VudGVycGFydC4KICAgICAgQHJldHVybiB7RnVuY3Rpb259IEEgbmV3IGZ1bmN0aW9uIHRoYXQgd3JhcHMgdGhlIG9yaWdpbmFsIGZ1bmN0aW9uIHdpdGggYSBkZXByZWNhdGlvbiB3YXJuaW5nCiAgICAgIEBwcml2YXRlCiAgICAqLwoKICAgIHNldERlYnVnRnVuY3Rpb24oJ2RlcHJlY2F0ZUZ1bmMnLCBmdW5jdGlvbiBkZXByZWNhdGVGdW5jKCkgewogICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHsKICAgICAgICB2YXIgbWVzc2FnZSA9IGFyZ3NbMF0sCiAgICAgICAgICAgIG9wdGlvbnMgPSBhcmdzWzFdLAogICAgICAgICAgICBmdW5jID0gYXJnc1syXTsKICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgICAgZGVwcmVjYXRlKG1lc3NhZ2UsIGZhbHNlLCBvcHRpb25zKTsKCiAgICAgICAgICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjIpLCBfa2V5MiA9IDA7IF9rZXkyIDwgX2xlbjI7IF9rZXkyKyspIHsKICAgICAgICAgICAgYXJnc1tfa2V5Ml0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3MpOwogICAgICAgIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIF9tZXNzYWdlID0gYXJnc1swXSwKICAgICAgICAgICAgX2Z1bmMgPSBhcmdzWzFdOwogICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBkZXByZWNhdGUoX21lc3NhZ2UpOwogICAgICAgICAgcmV0dXJuIF9mdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICAgICAgfTsKICAgICAgfQogICAgfSk7CiAgICAvKioKICAgICBAbW9kdWxlIEBlbWJlci9kZWJ1ZwogICAgIEBwdWJsaWMKICAgICovCgogICAgLyoqCiAgICAgIFJ1biBhIGZ1bmN0aW9uIG1lYW50IGZvciBkZWJ1Z2dpbmcuCiAgICAgICAgIENhbGxzIHRvIHRoaXMgZnVuY3Rpb24gYXJlIHJlbW92ZWQgZnJvbSBwcm9kdWN0aW9uIGJ1aWxkcywgc28gdGhleSBjYW4gYmUKICAgICAgZnJlZWx5IGFkZGVkIGZvciBkb2N1bWVudGF0aW9uIGFuZCBkZWJ1Z2dpbmcgcHVycG9zZXMgd2l0aG91dCB3b3JyaWVzIG9mCiAgICAgIGluY3VyaW5nIGFueSBwZXJmb3JtYW5jZSBwZW5hbHR5LgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICAgIGltcG9ydCB7IHJ1bkluRGVidWcgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgICBydW5JbkRlYnVnKCgpID0+IHsKICAgICAgICBDb21wb25lbnQucmVvcGVuKHsKICAgICAgICAgIGRpZEluc2VydEVsZW1lbnQoKSB7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKCJJJ20gaGFwcHkiKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgICBAbWV0aG9kIHJ1bkluRGVidWcKICAgICAgQGZvciBAZW1iZXIvZGVidWcKICAgICAgQHN0YXRpYwogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZC4KICAgICAgQHNpbmNlIDEuNS4wCiAgICAgIEBwdWJsaWMKICAgICovCgogICAgc2V0RGVidWdGdW5jdGlvbigncnVuSW5EZWJ1ZycsIGZ1bmN0aW9uIHJ1bkluRGVidWcoZnVuYykgewogICAgICBmdW5jKCk7CiAgICB9KTsKICAgIHNldERlYnVnRnVuY3Rpb24oJ2RlYnVnU2VhbCcsIGZ1bmN0aW9uIGRlYnVnU2VhbChvYmopIHsKICAgICAgT2JqZWN0LnNlYWwob2JqKTsKICAgIH0pOwogICAgc2V0RGVidWdGdW5jdGlvbignZGVidWdGcmVlemUnLCBmdW5jdGlvbiBkZWJ1Z0ZyZWV6ZShvYmopIHsKICAgICAgLy8gcmUtZnJlZXppbmcgYW4gYWxyZWFkeSBmcm96ZW4gb2JqZWN0IGludHJvZHVjZXMgYSBzaWduaWZpY2FudAogICAgICAvLyBwZXJmb3JtYW5jZSBwZW5hbHR5IG9uIENocm9tZSAodGVzdGVkIHRocm91Z2ggNTkpLgogICAgICAvLwogICAgICAvLyBTZWU6IGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTY0NTAKICAgICAgaWYgKCFPYmplY3QuaXNGcm96ZW4ob2JqKSkgewogICAgICAgIE9iamVjdC5mcmVlemUob2JqKTsKICAgICAgfQogICAgfSk7CiAgICBzZXREZWJ1Z0Z1bmN0aW9uKCdkZXByZWNhdGUnLCBfZGVwcmVjYXRlMi5kZWZhdWx0KTsKICAgIHNldERlYnVnRnVuY3Rpb24oJ3dhcm4nLCBfd2FybjIuZGVmYXVsdCk7CiAgfQoKICB2YXIgX3dhcm5JZlVzaW5nU3RyaXBwZWRGZWF0dXJlRmxhZ3M7CgogIF9leHBvcnRzLl93YXJuSWZVc2luZ1N0cmlwcGVkRmVhdHVyZUZsYWdzID0gX3dhcm5JZlVzaW5nU3RyaXBwZWRGZWF0dXJlRmxhZ3M7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgJiYgISgwLCBfdGVzdGluZy5pc1Rlc3RpbmcpKCkpIHsKICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiAoX2Jyb3dzZXJFbnZpcm9ubWVudC5pc0ZpcmVmb3ggfHwgX2Jyb3dzZXJFbnZpcm9ubWVudC5pc0Nocm9tZSkgJiYgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIpIHsKICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgaWYgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZGF0YXNldCAmJiAhZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmRhdGFzZXQuZW1iZXJFeHRlbnNpb24pIHsKICAgICAgICAgIHZhciBkb3dubG9hZFVSTDsKCiAgICAgICAgICBpZiAoX2Jyb3dzZXJFbnZpcm9ubWVudC5pc0Nocm9tZSkgewogICAgICAgICAgICBkb3dubG9hZFVSTCA9ICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9lbWJlci1pbnNwZWN0b3IvYm1kYmxuY2Vna2Vua2FjaWVpaGZocGpmcHBvY29uaGknOwogICAgICAgICAgfSBlbHNlIGlmIChfYnJvd3NlckVudmlyb25tZW50LmlzRmlyZWZveCkgewogICAgICAgICAgICBkb3dubG9hZFVSTCA9ICdodHRwczovL2FkZG9ucy5tb3ppbGxhLm9yZy9lbi1VUy9maXJlZm94L2FkZG9uL2VtYmVyLWluc3BlY3Rvci8nOwogICAgICAgICAgfQoKICAgICAgICAgIGRlYnVnKCJGb3IgbW9yZSBhZHZhbmNlZCBkZWJ1Z2dpbmcsIGluc3RhbGwgdGhlIEVtYmVyIEluc3BlY3RvciBmcm9tICIgKyBkb3dubG9hZFVSTCk7CiAgICAgICAgfQogICAgICB9LCBmYWxzZSk7CiAgICB9CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvZGVidWcvbGliL2RlcHJlY2F0ZSIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCIsICJAZW1iZXIvZGVidWcvaW5kZXgiLCAiQGVtYmVyL2RlYnVnL2xpYi9oYW5kbGVycyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbnZpcm9ubWVudCwgX2luZGV4LCBfaGFuZGxlcnMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zVW50aWxEZXByZWNhdGlvbiA9IF9leHBvcnRzLm1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9IF9leHBvcnRzLm1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb24gPSBfZXhwb3J0cy5yZWdpc3RlckhhbmRsZXIgPSBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgQG1vZHVsZSBAZW1iZXIvZGVidWcKICAgQHB1YmxpYwogICovCgogIC8qKgogICAgQWxsb3dzIGZvciBydW50aW1lIHJlZ2lzdHJhdGlvbiBvZiBoYW5kbGVyIGZ1bmN0aW9ucyB0aGF0IG92ZXJyaWRlIHRoZSBkZWZhdWx0IGRlcHJlY2F0aW9uIGJlaGF2aW9yLgogICAgRGVwcmVjYXRpb25zIGFyZSBpbnZva2VkIGJ5IGNhbGxzIHRvIFtAZW1iZXIvZGVidWcvZGVwcmVjYXRlXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL0BlbWJlciUyRmRlYnVnL21ldGhvZHMvZGVwcmVjYXRlP2FuY2hvcj1kZXByZWNhdGUpLgogICAgVGhlIGZvbGxvd2luZyBleGFtcGxlIGRlbW9uc3RyYXRlcyBpdHMgdXNhZ2UgYnkgcmVnaXN0ZXJpbmcgYSBoYW5kbGVyIHRoYXQgdGhyb3dzIGFuIGVycm9yIGlmIHRoZQogICAgbWVzc2FnZSBjb250YWlucyB0aGUgd29yZCAic2hvdWxkIiwgb3RoZXJ3aXNlIGRlZmVycyB0byB0aGUgZGVmYXVsdCBoYW5kbGVyLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgcmVnaXN0ZXJEZXByZWNhdGlvbkhhbmRsZXIgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogIAogICAgcmVnaXN0ZXJEZXByZWNhdGlvbkhhbmRsZXIoKG1lc3NhZ2UsIG9wdGlvbnMsIG5leHQpID0+IHsKICAgICAgaWYgKG1lc3NhZ2UuaW5kZXhPZignc2hvdWxkJykgIT09IC0xKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBEZXByZWNhdGlvbiBtZXNzYWdlIHdpdGggc2hvdWxkOiAke21lc3NhZ2V9YCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gZGVmZXIgdG8gd2hhdGV2ZXIgaGFuZGxlciB3YXMgcmVnaXN0ZXJlZCBiZWZvcmUgdGhpcyBvbmUKICAgICAgICBuZXh0KG1lc3NhZ2UsIG9wdGlvbnMpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgVGhlIGhhbmRsZXIgZnVuY3Rpb24gdGFrZXMgdGhlIGZvbGxvd2luZyBhcmd1bWVudHM6CiAgCiAgICA8dWw+CiAgICAgIDxsaT4gPGNvZGU+bWVzc2FnZTwvY29kZT4gLSBUaGUgbWVzc2FnZSByZWNlaXZlZCBmcm9tIHRoZSBkZXByZWNhdGlvbiBjYWxsLjwvbGk+CiAgICAgIDxsaT4gPGNvZGU+b3B0aW9uczwvY29kZT4gLSBBbiBvYmplY3QgcGFzc2VkIGluIHdpdGggdGhlIGRlcHJlY2F0aW9uIGNhbGwgY29udGFpbmluZyBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIGluY2x1ZGluZzo8L2xpPgogICAgICAgIDx1bD4KICAgICAgICAgIDxsaT4gPGNvZGU+aWQ8L2NvZGU+IC0gQW4gaWQgb2YgdGhlIGRlcHJlY2F0aW9uIGluIHRoZSBmb3JtIG9mIDxjb2RlPnBhY2thZ2UtbmFtZS5zcGVjaWZpYy1kZXByZWNhdGlvbjwvY29kZT4uPC9saT4KICAgICAgICAgIDxsaT4gPGNvZGU+dW50aWw8L2NvZGU+IC0gVGhlIEVtYmVyIHZlcnNpb24gbnVtYmVyIHRoZSBmZWF0dXJlIGFuZCBkZXByZWNhdGlvbiB3aWxsIGJlIHJlbW92ZWQgaW4uPC9saT4KICAgICAgICA8L3VsPgogICAgICA8bGk+IDxjb2RlPm5leHQ8L2NvZGU+IC0gQSBmdW5jdGlvbiB0aGF0IGNhbGxzIGludG8gdGhlIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCBoYW5kbGVyLjwvbGk+CiAgICA8L3VsPgogIAogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQG1ldGhvZCByZWdpc3RlckRlcHJlY2F0aW9uSGFuZGxlcgogICAgQGZvciBAZW1iZXIvZGVidWcKICAgIEBwYXJhbSBoYW5kbGVyIHtGdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBoYW5kbGUgZGVwcmVjYXRpb24gY2FsbHMuCiAgICBAc2luY2UgMi4xLjAKICAqLwogIHZhciByZWdpc3RlckhhbmRsZXIgPSBmdW5jdGlvbiByZWdpc3RlckhhbmRsZXIoKSB7fTsKCiAgX2V4cG9ydHMucmVnaXN0ZXJIYW5kbGVyID0gcmVnaXN0ZXJIYW5kbGVyOwogIHZhciBtaXNzaW5nT3B0aW9uc0RlcHJlY2F0aW9uOwogIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb24gPSBtaXNzaW5nT3B0aW9uc0RlcHJlY2F0aW9uOwogIHZhciBtaXNzaW5nT3B0aW9uc0lkRGVwcmVjYXRpb247CiAgX2V4cG9ydHMubWlzc2luZ09wdGlvbnNJZERlcHJlY2F0aW9uID0gbWlzc2luZ09wdGlvbnNJZERlcHJlY2F0aW9uOwogIHZhciBtaXNzaW5nT3B0aW9uc1VudGlsRGVwcmVjYXRpb247CiAgX2V4cG9ydHMubWlzc2luZ09wdGlvbnNVbnRpbERlcHJlY2F0aW9uID0gbWlzc2luZ09wdGlvbnNVbnRpbERlcHJlY2F0aW9uOwoKICB2YXIgZGVwcmVjYXRlID0gZnVuY3Rpb24gZGVwcmVjYXRlKCkge307CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICBfZXhwb3J0cy5yZWdpc3RlckhhbmRsZXIgPSByZWdpc3RlckhhbmRsZXIgPSBmdW5jdGlvbiByZWdpc3RlckhhbmRsZXIoaGFuZGxlcikgewogICAgICAoMCwgX2hhbmRsZXJzLnJlZ2lzdGVySGFuZGxlcikoJ2RlcHJlY2F0ZScsIGhhbmRsZXIpOwogICAgfTsKCiAgICB2YXIgZm9ybWF0TWVzc2FnZSA9IGZ1bmN0aW9uIGZvcm1hdE1lc3NhZ2UoX21lc3NhZ2UsIG9wdGlvbnMpIHsKICAgICAgdmFyIG1lc3NhZ2UgPSBfbWVzc2FnZTsKCiAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuaWQpIHsKICAgICAgICBtZXNzYWdlID0gbWVzc2FnZSArICgiIFtkZXByZWNhdGlvbiBpZDogIiArIG9wdGlvbnMuaWQgKyAiXSIpOwogICAgICB9CgogICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnVybCkgewogICAgICAgIG1lc3NhZ2UgKz0gIiBTZWUgIiArIG9wdGlvbnMudXJsICsgIiBmb3IgbW9yZSBkZXRhaWxzLiI7CiAgICAgIH0KCiAgICAgIHJldHVybiBtZXNzYWdlOwogICAgfTsKCiAgICByZWdpc3RlckhhbmRsZXIoZnVuY3Rpb24gbG9nRGVwcmVjYXRpb25Ub0NvbnNvbGUobWVzc2FnZSwgb3B0aW9ucykgewogICAgICB2YXIgdXBkYXRlZE1lc3NhZ2UgPSBmb3JtYXRNZXNzYWdlKG1lc3NhZ2UsIG9wdGlvbnMpOwogICAgICBjb25zb2xlLndhcm4oIkRFUFJFQ0FUSU9OOiAiICsgdXBkYXRlZE1lc3NhZ2UpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbnNvbGUKICAgIH0pOwogICAgdmFyIGNhcHR1cmVFcnJvckZvclN0YWNrOwoKICAgIGlmIChuZXcgRXJyb3IoKS5zdGFjaykgewogICAgICBjYXB0dXJlRXJyb3JGb3JTdGFjayA9IGZ1bmN0aW9uIGNhcHR1cmVFcnJvckZvclN0YWNrKCkgewogICAgICAgIHJldHVybiBuZXcgRXJyb3IoKTsKICAgICAgfTsKICAgIH0gZWxzZSB7CiAgICAgIGNhcHR1cmVFcnJvckZvclN0YWNrID0gZnVuY3Rpb24gY2FwdHVyZUVycm9yRm9yU3RhY2soKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIF9fZmFpbF9fLmZhaWwoKTsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICByZXR1cm4gZTsKICAgICAgICB9CiAgICAgIH07CiAgICB9CgogICAgcmVnaXN0ZXJIYW5kbGVyKGZ1bmN0aW9uIGxvZ0RlcHJlY2F0aW9uU3RhY2tUcmFjZShtZXNzYWdlLCBvcHRpb25zLCBuZXh0KSB7CiAgICAgIGlmIChfZW52aXJvbm1lbnQuRU5WLkxPR19TVEFDS1RSQUNFX09OX0RFUFJFQ0FUSU9OKSB7CiAgICAgICAgdmFyIHN0YWNrU3RyID0gJyc7CiAgICAgICAgdmFyIGVycm9yID0gY2FwdHVyZUVycm9yRm9yU3RhY2soKTsKICAgICAgICB2YXIgc3RhY2s7CgogICAgICAgIGlmIChlcnJvci5zdGFjaykgewogICAgICAgICAgaWYgKGVycm9yWydhcmd1bWVudHMnXSkgewogICAgICAgICAgICAvLyBDaHJvbWUKICAgICAgICAgICAgc3RhY2sgPSBlcnJvci5zdGFjay5yZXBsYWNlKC9eXHMrYXRccysvZ20sICcnKS5yZXBsYWNlKC9eKFteXChdKz8pKFtcbiRdKS9nbSwgJ3thbm9ueW1vdXN9KCQxKSQyJykucmVwbGFjZSgvXk9iamVjdC48YW5vbnltb3VzPlxzKlwoKFteXCldKylcKS9nbSwgJ3thbm9ueW1vdXN9KCQxKScpLnNwbGl0KCdcbicpOwogICAgICAgICAgICBzdGFjay5zaGlmdCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgLy8gRmlyZWZveAogICAgICAgICAgICBzdGFjayA9IGVycm9yLnN0YWNrLnJlcGxhY2UoLyg/OlxuQDowKT9ccyskL20sICcnKS5yZXBsYWNlKC9eXCgvZ20sICd7YW5vbnltb3VzfSgnKS5zcGxpdCgnXG4nKTsKICAgICAgICAgIH0KCiAgICAgICAgICBzdGFja1N0ciA9ICJcbiAgICAiICsgc3RhY2suc2xpY2UoMikuam9pbignXG4gICAgJyk7CiAgICAgICAgfQoKICAgICAgICB2YXIgdXBkYXRlZE1lc3NhZ2UgPSBmb3JtYXRNZXNzYWdlKG1lc3NhZ2UsIG9wdGlvbnMpOwogICAgICAgIGNvbnNvbGUud2FybigiREVQUkVDQVRJT046ICIgKyB1cGRhdGVkTWVzc2FnZSArIHN0YWNrU3RyKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlCiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmV4dChtZXNzYWdlLCBvcHRpb25zKTsKICAgICAgfQogICAgfSk7CiAgICByZWdpc3RlckhhbmRsZXIoZnVuY3Rpb24gcmFpc2VPbkRlcHJlY2F0aW9uKG1lc3NhZ2UsIG9wdGlvbnMsIG5leHQpIHsKICAgICAgaWYgKF9lbnZpcm9ubWVudC5FTlYuUkFJU0VfT05fREVQUkVDQVRJT04pIHsKICAgICAgICB2YXIgdXBkYXRlZE1lc3NhZ2UgPSBmb3JtYXRNZXNzYWdlKG1lc3NhZ2UpOwogICAgICAgIHRocm93IG5ldyBFcnJvcih1cGRhdGVkTWVzc2FnZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmV4dChtZXNzYWdlLCBvcHRpb25zKTsKICAgICAgfQogICAgfSk7CiAgICBfZXhwb3J0cy5taXNzaW5nT3B0aW9uc0RlcHJlY2F0aW9uID0gbWlzc2luZ09wdGlvbnNEZXByZWNhdGlvbiA9ICdXaGVuIGNhbGxpbmcgYGRlcHJlY2F0ZWAgeW91ICcgKyAnbXVzdCBwcm92aWRlIGFuIGBvcHRpb25zYCBoYXNoIGFzIHRoZSB0aGlyZCBwYXJhbWV0ZXIuICAnICsgJ2BvcHRpb25zYCBzaG91bGQgaW5jbHVkZSBgaWRgIGFuZCBgdW50aWxgIHByb3BlcnRpZXMuJzsKICAgIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9ICdXaGVuIGNhbGxpbmcgYGRlcHJlY2F0ZWAgeW91IG11c3QgcHJvdmlkZSBgaWRgIGluIG9wdGlvbnMuJzsKICAgIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zVW50aWxEZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zVW50aWxEZXByZWNhdGlvbiA9ICdXaGVuIGNhbGxpbmcgYGRlcHJlY2F0ZWAgeW91IG11c3QgcHJvdmlkZSBgdW50aWxgIGluIG9wdGlvbnMuJzsKICAgIC8qKgogICAgIEBtb2R1bGUgQGVtYmVyL2RlYnVnCiAgICAgQHB1YmxpYwogICAgICovCgogICAgLyoqCiAgICAgIERpc3BsYXkgYSBkZXByZWNhdGlvbiB3YXJuaW5nIHdpdGggdGhlIHByb3ZpZGVkIG1lc3NhZ2UgYW5kIGEgc3RhY2sgdHJhY2UKICAgICAgKENocm9tZSBhbmQgRmlyZWZveCBvbmx5KS4KICAgICAgICAgKiBJbiBhIHByb2R1Y3Rpb24gYnVpbGQsIHRoaXMgbWV0aG9kIGlzIGRlZmluZWQgYXMgYW4gZW1wdHkgZnVuY3Rpb24gKE5PUCkuCiAgICAgIFVzZXMgb2YgdGhpcyBtZXRob2QgaW4gRW1iZXIgaXRzZWxmIGFyZSBzdHJpcHBlZCBmcm9tIHRoZSBlbWJlci5wcm9kLmpzIGJ1aWxkLgogICAgICAgICBAbWV0aG9kIGRlcHJlY2F0ZQogICAgICBAZm9yIEBlbWJlci9kZWJ1ZwogICAgICBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBBIGRlc2NyaXB0aW9uIG9mIHRoZSBkZXByZWNhdGlvbi4KICAgICAgQHBhcmFtIHtCb29sZWFufSB0ZXN0IEEgYm9vbGVhbi4gSWYgZmFsc3ksIHRoZSBkZXByZWNhdGlvbiB3aWxsIGJlIGRpc3BsYXllZC4KICAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAgQHBhcmFtIHtTdHJpbmd9IG9wdGlvbnMuaWQgQSB1bmlxdWUgaWQgZm9yIHRoaXMgZGVwcmVjYXRpb24uIFRoZSBpZCBjYW4gYmUKICAgICAgICB1c2VkIGJ5IEVtYmVyIGRlYnVnZ2luZyB0b29scyB0byBjaGFuZ2UgdGhlIGJlaGF2aW9yIChyYWlzZSwgbG9nIG9yIHNpbGVuY2UpCiAgICAgICAgZm9yIHRoYXQgc3BlY2lmaWMgZGVwcmVjYXRpb24uIFRoZSBpZCBzaG91bGQgYmUgbmFtZXNwYWNlZCBieSBkb3RzLCBlLmcuCiAgICAgICAgInZpZXcuaGVscGVyLnNlbGVjdCIuCiAgICAgIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLnVudGlsIFRoZSB2ZXJzaW9uIG9mIEVtYmVyIHdoZW4gdGhpcyBkZXByZWNhdGlvbgogICAgICAgIHdhcm5pbmcgd2lsbCBiZSByZW1vdmVkLgogICAgICBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMudXJsXSBBbiBvcHRpb25hbCB1cmwgdG8gdGhlIHRyYW5zaXRpb24gZ3VpZGUgb24gdGhlCiAgICAgICAgZW1iZXJqcy5jb20gd2Vic2l0ZS4KICAgICAgQHN0YXRpYwogICAgICBAcHVibGljCiAgICAgIEBzaW5jZSAxLjAuMAogICAgKi8KCiAgICBkZXByZWNhdGUgPSBmdW5jdGlvbiBkZXByZWNhdGUobWVzc2FnZSwgdGVzdCwgb3B0aW9ucykgewogICAgICAoMCwgX2luZGV4LmFzc2VydCkobWlzc2luZ09wdGlvbnNEZXByZWNhdGlvbiwgQm9vbGVhbihvcHRpb25zICYmIChvcHRpb25zLmlkIHx8IG9wdGlvbnMudW50aWwpKSk7CiAgICAgICgwLCBfaW5kZXguYXNzZXJ0KShtaXNzaW5nT3B0aW9uc0lkRGVwcmVjYXRpb24sIEJvb2xlYW4ob3B0aW9ucy5pZCkpOwogICAgICAoMCwgX2luZGV4LmFzc2VydCkobWlzc2luZ09wdGlvbnNVbnRpbERlcHJlY2F0aW9uLCBCb29sZWFuKG9wdGlvbnMudW50aWwpKTsKICAgICAgKDAsIF9oYW5kbGVycy5pbnZva2UpKCdkZXByZWNhdGUnLCBtZXNzYWdlLCB0ZXN0LCBvcHRpb25zKTsKICAgIH07CiAgfQoKICB2YXIgX2RlZmF1bHQgPSBkZXByZWNhdGU7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJAZW1iZXIvZGVidWcvbGliL2hhbmRsZXJzIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuaW52b2tlID0gX2V4cG9ydHMucmVnaXN0ZXJIYW5kbGVyID0gX2V4cG9ydHMuSEFORExFUlMgPSB2b2lkIDA7CiAgdmFyIEhBTkRMRVJTID0ge307CiAgX2V4cG9ydHMuSEFORExFUlMgPSBIQU5ETEVSUzsKCiAgdmFyIHJlZ2lzdGVySGFuZGxlciA9IGZ1bmN0aW9uIHJlZ2lzdGVySGFuZGxlcigpIHt9OwoKICBfZXhwb3J0cy5yZWdpc3RlckhhbmRsZXIgPSByZWdpc3RlckhhbmRsZXI7CgogIHZhciBpbnZva2UgPSBmdW5jdGlvbiBpbnZva2UoKSB7fTsKCiAgX2V4cG9ydHMuaW52b2tlID0gaW52b2tlOwoKICBpZiAoZmFsc2UKICAvKiBERUJVRyAqLwogICkgewogICAgX2V4cG9ydHMucmVnaXN0ZXJIYW5kbGVyID0gcmVnaXN0ZXJIYW5kbGVyID0gZnVuY3Rpb24gcmVnaXN0ZXJIYW5kbGVyKHR5cGUsIGNhbGxiYWNrKSB7CiAgICAgIHZhciBuZXh0SGFuZGxlciA9IEhBTkRMRVJTW3R5cGVdIHx8IGZ1bmN0aW9uICgpIHt9OwoKICAgICAgSEFORExFUlNbdHlwZV0gPSBmdW5jdGlvbiAobWVzc2FnZSwgb3B0aW9ucykgewogICAgICAgIGNhbGxiYWNrKG1lc3NhZ2UsIG9wdGlvbnMsIG5leHRIYW5kbGVyKTsKICAgICAgfTsKICAgIH07CgogICAgX2V4cG9ydHMuaW52b2tlID0gaW52b2tlID0gZnVuY3Rpb24gaW52b2tlKHR5cGUsIG1lc3NhZ2UsIHRlc3QsIG9wdGlvbnMpIHsKICAgICAgaWYgKHRlc3QpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBoYW5kbGVyRm9yVHlwZSA9IEhBTkRMRVJTW3R5cGVdOwoKICAgICAgaWYgKGhhbmRsZXJGb3JUeXBlKSB7CiAgICAgICAgaGFuZGxlckZvclR5cGUobWVzc2FnZSwgb3B0aW9ucyk7CiAgICAgIH0KICAgIH07CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvZGVidWcvbGliL3Rlc3RpbmciLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5pc1Rlc3RpbmcgPSBpc1Rlc3Rpbmc7CiAgX2V4cG9ydHMuc2V0VGVzdGluZyA9IHNldFRlc3Rpbmc7CiAgdmFyIHRlc3RpbmcgPSBmYWxzZTsKCiAgZnVuY3Rpb24gaXNUZXN0aW5nKCkgewogICAgcmV0dXJuIHRlc3Rpbmc7CiAgfQoKICBmdW5jdGlvbiBzZXRUZXN0aW5nKHZhbHVlKSB7CiAgICB0ZXN0aW5nID0gQm9vbGVhbih2YWx1ZSk7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvZGVidWcvbGliL3dhcm4iLCBbImV4cG9ydHMiLCAiQGVtYmVyL2RlYnVnL2luZGV4IiwgIkBlbWJlci9kZWJ1Zy9saWIvaGFuZGxlcnMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfaW5kZXgsIF9oYW5kbGVycykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMubWlzc2luZ09wdGlvbnNEZXByZWNhdGlvbiA9IF9leHBvcnRzLm1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9IF9leHBvcnRzLnJlZ2lzdGVySGFuZGxlciA9IF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIHZhciByZWdpc3RlckhhbmRsZXIgPSBmdW5jdGlvbiByZWdpc3RlckhhbmRsZXIoKSB7fTsKCiAgX2V4cG9ydHMucmVnaXN0ZXJIYW5kbGVyID0gcmVnaXN0ZXJIYW5kbGVyOwoKICB2YXIgd2FybiA9IGZ1bmN0aW9uIHdhcm4oKSB7fTsKCiAgdmFyIG1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb247CiAgX2V4cG9ydHMubWlzc2luZ09wdGlvbnNEZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb247CiAgdmFyIG1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbjsKICAvKioKICBAbW9kdWxlIEBlbWJlci9kZWJ1ZwogICovCgogIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbjsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIC8qKgogICAgICBBbGxvd3MgZm9yIHJ1bnRpbWUgcmVnaXN0cmF0aW9uIG9mIGhhbmRsZXIgZnVuY3Rpb25zIHRoYXQgb3ZlcnJpZGUgdGhlIGRlZmF1bHQgd2FybmluZyBiZWhhdmlvci4KICAgICAgV2FybmluZ3MgYXJlIGludm9rZWQgYnkgY2FsbHMgbWFkZSB0byBbQGVtYmVyL2RlYnVnL3dhcm5dKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvQGVtYmVyJTJGZGVidWcvbWV0aG9kcy93YXJuP2FuY2hvcj13YXJuKS4KICAgICAgVGhlIGZvbGxvd2luZyBleGFtcGxlIGRlbW9uc3RyYXRlcyBpdHMgdXNhZ2UgYnkgcmVnaXN0ZXJpbmcgYSBoYW5kbGVyIHRoYXQgZG9lcyBub3RoaW5nIG92ZXJyaWRpbmcgRW1iZXIncwogICAgICBkZWZhdWx0IHdhcm5pbmcgYmVoYXZpb3IuCiAgICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgaW1wb3J0IHsgcmVnaXN0ZXJXYXJuSGFuZGxlciB9IGZyb20gJ0BlbWJlci9kZWJ1Zyc7CiAgICAgICAgIC8vIG5leHQgaXMgbm90IGNhbGxlZCwgc28gbm8gd2FybmluZ3MgZ2V0IHRoZSBkZWZhdWx0IGJlaGF2aW9yCiAgICAgIHJlZ2lzdGVyV2FybkhhbmRsZXIoKCkgPT4ge30pOwogICAgICBgYGAKICAgICAgICAgVGhlIGhhbmRsZXIgZnVuY3Rpb24gdGFrZXMgdGhlIGZvbGxvd2luZyBhcmd1bWVudHM6CiAgICAgICAgIDx1bD4KICAgICAgICA8bGk+IDxjb2RlPm1lc3NhZ2U8L2NvZGU+IC0gVGhlIG1lc3NhZ2UgcmVjZWl2ZWQgZnJvbSB0aGUgd2FybiBjYWxsLiA8L2xpPgogICAgICAgIDxsaT4gPGNvZGU+b3B0aW9uczwvY29kZT4gLSBBbiBvYmplY3QgcGFzc2VkIGluIHdpdGggdGhlIHdhcm4gY2FsbCBjb250YWluaW5nIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gaW5jbHVkaW5nOjwvbGk+CiAgICAgICAgICA8dWw+CiAgICAgICAgICAgIDxsaT4gPGNvZGU+aWQ8L2NvZGU+IC0gQW4gaWQgb2YgdGhlIHdhcm5pbmcgaW4gdGhlIGZvcm0gb2YgPGNvZGU+cGFja2FnZS1uYW1lLnNwZWNpZmljLXdhcm5pbmc8L2NvZGU+LjwvbGk+CiAgICAgICAgICA8L3VsPgogICAgICAgIDxsaT4gPGNvZGU+bmV4dDwvY29kZT4gLSBBIGZ1bmN0aW9uIHRoYXQgY2FsbHMgaW50byB0aGUgcHJldmlvdXNseSByZWdpc3RlcmVkIGhhbmRsZXIuPC9saT4KICAgICAgPC91bD4KICAgICAgICAgQHB1YmxpYwogICAgICBAc3RhdGljCiAgICAgIEBtZXRob2QgcmVnaXN0ZXJXYXJuSGFuZGxlcgogICAgICBAZm9yIEBlbWJlci9kZWJ1ZwogICAgICBAcGFyYW0gaGFuZGxlciB7RnVuY3Rpb259IEEgZnVuY3Rpb24gdG8gaGFuZGxlIHdhcm5pbmdzLgogICAgICBAc2luY2UgMi4xLjAKICAgICovCiAgICBfZXhwb3J0cy5yZWdpc3RlckhhbmRsZXIgPSByZWdpc3RlckhhbmRsZXIgPSBmdW5jdGlvbiByZWdpc3RlckhhbmRsZXIoaGFuZGxlcikgewogICAgICAoMCwgX2hhbmRsZXJzLnJlZ2lzdGVySGFuZGxlcikoJ3dhcm4nLCBoYW5kbGVyKTsKICAgIH07CgogICAgcmVnaXN0ZXJIYW5kbGVyKGZ1bmN0aW9uIGxvZ1dhcm5pbmcobWVzc2FnZSkgewogICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovCiAgICAgIGNvbnNvbGUud2FybigiV0FSTklORzogIiArIG1lc3NhZ2UpOwogICAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWNvbnNvbGUgKi8KICAgIH0pOwogICAgX2V4cG9ydHMubWlzc2luZ09wdGlvbnNEZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb24gPSAnV2hlbiBjYWxsaW5nIGB3YXJuYCB5b3UgJyArICdtdXN0IHByb3ZpZGUgYW4gYG9wdGlvbnNgIGhhc2ggYXMgdGhlIHRoaXJkIHBhcmFtZXRlci4gICcgKyAnYG9wdGlvbnNgIHNob3VsZCBpbmNsdWRlIGFuIGBpZGAgcHJvcGVydHkuJzsKICAgIF9leHBvcnRzLm1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9IG1pc3NpbmdPcHRpb25zSWREZXByZWNhdGlvbiA9ICdXaGVuIGNhbGxpbmcgYHdhcm5gIHlvdSBtdXN0IHByb3ZpZGUgYGlkYCBpbiBvcHRpb25zLic7CiAgICAvKioKICAgICAgRGlzcGxheSBhIHdhcm5pbmcgd2l0aCB0aGUgcHJvdmlkZWQgbWVzc2FnZS4KICAgICAgICAgKiBJbiBhIHByb2R1Y3Rpb24gYnVpbGQsIHRoaXMgbWV0aG9kIGlzIGRlZmluZWQgYXMgYW4gZW1wdHkgZnVuY3Rpb24gKE5PUCkuCiAgICAgIFVzZXMgb2YgdGhpcyBtZXRob2QgaW4gRW1iZXIgaXRzZWxmIGFyZSBzdHJpcHBlZCBmcm9tIHRoZSBlbWJlci5wcm9kLmpzIGJ1aWxkLgogICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCB7IHdhcm4gfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICBpbXBvcnQgdG9tc3RlckNvdW50IGZyb20gJy4vdG9tc3Rlci1jb3VudGVyJzsgLy8gYSBtb2R1bGUgaW4gbXkgcHJvamVjdAogICAgICAgICAvLyBMb2cgYSB3YXJuaW5nIGlmIHdlIGhhdmUgbW9yZSB0aGFuIDMgdG9tc3RlcnMKICAgICAgd2FybignVG9vIG1hbnkgdG9tc3RlcnMhJywgdG9tc3RlckNvdW50IDw9IDMsIHsKICAgICAgICBpZDogJ2VtYmVyLWRlYnVnLnRvby1tYW55LXRvbXN0ZXJzJwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAgIEBtZXRob2Qgd2FybgogICAgICBAZm9yIEBlbWJlci9kZWJ1ZwogICAgICBAc3RhdGljCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIEEgd2FybmluZyB0byBkaXNwbGF5LgogICAgICBAcGFyYW0ge0Jvb2xlYW59IHRlc3QgQW4gb3B0aW9uYWwgYm9vbGVhbi4gSWYgZmFsc3ksIHRoZSB3YXJuaW5nCiAgICAgICAgd2lsbCBiZSBkaXNwbGF5ZWQuCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIEFuIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIHBhc3MgYSB1bmlxdWUKICAgICAgICBgaWRgIGZvciB0aGlzIHdhcm5pbmcuICBUaGUgYGlkYCBjYW4gYmUgdXNlZCBieSBFbWJlciBkZWJ1Z2dpbmcgdG9vbHMKICAgICAgICB0byBjaGFuZ2UgdGhlIGJlaGF2aW9yIChyYWlzZSwgbG9nLCBvciBzaWxlbmNlKSBmb3IgdGhhdCBzcGVjaWZpYyB3YXJuaW5nLgogICAgICAgIFRoZSBgaWRgIHNob3VsZCBiZSBuYW1lc3BhY2VkIGJ5IGRvdHMsIGUuZy4gImVtYmVyLWRlYnVnLmZlYXR1cmUtZmxhZy13aXRoLWZlYXR1cmVzLXN0cmlwcGVkIgogICAgICBAcHVibGljCiAgICAgIEBzaW5jZSAxLjAuMAogICAgKi8KCiAgICB3YXJuID0gZnVuY3Rpb24gd2FybihtZXNzYWdlLCB0ZXN0LCBvcHRpb25zKSB7CiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmIHR5cGVvZiB0ZXN0ID09PSAnb2JqZWN0JykgewogICAgICAgIG9wdGlvbnMgPSB0ZXN0OwogICAgICAgIHRlc3QgPSBmYWxzZTsKICAgICAgfQoKICAgICAgKDAsIF9pbmRleC5hc3NlcnQpKG1pc3NpbmdPcHRpb25zRGVwcmVjYXRpb24sIEJvb2xlYW4ob3B0aW9ucykpOwogICAgICAoMCwgX2luZGV4LmFzc2VydCkobWlzc2luZ09wdGlvbnNJZERlcHJlY2F0aW9uLCBCb29sZWFuKG9wdGlvbnMgJiYgb3B0aW9ucy5pZCkpOwogICAgICAoMCwgX2hhbmRsZXJzLmludm9rZSkoJ3dhcm4nLCBtZXNzYWdlLCB0ZXN0LCBvcHRpb25zKTsKICAgIH07CiAgfQoKICB2YXIgX2RlZmF1bHQgPSB3YXJuOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2RlcHJlY2F0ZWQtZmVhdHVyZXMvaW5kZXgiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5NT1VTRV9FTlRFUl9MRUFWRV9NT1ZFX0VWRU5UUyA9IF9leHBvcnRzLkZVTkNUSU9OX1BST1RPVFlQRV9FWFRFTlNJT05TID0gX2V4cG9ydHMuQVBQX0NUUkxfUk9VVEVSX1BST1BTID0gX2V4cG9ydHMuQUxJQVNfTUVUSE9EID0gX2V4cG9ydHMuSlFVRVJZX0lOVEVHUkFUSU9OID0gX2V4cG9ydHMuQ09NUE9ORU5UX01BTkFHRVJfU1RSSU5HX0xPT0tVUCA9IF9leHBvcnRzLlJPVVRFUl9FVkVOVFMgPSBfZXhwb3J0cy5NRVJHRSA9IF9leHBvcnRzLkxPR0dFUiA9IF9leHBvcnRzLkVNQkVSX0VYVEVORF9QUk9UT1RZUEVTID0gX2V4cG9ydHMuU0VORF9BQ1RJT04gPSB2b2lkIDA7CgogIC8qIGVzbGludC1kaXNhYmxlIG5vLWltcGxpY2l0LWNvZXJjaW9uICovCiAgLy8gVGhlc2UgdmVyc2lvbnMgc2hvdWxkIGJlIHRoZSB2ZXJzaW9uIHRoYXQgdGhlIGRlcHJlY2F0aW9uIHdhcyBfaW50cm9kdWNlZF8sCiAgLy8gbm90IHRoZSB2ZXJzaW9uIHRoYXQgdGhlIGZlYXR1cmUgd2lsbCBiZSByZW1vdmVkLgogIHZhciBTRU5EX0FDVElPTiA9ICEhJzMuNC4wJzsKICBfZXhwb3J0cy5TRU5EX0FDVElPTiA9IFNFTkRfQUNUSU9OOwogIHZhciBFTUJFUl9FWFRFTkRfUFJPVE9UWVBFUyA9ICEhJzMuMi4wLWJldGEuNSc7CiAgX2V4cG9ydHMuRU1CRVJfRVhURU5EX1BST1RPVFlQRVMgPSBFTUJFUl9FWFRFTkRfUFJPVE9UWVBFUzsKICB2YXIgTE9HR0VSID0gISEnMy4yLjAtYmV0YS4xJzsKICBfZXhwb3J0cy5MT0dHRVIgPSBMT0dHRVI7CiAgdmFyIE1FUkdFID0gISEnMy42LjAtYmV0YS4xJzsKICBfZXhwb3J0cy5NRVJHRSA9IE1FUkdFOwogIHZhciBST1VURVJfRVZFTlRTID0gISEnNC4wLjAnOwogIF9leHBvcnRzLlJPVVRFUl9FVkVOVFMgPSBST1VURVJfRVZFTlRTOwogIHZhciBDT01QT05FTlRfTUFOQUdFUl9TVFJJTkdfTE9PS1VQID0gISEnMy44LjAnOwogIF9leHBvcnRzLkNPTVBPTkVOVF9NQU5BR0VSX1NUUklOR19MT09LVVAgPSBDT01QT05FTlRfTUFOQUdFUl9TVFJJTkdfTE9PS1VQOwogIHZhciBKUVVFUllfSU5URUdSQVRJT04gPSAhISczLjkuMCc7CiAgX2V4cG9ydHMuSlFVRVJZX0lOVEVHUkFUSU9OID0gSlFVRVJZX0lOVEVHUkFUSU9OOwogIHZhciBBTElBU19NRVRIT0QgPSAhISczLjkuMCc7CiAgX2V4cG9ydHMuQUxJQVNfTUVUSE9EID0gQUxJQVNfTUVUSE9EOwogIHZhciBBUFBfQ1RSTF9ST1VURVJfUFJPUFMgPSAhISczLjEwLjAtYmV0YS4xJzsKICBfZXhwb3J0cy5BUFBfQ1RSTF9ST1VURVJfUFJPUFMgPSBBUFBfQ1RSTF9ST1VURVJfUFJPUFM7CiAgdmFyIEZVTkNUSU9OX1BST1RPVFlQRV9FWFRFTlNJT05TID0gISEnMy4xMS4wLWJldGEuMSc7CiAgX2V4cG9ydHMuRlVOQ1RJT05fUFJPVE9UWVBFX0VYVEVOU0lPTlMgPSBGVU5DVElPTl9QUk9UT1RZUEVfRVhURU5TSU9OUzsKICB2YXIgTU9VU0VfRU5URVJfTEVBVkVfTU9WRV9FVkVOVFMgPSAhISczLjEzLjAtYmV0YS4xJzsKICBfZXhwb3J0cy5NT1VTRV9FTlRFUl9MRUFWRV9NT1ZFX0VWRU5UUyA9IE1PVVNFX0VOVEVSX0xFQVZFX01PVkVfRVZFTlRTOwp9KTsKZGVmaW5lKCJAZW1iZXIvZW5naW5lL2luZGV4IiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBlbWJlci9lbmdpbmUvbGliL2VuZ2luZS1wYXJlbnQiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyL2NvbnRyb2xsZXIiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSIsICJAZW1iZXIvLWludGVybmFscy9jb250YWluZXIiLCAiZGFnLW1hcCIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2FwcGxpY2F0aW9uL2dsb2JhbHMtcmVzb2x2ZXIiLCAiQGVtYmVyL2VuZ2luZS9pbnN0YW5jZSIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nIiwgIkBlbWJlci8taW50ZXJuYWxzL2V4dGVuc2lvbi1zdXBwb3J0IiwgIkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzIiwgIkBlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX2VuZ2luZVBhcmVudCwgX3V0aWxzLCBfY29udHJvbGxlciwgX3J1bnRpbWUsIF9jb250YWluZXIsIF9kYWdNYXAsIF9kZWJ1ZywgX21ldGFsLCBfZ2xvYmFsc1Jlc29sdmVyLCBfaW5zdGFuY2UsIF9yb3V0aW5nLCBfZXh0ZW5zaW9uU3VwcG9ydCwgX3ZpZXdzLCBfZ2xpbW1lcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ2V0RW5naW5lUGFyZW50IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2VuZ2luZVBhcmVudC5nZXRFbmdpbmVQYXJlbnQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0RW5naW5lUGFyZW50IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2VuZ2luZVBhcmVudC5zZXRFbmdpbmVQYXJlbnQ7CiAgICB9CiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0MigpIHsKICAgIHZhciBkYXRhID0gKDAsIF9lbWJlckJhYmVsLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlKShbIi1idWNrZXQtY2FjaGU6bWFpbiJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3QyID0gZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0MigpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0KCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsiLWJ1Y2tldC1jYWNoZTptYWluIl0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdCgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gcHJvcHMob2JqKSB7CiAgICB2YXIgcHJvcGVydGllcyA9IFtdOwoKICAgIGZvciAodmFyIGtleSBpbiBvYmopIHsKICAgICAgcHJvcGVydGllcy5wdXNoKGtleSk7CiAgICB9CgogICAgcmV0dXJuIHByb3BlcnRpZXM7CiAgfQogIC8qKgogIEBtb2R1bGUgQGVtYmVyL2VuZ2luZQogICovCgogIC8qKgogICAgVGhlIGBFbmdpbmVgIGNsYXNzIGNvbnRhaW5zIGNvcmUgZnVuY3Rpb25hbGl0eSBmb3IgYm90aCBhcHBsaWNhdGlvbnMgYW5kCiAgICBlbmdpbmVzLgogIAogICAgRWFjaCBlbmdpbmUgbWFuYWdlcyBhIHJlZ2lzdHJ5IHRoYXQncyB1c2VkIGZvciBkZXBlbmRlbmN5IGluamVjdGlvbiBhbmQKICAgIGV4cG9zZWQgdGhyb3VnaCBgUmVnaXN0cnlQcm94eWAuCiAgCiAgICBFbmdpbmVzIGFsc28gbWFuYWdlIGluaXRpYWxpemVycyBhbmQgaW5zdGFuY2UgaW5pdGlhbGl6ZXJzLgogIAogICAgRW5naW5lcyBjYW4gc3Bhd24gYEVuZ2luZUluc3RhbmNlYCBpbnN0YW5jZXMgdmlhIGBidWlsZEluc3RhbmNlKClgLgogIAogICAgQGNsYXNzIEVuZ2luZQogICAgQGV4dGVuZHMgRW1iZXIuTmFtZXNwYWNlCiAgICBAdXNlcyBSZWdpc3RyeVByb3h5CiAgICBAcHVibGljCiAgKi8KCgogIHZhciBFbmdpbmUgPSBfcnVudGltZS5OYW1lc3BhY2UuZXh0ZW5kKF9ydW50aW1lLlJlZ2lzdHJ5UHJveHlNaXhpbiwgewogICAgaW5pdDogZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIHRoaXMuYnVpbGRSZWdpc3RyeSgpOwogICAgfSwKCiAgICAvKioKICAgICAgQSBwcml2YXRlIGZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIGFuIGVuZ2luZSdzIGluaXRpYWxpemVycyBoYXZlIHJ1biB5ZXQuCiAgICAgICBAcHJpdmF0ZQogICAgICBAcHJvcGVydHkgX2luaXRpYWxpemVyc1JhbgogICAgKi8KICAgIF9pbml0aWFsaXplcnNSYW46IGZhbHNlLAoKICAgIC8qKgogICAgICBFbnN1cmUgdGhhdCBpbml0aWFsaXplcnMgYXJlIHJ1biBvbmNlLCBhbmQgb25seSBvbmNlLCBwZXIgZW5naW5lLgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBlbnN1cmVJbml0aWFsaXplcnMKICAgICovCiAgICBlbnN1cmVJbml0aWFsaXplcnM6IGZ1bmN0aW9uIGVuc3VyZUluaXRpYWxpemVycygpIHsKICAgICAgaWYgKCF0aGlzLl9pbml0aWFsaXplcnNSYW4pIHsKICAgICAgICB0aGlzLnJ1bkluaXRpYWxpemVycygpOwogICAgICAgIHRoaXMuX2luaXRpYWxpemVyc1JhbiA9IHRydWU7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIENyZWF0ZSBhbiBFbmdpbmVJbnN0YW5jZSBmb3IgdGhpcyBlbmdpbmUuCiAgICAgICBAcHVibGljCiAgICAgIEBtZXRob2QgYnVpbGRJbnN0YW5jZQogICAgICBAcmV0dXJuIHtFbmdpbmVJbnN0YW5jZX0gdGhlIGVuZ2luZSBpbnN0YW5jZQogICAgKi8KICAgIGJ1aWxkSW5zdGFuY2U6IGZ1bmN0aW9uIGJ1aWxkSW5zdGFuY2Uob3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICB0aGlzLmVuc3VyZUluaXRpYWxpemVycygpOwogICAgICBvcHRpb25zLmJhc2UgPSB0aGlzOwogICAgICByZXR1cm4gX2luc3RhbmNlLmRlZmF1bHQuY3JlYXRlKG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICAgQnVpbGQgYW5kIGNvbmZpZ3VyZSB0aGUgcmVnaXN0cnkgZm9yIHRoZSBjdXJyZW50IGVuZ2luZS4KICAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgYnVpbGRSZWdpc3RyeQogICAgICBAcmV0dXJuIHtFbWJlci5SZWdpc3RyeX0gdGhlIGNvbmZpZ3VyZWQgcmVnaXN0cnkKICAgICovCiAgICBidWlsZFJlZ2lzdHJ5OiBmdW5jdGlvbiBidWlsZFJlZ2lzdHJ5KCkgewogICAgICB2YXIgcmVnaXN0cnkgPSB0aGlzLl9fcmVnaXN0cnlfXyA9IHRoaXMuY29uc3RydWN0b3IuYnVpbGRSZWdpc3RyeSh0aGlzKTsKICAgICAgcmV0dXJuIHJlZ2lzdHJ5OwogICAgfSwKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBpbml0aWFsaXplcgogICAgKi8KICAgIGluaXRpYWxpemVyOiBmdW5jdGlvbiBpbml0aWFsaXplcihvcHRpb25zKSB7CiAgICAgIHRoaXMuY29uc3RydWN0b3IuaW5pdGlhbGl6ZXIob3B0aW9ucyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGluc3RhbmNlSW5pdGlhbGl6ZXIKICAgICovCiAgICBpbnN0YW5jZUluaXRpYWxpemVyOiBmdW5jdGlvbiBpbnN0YW5jZUluaXRpYWxpemVyKG9wdGlvbnMpIHsKICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5pbnN0YW5jZUluaXRpYWxpemVyKG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBydW5Jbml0aWFsaXplcnMKICAgICovCiAgICBydW5Jbml0aWFsaXplcnM6IGZ1bmN0aW9uIHJ1bkluaXRpYWxpemVycygpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHRoaXMuX3J1bkluaXRpYWxpemVyKCdpbml0aWFsaXplcnMnLCBmdW5jdGlvbiAobmFtZSwgaW5pdGlhbGl6ZXIpIHsKICAgICAgICAoZmFsc2UgJiYgIShCb29sZWFuKGluaXRpYWxpemVyKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJObyBhcHBsaWNhdGlvbiBpbml0aWFsaXplciBuYW1lZCAnIiArIG5hbWUgKyAiJyIsIEJvb2xlYW4oaW5pdGlhbGl6ZXIpKSk7CiAgICAgICAgaW5pdGlhbGl6ZXIuaW5pdGlhbGl6ZShfdGhpcyk7CiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgQHNpbmNlIDEuMTIuMAogICAgICBAbWV0aG9kIHJ1bkluc3RhbmNlSW5pdGlhbGl6ZXJzCiAgICAqLwogICAgcnVuSW5zdGFuY2VJbml0aWFsaXplcnM6IGZ1bmN0aW9uIHJ1bkluc3RhbmNlSW5pdGlhbGl6ZXJzKGluc3RhbmNlKSB7CiAgICAgIHRoaXMuX3J1bkluaXRpYWxpemVyKCdpbnN0YW5jZUluaXRpYWxpemVycycsIGZ1bmN0aW9uIChuYW1lLCBpbml0aWFsaXplcikgewogICAgICAgIChmYWxzZSAmJiAhKEJvb2xlYW4oaW5pdGlhbGl6ZXIpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIk5vIGluc3RhbmNlIGluaXRpYWxpemVyIG5hbWVkICciICsgbmFtZSArICInIiwgQm9vbGVhbihpbml0aWFsaXplcikpKTsKICAgICAgICBpbml0aWFsaXplci5pbml0aWFsaXplKGluc3RhbmNlKTsKICAgICAgfSk7CiAgICB9LAogICAgX3J1bkluaXRpYWxpemVyOiBmdW5jdGlvbiBfcnVuSW5pdGlhbGl6ZXIoYnVja2V0TmFtZSwgY2IpIHsKICAgICAgdmFyIGluaXRpYWxpemVyc0J5TmFtZSA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLmNvbnN0cnVjdG9yLCBidWNrZXROYW1lKTsKICAgICAgdmFyIGluaXRpYWxpemVycyA9IHByb3BzKGluaXRpYWxpemVyc0J5TmFtZSk7CiAgICAgIHZhciBncmFwaCA9IG5ldyBfZGFnTWFwLmRlZmF1bHQoKTsKICAgICAgdmFyIGluaXRpYWxpemVyOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbml0aWFsaXplcnMubGVuZ3RoOyBpKyspIHsKICAgICAgICBpbml0aWFsaXplciA9IGluaXRpYWxpemVyc0J5TmFtZVtpbml0aWFsaXplcnNbaV1dOwogICAgICAgIGdyYXBoLmFkZChpbml0aWFsaXplci5uYW1lLCBpbml0aWFsaXplciwgaW5pdGlhbGl6ZXIuYmVmb3JlLCBpbml0aWFsaXplci5hZnRlcik7CiAgICAgIH0KCiAgICAgIGdyYXBoLnRvcHNvcnQoY2IpOwogICAgfQogIH0pOwoKICBFbmdpbmUucmVvcGVuQ2xhc3MoewogICAgaW5pdGlhbGl6ZXJzOiBPYmplY3QuY3JlYXRlKG51bGwpLAogICAgaW5zdGFuY2VJbml0aWFsaXplcnM6IE9iamVjdC5jcmVhdGUobnVsbCksCgogICAgLyoqCiAgICAgIFRoZSBnb2FsIG9mIGluaXRpYWxpemVycyBzaG91bGQgYmUgdG8gcmVnaXN0ZXIgZGVwZW5kZW5jaWVzIGFuZCBpbmplY3Rpb25zLgogICAgICBUaGlzIHBoYXNlIHJ1bnMgb25jZS4gQmVjYXVzZSB0aGVzZSBpbml0aWFsaXplcnMgbWF5IGxvYWQgY29kZSwgdGhleSBhcmUKICAgICAgYWxsb3dlZCB0byBkZWZlciBhcHBsaWNhdGlvbiByZWFkaW5lc3MgYW5kIGFkdmFuY2UgaXQuIElmIHlvdSBuZWVkIHRvIGFjY2VzcwogICAgICB0aGUgY29udGFpbmVyIG9yIHN0b3JlIHlvdSBzaG91bGQgdXNlIGFuIEluc3RhbmNlSW5pdGlhbGl6ZXIgdGhhdCB3aWxsIGJlIHJ1bgogICAgICBhZnRlciBhbGwgaW5pdGlhbGl6ZXJzIGFuZCB0aGVyZWZvcmUgYWZ0ZXIgYWxsIGNvZGUgaXMgbG9hZGVkIGFuZCB0aGUgYXBwIGlzCiAgICAgIHJlYWR5LgogICAgICAgSW5pdGlhbGl6ZXIgcmVjZWl2ZXMgYW4gb2JqZWN0IHdoaWNoIGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXM6CiAgICAgIGBuYW1lYCwgYGJlZm9yZWAsIGBhZnRlcmAsIGBpbml0aWFsaXplYC4gVGhlIG9ubHkgcmVxdWlyZWQgYXR0cmlidXRlIGlzCiAgICAgIGBpbml0aWFsaXplYCwgYWxsIG90aGVycyBhcmUgb3B0aW9uYWwuCiAgICAgICAqIGBuYW1lYCBhbGxvd3MgeW91IHRvIHNwZWNpZnkgdW5kZXIgd2hpY2ggbmFtZSB0aGUgaW5pdGlhbGl6ZXIgaXMgcmVnaXN0ZXJlZC4KICAgICAgVGhpcyBtdXN0IGJlIGEgdW5pcXVlIG5hbWUsIGFzIHRyeWluZyB0byByZWdpc3RlciB0d28gaW5pdGlhbGl6ZXJzIHdpdGggdGhlCiAgICAgIHNhbWUgbmFtZSB3aWxsIHJlc3VsdCBpbiBhbiBlcnJvci4KICAgICAgIGBgYGFwcC9pbml0aWFsaXplci9uYW1lZC1pbml0aWFsaXplci5qcwogICAgICBpbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJ0BlbWJlci9kZWJ1Zyc7CiAgICAgICBleHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHsKICAgICAgICBkZWJ1ZygnUnVubmluZyBuYW1lZEluaXRpYWxpemVyIScpOwogICAgICB9CiAgICAgICBleHBvcnQgZGVmYXVsdCB7CiAgICAgICAgbmFtZTogJ25hbWVkLWluaXRpYWxpemVyJywKICAgICAgICBpbml0aWFsaXplCiAgICAgIH07CiAgICAgIGBgYAogICAgICAgKiBgYmVmb3JlYCBhbmQgYGFmdGVyYCBhcmUgdXNlZCB0byBlbnN1cmUgdGhhdCB0aGlzIGluaXRpYWxpemVyIGlzIHJhbiBwcmlvcgogICAgICBvciBhZnRlciB0aGUgb25lIGlkZW50aWZpZWQgYnkgdGhlIHZhbHVlLiBUaGlzIHZhbHVlIGNhbiBiZSBhIHNpbmdsZSBzdHJpbmcKICAgICAgb3IgYW4gYXJyYXkgb2Ygc3RyaW5ncywgcmVmZXJlbmNpbmcgdGhlIGBuYW1lYCBvZiBvdGhlciBpbml0aWFsaXplcnMuCiAgICAgICBBbiBleGFtcGxlIG9mIG9yZGVyaW5nIGluaXRpYWxpemVycywgd2UgY3JlYXRlIGFuIGluaXRpYWxpemVyIG5hbWVkIGBmaXJzdGA6CiAgICAgICBgYGBhcHAvaW5pdGlhbGl6ZXIvZmlyc3QuanMKICAgICAgaW1wb3J0IHsgZGVidWcgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7CiAgICAgICAgZGVidWcoJ0ZpcnN0IGluaXRpYWxpemVyIScpOwogICAgICB9CiAgICAgICBleHBvcnQgZGVmYXVsdCB7CiAgICAgICAgbmFtZTogJ2ZpcnN0JywKICAgICAgICBpbml0aWFsaXplCiAgICAgIH07CiAgICAgIGBgYAogICAgICAgYGBgYmFzaAogICAgICAvLyBERUJVRzogRmlyc3QgaW5pdGlhbGl6ZXIhCiAgICAgIGBgYAogICAgICAgV2UgYWRkIGFub3RoZXIgaW5pdGlhbGl6ZXIgbmFtZWQgYHNlY29uZGAsIHNwZWNpZnlpbmcgdGhhdCBpdCBzaG91bGQgcnVuCiAgICAgIGFmdGVyIHRoZSBpbml0aWFsaXplciBuYW1lZCBgZmlyc3RgOgogICAgICAgYGBgYXBwL2luaXRpYWxpemVyL3NlY29uZC5qcwogICAgICBpbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJ0BlbWJlci9kZWJ1Zyc7CiAgICAgICBleHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHsKICAgICAgICBkZWJ1ZygnU2Vjb25kIGluaXRpYWxpemVyIScpOwogICAgICB9CiAgICAgICBleHBvcnQgZGVmYXVsdCB7CiAgICAgICAgbmFtZTogJ3NlY29uZCcsCiAgICAgICAgYWZ0ZXI6ICdmaXJzdCcsCiAgICAgICAgaW5pdGlhbGl6ZQogICAgICB9OwogICAgICBgYGAKICAgICAgIGBgYAogICAgICAvLyBERUJVRzogRmlyc3QgaW5pdGlhbGl6ZXIhCiAgICAgIC8vIERFQlVHOiBTZWNvbmQgaW5pdGlhbGl6ZXIhCiAgICAgIGBgYAogICAgICAgQWZ0ZXJ3YXJkcyB3ZSBhZGQgYSBmdXJ0aGVyIGluaXRpYWxpemVyIG5hbWVkIGBwcmVgLCB0aGlzIHRpbWUgc3BlY2lmeWluZwogICAgICB0aGF0IGl0IHNob3VsZCBydW4gYmVmb3JlIHRoZSBpbml0aWFsaXplciBuYW1lZCBgZmlyc3RgOgogICAgICAgYGBgYXBwL2luaXRpYWxpemVyL3ByZS5qcwogICAgICBpbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJ0BlbWJlci9kZWJ1Zyc7CiAgICAgICBleHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHsKICAgICAgICBkZWJ1ZygnUHJlIGluaXRpYWxpemVyIScpOwogICAgICB9CiAgICAgICBleHBvcnQgZGVmYXVsdCB7CiAgICAgICAgbmFtZTogJ3ByZScsCiAgICAgICAgYmVmb3JlOiAnZmlyc3QnLAogICAgICAgIGluaXRpYWxpemUKICAgICAgfTsKICAgICAgYGBgCiAgICAgICBgYGBiYXNoCiAgICAgIC8vIERFQlVHOiBQcmUgaW5pdGlhbGl6ZXIhCiAgICAgIC8vIERFQlVHOiBGaXJzdCBpbml0aWFsaXplciEKICAgICAgLy8gREVCVUc6IFNlY29uZCBpbml0aWFsaXplciEKICAgICAgYGBgCiAgICAgICBGaW5hbGx5IHdlIGFkZCBhbiBpbml0aWFsaXplciBuYW1lZCBgcG9zdGAsIHNwZWNpZnlpbmcgaXQgc2hvdWxkIHJ1biBhZnRlcgogICAgICBib3RoIHRoZSBgZmlyc3RgIGFuZCB0aGUgYHNlY29uZGAgaW5pdGlhbGl6ZXJzOgogICAgICAgYGBgYXBwL2luaXRpYWxpemVyL3Bvc3QuanMKICAgICAgaW1wb3J0IHsgZGVidWcgfSBmcm9tICdAZW1iZXIvZGVidWcnOwogICAgICAgZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7CiAgICAgICAgZGVidWcoJ1Bvc3QgaW5pdGlhbGl6ZXIhJyk7CiAgICAgIH0KICAgICAgIGV4cG9ydCBkZWZhdWx0IHsKICAgICAgICBuYW1lOiAncG9zdCcsCiAgICAgICAgYWZ0ZXI6IFsnZmlyc3QnLCAnc2Vjb25kJ10sCiAgICAgICAgaW5pdGlhbGl6ZQogICAgICB9OwogICAgICBgYGAKICAgICAgIGBgYGJhc2gKICAgICAgLy8gREVCVUc6IFByZSBpbml0aWFsaXplciEKICAgICAgLy8gREVCVUc6IEZpcnN0IGluaXRpYWxpemVyIQogICAgICAvLyBERUJVRzogU2Vjb25kIGluaXRpYWxpemVyIQogICAgICAvLyBERUJVRzogUG9zdCBpbml0aWFsaXplciEKICAgICAgYGBgCiAgICAgICAqIGBpbml0aWFsaXplYCBpcyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgcmVjZWl2ZXMgb25lIGFyZ3VtZW50LAogICAgICAgIGBhcHBsaWNhdGlvbmAsIG9uIHdoaWNoIHlvdSBjYW4gb3BlcmF0ZS4KICAgICAgIEV4YW1wbGUgb2YgdXNpbmcgYGFwcGxpY2F0aW9uYCB0byByZWdpc3RlciBhbiBhZGFwdGVyOgogICAgICAgYGBgYXBwL2luaXRpYWxpemVyL2FwaS1hZGFwdGVyLmpzCiAgICAgIGltcG9ydCBBcGlBZGFwdGVyIGZyb20gJy4uL3V0aWxzL2FwaS1hZGFwdGVyJzsKICAgICAgIGV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplKGFwcGxpY2F0aW9uKSB7CiAgICAgICAgYXBwbGljYXRpb24ucmVnaXN0ZXIoJ2FwaS1hZGFwdGVyOm1haW4nLCBBcGlBZGFwdGVyKTsKICAgICAgfQogICAgICAgZXhwb3J0IGRlZmF1bHQgewogICAgICAgIG5hbWU6ICdwb3N0JywKICAgICAgICBhZnRlcjogWydmaXJzdCcsICdzZWNvbmQnXSwKICAgICAgICBpbml0aWFsaXplCiAgICAgIH07CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBpbml0aWFsaXplcgogICAgICBAcGFyYW0gaW5pdGlhbGl6ZXIge09iamVjdH0KICAgICAgQHB1YmxpYwogICAgKi8KICAgIGluaXRpYWxpemVyOiBidWlsZEluaXRpYWxpemVyTWV0aG9kKCdpbml0aWFsaXplcnMnLCAnaW5pdGlhbGl6ZXInKSwKCiAgICAvKioKICAgICAgSW5zdGFuY2UgaW5pdGlhbGl6ZXJzIHJ1biBhZnRlciBhbGwgaW5pdGlhbGl6ZXJzIGhhdmUgcnVuLiBCZWNhdXNlCiAgICAgIGluc3RhbmNlIGluaXRpYWxpemVycyBydW4gYWZ0ZXIgdGhlIGFwcCBpcyBmdWxseSBzZXQgdXAuIFdlIGhhdmUgYWNjZXNzCiAgICAgIHRvIHRoZSBzdG9yZSwgY29udGFpbmVyLCBhbmQgb3RoZXIgaXRlbXMuIEhvd2V2ZXIsIHRoZXNlIGluaXRpYWxpemVycyBydW4KICAgICAgYWZ0ZXIgY29kZSBoYXMgbG9hZGVkIGFuZCBhcmUgbm90IGFsbG93ZWQgdG8gZGVmZXIgcmVhZGluZXNzLgogICAgICAgSW5zdGFuY2UgaW5pdGlhbGl6ZXIgcmVjZWl2ZXMgYW4gb2JqZWN0IHdoaWNoIGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXM6CiAgICAgIGBuYW1lYCwgYGJlZm9yZWAsIGBhZnRlcmAsIGBpbml0aWFsaXplYC4gVGhlIG9ubHkgcmVxdWlyZWQgYXR0cmlidXRlIGlzCiAgICAgIGBpbml0aWFsaXplYCwgYWxsIG90aGVycyBhcmUgb3B0aW9uYWwuCiAgICAgICAqIGBuYW1lYCBhbGxvd3MgeW91IHRvIHNwZWNpZnkgdW5kZXIgd2hpY2ggbmFtZSB0aGUgaW5zdGFuY2VJbml0aWFsaXplciBpcwogICAgICByZWdpc3RlcmVkLiBUaGlzIG11c3QgYmUgYSB1bmlxdWUgbmFtZSwgYXMgdHJ5aW5nIHRvIHJlZ2lzdGVyIHR3bwogICAgICBpbnN0YW5jZUluaXRpYWxpemVyIHdpdGggdGhlIHNhbWUgbmFtZSB3aWxsIHJlc3VsdCBpbiBhbiBlcnJvci4KICAgICAgIGBgYGFwcC9pbml0aWFsaXplci9uYW1lZC1pbnN0YW5jZS1pbml0aWFsaXplci5qcwogICAgICBpbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJ0BlbWJlci9kZWJ1Zyc7CiAgICAgICBleHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHsKICAgICAgICBkZWJ1ZygnUnVubmluZyBuYW1lZC1pbnN0YW5jZS1pbml0aWFsaXplciEnKTsKICAgICAgfQogICAgICAgZXhwb3J0IGRlZmF1bHQgewogICAgICAgIG5hbWU6ICduYW1lZC1pbnN0YW5jZS1pbml0aWFsaXplcicsCiAgICAgICAgaW5pdGlhbGl6ZQogICAgICB9OwogICAgICBgYGAKICAgICAgICogYGJlZm9yZWAgYW5kIGBhZnRlcmAgYXJlIHVzZWQgdG8gZW5zdXJlIHRoYXQgdGhpcyBpbml0aWFsaXplciBpcyByYW4gcHJpb3IKICAgICAgb3IgYWZ0ZXIgdGhlIG9uZSBpZGVudGlmaWVkIGJ5IHRoZSB2YWx1ZS4gVGhpcyB2YWx1ZSBjYW4gYmUgYSBzaW5nbGUgc3RyaW5nCiAgICAgIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MsIHJlZmVyZW5jaW5nIHRoZSBgbmFtZWAgb2Ygb3RoZXIgaW5pdGlhbGl6ZXJzLgogICAgICAgKiBTZWUgQXBwbGljYXRpb24uaW5pdGlhbGl6ZXIgZm9yIGRpc2N1c3Npb24gb24gdGhlIHVzYWdlIG9mIGJlZm9yZQogICAgICBhbmQgYWZ0ZXIuCiAgICAgICBFeGFtcGxlIGluc3RhbmNlSW5pdGlhbGl6ZXIgdG8gcHJlbG9hZCBkYXRhIGludG8gdGhlIHN0b3JlLgogICAgICAgYGBgYXBwL2luaXRpYWxpemVyL3ByZWxvYWQtZGF0YS5qcwogICAgICBpbXBvcnQgJCBmcm9tICdqcXVlcnknOwogICAgICAgZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemUoYXBwbGljYXRpb24pIHsKICAgICAgICAgIHZhciB1c2VyQ29uZmlnLCB1c2VyQ29uZmlnRW5jb2RlZCwgc3RvcmU7CiAgICAgICAgICAvLyBXZSBoYXZlIGEgSFRNTCBlc2NhcGVkIEpTT04gcmVwcmVzZW50YXRpb24gb2YgdGhlIHVzZXIncyBiYXNpYwogICAgICAgICAgLy8gY29uZmlndXJhdGlvbiBnZW5lcmF0ZWQgc2VydmVyIHNpZGUgYW5kIHN0b3JlZCBpbiB0aGUgRE9NIG9mIHRoZSBtYWluCiAgICAgICAgICAvLyBpbmRleC5odG1sIGZpbGUuIFRoaXMgYWxsb3dzIHRoZSBhcHAgdG8gaGF2ZSBhY2Nlc3MgdG8gYSBzZXQgb2YgZGF0YQogICAgICAgICAgLy8gd2l0aG91dCBtYWtpbmcgYW55IGFkZGl0aW9uYWwgcmVtb3RlIGNhbGxzLiBHb29kIGZvciBiYXNpYyBkYXRhIHRoYXQgaXMKICAgICAgICAgIC8vIG5lZWRlZCBmb3IgaW1tZWRpYXRlIHJlbmRlcmluZyBvZiB0aGUgcGFnZS4gS2VlcCBpbiBtaW5kLCB0aGlzIGRhdGEsCiAgICAgICAgICAvLyBsaWtlIGFsbCBsb2NhbCBtb2RlbHMgYW5kIGRhdGEgY2FuIGJlIG1hbmlwdWxhdGVkIGJ5IHRoZSB1c2VyLCBzbyBpdAogICAgICAgICAgLy8gc2hvdWxkIG5vdCBiZSByZWxpZWQgdXBvbiBmb3Igc2VjdXJpdHkgb3IgYXV0aG9yaXphdGlvbi4KICAgICAgICAgICAvLyBHcmFiIHRoZSBlbmNvZGVkIGRhdGEgZnJvbSB0aGUgbWV0YSB0YWcKICAgICAgICAgIHVzZXJDb25maWdFbmNvZGVkID0gJCgnaGVhZCBtZXRhW25hbWU9YXBwLXVzZXItY29uZmlnXScpLmF0dHIoJ2NvbnRlbnQnKTsKICAgICAgICAgICAvLyBVbmVzY2FwZSB0aGUgdGV4dCwgdGhlbiBwYXJzZSB0aGUgcmVzdWx0aW5nIEpTT04gaW50byBhIHJlYWwgb2JqZWN0CiAgICAgICAgICB1c2VyQ29uZmlnID0gSlNPTi5wYXJzZSh1bmVzY2FwZSh1c2VyQ29uZmlnRW5jb2RlZCkpOwogICAgICAgICAgIC8vIExvb2t1cCB0aGUgc3RvcmUKICAgICAgICAgIHN0b3JlID0gYXBwbGljYXRpb24ubG9va3VwKCdzZXJ2aWNlOnN0b3JlJyk7CiAgICAgICAgICAgLy8gUHVzaCB0aGUgZW5jb2RlZCBKU09OIGludG8gdGhlIHN0b3JlCiAgICAgICAgICBzdG9yZS5wdXNoUGF5bG9hZCh1c2VyQ29uZmlnKTsKICAgICAgfQogICAgICAgZXhwb3J0IGRlZmF1bHQgewogICAgICAgIG5hbWU6ICduYW1lZC1pbnN0YW5jZS1pbml0aWFsaXplcicsCiAgICAgICAgaW5pdGlhbGl6ZQogICAgICB9OwogICAgICBgYGAKICAgICAgIEBtZXRob2QgaW5zdGFuY2VJbml0aWFsaXplcgogICAgICBAcGFyYW0gaW5zdGFuY2VJbml0aWFsaXplcgogICAgICBAcHVibGljCiAgICAqLwogICAgaW5zdGFuY2VJbml0aWFsaXplcjogYnVpbGRJbml0aWFsaXplck1ldGhvZCgnaW5zdGFuY2VJbml0aWFsaXplcnMnLCAnaW5zdGFuY2UgaW5pdGlhbGl6ZXInKSwKCiAgICAvKioKICAgICAgVGhpcyBjcmVhdGVzIGEgcmVnaXN0cnkgd2l0aCB0aGUgZGVmYXVsdCBFbWJlciBuYW1pbmcgY29udmVudGlvbnMuCiAgICAgICBJdCBhbHNvIGNvbmZpZ3VyZXMgdGhlIHJlZ2lzdHJ5OgogICAgICAgKiByZWdpc3RlcmVkIHZpZXdzIGFyZSBjcmVhdGVkIGV2ZXJ5IHRpbWUgdGhleSBhcmUgbG9va2VkIHVwICh0aGV5IGFyZQogICAgICAgIG5vdCBzaW5nbGV0b25zKQogICAgICAqIHJlZ2lzdGVyZWQgdGVtcGxhdGVzIGFyZSBub3QgZmFjdG9yaWVzOyB0aGUgcmVnaXN0ZXJlZCB2YWx1ZSBpcwogICAgICAgIHJldHVybmVkIGRpcmVjdGx5LgogICAgICAqIHRoZSByb3V0ZXIgcmVjZWl2ZXMgdGhlIGFwcGxpY2F0aW9uIGFzIGl0cyBgbmFtZXNwYWNlYCBwcm9wZXJ0eQogICAgICAqIGFsbCBjb250cm9sbGVycyByZWNlaXZlIHRoZSByb3V0ZXIgYXMgdGhlaXIgYHRhcmdldGAgYW5kIGBjb250cm9sbGVyc2AKICAgICAgICBwcm9wZXJ0aWVzCiAgICAgICogYWxsIGNvbnRyb2xsZXJzIHJlY2VpdmUgdGhlIGFwcGxpY2F0aW9uIGFzIHRoZWlyIGBuYW1lc3BhY2VgIHByb3BlcnR5CiAgICAgICogdGhlIGFwcGxpY2F0aW9uIHZpZXcgcmVjZWl2ZXMgdGhlIGFwcGxpY2F0aW9uIGNvbnRyb2xsZXIgYXMgaXRzCiAgICAgICAgYGNvbnRyb2xsZXJgIHByb3BlcnR5CiAgICAgICogdGhlIGFwcGxpY2F0aW9uIHZpZXcgcmVjZWl2ZXMgdGhlIGFwcGxpY2F0aW9uIHRlbXBsYXRlIGFzIGl0cwogICAgICAgIGBkZWZhdWx0VGVtcGxhdGVgIHByb3BlcnR5CiAgICAgICBAbWV0aG9kIGJ1aWxkUmVnaXN0cnkKICAgICAgQHN0YXRpYwogICAgICBAcGFyYW0ge0FwcGxpY2F0aW9ufSBuYW1lc3BhY2UgdGhlIGFwcGxpY2F0aW9uIGZvciB3aGljaCB0bwogICAgICAgIGJ1aWxkIHRoZSByZWdpc3RyeQogICAgICBAcmV0dXJuIHtFbWJlci5SZWdpc3RyeX0gdGhlIGJ1aWx0IHJlZ2lzdHJ5CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgYnVpbGRSZWdpc3RyeTogZnVuY3Rpb24gYnVpbGRSZWdpc3RyeShuYW1lc3BhY2UpIHsKICAgICAgdmFyIHJlZ2lzdHJ5ID0gbmV3IF9jb250YWluZXIuUmVnaXN0cnkoewogICAgICAgIHJlc29sdmVyOiByZXNvbHZlckZvcihuYW1lc3BhY2UpCiAgICAgIH0pOwogICAgICByZWdpc3RyeS5zZXQgPSBfbWV0YWwuc2V0OwogICAgICByZWdpc3RyeS5yZWdpc3RlcignYXBwbGljYXRpb246bWFpbicsIG5hbWVzcGFjZSwgewogICAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgICB9KTsKICAgICAgY29tbW9uU2V0dXBSZWdpc3RyeShyZWdpc3RyeSk7CiAgICAgICgwLCBfZ2xpbW1lci5zZXR1cEVuZ2luZVJlZ2lzdHJ5KShyZWdpc3RyeSk7CiAgICAgIHJldHVybiByZWdpc3RyeTsKICAgIH0sCgogICAgLyoqCiAgICAgIFNldCB0aGlzIHRvIHByb3ZpZGUgYW4gYWx0ZXJuYXRlIGNsYXNzIHRvIGBEZWZhdWx0UmVzb2x2ZXJgCiAgICAgICBAZGVwcmVjYXRlZCBVc2UgJ1Jlc29sdmVyJyBpbnN0ZWFkCiAgICAgIEBwcm9wZXJ0eSByZXNvbHZlcgogICAgICBAcHVibGljCiAgICAqLwogICAgcmVzb2x2ZXI6IG51bGwsCgogICAgLyoqCiAgICAgIFNldCB0aGlzIHRvIHByb3ZpZGUgYW4gYWx0ZXJuYXRlIGNsYXNzIHRvIGBEZWZhdWx0UmVzb2x2ZXJgCiAgICAgICBAcHJvcGVydHkgcmVzb2x2ZXIKICAgICAgQHB1YmxpYwogICAgKi8KICAgIFJlc29sdmVyOiBudWxsCiAgfSk7CiAgLyoqCiAgICBUaGlzIGZ1bmN0aW9uIGRlZmluZXMgdGhlIGRlZmF1bHQgbG9va3VwIHJ1bGVzIGZvciBjb250YWluZXIgbG9va3VwczoKICAKICAgICogdGVtcGxhdGVzIGFyZSBsb29rZWQgdXAgb24gYEVtYmVyLlRFTVBMQVRFU2AKICAgICogb3RoZXIgbmFtZXMgYXJlIGxvb2tlZCB1cCBvbiB0aGUgYXBwbGljYXRpb24gYWZ0ZXIgY2xhc3NpZnlpbmcgdGhlIG5hbWUuCiAgICAgIEZvciBleGFtcGxlLCBgY29udHJvbGxlcjpwb3N0YCBsb29rcyB1cCBgQXBwLlBvc3RDb250cm9sbGVyYCBieSBkZWZhdWx0LgogICAgKiBpZiB0aGUgZGVmYXVsdCBsb29rdXAgZmFpbHMsIGxvb2sgZm9yIHJlZ2lzdGVyZWQgY2xhc3NlcyBvbiB0aGUgY29udGFpbmVyCiAgCiAgICBUaGlzIGFsbG93cyB0aGUgYXBwbGljYXRpb24gdG8gcmVnaXN0ZXIgZGVmYXVsdCBpbmplY3Rpb25zIGluIHRoZSBjb250YWluZXIKICAgIHRoYXQgY291bGQgYmUgb3ZlcnJpZGRlbiBieSB0aGUgbm9ybWFsIG5hbWluZyBjb252ZW50aW9uLgogIAogICAgQHByaXZhdGUKICAgIEBtZXRob2QgcmVzb2x2ZXJGb3IKICAgIEBwYXJhbSB7RW1iZXIuTmFtZXNwYWNlfSBuYW1lc3BhY2UgdGhlIG5hbWVzcGFjZSB0byBsb29rIGZvciBjbGFzc2VzCiAgICBAcmV0dXJuIHsqfSB0aGUgcmVzb2x2ZWQgdmFsdWUgZm9yIGEgZ2l2ZW4gbG9va3VwCiAgKi8KCiAgZnVuY3Rpb24gcmVzb2x2ZXJGb3IobmFtZXNwYWNlKSB7CiAgICB2YXIgUmVzb2x2ZXJDbGFzcyA9ICgwLCBfbWV0YWwuZ2V0KShuYW1lc3BhY2UsICdSZXNvbHZlcicpIHx8IF9nbG9iYWxzUmVzb2x2ZXIuZGVmYXVsdDsKCiAgICB2YXIgcHJvcHMgPSB7CiAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlCiAgICB9OwogICAgcmV0dXJuIFJlc29sdmVyQ2xhc3MuY3JlYXRlKHByb3BzKTsKICB9CgogIGZ1bmN0aW9uIGJ1aWxkSW5pdGlhbGl6ZXJNZXRob2QoYnVja2V0TmFtZSwgaHVtYW5OYW1lKSB7CiAgICByZXR1cm4gZnVuY3Rpb24gKGluaXRpYWxpemVyKSB7CiAgICAgIC8vIElmIHRoaXMgaXMgdGhlIGZpcnN0IGluaXRpYWxpemVyIGJlaW5nIGFkZGVkIHRvIGEgc3ViY2xhc3MsIHdlIGFyZSBnb2luZyB0byByZW9wZW4gdGhlIGNsYXNzCiAgICAgIC8vIHRvIG1ha2Ugc3VyZSB3ZSBoYXZlIGEgbmV3IGBpbml0aWFsaXplcnNgIG9iamVjdCwgd2hpY2ggZXh0ZW5kcyBmcm9tIHRoZSBwYXJlbnQgY2xhc3MnIHVzaW5nCiAgICAgIC8vIHByb3RvdHlwYWwgaW5oZXJpdGFuY2UuIFdpdGhvdXQgdGhpcywgYXR0ZW1wdGluZyB0byBhZGQgaW5pdGlhbGl6ZXJzIHRvIHRoZSBzdWJjbGFzcyB3b3VsZAogICAgICAvLyBwb2xsdXRlIHRoZSBwYXJlbnQgY2xhc3MgYXMgd2VsbCBhcyBvdGhlciBzdWJjbGFzc2VzLgogICAgICBpZiAodGhpcy5zdXBlcmNsYXNzW2J1Y2tldE5hbWVdICE9PSB1bmRlZmluZWQgJiYgdGhpcy5zdXBlcmNsYXNzW2J1Y2tldE5hbWVdID09PSB0aGlzW2J1Y2tldE5hbWVdKSB7CiAgICAgICAgdmFyIGF0dHJzID0ge307CiAgICAgICAgYXR0cnNbYnVja2V0TmFtZV0gPSBPYmplY3QuY3JlYXRlKHRoaXNbYnVja2V0TmFtZV0pOwogICAgICAgIHRoaXMucmVvcGVuQ2xhc3MoYXR0cnMpOwogICAgICB9CgogICAgICAoZmFsc2UgJiYgISghdGhpc1tidWNrZXROYW1lXVtpbml0aWFsaXplci5uYW1lXSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJUaGUgIiArIGh1bWFuTmFtZSArICIgJyIgKyBpbml0aWFsaXplci5uYW1lICsgIicgaGFzIGFscmVhZHkgYmVlbiByZWdpc3RlcmVkIiwgIXRoaXNbYnVja2V0TmFtZV1baW5pdGlhbGl6ZXIubmFtZV0pKTsKICAgICAgKGZhbHNlICYmICEoKDAsIF91dGlscy5jYW5JbnZva2UpKGluaXRpYWxpemVyLCAnaW5pdGlhbGl6ZScpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkFuICIgKyBodW1hbk5hbWUgKyAiIGNhbm5vdCBiZSByZWdpc3RlcmVkIHdpdGhvdXQgYW4gaW5pdGlhbGl6ZSBmdW5jdGlvbiIsICgwLCBfdXRpbHMuY2FuSW52b2tlKShpbml0aWFsaXplciwgJ2luaXRpYWxpemUnKSkpOwogICAgICAoZmFsc2UgJiYgIShpbml0aWFsaXplci5uYW1lICE9PSB1bmRlZmluZWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQW4gIiArIGh1bWFuTmFtZSArICIgY2Fubm90IGJlIHJlZ2lzdGVyZWQgd2l0aG91dCBhIG5hbWUgcHJvcGVydHkiLCBpbml0aWFsaXplci5uYW1lICE9PSB1bmRlZmluZWQpKTsKICAgICAgdGhpc1tidWNrZXROYW1lXVtpbml0aWFsaXplci5uYW1lXSA9IGluaXRpYWxpemVyOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIGNvbW1vblNldHVwUmVnaXN0cnkocmVnaXN0cnkpIHsKICAgIHJlZ2lzdHJ5Lm9wdGlvbnNGb3JUeXBlKCdjb21wb25lbnQnLCB7CiAgICAgIHNpbmdsZXRvbjogZmFsc2UKICAgIH0pOwogICAgcmVnaXN0cnkub3B0aW9uc0ZvclR5cGUoJ3ZpZXcnLCB7CiAgICAgIHNpbmdsZXRvbjogZmFsc2UKICAgIH0pOwogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ2NvbnRyb2xsZXI6YmFzaWMnLCBfY29udHJvbGxlci5kZWZhdWx0LCB7CiAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgfSk7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3ZpZXcnLCAnX3ZpZXdSZWdpc3RyeScsICctdmlldy1yZWdpc3RyeTptYWluJyk7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3JlbmRlcmVyJywgJ192aWV3UmVnaXN0cnknLCAnLXZpZXctcmVnaXN0cnk6bWFpbicpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdyb3V0ZScsICdfdG9wTGV2ZWxWaWV3VGVtcGxhdGUnLCAndGVtcGxhdGU6LW91dGxldCcpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCd2aWV3Oi1vdXRsZXQnLCAnbmFtZXNwYWNlJywgJ2FwcGxpY2F0aW9uOm1haW4nKTsKICAgIHJlZ2lzdHJ5LmluamVjdGlvbignY29udHJvbGxlcicsICd0YXJnZXQnLCAncm91dGVyOm1haW4nKTsKICAgIHJlZ2lzdHJ5LmluamVjdGlvbignY29udHJvbGxlcicsICduYW1lc3BhY2UnLCAnYXBwbGljYXRpb246bWFpbicpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdyb3V0ZXInLCAnX2J1Y2tldENhY2hlJywgKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3QoKSkpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdyb3V0ZScsICdfYnVja2V0Q2FjaGUnLCAoMCwgX2NvbnRhaW5lci5wcml2YXRpemUpKF90ZW1wbGF0ZU9iamVjdDIoKSkpOwogICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdyb3V0ZScsICdfcm91dGVyJywgJ3JvdXRlcjptYWluJyk7IC8vIFJlZ2lzdGVyIHRoZSByb3V0aW5nIHNlcnZpY2UuLi4KCiAgICByZWdpc3RyeS5yZWdpc3Rlcignc2VydmljZTotcm91dGluZycsIF9yb3V0aW5nLlJvdXRpbmdTZXJ2aWNlKTsgLy8gVGhlbiBpbmplY3QgdGhlIGFwcCByb3V0ZXIgaW50byBpdAoKICAgIHJlZ2lzdHJ5LmluamVjdGlvbignc2VydmljZTotcm91dGluZycsICdyb3V0ZXInLCAncm91dGVyOm1haW4nKTsgLy8gREVCVUdHSU5HCgogICAgcmVnaXN0cnkucmVnaXN0ZXIoJ3Jlc29sdmVyLWZvci1kZWJ1Z2dpbmc6bWFpbicsIHJlZ2lzdHJ5LnJlc29sdmVyLCB7CiAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgfSk7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ2NvbnRhaW5lci1kZWJ1Zy1hZGFwdGVyOm1haW4nLCAncmVzb2x2ZXInLCAncmVzb2x2ZXItZm9yLWRlYnVnZ2luZzptYWluJyk7CiAgICByZWdpc3RyeS5pbmplY3Rpb24oJ2RhdGEtYWRhcHRlcjptYWluJywgJ2NvbnRhaW5lckRlYnVnQWRhcHRlcicsICdjb250YWluZXItZGVidWctYWRhcHRlcjptYWluJyk7IC8vIEN1c3RvbSByZXNvbHZlciBhdXRob3JzIG1heSB3YW50IHRvIHJlZ2lzdGVyIHRoZWlyIG93biBDb250YWluZXJEZWJ1Z0FkYXB0ZXIgd2l0aCB0aGlzIGtleQoKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdjb250YWluZXItZGVidWctYWRhcHRlcjptYWluJywgX2V4dGVuc2lvblN1cHBvcnQuQ29udGFpbmVyRGVidWdBZGFwdGVyKTsKICAgIHJlZ2lzdHJ5LnJlZ2lzdGVyKCdjb21wb25lbnQtbG9va3VwOm1haW4nLCBfdmlld3MuQ29tcG9uZW50TG9va3VwKTsKICB9CgogIHZhciBfZGVmYXVsdCA9IEVuZ2luZTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci9lbmdpbmUvaW5zdGFuY2UiLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyL2Vycm9yIiwgIkBlbWJlci8taW50ZXJuYWxzL2NvbnRhaW5lciIsICJAZW1iZXIvZW5naW5lL2xpYi9lbmdpbmUtcGFyZW50Il0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2VtYmVyQmFiZWwsIF91dGlscywgX3J1bnRpbWUsIF9kZWJ1ZywgX2Vycm9yLCBfY29udGFpbmVyLCBfZW5naW5lUGFyZW50KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICBmdW5jdGlvbiBfdGVtcGxhdGVPYmplY3QyKCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsidGVtcGxhdGUtY29tcGlsZXI6bWFpbiJdKTsKCiAgICBfdGVtcGxhdGVPYmplY3QyID0gZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0MigpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgZnVuY3Rpb24gX3RlbXBsYXRlT2JqZWN0KCkgewogICAgdmFyIGRhdGEgPSAoMCwgX2VtYmVyQmFiZWwudGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2UpKFsiLWJ1Y2tldC1jYWNoZTptYWluIl0pOwoKICAgIF90ZW1wbGF0ZU9iamVjdCA9IGZ1bmN0aW9uIF90ZW1wbGF0ZU9iamVjdCgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9OwoKICAgIHJldHVybiBkYXRhOwogIH0KCiAgLyoqCiAgICBUaGUgYEVuZ2luZUluc3RhbmNlYCBlbmNhcHN1bGF0ZXMgYWxsIG9mIHRoZSBzdGF0ZWZ1bCBhc3BlY3RzIG9mIGEKICAgIHJ1bm5pbmcgYEVuZ2luZWAuCiAgCiAgICBAcHVibGljCiAgICBAY2xhc3MgRW5naW5lSW5zdGFuY2UKICAgIEBleHRlbmRzIEVtYmVyT2JqZWN0CiAgICBAdXNlcyBSZWdpc3RyeVByb3h5TWl4aW4KICAgIEB1c2VzIENvbnRhaW5lclByb3h5TWl4aW4KICAqLwogIHZhciBFbmdpbmVJbnN0YW5jZSA9IF9ydW50aW1lLk9iamVjdC5leHRlbmQoX3J1bnRpbWUuUmVnaXN0cnlQcm94eU1peGluLCBfcnVudGltZS5Db250YWluZXJQcm94eU1peGluLCB7CiAgICAvKioKICAgICAgVGhlIGJhc2UgYEVuZ2luZWAgZm9yIHdoaWNoIHRoaXMgaXMgYW4gaW5zdGFuY2UuCiAgICAgICBAcHJvcGVydHkge0VuZ2luZX0gZW5naW5lCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgYmFzZTogbnVsbCwKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAoMCwgX3V0aWxzLmd1aWRGb3IpKHRoaXMpOwogICAgICB2YXIgYmFzZSA9IHRoaXMuYmFzZTsKCiAgICAgIGlmICghYmFzZSkgewogICAgICAgIGJhc2UgPSB0aGlzLmFwcGxpY2F0aW9uOwogICAgICAgIHRoaXMuYmFzZSA9IGJhc2U7CiAgICAgIH0gLy8gQ3JlYXRlIGEgcGVyLWluc3RhbmNlIHJlZ2lzdHJ5IHRoYXQgd2lsbCB1c2UgdGhlIGFwcGxpY2F0aW9uJ3MgcmVnaXN0cnkKICAgICAgLy8gYXMgYSBmYWxsYmFjayBmb3IgcmVzb2x2aW5nIHJlZ2lzdHJhdGlvbnMuCgoKICAgICAgdmFyIHJlZ2lzdHJ5ID0gdGhpcy5fX3JlZ2lzdHJ5X18gPSBuZXcgX2NvbnRhaW5lci5SZWdpc3RyeSh7CiAgICAgICAgZmFsbGJhY2s6IGJhc2UuX19yZWdpc3RyeV9fCiAgICAgIH0pOyAvLyBDcmVhdGUgYSBwZXItaW5zdGFuY2UgY29udGFpbmVyIGZyb20gdGhlIGluc3RhbmNlJ3MgcmVnaXN0cnkKCiAgICAgIHRoaXMuX19jb250YWluZXJfXyA9IHJlZ2lzdHJ5LmNvbnRhaW5lcih7CiAgICAgICAgb3duZXI6IHRoaXMKICAgICAgfSk7CiAgICAgIHRoaXMuX2Jvb3RlZCA9IGZhbHNlOwogICAgfSwKCiAgICAvKioKICAgICAgSW5pdGlhbGl6ZSB0aGUgYEVuZ2luZUluc3RhbmNlYCBhbmQgcmV0dXJuIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzCiAgICAgIHdpdGggdGhlIGluc3RhbmNlIGl0c2VsZiB3aGVuIHRoZSBib290IHByb2Nlc3MgaXMgY29tcGxldGUuCiAgICAgICBUaGUgcHJpbWFyeSB0YXNrIGhlcmUgaXMgdG8gcnVuIGFueSByZWdpc3RlcmVkIGluc3RhbmNlIGluaXRpYWxpemVycy4KICAgICAgIFNlZSB0aGUgZG9jdW1lbnRhdGlvbiBvbiBgQm9vdE9wdGlvbnNgIGZvciB0aGUgb3B0aW9ucyBpdCB0YWtlcy4KICAgICAgIEBwdWJsaWMKICAgICAgQG1ldGhvZCBib290CiAgICAgIEBwYXJhbSBvcHRpb25zIHtPYmplY3R9CiAgICAgIEByZXR1cm4ge1Byb21pc2U8RW5naW5lSW5zdGFuY2UsRXJyb3I+fQogICAgKi8KICAgIGJvb3Q6IGZ1bmN0aW9uIGJvb3Qob3B0aW9ucykgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgaWYgKHRoaXMuX2Jvb3RQcm9taXNlKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2Jvb3RQcm9taXNlOwogICAgICB9CgogICAgICB0aGlzLl9ib290UHJvbWlzZSA9IG5ldyBfcnVudGltZS5SU1ZQLlByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUpIHsKICAgICAgICByZXR1cm4gcmVzb2x2ZShfdGhpcy5fYm9vdFN5bmMob3B0aW9ucykpOwogICAgICB9KTsKICAgICAgcmV0dXJuIHRoaXMuX2Jvb3RQcm9taXNlOwogICAgfSwKCiAgICAvKioKICAgICAgVW5mb3J0dW5hdGVseSwgYSBsb3Qgb2YgZXhpc3RpbmcgY29kZSBhc3N1bWVzIGJvb3RpbmcgYW4gaW5zdGFuY2UgaXMKICAgICAgc3luY2hyb25vdXMg4oCTIHNwZWNpZmljYWxseSwgYSBsb3Qgb2YgdGVzdHMgYXNzdW1lIHRoZSBsYXN0IGNhbGwgdG8KICAgICAgYGFwcC5hZHZhbmNlUmVhZGluZXNzKClgIG9yIGBhcHAucmVzZXQoKWAgd2lsbCByZXN1bHQgaW4gYSBuZXcgaW5zdGFuY2UKICAgICAgYmVpbmcgZnVsbHktYm9vdGVkIHdoZW4gdGhlIGN1cnJlbnQgcnVubG9vcCBjb21wbGV0ZXMuCiAgICAgICBXZSB3b3VsZCBsaWtlIG5ldyBjb2RlIChsaWtlIHRoZSBgdmlzaXRgIEFQSSkgdG8gc3RvcCBtYWtpbmcgdGhpcwogICAgICBhc3N1bXB0aW9uLCBzbyB3ZSBjcmVhdGVkIHRoZSBhc3luY2hyb25vdXMgdmVyc2lvbiBhYm92ZSB0aGF0IHJldHVybnMgYQogICAgICBwcm9taXNlLiBCdXQgdW50aWwgd2UgaGF2ZSBtaWdyYXRlZCBhbGwgdGhlIGNvZGUsIHdlIHdvdWxkIGhhdmUgdG8gZXhwb3NlCiAgICAgIHRoaXMgbWV0aG9kIGZvciB1c2UgKmludGVybmFsbHkqIGluIHBsYWNlcyB3aGVyZSB3ZSBuZWVkIHRvIGJvb3QgYW4gaW5zdGFuY2UKICAgICAgc3luY2hyb25vdXNseS4KICAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX2Jvb3RTeW5jOiBmdW5jdGlvbiBfYm9vdFN5bmMob3B0aW9ucykgewogICAgICBpZiAodGhpcy5fYm9vdGVkKSB7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKCgwLCBfZW5naW5lUGFyZW50LmdldEVuZ2luZVBhcmVudCkodGhpcykpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiQW4gZW5naW5lIGluc3RhbmNlJ3MgcGFyZW50IG11c3QgYmUgc2V0IHZpYSBgc2V0RW5naW5lUGFyZW50KGVuZ2luZSwgcGFyZW50KWAgcHJpb3IgdG8gY2FsbGluZyBgZW5naW5lLmJvb3QoKWAuIiwgKDAsIF9lbmdpbmVQYXJlbnQuZ2V0RW5naW5lUGFyZW50KSh0aGlzKSkpOwogICAgICB0aGlzLmNsb25lUGFyZW50RGVwZW5kZW5jaWVzKCk7CiAgICAgIHRoaXMuc2V0dXBSZWdpc3RyeShvcHRpb25zKTsKICAgICAgdGhpcy5iYXNlLnJ1bkluc3RhbmNlSW5pdGlhbGl6ZXJzKHRoaXMpOwogICAgICB0aGlzLl9ib290ZWQgPSB0cnVlOwogICAgICByZXR1cm4gdGhpczsKICAgIH0sCiAgICBzZXR1cFJlZ2lzdHJ5OiBmdW5jdGlvbiBzZXR1cFJlZ2lzdHJ5KG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB0aGlzLl9fY29udGFpbmVyX18ubG9va3VwKCctZW52aXJvbm1lbnQ6bWFpbicpOwogICAgICB9CgogICAgICB0aGlzLmNvbnN0cnVjdG9yLnNldHVwUmVnaXN0cnkodGhpcy5fX3JlZ2lzdHJ5X18sIG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICBVbnJlZ2lzdGVyIGEgZmFjdG9yeS4KICAgICAgT3ZlcnJpZGVzIGBSZWdpc3RyeVByb3h5I3VucmVnaXN0ZXJgIGluIG9yZGVyIHRvIGNsZWFyIGFueSBjYWNoZWQgaW5zdGFuY2VzCiAgICAgb2YgdGhlIHVucmVnaXN0ZXJlZCBmYWN0b3J5LgogICAgICBAcHVibGljCiAgICAgQG1ldGhvZCB1bnJlZ2lzdGVyCiAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxOYW1lCiAgICAgKi8KICAgIHVucmVnaXN0ZXI6IGZ1bmN0aW9uIHVucmVnaXN0ZXIoZnVsbE5hbWUpIHsKICAgICAgdGhpcy5fX2NvbnRhaW5lcl9fLnJlc2V0KGZ1bGxOYW1lKTsKCiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qKgogICAgICBCdWlsZCBhIG5ldyBgRW5naW5lSW5zdGFuY2VgIHRoYXQncyBhIGNoaWxkIG9mIHRoaXMgaW5zdGFuY2UuCiAgICAgICBFbmdpbmVzIG11c3QgYmUgcmVnaXN0ZXJlZCBieSBuYW1lIHdpdGggdGhlaXIgcGFyZW50IGVuZ2luZQogICAgICAob3IgYXBwbGljYXRpb24pLgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBidWlsZENoaWxkRW5naW5lSW5zdGFuY2UKICAgICAgQHBhcmFtIG5hbWUge1N0cmluZ30gdGhlIHJlZ2lzdGVyZWQgbmFtZSBvZiB0aGUgZW5naW5lLgogICAgICBAcGFyYW0gb3B0aW9ucyB7T2JqZWN0fSBvcHRpb25zIHByb3ZpZGVkIHRvIHRoZSBlbmdpbmUgaW5zdGFuY2UuCiAgICAgIEByZXR1cm4ge0VuZ2luZUluc3RhbmNlLEVycm9yfQogICAgKi8KICAgIGJ1aWxkQ2hpbGRFbmdpbmVJbnN0YW5jZTogZnVuY3Rpb24gYnVpbGRDaGlsZEVuZ2luZUluc3RhbmNlKG5hbWUsIG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgfQoKICAgICAgdmFyIEVuZ2luZSA9IHRoaXMubG9va3VwKCJlbmdpbmU6IiArIG5hbWUpOwoKICAgICAgaWYgKCFFbmdpbmUpIHsKICAgICAgICB0aHJvdyBuZXcgX2Vycm9yLmRlZmF1bHQoIllvdSBhdHRlbXB0ZWQgdG8gbW91bnQgdGhlIGVuZ2luZSAnIiArIG5hbWUgKyAiJywgYnV0IGl0IGlzIG5vdCByZWdpc3RlcmVkIHdpdGggaXRzIHBhcmVudC4iKTsKICAgICAgfQoKICAgICAgdmFyIGVuZ2luZUluc3RhbmNlID0gRW5naW5lLmJ1aWxkSW5zdGFuY2Uob3B0aW9ucyk7CiAgICAgICgwLCBfZW5naW5lUGFyZW50LnNldEVuZ2luZVBhcmVudCkoZW5naW5lSW5zdGFuY2UsIHRoaXMpOwogICAgICByZXR1cm4gZW5naW5lSW5zdGFuY2U7CiAgICB9LAoKICAgIC8qKgogICAgICBDbG9uZSBkZXBlbmRlbmNpZXMgc2hhcmVkIGJldHdlZW4gYW4gZW5naW5lIGluc3RhbmNlIGFuZCBpdHMgcGFyZW50LgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBjbG9uZVBhcmVudERlcGVuZGVuY2llcwogICAgKi8KICAgIGNsb25lUGFyZW50RGVwZW5kZW5jaWVzOiBmdW5jdGlvbiBjbG9uZVBhcmVudERlcGVuZGVuY2llcygpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICB2YXIgcGFyZW50ID0gKDAsIF9lbmdpbmVQYXJlbnQuZ2V0RW5naW5lUGFyZW50KSh0aGlzKTsKICAgICAgdmFyIHJlZ2lzdHJhdGlvbnMgPSBbJ3JvdXRlOmJhc2ljJywgJ3NlcnZpY2U6LXJvdXRpbmcnLCAnc2VydmljZTotZ2xpbW1lci1lbnZpcm9ubWVudCddOwogICAgICByZWdpc3RyYXRpb25zLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgIHJldHVybiBfdGhpczIucmVnaXN0ZXIoa2V5LCBwYXJlbnQucmVzb2x2ZVJlZ2lzdHJhdGlvbihrZXkpKTsKICAgICAgfSk7CiAgICAgIHZhciBlbnYgPSBwYXJlbnQubG9va3VwKCctZW52aXJvbm1lbnQ6bWFpbicpOwogICAgICB0aGlzLnJlZ2lzdGVyKCctZW52aXJvbm1lbnQ6bWFpbicsIGVudiwgewogICAgICAgIGluc3RhbnRpYXRlOiBmYWxzZQogICAgICB9KTsKICAgICAgdmFyIHNpbmdsZXRvbnMgPSBbJ3JvdXRlcjptYWluJywgKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3QoKSksICctdmlldy1yZWdpc3RyeTptYWluJywgInJlbmRlcmVyOi0iICsgKGVudi5pc0ludGVyYWN0aXZlID8gJ2RvbScgOiAnaW5lcnQnKSwgJ3NlcnZpY2U6LWRvY3VtZW50JywgKDAsIF9jb250YWluZXIucHJpdmF0aXplKShfdGVtcGxhdGVPYmplY3QyKCkpXTsKCiAgICAgIGlmIChlbnYuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIHNpbmdsZXRvbnMucHVzaCgnZXZlbnRfZGlzcGF0Y2hlcjptYWluJyk7CiAgICAgIH0KCiAgICAgIHNpbmdsZXRvbnMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgcmV0dXJuIF90aGlzMi5yZWdpc3RlcihrZXksIHBhcmVudC5sb29rdXAoa2V5KSwgewogICAgICAgICAgaW5zdGFudGlhdGU6IGZhbHNlCiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICB0aGlzLmluamVjdCgndmlldycsICdfZW52aXJvbm1lbnQnLCAnLWVudmlyb25tZW50Om1haW4nKTsKICAgICAgdGhpcy5pbmplY3QoJ3JvdXRlJywgJ19lbnZpcm9ubWVudCcsICctZW52aXJvbm1lbnQ6bWFpbicpOwogICAgfQogIH0pOwoKICBFbmdpbmVJbnN0YW5jZS5yZW9wZW5DbGFzcyh7CiAgICAvKioKICAgICBAcHJpdmF0ZQogICAgIEBtZXRob2Qgc2V0dXBSZWdpc3RyeQogICAgIEBwYXJhbSB7UmVnaXN0cnl9IHJlZ2lzdHJ5CiAgICAgQHBhcmFtIHtCb290T3B0aW9uc30gb3B0aW9ucwogICAgICovCiAgICBzZXR1cFJlZ2lzdHJ5OiBmdW5jdGlvbiBzZXR1cFJlZ2lzdHJ5KHJlZ2lzdHJ5LCBvcHRpb25zKSB7CiAgICAgIC8vIHdoZW4gbm8gb3B0aW9ucy9lbnZpcm9ubWVudCBpcyBwcmVzZW50LCBkbyBub3RoaW5nCiAgICAgIGlmICghb3B0aW9ucykgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgcmVnaXN0cnkuaW5qZWN0aW9uKCd2aWV3JywgJ19lbnZpcm9ubWVudCcsICctZW52aXJvbm1lbnQ6bWFpbicpOwogICAgICByZWdpc3RyeS5pbmplY3Rpb24oJ3JvdXRlJywgJ19lbnZpcm9ubWVudCcsICctZW52aXJvbm1lbnQ6bWFpbicpOwoKICAgICAgaWYgKG9wdGlvbnMuaXNJbnRlcmFjdGl2ZSkgewogICAgICAgIHJlZ2lzdHJ5LmluamVjdGlvbigndmlldycsICdyZW5kZXJlcicsICdyZW5kZXJlcjotZG9tJyk7CiAgICAgICAgcmVnaXN0cnkuaW5qZWN0aW9uKCdjb21wb25lbnQnLCAncmVuZGVyZXInLCAncmVuZGVyZXI6LWRvbScpOwogICAgICB9IGVsc2UgewogICAgICAgIHJlZ2lzdHJ5LmluamVjdGlvbigndmlldycsICdyZW5kZXJlcicsICdyZW5kZXJlcjotaW5lcnQnKTsKICAgICAgICByZWdpc3RyeS5pbmplY3Rpb24oJ2NvbXBvbmVudCcsICdyZW5kZXJlcicsICdyZW5kZXJlcjotaW5lcnQnKTsKICAgICAgfQogICAgfQogIH0pOwogIHZhciBfZGVmYXVsdCA9IEVuZ2luZUluc3RhbmNlOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2VuZ2luZS9saWIvZW5naW5lLXBhcmVudCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy91dGlscyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF91dGlscykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZ2V0RW5naW5lUGFyZW50ID0gZ2V0RW5naW5lUGFyZW50OwogIF9leHBvcnRzLnNldEVuZ2luZVBhcmVudCA9IHNldEVuZ2luZVBhcmVudDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvZW5naW5lCiAgKi8KICB2YXIgRU5HSU5FX1BBUkVOVCA9ICgwLCBfdXRpbHMuc3ltYm9sKSgnRU5HSU5FX1BBUkVOVCcpOwogIC8qKgogICAgYGdldEVuZ2luZVBhcmVudGAgcmV0cmlldmVzIGFuIGVuZ2luZSBpbnN0YW5jZSdzIHBhcmVudCBpbnN0YW5jZS4KICAKICAgIEBtZXRob2QgZ2V0RW5naW5lUGFyZW50CiAgICBAcGFyYW0ge0VuZ2luZUluc3RhbmNlfSBlbmdpbmUgQW4gZW5naW5lIGluc3RhbmNlLgogICAgQHJldHVybiB7RW5naW5lSW5zdGFuY2V9IFRoZSBwYXJlbnQgZW5naW5lIGluc3RhbmNlLgogICAgQGZvciBAZW1iZXIvZW5naW5lCiAgICBAc3RhdGljCiAgICBAcHJpdmF0ZQogICovCgogIGZ1bmN0aW9uIGdldEVuZ2luZVBhcmVudChlbmdpbmUpIHsKICAgIHJldHVybiBlbmdpbmVbRU5HSU5FX1BBUkVOVF07CiAgfQogIC8qKgogICAgYHNldEVuZ2luZVBhcmVudGAgc2V0cyBhbiBlbmdpbmUgaW5zdGFuY2UncyBwYXJlbnQgaW5zdGFuY2UuCiAgCiAgICBAbWV0aG9kIHNldEVuZ2luZVBhcmVudAogICAgQHBhcmFtIHtFbmdpbmVJbnN0YW5jZX0gZW5naW5lIEFuIGVuZ2luZSBpbnN0YW5jZS4KICAgIEBwYXJhbSB7RW5naW5lSW5zdGFuY2V9IHBhcmVudCBUaGUgcGFyZW50IGVuZ2luZSBpbnN0YW5jZS4KICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIHNldEVuZ2luZVBhcmVudChlbmdpbmUsIHBhcmVudCkgewogICAgZW5naW5lW0VOR0lORV9QQVJFTlRdID0gcGFyZW50OwogIH0KfSk7CmRlZmluZSgiQGVtYmVyL2Vycm9yL2luZGV4IiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgIEBtb2R1bGUgQGVtYmVyL2Vycm9yCiAgKi8KCiAgLyoqCiAgICBUaGUgSmF2YVNjcmlwdCBFcnJvciBvYmplY3QgdXNlZCBieSBFbWJlci5hc3NlcnQuCiAgCiAgICBAY2xhc3MgRXJyb3IKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAgIEBleHRlbmRzIEVycm9yCiAgICBAY29uc3RydWN0b3IKICAgIEBwdWJsaWMKICAqLwogIHZhciBfZGVmYXVsdCA9IEVycm9yOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL2luc3RydW1lbnRhdGlvbi9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbnZpcm9ubWVudCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuaW5zdHJ1bWVudCA9IGluc3RydW1lbnQ7CiAgX2V4cG9ydHMuX2luc3RydW1lbnRTdGFydCA9IF9pbnN0cnVtZW50U3RhcnQ7CiAgX2V4cG9ydHMuc3Vic2NyaWJlID0gc3Vic2NyaWJlOwogIF9leHBvcnRzLnVuc3Vic2NyaWJlID0gdW5zdWJzY3JpYmU7CiAgX2V4cG9ydHMucmVzZXQgPSByZXNldDsKICBfZXhwb3J0cy5mbGFnZ2VkSW5zdHJ1bWVudCA9IF9leHBvcnRzLnN1YnNjcmliZXJzID0gdm9pZCAwOwoKICAvKiBlc2xpbnQgbm8tY29uc29sZTpvZmYgKi8KCiAgLyogZ2xvYmFsIGNvbnNvbGUgKi8KCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvaW5zdHJ1bWVudGF0aW9uCiAgQHByaXZhdGUKICAqLwoKICAvKioKICAgIFRoZSBwdXJwb3NlIG9mIHRoZSBFbWJlciBJbnN0cnVtZW50YXRpb24gbW9kdWxlIGlzCiAgICB0byBwcm92aWRlIGVmZmljaWVudCwgZ2VuZXJhbC1wdXJwb3NlIGluc3RydW1lbnRhdGlvbgogICAgZm9yIEVtYmVyLgogIAogICAgU3Vic2NyaWJlIHRvIGEgbGlzdGVuZXIgYnkgdXNpbmcgYHN1YnNjcmliZWA6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzdWJzY3JpYmUgfSBmcm9tICdAZW1iZXIvaW5zdHJ1bWVudGF0aW9uJzsKICAKICAgIHN1YnNjcmliZSgicmVuZGVyIiwgewogICAgICBiZWZvcmUobmFtZSwgdGltZXN0YW1wLCBwYXlsb2FkKSB7CiAgCiAgICAgIH0sCiAgCiAgICAgIGFmdGVyKG5hbWUsIHRpbWVzdGFtcCwgcGF5bG9hZCkgewogIAogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgeW91IHJldHVybiBhIHZhbHVlIGZyb20gdGhlIGBiZWZvcmVgIGNhbGxiYWNrLCB0aGF0IHNhbWUKICAgIHZhbHVlIHdpbGwgYmUgcGFzc2VkIGFzIGEgZm91cnRoIHBhcmFtZXRlciB0byB0aGUgYGFmdGVyYAogICAgY2FsbGJhY2suCiAgCiAgICBJbnN0cnVtZW50IGEgYmxvY2sgb2YgY29kZSBieSB1c2luZyBgaW5zdHJ1bWVudGA6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBpbnN0cnVtZW50IH0gZnJvbSAnQGVtYmVyL2luc3RydW1lbnRhdGlvbic7CiAgCiAgICBpbnN0cnVtZW50KCJyZW5kZXIuaGFuZGxlYmFycyIsIHBheWxvYWQsIGZ1bmN0aW9uKCkgewogICAgICAvLyByZW5kZXJpbmcgbG9naWMKICAgIH0sIGJpbmRpbmcpOwogICAgYGBgCiAgCiAgICBFdmVudCBuYW1lcyBwYXNzZWQgdG8gYGluc3RydW1lbnRgIGFyZSBuYW1lc3BhY2VkCiAgICBieSBwZXJpb2RzLCBmcm9tIG1vcmUgZ2VuZXJhbCB0byBtb3JlIHNwZWNpZmljLiBTdWJzY3JpYmVycwogICAgY2FuIGxpc3RlbiBmb3IgZXZlbnRzIGJ5IHdoYXRldmVyIGxldmVsIG9mIGdyYW51bGFyaXR5IHRoZXkKICAgIGFyZSBpbnRlcmVzdGVkIGluLgogIAogICAgSW4gdGhlIGFib3ZlIGV4YW1wbGUsIHRoZSBldmVudCBpcyBgcmVuZGVyLmhhbmRsZWJhcnNgLAogICAgYW5kIHRoZSBzdWJzY3JpYmVyIGxpc3RlbmVkIGZvciBhbGwgZXZlbnRzIGJlZ2lubmluZyB3aXRoCiAgICBgcmVuZGVyYC4gSXQgd291bGQgcmVjZWl2ZSBjYWxsYmFja3MgZm9yIGV2ZW50cyBuYW1lZAogICAgYHJlbmRlcmAsIGByZW5kZXIuaGFuZGxlYmFyc2AsIGByZW5kZXIuY29udGFpbmVyYCwgb3IKICAgIGV2ZW4gYHJlbmRlci5oYW5kbGViYXJzLmxheW91dGAuCiAgCiAgICBAY2xhc3MgSW5zdHJ1bWVudGF0aW9uCiAgICBAc3RhdGljCiAgICBAcHJpdmF0ZQogICovCiAgdmFyIHN1YnNjcmliZXJzID0gW107CiAgX2V4cG9ydHMuc3Vic2NyaWJlcnMgPSBzdWJzY3JpYmVyczsKICB2YXIgY2FjaGUgPSB7fTsKCiAgZnVuY3Rpb24gcG9wdWxhdGVMaXN0ZW5lcnMobmFtZSkgewogICAgdmFyIGxpc3RlbmVycyA9IFtdOwogICAgdmFyIHN1YnNjcmliZXI7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdWJzY3JpYmVycy5sZW5ndGg7IGkrKykgewogICAgICBzdWJzY3JpYmVyID0gc3Vic2NyaWJlcnNbaV07CgogICAgICBpZiAoc3Vic2NyaWJlci5yZWdleC50ZXN0KG5hbWUpKSB7CiAgICAgICAgbGlzdGVuZXJzLnB1c2goc3Vic2NyaWJlci5vYmplY3QpOwogICAgICB9CiAgICB9CgogICAgY2FjaGVbbmFtZV0gPSBsaXN0ZW5lcnM7CiAgICByZXR1cm4gbGlzdGVuZXJzOwogIH0KCiAgdmFyIHRpbWUgPSBmdW5jdGlvbiAoKSB7CiAgICB2YXIgcGVyZiA9ICd1bmRlZmluZWQnICE9PSB0eXBlb2Ygd2luZG93ID8gd2luZG93LnBlcmZvcm1hbmNlIHx8IHt9IDoge307CiAgICB2YXIgZm4gPSBwZXJmLm5vdyB8fCBwZXJmLm1vek5vdyB8fCBwZXJmLndlYmtpdE5vdyB8fCBwZXJmLm1zTm93IHx8IHBlcmYub05vdzsKICAgIHJldHVybiBmbiA/IGZuLmJpbmQocGVyZikgOiBEYXRlLm5vdzsKICB9KCk7CgogIGZ1bmN0aW9uIGlzQ2FsbGJhY2sodmFsdWUpIHsKICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbic7CiAgfQoKICBmdW5jdGlvbiBpbnN0cnVtZW50KG5hbWUsIHAxLCBwMiwgcDMpIHsKICAgIHZhciBfcGF5bG9hZDsKCiAgICB2YXIgY2FsbGJhY2s7CiAgICB2YXIgYmluZGluZzsKCiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8PSAzICYmIGlzQ2FsbGJhY2socDEpKSB7CiAgICAgIGNhbGxiYWNrID0gcDE7CiAgICAgIGJpbmRpbmcgPSBwMjsKICAgIH0gZWxzZSB7CiAgICAgIF9wYXlsb2FkID0gcDE7CiAgICAgIGNhbGxiYWNrID0gcDI7CiAgICAgIGJpbmRpbmcgPSBwMzsKICAgIH0gLy8gZmFzdCBwYXRoCgoKICAgIGlmIChzdWJzY3JpYmVycy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIGNhbGxiYWNrLmNhbGwoYmluZGluZyk7CiAgICB9IC8vIGF2b2lkIGFsbG9jYXRpbmcgdGhlIHBheWxvYWQgaW4gZmFzdCBwYXRoCgoKICAgIHZhciBwYXlsb2FkID0gX3BheWxvYWQgfHwge307CgogICAgdmFyIGZpbmFsaXplciA9IF9pbnN0cnVtZW50U3RhcnQobmFtZSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gcGF5bG9hZDsKICAgIH0pOwoKICAgIGlmIChmaW5hbGl6ZXIgPT09IE5PT1ApIHsKICAgICAgcmV0dXJuIGNhbGxiYWNrLmNhbGwoYmluZGluZyk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gd2l0aEZpbmFsaXplcihjYWxsYmFjaywgZmluYWxpemVyLCBwYXlsb2FkLCBiaW5kaW5nKTsKICAgIH0KICB9CgogIHZhciBmbGFnZ2VkSW5zdHJ1bWVudDsKICBfZXhwb3J0cy5mbGFnZ2VkSW5zdHJ1bWVudCA9IGZsYWdnZWRJbnN0cnVtZW50OwoKICBpZiAoZmFsc2UKICAvKiBFTUJFUl9JTVBST1ZFRF9JTlNUUlVNRU5UQVRJT04gKi8KICApIHsKICAgICAgX2V4cG9ydHMuZmxhZ2dlZEluc3RydW1lbnQgPSBmbGFnZ2VkSW5zdHJ1bWVudCA9IGluc3RydW1lbnQ7CiAgICB9IGVsc2UgewogICAgX2V4cG9ydHMuZmxhZ2dlZEluc3RydW1lbnQgPSBmbGFnZ2VkSW5zdHJ1bWVudCA9IGZ1bmN0aW9uIGluc3RydW1lbnQoX25hbWUsIF9wYXlsb2FkLCBjYWxsYmFjaykgewogICAgICByZXR1cm4gY2FsbGJhY2soKTsKICAgIH07CiAgfQoKICBmdW5jdGlvbiB3aXRoRmluYWxpemVyKGNhbGxiYWNrLCBmaW5hbGl6ZXIsIHBheWxvYWQsIGJpbmRpbmcpIHsKICAgIHRyeSB7CiAgICAgIHJldHVybiBjYWxsYmFjay5jYWxsKGJpbmRpbmcpOwogICAgfSBjYXRjaCAoZSkgewogICAgICBwYXlsb2FkLmV4Y2VwdGlvbiA9IGU7CiAgICAgIHRocm93IGU7CiAgICB9IGZpbmFsbHkgewogICAgICBmaW5hbGl6ZXIoKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIE5PT1AoKSB7fQoKICBmdW5jdGlvbiBfaW5zdHJ1bWVudFN0YXJ0KG5hbWUsIHBheWxvYWRGdW5jLCBwYXlsb2FkQXJnKSB7CiAgICBpZiAoc3Vic2NyaWJlcnMubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBOT09QOwogICAgfQoKICAgIHZhciBsaXN0ZW5lcnMgPSBjYWNoZVtuYW1lXTsKCiAgICBpZiAoIWxpc3RlbmVycykgewogICAgICBsaXN0ZW5lcnMgPSBwb3B1bGF0ZUxpc3RlbmVycyhuYW1lKTsKICAgIH0KCiAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gTk9PUDsKICAgIH0KCiAgICB2YXIgcGF5bG9hZCA9IHBheWxvYWRGdW5jKHBheWxvYWRBcmcpOwogICAgdmFyIFNUUlVDVFVSRURfUFJPRklMRSA9IF9lbnZpcm9ubWVudC5FTlYuU1RSVUNUVVJFRF9QUk9GSUxFOwogICAgdmFyIHRpbWVOYW1lOwoKICAgIGlmIChTVFJVQ1RVUkVEX1BST0ZJTEUpIHsKICAgICAgdGltZU5hbWUgPSBuYW1lICsgIjogIiArIHBheWxvYWQub2JqZWN0OwogICAgICBjb25zb2xlLnRpbWUodGltZU5hbWUpOwogICAgfQoKICAgIHZhciBiZWZvcmVWYWx1ZXMgPSBbXTsKICAgIHZhciB0aW1lc3RhbXAgPSB0aW1lKCk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldOwogICAgICBiZWZvcmVWYWx1ZXMucHVzaChsaXN0ZW5lci5iZWZvcmUobmFtZSwgdGltZXN0YW1wLCBwYXlsb2FkKSk7CiAgICB9CgogICAgcmV0dXJuIGZ1bmN0aW9uIF9pbnN0cnVtZW50RW5kKCkgewogICAgICB2YXIgdGltZXN0YW1wID0gdGltZSgpOwoKICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGxpc3RlbmVycy5sZW5ndGg7IF9pKyspIHsKICAgICAgICB2YXIgX2xpc3RlbmVyID0gbGlzdGVuZXJzW19pXTsKCiAgICAgICAgaWYgKHR5cGVvZiBfbGlzdGVuZXIuYWZ0ZXIgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIF9saXN0ZW5lci5hZnRlcihuYW1lLCB0aW1lc3RhbXAsIHBheWxvYWQsIGJlZm9yZVZhbHVlc1tfaV0pOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKFNUUlVDVFVSRURfUFJPRklMRSkgewogICAgICAgIGNvbnNvbGUudGltZUVuZCh0aW1lTmFtZSk7CiAgICAgIH0KICAgIH07CiAgfQogIC8qKgogICAgU3Vic2NyaWJlcyB0byBhIHBhcnRpY3VsYXIgZXZlbnQgb3IgaW5zdHJ1bWVudGVkIGJsb2NrIG9mIGNvZGUuCiAgCiAgICBAbWV0aG9kIHN1YnNjcmliZQogICAgQGZvciBAZW1iZXIvaW5zdHJ1bWVudGF0aW9uCiAgICBAc3RhdGljCiAgCiAgICBAcGFyYW0ge1N0cmluZ30gW3BhdHRlcm5dIE5hbWVzcGFjZWQgZXZlbnQgbmFtZS4KICAgIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBCZWZvcmUgYW5kIEFmdGVyIGhvb2tzLgogIAogICAgQHJldHVybiB7U3Vic2NyaWJlcn0KICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIHN1YnNjcmliZShwYXR0ZXJuLCBvYmplY3QpIHsKICAgIHZhciBwYXRocyA9IHBhdHRlcm4uc3BsaXQoJy4nKTsKICAgIHZhciBwYXRoOwogICAgdmFyIHJlZ2V4ZXMgPSBbXTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGhzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHBhdGggPSBwYXRoc1tpXTsKCiAgICAgIGlmIChwYXRoID09PSAnKicpIHsKICAgICAgICByZWdleGVzLnB1c2goJ1teXFwuXSonKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZWdleGVzLnB1c2gocGF0aCk7CiAgICAgIH0KICAgIH0KCiAgICB2YXIgcmVnZXggPSByZWdleGVzLmpvaW4oJ1xcLicpOwogICAgcmVnZXggPSByZWdleCArICIoXFwuLiopPyI7CiAgICB2YXIgc3Vic2NyaWJlciA9IHsKICAgICAgcGF0dGVybjogcGF0dGVybiwKICAgICAgcmVnZXg6IG5ldyBSZWdFeHAoIl4iICsgcmVnZXggKyAiJCIpLAogICAgICBvYmplY3Q6IG9iamVjdAogICAgfTsKICAgIHN1YnNjcmliZXJzLnB1c2goc3Vic2NyaWJlcik7CiAgICBjYWNoZSA9IHt9OwogICAgcmV0dXJuIHN1YnNjcmliZXI7CiAgfQogIC8qKgogICAgVW5zdWJzY3JpYmVzIGZyb20gYSBwYXJ0aWN1bGFyIGV2ZW50IG9yIGluc3RydW1lbnRlZCBibG9jayBvZiBjb2RlLgogIAogICAgQG1ldGhvZCB1bnN1YnNjcmliZQogICAgQGZvciBAZW1iZXIvaW5zdHJ1bWVudGF0aW9uCiAgICBAc3RhdGljCiAgCiAgICBAcGFyYW0ge09iamVjdH0gW3N1YnNjcmliZXJdCiAgICBAcHJpdmF0ZQogICovCgoKICBmdW5jdGlvbiB1bnN1YnNjcmliZShzdWJzY3JpYmVyKSB7CiAgICB2YXIgaW5kZXggPSAwOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3Vic2NyaWJlcnMubGVuZ3RoOyBpKyspIHsKICAgICAgaWYgKHN1YnNjcmliZXJzW2ldID09PSBzdWJzY3JpYmVyKSB7CiAgICAgICAgaW5kZXggPSBpOwogICAgICB9CiAgICB9CgogICAgc3Vic2NyaWJlcnMuc3BsaWNlKGluZGV4LCAxKTsKICAgIGNhY2hlID0ge307CiAgfQogIC8qKgogICAgUmVzZXRzIGBJbnN0cnVtZW50YXRpb25gIGJ5IGZsdXNoaW5nIGxpc3Qgb2Ygc3Vic2NyaWJlcnMuCiAgCiAgICBAbWV0aG9kIHJlc2V0CiAgICBAZm9yIEBlbWJlci9pbnN0cnVtZW50YXRpb24KICAgIEBzdGF0aWMKICAgIEBwcml2YXRlCiAgKi8KCgogIGZ1bmN0aW9uIHJlc2V0KCkgewogICAgc3Vic2NyaWJlcnMubGVuZ3RoID0gMDsKICAgIGNhY2hlID0ge307CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvbW9kaWZpZXIvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvZ2xpbW1lciJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9nbGltbWVyKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJzZXRNb2RpZmllck1hbmFnZXIiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZ2xpbW1lci5zZXRNb2RpZmllck1hbmFnZXI7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiY2FwYWJpbHRpZXMiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZ2xpbW1lci5tb2RpZmllckNhcGFiaWxpdGllczsKICAgIH0KICB9KTsKfSk7CmRlZmluZSgiQGVtYmVyL29iamVjdC9jb21wYXQiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyL2RlYnVnIiwgIkBnbGltbWVyL3JlZmVyZW5jZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX2RlYnVnLCBfcmVmZXJlbmNlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZXBlbmRlbnRLZXlDb21wYXQgPSBkZXBlbmRlbnRLZXlDb21wYXQ7CgogIHZhciB3cmFwR2V0dGVyU2V0dGVyID0gZnVuY3Rpb24gd3JhcEdldHRlclNldHRlcihfdGFyZ2V0LCBrZXksIGRlc2MpIHsKICAgIHZhciBvcmlnaW5hbEdldCA9IGRlc2MuZ2V0OwoKICAgIGlmIChvcmlnaW5hbEdldCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGRlc2MuZ2V0ID0gZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICAgIHZhciBwcm9wZXJ0eVRhZyA9ICgwLCBfbWV0YWwudGFnRm9yUHJvcGVydHkpKHRoaXMsIGtleSk7CiAgICAgICAgdmFyIHJldDsKICAgICAgICB2YXIgdGFnID0gKDAsIF9tZXRhbC50cmFjaykoZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0ID0gb3JpZ2luYWxHZXQuY2FsbChfdGhpcyk7CiAgICAgICAgfSk7CiAgICAgICAgKDAsIF9yZWZlcmVuY2UudXBkYXRlKShwcm9wZXJ0eVRhZywgdGFnKTsKICAgICAgICAoMCwgX21ldGFsLmNvbnN1bWUpKHRhZyk7CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfTsKICAgIH0KCiAgICByZXR1cm4gZGVzYzsKICB9OwoKICBmdW5jdGlvbiBkZXBlbmRlbnRLZXlDb21wYXQodGFyZ2V0LCBrZXksIGRlc2MpIHsKICAgIChmYWxzZSAmJiAhKEJvb2xlYW4odHJ1ZQogICAgLyogRU1CRVJfTUVUQUxfVFJBQ0tFRF9QUk9QRVJUSUVTICovCiAgICApKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBkZXBlbmRlbnRLZXlDb21wYXQgZGVjb3JhdG9yIGNhbiBvbmx5IGJlIHVzZWQgaWYgdGhlIHRyYWNrZWQgcHJvcGVydGllcyBmZWF0dXJlIGlzIGVuYWJsZWQnLCBCb29sZWFuKHRydWUpKSk7CgogICAgaWYgKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKFt0YXJnZXQsIGtleSwgZGVzY10pKSB7CiAgICAgIGRlc2MgPSB0YXJnZXQ7CgogICAgICB2YXIgZGVjb3JhdG9yID0gZnVuY3Rpb24gZGVjb3JhdG9yKHRhcmdldCwga2V5LCBfZGVzYywgX21ldGEsIGlzQ2xhc3NpY0RlY29yYXRvcikgewogICAgICAgIChmYWxzZSAmJiAhKGlzQ2xhc3NpY0RlY29yYXRvcikgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgQGRlcGVuZGVudEtleUNvbXBhdCBkZWNvcmF0b3IgbWF5IG9ubHkgYmUgcGFzc2VkIGEgbWV0aG9kIHdoZW4gdXNlZCBpbiBjbGFzc2ljIGNsYXNzZXMuIFlvdSBzaG91bGQgZGVjb3JhdGUgZ2V0dGVycy9zZXR0ZXJzIGRpcmVjdGx5IGluIG5hdGl2ZSBjbGFzc2VzJywgaXNDbGFzc2ljRGVjb3JhdG9yKSk7CiAgICAgICAgKGZhbHNlICYmICEoZGVzYyAhPT0gbnVsbCAmJiB0eXBlb2YgZGVzYyA9PT0gJ29iamVjdCcgJiYgKHR5cGVvZiBkZXNjLmdldCA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgZGVzYy5zZXQgPT09ICdmdW5jdGlvbicpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBkZXBlbmRlbnRLZXlDb21wYXQoKSBkZWNvcmF0b3IgbXVzdCBiZSBwYXNzZWQgYSBnZXR0ZXIgb3Igc2V0dGVyIHdoZW4gdXNlZCBpbiBjbGFzc2ljIGNsYXNzZXMnLCBkZXNjICE9PSBudWxsICYmIHR5cGVvZiBkZXNjID09PSAnb2JqZWN0JyAmJiAodHlwZW9mIGRlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBkZXNjLnNldCA9PT0gJ2Z1bmN0aW9uJykpKTsKICAgICAgICByZXR1cm4gd3JhcEdldHRlclNldHRlcih0YXJnZXQsIGtleSwgZGVzYyk7CiAgICAgIH07CgogICAgICAoMCwgX21ldGFsLnNldENsYXNzaWNEZWNvcmF0b3IpKGRlY29yYXRvcik7CiAgICAgIHJldHVybiBkZWNvcmF0b3I7CiAgICB9CgogICAgKGZhbHNlICYmICEoZGVzYyAhPT0gbnVsbCAmJiB0eXBlb2YgZGVzYy5nZXQgPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIGRlc2Muc2V0ID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBAZGVwZW5kZW50S2V5Q29tcGF0IGRlY29yYXRvciBtdXN0IGJlIGFwcGxpZWQgdG8gZ2V0dGVycy9zZXR0ZXJzIHdoZW4gdXNlZCBpbiBuYXRpdmUgY2xhc3NlcycsIGRlc2MgIT09IG51bGwgJiYgdHlwZW9mIGRlc2MuZ2V0ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBkZXNjLnNldCA9PT0gJ2Z1bmN0aW9uJykpOwogICAgcmV0dXJuIHdyYXBHZXR0ZXJTZXR0ZXIodGFyZ2V0LCBrZXksIGRlc2MpOwogIH0KCiAgKDAsIF9tZXRhbC5zZXRDbGFzc2ljRGVjb3JhdG9yKShkZXBlbmRlbnRLZXlDb21wYXQpOwp9KTsKZGVmaW5lKCJAZW1iZXIvb2JqZWN0L2NvbXB1dGVkIiwgWyJleHBvcnRzIiwgIkBlbWJlci9vYmplY3QvbGliL2NvbXB1dGVkL2NvbXB1dGVkX21hY3JvcyIsICJAZW1iZXIvb2JqZWN0L2xpYi9jb21wdXRlZC9yZWR1Y2VfY29tcHV0ZWRfbWFjcm9zIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2NvbXB1dGVkX21hY3JvcywgX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImVtcHR5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXB1dGVkX21hY3Jvcy5lbXB0eTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJub3RFbXB0eSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3Mubm90RW1wdHk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAibm9uZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3Mubm9uZTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJub3QiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcHV0ZWRfbWFjcm9zLm5vdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJib29sIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXB1dGVkX21hY3Jvcy5ib29sOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIm1hdGNoIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXB1dGVkX21hY3Jvcy5tYXRjaDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJlcXVhbCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3MuZXF1YWw7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ3QiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcHV0ZWRfbWFjcm9zLmd0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImd0ZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3MuZ3RlOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImx0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2NvbXB1dGVkX21hY3Jvcy5sdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJsdGUiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcHV0ZWRfbWFjcm9zLmx0ZTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJvbmVXYXkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcHV0ZWRfbWFjcm9zLm9uZVdheTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJyZWFkT25seSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3MucmVhZE9ubHk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZGVwcmVjYXRpbmdBbGlhcyIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3MuZGVwcmVjYXRpbmdBbGlhczsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJhbmQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfY29tcHV0ZWRfbWFjcm9zLmFuZDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJvciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9jb21wdXRlZF9tYWNyb3Mub3I7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic3VtIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3Muc3VtOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIm1pbiIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9yZWR1Y2VfY29tcHV0ZWRfbWFjcm9zLm1pbjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJtYXgiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcmVkdWNlX2NvbXB1dGVkX21hY3Jvcy5tYXg7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAibWFwIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MubWFwOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInNvcnQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcmVkdWNlX2NvbXB1dGVkX21hY3Jvcy5zb3J0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInNldERpZmYiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcmVkdWNlX2NvbXB1dGVkX21hY3Jvcy5zZXREaWZmOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIm1hcEJ5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MubWFwQnk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZmlsdGVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MuZmlsdGVyOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImZpbHRlckJ5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MuZmlsdGVyQnk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAidW5pcSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9yZWR1Y2VfY29tcHV0ZWRfbWFjcm9zLnVuaXE7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAidW5pcUJ5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MudW5pcUJ5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInVuaW9uIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MudW5pb247CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiaW50ZXJzZWN0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3JlZHVjZV9jb21wdXRlZF9tYWNyb3MuaW50ZXJzZWN0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImNvbGxlY3QiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcmVkdWNlX2NvbXB1dGVkX21hY3Jvcy5jb2xsZWN0OwogICAgfQogIH0pOwp9KTsKZGVmaW5lKCJAZW1iZXIvb2JqZWN0L2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvcG9seWZpbGxzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlYnVnLCBfcG9seWZpbGxzLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmFjdGlvbiA9IHZvaWQgMDsKCiAgLyoqCiAgICBEZWNvcmF0b3IgdGhhdCB0dXJucyB0aGUgdGFyZ2V0IGZ1bmN0aW9uIGludG8gYW4gQWN0aW9uIHdoaWNoIGNhbiBiZSBhY2Nlc3NlZAogICAgZGlyZWN0bHkgYnkgcmVmZXJlbmNlLgogIAogICAgYGBganMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBhY3Rpb24sIHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgY2xhc3MgVG9vbHRpcCBleHRlbmRzIENvbXBvbmVudCB7CiAgICAgIEBhY3Rpb24KICAgICAgdG9nZ2xlU2hvd2luZygpIHsKICAgICAgICBzZXQodGhpcywgJ2lzU2hvd2luZycsICF0aGlzLmlzU2hvd2luZyk7CiAgICAgIH0KICAgIH0KICAgIGBgYAogICAgYGBgaGJzCiAgICA8IS0tIHRlbXBsYXRlLmhicyAtLT4KICAgIDxidXR0b24ge3thY3Rpb24gdGhpcy50b2dnbGVTaG93aW5nfX0+U2hvdyB0b29sdGlwPC9idXR0b24+CiAgCiAgICB7eyNpZiBpc1Nob3dpbmd9fQogICAgICA8ZGl2IGNsYXNzPSJ0b29sdGlwIj4KICAgICAgICBJJ20gYSB0b29sdGlwIQogICAgICA8L2Rpdj4KICAgIHt7L2lmfX0KICAgIGBgYAogIAogICAgRGVjb3JhdGVkIGFjdGlvbnMgYWxzbyBpbnRlcm9wIHdpdGggdGhlIHN0cmluZyBzdHlsZSB0ZW1wbGF0ZSBhY3Rpb25zOgogIAogICAgYGBgaGJzCiAgICA8IS0tIHRlbXBsYXRlLmhicyAtLT4KICAgIDxidXR0b24ge3thY3Rpb24gInRvZ2dsZVNob3dpbmcifX0+U2hvdyB0b29sdGlwPC9idXR0b24+CiAgCiAgICB7eyNpZiBpc1Nob3dpbmd9fQogICAgICA8ZGl2IGNsYXNzPSJ0b29sdGlwIj4KICAgICAgICBJJ20gYSB0b29sdGlwIQogICAgICA8L2Rpdj4KICAgIHt7L2lmfX0KICAgIGBgYAogIAogICAgSXQgYWxzbyBiaW5kcyB0aGUgZnVuY3Rpb24gZGlyZWN0bHkgdG8gdGhlIGluc3RhbmNlLCBzbyBpdCBjYW4gYmUgdXNlZCBpbiBhbnkKICAgIGNvbnRleHQgYW5kIHdpbGwgY29ycmVjdGx5IHJlZmVyIHRvIHRoZSBjbGFzcyBpdCBjYW1lIGZyb206CiAgCiAgICBgYGBoYnMKICAgIDwhLS0gdGVtcGxhdGUuaGJzIC0tPgogICAgPGJ1dHRvbgogICAgICB7e2RpZC1pbnNlcnQgdGhpcy50b2dnbGVTaG93aW5nfX0KICAgICAge3tvbiAiY2xpY2siIHRoaXMudG9nZ2xlU2hvd2luZ319CiAgICA+CiAgICAgIFNob3cgdG9vbHRpcAogICAgPC9idXR0b24+CiAgCiAgICB7eyNpZiBpc1Nob3dpbmd9fQogICAgICA8ZGl2IGNsYXNzPSJ0b29sdGlwIj4KICAgICAgICBJJ20gYSB0b29sdGlwIQogICAgICA8L2Rpdj4KICAgIHt7L2lmfX0KICAgIGBgYAogIAogICAgVGhpcyBjYW4gYWxzbyBiZSB1c2VkIGluIEphdmFTY3JpcHQgY29kZSBkaXJlY3RseToKICAKICAgIGBgYGpzCiAgICBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAgaW1wb3J0IHsgYWN0aW9uLCBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IGNsYXNzIFRvb2x0aXAgZXh0ZW5kcyBDb21wb25lbnQgewogICAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpOwogIAogICAgICAgIC8vIHRoaXMudG9nZ2xlU2hvd2luZyBpcyBzdGlsbCBib3VuZCBjb3JyZWN0bHkgd2hlbiBhZGRlZCB0bwogICAgICAgIC8vIHRoZSBldmVudCBsaXN0ZW5lcgogICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy50b2dnbGVTaG93aW5nKTsKICAgICAgfQogIAogICAgICBAYWN0aW9uCiAgICAgIHRvZ2dsZVNob3dpbmcoKSB7CiAgICAgICAgc2V0KHRoaXMsICdpc1Nob3dpbmcnLCAhdGhpcy5pc1Nob3dpbmcpOwogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIFRoaXMgaXMgY29uc2lkZXJlZCBiZXN0IHByYWN0aWNlLCBzaW5jZSBpdCBtZWFucyB0aGF0IG1ldGhvZHMgd2lsbCBiZSBib3VuZAogICAgY29ycmVjdGx5IG5vIG1hdHRlciB3aGVyZSB0aGV5IGFyZSB1c2VkLiBCeSBjb250cmFzdCwgdGhlIGB7e2FjdGlvbn19YCBoZWxwZXIKICAgIGFuZCBtb2RpZmllciBjYW4gYWxzbyBiZSB1c2VkIHRvIGJpbmQgY29udGV4dCwgYnV0IGl0IHdpbGwgYmUgcmVxdWlyZWQgZm9yCiAgICBldmVyeSB1c2FnZSBvZiB0aGUgbWV0aG9kOgogIAogICAgYGBgaGJzCiAgICA8IS0tIHRlbXBsYXRlLmhicyAtLT4KICAgIDxidXR0b24KICAgICAge3tkaWQtaW5zZXJ0IChhY3Rpb24gdGhpcy50b2dnbGVTaG93aW5nKX19CiAgICAgIHt7b24gImNsaWNrIiAoYWN0aW9uIHRoaXMudG9nZ2xlU2hvd2luZyl9fQogICAgPgogICAgICBTaG93IHRvb2x0aXAKICAgIDwvYnV0dG9uPgogIAogICAge3sjaWYgaXNTaG93aW5nfX0KICAgICAgPGRpdiBjbGFzcz0idG9vbHRpcCI+CiAgICAgICAgSSdtIGEgdG9vbHRpcCEKICAgICAgPC9kaXY+CiAgICB7ey9pZn19CiAgICBgYGAKICAKICAgIFRoZXkgYWxzbyBkbyBub3QgaGF2ZSBlcXVpdmFsZW50cyBpbiBKYXZhU2NyaXB0IGRpcmVjdGx5LCBzbyB0aGV5IGNhbm5vdCBiZQogICAgdXNlZCBmb3Igb3RoZXIgc2l0dWF0aW9ucyB3aGVyZSBiaW5kaW5nIHdvdWxkIGJlIHVzZWZ1bC4KICAKICAgIEBwdWJsaWMKICAgIEBtZXRob2QgYWN0aW9uCiAgICBAY2F0ZWdvcnkgRU1CRVJfTkFUSVZFX0RFQ09SQVRPUl9TVVBQT1JUCiAgICBAZm9yIEBlbWJlci9vYmplY3QKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7RnVuY3Rpb258dW5kZWZpbmVkfSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gdHVybiBpbnRvIGFuIGFjdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGVuIHVzZWQgaW4gY2xhc3NpYyBjbGFzc2VzCiAgICBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gcHJvcGVydHkgZGVjb3JhdG9yIGluc3RhbmNlCiAgKi8KICB2YXIgYWN0aW9uOwogIF9leHBvcnRzLmFjdGlvbiA9IGFjdGlvbjsKCiAgaWYgKHRydWUKICAvKiBFTUJFUl9OQVRJVkVfREVDT1JBVE9SX1NVUFBPUlQgKi8KICApIHsKICAgICAgdmFyIEJJTkRJTkdTX01BUCA9IG5ldyBXZWFrTWFwKCk7CgogICAgICB2YXIgc2V0dXBBY3Rpb24gPSBmdW5jdGlvbiBzZXR1cEFjdGlvbih0YXJnZXQsIGtleSwgYWN0aW9uRm4pIHsKICAgICAgICBpZiAodGFyZ2V0LmNvbnN0cnVjdG9yICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIHRhcmdldC5jb25zdHJ1Y3Rvci5wcm90byA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgICAgdGFyZ2V0LmNvbnN0cnVjdG9yLnByb3RvKCk7CiAgICAgICAgfQoKICAgICAgICBpZiAoIXRhcmdldC5oYXNPd25Qcm9wZXJ0eSgnYWN0aW9ucycpKSB7CiAgICAgICAgICB2YXIgcGFyZW50QWN0aW9ucyA9IHRhcmdldC5hY3Rpb25zOyAvLyB3ZSBuZWVkIHRvIGFzc2lnbiBiZWNhdXNlIG9mIHRoZSB3YXkgbWl4aW5zIGNvcHkgYWN0aW9ucyBkb3duIHdoZW4gaW5oZXJpdGluZwoKICAgICAgICAgIHRhcmdldC5hY3Rpb25zID0gcGFyZW50QWN0aW9ucyA/ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIHBhcmVudEFjdGlvbnMpIDoge307CiAgICAgICAgfQoKICAgICAgICB0YXJnZXQuYWN0aW9uc1trZXldID0gYWN0aW9uRm47CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgICAgICB2YXIgYmluZGluZ3MgPSBCSU5ESU5HU19NQVAuZ2V0KHRoaXMpOwoKICAgICAgICAgICAgaWYgKGJpbmRpbmdzID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICBiaW5kaW5ncyA9IG5ldyBNYXAoKTsKICAgICAgICAgICAgICBCSU5ESU5HU19NQVAuc2V0KHRoaXMsIGJpbmRpbmdzKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdmFyIGZuID0gYmluZGluZ3MuZ2V0KGFjdGlvbkZuKTsKCiAgICAgICAgICAgIGlmIChmbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgZm4gPSBhY3Rpb25Gbi5iaW5kKHRoaXMpOwogICAgICAgICAgICAgIGJpbmRpbmdzLnNldChhY3Rpb25GbiwgZm4pOwogICAgICAgICAgICB9CgogICAgICAgICAgICByZXR1cm4gZm47CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgfTsKCiAgICAgIF9leHBvcnRzLmFjdGlvbiA9IGFjdGlvbiA9IGZ1bmN0aW9uIGFjdGlvbih0YXJnZXQsIGtleSwgZGVzYykgewogICAgICAgIHZhciBhY3Rpb25GbjsKCiAgICAgICAgaWYgKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKFt0YXJnZXQsIGtleSwgZGVzY10pKSB7CiAgICAgICAgICBhY3Rpb25GbiA9IHRhcmdldDsKCiAgICAgICAgICB2YXIgZGVjb3JhdG9yID0gZnVuY3Rpb24gZGVjb3JhdG9yKHRhcmdldCwga2V5LCBkZXNjLCBtZXRhLCBpc0NsYXNzaWNEZWNvcmF0b3IpIHsKICAgICAgICAgICAgKGZhbHNlICYmICEoaXNDbGFzc2ljRGVjb3JhdG9yKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBAYWN0aW9uIGRlY29yYXRvciBtYXkgb25seSBiZSBwYXNzZWQgYSBtZXRob2Qgd2hlbiB1c2VkIGluIGNsYXNzaWMgY2xhc3Nlcy4gWW91IHNob3VsZCBkZWNvcmF0ZSBtZXRob2RzIGRpcmVjdGx5IGluIG5hdGl2ZSBjbGFzc2VzJywgaXNDbGFzc2ljRGVjb3JhdG9yKSk7CiAgICAgICAgICAgIChmYWxzZSAmJiAhKHR5cGVvZiBhY3Rpb25GbiA9PT0gJ2Z1bmN0aW9uJykgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgYWN0aW9uKCkgZGVjb3JhdG9yIG11c3QgYmUgcGFzc2VkIGEgbWV0aG9kIHdoZW4gdXNlZCBpbiBjbGFzc2ljIGNsYXNzZXMnLCB0eXBlb2YgYWN0aW9uRm4gPT09ICdmdW5jdGlvbicpKTsKICAgICAgICAgICAgcmV0dXJuIHNldHVwQWN0aW9uKHRhcmdldCwga2V5LCBhY3Rpb25Gbik7CiAgICAgICAgICB9OwoKICAgICAgICAgICgwLCBfbWV0YWwuc2V0Q2xhc3NpY0RlY29yYXRvcikoZGVjb3JhdG9yKTsKICAgICAgICAgIHJldHVybiBkZWNvcmF0b3I7CiAgICAgICAgfQoKICAgICAgICBhY3Rpb25GbiA9IGRlc2MudmFsdWU7CiAgICAgICAgKGZhbHNlICYmICEodHlwZW9mIGFjdGlvbkZuID09PSAnZnVuY3Rpb24nKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1RoZSBAYWN0aW9uIGRlY29yYXRvciBtdXN0IGJlIGFwcGxpZWQgdG8gbWV0aG9kcyB3aGVuIHVzZWQgaW4gbmF0aXZlIGNsYXNzZXMnLCB0eXBlb2YgYWN0aW9uRm4gPT09ICdmdW5jdGlvbicpKTsKICAgICAgICByZXR1cm4gc2V0dXBBY3Rpb24odGFyZ2V0LCBrZXksIGFjdGlvbkZuKTsKICAgICAgfTsKCiAgICAgICgwLCBfbWV0YWwuc2V0Q2xhc3NpY0RlY29yYXRvcikoYWN0aW9uKTsKICAgIH0KfSk7CmRlZmluZSgiQGVtYmVyL29iamVjdC9saWIvY29tcHV0ZWQvY29tcHV0ZWRfbWFjcm9zIiwgWyJleHBvcnRzIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci9kZWJ1ZyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tZXRhbCwgX2RlYnVnKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5lbXB0eSA9IGVtcHR5OwogIF9leHBvcnRzLm5vdEVtcHR5ID0gbm90RW1wdHk7CiAgX2V4cG9ydHMubm9uZSA9IG5vbmU7CiAgX2V4cG9ydHMubm90ID0gbm90OwogIF9leHBvcnRzLmJvb2wgPSBib29sOwogIF9leHBvcnRzLm1hdGNoID0gbWF0Y2g7CiAgX2V4cG9ydHMuZXF1YWwgPSBlcXVhbDsKICBfZXhwb3J0cy5ndCA9IGd0OwogIF9leHBvcnRzLmd0ZSA9IGd0ZTsKICBfZXhwb3J0cy5sdCA9IGx0OwogIF9leHBvcnRzLmx0ZSA9IGx0ZTsKICBfZXhwb3J0cy5vbmVXYXkgPSBvbmVXYXk7CiAgX2V4cG9ydHMucmVhZE9ubHkgPSByZWFkT25seTsKICBfZXhwb3J0cy5kZXByZWNhdGluZ0FsaWFzID0gZGVwcmVjYXRpbmdBbGlhczsKICBfZXhwb3J0cy5vciA9IF9leHBvcnRzLmFuZCA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KICBmdW5jdGlvbiBleHBhbmRQcm9wZXJ0aWVzVG9BcnJheShwcmVkaWNhdGVOYW1lLCBwcm9wZXJ0aWVzKSB7CiAgICB2YXIgZXhwYW5kZWRQcm9wZXJ0aWVzID0gW107CgogICAgZnVuY3Rpb24gZXh0cmFjdFByb3BlcnR5KGVudHJ5KSB7CiAgICAgIGV4cGFuZGVkUHJvcGVydGllcy5wdXNoKGVudHJ5KTsKICAgIH0KCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BlcnRpZXMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1tpXTsKICAgICAgKGZhbHNlICYmICEocHJvcGVydHkuaW5kZXhPZignICcpIDwgMCkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJEZXBlbmRlbnQga2V5cyBwYXNzZWQgdG8gY29tcHV0ZWQuIiArIHByZWRpY2F0ZU5hbWUgKyAiKCkgY2FuJ3QgaGF2ZSBzcGFjZXMuIiwgcHJvcGVydHkuaW5kZXhPZignICcpIDwgMCkpOwogICAgICAoMCwgX21ldGFsLmV4cGFuZFByb3BlcnRpZXMpKHByb3BlcnR5LCBleHRyYWN0UHJvcGVydHkpOwogICAgfQoKICAgIHJldHVybiBleHBhbmRlZFByb3BlcnRpZXM7CiAgfQoKICBmdW5jdGlvbiBnZW5lcmF0ZUNvbXB1dGVkV2l0aFByZWRpY2F0ZShuYW1lLCBwcmVkaWNhdGUpIHsKICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBwcm9wZXJ0aWVzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIHByb3BlcnRpZXNbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKHByb3BlcnRpZXMpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIllvdSBhdHRlbXB0ZWQgdG8gdXNlIEAiICsgbmFtZSArICIgYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBhdCBsZWFzdCBvbmUgZGVwZW5kZW50IGtleSBwYXJhbWV0ZXIiLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShwcm9wZXJ0aWVzKSkpOwogICAgICB2YXIgZGVwZW5kZW50S2V5cyA9IGV4cGFuZFByb3BlcnRpZXNUb0FycmF5KG5hbWUsIHByb3BlcnRpZXMpOwoKICAgICAgdmFyIGNvbXB1dGVkRnVuYyA9IF9tZXRhbC5jb21wdXRlZC5hcHBseSh2b2lkIDAsIGRlcGVuZGVudEtleXMuY29uY2F0KFtmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIGxhc3RJZHggPSBkZXBlbmRlbnRLZXlzLmxlbmd0aCAtIDE7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGFzdElkeDsgaSsrKSB7CiAgICAgICAgICB2YXIgdmFsdWUgPSAoMCwgX21ldGFsLmdldCkodGhpcywgZGVwZW5kZW50S2V5c1tpXSk7CgogICAgICAgICAgaWYgKCFwcmVkaWNhdGUodmFsdWUpKSB7CiAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkodGhpcywgZGVwZW5kZW50S2V5c1tsYXN0SWR4XSk7CiAgICAgIH1dKSk7CgogICAgICByZXR1cm4gY29tcHV0ZWRGdW5jOwogICAgfTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IG1hY3JvIHRoYXQgcmV0dXJucyB0cnVlIGlmIHRoZSB2YWx1ZSBvZiB0aGUgZGVwZW5kZW50CiAgICBwcm9wZXJ0eSBpcyBudWxsLCBhbiBlbXB0eSBzdHJpbmcsIGVtcHR5IGFycmF5LCBvciBlbXB0eSBmdW5jdGlvbi4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGVtcHR5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBUb0RvTGlzdCB7CiAgICAgIGNvbnN0cnVjdG9yKHRvZG9zKSB7CiAgICAgICAgc2V0KHRoaXMsICd0b2RvcycsIHRvZG9zKTsKICAgICAgfQogIAogICAgICBAZW1wdHkoJ3RvZG9zJykgaXNEb25lOwogICAgfQogIAogICAgbGV0IHRvZG9MaXN0ID0gbmV3IFRvRG9MaXN0KAogICAgICBbJ1VuaXQgVGVzdCcsICdEb2N1bWVudGF0aW9uJywgJ1JlbGVhc2UnXQogICAgKTsKICAKICAgIHRvZG9MaXN0LmlzRG9uZTsgLy8gZmFsc2UKICAgIHNldCh0b2RvTGlzdCwgJ3RvZG9zJywgW10pOwogICAgdG9kb0xpc3QuaXNEb25lOyAvLyB0cnVlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGVtcHR5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgVG9Eb0xpc3QgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBpc0RvbmU6IGVtcHR5KCd0b2RvcycpCiAgICB9KTsKICAKICAgIGxldCB0b2RvTGlzdCA9IFRvRG9MaXN0LmNyZWF0ZSh7CiAgICAgIHRvZG9zOiBbJ1VuaXQgVGVzdCcsICdEb2N1bWVudGF0aW9uJywgJ1JlbGVhc2UnXQogICAgfSk7CiAgCiAgICB0b2RvTGlzdC5pc0RvbmU7IC8vIGZhbHNlCiAgICBzZXQodG9kb0xpc3QsICd0b2RvcycsIFtdKTsKICAgIHRvZG9MaXN0LmlzRG9uZTsgLy8gdHJ1ZQogICAgYGBgCiAgCiAgICBAc2luY2UgMS42LjAKICAgIEBtZXRob2QgZW1wdHkKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggcmV0dXJucyB0cnVlIGlmIHRoZSB2YWx1ZQogICAgb2YgdGhlIGRlcGVuZGVudCBwcm9wZXJ0eSBpcyBudWxsLCBhbiBlbXB0eSBzdHJpbmcsIGVtcHR5IGFycmF5LCBvciBlbXB0eQogICAgZnVuY3Rpb24gYW5kIGZhbHNlIGlmIHRoZSB1bmRlcmx5aW5nIHZhbHVlIGlzIG5vdCBlbXB0eS4KICAKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZW1wdHkoZGVwZW5kZW50S2V5KSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAZW1wdHkgYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBhIGBkZXBlbmRlbnRLZXlgIHBhcmFtZXRlcicsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoZGVwZW5kZW50S2V5ICsgIi5sZW5ndGgiLCBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmlzRW1wdHkpKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpKTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRydWUgaWYgdGhlIHZhbHVlIG9mIHRoZSBkZXBlbmRlbnQgcHJvcGVydHkKICAgIGlzIE5PVCBudWxsLCBhbiBlbXB0eSBzdHJpbmcsIGVtcHR5IGFycmF5LCBvciBlbXB0eSBmdW5jdGlvbi4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG5vdEVtcHR5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgY29uc3RydWN0b3IoYmFja3BhY2spIHsKICAgICAgICBzZXQodGhpcywgJ2JhY2twYWNrJywgYmFja3BhY2spOwogICAgICB9CiAgCiAgICAgIEBub3RFbXB0eSgnYmFja3BhY2snKSBoYXNTdHVmZgogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigKICAgICAgWydGb29kJywgJ1NsZWVwaW5nIEJhZycsICdUZW50J10KICAgICk7CiAgCiAgICBoYW1zdGVyLmhhc1N0dWZmOyAvLyB0cnVlCiAgICBzZXQoaGFtc3RlciwgJ2JhY2twYWNrJywgW10pOwogICAgaGFtc3Rlci5oYXNTdHVmZjsgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbm90RW1wdHkgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgaGFzU3R1ZmY6IG5vdEVtcHR5KCdiYWNrcGFjaycpCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoewogICAgICBiYWNrcGFjazogWydGb29kJywgJ1NsZWVwaW5nIEJhZycsICdUZW50J10KICAgIH0pOwogIAogICAgaGFtc3Rlci5oYXNTdHVmZjsgLy8gdHJ1ZQogICAgc2V0KGhhbXN0ZXIsICdiYWNrcGFjaycsIFtdKTsKICAgIGhhbXN0ZXIuaGFzU3R1ZmY7IC8vIGZhbHNlCiAgICBgYGAKICAKICAgIEBtZXRob2Qgbm90RW1wdHkKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggcmV0dXJucyB0cnVlIGlmIG9yaWdpbmFsCiAgICB2YWx1ZSBmb3IgcHJvcGVydHkgaXMgbm90IGVtcHR5LgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBub3RFbXB0eShkZXBlbmRlbnRLZXkpIHsKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBub3RFbXB0eSBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGEgYGRlcGVuZGVudEtleWAgcGFyYW1ldGVyJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmNvbXB1dGVkKShkZXBlbmRlbnRLZXkgKyAiLmxlbmd0aCIsIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuICEoMCwgX21ldGFsLmlzRW1wdHkpKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpKTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRydWUgaWYgdGhlIHZhbHVlIG9mIHRoZSBkZXBlbmRlbnQgcHJvcGVydHkKICAgIGlzIG51bGwgb3IgdW5kZWZpbmVkLiBUaGlzIGF2b2lkcyBlcnJvcnMgZnJvbSBKU0xpbnQgY29tcGxhaW5pbmcgYWJvdXQgdXNlIG9mCiAgICA9PSwgd2hpY2ggY2FuIGJlIHRlY2huaWNhbGx5IGNvbmZ1c2luZy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbm9uZSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBub25lKCdmb29kJykgaXNIdW5ncnk7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKCk7CiAgCiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyB0cnVlCiAgCiAgICBzZXQoaGFtc3RlciwgJ2Zvb2QnLCAnQmFuYW5hJyk7CiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdmb29kJywgbnVsbCk7CiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyB0cnVlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG5vbmUgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgaXNIdW5ncnk6IG5vbmUoJ2Zvb2QnKQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyB0cnVlCiAgCiAgICBzZXQoaGFtc3RlciwgJ2Zvb2QnLCAnQmFuYW5hJyk7CiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdmb29kJywgbnVsbCk7CiAgICBoYW1zdGVyLmlzSHVuZ3J5OyAvLyB0cnVlCiAgICBgYGAKICAKICAgIEBtZXRob2Qgbm9uZQogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIHRydWUgaWYgb3JpZ2luYWwKICAgIHZhbHVlIGZvciBwcm9wZXJ0eSBpcyBudWxsIG9yIHVuZGVmaW5lZC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbm9uZShkZXBlbmRlbnRLZXkpIHsKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBub25lIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgZGVwZW5kZW50S2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuY29tcHV0ZWQpKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5pc05vbmUpKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpKTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRoZSBpbnZlcnNlIGJvb2xlYW4gdmFsdWUgb2YgdGhlIG9yaWdpbmFsCiAgICB2YWx1ZSBmb3IgdGhlIGRlcGVuZGVudCBwcm9wZXJ0eS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG5vdCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgVXNlciB7CiAgICAgIGxvZ2dlZEluID0gZmFsc2U7CiAgCiAgICAgIEBub3QoJ2xvZ2dlZEluJykgaXNBbm9ueW1vdXM7CiAgICB9CiAgCiAgICBsZXQgdXNlciA9IG5ldyBVc2VyKCk7CiAgCiAgICB1c2VyLmlzQW5vbnltb3VzOyAvLyB0cnVlCiAgICBzZXQodXNlciwgJ2xvZ2dlZEluJywgdHJ1ZSk7CiAgICB1c2VyLmlzQW5vbnltb3VzOyAvLyBmYWxzZQogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QsIHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBub3QgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBVc2VyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgbG9nZ2VkSW46IGZhbHNlLAogIAogICAgICBpc0Fub255bW91czogbm90KCdsb2dnZWRJbicpCiAgICB9KTsKICAKICAgIGxldCB1c2VyID0gVXNlci5jcmVhdGUoKTsKICAKICAgIHVzZXIuaXNBbm9ueW1vdXM7IC8vIHRydWUKICAgIHNldCh1c2VyLCAnbG9nZ2VkSW4nLCB0cnVlKTsKICAgIHVzZXIuaXNBbm9ueW1vdXM7IC8vIGZhbHNlCiAgICBgYGAKICAKICAgIEBtZXRob2Qgbm90CiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBwYXJhbSB7U3RyaW5nfSBkZXBlbmRlbnRLZXkKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgaW52ZXJzZSBvZiB0aGUKICAgIG9yaWdpbmFsIHZhbHVlIGZvciBwcm9wZXJ0eQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBub3QoZGVwZW5kZW50S2V5KSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAbm90IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgZGVwZW5kZW50S2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuY29tcHV0ZWQpKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gISgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpOwogICAgfSk7CiAgfQogIC8qKgogICAgQSBjb21wdXRlZCBwcm9wZXJ0eSB0aGF0IGNvbnZlcnRzIHRoZSBwcm92aWRlZCBkZXBlbmRlbnQgcHJvcGVydHkgaW50byBhCiAgICBib29sZWFuIHZhbHVlLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgYm9vbCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBib29sKCdudW1CYW5hbmFzJykgaGFzQmFuYW5hcwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgaGFtc3Rlci5oYXNCYW5hbmFzOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgMCk7CiAgICBoYW1zdGVyLmhhc0JhbmFuYXM7IC8vIGZhbHNlCiAgCiAgICBzZXQoaGFtc3RlciwgJ251bUJhbmFuYXMnLCAxKTsKICAgIGhhbXN0ZXIuaGFzQmFuYW5hczsgLy8gdHJ1ZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgbnVsbCk7CiAgICBoYW1zdGVyLmhhc0JhbmFuYXM7IC8vIGZhbHNlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGJvb2wgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgaGFzQmFuYW5hczogYm9vbCgnbnVtQmFuYW5hcycpCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoKTsKICAKICAgIGhhbXN0ZXIuaGFzQmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDApOwogICAgaGFtc3Rlci5oYXNCYW5hbmFzOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgMSk7CiAgICBoYW1zdGVyLmhhc0JhbmFuYXM7IC8vIHRydWUKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIG51bGwpOwogICAgaGFtc3Rlci5oYXNCYW5hbmFzOyAvLyBmYWxzZQogICAgYGBgCiAgCiAgICBAbWV0aG9kIGJvb2wKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggY29udmVydHMgdG8gYm9vbGVhbiB0aGUKICAgIG9yaWdpbmFsIHZhbHVlIGZvciBwcm9wZXJ0eQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBib29sKGRlcGVuZGVudEtleSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGJvb2wgYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBhIGBkZXBlbmRlbnRLZXlgIHBhcmFtZXRlcicsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoZGVwZW5kZW50S2V5LCBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBCb29sZWFuKCgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpKTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggbWF0Y2hlcyB0aGUgb3JpZ2luYWwgdmFsdWUgZm9yIHRoZSBkZXBlbmRlbnQKICAgIHByb3BlcnR5IGFnYWluc3QgYSBnaXZlbiBSZWdFeHAsIHJldHVybmluZyBgdHJ1ZWAgaWYgdGhlIHZhbHVlIG1hdGNoZXMgdGhlCiAgICBSZWdFeHAgYW5kIGBmYWxzZWAgaWYgaXQgZG9lcyBub3QuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBtYXRjaCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgVXNlciB7CiAgICAgIEBtYXRjaCgnZW1haWwnLCAvXi4rQC4rXC4uKyQvKSBoYXNWYWxpZEVtYWlsOwogICAgfQogIAogICAgbGV0IHVzZXIgPSBuZXcgVXNlcigpOwogIAogICAgdXNlci5oYXNWYWxpZEVtYWlsOyAvLyBmYWxzZQogIAogICAgc2V0KHVzZXIsICdlbWFpbCcsICcnKTsKICAgIHVzZXIuaGFzVmFsaWRFbWFpbDsgLy8gZmFsc2UKICAKICAgIHNldCh1c2VyLCAnZW1haWwnLCAnZW1iZXJfaGFtc3RlckBleGFtcGxlLmNvbScpOwogICAgdXNlci5oYXNWYWxpZEVtYWlsOyAvLyB0cnVlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG1hdGNoIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgVXNlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGhhc1ZhbGlkRW1haWw6IG1hdGNoKCdlbWFpbCcsIC9eLitALitcLi4rJC8pCiAgICB9KTsKICAKICAgIGxldCB1c2VyID0gVXNlci5jcmVhdGUoKTsKICAKICAgIHVzZXIuaGFzVmFsaWRFbWFpbDsgLy8gZmFsc2UKICAKICAgIHNldCh1c2VyLCAnZW1haWwnLCAnJyk7CiAgICB1c2VyLmhhc1ZhbGlkRW1haWw7IC8vIGZhbHNlCiAgCiAgICBzZXQodXNlciwgJ2VtYWlsJywgJ2VtYmVyX2hhbXN0ZXJAZXhhbXBsZS5jb20nKTsKICAgIHVzZXIuaGFzVmFsaWRFbWFpbDsgLy8gdHJ1ZQogICAgYGBgCiAgCiAgICBAbWV0aG9kIG1hdGNoCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBwYXJhbSB7U3RyaW5nfSBkZXBlbmRlbnRLZXkKICAgIEBwYXJhbSB7UmVnRXhwfSByZWdleHAKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIG1hdGNoIHRoZSBvcmlnaW5hbCB2YWx1ZQogICAgZm9yIHByb3BlcnR5IGFnYWluc3QgYSBnaXZlbiBSZWdFeHAKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbWF0Y2goZGVwZW5kZW50S2V5LCByZWdleHApIHsKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBtYXRjaCBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGBkZXBlbmRlbnRLZXlgIGFuZCBgcmVnZXhwYCBwYXJhbWV0ZXJzJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmNvbXB1dGVkKShkZXBlbmRlbnRLZXksIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIHZhbHVlID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIGRlcGVuZGVudEtleSk7CiAgICAgIHJldHVybiByZWdleHAudGVzdCh2YWx1ZSk7CiAgICB9KTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgcmV0dXJucyB0cnVlIGlmIHRoZSBwcm92aWRlZCBkZXBlbmRlbnQgcHJvcGVydHkgaXMKICAgIGVxdWFsIHRvIHRoZSBnaXZlbiB2YWx1ZS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGVxdWFsIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgQGVxdWFsKCdwZXJjZW50Q2Fycm90c0VhdGVuJywgMTAwKSBzYXRpc2ZpZWQ7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKCk7CiAgCiAgICBoYW1zdGVyLnNhdGlzZmllZDsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAncGVyY2VudENhcnJvdHNFYXRlbicsIDEwMCk7CiAgICBoYW1zdGVyLnNhdGlzZmllZDsgLy8gdHJ1ZQogIAogICAgc2V0KGhhbXN0ZXIsICdwZXJjZW50Q2Fycm90c0VhdGVuJywgNTApOwogICAgaGFtc3Rlci5zYXRpc2ZpZWQ7IC8vIGZhbHNlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGVxdWFsIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgSGFtc3RlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIHNhdGlzZmllZDogZXF1YWwoJ3BlcmNlbnRDYXJyb3RzRWF0ZW4nLCAxMDApCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoKTsKICAKICAgIGhhbXN0ZXIuc2F0aXNmaWVkOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdwZXJjZW50Q2Fycm90c0VhdGVuJywgMTAwKTsKICAgIGhhbXN0ZXIuc2F0aXNmaWVkOyAvLyB0cnVlCiAgCiAgICBzZXQoaGFtc3RlciwgJ3BlcmNlbnRDYXJyb3RzRWF0ZW4nLCA1MCk7CiAgICBoYW1zdGVyLnNhdGlzZmllZDsgLy8gZmFsc2UKICAgIGBgYAogIAogICAgQG1ldGhvZCBlcXVhbAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ8T2JqZWN0fSB2YWx1ZQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggcmV0dXJucyB0cnVlIGlmIHRoZQogICAgb3JpZ2luYWwgdmFsdWUgZm9yIHByb3BlcnR5IGlzIGVxdWFsIHRvIHRoZSBnaXZlbiB2YWx1ZS4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZXF1YWwoZGVwZW5kZW50S2V5LCB2YWx1ZSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGVxdWFsIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYGRlcGVuZGVudEtleWAgYW5kIGB2YWx1ZWAgcGFyYW1ldGVyJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmNvbXB1dGVkKShkZXBlbmRlbnRLZXksIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpID09PSB2YWx1ZTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRydWUgaWYgdGhlIHByb3ZpZGVkIGRlcGVuZGVudCBwcm9wZXJ0eSBpcwogICAgZ3JlYXRlciB0aGFuIHRoZSBwcm92aWRlZCB2YWx1ZS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGd0IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgQGd0KCdudW1CYW5hbmFzJywgMTApIGhhc1Rvb01hbnlCYW5hbmFzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDExKTsKICAgIGhhbXN0ZXIuaGFzVG9vTWFueUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgZ3QgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgaGFzVG9vTWFueUJhbmFuYXM6IGd0KCdudW1CYW5hbmFzJywgMTApCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoKTsKICAKICAgIGhhbXN0ZXIuaGFzVG9vTWFueUJhbmFuYXM7IC8vIGZhbHNlCiAgCiAgICBzZXQoaGFtc3RlciwgJ251bUJhbmFuYXMnLCAzKTsKICAgIGhhbXN0ZXIuaGFzVG9vTWFueUJhbmFuYXM7IC8vIGZhbHNlCiAgCiAgICBzZXQoaGFtc3RlciwgJ251bUJhbmFuYXMnLCAxMSk7CiAgICBoYW1zdGVyLmhhc1Rvb01hbnlCYW5hbmFzOyAvLyB0cnVlCiAgICBgYGAKICAKICAgIEBtZXRob2QgZ3QKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHBhcmFtIHtOdW1iZXJ9IHZhbHVlCiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIHRydWUgaWYgdGhlCiAgICBvcmlnaW5hbCB2YWx1ZSBmb3IgcHJvcGVydHkgaXMgZ3JlYXRlciB0aGFuIGdpdmVuIHZhbHVlLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBndChkZXBlbmRlbnRLZXksIHZhbHVlKSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAZ3QgYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBgZGVwZW5kZW50S2V5YCBhbmQgYHZhbHVlYCBwYXJhbWV0ZXJzJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmNvbXB1dGVkKShkZXBlbmRlbnRLZXksIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBkZXBlbmRlbnRLZXkpID4gdmFsdWU7CiAgICB9KTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgcmV0dXJucyB0cnVlIGlmIHRoZSBwcm92aWRlZCBkZXBlbmRlbnQgcHJvcGVydHkgaXMKICAgIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byB0aGUgcHJvdmlkZWQgdmFsdWUuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBndGUgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGNsYXNzIEhhbXN0ZXIgewogICAgICBAZ3RlKCdudW1CYW5hbmFzJywgMTApIGhhc1Rvb01hbnlCYW5hbmFzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDEwKTsKICAgIGhhbXN0ZXIuaGFzVG9vTWFueUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgZ3RlIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgSGFtc3RlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGhhc1Rvb01hbnlCYW5hbmFzOiBndGUoJ251bUJhbmFuYXMnLCAxMCkKICAgIH0pOwogIAogICAgbGV0IGhhbXN0ZXIgPSBIYW1zdGVyLmNyZWF0ZSgpOwogIAogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5oYXNUb29NYW55QmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDEwKTsKICAgIGhhbXN0ZXIuaGFzVG9vTWFueUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQG1ldGhvZCBndGUKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHBhcmFtIHtOdW1iZXJ9IHZhbHVlCiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIHRydWUgaWYgdGhlCiAgICBvcmlnaW5hbCB2YWx1ZSBmb3IgcHJvcGVydHkgaXMgZ3JlYXRlciBvciBlcXVhbCB0aGVuIGdpdmVuIHZhbHVlLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBndGUoZGVwZW5kZW50S2V5LCB2YWx1ZSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGd0ZSBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGBkZXBlbmRlbnRLZXlgIGFuZCBgdmFsdWVgIHBhcmFtZXRlcnMnLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuY29tcHV0ZWQpKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIGRlcGVuZGVudEtleSkgPj0gdmFsdWU7CiAgICB9KTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgcmV0dXJucyB0cnVlIGlmIHRoZSBwcm92aWRlZCBkZXBlbmRlbnQgcHJvcGVydHkgaXMKICAgIGxlc3MgdGhhbiB0aGUgcHJvdmlkZWQgdmFsdWUuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBsdCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBsdCgnbnVtQmFuYW5hcycsIDMpIG5lZWRzTW9yZUJhbmFuYXM7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKCk7CiAgCiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5uZWVkc01vcmVCYW5hbmFzOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgMik7CiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbHQgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgbmVlZHNNb3JlQmFuYW5hczogbHQoJ251bUJhbmFuYXMnLCAzKQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5uZWVkc01vcmVCYW5hbmFzOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgMik7CiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQG1ldGhvZCBsdAogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge051bWJlcn0gdmFsdWUKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgdHJ1ZSBpZiB0aGUKICAgIG9yaWdpbmFsIHZhbHVlIGZvciBwcm9wZXJ0eSBpcyBsZXNzIHRoZW4gZ2l2ZW4gdmFsdWUuCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGx0KGRlcGVuZGVudEtleSwgdmFsdWUpIHsKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBsdCBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGBkZXBlbmRlbnRLZXlgIGFuZCBgdmFsdWVgIHBhcmFtZXRlcnMnLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuY29tcHV0ZWQpKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIGRlcGVuZGVudEtleSkgPCB2YWx1ZTsKICAgIH0pOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRydWUgaWYgdGhlIHByb3ZpZGVkIGRlcGVuZGVudCBwcm9wZXJ0eSBpcwogICAgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHRoZSBwcm92aWRlZCB2YWx1ZS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGx0ZSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBsdGUoJ251bUJhbmFuYXMnLCAzKSBuZWVkc01vcmVCYW5hbmFzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgaGFtc3Rlci5uZWVkc01vcmVCYW5hbmFzOyAvLyB0cnVlCiAgCiAgICBzZXQoaGFtc3RlciwgJ251bUJhbmFuYXMnLCA1KTsKICAgIGhhbXN0ZXIubmVlZHNNb3JlQmFuYW5hczsgLy8gZmFsc2UKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDMpOwogICAgaGFtc3Rlci5uZWVkc01vcmVCYW5hbmFzOyAvLyB0cnVlCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGx0ZSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBuZWVkc01vcmVCYW5hbmFzOiBsdGUoJ251bUJhbmFuYXMnLCAzKQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAKICAgIHNldChoYW1zdGVyLCAnbnVtQmFuYW5hcycsIDUpOwogICAgaGFtc3Rlci5uZWVkc01vcmVCYW5hbmFzOyAvLyBmYWxzZQogIAogICAgc2V0KGhhbXN0ZXIsICdudW1CYW5hbmFzJywgMyk7CiAgICBoYW1zdGVyLm5lZWRzTW9yZUJhbmFuYXM7IC8vIHRydWUKICAgIGBgYAogIAogICAgQG1ldGhvZCBsdGUKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHBhcmFtIHtOdW1iZXJ9IHZhbHVlCiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIHRydWUgaWYgdGhlCiAgICBvcmlnaW5hbCB2YWx1ZSBmb3IgcHJvcGVydHkgaXMgbGVzcyBvciBlcXVhbCB0aGFuIGdpdmVuIHZhbHVlLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBsdGUoZGVwZW5kZW50S2V5LCB2YWx1ZSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGx0ZSBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGBkZXBlbmRlbnRLZXlgIGFuZCBgdmFsdWVgIHBhcmFtZXRlcnMnLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuY29tcHV0ZWQpKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIGRlcGVuZGVudEtleSkgPD0gdmFsdWU7CiAgICB9KTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgcGVyZm9ybXMgYSBsb2dpY2FsIGBhbmRgIG9uIHRoZSBvcmlnaW5hbCB2YWx1ZXMgZm9yCiAgICB0aGUgcHJvdmlkZWQgZGVwZW5kZW50IHByb3BlcnRpZXMuCiAgCiAgICBZb3UgbWF5IHBhc3MgaW4gbW9yZSB0aGFuIHR3byBwcm9wZXJ0aWVzIGFuZCBldmVuIHVzZSBwcm9wZXJ0eSBicmFjZQogICAgZXhwYW5zaW9uLiAgVGhlIGNvbXB1dGVkIHByb3BlcnR5IHdpbGwgcmV0dXJuIHRoZSBmaXJzdCBmYWxzeSB2YWx1ZSBvciBsYXN0CiAgICB0cnV0aHkgdmFsdWUganVzdCBsaWtlIEphdmFTY3JpcHQncyBgJiZgIG9wZXJhdG9yLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgYW5kIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgQGFuZCgnaGFzVGVudCcsICdoYXNCYWNrcGFjaycpIHJlYWR5Rm9yQ2FtcDsKICAgICAgQGFuZCgnaGFzV2Fsa2luZ1N0aWNrJywgJ2hhc0JhY2twYWNrJykgcmVhZHlGb3JIaWtlOwogICAgfQogIAogICAgbGV0IHRvbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgdG9tc3Rlci5yZWFkeUZvckNhbXA7IC8vIGZhbHNlCiAgCiAgICBzZXQodG9tc3RlciwgJ2hhc1RlbnQnLCB0cnVlKTsKICAgIHRvbXN0ZXIucmVhZHlGb3JDYW1wOyAvLyBmYWxzZQogIAogICAgc2V0KHRvbXN0ZXIsICdoYXNCYWNrcGFjaycsIHRydWUpOwogICAgdG9tc3Rlci5yZWFkeUZvckNhbXA7IC8vIHRydWUKICAKICAgIHNldCh0b21zdGVyLCAnaGFzQmFja3BhY2snLCAnWWVzJyk7CiAgICB0b21zdGVyLnJlYWR5Rm9yQ2FtcDsgLy8gJ1llcycKICAKICAgIHNldCh0b21zdGVyLCAnaGFzV2Fsa2luZ1N0aWNrJywgbnVsbCk7CiAgICB0b21zdGVyLnJlYWR5Rm9ySGlrZTsgLy8gbnVsbAogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QsIHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBhbmQgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgcmVhZHlGb3JDYW1wOiBhbmQoJ2hhc1RlbnQnLCAnaGFzQmFja3BhY2snKSwKICAgICAgcmVhZHlGb3JIaWtlOiBhbmQoJ2hhc1dhbGtpbmdTdGljaycsICdoYXNCYWNrcGFjaycpCiAgICB9KTsKICAKICAgIGxldCB0b21zdGVyID0gSGFtc3Rlci5jcmVhdGUoKTsKICAKICAgIHRvbXN0ZXIucmVhZHlGb3JDYW1wOyAvLyBmYWxzZQogIAogICAgc2V0KHRvbXN0ZXIsICdoYXNUZW50JywgdHJ1ZSk7CiAgICB0b21zdGVyLnJlYWR5Rm9yQ2FtcDsgLy8gZmFsc2UKICAKICAgIHNldCh0b21zdGVyLCAnaGFzQmFja3BhY2snLCB0cnVlKTsKICAgIHRvbXN0ZXIucmVhZHlGb3JDYW1wOyAvLyB0cnVlCiAgCiAgICBzZXQodG9tc3RlciwgJ2hhc0JhY2twYWNrJywgJ1llcycpOwogICAgdG9tc3Rlci5yZWFkeUZvckNhbXA7IC8vICdZZXMnCiAgCiAgICBzZXQodG9tc3RlciwgJ2hhc1dhbGtpbmdTdGljaycsIG51bGwpOwogICAgdG9tc3Rlci5yZWFkeUZvckhpa2U7IC8vIG51bGwKICAgIGBgYAogIAogICAgQG1ldGhvZCBhbmQKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleSoKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHBlcmZvcm1zIGEgbG9naWNhbCBgYW5kYCBvbgogICAgdGhlIHZhbHVlcyBvZiBhbGwgdGhlIG9yaWdpbmFsIHZhbHVlcyBmb3IgcHJvcGVydGllcy4KICAgIEBwdWJsaWMKICAqLwoKCiAgdmFyIGFuZCA9IGdlbmVyYXRlQ29tcHV0ZWRXaXRoUHJlZGljYXRlKCdhbmQnLCBmdW5jdGlvbiAodmFsdWUpIHsKICAgIHJldHVybiB2YWx1ZTsKICB9KTsKICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggcGVyZm9ybXMgYSBsb2dpY2FsIGBvcmAgb24gdGhlIG9yaWdpbmFsIHZhbHVlcyBmb3IKICAgIHRoZSBwcm92aWRlZCBkZXBlbmRlbnQgcHJvcGVydGllcy4KICAKICAgIFlvdSBtYXkgcGFzcyBpbiBtb3JlIHRoYW4gdHdvIHByb3BlcnRpZXMgYW5kIGV2ZW4gdXNlIHByb3BlcnR5IGJyYWNlCiAgICBleHBhbnNpb24uICBUaGUgY29tcHV0ZWQgcHJvcGVydHkgd2lsbCByZXR1cm4gdGhlIGZpcnN0IHRydXRoeSB2YWx1ZSBvciBsYXN0CiAgICBmYWxzeSB2YWx1ZSBqdXN0IGxpa2UgSmF2YVNjcmlwdCdzIGB8fGAgb3BlcmF0b3IuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBvciB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBvcignaGFzSmFja2V0JywgJ2hhc1VtYnJlbGxhJykgcmVhZHlGb3JSYWluOwogICAgICBAb3IoJ2hhc1N1bnNjcmVlbicsICdoYXNVbWJyZWxsYScpIHJlYWR5Rm9yQmVhY2g7CiAgICB9CiAgCiAgICBsZXQgdG9tc3RlciA9IG5ldyBIYW1zdGVyKCk7CiAgCiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gdW5kZWZpbmVkCiAgCiAgICBzZXQodG9tc3RlciwgJ2hhc1VtYnJlbGxhJywgdHJ1ZSk7CiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gdHJ1ZQogIAogICAgc2V0KHRvbXN0ZXIsICdoYXNKYWNrZXQnLCAnWWVzJyk7CiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gJ1llcycKICAKICAgIHNldCh0b21zdGVyLCAnaGFzU3Vuc2NyZWVuJywgJ0NoZWNrJyk7CiAgICB0b21zdGVyLnJlYWR5Rm9yQmVhY2g7IC8vICdDaGVjaycKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgb3IgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgcmVhZHlGb3JSYWluOiBvcignaGFzSmFja2V0JywgJ2hhc1VtYnJlbGxhJyksCiAgICAgIHJlYWR5Rm9yQmVhY2g6IG9yKCdoYXNTdW5zY3JlZW4nLCAnaGFzVW1icmVsbGEnKQogICAgfSk7CiAgCiAgICBsZXQgdG9tc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gdW5kZWZpbmVkCiAgCiAgICBzZXQodG9tc3RlciwgJ2hhc1VtYnJlbGxhJywgdHJ1ZSk7CiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gdHJ1ZQogIAogICAgc2V0KHRvbXN0ZXIsICdoYXNKYWNrZXQnLCAnWWVzJyk7CiAgICB0b21zdGVyLnJlYWR5Rm9yUmFpbjsgLy8gJ1llcycKICAKICAgIHNldCh0b21zdGVyLCAnaGFzU3Vuc2NyZWVuJywgJ0NoZWNrJyk7CiAgICB0b21zdGVyLnJlYWR5Rm9yQmVhY2g7IC8vICdDaGVjaycKICAgIGBgYAogIAogICAgQG1ldGhvZCBvcgogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5KgogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggcGVyZm9ybXMgYSBsb2dpY2FsIGBvcmAgb24KICAgIHRoZSB2YWx1ZXMgb2YgYWxsIHRoZSBvcmlnaW5hbCB2YWx1ZXMgZm9yIHByb3BlcnRpZXMuCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMuYW5kID0gYW5kOwogIHZhciBvciA9IGdlbmVyYXRlQ29tcHV0ZWRXaXRoUHJlZGljYXRlKCdvcicsIGZ1bmN0aW9uICh2YWx1ZSkgewogICAgcmV0dXJuICF2YWx1ZTsKICB9KTsKICAvKioKICAgIENyZWF0ZXMgYSBuZXcgcHJvcGVydHkgdGhhdCBpcyBhbiBhbGlhcyBmb3IgYW5vdGhlciBwcm9wZXJ0eSBvbiBhbiBvYmplY3QuCiAgICBDYWxscyB0byBgZ2V0YCBvciBgc2V0YCB0aGlzIHByb3BlcnR5IGJlaGF2ZSBhcyB0aG91Z2ggdGhleSB3ZXJlIGNhbGxlZCBvbiB0aGUKICAgIG9yaWdpbmFsIHByb3BlcnR5LgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgYWxpYXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGNsYXNzIFBlcnNvbiB7CiAgICAgIG5hbWUgPSAnQWxleCBNYXRjaG5lZXInOwogIAogICAgICBAYWxpYXMoJ25hbWUnKSBub21lbjsKICAgIH0KICAKICAgIGxldCBhbGV4ID0gbmV3IFBlcnNvbigpOwogIAogICAgYWxleC5ub21lbjsgLy8gJ0FsZXggTWF0Y2huZWVyJwogICAgYWxleC5uYW1lOyAgLy8gJ0FsZXggTWF0Y2huZWVyJwogIAogICAgc2V0KGFsZXgsICdub21lbicsICdAbWFjaHR5Jyk7CiAgICBhbGV4Lm5hbWU7ICAvLyAnQG1hY2h0eScKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgYWxpYXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBQZXJzb24gPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBuYW1lOiAnQWxleCBNYXRjaG5lZXInLAogIAogICAgICBub21lbjogYWxpYXMoJ25hbWUnKQogICAgfSk7CiAgCiAgICBsZXQgYWxleCA9IFBlcnNvbi5jcmVhdGUoKTsKICAKICAgIGFsZXgubm9tZW47IC8vICdBbGV4IE1hdGNobmVlcicKICAgIGFsZXgubmFtZTsgIC8vICdBbGV4IE1hdGNobmVlcicKICAKICAgIHNldChhbGV4LCAnbm9tZW4nLCAnQG1hY2h0eScpOwogICAgYWxleC5uYW1lOyAgLy8gJ0BtYWNodHknCiAgICBgYGAKICAKICAgIEBtZXRob2QgYWxpYXMKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggY3JlYXRlcyBhbiBhbGlhcyB0byB0aGUKICAgIG9yaWdpbmFsIHZhbHVlIGZvciBwcm9wZXJ0eS4KICAgIEBwdWJsaWMKICAqLwoKICAvKioKICAgIFdoZXJlIGBjb21wdXRlZC5hbGlhc2AgYWxpYXNlcyBgZ2V0YCBhbmQgYHNldGAsIGFuZCBhbGxvd3MgZm9yIGJpZGlyZWN0aW9uYWwKICAgIGRhdGEgZmxvdywgYGNvbXB1dGVkLm9uZVdheWAgb25seSBwcm92aWRlcyBhbiBhbGlhc2VkIGBnZXRgLiBUaGUgYHNldGAgd2lsbAogICAgbm90IG11dGF0ZSB0aGUgdXBzdHJlYW0gcHJvcGVydHksIHJhdGhlciBjYXVzZXMgdGhlIGN1cnJlbnQgcHJvcGVydHkgdG8gYmVjb21lCiAgICB0aGUgdmFsdWUgc2V0LiBUaGlzIGNhdXNlcyB0aGUgZG93bnN0cmVhbSBwcm9wZXJ0eSB0byBwZXJtYW5lbnRseSBkaXZlcmdlIGZyb20KICAgIHRoZSB1cHN0cmVhbSBwcm9wZXJ0eS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG9uZVdheSB9ZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBVc2VyIHsKICAgICAgY29uc3RydWN0b3IoZmlyc3ROYW1lLCBsYXN0TmFtZSkgewogICAgICAgIHNldCh0aGlzLCAnZmlyc3ROYW1lJywgZmlyc3ROYW1lKTsKICAgICAgICBzZXQodGhpcywgJ2xhc3ROYW1lJywgbGFzdE5hbWUpOwogICAgICB9CiAgCiAgICAgIEBvbmVXYXkoJ2ZpcnN0TmFtZScpIG5pY2tOYW1lOwogICAgfQogIAogICAgbGV0IHRlZGR5ID0gbmV3IFVzZXIoJ1RlZGR5JywgJ1plZW5ueScpOwogIAogICAgdGVkZHkubmlja05hbWU7IC8vICdUZWRkeScKICAKICAgIHNldCh0ZWRkeSwgJ25pY2tOYW1lJywgJ1RlZGR5QmVhcicpOwogICAgdGVkZHkuZmlyc3ROYW1lOyAvLyAnVGVkZHknCiAgICB0ZWRkeS5uaWNrTmFtZTsgLy8gJ1RlZGR5QmVhcicKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgb25lV2F5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgVXNlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGZpcnN0TmFtZTogbnVsbCwKICAgICAgbGFzdE5hbWU6IG51bGwsCiAgCiAgICAgIG5pY2tOYW1lOiBvbmVXYXkoJ2ZpcnN0TmFtZScpCiAgICB9KTsKICAKICAgIGxldCB0ZWRkeSA9IFVzZXIuY3JlYXRlKHsKICAgICAgZmlyc3ROYW1lOiAnVGVkZHknLAogICAgICBsYXN0TmFtZTogJ1plZW5ueScKICAgIH0pOwogIAogICAgdGVkZHkubmlja05hbWU7IC8vICdUZWRkeScKICAKICAgIHNldCh0ZWRkeSwgJ25pY2tOYW1lJywgJ1RlZGR5QmVhcicpOyAvLyAnVGVkZHlCZWFyJwogICAgdGVkZHkuZmlyc3ROYW1lOyAvLyAnVGVkZHknCiAgICB0ZWRkeS5uaWNrTmFtZTsgLy8gJ1RlZGR5QmVhcicKICAgIGBgYAogIAogICAgQG1ldGhvZCBvbmVXYXkKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZWQgcHJvcGVydHkgd2hpY2ggY3JlYXRlcyBhIG9uZSB3YXkgY29tcHV0ZWQKICAgIHByb3BlcnR5IHRvIHRoZSBvcmlnaW5hbCB2YWx1ZSBmb3IgcHJvcGVydHkuCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMub3IgPSBvcjsKCiAgZnVuY3Rpb24gb25lV2F5KGRlcGVuZGVudEtleSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQG9uZVdheSBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGEgYGRlcGVuZGVudEtleWAgcGFyYW1ldGVyJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmFsaWFzKShkZXBlbmRlbnRLZXkpLm9uZVdheSgpOwogIH0KICAvKioKICAgIFRoaXMgaXMgYSBtb3JlIHNlbWFudGljYWxseSBtZWFuaW5nZnVsIGFsaWFzIG9mIGBjb21wdXRlZC5vbmVXYXlgLCB3aG9zZSBuYW1lCiAgICBpcyBzb21ld2hhdCBhbWJpZ3VvdXMgYXMgdG8gd2hpY2ggZGlyZWN0aW9uIHRoZSBkYXRhIGZsb3dzLgogIAogICAgQG1ldGhvZCByZWFkcwogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCBjcmVhdGVzIGEgb25lIHdheSBjb21wdXRlZAogICAgICBwcm9wZXJ0eSB0byB0aGUgb3JpZ2luYWwgdmFsdWUgZm9yIHByb3BlcnR5LgogICAgQHB1YmxpYwogICAqLwoKICAvKioKICAgIFdoZXJlIGBjb21wdXRlZC5vbmVXYXlgIHByb3ZpZGVzIG9uZVdheSBiaW5kaW5ncywgYGNvbXB1dGVkLnJlYWRPbmx5YCBwcm92aWRlcwogICAgYSByZWFkT25seSBvbmUgd2F5IGJpbmRpbmcuIFZlcnkgb2Z0ZW4gd2hlbiB1c2luZyBgY29tcHV0ZWQub25lV2F5YCBvbmUgZG9lcwogICAgbm90IGFsc28gd2FudCBjaGFuZ2VzIHRvIHByb3BhZ2F0ZSBiYWNrIHVwLCBhcyB0aGV5IHdpbGwgcmVwbGFjZSB0aGUgdmFsdWUuCiAgCiAgICBUaGlzIHByZXZlbnRzIHRoZSByZXZlcnNlIGZsb3csIGFuZCBhbHNvIHRocm93cyBhbiBleGNlcHRpb24gd2hlbiBpdCBvY2N1cnMuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyByZWFkT25seSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgVXNlciB7CiAgICAgIGNvbnN0cnVjdG9yKGZpcnN0TmFtZSwgbGFzdE5hbWUpIHsKICAgICAgICBzZXQodGhpcywgJ2ZpcnN0TmFtZScsIGZpcnN0TmFtZSk7CiAgICAgICAgc2V0KHRoaXMsICdsYXN0TmFtZScsIGxhc3ROYW1lKTsKICAgICAgfQogIAogICAgICBAcmVhZE9ubHkoJ2ZpcnN0TmFtZScpIG5pY2tOYW1lOwogICAgfSk7CiAgCiAgICBsZXQgdGVkZHkgPSBuZXcgVXNlcignVGVkZHknLCAnWmVlbm55Jyk7CiAgCiAgICB0ZWRkeS5uaWNrTmFtZTsgLy8gJ1RlZGR5JwogIAogICAgc2V0KHRlZGR5LCAnbmlja05hbWUnLCAnVGVkZHlCZWFyJyk7IC8vIHRocm93cyBFeGNlcHRpb24KICAgIC8vIHRocm93IG5ldyBFbWJlckVycm9yKCdDYW5ub3QgU2V0OiBuaWNrTmFtZSBvbjogPFVzZXI6ZW1iZXIyNzI4OD4nICk7YAogIAogICAgdGVkZHkuZmlyc3ROYW1lOyAvLyAnVGVkZHknCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IHJlYWRPbmx5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgVXNlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGZpcnN0TmFtZTogbnVsbCwKICAgICAgbGFzdE5hbWU6IG51bGwsCiAgCiAgICAgIG5pY2tOYW1lOiByZWFkT25seSgnZmlyc3ROYW1lJykKICAgIH0pOwogIAogICAgbGV0IHRlZGR5ID0gVXNlci5jcmVhdGUoewogICAgICBmaXJzdE5hbWU6ICdUZWRkeScsCiAgICAgIGxhc3ROYW1lOiAgJ1plZW5ueScKICAgIH0pOwogIAogICAgdGVkZHkubmlja05hbWU7IC8vICdUZWRkeScKICAKICAgIHNldCh0ZWRkeSwgJ25pY2tOYW1lJywgJ1RlZGR5QmVhcicpOyAvLyB0aHJvd3MgRXhjZXB0aW9uCiAgICAvLyB0aHJvdyBuZXcgRW1iZXJFcnJvcignQ2Fubm90IFNldDogbmlja05hbWUgb246IDxVc2VyOmVtYmVyMjcyODg+JyApO2AKICAKICAgIHRlZGR5LmZpcnN0TmFtZTsgLy8gJ1RlZGR5JwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHJlYWRPbmx5CiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBwYXJhbSB7U3RyaW5nfSBkZXBlbmRlbnRLZXkKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIGNyZWF0ZXMgYSBvbmUgd2F5IGNvbXB1dGVkCiAgICBwcm9wZXJ0eSB0byB0aGUgb3JpZ2luYWwgdmFsdWUgZm9yIHByb3BlcnR5LgogICAgQHNpbmNlIDEuNS4wCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIHJlYWRPbmx5KGRlcGVuZGVudEtleSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQHJlYWRPbmx5IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgZGVwZW5kZW50S2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuICgwLCBfbWV0YWwuYWxpYXMpKGRlcGVuZGVudEtleSkucmVhZE9ubHkoKTsKICB9CiAgLyoqCiAgICBDcmVhdGVzIGEgbmV3IHByb3BlcnR5IHRoYXQgaXMgYW4gYWxpYXMgZm9yIGFub3RoZXIgcHJvcGVydHkgb24gYW4gb2JqZWN0LgogICAgQ2FsbHMgdG8gYGdldGAgb3IgYHNldGAgdGhpcyBwcm9wZXJ0eSBiZWhhdmUgYXMgdGhvdWdoIHRoZXkgd2VyZSBjYWxsZWQgb24gdGhlCiAgICBvcmlnaW5hbCBwcm9wZXJ0eSwgYnV0IGFsc28gcHJpbnQgYSBkZXByZWNhdGlvbiB3YXJuaW5nLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgZGVwcmVjYXRpbmdBbGlhcyB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBkZXByZWNhdGluZ0FsaWFzKCdjYXZlbmRpc2hDb3VudCcsIHsKICAgICAgICBpZDogJ2hhbXN0ZXIuZGVwcmVjYXRlLWJhbmFuYScsCiAgICAgICAgdW50aWw6ICczLjAuMCcKICAgICAgfSkKICAgICAgYmFuYW5hQ291bnQ7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKCk7CiAgCiAgICBzZXQoaGFtc3RlciwgJ2JhbmFuYUNvdW50JywgNSk7IC8vIFByaW50cyBhIGRlcHJlY2F0aW9uIHdhcm5pbmcuCiAgICBoYW1zdGVyLmNhdmVuZGlzaENvdW50OyAvLyA1CiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCwgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGRlcHJlY2F0aW5nQWxpYXMgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgYmFuYW5hQ291bnQ6IGRlcHJlY2F0aW5nQWxpYXMoJ2NhdmVuZGlzaENvdW50JywgewogICAgICAgIGlkOiAnaGFtc3Rlci5kZXByZWNhdGUtYmFuYW5hJywKICAgICAgICB1bnRpbDogJzMuMC4wJwogICAgICB9KQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICBzZXQoaGFtc3RlciwgJ2JhbmFuYUNvdW50JywgNSk7IC8vIFByaW50cyBhIGRlcHJlY2F0aW9uIHdhcm5pbmcuCiAgICBoYW1zdGVyLmNhdmVuZGlzaENvdW50OyAvLyA1CiAgICBgYGAKICAKICAgIEBtZXRob2QgZGVwcmVjYXRpbmdBbGlhcwogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBPcHRpb25zIGZvciBgZGVwcmVjYXRlYC4KICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIGNyZWF0ZXMgYW4gYWxpYXMgd2l0aCBhCiAgICBkZXByZWNhdGlvbiB0byB0aGUgb3JpZ2luYWwgdmFsdWUgZm9yIHByb3BlcnR5LgogICAgQHNpbmNlIDEuNy4wCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGRlcHJlY2F0aW5nQWxpYXMoZGVwZW5kZW50S2V5LCBvcHRpb25zKSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAZGVwcmVjYXRpbmdBbGlhcyBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGBkZXBlbmRlbnRLZXlgIGFuZCBgb3B0aW9uc2AgcGFyYW1ldGVycycsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoZGVwZW5kZW50S2V5LCB7CiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIlVzYWdlIG9mIGAiICsga2V5ICsgImAgaXMgZGVwcmVjYXRlZCwgdXNlIGAiICsgZGVwZW5kZW50S2V5ICsgImAgaW5zdGVhZC4iLCBmYWxzZSwgb3B0aW9ucykpOwogICAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkodGhpcywgZGVwZW5kZW50S2V5KTsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5LCB2YWx1ZSkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgX2RlYnVnLmRlcHJlY2F0ZSkoIlVzYWdlIG9mIGAiICsga2V5ICsgImAgaXMgZGVwcmVjYXRlZCwgdXNlIGAiICsgZGVwZW5kZW50S2V5ICsgImAgaW5zdGVhZC4iLCBmYWxzZSwgb3B0aW9ucykpOwogICAgICAgICgwLCBfbWV0YWwuc2V0KSh0aGlzLCBkZXBlbmRlbnRLZXksIHZhbHVlKTsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0KICAgIH0pOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyL29iamVjdC9saWIvY29tcHV0ZWQvcmVkdWNlX2NvbXB1dGVkX21hY3JvcyIsIFsiZXhwb3J0cyIsICJAZW1iZXIvZGVidWciLCAiQGVtYmVyLy1pbnRlcm5hbHMvbWV0YWwiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9kZWJ1ZywgX21ldGFsLCBfcnVudGltZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuc3VtID0gc3VtOwogIF9leHBvcnRzLm1heCA9IG1heDsKICBfZXhwb3J0cy5taW4gPSBtaW47CiAgX2V4cG9ydHMubWFwID0gbWFwOwogIF9leHBvcnRzLm1hcEJ5ID0gbWFwQnk7CiAgX2V4cG9ydHMuZmlsdGVyID0gZmlsdGVyOwogIF9leHBvcnRzLmZpbHRlckJ5ID0gZmlsdGVyQnk7CiAgX2V4cG9ydHMudW5pcSA9IHVuaXE7CiAgX2V4cG9ydHMudW5pcUJ5ID0gdW5pcUJ5OwogIF9leHBvcnRzLmludGVyc2VjdCA9IGludGVyc2VjdDsKICBfZXhwb3J0cy5zZXREaWZmID0gc2V0RGlmZjsKICBfZXhwb3J0cy5jb2xsZWN0ID0gY29sbGVjdDsKICBfZXhwb3J0cy5zb3J0ID0gc29ydDsKICBfZXhwb3J0cy51bmlvbiA9IHZvaWQgMDsKCiAgLyoqCiAgQG1vZHVsZSBAZW1iZXIvb2JqZWN0CiAgKi8KICBmdW5jdGlvbiByZWR1Y2VNYWNybyhkZXBlbmRlbnRLZXksIGNhbGxiYWNrLCBpbml0aWFsVmFsdWUsIG5hbWUpIHsKICAgIChmYWxzZSAmJiAhKCEvW1xbXF1ce1x9XS9nLnRlc3QoZGVwZW5kZW50S2V5KSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJEZXBlbmRlbnQga2V5IHBhc3NlZCB0byBgY29tcHV0ZWQuIiArIG5hbWUgKyAiYCBzaG91bGRuJ3QgY29udGFpbiBicmFjZSBleHBhbmRpbmcgcGF0dGVybi4iLCAhL1tcW1xdXHtcfV0vZy50ZXN0KGRlcGVuZGVudEtleSkpKTsKICAgIHJldHVybiAoMCwgX21ldGFsLmNvbXB1dGVkKShkZXBlbmRlbnRLZXkgKyAiLltdIiwgZnVuY3Rpb24gKCkgewogICAgICB2YXIgYXJyID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIGRlcGVuZGVudEtleSk7CgogICAgICBpZiAoYXJyID09PSBudWxsIHx8IHR5cGVvZiBhcnIgIT09ICdvYmplY3QnKSB7CiAgICAgICAgcmV0dXJuIGluaXRpYWxWYWx1ZTsKICAgICAgfQoKICAgICAgcmV0dXJuIGFyci5yZWR1Y2UoY2FsbGJhY2ssIGluaXRpYWxWYWx1ZSwgdGhpcyk7CiAgICB9KS5yZWFkT25seSgpOwogIH0KCiAgZnVuY3Rpb24gYXJyYXlNYWNybyhkZXBlbmRlbnRLZXksIGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzLCBjYWxsYmFjaykgewogICAgLy8gVGhpcyBpcyBhIGJpdCB1Z2x5CiAgICB2YXIgcHJvcGVydHlOYW1lOwoKICAgIGlmICgvQGVhY2gvLnRlc3QoZGVwZW5kZW50S2V5KSkgewogICAgICBwcm9wZXJ0eU5hbWUgPSBkZXBlbmRlbnRLZXkucmVwbGFjZSgvXC5AZWFjaC4qJC8sICcnKTsKICAgIH0gZWxzZSB7CiAgICAgIHByb3BlcnR5TmFtZSA9IGRlcGVuZGVudEtleTsKICAgICAgZGVwZW5kZW50S2V5ICs9ICcuW10nOwogICAgfQoKICAgIHJldHVybiBfbWV0YWwuY29tcHV0ZWQuYXBwbHkodm9pZCAwLCBbZGVwZW5kZW50S2V5XS5jb25jYXQoYWRkaXRpb25hbERlcGVuZGVudEtleXMsIFtmdW5jdGlvbiAoKSB7CiAgICAgIHZhciB2YWx1ZSA9ICgwLCBfbWV0YWwuZ2V0KSh0aGlzLCBwcm9wZXJ0eU5hbWUpOwoKICAgICAgaWYgKCgwLCBfcnVudGltZS5pc0FycmF5KSh2YWx1ZSkpIHsKICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKGNhbGxiYWNrLmNhbGwodGhpcywgdmFsdWUpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICAgIH0KICAgIH1dKSkucmVhZE9ubHkoKTsKICB9CgogIGZ1bmN0aW9uIG11bHRpQXJyYXlNYWNybyhfZGVwZW5kZW50S2V5cywgY2FsbGJhY2ssIG5hbWUpIHsKICAgIChmYWxzZSAmJiAhKF9kZXBlbmRlbnRLZXlzLmV2ZXJ5KGZ1bmN0aW9uIChkZXBlbmRlbnRLZXkpIHsKICAgICAgcmV0dXJuICEvW1xbXF1ce1x9XS9nLnRlc3QoZGVwZW5kZW50S2V5KTsKICAgIH0pKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIkRlcGVuZGVudCBrZXlzIHBhc3NlZCB0byBgY29tcHV0ZWQuIiArIG5hbWUgKyAiYCBzaG91bGRuJ3QgY29udGFpbiBicmFjZSBleHBhbmRpbmcgcGF0dGVybi4iLCBfZGVwZW5kZW50S2V5cy5ldmVyeShmdW5jdGlvbiAoZGVwZW5kZW50S2V5KSB7CiAgICAgIHJldHVybiAhL1tcW1xdXHtcfV0vZy50ZXN0KGRlcGVuZGVudEtleSk7CiAgICB9KSkpOwoKICAgIHZhciBkZXBlbmRlbnRLZXlzID0gX2RlcGVuZGVudEtleXMubWFwKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgcmV0dXJuIGtleSArICIuW10iOwogICAgfSk7CgogICAgcmV0dXJuIF9tZXRhbC5jb21wdXRlZC5hcHBseSh2b2lkIDAsIGRlcGVuZGVudEtleXMuY29uY2F0KFtmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAoMCwgX3J1bnRpbWUuQSkoY2FsbGJhY2suY2FsbCh0aGlzLCBfZGVwZW5kZW50S2V5cykpOwogICAgfV0pKS5yZWFkT25seSgpOwogIH0KICAvKioKICAgIEEgY29tcHV0ZWQgcHJvcGVydHkgdGhhdCByZXR1cm5zIHRoZSBzdW0gb2YgdGhlIHZhbHVlcyBpbiB0aGUgZGVwZW5kZW50IGFycmF5LgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHN1bSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSW52b2ljZSB7CiAgICAgIGxpbmVJdGVtcyA9IFsxLjAwLCAyLjUwLCA5Ljk5XTsKICAKICAgICAgQHN1bSgnbGluZUl0ZW1zJykgdG90YWw7CiAgICB9CiAgCiAgICBsZXQgaW52b2ljZSA9IG5ldyBJbnZvaWNlKCk7CiAgCiAgICBpbnZvaWNlLnRvdGFsOyAvLyAxMy40OQogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBzdW0gfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBJbnZvaWNlID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgbGluZUl0ZW1zOiBbMS4wMCwgMi41MCwgOS45OV0sCiAgCiAgICAgIHRvdGFsOiBzdW0oJ2xpbmVJdGVtcycpCiAgICB9KQogIAogICAgbGV0IGludm9pY2UgPSBJbnZvaWNlLmNyZWF0ZSgpOwogIAogICAgaW52b2ljZS50b3RhbDsgLy8gMTMuNDkKICAgIGBgYAogIAogICAgQG1ldGhvZCBzdW0KICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHN0YXRpYwogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZXMgdGhlIHN1bSBvZiBhbGwgdmFsdWVzIGluIHRoZQogICAgZGVwZW5kZW50S2V5J3MgYXJyYXkKICAgIEBzaW5jZSAxLjQuMAogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBzdW0oZGVwZW5kZW50S2V5KSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAc3VtIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgZGVwZW5kZW50S2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIHJlZHVjZU1hY3JvKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKHN1bSwgaXRlbSkgewogICAgICByZXR1cm4gc3VtICsgaXRlbTsKICAgIH0sIDAsICdzdW0nKTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgY2FsY3VsYXRlcyB0aGUgbWF4aW11bSB2YWx1ZSBpbiB0aGUgZGVwZW5kZW50IGFycmF5LgogICAgVGhpcyB3aWxsIHJldHVybiBgLUluZmluaXR5YCB3aGVuIHRoZSBkZXBlbmRlbnQgYXJyYXkgaXMgZW1wdHkuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBtYXBCeSwgbWF4IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBQZXJzb24gewogICAgICBjaGlsZHJlbiA9IFtdOwogIAogICAgICBAbWFwQnkoJ2NoaWxkcmVuJywgJ2FnZScpIGNoaWxkQWdlczsKICAgICAgQG1heCgnY2hpbGRBZ2VzJykgbWF4Q2hpbGRBZ2U7CiAgICB9CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gbmV3IFBlcnNvbigpOwogIAogICAgbG9yZEJ5cm9uLm1heENoaWxkQWdlOyAvLyAtSW5maW5pdHkKICAKICAgIHNldChsb3JkQnlyb24sICdjaGlsZHJlbicsIFsKICAgICAgewogICAgICAgIG5hbWU6ICdBdWd1c3RhIEFkYSBCeXJvbicsCiAgICAgICAgYWdlOiA3CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLm1heENoaWxkQWdlOyAvLyA3CiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIC4uLmxvcmRCeXJvbi5jaGlsZHJlbiwKICAgICAgewogICAgICAgIG5hbWU6ICdBbGxlZ3JhIEJ5cm9uJywKICAgICAgICBhZ2U6IDUKICAgICAgfSwgewogICAgICAgIG5hbWU6ICdFbGl6YWJldGggTWVkb3JhIExlaWdoJywKICAgICAgICBhZ2U6IDgKICAgICAgfQogICAgXSk7CiAgICBsb3JkQnlyb24ubWF4Q2hpbGRBZ2U7IC8vIDgKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbWFwQnksIG1heCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGNoaWxkQWdlczogbWFwQnkoJ2NoaWxkcmVuJywgJ2FnZScpLAogICAgICBtYXhDaGlsZEFnZTogbWF4KCdjaGlsZEFnZXMnKQogICAgfSk7CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gUGVyc29uLmNyZWF0ZSh7IGNoaWxkcmVuOiBbXSB9KTsKICAKICAgIGxvcmRCeXJvbi5tYXhDaGlsZEFnZTsgLy8gLUluZmluaXR5CiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIHsKICAgICAgICBuYW1lOiAnQXVndXN0YSBBZGEgQnlyb24nLAogICAgICAgIGFnZTogNwogICAgICB9CiAgICBdKTsKICAgIGxvcmRCeXJvbi5tYXhDaGlsZEFnZTsgLy8gNwogIAogICAgc2V0KGxvcmRCeXJvbiwgJ2NoaWxkcmVuJywgWwogICAgICAuLi5sb3JkQnlyb24uY2hpbGRyZW4sCiAgICAgIHsKICAgICAgICBuYW1lOiAnQWxsZWdyYSBCeXJvbicsCiAgICAgICAgYWdlOiA1CiAgICAgIH0sIHsKICAgICAgICBuYW1lOiAnRWxpemFiZXRoIE1lZG9yYSBMZWlnaCcsCiAgICAgICAgYWdlOiA4CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLm1heENoaWxkQWdlOyAvLyA4CiAgICBgYGAKICAKICAgIElmIHRoZSB0eXBlcyBvZiB0aGUgYXJndW1lbnRzIGFyZSBub3QgbnVtYmVycywgdGhleSB3aWxsIGJlIGNvbnZlcnRlZCB0bwogICAgbnVtYmVycyBhbmQgdGhlIHR5cGUgb2YgdGhlIHJldHVybiB2YWx1ZSB3aWxsIGFsd2F5cyBiZSBgTnVtYmVyYC4gRm9yIGV4YW1wbGUsCiAgICB0aGUgbWF4IG9mIGEgbGlzdCBvZiBEYXRlIG9iamVjdHMgd2lsbCBiZSB0aGUgaGlnaGVzdCB0aW1lc3RhbXAgYXMgYSBgTnVtYmVyYC4KICAgIFRoaXMgYmVoYXZpb3IgaXMgY29uc2lzdGVudCB3aXRoIGBNYXRoLm1heGAuCiAgCiAgICBAbWV0aG9kIG1heAogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlcyB0aGUgbGFyZ2VzdCB2YWx1ZSBpbiB0aGUgZGVwZW5kZW50S2V5J3MKICAgIGFycmF5CiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIG1heChkZXBlbmRlbnRLZXkpIHsKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBtYXggYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBhIGBkZXBlbmRlbnRLZXlgIHBhcmFtZXRlcicsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICByZXR1cm4gcmVkdWNlTWFjcm8oZGVwZW5kZW50S2V5LCBmdW5jdGlvbiAobWF4LCBpdGVtKSB7CiAgICAgIHJldHVybiBNYXRoLm1heChtYXgsIGl0ZW0pOwogICAgfSwgLUluZmluaXR5LCAnbWF4Jyk7CiAgfQogIC8qKgogICAgQSBjb21wdXRlZCBwcm9wZXJ0eSB0aGF0IGNhbGN1bGF0ZXMgdGhlIG1pbmltdW0gdmFsdWUgaW4gdGhlIGRlcGVuZGVudCBhcnJheS4KICAgIFRoaXMgd2lsbCByZXR1cm4gYEluZmluaXR5YCB3aGVuIHRoZSBkZXBlbmRlbnQgYXJyYXkgaXMgZW1wdHkuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBtYXBCeSwgbWluIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBQZXJzb24gewogICAgICBjaGlsZHJlbiA9IFtdOwogIAogICAgICBAbWFwQnkoJ2NoaWxkcmVuJywgJ2FnZScpIGNoaWxkQWdlczsKICAgICAgQG1pbignY2hpbGRBZ2VzJykgbWluQ2hpbGRBZ2U7CiAgICB9CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gUGVyc29uLmNyZWF0ZSh7IGNoaWxkcmVuOiBbXSB9KTsKICAKICAgIGxvcmRCeXJvbi5taW5DaGlsZEFnZTsgLy8gSW5maW5pdHkKICAKICAgIHNldChsb3JkQnlyb24sICdjaGlsZHJlbicsIFsKICAgICAgewogICAgICAgIG5hbWU6ICdBdWd1c3RhIEFkYSBCeXJvbicsCiAgICAgICAgYWdlOiA3CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLm1pbkNoaWxkQWdlOyAvLyA3CiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIC4uLmxvcmRCeXJvbi5jaGlsZHJlbiwKICAgICAgewogICAgICAgIG5hbWU6ICdBbGxlZ3JhIEJ5cm9uJywKICAgICAgICBhZ2U6IDUKICAgICAgfSwgewogICAgICAgIG5hbWU6ICdFbGl6YWJldGggTWVkb3JhIExlaWdoJywKICAgICAgICBhZ2U6IDgKICAgICAgfQogICAgXSk7CiAgICBsb3JkQnlyb24ubWluQ2hpbGRBZ2U7IC8vIDUKICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbWFwQnksIG1pbiB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IFBlcnNvbiA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGNoaWxkQWdlczogbWFwQnkoJ2NoaWxkcmVuJywgJ2FnZScpLAogICAgICBtaW5DaGlsZEFnZTogbWluKCdjaGlsZEFnZXMnKQogICAgfSk7CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gUGVyc29uLmNyZWF0ZSh7IGNoaWxkcmVuOiBbXSB9KTsKICAKICAgIGxvcmRCeXJvbi5taW5DaGlsZEFnZTsgLy8gSW5maW5pdHkKICAKICAgIHNldChsb3JkQnlyb24sICdjaGlsZHJlbicsIFsKICAgICAgewogICAgICAgIG5hbWU6ICdBdWd1c3RhIEFkYSBCeXJvbicsCiAgICAgICAgYWdlOiA3CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLm1pbkNoaWxkQWdlOyAvLyA3CiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIC4uLmxvcmRCeXJvbi5jaGlsZHJlbiwKICAgICAgewogICAgICAgIG5hbWU6ICdBbGxlZ3JhIEJ5cm9uJywKICAgICAgICBhZ2U6IDUKICAgICAgfSwgewogICAgICAgIG5hbWU6ICdFbGl6YWJldGggTWVkb3JhIExlaWdoJywKICAgICAgICBhZ2U6IDgKICAgICAgfQogICAgXSk7CiAgICBsb3JkQnlyb24ubWluQ2hpbGRBZ2U7IC8vIDUKICAgIGBgYAogIAogICAgSWYgdGhlIHR5cGVzIG9mIHRoZSBhcmd1bWVudHMgYXJlIG5vdCBudW1iZXJzLCB0aGV5IHdpbGwgYmUgY29udmVydGVkIHRvCiAgICBudW1iZXJzIGFuZCB0aGUgdHlwZSBvZiB0aGUgcmV0dXJuIHZhbHVlIHdpbGwgYWx3YXlzIGJlIGBOdW1iZXJgLiBGb3IgZXhhbXBsZSwKICAgIHRoZSBtaW4gb2YgYSBsaXN0IG9mIERhdGUgb2JqZWN0cyB3aWxsIGJlIHRoZSBsb3dlc3QgdGltZXN0YW1wIGFzIGEgYE51bWJlcmAuCiAgICBUaGlzIGJlaGF2aW9yIGlzIGNvbnNpc3RlbnQgd2l0aCBgTWF0aC5taW5gLgogIAogICAgQG1ldGhvZCBtaW4KICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHN0YXRpYwogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZXMgdGhlIHNtYWxsZXN0IHZhbHVlIGluIHRoZSBkZXBlbmRlbnRLZXkncyBhcnJheQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBtaW4oZGVwZW5kZW50S2V5KSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAbWluIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYSBgZGVwZW5kZW50S2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIHJlZHVjZU1hY3JvKGRlcGVuZGVudEtleSwgZnVuY3Rpb24gKG1pbiwgaXRlbSkgewogICAgICByZXR1cm4gTWF0aC5taW4obWluLCBpdGVtKTsKICAgIH0sIEluZmluaXR5LCAnbWluJyk7CiAgfQogIC8qKgogICAgUmV0dXJucyBhbiBhcnJheSBtYXBwZWQgdmlhIHRoZSBjYWxsYmFjawogIAogICAgVGhlIGNhbGxiYWNrIG1ldGhvZCB5b3UgcHJvdmlkZSBzaG91bGQgaGF2ZSB0aGUgZm9sbG93aW5nIHNpZ25hdHVyZToKICAgIC0gYGl0ZW1gIGlzIHRoZSBjdXJyZW50IGl0ZW0gaW4gdGhlIGl0ZXJhdGlvbi4KICAgIC0gYGluZGV4YCBpcyB0aGUgaW50ZWdlciBpbmRleCBvZiB0aGUgY3VycmVudCBpdGVtIGluIHRoZSBpdGVyYXRpb24uCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBmdW5jdGlvbiBtYXBDYWxsYmFjayhpdGVtLCBpbmRleCk7CiAgICBgYGAKICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IG1hcCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIGNvbnN0cnVjdG9yKGNob3JlcykgewogICAgICAgIHNldCh0aGlzLCAnY2hvcmVzJywgY2hvcmVzKTsKICAgICAgfQogIAogICAgICBAbWFwKCdjaG9yZXMnLCBmdW5jdGlvbihjaG9yZSwgaW5kZXgpIHsKICAgICAgICByZXR1cm4gYCR7Y2hvcmUudG9VcHBlckNhc2UoKX0hYDsKICAgICAgfSkKICAgICAgZXhjaXRpbmdDaG9yZXM7CiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gbmV3IEhhbXN0ZXIoWydjbGVhbicsICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnXSk7CiAgCiAgICBoYW1zdGVyLmV4Y2l0aW5nQ2hvcmVzOyAvLyBbJ0NMRUFOIScsICdXUklURSBNT1JFIFVOSVQgVEVTVFMhJ10KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbWFwIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgSGFtc3RlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIGV4Y2l0aW5nQ2hvcmVzOiBtYXAoJ2Nob3JlcycsIGZ1bmN0aW9uKGNob3JlLCBpbmRleCkgewogICAgICAgIHJldHVybiBgJHtjaG9yZS50b1VwcGVyQ2FzZSgpfSFgOwogICAgICB9KQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKHsKICAgICAgY2hvcmVzOiBbJ2NsZWFuJywgJ3dyaXRlIG1vcmUgdW5pdCB0ZXN0cyddCiAgICB9KTsKICAKICAgIGhhbXN0ZXIuZXhjaXRpbmdDaG9yZXM7IC8vIFsnQ0xFQU4hJywgJ1dSSVRFIE1PUkUgVU5JVCBURVNUUyEnXQogICAgYGBgCiAgCiAgICBZb3UgY2FuIG9wdGlvbmFsbHkgcGFzcyBhbiBhcnJheSBvZiBhZGRpdGlvbmFsIGRlcGVuZGVudCBrZXlzIGFzIHRoZSBzZWNvbmQKICAgIHBhcmFtZXRlciB0byB0aGUgbWFjcm8sIGlmIHlvdXIgbWFwIGZ1bmN0aW9uIHJlbGllcyBvbiBhbnkgZXh0ZXJuYWwgdmFsdWVzOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBtYXAgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGNsYXNzIEhhbXN0ZXIgewogICAgICBzaG91bGRVcHBlckNhc2UgPSBmYWxzZTsKICAKICAgICAgY29uc3RydWN0b3IoY2hvcmVzKSB7CiAgICAgICAgc2V0KHRoaXMsICdjaG9yZXMnLCBjaG9yZXMpOwogICAgICB9CiAgCiAgICAgIEBtYXAoJ2Nob3JlcycsIFsnc2hvdWxkVXBwZXJDYXNlJ10sIGZ1bmN0aW9uKGNob3JlLCBpbmRleCkgewogICAgICAgIGlmICh0aGlzLnNob3VsZFVwcGVyQ2FzZSkgewogICAgICAgICAgcmV0dXJuIGAke2Nob3JlLnRvVXBwZXJDYXNlKCl9IWA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBgJHtjaG9yZX0hYDsKICAgICAgICB9CiAgICAgIH0pCiAgICAgIGV4Y2l0aW5nQ2hvcmVzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcihbJ2NsZWFuJywgJ3dyaXRlIG1vcmUgdW5pdCB0ZXN0cyddKTsKICAKICAgIGhhbXN0ZXIuZXhjaXRpbmdDaG9yZXM7IC8vIFsnY2xlYW4hJywgJ3dyaXRlIG1vcmUgdW5pdCB0ZXN0cyEnXQogIAogICAgc2V0KGhhbXN0ZXIsICdzaG91bGRVcHBlckNhc2UnLCB0cnVlKTsKICAgIGhhbXN0ZXIuZXhjaXRpbmdDaG9yZXM7IC8vIFsnQ0xFQU4hJywgJ1dSSVRFIE1PUkUgVU5JVCBURVNUUyEnXQogICAgYGBgCiAgCiAgICBAbWV0aG9kIG1hcAogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge0FycmF5fSBbYWRkaXRpb25hbERlcGVuZGVudEtleXNdIG9wdGlvbmFsIGFycmF5IG9mIGFkZGl0aW9uYWwKICAgIGRlcGVuZGVudCBrZXlzCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gYW4gYXJyYXkgbWFwcGVkIHZpYSB0aGUgY2FsbGJhY2sKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbWFwKGRlcGVuZGVudEtleSwgYWRkaXRpb25hbERlcGVuZGVudEtleXMsIGNhbGxiYWNrKSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAbWFwIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBgZGVwZW5kZW50S2V5YCBhbmQgYGNhbGxiYWNrYCBwYXJhbWV0ZXJzJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKCiAgICBpZiAoY2FsbGJhY2sgPT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYWRkaXRpb25hbERlcGVuZGVudEtleXMgPT09ICdmdW5jdGlvbicpIHsKICAgICAgY2FsbGJhY2sgPSBhZGRpdGlvbmFsRGVwZW5kZW50S2V5czsKICAgICAgYWRkaXRpb25hbERlcGVuZGVudEtleXMgPSBbXTsKICAgIH0KCiAgICAoZmFsc2UgJiYgISh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnVGhlIGZpbmFsIHBhcmFtZXRlciBwcm92aWRlZCB0byBtYXAgbXVzdCBiZSBhIGNhbGxiYWNrIGZ1bmN0aW9uJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICAoZmFsc2UgJiYgIShBcnJheS5pc0FycmF5KGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgc2Vjb25kIHBhcmFtZXRlciBwcm92aWRlZCB0byBtYXAgbXVzdCBlaXRoZXIgYmUgdGhlIGNhbGxiYWNrIG9yIGFuIGFycmF5IG9mIGFkZGl0aW9uYWwgZGVwZW5kZW50IGtleXMnLCBBcnJheS5pc0FycmF5KGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzKSkpOwogICAgcmV0dXJuIGFycmF5TWFjcm8oZGVwZW5kZW50S2V5LCBhZGRpdGlvbmFsRGVwZW5kZW50S2V5cywgZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgIHJldHVybiB2YWx1ZS5tYXAoY2FsbGJhY2ssIHRoaXMpOwogICAgfSk7CiAgfQogIC8qKgogICAgUmV0dXJucyBhbiBhcnJheSBtYXBwZWQgdG8gdGhlIHNwZWNpZmllZCBrZXkuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBtYXBCeSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgUGVyc29uIHsKICAgICAgY2hpbGRyZW4gPSBbXTsKICAKICAgICAgQG1hcEJ5KCdjaGlsZHJlbicsICdhZ2UnKSBjaGlsZEFnZXM7CiAgICB9CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gbmV3IFBlcnNvbigpOwogIAogICAgbG9yZEJ5cm9uLmNoaWxkQWdlczsgLy8gW10KICAKICAgIHNldChsb3JkQnlyb24sICdjaGlsZHJlbicsIFsKICAgICAgewogICAgICAgIG5hbWU6ICdBdWd1c3RhIEFkYSBCeXJvbicsCiAgICAgICAgYWdlOiA3CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLmNoaWxkQWdlczsgLy8gWzddCiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIC4uLmxvcmRCeXJvbi5jaGlsZHJlbiwKICAgICAgewogICAgICAgIG5hbWU6ICdBbGxlZ3JhIEJ5cm9uJywKICAgICAgICBhZ2U6IDUKICAgICAgfSwgewogICAgICAgIG5hbWU6ICdFbGl6YWJldGggTWVkb3JhIExlaWdoJywKICAgICAgICBhZ2U6IDgKICAgICAgfQogICAgXSk7CiAgICBsb3JkQnlyb24uY2hpbGRBZ2VzOyAvLyBbNywgNSwgOF0KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgbWFwQnkgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBQZXJzb24gPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBjaGlsZEFnZXM6IG1hcEJ5KCdjaGlsZHJlbicsICdhZ2UnKQogICAgfSk7CiAgCiAgICBsZXQgbG9yZEJ5cm9uID0gUGVyc29uLmNyZWF0ZSh7IGNoaWxkcmVuOiBbXSB9KTsKICAKICAgIGxvcmRCeXJvbi5jaGlsZEFnZXM7IC8vIFtdCiAgCiAgICBzZXQobG9yZEJ5cm9uLCAnY2hpbGRyZW4nLCBbCiAgICAgIHsKICAgICAgICBuYW1lOiAnQXVndXN0YSBBZGEgQnlyb24nLAogICAgICAgIGFnZTogNwogICAgICB9CiAgICBdKTsKICAgIGxvcmRCeXJvbi5jaGlsZEFnZXM7IC8vIFs3XQogIAogICAgc2V0KGxvcmRCeXJvbiwgJ2NoaWxkcmVuJywgWwogICAgICAuLi5sb3JkQnlyb24uY2hpbGRyZW4sCiAgICAgIHsKICAgICAgICBuYW1lOiAnQWxsZWdyYSBCeXJvbicsCiAgICAgICAgYWdlOiA1CiAgICAgIH0sIHsKICAgICAgICBuYW1lOiAnRWxpemFiZXRoIE1lZG9yYSBMZWlnaCcsCiAgICAgICAgYWdlOiA4CiAgICAgIH0KICAgIF0pOwogICAgbG9yZEJ5cm9uLmNoaWxkQWdlczsgLy8gWzcsIDUsIDhdCiAgICBgYGAKICAKICAgIEBtZXRob2QgbWFwQnkKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHN0YXRpYwogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleQogICAgQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5S2V5CiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBhbiBhcnJheSBtYXBwZWQgdG8gdGhlIHNwZWNpZmllZCBrZXkKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbWFwQnkoZGVwZW5kZW50S2V5LCBwcm9wZXJ0eUtleSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQG1hcEJ5IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYGRlcGVuZGVudEtleWAgYW5kIGBwcm9wZXJ0eUtleWAgcGFyYW1ldGVycycsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICAoZmFsc2UgJiYgISh0eXBlb2YgcHJvcGVydHlLZXkgPT09ICdzdHJpbmcnKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2Bjb21wdXRlZC5tYXBCeWAgZXhwZWN0cyBhIHByb3BlcnR5IHN0cmluZyBmb3IgaXRzIHNlY29uZCBhcmd1bWVudCwgJyArICdwZXJoYXBzIHlvdSBtZWFudCB0byB1c2UgIm1hcCInLCB0eXBlb2YgcHJvcGVydHlLZXkgPT09ICdzdHJpbmcnKSk7CiAgICAoZmFsc2UgJiYgISghL1tcW1xdXHtcfV0vZy50ZXN0KGRlcGVuZGVudEtleSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiRGVwZW5kZW50IGtleSBwYXNzZWQgdG8gYGNvbXB1dGVkLm1hcEJ5YCBzaG91bGRuJ3QgY29udGFpbiBicmFjZSBleHBhbmRpbmcgcGF0dGVybi4iLCAhL1tcW1xdXHtcfV0vZy50ZXN0KGRlcGVuZGVudEtleSkpKTsKICAgIHJldHVybiBtYXAoZGVwZW5kZW50S2V5ICsgIi5AZWFjaC4iICsgcHJvcGVydHlLZXksIGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkoaXRlbSwgcHJvcGVydHlLZXkpOwogICAgfSk7CiAgfQogIC8qKgogICAgRmlsdGVycyB0aGUgYXJyYXkgYnkgdGhlIGNhbGxiYWNrLgogIAogICAgVGhlIGNhbGxiYWNrIG1ldGhvZCB5b3UgcHJvdmlkZSBzaG91bGQgaGF2ZSB0aGUgZm9sbG93aW5nIHNpZ25hdHVyZToKICAgIC0gYGl0ZW1gIGlzIHRoZSBjdXJyZW50IGl0ZW0gaW4gdGhlIGl0ZXJhdGlvbi4KICAgIC0gYGluZGV4YCBpcyB0aGUgaW50ZWdlciBpbmRleCBvZiB0aGUgY3VycmVudCBpdGVtIGluIHRoZSBpdGVyYXRpb24uCiAgICAtIGBhcnJheWAgaXMgdGhlIGRlcGVuZGFudCBhcnJheSBpdHNlbGYuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBmdW5jdGlvbiBmaWx0ZXJDYWxsYmFjayhpdGVtLCBpbmRleCwgYXJyYXkpOwogICAgYGBgCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBmaWx0ZXIgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGNsYXNzIEhhbXN0ZXIgewogICAgICBjb25zdHJ1Y3RvcihjaG9yZXMpIHsKICAgICAgICBzZXQodGhpcywgJ2Nob3JlcycsIGNob3Jlcyk7CiAgICAgIH0KICAKICAgICAgQGZpbHRlcignY2hvcmVzJywgZnVuY3Rpb24oY2hvcmUsIGluZGV4LCBhcnJheSkgewogICAgICAgIHJldHVybiAhY2hvcmUuZG9uZTsKICAgICAgfSkKICAgICAgcmVtYWluaW5nQ2hvcmVzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBIYW1zdGVyLmNyZWF0ZShbCiAgICAgIHsgbmFtZTogJ2Nvb2snLCBkb25lOiB0cnVlIH0sCiAgICAgIHsgbmFtZTogJ2NsZWFuJywgZG9uZTogdHJ1ZSB9LAogICAgICB7IG5hbWU6ICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnLCBkb25lOiBmYWxzZSB9CiAgICBdKTsKICAKICAgIGhhbXN0ZXIucmVtYWluaW5nQ2hvcmVzOyAvLyBbe25hbWU6ICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnLCBkb25lOiBmYWxzZX1dCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGZpbHRlciB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICByZW1haW5pbmdDaG9yZXM6IGZpbHRlcignY2hvcmVzJywgZnVuY3Rpb24oY2hvcmUsIGluZGV4LCBhcnJheSkgewogICAgICAgIHJldHVybiAhY2hvcmUuZG9uZTsKICAgICAgfSkKICAgIH0pOwogIAogICAgbGV0IGhhbXN0ZXIgPSBIYW1zdGVyLmNyZWF0ZSh7CiAgICAgIGNob3JlczogWwogICAgICAgIHsgbmFtZTogJ2Nvb2snLCBkb25lOiB0cnVlIH0sCiAgICAgICAgeyBuYW1lOiAnY2xlYW4nLCBkb25lOiB0cnVlIH0sCiAgICAgICAgeyBuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2UgfQogICAgICBdCiAgICB9KTsKICAKICAgIGhhbXN0ZXIucmVtYWluaW5nQ2hvcmVzOyAvLyBbe25hbWU6ICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnLCBkb25lOiBmYWxzZX1dCiAgICBgYGAKICAKICAgIFlvdSBjYW4gYWxzbyB1c2UgYEBlYWNoLnByb3BlcnR5YCBpbiB5b3VyIGRlcGVuZGVudCBrZXksIHRoZSBjYWxsYmFjayB3aWxsCiAgICBzdGlsbCB1c2UgdGhlIHVuZGVybHlpbmcgYXJyYXk6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGZpbHRlciB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIGNvbnN0cnVjdG9yKGNob3JlcykgewogICAgICAgIHNldCh0aGlzLCAnY2hvcmVzJywgY2hvcmVzKTsKICAgICAgfQogIAogICAgICBAZmlsdGVyKCdjaG9yZXMuQGVhY2guZG9uZScsIGZ1bmN0aW9uKGNob3JlLCBpbmRleCwgYXJyYXkpIHsKICAgICAgICByZXR1cm4gIWNob3JlLmRvbmU7CiAgICAgIH0pCiAgICAgIHJlbWFpbmluZ0Nob3JlczsKICAgIH0KICAKICAgIGxldCBoYW1zdGVyID0gbmV3IEhhbXN0ZXIoWwogICAgICB7IG5hbWU6ICdjb29rJywgZG9uZTogdHJ1ZSB9LAogICAgICB7IG5hbWU6ICdjbGVhbicsIGRvbmU6IHRydWUgfSwKICAgICAgeyBuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2UgfQogICAgXSk7CiAgICBoYW1zdGVyLnJlbWFpbmluZ0Nob3JlczsgLy8gW3tuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2V9XQogIAogICAgc2V0KGhhbXN0ZXIuY2hvcmVzWzJdLCAnZG9uZScsIHRydWUpOwogICAgaGFtc3Rlci5yZW1haW5pbmdDaG9yZXM7IC8vIFtdCiAgICBgYGAKICAKICAgIEZpbmFsbHksIHlvdSBjYW4gb3B0aW9uYWxseSBwYXNzIGFuIGFycmF5IG9mIGFkZGl0aW9uYWwgZGVwZW5kZW50IGtleXMgYXMgdGhlCiAgICBzZWNvbmQgcGFyYW1ldGVyIHRvIHRoZSBtYWNybywgaWYgeW91ciBmaWx0ZXIgZnVuY3Rpb24gcmVsaWVzIG9uIGFueSBleHRlcm5hbAogICAgdmFsdWVzOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZmlsdGVyIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgY29uc3RydWN0b3IoY2hvcmVzKSB7CiAgICAgICAgc2V0KHRoaXMsICdjaG9yZXMnLCBjaG9yZXMpOwogICAgICB9CiAgCiAgICAgIGRvbmVLZXkgPSAnZmluaXNoZWQnOwogIAogICAgICBAZmlsdGVyKCdjaG9yZXMnLCBbJ2RvbmVLZXknXSwgZnVuY3Rpb24oY2hvcmUsIGluZGV4LCBhcnJheSkgewogICAgICAgIHJldHVybiAhY2hvcmVbdGhpcy5kb25lS2V5XTsKICAgICAgfSkKICAgICAgcmVtYWluaW5nQ2hvcmVzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcihbCiAgICAgIHsgbmFtZTogJ2Nvb2snLCBmaW5pc2hlZDogdHJ1ZSB9LAogICAgICB7IG5hbWU6ICdjbGVhbicsIGZpbmlzaGVkOiB0cnVlIH0sCiAgICAgIHsgbmFtZTogJ3dyaXRlIG1vcmUgdW5pdCB0ZXN0cycsIGZpbmlzaGVkOiBmYWxzZSB9CiAgICBdKTsKICAKICAgIGhhbXN0ZXIucmVtYWluaW5nQ2hvcmVzOyAvLyBbe25hbWU6ICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnLCBmaW5pc2hlZDogZmFsc2V9XQogICAgYGBgCiAgCiAgICBAbWV0aG9kIGZpbHRlcgogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge0FycmF5fSBbYWRkaXRpb25hbERlcGVuZGVudEtleXNdIG9wdGlvbmFsIGFycmF5IG9mIGFkZGl0aW9uYWwgZGVwZW5kZW50IGtleXMKICAgIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrCiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSB0aGUgZmlsdGVyZWQgYXJyYXkKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZmlsdGVyKGRlcGVuZGVudEtleSwgYWRkaXRpb25hbERlcGVuZGVudEtleXMsIGNhbGxiYWNrKSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAZmlsdGVyIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBgZGVwZW5kZW50S2V5YCBhbmQgYGNhbGxiYWNrYCBwYXJhbWV0ZXJzJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKCiAgICBpZiAoY2FsbGJhY2sgPT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYWRkaXRpb25hbERlcGVuZGVudEtleXMgPT09ICdmdW5jdGlvbicpIHsKICAgICAgY2FsbGJhY2sgPSBhZGRpdGlvbmFsRGVwZW5kZW50S2V5czsKICAgICAgYWRkaXRpb25hbERlcGVuZGVudEtleXMgPSBbXTsKICAgIH0KCiAgICAoZmFsc2UgJiYgISh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnVGhlIGZpbmFsIHBhcmFtZXRlciBwcm92aWRlZCB0byBmaWx0ZXIgbXVzdCBiZSBhIGNhbGxiYWNrIGZ1bmN0aW9uJywgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSk7CiAgICAoZmFsc2UgJiYgIShBcnJheS5pc0FycmF5KGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdUaGUgc2Vjb25kIHBhcmFtZXRlciBwcm92aWRlZCB0byBmaWx0ZXIgbXVzdCBlaXRoZXIgYmUgdGhlIGNhbGxiYWNrIG9yIGFuIGFycmF5IG9mIGFkZGl0aW9uYWwgZGVwZW5kZW50IGtleXMnLCBBcnJheS5pc0FycmF5KGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzKSkpOwogICAgcmV0dXJuIGFycmF5TWFjcm8oZGVwZW5kZW50S2V5LCBhZGRpdGlvbmFsRGVwZW5kZW50S2V5cywgZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgIHJldHVybiB2YWx1ZS5maWx0ZXIoY2FsbGJhY2ssIHRoaXMpOwogICAgfSk7CiAgfQogIC8qKgogICAgRmlsdGVycyB0aGUgYXJyYXkgYnkgdGhlIHByb3BlcnR5IGFuZCB2YWx1ZS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IGZpbHRlckJ5IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBIYW1zdGVyIHsKICAgICAgY29uc3RydWN0b3IoY2hvcmVzKSB7CiAgICAgICAgc2V0KHRoaXMsICdjaG9yZXMnLCBjaG9yZXMpOwogICAgICB9CiAgCiAgICAgIEBmaWx0ZXJCeSgnY2hvcmVzJywgJ2RvbmUnLCBmYWxzZSkgcmVtYWluaW5nQ2hvcmVzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcihbCiAgICAgIHsgbmFtZTogJ2Nvb2snLCBkb25lOiB0cnVlIH0sCiAgICAgIHsgbmFtZTogJ2NsZWFuJywgZG9uZTogdHJ1ZSB9LAogICAgICB7IG5hbWU6ICd3cml0ZSBtb3JlIHVuaXQgdGVzdHMnLCBkb25lOiBmYWxzZSB9CiAgICBdKTsKICAKICAgIGhhbXN0ZXIucmVtYWluaW5nQ2hvcmVzOyAvLyBbeyBuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2UgfV0KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgZmlsdGVyQnkgfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGxldCBIYW1zdGVyID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgcmVtYWluaW5nQ2hvcmVzOiBmaWx0ZXJCeSgnY2hvcmVzJywgJ2RvbmUnLCBmYWxzZSkKICAgIH0pOwogIAogICAgbGV0IGhhbXN0ZXIgPSBIYW1zdGVyLmNyZWF0ZSh7CiAgICAgIGNob3JlczogWwogICAgICAgIHsgbmFtZTogJ2Nvb2snLCBkb25lOiB0cnVlIH0sCiAgICAgICAgeyBuYW1lOiAnY2xlYW4nLCBkb25lOiB0cnVlIH0sCiAgICAgICAgeyBuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2UgfQogICAgICBdCiAgICB9KTsKICAKICAgIGhhbXN0ZXIucmVtYWluaW5nQ2hvcmVzOyAvLyBbeyBuYW1lOiAnd3JpdGUgbW9yZSB1bml0IHRlc3RzJywgZG9uZTogZmFsc2UgfV0KICAgIGBgYAogIAogICAgQG1ldGhvZCBmaWx0ZXJCeQogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gZGVwZW5kZW50S2V5CiAgICBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlLZXkKICAgIEBwYXJhbSB7Kn0gdmFsdWUKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IHRoZSBmaWx0ZXJlZCBhcnJheQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBmaWx0ZXJCeShkZXBlbmRlbnRLZXksIHByb3BlcnR5S2V5LCB2YWx1ZSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQGZpbHRlckJ5IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBgZGVwZW5kZW50S2V5YCBhbmQgYHByb3BlcnR5S2V5YCBwYXJhbWV0ZXJzJywgISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpKTsKICAgIChmYWxzZSAmJiAhKCEvW1xbXF1ce1x9XS9nLnRlc3QoZGVwZW5kZW50S2V5KSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCJEZXBlbmRlbnQga2V5IHBhc3NlZCB0byBgY29tcHV0ZWQuZmlsdGVyQnlgIHNob3VsZG4ndCBjb250YWluIGJyYWNlIGV4cGFuZGluZyBwYXR0ZXJuLiIsICEvW1xbXF1ce1x9XS9nLnRlc3QoZGVwZW5kZW50S2V5KSkpOwogICAgdmFyIGNhbGxiYWNrOwoKICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyKSB7CiAgICAgIGNhbGxiYWNrID0gZnVuY3Rpb24gY2FsbGJhY2soaXRlbSkgewogICAgICAgIHJldHVybiAoMCwgX21ldGFsLmdldCkoaXRlbSwgcHJvcGVydHlLZXkpOwogICAgICB9OwogICAgfSBlbHNlIHsKICAgICAgY2FsbGJhY2sgPSBmdW5jdGlvbiBjYWxsYmFjayhpdGVtKSB7CiAgICAgICAgcmV0dXJuICgwLCBfbWV0YWwuZ2V0KShpdGVtLCBwcm9wZXJ0eUtleSkgPT09IHZhbHVlOwogICAgICB9OwogICAgfQoKICAgIHJldHVybiBmaWx0ZXIoZGVwZW5kZW50S2V5ICsgIi5AZWFjaC4iICsgcHJvcGVydHlLZXksIGNhbGxiYWNrKTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgYSBuZXcgYXJyYXkgd2l0aCBhbGwgdGhlIHVuaXF1ZSBlbGVtZW50cwogICAgZnJvbSBvbmUgb3IgbW9yZSBkZXBlbmRlbnQgYXJyYXlzLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgdW5pcSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIGNvbnN0cnVjdG9yKGZydWl0cykgewogICAgICAgIHNldCh0aGlzLCAnZnJ1aXRzJywgZnJ1aXRzKTsKICAgICAgfQogIAogICAgICBAdW5pcSgnZnJ1aXRzJykgdW5pcXVlRnJ1aXRzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcihbCiAgICAgICdiYW5hbmEnLAogICAgICAnZ3JhcGUnLAogICAgICAna2FsZScsCiAgICAgICdiYW5hbmEnCiAgICBdKTsKICAKICAgIGhhbXN0ZXIudW5pcXVlRnJ1aXRzOyAvLyBbJ2JhbmFuYScsICdncmFwZScsICdrYWxlJ10KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgdW5pcSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICB1bmlxdWVGcnVpdHM6IHVuaXEoJ2ZydWl0cycpCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoewogICAgICBmcnVpdHM6IFsKICAgICAgICAnYmFuYW5hJywKICAgICAgICAnZ3JhcGUnLAogICAgICAgICdrYWxlJywKICAgICAgICAnYmFuYW5hJwogICAgICBdCiAgICB9KTsKICAKICAgIGhhbXN0ZXIudW5pcXVlRnJ1aXRzOyAvLyBbJ2JhbmFuYScsICdncmFwZScsICdrYWxlJ10KICAgIGBgYAogIAogICAgQG1ldGhvZCB1bmlxCiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eUtleSoKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVzIGEgbmV3IGFycmF5IHdpdGggYWxsIHRoZQogICAgdW5pcXVlIGVsZW1lbnRzIGZyb20gdGhlIGRlcGVuZGVudCBhcnJheQogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiB1bmlxKCkgewogICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICB9CgogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQHVuaXEvQHVuaW9uIGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBvbmUgZGVwZW5kZW50IGtleSBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIG11bHRpQXJyYXlNYWNybyhhcmdzLCBmdW5jdGlvbiAoZGVwZW5kZW50S2V5cykgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgdmFyIHVuaXEgPSAoMCwgX3J1bnRpbWUuQSkoKTsKICAgICAgdmFyIHNlZW4gPSBuZXcgU2V0KCk7CiAgICAgIGRlcGVuZGVudEtleXMuZm9yRWFjaChmdW5jdGlvbiAoZGVwZW5kZW50S2V5KSB7CiAgICAgICAgdmFyIHZhbHVlID0gKDAsIF9tZXRhbC5nZXQpKF90aGlzLCBkZXBlbmRlbnRLZXkpOwoKICAgICAgICBpZiAoKDAsIF9ydW50aW1lLmlzQXJyYXkpKHZhbHVlKSkgewogICAgICAgICAgdmFsdWUuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkgewogICAgICAgICAgICBpZiAoIXNlZW4uaGFzKGl0ZW0pKSB7CiAgICAgICAgICAgICAgc2Vlbi5hZGQoaXRlbSk7CiAgICAgICAgICAgICAgdW5pcS5wdXNoKGl0ZW0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gdW5pcTsKICAgIH0sICd1bmlxJyk7CiAgfQogIC8qKgogICAgQSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIGEgbmV3IGFycmF5IHdpdGggYWxsIHRoZSB1bmlxdWUgZWxlbWVudHMKICAgIGZyb20gYW4gYXJyYXksIHdpdGggdW5pcXVlbmVzcyBkZXRlcm1pbmVkIGJ5IHNwZWNpZmljIGtleS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzZXQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IHVuaXFCeSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIGNvbnN0cnVjdG9yKGZydWl0cykgewogICAgICAgIHNldCh0aGlzLCAnZnJ1aXRzJywgZnJ1aXRzKTsKICAgICAgfQogIAogICAgICBAdW5pcUJ5KCdmcnVpdHMnLCAnaWQnKSB1bmlxdWVGcnVpdHM7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKFsKICAgICAgeyBpZDogMSwgJ2JhbmFuYScgfSwKICAgICAgeyBpZDogMiwgJ2dyYXBlJyB9LAogICAgICB7IGlkOiAzLCAncGVhY2gnIH0sCiAgICAgIHsgaWQ6IDEsICdiYW5hbmEnIH0KICAgIF0pOwogIAogICAgaGFtc3Rlci51bmlxdWVGcnVpdHM7IC8vIFsgeyBpZDogMSwgJ2JhbmFuYScgfSwgeyBpZDogMiwgJ2dyYXBlJyB9LCB7IGlkOiAzLCAncGVhY2gnIH1dCiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBFbWJlck9iamVjdCBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAgIGltcG9ydCB7IHVuaXFCeSB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICB1bmlxdWVGcnVpdHM6IHVuaXFCeSgnZnJ1aXRzJywgJ2lkJykKICAgIH0pOwogIAogICAgbGV0IGhhbXN0ZXIgPSBIYW1zdGVyLmNyZWF0ZSh7CiAgICAgIGZydWl0czogWwogICAgICAgIHsgaWQ6IDEsICdiYW5hbmEnIH0sCiAgICAgICAgeyBpZDogMiwgJ2dyYXBlJyB9LAogICAgICAgIHsgaWQ6IDMsICdwZWFjaCcgfSwKICAgICAgICB7IGlkOiAxLCAnYmFuYW5hJyB9CiAgICAgIF0KICAgIH0pOwogIAogICAgaGFtc3Rlci51bmlxdWVGcnVpdHM7IC8vIFsgeyBpZDogMSwgJ2JhbmFuYScgfSwgeyBpZDogMiwgJ2dyYXBlJyB9LCB7IGlkOiAzLCAncGVhY2gnIH1dCiAgICBgYGAKICAKICAgIEBtZXRob2QgdW5pcUJ5CiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7U3RyaW5nfSBkZXBlbmRlbnRLZXkKICAgIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eUtleQogICAgQHJldHVybiB7Q29tcHV0ZWRQcm9wZXJ0eX0gY29tcHV0ZXMgYSBuZXcgYXJyYXkgd2l0aCBhbGwgdGhlCiAgICB1bmlxdWUgZWxlbWVudHMgZnJvbSB0aGUgZGVwZW5kZW50IGFycmF5CiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIHVuaXFCeShkZXBlbmRlbnRLZXksIHByb3BlcnR5S2V5KSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAdW5pcUJ5IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYGRlcGVuZGVudEtleWAgYW5kIGBwcm9wZXJ0eUtleWAgcGFyYW1ldGVycycsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICAoZmFsc2UgJiYgISghL1tcW1xdXHtcfV0vZy50ZXN0KGRlcGVuZGVudEtleSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiRGVwZW5kZW50IGtleSBwYXNzZWQgdG8gYGNvbXB1dGVkLnVuaXFCeWAgc2hvdWxkbid0IGNvbnRhaW4gYnJhY2UgZXhwYW5kaW5nIHBhdHRlcm4uIiwgIS9bXFtcXVx7XH1dL2cudGVzdChkZXBlbmRlbnRLZXkpKSk7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoZGVwZW5kZW50S2V5ICsgIi5bXSIsIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGxpc3QgPSAoMCwgX21ldGFsLmdldCkodGhpcywgZGVwZW5kZW50S2V5KTsKICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5pc0FycmF5KShsaXN0KSA/ICgwLCBfcnVudGltZS51bmlxQnkpKGxpc3QsIHByb3BlcnR5S2V5KSA6ICgwLCBfcnVudGltZS5BKSgpOwogICAgfSkucmVhZE9ubHkoKTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgYSBuZXcgYXJyYXkgd2l0aCBhbGwgdGhlIHVuaXF1ZSBlbGVtZW50cwogICAgZnJvbSBvbmUgb3IgbW9yZSBkZXBlbmRlbnQgYXJyYXlzLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgdW5pb24gfSBmcm9tICdAZW1iZXIvb2JqZWN0L2NvbXB1dGVkJzsKICAKICAgIGNsYXNzIEhhbXN0ZXIgewogICAgICBjb25zdHJ1Y3RvcihmcnVpdHMsIHZlZ2V0YWJsZXMpIHsKICAgICAgICBzZXQodGhpcywgJ2ZydWl0cycsIGZydWl0cyk7CiAgICAgICAgc2V0KHRoaXMsICd2ZWdldGFibGVzJywgdmVnZXRhYmxlcyk7CiAgICAgIH0KICAKICAgICAgQHVuaW9uKCdmcnVpdHMnLCAndmVnZXRhYmxlcycpIGVkaWJsZVBsYW50czsKICAgIH0pOwogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcsIEhhbXN0ZXIoCiAgICAgIFsKICAgICAgICAnYmFuYW5hJywKICAgICAgICAnZ3JhcGUnLAogICAgICAgICdrYWxlJywKICAgICAgICAnYmFuYW5hJywKICAgICAgICAndG9tYXRvJwogICAgICBdLAogICAgICBbCiAgICAgICAgJ3RvbWF0bycsCiAgICAgICAgJ2NhcnJvdCcsCiAgICAgICAgJ2xldHR1Y2UnCiAgICAgIF0KICAgICk7CiAgCiAgICBoYW1zdGVyLnVuaXF1ZUZydWl0czsgLy8gWydiYW5hbmEnLCAnZ3JhcGUnLCAna2FsZScsICd0b21hdG8nLCAnY2Fycm90JywgJ2xldHR1Y2UnXQogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyB1bmlvbiB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICB1bmlxdWVGcnVpdHM6IHVuaW9uKCdmcnVpdHMnLCAndmVnZXRhYmxlcycpCiAgICB9KTsKICAKICAgIGxldCBoYW1zdGVyID0gSGFtc3Rlci5jcmVhdGUoewogICAgICBmcnVpdHM6IFsKICAgICAgICAnYmFuYW5hJywKICAgICAgICAnZ3JhcGUnLAogICAgICAgICdrYWxlJywKICAgICAgICAnYmFuYW5hJywKICAgICAgICAndG9tYXRvJwogICAgICBdLAogICAgICB2ZWdldGFibGVzOiBbCiAgICAgICAgJ3RvbWF0bycsCiAgICAgICAgJ2NhcnJvdCcsCiAgICAgICAgJ2xldHR1Y2UnCiAgICAgIF0KICAgIH0pOwogIAogICAgaGFtc3Rlci51bmlxdWVGcnVpdHM7IC8vIFsnYmFuYW5hJywgJ2dyYXBlJywgJ2thbGUnLCAndG9tYXRvJywgJ2NhcnJvdCcsICdsZXR0dWNlJ10KICAgIGBgYAogIAogICAgQG1ldGhvZCB1bmlvbgogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlLZXkqCiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlcyBhIG5ldyBhcnJheSB3aXRoIGFsbCB0aGUgdW5pcXVlIGVsZW1lbnRzCiAgICBmcm9tIG9uZSBvciBtb3JlIGRlcGVuZGVudCBhcnJheXMuCiAgICBAcHVibGljCiAgKi8KCgogIHZhciB1bmlvbiA9IHVuaXE7CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgYSBuZXcgYXJyYXkgd2l0aCBhbGwgdGhlIGVsZW1lbnRzCiAgICB0d28gb3IgbW9yZSBkZXBlbmRlbnQgYXJyYXlzIGhhdmUgaW4gY29tbW9uLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgaW50ZXJzZWN0IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBGcmllbmRHcm91cHMgewogICAgICBjb25zdHJ1Y3RvcihhZGFGcmllbmRzLCBjaGFybGVzRnJpZW5kcykgewogICAgICAgIHNldCh0aGlzLCAnYWRhRnJpZW5kcycsIGFkYUZyaWVuZHMpOwogICAgICAgIHNldCh0aGlzLCAnY2hhcmxlc0ZyaWVuZHMnLCBjaGFybGVzRnJpZW5kcyk7CiAgICAgIH0KICAKICAgICAgQGludGVyc2VjdCgnYWRhRnJpZW5kcycsICdjaGFybGVzRnJpZW5kcycpIGZyaWVuZHNJbkNvbW1vbjsKICAgIH0KICAKICAgIGxldCBncm91cHMgPSBuZXcgRnJpZW5kR3JvdXBzKAogICAgICBbJ0NoYXJsZXMgQmFiYmFnZScsICdKb2huIEhvYmhvdXNlJywgJ1dpbGxpYW0gS2luZycsICdNYXJ5IFNvbWVydmlsbGUnXSwKICAgICAgWydXaWxsaWFtIEtpbmcnLCAnTWFyeSBTb21lcnZpbGxlJywgJ0FkYSBMb3ZlbGFjZScsICdHZW9yZ2UgUGVhY29jayddCiAgICApOwogIAogICAgZ3JvdXBzLmZyaWVuZHNJbkNvbW1vbjsgLy8gWydXaWxsaWFtIEtpbmcnLCAnTWFyeSBTb21lcnZpbGxlJ10KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgaW50ZXJzZWN0IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgRnJpZW5kR3JvdXBzID0gRW1iZXJPYmplY3QuZXh0ZW5kKHsKICAgICAgZnJpZW5kc0luQ29tbW9uOiBpbnRlcnNlY3QoJ2FkYUZyaWVuZHMnLCAnY2hhcmxlc0ZyaWVuZHMnKQogICAgfSk7CiAgCiAgICBsZXQgZ3JvdXBzID0gRnJpZW5kR3JvdXBzLmNyZWF0ZSh7CiAgICAgIGFkYUZyaWVuZHM6IFsnQ2hhcmxlcyBCYWJiYWdlJywgJ0pvaG4gSG9iaG91c2UnLCAnV2lsbGlhbSBLaW5nJywgJ01hcnkgU29tZXJ2aWxsZSddLAogICAgICBjaGFybGVzRnJpZW5kczogWydXaWxsaWFtIEtpbmcnLCAnTWFyeSBTb21lcnZpbGxlJywgJ0FkYSBMb3ZlbGFjZScsICdHZW9yZ2UgUGVhY29jayddCiAgICB9KTsKICAKICAgIGdyb3Vwcy5mcmllbmRzSW5Db21tb247IC8vIFsnV2lsbGlhbSBLaW5nJywgJ01hcnkgU29tZXJ2aWxsZSddCiAgICBgYGAKICAKICAgIEBtZXRob2QgaW50ZXJzZWN0CiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eUtleSoKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVzIGEgbmV3IGFycmF5IHdpdGggYWxsIHRoZSBkdXBsaWNhdGVkCiAgICBlbGVtZW50cyBmcm9tIHRoZSBkZXBlbmRlbnQgYXJyYXlzCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMudW5pb24gPSB1bmlvbjsKCiAgZnVuY3Rpb24gaW50ZXJzZWN0KCkgewogICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4yKSwgX2tleTIgPSAwOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7CiAgICAgIGFyZ3NbX2tleTJdID0gYXJndW1lbnRzW19rZXkyXTsKICAgIH0KCiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAaW50ZXJzZWN0IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBvbmUgZGVwZW5kZW50IGtleSBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIG11bHRpQXJyYXlNYWNybyhhcmdzLCBmdW5jdGlvbiAoZGVwZW5kZW50S2V5cykgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIHZhciBhcnJheXMgPSBkZXBlbmRlbnRLZXlzLm1hcChmdW5jdGlvbiAoZGVwZW5kZW50S2V5KSB7CiAgICAgICAgdmFyIGFycmF5ID0gKDAsIF9tZXRhbC5nZXQpKF90aGlzMiwgZGVwZW5kZW50S2V5KTsKICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLmlzQXJyYXkpKGFycmF5KSA/IGFycmF5IDogW107CiAgICAgIH0pOwogICAgICB2YXIgcmVzdWx0cyA9IGFycmF5cy5wb3AoKS5maWx0ZXIoZnVuY3Rpb24gKGNhbmRpZGF0ZSkgewogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICB2YXIgZm91bmQgPSBmYWxzZTsKICAgICAgICAgIHZhciBhcnJheSA9IGFycmF5c1tpXTsKCiAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGFycmF5Lmxlbmd0aDsgaisrKSB7CiAgICAgICAgICAgIGlmIChhcnJheVtqXSA9PT0gY2FuZGlkYXRlKSB7CiAgICAgICAgICAgICAgZm91bmQgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKGZvdW5kID09PSBmYWxzZSkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfSk7CiAgICAgIHJldHVybiAoMCwgX3J1bnRpbWUuQSkocmVzdWx0cyk7CiAgICB9LCAnaW50ZXJzZWN0Jyk7CiAgfQogIC8qKgogICAgQSBjb21wdXRlZCBwcm9wZXJ0eSB3aGljaCByZXR1cm5zIGEgbmV3IGFycmF5IHdpdGggYWxsIHRoZSBwcm9wZXJ0aWVzIGZyb20gdGhlCiAgICBmaXJzdCBkZXBlbmRlbnQgYXJyYXkgdGhhdCBhcmUgbm90IGluIHRoZSBzZWNvbmQgZGVwZW5kZW50IGFycmF5LgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgc2V0RGlmZiB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIGNvbnN0cnVjdG9yKGxpa2VzLCBmcnVpdHMpIHsKICAgICAgICBzZXQodGhpcywgJ2xpa2VzJywgbGlrZXMpOwogICAgICAgIHNldCh0aGlzLCAnZnJ1aXRzJywgZnJ1aXRzKTsKICAgICAgfQogIAogICAgICBAc2V0RGlmZignbGlrZXMnLCAnZnJ1aXRzJykgd2FudHM7CiAgICB9CiAgCiAgICBsZXQgaGFtc3RlciA9IG5ldyBIYW1zdGVyKAogICAgICBbCiAgICAgICAgJ2JhbmFuYScsCiAgICAgICAgJ2dyYXBlJywKICAgICAgICAna2FsZScKICAgICAgXSwKICAgICAgWwogICAgICAgICdncmFwZScsCiAgICAgICAgJ2thbGUnLAogICAgICBdCiAgICApOwogIAogICAgaGFtc3Rlci53YW50czsgLy8gWydiYW5hbmEnXQogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBzZXREaWZmIH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgSGFtc3RlciA9IEVtYmVyT2JqZWN0LmV4dGVuZCh7CiAgICAgIHdhbnRzOiBzZXREaWZmKCdsaWtlcycsICdmcnVpdHMnKQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKHsKICAgICAgbGlrZXM6IFsKICAgICAgICAnYmFuYW5hJywKICAgICAgICAnZ3JhcGUnLAogICAgICAgICdrYWxlJwogICAgICBdLAogICAgICBmcnVpdHM6IFsKICAgICAgICAnZ3JhcGUnLAogICAgICAgICdrYWxlJywKICAgICAgXQogICAgfSk7CiAgCiAgICBoYW1zdGVyLndhbnRzOyAvLyBbJ2JhbmFuYSddCiAgICBgYGAKICAKICAgIEBtZXRob2Qgc2V0RGlmZgogICAgQGZvciBAZW1iZXIvb2JqZWN0L2NvbXB1dGVkCiAgICBAc3RhdGljCiAgICBAcGFyYW0ge1N0cmluZ30gc2V0QVByb3BlcnR5CiAgICBAcGFyYW0ge1N0cmluZ30gc2V0QlByb3BlcnR5CiAgICBAcmV0dXJuIHtDb21wdXRlZFByb3BlcnR5fSBjb21wdXRlcyBhIG5ldyBhcnJheSB3aXRoIGFsbCB0aGUgaXRlbXMgZnJvbSB0aGUKICAgIGZpcnN0IGRlcGVuZGVudCBhcnJheSB0aGF0IGFyZSBub3QgaW4gdGhlIHNlY29uZCBkZXBlbmRlbnQgYXJyYXkKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gc2V0RGlmZihzZXRBUHJvcGVydHksIHNldEJQcm9wZXJ0eSkgewogICAgKGZhbHNlICYmICEoISgwLCBfbWV0YWwuaXNFbGVtZW50RGVzY3JpcHRvcikoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnWW91IGF0dGVtcHRlZCB0byB1c2UgQHNldERpZmYgYXMgYSBkZWNvcmF0b3IgZGlyZWN0bHksIGJ1dCBpdCByZXF1aXJlcyBhdGxlYXN0IG9uZSBkZXBlbmRlbnQga2V5IHBhcmFtZXRlcicsICEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSk7CiAgICAoZmFsc2UgJiYgIShhcmd1bWVudHMubGVuZ3RoID09PSAyKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ2Bjb21wdXRlZC5zZXREaWZmYCByZXF1aXJlcyBleGFjdGx5IHR3byBkZXBlbmRlbnQgYXJyYXlzLicsIGFyZ3VtZW50cy5sZW5ndGggPT09IDIpKTsKICAgIChmYWxzZSAmJiAhKCEvW1xbXF1ce1x9XS9nLnRlc3Qoc2V0QVByb3BlcnR5KSAmJiAhL1tcW1xdXHtcfV0vZy50ZXN0KHNldEJQcm9wZXJ0eSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiRGVwZW5kZW50IGtleXMgcGFzc2VkIHRvIGBjb21wdXRlZC5zZXREaWZmYCBzaG91bGRuJ3QgY29udGFpbiBicmFjZSBleHBhbmRpbmcgcGF0dGVybi4iLCAhL1tcW1xdXHtcfV0vZy50ZXN0KHNldEFQcm9wZXJ0eSkgJiYgIS9bXFtcXVx7XH1dL2cudGVzdChzZXRCUHJvcGVydHkpKSk7CiAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoc2V0QVByb3BlcnR5ICsgIi5bXSIsIHNldEJQcm9wZXJ0eSArICIuW10iLCBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBzZXRBID0gdGhpcy5nZXQoc2V0QVByb3BlcnR5KTsKICAgICAgdmFyIHNldEIgPSB0aGlzLmdldChzZXRCUHJvcGVydHkpOwoKICAgICAgaWYgKCEoMCwgX3J1bnRpbWUuaXNBcnJheSkoc2V0QSkpIHsKICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICAgIH0KCiAgICAgIGlmICghKDAsIF9ydW50aW1lLmlzQXJyYXkpKHNldEIpKSB7CiAgICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5BKShzZXRBKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHNldEEuZmlsdGVyKGZ1bmN0aW9uICh4KSB7CiAgICAgICAgcmV0dXJuIHNldEIuaW5kZXhPZih4KSA9PT0gLTE7CiAgICAgIH0pOwogICAgfSkucmVhZE9ubHkoKTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHRoYXQgcmV0dXJucyB0aGUgYXJyYXkgb2YgdmFsdWVzIGZvciB0aGUgcHJvdmlkZWQKICAgIGRlcGVuZGVudCBwcm9wZXJ0aWVzLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgY29sbGVjdCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgSGFtc3RlciB7CiAgICAgIEBjb2xsZWN0KCdoYXQnLCAnc2hpcnQnKSBjbG90aGVzOwogICAgfQogIAogICAgbGV0IGhhbXN0ZXIgPSBuZXcgSGFtc3RlcigpOwogIAogICAgaGFtc3Rlci5jbG90aGVzOyAvLyBbbnVsbCwgbnVsbF0KICAKICAgIHNldChoYW1zdGVyLCAnaGF0JywgJ0NhbXAgSGF0Jyk7CiAgICBzZXQoaGFtc3RlciwgJ3NoaXJ0JywgJ0NhbXAgU2hpcnQnKTsKICAgIGhhbXN0ZXIuY2xvdGhlczsgLy8gWydDYW1wIEhhdCcsICdDYW1wIFNoaXJ0J10KICAgIGBgYAogIAogICAgQ2xhc3NpYyBDbGFzcyBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgY29sbGVjdCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgbGV0IEhhbXN0ZXIgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICBjbG90aGVzOiBjb2xsZWN0KCdoYXQnLCAnc2hpcnQnKQogICAgfSk7CiAgCiAgICBsZXQgaGFtc3RlciA9IEhhbXN0ZXIuY3JlYXRlKCk7CiAgCiAgICBoYW1zdGVyLmNsb3RoZXM7IC8vIFtudWxsLCBudWxsXQogIAogICAgc2V0KGhhbXN0ZXIsICdoYXQnLCAnQ2FtcCBIYXQnKTsKICAgIHNldChoYW1zdGVyLCAnc2hpcnQnLCAnQ2FtcCBTaGlydCcpOwogICAgaGFtc3Rlci5jbG90aGVzOyAvLyBbJ0NhbXAgSGF0JywgJ0NhbXAgU2hpcnQnXQogICAgYGBgCiAgCiAgICBAbWV0aG9kIGNvbGxlY3QKICAgIEBmb3IgQGVtYmVyL29iamVjdC9jb21wdXRlZAogICAgQHN0YXRpYwogICAgQHBhcmFtIHtTdHJpbmd9IGRlcGVuZGVudEtleSoKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIG1hcHMgdmFsdWVzIG9mIGFsbCBwYXNzZWQKICAgIGluIHByb3BlcnRpZXMgdG8gYW4gYXJyYXkuCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGNvbGxlY3QoKSB7CiAgICBmb3IgKHZhciBfbGVuMyA9IGFyZ3VtZW50cy5sZW5ndGgsIGRlcGVuZGVudEtleXMgPSBuZXcgQXJyYXkoX2xlbjMpLCBfa2V5MyA9IDA7IF9rZXkzIDwgX2xlbjM7IF9rZXkzKyspIHsKICAgICAgZGVwZW5kZW50S2V5c1tfa2V5M10gPSBhcmd1bWVudHNbX2tleTNdOwogICAgfQoKICAgIChmYWxzZSAmJiAhKCEoMCwgX21ldGFsLmlzRWxlbWVudERlc2NyaXB0b3IpKEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoJ1lvdSBhdHRlbXB0ZWQgdG8gdXNlIEBjb2xsZWN0IGFzIGEgZGVjb3JhdG9yIGRpcmVjdGx5LCBidXQgaXQgcmVxdWlyZXMgYXRsZWFzdCBvbmUgZGVwZW5kZW50IGtleSBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwogICAgcmV0dXJuIG11bHRpQXJyYXlNYWNybyhkZXBlbmRlbnRLZXlzLCBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBfdGhpczMgPSB0aGlzOwoKICAgICAgdmFyIHJlcyA9IGRlcGVuZGVudEtleXMubWFwKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICB2YXIgdmFsID0gKDAsIF9tZXRhbC5nZXQpKF90aGlzMywga2V5KTsKICAgICAgICByZXR1cm4gdmFsID09PSB1bmRlZmluZWQgPyBudWxsIDogdmFsOwogICAgICB9KTsKICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5BKShyZXMpOwogICAgfSwgJ2NvbGxlY3QnKTsKICB9CiAgLyoqCiAgICBBIGNvbXB1dGVkIHByb3BlcnR5IHdoaWNoIHJldHVybnMgYSBuZXcgYXJyYXkgd2l0aCBhbGwgdGhlIHByb3BlcnRpZXMgZnJvbSB0aGUKICAgIGZpcnN0IGRlcGVuZGVudCBhcnJheSBzb3J0ZWQgYmFzZWQgb24gYSBwcm9wZXJ0eSBvciBzb3J0IGZ1bmN0aW9uLiBUaGUgc29ydAogICAgbWFjcm8gY2FuIGJlIHVzZWQgaW4gdHdvIGRpZmZlcmVudCB3YXlzOgogIAogICAgMS4gQnkgcHJvdmlkaW5nIGEgc29ydCBjYWxsYmFjayBmdW5jdGlvbgogICAgMi4gQnkgcHJvdmlkaW5nIGFuIGFycmF5IG9mIGtleXMgdG8gc29ydCB0aGUgYXJyYXkKICAKICAgIEluIHRoZSBmaXJzdCBmb3JtLCB0aGUgY2FsbGJhY2sgbWV0aG9kIHlvdSBwcm92aWRlIHNob3VsZCBoYXZlIHRoZSBmb2xsb3dpbmcKICAgIHNpZ25hdHVyZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGZ1bmN0aW9uIHNvcnRDYWxsYmFjayhpdGVtQSwgaXRlbUIpOwogICAgYGBgCiAgCiAgICAtIGBpdGVtQWAgdGhlIGZpcnN0IGl0ZW0gdG8gY29tcGFyZS4KICAgIC0gYGl0ZW1CYCB0aGUgc2Vjb25kIGl0ZW0gdG8gY29tcGFyZS4KICAKICAgIFRoaXMgZnVuY3Rpb24gc2hvdWxkIHJldHVybiBuZWdhdGl2ZSBudW1iZXIgKGUuZy4gYC0xYCkgd2hlbiBgaXRlbUFgIHNob3VsZAogICAgY29tZSBiZWZvcmUgYGl0ZW1CYC4gSXQgc2hvdWxkIHJldHVybiBwb3NpdGl2ZSBudW1iZXIgKGUuZy4gYDFgKSB3aGVuIGBpdGVtQWAKICAgIHNob3VsZCBjb21lIGFmdGVyIGBpdGVtQmAuIElmIHRoZSBgaXRlbUFgIGFuZCBgaXRlbUJgIGFyZSBlcXVhbCB0aGlzIGZ1bmN0aW9uCiAgICBzaG91bGQgcmV0dXJuIGAwYC4KICAKICAgIFRoZXJlZm9yZSwgaWYgdGhpcyBmdW5jdGlvbiBpcyBjb21wYXJpbmcgc29tZSBudW1lcmljIHZhbHVlcywgc2ltcGxlIGBpdGVtQSAtCiAgICBpdGVtQmAgb3IgYGl0ZW1BLmdldCggJ2ZvbycgKSAtIGl0ZW1CLmdldCggJ2ZvbycgKWAgY2FuIGJlIHVzZWQgaW5zdGVhZCBvZgogICAgc2VyaWVzIG9mIGBpZmAuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgc2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBzb3J0IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBjbGFzcyBUb0RvTGlzdCB7CiAgICAgIGNvbnN0cnVjdG9yKHRvZG9zKSB7CiAgICAgICAgc2V0KHRoaXMsICd0b2RvcycsIHRvZG9zKTsKICAgICAgfQogIAogICAgICAvLyB1c2luZyBhIGN1c3RvbSBzb3J0IGZ1bmN0aW9uCiAgICAgIEBzb3J0KCd0b2RvcycsIGZ1bmN0aW9uKGEsIGIpewogICAgICAgIGlmIChhLnByaW9yaXR5ID4gYi5wcmlvcml0eSkgewogICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfSBlbHNlIGlmIChhLnByaW9yaXR5IDwgYi5wcmlvcml0eSkgewogICAgICAgICAgcmV0dXJuIC0xOwogICAgICAgIH0KICAKICAgICAgICByZXR1cm4gMDsKICAgICAgfSkKICAgICAgcHJpb3JpdHlUb2RvczsKICAgIH0KICAKICAgIGxldCB0b2RvTGlzdCA9IG5ldyBUb0RvTGlzdChbCiAgICAgIHsgbmFtZTogJ1VuaXQgVGVzdCcsIHByaW9yaXR5OiAyIH0sCiAgICAgIHsgbmFtZTogJ0RvY3VtZW50YXRpb24nLCBwcmlvcml0eTogMyB9LAogICAgICB7IG5hbWU6ICdSZWxlYXNlJywgcHJpb3JpdHk6IDEgfQogICAgXSk7CiAgCiAgICB0b2RvTGlzdC5wcmlvcml0eVRvZG9zOyAvLyBbeyBuYW1lOidSZWxlYXNlJywgcHJpb3JpdHk6MSB9LCB7IG5hbWU6J1VuaXQgVGVzdCcsIHByaW9yaXR5OjIgfSwgeyBuYW1lOidEb2N1bWVudGF0aW9uJywgcHJpb3JpdHk6MyB9XQogICAgYGBgCiAgCiAgICBDbGFzc2ljIENsYXNzIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgRW1iZXJPYmplY3QgZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBzb3J0IH0gZnJvbSAnQGVtYmVyL29iamVjdC9jb21wdXRlZCc7CiAgCiAgICBsZXQgVG9Eb0xpc3QgPSBFbWJlck9iamVjdC5leHRlbmQoewogICAgICAvLyB1c2luZyBhIGN1c3RvbSBzb3J0IGZ1bmN0aW9uCiAgICAgIHByaW9yaXR5VG9kb3M6IHNvcnQoJ3RvZG9zJywgZnVuY3Rpb24oYSwgYil7CiAgICAgICAgaWYgKGEucHJpb3JpdHkgPiBiLnByaW9yaXR5KSB7CiAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9IGVsc2UgaWYgKGEucHJpb3JpdHkgPCBiLnByaW9yaXR5KSB7CiAgICAgICAgICByZXR1cm4gLTE7CiAgICAgICAgfQogIAogICAgICAgIHJldHVybiAwOwogICAgICB9KQogICAgfSk7CiAgCiAgICBsZXQgdG9kb0xpc3QgPSBUb0RvTGlzdC5jcmVhdGUoewogICAgICB0b2RvczogWwogICAgICAgIHsgbmFtZTogJ1VuaXQgVGVzdCcsIHByaW9yaXR5OiAyIH0sCiAgICAgICAgeyBuYW1lOiAnRG9jdW1lbnRhdGlvbicsIHByaW9yaXR5OiAzIH0sCiAgICAgICAgeyBuYW1lOiAnUmVsZWFzZScsIHByaW9yaXR5OiAxIH0KICAgICAgXQogICAgfSk7CiAgCiAgICB0b2RvTGlzdC5wcmlvcml0eVRvZG9zOyAvLyBbeyBuYW1lOidSZWxlYXNlJywgcHJpb3JpdHk6MSB9LCB7IG5hbWU6J1VuaXQgVGVzdCcsIHByaW9yaXR5OjIgfSwgeyBuYW1lOidEb2N1bWVudGF0aW9uJywgcHJpb3JpdHk6MyB9XQogICAgYGBgCiAgCiAgICBZb3UgY2FuIGFsc28gb3B0aW9uYWxseSBwYXNzIGFuIGFycmF5IG9mIGFkZGl0aW9uYWwgZGVwZW5kZW50IGtleXMgYXMgdGhlCiAgICBzZWNvbmQgcGFyYW1ldGVyLCBpZiB5b3VyIHNvcnQgZnVuY3Rpb24gaXMgZGVwZW5kZW50IG9uIGFkZGl0aW9uYWwgdmFsdWVzIHRoYXQKICAgIGNvdWxkIGNoYW5nZXM6CiAgCiAgICBgYGBqcwogICAgaW1wb3J0IEVtYmVyT2JqZWN0LCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgc29ydCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgVG9Eb0xpc3QgewogICAgICBzb3J0S2V5ID0gJ3ByaW9yaXR5JzsKICAKICAgICAgY29uc3RydWN0b3IodG9kb3MpIHsKICAgICAgICBzZXQodGhpcywgJ3RvZG9zJywgdG9kb3MpOwogICAgICB9CiAgCiAgICAgIC8vIHVzaW5nIGEgY3VzdG9tIHNvcnQgZnVuY3Rpb24KICAgICAgQHNvcnQoJ3RvZG9zJywgWydzb3J0S2V5J10sIGZ1bmN0aW9uKGEsIGIpewogICAgICAgIGlmIChhW3RoaXMuc29ydEtleV0gPiBiW3RoaXMuc29ydEtleV0pIHsKICAgICAgICAgIHJldHVybiAxOwogICAgICAgIH0gZWxzZSBpZiAoYVt0aGlzLnNvcnRLZXldIDwgYlt0aGlzLnNvcnRLZXldKSB7CiAgICAgICAgICByZXR1cm4gLTE7CiAgICAgICAgfQogIAogICAgICAgIHJldHVybiAwOwogICAgICB9KQogICAgICBzb3J0ZWRUb2RvczsKICAgIH0pOwogIAogICAgbGV0IHRvZG9MaXN0ID0gbmV3IFRvRG9MaXN0KFsKICAgICAgeyBuYW1lOiAnVW5pdCBUZXN0JywgcHJpb3JpdHk6IDIgfSwKICAgICAgeyBuYW1lOiAnRG9jdW1lbnRhdGlvbicsIHByaW9yaXR5OiAzIH0sCiAgICAgIHsgbmFtZTogJ1JlbGVhc2UnLCBwcmlvcml0eTogMSB9CiAgICBdKTsKICAKICAgIHRvZG9MaXN0LnByaW9yaXR5VG9kb3M7IC8vIFt7IG5hbWU6J1JlbGVhc2UnLCBwcmlvcml0eToxIH0sIHsgbmFtZTonVW5pdCBUZXN0JywgcHJpb3JpdHk6MiB9LCB7IG5hbWU6J0RvY3VtZW50YXRpb24nLCBwcmlvcml0eTozIH1dCiAgICBgYGAKICAKICAgIEluIHRoZSBzZWNvbmQgZm9ybSwgeW91IHNob3VsZCBwcm92aWRlIHRoZSBrZXkgb2YgdGhlIGFycmF5IG9mIHNvcnQgdmFsdWVzIGFzCiAgICB0aGUgc2Vjb25kIHBhcmFtZXRlcjoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgaW1wb3J0IHsgc29ydCB9IGZyb20gJ0BlbWJlci9vYmplY3QvY29tcHV0ZWQnOwogIAogICAgY2xhc3MgVG9Eb0xpc3QgewogICAgICBjb25zdHJ1Y3Rvcih0b2RvcykgewogICAgICAgIHNldCh0aGlzLCAndG9kb3MnLCB0b2Rvcyk7CiAgICAgIH0KICAKICAgICAgLy8gdXNpbmcgc3RhbmRhcmQgYXNjZW5kaW5nIHNvcnQKICAgICAgdG9kb3NTb3J0aW5nID0gWyduYW1lJ107CiAgICAgIEBzb3J0KCd0b2RvcycsICd0b2Rvc1NvcnRpbmcnKSBzb3J0ZWRUb2RvczsKICAKICAgICAgLy8gdXNpbmcgZGVzY2VuZGluZyBzb3J0CiAgICAgIHRvZG9zU29ydGluZ0Rlc2MgPSBbJ25hbWU6ZGVzYyddOwogICAgICBAc29ydCgndG9kb3MnLCAndG9kb3NTb3J0aW5nRGVzYycpIHNvcnRlZFRvZG9zRGVzYzsKICAgIH0KICAKICAgIGxldCB0b2RvTGlzdCA9IG5ldyBUb0RvTGlzdChbCiAgICAgIHsgbmFtZTogJ1VuaXQgVGVzdCcsIHByaW9yaXR5OiAyIH0sCiAgICAgIHsgbmFtZTogJ0RvY3VtZW50YXRpb24nLCBwcmlvcml0eTogMyB9LAogICAgICB7IG5hbWU6ICdSZWxlYXNlJywgcHJpb3JpdHk6IDEgfQogICAgXSk7CiAgCiAgICB0b2RvTGlzdC5zb3J0ZWRUb2RvczsgLy8gW3sgbmFtZTonRG9jdW1lbnRhdGlvbicsIHByaW9yaXR5OjMgfSwgeyBuYW1lOidSZWxlYXNlJywgcHJpb3JpdHk6MSB9LCB7IG5hbWU6J1VuaXQgVGVzdCcsIHByaW9yaXR5OjIgfV0KICAgIHRvZG9MaXN0LnNvcnRlZFRvZG9zRGVzYzsgLy8gW3sgbmFtZTonVW5pdCBUZXN0JywgcHJpb3JpdHk6MiB9LCB7IG5hbWU6J1JlbGVhc2UnLCBwcmlvcml0eToxIH0sIHsgbmFtZTonRG9jdW1lbnRhdGlvbicsIHByaW9yaXR5OjMgfV0KICAgIGBgYAogIAogICAgQG1ldGhvZCBzb3J0CiAgICBAZm9yIEBlbWJlci9vYmplY3QvY29tcHV0ZWQKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7U3RyaW5nfSBpdGVtc0tleQogICAgQHBhcmFtIHtBcnJheX0gW2FkZGl0aW9uYWxEZXBlbmRlbnRLZXlzXSBvcHRpb25hbCBhcnJheSBvZiBhZGRpdGlvbmFsCiAgICBkZXBlbmRlbnQga2V5cwogICAgQHBhcmFtIHtTdHJpbmcgb3IgRnVuY3Rpb259IHNvcnREZWZpbml0aW9uIGEgZGVwZW5kZW50IGtleSB0byBhbiBhcnJheSBvZiBzb3J0CiAgICBwcm9wZXJ0aWVzIChhZGQgYDpkZXNjYCB0byB0aGUgYXJyYXlzIHNvcnQgcHJvcGVydGllcyB0byBzb3J0IGRlc2NlbmRpbmcpIG9yIGEKICAgIGZ1bmN0aW9uIHRvIHVzZSB3aGVuIHNvcnRpbmcKICAgIEByZXR1cm4ge0NvbXB1dGVkUHJvcGVydHl9IGNvbXB1dGVzIGEgbmV3IHNvcnRlZCBhcnJheSBiYXNlZCBvbiB0aGUgc29ydAogICAgcHJvcGVydHkgYXJyYXkgb3IgY2FsbGJhY2sgZnVuY3Rpb24KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gc29ydChpdGVtc0tleSwgYWRkaXRpb25hbERlcGVuZGVudEtleXMsIHNvcnREZWZpbml0aW9uKSB7CiAgICAoZmFsc2UgJiYgISghKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkgJiYgKDAsIF9kZWJ1Zy5hc3NlcnQpKCdZb3UgYXR0ZW1wdGVkIHRvIHVzZSBAc29ydCBhcyBhIGRlY29yYXRvciBkaXJlY3RseSwgYnV0IGl0IHJlcXVpcmVzIGF0bGVhc3QgYW4gYGl0ZW1zS2V5YCBwYXJhbWV0ZXInLCAhKDAsIF9tZXRhbC5pc0VsZW1lbnREZXNjcmlwdG9yKShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSkpOwoKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICB2YXIgYXJndW1lbnRzVmFsaWQgPSBmYWxzZTsKCiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyKSB7CiAgICAgICAgYXJndW1lbnRzVmFsaWQgPSB0eXBlb2YgaXRlbXNLZXkgPT09ICdzdHJpbmcnICYmICh0eXBlb2YgYWRkaXRpb25hbERlcGVuZGVudEtleXMgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBhZGRpdGlvbmFsRGVwZW5kZW50S2V5cyA9PT0gJ2Z1bmN0aW9uJyk7CiAgICAgIH0KCiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAzKSB7CiAgICAgICAgYXJndW1lbnRzVmFsaWQgPSB0eXBlb2YgaXRlbXNLZXkgPT09ICdzdHJpbmcnICYmIEFycmF5LmlzQXJyYXkoYWRkaXRpb25hbERlcGVuZGVudEtleXMpICYmIHR5cGVvZiBzb3J0RGVmaW5pdGlvbiA9PT0gJ2Z1bmN0aW9uJzsKICAgICAgfQoKICAgICAgKGZhbHNlICYmICEoYXJndW1lbnRzVmFsaWQpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnYGNvbXB1dGVkLnNvcnRgIGNhbiBlaXRoZXIgYmUgdXNlZCB3aXRoIGFuIGFycmF5IG9mIHNvcnQgcHJvcGVydGllcyBvciB3aXRoIGEgc29ydCBmdW5jdGlvbi4gSWYgdXNlZCB3aXRoIGFuIGFycmF5IG9mIHNvcnQgcHJvcGVydGllcywgaXQgbXVzdCByZWNlaXZlIGV4YWN0bHkgdHdvIGFyZ3VtZW50czogdGhlIGtleSBvZiB0aGUgYXJyYXkgdG8gc29ydCwgYW5kIHRoZSBrZXkgb2YgdGhlIGFycmF5IG9mIHNvcnQgcHJvcGVydGllcy4gSWYgdXNlZCB3aXRoIGEgc29ydCBmdW5jdGlvbiwgaXQgbWF5IHJlY2lldmUgdXAgdG8gdGhyZWUgYXJndW1lbnRzOiB0aGUga2V5IG9mIHRoZSBhcnJheSB0byBzb3J0LCBhbiBvcHRpb25hbCBhZGRpdGlvbmFsIGFycmF5IG9mIGRlcGVuZGVudCBrZXlzIGZvciB0aGUgY29tcHV0ZWQgcHJvcGVydHksIGFuZCB0aGUgc29ydCBmdW5jdGlvbi4nLCBhcmd1bWVudHNWYWxpZCkpOwogICAgfQoKICAgIGlmIChzb3J0RGVmaW5pdGlvbiA9PT0gdW5kZWZpbmVkICYmICFBcnJheS5pc0FycmF5KGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzKSkgewogICAgICBzb3J0RGVmaW5pdGlvbiA9IGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzOwogICAgICBhZGRpdGlvbmFsRGVwZW5kZW50S2V5cyA9IFtdOwogICAgfQoKICAgIGlmICh0eXBlb2Ygc29ydERlZmluaXRpb24gPT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuIGN1c3RvbVNvcnQoaXRlbXNLZXksIGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzLCBzb3J0RGVmaW5pdGlvbik7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gcHJvcGVydHlTb3J0KGl0ZW1zS2V5LCBzb3J0RGVmaW5pdGlvbik7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBjdXN0b21Tb3J0KGl0ZW1zS2V5LCBhZGRpdGlvbmFsRGVwZW5kZW50S2V5cywgY29tcGFyYXRvcikgewogICAgcmV0dXJuIGFycmF5TWFjcm8oaXRlbXNLZXksIGFkZGl0aW9uYWxEZXBlbmRlbnRLZXlzLCBmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgdmFyIF90aGlzNCA9IHRoaXM7CgogICAgICByZXR1cm4gdmFsdWUuc2xpY2UoKS5zb3J0KGZ1bmN0aW9uICh4LCB5KSB7CiAgICAgICAgcmV0dXJuIGNvbXBhcmF0b3IuY2FsbChfdGhpczQsIHgsIHkpOwogICAgICB9KTsKICAgIH0pOwogIH0gLy8gVGhpcyBvbmUgbmVlZHMgdG8gZHluYW1pY2FsbHkgc2V0IHVwIGFuZCB0ZWFyIGRvd24gb2JzZXJ2ZXJzIG9uIHRoZSBpdGVtc0tleQogIC8vIGRlcGVuZGluZyBvbiB0aGUgc29ydFByb3BlcnRpZXMKCgogIGZ1bmN0aW9uIHByb3BlcnR5U29ydChpdGVtc0tleSwgc29ydFByb3BlcnRpZXNLZXkpIHsKICAgIHZhciBhY3RpdmVPYnNlcnZlcnNNYXAgPSBuZXcgV2Vha01hcCgpOwogICAgdmFyIHNvcnRQcm9wZXJ0eURpZENoYW5nZU1hcCA9IG5ldyBXZWFrTWFwKCk7CgogICAgaWYgKHRydWUKICAgIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICAgKSB7CiAgICAgICAgdmFyIGNwID0gKDAsIF9tZXRhbC5jb21wdXRlZCkoaXRlbXNLZXkgKyAiLltdIiwgc29ydFByb3BlcnRpZXNLZXkgKyAiLltdIiwgZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgdmFyIHNvcnRQcm9wZXJ0aWVzID0gKDAsIF9tZXRhbC5nZXQpKHRoaXMsIHNvcnRQcm9wZXJ0aWVzS2V5KTsKICAgICAgICAgIChmYWxzZSAmJiAhKCgwLCBfcnVudGltZS5pc0FycmF5KShzb3J0UHJvcGVydGllcykgJiYgc29ydFByb3BlcnRpZXMuZXZlcnkoZnVuY3Rpb24gKHMpIHsKICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBzID09PSAnc3RyaW5nJzsKICAgICAgICAgIH0pKSAmJiAoMCwgX2RlYnVnLmFzc2VydCkoIlRoZSBzb3J0IGRlZmluaXRpb24gZm9yICciICsga2V5ICsgIicgb24gIiArIHRoaXMgKyAiIG11c3QgYmUgYSBmdW5jdGlvbiBvciBhbiBhcnJheSBvZiBzdHJpbmdzIiwgKDAsIF9ydW50aW1lLmlzQXJyYXkpKHNvcnRQcm9wZXJ0aWVzKSAmJiBzb3J0UHJvcGVydGllcy5ldmVyeShmdW5jdGlvbiAocykgewogICAgICAgICAgICByZXR1cm4gdHlwZW9mIHMgPT09ICdzdHJpbmcnOwogICAgICAgICAgfSkpKTsKICAgICAgICAgIHZhciBpdGVtc0tleUlzQXRUaGlzID0gaXRlbXNLZXkgPT09ICdAdGhpcyc7CiAgICAgICAgICB2YXIgbm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzID0gbm9ybWFsaXplU29ydFByb3BlcnRpZXMoc29ydFByb3BlcnRpZXMpOwogICAgICAgICAgdmFyIGl0ZW1zID0gaXRlbXNLZXlJc0F0VGhpcyA/IHRoaXMgOiAoMCwgX21ldGFsLmdldCkodGhpcywgaXRlbXNLZXkpOwoKICAgICAgICAgIGlmICghKDAsIF9ydW50aW1lLmlzQXJyYXkpKGl0ZW1zKSkgewogICAgICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKCk7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKG5vcm1hbGl6ZWRTb3J0UHJvcGVydGllcy5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgcmV0dXJuICgwLCBfcnVudGltZS5BKShpdGVtcy5zbGljZSgpKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBzb3J0QnlOb3JtYWxpemVkU29ydFByb3BlcnRpZXMoaXRlbXMsIG5vcm1hbGl6ZWRTb3J0UHJvcGVydGllcyk7CiAgICAgICAgICB9CiAgICAgICAgfSkucmVhZE9ubHkoKTsKICAgICAgICAoMCwgX21ldGFsLmRlc2NyaXB0b3JGb3JEZWNvcmF0b3IpKGNwKS5hdXRvKCk7CiAgICAgICAgcmV0dXJuIGNwOwogICAgICB9IGVsc2UgewogICAgICByZXR1cm4gKDAsIF9tZXRhbC5jb21wdXRlZCkoc29ydFByb3BlcnRpZXNLZXkgKyAiLltdIiwgZnVuY3Rpb24gKGtleSkgewogICAgICAgIHZhciBfdGhpczUgPSB0aGlzOwoKICAgICAgICB2YXIgc29ydFByb3BlcnRpZXMgPSAoMCwgX21ldGFsLmdldCkodGhpcywgc29ydFByb3BlcnRpZXNLZXkpOwogICAgICAgIChmYWxzZSAmJiAhKCgwLCBfcnVudGltZS5pc0FycmF5KShzb3J0UHJvcGVydGllcykgJiYgc29ydFByb3BlcnRpZXMuZXZlcnkoZnVuY3Rpb24gKHMpIHsKICAgICAgICAgIHJldHVybiB0eXBlb2YgcyA9PT0gJ3N0cmluZyc7CiAgICAgICAgfSkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgiVGhlIHNvcnQgZGVmaW5pdGlvbiBmb3IgJyIgKyBrZXkgKyAiJyBvbiAiICsgdGhpcyArICIgbXVzdCBiZSBhIGZ1bmN0aW9uIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MiLCAoMCwgX3J1bnRpbWUuaXNBcnJheSkoc29ydFByb3BlcnRpZXMpICYmIHNvcnRQcm9wZXJ0aWVzLmV2ZXJ5KGZ1bmN0aW9uIChzKSB7CiAgICAgICAgICByZXR1cm4gdHlwZW9mIHMgPT09ICdzdHJpbmcnOwogICAgICAgIH0pKSk7IC8vIEFkZC9yZW1vdmUgcHJvcGVydHkgb2JzZXJ2ZXJzIGFzIHJlcXVpcmVkLgoKICAgICAgICB2YXIgYWN0aXZlT2JzZXJ2ZXJzID0gYWN0aXZlT2JzZXJ2ZXJzTWFwLmdldCh0aGlzKTsKCiAgICAgICAgaWYgKCFzb3J0UHJvcGVydHlEaWRDaGFuZ2VNYXAuaGFzKHRoaXMpKSB7CiAgICAgICAgICBzb3J0UHJvcGVydHlEaWRDaGFuZ2VNYXAuc2V0KHRoaXMsIGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgKDAsIF9tZXRhbC5ub3RpZnlQcm9wZXJ0eUNoYW5nZSkodGhpcywga2V5KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgdmFyIHNvcnRQcm9wZXJ0eURpZENoYW5nZSA9IHNvcnRQcm9wZXJ0eURpZENoYW5nZU1hcC5nZXQodGhpcyk7CgogICAgICAgIGlmIChhY3RpdmVPYnNlcnZlcnMgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgYWN0aXZlT2JzZXJ2ZXJzLmZvckVhY2goZnVuY3Rpb24gKHBhdGgpIHsKICAgICAgICAgICAgcmV0dXJuICgwLCBfbWV0YWwucmVtb3ZlT2JzZXJ2ZXIpKF90aGlzNSwgcGF0aCwgc29ydFByb3BlcnR5RGlkQ2hhbmdlKTsKICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgdmFyIGl0ZW1zS2V5SXNBdFRoaXMgPSBpdGVtc0tleSA9PT0gJ0B0aGlzJzsKICAgICAgICB2YXIgbm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzID0gbm9ybWFsaXplU29ydFByb3BlcnRpZXMoc29ydFByb3BlcnRpZXMpOwoKICAgICAgICBpZiAobm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgdmFyIHBhdGggPSBpdGVtc0tleUlzQXRUaGlzID8gIltdIiA6IGl0ZW1zS2V5ICsgIi5bXSI7CiAgICAgICAgICAoMCwgX21ldGFsLmFkZE9ic2VydmVyKSh0aGlzLCBwYXRoLCBzb3J0UHJvcGVydHlEaWRDaGFuZ2UpOwogICAgICAgICAgYWN0aXZlT2JzZXJ2ZXJzID0gW3BhdGhdOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBhY3RpdmVPYnNlcnZlcnMgPSBub3JtYWxpemVkU29ydFByb3BlcnRpZXMubWFwKGZ1bmN0aW9uIChfcmVmKSB7CiAgICAgICAgICAgIHZhciBwcm9wID0gX3JlZlswXTsKICAgICAgICAgICAgdmFyIHBhdGggPSBpdGVtc0tleUlzQXRUaGlzID8gIkBlYWNoLiIgKyBwcm9wIDogaXRlbXNLZXkgKyAiLkBlYWNoLiIgKyBwcm9wOwogICAgICAgICAgICAoMCwgX21ldGFsLmFkZE9ic2VydmVyKShfdGhpczUsIHBhdGgsIHNvcnRQcm9wZXJ0eURpZENoYW5nZSk7CiAgICAgICAgICAgIHJldHVybiBwYXRoOwogICAgICAgICAgfSk7CiAgICAgICAgfQoKICAgICAgICBhY3RpdmVPYnNlcnZlcnNNYXAuc2V0KHRoaXMsIGFjdGl2ZU9ic2VydmVycyk7CiAgICAgICAgdmFyIGl0ZW1zID0gaXRlbXNLZXlJc0F0VGhpcyA/IHRoaXMgOiAoMCwgX21ldGFsLmdldCkodGhpcywgaXRlbXNLZXkpOwoKICAgICAgICBpZiAoISgwLCBfcnVudGltZS5pc0FycmF5KShpdGVtcykpIHsKICAgICAgICAgIHJldHVybiAoMCwgX3J1bnRpbWUuQSkoKTsKICAgICAgICB9CgogICAgICAgIGlmIChub3JtYWxpemVkU29ydFByb3BlcnRpZXMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKGl0ZW1zLnNsaWNlKCkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gc29ydEJ5Tm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzKGl0ZW1zLCBub3JtYWxpemVkU29ydFByb3BlcnRpZXMpOwogICAgICAgIH0KICAgICAgfSkucmVhZE9ubHkoKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIG5vcm1hbGl6ZVNvcnRQcm9wZXJ0aWVzKHNvcnRQcm9wZXJ0aWVzKSB7CiAgICByZXR1cm4gc29ydFByb3BlcnRpZXMubWFwKGZ1bmN0aW9uIChwKSB7CiAgICAgIHZhciBfcCRzcGxpdCA9IHAuc3BsaXQoJzonKSwKICAgICAgICAgIHByb3AgPSBfcCRzcGxpdFswXSwKICAgICAgICAgIGRpcmVjdGlvbiA9IF9wJHNwbGl0WzFdOwoKICAgICAgZGlyZWN0aW9uID0gZGlyZWN0aW9uIHx8ICdhc2MnOwogICAgICByZXR1cm4gW3Byb3AsIGRpcmVjdGlvbl07CiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHNvcnRCeU5vcm1hbGl6ZWRTb3J0UHJvcGVydGllcyhpdGVtcywgbm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzKSB7CiAgICByZXR1cm4gKDAsIF9ydW50aW1lLkEpKGl0ZW1zLnNsaWNlKCkuc29ydChmdW5jdGlvbiAoaXRlbUEsIGl0ZW1CKSB7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbm9ybWFsaXplZFNvcnRQcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIF9ub3JtYWxpemVkU29ydFByb3BlciA9IG5vcm1hbGl6ZWRTb3J0UHJvcGVydGllc1tpXSwKICAgICAgICAgICAgcHJvcCA9IF9ub3JtYWxpemVkU29ydFByb3BlclswXSwKICAgICAgICAgICAgZGlyZWN0aW9uID0gX25vcm1hbGl6ZWRTb3J0UHJvcGVyWzFdOwogICAgICAgIHZhciByZXN1bHQgPSAoMCwgX3J1bnRpbWUuY29tcGFyZSkoKDAsIF9tZXRhbC5nZXQpKGl0ZW1BLCBwcm9wKSwgKDAsIF9tZXRhbC5nZXQpKGl0ZW1CLCBwcm9wKSk7CgogICAgICAgIGlmIChyZXN1bHQgIT09IDApIHsKICAgICAgICAgIHJldHVybiBkaXJlY3Rpb24gPT09ICdkZXNjJyA/IC0xICogcmVzdWx0IDogcmVzdWx0OwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIDA7CiAgICB9KSk7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvcG9seWZpbGxzL2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIiwgIkBlbWJlci9wb2x5ZmlsbHMvbGliL21lcmdlIiwgIkBlbWJlci9wb2x5ZmlsbHMvbGliL2Fzc2lnbiIsICJAZW1iZXIvcG9seWZpbGxzL2xpYi93ZWFrX3NldCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9kZXByZWNhdGVkRmVhdHVyZXMsIF9tZXJnZSwgX2Fzc2lnbiwgX3dlYWtfc2V0KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJhc3NpZ24iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXNzaWduLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiYXNzaWduUG9seWZpbGwiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYXNzaWduLmFzc2lnbjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfV2Vha1NldCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF93ZWFrX3NldC5kZWZhdWx0OwogICAgfQogIH0pOwogIF9leHBvcnRzLm1lcmdlID0gdm9pZCAwOwogIHZhciBtZXJnZSA9IF9kZXByZWNhdGVkRmVhdHVyZXMuTUVSR0UgPyBfbWVyZ2UuZGVmYXVsdCA6IHVuZGVmaW5lZDsgLy8gRXhwb3J0IGBhc3NpZ25Qb2x5ZmlsbGAgZm9yIHRlc3RpbmcKCiAgX2V4cG9ydHMubWVyZ2UgPSBtZXJnZTsKfSk7CmRlZmluZSgiQGVtYmVyL3BvbHlmaWxscy9saWIvYXNzaWduIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuYXNzaWduID0gYXNzaWduOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICBAbW9kdWxlIEBlbWJlci9wb2x5ZmlsbHMKICAqLwoKICAvKioKICAgIENvcHkgcHJvcGVydGllcyBmcm9tIGEgc291cmNlIG9iamVjdCB0byBhIHRhcmdldCBvYmplY3QuIFNvdXJjZSBhcmd1bWVudHMgcmVtYWluIHVuY2hhbmdlZC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGFzc2lnbiB9IGZyb20gJ0BlbWJlci9wb2x5ZmlsbHMnOwogIAogICAgdmFyIGEgPSB7IGZpcnN0OiAnWWVodWRhJyB9OwogICAgdmFyIGIgPSB7IGxhc3Q6ICdLYXR6JyB9OwogICAgdmFyIGMgPSB7IGNvbXBhbnk6ICdPdGhlciBDb21wYW55JyB9OwogICAgdmFyIGQgPSB7IGNvbXBhbnk6ICdUaWxkZSBJbmMuJyB9OwogICAgYXNzaWduKGEsIGIsIGMsIGQpOyAvLyBhID09PSB7IGZpcnN0OiAnWWVodWRhJywgbGFzdDogJ0thdHonLCBjb21wYW55OiAnVGlsZGUgSW5jLicgfTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBhc3NpZ24KICAgIEBmb3IgQGVtYmVyL3BvbHlmaWxscwogICAgQHBhcmFtIHtPYmplY3R9IHRhcmdldCBUaGUgb2JqZWN0IHRvIGFzc2lnbiBpbnRvCiAgICBAcGFyYW0ge09iamVjdH0gLi4uYXJncyBUaGUgb2JqZWN0cyB0byBjb3B5IHByb3BlcnRpZXMgZnJvbQogICAgQHJldHVybiB7T2JqZWN0fQogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICovCiAgZnVuY3Rpb24gYXNzaWduKHRhcmdldCkgewogICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGFyZyA9IGFyZ3VtZW50c1tpXTsKCiAgICAgIGlmICghYXJnKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIHZhciB1cGRhdGVzID0gT2JqZWN0LmtleXMoYXJnKTsKCiAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCB1cGRhdGVzLmxlbmd0aDsgX2krKykgewogICAgICAgIHZhciBwcm9wID0gdXBkYXRlc1tfaV07CiAgICAgICAgdGFyZ2V0W3Byb3BdID0gYXJnW3Byb3BdOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHRhcmdldDsKICB9IC8vIE5vdGU6IFdlIHVzZSB0aGUgYnJhY2tldCBub3RhdGlvbiBzbwogIC8vICAgICAgIHRoYXQgdGhlIGJhYmVsIHBsdWdpbiBkb2VzIG5vdAogIC8vICAgICAgIHRyYW5zZm9ybSBpdC4KICAvLyBodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9iYWJlbC1wbHVnaW4tdHJhbnNmb3JtLW9iamVjdC1hc3NpZ24KCgogIHZhciBfYXNzaWduID0gT2JqZWN0LmFzc2lnbjsKCiAgdmFyIF9kZWZhdWx0ID0gX2Fzc2lnbiB8fCBhc3NpZ247CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiQGVtYmVyL3BvbHlmaWxscy9saWIvbWVyZ2UiLCBbImV4cG9ydHMiLCAiQGVtYmVyL2RlYnVnIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlYnVnKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gbWVyZ2U7CgogIC8qKgogICAgTWVyZ2UgdGhlIGNvbnRlbnRzIG9mIHR3byBvYmplY3RzIHRvZ2V0aGVyIGludG8gdGhlIGZpcnN0IG9iamVjdC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IG1lcmdlIH0gZnJvbSAnQGVtYmVyL3BvbHlmaWxscyc7CiAgCiAgICBtZXJnZSh7IGZpcnN0OiAnVG9tJyB9LCB7IGxhc3Q6ICdEYWxlJyB9KTsgLy8geyBmaXJzdDogJ1RvbScsIGxhc3Q6ICdEYWxlJyB9CiAgICB2YXIgYSA9IHsgZmlyc3Q6ICdZZWh1ZGEnIH07CiAgICB2YXIgYiA9IHsgbGFzdDogJ0thdHonIH07CiAgICBtZXJnZShhLCBiKTsgLy8gYSA9PSB7IGZpcnN0OiAnWWVodWRhJywgbGFzdDogJ0thdHonIH0sIGIgPT0geyBsYXN0OiAnS2F0eicgfQogICAgYGBgCiAgCiAgICBAbWV0aG9kIG1lcmdlCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9wb2x5ZmlsbHMKICAgIEBwYXJhbSB7T2JqZWN0fSBvcmlnaW5hbCBUaGUgb2JqZWN0IHRvIG1lcmdlIGludG8KICAgIEBwYXJhbSB7T2JqZWN0fSB1cGRhdGVzIFRoZSBvYmplY3QgdG8gY29weSBwcm9wZXJ0aWVzIGZyb20KICAgIEByZXR1cm4ge09iamVjdH0KICAgIEBkZXByZWNhdGVkCiAgICBAcHVibGljCiAgKi8KICBmdW5jdGlvbiBtZXJnZShvcmlnaW5hbCwgdXBkYXRlcykgewogICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBfZGVidWcuZGVwcmVjYXRlKSgnVXNlIG9mIGBtZXJnZWAgaGFzIGJlZW4gZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBgYXNzaWduYCBpbnN0ZWFkLicsIGZhbHNlLCB7CiAgICAgIGlkOiAnZW1iZXItcG9seWZpbGxzLmRlcHJlY2F0ZS1tZXJnZScsCiAgICAgIHVudGlsOiAnNC4wLjAnLAogICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54LyN0b2NfZW1iZXItcG9seWZpbGxzLWRlcHJlY2F0ZS1tZXJnZScKICAgIH0pKTsKCiAgICBpZiAodXBkYXRlcyA9PT0gbnVsbCB8fCB0eXBlb2YgdXBkYXRlcyAhPT0gJ29iamVjdCcpIHsKICAgICAgcmV0dXJuIG9yaWdpbmFsOwogICAgfQoKICAgIHZhciBwcm9wcyA9IE9iamVjdC5rZXlzKHVwZGF0ZXMpOwogICAgdmFyIHByb3A7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgewogICAgICBwcm9wID0gcHJvcHNbaV07CiAgICAgIG9yaWdpbmFsW3Byb3BdID0gdXBkYXRlc1twcm9wXTsKICAgIH0KCiAgICByZXR1cm4gb3JpZ2luYWw7CiAgfQp9KTsKZGVmaW5lKCJAZW1iZXIvcG9seWZpbGxzL2xpYi93ZWFrX3NldCIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qIGdsb2JhbHMgV2Vha1NldCAqLwogIHZhciBfZGVmYXVsdCA9IHR5cGVvZiBXZWFrU2V0ID09PSAnZnVuY3Rpb24nID8gV2Vha1NldCA6CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFdlYWtTZXRQb2x5RmlsbCgpIHsKICAgICAgdGhpcy5fbWFwID0gbmV3IFdlYWtNYXAoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gV2Vha1NldFBvbHlGaWxsLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uYWRkID0gZnVuY3Rpb24gYWRkKHZhbCkgewogICAgICB0aGlzLl9tYXAuc2V0KHZhbCwgdHJ1ZSk7CgogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgX3Byb3RvLmRlbGV0ZSA9IGZ1bmN0aW9uIF9kZWxldGUodmFsKSB7CiAgICAgIHJldHVybiB0aGlzLl9tYXAuZGVsZXRlKHZhbCk7CiAgICB9OwoKICAgIF9wcm90by5oYXMgPSBmdW5jdGlvbiBoYXModmFsKSB7CiAgICAgIHJldHVybiB0aGlzLl9tYXAuaGFzKHZhbCk7CiAgICB9OwoKICAgIHJldHVybiBXZWFrU2V0UG9seUZpbGw7CiAgfSgpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci9ydW5sb29wL2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci9kZWJ1ZyIsICJAZW1iZXIvLWludGVybmFscy9lcnJvci1oYW5kbGluZyIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCIsICJiYWNrYnVybmVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2RlYnVnLCBfZXJyb3JIYW5kbGluZywgX21ldGFsLCBfYmFja2J1cm5lcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZ2V0Q3VycmVudFJ1bkxvb3AgPSBnZXRDdXJyZW50UnVuTG9vcDsKICBfZXhwb3J0cy5ydW4gPSBydW47CiAgX2V4cG9ydHMuam9pbiA9IGpvaW47CiAgX2V4cG9ydHMuYmVnaW4gPSBiZWdpbjsKICBfZXhwb3J0cy5lbmQgPSBlbmQ7CiAgX2V4cG9ydHMuc2NoZWR1bGUgPSBzY2hlZHVsZTsKICBfZXhwb3J0cy5oYXNTY2hlZHVsZWRUaW1lcnMgPSBoYXNTY2hlZHVsZWRUaW1lcnM7CiAgX2V4cG9ydHMuY2FuY2VsVGltZXJzID0gY2FuY2VsVGltZXJzOwogIF9leHBvcnRzLmxhdGVyID0gbGF0ZXI7CiAgX2V4cG9ydHMub25jZSA9IG9uY2U7CiAgX2V4cG9ydHMuc2NoZWR1bGVPbmNlID0gc2NoZWR1bGVPbmNlOwogIF9leHBvcnRzLm5leHQgPSBuZXh0OwogIF9leHBvcnRzLmNhbmNlbCA9IGNhbmNlbDsKICBfZXhwb3J0cy5kZWJvdW5jZSA9IGRlYm91bmNlOwogIF9leHBvcnRzLnRocm90dGxlID0gdGhyb3R0bGU7CiAgX2V4cG9ydHMuYmluZCA9IF9leHBvcnRzLl9nbG9iYWxzUnVuID0gX2V4cG9ydHMuYmFja2J1cm5lciA9IF9leHBvcnRzLnF1ZXVlcyA9IF9leHBvcnRzLl9yc3ZwRXJyb3JRdWV1ZSA9IHZvaWQgMDsKICB2YXIgY3VycmVudFJ1bkxvb3AgPSBudWxsOwoKICBmdW5jdGlvbiBnZXRDdXJyZW50UnVuTG9vcCgpIHsKICAgIHJldHVybiBjdXJyZW50UnVuTG9vcDsKICB9CgogIGZ1bmN0aW9uIG9uQmVnaW4oY3VycmVudCkgewogICAgY3VycmVudFJ1bkxvb3AgPSBjdXJyZW50OwogIH0KCiAgZnVuY3Rpb24gb25FbmQoY3VycmVudCwgbmV4dCkgewogICAgY3VycmVudFJ1bkxvb3AgPSBuZXh0OwoKICAgIGlmICh0cnVlCiAgICAvKiBFTUJFUl9NRVRBTF9UUkFDS0VEX1BST1BFUlRJRVMgKi8KICAgICkgewogICAgICAgICgwLCBfbWV0YWwuZmx1c2hBc3luY09ic2VydmVycykoKTsKICAgICAgfQogIH0KCiAgdmFyIGZsdXNoOwoKICBpZiAodHJ1ZQogIC8qIEVNQkVSX01FVEFMX1RSQUNLRURfUFJPUEVSVElFUyAqLwogICkgewogICAgICBmbHVzaCA9IGZ1bmN0aW9uIGZsdXNoKHF1ZXVlTmFtZSwgbmV4dCkgewogICAgICAgIGlmIChxdWV1ZU5hbWUgPT09ICdyZW5kZXInIHx8IHF1ZXVlTmFtZSA9PT0gX3JzdnBFcnJvclF1ZXVlKSB7CiAgICAgICAgICAoMCwgX21ldGFsLmZsdXNoQXN5bmNPYnNlcnZlcnMpKCk7CiAgICAgICAgfQoKICAgICAgICBuZXh0KCk7CiAgICAgIH07CiAgICB9CgogIHZhciBfcnN2cEVycm9yUXVldWUgPSAoIiIgKyBNYXRoLnJhbmRvbSgpICsgRGF0ZS5ub3coKSkucmVwbGFjZSgnLicsICcnKTsKICAvKioKICAgIEFycmF5IG9mIG5hbWVkIHF1ZXVlcy4gVGhpcyBhcnJheSBkZXRlcm1pbmVzIHRoZSBvcmRlciBpbiB3aGljaCBxdWV1ZXMKICAgIGFyZSBmbHVzaGVkIGF0IHRoZSBlbmQgb2YgdGhlIFJ1bkxvb3AuIFlvdSBjYW4gZGVmaW5lIHlvdXIgb3duIHF1ZXVlcyBieQogICAgc2ltcGx5IGFkZGluZyB0aGUgcXVldWUgbmFtZSB0byB0aGlzIGFycmF5LiBOb3JtYWxseSB5b3Ugc2hvdWxkIG5vdCBuZWVkCiAgICB0byBpbnNwZWN0IG9yIG1vZGlmeSB0aGlzIHByb3BlcnR5LgogIAogICAgQHByb3BlcnR5IHF1ZXVlcwogICAgQHR5cGUgQXJyYXkKICAgIEBkZWZhdWx0IFsnYWN0aW9ucycsICdkZXN0cm95J10KICAgIEBwcml2YXRlCiAgKi8KCgogIF9leHBvcnRzLl9yc3ZwRXJyb3JRdWV1ZSA9IF9yc3ZwRXJyb3JRdWV1ZTsKICB2YXIgcXVldWVzID0gWydhY3Rpb25zJywgLy8gdXNlZCBpbiByb3V0ZXIgdHJhbnNpdGlvbnMgdG8gcHJldmVudCB1bm5lY2Vzc2FyeSBsb2FkaW5nIHN0YXRlIGVudHJ5CiAgLy8gaWYgYWxsIGNvbnRleHQgcHJvbWlzZXMgcmVzb2x2ZSBvbiB0aGUgJ2FjdGlvbnMnIHF1ZXVlIGZpcnN0CiAgJ3JvdXRlclRyYW5zaXRpb25zJywgJ3JlbmRlcicsICdhZnRlclJlbmRlcicsICdkZXN0cm95JywgLy8gdXNlZCB0byByZS10aHJvdyB1bmhhbmRsZWQgUlNWUCByZWplY3Rpb24gZXJyb3JzIHNwZWNpZmljYWxseSBpbiB0aGlzCiAgLy8gcG9zaXRpb24gdG8gYXZvaWQgYnJlYWtpbmcgYW55dGhpbmcgcmVuZGVyZWQgaW4gdGhlIG90aGVyIHNlY3Rpb25zCiAgX3JzdnBFcnJvclF1ZXVlXTsKICBfZXhwb3J0cy5xdWV1ZXMgPSBxdWV1ZXM7CiAgdmFyIGJhY2tidXJuZXIgPSBuZXcgX2JhY2tidXJuZXIuZGVmYXVsdChxdWV1ZXMsIHsKICAgIGRlZmF1bHRRdWV1ZTogJ2FjdGlvbnMnLAogICAgb25CZWdpbjogb25CZWdpbiwKICAgIG9uRW5kOiBvbkVuZCwKICAgIG9uRXJyb3JUYXJnZXQ6IF9lcnJvckhhbmRsaW5nLm9uRXJyb3JUYXJnZXQsCiAgICBvbkVycm9yTWV0aG9kOiAnb25lcnJvcicsCiAgICBmbHVzaDogZmx1c2gKICB9KTsKICAvKioKICAgQG1vZHVsZSBAZW1iZXIvcnVubG9vcAogICovCiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogIC8vIHJ1biAtIHRoaXMgaXMgaWRlYWxseSB0aGUgb25seSBwdWJsaWMgQVBJIHRoZSBkZXYgc2VlcwogIC8vCgogIC8qKgogICAgUnVucyB0aGUgcGFzc2VkIHRhcmdldCBhbmQgbWV0aG9kIGluc2lkZSBvZiBhIFJ1bkxvb3AsIGVuc3VyaW5nIGFueQogICAgZGVmZXJyZWQgYWN0aW9ucyBpbmNsdWRpbmcgYmluZGluZ3MgYW5kIHZpZXdzIHVwZGF0ZXMgYXJlIGZsdXNoZWQgYXQgdGhlCiAgICBlbmQuCiAgCiAgICBOb3JtYWxseSB5b3Ugc2hvdWxkIG5vdCBuZWVkIHRvIGludm9rZSB0aGlzIG1ldGhvZCB5b3Vyc2VsZi4gSG93ZXZlciBpZgogICAgeW91IGFyZSBpbXBsZW1lbnRpbmcgcmF3IGV2ZW50IGhhbmRsZXJzIHdoZW4gaW50ZXJmYWNpbmcgd2l0aCBvdGhlcgogICAgbGlicmFyaWVzIG9yIHBsdWdpbnMsIHlvdSBzaG91bGQgcHJvYmFibHkgd3JhcCBhbGwgb2YgeW91ciBjb2RlIGluc2lkZSB0aGlzCiAgICBjYWxsLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgcnVuIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogIAogICAgcnVuKGZ1bmN0aW9uKCkgewogICAgICAvLyBjb2RlIHRvIGJlIGV4ZWN1dGVkIHdpdGhpbiBhIFJ1bkxvb3AKICAgIH0pOwogICAgYGBgCiAgICBAbWV0aG9kIHJ1bgogICAgQGZvciBAZW1iZXIvcnVubG9vcAogICAgQHN0YXRpYwogICAgQHBhcmFtIHtPYmplY3R9IFt0YXJnZXRdIHRhcmdldCBvZiBtZXRob2QgdG8gY2FsbAogICAgQHBhcmFtIHtGdW5jdGlvbnxTdHJpbmd9IG1ldGhvZCBNZXRob2QgdG8gaW52b2tlLgogICAgICBNYXkgYmUgYSBmdW5jdGlvbiBvciBhIHN0cmluZy4gSWYgeW91IHBhc3MgYSBzdHJpbmcKICAgICAgdGhlbiBpdCB3aWxsIGJlIGxvb2tlZCB1cCBvbiB0aGUgcGFzc2VkIHRhcmdldC4KICAgIEBwYXJhbSB7T2JqZWN0fSBbYXJncypdIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyB5b3Ugd2lzaCB0byBwYXNzIHRvIHRoZSBtZXRob2QuCiAgICBAcmV0dXJuIHtPYmplY3R9IHJldHVybiB2YWx1ZSBmcm9tIGludm9raW5nIHRoZSBwYXNzZWQgZnVuY3Rpb24uCiAgICBAcHVibGljCiAgKi8KCiAgX2V4cG9ydHMuYmFja2J1cm5lciA9IGJhY2tidXJuZXI7CgogIGZ1bmN0aW9uIHJ1bigpIHsKICAgIHJldHVybiBiYWNrYnVybmVyLnJ1bi5hcHBseShiYWNrYnVybmVyLCBhcmd1bWVudHMpOwogIH0gLy8gdXNlZCBmb3IgdGhlIEVtYmVyLnJ1biBnbG9iYWwgb25seQoKCiAgdmFyIF9nbG9iYWxzUnVuID0gcnVuLmJpbmQobnVsbCk7CiAgLyoqCiAgICBJZiBubyBydW4tbG9vcCBpcyBwcmVzZW50LCBpdCBjcmVhdGVzIGEgbmV3IG9uZS4gSWYgYSBydW4gbG9vcCBpcwogICAgcHJlc2VudCBpdCB3aWxsIHF1ZXVlIGl0c2VsZiB0byBydW4gb24gdGhlIGV4aXN0aW5nIHJ1bi1sb29wcyBhY3Rpb24KICAgIHF1ZXVlLgogIAogICAgUGxlYXNlIG5vdGU6IFRoaXMgaXMgbm90IGZvciBub3JtYWwgdXNhZ2UsIGFuZCBzaG91bGQgYmUgdXNlZCBzcGFyaW5nbHkuCiAgCiAgICBJZiBpbnZva2VkIHdoZW4gbm90IHdpdGhpbiBhIHJ1biBsb29wOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgam9pbiB9IGZyb20gJ0BlbWJlci9ydW5sb29wJzsKICAKICAgIGpvaW4oZnVuY3Rpb24oKSB7CiAgICAgIC8vIGNyZWF0ZXMgYSBuZXcgcnVuLWxvb3AKICAgIH0pOwogICAgYGBgCiAgCiAgICBBbHRlcm5hdGl2ZWx5LCBpZiBjYWxsZWQgd2l0aGluIGFuIGV4aXN0aW5nIHJ1biBsb29wOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgcnVuLCBqb2luIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogIAogICAgcnVuKGZ1bmN0aW9uKCkgewogICAgICAvLyBjcmVhdGVzIGEgbmV3IHJ1bi1sb29wCiAgCiAgICAgIGpvaW4oZnVuY3Rpb24oKSB7CiAgICAgICAgLy8gam9pbnMgd2l0aCB0aGUgZXhpc3RpbmcgcnVuLWxvb3AsIGFuZCBxdWV1ZXMgZm9yIGludm9jYXRpb24gb24KICAgICAgICAvLyB0aGUgZXhpc3RpbmcgcnVuLWxvb3BzIGFjdGlvbiBxdWV1ZS4KICAgICAgfSk7CiAgICB9KTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBqb2luCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9ydW5sb29wCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gdGFyZ2V0IG9mIG1ldGhvZCB0byBjYWxsCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIE1ldGhvZCB0byBpbnZva2UuCiAgICAgIE1heSBiZSBhIGZ1bmN0aW9uIG9yIGEgc3RyaW5nLiBJZiB5b3UgcGFzcyBhIHN0cmluZwogICAgICB0aGVuIGl0IHdpbGwgYmUgbG9va2VkIHVwIG9uIHRoZSBwYXNzZWQgdGFyZ2V0LgogICAgQHBhcmFtIHtPYmplY3R9IFthcmdzKl0gQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIHlvdSB3aXNoIHRvIHBhc3MgdG8gdGhlIG1ldGhvZC4KICAgIEByZXR1cm4ge09iamVjdH0gUmV0dXJuIHZhbHVlIGZyb20gaW52b2tpbmcgdGhlIHBhc3NlZCBmdW5jdGlvbi4gUGxlYXNlIG5vdGUsCiAgICB3aGVuIGNhbGxlZCB3aXRoaW4gYW4gZXhpc3RpbmcgbG9vcCwgbm8gcmV0dXJuIHZhbHVlIGlzIHBvc3NpYmxlLgogICAgQHB1YmxpYwogICovCgoKICBfZXhwb3J0cy5fZ2xvYmFsc1J1biA9IF9nbG9iYWxzUnVuOwoKICBmdW5jdGlvbiBqb2luKCkgewogICAgcmV0dXJuIGJhY2tidXJuZXIuam9pbi5hcHBseShiYWNrYnVybmVyLCBhcmd1bWVudHMpOwogIH0KICAvKioKICAgIEFsbG93cyB5b3UgdG8gc3BlY2lmeSB3aGljaCBjb250ZXh0IHRvIGNhbGwgdGhlIHNwZWNpZmllZCBmdW5jdGlvbiBpbiB3aGlsZQogICAgYWRkaW5nIHRoZSBleGVjdXRpb24gb2YgdGhhdCBmdW5jdGlvbiB0byB0aGUgRW1iZXIgcnVuIGxvb3AuIFRoaXMgYWJpbGl0eQogICAgbWFrZXMgdGhpcyBtZXRob2QgYSBncmVhdCB3YXkgdG8gYXN5bmNocm9ub3VzbHkgaW50ZWdyYXRlIHRoaXJkLXBhcnR5IGxpYnJhcmllcwogICAgaW50byB5b3VyIEVtYmVyIGFwcGxpY2F0aW9uLgogIAogICAgYGJpbmRgIHRha2VzIHR3byBtYWluIGFyZ3VtZW50cywgdGhlIGRlc2lyZWQgY29udGV4dCBhbmQgdGhlIGZ1bmN0aW9uIHRvCiAgICBpbnZva2UgaW4gdGhhdCBjb250ZXh0LiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgd2lsbCBiZSBzdXBwbGllZCBhcyBhcmd1bWVudHMKICAgIHRvIHRoZSBmdW5jdGlvbiB0aGF0IGlzIHBhc3NlZCBpbi4KICAKICAgIExldCdzIHVzZSB0aGUgY3JlYXRpb24gb2YgYSBUaW55TUNFIGNvbXBvbmVudCBhcyBhbiBleGFtcGxlLiBDdXJyZW50bHksCiAgICBUaW55TUNFIHByb3ZpZGVzIGEgc2V0dXAgY29uZmlndXJhdGlvbiBvcHRpb24gd2UgY2FuIHVzZSB0byBkbyBzb21lIHByb2Nlc3NpbmcKICAgIGFmdGVyIHRoZSBUaW55TUNFIGluc3RhbmNlIGlzIGluaXRpYWxpemVkIGJ1dCBiZWZvcmUgaXQgaXMgYWN0dWFsbHkgcmVuZGVyZWQuCiAgICBXZSBjYW4gdXNlIHRoYXQgc2V0dXAgb3B0aW9uIHRvIGRvIHNvbWUgYWRkaXRpb25hbCBzZXR1cCBmb3Igb3VyIGNvbXBvbmVudC4KICAgIFRoZSBjb21wb25lbnQgaXRzZWxmIGNvdWxkIGxvb2sgc29tZXRoaW5nIGxpa2UgdGhlIGZvbGxvd2luZzoKICAKICAgIGBgYGFwcC9jb21wb25lbnRzL3JpY2gtdGV4dC1lZGl0b3IuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBvbiB9IGZyb20gJ0BlbWJlci9vYmplY3QvZXZlbnRlZCc7CiAgICBpbXBvcnQgeyBiaW5kIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGluaXRpYWxpemVUaW55TUNFOiBvbignZGlkSW5zZXJ0RWxlbWVudCcsIGZ1bmN0aW9uKCkgewogICAgICAgIHRpbnltY2UuaW5pdCh7CiAgICAgICAgICBzZWxlY3RvcjogJyMnICsgdGhpcy4kKCkucHJvcCgnaWQnKSwKICAgICAgICAgIHNldHVwOiBiaW5kKHRoaXMsIHRoaXMuc2V0dXBFZGl0b3IpCiAgICAgICAgfSk7CiAgICAgIH0pLAogIAogICAgICBkaWRJbnNlcnRFbGVtZW50KCkgewogICAgICAgIHRpbnltY2UuaW5pdCh7CiAgICAgICAgICBzZWxlY3RvcjogJyMnICsgdGhpcy4kKCkucHJvcCgnaWQnKSwKICAgICAgICAgIHNldHVwOiBiaW5kKHRoaXMsIHRoaXMuc2V0dXBFZGl0b3IpCiAgICAgICAgfSk7CiAgICAgIH0KICAKICAgICAgc2V0dXBFZGl0b3IoZWRpdG9yKSB7CiAgICAgICAgdGhpcy5zZXQoJ2VkaXRvcicsIGVkaXRvcik7CiAgCiAgICAgICAgZWRpdG9yLm9uKCdjaGFuZ2UnLCBmdW5jdGlvbigpIHsKICAgICAgICAgIGNvbnNvbGUubG9nKCdjb250ZW50IGNoYW5nZWQhJyk7CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBJbiB0aGlzIGV4YW1wbGUsIHdlIHVzZSBgYmluZGAgdG8gYmluZCB0aGUgc2V0dXBFZGl0b3IgbWV0aG9kIHRvIHRoZQogICAgY29udGV4dCBvZiB0aGUgUmljaFRleHRFZGl0b3IgY29tcG9uZW50IGFuZCB0byBoYXZlIHRoZSBpbnZvY2F0aW9uIG9mIHRoYXQKICAgIG1ldGhvZCBiZSBzYWZlbHkgaGFuZGxlZCBhbmQgZXhlY3V0ZWQgYnkgdGhlIEVtYmVyIHJ1biBsb29wLgogIAogICAgQG1ldGhvZCBiaW5kCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9ydW5sb29wCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gdGFyZ2V0IG9mIG1ldGhvZCB0byBjYWxsCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIE1ldGhvZCB0byBpbnZva2UuCiAgICAgIE1heSBiZSBhIGZ1bmN0aW9uIG9yIGEgc3RyaW5nLiBJZiB5b3UgcGFzcyBhIHN0cmluZwogICAgICB0aGVuIGl0IHdpbGwgYmUgbG9va2VkIHVwIG9uIHRoZSBwYXNzZWQgdGFyZ2V0LgogICAgQHBhcmFtIHtPYmplY3R9IFthcmdzKl0gQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIHlvdSB3aXNoIHRvIHBhc3MgdG8gdGhlIG1ldGhvZC4KICAgIEByZXR1cm4ge0Z1bmN0aW9ufSByZXR1cm5zIGEgbmV3IGZ1bmN0aW9uIHRoYXQgd2lsbCBhbHdheXMgaGF2ZSBhIHBhcnRpY3VsYXIgY29udGV4dAogICAgQHNpbmNlIDEuNC4wCiAgICBAcHVibGljCiAgKi8KCgogIHZhciBiaW5kID0gZnVuY3Rpb24gYmluZCgpIHsKICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBjdXJyaWVkID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICBjdXJyaWVkW19rZXldID0gYXJndW1lbnRzW19rZXldOwogICAgfQoKICAgIChmYWxzZSAmJiAhKGZ1bmN0aW9uIChtZXRob2RPclRhcmdldCwgbWV0aG9kT3JBcmcpIHsKICAgICAgLy8gQXBwbGllcyB0aGUgc2FtZSBsb2dpYyBhcyBiYWNrYnVybmVyIHBhcnNlQXJncyBmb3IgZGV0ZWN0aW5nIGlmIGEgbWV0aG9kCiAgICAgIC8vIGlzIGFjdHVhbGx5IGJlaW5nIHBhc3NlZC4KICAgICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7CgogICAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gMSkgewogICAgICAgIHJldHVybiB0eXBlb2YgbWV0aG9kT3JUYXJnZXQgPT09ICdmdW5jdGlvbic7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgbWV0aG9kT3JBcmc7CiAgICAgICAgcmV0dXJuIHR5cGUgPT09ICdmdW5jdGlvbicgfHwgLy8gc2Vjb25kIGFyZ3VtZW50IGlzIGEgZnVuY3Rpb24KICAgICAgICBtZXRob2RPclRhcmdldCAhPT0gbnVsbCAmJiB0eXBlID09PSAnc3RyaW5nJyAmJiBtZXRob2RPckFyZyBpbiBtZXRob2RPclRhcmdldCB8fCAvLyBzZWNvbmQgYXJndW1lbnQgaXMgdGhlIG5hbWUgb2YgYSBtZXRob2QgaW4gZmlyc3QgYXJndW1lbnQKICAgICAgICB0eXBlb2YgbWV0aG9kT3JUYXJnZXQgPT09ICdmdW5jdGlvbicgLy9maXJzdCBhcmd1bWVudCBpcyBhIGZ1bmN0aW9uCiAgICAgICAgOwogICAgICB9CiAgICB9LmFwcGx5KHZvaWQgMCwgY3VycmllZCkpICYmICgwLCBfZGVidWcuYXNzZXJ0KSgnY291bGQgbm90IGZpbmQgYSBzdWl0YWJsZSBtZXRob2QgdG8gYmluZCcsIGZ1bmN0aW9uIChtZXRob2RPclRhcmdldCwgbWV0aG9kT3JBcmcpIHsKICAgICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7CgogICAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gMSkgewogICAgICAgIHJldHVybiB0eXBlb2YgbWV0aG9kT3JUYXJnZXQgPT09ICdmdW5jdGlvbic7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgbWV0aG9kT3JBcmc7CiAgICAgICAgcmV0dXJuIHR5cGUgPT09ICdmdW5jdGlvbicgfHwgbWV0aG9kT3JUYXJnZXQgIT09IG51bGwgJiYgdHlwZSA9PT0gJ3N0cmluZycgJiYgbWV0aG9kT3JBcmcgaW4gbWV0aG9kT3JUYXJnZXQgfHwgdHlwZW9mIG1ldGhvZE9yVGFyZ2V0ID09PSAnZnVuY3Rpb24nOwogICAgICB9CiAgICB9LmFwcGx5KHZvaWQgMCwgY3VycmllZCkpKTsKICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgIGZvciAodmFyIF9sZW4yID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuMiksIF9rZXkyID0gMDsgX2tleTIgPCBfbGVuMjsgX2tleTIrKykgewogICAgICAgIGFyZ3NbX2tleTJdID0gYXJndW1lbnRzW19rZXkyXTsKICAgICAgfQoKICAgICAgcmV0dXJuIGpvaW4uYXBwbHkodm9pZCAwLCBjdXJyaWVkLmNvbmNhdChhcmdzKSk7CiAgICB9OwogIH07CiAgLyoqCiAgICBCZWdpbnMgYSBuZXcgUnVuTG9vcC4gQW55IGRlZmVycmVkIGFjdGlvbnMgaW52b2tlZCBhZnRlciB0aGUgYmVnaW4gd2lsbAogICAgYmUgYnVmZmVyZWQgdW50aWwgeW91IGludm9rZSBhIG1hdGNoaW5nIGNhbGwgdG8gYGVuZCgpYC4gVGhpcyBpcwogICAgYSBsb3dlci1sZXZlbCB3YXkgdG8gdXNlIGEgUnVuTG9vcCBpbnN0ZWFkIG9mIHVzaW5nIGBydW4oKWAuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBiZWdpbiwgZW5kIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogIAogICAgYmVnaW4oKTsKICAgIC8vIGNvZGUgdG8gYmUgZXhlY3V0ZWQgd2l0aGluIGEgUnVuTG9vcAogICAgZW5kKCk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgYmVnaW4KICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL3J1bmxvb3AKICAgIEByZXR1cm4ge3ZvaWR9CiAgICBAcHVibGljCiAgKi8KCgogIF9leHBvcnRzLmJpbmQgPSBiaW5kOwoKICBmdW5jdGlvbiBiZWdpbigpIHsKICAgIGJhY2tidXJuZXIuYmVnaW4oKTsKICB9CiAgLyoqCiAgICBFbmRzIGEgUnVuTG9vcC4gVGhpcyBtdXN0IGJlIGNhbGxlZCBzb21ldGltZSBhZnRlciB5b3UgY2FsbAogICAgYGJlZ2luKClgIHRvIGZsdXNoIGFueSBkZWZlcnJlZCBhY3Rpb25zLiBUaGlzIGlzIGEgbG93ZXItbGV2ZWwgd2F5CiAgICB0byB1c2UgYSBSdW5Mb29wIGluc3RlYWQgb2YgdXNpbmcgYHJ1bigpYC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGJlZ2luLCBlbmQgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBiZWdpbigpOwogICAgLy8gY29kZSB0byBiZSBleGVjdXRlZCB3aXRoaW4gYSBSdW5Mb29wCiAgICBlbmQoKTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBlbmQKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL3J1bmxvb3AKICAgIEByZXR1cm4ge3ZvaWR9CiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGVuZCgpIHsKICAgIGJhY2tidXJuZXIuZW5kKCk7CiAgfQogIC8qKgogICAgQWRkcyB0aGUgcGFzc2VkIHRhcmdldC9tZXRob2QgYW5kIGFueSBvcHRpb25hbCBhcmd1bWVudHMgdG8gdGhlIG5hbWVkCiAgICBxdWV1ZSB0byBiZSBleGVjdXRlZCBhdCB0aGUgZW5kIG9mIHRoZSBSdW5Mb29wLiBJZiB5b3UgaGF2ZSBub3QgYWxyZWFkeQogICAgc3RhcnRlZCBhIFJ1bkxvb3Agd2hlbiBjYWxsaW5nIHRoaXMgbWV0aG9kIG9uZSB3aWxsIGJlIHN0YXJ0ZWQgZm9yIHlvdQogICAgYXV0b21hdGljYWxseS4KICAKICAgIEF0IHRoZSBlbmQgb2YgYSBSdW5Mb29wLCBhbnkgbWV0aG9kcyBzY2hlZHVsZWQgaW4gdGhpcyB3YXkgd2lsbCBiZSBpbnZva2VkLgogICAgTWV0aG9kcyB3aWxsIGJlIGludm9rZWQgaW4gYW4gb3JkZXIgbWF0Y2hpbmcgdGhlIG5hbWVkIHF1ZXVlcyBkZWZpbmVkIGluCiAgICB0aGUgYHF1ZXVlc2AgcHJvcGVydHkuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBzY2hlZHVsZSB9IGZyb20gJ0BlbWJlci9ydW5sb29wJzsKICAKICAgIHNjaGVkdWxlKCdhZnRlclJlbmRlcicsIHRoaXMsIGZ1bmN0aW9uKCkgewogICAgICAvLyB0aGlzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlICdhZnRlclJlbmRlcicgcXVldWUKICAgICAgY29uc29sZS5sb2coJ3NjaGVkdWxlZCBvbiBhZnRlclJlbmRlciBxdWV1ZScpOwogICAgfSk7CiAgCiAgICBzY2hlZHVsZSgnYWN0aW9ucycsIHRoaXMsIGZ1bmN0aW9uKCkgewogICAgICAvLyB0aGlzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlICdhY3Rpb25zJyBxdWV1ZQogICAgICBjb25zb2xlLmxvZygnc2NoZWR1bGVkIG9uIGFjdGlvbnMgcXVldWUnKTsKICAgIH0pOwogIAogICAgLy8gTm90ZSB0aGUgZnVuY3Rpb25zIHdpbGwgYmUgcnVuIGluIG9yZGVyIGJhc2VkIG9uIHRoZSBydW4gcXVldWVzIG9yZGVyLgogICAgLy8gT3V0cHV0IHdvdWxkIGJlOgogICAgLy8gICBzY2hlZHVsZWQgb24gYWN0aW9ucyBxdWV1ZQogICAgLy8gICBzY2hlZHVsZWQgb24gYWZ0ZXJSZW5kZXIgcXVldWUKICAgIGBgYAogIAogICAgQG1ldGhvZCBzY2hlZHVsZQogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvcnVubG9vcAogICAgQHBhcmFtIHtTdHJpbmd9IHF1ZXVlIFRoZSBuYW1lIG9mIHRoZSBxdWV1ZSB0byBzY2hlZHVsZSBhZ2FpbnN0LiBEZWZhdWx0IHF1ZXVlcyBpcyAnYWN0aW9ucycKICAgIEBwYXJhbSB7T2JqZWN0fSBbdGFyZ2V0XSB0YXJnZXQgb2JqZWN0IHRvIHVzZSBhcyB0aGUgY29udGV4dCB3aGVuIGludm9raW5nIGEgbWV0aG9kLgogICAgQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IG1ldGhvZCBUaGUgbWV0aG9kIHRvIGludm9rZS4gSWYgeW91IHBhc3MgYSBzdHJpbmcgaXQKICAgICAgd2lsbCBiZSByZXNvbHZlZCBvbiB0aGUgdGFyZ2V0IG9iamVjdCBhdCB0aGUgdGltZSB0aGUgc2NoZWR1bGVkIGl0ZW0gaXMKICAgICAgaW52b2tlZCBhbGxvd2luZyB5b3UgdG8gY2hhbmdlIHRoZSB0YXJnZXQgZnVuY3Rpb24uCiAgICBAcGFyYW0ge09iamVjdH0gW2FyZ3VtZW50cypdIE9wdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gdGhlIHF1ZXVlZCBtZXRob2QuCiAgICBAcmV0dXJuIHsqfSBUaW1lciBpbmZvcm1hdGlvbiBmb3IgdXNlIGluIGNhbmNlbGluZywgc2VlIGBjYW5jZWxgLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBzY2hlZHVsZSgpCiAgLyogcXVldWUsIHRhcmdldCwgbWV0aG9kICovCiAgewogICAgcmV0dXJuIGJhY2tidXJuZXIuc2NoZWR1bGUuYXBwbHkoYmFja2J1cm5lciwgYXJndW1lbnRzKTsKICB9IC8vIFVzZWQgYnkgZ2xvYmFsIHRlc3QgdGVhcmRvd24KCgogIGZ1bmN0aW9uIGhhc1NjaGVkdWxlZFRpbWVycygpIHsKICAgIHJldHVybiBiYWNrYnVybmVyLmhhc1RpbWVycygpOwogIH0gLy8gVXNlZCBieSBnbG9iYWwgdGVzdCB0ZWFyZG93bgoKCiAgZnVuY3Rpb24gY2FuY2VsVGltZXJzKCkgewogICAgYmFja2J1cm5lci5jYW5jZWxUaW1lcnMoKTsKICB9CiAgLyoqCiAgICBJbnZva2VzIHRoZSBwYXNzZWQgdGFyZ2V0L21ldGhvZCBhbmQgb3B0aW9uYWwgYXJndW1lbnRzIGFmdGVyIGEgc3BlY2lmaWVkCiAgICBwZXJpb2Qgb2YgdGltZS4gVGhlIGxhc3QgcGFyYW1ldGVyIG9mIHRoaXMgbWV0aG9kIG11c3QgYWx3YXlzIGJlIGEgbnVtYmVyCiAgICBvZiBtaWxsaXNlY29uZHMuCiAgCiAgICBZb3Ugc2hvdWxkIHVzZSB0aGlzIG1ldGhvZCB3aGVuZXZlciB5b3UgbmVlZCB0byBydW4gc29tZSBhY3Rpb24gYWZ0ZXIgYQogICAgcGVyaW9kIG9mIHRpbWUgaW5zdGVhZCBvZiB1c2luZyBgc2V0VGltZW91dCgpYC4gVGhpcyBtZXRob2Qgd2lsbCBlbnN1cmUgdGhhdAogICAgaXRlbXMgdGhhdCBleHBpcmUgZHVyaW5nIHRoZSBzYW1lIHNjcmlwdCBleGVjdXRpb24gY3ljbGUgYWxsIGV4ZWN1dGUKICAgIHRvZ2V0aGVyLCB3aGljaCBpcyBvZnRlbiBtb3JlIGVmZmljaWVudCB0aGFuIHVzaW5nIGEgcmVhbCBzZXRUaW1lb3V0LgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgbGF0ZXIgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBsYXRlcihteUNvbnRleHQsIGZ1bmN0aW9uKCkgewogICAgICAvLyBjb2RlIGhlcmUgd2lsbCBleGVjdXRlIHdpdGhpbiBhIFJ1bkxvb3AgaW4gYWJvdXQgNTAwbXMgd2l0aCB0aGlzID09IG15Q29udGV4dAogICAgfSwgNTAwKTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBsYXRlcgogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvcnVubG9vcAogICAgQHBhcmFtIHtPYmplY3R9IFt0YXJnZXRdIHRhcmdldCBvZiBtZXRob2QgdG8gaW52b2tlCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIFRoZSBtZXRob2QgdG8gaW52b2tlLgogICAgICBJZiB5b3UgcGFzcyBhIHN0cmluZyBpdCB3aWxsIGJlIHJlc29sdmVkIG9uIHRoZQogICAgICB0YXJnZXQgYXQgdGhlIHRpbWUgdGhlIG1ldGhvZCBpcyBpbnZva2VkLgogICAgQHBhcmFtIHtPYmplY3R9IFthcmdzKl0gT3B0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIHRpbWVvdXQuCiAgICBAcGFyYW0ge051bWJlcn0gd2FpdCBOdW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIHdhaXQuCiAgICBAcmV0dXJuIHsqfSBUaW1lciBpbmZvcm1hdGlvbiBmb3IgdXNlIGluIGNhbmNlbGluZywgc2VlIGBjYW5jZWxgLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBsYXRlcigpCiAgLyp0YXJnZXQsIG1ldGhvZCovCiAgewogICAgcmV0dXJuIGJhY2tidXJuZXIubGF0ZXIuYXBwbHkoYmFja2J1cm5lciwgYXJndW1lbnRzKTsKICB9CiAgLyoqCiAgIFNjaGVkdWxlIGEgZnVuY3Rpb24gdG8gcnVuIG9uZSB0aW1lIGR1cmluZyB0aGUgY3VycmVudCBSdW5Mb29wLiBUaGlzIGlzIGVxdWl2YWxlbnQKICAgIHRvIGNhbGxpbmcgYHNjaGVkdWxlT25jZWAgd2l0aCB0aGUgImFjdGlvbnMiIHF1ZXVlLgogIAogICAgQG1ldGhvZCBvbmNlCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9ydW5sb29wCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gVGhlIHRhcmdldCBvZiB0aGUgbWV0aG9kIHRvIGludm9rZS4KICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBtZXRob2QgVGhlIG1ldGhvZCB0byBpbnZva2UuCiAgICAgIElmIHlvdSBwYXNzIGEgc3RyaW5nIGl0IHdpbGwgYmUgcmVzb2x2ZWQgb24gdGhlCiAgICAgIHRhcmdldCBhdCB0aGUgdGltZSB0aGUgbWV0aG9kIGlzIGludm9rZWQuCiAgICBAcGFyYW0ge09iamVjdH0gW2FyZ3MqXSBPcHRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgdGltZW91dC4KICAgIEByZXR1cm4ge09iamVjdH0gVGltZXIgaW5mb3JtYXRpb24gZm9yIHVzZSBpbiBjYW5jZWxpbmcsIHNlZSBgY2FuY2VsYC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gb25jZSgpIHsKICAgIGZvciAodmFyIF9sZW4zID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuMyksIF9rZXkzID0gMDsgX2tleTMgPCBfbGVuMzsgX2tleTMrKykgewogICAgICBhcmdzW19rZXkzXSA9IGFyZ3VtZW50c1tfa2V5M107CiAgICB9CgogICAgYXJncy51bnNoaWZ0KCdhY3Rpb25zJyk7CiAgICByZXR1cm4gYmFja2J1cm5lci5zY2hlZHVsZU9uY2UuYXBwbHkoYmFja2J1cm5lciwgYXJncyk7CiAgfQogIC8qKgogICAgU2NoZWR1bGVzIGEgZnVuY3Rpb24gdG8gcnVuIG9uZSB0aW1lIGluIGEgZ2l2ZW4gcXVldWUgb2YgdGhlIGN1cnJlbnQgUnVuTG9vcC4KICAgIENhbGxpbmcgdGhpcyBtZXRob2Qgd2l0aCB0aGUgc2FtZSBxdWV1ZS90YXJnZXQvbWV0aG9kIGNvbWJpbmF0aW9uIHdpbGwgaGF2ZQogICAgbm8gZWZmZWN0IChwYXN0IHRoZSBpbml0aWFsIGNhbGwpLgogIAogICAgTm90ZSB0aGF0IGFsdGhvdWdoIHlvdSBjYW4gcGFzcyBvcHRpb25hbCBhcmd1bWVudHMgdGhlc2Ugd2lsbCBub3QgYmUKICAgIGNvbnNpZGVyZWQgd2hlbiBsb29raW5nIGZvciBkdXBsaWNhdGVzLiBOZXcgYXJndW1lbnRzIHdpbGwgcmVwbGFjZSBwcmV2aW91cwogICAgY2FsbHMuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBydW4sIHNjaGVkdWxlT25jZSB9IGZyb20gJ0BlbWJlci9ydW5sb29wJzsKICAKICAgIGZ1bmN0aW9uIHNheUhpKCkgewogICAgICBjb25zb2xlLmxvZygnaGknKTsKICAgIH0KICAKICAgIHJ1bihmdW5jdGlvbigpIHsKICAgICAgc2NoZWR1bGVPbmNlKCdhZnRlclJlbmRlcicsIG15Q29udGV4dCwgc2F5SGkpOwogICAgICBzY2hlZHVsZU9uY2UoJ2FmdGVyUmVuZGVyJywgbXlDb250ZXh0LCBzYXlIaSk7CiAgICAgIC8vIHNheUhpIHdpbGwgb25seSBiZSBleGVjdXRlZCBvbmNlLCBpbiB0aGUgYWZ0ZXJSZW5kZXIgcXVldWUgb2YgdGhlIFJ1bkxvb3AKICAgIH0pOwogICAgYGBgCiAgCiAgICBBbHNvIG5vdGUgdGhhdCBmb3IgYHNjaGVkdWxlT25jZWAgdG8gcHJldmVudCBhZGRpdGlvbmFsIGNhbGxzLCB5b3UgbmVlZCB0bwogICAgcGFzcyB0aGUgc2FtZSBmdW5jdGlvbiBpbnN0YW5jZS4gVGhlIGZvbGxvd2luZyBjYXNlIHdvcmtzIGFzIGV4cGVjdGVkOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgZnVuY3Rpb24gbG9nKCkgewogICAgICBjb25zb2xlLmxvZygnTG9nZ2luZyBvbmx5IG9uY2UnKTsKICAgIH0KICAKICAgIGZ1bmN0aW9uIHNjaGVkdWxlSXQoKSB7CiAgICAgIHNjaGVkdWxlT25jZSgnYWN0aW9ucycsIG15Q29udGV4dCwgbG9nKTsKICAgIH0KICAKICAgIHNjaGVkdWxlSXQoKTsKICAgIHNjaGVkdWxlSXQoKTsKICAgIGBgYAogIAogICAgQnV0IHRoaXMgb3RoZXIgY2FzZSB3aWxsIHNjaGVkdWxlIHRoZSBmdW5jdGlvbiBtdWx0aXBsZSB0aW1lczoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IHNjaGVkdWxlT25jZSB9IGZyb20gJ0BlbWJlci9ydW5sb29wJzsKICAKICAgIGZ1bmN0aW9uIHNjaGVkdWxlSXQoKSB7CiAgICAgIHNjaGVkdWxlT25jZSgnYWN0aW9ucycsIG15Q29udGV4dCwgZnVuY3Rpb24oKSB7CiAgICAgICAgY29uc29sZS5sb2coJ0Nsb3N1cmUnKTsKICAgICAgfSk7CiAgICB9CiAgCiAgICBzY2hlZHVsZUl0KCk7CiAgICBzY2hlZHVsZUl0KCk7CiAgCiAgICAvLyAiQ2xvc3VyZSIgd2lsbCBwcmludCB0d2ljZSwgZXZlbiB0aG91Z2ggd2UncmUgdXNpbmcgYHNjaGVkdWxlT25jZWAsCiAgICAvLyBiZWNhdXNlIHRoZSBmdW5jdGlvbiB3ZSBwYXNzIHRvIGl0IHdvbid0IG1hdGNoIHRoZQogICAgLy8gcHJldmlvdXNseSBzY2hlZHVsZWQgb3BlcmF0aW9uLgogICAgYGBgCiAgCiAgICBBdmFpbGFibGUgcXVldWVzLCBhbmQgdGhlaXIgb3JkZXIsIGNhbiBiZSBmb3VuZCBhdCBgcXVldWVzYAogIAogICAgQG1ldGhvZCBzY2hlZHVsZU9uY2UKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL3J1bmxvb3AKICAgIEBwYXJhbSB7U3RyaW5nfSBbcXVldWVdIFRoZSBuYW1lIG9mIHRoZSBxdWV1ZSB0byBzY2hlZHVsZSBhZ2FpbnN0LiBEZWZhdWx0IHF1ZXVlcyBpcyAnYWN0aW9ucycuCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gVGhlIHRhcmdldCBvZiB0aGUgbWV0aG9kIHRvIGludm9rZS4KICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBtZXRob2QgVGhlIG1ldGhvZCB0byBpbnZva2UuCiAgICAgIElmIHlvdSBwYXNzIGEgc3RyaW5nIGl0IHdpbGwgYmUgcmVzb2x2ZWQgb24gdGhlCiAgICAgIHRhcmdldCBhdCB0aGUgdGltZSB0aGUgbWV0aG9kIGlzIGludm9rZWQuCiAgICBAcGFyYW0ge09iamVjdH0gW2FyZ3MqXSBPcHRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgdGltZW91dC4KICAgIEByZXR1cm4ge09iamVjdH0gVGltZXIgaW5mb3JtYXRpb24gZm9yIHVzZSBpbiBjYW5jZWxpbmcsIHNlZSBgY2FuY2VsYC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gc2NoZWR1bGVPbmNlKCkKICAvKiBxdWV1ZSwgdGFyZ2V0LCBtZXRob2QqLwogIHsKICAgIHJldHVybiBiYWNrYnVybmVyLnNjaGVkdWxlT25jZS5hcHBseShiYWNrYnVybmVyLCBhcmd1bWVudHMpOwogIH0KICAvKioKICAgIFNjaGVkdWxlcyBhbiBpdGVtIHRvIHJ1biBmcm9tIHdpdGhpbiBhIHNlcGFyYXRlIHJ1biBsb29wLCBhZnRlcgogICAgY29udHJvbCBoYXMgYmVlbiByZXR1cm5lZCB0byB0aGUgc3lzdGVtLiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gY2FsbGluZwogICAgYGxhdGVyYCB3aXRoIGEgd2FpdCB0aW1lIG9mIDFtcy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IG5leHQgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBuZXh0KG15Q29udGV4dCwgZnVuY3Rpb24oKSB7CiAgICAgIC8vIGNvZGUgdG8gYmUgZXhlY3V0ZWQgaW4gdGhlIG5leHQgcnVuIGxvb3AsCiAgICAgIC8vIHdoaWNoIHdpbGwgYmUgc2NoZWR1bGVkIGFmdGVyIHRoZSBjdXJyZW50IG9uZQogICAgfSk7CiAgICBgYGAKICAKICAgIE11bHRpcGxlIG9wZXJhdGlvbnMgc2NoZWR1bGVkIHdpdGggYG5leHRgIHdpbGwgY29hbGVzY2UKICAgIGludG8gdGhlIHNhbWUgbGF0ZXIgcnVuIGxvb3AsIGFsb25nIHdpdGggYW55IG90aGVyIG9wZXJhdGlvbnMKICAgIHNjaGVkdWxlZCBieSBgbGF0ZXJgIHRoYXQgZXhwaXJlIHJpZ2h0IGFyb3VuZCB0aGUgc2FtZQogICAgdGltZSB0aGF0IGBuZXh0YCBvcGVyYXRpb25zIHdpbGwgZmlyZS4KICAKICAgIE5vdGUgdGhhdCB0aGVyZSBhcmUgb2Z0ZW4gYWx0ZXJuYXRpdmVzIHRvIHVzaW5nIGBuZXh0YC4KICAgIEZvciBpbnN0YW5jZSwgaWYgeW91J2QgbGlrZSB0byBzY2hlZHVsZSBhbiBvcGVyYXRpb24gdG8gaGFwcGVuCiAgICBhZnRlciBhbGwgRE9NIGVsZW1lbnQgb3BlcmF0aW9ucyBoYXZlIGNvbXBsZXRlZCB3aXRoaW4gdGhlIGN1cnJlbnQKICAgIHJ1biBsb29wLCB5b3UgY2FuIG1ha2UgdXNlIG9mIHRoZSBgYWZ0ZXJSZW5kZXJgIHJ1biBsb29wIHF1ZXVlIChhZGRlZAogICAgYnkgdGhlIGBlbWJlci12aWV3c2AgcGFja2FnZSwgYWxvbmcgd2l0aCB0aGUgcHJlY2VkaW5nIGByZW5kZXJgIHF1ZXVlCiAgICB3aGVyZSBhbGwgdGhlIERPTSBlbGVtZW50IG9wZXJhdGlvbnMgaGFwcGVuKS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBhcHAvY29tcG9uZW50cy9teS1jb21wb25lbnQuanMKICAgIGltcG9ydCBDb21wb25lbnQgZnJvbSAnQGVtYmVyL2NvbXBvbmVudCc7CiAgICBpbXBvcnQgeyBzY2hlZHVsZU9uY2UgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBleHBvcnQgQ29tcG9uZW50LmV4dGVuZCh7CiAgICAgIGRpZEluc2VydEVsZW1lbnQoKSB7CiAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICBzY2hlZHVsZU9uY2UoJ2FmdGVyUmVuZGVyJywgdGhpcywgJ3Byb2Nlc3NDaGlsZEVsZW1lbnRzJyk7CiAgICAgIH0sCiAgCiAgICAgIHByb2Nlc3NDaGlsZEVsZW1lbnRzKCkgewogICAgICAgIC8vIC4uLiBkbyBzb21ldGhpbmcgd2l0aCBjb21wb25lbnQncyBjaGlsZCBjb21wb25lbnQKICAgICAgICAvLyBlbGVtZW50cyBhZnRlciB0aGV5J3ZlIGZpbmlzaGVkIHJlbmRlcmluZywgd2hpY2gKICAgICAgICAvLyBjYW4ndCBiZSBkb25lIHdpdGhpbiB0aGlzIGNvbXBvbmVudCdzCiAgICAgICAgLy8gYGRpZEluc2VydEVsZW1lbnRgIGhvb2sgYmVjYXVzZSB0aGF0IGdldHMgcnVuCiAgICAgICAgLy8gYmVmb3JlIHRoZSBjaGlsZCBlbGVtZW50cyBoYXZlIGJlZW4gYWRkZWQgdG8gdGhlIERPTS4KICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIE9uZSBiZW5lZml0IG9mIHRoZSBhYm92ZSBhcHByb2FjaCBjb21wYXJlZCB0byB1c2luZyBgbmV4dGAgaXMKICAgIHRoYXQgeW91IHdpbGwgYmUgYWJsZSB0byBwZXJmb3JtIERPTS9DU1Mgb3BlcmF0aW9ucyBiZWZvcmUgdW5wcm9jZXNzZWQKICAgIGVsZW1lbnRzIGFyZSByZW5kZXJlZCB0byB0aGUgc2NyZWVuLCB3aGljaCBtYXkgcHJldmVudCBmbGlja2VyaW5nIG9yCiAgICBvdGhlciBhcnRpZmFjdHMgY2F1c2VkIGJ5IGRlbGF5aW5nIHByb2Nlc3NpbmcgdW50aWwgYWZ0ZXIgcmVuZGVyaW5nLgogIAogICAgVGhlIG90aGVyIG1ham9yIGJlbmVmaXQgdG8gdGhlIGFib3ZlIGFwcHJvYWNoIGlzIHRoYXQgYG5leHRgCiAgICBpbnRyb2R1Y2VzIGFuIGVsZW1lbnQgb2Ygbm9uLWRldGVybWluaXNtLCB3aGljaCBjYW4gbWFrZSB0aGluZ3MgbXVjaAogICAgaGFyZGVyIHRvIHRlc3QsIGR1ZSB0byBpdHMgcmVsaWFuY2Ugb24gYHNldFRpbWVvdXRgOyBpdCdzIG11Y2ggaGFyZGVyCiAgICB0byBndWFyYW50ZWUgdGhlIG9yZGVyIG9mIHNjaGVkdWxlZCBvcGVyYXRpb25zIHdoZW4gdGhleSBhcmUgc2NoZWR1bGVkCiAgICBvdXRzaWRlIG9mIHRoZSBjdXJyZW50IHJ1biBsb29wLCBpLmUuIHdpdGggYG5leHRgLgogIAogICAgQG1ldGhvZCBuZXh0CiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9ydW5sb29wCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gdGFyZ2V0IG9mIG1ldGhvZCB0byBpbnZva2UKICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBtZXRob2QgVGhlIG1ldGhvZCB0byBpbnZva2UuCiAgICAgIElmIHlvdSBwYXNzIGEgc3RyaW5nIGl0IHdpbGwgYmUgcmVzb2x2ZWQgb24gdGhlCiAgICAgIHRhcmdldCBhdCB0aGUgdGltZSB0aGUgbWV0aG9kIGlzIGludm9rZWQuCiAgICBAcGFyYW0ge09iamVjdH0gW2FyZ3MqXSBPcHRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgdGltZW91dC4KICAgIEByZXR1cm4ge09iamVjdH0gVGltZXIgaW5mb3JtYXRpb24gZm9yIHVzZSBpbiBjYW5jZWxpbmcsIHNlZSBgY2FuY2VsYC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gbmV4dCgpIHsKICAgIGZvciAodmFyIF9sZW40ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuNCksIF9rZXk0ID0gMDsgX2tleTQgPCBfbGVuNDsgX2tleTQrKykgewogICAgICBhcmdzW19rZXk0XSA9IGFyZ3VtZW50c1tfa2V5NF07CiAgICB9CgogICAgYXJncy5wdXNoKDEpOwogICAgcmV0dXJuIGJhY2tidXJuZXIubGF0ZXIuYXBwbHkoYmFja2J1cm5lciwgYXJncyk7CiAgfQogIC8qKgogICAgQ2FuY2VscyBhIHNjaGVkdWxlZCBpdGVtLiBNdXN0IGJlIGEgdmFsdWUgcmV0dXJuZWQgYnkgYGxhdGVyKClgLAogICAgYG9uY2UoKWAsIGBzY2hlZHVsZU9uY2UoKWAsIGBuZXh0KClgLCBgZGVib3VuY2UoKWAsIG9yCiAgICBgdGhyb3R0bGUoKWAuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgewogICAgICBuZXh0LAogICAgICBjYW5jZWwsCiAgICAgIGxhdGVyLAogICAgICBzY2hlZHVsZU9uY2UsCiAgICAgIG9uY2UsCiAgICAgIHRocm90dGxlLAogICAgICBkZWJvdW5jZQogICAgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBsZXQgcnVuTmV4dCA9IG5leHQobXlDb250ZXh0LCBmdW5jdGlvbigpIHsKICAgICAgLy8gd2lsbCBub3QgYmUgZXhlY3V0ZWQKICAgIH0pOwogIAogICAgY2FuY2VsKHJ1bk5leHQpOwogIAogICAgbGV0IHJ1bkxhdGVyID0gbGF0ZXIobXlDb250ZXh0LCBmdW5jdGlvbigpIHsKICAgICAgLy8gd2lsbCBub3QgYmUgZXhlY3V0ZWQKICAgIH0sIDUwMCk7CiAgCiAgICBjYW5jZWwocnVuTGF0ZXIpOwogIAogICAgbGV0IHJ1blNjaGVkdWxlT25jZSA9IHNjaGVkdWxlT25jZSgnYWZ0ZXJSZW5kZXInLCBteUNvbnRleHQsIGZ1bmN0aW9uKCkgewogICAgICAvLyB3aWxsIG5vdCBiZSBleGVjdXRlZAogICAgfSk7CiAgCiAgICBjYW5jZWwocnVuU2NoZWR1bGVPbmNlKTsKICAKICAgIGxldCBydW5PbmNlID0gb25jZShteUNvbnRleHQsIGZ1bmN0aW9uKCkgewogICAgICAvLyB3aWxsIG5vdCBiZSBleGVjdXRlZAogICAgfSk7CiAgCiAgICBjYW5jZWwocnVuT25jZSk7CiAgCiAgICBsZXQgdGhyb3R0bGUgPSB0aHJvdHRsZShteUNvbnRleHQsIGZ1bmN0aW9uKCkgewogICAgICAvLyB3aWxsIG5vdCBiZSBleGVjdXRlZAogICAgfSwgMSwgZmFsc2UpOwogIAogICAgY2FuY2VsKHRocm90dGxlKTsKICAKICAgIGxldCBkZWJvdW5jZSA9IGRlYm91bmNlKG15Q29udGV4dCwgZnVuY3Rpb24oKSB7CiAgICAgIC8vIHdpbGwgbm90IGJlIGV4ZWN1dGVkCiAgICB9LCAxKTsKICAKICAgIGNhbmNlbChkZWJvdW5jZSk7CiAgCiAgICBsZXQgZGVib3VuY2VJbW1lZGlhdGUgPSBkZWJvdW5jZShteUNvbnRleHQsIGZ1bmN0aW9uKCkgewogICAgICAvLyB3aWxsIGJlIGV4ZWN1dGVkIHNpbmNlIHdlIHBhc3NlZCBpbiB0cnVlIChpbW1lZGlhdGUpCiAgICB9LCAxMDAsIHRydWUpOwogIAogICAgLy8gdGhlIDEwMG1zIGRlbGF5IHVudGlsIHRoaXMgbWV0aG9kIGNhbiBiZSBjYWxsZWQgYWdhaW4gd2lsbCBiZSBjYW5jZWxlZAogICAgY2FuY2VsKGRlYm91bmNlSW1tZWRpYXRlKTsKICAgIGBgYAogIAogICAgQG1ldGhvZCBjYW5jZWwKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyL3J1bmxvb3AKICAgIEBwYXJhbSB7T2JqZWN0fSB0aW1lciBUaW1lciBvYmplY3QgdG8gY2FuY2VsCiAgICBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIGNhbmNlbGVkIG9yIGZhbHNlL3VuZGVmaW5lZCBpZiBpdCB3YXNuJ3QgZm91bmQKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gY2FuY2VsKHRpbWVyKSB7CiAgICByZXR1cm4gYmFja2J1cm5lci5jYW5jZWwodGltZXIpOwogIH0KICAvKioKICAgIERlbGF5IGNhbGxpbmcgdGhlIHRhcmdldCBtZXRob2QgdW50aWwgdGhlIGRlYm91bmNlIHBlcmlvZCBoYXMgZWxhcHNlZAogICAgd2l0aCBubyBhZGRpdGlvbmFsIGRlYm91bmNlIGNhbGxzLiBJZiBgZGVib3VuY2VgIGlzIGNhbGxlZCBhZ2FpbiBiZWZvcmUKICAgIHRoZSBzcGVjaWZpZWQgdGltZSBoYXMgZWxhcHNlZCwgdGhlIHRpbWVyIGlzIHJlc2V0IGFuZCB0aGUgZW50aXJlIHBlcmlvZAogICAgbXVzdCBwYXNzIGFnYWluIGJlZm9yZSB0aGUgdGFyZ2V0IG1ldGhvZCBpcyBjYWxsZWQuCiAgCiAgICBUaGlzIG1ldGhvZCBzaG91bGQgYmUgdXNlZCB3aGVuIGFuIGV2ZW50IG1heSBiZSBjYWxsZWQgbXVsdGlwbGUgdGltZXMKICAgIGJ1dCB0aGUgYWN0aW9uIHNob3VsZCBvbmx5IGJlIGNhbGxlZCBvbmNlIHdoZW4gdGhlIGV2ZW50IGlzIGRvbmUgZmlyaW5nLgogICAgQSBjb21tb24gZXhhbXBsZSBpcyBmb3Igc2Nyb2xsIGV2ZW50cyB3aGVyZSB5b3Ugb25seSB3YW50IHVwZGF0ZXMgdG8KICAgIGhhcHBlbiBvbmNlIHNjcm9sbGluZyBoYXMgY2Vhc2VkLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZGVib3VuY2UgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBmdW5jdGlvbiB3aG9SYW4oKSB7CiAgICAgIGNvbnNvbGUubG9nKHRoaXMubmFtZSArICcgcmFuLicpOwogICAgfQogIAogICAgbGV0IG15Q29udGV4dCA9IHsgbmFtZTogJ2RlYm91bmNlJyB9OwogIAogICAgZGVib3VuY2UobXlDb250ZXh0LCB3aG9SYW4sIDE1MCk7CiAgCiAgICAvLyBsZXNzIHRoYW4gMTUwbXMgcGFzc2VzCiAgICBkZWJvdW5jZShteUNvbnRleHQsIHdob1JhbiwgMTUwKTsKICAKICAgIC8vIDE1MG1zIHBhc3NlcwogICAgLy8gd2hvUmFuIGlzIGludm9rZWQgd2l0aCBjb250ZXh0IG15Q29udGV4dAogICAgLy8gY29uc29sZSBsb2dzICdkZWJvdW5jZSByYW4uJyBvbmUgdGltZS4KICAgIGBgYAogIAogICAgSW1tZWRpYXRlIGFsbG93cyB5b3UgdG8gcnVuIHRoZSBmdW5jdGlvbiBpbW1lZGlhdGVseSwgYnV0IGRlYm91bmNlCiAgICBvdGhlciBjYWxscyBmb3IgdGhpcyBmdW5jdGlvbiB1bnRpbCB0aGUgd2FpdCB0aW1lIGhhcyBlbGFwc2VkLiBJZgogICAgYGRlYm91bmNlYCBpcyBjYWxsZWQgYWdhaW4gYmVmb3JlIHRoZSBzcGVjaWZpZWQgdGltZSBoYXMgZWxhcHNlZCwKICAgIHRoZSB0aW1lciBpcyByZXNldCBhbmQgdGhlIGVudGlyZSBwZXJpb2QgbXVzdCBwYXNzIGFnYWluIGJlZm9yZQogICAgdGhlIG1ldGhvZCBjYW4gYmUgY2FsbGVkIGFnYWluLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZGVib3VuY2UgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBmdW5jdGlvbiB3aG9SYW4oKSB7CiAgICAgIGNvbnNvbGUubG9nKHRoaXMubmFtZSArICcgcmFuLicpOwogICAgfQogIAogICAgbGV0IG15Q29udGV4dCA9IHsgbmFtZTogJ2RlYm91bmNlJyB9OwogIAogICAgZGVib3VuY2UobXlDb250ZXh0LCB3aG9SYW4sIDE1MCwgdHJ1ZSk7CiAgCiAgICAvLyBjb25zb2xlIGxvZ3MgJ2RlYm91bmNlIHJhbi4nIG9uZSB0aW1lIGltbWVkaWF0ZWx5LgogICAgLy8gMTAwbXMgcGFzc2VzCiAgICBkZWJvdW5jZShteUNvbnRleHQsIHdob1JhbiwgMTUwLCB0cnVlKTsKICAKICAgIC8vIDE1MG1zIHBhc3NlcyBhbmQgbm90aGluZyBlbHNlIGlzIGxvZ2dlZCB0byB0aGUgY29uc29sZSBhbmQKICAgIC8vIHRoZSBkZWJvdW5jZWUgaXMgbm8gbG9uZ2VyIGJlaW5nIHdhdGNoZWQKICAgIGRlYm91bmNlKG15Q29udGV4dCwgd2hvUmFuLCAxNTAsIHRydWUpOwogIAogICAgLy8gY29uc29sZSBsb2dzICdkZWJvdW5jZSByYW4uJyBvbmUgdGltZSBpbW1lZGlhdGVseS4KICAgIC8vIDE1MG1zIHBhc3NlcyBhbmQgbm90aGluZyBlbHNlIGlzIGxvZ2dlZCB0byB0aGUgY29uc29sZSBhbmQKICAgIC8vIHRoZSBkZWJvdW5jZWUgaXMgbm8gbG9uZ2VyIGJlaW5nIHdhdGNoZWQKICAgIGBgYAogIAogICAgQG1ldGhvZCBkZWJvdW5jZQogICAgQHN0YXRpYwogICAgQGZvciBAZW1iZXIvcnVubG9vcAogICAgQHBhcmFtIHtPYmplY3R9IFt0YXJnZXRdIHRhcmdldCBvZiBtZXRob2QgdG8gaW52b2tlCiAgICBAcGFyYW0ge0Z1bmN0aW9ufFN0cmluZ30gbWV0aG9kIFRoZSBtZXRob2QgdG8gaW52b2tlLgogICAgICBNYXkgYmUgYSBmdW5jdGlvbiBvciBhIHN0cmluZy4gSWYgeW91IHBhc3MgYSBzdHJpbmcKICAgICAgdGhlbiBpdCB3aWxsIGJlIGxvb2tlZCB1cCBvbiB0aGUgcGFzc2VkIHRhcmdldC4KICAgIEBwYXJhbSB7T2JqZWN0fSBbYXJncypdIE9wdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSB0aW1lb3V0LgogICAgQHBhcmFtIHtOdW1iZXJ9IHdhaXQgTnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byB3YWl0LgogICAgQHBhcmFtIHtCb29sZWFufSBpbW1lZGlhdGUgVHJpZ2dlciB0aGUgZnVuY3Rpb24gb24gdGhlIGxlYWRpbmcgaW5zdGVhZAogICAgICBvZiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgd2FpdCBpbnRlcnZhbC4gRGVmYXVsdHMgdG8gZmFsc2UuCiAgICBAcmV0dXJuIHtBcnJheX0gVGltZXIgaW5mb3JtYXRpb24gZm9yIHVzZSBpbiBjYW5jZWxpbmcsIHNlZSBgY2FuY2VsYC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZGVib3VuY2UoKSB7CiAgICByZXR1cm4gYmFja2J1cm5lci5kZWJvdW5jZS5hcHBseShiYWNrYnVybmVyLCBhcmd1bWVudHMpOwogIH0KICAvKioKICAgIEVuc3VyZSB0aGF0IHRoZSB0YXJnZXQgbWV0aG9kIGlzIG5ldmVyIGNhbGxlZCBtb3JlIGZyZXF1ZW50bHkgdGhhbgogICAgdGhlIHNwZWNpZmllZCBzcGFjaW5nIHBlcmlvZC4gVGhlIHRhcmdldCBtZXRob2QgaXMgY2FsbGVkIGltbWVkaWF0ZWx5LgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgdGhyb3R0bGUgfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgCiAgICBmdW5jdGlvbiB3aG9SYW4oKSB7CiAgICAgIGNvbnNvbGUubG9nKHRoaXMubmFtZSArICcgcmFuLicpOwogICAgfQogIAogICAgbGV0IG15Q29udGV4dCA9IHsgbmFtZTogJ3Rocm90dGxlJyB9OwogIAogICAgdGhyb3R0bGUobXlDb250ZXh0LCB3aG9SYW4sIDE1MCk7CiAgICAvLyB3aG9SYW4gaXMgaW52b2tlZCB3aXRoIGNvbnRleHQgbXlDb250ZXh0CiAgICAvLyBjb25zb2xlIGxvZ3MgJ3Rocm90dGxlIHJhbi4nCiAgCiAgICAvLyA1MG1zIHBhc3NlcwogICAgdGhyb3R0bGUobXlDb250ZXh0LCB3aG9SYW4sIDE1MCk7CiAgCiAgICAvLyA1MG1zIHBhc3NlcwogICAgdGhyb3R0bGUobXlDb250ZXh0LCB3aG9SYW4sIDE1MCk7CiAgCiAgICAvLyAxNTBtcyBwYXNzZXMKICAgIHRocm90dGxlKG15Q29udGV4dCwgd2hvUmFuLCAxNTApOwogICAgLy8gd2hvUmFuIGlzIGludm9rZWQgd2l0aCBjb250ZXh0IG15Q29udGV4dAogICAgLy8gY29uc29sZSBsb2dzICd0aHJvdHRsZSByYW4uJwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHRocm90dGxlCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci9ydW5sb29wCiAgICBAcGFyYW0ge09iamVjdH0gW3RhcmdldF0gdGFyZ2V0IG9mIG1ldGhvZCB0byBpbnZva2UKICAgIEBwYXJhbSB7RnVuY3Rpb258U3RyaW5nfSBtZXRob2QgVGhlIG1ldGhvZCB0byBpbnZva2UuCiAgICAgIE1heSBiZSBhIGZ1bmN0aW9uIG9yIGEgc3RyaW5nLiBJZiB5b3UgcGFzcyBhIHN0cmluZwogICAgICB0aGVuIGl0IHdpbGwgYmUgbG9va2VkIHVwIG9uIHRoZSBwYXNzZWQgdGFyZ2V0LgogICAgQHBhcmFtIHtPYmplY3R9IFthcmdzKl0gT3B0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIHRpbWVvdXQuCiAgICBAcGFyYW0ge051bWJlcn0gc3BhY2luZyBOdW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIHNwYWNlIG91dCByZXF1ZXN0cy4KICAgIEBwYXJhbSB7Qm9vbGVhbn0gaW1tZWRpYXRlIFRyaWdnZXIgdGhlIGZ1bmN0aW9uIG9uIHRoZSBsZWFkaW5nIGluc3RlYWQKICAgICAgb2YgdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHdhaXQgaW50ZXJ2YWwuIERlZmF1bHRzIHRvIHRydWUuCiAgICBAcmV0dXJuIHtBcnJheX0gVGltZXIgaW5mb3JtYXRpb24gZm9yIHVzZSBpbiBjYW5jZWxpbmcsIHNlZSBgY2FuY2VsYC4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gdGhyb3R0bGUoKSB7CiAgICByZXR1cm4gYmFja2J1cm5lci50aHJvdHRsZS5hcHBseShiYWNrYnVybmVyLCBhcmd1bWVudHMpOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyL3NlcnZpY2UvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSIsICJAZW1iZXIvLWludGVybmFscy9tZXRhbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9ydW50aW1lLCBfbWV0YWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmluamVjdCA9IGluamVjdDsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgQG1vZHVsZSBAZW1iZXIvc2VydmljZQogICBAcHVibGljCiAgICovCgogIC8qKgogICAgQ3JlYXRlcyBhIHByb3BlcnR5IHRoYXQgbGF6aWx5IGxvb2tzIHVwIGEgc2VydmljZSBpbiB0aGUgY29udGFpbmVyLiBUaGVyZSBhcmUKICAgIG5vIHJlc3RyaWN0aW9ucyBhcyB0byB3aGF0IG9iamVjdHMgYSBzZXJ2aWNlIGNhbiBiZSBpbmplY3RlZCBpbnRvLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IGNsYXNzIEFwcGxpY2F0aW9uUm91dGUgZXh0ZW5kcyBSb3V0ZSB7CiAgICAgIEBzZXJ2aWNlKCdhdXRoJykgYXV0aE1hbmFnZXI7CiAgCiAgICAgIG1vZGVsKCkgewogICAgICAgIHJldHVybiB0aGlzLmF1dGhNYW5hZ2VyLmZpbmRDdXJyZW50VXNlcigpOwogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIENsYXNzaWMgQ2xhc3MgRXhhbXBsZToKICAKICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICBpbXBvcnQgeyBpbmplY3QgYXMgc2VydmljZSB9IGZyb20gJ0BlbWJlci9zZXJ2aWNlJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgIGF1dGhNYW5hZ2VyOiBzZXJ2aWNlKCdhdXRoJyksCiAgCiAgICAgIG1vZGVsKCkgewogICAgICAgIHJldHVybiB0aGlzLmdldCgnYXV0aE1hbmFnZXInKS5maW5kQ3VycmVudFVzZXIoKTsKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIFRoaXMgZXhhbXBsZSB3aWxsIGNyZWF0ZSBhbiBgYXV0aE1hbmFnZXJgIHByb3BlcnR5IG9uIHRoZSBhcHBsaWNhdGlvbiByb3V0ZQogICAgdGhhdCBsb29rcyB1cCB0aGUgYGF1dGhgIHNlcnZpY2UgaW4gdGhlIGNvbnRhaW5lciwgbWFraW5nIGl0IGVhc2lseSBhY2Nlc3NpYmxlCiAgICBpbiB0aGUgYG1vZGVsYCBob29rLgogIAogICAgQG1ldGhvZCBpbmplY3QKICAgIEBzdGF0aWMKICAgIEBzaW5jZSAxLjEwLjAKICAgIEBmb3IgQGVtYmVyL3NlcnZpY2UKICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIChvcHRpb25hbCkgbmFtZSBvZiB0aGUgc2VydmljZSB0byBpbmplY3QsIGRlZmF1bHRzIHRvCiAgICAgICAgICAgdGhlIHByb3BlcnR5J3MgbmFtZQogICAgQHJldHVybiB7Q29tcHV0ZWREZWNvcmF0b3J9IGluamVjdGlvbiBkZWNvcmF0b3IgaW5zdGFuY2UKICAgIEBwdWJsaWMKICAqLwogIGZ1bmN0aW9uIGluamVjdCgpIHsKICAgIHJldHVybiBfbWV0YWwuaW5qZWN0LmFwcGx5KHZvaWQgMCwgWydzZXJ2aWNlJ10uY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTsKICB9CiAgLyoqCiAgICBAY2xhc3MgU2VydmljZQogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAgIEBzaW5jZSAxLjEwLjAKICAgIEBwdWJsaWMKICAqLwoKCiAgdmFyIFNlcnZpY2UgPSBfcnVudGltZS5GcmFtZXdvcmtPYmplY3QuZXh0ZW5kKCk7CgogIFNlcnZpY2UucmVvcGVuQ2xhc3MoewogICAgaXNTZXJ2aWNlRmFjdG9yeTogdHJ1ZQogIH0pOwoKICBpZiAodHJ1ZQogIC8qIEVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQgKi8KICApIHsKICAgICAgKDAsIF9ydW50aW1lLnNldEZyYW1ld29ya0NsYXNzKShTZXJ2aWNlKTsKICAgIH0KCiAgdmFyIF9kZWZhdWx0ID0gU2VydmljZTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpkZWZpbmUoIkBlbWJlci9zdHJpbmcvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyL3N0cmluZy9saWIvc3RyaW5nX3JlZ2lzdHJ5IiwgIkBlbWJlci8taW50ZXJuYWxzL2Vudmlyb25tZW50IiwgIkBlbWJlci8taW50ZXJuYWxzL3V0aWxzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3N0cmluZ19yZWdpc3RyeSwgX2Vudmlyb25tZW50LCBfdXRpbHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmxvYyA9IGxvYzsKICBfZXhwb3J0cy53ID0gdzsKICBfZXhwb3J0cy5kZWNhbWVsaXplID0gZGVjYW1lbGl6ZTsKICBfZXhwb3J0cy5kYXNoZXJpemUgPSBkYXNoZXJpemU7CiAgX2V4cG9ydHMuY2FtZWxpemUgPSBjYW1lbGl6ZTsKICBfZXhwb3J0cy5jbGFzc2lmeSA9IGNsYXNzaWZ5OwogIF9leHBvcnRzLnVuZGVyc2NvcmUgPSB1bmRlcnNjb3JlOwogIF9leHBvcnRzLmNhcGl0YWxpemUgPSBjYXBpdGFsaXplOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9nZXRTdHJpbmdzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3N0cmluZ19yZWdpc3RyeS5nZXRTdHJpbmdzOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9zZXRTdHJpbmdzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3N0cmluZ19yZWdpc3RyeS5zZXRTdHJpbmdzOwogICAgfQogIH0pOwoKICAvKioKICBAbW9kdWxlIEBlbWJlci9zdHJpbmcKICAqLwogIHZhciBTVFJJTkdfREFTSEVSSVpFX1JFR0VYUCA9IC9bIF9dL2c7CiAgdmFyIFNUUklOR19EQVNIRVJJWkVfQ0FDSEUgPSBuZXcgX3V0aWxzLkNhY2hlKDEwMDAsIGZ1bmN0aW9uIChrZXkpIHsKICAgIHJldHVybiBkZWNhbWVsaXplKGtleSkucmVwbGFjZShTVFJJTkdfREFTSEVSSVpFX1JFR0VYUCwgJy0nKTsKICB9KTsKICB2YXIgU1RSSU5HX0NBTUVMSVpFX1JFR0VYUF8xID0gLyhcLXxcX3xcLnxccykrKC4pPy9nOwogIHZhciBTVFJJTkdfQ0FNRUxJWkVfUkVHRVhQXzIgPSAvKF58XC8pKFtBLVpdKS9nOwogIHZhciBDQU1FTElaRV9DQUNIRSA9IG5ldyBfdXRpbHMuQ2FjaGUoMTAwMCwgZnVuY3Rpb24gKGtleSkgewogICAgcmV0dXJuIGtleS5yZXBsYWNlKFNUUklOR19DQU1FTElaRV9SRUdFWFBfMSwgZnVuY3Rpb24gKF9tYXRjaCwgX3NlcGFyYXRvciwgY2hyKSB7CiAgICAgIHJldHVybiBjaHIgPyBjaHIudG9VcHBlckNhc2UoKSA6ICcnOwogICAgfSkucmVwbGFjZShTVFJJTkdfQ0FNRUxJWkVfUkVHRVhQXzIsIGZ1bmN0aW9uIChtYXRjaAogICAgLyosIHNlcGFyYXRvciwgY2hyICovCiAgICApIHsKICAgICAgcmV0dXJuIG1hdGNoLnRvTG93ZXJDYXNlKCk7CiAgICB9KTsKICB9KTsKICB2YXIgU1RSSU5HX0NMQVNTSUZZX1JFR0VYUF8xID0gL14oXC18XykrKC4pPy87CiAgdmFyIFNUUklOR19DTEFTU0lGWV9SRUdFWFBfMiA9IC8oLikoXC18XF98XC58XHMpKyguKT8vZzsKICB2YXIgU1RSSU5HX0NMQVNTSUZZX1JFR0VYUF8zID0gLyhefFwvfFwuKShbYS16XSkvZzsKICB2YXIgQ0xBU1NJRllfQ0FDSEUgPSBuZXcgX3V0aWxzLkNhY2hlKDEwMDAsIGZ1bmN0aW9uIChzdHIpIHsKICAgIHZhciByZXBsYWNlMSA9IGZ1bmN0aW9uIHJlcGxhY2UxKF9tYXRjaCwgX3NlcGFyYXRvciwgY2hyKSB7CiAgICAgIHJldHVybiBjaHIgPyAiXyIgKyBjaHIudG9VcHBlckNhc2UoKSA6ICcnOwogICAgfTsKCiAgICB2YXIgcmVwbGFjZTIgPSBmdW5jdGlvbiByZXBsYWNlMihfbWF0Y2gsIGluaXRpYWxDaGFyLCBfc2VwYXJhdG9yLCBjaHIpIHsKICAgICAgcmV0dXJuIGluaXRpYWxDaGFyICsgKGNociA/IGNoci50b1VwcGVyQ2FzZSgpIDogJycpOwogICAgfTsKCiAgICB2YXIgcGFydHMgPSBzdHIuc3BsaXQoJy8nKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHBhcnRzW2ldID0gcGFydHNbaV0ucmVwbGFjZShTVFJJTkdfQ0xBU1NJRllfUkVHRVhQXzEsIHJlcGxhY2UxKS5yZXBsYWNlKFNUUklOR19DTEFTU0lGWV9SRUdFWFBfMiwgcmVwbGFjZTIpOwogICAgfQoKICAgIHJldHVybiBwYXJ0cy5qb2luKCcvJykucmVwbGFjZShTVFJJTkdfQ0xBU1NJRllfUkVHRVhQXzMsIGZ1bmN0aW9uIChtYXRjaAogICAgLyosIHNlcGFyYXRvciwgY2hyICovCiAgICApIHsKICAgICAgcmV0dXJuIG1hdGNoLnRvVXBwZXJDYXNlKCk7CiAgICB9KTsKICB9KTsKICB2YXIgU1RSSU5HX1VOREVSU0NPUkVfUkVHRVhQXzEgPSAvKFthLXpcZF0pKFtBLVpdKykvZzsKICB2YXIgU1RSSU5HX1VOREVSU0NPUkVfUkVHRVhQXzIgPSAvXC18XHMrL2c7CiAgdmFyIFVOREVSU0NPUkVfQ0FDSEUgPSBuZXcgX3V0aWxzLkNhY2hlKDEwMDAsIGZ1bmN0aW9uIChzdHIpIHsKICAgIHJldHVybiBzdHIucmVwbGFjZShTVFJJTkdfVU5ERVJTQ09SRV9SRUdFWFBfMSwgJyQxXyQyJykucmVwbGFjZShTVFJJTkdfVU5ERVJTQ09SRV9SRUdFWFBfMiwgJ18nKS50b0xvd2VyQ2FzZSgpOwogIH0pOwogIHZhciBTVFJJTkdfQ0FQSVRBTElaRV9SRUdFWFAgPSAvKF58XC8pKFthLXpcdTAwQzAtXHUwMjRGXSkvZzsKICB2YXIgQ0FQSVRBTElaRV9DQUNIRSA9IG5ldyBfdXRpbHMuQ2FjaGUoMTAwMCwgZnVuY3Rpb24gKHN0cikgewogICAgcmV0dXJuIHN0ci5yZXBsYWNlKFNUUklOR19DQVBJVEFMSVpFX1JFR0VYUCwgZnVuY3Rpb24gKG1hdGNoCiAgICAvKiwgc2VwYXJhdG9yLCBjaHIgKi8KICAgICkgewogICAgICByZXR1cm4gbWF0Y2gudG9VcHBlckNhc2UoKTsKICAgIH0pOwogIH0pOwogIHZhciBTVFJJTkdfREVDQU1FTElaRV9SRUdFWFAgPSAvKFthLXpcZF0pKFtBLVpdKS9nOwogIHZhciBERUNBTUVMSVpFX0NBQ0hFID0gbmV3IF91dGlscy5DYWNoZSgxMDAwLCBmdW5jdGlvbiAoc3RyKSB7CiAgICByZXR1cm4gc3RyLnJlcGxhY2UoU1RSSU5HX0RFQ0FNRUxJWkVfUkVHRVhQLCAnJDFfJDInKS50b0xvd2VyQ2FzZSgpOwogIH0pOwogIC8qKgogICAgRGVmaW5lcyBzdHJpbmcgaGVscGVyIG1ldGhvZHMgaW5jbHVkaW5nIHN0cmluZyBmb3JtYXR0aW5nIGFuZCBsb2NhbGl6YXRpb24uCiAgICBVbmxlc3MgYEVtYmVyRU5WLkVYVEVORF9QUk9UT1RZUEVTLlN0cmluZ2AgaXMgYGZhbHNlYCB0aGVzZSBtZXRob2RzIHdpbGwgYWxzbyBiZQogICAgYWRkZWQgdG8gdGhlIGBTdHJpbmcucHJvdG90eXBlYCBhcyB3ZWxsLgogIAogICAgQGNsYXNzIFN0cmluZwogICAgQHB1YmxpYwogICovCgogIGZ1bmN0aW9uIF9mbXQoc3RyLCBmb3JtYXRzKSB7CiAgICAvLyBmaXJzdCwgcmVwbGFjZSBhbnkgT1JERVJFRCByZXBsYWNlbWVudHMuCiAgICB2YXIgaWR4ID0gMDsgLy8gdGhlIGN1cnJlbnQgaW5kZXggZm9yIG5vbi1udW1lcmljYWwgcmVwbGFjZW1lbnRzCgogICAgcmV0dXJuIHN0ci5yZXBsYWNlKC8lQChbMC05XSspPy9nLCBmdW5jdGlvbiAoX3MsIGFyZ0luZGV4KSB7CiAgICAgIHZhciBpID0gYXJnSW5kZXggPyBwYXJzZUludChhcmdJbmRleCwgMTApIC0gMSA6IGlkeCsrOwogICAgICB2YXIgciA9IGkgPCBmb3JtYXRzLmxlbmd0aCA/IGZvcm1hdHNbaV0gOiB1bmRlZmluZWQ7CiAgICAgIHJldHVybiB0eXBlb2YgciA9PT0gJ3N0cmluZycgPyByIDogciA9PT0gbnVsbCA/ICcobnVsbCknIDogciA9PT0gdW5kZWZpbmVkID8gJycgOiBTdHJpbmcocik7CiAgICB9KTsKICB9CiAgLyoqCiAgICBGb3JtYXRzIHRoZSBwYXNzZWQgc3RyaW5nLCBidXQgZmlyc3QgbG9va3MgdXAgdGhlIHN0cmluZyBpbiB0aGUgbG9jYWxpemVkCiAgICBzdHJpbmdzIGhhc2guIFRoaXMgaXMgYSBjb252ZW5pZW50IHdheSB0byBsb2NhbGl6ZSB0ZXh0LgogIAogICAgTm90ZSB0aGF0IGl0IGlzIHRyYWRpdGlvbmFsIGJ1dCBub3QgcmVxdWlyZWQgdG8gcHJlZml4IGxvY2FsaXplZCBzdHJpbmcKICAgIGtleXMgd2l0aCBhbiB1bmRlcnNjb3JlIG9yIG90aGVyIGNoYXJhY3RlciBzbyB5b3UgY2FuIGVhc2lseSBpZGVudGlmeQogICAgbG9jYWxpemVkIHN0cmluZ3MuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBsb2MgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAKICAgIEVtYmVyLlNUUklOR1MgPSB7CiAgICAgICdfSGVsbG8gV29ybGQnOiAnQm9uam91ciBsZSBtb25kZScsCiAgICAgICdfSGVsbG8gJUAgJUAnOiAnQm9uam91ciAlQCAlQCcKICAgIH07CiAgCiAgICBsb2MoIl9IZWxsbyBXb3JsZCIpOyAgLy8gJ0JvbmpvdXIgbGUgbW9uZGUnOwogICAgbG9jKCJfSGVsbG8gJUAgJUAiLCBbIkpvaG4iLCAiU21pdGgiXSk7ICAvLyAiQm9uam91ciBKb2huIFNtaXRoIjsKICAgIGBgYAogIAogICAgQG1ldGhvZCBsb2MKICAgIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byBmb3JtYXQKICAgIEBwYXJhbSB7QXJyYXl9IGZvcm1hdHMgT3B0aW9uYWwgYXJyYXkgb2YgcGFyYW1ldGVycyB0byBpbnRlcnBvbGF0ZSBpbnRvIHN0cmluZy4KICAgIEByZXR1cm4ge1N0cmluZ30gZm9ybWF0dGVkIHN0cmluZwogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiBsb2Moc3RyLCBmb3JtYXRzKSB7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZm9ybWF0cykgfHwgYXJndW1lbnRzLmxlbmd0aCA+IDIpIHsKICAgICAgZm9ybWF0cyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7CiAgICB9CgogICAgc3RyID0gKDAsIF9zdHJpbmdfcmVnaXN0cnkuZ2V0U3RyaW5nKShzdHIpIHx8IHN0cjsKICAgIHJldHVybiBfZm10KHN0ciwgZm9ybWF0cyk7CiAgfQogIC8qKgogICAgU3BsaXRzIGEgc3RyaW5nIGludG8gc2VwYXJhdGUgdW5pdHMgc2VwYXJhdGVkIGJ5IHNwYWNlcywgZWxpbWluYXRpbmcgYW55CiAgICBlbXB0eSBzdHJpbmdzIGluIHRoZSBwcm9jZXNzLiBUaGlzIGlzIGEgY29udmVuaWVuY2UgbWV0aG9kIGZvciBzcGxpdCB0aGF0CiAgICBpcyBtb3N0bHkgdXNlZnVsIHdoZW4gYXBwbGllZCB0byB0aGUgYFN0cmluZy5wcm90b3R5cGVgLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgdyB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogIAogICAgdygiYWxwaGEgYmV0YSBnYW1tYSIpLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7CiAgICAgIGNvbnNvbGUubG9nKGtleSk7CiAgICB9KTsKICAKICAgIC8vID4gYWxwaGEKICAgIC8vID4gYmV0YQogICAgLy8gPiBnYW1tYQogICAgYGBgCiAgCiAgICBAbWV0aG9kIHcKICAgIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byBzcGxpdAogICAgQHJldHVybiB7QXJyYXl9IGFycmF5IGNvbnRhaW5pbmcgdGhlIHNwbGl0IHN0cmluZ3MKICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gdyhzdHIpIHsKICAgIHJldHVybiBzdHIuc3BsaXQoL1xzKy8pOwogIH0KICAvKioKICAgIENvbnZlcnRzIGEgY2FtZWxpemVkIHN0cmluZyBpbnRvIGFsbCBsb3dlciBjYXNlIHNlcGFyYXRlZCBieSB1bmRlcnNjb3Jlcy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGRlY2FtZWxpemUgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAKICAgIGRlY2FtZWxpemUoJ2lubmVySFRNTCcpOyAgICAgICAgICAvLyAnaW5uZXJfaHRtbCcKICAgIGRlY2FtZWxpemUoJ2FjdGlvbl9uYW1lJyk7ICAgICAgICAvLyAnYWN0aW9uX25hbWUnCiAgICBkZWNhbWVsaXplKCdjc3MtY2xhc3MtbmFtZScpOyAgICAgLy8gJ2Nzcy1jbGFzcy1uYW1lJwogICAgZGVjYW1lbGl6ZSgnbXkgZmF2b3JpdGUgaXRlbXMnKTsgIC8vICdteSBmYXZvcml0ZSBpdGVtcycKICAgIGBgYAogIAogICAgQG1ldGhvZCBkZWNhbWVsaXplCiAgICBAcGFyYW0ge1N0cmluZ30gc3RyIFRoZSBzdHJpbmcgdG8gZGVjYW1lbGl6ZS4KICAgIEByZXR1cm4ge1N0cmluZ30gdGhlIGRlY2FtZWxpemVkIHN0cmluZy4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gZGVjYW1lbGl6ZShzdHIpIHsKICAgIHJldHVybiBERUNBTUVMSVpFX0NBQ0hFLmdldChzdHIpOwogIH0KICAvKioKICAgIFJlcGxhY2VzIHVuZGVyc2NvcmVzLCBzcGFjZXMsIG9yIGNhbWVsQ2FzZSB3aXRoIGRhc2hlcy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGRhc2hlcml6ZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogIAogICAgZGFzaGVyaXplKCdpbm5lckhUTUwnKTsgICAgICAgICAgICAgICAgLy8gJ2lubmVyLWh0bWwnCiAgICBkYXNoZXJpemUoJ2FjdGlvbl9uYW1lJyk7ICAgICAgICAgICAgICAvLyAnYWN0aW9uLW5hbWUnCiAgICBkYXNoZXJpemUoJ2Nzcy1jbGFzcy1uYW1lJyk7ICAgICAgICAgICAvLyAnY3NzLWNsYXNzLW5hbWUnCiAgICBkYXNoZXJpemUoJ215IGZhdm9yaXRlIGl0ZW1zJyk7ICAgICAgICAvLyAnbXktZmF2b3JpdGUtaXRlbXMnCiAgICBkYXNoZXJpemUoJ3ByaXZhdGVEb2NzL293bmVySW52b2ljZSc7ICAvLyAncHJpdmF0ZS1kb2NzL293bmVyLWludm9pY2UnCiAgICBgYGAKICAKICAgIEBtZXRob2QgZGFzaGVyaXplCiAgICBAcGFyYW0ge1N0cmluZ30gc3RyIFRoZSBzdHJpbmcgdG8gZGFzaGVyaXplLgogICAgQHJldHVybiB7U3RyaW5nfSB0aGUgZGFzaGVyaXplZCBzdHJpbmcuCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGRhc2hlcml6ZShzdHIpIHsKICAgIHJldHVybiBTVFJJTkdfREFTSEVSSVpFX0NBQ0hFLmdldChzdHIpOwogIH0KICAvKioKICAgIFJldHVybnMgdGhlIGxvd2VyQ2FtZWxDYXNlIGZvcm0gb2YgYSBzdHJpbmcuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBjYW1lbGl6ZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogIAogICAgY2FtZWxpemUoJ2lubmVySFRNTCcpOyAgICAgICAgICAgICAgICAgICAvLyAnaW5uZXJIVE1MJwogICAgY2FtZWxpemUoJ2FjdGlvbl9uYW1lJyk7ICAgICAgICAgICAgICAgICAvLyAnYWN0aW9uTmFtZScKICAgIGNhbWVsaXplKCdjc3MtY2xhc3MtbmFtZScpOyAgICAgICAgICAgICAgLy8gJ2Nzc0NsYXNzTmFtZScKICAgIGNhbWVsaXplKCdteSBmYXZvcml0ZSBpdGVtcycpOyAgICAgICAgICAgLy8gJ215RmF2b3JpdGVJdGVtcycKICAgIGNhbWVsaXplKCdNeSBGYXZvcml0ZSBJdGVtcycpOyAgICAgICAgICAgLy8gJ215RmF2b3JpdGVJdGVtcycKICAgIGNhbWVsaXplKCdwcml2YXRlLWRvY3Mvb3duZXItaW52b2ljZScpOyAgLy8gJ3ByaXZhdGVEb2NzL293bmVySW52b2ljZScKICAgIGBgYAogIAogICAgQG1ldGhvZCBjYW1lbGl6ZQogICAgQHBhcmFtIHtTdHJpbmd9IHN0ciBUaGUgc3RyaW5nIHRvIGNhbWVsaXplLgogICAgQHJldHVybiB7U3RyaW5nfSB0aGUgY2FtZWxpemVkIHN0cmluZy4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gY2FtZWxpemUoc3RyKSB7CiAgICByZXR1cm4gQ0FNRUxJWkVfQ0FDSEUuZ2V0KHN0cik7CiAgfQogIC8qKgogICAgUmV0dXJucyB0aGUgVXBwZXJDYW1lbENhc2UgZm9ybSBvZiBhIHN0cmluZy4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGNsYXNzaWZ5IH0gZnJvbSAnQGVtYmVyL3N0cmluZyc7CiAgCiAgICBjbGFzc2lmeSgnaW5uZXJIVE1MJyk7ICAgICAgICAgICAgICAgICAgIC8vICdJbm5lckhUTUwnCiAgICBjbGFzc2lmeSgnYWN0aW9uX25hbWUnKTsgICAgICAgICAgICAgICAgIC8vICdBY3Rpb25OYW1lJwogICAgY2xhc3NpZnkoJ2Nzcy1jbGFzcy1uYW1lJyk7ICAgICAgICAgICAgICAvLyAnQ3NzQ2xhc3NOYW1lJwogICAgY2xhc3NpZnkoJ215IGZhdm9yaXRlIGl0ZW1zJyk7ICAgICAgICAgICAvLyAnTXlGYXZvcml0ZUl0ZW1zJwogICAgY2xhc3NpZnkoJ3ByaXZhdGUtZG9jcy9vd25lci1pbnZvaWNlJyk7ICAvLyAnUHJpdmF0ZURvY3MvT3duZXJJbnZvaWNlJwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGNsYXNzaWZ5CiAgICBAcGFyYW0ge1N0cmluZ30gc3RyIHRoZSBzdHJpbmcgdG8gY2xhc3NpZnkKICAgIEByZXR1cm4ge1N0cmluZ30gdGhlIGNsYXNzaWZpZWQgc3RyaW5nCiAgICBAcHVibGljCiAgKi8KCgogIGZ1bmN0aW9uIGNsYXNzaWZ5KHN0cikgewogICAgcmV0dXJuIENMQVNTSUZZX0NBQ0hFLmdldChzdHIpOwogIH0KICAvKioKICAgIE1vcmUgZ2VuZXJhbCB0aGFuIGRlY2FtZWxpemUuIFJldHVybnMgdGhlIGxvd2VyXF9jYXNlXF9hbmRcX3VuZGVyc2NvcmVkCiAgICBmb3JtIG9mIGEgc3RyaW5nLgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgdW5kZXJzY29yZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogIAogICAgdW5kZXJzY29yZSgnaW5uZXJIVE1MJyk7ICAgICAgICAgICAgICAgICAvLyAnaW5uZXJfaHRtbCcKICAgIHVuZGVyc2NvcmUoJ2FjdGlvbl9uYW1lJyk7ICAgICAgICAgICAgICAgLy8gJ2FjdGlvbl9uYW1lJwogICAgdW5kZXJzY29yZSgnY3NzLWNsYXNzLW5hbWUnKTsgICAgICAgICAgICAvLyAnY3NzX2NsYXNzX25hbWUnCiAgICB1bmRlcnNjb3JlKCdteSBmYXZvcml0ZSBpdGVtcycpOyAgICAgICAgIC8vICdteV9mYXZvcml0ZV9pdGVtcycKICAgIHVuZGVyc2NvcmUoJ3ByaXZhdGVEb2NzL293bmVySW52b2ljZScpOyAgLy8gJ3ByaXZhdGVfZG9jcy9vd25lcl9pbnZvaWNlJwogICAgYGBgCiAgCiAgICBAbWV0aG9kIHVuZGVyc2NvcmUKICAgIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byB1bmRlcnNjb3JlLgogICAgQHJldHVybiB7U3RyaW5nfSB0aGUgdW5kZXJzY29yZWQgc3RyaW5nLgogICAgQHB1YmxpYwogICovCgoKICBmdW5jdGlvbiB1bmRlcnNjb3JlKHN0cikgewogICAgcmV0dXJuIFVOREVSU0NPUkVfQ0FDSEUuZ2V0KHN0cik7CiAgfQogIC8qKgogICAgUmV0dXJucyB0aGUgQ2FwaXRhbGl6ZWQgZm9ybSBvZiBhIHN0cmluZwogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgY2FwaXRhbGl6ZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogIAogICAgY2FwaXRhbGl6ZSgnaW5uZXJIVE1MJykgICAgICAgICAgICAgICAgIC8vICdJbm5lckhUTUwnCiAgICBjYXBpdGFsaXplKCdhY3Rpb25fbmFtZScpICAgICAgICAgICAgICAgLy8gJ0FjdGlvbl9uYW1lJwogICAgY2FwaXRhbGl6ZSgnY3NzLWNsYXNzLW5hbWUnKSAgICAgICAgICAgIC8vICdDc3MtY2xhc3MtbmFtZScKICAgIGNhcGl0YWxpemUoJ215IGZhdm9yaXRlIGl0ZW1zJykgICAgICAgICAvLyAnTXkgZmF2b3JpdGUgaXRlbXMnCiAgICBjYXBpdGFsaXplKCdwcml2YXRlRG9jcy9vd25lckludm9pY2UnKTsgLy8gJ1ByaXZhdGVEb2NzL293bmVySW52b2ljZScKICAgIGBgYAogIAogICAgQG1ldGhvZCBjYXBpdGFsaXplCiAgICBAcGFyYW0ge1N0cmluZ30gc3RyIFRoZSBzdHJpbmcgdG8gY2FwaXRhbGl6ZS4KICAgIEByZXR1cm4ge1N0cmluZ30gVGhlIGNhcGl0YWxpemVkIHN0cmluZy4KICAgIEBwdWJsaWMKICAqLwoKCiAgZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHIpIHsKICAgIHJldHVybiBDQVBJVEFMSVpFX0NBQ0hFLmdldChzdHIpOwogIH0KCiAgaWYgKF9lbnZpcm9ubWVudC5FTlYuRVhURU5EX1BST1RPVFlQRVMuU3RyaW5nKSB7CiAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhTdHJpbmcucHJvdG90eXBlLCB7CiAgICAgIC8qKgogICAgICAgIFNlZSBbU3RyaW5nLnddKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvU3RyaW5nL21ldGhvZHMvdz9hbmNob3I9dykuCiAgICAgICAgICAgICBAbWV0aG9kIHcKICAgICAgICBAZm9yIEBlbWJlci9zdHJpbmcKICAgICAgICBAc3RhdGljCiAgICAgICAgQHByaXZhdGUKICAgICAgKi8KICAgICAgdzogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0ZWFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgcmV0dXJuIHcodGhpcyk7CiAgICAgICAgfQogICAgICB9LAoKICAgICAgLyoqCiAgICAgICAgU2VlIFtTdHJpbmcubG9jXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1N0cmluZy9tZXRob2RzL2xvYz9hbmNob3I9bG9jKS4KICAgICAgICAgICAgIEBtZXRob2QgbG9jCiAgICAgICAgQGZvciBAZW1iZXIvc3RyaW5nCiAgICAgICAgQHN0YXRpYwogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIGxvYzogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0ZWFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgICAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIGxvYyh0aGlzLCBhcmdzKTsKICAgICAgICB9CiAgICAgIH0sCgogICAgICAvKioKICAgICAgICBTZWUgW1N0cmluZy5jYW1lbGl6ZV0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9TdHJpbmcvbWV0aG9kcy9jYW1lbGl6ZT9hbmNob3I9Y2FtZWxpemUpLgogICAgICAgICAgICAgQG1ldGhvZCBjYW1lbGl6ZQogICAgICAgIEBmb3IgQGVtYmVyL3N0cmluZwogICAgICAgIEBzdGF0aWMKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBjYW1lbGl6ZTogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0ZWFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgcmV0dXJuIGNhbWVsaXplKHRoaXMpOwogICAgICAgIH0KICAgICAgfSwKCiAgICAgIC8qKgogICAgICAgIFNlZSBbU3RyaW5nLmRlY2FtZWxpemVdKC9lbWJlci9yZWxlYXNlL2NsYXNzZXMvU3RyaW5nL21ldGhvZHMvZGVjYW1lbGl6ZT9hbmNob3I9ZGVjYW1lbGl6ZSkuCiAgICAgICAgICAgICBAbWV0aG9kIGRlY2FtZWxpemUKICAgICAgICBAZm9yIEBlbWJlci9zdHJpbmcKICAgICAgICBAc3RhdGljCiAgICAgICAgQHByaXZhdGUKICAgICAgKi8KICAgICAgZGVjYW1lbGl6ZTogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0ZWFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgcmV0dXJuIGRlY2FtZWxpemUodGhpcyk7CiAgICAgICAgfQogICAgICB9LAoKICAgICAgLyoqCiAgICAgICAgU2VlIFtTdHJpbmcuZGFzaGVyaXplXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1N0cmluZy9tZXRob2RzL2Rhc2hlcml6ZT9hbmNob3I9ZGFzaGVyaXplKS4KICAgICAgICAgICAgIEBtZXRob2QgZGFzaGVyaXplCiAgICAgICAgQGZvciBAZW1iZXIvc3RyaW5nCiAgICAgICAgQHN0YXRpYwogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIGRhc2hlcml6ZTogewogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0ZWFibGU6IHRydWUsCiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICAgICAgcmV0dXJuIGRhc2hlcml6ZSh0aGlzKTsKICAgICAgICB9CiAgICAgIH0sCgogICAgICAvKioKICAgICAgICBTZWUgW1N0cmluZy51bmRlcnNjb3JlXSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1N0cmluZy9tZXRob2RzL3VuZGVyc2NvcmU/YW5jaG9yPXVuZGVyc2NvcmUpLgogICAgICAgICAgICAgQG1ldGhvZCB1bmRlcnNjb3JlCiAgICAgICAgQGZvciBAZW1iZXIvc3RyaW5nCiAgICAgICAgQHN0YXRpYwogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIHVuZGVyc2NvcmU6IHsKICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsCiAgICAgICAgd3JpdGVhYmxlOiB0cnVlLAogICAgICAgIHZhbHVlOiBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgICAgIHJldHVybiB1bmRlcnNjb3JlKHRoaXMpOwogICAgICAgIH0KICAgICAgfSwKCiAgICAgIC8qKgogICAgICAgIFNlZSBbU3RyaW5nLmNsYXNzaWZ5XSgvZW1iZXIvcmVsZWFzZS9jbGFzc2VzL1N0cmluZy9tZXRob2RzL2NsYXNzaWZ5P2FuY2hvcj1jbGFzc2lmeSkuCiAgICAgICAgICAgICBAbWV0aG9kIGNsYXNzaWZ5CiAgICAgICAgQGZvciBAZW1iZXIvc3RyaW5nCiAgICAgICAgQHN0YXRpYwogICAgICAgIEBwcml2YXRlCiAgICAgICovCiAgICAgIGNsYXNzaWZ5OiB7CiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgIGVudW1lcmFibGU6IGZhbHNlLAogICAgICAgIHdyaXRlYWJsZTogdHJ1ZSwKICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgICAgICByZXR1cm4gY2xhc3NpZnkodGhpcyk7CiAgICAgICAgfQogICAgICB9LAoKICAgICAgLyoqCiAgICAgICAgU2VlIFtTdHJpbmcuY2FwaXRhbGl6ZV0oL2VtYmVyL3JlbGVhc2UvY2xhc3Nlcy9TdHJpbmcvbWV0aG9kcy9jYXBpdGFsaXplP2FuY2hvcj1jYXBpdGFsaXplKS4KICAgICAgICAgICAgIEBtZXRob2QgY2FwaXRhbGl6ZQogICAgICAgIEBmb3IgQGVtYmVyL3N0cmluZwogICAgICAgIEBzdGF0aWMKICAgICAgICBAcHJpdmF0ZQogICAgICAqLwogICAgICBjYXBpdGFsaXplOiB7CiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgIGVudW1lcmFibGU6IGZhbHNlLAogICAgICAgIHdyaXRlYWJsZTogdHJ1ZSwKICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgICAgICByZXR1cm4gY2FwaXRhbGl6ZSh0aGlzKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0pOwogIH0KfSk7CmRlZmluZSgiQGVtYmVyL3N0cmluZy9saWIvc3RyaW5nX3JlZ2lzdHJ5IiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuc2V0U3RyaW5ncyA9IHNldFN0cmluZ3M7CiAgX2V4cG9ydHMuZ2V0U3RyaW5ncyA9IGdldFN0cmluZ3M7CiAgX2V4cG9ydHMuZ2V0U3RyaW5nID0gZ2V0U3RyaW5nOwogIC8vIFNUQVRFIHdpdGhpbiBhIG1vZHVsZSBpcyBmcm93bmVkIHVwb24sIHRoaXMgZXhpc3RzCiAgLy8gdG8gc3VwcG9ydCBFbWJlci5TVFJJTkdTIGJ1dCBzaGllbGQgZW1iZXIgaW50ZXJuYWxzIGZyb20gdGhpcyBsZWdhY3kgZ2xvYmFsCiAgLy8gQVBJLgogIHZhciBTVFJJTkdTID0ge307CgogIGZ1bmN0aW9uIHNldFN0cmluZ3Moc3RyaW5ncykgewogICAgU1RSSU5HUyA9IHN0cmluZ3M7CiAgfQoKICBmdW5jdGlvbiBnZXRTdHJpbmdzKCkgewogICAgcmV0dXJuIFNUUklOR1M7CiAgfQoKICBmdW5jdGlvbiBnZXRTdHJpbmcobmFtZSkgewogICAgcmV0dXJuIFNUUklOR1NbbmFtZV07CiAgfQp9KTsKZGVmaW5lKCJAZ2xpbW1lci9lbmNvZGVyIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuSW5zdHJ1Y3Rpb25FbmNvZGVyID0gdm9pZCAwOwoKICB2YXIgSW5zdHJ1Y3Rpb25FbmNvZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSW5zdHJ1Y3Rpb25FbmNvZGVyKGJ1ZmZlcikgewogICAgICB0aGlzLmJ1ZmZlciA9IGJ1ZmZlcjsKICAgICAgdGhpcy50eXBlUG9zID0gMDsKICAgICAgdGhpcy5zaXplID0gMDsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gSW5zdHJ1Y3Rpb25FbmNvZGVyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKHR5cGUsIG1hY2hpbmUpIHsKICAgICAgaWYgKHR5cGUgPiAyNTUKICAgICAgLyogVFlQRV9TSVpFICovCiAgICAgICkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJPcGNvZGUgdHlwZSBvdmVyIDgtYml0cy4gR290ICIgKyB0eXBlICsgIi4iKTsKICAgICAgICB9CgogICAgICB0aGlzLmJ1ZmZlci5wdXNoKHR5cGUgfCBtYWNoaW5lIHwgYXJndW1lbnRzLmxlbmd0aCAtIDIgPDwgOAogICAgICAvKiBBUkdfU0hJRlQgKi8KICAgICAgKTsKICAgICAgdGhpcy50eXBlUG9zID0gdGhpcy5idWZmZXIubGVuZ3RoIC0gMTsKCiAgICAgIGZvciAodmFyIGkgPSAyOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIG9wID0gYXJndW1lbnRzW2ldOwoKICAgICAgICBpZiAodHlwZW9mIG9wID09PSAnbnVtYmVyJyAmJiBvcCA+IDQyOTQ5NjcyOTUKICAgICAgICAvKiBNQVhfU0laRSAqLwogICAgICAgICkgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIk9wZXJhbmQgb3ZlciAzMi1iaXRzLiBHb3QgIiArIG9wICsgIi4iKTsKICAgICAgICAgIH0KCiAgICAgICAgdGhpcy5idWZmZXIucHVzaChvcCk7CiAgICAgIH0KCiAgICAgIHRoaXMuc2l6ZSA9IHRoaXMuYnVmZmVyLmxlbmd0aDsKICAgIH07CgogICAgX3Byb3RvLnBhdGNoID0gZnVuY3Rpb24gcGF0Y2gocG9zaXRpb24sIHRhcmdldCkgewogICAgICBpZiAodGhpcy5idWZmZXJbcG9zaXRpb24gKyAxXSA9PT0gLTEpIHsKICAgICAgICB0aGlzLmJ1ZmZlcltwb3NpdGlvbiArIDFdID0gdGFyZ2V0OwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcignVHJ5aW5nIHRvIHBhdGNoIG9wZXJhbmQgaW4gcG9wdWxhdGVkIHNsb3QgaW5zdGVhZCBvZiBhIHJlc2VydmVkIHNsb3QuJyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnBhdGNoV2l0aCA9IGZ1bmN0aW9uIHBhdGNoV2l0aChwb3NpdGlvbiwgdGFyZ2V0LCBvcGVyYW5kKSB7CiAgICAgIGlmICh0aGlzLmJ1ZmZlcltwb3NpdGlvbiArIDFdID09PSAtMSkgewogICAgICAgIHRoaXMuYnVmZmVyW3Bvc2l0aW9uICsgMV0gPSB0YXJnZXQ7CiAgICAgICAgdGhpcy5idWZmZXJbcG9zaXRpb24gKyAyXSA9IG9wZXJhbmQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUcnlpbmcgdG8gcGF0Y2ggb3BlcmFuZCBpbiBwb3B1bGF0ZWQgc2xvdCBpbnN0ZWFkIG9mIGEgcmVzZXJ2ZWQgc2xvdC4nKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gSW5zdHJ1Y3Rpb25FbmNvZGVyOwogIH0oKTsKCiAgX2V4cG9ydHMuSW5zdHJ1Y3Rpb25FbmNvZGVyID0gSW5zdHJ1Y3Rpb25FbmNvZGVyOwp9KTsKZGVmaW5lKCJAZ2xpbW1lci9sb3ctbGV2ZWwiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5TdGFjayA9IF9leHBvcnRzLlN0b3JhZ2UgPSB2b2lkIDA7CgogIHZhciBTdG9yYWdlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gU3RvcmFnZSgpIHsKICAgICAgdGhpcy5hcnJheSA9IFtdOwogICAgICB0aGlzLm5leHQgPSAwOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBTdG9yYWdlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uYWRkID0gZnVuY3Rpb24gYWRkKGVsZW1lbnQpIHsKICAgICAgdmFyIHNsb3QgPSB0aGlzLm5leHQsCiAgICAgICAgICBhcnJheSA9IHRoaXMuYXJyYXk7CgogICAgICBpZiAoc2xvdCA9PT0gYXJyYXkubGVuZ3RoKSB7CiAgICAgICAgdGhpcy5uZXh0Kys7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIHByZXYgPSBhcnJheVtzbG90XTsKICAgICAgICB0aGlzLm5leHQgPSBwcmV2OwogICAgICB9CgogICAgICB0aGlzLmFycmF5W3Nsb3RdID0gZWxlbWVudDsKICAgICAgcmV0dXJuIHNsb3Q7CiAgICB9OwoKICAgIF9wcm90by5kZXJlZiA9IGZ1bmN0aW9uIGRlcmVmKHBvaW50ZXIpIHsKICAgICAgcmV0dXJuIHRoaXMuYXJyYXlbcG9pbnRlcl07CiAgICB9OwoKICAgIF9wcm90by5kcm9wID0gZnVuY3Rpb24gZHJvcChwb2ludGVyKSB7CiAgICAgIHRoaXMuYXJyYXlbcG9pbnRlcl0gPSB0aGlzLm5leHQ7CiAgICAgIHRoaXMubmV4dCA9IHBvaW50ZXI7CiAgICB9OwoKICAgIHJldHVybiBTdG9yYWdlOwogIH0oKTsKCiAgX2V4cG9ydHMuU3RvcmFnZSA9IFN0b3JhZ2U7CgogIHZhciBTdGFjayA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFN0YWNrKHZlYykgewogICAgICBpZiAodmVjID09PSB2b2lkIDApIHsKICAgICAgICB2ZWMgPSBbXTsKICAgICAgfQoKICAgICAgdGhpcy52ZWMgPSB2ZWM7CiAgICB9CgogICAgdmFyIF9wcm90bzIgPSBTdGFjay5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5jbG9uZSA9IGZ1bmN0aW9uIGNsb25lKCkgewogICAgICByZXR1cm4gbmV3IFN0YWNrKHRoaXMudmVjLnNsaWNlKCkpOwogICAgfTsKCiAgICBfcHJvdG8yLnNsaWNlRnJvbSA9IGZ1bmN0aW9uIHNsaWNlRnJvbShzdGFydCkgewogICAgICByZXR1cm4gbmV3IFN0YWNrKHRoaXMudmVjLnNsaWNlKHN0YXJ0KSk7CiAgICB9OwoKICAgIF9wcm90bzIuc2xpY2UgPSBmdW5jdGlvbiBzbGljZShzdGFydCwgZW5kKSB7CiAgICAgIHJldHVybiBuZXcgU3RhY2sodGhpcy52ZWMuc2xpY2Uoc3RhcnQsIGVuZCkpOwogICAgfTsKCiAgICBfcHJvdG8yLmNvcHkgPSBmdW5jdGlvbiBjb3B5KGZyb20sIHRvKSB7CiAgICAgIHRoaXMudmVjW3RvXSA9IHRoaXMudmVjW2Zyb21dOwogICAgfSAvLyBUT0RPOiBob3cgdG8gbW9kZWwgdTY0IGFyZ3VtZW50PwogICAgOwoKICAgIF9wcm90bzIud3JpdGVSYXcgPSBmdW5jdGlvbiB3cml0ZVJhdyhwb3MsIHZhbHVlKSB7CiAgICAgIC8vIFRPRE86IEdyb3c/CiAgICAgIHRoaXMudmVjW3Bvc10gPSB2YWx1ZTsKICAgIH0gLy8gVE9ETzogcGFydGlhbGx5IGRlY29kZWQgZW51bT8KICAgIDsKCiAgICBfcHJvdG8yLmdldFJhdyA9IGZ1bmN0aW9uIGdldFJhdyhwb3MpIHsKICAgICAgcmV0dXJuIHRoaXMudmVjW3Bvc107CiAgICB9OwoKICAgIF9wcm90bzIucmVzZXQgPSBmdW5jdGlvbiByZXNldCgpIHsKICAgICAgdGhpcy52ZWMubGVuZ3RoID0gMDsKICAgIH07CgogICAgX3Byb3RvMi5sZW4gPSBmdW5jdGlvbiBsZW4oKSB7CiAgICAgIHJldHVybiB0aGlzLnZlYy5sZW5ndGg7CiAgICB9OwoKICAgIHJldHVybiBTdGFjazsKICB9KCk7CgogIF9leHBvcnRzLlN0YWNrID0gU3RhY2s7Cn0pOwpkZWZpbmUoIkBnbGltbWVyL25vZGUiLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiLCAiQGdsaW1tZXIvcnVudGltZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfcnVudGltZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuc2VyaWFsaXplQnVpbGRlciA9IHNlcmlhbGl6ZUJ1aWxkZXI7CiAgX2V4cG9ydHMuTm9kZURPTVRyZWVDb25zdHJ1Y3Rpb24gPSB2b2lkIDA7CgogIHZhciBOb2RlRE9NVHJlZUNvbnN0cnVjdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRE9NVHJlZUNvbnN0cnVjdGlvbikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE5vZGVET01UcmVlQ29uc3RydWN0aW9uLCBfRE9NVHJlZUNvbnN0cnVjdGlvbik7CgogICAgZnVuY3Rpb24gTm9kZURPTVRyZWVDb25zdHJ1Y3Rpb24oZG9jKSB7CiAgICAgIHJldHVybiBfRE9NVHJlZUNvbnN0cnVjdGlvbi5jYWxsKHRoaXMsIGRvYykgfHwgdGhpczsKICAgIH0gLy8gb3ZlcnJpZGUgdG8gcHJldmVudCB1c2FnZSBvZiBgdGhpcy5kb2N1bWVudGAgdW50aWwgYWZ0ZXIgdGhlIGNvbnN0cnVjdG9yCgoKICAgIHZhciBfcHJvdG8gPSBOb2RlRE9NVHJlZUNvbnN0cnVjdGlvbi5wcm90b3R5cGU7CgogICAgX3Byb3RvLnNldHVwVXNlbGVzc0VsZW1lbnQgPSBmdW5jdGlvbiBzZXR1cFVzZWxlc3NFbGVtZW50KCkge30gLy8gb3ZlcnJpZGUgdG8gYXZvaWQgU1ZHIGRldGVjdGlvbi93b3JrIHdoZW4gaW4gbm9kZSAodGhpcyBpcyBub3QgbmVlZGVkIGluIFNTUikKICAgIDsKCiAgICBfcHJvdG8uY3JlYXRlRWxlbWVudCA9IGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodGFnKSB7CiAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTsKICAgIH0gLy8gb3ZlcnJpZGUgdG8gYXZvaWQgbmFtZXNwYWNlIHNoZW5hbmlnYW5zIHdoZW4gaW4gbm9kZSAodGhpcyBpcyBub3QgbmVlZGVkIGluIFNTUikKICAgIDsKCiAgICBfcHJvdG8uc2V0QXR0cmlidXRlID0gZnVuY3Rpb24gc2V0QXR0cmlidXRlKGVsZW1lbnQsIG5hbWUsIHZhbHVlKSB7CiAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlKTsKICAgIH07CgogICAgcmV0dXJuIE5vZGVET01UcmVlQ29uc3RydWN0aW9uOwogIH0oX3J1bnRpbWUuRE9NVHJlZUNvbnN0cnVjdGlvbik7CgogIF9leHBvcnRzLk5vZGVET01UcmVlQ29uc3RydWN0aW9uID0gTm9kZURPTVRyZWVDb25zdHJ1Y3Rpb247CiAgdmFyIFRFWFRfTk9ERSA9IDM7CgogIGZ1bmN0aW9uIGN1cnJlbnROb2RlKGN1cnNvcikgewogICAgdmFyIGVsZW1lbnQgPSBjdXJzb3IuZWxlbWVudCwKICAgICAgICBuZXh0U2libGluZyA9IGN1cnNvci5uZXh0U2libGluZzsKCiAgICBpZiAobmV4dFNpYmxpbmcgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIGVsZW1lbnQubGFzdENoaWxkOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG5leHRTaWJsaW5nLnByZXZpb3VzU2libGluZzsKICAgIH0KICB9CgogIHZhciBTZXJpYWxpemVCdWlsZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9OZXdFbGVtZW50QnVpbGRlcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFNlcmlhbGl6ZUJ1aWxkZXIsIF9OZXdFbGVtZW50QnVpbGRlcik7CgogICAgZnVuY3Rpb24gU2VyaWFsaXplQnVpbGRlcigpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfTmV3RWxlbWVudEJ1aWxkZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpcy5zZXJpYWxpemVCbG9ja0RlcHRoID0gMDsKICAgICAgcmV0dXJuIF90aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8yID0gU2VyaWFsaXplQnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5fX29wZW5CbG9jayA9IGZ1bmN0aW9uIF9fb3BlbkJsb2NrKCkgewogICAgICB2YXIgdGFnTmFtZSA9IHRoaXMuZWxlbWVudC50YWdOYW1lOwoKICAgICAgaWYgKHRhZ05hbWUgIT09ICdUSVRMRScgJiYgdGFnTmFtZSAhPT0gJ1NDUklQVCcgJiYgdGFnTmFtZSAhPT0gJ1NUWUxFJykgewogICAgICAgIHZhciBkZXB0aCA9IHRoaXMuc2VyaWFsaXplQmxvY2tEZXB0aCsrOwoKICAgICAgICB0aGlzLl9fYXBwZW5kQ29tbWVudCgiJStiOiIgKyBkZXB0aCArICIlIik7CiAgICAgIH0KCiAgICAgIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuX19vcGVuQmxvY2suY2FsbCh0aGlzKTsKICAgIH07CgogICAgX3Byb3RvMi5fX2Nsb3NlQmxvY2sgPSBmdW5jdGlvbiBfX2Nsb3NlQmxvY2soKSB7CiAgICAgIHZhciB0YWdOYW1lID0gdGhpcy5lbGVtZW50LnRhZ05hbWU7CgogICAgICBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fY2xvc2VCbG9jay5jYWxsKHRoaXMpOwoKICAgICAgaWYgKHRhZ05hbWUgIT09ICdUSVRMRScgJiYgdGFnTmFtZSAhPT0gJ1NDUklQVCcgJiYgdGFnTmFtZSAhPT0gJ1NUWUxFJykgewogICAgICAgIHZhciBkZXB0aCA9IC0tdGhpcy5zZXJpYWxpemVCbG9ja0RlcHRoOwoKICAgICAgICB0aGlzLl9fYXBwZW5kQ29tbWVudCgiJS1iOiIgKyBkZXB0aCArICIlIik7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMi5fX2FwcGVuZEhUTUwgPSBmdW5jdGlvbiBfX2FwcGVuZEhUTUwoaHRtbCkgewogICAgICB2YXIgdGFnTmFtZSA9IHRoaXMuZWxlbWVudC50YWdOYW1lOwoKICAgICAgaWYgKHRhZ05hbWUgPT09ICdUSVRMRScgfHwgdGFnTmFtZSA9PT0gJ1NDUklQVCcgfHwgdGFnTmFtZSA9PT0gJ1NUWUxFJykgewogICAgICAgIHJldHVybiBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fYXBwZW5kSFRNTC5jYWxsKHRoaXMsIGh0bWwpOwogICAgICB9IC8vIERvIHdlIG5lZWQgdG8gcnVuIHRoZSBodG1sIHRva2VuaXplciBoZXJlPwoKCiAgICAgIHZhciBmaXJzdCA9IHRoaXMuX19hcHBlbmRDb21tZW50KCclZ2xtciUnKTsKCiAgICAgIGlmICh0YWdOYW1lID09PSAnVEFCTEUnKSB7CiAgICAgICAgdmFyIG9wZW5JbmRleCA9IGh0bWwuaW5kZXhPZignPCcpOwoKICAgICAgICBpZiAob3BlbkluZGV4ID4gLTEpIHsKICAgICAgICAgIHZhciB0ciA9IGh0bWwuc2xpY2Uob3BlbkluZGV4ICsgMSwgb3BlbkluZGV4ICsgMyk7CgogICAgICAgICAgaWYgKHRyID09PSAndHInKSB7CiAgICAgICAgICAgIGh0bWwgPSAiPHRib2R5PiIgKyBodG1sICsgIjwvdGJvZHk+IjsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChodG1sID09PSAnJykgewogICAgICAgIHRoaXMuX19hcHBlbmRDb21tZW50KCclICUnKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fYXBwZW5kSFRNTC5jYWxsKHRoaXMsIGh0bWwpOwogICAgICB9CgogICAgICB2YXIgbGFzdCA9IHRoaXMuX19hcHBlbmRDb21tZW50KCclZ2xtciUnKTsKCiAgICAgIHJldHVybiBuZXcgX3J1bnRpbWUuQ29uY3JldGVCb3VuZHModGhpcy5lbGVtZW50LCBmaXJzdCwgbGFzdCk7CiAgICB9OwoKICAgIF9wcm90bzIuX19hcHBlbmRUZXh0ID0gZnVuY3Rpb24gX19hcHBlbmRUZXh0KHN0cmluZykgewogICAgICB2YXIgdGFnTmFtZSA9IHRoaXMuZWxlbWVudC50YWdOYW1lOwogICAgICB2YXIgY3VycmVudCA9IGN1cnJlbnROb2RlKHRoaXMpOwoKICAgICAgaWYgKHRhZ05hbWUgPT09ICdUSVRMRScgfHwgdGFnTmFtZSA9PT0gJ1NDUklQVCcgfHwgdGFnTmFtZSA9PT0gJ1NUWUxFJykgewogICAgICAgIHJldHVybiBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fYXBwZW5kVGV4dC5jYWxsKHRoaXMsIHN0cmluZyk7CiAgICAgIH0gZWxzZSBpZiAoc3RyaW5nID09PSAnJykgewogICAgICAgIHJldHVybiB0aGlzLl9fYXBwZW5kQ29tbWVudCgnJSAlJyk7CiAgICAgIH0gZWxzZSBpZiAoY3VycmVudCAmJiBjdXJyZW50Lm5vZGVUeXBlID09PSBURVhUX05PREUpIHsKICAgICAgICB0aGlzLl9fYXBwZW5kQ29tbWVudCgnJXwlJyk7CiAgICAgIH0KCiAgICAgIHJldHVybiBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fYXBwZW5kVGV4dC5jYWxsKHRoaXMsIHN0cmluZyk7CiAgICB9OwoKICAgIF9wcm90bzIuY2xvc2VFbGVtZW50ID0gZnVuY3Rpb24gY2xvc2VFbGVtZW50KCkgewogICAgICBpZiAodGhpcy5lbGVtZW50WyduZWVkc0V4dHJhQ2xvc2UnXSA9PT0gdHJ1ZSkgewogICAgICAgIHRoaXMuZWxlbWVudFsnbmVlZHNFeHRyYUNsb3NlJ10gPSBmYWxzZTsKCiAgICAgICAgX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS5jbG9zZUVsZW1lbnQuY2FsbCh0aGlzKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuY2xvc2VFbGVtZW50LmNhbGwodGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzIub3BlbkVsZW1lbnQgPSBmdW5jdGlvbiBvcGVuRWxlbWVudCh0YWcpIHsKICAgICAgaWYgKHRhZyA9PT0gJ3RyJykgewogICAgICAgIGlmICh0aGlzLmVsZW1lbnQudGFnTmFtZSAhPT0gJ1RCT0RZJyAmJiB0aGlzLmVsZW1lbnQudGFnTmFtZSAhPT0gJ1RIRUFEJyAmJiB0aGlzLmVsZW1lbnQudGFnTmFtZSAhPT0gJ1RGT09UJykgewogICAgICAgICAgdGhpcy5vcGVuRWxlbWVudCgndGJvZHknKTsgLy8gVGhpcyBwcmV2ZW50cyB0aGUgY2xvc2VCbG9jayBjb21tZW50IGZyb20gYmVpbmcgcmUtcGFyZW50ZWQKICAgICAgICAgIC8vIHVuZGVyIHRoZSBhdXRvIGluc2VydGVkIHRib2R5LiBSZWh5ZHJhdGlvbiBidWlsZGVyIG5lZWRzIHRvCiAgICAgICAgICAvLyBhY2NvdW50IGZvciB0aGUgaW5zZXJ0aW9uIHNpbmNlIGl0IGlzIGluamVjdGVkIGhlcmUgYW5kIG5vdAogICAgICAgICAgLy8gcmVhbGx5IGluIHRoZSB0ZW1wbGF0ZS4KCiAgICAgICAgICB0aGlzLmNvbnN0cnVjdGluZ1snbmVlZHNFeHRyYUNsb3NlJ10gPSB0cnVlOwogICAgICAgICAgdGhpcy5mbHVzaEVsZW1lbnQobnVsbCk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS5vcGVuRWxlbWVudC5jYWxsKHRoaXMsIHRhZyk7CiAgICB9OwoKICAgIF9wcm90bzIucHVzaFJlbW90ZUVsZW1lbnQgPSBmdW5jdGlvbiBwdXNoUmVtb3RlRWxlbWVudChlbGVtZW50LCBjdXJzb3JJZCwgbmV4dFNpYmxpbmcpIHsKICAgICAgaWYgKG5leHRTaWJsaW5nID09PSB2b2lkIDApIHsKICAgICAgICBuZXh0U2libGluZyA9IG51bGw7CiAgICAgIH0KCiAgICAgIHZhciBkb20gPSB0aGlzLmRvbTsKICAgICAgdmFyIHNjcmlwdCA9IGRvbS5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTsKICAgICAgc2NyaXB0LnNldEF0dHJpYnV0ZSgnZ2xtcicsIGN1cnNvcklkKTsKICAgICAgZG9tLmluc2VydEJlZm9yZShlbGVtZW50LCBzY3JpcHQsIG5leHRTaWJsaW5nKTsKCiAgICAgIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUucHVzaFJlbW90ZUVsZW1lbnQuY2FsbCh0aGlzLCBlbGVtZW50LCBjdXJzb3JJZCwgbmV4dFNpYmxpbmcpOwogICAgfTsKCiAgICByZXR1cm4gU2VyaWFsaXplQnVpbGRlcjsKICB9KF9ydW50aW1lLk5ld0VsZW1lbnRCdWlsZGVyKTsKCiAgZnVuY3Rpb24gc2VyaWFsaXplQnVpbGRlcihlbnYsIGN1cnNvcikgewogICAgcmV0dXJuIFNlcmlhbGl6ZUJ1aWxkZXIuZm9ySW5pdGlhbFJlbmRlcihlbnYsIGN1cnNvcik7CiAgfQp9KTsKZGVmaW5lKCJAZ2xpbW1lci9vcGNvZGUtY29tcGlsZXIiLCBbImV4cG9ydHMiLCAiQGVtYmVyL3BvbHlmaWxscyIsICJlbWJlci1iYWJlbCIsICJAZ2xpbW1lci91dGlsIiwgIkBnbGltbWVyL3ZtIiwgIkBnbGltbWVyL3dpcmUtZm9ybWF0IiwgIkBnbGltbWVyL2VuY29kZXIiLCAiQGdsaW1tZXIvcHJvZ3JhbSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9wb2x5ZmlsbHMsIF9lbWJlckJhYmVsLCBfdXRpbCwgX3ZtLCBfd2lyZUZvcm1hdCwgX2VuY29kZXIsIF9wcm9ncmFtKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5jb21waWxlID0gY29tcGlsZTsKICBfZXhwb3J0cy50ZW1wbGF0ZUZhY3RvcnkgPSB0ZW1wbGF0ZUZhY3Rvcnk7CiAgX2V4cG9ydHMuZGVidWcgPSBkZWJ1ZzsKICBfZXhwb3J0cy5kZWJ1Z1NsaWNlID0gZGVidWdTbGljZTsKICBfZXhwb3J0cy5sb2dPcGNvZGUgPSBsb2dPcGNvZGU7CiAgX2V4cG9ydHMuUExBQ0VIT0xERVJfSEFORExFID0gX2V4cG9ydHMuV3JhcHBlZEJ1aWxkZXIgPSBfZXhwb3J0cy5QYXJ0aWFsRGVmaW5pdGlvbiA9IF9leHBvcnRzLlN0ZE9wY29kZUJ1aWxkZXIgPSBfZXhwb3J0cy5PcGNvZGVCdWlsZGVyID0gX2V4cG9ydHMuRWFnZXJPcGNvZGVCdWlsZGVyID0gX2V4cG9ydHMuTGF6eU9wY29kZUJ1aWxkZXIgPSBfZXhwb3J0cy5Db21waWxhYmxlUHJvZ3JhbSA9IF9leHBvcnRzLkNvbXBpbGFibGVCbG9jayA9IF9leHBvcnRzLmRlYnVnQ29tcGlsZXIgPSBfZXhwb3J0cy5BYnN0cmFjdENvbXBpbGVyID0gX2V4cG9ydHMuTGF6eUNvbXBpbGVyID0gX2V4cG9ydHMuTWFjcm9zID0gX2V4cG9ydHMuQVRUUlNfQkxPQ0sgPSB2b2lkIDA7CiAgdmFyIFBMQUNFSE9MREVSX0hBTkRMRSA9IC0xOwogIF9leHBvcnRzLlBMQUNFSE9MREVSX0hBTkRMRSA9IFBMQUNFSE9MREVSX0hBTkRMRTsKICB2YXIgT3BzJDE7CgogIChmdW5jdGlvbiAoT3BzJCQxKSB7CiAgICBPcHMkJDFbT3BzJCQxWyJPcGVuQ29tcG9uZW50RWxlbWVudCJdID0gMF0gPSAiT3BlbkNvbXBvbmVudEVsZW1lbnQiOwogICAgT3BzJCQxW09wcyQkMVsiRGlkQ3JlYXRlRWxlbWVudCJdID0gMV0gPSAiRGlkQ3JlYXRlRWxlbWVudCI7CiAgICBPcHMkJDFbT3BzJCQxWyJEaWRSZW5kZXJMYXlvdXQiXSA9IDJdID0gIkRpZFJlbmRlckxheW91dCI7CiAgICBPcHMkJDFbT3BzJCQxWyJEZWJ1Z2dlciJdID0gM10gPSAiRGVidWdnZXIiOwogIH0pKE9wcyQxIHx8IChPcHMkMSA9IHt9KSk7CgogIHZhciBPcHMkMiA9IF93aXJlRm9ybWF0Lk9wczsKICB2YXIgQVRUUlNfQkxPQ0sgPSAnJmF0dHJzJzsKICBfZXhwb3J0cy5BVFRSU19CTE9DSyA9IEFUVFJTX0JMT0NLOwoKICB2YXIgQ29tcGlsZXJzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ29tcGlsZXJzKG9mZnNldCkgewogICAgICBpZiAob2Zmc2V0ID09PSB2b2lkIDApIHsKICAgICAgICBvZmZzZXQgPSAwOwogICAgICB9CgogICAgICB0aGlzLm9mZnNldCA9IG9mZnNldDsKICAgICAgdGhpcy5uYW1lcyA9ICgwLCBfdXRpbC5kaWN0KSgpOwogICAgICB0aGlzLmZ1bmNzID0gW107CiAgICB9CgogICAgdmFyIF9wcm90byA9IENvbXBpbGVycy5wcm90b3R5cGU7CgogICAgX3Byb3RvLmFkZCA9IGZ1bmN0aW9uIGFkZChuYW1lLCBmdW5jKSB7CiAgICAgIHRoaXMuZnVuY3MucHVzaChmdW5jKTsKICAgICAgdGhpcy5uYW1lc1tuYW1lXSA9IHRoaXMuZnVuY3MubGVuZ3RoIC0gMTsKICAgIH07CgogICAgX3Byb3RvLmNvbXBpbGUgPSBmdW5jdGlvbiBjb21waWxlKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIG5hbWUgPSBzZXhwW3RoaXMub2Zmc2V0XTsKICAgICAgdmFyIGluZGV4ID0gdGhpcy5uYW1lc1tuYW1lXTsKICAgICAgdmFyIGZ1bmMgPSB0aGlzLmZ1bmNzW2luZGV4XTsKICAgICAgZnVuYyhzZXhwLCBidWlsZGVyKTsKICAgIH07CgogICAgcmV0dXJuIENvbXBpbGVyczsKICB9KCk7CgogIHZhciBfc3RhdGVtZW50Q29tcGlsZXI7CgogIGZ1bmN0aW9uIHN0YXRlbWVudENvbXBpbGVyKCkgewogICAgaWYgKF9zdGF0ZW1lbnRDb21waWxlcikgewogICAgICByZXR1cm4gX3N0YXRlbWVudENvbXBpbGVyOwogICAgfQoKICAgIHZhciBTVEFURU1FTlRTID0gX3N0YXRlbWVudENvbXBpbGVyID0gbmV3IENvbXBpbGVycygpOwogICAgU1RBVEVNRU5UUy5hZGQoT3BzJDIuVGV4dCwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgYnVpbGRlci50ZXh0KHNleHBbMV0pOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5Db21tZW50LCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICBidWlsZGVyLmNvbW1lbnQoc2V4cFsxXSk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkNsb3NlRWxlbWVudCwgZnVuY3Rpb24gKF9zZXhwLCBidWlsZGVyKSB7CiAgICAgIGJ1aWxkZXIuY2xvc2VFbGVtZW50KCk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkZsdXNoRWxlbWVudCwgZnVuY3Rpb24gKF9zZXhwLCBidWlsZGVyKSB7CiAgICAgIGJ1aWxkZXIuZmx1c2hFbGVtZW50KCk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLk1vZGlmaWVyLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgcmVmZXJyZXIgPSBidWlsZGVyLnJlZmVycmVyOwogICAgICB2YXIgbmFtZSA9IHNleHBbMV0sCiAgICAgICAgICBwYXJhbXMgPSBzZXhwWzJdLAogICAgICAgICAgaGFzaCA9IHNleHBbM107CiAgICAgIHZhciBoYW5kbGUgPSBidWlsZGVyLmNvbXBpbGVyLnJlc29sdmVNb2RpZmllcihuYW1lLCByZWZlcnJlcik7CgogICAgICBpZiAoaGFuZGxlICE9PSBudWxsKSB7CiAgICAgICAgYnVpbGRlci5tb2RpZmllcihoYW5kbGUsIHBhcmFtcywgaGFzaCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDb21waWxlIEVycm9yICIgKyBuYW1lICsgIiBpcyBub3QgYSBtb2RpZmllcjogSGVscGVycyBtYXkgbm90IGJlIHVzZWQgaW4gdGhlIGVsZW1lbnQgZm9ybS4iKTsKICAgICAgfQogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5TdGF0aWNBdHRyLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgbmFtZSA9IHNleHBbMV0sCiAgICAgICAgICB2YWx1ZSA9IHNleHBbMl0sCiAgICAgICAgICBuYW1lc3BhY2UgPSBzZXhwWzNdOwogICAgICBidWlsZGVyLnN0YXRpY0F0dHIobmFtZSwgbmFtZXNwYWNlLCB2YWx1ZSk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkR5bmFtaWNBdHRyLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICBkeW5hbWljQXR0cihzZXhwLCBmYWxzZSwgYnVpbGRlcik7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkNvbXBvbmVudEF0dHIsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIGNvbXBvbmVudEF0dHIoc2V4cCwgZmFsc2UsIGJ1aWxkZXIpOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5UcnVzdGluZ0F0dHIsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIGR5bmFtaWNBdHRyKHNleHAsIHRydWUsIGJ1aWxkZXIpOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5UcnVzdGluZ0NvbXBvbmVudEF0dHIsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIGNvbXBvbmVudEF0dHIoc2V4cCwgdHJ1ZSwgYnVpbGRlcik7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLk9wZW5FbGVtZW50LCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgdGFnID0gc2V4cFsxXSwKICAgICAgICAgIHNpbXBsZSA9IHNleHBbMl07CgogICAgICBpZiAoIXNpbXBsZSkgewogICAgICAgIGJ1aWxkZXIucHV0Q29tcG9uZW50T3BlcmF0aW9ucygpOwogICAgICB9CgogICAgICBidWlsZGVyLm9wZW5QcmltaXRpdmVFbGVtZW50KHRhZyk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkR5bmFtaWNDb21wb25lbnQsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciBkZWZpbml0aW9uID0gc2V4cFsxXSwKICAgICAgICAgIGF0dHJzID0gc2V4cFsyXSwKICAgICAgICAgIGFyZ3MgPSBzZXhwWzNdLAogICAgICAgICAgdGVtcGxhdGUgPSBzZXhwWzRdOwogICAgICB2YXIgYmxvY2sgPSBidWlsZGVyLnRlbXBsYXRlKHRlbXBsYXRlKTsKICAgICAgdmFyIGF0dHJzQmxvY2sgPSBudWxsOwoKICAgICAgaWYgKGF0dHJzLmxlbmd0aCA+IDApIHsKICAgICAgICBhdHRyc0Jsb2NrID0gYnVpbGRlci5pbmxpbmVCbG9jayh7CiAgICAgICAgICBzdGF0ZW1lbnRzOiBhdHRycywKICAgICAgICAgIHBhcmFtZXRlcnM6IF91dGlsLkVNUFRZX0FSUkFZCiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIGJ1aWxkZXIuZHluYW1pY0NvbXBvbmVudChkZWZpbml0aW9uLCBhdHRyc0Jsb2NrLCBudWxsLCBhcmdzLCBmYWxzZSwgYmxvY2ssIG51bGwpOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5Db21wb25lbnQsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciB0YWcgPSBzZXhwWzFdLAogICAgICAgICAgYXR0cnMgPSBzZXhwWzJdLAogICAgICAgICAgYXJncyA9IHNleHBbM10sCiAgICAgICAgICBibG9jayA9IHNleHBbNF07CiAgICAgIHZhciByZWZlcnJlciA9IGJ1aWxkZXIucmVmZXJyZXI7CgogICAgICB2YXIgX2J1aWxkZXIkY29tcGlsZXIkcmVzID0gYnVpbGRlci5jb21waWxlci5yZXNvbHZlTGF5b3V0Rm9yVGFnKHRhZywgcmVmZXJyZXIpLAogICAgICAgICAgaGFuZGxlID0gX2J1aWxkZXIkY29tcGlsZXIkcmVzLmhhbmRsZSwKICAgICAgICAgIGNhcGFiaWxpdGllcyA9IF9idWlsZGVyJGNvbXBpbGVyJHJlcy5jYXBhYmlsaXRpZXMsCiAgICAgICAgICBjb21waWxhYmxlID0gX2J1aWxkZXIkY29tcGlsZXIkcmVzLmNvbXBpbGFibGU7CgogICAgICBpZiAoaGFuZGxlICE9PSBudWxsICYmIGNhcGFiaWxpdGllcyAhPT0gbnVsbCkgewogICAgICAgIHZhciBhdHRyc0Jsb2NrID0gbnVsbDsKCiAgICAgICAgaWYgKGF0dHJzLmxlbmd0aCA+IDApIHsKICAgICAgICAgIGF0dHJzQmxvY2sgPSBidWlsZGVyLmlubGluZUJsb2NrKHsKICAgICAgICAgICAgc3RhdGVtZW50czogYXR0cnMsCiAgICAgICAgICAgIHBhcmFtZXRlcnM6IF91dGlsLkVNUFRZX0FSUkFZCiAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIHZhciBjaGlsZCA9IGJ1aWxkZXIudGVtcGxhdGUoYmxvY2spOwoKICAgICAgICBpZiAoY29tcGlsYWJsZSkgewogICAgICAgICAgYnVpbGRlci5wdXNoQ29tcG9uZW50RGVmaW5pdGlvbihoYW5kbGUpOwogICAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNDb21wb25lbnQoY2FwYWJpbGl0aWVzLCBjb21waWxhYmxlLCBhdHRyc0Jsb2NrLCBudWxsLCBhcmdzLCBmYWxzZSwgY2hpbGQgJiYgY2hpbGQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBidWlsZGVyLnB1c2hDb21wb25lbnREZWZpbml0aW9uKGhhbmRsZSk7CiAgICAgICAgICBidWlsZGVyLmludm9rZUNvbXBvbmVudChjYXBhYmlsaXRpZXMsIGF0dHJzQmxvY2ssIG51bGwsIGFyZ3MsIGZhbHNlLCBjaGlsZCAmJiBjaGlsZCk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiQ29tcGlsZSBFcnJvcjogQ2Fubm90IGZpbmQgY29tcG9uZW50ICIgKyB0YWcpOwogICAgICB9CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLlBhcnRpYWwsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciBuYW1lID0gc2V4cFsxXSwKICAgICAgICAgIGV2YWxJbmZvID0gc2V4cFsyXTsKICAgICAgdmFyIHJlZmVycmVyID0gYnVpbGRlci5yZWZlcnJlcjsKICAgICAgYnVpbGRlci5yZXBsYXlhYmxlSWYoewogICAgICAgIGFyZ3M6IGZ1bmN0aW9uIGFyZ3MoKSB7CiAgICAgICAgICBidWlsZGVyLmV4cHIobmFtZSk7CiAgICAgICAgICBidWlsZGVyLmR1cCgpOwogICAgICAgICAgcmV0dXJuIDI7CiAgICAgICAgfSwKICAgICAgICBpZlRydWU6IGZ1bmN0aW9uIGlmVHJ1ZSgpIHsKICAgICAgICAgIGJ1aWxkZXIuaW52b2tlUGFydGlhbChyZWZlcnJlciwgYnVpbGRlci5ldmFsU3ltYm9scygpLCBldmFsSW5mbyk7CiAgICAgICAgICBidWlsZGVyLnBvcFNjb3BlKCk7CiAgICAgICAgICBidWlsZGVyLnBvcEZyYW1lKCk7IC8vIEZJWE1FOiBXQVQKICAgICAgICB9CiAgICAgIH0pOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5ZaWVsZCwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIHRvID0gc2V4cFsxXSwKICAgICAgICAgIHBhcmFtcyA9IHNleHBbMl07CiAgICAgIGJ1aWxkZXIueWllbGQodG8sIHBhcmFtcyk7CiAgICB9KTsKICAgIFNUQVRFTUVOVFMuYWRkKE9wcyQyLkF0dHJTcGxhdCwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIHRvID0gc2V4cFsxXTsKICAgICAgYnVpbGRlci55aWVsZCh0bywgW10pOwogICAgfSk7CiAgICBTVEFURU1FTlRTLmFkZChPcHMkMi5EZWJ1Z2dlciwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIGV2YWxJbmZvID0gc2V4cFsxXTsKICAgICAgYnVpbGRlci5kZWJ1Z2dlcihidWlsZGVyLmV2YWxTeW1ib2xzKCksIGV2YWxJbmZvKTsKICAgIH0pOwogICAgU1RBVEVNRU5UUy5hZGQoT3BzJDIuQ2xpZW50U2lkZVN0YXRlbWVudCwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgQ0xJRU5UX1NJREUuY29tcGlsZShzZXhwLCBidWlsZGVyKTsKICAgIH0pOwogICAgU1RBVEVNRU5UUy5hZGQoT3BzJDIuQXBwZW5kLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgdmFsdWUgPSBzZXhwWzFdLAogICAgICAgICAgdHJ1c3RpbmcgPSBzZXhwWzJdOwogICAgICB2YXIgcmV0dXJuZWQgPSBidWlsZGVyLmNvbXBpbGVJbmxpbmUoc2V4cCkgfHwgdmFsdWU7CiAgICAgIGlmIChyZXR1cm5lZCA9PT0gdHJ1ZSkgcmV0dXJuOwogICAgICBidWlsZGVyLmd1YXJkZWRBcHBlbmQodmFsdWUsIHRydXN0aW5nKTsKICAgIH0pOwogICAgU1RBVEVNRU5UUy5hZGQoT3BzJDIuQmxvY2ssIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciBuYW1lID0gc2V4cFsxXSwKICAgICAgICAgIHBhcmFtcyA9IHNleHBbMl0sCiAgICAgICAgICBoYXNoID0gc2V4cFszXSwKICAgICAgICAgIF90ZW1wbGF0ZSA9IHNleHBbNF0sCiAgICAgICAgICBfaW52ZXJzZSA9IHNleHBbNV07CiAgICAgIHZhciB0ZW1wbGF0ZSA9IGJ1aWxkZXIudGVtcGxhdGUoX3RlbXBsYXRlKTsKICAgICAgdmFyIGludmVyc2UgPSBidWlsZGVyLnRlbXBsYXRlKF9pbnZlcnNlKTsKICAgICAgdmFyIHRlbXBsYXRlQmxvY2sgPSB0ZW1wbGF0ZSAmJiB0ZW1wbGF0ZTsKICAgICAgdmFyIGludmVyc2VCbG9jayA9IGludmVyc2UgJiYgaW52ZXJzZTsKICAgICAgYnVpbGRlci5jb21waWxlQmxvY2sobmFtZSwgcGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZUJsb2NrLCBpbnZlcnNlQmxvY2spOwogICAgfSk7CiAgICB2YXIgQ0xJRU5UX1NJREUgPSBuZXcgQ29tcGlsZXJzKDEpOwogICAgQ0xJRU5UX1NJREUuYWRkKE9wcyQxLk9wZW5Db21wb25lbnRFbGVtZW50LCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICBidWlsZGVyLnB1dENvbXBvbmVudE9wZXJhdGlvbnMoKTsKICAgICAgYnVpbGRlci5vcGVuUHJpbWl0aXZlRWxlbWVudChzZXhwWzJdKTsKICAgIH0pOwogICAgQ0xJRU5UX1NJREUuYWRkKE9wcyQxLkRpZENyZWF0ZUVsZW1lbnQsIGZ1bmN0aW9uIChfc2V4cCwgYnVpbGRlcikgewogICAgICBidWlsZGVyLmRpZENyZWF0ZUVsZW1lbnQoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgIH0pOwogICAgQ0xJRU5UX1NJREUuYWRkKE9wcyQxLkRlYnVnZ2VyLCBmdW5jdGlvbiAoKSB7CiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1kZWJ1Z2dlcgogICAgICBkZWJ1Z2dlcjsKICAgIH0pOwogICAgQ0xJRU5UX1NJREUuYWRkKE9wcyQxLkRpZFJlbmRlckxheW91dCwgZnVuY3Rpb24gKF9zZXhwLCBidWlsZGVyKSB7CiAgICAgIGJ1aWxkZXIuZGlkUmVuZGVyTGF5b3V0KF92bS5SZWdpc3Rlci5zMCk7CiAgICB9KTsKICAgIHJldHVybiBTVEFURU1FTlRTOwogIH0KCiAgZnVuY3Rpb24gY29tcG9uZW50QXR0cihzZXhwLCB0cnVzdGluZywgYnVpbGRlcikgewogICAgdmFyIG5hbWUgPSBzZXhwWzFdLAogICAgICAgIHZhbHVlID0gc2V4cFsyXSwKICAgICAgICBuYW1lc3BhY2UgPSBzZXhwWzNdOwogICAgYnVpbGRlci5leHByKHZhbHVlKTsKCiAgICBpZiAobmFtZXNwYWNlKSB7CiAgICAgIGJ1aWxkZXIuY29tcG9uZW50QXR0cihuYW1lLCBuYW1lc3BhY2UsIHRydXN0aW5nKTsKICAgIH0gZWxzZSB7CiAgICAgIGJ1aWxkZXIuY29tcG9uZW50QXR0cihuYW1lLCBudWxsLCB0cnVzdGluZyk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBkeW5hbWljQXR0cihzZXhwLCB0cnVzdGluZywgYnVpbGRlcikgewogICAgdmFyIG5hbWUgPSBzZXhwWzFdLAogICAgICAgIHZhbHVlID0gc2V4cFsyXSwKICAgICAgICBuYW1lc3BhY2UgPSBzZXhwWzNdOwogICAgYnVpbGRlci5leHByKHZhbHVlKTsKCiAgICBpZiAobmFtZXNwYWNlKSB7CiAgICAgIGJ1aWxkZXIuZHluYW1pY0F0dHIobmFtZSwgbmFtZXNwYWNlLCB0cnVzdGluZyk7CiAgICB9IGVsc2UgewogICAgICBidWlsZGVyLmR5bmFtaWNBdHRyKG5hbWUsIG51bGwsIHRydXN0aW5nKTsKICAgIH0KICB9CgogIHZhciBfZXhwcmVzc2lvbkNvbXBpbGVyOwoKICBmdW5jdGlvbiBleHByZXNzaW9uQ29tcGlsZXIoKSB7CiAgICBpZiAoX2V4cHJlc3Npb25Db21waWxlcikgewogICAgICByZXR1cm4gX2V4cHJlc3Npb25Db21waWxlcjsKICAgIH0KCiAgICB2YXIgRVhQUkVTU0lPTlMgPSBfZXhwcmVzc2lvbkNvbXBpbGVyID0gbmV3IENvbXBpbGVycygpOwogICAgRVhQUkVTU0lPTlMuYWRkKE9wcyQyLlVua25vd24sIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciBjb21waWxlciA9IGJ1aWxkZXIuY29tcGlsZXIsCiAgICAgICAgICByZWZlcnJlciA9IGJ1aWxkZXIucmVmZXJyZXIsCiAgICAgICAgICBhc1BhcnRpYWwgPSBidWlsZGVyLmNvbnRhaW5pbmdMYXlvdXQuYXNQYXJ0aWFsOwogICAgICB2YXIgbmFtZSA9IHNleHBbMV07CiAgICAgIHZhciBoYW5kbGUgPSBjb21waWxlci5yZXNvbHZlSGVscGVyKG5hbWUsIHJlZmVycmVyKTsKCiAgICAgIGlmIChoYW5kbGUgIT09IG51bGwpIHsKICAgICAgICBidWlsZGVyLmhlbHBlcihoYW5kbGUsIG51bGwsIG51bGwpOwogICAgICB9IGVsc2UgaWYgKGFzUGFydGlhbCkgewogICAgICAgIGJ1aWxkZXIucmVzb2x2ZU1heWJlTG9jYWwobmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnVpbGRlci5nZXRWYXJpYWJsZSgwKTsKICAgICAgICBidWlsZGVyLmdldFByb3BlcnR5KG5hbWUpOwogICAgICB9CiAgICB9KTsKICAgIEVYUFJFU1NJT05TLmFkZChPcHMkMi5Db25jYXQsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIHZhciBwYXJ0cyA9IHNleHBbMV07CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgYnVpbGRlci5leHByKHBhcnRzW2ldKTsKICAgICAgfQoKICAgICAgYnVpbGRlci5jb25jYXQocGFydHMubGVuZ3RoKTsKICAgIH0pOwogICAgRVhQUkVTU0lPTlMuYWRkKE9wcyQyLkhlbHBlciwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIGNvbXBpbGVyID0gYnVpbGRlci5jb21waWxlciwKICAgICAgICAgIHJlZmVycmVyID0gYnVpbGRlci5yZWZlcnJlcjsKICAgICAgdmFyIG5hbWUgPSBzZXhwWzFdLAogICAgICAgICAgcGFyYW1zID0gc2V4cFsyXSwKICAgICAgICAgIGhhc2ggPSBzZXhwWzNdOyAvLyBUT0RPOiB0cmlhZ2UgdGhpcyBpbiB0aGUgV0YgY29tcGlsZXIKCiAgICAgIGlmIChuYW1lID09PSAnY29tcG9uZW50JykgewogICAgICAgIHZhciBkZWZpbml0aW9uID0gcGFyYW1zWzBdLAogICAgICAgICAgICByZXN0QXJncyA9IHBhcmFtcy5zbGljZSgxKTsKICAgICAgICBidWlsZGVyLmN1cnJ5Q29tcG9uZW50KGRlZmluaXRpb24sIHJlc3RBcmdzLCBoYXNoLCB0cnVlKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBoYW5kbGUgPSBjb21waWxlci5yZXNvbHZlSGVscGVyKG5hbWUsIHJlZmVycmVyKTsKCiAgICAgIGlmIChoYW5kbGUgIT09IG51bGwpIHsKICAgICAgICBidWlsZGVyLmhlbHBlcihoYW5kbGUsIHBhcmFtcywgaGFzaCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDb21waWxlIEVycm9yOiAiICsgbmFtZSArICIgaXMgbm90IGEgaGVscGVyIik7CiAgICAgIH0KICAgIH0pOwogICAgRVhQUkVTU0lPTlMuYWRkKE9wcyQyLkdldCwgZnVuY3Rpb24gKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIGhlYWQgPSBzZXhwWzFdLAogICAgICAgICAgcGF0aCA9IHNleHBbMl07CiAgICAgIGJ1aWxkZXIuZ2V0VmFyaWFibGUoaGVhZCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGgubGVuZ3RoOyBpKyspIHsKICAgICAgICBidWlsZGVyLmdldFByb3BlcnR5KHBhdGhbaV0pOwogICAgICB9CiAgICB9KTsKICAgIEVYUFJFU1NJT05TLmFkZChPcHMkMi5NYXliZUxvY2FsLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgcGF0aCA9IHNleHBbMV07CgogICAgICBpZiAoYnVpbGRlci5jb250YWluaW5nTGF5b3V0LmFzUGFydGlhbCkgewogICAgICAgIHZhciBoZWFkID0gcGF0aFswXTsKICAgICAgICBwYXRoID0gcGF0aC5zbGljZSgxKTsKICAgICAgICBidWlsZGVyLnJlc29sdmVNYXliZUxvY2FsKGhlYWQpOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1aWxkZXIuZ2V0VmFyaWFibGUoMCk7CiAgICAgIH0KCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0aC5sZW5ndGg7IGkrKykgewogICAgICAgIGJ1aWxkZXIuZ2V0UHJvcGVydHkocGF0aFtpXSk7CiAgICAgIH0KICAgIH0pOwogICAgRVhQUkVTU0lPTlMuYWRkKE9wcyQyLlVuZGVmaW5lZCwgZnVuY3Rpb24gKF9zZXhwLCBidWlsZGVyKSB7CiAgICAgIHJldHVybiBidWlsZGVyLnB1c2hQcmltaXRpdmVSZWZlcmVuY2UodW5kZWZpbmVkKTsKICAgIH0pOwogICAgRVhQUkVTU0lPTlMuYWRkKE9wcyQyLkhhc0Jsb2NrLCBmdW5jdGlvbiAoc2V4cCwgYnVpbGRlcikgewogICAgICBidWlsZGVyLmhhc0Jsb2NrKHNleHBbMV0pOwogICAgfSk7CiAgICBFWFBSRVNTSU9OUy5hZGQoT3BzJDIuSGFzQmxvY2tQYXJhbXMsIGZ1bmN0aW9uIChzZXhwLCBidWlsZGVyKSB7CiAgICAgIGJ1aWxkZXIuaGFzQmxvY2tQYXJhbXMoc2V4cFsxXSk7CiAgICB9KTsKICAgIHJldHVybiBFWFBSRVNTSU9OUzsKICB9CgogIHZhciBNYWNyb3MgPSBmdW5jdGlvbiBNYWNyb3MoKSB7CiAgICB2YXIgX3BvcHVsYXRlQnVpbHRpbnMgPSBwb3B1bGF0ZUJ1aWx0aW5zKCksCiAgICAgICAgYmxvY2tzID0gX3BvcHVsYXRlQnVpbHRpbnMuYmxvY2tzLAogICAgICAgIGlubGluZXMgPSBfcG9wdWxhdGVCdWlsdGlucy5pbmxpbmVzOwoKICAgIHRoaXMuYmxvY2tzID0gYmxvY2tzOwogICAgdGhpcy5pbmxpbmVzID0gaW5saW5lczsKICB9OwoKICBfZXhwb3J0cy5NYWNyb3MgPSBNYWNyb3M7CgogIHZhciBCbG9ja3MgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBCbG9ja3MoKSB7CiAgICAgIHRoaXMubmFtZXMgPSAoMCwgX3V0aWwuZGljdCkoKTsKICAgICAgdGhpcy5mdW5jcyA9IFtdOwogICAgfQoKICAgIHZhciBfcHJvdG8yID0gQmxvY2tzLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yLmFkZCA9IGZ1bmN0aW9uIGFkZChuYW1lLCBmdW5jKSB7CiAgICAgIHRoaXMuZnVuY3MucHVzaChmdW5jKTsKICAgICAgdGhpcy5uYW1lc1tuYW1lXSA9IHRoaXMuZnVuY3MubGVuZ3RoIC0gMTsKICAgIH07CgogICAgX3Byb3RvMi5hZGRNaXNzaW5nID0gZnVuY3Rpb24gYWRkTWlzc2luZyhmdW5jKSB7CiAgICAgIHRoaXMubWlzc2luZyA9IGZ1bmM7CiAgICB9OwoKICAgIF9wcm90bzIuY29tcGlsZSA9IGZ1bmN0aW9uIGNvbXBpbGUobmFtZSwgcGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZSwgaW52ZXJzZSwgYnVpbGRlcikgewogICAgICB2YXIgaW5kZXggPSB0aGlzLm5hbWVzW25hbWVdOwoKICAgICAgaWYgKGluZGV4ID09PSB1bmRlZmluZWQpIHsKICAgICAgICB2YXIgZnVuYyA9IHRoaXMubWlzc2luZzsKICAgICAgICB2YXIgaGFuZGxlZCA9IGZ1bmMobmFtZSwgcGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZSwgaW52ZXJzZSwgYnVpbGRlcik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIF9mdW5jID0gdGhpcy5mdW5jc1tpbmRleF07CgogICAgICAgIF9mdW5jKHBhcmFtcywgaGFzaCwgdGVtcGxhdGUsIGludmVyc2UsIGJ1aWxkZXIpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBCbG9ja3M7CiAgfSgpOwoKICB2YXIgSW5saW5lcyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIElubGluZXMoKSB7CiAgICAgIHRoaXMubmFtZXMgPSAoMCwgX3V0aWwuZGljdCkoKTsKICAgICAgdGhpcy5mdW5jcyA9IFtdOwogICAgfQoKICAgIHZhciBfcHJvdG8zID0gSW5saW5lcy5wcm90b3R5cGU7CgogICAgX3Byb3RvMy5hZGQgPSBmdW5jdGlvbiBhZGQobmFtZSwgZnVuYykgewogICAgICB0aGlzLmZ1bmNzLnB1c2goZnVuYyk7CiAgICAgIHRoaXMubmFtZXNbbmFtZV0gPSB0aGlzLmZ1bmNzLmxlbmd0aCAtIDE7CiAgICB9OwoKICAgIF9wcm90bzMuYWRkTWlzc2luZyA9IGZ1bmN0aW9uIGFkZE1pc3NpbmcoZnVuYykgewogICAgICB0aGlzLm1pc3NpbmcgPSBmdW5jOwogICAgfTsKCiAgICBfcHJvdG8zLmNvbXBpbGUgPSBmdW5jdGlvbiBjb21waWxlKHNleHAsIGJ1aWxkZXIpIHsKICAgICAgdmFyIHZhbHVlID0gc2V4cFsxXTsgLy8gVE9ETzogRml4IHRoaXMgc28gdGhhdCBleHByZXNzaW9uIG1hY3JvcyBjYW4gcmV0dXJuCiAgICAgIC8vIHRoaW5ncyBsaWtlIGNvbXBvbmVudHMsIHNvIHRoYXQge3tjb21wb25lbnQgZm9vfX0KICAgICAgLy8gaXMgdGhlIHNhbWUgYXMge3soY29tcG9uZW50IGZvbyl9fQoKICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSkgcmV0dXJuIFsnZXhwcicsIHZhbHVlXTsKICAgICAgdmFyIG5hbWU7CiAgICAgIHZhciBwYXJhbXM7CiAgICAgIHZhciBoYXNoOwoKICAgICAgaWYgKHZhbHVlWzBdID09PSBPcHMkMi5IZWxwZXIpIHsKICAgICAgICBuYW1lID0gdmFsdWVbMV07CiAgICAgICAgcGFyYW1zID0gdmFsdWVbMl07CiAgICAgICAgaGFzaCA9IHZhbHVlWzNdOwogICAgICB9IGVsc2UgaWYgKHZhbHVlWzBdID09PSBPcHMkMi5Vbmtub3duKSB7CiAgICAgICAgbmFtZSA9IHZhbHVlWzFdOwogICAgICAgIHBhcmFtcyA9IGhhc2ggPSBudWxsOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBbJ2V4cHInLCB2YWx1ZV07CiAgICAgIH0KCiAgICAgIHZhciBpbmRleCA9IHRoaXMubmFtZXNbbmFtZV07CgogICAgICBpZiAoaW5kZXggPT09IHVuZGVmaW5lZCAmJiB0aGlzLm1pc3NpbmcpIHsKICAgICAgICB2YXIgZnVuYyA9IHRoaXMubWlzc2luZzsKICAgICAgICB2YXIgcmV0dXJuZWQgPSBmdW5jKG5hbWUsIHBhcmFtcywgaGFzaCwgYnVpbGRlcik7CiAgICAgICAgcmV0dXJuIHJldHVybmVkID09PSBmYWxzZSA/IFsnZXhwcicsIHZhbHVlXSA6IHJldHVybmVkOwogICAgICB9IGVsc2UgaWYgKGluZGV4ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB2YXIgX2Z1bmMyID0gdGhpcy5mdW5jc1tpbmRleF07CgogICAgICAgIHZhciBfcmV0dXJuZWQgPSBfZnVuYzIobmFtZSwgcGFyYW1zLCBoYXNoLCBidWlsZGVyKTsKCiAgICAgICAgcmV0dXJuIF9yZXR1cm5lZCA9PT0gZmFsc2UgPyBbJ2V4cHInLCB2YWx1ZV0gOiBfcmV0dXJuZWQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIFsnZXhwcicsIHZhbHVlXTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gSW5saW5lczsKICB9KCk7CgogIGZ1bmN0aW9uIHBvcHVsYXRlQnVpbHRpbnMoYmxvY2tzLCBpbmxpbmVzKSB7CiAgICBpZiAoYmxvY2tzID09PSB2b2lkIDApIHsKICAgICAgYmxvY2tzID0gbmV3IEJsb2NrcygpOwogICAgfQoKICAgIGlmIChpbmxpbmVzID09PSB2b2lkIDApIHsKICAgICAgaW5saW5lcyA9IG5ldyBJbmxpbmVzKCk7CiAgICB9CgogICAgYmxvY2tzLmFkZCgnaWYnLCBmdW5jdGlvbiAocGFyYW1zLCBfaGFzaCwgdGVtcGxhdGUsIGludmVyc2UsIGJ1aWxkZXIpIHsKICAgICAgLy8gICAgICAgIFB1dEFyZ3MKICAgICAgLy8gICAgICAgIFRlc3QoRW52aXJvbm1lbnQpCiAgICAgIC8vICAgICAgICBFbnRlcihCRUdJTiwgRU5EKQogICAgICAvLyBCRUdJTjogTm9vcAogICAgICAvLyAgICAgICAgSnVtcFVubGVzcyhFTFNFKQogICAgICAvLyAgICAgICAgRXZhbHVhdGUoZGVmYXVsdCkKICAgICAgLy8gICAgICAgIEp1bXAoRU5EKQogICAgICAvLyBFTFNFOiAgTm9vcAogICAgICAvLyAgICAgICAgRXZhbHVsYXRlKGludmVyc2UpCiAgICAgIC8vIEVORDogICBOb29wCiAgICAgIC8vICAgICAgICBFeGl0CiAgICAgIGlmICghcGFyYW1zIHx8IHBhcmFtcy5sZW5ndGggIT09IDEpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlNZTlRBWCBFUlJPUjogI2lmIHJlcXVpcmVzIGEgc2luZ2xlIGFyZ3VtZW50Iik7CiAgICAgIH0KCiAgICAgIGJ1aWxkZXIucmVwbGF5YWJsZUlmKHsKICAgICAgICBhcmdzOiBmdW5jdGlvbiBhcmdzKCkgewogICAgICAgICAgYnVpbGRlci5leHByKHBhcmFtc1swXSk7CiAgICAgICAgICBidWlsZGVyLnRvQm9vbGVhbigpOwogICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfSwKICAgICAgICBpZlRydWU6IGZ1bmN0aW9uIGlmVHJ1ZSgpIHsKICAgICAgICAgIGJ1aWxkZXIuaW52b2tlU3RhdGljQmxvY2sodGVtcGxhdGUpOwogICAgICAgIH0sCiAgICAgICAgaWZGYWxzZTogZnVuY3Rpb24gaWZGYWxzZSgpIHsKICAgICAgICAgIGlmIChpbnZlcnNlKSB7CiAgICAgICAgICAgIGJ1aWxkZXIuaW52b2tlU3RhdGljQmxvY2soaW52ZXJzZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgIH0pOwogICAgYmxvY2tzLmFkZCgndW5sZXNzJywgZnVuY3Rpb24gKHBhcmFtcywgX2hhc2gsIHRlbXBsYXRlLCBpbnZlcnNlLCBidWlsZGVyKSB7CiAgICAgIC8vICAgICAgICBQdXRBcmdzCiAgICAgIC8vICAgICAgICBUZXN0KEVudmlyb25tZW50KQogICAgICAvLyAgICAgICAgRW50ZXIoQkVHSU4sIEVORCkKICAgICAgLy8gQkVHSU46IE5vb3AKICAgICAgLy8gICAgICAgIEp1bXBVbmxlc3MoRUxTRSkKICAgICAgLy8gICAgICAgIEV2YWx1YXRlKGRlZmF1bHQpCiAgICAgIC8vICAgICAgICBKdW1wKEVORCkKICAgICAgLy8gRUxTRTogIE5vb3AKICAgICAgLy8gICAgICAgIEV2YWx1bGF0ZShpbnZlcnNlKQogICAgICAvLyBFTkQ6ICAgTm9vcAogICAgICAvLyAgICAgICAgRXhpdAogICAgICBpZiAoIXBhcmFtcyB8fCBwYXJhbXMubGVuZ3RoICE9PSAxKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJTWU5UQVggRVJST1I6ICN1bmxlc3MgcmVxdWlyZXMgYSBzaW5nbGUgYXJndW1lbnQiKTsKICAgICAgfQoKICAgICAgYnVpbGRlci5yZXBsYXlhYmxlSWYoewogICAgICAgIGFyZ3M6IGZ1bmN0aW9uIGFyZ3MoKSB7CiAgICAgICAgICBidWlsZGVyLmV4cHIocGFyYW1zWzBdKTsKICAgICAgICAgIGJ1aWxkZXIudG9Cb29sZWFuKCk7CiAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9LAogICAgICAgIGlmVHJ1ZTogZnVuY3Rpb24gaWZUcnVlKCkgewogICAgICAgICAgaWYgKGludmVyc2UpIHsKICAgICAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNCbG9jayhpbnZlcnNlKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGlmRmFsc2U6IGZ1bmN0aW9uIGlmRmFsc2UoKSB7CiAgICAgICAgICBidWlsZGVyLmludm9rZVN0YXRpY0Jsb2NrKHRlbXBsYXRlKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfSk7CiAgICBibG9ja3MuYWRkKCd3aXRoJywgZnVuY3Rpb24gKHBhcmFtcywgX2hhc2gsIHRlbXBsYXRlLCBpbnZlcnNlLCBidWlsZGVyKSB7CiAgICAgIC8vICAgICAgICBQdXRBcmdzCiAgICAgIC8vICAgICAgICBUZXN0KEVudmlyb25tZW50KQogICAgICAvLyAgICAgICAgRW50ZXIoQkVHSU4sIEVORCkKICAgICAgLy8gQkVHSU46IE5vb3AKICAgICAgLy8gICAgICAgIEp1bXBVbmxlc3MoRUxTRSkKICAgICAgLy8gICAgICAgIEV2YWx1YXRlKGRlZmF1bHQpCiAgICAgIC8vICAgICAgICBKdW1wKEVORCkKICAgICAgLy8gRUxTRTogIE5vb3AKICAgICAgLy8gICAgICAgIEV2YWx1bGF0ZShpbnZlcnNlKQogICAgICAvLyBFTkQ6ICAgTm9vcAogICAgICAvLyAgICAgICAgRXhpdAogICAgICBpZiAoIXBhcmFtcyB8fCBwYXJhbXMubGVuZ3RoICE9PSAxKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJTWU5UQVggRVJST1I6ICN3aXRoIHJlcXVpcmVzIGEgc2luZ2xlIGFyZ3VtZW50Iik7CiAgICAgIH0KCiAgICAgIGJ1aWxkZXIucmVwbGF5YWJsZUlmKHsKICAgICAgICBhcmdzOiBmdW5jdGlvbiBhcmdzKCkgewogICAgICAgICAgYnVpbGRlci5leHByKHBhcmFtc1swXSk7CiAgICAgICAgICBidWlsZGVyLmR1cCgpOwogICAgICAgICAgYnVpbGRlci50b0Jvb2xlYW4oKTsKICAgICAgICAgIHJldHVybiAyOwogICAgICAgIH0sCiAgICAgICAgaWZUcnVlOiBmdW5jdGlvbiBpZlRydWUoKSB7CiAgICAgICAgICBidWlsZGVyLmludm9rZVN0YXRpY0Jsb2NrKHRlbXBsYXRlLCAxKTsKICAgICAgICB9LAogICAgICAgIGlmRmFsc2U6IGZ1bmN0aW9uIGlmRmFsc2UoKSB7CiAgICAgICAgICBpZiAoaW52ZXJzZSkgewogICAgICAgICAgICBidWlsZGVyLmludm9rZVN0YXRpY0Jsb2NrKGludmVyc2UpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICB9KTsKICAgIGJsb2Nrcy5hZGQoJ2VhY2gnLCBmdW5jdGlvbiAocGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZSwgaW52ZXJzZSwgYnVpbGRlcikgewogICAgICAvLyAgICAgICAgIEVudGVyKEJFR0lOLCBFTkQpCiAgICAgIC8vIEJFR0lOOiAgTm9vcAogICAgICAvLyAgICAgICAgIFB1dEFyZ3MKICAgICAgLy8gICAgICAgICBQdXRJdGVyYWJsZQogICAgICAvLyAgICAgICAgIEp1bXBVbmxlc3MoRUxTRSkKICAgICAgLy8gICAgICAgICBFbnRlckxpc3QoQkVHSU4yLCBFTkQyKQogICAgICAvLyBJVEVSOiAgIE5vb3AKICAgICAgLy8gICAgICAgICBOZXh0SXRlcihCUkVBSykKICAgICAgLy8gQkVHSU4yOiBOb29wCiAgICAgIC8vICAgICAgICAgUHVzaENoaWxkU2NvcGUKICAgICAgLy8gICAgICAgICBFdmFsdWF0ZShkZWZhdWx0KQogICAgICAvLyAgICAgICAgIFBvcFNjb3BlCiAgICAgIC8vIEVORDI6ICAgTm9vcAogICAgICAvLyAgICAgICAgIEV4aXQKICAgICAgLy8gICAgICAgICBKdW1wKElURVIpCiAgICAgIC8vIEJSRUFLOiAgTm9vcAogICAgICAvLyAgICAgICAgIEV4aXRMaXN0CiAgICAgIC8vICAgICAgICAgSnVtcChFTkQpCiAgICAgIC8vIEVMU0U6ICAgTm9vcAogICAgICAvLyAgICAgICAgIEV2YWx1bGF0ZShpbnZlcnNlKQogICAgICAvLyBFTkQ6ICAgIE5vb3AKICAgICAgLy8gICAgICAgICBFeGl0CiAgICAgIGJ1aWxkZXIucmVwbGF5YWJsZSh7CiAgICAgICAgYXJnczogZnVuY3Rpb24gYXJncygpIHsKICAgICAgICAgIGlmIChoYXNoICYmIGhhc2hbMF1bMF0gPT09ICdrZXknKSB7CiAgICAgICAgICAgIGJ1aWxkZXIuZXhwcihoYXNoWzFdWzBdKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGJ1aWxkZXIucHVzaFByaW1pdGl2ZVJlZmVyZW5jZShudWxsKTsKICAgICAgICAgIH0KCiAgICAgICAgICBidWlsZGVyLmV4cHIocGFyYW1zWzBdKTsKICAgICAgICAgIHJldHVybiAyOwogICAgICAgIH0sCiAgICAgICAgYm9keTogZnVuY3Rpb24gYm9keSgpIHsKICAgICAgICAgIGJ1aWxkZXIucHV0SXRlcmF0b3IoKTsKICAgICAgICAgIGJ1aWxkZXIuanVtcFVubGVzcygnRUxTRScpOwogICAgICAgICAgYnVpbGRlci5wdXNoRnJhbWUoKTsKICAgICAgICAgIGJ1aWxkZXIuZHVwKF92bS5SZWdpc3Rlci5mcCwgMSk7CiAgICAgICAgICBidWlsZGVyLnJldHVyblRvKCdJVEVSJyk7CiAgICAgICAgICBidWlsZGVyLmVudGVyTGlzdCgnQk9EWScpOwogICAgICAgICAgYnVpbGRlci5sYWJlbCgnSVRFUicpOwogICAgICAgICAgYnVpbGRlci5pdGVyYXRlKCdCUkVBSycpOwogICAgICAgICAgYnVpbGRlci5sYWJlbCgnQk9EWScpOwogICAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNCbG9jayh0ZW1wbGF0ZSwgMik7CiAgICAgICAgICBidWlsZGVyLnBvcCgyKTsKICAgICAgICAgIGJ1aWxkZXIuanVtcCgnRklOQUxMWScpOwogICAgICAgICAgYnVpbGRlci5sYWJlbCgnQlJFQUsnKTsKICAgICAgICAgIGJ1aWxkZXIuZXhpdExpc3QoKTsKICAgICAgICAgIGJ1aWxkZXIucG9wRnJhbWUoKTsKICAgICAgICAgIGJ1aWxkZXIuanVtcCgnRklOQUxMWScpOwogICAgICAgICAgYnVpbGRlci5sYWJlbCgnRUxTRScpOwoKICAgICAgICAgIGlmIChpbnZlcnNlKSB7CiAgICAgICAgICAgIGJ1aWxkZXIuaW52b2tlU3RhdGljQmxvY2soaW52ZXJzZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgIH0pOwogICAgYmxvY2tzLmFkZCgnaW4tZWxlbWVudCcsIGZ1bmN0aW9uIChwYXJhbXMsIGhhc2gsIHRlbXBsYXRlLCBfaW52ZXJzZSwgYnVpbGRlcikgewogICAgICBpZiAoIXBhcmFtcyB8fCBwYXJhbXMubGVuZ3RoICE9PSAxKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJTWU5UQVggRVJST1I6ICNpbi1lbGVtZW50IHJlcXVpcmVzIGEgc2luZ2xlIGFyZ3VtZW50Iik7CiAgICAgIH0KCiAgICAgIGJ1aWxkZXIucmVwbGF5YWJsZUlmKHsKICAgICAgICBhcmdzOiBmdW5jdGlvbiBhcmdzKCkgewogICAgICAgICAgdmFyIGtleXMgPSBoYXNoWzBdLAogICAgICAgICAgICAgIHZhbHVlcyA9IGhhc2hbMV07CgogICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHZhciBrZXkgPSBrZXlzW2ldOwoKICAgICAgICAgICAgaWYgKGtleSA9PT0gJ25leHRTaWJsaW5nJyB8fCBrZXkgPT09ICdndWlkJykgewogICAgICAgICAgICAgIGJ1aWxkZXIuZXhwcih2YWx1ZXNbaV0pOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiU1lOVEFYIEVSUk9SOiAjaW4tZWxlbWVudCBkb2VzIG5vdCB0YWtlIGEgYCIgKyBrZXlzWzBdICsgImAgb3B0aW9uIik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICBidWlsZGVyLmV4cHIocGFyYW1zWzBdKTsKICAgICAgICAgIGJ1aWxkZXIuZHVwKCk7CiAgICAgICAgICByZXR1cm4gNDsKICAgICAgICB9LAogICAgICAgIGlmVHJ1ZTogZnVuY3Rpb24gaWZUcnVlKCkgewogICAgICAgICAgYnVpbGRlci5wdXNoUmVtb3RlRWxlbWVudCgpOwogICAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNCbG9jayh0ZW1wbGF0ZSk7CiAgICAgICAgICBidWlsZGVyLnBvcFJlbW90ZUVsZW1lbnQoKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfSk7CiAgICBibG9ja3MuYWRkKCctd2l0aC1keW5hbWljLXZhcnMnLCBmdW5jdGlvbiAoX3BhcmFtcywgaGFzaCwgdGVtcGxhdGUsIF9pbnZlcnNlLCBidWlsZGVyKSB7CiAgICAgIGlmIChoYXNoKSB7CiAgICAgICAgdmFyIG5hbWVzID0gaGFzaFswXSwKICAgICAgICAgICAgZXhwcmVzc2lvbnMgPSBoYXNoWzFdOwogICAgICAgIGJ1aWxkZXIuY29tcGlsZVBhcmFtcyhleHByZXNzaW9ucyk7CiAgICAgICAgYnVpbGRlci5wdXNoRHluYW1pY1Njb3BlKCk7CiAgICAgICAgYnVpbGRlci5iaW5kRHluYW1pY1Njb3BlKG5hbWVzKTsKICAgICAgICBidWlsZGVyLmludm9rZVN0YXRpY0Jsb2NrKHRlbXBsYXRlKTsKICAgICAgICBidWlsZGVyLnBvcER5bmFtaWNTY29wZSgpOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1aWxkZXIuaW52b2tlU3RhdGljQmxvY2sodGVtcGxhdGUpOwogICAgICB9CiAgICB9KTsKICAgIGJsb2Nrcy5hZGQoJ2NvbXBvbmVudCcsIGZ1bmN0aW9uIChfcGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZSwgaW52ZXJzZSwgYnVpbGRlcikgewogICAgICB2YXIgdGFnID0gX3BhcmFtc1swXTsKCiAgICAgIGlmICh0eXBlb2YgdGFnID09PSAnc3RyaW5nJykgewogICAgICAgIHZhciByZXR1cm5lZCA9IGJ1aWxkZXIuc3RhdGljQ29tcG9uZW50SGVscGVyKF9wYXJhbXNbMF0sIGhhc2gsIHRlbXBsYXRlKTsKICAgICAgICBpZiAocmV0dXJuZWQpIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIGRlZmluaXRpb24gPSBfcGFyYW1zWzBdLAogICAgICAgICAgcGFyYW1zID0gX3BhcmFtcy5zbGljZSgxKTsKCiAgICAgIGJ1aWxkZXIuZHluYW1pY0NvbXBvbmVudChkZWZpbml0aW9uLCBudWxsLCBwYXJhbXMsIGhhc2gsIHRydWUsIHRlbXBsYXRlLCBpbnZlcnNlKTsKICAgIH0pOwogICAgaW5saW5lcy5hZGQoJ2NvbXBvbmVudCcsIGZ1bmN0aW9uIChfbmFtZSwgX3BhcmFtcywgaGFzaCwgYnVpbGRlcikgewogICAgICB2YXIgdGFnID0gX3BhcmFtcyAmJiBfcGFyYW1zWzBdOwoKICAgICAgaWYgKHR5cGVvZiB0YWcgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgdmFyIHJldHVybmVkID0gYnVpbGRlci5zdGF0aWNDb21wb25lbnRIZWxwZXIodGFnLCBoYXNoLCBudWxsKTsKICAgICAgICBpZiAocmV0dXJuZWQpIHJldHVybiB0cnVlOwogICAgICB9CgogICAgICB2YXIgZGVmaW5pdGlvbiA9IF9wYXJhbXNbMF0sCiAgICAgICAgICBwYXJhbXMgPSBfcGFyYW1zLnNsaWNlKDEpOwoKICAgICAgYnVpbGRlci5keW5hbWljQ29tcG9uZW50KGRlZmluaXRpb24sIG51bGwsIHBhcmFtcywgaGFzaCwgdHJ1ZSwgbnVsbCwgbnVsbCk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSk7CiAgICByZXR1cm4gewogICAgICBibG9ja3M6IGJsb2NrcywKICAgICAgaW5saW5lczogaW5saW5lcwogICAgfTsKICB9CgogIHZhciBQTEFDRUhPTERFUl9IQU5ETEUkMSA9IC0xOwoKICB2YXIgQ29tcGlsYWJsZVByb2dyYW0gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDb21waWxhYmxlUHJvZ3JhbShjb21waWxlciwgbGF5b3V0KSB7CiAgICAgIHRoaXMuY29tcGlsZXIgPSBjb21waWxlcjsKICAgICAgdGhpcy5sYXlvdXQgPSBsYXlvdXQ7CiAgICAgIHRoaXMuY29tcGlsZWQgPSBudWxsOwogICAgfQoKICAgIHZhciBfcHJvdG80ID0gQ29tcGlsYWJsZVByb2dyYW0ucHJvdG90eXBlOwoKICAgIF9wcm90bzQuY29tcGlsZSA9IGZ1bmN0aW9uIGNvbXBpbGUoKSB7CiAgICAgIGlmICh0aGlzLmNvbXBpbGVkICE9PSBudWxsKSByZXR1cm4gdGhpcy5jb21waWxlZDsKICAgICAgdGhpcy5jb21waWxlZCA9IFBMQUNFSE9MREVSX0hBTkRMRSQxOwogICAgICB2YXIgc3RhdGVtZW50cyA9IHRoaXMubGF5b3V0LmJsb2NrLnN0YXRlbWVudHM7CiAgICAgIHJldHVybiB0aGlzLmNvbXBpbGVkID0gdGhpcy5jb21waWxlci5hZGQoc3RhdGVtZW50cywgdGhpcy5sYXlvdXQpOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKENvbXBpbGFibGVQcm9ncmFtLCBbewogICAgICBrZXk6ICJzeW1ib2xUYWJsZSIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmxheW91dC5ibG9jazsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIENvbXBpbGFibGVQcm9ncmFtOwogIH0oKTsKCiAgX2V4cG9ydHMuQ29tcGlsYWJsZVByb2dyYW0gPSBDb21waWxhYmxlUHJvZ3JhbTsKCiAgdmFyIENvbXBpbGFibGVCbG9jayA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENvbXBpbGFibGVCbG9jayhjb21waWxlciwgcGFyc2VkKSB7CiAgICAgIHRoaXMuY29tcGlsZXIgPSBjb21waWxlcjsKICAgICAgdGhpcy5wYXJzZWQgPSBwYXJzZWQ7CiAgICAgIHRoaXMuY29tcGlsZWQgPSBudWxsOwogICAgfQoKICAgIHZhciBfcHJvdG81ID0gQ29tcGlsYWJsZUJsb2NrLnByb3RvdHlwZTsKCiAgICBfcHJvdG81LmNvbXBpbGUgPSBmdW5jdGlvbiBjb21waWxlKCkgewogICAgICBpZiAodGhpcy5jb21waWxlZCAhPT0gbnVsbCkgcmV0dXJuIHRoaXMuY29tcGlsZWQ7IC8vIFRyYWNrIHRoYXQgY29tcGlsYXRpb24gaGFzIHN0YXJ0ZWQgYnV0IG5vdCB5ZXQgZmluaXNoZWQgYnkgdGVtcG9yYXJpbHkKICAgICAgLy8gdXNpbmcgYSBwbGFjZWhvbGRlciBoYW5kbGUuIEluIGVhZ2VyIGNvbXBpbGF0aW9uIG1vZGUsIHdoZXJlIGNvbXBpbGUoKQogICAgICAvLyBtYXkgYmUgY2FsbGVkIHJlY3Vyc2l2ZWx5LCB3ZSB1c2UgdGhpcyBhcyBhIHNpZ25hbCB0aGF0IHRoZSBoYW5kbGUgY2Fubm90CiAgICAgIC8vIGJlIGtub3duIHN5bmNocm9ub3VzbHkgYW5kIG11c3QgYmUgbGlua2VkIGxhemlseS4KCiAgICAgIHRoaXMuY29tcGlsZWQgPSBQTEFDRUhPTERFUl9IQU5ETEUkMTsKICAgICAgdmFyIF90aGlzJHBhcnNlZCA9IHRoaXMucGFyc2VkLAogICAgICAgICAgc3RhdGVtZW50cyA9IF90aGlzJHBhcnNlZC5ibG9jay5zdGF0ZW1lbnRzLAogICAgICAgICAgY29udGFpbmluZ0xheW91dCA9IF90aGlzJHBhcnNlZC5jb250YWluaW5nTGF5b3V0OwogICAgICByZXR1cm4gdGhpcy5jb21waWxlZCA9IHRoaXMuY29tcGlsZXIuYWRkKHN0YXRlbWVudHMsIGNvbnRhaW5pbmdMYXlvdXQpOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKENvbXBpbGFibGVCbG9jaywgW3sKICAgICAga2V5OiAic3ltYm9sVGFibGUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5wYXJzZWQuYmxvY2s7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBDb21waWxhYmxlQmxvY2s7CiAgfSgpOwoKICBfZXhwb3J0cy5Db21waWxhYmxlQmxvY2sgPSBDb21waWxhYmxlQmxvY2s7CgogIGZ1bmN0aW9uIGNvbXBpbGUoc3RhdGVtZW50cywgYnVpbGRlciwgY29tcGlsZXIpIHsKICAgIHZhciBzQ29tcGlsZXIgPSBzdGF0ZW1lbnRDb21waWxlcigpOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RhdGVtZW50cy5sZW5ndGg7IGkrKykgewogICAgICBzQ29tcGlsZXIuY29tcGlsZShzdGF0ZW1lbnRzW2ldLCBidWlsZGVyKTsKICAgIH0KCiAgICB2YXIgaGFuZGxlID0gYnVpbGRlci5jb21taXQoKTsKICAgIHJldHVybiBoYW5kbGU7CiAgfQoKICBmdW5jdGlvbiBkZWJ1Z1NsaWNlKHByb2dyYW0sIHN0YXJ0LCBlbmQpIHt9CgogIGZ1bmN0aW9uIGxvZ09wY29kZSh0eXBlLCBwYXJhbXMpIHsKICAgIHZhciBvdXQgPSB0eXBlOwoKICAgIGlmIChwYXJhbXMpIHsKICAgICAgdmFyIGFyZ3MgPSBPYmplY3Qua2V5cyhwYXJhbXMpLm1hcChmdW5jdGlvbiAocCkgewogICAgICAgIHJldHVybiAiICIgKyBwICsgIj0iICsganNvbihwYXJhbXNbcF0pOwogICAgICB9KS5qb2luKCcnKTsKICAgICAgb3V0ICs9IGFyZ3M7CiAgICB9CgogICAgcmV0dXJuICIoIiArIG91dCArICIpIjsKICB9CgogIGZ1bmN0aW9uIGpzb24ocGFyYW0pIHt9CgogIGZ1bmN0aW9uIGRlYnVnKHBvcywgYywgb3ApIHsKICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBvcGVyYW5kcyA9IG5ldyBBcnJheShfbGVuID4gMyA/IF9sZW4gLSAzIDogMCksIF9rZXkgPSAzOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgIG9wZXJhbmRzW19rZXkgLSAzXSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgIH0KCiAgICB2YXIgbWV0YWRhdGEgPSBudWxsOwoKICAgIGlmICghbWV0YWRhdGEpIHsKICAgICAgdGhyb3cgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiTWlzc2luZyBPcGNvZGUgTWV0YWRhdGEgZm9yICIgKyBvcCk7CiAgICB9CgogICAgdmFyIG91dCA9ICgwLCBfdXRpbC5kaWN0KSgpOwogICAgbWV0YWRhdGEub3BzLmZvckVhY2goZnVuY3Rpb24gKG9wZXJhbmQsIGluZGV4KSB7CiAgICAgIHZhciBvcCA9IG9wZXJhbmRzW2luZGV4XTsKCiAgICAgIHN3aXRjaCAob3BlcmFuZC50eXBlKSB7CiAgICAgICAgY2FzZSAndG8nOgogICAgICAgICAgb3V0W29wZXJhbmQubmFtZV0gPSBwb3MgKyBvcDsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICdpMzInOgogICAgICAgIGNhc2UgJ3N5bWJvbCc6CiAgICAgICAgY2FzZSAnYmxvY2snOgogICAgICAgICAgb3V0W29wZXJhbmQubmFtZV0gPSBvcDsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICdoYW5kbGUnOgogICAgICAgICAgb3V0W29wZXJhbmQubmFtZV0gPSBjLnJlc29sdmVIYW5kbGUob3ApOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ3N0cic6CiAgICAgICAgICBvdXRbb3BlcmFuZC5uYW1lXSA9IGMuZ2V0U3RyaW5nKG9wKTsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICdvcHRpb24tc3RyJzoKICAgICAgICAgIG91dFtvcGVyYW5kLm5hbWVdID0gb3AgPyBjLmdldFN0cmluZyhvcCkgOiBudWxsOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ3N0ci1hcnJheSc6CiAgICAgICAgICBvdXRbb3BlcmFuZC5uYW1lXSA9IGMuZ2V0U3RyaW5nQXJyYXkob3ApOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ2FycmF5JzoKICAgICAgICAgIG91dFtvcGVyYW5kLm5hbWVdID0gYy5nZXRBcnJheShvcCk7CiAgICAgICAgICBicmVhazsKCiAgICAgICAgY2FzZSAnYm9vbCc6CiAgICAgICAgICBvdXRbb3BlcmFuZC5uYW1lXSA9ICEhb3A7CiAgICAgICAgICBicmVhazsKCiAgICAgICAgY2FzZSAncHJpbWl0aXZlJzoKICAgICAgICAgIG91dFtvcGVyYW5kLm5hbWVdID0gZGVjb2RlUHJpbWl0aXZlKG9wLCBjKTsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICdyZWdpc3Rlcic6CiAgICAgICAgICBvdXRbb3BlcmFuZC5uYW1lXSA9IF92bS5SZWdpc3RlcltvcF07CiAgICAgICAgICBicmVhazsKCiAgICAgICAgY2FzZSAnc2VyaWFsaXphYmxlJzoKICAgICAgICAgIG91dFtvcGVyYW5kLm5hbWVdID0gYy5nZXRTZXJpYWxpemFibGUob3ApOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ2xhenktY29uc3RhbnQnOgogICAgICAgICAgb3V0W29wZXJhbmQubmFtZV0gPSBjLmdldE90aGVyKG9wKTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9KTsKICAgIHJldHVybiBbbWV0YWRhdGEubmFtZSwgb3V0XTsKICB9CgogIGZ1bmN0aW9uIGRlY29kZVByaW1pdGl2ZShwcmltaXRpdmUsIGNvbnN0YW50cykgewogICAgdmFyIGZsYWcgPSBwcmltaXRpdmUgJiA3OyAvLyAxMTEKCiAgICB2YXIgdmFsdWUgPSBwcmltaXRpdmUgPj4gMzsKCiAgICBzd2l0Y2ggKGZsYWcpIHsKICAgICAgY2FzZSAwCiAgICAgIC8qIE5VTUJFUiAqLwogICAgICA6CiAgICAgICAgcmV0dXJuIHZhbHVlOwoKICAgICAgY2FzZSAxCiAgICAgIC8qIEZMT0FUICovCiAgICAgIDoKICAgICAgICByZXR1cm4gY29uc3RhbnRzLmdldE51bWJlcih2YWx1ZSk7CgogICAgICBjYXNlIDIKICAgICAgLyogU1RSSU5HICovCiAgICAgIDoKICAgICAgICByZXR1cm4gY29uc3RhbnRzLmdldFN0cmluZyh2YWx1ZSk7CgogICAgICBjYXNlIDMKICAgICAgLyogQk9PTEVBTl9PUl9WT0lEICovCiAgICAgIDoKICAgICAgICBzd2l0Y2ggKHZhbHVlKSB7CiAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKCiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHJldHVybiB0cnVlOwoKICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgcmV0dXJuIG51bGw7CgogICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgICAgIH0KCiAgICAgIGNhc2UgNAogICAgICAvKiBORUdBVElWRSAqLwogICAgICA6CiAgICAgIGNhc2UgNQogICAgICAvKiBCSUdfTlVNICovCiAgICAgIDoKICAgICAgICByZXR1cm4gY29uc3RhbnRzLmdldE51bWJlcih2YWx1ZSk7CgogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoKTsKICAgIH0KICB9CgogIHZhciBTdGRMaWIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBTdGRMaWIobWFpbiwgdHJ1c3RpbmdHdWFyZGVkQXBwZW5kLCBjYXV0aW91c0d1YXJkZWRBcHBlbmQpIHsKICAgICAgdGhpcy5tYWluID0gbWFpbjsKICAgICAgdGhpcy50cnVzdGluZ0d1YXJkZWRBcHBlbmQgPSB0cnVzdGluZ0d1YXJkZWRBcHBlbmQ7CiAgICAgIHRoaXMuY2F1dGlvdXNHdWFyZGVkQXBwZW5kID0gY2F1dGlvdXNHdWFyZGVkQXBwZW5kOwogICAgfQoKICAgIFN0ZExpYi5jb21waWxlID0gZnVuY3Rpb24gY29tcGlsZShjb21waWxlcikgewogICAgICB2YXIgbWFpbiA9IHRoaXMuc3RkKGNvbXBpbGVyLCBmdW5jdGlvbiAoYikgewogICAgICAgIHJldHVybiBiLm1haW4oKTsKICAgICAgfSk7CiAgICAgIHZhciB0cnVzdGluZ0d1YXJkZWRBcHBlbmQgPSB0aGlzLnN0ZChjb21waWxlciwgZnVuY3Rpb24gKGIpIHsKICAgICAgICByZXR1cm4gYi5zdGRBcHBlbmQodHJ1ZSk7CiAgICAgIH0pOwogICAgICB2YXIgY2F1dGlvdXNHdWFyZGVkQXBwZW5kID0gdGhpcy5zdGQoY29tcGlsZXIsIGZ1bmN0aW9uIChiKSB7CiAgICAgICAgcmV0dXJuIGIuc3RkQXBwZW5kKGZhbHNlKTsKICAgICAgfSk7CiAgICAgIHJldHVybiBuZXcgU3RkTGliKG1haW4sIHRydXN0aW5nR3VhcmRlZEFwcGVuZCwgY2F1dGlvdXNHdWFyZGVkQXBwZW5kKTsKICAgIH07CgogICAgU3RkTGliLnN0ZCA9IGZ1bmN0aW9uIHN0ZChjb21waWxlciwgY2FsbGJhY2spIHsKICAgICAgcmV0dXJuIFN0ZE9wY29kZUJ1aWxkZXIuYnVpbGQoY29tcGlsZXIsIGNhbGxiYWNrKTsKICAgIH07CgogICAgdmFyIF9wcm90bzYgPSBTdGRMaWIucHJvdG90eXBlOwoKICAgIF9wcm90bzYuZ2V0QXBwZW5kID0gZnVuY3Rpb24gZ2V0QXBwZW5kKHRydXN0aW5nKSB7CiAgICAgIHJldHVybiB0cnVzdGluZyA/IHRoaXMudHJ1c3RpbmdHdWFyZGVkQXBwZW5kIDogdGhpcy5jYXV0aW91c0d1YXJkZWRBcHBlbmQ7CiAgICB9OwoKICAgIHJldHVybiBTdGRMaWI7CiAgfSgpOwoKICB2YXIgQWJzdHJhY3RDb21waWxlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEFic3RyYWN0Q29tcGlsZXIobWFjcm9zLCBwcm9ncmFtLCByZXNvbHZlcikgewogICAgICB0aGlzLm1hY3JvcyA9IG1hY3JvczsKICAgICAgdGhpcy5wcm9ncmFtID0gcHJvZ3JhbTsKICAgICAgdGhpcy5yZXNvbHZlciA9IHJlc29sdmVyOwogICAgICB0aGlzLmluaXRpYWxpemUoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNyA9IEFic3RyYWN0Q29tcGlsZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzcuaW5pdGlhbGl6ZSA9IGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7CiAgICAgIHRoaXMuc3RkTGliID0gU3RkTGliLmNvbXBpbGUodGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzcuY29tcGlsZUlubGluZSA9IGZ1bmN0aW9uIGNvbXBpbGVJbmxpbmUoc2V4cCwgYnVpbGRlcikgewogICAgICB2YXIgaW5saW5lcyA9IHRoaXMubWFjcm9zLmlubGluZXM7CiAgICAgIHJldHVybiBpbmxpbmVzLmNvbXBpbGUoc2V4cCwgYnVpbGRlcik7CiAgICB9OwoKICAgIF9wcm90bzcuY29tcGlsZUJsb2NrID0gZnVuY3Rpb24gY29tcGlsZUJsb2NrKG5hbWUsIHBhcmFtcywgaGFzaCwgdGVtcGxhdGUsIGludmVyc2UsIGJ1aWxkZXIpIHsKICAgICAgdmFyIGJsb2NrcyA9IHRoaXMubWFjcm9zLmJsb2NrczsKICAgICAgYmxvY2tzLmNvbXBpbGUobmFtZSwgcGFyYW1zLCBoYXNoLCB0ZW1wbGF0ZSwgaW52ZXJzZSwgYnVpbGRlcik7CiAgICB9OwoKICAgIF9wcm90bzcuYWRkID0gZnVuY3Rpb24gYWRkKHN0YXRlbWVudHMsIGNvbnRhaW5pbmdMYXlvdXQpIHsKICAgICAgcmV0dXJuIGNvbXBpbGUoc3RhdGVtZW50cywgdGhpcy5idWlsZGVyRm9yKGNvbnRhaW5pbmdMYXlvdXQpLCB0aGlzKTsKICAgIH07CgogICAgX3Byb3RvNy5jb21taXQgPSBmdW5jdGlvbiBjb21taXQoc2NvcGVTaXplLCBidWZmZXIpIHsKICAgICAgdmFyIGhlYXAgPSB0aGlzLnByb2dyYW0uaGVhcDsgLy8gVE9ETzogY2hhbmdlIHRoZSB3aG9sZSBtYWxsb2MgQVBJIGFuZCBkbyBzb21ldGhpbmcgbW9yZSBlZmZpY2llbnQKCiAgICAgIHZhciBoYW5kbGUgPSBoZWFwLm1hbGxvYygpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBidWZmZXIubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgdmFsdWUgPSBidWZmZXJbaV07CgogICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIGhlYXAucHVzaFBsYWNlaG9sZGVyKHZhbHVlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaGVhcC5wdXNoKHZhbHVlKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGhlYXAuZmluaXNoTWFsbG9jKGhhbmRsZSwgc2NvcGVTaXplKTsKICAgICAgcmV0dXJuIGhhbmRsZTsKICAgIH07CgogICAgX3Byb3RvNy5yZXNvbHZlTGF5b3V0Rm9yVGFnID0gZnVuY3Rpb24gcmVzb2x2ZUxheW91dEZvclRhZyh0YWcsIHJlZmVycmVyKSB7CiAgICAgIHZhciByZXNvbHZlciA9IHRoaXMucmVzb2x2ZXI7CiAgICAgIHZhciBoYW5kbGUgPSByZXNvbHZlci5sb29rdXBDb21wb25lbnREZWZpbml0aW9uKHRhZywgcmVmZXJyZXIpOwogICAgICBpZiAoaGFuZGxlID09PSBudWxsKSByZXR1cm4gewogICAgICAgIGhhbmRsZTogbnVsbCwKICAgICAgICBjYXBhYmlsaXRpZXM6IG51bGwsCiAgICAgICAgY29tcGlsYWJsZTogbnVsbAogICAgICB9OwogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlTGF5b3V0Rm9ySGFuZGxlKGhhbmRsZSk7CiAgICB9OwoKICAgIF9wcm90bzcucmVzb2x2ZUxheW91dEZvckhhbmRsZSA9IGZ1bmN0aW9uIHJlc29sdmVMYXlvdXRGb3JIYW5kbGUoaGFuZGxlKSB7CiAgICAgIHZhciByZXNvbHZlciA9IHRoaXMucmVzb2x2ZXI7CiAgICAgIHZhciBjYXBhYmlsaXRpZXMgPSByZXNvbHZlci5nZXRDYXBhYmlsaXRpZXMoaGFuZGxlKTsKICAgICAgdmFyIGNvbXBpbGFibGUgPSBudWxsOwoKICAgICAgaWYgKCFjYXBhYmlsaXRpZXMuZHluYW1pY0xheW91dCkgewogICAgICAgIGNvbXBpbGFibGUgPSByZXNvbHZlci5nZXRMYXlvdXQoaGFuZGxlKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHsKICAgICAgICBoYW5kbGU6IGhhbmRsZSwKICAgICAgICBjYXBhYmlsaXRpZXM6IGNhcGFiaWxpdGllcywKICAgICAgICBjb21waWxhYmxlOiBjb21waWxhYmxlCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzcucmVzb2x2ZU1vZGlmaWVyID0gZnVuY3Rpb24gcmVzb2x2ZU1vZGlmaWVyKG5hbWUsIHJlZmVycmVyKSB7CiAgICAgIHJldHVybiB0aGlzLnJlc29sdmVyLmxvb2t1cE1vZGlmaWVyKG5hbWUsIHJlZmVycmVyKTsKICAgIH07CgogICAgX3Byb3RvNy5yZXNvbHZlSGVscGVyID0gZnVuY3Rpb24gcmVzb2x2ZUhlbHBlcihuYW1lLCByZWZlcnJlcikgewogICAgICByZXR1cm4gdGhpcy5yZXNvbHZlci5sb29rdXBIZWxwZXIobmFtZSwgcmVmZXJyZXIpOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKEFic3RyYWN0Q29tcGlsZXIsIFt7CiAgICAgIGtleTogImNvbnN0YW50cyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLnByb2dyYW0uY29uc3RhbnRzOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gQWJzdHJhY3RDb21waWxlcjsKICB9KCk7CgogIF9leHBvcnRzLkFic3RyYWN0Q29tcGlsZXIgPSBBYnN0cmFjdENvbXBpbGVyOwogIHZhciBkZWJ1Z0NvbXBpbGVyOwogIF9leHBvcnRzLmRlYnVnQ29tcGlsZXIgPSBkZWJ1Z0NvbXBpbGVyOwoKICB2YXIgV3JhcHBlZEJ1aWxkZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBXcmFwcGVkQnVpbGRlcihjb21waWxlciwgbGF5b3V0KSB7CiAgICAgIHRoaXMuY29tcGlsZXIgPSBjb21waWxlcjsKICAgICAgdGhpcy5sYXlvdXQgPSBsYXlvdXQ7CiAgICAgIHRoaXMuY29tcGlsZWQgPSBudWxsOwogICAgICB2YXIgYmxvY2sgPSBsYXlvdXQuYmxvY2s7CiAgICAgIHZhciBzeW1ib2xzID0gYmxvY2suc3ltYm9scy5zbGljZSgpOyAvLyBlbnN1cmUgQVRUUlNfQkxPQ0sgaXMgYWx3YXlzIGluY2x1ZGVkIChvbmx5IG9uY2UpIGluIHRoZSBsaXN0IG9mIHN5bWJvbHMKCiAgICAgIHZhciBhdHRyc0Jsb2NrSW5kZXggPSBzeW1ib2xzLmluZGV4T2YoQVRUUlNfQkxPQ0spOwoKICAgICAgaWYgKGF0dHJzQmxvY2tJbmRleCA9PT0gLTEpIHsKICAgICAgICB0aGlzLmF0dHJzQmxvY2tOdW1iZXIgPSBzeW1ib2xzLnB1c2goQVRUUlNfQkxPQ0spOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuYXR0cnNCbG9ja051bWJlciA9IGF0dHJzQmxvY2tJbmRleCArIDE7CiAgICAgIH0KCiAgICAgIHRoaXMuc3ltYm9sVGFibGUgPSB7CiAgICAgICAgaGFzRXZhbDogYmxvY2suaGFzRXZhbCwKICAgICAgICBzeW1ib2xzOiBzeW1ib2xzCiAgICAgIH07CiAgICB9CgogICAgdmFyIF9wcm90bzggPSBXcmFwcGVkQnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvOC5jb21waWxlID0gZnVuY3Rpb24gY29tcGlsZSgpIHsKICAgICAgaWYgKHRoaXMuY29tcGlsZWQgIT09IG51bGwpIHJldHVybiB0aGlzLmNvbXBpbGVkOyAvLz09PT09PT09RFlOQU1JQwogICAgICAvLyAgICAgICAgUHV0VmFsdWUoVGFnRXhwcikKICAgICAgLy8gICAgICAgIFRlc3QKICAgICAgLy8gICAgICAgIEp1bXBVbmxlc3MoQk9EWSkKICAgICAgLy8gICAgICAgIFB1dENvbXBvbmVudE9wZXJhdGlvbnMKICAgICAgLy8gICAgICAgIE9wZW5EeW5hbWljUHJpbWl0aXZlRWxlbWVudAogICAgICAvLyAgICAgICAgRGlkQ3JlYXRlRWxlbWVudAogICAgICAvLyAgICAgICAgLi4uYXR0ciBzdGF0ZW1lbnRzLi4uCiAgICAgIC8vICAgICAgICBGbHVzaEVsZW1lbnQKICAgICAgLy8gQk9EWTogIE5vb3AKICAgICAgLy8gICAgICAgIC4uLmJvZHkgc3RhdGVtZW50cy4uLgogICAgICAvLyAgICAgICAgUHV0VmFsdWUoVGFnRXhwcikKICAgICAgLy8gICAgICAgIFRlc3QKICAgICAgLy8gICAgICAgIEp1bXBVbmxlc3MoRU5EKQogICAgICAvLyAgICAgICAgQ2xvc2VFbGVtZW50CiAgICAgIC8vIEVORDogICBOb29wCiAgICAgIC8vICAgICAgICBEaWRSZW5kZXJMYXlvdXQKICAgICAgLy8gICAgICAgIEV4aXQKICAgICAgLy8KICAgICAgLy89PT09PT09PVNUQVRJQwogICAgICAvLyAgICAgICAgT3BlblByaW1pdGl2ZUVsZW1lbnRPcGNvZGUKICAgICAgLy8gICAgICAgIERpZENyZWF0ZUVsZW1lbnQKICAgICAgLy8gICAgICAgIC4uLmF0dHIgc3RhdGVtZW50cy4uLgogICAgICAvLyAgICAgICAgRmx1c2hFbGVtZW50CiAgICAgIC8vICAgICAgICAuLi5ib2R5IHN0YXRlbWVudHMuLi4KICAgICAgLy8gICAgICAgIENsb3NlRWxlbWVudAogICAgICAvLyAgICAgICAgRGlkUmVuZGVyTGF5b3V0CiAgICAgIC8vICAgICAgICBFeGl0CgogICAgICB2YXIgY29tcGlsZXIgPSB0aGlzLmNvbXBpbGVyLAogICAgICAgICAgbGF5b3V0ID0gdGhpcy5sYXlvdXQ7CiAgICAgIHZhciBiID0gY29tcGlsZXIuYnVpbGRlckZvcihsYXlvdXQpOwogICAgICBiLnN0YXJ0TGFiZWxzKCk7CiAgICAgIGIuZmV0Y2goX3ZtLlJlZ2lzdGVyLnMxKTsKICAgICAgYi5nZXRDb21wb25lbnRUYWdOYW1lKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIGIucHJpbWl0aXZlUmVmZXJlbmNlKCk7CiAgICAgIGIuZHVwKCk7CiAgICAgIGIubG9hZChfdm0uUmVnaXN0ZXIuczEpOwogICAgICBiLmp1bXBVbmxlc3MoJ0JPRFknKTsKICAgICAgYi5mZXRjaChfdm0uUmVnaXN0ZXIuczEpOwogICAgICBiLnB1dENvbXBvbmVudE9wZXJhdGlvbnMoKTsKICAgICAgYi5vcGVuRHluYW1pY0VsZW1lbnQoKTsKICAgICAgYi5kaWRDcmVhdGVFbGVtZW50KF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIGIueWllbGQodGhpcy5hdHRyc0Jsb2NrTnVtYmVyLCBbXSk7CiAgICAgIGIuZmx1c2hFbGVtZW50KCk7CiAgICAgIGIubGFiZWwoJ0JPRFknKTsKICAgICAgYi5pbnZva2VTdGF0aWNCbG9jayhibG9ja0ZvcihsYXlvdXQsIGNvbXBpbGVyKSk7CiAgICAgIGIuZmV0Y2goX3ZtLlJlZ2lzdGVyLnMxKTsKICAgICAgYi5qdW1wVW5sZXNzKCdFTkQnKTsKICAgICAgYi5jbG9zZUVsZW1lbnQoKTsKICAgICAgYi5sYWJlbCgnRU5EJyk7CiAgICAgIGIubG9hZChfdm0uUmVnaXN0ZXIuczEpOwogICAgICBiLnN0b3BMYWJlbHMoKTsKICAgICAgdmFyIGhhbmRsZSA9IGIuY29tbWl0KCk7CiAgICAgIHJldHVybiB0aGlzLmNvbXBpbGVkID0gaGFuZGxlOwogICAgfTsKCiAgICByZXR1cm4gV3JhcHBlZEJ1aWxkZXI7CiAgfSgpOwoKICBfZXhwb3J0cy5XcmFwcGVkQnVpbGRlciA9IFdyYXBwZWRCdWlsZGVyOwoKICBmdW5jdGlvbiBibG9ja0ZvcihsYXlvdXQsIGNvbXBpbGVyKSB7CiAgICByZXR1cm4gbmV3IENvbXBpbGFibGVCbG9jayhjb21waWxlciwgewogICAgICBibG9jazogewogICAgICAgIHN0YXRlbWVudHM6IGxheW91dC5ibG9jay5zdGF0ZW1lbnRzLAogICAgICAgIHBhcmFtZXRlcnM6IF91dGlsLkVNUFRZX0FSUkFZCiAgICAgIH0sCiAgICAgIGNvbnRhaW5pbmdMYXlvdXQ6IGxheW91dAogICAgfSk7CiAgfQoKICB2YXIgQ29tcG9uZW50QnVpbGRlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENvbXBvbmVudEJ1aWxkZXIoYnVpbGRlcikgewogICAgICB0aGlzLmJ1aWxkZXIgPSBidWlsZGVyOwogICAgfQoKICAgIHZhciBfcHJvdG85ID0gQ29tcG9uZW50QnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvOS5zdGF0aWMgPSBmdW5jdGlvbiBfc3RhdGljKGhhbmRsZSwgYXJncykgewogICAgICB2YXIgcGFyYW1zID0gYXJnc1swXSwKICAgICAgICAgIGhhc2ggPSBhcmdzWzFdLAogICAgICAgICAgX2RlZmF1bHQgPSBhcmdzWzJdLAogICAgICAgICAgaW52ZXJzZSA9IGFyZ3NbM107CiAgICAgIHZhciBidWlsZGVyID0gdGhpcy5idWlsZGVyOwoKICAgICAgaWYgKGhhbmRsZSAhPT0gbnVsbCkgewogICAgICAgIHZhciBfYnVpbGRlciRjb21waWxlciRyZXMyID0gYnVpbGRlci5jb21waWxlci5yZXNvbHZlTGF5b3V0Rm9ySGFuZGxlKGhhbmRsZSksCiAgICAgICAgICAgIGNhcGFiaWxpdGllcyA9IF9idWlsZGVyJGNvbXBpbGVyJHJlczIuY2FwYWJpbGl0aWVzLAogICAgICAgICAgICBjb21waWxhYmxlID0gX2J1aWxkZXIkY29tcGlsZXIkcmVzMi5jb21waWxhYmxlOwoKICAgICAgICBpZiAoY29tcGlsYWJsZSkgewogICAgICAgICAgYnVpbGRlci5wdXNoQ29tcG9uZW50RGVmaW5pdGlvbihoYW5kbGUpOwogICAgICAgICAgYnVpbGRlci5pbnZva2VTdGF0aWNDb21wb25lbnQoY2FwYWJpbGl0aWVzLCBjb21waWxhYmxlLCBudWxsLCBwYXJhbXMsIGhhc2gsIGZhbHNlLCBfZGVmYXVsdCwgaW52ZXJzZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGJ1aWxkZXIucHVzaENvbXBvbmVudERlZmluaXRpb24oaGFuZGxlKTsKICAgICAgICAgIGJ1aWxkZXIuaW52b2tlQ29tcG9uZW50KGNhcGFiaWxpdGllcywgbnVsbCwgcGFyYW1zLCBoYXNoLCBmYWxzZSwgX2RlZmF1bHQsIGludmVyc2UpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gQ29tcG9uZW50QnVpbGRlcjsKICB9KCk7CgogIHZhciBMYWJlbHMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBMYWJlbHMoKSB7CiAgICAgIHRoaXMubGFiZWxzID0gKDAsIF91dGlsLmRpY3QpKCk7CiAgICAgIHRoaXMudGFyZ2V0cyA9IFtdOwogICAgfQoKICAgIHZhciBfcHJvdG8xMCA9IExhYmVscy5wcm90b3R5cGU7CgogICAgX3Byb3RvMTAubGFiZWwgPSBmdW5jdGlvbiBsYWJlbChuYW1lLCBpbmRleCkgewogICAgICB0aGlzLmxhYmVsc1tuYW1lXSA9IGluZGV4OwogICAgfTsKCiAgICBfcHJvdG8xMC50YXJnZXQgPSBmdW5jdGlvbiB0YXJnZXQoYXQsIF90YXJnZXQpIHsKICAgICAgdGhpcy50YXJnZXRzLnB1c2goewogICAgICAgIGF0OiBhdCwKICAgICAgICB0YXJnZXQ6IF90YXJnZXQKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90bzEwLnBhdGNoID0gZnVuY3Rpb24gcGF0Y2goZW5jb2RlcikgewogICAgICB2YXIgdGFyZ2V0cyA9IHRoaXMudGFyZ2V0cywKICAgICAgICAgIGxhYmVscyA9IHRoaXMubGFiZWxzOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0YXJnZXRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIF90YXJnZXRzJGkgPSB0YXJnZXRzW2ldLAogICAgICAgICAgICBhdCA9IF90YXJnZXRzJGkuYXQsCiAgICAgICAgICAgIHRhcmdldCA9IF90YXJnZXRzJGkudGFyZ2V0OwogICAgICAgIHZhciBhZGRyZXNzID0gbGFiZWxzW3RhcmdldF0gLSBhdDsKICAgICAgICBlbmNvZGVyLnBhdGNoKGF0LCBhZGRyZXNzKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gTGFiZWxzOwogIH0oKTsKCiAgdmFyIFN0ZE9wY29kZUJ1aWxkZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBTdGRPcGNvZGVCdWlsZGVyKGNvbXBpbGVyLCBzaXplKSB7CiAgICAgIGlmIChzaXplID09PSB2b2lkIDApIHsKICAgICAgICBzaXplID0gMDsKICAgICAgfQoKICAgICAgdGhpcy5zaXplID0gc2l6ZTsKICAgICAgdGhpcy5lbmNvZGVyID0gbmV3IF9lbmNvZGVyLkluc3RydWN0aW9uRW5jb2RlcihbXSk7CiAgICAgIHRoaXMubGFiZWxzU3RhY2sgPSBuZXcgX3V0aWwuU3RhY2soKTsKICAgICAgdGhpcy5jb21waWxlciA9IGNvbXBpbGVyOwogICAgfQoKICAgIFN0ZE9wY29kZUJ1aWxkZXIuYnVpbGQgPSBmdW5jdGlvbiBidWlsZChjb21waWxlciwgY2FsbGJhY2spIHsKICAgICAgdmFyIGJ1aWxkZXIgPSBuZXcgU3RkT3Bjb2RlQnVpbGRlcihjb21waWxlcik7CiAgICAgIGNhbGxiYWNrKGJ1aWxkZXIpOwogICAgICByZXR1cm4gYnVpbGRlci5jb21taXQoKTsKICAgIH07CgogICAgdmFyIF9wcm90bzExID0gU3RkT3Bjb2RlQnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMTEucHVzaCA9IGZ1bmN0aW9uIHB1c2gobmFtZSkgewogICAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGVyLmVuY29kZShuYW1lLCAwKTsKCiAgICAgICAgY2FzZSAyOgogICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2Rlci5lbmNvZGUobmFtZSwgMCwgYXJndW1lbnRzWzFdKTsKCiAgICAgICAgY2FzZSAzOgogICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2Rlci5lbmNvZGUobmFtZSwgMCwgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0pOwoKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2Rlci5lbmNvZGUobmFtZSwgMCwgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTEucHVzaE1hY2hpbmUgPSBmdW5jdGlvbiBwdXNoTWFjaGluZShuYW1lKSB7CiAgICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkgewogICAgICAgIGNhc2UgMToKICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZXIuZW5jb2RlKG5hbWUsIDEwMjQKICAgICAgICAgIC8qIE1BQ0hJTkVfTUFTSyAqLwogICAgICAgICAgKTsKCiAgICAgICAgY2FzZSAyOgogICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2Rlci5lbmNvZGUobmFtZSwgMTAyNAogICAgICAgICAgLyogTUFDSElORV9NQVNLICovCiAgICAgICAgICAsIGFyZ3VtZW50c1sxXSk7CgogICAgICAgIGNhc2UgMzoKICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZXIuZW5jb2RlKG5hbWUsIDEwMjQKICAgICAgICAgIC8qIE1BQ0hJTkVfTUFTSyAqLwogICAgICAgICAgLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSk7CgogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGVyLmVuY29kZShuYW1lLCAxMDI0CiAgICAgICAgICAvKiBNQUNISU5FX01BU0sgKi8KICAgICAgICAgICwgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0sIGFyZ3VtZW50c1szXSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTEuY29tbWl0ID0gZnVuY3Rpb24gY29tbWl0KCkgewogICAgICB0aGlzLnB1c2hNYWNoaW5lKDI0CiAgICAgIC8qIFJldHVybiAqLwogICAgICApOwogICAgICByZXR1cm4gdGhpcy5jb21waWxlci5jb21taXQodGhpcy5zaXplLCB0aGlzLmVuY29kZXIuYnVmZmVyKTsKICAgIH07CgogICAgX3Byb3RvMTEucmVzZXJ2ZSA9IGZ1bmN0aW9uIHJlc2VydmUobmFtZSkgewogICAgICB0aGlzLmVuY29kZXIuZW5jb2RlKG5hbWUsIDAsIC0xKTsKICAgIH07CgogICAgX3Byb3RvMTEucmVzZXJ2ZVdpdGhPcGVyYW5kID0gZnVuY3Rpb24gcmVzZXJ2ZVdpdGhPcGVyYW5kKG5hbWUsIG9wZXJhbmQpIHsKICAgICAgdGhpcy5lbmNvZGVyLmVuY29kZShuYW1lLCAwLCAtMSwgb3BlcmFuZCk7CiAgICB9OwoKICAgIF9wcm90bzExLnJlc2VydmVNYWNoaW5lID0gZnVuY3Rpb24gcmVzZXJ2ZU1hY2hpbmUobmFtZSkgewogICAgICB0aGlzLmVuY29kZXIuZW5jb2RlKG5hbWUsIDEwMjQKICAgICAgLyogTUFDSElORV9NQVNLICovCiAgICAgICwgLTEpOwogICAgfSAvLy8KICAgIDsKCiAgICBfcHJvdG8xMS5tYWluID0gZnVuY3Rpb24gbWFpbigpIHsKICAgICAgdGhpcy5wdXNoKDY4CiAgICAgIC8qIE1haW4gKi8KICAgICAgLCBfdm0uUmVnaXN0ZXIuczApOwogICAgICB0aGlzLmludm9rZVByZXBhcmVkQ29tcG9uZW50KGZhbHNlLCBmYWxzZSwgdHJ1ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLmFwcGVuZEhUTUwgPSBmdW5jdGlvbiBhcHBlbmRIVE1MKCkgewogICAgICB0aGlzLnB1c2goMjgKICAgICAgLyogQXBwZW5kSFRNTCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5hcHBlbmRTYWZlSFRNTCA9IGZ1bmN0aW9uIGFwcGVuZFNhZmVIVE1MKCkgewogICAgICB0aGlzLnB1c2goMjkKICAgICAgLyogQXBwZW5kU2FmZUhUTUwgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuYXBwZW5kRG9jdW1lbnRGcmFnbWVudCA9IGZ1bmN0aW9uIGFwcGVuZERvY3VtZW50RnJhZ21lbnQoKSB7CiAgICAgIHRoaXMucHVzaCgzMAogICAgICAvKiBBcHBlbmREb2N1bWVudEZyYWdtZW50ICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLmFwcGVuZE5vZGUgPSBmdW5jdGlvbiBhcHBlbmROb2RlKCkgewogICAgICB0aGlzLnB1c2goMzEKICAgICAgLyogQXBwZW5kTm9kZSAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5hcHBlbmRUZXh0ID0gZnVuY3Rpb24gYXBwZW5kVGV4dCgpIHsKICAgICAgdGhpcy5wdXNoKDMyCiAgICAgIC8qIEFwcGVuZFRleHQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuYmVnaW5Db21wb25lbnRUcmFuc2FjdGlvbiA9IGZ1bmN0aW9uIGJlZ2luQ29tcG9uZW50VHJhbnNhY3Rpb24oKSB7CiAgICAgIHRoaXMucHVzaCg5MQogICAgICAvKiBCZWdpbkNvbXBvbmVudFRyYW5zYWN0aW9uICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLmNvbW1pdENvbXBvbmVudFRyYW5zYWN0aW9uID0gZnVuY3Rpb24gY29tbWl0Q29tcG9uZW50VHJhbnNhY3Rpb24oKSB7CiAgICAgIHRoaXMucHVzaCg5MgogICAgICAvKiBDb21taXRDb21wb25lbnRUcmFuc2FjdGlvbiAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5wdXNoRHluYW1pY1Njb3BlID0gZnVuY3Rpb24gcHVzaER5bmFtaWNTY29wZSgpIHsKICAgICAgdGhpcy5wdXNoKDQ0CiAgICAgIC8qIFB1c2hEeW5hbWljU2NvcGUgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEucG9wRHluYW1pY1Njb3BlID0gZnVuY3Rpb24gcG9wRHluYW1pY1Njb3BlKCkgewogICAgICB0aGlzLnB1c2goNDUKICAgICAgLyogUG9wRHluYW1pY1Njb3BlICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLnB1c2hSZW1vdGVFbGVtZW50ID0gZnVuY3Rpb24gcHVzaFJlbW90ZUVsZW1lbnQoKSB7CiAgICAgIHRoaXMucHVzaCg0MQogICAgICAvKiBQdXNoUmVtb3RlRWxlbWVudCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5wb3BSZW1vdGVFbGVtZW50ID0gZnVuY3Rpb24gcG9wUmVtb3RlRWxlbWVudCgpIHsKICAgICAgdGhpcy5wdXNoKDQyCiAgICAgIC8qIFBvcFJlbW90ZUVsZW1lbnQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEucHVzaFJvb3RTY29wZSA9IGZ1bmN0aW9uIHB1c2hSb290U2NvcGUoc3ltYm9scywgYmluZENhbGxlclNjb3BlKSB7CiAgICAgIHRoaXMucHVzaCgyMAogICAgICAvKiBSb290U2NvcGUgKi8KICAgICAgLCBzeW1ib2xzLCBiaW5kQ2FsbGVyU2NvcGUgPyAxIDogMCk7CiAgICB9OwoKICAgIF9wcm90bzExLnB1c2hWaXJ0dWFsUm9vdFNjb3BlID0gZnVuY3Rpb24gcHVzaFZpcnR1YWxSb290U2NvcGUocmVnaXN0ZXIpIHsKICAgICAgdGhpcy5wdXNoKDIxCiAgICAgIC8qIFZpcnR1YWxSb290U2NvcGUgKi8KICAgICAgLCByZWdpc3Rlcik7CiAgICB9OwoKICAgIF9wcm90bzExLnB1c2hDaGlsZFNjb3BlID0gZnVuY3Rpb24gcHVzaENoaWxkU2NvcGUoKSB7CiAgICAgIHRoaXMucHVzaCgyMgogICAgICAvKiBDaGlsZFNjb3BlICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLnBvcFNjb3BlID0gZnVuY3Rpb24gcG9wU2NvcGUoKSB7CiAgICAgIHRoaXMucHVzaCgyMwogICAgICAvKiBQb3BTY29wZSAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5wcmVwYXJlQXJncyA9IGZ1bmN0aW9uIHByZXBhcmVBcmdzKHN0YXRlKSB7CiAgICAgIHRoaXMucHVzaCg3OQogICAgICAvKiBQcmVwYXJlQXJncyAqLwogICAgICAsIHN0YXRlKTsKICAgIH07CgogICAgX3Byb3RvMTEuY3JlYXRlQ29tcG9uZW50ID0gZnVuY3Rpb24gY3JlYXRlQ29tcG9uZW50KHN0YXRlLCBoYXNEZWZhdWx0KSB7CiAgICAgIHZhciBmbGFnID0gaGFzRGVmYXVsdCB8IDA7CiAgICAgIHRoaXMucHVzaCg4MQogICAgICAvKiBDcmVhdGVDb21wb25lbnQgKi8KICAgICAgLCBmbGFnLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLnJlZ2lzdGVyQ29tcG9uZW50RGVzdHJ1Y3RvciA9IGZ1bmN0aW9uIHJlZ2lzdGVyQ29tcG9uZW50RGVzdHJ1Y3RvcihzdGF0ZSkgewogICAgICB0aGlzLnB1c2goODIKICAgICAgLyogUmVnaXN0ZXJDb21wb25lbnREZXN0cnVjdG9yICovCiAgICAgICwgc3RhdGUpOwogICAgfTsKCiAgICBfcHJvdG8xMS5wdXRDb21wb25lbnRPcGVyYXRpb25zID0gZnVuY3Rpb24gcHV0Q29tcG9uZW50T3BlcmF0aW9ucygpIHsKICAgICAgdGhpcy5wdXNoKDgzCiAgICAgIC8qIFB1dENvbXBvbmVudE9wZXJhdGlvbnMgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuZ2V0Q29tcG9uZW50U2VsZiA9IGZ1bmN0aW9uIGdldENvbXBvbmVudFNlbGYoc3RhdGUpIHsKICAgICAgdGhpcy5wdXNoKDg0CiAgICAgIC8qIEdldENvbXBvbmVudFNlbGYgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLmdldENvbXBvbmVudFRhZ05hbWUgPSBmdW5jdGlvbiBnZXRDb21wb25lbnRUYWdOYW1lKHN0YXRlKSB7CiAgICAgIHRoaXMucHVzaCg4NQogICAgICAvKiBHZXRDb21wb25lbnRUYWdOYW1lICovCiAgICAgICwgc3RhdGUpOwogICAgfTsKCiAgICBfcHJvdG8xMS5nZXRDb21wb25lbnRMYXlvdXQgPSBmdW5jdGlvbiBnZXRDb21wb25lbnRMYXlvdXQoc3RhdGUpIHsKICAgICAgdGhpcy5wdXNoKDg2CiAgICAgIC8qIEdldENvbXBvbmVudExheW91dCAqLwogICAgICAsIHN0YXRlKTsKICAgIH07CgogICAgX3Byb3RvMTEuc2V0dXBGb3JFdmFsID0gZnVuY3Rpb24gc2V0dXBGb3JFdmFsKHN0YXRlKSB7CiAgICAgIHRoaXMucHVzaCg4NwogICAgICAvKiBTZXR1cEZvckV2YWwgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLmludm9rZUNvbXBvbmVudExheW91dCA9IGZ1bmN0aW9uIGludm9rZUNvbXBvbmVudExheW91dChzdGF0ZSkgewogICAgICB0aGlzLnB1c2goOTAKICAgICAgLyogSW52b2tlQ29tcG9uZW50TGF5b3V0ICovCiAgICAgICwgc3RhdGUpOwogICAgfTsKCiAgICBfcHJvdG8xMS5kaWRDcmVhdGVFbGVtZW50ID0gZnVuY3Rpb24gZGlkQ3JlYXRlRWxlbWVudChzdGF0ZSkgewogICAgICB0aGlzLnB1c2goOTMKICAgICAgLyogRGlkQ3JlYXRlRWxlbWVudCAqLwogICAgICAsIHN0YXRlKTsKICAgIH07CgogICAgX3Byb3RvMTEuZGlkUmVuZGVyTGF5b3V0ID0gZnVuY3Rpb24gZGlkUmVuZGVyTGF5b3V0KHN0YXRlKSB7CiAgICAgIHRoaXMucHVzaCg5NAogICAgICAvKiBEaWRSZW5kZXJMYXlvdXQgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLnB1c2hGcmFtZSA9IGZ1bmN0aW9uIHB1c2hGcmFtZSgpIHsKICAgICAgdGhpcy5wdXNoTWFjaGluZSg1NwogICAgICAvKiBQdXNoRnJhbWUgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEucG9wRnJhbWUgPSBmdW5jdGlvbiBwb3BGcmFtZSgpIHsKICAgICAgdGhpcy5wdXNoTWFjaGluZSg1OAogICAgICAvKiBQb3BGcmFtZSAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5wdXNoU21hbGxGcmFtZSA9IGZ1bmN0aW9uIHB1c2hTbWFsbEZyYW1lKCkgewogICAgICB0aGlzLnB1c2hNYWNoaW5lKDU5CiAgICAgIC8qIFB1c2hTbWFsbEZyYW1lICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLnBvcFNtYWxsRnJhbWUgPSBmdW5jdGlvbiBwb3BTbWFsbEZyYW1lKCkgewogICAgICB0aGlzLnB1c2hNYWNoaW5lKDYwCiAgICAgIC8qIFBvcFNtYWxsRnJhbWUgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuaW52b2tlVmlydHVhbCA9IGZ1bmN0aW9uIGludm9rZVZpcnR1YWwoKSB7CiAgICAgIHRoaXMucHVzaE1hY2hpbmUoNDkKICAgICAgLyogSW52b2tlVmlydHVhbCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5pbnZva2VZaWVsZCA9IGZ1bmN0aW9uIGludm9rZVlpZWxkKCkgewogICAgICB0aGlzLnB1c2goNTEKICAgICAgLyogSW52b2tlWWllbGQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEudG9Cb29sZWFuID0gZnVuY3Rpb24gdG9Cb29sZWFuKCkgewogICAgICB0aGlzLnB1c2goNjMKICAgICAgLyogVG9Cb29sZWFuICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLmludm9rZVByZXBhcmVkQ29tcG9uZW50ID0gZnVuY3Rpb24gaW52b2tlUHJlcGFyZWRDb21wb25lbnQoaGFzQmxvY2ssIGJpbmRhYmxlQmxvY2tzLCBiaW5kYWJsZUF0TmFtZXMsIHBvcHVsYXRlTGF5b3V0KSB7CiAgICAgIGlmIChwb3B1bGF0ZUxheW91dCA9PT0gdm9pZCAwKSB7CiAgICAgICAgcG9wdWxhdGVMYXlvdXQgPSBudWxsOwogICAgICB9CgogICAgICB0aGlzLmJlZ2luQ29tcG9uZW50VHJhbnNhY3Rpb24oKTsKICAgICAgdGhpcy5wdXNoRHluYW1pY1Njb3BlKCk7CiAgICAgIHRoaXMuY3JlYXRlQ29tcG9uZW50KF92bS5SZWdpc3Rlci5zMCwgaGFzQmxvY2spOyAvLyB0aGlzIGhhcyB0byBydW4gYWZ0ZXIgY3JlYXRlQ29tcG9uZW50IHRvIGFsbG93CiAgICAgIC8vIGZvciBsYXRlLWJvdW5kIGxheW91dHMsIGJ1dCBhIGNhbGxlciBpcyBmcmVlCiAgICAgIC8vIHRvIHBvcHVsYXRlIHRoZSBsYXlvdXQgZWFybGllciBpZiBpdCB3YW50cyB0bwogICAgICAvLyBhbmQgZG8gbm90aGluZyBoZXJlLgoKICAgICAgaWYgKHBvcHVsYXRlTGF5b3V0KSBwb3B1bGF0ZUxheW91dCgpOwogICAgICB0aGlzLnJlZ2lzdGVyQ29tcG9uZW50RGVzdHJ1Y3Rvcihfdm0uUmVnaXN0ZXIuczApOwogICAgICB0aGlzLmdldENvbXBvbmVudFNlbGYoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5wdXNoVmlydHVhbFJvb3RTY29wZShfdm0uUmVnaXN0ZXIuczApOwogICAgICB0aGlzLnNldFZhcmlhYmxlKDApOwogICAgICB0aGlzLnNldHVwRm9yRXZhbChfdm0uUmVnaXN0ZXIuczApOwogICAgICBpZiAoYmluZGFibGVBdE5hbWVzKSB0aGlzLnNldE5hbWVkVmFyaWFibGVzKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIGlmIChiaW5kYWJsZUJsb2NrcykgdGhpcy5zZXRCbG9ja3MoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5wb3AoKTsKICAgICAgdGhpcy5pbnZva2VDb21wb25lbnRMYXlvdXQoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5kaWRSZW5kZXJMYXlvdXQoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5wb3BGcmFtZSgpOwogICAgICB0aGlzLnBvcFNjb3BlKCk7CiAgICAgIHRoaXMucG9wRHluYW1pY1Njb3BlKCk7CiAgICAgIHRoaXMuY29tbWl0Q29tcG9uZW50VHJhbnNhY3Rpb24oKTsKICAgIH07CgogICAgLy8vCiAgICBfcHJvdG8xMS5jb21waWxlSW5saW5lID0gZnVuY3Rpb24gY29tcGlsZUlubGluZShzZXhwKSB7CiAgICAgIHJldHVybiB0aGlzLmNvbXBpbGVyLmNvbXBpbGVJbmxpbmUoc2V4cCwgdGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzExLmNvbXBpbGVCbG9jayA9IGZ1bmN0aW9uIGNvbXBpbGVCbG9jayhuYW1lLCBwYXJhbXMsIGhhc2gsIHRlbXBsYXRlLCBpbnZlcnNlKSB7CiAgICAgIHRoaXMuY29tcGlsZXIuY29tcGlsZUJsb2NrKG5hbWUsIHBhcmFtcywgaGFzaCwgdGVtcGxhdGUsIGludmVyc2UsIHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG8xMS5sYWJlbCA9IGZ1bmN0aW9uIGxhYmVsKG5hbWUpIHsKICAgICAgdGhpcy5sYWJlbHMubGFiZWwobmFtZSwgdGhpcy5uZXh0UG9zKTsKICAgIH0gLy8gaGVscGVycwogICAgOwoKICAgIF9wcm90bzExLnN0YXJ0TGFiZWxzID0gZnVuY3Rpb24gc3RhcnRMYWJlbHMoKSB7CiAgICAgIHRoaXMubGFiZWxzU3RhY2sucHVzaChuZXcgTGFiZWxzKCkpOwogICAgfTsKCiAgICBfcHJvdG8xMS5zdG9wTGFiZWxzID0gZnVuY3Rpb24gc3RvcExhYmVscygpIHsKICAgICAgdmFyIGxhYmVsID0gdGhpcy5sYWJlbHNTdGFjay5wb3AoKTsKICAgICAgbGFiZWwucGF0Y2godGhpcy5lbmNvZGVyKTsKICAgIH0gLy8gY29tcG9uZW50cwogICAgOwoKICAgIF9wcm90bzExLnB1c2hDdXJyaWVkQ29tcG9uZW50ID0gZnVuY3Rpb24gcHVzaEN1cnJpZWRDb21wb25lbnQoKSB7CiAgICAgIHRoaXMucHVzaCg3NAogICAgICAvKiBQdXNoQ3VycmllZENvbXBvbmVudCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5wdXNoRHluYW1pY0NvbXBvbmVudEluc3RhbmNlID0gZnVuY3Rpb24gcHVzaER5bmFtaWNDb21wb25lbnRJbnN0YW5jZSgpIHsKICAgICAgdGhpcy5wdXNoKDczCiAgICAgIC8qIFB1c2hEeW5hbWljQ29tcG9uZW50SW5zdGFuY2UgKi8KICAgICAgKTsKICAgIH0gLy8gZG9tCiAgICA7CgogICAgX3Byb3RvMTEub3BlbkR5bmFtaWNFbGVtZW50ID0gZnVuY3Rpb24gb3BlbkR5bmFtaWNFbGVtZW50KCkgewogICAgICB0aGlzLnB1c2goMzQKICAgICAgLyogT3BlbkR5bmFtaWNFbGVtZW50ICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLmZsdXNoRWxlbWVudCA9IGZ1bmN0aW9uIGZsdXNoRWxlbWVudCgpIHsKICAgICAgdGhpcy5wdXNoKDM4CiAgICAgIC8qIEZsdXNoRWxlbWVudCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5jbG9zZUVsZW1lbnQgPSBmdW5jdGlvbiBjbG9zZUVsZW1lbnQoKSB7CiAgICAgIHRoaXMucHVzaCgzOQogICAgICAvKiBDbG9zZUVsZW1lbnQgKi8KICAgICAgKTsKICAgIH0gLy8gbGlzdHMKICAgIDsKCiAgICBfcHJvdG8xMS5wdXRJdGVyYXRvciA9IGZ1bmN0aW9uIHB1dEl0ZXJhdG9yKCkgewogICAgICB0aGlzLnB1c2goNjYKICAgICAgLyogUHV0SXRlcmF0b3IgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuZW50ZXJMaXN0ID0gZnVuY3Rpb24gZW50ZXJMaXN0KHN0YXJ0KSB7CiAgICAgIHRoaXMucmVzZXJ2ZSg2NAogICAgICAvKiBFbnRlckxpc3QgKi8KICAgICAgKTsKICAgICAgdGhpcy5sYWJlbHMudGFyZ2V0KHRoaXMucG9zLCBzdGFydCk7CiAgICB9OwoKICAgIF9wcm90bzExLmV4aXRMaXN0ID0gZnVuY3Rpb24gZXhpdExpc3QoKSB7CiAgICAgIHRoaXMucHVzaCg2NQogICAgICAvKiBFeGl0TGlzdCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5pdGVyYXRlID0gZnVuY3Rpb24gaXRlcmF0ZShicmVha3MpIHsKICAgICAgdGhpcy5yZXNlcnZlKDY3CiAgICAgIC8qIEl0ZXJhdGUgKi8KICAgICAgKTsKICAgICAgdGhpcy5sYWJlbHMudGFyZ2V0KHRoaXMucG9zLCBicmVha3MpOwogICAgfSAvLyBleHByZXNzaW9ucwogICAgOwoKICAgIF9wcm90bzExLnNldE5hbWVkVmFyaWFibGVzID0gZnVuY3Rpb24gc2V0TmFtZWRWYXJpYWJsZXMoc3RhdGUpIHsKICAgICAgdGhpcy5wdXNoKDIKICAgICAgLyogU2V0TmFtZWRWYXJpYWJsZXMgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLnNldEJsb2NrcyA9IGZ1bmN0aW9uIHNldEJsb2NrcyhzdGF0ZSkgewogICAgICB0aGlzLnB1c2goMwogICAgICAvKiBTZXRCbG9ja3MgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLnNldFZhcmlhYmxlID0gZnVuY3Rpb24gc2V0VmFyaWFibGUoc3ltYm9sKSB7CiAgICAgIHRoaXMucHVzaCg0CiAgICAgIC8qIFNldFZhcmlhYmxlICovCiAgICAgICwgc3ltYm9sKTsKICAgIH07CgogICAgX3Byb3RvMTEuc2V0QmxvY2sgPSBmdW5jdGlvbiBzZXRCbG9jayhzeW1ib2wpIHsKICAgICAgdGhpcy5wdXNoKDUKICAgICAgLyogU2V0QmxvY2sgKi8KICAgICAgLCBzeW1ib2wpOwogICAgfTsKCiAgICBfcHJvdG8xMS5nZXRWYXJpYWJsZSA9IGZ1bmN0aW9uIGdldFZhcmlhYmxlKHN5bWJvbCkgewogICAgICB0aGlzLnB1c2goNgogICAgICAvKiBHZXRWYXJpYWJsZSAqLwogICAgICAsIHN5bWJvbCk7CiAgICB9OwoKICAgIF9wcm90bzExLmdldEJsb2NrID0gZnVuY3Rpb24gZ2V0QmxvY2soc3ltYm9sKSB7CiAgICAgIHRoaXMucHVzaCg4CiAgICAgIC8qIEdldEJsb2NrICovCiAgICAgICwgc3ltYm9sKTsKICAgIH07CgogICAgX3Byb3RvMTEuaGFzQmxvY2sgPSBmdW5jdGlvbiBoYXNCbG9jayhzeW1ib2wpIHsKICAgICAgdGhpcy5wdXNoKDkKICAgICAgLyogSGFzQmxvY2sgKi8KICAgICAgLCBzeW1ib2wpOwogICAgfTsKCiAgICBfcHJvdG8xMS5jb25jYXQgPSBmdW5jdGlvbiBjb25jYXQoc2l6ZSkgewogICAgICB0aGlzLnB1c2goMTEKICAgICAgLyogQ29uY2F0ICovCiAgICAgICwgc2l6ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLmxvYWQgPSBmdW5jdGlvbiBsb2FkKHJlZ2lzdGVyKSB7CiAgICAgIHRoaXMucHVzaCgxOAogICAgICAvKiBMb2FkICovCiAgICAgICwgcmVnaXN0ZXIpOwogICAgfTsKCiAgICBfcHJvdG8xMS5mZXRjaCA9IGZ1bmN0aW9uIGZldGNoKHJlZ2lzdGVyKSB7CiAgICAgIHRoaXMucHVzaCgxOQogICAgICAvKiBGZXRjaCAqLwogICAgICAsIHJlZ2lzdGVyKTsKICAgIH07CgogICAgX3Byb3RvMTEuZHVwID0gZnVuY3Rpb24gZHVwKHJlZ2lzdGVyLCBvZmZzZXQpIHsKICAgICAgaWYgKHJlZ2lzdGVyID09PSB2b2lkIDApIHsKICAgICAgICByZWdpc3RlciA9IF92bS5SZWdpc3Rlci5zcDsKICAgICAgfQoKICAgICAgaWYgKG9mZnNldCA9PT0gdm9pZCAwKSB7CiAgICAgICAgb2Zmc2V0ID0gMDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMucHVzaCgxNgogICAgICAvKiBEdXAgKi8KICAgICAgLCByZWdpc3Rlciwgb2Zmc2V0KTsKICAgIH07CgogICAgX3Byb3RvMTEucG9wID0gZnVuY3Rpb24gcG9wKGNvdW50KSB7CiAgICAgIGlmIChjb3VudCA9PT0gdm9pZCAwKSB7CiAgICAgICAgY291bnQgPSAxOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5wdXNoKDE3CiAgICAgIC8qIFBvcCAqLwogICAgICAsIGNvdW50KTsKICAgIH0gLy8gdm0KICAgIDsKCiAgICBfcHJvdG8xMS5yZXR1cm5UbyA9IGZ1bmN0aW9uIHJldHVyblRvKGxhYmVsKSB7CiAgICAgIHRoaXMucmVzZXJ2ZU1hY2hpbmUoMjUKICAgICAgLyogUmV0dXJuVG8gKi8KICAgICAgKTsKICAgICAgdGhpcy5sYWJlbHMudGFyZ2V0KHRoaXMucG9zLCBsYWJlbCk7CiAgICB9OwoKICAgIF9wcm90bzExLnByaW1pdGl2ZVJlZmVyZW5jZSA9IGZ1bmN0aW9uIHByaW1pdGl2ZVJlZmVyZW5jZSgpIHsKICAgICAgdGhpcy5wdXNoKDE0CiAgICAgIC8qIFByaW1pdGl2ZVJlZmVyZW5jZSAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMS5yZWlmeVUzMiA9IGZ1bmN0aW9uIHJlaWZ5VTMyKCkgewogICAgICB0aGlzLnB1c2goMTUKICAgICAgLyogUmVpZnlVMzIgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuZW50ZXIgPSBmdW5jdGlvbiBlbnRlcihhcmdzKSB7CiAgICAgIHRoaXMucHVzaCg2MQogICAgICAvKiBFbnRlciAqLwogICAgICAsIGFyZ3MpOwogICAgfTsKCiAgICBfcHJvdG8xMS5leGl0ID0gZnVuY3Rpb24gZXhpdCgpIHsKICAgICAgdGhpcy5wdXNoKDYyCiAgICAgIC8qIEV4aXQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEucmV0dXJuID0gZnVuY3Rpb24gX3JldHVybigpIHsKICAgICAgdGhpcy5wdXNoTWFjaGluZSgyNAogICAgICAvKiBSZXR1cm4gKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuanVtcCA9IGZ1bmN0aW9uIGp1bXAodGFyZ2V0KSB7CiAgICAgIHRoaXMucmVzZXJ2ZU1hY2hpbmUoNTIKICAgICAgLyogSnVtcCAqLwogICAgICApOwogICAgICB0aGlzLmxhYmVscy50YXJnZXQodGhpcy5wb3MsIHRhcmdldCk7CiAgICB9OwoKICAgIF9wcm90bzExLmp1bXBJZiA9IGZ1bmN0aW9uIGp1bXBJZih0YXJnZXQpIHsKICAgICAgdGhpcy5yZXNlcnZlKDUzCiAgICAgIC8qIEp1bXBJZiAqLwogICAgICApOwogICAgICB0aGlzLmxhYmVscy50YXJnZXQodGhpcy5wb3MsIHRhcmdldCk7CiAgICB9OwoKICAgIF9wcm90bzExLmp1bXBVbmxlc3MgPSBmdW5jdGlvbiBqdW1wVW5sZXNzKHRhcmdldCkgewogICAgICB0aGlzLnJlc2VydmUoNTQKICAgICAgLyogSnVtcFVubGVzcyAqLwogICAgICApOwogICAgICB0aGlzLmxhYmVscy50YXJnZXQodGhpcy5wb3MsIHRhcmdldCk7CiAgICB9OwoKICAgIF9wcm90bzExLmp1bXBFcSA9IGZ1bmN0aW9uIGp1bXBFcSh2YWx1ZSwgdGFyZ2V0KSB7CiAgICAgIHRoaXMucmVzZXJ2ZVdpdGhPcGVyYW5kKDU1CiAgICAgIC8qIEp1bXBFcSAqLwogICAgICAsIHZhbHVlKTsKICAgICAgdGhpcy5sYWJlbHMudGFyZ2V0KHRoaXMucG9zLCB0YXJnZXQpOwogICAgfTsKCiAgICBfcHJvdG8xMS5hc3NlcnRTYW1lID0gZnVuY3Rpb24gYXNzZXJ0U2FtZSgpIHsKICAgICAgdGhpcy5wdXNoKDU2CiAgICAgIC8qIEFzc2VydFNhbWUgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEucHVzaEVtcHR5QXJncyA9IGZ1bmN0aW9uIHB1c2hFbXB0eUFyZ3MoKSB7CiAgICAgIHRoaXMucHVzaCg3NwogICAgICAvKiBQdXNoRW1wdHlBcmdzICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLnN3aXRjaCA9IGZ1bmN0aW9uIF9zd2l0Y2goX29wY29kZSwgY2FsbGJhY2spIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIC8vIFNldHVwIHRoZSBzd2l0Y2ggRFNMCiAgICAgIHZhciBjbGF1c2VzID0gW107CiAgICAgIHZhciBjb3VudCA9IDA7CgogICAgICBmdW5jdGlvbiB3aGVuKG1hdGNoLCBjYWxsYmFjaykgewogICAgICAgIGNsYXVzZXMucHVzaCh7CiAgICAgICAgICBtYXRjaDogbWF0Y2gsCiAgICAgICAgICBjYWxsYmFjazogY2FsbGJhY2ssCiAgICAgICAgICBsYWJlbDogIkNMQVVTRSIgKyBjb3VudCsrCiAgICAgICAgfSk7CiAgICAgIH0gLy8gQ2FsbCB0aGUgY2FsbGJhY2sKCgogICAgICBjYWxsYmFjayh3aGVuKTsgLy8gRW1pdCB0aGUgb3Bjb2RlcyBmb3IgdGhlIHN3aXRjaAoKICAgICAgdGhpcy5lbnRlcigyKTsKICAgICAgdGhpcy5hc3NlcnRTYW1lKCk7CiAgICAgIHRoaXMucmVpZnlVMzIoKTsKICAgICAgdGhpcy5zdGFydExhYmVscygpOyAvLyBGaXJzdCwgZW1pdCB0aGUganVtcCBvcGNvZGVzLiBXZSBkb24ndCBuZWVkIGEganVtcCBmb3IgdGhlIGxhc3QKICAgICAgLy8gb3Bjb2RlLCBzaW5jZSBpdCBibGVlZHMgZGlyZWN0bHkgaW50byBpdHMgY2xhdXNlLgoKICAgICAgY2xhdXNlcy5zbGljZSgwLCAtMSkuZm9yRWFjaChmdW5jdGlvbiAoY2xhdXNlKSB7CiAgICAgICAgcmV0dXJuIF90aGlzLmp1bXBFcShjbGF1c2UubWF0Y2gsIGNsYXVzZS5sYWJlbCk7CiAgICAgIH0pOyAvLyBFbnVtZXJhdGUgdGhlIGNsYXVzZXMgaW4gcmV2ZXJzZSBvcmRlci4gRWFybGllciBtYXRjaGVzIHdpbGwKICAgICAgLy8gcmVxdWlyZSBmZXdlciBjaGVja3MuCgogICAgICBmb3IgKHZhciBpID0gY2xhdXNlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICAgIHZhciBjbGF1c2UgPSBjbGF1c2VzW2ldOwogICAgICAgIHRoaXMubGFiZWwoY2xhdXNlLmxhYmVsKTsKICAgICAgICB0aGlzLnBvcCgyKTsKICAgICAgICBjbGF1c2UuY2FsbGJhY2soKTsgLy8gVGhlIGZpcnN0IG1hdGNoIGlzIHNwZWNpYWw6IGl0IGlzIHBsYWNlZCBkaXJlY3RseSBiZWZvcmUgdGhlIEVORAogICAgICAgIC8vIGxhYmVsLCBzbyBubyBhZGRpdGlvbmFsIGp1bXAgaXMgbmVlZGVkIGF0IHRoZSBlbmQgb2YgaXQuCgogICAgICAgIGlmIChpICE9PSAwKSB7CiAgICAgICAgICB0aGlzLmp1bXAoJ0VORCcpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdGhpcy5sYWJlbCgnRU5EJyk7CiAgICAgIHRoaXMuc3RvcExhYmVscygpOwogICAgICB0aGlzLmV4aXQoKTsKICAgIH07CgogICAgX3Byb3RvMTEuc3RkQXBwZW5kID0gZnVuY3Rpb24gc3RkQXBwZW5kKHRydXN0aW5nKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgdGhpcy5zd2l0Y2godGhpcy5jb250ZW50VHlwZSgpLCBmdW5jdGlvbiAod2hlbikgewogICAgICAgIHdoZW4oMQogICAgICAgIC8qIFN0cmluZyAqLwogICAgICAgICwgZnVuY3Rpb24gKCkgewogICAgICAgICAgaWYgKHRydXN0aW5nKSB7CiAgICAgICAgICAgIF90aGlzMi5hc3NlcnRTYW1lKCk7CgogICAgICAgICAgICBfdGhpczIuYXBwZW5kSFRNTCgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgX3RoaXMyLmFwcGVuZFRleHQoKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgICB3aGVuKDAKICAgICAgICAvKiBDb21wb25lbnQgKi8KICAgICAgICAsIGZ1bmN0aW9uICgpIHsKICAgICAgICAgIF90aGlzMi5wdXNoQ3VycmllZENvbXBvbmVudCgpOwoKICAgICAgICAgIF90aGlzMi5wdXNoRHluYW1pY0NvbXBvbmVudEluc3RhbmNlKCk7CgogICAgICAgICAgX3RoaXMyLmludm9rZUJhcmVDb21wb25lbnQoKTsKICAgICAgICB9KTsKICAgICAgICB3aGVuKDMKICAgICAgICAvKiBTYWZlU3RyaW5nICovCiAgICAgICAgLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBfdGhpczIuYXNzZXJ0U2FtZSgpOwoKICAgICAgICAgIF90aGlzMi5hcHBlbmRTYWZlSFRNTCgpOwogICAgICAgIH0pOwogICAgICAgIHdoZW4oNAogICAgICAgIC8qIEZyYWdtZW50ICovCiAgICAgICAgLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICBfdGhpczIuYXNzZXJ0U2FtZSgpOwoKICAgICAgICAgIF90aGlzMi5hcHBlbmREb2N1bWVudEZyYWdtZW50KCk7CiAgICAgICAgfSk7CiAgICAgICAgd2hlbig1CiAgICAgICAgLyogTm9kZSAqLwogICAgICAgICwgZnVuY3Rpb24gKCkgewogICAgICAgICAgX3RoaXMyLmFzc2VydFNhbWUoKTsKCiAgICAgICAgICBfdGhpczIuYXBwZW5kTm9kZSgpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvMTEucG9wdWxhdGVMYXlvdXQgPSBmdW5jdGlvbiBwb3B1bGF0ZUxheW91dChzdGF0ZSkgewogICAgICB0aGlzLnB1c2goODkKICAgICAgLyogUG9wdWxhdGVMYXlvdXQgKi8KICAgICAgLCBzdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzExLmludm9rZUJhcmVDb21wb25lbnQgPSBmdW5jdGlvbiBpbnZva2VCYXJlQ29tcG9uZW50KCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHRoaXMuZmV0Y2goX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5kdXAoX3ZtLlJlZ2lzdGVyLnNwLCAxKTsKICAgICAgdGhpcy5sb2FkKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHRoaXMucHVzaEZyYW1lKCk7CiAgICAgIHRoaXMucHVzaEVtcHR5QXJncygpOwogICAgICB0aGlzLnByZXBhcmVBcmdzKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHRoaXMuaW52b2tlUHJlcGFyZWRDb21wb25lbnQoZmFsc2UsIGZhbHNlLCB0cnVlLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgX3RoaXMzLmdldENvbXBvbmVudExheW91dChfdm0uUmVnaXN0ZXIuczApOwoKICAgICAgICBfdGhpczMucG9wdWxhdGVMYXlvdXQoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgfSk7CiAgICAgIHRoaXMubG9hZChfdm0uUmVnaXN0ZXIuczApOwogICAgfTsKCiAgICBfcHJvdG8xMS5pc0NvbXBvbmVudCA9IGZ1bmN0aW9uIGlzQ29tcG9uZW50KCkgewogICAgICB0aGlzLnB1c2goNjkKICAgICAgLyogSXNDb21wb25lbnQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTEuY29udGVudFR5cGUgPSBmdW5jdGlvbiBjb250ZW50VHlwZSgpIHsKICAgICAgdGhpcy5wdXNoKDcwCiAgICAgIC8qIENvbnRlbnRUeXBlICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzExLnB1c2hCbG9ja1Njb3BlID0gZnVuY3Rpb24gcHVzaEJsb2NrU2NvcGUoKSB7CiAgICAgIHRoaXMucHVzaCg0NwogICAgICAvKiBQdXNoQmxvY2tTY29wZSAqLwogICAgICApOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKFN0ZE9wY29kZUJ1aWxkZXIsIFt7CiAgICAgIGtleTogInBvcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmVuY29kZXIudHlwZVBvczsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJuZXh0UG9zIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2Rlci5zaXplOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImxhYmVscyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmxhYmVsc1N0YWNrLmN1cnJlbnQ7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBTdGRPcGNvZGVCdWlsZGVyOwogIH0oKTsKCiAgX2V4cG9ydHMuU3RkT3Bjb2RlQnVpbGRlciA9IFN0ZE9wY29kZUJ1aWxkZXI7CgogIHZhciBPcGNvZGVCdWlsZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9TdGRPcGNvZGVCdWlsZGVyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoT3Bjb2RlQnVpbGRlciwgX1N0ZE9wY29kZUJ1aWxkZXIpOwoKICAgIGZ1bmN0aW9uIE9wY29kZUJ1aWxkZXIoY29tcGlsZXIsIGNvbnRhaW5pbmdMYXlvdXQpIHsKICAgICAgdmFyIF90aGlzNDsKCiAgICAgIF90aGlzNCA9IF9TdGRPcGNvZGVCdWlsZGVyLmNhbGwodGhpcywgY29tcGlsZXIsIGNvbnRhaW5pbmdMYXlvdXQgPyBjb250YWluaW5nTGF5b3V0LmJsb2NrLnN5bWJvbHMubGVuZ3RoIDogMCkgfHwgdGhpczsKICAgICAgX3RoaXM0LmNvbnRhaW5pbmdMYXlvdXQgPSBjb250YWluaW5nTGF5b3V0OwogICAgICBfdGhpczQuY29tcG9uZW50ID0gbmV3IENvbXBvbmVudEJ1aWxkZXIoKDAsIF9lbWJlckJhYmVsLmFzc2VydFRoaXNJbml0aWFsaXplZCkoX3RoaXM0KSk7CiAgICAgIF90aGlzNC5leHByZXNzaW9uQ29tcGlsZXIgPSBleHByZXNzaW9uQ29tcGlsZXIoKTsKICAgICAgX3RoaXM0LmNvbnN0YW50cyA9IGNvbXBpbGVyLmNvbnN0YW50czsKICAgICAgX3RoaXM0LnN0ZExpYiA9IGNvbXBpbGVyLnN0ZExpYjsKICAgICAgcmV0dXJuIF90aGlzNDsKICAgIH0gLy8vIE1FQ0hBTklDUwoKCiAgICB2YXIgX3Byb3RvMTIgPSBPcGNvZGVCdWlsZGVyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xMi5leHByID0gZnVuY3Rpb24gZXhwcihleHByZXNzaW9uKSB7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KGV4cHJlc3Npb24pKSB7CiAgICAgICAgdGhpcy5leHByZXNzaW9uQ29tcGlsZXIuY29tcGlsZShleHByZXNzaW9uLCB0aGlzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnB1c2hQcmltaXRpdmVSZWZlcmVuY2UoZXhwcmVzc2lvbik7CiAgICAgIH0KICAgIH0gLy8vCiAgICAvLyBhcmdzCiAgICA7CgogICAgX3Byb3RvMTIucHVzaEFyZ3MgPSBmdW5jdGlvbiBwdXNoQXJncyhuYW1lcywgZmxhZ3MpIHsKICAgICAgdmFyIHNlcmlhbGl6ZWQgPSB0aGlzLmNvbnN0YW50cy5zdHJpbmdBcnJheShuYW1lcyk7CiAgICAgIHRoaXMucHVzaCg3NgogICAgICAvKiBQdXNoQXJncyAqLwogICAgICAsIHNlcmlhbGl6ZWQsIGZsYWdzKTsKICAgIH07CgogICAgX3Byb3RvMTIucHVzaFlpZWxkYWJsZUJsb2NrID0gZnVuY3Rpb24gcHVzaFlpZWxkYWJsZUJsb2NrKGJsb2NrKSB7CiAgICAgIHRoaXMucHVzaFN5bWJvbFRhYmxlKGJsb2NrICYmIGJsb2NrLnN5bWJvbFRhYmxlKTsKICAgICAgdGhpcy5wdXNoQmxvY2tTY29wZSgpOwogICAgICB0aGlzLnB1c2hCbG9jayhibG9jayk7CiAgICB9OwoKICAgIF9wcm90bzEyLmN1cnJ5Q29tcG9uZW50ID0gZnVuY3Rpb24gY3VycnlDb21wb25lbnQoZGVmaW5pdGlvbiwKICAgIC8qIFRPRE86IGF0dHJzOiBPcHRpb248UmF3SW5saW5lQmxvY2s+LCAqLwogICAgcGFyYW1zLCBoYXNoLCBzeW50aGV0aWMpIHsKICAgICAgdmFyIHJlZmVycmVyID0gdGhpcy5jb250YWluaW5nTGF5b3V0LnJlZmVycmVyOwogICAgICB0aGlzLnB1c2hGcmFtZSgpOwogICAgICB0aGlzLmNvbXBpbGVBcmdzKHBhcmFtcywgaGFzaCwgbnVsbCwgc3ludGhldGljKTsKICAgICAgdGhpcy5wdXNoKDgwCiAgICAgIC8qIENhcHR1cmVBcmdzICovCiAgICAgICk7CiAgICAgIHRoaXMuZXhwcihkZWZpbml0aW9uKTsKICAgICAgdGhpcy5wdXNoKDcxCiAgICAgIC8qIEN1cnJ5Q29tcG9uZW50ICovCiAgICAgICwgdGhpcy5jb25zdGFudHMuc2VyaWFsaXphYmxlKHJlZmVycmVyKSk7CiAgICAgIHRoaXMucG9wRnJhbWUoKTsKICAgICAgdGhpcy5mZXRjaChfdm0uUmVnaXN0ZXIudjApOwogICAgfTsKCiAgICBfcHJvdG8xMi5wdXNoU3ltYm9sVGFibGUgPSBmdW5jdGlvbiBwdXNoU3ltYm9sVGFibGUodGFibGUpIHsKICAgICAgaWYgKHRhYmxlKSB7CiAgICAgICAgdmFyIGNvbnN0YW50ID0gdGhpcy5jb25zdGFudHMuc2VyaWFsaXphYmxlKHRhYmxlKTsKICAgICAgICB0aGlzLnB1c2goNDgKICAgICAgICAvKiBQdXNoU3ltYm9sVGFibGUgKi8KICAgICAgICAsIGNvbnN0YW50KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnByaW1pdGl2ZShudWxsKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8xMi5pbnZva2VDb21wb25lbnQgPSBmdW5jdGlvbiBpbnZva2VDb21wb25lbnQoY2FwYWJpbGl0aWVzLCBhdHRycywgcGFyYW1zLCBoYXNoLCBzeW50aGV0aWMsIGJsb2NrLCBpbnZlcnNlLCBsYXlvdXQpIHsKICAgICAgdmFyIF90aGlzNSA9IHRoaXM7CgogICAgICBpZiAoaW52ZXJzZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgaW52ZXJzZSA9IG51bGw7CiAgICAgIH0KCiAgICAgIHRoaXMuZmV0Y2goX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5kdXAoX3ZtLlJlZ2lzdGVyLnNwLCAxKTsKICAgICAgdGhpcy5sb2FkKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHRoaXMucHVzaEZyYW1lKCk7CiAgICAgIHZhciBiaW5kYWJsZUJsb2NrcyA9ICEhKGJsb2NrIHx8IGludmVyc2UgfHwgYXR0cnMpOwogICAgICB2YXIgYmluZGFibGVBdE5hbWVzID0gY2FwYWJpbGl0aWVzID09PSB0cnVlIHx8IGNhcGFiaWxpdGllcy5wcmVwYXJlQXJncyB8fCAhIShoYXNoICYmIGhhc2hbMF0ubGVuZ3RoICE9PSAwKTsKICAgICAgdmFyIGJsb2NrcyA9IHsKICAgICAgICBtYWluOiBibG9jaywKICAgICAgICBlbHNlOiBpbnZlcnNlLAogICAgICAgIGF0dHJzOiBhdHRycwogICAgICB9OwogICAgICB0aGlzLmNvbXBpbGVBcmdzKHBhcmFtcywgaGFzaCwgYmxvY2tzLCBzeW50aGV0aWMpOwogICAgICB0aGlzLnByZXBhcmVBcmdzKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHRoaXMuaW52b2tlUHJlcGFyZWRDb21wb25lbnQoYmxvY2sgIT09IG51bGwsIGJpbmRhYmxlQmxvY2tzLCBiaW5kYWJsZUF0TmFtZXMsIGZ1bmN0aW9uICgpIHsKICAgICAgICBpZiAobGF5b3V0KSB7CiAgICAgICAgICBfdGhpczUucHVzaFN5bWJvbFRhYmxlKGxheW91dC5zeW1ib2xUYWJsZSk7CgogICAgICAgICAgX3RoaXM1LnB1c2hMYXlvdXQobGF5b3V0KTsKCiAgICAgICAgICBfdGhpczUucmVzb2x2ZUxheW91dCgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBfdGhpczUuZ2V0Q29tcG9uZW50TGF5b3V0KF92bS5SZWdpc3Rlci5zMCk7CiAgICAgICAgfQoKICAgICAgICBfdGhpczUucG9wdWxhdGVMYXlvdXQoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgfSk7CiAgICAgIHRoaXMubG9hZChfdm0uUmVnaXN0ZXIuczApOwogICAgfTsKCiAgICBfcHJvdG8xMi5pbnZva2VTdGF0aWNDb21wb25lbnQgPSBmdW5jdGlvbiBpbnZva2VTdGF0aWNDb21wb25lbnQoY2FwYWJpbGl0aWVzLCBsYXlvdXQsIGF0dHJzLCBwYXJhbXMsIGhhc2gsIHN5bnRoZXRpYywgYmxvY2ssIGludmVyc2UpIHsKICAgICAgaWYgKGludmVyc2UgPT09IHZvaWQgMCkgewogICAgICAgIGludmVyc2UgPSBudWxsOwogICAgICB9CgogICAgICB2YXIgc3ltYm9sVGFibGUgPSBsYXlvdXQuc3ltYm9sVGFibGU7CiAgICAgIHZhciBiYWlsT3V0ID0gc3ltYm9sVGFibGUuaGFzRXZhbCB8fCBjYXBhYmlsaXRpZXMucHJlcGFyZUFyZ3M7CgogICAgICBpZiAoYmFpbE91dCkgewogICAgICAgIHRoaXMuaW52b2tlQ29tcG9uZW50KGNhcGFiaWxpdGllcywgYXR0cnMsIHBhcmFtcywgaGFzaCwgc3ludGhldGljLCBibG9jaywgaW52ZXJzZSwgbGF5b3V0KTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuZmV0Y2goX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgdGhpcy5kdXAoX3ZtLlJlZ2lzdGVyLnNwLCAxKTsKICAgICAgdGhpcy5sb2FkKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHZhciBzeW1ib2xzID0gc3ltYm9sVGFibGUuc3ltYm9sczsKCiAgICAgIGlmIChjYXBhYmlsaXRpZXMuY3JlYXRlQXJncykgewogICAgICAgIHRoaXMucHVzaEZyYW1lKCk7CiAgICAgICAgdGhpcy5jb21waWxlQXJncyhwYXJhbXMsIGhhc2gsIG51bGwsIHN5bnRoZXRpYyk7CiAgICAgIH0KCiAgICAgIHRoaXMuYmVnaW5Db21wb25lbnRUcmFuc2FjdGlvbigpOwoKICAgICAgaWYgKGNhcGFiaWxpdGllcy5keW5hbWljU2NvcGUpIHsKICAgICAgICB0aGlzLnB1c2hEeW5hbWljU2NvcGUoKTsKICAgICAgfQoKICAgICAgaWYgKGNhcGFiaWxpdGllcy5jcmVhdGVJbnN0YW5jZSkgewogICAgICAgIHRoaXMuY3JlYXRlQ29tcG9uZW50KF92bS5SZWdpc3Rlci5zMCwgYmxvY2sgIT09IG51bGwpOwogICAgICB9CgogICAgICBpZiAoY2FwYWJpbGl0aWVzLmNyZWF0ZUFyZ3MpIHsKICAgICAgICB0aGlzLnBvcEZyYW1lKCk7CiAgICAgIH0KCiAgICAgIHRoaXMucHVzaEZyYW1lKCk7CiAgICAgIHRoaXMucmVnaXN0ZXJDb21wb25lbnREZXN0cnVjdG9yKF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIHZhciBiaW5kaW5ncyA9IFtdOwogICAgICB0aGlzLmdldENvbXBvbmVudFNlbGYoX3ZtLlJlZ2lzdGVyLnMwKTsKICAgICAgYmluZGluZ3MucHVzaCh7CiAgICAgICAgc3ltYm9sOiAwLAogICAgICAgIGlzQmxvY2s6IGZhbHNlCiAgICAgIH0pOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzeW1ib2xzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIHN5bWJvbCA9IHN5bWJvbHNbaV07CgogICAgICAgIHN3aXRjaCAoc3ltYm9sLmNoYXJBdCgwKSkgewogICAgICAgICAgY2FzZSAnJic6CiAgICAgICAgICAgIHZhciBjYWxsZXJCbG9jayA9IG51bGw7CgogICAgICAgICAgICBpZiAoc3ltYm9sID09PSAnJmRlZmF1bHQnKSB7CiAgICAgICAgICAgICAgY2FsbGVyQmxvY2sgPSBibG9jazsKICAgICAgICAgICAgfSBlbHNlIGlmIChzeW1ib2wgPT09ICcmaW52ZXJzZScpIHsKICAgICAgICAgICAgICBjYWxsZXJCbG9jayA9IGludmVyc2U7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoc3ltYm9sID09PSBBVFRSU19CTE9DSykgewogICAgICAgICAgICAgIGNhbGxlckJsb2NrID0gYXR0cnM7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdGhyb3cgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAoY2FsbGVyQmxvY2spIHsKICAgICAgICAgICAgICB0aGlzLnB1c2hZaWVsZGFibGVCbG9jayhjYWxsZXJCbG9jayk7CiAgICAgICAgICAgICAgYmluZGluZ3MucHVzaCh7CiAgICAgICAgICAgICAgICBzeW1ib2w6IGkgKyAxLAogICAgICAgICAgICAgICAgaXNCbG9jazogdHJ1ZQogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRoaXMucHVzaFlpZWxkYWJsZUJsb2NrKG51bGwpOwogICAgICAgICAgICAgIGJpbmRpbmdzLnB1c2goewogICAgICAgICAgICAgICAgc3ltYm9sOiBpICsgMSwKICAgICAgICAgICAgICAgIGlzQmxvY2s6IHRydWUKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgY2FzZSAnQCc6CiAgICAgICAgICAgIGlmICghaGFzaCkgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CgogICAgICAgICAgICB2YXIga2V5cyA9IGhhc2hbMF0sCiAgICAgICAgICAgICAgICB2YWx1ZXMgPSBoYXNoWzFdOwogICAgICAgICAgICB2YXIgbG9va3VwTmFtZSA9IHN5bWJvbDsKCiAgICAgICAgICAgIGlmIChzeW50aGV0aWMpIHsKICAgICAgICAgICAgICBsb29rdXBOYW1lID0gc3ltYm9sLnNsaWNlKDEpOwogICAgICAgICAgICB9CgogICAgICAgICAgICB2YXIgaW5kZXggPSBrZXlzLmluZGV4T2YobG9va3VwTmFtZSk7CgogICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7CiAgICAgICAgICAgICAgdGhpcy5leHByKHZhbHVlc1tpbmRleF0pOwogICAgICAgICAgICAgIGJpbmRpbmdzLnB1c2goewogICAgICAgICAgICAgICAgc3ltYm9sOiBpICsgMSwKICAgICAgICAgICAgICAgIGlzQmxvY2s6IGZhbHNlCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdGhpcy5wdXNoUm9vdFNjb3BlKHN5bWJvbHMubGVuZ3RoICsgMSwgISEoYmxvY2sgfHwgaW52ZXJzZSB8fCBhdHRycykpOwoKICAgICAgZm9yICh2YXIgX2kgPSBiaW5kaW5ncy5sZW5ndGggLSAxOyBfaSA+PSAwOyBfaS0tKSB7CiAgICAgICAgdmFyIF9iaW5kaW5ncyRfaSA9IGJpbmRpbmdzW19pXSwKICAgICAgICAgICAgX3N5bWJvbCA9IF9iaW5kaW5ncyRfaS5zeW1ib2wsCiAgICAgICAgICAgIGlzQmxvY2sgPSBfYmluZGluZ3MkX2kuaXNCbG9jazsKCiAgICAgICAgaWYgKGlzQmxvY2spIHsKICAgICAgICAgIHRoaXMuc2V0QmxvY2soX3N5bWJvbCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuc2V0VmFyaWFibGUoX3N5bWJvbCk7CiAgICAgICAgfQogICAgICB9CgogICAgICB0aGlzLmludm9rZVN0YXRpYyhsYXlvdXQpOwoKICAgICAgaWYgKGNhcGFiaWxpdGllcy5jcmVhdGVJbnN0YW5jZSkgewogICAgICAgIHRoaXMuZGlkUmVuZGVyTGF5b3V0KF92bS5SZWdpc3Rlci5zMCk7CiAgICAgIH0KCiAgICAgIHRoaXMucG9wRnJhbWUoKTsKICAgICAgdGhpcy5wb3BTY29wZSgpOwoKICAgICAgaWYgKGNhcGFiaWxpdGllcy5keW5hbWljU2NvcGUpIHsKICAgICAgICB0aGlzLnBvcER5bmFtaWNTY29wZSgpOwogICAgICB9CgogICAgICB0aGlzLmNvbW1pdENvbXBvbmVudFRyYW5zYWN0aW9uKCk7CiAgICAgIHRoaXMubG9hZChfdm0uUmVnaXN0ZXIuczApOwogICAgfTsKCiAgICBfcHJvdG8xMi5keW5hbWljQ29tcG9uZW50ID0gZnVuY3Rpb24gZHluYW1pY0NvbXBvbmVudChkZWZpbml0aW9uLCBhdHRycywgcGFyYW1zLCBoYXNoLCBzeW50aGV0aWMsIGJsb2NrLCBpbnZlcnNlKSB7CiAgICAgIHZhciBfdGhpczYgPSB0aGlzOwoKICAgICAgaWYgKGludmVyc2UgPT09IHZvaWQgMCkgewogICAgICAgIGludmVyc2UgPSBudWxsOwogICAgICB9CgogICAgICB0aGlzLnJlcGxheWFibGUoewogICAgICAgIGFyZ3M6IGZ1bmN0aW9uIGFyZ3MoKSB7CiAgICAgICAgICBfdGhpczYuZXhwcihkZWZpbml0aW9uKTsKCiAgICAgICAgICBfdGhpczYuZHVwKCk7CgogICAgICAgICAgcmV0dXJuIDI7CiAgICAgICAgfSwKICAgICAgICBib2R5OiBmdW5jdGlvbiBib2R5KCkgewogICAgICAgICAgX3RoaXM2Lmp1bXBVbmxlc3MoJ0VMU0UnKTsKCiAgICAgICAgICBfdGhpczYucmVzb2x2ZUR5bmFtaWNDb21wb25lbnQoX3RoaXM2LmNvbnRhaW5pbmdMYXlvdXQucmVmZXJyZXIpOwoKICAgICAgICAgIF90aGlzNi5wdXNoRHluYW1pY0NvbXBvbmVudEluc3RhbmNlKCk7CgogICAgICAgICAgX3RoaXM2Lmludm9rZUNvbXBvbmVudCh0cnVlLCBhdHRycywgcGFyYW1zLCBoYXNoLCBzeW50aGV0aWMsIGJsb2NrLCBpbnZlcnNlKTsKCiAgICAgICAgICBfdGhpczYubGFiZWwoJ0VMU0UnKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8xMi55aWVsZCA9IGZ1bmN0aW9uIF95aWVsZCh0bywgcGFyYW1zKSB7CiAgICAgIHRoaXMuY29tcGlsZUFyZ3MocGFyYW1zLCBudWxsLCBudWxsLCBmYWxzZSk7CiAgICAgIHRoaXMuZ2V0QmxvY2sodG8pOwogICAgICB0aGlzLnJlc29sdmVCbG9jaygpOwogICAgICB0aGlzLmludm9rZVlpZWxkKCk7CiAgICAgIHRoaXMucG9wU2NvcGUoKTsKICAgICAgdGhpcy5wb3BGcmFtZSgpOwogICAgfTsKCiAgICBfcHJvdG8xMi5ndWFyZGVkQXBwZW5kID0gZnVuY3Rpb24gZ3VhcmRlZEFwcGVuZChleHByZXNzaW9uLCB0cnVzdGluZykgewogICAgICB0aGlzLnB1c2hGcmFtZSgpOwogICAgICB0aGlzLmV4cHIoZXhwcmVzc2lvbik7CiAgICAgIHRoaXMucHVzaE1hY2hpbmUoNTAKICAgICAgLyogSW52b2tlU3RhdGljICovCiAgICAgICwgdGhpcy5zdGRMaWIuZ2V0QXBwZW5kKHRydXN0aW5nKSk7CiAgICAgIHRoaXMucG9wRnJhbWUoKTsKICAgIH07CgogICAgX3Byb3RvMTIuaW52b2tlU3RhdGljQmxvY2sgPSBmdW5jdGlvbiBpbnZva2VTdGF0aWNCbG9jayhibG9jaywgY2FsbGVyQ291bnQpIHsKICAgICAgaWYgKGNhbGxlckNvdW50ID09PSB2b2lkIDApIHsKICAgICAgICBjYWxsZXJDb3VudCA9IDA7CiAgICAgIH0KCiAgICAgIHZhciBwYXJhbWV0ZXJzID0gYmxvY2suc3ltYm9sVGFibGUucGFyYW1ldGVyczsKICAgICAgdmFyIGNhbGxlZUNvdW50ID0gcGFyYW1ldGVycy5sZW5ndGg7CiAgICAgIHZhciBjb3VudCA9IE1hdGgubWluKGNhbGxlckNvdW50LCBjYWxsZWVDb3VudCk7CiAgICAgIHRoaXMucHVzaEZyYW1lKCk7CgogICAgICBpZiAoY291bnQpIHsKICAgICAgICB0aGlzLnB1c2hDaGlsZFNjb3BlKCk7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewogICAgICAgICAgdGhpcy5kdXAoX3ZtLlJlZ2lzdGVyLmZwLCBjYWxsZXJDb3VudCAtIGkpOwogICAgICAgICAgdGhpcy5zZXRWYXJpYWJsZShwYXJhbWV0ZXJzW2ldKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHRoaXMucHVzaEJsb2NrKGJsb2NrKTsKICAgICAgdGhpcy5yZXNvbHZlQmxvY2soKTsKICAgICAgdGhpcy5pbnZva2VWaXJ0dWFsKCk7CgogICAgICBpZiAoY291bnQpIHsKICAgICAgICB0aGlzLnBvcFNjb3BlKCk7CiAgICAgIH0KCiAgICAgIHRoaXMucG9wRnJhbWUoKTsKICAgIH0gLy8vIENPTlZFTklFTkNFCiAgICAvLyBpbnRlcm5hbCBoZWxwZXJzCiAgICA7CgogICAgX3Byb3RvMTIuc3RyaW5nID0gZnVuY3Rpb24gc3RyaW5nKF9zdHJpbmcpIHsKICAgICAgcmV0dXJuIHRoaXMuY29uc3RhbnRzLnN0cmluZyhfc3RyaW5nKTsKICAgIH07CgogICAgX3Byb3RvMTIubmFtZXMgPSBmdW5jdGlvbiBuYW1lcyhfbmFtZXMpIHsKICAgICAgdmFyIG5hbWVzID0gW107CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IF9uYW1lcy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBuID0gX25hbWVzW2ldOwogICAgICAgIG5hbWVzW2ldID0gdGhpcy5jb25zdGFudHMuc3RyaW5nKG4pOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5jb25zdGFudHMuYXJyYXkobmFtZXMpOwogICAgfTsKCiAgICBfcHJvdG8xMi5zeW1ib2xzID0gZnVuY3Rpb24gc3ltYm9scyhfc3ltYm9sczIpIHsKICAgICAgcmV0dXJuIHRoaXMuY29uc3RhbnRzLmFycmF5KF9zeW1ib2xzMik7CiAgICB9IC8vIHZtCiAgICA7CgogICAgX3Byb3RvMTIucHJpbWl0aXZlID0gZnVuY3Rpb24gcHJpbWl0aXZlKF9wcmltaXRpdmUpIHsKICAgICAgdmFyIHR5cGUgPSAwCiAgICAgIC8qIE5VTUJFUiAqLwogICAgICA7CiAgICAgIHZhciBwcmltaXRpdmU7CgogICAgICBzd2l0Y2ggKHR5cGVvZiBfcHJpbWl0aXZlKSB7CiAgICAgICAgY2FzZSAnbnVtYmVyJzoKICAgICAgICAgIGlmIChfcHJpbWl0aXZlICUgMSA9PT0gMCkgewogICAgICAgICAgICBpZiAoX3ByaW1pdGl2ZSA+IC0xKSB7CiAgICAgICAgICAgICAgcHJpbWl0aXZlID0gX3ByaW1pdGl2ZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBwcmltaXRpdmUgPSB0aGlzLmNvbnN0YW50cy5udW1iZXIoX3ByaW1pdGl2ZSk7CiAgICAgICAgICAgICAgdHlwZSA9IDQKICAgICAgICAgICAgICAvKiBORUdBVElWRSAqLwogICAgICAgICAgICAgIDsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcHJpbWl0aXZlID0gdGhpcy5jb25zdGFudHMubnVtYmVyKF9wcmltaXRpdmUpOwogICAgICAgICAgICB0eXBlID0gMQogICAgICAgICAgICAvKiBGTE9BVCAqLwogICAgICAgICAgICA7CiAgICAgICAgICB9CgogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ3N0cmluZyc6CiAgICAgICAgICBwcmltaXRpdmUgPSB0aGlzLnN0cmluZyhfcHJpbWl0aXZlKTsKICAgICAgICAgIHR5cGUgPSAyCiAgICAgICAgICAvKiBTVFJJTkcgKi8KICAgICAgICAgIDsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICdib29sZWFuJzoKICAgICAgICAgIHByaW1pdGl2ZSA9IF9wcmltaXRpdmUgfCAwOwogICAgICAgICAgdHlwZSA9IDMKICAgICAgICAgIC8qIEJPT0xFQU5fT1JfVk9JRCAqLwogICAgICAgICAgOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgJ29iamVjdCc6CiAgICAgICAgICAvLyBhc3N1bWUgbnVsbAogICAgICAgICAgcHJpbWl0aXZlID0gMjsKICAgICAgICAgIHR5cGUgPSAzCiAgICAgICAgICAvKiBCT09MRUFOX09SX1ZPSUQgKi8KICAgICAgICAgIDsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICd1bmRlZmluZWQnOgogICAgICAgICAgcHJpbWl0aXZlID0gMzsKICAgICAgICAgIHR5cGUgPSAzCiAgICAgICAgICAvKiBCT09MRUFOX09SX1ZPSUQgKi8KICAgICAgICAgIDsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHByaW1pdGl2ZSBwYXNzZWQgdG8gcHVzaFByaW1pdGl2ZScpOwogICAgICB9CgogICAgICB2YXIgaW1tZWRpYXRlID0gdGhpcy5zaXplSW1tZWRpYXRlKHByaW1pdGl2ZSA8PCAzIHwgdHlwZSwgcHJpbWl0aXZlKTsKICAgICAgdGhpcy5wdXNoKDEzCiAgICAgIC8qIFByaW1pdGl2ZSAqLwogICAgICAsIGltbWVkaWF0ZSk7CiAgICB9OwoKICAgIF9wcm90bzEyLnNpemVJbW1lZGlhdGUgPSBmdW5jdGlvbiBzaXplSW1tZWRpYXRlKHNoaWZ0ZWQsIHByaW1pdGl2ZSkgewogICAgICBpZiAoc2hpZnRlZCA+PSA0Mjk0OTY3Mjk1CiAgICAgIC8qIE1BWF9TSVpFICovCiAgICAgIHx8IHNoaWZ0ZWQgPCAwKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RhbnRzLm51bWJlcihwcmltaXRpdmUpIDw8IDMgfCA1CiAgICAgICAgLyogQklHX05VTSAqLwogICAgICAgIDsKICAgICAgfQoKICAgICAgcmV0dXJuIHNoaWZ0ZWQ7CiAgICB9OwoKICAgIF9wcm90bzEyLnB1c2hQcmltaXRpdmVSZWZlcmVuY2UgPSBmdW5jdGlvbiBwdXNoUHJpbWl0aXZlUmVmZXJlbmNlKHByaW1pdGl2ZSkgewogICAgICB0aGlzLnByaW1pdGl2ZShwcmltaXRpdmUpOwogICAgICB0aGlzLnByaW1pdGl2ZVJlZmVyZW5jZSgpOwogICAgfSAvLyBjb21wb25lbnRzCiAgICA7CgogICAgX3Byb3RvMTIucHVzaENvbXBvbmVudERlZmluaXRpb24gPSBmdW5jdGlvbiBwdXNoQ29tcG9uZW50RGVmaW5pdGlvbihoYW5kbGUpIHsKICAgICAgdGhpcy5wdXNoKDcyCiAgICAgIC8qIFB1c2hDb21wb25lbnREZWZpbml0aW9uICovCiAgICAgICwgdGhpcy5jb25zdGFudHMuaGFuZGxlKGhhbmRsZSkpOwogICAgfTsKCiAgICBfcHJvdG8xMi5yZXNvbHZlRHluYW1pY0NvbXBvbmVudCA9IGZ1bmN0aW9uIHJlc29sdmVEeW5hbWljQ29tcG9uZW50KHJlZmVycmVyKSB7CiAgICAgIHRoaXMucHVzaCg3NQogICAgICAvKiBSZXNvbHZlRHluYW1pY0NvbXBvbmVudCAqLwogICAgICAsIHRoaXMuY29uc3RhbnRzLnNlcmlhbGl6YWJsZShyZWZlcnJlcikpOwogICAgfTsKCiAgICBfcHJvdG8xMi5zdGF0aWNDb21wb25lbnRIZWxwZXIgPSBmdW5jdGlvbiBzdGF0aWNDb21wb25lbnRIZWxwZXIodGFnLCBoYXNoLCB0ZW1wbGF0ZSkgewogICAgICB2YXIgX3RoaXMkY29tcGlsZXIkcmVzb2x2ID0gdGhpcy5jb21waWxlci5yZXNvbHZlTGF5b3V0Rm9yVGFnKHRhZywgdGhpcy5yZWZlcnJlciksCiAgICAgICAgICBoYW5kbGUgPSBfdGhpcyRjb21waWxlciRyZXNvbHYuaGFuZGxlLAogICAgICAgICAgY2FwYWJpbGl0aWVzID0gX3RoaXMkY29tcGlsZXIkcmVzb2x2LmNhcGFiaWxpdGllcywKICAgICAgICAgIGNvbXBpbGFibGUgPSBfdGhpcyRjb21waWxlciRyZXNvbHYuY29tcGlsYWJsZTsKCiAgICAgIGlmIChoYW5kbGUgIT09IG51bGwgJiYgY2FwYWJpbGl0aWVzICE9PSBudWxsKSB7CiAgICAgICAgaWYgKGNvbXBpbGFibGUpIHsKICAgICAgICAgIGlmIChoYXNoKSB7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGFzaC5sZW5ndGg7IGkgPSBpICsgMikgewogICAgICAgICAgICAgIGhhc2hbaV1bMF0gPSAiQCIgKyBoYXNoW2ldWzBdOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5wdXNoQ29tcG9uZW50RGVmaW5pdGlvbihoYW5kbGUpOwogICAgICAgICAgdGhpcy5pbnZva2VTdGF0aWNDb21wb25lbnQoY2FwYWJpbGl0aWVzLCBjb21waWxhYmxlLCBudWxsLCBudWxsLCBoYXNoLCBmYWxzZSwgdGVtcGxhdGUgJiYgdGVtcGxhdGUpOwogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gZmFsc2U7CiAgICB9IC8vIHBhcnRpYWwKICAgIDsKCiAgICBfcHJvdG8xMi5pbnZva2VQYXJ0aWFsID0gZnVuY3Rpb24gaW52b2tlUGFydGlhbChyZWZlcnJlciwgc3ltYm9scywgZXZhbEluZm8pIHsKICAgICAgdmFyIF9tZXRhID0gdGhpcy5jb25zdGFudHMuc2VyaWFsaXphYmxlKHJlZmVycmVyKTsKCiAgICAgIHZhciBfc3ltYm9scyA9IHRoaXMuY29uc3RhbnRzLnN0cmluZ0FycmF5KHN5bWJvbHMpOwoKICAgICAgdmFyIF9ldmFsSW5mbyA9IHRoaXMuY29uc3RhbnRzLmFycmF5KGV2YWxJbmZvKTsKCiAgICAgIHRoaXMucHVzaCg5NQogICAgICAvKiBJbnZva2VQYXJ0aWFsICovCiAgICAgICwgX21ldGEsIF9zeW1ib2xzLCBfZXZhbEluZm8pOwogICAgfTsKCiAgICBfcHJvdG8xMi5yZXNvbHZlTWF5YmVMb2NhbCA9IGZ1bmN0aW9uIHJlc29sdmVNYXliZUxvY2FsKG5hbWUpIHsKICAgICAgdGhpcy5wdXNoKDk2CiAgICAgIC8qIFJlc29sdmVNYXliZUxvY2FsICovCiAgICAgICwgdGhpcy5zdHJpbmcobmFtZSkpOwogICAgfSAvLyBkZWJ1Z2dlcgogICAgOwoKICAgIF9wcm90bzEyLmRlYnVnZ2VyID0gZnVuY3Rpb24gX2RlYnVnZ2VyKHN5bWJvbHMsIGV2YWxJbmZvKSB7CiAgICAgIHRoaXMucHVzaCg5NwogICAgICAvKiBEZWJ1Z2dlciAqLwogICAgICAsIHRoaXMuY29uc3RhbnRzLnN0cmluZ0FycmF5KHN5bWJvbHMpLCB0aGlzLmNvbnN0YW50cy5hcnJheShldmFsSW5mbykpOwogICAgfSAvLyBkb20KICAgIDsKCiAgICBfcHJvdG8xMi50ZXh0ID0gZnVuY3Rpb24gdGV4dChfdGV4dCkgewogICAgICB0aGlzLnB1c2goMjYKICAgICAgLyogVGV4dCAqLwogICAgICAsIHRoaXMuY29uc3RhbnRzLnN0cmluZyhfdGV4dCkpOwogICAgfTsKCiAgICBfcHJvdG8xMi5vcGVuUHJpbWl0aXZlRWxlbWVudCA9IGZ1bmN0aW9uIG9wZW5QcmltaXRpdmVFbGVtZW50KHRhZykgewogICAgICB0aGlzLnB1c2goMzMKICAgICAgLyogT3BlbkVsZW1lbnQgKi8KICAgICAgLCB0aGlzLmNvbnN0YW50cy5zdHJpbmcodGFnKSk7CiAgICB9OwoKICAgIF9wcm90bzEyLm1vZGlmaWVyID0gZnVuY3Rpb24gbW9kaWZpZXIobG9jYXRvciwgcGFyYW1zLCBoYXNoKSB7CiAgICAgIHRoaXMucHVzaEZyYW1lKCk7CiAgICAgIHRoaXMuY29tcGlsZUFyZ3MocGFyYW1zLCBoYXNoLCBudWxsLCB0cnVlKTsKICAgICAgdGhpcy5wdXNoKDQwCiAgICAgIC8qIE1vZGlmaWVyICovCiAgICAgICwgdGhpcy5jb25zdGFudHMuaGFuZGxlKGxvY2F0b3IpKTsKICAgICAgdGhpcy5wb3BGcmFtZSgpOwogICAgfTsKCiAgICBfcHJvdG8xMi5jb21tZW50ID0gZnVuY3Rpb24gY29tbWVudChfY29tbWVudCkgewogICAgICB2YXIgY29tbWVudCA9IHRoaXMuY29uc3RhbnRzLnN0cmluZyhfY29tbWVudCk7CiAgICAgIHRoaXMucHVzaCgyNwogICAgICAvKiBDb21tZW50ICovCiAgICAgICwgY29tbWVudCk7CiAgICB9OwoKICAgIF9wcm90bzEyLmR5bmFtaWNBdHRyID0gZnVuY3Rpb24gZHluYW1pY0F0dHIoX25hbWUsIF9uYW1lc3BhY2UsIHRydXN0aW5nKSB7CiAgICAgIHZhciBuYW1lID0gdGhpcy5jb25zdGFudHMuc3RyaW5nKF9uYW1lKTsKICAgICAgdmFyIG5hbWVzcGFjZSA9IF9uYW1lc3BhY2UgPyB0aGlzLmNvbnN0YW50cy5zdHJpbmcoX25hbWVzcGFjZSkgOiAwOwogICAgICB0aGlzLnB1c2goMzYKICAgICAgLyogRHluYW1pY0F0dHIgKi8KICAgICAgLCBuYW1lLCB0cnVzdGluZyA9PT0gdHJ1ZSA/IDEgOiAwLCBuYW1lc3BhY2UpOwogICAgfTsKCiAgICBfcHJvdG8xMi5jb21wb25lbnRBdHRyID0gZnVuY3Rpb24gY29tcG9uZW50QXR0cihfbmFtZSwgX25hbWVzcGFjZSwgdHJ1c3RpbmcpIHsKICAgICAgdmFyIG5hbWUgPSB0aGlzLmNvbnN0YW50cy5zdHJpbmcoX25hbWUpOwogICAgICB2YXIgbmFtZXNwYWNlID0gX25hbWVzcGFjZSA/IHRoaXMuY29uc3RhbnRzLnN0cmluZyhfbmFtZXNwYWNlKSA6IDA7CiAgICAgIHRoaXMucHVzaCgzNwogICAgICAvKiBDb21wb25lbnRBdHRyICovCiAgICAgICwgbmFtZSwgdHJ1c3RpbmcgPT09IHRydWUgPyAxIDogMCwgbmFtZXNwYWNlKTsKICAgIH07CgogICAgX3Byb3RvMTIuc3RhdGljQXR0ciA9IGZ1bmN0aW9uIHN0YXRpY0F0dHIoX25hbWUsIF9uYW1lc3BhY2UsIF92YWx1ZSkgewogICAgICB2YXIgbmFtZSA9IHRoaXMuY29uc3RhbnRzLnN0cmluZyhfbmFtZSk7CiAgICAgIHZhciBuYW1lc3BhY2UgPSBfbmFtZXNwYWNlID8gdGhpcy5jb25zdGFudHMuc3RyaW5nKF9uYW1lc3BhY2UpIDogMDsKICAgICAgdmFyIHZhbHVlID0gdGhpcy5jb25zdGFudHMuc3RyaW5nKF92YWx1ZSk7CiAgICAgIHRoaXMucHVzaCgzNQogICAgICAvKiBTdGF0aWNBdHRyICovCiAgICAgICwgbmFtZSwgdmFsdWUsIG5hbWVzcGFjZSk7CiAgICB9IC8vIGV4cHJlc3Npb25zCiAgICA7CgogICAgX3Byb3RvMTIuaGFzQmxvY2tQYXJhbXMgPSBmdW5jdGlvbiBoYXNCbG9ja1BhcmFtcyh0bykgewogICAgICB0aGlzLmdldEJsb2NrKHRvKTsKICAgICAgdGhpcy5yZXNvbHZlQmxvY2soKTsKICAgICAgdGhpcy5wdXNoKDEwCiAgICAgIC8qIEhhc0Jsb2NrUGFyYW1zICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzEyLmdldFByb3BlcnR5ID0gZnVuY3Rpb24gZ2V0UHJvcGVydHkoa2V5KSB7CiAgICAgIHRoaXMucHVzaCg3CiAgICAgIC8qIEdldFByb3BlcnR5ICovCiAgICAgICwgdGhpcy5zdHJpbmcoa2V5KSk7CiAgICB9OwoKICAgIF9wcm90bzEyLmhlbHBlciA9IGZ1bmN0aW9uIGhlbHBlcihfaGVscGVyLCBwYXJhbXMsIGhhc2gpIHsKICAgICAgdGhpcy5wdXNoRnJhbWUoKTsKICAgICAgdGhpcy5jb21waWxlQXJncyhwYXJhbXMsIGhhc2gsIG51bGwsIHRydWUpOwogICAgICB0aGlzLnB1c2goMQogICAgICAvKiBIZWxwZXIgKi8KICAgICAgLCB0aGlzLmNvbnN0YW50cy5oYW5kbGUoX2hlbHBlcikpOwogICAgICB0aGlzLnBvcEZyYW1lKCk7CiAgICAgIHRoaXMuZmV0Y2goX3ZtLlJlZ2lzdGVyLnYwKTsKICAgIH07CgogICAgX3Byb3RvMTIuYmluZER5bmFtaWNTY29wZSA9IGZ1bmN0aW9uIGJpbmREeW5hbWljU2NvcGUoX25hbWVzKSB7CiAgICAgIHRoaXMucHVzaCg0MwogICAgICAvKiBCaW5kRHluYW1pY1Njb3BlICovCiAgICAgICwgdGhpcy5uYW1lcyhfbmFtZXMpKTsKICAgIH0gLy8gY29udmVuaWVuY2UgbWV0aG9kcwoKICAgIC8qKgogICAgICogQSBjb252ZW5pZW5jZSBmb3IgcHVzaGluZyBzb21lIGFyZ3VtZW50cyBvbiB0aGUgc3RhY2sgYW5kCiAgICAgKiBydW5uaW5nIHNvbWUgY29kZSBpZiB0aGUgY29kZSBuZWVkcyB0byBiZSByZS1leGVjdXRlZCBkdXJpbmcKICAgICAqIHVwZGF0aW5nIGV4ZWN1dGlvbiBpZiBzb21lIG9mIHRoZSBhcmd1bWVudHMgaGF2ZSBjaGFuZ2VkLgogICAgICoKICAgICAqICMgSW5pdGlhbCBFeGVjdXRpb24KICAgICAqCiAgICAgKiBUaGUgYGFyZ3NgIGZ1bmN0aW9uIHNob3VsZCBwdXNoIHplcm8gb3IgbW9yZSBhcmd1bWVudHMgb250bwogICAgICogdGhlIHN0YWNrIGFuZCByZXR1cm4gdGhlIG51bWJlciBvZiBhcmd1bWVudHMgcHVzaGVkLgogICAgICoKICAgICAqIFRoZSBgYm9keWAgZnVuY3Rpb24gcHJvdmlkZXMgdGhlIGluc3RydWN0aW9ucyB0byBleGVjdXRlIGJvdGgKICAgICAqIGR1cmluZyBpbml0aWFsIGV4ZWN1dGlvbiBhbmQgZHVyaW5nIHVwZGF0aW5nIGV4ZWN1dGlvbi4KICAgICAqCiAgICAgKiBJbnRlcm5hbGx5LCB0aGlzIGZ1bmN0aW9uIHN0YXJ0cyBieSBwdXNoaW5nIGEgbmV3IGZyYW1lLCBzbwogICAgICogdGhhdCB0aGUgYm9keSBjYW4gcmV0dXJuIGFuZCBzZXRzIHRoZSByZXR1cm4gcG9pbnQgKCRyYSkgdG8KICAgICAqIHRoZSBFTkRJTklUSUFMIGxhYmVsLgogICAgICoKICAgICAqIEl0IHRoZW4gZXhlY3V0ZXMgdGhlIGBhcmdzYCBmdW5jdGlvbiwgd2hpY2ggYWRkcyBpbnN0cnVjdGlvbnMKICAgICAqIHJlc3BvbnNpYmxlIGZvciBwdXNoaW5nIHRoZSBhcmd1bWVudHMgZm9yIHRoZSBibG9jayB0byB0aGUKICAgICAqIHN0YWNrLiBUaGVzZSBhcmd1bWVudHMgd2lsbCBiZSByZXN0b3JlZCB0byB0aGUgc3RhY2sgYmVmb3JlCiAgICAgKiB1cGRhdGluZyBleGVjdXRpb24uCiAgICAgKgogICAgICogTmV4dCwgaXQgYWRkcyB0aGUgRW50ZXIgb3Bjb2RlLCB3aGljaCBtYXJrcyB0aGUgY3VycmVudCBwb3NpdGlvbgogICAgICogaW4gdGhlIERPTSwgYW5kIHJlbWVtYmVycyB0aGUgY3VycmVudCAkcGMgKHRoZSBuZXh0IGluc3RydWN0aW9uKQogICAgICogYXMgdGhlIGZpcnN0IGluc3RydWN0aW9uIHRvIGV4ZWN1dGUgZHVyaW5nIHVwZGF0aW5nIGV4ZWN1dGlvbi4KICAgICAqCiAgICAgKiBOZXh0LCBpdCBydW5zIGBib2R5YCwgd2hpY2ggYWRkcyB0aGUgb3Bjb2RlcyB0aGF0IHNob3VsZAogICAgICogZXhlY3V0ZSBib3RoIGR1cmluZyBpbml0aWFsIGV4ZWN1dGlvbiBhbmQgZHVyaW5nIHVwZGF0aW5nIGV4ZWN1dGlvbi4KICAgICAqIElmIHRoZSBgYm9keWAgd2lzaGVzIHRvIGZpbmlzaCBlYXJseSwgaXQgc2hvdWxkIEp1bXAgdG8gdGhlCiAgICAgKiBgRklOQUxMWWAgbGFiZWwuCiAgICAgKgogICAgICogTmV4dCwgaXQgYWRkcyB0aGUgRklOQUxMWSBsYWJlbCwgZm9sbG93ZWQgYnk6CiAgICAgKgogICAgICogLSB0aGUgRXhpdCBvcGNvZGUsIHdoaWNoIGZpbmFsaXplcyB0aGUgbWFya2VkIERPTSBzdGFydGVkIGJ5IHRoZQogICAgICogICBFbnRlciBvcGNvZGUuCiAgICAgKiAtIHRoZSBSZXR1cm4gb3Bjb2RlLCB3aGljaCByZXR1cm5zIHRvIHRoZSBjdXJyZW50IHJldHVybiBwb2ludAogICAgICogICAoJHJhKS4KICAgICAqCiAgICAgKiBGaW5hbGx5LCBpdCBhZGRzIHRoZSBFTkRJTklUSUFMIGxhYmVsIGZvbGxvd2VkIGJ5IHRoZSBQb3BGcmFtZQogICAgICogaW5zdHJ1Y3Rpb24sIHdoaWNoIHJlc3RvcmVzICRmcCwgJHNwIGFuZCAkcmEuCiAgICAgKgogICAgICogIyBVcGRhdGluZyBFeGVjdXRpb24KICAgICAqCiAgICAgKiBVcGRhdGluZyBleGVjdXRpb24gZm9yIHRoaXMgYHJlcGxheWFibGVgIG9jY3VycyBpZiB0aGUgYGJvZHlgIGFkZGVkIGFuCiAgICAgKiBhc3NlcnRpb24sIHZpYSBvbmUgb2YgdGhlIGBKdW1wSWZgLCBgSnVtcFVubGVzc2Agb3IgYEFzc2VydFNhbWVgIG9wY29kZXMuCiAgICAgKgogICAgICogSWYsIGR1cmluZyB1cGRhdGluZyBleGVjdXRvbiwgdGhlIGFzc2VydGlvbiBmYWlscywgdGhlIGluaXRpYWwgVk0gaXMKICAgICAqIHJlc3RvcmVkLCBhbmQgdGhlIHN0b3JlZCBhcmd1bWVudHMgYXJlIHB1c2hlZCBvbnRvIHRoZSBzdGFjay4gVGhlIERPTQogICAgICogYmV0d2VlbiB0aGUgc3RhcnRpbmcgYW5kIGVuZGluZyBtYXJrZXJzIGlzIGNsZWFyZWQsIGFuZCB0aGUgVk0ncyBjdXJzb3IKICAgICAqIGlzIHNldCB0byB0aGUgYXJlYSBqdXN0IGNsZWFyZWQuCiAgICAgKgogICAgICogVGhlIHJldHVybiBwb2ludCAoJHJhKSBpcyBzZXQgdG8gLTEsIHRoZSBleGl0IGluc3RydWN0aW9uLgogICAgICoKICAgICAqIEZpbmFsbHksIHRoZSAkcGMgaXMgc2V0IHRvIHRvIHRoZSBpbnN0cnVjdGlvbiBzYXZlZCBvZmYgYnkgdGhlCiAgICAgKiBFbnRlciBvcGNvZGUgZHVyaW5nIGluaXRpYWwgZXhlY3V0aW9uLCBhbmQgZXhlY3V0aW9uIHByb2NlZWRzIGFzCiAgICAgKiB1c3VhbC4KICAgICAqCiAgICAgKiBUaGUgb25seSBkaWZmZXJlbmNlIGlzIHRoYXQgd2hlbiBhIGBSZXR1cm5gIGluc3RydWN0aW9uIGlzCiAgICAgKiBlbmNvdW50ZXJlZCwgdGhlIHByb2dyYW0ganVtcHMgdG8gLTEgcmF0aGVyIHRoYW4gdGhlIEVORCBsYWJlbCwKICAgICAqIGFuZCB0aGUgUG9wRnJhbWUgb3Bjb2RlIGlzIG5vdCBuZWVkZWQuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8xMi5yZXBsYXlhYmxlID0gZnVuY3Rpb24gcmVwbGF5YWJsZShfcmVmKSB7CiAgICAgIHZhciBhcmdzID0gX3JlZi5hcmdzLAogICAgICAgICAgYm9keSA9IF9yZWYuYm9keTsKICAgICAgLy8gU3RhcnQgYSBuZXcgbGFiZWwgZnJhbWUsIHRvIGdpdmUgRU5EIGFuZCBSRVRVUk4KICAgICAgLy8gYSB1bmlxdWUgbWVhbmluZy4KICAgICAgdGhpcy5zdGFydExhYmVscygpOwogICAgICB0aGlzLnB1c2hGcmFtZSgpOyAvLyBJZiB0aGUgYm9keSBpbnZva2VzIGEgYmxvY2ssIGl0cyByZXR1cm4gd2lsbCByZXR1cm4gdG8KICAgICAgLy8gRU5ELiBPdGhlcndpc2UsIHRoZSByZXR1cm4gaW4gUkVUVVJOIHdpbGwgcmV0dXJuIHRvIEVORC4KCiAgICAgIHRoaXMucmV0dXJuVG8oJ0VORElOSVRJQUwnKTsgLy8gUHVzaCB0aGUgYXJndW1lbnRzIG9udG8gdGhlIHN0YWNrLiBUaGUgYXJncygpIGZ1bmN0aW9uCiAgICAgIC8vIHRlbGxzIHVzIGhvdyBtYW55IHN0YWNrIGVsZW1lbnRzIHRvIHJldGFpbiBmb3IgcmUtZXhlY3V0aW9uCiAgICAgIC8vIHdoZW4gdXBkYXRpbmcuCgogICAgICB2YXIgY291bnQgPSBhcmdzKCk7IC8vIFN0YXJ0IGEgbmV3IHVwZGF0aW5nIGNsb3N1cmUsIHJlbWVtYmVyaW5nIGBjb3VudGAgZWxlbWVudHMKICAgICAgLy8gZnJvbSB0aGUgc3RhY2suIEV2ZXJ5dGhpbmcgYWZ0ZXIgdGhpcyBwb2ludCwgYW5kIGJlZm9yZSBFTkQsCiAgICAgIC8vIHdpbGwgZXhlY3V0ZSBib3RoIGluaXRpYWxseSBhbmQgdG8gdXBkYXRlIHRoZSBibG9jay4KICAgICAgLy8KICAgICAgLy8gVGhlIGVudGVyIGFuZCBleGl0IG9wY29kZXMgYWxzbyB0cmFjayB0aGUgYXJlYSBvZiB0aGUgRE9NCiAgICAgIC8vIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGJsb2NrLiBJZiBhbiBhc3NlcnRpb24gaW5zaWRlIHRoZSBibG9jawogICAgICAvLyBmYWlscyAoZm9yIGV4YW1wbGUsIHRoZSB0ZXN0IHZhbHVlIGNoYW5nZXMgZnJvbSB0cnVlIHRvIGZhbHNlCiAgICAgIC8vIGluIGFuICNpZiksIHRoZSBET00gaXMgY2xlYXJlZCBhbmQgdGhlIHByb2dyYW0gaXMgcmUtZXhlY3V0ZWQsCiAgICAgIC8vIHJlc3RvcmluZyBgY291bnRgIGVsZW1lbnRzIHRvIHRoZSBzdGFjayBhbmQgZXhlY3V0aW5nIHRoZQogICAgICAvLyBpbnN0cnVjdGlvbnMgYmV0d2VlbiB0aGUgZW50ZXIgYW5kIGV4aXQuCgogICAgICB0aGlzLmVudGVyKGNvdW50KTsgLy8gRXZhbHVhdGUgdGhlIGJvZHkgb2YgdGhlIGJsb2NrLiBUaGUgYm9keSBvZiB0aGUgYmxvY2sgbWF5CiAgICAgIC8vIHJldHVybiwgd2hpY2ggd2lsbCBqdW1wIGV4ZWN1dGlvbiB0byBFTkQgZHVyaW5nIGluaXRpYWwKICAgICAgLy8gZXhlY3V0aW9uLCBhbmQgZXhpdCB0aGUgdXBkYXRpbmcgcm91dGluZS4KCiAgICAgIGJvZHkoKTsgLy8gQWxsIGV4ZWN1dGlvbiBwYXRocyBpbiB0aGUgYm9keSBzaG91bGQgcnVuIHRoZSBGSU5BTExZIG9uY2UKICAgICAgLy8gdGhleSBhcmUgZG9uZS4gSXQgaXMgZXhlY3V0ZWQgYm90aCBkdXJpbmcgaW5pdGlhbCBleGVjdXRpb24KICAgICAgLy8gYW5kIGR1cmluZyB1cGRhdGluZyBleGVjdXRpb24uCgogICAgICB0aGlzLmxhYmVsKCdGSU5BTExZJyk7IC8vIEZpbmFsaXplIHRoZSBET00uCgogICAgICB0aGlzLmV4aXQoKTsgLy8gSW4gaW5pdGlhbCBleGVjdXRpb24sIHRoaXMgaXMgYSBub29wOiBpdCByZXR1cm5zIHRvIHRoZQogICAgICAvLyBpbW1lZGlhdGVseSBmb2xsb3dpbmcgb3Bjb2RlLiBJbiB1cGRhdGluZyBleGVjdXRpb24sIHRoaXMKICAgICAgLy8gZXhpdHMgdGhlIHVwZGF0aW5nIHJvdXRpbmUuCgogICAgICB0aGlzLnJldHVybigpOyAvLyBDbGVhbnVwIGNvZGUgZm9yIHRoZSBibG9jay4gUnVucyBvbiBpbml0aWFsIGV4ZWN1dGlvbgogICAgICAvLyBidXQgbm90IG9uIHVwZGF0aW5nLgoKICAgICAgdGhpcy5sYWJlbCgnRU5ESU5JVElBTCcpOwogICAgICB0aGlzLnBvcEZyYW1lKCk7CiAgICAgIHRoaXMuc3RvcExhYmVscygpOwogICAgfQogICAgLyoqCiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgdGhlIGByZXBsYXlhYmxlYCBjb252ZW5pZW5jZSB0aGF0IGFsbG93cyB0aGUKICAgICAqIGNhbGxlciB0byBwcm92aWRlIGRpZmZlcmVudCBjb2RlIGJhc2VkIHVwb24gd2hldGhlciB0aGUgaXRlbSBhdAogICAgICogdGhlIHRvcCBvZiB0aGUgc3RhY2sgaXMgdHJ1ZSBvciBmYWxzZS4KICAgICAqCiAgICAgKiBBcyBpbiBgcmVwbGF5YWJsZWAsIHRoZSBgaWZUcnVlYCBhbmQgYGlmRmFsc2VgIGNvZGUgY2FuIGludm9rZSBgcmV0dXJuYC4KICAgICAqCiAgICAgKiBEdXJpbmcgdGhlIGluaXRpYWwgZXhlY3V0aW9uLCBhIGByZXR1cm5gIHdpbGwgY29udGludWUgZXhlY3V0aW9uCiAgICAgKiBpbiB0aGUgY2xlYW51cCBjb2RlLCB3aGljaCBmaW5hbGl6ZXMgdGhlIGN1cnJlbnQgRE9NIGJsb2NrIGFuZCBwb3BzCiAgICAgKiB0aGUgY3VycmVudCBmcmFtZS4KICAgICAqCiAgICAgKiBEdXJpbmcgdGhlIHVwZGF0aW5nIGV4ZWN1dGlvbiwgYSBgcmV0dXJuYCB3aWxsIGV4aXQgdGhlIHVwZGF0aW5nCiAgICAgKiByb3V0aW5lLCBhcyBpdCBjYW4gcmV1c2UgdGhlIERPTSBibG9jayBhbmQgaXMgYWx3YXlzIG9ubHkgYSBzaW5nbGUKICAgICAqIGZyYW1lIGRlZXAuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8xMi5yZXBsYXlhYmxlSWYgPSBmdW5jdGlvbiByZXBsYXlhYmxlSWYoX3JlZjIpIHsKICAgICAgdmFyIF90aGlzNyA9IHRoaXM7CgogICAgICB2YXIgYXJncyA9IF9yZWYyLmFyZ3MsCiAgICAgICAgICBpZlRydWUgPSBfcmVmMi5pZlRydWUsCiAgICAgICAgICBpZkZhbHNlID0gX3JlZjIuaWZGYWxzZTsKICAgICAgdGhpcy5yZXBsYXlhYmxlKHsKICAgICAgICBhcmdzOiBhcmdzLAogICAgICAgIGJvZHk6IGZ1bmN0aW9uIGJvZHkoKSB7CiAgICAgICAgICAvLyBJZiB0aGUgY29uZGl0aW9uYWwgaXMgZmFsc2UsIGp1bXAgdG8gdGhlIEVMU0UgbGFiZWwuCiAgICAgICAgICBfdGhpczcuanVtcFVubGVzcygnRUxTRScpOyAvLyBPdGhlcndpc2UsIGV4ZWN1dGUgdGhlIGNvZGUgYXNzb2NpYXRlZCB3aXRoIHRoZSB0cnVlIGJyYW5jaC4KCgogICAgICAgICAgaWZUcnVlKCk7IC8vIFdlJ3JlIGRvbmUsIHNvIHJldHVybi4gSW4gdGhlIGluaXRpYWwgZXhlY3V0aW9uLCB0aGlzIHJ1bnMKICAgICAgICAgIC8vIHRoZSBjbGVhbnVwIGNvZGUuIEluIHRoZSB1cGRhdGluZyBWTSwgaXQgZXhpdHMgdGhlIHVwZGF0aW5nCiAgICAgICAgICAvLyByb3V0aW5lLgoKICAgICAgICAgIF90aGlzNy5qdW1wKCdGSU5BTExZJyk7CgogICAgICAgICAgX3RoaXM3LmxhYmVsKCdFTFNFJyk7IC8vIElmIHRoZSBjb25kaXRpb25hbCBpcyBmYWxzZSwgYW5kIGNvZGUgYXNzb2NpYXRpZWQgaXRoIHRoZQogICAgICAgICAgLy8gZmFsc2UgYnJhbmNoIHdhcyBwcm92aWRlZCwgZXhlY3V0ZSBpdC4gSWYgdGhlcmUgd2FzIG5vIGNvZGUKICAgICAgICAgIC8vIGFzc29jaWF0ZWQgd2l0aCB0aGUgZmFsc2UgYnJhbmNoLCBqdW1waW5nIHRvIHRoZSBlbHNlIHN0YXRlbWVudAogICAgICAgICAgLy8gaGFzIG5vIG90aGVyIGJlaGF2aW9yLgoKCiAgICAgICAgICBpZiAoaWZGYWxzZSkgewogICAgICAgICAgICBpZkZhbHNlKCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvMTIuaW5saW5lQmxvY2sgPSBmdW5jdGlvbiBpbmxpbmVCbG9jayhibG9jaykgewogICAgICByZXR1cm4gbmV3IENvbXBpbGFibGVCbG9jayh0aGlzLmNvbXBpbGVyLCB7CiAgICAgICAgYmxvY2s6IGJsb2NrLAogICAgICAgIGNvbnRhaW5pbmdMYXlvdXQ6IHRoaXMuY29udGFpbmluZ0xheW91dAogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvMTIuZXZhbFN5bWJvbHMgPSBmdW5jdGlvbiBldmFsU3ltYm9scygpIHsKICAgICAgdmFyIGJsb2NrID0gdGhpcy5jb250YWluaW5nTGF5b3V0LmJsb2NrOwogICAgICByZXR1cm4gYmxvY2suaGFzRXZhbCA/IGJsb2NrLnN5bWJvbHMgOiBudWxsOwogICAgfTsKCiAgICBfcHJvdG8xMi5jb21waWxlUGFyYW1zID0gZnVuY3Rpb24gY29tcGlsZVBhcmFtcyhwYXJhbXMpIHsKICAgICAgaWYgKCFwYXJhbXMpIHJldHVybiAwOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJhbXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB0aGlzLmV4cHIocGFyYW1zW2ldKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHBhcmFtcy5sZW5ndGg7CiAgICB9OwoKICAgIF9wcm90bzEyLmNvbXBpbGVBcmdzID0gZnVuY3Rpb24gY29tcGlsZUFyZ3MocGFyYW1zLCBoYXNoLCBibG9ja3MsIHN5bnRoZXRpYykgewogICAgICBpZiAoYmxvY2tzKSB7CiAgICAgICAgdGhpcy5wdXNoWWllbGRhYmxlQmxvY2soYmxvY2tzLm1haW4pOwogICAgICAgIHRoaXMucHVzaFlpZWxkYWJsZUJsb2NrKGJsb2Nrcy5lbHNlKTsKICAgICAgICB0aGlzLnB1c2hZaWVsZGFibGVCbG9jayhibG9ja3MuYXR0cnMpOwogICAgICB9CgogICAgICB2YXIgY291bnQgPSB0aGlzLmNvbXBpbGVQYXJhbXMocGFyYW1zKTsKICAgICAgdmFyIGZsYWdzID0gY291bnQgPDwgNDsKICAgICAgaWYgKHN5bnRoZXRpYykgZmxhZ3MgfD0gODsKCiAgICAgIGlmIChibG9ja3MpIHsKICAgICAgICBmbGFncyB8PSA3OwogICAgICB9CgogICAgICB2YXIgbmFtZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKCiAgICAgIGlmIChoYXNoKSB7CiAgICAgICAgbmFtZXMgPSBoYXNoWzBdOwogICAgICAgIHZhciB2YWwgPSBoYXNoWzFdOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZhbC5sZW5ndGg7IGkrKykgewogICAgICAgICAgdGhpcy5leHByKHZhbFtpXSk7CiAgICAgICAgfQogICAgICB9CgogICAgICB0aGlzLnB1c2hBcmdzKG5hbWVzLCBmbGFncyk7CiAgICB9OwoKICAgIF9wcm90bzEyLnRlbXBsYXRlID0gZnVuY3Rpb24gdGVtcGxhdGUoYmxvY2spIHsKICAgICAgaWYgKCFibG9jaykgcmV0dXJuIG51bGw7CiAgICAgIHJldHVybiB0aGlzLmlubGluZUJsb2NrKGJsb2NrKTsKICAgIH07CgogICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShPcGNvZGVCdWlsZGVyLCBbewogICAgICBrZXk6ICJyZWZlcnJlciIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5pbmdMYXlvdXQgJiYgdGhpcy5jb250YWluaW5nTGF5b3V0LnJlZmVycmVyOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gT3Bjb2RlQnVpbGRlcjsKICB9KFN0ZE9wY29kZUJ1aWxkZXIpOwoKICBfZXhwb3J0cy5PcGNvZGVCdWlsZGVyID0gT3Bjb2RlQnVpbGRlcjsKCiAgdmFyIExhenlPcGNvZGVCdWlsZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9PcGNvZGVCdWlsZGVyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTGF6eU9wY29kZUJ1aWxkZXIsIF9PcGNvZGVCdWlsZGVyKTsKCiAgICBmdW5jdGlvbiBMYXp5T3Bjb2RlQnVpbGRlcigpIHsKICAgICAgcmV0dXJuIF9PcGNvZGVCdWlsZGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTMgPSBMYXp5T3Bjb2RlQnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMTMucHVzaEJsb2NrID0gZnVuY3Rpb24gcHVzaEJsb2NrKGJsb2NrKSB7CiAgICAgIGlmIChibG9jaykgewogICAgICAgIHRoaXMucHVzaE90aGVyKGJsb2NrKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnByaW1pdGl2ZShudWxsKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8xMy5yZXNvbHZlQmxvY2sgPSBmdW5jdGlvbiByZXNvbHZlQmxvY2soKSB7CiAgICAgIHRoaXMucHVzaCg0NgogICAgICAvKiBDb21waWxlQmxvY2sgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvMTMucHVzaExheW91dCA9IGZ1bmN0aW9uIHB1c2hMYXlvdXQobGF5b3V0KSB7CiAgICAgIGlmIChsYXlvdXQpIHsKICAgICAgICB0aGlzLnB1c2hPdGhlcihsYXlvdXQpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMucHJpbWl0aXZlKG51bGwpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzEzLnJlc29sdmVMYXlvdXQgPSBmdW5jdGlvbiByZXNvbHZlTGF5b3V0KCkgewogICAgICB0aGlzLnB1c2goNDYKICAgICAgLyogQ29tcGlsZUJsb2NrICovCiAgICAgICk7CiAgICB9OwoKICAgIF9wcm90bzEzLmludm9rZVN0YXRpYyA9IGZ1bmN0aW9uIGludm9rZVN0YXRpYyhjb21waWxhYmxlKSB7CiAgICAgIHRoaXMucHVzaE90aGVyKGNvbXBpbGFibGUpOwogICAgICB0aGlzLnB1c2goNDYKICAgICAgLyogQ29tcGlsZUJsb2NrICovCiAgICAgICk7CiAgICAgIHRoaXMucHVzaE1hY2hpbmUoNDkKICAgICAgLyogSW52b2tlVmlydHVhbCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG8xMy5wdXNoT3RoZXIgPSBmdW5jdGlvbiBwdXNoT3RoZXIodmFsdWUpIHsKICAgICAgdGhpcy5wdXNoKDEyCiAgICAgIC8qIENvbnN0YW50ICovCiAgICAgICwgdGhpcy5vdGhlcih2YWx1ZSkpOwogICAgfTsKCiAgICBfcHJvdG8xMy5vdGhlciA9IGZ1bmN0aW9uIG90aGVyKHZhbHVlKSB7CiAgICAgIHJldHVybiB0aGlzLmNvbnN0YW50cy5vdGhlcih2YWx1ZSk7CiAgICB9OwoKICAgIHJldHVybiBMYXp5T3Bjb2RlQnVpbGRlcjsKICB9KE9wY29kZUJ1aWxkZXIpOwoKICBfZXhwb3J0cy5MYXp5T3Bjb2RlQnVpbGRlciA9IExhenlPcGNvZGVCdWlsZGVyOwoKICB2YXIgRWFnZXJPcGNvZGVCdWlsZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9PcGNvZGVCdWlsZGVyMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEVhZ2VyT3Bjb2RlQnVpbGRlciwgX09wY29kZUJ1aWxkZXIyKTsKCiAgICBmdW5jdGlvbiBFYWdlck9wY29kZUJ1aWxkZXIoKSB7CiAgICAgIHJldHVybiBfT3Bjb2RlQnVpbGRlcjIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8xNCA9IEVhZ2VyT3Bjb2RlQnVpbGRlci5wcm90b3R5cGU7CgogICAgX3Byb3RvMTQucHVzaEJsb2NrID0gZnVuY3Rpb24gcHVzaEJsb2NrKGJsb2NrKSB7CiAgICAgIHZhciBoYW5kbGUgPSBibG9jayA/IGJsb2NrLmNvbXBpbGUoKSA6IG51bGw7CiAgICAgIHRoaXMucHJpbWl0aXZlKGhhbmRsZSk7CiAgICB9OwoKICAgIF9wcm90bzE0LnJlc29sdmVCbG9jayA9IGZ1bmN0aW9uIHJlc29sdmVCbG9jaygpIHsKICAgICAgcmV0dXJuOwogICAgfTsKCiAgICBfcHJvdG8xNC5wdXNoTGF5b3V0ID0gZnVuY3Rpb24gcHVzaExheW91dChsYXlvdXQpIHsKICAgICAgaWYgKGxheW91dCkgewogICAgICAgIHRoaXMucHJpbWl0aXZlKGxheW91dC5jb21waWxlKCkpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMucHJpbWl0aXZlKG51bGwpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzE0LnJlc29sdmVMYXlvdXQgPSBmdW5jdGlvbiByZXNvbHZlTGF5b3V0KCkge307CgogICAgX3Byb3RvMTQuaW52b2tlU3RhdGljID0gZnVuY3Rpb24gaW52b2tlU3RhdGljKGNvbXBpbGFibGUpIHsKICAgICAgdmFyIGhhbmRsZSA9IGNvbXBpbGFibGUuY29tcGlsZSgpOyAvLyBJZiB0aGUgaGFuZGxlIGZvciB0aGUgaW52b2tlZCBjb21wb25lbnQgaXMgbm90IHlldCBrbm93biAoZm9yIGV4YW1wbGUsCiAgICAgIC8vIGJlY2F1c2UgdGhpcyBpcyBhIHJlY3Vyc2l2ZSBpbnZvY2F0aW9uIGFuZCB3ZSdyZSBzdGlsbCBjb21waWxpbmcpLCBwdXNoIGEKICAgICAgLy8gZnVuY3Rpb24gdGhhdCB3aWxsIHByb2R1Y2UgdGhlIGNvcnJlY3QgaGFuZGxlIHdoZW4gdGhlIGhlYXAgaXMKICAgICAgLy8gc2VyaWFsaXplZC4KCiAgICAgIGlmIChoYW5kbGUgPT09IFBMQUNFSE9MREVSX0hBTkRMRSQxKSB7CiAgICAgICAgdGhpcy5wdXNoTWFjaGluZSg1MAogICAgICAgIC8qIEludm9rZVN0YXRpYyAqLwogICAgICAgICwgZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuIGNvbXBpbGFibGUuY29tcGlsZSgpOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMucHVzaE1hY2hpbmUoNTAKICAgICAgICAvKiBJbnZva2VTdGF0aWMgKi8KICAgICAgICAsIGhhbmRsZSk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIEVhZ2VyT3Bjb2RlQnVpbGRlcjsKICB9KE9wY29kZUJ1aWxkZXIpOwoKICBfZXhwb3J0cy5FYWdlck9wY29kZUJ1aWxkZXIgPSBFYWdlck9wY29kZUJ1aWxkZXI7CgogIHZhciBMYXp5Q29tcGlsZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Fic3RyYWN0Q29tcGlsZXIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShMYXp5Q29tcGlsZXIsIF9BYnN0cmFjdENvbXBpbGVyKTsKCiAgICAvLyBGSVhNRTogdHVybiB0byBzdGF0aWMgbWV0aG9kCiAgICBmdW5jdGlvbiBMYXp5Q29tcGlsZXIobG9va3VwLCByZXNvbHZlciwgbWFjcm9zKSB7CiAgICAgIHZhciBjb25zdGFudHMgPSBuZXcgX3Byb2dyYW0uTGF6eUNvbnN0YW50cyhyZXNvbHZlcik7CiAgICAgIHZhciBwcm9ncmFtID0gbmV3IF9wcm9ncmFtLlByb2dyYW0oY29uc3RhbnRzKTsKICAgICAgcmV0dXJuIF9BYnN0cmFjdENvbXBpbGVyLmNhbGwodGhpcywgbWFjcm9zLCBwcm9ncmFtLCBsb29rdXApIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzE1ID0gTGF6eUNvbXBpbGVyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xNS5idWlsZGVyRm9yID0gZnVuY3Rpb24gYnVpbGRlckZvcihjb250YWluaW5nTGF5b3V0KSB7CiAgICAgIHJldHVybiBuZXcgTGF6eU9wY29kZUJ1aWxkZXIodGhpcywgY29udGFpbmluZ0xheW91dCk7CiAgICB9OwoKICAgIHJldHVybiBMYXp5Q29tcGlsZXI7CiAgfShBYnN0cmFjdENvbXBpbGVyKTsKCiAgX2V4cG9ydHMuTGF6eUNvbXBpbGVyID0gTGF6eUNvbXBpbGVyOwoKICB2YXIgUGFydGlhbERlZmluaXRpb24gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBQYXJ0aWFsRGVmaW5pdGlvbihuYW1lLCAvLyBmb3IgZGVidWdnaW5nCiAgICB0ZW1wbGF0ZSkgewogICAgICB0aGlzLm5hbWUgPSBuYW1lOwogICAgICB0aGlzLnRlbXBsYXRlID0gdGVtcGxhdGU7CiAgICB9CgogICAgdmFyIF9wcm90bzE2ID0gUGFydGlhbERlZmluaXRpb24ucHJvdG90eXBlOwoKICAgIF9wcm90bzE2LmdldFBhcnRpYWwgPSBmdW5jdGlvbiBnZXRQYXJ0aWFsKCkgewogICAgICB2YXIgcGFydGlhbCA9IHRoaXMudGVtcGxhdGUuYXNQYXJ0aWFsKCk7CiAgICAgIHZhciBoYW5kbGUgPSBwYXJ0aWFsLmNvbXBpbGUoKTsKICAgICAgcmV0dXJuIHsKICAgICAgICBzeW1ib2xUYWJsZTogcGFydGlhbC5zeW1ib2xUYWJsZSwKICAgICAgICBoYW5kbGU6IGhhbmRsZQogICAgICB9OwogICAgfTsKCiAgICByZXR1cm4gUGFydGlhbERlZmluaXRpb247CiAgfSgpOwoKICBfZXhwb3J0cy5QYXJ0aWFsRGVmaW5pdGlvbiA9IFBhcnRpYWxEZWZpbml0aW9uOwogIHZhciBjbGllbnRJZCA9IDA7CgogIGZ1bmN0aW9uIHRlbXBsYXRlRmFjdG9yeShfcmVmMykgewogICAgdmFyIHRlbXBsYXRlSWQgPSBfcmVmMy5pZCwKICAgICAgICBtZXRhID0gX3JlZjMubWV0YSwKICAgICAgICBibG9jayA9IF9yZWYzLmJsb2NrOwogICAgdmFyIHBhcnNlZEJsb2NrOwogICAgdmFyIGlkID0gdGVtcGxhdGVJZCB8fCAiY2xpZW50LSIgKyBjbGllbnRJZCsrOwoKICAgIHZhciBjcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoY29tcGlsZXIsIGVudk1ldGEpIHsKICAgICAgdmFyIG5ld01ldGEgPSBlbnZNZXRhID8gKDAsIF91dGlsLmFzc2lnbikoe30sIGVudk1ldGEsIG1ldGEpIDogbWV0YTsKCiAgICAgIGlmICghcGFyc2VkQmxvY2spIHsKICAgICAgICBwYXJzZWRCbG9jayA9IEpTT04ucGFyc2UoYmxvY2spOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IFRlbXBsYXRlSW1wbChjb21waWxlciwgewogICAgICAgIGlkOiBpZCwKICAgICAgICBibG9jazogcGFyc2VkQmxvY2ssCiAgICAgICAgcmVmZXJyZXI6IG5ld01ldGEKICAgICAgfSk7CiAgICB9OwoKICAgIHJldHVybiB7CiAgICAgIGlkOiBpZCwKICAgICAgbWV0YTogbWV0YSwKICAgICAgY3JlYXRlOiBjcmVhdGUKICAgIH07CiAgfQoKICB2YXIgVGVtcGxhdGVJbXBsID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gVGVtcGxhdGVJbXBsKGNvbXBpbGVyLCBwYXJzZWRMYXlvdXQpIHsKICAgICAgdGhpcy5jb21waWxlciA9IGNvbXBpbGVyOwogICAgICB0aGlzLnBhcnNlZExheW91dCA9IHBhcnNlZExheW91dDsKICAgICAgdGhpcy5sYXlvdXQgPSBudWxsOwogICAgICB0aGlzLnBhcnRpYWwgPSBudWxsOwogICAgICB0aGlzLndyYXBwZWRMYXlvdXQgPSBudWxsOwogICAgICB2YXIgYmxvY2sgPSBwYXJzZWRMYXlvdXQuYmxvY2s7CiAgICAgIHRoaXMuc3ltYm9scyA9IGJsb2NrLnN5bWJvbHM7CiAgICAgIHRoaXMuaGFzRXZhbCA9IGJsb2NrLmhhc0V2YWw7CiAgICAgIHRoaXMucmVmZXJyZXIgPSBwYXJzZWRMYXlvdXQucmVmZXJyZXI7CiAgICAgIHRoaXMuaWQgPSBwYXJzZWRMYXlvdXQuaWQgfHwgImNsaWVudC0iICsgY2xpZW50SWQrKzsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTcgPSBUZW1wbGF0ZUltcGwucHJvdG90eXBlOwoKICAgIF9wcm90bzE3LmFzTGF5b3V0ID0gZnVuY3Rpb24gYXNMYXlvdXQoKSB7CiAgICAgIGlmICh0aGlzLmxheW91dCkgcmV0dXJuIHRoaXMubGF5b3V0OwogICAgICByZXR1cm4gdGhpcy5sYXlvdXQgPSBuZXcgQ29tcGlsYWJsZVByb2dyYW0odGhpcy5jb21waWxlciwgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgdGhpcy5wYXJzZWRMYXlvdXQsIHsKICAgICAgICBhc1BhcnRpYWw6IGZhbHNlCiAgICAgIH0pKTsKICAgIH07CgogICAgX3Byb3RvMTcuYXNQYXJ0aWFsID0gZnVuY3Rpb24gYXNQYXJ0aWFsKCkgewogICAgICBpZiAodGhpcy5wYXJ0aWFsKSByZXR1cm4gdGhpcy5wYXJ0aWFsOwogICAgICByZXR1cm4gdGhpcy5sYXlvdXQgPSBuZXcgQ29tcGlsYWJsZVByb2dyYW0odGhpcy5jb21waWxlciwgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgdGhpcy5wYXJzZWRMYXlvdXQsIHsKICAgICAgICBhc1BhcnRpYWw6IHRydWUKICAgICAgfSkpOwogICAgfTsKCiAgICBfcHJvdG8xNy5hc1dyYXBwZWRMYXlvdXQgPSBmdW5jdGlvbiBhc1dyYXBwZWRMYXlvdXQoKSB7CiAgICAgIGlmICh0aGlzLndyYXBwZWRMYXlvdXQpIHJldHVybiB0aGlzLndyYXBwZWRMYXlvdXQ7CiAgICAgIHJldHVybiB0aGlzLndyYXBwZWRMYXlvdXQgPSBuZXcgV3JhcHBlZEJ1aWxkZXIodGhpcy5jb21waWxlciwgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgdGhpcy5wYXJzZWRMYXlvdXQsIHsKICAgICAgICBhc1BhcnRpYWw6IGZhbHNlCiAgICAgIH0pKTsKICAgIH07CgogICAgcmV0dXJuIFRlbXBsYXRlSW1wbDsKICB9KCk7Cn0pOwpkZWZpbmUoIkBnbGltbWVyL3Byb2dyYW0iLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiLCAiQGdsaW1tZXIvdXRpbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsLCBfdXRpbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuT3Bjb2RlID0gX2V4cG9ydHMuUHJvZ3JhbSA9IF9leHBvcnRzLlJ1bnRpbWVQcm9ncmFtID0gX2V4cG9ydHMuV3JpdGVPbmx5UHJvZ3JhbSA9IF9leHBvcnRzLkhlYXAgPSBfZXhwb3J0cy5MYXp5Q29uc3RhbnRzID0gX2V4cG9ydHMuQ29uc3RhbnRzID0gX2V4cG9ydHMuUnVudGltZUNvbnN0YW50cyA9IF9leHBvcnRzLldyaXRlT25seUNvbnN0YW50cyA9IF9leHBvcnRzLldFTExfS05PV05fRU1QVFlfQVJSQVlfUE9TSVRJT04gPSB2b2lkIDA7CiAgdmFyIFVOUkVTT0xWRUQgPSB7fTsKICB2YXIgV0VMTF9LTk9XTl9FTVBUWV9BUlJBWV9QT1NJVElPTiA9IDA7CiAgX2V4cG9ydHMuV0VMTF9LTk9XTl9FTVBUWV9BUlJBWV9QT1NJVElPTiA9IFdFTExfS05PV05fRU1QVFlfQVJSQVlfUE9TSVRJT047CiAgdmFyIFdFTExfS05PV19FTVBUWV9BUlJBWSA9IE9iamVjdC5mcmVlemUoW10pOwoKICB2YXIgV3JpdGVPbmx5Q29uc3RhbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gV3JpdGVPbmx5Q29uc3RhbnRzKCkgewogICAgICAvLyBgMGAgbWVhbnMgTlVMTAogICAgICB0aGlzLnN0cmluZ3MgPSBbXTsKICAgICAgdGhpcy5hcnJheXMgPSBbV0VMTF9LTk9XX0VNUFRZX0FSUkFZXTsKICAgICAgdGhpcy50YWJsZXMgPSBbXTsKICAgICAgdGhpcy5oYW5kbGVzID0gW107CiAgICAgIHRoaXMucmVzb2x2ZWQgPSBbXTsKICAgICAgdGhpcy5udW1iZXJzID0gW107CiAgICB9CgogICAgdmFyIF9wcm90byA9IFdyaXRlT25seUNvbnN0YW50cy5wcm90b3R5cGU7CgogICAgX3Byb3RvLnN0cmluZyA9IGZ1bmN0aW9uIHN0cmluZyh2YWx1ZSkgewogICAgICB2YXIgaW5kZXggPSB0aGlzLnN0cmluZ3MuaW5kZXhPZih2YWx1ZSk7CgogICAgICBpZiAoaW5kZXggPiAtMSkgewogICAgICAgIHJldHVybiBpbmRleDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuc3RyaW5ncy5wdXNoKHZhbHVlKSAtIDE7CiAgICB9OwoKICAgIF9wcm90by5zdHJpbmdBcnJheSA9IGZ1bmN0aW9uIHN0cmluZ0FycmF5KHN0cmluZ3MpIHsKICAgICAgdmFyIF9zdHJpbmdzID0gbmV3IEFycmF5KHN0cmluZ3MubGVuZ3RoKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyaW5ncy5sZW5ndGg7IGkrKykgewogICAgICAgIF9zdHJpbmdzW2ldID0gdGhpcy5zdHJpbmcoc3RyaW5nc1tpXSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLmFycmF5KF9zdHJpbmdzKTsKICAgIH07CgogICAgX3Byb3RvLmFycmF5ID0gZnVuY3Rpb24gYXJyYXkodmFsdWVzKSB7CiAgICAgIGlmICh2YWx1ZXMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIFdFTExfS05PV05fRU1QVFlfQVJSQVlfUE9TSVRJT047CiAgICAgIH0KCiAgICAgIHZhciBpbmRleCA9IHRoaXMuYXJyYXlzLmluZGV4T2YodmFsdWVzKTsKCiAgICAgIGlmIChpbmRleCA+IC0xKSB7CiAgICAgICAgcmV0dXJuIGluZGV4OwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5hcnJheXMucHVzaCh2YWx1ZXMpIC0gMTsKICAgIH07CgogICAgX3Byb3RvLmhhbmRsZSA9IGZ1bmN0aW9uIGhhbmRsZShfaGFuZGxlKSB7CiAgICAgIHZhciBpbmRleCA9IHRoaXMuaGFuZGxlcy5pbmRleE9mKF9oYW5kbGUpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICByZXR1cm4gaW5kZXg7CiAgICAgIH0KCiAgICAgIHRoaXMucmVzb2x2ZWQucHVzaChVTlJFU09MVkVEKTsKICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlcy5wdXNoKF9oYW5kbGUpIC0gMTsKICAgIH07CgogICAgX3Byb3RvLnNlcmlhbGl6YWJsZSA9IGZ1bmN0aW9uIHNlcmlhbGl6YWJsZSh2YWx1ZSkgewogICAgICB2YXIgc3RyID0gSlNPTi5zdHJpbmdpZnkodmFsdWUpOwogICAgICB2YXIgaW5kZXggPSB0aGlzLnN0cmluZ3MuaW5kZXhPZihzdHIpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICByZXR1cm4gaW5kZXg7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLnN0cmluZ3MucHVzaChzdHIpIC0gMTsKICAgIH07CgogICAgX3Byb3RvLm51bWJlciA9IGZ1bmN0aW9uIG51bWJlcihfbnVtYmVyKSB7CiAgICAgIHZhciBpbmRleCA9IHRoaXMubnVtYmVycy5pbmRleE9mKF9udW1iZXIpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICByZXR1cm4gaW5kZXg7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLm51bWJlcnMucHVzaChfbnVtYmVyKSAtIDE7CiAgICB9OwoKICAgIF9wcm90by50b1Bvb2wgPSBmdW5jdGlvbiB0b1Bvb2woKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgc3RyaW5nczogdGhpcy5zdHJpbmdzLAogICAgICAgIGFycmF5czogdGhpcy5hcnJheXMsCiAgICAgICAgaGFuZGxlczogdGhpcy5oYW5kbGVzLAogICAgICAgIG51bWJlcnM6IHRoaXMubnVtYmVycwogICAgICB9OwogICAgfTsKCiAgICByZXR1cm4gV3JpdGVPbmx5Q29uc3RhbnRzOwogIH0oKTsKCiAgX2V4cG9ydHMuV3JpdGVPbmx5Q29uc3RhbnRzID0gV3JpdGVPbmx5Q29uc3RhbnRzOwoKICB2YXIgUnVudGltZUNvbnN0YW50cyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJ1bnRpbWVDb25zdGFudHMocmVzb2x2ZXIsIHBvb2wpIHsKICAgICAgdGhpcy5yZXNvbHZlciA9IHJlc29sdmVyOwogICAgICB0aGlzLnN0cmluZ3MgPSBwb29sLnN0cmluZ3M7CiAgICAgIHRoaXMuYXJyYXlzID0gcG9vbC5hcnJheXM7CiAgICAgIHRoaXMuaGFuZGxlcyA9IHBvb2wuaGFuZGxlczsKICAgICAgdGhpcy5yZXNvbHZlZCA9IHRoaXMuaGFuZGxlcy5tYXAoZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBVTlJFU09MVkVEOwogICAgICB9KTsKICAgICAgdGhpcy5udW1iZXJzID0gcG9vbC5udW1iZXJzOwogICAgfQoKICAgIHZhciBfcHJvdG8yID0gUnVudGltZUNvbnN0YW50cy5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5nZXRTdHJpbmcgPSBmdW5jdGlvbiBnZXRTdHJpbmcodmFsdWUpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RyaW5nc1t2YWx1ZV07CiAgICB9OwoKICAgIF9wcm90bzIuZ2V0TnVtYmVyID0gZnVuY3Rpb24gZ2V0TnVtYmVyKHZhbHVlKSB7CiAgICAgIHJldHVybiB0aGlzLm51bWJlcnNbdmFsdWVdOwogICAgfTsKCiAgICBfcHJvdG8yLmdldFN0cmluZ0FycmF5ID0gZnVuY3Rpb24gZ2V0U3RyaW5nQXJyYXkodmFsdWUpIHsKICAgICAgdmFyIG5hbWVzID0gdGhpcy5nZXRBcnJheSh2YWx1ZSk7CgogICAgICB2YXIgX25hbWVzID0gbmV3IEFycmF5KG5hbWVzLmxlbmd0aCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIG4gPSBuYW1lc1tpXTsKICAgICAgICBfbmFtZXNbaV0gPSB0aGlzLmdldFN0cmluZyhuKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9uYW1lczsKICAgIH07CgogICAgX3Byb3RvMi5nZXRBcnJheSA9IGZ1bmN0aW9uIGdldEFycmF5KHZhbHVlKSB7CiAgICAgIHJldHVybiB0aGlzLmFycmF5c1t2YWx1ZV07CiAgICB9OwoKICAgIF9wcm90bzIucmVzb2x2ZUhhbmRsZSA9IGZ1bmN0aW9uIHJlc29sdmVIYW5kbGUoaW5kZXgpIHsKICAgICAgdmFyIHJlc29sdmVkID0gdGhpcy5yZXNvbHZlZFtpbmRleF07CgogICAgICBpZiAocmVzb2x2ZWQgPT09IFVOUkVTT0xWRUQpIHsKICAgICAgICB2YXIgaGFuZGxlID0gdGhpcy5oYW5kbGVzW2luZGV4XTsKICAgICAgICByZXNvbHZlZCA9IHRoaXMucmVzb2x2ZWRbaW5kZXhdID0gdGhpcy5yZXNvbHZlci5yZXNvbHZlKGhhbmRsZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiByZXNvbHZlZDsKICAgIH07CgogICAgX3Byb3RvMi5nZXRTZXJpYWxpemFibGUgPSBmdW5jdGlvbiBnZXRTZXJpYWxpemFibGUocykgewogICAgICByZXR1cm4gSlNPTi5wYXJzZSh0aGlzLnN0cmluZ3Nbc10pOwogICAgfTsKCiAgICByZXR1cm4gUnVudGltZUNvbnN0YW50czsKICB9KCk7CgogIF9leHBvcnRzLlJ1bnRpbWVDb25zdGFudHMgPSBSdW50aW1lQ29uc3RhbnRzOwoKICB2YXIgQ29uc3RhbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Xcml0ZU9ubHlDb25zdGFudHMpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDb25zdGFudHMsIF9Xcml0ZU9ubHlDb25zdGFudHMpOwoKICAgIGZ1bmN0aW9uIENvbnN0YW50cyhyZXNvbHZlciwgcG9vbCkgewogICAgICB2YXIgX3RoaXM7CgogICAgICBfdGhpcyA9IF9Xcml0ZU9ubHlDb25zdGFudHMuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpcy5yZXNvbHZlciA9IHJlc29sdmVyOwoKICAgICAgaWYgKHBvb2wpIHsKICAgICAgICBfdGhpcy5zdHJpbmdzID0gcG9vbC5zdHJpbmdzOwogICAgICAgIF90aGlzLmFycmF5cyA9IHBvb2wuYXJyYXlzOwogICAgICAgIF90aGlzLmhhbmRsZXMgPSBwb29sLmhhbmRsZXM7CiAgICAgICAgX3RoaXMucmVzb2x2ZWQgPSBfdGhpcy5oYW5kbGVzLm1hcChmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gVU5SRVNPTFZFRDsKICAgICAgICB9KTsKICAgICAgICBfdGhpcy5udW1iZXJzID0gcG9vbC5udW1iZXJzOwogICAgICB9CgogICAgICByZXR1cm4gX3RoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzMgPSBDb25zdGFudHMucHJvdG90eXBlOwoKICAgIF9wcm90bzMuZ2V0TnVtYmVyID0gZnVuY3Rpb24gZ2V0TnVtYmVyKHZhbHVlKSB7CiAgICAgIHJldHVybiB0aGlzLm51bWJlcnNbdmFsdWVdOwogICAgfTsKCiAgICBfcHJvdG8zLmdldFN0cmluZyA9IGZ1bmN0aW9uIGdldFN0cmluZyh2YWx1ZSkgewogICAgICByZXR1cm4gdGhpcy5zdHJpbmdzW3ZhbHVlXTsKICAgIH07CgogICAgX3Byb3RvMy5nZXRTdHJpbmdBcnJheSA9IGZ1bmN0aW9uIGdldFN0cmluZ0FycmF5KHZhbHVlKSB7CiAgICAgIHZhciBuYW1lcyA9IHRoaXMuZ2V0QXJyYXkodmFsdWUpOwoKICAgICAgdmFyIF9uYW1lcyA9IG5ldyBBcnJheShuYW1lcy5sZW5ndGgpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBuID0gbmFtZXNbaV07CiAgICAgICAgX25hbWVzW2ldID0gdGhpcy5nZXRTdHJpbmcobik7CiAgICAgIH0KCiAgICAgIHJldHVybiBfbmFtZXM7CiAgICB9OwoKICAgIF9wcm90bzMuZ2V0QXJyYXkgPSBmdW5jdGlvbiBnZXRBcnJheSh2YWx1ZSkgewogICAgICByZXR1cm4gdGhpcy5hcnJheXNbdmFsdWVdOwogICAgfTsKCiAgICBfcHJvdG8zLnJlc29sdmVIYW5kbGUgPSBmdW5jdGlvbiByZXNvbHZlSGFuZGxlKGluZGV4KSB7CiAgICAgIHZhciByZXNvbHZlZCA9IHRoaXMucmVzb2x2ZWRbaW5kZXhdOwoKICAgICAgaWYgKHJlc29sdmVkID09PSBVTlJFU09MVkVEKSB7CiAgICAgICAgdmFyIGhhbmRsZSA9IHRoaXMuaGFuZGxlc1tpbmRleF07CiAgICAgICAgcmVzb2x2ZWQgPSB0aGlzLnJlc29sdmVkW2luZGV4XSA9IHRoaXMucmVzb2x2ZXIucmVzb2x2ZShoYW5kbGUpOwogICAgICB9CgogICAgICByZXR1cm4gcmVzb2x2ZWQ7CiAgICB9OwoKICAgIF9wcm90bzMuZ2V0U2VyaWFsaXphYmxlID0gZnVuY3Rpb24gZ2V0U2VyaWFsaXphYmxlKHMpIHsKICAgICAgcmV0dXJuIEpTT04ucGFyc2UodGhpcy5zdHJpbmdzW3NdKTsKICAgIH07CgogICAgcmV0dXJuIENvbnN0YW50czsKICB9KFdyaXRlT25seUNvbnN0YW50cyk7CgogIF9leHBvcnRzLkNvbnN0YW50cyA9IENvbnN0YW50czsKCiAgdmFyIExhenlDb25zdGFudHMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NvbnN0YW50cykgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKExhenlDb25zdGFudHMsIF9Db25zdGFudHMpOwoKICAgIGZ1bmN0aW9uIExhenlDb25zdGFudHMoKSB7CiAgICAgIHZhciBfdGhpczI7CgogICAgICBfdGhpczIgPSBfQ29uc3RhbnRzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgICAgX3RoaXMyLm90aGVycyA9IFtdOwogICAgICBfdGhpczIuc2VyaWFsaXphYmxlcyA9IFtdOwogICAgICByZXR1cm4gX3RoaXMyOwogICAgfQoKICAgIHZhciBfcHJvdG80ID0gTGF6eUNvbnN0YW50cy5wcm90b3R5cGU7CgogICAgX3Byb3RvNC5zZXJpYWxpemFibGUgPSBmdW5jdGlvbiBzZXJpYWxpemFibGUodmFsdWUpIHsKICAgICAgdmFyIGluZGV4ID0gdGhpcy5zZXJpYWxpemFibGVzLmluZGV4T2YodmFsdWUpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICByZXR1cm4gaW5kZXg7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLnNlcmlhbGl6YWJsZXMucHVzaCh2YWx1ZSkgLSAxOwogICAgfTsKCiAgICBfcHJvdG80LmdldFNlcmlhbGl6YWJsZSA9IGZ1bmN0aW9uIGdldFNlcmlhbGl6YWJsZShzKSB7CiAgICAgIHJldHVybiB0aGlzLnNlcmlhbGl6YWJsZXNbc107CiAgICB9OwoKICAgIF9wcm90bzQuZ2V0T3RoZXIgPSBmdW5jdGlvbiBnZXRPdGhlcih2YWx1ZSkgewogICAgICByZXR1cm4gdGhpcy5vdGhlcnNbdmFsdWUgLSAxXTsKICAgIH07CgogICAgX3Byb3RvNC5vdGhlciA9IGZ1bmN0aW9uIG90aGVyKF9vdGhlcikgewogICAgICByZXR1cm4gdGhpcy5vdGhlcnMucHVzaChfb3RoZXIpOwogICAgfTsKCiAgICByZXR1cm4gTGF6eUNvbnN0YW50czsKICB9KENvbnN0YW50cyk7CgogIF9leHBvcnRzLkxhenlDb25zdGFudHMgPSBMYXp5Q29uc3RhbnRzOwoKICB2YXIgT3Bjb2RlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gT3Bjb2RlKGhlYXApIHsKICAgICAgdGhpcy5oZWFwID0gaGVhcDsKICAgICAgdGhpcy5vZmZzZXQgPSAwOwogICAgfQoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoT3Bjb2RlLCBbewogICAgICBrZXk6ICJzaXplIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIHJhd1R5cGUgPSB0aGlzLmhlYXAuZ2V0YnlhZGRyKHRoaXMub2Zmc2V0KTsKICAgICAgICByZXR1cm4gKChyYXdUeXBlICYgNzY4CiAgICAgICAgLyogT1BFUkFORF9MRU5fTUFTSyAqLwogICAgICAgICkgPj4gOAogICAgICAgIC8qIEFSR19TSElGVCAqLwogICAgICAgICkgKyAxOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImlzTWFjaGluZSIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciByYXdUeXBlID0gdGhpcy5oZWFwLmdldGJ5YWRkcih0aGlzLm9mZnNldCk7CiAgICAgICAgcmV0dXJuIHJhd1R5cGUgJiAxMDI0CiAgICAgICAgLyogTUFDSElORV9NQVNLICovCiAgICAgICAgOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInR5cGUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5oZWFwLmdldGJ5YWRkcih0aGlzLm9mZnNldCkgJiAyNTUKICAgICAgICAvKiBUWVBFX01BU0sgKi8KICAgICAgICA7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAib3AxIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaGVhcC5nZXRieWFkZHIodGhpcy5vZmZzZXQgKyAxKTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJvcDIiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5oZWFwLmdldGJ5YWRkcih0aGlzLm9mZnNldCArIDIpOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogIm9wMyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmhlYXAuZ2V0YnlhZGRyKHRoaXMub2Zmc2V0ICsgMyk7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBPcGNvZGU7CiAgfSgpOwoKICBfZXhwb3J0cy5PcGNvZGUgPSBPcGNvZGU7CgogIGZ1bmN0aW9uIGVuY29kZVRhYmxlSW5mbyhzY29wZVNpemUsIHN0YXRlKSB7CiAgICByZXR1cm4gc3RhdGUgfCBzY29wZVNpemUgPDwgMjsKICB9CgogIGZ1bmN0aW9uIGNoYW5nZVN0YXRlKGluZm8sIG5ld1N0YXRlKSB7CiAgICByZXR1cm4gaW5mbyB8IG5ld1N0YXRlIDw8IDMwOwogIH0KCiAgdmFyIFBBR0VfU0laRSA9IDB4MTAwMDAwOwogIC8qKgogICAqIFRoZSBIZWFwIGlzIHJlc3BvbnNpYmxlIGZvciBkeW5hbWljYWxseSBhbGxvY2F0aW5nCiAgICogbWVtb3J5IGluIHdoaWNoIHdlIHJlYWQvd3JpdGUgdGhlIFZNJ3MgaW5zdHJ1Y3Rpb25zCiAgICogZnJvbS90by4gV2hlbiB3ZSBtYWxsb2Mgd2UgcGFzcyBvdXQgYSBWTUhhbmRsZSwgd2hpY2gKICAgKiBpcyB1c2VkIGFzIGFuIGluZGlyZWN0IHdheSBvZiBhY2Nlc3NpbmcgdGhlIG1lbW9yeSBkdXJpbmcKICAgKiBleGVjdXRpb24gb2YgdGhlIFZNLiBJbnRlcm5hbGx5IHdlIHRyYWNrIHRoZSBkaWZmZXJlbnQKICAgKiByZWdpb25zIG9mIHRoZSBtZW1vcnkgaW4gYW4gaW50IGFycmF5IGtub3duIGFzIHRoZSB0YWJsZS4KICAgKgogICAqIFRoZSB0YWJsZSAzMi1iaXQgYWxpZ25lZCBhbmQgaGFzIHRoZSBmb2xsb3dpbmcgbGF5b3V0OgogICAqCiAgICogfCAuLi4gfCBocCAodTMyKSB8ICAgICAgIGluZm8gKHUzMikgICB8IHNpemUgKHUzMikgfAogICAqIHwgLi4uIHwgIEhhbmRsZSAgfCBTY29wZSBTaXplIHwgU3RhdGUgfCBTaXplICAgICAgIHwKICAgKiB8IC4uLiB8IDMyYml0cyAgIHwgMzBiaXRzICAgICB8IDJiaXRzIHwgMzJiaXQgICAgICB8CiAgICoKICAgKiBXaXRoIHRoaXMgaW5mb3JtYXRpb24gd2UgZWZmZWN0aXZlbHkgaGF2ZSB0aGUgYWJpbGl0eSB0bwogICAqIGNvbnRyb2wgd2hlbiB3ZSB3YW50IHRvIGZyZWUgbWVtb3J5LiBUaGF0IGJlaW5nIHNhaWQgeW91CiAgICogY2FuIG5vdCBmcmVlIGR1cmluZyBleGVjdXRpb24gYXMgcmF3IGFkZHJlc3MgYXJlIG9ubHkKICAgKiB2YWxpZCBkdXJpbmcgdGhlIGV4ZWN1dGlvbi4gVGhpcyBtZWFucyB5b3UgY2Fubm90IGNsb3NlCiAgICogb3ZlciB0aGVtIGFzIHlvdSB3aWxsIGhhdmUgYSBiYWQgbWVtb3J5IGFjY2VzcyBleGNlcHRpb24uCiAgICovCgogIHZhciBIZWFwID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSGVhcChzZXJpYWxpemVkSGVhcCkgewogICAgICB0aGlzLnBsYWNlaG9sZGVycyA9IFtdOwogICAgICB0aGlzLm9mZnNldCA9IDA7CiAgICAgIHRoaXMuaGFuZGxlID0gMDsKICAgICAgdGhpcy5jYXBhY2l0eSA9IFBBR0VfU0laRTsKCiAgICAgIGlmIChzZXJpYWxpemVkSGVhcCkgewogICAgICAgIHZhciBidWZmZXIgPSBzZXJpYWxpemVkSGVhcC5idWZmZXIsCiAgICAgICAgICAgIHRhYmxlID0gc2VyaWFsaXplZEhlYXAudGFibGUsCiAgICAgICAgICAgIGhhbmRsZSA9IHNlcmlhbGl6ZWRIZWFwLmhhbmRsZTsKICAgICAgICB0aGlzLmhlYXAgPSBuZXcgVWludDMyQXJyYXkoYnVmZmVyKTsKICAgICAgICB0aGlzLnRhYmxlID0gdGFibGU7CiAgICAgICAgdGhpcy5vZmZzZXQgPSB0aGlzLmhlYXAubGVuZ3RoOwogICAgICAgIHRoaXMuaGFuZGxlID0gaGFuZGxlOwogICAgICAgIHRoaXMuY2FwYWNpdHkgPSAwOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuaGVhcCA9IG5ldyBVaW50MzJBcnJheShQQUdFX1NJWkUpOwogICAgICAgIHRoaXMudGFibGUgPSBbXTsKICAgICAgfQogICAgfQoKICAgIHZhciBfcHJvdG81ID0gSGVhcC5wcm90b3R5cGU7CgogICAgX3Byb3RvNS5wdXNoID0gZnVuY3Rpb24gcHVzaChpdGVtKSB7CiAgICAgIHRoaXMuc2l6ZUNoZWNrKCk7CiAgICAgIHRoaXMuaGVhcFt0aGlzLm9mZnNldCsrXSA9IGl0ZW07CiAgICB9OwoKICAgIF9wcm90bzUuc2l6ZUNoZWNrID0gZnVuY3Rpb24gc2l6ZUNoZWNrKCkgewogICAgICBpZiAodGhpcy5jYXBhY2l0eSA9PT0gMCkgewogICAgICAgIHZhciBoZWFwID0gc2xpY2UodGhpcy5oZWFwLCAwLCB0aGlzLm9mZnNldCk7CiAgICAgICAgdGhpcy5oZWFwID0gbmV3IFVpbnQzMkFycmF5KGhlYXAubGVuZ3RoICsgUEFHRV9TSVpFKTsKICAgICAgICB0aGlzLmhlYXAuc2V0KGhlYXAsIDApOwogICAgICAgIHRoaXMuY2FwYWNpdHkgPSBQQUdFX1NJWkU7CiAgICAgIH0KCiAgICAgIHRoaXMuY2FwYWNpdHktLTsKICAgIH07CgogICAgX3Byb3RvNS5nZXRieWFkZHIgPSBmdW5jdGlvbiBnZXRieWFkZHIoYWRkcmVzcykgewogICAgICByZXR1cm4gdGhpcy5oZWFwW2FkZHJlc3NdOwogICAgfTsKCiAgICBfcHJvdG81LnNldGJ5YWRkciA9IGZ1bmN0aW9uIHNldGJ5YWRkcihhZGRyZXNzLCB2YWx1ZSkgewogICAgICB0aGlzLmhlYXBbYWRkcmVzc10gPSB2YWx1ZTsKICAgIH07CgogICAgX3Byb3RvNS5tYWxsb2MgPSBmdW5jdGlvbiBtYWxsb2MoKSB7CiAgICAgIC8vIHB1c2ggb2Zmc2V0LCBpbmZvLCBzaXplCiAgICAgIHRoaXMudGFibGUucHVzaCh0aGlzLm9mZnNldCwgMCwgMCk7CiAgICAgIHZhciBoYW5kbGUgPSB0aGlzLmhhbmRsZTsKICAgICAgdGhpcy5oYW5kbGUgKz0gMwogICAgICAvKiBFTlRSWV9TSVpFICovCiAgICAgIDsKICAgICAgcmV0dXJuIGhhbmRsZTsKICAgIH07CgogICAgX3Byb3RvNS5maW5pc2hNYWxsb2MgPSBmdW5jdGlvbiBmaW5pc2hNYWxsb2MoaGFuZGxlLCBzY29wZVNpemUpIHsKICAgICAgdGhpcy50YWJsZVtoYW5kbGUgKyAxCiAgICAgIC8qIElORk9fT0ZGU0VUICovCiAgICAgIF0gPSBlbmNvZGVUYWJsZUluZm8oc2NvcGVTaXplLCAwCiAgICAgIC8qIEFsbG9jYXRlZCAqLwogICAgICApOwogICAgfTsKCiAgICBfcHJvdG81LnNpemUgPSBmdW5jdGlvbiBzaXplKCkgewogICAgICByZXR1cm4gdGhpcy5vZmZzZXQ7CiAgICB9IC8vIEl0IGlzIGlsbGVnYWwgdG8gY2xvc2Ugb3ZlciB0aGlzIGFkZHJlc3MsIGFzIGNvbXBhY3Rpb24KICAgIC8vIG1heSBtb3ZlIGl0LiBIb3dldmVyLCBpdCBpcyBsZWdhbCB0byB1c2UgdGhpcyBhZGRyZXNzCiAgICAvLyBtdWx0aXBsZSB0aW1lcyBiZXR3ZWVuIGNvbXBhY3Rpb25zLgogICAgOwoKICAgIF9wcm90bzUuZ2V0YWRkciA9IGZ1bmN0aW9uIGdldGFkZHIoaGFuZGxlKSB7CiAgICAgIHJldHVybiB0aGlzLnRhYmxlW2hhbmRsZV07CiAgICB9OwoKICAgIF9wcm90bzUuZ2V0aGFuZGxlID0gZnVuY3Rpb24gZ2V0aGFuZGxlKGFkZHJlc3MpIHsKICAgICAgdGhpcy50YWJsZS5wdXNoKGFkZHJlc3MsIGVuY29kZVRhYmxlSW5mbygwLCAzCiAgICAgIC8qIFBvaW50ZXIgKi8KICAgICAgKSwgMCk7CiAgICAgIHZhciBoYW5kbGUgPSB0aGlzLmhhbmRsZTsKICAgICAgdGhpcy5oYW5kbGUgKz0gMwogICAgICAvKiBFTlRSWV9TSVpFICovCiAgICAgIDsKICAgICAgcmV0dXJuIGhhbmRsZTsKICAgIH07CgogICAgX3Byb3RvNS5zaXplb2YgPSBmdW5jdGlvbiBzaXplb2YoaGFuZGxlKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH07CgogICAgX3Byb3RvNS5zY29wZXNpemVvZiA9IGZ1bmN0aW9uIHNjb3Blc2l6ZW9mKGhhbmRsZSkgewogICAgICB2YXIgaW5mbyA9IHRoaXMudGFibGVbaGFuZGxlICsgMQogICAgICAvKiBJTkZPX09GRlNFVCAqLwogICAgICBdOwogICAgICByZXR1cm4gaW5mbyA+PiAyOwogICAgfTsKCiAgICBfcHJvdG81LmZyZWUgPSBmdW5jdGlvbiBmcmVlKGhhbmRsZSkgewogICAgICB2YXIgaW5mbyA9IHRoaXMudGFibGVbaGFuZGxlICsgMQogICAgICAvKiBJTkZPX09GRlNFVCAqLwogICAgICBdOwogICAgICB0aGlzLnRhYmxlW2hhbmRsZSArIDEKICAgICAgLyogSU5GT19PRkZTRVQgKi8KICAgICAgXSA9IGNoYW5nZVN0YXRlKGluZm8sIDEKICAgICAgLyogRnJlZWQgKi8KICAgICAgKTsKICAgIH07CgogICAgX3Byb3RvNS5wdXNoUGxhY2Vob2xkZXIgPSBmdW5jdGlvbiBwdXNoUGxhY2Vob2xkZXIodmFsdWVGdW5jKSB7CiAgICAgIHRoaXMuc2l6ZUNoZWNrKCk7CiAgICAgIHZhciBhZGRyZXNzID0gdGhpcy5vZmZzZXQrKzsKICAgICAgdGhpcy5oZWFwW2FkZHJlc3NdID0gMjE0NzQ4MzY0NwogICAgICAvKiBNQVhfU0laRSAqLwogICAgICA7CiAgICAgIHRoaXMucGxhY2Vob2xkZXJzLnB1c2goW2FkZHJlc3MsIHZhbHVlRnVuY10pOwogICAgfTsKCiAgICBfcHJvdG81LnBhdGNoUGxhY2Vob2xkZXJzID0gZnVuY3Rpb24gcGF0Y2hQbGFjZWhvbGRlcnMoKSB7CiAgICAgIHZhciBwbGFjZWhvbGRlcnMgPSB0aGlzLnBsYWNlaG9sZGVyczsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGxhY2Vob2xkZXJzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIF9wbGFjZWhvbGRlcnMkaSA9IHBsYWNlaG9sZGVyc1tpXSwKICAgICAgICAgICAgYWRkcmVzcyA9IF9wbGFjZWhvbGRlcnMkaVswXSwKICAgICAgICAgICAgZ2V0VmFsdWUgPSBfcGxhY2Vob2xkZXJzJGlbMV07CiAgICAgICAgdGhpcy5zZXRieWFkZHIoYWRkcmVzcywgZ2V0VmFsdWUoKSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNS5jYXB0dXJlID0gZnVuY3Rpb24gY2FwdHVyZShvZmZzZXQpIHsKICAgICAgaWYgKG9mZnNldCA9PT0gdm9pZCAwKSB7CiAgICAgICAgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7CiAgICAgIH0KCiAgICAgIHRoaXMucGF0Y2hQbGFjZWhvbGRlcnMoKTsgLy8gT25seSBjYWxsZWQgaW4gZWFnZXIgbW9kZQoKICAgICAgdmFyIGJ1ZmZlciA9IHNsaWNlKHRoaXMuaGVhcCwgMCwgb2Zmc2V0KS5idWZmZXI7CiAgICAgIHJldHVybiB7CiAgICAgICAgaGFuZGxlOiB0aGlzLmhhbmRsZSwKICAgICAgICB0YWJsZTogdGhpcy50YWJsZSwKICAgICAgICBidWZmZXI6IGJ1ZmZlcgogICAgICB9OwogICAgfTsKCiAgICByZXR1cm4gSGVhcDsKICB9KCk7CgogIF9leHBvcnRzLkhlYXAgPSBIZWFwOwoKICB2YXIgV3JpdGVPbmx5UHJvZ3JhbSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFdyaXRlT25seVByb2dyYW0oY29uc3RhbnRzLCBoZWFwKSB7CiAgICAgIGlmIChjb25zdGFudHMgPT09IHZvaWQgMCkgewogICAgICAgIGNvbnN0YW50cyA9IG5ldyBXcml0ZU9ubHlDb25zdGFudHMoKTsKICAgICAgfQoKICAgICAgaWYgKGhlYXAgPT09IHZvaWQgMCkgewogICAgICAgIGhlYXAgPSBuZXcgSGVhcCgpOwogICAgICB9CgogICAgICB0aGlzLmNvbnN0YW50cyA9IGNvbnN0YW50czsKICAgICAgdGhpcy5oZWFwID0gaGVhcDsKICAgICAgdGhpcy5fb3Bjb2RlID0gbmV3IE9wY29kZSh0aGlzLmhlYXApOwogICAgfQoKICAgIHZhciBfcHJvdG82ID0gV3JpdGVPbmx5UHJvZ3JhbS5wcm90b3R5cGU7CgogICAgX3Byb3RvNi5vcGNvZGUgPSBmdW5jdGlvbiBvcGNvZGUob2Zmc2V0KSB7CiAgICAgIHRoaXMuX29wY29kZS5vZmZzZXQgPSBvZmZzZXQ7CiAgICAgIHJldHVybiB0aGlzLl9vcGNvZGU7CiAgICB9OwoKICAgIHJldHVybiBXcml0ZU9ubHlQcm9ncmFtOwogIH0oKTsKCiAgX2V4cG9ydHMuV3JpdGVPbmx5UHJvZ3JhbSA9IFdyaXRlT25seVByb2dyYW07CgogIHZhciBSdW50aW1lUHJvZ3JhbSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJ1bnRpbWVQcm9ncmFtKGNvbnN0YW50cywgaGVhcCkgewogICAgICB0aGlzLmNvbnN0YW50cyA9IGNvbnN0YW50czsKICAgICAgdGhpcy5oZWFwID0gaGVhcDsKICAgICAgdGhpcy5fb3Bjb2RlID0gbmV3IE9wY29kZSh0aGlzLmhlYXApOwogICAgfQoKICAgIFJ1bnRpbWVQcm9ncmFtLmh5ZHJhdGUgPSBmdW5jdGlvbiBoeWRyYXRlKHJhd0hlYXAsIHBvb2wsIHJlc29sdmVyKSB7CiAgICAgIHZhciBoZWFwID0gbmV3IEhlYXAocmF3SGVhcCk7CiAgICAgIHZhciBjb25zdGFudHMgPSBuZXcgUnVudGltZUNvbnN0YW50cyhyZXNvbHZlciwgcG9vbCk7CiAgICAgIHJldHVybiBuZXcgUnVudGltZVByb2dyYW0oY29uc3RhbnRzLCBoZWFwKTsKICAgIH07CgogICAgdmFyIF9wcm90bzcgPSBSdW50aW1lUHJvZ3JhbS5wcm90b3R5cGU7CgogICAgX3Byb3RvNy5vcGNvZGUgPSBmdW5jdGlvbiBvcGNvZGUob2Zmc2V0KSB7CiAgICAgIHRoaXMuX29wY29kZS5vZmZzZXQgPSBvZmZzZXQ7CiAgICAgIHJldHVybiB0aGlzLl9vcGNvZGU7CiAgICB9OwoKICAgIHJldHVybiBSdW50aW1lUHJvZ3JhbTsKICB9KCk7CgogIF9leHBvcnRzLlJ1bnRpbWVQcm9ncmFtID0gUnVudGltZVByb2dyYW07CgogIHZhciBQcm9ncmFtID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Xcml0ZU9ubHlQcm9ncmFtKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUHJvZ3JhbSwgX1dyaXRlT25seVByb2dyYW0pOwoKICAgIGZ1bmN0aW9uIFByb2dyYW0oKSB7CiAgICAgIHJldHVybiBfV3JpdGVPbmx5UHJvZ3JhbS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgcmV0dXJuIFByb2dyYW07CiAgfShXcml0ZU9ubHlQcm9ncmFtKTsKCiAgX2V4cG9ydHMuUHJvZ3JhbSA9IFByb2dyYW07CgogIGZ1bmN0aW9uIHNsaWNlKGFyciwgc3RhcnQsIGVuZCkgewogICAgaWYgKGFyci5zbGljZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBhcnIuc2xpY2Uoc3RhcnQsIGVuZCk7CiAgICB9CgogICAgdmFyIHJldCA9IG5ldyBVaW50MzJBcnJheShlbmQpOwoKICAgIGZvciAoOyBzdGFydCA8IGVuZDsgc3RhcnQrKykgewogICAgICByZXRbc3RhcnRdID0gYXJyW3N0YXJ0XTsKICAgIH0KCiAgICByZXR1cm4gcmV0OwogIH0KfSk7CmRlZmluZSgiQGdsaW1tZXIvcmVmZXJlbmNlIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIiwgIkBnbGltbWVyL3V0aWwiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCwgX3V0aWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLm1hcCA9IG1hcDsKICBfZXhwb3J0cy5pc01vZGlmaWVkID0gaXNNb2RpZmllZDsKICBfZXhwb3J0cy5idW1wID0gYnVtcDsKICBfZXhwb3J0cy52YWx1ZSA9IF92YWx1ZTI7CiAgX2V4cG9ydHMudmFsaWRhdGUgPSB2YWxpZGF0ZTsKICBfZXhwb3J0cy5jcmVhdGVUYWcgPSBjcmVhdGVUYWc7CiAgX2V4cG9ydHMuY3JlYXRlVXBkYXRhYmxlVGFnID0gY3JlYXRlVXBkYXRhYmxlVGFnOwogIF9leHBvcnRzLmlzQ29uc3QgPSBpc0NvbnN0OwogIF9leHBvcnRzLmlzQ29uc3RUYWcgPSBpc0NvbnN0VGFnOwogIF9leHBvcnRzLmNvbWJpbmVUYWdnZWQgPSBjb21iaW5lVGFnZ2VkOwogIF9leHBvcnRzLmNvbWJpbmVTbGljZSA9IGNvbWJpbmVTbGljZTsKICBfZXhwb3J0cy5jb21iaW5lID0gY29tYmluZTsKICBfZXhwb3J0cy5DVVJSRU5UX1RBRyA9IF9leHBvcnRzLlZPTEFUSUxFX1RBRyA9IF9leHBvcnRzLkNPTlNUQU5UX1RBRyA9IF9leHBvcnRzLnVwZGF0ZSA9IF9leHBvcnRzLmRpcnR5ID0gX2V4cG9ydHMuTW9ub21vcnBoaWNUYWdJbXBsID0gX2V4cG9ydHMuQUxMT1dfQ1lDTEVTID0gX2V4cG9ydHMuQ09NUFVURSA9IF9leHBvcnRzLlZPTEFUSUxFID0gX2V4cG9ydHMuSU5JVElBTCA9IF9leHBvcnRzLkNPTlNUQU5UID0gX2V4cG9ydHMuSXRlcmF0b3JTeW5jaHJvbml6ZXIgPSBfZXhwb3J0cy5SZWZlcmVuY2VJdGVyYXRvciA9IF9leHBvcnRzLkl0ZXJhdGlvbkFydGlmYWN0cyA9IF9leHBvcnRzLkxpc3RJdGVtID0gX2V4cG9ydHMuQ29uc3RSZWZlcmVuY2UgPSBfZXhwb3J0cy5SZWZlcmVuY2VDYWNoZSA9IF9leHBvcnRzLkNhY2hlZFJlZmVyZW5jZSA9IHZvaWQgMDsKICB2YXIgc3ltYm9sID0gdHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgPyBTeW1ib2wgOiBmdW5jdGlvbiAoa2V5KSB7CiAgICByZXR1cm4gIl9fIiArIGtleSArIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIERhdGUubm93KCkpICsgIl9fIjsKICB9OwogIHZhciBDT05TVEFOVCA9IDA7CiAgX2V4cG9ydHMuQ09OU1RBTlQgPSBDT05TVEFOVDsKICB2YXIgSU5JVElBTCA9IDE7CiAgX2V4cG9ydHMuSU5JVElBTCA9IElOSVRJQUw7CiAgdmFyIFZPTEFUSUxFID0gOTAwNzE5OTI1NDc0MDk5MTsgLy8gTUFYX0lOVAoKICBfZXhwb3J0cy5WT0xBVElMRSA9IFZPTEFUSUxFOwogIHZhciAkUkVWSVNJT04gPSBJTklUSUFMOwoKICBmdW5jdGlvbiBidW1wKCkgewogICAgJFJFVklTSU9OKys7CiAgfSAvLy8vLy8vLy8vCgoKICB2YXIgQ09NUFVURSA9IHN5bWJvbCgnVEFHX0NPTVBVVEUnKTsgLy8vLy8vLy8vLwoKICAvKioKICAgKiBgdmFsdWVgIHJlY2VpdmVzIGEgdGFnIGFuZCByZXR1cm5zIGFuIG9wYXF1ZSBSZXZpc2lvbiBiYXNlZCBvbiB0aGF0IHRhZy4gVGhpcwogICAqIHNuYXBzaG90IGNhbiB0aGVuIGxhdGVyIGJlIHBhc3NlZCB0byBgdmFsaWRhdGVgIHdpdGggdGhlIHNhbWUgdGFnIHRvCiAgICogZGV0ZXJtaW5lIGlmIHRoZSB0YWcgaGFzIGNoYW5nZWQgYXQgYWxsIHNpbmNlIHRoZSB0aW1lIHRoYXQgYHZhbHVlYCB3YXMKICAgKiBjYWxsZWQuCiAgICoKICAgKiBUaGUgY3VycmVudCBpbXBsZW1lbnRhdGlvbiByZXR1cm5zIHRoZSBnbG9iYWwgcmV2aXNpb24gY291bnQgZGlyZWN0bHkgZm9yCiAgICogcGVyZm9ybWFuY2UgcmVhc29ucy4gVGhpcyBpcyBhbiBpbXBsZW1lbnRhdGlvbiBkZXRhaWwsIGFuZCBzaG91bGQgbm90IGJlCiAgICogcmVsaWVkIG9uIGRpcmVjdGx5IGJ5IHVzZXJzIG9mIHRoZXNlIEFQSXMuIEluc3RlYWQsIFJldmlzaW9ucyBzaG91bGQgYmUKICAgKiB0cmVhdGVkIGFzIGlmIHRoZXkgYXJlIG9wYXF1ZS91bmtub3duLCBhbmQgc2hvdWxkIG9ubHkgYmUgaW50ZXJhY3RlZCB3aXRoIHZpYQogICAqIHRoZSBgdmFsdWVgL2B2YWxpZGF0ZWAgQVBJLgogICAqCiAgICogQHBhcmFtIHRhZwogICAqLwoKICBfZXhwb3J0cy5DT01QVVRFID0gQ09NUFVURTsKCiAgZnVuY3Rpb24gX3ZhbHVlMihfdGFnKSB7CiAgICByZXR1cm4gJFJFVklTSU9OOwogIH0KICAvKioKICAgKiBgdmFsaWRhdGVgIHJlY2VpdmVzIGEgdGFnIGFuZCBhIHNuYXBzaG90IGZyb20gYSBwcmV2aW91cyBjYWxsIHRvIGB2YWx1ZWAgd2l0aAogICAqIHRoZSBzYW1lIHRhZywgYW5kIGRldGVybWluZXMgaWYgdGhlIHRhZyBpcyBzdGlsbCB2YWxpZCBjb21wYXJlZCB0byB0aGUKICAgKiBzbmFwc2hvdC4gSWYgdGhlIHRhZydzIHN0YXRlIGhhcyBjaGFuZ2VkIGF0IGFsbCBzaW5jZSB0aGVuLCBgdmFsaWRhdGVgIHdpbGwKICAgKiByZXR1cm4gZmFsc2UsIG90aGVyd2lzZSBpdCB3aWxsIHJldHVybiB0cnVlLiBUaGlzIGlzIHVzZWQgdG8gZGV0ZXJtaW5lIGlmIGEKICAgKiBjYWxjdWxhdGlvbiByZWxhdGVkIHRvIHRoZSB0YWdzIHNob3VsZCBiZSByZXJ1bi4KICAgKgogICAqIEBwYXJhbSB0YWcKICAgKiBAcGFyYW0gc25hcHNob3QKICAgKi8KCgogIGZ1bmN0aW9uIHZhbGlkYXRlKHRhZywgc25hcHNob3QpIHsKICAgIHJldHVybiBzbmFwc2hvdCA+PSB0YWdbQ09NUFVURV0oKTsKICB9CgogIHZhciBUWVBFID0gc3ltYm9sKCdUQUdfVFlQRScpOwogIHZhciBBTExPV19DWUNMRVM7CiAgX2V4cG9ydHMuQUxMT1dfQ1lDTEVTID0gQUxMT1dfQ1lDTEVTOwoKICB2YXIgTW9ub21vcnBoaWNUYWdJbXBsID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gTW9ub21vcnBoaWNUYWdJbXBsKHR5cGUpIHsKICAgICAgdGhpcy5yZXZpc2lvbiA9IElOSVRJQUw7CiAgICAgIHRoaXMubGFzdENoZWNrZWQgPSBJTklUSUFMOwogICAgICB0aGlzLmxhc3RWYWx1ZSA9IElOSVRJQUw7CiAgICAgIHRoaXMuaXNVcGRhdGluZyA9IGZhbHNlOwogICAgICB0aGlzLnN1YnRhZyA9IG51bGw7CiAgICAgIHRoaXMuc3VidGFncyA9IG51bGw7CiAgICAgIHRoaXNbVFlQRV0gPSB0eXBlOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBNb25vbW9ycGhpY1RhZ0ltcGwucHJvdG90eXBlOwoKICAgIF9wcm90b1tDT01QVVRFXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGxhc3RDaGVja2VkID0gdGhpcy5sYXN0Q2hlY2tlZDsKCiAgICAgIGlmIChsYXN0Q2hlY2tlZCAhPT0gJFJFVklTSU9OKSB7CiAgICAgICAgdGhpcy5pc1VwZGF0aW5nID0gdHJ1ZTsKICAgICAgICB0aGlzLmxhc3RDaGVja2VkID0gJFJFVklTSU9OOwoKICAgICAgICB0cnkgewogICAgICAgICAgdmFyIHN1YnRhZ3MgPSB0aGlzLnN1YnRhZ3MsCiAgICAgICAgICAgICAgc3VidGFnID0gdGhpcy5zdWJ0YWcsCiAgICAgICAgICAgICAgcmV2aXNpb24gPSB0aGlzLnJldmlzaW9uOwoKICAgICAgICAgIGlmIChzdWJ0YWcgIT09IG51bGwpIHsKICAgICAgICAgICAgcmV2aXNpb24gPSBNYXRoLm1heChyZXZpc2lvbiwgc3VidGFnW0NPTVBVVEVdKCkpOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChzdWJ0YWdzICE9PSBudWxsKSB7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3VidGFncy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgIHZhciBfdmFsdWUgPSBzdWJ0YWdzW2ldW0NPTVBVVEVdKCk7CgogICAgICAgICAgICAgIHJldmlzaW9uID0gTWF0aC5tYXgoX3ZhbHVlLCByZXZpc2lvbik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICB0aGlzLmxhc3RWYWx1ZSA9IHJldmlzaW9uOwogICAgICAgIH0gZmluYWxseSB7CiAgICAgICAgICB0aGlzLmlzVXBkYXRpbmcgPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmlzVXBkYXRpbmcgPT09IHRydWUpIHsKICAgICAgICB0aGlzLmxhc3RDaGVja2VkID0gKyskUkVWSVNJT047CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLmxhc3RWYWx1ZTsKICAgIH07CgogICAgTW9ub21vcnBoaWNUYWdJbXBsLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZShfdGFnLCBzdWJ0YWcpIHsKICAgICAgLy8gVE9ETzogVFMgMy43IHNob3VsZCBhbGxvdyB1cyB0byBkbyB0aGlzIHZpYSBhc3NlcnRpb24KICAgICAgdmFyIHRhZyA9IF90YWc7CgogICAgICBpZiAoc3VidGFnID09PSBDT05TVEFOVF9UQUcpIHsKICAgICAgICB0YWcuc3VidGFnID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0YWcuc3VidGFnID0gc3VidGFnOyAvLyBzdWJ0YWcgY291bGQgYmUgYW5vdGhlciB0eXBlIG9mIHRhZywgZS5nLiBDVVJSRU5UX1RBRyBvciBWT0xBVElMRV9UQUcuCiAgICAgICAgLy8gSWYgc28sIGxhc3RDaGVja2VkL2xhc3RWYWx1ZSB3aWxsIGJlIHVuZGVmaW5lZCwgcmVzdWx0IGluIHRoZXNlIGJlaW5nCiAgICAgICAgLy8gTmFOLiBUaGlzIGlzIGZpbmUsIGl0IHdpbGwgZm9yY2UgdGhlIHN5c3RlbSB0byByZWNvbXB1dGUuCgogICAgICAgIHRhZy5sYXN0Q2hlY2tlZCA9IE1hdGgubWluKHRhZy5sYXN0Q2hlY2tlZCwgc3VidGFnLmxhc3RDaGVja2VkKTsKICAgICAgICB0YWcubGFzdFZhbHVlID0gTWF0aC5tYXgodGFnLmxhc3RWYWx1ZSwgc3VidGFnLmxhc3RWYWx1ZSk7CiAgICAgIH0KICAgIH07CgogICAgTW9ub21vcnBoaWNUYWdJbXBsLmRpcnR5ID0gZnVuY3Rpb24gZGlydHkodGFnKSB7CiAgICAgIHRhZy5yZXZpc2lvbiA9ICsrJFJFVklTSU9OOwogICAgfTsKCiAgICByZXR1cm4gTW9ub21vcnBoaWNUYWdJbXBsOwogIH0oKTsKCiAgX2V4cG9ydHMuTW9ub21vcnBoaWNUYWdJbXBsID0gTW9ub21vcnBoaWNUYWdJbXBsOwogIHZhciBkaXJ0eSA9IE1vbm9tb3JwaGljVGFnSW1wbC5kaXJ0eTsKICBfZXhwb3J0cy5kaXJ0eSA9IGRpcnR5OwogIHZhciB1cGRhdGUgPSBNb25vbW9ycGhpY1RhZ0ltcGwudXBkYXRlOyAvLy8vLy8vLy8vCgogIF9leHBvcnRzLnVwZGF0ZSA9IHVwZGF0ZTsKCiAgZnVuY3Rpb24gY3JlYXRlVGFnKCkgewogICAgcmV0dXJuIG5ldyBNb25vbW9ycGhpY1RhZ0ltcGwoMAogICAgLyogRGlydHlhYmxlICovCiAgICApOwogIH0KCiAgZnVuY3Rpb24gY3JlYXRlVXBkYXRhYmxlVGFnKCkgewogICAgcmV0dXJuIG5ldyBNb25vbW9ycGhpY1RhZ0ltcGwoMQogICAgLyogVXBkYXRhYmxlICovCiAgICApOwogIH0gLy8vLy8vLy8vLwoKCiAgdmFyIENPTlNUQU5UX1RBRyA9IG5ldyBNb25vbW9ycGhpY1RhZ0ltcGwoMwogIC8qIENvbnN0YW50ICovCiAgKTsKICBfZXhwb3J0cy5DT05TVEFOVF9UQUcgPSBDT05TVEFOVF9UQUc7CgogIGZ1bmN0aW9uIGlzQ29uc3QoX3JlZikgewogICAgdmFyIHRhZyA9IF9yZWYudGFnOwogICAgcmV0dXJuIHRhZyA9PT0gQ09OU1RBTlRfVEFHOwogIH0KCiAgZnVuY3Rpb24gaXNDb25zdFRhZyh0YWcpIHsKICAgIHJldHVybiB0YWcgPT09IENPTlNUQU5UX1RBRzsKICB9IC8vLy8vLy8vLy8KCgogIHZhciBWb2xhdGlsZVRhZyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFZvbGF0aWxlVGFnKCkge30KCiAgICB2YXIgX3Byb3RvMiA9IFZvbGF0aWxlVGFnLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yW0NPTVBVVEVdID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gVk9MQVRJTEU7CiAgICB9OwoKICAgIHJldHVybiBWb2xhdGlsZVRhZzsKICB9KCk7CgogIHZhciBWT0xBVElMRV9UQUcgPSBuZXcgVm9sYXRpbGVUYWcoKTsgLy8vLy8vLy8vLwoKICBfZXhwb3J0cy5WT0xBVElMRV9UQUcgPSBWT0xBVElMRV9UQUc7CgogIHZhciBDdXJyZW50VGFnID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ3VycmVudFRhZygpIHt9CgogICAgdmFyIF9wcm90bzMgPSBDdXJyZW50VGFnLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zW0NPTVBVVEVdID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gJFJFVklTSU9OOwogICAgfTsKCiAgICByZXR1cm4gQ3VycmVudFRhZzsKICB9KCk7CgogIHZhciBDVVJSRU5UX1RBRyA9IG5ldyBDdXJyZW50VGFnKCk7IC8vLy8vLy8vLy8KCiAgX2V4cG9ydHMuQ1VSUkVOVF9UQUcgPSBDVVJSRU5UX1RBRzsKCiAgZnVuY3Rpb24gY29tYmluZVRhZ2dlZCh0YWdnZWQpIHsKICAgIHZhciBvcHRpbWl6ZWQgPSBbXTsKCiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRhZ2dlZC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgdmFyIHRhZyA9IHRhZ2dlZFtpXS50YWc7CiAgICAgIGlmICh0YWcgPT09IENPTlNUQU5UX1RBRykgY29udGludWU7CiAgICAgIG9wdGltaXplZC5wdXNoKHRhZyk7CiAgICB9CgogICAgcmV0dXJuIF9jb21iaW5lKG9wdGltaXplZCk7CiAgfQoKICBmdW5jdGlvbiBjb21iaW5lU2xpY2Uoc2xpY2UpIHsKICAgIHZhciBvcHRpbWl6ZWQgPSBbXTsKICAgIHZhciBub2RlID0gc2xpY2UuaGVhZCgpOwoKICAgIHdoaWxlIChub2RlICE9PSBudWxsKSB7CiAgICAgIHZhciB0YWcgPSBub2RlLnRhZzsKICAgICAgaWYgKHRhZyAhPT0gQ09OU1RBTlRfVEFHKSBvcHRpbWl6ZWQucHVzaCh0YWcpOwogICAgICBub2RlID0gc2xpY2UubmV4dE5vZGUobm9kZSk7CiAgICB9CgogICAgcmV0dXJuIF9jb21iaW5lKG9wdGltaXplZCk7CiAgfQoKICBmdW5jdGlvbiBjb21iaW5lKHRhZ3MpIHsKICAgIHZhciBvcHRpbWl6ZWQgPSBbXTsKCiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRhZ3MubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgIHZhciB0YWcgPSB0YWdzW2ldOwogICAgICBpZiAodGFnID09PSBDT05TVEFOVF9UQUcpIGNvbnRpbnVlOwogICAgICBvcHRpbWl6ZWQucHVzaCh0YWcpOwogICAgfQoKICAgIHJldHVybiBfY29tYmluZShvcHRpbWl6ZWQpOwogIH0KCiAgZnVuY3Rpb24gX2NvbWJpbmUodGFncykgewogICAgc3dpdGNoICh0YWdzLmxlbmd0aCkgewogICAgICBjYXNlIDA6CiAgICAgICAgcmV0dXJuIENPTlNUQU5UX1RBRzsKCiAgICAgIGNhc2UgMToKICAgICAgICByZXR1cm4gdGFnc1swXTsKCiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdmFyIHRhZyA9IG5ldyBNb25vbW9ycGhpY1RhZ0ltcGwoMgogICAgICAgIC8qIENvbWJpbmF0b3IgKi8KICAgICAgICApOwogICAgICAgIHRhZy5zdWJ0YWdzID0gdGFnczsKICAgICAgICByZXR1cm4gdGFnOwogICAgfQogIH0KCiAgdmFyIENhY2hlZFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENhY2hlZFJlZmVyZW5jZSgpIHsKICAgICAgdGhpcy5sYXN0UmV2aXNpb24gPSBudWxsOwogICAgICB0aGlzLmxhc3RWYWx1ZSA9IG51bGw7CiAgICB9CgogICAgdmFyIF9wcm90bzQgPSBDYWNoZWRSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzQudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgdmFyIHRhZyA9IHRoaXMudGFnLAogICAgICAgICAgbGFzdFJldmlzaW9uID0gdGhpcy5sYXN0UmV2aXNpb24sCiAgICAgICAgICBsYXN0VmFsdWUgPSB0aGlzLmxhc3RWYWx1ZTsKCiAgICAgIGlmIChsYXN0UmV2aXNpb24gPT09IG51bGwgfHwgIXZhbGlkYXRlKHRhZywgbGFzdFJldmlzaW9uKSkgewogICAgICAgIGxhc3RWYWx1ZSA9IHRoaXMubGFzdFZhbHVlID0gdGhpcy5jb21wdXRlKCk7CiAgICAgICAgdGhpcy5sYXN0UmV2aXNpb24gPSBfdmFsdWUyKHRhZyk7CiAgICAgIH0KCiAgICAgIHJldHVybiBsYXN0VmFsdWU7CiAgICB9OwoKICAgIF9wcm90bzQuaW52YWxpZGF0ZSA9IGZ1bmN0aW9uIGludmFsaWRhdGUoKSB7CiAgICAgIHRoaXMubGFzdFJldmlzaW9uID0gbnVsbDsKICAgIH07CgogICAgcmV0dXJuIENhY2hlZFJlZmVyZW5jZTsKICB9KCk7CgogIF9leHBvcnRzLkNhY2hlZFJlZmVyZW5jZSA9IENhY2hlZFJlZmVyZW5jZTsKCiAgdmFyIE1hcHBlclJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ2FjaGVkUmVmZXJlbmNlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTWFwcGVyUmVmZXJlbmNlLCBfQ2FjaGVkUmVmZXJlbmNlKTsKCiAgICBmdW5jdGlvbiBNYXBwZXJSZWZlcmVuY2UocmVmZXJlbmNlLCBtYXBwZXIpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfQ2FjaGVkUmVmZXJlbmNlLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXMudGFnID0gcmVmZXJlbmNlLnRhZzsKICAgICAgX3RoaXMucmVmZXJlbmNlID0gcmVmZXJlbmNlOwogICAgICBfdGhpcy5tYXBwZXIgPSBtYXBwZXI7CiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNSA9IE1hcHBlclJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNS5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgdmFyIHJlZmVyZW5jZSA9IHRoaXMucmVmZXJlbmNlLAogICAgICAgICAgbWFwcGVyID0gdGhpcy5tYXBwZXI7CiAgICAgIHJldHVybiBtYXBwZXIocmVmZXJlbmNlLnZhbHVlKCkpOwogICAgfTsKCiAgICByZXR1cm4gTWFwcGVyUmVmZXJlbmNlOwogIH0oQ2FjaGVkUmVmZXJlbmNlKTsKCiAgZnVuY3Rpb24gbWFwKHJlZmVyZW5jZSwgbWFwcGVyKSB7CiAgICByZXR1cm4gbmV3IE1hcHBlclJlZmVyZW5jZShyZWZlcmVuY2UsIG1hcHBlcik7CiAgfSAvLy8vLy8vLy8vCgoKICB2YXIgUmVmZXJlbmNlQ2FjaGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBSZWZlcmVuY2VDYWNoZShyZWZlcmVuY2UpIHsKICAgICAgdGhpcy5sYXN0VmFsdWUgPSBudWxsOwogICAgICB0aGlzLmxhc3RSZXZpc2lvbiA9IG51bGw7CiAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSBmYWxzZTsKICAgICAgdGhpcy50YWcgPSByZWZlcmVuY2UudGFnOwogICAgICB0aGlzLnJlZmVyZW5jZSA9IHJlZmVyZW5jZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNiA9IFJlZmVyZW5jZUNhY2hlLnByb3RvdHlwZTsKCiAgICBfcHJvdG82LnBlZWsgPSBmdW5jdGlvbiBwZWVrKCkgewogICAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZWQpIHsKICAgICAgICByZXR1cm4gdGhpcy5pbml0aWFsaXplKCk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLmxhc3RWYWx1ZTsKICAgIH07CgogICAgX3Byb3RvNi5yZXZhbGlkYXRlID0gZnVuY3Rpb24gcmV2YWxpZGF0ZSgpIHsKICAgICAgaWYgKCF0aGlzLmluaXRpYWxpemVkKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW5pdGlhbGl6ZSgpOwogICAgICB9CgogICAgICB2YXIgcmVmZXJlbmNlID0gdGhpcy5yZWZlcmVuY2UsCiAgICAgICAgICBsYXN0UmV2aXNpb24gPSB0aGlzLmxhc3RSZXZpc2lvbjsKICAgICAgdmFyIHRhZyA9IHJlZmVyZW5jZS50YWc7CiAgICAgIGlmICh2YWxpZGF0ZSh0YWcsIGxhc3RSZXZpc2lvbikpIHJldHVybiBOT1RfTU9ESUZJRUQ7CiAgICAgIHRoaXMubGFzdFJldmlzaW9uID0gX3ZhbHVlMih0YWcpOwogICAgICB2YXIgbGFzdFZhbHVlID0gdGhpcy5sYXN0VmFsdWU7CiAgICAgIHZhciBjdXJyZW50VmFsdWUgPSByZWZlcmVuY2UudmFsdWUoKTsKICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA9PT0gbGFzdFZhbHVlKSByZXR1cm4gTk9UX01PRElGSUVEOwogICAgICB0aGlzLmxhc3RWYWx1ZSA9IGN1cnJlbnRWYWx1ZTsKICAgICAgcmV0dXJuIGN1cnJlbnRWYWx1ZTsKICAgIH07CgogICAgX3Byb3RvNi5pbml0aWFsaXplID0gZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHsKICAgICAgdmFyIHJlZmVyZW5jZSA9IHRoaXMucmVmZXJlbmNlOwogICAgICB2YXIgY3VycmVudFZhbHVlID0gdGhpcy5sYXN0VmFsdWUgPSByZWZlcmVuY2UudmFsdWUoKTsKICAgICAgdGhpcy5sYXN0UmV2aXNpb24gPSBfdmFsdWUyKHJlZmVyZW5jZS50YWcpOwogICAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTsKICAgICAgcmV0dXJuIGN1cnJlbnRWYWx1ZTsKICAgIH07CgogICAgcmV0dXJuIFJlZmVyZW5jZUNhY2hlOwogIH0oKTsKCiAgX2V4cG9ydHMuUmVmZXJlbmNlQ2FjaGUgPSBSZWZlcmVuY2VDYWNoZTsKICB2YXIgTk9UX01PRElGSUVEID0gJ2FkYjNiNzhlLTNkMjItNGU0Yi04NzdhLTYzMTdjMmM1YzE0NSc7CgogIGZ1bmN0aW9uIGlzTW9kaWZpZWQodmFsdWUkJDEpIHsKICAgIHJldHVybiB2YWx1ZSQkMSAhPT0gTk9UX01PRElGSUVEOwogIH0KCiAgdmFyIENvbnN0UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ29uc3RSZWZlcmVuY2UoaW5uZXIpIHsKICAgICAgdGhpcy5pbm5lciA9IGlubmVyOwogICAgICB0aGlzLnRhZyA9IENPTlNUQU5UX1RBRzsKICAgIH0KCiAgICB2YXIgX3Byb3RvNyA9IENvbnN0UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG83LnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHJldHVybiB0aGlzLmlubmVyOwogICAgfTsKCiAgICByZXR1cm4gQ29uc3RSZWZlcmVuY2U7CiAgfSgpOwoKICBfZXhwb3J0cy5Db25zdFJlZmVyZW5jZSA9IENvbnN0UmVmZXJlbmNlOwoKICB2YXIgTGlzdEl0ZW0gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0xpc3ROb2RlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTGlzdEl0ZW0sIF9MaXN0Tm9kZSk7CgogICAgZnVuY3Rpb24gTGlzdEl0ZW0oaXRlcmFibGUsIHJlc3VsdCkgewogICAgICB2YXIgX3RoaXMyOwoKICAgICAgX3RoaXMyID0gX0xpc3ROb2RlLmNhbGwodGhpcywgaXRlcmFibGUudmFsdWVSZWZlcmVuY2VGb3IocmVzdWx0KSkgfHwgdGhpczsKICAgICAgX3RoaXMyLnJldGFpbmVkID0gZmFsc2U7CiAgICAgIF90aGlzMi5zZWVuID0gZmFsc2U7CiAgICAgIF90aGlzMi5rZXkgPSByZXN1bHQua2V5OwogICAgICBfdGhpczIuaXRlcmFibGUgPSBpdGVyYWJsZTsKICAgICAgX3RoaXMyLm1lbW8gPSBpdGVyYWJsZS5tZW1vUmVmZXJlbmNlRm9yKHJlc3VsdCk7CiAgICAgIHJldHVybiBfdGhpczI7CiAgICB9CgogICAgdmFyIF9wcm90bzggPSBMaXN0SXRlbS5wcm90b3R5cGU7CgogICAgX3Byb3RvOC51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoaXRlbSkgewogICAgICB0aGlzLnJldGFpbmVkID0gdHJ1ZTsKICAgICAgdGhpcy5pdGVyYWJsZS51cGRhdGVWYWx1ZVJlZmVyZW5jZSh0aGlzLnZhbHVlLCBpdGVtKTsKICAgICAgdGhpcy5pdGVyYWJsZS51cGRhdGVNZW1vUmVmZXJlbmNlKHRoaXMubWVtbywgaXRlbSk7CiAgICB9OwoKICAgIF9wcm90bzguc2hvdWxkUmVtb3ZlID0gZnVuY3Rpb24gc2hvdWxkUmVtb3ZlKCkgewogICAgICByZXR1cm4gIXRoaXMucmV0YWluZWQ7CiAgICB9OwoKICAgIF9wcm90bzgucmVzZXQgPSBmdW5jdGlvbiByZXNldCgpIHsKICAgICAgdGhpcy5yZXRhaW5lZCA9IGZhbHNlOwogICAgICB0aGlzLnNlZW4gPSBmYWxzZTsKICAgIH07CgogICAgcmV0dXJuIExpc3RJdGVtOwogIH0oX3V0aWwuTGlzdE5vZGUpOwoKICBfZXhwb3J0cy5MaXN0SXRlbSA9IExpc3RJdGVtOwoKICB2YXIgSXRlcmF0aW9uQXJ0aWZhY3RzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSXRlcmF0aW9uQXJ0aWZhY3RzKGl0ZXJhYmxlKSB7CiAgICAgIHRoaXMuaXRlcmF0b3IgPSBudWxsOwogICAgICB0aGlzLm1hcCA9ICgwLCBfdXRpbC5kaWN0KSgpOwogICAgICB0aGlzLmxpc3QgPSBuZXcgX3V0aWwuTGlua2VkTGlzdCgpOwogICAgICB0aGlzLnRhZyA9IGl0ZXJhYmxlLnRhZzsKICAgICAgdGhpcy5pdGVyYWJsZSA9IGl0ZXJhYmxlOwogICAgfQoKICAgIHZhciBfcHJvdG85ID0gSXRlcmF0aW9uQXJ0aWZhY3RzLnByb3RvdHlwZTsKCiAgICBfcHJvdG85LmlzRW1wdHkgPSBmdW5jdGlvbiBpc0VtcHR5KCkgewogICAgICB2YXIgaXRlcmF0b3IgPSB0aGlzLml0ZXJhdG9yID0gdGhpcy5pdGVyYWJsZS5pdGVyYXRlKCk7CiAgICAgIHJldHVybiBpdGVyYXRvci5pc0VtcHR5KCk7CiAgICB9OwoKICAgIF9wcm90bzkuaXRlcmF0ZSA9IGZ1bmN0aW9uIGl0ZXJhdGUoKSB7CiAgICAgIHZhciBpdGVyYXRvcjsKCiAgICAgIGlmICh0aGlzLml0ZXJhdG9yID09PSBudWxsKSB7CiAgICAgICAgaXRlcmF0b3IgPSB0aGlzLml0ZXJhYmxlLml0ZXJhdGUoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpdGVyYXRvciA9IHRoaXMuaXRlcmF0b3I7CiAgICAgIH0KCiAgICAgIHRoaXMuaXRlcmF0b3IgPSBudWxsOwogICAgICByZXR1cm4gaXRlcmF0b3I7CiAgICB9OwoKICAgIF9wcm90bzkuaGFzID0gZnVuY3Rpb24gaGFzKGtleSkgewogICAgICByZXR1cm4gISF0aGlzLm1hcFtrZXldOwogICAgfTsKCiAgICBfcHJvdG85LmdldCA9IGZ1bmN0aW9uIGdldChrZXkpIHsKICAgICAgcmV0dXJuIHRoaXMubWFwW2tleV07CiAgICB9OwoKICAgIF9wcm90bzkud2FzU2VlbiA9IGZ1bmN0aW9uIHdhc1NlZW4oa2V5KSB7CiAgICAgIHZhciBub2RlID0gdGhpcy5tYXBba2V5XTsKICAgICAgcmV0dXJuIG5vZGUgIT09IHVuZGVmaW5lZCAmJiBub2RlLnNlZW47CiAgICB9OwoKICAgIF9wcm90bzkuYXBwZW5kID0gZnVuY3Rpb24gYXBwZW5kKGl0ZW0pIHsKICAgICAgdmFyIG1hcCA9IHRoaXMubWFwLAogICAgICAgICAgbGlzdCA9IHRoaXMubGlzdCwKICAgICAgICAgIGl0ZXJhYmxlID0gdGhpcy5pdGVyYWJsZTsKICAgICAgdmFyIG5vZGUgPSBtYXBbaXRlbS5rZXldID0gbmV3IExpc3RJdGVtKGl0ZXJhYmxlLCBpdGVtKTsKICAgICAgbGlzdC5hcHBlbmQobm9kZSk7CiAgICAgIHJldHVybiBub2RlOwogICAgfTsKCiAgICBfcHJvdG85Lmluc2VydEJlZm9yZSA9IGZ1bmN0aW9uIGluc2VydEJlZm9yZShpdGVtLCByZWZlcmVuY2UpIHsKICAgICAgdmFyIG1hcCA9IHRoaXMubWFwLAogICAgICAgICAgbGlzdCA9IHRoaXMubGlzdCwKICAgICAgICAgIGl0ZXJhYmxlID0gdGhpcy5pdGVyYWJsZTsKICAgICAgdmFyIG5vZGUgPSBtYXBbaXRlbS5rZXldID0gbmV3IExpc3RJdGVtKGl0ZXJhYmxlLCBpdGVtKTsKICAgICAgbm9kZS5yZXRhaW5lZCA9IHRydWU7CiAgICAgIGxpc3QuaW5zZXJ0QmVmb3JlKG5vZGUsIHJlZmVyZW5jZSk7CiAgICAgIHJldHVybiBub2RlOwogICAgfTsKCiAgICBfcHJvdG85Lm1vdmUgPSBmdW5jdGlvbiBtb3ZlKGl0ZW0sIHJlZmVyZW5jZSkgewogICAgICB2YXIgbGlzdCA9IHRoaXMubGlzdDsKICAgICAgaXRlbS5yZXRhaW5lZCA9IHRydWU7CiAgICAgIGxpc3QucmVtb3ZlKGl0ZW0pOwogICAgICBsaXN0Lmluc2VydEJlZm9yZShpdGVtLCByZWZlcmVuY2UpOwogICAgfTsKCiAgICBfcHJvdG85LnJlbW92ZSA9IGZ1bmN0aW9uIHJlbW92ZShpdGVtKSB7CiAgICAgIHZhciBsaXN0ID0gdGhpcy5saXN0OwogICAgICBsaXN0LnJlbW92ZShpdGVtKTsKICAgICAgZGVsZXRlIHRoaXMubWFwW2l0ZW0ua2V5XTsKICAgIH07CgogICAgX3Byb3RvOS5uZXh0Tm9kZSA9IGZ1bmN0aW9uIG5leHROb2RlKGl0ZW0pIHsKICAgICAgcmV0dXJuIHRoaXMubGlzdC5uZXh0Tm9kZShpdGVtKTsKICAgIH07CgogICAgX3Byb3RvOS5oZWFkID0gZnVuY3Rpb24gaGVhZCgpIHsKICAgICAgcmV0dXJuIHRoaXMubGlzdC5oZWFkKCk7CiAgICB9OwoKICAgIHJldHVybiBJdGVyYXRpb25BcnRpZmFjdHM7CiAgfSgpOwoKICBfZXhwb3J0cy5JdGVyYXRpb25BcnRpZmFjdHMgPSBJdGVyYXRpb25BcnRpZmFjdHM7CgogIHZhciBSZWZlcmVuY2VJdGVyYXRvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIC8vIGlmIGFueW9uZSBuZWVkcyB0byBjb25zdHJ1Y3QgdGhpcyBvYmplY3Qgd2l0aCBzb21ldGhpbmcgb3RoZXIgdGhhbgogICAgLy8gYW4gaXRlcmFibGUsIGxldCBAd3ljYXRzIGtub3cuCiAgICBmdW5jdGlvbiBSZWZlcmVuY2VJdGVyYXRvcihpdGVyYWJsZSkgewogICAgICB0aGlzLml0ZXJhdG9yID0gbnVsbDsKICAgICAgdmFyIGFydGlmYWN0cyA9IG5ldyBJdGVyYXRpb25BcnRpZmFjdHMoaXRlcmFibGUpOwogICAgICB0aGlzLmFydGlmYWN0cyA9IGFydGlmYWN0czsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTAgPSBSZWZlcmVuY2VJdGVyYXRvci5wcm90b3R5cGU7CgogICAgX3Byb3RvMTAubmV4dCA9IGZ1bmN0aW9uIG5leHQoKSB7CiAgICAgIHZhciBhcnRpZmFjdHMgPSB0aGlzLmFydGlmYWN0czsKICAgICAgdmFyIGl0ZXJhdG9yID0gdGhpcy5pdGVyYXRvciA9IHRoaXMuaXRlcmF0b3IgfHwgYXJ0aWZhY3RzLml0ZXJhdGUoKTsKICAgICAgdmFyIGl0ZW0gPSBpdGVyYXRvci5uZXh0KCk7CiAgICAgIGlmIChpdGVtID09PSBudWxsKSByZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuIGFydGlmYWN0cy5hcHBlbmQoaXRlbSk7CiAgICB9OwoKICAgIHJldHVybiBSZWZlcmVuY2VJdGVyYXRvcjsKICB9KCk7CgogIF9leHBvcnRzLlJlZmVyZW5jZUl0ZXJhdG9yID0gUmVmZXJlbmNlSXRlcmF0b3I7CiAgdmFyIFBoYXNlOwoKICAoZnVuY3Rpb24gKFBoYXNlKSB7CiAgICBQaGFzZVtQaGFzZVsiQXBwZW5kIl0gPSAwXSA9ICJBcHBlbmQiOwogICAgUGhhc2VbUGhhc2VbIlBydW5lIl0gPSAxXSA9ICJQcnVuZSI7CiAgICBQaGFzZVtQaGFzZVsiRG9uZSJdID0gMl0gPSAiRG9uZSI7CiAgfSkoUGhhc2UgfHwgKFBoYXNlID0ge30pKTsKCiAgdmFyIEl0ZXJhdG9yU3luY2hyb25pemVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSXRlcmF0b3JTeW5jaHJvbml6ZXIoX3JlZjIpIHsKICAgICAgdmFyIHRhcmdldCA9IF9yZWYyLnRhcmdldCwKICAgICAgICAgIGFydGlmYWN0cyA9IF9yZWYyLmFydGlmYWN0czsKICAgICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7CiAgICAgIHRoaXMuYXJ0aWZhY3RzID0gYXJ0aWZhY3RzOwogICAgICB0aGlzLml0ZXJhdG9yID0gYXJ0aWZhY3RzLml0ZXJhdGUoKTsKICAgICAgdGhpcy5jdXJyZW50ID0gYXJ0aWZhY3RzLmhlYWQoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTEgPSBJdGVyYXRvclN5bmNocm9uaXplci5wcm90b3R5cGU7CgogICAgX3Byb3RvMTEuc3luYyA9IGZ1bmN0aW9uIHN5bmMoKSB7CiAgICAgIHZhciBwaGFzZSA9IFBoYXNlLkFwcGVuZDsKCiAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgc3dpdGNoIChwaGFzZSkgewogICAgICAgICAgY2FzZSBQaGFzZS5BcHBlbmQ6CiAgICAgICAgICAgIHBoYXNlID0gdGhpcy5uZXh0QXBwZW5kKCk7CiAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgIGNhc2UgUGhhc2UuUHJ1bmU6CiAgICAgICAgICAgIHBoYXNlID0gdGhpcy5uZXh0UHJ1bmUoKTsKICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgY2FzZSBQaGFzZS5Eb25lOgogICAgICAgICAgICB0aGlzLm5leHREb25lKCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTEuYWR2YW5jZVRvS2V5ID0gZnVuY3Rpb24gYWR2YW5jZVRvS2V5KGtleSkgewogICAgICB2YXIgY3VycmVudCA9IHRoaXMuY3VycmVudCwKICAgICAgICAgIGFydGlmYWN0cyA9IHRoaXMuYXJ0aWZhY3RzOwogICAgICB2YXIgc2VlayA9IGN1cnJlbnQ7CgogICAgICB3aGlsZSAoc2VlayAhPT0gbnVsbCAmJiBzZWVrLmtleSAhPT0ga2V5KSB7CiAgICAgICAgc2Vlay5zZWVuID0gdHJ1ZTsKICAgICAgICBzZWVrID0gYXJ0aWZhY3RzLm5leHROb2RlKHNlZWspOwogICAgICB9CgogICAgICBpZiAoc2VlayAhPT0gbnVsbCkgewogICAgICAgIHRoaXMuY3VycmVudCA9IGFydGlmYWN0cy5uZXh0Tm9kZShzZWVrKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8xMS5uZXh0QXBwZW5kID0gZnVuY3Rpb24gbmV4dEFwcGVuZCgpIHsKICAgICAgdmFyIGl0ZXJhdG9yID0gdGhpcy5pdGVyYXRvciwKICAgICAgICAgIGN1cnJlbnQgPSB0aGlzLmN1cnJlbnQsCiAgICAgICAgICBhcnRpZmFjdHMgPSB0aGlzLmFydGlmYWN0czsKICAgICAgdmFyIGl0ZW0gPSBpdGVyYXRvci5uZXh0KCk7CgogICAgICBpZiAoaXRlbSA9PT0gbnVsbCkgewogICAgICAgIHJldHVybiB0aGlzLnN0YXJ0UHJ1bmUoKTsKICAgICAgfQoKICAgICAgdmFyIGtleSA9IGl0ZW0ua2V5OwoKICAgICAgaWYgKGN1cnJlbnQgIT09IG51bGwgJiYgY3VycmVudC5rZXkgPT09IGtleSkgewogICAgICAgIHRoaXMubmV4dFJldGFpbihpdGVtKTsKICAgICAgfSBlbHNlIGlmIChhcnRpZmFjdHMuaGFzKGtleSkpIHsKICAgICAgICB0aGlzLm5leHRNb3ZlKGl0ZW0pOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMubmV4dEluc2VydChpdGVtKTsKICAgICAgfQoKICAgICAgcmV0dXJuIFBoYXNlLkFwcGVuZDsKICAgIH07CgogICAgX3Byb3RvMTEubmV4dFJldGFpbiA9IGZ1bmN0aW9uIG5leHRSZXRhaW4oaXRlbSkgewogICAgICB2YXIgYXJ0aWZhY3RzID0gdGhpcy5hcnRpZmFjdHMsCiAgICAgICAgICBjdXJyZW50ID0gdGhpcy5jdXJyZW50OwogICAgICBjdXJyZW50ID0gY3VycmVudDsKICAgICAgY3VycmVudC51cGRhdGUoaXRlbSk7CiAgICAgIHRoaXMuY3VycmVudCA9IGFydGlmYWN0cy5uZXh0Tm9kZShjdXJyZW50KTsKICAgICAgdGhpcy50YXJnZXQucmV0YWluKGl0ZW0ua2V5LCBjdXJyZW50LnZhbHVlLCBjdXJyZW50Lm1lbW8pOwogICAgfTsKCiAgICBfcHJvdG8xMS5uZXh0TW92ZSA9IGZ1bmN0aW9uIG5leHRNb3ZlKGl0ZW0pIHsKICAgICAgdmFyIGN1cnJlbnQgPSB0aGlzLmN1cnJlbnQsCiAgICAgICAgICBhcnRpZmFjdHMgPSB0aGlzLmFydGlmYWN0cywKICAgICAgICAgIHRhcmdldCA9IHRoaXMudGFyZ2V0OwogICAgICB2YXIga2V5ID0gaXRlbS5rZXk7CiAgICAgIHZhciBmb3VuZCA9IGFydGlmYWN0cy5nZXQoaXRlbS5rZXkpOwogICAgICBmb3VuZC51cGRhdGUoaXRlbSk7CgogICAgICBpZiAoYXJ0aWZhY3RzLndhc1NlZW4oaXRlbS5rZXkpKSB7CiAgICAgICAgYXJ0aWZhY3RzLm1vdmUoZm91bmQsIGN1cnJlbnQpOwogICAgICAgIHRhcmdldC5tb3ZlKGZvdW5kLmtleSwgZm91bmQudmFsdWUsIGZvdW5kLm1lbW8sIGN1cnJlbnQgPyBjdXJyZW50LmtleSA6IG51bGwpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuYWR2YW5jZVRvS2V5KGtleSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTEubmV4dEluc2VydCA9IGZ1bmN0aW9uIG5leHRJbnNlcnQoaXRlbSkgewogICAgICB2YXIgYXJ0aWZhY3RzID0gdGhpcy5hcnRpZmFjdHMsCiAgICAgICAgICB0YXJnZXQgPSB0aGlzLnRhcmdldCwKICAgICAgICAgIGN1cnJlbnQgPSB0aGlzLmN1cnJlbnQ7CiAgICAgIHZhciBub2RlID0gYXJ0aWZhY3RzLmluc2VydEJlZm9yZShpdGVtLCBjdXJyZW50KTsKICAgICAgdGFyZ2V0Lmluc2VydChub2RlLmtleSwgbm9kZS52YWx1ZSwgbm9kZS5tZW1vLCBjdXJyZW50ID8gY3VycmVudC5rZXkgOiBudWxsKTsKICAgIH07CgogICAgX3Byb3RvMTEuc3RhcnRQcnVuZSA9IGZ1bmN0aW9uIHN0YXJ0UHJ1bmUoKSB7CiAgICAgIHRoaXMuY3VycmVudCA9IHRoaXMuYXJ0aWZhY3RzLmhlYWQoKTsKICAgICAgcmV0dXJuIFBoYXNlLlBydW5lOwogICAgfTsKCiAgICBfcHJvdG8xMS5uZXh0UHJ1bmUgPSBmdW5jdGlvbiBuZXh0UHJ1bmUoKSB7CiAgICAgIHZhciBhcnRpZmFjdHMgPSB0aGlzLmFydGlmYWN0cywKICAgICAgICAgIHRhcmdldCA9IHRoaXMudGFyZ2V0LAogICAgICAgICAgY3VycmVudCA9IHRoaXMuY3VycmVudDsKCiAgICAgIGlmIChjdXJyZW50ID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIFBoYXNlLkRvbmU7CiAgICAgIH0KCiAgICAgIHZhciBub2RlID0gY3VycmVudDsKICAgICAgdGhpcy5jdXJyZW50ID0gYXJ0aWZhY3RzLm5leHROb2RlKG5vZGUpOwoKICAgICAgaWYgKG5vZGUuc2hvdWxkUmVtb3ZlKCkpIHsKICAgICAgICBhcnRpZmFjdHMucmVtb3ZlKG5vZGUpOwogICAgICAgIHRhcmdldC5kZWxldGUobm9kZS5rZXkpOwogICAgICB9IGVsc2UgewogICAgICAgIG5vZGUucmVzZXQoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIFBoYXNlLlBydW5lOwogICAgfTsKCiAgICBfcHJvdG8xMS5uZXh0RG9uZSA9IGZ1bmN0aW9uIG5leHREb25lKCkgewogICAgICB0aGlzLnRhcmdldC5kb25lKCk7CiAgICB9OwoKICAgIHJldHVybiBJdGVyYXRvclN5bmNocm9uaXplcjsKICB9KCk7CgogIF9leHBvcnRzLkl0ZXJhdG9yU3luY2hyb25pemVyID0gSXRlcmF0b3JTeW5jaHJvbml6ZXI7Cn0pOwpkZWZpbmUoIkBnbGltbWVyL3J1bnRpbWUiLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiLCAiQGdsaW1tZXIvdXRpbCIsICJAZ2xpbW1lci9yZWZlcmVuY2UiLCAiQGdsaW1tZXIvdm0iLCAiQGdsaW1tZXIvbG93LWxldmVsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2VtYmVyQmFiZWwsIF91dGlsLCBfcmVmZXJlbmNlMiwgX3ZtMiwgX2xvd0xldmVsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5yZW5kZXJNYWluID0gcmVuZGVyTWFpbjsKICBfZXhwb3J0cy5yZW5kZXJDb21wb25lbnQgPSByZW5kZXJDb21wb25lbnQ7CiAgX2V4cG9ydHMuc2V0RGVidWdnZXJDYWxsYmFjayA9IHNldERlYnVnZ2VyQ2FsbGJhY2s7CiAgX2V4cG9ydHMucmVzZXREZWJ1Z2dlckNhbGxiYWNrID0gcmVzZXREZWJ1Z2dlckNhbGxiYWNrOwogIF9leHBvcnRzLmdldER5bmFtaWNWYXIgPSBnZXREeW5hbWljVmFyOwogIF9leHBvcnRzLmlzQ3VycmllZENvbXBvbmVudERlZmluaXRpb24gPSBpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uOwogIF9leHBvcnRzLmN1cnJ5ID0gY3Vycnk7CiAgX2V4cG9ydHMuaXNXaGl0ZXNwYWNlID0gaXNXaGl0ZXNwYWNlOwogIF9leHBvcnRzLm5vcm1hbGl6ZVByb3BlcnR5ID0gbm9ybWFsaXplUHJvcGVydHk7CiAgX2V4cG9ydHMuY2xpZW50QnVpbGRlciA9IGNsaWVudEJ1aWxkZXI7CiAgX2V4cG9ydHMucmVoeWRyYXRpb25CdWlsZGVyID0gcmVoeWRyYXRpb25CdWlsZGVyOwogIF9leHBvcnRzLmlzU2VyaWFsaXphdGlvbkZpcnN0Tm9kZSA9IGlzU2VyaWFsaXphdGlvbkZpcnN0Tm9kZTsKICBfZXhwb3J0cy5jYXBhYmlsaXR5RmxhZ3NGcm9tID0gY2FwYWJpbGl0eUZsYWdzRnJvbTsKICBfZXhwb3J0cy5oYXNDYXBhYmlsaXR5ID0gaGFzQ2FwYWJpbGl0eTsKICBfZXhwb3J0cy5DdXJzb3IgPSBfZXhwb3J0cy5Db25jcmV0ZUJvdW5kcyA9IF9leHBvcnRzLlNFUklBTElaQVRJT05fRklSU1RfTk9ERV9TVFJJTkcgPSBfZXhwb3J0cy5SZWh5ZHJhdGVCdWlsZGVyID0gX2V4cG9ydHMuTmV3RWxlbWVudEJ1aWxkZXIgPSBfZXhwb3J0cy5ET01UcmVlQ29uc3RydWN0aW9uID0gX2V4cG9ydHMuSURPTUNoYW5nZXMgPSBfZXhwb3J0cy5TVkdfTkFNRVNQQUNFID0gX2V4cG9ydHMuRE9NQ2hhbmdlcyA9IF9leHBvcnRzLkN1cnJpZWRDb21wb25lbnREZWZpbml0aW9uID0gX2V4cG9ydHMuTUlOSU1BTF9DQVBBQklMSVRJRVMgPSBfZXhwb3J0cy5ERUZBVUxUX0NBUEFCSUxJVElFUyA9IF9leHBvcnRzLkRlZmF1bHRFbnZpcm9ubWVudCA9IF9leHBvcnRzLkVudmlyb25tZW50ID0gX2V4cG9ydHMuU2NvcGUgPSBfZXhwb3J0cy5FTVBUWV9BUkdTID0gX2V4cG9ydHMuRHluYW1pY0F0dHJpYnV0ZSA9IF9leHBvcnRzLlNpbXBsZUR5bmFtaWNBdHRyaWJ1dGUgPSBfZXhwb3J0cy5SZW5kZXJSZXN1bHQgPSBfZXhwb3J0cy5VcGRhdGluZ1ZNID0gX2V4cG9ydHMuTG93TGV2ZWxWTSA9IF9leHBvcnRzLkNvbmRpdGlvbmFsUmVmZXJlbmNlID0gX2V4cG9ydHMuUHJpbWl0aXZlUmVmZXJlbmNlID0gX2V4cG9ydHMuVU5ERUZJTkVEX1JFRkVSRU5DRSA9IF9leHBvcnRzLk5VTExfUkVGRVJFTkNFID0gdm9pZCAwOwoKICAvLyB0aGVzZSBpbXBvcnQgYmluZGluZ3Mgd2lsbCBiZSBzdHJpcHBlZCBmcm9tIGJ1aWxkCiAgdmFyIEFwcGVuZE9wY29kZXMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBBcHBlbmRPcGNvZGVzKCkgewogICAgICB0aGlzLmV2YWx1YXRlT3Bjb2RlID0gKDAsIF91dGlsLmZpbGxOdWxscykoOTgKICAgICAgLyogU2l6ZSAqLwogICAgICApLnNsaWNlKCk7CiAgICB9CgogICAgdmFyIF9wcm90byA9IEFwcGVuZE9wY29kZXMucHJvdG90eXBlOwoKICAgIF9wcm90by5hZGQgPSBmdW5jdGlvbiBhZGQobmFtZSwgZXZhbHVhdGUsIGtpbmQpIHsKICAgICAgaWYgKGtpbmQgPT09IHZvaWQgMCkgewogICAgICAgIGtpbmQgPSAnc3lzY2FsbCc7CiAgICAgIH0KCiAgICAgIHRoaXMuZXZhbHVhdGVPcGNvZGVbbmFtZV0gPSB7CiAgICAgICAgc3lzY2FsbDoga2luZCA9PT0gJ3N5c2NhbGwnLAogICAgICAgIGV2YWx1YXRlOiBldmFsdWF0ZQogICAgICB9OwogICAgfTsKCiAgICBfcHJvdG8uZGVidWdCZWZvcmUgPSBmdW5jdGlvbiBkZWJ1Z0JlZm9yZSh2bSwgb3Bjb2RlLCB0eXBlKSB7CiAgICAgIHZhciBzcDsKICAgICAgdmFyIHN0YXRlOwogICAgICByZXR1cm4gewogICAgICAgIHNwOiBzcCwKICAgICAgICBzdGF0ZTogc3RhdGUKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvLmRlYnVnQWZ0ZXIgPSBmdW5jdGlvbiBkZWJ1Z0FmdGVyKHZtLCBvcGNvZGUsIHR5cGUsIHByZSkgewogICAgICB2YXIgZXhwZWN0ZWRDaGFuZ2U7CiAgICAgIHZhciBzcCA9IHByZS5zcCwKICAgICAgICAgIHN0YXRlID0gcHJlLnN0YXRlOwogICAgICB2YXIgbWV0YWRhdGEgPSBudWxsOwoKICAgICAgaWYgKG1ldGFkYXRhICE9PSBudWxsKSB7CiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YS5zdGFja0NoYW5nZSA9PT0gJ251bWJlcicpIHsKICAgICAgICAgIGV4cGVjdGVkQ2hhbmdlID0gbWV0YWRhdGEuc3RhY2tDaGFuZ2U7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGV4cGVjdGVkQ2hhbmdlID0gbWV0YWRhdGEuc3RhY2tDaGFuZ2UoewogICAgICAgICAgICBvcGNvZGU6IG9wY29kZSwKICAgICAgICAgICAgY29uc3RhbnRzOiB2bS5jb25zdGFudHMsCiAgICAgICAgICAgIHN0YXRlOiBzdGF0ZQogICAgICAgICAgfSk7CiAgICAgICAgICBpZiAoaXNOYU4oZXhwZWN0ZWRDaGFuZ2UpKSB0aHJvdyAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKHZtLCBvcGNvZGUsIHR5cGUpIHsKICAgICAgdmFyIG9wZXJhdGlvbiA9IHRoaXMuZXZhbHVhdGVPcGNvZGVbdHlwZV07CgogICAgICBpZiAob3BlcmF0aW9uLnN5c2NhbGwpIHsKICAgICAgICBvcGVyYXRpb24uZXZhbHVhdGUodm0sIG9wY29kZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgb3BlcmF0aW9uLmV2YWx1YXRlKHZtLmlubmVyLCBvcGNvZGUpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBBcHBlbmRPcGNvZGVzOwogIH0oKTsKCiAgdmFyIEFQUEVORF9PUENPREVTID0gbmV3IEFwcGVuZE9wY29kZXMoKTsKCiAgdmFyIEFic3RyYWN0T3Bjb2RlID0gZnVuY3Rpb24gQWJzdHJhY3RPcGNvZGUoKSB7CiAgICAoMCwgX3V0aWwuaW5pdGlhbGl6ZUd1aWQpKHRoaXMpOwogIH07CgogIHZhciBVcGRhdGluZ09wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQWJzdHJhY3RPcGNvZGUpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShVcGRhdGluZ09wY29kZSwgX0Fic3RyYWN0T3Bjb2RlKTsKCiAgICBmdW5jdGlvbiBVcGRhdGluZ09wY29kZSgpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfQWJzdHJhY3RPcGNvZGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpcy5uZXh0ID0gbnVsbDsKICAgICAgX3RoaXMucHJldiA9IG51bGw7CiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KCiAgICByZXR1cm4gVXBkYXRpbmdPcGNvZGU7CiAgfShBYnN0cmFjdE9wY29kZSk7CgogIHZhciBQcmltaXRpdmVSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0NvbnN0UmVmZXJlbmNlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUHJpbWl0aXZlUmVmZXJlbmNlLCBfQ29uc3RSZWZlcmVuY2UpOwoKICAgIGZ1bmN0aW9uIFByaW1pdGl2ZVJlZmVyZW5jZSh2YWx1ZSQkMSkgewogICAgICByZXR1cm4gX0NvbnN0UmVmZXJlbmNlLmNhbGwodGhpcywgdmFsdWUkJDEpIHx8IHRoaXM7CiAgICB9CgogICAgUHJpbWl0aXZlUmVmZXJlbmNlLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSh2YWx1ZSQkMSkgewogICAgICBpZiAodmFsdWUkJDEgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBVTkRFRklORURfUkVGRVJFTkNFOwogICAgICB9IGVsc2UgaWYgKHZhbHVlJCQxID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIE5VTExfUkVGRVJFTkNFOwogICAgICB9IGVsc2UgaWYgKHZhbHVlJCQxID09PSB0cnVlKSB7CiAgICAgICAgcmV0dXJuIFRSVUVfUkVGRVJFTkNFOwogICAgICB9IGVsc2UgaWYgKHZhbHVlJCQxID09PSBmYWxzZSkgewogICAgICAgIHJldHVybiBGQUxTRV9SRUZFUkVOQ0U7CiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlJCQxID09PSAnbnVtYmVyJykgewogICAgICAgIHJldHVybiBuZXcgVmFsdWVSZWZlcmVuY2UodmFsdWUkJDEpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBuZXcgU3RyaW5nUmVmZXJlbmNlKHZhbHVlJCQxKTsKICAgICAgfQogICAgfTsKCiAgICB2YXIgX3Byb3RvMiA9IFByaW1pdGl2ZVJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5nZXQgPSBmdW5jdGlvbiBnZXQoX2tleSkgewogICAgICByZXR1cm4gVU5ERUZJTkVEX1JFRkVSRU5DRTsKICAgIH07CgogICAgcmV0dXJuIFByaW1pdGl2ZVJlZmVyZW5jZTsKICB9KF9yZWZlcmVuY2UyLkNvbnN0UmVmZXJlbmNlKTsKCiAgX2V4cG9ydHMuUHJpbWl0aXZlUmVmZXJlbmNlID0gUHJpbWl0aXZlUmVmZXJlbmNlOwoKICB2YXIgU3RyaW5nUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9QcmltaXRpdmVSZWZlcmVuY2UpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShTdHJpbmdSZWZlcmVuY2UsIF9QcmltaXRpdmVSZWZlcmVuY2UpOwoKICAgIGZ1bmN0aW9uIFN0cmluZ1JlZmVyZW5jZSgpIHsKICAgICAgdmFyIF90aGlzMjsKCiAgICAgIF90aGlzMiA9IF9QcmltaXRpdmVSZWZlcmVuY2UuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICBfdGhpczIubGVuZ3RoUmVmZXJlbmNlID0gbnVsbDsKICAgICAgcmV0dXJuIF90aGlzMjsKICAgIH0KCiAgICB2YXIgX3Byb3RvMyA9IFN0cmluZ1JlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMy5nZXQgPSBmdW5jdGlvbiBnZXQoa2V5KSB7CiAgICAgIGlmIChrZXkgPT09ICdsZW5ndGgnKSB7CiAgICAgICAgdmFyIGxlbmd0aFJlZmVyZW5jZSA9IHRoaXMubGVuZ3RoUmVmZXJlbmNlOwoKICAgICAgICBpZiAobGVuZ3RoUmVmZXJlbmNlID09PSBudWxsKSB7CiAgICAgICAgICBsZW5ndGhSZWZlcmVuY2UgPSB0aGlzLmxlbmd0aFJlZmVyZW5jZSA9IG5ldyBWYWx1ZVJlZmVyZW5jZSh0aGlzLmlubmVyLmxlbmd0aCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gbGVuZ3RoUmVmZXJlbmNlOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBfUHJpbWl0aXZlUmVmZXJlbmNlLnByb3RvdHlwZS5nZXQuY2FsbCh0aGlzLCBrZXkpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBTdHJpbmdSZWZlcmVuY2U7CiAgfShQcmltaXRpdmVSZWZlcmVuY2UpOwoKICB2YXIgVmFsdWVSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1ByaW1pdGl2ZVJlZmVyZW5jZTIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShWYWx1ZVJlZmVyZW5jZSwgX1ByaW1pdGl2ZVJlZmVyZW5jZTIpOwoKICAgIGZ1bmN0aW9uIFZhbHVlUmVmZXJlbmNlKHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiBfUHJpbWl0aXZlUmVmZXJlbmNlMi5jYWxsKHRoaXMsIHZhbHVlJCQxKSB8fCB0aGlzOwogICAgfQoKICAgIHJldHVybiBWYWx1ZVJlZmVyZW5jZTsKICB9KFByaW1pdGl2ZVJlZmVyZW5jZSk7CgogIHZhciBVTkRFRklORURfUkVGRVJFTkNFID0gbmV3IFZhbHVlUmVmZXJlbmNlKHVuZGVmaW5lZCk7CiAgX2V4cG9ydHMuVU5ERUZJTkVEX1JFRkVSRU5DRSA9IFVOREVGSU5FRF9SRUZFUkVOQ0U7CiAgdmFyIE5VTExfUkVGRVJFTkNFID0gbmV3IFZhbHVlUmVmZXJlbmNlKG51bGwpOwogIF9leHBvcnRzLk5VTExfUkVGRVJFTkNFID0gTlVMTF9SRUZFUkVOQ0U7CiAgdmFyIFRSVUVfUkVGRVJFTkNFID0gbmV3IFZhbHVlUmVmZXJlbmNlKHRydWUpOwogIHZhciBGQUxTRV9SRUZFUkVOQ0UgPSBuZXcgVmFsdWVSZWZlcmVuY2UoZmFsc2UpOwoKICB2YXIgQ29uZGl0aW9uYWxSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDb25kaXRpb25hbFJlZmVyZW5jZShpbm5lcikgewogICAgICB0aGlzLmlubmVyID0gaW5uZXI7CiAgICAgIHRoaXMudGFnID0gaW5uZXIudGFnOwogICAgfQoKICAgIHZhciBfcHJvdG80ID0gQ29uZGl0aW9uYWxSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzQudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgcmV0dXJuIHRoaXMudG9Cb29sKHRoaXMuaW5uZXIudmFsdWUoKSk7CiAgICB9OwoKICAgIF9wcm90bzQudG9Cb29sID0gZnVuY3Rpb24gdG9Cb29sKHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiAhIXZhbHVlJCQxOwogICAgfTsKCiAgICByZXR1cm4gQ29uZGl0aW9uYWxSZWZlcmVuY2U7CiAgfSgpOwoKICBfZXhwb3J0cy5Db25kaXRpb25hbFJlZmVyZW5jZSA9IENvbmRpdGlvbmFsUmVmZXJlbmNlOwoKICB2YXIgQ29uY2F0UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9DYWNoZWRSZWZlcmVuY2UpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShDb25jYXRSZWZlcmVuY2UsIF9DYWNoZWRSZWZlcmVuY2UpOwoKICAgIGZ1bmN0aW9uIENvbmNhdFJlZmVyZW5jZShwYXJ0cykgewogICAgICB2YXIgX3RoaXMzOwoKICAgICAgX3RoaXMzID0gX0NhY2hlZFJlZmVyZW5jZS5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMy5wYXJ0cyA9IHBhcnRzOwogICAgICBfdGhpczMudGFnID0gKDAsIF9yZWZlcmVuY2UyLmNvbWJpbmVUYWdnZWQpKHBhcnRzKTsKICAgICAgcmV0dXJuIF90aGlzMzsKICAgIH0KCiAgICB2YXIgX3Byb3RvNSA9IENvbmNhdFJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNS5jb21wdXRlID0gZnVuY3Rpb24gY29tcHV0ZSgpIHsKICAgICAgdmFyIHBhcnRzID0gbmV3IEFycmF5KCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucGFydHMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgdmFsdWUkJDEgPSB0aGlzLnBhcnRzW2ldLnZhbHVlKCk7CgogICAgICAgIGlmICh2YWx1ZSQkMSAhPT0gbnVsbCAmJiB2YWx1ZSQkMSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBwYXJ0c1tpXSA9IGNhc3RUb1N0cmluZyh2YWx1ZSQkMSk7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAocGFydHMubGVuZ3RoID4gMCkgewogICAgICAgIHJldHVybiBwYXJ0cy5qb2luKCcnKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG51bGw7CiAgICB9OwoKICAgIHJldHVybiBDb25jYXRSZWZlcmVuY2U7CiAgfShfcmVmZXJlbmNlMi5DYWNoZWRSZWZlcmVuY2UpOwoKICBmdW5jdGlvbiBjYXN0VG9TdHJpbmcodmFsdWUkJDEpIHsKICAgIGlmICh0eXBlb2YgdmFsdWUkJDEudG9TdHJpbmcgIT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuICcnOwogICAgfQoKICAgIHJldHVybiBTdHJpbmcodmFsdWUkJDEpOwogIH0KCiAgQVBQRU5EX09QQ09ERVMuYWRkKDEKICAvKiBIZWxwZXIgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZikgewogICAgdmFyIGhhbmRsZSA9IF9yZWYub3AxOwogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgaGVscGVyID0gdm0uY29uc3RhbnRzLnJlc29sdmVIYW5kbGUoaGFuZGxlKTsKICAgIHZhciBhcmdzID0gc3RhY2sucG9wKCk7CiAgICB2YXIgdmFsdWUkJDEgPSBoZWxwZXIodm0sIGFyZ3MpOwogICAgdm0ubG9hZFZhbHVlKF92bTIuUmVnaXN0ZXIudjAsIHZhbHVlJCQxKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNgogIC8qIEdldFZhcmlhYmxlICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYyKSB7CiAgICB2YXIgc3ltYm9sID0gX3JlZjIub3AxOwogICAgdmFyIGV4cHIgPSB2bS5yZWZlcmVuY2VGb3JTeW1ib2woc3ltYm9sKTsKICAgIHZtLnN0YWNrLnB1c2goZXhwcik7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDQKICAvKiBTZXRWYXJpYWJsZSAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMykgewogICAgdmFyIHN5bWJvbCA9IF9yZWYzLm9wMTsKICAgIHZhciBleHByID0gdm0uc3RhY2sucG9wKCk7CiAgICB2bS5zY29wZSgpLmJpbmRTeW1ib2woc3ltYm9sLCBleHByKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNQogIC8qIFNldEJsb2NrICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY0KSB7CiAgICB2YXIgc3ltYm9sID0gX3JlZjQub3AxOwogICAgdmFyIGhhbmRsZSA9IHZtLnN0YWNrLnBvcCgpOwogICAgdmFyIHNjb3BlID0gdm0uc3RhY2sucG9wKCk7IC8vIEZJWE1FKG1tdW4pOiBzaG91bGRuJ3QgbmVlZCB0byBjYXN0IHRoaXMKCiAgICB2YXIgdGFibGUgPSB2bS5zdGFjay5wb3AoKTsKICAgIHZhciBibG9jayA9IHRhYmxlID8gW2hhbmRsZSwgc2NvcGUsIHRhYmxlXSA6IG51bGw7CiAgICB2bS5zY29wZSgpLmJpbmRCbG9jayhzeW1ib2wsIGJsb2NrKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoOTYKICAvKiBSZXNvbHZlTWF5YmVMb2NhbCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNSkgewogICAgdmFyIF9uYW1lID0gX3JlZjUub3AxOwogICAgdmFyIG5hbWUgPSB2bS5jb25zdGFudHMuZ2V0U3RyaW5nKF9uYW1lKTsKICAgIHZhciBsb2NhbHMgPSB2bS5zY29wZSgpLmdldFBhcnRpYWxNYXAoKTsKICAgIHZhciByZWYgPSBsb2NhbHNbbmFtZV07CgogICAgaWYgKHJlZiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJlZiA9IHZtLmdldFNlbGYoKS5nZXQobmFtZSk7CiAgICB9CgogICAgdm0uc3RhY2sucHVzaChyZWYpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgyMAogIC8qIFJvb3RTY29wZSAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNikgewogICAgdmFyIHN5bWJvbHMgPSBfcmVmNi5vcDEsCiAgICAgICAgYmluZENhbGxlclNjb3BlID0gX3JlZjYub3AyOwogICAgdm0ucHVzaFJvb3RTY29wZShzeW1ib2xzLCAhIWJpbmRDYWxsZXJTY29wZSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDcKICAvKiBHZXRQcm9wZXJ0eSAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNykgewogICAgdmFyIF9rZXkgPSBfcmVmNy5vcDE7CiAgICB2YXIga2V5ID0gdm0uY29uc3RhbnRzLmdldFN0cmluZyhfa2V5KTsKICAgIHZhciBleHByID0gdm0uc3RhY2sucG9wKCk7CiAgICB2bS5zdGFjay5wdXNoKGV4cHIuZ2V0KGtleSkpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4CiAgLyogR2V0QmxvY2sgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjgpIHsKICAgIHZhciBfYmxvY2sgPSBfcmVmOC5vcDE7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciBibG9jayA9IHZtLnNjb3BlKCkuZ2V0QmxvY2soX2Jsb2NrKTsKCiAgICBpZiAoYmxvY2spIHsKICAgICAgc3RhY2sucHVzaChibG9ja1syXSk7CiAgICAgIHN0YWNrLnB1c2goYmxvY2tbMV0pOwogICAgICBzdGFjay5wdXNoKGJsb2NrWzBdKTsKICAgIH0gZWxzZSB7CiAgICAgIHN0YWNrLnB1c2gobnVsbCk7CiAgICAgIHN0YWNrLnB1c2gobnVsbCk7CiAgICAgIHN0YWNrLnB1c2gobnVsbCk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDkKICAvKiBIYXNCbG9jayAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmOSkgewogICAgdmFyIF9ibG9jayA9IF9yZWY5Lm9wMTsKICAgIHZhciBoYXNCbG9jayA9ICEhdm0uc2NvcGUoKS5nZXRCbG9jayhfYmxvY2spOwogICAgdm0uc3RhY2sucHVzaChoYXNCbG9jayA/IFRSVUVfUkVGRVJFTkNFIDogRkFMU0VfUkVGRVJFTkNFKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMTAKICAvKiBIYXNCbG9ja1BhcmFtcyAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICAvLyBGSVhNRShtbXVuKTogc2hvdWxkIG9ubHkgbmVlZCB0byBwdXNoIHRoZSBzeW1ib2wgdGFibGUKICAgIHZhciBibG9jayA9IHZtLnN0YWNrLnBvcCgpOwogICAgdmFyIHNjb3BlID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgdGFibGUgPSB2bS5zdGFjay5wb3AoKTsKICAgIHZhciBoYXNCbG9ja1BhcmFtcyA9IHRhYmxlICYmIHRhYmxlLnBhcmFtZXRlcnMubGVuZ3RoOwogICAgdm0uc3RhY2sucHVzaChoYXNCbG9ja1BhcmFtcyA/IFRSVUVfUkVGRVJFTkNFIDogRkFMU0VfUkVGRVJFTkNFKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMTEKICAvKiBDb25jYXQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjEwKSB7CiAgICB2YXIgY291bnQgPSBfcmVmMTAub3AxOwogICAgdmFyIG91dCA9IG5ldyBBcnJheShjb3VudCk7CgogICAgZm9yICh2YXIgaSA9IGNvdW50OyBpID4gMDsgaS0tKSB7CiAgICAgIHZhciBvZmZzZXQgPSBpIC0gMTsKICAgICAgb3V0W29mZnNldF0gPSB2bS5zdGFjay5wb3AoKTsKICAgIH0KCiAgICB2bS5zdGFjay5wdXNoKG5ldyBDb25jYXRSZWZlcmVuY2Uob3V0KSk7CiAgfSk7CiAgdmFyIENVUlJJRURfQ09NUE9ORU5UX0RFRklOSVRJT05fQlJBTkQgPSAnQ1VSUklFRCBDT01QT05FTlQgREVGSU5JVElPTiBbaWQ9NmYwMGZlYjktYTBlZi00NTQ3LTk5ZWEtYWMzMjhmODBhY2VhXSc7CgogIGZ1bmN0aW9uIGlzQ3VycmllZENvbXBvbmVudERlZmluaXRpb24oZGVmaW5pdGlvbikgewogICAgcmV0dXJuICEhKGRlZmluaXRpb24gJiYgZGVmaW5pdGlvbltDVVJSSUVEX0NPTVBPTkVOVF9ERUZJTklUSU9OX0JSQU5EXSk7CiAgfQoKICBmdW5jdGlvbiBpc0NvbXBvbmVudERlZmluaXRpb24oZGVmaW5pdGlvbikgewogICAgcmV0dXJuIGRlZmluaXRpb24gJiYgZGVmaW5pdGlvbltDVVJSSUVEX0NPTVBPTkVOVF9ERUZJTklUSU9OX0JSQU5EXTsKICB9CgogIHZhciBDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIC8qKiBAaW50ZXJuYWwgKi8KICAgIGZ1bmN0aW9uIEN1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGlubmVyLCBhcmdzKSB7CiAgICAgIHRoaXMuaW5uZXIgPSBpbm5lcjsKICAgICAgdGhpcy5hcmdzID0gYXJnczsKICAgICAgdGhpc1tDVVJSSUVEX0NPTVBPTkVOVF9ERUZJTklUSU9OX0JSQU5EXSA9IHRydWU7CiAgICB9CgogICAgdmFyIF9wcm90bzYgPSBDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbi5wcm90b3R5cGU7CgogICAgX3Byb3RvNi51bndyYXAgPSBmdW5jdGlvbiB1bndyYXAoYXJncykgewogICAgICBhcmdzLnJlYWxsb2ModGhpcy5vZmZzZXQpOwogICAgICB2YXIgZGVmaW5pdGlvbiA9IHRoaXM7CgogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgIHZhciBfZGVmaW5pdGlvbiA9IGRlZmluaXRpb24sCiAgICAgICAgICAgIGN1cnJpZWRBcmdzID0gX2RlZmluaXRpb24uYXJncywKICAgICAgICAgICAgaW5uZXIgPSBfZGVmaW5pdGlvbi5pbm5lcjsKCiAgICAgICAgaWYgKGN1cnJpZWRBcmdzKSB7CiAgICAgICAgICBhcmdzLnBvc2l0aW9uYWwucHJlcGVuZChjdXJyaWVkQXJncy5wb3NpdGlvbmFsKTsKICAgICAgICAgIGFyZ3MubmFtZWQubWVyZ2UoY3VycmllZEFyZ3MubmFtZWQpOwogICAgICAgIH0KCiAgICAgICAgaWYgKCFpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGlubmVyKSkgewogICAgICAgICAgcmV0dXJuIGlubmVyOwogICAgICAgIH0KCiAgICAgICAgZGVmaW5pdGlvbiA9IGlubmVyOwogICAgICB9CiAgICB9CiAgICAvKiogQGludGVybmFsICovCiAgICA7CgogICAgKDAsIF9lbWJlckJhYmVsLmNyZWF0ZUNsYXNzKShDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbiwgW3sKICAgICAga2V5OiAib2Zmc2V0IiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIGlubmVyID0gdGhpcy5pbm5lciwKICAgICAgICAgICAgYXJncyA9IHRoaXMuYXJnczsKICAgICAgICB2YXIgbGVuZ3RoID0gYXJncyA/IGFyZ3MucG9zaXRpb25hbC5sZW5ndGggOiAwOwogICAgICAgIHJldHVybiBpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGlubmVyKSA/IGxlbmd0aCArIGlubmVyLm9mZnNldCA6IGxlbmd0aDsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIEN1cnJpZWRDb21wb25lbnREZWZpbml0aW9uOwogIH0oKTsKCiAgX2V4cG9ydHMuQ3VycmllZENvbXBvbmVudERlZmluaXRpb24gPSBDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbjsKCiAgZnVuY3Rpb24gY3Vycnkoc3BlYywgYXJncykgewogICAgaWYgKGFyZ3MgPT09IHZvaWQgMCkgewogICAgICBhcmdzID0gbnVsbDsKICAgIH0KCiAgICByZXR1cm4gbmV3IEN1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKHNwZWMsIGFyZ3MpOwogIH0KCiAgZnVuY3Rpb24gbm9ybWFsaXplU3RyaW5nVmFsdWUodmFsdWUkJDEpIHsKICAgIGlmIChpc0VtcHR5KHZhbHVlJCQxKSkgewogICAgICByZXR1cm4gJyc7CiAgICB9CgogICAgcmV0dXJuIFN0cmluZyh2YWx1ZSQkMSk7CiAgfQoKICBmdW5jdGlvbiBzaG91bGRDb2VyY2UodmFsdWUkJDEpIHsKICAgIHJldHVybiBpc1N0cmluZyh2YWx1ZSQkMSkgfHwgaXNFbXB0eSh2YWx1ZSQkMSkgfHwgdHlwZW9mIHZhbHVlJCQxID09PSAnYm9vbGVhbicgfHwgdHlwZW9mIHZhbHVlJCQxID09PSAnbnVtYmVyJzsKICB9CgogIGZ1bmN0aW9uIGlzRW1wdHkodmFsdWUkJDEpIHsKICAgIHJldHVybiB2YWx1ZSQkMSA9PT0gbnVsbCB8fCB2YWx1ZSQkMSA9PT0gdW5kZWZpbmVkIHx8IHR5cGVvZiB2YWx1ZSQkMS50b1N0cmluZyAhPT0gJ2Z1bmN0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGlzU2FmZVN0cmluZyh2YWx1ZSQkMSkgewogICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSQkMSA9PT0gJ29iamVjdCcgJiYgdmFsdWUkJDEgIT09IG51bGwgJiYgdHlwZW9mIHZhbHVlJCQxLnRvSFRNTCA9PT0gJ2Z1bmN0aW9uJzsKICB9CgogIGZ1bmN0aW9uIGlzTm9kZSh2YWx1ZSQkMSkgewogICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSQkMSA9PT0gJ29iamVjdCcgJiYgdmFsdWUkJDEgIT09IG51bGwgJiYgdHlwZW9mIHZhbHVlJCQxLm5vZGVUeXBlID09PSAnbnVtYmVyJzsKICB9CgogIGZ1bmN0aW9uIGlzRnJhZ21lbnQodmFsdWUkJDEpIHsKICAgIHJldHVybiBpc05vZGUodmFsdWUkJDEpICYmIHZhbHVlJCQxLm5vZGVUeXBlID09PSAxMTsKICB9CgogIGZ1bmN0aW9uIGlzU3RyaW5nKHZhbHVlJCQxKSB7CiAgICByZXR1cm4gdHlwZW9mIHZhbHVlJCQxID09PSAnc3RyaW5nJzsKICB9CgogIHZhciBEeW5hbWljVGV4dENvbnRlbnQgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1VwZGF0aW5nT3Bjb2RlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRHluYW1pY1RleHRDb250ZW50LCBfVXBkYXRpbmdPcGNvZGUpOwoKICAgIGZ1bmN0aW9uIER5bmFtaWNUZXh0Q29udGVudChub2RlLCByZWZlcmVuY2UsIGxhc3RWYWx1ZSkgewogICAgICB2YXIgX3RoaXM0OwoKICAgICAgX3RoaXM0ID0gX1VwZGF0aW5nT3Bjb2RlLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXM0Lm5vZGUgPSBub2RlOwogICAgICBfdGhpczQucmVmZXJlbmNlID0gcmVmZXJlbmNlOwogICAgICBfdGhpczQubGFzdFZhbHVlID0gbGFzdFZhbHVlOwogICAgICBfdGhpczQudHlwZSA9ICdkeW5hbWljLXRleHQnOwogICAgICBfdGhpczQudGFnID0gcmVmZXJlbmNlLnRhZzsKICAgICAgX3RoaXM0Lmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlMi52YWx1ZSkoX3RoaXM0LnRhZyk7CiAgICAgIHJldHVybiBfdGhpczQ7CiAgICB9CgogICAgdmFyIF9wcm90bzcgPSBEeW5hbWljVGV4dENvbnRlbnQucHJvdG90eXBlOwoKICAgIF9wcm90bzcuZXZhbHVhdGUgPSBmdW5jdGlvbiBldmFsdWF0ZSgpIHsKICAgICAgdmFyIHJlZmVyZW5jZSA9IHRoaXMucmVmZXJlbmNlLAogICAgICAgICAgdGFnID0gdGhpcy50YWc7CgogICAgICBpZiAoISgwLCBfcmVmZXJlbmNlMi52YWxpZGF0ZSkodGFnLCB0aGlzLmxhc3RSZXZpc2lvbikpIHsKICAgICAgICB0aGlzLmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlMi52YWx1ZSkodGFnKTsKICAgICAgICB0aGlzLnVwZGF0ZShyZWZlcmVuY2UudmFsdWUoKSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNy51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUodmFsdWUkJDEpIHsKICAgICAgdmFyIGxhc3RWYWx1ZSA9IHRoaXMubGFzdFZhbHVlOwogICAgICBpZiAodmFsdWUkJDEgPT09IGxhc3RWYWx1ZSkgcmV0dXJuOwogICAgICB2YXIgbm9ybWFsaXplZDsKCiAgICAgIGlmIChpc0VtcHR5KHZhbHVlJCQxKSkgewogICAgICAgIG5vcm1hbGl6ZWQgPSAnJzsKICAgICAgfSBlbHNlIGlmIChpc1N0cmluZyh2YWx1ZSQkMSkpIHsKICAgICAgICBub3JtYWxpemVkID0gdmFsdWUkJDE7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbm9ybWFsaXplZCA9IFN0cmluZyh2YWx1ZSQkMSk7CiAgICAgIH0KCiAgICAgIGlmIChub3JtYWxpemVkICE9PSBsYXN0VmFsdWUpIHsKICAgICAgICB2YXIgdGV4dE5vZGUgPSB0aGlzLm5vZGU7CiAgICAgICAgdGV4dE5vZGUubm9kZVZhbHVlID0gdGhpcy5sYXN0VmFsdWUgPSBub3JtYWxpemVkOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBEeW5hbWljVGV4dENvbnRlbnQ7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBJc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Db25kaXRpb25hbFJlZmVyZW5jZSkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKElzQ3VycmllZENvbXBvbmVudERlZmluaXRpb25SZWZlcmVuY2UsIF9Db25kaXRpb25hbFJlZmVyZW5jZSk7CgogICAgZnVuY3Rpb24gSXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvblJlZmVyZW5jZSgpIHsKICAgICAgcmV0dXJuIF9Db25kaXRpb25hbFJlZmVyZW5jZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgSXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvblJlZmVyZW5jZS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoaW5uZXIpIHsKICAgICAgcmV0dXJuIG5ldyBJc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uUmVmZXJlbmNlKGlubmVyKTsKICAgIH07CgogICAgdmFyIF9wcm90bzggPSBJc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG84LnRvQm9vbCA9IGZ1bmN0aW9uIHRvQm9vbCh2YWx1ZSQkMSkgewogICAgICByZXR1cm4gaXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbih2YWx1ZSQkMSk7CiAgICB9OwoKICAgIHJldHVybiBJc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uUmVmZXJlbmNlOwogIH0oQ29uZGl0aW9uYWxSZWZlcmVuY2UpOwoKICB2YXIgQ29udGVudFR5cGVSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDb250ZW50VHlwZVJlZmVyZW5jZShpbm5lcikgewogICAgICB0aGlzLmlubmVyID0gaW5uZXI7CiAgICAgIHRoaXMudGFnID0gaW5uZXIudGFnOwogICAgfQoKICAgIHZhciBfcHJvdG85ID0gQ29udGVudFR5cGVSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzkudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgdmFyIHZhbHVlJCQxID0gdGhpcy5pbm5lci52YWx1ZSgpOwoKICAgICAgaWYgKHNob3VsZENvZXJjZSh2YWx1ZSQkMSkpIHsKICAgICAgICByZXR1cm4gMQogICAgICAgIC8qIFN0cmluZyAqLwogICAgICAgIDsKICAgICAgfSBlbHNlIGlmIChpc0NvbXBvbmVudERlZmluaXRpb24odmFsdWUkJDEpKSB7CiAgICAgICAgcmV0dXJuIDAKICAgICAgICAvKiBDb21wb25lbnQgKi8KICAgICAgICA7CiAgICAgIH0gZWxzZSBpZiAoaXNTYWZlU3RyaW5nKHZhbHVlJCQxKSkgewogICAgICAgIHJldHVybiAzCiAgICAgICAgLyogU2FmZVN0cmluZyAqLwogICAgICAgIDsKICAgICAgfSBlbHNlIGlmIChpc0ZyYWdtZW50KHZhbHVlJCQxKSkgewogICAgICAgIHJldHVybiA0CiAgICAgICAgLyogRnJhZ21lbnQgKi8KICAgICAgICA7CiAgICAgIH0gZWxzZSBpZiAoaXNOb2RlKHZhbHVlJCQxKSkgewogICAgICAgIHJldHVybiA1CiAgICAgICAgLyogTm9kZSAqLwogICAgICAgIDsKICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiAxCiAgICAgICAgICAvKiBTdHJpbmcgKi8KICAgICAgICAgIDsKICAgICAgICB9CiAgICB9OwoKICAgIHJldHVybiBDb250ZW50VHlwZVJlZmVyZW5jZTsKICB9KCk7CgogIEFQUEVORF9PUENPREVTLmFkZCgyOAogIC8qIEFwcGVuZEhUTUwgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIHJlZmVyZW5jZSA9IHZtLnN0YWNrLnBvcCgpOwogICAgdmFyIHJhd1ZhbHVlID0gcmVmZXJlbmNlLnZhbHVlKCk7CiAgICB2YXIgdmFsdWUkJDEgPSBpc0VtcHR5KHJhd1ZhbHVlKSA/ICcnIDogU3RyaW5nKHJhd1ZhbHVlKTsKICAgIHZtLmVsZW1lbnRzKCkuYXBwZW5kRHluYW1pY0hUTUwodmFsdWUkJDEpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgyOQogIC8qIEFwcGVuZFNhZmVIVE1MICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciByZWZlcmVuY2UgPSB2bS5zdGFjay5wb3AoKTsKICAgIHZhciByYXdWYWx1ZSA9IHJlZmVyZW5jZS52YWx1ZSgpLnRvSFRNTCgpOwogICAgdmFyIHZhbHVlJCQxID0gaXNFbXB0eShyYXdWYWx1ZSkgPyAnJyA6IHJhd1ZhbHVlOwogICAgdm0uZWxlbWVudHMoKS5hcHBlbmREeW5hbWljSFRNTCh2YWx1ZSQkMSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDMyCiAgLyogQXBwZW5kVGV4dCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgcmVmZXJlbmNlID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgcmF3VmFsdWUgPSByZWZlcmVuY2UudmFsdWUoKTsKICAgIHZhciB2YWx1ZSQkMSA9IGlzRW1wdHkocmF3VmFsdWUpID8gJycgOiBTdHJpbmcocmF3VmFsdWUpOwogICAgdmFyIG5vZGUgPSB2bS5lbGVtZW50cygpLmFwcGVuZER5bmFtaWNUZXh0KHZhbHVlJCQxKTsKCiAgICBpZiAoISgwLCBfcmVmZXJlbmNlMi5pc0NvbnN0KShyZWZlcmVuY2UpKSB7CiAgICAgIHZtLnVwZGF0ZVdpdGgobmV3IER5bmFtaWNUZXh0Q29udGVudChub2RlLCByZWZlcmVuY2UsIHZhbHVlJCQxKSk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDMwCiAgLyogQXBwZW5kRG9jdW1lbnRGcmFnbWVudCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgcmVmZXJlbmNlID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgdmFsdWUkJDEgPSByZWZlcmVuY2UudmFsdWUoKTsKICAgIHZtLmVsZW1lbnRzKCkuYXBwZW5kRHluYW1pY0ZyYWdtZW50KHZhbHVlJCQxKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMzEKICAvKiBBcHBlbmROb2RlICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciByZWZlcmVuY2UgPSB2bS5zdGFjay5wb3AoKTsKICAgIHZhciB2YWx1ZSQkMSA9IHJlZmVyZW5jZS52YWx1ZSgpOwogICAgdm0uZWxlbWVudHMoKS5hcHBlbmREeW5hbWljTm9kZSh2YWx1ZSQkMSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDIyCiAgLyogQ2hpbGRTY29wZSAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICByZXR1cm4gdm0ucHVzaENoaWxkU2NvcGUoKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMjMKICAvKiBQb3BTY29wZSAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICByZXR1cm4gdm0ucG9wU2NvcGUoKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNDQKICAvKiBQdXNoRHluYW1pY1Njb3BlICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHJldHVybiB2bS5wdXNoRHluYW1pY1Njb3BlKCk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDQ1CiAgLyogUG9wRHluYW1pY1Njb3BlICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHJldHVybiB2bS5wb3BEeW5hbWljU2NvcGUoKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMTIKICAvKiBDb25zdGFudCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMTEpIHsKICAgIHZhciBvdGhlciA9IF9yZWYxMS5vcDE7CiAgICB2bS5zdGFjay5wdXNoKHZtLmNvbnN0YW50cy5nZXRPdGhlcihvdGhlcikpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgxMwogIC8qIFByaW1pdGl2ZSAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMTIpIHsKICAgIHZhciBwcmltaXRpdmUgPSBfcmVmMTIub3AxOwogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgZmxhZyA9IHByaW1pdGl2ZSAmIDc7IC8vIDExMQoKICAgIHZhciB2YWx1ZSQkMSA9IHByaW1pdGl2ZSA+PiAzOwoKICAgIHN3aXRjaCAoZmxhZykgewogICAgICBjYXNlIDAKICAgICAgLyogTlVNQkVSICovCiAgICAgIDoKICAgICAgICBzdGFjay5wdXNoKHZhbHVlJCQxKTsKICAgICAgICBicmVhazsKCiAgICAgIGNhc2UgMQogICAgICAvKiBGTE9BVCAqLwogICAgICA6CiAgICAgICAgc3RhY2sucHVzaCh2bS5jb25zdGFudHMuZ2V0TnVtYmVyKHZhbHVlJCQxKSk7CiAgICAgICAgYnJlYWs7CgogICAgICBjYXNlIDIKICAgICAgLyogU1RSSU5HICovCiAgICAgIDoKICAgICAgICBzdGFjay5wdXNoKHZtLmNvbnN0YW50cy5nZXRTdHJpbmcodmFsdWUkJDEpKTsKICAgICAgICBicmVhazsKCiAgICAgIGNhc2UgMwogICAgICAvKiBCT09MRUFOX09SX1ZPSUQgKi8KICAgICAgOgogICAgICAgIHN0YWNrLnB1c2hFbmNvZGVkSW1tZWRpYXRlKHByaW1pdGl2ZSk7CiAgICAgICAgYnJlYWs7CgogICAgICBjYXNlIDQKICAgICAgLyogTkVHQVRJVkUgKi8KICAgICAgOgogICAgICAgIHN0YWNrLnB1c2godm0uY29uc3RhbnRzLmdldE51bWJlcih2YWx1ZSQkMSkpOwogICAgICAgIGJyZWFrOwoKICAgICAgY2FzZSA1CiAgICAgIC8qIEJJR19OVU0gKi8KICAgICAgOgogICAgICAgIHN0YWNrLnB1c2godm0uY29uc3RhbnRzLmdldE51bWJlcih2YWx1ZSQkMSkpOwogICAgICAgIGJyZWFrOwogICAgfQogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgxNAogIC8qIFByaW1pdGl2ZVJlZmVyZW5jZSAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHN0YWNrLnB1c2goUHJpbWl0aXZlUmVmZXJlbmNlLmNyZWF0ZShzdGFjay5wb3AoKSkpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgxNQogIC8qIFJlaWZ5VTMyICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgc3RhY2sucHVzaChzdGFjay5wZWVrKCkudmFsdWUoKSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDE2CiAgLyogRHVwICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYxMykgewogICAgdmFyIHJlZ2lzdGVyID0gX3JlZjEzLm9wMSwKICAgICAgICBvZmZzZXQgPSBfcmVmMTMub3AyOwogICAgdmFyIHBvc2l0aW9uID0gdm0uZmV0Y2hWYWx1ZShyZWdpc3RlcikgLSBvZmZzZXQ7CiAgICB2bS5zdGFjay5kdXAocG9zaXRpb24pOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgxNwogIC8qIFBvcCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMTQpIHsKICAgIHZhciBjb3VudCA9IF9yZWYxNC5vcDE7CiAgICB2bS5zdGFjay5wb3AoY291bnQpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgxOAogIC8qIExvYWQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjE1KSB7CiAgICB2YXIgcmVnaXN0ZXIgPSBfcmVmMTUub3AxOwogICAgdm0ubG9hZChyZWdpc3Rlcik7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDE5CiAgLyogRmV0Y2ggKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjE2KSB7CiAgICB2YXIgcmVnaXN0ZXIgPSBfcmVmMTYub3AxOwogICAgdm0uZmV0Y2gocmVnaXN0ZXIpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg0MwogIC8qIEJpbmREeW5hbWljU2NvcGUgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjE3KSB7CiAgICB2YXIgX25hbWVzID0gX3JlZjE3Lm9wMTsKICAgIHZhciBuYW1lcyA9IHZtLmNvbnN0YW50cy5nZXRBcnJheShfbmFtZXMpOwogICAgdm0uYmluZER5bmFtaWNTY29wZShuYW1lcyk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDYxCiAgLyogRW50ZXIgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjE4KSB7CiAgICB2YXIgYXJncyA9IF9yZWYxOC5vcDE7CiAgICB2bS5lbnRlcihhcmdzKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNjIKICAvKiBFeGl0ICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZtLmV4aXQoKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNDgKICAvKiBQdXNoU3ltYm9sVGFibGUgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjE5KSB7CiAgICB2YXIgX3RhYmxlID0gX3JlZjE5Lm9wMTsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgc3RhY2sucHVzaCh2bS5jb25zdGFudHMuZ2V0U2VyaWFsaXphYmxlKF90YWJsZSkpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg0NwogIC8qIFB1c2hCbG9ja1Njb3BlICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgc3RhY2sucHVzaCh2bS5zY29wZSgpKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNDYKICAvKiBDb21waWxlQmxvY2sgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgYmxvY2sgPSBzdGFjay5wb3AoKTsKCiAgICBpZiAoYmxvY2spIHsKICAgICAgc3RhY2sucHVzaChibG9jay5jb21waWxlKCkpOwogICAgfSBlbHNlIHsKICAgICAgc3RhY2sucHVzaE51bGwoKTsKICAgIH0KICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNTEKICAvKiBJbnZva2VZaWVsZCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciBoYW5kbGUgPSBzdGFjay5wb3AoKTsKICAgIHZhciBzY29wZSA9IHN0YWNrLnBvcCgpOyAvLyBGSVhNRShtbXVuKTogc2hvdWxkbid0IG5lZWQgdG8gY2FzdCB0aGlzCgogICAgdmFyIHRhYmxlID0gc3RhY2sucG9wKCk7CiAgICB2YXIgYXJncyA9IHN0YWNrLnBvcCgpOwoKICAgIGlmICh0YWJsZSA9PT0gbnVsbCkgewogICAgICAvLyBUbyBiYWxhbmNlIHRoZSBwb3B7RnJhbWUsU2NvcGV9CiAgICAgIHZtLnB1c2hGcmFtZSgpOwogICAgICB2bS5wdXNoU2NvcGUoc2NvcGUpOyAvLyBDb3VsZCBiZSBudWxsIGJ1dCBpdCBkb2VzbnQgbWF0dGVyIGFzIGl0IGlzIGltbWVkaWF0ZWxseSBwb3BwZWQuCgogICAgICByZXR1cm47CiAgICB9CgogICAgdmFyIGludm9raW5nU2NvcGUgPSBzY29wZTsgLy8gSWYgbmVjZXNzYXJ5LCBjcmVhdGUgYSBjaGlsZCBzY29wZQoKICAgIHsKICAgICAgdmFyIGxvY2FscyA9IHRhYmxlLnBhcmFtZXRlcnM7CiAgICAgIHZhciBsb2NhbHNDb3VudCA9IGxvY2Fscy5sZW5ndGg7CgogICAgICBpZiAobG9jYWxzQ291bnQgPiAwKSB7CiAgICAgICAgaW52b2tpbmdTY29wZSA9IGludm9raW5nU2NvcGUuY2hpbGQoKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb2NhbHNDb3VudDsgaSsrKSB7CiAgICAgICAgICBpbnZva2luZ1Njb3BlLmJpbmRTeW1ib2wobG9jYWxzW2ldLCBhcmdzLmF0KGkpKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHZtLnB1c2hGcmFtZSgpOwogICAgdm0ucHVzaFNjb3BlKGludm9raW5nU2NvcGUpOwogICAgdm0uY2FsbChoYW5kbGUpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg1MwogIC8qIEp1bXBJZiAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMjApIHsKICAgIHZhciB0YXJnZXQgPSBfcmVmMjAub3AxOwogICAgdmFyIHJlZmVyZW5jZSA9IHZtLnN0YWNrLnBvcCgpOwoKICAgIGlmICgoMCwgX3JlZmVyZW5jZTIuaXNDb25zdCkocmVmZXJlbmNlKSkgewogICAgICBpZiAocmVmZXJlbmNlLnZhbHVlKCkpIHsKICAgICAgICB2bS5nb3RvKHRhcmdldCk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhciBjYWNoZSA9IG5ldyBfcmVmZXJlbmNlMi5SZWZlcmVuY2VDYWNoZShyZWZlcmVuY2UpOwoKICAgICAgaWYgKGNhY2hlLnBlZWsoKSkgewogICAgICAgIHZtLmdvdG8odGFyZ2V0KTsKICAgICAgfQoKICAgICAgdm0udXBkYXRlV2l0aChuZXcgQXNzZXJ0KGNhY2hlKSk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDU0CiAgLyogSnVtcFVubGVzcyAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMjEpIHsKICAgIHZhciB0YXJnZXQgPSBfcmVmMjEub3AxOwogICAgdmFyIHJlZmVyZW5jZSA9IHZtLnN0YWNrLnBvcCgpOwoKICAgIGlmICgoMCwgX3JlZmVyZW5jZTIuaXNDb25zdCkocmVmZXJlbmNlKSkgewogICAgICBpZiAoIXJlZmVyZW5jZS52YWx1ZSgpKSB7CiAgICAgICAgdm0uZ290byh0YXJnZXQpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB2YXIgY2FjaGUgPSBuZXcgX3JlZmVyZW5jZTIuUmVmZXJlbmNlQ2FjaGUocmVmZXJlbmNlKTsKCiAgICAgIGlmICghY2FjaGUucGVlaygpKSB7CiAgICAgICAgdm0uZ290byh0YXJnZXQpOwogICAgICB9CgogICAgICB2bS51cGRhdGVXaXRoKG5ldyBBc3NlcnQoY2FjaGUpKTsKICAgIH0KICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNTUKICAvKiBKdW1wRXEgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjIyKSB7CiAgICB2YXIgdGFyZ2V0ID0gX3JlZjIyLm9wMSwKICAgICAgICBjb21wYXJpc29uID0gX3JlZjIyLm9wMjsKICAgIHZhciBvdGhlciA9IHZtLnN0YWNrLnBlZWsoKTsKCiAgICBpZiAob3RoZXIgPT09IGNvbXBhcmlzb24pIHsKICAgICAgdm0uZ290byh0YXJnZXQpOwogICAgfQogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg1NgogIC8qIEFzc2VydFNhbWUgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIHJlZmVyZW5jZSA9IHZtLnN0YWNrLnBlZWsoKTsKCiAgICBpZiAoISgwLCBfcmVmZXJlbmNlMi5pc0NvbnN0KShyZWZlcmVuY2UpKSB7CiAgICAgIHZtLnVwZGF0ZVdpdGgoQXNzZXJ0LmluaXRpYWxpemUobmV3IF9yZWZlcmVuY2UyLlJlZmVyZW5jZUNhY2hlKHJlZmVyZW5jZSkpKTsKICAgIH0KICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNjMKICAvKiBUb0Jvb2xlYW4gKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIGVudiA9IHZtLmVudiwKICAgICAgICBzdGFjayA9IHZtLnN0YWNrOwogICAgc3RhY2sucHVzaChlbnYudG9Db25kaXRpb25hbFJlZmVyZW5jZShzdGFjay5wb3AoKSkpOwogIH0pOwoKICB2YXIgQXNzZXJ0ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9VcGRhdGluZ09wY29kZTIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShBc3NlcnQsIF9VcGRhdGluZ09wY29kZTIpOwoKICAgIGZ1bmN0aW9uIEFzc2VydChjYWNoZSkgewogICAgICB2YXIgX3RoaXM1OwoKICAgICAgX3RoaXM1ID0gX1VwZGF0aW5nT3Bjb2RlMi5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzNS50eXBlID0gJ2Fzc2VydCc7CiAgICAgIF90aGlzNS50YWcgPSBjYWNoZS50YWc7CiAgICAgIF90aGlzNS5jYWNoZSA9IGNhY2hlOwogICAgICByZXR1cm4gX3RoaXM1OwogICAgfQoKICAgIEFzc2VydC5pbml0aWFsaXplID0gZnVuY3Rpb24gaW5pdGlhbGl6ZShjYWNoZSkgewogICAgICB2YXIgYXNzZXJ0ID0gbmV3IEFzc2VydChjYWNoZSk7CiAgICAgIGNhY2hlLnBlZWsoKTsKICAgICAgcmV0dXJuIGFzc2VydDsKICAgIH07CgogICAgdmFyIF9wcm90bzEwID0gQXNzZXJ0LnByb3RvdHlwZTsKCiAgICBfcHJvdG8xMC5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKHZtKSB7CiAgICAgIHZhciBjYWNoZSA9IHRoaXMuY2FjaGU7CgogICAgICBpZiAoKDAsIF9yZWZlcmVuY2UyLmlzTW9kaWZpZWQpKGNhY2hlLnJldmFsaWRhdGUoKSkpIHsKICAgICAgICB2bS50aHJvdygpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBBc3NlcnQ7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBKdW1wSWZOb3RNb2RpZmllZE9wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfVXBkYXRpbmdPcGNvZGUzKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoSnVtcElmTm90TW9kaWZpZWRPcGNvZGUsIF9VcGRhdGluZ09wY29kZTMpOwoKICAgIGZ1bmN0aW9uIEp1bXBJZk5vdE1vZGlmaWVkT3Bjb2RlKHRhZywgdGFyZ2V0KSB7CiAgICAgIHZhciBfdGhpczY7CgogICAgICBfdGhpczYgPSBfVXBkYXRpbmdPcGNvZGUzLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgX3RoaXM2LnRhcmdldCA9IHRhcmdldDsKICAgICAgX3RoaXM2LnR5cGUgPSAnanVtcC1pZi1ub3QtbW9kaWZpZWQnOwogICAgICBfdGhpczYudGFnID0gdGFnOwogICAgICBfdGhpczYubGFzdFJldmlzaW9uID0gKDAsIF9yZWZlcmVuY2UyLnZhbHVlKSh0YWcpOwogICAgICByZXR1cm4gX3RoaXM2OwogICAgfQoKICAgIHZhciBfcHJvdG8xMSA9IEp1bXBJZk5vdE1vZGlmaWVkT3Bjb2RlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xMS5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKHZtKSB7CiAgICAgIHZhciB0YWcgPSB0aGlzLnRhZywKICAgICAgICAgIHRhcmdldCA9IHRoaXMudGFyZ2V0LAogICAgICAgICAgbGFzdFJldmlzaW9uID0gdGhpcy5sYXN0UmV2aXNpb247CgogICAgICBpZiAoIXZtLmFsd2F5c1JldmFsaWRhdGUgJiYgKDAsIF9yZWZlcmVuY2UyLnZhbGlkYXRlKSh0YWcsIGxhc3RSZXZpc2lvbikpIHsKICAgICAgICB2bS5nb3RvKHRhcmdldCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMTEuZGlkTW9kaWZ5ID0gZnVuY3Rpb24gZGlkTW9kaWZ5KCkgewogICAgICB0aGlzLmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlMi52YWx1ZSkodGhpcy50YWcpOwogICAgfTsKCiAgICByZXR1cm4gSnVtcElmTm90TW9kaWZpZWRPcGNvZGU7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBEaWRNb2RpZnlPcGNvZGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1VwZGF0aW5nT3Bjb2RlNCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKERpZE1vZGlmeU9wY29kZSwgX1VwZGF0aW5nT3Bjb2RlNCk7CgogICAgZnVuY3Rpb24gRGlkTW9kaWZ5T3Bjb2RlKHRhcmdldCkgewogICAgICB2YXIgX3RoaXM3OwoKICAgICAgX3RoaXM3ID0gX1VwZGF0aW5nT3Bjb2RlNC5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzNy50YXJnZXQgPSB0YXJnZXQ7CiAgICAgIF90aGlzNy50eXBlID0gJ2RpZC1tb2RpZnknOwogICAgICBfdGhpczcudGFnID0gX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHOwogICAgICByZXR1cm4gX3RoaXM3OwogICAgfQoKICAgIHZhciBfcHJvdG8xMiA9IERpZE1vZGlmeU9wY29kZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMTIuZXZhbHVhdGUgPSBmdW5jdGlvbiBldmFsdWF0ZSgpIHsKICAgICAgdGhpcy50YXJnZXQuZGlkTW9kaWZ5KCk7CiAgICB9OwoKICAgIHJldHVybiBEaWRNb2RpZnlPcGNvZGU7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBMYWJlbE9wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIExhYmVsT3Bjb2RlKGxhYmVsKSB7CiAgICAgIHRoaXMudGFnID0gX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHOwogICAgICB0aGlzLnR5cGUgPSAnbGFiZWwnOwogICAgICB0aGlzLmxhYmVsID0gbnVsbDsKICAgICAgdGhpcy5wcmV2ID0gbnVsbDsKICAgICAgdGhpcy5uZXh0ID0gbnVsbDsKICAgICAgKDAsIF91dGlsLmluaXRpYWxpemVHdWlkKSh0aGlzKTsKICAgICAgdGhpcy5sYWJlbCA9IGxhYmVsOwogICAgfQoKICAgIHZhciBfcHJvdG8xMyA9IExhYmVsT3Bjb2RlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xMy5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKCkge307CgogICAgX3Byb3RvMTMuaW5zcGVjdCA9IGZ1bmN0aW9uIGluc3BlY3QoKSB7CiAgICAgIHJldHVybiB0aGlzLmxhYmVsICsgIiBbIiArIHRoaXMuX2d1aWQgKyAiXSI7CiAgICB9OwoKICAgIHJldHVybiBMYWJlbE9wY29kZTsKICB9KCk7CgogIEFQUEVORF9PUENPREVTLmFkZCgyNgogIC8qIFRleHQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjIzKSB7CiAgICB2YXIgdGV4dCA9IF9yZWYyMy5vcDE7CiAgICB2bS5lbGVtZW50cygpLmFwcGVuZFRleHQodm0uY29uc3RhbnRzLmdldFN0cmluZyh0ZXh0KSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDI3CiAgLyogQ29tbWVudCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMjQpIHsKICAgIHZhciB0ZXh0ID0gX3JlZjI0Lm9wMTsKICAgIHZtLmVsZW1lbnRzKCkuYXBwZW5kQ29tbWVudCh2bS5jb25zdGFudHMuZ2V0U3RyaW5nKHRleHQpKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMzMKICAvKiBPcGVuRWxlbWVudCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMjUpIHsKICAgIHZhciB0YWcgPSBfcmVmMjUub3AxOwogICAgdm0uZWxlbWVudHMoKS5vcGVuRWxlbWVudCh2bS5jb25zdGFudHMuZ2V0U3RyaW5nKHRhZykpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgzNAogIC8qIE9wZW5EeW5hbWljRWxlbWVudCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgdGFnTmFtZSA9IHZtLnN0YWNrLnBvcCgpLnZhbHVlKCk7CiAgICB2bS5lbGVtZW50cygpLm9wZW5FbGVtZW50KHRhZ05hbWUpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg0MQogIC8qIFB1c2hSZW1vdGVFbGVtZW50ICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBlbGVtZW50UmVmID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgbmV4dFNpYmxpbmdSZWYgPSB2bS5zdGFjay5wb3AoKTsKICAgIHZhciBndWlkUmVmID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgZWxlbWVudDsKICAgIHZhciBuZXh0U2libGluZzsKICAgIHZhciBndWlkID0gZ3VpZFJlZi52YWx1ZSgpOwoKICAgIGlmICgoMCwgX3JlZmVyZW5jZTIuaXNDb25zdCkoZWxlbWVudFJlZikpIHsKICAgICAgZWxlbWVudCA9IGVsZW1lbnRSZWYudmFsdWUoKTsKICAgIH0gZWxzZSB7CiAgICAgIHZhciBjYWNoZSA9IG5ldyBfcmVmZXJlbmNlMi5SZWZlcmVuY2VDYWNoZShlbGVtZW50UmVmKTsKICAgICAgZWxlbWVudCA9IGNhY2hlLnBlZWsoKTsKICAgICAgdm0udXBkYXRlV2l0aChuZXcgQXNzZXJ0KGNhY2hlKSk7CiAgICB9CgogICAgaWYgKCgwLCBfcmVmZXJlbmNlMi5pc0NvbnN0KShuZXh0U2libGluZ1JlZikpIHsKICAgICAgbmV4dFNpYmxpbmcgPSBuZXh0U2libGluZ1JlZi52YWx1ZSgpOwogICAgfSBlbHNlIHsKICAgICAgdmFyIF9jYWNoZSA9IG5ldyBfcmVmZXJlbmNlMi5SZWZlcmVuY2VDYWNoZShuZXh0U2libGluZ1JlZik7CgogICAgICBuZXh0U2libGluZyA9IF9jYWNoZS5wZWVrKCk7CiAgICAgIHZtLnVwZGF0ZVdpdGgobmV3IEFzc2VydChfY2FjaGUpKTsKICAgIH0KCiAgICB2bS5lbGVtZW50cygpLnB1c2hSZW1vdGVFbGVtZW50KGVsZW1lbnQsIGd1aWQsIG5leHRTaWJsaW5nKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNDIKICAvKiBQb3BSZW1vdGVFbGVtZW50ICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZtLmVsZW1lbnRzKCkucG9wUmVtb3RlRWxlbWVudCgpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCgzOAogIC8qIEZsdXNoRWxlbWVudCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgb3BlcmF0aW9ucyA9IHZtLmZldGNoVmFsdWUoX3ZtMi5SZWdpc3Rlci50MCk7CiAgICB2YXIgbW9kaWZpZXJzID0gbnVsbDsKCiAgICBpZiAob3BlcmF0aW9ucykgewogICAgICBtb2RpZmllcnMgPSBvcGVyYXRpb25zLmZsdXNoKHZtKTsKICAgICAgdm0ubG9hZFZhbHVlKF92bTIuUmVnaXN0ZXIudDAsIG51bGwpOwogICAgfQoKICAgIHZtLmVsZW1lbnRzKCkuZmx1c2hFbGVtZW50KG1vZGlmaWVycyk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDM5CiAgLyogQ2xvc2VFbGVtZW50ICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBtb2RpZmllcnMgPSB2bS5lbGVtZW50cygpLmNsb3NlRWxlbWVudCgpOwoKICAgIGlmIChtb2RpZmllcnMpIHsKICAgICAgbW9kaWZpZXJzLmZvckVhY2goZnVuY3Rpb24gKF9yZWYyNikgewogICAgICAgIHZhciBtYW5hZ2VyID0gX3JlZjI2WzBdLAogICAgICAgICAgICBtb2RpZmllciA9IF9yZWYyNlsxXTsKICAgICAgICB2bS5lbnYuc2NoZWR1bGVJbnN0YWxsTW9kaWZpZXIobW9kaWZpZXIsIG1hbmFnZXIpOwogICAgICAgIHZhciBkZXN0cnVjdG9yID0gbWFuYWdlci5nZXREZXN0cnVjdG9yKG1vZGlmaWVyKTsKCiAgICAgICAgaWYgKGRlc3RydWN0b3IpIHsKICAgICAgICAgIHZtLm5ld0Rlc3Ryb3lhYmxlKGRlc3RydWN0b3IpOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDQwCiAgLyogTW9kaWZpZXIgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjI3KSB7CiAgICB2YXIgaGFuZGxlID0gX3JlZjI3Lm9wMTsKCiAgICB2YXIgX3ZtJGNvbnN0YW50cyRyZXNvbHZlID0gdm0uY29uc3RhbnRzLnJlc29sdmVIYW5kbGUoaGFuZGxlKSwKICAgICAgICBtYW5hZ2VyID0gX3ZtJGNvbnN0YW50cyRyZXNvbHZlLm1hbmFnZXIsCiAgICAgICAgc3RhdGUgPSBfdm0kY29uc3RhbnRzJHJlc29sdmUuc3RhdGU7CgogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgYXJncyA9IHN0YWNrLnBvcCgpOwoKICAgIHZhciBfdm0kZWxlbWVudHMgPSB2bS5lbGVtZW50cygpLAogICAgICAgIGNvbnN0cnVjdGluZyA9IF92bSRlbGVtZW50cy5jb25zdHJ1Y3RpbmcsCiAgICAgICAgdXBkYXRlT3BlcmF0aW9ucyA9IF92bSRlbGVtZW50cy51cGRhdGVPcGVyYXRpb25zOwoKICAgIHZhciBkeW5hbWljU2NvcGUgPSB2bS5keW5hbWljU2NvcGUoKTsKICAgIHZhciBtb2RpZmllciA9IG1hbmFnZXIuY3JlYXRlKGNvbnN0cnVjdGluZywgc3RhdGUsIGFyZ3MsIGR5bmFtaWNTY29wZSwgdXBkYXRlT3BlcmF0aW9ucyk7CiAgICB2YXIgb3BlcmF0aW9ucyA9IHZtLmZldGNoVmFsdWUoX3ZtMi5SZWdpc3Rlci50MCk7CiAgICBvcGVyYXRpb25zLmFkZE1vZGlmaWVyKG1hbmFnZXIsIG1vZGlmaWVyKTsKICAgIHZhciB0YWcgPSBtYW5hZ2VyLmdldFRhZyhtb2RpZmllcik7CgogICAgaWYgKCEoMCwgX3JlZmVyZW5jZTIuaXNDb25zdFRhZykodGFnKSkgewogICAgICB2bS51cGRhdGVXaXRoKG5ldyBVcGRhdGVNb2RpZmllck9wY29kZSh0YWcsIG1hbmFnZXIsIG1vZGlmaWVyKSk7CiAgICB9CiAgfSk7CgogIHZhciBVcGRhdGVNb2RpZmllck9wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfVXBkYXRpbmdPcGNvZGU1KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoVXBkYXRlTW9kaWZpZXJPcGNvZGUsIF9VcGRhdGluZ09wY29kZTUpOwoKICAgIGZ1bmN0aW9uIFVwZGF0ZU1vZGlmaWVyT3Bjb2RlKHRhZywgbWFuYWdlciwgbW9kaWZpZXIpIHsKICAgICAgdmFyIF90aGlzODsKCiAgICAgIF90aGlzOCA9IF9VcGRhdGluZ09wY29kZTUuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczgudGFnID0gdGFnOwogICAgICBfdGhpczgubWFuYWdlciA9IG1hbmFnZXI7CiAgICAgIF90aGlzOC5tb2RpZmllciA9IG1vZGlmaWVyOwogICAgICBfdGhpczgudHlwZSA9ICd1cGRhdGUtbW9kaWZpZXInOwogICAgICBfdGhpczgubGFzdFVwZGF0ZWQgPSAoMCwgX3JlZmVyZW5jZTIudmFsdWUpKHRhZyk7CiAgICAgIHJldHVybiBfdGhpczg7CiAgICB9CgogICAgdmFyIF9wcm90bzE0ID0gVXBkYXRlTW9kaWZpZXJPcGNvZGUucHJvdG90eXBlOwoKICAgIF9wcm90bzE0LmV2YWx1YXRlID0gZnVuY3Rpb24gZXZhbHVhdGUodm0pIHsKICAgICAgdmFyIG1hbmFnZXIgPSB0aGlzLm1hbmFnZXIsCiAgICAgICAgICBtb2RpZmllciA9IHRoaXMubW9kaWZpZXIsCiAgICAgICAgICB0YWcgPSB0aGlzLnRhZywKICAgICAgICAgIGxhc3RVcGRhdGVkID0gdGhpcy5sYXN0VXBkYXRlZDsKCiAgICAgIGlmICghKDAsIF9yZWZlcmVuY2UyLnZhbGlkYXRlKSh0YWcsIGxhc3RVcGRhdGVkKSkgewogICAgICAgIHZtLmVudi5zY2hlZHVsZVVwZGF0ZU1vZGlmaWVyKG1vZGlmaWVyLCBtYW5hZ2VyKTsKICAgICAgICB0aGlzLmxhc3RVcGRhdGVkID0gKDAsIF9yZWZlcmVuY2UyLnZhbHVlKSh0YWcpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBVcGRhdGVNb2RpZmllck9wY29kZTsKICB9KFVwZGF0aW5nT3Bjb2RlKTsKCiAgQVBQRU5EX09QQ09ERVMuYWRkKDM1CiAgLyogU3RhdGljQXR0ciAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMjgpIHsKICAgIHZhciBfbmFtZSA9IF9yZWYyOC5vcDEsCiAgICAgICAgX3ZhbHVlID0gX3JlZjI4Lm9wMiwKICAgICAgICBfbmFtZXNwYWNlID0gX3JlZjI4Lm9wMzsKICAgIHZhciBuYW1lID0gdm0uY29uc3RhbnRzLmdldFN0cmluZyhfbmFtZSk7CiAgICB2YXIgdmFsdWUkJDEgPSB2bS5jb25zdGFudHMuZ2V0U3RyaW5nKF92YWx1ZSk7CiAgICB2YXIgbmFtZXNwYWNlID0gX25hbWVzcGFjZSA/IHZtLmNvbnN0YW50cy5nZXRTdHJpbmcoX25hbWVzcGFjZSkgOiBudWxsOwogICAgdm0uZWxlbWVudHMoKS5zZXRTdGF0aWNBdHRyaWJ1dGUobmFtZSwgdmFsdWUkJDEsIG5hbWVzcGFjZSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDM2CiAgLyogRHluYW1pY0F0dHIgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjI5KSB7CiAgICB2YXIgX25hbWUgPSBfcmVmMjkub3AxLAogICAgICAgIHRydXN0aW5nID0gX3JlZjI5Lm9wMiwKICAgICAgICBfbmFtZXNwYWNlID0gX3JlZjI5Lm9wMzsKICAgIHZhciBuYW1lID0gdm0uY29uc3RhbnRzLmdldFN0cmluZyhfbmFtZSk7CiAgICB2YXIgcmVmZXJlbmNlID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgdmFsdWUkJDEgPSByZWZlcmVuY2UudmFsdWUoKTsKICAgIHZhciBuYW1lc3BhY2UgPSBfbmFtZXNwYWNlID8gdm0uY29uc3RhbnRzLmdldFN0cmluZyhfbmFtZXNwYWNlKSA6IG51bGw7CiAgICB2YXIgYXR0cmlidXRlID0gdm0uZWxlbWVudHMoKS5zZXREeW5hbWljQXR0cmlidXRlKG5hbWUsIHZhbHVlJCQxLCAhIXRydXN0aW5nLCBuYW1lc3BhY2UpOwoKICAgIGlmICghKDAsIF9yZWZlcmVuY2UyLmlzQ29uc3QpKHJlZmVyZW5jZSkpIHsKICAgICAgdm0udXBkYXRlV2l0aChuZXcgVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZShyZWZlcmVuY2UsIGF0dHJpYnV0ZSkpOwogICAgfQogIH0pOwoKICB2YXIgVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfVXBkYXRpbmdPcGNvZGU2KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZSwgX1VwZGF0aW5nT3Bjb2RlNik7CgogICAgZnVuY3Rpb24gVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZShyZWZlcmVuY2UsIGF0dHJpYnV0ZSkgewogICAgICB2YXIgX3RoaXM5OwoKICAgICAgX3RoaXM5ID0gX1VwZGF0aW5nT3Bjb2RlNi5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzOS5yZWZlcmVuY2UgPSByZWZlcmVuY2U7CiAgICAgIF90aGlzOS5hdHRyaWJ1dGUgPSBhdHRyaWJ1dGU7CiAgICAgIF90aGlzOS50eXBlID0gJ3BhdGNoLWVsZW1lbnQnOwogICAgICB2YXIgdGFnID0gcmVmZXJlbmNlLnRhZzsKICAgICAgX3RoaXM5LnRhZyA9IHRhZzsKICAgICAgX3RoaXM5Lmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlMi52YWx1ZSkodGFnKTsKICAgICAgcmV0dXJuIF90aGlzOTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTUgPSBVcGRhdGVEeW5hbWljQXR0cmlidXRlT3Bjb2RlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xNS5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKHZtKSB7CiAgICAgIHZhciBhdHRyaWJ1dGUgPSB0aGlzLmF0dHJpYnV0ZSwKICAgICAgICAgIHJlZmVyZW5jZSA9IHRoaXMucmVmZXJlbmNlLAogICAgICAgICAgdGFnID0gdGhpcy50YWc7CgogICAgICBpZiAoISgwLCBfcmVmZXJlbmNlMi52YWxpZGF0ZSkodGFnLCB0aGlzLmxhc3RSZXZpc2lvbikpIHsKICAgICAgICB0aGlzLmxhc3RSZXZpc2lvbiA9ICgwLCBfcmVmZXJlbmNlMi52YWx1ZSkodGFnKTsKICAgICAgICBhdHRyaWJ1dGUudXBkYXRlKHJlZmVyZW5jZS52YWx1ZSgpLCB2bS5lbnYpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBVcGRhdGVEeW5hbWljQXR0cmlidXRlT3Bjb2RlOwogIH0oVXBkYXRpbmdPcGNvZGUpOwoKICBmdW5jdGlvbiByZXNvbHZlQ29tcG9uZW50KHJlc29sdmVyLCBuYW1lLCBtZXRhKSB7CiAgICB2YXIgZGVmaW5pdGlvbiA9IHJlc29sdmVyLmxvb2t1cENvbXBvbmVudERlZmluaXRpb24obmFtZSwgbWV0YSk7CiAgICByZXR1cm4gZGVmaW5pdGlvbjsKICB9CgogIHZhciBDdXJyeUNvbXBvbmVudFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEN1cnJ5Q29tcG9uZW50UmVmZXJlbmNlKGlubmVyLCByZXNvbHZlciwgbWV0YSwgYXJncykgewogICAgICB0aGlzLmlubmVyID0gaW5uZXI7CiAgICAgIHRoaXMucmVzb2x2ZXIgPSByZXNvbHZlcjsKICAgICAgdGhpcy5tZXRhID0gbWV0YTsKICAgICAgdGhpcy5hcmdzID0gYXJnczsKICAgICAgdGhpcy50YWcgPSBpbm5lci50YWc7CiAgICAgIHRoaXMubGFzdFZhbHVlID0gbnVsbDsKICAgICAgdGhpcy5sYXN0RGVmaW5pdGlvbiA9IG51bGw7CiAgICB9CgogICAgdmFyIF9wcm90bzE2ID0gQ3VycnlDb21wb25lbnRSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzE2LnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHZhciBpbm5lciA9IHRoaXMuaW5uZXIsCiAgICAgICAgICBsYXN0VmFsdWUgPSB0aGlzLmxhc3RWYWx1ZTsKICAgICAgdmFyIHZhbHVlJCQxID0gaW5uZXIudmFsdWUoKTsKCiAgICAgIGlmICh2YWx1ZSQkMSA9PT0gbGFzdFZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHRoaXMubGFzdERlZmluaXRpb247CiAgICAgIH0KCiAgICAgIHZhciBkZWZpbml0aW9uID0gbnVsbDsKCiAgICAgIGlmIChpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKHZhbHVlJCQxKSkgewogICAgICAgIGRlZmluaXRpb24gPSB2YWx1ZSQkMTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUkJDEgPT09ICdzdHJpbmcnICYmIHZhbHVlJCQxKSB7CiAgICAgICAgdmFyIHJlc29sdmVyID0gdGhpcy5yZXNvbHZlciwKICAgICAgICAgICAgbWV0YSA9IHRoaXMubWV0YTsKICAgICAgICBkZWZpbml0aW9uID0gcmVzb2x2ZUNvbXBvbmVudChyZXNvbHZlciwgdmFsdWUkJDEsIG1ldGEpOwogICAgICB9CgogICAgICBkZWZpbml0aW9uID0gdGhpcy5jdXJyeShkZWZpbml0aW9uKTsKICAgICAgdGhpcy5sYXN0VmFsdWUgPSB2YWx1ZSQkMTsKICAgICAgdGhpcy5sYXN0RGVmaW5pdGlvbiA9IGRlZmluaXRpb247CiAgICAgIHJldHVybiBkZWZpbml0aW9uOwogICAgfTsKCiAgICBfcHJvdG8xNi5nZXQgPSBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBVTkRFRklORURfUkVGRVJFTkNFOwogICAgfTsKCiAgICBfcHJvdG8xNi5jdXJyeSA9IGZ1bmN0aW9uIGN1cnJ5KGRlZmluaXRpb24pIHsKICAgICAgdmFyIGFyZ3MgPSB0aGlzLmFyZ3M7CgogICAgICBpZiAoIWFyZ3MgJiYgaXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbihkZWZpbml0aW9uKSkgewogICAgICAgIHJldHVybiBkZWZpbml0aW9uOwogICAgICB9IGVsc2UgaWYgKCFkZWZpbml0aW9uKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyBDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbihkZWZpbml0aW9uLCBhcmdzKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gQ3VycnlDb21wb25lbnRSZWZlcmVuY2U7CiAgfSgpOwoKICB2YXIgQ2xhc3NMaXN0UmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ2xhc3NMaXN0UmVmZXJlbmNlKGxpc3QpIHsKICAgICAgdGhpcy5saXN0ID0gbGlzdDsKICAgICAgdGhpcy50YWcgPSAoMCwgX3JlZmVyZW5jZTIuY29tYmluZVRhZ2dlZCkobGlzdCk7CiAgICAgIHRoaXMubGlzdCA9IGxpc3Q7CiAgICB9CgogICAgdmFyIF9wcm90bzE3ID0gQ2xhc3NMaXN0UmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8xNy52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICB2YXIgcmV0ID0gW107CiAgICAgIHZhciBsaXN0ID0gdGhpcy5saXN0OwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIHZhbHVlJCQxID0gbm9ybWFsaXplU3RyaW5nVmFsdWUobGlzdFtpXS52YWx1ZSgpKTsKICAgICAgICBpZiAodmFsdWUkJDEpIHJldC5wdXNoKHZhbHVlJCQxKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJldC5sZW5ndGggPT09IDAgPyBudWxsIDogcmV0LmpvaW4oJyAnKTsKICAgIH07CgogICAgcmV0dXJuIENsYXNzTGlzdFJlZmVyZW5jZTsKICB9KCk7CiAgLyoqCiAgICogQ29udmVydHMgYSBDb21wb25lbnRDYXBhYmlsaXRpZXMgb2JqZWN0IGludG8gYSAzMi1iaXQgaW50ZWdlciByZXByZXNlbnRhdGlvbi4KICAgKi8KCgogIGZ1bmN0aW9uIGNhcGFiaWxpdHlGbGFnc0Zyb20oY2FwYWJpbGl0aWVzKSB7CiAgICByZXR1cm4gMCB8IChjYXBhYmlsaXRpZXMuZHluYW1pY0xheW91dCA/IDEKICAgIC8qIER5bmFtaWNMYXlvdXQgKi8KICAgIDogMCkgfCAoY2FwYWJpbGl0aWVzLmR5bmFtaWNUYWcgPyAyCiAgICAvKiBEeW5hbWljVGFnICovCiAgICA6IDApIHwgKGNhcGFiaWxpdGllcy5wcmVwYXJlQXJncyA/IDQKICAgIC8qIFByZXBhcmVBcmdzICovCiAgICA6IDApIHwgKGNhcGFiaWxpdGllcy5jcmVhdGVBcmdzID8gOAogICAgLyogQ3JlYXRlQXJncyAqLwogICAgOiAwKSB8IChjYXBhYmlsaXRpZXMuYXR0cmlidXRlSG9vayA/IDE2CiAgICAvKiBBdHRyaWJ1dGVIb29rICovCiAgICA6IDApIHwgKGNhcGFiaWxpdGllcy5lbGVtZW50SG9vayA/IDMyCiAgICAvKiBFbGVtZW50SG9vayAqLwogICAgOiAwKSB8IChjYXBhYmlsaXRpZXMuZHluYW1pY1Njb3BlID8gNjQKICAgIC8qIER5bmFtaWNTY29wZSAqLwogICAgOiAwKSB8IChjYXBhYmlsaXRpZXMuY3JlYXRlQ2FsbGVyID8gMTI4CiAgICAvKiBDcmVhdGVDYWxsZXIgKi8KICAgIDogMCkgfCAoY2FwYWJpbGl0aWVzLnVwZGF0ZUhvb2sgPyAyNTYKICAgIC8qIFVwZGF0ZUhvb2sgKi8KICAgIDogMCkgfCAoY2FwYWJpbGl0aWVzLmNyZWF0ZUluc3RhbmNlID8gNTEyCiAgICAvKiBDcmVhdGVJbnN0YW5jZSAqLwogICAgOiAwKTsKICB9CgogIGZ1bmN0aW9uIGhhc0NhcGFiaWxpdHkoY2FwYWJpbGl0aWVzLCBjYXBhYmlsaXR5KSB7CiAgICByZXR1cm4gISEoY2FwYWJpbGl0aWVzICYgY2FwYWJpbGl0eSk7CiAgfQoKICBBUFBFTkRfT1BDT0RFUy5hZGQoNjkKICAvKiBJc0NvbXBvbmVudCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciByZWYgPSBzdGFjay5wb3AoKTsKICAgIHN0YWNrLnB1c2goSXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvblJlZmVyZW5jZS5jcmVhdGUocmVmKSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDcwCiAgLyogQ29udGVudFR5cGUgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgcmVmID0gc3RhY2sucGVlaygpOwogICAgc3RhY2sucHVzaChuZXcgQ29udGVudFR5cGVSZWZlcmVuY2UocmVmKSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDcxCiAgLyogQ3VycnlDb21wb25lbnQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjMwKSB7CiAgICB2YXIgX21ldGEgPSBfcmVmMzAub3AxOwogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgZGVmaW5pdGlvbiA9IHN0YWNrLnBvcCgpOwogICAgdmFyIGNhcHR1cmVkQXJncyA9IHN0YWNrLnBvcCgpOwogICAgdmFyIG1ldGEgPSB2bS5jb25zdGFudHMuZ2V0U2VyaWFsaXphYmxlKF9tZXRhKTsKICAgIHZhciByZXNvbHZlciA9IHZtLmNvbnN0YW50cy5yZXNvbHZlcjsKICAgIHZtLmxvYWRWYWx1ZShfdm0yLlJlZ2lzdGVyLnYwLCBuZXcgQ3VycnlDb21wb25lbnRSZWZlcmVuY2UoZGVmaW5pdGlvbiwgcmVzb2x2ZXIsIG1ldGEsIGNhcHR1cmVkQXJncykpOyAvLyBleHBlY3RTdGFja0NoYW5nZSh2bS5zdGFjaywgLWFyZ3MubGVuZ3RoIC0gMSwgJ0N1cnJ5Q29tcG9uZW50Jyk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDcyCiAgLyogUHVzaENvbXBvbmVudERlZmluaXRpb24gKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjMxKSB7CiAgICB2YXIgaGFuZGxlID0gX3JlZjMxLm9wMTsKICAgIHZhciBkZWZpbml0aW9uID0gdm0uY29uc3RhbnRzLnJlc29sdmVIYW5kbGUoaGFuZGxlKTsKICAgIHZhciBtYW5hZ2VyID0gZGVmaW5pdGlvbi5tYW5hZ2VyOwogICAgdmFyIGNhcGFiaWxpdGllcyA9IGNhcGFiaWxpdHlGbGFnc0Zyb20obWFuYWdlci5nZXRDYXBhYmlsaXRpZXMoZGVmaW5pdGlvbi5zdGF0ZSkpOwogICAgdmFyIGluc3RhbmNlID0gewogICAgICBkZWZpbml0aW9uOiBkZWZpbml0aW9uLAogICAgICBtYW5hZ2VyOiBtYW5hZ2VyLAogICAgICBjYXBhYmlsaXRpZXM6IGNhcGFiaWxpdGllcywKICAgICAgc3RhdGU6IG51bGwsCiAgICAgIGhhbmRsZTogbnVsbCwKICAgICAgdGFibGU6IG51bGwsCiAgICAgIGxvb2t1cDogbnVsbAogICAgfTsKICAgIHZtLnN0YWNrLnB1c2goaW5zdGFuY2UpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg3NQogIC8qIFJlc29sdmVEeW5hbWljQ29tcG9uZW50ICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYzMikgewogICAgdmFyIF9tZXRhID0gX3JlZjMyLm9wMTsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIGNvbXBvbmVudCA9IHN0YWNrLnBvcCgpLnZhbHVlKCk7CiAgICB2YXIgbWV0YSA9IHZtLmNvbnN0YW50cy5nZXRTZXJpYWxpemFibGUoX21ldGEpOwogICAgdm0ubG9hZFZhbHVlKF92bTIuUmVnaXN0ZXIudDEsIG51bGwpOyAvLyBDbGVhciB0aGUgdGVtcCByZWdpc3RlcgoKICAgIHZhciBkZWZpbml0aW9uOwoKICAgIGlmICh0eXBlb2YgY29tcG9uZW50ID09PSAnc3RyaW5nJykgewogICAgICB2YXIgcmVzb2x2ZXIgPSB2bS5jb25zdGFudHMucmVzb2x2ZXI7CiAgICAgIHZhciByZXNvbHZlZERlZmluaXRpb24gPSByZXNvbHZlQ29tcG9uZW50KHJlc29sdmVyLCBjb21wb25lbnQsIG1ldGEpOwogICAgICBkZWZpbml0aW9uID0gcmVzb2x2ZWREZWZpbml0aW9uOwogICAgfSBlbHNlIGlmIChpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGNvbXBvbmVudCkpIHsKICAgICAgZGVmaW5pdGlvbiA9IGNvbXBvbmVudDsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoKTsKICAgIH0KCiAgICBzdGFjay5wdXNoKGRlZmluaXRpb24pOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg3MwogIC8qIFB1c2hEeW5hbWljQ29tcG9uZW50SW5zdGFuY2UgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgZGVmaW5pdGlvbiA9IHN0YWNrLnBvcCgpOwogICAgdmFyIGNhcGFiaWxpdGllcywgbWFuYWdlcjsKCiAgICBpZiAoaXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbihkZWZpbml0aW9uKSkgewogICAgICBtYW5hZ2VyID0gY2FwYWJpbGl0aWVzID0gbnVsbDsKICAgIH0gZWxzZSB7CiAgICAgIG1hbmFnZXIgPSBkZWZpbml0aW9uLm1hbmFnZXI7CiAgICAgIGNhcGFiaWxpdGllcyA9IGNhcGFiaWxpdHlGbGFnc0Zyb20obWFuYWdlci5nZXRDYXBhYmlsaXRpZXMoZGVmaW5pdGlvbi5zdGF0ZSkpOwogICAgfQoKICAgIHN0YWNrLnB1c2goewogICAgICBkZWZpbml0aW9uOiBkZWZpbml0aW9uLAogICAgICBjYXBhYmlsaXRpZXM6IGNhcGFiaWxpdGllcywKICAgICAgbWFuYWdlcjogbWFuYWdlciwKICAgICAgc3RhdGU6IG51bGwsCiAgICAgIGhhbmRsZTogbnVsbCwKICAgICAgdGFibGU6IG51bGwKICAgIH0pOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg3NAogIC8qIFB1c2hDdXJyaWVkQ29tcG9uZW50ICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYzMykgewogICAgKDAsIF9lbWJlckJhYmVsLm9iamVjdERlc3RydWN0dXJpbmdFbXB0eSkoX3JlZjMzKTsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIGNvbXBvbmVudCA9IHN0YWNrLnBvcCgpLnZhbHVlKCk7CiAgICB2YXIgZGVmaW5pdGlvbjsKCiAgICBpZiAoaXNDdXJyaWVkQ29tcG9uZW50RGVmaW5pdGlvbihjb21wb25lbnQpKSB7CiAgICAgIGRlZmluaXRpb24gPSBjb21wb25lbnQ7CiAgICB9IGVsc2UgewogICAgICB0aHJvdyAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCk7CiAgICB9CgogICAgc3RhY2sucHVzaChkZWZpbml0aW9uKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNzYKICAvKiBQdXNoQXJncyAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMzQpIHsKICAgIHZhciBfbmFtZXMgPSBfcmVmMzQub3AxLAogICAgICAgIGZsYWdzID0gX3JlZjM0Lm9wMjsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIG5hbWVzID0gdm0uY29uc3RhbnRzLmdldFN0cmluZ0FycmF5KF9uYW1lcyk7CiAgICB2YXIgcG9zaXRpb25hbENvdW50ID0gZmxhZ3MgPj4gNDsKICAgIHZhciBzeW50aGV0aWMgPSBmbGFncyAmIDg7CiAgICB2YXIgYmxvY2tOYW1lcyA9IFtdOwogICAgaWYgKGZsYWdzICYgNCkgYmxvY2tOYW1lcy5wdXNoKCdtYWluJyk7CiAgICBpZiAoZmxhZ3MgJiAyKSBibG9ja05hbWVzLnB1c2goJ2Vsc2UnKTsKICAgIGlmIChmbGFncyAmIDEpIGJsb2NrTmFtZXMucHVzaCgnYXR0cnMnKTsKICAgIHZtLmFyZ3Muc2V0dXAoc3RhY2ssIG5hbWVzLCBibG9ja05hbWVzLCBwb3NpdGlvbmFsQ291bnQsICEhc3ludGhldGljKTsKICAgIHN0YWNrLnB1c2godm0uYXJncyk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDc3CiAgLyogUHVzaEVtcHR5QXJncyAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHN0YWNrLnB1c2godm0uYXJncy5lbXB0eShzdGFjaykpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4MAogIC8qIENhcHR1cmVBcmdzICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIGFyZ3MgPSBzdGFjay5wb3AoKTsKICAgIHZhciBjYXB0dXJlZEFyZ3MgPSBhcmdzLmNhcHR1cmUoKTsKICAgIHN0YWNrLnB1c2goY2FwdHVyZWRBcmdzKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNzkKICAvKiBQcmVwYXJlQXJncyAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmMzUpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmMzUub3AxOwogICAgdmFyIHN0YWNrID0gdm0uc3RhY2s7CiAgICB2YXIgaW5zdGFuY2UgPSB2bS5mZXRjaFZhbHVlKF9zdGF0ZSk7CiAgICB2YXIgYXJncyA9IHN0YWNrLnBvcCgpOwogICAgdmFyIGRlZmluaXRpb24gPSBpbnN0YW5jZS5kZWZpbml0aW9uOwoKICAgIGlmIChpc0N1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGRlZmluaXRpb24pKSB7CiAgICAgIGRlZmluaXRpb24gPSByZXNvbHZlQ3VycmllZENvbXBvbmVudERlZmluaXRpb24oaW5zdGFuY2UsIGRlZmluaXRpb24sIGFyZ3MpOwogICAgfQoKICAgIHZhciBfZGVmaW5pdGlvbjIgPSBkZWZpbml0aW9uLAogICAgICAgIG1hbmFnZXIgPSBfZGVmaW5pdGlvbjIubWFuYWdlciwKICAgICAgICBzdGF0ZSA9IF9kZWZpbml0aW9uMi5zdGF0ZTsKICAgIHZhciBjYXBhYmlsaXRpZXMgPSBpbnN0YW5jZS5jYXBhYmlsaXRpZXM7CgogICAgaWYgKGhhc0NhcGFiaWxpdHkoY2FwYWJpbGl0aWVzLCA0CiAgICAvKiBQcmVwYXJlQXJncyAqLwogICAgKSAhPT0gdHJ1ZSkgewogICAgICBzdGFjay5wdXNoKGFyZ3MpOwogICAgICByZXR1cm47CiAgICB9CgogICAgdmFyIGJsb2NrcyA9IGFyZ3MuYmxvY2tzLnZhbHVlczsKICAgIHZhciBibG9ja05hbWVzID0gYXJncy5ibG9ja3MubmFtZXM7CiAgICB2YXIgcHJlcGFyZWRBcmdzID0gbWFuYWdlci5wcmVwYXJlQXJncyhzdGF0ZSwgYXJncyk7CgogICAgaWYgKHByZXBhcmVkQXJncykgewogICAgICBhcmdzLmNsZWFyKCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2Nrcy5sZW5ndGg7IGkrKykgewogICAgICAgIHN0YWNrLnB1c2goYmxvY2tzW2ldKTsKICAgICAgfQoKICAgICAgdmFyIHBvc2l0aW9uYWwgPSBwcmVwYXJlZEFyZ3MucG9zaXRpb25hbCwKICAgICAgICAgIG5hbWVkID0gcHJlcGFyZWRBcmdzLm5hbWVkOwogICAgICB2YXIgcG9zaXRpb25hbENvdW50ID0gcG9zaXRpb25hbC5sZW5ndGg7CgogICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgcG9zaXRpb25hbENvdW50OyBfaSsrKSB7CiAgICAgICAgc3RhY2sucHVzaChwb3NpdGlvbmFsW19pXSk7CiAgICAgIH0KCiAgICAgIHZhciBuYW1lcyA9IE9iamVjdC5rZXlzKG5hbWVkKTsKCiAgICAgIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IG5hbWVzLmxlbmd0aDsgX2kyKyspIHsKICAgICAgICBzdGFjay5wdXNoKG5hbWVkW25hbWVzW19pMl1dKTsKICAgICAgfQoKICAgICAgYXJncy5zZXR1cChzdGFjaywgbmFtZXMsIGJsb2NrTmFtZXMsIHBvc2l0aW9uYWxDb3VudCwgdHJ1ZSk7CiAgICB9CgogICAgc3RhY2sucHVzaChhcmdzKTsKICB9KTsKCiAgZnVuY3Rpb24gcmVzb2x2ZUN1cnJpZWRDb21wb25lbnREZWZpbml0aW9uKGluc3RhbmNlLCBkZWZpbml0aW9uLCBhcmdzKSB7CiAgICB2YXIgdW53cmFwcGVkRGVmaW5pdGlvbiA9IGluc3RhbmNlLmRlZmluaXRpb24gPSBkZWZpbml0aW9uLnVud3JhcChhcmdzKTsKICAgIHZhciBtYW5hZ2VyID0gdW53cmFwcGVkRGVmaW5pdGlvbi5tYW5hZ2VyLAogICAgICAgIHN0YXRlID0gdW53cmFwcGVkRGVmaW5pdGlvbi5zdGF0ZTsKICAgIGluc3RhbmNlLm1hbmFnZXIgPSBtYW5hZ2VyOwogICAgaW5zdGFuY2UuY2FwYWJpbGl0aWVzID0gY2FwYWJpbGl0eUZsYWdzRnJvbShtYW5hZ2VyLmdldENhcGFiaWxpdGllcyhzdGF0ZSkpOwogICAgcmV0dXJuIHVud3JhcHBlZERlZmluaXRpb247CiAgfQoKICBBUFBFTkRfT1BDT0RFUy5hZGQoODEKICAvKiBDcmVhdGVDb21wb25lbnQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjM2KSB7CiAgICB2YXIgZmxhZ3MgPSBfcmVmMzYub3AxLAogICAgICAgIF9zdGF0ZSA9IF9yZWYzNi5vcDI7CiAgICB2YXIgaW5zdGFuY2UgPSB2bS5mZXRjaFZhbHVlKF9zdGF0ZSk7CiAgICB2YXIgZGVmaW5pdGlvbiA9IGluc3RhbmNlLmRlZmluaXRpb24sCiAgICAgICAgbWFuYWdlciA9IGluc3RhbmNlLm1hbmFnZXI7CiAgICB2YXIgY2FwYWJpbGl0aWVzID0gaW5zdGFuY2UuY2FwYWJpbGl0aWVzID0gY2FwYWJpbGl0eUZsYWdzRnJvbShtYW5hZ2VyLmdldENhcGFiaWxpdGllcyhkZWZpbml0aW9uLnN0YXRlKSk7CiAgICB2YXIgZHluYW1pY1Njb3BlID0gbnVsbDsKCiAgICBpZiAoaGFzQ2FwYWJpbGl0eShjYXBhYmlsaXRpZXMsIDY0CiAgICAvKiBEeW5hbWljU2NvcGUgKi8KICAgICkpIHsKICAgICAgZHluYW1pY1Njb3BlID0gdm0uZHluYW1pY1Njb3BlKCk7CiAgICB9CgogICAgdmFyIGhhc0RlZmF1bHRCbG9jayA9IGZsYWdzICYgMTsKICAgIHZhciBhcmdzID0gbnVsbDsKCiAgICBpZiAoaGFzQ2FwYWJpbGl0eShjYXBhYmlsaXRpZXMsIDgKICAgIC8qIENyZWF0ZUFyZ3MgKi8KICAgICkpIHsKICAgICAgYXJncyA9IHZtLnN0YWNrLnBlZWsoKTsKICAgIH0KCiAgICB2YXIgc2VsZiA9IG51bGw7CgogICAgaWYgKGhhc0NhcGFiaWxpdHkoY2FwYWJpbGl0aWVzLCAxMjgKICAgIC8qIENyZWF0ZUNhbGxlciAqLwogICAgKSkgewogICAgICBzZWxmID0gdm0uZ2V0U2VsZigpOwogICAgfQoKICAgIHZhciBzdGF0ZSA9IG1hbmFnZXIuY3JlYXRlKHZtLmVudiwgZGVmaW5pdGlvbi5zdGF0ZSwgYXJncywgZHluYW1pY1Njb3BlLCBzZWxmLCAhIWhhc0RlZmF1bHRCbG9jayk7IC8vIFdlIHdhbnQgdG8gcmV1c2UgdGhlIGBzdGF0ZWAgUE9KTyBoZXJlLCBiZWNhdXNlIHdlIGtub3cgdGhhdCB0aGUgb3Bjb2RlcwogICAgLy8gb25seSB0cmFuc2l0aW9uIGF0IGV4YWN0bHkgb25lIHBsYWNlLgoKICAgIGluc3RhbmNlLnN0YXRlID0gc3RhdGU7CiAgICB2YXIgdGFnID0gbWFuYWdlci5nZXRUYWcoc3RhdGUpOwoKICAgIGlmIChoYXNDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgMjU2CiAgICAvKiBVcGRhdGVIb29rICovCiAgICApICYmICEoMCwgX3JlZmVyZW5jZTIuaXNDb25zdFRhZykodGFnKSkgewogICAgICB2bS51cGRhdGVXaXRoKG5ldyBVcGRhdGVDb21wb25lbnRPcGNvZGUodGFnLCBzdGF0ZSwgbWFuYWdlciwgZHluYW1pY1Njb3BlKSk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDgyCiAgLyogUmVnaXN0ZXJDb21wb25lbnREZXN0cnVjdG9yICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYzNykgewogICAgdmFyIF9zdGF0ZSA9IF9yZWYzNy5vcDE7CgogICAgdmFyIF92bSRmZXRjaFZhbHVlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpLAogICAgICAgIG1hbmFnZXIgPSBfdm0kZmV0Y2hWYWx1ZS5tYW5hZ2VyLAogICAgICAgIHN0YXRlID0gX3ZtJGZldGNoVmFsdWUuc3RhdGU7CgogICAgdmFyIGRlc3RydWN0b3IgPSBtYW5hZ2VyLmdldERlc3RydWN0b3Ioc3RhdGUpOwogICAgaWYgKGRlc3RydWN0b3IpIHZtLm5ld0Rlc3Ryb3lhYmxlKGRlc3RydWN0b3IpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg5MQogIC8qIEJlZ2luQ29tcG9uZW50VHJhbnNhY3Rpb24gKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdm0uYmVnaW5DYWNoZUdyb3VwKCk7CiAgICB2bS5lbGVtZW50cygpLnB1c2hTaW1wbGVCbG9jaygpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4MwogIC8qIFB1dENvbXBvbmVudE9wZXJhdGlvbnMgKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdm0ubG9hZFZhbHVlKF92bTIuUmVnaXN0ZXIudDAsIG5ldyBDb21wb25lbnRFbGVtZW50T3BlcmF0aW9ucygpKTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMzcKICAvKiBDb21wb25lbnRBdHRyICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWYzOCkgewogICAgdmFyIF9uYW1lID0gX3JlZjM4Lm9wMSwKICAgICAgICB0cnVzdGluZyA9IF9yZWYzOC5vcDIsCiAgICAgICAgX25hbWVzcGFjZSA9IF9yZWYzOC5vcDM7CiAgICB2YXIgbmFtZSA9IHZtLmNvbnN0YW50cy5nZXRTdHJpbmcoX25hbWUpOwogICAgdmFyIHJlZmVyZW5jZSA9IHZtLnN0YWNrLnBvcCgpOwogICAgdmFyIG5hbWVzcGFjZSA9IF9uYW1lc3BhY2UgPyB2bS5jb25zdGFudHMuZ2V0U3RyaW5nKF9uYW1lc3BhY2UpIDogbnVsbDsKICAgIHZtLmZldGNoVmFsdWUoX3ZtMi5SZWdpc3Rlci50MCkuc2V0QXR0cmlidXRlKG5hbWUsIHJlZmVyZW5jZSwgISF0cnVzdGluZywgbmFtZXNwYWNlKTsKICB9KTsKCiAgdmFyIENvbXBvbmVudEVsZW1lbnRPcGVyYXRpb25zID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ29tcG9uZW50RWxlbWVudE9wZXJhdGlvbnMoKSB7CiAgICAgIHRoaXMuYXR0cmlidXRlcyA9ICgwLCBfdXRpbC5kaWN0KSgpOwogICAgICB0aGlzLmNsYXNzZXMgPSBbXTsKICAgICAgdGhpcy5tb2RpZmllcnMgPSBbXTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMTggPSBDb21wb25lbnRFbGVtZW50T3BlcmF0aW9ucy5wcm90b3R5cGU7CgogICAgX3Byb3RvMTguc2V0QXR0cmlidXRlID0gZnVuY3Rpb24gc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlJCQxLCB0cnVzdGluZywgbmFtZXNwYWNlKSB7CiAgICAgIHZhciBkZWZlcnJlZCA9IHsKICAgICAgICB2YWx1ZTogdmFsdWUkJDEsCiAgICAgICAgbmFtZXNwYWNlOiBuYW1lc3BhY2UsCiAgICAgICAgdHJ1c3Rpbmc6IHRydXN0aW5nCiAgICAgIH07CgogICAgICBpZiAobmFtZSA9PT0gJ2NsYXNzJykgewogICAgICAgIHRoaXMuY2xhc3Nlcy5wdXNoKHZhbHVlJCQxKTsKICAgICAgfQoKICAgICAgdGhpcy5hdHRyaWJ1dGVzW25hbWVdID0gZGVmZXJyZWQ7CiAgICB9OwoKICAgIF9wcm90bzE4LmFkZE1vZGlmaWVyID0gZnVuY3Rpb24gYWRkTW9kaWZpZXIobWFuYWdlciwgbW9kaWZpZXIpIHsKICAgICAgdGhpcy5tb2RpZmllcnMucHVzaChbbWFuYWdlciwgbW9kaWZpZXJdKTsKICAgIH07CgogICAgX3Byb3RvMTguZmx1c2ggPSBmdW5jdGlvbiBmbHVzaCh2bSkgewogICAgICBmb3IgKHZhciBuYW1lIGluIHRoaXMuYXR0cmlidXRlcykgewogICAgICAgIHZhciBhdHRyID0gdGhpcy5hdHRyaWJ1dGVzW25hbWVdOwogICAgICAgIHZhciByZWZlcmVuY2UgPSBhdHRyLnZhbHVlLAogICAgICAgICAgICBuYW1lc3BhY2UgPSBhdHRyLm5hbWVzcGFjZSwKICAgICAgICAgICAgdHJ1c3RpbmcgPSBhdHRyLnRydXN0aW5nOwoKICAgICAgICBpZiAobmFtZSA9PT0gJ2NsYXNzJykgewogICAgICAgICAgcmVmZXJlbmNlID0gbmV3IENsYXNzTGlzdFJlZmVyZW5jZSh0aGlzLmNsYXNzZXMpOwogICAgICAgIH0KCiAgICAgICAgaWYgKG5hbWUgPT09ICd0eXBlJykgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICB2YXIgYXR0cmlidXRlID0gdm0uZWxlbWVudHMoKS5zZXREeW5hbWljQXR0cmlidXRlKG5hbWUsIHJlZmVyZW5jZS52YWx1ZSgpLCB0cnVzdGluZywgbmFtZXNwYWNlKTsKCiAgICAgICAgaWYgKCEoMCwgX3JlZmVyZW5jZTIuaXNDb25zdCkocmVmZXJlbmNlKSkgewogICAgICAgICAgdm0udXBkYXRlV2l0aChuZXcgVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZShyZWZlcmVuY2UsIGF0dHJpYnV0ZSkpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKCd0eXBlJyBpbiB0aGlzLmF0dHJpYnV0ZXMpIHsKICAgICAgICB2YXIgdHlwZSA9IHRoaXMuYXR0cmlidXRlcy50eXBlOwogICAgICAgIHZhciBfcmVmZXJlbmNlID0gdHlwZS52YWx1ZSwKICAgICAgICAgICAgX25hbWVzcGFjZTIgPSB0eXBlLm5hbWVzcGFjZSwKICAgICAgICAgICAgX3RydXN0aW5nID0gdHlwZS50cnVzdGluZzsKCiAgICAgICAgdmFyIF9hdHRyaWJ1dGUgPSB2bS5lbGVtZW50cygpLnNldER5bmFtaWNBdHRyaWJ1dGUoJ3R5cGUnLCBfcmVmZXJlbmNlLnZhbHVlKCksIF90cnVzdGluZywgX25hbWVzcGFjZTIpOwoKICAgICAgICBpZiAoISgwLCBfcmVmZXJlbmNlMi5pc0NvbnN0KShfcmVmZXJlbmNlKSkgewogICAgICAgICAgdm0udXBkYXRlV2l0aChuZXcgVXBkYXRlRHluYW1pY0F0dHJpYnV0ZU9wY29kZShfcmVmZXJlbmNlLCBfYXR0cmlidXRlKSk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5tb2RpZmllcnM7CiAgICB9OwoKICAgIHJldHVybiBDb21wb25lbnRFbGVtZW50T3BlcmF0aW9uczsKICB9KCk7CgogIEFQUEVORF9PUENPREVTLmFkZCg5MwogIC8qIERpZENyZWF0ZUVsZW1lbnQgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjM5KSB7CiAgICB2YXIgX3N0YXRlID0gX3JlZjM5Lm9wMTsKCiAgICB2YXIgX3ZtJGZldGNoVmFsdWUyID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpLAogICAgICAgIGRlZmluaXRpb24gPSBfdm0kZmV0Y2hWYWx1ZTIuZGVmaW5pdGlvbiwKICAgICAgICBzdGF0ZSA9IF92bSRmZXRjaFZhbHVlMi5zdGF0ZTsKCiAgICB2YXIgbWFuYWdlciA9IGRlZmluaXRpb24ubWFuYWdlcjsKICAgIHZhciBvcGVyYXRpb25zID0gdm0uZmV0Y2hWYWx1ZShfdm0yLlJlZ2lzdGVyLnQwKTsKICAgIHZhciBhY3Rpb24gPSAnRGlkQ3JlYXRlRWxlbWVudE9wY29kZSNldmFsdWF0ZSc7CiAgICBtYW5hZ2VyLmRpZENyZWF0ZUVsZW1lbnQoc3RhdGUsIHZtLmVsZW1lbnRzKCkuZXhwZWN0Q29uc3RydWN0aW5nKGFjdGlvbiksIG9wZXJhdGlvbnMpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4NAogIC8qIEdldENvbXBvbmVudFNlbGYgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjQwKSB7CiAgICB2YXIgX3N0YXRlID0gX3JlZjQwLm9wMTsKCiAgICB2YXIgX3ZtJGZldGNoVmFsdWUzID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpLAogICAgICAgIGRlZmluaXRpb24gPSBfdm0kZmV0Y2hWYWx1ZTMuZGVmaW5pdGlvbiwKICAgICAgICBzdGF0ZSA9IF92bSRmZXRjaFZhbHVlMy5zdGF0ZTsKCiAgICB2YXIgbWFuYWdlciA9IGRlZmluaXRpb24ubWFuYWdlcjsKICAgIHZtLnN0YWNrLnB1c2gobWFuYWdlci5nZXRTZWxmKHN0YXRlKSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDg1CiAgLyogR2V0Q29tcG9uZW50VGFnTmFtZSAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNDEpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNDEub3AxOwoKICAgIHZhciBfdm0kZmV0Y2hWYWx1ZTQgPSB2bS5mZXRjaFZhbHVlKF9zdGF0ZSksCiAgICAgICAgZGVmaW5pdGlvbiA9IF92bSRmZXRjaFZhbHVlNC5kZWZpbml0aW9uLAogICAgICAgIHN0YXRlID0gX3ZtJGZldGNoVmFsdWU0LnN0YXRlOwoKICAgIHZhciBtYW5hZ2VyID0gZGVmaW5pdGlvbi5tYW5hZ2VyOwogICAgdm0uc3RhY2sucHVzaChtYW5hZ2VyLmdldFRhZ05hbWUoc3RhdGUpKTsKICB9KTsgLy8gRHluYW1pYyBJbnZvY2F0aW9uIE9ubHkKCiAgQVBQRU5EX09QQ09ERVMuYWRkKDg2CiAgLyogR2V0Q29tcG9uZW50TGF5b3V0ICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY0MikgewogICAgdmFyIF9zdGF0ZSA9IF9yZWY0Mi5vcDE7CiAgICB2YXIgaW5zdGFuY2UgPSB2bS5mZXRjaFZhbHVlKF9zdGF0ZSk7CiAgICB2YXIgbWFuYWdlciA9IGluc3RhbmNlLm1hbmFnZXIsCiAgICAgICAgZGVmaW5pdGlvbiA9IGluc3RhbmNlLmRlZmluaXRpb247CiAgICB2YXIgcmVzb2x2ZXIgPSB2bS5jb25zdGFudHMucmVzb2x2ZXIsCiAgICAgICAgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciBpbnN0YW5jZVN0YXRlID0gaW5zdGFuY2Uuc3RhdGUsCiAgICAgICAgY2FwYWJpbGl0aWVzID0gaW5zdGFuY2UuY2FwYWJpbGl0aWVzOwogICAgdmFyIGRlZmluaXRpb25TdGF0ZSA9IGRlZmluaXRpb24uc3RhdGU7CiAgICB2YXIgaW52b2tlOwoKICAgIGlmIChoYXNTdGF0aWNMYXlvdXRDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgbWFuYWdlcikpIHsKICAgICAgaW52b2tlID0gbWFuYWdlci5nZXRMYXlvdXQoZGVmaW5pdGlvblN0YXRlLCByZXNvbHZlcik7CiAgICB9IGVsc2UgaWYgKGhhc0R5bmFtaWNMYXlvdXRDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgbWFuYWdlcikpIHsKICAgICAgaW52b2tlID0gbWFuYWdlci5nZXREeW5hbWljTGF5b3V0KGluc3RhbmNlU3RhdGUsIHJlc29sdmVyKTsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoKTsKICAgIH0KCiAgICBzdGFjay5wdXNoKGludm9rZS5zeW1ib2xUYWJsZSk7CiAgICBzdGFjay5wdXNoKGludm9rZS5oYW5kbGUpOwogIH0pOwoKICBmdW5jdGlvbiBoYXNTdGF0aWNMYXlvdXRDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgX21hbmFnZXIpIHsKICAgIHJldHVybiBoYXNDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgMQogICAgLyogRHluYW1pY0xheW91dCAqLwogICAgKSA9PT0gZmFsc2U7CiAgfQoKICBmdW5jdGlvbiBoYXNEeW5hbWljTGF5b3V0Q2FwYWJpbGl0eShjYXBhYmlsaXRpZXMsIF9tYW5hZ2VyKSB7CiAgICByZXR1cm4gaGFzQ2FwYWJpbGl0eShjYXBhYmlsaXRpZXMsIDEKICAgIC8qIER5bmFtaWNMYXlvdXQgKi8KICAgICkgPT09IHRydWU7CiAgfQoKICBBUFBFTkRfT1BDT0RFUy5hZGQoNjgKICAvKiBNYWluICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY0MykgewogICAgdmFyIHJlZ2lzdGVyID0gX3JlZjQzLm9wMTsKICAgIHZhciBkZWZpbml0aW9uID0gdm0uc3RhY2sucG9wKCk7CiAgICB2YXIgaW52b2NhdGlvbiA9IHZtLnN0YWNrLnBvcCgpOwogICAgdmFyIG1hbmFnZXIgPSBkZWZpbml0aW9uLm1hbmFnZXI7CiAgICB2YXIgY2FwYWJpbGl0aWVzID0gY2FwYWJpbGl0eUZsYWdzRnJvbShtYW5hZ2VyLmdldENhcGFiaWxpdGllcyhkZWZpbml0aW9uLnN0YXRlKSk7CiAgICB2YXIgc3RhdGUgPSB7CiAgICAgIGRlZmluaXRpb246IGRlZmluaXRpb24sCiAgICAgIG1hbmFnZXI6IG1hbmFnZXIsCiAgICAgIGNhcGFiaWxpdGllczogY2FwYWJpbGl0aWVzLAogICAgICBzdGF0ZTogbnVsbCwKICAgICAgaGFuZGxlOiBpbnZvY2F0aW9uLmhhbmRsZSwKICAgICAgdGFibGU6IGludm9jYXRpb24uc3ltYm9sVGFibGUsCiAgICAgIGxvb2t1cDogbnVsbAogICAgfTsKICAgIHZtLmxvYWRWYWx1ZShyZWdpc3Rlciwgc3RhdGUpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4OQogIC8qIFBvcHVsYXRlTGF5b3V0ICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY0NCkgewogICAgdmFyIF9zdGF0ZSA9IF9yZWY0NC5vcDE7CiAgICB2YXIgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciBoYW5kbGUgPSBzdGFjay5wb3AoKTsKICAgIHZhciB0YWJsZSA9IHN0YWNrLnBvcCgpOwogICAgdmFyIHN0YXRlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpOwogICAgc3RhdGUuaGFuZGxlID0gaGFuZGxlOwogICAgc3RhdGUudGFibGUgPSB0YWJsZTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoMjEKICAvKiBWaXJ0dWFsUm9vdFNjb3BlICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY0NSkgewogICAgdmFyIF9zdGF0ZSA9IF9yZWY0NS5vcDE7CiAgICB2YXIgc3ltYm9scyA9IHZtLmZldGNoVmFsdWUoX3N0YXRlKS50YWJsZS5zeW1ib2xzOwogICAgdm0ucHVzaFJvb3RTY29wZShzeW1ib2xzLmxlbmd0aCArIDEsIHRydWUpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg4NwogIC8qIFNldHVwRm9yRXZhbCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNDYpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNDYub3AxOwogICAgdmFyIHN0YXRlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpOwoKICAgIGlmIChzdGF0ZS50YWJsZS5oYXNFdmFsKSB7CiAgICAgIHZhciBsb29rdXAgPSBzdGF0ZS5sb29rdXAgPSAoMCwgX3V0aWwuZGljdCkoKTsKICAgICAgdm0uc2NvcGUoKS5iaW5kRXZhbFNjb3BlKGxvb2t1cCk7CiAgICB9CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDIKICAvKiBTZXROYW1lZFZhcmlhYmxlcyAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNDcpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNDcub3AxOwogICAgdmFyIHN0YXRlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpOwogICAgdmFyIHNjb3BlID0gdm0uc2NvcGUoKTsKICAgIHZhciBhcmdzID0gdm0uc3RhY2sucGVlaygpOwogICAgdmFyIGNhbGxlck5hbWVzID0gYXJncy5uYW1lZC5hdE5hbWVzOwoKICAgIGZvciAodmFyIGkgPSBjYWxsZXJOYW1lcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICB2YXIgYXROYW1lID0gY2FsbGVyTmFtZXNbaV07CiAgICAgIHZhciBzeW1ib2wgPSBzdGF0ZS50YWJsZS5zeW1ib2xzLmluZGV4T2YoY2FsbGVyTmFtZXNbaV0pOwogICAgICB2YXIgdmFsdWUkJDEgPSBhcmdzLm5hbWVkLmdldChhdE5hbWUsIGZhbHNlKTsKICAgICAgaWYgKHN5bWJvbCAhPT0gLTEpIHNjb3BlLmJpbmRTeW1ib2woc3ltYm9sICsgMSwgdmFsdWUkJDEpOwogICAgICBpZiAoc3RhdGUubG9va3VwKSBzdGF0ZS5sb29rdXBbYXROYW1lXSA9IHZhbHVlJCQxOwogICAgfQogIH0pOwoKICBmdW5jdGlvbiBiaW5kQmxvY2soc3ltYm9sTmFtZSwgYmxvY2tOYW1lLCBzdGF0ZSwgYmxvY2tzLCB2bSkgewogICAgdmFyIHN5bWJvbCA9IHN0YXRlLnRhYmxlLnN5bWJvbHMuaW5kZXhPZihzeW1ib2xOYW1lKTsKICAgIHZhciBibG9jayA9IGJsb2Nrcy5nZXQoYmxvY2tOYW1lKTsKCiAgICBpZiAoc3ltYm9sICE9PSAtMSkgewogICAgICB2bS5zY29wZSgpLmJpbmRCbG9jayhzeW1ib2wgKyAxLCBibG9jayk7CiAgICB9CgogICAgaWYgKHN0YXRlLmxvb2t1cCkgc3RhdGUubG9va3VwW3N5bWJvbE5hbWVdID0gYmxvY2s7CiAgfQoKICBBUFBFTkRfT1BDT0RFUy5hZGQoMwogIC8qIFNldEJsb2NrcyAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNDgpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNDgub3AxOwogICAgdmFyIHN0YXRlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpOwoKICAgIHZhciBfdm0kc3RhY2skcGVlayA9IHZtLnN0YWNrLnBlZWsoKSwKICAgICAgICBibG9ja3MgPSBfdm0kc3RhY2skcGVlay5ibG9ja3M7CgogICAgYmluZEJsb2NrKCcmYXR0cnMnLCAnYXR0cnMnLCBzdGF0ZSwgYmxvY2tzLCB2bSk7CiAgICBiaW5kQmxvY2soJyZpbnZlcnNlJywgJ2Vsc2UnLCBzdGF0ZSwgYmxvY2tzLCB2bSk7CiAgICBiaW5kQmxvY2soJyZkZWZhdWx0JywgJ21haW4nLCBzdGF0ZSwgYmxvY2tzLCB2bSk7CiAgfSk7IC8vIER5bmFtaWMgSW52b2NhdGlvbiBPbmx5CgogIEFQUEVORF9PUENPREVTLmFkZCg5MAogIC8qIEludm9rZUNvbXBvbmVudExheW91dCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNDkpIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNDkub3AxOwogICAgdmFyIHN0YXRlID0gdm0uZmV0Y2hWYWx1ZShfc3RhdGUpOwogICAgdm0uY2FsbChzdGF0ZS5oYW5kbGUpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg5NAogIC8qIERpZFJlbmRlckxheW91dCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNTApIHsKICAgIHZhciBfc3RhdGUgPSBfcmVmNTAub3AxOwoKICAgIHZhciBfdm0kZmV0Y2hWYWx1ZTUgPSB2bS5mZXRjaFZhbHVlKF9zdGF0ZSksCiAgICAgICAgbWFuYWdlciA9IF92bSRmZXRjaFZhbHVlNS5tYW5hZ2VyLAogICAgICAgIHN0YXRlID0gX3ZtJGZldGNoVmFsdWU1LnN0YXRlOwoKICAgIHZhciBib3VuZHMgPSB2bS5lbGVtZW50cygpLnBvcEJsb2NrKCk7CiAgICB2YXIgbWdyID0gbWFuYWdlcjsKICAgIG1nci5kaWRSZW5kZXJMYXlvdXQoc3RhdGUsIGJvdW5kcyk7CiAgICB2bS5lbnYuZGlkQ3JlYXRlKHN0YXRlLCBtYW5hZ2VyKTsKICAgIHZtLnVwZGF0ZVdpdGgobmV3IERpZFVwZGF0ZUxheW91dE9wY29kZShtYW5hZ2VyLCBzdGF0ZSwgYm91bmRzKSk7CiAgfSk7CiAgQVBQRU5EX09QQ09ERVMuYWRkKDkyCiAgLyogQ29tbWl0Q29tcG9uZW50VHJhbnNhY3Rpb24gKi8KICAsIGZ1bmN0aW9uICh2bSkgewogICAgdm0uY29tbWl0Q2FjaGVHcm91cCgpOwogIH0pOwoKICB2YXIgVXBkYXRlQ29tcG9uZW50T3Bjb2RlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9VcGRhdGluZ09wY29kZTcpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShVcGRhdGVDb21wb25lbnRPcGNvZGUsIF9VcGRhdGluZ09wY29kZTcpOwoKICAgIGZ1bmN0aW9uIFVwZGF0ZUNvbXBvbmVudE9wY29kZSh0YWcsIGNvbXBvbmVudCwgbWFuYWdlciwgZHluYW1pY1Njb3BlKSB7CiAgICAgIHZhciBfdGhpczEwOwoKICAgICAgX3RoaXMxMCA9IF9VcGRhdGluZ09wY29kZTcuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczEwLnRhZyA9IHRhZzsKICAgICAgX3RoaXMxMC5jb21wb25lbnQgPSBjb21wb25lbnQ7CiAgICAgIF90aGlzMTAubWFuYWdlciA9IG1hbmFnZXI7CiAgICAgIF90aGlzMTAuZHluYW1pY1Njb3BlID0gZHluYW1pY1Njb3BlOwogICAgICBfdGhpczEwLnR5cGUgPSAndXBkYXRlLWNvbXBvbmVudCc7CiAgICAgIHJldHVybiBfdGhpczEwOwogICAgfQoKICAgIHZhciBfcHJvdG8xOSA9IFVwZGF0ZUNvbXBvbmVudE9wY29kZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMTkuZXZhbHVhdGUgPSBmdW5jdGlvbiBldmFsdWF0ZShfdm0pIHsKICAgICAgdmFyIGNvbXBvbmVudCA9IHRoaXMuY29tcG9uZW50LAogICAgICAgICAgbWFuYWdlciA9IHRoaXMubWFuYWdlciwKICAgICAgICAgIGR5bmFtaWNTY29wZSA9IHRoaXMuZHluYW1pY1Njb3BlOwogICAgICBtYW5hZ2VyLnVwZGF0ZShjb21wb25lbnQsIGR5bmFtaWNTY29wZSk7CiAgICB9OwoKICAgIHJldHVybiBVcGRhdGVDb21wb25lbnRPcGNvZGU7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBEaWRVcGRhdGVMYXlvdXRPcGNvZGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1VwZGF0aW5nT3Bjb2RlOCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKERpZFVwZGF0ZUxheW91dE9wY29kZSwgX1VwZGF0aW5nT3Bjb2RlOCk7CgogICAgZnVuY3Rpb24gRGlkVXBkYXRlTGF5b3V0T3Bjb2RlKG1hbmFnZXIsIGNvbXBvbmVudCwgYm91bmRzKSB7CiAgICAgIHZhciBfdGhpczExOwoKICAgICAgX3RoaXMxMSA9IF9VcGRhdGluZ09wY29kZTguY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICBfdGhpczExLm1hbmFnZXIgPSBtYW5hZ2VyOwogICAgICBfdGhpczExLmNvbXBvbmVudCA9IGNvbXBvbmVudDsKICAgICAgX3RoaXMxMS5ib3VuZHMgPSBib3VuZHM7CiAgICAgIF90aGlzMTEudHlwZSA9ICdkaWQtdXBkYXRlLWxheW91dCc7CiAgICAgIF90aGlzMTEudGFnID0gX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHOwogICAgICByZXR1cm4gX3RoaXMxMTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMjAgPSBEaWRVcGRhdGVMYXlvdXRPcGNvZGUucHJvdG90eXBlOwoKICAgIF9wcm90bzIwLmV2YWx1YXRlID0gZnVuY3Rpb24gZXZhbHVhdGUodm0pIHsKICAgICAgdmFyIG1hbmFnZXIgPSB0aGlzLm1hbmFnZXIsCiAgICAgICAgICBjb21wb25lbnQgPSB0aGlzLmNvbXBvbmVudCwKICAgICAgICAgIGJvdW5kcyA9IHRoaXMuYm91bmRzOwogICAgICBtYW5hZ2VyLmRpZFVwZGF0ZUxheW91dChjb21wb25lbnQsIGJvdW5kcyk7CiAgICAgIHZtLmVudi5kaWRVcGRhdGUoY29tcG9uZW50LCBtYW5hZ2VyKTsKICAgIH07CgogICAgcmV0dXJuIERpZFVwZGF0ZUxheW91dE9wY29kZTsKICB9KFVwZGF0aW5nT3Bjb2RlKTsKICAvKiB0c2xpbnQ6ZGlzYWJsZSAqLwoKCiAgZnVuY3Rpb24gZGVidWdDYWxsYmFjayhjb250ZXh0LCBnZXQpIHsKICAgIGNvbnNvbGUuaW5mbygnVXNlIGBjb250ZXh0YCwgYW5kIGBnZXQoPHBhdGg+KWAgdG8gZGVidWcgdGhpcyB0ZW1wbGF0ZS4nKTsgLy8gZm9yIGV4YW1wbGUuLi4KCiAgICBjb250ZXh0ID09PSBnZXQoJ3RoaXMnKTsKICAgIGRlYnVnZ2VyOwogIH0KICAvKiB0c2xpbnQ6ZW5hYmxlICovCgoKICB2YXIgY2FsbGJhY2sgPSBkZWJ1Z0NhbGxiYWNrOyAvLyBGb3IgdGVzdGluZyBwdXJwb3NlcwoKICBmdW5jdGlvbiBzZXREZWJ1Z2dlckNhbGxiYWNrKGNiKSB7CiAgICBjYWxsYmFjayA9IGNiOwogIH0KCiAgZnVuY3Rpb24gcmVzZXREZWJ1Z2dlckNhbGxiYWNrKCkgewogICAgY2FsbGJhY2sgPSBkZWJ1Z0NhbGxiYWNrOwogIH0KCiAgdmFyIFNjb3BlSW5zcGVjdG9yID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gU2NvcGVJbnNwZWN0b3Ioc2NvcGUsIHN5bWJvbHMsIGV2YWxJbmZvKSB7CiAgICAgIHRoaXMuc2NvcGUgPSBzY29wZTsKICAgICAgdGhpcy5sb2NhbHMgPSAoMCwgX3V0aWwuZGljdCkoKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXZhbEluZm8ubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgc2xvdCA9IGV2YWxJbmZvW2ldOwogICAgICAgIHZhciBuYW1lID0gc3ltYm9sc1tzbG90IC0gMV07CiAgICAgICAgdmFyIHJlZiA9IHNjb3BlLmdldFN5bWJvbChzbG90KTsKICAgICAgICB0aGlzLmxvY2Fsc1tuYW1lXSA9IHJlZjsKICAgICAgfQogICAgfQoKICAgIHZhciBfcHJvdG8yMSA9IFNjb3BlSW5zcGVjdG9yLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yMS5nZXQgPSBmdW5jdGlvbiBnZXQocGF0aCkgewogICAgICB2YXIgc2NvcGUgPSB0aGlzLnNjb3BlLAogICAgICAgICAgbG9jYWxzID0gdGhpcy5sb2NhbHM7CiAgICAgIHZhciBwYXJ0cyA9IHBhdGguc3BsaXQoJy4nKTsKCiAgICAgIHZhciBfcGF0aCRzcGxpdCA9IHBhdGguc3BsaXQoJy4nKSwKICAgICAgICAgIGhlYWQgPSBfcGF0aCRzcGxpdFswXSwKICAgICAgICAgIHRhaWwgPSBfcGF0aCRzcGxpdC5zbGljZSgxKTsKCiAgICAgIHZhciBldmFsU2NvcGUgPSBzY29wZS5nZXRFdmFsU2NvcGUoKTsKICAgICAgdmFyIHJlZjsKCiAgICAgIGlmIChoZWFkID09PSAndGhpcycpIHsKICAgICAgICByZWYgPSBzY29wZS5nZXRTZWxmKCk7CiAgICAgIH0gZWxzZSBpZiAobG9jYWxzW2hlYWRdKSB7CiAgICAgICAgcmVmID0gbG9jYWxzW2hlYWRdOwogICAgICB9IGVsc2UgaWYgKGhlYWQuaW5kZXhPZignQCcpID09PSAwICYmIGV2YWxTY29wZVtoZWFkXSkgewogICAgICAgIHJlZiA9IGV2YWxTY29wZVtoZWFkXTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZWYgPSB0aGlzLnNjb3BlLmdldFNlbGYoKTsKICAgICAgICB0YWlsID0gcGFydHM7CiAgICAgIH0KCiAgICAgIHJldHVybiB0YWlsLnJlZHVjZShmdW5jdGlvbiAociwgcGFydCkgewogICAgICAgIHJldHVybiByLmdldChwYXJ0KTsKICAgICAgfSwgcmVmKTsKICAgIH07CgogICAgcmV0dXJuIFNjb3BlSW5zcGVjdG9yOwogIH0oKTsKCiAgQVBQRU5EX09QQ09ERVMuYWRkKDk3CiAgLyogRGVidWdnZXIgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjUxKSB7CiAgICB2YXIgX3N5bWJvbHMgPSBfcmVmNTEub3AxLAogICAgICAgIF9ldmFsSW5mbyA9IF9yZWY1MS5vcDI7CiAgICB2YXIgc3ltYm9scyA9IHZtLmNvbnN0YW50cy5nZXRTdHJpbmdBcnJheShfc3ltYm9scyk7CiAgICB2YXIgZXZhbEluZm8gPSB2bS5jb25zdGFudHMuZ2V0QXJyYXkoX2V2YWxJbmZvKTsKICAgIHZhciBpbnNwZWN0b3IgPSBuZXcgU2NvcGVJbnNwZWN0b3Iodm0uc2NvcGUoKSwgc3ltYm9scywgZXZhbEluZm8pOwogICAgY2FsbGJhY2sodm0uZ2V0U2VsZigpLnZhbHVlKCksIGZ1bmN0aW9uIChwYXRoKSB7CiAgICAgIHJldHVybiBpbnNwZWN0b3IuZ2V0KHBhdGgpLnZhbHVlKCk7CiAgICB9KTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoOTUKICAvKiBJbnZva2VQYXJ0aWFsICovCiAgLCBmdW5jdGlvbiAodm0sIF9yZWY1MikgewogICAgdmFyIF9tZXRhID0gX3JlZjUyLm9wMSwKICAgICAgICBfc3ltYm9scyA9IF9yZWY1Mi5vcDIsCiAgICAgICAgX2V2YWxJbmZvID0gX3JlZjUyLm9wMzsKICAgIHZhciBjb25zdGFudHMgPSB2bS5jb25zdGFudHMsCiAgICAgICAgcmVzb2x2ZXIgPSB2bS5jb25zdGFudHMucmVzb2x2ZXIsCiAgICAgICAgc3RhY2sgPSB2bS5zdGFjazsKICAgIHZhciBuYW1lID0gc3RhY2sucG9wKCkudmFsdWUoKTsKICAgIHZhciBtZXRhID0gY29uc3RhbnRzLmdldFNlcmlhbGl6YWJsZShfbWV0YSk7CiAgICB2YXIgb3V0ZXJTeW1ib2xzID0gY29uc3RhbnRzLmdldFN0cmluZ0FycmF5KF9zeW1ib2xzKTsKICAgIHZhciBldmFsSW5mbyA9IGNvbnN0YW50cy5nZXRBcnJheShfZXZhbEluZm8pOwogICAgdmFyIGhhbmRsZSA9IHJlc29sdmVyLmxvb2t1cFBhcnRpYWwobmFtZSwgbWV0YSk7CiAgICB2YXIgZGVmaW5pdGlvbiA9IHJlc29sdmVyLnJlc29sdmUoaGFuZGxlKTsKCiAgICB2YXIgX2RlZmluaXRpb24kZ2V0UGFydGlhID0gZGVmaW5pdGlvbi5nZXRQYXJ0aWFsKCksCiAgICAgICAgc3ltYm9sVGFibGUgPSBfZGVmaW5pdGlvbiRnZXRQYXJ0aWEuc3ltYm9sVGFibGUsCiAgICAgICAgdm1IYW5kbGUgPSBfZGVmaW5pdGlvbiRnZXRQYXJ0aWEuaGFuZGxlOwoKICAgIHsKICAgICAgdmFyIHBhcnRpYWxTeW1ib2xzID0gc3ltYm9sVGFibGUuc3ltYm9sczsKICAgICAgdmFyIG91dGVyU2NvcGUgPSB2bS5zY29wZSgpOwogICAgICB2YXIgcGFydGlhbFNjb3BlID0gdm0ucHVzaFJvb3RTY29wZShwYXJ0aWFsU3ltYm9scy5sZW5ndGgsIGZhbHNlKTsKICAgICAgdmFyIGV2YWxTY29wZSA9IG91dGVyU2NvcGUuZ2V0RXZhbFNjb3BlKCk7CiAgICAgIHBhcnRpYWxTY29wZS5iaW5kQ2FsbGVyU2NvcGUob3V0ZXJTY29wZS5nZXRDYWxsZXJTY29wZSgpKTsKICAgICAgcGFydGlhbFNjb3BlLmJpbmRFdmFsU2NvcGUoZXZhbFNjb3BlKTsKICAgICAgcGFydGlhbFNjb3BlLmJpbmRTZWxmKG91dGVyU2NvcGUuZ2V0U2VsZigpKTsKICAgICAgdmFyIGxvY2FscyA9IE9iamVjdC5jcmVhdGUob3V0ZXJTY29wZS5nZXRQYXJ0aWFsTWFwKCkpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldmFsSW5mby5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBzbG90ID0gZXZhbEluZm9baV07CiAgICAgICAgdmFyIF9uYW1lMiA9IG91dGVyU3ltYm9sc1tzbG90IC0gMV07CiAgICAgICAgdmFyIHJlZiA9IG91dGVyU2NvcGUuZ2V0U3ltYm9sKHNsb3QpOwogICAgICAgIGxvY2Fsc1tfbmFtZTJdID0gcmVmOwogICAgICB9CgogICAgICBpZiAoZXZhbFNjb3BlKSB7CiAgICAgICAgZm9yICh2YXIgX2kzID0gMDsgX2kzIDwgcGFydGlhbFN5bWJvbHMubGVuZ3RoOyBfaTMrKykgewogICAgICAgICAgdmFyIF9uYW1lMyA9IHBhcnRpYWxTeW1ib2xzW19pM107CiAgICAgICAgICB2YXIgc3ltYm9sID0gX2kzICsgMTsKICAgICAgICAgIHZhciB2YWx1ZSQkMSA9IGV2YWxTY29wZVtfbmFtZTNdOwogICAgICAgICAgaWYgKHZhbHVlJCQxICE9PSB1bmRlZmluZWQpIHBhcnRpYWxTY29wZS5iaW5kKHN5bWJvbCwgdmFsdWUkJDEpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcGFydGlhbFNjb3BlLmJpbmRQYXJ0aWFsTWFwKGxvY2Fscyk7CiAgICAgIHZtLnB1c2hGcmFtZSgpOyAvLyBzcCArPSAyCgogICAgICB2bS5jYWxsKHZtSGFuZGxlKTsKICAgIH0KICB9KTsKCiAgdmFyIEl0ZXJhYmxlUHJlc2VuY2VSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBJdGVyYWJsZVByZXNlbmNlUmVmZXJlbmNlKGFydGlmYWN0cykgewogICAgICB0aGlzLnRhZyA9IGFydGlmYWN0cy50YWc7CiAgICAgIHRoaXMuYXJ0aWZhY3RzID0gYXJ0aWZhY3RzOwogICAgfQoKICAgIHZhciBfcHJvdG8yMiA9IEl0ZXJhYmxlUHJlc2VuY2VSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzIyLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHJldHVybiAhdGhpcy5hcnRpZmFjdHMuaXNFbXB0eSgpOwogICAgfTsKCiAgICByZXR1cm4gSXRlcmFibGVQcmVzZW5jZVJlZmVyZW5jZTsKICB9KCk7CgogIEFQUEVORF9PUENPREVTLmFkZCg2NgogIC8qIFB1dEl0ZXJhdG9yICovCiAgLCBmdW5jdGlvbiAodm0pIHsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIGxpc3RSZWYgPSBzdGFjay5wb3AoKTsKICAgIHZhciBrZXkgPSBzdGFjay5wb3AoKTsKICAgIHZhciBpdGVyYWJsZSA9IHZtLmVudi5pdGVyYWJsZUZvcihsaXN0UmVmLCBrZXkudmFsdWUoKSk7CiAgICB2YXIgaXRlcmF0b3IgPSBuZXcgX3JlZmVyZW5jZTIuUmVmZXJlbmNlSXRlcmF0b3IoaXRlcmFibGUpOwogICAgc3RhY2sucHVzaChpdGVyYXRvcik7CiAgICBzdGFjay5wdXNoKG5ldyBJdGVyYWJsZVByZXNlbmNlUmVmZXJlbmNlKGl0ZXJhdG9yLmFydGlmYWN0cykpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg2NAogIC8qIEVudGVyTGlzdCAqLwogICwgZnVuY3Rpb24gKHZtLCBfcmVmNTMpIHsKICAgIHZhciByZWxhdGl2ZVN0YXJ0ID0gX3JlZjUzLm9wMTsKICAgIHZtLmVudGVyTGlzdChyZWxhdGl2ZVN0YXJ0KTsKICB9KTsKICBBUFBFTkRfT1BDT0RFUy5hZGQoNjUKICAvKiBFeGl0TGlzdCAqLwogICwgZnVuY3Rpb24gKHZtKSB7CiAgICB2bS5leGl0TGlzdCgpOwogIH0pOwogIEFQUEVORF9PUENPREVTLmFkZCg2NwogIC8qIEl0ZXJhdGUgKi8KICAsIGZ1bmN0aW9uICh2bSwgX3JlZjU0KSB7CiAgICB2YXIgYnJlYWtzID0gX3JlZjU0Lm9wMTsKICAgIHZhciBzdGFjayA9IHZtLnN0YWNrOwogICAgdmFyIGl0ZW0gPSBzdGFjay5wZWVrKCkubmV4dCgpOwoKICAgIGlmIChpdGVtKSB7CiAgICAgIHZhciB0cnlPcGNvZGUgPSB2bS5pdGVyYXRlKGl0ZW0ubWVtbywgaXRlbS52YWx1ZSk7CiAgICAgIHZtLmVudGVySXRlbShpdGVtLmtleSwgdHJ5T3Bjb2RlKTsKICAgIH0gZWxzZSB7CiAgICAgIHZtLmdvdG8oYnJlYWtzKTsKICAgIH0KICB9KTsKCiAgdmFyIEN1cnNvciA9IGZ1bmN0aW9uIEN1cnNvcihlbGVtZW50LCBuZXh0U2libGluZykgewogICAgdGhpcy5lbGVtZW50ID0gZWxlbWVudDsKICAgIHRoaXMubmV4dFNpYmxpbmcgPSBuZXh0U2libGluZzsKICB9OwoKICBfZXhwb3J0cy5DdXJzb3IgPSBDdXJzb3I7CgogIHZhciBDb25jcmV0ZUJvdW5kcyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENvbmNyZXRlQm91bmRzKHBhcmVudE5vZGUsIGZpcnN0LCBsYXN0KSB7CiAgICAgIHRoaXMucGFyZW50Tm9kZSA9IHBhcmVudE5vZGU7CiAgICAgIHRoaXMuZmlyc3QgPSBmaXJzdDsKICAgICAgdGhpcy5sYXN0ID0gbGFzdDsKICAgIH0KCiAgICB2YXIgX3Byb3RvMjMgPSBDb25jcmV0ZUJvdW5kcy5wcm90b3R5cGU7CgogICAgX3Byb3RvMjMucGFyZW50RWxlbWVudCA9IGZ1bmN0aW9uIHBhcmVudEVsZW1lbnQoKSB7CiAgICAgIHJldHVybiB0aGlzLnBhcmVudE5vZGU7CiAgICB9OwoKICAgIF9wcm90bzIzLmZpcnN0Tm9kZSA9IGZ1bmN0aW9uIGZpcnN0Tm9kZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZmlyc3Q7CiAgICB9OwoKICAgIF9wcm90bzIzLmxhc3ROb2RlID0gZnVuY3Rpb24gbGFzdE5vZGUoKSB7CiAgICAgIHJldHVybiB0aGlzLmxhc3Q7CiAgICB9OwoKICAgIHJldHVybiBDb25jcmV0ZUJvdW5kczsKICB9KCk7CgogIF9leHBvcnRzLkNvbmNyZXRlQm91bmRzID0gQ29uY3JldGVCb3VuZHM7CgogIHZhciBTaW5nbGVOb2RlQm91bmRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gU2luZ2xlTm9kZUJvdW5kcyhwYXJlbnROb2RlLCBub2RlKSB7CiAgICAgIHRoaXMucGFyZW50Tm9kZSA9IHBhcmVudE5vZGU7CiAgICAgIHRoaXMubm9kZSA9IG5vZGU7CiAgICB9CgogICAgdmFyIF9wcm90bzI0ID0gU2luZ2xlTm9kZUJvdW5kcy5wcm90b3R5cGU7CgogICAgX3Byb3RvMjQucGFyZW50RWxlbWVudCA9IGZ1bmN0aW9uIHBhcmVudEVsZW1lbnQoKSB7CiAgICAgIHJldHVybiB0aGlzLnBhcmVudE5vZGU7CiAgICB9OwoKICAgIF9wcm90bzI0LmZpcnN0Tm9kZSA9IGZ1bmN0aW9uIGZpcnN0Tm9kZSgpIHsKICAgICAgcmV0dXJuIHRoaXMubm9kZTsKICAgIH07CgogICAgX3Byb3RvMjQubGFzdE5vZGUgPSBmdW5jdGlvbiBsYXN0Tm9kZSgpIHsKICAgICAgcmV0dXJuIHRoaXMubm9kZTsKICAgIH07CgogICAgcmV0dXJuIFNpbmdsZU5vZGVCb3VuZHM7CiAgfSgpOwoKICBmdW5jdGlvbiBfbW92ZShib3VuZHMsIHJlZmVyZW5jZSkgewogICAgdmFyIHBhcmVudCA9IGJvdW5kcy5wYXJlbnRFbGVtZW50KCk7CiAgICB2YXIgZmlyc3QgPSBib3VuZHMuZmlyc3ROb2RlKCk7CiAgICB2YXIgbGFzdCA9IGJvdW5kcy5sYXN0Tm9kZSgpOwogICAgdmFyIGN1cnJlbnQgPSBmaXJzdDsKCiAgICB3aGlsZSAodHJ1ZSkgewogICAgICB2YXIgbmV4dCA9IGN1cnJlbnQubmV4dFNpYmxpbmc7CiAgICAgIHBhcmVudC5pbnNlcnRCZWZvcmUoY3VycmVudCwgcmVmZXJlbmNlKTsKCiAgICAgIGlmIChjdXJyZW50ID09PSBsYXN0KSB7CiAgICAgICAgcmV0dXJuIG5leHQ7CiAgICAgIH0KCiAgICAgIGN1cnJlbnQgPSBuZXh0OwogICAgfQogIH0KCiAgZnVuY3Rpb24gY2xlYXIoYm91bmRzKSB7CiAgICB2YXIgcGFyZW50ID0gYm91bmRzLnBhcmVudEVsZW1lbnQoKTsKICAgIHZhciBmaXJzdCA9IGJvdW5kcy5maXJzdE5vZGUoKTsKICAgIHZhciBsYXN0ID0gYm91bmRzLmxhc3ROb2RlKCk7CiAgICB2YXIgY3VycmVudCA9IGZpcnN0OwoKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIHZhciBuZXh0ID0gY3VycmVudC5uZXh0U2libGluZzsKICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKGN1cnJlbnQpOwoKICAgICAgaWYgKGN1cnJlbnQgPT09IGxhc3QpIHsKICAgICAgICByZXR1cm4gbmV4dDsKICAgICAgfQoKICAgICAgY3VycmVudCA9IG5leHQ7CiAgICB9CiAgfSAvLyBQYXRjaDogICAgaW5zZXJ0QWRqYWNlbnRIVE1MIG9uIFNWRyBGaXgKICAvLyBCcm93c2VyczogU2FmYXJpLCBJRSwgRWRnZSwgRmlyZWZveCB+MzMtMzQKICAvLyBSZWFzb246ICAgaW5zZXJ0QWRqYWNlbnRIVE1MIGRvZXMgbm90IGV4aXN0IG9uIFNWRyBlbGVtZW50cyBpbiBTYWZhcmkuIEl0IGlzCiAgLy8gICAgICAgICAgIHByZXNlbnQgYnV0IHRocm93cyBhbiBleGNlcHRpb24gb24gSUUgYW5kIEVkZ2UuIE9sZCB2ZXJzaW9ucyBvZgogIC8vICAgICAgICAgICBGaXJlZm94IGNyZWF0ZSBub2RlcyBpbiB0aGUgaW5jb3JyZWN0IG5hbWVzcGFjZS4KICAvLyBGaXg6ICAgICAgU2luY2UgSUUgYW5kIEVkZ2Ugc2lsZW50bHkgZmFpbCB0byBjcmVhdGUgU1ZHIG5vZGVzIHVzaW5nCiAgLy8gICAgICAgICAgIGlubmVySFRNTCwgYW5kIGJlY2F1c2UgRmlyZWZveCBtYXkgY3JlYXRlIG5vZGVzIGluIHRoZSBpbmNvcnJlY3QKICAvLyAgICAgICAgICAgbmFtZXNwYWNlIHVzaW5nIGlubmVySFRNTCBvbiBTVkcgZWxlbWVudHMsIGFuIEhUTUwtc3RyaW5nIHdyYXBwaW5nCiAgLy8gICAgICAgICAgIGFwcHJvYWNoIGlzIHVzZWQuIEEgcHJlL3Bvc3QgU1ZHIHRhZyBpcyBhZGRlZCB0byB0aGUgc3RyaW5nLCB0aGVuCiAgLy8gICAgICAgICAgIHRoYXQgd2hvbGUgc3RyaW5nIGlzIGFkZGVkIHRvIGEgZGl2LiBUaGUgY3JlYXRlZCBub2RlcyBhcmUgcGx1Y2tlZAogIC8vICAgICAgICAgICBvdXQgYW5kIGFwcGxpZWQgdG8gdGhlIHRhcmdldCBsb2NhdGlvbiBvbiBET00uCgoKICBmdW5jdGlvbiBhcHBseVNWR0lubmVySFRNTEZpeChkb2N1bWVudCwgRE9NQ2xhc3MsIHN2Z05hbWVzcGFjZSkgewogICAgaWYgKCFkb2N1bWVudCkgcmV0dXJuIERPTUNsYXNzOwoKICAgIGlmICghc2hvdWxkQXBwbHlGaXgoZG9jdW1lbnQsIHN2Z05hbWVzcGFjZSkpIHsKICAgICAgcmV0dXJuIERPTUNsYXNzOwogICAgfQoKICAgIHZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgIHJldHVybiAoCiAgICAgIC8qI19fUFVSRV9fKi8KICAgICAgZnVuY3Rpb24gKF9ET01DbGFzcykgewogICAgICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShET01DaGFuZ2VzV2l0aFNWR0lubmVySFRNTEZpeCwgX0RPTUNsYXNzKTsKCiAgICAgICAgZnVuY3Rpb24gRE9NQ2hhbmdlc1dpdGhTVkdJbm5lckhUTUxGaXgoKSB7CiAgICAgICAgICByZXR1cm4gX0RPTUNsYXNzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgICAgICB9CgogICAgICAgIHZhciBfcHJvdG8yNSA9IERPTUNoYW5nZXNXaXRoU1ZHSW5uZXJIVE1MRml4LnByb3RvdHlwZTsKCiAgICAgICAgX3Byb3RvMjUuaW5zZXJ0SFRNTEJlZm9yZSA9IGZ1bmN0aW9uIGluc2VydEhUTUxCZWZvcmUocGFyZW50LCBuZXh0U2libGluZywgaHRtbCkgewogICAgICAgICAgaWYgKGh0bWwgPT09ICcnKSB7CiAgICAgICAgICAgIHJldHVybiBfRE9NQ2xhc3MucHJvdG90eXBlLmluc2VydEhUTUxCZWZvcmUuY2FsbCh0aGlzLCBwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAocGFyZW50Lm5hbWVzcGFjZVVSSSAhPT0gc3ZnTmFtZXNwYWNlKSB7CiAgICAgICAgICAgIHJldHVybiBfRE9NQ2xhc3MucHJvdG90eXBlLmluc2VydEhUTUxCZWZvcmUuY2FsbCh0aGlzLCBwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKTsKICAgICAgICAgIH0KCiAgICAgICAgICByZXR1cm4gZml4U1ZHKHBhcmVudCwgZGl2LCBodG1sLCBuZXh0U2libGluZyk7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIERPTUNoYW5nZXNXaXRoU1ZHSW5uZXJIVE1MRml4OwogICAgICB9KERPTUNsYXNzKQogICAgKTsKICB9CgogIGZ1bmN0aW9uIGZpeFNWRyhwYXJlbnQsIGRpdiwgaHRtbCwgcmVmZXJlbmNlKSB7CiAgICB2YXIgc291cmNlOyAvLyBUaGlzIGlzIGltcG9ydGFudCwgYmVjYXVzZSBkZWNlbmRhbnRzIG9mIHRoZSA8Zm9yZWlnbk9iamVjdD4gaW50ZWdyYXRpb24KICAgIC8vIHBvaW50IGFyZSBwYXJzZWQgaW4gdGhlIEhUTUwgbmFtZXNwYWNlCgogICAgaWYgKHBhcmVudC50YWdOYW1lLnRvVXBwZXJDYXNlKCkgPT09ICdGT1JFSUdOT0JKRUNUJykgewogICAgICAvLyBJRSwgRWRnZTogYWxzbyBkbyBub3QgY29ycmVjdGx5IHN1cHBvcnQgdXNpbmcgYGlubmVySFRNTGAgb24gU1ZHCiAgICAgIC8vIG5hbWVzcGFjZWQgZWxlbWVudHMuIFNvIGhlcmUgYSB3cmFwcGVyIGlzIHVzZWQuCiAgICAgIHZhciB3cmFwcGVkSHRtbCA9ICc8c3ZnPjxmb3JlaWduT2JqZWN0PicgKyBodG1sICsgJzwvZm9yZWlnbk9iamVjdD48L3N2Zz4nOwogICAgICBkaXYuaW5uZXJIVE1MID0gd3JhcHBlZEh0bWw7CiAgICAgIHNvdXJjZSA9IGRpdi5maXJzdENoaWxkLmZpcnN0Q2hpbGQ7CiAgICB9IGVsc2UgewogICAgICAvLyBJRSwgRWRnZTogYWxzbyBkbyBub3QgY29ycmVjdGx5IHN1cHBvcnQgdXNpbmcgYGlubmVySFRNTGAgb24gU1ZHCiAgICAgIC8vIG5hbWVzcGFjZWQgZWxlbWVudHMuIFNvIGhlcmUgYSB3cmFwcGVyIGlzIHVzZWQuCiAgICAgIHZhciBfd3JhcHBlZEh0bWwgPSAnPHN2Zz4nICsgaHRtbCArICc8L3N2Zz4nOwoKICAgICAgZGl2LmlubmVySFRNTCA9IF93cmFwcGVkSHRtbDsKICAgICAgc291cmNlID0gZGl2LmZpcnN0Q2hpbGQ7CiAgICB9CgogICAgcmV0dXJuIG1vdmVOb2Rlc0JlZm9yZShzb3VyY2UsIHBhcmVudCwgcmVmZXJlbmNlKTsKICB9CgogIGZ1bmN0aW9uIHNob3VsZEFwcGx5Rml4KGRvY3VtZW50LCBzdmdOYW1lc3BhY2UpIHsKICAgIHZhciBzdmcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoc3ZnTmFtZXNwYWNlLCAnc3ZnJyk7CgogICAgdHJ5IHsKICAgICAgc3ZnWydpbnNlcnRBZGphY2VudEhUTUwnXSgnYmVmb3JlZW5kJywgJzxjaXJjbGU+PC9jaXJjbGU+Jyk7CiAgICB9IGNhdGNoIChlKSB7Ly8gSUUsIEVkZ2U6IFdpbGwgdGhyb3csIGluc2VydEFkamFjZW50SFRNTCBpcyB1bnN1cHBvcnRlZCBvbiBTVkcKICAgICAgLy8gU2FmYXJpOiBXaWxsIHRocm93LCBpbnNlcnRBZGphY2VudEhUTUwgaXMgbm90IHByZXNlbnQgb24gU1ZHCiAgICB9IGZpbmFsbHkgewogICAgICAvLyBGRjogT2xkIHZlcnNpb25zIHdpbGwgY3JlYXRlIGEgbm9kZSBpbiB0aGUgd3JvbmcgbmFtZXNwYWNlCiAgICAgIGlmIChzdmcuY2hpbGROb2Rlcy5sZW5ndGggPT09IDEgJiYgc3ZnLmZpcnN0Q2hpbGQubmFtZXNwYWNlVVJJID09PSBTVkdfTkFNRVNQQUNFKSB7CiAgICAgICAgLy8gVGhlIHRlc3Qgd29ya2VkIGFzIGV4cGVjdGVkLCBubyBmaXggcmVxdWlyZWQKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIHJldHVybiB0cnVlOwogICAgfQogIH0gLy8gUGF0Y2g6ICAgIEFkamFjZW50IHRleHQgbm9kZSBtZXJnaW5nIGZpeAogIC8vIEJyb3dzZXJzOiBJRSwgRWRnZSwgRmlyZWZveCB3L28gaW5zcGVjdG9yIG9wZW4KICAvLyBSZWFzb246ICAgVGhlc2UgYnJvd3NlcnMgd2lsbCBtZXJnZSBhZGphY2VudCB0ZXh0IG5vZGVzLiBGb3IgZXhtYXBsZSBnaXZlbgogIC8vICAgICAgICAgICA8ZGl2PkhlbGxvPC9kaXY+IHdpdGggZGl2Lmluc2VydEFkamFjZW50SFRNTCgnIHdvcmxkJykgYnJvd3NlcnMKICAvLyAgICAgICAgICAgd2l0aCBwcm9wZXIgYmVoYXZpb3Igd2lsbCBwb3B1bGF0ZSBkaXYuY2hpbGROb2RlcyB3aXRoIHR3byBpdGVtcy4KICAvLyAgICAgICAgICAgVGhlc2UgYnJvd3NlcnMgd2lsbCBwb3B1bGF0ZSBpdCB3aXRoIG9uZSBtZXJnZWQgbm9kZSBpbnN0ZWFkLgogIC8vIEZpeDogICAgICBBZGQgdGhlc2Ugbm9kZXMgdG8gYSB3cmFwcGVyIGVsZW1lbnQsIHRoZW4gaXRlcmF0ZSB0aGUgY2hpbGROb2RlcwogIC8vICAgICAgICAgICBvZiB0aGF0IHdyYXBwZXIgYW5kIG1vdmUgdGhlIG5vZGVzIHRvIHRoZWlyIHRhcmdldCBsb2NhdGlvbi4gTm90ZQogIC8vICAgICAgICAgICB0aGF0IHBvdGVudGlhbCBTVkcgYnVncyB3aWxsIGhhdmUgYmVlbiBoYW5kbGVkIGJlZm9yZSB0aGlzIGZpeC4KICAvLyAgICAgICAgICAgTm90ZSB0aGF0IHRoaXMgZml4IG11c3Qgb25seSBhcHBseSB0byB0aGUgcHJldmlvdXMgdGV4dCBub2RlLCBhcwogIC8vICAgICAgICAgICB0aGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgaW5zZXJ0SFRNTEJlZm9yZWAgYWxyZWFkeSBoYW5kbGVzCiAgLy8gICAgICAgICAgIGZvbGxvd2luZyB0ZXh0IG5vZGVzIGNvcnJlY3RseS4KCgogIGZ1bmN0aW9uIGFwcGx5VGV4dE5vZGVNZXJnaW5nRml4KGRvY3VtZW50LCBET01DbGFzcykgewogICAgaWYgKCFkb2N1bWVudCkgcmV0dXJuIERPTUNsYXNzOwoKICAgIGlmICghc2hvdWxkQXBwbHlGaXgkMShkb2N1bWVudCkpIHsKICAgICAgcmV0dXJuIERPTUNsYXNzOwogICAgfQoKICAgIHJldHVybiAoCiAgICAgIC8qI19fUFVSRV9fKi8KICAgICAgZnVuY3Rpb24gKF9ET01DbGFzczIpIHsKICAgICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRE9NQ2hhbmdlc1dpdGhUZXh0Tm9kZU1lcmdpbmdGaXgsIF9ET01DbGFzczIpOwoKICAgICAgICBmdW5jdGlvbiBET01DaGFuZ2VzV2l0aFRleHROb2RlTWVyZ2luZ0ZpeChkb2N1bWVudCkgewogICAgICAgICAgdmFyIF90aGlzMTI7CgogICAgICAgICAgX3RoaXMxMiA9IF9ET01DbGFzczIuY2FsbCh0aGlzLCBkb2N1bWVudCkgfHwgdGhpczsKICAgICAgICAgIF90aGlzMTIudXNlbGVzc0NvbW1lbnQgPSBkb2N1bWVudC5jcmVhdGVDb21tZW50KCcnKTsKICAgICAgICAgIHJldHVybiBfdGhpczEyOwogICAgICAgIH0KCiAgICAgICAgdmFyIF9wcm90bzI2ID0gRE9NQ2hhbmdlc1dpdGhUZXh0Tm9kZU1lcmdpbmdGaXgucHJvdG90eXBlOwoKICAgICAgICBfcHJvdG8yNi5pbnNlcnRIVE1MQmVmb3JlID0gZnVuY3Rpb24gaW5zZXJ0SFRNTEJlZm9yZShwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKSB7CiAgICAgICAgICBpZiAoaHRtbCA9PT0gJycpIHsKICAgICAgICAgICAgcmV0dXJuIF9ET01DbGFzczIucHJvdG90eXBlLmluc2VydEhUTUxCZWZvcmUuY2FsbCh0aGlzLCBwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKTsKICAgICAgICAgIH0KCiAgICAgICAgICB2YXIgZGlkU2V0VXNlbGVzc0NvbW1lbnQgPSBmYWxzZTsKICAgICAgICAgIHZhciBuZXh0UHJldmlvdXMgPSBuZXh0U2libGluZyA/IG5leHRTaWJsaW5nLnByZXZpb3VzU2libGluZyA6IHBhcmVudC5sYXN0Q2hpbGQ7CgogICAgICAgICAgaWYgKG5leHRQcmV2aW91cyAmJiBuZXh0UHJldmlvdXMgaW5zdGFuY2VvZiBUZXh0KSB7CiAgICAgICAgICAgIGRpZFNldFVzZWxlc3NDb21tZW50ID0gdHJ1ZTsKICAgICAgICAgICAgcGFyZW50Lmluc2VydEJlZm9yZSh0aGlzLnVzZWxlc3NDb21tZW50LCBuZXh0U2libGluZyk7CiAgICAgICAgICB9CgogICAgICAgICAgdmFyIGJvdW5kcyA9IF9ET01DbGFzczIucHJvdG90eXBlLmluc2VydEhUTUxCZWZvcmUuY2FsbCh0aGlzLCBwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKTsKCiAgICAgICAgICBpZiAoZGlkU2V0VXNlbGVzc0NvbW1lbnQpIHsKICAgICAgICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKHRoaXMudXNlbGVzc0NvbW1lbnQpOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBib3VuZHM7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIERPTUNoYW5nZXNXaXRoVGV4dE5vZGVNZXJnaW5nRml4OwogICAgICB9KERPTUNsYXNzKQogICAgKTsKICB9CgogIGZ1bmN0aW9uIHNob3VsZEFwcGx5Rml4JDEoZG9jdW1lbnQpIHsKICAgIHZhciBtZXJnaW5nVGV4dERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgbWVyZ2luZ1RleHREaXYuaW5uZXJIVE1MID0gJ2ZpcnN0JzsKICAgIG1lcmdpbmdUZXh0RGl2Lmluc2VydEFkamFjZW50SFRNTCgnYmVmb3JlZW5kJywgJ3NlY29uZCcpOwoKICAgIGlmIChtZXJnaW5nVGV4dERpdi5jaGlsZE5vZGVzLmxlbmd0aCA9PT0gMikgewogICAgICAvLyBJdCB3b3JrZWQgYXMgZXhwZWN0ZWQsIG5vIGZpeCByZXF1aXJlZAogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgcmV0dXJuIHRydWU7CiAgfQoKICB2YXIgU1ZHX05BTUVTUEFDRSA9ICJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAvKiBTVkcgKi8KICA7IC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2h0bWwvc3ludGF4Lmh0bWwjaHRtbC1pbnRlZ3JhdGlvbi1wb2ludAoKICBfZXhwb3J0cy5TVkdfTkFNRVNQQUNFID0gU1ZHX05BTUVTUEFDRTsKICB2YXIgU1ZHX0lOVEVHUkFUSU9OX1BPSU5UUyA9IHsKICAgIGZvcmVpZ25PYmplY3Q6IDEsCiAgICBkZXNjOiAxLAogICAgdGl0bGU6IDEKICB9OyAvLyBodHRwOi8vd3d3LnczLm9yZy9UUi9odG1sL3N5bnRheC5odG1sI2FkanVzdC1zdmctYXR0cmlidXRlcwogIC8vIFRPRE86IEFkanVzdCBTVkcgYXR0cmlidXRlcwogIC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2h0bWwvc3ludGF4Lmh0bWwjcGFyc2luZy1tYWluLWluZm9yZWlnbgogIC8vIFRPRE86IEFkanVzdCBTVkcgZWxlbWVudHMKICAvLyBodHRwOi8vd3d3LnczLm9yZy9UUi9odG1sL3N5bnRheC5odG1sI3BhcnNpbmctbWFpbi1pbmZvcmVpZ24KCiAgdmFyIEJMQUNLTElTVF9UQUJMRSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgWydiJywgJ2JpZycsICdibG9ja3F1b3RlJywgJ2JvZHknLCAnYnInLCAnY2VudGVyJywgJ2NvZGUnLCAnZGQnLCAnZGl2JywgJ2RsJywgJ2R0JywgJ2VtJywgJ2VtYmVkJywgJ2gxJywgJ2gyJywgJ2gzJywgJ2g0JywgJ2g1JywgJ2g2JywgJ2hlYWQnLCAnaHInLCAnaScsICdpbWcnLCAnbGknLCAnbGlzdGluZycsICdtYWluJywgJ21ldGEnLCAnbm9icicsICdvbCcsICdwJywgJ3ByZScsICdydWJ5JywgJ3MnLCAnc21hbGwnLCAnc3BhbicsICdzdHJvbmcnLCAnc3RyaWtlJywgJ3N1YicsICdzdXAnLCAndGFibGUnLCAndHQnLCAndScsICd1bCcsICd2YXInXS5mb3JFYWNoKGZ1bmN0aW9uICh0YWcpIHsKICAgIHJldHVybiBCTEFDS0xJU1RfVEFCTEVbdGFnXSA9IDE7CiAgfSk7CiAgdmFyIFdISVRFU1BBQ0UgPSAvW1x0LVxyIFx4QTBcdTE2ODBcdTE4MEVcdTIwMDAtXHUyMDBBXHUyMDI4XHUyMDI5XHUyMDJGXHUyMDVGXHUzMDAwXHVGRUZGXS87CiAgdmFyIGRvYyA9IHR5cGVvZiBkb2N1bWVudCA9PT0gJ3VuZGVmaW5lZCcgPyBudWxsIDogZG9jdW1lbnQ7CgogIGZ1bmN0aW9uIGlzV2hpdGVzcGFjZShzdHJpbmcpIHsKICAgIHJldHVybiBXSElURVNQQUNFLnRlc3Qoc3RyaW5nKTsKICB9CgogIGZ1bmN0aW9uIG1vdmVOb2Rlc0JlZm9yZShzb3VyY2UsIHRhcmdldCwgbmV4dFNpYmxpbmcpIHsKICAgIHZhciBmaXJzdCA9IHNvdXJjZS5maXJzdENoaWxkOwogICAgdmFyIGxhc3QgPSBmaXJzdDsKICAgIHZhciBjdXJyZW50ID0gZmlyc3Q7CgogICAgd2hpbGUgKGN1cnJlbnQpIHsKICAgICAgdmFyIG5leHQgPSBjdXJyZW50Lm5leHRTaWJsaW5nOwogICAgICB0YXJnZXQuaW5zZXJ0QmVmb3JlKGN1cnJlbnQsIG5leHRTaWJsaW5nKTsKICAgICAgbGFzdCA9IGN1cnJlbnQ7CiAgICAgIGN1cnJlbnQgPSBuZXh0OwogICAgfQoKICAgIHJldHVybiBuZXcgQ29uY3JldGVCb3VuZHModGFyZ2V0LCBmaXJzdCwgbGFzdCk7CiAgfQoKICB2YXIgRE9NT3BlcmF0aW9ucyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIERPTU9wZXJhdGlvbnMoZG9jdW1lbnQpIHsKICAgICAgdGhpcy5kb2N1bWVudCA9IGRvY3VtZW50OwogICAgICB0aGlzLnNldHVwVXNlbGVzc0VsZW1lbnQoKTsKICAgIH0gLy8gc3BsaXQgaW50byBzZXBlcmF0ZSBtZXRob2Qgc28gdGhhdCBOb2RlRE9NVHJlZUNvbnN0cnVjdGlvbgogICAgLy8gY2FuIG92ZXJyaWRlIGl0LgoKCiAgICB2YXIgX3Byb3RvMjcgPSBET01PcGVyYXRpb25zLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yNy5zZXR1cFVzZWxlc3NFbGVtZW50ID0gZnVuY3Rpb24gc2V0dXBVc2VsZXNzRWxlbWVudCgpIHsKICAgICAgdGhpcy51c2VsZXNzRWxlbWVudCA9IHRoaXMuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICB9OwoKICAgIF9wcm90bzI3LmNyZWF0ZUVsZW1lbnQgPSBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHRhZywgY29udGV4dCkgewogICAgICB2YXIgaXNFbGVtZW50SW5TVkdOYW1lc3BhY2UsIGlzSFRNTEludGVncmF0aW9uUG9pbnQ7CgogICAgICBpZiAoY29udGV4dCkgewogICAgICAgIGlzRWxlbWVudEluU1ZHTmFtZXNwYWNlID0gY29udGV4dC5uYW1lc3BhY2VVUkkgPT09IFNWR19OQU1FU1BBQ0UgfHwgdGFnID09PSAnc3ZnJzsKICAgICAgICBpc0hUTUxJbnRlZ3JhdGlvblBvaW50ID0gU1ZHX0lOVEVHUkFUSU9OX1BPSU5UU1tjb250ZXh0LnRhZ05hbWVdOwogICAgICB9IGVsc2UgewogICAgICAgIGlzRWxlbWVudEluU1ZHTmFtZXNwYWNlID0gdGFnID09PSAnc3ZnJzsKICAgICAgICBpc0hUTUxJbnRlZ3JhdGlvblBvaW50ID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIGlmIChpc0VsZW1lbnRJblNWR05hbWVzcGFjZSAmJiAhaXNIVE1MSW50ZWdyYXRpb25Qb2ludCkgewogICAgICAgIC8vIEZJWE1FOiBUaGlzIGRvZXMgbm90IHByb3Blcmx5IGhhbmRsZSA8Zm9udD4gd2l0aCBjb2xvciwgZmFjZSwgb3IKICAgICAgICAvLyBzaXplIGF0dHJpYnV0ZXMsIHdoaWNoIGlzIGFsc28gZGlzYWxsb3dlZCBieSB0aGUgc3BlYy4gV2Ugc2hvdWxkIGZpeAogICAgICAgIC8vIHRoaXMuCiAgICAgICAgaWYgKEJMQUNLTElTVF9UQUJMRVt0YWddKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkNhbm5vdCBjcmVhdGUgYSAiICsgdGFnICsgIiBpbnNpZGUgYW4gU1ZHIGNvbnRleHQiKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhTVkdfTkFNRVNQQUNFLCB0YWcpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8yNy5pbnNlcnRCZWZvcmUgPSBmdW5jdGlvbiBpbnNlcnRCZWZvcmUocGFyZW50LCBub2RlLCByZWZlcmVuY2UpIHsKICAgICAgcGFyZW50Lmluc2VydEJlZm9yZShub2RlLCByZWZlcmVuY2UpOwogICAgfTsKCiAgICBfcHJvdG8yNy5pbnNlcnRIVE1MQmVmb3JlID0gZnVuY3Rpb24gaW5zZXJ0SFRNTEJlZm9yZShwYXJlbnQsIG5leHRTaWJsaW5nLCBodG1sKSB7CiAgICAgIGlmIChodG1sID09PSAnJykgewogICAgICAgIHZhciBjb21tZW50ID0gdGhpcy5jcmVhdGVDb21tZW50KCcnKTsKICAgICAgICBwYXJlbnQuaW5zZXJ0QmVmb3JlKGNvbW1lbnQsIG5leHRTaWJsaW5nKTsKICAgICAgICByZXR1cm4gbmV3IENvbmNyZXRlQm91bmRzKHBhcmVudCwgY29tbWVudCwgY29tbWVudCk7CiAgICAgIH0KCiAgICAgIHZhciBwcmV2ID0gbmV4dFNpYmxpbmcgPyBuZXh0U2libGluZy5wcmV2aW91c1NpYmxpbmcgOiBwYXJlbnQubGFzdENoaWxkOwogICAgICB2YXIgbGFzdDsKCiAgICAgIGlmIChuZXh0U2libGluZyA9PT0gbnVsbCkgewogICAgICAgIHBhcmVudC5pbnNlcnRBZGphY2VudEhUTUwoImJlZm9yZWVuZCIKICAgICAgICAvKiBiZWZvcmVlbmQgKi8KICAgICAgICAsIGh0bWwpOwogICAgICAgIGxhc3QgPSBwYXJlbnQubGFzdENoaWxkOwogICAgICB9IGVsc2UgaWYgKG5leHRTaWJsaW5nIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHsKICAgICAgICBuZXh0U2libGluZy5pbnNlcnRBZGphY2VudEhUTUwoImJlZm9yZWJlZ2luIgogICAgICAgIC8qIGJlZm9yZWJlZ2luICovCiAgICAgICAgLCBodG1sKTsKICAgICAgICBsYXN0ID0gbmV4dFNpYmxpbmcucHJldmlvdXNTaWJsaW5nOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIE5vbi1lbGVtZW50IG5vZGVzIGRvIG5vdCBzdXBwb3J0IGluc2VydEFkamFjZW50SFRNTCwgc28gYWRkIGFuCiAgICAgICAgLy8gZWxlbWVudCBhbmQgY2FsbCBpdCBvbiB0aGF0IGVsZW1lbnQuIFRoZW4gcmVtb3ZlIHRoZSBlbGVtZW50LgogICAgICAgIC8vCiAgICAgICAgLy8gVGhpcyBhbHNvIHByb3RlY3RzIEVkZ2UsIElFIGFuZCBGaXJlZm94IHcvbyB0aGUgaW5zcGVjdG9yIG9wZW4KICAgICAgICAvLyBmcm9tIG1lcmdpbmcgYWRqYWNlbnQgdGV4dCBub2Rlcy4gU2VlIC4vY29tcGF0L3RleHQtbm9kZS1tZXJnaW5nLWZpeC50cwogICAgICAgIHZhciB1c2VsZXNzRWxlbWVudCA9IHRoaXMudXNlbGVzc0VsZW1lbnQ7CiAgICAgICAgcGFyZW50Lmluc2VydEJlZm9yZSh1c2VsZXNzRWxlbWVudCwgbmV4dFNpYmxpbmcpOwogICAgICAgIHVzZWxlc3NFbGVtZW50Lmluc2VydEFkamFjZW50SFRNTCgiYmVmb3JlYmVnaW4iCiAgICAgICAgLyogYmVmb3JlYmVnaW4gKi8KICAgICAgICAsIGh0bWwpOwogICAgICAgIGxhc3QgPSB1c2VsZXNzRWxlbWVudC5wcmV2aW91c1NpYmxpbmc7CiAgICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKHVzZWxlc3NFbGVtZW50KTsKICAgICAgfQoKICAgICAgdmFyIGZpcnN0ID0gcHJldiA/IHByZXYubmV4dFNpYmxpbmcgOiBwYXJlbnQuZmlyc3RDaGlsZDsKICAgICAgcmV0dXJuIG5ldyBDb25jcmV0ZUJvdW5kcyhwYXJlbnQsIGZpcnN0LCBsYXN0KTsKICAgIH07CgogICAgX3Byb3RvMjcuY3JlYXRlVGV4dE5vZGUgPSBmdW5jdGlvbiBjcmVhdGVUZXh0Tm9kZSh0ZXh0KSB7CiAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHRleHQpOwogICAgfTsKCiAgICBfcHJvdG8yNy5jcmVhdGVDb21tZW50ID0gZnVuY3Rpb24gY3JlYXRlQ29tbWVudChkYXRhKSB7CiAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZUNvbW1lbnQoZGF0YSk7CiAgICB9OwoKICAgIHJldHVybiBET01PcGVyYXRpb25zOwogIH0oKTsKCiAgdmFyIERPTTsKCiAgKGZ1bmN0aW9uIChET00pIHsKICAgIHZhciBUcmVlQ29uc3RydWN0aW9uID0KICAgIC8qI19fUFVSRV9fKi8KICAgIGZ1bmN0aW9uIChfRE9NT3BlcmF0aW9ucykgewogICAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoVHJlZUNvbnN0cnVjdGlvbiwgX0RPTU9wZXJhdGlvbnMpOwoKICAgICAgZnVuY3Rpb24gVHJlZUNvbnN0cnVjdGlvbigpIHsKICAgICAgICByZXR1cm4gX0RPTU9wZXJhdGlvbnMuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICB9CgogICAgICB2YXIgX3Byb3RvMjggPSBUcmVlQ29uc3RydWN0aW9uLnByb3RvdHlwZTsKCiAgICAgIF9wcm90bzI4LmNyZWF0ZUVsZW1lbnROUyA9IGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnROUyhuYW1lc3BhY2UsIHRhZykgewogICAgICAgIHJldHVybiB0aGlzLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhuYW1lc3BhY2UsIHRhZyk7CiAgICAgIH07CgogICAgICBfcHJvdG8yOC5zZXRBdHRyaWJ1dGUgPSBmdW5jdGlvbiBzZXRBdHRyaWJ1dGUoZWxlbWVudCwgbmFtZSwgdmFsdWUkJDEsIG5hbWVzcGFjZSkgewogICAgICAgIGlmIChuYW1lc3BhY2UgPT09IHZvaWQgMCkgewogICAgICAgICAgbmFtZXNwYWNlID0gbnVsbDsKICAgICAgICB9CgogICAgICAgIGlmIChuYW1lc3BhY2UpIHsKICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlTlMobmFtZXNwYWNlLCBuYW1lLCB2YWx1ZSQkMSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlJCQxKTsKICAgICAgICB9CiAgICAgIH07CgogICAgICByZXR1cm4gVHJlZUNvbnN0cnVjdGlvbjsKICAgIH0oRE9NT3BlcmF0aW9ucyk7CgogICAgRE9NLlRyZWVDb25zdHJ1Y3Rpb24gPSBUcmVlQ29uc3RydWN0aW9uOwogICAgdmFyIGFwcGxpZWRUcmVlQ29udHJ1Y3Rpb24gPSBUcmVlQ29uc3RydWN0aW9uOwogICAgYXBwbGllZFRyZWVDb250cnVjdGlvbiA9IGFwcGx5VGV4dE5vZGVNZXJnaW5nRml4KGRvYywgYXBwbGllZFRyZWVDb250cnVjdGlvbik7CiAgICBhcHBsaWVkVHJlZUNvbnRydWN0aW9uID0gYXBwbHlTVkdJbm5lckhUTUxGaXgoZG9jLCBhcHBsaWVkVHJlZUNvbnRydWN0aW9uLCBTVkdfTkFNRVNQQUNFKTsKICAgIERPTS5ET01UcmVlQ29uc3RydWN0aW9uID0gYXBwbGllZFRyZWVDb250cnVjdGlvbjsKICB9KShET00gfHwgKERPTSA9IHt9KSk7CgogIHZhciBET01DaGFuZ2VzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9ET01PcGVyYXRpb25zMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKERPTUNoYW5nZXMsIF9ET01PcGVyYXRpb25zMik7CgogICAgZnVuY3Rpb24gRE9NQ2hhbmdlcyhkb2N1bWVudCkgewogICAgICB2YXIgX3RoaXMxMzsKCiAgICAgIF90aGlzMTMgPSBfRE9NT3BlcmF0aW9uczIuY2FsbCh0aGlzLCBkb2N1bWVudCkgfHwgdGhpczsKICAgICAgX3RoaXMxMy5kb2N1bWVudCA9IGRvY3VtZW50OwogICAgICBfdGhpczEzLm5hbWVzcGFjZSA9IG51bGw7CiAgICAgIHJldHVybiBfdGhpczEzOwogICAgfQoKICAgIHZhciBfcHJvdG8yOSA9IERPTUNoYW5nZXMucHJvdG90eXBlOwoKICAgIF9wcm90bzI5LnNldEF0dHJpYnV0ZSA9IGZ1bmN0aW9uIHNldEF0dHJpYnV0ZShlbGVtZW50LCBuYW1lLCB2YWx1ZSQkMSkgewogICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzI5LnJlbW92ZUF0dHJpYnV0ZSA9IGZ1bmN0aW9uIHJlbW92ZUF0dHJpYnV0ZShlbGVtZW50LCBuYW1lKSB7CiAgICAgIGVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKG5hbWUpOwogICAgfTsKCiAgICBfcHJvdG8yOS5pbnNlcnRBZnRlciA9IGZ1bmN0aW9uIGluc2VydEFmdGVyKGVsZW1lbnQsIG5vZGUsIHJlZmVyZW5jZSkgewogICAgICB0aGlzLmluc2VydEJlZm9yZShlbGVtZW50LCBub2RlLCByZWZlcmVuY2UubmV4dFNpYmxpbmcpOwogICAgfTsKCiAgICByZXR1cm4gRE9NQ2hhbmdlczsKICB9KERPTU9wZXJhdGlvbnMpOwoKICBfZXhwb3J0cy5JRE9NQ2hhbmdlcyA9IERPTUNoYW5nZXM7CiAgdmFyIGhlbHBlciA9IERPTUNoYW5nZXM7CiAgaGVscGVyID0gYXBwbHlUZXh0Tm9kZU1lcmdpbmdGaXgoZG9jLCBoZWxwZXIpOwogIGhlbHBlciA9IGFwcGx5U1ZHSW5uZXJIVE1MRml4KGRvYywgaGVscGVyLCBTVkdfTkFNRVNQQUNFKTsKICB2YXIgaGVscGVyJDEgPSBoZWxwZXI7CiAgX2V4cG9ydHMuRE9NQ2hhbmdlcyA9IGhlbHBlciQxOwogIHZhciBET01UcmVlQ29uc3RydWN0aW9uID0gRE9NLkRPTVRyZWVDb25zdHJ1Y3Rpb247CiAgX2V4cG9ydHMuRE9NVHJlZUNvbnN0cnVjdGlvbiA9IERPTVRyZWVDb25zdHJ1Y3Rpb247CiAgdmFyIGJhZFByb3RvY29scyA9IFsnamF2YXNjcmlwdDonLCAndmJzY3JpcHQ6J107CiAgdmFyIGJhZFRhZ3MgPSBbJ0EnLCAnQk9EWScsICdMSU5LJywgJ0lNRycsICdJRlJBTUUnLCAnQkFTRScsICdGT1JNJ107CiAgdmFyIGJhZFRhZ3NGb3JEYXRhVVJJID0gWydFTUJFRCddOwogIHZhciBiYWRBdHRyaWJ1dGVzID0gWydocmVmJywgJ3NyYycsICdiYWNrZ3JvdW5kJywgJ2FjdGlvbiddOwogIHZhciBiYWRBdHRyaWJ1dGVzRm9yRGF0YVVSSSA9IFsnc3JjJ107CgogIGZ1bmN0aW9uIGhhcyhhcnJheSwgaXRlbSkgewogICAgcmV0dXJuIGFycmF5LmluZGV4T2YoaXRlbSkgIT09IC0xOwogIH0KCiAgZnVuY3Rpb24gY2hlY2tVUkkodGFnTmFtZSwgYXR0cmlidXRlKSB7CiAgICByZXR1cm4gKHRhZ05hbWUgPT09IG51bGwgfHwgaGFzKGJhZFRhZ3MsIHRhZ05hbWUpKSAmJiBoYXMoYmFkQXR0cmlidXRlcywgYXR0cmlidXRlKTsKICB9CgogIGZ1bmN0aW9uIGNoZWNrRGF0YVVSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpIHsKICAgIGlmICh0YWdOYW1lID09PSBudWxsKSByZXR1cm4gZmFsc2U7CiAgICByZXR1cm4gaGFzKGJhZFRhZ3NGb3JEYXRhVVJJLCB0YWdOYW1lKSAmJiBoYXMoYmFkQXR0cmlidXRlc0ZvckRhdGFVUkksIGF0dHJpYnV0ZSk7CiAgfQoKICBmdW5jdGlvbiByZXF1aXJlc1Nhbml0aXphdGlvbih0YWdOYW1lLCBhdHRyaWJ1dGUpIHsKICAgIHJldHVybiBjaGVja1VSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpIHx8IGNoZWNrRGF0YVVSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpOwogIH0KCiAgZnVuY3Rpb24gc2FuaXRpemVBdHRyaWJ1dGVWYWx1ZShlbnYsIGVsZW1lbnQsIGF0dHJpYnV0ZSwgdmFsdWUkJDEpIHsKICAgIHZhciB0YWdOYW1lID0gbnVsbDsKCiAgICBpZiAodmFsdWUkJDEgPT09IG51bGwgfHwgdmFsdWUkJDEgPT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gdmFsdWUkJDE7CiAgICB9CgogICAgaWYgKGlzU2FmZVN0cmluZyh2YWx1ZSQkMSkpIHsKICAgICAgcmV0dXJuIHZhbHVlJCQxLnRvSFRNTCgpOwogICAgfQoKICAgIGlmICghZWxlbWVudCkgewogICAgICB0YWdOYW1lID0gbnVsbDsKICAgIH0gZWxzZSB7CiAgICAgIHRhZ05hbWUgPSBlbGVtZW50LnRhZ05hbWUudG9VcHBlckNhc2UoKTsKICAgIH0KCiAgICB2YXIgc3RyID0gbm9ybWFsaXplU3RyaW5nVmFsdWUodmFsdWUkJDEpOwoKICAgIGlmIChjaGVja1VSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpKSB7CiAgICAgIHZhciBwcm90b2NvbCA9IGVudi5wcm90b2NvbEZvclVSTChzdHIpOwoKICAgICAgaWYgKGhhcyhiYWRQcm90b2NvbHMsIHByb3RvY29sKSkgewogICAgICAgIHJldHVybiAidW5zYWZlOiIgKyBzdHI7CiAgICAgIH0KICAgIH0KCiAgICBpZiAoY2hlY2tEYXRhVVJJKHRhZ05hbWUsIGF0dHJpYnV0ZSkpIHsKICAgICAgcmV0dXJuICJ1bnNhZmU6IiArIHN0cjsKICAgIH0KCiAgICByZXR1cm4gc3RyOwogIH0KICAvKgogICAqIEBtZXRob2Qgbm9ybWFsaXplUHJvcGVydHkKICAgKiBAcGFyYW0gZWxlbWVudCB7SFRNTEVsZW1lbnR9CiAgICogQHBhcmFtIHNsb3ROYW1lIHtTdHJpbmd9CiAgICogQHJldHVybnMge09iamVjdH0geyBuYW1lLCB0eXBlIH0KICAgKi8KCgogIGZ1bmN0aW9uIG5vcm1hbGl6ZVByb3BlcnR5KGVsZW1lbnQsIHNsb3ROYW1lKSB7CiAgICB2YXIgdHlwZSwgbm9ybWFsaXplZDsKCiAgICBpZiAoc2xvdE5hbWUgaW4gZWxlbWVudCkgewogICAgICBub3JtYWxpemVkID0gc2xvdE5hbWU7CiAgICAgIHR5cGUgPSAncHJvcCc7CiAgICB9IGVsc2UgewogICAgICB2YXIgbG93ZXIgPSBzbG90TmFtZS50b0xvd2VyQ2FzZSgpOwoKICAgICAgaWYgKGxvd2VyIGluIGVsZW1lbnQpIHsKICAgICAgICB0eXBlID0gJ3Byb3AnOwogICAgICAgIG5vcm1hbGl6ZWQgPSBsb3dlcjsKICAgICAgfSBlbHNlIHsKICAgICAgICB0eXBlID0gJ2F0dHInOwogICAgICAgIG5vcm1hbGl6ZWQgPSBzbG90TmFtZTsKICAgICAgfQogICAgfQoKICAgIGlmICh0eXBlID09PSAncHJvcCcgJiYgKG5vcm1hbGl6ZWQudG9Mb3dlckNhc2UoKSA9PT0gJ3N0eWxlJyB8fCBwcmVmZXJBdHRyKGVsZW1lbnQudGFnTmFtZSwgbm9ybWFsaXplZCkpKSB7CiAgICAgIHR5cGUgPSAnYXR0cic7CiAgICB9CgogICAgcmV0dXJuIHsKICAgICAgbm9ybWFsaXplZDogbm9ybWFsaXplZCwKICAgICAgdHlwZTogdHlwZQogICAgfTsKICB9IC8vIHByb3BlcnRpZXMgdGhhdCBNVVNUIGJlIHNldCBhcyBhdHRyaWJ1dGVzLCBkdWUgdG86CiAgLy8gKiBicm93c2VyIGJ1ZwogIC8vICogc3RyYW5nZSBzcGVjIG91dGxpZXIKCgogIHZhciBBVFRSX09WRVJSSURFUyA9IHsKICAgIElOUFVUOiB7CiAgICAgIGZvcm06IHRydWUsCiAgICAgIC8vIENocm9tZSA0Ni4wLjI0NjQuMDogJ2F1dG9jb3JyZWN0JyBpbiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbnB1dCcpID09PSBmYWxzZQogICAgICAvLyBTYWZhcmkgOC4wLjc6ICdhdXRvY29ycmVjdCcgaW4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKSA9PT0gZmFsc2UKICAgICAgLy8gTW9iaWxlIFNhZmFyaSAoaU9TIDguNCBzaW11bGF0b3IpOiAnYXV0b2NvcnJlY3QnIGluIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0JykgPT09IHRydWUKICAgICAgYXV0b2NvcnJlY3Q6IHRydWUsCiAgICAgIC8vIENocm9tZSA1NC4wLjI4NDAuOTg6ICdsaXN0JyBpbiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbnB1dCcpID09PSB0cnVlCiAgICAgIC8vIFNhZmFyaSA5LjEuMzogJ2xpc3QnIGluIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0JykgPT09IGZhbHNlCiAgICAgIGxpc3Q6IHRydWUKICAgIH0sCiAgICAvLyBlbGVtZW50LmZvcm0gaXMgYWN0dWFsbHkgYSBsZWdpdGltYXRlIHJlYWRPbmx5IHByb3BlcnR5LCB0aGF0IGlzIHRvIGJlCiAgICAvLyBtdXRhdGVkLCBidXQgbXVzdCBiZSBtdXRhdGVkIGJ5IHNldEF0dHJpYnV0ZS4uLgogICAgU0VMRUNUOiB7CiAgICAgIGZvcm06IHRydWUKICAgIH0sCiAgICBPUFRJT046IHsKICAgICAgZm9ybTogdHJ1ZQogICAgfSwKICAgIFRFWFRBUkVBOiB7CiAgICAgIGZvcm06IHRydWUKICAgIH0sCiAgICBMQUJFTDogewogICAgICBmb3JtOiB0cnVlCiAgICB9LAogICAgRklFTERTRVQ6IHsKICAgICAgZm9ybTogdHJ1ZQogICAgfSwKICAgIExFR0VORDogewogICAgICBmb3JtOiB0cnVlCiAgICB9LAogICAgT0JKRUNUOiB7CiAgICAgIGZvcm06IHRydWUKICAgIH0sCiAgICBCVVRUT046IHsKICAgICAgZm9ybTogdHJ1ZQogICAgfQogIH07CgogIGZ1bmN0aW9uIHByZWZlckF0dHIodGFnTmFtZSwgcHJvcE5hbWUpIHsKICAgIHZhciB0YWcgPSBBVFRSX09WRVJSSURFU1t0YWdOYW1lLnRvVXBwZXJDYXNlKCldOwogICAgcmV0dXJuIHRhZyAmJiB0YWdbcHJvcE5hbWUudG9Mb3dlckNhc2UoKV0gfHwgZmFsc2U7CiAgfQoKICBmdW5jdGlvbiBkeW5hbWljQXR0cmlidXRlKGVsZW1lbnQsIGF0dHIsIG5hbWVzcGFjZSkgewogICAgdmFyIHRhZ05hbWUgPSBlbGVtZW50LnRhZ05hbWUsCiAgICAgICAgbmFtZXNwYWNlVVJJID0gZWxlbWVudC5uYW1lc3BhY2VVUkk7CiAgICB2YXIgYXR0cmlidXRlID0gewogICAgICBlbGVtZW50OiBlbGVtZW50LAogICAgICBuYW1lOiBhdHRyLAogICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZQogICAgfTsKCiAgICBpZiAobmFtZXNwYWNlVVJJID09PSBTVkdfTkFNRVNQQUNFKSB7CiAgICAgIHJldHVybiBidWlsZER5bmFtaWNBdHRyaWJ1dGUodGFnTmFtZSwgYXR0ciwgYXR0cmlidXRlKTsKICAgIH0KCiAgICB2YXIgX25vcm1hbGl6ZVByb3BlcnR5ID0gbm9ybWFsaXplUHJvcGVydHkoZWxlbWVudCwgYXR0ciksCiAgICAgICAgdHlwZSA9IF9ub3JtYWxpemVQcm9wZXJ0eS50eXBlLAogICAgICAgIG5vcm1hbGl6ZWQgPSBfbm9ybWFsaXplUHJvcGVydHkubm9ybWFsaXplZDsKCiAgICBpZiAodHlwZSA9PT0gJ2F0dHInKSB7CiAgICAgIHJldHVybiBidWlsZER5bmFtaWNBdHRyaWJ1dGUodGFnTmFtZSwgbm9ybWFsaXplZCwgYXR0cmlidXRlKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBidWlsZER5bmFtaWNQcm9wZXJ0eSh0YWdOYW1lLCBub3JtYWxpemVkLCBhdHRyaWJ1dGUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gYnVpbGREeW5hbWljQXR0cmlidXRlKHRhZ05hbWUsIG5hbWUsIGF0dHJpYnV0ZSkgewogICAgaWYgKHJlcXVpcmVzU2FuaXRpemF0aW9uKHRhZ05hbWUsIG5hbWUpKSB7CiAgICAgIHJldHVybiBuZXcgU2FmZUR5bmFtaWNBdHRyaWJ1dGUoYXR0cmlidXRlKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBuZXcgU2ltcGxlRHluYW1pY0F0dHJpYnV0ZShhdHRyaWJ1dGUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gYnVpbGREeW5hbWljUHJvcGVydHkodGFnTmFtZSwgbmFtZSwgYXR0cmlidXRlKSB7CiAgICBpZiAocmVxdWlyZXNTYW5pdGl6YXRpb24odGFnTmFtZSwgbmFtZSkpIHsKICAgICAgcmV0dXJuIG5ldyBTYWZlRHluYW1pY1Byb3BlcnR5KG5hbWUsIGF0dHJpYnV0ZSk7CiAgICB9CgogICAgaWYgKGlzVXNlcklucHV0VmFsdWUodGFnTmFtZSwgbmFtZSkpIHsKICAgICAgcmV0dXJuIG5ldyBJbnB1dFZhbHVlRHluYW1pY0F0dHJpYnV0ZShuYW1lLCBhdHRyaWJ1dGUpOwogICAgfQoKICAgIGlmIChpc09wdGlvblNlbGVjdGVkKHRhZ05hbWUsIG5hbWUpKSB7CiAgICAgIHJldHVybiBuZXcgT3B0aW9uU2VsZWN0ZWREeW5hbWljQXR0cmlidXRlKG5hbWUsIGF0dHJpYnV0ZSk7CiAgICB9CgogICAgcmV0dXJuIG5ldyBEZWZhdWx0RHluYW1pY1Byb3BlcnR5KG5hbWUsIGF0dHJpYnV0ZSk7CiAgfQoKICB2YXIgRHluYW1pY0F0dHJpYnV0ZSA9IGZ1bmN0aW9uIER5bmFtaWNBdHRyaWJ1dGUoYXR0cmlidXRlKSB7CiAgICB0aGlzLmF0dHJpYnV0ZSA9IGF0dHJpYnV0ZTsKICB9OwoKICBfZXhwb3J0cy5EeW5hbWljQXR0cmlidXRlID0gRHluYW1pY0F0dHJpYnV0ZTsKCiAgdmFyIFNpbXBsZUR5bmFtaWNBdHRyaWJ1dGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0R5bmFtaWNBdHRyaWJ1dGUpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShTaW1wbGVEeW5hbWljQXR0cmlidXRlLCBfRHluYW1pY0F0dHJpYnV0ZSk7CgogICAgZnVuY3Rpb24gU2ltcGxlRHluYW1pY0F0dHJpYnV0ZSgpIHsKICAgICAgcmV0dXJuIF9EeW5hbWljQXR0cmlidXRlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvMzAgPSBTaW1wbGVEeW5hbWljQXR0cmlidXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zMC5zZXQgPSBmdW5jdGlvbiBzZXQoZG9tLCB2YWx1ZSQkMSwgX2VudikgewogICAgICB2YXIgbm9ybWFsaXplZFZhbHVlID0gbm9ybWFsaXplVmFsdWUodmFsdWUkJDEpOwoKICAgICAgaWYgKG5vcm1hbGl6ZWRWYWx1ZSAhPT0gbnVsbCkgewogICAgICAgIHZhciBfdGhpcyRhdHRyaWJ1dGUgPSB0aGlzLmF0dHJpYnV0ZSwKICAgICAgICAgICAgbmFtZSA9IF90aGlzJGF0dHJpYnV0ZS5uYW1lLAogICAgICAgICAgICBuYW1lc3BhY2UgPSBfdGhpcyRhdHRyaWJ1dGUubmFtZXNwYWNlOwoKICAgICAgICBkb20uX19zZXRBdHRyaWJ1dGUobmFtZSwgbm9ybWFsaXplZFZhbHVlLCBuYW1lc3BhY2UpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzMwLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZSh2YWx1ZSQkMSwgX2VudikgewogICAgICB2YXIgbm9ybWFsaXplZFZhbHVlID0gbm9ybWFsaXplVmFsdWUodmFsdWUkJDEpOwogICAgICB2YXIgX3RoaXMkYXR0cmlidXRlMiA9IHRoaXMuYXR0cmlidXRlLAogICAgICAgICAgZWxlbWVudCA9IF90aGlzJGF0dHJpYnV0ZTIuZWxlbWVudCwKICAgICAgICAgIG5hbWUgPSBfdGhpcyRhdHRyaWJ1dGUyLm5hbWU7CgogICAgICBpZiAobm9ybWFsaXplZFZhbHVlID09PSBudWxsKSB7CiAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUobmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUobmFtZSwgbm9ybWFsaXplZFZhbHVlKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gU2ltcGxlRHluYW1pY0F0dHJpYnV0ZTsKICB9KER5bmFtaWNBdHRyaWJ1dGUpOwoKICBfZXhwb3J0cy5TaW1wbGVEeW5hbWljQXR0cmlidXRlID0gU2ltcGxlRHluYW1pY0F0dHJpYnV0ZTsKCiAgdmFyIERlZmF1bHREeW5hbWljUHJvcGVydHkgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0R5bmFtaWNBdHRyaWJ1dGUyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoRGVmYXVsdER5bmFtaWNQcm9wZXJ0eSwgX0R5bmFtaWNBdHRyaWJ1dGUyKTsKCiAgICBmdW5jdGlvbiBEZWZhdWx0RHluYW1pY1Byb3BlcnR5KG5vcm1hbGl6ZWROYW1lLCBhdHRyaWJ1dGUpIHsKICAgICAgdmFyIF90aGlzMTQ7CgogICAgICBfdGhpczE0ID0gX0R5bmFtaWNBdHRyaWJ1dGUyLmNhbGwodGhpcywgYXR0cmlidXRlKSB8fCB0aGlzOwogICAgICBfdGhpczE0Lm5vcm1hbGl6ZWROYW1lID0gbm9ybWFsaXplZE5hbWU7CiAgICAgIHJldHVybiBfdGhpczE0OwogICAgfQoKICAgIHZhciBfcHJvdG8zMSA9IERlZmF1bHREeW5hbWljUHJvcGVydHkucHJvdG90eXBlOwoKICAgIF9wcm90bzMxLnNldCA9IGZ1bmN0aW9uIHNldChkb20sIHZhbHVlJCQxLCBfZW52KSB7CiAgICAgIGlmICh2YWx1ZSQkMSAhPT0gbnVsbCAmJiB2YWx1ZSQkMSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlJCQxOwoKICAgICAgICBkb20uX19zZXRQcm9wZXJ0eSh0aGlzLm5vcm1hbGl6ZWROYW1lLCB2YWx1ZSQkMSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMzEudXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKHZhbHVlJCQxLCBfZW52KSB7CiAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5hdHRyaWJ1dGUuZWxlbWVudDsKCiAgICAgIGlmICh0aGlzLnZhbHVlICE9PSB2YWx1ZSQkMSkgewogICAgICAgIGVsZW1lbnRbdGhpcy5ub3JtYWxpemVkTmFtZV0gPSB0aGlzLnZhbHVlID0gdmFsdWUkJDE7CgogICAgICAgIGlmICh2YWx1ZSQkMSA9PT0gbnVsbCB8fCB2YWx1ZSQkMSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB0aGlzLnJlbW92ZUF0dHJpYnV0ZSgpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zMS5yZW1vdmVBdHRyaWJ1dGUgPSBmdW5jdGlvbiByZW1vdmVBdHRyaWJ1dGUoKSB7CiAgICAgIC8vIFRPRE8gdGhpcyBzdWNrcyBidXQgdG8gcHJlc2VydmUgcHJvcGVydGllcyBmaXJzdCBhbmQgdG8gbWVldCBjdXJyZW50CiAgICAgIC8vIHNlbWFudGljcyB3ZSBtdXN0IGRvIHRoaXMuCiAgICAgIHZhciBfdGhpcyRhdHRyaWJ1dGUzID0gdGhpcy5hdHRyaWJ1dGUsCiAgICAgICAgICBlbGVtZW50ID0gX3RoaXMkYXR0cmlidXRlMy5lbGVtZW50LAogICAgICAgICAgbmFtZXNwYWNlID0gX3RoaXMkYXR0cmlidXRlMy5uYW1lc3BhY2U7CgogICAgICBpZiAobmFtZXNwYWNlKSB7CiAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGVOUyhuYW1lc3BhY2UsIHRoaXMubm9ybWFsaXplZE5hbWUpOwogICAgICB9IGVsc2UgewogICAgICAgIGVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKHRoaXMubm9ybWFsaXplZE5hbWUpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBEZWZhdWx0RHluYW1pY1Byb3BlcnR5OwogIH0oRHluYW1pY0F0dHJpYnV0ZSk7CgogIHZhciBTYWZlRHluYW1pY1Byb3BlcnR5ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9EZWZhdWx0RHluYW1pY1Byb3BlcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFNhZmVEeW5hbWljUHJvcGVydHksIF9EZWZhdWx0RHluYW1pY1Byb3Blcik7CgogICAgZnVuY3Rpb24gU2FmZUR5bmFtaWNQcm9wZXJ0eSgpIHsKICAgICAgcmV0dXJuIF9EZWZhdWx0RHluYW1pY1Byb3Blci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzMyID0gU2FmZUR5bmFtaWNQcm9wZXJ0eS5wcm90b3R5cGU7CgogICAgX3Byb3RvMzIuc2V0ID0gZnVuY3Rpb24gc2V0KGRvbSwgdmFsdWUkJDEsIGVudikgewogICAgICB2YXIgX3RoaXMkYXR0cmlidXRlNCA9IHRoaXMuYXR0cmlidXRlLAogICAgICAgICAgZWxlbWVudCA9IF90aGlzJGF0dHJpYnV0ZTQuZWxlbWVudCwKICAgICAgICAgIG5hbWUgPSBfdGhpcyRhdHRyaWJ1dGU0Lm5hbWU7CiAgICAgIHZhciBzYW5pdGl6ZWQgPSBzYW5pdGl6ZUF0dHJpYnV0ZVZhbHVlKGVudiwgZWxlbWVudCwgbmFtZSwgdmFsdWUkJDEpOwoKICAgICAgX0RlZmF1bHREeW5hbWljUHJvcGVyLnByb3RvdHlwZS5zZXQuY2FsbCh0aGlzLCBkb20sIHNhbml0aXplZCwgZW52KTsKICAgIH07CgogICAgX3Byb3RvMzIudXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKHZhbHVlJCQxLCBlbnYpIHsKICAgICAgdmFyIF90aGlzJGF0dHJpYnV0ZTUgPSB0aGlzLmF0dHJpYnV0ZSwKICAgICAgICAgIGVsZW1lbnQgPSBfdGhpcyRhdHRyaWJ1dGU1LmVsZW1lbnQsCiAgICAgICAgICBuYW1lID0gX3RoaXMkYXR0cmlidXRlNS5uYW1lOwogICAgICB2YXIgc2FuaXRpemVkID0gc2FuaXRpemVBdHRyaWJ1dGVWYWx1ZShlbnYsIGVsZW1lbnQsIG5hbWUsIHZhbHVlJCQxKTsKCiAgICAgIF9EZWZhdWx0RHluYW1pY1Byb3Blci5wcm90b3R5cGUudXBkYXRlLmNhbGwodGhpcywgc2FuaXRpemVkLCBlbnYpOwogICAgfTsKCiAgICByZXR1cm4gU2FmZUR5bmFtaWNQcm9wZXJ0eTsKICB9KERlZmF1bHREeW5hbWljUHJvcGVydHkpOwoKICB2YXIgU2FmZUR5bmFtaWNBdHRyaWJ1dGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1NpbXBsZUR5bmFtaWNBdHRyaWJ1KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoU2FmZUR5bmFtaWNBdHRyaWJ1dGUsIF9TaW1wbGVEeW5hbWljQXR0cmlidSk7CgogICAgZnVuY3Rpb24gU2FmZUR5bmFtaWNBdHRyaWJ1dGUoKSB7CiAgICAgIHJldHVybiBfU2ltcGxlRHluYW1pY0F0dHJpYnUuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8zMyA9IFNhZmVEeW5hbWljQXR0cmlidXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zMy5zZXQgPSBmdW5jdGlvbiBzZXQoZG9tLCB2YWx1ZSQkMSwgZW52KSB7CiAgICAgIHZhciBfdGhpcyRhdHRyaWJ1dGU2ID0gdGhpcy5hdHRyaWJ1dGUsCiAgICAgICAgICBlbGVtZW50ID0gX3RoaXMkYXR0cmlidXRlNi5lbGVtZW50LAogICAgICAgICAgbmFtZSA9IF90aGlzJGF0dHJpYnV0ZTYubmFtZTsKICAgICAgdmFyIHNhbml0aXplZCA9IHNhbml0aXplQXR0cmlidXRlVmFsdWUoZW52LCBlbGVtZW50LCBuYW1lLCB2YWx1ZSQkMSk7CgogICAgICBfU2ltcGxlRHluYW1pY0F0dHJpYnUucHJvdG90eXBlLnNldC5jYWxsKHRoaXMsIGRvbSwgc2FuaXRpemVkLCBlbnYpOwogICAgfTsKCiAgICBfcHJvdG8zMy51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUodmFsdWUkJDEsIGVudikgewogICAgICB2YXIgX3RoaXMkYXR0cmlidXRlNyA9IHRoaXMuYXR0cmlidXRlLAogICAgICAgICAgZWxlbWVudCA9IF90aGlzJGF0dHJpYnV0ZTcuZWxlbWVudCwKICAgICAgICAgIG5hbWUgPSBfdGhpcyRhdHRyaWJ1dGU3Lm5hbWU7CiAgICAgIHZhciBzYW5pdGl6ZWQgPSBzYW5pdGl6ZUF0dHJpYnV0ZVZhbHVlKGVudiwgZWxlbWVudCwgbmFtZSwgdmFsdWUkJDEpOwoKICAgICAgX1NpbXBsZUR5bmFtaWNBdHRyaWJ1LnByb3RvdHlwZS51cGRhdGUuY2FsbCh0aGlzLCBzYW5pdGl6ZWQsIGVudik7CiAgICB9OwoKICAgIHJldHVybiBTYWZlRHluYW1pY0F0dHJpYnV0ZTsKICB9KFNpbXBsZUR5bmFtaWNBdHRyaWJ1dGUpOwoKICB2YXIgSW5wdXRWYWx1ZUR5bmFtaWNBdHRyaWJ1dGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0RlZmF1bHREeW5hbWljUHJvcGVyMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKElucHV0VmFsdWVEeW5hbWljQXR0cmlidXRlLCBfRGVmYXVsdER5bmFtaWNQcm9wZXIyKTsKCiAgICBmdW5jdGlvbiBJbnB1dFZhbHVlRHluYW1pY0F0dHJpYnV0ZSgpIHsKICAgICAgcmV0dXJuIF9EZWZhdWx0RHluYW1pY1Byb3BlcjIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8zNCA9IElucHV0VmFsdWVEeW5hbWljQXR0cmlidXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zNC5zZXQgPSBmdW5jdGlvbiBzZXQoZG9tLCB2YWx1ZSQkMSkgewogICAgICBkb20uX19zZXRQcm9wZXJ0eSgndmFsdWUnLCBub3JtYWxpemVTdHJpbmdWYWx1ZSh2YWx1ZSQkMSkpOwogICAgfTsKCiAgICBfcHJvdG8zNC51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUodmFsdWUkJDEpIHsKICAgICAgdmFyIGlucHV0ID0gdGhpcy5hdHRyaWJ1dGUuZWxlbWVudDsKICAgICAgdmFyIGN1cnJlbnRWYWx1ZSA9IGlucHV0LnZhbHVlOwogICAgICB2YXIgbm9ybWFsaXplZFZhbHVlID0gbm9ybWFsaXplU3RyaW5nVmFsdWUodmFsdWUkJDEpOwoKICAgICAgaWYgKGN1cnJlbnRWYWx1ZSAhPT0gbm9ybWFsaXplZFZhbHVlKSB7CiAgICAgICAgaW5wdXQudmFsdWUgPSBub3JtYWxpemVkVmFsdWU7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIElucHV0VmFsdWVEeW5hbWljQXR0cmlidXRlOwogIH0oRGVmYXVsdER5bmFtaWNQcm9wZXJ0eSk7CgogIHZhciBPcHRpb25TZWxlY3RlZER5bmFtaWNBdHRyaWJ1dGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0RlZmF1bHREeW5hbWljUHJvcGVyMykgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKE9wdGlvblNlbGVjdGVkRHluYW1pY0F0dHJpYnV0ZSwgX0RlZmF1bHREeW5hbWljUHJvcGVyMyk7CgogICAgZnVuY3Rpb24gT3B0aW9uU2VsZWN0ZWREeW5hbWljQXR0cmlidXRlKCkgewogICAgICByZXR1cm4gX0RlZmF1bHREeW5hbWljUHJvcGVyMy5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzM1ID0gT3B0aW9uU2VsZWN0ZWREeW5hbWljQXR0cmlidXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zNS5zZXQgPSBmdW5jdGlvbiBzZXQoZG9tLCB2YWx1ZSQkMSkgewogICAgICBpZiAodmFsdWUkJDEgIT09IG51bGwgJiYgdmFsdWUkJDEgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSQkMSAhPT0gZmFsc2UpIHsKICAgICAgICBkb20uX19zZXRQcm9wZXJ0eSgnc2VsZWN0ZWQnLCB0cnVlKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zNS51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUodmFsdWUkJDEpIHsKICAgICAgdmFyIG9wdGlvbiA9IHRoaXMuYXR0cmlidXRlLmVsZW1lbnQ7CgogICAgICBpZiAodmFsdWUkJDEpIHsKICAgICAgICBvcHRpb24uc2VsZWN0ZWQgPSB0cnVlOwogICAgICB9IGVsc2UgewogICAgICAgIG9wdGlvbi5zZWxlY3RlZCA9IGZhbHNlOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBPcHRpb25TZWxlY3RlZER5bmFtaWNBdHRyaWJ1dGU7CiAgfShEZWZhdWx0RHluYW1pY1Byb3BlcnR5KTsKCiAgZnVuY3Rpb24gaXNPcHRpb25TZWxlY3RlZCh0YWdOYW1lLCBhdHRyaWJ1dGUpIHsKICAgIHJldHVybiB0YWdOYW1lID09PSAnT1BUSU9OJyAmJiBhdHRyaWJ1dGUgPT09ICdzZWxlY3RlZCc7CiAgfQoKICBmdW5jdGlvbiBpc1VzZXJJbnB1dFZhbHVlKHRhZ05hbWUsIGF0dHJpYnV0ZSkgewogICAgcmV0dXJuICh0YWdOYW1lID09PSAnSU5QVVQnIHx8IHRhZ05hbWUgPT09ICdURVhUQVJFQScpICYmIGF0dHJpYnV0ZSA9PT0gJ3ZhbHVlJzsKICB9CgogIGZ1bmN0aW9uIG5vcm1hbGl6ZVZhbHVlKHZhbHVlJCQxKSB7CiAgICBpZiAodmFsdWUkJDEgPT09IGZhbHNlIHx8IHZhbHVlJCQxID09PSB1bmRlZmluZWQgfHwgdmFsdWUkJDEgPT09IG51bGwgfHwgdHlwZW9mIHZhbHVlJCQxLnRvU3RyaW5nID09PSAndW5kZWZpbmVkJykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KCiAgICBpZiAodmFsdWUkJDEgPT09IHRydWUpIHsKICAgICAgcmV0dXJuICcnOwogICAgfSAvLyBvbmNsaWNrIGZ1bmN0aW9uIGV0YyBpbiBTU1IKCgogICAgaWYgKHR5cGVvZiB2YWx1ZSQkMSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KCiAgICByZXR1cm4gU3RyaW5nKHZhbHVlJCQxKTsKICB9CgogIHZhciBTY29wZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFNjb3BlKCAvLyB0aGUgMHRoIHNsb3QgaXMgYHNlbGZgCiAgICBzbG90cywgY2FsbGVyU2NvcGUsIC8vIG5hbWVkIGFyZ3VtZW50cyBhbmQgYmxvY2tzIHBhc3NlZCB0byBhIGxheW91dCB0aGF0IHVzZXMgZXZhbAogICAgZXZhbFNjb3BlLCAvLyBsb2NhbHMgaW4gc2NvcGUgd2hlbiB0aGUgcGFydGlhbCB3YXMgaW52b2tlZAogICAgcGFydGlhbE1hcCkgewogICAgICB0aGlzLnNsb3RzID0gc2xvdHM7CiAgICAgIHRoaXMuY2FsbGVyU2NvcGUgPSBjYWxsZXJTY29wZTsKICAgICAgdGhpcy5ldmFsU2NvcGUgPSBldmFsU2NvcGU7CiAgICAgIHRoaXMucGFydGlhbE1hcCA9IHBhcnRpYWxNYXA7CiAgICB9CgogICAgU2NvcGUucm9vdCA9IGZ1bmN0aW9uIHJvb3Qoc2VsZiwgc2l6ZSkgewogICAgICBpZiAoc2l6ZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgc2l6ZSA9IDA7CiAgICAgIH0KCiAgICAgIHZhciByZWZzID0gbmV3IEFycmF5KHNpemUgKyAxKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDw9IHNpemU7IGkrKykgewogICAgICAgIHJlZnNbaV0gPSBVTkRFRklORURfUkVGRVJFTkNFOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IFNjb3BlKHJlZnMsIG51bGwsIG51bGwsIG51bGwpLmluaXQoewogICAgICAgIHNlbGY6IHNlbGYKICAgICAgfSk7CiAgICB9OwoKICAgIFNjb3BlLnNpemVkID0gZnVuY3Rpb24gc2l6ZWQoc2l6ZSkgewogICAgICBpZiAoc2l6ZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgc2l6ZSA9IDA7CiAgICAgIH0KCiAgICAgIHZhciByZWZzID0gbmV3IEFycmF5KHNpemUgKyAxKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDw9IHNpemU7IGkrKykgewogICAgICAgIHJlZnNbaV0gPSBVTkRFRklORURfUkVGRVJFTkNFOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IFNjb3BlKHJlZnMsIG51bGwsIG51bGwsIG51bGwpOwogICAgfTsKCiAgICB2YXIgX3Byb3RvMzYgPSBTY29wZS5wcm90b3R5cGU7CgogICAgX3Byb3RvMzYuaW5pdCA9IGZ1bmN0aW9uIGluaXQoX3JlZjU1KSB7CiAgICAgIHZhciBzZWxmID0gX3JlZjU1LnNlbGY7CiAgICAgIHRoaXMuc2xvdHNbMF0gPSBzZWxmOwogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgX3Byb3RvMzYuZ2V0U2VsZiA9IGZ1bmN0aW9uIGdldFNlbGYoKSB7CiAgICAgIHJldHVybiB0aGlzLmdldCgwKTsKICAgIH07CgogICAgX3Byb3RvMzYuZ2V0U3ltYm9sID0gZnVuY3Rpb24gZ2V0U3ltYm9sKHN5bWJvbCkgewogICAgICByZXR1cm4gdGhpcy5nZXQoc3ltYm9sKTsKICAgIH07CgogICAgX3Byb3RvMzYuZ2V0QmxvY2sgPSBmdW5jdGlvbiBnZXRCbG9jayhzeW1ib2wpIHsKICAgICAgdmFyIGJsb2NrID0gdGhpcy5nZXQoc3ltYm9sKTsKICAgICAgcmV0dXJuIGJsb2NrID09PSBVTkRFRklORURfUkVGRVJFTkNFID8gbnVsbCA6IGJsb2NrOwogICAgfTsKCiAgICBfcHJvdG8zNi5nZXRFdmFsU2NvcGUgPSBmdW5jdGlvbiBnZXRFdmFsU2NvcGUoKSB7CiAgICAgIHJldHVybiB0aGlzLmV2YWxTY29wZTsKICAgIH07CgogICAgX3Byb3RvMzYuZ2V0UGFydGlhbE1hcCA9IGZ1bmN0aW9uIGdldFBhcnRpYWxNYXAoKSB7CiAgICAgIHJldHVybiB0aGlzLnBhcnRpYWxNYXA7CiAgICB9OwoKICAgIF9wcm90bzM2LmJpbmQgPSBmdW5jdGlvbiBiaW5kKHN5bWJvbCwgdmFsdWUkJDEpIHsKICAgICAgdGhpcy5zZXQoc3ltYm9sLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzM2LmJpbmRTZWxmID0gZnVuY3Rpb24gYmluZFNlbGYoc2VsZikgewogICAgICB0aGlzLnNldCgwLCBzZWxmKTsKICAgIH07CgogICAgX3Byb3RvMzYuYmluZFN5bWJvbCA9IGZ1bmN0aW9uIGJpbmRTeW1ib2woc3ltYm9sLCB2YWx1ZSQkMSkgewogICAgICB0aGlzLnNldChzeW1ib2wsIHZhbHVlJCQxKTsKICAgIH07CgogICAgX3Byb3RvMzYuYmluZEJsb2NrID0gZnVuY3Rpb24gYmluZEJsb2NrKHN5bWJvbCwgdmFsdWUkJDEpIHsKICAgICAgdGhpcy5zZXQoc3ltYm9sLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzM2LmJpbmRFdmFsU2NvcGUgPSBmdW5jdGlvbiBiaW5kRXZhbFNjb3BlKG1hcCkgewogICAgICB0aGlzLmV2YWxTY29wZSA9IG1hcDsKICAgIH07CgogICAgX3Byb3RvMzYuYmluZFBhcnRpYWxNYXAgPSBmdW5jdGlvbiBiaW5kUGFydGlhbE1hcChtYXApIHsKICAgICAgdGhpcy5wYXJ0aWFsTWFwID0gbWFwOwogICAgfTsKCiAgICBfcHJvdG8zNi5iaW5kQ2FsbGVyU2NvcGUgPSBmdW5jdGlvbiBiaW5kQ2FsbGVyU2NvcGUoc2NvcGUpIHsKICAgICAgdGhpcy5jYWxsZXJTY29wZSA9IHNjb3BlOwogICAgfTsKCiAgICBfcHJvdG8zNi5nZXRDYWxsZXJTY29wZSA9IGZ1bmN0aW9uIGdldENhbGxlclNjb3BlKCkgewogICAgICByZXR1cm4gdGhpcy5jYWxsZXJTY29wZTsKICAgIH07CgogICAgX3Byb3RvMzYuY2hpbGQgPSBmdW5jdGlvbiBjaGlsZCgpIHsKICAgICAgcmV0dXJuIG5ldyBTY29wZSh0aGlzLnNsb3RzLnNsaWNlKCksIHRoaXMuY2FsbGVyU2NvcGUsIHRoaXMuZXZhbFNjb3BlLCB0aGlzLnBhcnRpYWxNYXApOwogICAgfTsKCiAgICBfcHJvdG8zNi5nZXQgPSBmdW5jdGlvbiBnZXQoaW5kZXgpIHsKICAgICAgaWYgKGluZGV4ID49IHRoaXMuc2xvdHMubGVuZ3RoKSB7CiAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoIkJVRzogY2Fubm90IGdldCAkIiArIGluZGV4ICsgIiBmcm9tIHNjb3BlOyBsZW5ndGg9IiArIHRoaXMuc2xvdHMubGVuZ3RoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuc2xvdHNbaW5kZXhdOwogICAgfTsKCiAgICBfcHJvdG8zNi5zZXQgPSBmdW5jdGlvbiBzZXQoaW5kZXgsIHZhbHVlJCQxKSB7CiAgICAgIGlmIChpbmRleCA+PSB0aGlzLnNsb3RzLmxlbmd0aCkgewogICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCJCVUc6IGNhbm5vdCBnZXQgJCIgKyBpbmRleCArICIgZnJvbSBzY29wZTsgbGVuZ3RoPSIgKyB0aGlzLnNsb3RzLmxlbmd0aCk7CiAgICAgIH0KCiAgICAgIHRoaXMuc2xvdHNbaW5kZXhdID0gdmFsdWUkJDE7CiAgICB9OwoKICAgIHJldHVybiBTY29wZTsKICB9KCk7CgogIF9leHBvcnRzLlNjb3BlID0gU2NvcGU7CgogIHZhciBUcmFuc2FjdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFRyYW5zYWN0aW9uKCkgewogICAgICB0aGlzLnNjaGVkdWxlZEluc3RhbGxNYW5hZ2VycyA9IFtdOwogICAgICB0aGlzLnNjaGVkdWxlZEluc3RhbGxNb2RpZmllcnMgPSBbXTsKICAgICAgdGhpcy5zY2hlZHVsZWRVcGRhdGVNb2RpZmllck1hbmFnZXJzID0gW107CiAgICAgIHRoaXMuc2NoZWR1bGVkVXBkYXRlTW9kaWZpZXJzID0gW107CiAgICAgIHRoaXMuY3JlYXRlZENvbXBvbmVudHMgPSBbXTsKICAgICAgdGhpcy5jcmVhdGVkTWFuYWdlcnMgPSBbXTsKICAgICAgdGhpcy51cGRhdGVkQ29tcG9uZW50cyA9IFtdOwogICAgICB0aGlzLnVwZGF0ZWRNYW5hZ2VycyA9IFtdOwogICAgICB0aGlzLmRlc3RydWN0b3JzID0gW107CiAgICB9CgogICAgdmFyIF9wcm90bzM3ID0gVHJhbnNhY3Rpb24ucHJvdG90eXBlOwoKICAgIF9wcm90bzM3LmRpZENyZWF0ZSA9IGZ1bmN0aW9uIGRpZENyZWF0ZShjb21wb25lbnQsIG1hbmFnZXIpIHsKICAgICAgdGhpcy5jcmVhdGVkQ29tcG9uZW50cy5wdXNoKGNvbXBvbmVudCk7CiAgICAgIHRoaXMuY3JlYXRlZE1hbmFnZXJzLnB1c2gobWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM3LmRpZFVwZGF0ZSA9IGZ1bmN0aW9uIGRpZFVwZGF0ZShjb21wb25lbnQsIG1hbmFnZXIpIHsKICAgICAgdGhpcy51cGRhdGVkQ29tcG9uZW50cy5wdXNoKGNvbXBvbmVudCk7CiAgICAgIHRoaXMudXBkYXRlZE1hbmFnZXJzLnB1c2gobWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM3LnNjaGVkdWxlSW5zdGFsbE1vZGlmaWVyID0gZnVuY3Rpb24gc2NoZWR1bGVJbnN0YWxsTW9kaWZpZXIobW9kaWZpZXIsIG1hbmFnZXIpIHsKICAgICAgdGhpcy5zY2hlZHVsZWRJbnN0YWxsTW9kaWZpZXJzLnB1c2gobW9kaWZpZXIpOwogICAgICB0aGlzLnNjaGVkdWxlZEluc3RhbGxNYW5hZ2Vycy5wdXNoKG1hbmFnZXIpOwogICAgfTsKCiAgICBfcHJvdG8zNy5zY2hlZHVsZVVwZGF0ZU1vZGlmaWVyID0gZnVuY3Rpb24gc2NoZWR1bGVVcGRhdGVNb2RpZmllcihtb2RpZmllciwgbWFuYWdlcikgewogICAgICB0aGlzLnNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVycy5wdXNoKG1vZGlmaWVyKTsKICAgICAgdGhpcy5zY2hlZHVsZWRVcGRhdGVNb2RpZmllck1hbmFnZXJzLnB1c2gobWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM3LmRpZERlc3Ryb3kgPSBmdW5jdGlvbiBkaWREZXN0cm95KGQpIHsKICAgICAgdGhpcy5kZXN0cnVjdG9ycy5wdXNoKGQpOwogICAgfTsKCiAgICBfcHJvdG8zNy5jb21taXQgPSBmdW5jdGlvbiBjb21taXQoKSB7CiAgICAgIHZhciBjcmVhdGVkQ29tcG9uZW50cyA9IHRoaXMuY3JlYXRlZENvbXBvbmVudHMsCiAgICAgICAgICBjcmVhdGVkTWFuYWdlcnMgPSB0aGlzLmNyZWF0ZWRNYW5hZ2VyczsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY3JlYXRlZENvbXBvbmVudHMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgY29tcG9uZW50ID0gY3JlYXRlZENvbXBvbmVudHNbaV07CiAgICAgICAgdmFyIG1hbmFnZXIgPSBjcmVhdGVkTWFuYWdlcnNbaV07CiAgICAgICAgbWFuYWdlci5kaWRDcmVhdGUoY29tcG9uZW50KTsKICAgICAgfQoKICAgICAgdmFyIHVwZGF0ZWRDb21wb25lbnRzID0gdGhpcy51cGRhdGVkQ29tcG9uZW50cywKICAgICAgICAgIHVwZGF0ZWRNYW5hZ2VycyA9IHRoaXMudXBkYXRlZE1hbmFnZXJzOwoKICAgICAgZm9yICh2YXIgX2k0ID0gMDsgX2k0IDwgdXBkYXRlZENvbXBvbmVudHMubGVuZ3RoOyBfaTQrKykgewogICAgICAgIHZhciBfY29tcG9uZW50ID0gdXBkYXRlZENvbXBvbmVudHNbX2k0XTsKICAgICAgICB2YXIgX21hbmFnZXIyID0gdXBkYXRlZE1hbmFnZXJzW19pNF07CgogICAgICAgIF9tYW5hZ2VyMi5kaWRVcGRhdGUoX2NvbXBvbmVudCk7CiAgICAgIH0KCiAgICAgIHZhciBkZXN0cnVjdG9ycyA9IHRoaXMuZGVzdHJ1Y3RvcnM7CgogICAgICBmb3IgKHZhciBfaTUgPSAwOyBfaTUgPCBkZXN0cnVjdG9ycy5sZW5ndGg7IF9pNSsrKSB7CiAgICAgICAgZGVzdHJ1Y3RvcnNbX2k1XS5kZXN0cm95KCk7CiAgICAgIH0KCiAgICAgIHZhciBzY2hlZHVsZWRJbnN0YWxsTWFuYWdlcnMgPSB0aGlzLnNjaGVkdWxlZEluc3RhbGxNYW5hZ2VycywKICAgICAgICAgIHNjaGVkdWxlZEluc3RhbGxNb2RpZmllcnMgPSB0aGlzLnNjaGVkdWxlZEluc3RhbGxNb2RpZmllcnM7CgogICAgICBmb3IgKHZhciBfaTYgPSAwOyBfaTYgPCBzY2hlZHVsZWRJbnN0YWxsTWFuYWdlcnMubGVuZ3RoOyBfaTYrKykgewogICAgICAgIHZhciBtb2RpZmllciA9IHNjaGVkdWxlZEluc3RhbGxNb2RpZmllcnNbX2k2XTsKICAgICAgICB2YXIgX21hbmFnZXIzID0gc2NoZWR1bGVkSW5zdGFsbE1hbmFnZXJzW19pNl07CgogICAgICAgIF9tYW5hZ2VyMy5pbnN0YWxsKG1vZGlmaWVyKTsKICAgICAgfQoKICAgICAgdmFyIHNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVyTWFuYWdlcnMgPSB0aGlzLnNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVyTWFuYWdlcnMsCiAgICAgICAgICBzY2hlZHVsZWRVcGRhdGVNb2RpZmllcnMgPSB0aGlzLnNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVyczsKCiAgICAgIGZvciAodmFyIF9pNyA9IDA7IF9pNyA8IHNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVyTWFuYWdlcnMubGVuZ3RoOyBfaTcrKykgewogICAgICAgIHZhciBfbW9kaWZpZXIgPSBzY2hlZHVsZWRVcGRhdGVNb2RpZmllcnNbX2k3XTsKICAgICAgICB2YXIgX21hbmFnZXI0ID0gc2NoZWR1bGVkVXBkYXRlTW9kaWZpZXJNYW5hZ2Vyc1tfaTddOwoKICAgICAgICBfbWFuYWdlcjQudXBkYXRlKF9tb2RpZmllcik7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIFRyYW5zYWN0aW9uOwogIH0oKTsKCiAgdmFyIEVudmlyb25tZW50ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRW52aXJvbm1lbnQoX3JlZjU2KSB7CiAgICAgIHZhciBhcHBlbmRPcGVyYXRpb25zID0gX3JlZjU2LmFwcGVuZE9wZXJhdGlvbnMsCiAgICAgICAgICB1cGRhdGVPcGVyYXRpb25zID0gX3JlZjU2LnVwZGF0ZU9wZXJhdGlvbnM7CiAgICAgIHRoaXMuX3RyYW5zYWN0aW9uID0gbnVsbDsKICAgICAgdGhpcy5hcHBlbmRPcGVyYXRpb25zID0gYXBwZW5kT3BlcmF0aW9uczsKICAgICAgdGhpcy51cGRhdGVPcGVyYXRpb25zID0gdXBkYXRlT3BlcmF0aW9uczsKICAgIH0KCiAgICB2YXIgX3Byb3RvMzggPSBFbnZpcm9ubWVudC5wcm90b3R5cGU7CgogICAgX3Byb3RvMzgudG9Db25kaXRpb25hbFJlZmVyZW5jZSA9IGZ1bmN0aW9uIHRvQ29uZGl0aW9uYWxSZWZlcmVuY2UocmVmZXJlbmNlKSB7CiAgICAgIHJldHVybiBuZXcgQ29uZGl0aW9uYWxSZWZlcmVuY2UocmVmZXJlbmNlKTsKICAgIH07CgogICAgX3Byb3RvMzguZ2V0QXBwZW5kT3BlcmF0aW9ucyA9IGZ1bmN0aW9uIGdldEFwcGVuZE9wZXJhdGlvbnMoKSB7CiAgICAgIHJldHVybiB0aGlzLmFwcGVuZE9wZXJhdGlvbnM7CiAgICB9OwoKICAgIF9wcm90bzM4LmdldERPTSA9IGZ1bmN0aW9uIGdldERPTSgpIHsKICAgICAgcmV0dXJuIHRoaXMudXBkYXRlT3BlcmF0aW9uczsKICAgIH07CgogICAgX3Byb3RvMzguYmVnaW4gPSBmdW5jdGlvbiBiZWdpbigpIHsKICAgICAgdGhpcy5fdHJhbnNhY3Rpb24gPSBuZXcgVHJhbnNhY3Rpb24oKTsKICAgIH07CgogICAgX3Byb3RvMzguZGlkQ3JlYXRlID0gZnVuY3Rpb24gZGlkQ3JlYXRlKGNvbXBvbmVudCwgbWFuYWdlcikgewogICAgICB0aGlzLnRyYW5zYWN0aW9uLmRpZENyZWF0ZShjb21wb25lbnQsIG1hbmFnZXIpOwogICAgfTsKCiAgICBfcHJvdG8zOC5kaWRVcGRhdGUgPSBmdW5jdGlvbiBkaWRVcGRhdGUoY29tcG9uZW50LCBtYW5hZ2VyKSB7CiAgICAgIHRoaXMudHJhbnNhY3Rpb24uZGlkVXBkYXRlKGNvbXBvbmVudCwgbWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM4LnNjaGVkdWxlSW5zdGFsbE1vZGlmaWVyID0gZnVuY3Rpb24gc2NoZWR1bGVJbnN0YWxsTW9kaWZpZXIobW9kaWZpZXIsIG1hbmFnZXIpIHsKICAgICAgdGhpcy50cmFuc2FjdGlvbi5zY2hlZHVsZUluc3RhbGxNb2RpZmllcihtb2RpZmllciwgbWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM4LnNjaGVkdWxlVXBkYXRlTW9kaWZpZXIgPSBmdW5jdGlvbiBzY2hlZHVsZVVwZGF0ZU1vZGlmaWVyKG1vZGlmaWVyLCBtYW5hZ2VyKSB7CiAgICAgIHRoaXMudHJhbnNhY3Rpb24uc2NoZWR1bGVVcGRhdGVNb2RpZmllcihtb2RpZmllciwgbWFuYWdlcik7CiAgICB9OwoKICAgIF9wcm90bzM4LmRpZERlc3Ryb3kgPSBmdW5jdGlvbiBkaWREZXN0cm95KGQpIHsKICAgICAgdGhpcy50cmFuc2FjdGlvbi5kaWREZXN0cm95KGQpOwogICAgfTsKCiAgICBfcHJvdG8zOC5jb21taXQgPSBmdW5jdGlvbiBjb21taXQoKSB7CiAgICAgIHZhciB0cmFuc2FjdGlvbiA9IHRoaXMudHJhbnNhY3Rpb247CiAgICAgIHRoaXMuX3RyYW5zYWN0aW9uID0gbnVsbDsKICAgICAgdHJhbnNhY3Rpb24uY29tbWl0KCk7CiAgICB9OwoKICAgIF9wcm90bzM4LmF0dHJpYnV0ZUZvciA9IGZ1bmN0aW9uIGF0dHJpYnV0ZUZvcihlbGVtZW50LCBhdHRyLCBfaXNUcnVzdGluZywgbmFtZXNwYWNlKSB7CiAgICAgIGlmIChuYW1lc3BhY2UgPT09IHZvaWQgMCkgewogICAgICAgIG5hbWVzcGFjZSA9IG51bGw7CiAgICAgIH0KCiAgICAgIHJldHVybiBkeW5hbWljQXR0cmlidXRlKGVsZW1lbnQsIGF0dHIsIG5hbWVzcGFjZSk7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoRW52aXJvbm1lbnQsIFt7CiAgICAgIGtleTogInRyYW5zYWN0aW9uIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3RyYW5zYWN0aW9uOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gRW52aXJvbm1lbnQ7CiAgfSgpOwoKICBfZXhwb3J0cy5FbnZpcm9ubWVudCA9IEVudmlyb25tZW50OwoKICB2YXIgRGVmYXVsdEVudmlyb25tZW50ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9FbnZpcm9ubWVudCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKERlZmF1bHRFbnZpcm9ubWVudCwgX0Vudmlyb25tZW50KTsKCiAgICBmdW5jdGlvbiBEZWZhdWx0RW52aXJvbm1lbnQob3B0aW9ucykgewogICAgICBpZiAoIW9wdGlvbnMpIHsKICAgICAgICB2YXIgX2RvY3VtZW50ID0gd2luZG93LmRvY3VtZW50OwogICAgICAgIHZhciBhcHBlbmRPcGVyYXRpb25zID0gbmV3IERPTVRyZWVDb25zdHJ1Y3Rpb24oX2RvY3VtZW50KTsKICAgICAgICB2YXIgdXBkYXRlT3BlcmF0aW9ucyA9IG5ldyBET01DaGFuZ2VzKF9kb2N1bWVudCk7CiAgICAgICAgb3B0aW9ucyA9IHsKICAgICAgICAgIGFwcGVuZE9wZXJhdGlvbnM6IGFwcGVuZE9wZXJhdGlvbnMsCiAgICAgICAgICB1cGRhdGVPcGVyYXRpb25zOiB1cGRhdGVPcGVyYXRpb25zCiAgICAgICAgfTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9FbnZpcm9ubWVudC5jYWxsKHRoaXMsIG9wdGlvbnMpIHx8IHRoaXM7CiAgICB9CgogICAgcmV0dXJuIERlZmF1bHRFbnZpcm9ubWVudDsKICB9KEVudmlyb25tZW50KTsKCiAgX2V4cG9ydHMuRGVmYXVsdEVudmlyb25tZW50ID0gRGVmYXVsdEVudmlyb25tZW50OwoKICB2YXIgTG93TGV2ZWxWTSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIExvd0xldmVsVk0oc3RhY2ssIGhlYXAsIHByb2dyYW0sIGV4dGVybnMsIHBjLCByYSkgewogICAgICBpZiAocGMgPT09IHZvaWQgMCkgewogICAgICAgIHBjID0gLTE7CiAgICAgIH0KCiAgICAgIGlmIChyYSA9PT0gdm9pZCAwKSB7CiAgICAgICAgcmEgPSAtMTsKICAgICAgfQoKICAgICAgdGhpcy5zdGFjayA9IHN0YWNrOwogICAgICB0aGlzLmhlYXAgPSBoZWFwOwogICAgICB0aGlzLnByb2dyYW0gPSBwcm9ncmFtOwogICAgICB0aGlzLmV4dGVybnMgPSBleHRlcm5zOwogICAgICB0aGlzLnBjID0gcGM7CiAgICAgIHRoaXMucmEgPSByYTsKICAgICAgdGhpcy5jdXJyZW50T3BTaXplID0gMDsKICAgIH0gLy8gU3RhcnQgYSBuZXcgZnJhbWUgYW5kIHNhdmUgJHJhIGFuZCAkZnAgb24gdGhlIHN0YWNrCgoKICAgIHZhciBfcHJvdG8zOSA9IExvd0xldmVsVk0ucHJvdG90eXBlOwoKICAgIF9wcm90bzM5LnB1c2hGcmFtZSA9IGZ1bmN0aW9uIHB1c2hGcmFtZSgpIHsKICAgICAgdGhpcy5zdGFjay5wdXNoKHRoaXMucmEpOwogICAgICB0aGlzLnN0YWNrLnB1c2godGhpcy5zdGFjay5mcCk7CiAgICAgIHRoaXMuc3RhY2suZnAgPSB0aGlzLnN0YWNrLnNwIC0gMTsKICAgIH0gLy8gUmVzdG9yZSAkcmEsICRzcCBhbmQgJGZwCiAgICA7CgogICAgX3Byb3RvMzkucG9wRnJhbWUgPSBmdW5jdGlvbiBwb3BGcmFtZSgpIHsKICAgICAgdGhpcy5zdGFjay5zcCA9IHRoaXMuc3RhY2suZnAgLSAxOwogICAgICB0aGlzLnJhID0gdGhpcy5zdGFjay5nZXQoMCk7CiAgICAgIHRoaXMuc3RhY2suZnAgPSB0aGlzLnN0YWNrLmdldCgxKTsKICAgIH07CgogICAgX3Byb3RvMzkucHVzaFNtYWxsRnJhbWUgPSBmdW5jdGlvbiBwdXNoU21hbGxGcmFtZSgpIHsKICAgICAgdGhpcy5zdGFjay5wdXNoKHRoaXMucmEpOwogICAgfTsKCiAgICBfcHJvdG8zOS5wb3BTbWFsbEZyYW1lID0gZnVuY3Rpb24gcG9wU21hbGxGcmFtZSgpIHsKICAgICAgdGhpcy5yYSA9IHRoaXMuc3RhY2sucG9wU21pKCk7CiAgICB9IC8vIEp1bXAgdG8gYW4gYWRkcmVzcyBpbiBgcHJvZ3JhbWAKICAgIDsKCiAgICBfcHJvdG8zOS5nb3RvID0gZnVuY3Rpb24gZ290byhvZmZzZXQpIHsKICAgICAgdmFyIGFkZHIgPSB0aGlzLnBjICsgb2Zmc2V0IC0gdGhpcy5jdXJyZW50T3BTaXplOwogICAgICB0aGlzLnBjID0gYWRkcjsKICAgIH0gLy8gU2F2ZSAkcGMgaW50byAkcmEsIHRoZW4ganVtcCB0byBhIG5ldyBhZGRyZXNzIGluIGBwcm9ncmFtYCAoamFsIGluIE1JUFMpCiAgICA7CgogICAgX3Byb3RvMzkuY2FsbCA9IGZ1bmN0aW9uIGNhbGwoaGFuZGxlKSB7CiAgICAgIHRoaXMucmEgPSB0aGlzLnBjOwogICAgICB0aGlzLnBjID0gdGhpcy5oZWFwLmdldGFkZHIoaGFuZGxlKTsKICAgIH0gLy8gUHV0IGEgc3BlY2lmaWMgYHByb2dyYW1gIGFkZHJlc3MgaW4gJHJhCiAgICA7CgogICAgX3Byb3RvMzkucmV0dXJuVG8gPSBmdW5jdGlvbiByZXR1cm5UbyhvZmZzZXQpIHsKICAgICAgdmFyIGFkZHIgPSB0aGlzLnBjICsgb2Zmc2V0IC0gdGhpcy5jdXJyZW50T3BTaXplOwogICAgICB0aGlzLnJhID0gYWRkcjsKICAgIH0gLy8gUmV0dXJuIHRvIHRoZSBgcHJvZ3JhbWAgYWRkcmVzcyBzdG9yZWQgaW4gJHJhCiAgICA7CgogICAgX3Byb3RvMzkucmV0dXJuID0gZnVuY3Rpb24gX3JldHVybigpIHsKICAgICAgdGhpcy5wYyA9IHRoaXMucmE7CiAgICB9OwoKICAgIF9wcm90bzM5Lm5leHRTdGF0ZW1lbnQgPSBmdW5jdGlvbiBuZXh0U3RhdGVtZW50KCkgewogICAgICB2YXIgcGMgPSB0aGlzLnBjLAogICAgICAgICAgcHJvZ3JhbSA9IHRoaXMucHJvZ3JhbTsKCiAgICAgIGlmIChwYyA9PT0gLTEpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfSAvLyBXZSBoYXZlIHRvIHNhdmUgb2ZmIHRoZSBjdXJyZW50IG9wZXJhdGlvbnMgc2l6ZSBzbyB0aGF0CiAgICAgIC8vIHdoZW4gd2UgZG8gYSBqdW1wIHdlIGNhbiBjYWxjdWxhdGUgdGhlIGNvcnJlY3Qgb2Zmc2V0CiAgICAgIC8vIHRvIHdoZXJlIHdlIGFyZSBnb2luZy4gV2UgY2FuJ3Qgc2ltcGx5IGFzayBmb3IgdGhlIHNpemUKICAgICAgLy8gaW4gYSBqdW1wIGJlY2F1c2Ugd2UgaGF2ZSBoYXZlIGFscmVhZHkgaW5jcmVtZW50ZWQgdGhlCiAgICAgIC8vIHByb2dyYW0gY291bnRlciB0byB0aGUgbmV4dCBpbnN0cnVjdGlvbiBwcmlvciB0byBleGVjdXRpbmcuCgoKICAgICAgdmFyIF90aGlzJHByb2dyYW0kb3Bjb2RlID0gdGhpcy5wcm9ncmFtLm9wY29kZShwYyksCiAgICAgICAgICBzaXplID0gX3RoaXMkcHJvZ3JhbSRvcGNvZGUuc2l6ZTsKCiAgICAgIHZhciBvcGVyYXRpb25TaXplID0gdGhpcy5jdXJyZW50T3BTaXplID0gc2l6ZTsKICAgICAgdGhpcy5wYyArPSBvcGVyYXRpb25TaXplOwogICAgICByZXR1cm4gcHJvZ3JhbS5vcGNvZGUocGMpOwogICAgfTsKCiAgICBfcHJvdG8zOS5ldmFsdWF0ZU91dGVyID0gZnVuY3Rpb24gZXZhbHVhdGVPdXRlcihvcGNvZGUsIHZtKSB7CiAgICAgIHsKICAgICAgICB0aGlzLmV2YWx1YXRlSW5uZXIob3Bjb2RlLCB2bSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMzkuZXZhbHVhdGVJbm5lciA9IGZ1bmN0aW9uIGV2YWx1YXRlSW5uZXIob3Bjb2RlLCB2bSkgewogICAgICBpZiAob3Bjb2RlLmlzTWFjaGluZSkgewogICAgICAgIHRoaXMuZXZhbHVhdGVNYWNoaW5lKG9wY29kZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5ldmFsdWF0ZVN5c2NhbGwob3Bjb2RlLCB2bSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMzkuZXZhbHVhdGVNYWNoaW5lID0gZnVuY3Rpb24gZXZhbHVhdGVNYWNoaW5lKG9wY29kZSkgewogICAgICBzd2l0Y2ggKG9wY29kZS50eXBlKSB7CiAgICAgICAgY2FzZSA1NwogICAgICAgIC8qIFB1c2hGcmFtZSAqLwogICAgICAgIDoKICAgICAgICAgIHJldHVybiB0aGlzLnB1c2hGcmFtZSgpOwoKICAgICAgICBjYXNlIDU4CiAgICAgICAgLyogUG9wRnJhbWUgKi8KICAgICAgICA6CiAgICAgICAgICByZXR1cm4gdGhpcy5wb3BGcmFtZSgpOwoKICAgICAgICBjYXNlIDU5CiAgICAgICAgLyogUHVzaFNtYWxsRnJhbWUgKi8KICAgICAgICA6CiAgICAgICAgICByZXR1cm4gdGhpcy5wdXNoU21hbGxGcmFtZSgpOwoKICAgICAgICBjYXNlIDYwCiAgICAgICAgLyogUG9wU21hbGxGcmFtZSAqLwogICAgICAgIDoKICAgICAgICAgIHJldHVybiB0aGlzLnBvcFNtYWxsRnJhbWUoKTsKCiAgICAgICAgY2FzZSA1MAogICAgICAgIC8qIEludm9rZVN0YXRpYyAqLwogICAgICAgIDoKICAgICAgICAgIHJldHVybiB0aGlzLmNhbGwob3Bjb2RlLm9wMSk7CgogICAgICAgIGNhc2UgNDkKICAgICAgICAvKiBJbnZva2VWaXJ0dWFsICovCiAgICAgICAgOgogICAgICAgICAgcmV0dXJuIHRoaXMuY2FsbCh0aGlzLnN0YWNrLnBvcFNtaSgpKTsKCiAgICAgICAgY2FzZSA1MgogICAgICAgIC8qIEp1bXAgKi8KICAgICAgICA6CiAgICAgICAgICByZXR1cm4gdGhpcy5nb3RvKG9wY29kZS5vcDEpOwoKICAgICAgICBjYXNlIDI0CiAgICAgICAgLyogUmV0dXJuICovCiAgICAgICAgOgogICAgICAgICAgcmV0dXJuIHRoaXMucmV0dXJuKCk7CgogICAgICAgIGNhc2UgMjUKICAgICAgICAvKiBSZXR1cm5UbyAqLwogICAgICAgIDoKICAgICAgICAgIHJldHVybiB0aGlzLnJldHVyblRvKG9wY29kZS5vcDEpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzM5LmV2YWx1YXRlU3lzY2FsbCA9IGZ1bmN0aW9uIGV2YWx1YXRlU3lzY2FsbChvcGNvZGUsIHZtKSB7CiAgICAgIEFQUEVORF9PUENPREVTLmV2YWx1YXRlKHZtLCBvcGNvZGUsIG9wY29kZS50eXBlKTsKICAgIH07CgogICAgcmV0dXJuIExvd0xldmVsVk07CiAgfSgpOwoKICB2YXIgRmlyc3QgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBGaXJzdChub2RlKSB7CiAgICAgIHRoaXMubm9kZSA9IG5vZGU7CiAgICB9CgogICAgdmFyIF9wcm90bzQwID0gRmlyc3QucHJvdG90eXBlOwoKICAgIF9wcm90bzQwLmZpcnN0Tm9kZSA9IGZ1bmN0aW9uIGZpcnN0Tm9kZSgpIHsKICAgICAgcmV0dXJuIHRoaXMubm9kZTsKICAgIH07CgogICAgcmV0dXJuIEZpcnN0OwogIH0oKTsKCiAgdmFyIExhc3QgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBMYXN0KG5vZGUpIHsKICAgICAgdGhpcy5ub2RlID0gbm9kZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDEgPSBMYXN0LnByb3RvdHlwZTsKCiAgICBfcHJvdG80MS5sYXN0Tm9kZSA9IGZ1bmN0aW9uIGxhc3ROb2RlKCkgewogICAgICByZXR1cm4gdGhpcy5ub2RlOwogICAgfTsKCiAgICByZXR1cm4gTGFzdDsKICB9KCk7CgogIHZhciBOZXdFbGVtZW50QnVpbGRlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIE5ld0VsZW1lbnRCdWlsZGVyKGVudiwgcGFyZW50Tm9kZSwgbmV4dFNpYmxpbmcpIHsKICAgICAgdGhpcy5jb25zdHJ1Y3RpbmcgPSBudWxsOwogICAgICB0aGlzLm9wZXJhdGlvbnMgPSBudWxsOwogICAgICB0aGlzLmN1cnNvclN0YWNrID0gbmV3IF91dGlsLlN0YWNrKCk7CiAgICAgIHRoaXMubW9kaWZpZXJTdGFjayA9IG5ldyBfdXRpbC5TdGFjaygpOwogICAgICB0aGlzLmJsb2NrU3RhY2sgPSBuZXcgX3V0aWwuU3RhY2soKTsKICAgICAgdGhpcy5wdXNoRWxlbWVudChwYXJlbnROb2RlLCBuZXh0U2libGluZyk7CiAgICAgIHRoaXMuZW52ID0gZW52OwogICAgICB0aGlzLmRvbSA9IGVudi5nZXRBcHBlbmRPcGVyYXRpb25zKCk7CiAgICAgIHRoaXMudXBkYXRlT3BlcmF0aW9ucyA9IGVudi5nZXRET00oKTsKICAgIH0KCiAgICBOZXdFbGVtZW50QnVpbGRlci5mb3JJbml0aWFsUmVuZGVyID0gZnVuY3Rpb24gZm9ySW5pdGlhbFJlbmRlcihlbnYsIGN1cnNvcikgewogICAgICB2YXIgYnVpbGRlciA9IG5ldyB0aGlzKGVudiwgY3Vyc29yLmVsZW1lbnQsIGN1cnNvci5uZXh0U2libGluZyk7CiAgICAgIGJ1aWxkZXIucHVzaFNpbXBsZUJsb2NrKCk7CiAgICAgIHJldHVybiBidWlsZGVyOwogICAgfTsKCiAgICBOZXdFbGVtZW50QnVpbGRlci5yZXN1bWUgPSBmdW5jdGlvbiByZXN1bWUoZW52LCB0cmFja2VyLCBuZXh0U2libGluZykgewogICAgICB2YXIgcGFyZW50Tm9kZSA9IHRyYWNrZXIucGFyZW50RWxlbWVudCgpOwogICAgICB2YXIgc3RhY2sgPSBuZXcgdGhpcyhlbnYsIHBhcmVudE5vZGUsIG5leHRTaWJsaW5nKTsKICAgICAgc3RhY2sucHVzaFNpbXBsZUJsb2NrKCk7CiAgICAgIHN0YWNrLnB1c2hCbG9ja1RyYWNrZXIodHJhY2tlcik7CiAgICAgIHJldHVybiBzdGFjazsKICAgIH07CgogICAgdmFyIF9wcm90bzQyID0gTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzQyLmV4cGVjdENvbnN0cnVjdGluZyA9IGZ1bmN0aW9uIGV4cGVjdENvbnN0cnVjdGluZyhtZXRob2QpIHsKICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0aW5nOwogICAgfTsKCiAgICBfcHJvdG80Mi5ibG9jayA9IGZ1bmN0aW9uIGJsb2NrKCkgewogICAgICByZXR1cm4gdGhpcy5ibG9ja1N0YWNrLmN1cnJlbnQ7CiAgICB9OwoKICAgIF9wcm90bzQyLnBvcEVsZW1lbnQgPSBmdW5jdGlvbiBwb3BFbGVtZW50KCkgewogICAgICB0aGlzLmN1cnNvclN0YWNrLnBvcCgpOwogICAgICB0aGlzLmN1cnNvclN0YWNrLmN1cnJlbnQ7CiAgICB9OwoKICAgIF9wcm90bzQyLnB1c2hTaW1wbGVCbG9jayA9IGZ1bmN0aW9uIHB1c2hTaW1wbGVCbG9jaygpIHsKICAgICAgcmV0dXJuIHRoaXMucHVzaEJsb2NrVHJhY2tlcihuZXcgU2ltcGxlQmxvY2tUcmFja2VyKHRoaXMuZWxlbWVudCkpOwogICAgfTsKCiAgICBfcHJvdG80Mi5wdXNoVXBkYXRhYmxlQmxvY2sgPSBmdW5jdGlvbiBwdXNoVXBkYXRhYmxlQmxvY2soKSB7CiAgICAgIHJldHVybiB0aGlzLnB1c2hCbG9ja1RyYWNrZXIobmV3IFVwZGF0YWJsZUJsb2NrVHJhY2tlcih0aGlzLmVsZW1lbnQpKTsKICAgIH07CgogICAgX3Byb3RvNDIucHVzaEJsb2NrTGlzdCA9IGZ1bmN0aW9uIHB1c2hCbG9ja0xpc3QobGlzdCkgewogICAgICByZXR1cm4gdGhpcy5wdXNoQmxvY2tUcmFja2VyKG5ldyBCbG9ja0xpc3RUcmFja2VyKHRoaXMuZWxlbWVudCwgbGlzdCkpOwogICAgfTsKCiAgICBfcHJvdG80Mi5wdXNoQmxvY2tUcmFja2VyID0gZnVuY3Rpb24gcHVzaEJsb2NrVHJhY2tlcih0cmFja2VyLCBpc1JlbW90ZSkgewogICAgICBpZiAoaXNSZW1vdGUgPT09IHZvaWQgMCkgewogICAgICAgIGlzUmVtb3RlID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIHZhciBjdXJyZW50ID0gdGhpcy5ibG9ja1N0YWNrLmN1cnJlbnQ7CgogICAgICBpZiAoY3VycmVudCAhPT0gbnVsbCkgewogICAgICAgIGN1cnJlbnQubmV3RGVzdHJveWFibGUodHJhY2tlcik7CgogICAgICAgIGlmICghaXNSZW1vdGUpIHsKICAgICAgICAgIGN1cnJlbnQuZGlkQXBwZW5kQm91bmRzKHRyYWNrZXIpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdGhpcy5fX29wZW5CbG9jaygpOwoKICAgICAgdGhpcy5ibG9ja1N0YWNrLnB1c2godHJhY2tlcik7CiAgICAgIHJldHVybiB0cmFja2VyOwogICAgfTsKCiAgICBfcHJvdG80Mi5wb3BCbG9jayA9IGZ1bmN0aW9uIHBvcEJsb2NrKCkgewogICAgICB0aGlzLmJsb2NrKCkuZmluYWxpemUodGhpcyk7CgogICAgICB0aGlzLl9fY2xvc2VCbG9jaygpOwoKICAgICAgcmV0dXJuIHRoaXMuYmxvY2tTdGFjay5wb3AoKTsKICAgIH07CgogICAgX3Byb3RvNDIuX19vcGVuQmxvY2sgPSBmdW5jdGlvbiBfX29wZW5CbG9jaygpIHt9OwoKICAgIF9wcm90bzQyLl9fY2xvc2VCbG9jayA9IGZ1bmN0aW9uIF9fY2xvc2VCbG9jaygpIHt9IC8vIHRvZG8gcmV0dXJuIHNlZW1zIHVudXNlZAogICAgOwoKICAgIF9wcm90bzQyLm9wZW5FbGVtZW50ID0gZnVuY3Rpb24gb3BlbkVsZW1lbnQodGFnKSB7CiAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5fX29wZW5FbGVtZW50KHRhZyk7CgogICAgICB0aGlzLmNvbnN0cnVjdGluZyA9IGVsZW1lbnQ7CiAgICAgIHJldHVybiBlbGVtZW50OwogICAgfTsKCiAgICBfcHJvdG80Mi5fX29wZW5FbGVtZW50ID0gZnVuY3Rpb24gX19vcGVuRWxlbWVudCh0YWcpIHsKICAgICAgcmV0dXJuIHRoaXMuZG9tLmNyZWF0ZUVsZW1lbnQodGFnLCB0aGlzLmVsZW1lbnQpOwogICAgfTsKCiAgICBfcHJvdG80Mi5mbHVzaEVsZW1lbnQgPSBmdW5jdGlvbiBmbHVzaEVsZW1lbnQobW9kaWZpZXJzKSB7CiAgICAgIHZhciBwYXJlbnQgPSB0aGlzLmVsZW1lbnQ7CiAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5jb25zdHJ1Y3Rpbmc7CgogICAgICB0aGlzLl9fZmx1c2hFbGVtZW50KHBhcmVudCwgZWxlbWVudCk7CgogICAgICB0aGlzLmNvbnN0cnVjdGluZyA9IG51bGw7CiAgICAgIHRoaXMub3BlcmF0aW9ucyA9IG51bGw7CiAgICAgIHRoaXMucHVzaE1vZGlmaWVycyhtb2RpZmllcnMpOwogICAgICB0aGlzLnB1c2hFbGVtZW50KGVsZW1lbnQsIG51bGwpOwogICAgICB0aGlzLmRpZE9wZW5FbGVtZW50KGVsZW1lbnQpOwogICAgfTsKCiAgICBfcHJvdG80Mi5fX2ZsdXNoRWxlbWVudCA9IGZ1bmN0aW9uIF9fZmx1c2hFbGVtZW50KHBhcmVudCwgY29uc3RydWN0aW5nKSB7CiAgICAgIHRoaXMuZG9tLmluc2VydEJlZm9yZShwYXJlbnQsIGNvbnN0cnVjdGluZywgdGhpcy5uZXh0U2libGluZyk7CiAgICB9OwoKICAgIF9wcm90bzQyLmNsb3NlRWxlbWVudCA9IGZ1bmN0aW9uIGNsb3NlRWxlbWVudCgpIHsKICAgICAgdGhpcy53aWxsQ2xvc2VFbGVtZW50KCk7CiAgICAgIHRoaXMucG9wRWxlbWVudCgpOwogICAgICByZXR1cm4gdGhpcy5wb3BNb2RpZmllcnMoKTsKICAgIH07CgogICAgX3Byb3RvNDIucHVzaFJlbW90ZUVsZW1lbnQgPSBmdW5jdGlvbiBwdXNoUmVtb3RlRWxlbWVudChlbGVtZW50LCBndWlkLCBuZXh0U2libGluZykgewogICAgICBpZiAobmV4dFNpYmxpbmcgPT09IHZvaWQgMCkgewogICAgICAgIG5leHRTaWJsaW5nID0gbnVsbDsKICAgICAgfQoKICAgICAgdGhpcy5fX3B1c2hSZW1vdGVFbGVtZW50KGVsZW1lbnQsIGd1aWQsIG5leHRTaWJsaW5nKTsKICAgIH07CgogICAgX3Byb3RvNDIuX19wdXNoUmVtb3RlRWxlbWVudCA9IGZ1bmN0aW9uIF9fcHVzaFJlbW90ZUVsZW1lbnQoZWxlbWVudCwgX2d1aWQsIG5leHRTaWJsaW5nKSB7CiAgICAgIHRoaXMucHVzaEVsZW1lbnQoZWxlbWVudCwgbmV4dFNpYmxpbmcpOwogICAgICB2YXIgdHJhY2tlciA9IG5ldyBSZW1vdGVCbG9ja1RyYWNrZXIoZWxlbWVudCk7CiAgICAgIHRoaXMucHVzaEJsb2NrVHJhY2tlcih0cmFja2VyLCB0cnVlKTsKICAgIH07CgogICAgX3Byb3RvNDIucG9wUmVtb3RlRWxlbWVudCA9IGZ1bmN0aW9uIHBvcFJlbW90ZUVsZW1lbnQoKSB7CiAgICAgIHRoaXMucG9wQmxvY2soKTsKICAgICAgdGhpcy5wb3BFbGVtZW50KCk7CiAgICB9OwoKICAgIF9wcm90bzQyLnB1c2hFbGVtZW50ID0gZnVuY3Rpb24gcHVzaEVsZW1lbnQoZWxlbWVudCwgbmV4dFNpYmxpbmcpIHsKICAgICAgdGhpcy5jdXJzb3JTdGFjay5wdXNoKG5ldyBDdXJzb3IoZWxlbWVudCwgbmV4dFNpYmxpbmcpKTsKICAgIH07CgogICAgX3Byb3RvNDIucHVzaE1vZGlmaWVycyA9IGZ1bmN0aW9uIHB1c2hNb2RpZmllcnMobW9kaWZpZXJzKSB7CiAgICAgIHRoaXMubW9kaWZpZXJTdGFjay5wdXNoKG1vZGlmaWVycyk7CiAgICB9OwoKICAgIF9wcm90bzQyLnBvcE1vZGlmaWVycyA9IGZ1bmN0aW9uIHBvcE1vZGlmaWVycygpIHsKICAgICAgcmV0dXJuIHRoaXMubW9kaWZpZXJTdGFjay5wb3AoKTsKICAgIH07CgogICAgX3Byb3RvNDIuZGlkQWRkRGVzdHJveWFibGUgPSBmdW5jdGlvbiBkaWRBZGREZXN0cm95YWJsZShkKSB7CiAgICAgIHRoaXMuYmxvY2soKS5uZXdEZXN0cm95YWJsZShkKTsKICAgIH07CgogICAgX3Byb3RvNDIuZGlkQXBwZW5kQm91bmRzID0gZnVuY3Rpb24gZGlkQXBwZW5kQm91bmRzKGJvdW5kcykgewogICAgICB0aGlzLmJsb2NrKCkuZGlkQXBwZW5kQm91bmRzKGJvdW5kcyk7CiAgICAgIHJldHVybiBib3VuZHM7CiAgICB9OwoKICAgIF9wcm90bzQyLmRpZEFwcGVuZE5vZGUgPSBmdW5jdGlvbiBkaWRBcHBlbmROb2RlKG5vZGUpIHsKICAgICAgdGhpcy5ibG9jaygpLmRpZEFwcGVuZE5vZGUobm9kZSk7CiAgICAgIHJldHVybiBub2RlOwogICAgfTsKCiAgICBfcHJvdG80Mi5kaWRPcGVuRWxlbWVudCA9IGZ1bmN0aW9uIGRpZE9wZW5FbGVtZW50KGVsZW1lbnQpIHsKICAgICAgdGhpcy5ibG9jaygpLm9wZW5FbGVtZW50KGVsZW1lbnQpOwogICAgICByZXR1cm4gZWxlbWVudDsKICAgIH07CgogICAgX3Byb3RvNDIud2lsbENsb3NlRWxlbWVudCA9IGZ1bmN0aW9uIHdpbGxDbG9zZUVsZW1lbnQoKSB7CiAgICAgIHRoaXMuYmxvY2soKS5jbG9zZUVsZW1lbnQoKTsKICAgIH07CgogICAgX3Byb3RvNDIuYXBwZW5kVGV4dCA9IGZ1bmN0aW9uIGFwcGVuZFRleHQoc3RyaW5nKSB7CiAgICAgIHJldHVybiB0aGlzLmRpZEFwcGVuZE5vZGUodGhpcy5fX2FwcGVuZFRleHQoc3RyaW5nKSk7CiAgICB9OwoKICAgIF9wcm90bzQyLl9fYXBwZW5kVGV4dCA9IGZ1bmN0aW9uIF9fYXBwZW5kVGV4dCh0ZXh0KSB7CiAgICAgIHZhciBkb20gPSB0aGlzLmRvbSwKICAgICAgICAgIGVsZW1lbnQgPSB0aGlzLmVsZW1lbnQsCiAgICAgICAgICBuZXh0U2libGluZyA9IHRoaXMubmV4dFNpYmxpbmc7CiAgICAgIHZhciBub2RlID0gZG9tLmNyZWF0ZVRleHROb2RlKHRleHQpOwogICAgICBkb20uaW5zZXJ0QmVmb3JlKGVsZW1lbnQsIG5vZGUsIG5leHRTaWJsaW5nKTsKICAgICAgcmV0dXJuIG5vZGU7CiAgICB9OwoKICAgIF9wcm90bzQyLl9fYXBwZW5kTm9kZSA9IGZ1bmN0aW9uIF9fYXBwZW5kTm9kZShub2RlKSB7CiAgICAgIHRoaXMuZG9tLmluc2VydEJlZm9yZSh0aGlzLmVsZW1lbnQsIG5vZGUsIHRoaXMubmV4dFNpYmxpbmcpOwogICAgICByZXR1cm4gbm9kZTsKICAgIH07CgogICAgX3Byb3RvNDIuX19hcHBlbmRGcmFnbWVudCA9IGZ1bmN0aW9uIF9fYXBwZW5kRnJhZ21lbnQoZnJhZ21lbnQpIHsKICAgICAgdmFyIGZpcnN0ID0gZnJhZ21lbnQuZmlyc3RDaGlsZDsKCiAgICAgIGlmIChmaXJzdCkgewogICAgICAgIHZhciByZXQgPSBuZXcgQ29uY3JldGVCb3VuZHModGhpcy5lbGVtZW50LCBmaXJzdCwgZnJhZ21lbnQubGFzdENoaWxkKTsKICAgICAgICB0aGlzLmRvbS5pbnNlcnRCZWZvcmUodGhpcy5lbGVtZW50LCBmcmFnbWVudCwgdGhpcy5uZXh0U2libGluZyk7CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbmV3IFNpbmdsZU5vZGVCb3VuZHModGhpcy5lbGVtZW50LCB0aGlzLl9fYXBwZW5kQ29tbWVudCgnJykpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQyLl9fYXBwZW5kSFRNTCA9IGZ1bmN0aW9uIF9fYXBwZW5kSFRNTChodG1sKSB7CiAgICAgIHJldHVybiB0aGlzLmRvbS5pbnNlcnRIVE1MQmVmb3JlKHRoaXMuZWxlbWVudCwgdGhpcy5uZXh0U2libGluZywgaHRtbCk7CiAgICB9OwoKICAgIF9wcm90bzQyLmFwcGVuZER5bmFtaWNIVE1MID0gZnVuY3Rpb24gYXBwZW5kRHluYW1pY0hUTUwodmFsdWUkJDEpIHsKICAgICAgdmFyIGJvdW5kcyA9IHRoaXMudHJ1c3RlZENvbnRlbnQodmFsdWUkJDEpOwogICAgICB0aGlzLmRpZEFwcGVuZEJvdW5kcyhib3VuZHMpOwogICAgfTsKCiAgICBfcHJvdG80Mi5hcHBlbmREeW5hbWljVGV4dCA9IGZ1bmN0aW9uIGFwcGVuZER5bmFtaWNUZXh0KHZhbHVlJCQxKSB7CiAgICAgIHZhciBub2RlID0gdGhpcy51bnRydXN0ZWRDb250ZW50KHZhbHVlJCQxKTsKICAgICAgdGhpcy5kaWRBcHBlbmROb2RlKG5vZGUpOwogICAgICByZXR1cm4gbm9kZTsKICAgIH07CgogICAgX3Byb3RvNDIuYXBwZW5kRHluYW1pY0ZyYWdtZW50ID0gZnVuY3Rpb24gYXBwZW5kRHluYW1pY0ZyYWdtZW50KHZhbHVlJCQxKSB7CiAgICAgIHZhciBib3VuZHMgPSB0aGlzLl9fYXBwZW5kRnJhZ21lbnQodmFsdWUkJDEpOwoKICAgICAgdGhpcy5kaWRBcHBlbmRCb3VuZHMoYm91bmRzKTsKICAgIH07CgogICAgX3Byb3RvNDIuYXBwZW5kRHluYW1pY05vZGUgPSBmdW5jdGlvbiBhcHBlbmREeW5hbWljTm9kZSh2YWx1ZSQkMSkgewogICAgICB2YXIgbm9kZSA9IHRoaXMuX19hcHBlbmROb2RlKHZhbHVlJCQxKTsKCiAgICAgIHZhciBib3VuZHMgPSBuZXcgU2luZ2xlTm9kZUJvdW5kcyh0aGlzLmVsZW1lbnQsIG5vZGUpOwogICAgICB0aGlzLmRpZEFwcGVuZEJvdW5kcyhib3VuZHMpOwogICAgfTsKCiAgICBfcHJvdG80Mi50cnVzdGVkQ29udGVudCA9IGZ1bmN0aW9uIHRydXN0ZWRDb250ZW50KHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiB0aGlzLl9fYXBwZW5kSFRNTCh2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzQyLnVudHJ1c3RlZENvbnRlbnQgPSBmdW5jdGlvbiB1bnRydXN0ZWRDb250ZW50KHZhbHVlJCQxKSB7CiAgICAgIHJldHVybiB0aGlzLl9fYXBwZW5kVGV4dCh2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzQyLmFwcGVuZENvbW1lbnQgPSBmdW5jdGlvbiBhcHBlbmRDb21tZW50KHN0cmluZykgewogICAgICByZXR1cm4gdGhpcy5kaWRBcHBlbmROb2RlKHRoaXMuX19hcHBlbmRDb21tZW50KHN0cmluZykpOwogICAgfTsKCiAgICBfcHJvdG80Mi5fX2FwcGVuZENvbW1lbnQgPSBmdW5jdGlvbiBfX2FwcGVuZENvbW1lbnQoc3RyaW5nKSB7CiAgICAgIHZhciBkb20gPSB0aGlzLmRvbSwKICAgICAgICAgIGVsZW1lbnQgPSB0aGlzLmVsZW1lbnQsCiAgICAgICAgICBuZXh0U2libGluZyA9IHRoaXMubmV4dFNpYmxpbmc7CiAgICAgIHZhciBub2RlID0gZG9tLmNyZWF0ZUNvbW1lbnQoc3RyaW5nKTsKICAgICAgZG9tLmluc2VydEJlZm9yZShlbGVtZW50LCBub2RlLCBuZXh0U2libGluZyk7CiAgICAgIHJldHVybiBub2RlOwogICAgfTsKCiAgICBfcHJvdG80Mi5fX3NldEF0dHJpYnV0ZSA9IGZ1bmN0aW9uIF9fc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlJCQxLCBuYW1lc3BhY2UpIHsKICAgICAgdGhpcy5kb20uc2V0QXR0cmlidXRlKHRoaXMuY29uc3RydWN0aW5nLCBuYW1lLCB2YWx1ZSQkMSwgbmFtZXNwYWNlKTsKICAgIH07CgogICAgX3Byb3RvNDIuX19zZXRQcm9wZXJ0eSA9IGZ1bmN0aW9uIF9fc2V0UHJvcGVydHkobmFtZSwgdmFsdWUkJDEpIHsKICAgICAgdGhpcy5jb25zdHJ1Y3RpbmdbbmFtZV0gPSB2YWx1ZSQkMTsKICAgIH07CgogICAgX3Byb3RvNDIuc2V0U3RhdGljQXR0cmlidXRlID0gZnVuY3Rpb24gc2V0U3RhdGljQXR0cmlidXRlKG5hbWUsIHZhbHVlJCQxLCBuYW1lc3BhY2UpIHsKICAgICAgdGhpcy5fX3NldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSQkMSwgbmFtZXNwYWNlKTsKICAgIH07CgogICAgX3Byb3RvNDIuc2V0RHluYW1pY0F0dHJpYnV0ZSA9IGZ1bmN0aW9uIHNldER5bmFtaWNBdHRyaWJ1dGUobmFtZSwgdmFsdWUkJDEsIHRydXN0aW5nLCBuYW1lc3BhY2UpIHsKICAgICAgdmFyIGVsZW1lbnQgPSB0aGlzLmNvbnN0cnVjdGluZzsKICAgICAgdmFyIGF0dHJpYnV0ZSA9IHRoaXMuZW52LmF0dHJpYnV0ZUZvcihlbGVtZW50LCBuYW1lLCB0cnVzdGluZywgbmFtZXNwYWNlKTsKICAgICAgYXR0cmlidXRlLnNldCh0aGlzLCB2YWx1ZSQkMSwgdGhpcy5lbnYpOwogICAgICByZXR1cm4gYXR0cmlidXRlOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKE5ld0VsZW1lbnRCdWlsZGVyLCBbewogICAgICBrZXk6ICJlbGVtZW50IiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuY3Vyc29yU3RhY2suY3VycmVudC5lbGVtZW50OwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogIm5leHRTaWJsaW5nIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuY3Vyc29yU3RhY2suY3VycmVudC5uZXh0U2libGluZzsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIE5ld0VsZW1lbnRCdWlsZGVyOwogIH0oKTsKCiAgX2V4cG9ydHMuTmV3RWxlbWVudEJ1aWxkZXIgPSBOZXdFbGVtZW50QnVpbGRlcjsKCiAgdmFyIFNpbXBsZUJsb2NrVHJhY2tlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFNpbXBsZUJsb2NrVHJhY2tlcihwYXJlbnQpIHsKICAgICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7CiAgICAgIHRoaXMuZmlyc3QgPSBudWxsOwogICAgICB0aGlzLmxhc3QgPSBudWxsOwogICAgICB0aGlzLmRlc3Ryb3lhYmxlcyA9IG51bGw7CiAgICAgIHRoaXMubmVzdGluZyA9IDA7CiAgICB9CgogICAgdmFyIF9wcm90bzQzID0gU2ltcGxlQmxvY2tUcmFja2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG80My5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdmFyIGRlc3Ryb3lhYmxlcyA9IHRoaXMuZGVzdHJveWFibGVzOwoKICAgICAgaWYgKGRlc3Ryb3lhYmxlcyAmJiBkZXN0cm95YWJsZXMubGVuZ3RoKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkZXN0cm95YWJsZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGRlc3Ryb3lhYmxlc1tpXS5kZXN0cm95KCk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQzLnBhcmVudEVsZW1lbnQgPSBmdW5jdGlvbiBwYXJlbnRFbGVtZW50KCkgewogICAgICByZXR1cm4gdGhpcy5wYXJlbnQ7CiAgICB9OwoKICAgIF9wcm90bzQzLmZpcnN0Tm9kZSA9IGZ1bmN0aW9uIGZpcnN0Tm9kZSgpIHsKICAgICAgdmFyIGZpcnN0ID0gdGhpcy5maXJzdDsKICAgICAgcmV0dXJuIGZpcnN0LmZpcnN0Tm9kZSgpOwogICAgfTsKCiAgICBfcHJvdG80My5sYXN0Tm9kZSA9IGZ1bmN0aW9uIGxhc3ROb2RlKCkgewogICAgICB2YXIgbGFzdCA9IHRoaXMubGFzdDsKICAgICAgcmV0dXJuIGxhc3QubGFzdE5vZGUoKTsKICAgIH07CgogICAgX3Byb3RvNDMub3BlbkVsZW1lbnQgPSBmdW5jdGlvbiBvcGVuRWxlbWVudChlbGVtZW50KSB7CiAgICAgIHRoaXMuZGlkQXBwZW5kTm9kZShlbGVtZW50KTsKICAgICAgdGhpcy5uZXN0aW5nKys7CiAgICB9OwoKICAgIF9wcm90bzQzLmNsb3NlRWxlbWVudCA9IGZ1bmN0aW9uIGNsb3NlRWxlbWVudCgpIHsKICAgICAgdGhpcy5uZXN0aW5nLS07CiAgICB9OwoKICAgIF9wcm90bzQzLmRpZEFwcGVuZE5vZGUgPSBmdW5jdGlvbiBkaWRBcHBlbmROb2RlKG5vZGUpIHsKICAgICAgaWYgKHRoaXMubmVzdGluZyAhPT0gMCkgcmV0dXJuOwoKICAgICAgaWYgKCF0aGlzLmZpcnN0KSB7CiAgICAgICAgdGhpcy5maXJzdCA9IG5ldyBGaXJzdChub2RlKTsKICAgICAgfQoKICAgICAgdGhpcy5sYXN0ID0gbmV3IExhc3Qobm9kZSk7CiAgICB9OwoKICAgIF9wcm90bzQzLmRpZEFwcGVuZEJvdW5kcyA9IGZ1bmN0aW9uIGRpZEFwcGVuZEJvdW5kcyhib3VuZHMpIHsKICAgICAgaWYgKHRoaXMubmVzdGluZyAhPT0gMCkgcmV0dXJuOwoKICAgICAgaWYgKCF0aGlzLmZpcnN0KSB7CiAgICAgICAgdGhpcy5maXJzdCA9IGJvdW5kczsKICAgICAgfQoKICAgICAgdGhpcy5sYXN0ID0gYm91bmRzOwogICAgfTsKCiAgICBfcHJvdG80My5uZXdEZXN0cm95YWJsZSA9IGZ1bmN0aW9uIG5ld0Rlc3Ryb3lhYmxlKGQpIHsKICAgICAgdGhpcy5kZXN0cm95YWJsZXMgPSB0aGlzLmRlc3Ryb3lhYmxlcyB8fCBbXTsKICAgICAgdGhpcy5kZXN0cm95YWJsZXMucHVzaChkKTsKICAgIH07CgogICAgX3Byb3RvNDMuZmluYWxpemUgPSBmdW5jdGlvbiBmaW5hbGl6ZShzdGFjaykgewogICAgICBpZiAodGhpcy5maXJzdCA9PT0gbnVsbCkgewogICAgICAgIHN0YWNrLmFwcGVuZENvbW1lbnQoJycpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBTaW1wbGVCbG9ja1RyYWNrZXI7CiAgfSgpOwoKICB2YXIgUmVtb3RlQmxvY2tUcmFja2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9TaW1wbGVCbG9ja1RyYWNrZXIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShSZW1vdGVCbG9ja1RyYWNrZXIsIF9TaW1wbGVCbG9ja1RyYWNrZXIpOwoKICAgIGZ1bmN0aW9uIFJlbW90ZUJsb2NrVHJhY2tlcigpIHsKICAgICAgcmV0dXJuIF9TaW1wbGVCbG9ja1RyYWNrZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG80NCA9IFJlbW90ZUJsb2NrVHJhY2tlci5wcm90b3R5cGU7CgogICAgX3Byb3RvNDQuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIF9TaW1wbGVCbG9ja1RyYWNrZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTsKCiAgICAgIGNsZWFyKHRoaXMpOwogICAgfTsKCiAgICByZXR1cm4gUmVtb3RlQmxvY2tUcmFja2VyOwogIH0oU2ltcGxlQmxvY2tUcmFja2VyKTsKCiAgdmFyIFVwZGF0YWJsZUJsb2NrVHJhY2tlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfU2ltcGxlQmxvY2tUcmFja2VyMikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFVwZGF0YWJsZUJsb2NrVHJhY2tlciwgX1NpbXBsZUJsb2NrVHJhY2tlcjIpOwoKICAgIGZ1bmN0aW9uIFVwZGF0YWJsZUJsb2NrVHJhY2tlcigpIHsKICAgICAgcmV0dXJuIF9TaW1wbGVCbG9ja1RyYWNrZXIyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDUgPSBVcGRhdGFibGVCbG9ja1RyYWNrZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzQ1LnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoZW52KSB7CiAgICAgIHZhciBkZXN0cm95YWJsZXMgPSB0aGlzLmRlc3Ryb3lhYmxlczsKCiAgICAgIGlmIChkZXN0cm95YWJsZXMgJiYgZGVzdHJveWFibGVzLmxlbmd0aCkgewogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVzdHJveWFibGVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBlbnYuZGlkRGVzdHJveShkZXN0cm95YWJsZXNbaV0pOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdmFyIG5leHRTaWJsaW5nID0gY2xlYXIodGhpcyk7CiAgICAgIHRoaXMuZmlyc3QgPSBudWxsOwogICAgICB0aGlzLmxhc3QgPSBudWxsOwogICAgICB0aGlzLmRlc3Ryb3lhYmxlcyA9IG51bGw7CiAgICAgIHRoaXMubmVzdGluZyA9IDA7CiAgICAgIHJldHVybiBuZXh0U2libGluZzsKICAgIH07CgogICAgcmV0dXJuIFVwZGF0YWJsZUJsb2NrVHJhY2tlcjsKICB9KFNpbXBsZUJsb2NrVHJhY2tlcik7CgogIHZhciBCbG9ja0xpc3RUcmFja2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQmxvY2tMaXN0VHJhY2tlcihwYXJlbnQsIGJvdW5kTGlzdCkgewogICAgICB0aGlzLnBhcmVudCA9IHBhcmVudDsKICAgICAgdGhpcy5ib3VuZExpc3QgPSBib3VuZExpc3Q7CiAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50OwogICAgICB0aGlzLmJvdW5kTGlzdCA9IGJvdW5kTGlzdDsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDYgPSBCbG9ja0xpc3RUcmFja2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG80Ni5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdGhpcy5ib3VuZExpc3QuZm9yRWFjaE5vZGUoZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICByZXR1cm4gbm9kZS5kZXN0cm95KCk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG80Ni5wYXJlbnRFbGVtZW50ID0gZnVuY3Rpb24gcGFyZW50RWxlbWVudCgpIHsKICAgICAgcmV0dXJuIHRoaXMucGFyZW50OwogICAgfTsKCiAgICBfcHJvdG80Ni5maXJzdE5vZGUgPSBmdW5jdGlvbiBmaXJzdE5vZGUoKSB7CiAgICAgIHZhciBoZWFkID0gdGhpcy5ib3VuZExpc3QuaGVhZCgpOwogICAgICByZXR1cm4gaGVhZC5maXJzdE5vZGUoKTsKICAgIH07CgogICAgX3Byb3RvNDYubGFzdE5vZGUgPSBmdW5jdGlvbiBsYXN0Tm9kZSgpIHsKICAgICAgdmFyIHRhaWwgPSB0aGlzLmJvdW5kTGlzdC50YWlsKCk7CiAgICAgIHJldHVybiB0YWlsLmxhc3ROb2RlKCk7CiAgICB9OwoKICAgIF9wcm90bzQ2Lm9wZW5FbGVtZW50ID0gZnVuY3Rpb24gb3BlbkVsZW1lbnQoX2VsZW1lbnQpIHt9OwoKICAgIF9wcm90bzQ2LmNsb3NlRWxlbWVudCA9IGZ1bmN0aW9uIGNsb3NlRWxlbWVudCgpIHt9OwoKICAgIF9wcm90bzQ2LmRpZEFwcGVuZE5vZGUgPSBmdW5jdGlvbiBkaWRBcHBlbmROb2RlKF9ub2RlKSB7fTsKCiAgICBfcHJvdG80Ni5kaWRBcHBlbmRCb3VuZHMgPSBmdW5jdGlvbiBkaWRBcHBlbmRCb3VuZHMoX2JvdW5kcykge307CgogICAgX3Byb3RvNDYubmV3RGVzdHJveWFibGUgPSBmdW5jdGlvbiBuZXdEZXN0cm95YWJsZShfZCkge307CgogICAgX3Byb3RvNDYuZmluYWxpemUgPSBmdW5jdGlvbiBmaW5hbGl6ZShfc3RhY2spIHt9OwoKICAgIHJldHVybiBCbG9ja0xpc3RUcmFja2VyOwogIH0oKTsKCiAgZnVuY3Rpb24gY2xpZW50QnVpbGRlcihlbnYsIGN1cnNvcikgewogICAgcmV0dXJuIE5ld0VsZW1lbnRCdWlsZGVyLmZvckluaXRpYWxSZW5kZXIoZW52LCBjdXJzb3IpOwogIH0KCiAgdmFyIE1BWF9TTUkgPSAweGZmZmZmZmY7CgogIHZhciBJbm5lclN0YWNrID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSW5uZXJTdGFjayhpbm5lciwganMpIHsKICAgICAgaWYgKGlubmVyID09PSB2b2lkIDApIHsKICAgICAgICBpbm5lciA9IG5ldyBfbG93TGV2ZWwuU3RhY2soKTsKICAgICAgfQoKICAgICAgaWYgKGpzID09PSB2b2lkIDApIHsKICAgICAgICBqcyA9IFtdOwogICAgICB9CgogICAgICB0aGlzLmlubmVyID0gaW5uZXI7CiAgICAgIHRoaXMuanMgPSBqczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNDcgPSBJbm5lclN0YWNrLnByb3RvdHlwZTsKCiAgICBfcHJvdG80Ny5zbGljZSA9IGZ1bmN0aW9uIHNsaWNlKHN0YXJ0LCBlbmQpIHsKICAgICAgdmFyIGlubmVyOwoKICAgICAgaWYgKHR5cGVvZiBzdGFydCA9PT0gJ251bWJlcicgJiYgdHlwZW9mIGVuZCA9PT0gJ251bWJlcicpIHsKICAgICAgICBpbm5lciA9IHRoaXMuaW5uZXIuc2xpY2Uoc3RhcnQsIGVuZCk7CiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHN0YXJ0ID09PSAnbnVtYmVyJyAmJiBlbmQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGlubmVyID0gdGhpcy5pbm5lci5zbGljZUZyb20oc3RhcnQpOwogICAgICB9IGVsc2UgewogICAgICAgIGlubmVyID0gdGhpcy5pbm5lci5jbG9uZSgpOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IElubmVyU3RhY2soaW5uZXIsIHRoaXMuanMuc2xpY2Uoc3RhcnQsIGVuZCkpOwogICAgfTsKCiAgICBfcHJvdG80Ny5zbGljZUlubmVyID0gZnVuY3Rpb24gc2xpY2VJbm5lcihzdGFydCwgZW5kKSB7CiAgICAgIHZhciBvdXQgPSBbXTsKCiAgICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7CiAgICAgICAgb3V0LnB1c2godGhpcy5nZXQoaSkpOwogICAgICB9CgogICAgICByZXR1cm4gb3V0OwogICAgfTsKCiAgICBfcHJvdG80Ny5jb3B5ID0gZnVuY3Rpb24gY29weShmcm9tLCB0bykgewogICAgICB0aGlzLmlubmVyLmNvcHkoZnJvbSwgdG8pOwogICAgfTsKCiAgICBfcHJvdG80Ny53cml0ZSA9IGZ1bmN0aW9uIHdyaXRlKHBvcywgdmFsdWUkJDEpIHsKICAgICAgaWYgKGlzSW1tZWRpYXRlKHZhbHVlJCQxKSkgewogICAgICAgIHRoaXMuaW5uZXIud3JpdGVSYXcocG9zLCBlbmNvZGVJbW1lZGlhdGUodmFsdWUkJDEpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgaWR4ID0gdGhpcy5qcy5sZW5ndGg7CiAgICAgICAgdGhpcy5qcy5wdXNoKHZhbHVlJCQxKTsKICAgICAgICB0aGlzLmlubmVyLndyaXRlUmF3KHBvcywgfmlkeCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNDcud3JpdGVSYXcgPSBmdW5jdGlvbiB3cml0ZVJhdyhwb3MsIHZhbHVlJCQxKSB7CiAgICAgIHRoaXMuaW5uZXIud3JpdGVSYXcocG9zLCB2YWx1ZSQkMSk7CiAgICB9OwoKICAgIF9wcm90bzQ3LmdldCA9IGZ1bmN0aW9uIGdldChwb3MpIHsKICAgICAgdmFyIHZhbHVlJCQxID0gdGhpcy5pbm5lci5nZXRSYXcocG9zKTsKCiAgICAgIGlmICh2YWx1ZSQkMSA8IDApIHsKICAgICAgICByZXR1cm4gdGhpcy5qc1t+dmFsdWUkJDFdOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBkZWNvZGVJbW1lZGlhdGUodmFsdWUkJDEpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQ3LnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoKSB7CiAgICAgIHRoaXMuaW5uZXIucmVzZXQoKTsKICAgICAgdGhpcy5qcy5sZW5ndGggPSAwOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKElubmVyU3RhY2ssIFt7CiAgICAgIGtleTogImxlbmd0aCIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmlubmVyLmxlbigpOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gSW5uZXJTdGFjazsKICB9KCk7CgogIHZhciBFdmFsdWF0aW9uU3RhY2sgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBFdmFsdWF0aW9uU3RhY2soc3RhY2ssIGZwLCBzcCkgewogICAgICB0aGlzLnN0YWNrID0gc3RhY2s7CiAgICAgIHRoaXMuZnAgPSBmcDsKICAgICAgdGhpcy5zcCA9IHNwOwogICAgfQoKICAgIEV2YWx1YXRpb25TdGFjay5lbXB0eSA9IGZ1bmN0aW9uIGVtcHR5KCkgewogICAgICByZXR1cm4gbmV3IHRoaXMobmV3IElubmVyU3RhY2soKSwgMCwgLTEpOwogICAgfTsKCiAgICBFdmFsdWF0aW9uU3RhY2sucmVzdG9yZSA9IGZ1bmN0aW9uIHJlc3RvcmUoc25hcHNob3QpIHsKICAgICAgdmFyIHN0YWNrID0gbmV3IElubmVyU3RhY2soKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc25hcHNob3QubGVuZ3RoOyBpKyspIHsKICAgICAgICBzdGFjay53cml0ZShpLCBzbmFwc2hvdFtpXSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXcgdGhpcyhzdGFjaywgMCwgc25hcHNob3QubGVuZ3RoIC0gMSk7CiAgICB9OwoKICAgIHZhciBfcHJvdG80OCA9IEV2YWx1YXRpb25TdGFjay5wcm90b3R5cGU7CgogICAgX3Byb3RvNDgucHVzaCA9IGZ1bmN0aW9uIHB1c2godmFsdWUkJDEpIHsKICAgICAgdGhpcy5zdGFjay53cml0ZSgrK3RoaXMuc3AsIHZhbHVlJCQxKTsKICAgIH07CgogICAgX3Byb3RvNDgucHVzaEVuY29kZWRJbW1lZGlhdGUgPSBmdW5jdGlvbiBwdXNoRW5jb2RlZEltbWVkaWF0ZSh2YWx1ZSQkMSkgewogICAgICB0aGlzLnN0YWNrLndyaXRlUmF3KCsrdGhpcy5zcCwgdmFsdWUkJDEpOwogICAgfTsKCiAgICBfcHJvdG80OC5wdXNoTnVsbCA9IGZ1bmN0aW9uIHB1c2hOdWxsKCkgewogICAgICB0aGlzLnN0YWNrLndyaXRlKCsrdGhpcy5zcCwgbnVsbCk7CiAgICB9OwoKICAgIF9wcm90bzQ4LmR1cCA9IGZ1bmN0aW9uIGR1cChwb3NpdGlvbikgewogICAgICBpZiAocG9zaXRpb24gPT09IHZvaWQgMCkgewogICAgICAgIHBvc2l0aW9uID0gdGhpcy5zcDsKICAgICAgfQoKICAgICAgdGhpcy5zdGFjay5jb3B5KHBvc2l0aW9uLCArK3RoaXMuc3ApOwogICAgfTsKCiAgICBfcHJvdG80OC5jb3B5ID0gZnVuY3Rpb24gY29weShmcm9tLCB0bykgewogICAgICB0aGlzLnN0YWNrLmNvcHkoZnJvbSwgdG8pOwogICAgfTsKCiAgICBfcHJvdG80OC5wb3AgPSBmdW5jdGlvbiBwb3AobikgewogICAgICBpZiAobiA9PT0gdm9pZCAwKSB7CiAgICAgICAgbiA9IDE7CiAgICAgIH0KCiAgICAgIHZhciB0b3AgPSB0aGlzLnN0YWNrLmdldCh0aGlzLnNwKTsKICAgICAgdGhpcy5zcCAtPSBuOwogICAgICByZXR1cm4gdG9wOwogICAgfTsKCiAgICBfcHJvdG80OC5wb3BTbWkgPSBmdW5jdGlvbiBwb3BTbWkoKSB7CiAgICAgIHJldHVybiB0aGlzLnN0YWNrLmdldCh0aGlzLnNwLS0pOwogICAgfTsKCiAgICBfcHJvdG80OC5wZWVrID0gZnVuY3Rpb24gcGVlayhvZmZzZXQpIHsKICAgICAgaWYgKG9mZnNldCA9PT0gdm9pZCAwKSB7CiAgICAgICAgb2Zmc2V0ID0gMDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suZ2V0KHRoaXMuc3AgLSBvZmZzZXQpOwogICAgfTsKCiAgICBfcHJvdG80OC5nZXQgPSBmdW5jdGlvbiBnZXQob2Zmc2V0LCBiYXNlKSB7CiAgICAgIGlmIChiYXNlID09PSB2b2lkIDApIHsKICAgICAgICBiYXNlID0gdGhpcy5mcDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suZ2V0KGJhc2UgKyBvZmZzZXQpOwogICAgfTsKCiAgICBfcHJvdG80OC5zZXQgPSBmdW5jdGlvbiBzZXQodmFsdWUkJDEsIG9mZnNldCwgYmFzZSkgewogICAgICBpZiAoYmFzZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgYmFzZSA9IHRoaXMuZnA7CiAgICAgIH0KCiAgICAgIHRoaXMuc3RhY2sud3JpdGUoYmFzZSArIG9mZnNldCwgdmFsdWUkJDEpOwogICAgfTsKCiAgICBfcHJvdG80OC5zbGljZSA9IGZ1bmN0aW9uIHNsaWNlKHN0YXJ0LCBlbmQpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suc2xpY2Uoc3RhcnQsIGVuZCk7CiAgICB9OwoKICAgIF9wcm90bzQ4LnNsaWNlQXJyYXkgPSBmdW5jdGlvbiBzbGljZUFycmF5KHN0YXJ0LCBlbmQpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suc2xpY2VJbm5lcihzdGFydCwgZW5kKTsKICAgIH07CgogICAgX3Byb3RvNDguY2FwdHVyZSA9IGZ1bmN0aW9uIGNhcHR1cmUoaXRlbXMpIHsKICAgICAgdmFyIGVuZCA9IHRoaXMuc3AgKyAxOwogICAgICB2YXIgc3RhcnQgPSBlbmQgLSBpdGVtczsKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suc2xpY2VJbm5lcihzdGFydCwgZW5kKTsKICAgIH07CgogICAgX3Byb3RvNDgucmVzZXQgPSBmdW5jdGlvbiByZXNldCgpIHsKICAgICAgdGhpcy5zdGFjay5yZXNldCgpOwogICAgfTsKCiAgICBfcHJvdG80OC50b0FycmF5ID0gZnVuY3Rpb24gdG9BcnJheSgpIHsKICAgICAgcmV0dXJuIHRoaXMuc3RhY2suc2xpY2VJbm5lcih0aGlzLmZwLCB0aGlzLnNwICsgMSk7CiAgICB9OwoKICAgIHJldHVybiBFdmFsdWF0aW9uU3RhY2s7CiAgfSgpOwoKICBmdW5jdGlvbiBpc0ltbWVkaWF0ZSh2YWx1ZSQkMSkgewogICAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWUkJDE7CiAgICBpZiAodmFsdWUkJDEgPT09IG51bGwgfHwgdmFsdWUkJDEgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRydWU7CgogICAgc3dpdGNoICh0eXBlKSB7CiAgICAgIGNhc2UgJ2Jvb2xlYW4nOgogICAgICBjYXNlICd1bmRlZmluZWQnOgogICAgICAgIHJldHVybiB0cnVlOwoKICAgICAgY2FzZSAnbnVtYmVyJzoKICAgICAgICAvLyBub3QgYW4gaW50ZWdlcgogICAgICAgIGlmICh2YWx1ZSQkMSAlIDEgIT09IDApIHJldHVybiBmYWxzZTsKICAgICAgICB2YXIgYWJzID0gTWF0aC5hYnModmFsdWUkJDEpOwogICAgICAgIGlmIChhYnMgPiBNQVhfU01JKSByZXR1cm4gZmFsc2U7CiAgICAgICAgcmV0dXJuIHRydWU7CgogICAgICBkZWZhdWx0OgogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGVuY29kZVNtaShwcmltaXRpdmUpIHsKICAgIGlmIChwcmltaXRpdmUgPCAwKSB7CiAgICAgIHZhciBhYnMgPSBNYXRoLmFicyhwcmltaXRpdmUpOwogICAgICBpZiAoYWJzID4gTUFYX1NNSSkgdGhyb3cgbmV3IEVycm9yKCdub3Qgc21pJyk7CiAgICAgIHJldHVybiBNYXRoLmFicyhwcmltaXRpdmUpIDw8IDMgfCA0CiAgICAgIC8qIE5FR0FUSVZFICovCiAgICAgIDsKICAgIH0gZWxzZSB7CiAgICAgIGlmIChwcmltaXRpdmUgPiBNQVhfU01JKSB0aHJvdyBuZXcgRXJyb3IoJ25vdCBzbWknKTsKICAgICAgcmV0dXJuIHByaW1pdGl2ZSA8PCAzIHwgMAogICAgICAvKiBOVU1CRVIgKi8KICAgICAgOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZW5jb2RlSW1tZWRpYXRlKHByaW1pdGl2ZSkgewogICAgc3dpdGNoICh0eXBlb2YgcHJpbWl0aXZlKSB7CiAgICAgIGNhc2UgJ251bWJlcic6CiAgICAgICAgcmV0dXJuIGVuY29kZVNtaShwcmltaXRpdmUpOwoKICAgICAgY2FzZSAnYm9vbGVhbic6CiAgICAgICAgcmV0dXJuIHByaW1pdGl2ZSA/IDExCiAgICAgICAgLyogVHJ1ZSAqLwogICAgICAgIDogMwogICAgICAgIC8qIEZhbHNlICovCiAgICAgICAgOwoKICAgICAgY2FzZSAnb2JqZWN0JzoKICAgICAgICAvLyBhc3N1bWUgbnVsbAogICAgICAgIHJldHVybiAxOQogICAgICAgIC8qIE51bGwgKi8KICAgICAgICA7CgogICAgICBjYXNlICd1bmRlZmluZWQnOgogICAgICAgIHJldHVybiAyNwogICAgICAgIC8qIFVuZGVmICovCiAgICAgICAgOwoKICAgICAgZGVmYXVsdDoKICAgICAgICB0aHJvdyAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBkZWNvZGVTbWkoc21pKSB7CiAgICBzd2l0Y2ggKHNtaSAmIDcpIHsKICAgICAgY2FzZSAwCiAgICAgIC8qIE5VTUJFUiAqLwogICAgICA6CiAgICAgICAgcmV0dXJuIHNtaSA+PiAzOwoKICAgICAgY2FzZSA0CiAgICAgIC8qIE5FR0FUSVZFICovCiAgICAgIDoKICAgICAgICByZXR1cm4gLShzbWkgPj4gMyk7CgogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93ICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGRlY29kZUltbWVkaWF0ZShpbW1lZGlhdGUpIHsKICAgIHN3aXRjaCAoaW1tZWRpYXRlKSB7CiAgICAgIGNhc2UgMwogICAgICAvKiBGYWxzZSAqLwogICAgICA6CiAgICAgICAgcmV0dXJuIGZhbHNlOwoKICAgICAgY2FzZSAxMQogICAgICAvKiBUcnVlICovCiAgICAgIDoKICAgICAgICByZXR1cm4gdHJ1ZTsKCiAgICAgIGNhc2UgMTkKICAgICAgLyogTnVsbCAqLwogICAgICA6CiAgICAgICAgcmV0dXJuIG51bGw7CgogICAgICBjYXNlIDI3CiAgICAgIC8qIFVuZGVmICovCiAgICAgIDoKICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwoKICAgICAgZGVmYXVsdDoKICAgICAgICByZXR1cm4gZGVjb2RlU21pKGltbWVkaWF0ZSk7CiAgICB9CiAgfQoKICB2YXIgVXBkYXRpbmdWTSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFVwZGF0aW5nVk0oZW52LCBwcm9ncmFtLCBfcmVmNTcpIHsKICAgICAgdmFyIF9yZWY1NyRhbHdheXNSZXZhbGlkYSA9IF9yZWY1Ny5hbHdheXNSZXZhbGlkYXRlLAogICAgICAgICAgYWx3YXlzUmV2YWxpZGF0ZSA9IF9yZWY1NyRhbHdheXNSZXZhbGlkYSA9PT0gdm9pZCAwID8gZmFsc2UgOiBfcmVmNTckYWx3YXlzUmV2YWxpZGE7CiAgICAgIHRoaXMuZnJhbWVTdGFjayA9IG5ldyBfdXRpbC5TdGFjaygpOwogICAgICB0aGlzLmVudiA9IGVudjsKICAgICAgdGhpcy5jb25zdGFudHMgPSBwcm9ncmFtLmNvbnN0YW50czsKICAgICAgdGhpcy5kb20gPSBlbnYuZ2V0RE9NKCk7CiAgICAgIHRoaXMuYWx3YXlzUmV2YWxpZGF0ZSA9IGFsd2F5c1JldmFsaWRhdGU7CiAgICB9CgogICAgdmFyIF9wcm90bzQ5ID0gVXBkYXRpbmdWTS5wcm90b3R5cGU7CgogICAgX3Byb3RvNDkuZXhlY3V0ZSA9IGZ1bmN0aW9uIGV4ZWN1dGUob3Bjb2RlcywgaGFuZGxlcikgewogICAgICB2YXIgZnJhbWVTdGFjayA9IHRoaXMuZnJhbWVTdGFjazsKICAgICAgdGhpcy50cnkob3Bjb2RlcywgaGFuZGxlcik7CgogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgIGlmIChmcmFtZVN0YWNrLmlzRW1wdHkoKSkgYnJlYWs7CiAgICAgICAgdmFyIG9wY29kZSA9IHRoaXMuZnJhbWUubmV4dFN0YXRlbWVudCgpOwoKICAgICAgICBpZiAob3Bjb2RlID09PSBudWxsKSB7CiAgICAgICAgICB0aGlzLmZyYW1lU3RhY2sucG9wKCk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIG9wY29kZS5ldmFsdWF0ZSh0aGlzKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG80OS5nb3RvID0gZnVuY3Rpb24gZ290byhvcCkgewogICAgICB0aGlzLmZyYW1lLmdvdG8ob3ApOwogICAgfTsKCiAgICBfcHJvdG80OS50cnkgPSBmdW5jdGlvbiBfdHJ5KG9wcywgaGFuZGxlcikgewogICAgICB0aGlzLmZyYW1lU3RhY2sucHVzaChuZXcgVXBkYXRpbmdWTUZyYW1lKG9wcywgaGFuZGxlcikpOwogICAgfTsKCiAgICBfcHJvdG80OS50aHJvdyA9IGZ1bmN0aW9uIF90aHJvdygpIHsKICAgICAgdGhpcy5mcmFtZS5oYW5kbGVFeGNlcHRpb24oKTsKICAgICAgdGhpcy5mcmFtZVN0YWNrLnBvcCgpOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKFVwZGF0aW5nVk0sIFt7CiAgICAgIGtleTogImZyYW1lIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZnJhbWVTdGFjay5jdXJyZW50OwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gVXBkYXRpbmdWTTsKICB9KCk7CgogIF9leHBvcnRzLlVwZGF0aW5nVk0gPSBVcGRhdGluZ1ZNOwoKICB2YXIgQmxvY2tPcGNvZGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1VwZGF0aW5nT3Bjb2RlOSkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEJsb2NrT3Bjb2RlLCBfVXBkYXRpbmdPcGNvZGU5KTsKCiAgICBmdW5jdGlvbiBCbG9ja09wY29kZShzdGFydCwgc3RhdGUsIHJ1bnRpbWUsIGJvdW5kcywgY2hpbGRyZW4pIHsKICAgICAgdmFyIF90aGlzMTU7CgogICAgICBfdGhpczE1ID0gX1VwZGF0aW5nT3Bjb2RlOS5jYWxsKHRoaXMpIHx8IHRoaXM7CiAgICAgIF90aGlzMTUuc3RhcnQgPSBzdGFydDsKICAgICAgX3RoaXMxNS5zdGF0ZSA9IHN0YXRlOwogICAgICBfdGhpczE1LnJ1bnRpbWUgPSBydW50aW1lOwogICAgICBfdGhpczE1LnR5cGUgPSAnYmxvY2snOwogICAgICBfdGhpczE1Lm5leHQgPSBudWxsOwogICAgICBfdGhpczE1LnByZXYgPSBudWxsOwogICAgICBfdGhpczE1LmNoaWxkcmVuID0gY2hpbGRyZW47CiAgICAgIF90aGlzMTUuYm91bmRzID0gYm91bmRzOwogICAgICByZXR1cm4gX3RoaXMxNTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTAgPSBCbG9ja09wY29kZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNTAucGFyZW50RWxlbWVudCA9IGZ1bmN0aW9uIHBhcmVudEVsZW1lbnQoKSB7CiAgICAgIHJldHVybiB0aGlzLmJvdW5kcy5wYXJlbnRFbGVtZW50KCk7CiAgICB9OwoKICAgIF9wcm90bzUwLmZpcnN0Tm9kZSA9IGZ1bmN0aW9uIGZpcnN0Tm9kZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuYm91bmRzLmZpcnN0Tm9kZSgpOwogICAgfTsKCiAgICBfcHJvdG81MC5sYXN0Tm9kZSA9IGZ1bmN0aW9uIGxhc3ROb2RlKCkgewogICAgICByZXR1cm4gdGhpcy5ib3VuZHMubGFzdE5vZGUoKTsKICAgIH07CgogICAgX3Byb3RvNTAuZXZhbHVhdGUgPSBmdW5jdGlvbiBldmFsdWF0ZSh2bSkgewogICAgICB2bS50cnkodGhpcy5jaGlsZHJlbiwgbnVsbCk7CiAgICB9OwoKICAgIF9wcm90bzUwLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICB0aGlzLmJvdW5kcy5kZXN0cm95KCk7CiAgICB9OwoKICAgIF9wcm90bzUwLmRpZERlc3Ryb3kgPSBmdW5jdGlvbiBkaWREZXN0cm95KCkgewogICAgICB0aGlzLnJ1bnRpbWUuZW52LmRpZERlc3Ryb3kodGhpcy5ib3VuZHMpOwogICAgfTsKCiAgICByZXR1cm4gQmxvY2tPcGNvZGU7CiAgfShVcGRhdGluZ09wY29kZSk7CgogIHZhciBUcnlPcGNvZGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0Jsb2NrT3Bjb2RlKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoVHJ5T3Bjb2RlLCBfQmxvY2tPcGNvZGUpOwoKICAgIGZ1bmN0aW9uIFRyeU9wY29kZShzdGFydCwgc3RhdGUsIHJ1bnRpbWUsIGJvdW5kcywgY2hpbGRyZW4pIHsKICAgICAgdmFyIF90aGlzMTY7CgogICAgICBfdGhpczE2ID0gX0Jsb2NrT3Bjb2RlLmNhbGwodGhpcywgc3RhcnQsIHN0YXRlLCBydW50aW1lLCBib3VuZHMsIGNoaWxkcmVuKSB8fCB0aGlzOwogICAgICBfdGhpczE2LnR5cGUgPSAndHJ5JzsKICAgICAgX3RoaXMxNi50YWcgPSBfdGhpczE2Ll90YWcgPSAoMCwgX3JlZmVyZW5jZTIuY3JlYXRlVXBkYXRhYmxlVGFnKSgpOwogICAgICByZXR1cm4gX3RoaXMxNjsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTEgPSBUcnlPcGNvZGUucHJvdG90eXBlOwoKICAgIF9wcm90bzUxLmRpZEluaXRpYWxpemVDaGlsZHJlbiA9IGZ1bmN0aW9uIGRpZEluaXRpYWxpemVDaGlsZHJlbigpIHsKICAgICAgKDAsIF9yZWZlcmVuY2UyLnVwZGF0ZSkodGhpcy5fdGFnLCAoMCwgX3JlZmVyZW5jZTIuY29tYmluZVNsaWNlKSh0aGlzLmNoaWxkcmVuKSk7CiAgICB9OwoKICAgIF9wcm90bzUxLmV2YWx1YXRlID0gZnVuY3Rpb24gZXZhbHVhdGUodm0pIHsKICAgICAgdm0udHJ5KHRoaXMuY2hpbGRyZW4sIHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG81MS5oYW5kbGVFeGNlcHRpb24gPSBmdW5jdGlvbiBoYW5kbGVFeGNlcHRpb24oKSB7CiAgICAgIHZhciBfdGhpczE3ID0gdGhpczsKCiAgICAgIHZhciBzdGF0ZSA9IHRoaXMuc3RhdGUsCiAgICAgICAgICBib3VuZHMgPSB0aGlzLmJvdW5kcywKICAgICAgICAgIGNoaWxkcmVuID0gdGhpcy5jaGlsZHJlbiwKICAgICAgICAgIHN0YXJ0ID0gdGhpcy5zdGFydCwKICAgICAgICAgIHByZXYgPSB0aGlzLnByZXYsCiAgICAgICAgICBuZXh0ID0gdGhpcy5uZXh0LAogICAgICAgICAgcnVudGltZSA9IHRoaXMucnVudGltZTsKICAgICAgY2hpbGRyZW4uY2xlYXIoKTsKICAgICAgdmFyIGVsZW1lbnRTdGFjayA9IE5ld0VsZW1lbnRCdWlsZGVyLnJlc3VtZShydW50aW1lLmVudiwgYm91bmRzLCBib3VuZHMucmVzZXQocnVudGltZS5lbnYpKTsKICAgICAgdmFyIHZtID0gVk0ucmVzdW1lKHN0YXRlLCBydW50aW1lLCBlbGVtZW50U3RhY2spOwogICAgICB2YXIgdXBkYXRpbmcgPSBuZXcgX3V0aWwuTGlua2VkTGlzdCgpOwogICAgICB2bS5leGVjdXRlKHN0YXJ0LCBmdW5jdGlvbiAodm0pIHsKICAgICAgICB2bS5zdGFjayA9IEV2YWx1YXRpb25TdGFjay5yZXN0b3JlKHN0YXRlLnN0YWNrKTsKICAgICAgICB2bS51cGRhdGluZ09wY29kZVN0YWNrLnB1c2godXBkYXRpbmcpOwogICAgICAgIHZtLnVwZGF0ZVdpdGgoX3RoaXMxNyk7CiAgICAgICAgdm0udXBkYXRpbmdPcGNvZGVTdGFjay5wdXNoKGNoaWxkcmVuKTsKICAgICAgfSk7CiAgICAgIHRoaXMucHJldiA9IHByZXY7CiAgICAgIHRoaXMubmV4dCA9IG5leHQ7CiAgICB9OwoKICAgIHJldHVybiBUcnlPcGNvZGU7CiAgfShCbG9ja09wY29kZSk7CgogIHZhciBMaXN0UmV2YWxpZGF0aW9uRGVsZWdhdGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBMaXN0UmV2YWxpZGF0aW9uRGVsZWdhdGUob3Bjb2RlLCBtYXJrZXIpIHsKICAgICAgdGhpcy5vcGNvZGUgPSBvcGNvZGU7CiAgICAgIHRoaXMubWFya2VyID0gbWFya2VyOwogICAgICB0aGlzLmRpZEluc2VydCA9IGZhbHNlOwogICAgICB0aGlzLmRpZERlbGV0ZSA9IGZhbHNlOwogICAgICB0aGlzLm1hcCA9IG9wY29kZS5tYXA7CiAgICAgIHRoaXMudXBkYXRpbmcgPSBvcGNvZGVbJ2NoaWxkcmVuJ107CiAgICB9CgogICAgdmFyIF9wcm90bzUyID0gTGlzdFJldmFsaWRhdGlvbkRlbGVnYXRlLnByb3RvdHlwZTsKCiAgICBfcHJvdG81Mi5pbnNlcnQgPSBmdW5jdGlvbiBpbnNlcnQoa2V5LCBpdGVtLCBtZW1vLCBiZWZvcmUpIHsKICAgICAgdmFyIG1hcCA9IHRoaXMubWFwLAogICAgICAgICAgb3Bjb2RlID0gdGhpcy5vcGNvZGUsCiAgICAgICAgICB1cGRhdGluZyA9IHRoaXMudXBkYXRpbmc7CiAgICAgIHZhciBuZXh0U2libGluZyA9IG51bGw7CiAgICAgIHZhciByZWZlcmVuY2UgPSBudWxsOwoKICAgICAgaWYgKHR5cGVvZiBiZWZvcmUgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgcmVmZXJlbmNlID0gbWFwW2JlZm9yZV07CiAgICAgICAgbmV4dFNpYmxpbmcgPSByZWZlcmVuY2VbJ2JvdW5kcyddLmZpcnN0Tm9kZSgpOwogICAgICB9IGVsc2UgewogICAgICAgIG5leHRTaWJsaW5nID0gdGhpcy5tYXJrZXI7CiAgICAgIH0KCiAgICAgIHZhciB2bSA9IG9wY29kZS52bUZvckluc2VydGlvbihuZXh0U2libGluZyk7CiAgICAgIHZhciB0cnlPcGNvZGUgPSBudWxsOwogICAgICB2YXIgc3RhcnQgPSBvcGNvZGUuc3RhcnQ7CiAgICAgIHZtLmV4ZWN1dGUoc3RhcnQsIGZ1bmN0aW9uICh2bSkgewogICAgICAgIG1hcFtrZXldID0gdHJ5T3Bjb2RlID0gdm0uaXRlcmF0ZShtZW1vLCBpdGVtKTsKICAgICAgICB2bS51cGRhdGluZ09wY29kZVN0YWNrLnB1c2gobmV3IF91dGlsLkxpbmtlZExpc3QoKSk7CiAgICAgICAgdm0udXBkYXRlV2l0aCh0cnlPcGNvZGUpOwogICAgICAgIHZtLnVwZGF0aW5nT3Bjb2RlU3RhY2sucHVzaCh0cnlPcGNvZGUuY2hpbGRyZW4pOwogICAgICB9KTsKICAgICAgdXBkYXRpbmcuaW5zZXJ0QmVmb3JlKHRyeU9wY29kZSwgcmVmZXJlbmNlKTsKICAgICAgdGhpcy5kaWRJbnNlcnQgPSB0cnVlOwogICAgfTsKCiAgICBfcHJvdG81Mi5yZXRhaW4gPSBmdW5jdGlvbiByZXRhaW4oX2tleSwgX2l0ZW0sIF9tZW1vKSB7fTsKCiAgICBfcHJvdG81Mi5tb3ZlID0gZnVuY3Rpb24gbW92ZShrZXksIF9pdGVtLCBfbWVtbywgYmVmb3JlKSB7CiAgICAgIHZhciBtYXAgPSB0aGlzLm1hcCwKICAgICAgICAgIHVwZGF0aW5nID0gdGhpcy51cGRhdGluZzsKICAgICAgdmFyIGVudHJ5ID0gbWFwW2tleV07CiAgICAgIHZhciByZWZlcmVuY2UgPSBtYXBbYmVmb3JlXSB8fCBudWxsOwoKICAgICAgaWYgKHR5cGVvZiBiZWZvcmUgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgX21vdmUoZW50cnksIHJlZmVyZW5jZS5maXJzdE5vZGUoKSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgX21vdmUoZW50cnksIHRoaXMubWFya2VyKTsKICAgICAgfQoKICAgICAgdXBkYXRpbmcucmVtb3ZlKGVudHJ5KTsKICAgICAgdXBkYXRpbmcuaW5zZXJ0QmVmb3JlKGVudHJ5LCByZWZlcmVuY2UpOwogICAgfTsKCiAgICBfcHJvdG81Mi5kZWxldGUgPSBmdW5jdGlvbiBfZGVsZXRlKGtleSkgewogICAgICB2YXIgbWFwID0gdGhpcy5tYXA7CiAgICAgIHZhciBvcGNvZGUgPSBtYXBba2V5XTsKICAgICAgb3Bjb2RlLmRpZERlc3Ryb3koKTsKICAgICAgY2xlYXIob3Bjb2RlKTsKICAgICAgdGhpcy51cGRhdGluZy5yZW1vdmUob3Bjb2RlKTsKICAgICAgZGVsZXRlIG1hcFtrZXldOwogICAgICB0aGlzLmRpZERlbGV0ZSA9IHRydWU7CiAgICB9OwoKICAgIF9wcm90bzUyLmRvbmUgPSBmdW5jdGlvbiBkb25lKCkgewogICAgICB0aGlzLm9wY29kZS5kaWRJbml0aWFsaXplQ2hpbGRyZW4odGhpcy5kaWRJbnNlcnQgfHwgdGhpcy5kaWREZWxldGUpOwogICAgfTsKCiAgICByZXR1cm4gTGlzdFJldmFsaWRhdGlvbkRlbGVnYXRlOwogIH0oKTsKCiAgdmFyIExpc3RCbG9ja09wY29kZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQmxvY2tPcGNvZGUyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTGlzdEJsb2NrT3Bjb2RlLCBfQmxvY2tPcGNvZGUyKTsKCiAgICBmdW5jdGlvbiBMaXN0QmxvY2tPcGNvZGUoc3RhcnQsIHN0YXRlLCBydW50aW1lLCBib3VuZHMsIGNoaWxkcmVuLCBhcnRpZmFjdHMpIHsKICAgICAgdmFyIF90aGlzMTg7CgogICAgICBfdGhpczE4ID0gX0Jsb2NrT3Bjb2RlMi5jYWxsKHRoaXMsIHN0YXJ0LCBzdGF0ZSwgcnVudGltZSwgYm91bmRzLCBjaGlsZHJlbikgfHwgdGhpczsKICAgICAgX3RoaXMxOC50eXBlID0gJ2xpc3QtYmxvY2snOwogICAgICBfdGhpczE4Lm1hcCA9ICgwLCBfdXRpbC5kaWN0KSgpOwogICAgICBfdGhpczE4Lmxhc3RJdGVyYXRlZCA9IF9yZWZlcmVuY2UyLklOSVRJQUw7CiAgICAgIF90aGlzMTguYXJ0aWZhY3RzID0gYXJ0aWZhY3RzOwoKICAgICAgdmFyIF90YWcgPSBfdGhpczE4Ll90YWcgPSAoMCwgX3JlZmVyZW5jZTIuY3JlYXRlVXBkYXRhYmxlVGFnKSgpOwoKICAgICAgX3RoaXMxOC50YWcgPSAoMCwgX3JlZmVyZW5jZTIuY29tYmluZSkoW2FydGlmYWN0cy50YWcsIF90YWddKTsKICAgICAgcmV0dXJuIF90aGlzMTg7CiAgICB9CgogICAgdmFyIF9wcm90bzUzID0gTGlzdEJsb2NrT3Bjb2RlLnByb3RvdHlwZTsKCiAgICBfcHJvdG81My5kaWRJbml0aWFsaXplQ2hpbGRyZW4gPSBmdW5jdGlvbiBkaWRJbml0aWFsaXplQ2hpbGRyZW4obGlzdERpZENoYW5nZSkgewogICAgICBpZiAobGlzdERpZENoYW5nZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgbGlzdERpZENoYW5nZSA9IHRydWU7CiAgICAgIH0KCiAgICAgIHRoaXMubGFzdEl0ZXJhdGVkID0gKDAsIF9yZWZlcmVuY2UyLnZhbHVlKSh0aGlzLmFydGlmYWN0cy50YWcpOwoKICAgICAgaWYgKGxpc3REaWRDaGFuZ2UpIHsKICAgICAgICAoMCwgX3JlZmVyZW5jZTIudXBkYXRlKSh0aGlzLl90YWcsICgwLCBfcmVmZXJlbmNlMi5jb21iaW5lU2xpY2UpKHRoaXMuY2hpbGRyZW4pKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG81My5ldmFsdWF0ZSA9IGZ1bmN0aW9uIGV2YWx1YXRlKHZtKSB7CiAgICAgIHZhciBhcnRpZmFjdHMgPSB0aGlzLmFydGlmYWN0cywKICAgICAgICAgIGxhc3RJdGVyYXRlZCA9IHRoaXMubGFzdEl0ZXJhdGVkOwoKICAgICAgaWYgKCEoMCwgX3JlZmVyZW5jZTIudmFsaWRhdGUpKGFydGlmYWN0cy50YWcsIGxhc3RJdGVyYXRlZCkpIHsKICAgICAgICB2YXIgYm91bmRzID0gdGhpcy5ib3VuZHM7CiAgICAgICAgdmFyIGRvbSA9IHZtLmRvbTsKICAgICAgICB2YXIgbWFya2VyID0gZG9tLmNyZWF0ZUNvbW1lbnQoJycpOwogICAgICAgIGRvbS5pbnNlcnRBZnRlcihib3VuZHMucGFyZW50RWxlbWVudCgpLCBtYXJrZXIsIGJvdW5kcy5sYXN0Tm9kZSgpKTsKICAgICAgICB2YXIgdGFyZ2V0ID0gbmV3IExpc3RSZXZhbGlkYXRpb25EZWxlZ2F0ZSh0aGlzLCBtYXJrZXIpOwogICAgICAgIHZhciBzeW5jaHJvbml6ZXIgPSBuZXcgX3JlZmVyZW5jZTIuSXRlcmF0b3JTeW5jaHJvbml6ZXIoewogICAgICAgICAgdGFyZ2V0OiB0YXJnZXQsCiAgICAgICAgICBhcnRpZmFjdHM6IGFydGlmYWN0cwogICAgICAgIH0pOwogICAgICAgIHN5bmNocm9uaXplci5zeW5jKCk7CiAgICAgICAgdGhpcy5wYXJlbnRFbGVtZW50KCkucmVtb3ZlQ2hpbGQobWFya2VyKTsKICAgICAgfSAvLyBSdW4gbm93LXVwZGF0ZWQgdXBkYXRpbmcgb3Bjb2RlcwoKCiAgICAgIF9CbG9ja09wY29kZTIucHJvdG90eXBlLmV2YWx1YXRlLmNhbGwodGhpcywgdm0pOwogICAgfTsKCiAgICBfcHJvdG81My52bUZvckluc2VydGlvbiA9IGZ1bmN0aW9uIHZtRm9ySW5zZXJ0aW9uKG5leHRTaWJsaW5nKSB7CiAgICAgIHZhciBib3VuZHMgPSB0aGlzLmJvdW5kcywKICAgICAgICAgIHN0YXRlID0gdGhpcy5zdGF0ZSwKICAgICAgICAgIHJ1bnRpbWUgPSB0aGlzLnJ1bnRpbWU7CiAgICAgIHZhciBlbGVtZW50U3RhY2sgPSBOZXdFbGVtZW50QnVpbGRlci5mb3JJbml0aWFsUmVuZGVyKHJ1bnRpbWUuZW52LCB7CiAgICAgICAgZWxlbWVudDogYm91bmRzLnBhcmVudEVsZW1lbnQoKSwKICAgICAgICBuZXh0U2libGluZzogbmV4dFNpYmxpbmcKICAgICAgfSk7CiAgICAgIHJldHVybiBWTS5yZXN1bWUoc3RhdGUsIHJ1bnRpbWUsIGVsZW1lbnRTdGFjayk7CiAgICB9OwoKICAgIHJldHVybiBMaXN0QmxvY2tPcGNvZGU7CiAgfShCbG9ja09wY29kZSk7CgogIHZhciBVcGRhdGluZ1ZNRnJhbWUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBVcGRhdGluZ1ZNRnJhbWUob3BzLCBleGNlcHRpb25IYW5kbGVyKSB7CiAgICAgIHRoaXMub3BzID0gb3BzOwogICAgICB0aGlzLmV4Y2VwdGlvbkhhbmRsZXIgPSBleGNlcHRpb25IYW5kbGVyOwogICAgICB0aGlzLmN1cnJlbnQgPSBvcHMuaGVhZCgpOwogICAgfQoKICAgIHZhciBfcHJvdG81NCA9IFVwZGF0aW5nVk1GcmFtZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNTQuZ290byA9IGZ1bmN0aW9uIGdvdG8ob3ApIHsKICAgICAgdGhpcy5jdXJyZW50ID0gb3A7CiAgICB9OwoKICAgIF9wcm90bzU0Lm5leHRTdGF0ZW1lbnQgPSBmdW5jdGlvbiBuZXh0U3RhdGVtZW50KCkgewogICAgICB2YXIgY3VycmVudCA9IHRoaXMuY3VycmVudCwKICAgICAgICAgIG9wcyA9IHRoaXMub3BzOwogICAgICBpZiAoY3VycmVudCkgdGhpcy5jdXJyZW50ID0gb3BzLm5leHROb2RlKGN1cnJlbnQpOwogICAgICByZXR1cm4gY3VycmVudDsKICAgIH07CgogICAgX3Byb3RvNTQuaGFuZGxlRXhjZXB0aW9uID0gZnVuY3Rpb24gaGFuZGxlRXhjZXB0aW9uKCkgewogICAgICBpZiAodGhpcy5leGNlcHRpb25IYW5kbGVyKSB7CiAgICAgICAgdGhpcy5leGNlcHRpb25IYW5kbGVyLmhhbmRsZUV4Y2VwdGlvbigpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBVcGRhdGluZ1ZNRnJhbWU7CiAgfSgpOwoKICB2YXIgUmVuZGVyUmVzdWx0ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUmVuZGVyUmVzdWx0KGVudiwgcHJvZ3JhbSwgdXBkYXRpbmcsIGJvdW5kcykgewogICAgICB0aGlzLmVudiA9IGVudjsKICAgICAgdGhpcy5wcm9ncmFtID0gcHJvZ3JhbTsKICAgICAgdGhpcy51cGRhdGluZyA9IHVwZGF0aW5nOwogICAgICB0aGlzLmJvdW5kcyA9IGJvdW5kczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTUgPSBSZW5kZXJSZXN1bHQucHJvdG90eXBlOwoKICAgIF9wcm90bzU1LnJlcmVuZGVyID0gZnVuY3Rpb24gcmVyZW5kZXIoX3RlbXApIHsKICAgICAgdmFyIF9yZWY1OCA9IF90ZW1wID09PSB2b2lkIDAgPyB7CiAgICAgICAgYWx3YXlzUmV2YWxpZGF0ZTogZmFsc2UKICAgICAgfSA6IF90ZW1wLAogICAgICAgICAgX3JlZjU4JGFsd2F5c1JldmFsaWRhID0gX3JlZjU4LmFsd2F5c1JldmFsaWRhdGUsCiAgICAgICAgICBhbHdheXNSZXZhbGlkYXRlID0gX3JlZjU4JGFsd2F5c1JldmFsaWRhID09PSB2b2lkIDAgPyBmYWxzZSA6IF9yZWY1OCRhbHdheXNSZXZhbGlkYTsKCiAgICAgIHZhciBlbnYgPSB0aGlzLmVudiwKICAgICAgICAgIHByb2dyYW0gPSB0aGlzLnByb2dyYW0sCiAgICAgICAgICB1cGRhdGluZyA9IHRoaXMudXBkYXRpbmc7CiAgICAgIHZhciB2bSA9IG5ldyBVcGRhdGluZ1ZNKGVudiwgcHJvZ3JhbSwgewogICAgICAgIGFsd2F5c1JldmFsaWRhdGU6IGFsd2F5c1JldmFsaWRhdGUKICAgICAgfSk7CiAgICAgIHZtLmV4ZWN1dGUodXBkYXRpbmcsIHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG81NS5wYXJlbnRFbGVtZW50ID0gZnVuY3Rpb24gcGFyZW50RWxlbWVudCgpIHsKICAgICAgcmV0dXJuIHRoaXMuYm91bmRzLnBhcmVudEVsZW1lbnQoKTsKICAgIH07CgogICAgX3Byb3RvNTUuZmlyc3ROb2RlID0gZnVuY3Rpb24gZmlyc3ROb2RlKCkgewogICAgICByZXR1cm4gdGhpcy5ib3VuZHMuZmlyc3ROb2RlKCk7CiAgICB9OwoKICAgIF9wcm90bzU1Lmxhc3ROb2RlID0gZnVuY3Rpb24gbGFzdE5vZGUoKSB7CiAgICAgIHJldHVybiB0aGlzLmJvdW5kcy5sYXN0Tm9kZSgpOwogICAgfTsKCiAgICBfcHJvdG81NS5oYW5kbGVFeGNlcHRpb24gPSBmdW5jdGlvbiBoYW5kbGVFeGNlcHRpb24oKSB7CiAgICAgIHRocm93ICd0aGlzIHNob3VsZCBuZXZlciBoYXBwZW4nOwogICAgfTsKCiAgICBfcHJvdG81NS5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdGhpcy5ib3VuZHMuZGVzdHJveSgpOwogICAgICBjbGVhcih0aGlzLmJvdW5kcyk7CiAgICB9OwoKICAgIHJldHVybiBSZW5kZXJSZXN1bHQ7CiAgfSgpOwoKICBfZXhwb3J0cy5SZW5kZXJSZXN1bHQgPSBSZW5kZXJSZXN1bHQ7CgogIHZhciBBcmd1bWVudHMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBBcmd1bWVudHMoKSB7CiAgICAgIHRoaXMuc3RhY2sgPSBudWxsOwogICAgICB0aGlzLnBvc2l0aW9uYWwgPSBuZXcgUG9zaXRpb25hbEFyZ3VtZW50cygpOwogICAgICB0aGlzLm5hbWVkID0gbmV3IE5hbWVkQXJndW1lbnRzKCk7CiAgICAgIHRoaXMuYmxvY2tzID0gbmV3IEJsb2NrQXJndW1lbnRzKCk7CiAgICB9CgogICAgdmFyIF9wcm90bzU2ID0gQXJndW1lbnRzLnByb3RvdHlwZTsKCiAgICBfcHJvdG81Ni5lbXB0eSA9IGZ1bmN0aW9uIGVtcHR5KHN0YWNrKSB7CiAgICAgIHZhciBiYXNlID0gc3RhY2suc3AgKyAxOwogICAgICB0aGlzLm5hbWVkLmVtcHR5KHN0YWNrLCBiYXNlKTsKICAgICAgdGhpcy5wb3NpdGlvbmFsLmVtcHR5KHN0YWNrLCBiYXNlKTsKICAgICAgdGhpcy5ibG9ja3MuZW1wdHkoc3RhY2ssIGJhc2UpOwogICAgICByZXR1cm4gdGhpczsKICAgIH07CgogICAgX3Byb3RvNTYuc2V0dXAgPSBmdW5jdGlvbiBzZXR1cChzdGFjaywgbmFtZXMsIGJsb2NrTmFtZXMsIHBvc2l0aW9uYWxDb3VudCwgc3ludGhldGljKSB7CiAgICAgIHRoaXMuc3RhY2sgPSBzdGFjazsKICAgICAgLyoKICAgICAgICAgICAgIHwgLi4uIHwgYmxvY2tzICAgICAgfCBwb3NpdGlvbmFsICB8IG5hbWVkIHwKICAgICAgICAgICAgIHwgLi4uIHwgYjAgICAgYjEgICAgfCBwMCBwMSBwMiBwMyB8IG4wIG4xIHwKICAgICAgIGluZGV4IHwgLi4uIHwgNC81LzYgNy84LzkgfCAxMCAxMSAxMiAxMyB8IDE0IDE1IHwKICAgICAgICAgICAgICAgICAgICAgXiAgICAgICAgICAgICBeICAgICAgICAgICAgIF4gIF4KICAgICAgICAgICAgICAgICAgIGJiYXNlICAgICAgICAgcGJhc2UgICAgICAgbmJhc2UgIHNwCiAgICAgICovCgogICAgICB2YXIgbmFtZWQgPSB0aGlzLm5hbWVkOwogICAgICB2YXIgbmFtZWRDb3VudCA9IG5hbWVzLmxlbmd0aDsKICAgICAgdmFyIG5hbWVkQmFzZSA9IHN0YWNrLnNwIC0gbmFtZWRDb3VudCArIDE7CiAgICAgIG5hbWVkLnNldHVwKHN0YWNrLCBuYW1lZEJhc2UsIG5hbWVkQ291bnQsIG5hbWVzLCBzeW50aGV0aWMpOwogICAgICB2YXIgcG9zaXRpb25hbCA9IHRoaXMucG9zaXRpb25hbDsKICAgICAgdmFyIHBvc2l0aW9uYWxCYXNlID0gbmFtZWRCYXNlIC0gcG9zaXRpb25hbENvdW50OwogICAgICBwb3NpdGlvbmFsLnNldHVwKHN0YWNrLCBwb3NpdGlvbmFsQmFzZSwgcG9zaXRpb25hbENvdW50KTsKICAgICAgdmFyIGJsb2NrcyA9IHRoaXMuYmxvY2tzOwogICAgICB2YXIgYmxvY2tzQ291bnQgPSBibG9ja05hbWVzLmxlbmd0aDsKICAgICAgdmFyIGJsb2Nrc0Jhc2UgPSBwb3NpdGlvbmFsQmFzZSAtIGJsb2Nrc0NvdW50ICogMzsKICAgICAgYmxvY2tzLnNldHVwKHN0YWNrLCBibG9ja3NCYXNlLCBibG9ja3NDb3VudCwgYmxvY2tOYW1lcyk7CiAgICB9OwoKICAgIF9wcm90bzU2LmF0ID0gZnVuY3Rpb24gYXQocG9zKSB7CiAgICAgIHJldHVybiB0aGlzLnBvc2l0aW9uYWwuYXQocG9zKTsKICAgIH07CgogICAgX3Byb3RvNTYucmVhbGxvYyA9IGZ1bmN0aW9uIHJlYWxsb2Mob2Zmc2V0KSB7CiAgICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2s7CgogICAgICBpZiAob2Zmc2V0ID4gMCAmJiBzdGFjayAhPT0gbnVsbCkgewogICAgICAgIHZhciBwb3NpdGlvbmFsID0gdGhpcy5wb3NpdGlvbmFsLAogICAgICAgICAgICBuYW1lZCA9IHRoaXMubmFtZWQ7CiAgICAgICAgdmFyIG5ld0Jhc2UgPSBwb3NpdGlvbmFsLmJhc2UgKyBvZmZzZXQ7CiAgICAgICAgdmFyIGxlbmd0aCA9IHBvc2l0aW9uYWwubGVuZ3RoICsgbmFtZWQubGVuZ3RoOwoKICAgICAgICBmb3IgKHZhciBpID0gbGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICAgIHN0YWNrLmNvcHkoaSArIHBvc2l0aW9uYWwuYmFzZSwgaSArIG5ld0Jhc2UpOwogICAgICAgIH0KCiAgICAgICAgcG9zaXRpb25hbC5iYXNlICs9IG9mZnNldDsKICAgICAgICBuYW1lZC5iYXNlICs9IG9mZnNldDsKICAgICAgICBzdGFjay5zcCArPSBvZmZzZXQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNTYuY2FwdHVyZSA9IGZ1bmN0aW9uIGNhcHR1cmUoKSB7CiAgICAgIHZhciBwb3NpdGlvbmFsID0gdGhpcy5wb3NpdGlvbmFsLmxlbmd0aCA9PT0gMCA/IEVNUFRZX1BPU0lUSU9OQUwgOiB0aGlzLnBvc2l0aW9uYWwuY2FwdHVyZSgpOwogICAgICB2YXIgbmFtZWQgPSB0aGlzLm5hbWVkLmxlbmd0aCA9PT0gMCA/IEVNUFRZX05BTUVEIDogdGhpcy5uYW1lZC5jYXB0dXJlKCk7CiAgICAgIHJldHVybiBuZXcgQ2FwdHVyZWRBcmd1bWVudHModGhpcy50YWcsIHBvc2l0aW9uYWwsIG5hbWVkLCB0aGlzLmxlbmd0aCk7CiAgICB9OwoKICAgIF9wcm90bzU2LmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7CiAgICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2ssCiAgICAgICAgICBsZW5ndGggPSB0aGlzLmxlbmd0aDsKICAgICAgaWYgKGxlbmd0aCA+IDAgJiYgc3RhY2sgIT09IG51bGwpIHN0YWNrLnBvcChsZW5ndGgpOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKEFyZ3VtZW50cywgW3sKICAgICAga2V5OiAidGFnIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuICgwLCBfcmVmZXJlbmNlMi5jb21iaW5lVGFnZ2VkKShbdGhpcy5wb3NpdGlvbmFsLCB0aGlzLm5hbWVkXSk7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiYmFzZSIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmJsb2Nrcy5iYXNlOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImxlbmd0aCIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLnBvc2l0aW9uYWwubGVuZ3RoICsgdGhpcy5uYW1lZC5sZW5ndGggKyB0aGlzLmJsb2Nrcy5sZW5ndGggKiAzOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gQXJndW1lbnRzOwogIH0oKTsKCiAgdmFyIENhcHR1cmVkQXJndW1lbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ2FwdHVyZWRBcmd1bWVudHModGFnLCBwb3NpdGlvbmFsLCBuYW1lZCwgbGVuZ3RoKSB7CiAgICAgIHRoaXMudGFnID0gdGFnOwogICAgICB0aGlzLnBvc2l0aW9uYWwgPSBwb3NpdGlvbmFsOwogICAgICB0aGlzLm5hbWVkID0gbmFtZWQ7CiAgICAgIHRoaXMubGVuZ3RoID0gbGVuZ3RoOwogICAgfQoKICAgIHZhciBfcHJvdG81NyA9IENhcHR1cmVkQXJndW1lbnRzLnByb3RvdHlwZTsKCiAgICBfcHJvdG81Ny52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkgewogICAgICByZXR1cm4gewogICAgICAgIG5hbWVkOiB0aGlzLm5hbWVkLnZhbHVlKCksCiAgICAgICAgcG9zaXRpb25hbDogdGhpcy5wb3NpdGlvbmFsLnZhbHVlKCkKICAgICAgfTsKICAgIH07CgogICAgcmV0dXJuIENhcHR1cmVkQXJndW1lbnRzOwogIH0oKTsKCiAgdmFyIFBvc2l0aW9uYWxBcmd1bWVudHMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBQb3NpdGlvbmFsQXJndW1lbnRzKCkgewogICAgICB0aGlzLmJhc2UgPSAwOwogICAgICB0aGlzLmxlbmd0aCA9IDA7CiAgICAgIHRoaXMuc3RhY2sgPSBudWxsOwogICAgICB0aGlzLl90YWcgPSBudWxsOwogICAgICB0aGlzLl9yZWZlcmVuY2VzID0gbnVsbDsKICAgIH0KCiAgICB2YXIgX3Byb3RvNTggPSBQb3NpdGlvbmFsQXJndW1lbnRzLnByb3RvdHlwZTsKCiAgICBfcHJvdG81OC5lbXB0eSA9IGZ1bmN0aW9uIGVtcHR5KHN0YWNrLCBiYXNlKSB7CiAgICAgIHRoaXMuc3RhY2sgPSBzdGFjazsKICAgICAgdGhpcy5iYXNlID0gYmFzZTsKICAgICAgdGhpcy5sZW5ndGggPSAwOwogICAgICB0aGlzLl90YWcgPSBfcmVmZXJlbmNlMi5DT05TVEFOVF9UQUc7CiAgICAgIHRoaXMuX3JlZmVyZW5jZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgIH07CgogICAgX3Byb3RvNTguc2V0dXAgPSBmdW5jdGlvbiBzZXR1cChzdGFjaywgYmFzZSwgbGVuZ3RoKSB7CiAgICAgIHRoaXMuc3RhY2sgPSBzdGFjazsKICAgICAgdGhpcy5iYXNlID0gYmFzZTsKICAgICAgdGhpcy5sZW5ndGggPSBsZW5ndGg7CgogICAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgICAgdGhpcy5fdGFnID0gX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHOwogICAgICAgIHRoaXMuX3JlZmVyZW5jZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLl90YWcgPSBudWxsOwogICAgICAgIHRoaXMuX3JlZmVyZW5jZXMgPSBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzU4LmF0ID0gZnVuY3Rpb24gYXQocG9zaXRpb24pIHsKICAgICAgdmFyIGJhc2UgPSB0aGlzLmJhc2UsCiAgICAgICAgICBsZW5ndGggPSB0aGlzLmxlbmd0aCwKICAgICAgICAgIHN0YWNrID0gdGhpcy5zdGFjazsKCiAgICAgIGlmIChwb3NpdGlvbiA8IDAgfHwgcG9zaXRpb24gPj0gbGVuZ3RoKSB7CiAgICAgICAgcmV0dXJuIFVOREVGSU5FRF9SRUZFUkVOQ0U7CiAgICAgIH0KCiAgICAgIHJldHVybiBzdGFjay5nZXQocG9zaXRpb24sIGJhc2UpOwogICAgfTsKCiAgICBfcHJvdG81OC5jYXB0dXJlID0gZnVuY3Rpb24gY2FwdHVyZSgpIHsKICAgICAgcmV0dXJuIG5ldyBDYXB0dXJlZFBvc2l0aW9uYWxBcmd1bWVudHModGhpcy50YWcsIHRoaXMucmVmZXJlbmNlcyk7CiAgICB9OwoKICAgIF9wcm90bzU4LnByZXBlbmQgPSBmdW5jdGlvbiBwcmVwZW5kKG90aGVyKSB7CiAgICAgIHZhciBhZGRpdGlvbnMgPSBvdGhlci5sZW5ndGg7CgogICAgICBpZiAoYWRkaXRpb25zID4gMCkgewogICAgICAgIHZhciBiYXNlID0gdGhpcy5iYXNlLAogICAgICAgICAgICBsZW5ndGggPSB0aGlzLmxlbmd0aCwKICAgICAgICAgICAgc3RhY2sgPSB0aGlzLnN0YWNrOwogICAgICAgIHRoaXMuYmFzZSA9IGJhc2UgPSBiYXNlIC0gYWRkaXRpb25zOwogICAgICAgIHRoaXMubGVuZ3RoID0gbGVuZ3RoICsgYWRkaXRpb25zOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFkZGl0aW9uczsgaSsrKSB7CiAgICAgICAgICBzdGFjay5zZXQob3RoZXIuYXQoaSksIGksIGJhc2UpOwogICAgICAgIH0KCiAgICAgICAgdGhpcy5fdGFnID0gbnVsbDsKICAgICAgICB0aGlzLl9yZWZlcmVuY2VzID0gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKFBvc2l0aW9uYWxBcmd1bWVudHMsIFt7CiAgICAgIGtleTogInRhZyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciB0YWcgPSB0aGlzLl90YWc7CgogICAgICAgIGlmICghdGFnKSB7CiAgICAgICAgICB0YWcgPSB0aGlzLl90YWcgPSAoMCwgX3JlZmVyZW5jZTIuY29tYmluZVRhZ2dlZCkodGhpcy5yZWZlcmVuY2VzKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0YWc7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAicmVmZXJlbmNlcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciByZWZlcmVuY2VzID0gdGhpcy5fcmVmZXJlbmNlczsKCiAgICAgICAgaWYgKCFyZWZlcmVuY2VzKSB7CiAgICAgICAgICB2YXIgc3RhY2sgPSB0aGlzLnN0YWNrLAogICAgICAgICAgICAgIGJhc2UgPSB0aGlzLmJhc2UsCiAgICAgICAgICAgICAgbGVuZ3RoID0gdGhpcy5sZW5ndGg7CiAgICAgICAgICByZWZlcmVuY2VzID0gdGhpcy5fcmVmZXJlbmNlcyA9IHN0YWNrLnNsaWNlQXJyYXkoYmFzZSwgYmFzZSArIGxlbmd0aCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcmVmZXJlbmNlczsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIFBvc2l0aW9uYWxBcmd1bWVudHM7CiAgfSgpOwoKICB2YXIgQ2FwdHVyZWRQb3NpdGlvbmFsQXJndW1lbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQ2FwdHVyZWRQb3NpdGlvbmFsQXJndW1lbnRzKHRhZywgcmVmZXJlbmNlcywgbGVuZ3RoKSB7CiAgICAgIGlmIChsZW5ndGggPT09IHZvaWQgMCkgewogICAgICAgIGxlbmd0aCA9IHJlZmVyZW5jZXMubGVuZ3RoOwogICAgICB9CgogICAgICB0aGlzLnRhZyA9IHRhZzsKICAgICAgdGhpcy5yZWZlcmVuY2VzID0gcmVmZXJlbmNlczsKICAgICAgdGhpcy5sZW5ndGggPSBsZW5ndGg7CiAgICB9CgogICAgQ2FwdHVyZWRQb3NpdGlvbmFsQXJndW1lbnRzLmVtcHR5ID0gZnVuY3Rpb24gZW1wdHkoKSB7CiAgICAgIHJldHVybiBuZXcgQ2FwdHVyZWRQb3NpdGlvbmFsQXJndW1lbnRzKF9yZWZlcmVuY2UyLkNPTlNUQU5UX1RBRywgX3V0aWwuRU1QVFlfQVJSQVksIDApOwogICAgfTsKCiAgICB2YXIgX3Byb3RvNTkgPSBDYXB0dXJlZFBvc2l0aW9uYWxBcmd1bWVudHMucHJvdG90eXBlOwoKICAgIF9wcm90bzU5LmF0ID0gZnVuY3Rpb24gYXQocG9zaXRpb24pIHsKICAgICAgcmV0dXJuIHRoaXMucmVmZXJlbmNlc1twb3NpdGlvbl07CiAgICB9OwoKICAgIF9wcm90bzU5LnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHJldHVybiB0aGlzLnJlZmVyZW5jZXMubWFwKHRoaXMudmFsdWVPZik7CiAgICB9OwoKICAgIF9wcm90bzU5LmdldCA9IGZ1bmN0aW9uIGdldChuYW1lKSB7CiAgICAgIHZhciByZWZlcmVuY2VzID0gdGhpcy5yZWZlcmVuY2VzLAogICAgICAgICAgbGVuZ3RoID0gdGhpcy5sZW5ndGg7CgogICAgICBpZiAobmFtZSA9PT0gJ2xlbmd0aCcpIHsKICAgICAgICByZXR1cm4gUHJpbWl0aXZlUmVmZXJlbmNlLmNyZWF0ZShsZW5ndGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHZhciBpZHggPSBwYXJzZUludChuYW1lLCAxMCk7CgogICAgICAgIGlmIChpZHggPCAwIHx8IGlkeCA+PSBsZW5ndGgpIHsKICAgICAgICAgIHJldHVybiBVTkRFRklORURfUkVGRVJFTkNFOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gcmVmZXJlbmNlc1tpZHhdOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG81OS52YWx1ZU9mID0gZnVuY3Rpb24gdmFsdWVPZihyZWZlcmVuY2UpIHsKICAgICAgcmV0dXJuIHJlZmVyZW5jZS52YWx1ZSgpOwogICAgfTsKCiAgICByZXR1cm4gQ2FwdHVyZWRQb3NpdGlvbmFsQXJndW1lbnRzOwogIH0oKTsKCiAgdmFyIE5hbWVkQXJndW1lbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gTmFtZWRBcmd1bWVudHMoKSB7CiAgICAgIHRoaXMuYmFzZSA9IDA7CiAgICAgIHRoaXMubGVuZ3RoID0gMDsKICAgICAgdGhpcy5fcmVmZXJlbmNlcyA9IG51bGw7CiAgICAgIHRoaXMuX25hbWVzID0gX3V0aWwuRU1QVFlfQVJSQVk7CiAgICAgIHRoaXMuX2F0TmFtZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjAgPSBOYW1lZEFyZ3VtZW50cy5wcm90b3R5cGU7CgogICAgX3Byb3RvNjAuZW1wdHkgPSBmdW5jdGlvbiBlbXB0eShzdGFjaywgYmFzZSkgewogICAgICB0aGlzLnN0YWNrID0gc3RhY2s7CiAgICAgIHRoaXMuYmFzZSA9IGJhc2U7CiAgICAgIHRoaXMubGVuZ3RoID0gMDsKICAgICAgdGhpcy5fcmVmZXJlbmNlcyA9IF91dGlsLkVNUFRZX0FSUkFZOwogICAgICB0aGlzLl9uYW1lcyA9IF91dGlsLkVNUFRZX0FSUkFZOwogICAgICB0aGlzLl9hdE5hbWVzID0gX3V0aWwuRU1QVFlfQVJSQVk7CiAgICB9OwoKICAgIF9wcm90bzYwLnNldHVwID0gZnVuY3Rpb24gc2V0dXAoc3RhY2ssIGJhc2UsIGxlbmd0aCwgbmFtZXMsIHN5bnRoZXRpYykgewogICAgICB0aGlzLnN0YWNrID0gc3RhY2s7CiAgICAgIHRoaXMuYmFzZSA9IGJhc2U7CiAgICAgIHRoaXMubGVuZ3RoID0gbGVuZ3RoOwoKICAgICAgaWYgKGxlbmd0aCA9PT0gMCkgewogICAgICAgIHRoaXMuX3JlZmVyZW5jZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgICAgICB0aGlzLl9uYW1lcyA9IF91dGlsLkVNUFRZX0FSUkFZOwogICAgICAgIHRoaXMuX2F0TmFtZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLl9yZWZlcmVuY2VzID0gbnVsbDsKCiAgICAgICAgaWYgKHN5bnRoZXRpYykgewogICAgICAgICAgdGhpcy5fbmFtZXMgPSBuYW1lczsKICAgICAgICAgIHRoaXMuX2F0TmFtZXMgPSBudWxsOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9uYW1lcyA9IG51bGw7CiAgICAgICAgICB0aGlzLl9hdE5hbWVzID0gbmFtZXM7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzYwLmhhcyA9IGZ1bmN0aW9uIGhhcyhuYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLm5hbWVzLmluZGV4T2YobmFtZSkgIT09IC0xOwogICAgfTsKCiAgICBfcHJvdG82MC5nZXQgPSBmdW5jdGlvbiBnZXQobmFtZSwgc3ludGhldGljKSB7CiAgICAgIGlmIChzeW50aGV0aWMgPT09IHZvaWQgMCkgewogICAgICAgIHN5bnRoZXRpYyA9IHRydWU7CiAgICAgIH0KCiAgICAgIHZhciBiYXNlID0gdGhpcy5iYXNlLAogICAgICAgICAgc3RhY2sgPSB0aGlzLnN0YWNrOwogICAgICB2YXIgbmFtZXMgPSBzeW50aGV0aWMgPyB0aGlzLm5hbWVzIDogdGhpcy5hdE5hbWVzOwogICAgICB2YXIgaWR4ID0gbmFtZXMuaW5kZXhPZihuYW1lKTsKCiAgICAgIGlmIChpZHggPT09IC0xKSB7CiAgICAgICAgcmV0dXJuIFVOREVGSU5FRF9SRUZFUkVOQ0U7CiAgICAgIH0KCiAgICAgIHJldHVybiBzdGFjay5nZXQoaWR4LCBiYXNlKTsKICAgIH07CgogICAgX3Byb3RvNjAuY2FwdHVyZSA9IGZ1bmN0aW9uIGNhcHR1cmUoKSB7CiAgICAgIHJldHVybiBuZXcgQ2FwdHVyZWROYW1lZEFyZ3VtZW50cyh0aGlzLnRhZywgdGhpcy5uYW1lcywgdGhpcy5yZWZlcmVuY2VzKTsKICAgIH07CgogICAgX3Byb3RvNjAubWVyZ2UgPSBmdW5jdGlvbiBtZXJnZShvdGhlcikgewogICAgICB2YXIgZXh0cmFzID0gb3RoZXIubGVuZ3RoOwoKICAgICAgaWYgKGV4dHJhcyA+IDApIHsKICAgICAgICB2YXIgbmFtZXMgPSB0aGlzLm5hbWVzLAogICAgICAgICAgICBsZW5ndGggPSB0aGlzLmxlbmd0aCwKICAgICAgICAgICAgc3RhY2sgPSB0aGlzLnN0YWNrOwogICAgICAgIHZhciBleHRyYU5hbWVzID0gb3RoZXIubmFtZXM7CgogICAgICAgIGlmIChPYmplY3QuaXNGcm96ZW4obmFtZXMpICYmIG5hbWVzLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgbmFtZXMgPSBbXTsKICAgICAgICB9CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXh0cmFzOyBpKyspIHsKICAgICAgICAgIHZhciBuYW1lID0gZXh0cmFOYW1lc1tpXTsKICAgICAgICAgIHZhciBpZHggPSBuYW1lcy5pbmRleE9mKG5hbWUpOwoKICAgICAgICAgIGlmIChpZHggPT09IC0xKSB7CiAgICAgICAgICAgIGxlbmd0aCA9IG5hbWVzLnB1c2gobmFtZSk7CiAgICAgICAgICAgIHN0YWNrLnB1c2gob3RoZXIucmVmZXJlbmNlc1tpXSk7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB0aGlzLmxlbmd0aCA9IGxlbmd0aDsKICAgICAgICB0aGlzLl9yZWZlcmVuY2VzID0gbnVsbDsKICAgICAgICB0aGlzLl9uYW1lcyA9IG5hbWVzOwogICAgICAgIHRoaXMuX2F0TmFtZXMgPSBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzYwLnRvU3ludGhldGljTmFtZSA9IGZ1bmN0aW9uIHRvU3ludGhldGljTmFtZShuYW1lKSB7CiAgICAgIHJldHVybiBuYW1lLnNsaWNlKDEpOwogICAgfTsKCiAgICBfcHJvdG82MC50b0F0TmFtZSA9IGZ1bmN0aW9uIHRvQXROYW1lKG5hbWUpIHsKICAgICAgcmV0dXJuICJAIiArIG5hbWU7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoTmFtZWRBcmd1bWVudHMsIFt7CiAgICAgIGtleTogInRhZyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiAoMCwgX3JlZmVyZW5jZTIuY29tYmluZVRhZ2dlZCkodGhpcy5yZWZlcmVuY2VzKTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJuYW1lcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciBuYW1lcyA9IHRoaXMuX25hbWVzOwoKICAgICAgICBpZiAoIW5hbWVzKSB7CiAgICAgICAgICBuYW1lcyA9IHRoaXMuX25hbWVzID0gdGhpcy5fYXROYW1lcy5tYXAodGhpcy50b1N5bnRoZXRpY05hbWUpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIG5hbWVzOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImF0TmFtZXMiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICB2YXIgYXROYW1lcyA9IHRoaXMuX2F0TmFtZXM7CgogICAgICAgIGlmICghYXROYW1lcykgewogICAgICAgICAgYXROYW1lcyA9IHRoaXMuX2F0TmFtZXMgPSB0aGlzLl9uYW1lcy5tYXAodGhpcy50b0F0TmFtZSk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gYXROYW1lczsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJyZWZlcmVuY2VzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIHJlZmVyZW5jZXMgPSB0aGlzLl9yZWZlcmVuY2VzOwoKICAgICAgICBpZiAoIXJlZmVyZW5jZXMpIHsKICAgICAgICAgIHZhciBiYXNlID0gdGhpcy5iYXNlLAogICAgICAgICAgICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoLAogICAgICAgICAgICAgIHN0YWNrID0gdGhpcy5zdGFjazsKICAgICAgICAgIHJlZmVyZW5jZXMgPSB0aGlzLl9yZWZlcmVuY2VzID0gc3RhY2suc2xpY2VBcnJheShiYXNlLCBiYXNlICsgbGVuZ3RoKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiByZWZlcmVuY2VzOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gTmFtZWRBcmd1bWVudHM7CiAgfSgpOwoKICB2YXIgQ2FwdHVyZWROYW1lZEFyZ3VtZW50cyA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENhcHR1cmVkTmFtZWRBcmd1bWVudHModGFnLCBuYW1lcywgcmVmZXJlbmNlcykgewogICAgICB0aGlzLnRhZyA9IHRhZzsKICAgICAgdGhpcy5uYW1lcyA9IG5hbWVzOwogICAgICB0aGlzLnJlZmVyZW5jZXMgPSByZWZlcmVuY2VzOwogICAgICB0aGlzLmxlbmd0aCA9IG5hbWVzLmxlbmd0aDsKICAgICAgdGhpcy5fbWFwID0gbnVsbDsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjEgPSBDYXB0dXJlZE5hbWVkQXJndW1lbnRzLnByb3RvdHlwZTsKCiAgICBfcHJvdG82MS5oYXMgPSBmdW5jdGlvbiBoYXMobmFtZSkgewogICAgICByZXR1cm4gdGhpcy5uYW1lcy5pbmRleE9mKG5hbWUpICE9PSAtMTsKICAgIH07CgogICAgX3Byb3RvNjEuZ2V0ID0gZnVuY3Rpb24gZ2V0KG5hbWUpIHsKICAgICAgdmFyIG5hbWVzID0gdGhpcy5uYW1lcywKICAgICAgICAgIHJlZmVyZW5jZXMgPSB0aGlzLnJlZmVyZW5jZXM7CiAgICAgIHZhciBpZHggPSBuYW1lcy5pbmRleE9mKG5hbWUpOwoKICAgICAgaWYgKGlkeCA9PT0gLTEpIHsKICAgICAgICByZXR1cm4gVU5ERUZJTkVEX1JFRkVSRU5DRTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gcmVmZXJlbmNlc1tpZHhdOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzYxLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHZhciBuYW1lcyA9IHRoaXMubmFtZXMsCiAgICAgICAgICByZWZlcmVuY2VzID0gdGhpcy5yZWZlcmVuY2VzOwogICAgICB2YXIgb3V0ID0gKDAsIF91dGlsLmRpY3QpKCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIG5hbWUgPSBuYW1lc1tpXTsKICAgICAgICBvdXRbbmFtZV0gPSByZWZlcmVuY2VzW2ldLnZhbHVlKCk7CiAgICAgIH0KCiAgICAgIHJldHVybiBvdXQ7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoQ2FwdHVyZWROYW1lZEFyZ3VtZW50cywgW3sKICAgICAga2V5OiAibWFwIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIG1hcCA9IHRoaXMuX21hcDsKCiAgICAgICAgaWYgKCFtYXApIHsKICAgICAgICAgIHZhciBuYW1lcyA9IHRoaXMubmFtZXMsCiAgICAgICAgICAgICAgcmVmZXJlbmNlcyA9IHRoaXMucmVmZXJlbmNlczsKICAgICAgICAgIG1hcCA9IHRoaXMuX21hcCA9ICgwLCBfdXRpbC5kaWN0KSgpOwoKICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFtZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgdmFyIG5hbWUgPSBuYW1lc1tpXTsKICAgICAgICAgICAgbWFwW25hbWVdID0gcmVmZXJlbmNlc1tpXTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiBtYXA7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBDYXB0dXJlZE5hbWVkQXJndW1lbnRzOwogIH0oKTsKCiAgdmFyIEJsb2NrQXJndW1lbnRzID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gQmxvY2tBcmd1bWVudHMoKSB7CiAgICAgIHRoaXMuaW50ZXJuYWxWYWx1ZXMgPSBudWxsOwogICAgICB0aGlzLmludGVybmFsVGFnID0gbnVsbDsKICAgICAgdGhpcy5uYW1lcyA9IF91dGlsLkVNUFRZX0FSUkFZOwogICAgICB0aGlzLmxlbmd0aCA9IDA7CiAgICAgIHRoaXMuYmFzZSA9IDA7CiAgICB9CgogICAgdmFyIF9wcm90bzYyID0gQmxvY2tBcmd1bWVudHMucHJvdG90eXBlOwoKICAgIF9wcm90bzYyLmVtcHR5ID0gZnVuY3Rpb24gZW1wdHkoc3RhY2ssIGJhc2UpIHsKICAgICAgdGhpcy5zdGFjayA9IHN0YWNrOwogICAgICB0aGlzLm5hbWVzID0gX3V0aWwuRU1QVFlfQVJSQVk7CiAgICAgIHRoaXMuYmFzZSA9IGJhc2U7CiAgICAgIHRoaXMubGVuZ3RoID0gMDsKICAgICAgdGhpcy5pbnRlcm5hbFRhZyA9IF9yZWZlcmVuY2UyLkNPTlNUQU5UX1RBRzsKICAgICAgdGhpcy5pbnRlcm5hbFZhbHVlcyA9IF91dGlsLkVNUFRZX0FSUkFZOwogICAgfTsKCiAgICBfcHJvdG82Mi5zZXR1cCA9IGZ1bmN0aW9uIHNldHVwKHN0YWNrLCBiYXNlLCBsZW5ndGgsIG5hbWVzKSB7CiAgICAgIHRoaXMuc3RhY2sgPSBzdGFjazsKICAgICAgdGhpcy5uYW1lcyA9IG5hbWVzOwogICAgICB0aGlzLmJhc2UgPSBiYXNlOwogICAgICB0aGlzLmxlbmd0aCA9IGxlbmd0aDsKCiAgICAgIGlmIChsZW5ndGggPT09IDApIHsKICAgICAgICB0aGlzLmludGVybmFsVGFnID0gX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHOwogICAgICAgIHRoaXMuaW50ZXJuYWxWYWx1ZXMgPSBfdXRpbC5FTVBUWV9BUlJBWTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLmludGVybmFsVGFnID0gbnVsbDsKICAgICAgICB0aGlzLmludGVybmFsVmFsdWVzID0gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG82Mi5oYXMgPSBmdW5jdGlvbiBoYXMobmFtZSkgewogICAgICByZXR1cm4gdGhpcy5uYW1lcy5pbmRleE9mKG5hbWUpICE9PSAtMTsKICAgIH07CgogICAgX3Byb3RvNjIuZ2V0ID0gZnVuY3Rpb24gZ2V0KG5hbWUpIHsKICAgICAgdmFyIGJhc2UgPSB0aGlzLmJhc2UsCiAgICAgICAgICBzdGFjayA9IHRoaXMuc3RhY2ssCiAgICAgICAgICBuYW1lcyA9IHRoaXMubmFtZXM7CiAgICAgIHZhciBpZHggPSBuYW1lcy5pbmRleE9mKG5hbWUpOwoKICAgICAgaWYgKG5hbWVzLmluZGV4T2YobmFtZSkgPT09IC0xKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KCiAgICAgIHZhciB0YWJsZSA9IHN0YWNrLmdldChpZHggKiAzLCBiYXNlKTsKICAgICAgdmFyIHNjb3BlID0gc3RhY2suZ2V0KGlkeCAqIDMgKyAxLCBiYXNlKTsgLy8gRklYTUUobW11bik6IHNob3VsZG4ndCBuZWVkIHRvIGNhc3QgdGhpcwoKICAgICAgdmFyIGhhbmRsZSA9IHN0YWNrLmdldChpZHggKiAzICsgMiwgYmFzZSk7CiAgICAgIHJldHVybiBoYW5kbGUgPT09IG51bGwgPyBudWxsIDogW2hhbmRsZSwgc2NvcGUsIHRhYmxlXTsKICAgIH07CgogICAgX3Byb3RvNjIuY2FwdHVyZSA9IGZ1bmN0aW9uIGNhcHR1cmUoKSB7CiAgICAgIHJldHVybiBuZXcgQ2FwdHVyZWRCbG9ja0FyZ3VtZW50cyh0aGlzLm5hbWVzLCB0aGlzLnZhbHVlcyk7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoQmxvY2tBcmd1bWVudHMsIFt7CiAgICAgIGtleTogInZhbHVlcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciB2YWx1ZXMgPSB0aGlzLmludGVybmFsVmFsdWVzOwoKICAgICAgICBpZiAoIXZhbHVlcykgewogICAgICAgICAgdmFyIGJhc2UgPSB0aGlzLmJhc2UsCiAgICAgICAgICAgICAgbGVuZ3RoID0gdGhpcy5sZW5ndGgsCiAgICAgICAgICAgICAgc3RhY2sgPSB0aGlzLnN0YWNrOwogICAgICAgICAgdmFsdWVzID0gdGhpcy5pbnRlcm5hbFZhbHVlcyA9IHN0YWNrLnNsaWNlQXJyYXkoYmFzZSwgYmFzZSArIGxlbmd0aCAqIDMpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHZhbHVlczsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIEJsb2NrQXJndW1lbnRzOwogIH0oKTsKCiAgdmFyIENhcHR1cmVkQmxvY2tBcmd1bWVudHMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDYXB0dXJlZEJsb2NrQXJndW1lbnRzKG5hbWVzLCB2YWx1ZXMpIHsKICAgICAgdGhpcy5uYW1lcyA9IG5hbWVzOwogICAgICB0aGlzLnZhbHVlcyA9IHZhbHVlczsKICAgICAgdGhpcy5sZW5ndGggPSBuYW1lcy5sZW5ndGg7CiAgICB9CgogICAgdmFyIF9wcm90bzYzID0gQ2FwdHVyZWRCbG9ja0FyZ3VtZW50cy5wcm90b3R5cGU7CgogICAgX3Byb3RvNjMuaGFzID0gZnVuY3Rpb24gaGFzKG5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXMubmFtZXMuaW5kZXhPZihuYW1lKSAhPT0gLTE7CiAgICB9OwoKICAgIF9wcm90bzYzLmdldCA9IGZ1bmN0aW9uIGdldChuYW1lKSB7CiAgICAgIHZhciBpZHggPSB0aGlzLm5hbWVzLmluZGV4T2YobmFtZSk7CiAgICAgIGlmIChpZHggPT09IC0xKSByZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuIFt0aGlzLnZhbHVlc1tpZHggKiAzICsgMl0sIHRoaXMudmFsdWVzW2lkeCAqIDMgKyAxXSwgdGhpcy52YWx1ZXNbaWR4ICogM11dOwogICAgfTsKCiAgICByZXR1cm4gQ2FwdHVyZWRCbG9ja0FyZ3VtZW50czsKICB9KCk7CgogIHZhciBFTVBUWV9OQU1FRCA9IG5ldyBDYXB0dXJlZE5hbWVkQXJndW1lbnRzKF9yZWZlcmVuY2UyLkNPTlNUQU5UX1RBRywgX3V0aWwuRU1QVFlfQVJSQVksIF91dGlsLkVNUFRZX0FSUkFZKTsKICB2YXIgRU1QVFlfUE9TSVRJT05BTCA9IG5ldyBDYXB0dXJlZFBvc2l0aW9uYWxBcmd1bWVudHMoX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHLCBfdXRpbC5FTVBUWV9BUlJBWSk7CiAgdmFyIEVNUFRZX0FSR1MgPSBuZXcgQ2FwdHVyZWRBcmd1bWVudHMoX3JlZmVyZW5jZTIuQ09OU1RBTlRfVEFHLCBFTVBUWV9QT1NJVElPTkFMLCBFTVBUWV9OQU1FRCwgMCk7CiAgX2V4cG9ydHMuRU1QVFlfQVJHUyA9IEVNUFRZX0FSR1M7CgogIHZhciBWTSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFZNKHJ1bnRpbWUsIHNjb3BlLCBkeW5hbWljU2NvcGUsIGVsZW1lbnRTdGFjaykgewogICAgICB2YXIgX3RoaXMxOSA9IHRoaXM7CgogICAgICB0aGlzLnJ1bnRpbWUgPSBydW50aW1lOwogICAgICB0aGlzLmVsZW1lbnRTdGFjayA9IGVsZW1lbnRTdGFjazsKICAgICAgdGhpcy5keW5hbWljU2NvcGVTdGFjayA9IG5ldyBfdXRpbC5TdGFjaygpOwogICAgICB0aGlzLnNjb3BlU3RhY2sgPSBuZXcgX3V0aWwuU3RhY2soKTsKICAgICAgdGhpcy51cGRhdGluZ09wY29kZVN0YWNrID0gbmV3IF91dGlsLlN0YWNrKCk7CiAgICAgIHRoaXMuY2FjaGVHcm91cHMgPSBuZXcgX3V0aWwuU3RhY2soKTsKICAgICAgdGhpcy5saXN0QmxvY2tTdGFjayA9IG5ldyBfdXRpbC5TdGFjaygpOwogICAgICB0aGlzLnMwID0gbnVsbDsKICAgICAgdGhpcy5zMSA9IG51bGw7CiAgICAgIHRoaXMudDAgPSBudWxsOwogICAgICB0aGlzLnQxID0gbnVsbDsKICAgICAgdGhpcy52MCA9IG51bGw7CiAgICAgIHRoaXMuaGVhcCA9IHRoaXMucHJvZ3JhbS5oZWFwOwogICAgICB0aGlzLmNvbnN0YW50cyA9IHRoaXMucHJvZ3JhbS5jb25zdGFudHM7CiAgICAgIHRoaXMuZWxlbWVudFN0YWNrID0gZWxlbWVudFN0YWNrOwogICAgICB0aGlzLnNjb3BlU3RhY2sucHVzaChzY29wZSk7CiAgICAgIHRoaXMuZHluYW1pY1Njb3BlU3RhY2sucHVzaChkeW5hbWljU2NvcGUpOwogICAgICB0aGlzLmFyZ3MgPSBuZXcgQXJndW1lbnRzKCk7CiAgICAgIHRoaXMuaW5uZXIgPSBuZXcgTG93TGV2ZWxWTShFdmFsdWF0aW9uU3RhY2suZW1wdHkoKSwgdGhpcy5oZWFwLCBydW50aW1lLnByb2dyYW0sIHsKICAgICAgICBkZWJ1Z0JlZm9yZTogZnVuY3Rpb24gZGVidWdCZWZvcmUob3Bjb2RlKSB7CiAgICAgICAgICByZXR1cm4gQVBQRU5EX09QQ09ERVMuZGVidWdCZWZvcmUoX3RoaXMxOSwgb3Bjb2RlLCBvcGNvZGUudHlwZSk7CiAgICAgICAgfSwKICAgICAgICBkZWJ1Z0FmdGVyOiBmdW5jdGlvbiBkZWJ1Z0FmdGVyKG9wY29kZSwgc3RhdGUpIHsKICAgICAgICAgIEFQUEVORF9PUENPREVTLmRlYnVnQWZ0ZXIoX3RoaXMxOSwgb3Bjb2RlLCBvcGNvZGUudHlwZSwgc3RhdGUpOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CgogICAgdmFyIF9wcm90bzY0ID0gVk0ucHJvdG90eXBlOwoKICAgIC8vIEZldGNoIGEgdmFsdWUgZnJvbSBhIHJlZ2lzdGVyIG9udG8gdGhlIHN0YWNrCiAgICBfcHJvdG82NC5mZXRjaCA9IGZ1bmN0aW9uIGZldGNoKHJlZ2lzdGVyKSB7CiAgICAgIHRoaXMuc3RhY2sucHVzaCh0aGlzW192bTIuUmVnaXN0ZXJbcmVnaXN0ZXJdXSk7CiAgICB9IC8vIExvYWQgYSB2YWx1ZSBmcm9tIHRoZSBzdGFjayBpbnRvIGEgcmVnaXN0ZXIKICAgIDsKCiAgICBfcHJvdG82NC5sb2FkID0gZnVuY3Rpb24gbG9hZChyZWdpc3RlcikgewogICAgICB0aGlzW192bTIuUmVnaXN0ZXJbcmVnaXN0ZXJdXSA9IHRoaXMuc3RhY2sucG9wKCk7CiAgICB9IC8vIEZldGNoIGEgdmFsdWUgZnJvbSBhIHJlZ2lzdGVyCiAgICA7CgogICAgX3Byb3RvNjQuZmV0Y2hWYWx1ZSA9IGZ1bmN0aW9uIGZldGNoVmFsdWUocmVnaXN0ZXIpIHsKICAgICAgcmV0dXJuIHRoaXNbX3ZtMi5SZWdpc3RlcltyZWdpc3Rlcl1dOwogICAgfSAvLyBMb2FkIGEgdmFsdWUgaW50byBhIHJlZ2lzdGVyCiAgICA7CgogICAgX3Byb3RvNjQubG9hZFZhbHVlID0gZnVuY3Rpb24gbG9hZFZhbHVlKHJlZ2lzdGVyLCB2YWx1ZSQkMSkgewogICAgICB0aGlzW192bTIuUmVnaXN0ZXJbcmVnaXN0ZXJdXSA9IHZhbHVlJCQxOwogICAgfQogICAgLyoqCiAgICAgKiBNaWdyYXRlZCB0byBJbm5lcgogICAgICovCiAgICAvLyBTdGFydCBhIG5ldyBmcmFtZSBhbmQgc2F2ZSAkcmEgYW5kICRmcCBvbiB0aGUgc3RhY2sKICAgIDsKCiAgICBfcHJvdG82NC5wdXNoRnJhbWUgPSBmdW5jdGlvbiBwdXNoRnJhbWUoKSB7CiAgICAgIHRoaXMuaW5uZXIucHVzaEZyYW1lKCk7CiAgICB9IC8vIFJlc3RvcmUgJHJhLCAkc3AgYW5kICRmcAogICAgOwoKICAgIF9wcm90bzY0LnBvcEZyYW1lID0gZnVuY3Rpb24gcG9wRnJhbWUoKSB7CiAgICAgIHRoaXMuaW5uZXIucG9wRnJhbWUoKTsKICAgIH0gLy8gSnVtcCB0byBhbiBhZGRyZXNzIGluIGBwcm9ncmFtYAogICAgOwoKICAgIF9wcm90bzY0LmdvdG8gPSBmdW5jdGlvbiBnb3RvKG9mZnNldCkgewogICAgICB0aGlzLmlubmVyLmdvdG8ob2Zmc2V0KTsKICAgIH0gLy8gU2F2ZSAkcGMgaW50byAkcmEsIHRoZW4ganVtcCB0byBhIG5ldyBhZGRyZXNzIGluIGBwcm9ncmFtYCAoamFsIGluIE1JUFMpCiAgICA7CgogICAgX3Byb3RvNjQuY2FsbCA9IGZ1bmN0aW9uIGNhbGwoaGFuZGxlKSB7CiAgICAgIHRoaXMuaW5uZXIuY2FsbChoYW5kbGUpOwogICAgfSAvLyBQdXQgYSBzcGVjaWZpYyBgcHJvZ3JhbWAgYWRkcmVzcyBpbiAkcmEKICAgIDsKCiAgICBfcHJvdG82NC5yZXR1cm5UbyA9IGZ1bmN0aW9uIHJldHVyblRvKG9mZnNldCkgewogICAgICB0aGlzLmlubmVyLnJldHVyblRvKG9mZnNldCk7CiAgICB9IC8vIFJldHVybiB0byB0aGUgYHByb2dyYW1gIGFkZHJlc3Mgc3RvcmVkIGluICRyYQogICAgOwoKICAgIF9wcm90bzY0LnJldHVybiA9IGZ1bmN0aW9uIF9yZXR1cm4oKSB7CiAgICAgIHRoaXMuaW5uZXIucmV0dXJuKCk7CiAgICB9CiAgICAvKioKICAgICAqIEVuZCBvZiBtaWdyYXRlZC4KICAgICAqLwogICAgOwoKICAgIFZNLmluaXRpYWwgPSBmdW5jdGlvbiBpbml0aWFsKHByb2dyYW0sIGVudiwgc2VsZiwgZHluYW1pY1Njb3BlLCBlbGVtZW50U3RhY2ssIGhhbmRsZSkgewogICAgICB2YXIgc2NvcGVTaXplID0gcHJvZ3JhbS5oZWFwLnNjb3Blc2l6ZW9mKGhhbmRsZSk7CiAgICAgIHZhciBzY29wZSA9IFNjb3BlLnJvb3Qoc2VsZiwgc2NvcGVTaXplKTsKICAgICAgdmFyIHZtID0gbmV3IFZNKHsKICAgICAgICBwcm9ncmFtOiBwcm9ncmFtLAogICAgICAgIGVudjogZW52CiAgICAgIH0sIHNjb3BlLCBkeW5hbWljU2NvcGUsIGVsZW1lbnRTdGFjayk7CiAgICAgIHZtLnBjID0gdm0uaGVhcC5nZXRhZGRyKGhhbmRsZSk7CiAgICAgIHZtLnVwZGF0aW5nT3Bjb2RlU3RhY2sucHVzaChuZXcgX3V0aWwuTGlua2VkTGlzdCgpKTsKICAgICAgcmV0dXJuIHZtOwogICAgfTsKCiAgICBWTS5lbXB0eSA9IGZ1bmN0aW9uIGVtcHR5KHByb2dyYW0sIGVudiwgZWxlbWVudFN0YWNrLCBoYW5kbGUpIHsKICAgICAgdmFyIGR5bmFtaWNTY29wZSA9IHsKICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICAgIHJldHVybiBVTkRFRklORURfUkVGRVJFTkNFOwogICAgICAgIH0sCiAgICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoKSB7CiAgICAgICAgICByZXR1cm4gVU5ERUZJTkVEX1JFRkVSRU5DRTsKICAgICAgICB9LAogICAgICAgIGNoaWxkOiBmdW5jdGlvbiBjaGlsZCgpIHsKICAgICAgICAgIHJldHVybiBkeW5hbWljU2NvcGU7CiAgICAgICAgfQogICAgICB9OwogICAgICB2YXIgdm0gPSBuZXcgVk0oewogICAgICAgIHByb2dyYW06IHByb2dyYW0sCiAgICAgICAgZW52OiBlbnYKICAgICAgfSwgU2NvcGUucm9vdChVTkRFRklORURfUkVGRVJFTkNFLCAwKSwgZHluYW1pY1Njb3BlLCBlbGVtZW50U3RhY2spOwogICAgICB2bS51cGRhdGluZ09wY29kZVN0YWNrLnB1c2gobmV3IF91dGlsLkxpbmtlZExpc3QoKSk7CiAgICAgIHZtLnBjID0gdm0uaGVhcC5nZXRhZGRyKGhhbmRsZSk7CiAgICAgIHJldHVybiB2bTsKICAgIH07CgogICAgVk0ucmVzdW1lID0gZnVuY3Rpb24gcmVzdW1lKF9yZWY1OSwgcnVudGltZSwgc3RhY2spIHsKICAgICAgdmFyIHNjb3BlID0gX3JlZjU5LnNjb3BlLAogICAgICAgICAgZHluYW1pY1Njb3BlID0gX3JlZjU5LmR5bmFtaWNTY29wZTsKICAgICAgcmV0dXJuIG5ldyBWTShydW50aW1lLCBzY29wZSwgZHluYW1pY1Njb3BlLCBzdGFjayk7CiAgICB9OwoKICAgIF9wcm90bzY0LmNhcHR1cmUgPSBmdW5jdGlvbiBjYXB0dXJlKGFyZ3MpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBkeW5hbWljU2NvcGU6IHRoaXMuZHluYW1pY1Njb3BlKCksCiAgICAgICAgc2NvcGU6IHRoaXMuc2NvcGUoKSwKICAgICAgICBzdGFjazogdGhpcy5zdGFjay5jYXB0dXJlKGFyZ3MpCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90bzY0LmJlZ2luQ2FjaGVHcm91cCA9IGZ1bmN0aW9uIGJlZ2luQ2FjaGVHcm91cCgpIHsKICAgICAgdGhpcy5jYWNoZUdyb3Vwcy5wdXNoKHRoaXMudXBkYXRpbmcoKS50YWlsKCkpOwogICAgfTsKCiAgICBfcHJvdG82NC5jb21taXRDYWNoZUdyb3VwID0gZnVuY3Rpb24gY29tbWl0Q2FjaGVHcm91cCgpIHsKICAgICAgLy8gICAgICAgIEp1bXBJZk5vdE1vZGlmaWVkKEVORCkKICAgICAgLy8gICAgICAgIChoZWFkKQogICAgICAvLyAgICAgICAgKC4uLi4pCiAgICAgIC8vICAgICAgICAodGFpbCkKICAgICAgLy8gICAgICAgIERpZE1vZGlmeQogICAgICAvLyBFTkQ6ICAgTm9vcAogICAgICB2YXIgRU5EID0gbmV3IExhYmVsT3Bjb2RlKCdFTkQnKTsKICAgICAgdmFyIG9wY29kZXMgPSB0aGlzLnVwZGF0aW5nKCk7CiAgICAgIHZhciBtYXJrZXIgPSB0aGlzLmNhY2hlR3JvdXBzLnBvcCgpOwogICAgICB2YXIgaGVhZCA9IG1hcmtlciA/IG9wY29kZXMubmV4dE5vZGUobWFya2VyKSA6IG9wY29kZXMuaGVhZCgpOwogICAgICB2YXIgdGFpbCA9IG9wY29kZXMudGFpbCgpOwogICAgICB2YXIgdGFnID0gKDAsIF9yZWZlcmVuY2UyLmNvbWJpbmVTbGljZSkobmV3IF91dGlsLkxpc3RTbGljZShoZWFkLCB0YWlsKSk7CiAgICAgIHZhciBndWFyZCA9IG5ldyBKdW1wSWZOb3RNb2RpZmllZE9wY29kZSh0YWcsIEVORCk7CiAgICAgIG9wY29kZXMuaW5zZXJ0QmVmb3JlKGd1YXJkLCBoZWFkKTsKICAgICAgb3Bjb2Rlcy5hcHBlbmQobmV3IERpZE1vZGlmeU9wY29kZShndWFyZCkpOwogICAgICBvcGNvZGVzLmFwcGVuZChFTkQpOwogICAgfTsKCiAgICBfcHJvdG82NC5lbnRlciA9IGZ1bmN0aW9uIGVudGVyKGFyZ3MpIHsKICAgICAgdmFyIHVwZGF0aW5nID0gbmV3IF91dGlsLkxpbmtlZExpc3QoKTsKICAgICAgdmFyIHN0YXRlID0gdGhpcy5jYXB0dXJlKGFyZ3MpOwogICAgICB2YXIgdHJhY2tlciA9IHRoaXMuZWxlbWVudHMoKS5wdXNoVXBkYXRhYmxlQmxvY2soKTsKICAgICAgdmFyIHRyeU9wY29kZSA9IG5ldyBUcnlPcGNvZGUodGhpcy5oZWFwLmdldGhhbmRsZSh0aGlzLnBjKSwgc3RhdGUsIHRoaXMucnVudGltZSwgdHJhY2tlciwgdXBkYXRpbmcpOwogICAgICB0aGlzLmRpZEVudGVyKHRyeU9wY29kZSk7CiAgICB9OwoKICAgIF9wcm90bzY0Lml0ZXJhdGUgPSBmdW5jdGlvbiBpdGVyYXRlKG1lbW8sIHZhbHVlJCQxKSB7CiAgICAgIHZhciBzdGFjayA9IHRoaXMuc3RhY2s7CiAgICAgIHN0YWNrLnB1c2godmFsdWUkJDEpOwogICAgICBzdGFjay5wdXNoKG1lbW8pOwogICAgICB2YXIgc3RhdGUgPSB0aGlzLmNhcHR1cmUoMik7CiAgICAgIHZhciB0cmFja2VyID0gdGhpcy5lbGVtZW50cygpLnB1c2hVcGRhdGFibGVCbG9jaygpOyAvLyBsZXQgaXAgPSB0aGlzLmlwOwogICAgICAvLyB0aGlzLmlwID0gZW5kICsgNDsKICAgICAgLy8gdGhpcy5mcmFtZXMucHVzaChpcCk7CgogICAgICByZXR1cm4gbmV3IFRyeU9wY29kZSh0aGlzLmhlYXAuZ2V0aGFuZGxlKHRoaXMucGMpLCBzdGF0ZSwgdGhpcy5ydW50aW1lLCB0cmFja2VyLCBuZXcgX3V0aWwuTGlua2VkTGlzdCgpKTsKICAgIH07CgogICAgX3Byb3RvNjQuZW50ZXJJdGVtID0gZnVuY3Rpb24gZW50ZXJJdGVtKGtleSwgb3Bjb2RlKSB7CiAgICAgIHRoaXMubGlzdEJsb2NrKCkubWFwW2tleV0gPSBvcGNvZGU7CiAgICAgIHRoaXMuZGlkRW50ZXIob3Bjb2RlKTsKICAgIH07CgogICAgX3Byb3RvNjQuZW50ZXJMaXN0ID0gZnVuY3Rpb24gZW50ZXJMaXN0KHJlbGF0aXZlU3RhcnQpIHsKICAgICAgdmFyIHVwZGF0aW5nID0gbmV3IF91dGlsLkxpbmtlZExpc3QoKTsKICAgICAgdmFyIHN0YXRlID0gdGhpcy5jYXB0dXJlKDApOwogICAgICB2YXIgdHJhY2tlciA9IHRoaXMuZWxlbWVudHMoKS5wdXNoQmxvY2tMaXN0KHVwZGF0aW5nKTsKICAgICAgdmFyIGFydGlmYWN0cyA9IHRoaXMuc3RhY2sucGVlaygpLmFydGlmYWN0czsKICAgICAgdmFyIGFkZHIgPSB0aGlzLnBjICsgcmVsYXRpdmVTdGFydCAtIHRoaXMuY3VycmVudE9wU2l6ZTsKICAgICAgdmFyIHN0YXJ0ID0gdGhpcy5oZWFwLmdldGhhbmRsZShhZGRyKTsKICAgICAgdmFyIG9wY29kZSA9IG5ldyBMaXN0QmxvY2tPcGNvZGUoc3RhcnQsIHN0YXRlLCB0aGlzLnJ1bnRpbWUsIHRyYWNrZXIsIHVwZGF0aW5nLCBhcnRpZmFjdHMpOwogICAgICB0aGlzLmxpc3RCbG9ja1N0YWNrLnB1c2gob3Bjb2RlKTsKICAgICAgdGhpcy5kaWRFbnRlcihvcGNvZGUpOwogICAgfTsKCiAgICBfcHJvdG82NC5kaWRFbnRlciA9IGZ1bmN0aW9uIGRpZEVudGVyKG9wY29kZSkgewogICAgICB0aGlzLnVwZGF0ZVdpdGgob3Bjb2RlKTsKICAgICAgdGhpcy51cGRhdGluZ09wY29kZVN0YWNrLnB1c2gob3Bjb2RlLmNoaWxkcmVuKTsKICAgIH07CgogICAgX3Byb3RvNjQuZXhpdCA9IGZ1bmN0aW9uIGV4aXQoKSB7CiAgICAgIHRoaXMuZWxlbWVudHMoKS5wb3BCbG9jaygpOwogICAgICB0aGlzLnVwZGF0aW5nT3Bjb2RlU3RhY2sucG9wKCk7CiAgICAgIHZhciBwYXJlbnQgPSB0aGlzLnVwZGF0aW5nKCkudGFpbCgpOwogICAgICBwYXJlbnQuZGlkSW5pdGlhbGl6ZUNoaWxkcmVuKCk7CiAgICB9OwoKICAgIF9wcm90bzY0LmV4aXRMaXN0ID0gZnVuY3Rpb24gZXhpdExpc3QoKSB7CiAgICAgIHRoaXMuZXhpdCgpOwogICAgICB0aGlzLmxpc3RCbG9ja1N0YWNrLnBvcCgpOwogICAgfTsKCiAgICBfcHJvdG82NC51cGRhdGVXaXRoID0gZnVuY3Rpb24gdXBkYXRlV2l0aChvcGNvZGUpIHsKICAgICAgdGhpcy51cGRhdGluZygpLmFwcGVuZChvcGNvZGUpOwogICAgfTsKCiAgICBfcHJvdG82NC5saXN0QmxvY2sgPSBmdW5jdGlvbiBsaXN0QmxvY2soKSB7CiAgICAgIHJldHVybiB0aGlzLmxpc3RCbG9ja1N0YWNrLmN1cnJlbnQ7CiAgICB9OwoKICAgIF9wcm90bzY0LnVwZGF0aW5nID0gZnVuY3Rpb24gdXBkYXRpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLnVwZGF0aW5nT3Bjb2RlU3RhY2suY3VycmVudDsKICAgIH07CgogICAgX3Byb3RvNjQuZWxlbWVudHMgPSBmdW5jdGlvbiBlbGVtZW50cygpIHsKICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudFN0YWNrOwogICAgfTsKCiAgICBfcHJvdG82NC5zY29wZSA9IGZ1bmN0aW9uIHNjb3BlKCkgewogICAgICByZXR1cm4gdGhpcy5zY29wZVN0YWNrLmN1cnJlbnQ7CiAgICB9OwoKICAgIF9wcm90bzY0LmR5bmFtaWNTY29wZSA9IGZ1bmN0aW9uIGR5bmFtaWNTY29wZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZHluYW1pY1Njb3BlU3RhY2suY3VycmVudDsKICAgIH07CgogICAgX3Byb3RvNjQucHVzaENoaWxkU2NvcGUgPSBmdW5jdGlvbiBwdXNoQ2hpbGRTY29wZSgpIHsKICAgICAgdGhpcy5zY29wZVN0YWNrLnB1c2godGhpcy5zY29wZSgpLmNoaWxkKCkpOwogICAgfTsKCiAgICBfcHJvdG82NC5wdXNoRHluYW1pY1Njb3BlID0gZnVuY3Rpb24gcHVzaER5bmFtaWNTY29wZSgpIHsKICAgICAgdmFyIGNoaWxkID0gdGhpcy5keW5hbWljU2NvcGUoKS5jaGlsZCgpOwogICAgICB0aGlzLmR5bmFtaWNTY29wZVN0YWNrLnB1c2goY2hpbGQpOwogICAgICByZXR1cm4gY2hpbGQ7CiAgICB9OwoKICAgIF9wcm90bzY0LnB1c2hSb290U2NvcGUgPSBmdW5jdGlvbiBwdXNoUm9vdFNjb3BlKHNpemUsIGJpbmRDYWxsZXIpIHsKICAgICAgdmFyIHNjb3BlID0gU2NvcGUuc2l6ZWQoc2l6ZSk7CiAgICAgIGlmIChiaW5kQ2FsbGVyKSBzY29wZS5iaW5kQ2FsbGVyU2NvcGUodGhpcy5zY29wZSgpKTsKICAgICAgdGhpcy5zY29wZVN0YWNrLnB1c2goc2NvcGUpOwogICAgICByZXR1cm4gc2NvcGU7CiAgICB9OwoKICAgIF9wcm90bzY0LnB1c2hTY29wZSA9IGZ1bmN0aW9uIHB1c2hTY29wZShzY29wZSkgewogICAgICB0aGlzLnNjb3BlU3RhY2sucHVzaChzY29wZSk7CiAgICB9OwoKICAgIF9wcm90bzY0LnBvcFNjb3BlID0gZnVuY3Rpb24gcG9wU2NvcGUoKSB7CiAgICAgIHRoaXMuc2NvcGVTdGFjay5wb3AoKTsKICAgIH07CgogICAgX3Byb3RvNjQucG9wRHluYW1pY1Njb3BlID0gZnVuY3Rpb24gcG9wRHluYW1pY1Njb3BlKCkgewogICAgICB0aGlzLmR5bmFtaWNTY29wZVN0YWNrLnBvcCgpOwogICAgfTsKCiAgICBfcHJvdG82NC5uZXdEZXN0cm95YWJsZSA9IGZ1bmN0aW9uIG5ld0Rlc3Ryb3lhYmxlKGQpIHsKICAgICAgdGhpcy5lbGVtZW50cygpLmRpZEFkZERlc3Ryb3lhYmxlKGQpOwogICAgfSAvLy8gU0NPUEUgSEVMUEVSUwogICAgOwoKICAgIF9wcm90bzY0LmdldFNlbGYgPSBmdW5jdGlvbiBnZXRTZWxmKCkgewogICAgICByZXR1cm4gdGhpcy5zY29wZSgpLmdldFNlbGYoKTsKICAgIH07CgogICAgX3Byb3RvNjQucmVmZXJlbmNlRm9yU3ltYm9sID0gZnVuY3Rpb24gcmVmZXJlbmNlRm9yU3ltYm9sKHN5bWJvbCkgewogICAgICByZXR1cm4gdGhpcy5zY29wZSgpLmdldFN5bWJvbChzeW1ib2wpOwogICAgfSAvLy8gRVhFQ1VUSU9OCiAgICA7CgogICAgX3Byb3RvNjQuZXhlY3V0ZSA9IGZ1bmN0aW9uIGV4ZWN1dGUoc3RhcnQsIGluaXRpYWxpemUpIHsKICAgICAgdGhpcy5wYyA9IHRoaXMuaGVhcC5nZXRhZGRyKHN0YXJ0KTsKICAgICAgaWYgKGluaXRpYWxpemUpIGluaXRpYWxpemUodGhpcyk7CiAgICAgIHZhciByZXN1bHQ7CgogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgIHJlc3VsdCA9IHRoaXMubmV4dCgpOwogICAgICAgIGlmIChyZXN1bHQuZG9uZSkgYnJlYWs7CiAgICAgIH0KCiAgICAgIHJldHVybiByZXN1bHQudmFsdWU7CiAgICB9OwoKICAgIF9wcm90bzY0Lm5leHQgPSBmdW5jdGlvbiBuZXh0KCkgewogICAgICB2YXIgZW52ID0gdGhpcy5lbnYsCiAgICAgICAgICBwcm9ncmFtID0gdGhpcy5wcm9ncmFtLAogICAgICAgICAgdXBkYXRpbmdPcGNvZGVTdGFjayA9IHRoaXMudXBkYXRpbmdPcGNvZGVTdGFjaywKICAgICAgICAgIGVsZW1lbnRTdGFjayA9IHRoaXMuZWxlbWVudFN0YWNrOwogICAgICB2YXIgb3Bjb2RlID0gdGhpcy5pbm5lci5uZXh0U3RhdGVtZW50KCk7CiAgICAgIHZhciByZXN1bHQ7CgogICAgICBpZiAob3Bjb2RlICE9PSBudWxsKSB7CiAgICAgICAgdGhpcy5pbm5lci5ldmFsdWF0ZU91dGVyKG9wY29kZSwgdGhpcyk7CiAgICAgICAgcmVzdWx0ID0gewogICAgICAgICAgZG9uZTogZmFsc2UsCiAgICAgICAgICB2YWx1ZTogbnVsbAogICAgICAgIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gVW5sb2FkIHRoZSBzdGFjawogICAgICAgIHRoaXMuc3RhY2sucmVzZXQoKTsKICAgICAgICByZXN1bHQgPSB7CiAgICAgICAgICBkb25lOiB0cnVlLAogICAgICAgICAgdmFsdWU6IG5ldyBSZW5kZXJSZXN1bHQoZW52LCBwcm9ncmFtLCB1cGRhdGluZ09wY29kZVN0YWNrLnBvcCgpLCBlbGVtZW50U3RhY2sucG9wQmxvY2soKSkKICAgICAgICB9OwogICAgICB9CgogICAgICByZXR1cm4gcmVzdWx0OwogICAgfTsKCiAgICBfcHJvdG82NC5iaW5kRHluYW1pY1Njb3BlID0gZnVuY3Rpb24gYmluZER5bmFtaWNTY29wZShuYW1lcykgewogICAgICB2YXIgc2NvcGUgPSB0aGlzLmR5bmFtaWNTY29wZSgpOwoKICAgICAgZm9yICh2YXIgaSA9IG5hbWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgdmFyIG5hbWUgPSB0aGlzLmNvbnN0YW50cy5nZXRTdHJpbmcobmFtZXNbaV0pOwogICAgICAgIHNjb3BlLnNldChuYW1lLCB0aGlzLnN0YWNrLnBvcCgpKTsKICAgICAgfQogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKFZNLCBbewogICAgICBrZXk6ICJzdGFjayIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmlubmVyLnN0YWNrOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSQkMSkgewogICAgICAgIHRoaXMuaW5uZXIuc3RhY2sgPSB2YWx1ZSQkMTsKICAgICAgfQogICAgICAvKiBSZWdpc3RlcnMgKi8KCiAgICB9LCB7CiAgICAgIGtleTogImN1cnJlbnRPcFNpemUiLAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSQkMSkgewogICAgICAgIHRoaXMuaW5uZXIuY3VycmVudE9wU2l6ZSA9IHZhbHVlJCQxOwogICAgICB9LAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5pbm5lci5jdXJyZW50T3BTaXplOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInBjIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW5uZXIucGM7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHZhbHVlJCQxKSB7CiAgICAgICAgdGhpcy5pbm5lci5wYyA9IHZhbHVlJCQxOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInJhIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW5uZXIucmE7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHZhbHVlJCQxKSB7CiAgICAgICAgdGhpcy5pbm5lci5yYSA9IHZhbHVlJCQxOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImZwIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuc3RhY2suZnA7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KGZwKSB7CiAgICAgICAgdGhpcy5zdGFjay5mcCA9IGZwOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInNwIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuc3RhY2suc3A7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHNwKSB7CiAgICAgICAgdGhpcy5zdGFjay5zcCA9IHNwOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInByb2dyYW0iLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5ydW50aW1lLnByb2dyYW07CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiZW52IiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMucnVudGltZS5lbnY7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBWTTsKICB9KCk7CgogIF9leHBvcnRzLkxvd0xldmVsVk0gPSBWTTsKCiAgdmFyIFRlbXBsYXRlSXRlcmF0b3JJbXBsID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gVGVtcGxhdGVJdGVyYXRvckltcGwodm0pIHsKICAgICAgdGhpcy52bSA9IHZtOwogICAgfQoKICAgIHZhciBfcHJvdG82NSA9IFRlbXBsYXRlSXRlcmF0b3JJbXBsLnByb3RvdHlwZTsKCiAgICBfcHJvdG82NS5uZXh0ID0gZnVuY3Rpb24gbmV4dCgpIHsKICAgICAgcmV0dXJuIHRoaXMudm0ubmV4dCgpOwogICAgfTsKCiAgICByZXR1cm4gVGVtcGxhdGVJdGVyYXRvckltcGw7CiAgfSgpOwoKICBmdW5jdGlvbiByZW5kZXJNYWluKHByb2dyYW0sIGVudiwgc2VsZiwgZHluYW1pY1Njb3BlLCBidWlsZGVyLCBoYW5kbGUpIHsKICAgIHZhciB2bSA9IFZNLmluaXRpYWwocHJvZ3JhbSwgZW52LCBzZWxmLCBkeW5hbWljU2NvcGUsIGJ1aWxkZXIsIGhhbmRsZSk7CiAgICByZXR1cm4gbmV3IFRlbXBsYXRlSXRlcmF0b3JJbXBsKHZtKTsKICB9CiAgLyoqCiAgICogUmV0dXJucyBhIFRlbXBsYXRlSXRlcmF0b3IgY29uZmlndXJlZCB0byByZW5kZXIgYSByb290IGNvbXBvbmVudC4KICAgKi8KCgogIGZ1bmN0aW9uIHJlbmRlckNvbXBvbmVudChwcm9ncmFtLCBlbnYsIGJ1aWxkZXIsIG1haW4sIG5hbWUsIGFyZ3MpIHsKICAgIGlmIChhcmdzID09PSB2b2lkIDApIHsKICAgICAgYXJncyA9IHt9OwogICAgfQoKICAgIHZhciB2bSA9IFZNLmVtcHR5KHByb2dyYW0sIGVudiwgYnVpbGRlciwgbWFpbik7CiAgICB2YXIgcmVzb2x2ZXIgPSB2bS5jb25zdGFudHMucmVzb2x2ZXI7CiAgICB2YXIgZGVmaW5pdGlvbiA9IHJlc29sdmVDb21wb25lbnQocmVzb2x2ZXIsIG5hbWUsIG51bGwpOwogICAgdmFyIG1hbmFnZXIgPSBkZWZpbml0aW9uLm1hbmFnZXIsCiAgICAgICAgc3RhdGUgPSBkZWZpbml0aW9uLnN0YXRlOwogICAgdmFyIGNhcGFiaWxpdGllcyA9IGNhcGFiaWxpdHlGbGFnc0Zyb20obWFuYWdlci5nZXRDYXBhYmlsaXRpZXMoc3RhdGUpKTsKICAgIHZhciBpbnZvY2F0aW9uOwoKICAgIGlmIChoYXNTdGF0aWNMYXlvdXRDYXBhYmlsaXR5KGNhcGFiaWxpdGllcywgbWFuYWdlcikpIHsKICAgICAgaW52b2NhdGlvbiA9IG1hbmFnZXIuZ2V0TGF5b3V0KHN0YXRlLCByZXNvbHZlcik7CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBpbnZva2UgY29tcG9uZW50cyB3aXRoIGR5bmFtaWMgbGF5b3V0cyBhcyBhIHJvb3QgY29tcG9uZW50LicpOwogICAgfSAvLyBHZXQgYSBsaXN0IG9mIHR1cGxlcyBvZiBhcmd1bWVudCBuYW1lcyBhbmQgcmVmZXJlbmNlcywgbGlrZQogICAgLy8gW1sndGl0bGUnLCByZWZlcmVuY2VdLCBbJ25hbWUnLCByZWZlcmVuY2VdXQoKCiAgICB2YXIgYXJnTGlzdCA9IE9iamVjdC5rZXlzKGFyZ3MpLm1hcChmdW5jdGlvbiAoa2V5KSB7CiAgICAgIHJldHVybiBba2V5LCBhcmdzW2tleV1dOwogICAgfSk7CiAgICB2YXIgYmxvY2tOYW1lcyA9IFsnbWFpbicsICdlbHNlJywgJ2F0dHJzJ107IC8vIFByZWZpeCBhcmd1bWVudCBuYW1lcyB3aXRoIGBAYCBzeW1ib2wKCiAgICB2YXIgYXJnTmFtZXMgPSBhcmdMaXN0Lm1hcChmdW5jdGlvbiAoX3JlZjYwKSB7CiAgICAgIHZhciBuYW1lID0gX3JlZjYwWzBdOwogICAgICByZXR1cm4gIkAiICsgbmFtZTsKICAgIH0pOwogICAgdm0ucHVzaEZyYW1lKCk7IC8vIFB1c2ggYmxvY2tzIG9uIHRvIHRoZSBzdGFjaywgdGhyZWUgc3RhY2sgdmFsdWVzIHBlciBibG9jawoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMyAqIGJsb2NrTmFtZXMubGVuZ3RoOyBpKyspIHsKICAgICAgdm0uc3RhY2sucHVzaChudWxsKTsKICAgIH0KCiAgICB2bS5zdGFjay5wdXNoKG51bGwpOyAvLyBGb3IgZWFjaCBhcmd1bWVudCwgcHVzaCBpdHMgYmFja2luZyByZWZlcmVuY2Ugb24gdG8gdGhlIHN0YWNrCgogICAgYXJnTGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChfcmVmNjEpIHsKICAgICAgdmFyIHJlZmVyZW5jZSA9IF9yZWY2MVsxXTsKICAgICAgdm0uc3RhY2sucHVzaChyZWZlcmVuY2UpOwogICAgfSk7IC8vIENvbmZpZ3VyZSBWTSBiYXNlZCBvbiBibG9ja3MgYW5kIGFyZ3MganVzdCBwdXNoZWQgb24gdG8gdGhlIHN0YWNrLgoKICAgIHZtLmFyZ3Muc2V0dXAodm0uc3RhY2ssIGFyZ05hbWVzLCBibG9ja05hbWVzLCAwLCBmYWxzZSk7IC8vIE5lZWRlZCBmb3IgdGhlIE9wLk1haW4gb3Bjb2RlOiBhcmd1bWVudHMsIGNvbXBvbmVudCBpbnZvY2F0aW9uIG9iamVjdCwgYW5kCiAgICAvLyBjb21wb25lbnQgZGVmaW5pdGlvbi4KCiAgICB2bS5zdGFjay5wdXNoKHZtLmFyZ3MpOwogICAgdm0uc3RhY2sucHVzaChpbnZvY2F0aW9uKTsKICAgIHZtLnN0YWNrLnB1c2goZGVmaW5pdGlvbik7CiAgICByZXR1cm4gbmV3IFRlbXBsYXRlSXRlcmF0b3JJbXBsKHZtKTsKICB9CgogIHZhciBEeW5hbWljVmFyUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRHluYW1pY1ZhclJlZmVyZW5jZShzY29wZSwgbmFtZVJlZikgewogICAgICB0aGlzLnNjb3BlID0gc2NvcGU7CiAgICAgIHRoaXMubmFtZVJlZiA9IG5hbWVSZWY7CiAgICAgIHZhciB2YXJUYWcgPSB0aGlzLnZhclRhZyA9ICgwLCBfcmVmZXJlbmNlMi5jcmVhdGVVcGRhdGFibGVUYWcpKCk7CiAgICAgIHRoaXMudGFnID0gKDAsIF9yZWZlcmVuY2UyLmNvbWJpbmUpKFtuYW1lUmVmLnRhZywgdmFyVGFnXSk7CiAgICB9CgogICAgdmFyIF9wcm90bzY2ID0gRHluYW1pY1ZhclJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvNjYudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuZ2V0VmFyKCkudmFsdWUoKTsKICAgIH07CgogICAgX3Byb3RvNjYuZ2V0ID0gZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICByZXR1cm4gdGhpcy5nZXRWYXIoKS5nZXQoa2V5KTsKICAgIH07CgogICAgX3Byb3RvNjYuZ2V0VmFyID0gZnVuY3Rpb24gZ2V0VmFyKCkgewogICAgICB2YXIgbmFtZSA9IFN0cmluZyh0aGlzLm5hbWVSZWYudmFsdWUoKSk7CiAgICAgIHZhciByZWYgPSB0aGlzLnNjb3BlLmdldChuYW1lKTsKICAgICAgKDAsIF9yZWZlcmVuY2UyLnVwZGF0ZSkodGhpcy52YXJUYWcsIHJlZi50YWcpOwogICAgICByZXR1cm4gcmVmOwogICAgfTsKCiAgICByZXR1cm4gRHluYW1pY1ZhclJlZmVyZW5jZTsKICB9KCk7CgogIGZ1bmN0aW9uIGdldER5bmFtaWNWYXIodm0sIGFyZ3MpIHsKICAgIHZhciBzY29wZSA9IHZtLmR5bmFtaWNTY29wZSgpOwogICAgdmFyIG5hbWVSZWYgPSBhcmdzLnBvc2l0aW9uYWwuYXQoMCk7CiAgICByZXR1cm4gbmV3IER5bmFtaWNWYXJSZWZlcmVuY2Uoc2NvcGUsIG5hbWVSZWYpOwogIH0KICAvKiogQGludGVybmFsICovCgoKICB2YXIgREVGQVVMVF9DQVBBQklMSVRJRVMgPSB7CiAgICBkeW5hbWljTGF5b3V0OiB0cnVlLAogICAgZHluYW1pY1RhZzogdHJ1ZSwKICAgIHByZXBhcmVBcmdzOiB0cnVlLAogICAgY3JlYXRlQXJnczogdHJ1ZSwKICAgIGF0dHJpYnV0ZUhvb2s6IGZhbHNlLAogICAgZWxlbWVudEhvb2s6IGZhbHNlLAogICAgZHluYW1pY1Njb3BlOiB0cnVlLAogICAgY3JlYXRlQ2FsbGVyOiBmYWxzZSwKICAgIHVwZGF0ZUhvb2s6IHRydWUsCiAgICBjcmVhdGVJbnN0YW5jZTogdHJ1ZQogIH07CiAgX2V4cG9ydHMuREVGQVVMVF9DQVBBQklMSVRJRVMgPSBERUZBVUxUX0NBUEFCSUxJVElFUzsKICB2YXIgTUlOSU1BTF9DQVBBQklMSVRJRVMgPSB7CiAgICBkeW5hbWljTGF5b3V0OiBmYWxzZSwKICAgIGR5bmFtaWNUYWc6IGZhbHNlLAogICAgcHJlcGFyZUFyZ3M6IGZhbHNlLAogICAgY3JlYXRlQXJnczogZmFsc2UsCiAgICBhdHRyaWJ1dGVIb29rOiBmYWxzZSwKICAgIGVsZW1lbnRIb29rOiBmYWxzZSwKICAgIGR5bmFtaWNTY29wZTogZmFsc2UsCiAgICBjcmVhdGVDYWxsZXI6IGZhbHNlLAogICAgdXBkYXRlSG9vazogZmFsc2UsCiAgICBjcmVhdGVJbnN0YW5jZTogZmFsc2UKICB9OwogIF9leHBvcnRzLk1JTklNQUxfQ0FQQUJJTElUSUVTID0gTUlOSU1BTF9DQVBBQklMSVRJRVM7CiAgdmFyIFNFUklBTElaQVRJT05fRklSU1RfTk9ERV9TVFJJTkcgPSAnJStiOjAlJzsKICBfZXhwb3J0cy5TRVJJQUxJWkFUSU9OX0ZJUlNUX05PREVfU1RSSU5HID0gU0VSSUFMSVpBVElPTl9GSVJTVF9OT0RFX1NUUklORzsKCiAgZnVuY3Rpb24gaXNTZXJpYWxpemF0aW9uRmlyc3ROb2RlKG5vZGUpIHsKICAgIHJldHVybiBub2RlLm5vZGVWYWx1ZSA9PT0gU0VSSUFMSVpBVElPTl9GSVJTVF9OT0RFX1NUUklORzsKICB9CgogIHZhciBSZWh5ZHJhdGluZ0N1cnNvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfQ3Vyc29yKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUmVoeWRyYXRpbmdDdXJzb3IsIF9DdXJzb3IpOwoKICAgIGZ1bmN0aW9uIFJlaHlkcmF0aW5nQ3Vyc29yKGVsZW1lbnQsIG5leHRTaWJsaW5nLCBzdGFydGluZ0Jsb2NrRGVwdGgpIHsKICAgICAgdmFyIF90aGlzMjA7CgogICAgICBfdGhpczIwID0gX0N1cnNvci5jYWxsKHRoaXMsIGVsZW1lbnQsIG5leHRTaWJsaW5nKSB8fCB0aGlzOwogICAgICBfdGhpczIwLnN0YXJ0aW5nQmxvY2tEZXB0aCA9IHN0YXJ0aW5nQmxvY2tEZXB0aDsKICAgICAgX3RoaXMyMC5jYW5kaWRhdGUgPSBudWxsOwogICAgICBfdGhpczIwLmluamVjdGVkT21pdHRlZE5vZGUgPSBmYWxzZTsKICAgICAgX3RoaXMyMC5vcGVuQmxvY2tEZXB0aCA9IHN0YXJ0aW5nQmxvY2tEZXB0aCAtIDE7CiAgICAgIHJldHVybiBfdGhpczIwOwogICAgfQoKICAgIHJldHVybiBSZWh5ZHJhdGluZ0N1cnNvcjsKICB9KEN1cnNvcik7CgogIHZhciBSZWh5ZHJhdGVCdWlsZGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9OZXdFbGVtZW50QnVpbGRlcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFJlaHlkcmF0ZUJ1aWxkZXIsIF9OZXdFbGVtZW50QnVpbGRlcik7CgogICAgLy8gcHJpdmF0ZSBjYW5kaWRhdGU6IE9wdGlvbjxTaW1wbGUuTm9kZT4gPSBudWxsOwogICAgZnVuY3Rpb24gUmVoeWRyYXRlQnVpbGRlcihlbnYsIHBhcmVudE5vZGUsIG5leHRTaWJsaW5nKSB7CiAgICAgIHZhciBfdGhpczIxOwoKICAgICAgX3RoaXMyMSA9IF9OZXdFbGVtZW50QnVpbGRlci5jYWxsKHRoaXMsIGVudiwgcGFyZW50Tm9kZSwgbmV4dFNpYmxpbmcpIHx8IHRoaXM7CiAgICAgIF90aGlzMjEudW5tYXRjaGVkQXR0cmlidXRlcyA9IG51bGw7CiAgICAgIF90aGlzMjEuYmxvY2tEZXB0aCA9IDA7CiAgICAgIGlmIChuZXh0U2libGluZykgdGhyb3cgbmV3IEVycm9yKCdSZWh5ZHJhdGlvbiB3aXRoIG5leHRTaWJsaW5nIG5vdCBzdXBwb3J0ZWQnKTsKICAgICAgdmFyIG5vZGUgPSBfdGhpczIxLmN1cnJlbnRDdXJzb3IuZWxlbWVudC5maXJzdENoaWxkOwoKICAgICAgd2hpbGUgKG5vZGUgIT09IG51bGwpIHsKICAgICAgICBpZiAoaXNDb21tZW50KG5vZGUpICYmIGlzU2VyaWFsaXphdGlvbkZpcnN0Tm9kZShub2RlKSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICBub2RlID0gbm9kZS5uZXh0U2libGluZzsKICAgICAgfQoKICAgICAgX3RoaXMyMS5jYW5kaWRhdGUgPSBub2RlOwogICAgICByZXR1cm4gX3RoaXMyMTsKICAgIH0KCiAgICB2YXIgX3Byb3RvNjcgPSBSZWh5ZHJhdGVCdWlsZGVyLnByb3RvdHlwZTsKCiAgICBfcHJvdG82Ny5wdXNoRWxlbWVudCA9IGZ1bmN0aW9uIHB1c2hFbGVtZW50KGVsZW1lbnQsIG5leHRTaWJsaW5nKSB7CiAgICAgIHZhciBfdGhpcyRibG9ja0RlcHRoID0gdGhpcy5ibG9ja0RlcHRoLAogICAgICAgICAgYmxvY2tEZXB0aCA9IF90aGlzJGJsb2NrRGVwdGggPT09IHZvaWQgMCA/IDAgOiBfdGhpcyRibG9ja0RlcHRoOwogICAgICB2YXIgY3Vyc29yID0gbmV3IFJlaHlkcmF0aW5nQ3Vyc29yKGVsZW1lbnQsIG5leHRTaWJsaW5nLCBibG9ja0RlcHRoKTsKICAgICAgdmFyIGN1cnJlbnRDdXJzb3IgPSB0aGlzLmN1cnJlbnRDdXJzb3I7CgogICAgICBpZiAoY3VycmVudEN1cnNvcikgewogICAgICAgIGlmIChjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSkgewogICAgICAgICAgLyoqCiAgICAgICAgICAgKiA8ZGl2PiAgIDwtLS0tLS0tLS0tLS0tLS0gIGN1cnJlbnRDdXJzb3IuZWxlbWVudAogICAgICAgICAgICogICA8IS0tJStiOjElLS0+CiAgICAgICAgICAgKiAgIDxkaXY+IDwtLS0tLS0tLS0tLS0tLS0gIGN1cnJlbnRDdXJzb3IuY2FuZGlkYXRlIC0+IGN1cnNvci5lbGVtZW50CiAgICAgICAgICAgKiAgICAgPCEtLSUrYjoyJS0tPiA8LSAgY3VycmVudEN1cnNvci5jYW5kaWRhdGUuZmlyc3RDaGlsZCAtPiBjdXJzb3IuY2FuZGlkYXRlCiAgICAgICAgICAgKiAgICAgRm9vCiAgICAgICAgICAgKiAgICAgPCEtLSUtYjoyJS0tPgogICAgICAgICAgICogICA8L2Rpdj4KICAgICAgICAgICAqICAgPCEtLSUtYjoxJS0tPiAgPC0tICBiZWNvbWVzIGN1cnJlbnRDdXJzb3IuY2FuZGlkYXRlCiAgICAgICAgICAgKi8KICAgICAgICAgIC8vIHdoZXJlIHRvIHJlaHlkcmF0ZSBmcm9tIGlmIHdlIGFyZSBpbiByZWh5ZHJhdGlvbiBtb2RlCiAgICAgICAgICBjdXJzb3IuY2FuZGlkYXRlID0gZWxlbWVudC5maXJzdENoaWxkOyAvLyB3aGVyZSB0byBjb250aW51ZSB3aGVuIHdlIHBvcAoKICAgICAgICAgIGN1cnJlbnRDdXJzb3IuY2FuZGlkYXRlID0gZWxlbWVudC5uZXh0U2libGluZzsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHRoaXMuY3Vyc29yU3RhY2sucHVzaChjdXJzb3IpOwogICAgfTsKCiAgICBfcHJvdG82Ny5jbGVhck1pc21hdGNoID0gZnVuY3Rpb24gY2xlYXJNaXNtYXRjaChjYW5kaWRhdGUpIHsKICAgICAgdmFyIGN1cnJlbnQgPSBjYW5kaWRhdGU7CiAgICAgIHZhciBjdXJyZW50Q3Vyc29yID0gdGhpcy5jdXJyZW50Q3Vyc29yOwoKICAgICAgaWYgKGN1cnJlbnRDdXJzb3IgIT09IG51bGwpIHsKICAgICAgICB2YXIgb3BlbkJsb2NrRGVwdGggPSBjdXJyZW50Q3Vyc29yLm9wZW5CbG9ja0RlcHRoOwoKICAgICAgICBpZiAob3BlbkJsb2NrRGVwdGggPj0gY3VycmVudEN1cnNvci5zdGFydGluZ0Jsb2NrRGVwdGgpIHsKICAgICAgICAgIHdoaWxlIChjdXJyZW50ICYmICEoaXNDb21tZW50KGN1cnJlbnQpICYmIGdldENsb3NlQmxvY2tEZXB0aChjdXJyZW50KSA9PT0gb3BlbkJsb2NrRGVwdGgpKSB7CiAgICAgICAgICAgIGN1cnJlbnQgPSB0aGlzLnJlbW92ZShjdXJyZW50KTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgd2hpbGUgKGN1cnJlbnQgIT09IG51bGwpIHsKICAgICAgICAgICAgY3VycmVudCA9IHRoaXMucmVtb3ZlKGN1cnJlbnQpOwogICAgICAgICAgfQogICAgICAgIH0gLy8gY3VycmVudCBjdXJzb3IgcGFyZW50Tm9kZSBzaG91bGQgYmUgb3BlbkNhbmRpZGF0ZSBpZiBlbGVtZW50CiAgICAgICAgLy8gb3Igb3BlbkNhbmRpZGF0ZS5wYXJlbnROb2RlIGlmIGNvbW1lbnQKCgogICAgICAgIGN1cnJlbnRDdXJzb3IubmV4dFNpYmxpbmcgPSBjdXJyZW50OyAvLyBkaXNhYmxlIHJlaHlkcmF0aW9uIHVudGlsIHdlIHBvcEVsZW1lbnQgb3IgY2xvc2VCbG9jayBmb3Igb3BlbkJsb2NrRGVwdGgKCiAgICAgICAgY3VycmVudEN1cnNvci5jYW5kaWRhdGUgPSBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzY3Ll9fb3BlbkJsb2NrID0gZnVuY3Rpb24gX19vcGVuQmxvY2soKSB7CiAgICAgIHZhciBjdXJyZW50Q3Vyc29yID0gdGhpcy5jdXJyZW50Q3Vyc29yOwogICAgICBpZiAoY3VycmVudEN1cnNvciA9PT0gbnVsbCkgcmV0dXJuOwogICAgICB2YXIgYmxvY2tEZXB0aCA9IHRoaXMuYmxvY2tEZXB0aDsKICAgICAgdGhpcy5ibG9ja0RlcHRoKys7CiAgICAgIHZhciBjYW5kaWRhdGUgPSBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZTsKICAgICAgaWYgKGNhbmRpZGF0ZSA9PT0gbnVsbCkgcmV0dXJuOwogICAgICB2YXIgdGFnTmFtZSA9IGN1cnJlbnRDdXJzb3IuZWxlbWVudC50YWdOYW1lOwoKICAgICAgaWYgKGlzQ29tbWVudChjYW5kaWRhdGUpICYmIGdldE9wZW5CbG9ja0RlcHRoKGNhbmRpZGF0ZSkgPT09IGJsb2NrRGVwdGgpIHsKICAgICAgICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSA9IHRoaXMucmVtb3ZlKGNhbmRpZGF0ZSk7CiAgICAgICAgY3VycmVudEN1cnNvci5vcGVuQmxvY2tEZXB0aCA9IGJsb2NrRGVwdGg7CiAgICAgIH0gZWxzZSBpZiAodGFnTmFtZSAhPT0gJ1RJVExFJyAmJiB0YWdOYW1lICE9PSAnU0NSSVBUJyAmJiB0YWdOYW1lICE9PSAnU1RZTEUnKSB7CiAgICAgICAgdGhpcy5jbGVhck1pc21hdGNoKGNhbmRpZGF0ZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNjcuX19jbG9zZUJsb2NrID0gZnVuY3Rpb24gX19jbG9zZUJsb2NrKCkgewogICAgICB2YXIgY3VycmVudEN1cnNvciA9IHRoaXMuY3VycmVudEN1cnNvcjsKICAgICAgaWYgKGN1cnJlbnRDdXJzb3IgPT09IG51bGwpIHJldHVybjsgLy8gb3BlbkJsb2NrIGlzIHRoZSBsYXN0IHJlaHlkcmF0ZWQgb3BlbiBibG9jawoKICAgICAgdmFyIG9wZW5CbG9ja0RlcHRoID0gY3VycmVudEN1cnNvci5vcGVuQmxvY2tEZXB0aDsgLy8gdGhpcyBjdXJyZW50bHkgaXMgdGhlIGV4cGVjdGVkIG5leHQgb3BlbiBibG9jayBkZXB0aAoKICAgICAgdGhpcy5ibG9ja0RlcHRoLS07CiAgICAgIHZhciBjYW5kaWRhdGUgPSBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZTsgLy8gcmVoeWRyYXRpbmcKCiAgICAgIGlmIChjYW5kaWRhdGUgIT09IG51bGwpIHsKICAgICAgICBpZiAoaXNDb21tZW50KGNhbmRpZGF0ZSkgJiYgZ2V0Q2xvc2VCbG9ja0RlcHRoKGNhbmRpZGF0ZSkgPT09IG9wZW5CbG9ja0RlcHRoKSB7CiAgICAgICAgICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSA9IHRoaXMucmVtb3ZlKGNhbmRpZGF0ZSk7CiAgICAgICAgICBjdXJyZW50Q3Vyc29yLm9wZW5CbG9ja0RlcHRoLS07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuY2xlYXJNaXNtYXRjaChjYW5kaWRhdGUpOwogICAgICAgIH0gLy8gaWYgdGhlIG9wZW5CbG9ja0RlcHRoIG1hdGNoZXMgdGhlIGJsb2NrRGVwdGggd2UganVzdCBjbG9zZWQgdG8KICAgICAgICAvLyB0aGVuIHJlc3RvcmUgcmVoeWRyYXRpb24KCiAgICAgIH0KCiAgICAgIGlmIChjdXJyZW50Q3Vyc29yLm9wZW5CbG9ja0RlcHRoID09PSB0aGlzLmJsb2NrRGVwdGgpIHsKICAgICAgICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSA9IHRoaXMucmVtb3ZlKGN1cnJlbnRDdXJzb3IubmV4dFNpYmxpbmcpOwogICAgICAgIGN1cnJlbnRDdXJzb3Iub3BlbkJsb2NrRGVwdGgtLTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG82Ny5fX2FwcGVuZE5vZGUgPSBmdW5jdGlvbiBfX2FwcGVuZE5vZGUobm9kZSkgewogICAgICB2YXIgY2FuZGlkYXRlID0gdGhpcy5jYW5kaWRhdGU7IC8vIFRoaXMgY29kZSBwYXRoIGlzIG9ubHkgdXNlZCB3aGVuIGluc2VydGluZyBwcmVjaXNlbHkgb25lIG5vZGUuIEl0IG5lZWRzIG1vcmUKICAgICAgLy8gY29tcGFyaXNvbiBsb2dpYywgYnV0IHdlIGNhbiBwcm9iYWJseSBsZWFuIG9uIHRoZSBjYXNlcyB3aGVyZSB0aGlzIGNvZGUgcGF0aAogICAgICAvLyBpcyBhY3R1YWxseSB1c2VkLgoKICAgICAgaWYgKGNhbmRpZGF0ZSkgewogICAgICAgIHJldHVybiBjYW5kaWRhdGU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuX19hcHBlbmROb2RlLmNhbGwodGhpcywgbm9kZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNjcuX19hcHBlbmRIVE1MID0gZnVuY3Rpb24gX19hcHBlbmRIVE1MKGh0bWwpIHsKICAgICAgdmFyIGNhbmRpZGF0ZUJvdW5kcyA9IHRoaXMubWFya2VyQm91bmRzKCk7CgogICAgICBpZiAoY2FuZGlkYXRlQm91bmRzKSB7CiAgICAgICAgdmFyIGZpcnN0ID0gY2FuZGlkYXRlQm91bmRzLmZpcnN0Tm9kZSgpOwogICAgICAgIHZhciBsYXN0ID0gY2FuZGlkYXRlQm91bmRzLmxhc3ROb2RlKCk7CiAgICAgICAgdmFyIG5ld0JvdW5kcyA9IG5ldyBDb25jcmV0ZUJvdW5kcyh0aGlzLmVsZW1lbnQsIGZpcnN0Lm5leHRTaWJsaW5nLCBsYXN0LnByZXZpb3VzU2libGluZyk7CiAgICAgICAgdmFyIHBvc3NpYmxlRW1wdHlNYXJrZXIgPSB0aGlzLnJlbW92ZShmaXJzdCk7CiAgICAgICAgdGhpcy5yZW1vdmUobGFzdCk7CgogICAgICAgIGlmIChwb3NzaWJsZUVtcHR5TWFya2VyICE9PSBudWxsICYmIGlzRW1wdHkkMShwb3NzaWJsZUVtcHR5TWFya2VyKSkgewogICAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSB0aGlzLnJlbW92ZShwb3NzaWJsZUVtcHR5TWFya2VyKTsKCiAgICAgICAgICBpZiAodGhpcy5jYW5kaWRhdGUgIT09IG51bGwpIHsKICAgICAgICAgICAgdGhpcy5jbGVhck1pc21hdGNoKHRoaXMuY2FuZGlkYXRlKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiBuZXdCb3VuZHM7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuX19hcHBlbmRIVE1MLmNhbGwodGhpcywgaHRtbCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvNjcucmVtb3ZlID0gZnVuY3Rpb24gcmVtb3ZlKG5vZGUpIHsKICAgICAgdmFyIGVsZW1lbnQgPSBub2RlLnBhcmVudE5vZGU7CiAgICAgIHZhciBuZXh0ID0gbm9kZS5uZXh0U2libGluZzsKICAgICAgZWxlbWVudC5yZW1vdmVDaGlsZChub2RlKTsKICAgICAgcmV0dXJuIG5leHQ7CiAgICB9OwoKICAgIF9wcm90bzY3Lm1hcmtlckJvdW5kcyA9IGZ1bmN0aW9uIG1hcmtlckJvdW5kcygpIHsKICAgICAgdmFyIF9jYW5kaWRhdGUgPSB0aGlzLmNhbmRpZGF0ZTsKCiAgICAgIGlmIChfY2FuZGlkYXRlICYmIGlzTWFya2VyKF9jYW5kaWRhdGUpKSB7CiAgICAgICAgdmFyIGZpcnN0ID0gX2NhbmRpZGF0ZTsKICAgICAgICB2YXIgbGFzdCA9IGZpcnN0Lm5leHRTaWJsaW5nOwoKICAgICAgICB3aGlsZSAobGFzdCAmJiAhaXNNYXJrZXIobGFzdCkpIHsKICAgICAgICAgIGxhc3QgPSBsYXN0Lm5leHRTaWJsaW5nOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIG5ldyBDb25jcmV0ZUJvdW5kcyh0aGlzLmVsZW1lbnQsIGZpcnN0LCBsYXN0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG82Ny5fX2FwcGVuZFRleHQgPSBmdW5jdGlvbiBfX2FwcGVuZFRleHQoc3RyaW5nKSB7CiAgICAgIHZhciBjYW5kaWRhdGUgPSB0aGlzLmNhbmRpZGF0ZTsKCiAgICAgIGlmIChjYW5kaWRhdGUpIHsKICAgICAgICBpZiAoaXNUZXh0Tm9kZShjYW5kaWRhdGUpKSB7CiAgICAgICAgICBpZiAoY2FuZGlkYXRlLm5vZGVWYWx1ZSAhPT0gc3RyaW5nKSB7CiAgICAgICAgICAgIGNhbmRpZGF0ZS5ub2RlVmFsdWUgPSBzdHJpbmc7CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSBjYW5kaWRhdGUubmV4dFNpYmxpbmc7CiAgICAgICAgICByZXR1cm4gY2FuZGlkYXRlOwogICAgICAgIH0gZWxzZSBpZiAoY2FuZGlkYXRlICYmIChpc1NlcGFyYXRvcihjYW5kaWRhdGUpIHx8IGlzRW1wdHkkMShjYW5kaWRhdGUpKSkgewogICAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSBjYW5kaWRhdGUubmV4dFNpYmxpbmc7CiAgICAgICAgICB0aGlzLnJlbW92ZShjYW5kaWRhdGUpOwogICAgICAgICAgcmV0dXJuIHRoaXMuX19hcHBlbmRUZXh0KHN0cmluZyk7CiAgICAgICAgfSBlbHNlIGlmIChpc0VtcHR5JDEoY2FuZGlkYXRlKSkgewogICAgICAgICAgdmFyIG5leHQgPSB0aGlzLnJlbW92ZShjYW5kaWRhdGUpOwogICAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSBuZXh0OwogICAgICAgICAgdmFyIHRleHQgPSB0aGlzLmRvbS5jcmVhdGVUZXh0Tm9kZShzdHJpbmcpOwogICAgICAgICAgdGhpcy5kb20uaW5zZXJ0QmVmb3JlKHRoaXMuZWxlbWVudCwgdGV4dCwgbmV4dCk7CiAgICAgICAgICByZXR1cm4gdGV4dDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhpcy5jbGVhck1pc21hdGNoKGNhbmRpZGF0ZSk7CiAgICAgICAgICByZXR1cm4gX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS5fX2FwcGVuZFRleHQuY2FsbCh0aGlzLCBzdHJpbmcpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS5fX2FwcGVuZFRleHQuY2FsbCh0aGlzLCBzdHJpbmcpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzY3Ll9fYXBwZW5kQ29tbWVudCA9IGZ1bmN0aW9uIF9fYXBwZW5kQ29tbWVudChzdHJpbmcpIHsKICAgICAgdmFyIF9jYW5kaWRhdGUgPSB0aGlzLmNhbmRpZGF0ZTsKCiAgICAgIGlmIChfY2FuZGlkYXRlICYmIGlzQ29tbWVudChfY2FuZGlkYXRlKSkgewogICAgICAgIGlmIChfY2FuZGlkYXRlLm5vZGVWYWx1ZSAhPT0gc3RyaW5nKSB7CiAgICAgICAgICBfY2FuZGlkYXRlLm5vZGVWYWx1ZSA9IHN0cmluZzsKICAgICAgICB9CgogICAgICAgIHRoaXMuY2FuZGlkYXRlID0gX2NhbmRpZGF0ZS5uZXh0U2libGluZzsKICAgICAgICByZXR1cm4gX2NhbmRpZGF0ZTsKICAgICAgfSBlbHNlIGlmIChfY2FuZGlkYXRlKSB7CiAgICAgICAgdGhpcy5jbGVhck1pc21hdGNoKF9jYW5kaWRhdGUpOwogICAgICB9CgogICAgICByZXR1cm4gX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS5fX2FwcGVuZENvbW1lbnQuY2FsbCh0aGlzLCBzdHJpbmcpOwogICAgfTsKCiAgICBfcHJvdG82Ny5fX29wZW5FbGVtZW50ID0gZnVuY3Rpb24gX19vcGVuRWxlbWVudCh0YWcpIHsKICAgICAgdmFyIF9jYW5kaWRhdGUgPSB0aGlzLmNhbmRpZGF0ZTsKCiAgICAgIGlmIChfY2FuZGlkYXRlICYmIGlzRWxlbWVudChfY2FuZGlkYXRlKSAmJiBpc1NhbWVOb2RlVHlwZShfY2FuZGlkYXRlLCB0YWcpKSB7CiAgICAgICAgdGhpcy51bm1hdGNoZWRBdHRyaWJ1dGVzID0gW10uc2xpY2UuY2FsbChfY2FuZGlkYXRlLmF0dHJpYnV0ZXMpOwogICAgICAgIHJldHVybiBfY2FuZGlkYXRlOwogICAgICB9IGVsc2UgaWYgKF9jYW5kaWRhdGUpIHsKICAgICAgICBpZiAoaXNFbGVtZW50KF9jYW5kaWRhdGUpICYmIF9jYW5kaWRhdGUudGFnTmFtZSA9PT0gJ1RCT0RZJykgewogICAgICAgICAgdGhpcy5wdXNoRWxlbWVudChfY2FuZGlkYXRlLCBudWxsKTsKICAgICAgICAgIHRoaXMuY3VycmVudEN1cnNvci5pbmplY3RlZE9taXR0ZWROb2RlID0gdHJ1ZTsKICAgICAgICAgIHJldHVybiB0aGlzLl9fb3BlbkVsZW1lbnQodGFnKTsKICAgICAgICB9CgogICAgICAgIHRoaXMuY2xlYXJNaXNtYXRjaChfY2FuZGlkYXRlKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuX19vcGVuRWxlbWVudC5jYWxsKHRoaXMsIHRhZyk7CiAgICB9OwoKICAgIF9wcm90bzY3Ll9fc2V0QXR0cmlidXRlID0gZnVuY3Rpb24gX19zZXRBdHRyaWJ1dGUobmFtZSwgdmFsdWUkJDEsIG5hbWVzcGFjZSkgewogICAgICB2YXIgdW5tYXRjaGVkID0gdGhpcy51bm1hdGNoZWRBdHRyaWJ1dGVzOwoKICAgICAgaWYgKHVubWF0Y2hlZCkgewogICAgICAgIHZhciBhdHRyID0gZmluZEJ5TmFtZSh1bm1hdGNoZWQsIG5hbWUpOwoKICAgICAgICBpZiAoYXR0cikgewogICAgICAgICAgaWYgKGF0dHIudmFsdWUgIT09IHZhbHVlJCQxKSB7CiAgICAgICAgICAgIGF0dHIudmFsdWUgPSB2YWx1ZSQkMTsKICAgICAgICAgIH0KCiAgICAgICAgICB1bm1hdGNoZWQuc3BsaWNlKHVubWF0Y2hlZC5pbmRleE9mKGF0dHIpLCAxKTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fc2V0QXR0cmlidXRlLmNhbGwodGhpcywgbmFtZSwgdmFsdWUkJDEsIG5hbWVzcGFjZSk7CiAgICB9OwoKICAgIF9wcm90bzY3Ll9fc2V0UHJvcGVydHkgPSBmdW5jdGlvbiBfX3NldFByb3BlcnR5KG5hbWUsIHZhbHVlJCQxKSB7CiAgICAgIHZhciB1bm1hdGNoZWQgPSB0aGlzLnVubWF0Y2hlZEF0dHJpYnV0ZXM7CgogICAgICBpZiAodW5tYXRjaGVkKSB7CiAgICAgICAgdmFyIGF0dHIgPSBmaW5kQnlOYW1lKHVubWF0Y2hlZCwgbmFtZSk7CgogICAgICAgIGlmIChhdHRyKSB7CiAgICAgICAgICBpZiAoYXR0ci52YWx1ZSAhPT0gdmFsdWUkJDEpIHsKICAgICAgICAgICAgYXR0ci52YWx1ZSA9IHZhbHVlJCQxOwogICAgICAgICAgfQoKICAgICAgICAgIHVubWF0Y2hlZC5zcGxpY2UodW5tYXRjaGVkLmluZGV4T2YoYXR0ciksIDEpOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuX19zZXRQcm9wZXJ0eS5jYWxsKHRoaXMsIG5hbWUsIHZhbHVlJCQxKTsKICAgIH07CgogICAgX3Byb3RvNjcuX19mbHVzaEVsZW1lbnQgPSBmdW5jdGlvbiBfX2ZsdXNoRWxlbWVudChwYXJlbnQsIGNvbnN0cnVjdGluZykgewogICAgICB2YXIgdW5tYXRjaGVkID0gdGhpcy51bm1hdGNoZWRBdHRyaWJ1dGVzOwoKICAgICAgaWYgKHVubWF0Y2hlZCkgewogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdW5tYXRjaGVkLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICB0aGlzLmNvbnN0cnVjdGluZy5yZW1vdmVBdHRyaWJ1dGUodW5tYXRjaGVkW2ldLm5hbWUpOwogICAgICAgIH0KCiAgICAgICAgdGhpcy51bm1hdGNoZWRBdHRyaWJ1dGVzID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICBfTmV3RWxlbWVudEJ1aWxkZXIucHJvdG90eXBlLl9fZmx1c2hFbGVtZW50LmNhbGwodGhpcywgcGFyZW50LCBjb25zdHJ1Y3RpbmcpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzY3LndpbGxDbG9zZUVsZW1lbnQgPSBmdW5jdGlvbiB3aWxsQ2xvc2VFbGVtZW50KCkgewogICAgICB2YXIgY2FuZGlkYXRlID0gdGhpcy5jYW5kaWRhdGUsCiAgICAgICAgICBjdXJyZW50Q3Vyc29yID0gdGhpcy5jdXJyZW50Q3Vyc29yOwoKICAgICAgaWYgKGNhbmRpZGF0ZSAhPT0gbnVsbCkgewogICAgICAgIHRoaXMuY2xlYXJNaXNtYXRjaChjYW5kaWRhdGUpOwogICAgICB9CgogICAgICBpZiAoY3VycmVudEN1cnNvciAmJiBjdXJyZW50Q3Vyc29yLmluamVjdGVkT21pdHRlZE5vZGUpIHsKICAgICAgICB0aGlzLnBvcEVsZW1lbnQoKTsKICAgICAgfQoKICAgICAgX05ld0VsZW1lbnRCdWlsZGVyLnByb3RvdHlwZS53aWxsQ2xvc2VFbGVtZW50LmNhbGwodGhpcyk7CiAgICB9OwoKICAgIF9wcm90bzY3LmdldE1hcmtlciA9IGZ1bmN0aW9uIGdldE1hcmtlcihlbGVtZW50LCBndWlkKSB7CiAgICAgIHZhciBtYXJrZXIgPSBlbGVtZW50LnF1ZXJ5U2VsZWN0b3IoInNjcmlwdFtnbG1yPVwiIiArIGd1aWQgKyAiXCJdIik7CgogICAgICBpZiAobWFya2VyKSB7CiAgICAgICAgcmV0dXJuIG1hcmtlcjsKICAgICAgfQoKICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZmluZCBzZXJpYWxpemVkIGN1cnNvciBmb3IgYGluLWVsZW1lbnRgJyk7CiAgICB9OwoKICAgIF9wcm90bzY3Ll9fcHVzaFJlbW90ZUVsZW1lbnQgPSBmdW5jdGlvbiBfX3B1c2hSZW1vdGVFbGVtZW50KGVsZW1lbnQsIGN1cnNvcklkLCBuZXh0U2libGluZykgewogICAgICBpZiAobmV4dFNpYmxpbmcgPT09IHZvaWQgMCkgewogICAgICAgIG5leHRTaWJsaW5nID0gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIG1hcmtlciA9IHRoaXMuZ2V0TWFya2VyKGVsZW1lbnQsIGN1cnNvcklkKTsKCiAgICAgIGlmIChtYXJrZXIucGFyZW50Tm9kZSA9PT0gZWxlbWVudCkgewogICAgICAgIHZhciBjdXJyZW50Q3Vyc29yID0gdGhpcy5jdXJyZW50Q3Vyc29yOwogICAgICAgIHZhciBjYW5kaWRhdGUgPSBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZTsKICAgICAgICB0aGlzLnB1c2hFbGVtZW50KGVsZW1lbnQsIG5leHRTaWJsaW5nKTsKICAgICAgICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSA9IGNhbmRpZGF0ZTsKICAgICAgICB0aGlzLmNhbmRpZGF0ZSA9IHRoaXMucmVtb3ZlKG1hcmtlcik7CiAgICAgICAgdmFyIHRyYWNrZXIgPSBuZXcgUmVtb3RlQmxvY2tUcmFja2VyKGVsZW1lbnQpOwogICAgICAgIHRoaXMucHVzaEJsb2NrVHJhY2tlcih0cmFja2VyLCB0cnVlKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG82Ny5kaWRBcHBlbmRCb3VuZHMgPSBmdW5jdGlvbiBkaWRBcHBlbmRCb3VuZHMoYm91bmRzKSB7CiAgICAgIF9OZXdFbGVtZW50QnVpbGRlci5wcm90b3R5cGUuZGlkQXBwZW5kQm91bmRzLmNhbGwodGhpcywgYm91bmRzKTsKCiAgICAgIGlmICh0aGlzLmNhbmRpZGF0ZSkgewogICAgICAgIHZhciBsYXN0ID0gYm91bmRzLmxhc3ROb2RlKCk7CiAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSBsYXN0ICYmIGxhc3QubmV4dFNpYmxpbmc7CiAgICAgIH0KCiAgICAgIHJldHVybiBib3VuZHM7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoUmVoeWRyYXRlQnVpbGRlciwgW3sKICAgICAga2V5OiAiY3VycmVudEN1cnNvciIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLmN1cnNvclN0YWNrLmN1cnJlbnQ7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiY2FuZGlkYXRlIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMuY3VycmVudEN1cnNvcikgewogICAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudEN1cnNvci5jYW5kaWRhdGU7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQobm9kZSkgewogICAgICAgIHRoaXMuY3VycmVudEN1cnNvci5jYW5kaWRhdGUgPSBub2RlOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gUmVoeWRyYXRlQnVpbGRlcjsKICB9KE5ld0VsZW1lbnRCdWlsZGVyKTsKCiAgX2V4cG9ydHMuUmVoeWRyYXRlQnVpbGRlciA9IFJlaHlkcmF0ZUJ1aWxkZXI7CgogIGZ1bmN0aW9uIGlzVGV4dE5vZGUobm9kZSkgewogICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IDM7CiAgfQoKICBmdW5jdGlvbiBpc0NvbW1lbnQobm9kZSkgewogICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IDg7CiAgfQoKICBmdW5jdGlvbiBnZXRPcGVuQmxvY2tEZXB0aChub2RlKSB7CiAgICB2YXIgYm91bmRzRGVwdGggPSBub2RlLm5vZGVWYWx1ZS5tYXRjaCgvXiVcK2I6KFxkKyklJC8pOwoKICAgIGlmIChib3VuZHNEZXB0aCAmJiBib3VuZHNEZXB0aFsxXSkgewogICAgICByZXR1cm4gTnVtYmVyKGJvdW5kc0RlcHRoWzFdKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZ2V0Q2xvc2VCbG9ja0RlcHRoKG5vZGUpIHsKICAgIHZhciBib3VuZHNEZXB0aCA9IG5vZGUubm9kZVZhbHVlLm1hdGNoKC9eJVwtYjooXGQrKSUkLyk7CgogICAgaWYgKGJvdW5kc0RlcHRoICYmIGJvdW5kc0RlcHRoWzFdKSB7CiAgICAgIHJldHVybiBOdW1iZXIoYm91bmRzRGVwdGhbMV0pOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBpc0VsZW1lbnQobm9kZSkgewogICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IDE7CiAgfQoKICBmdW5jdGlvbiBpc01hcmtlcihub2RlKSB7CiAgICByZXR1cm4gbm9kZS5ub2RlVHlwZSA9PT0gOCAmJiBub2RlLm5vZGVWYWx1ZSA9PT0gJyVnbG1yJSc7CiAgfQoKICBmdW5jdGlvbiBpc1NlcGFyYXRvcihub2RlKSB7CiAgICByZXR1cm4gbm9kZS5ub2RlVHlwZSA9PT0gOCAmJiBub2RlLm5vZGVWYWx1ZSA9PT0gJyV8JSc7CiAgfQoKICBmdW5jdGlvbiBpc0VtcHR5JDEobm9kZSkgewogICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IDggJiYgbm9kZS5ub2RlVmFsdWUgPT09ICclICUnOwogIH0KCiAgZnVuY3Rpb24gaXNTYW1lTm9kZVR5cGUoY2FuZGlkYXRlLCB0YWcpIHsKICAgIGlmIChjYW5kaWRhdGUubmFtZXNwYWNlVVJJID09PSBTVkdfTkFNRVNQQUNFKSB7CiAgICAgIHJldHVybiBjYW5kaWRhdGUudGFnTmFtZSA9PT0gdGFnOwogICAgfQoKICAgIHJldHVybiBjYW5kaWRhdGUudGFnTmFtZSA9PT0gdGFnLnRvVXBwZXJDYXNlKCk7CiAgfQoKICBmdW5jdGlvbiBmaW5kQnlOYW1lKGFycmF5LCBuYW1lKSB7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBhdHRyID0gYXJyYXlbaV07CiAgICAgIGlmIChhdHRyLm5hbWUgPT09IG5hbWUpIHJldHVybiBhdHRyOwogICAgfQoKICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQoKICBmdW5jdGlvbiByZWh5ZHJhdGlvbkJ1aWxkZXIoZW52LCBjdXJzb3IpIHsKICAgIHJldHVybiBSZWh5ZHJhdGVCdWlsZGVyLmZvckluaXRpYWxSZW5kZXIoZW52LCBjdXJzb3IpOwogIH0KfSk7CmRlZmluZSgiQGdsaW1tZXIvdXRpbCIsIFsiZXhwb3J0cyIsICJlbWJlci1iYWJlbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckJhYmVsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5hc3NlcnQgPSBkZWJ1Z0Fzc2VydDsKICBfZXhwb3J0cy5hc3NpZ24gPSBhc3NpZ247CiAgX2V4cG9ydHMuZmlsbE51bGxzID0gZmlsbE51bGxzOwogIF9leHBvcnRzLmVuc3VyZUd1aWQgPSBlbnN1cmVHdWlkOwogIF9leHBvcnRzLmluaXRpYWxpemVHdWlkID0gaW5pdGlhbGl6ZUd1aWQ7CiAgX2V4cG9ydHMuZGljdCA9IGRpY3Q7CiAgX2V4cG9ydHMudW53cmFwID0gdW53cmFwOwogIF9leHBvcnRzLmV4cGVjdCA9IGV4cGVjdDsKICBfZXhwb3J0cy51bnJlYWNoYWJsZSA9IHVucmVhY2hhYmxlOwogIF9leHBvcnRzLkVNUFRZX0FSUkFZID0gX2V4cG9ydHMuTGlzdFNsaWNlID0gX2V4cG9ydHMuTGlzdE5vZGUgPSBfZXhwb3J0cy5MaW5rZWRMaXN0ID0gX2V4cG9ydHMuRU1QVFlfU0xJQ0UgPSBfZXhwb3J0cy5EaWN0U2V0ID0gX2V4cG9ydHMuU3RhY2sgPSB2b2lkIDA7CgogIGZ1bmN0aW9uIHVud3JhcCh2YWwpIHsKICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQpIHRocm93IG5ldyBFcnJvcigiRXhwZWN0ZWQgdmFsdWUgdG8gYmUgcHJlc2VudCIpOwogICAgcmV0dXJuIHZhbDsKICB9CgogIGZ1bmN0aW9uIGV4cGVjdCh2YWwsIG1lc3NhZ2UpIHsKICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQpIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTsKICAgIHJldHVybiB2YWw7CiAgfQoKICBmdW5jdGlvbiB1bnJlYWNoYWJsZShtZXNzYWdlKSB7CiAgICBpZiAobWVzc2FnZSA9PT0gdm9pZCAwKSB7CiAgICAgIG1lc3NhZ2UgPSAndW5yZWFjaGFibGUnOwogICAgfQoKICAgIHJldHVybiBuZXcgRXJyb3IobWVzc2FnZSk7CiAgfSAvLyBpbXBvcnQgTG9nZ2VyIGZyb20gJy4vbG9nZ2VyJzsKICAvLyBsZXQgYWxyZWFkeVdhcm5lZCA9IGZhbHNlOwoKCiAgZnVuY3Rpb24gZGVidWdBc3NlcnQodGVzdCwgbXNnKSB7CiAgICAvLyBpZiAoIWFscmVhZHlXYXJuZWQpIHsKICAgIC8vICAgYWxyZWFkeVdhcm5lZCA9IHRydWU7CiAgICAvLyAgIExvZ2dlci53YXJuKCJEb24ndCBsZWF2ZSBkZWJ1ZyBhc3NlcnRpb25zIG9uIGluIHB1YmxpYyBidWlsZHMiKTsKICAgIC8vIH0KICAgIGlmICghdGVzdCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IobXNnIHx8ICdhc3NlcnRpb24gZmFpbHVyZScpOwogICAgfQogIH0KCiAgdmFyIG9iaktleXMgPSBPYmplY3Qua2V5czsKCiAgZnVuY3Rpb24gYXNzaWduKG9iaikgewogICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGFzc2lnbm1lbnQgPSBhcmd1bWVudHNbaV07CiAgICAgIGlmIChhc3NpZ25tZW50ID09PSBudWxsIHx8IHR5cGVvZiBhc3NpZ25tZW50ICE9PSAnb2JqZWN0JykgY29udGludWU7CiAgICAgIHZhciBrZXlzID0gb2JqS2V5cyhhc3NpZ25tZW50KTsKCiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwga2V5cy5sZW5ndGg7IGorKykgewogICAgICAgIHZhciBrZXkgPSBrZXlzW2pdOwogICAgICAgIG9ialtrZXldID0gYXNzaWdubWVudFtrZXldOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIG9iajsKICB9CgogIGZ1bmN0aW9uIGZpbGxOdWxscyhjb3VudCkgewogICAgdmFyIGFyciA9IG5ldyBBcnJheShjb3VudCk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIGFycltpXSA9IG51bGw7CiAgICB9CgogICAgcmV0dXJuIGFycjsKICB9CgogIHZhciBHVUlEID0gMDsKCiAgZnVuY3Rpb24gaW5pdGlhbGl6ZUd1aWQob2JqZWN0KSB7CiAgICByZXR1cm4gb2JqZWN0Ll9ndWlkID0gKytHVUlEOwogIH0KCiAgZnVuY3Rpb24gZW5zdXJlR3VpZChvYmplY3QpIHsKICAgIHJldHVybiBvYmplY3QuX2d1aWQgfHwgaW5pdGlhbGl6ZUd1aWQob2JqZWN0KTsKICB9CgogIGZ1bmN0aW9uIGRpY3QoKSB7CiAgICByZXR1cm4gT2JqZWN0LmNyZWF0ZShudWxsKTsKICB9CgogIHZhciBEaWN0U2V0ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRGljdFNldCgpIHsKICAgICAgdGhpcy5kaWN0ID0gZGljdCgpOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBEaWN0U2V0LnByb3RvdHlwZTsKCiAgICBfcHJvdG8uYWRkID0gZnVuY3Rpb24gYWRkKG9iaikgewogICAgICBpZiAodHlwZW9mIG9iaiA9PT0gJ3N0cmluZycpIHRoaXMuZGljdFtvYmpdID0gb2JqO2Vsc2UgdGhpcy5kaWN0W2Vuc3VyZUd1aWQob2JqKV0gPSBvYmo7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICBfcHJvdG8uZGVsZXRlID0gZnVuY3Rpb24gX2RlbGV0ZShvYmopIHsKICAgICAgaWYgKHR5cGVvZiBvYmogPT09ICdzdHJpbmcnKSBkZWxldGUgdGhpcy5kaWN0W29ial07ZWxzZSBpZiAob2JqLl9ndWlkKSBkZWxldGUgdGhpcy5kaWN0W29iai5fZ3VpZF07CiAgICB9OwoKICAgIHJldHVybiBEaWN0U2V0OwogIH0oKTsKCiAgX2V4cG9ydHMuRGljdFNldCA9IERpY3RTZXQ7CgogIHZhciBTdGFjayA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFN0YWNrKCkgewogICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgIHRoaXMuY3VycmVudCA9IG51bGw7CiAgICB9CgogICAgdmFyIF9wcm90bzIgPSBTdGFjay5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5wdXNoID0gZnVuY3Rpb24gcHVzaChpdGVtKSB7CiAgICAgIHRoaXMuY3VycmVudCA9IGl0ZW07CiAgICAgIHRoaXMuc3RhY2sucHVzaChpdGVtKTsKICAgIH07CgogICAgX3Byb3RvMi5wb3AgPSBmdW5jdGlvbiBwb3AoKSB7CiAgICAgIHZhciBpdGVtID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgdmFyIGxlbiA9IHRoaXMuc3RhY2subGVuZ3RoOwogICAgICB0aGlzLmN1cnJlbnQgPSBsZW4gPT09IDAgPyBudWxsIDogdGhpcy5zdGFja1tsZW4gLSAxXTsKICAgICAgcmV0dXJuIGl0ZW0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBpdGVtOwogICAgfTsKCiAgICBfcHJvdG8yLmlzRW1wdHkgPSBmdW5jdGlvbiBpc0VtcHR5KCkgewogICAgICByZXR1cm4gdGhpcy5zdGFjay5sZW5ndGggPT09IDA7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoU3RhY2ssIFt7CiAgICAgIGtleTogInNpemUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5zdGFjay5sZW5ndGg7CiAgICAgIH0KICAgIH1dKTsKICAgIHJldHVybiBTdGFjazsKICB9KCk7CgogIF9leHBvcnRzLlN0YWNrID0gU3RhY2s7CgogIHZhciBMaXN0Tm9kZSA9IGZ1bmN0aW9uIExpc3ROb2RlKHZhbHVlKSB7CiAgICB0aGlzLm5leHQgPSBudWxsOwogICAgdGhpcy5wcmV2ID0gbnVsbDsKICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICB9OwoKICBfZXhwb3J0cy5MaXN0Tm9kZSA9IExpc3ROb2RlOwoKICB2YXIgTGlua2VkTGlzdCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIExpbmtlZExpc3QoKSB7CiAgICAgIHRoaXMuY2xlYXIoKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMyA9IExpbmtlZExpc3QucHJvdG90eXBlOwoKICAgIF9wcm90bzMuaGVhZCA9IGZ1bmN0aW9uIGhlYWQoKSB7CiAgICAgIHJldHVybiB0aGlzLl9oZWFkOwogICAgfTsKCiAgICBfcHJvdG8zLnRhaWwgPSBmdW5jdGlvbiB0YWlsKCkgewogICAgICByZXR1cm4gdGhpcy5fdGFpbDsKICAgIH07CgogICAgX3Byb3RvMy5jbGVhciA9IGZ1bmN0aW9uIGNsZWFyKCkgewogICAgICB0aGlzLl9oZWFkID0gdGhpcy5fdGFpbCA9IG51bGw7CiAgICB9OwoKICAgIF9wcm90bzMudG9BcnJheSA9IGZ1bmN0aW9uIHRvQXJyYXkoKSB7CiAgICAgIHZhciBvdXQgPSBbXTsKICAgICAgdGhpcy5mb3JFYWNoTm9kZShmdW5jdGlvbiAobikgewogICAgICAgIHJldHVybiBvdXQucHVzaChuKTsKICAgICAgfSk7CiAgICAgIHJldHVybiBvdXQ7CiAgICB9OwoKICAgIF9wcm90bzMubmV4dE5vZGUgPSBmdW5jdGlvbiBuZXh0Tm9kZShub2RlKSB7CiAgICAgIHJldHVybiBub2RlLm5leHQ7CiAgICB9OwoKICAgIF9wcm90bzMuZm9yRWFjaE5vZGUgPSBmdW5jdGlvbiBmb3JFYWNoTm9kZShjYWxsYmFjaykgewogICAgICB2YXIgbm9kZSA9IHRoaXMuX2hlYWQ7CgogICAgICB3aGlsZSAobm9kZSAhPT0gbnVsbCkgewogICAgICAgIGNhbGxiYWNrKG5vZGUpOwogICAgICAgIG5vZGUgPSBub2RlLm5leHQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMy5pbnNlcnRCZWZvcmUgPSBmdW5jdGlvbiBpbnNlcnRCZWZvcmUobm9kZSwgcmVmZXJlbmNlKSB7CiAgICAgIGlmIChyZWZlcmVuY2UgPT09IHZvaWQgMCkgewogICAgICAgIHJlZmVyZW5jZSA9IG51bGw7CiAgICAgIH0KCiAgICAgIGlmIChyZWZlcmVuY2UgPT09IG51bGwpIHJldHVybiB0aGlzLmFwcGVuZChub2RlKTsKICAgICAgaWYgKHJlZmVyZW5jZS5wcmV2KSByZWZlcmVuY2UucHJldi5uZXh0ID0gbm9kZTtlbHNlIHRoaXMuX2hlYWQgPSBub2RlOwogICAgICBub2RlLnByZXYgPSByZWZlcmVuY2UucHJldjsKICAgICAgbm9kZS5uZXh0ID0gcmVmZXJlbmNlOwogICAgICByZWZlcmVuY2UucHJldiA9IG5vZGU7CiAgICAgIHJldHVybiBub2RlOwogICAgfTsKCiAgICBfcHJvdG8zLmFwcGVuZCA9IGZ1bmN0aW9uIGFwcGVuZChub2RlKSB7CiAgICAgIHZhciB0YWlsID0gdGhpcy5fdGFpbDsKCiAgICAgIGlmICh0YWlsKSB7CiAgICAgICAgdGFpbC5uZXh0ID0gbm9kZTsKICAgICAgICBub2RlLnByZXYgPSB0YWlsOwogICAgICAgIG5vZGUubmV4dCA9IG51bGw7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5faGVhZCA9IG5vZGU7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLl90YWlsID0gbm9kZTsKICAgIH07CgogICAgX3Byb3RvMy5yZW1vdmUgPSBmdW5jdGlvbiByZW1vdmUobm9kZSkgewogICAgICBpZiAobm9kZS5wcmV2KSBub2RlLnByZXYubmV4dCA9IG5vZGUubmV4dDtlbHNlIHRoaXMuX2hlYWQgPSBub2RlLm5leHQ7CiAgICAgIGlmIChub2RlLm5leHQpIG5vZGUubmV4dC5wcmV2ID0gbm9kZS5wcmV2O2Vsc2UgdGhpcy5fdGFpbCA9IG5vZGUucHJldjsKICAgICAgcmV0dXJuIG5vZGU7CiAgICB9OwoKICAgIHJldHVybiBMaW5rZWRMaXN0OwogIH0oKTsKCiAgX2V4cG9ydHMuTGlua2VkTGlzdCA9IExpbmtlZExpc3Q7CgogIHZhciBMaXN0U2xpY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBMaXN0U2xpY2UoaGVhZCwgdGFpbCkgewogICAgICB0aGlzLl9oZWFkID0gaGVhZDsKICAgICAgdGhpcy5fdGFpbCA9IHRhaWw7CiAgICB9CgogICAgdmFyIF9wcm90bzQgPSBMaXN0U2xpY2UucHJvdG90eXBlOwoKICAgIF9wcm90bzQuZm9yRWFjaE5vZGUgPSBmdW5jdGlvbiBmb3JFYWNoTm9kZShjYWxsYmFjaykgewogICAgICB2YXIgbm9kZSA9IHRoaXMuX2hlYWQ7CgogICAgICB3aGlsZSAobm9kZSAhPT0gbnVsbCkgewogICAgICAgIGNhbGxiYWNrKG5vZGUpOwogICAgICAgIG5vZGUgPSB0aGlzLm5leHROb2RlKG5vZGUpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzQuaGVhZCA9IGZ1bmN0aW9uIGhlYWQoKSB7CiAgICAgIHJldHVybiB0aGlzLl9oZWFkOwogICAgfTsKCiAgICBfcHJvdG80LnRhaWwgPSBmdW5jdGlvbiB0YWlsKCkgewogICAgICByZXR1cm4gdGhpcy5fdGFpbDsKICAgIH07CgogICAgX3Byb3RvNC50b0FycmF5ID0gZnVuY3Rpb24gdG9BcnJheSgpIHsKICAgICAgdmFyIG91dCA9IFtdOwogICAgICB0aGlzLmZvckVhY2hOb2RlKGZ1bmN0aW9uIChuKSB7CiAgICAgICAgcmV0dXJuIG91dC5wdXNoKG4pOwogICAgICB9KTsKICAgICAgcmV0dXJuIG91dDsKICAgIH07CgogICAgX3Byb3RvNC5uZXh0Tm9kZSA9IGZ1bmN0aW9uIG5leHROb2RlKG5vZGUpIHsKICAgICAgaWYgKG5vZGUgPT09IHRoaXMuX3RhaWwpIHJldHVybiBudWxsOwogICAgICByZXR1cm4gbm9kZS5uZXh0OwogICAgfTsKCiAgICByZXR1cm4gTGlzdFNsaWNlOwogIH0oKTsKCiAgX2V4cG9ydHMuTGlzdFNsaWNlID0gTGlzdFNsaWNlOwogIHZhciBFTVBUWV9TTElDRSA9IG5ldyBMaXN0U2xpY2UobnVsbCwgbnVsbCk7CiAgX2V4cG9ydHMuRU1QVFlfU0xJQ0UgPSBFTVBUWV9TTElDRTsKICB2YXIgRU1QVFlfQVJSQVkgPSBPYmplY3QuZnJlZXplKFtdKTsKICBfZXhwb3J0cy5FTVBUWV9BUlJBWSA9IEVNUFRZX0FSUkFZOwp9KTsKZGVmaW5lKCJAZ2xpbW1lci92bSIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLlJlZ2lzdGVyID0gdm9pZCAwOwoKICAvKioKICAgKiBSZWdpc3RlcnMKICAgKgogICAqIEZvciB0aGUgbW9zdCBwYXJ0LCB0aGVzZSBmb2xsb3dzIE1JUFMgbmFtaW5nIGNvbnZlbnRpb25zLCBob3dldmVyIHRoZQogICAqIHJlZ2lzdGVyIG51bWJlcnMgYXJlIGRpZmZlcmVudC4KICAgKi8KICB2YXIgUmVnaXN0ZXI7CiAgX2V4cG9ydHMuUmVnaXN0ZXIgPSBSZWdpc3RlcjsKCiAgKGZ1bmN0aW9uIChSZWdpc3RlcikgewogICAgLy8gJDAgb3IgJHBjIChwcm9ncmFtIGNvdW50ZXIpOiBwb2ludGVyIGludG8gYHByb2dyYW1gIGZvciB0aGUgbmV4dCBpbnN0dXJjdGlvbjsgLTEgbWVhbnMgZXhpdAogICAgUmVnaXN0ZXJbUmVnaXN0ZXJbInBjIl0gPSAwXSA9ICJwYyI7IC8vICQxIG9yICRyYSAocmV0dXJuIGFkZHJlc3MpOiBwb2ludGVyIGludG8gYHByb2dyYW1gIGZvciB0aGUgcmV0dXJuCgogICAgUmVnaXN0ZXJbUmVnaXN0ZXJbInJhIl0gPSAxXSA9ICJyYSI7IC8vICQyIG9yICRmcCAoZnJhbWUgcG9pbnRlcik6IHBvaW50ZXIgaW50byB0aGUgYGV2YWxTdGFja2AgZm9yIHRoZSBiYXNlIG9mIHRoZSBzdGFjawoKICAgIFJlZ2lzdGVyW1JlZ2lzdGVyWyJmcCJdID0gMl0gPSAiZnAiOyAvLyAkMyBvciAkc3AgKHN0YWNrIHBvaW50ZXIpOiBwb2ludGVyIGludG8gdGhlIGBldmFsU3RhY2tgIGZvciB0aGUgdG9wIG9mIHRoZSBzdGFjawoKICAgIFJlZ2lzdGVyW1JlZ2lzdGVyWyJzcCJdID0gM10gPSAic3AiOyAvLyAkNC0kNSBvciAkczAtJHMxIChzYXZlZCk6IGNhbGxlZSBzYXZlZCBnZW5lcmFsLXB1cnBvc2UgcmVnaXN0ZXJzCgogICAgUmVnaXN0ZXJbUmVnaXN0ZXJbInMwIl0gPSA0XSA9ICJzMCI7CiAgICBSZWdpc3RlcltSZWdpc3RlclsiczEiXSA9IDVdID0gInMxIjsgLy8gJDYtJDcgb3IgJHQwLSR0MSAodGVtcG9yYXJpZXMpOiBjYWxsZXIgc2F2ZWQgZ2VuZXJhbC1wdXJwb3NlIHJlZ2lzdGVycwoKICAgIFJlZ2lzdGVyW1JlZ2lzdGVyWyJ0MCJdID0gNl0gPSAidDAiOwogICAgUmVnaXN0ZXJbUmVnaXN0ZXJbInQxIl0gPSA3XSA9ICJ0MSI7IC8vICQ4IG9yICR2MCAocmV0dXJuIHZhbHVlKQoKICAgIFJlZ2lzdGVyW1JlZ2lzdGVyWyJ2MCJdID0gOF0gPSAidjAiOwogIH0pKFJlZ2lzdGVyIHx8IChfZXhwb3J0cy5SZWdpc3RlciA9IFJlZ2lzdGVyID0ge30pKTsKfSk7CmRlZmluZSgiQGdsaW1tZXIvd2lyZS1mb3JtYXQiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5pcyA9IGlzOwogIF9leHBvcnRzLmlzQXR0cmlidXRlID0gaXNBdHRyaWJ1dGU7CiAgX2V4cG9ydHMuaXNBcmd1bWVudCA9IGlzQXJndW1lbnQ7CiAgX2V4cG9ydHMuaXNNYXliZUxvY2FsID0gX2V4cG9ydHMuaXNHZXQgPSBfZXhwb3J0cy5pc0ZsdXNoRWxlbWVudCA9IF9leHBvcnRzLk9wcyA9IHZvaWQgMDsKICB2YXIgT3Bjb2RlczsKICBfZXhwb3J0cy5PcHMgPSBPcGNvZGVzOwoKICAoZnVuY3Rpb24gKE9wY29kZXMpIHsKICAgIC8vIFN0YXRlbWVudHMKICAgIE9wY29kZXNbT3Bjb2Rlc1siVGV4dCJdID0gMF0gPSAiVGV4dCI7CiAgICBPcGNvZGVzW09wY29kZXNbIkFwcGVuZCJdID0gMV0gPSAiQXBwZW5kIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siQ29tbWVudCJdID0gMl0gPSAiQ29tbWVudCI7CiAgICBPcGNvZGVzW09wY29kZXNbIk1vZGlmaWVyIl0gPSAzXSA9ICJNb2RpZmllciI7CiAgICBPcGNvZGVzW09wY29kZXNbIkJsb2NrIl0gPSA0XSA9ICJCbG9jayI7CiAgICBPcGNvZGVzW09wY29kZXNbIkNvbXBvbmVudCJdID0gNV0gPSAiQ29tcG9uZW50IjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siRHluYW1pY0NvbXBvbmVudCJdID0gNl0gPSAiRHluYW1pY0NvbXBvbmVudCI7CiAgICBPcGNvZGVzW09wY29kZXNbIk9wZW5FbGVtZW50Il0gPSA3XSA9ICJPcGVuRWxlbWVudCI7CiAgICBPcGNvZGVzW09wY29kZXNbIkZsdXNoRWxlbWVudCJdID0gOF0gPSAiRmx1c2hFbGVtZW50IjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siQ2xvc2VFbGVtZW50Il0gPSA5XSA9ICJDbG9zZUVsZW1lbnQiOwogICAgT3Bjb2Rlc1tPcGNvZGVzWyJTdGF0aWNBdHRyIl0gPSAxMF0gPSAiU3RhdGljQXR0ciI7CiAgICBPcGNvZGVzW09wY29kZXNbIkR5bmFtaWNBdHRyIl0gPSAxMV0gPSAiRHluYW1pY0F0dHIiOwogICAgT3Bjb2Rlc1tPcGNvZGVzWyJDb21wb25lbnRBdHRyIl0gPSAxMl0gPSAiQ29tcG9uZW50QXR0ciI7CiAgICBPcGNvZGVzW09wY29kZXNbIkF0dHJTcGxhdCJdID0gMTNdID0gIkF0dHJTcGxhdCI7CiAgICBPcGNvZGVzW09wY29kZXNbIllpZWxkIl0gPSAxNF0gPSAiWWllbGQiOwogICAgT3Bjb2Rlc1tPcGNvZGVzWyJQYXJ0aWFsIl0gPSAxNV0gPSAiUGFydGlhbCI7CiAgICBPcGNvZGVzW09wY29kZXNbIkR5bmFtaWNBcmciXSA9IDE2XSA9ICJEeW5hbWljQXJnIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siU3RhdGljQXJnIl0gPSAxN10gPSAiU3RhdGljQXJnIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siVHJ1c3RpbmdBdHRyIl0gPSAxOF0gPSAiVHJ1c3RpbmdBdHRyIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siVHJ1c3RpbmdDb21wb25lbnRBdHRyIl0gPSAxOV0gPSAiVHJ1c3RpbmdDb21wb25lbnRBdHRyIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siRGVidWdnZXIiXSA9IDIwXSA9ICJEZWJ1Z2dlciI7CiAgICBPcGNvZGVzW09wY29kZXNbIkNsaWVudFNpZGVTdGF0ZW1lbnQiXSA9IDIxXSA9ICJDbGllbnRTaWRlU3RhdGVtZW50IjsgLy8gRXhwcmVzc2lvbnMKCiAgICBPcGNvZGVzW09wY29kZXNbIlVua25vd24iXSA9IDIyXSA9ICJVbmtub3duIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siR2V0Il0gPSAyM10gPSAiR2V0IjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siTWF5YmVMb2NhbCJdID0gMjRdID0gIk1heWJlTG9jYWwiOwogICAgT3Bjb2Rlc1tPcGNvZGVzWyJIYXNCbG9jayJdID0gMjVdID0gIkhhc0Jsb2NrIjsKICAgIE9wY29kZXNbT3Bjb2Rlc1siSGFzQmxvY2tQYXJhbXMiXSA9IDI2XSA9ICJIYXNCbG9ja1BhcmFtcyI7CiAgICBPcGNvZGVzW09wY29kZXNbIlVuZGVmaW5lZCJdID0gMjddID0gIlVuZGVmaW5lZCI7CiAgICBPcGNvZGVzW09wY29kZXNbIkhlbHBlciJdID0gMjhdID0gIkhlbHBlciI7CiAgICBPcGNvZGVzW09wY29kZXNbIkNvbmNhdCJdID0gMjldID0gIkNvbmNhdCI7CiAgICBPcGNvZGVzW09wY29kZXNbIkNsaWVudFNpZGVFeHByZXNzaW9uIl0gPSAzMF0gPSAiQ2xpZW50U2lkZUV4cHJlc3Npb24iOwogIH0pKE9wY29kZXMgfHwgKF9leHBvcnRzLk9wcyA9IE9wY29kZXMgPSB7fSkpOwoKICBmdW5jdGlvbiBpcyh2YXJpYW50KSB7CiAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKSAmJiB2YWx1ZVswXSA9PT0gdmFyaWFudDsKICAgIH07CiAgfSAvLyBTdGF0ZW1lbnRzCgoKICB2YXIgaXNGbHVzaEVsZW1lbnQgPSBpcyhPcGNvZGVzLkZsdXNoRWxlbWVudCk7CiAgX2V4cG9ydHMuaXNGbHVzaEVsZW1lbnQgPSBpc0ZsdXNoRWxlbWVudDsKCiAgZnVuY3Rpb24gaXNBdHRyaWJ1dGUodmFsKSB7CiAgICByZXR1cm4gdmFsWzBdID09PSBPcGNvZGVzLlN0YXRpY0F0dHIgfHwgdmFsWzBdID09PSBPcGNvZGVzLkR5bmFtaWNBdHRyIHx8IHZhbFswXSA9PT0gT3Bjb2Rlcy5Db21wb25lbnRBdHRyIHx8IHZhbFswXSA9PT0gT3Bjb2Rlcy5UcnVzdGluZ0F0dHIgfHwgdmFsWzBdID09PSBPcGNvZGVzLlRydXN0aW5nQ29tcG9uZW50QXR0ciB8fCB2YWxbMF0gPT09IE9wY29kZXMuQXR0clNwbGF0IHx8IHZhbFswXSA9PT0gT3Bjb2Rlcy5Nb2RpZmllcjsKICB9CgogIGZ1bmN0aW9uIGlzQXJndW1lbnQodmFsKSB7CiAgICByZXR1cm4gdmFsWzBdID09PSBPcGNvZGVzLlN0YXRpY0FyZyB8fCB2YWxbMF0gPT09IE9wY29kZXMuRHluYW1pY0FyZzsKICB9IC8vIEV4cHJlc3Npb25zCgoKICB2YXIgaXNHZXQgPSBpcyhPcGNvZGVzLkdldCk7CiAgX2V4cG9ydHMuaXNHZXQgPSBpc0dldDsKICB2YXIgaXNNYXliZUxvY2FsID0gaXMoT3Bjb2Rlcy5NYXliZUxvY2FsKTsKICBfZXhwb3J0cy5pc01heWJlTG9jYWwgPSBpc01heWJlTG9jYWw7Cn0pOwpkZWZpbmUoImJhY2tidXJuZXIiLCBbImV4cG9ydHMiLCAiZW1iZXItYmFiZWwiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJCYWJlbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuYnVpbGRQbGF0Zm9ybSA9IGJ1aWxkUGxhdGZvcm07CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKICB2YXIgU0VUX1RJTUVPVVQgPSBzZXRUaW1lb3V0OwoKICB2YXIgTk9PUCA9IGZ1bmN0aW9uIE5PT1AoKSB7fTsKCiAgZnVuY3Rpb24gYnVpbGROZXh0KGZsdXNoKSB7CiAgICAvLyBVc2luZyAicHJvbWlzZXMgZmlyc3QiIGhlcmUgdG86CiAgICAvLwogICAgLy8gMSkgRW5zdXJlIG1vcmUgY29uc2lzdGVudCBleHBlcmllbmNlIG9uIGJyb3dzZXJzIHRoYXQKICAgIC8vICAgIGhhdmUgZGlmZmVyZW50bHkgcXVldWVkIG1pY3JvdGFza3MgKHNlcGFyYXRlIHF1ZXVlcyBmb3IKICAgIC8vICAgIE11dGF0aW9uT2JzZXJ2ZXIgdnMgUHJvbWlzZXMpLgogICAgLy8gMikgRW5zdXJlIGJldHRlciBkZWJ1Z2dpbmcgZXhwZXJpZW5jZXMgKGl0IHNob3dzIHVwIGluIENocm9tZQogICAgLy8gICAgY2FsbCBzdGFjayBhcyAiUHJvbWlzZS50aGVuIChhc3luYykiKSB3aGljaCBpcyBtb3JlIGNvbnNpc3RlbnQKICAgIC8vICAgIHdpdGggdXNlciBleHBlY3RhdGlvbnMKICAgIC8vCiAgICAvLyBXaGVuIFByb21pc2UgaXMgdW5hdmFpbGFibGUgdXNlIE11dGF0aW9uT2JzZXJ2ZXIgKG1vc3RseSBzbyB0aGF0IHdlCiAgICAvLyBzdGlsbCBnZXQgbWljcm90YXNrcyBvbiBJRTExKSwgYW5kIHdoZW4gbmVpdGhlciBNdXRhdGlvbk9ic2VydmVyIGFuZAogICAgLy8gUHJvbWlzZSBhcmUgcHJlc2VudCB1c2UgYSBwbGFpbiBvbGQgc2V0VGltZW91dC4KICAgIGlmICh0eXBlb2YgUHJvbWlzZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICB2YXIgYXV0b3J1blByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTsKICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gYXV0b3J1blByb21pc2UudGhlbihmbHVzaCk7CiAgICAgIH07CiAgICB9IGVsc2UgaWYgKHR5cGVvZiBNdXRhdGlvbk9ic2VydmVyID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIHZhciBpdGVyYXRpb25zID0gMDsKICAgICAgdmFyIG9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoZmx1c2gpOwogICAgICB2YXIgbm9kZSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCcnKTsKICAgICAgb2JzZXJ2ZXIub2JzZXJ2ZShub2RlLCB7CiAgICAgICAgY2hhcmFjdGVyRGF0YTogdHJ1ZQogICAgICB9KTsKICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgICBpdGVyYXRpb25zID0gKytpdGVyYXRpb25zICUgMjsKICAgICAgICBub2RlLmRhdGEgPSAnJyArIGl0ZXJhdGlvbnM7CiAgICAgICAgcmV0dXJuIGl0ZXJhdGlvbnM7CiAgICAgIH07CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBTRVRfVElNRU9VVChmbHVzaCwgMCk7CiAgICAgIH07CiAgICB9CiAgfQoKICBmdW5jdGlvbiBidWlsZFBsYXRmb3JtKGZsdXNoKSB7CiAgICB2YXIgY2xlYXJOZXh0ID0gTk9PUDsKICAgIHJldHVybiB7CiAgICAgIHNldFRpbWVvdXQ6IGZ1bmN0aW9uIChfc2V0VGltZW91dCkgewogICAgICAgIGZ1bmN0aW9uIHNldFRpbWVvdXQoX3gsIF94MikgewogICAgICAgICAgcmV0dXJuIF9zZXRUaW1lb3V0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICAgICAgfQoKICAgICAgICBzZXRUaW1lb3V0LnRvU3RyaW5nID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuIF9zZXRUaW1lb3V0LnRvU3RyaW5nKCk7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQ7CiAgICAgIH0oZnVuY3Rpb24gKGZuLCBtcykgewogICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZuLCBtcyk7CiAgICAgIH0pLAogICAgICBjbGVhclRpbWVvdXQ6IGZ1bmN0aW9uIChfY2xlYXJUaW1lb3V0KSB7CiAgICAgICAgZnVuY3Rpb24gY2xlYXJUaW1lb3V0KF94MykgewogICAgICAgICAgcmV0dXJuIF9jbGVhclRpbWVvdXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgICAgICB9CgogICAgICAgIGNsZWFyVGltZW91dC50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBfY2xlYXJUaW1lb3V0LnRvU3RyaW5nKCk7CiAgICAgICAgfTsKCiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dDsKICAgICAgfShmdW5jdGlvbiAodGltZXJJZCkgewogICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQodGltZXJJZCk7CiAgICAgIH0pLAogICAgICBub3c6IGZ1bmN0aW9uIG5vdygpIHsKICAgICAgICByZXR1cm4gRGF0ZS5ub3coKTsKICAgICAgfSwKICAgICAgbmV4dDogYnVpbGROZXh0KGZsdXNoKSwKICAgICAgY2xlYXJOZXh0OiBjbGVhck5leHQKICAgIH07CiAgfQoKICB2YXIgTlVNQkVSID0gL1xkKy87CiAgdmFyIFRJTUVSU19PRkZTRVQgPSA2OwoKICBmdW5jdGlvbiBpc0NvZXJjYWJsZU51bWJlcihzdXNwZWN0KSB7CiAgICB2YXIgdHlwZSA9IHR5cGVvZiBzdXNwZWN0OwogICAgcmV0dXJuIHR5cGUgPT09ICdudW1iZXInICYmIHN1c3BlY3QgPT09IHN1c3BlY3QgfHwgdHlwZSA9PT0gJ3N0cmluZycgJiYgTlVNQkVSLnRlc3Qoc3VzcGVjdCk7CiAgfQoKICBmdW5jdGlvbiBnZXRPbkVycm9yKG9wdGlvbnMpIHsKICAgIHJldHVybiBvcHRpb25zLm9uRXJyb3IgfHwgb3B0aW9ucy5vbkVycm9yVGFyZ2V0ICYmIG9wdGlvbnMub25FcnJvclRhcmdldFtvcHRpb25zLm9uRXJyb3JNZXRob2RdOwogIH0KCiAgZnVuY3Rpb24gZmluZEl0ZW0odGFyZ2V0LCBtZXRob2QsIGNvbGxlY3Rpb24pIHsKICAgIHZhciBpbmRleCA9IC0xOwoKICAgIGZvciAodmFyIGkgPSAwLCBsID0gY29sbGVjdGlvbi5sZW5ndGg7IGkgPCBsOyBpICs9IDQpIHsKICAgICAgaWYgKGNvbGxlY3Rpb25baV0gPT09IHRhcmdldCAmJiBjb2xsZWN0aW9uW2kgKyAxXSA9PT0gbWV0aG9kKSB7CiAgICAgICAgaW5kZXggPSBpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGluZGV4OwogIH0KCiAgZnVuY3Rpb24gZmluZFRpbWVySXRlbSh0YXJnZXQsIG1ldGhvZCwgY29sbGVjdGlvbikgewogICAgdmFyIGluZGV4ID0gLTE7CgogICAgZm9yICh2YXIgaSA9IDIsIGwgPSBjb2xsZWN0aW9uLmxlbmd0aDsgaSA8IGw7IGkgKz0gNikgewogICAgICBpZiAoY29sbGVjdGlvbltpXSA9PT0gdGFyZ2V0ICYmIGNvbGxlY3Rpb25baSArIDFdID09PSBtZXRob2QpIHsKICAgICAgICBpbmRleCA9IGkgLSAyOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGluZGV4OwogIH0KCiAgZnVuY3Rpb24gZ2V0UXVldWVJdGVtcyhpdGVtcywgcXVldWVJdGVtTGVuZ3RoLCBxdWV1ZUl0ZW1Qb3NpdGlvbk9mZnNldCkgewogICAgaWYgKHF1ZXVlSXRlbVBvc2l0aW9uT2Zmc2V0ID09PSB2b2lkIDApIHsKICAgICAgcXVldWVJdGVtUG9zaXRpb25PZmZzZXQgPSAwOwogICAgfQoKICAgIHZhciBxdWV1ZUl0ZW1zID0gW107CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpdGVtcy5sZW5ndGg7IGkgKz0gcXVldWVJdGVtTGVuZ3RoKSB7CiAgICAgIHZhciBtYXliZUVycm9yID0gaXRlbXNbaSArIDMKICAgICAgLyogc3RhY2sgKi8KICAgICAgKyBxdWV1ZUl0ZW1Qb3NpdGlvbk9mZnNldF07CiAgICAgIHZhciBxdWV1ZUl0ZW0gPSB7CiAgICAgICAgdGFyZ2V0OiBpdGVtc1tpICsgMAogICAgICAgIC8qIHRhcmdldCAqLwogICAgICAgICsgcXVldWVJdGVtUG9zaXRpb25PZmZzZXRdLAogICAgICAgIG1ldGhvZDogaXRlbXNbaSArIDEKICAgICAgICAvKiBtZXRob2QgKi8KICAgICAgICArIHF1ZXVlSXRlbVBvc2l0aW9uT2Zmc2V0XSwKICAgICAgICBhcmdzOiBpdGVtc1tpICsgMgogICAgICAgIC8qIGFyZ3MgKi8KICAgICAgICArIHF1ZXVlSXRlbVBvc2l0aW9uT2Zmc2V0XSwKICAgICAgICBzdGFjazogbWF5YmVFcnJvciAhPT0gdW5kZWZpbmVkICYmICdzdGFjaycgaW4gbWF5YmVFcnJvciA/IG1heWJlRXJyb3Iuc3RhY2sgOiAnJwogICAgICB9OwogICAgICBxdWV1ZUl0ZW1zLnB1c2gocXVldWVJdGVtKTsKICAgIH0KCiAgICByZXR1cm4gcXVldWVJdGVtczsKICB9CgogIGZ1bmN0aW9uIGJpbmFyeVNlYXJjaCh0aW1lLCB0aW1lcnMpIHsKICAgIHZhciBzdGFydCA9IDA7CiAgICB2YXIgZW5kID0gdGltZXJzLmxlbmd0aCAtIFRJTUVSU19PRkZTRVQ7CiAgICB2YXIgbWlkZGxlOwogICAgdmFyIGw7CgogICAgd2hpbGUgKHN0YXJ0IDwgZW5kKSB7CiAgICAgIC8vIHNpbmNlIHRpbWVycyBpcyBhbiBhcnJheSBvZiBwYWlycyAnbCcgd2lsbCBhbHdheXMKICAgICAgLy8gYmUgYW4gaW50ZWdlcgogICAgICBsID0gKGVuZCAtIHN0YXJ0KSAvIFRJTUVSU19PRkZTRVQ7IC8vIGNvbXBlbnNhdGUgZm9yIHRoZSBpbmRleCBpbiBjYXNlIGV2ZW4gbnVtYmVyCiAgICAgIC8vIG9mIHBhaXJzIGluc2lkZSB0aW1lcnMKCiAgICAgIG1pZGRsZSA9IHN0YXJ0ICsgbCAtIGwgJSBUSU1FUlNfT0ZGU0VUOwoKICAgICAgaWYgKHRpbWUgPj0gdGltZXJzW21pZGRsZV0pIHsKICAgICAgICBzdGFydCA9IG1pZGRsZSArIFRJTUVSU19PRkZTRVQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZW5kID0gbWlkZGxlOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHRpbWUgPj0gdGltZXJzW3N0YXJ0XSA/IHN0YXJ0ICsgVElNRVJTX09GRlNFVCA6IHN0YXJ0OwogIH0KCiAgdmFyIFFVRVVFX0lURU1fTEVOR1RIID0gNDsKCiAgdmFyIFF1ZXVlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUXVldWUobmFtZSwgb3B0aW9ucywgZ2xvYmFsT3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICBpZiAoZ2xvYmFsT3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgZ2xvYmFsT3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICB0aGlzLl9xdWV1ZUJlaW5nRmx1c2hlZCA9IFtdOwogICAgICB0aGlzLnRhcmdldFF1ZXVlcyA9IG5ldyBNYXAoKTsKICAgICAgdGhpcy5pbmRleCA9IDA7CiAgICAgIHRoaXMuX3F1ZXVlID0gW107CiAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7CiAgICAgIHRoaXMuZ2xvYmFsT3B0aW9ucyA9IGdsb2JhbE9wdGlvbnM7CiAgICB9CgogICAgdmFyIF9wcm90byA9IFF1ZXVlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uc3RhY2tGb3IgPSBmdW5jdGlvbiBzdGFja0ZvcihpbmRleCkgewogICAgICBpZiAoaW5kZXggPCB0aGlzLl9xdWV1ZS5sZW5ndGgpIHsKICAgICAgICB2YXIgZW50cnkgPSB0aGlzLl9xdWV1ZVtpbmRleCAqIDMgKyBRVUVVRV9JVEVNX0xFTkdUSF07CgogICAgICAgIGlmIChlbnRyeSkgewogICAgICAgICAgcmV0dXJuIGVudHJ5LnN0YWNrOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmZsdXNoID0gZnVuY3Rpb24gZmx1c2goc3luYykgewogICAgICB2YXIgX3RoaXMkb3B0aW9ucyA9IHRoaXMub3B0aW9ucywKICAgICAgICAgIGJlZm9yZSA9IF90aGlzJG9wdGlvbnMuYmVmb3JlLAogICAgICAgICAgYWZ0ZXIgPSBfdGhpcyRvcHRpb25zLmFmdGVyOwogICAgICB2YXIgdGFyZ2V0OwogICAgICB2YXIgbWV0aG9kOwogICAgICB2YXIgYXJnczsKICAgICAgdmFyIGVycm9yUmVjb3JkZWRGb3JTdGFjazsKICAgICAgdGhpcy50YXJnZXRRdWV1ZXMuY2xlYXIoKTsKCiAgICAgIGlmICh0aGlzLl9xdWV1ZUJlaW5nRmx1c2hlZC5sZW5ndGggPT09IDApIHsKICAgICAgICB0aGlzLl9xdWV1ZUJlaW5nRmx1c2hlZCA9IHRoaXMuX3F1ZXVlOwogICAgICAgIHRoaXMuX3F1ZXVlID0gW107CiAgICAgIH0KCiAgICAgIGlmIChiZWZvcmUgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGJlZm9yZSgpOwogICAgICB9CgogICAgICB2YXIgaW52b2tlOwogICAgICB2YXIgcXVldWVJdGVtcyA9IHRoaXMuX3F1ZXVlQmVpbmdGbHVzaGVkOwoKICAgICAgaWYgKHF1ZXVlSXRlbXMubGVuZ3RoID4gMCkgewogICAgICAgIHZhciBvbkVycm9yID0gZ2V0T25FcnJvcih0aGlzLmdsb2JhbE9wdGlvbnMpOwogICAgICAgIGludm9rZSA9IG9uRXJyb3IgPyB0aGlzLmludm9rZVdpdGhPbkVycm9yIDogdGhpcy5pbnZva2U7CgogICAgICAgIGZvciAodmFyIGkgPSB0aGlzLmluZGV4OyBpIDwgcXVldWVJdGVtcy5sZW5ndGg7IGkgKz0gUVVFVUVfSVRFTV9MRU5HVEgpIHsKICAgICAgICAgIHRoaXMuaW5kZXggKz0gUVVFVUVfSVRFTV9MRU5HVEg7CiAgICAgICAgICBtZXRob2QgPSBxdWV1ZUl0ZW1zW2kgKyAxXTsgLy8gbWV0aG9kIGNvdWxkIGhhdmUgYmVlbiBudWxsaWZpZWQgLyBjYW5jZWxlZCBkdXJpbmcgZmx1c2gKCiAgICAgICAgICBpZiAobWV0aG9kICE9PSBudWxsKSB7CiAgICAgICAgICAgIC8vCiAgICAgICAgICAgIC8vICAgICoqIEF0dGVudGlvbiBpbnRyZXBpZCBkZXZlbG9wZXIgKioKICAgICAgICAgICAgLy8KICAgICAgICAgICAgLy8gICAgVG8gZmluZCBvdXQgdGhlIHN0YWNrIG9mIHRoaXMgdGFzayB3aGVuIGl0IHdhcyBzY2hlZHVsZWQgb250bwogICAgICAgICAgICAvLyAgICB0aGUgcnVuIGxvb3AsIGFkZCB0aGUgZm9sbG93aW5nIHRvIHlvdXIgYXBwLmpzOgogICAgICAgICAgICAvLwogICAgICAgICAgICAvLyAgICBFbWJlci5ydW4uYmFja2J1cm5lci5ERUJVRyA9IHRydWU7IC8vIE5PVEU6IFRoaXMgc2xvd3MgeW91ciBhcHAsIGRvbid0IGxlYXZlIGl0IG9uIGluIHByb2R1Y3Rpb24uCiAgICAgICAgICAgIC8vCiAgICAgICAgICAgIC8vICAgIE9uY2UgdGhhdCBpcyBpbiBwbGFjZSwgd2hlbiB5b3UgYXJlIGF0IGEgYnJlYWtwb2ludCBhbmQgbmF2aWdhdGUKICAgICAgICAgICAgLy8gICAgaGVyZSBpbiB0aGUgc3RhY2sgZXhwbG9yZXIsIHlvdSBjYW4gbG9vayBhdCBgZXJyb3JSZWNvcmRlZEZvclN0YWNrLnN0YWNrYCwKICAgICAgICAgICAgLy8gICAgd2hpY2ggd2lsbCBiZSB0aGUgY2FwdHVyZWQgc3RhY2sgd2hlbiB0aGlzIGpvYiB3YXMgc2NoZWR1bGVkLgogICAgICAgICAgICAvLwogICAgICAgICAgICAvLyAgICBPbmUgcG9zc2libGUgbG9uZy10ZXJtIHNvbHV0aW9uIGlzIHRoZSBmb2xsb3dpbmcgQ2hyb21lIGlzc3VlOgogICAgICAgICAgICAvLyAgICAgICBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD0zMzI2MjQKICAgICAgICAgICAgLy8KICAgICAgICAgICAgdGFyZ2V0ID0gcXVldWVJdGVtc1tpXTsKICAgICAgICAgICAgYXJncyA9IHF1ZXVlSXRlbXNbaSArIDJdOwogICAgICAgICAgICBlcnJvclJlY29yZGVkRm9yU3RhY2sgPSBxdWV1ZUl0ZW1zW2kgKyAzXTsgLy8gRGVidWdnaW5nIGFzc2lzdGFuY2UKCiAgICAgICAgICAgIGludm9rZSh0YXJnZXQsIG1ldGhvZCwgYXJncywgb25FcnJvciwgZXJyb3JSZWNvcmRlZEZvclN0YWNrKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAodGhpcy5pbmRleCAhPT0gdGhpcy5fcXVldWVCZWluZ0ZsdXNoZWQubGVuZ3RoICYmIHRoaXMuZ2xvYmFsT3B0aW9ucy5tdXN0WWllbGQgJiYgdGhpcy5nbG9iYWxPcHRpb25zLm11c3RZaWVsZCgpKSB7CiAgICAgICAgICAgIHJldHVybiAxCiAgICAgICAgICAgIC8qIFBhdXNlICovCiAgICAgICAgICAgIDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChhZnRlciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgYWZ0ZXIoKTsKICAgICAgfQoKICAgICAgdGhpcy5fcXVldWVCZWluZ0ZsdXNoZWQubGVuZ3RoID0gMDsKICAgICAgdGhpcy5pbmRleCA9IDA7CgogICAgICBpZiAoc3luYyAhPT0gZmFsc2UgJiYgdGhpcy5fcXVldWUubGVuZ3RoID4gMCkgewogICAgICAgIC8vIGNoZWNrIGlmIG5ldyBpdGVtcyBoYXZlIGJlZW4gYWRkZWQKICAgICAgICB0aGlzLmZsdXNoKHRydWUpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5oYXNXb3JrID0gZnVuY3Rpb24gaGFzV29yaygpIHsKICAgICAgcmV0dXJuIHRoaXMuX3F1ZXVlQmVpbmdGbHVzaGVkLmxlbmd0aCA+IDAgfHwgdGhpcy5fcXVldWUubGVuZ3RoID4gMDsKICAgIH07CgogICAgX3Byb3RvLmNhbmNlbCA9IGZ1bmN0aW9uIGNhbmNlbChfcmVmKSB7CiAgICAgIHZhciB0YXJnZXQgPSBfcmVmLnRhcmdldCwKICAgICAgICAgIG1ldGhvZCA9IF9yZWYubWV0aG9kOwogICAgICB2YXIgcXVldWUgPSB0aGlzLl9xdWV1ZTsKICAgICAgdmFyIHRhcmdldFF1ZXVlTWFwID0gdGhpcy50YXJnZXRRdWV1ZXMuZ2V0KHRhcmdldCk7CgogICAgICBpZiAodGFyZ2V0UXVldWVNYXAgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHRhcmdldFF1ZXVlTWFwLmRlbGV0ZShtZXRob2QpOwogICAgICB9CgogICAgICB2YXIgaW5kZXggPSBmaW5kSXRlbSh0YXJnZXQsIG1ldGhvZCwgcXVldWUpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICBxdWV1ZS5zcGxpY2UoaW5kZXgsIFFVRVVFX0lURU1fTEVOR1RIKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfSAvLyBpZiBub3QgZm91bmQgaW4gY3VycmVudCBxdWV1ZQogICAgICAvLyBjb3VsZCBiZSBpbiB0aGUgcXVldWUgdGhhdCBpcyBiZWluZyBmbHVzaGVkCgoKICAgICAgcXVldWUgPSB0aGlzLl9xdWV1ZUJlaW5nRmx1c2hlZDsKICAgICAgaW5kZXggPSBmaW5kSXRlbSh0YXJnZXQsIG1ldGhvZCwgcXVldWUpOwoKICAgICAgaWYgKGluZGV4ID4gLTEpIHsKICAgICAgICBxdWV1ZVtpbmRleCArIDFdID0gbnVsbDsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfTsKCiAgICBfcHJvdG8ucHVzaCA9IGZ1bmN0aW9uIHB1c2godGFyZ2V0LCBtZXRob2QsIGFyZ3MsIHN0YWNrKSB7CiAgICAgIHRoaXMuX3F1ZXVlLnB1c2godGFyZ2V0LCBtZXRob2QsIGFyZ3MsIHN0YWNrKTsKCiAgICAgIHJldHVybiB7CiAgICAgICAgcXVldWU6IHRoaXMsCiAgICAgICAgdGFyZ2V0OiB0YXJnZXQsCiAgICAgICAgbWV0aG9kOiBtZXRob2QKICAgICAgfTsKICAgIH07CgogICAgX3Byb3RvLnB1c2hVbmlxdWUgPSBmdW5jdGlvbiBwdXNoVW5pcXVlKHRhcmdldCwgbWV0aG9kLCBhcmdzLCBzdGFjaykgewogICAgICB2YXIgbG9jYWxRdWV1ZU1hcCA9IHRoaXMudGFyZ2V0UXVldWVzLmdldCh0YXJnZXQpOwoKICAgICAgaWYgKGxvY2FsUXVldWVNYXAgPT09IHVuZGVmaW5lZCkgewogICAgICAgIGxvY2FsUXVldWVNYXAgPSBuZXcgTWFwKCk7CiAgICAgICAgdGhpcy50YXJnZXRRdWV1ZXMuc2V0KHRhcmdldCwgbG9jYWxRdWV1ZU1hcCk7CiAgICAgIH0KCiAgICAgIHZhciBpbmRleCA9IGxvY2FsUXVldWVNYXAuZ2V0KG1ldGhvZCk7CgogICAgICBpZiAoaW5kZXggPT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhciBxdWV1ZUluZGV4ID0gdGhpcy5fcXVldWUucHVzaCh0YXJnZXQsIG1ldGhvZCwgYXJncywgc3RhY2spIC0gUVVFVUVfSVRFTV9MRU5HVEg7CiAgICAgICAgbG9jYWxRdWV1ZU1hcC5zZXQobWV0aG9kLCBxdWV1ZUluZGV4KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgcXVldWUgPSB0aGlzLl9xdWV1ZTsKICAgICAgICBxdWV1ZVtpbmRleCArIDJdID0gYXJnczsgLy8gcmVwbGFjZSBhcmdzCgogICAgICAgIHF1ZXVlW2luZGV4ICsgM10gPSBzdGFjazsgLy8gcmVwbGFjZSBzdGFjawogICAgICB9CgogICAgICByZXR1cm4gewogICAgICAgIHF1ZXVlOiB0aGlzLAogICAgICAgIHRhcmdldDogdGFyZ2V0LAogICAgICAgIG1ldGhvZDogbWV0aG9kCiAgICAgIH07CiAgICB9OwoKICAgIF9wcm90by5fZ2V0RGVidWdJbmZvID0gZnVuY3Rpb24gX2dldERlYnVnSW5mbyhkZWJ1Z0VuYWJsZWQpIHsKICAgICAgaWYgKGRlYnVnRW5hYmxlZCkgewogICAgICAgIHZhciBkZWJ1Z0luZm8gPSBnZXRRdWV1ZUl0ZW1zKHRoaXMuX3F1ZXVlLCBRVUVVRV9JVEVNX0xFTkdUSCk7CiAgICAgICAgcmV0dXJuIGRlYnVnSW5mbzsKICAgICAgfQoKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH07CgogICAgX3Byb3RvLmludm9rZSA9IGZ1bmN0aW9uIGludm9rZSh0YXJnZXQsIG1ldGhvZCwgYXJncwogICAgLyosIG9uRXJyb3IsIGVycm9yUmVjb3JkZWRGb3JTdGFjayAqLwogICAgKSB7CiAgICAgIGlmIChhcmdzID09PSB1bmRlZmluZWQpIHsKICAgICAgICBtZXRob2QuY2FsbCh0YXJnZXQpOwogICAgICB9IGVsc2UgewogICAgICAgIG1ldGhvZC5hcHBseSh0YXJnZXQsIGFyZ3MpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5pbnZva2VXaXRoT25FcnJvciA9IGZ1bmN0aW9uIGludm9rZVdpdGhPbkVycm9yKHRhcmdldCwgbWV0aG9kLCBhcmdzLCBvbkVycm9yLCBlcnJvclJlY29yZGVkRm9yU3RhY2spIHsKICAgICAgdHJ5IHsKICAgICAgICBpZiAoYXJncyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBtZXRob2QuY2FsbCh0YXJnZXQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBtZXRob2QuYXBwbHkodGFyZ2V0LCBhcmdzKTsKICAgICAgICB9CiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgb25FcnJvcihlcnJvciwgZXJyb3JSZWNvcmRlZEZvclN0YWNrKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gUXVldWU7CiAgfSgpOwoKICB2YXIgRGVmZXJyZWRBY3Rpb25RdWV1ZXMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBEZWZlcnJlZEFjdGlvblF1ZXVlcyhxdWV1ZU5hbWVzLCBvcHRpb25zKSB7CiAgICAgIGlmIChxdWV1ZU5hbWVzID09PSB2b2lkIDApIHsKICAgICAgICBxdWV1ZU5hbWVzID0gW107CiAgICAgIH0KCiAgICAgIHRoaXMucXVldWVzID0ge307CiAgICAgIHRoaXMucXVldWVOYW1lSW5kZXggPSAwOwogICAgICB0aGlzLnF1ZXVlTmFtZXMgPSBxdWV1ZU5hbWVzOwogICAgICBxdWV1ZU5hbWVzLnJlZHVjZShmdW5jdGlvbiAocXVldWVzLCBxdWV1ZU5hbWUpIHsKICAgICAgICBxdWV1ZXNbcXVldWVOYW1lXSA9IG5ldyBRdWV1ZShxdWV1ZU5hbWUsIG9wdGlvbnNbcXVldWVOYW1lXSwgb3B0aW9ucyk7CiAgICAgICAgcmV0dXJuIHF1ZXVlczsKICAgICAgfSwgdGhpcy5xdWV1ZXMpOwogICAgfQogICAgLyoqCiAgICAgKiBAbWV0aG9kIHNjaGVkdWxlCiAgICAgKiBAcGFyYW0ge1N0cmluZ30gcXVldWVOYW1lCiAgICAgKiBAcGFyYW0ge0FueX0gdGFyZ2V0CiAgICAgKiBAcGFyYW0ge0FueX0gbWV0aG9kCiAgICAgKiBAcGFyYW0ge0FueX0gYXJncwogICAgICogQHBhcmFtIHtCb29sZWFufSBvbmNlRmxhZwogICAgICogQHBhcmFtIHtBbnl9IHN0YWNrCiAgICAgKiBAcmV0dXJuIHF1ZXVlCiAgICAgKi8KCgogICAgdmFyIF9wcm90bzIgPSBEZWZlcnJlZEFjdGlvblF1ZXVlcy5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5zY2hlZHVsZSA9IGZ1bmN0aW9uIHNjaGVkdWxlKHF1ZXVlTmFtZSwgdGFyZ2V0LCBtZXRob2QsIGFyZ3MsIG9uY2VGbGFnLCBzdGFjaykgewogICAgICB2YXIgcXVldWVzID0gdGhpcy5xdWV1ZXM7CiAgICAgIHZhciBxdWV1ZSA9IHF1ZXVlc1txdWV1ZU5hbWVdOwoKICAgICAgaWYgKHF1ZXVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIllvdSBhdHRlbXB0ZWQgdG8gc2NoZWR1bGUgYW4gYWN0aW9uIGluIGEgcXVldWUgKCIgKyBxdWV1ZU5hbWUgKyAiKSB0aGF0IGRvZXNuJ3QgZXhpc3QiKTsKICAgICAgfQoKICAgICAgaWYgKG1ldGhvZCA9PT0gdW5kZWZpbmVkIHx8IG1ldGhvZCA9PT0gbnVsbCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiWW91IGF0dGVtcHRlZCB0byBzY2hlZHVsZSBhbiBhY3Rpb24gaW4gYSBxdWV1ZSAoIiArIHF1ZXVlTmFtZSArICIpIGZvciBhIG1ldGhvZCB0aGF0IGRvZXNuJ3QgZXhpc3QiKTsKICAgICAgfQoKICAgICAgdGhpcy5xdWV1ZU5hbWVJbmRleCA9IDA7CgogICAgICBpZiAob25jZUZsYWcpIHsKICAgICAgICByZXR1cm4gcXVldWUucHVzaFVuaXF1ZSh0YXJnZXQsIG1ldGhvZCwgYXJncywgc3RhY2spOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBxdWV1ZS5wdXNoKHRhcmdldCwgbWV0aG9kLCBhcmdzLCBzdGFjayk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogRGVmZXJyZWRBY3Rpb25RdWV1ZXMuZmx1c2goKSBjYWxscyBRdWV1ZS5mbHVzaCgpCiAgICAgKgogICAgICogQG1ldGhvZCBmbHVzaAogICAgICogQHBhcmFtIHtCb29sZWFufSBmcm9tQXV0b3J1bgogICAgICovCiAgICA7CgogICAgX3Byb3RvMi5mbHVzaCA9IGZ1bmN0aW9uIGZsdXNoKGZyb21BdXRvcnVuKSB7CiAgICAgIGlmIChmcm9tQXV0b3J1biA9PT0gdm9pZCAwKSB7CiAgICAgICAgZnJvbUF1dG9ydW4gPSBmYWxzZTsKICAgICAgfQoKICAgICAgdmFyIHF1ZXVlOwogICAgICB2YXIgcXVldWVOYW1lOwogICAgICB2YXIgbnVtYmVyT2ZRdWV1ZXMgPSB0aGlzLnF1ZXVlTmFtZXMubGVuZ3RoOwoKICAgICAgd2hpbGUgKHRoaXMucXVldWVOYW1lSW5kZXggPCBudW1iZXJPZlF1ZXVlcykgewogICAgICAgIHF1ZXVlTmFtZSA9IHRoaXMucXVldWVOYW1lc1t0aGlzLnF1ZXVlTmFtZUluZGV4XTsKICAgICAgICBxdWV1ZSA9IHRoaXMucXVldWVzW3F1ZXVlTmFtZV07CgogICAgICAgIGlmIChxdWV1ZS5oYXNXb3JrKCkgPT09IGZhbHNlKSB7CiAgICAgICAgICB0aGlzLnF1ZXVlTmFtZUluZGV4Kys7CgogICAgICAgICAgaWYgKGZyb21BdXRvcnVuICYmIHRoaXMucXVldWVOYW1lSW5kZXggPCBudW1iZXJPZlF1ZXVlcykgewogICAgICAgICAgICByZXR1cm4gMQogICAgICAgICAgICAvKiBQYXVzZSAqLwogICAgICAgICAgICA7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChxdWV1ZS5mbHVzaChmYWxzZQogICAgICAgICAgLyogYXN5bmMgKi8KICAgICAgICAgICkgPT09IDEKICAgICAgICAgIC8qIFBhdXNlICovCiAgICAgICAgICApIHsKICAgICAgICAgICAgICByZXR1cm4gMQogICAgICAgICAgICAgIC8qIFBhdXNlICovCiAgICAgICAgICAgICAgOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIFJldHVybnMgZGVidWcgaW5mb3JtYXRpb24gZm9yIHRoZSBjdXJyZW50IHF1ZXVlcy4KICAgICAqCiAgICAgKiBAbWV0aG9kIF9nZXREZWJ1Z0luZm8KICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gZGVidWdFbmFibGVkCiAgICAgKiBAcmV0dXJucyB7SURlYnVnSW5mbyB8IHVuZGVmaW5lZH0KICAgICAqLwogICAgOwoKICAgIF9wcm90bzIuX2dldERlYnVnSW5mbyA9IGZ1bmN0aW9uIF9nZXREZWJ1Z0luZm8oZGVidWdFbmFibGVkKSB7CiAgICAgIGlmIChkZWJ1Z0VuYWJsZWQpIHsKICAgICAgICB2YXIgZGVidWdJbmZvID0ge307CiAgICAgICAgdmFyIHF1ZXVlOwogICAgICAgIHZhciBxdWV1ZU5hbWU7CiAgICAgICAgdmFyIG51bWJlck9mUXVldWVzID0gdGhpcy5xdWV1ZU5hbWVzLmxlbmd0aDsKICAgICAgICB2YXIgaSA9IDA7CgogICAgICAgIHdoaWxlIChpIDwgbnVtYmVyT2ZRdWV1ZXMpIHsKICAgICAgICAgIHF1ZXVlTmFtZSA9IHRoaXMucXVldWVOYW1lc1tpXTsKICAgICAgICAgIHF1ZXVlID0gdGhpcy5xdWV1ZXNbcXVldWVOYW1lXTsKICAgICAgICAgIGRlYnVnSW5mb1txdWV1ZU5hbWVdID0gcXVldWUuX2dldERlYnVnSW5mbyhkZWJ1Z0VuYWJsZWQpOwogICAgICAgICAgaSsrOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGRlYnVnSW5mbzsKICAgICAgfQoKICAgICAgcmV0dXJuOwogICAgfTsKCiAgICByZXR1cm4gRGVmZXJyZWRBY3Rpb25RdWV1ZXM7CiAgfSgpOwoKICBmdW5jdGlvbiBpdGVyYXRvckRyYWluKGZuKSB7CiAgICB2YXIgaXRlcmF0b3IgPSBmbigpOwogICAgdmFyIHJlc3VsdCA9IGl0ZXJhdG9yLm5leHQoKTsKCiAgICB3aGlsZSAocmVzdWx0LmRvbmUgPT09IGZhbHNlKSB7CiAgICAgIHJlc3VsdC52YWx1ZSgpOwogICAgICByZXN1bHQgPSBpdGVyYXRvci5uZXh0KCk7CiAgICB9CiAgfQoKICB2YXIgbm9vcCA9IGZ1bmN0aW9uIG5vb3AoKSB7fTsKCiAgdmFyIERJU0FCTEVfU0NIRURVTEUgPSBPYmplY3QuZnJlZXplKFtdKTsKCiAgZnVuY3Rpb24gcGFyc2VBcmdzKCkgewogICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7CiAgICB2YXIgYXJnczsKICAgIHZhciBtZXRob2Q7CiAgICB2YXIgdGFyZ2V0OwoKICAgIGlmIChsZW5ndGggPT09IDApIHt9IGVsc2UgaWYgKGxlbmd0aCA9PT0gMSkgewogICAgICB0YXJnZXQgPSBudWxsOwogICAgICBtZXRob2QgPSBhcmd1bWVudHNbMF07CiAgICB9IGVsc2UgewogICAgICB2YXIgYXJnc0luZGV4ID0gMjsKICAgICAgdmFyIG1ldGhvZE9yVGFyZ2V0ID0gYXJndW1lbnRzWzBdOwogICAgICB2YXIgbWV0aG9kT3JBcmdzID0gYXJndW1lbnRzWzFdOwogICAgICB2YXIgdHlwZSA9IHR5cGVvZiBtZXRob2RPckFyZ3M7CgogICAgICBpZiAodHlwZSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIHRhcmdldCA9IG1ldGhvZE9yVGFyZ2V0OwogICAgICAgIG1ldGhvZCA9IG1ldGhvZE9yQXJnczsKICAgICAgfSBlbHNlIGlmIChtZXRob2RPclRhcmdldCAhPT0gbnVsbCAmJiB0eXBlID09PSAnc3RyaW5nJyAmJiBtZXRob2RPckFyZ3MgaW4gbWV0aG9kT3JUYXJnZXQpIHsKICAgICAgICB0YXJnZXQgPSBtZXRob2RPclRhcmdldDsKICAgICAgICBtZXRob2QgPSB0YXJnZXRbbWV0aG9kT3JBcmdzXTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbWV0aG9kT3JUYXJnZXQgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICBhcmdzSW5kZXggPSAxOwogICAgICAgIHRhcmdldCA9IG51bGw7CiAgICAgICAgbWV0aG9kID0gbWV0aG9kT3JUYXJnZXQ7CiAgICAgIH0KCiAgICAgIGlmIChsZW5ndGggPiBhcmdzSW5kZXgpIHsKICAgICAgICB2YXIgbGVuID0gbGVuZ3RoIC0gYXJnc0luZGV4OwogICAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpICsgYXJnc0luZGV4XTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gW3RhcmdldCwgbWV0aG9kLCBhcmdzXTsKICB9CgogIGZ1bmN0aW9uIHBhcnNlVGltZXJBcmdzKCkgewogICAgdmFyIF9wYXJzZUFyZ3MgPSBwYXJzZUFyZ3MuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpLAogICAgICAgIHRhcmdldCA9IF9wYXJzZUFyZ3NbMF0sCiAgICAgICAgbWV0aG9kID0gX3BhcnNlQXJnc1sxXSwKICAgICAgICBhcmdzID0gX3BhcnNlQXJnc1syXTsKCiAgICB2YXIgd2FpdCA9IDA7CiAgICB2YXIgbGVuZ3RoID0gYXJncyAhPT0gdW5kZWZpbmVkID8gYXJncy5sZW5ndGggOiAwOwoKICAgIGlmIChsZW5ndGggPiAwKSB7CiAgICAgIHZhciBsYXN0ID0gYXJnc1tsZW5ndGggLSAxXTsKCiAgICAgIGlmIChpc0NvZXJjYWJsZU51bWJlcihsYXN0KSkgewogICAgICAgIHdhaXQgPSBwYXJzZUludChhcmdzLnBvcCgpLCAxMCk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gW3RhcmdldCwgbWV0aG9kLCBhcmdzLCB3YWl0XTsKICB9CgogIGZ1bmN0aW9uIHBhcnNlRGVib3VuY2VBcmdzKCkgewogICAgdmFyIHRhcmdldDsKICAgIHZhciBtZXRob2Q7CiAgICB2YXIgaXNJbW1lZGlhdGU7CiAgICB2YXIgYXJnczsKICAgIHZhciB3YWl0OwoKICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyKSB7CiAgICAgIG1ldGhvZCA9IGFyZ3VtZW50c1swXTsKICAgICAgd2FpdCA9IGFyZ3VtZW50c1sxXTsKICAgICAgdGFyZ2V0ID0gbnVsbDsKICAgIH0gZWxzZSB7CiAgICAgIHZhciBfcGFyc2VBcmdzMiA9IHBhcnNlQXJncy5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cyk7CgogICAgICB0YXJnZXQgPSBfcGFyc2VBcmdzMlswXTsKICAgICAgbWV0aG9kID0gX3BhcnNlQXJnczJbMV07CiAgICAgIGFyZ3MgPSBfcGFyc2VBcmdzMlsyXTsKCiAgICAgIGlmIChhcmdzID09PSB1bmRlZmluZWQpIHsKICAgICAgICB3YWl0ID0gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICB3YWl0ID0gYXJncy5wb3AoKTsKCiAgICAgICAgaWYgKCFpc0NvZXJjYWJsZU51bWJlcih3YWl0KSkgewogICAgICAgICAgaXNJbW1lZGlhdGUgPSB3YWl0ID09PSB0cnVlOwogICAgICAgICAgd2FpdCA9IGFyZ3MucG9wKCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgd2FpdCA9IHBhcnNlSW50KHdhaXQsIDEwKTsKICAgIHJldHVybiBbdGFyZ2V0LCBtZXRob2QsIGFyZ3MsIHdhaXQsIGlzSW1tZWRpYXRlXTsKICB9CgogIHZhciBVVUlEID0gMDsKICB2YXIgYmVnaW5Db3VudCA9IDA7CiAgdmFyIGVuZENvdW50ID0gMDsKICB2YXIgYmVnaW5FdmVudENvdW50ID0gMDsKICB2YXIgZW5kRXZlbnRDb3VudCA9IDA7CiAgdmFyIHJ1bkNvdW50ID0gMDsKICB2YXIgam9pbkNvdW50ID0gMDsKICB2YXIgZGVmZXJDb3VudCA9IDA7CiAgdmFyIHNjaGVkdWxlQ291bnQgPSAwOwogIHZhciBzY2hlZHVsZUl0ZXJhYmxlQ291bnQgPSAwOwogIHZhciBkZWZlck9uY2VDb3VudCA9IDA7CiAgdmFyIHNjaGVkdWxlT25jZUNvdW50ID0gMDsKICB2YXIgc2V0VGltZW91dENvdW50ID0gMDsKICB2YXIgbGF0ZXJDb3VudCA9IDA7CiAgdmFyIHRocm90dGxlQ291bnQgPSAwOwogIHZhciBkZWJvdW5jZUNvdW50ID0gMDsKICB2YXIgY2FuY2VsVGltZXJzQ291bnQgPSAwOwogIHZhciBjYW5jZWxDb3VudCA9IDA7CiAgdmFyIGF1dG9ydW5zQ3JlYXRlZENvdW50ID0gMDsKICB2YXIgYXV0b3J1bnNDb21wbGV0ZWRDb3VudCA9IDA7CiAgdmFyIGRlZmVycmVkQWN0aW9uUXVldWVzQ3JlYXRlZENvdW50ID0gMDsKICB2YXIgbmVzdGVkRGVmZXJyZWRBY3Rpb25RdWV1ZXNDcmVhdGVkID0gMDsKCiAgdmFyIEJhY2tidXJuZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBCYWNrYnVybmVyKHF1ZXVlTmFtZXMsIG9wdGlvbnMpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHRoaXMuREVCVUcgPSBmYWxzZTsKICAgICAgdGhpcy5jdXJyZW50SW5zdGFuY2UgPSBudWxsOwogICAgICB0aGlzLmluc3RhbmNlU3RhY2sgPSBbXTsKICAgICAgdGhpcy5fZXZlbnRDYWxsYmFja3MgPSB7CiAgICAgICAgZW5kOiBbXSwKICAgICAgICBiZWdpbjogW10KICAgICAgfTsKICAgICAgdGhpcy5fdGltZXJUaW1lb3V0SWQgPSBudWxsOwogICAgICB0aGlzLl90aW1lcnMgPSBbXTsKICAgICAgdGhpcy5fYXV0b3J1biA9IGZhbHNlOwogICAgICB0aGlzLl9hdXRvcnVuU3RhY2sgPSBudWxsOwogICAgICB0aGlzLnF1ZXVlTmFtZXMgPSBxdWV1ZU5hbWVzOwogICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zIHx8IHt9OwoKICAgICAgaWYgKHR5cGVvZiB0aGlzLm9wdGlvbnMuZGVmYXVsdFF1ZXVlID09PSAnc3RyaW5nJykgewogICAgICAgIHRoaXMuX2RlZmF1bHRRdWV1ZSA9IHRoaXMub3B0aW9ucy5kZWZhdWx0UXVldWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fZGVmYXVsdFF1ZXVlID0gdGhpcy5xdWV1ZU5hbWVzWzBdOwogICAgICB9CgogICAgICB0aGlzLl9vbkJlZ2luID0gdGhpcy5vcHRpb25zLm9uQmVnaW4gfHwgbm9vcDsKICAgICAgdGhpcy5fb25FbmQgPSB0aGlzLm9wdGlvbnMub25FbmQgfHwgbm9vcDsKICAgICAgdGhpcy5fYm91bmRSdW5FeHBpcmVkVGltZXJzID0gdGhpcy5fcnVuRXhwaXJlZFRpbWVycy5iaW5kKHRoaXMpOwoKICAgICAgdGhpcy5fYm91bmRBdXRvcnVuRW5kID0gZnVuY3Rpb24gKCkgewogICAgICAgIGF1dG9ydW5zQ29tcGxldGVkQ291bnQrKzsgLy8gaWYgdGhlIGF1dG9ydW4gd2FzIGFscmVhZHkgZmx1c2hlZCwgZG8gbm90aGluZwoKICAgICAgICBpZiAoX3RoaXMuX2F1dG9ydW4gPT09IGZhbHNlKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBfdGhpcy5fYXV0b3J1biA9IGZhbHNlOwogICAgICAgIF90aGlzLl9hdXRvcnVuU3RhY2sgPSBudWxsOwoKICAgICAgICBfdGhpcy5fZW5kKHRydWUKICAgICAgICAvKiBmcm9tQXV0b3J1biAqLwogICAgICAgICk7CiAgICAgIH07CgogICAgICB2YXIgYnVpbGRlciA9IHRoaXMub3B0aW9ucy5fYnVpbGRQbGF0Zm9ybSB8fCBidWlsZFBsYXRmb3JtOwogICAgICB0aGlzLl9wbGF0Zm9ybSA9IGJ1aWxkZXIodGhpcy5fYm91bmRBdXRvcnVuRW5kKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvMyA9IEJhY2tidXJuZXIucHJvdG90eXBlOwoKICAgIC8qCiAgICAgIEBtZXRob2QgYmVnaW4KICAgICAgQHJldHVybiBpbnN0YW50aWF0ZWQgY2xhc3MgRGVmZXJyZWRBY3Rpb25RdWV1ZXMKICAgICovCiAgICBfcHJvdG8zLmJlZ2luID0gZnVuY3Rpb24gYmVnaW4oKSB7CiAgICAgIGJlZ2luQ291bnQrKzsKICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7CiAgICAgIHZhciBwcmV2aW91c0luc3RhbmNlID0gdGhpcy5jdXJyZW50SW5zdGFuY2U7CiAgICAgIHZhciBjdXJyZW50OwoKICAgICAgaWYgKHRoaXMuX2F1dG9ydW4gIT09IGZhbHNlKSB7CiAgICAgICAgY3VycmVudCA9IHByZXZpb3VzSW5zdGFuY2U7CgogICAgICAgIHRoaXMuX2NhbmNlbEF1dG9ydW4oKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAocHJldmlvdXNJbnN0YW5jZSAhPT0gbnVsbCkgewogICAgICAgICAgbmVzdGVkRGVmZXJyZWRBY3Rpb25RdWV1ZXNDcmVhdGVkKys7CiAgICAgICAgICB0aGlzLmluc3RhbmNlU3RhY2sucHVzaChwcmV2aW91c0luc3RhbmNlKTsKICAgICAgICB9CgogICAgICAgIGRlZmVycmVkQWN0aW9uUXVldWVzQ3JlYXRlZENvdW50Kys7CiAgICAgICAgY3VycmVudCA9IHRoaXMuY3VycmVudEluc3RhbmNlID0gbmV3IERlZmVycmVkQWN0aW9uUXVldWVzKHRoaXMucXVldWVOYW1lcywgb3B0aW9ucyk7CiAgICAgICAgYmVnaW5FdmVudENvdW50Kys7CgogICAgICAgIHRoaXMuX3RyaWdnZXIoJ2JlZ2luJywgY3VycmVudCwgcHJldmlvdXNJbnN0YW5jZSk7CiAgICAgIH0KCiAgICAgIHRoaXMuX29uQmVnaW4oY3VycmVudCwgcHJldmlvdXNJbnN0YW5jZSk7CgogICAgICByZXR1cm4gY3VycmVudDsKICAgIH07CgogICAgX3Byb3RvMy5lbmQgPSBmdW5jdGlvbiBlbmQoKSB7CiAgICAgIGVuZENvdW50Kys7CgogICAgICB0aGlzLl9lbmQoZmFsc2UpOwogICAgfTsKCiAgICBfcHJvdG8zLm9uID0gZnVuY3Rpb24gb24oZXZlbnROYW1lLCBjYWxsYmFjaykgewogICAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2FsbGJhY2sgbXVzdCBiZSBhIGZ1bmN0aW9uIik7CiAgICAgIH0KCiAgICAgIHZhciBjYWxsYmFja3MgPSB0aGlzLl9ldmVudENhbGxiYWNrc1tldmVudE5hbWVdOwoKICAgICAgaWYgKGNhbGxiYWNrcyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgY2FsbGJhY2tzLnB1c2goY2FsbGJhY2spOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIkNhbm5vdCBvbigpIGV2ZW50ICIgKyBldmVudE5hbWUgKyAiIGJlY2F1c2UgaXQgZG9lcyBub3QgZXhpc3QiKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zLm9mZiA9IGZ1bmN0aW9uIG9mZihldmVudE5hbWUsIGNhbGxiYWNrKSB7CiAgICAgIHZhciBjYWxsYmFja3MgPSB0aGlzLl9ldmVudENhbGxiYWNrc1tldmVudE5hbWVdOwoKICAgICAgaWYgKCFldmVudE5hbWUgfHwgY2FsbGJhY2tzID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3Qgb2ZmKCkgZXZlbnQgIiArIGV2ZW50TmFtZSArICIgYmVjYXVzZSBpdCBkb2VzIG5vdCBleGlzdCIpOwogICAgICB9CgogICAgICB2YXIgY2FsbGJhY2tGb3VuZCA9IGZhbHNlOwoKICAgICAgaWYgKGNhbGxiYWNrKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjYWxsYmFja3MubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGlmIChjYWxsYmFja3NbaV0gPT09IGNhbGxiYWNrKSB7CiAgICAgICAgICAgIGNhbGxiYWNrRm91bmQgPSB0cnVlOwogICAgICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpOwogICAgICAgICAgICBpLS07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoIWNhbGxiYWNrRm91bmQpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3Qgb2ZmKCkgY2FsbGJhY2sgdGhhdCBkb2VzIG5vdCBleGlzdCIpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzMucnVuID0gZnVuY3Rpb24gcnVuKCkgewogICAgICBydW5Db3VudCsrOwoKICAgICAgdmFyIF9wYXJzZUFyZ3MzID0gcGFyc2VBcmdzLmFwcGx5KHZvaWQgMCwgYXJndW1lbnRzKSwKICAgICAgICAgIHRhcmdldCA9IF9wYXJzZUFyZ3MzWzBdLAogICAgICAgICAgbWV0aG9kID0gX3BhcnNlQXJnczNbMV0sCiAgICAgICAgICBhcmdzID0gX3BhcnNlQXJnczNbMl07CgogICAgICByZXR1cm4gdGhpcy5fcnVuKHRhcmdldCwgbWV0aG9kLCBhcmdzKTsKICAgIH07CgogICAgX3Byb3RvMy5qb2luID0gZnVuY3Rpb24gam9pbigpIHsKICAgICAgam9pbkNvdW50Kys7CgogICAgICB2YXIgX3BhcnNlQXJnczQgPSBwYXJzZUFyZ3MuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpLAogICAgICAgICAgdGFyZ2V0ID0gX3BhcnNlQXJnczRbMF0sCiAgICAgICAgICBtZXRob2QgPSBfcGFyc2VBcmdzNFsxXSwKICAgICAgICAgIGFyZ3MgPSBfcGFyc2VBcmdzNFsyXTsKCiAgICAgIHJldHVybiB0aGlzLl9qb2luKHRhcmdldCwgbWV0aG9kLCBhcmdzKTsKICAgIH0KICAgIC8qKgogICAgICogQGRlcHJlY2F0ZWQgcGxlYXNlIHVzZSBzY2hlZHVsZSBpbnN0ZWFkLgogICAgICovCiAgICA7CgogICAgX3Byb3RvMy5kZWZlciA9IGZ1bmN0aW9uIGRlZmVyKHF1ZXVlTmFtZSwgdGFyZ2V0LCBtZXRob2QpIHsKICAgICAgZGVmZXJDb3VudCsrOwoKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDMgPyBfbGVuIC0gMyA6IDApLCBfa2V5ID0gMzsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgIGFyZ3NbX2tleSAtIDNdID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5zY2hlZHVsZS5hcHBseSh0aGlzLCBbcXVldWVOYW1lLCB0YXJnZXQsIG1ldGhvZF0uY29uY2F0KGFyZ3MpKTsKICAgIH07CgogICAgX3Byb3RvMy5zY2hlZHVsZSA9IGZ1bmN0aW9uIHNjaGVkdWxlKHF1ZXVlTmFtZSkgewogICAgICBzY2hlZHVsZUNvdW50Kys7CgogICAgICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIF9hcmdzID0gbmV3IEFycmF5KF9sZW4yID4gMSA/IF9sZW4yIC0gMSA6IDApLCBfa2V5MiA9IDE7IF9rZXkyIDwgX2xlbjI7IF9rZXkyKyspIHsKICAgICAgICBfYXJnc1tfa2V5MiAtIDFdID0gYXJndW1lbnRzW19rZXkyXTsKICAgICAgfQoKICAgICAgdmFyIF9wYXJzZUFyZ3M1ID0gcGFyc2VBcmdzLmFwcGx5KHZvaWQgMCwgX2FyZ3MpLAogICAgICAgICAgdGFyZ2V0ID0gX3BhcnNlQXJnczVbMF0sCiAgICAgICAgICBtZXRob2QgPSBfcGFyc2VBcmdzNVsxXSwKICAgICAgICAgIGFyZ3MgPSBfcGFyc2VBcmdzNVsyXTsKCiAgICAgIHZhciBzdGFjayA9IHRoaXMuREVCVUcgPyBuZXcgRXJyb3IoKSA6IHVuZGVmaW5lZDsKICAgICAgcmV0dXJuIHRoaXMuX2Vuc3VyZUluc3RhbmNlKCkuc2NoZWR1bGUocXVldWVOYW1lLCB0YXJnZXQsIG1ldGhvZCwgYXJncywgZmFsc2UsIHN0YWNrKTsKICAgIH0KICAgIC8qCiAgICAgIERlZmVyIHRoZSBwYXNzZWQgaXRlcmFibGUgb2YgZnVuY3Rpb25zIHRvIHJ1biBpbnNpZGUgdGhlIHNwZWNpZmllZCBxdWV1ZS4KICAgICAgICAgQG1ldGhvZCBzY2hlZHVsZUl0ZXJhYmxlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBxdWV1ZU5hbWUKICAgICAgQHBhcmFtIHtJdGVyYWJsZX0gYW4gaXRlcmFibGUgb2YgZnVuY3Rpb25zIHRvIGV4ZWN1dGUKICAgICAgQHJldHVybiBtZXRob2QgcmVzdWx0CiAgICAqLwogICAgOwoKICAgIF9wcm90bzMuc2NoZWR1bGVJdGVyYWJsZSA9IGZ1bmN0aW9uIHNjaGVkdWxlSXRlcmFibGUocXVldWVOYW1lLCBpdGVyYWJsZSkgewogICAgICBzY2hlZHVsZUl0ZXJhYmxlQ291bnQrKzsKICAgICAgdmFyIHN0YWNrID0gdGhpcy5ERUJVRyA/IG5ldyBFcnJvcigpIDogdW5kZWZpbmVkOwogICAgICByZXR1cm4gdGhpcy5fZW5zdXJlSW5zdGFuY2UoKS5zY2hlZHVsZShxdWV1ZU5hbWUsIG51bGwsIGl0ZXJhdG9yRHJhaW4sIFtpdGVyYWJsZV0sIGZhbHNlLCBzdGFjayk7CiAgICB9CiAgICAvKioKICAgICAqIEBkZXByZWNhdGVkIHBsZWFzZSB1c2Ugc2NoZWR1bGVPbmNlIGluc3RlYWQuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8zLmRlZmVyT25jZSA9IGZ1bmN0aW9uIGRlZmVyT25jZShxdWV1ZU5hbWUsIHRhcmdldCwgbWV0aG9kKSB7CiAgICAgIGRlZmVyT25jZUNvdW50Kys7CgogICAgICBmb3IgKHZhciBfbGVuMyA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjMgPiAzID8gX2xlbjMgLSAzIDogMCksIF9rZXkzID0gMzsgX2tleTMgPCBfbGVuMzsgX2tleTMrKykgewogICAgICAgIGFyZ3NbX2tleTMgLSAzXSA9IGFyZ3VtZW50c1tfa2V5M107CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLnNjaGVkdWxlT25jZS5hcHBseSh0aGlzLCBbcXVldWVOYW1lLCB0YXJnZXQsIG1ldGhvZF0uY29uY2F0KGFyZ3MpKTsKICAgIH07CgogICAgX3Byb3RvMy5zY2hlZHVsZU9uY2UgPSBmdW5jdGlvbiBzY2hlZHVsZU9uY2UocXVldWVOYW1lKSB7CiAgICAgIHNjaGVkdWxlT25jZUNvdW50Kys7CgogICAgICBmb3IgKHZhciBfbGVuNCA9IGFyZ3VtZW50cy5sZW5ndGgsIF9hcmdzID0gbmV3IEFycmF5KF9sZW40ID4gMSA/IF9sZW40IC0gMSA6IDApLCBfa2V5NCA9IDE7IF9rZXk0IDwgX2xlbjQ7IF9rZXk0KyspIHsKICAgICAgICBfYXJnc1tfa2V5NCAtIDFdID0gYXJndW1lbnRzW19rZXk0XTsKICAgICAgfQoKICAgICAgdmFyIF9wYXJzZUFyZ3M2ID0gcGFyc2VBcmdzLmFwcGx5KHZvaWQgMCwgX2FyZ3MpLAogICAgICAgICAgdGFyZ2V0ID0gX3BhcnNlQXJnczZbMF0sCiAgICAgICAgICBtZXRob2QgPSBfcGFyc2VBcmdzNlsxXSwKICAgICAgICAgIGFyZ3MgPSBfcGFyc2VBcmdzNlsyXTsKCiAgICAgIHZhciBzdGFjayA9IHRoaXMuREVCVUcgPyBuZXcgRXJyb3IoKSA6IHVuZGVmaW5lZDsKICAgICAgcmV0dXJuIHRoaXMuX2Vuc3VyZUluc3RhbmNlKCkuc2NoZWR1bGUocXVldWVOYW1lLCB0YXJnZXQsIG1ldGhvZCwgYXJncywgdHJ1ZSwgc3RhY2spOwogICAgfTsKCiAgICBfcHJvdG8zLnNldFRpbWVvdXQgPSBmdW5jdGlvbiBzZXRUaW1lb3V0KCkgewogICAgICBzZXRUaW1lb3V0Q291bnQrKzsKICAgICAgcmV0dXJuIHRoaXMubGF0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH07CgogICAgX3Byb3RvMy5sYXRlciA9IGZ1bmN0aW9uIGxhdGVyKCkgewogICAgICBsYXRlckNvdW50Kys7CgogICAgICB2YXIgX3BhcnNlVGltZXJBcmdzID0gcGFyc2VUaW1lckFyZ3MuYXBwbHkodm9pZCAwLCBhcmd1bWVudHMpLAogICAgICAgICAgdGFyZ2V0ID0gX3BhcnNlVGltZXJBcmdzWzBdLAogICAgICAgICAgbWV0aG9kID0gX3BhcnNlVGltZXJBcmdzWzFdLAogICAgICAgICAgYXJncyA9IF9wYXJzZVRpbWVyQXJnc1syXSwKICAgICAgICAgIHdhaXQgPSBfcGFyc2VUaW1lckFyZ3NbM107CgogICAgICByZXR1cm4gdGhpcy5fbGF0ZXIodGFyZ2V0LCBtZXRob2QsIGFyZ3MsIHdhaXQpOwogICAgfTsKCiAgICBfcHJvdG8zLnRocm90dGxlID0gZnVuY3Rpb24gdGhyb3R0bGUoKSB7CiAgICAgIHRocm90dGxlQ291bnQrKzsKCiAgICAgIHZhciBfcGFyc2VEZWJvdW5jZUFyZ3MgPSBwYXJzZURlYm91bmNlQXJncy5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cyksCiAgICAgICAgICB0YXJnZXQgPSBfcGFyc2VEZWJvdW5jZUFyZ3NbMF0sCiAgICAgICAgICBtZXRob2QgPSBfcGFyc2VEZWJvdW5jZUFyZ3NbMV0sCiAgICAgICAgICBhcmdzID0gX3BhcnNlRGVib3VuY2VBcmdzWzJdLAogICAgICAgICAgd2FpdCA9IF9wYXJzZURlYm91bmNlQXJnc1szXSwKICAgICAgICAgIF9wYXJzZURlYm91bmNlQXJncyQgPSBfcGFyc2VEZWJvdW5jZUFyZ3NbNF0sCiAgICAgICAgICBpc0ltbWVkaWF0ZSA9IF9wYXJzZURlYm91bmNlQXJncyQgPT09IHZvaWQgMCA/IHRydWUgOiBfcGFyc2VEZWJvdW5jZUFyZ3MkOwoKICAgICAgdmFyIGluZGV4ID0gZmluZFRpbWVySXRlbSh0YXJnZXQsIG1ldGhvZCwgdGhpcy5fdGltZXJzKTsKICAgICAgdmFyIHRpbWVySWQ7CgogICAgICBpZiAoaW5kZXggPT09IC0xKSB7CiAgICAgICAgdGltZXJJZCA9IHRoaXMuX2xhdGVyKHRhcmdldCwgbWV0aG9kLCBpc0ltbWVkaWF0ZSA/IERJU0FCTEVfU0NIRURVTEUgOiBhcmdzLCB3YWl0KTsKCiAgICAgICAgaWYgKGlzSW1tZWRpYXRlKSB7CiAgICAgICAgICB0aGlzLl9qb2luKHRhcmdldCwgbWV0aG9kLCBhcmdzKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGltZXJJZCA9IHRoaXMuX3RpbWVyc1tpbmRleCArIDFdOwogICAgICAgIHZhciBhcmdJbmRleCA9IGluZGV4ICsgNDsKCiAgICAgICAgaWYgKHRoaXMuX3RpbWVyc1thcmdJbmRleF0gIT09IERJU0FCTEVfU0NIRURVTEUpIHsKICAgICAgICAgIHRoaXMuX3RpbWVyc1thcmdJbmRleF0gPSBhcmdzOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHRpbWVySWQ7CiAgICB9OwoKICAgIF9wcm90bzMuZGVib3VuY2UgPSBmdW5jdGlvbiBkZWJvdW5jZSgpIHsKICAgICAgZGVib3VuY2VDb3VudCsrOwoKICAgICAgdmFyIF9wYXJzZURlYm91bmNlQXJnczIgPSBwYXJzZURlYm91bmNlQXJncy5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cyksCiAgICAgICAgICB0YXJnZXQgPSBfcGFyc2VEZWJvdW5jZUFyZ3MyWzBdLAogICAgICAgICAgbWV0aG9kID0gX3BhcnNlRGVib3VuY2VBcmdzMlsxXSwKICAgICAgICAgIGFyZ3MgPSBfcGFyc2VEZWJvdW5jZUFyZ3MyWzJdLAogICAgICAgICAgd2FpdCA9IF9wYXJzZURlYm91bmNlQXJnczJbM10sCiAgICAgICAgICBfcGFyc2VEZWJvdW5jZUFyZ3MyJCA9IF9wYXJzZURlYm91bmNlQXJnczJbNF0sCiAgICAgICAgICBpc0ltbWVkaWF0ZSA9IF9wYXJzZURlYm91bmNlQXJnczIkID09PSB2b2lkIDAgPyBmYWxzZSA6IF9wYXJzZURlYm91bmNlQXJnczIkOwoKICAgICAgdmFyIF90aW1lcnMgPSB0aGlzLl90aW1lcnM7CiAgICAgIHZhciBpbmRleCA9IGZpbmRUaW1lckl0ZW0odGFyZ2V0LCBtZXRob2QsIF90aW1lcnMpOwogICAgICB2YXIgdGltZXJJZDsKCiAgICAgIGlmIChpbmRleCA9PT0gLTEpIHsKICAgICAgICB0aW1lcklkID0gdGhpcy5fbGF0ZXIodGFyZ2V0LCBtZXRob2QsIGlzSW1tZWRpYXRlID8gRElTQUJMRV9TQ0hFRFVMRSA6IGFyZ3MsIHdhaXQpOwoKICAgICAgICBpZiAoaXNJbW1lZGlhdGUpIHsKICAgICAgICAgIHRoaXMuX2pvaW4odGFyZ2V0LCBtZXRob2QsIGFyZ3MpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgZXhlY3V0ZUF0ID0gdGhpcy5fcGxhdGZvcm0ubm93KCkgKyB3YWl0OwogICAgICAgIHZhciBhcmdJbmRleCA9IGluZGV4ICsgNDsKCiAgICAgICAgaWYgKF90aW1lcnNbYXJnSW5kZXhdID09PSBESVNBQkxFX1NDSEVEVUxFKSB7CiAgICAgICAgICBhcmdzID0gRElTQUJMRV9TQ0hFRFVMRTsKICAgICAgICB9CgogICAgICAgIHRpbWVySWQgPSBfdGltZXJzW2luZGV4ICsgMV07CiAgICAgICAgdmFyIGkgPSBiaW5hcnlTZWFyY2goZXhlY3V0ZUF0LCBfdGltZXJzKTsKCiAgICAgICAgaWYgKGluZGV4ICsgVElNRVJTX09GRlNFVCA9PT0gaSkgewogICAgICAgICAgX3RpbWVyc1tpbmRleF0gPSBleGVjdXRlQXQ7CiAgICAgICAgICBfdGltZXJzW2FyZ0luZGV4XSA9IGFyZ3M7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBzdGFjayA9IHRoaXMuX3RpbWVyc1tpbmRleCArIDVdOwoKICAgICAgICAgIHRoaXMuX3RpbWVycy5zcGxpY2UoaSwgMCwgZXhlY3V0ZUF0LCB0aW1lcklkLCB0YXJnZXQsIG1ldGhvZCwgYXJncywgc3RhY2spOwoKICAgICAgICAgIHRoaXMuX3RpbWVycy5zcGxpY2UoaW5kZXgsIFRJTUVSU19PRkZTRVQpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGluZGV4ID09PSAwKSB7CiAgICAgICAgICB0aGlzLl9yZWluc3RhbGxUaW1lclRpbWVvdXQoKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiB0aW1lcklkOwogICAgfTsKCiAgICBfcHJvdG8zLmNhbmNlbFRpbWVycyA9IGZ1bmN0aW9uIGNhbmNlbFRpbWVycygpIHsKICAgICAgY2FuY2VsVGltZXJzQ291bnQrKzsKCiAgICAgIHRoaXMuX2NsZWFyVGltZXJUaW1lb3V0KCk7CgogICAgICB0aGlzLl90aW1lcnMgPSBbXTsKCiAgICAgIHRoaXMuX2NhbmNlbEF1dG9ydW4oKTsKICAgIH07CgogICAgX3Byb3RvMy5oYXNUaW1lcnMgPSBmdW5jdGlvbiBoYXNUaW1lcnMoKSB7CiAgICAgIHJldHVybiB0aGlzLl90aW1lcnMubGVuZ3RoID4gMCB8fCB0aGlzLl9hdXRvcnVuOwogICAgfTsKCiAgICBfcHJvdG8zLmNhbmNlbCA9IGZ1bmN0aW9uIGNhbmNlbCh0aW1lcikgewogICAgICBjYW5jZWxDb3VudCsrOwoKICAgICAgaWYgKHRpbWVyID09PSBudWxsIHx8IHRpbWVyID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIHZhciB0aW1lclR5cGUgPSB0eXBlb2YgdGltZXI7CgogICAgICBpZiAodGltZXJUeXBlID09PSAnbnVtYmVyJykgewogICAgICAgIC8vIHdlJ3JlIGNhbmNlbGxpbmcgYSBzZXRUaW1lb3V0IG9yIHRocm90dGxlIG9yIGRlYm91bmNlCiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbmNlbExhdGVyVGltZXIodGltZXIpOwogICAgICB9IGVsc2UgaWYgKHRpbWVyVHlwZSA9PT0gJ29iamVjdCcgJiYgdGltZXIucXVldWUgJiYgdGltZXIubWV0aG9kKSB7CiAgICAgICAgLy8gd2UncmUgY2FuY2VsbGluZyBhIGRlZmVyT25jZQogICAgICAgIHJldHVybiB0aW1lci5xdWV1ZS5jYW5jZWwodGltZXIpOwogICAgICB9CgogICAgICByZXR1cm4gZmFsc2U7CiAgICB9OwoKICAgIF9wcm90bzMuZW5zdXJlSW5zdGFuY2UgPSBmdW5jdGlvbiBlbnN1cmVJbnN0YW5jZSgpIHsKICAgICAgdGhpcy5fZW5zdXJlSW5zdGFuY2UoKTsKICAgIH0KICAgIC8qKgogICAgICogUmV0dXJucyBkZWJ1ZyBpbmZvcm1hdGlvbiByZWxhdGVkIHRvIHRoZSBjdXJyZW50IGluc3RhbmNlIG9mIEJhY2tidXJuZXIKICAgICAqCiAgICAgKiBAbWV0aG9kIGdldERlYnVnSW5mbwogICAgICogQHJldHVybnMge09iamVjdCB8IHVuZGVmaW5lZH0gV2lsbCByZXR1cm4gYW5kIE9iamVjdCBjb250YWluaW5nIGRlYnVnIGluZm9ybWF0aW9uIGlmCiAgICAgKiB0aGUgREVCVUcgZmxhZyBpcyBzZXQgdG8gdHJ1ZSBvbiB0aGUgY3VycmVudCBpbnN0YW5jZSBvZiBCYWNrYnVybmVyLCBlbHNlIHVuZGVmaW5lZC4KICAgICAqLwogICAgOwoKICAgIF9wcm90bzMuZ2V0RGVidWdJbmZvID0gZnVuY3Rpb24gZ2V0RGVidWdJbmZvKCkgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIGlmICh0aGlzLkRFQlVHKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGF1dG9ydW46IHRoaXMuX2F1dG9ydW5TdGFjaywKICAgICAgICAgIGNvdW50ZXJzOiB0aGlzLmNvdW50ZXJzLAogICAgICAgICAgdGltZXJzOiBnZXRRdWV1ZUl0ZW1zKHRoaXMuX3RpbWVycywgVElNRVJTX09GRlNFVCwgMiksCiAgICAgICAgICBpbnN0YW5jZVN0YWNrOiBbdGhpcy5jdXJyZW50SW5zdGFuY2VdLmNvbmNhdCh0aGlzLmluc3RhbmNlU3RhY2spLm1hcChmdW5jdGlvbiAoZGVmZXJyZWRBY3Rpb25RdWV1ZSkgewogICAgICAgICAgICByZXR1cm4gZGVmZXJyZWRBY3Rpb25RdWV1ZSAmJiBkZWZlcnJlZEFjdGlvblF1ZXVlLl9nZXREZWJ1Z0luZm8oX3RoaXMyLkRFQlVHKTsKICAgICAgICAgIH0pCiAgICAgICAgfTsKICAgICAgfQoKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH07CgogICAgX3Byb3RvMy5fZW5kID0gZnVuY3Rpb24gX2VuZChmcm9tQXV0b3J1bikgewogICAgICB2YXIgY3VycmVudEluc3RhbmNlID0gdGhpcy5jdXJyZW50SW5zdGFuY2U7CiAgICAgIHZhciBuZXh0SW5zdGFuY2UgPSBudWxsOwoKICAgICAgaWYgKGN1cnJlbnRJbnN0YW5jZSA9PT0gbnVsbCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiZW5kIGNhbGxlZCB3aXRob3V0IGJlZ2luIik7CiAgICAgIH0gLy8gUHJldmVudCBkb3VibGUtZmluYWxseSBidWcgaW4gU2FmYXJpIDYuMC4yIGFuZCBpT1MgNgogICAgICAvLyBUaGlzIGJ1ZyBhcHBlYXJzIHRvIGJlIHJlc29sdmVkIGluIFNhZmFyaSA2LjAuNSBhbmQgaU9TIDcKCgogICAgICB2YXIgZmluYWxseUFscmVhZHlDYWxsZWQgPSBmYWxzZTsKICAgICAgdmFyIHJlc3VsdDsKCiAgICAgIHRyeSB7CiAgICAgICAgcmVzdWx0ID0gY3VycmVudEluc3RhbmNlLmZsdXNoKGZyb21BdXRvcnVuKTsKICAgICAgfSBmaW5hbGx5IHsKICAgICAgICBpZiAoIWZpbmFsbHlBbHJlYWR5Q2FsbGVkKSB7CiAgICAgICAgICBmaW5hbGx5QWxyZWFkeUNhbGxlZCA9IHRydWU7CgogICAgICAgICAgaWYgKHJlc3VsdCA9PT0gMQogICAgICAgICAgLyogUGF1c2UgKi8KICAgICAgICAgICkgewogICAgICAgICAgICAgIHZhciBwbGFubmVkTmV4dFF1ZXVlID0gdGhpcy5xdWV1ZU5hbWVzW2N1cnJlbnRJbnN0YW5jZS5xdWV1ZU5hbWVJbmRleF07CgogICAgICAgICAgICAgIHRoaXMuX3NjaGVkdWxlQXV0b3J1bihwbGFubmVkTmV4dFF1ZXVlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGhpcy5jdXJyZW50SW5zdGFuY2UgPSBudWxsOwoKICAgICAgICAgICAgaWYgKHRoaXMuaW5zdGFuY2VTdGFjay5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgbmV4dEluc3RhbmNlID0gdGhpcy5pbnN0YW5jZVN0YWNrLnBvcCgpOwogICAgICAgICAgICAgIHRoaXMuY3VycmVudEluc3RhbmNlID0gbmV4dEluc3RhbmNlOwogICAgICAgICAgICB9CgogICAgICAgICAgICB0aGlzLl90cmlnZ2VyKCdlbmQnLCBjdXJyZW50SW5zdGFuY2UsIG5leHRJbnN0YW5jZSk7CgogICAgICAgICAgICB0aGlzLl9vbkVuZChjdXJyZW50SW5zdGFuY2UsIG5leHRJbnN0YW5jZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzMuX2pvaW4gPSBmdW5jdGlvbiBfam9pbih0YXJnZXQsIG1ldGhvZCwgYXJncykgewogICAgICBpZiAodGhpcy5jdXJyZW50SW5zdGFuY2UgPT09IG51bGwpIHsKICAgICAgICByZXR1cm4gdGhpcy5fcnVuKHRhcmdldCwgbWV0aG9kLCBhcmdzKTsKICAgICAgfQoKICAgICAgaWYgKHRhcmdldCA9PT0gdW5kZWZpbmVkICYmIGFyZ3MgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBtZXRob2QoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbWV0aG9kLmFwcGx5KHRhcmdldCwgYXJncyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMy5fcnVuID0gZnVuY3Rpb24gX3J1bih0YXJnZXQsIG1ldGhvZCwgYXJncykgewogICAgICB2YXIgb25FcnJvciA9IGdldE9uRXJyb3IodGhpcy5vcHRpb25zKTsKICAgICAgdGhpcy5iZWdpbigpOwoKICAgICAgaWYgKG9uRXJyb3IpIHsKICAgICAgICB0cnkgewogICAgICAgICAgcmV0dXJuIG1ldGhvZC5hcHBseSh0YXJnZXQsIGFyZ3MpOwogICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICBvbkVycm9yKGVycm9yKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgdGhpcy5lbmQoKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHJldHVybiBtZXRob2QuYXBwbHkodGFyZ2V0LCBhcmdzKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgdGhpcy5lbmQoKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMy5fY2FuY2VsQXV0b3J1biA9IGZ1bmN0aW9uIF9jYW5jZWxBdXRvcnVuKCkgewogICAgICBpZiAodGhpcy5fYXV0b3J1bikgewogICAgICAgIHRoaXMuX3BsYXRmb3JtLmNsZWFyTmV4dCgpOwoKICAgICAgICB0aGlzLl9hdXRvcnVuID0gZmFsc2U7CiAgICAgICAgdGhpcy5fYXV0b3J1blN0YWNrID0gbnVsbDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zLl9sYXRlciA9IGZ1bmN0aW9uIF9sYXRlcih0YXJnZXQsIG1ldGhvZCwgYXJncywgd2FpdCkgewogICAgICB2YXIgc3RhY2sgPSB0aGlzLkRFQlVHID8gbmV3IEVycm9yKCkgOiB1bmRlZmluZWQ7CiAgICAgIHZhciBleGVjdXRlQXQgPSB0aGlzLl9wbGF0Zm9ybS5ub3coKSArIHdhaXQ7CiAgICAgIHZhciBpZCA9IFVVSUQrKzsKCiAgICAgIGlmICh0aGlzLl90aW1lcnMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgdGhpcy5fdGltZXJzLnB1c2goZXhlY3V0ZUF0LCBpZCwgdGFyZ2V0LCBtZXRob2QsIGFyZ3MsIHN0YWNrKTsKCiAgICAgICAgdGhpcy5faW5zdGFsbFRpbWVyVGltZW91dCgpOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIGZpbmQgcG9zaXRpb24gdG8gaW5zZXJ0CiAgICAgICAgdmFyIGkgPSBiaW5hcnlTZWFyY2goZXhlY3V0ZUF0LCB0aGlzLl90aW1lcnMpOwoKICAgICAgICB0aGlzLl90aW1lcnMuc3BsaWNlKGksIDAsIGV4ZWN1dGVBdCwgaWQsIHRhcmdldCwgbWV0aG9kLCBhcmdzLCBzdGFjayk7IC8vIGFsd2F5cyByZWluc3RhbGwgc2luY2UgaXQgY291bGQgYmUgb3V0IG9mIHN5bmMKCgogICAgICAgIHRoaXMuX3JlaW5zdGFsbFRpbWVyVGltZW91dCgpOwogICAgICB9CgogICAgICByZXR1cm4gaWQ7CiAgICB9OwoKICAgIF9wcm90bzMuX2NhbmNlbExhdGVyVGltZXIgPSBmdW5jdGlvbiBfY2FuY2VsTGF0ZXJUaW1lcih0aW1lcikgewogICAgICBmb3IgKHZhciBpID0gMTsgaSA8IHRoaXMuX3RpbWVycy5sZW5ndGg7IGkgKz0gVElNRVJTX09GRlNFVCkgewogICAgICAgIGlmICh0aGlzLl90aW1lcnNbaV0gPT09IHRpbWVyKSB7CiAgICAgICAgICB0aGlzLl90aW1lcnMuc3BsaWNlKGkgLSAxLCBUSU1FUlNfT0ZGU0VUKTsKCiAgICAgICAgICBpZiAoaSA9PT0gMSkgewogICAgICAgICAgICB0aGlzLl9yZWluc3RhbGxUaW1lclRpbWVvdXQoKTsKICAgICAgICAgIH0KCiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIC8qKgogICAgIFRyaWdnZXIgYW4gZXZlbnQuIFN1cHBvcnRzIHVwIHRvIHR3byBhcmd1bWVudHMuIERlc2lnbmVkIGFyb3VuZAogICAgIHRyaWdnZXJpbmcgdHJhbnNpdGlvbiBldmVudHMgZnJvbSBvbmUgcnVuIGxvb3AgaW5zdGFuY2UgdG8gdGhlCiAgICAgbmV4dCwgd2hpY2ggcmVxdWlyZXMgYW4gYXJndW1lbnQgZm9yIHRoZSAgaW5zdGFuY2UgYW5kIHRoZW4KICAgICBhbiBhcmd1bWVudCBmb3IgdGhlIG5leHQgaW5zdGFuY2UuCiAgICAgICAgQHByaXZhdGUKICAgICBAbWV0aG9kIF90cmlnZ2VyCiAgICAgQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZQogICAgIEBwYXJhbSB7YW55fSBhcmcxCiAgICAgQHBhcmFtIHthbnl9IGFyZzIKICAgICAqLwogICAgOwoKICAgIF9wcm90bzMuX3RyaWdnZXIgPSBmdW5jdGlvbiBfdHJpZ2dlcihldmVudE5hbWUsIGFyZzEsIGFyZzIpIHsKICAgICAgdmFyIGNhbGxiYWNrcyA9IHRoaXMuX2V2ZW50Q2FsbGJhY2tzW2V2ZW50TmFtZV07CgogICAgICBpZiAoY2FsbGJhY2tzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNhbGxiYWNrcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgY2FsbGJhY2tzW2ldKGFyZzEsIGFyZzIpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8zLl9ydW5FeHBpcmVkVGltZXJzID0gZnVuY3Rpb24gX3J1bkV4cGlyZWRUaW1lcnMoKSB7CiAgICAgIHRoaXMuX3RpbWVyVGltZW91dElkID0gbnVsbDsKCiAgICAgIGlmICh0aGlzLl90aW1lcnMubGVuZ3RoID4gMCkgewogICAgICAgIHRoaXMuYmVnaW4oKTsKCiAgICAgICAgdGhpcy5fc2NoZWR1bGVFeHBpcmVkVGltZXJzKCk7CgogICAgICAgIHRoaXMuZW5kKCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvMy5fc2NoZWR1bGVFeHBpcmVkVGltZXJzID0gZnVuY3Rpb24gX3NjaGVkdWxlRXhwaXJlZFRpbWVycygpIHsKICAgICAgdmFyIHRpbWVycyA9IHRoaXMuX3RpbWVyczsKICAgICAgdmFyIGkgPSAwOwogICAgICB2YXIgbCA9IHRpbWVycy5sZW5ndGg7CiAgICAgIHZhciBkZWZhdWx0UXVldWUgPSB0aGlzLl9kZWZhdWx0UXVldWU7CgogICAgICB2YXIgbiA9IHRoaXMuX3BsYXRmb3JtLm5vdygpOwoKICAgICAgZm9yICg7IGkgPCBsOyBpICs9IFRJTUVSU19PRkZTRVQpIHsKICAgICAgICB2YXIgZXhlY3V0ZUF0ID0gdGltZXJzW2ldOwoKICAgICAgICBpZiAoZXhlY3V0ZUF0ID4gbikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICB2YXIgYXJncyA9IHRpbWVyc1tpICsgNF07CgogICAgICAgIGlmIChhcmdzICE9PSBESVNBQkxFX1NDSEVEVUxFKSB7CiAgICAgICAgICB2YXIgdGFyZ2V0ID0gdGltZXJzW2kgKyAyXTsKICAgICAgICAgIHZhciBtZXRob2QgPSB0aW1lcnNbaSArIDNdOwogICAgICAgICAgdmFyIHN0YWNrID0gdGltZXJzW2kgKyA1XTsKICAgICAgICAgIHRoaXMuY3VycmVudEluc3RhbmNlLnNjaGVkdWxlKGRlZmF1bHRRdWV1ZSwgdGFyZ2V0LCBtZXRob2QsIGFyZ3MsIGZhbHNlLCBzdGFjayk7CiAgICAgICAgfQogICAgICB9CgogICAgICB0aW1lcnMuc3BsaWNlKDAsIGkpOwoKICAgICAgdGhpcy5faW5zdGFsbFRpbWVyVGltZW91dCgpOwogICAgfTsKCiAgICBfcHJvdG8zLl9yZWluc3RhbGxUaW1lclRpbWVvdXQgPSBmdW5jdGlvbiBfcmVpbnN0YWxsVGltZXJUaW1lb3V0KCkgewogICAgICB0aGlzLl9jbGVhclRpbWVyVGltZW91dCgpOwoKICAgICAgdGhpcy5faW5zdGFsbFRpbWVyVGltZW91dCgpOwogICAgfTsKCiAgICBfcHJvdG8zLl9jbGVhclRpbWVyVGltZW91dCA9IGZ1bmN0aW9uIF9jbGVhclRpbWVyVGltZW91dCgpIHsKICAgICAgaWYgKHRoaXMuX3RpbWVyVGltZW91dElkID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9wbGF0Zm9ybS5jbGVhclRpbWVvdXQodGhpcy5fdGltZXJUaW1lb3V0SWQpOwoKICAgICAgdGhpcy5fdGltZXJUaW1lb3V0SWQgPSBudWxsOwogICAgfTsKCiAgICBfcHJvdG8zLl9pbnN0YWxsVGltZXJUaW1lb3V0ID0gZnVuY3Rpb24gX2luc3RhbGxUaW1lclRpbWVvdXQoKSB7CiAgICAgIGlmICh0aGlzLl90aW1lcnMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgbWluRXhwaXJlc0F0ID0gdGhpcy5fdGltZXJzWzBdOwoKICAgICAgdmFyIG4gPSB0aGlzLl9wbGF0Zm9ybS5ub3coKTsKCiAgICAgIHZhciB3YWl0ID0gTWF0aC5tYXgoMCwgbWluRXhwaXJlc0F0IC0gbik7CiAgICAgIHRoaXMuX3RpbWVyVGltZW91dElkID0gdGhpcy5fcGxhdGZvcm0uc2V0VGltZW91dCh0aGlzLl9ib3VuZFJ1bkV4cGlyZWRUaW1lcnMsIHdhaXQpOwogICAgfTsKCiAgICBfcHJvdG8zLl9lbnN1cmVJbnN0YW5jZSA9IGZ1bmN0aW9uIF9lbnN1cmVJbnN0YW5jZSgpIHsKICAgICAgdmFyIGN1cnJlbnRJbnN0YW5jZSA9IHRoaXMuY3VycmVudEluc3RhbmNlOwoKICAgICAgaWYgKGN1cnJlbnRJbnN0YW5jZSA9PT0gbnVsbCkgewogICAgICAgIHRoaXMuX2F1dG9ydW5TdGFjayA9IHRoaXMuREVCVUcgPyBuZXcgRXJyb3IoKSA6IHVuZGVmaW5lZDsKICAgICAgICBjdXJyZW50SW5zdGFuY2UgPSB0aGlzLmJlZ2luKCk7CgogICAgICAgIHRoaXMuX3NjaGVkdWxlQXV0b3J1bih0aGlzLnF1ZXVlTmFtZXNbMF0pOwogICAgICB9CgogICAgICByZXR1cm4gY3VycmVudEluc3RhbmNlOwogICAgfTsKCiAgICBfcHJvdG8zLl9zY2hlZHVsZUF1dG9ydW4gPSBmdW5jdGlvbiBfc2NoZWR1bGVBdXRvcnVuKHBsYW5uZWROZXh0UXVldWUpIHsKICAgICAgYXV0b3J1bnNDcmVhdGVkQ291bnQrKzsKICAgICAgdmFyIG5leHQgPSB0aGlzLl9wbGF0Zm9ybS5uZXh0OwogICAgICB2YXIgZmx1c2ggPSB0aGlzLm9wdGlvbnMuZmx1c2g7CgogICAgICBpZiAoZmx1c2gpIHsKICAgICAgICBmbHVzaChwbGFubmVkTmV4dFF1ZXVlLCBuZXh0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBuZXh0KCk7CiAgICAgIH0KCiAgICAgIHRoaXMuX2F1dG9ydW4gPSB0cnVlOwogICAgfTsKCiAgICAoMCwgX2VtYmVyQmFiZWwuY3JlYXRlQ2xhc3MpKEJhY2tidXJuZXIsIFt7CiAgICAgIGtleTogImNvdW50ZXJzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGJlZ2luOiBiZWdpbkNvdW50LAogICAgICAgICAgZW5kOiBlbmRDb3VudCwKICAgICAgICAgIGV2ZW50czogewogICAgICAgICAgICBiZWdpbjogYmVnaW5FdmVudENvdW50LAogICAgICAgICAgICBlbmQ6IGVuZEV2ZW50Q291bnQKICAgICAgICAgIH0sCiAgICAgICAgICBhdXRvcnVuczogewogICAgICAgICAgICBjcmVhdGVkOiBhdXRvcnVuc0NyZWF0ZWRDb3VudCwKICAgICAgICAgICAgY29tcGxldGVkOiBhdXRvcnVuc0NvbXBsZXRlZENvdW50CiAgICAgICAgICB9LAogICAgICAgICAgcnVuOiBydW5Db3VudCwKICAgICAgICAgIGpvaW46IGpvaW5Db3VudCwKICAgICAgICAgIGRlZmVyOiBkZWZlckNvdW50LAogICAgICAgICAgc2NoZWR1bGU6IHNjaGVkdWxlQ291bnQsCiAgICAgICAgICBzY2hlZHVsZUl0ZXJhYmxlOiBzY2hlZHVsZUl0ZXJhYmxlQ291bnQsCiAgICAgICAgICBkZWZlck9uY2U6IGRlZmVyT25jZUNvdW50LAogICAgICAgICAgc2NoZWR1bGVPbmNlOiBzY2hlZHVsZU9uY2VDb3VudCwKICAgICAgICAgIHNldFRpbWVvdXQ6IHNldFRpbWVvdXRDb3VudCwKICAgICAgICAgIGxhdGVyOiBsYXRlckNvdW50LAogICAgICAgICAgdGhyb3R0bGU6IHRocm90dGxlQ291bnQsCiAgICAgICAgICBkZWJvdW5jZTogZGVib3VuY2VDb3VudCwKICAgICAgICAgIGNhbmNlbFRpbWVyczogY2FuY2VsVGltZXJzQ291bnQsCiAgICAgICAgICBjYW5jZWw6IGNhbmNlbENvdW50LAogICAgICAgICAgbG9vcHM6IHsKICAgICAgICAgICAgdG90YWw6IGRlZmVycmVkQWN0aW9uUXVldWVzQ3JlYXRlZENvdW50LAogICAgICAgICAgICBuZXN0ZWQ6IG5lc3RlZERlZmVycmVkQWN0aW9uUXVldWVzQ3JlYXRlZAogICAgICAgICAgfQogICAgICAgIH07CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiZGVmYXVsdFF1ZXVlIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2RlZmF1bHRRdWV1ZTsKICAgICAgfQogICAgfV0pOwogICAgcmV0dXJuIEJhY2tidXJuZXI7CiAgfSgpOwoKICBCYWNrYnVybmVyLlF1ZXVlID0gUXVldWU7CiAgQmFja2J1cm5lci5idWlsZFBsYXRmb3JtID0gYnVpbGRQbGF0Zm9ybTsKICBCYWNrYnVybmVyLmJ1aWxkTmV4dCA9IGJ1aWxkTmV4dDsKICB2YXIgX2RlZmF1bHQgPSBCYWNrYnVybmVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgiZGFnLW1hcCIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAqIEEgdG9wb2xvZ2ljYWxseSBvcmRlcmVkIG1hcCBvZiBrZXkvdmFsdWUgcGFpcnMgd2l0aCBhIHNpbXBsZSBBUEkgZm9yIGFkZGluZyBjb25zdHJhaW50cy4KICAgKgogICAqIEVkZ2VzIGNhbiBmb3J3YXJkIHJlZmVyZW5jZSBrZXlzIHRoYXQgaGF2ZSBub3QgYmVlbiBhZGRlZCB5ZXQgKHRoZSBmb3J3YXJkIHJlZmVyZW5jZSB3aWxsCiAgICogbWFwIHRoZSBrZXkgdG8gdW5kZWZpbmVkKS4KICAgKi8KICB2YXIgREFHID0gZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gREFHKCkgewogICAgICB0aGlzLl92ZXJ0aWNlcyA9IG5ldyBWZXJ0aWNlcygpOwogICAgfQogICAgLyoqCiAgICAgKiBBZGRzIGEga2V5L3ZhbHVlIHBhaXIgd2l0aCBkZXBlbmRlbmNpZXMgb24gb3RoZXIga2V5L3ZhbHVlIHBhaXJzLgogICAgICoKICAgICAqIEBwdWJsaWMKICAgICAqIEBwYXJhbSBrZXkgICAgVGhlIGtleSBvZiB0aGUgdmVydGV4IHRvIGJlIGFkZGVkLgogICAgICogQHBhcmFtIHZhbHVlICBUaGUgdmFsdWUgb2YgdGhhdCB2ZXJ0ZXguCiAgICAgKiBAcGFyYW0gYmVmb3JlIEEga2V5IG9yIGFycmF5IG9mIGtleXMgb2YgdGhlIHZlcnRpY2VzIHRoYXQgbXVzdAogICAgICogICAgICAgICAgICAgICBiZSB2aXNpdGVkIGJlZm9yZSB0aGlzIHZlcnRleC4KICAgICAqIEBwYXJhbSBhZnRlciAgQW4gc3RyaW5nIG9yIGFycmF5IG9mIHN0cmluZ3Mgd2l0aCB0aGUga2V5cyBvZiB0aGUKICAgICAqICAgICAgICAgICAgICAgdmVydGljZXMgdGhhdCBtdXN0IGJlIGFmdGVyIHRoaXMgdmVydGV4IGlzIHZpc2l0ZWQuCiAgICAgKi8KCgogICAgREFHLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSwgYmVmb3JlLCBhZnRlcikgewogICAgICBpZiAoIWtleSkgdGhyb3cgbmV3IEVycm9yKCdhcmd1bWVudCBga2V5YCBpcyByZXF1aXJlZCcpOwogICAgICB2YXIgdmVydGljZXMgPSB0aGlzLl92ZXJ0aWNlczsKICAgICAgdmFyIHYgPSB2ZXJ0aWNlcy5hZGQoa2V5KTsKICAgICAgdi52YWwgPSB2YWx1ZTsKCiAgICAgIGlmIChiZWZvcmUpIHsKICAgICAgICBpZiAodHlwZW9mIGJlZm9yZSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgIHZlcnRpY2VzLmFkZEVkZ2UodiwgdmVydGljZXMuYWRkKGJlZm9yZSkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJlZm9yZS5sZW5ndGg7IGkrKykgewogICAgICAgICAgICB2ZXJ0aWNlcy5hZGRFZGdlKHYsIHZlcnRpY2VzLmFkZChiZWZvcmVbaV0pKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChhZnRlcikgewogICAgICAgIGlmICh0eXBlb2YgYWZ0ZXIgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICB2ZXJ0aWNlcy5hZGRFZGdlKHZlcnRpY2VzLmFkZChhZnRlciksIHYpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFmdGVyLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHZlcnRpY2VzLmFkZEVkZ2UodmVydGljZXMuYWRkKGFmdGVyW2ldKSwgdik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwogICAgLyoqCiAgICAgKiBAZGVwcmVjYXRlZCBwbGVhc2UgdXNlIGFkZC4KICAgICAqLwoKCiAgICBEQUcucHJvdG90eXBlLmFkZEVkZ2VzID0gZnVuY3Rpb24gKGtleSwgdmFsdWUsIGJlZm9yZSwgYWZ0ZXIpIHsKICAgICAgdGhpcy5hZGQoa2V5LCB2YWx1ZSwgYmVmb3JlLCBhZnRlcik7CiAgICB9OwogICAgLyoqCiAgICAgKiBWaXNpdHMga2V5L3ZhbHVlIHBhaXJzIGluIHRvcG9sb2dpY2FsIG9yZGVyLgogICAgICoKICAgICAqIEBwdWJsaWMKICAgICAqIEBwYXJhbSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gYmUgaW52b2tlZCB3aXRoIGVhY2gga2V5L3ZhbHVlLgogICAgICovCgoKICAgIERBRy5wcm90b3R5cGUuZWFjaCA9IGZ1bmN0aW9uIChjYWxsYmFjaykgewogICAgICB0aGlzLl92ZXJ0aWNlcy53YWxrKGNhbGxiYWNrKTsKICAgIH07CiAgICAvKioKICAgICAqIEBkZXByZWNhdGVkIHBsZWFzZSB1c2UgZWFjaC4KICAgICAqLwoKCiAgICBEQUcucHJvdG90eXBlLnRvcHNvcnQgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHsKICAgICAgdGhpcy5lYWNoKGNhbGxiYWNrKTsKICAgIH07CgogICAgcmV0dXJuIERBRzsKICB9KCk7CgogIHZhciBfZGVmYXVsdCA9IERBRzsKICAvKiogQHByaXZhdGUgKi8KCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OwoKICB2YXIgVmVydGljZXMgPSBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBWZXJ0aWNlcygpIHsKICAgICAgdGhpcy5sZW5ndGggPSAwOwogICAgICB0aGlzLnN0YWNrID0gbmV3IEludFN0YWNrKCk7CiAgICAgIHRoaXMucGF0aCA9IG5ldyBJbnRTdGFjaygpOwogICAgICB0aGlzLnJlc3VsdCA9IG5ldyBJbnRTdGFjaygpOwogICAgfQoKICAgIFZlcnRpY2VzLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAoa2V5KSB7CiAgICAgIGlmICgha2V5KSB0aHJvdyBuZXcgRXJyb3IoIm1pc3Npbmcga2V5Iik7CiAgICAgIHZhciBsID0gdGhpcy5sZW5ndGggfCAwOwogICAgICB2YXIgdmVydGV4OwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHsKICAgICAgICB2ZXJ0ZXggPSB0aGlzW2ldOwogICAgICAgIGlmICh2ZXJ0ZXgua2V5ID09PSBrZXkpIHJldHVybiB2ZXJ0ZXg7CiAgICAgIH0KCiAgICAgIHRoaXMubGVuZ3RoID0gbCArIDE7CiAgICAgIHJldHVybiB0aGlzW2xdID0gewogICAgICAgIGlkeDogbCwKICAgICAgICBrZXk6IGtleSwKICAgICAgICB2YWw6IHVuZGVmaW5lZCwKICAgICAgICBvdXQ6IGZhbHNlLAogICAgICAgIGZsYWc6IGZhbHNlLAogICAgICAgIGxlbmd0aDogMAogICAgICB9OwogICAgfTsKCiAgICBWZXJ0aWNlcy5wcm90b3R5cGUuYWRkRWRnZSA9IGZ1bmN0aW9uICh2LCB3KSB7CiAgICAgIHRoaXMuY2hlY2sodiwgdy5rZXkpOwogICAgICB2YXIgbCA9IHcubGVuZ3RoIHwgMDsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgaWYgKHdbaV0gPT09IHYuaWR4KSByZXR1cm47CiAgICAgIH0KCiAgICAgIHcubGVuZ3RoID0gbCArIDE7CiAgICAgIHdbbF0gPSB2LmlkeDsKICAgICAgdi5vdXQgPSB0cnVlOwogICAgfTsKCiAgICBWZXJ0aWNlcy5wcm90b3R5cGUud2FsayA9IGZ1bmN0aW9uIChjYikgewogICAgICB0aGlzLnJlc2V0KCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgdmVydGV4ID0gdGhpc1tpXTsKICAgICAgICBpZiAodmVydGV4Lm91dCkgY29udGludWU7CiAgICAgICAgdGhpcy52aXNpdCh2ZXJ0ZXgsICIiKTsKICAgICAgfQoKICAgICAgdGhpcy5lYWNoKHRoaXMucmVzdWx0LCBjYik7CiAgICB9OwoKICAgIFZlcnRpY2VzLnByb3RvdHlwZS5jaGVjayA9IGZ1bmN0aW9uICh2LCB3KSB7CiAgICAgIGlmICh2LmtleSA9PT0gdykgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiY3ljbGUgZGV0ZWN0ZWQ6ICIgKyB3ICsgIiA8LSAiICsgdyk7CiAgICAgIH0gLy8gcXVpY2sgY2hlY2sKCgogICAgICBpZiAodi5sZW5ndGggPT09IDApIHJldHVybjsgLy8gc2hhbGxvdyBjaGVjawoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGtleSA9IHRoaXNbdltpXV0ua2V5OwoKICAgICAgICBpZiAoa2V5ID09PSB3KSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImN5Y2xlIGRldGVjdGVkOiAiICsgdyArICIgPC0gIiArIHYua2V5ICsgIiA8LSAiICsgdyk7CiAgICAgICAgfQogICAgICB9IC8vIGRlZXAgY2hlY2sKCgogICAgICB0aGlzLnJlc2V0KCk7CiAgICAgIHRoaXMudmlzaXQodiwgdyk7CgogICAgICBpZiAodGhpcy5wYXRoLmxlbmd0aCA+IDApIHsKICAgICAgICB2YXIgbXNnXzEgPSAiY3ljbGUgZGV0ZWN0ZWQ6ICIgKyB3OwogICAgICAgIHRoaXMuZWFjaCh0aGlzLnBhdGgsIGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgIG1zZ18xICs9ICIgPC0gIiArIGtleTsKICAgICAgICB9KTsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnXzEpOwogICAgICB9CiAgICB9OwoKICAgIFZlcnRpY2VzLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uICgpIHsKICAgICAgdGhpcy5zdGFjay5sZW5ndGggPSAwOwogICAgICB0aGlzLnBhdGgubGVuZ3RoID0gMDsKICAgICAgdGhpcy5yZXN1bHQubGVuZ3RoID0gMDsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gdGhpcy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICB0aGlzW2ldLmZsYWcgPSBmYWxzZTsKICAgICAgfQogICAgfTsKCiAgICBWZXJ0aWNlcy5wcm90b3R5cGUudmlzaXQgPSBmdW5jdGlvbiAoc3RhcnQsIHNlYXJjaCkgewogICAgICB2YXIgX2EgPSB0aGlzLAogICAgICAgICAgc3RhY2sgPSBfYS5zdGFjaywKICAgICAgICAgIHBhdGggPSBfYS5wYXRoLAogICAgICAgICAgcmVzdWx0ID0gX2EucmVzdWx0OwoKICAgICAgc3RhY2sucHVzaChzdGFydC5pZHgpOwoKICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCkgewogICAgICAgIHZhciBpbmRleCA9IHN0YWNrLnBvcCgpIHwgMDsKCiAgICAgICAgaWYgKGluZGV4ID49IDApIHsKICAgICAgICAgIC8vIGVudGVyCiAgICAgICAgICB2YXIgdmVydGV4ID0gdGhpc1tpbmRleF07CiAgICAgICAgICBpZiAodmVydGV4LmZsYWcpIGNvbnRpbnVlOwogICAgICAgICAgdmVydGV4LmZsYWcgPSB0cnVlOwogICAgICAgICAgcGF0aC5wdXNoKGluZGV4KTsKICAgICAgICAgIGlmIChzZWFyY2ggPT09IHZlcnRleC5rZXkpIGJyZWFrOyAvLyBwdXNoIGV4aXQKCiAgICAgICAgICBzdGFjay5wdXNoKH5pbmRleCk7CiAgICAgICAgICB0aGlzLnB1c2hJbmNvbWluZyh2ZXJ0ZXgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBleGl0CiAgICAgICAgICBwYXRoLnBvcCgpOwogICAgICAgICAgcmVzdWx0LnB1c2gofmluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgVmVydGljZXMucHJvdG90eXBlLnB1c2hJbmNvbWluZyA9IGZ1bmN0aW9uIChpbmNvbW1pbmcpIHsKICAgICAgdmFyIHN0YWNrID0gdGhpcy5zdGFjazsKCiAgICAgIGZvciAodmFyIGkgPSBpbmNvbW1pbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICB2YXIgaW5kZXggPSBpbmNvbW1pbmdbaV07CgogICAgICAgIGlmICghdGhpc1tpbmRleF0uZmxhZykgewogICAgICAgICAgc3RhY2sucHVzaChpbmRleCk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIFZlcnRpY2VzLnByb3RvdHlwZS5lYWNoID0gZnVuY3Rpb24gKGluZGljZXMsIGNiKSB7CiAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gaW5kaWNlcy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICB2YXIgdmVydGV4ID0gdGhpc1tpbmRpY2VzW2ldXTsKICAgICAgICBjYih2ZXJ0ZXgua2V5LCB2ZXJ0ZXgudmFsKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gVmVydGljZXM7CiAgfSgpOwogIC8qKiBAcHJpdmF0ZSAqLwoKCiAgdmFyIEludFN0YWNrID0gZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSW50U3RhY2soKSB7CiAgICAgIHRoaXMubGVuZ3RoID0gMDsKICAgIH0KCiAgICBJbnRTdGFjay5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uIChuKSB7CiAgICAgIHRoaXNbdGhpcy5sZW5ndGgrK10gPSBuIHwgMDsKICAgIH07CgogICAgSW50U3RhY2sucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIHRoaXNbLS10aGlzLmxlbmd0aF0gfCAwOwogICAgfTsKCiAgICByZXR1cm4gSW50U3RhY2s7CiAgfSgpOwp9KTsKZGVmaW5lKCJlbWJlci1iYWJlbCIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLndyYXBOYXRpdmVTdXBlciA9IHdyYXBOYXRpdmVTdXBlcjsKICBfZXhwb3J0cy5jbGFzc0NhbGxDaGVjayA9IGNsYXNzQ2FsbENoZWNrOwogIF9leHBvcnRzLmluaGVyaXRzTG9vc2UgPSBpbmhlcml0c0xvb3NlOwogIF9leHBvcnRzLnRhZ2dlZFRlbXBsYXRlTGl0ZXJhbExvb3NlID0gdGFnZ2VkVGVtcGxhdGVMaXRlcmFsTG9vc2U7CiAgX2V4cG9ydHMuY3JlYXRlQ2xhc3MgPSBjcmVhdGVDbGFzczsKICBfZXhwb3J0cy5hc3NlcnRUaGlzSW5pdGlhbGl6ZWQgPSBhc3NlcnRUaGlzSW5pdGlhbGl6ZWQ7CiAgX2V4cG9ydHMucG9zc2libGVDb25zdHJ1Y3RvclJldHVybiA9IHBvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm47CiAgX2V4cG9ydHMub2JqZWN0RGVzdHJ1Y3R1cmluZ0VtcHR5ID0gb2JqZWN0RGVzdHJ1Y3R1cmluZ0VtcHR5OwogIHZhciBzZXRQcm90b3R5cGVPZiA9IE9iamVjdC5zZXRQcm90b3R5cGVPZjsKICB2YXIgbmF0aXZlV3JhcHBlckNhY2hlID0gbmV3IE1hcCgpOyAvLyBTdXBlciBtaW5pbWFsIHZlcnNpb24gb2YgQmFiZWwncyB3cmFwTmF0aXZlU3VwZXIuIFdlIG9ubHkgdXNlIHRoaXMgZm9yCiAgLy8gZXh0ZW5kaW5nIEZ1bmN0aW9uLCBmb3IgQ29tcHV0ZWREZWNvcmF0b3JJbXBsIGFuZCBBbGlhc0RlY29yYXRvckltcGwuIFdlIGtub3cKICAvLyB3ZSB3aWxsIG5ldmVyIGRpcmVjdGx5IGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiB0aGVzZSBjbGFzc2VzIHNvIG5vIG5lZWQgdG8KICAvLyBpbmNsdWRlIGBjb25zdHJ1Y3RgIGNvZGUgb3Igb3RoZXIgaGVscGVycy4KCiAgZnVuY3Rpb24gd3JhcE5hdGl2ZVN1cGVyKENsYXNzKSB7CiAgICBpZiAobmF0aXZlV3JhcHBlckNhY2hlLmhhcyhDbGFzcykpIHsKICAgICAgcmV0dXJuIG5hdGl2ZVdyYXBwZXJDYWNoZS5nZXQoQ2xhc3MpOwogICAgfQoKICAgIGZ1bmN0aW9uIFdyYXBwZXIoKSB7fQoKICAgIFdyYXBwZXIucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShDbGFzcy5wcm90b3R5cGUsIHsKICAgICAgY29uc3RydWN0b3I6IHsKICAgICAgICB2YWx1ZTogV3JhcHBlciwKICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICBjb25maWd1cmFibGU6IHRydWUKICAgICAgfQogICAgfSk7CiAgICBuYXRpdmVXcmFwcGVyQ2FjaGUuc2V0KENsYXNzLCBXcmFwcGVyKTsKICAgIHJldHVybiBzZXRQcm90b3R5cGVPZihXcmFwcGVyLCBDbGFzcyk7CiAgfQoKICBmdW5jdGlvbiBjbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgewogICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOwogICAgICB9CiAgICB9CiAgfQogIC8qCiAgICBPdmVycmlkZXMgZGVmYXVsdCBgaW5oZXJpdHNMb29zZWAgdG8gX2Fsc29fIGNhbGwgYE9iamVjdC5zZXRQcm90b3R5cGVPZmAuCiAgICBUaGlzIGlzIG5lZWRlZCBzbyB0aGF0IHdlIGNhbiB1c2UgYGxvb3NlYCBvcHRpb24gd2l0aCB0aGUKICAgIGBAYmFiZWwvcGx1Z2luLXRyYW5zZm9ybS1jbGFzc2VzYCAoYmVjYXVzZSB3ZSB3YW50IHNpbXBsZSBhc3NpZ25tZW50IHRvIHRoZQogICAgcHJvdG90eXBlIHdoZXJlZXZlciBwb3NzaWJsZSkgYnV0IGFsc28ga2VlcCBvdXIgY29uc3RydWN0b3IgYmFzZWQgcHJvdG90eXBhbAogICAgaW5oZXJpdGFuY2Ugd29ya2luZyBwcm9wZXJseQogICovCgoKICBmdW5jdGlvbiBpbmhlcml0c0xvb3NlKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7CiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbicpOwogICAgICB9CiAgICB9CgogICAgc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzID09PSBudWxsID8gbnVsbCA6IHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7CiAgICAgIGNvbnN0cnVjdG9yOiB7CiAgICAgICAgdmFsdWU6IHN1YkNsYXNzLAogICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogICAgICB9CiAgICB9KTsKCiAgICBpZiAoc3VwZXJDbGFzcyAhPT0gbnVsbCkgewogICAgICBzZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcyk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiB0YWdnZWRUZW1wbGF0ZUxpdGVyYWxMb29zZShzdHJpbmdzLCByYXcpIHsKICAgIGlmICghcmF3KSB7CiAgICAgIHJhdyA9IHN0cmluZ3Muc2xpY2UoMCk7CiAgICB9CgogICAgc3RyaW5ncy5yYXcgPSByYXc7CiAgICByZXR1cm4gc3RyaW5nczsKICB9CgogIGZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsKICAgICAgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOwogICAgICBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7CiAgICAgIGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOwogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7CiAgICB9CiAgfQogIC8qCiAgICBEaWZmZXJzIGZyb20gZGVmYXVsdCBpbXBsZW1lbnRhdGlvbiBieSBhdm9pZGluZyBib29sZWFuIGNvZXJjaW9uIG9mCiAgICBgcHJvdG9Qcm9wc2AgYW5kIGBzdGF0aWNQcm9wc2AuCiAgKi8KCgogIGZ1bmN0aW9uIGNyZWF0ZUNsYXNzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgewogICAgaWYgKHByb3RvUHJvcHMgIT09IG51bGwgJiYgcHJvdG9Qcm9wcyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIF9kZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7CiAgICB9CgogICAgaWYgKHN0YXRpY1Byb3BzICE9PSBudWxsICYmIHN0YXRpY1Byb3BzICE9PSB1bmRlZmluZWQpIHsKICAgICAgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsKICAgIH0KCiAgICByZXR1cm4gQ29uc3RydWN0b3I7CiAgfQoKICBmdW5jdGlvbiBhc3NlcnRUaGlzSW5pdGlhbGl6ZWQoc2VsZikgewogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgJiYgc2VsZiA9PT0gdm9pZCAwKSB7CiAgICAgIHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcigidGhpcyBoYXNuJ3QgYmVlbiBpbml0aWFsaXNlZCAtIHN1cGVyKCkgaGFzbid0IGJlZW4gY2FsbGVkIik7CiAgICB9CgogICAgcmV0dXJuIHNlbGY7CiAgfQogIC8qCiAgICBBZGRzIGBERUJVR2AgZ3VhcmQgdG8gZXJyb3IgYmVpbmcgdGhyb3duLCBhbmQgYXZvaWRzIGJvb2xlYW4gY29lcmNpb24gb2YgYGNhbGxgLgogICovCgoKICBmdW5jdGlvbiBwb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHsKICAgIGlmICh0eXBlb2YgY2FsbCA9PT0gJ29iamVjdCcgJiYgY2FsbCAhPT0gbnVsbCB8fCB0eXBlb2YgY2FsbCA9PT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gY2FsbDsKICAgIH0KCiAgICByZXR1cm4gYXNzZXJ0VGhpc0luaXRpYWxpemVkKHNlbGYpOwogIH0KCiAgZnVuY3Rpb24gb2JqZWN0RGVzdHJ1Y3R1cmluZ0VtcHR5KG9iaikgewogICAgaWYgKGZhbHNlCiAgICAvKiBERUJVRyAqLwogICAgJiYgKG9iaiA9PT0gbnVsbCB8fCBvYmogPT09IHVuZGVmaW5lZCkpIHsKICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGRlc3RydWN0dXJlIHVuZGVmaW5lZCcpOwogICAgfQogIH0KfSk7CmRlZmluZSgiZW1iZXIvaW5kZXgiLCBbImV4cG9ydHMiLCAicmVxdWlyZSIsICJAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCIsICJub2RlLW1vZHVsZSIsICJAZW1iZXIvLWludGVybmFscy91dGlscyIsICJAZW1iZXIvLWludGVybmFscy9jb250YWluZXIiLCAiQGVtYmVyL2luc3RydW1lbnRhdGlvbiIsICJAZW1iZXIvLWludGVybmFscy9tZXRhIiwgIkBlbWJlci8taW50ZXJuYWxzL21ldGFsIiwgIkBlbWJlci9jYW5hcnktZmVhdHVyZXMiLCAiQGVtYmVyL2RlYnVnIiwgImJhY2tidXJuZXIiLCAiQGVtYmVyLy1pbnRlcm5hbHMvY29uc29sZSIsICJAZW1iZXIvY29udHJvbGxlciIsICJAZW1iZXIvY29udHJvbGxlci9saWIvY29udHJvbGxlcl9taXhpbiIsICJAZW1iZXIvc3RyaW5nIiwgIkBlbWJlci9zZXJ2aWNlIiwgIkBlbWJlci9vYmplY3QiLCAiQGVtYmVyL29iamVjdC9jb21wYXQiLCAiQGVtYmVyL29iamVjdC9jb21wdXRlZCIsICJAZW1iZXIvLWludGVybmFscy9ydW50aW1lIiwgIkBlbWJlci8taW50ZXJuYWxzL2dsaW1tZXIiLCAiZW1iZXIvdmVyc2lvbiIsICJAZW1iZXIvLWludGVybmFscy92aWV3cyIsICJAZW1iZXIvLWludGVybmFscy9yb3V0aW5nIiwgIkBlbWJlci8taW50ZXJuYWxzL2V4dGVuc2lvbi1zdXBwb3J0IiwgIkBlbWJlci9lcnJvciIsICJAZW1iZXIvcnVubG9vcCIsICJAZW1iZXIvLWludGVybmFscy9lcnJvci1oYW5kbGluZyIsICJAZW1iZXIvLWludGVybmFscy9vd25lciIsICJAZW1iZXIvYXBwbGljYXRpb24iLCAiQGVtYmVyL2FwcGxpY2F0aW9uL2dsb2JhbHMtcmVzb2x2ZXIiLCAiQGVtYmVyL2FwcGxpY2F0aW9uL2luc3RhbmNlIiwgIkBlbWJlci9lbmdpbmUiLCAiQGVtYmVyL2VuZ2luZS9pbnN0YW5jZSIsICJAZW1iZXIvcG9seWZpbGxzIiwgIkBlbWJlci9kZXByZWNhdGVkLWZlYXR1cmVzIiwgIkBlbWJlci9jb21wb25lbnQvdGVtcGxhdGUtb25seSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9yZXF1aXJlLCBfZW52aXJvbm1lbnQsIF9ub2RlTW9kdWxlLCB1dGlscywgX2NvbnRhaW5lciwgaW5zdHJ1bWVudGF0aW9uLCBfbWV0YSwgbWV0YWwsIF9jYW5hcnlGZWF0dXJlcywgRW1iZXJEZWJ1ZywgX2JhY2tidXJuZXIsIF9jb25zb2xlLCBfY29udHJvbGxlciwgX2NvbnRyb2xsZXJfbWl4aW4sIF9zdHJpbmcsIF9zZXJ2aWNlLCBfb2JqZWN0LCBfY29tcGF0LCBfY29tcHV0ZWQsIF9ydW50aW1lLCBfZ2xpbW1lciwgX3ZlcnNpb24sIHZpZXdzLCByb3V0aW5nLCBleHRlbnNpb25TdXBwb3J0LCBfZXJyb3IsIHJ1bmxvb3AsIF9lcnJvckhhbmRsaW5nLCBfb3duZXIsIF9hcHBsaWNhdGlvbiwgX2dsb2JhbHNSZXNvbHZlciwgX2luc3RhbmNlLCBfZW5naW5lLCBfaW5zdGFuY2UyLCBfcG9seWZpbGxzLCBfZGVwcmVjYXRlZEZlYXR1cmVzLCBfdGVtcGxhdGVPbmx5KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tdW5yZXNvbHZlZAogIC8vICoqKipAZW1iZXIvLWludGVybmFscy9lbnZpcm9ubWVudCoqKioKICB2YXIgRW1iZXIgPSB0eXBlb2YgX2Vudmlyb25tZW50LmNvbnRleHQuaW1wb3J0cy5FbWJlciA9PT0gJ29iamVjdCcgJiYgX2Vudmlyb25tZW50LmNvbnRleHQuaW1wb3J0cy5FbWJlciB8fCB7fTsKICBFbWJlci5pc05hbWVzcGFjZSA9IHRydWU7CgogIEVtYmVyLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkgewogICAgcmV0dXJuICdFbWJlcic7CiAgfTsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEVtYmVyLCAnRU5WJywgewogICAgZ2V0OiBfZW52aXJvbm1lbnQuZ2V0RU5WLAogICAgZW51bWVyYWJsZTogZmFsc2UKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICdsb29rdXAnLCB7CiAgICBnZXQ6IF9lbnZpcm9ubWVudC5nZXRMb29rdXAsCiAgICBzZXQ6IF9lbnZpcm9ubWVudC5zZXRMb29rdXAsCiAgICBlbnVtZXJhYmxlOiBmYWxzZQogIH0pOwoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5FTUJFUl9FWFRFTkRfUFJPVE9UWVBFUykgewogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEVtYmVyLCAnRVhURU5EX1BST1RPVFlQRVMnLCB7CiAgICAgIGVudW1lcmFibGU6IGZhbHNlLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIEVtYmVyRGVidWcuZGVwcmVjYXRlKSgnQWNjZXNzaW5nIEVtYmVyLkVYVEVORF9QUk9UT1RZUEVTIGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSBtaWdyYXRlIHRvIEVtYmVyLkVOVi5FWFRFTkRfUFJPVE9UWVBFUycsIGZhbHNlLCB7CiAgICAgICAgICBpZDogJ2VtYmVyLWVudi5vbGQtZXh0ZW5kLXByb3RvdHlwZXMnLAogICAgICAgICAgdW50aWw6ICc0LjAuMCcKICAgICAgICB9KSk7CiAgICAgICAgcmV0dXJuIF9lbnZpcm9ubWVudC5FTlYuRVhURU5EX1BST1RPVFlQRVM7CiAgICAgIH0KICAgIH0pOwogIH0gLy8gKioqKkBlbWJlci9hcHBsaWNhdGlvbioqKioKCgogIEVtYmVyLmdldE93bmVyID0gX293bmVyLmdldE93bmVyOwogIEVtYmVyLnNldE93bmVyID0gX293bmVyLnNldE93bmVyOwogIEVtYmVyLkFwcGxpY2F0aW9uID0gX2FwcGxpY2F0aW9uLmRlZmF1bHQ7CiAgRW1iZXIuRGVmYXVsdFJlc29sdmVyID0gRW1iZXIuUmVzb2x2ZXIgPSBfZ2xvYmFsc1Jlc29sdmVyLmRlZmF1bHQ7CiAgRW1iZXIuQXBwbGljYXRpb25JbnN0YW5jZSA9IF9pbnN0YW5jZS5kZWZhdWx0OyAvLyAqKioqQGVtYmVyL2VuZ2luZSoqKioKCiAgRW1iZXIuRW5naW5lID0gX2VuZ2luZS5kZWZhdWx0OwogIEVtYmVyLkVuZ2luZUluc3RhbmNlID0gX2luc3RhbmNlMi5kZWZhdWx0OyAvLyAqKioqQGVtYmVyL3BvbHlmaWxscyoqKioKCiAgRW1iZXIuYXNzaWduID0gX3BvbHlmaWxscy5hc3NpZ247CiAgRW1iZXIubWVyZ2UgPSBfcG9seWZpbGxzLm1lcmdlOyAvLyAqKioqQGVtYmVyLy1pbnRlcm5hbHMvdXRpbHMqKioqCgogIEVtYmVyLmdlbmVyYXRlR3VpZCA9IHV0aWxzLmdlbmVyYXRlR3VpZDsKICBFbWJlci5HVUlEX0tFWSA9IHV0aWxzLkdVSURfS0VZOwogIEVtYmVyLmd1aWRGb3IgPSB1dGlscy5ndWlkRm9yOwogIEVtYmVyLmluc3BlY3QgPSB1dGlscy5pbnNwZWN0OwogIEVtYmVyLm1ha2VBcnJheSA9IHV0aWxzLm1ha2VBcnJheTsKICBFbWJlci5jYW5JbnZva2UgPSB1dGlscy5jYW5JbnZva2U7CiAgRW1iZXIudHJ5SW52b2tlID0gdXRpbHMudHJ5SW52b2tlOwogIEVtYmVyLndyYXAgPSB1dGlscy53cmFwOwogIEVtYmVyLnV1aWQgPSB1dGlscy51dWlkOyAvLyAqKioqQGVtYmVyLy1pbnRlcm5hbHMvY29udGFpbmVyKioqKgoKICBFbWJlci5Db250YWluZXIgPSBfY29udGFpbmVyLkNvbnRhaW5lcjsKICBFbWJlci5SZWdpc3RyeSA9IF9jb250YWluZXIuUmVnaXN0cnk7IC8vICoqKipAZW1iZXIvZGVidWcqKioqCgogIEVtYmVyLmFzc2VydCA9IEVtYmVyRGVidWcuYXNzZXJ0OwogIEVtYmVyLndhcm4gPSBFbWJlckRlYnVnLndhcm47CiAgRW1iZXIuZGVidWcgPSBFbWJlckRlYnVnLmRlYnVnOwogIEVtYmVyLmRlcHJlY2F0ZSA9IEVtYmVyRGVidWcuZGVwcmVjYXRlOwogIEVtYmVyLmRlcHJlY2F0ZUZ1bmMgPSBFbWJlckRlYnVnLmRlcHJlY2F0ZUZ1bmM7CiAgRW1iZXIucnVuSW5EZWJ1ZyA9IEVtYmVyRGVidWcucnVuSW5EZWJ1ZzsgLy8gKioqKkBlbWJlci9lcnJvcioqKioKCiAgRW1iZXIuRXJyb3IgPSBfZXJyb3IuZGVmYXVsdDsKICAvKioKICAgIEBwdWJsaWMKICAgIEBjbGFzcyBFbWJlci5EZWJ1ZwogICovCgogIEVtYmVyLkRlYnVnID0gewogICAgcmVnaXN0ZXJEZXByZWNhdGlvbkhhbmRsZXI6IEVtYmVyRGVidWcucmVnaXN0ZXJEZXByZWNhdGlvbkhhbmRsZXIsCiAgICByZWdpc3Rlcldhcm5IYW5kbGVyOiBFbWJlckRlYnVnLnJlZ2lzdGVyV2FybkhhbmRsZXIsCiAgICBpc0NvbXB1dGVkOiBtZXRhbC5pc0NvbXB1dGVkCiAgfTsgLy8gKioqKkBlbWJlci9pbnN0cnVtZW50YXRpb24qKioqCgogIEVtYmVyLmluc3RydW1lbnQgPSBpbnN0cnVtZW50YXRpb24uaW5zdHJ1bWVudDsKICBFbWJlci5zdWJzY3JpYmUgPSBpbnN0cnVtZW50YXRpb24uc3Vic2NyaWJlOwogIEVtYmVyLkluc3RydW1lbnRhdGlvbiA9IHsKICAgIGluc3RydW1lbnQ6IGluc3RydW1lbnRhdGlvbi5pbnN0cnVtZW50LAogICAgc3Vic2NyaWJlOiBpbnN0cnVtZW50YXRpb24uc3Vic2NyaWJlLAogICAgdW5zdWJzY3JpYmU6IGluc3RydW1lbnRhdGlvbi51bnN1YnNjcmliZSwKICAgIHJlc2V0OiBpbnN0cnVtZW50YXRpb24ucmVzZXQKICB9OyAvLyAqKioqQGVtYmVyL3J1bmxvb3AqKioqCiAgLy8gVXNpbmcgX2dsb2JhbHNSdW4gaGVyZSBzbyB0aGF0IG11dGF0aW5nIHRoZSBmdW5jdGlvbiAoYWRkaW5nCiAgLy8gYG5leHRgLCBgbGF0ZXJgLCBldGMgdG8gaXQpIGlzIG9ubHkgYXZhaWxhYmxlIGluIGdsb2JhbHMgYnVpbGRzCgogIEVtYmVyLnJ1biA9IHJ1bmxvb3AuX2dsb2JhbHNSdW47CiAgRW1iZXIucnVuLmJhY2tidXJuZXIgPSBydW5sb29wLmJhY2tidXJuZXI7CiAgRW1iZXIucnVuLmJlZ2luID0gcnVubG9vcC5iZWdpbjsKICBFbWJlci5ydW4uYmluZCA9IHJ1bmxvb3AuYmluZDsKICBFbWJlci5ydW4uY2FuY2VsID0gcnVubG9vcC5jYW5jZWw7CiAgRW1iZXIucnVuLmRlYm91bmNlID0gcnVubG9vcC5kZWJvdW5jZTsKICBFbWJlci5ydW4uZW5kID0gcnVubG9vcC5lbmQ7CiAgRW1iZXIucnVuLmhhc1NjaGVkdWxlZFRpbWVycyA9IHJ1bmxvb3AuaGFzU2NoZWR1bGVkVGltZXJzOwogIEVtYmVyLnJ1bi5qb2luID0gcnVubG9vcC5qb2luOwogIEVtYmVyLnJ1bi5sYXRlciA9IHJ1bmxvb3AubGF0ZXI7CiAgRW1iZXIucnVuLm5leHQgPSBydW5sb29wLm5leHQ7CiAgRW1iZXIucnVuLm9uY2UgPSBydW5sb29wLm9uY2U7CiAgRW1iZXIucnVuLnNjaGVkdWxlID0gcnVubG9vcC5zY2hlZHVsZTsKICBFbWJlci5ydW4uc2NoZWR1bGVPbmNlID0gcnVubG9vcC5zY2hlZHVsZU9uY2U7CiAgRW1iZXIucnVuLnRocm90dGxlID0gcnVubG9vcC50aHJvdHRsZTsKICBFbWJlci5ydW4uY2FuY2VsVGltZXJzID0gcnVubG9vcC5jYW5jZWxUaW1lcnM7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEVtYmVyLnJ1biwgJ2N1cnJlbnRSdW5Mb29wJywgewogICAgZ2V0OiBydW5sb29wLmdldEN1cnJlbnRSdW5Mb29wLAogICAgZW51bWVyYWJsZTogZmFsc2UKICB9KTsgLy8gKioqKkBlbWJlci8taW50ZXJuYWxzL21ldGFsKioqKgogIC8vIFVzaW5nIF9nbG9iYWxzQ29tcHV0ZWQgaGVyZSBzbyB0aGF0IG11dGF0aW5nIHRoZSBmdW5jdGlvbiBpcyBvbmx5IGF2YWlsYWJsZQogIC8vIGluIGdsb2JhbHMgYnVpbGRzCgogIHZhciBjb21wdXRlZCA9IG1ldGFsLl9nbG9iYWxzQ29tcHV0ZWQ7CiAgRW1iZXIuY29tcHV0ZWQgPSBjb21wdXRlZDsKICBFbWJlci5fZGVzY3JpcHRvciA9IG1ldGFsLm5hdGl2ZURlc2NEZWNvcmF0b3I7CiAgRW1iZXIuX3RyYWNrZWQgPSBtZXRhbC50cmFja2VkOwogIGNvbXB1dGVkLmFsaWFzID0gbWV0YWwuYWxpYXM7CiAgRW1iZXIuY2FjaGVGb3IgPSBtZXRhbC5nZXRDYWNoZWRWYWx1ZUZvcjsKICBFbWJlci5Db21wdXRlZFByb3BlcnR5ID0gbWV0YWwuQ29tcHV0ZWRQcm9wZXJ0eTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICdfc2V0Q29tcHV0ZWREZWNvcmF0b3InLCB7CiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmICgwLCBFbWJlckRlYnVnLmRlcHJlY2F0ZSkoJ1BsZWFzZSBtaWdyYXRlIGZyb20gRW1iZXIuX3NldENvbXB1dGVkRGVjb3JhdG9yIHRvIEVtYmVyLl9zZXRDbGFzc2ljRGVjb3JhdG9yJywgZmFsc2UsIHsKICAgICAgICBpZDogJ2VtYmVyLl9zZXRDb21wdXRlZERlY29yYXRvcicsCiAgICAgICAgdW50aWw6ICczLjEzLjAnCiAgICAgIH0pKTsKICAgICAgcmV0dXJuIG1ldGFsLnNldENsYXNzaWNEZWNvcmF0b3I7CiAgICB9CiAgfSk7CiAgRW1iZXIuX3NldENsYXNzaWNEZWNvcmF0b3IgPSBtZXRhbC5zZXRDbGFzc2ljRGVjb3JhdG9yOwogIEVtYmVyLm1ldGEgPSBfbWV0YS5tZXRhOwogIEVtYmVyLmdldCA9IG1ldGFsLmdldDsKICBFbWJlci5nZXRXaXRoRGVmYXVsdCA9IG1ldGFsLmdldFdpdGhEZWZhdWx0OwogIEVtYmVyLl9nZXRQYXRoID0gbWV0YWwuX2dldFBhdGg7CiAgRW1iZXIuc2V0ID0gbWV0YWwuc2V0OwogIEVtYmVyLnRyeVNldCA9IG1ldGFsLnRyeVNldDsKICBFbWJlci5GRUFUVVJFUyA9ICgwLCBfcG9seWZpbGxzLmFzc2lnbikoewogICAgaXNFbmFibGVkOiBfY2FuYXJ5RmVhdHVyZXMuaXNFbmFibGVkCiAgfSwgX2NhbmFyeUZlYXR1cmVzLkZFQVRVUkVTKTsKICBFbWJlci5fQ2FjaGUgPSB1dGlscy5DYWNoZTsKICBFbWJlci5vbiA9IG1ldGFsLm9uOwogIEVtYmVyLmFkZExpc3RlbmVyID0gbWV0YWwuYWRkTGlzdGVuZXI7CiAgRW1iZXIucmVtb3ZlTGlzdGVuZXIgPSBtZXRhbC5yZW1vdmVMaXN0ZW5lcjsKICBFbWJlci5zZW5kRXZlbnQgPSBtZXRhbC5zZW5kRXZlbnQ7CiAgRW1iZXIuaGFzTGlzdGVuZXJzID0gbWV0YWwuaGFzTGlzdGVuZXJzOwogIEVtYmVyLmlzTm9uZSA9IG1ldGFsLmlzTm9uZTsKICBFbWJlci5pc0VtcHR5ID0gbWV0YWwuaXNFbXB0eTsKICBFbWJlci5pc0JsYW5rID0gbWV0YWwuaXNCbGFuazsKICBFbWJlci5pc1ByZXNlbnQgPSBtZXRhbC5pc1ByZXNlbnQ7CiAgRW1iZXIubm90aWZ5UHJvcGVydHlDaGFuZ2UgPSBtZXRhbC5ub3RpZnlQcm9wZXJ0eUNoYW5nZTsKICBFbWJlci5vdmVycmlkZUNoYWlucyA9IG1ldGFsLm92ZXJyaWRlQ2hhaW5zOwogIEVtYmVyLmJlZ2luUHJvcGVydHlDaGFuZ2VzID0gbWV0YWwuYmVnaW5Qcm9wZXJ0eUNoYW5nZXM7CiAgRW1iZXIuZW5kUHJvcGVydHlDaGFuZ2VzID0gbWV0YWwuZW5kUHJvcGVydHlDaGFuZ2VzOwogIEVtYmVyLmNoYW5nZVByb3BlcnRpZXMgPSBtZXRhbC5jaGFuZ2VQcm9wZXJ0aWVzOwogIEVtYmVyLnBsYXRmb3JtID0gewogICAgZGVmaW5lUHJvcGVydHk6IHRydWUsCiAgICBoYXNQcm9wZXJ0eUFjY2Vzc29yczogdHJ1ZQogIH07CiAgRW1iZXIuZGVmaW5lUHJvcGVydHkgPSBtZXRhbC5kZWZpbmVQcm9wZXJ0eTsKICBFbWJlci53YXRjaEtleSA9IG1ldGFsLndhdGNoS2V5OwogIEVtYmVyLnVud2F0Y2hLZXkgPSBtZXRhbC51bndhdGNoS2V5OwogIEVtYmVyLnJlbW92ZUNoYWluV2F0Y2hlciA9IG1ldGFsLnJlbW92ZUNoYWluV2F0Y2hlcjsKICBFbWJlci5fQ2hhaW5Ob2RlID0gbWV0YWwuQ2hhaW5Ob2RlOwogIEVtYmVyLmZpbmlzaENoYWlucyA9IG1ldGFsLmZpbmlzaENoYWluczsKICBFbWJlci53YXRjaFBhdGggPSBtZXRhbC53YXRjaFBhdGg7CiAgRW1iZXIudW53YXRjaFBhdGggPSBtZXRhbC51bndhdGNoUGF0aDsKICBFbWJlci53YXRjaCA9IG1ldGFsLndhdGNoOwogIEVtYmVyLmlzV2F0Y2hpbmcgPSBtZXRhbC5pc1dhdGNoaW5nOwogIEVtYmVyLnVud2F0Y2ggPSBtZXRhbC51bndhdGNoOwogIEVtYmVyLmRlc3Ryb3kgPSBfbWV0YS5kZWxldGVNZXRhOwogIEVtYmVyLmxpYnJhcmllcyA9IG1ldGFsLmxpYnJhcmllczsKICBFbWJlci5nZXRQcm9wZXJ0aWVzID0gbWV0YWwuZ2V0UHJvcGVydGllczsKICBFbWJlci5zZXRQcm9wZXJ0aWVzID0gbWV0YWwuc2V0UHJvcGVydGllczsKICBFbWJlci5leHBhbmRQcm9wZXJ0aWVzID0gbWV0YWwuZXhwYW5kUHJvcGVydGllczsKICBFbWJlci5hZGRPYnNlcnZlciA9IG1ldGFsLmFkZE9ic2VydmVyOwogIEVtYmVyLnJlbW92ZU9ic2VydmVyID0gbWV0YWwucmVtb3ZlT2JzZXJ2ZXI7CiAgRW1iZXIuYWxpYXNNZXRob2QgPSBtZXRhbC5hbGlhc01ldGhvZDsKICBFbWJlci5vYnNlcnZlciA9IG1ldGFsLm9ic2VydmVyOwogIEVtYmVyLm1peGluID0gbWV0YWwubWl4aW47CiAgRW1iZXIuTWl4aW4gPSBtZXRhbC5NaXhpbjsKICAvKioKICAgIEEgZnVuY3Rpb24gbWF5IGJlIGFzc2lnbmVkIHRvIGBFbWJlci5vbmVycm9yYCB0byBiZSBjYWxsZWQgd2hlbiBFbWJlcgogICAgaW50ZXJuYWxzIGVuY291bnRlciBhbiBlcnJvci4gVGhpcyBpcyB1c2VmdWwgZm9yIHNwZWNpYWxpemVkIGVycm9yIGhhbmRsaW5nCiAgICBhbmQgcmVwb3J0aW5nIGNvZGUuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgJCBmcm9tICdqcXVlcnknOwogIAogICAgRW1iZXIub25lcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7CiAgICAgICQuYWpheCgnL3JlcG9ydC1lcnJvcicsICdQT1NUJywgewogICAgICAgIHN0YWNrOiBlcnJvci5zdGFjaywKICAgICAgICBvdGhlckluZm9ybWF0aW9uOiAnd2hhdGV2ZXIgYXBwIHN0YXRlIHlvdSB3YW50IHRvIHByb3ZpZGUnCiAgICAgIH0pOwogICAgfTsKICAgIGBgYAogIAogICAgSW50ZXJuYWxseSwgYEVtYmVyLm9uZXJyb3JgIGlzIHVzZWQgYXMgQmFja2J1cm5lcidzIGVycm9yIGhhbmRsZXIuCiAgCiAgICBAZXZlbnQgb25lcnJvcgogICAgQGZvciBFbWJlcgogICAgQHBhcmFtIHtFeGNlcHRpb259IGVycm9yIHRoZSBlcnJvciBvYmplY3QKICAgIEBwdWJsaWMKICAqLwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICdvbmVycm9yJywgewogICAgZ2V0OiBfZXJyb3JIYW5kbGluZy5nZXRPbmVycm9yLAogICAgc2V0OiBfZXJyb3JIYW5kbGluZy5zZXRPbmVycm9yLAogICAgZW51bWVyYWJsZTogZmFsc2UKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICd0ZXN0aW5nJywgewogICAgZ2V0OiBFbWJlckRlYnVnLmlzVGVzdGluZywKICAgIHNldDogRW1iZXJEZWJ1Zy5zZXRUZXN0aW5nLAogICAgZW51bWVyYWJsZTogZmFsc2UKICB9KTsKICBFbWJlci5fQmFja2J1cm5lciA9IF9iYWNrYnVybmVyLmRlZmF1bHQ7IC8vICoqKipAZW1iZXIvLWludGVybmFscy9jb25zb2xlKioqKgoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5MT0dHRVIpIHsKICAgIEVtYmVyLkxvZ2dlciA9IF9jb25zb2xlLmRlZmF1bHQ7CiAgfSAvLyAqKioqQGVtYmVyLy1pbnRlcm5hbHMvcnVudGltZSoqKioKCgogIEVtYmVyLkEgPSBfcnVudGltZS5BOwogIEVtYmVyLlN0cmluZyA9IHsKICAgIGxvYzogX3N0cmluZy5sb2MsCiAgICB3OiBfc3RyaW5nLncsCiAgICBkYXNoZXJpemU6IF9zdHJpbmcuZGFzaGVyaXplLAogICAgZGVjYW1lbGl6ZTogX3N0cmluZy5kZWNhbWVsaXplLAogICAgY2FtZWxpemU6IF9zdHJpbmcuY2FtZWxpemUsCiAgICBjbGFzc2lmeTogX3N0cmluZy5jbGFzc2lmeSwKICAgIHVuZGVyc2NvcmU6IF9zdHJpbmcudW5kZXJzY29yZSwKICAgIGNhcGl0YWxpemU6IF9zdHJpbmcuY2FwaXRhbGl6ZQogIH07CiAgRW1iZXIuT2JqZWN0ID0gX3J1bnRpbWUuT2JqZWN0OwogIEVtYmVyLl9SZWdpc3RyeVByb3h5TWl4aW4gPSBfcnVudGltZS5SZWdpc3RyeVByb3h5TWl4aW47CiAgRW1iZXIuX0NvbnRhaW5lclByb3h5TWl4aW4gPSBfcnVudGltZS5Db250YWluZXJQcm94eU1peGluOwogIEVtYmVyLmNvbXBhcmUgPSBfcnVudGltZS5jb21wYXJlOwogIEVtYmVyLmNvcHkgPSBfcnVudGltZS5jb3B5OwogIEVtYmVyLmlzRXF1YWwgPSBfcnVudGltZS5pc0VxdWFsOwoKICBpZiAodHJ1ZQogIC8qIEVNQkVSX0ZSQU1FV09SS19PQkpFQ1RfT1dORVJfQVJHVU1FTlQgKi8KICApIHsKICAgICAgRW1iZXIuX3NldEZyYW1ld29ya0NsYXNzID0gX3J1bnRpbWUuc2V0RnJhbWV3b3JrQ2xhc3M7CiAgICB9CiAgLyoqCiAgQG1vZHVsZSBlbWJlcgogICovCgogIC8qKgogICAgTmFtZXNwYWNlIGZvciBpbmplY3Rpb24gaGVscGVyIG1ldGhvZHMuCiAgCiAgICBAY2xhc3MgaW5qZWN0CiAgICBAbmFtZXNwYWNlIEVtYmVyCiAgICBAc3RhdGljCiAgICBAcHVibGljCiAgKi8KCgogIEVtYmVyLmluamVjdCA9IGZ1bmN0aW9uIGluamVjdCgpIHsKICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiAoMCwgRW1iZXJEZWJ1Zy5hc3NlcnQpKCJJbmplY3RlZCBwcm9wZXJ0aWVzIG11c3QgYmUgY3JlYXRlZCB0aHJvdWdoIGhlbHBlcnMsIHNlZSAnIiArIE9iamVjdC5rZXlzKGluamVjdCkubWFwKGZ1bmN0aW9uIChrKSB7CiAgICAgIHJldHVybiAiJ2luamVjdC4iICsgayArICInIjsKICAgIH0pLmpvaW4oJyBvciAnKSArICInIikpOwogIH07CgogIEVtYmVyLmluamVjdC5zZXJ2aWNlID0gX3NlcnZpY2UuaW5qZWN0OwogIEVtYmVyLmluamVjdC5jb250cm9sbGVyID0gX2NvbnRyb2xsZXIuaW5qZWN0OwogIEVtYmVyLkFycmF5ID0gX3J1bnRpbWUuQXJyYXk7CiAgRW1iZXIuQ29tcGFyYWJsZSA9IF9ydW50aW1lLkNvbXBhcmFibGU7CiAgRW1iZXIuRW51bWVyYWJsZSA9IF9ydW50aW1lLkVudW1lcmFibGU7CiAgRW1iZXIuQXJyYXlQcm94eSA9IF9ydW50aW1lLkFycmF5UHJveHk7CiAgRW1iZXIuT2JqZWN0UHJveHkgPSBfcnVudGltZS5PYmplY3RQcm94eTsKICBFbWJlci5BY3Rpb25IYW5kbGVyID0gX3J1bnRpbWUuQWN0aW9uSGFuZGxlcjsKICBFbWJlci5Db3JlT2JqZWN0ID0gX3J1bnRpbWUuQ29yZU9iamVjdDsKICBFbWJlci5OYXRpdmVBcnJheSA9IF9ydW50aW1lLk5hdGl2ZUFycmF5OwogIEVtYmVyLkNvcHlhYmxlID0gX3J1bnRpbWUuQ29weWFibGU7CiAgRW1iZXIuTXV0YWJsZUVudW1lcmFibGUgPSBfcnVudGltZS5NdXRhYmxlRW51bWVyYWJsZTsKICBFbWJlci5NdXRhYmxlQXJyYXkgPSBfcnVudGltZS5NdXRhYmxlQXJyYXk7CiAgRW1iZXIuVGFyZ2V0QWN0aW9uU3VwcG9ydCA9IF9ydW50aW1lLlRhcmdldEFjdGlvblN1cHBvcnQ7CiAgRW1iZXIuRXZlbnRlZCA9IF9ydW50aW1lLkV2ZW50ZWQ7CiAgRW1iZXIuUHJvbWlzZVByb3h5TWl4aW4gPSBfcnVudGltZS5Qcm9taXNlUHJveHlNaXhpbjsKICBFbWJlci5PYnNlcnZhYmxlID0gX3J1bnRpbWUuT2JzZXJ2YWJsZTsKICBFbWJlci50eXBlT2YgPSBfcnVudGltZS50eXBlT2Y7CiAgRW1iZXIuaXNBcnJheSA9IF9ydW50aW1lLmlzQXJyYXk7CiAgRW1iZXIuT2JqZWN0ID0gX3J1bnRpbWUuT2JqZWN0OwogIEVtYmVyLm9uTG9hZCA9IF9hcHBsaWNhdGlvbi5vbkxvYWQ7CiAgRW1iZXIucnVuTG9hZEhvb2tzID0gX2FwcGxpY2F0aW9uLnJ1bkxvYWRIb29rczsKICBFbWJlci5Db250cm9sbGVyID0gX2NvbnRyb2xsZXIuZGVmYXVsdDsKICBFbWJlci5Db250cm9sbGVyTWl4aW4gPSBfY29udHJvbGxlcl9taXhpbi5kZWZhdWx0OwogIEVtYmVyLlNlcnZpY2UgPSBfc2VydmljZS5kZWZhdWx0OwogIEVtYmVyLl9Qcm94eU1peGluID0gX3J1bnRpbWUuX1Byb3h5TWl4aW47CiAgRW1iZXIuUlNWUCA9IF9ydW50aW1lLlJTVlA7CiAgRW1iZXIuTmFtZXNwYWNlID0gX3J1bnRpbWUuTmFtZXNwYWNlOwogIEVtYmVyLl9hY3Rpb24gPSBfb2JqZWN0LmFjdGlvbjsKICBFbWJlci5fZGVwZW5kZW50S2V5Q29tcGF0ID0gX2NvbXBhdC5kZXBlbmRlbnRLZXlDb21wYXQ7CiAgY29tcHV0ZWQuZW1wdHkgPSBfY29tcHV0ZWQuZW1wdHk7CiAgY29tcHV0ZWQubm90RW1wdHkgPSBfY29tcHV0ZWQubm90RW1wdHk7CiAgY29tcHV0ZWQubm9uZSA9IF9jb21wdXRlZC5ub25lOwogIGNvbXB1dGVkLm5vdCA9IF9jb21wdXRlZC5ub3Q7CiAgY29tcHV0ZWQuYm9vbCA9IF9jb21wdXRlZC5ib29sOwogIGNvbXB1dGVkLm1hdGNoID0gX2NvbXB1dGVkLm1hdGNoOwogIGNvbXB1dGVkLmVxdWFsID0gX2NvbXB1dGVkLmVxdWFsOwogIGNvbXB1dGVkLmd0ID0gX2NvbXB1dGVkLmd0OwogIGNvbXB1dGVkLmd0ZSA9IF9jb21wdXRlZC5ndGU7CiAgY29tcHV0ZWQubHQgPSBfY29tcHV0ZWQubHQ7CiAgY29tcHV0ZWQubHRlID0gX2NvbXB1dGVkLmx0ZTsKICBjb21wdXRlZC5vbmVXYXkgPSBfY29tcHV0ZWQub25lV2F5OwogIGNvbXB1dGVkLnJlYWRzID0gX2NvbXB1dGVkLm9uZVdheTsKICBjb21wdXRlZC5yZWFkT25seSA9IF9jb21wdXRlZC5yZWFkT25seTsKICBjb21wdXRlZC5kZXByZWNhdGluZ0FsaWFzID0gX2NvbXB1dGVkLmRlcHJlY2F0aW5nQWxpYXM7CiAgY29tcHV0ZWQuYW5kID0gX2NvbXB1dGVkLmFuZDsKICBjb21wdXRlZC5vciA9IF9jb21wdXRlZC5vcjsKICBjb21wdXRlZC5zdW0gPSBfY29tcHV0ZWQuc3VtOwogIGNvbXB1dGVkLm1pbiA9IF9jb21wdXRlZC5taW47CiAgY29tcHV0ZWQubWF4ID0gX2NvbXB1dGVkLm1heDsKICBjb21wdXRlZC5tYXAgPSBfY29tcHV0ZWQubWFwOwogIGNvbXB1dGVkLnNvcnQgPSBfY29tcHV0ZWQuc29ydDsKICBjb21wdXRlZC5zZXREaWZmID0gX2NvbXB1dGVkLnNldERpZmY7CiAgY29tcHV0ZWQubWFwQnkgPSBfY29tcHV0ZWQubWFwQnk7CiAgY29tcHV0ZWQuZmlsdGVyID0gX2NvbXB1dGVkLmZpbHRlcjsKICBjb21wdXRlZC5maWx0ZXJCeSA9IF9jb21wdXRlZC5maWx0ZXJCeTsKICBjb21wdXRlZC51bmlxID0gX2NvbXB1dGVkLnVuaXE7CiAgY29tcHV0ZWQudW5pcUJ5ID0gX2NvbXB1dGVkLnVuaXFCeTsKICBjb21wdXRlZC51bmlvbiA9IF9jb21wdXRlZC51bmlvbjsKICBjb21wdXRlZC5pbnRlcnNlY3QgPSBfY29tcHV0ZWQuaW50ZXJzZWN0OwogIGNvbXB1dGVkLmNvbGxlY3QgPSBfY29tcHV0ZWQuY29sbGVjdDsKICAvKioKICAgIERlZmluZXMgdGhlIGhhc2ggb2YgbG9jYWxpemVkIHN0cmluZ3MgZm9yIHRoZSBjdXJyZW50IGxhbmd1YWdlLiBVc2VkIGJ5CiAgICB0aGUgYFN0cmluZy5sb2NgIGhlbHBlci4gVG8gbG9jYWxpemUsIGFkZCBzdHJpbmcgdmFsdWVzIHRvIHRoaXMKICAgIGhhc2guCiAgCiAgICBAcHJvcGVydHkgU1RSSU5HUwogICAgQGZvciBFbWJlcgogICAgQHR5cGUgT2JqZWN0CiAgICBAcHJpdmF0ZQogICovCgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFbWJlciwgJ1NUUklOR1MnLCB7CiAgICBjb25maWd1cmFibGU6IGZhbHNlLAogICAgZ2V0OiBfc3RyaW5nLl9nZXRTdHJpbmdzLAogICAgc2V0OiBfc3RyaW5nLl9zZXRTdHJpbmdzCiAgfSk7CiAgLyoqCiAgICBXaGV0aGVyIHNlYXJjaGluZyBvbiB0aGUgZ2xvYmFsIGZvciBuZXcgTmFtZXNwYWNlIGluc3RhbmNlcyBpcyBlbmFibGVkLgogIAogICAgVGhpcyBpcyBvbmx5IGV4cG9ydGVkIGhlcmUgYXMgdG8gbm90IGJyZWFrIGFueSBhZGRvbnMuICBHaXZlbiB0aGUgbmV3CiAgICB2aXNpdCBBUEksIHlvdSB3aWxsIGhhdmUgaXNzdWVzIGlmIHlvdSB0cmVhdCB0aGlzIGFzIGEgaW5kaWNhdG9yIG9mCiAgICBib290ZWQuCiAgCiAgICBJbnRlcm5hbGx5IHRoaXMgaXMgb25seSBleHBvc2luZyBhIGZsYWcgaW4gTmFtZXNwYWNlLgogIAogICAgQHByb3BlcnR5IEJPT1RFRAogICAgQGZvciBFbWJlcgogICAgQHR5cGUgQm9vbGVhbgogICAgQHByaXZhdGUKICAqLwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICdCT09URUQnLCB7CiAgICBjb25maWd1cmFibGU6IGZhbHNlLAogICAgZW51bWVyYWJsZTogZmFsc2UsCiAgICBnZXQ6IG1ldGFsLmlzTmFtZXNwYWNlU2VhcmNoRGlzYWJsZWQsCiAgICBzZXQ6IG1ldGFsLnNldE5hbWVzcGFjZVNlYXJjaERpc2FibGVkCiAgfSk7IC8vICoqKipAZW1iZXIvLWludGVybmFscy9nbGltbWVyKioqKgoKICBFbWJlci5Db21wb25lbnQgPSBfZ2xpbW1lci5Db21wb25lbnQ7CiAgX2dsaW1tZXIuSGVscGVyLmhlbHBlciA9IF9nbGltbWVyLmhlbHBlcjsKICBFbWJlci5IZWxwZXIgPSBfZ2xpbW1lci5IZWxwZXI7CiAgRW1iZXIuQ2hlY2tib3ggPSBfZ2xpbW1lci5DaGVja2JveDsKICBFbWJlci5UZXh0RmllbGQgPSBfZ2xpbW1lci5UZXh0RmllbGQ7CiAgRW1iZXIuVGV4dEFyZWEgPSBfZ2xpbW1lci5UZXh0QXJlYTsKICBFbWJlci5MaW5rQ29tcG9uZW50ID0gX2dsaW1tZXIuTGlua0NvbXBvbmVudDsKICBFbWJlci5fc2V0Q29tcG9uZW50TWFuYWdlciA9IF9nbGltbWVyLnNldENvbXBvbmVudE1hbmFnZXI7CiAgRW1iZXIuX2NvbXBvbmVudE1hbmFnZXJDYXBhYmlsaXRpZXMgPSBfZ2xpbW1lci5jYXBhYmlsaXRpZXM7CiAgRW1iZXIuX3NldE1vZGlmaWVyTWFuYWdlciA9IF9nbGltbWVyLnNldE1vZGlmaWVyTWFuYWdlcjsKICBFbWJlci5fbW9kaWZpZXJNYW5hZ2VyQ2FwYWJpbGl0aWVzID0gX2dsaW1tZXIubW9kaWZpZXJDYXBhYmlsaXRpZXM7CgogIGlmICh0cnVlCiAgLyogRU1CRVJfR0xJTU1FUl9TRVRfQ09NUE9ORU5UX1RFTVBMQVRFICovCiAgKSB7CiAgICAgIEVtYmVyLl9nZXRDb21wb25lbnRUZW1wbGF0ZSA9IF9nbGltbWVyLmdldENvbXBvbmVudFRlbXBsYXRlOwogICAgICBFbWJlci5fc2V0Q29tcG9uZW50VGVtcGxhdGUgPSBfZ2xpbW1lci5zZXRDb21wb25lbnRUZW1wbGF0ZTsKICAgICAgRW1iZXIuX3RlbXBsYXRlT25seUNvbXBvbmVudCA9IF90ZW1wbGF0ZU9ubHkuZGVmYXVsdDsKICAgIH0KCiAgRW1iZXIuSGFuZGxlYmFycyA9IHsKICAgIHRlbXBsYXRlOiBfZ2xpbW1lci50ZW1wbGF0ZSwKICAgIFV0aWxzOiB7CiAgICAgIGVzY2FwZUV4cHJlc3Npb246IF9nbGltbWVyLmVzY2FwZUV4cHJlc3Npb24KICAgIH0KICB9OwogIEVtYmVyLkhUTUxCYXJzID0gewogICAgdGVtcGxhdGU6IF9nbGltbWVyLnRlbXBsYXRlCiAgfTsKCiAgaWYgKF9lbnZpcm9ubWVudC5FTlYuRVhURU5EX1BST1RPVFlQRVMuU3RyaW5nKSB7CiAgICBTdHJpbmcucHJvdG90eXBlLmh0bWxTYWZlID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gKDAsIF9nbGltbWVyLmh0bWxTYWZlKSh0aGlzKTsKICAgIH07CiAgfQoKICBFbWJlci5TdHJpbmcuaHRtbFNhZmUgPSBfZ2xpbW1lci5odG1sU2FmZTsKICBFbWJlci5TdHJpbmcuaXNIVE1MU2FmZSA9IF9nbGltbWVyLmlzSFRNTFNhZmU7CiAgLyoqCiAgICBHbG9iYWwgaGFzaCBvZiBzaGFyZWQgdGVtcGxhdGVzLiBUaGlzIHdpbGwgYXV0b21hdGljYWxseSBiZSBwb3B1bGF0ZWQKICAgIGJ5IHRoZSBidWlsZCB0b29scyBzbyB0aGF0IHlvdSBjYW4gc3RvcmUgeW91ciBIYW5kbGViYXJzIHRlbXBsYXRlcyBpbgogICAgc2VwYXJhdGUgZmlsZXMgdGhhdCBnZXQgbG9hZGVkIGludG8gSmF2YVNjcmlwdCBhdCBidWlsZHRpbWUuCiAgCiAgICBAcHJvcGVydHkgVEVNUExBVEVTCiAgICBAZm9yIEVtYmVyCiAgICBAdHlwZSBPYmplY3QKICAgIEBwcml2YXRlCiAgKi8KCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEVtYmVyLCAnVEVNUExBVEVTJywgewogICAgZ2V0OiBfZ2xpbW1lci5nZXRUZW1wbGF0ZXMsCiAgICBzZXQ6IF9nbGltbWVyLnNldFRlbXBsYXRlcywKICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsCiAgICBlbnVtZXJhYmxlOiBmYWxzZQogIH0pOwogIC8qKgogICAgVGhlIHNlbWFudGljIHZlcnNpb24KICAKICAgIEBwcm9wZXJ0eSBWRVJTSU9OCiAgICBAdHlwZSBTdHJpbmcKICAgIEBwdWJsaWMKICAqLwoKICBFbWJlci5WRVJTSU9OID0gX3ZlcnNpb24uZGVmYXVsdDsgLy8gKioqKkBlbWJlci8taW50ZXJuYWxzL3ZpZXdzKioqKgoKICBpZiAoX2RlcHJlY2F0ZWRGZWF0dXJlcy5KUVVFUllfSU5URUdSQVRJT04gJiYgIXZpZXdzLmpRdWVyeURpc2FibGVkKSB7CiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICckJywgewogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgKDAsIEVtYmVyRGVidWcuZGVwcmVjYXRlKSgiVXNpbmcgRW1iZXIuJCgpIGhhcyBiZWVuIGRlcHJlY2F0ZWQsIHVzZSBgaW1wb3J0IGpRdWVyeSBmcm9tICdqcXVlcnknO2AgaW5zdGVhZCIsIGZhbHNlLCB7CiAgICAgICAgICBpZDogJ2VtYmVyLXZpZXdzLmN1cmx5LWNvbXBvbmVudHMuanF1ZXJ5LWVsZW1lbnQnLAogICAgICAgICAgdW50aWw6ICc0LjAuMCcsCiAgICAgICAgICB1cmw6ICdodHRwczovL2VtYmVyanMuY29tL2RlcHJlY2F0aW9ucy92My54I3RvY19qcXVlcnktYXBpcycKICAgICAgICB9KSk7CiAgICAgICAgcmV0dXJuIHZpZXdzLmpRdWVyeTsKICAgICAgfSwKICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICBlbnVtZXJhYmxlOiB0cnVlCiAgICB9KTsKICB9CgogIEVtYmVyLlZpZXdVdGlscyA9IHsKICAgIGlzU2ltcGxlQ2xpY2s6IHZpZXdzLmlzU2ltcGxlQ2xpY2ssCiAgICBnZXRFbGVtZW50Vmlldzogdmlld3MuZ2V0RWxlbWVudFZpZXcsCiAgICBnZXRWaWV3RWxlbWVudDogdmlld3MuZ2V0Vmlld0VsZW1lbnQsCiAgICBnZXRWaWV3Qm91bmRzOiB2aWV3cy5nZXRWaWV3Qm91bmRzLAogICAgZ2V0Vmlld0NsaWVudFJlY3RzOiB2aWV3cy5nZXRWaWV3Q2xpZW50UmVjdHMsCiAgICBnZXRWaWV3Qm91bmRpbmdDbGllbnRSZWN0OiB2aWV3cy5nZXRWaWV3Qm91bmRpbmdDbGllbnRSZWN0LAogICAgZ2V0Um9vdFZpZXdzOiB2aWV3cy5nZXRSb290Vmlld3MsCiAgICBnZXRDaGlsZFZpZXdzOiB2aWV3cy5nZXRDaGlsZFZpZXdzLAogICAgaXNTZXJpYWxpemF0aW9uRmlyc3ROb2RlOiBfZ2xpbW1lci5pc1NlcmlhbGl6YXRpb25GaXJzdE5vZGUKICB9OwogIEVtYmVyLlRleHRTdXBwb3J0ID0gdmlld3MuVGV4dFN1cHBvcnQ7CiAgRW1iZXIuQ29tcG9uZW50TG9va3VwID0gdmlld3MuQ29tcG9uZW50TG9va3VwOwogIEVtYmVyLkV2ZW50RGlzcGF0Y2hlciA9IHZpZXdzLkV2ZW50RGlzcGF0Y2hlcjsgLy8gKioqKkBlbWJlci8taW50ZXJuYWxzL3JvdXRpbmcqKioqCgogIEVtYmVyLkxvY2F0aW9uID0gcm91dGluZy5Mb2NhdGlvbjsKICBFbWJlci5BdXRvTG9jYXRpb24gPSByb3V0aW5nLkF1dG9Mb2NhdGlvbjsKICBFbWJlci5IYXNoTG9jYXRpb24gPSByb3V0aW5nLkhhc2hMb2NhdGlvbjsKICBFbWJlci5IaXN0b3J5TG9jYXRpb24gPSByb3V0aW5nLkhpc3RvcnlMb2NhdGlvbjsKICBFbWJlci5Ob25lTG9jYXRpb24gPSByb3V0aW5nLk5vbmVMb2NhdGlvbjsKICBFbWJlci5jb250cm9sbGVyRm9yID0gcm91dGluZy5jb250cm9sbGVyRm9yOwogIEVtYmVyLmdlbmVyYXRlQ29udHJvbGxlckZhY3RvcnkgPSByb3V0aW5nLmdlbmVyYXRlQ29udHJvbGxlckZhY3Rvcnk7CiAgRW1iZXIuZ2VuZXJhdGVDb250cm9sbGVyID0gcm91dGluZy5nZW5lcmF0ZUNvbnRyb2xsZXI7CiAgRW1iZXIuUm91dGVyRFNMID0gcm91dGluZy5Sb3V0ZXJEU0w7CiAgRW1iZXIuUm91dGVyID0gcm91dGluZy5Sb3V0ZXI7CiAgRW1iZXIuUm91dGUgPSByb3V0aW5nLlJvdXRlOwogICgwLCBfYXBwbGljYXRpb24ucnVuTG9hZEhvb2tzKSgnRW1iZXIuQXBwbGljYXRpb24nLCBfYXBwbGljYXRpb24uZGVmYXVsdCk7CiAgRW1iZXIuRGF0YUFkYXB0ZXIgPSBleHRlbnNpb25TdXBwb3J0LkRhdGFBZGFwdGVyOwogIEVtYmVyLkNvbnRhaW5lckRlYnVnQWRhcHRlciA9IGV4dGVuc2lvblN1cHBvcnQuQ29udGFpbmVyRGVidWdBZGFwdGVyOwoKICBpZiAoKDAsIF9yZXF1aXJlLmhhcykoJ2VtYmVyLXRlbXBsYXRlLWNvbXBpbGVyJykpIHsKICAgICgwLCBfcmVxdWlyZS5kZWZhdWx0KSgiZW1iZXItdGVtcGxhdGUtY29tcGlsZXIiKTsKICB9IC8vIGRvIHRoaXMgdG8gZW5zdXJlIHRoYXQgRW1iZXIuVGVzdCBpcyBkZWZpbmVkIHByb3Blcmx5IG9uIHRoZSBnbG9iYWwKICAvLyBpZiBpdCBpcyBwcmVzZW50LgoKCiAgaWYgKCgwLCBfcmVxdWlyZS5oYXMpKCdlbWJlci10ZXN0aW5nJykpIHsKICAgIHZhciB0ZXN0aW5nID0gKDAsIF9yZXF1aXJlLmRlZmF1bHQpKCJlbWJlci10ZXN0aW5nIik7CiAgICBFbWJlci5UZXN0ID0gdGVzdGluZy5UZXN0OwogICAgRW1iZXIuVGVzdC5BZGFwdGVyID0gdGVzdGluZy5BZGFwdGVyOwogICAgRW1iZXIuVGVzdC5RVW5pdEFkYXB0ZXIgPSB0ZXN0aW5nLlFVbml0QWRhcHRlcjsKICAgIEVtYmVyLnNldHVwRm9yVGVzdGluZyA9IHRlc3Rpbmcuc2V0dXBGb3JUZXN0aW5nOwogIH0KCiAgKDAsIF9hcHBsaWNhdGlvbi5ydW5Mb2FkSG9va3MpKCdFbWJlcicpOwogIHZhciBfZGVmYXVsdCA9IEVtYmVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKCiAgaWYgKF9ub2RlTW9kdWxlLklTX05PREUpIHsKICAgIF9ub2RlTW9kdWxlLm1vZHVsZS5leHBvcnRzID0gRW1iZXI7CiAgfSBlbHNlIHsKICAgIF9lbnZpcm9ubWVudC5jb250ZXh0LmV4cG9ydHMuRW1iZXIgPSBfZW52aXJvbm1lbnQuY29udGV4dC5leHBvcnRzLkVtID0gRW1iZXI7CiAgfQogIC8qKgogICBAbW9kdWxlIGpxdWVyeQogICBAcHVibGljCiAgICovCgogIC8qKgogICBAY2xhc3MganF1ZXJ5CiAgIEBwdWJsaWMKICAgQHN0YXRpYwogICAqLwoKICAvKioKICAgIEFsaWFzIGZvciBqUXVlcnkKICAKICAgIEBmb3IganF1ZXJ5CiAgICBAbWV0aG9kICQKICAgIEBzdGF0aWMKICAgIEBwdWJsaWMKICAqLwoKfSk7CmRlZmluZSgiZW1iZXIvdmVyc2lvbiIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CiAgdmFyIF9kZWZhdWx0ID0gIjMuMTMuMyI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJub2RlLW1vZHVsZS9pbmRleCIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLnJlcXVpcmUgPSBfZXhwb3J0cy5tb2R1bGUgPSBfZXhwb3J0cy5JU19OT0RFID0gdm9pZCAwOwoKICAvKmdsb2JhbCBtb2R1bGUgKi8KICB2YXIgSVNfTk9ERSA9IHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUucmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJzsKICBfZXhwb3J0cy5JU19OT0RFID0gSVNfTk9ERTsKICB2YXIgZXhwb3J0TW9kdWxlOwogIF9leHBvcnRzLm1vZHVsZSA9IGV4cG9ydE1vZHVsZTsKICB2YXIgZXhwb3J0UmVxdWlyZTsKICBfZXhwb3J0cy5yZXF1aXJlID0gZXhwb3J0UmVxdWlyZTsKCiAgaWYgKElTX05PREUpIHsKICAgIF9leHBvcnRzLm1vZHVsZSA9IGV4cG9ydE1vZHVsZSA9IG1vZHVsZTsKICAgIF9leHBvcnRzLnJlcXVpcmUgPSBleHBvcnRSZXF1aXJlID0gbW9kdWxlLnJlcXVpcmU7CiAgfSBlbHNlIHsKICAgIF9leHBvcnRzLm1vZHVsZSA9IGV4cG9ydE1vZHVsZSA9IG51bGw7CiAgICBfZXhwb3J0cy5yZXF1aXJlID0gZXhwb3J0UmVxdWlyZSA9IG51bGw7CiAgfQp9KTsKZGVmaW5lKCJyb3V0ZS1yZWNvZ25pemVyIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKICB2YXIgY3JlYXRlT2JqZWN0ID0gT2JqZWN0LmNyZWF0ZTsKCiAgZnVuY3Rpb24gY3JlYXRlTWFwKCkgewogICAgdmFyIG1hcCA9IGNyZWF0ZU9iamVjdChudWxsKTsKICAgIG1hcFsiX18iXSA9IHVuZGVmaW5lZDsKICAgIGRlbGV0ZSBtYXBbIl9fIl07CiAgICByZXR1cm4gbWFwOwogIH0KCiAgdmFyIFRhcmdldCA9IGZ1bmN0aW9uIFRhcmdldChwYXRoLCBtYXRjaGVyLCBkZWxlZ2F0ZSkgewogICAgdGhpcy5wYXRoID0gcGF0aDsKICAgIHRoaXMubWF0Y2hlciA9IG1hdGNoZXI7CiAgICB0aGlzLmRlbGVnYXRlID0gZGVsZWdhdGU7CiAgfTsKCiAgVGFyZ2V0LnByb3RvdHlwZS50byA9IGZ1bmN0aW9uIHRvKHRhcmdldCwgY2FsbGJhY2spIHsKICAgIHZhciBkZWxlZ2F0ZSA9IHRoaXMuZGVsZWdhdGU7CgogICAgaWYgKGRlbGVnYXRlICYmIGRlbGVnYXRlLndpbGxBZGRSb3V0ZSkgewogICAgICB0YXJnZXQgPSBkZWxlZ2F0ZS53aWxsQWRkUm91dGUodGhpcy5tYXRjaGVyLnRhcmdldCwgdGFyZ2V0KTsKICAgIH0KCiAgICB0aGlzLm1hdGNoZXIuYWRkKHRoaXMucGF0aCwgdGFyZ2V0KTsKCiAgICBpZiAoY2FsbGJhY2spIHsKICAgICAgaWYgKGNhbGxiYWNrLmxlbmd0aCA9PT0gMCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiWW91IG11c3QgaGF2ZSBhbiBhcmd1bWVudCBpbiB0aGUgZnVuY3Rpb24gcGFzc2VkIHRvIGB0b2AiKTsKICAgICAgfQoKICAgICAgdGhpcy5tYXRjaGVyLmFkZENoaWxkKHRoaXMucGF0aCwgdGFyZ2V0LCBjYWxsYmFjaywgdGhpcy5kZWxlZ2F0ZSk7CiAgICB9CiAgfTsKCiAgdmFyIE1hdGNoZXIgPSBmdW5jdGlvbiBNYXRjaGVyKHRhcmdldCkgewogICAgdGhpcy5yb3V0ZXMgPSBjcmVhdGVNYXAoKTsKICAgIHRoaXMuY2hpbGRyZW4gPSBjcmVhdGVNYXAoKTsKICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0OwogIH07CgogIE1hdGNoZXIucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uIGFkZChwYXRoLCB0YXJnZXQpIHsKICAgIHRoaXMucm91dGVzW3BhdGhdID0gdGFyZ2V0OwogIH07CgogIE1hdGNoZXIucHJvdG90eXBlLmFkZENoaWxkID0gZnVuY3Rpb24gYWRkQ2hpbGQocGF0aCwgdGFyZ2V0LCBjYWxsYmFjaywgZGVsZWdhdGUpIHsKICAgIHZhciBtYXRjaGVyID0gbmV3IE1hdGNoZXIodGFyZ2V0KTsKICAgIHRoaXMuY2hpbGRyZW5bcGF0aF0gPSBtYXRjaGVyOwogICAgdmFyIG1hdGNoID0gZ2VuZXJhdGVNYXRjaChwYXRoLCBtYXRjaGVyLCBkZWxlZ2F0ZSk7CgogICAgaWYgKGRlbGVnYXRlICYmIGRlbGVnYXRlLmNvbnRleHRFbnRlcmVkKSB7CiAgICAgIGRlbGVnYXRlLmNvbnRleHRFbnRlcmVkKHRhcmdldCwgbWF0Y2gpOwogICAgfQoKICAgIGNhbGxiYWNrKG1hdGNoKTsKICB9OwoKICBmdW5jdGlvbiBnZW5lcmF0ZU1hdGNoKHN0YXJ0aW5nUGF0aCwgbWF0Y2hlciwgZGVsZWdhdGUpIHsKICAgIGZ1bmN0aW9uIG1hdGNoKHBhdGgsIGNhbGxiYWNrKSB7CiAgICAgIHZhciBmdWxsUGF0aCA9IHN0YXJ0aW5nUGF0aCArIHBhdGg7CgogICAgICBpZiAoY2FsbGJhY2spIHsKICAgICAgICBjYWxsYmFjayhnZW5lcmF0ZU1hdGNoKGZ1bGxQYXRoLCBtYXRjaGVyLCBkZWxlZ2F0ZSkpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBuZXcgVGFyZ2V0KGZ1bGxQYXRoLCBtYXRjaGVyLCBkZWxlZ2F0ZSk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gbWF0Y2g7CiAgfQoKICBmdW5jdGlvbiBhZGRSb3V0ZShyb3V0ZUFycmF5LCBwYXRoLCBoYW5kbGVyKSB7CiAgICB2YXIgbGVuID0gMDsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvdXRlQXJyYXkubGVuZ3RoOyBpKyspIHsKICAgICAgbGVuICs9IHJvdXRlQXJyYXlbaV0ucGF0aC5sZW5ndGg7CiAgICB9CgogICAgcGF0aCA9IHBhdGguc3Vic3RyKGxlbik7CiAgICB2YXIgcm91dGUgPSB7CiAgICAgIHBhdGg6IHBhdGgsCiAgICAgIGhhbmRsZXI6IGhhbmRsZXIKICAgIH07CiAgICByb3V0ZUFycmF5LnB1c2gocm91dGUpOwogIH0KCiAgZnVuY3Rpb24gZWFjaFJvdXRlKGJhc2VSb3V0ZSwgbWF0Y2hlciwgY2FsbGJhY2ssIGJpbmRpbmcpIHsKICAgIHZhciByb3V0ZXMgPSBtYXRjaGVyLnJvdXRlczsKICAgIHZhciBwYXRocyA9IE9iamVjdC5rZXlzKHJvdXRlcyk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRocy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgcGF0aCA9IHBhdGhzW2ldOwogICAgICB2YXIgcm91dGVBcnJheSA9IGJhc2VSb3V0ZS5zbGljZSgpOwogICAgICBhZGRSb3V0ZShyb3V0ZUFycmF5LCBwYXRoLCByb3V0ZXNbcGF0aF0pOwogICAgICB2YXIgbmVzdGVkID0gbWF0Y2hlci5jaGlsZHJlbltwYXRoXTsKCiAgICAgIGlmIChuZXN0ZWQpIHsKICAgICAgICBlYWNoUm91dGUocm91dGVBcnJheSwgbmVzdGVkLCBjYWxsYmFjaywgYmluZGluZyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY2FsbGJhY2suY2FsbChiaW5kaW5nLCByb3V0ZUFycmF5KTsKICAgICAgfQogICAgfQogIH0KCiAgdmFyIG1hcCA9IGZ1bmN0aW9uIG1hcChjYWxsYmFjaywgYWRkUm91dGVDYWxsYmFjaykgewogICAgdmFyIG1hdGNoZXIgPSBuZXcgTWF0Y2hlcigpOwogICAgY2FsbGJhY2soZ2VuZXJhdGVNYXRjaCgiIiwgbWF0Y2hlciwgdGhpcy5kZWxlZ2F0ZSkpOwogICAgZWFjaFJvdXRlKFtdLCBtYXRjaGVyLCBmdW5jdGlvbiAocm91dGVzKSB7CiAgICAgIGlmIChhZGRSb3V0ZUNhbGxiYWNrKSB7CiAgICAgICAgYWRkUm91dGVDYWxsYmFjayh0aGlzLCByb3V0ZXMpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuYWRkKHJvdXRlcyk7CiAgICAgIH0KICAgIH0sIHRoaXMpOwogIH07IC8vIE5vcm1hbGl6ZXMgcGVyY2VudC1lbmNvZGVkIHZhbHVlcyBpbiBgcGF0aGAgdG8gdXBwZXItY2FzZSBhbmQgZGVjb2RlcyBwZXJjZW50LWVuY29kZWQKICAvLyB2YWx1ZXMgdGhhdCBhcmUgbm90IHJlc2VydmVkIChpLmUuLCB1bmljb2RlIGNoYXJhY3RlcnMsIGVtb2ppLCBldGMpLiBUaGUgcmVzZXJ2ZWQKICAvLyBjaGFycyBhcmUgIi8iIGFuZCAiJSIuCiAgLy8gU2FmZSB0byBjYWxsIG11bHRpcGxlIHRpbWVzIG9uIHRoZSBzYW1lIHBhdGguCiAgLy8gTm9ybWFsaXplcyBwZXJjZW50LWVuY29kZWQgdmFsdWVzIGluIGBwYXRoYCB0byB1cHBlci1jYXNlIGFuZCBkZWNvZGVzIHBlcmNlbnQtZW5jb2RlZAoKCiAgZnVuY3Rpb24gbm9ybWFsaXplUGF0aChwYXRoKSB7CiAgICByZXR1cm4gcGF0aC5zcGxpdCgiLyIpLm1hcChub3JtYWxpemVTZWdtZW50KS5qb2luKCIvIik7CiAgfSAvLyBXZSB3YW50IHRvIGVuc3VyZSB0aGUgY2hhcmFjdGVycyAiJSIgYW5kICIvIiByZW1haW4gaW4gcGVyY2VudC1lbmNvZGVkCiAgLy8gZm9ybSB3aGVuIG5vcm1hbGl6aW5nIHBhdGhzLCBzbyByZXBsYWNlIHRoZW0gd2l0aCB0aGVpciBlbmNvZGVkIGZvcm0gYWZ0ZXIKICAvLyBkZWNvZGluZyB0aGUgcmVzdCBvZiB0aGUgcGF0aAoKCiAgdmFyIFNFR01FTlRfUkVTRVJWRURfQ0hBUlMgPSAvJXxcLy9nOwoKICBmdW5jdGlvbiBub3JtYWxpemVTZWdtZW50KHNlZ21lbnQpIHsKICAgIGlmIChzZWdtZW50Lmxlbmd0aCA8IDMgfHwgc2VnbWVudC5pbmRleE9mKCIlIikgPT09IC0xKSB7CiAgICAgIHJldHVybiBzZWdtZW50OwogICAgfQoKICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQoc2VnbWVudCkucmVwbGFjZShTRUdNRU5UX1JFU0VSVkVEX0NIQVJTLCBlbmNvZGVVUklDb21wb25lbnQpOwogIH0gLy8gV2UgZG8gbm90IHdhbnQgdG8gZW5jb2RlIHRoZXNlIGNoYXJhY3RlcnMgd2hlbiBnZW5lcmF0aW5nIGR5bmFtaWMgcGF0aCBzZWdtZW50cwogIC8vIFNlZSBodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjMzk4NiNzZWN0aW9uLTMuMwogIC8vIHN1Yi1kZWxpbXM6ICIhIiwgIiQiLCAiJiIsICInIiwgIigiLCAiKSIsICIqIiwgIisiLCAiLCIsICI7IiwgIj0iCiAgLy8gb3RoZXJzIGFsbG93ZWQgYnkgUkZDIDM5ODY6ICI6IiwgIkAiCiAgLy8KICAvLyBGaXJzdCBlbmNvZGUgdGhlIGVudGlyZSBwYXRoIHNlZ21lbnQsIHRoZW4gZGVjb2RlIGFueSBvZiB0aGUgZW5jb2RlZCBzcGVjaWFsIGNoYXJzLgogIC8vCiAgLy8gVGhlIGNoYXJzICIhIiwgIiciLCAiKCIsICIpIiwgIioiIGRvIG5vdCBnZXQgY2hhbmdlZCBieSBgZW5jb2RlVVJJQ29tcG9uZW50YCwKICAvLyBzbyB0aGUgcG9zc2libGUgZW5jb2RlZCBjaGFycyBhcmU6CiAgLy8gWyclMjQnLCAnJTI2JywgJyUyQicsICclMkMnLCAnJTNCJywgJyUzRCcsICclM0EnLCAnJTQwJ10uCgoKICB2YXIgUEFUSF9TRUdNRU5UX0VOQ09ESU5HUyA9IC8lKD86Mig/OjR8NnxCfEMpfDMoPzpCfER8QSl8NDApL2c7CgogIGZ1bmN0aW9uIGVuY29kZVBhdGhTZWdtZW50KHN0cikgewogICAgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoUEFUSF9TRUdNRU5UX0VOQ09ESU5HUywgZGVjb2RlVVJJQ29tcG9uZW50KTsKICB9CgogIHZhciBlc2NhcGVSZWdleCA9IC8oXC98XC58XCp8XCt8XD98XHx8XCh8XCl8XFt8XF18XHt8XH18XFwpL2c7CiAgdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5OwogIHZhciBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7CgogIGZ1bmN0aW9uIGdldFBhcmFtKHBhcmFtcywga2V5KSB7CiAgICBpZiAodHlwZW9mIHBhcmFtcyAhPT0gIm9iamVjdCIgfHwgcGFyYW1zID09PSBudWxsKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiWW91IG11c3QgcGFzcyBhbiBvYmplY3QgYXMgdGhlIHNlY29uZCBhcmd1bWVudCB0byBgZ2VuZXJhdGVgLiIpOwogICAgfQoKICAgIGlmICghaGFzT3duUHJvcGVydHkuY2FsbChwYXJhbXMsIGtleSkpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJZb3UgbXVzdCBwcm92aWRlIHBhcmFtIGAiICsga2V5ICsgImAgdG8gYGdlbmVyYXRlYC4iKTsKICAgIH0KCiAgICB2YXIgdmFsdWUgPSBwYXJhbXNba2V5XTsKICAgIHZhciBzdHIgPSB0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciID8gdmFsdWUgOiAiIiArIHZhbHVlOwoKICAgIGlmIChzdHIubGVuZ3RoID09PSAwKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiWW91IG11c3QgcHJvdmlkZSBhIHBhcmFtIGAiICsga2V5ICsgImAuIik7CiAgICB9CgogICAgcmV0dXJuIHN0cjsKICB9CgogIHZhciBlYWNoQ2hhciA9IFtdOwoKICBlYWNoQ2hhclswCiAgLyogU3RhdGljICovCiAgXSA9IGZ1bmN0aW9uIChzZWdtZW50LCBjdXJyZW50U3RhdGUpIHsKICAgIHZhciBzdGF0ZSA9IGN1cnJlbnRTdGF0ZTsKICAgIHZhciB2YWx1ZSA9IHNlZ21lbnQudmFsdWU7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWx1ZS5sZW5ndGg7IGkrKykgewogICAgICB2YXIgY2ggPSB2YWx1ZS5jaGFyQ29kZUF0KGkpOwogICAgICBzdGF0ZSA9IHN0YXRlLnB1dChjaCwgZmFsc2UsIGZhbHNlKTsKICAgIH0KCiAgICByZXR1cm4gc3RhdGU7CiAgfTsKCiAgZWFjaENoYXJbMQogIC8qIER5bmFtaWMgKi8KICBdID0gZnVuY3Rpb24gKF8sIGN1cnJlbnRTdGF0ZSkgewogICAgcmV0dXJuIGN1cnJlbnRTdGF0ZS5wdXQoNDcKICAgIC8qIFNMQVNIICovCiAgICAsIHRydWUsIHRydWUpOwogIH07CgogIGVhY2hDaGFyWzIKICAvKiBTdGFyICovCiAgXSA9IGZ1bmN0aW9uIChfLCBjdXJyZW50U3RhdGUpIHsKICAgIHJldHVybiBjdXJyZW50U3RhdGUucHV0KC0xCiAgICAvKiBBTlkgKi8KICAgICwgZmFsc2UsIHRydWUpOwogIH07CgogIGVhY2hDaGFyWzQKICAvKiBFcHNpbG9uICovCiAgXSA9IGZ1bmN0aW9uIChfLCBjdXJyZW50U3RhdGUpIHsKICAgIHJldHVybiBjdXJyZW50U3RhdGU7CiAgfTsKCiAgdmFyIHJlZ2V4ID0gW107CgogIHJlZ2V4WzAKICAvKiBTdGF0aWMgKi8KICBdID0gZnVuY3Rpb24gKHNlZ21lbnQpIHsKICAgIHJldHVybiBzZWdtZW50LnZhbHVlLnJlcGxhY2UoZXNjYXBlUmVnZXgsICJcXCQxIik7CiAgfTsKCiAgcmVnZXhbMQogIC8qIER5bmFtaWMgKi8KICBdID0gZnVuY3Rpb24gKCkgewogICAgcmV0dXJuICIoW14vXSspIjsKICB9OwoKICByZWdleFsyCiAgLyogU3RhciAqLwogIF0gPSBmdW5jdGlvbiAoKSB7CiAgICByZXR1cm4gIiguKykiOwogIH07CgogIHJlZ2V4WzQKICAvKiBFcHNpbG9uICovCiAgXSA9IGZ1bmN0aW9uICgpIHsKICAgIHJldHVybiAiIjsKICB9OwoKICB2YXIgZ2VuZXJhdGUgPSBbXTsKCiAgZ2VuZXJhdGVbMAogIC8qIFN0YXRpYyAqLwogIF0gPSBmdW5jdGlvbiAoc2VnbWVudCkgewogICAgcmV0dXJuIHNlZ21lbnQudmFsdWU7CiAgfTsKCiAgZ2VuZXJhdGVbMQogIC8qIER5bmFtaWMgKi8KICBdID0gZnVuY3Rpb24gKHNlZ21lbnQsIHBhcmFtcykgewogICAgdmFyIHZhbHVlID0gZ2V0UGFyYW0ocGFyYW1zLCBzZWdtZW50LnZhbHVlKTsKCiAgICBpZiAoUm91dGVSZWNvZ25pemVyLkVOQ09ERV9BTkRfREVDT0RFX1BBVEhfU0VHTUVOVFMpIHsKICAgICAgcmV0dXJuIGVuY29kZVBhdGhTZWdtZW50KHZhbHVlKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KICB9OwoKICBnZW5lcmF0ZVsyCiAgLyogU3RhciAqLwogIF0gPSBmdW5jdGlvbiAoc2VnbWVudCwgcGFyYW1zKSB7CiAgICByZXR1cm4gZ2V0UGFyYW0ocGFyYW1zLCBzZWdtZW50LnZhbHVlKTsKICB9OwoKICBnZW5lcmF0ZVs0CiAgLyogRXBzaWxvbiAqLwogIF0gPSBmdW5jdGlvbiAoKSB7CiAgICByZXR1cm4gIiI7CiAgfTsKCiAgdmFyIEVtcHR5T2JqZWN0ID0gT2JqZWN0LmZyZWV6ZSh7fSk7CiAgdmFyIEVtcHR5QXJyYXkgPSBPYmplY3QuZnJlZXplKFtdKTsgLy8gVGhlIGBuYW1lc2Agd2lsbCBiZSBwb3B1bGF0ZWQgd2l0aCB0aGUgcGFyYW10ZXIgbmFtZSBmb3IgZWFjaCBkeW5hbWljL3N0YXIKICAvLyBzZWdtZW50LiBgc2hvdWxkRGVjb2Rlc2Agd2lsbCBiZSBwb3B1bGF0ZWQgd2l0aCBhIGJvb2xlYW4gZm9yIGVhY2ggZHlhbmFtaWMvc3RhcgogIC8vIHNlZ21lbnQsIGluZGljYXRpbmcgd2hldGhlciBpdCBzaG91bGQgYmUgZGVjb2RlZCBkdXJpbmcgcmVjb2duaXRpb24uCgogIGZ1bmN0aW9uIHBhcnNlKHNlZ21lbnRzLCByb3V0ZSwgdHlwZXMpIHsKICAgIC8vIG5vcm1hbGl6ZSByb3V0ZSBhcyBub3Qgc3RhcnRpbmcgd2l0aCBhICIvIi4gUmVjb2duaXRpb24gd2lsbAogICAgLy8gYWxzbyBub3JtYWxpemUuCiAgICBpZiAocm91dGUubGVuZ3RoID4gMCAmJiByb3V0ZS5jaGFyQ29kZUF0KDApID09PSA0NwogICAgLyogU0xBU0ggKi8KICAgICkgewogICAgICAgIHJvdXRlID0gcm91dGUuc3Vic3RyKDEpOwogICAgICB9CgogICAgdmFyIHBhcnRzID0gcm91dGUuc3BsaXQoIi8iKTsKICAgIHZhciBuYW1lcyA9IHVuZGVmaW5lZDsKICAgIHZhciBzaG91bGREZWNvZGVzID0gdW5kZWZpbmVkOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIHBhcnQgPSBwYXJ0c1tpXTsKICAgICAgdmFyIGZsYWdzID0gMDsKICAgICAgdmFyIHR5cGUgPSAwOwoKICAgICAgaWYgKHBhcnQgPT09ICIiKSB7CiAgICAgICAgdHlwZSA9IDQKICAgICAgICAvKiBFcHNpbG9uICovCiAgICAgICAgOwogICAgICB9IGVsc2UgaWYgKHBhcnQuY2hhckNvZGVBdCgwKSA9PT0gNTgKICAgICAgLyogQ09MT04gKi8KICAgICAgKSB7CiAgICAgICAgICB0eXBlID0gMQogICAgICAgICAgLyogRHluYW1pYyAqLwogICAgICAgICAgOwogICAgICAgIH0gZWxzZSBpZiAocGFydC5jaGFyQ29kZUF0KDApID09PSA0MgogICAgICAvKiBTVEFSICovCiAgICAgICkgewogICAgICAgICAgdHlwZSA9IDIKICAgICAgICAgIC8qIFN0YXIgKi8KICAgICAgICAgIDsKICAgICAgICB9IGVsc2UgewogICAgICAgIHR5cGUgPSAwCiAgICAgICAgLyogU3RhdGljICovCiAgICAgICAgOwogICAgICB9CgogICAgICBmbGFncyA9IDIgPDwgdHlwZTsKCiAgICAgIGlmIChmbGFncyAmIDEyCiAgICAgIC8qIE5hbWVkICovCiAgICAgICkgewogICAgICAgICAgcGFydCA9IHBhcnQuc2xpY2UoMSk7CiAgICAgICAgICBuYW1lcyA9IG5hbWVzIHx8IFtdOwogICAgICAgICAgbmFtZXMucHVzaChwYXJ0KTsKICAgICAgICAgIHNob3VsZERlY29kZXMgPSBzaG91bGREZWNvZGVzIHx8IFtdOwogICAgICAgICAgc2hvdWxkRGVjb2Rlcy5wdXNoKChmbGFncyAmIDQKICAgICAgICAgIC8qIERlY29kZWQgKi8KICAgICAgICAgICkgIT09IDApOwogICAgICAgIH0KCiAgICAgIGlmIChmbGFncyAmIDE0CiAgICAgIC8qIENvdW50ZWQgKi8KICAgICAgKSB7CiAgICAgICAgICB0eXBlc1t0eXBlXSsrOwogICAgICAgIH0KCiAgICAgIHNlZ21lbnRzLnB1c2goewogICAgICAgIHR5cGU6IHR5cGUsCiAgICAgICAgdmFsdWU6IG5vcm1hbGl6ZVNlZ21lbnQocGFydCkKICAgICAgfSk7CiAgICB9CgogICAgcmV0dXJuIHsKICAgICAgbmFtZXM6IG5hbWVzIHx8IEVtcHR5QXJyYXksCiAgICAgIHNob3VsZERlY29kZXM6IHNob3VsZERlY29kZXMgfHwgRW1wdHlBcnJheQogICAgfTsKICB9CgogIGZ1bmN0aW9uIGlzRXF1YWxDaGFyU3BlYyhzcGVjLCBjaGFyLCBuZWdhdGUpIHsKICAgIHJldHVybiBzcGVjLmNoYXIgPT09IGNoYXIgJiYgc3BlYy5uZWdhdGUgPT09IG5lZ2F0ZTsKICB9IC8vIEEgU3RhdGUgaGFzIGEgY2hhcmFjdGVyIHNwZWNpZmljYXRpb24gYW5kIChgY2hhclNwZWNgKSBhbmQgYSBsaXN0IG9mIHBvc3NpYmxlCiAgLy8gc3Vic2VxdWVudCBzdGF0ZXMgKGBuZXh0U3RhdGVzYCkuCiAgLy8KICAvLyBJZiBhIFN0YXRlIGlzIGFuIGFjY2VwdGluZyBzdGF0ZSwgaXQgd2lsbCBhbHNvIGhhdmUgc2V2ZXJhbCBhZGRpdGlvbmFsCiAgLy8gcHJvcGVydGllczoKICAvLwogIC8vICogYHJlZ2V4YDogQSByZWd1bGFyIGV4cHJlc3Npb24gdGhhdCBpcyB1c2VkIHRvIGV4dHJhY3QgcGFyYW1ldGVycyBmcm9tIHBhdGhzCiAgLy8gICB0aGF0IHJlYWNoZWQgdGhpcyBhY2NlcHRpbmcgc3RhdGUuCiAgLy8gKiBgaGFuZGxlcnNgOiBJbmZvcm1hdGlvbiBvbiBob3cgdG8gY29udmVydCB0aGUgbGlzdCBvZiBjYXB0dXJlcyBpbnRvIGNhbGxzCiAgLy8gICB0byByZWdpc3RlcmVkIGhhbmRsZXJzIHdpdGggdGhlIHNwZWNpZmllZCBwYXJhbWV0ZXJzCiAgLy8gKiBgdHlwZXNgOiBIb3cgbWFueSBzdGF0aWMsIGR5bmFtaWMgb3Igc3RhciBzZWdtZW50cyBpbiB0aGlzIHJvdXRlLiBVc2VkIHRvCiAgLy8gICBkZWNpZGUgd2hpY2ggcm91dGUgdG8gdXNlIGlmIG11bHRpcGxlIHJlZ2lzdGVyZWQgcm91dGVzIG1hdGNoIGEgcGF0aC4KICAvLwogIC8vIEN1cnJlbnRseSwgU3RhdGUgaXMgaW1wbGVtZW50ZWQgbmFpdmVseSBieSBsb29waW5nIG92ZXIgYG5leHRTdGF0ZXNgIGFuZAogIC8vIGNvbXBhcmluZyBhIGNoYXJhY3RlciBzcGVjaWZpY2F0aW9uIGFnYWluc3QgYSBjaGFyYWN0ZXIuIEEgbW9yZSBlZmZpY2llbnQKICAvLyBpbXBsZW1lbnRhdGlvbiB3b3VsZCB1c2UgYSBoYXNoIG9mIGtleXMgcG9pbnRpbmcgYXQgb25lIG9yIG1vcmUgbmV4dCBzdGF0ZXMuCgoKICB2YXIgU3RhdGUgPSBmdW5jdGlvbiBTdGF0ZShzdGF0ZXMsIGlkLCBjaGFyLCBuZWdhdGUsIHJlcGVhdCkgewogICAgdGhpcy5zdGF0ZXMgPSBzdGF0ZXM7CiAgICB0aGlzLmlkID0gaWQ7CiAgICB0aGlzLmNoYXIgPSBjaGFyOwogICAgdGhpcy5uZWdhdGUgPSBuZWdhdGU7CiAgICB0aGlzLm5leHRTdGF0ZXMgPSByZXBlYXQgPyBpZCA6IG51bGw7CiAgICB0aGlzLnBhdHRlcm4gPSAiIjsKICAgIHRoaXMuX3JlZ2V4ID0gdW5kZWZpbmVkOwogICAgdGhpcy5oYW5kbGVycyA9IHVuZGVmaW5lZDsKICAgIHRoaXMudHlwZXMgPSB1bmRlZmluZWQ7CiAgfTsKCiAgU3RhdGUucHJvdG90eXBlLnJlZ2V4ID0gZnVuY3Rpb24gcmVnZXgkMSgpIHsKICAgIGlmICghdGhpcy5fcmVnZXgpIHsKICAgICAgdGhpcy5fcmVnZXggPSBuZXcgUmVnRXhwKHRoaXMucGF0dGVybik7CiAgICB9CgogICAgcmV0dXJuIHRoaXMuX3JlZ2V4OwogIH07CgogIFN0YXRlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiBnZXQoY2hhciwgbmVnYXRlKSB7CiAgICB2YXIgdGhpcyQxID0gdGhpczsKICAgIHZhciBuZXh0U3RhdGVzID0gdGhpcy5uZXh0U3RhdGVzOwoKICAgIGlmIChuZXh0U3RhdGVzID09PSBudWxsKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoaXNBcnJheShuZXh0U3RhdGVzKSkgewogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5leHRTdGF0ZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgY2hpbGQgPSB0aGlzJDEuc3RhdGVzW25leHRTdGF0ZXNbaV1dOwoKICAgICAgICBpZiAoaXNFcXVhbENoYXJTcGVjKGNoaWxkLCBjaGFyLCBuZWdhdGUpKSB7CiAgICAgICAgICByZXR1cm4gY2hpbGQ7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICB2YXIgY2hpbGQkMSA9IHRoaXMuc3RhdGVzW25leHRTdGF0ZXNdOwoKICAgICAgaWYgKGlzRXF1YWxDaGFyU3BlYyhjaGlsZCQxLCBjaGFyLCBuZWdhdGUpKSB7CiAgICAgICAgcmV0dXJuIGNoaWxkJDE7CiAgICAgIH0KICAgIH0KICB9OwoKICBTdGF0ZS5wcm90b3R5cGUucHV0ID0gZnVuY3Rpb24gcHV0KGNoYXIsIG5lZ2F0ZSwgcmVwZWF0KSB7CiAgICB2YXIgc3RhdGU7IC8vIElmIHRoZSBjaGFyYWN0ZXIgc3BlY2lmaWNhdGlvbiBhbHJlYWR5IGV4aXN0cyBpbiBhIGNoaWxkIG9mIHRoZSBjdXJyZW50CiAgICAvLyBzdGF0ZSwganVzdCByZXR1cm4gdGhhdCBzdGF0ZS4KCiAgICBpZiAoc3RhdGUgPSB0aGlzLmdldChjaGFyLCBuZWdhdGUpKSB7CiAgICAgIHJldHVybiBzdGF0ZTsKICAgIH0gLy8gTWFrZSBhIG5ldyBzdGF0ZSBmb3IgdGhlIGNoYXJhY3RlciBzcGVjCgoKICAgIHZhciBzdGF0ZXMgPSB0aGlzLnN0YXRlczsKICAgIHN0YXRlID0gbmV3IFN0YXRlKHN0YXRlcywgc3RhdGVzLmxlbmd0aCwgY2hhciwgbmVnYXRlLCByZXBlYXQpOwogICAgc3RhdGVzW3N0YXRlcy5sZW5ndGhdID0gc3RhdGU7IC8vIEluc2VydCB0aGUgbmV3IHN0YXRlIGFzIGEgY2hpbGQgb2YgdGhlIGN1cnJlbnQgc3RhdGUKCiAgICBpZiAodGhpcy5uZXh0U3RhdGVzID09IG51bGwpIHsKICAgICAgdGhpcy5uZXh0U3RhdGVzID0gc3RhdGUuaWQ7CiAgICB9IGVsc2UgaWYgKGlzQXJyYXkodGhpcy5uZXh0U3RhdGVzKSkgewogICAgICB0aGlzLm5leHRTdGF0ZXMucHVzaChzdGF0ZS5pZCk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLm5leHRTdGF0ZXMgPSBbdGhpcy5uZXh0U3RhdGVzLCBzdGF0ZS5pZF07CiAgICB9IC8vIFJldHVybiB0aGUgbmV3IHN0YXRlCgoKICAgIHJldHVybiBzdGF0ZTsKICB9OyAvLyBGaW5kIGEgbGlzdCBvZiBjaGlsZCBzdGF0ZXMgbWF0Y2hpbmcgdGhlIG5leHQgY2hhcmFjdGVyCgoKICBTdGF0ZS5wcm90b3R5cGUubWF0Y2ggPSBmdW5jdGlvbiBtYXRjaChjaCkgewogICAgdmFyIHRoaXMkMSA9IHRoaXM7CiAgICB2YXIgbmV4dFN0YXRlcyA9IHRoaXMubmV4dFN0YXRlczsKCiAgICBpZiAoIW5leHRTdGF0ZXMpIHsKICAgICAgcmV0dXJuIFtdOwogICAgfQoKICAgIHZhciByZXR1cm5lZCA9IFtdOwoKICAgIGlmIChpc0FycmF5KG5leHRTdGF0ZXMpKSB7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmV4dFN0YXRlcy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBjaGlsZCA9IHRoaXMkMS5zdGF0ZXNbbmV4dFN0YXRlc1tpXV07CgogICAgICAgIGlmIChpc01hdGNoKGNoaWxkLCBjaCkpIHsKICAgICAgICAgIHJldHVybmVkLnB1c2goY2hpbGQpOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdmFyIGNoaWxkJDEgPSB0aGlzLnN0YXRlc1tuZXh0U3RhdGVzXTsKCiAgICAgIGlmIChpc01hdGNoKGNoaWxkJDEsIGNoKSkgewogICAgICAgIHJldHVybmVkLnB1c2goY2hpbGQkMSk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcmV0dXJuZWQ7CiAgfTsKCiAgZnVuY3Rpb24gaXNNYXRjaChzcGVjLCBjaGFyKSB7CiAgICByZXR1cm4gc3BlYy5uZWdhdGUgPyBzcGVjLmNoYXIgIT09IGNoYXIgJiYgc3BlYy5jaGFyICE9PSAtMQogICAgLyogQU5ZICovCiAgICA6IHNwZWMuY2hhciA9PT0gY2hhciB8fCBzcGVjLmNoYXIgPT09IC0xCiAgICAvKiBBTlkgKi8KICAgIDsKICB9IC8vIFRoaXMgaXMgYSBzb21ld2hhdCBuYWl2ZSBzdHJhdGVneSwgYnV0IHNob3VsZCB3b3JrIGluIGEgbG90IG9mIGNhc2VzCiAgLy8gQSBiZXR0ZXIgc3RyYXRlZ3kgd291bGQgcHJvcGVybHkgcmVzb2x2ZSAvcG9zdHMvOmlkL25ldyBhbmQgL3Bvc3RzL2VkaXQvOmlkLgogIC8vCiAgLy8gVGhpcyBzdHJhdGVneSBnZW5lcmFsbHkgcHJlZmVycyBtb3JlIHN0YXRpYyBhbmQgbGVzcyBkeW5hbWljIG1hdGNoaW5nLgogIC8vIFNwZWNpZmljYWxseSwgaXQKICAvLwogIC8vICAqIHByZWZlcnMgZmV3ZXIgc3RhcnMgdG8gbW9yZSwgdGhlbgogIC8vICAqIHByZWZlcnMgdXNpbmcgc3RhcnMgZm9yIGxlc3Mgb2YgdGhlIG1hdGNoIHRvIG1vcmUsIHRoZW4KICAvLyAgKiBwcmVmZXJzIGZld2VyIGR5bmFtaWMgc2VnbWVudHMgdG8gbW9yZSwgdGhlbgogIC8vICAqIHByZWZlcnMgbW9yZSBzdGF0aWMgc2VnbWVudHMgdG8gbW9yZQoKCiAgZnVuY3Rpb24gc29ydFNvbHV0aW9ucyhzdGF0ZXMpIHsKICAgIHJldHVybiBzdGF0ZXMuc29ydChmdW5jdGlvbiAoYSwgYikgewogICAgICB2YXIgcmVmID0gYS50eXBlcyB8fCBbMCwgMCwgMF07CiAgICAgIHZhciBhc3RhdGljcyA9IHJlZlswXTsKICAgICAgdmFyIGFkeW5hbWljcyA9IHJlZlsxXTsKICAgICAgdmFyIGFzdGFycyA9IHJlZlsyXTsKICAgICAgdmFyIHJlZiQxID0gYi50eXBlcyB8fCBbMCwgMCwgMF07CiAgICAgIHZhciBic3RhdGljcyA9IHJlZiQxWzBdOwogICAgICB2YXIgYmR5bmFtaWNzID0gcmVmJDFbMV07CiAgICAgIHZhciBic3RhcnMgPSByZWYkMVsyXTsKCiAgICAgIGlmIChhc3RhcnMgIT09IGJzdGFycykgewogICAgICAgIHJldHVybiBhc3RhcnMgLSBic3RhcnM7CiAgICAgIH0KCiAgICAgIGlmIChhc3RhcnMpIHsKICAgICAgICBpZiAoYXN0YXRpY3MgIT09IGJzdGF0aWNzKSB7CiAgICAgICAgICByZXR1cm4gYnN0YXRpY3MgLSBhc3RhdGljczsKICAgICAgICB9CgogICAgICAgIGlmIChhZHluYW1pY3MgIT09IGJkeW5hbWljcykgewogICAgICAgICAgcmV0dXJuIGJkeW5hbWljcyAtIGFkeW5hbWljczsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChhZHluYW1pY3MgIT09IGJkeW5hbWljcykgewogICAgICAgIHJldHVybiBhZHluYW1pY3MgLSBiZHluYW1pY3M7CiAgICAgIH0KCiAgICAgIGlmIChhc3RhdGljcyAhPT0gYnN0YXRpY3MpIHsKICAgICAgICByZXR1cm4gYnN0YXRpY3MgLSBhc3RhdGljczsKICAgICAgfQoKICAgICAgcmV0dXJuIDA7CiAgICB9KTsKICB9CgogIGZ1bmN0aW9uIHJlY29nbml6ZUNoYXIoc3RhdGVzLCBjaCkgewogICAgdmFyIG5leHRTdGF0ZXMgPSBbXTsKCiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHN0YXRlcy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgdmFyIHN0YXRlID0gc3RhdGVzW2ldOwogICAgICBuZXh0U3RhdGVzID0gbmV4dFN0YXRlcy5jb25jYXQoc3RhdGUubWF0Y2goY2gpKTsKICAgIH0KCiAgICByZXR1cm4gbmV4dFN0YXRlczsKICB9CgogIHZhciBSZWNvZ25pemVSZXN1bHRzID0gZnVuY3Rpb24gUmVjb2duaXplUmVzdWx0cyhxdWVyeVBhcmFtcykgewogICAgdGhpcy5sZW5ndGggPSAwOwogICAgdGhpcy5xdWVyeVBhcmFtcyA9IHF1ZXJ5UGFyYW1zIHx8IHt9OwogIH07CgogIFJlY29nbml6ZVJlc3VsdHMucHJvdG90eXBlLnNwbGljZSA9IEFycmF5LnByb3RvdHlwZS5zcGxpY2U7CiAgUmVjb2duaXplUmVzdWx0cy5wcm90b3R5cGUuc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7CiAgUmVjb2duaXplUmVzdWx0cy5wcm90b3R5cGUucHVzaCA9IEFycmF5LnByb3RvdHlwZS5wdXNoOwoKICBmdW5jdGlvbiBmaW5kSGFuZGxlcihzdGF0ZSwgb3JpZ2luYWxQYXRoLCBxdWVyeVBhcmFtcykgewogICAgdmFyIGhhbmRsZXJzID0gc3RhdGUuaGFuZGxlcnM7CiAgICB2YXIgcmVnZXggPSBzdGF0ZS5yZWdleCgpOwoKICAgIGlmICghcmVnZXggfHwgIWhhbmRsZXJzKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigic3RhdGUgbm90IGluaXRpYWxpemVkIik7CiAgICB9CgogICAgdmFyIGNhcHR1cmVzID0gb3JpZ2luYWxQYXRoLm1hdGNoKHJlZ2V4KTsKICAgIHZhciBjdXJyZW50Q2FwdHVyZSA9IDE7CiAgICB2YXIgcmVzdWx0ID0gbmV3IFJlY29nbml6ZVJlc3VsdHMocXVlcnlQYXJhbXMpOwogICAgcmVzdWx0Lmxlbmd0aCA9IGhhbmRsZXJzLmxlbmd0aDsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhbmRsZXJzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBoYW5kbGVyID0gaGFuZGxlcnNbaV07CiAgICAgIHZhciBuYW1lcyA9IGhhbmRsZXIubmFtZXM7CiAgICAgIHZhciBzaG91bGREZWNvZGVzID0gaGFuZGxlci5zaG91bGREZWNvZGVzOwogICAgICB2YXIgcGFyYW1zID0gRW1wdHlPYmplY3Q7CiAgICAgIHZhciBpc0R5bmFtaWMgPSBmYWxzZTsKCiAgICAgIGlmIChuYW1lcyAhPT0gRW1wdHlBcnJheSAmJiBzaG91bGREZWNvZGVzICE9PSBFbXB0eUFycmF5KSB7CiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBuYW1lcy5sZW5ndGg7IGorKykgewogICAgICAgICAgaXNEeW5hbWljID0gdHJ1ZTsKICAgICAgICAgIHZhciBuYW1lID0gbmFtZXNbal07CiAgICAgICAgICB2YXIgY2FwdHVyZSA9IGNhcHR1cmVzICYmIGNhcHR1cmVzW2N1cnJlbnRDYXB0dXJlKytdOwoKICAgICAgICAgIGlmIChwYXJhbXMgPT09IEVtcHR5T2JqZWN0KSB7CiAgICAgICAgICAgIHBhcmFtcyA9IHt9OwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChSb3V0ZVJlY29nbml6ZXIuRU5DT0RFX0FORF9ERUNPREVfUEFUSF9TRUdNRU5UUyAmJiBzaG91bGREZWNvZGVzW2pdKSB7CiAgICAgICAgICAgIHBhcmFtc1tuYW1lXSA9IGNhcHR1cmUgJiYgZGVjb2RlVVJJQ29tcG9uZW50KGNhcHR1cmUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcGFyYW1zW25hbWVdID0gY2FwdHVyZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJlc3VsdFtpXSA9IHsKICAgICAgICBoYW5kbGVyOiBoYW5kbGVyLmhhbmRsZXIsCiAgICAgICAgcGFyYW1zOiBwYXJhbXMsCiAgICAgICAgaXNEeW5hbWljOiBpc0R5bmFtaWMKICAgICAgfTsKICAgIH0KCiAgICByZXR1cm4gcmVzdWx0OwogIH0KCiAgZnVuY3Rpb24gZGVjb2RlUXVlcnlQYXJhbVBhcnQocGFydCkgewogICAgLy8gaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQwMS9pbnRlcmFjdC9mb3Jtcy5odG1sI2gtMTcuMTMuNC4xCiAgICBwYXJ0ID0gcGFydC5yZXBsYWNlKC9cKy9nbSwgIiUyMCIpOwogICAgdmFyIHJlc3VsdDsKCiAgICB0cnkgewogICAgICByZXN1bHQgPSBkZWNvZGVVUklDb21wb25lbnQocGFydCk7CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgICByZXN1bHQgPSAiIjsKICAgIH0KCiAgICByZXR1cm4gcmVzdWx0OwogIH0KCiAgdmFyIFJvdXRlUmVjb2duaXplciA9IGZ1bmN0aW9uIFJvdXRlUmVjb2duaXplcigpIHsKICAgIHRoaXMubmFtZXMgPSBjcmVhdGVNYXAoKTsKICAgIHZhciBzdGF0ZXMgPSBbXTsKICAgIHZhciBzdGF0ZSA9IG5ldyBTdGF0ZShzdGF0ZXMsIDAsIC0xCiAgICAvKiBBTlkgKi8KICAgICwgdHJ1ZSwgZmFsc2UpOwogICAgc3RhdGVzWzBdID0gc3RhdGU7CiAgICB0aGlzLnN0YXRlcyA9IHN0YXRlczsKICAgIHRoaXMucm9vdFN0YXRlID0gc3RhdGU7CiAgfTsKCiAgUm91dGVSZWNvZ25pemVyLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiBhZGQocm91dGVzLCBvcHRpb25zKSB7CiAgICB2YXIgY3VycmVudFN0YXRlID0gdGhpcy5yb290U3RhdGU7CiAgICB2YXIgcGF0dGVybiA9ICJeIjsKICAgIHZhciB0eXBlcyA9IFswLCAwLCAwXTsKICAgIHZhciBoYW5kbGVycyA9IG5ldyBBcnJheShyb3V0ZXMubGVuZ3RoKTsKICAgIHZhciBhbGxTZWdtZW50cyA9IFtdOwogICAgdmFyIGlzRW1wdHkgPSB0cnVlOwogICAgdmFyIGogPSAwOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm91dGVzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciByb3V0ZSA9IHJvdXRlc1tpXTsKICAgICAgdmFyIHJlZiA9IHBhcnNlKGFsbFNlZ21lbnRzLCByb3V0ZS5wYXRoLCB0eXBlcyk7CiAgICAgIHZhciBuYW1lcyA9IHJlZi5uYW1lczsKICAgICAgdmFyIHNob3VsZERlY29kZXMgPSByZWYuc2hvdWxkRGVjb2RlczsgLy8gcHJlc2VydmUgaiBzbyBpdCBwb2ludHMgdG8gdGhlIHN0YXJ0IG9mIG5ld2x5IGFkZGVkIHNlZ21lbnRzCgogICAgICBmb3IgKDsgaiA8IGFsbFNlZ21lbnRzLmxlbmd0aDsgaisrKSB7CiAgICAgICAgdmFyIHNlZ21lbnQgPSBhbGxTZWdtZW50c1tqXTsKCiAgICAgICAgaWYgKHNlZ21lbnQudHlwZSA9PT0gNAogICAgICAgIC8qIEVwc2lsb24gKi8KICAgICAgICApIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CgogICAgICAgIGlzRW1wdHkgPSBmYWxzZTsgLy8gQWRkIGEgIi8iIGZvciB0aGUgbmV3IHNlZ21lbnQKCiAgICAgICAgY3VycmVudFN0YXRlID0gY3VycmVudFN0YXRlLnB1dCg0NwogICAgICAgIC8qIFNMQVNIICovCiAgICAgICAgLCBmYWxzZSwgZmFsc2UpOwogICAgICAgIHBhdHRlcm4gKz0gIi8iOyAvLyBBZGQgYSByZXByZXNlbnRhdGlvbiBvZiB0aGUgc2VnbWVudCB0byB0aGUgTkZBIGFuZCByZWdleAoKICAgICAgICBjdXJyZW50U3RhdGUgPSBlYWNoQ2hhcltzZWdtZW50LnR5cGVdKHNlZ21lbnQsIGN1cnJlbnRTdGF0ZSk7CiAgICAgICAgcGF0dGVybiArPSByZWdleFtzZWdtZW50LnR5cGVdKHNlZ21lbnQpOwogICAgICB9CgogICAgICBoYW5kbGVyc1tpXSA9IHsKICAgICAgICBoYW5kbGVyOiByb3V0ZS5oYW5kbGVyLAogICAgICAgIG5hbWVzOiBuYW1lcywKICAgICAgICBzaG91bGREZWNvZGVzOiBzaG91bGREZWNvZGVzCiAgICAgIH07CiAgICB9CgogICAgaWYgKGlzRW1wdHkpIHsKICAgICAgY3VycmVudFN0YXRlID0gY3VycmVudFN0YXRlLnB1dCg0NwogICAgICAvKiBTTEFTSCAqLwogICAgICAsIGZhbHNlLCBmYWxzZSk7CiAgICAgIHBhdHRlcm4gKz0gIi8iOwogICAgfQoKICAgIGN1cnJlbnRTdGF0ZS5oYW5kbGVycyA9IGhhbmRsZXJzOwogICAgY3VycmVudFN0YXRlLnBhdHRlcm4gPSBwYXR0ZXJuICsgIiQiOwogICAgY3VycmVudFN0YXRlLnR5cGVzID0gdHlwZXM7CiAgICB2YXIgbmFtZTsKCiAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICJvYmplY3QiICYmIG9wdGlvbnMgIT09IG51bGwgJiYgb3B0aW9ucy5hcykgewogICAgICBuYW1lID0gb3B0aW9ucy5hczsKICAgIH0KCiAgICBpZiAobmFtZSkgewogICAgICAvLyBpZiAodGhpcy5uYW1lc1tuYW1lXSkgewogICAgICAvLyAgIHRocm93IG5ldyBFcnJvcigiWW91IG1heSBub3QgYWRkIGEgZHVwbGljYXRlIHJvdXRlIG5hbWVkIGAiICsgbmFtZSArICJgLiIpOwogICAgICAvLyB9CiAgICAgIHRoaXMubmFtZXNbbmFtZV0gPSB7CiAgICAgICAgc2VnbWVudHM6IGFsbFNlZ21lbnRzLAogICAgICAgIGhhbmRsZXJzOiBoYW5kbGVycwogICAgICB9OwogICAgfQogIH07CgogIFJvdXRlUmVjb2duaXplci5wcm90b3R5cGUuaGFuZGxlcnNGb3IgPSBmdW5jdGlvbiBoYW5kbGVyc0ZvcihuYW1lKSB7CiAgICB2YXIgcm91dGUgPSB0aGlzLm5hbWVzW25hbWVdOwoKICAgIGlmICghcm91dGUpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJUaGVyZSBpcyBubyByb3V0ZSBuYW1lZCAiICsgbmFtZSk7CiAgICB9CgogICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShyb3V0ZS5oYW5kbGVycy5sZW5ndGgpOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcm91dGUuaGFuZGxlcnMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGhhbmRsZXIgPSByb3V0ZS5oYW5kbGVyc1tpXTsKICAgICAgcmVzdWx0W2ldID0gaGFuZGxlcjsKICAgIH0KCiAgICByZXR1cm4gcmVzdWx0OwogIH07CgogIFJvdXRlUmVjb2duaXplci5wcm90b3R5cGUuaGFzUm91dGUgPSBmdW5jdGlvbiBoYXNSb3V0ZShuYW1lKSB7CiAgICByZXR1cm4gISF0aGlzLm5hbWVzW25hbWVdOwogIH07CgogIFJvdXRlUmVjb2duaXplci5wcm90b3R5cGUuZ2VuZXJhdGUgPSBmdW5jdGlvbiBnZW5lcmF0ZSQxKG5hbWUsIHBhcmFtcykgewogICAgdmFyIHJvdXRlID0gdGhpcy5uYW1lc1tuYW1lXTsKICAgIHZhciBvdXRwdXQgPSAiIjsKCiAgICBpZiAoIXJvdXRlKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiVGhlcmUgaXMgbm8gcm91dGUgbmFtZWQgIiArIG5hbWUpOwogICAgfQoKICAgIHZhciBzZWdtZW50cyA9IHJvdXRlLnNlZ21lbnRzOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VnbWVudHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIHNlZ21lbnQgPSBzZWdtZW50c1tpXTsKCiAgICAgIGlmIChzZWdtZW50LnR5cGUgPT09IDQKICAgICAgLyogRXBzaWxvbiAqLwogICAgICApIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KCiAgICAgIG91dHB1dCArPSAiLyI7CiAgICAgIG91dHB1dCArPSBnZW5lcmF0ZVtzZWdtZW50LnR5cGVdKHNlZ21lbnQsIHBhcmFtcyk7CiAgICB9CgogICAgaWYgKG91dHB1dC5jaGFyQXQoMCkgIT09ICIvIikgewogICAgICBvdXRwdXQgPSAiLyIgKyBvdXRwdXQ7CiAgICB9CgogICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMucXVlcnlQYXJhbXMpIHsKICAgICAgb3V0cHV0ICs9IHRoaXMuZ2VuZXJhdGVRdWVyeVN0cmluZyhwYXJhbXMucXVlcnlQYXJhbXMpOwogICAgfQoKICAgIHJldHVybiBvdXRwdXQ7CiAgfTsKCiAgUm91dGVSZWNvZ25pemVyLnByb3RvdHlwZS5nZW5lcmF0ZVF1ZXJ5U3RyaW5nID0gZnVuY3Rpb24gZ2VuZXJhdGVRdWVyeVN0cmluZyhwYXJhbXMpIHsKICAgIHZhciBwYWlycyA9IFtdOwogICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhwYXJhbXMpOwogICAga2V5cy5zb3J0KCk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBrZXkgPSBrZXlzW2ldOwogICAgICB2YXIgdmFsdWUgPSBwYXJhbXNba2V5XTsKCiAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIHZhciBwYWlyID0gZW5jb2RlVVJJQ29tcG9uZW50KGtleSk7CgogICAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHZhbHVlLmxlbmd0aDsgaisrKSB7CiAgICAgICAgICB2YXIgYXJyYXlQYWlyID0ga2V5ICsgIltdIiArICI9IiArIGVuY29kZVVSSUNvbXBvbmVudCh2YWx1ZVtqXSk7CiAgICAgICAgICBwYWlycy5wdXNoKGFycmF5UGFpcik7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHBhaXIgKz0gIj0iICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKTsKICAgICAgICBwYWlycy5wdXNoKHBhaXIpOwogICAgICB9CiAgICB9CgogICAgaWYgKHBhaXJzLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gIiI7CiAgICB9CgogICAgcmV0dXJuICI/IiArIHBhaXJzLmpvaW4oIiYiKTsKICB9OwoKICBSb3V0ZVJlY29nbml6ZXIucHJvdG90eXBlLnBhcnNlUXVlcnlTdHJpbmcgPSBmdW5jdGlvbiBwYXJzZVF1ZXJ5U3RyaW5nKHF1ZXJ5U3RyaW5nKSB7CiAgICB2YXIgcGFpcnMgPSBxdWVyeVN0cmluZy5zcGxpdCgiJiIpOwogICAgdmFyIHF1ZXJ5UGFyYW1zID0ge307CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYWlycy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgcGFpciA9IHBhaXJzW2ldLnNwbGl0KCI9IiksCiAgICAgICAgICBrZXkgPSBkZWNvZGVRdWVyeVBhcmFtUGFydChwYWlyWzBdKSwKICAgICAgICAgIGtleUxlbmd0aCA9IGtleS5sZW5ndGgsCiAgICAgICAgICBpc0FycmF5ID0gZmFsc2UsCiAgICAgICAgICB2YWx1ZSA9IHZvaWQgMDsKCiAgICAgIGlmIChwYWlyLmxlbmd0aCA9PT0gMSkgewogICAgICAgIHZhbHVlID0gInRydWUiOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIEhhbmRsZSBhcnJheXMKICAgICAgICBpZiAoa2V5TGVuZ3RoID4gMiAmJiBrZXkuc2xpY2Uoa2V5TGVuZ3RoIC0gMikgPT09ICJbXSIpIHsKICAgICAgICAgIGlzQXJyYXkgPSB0cnVlOwogICAgICAgICAga2V5ID0ga2V5LnNsaWNlKDAsIGtleUxlbmd0aCAtIDIpOwoKICAgICAgICAgIGlmICghcXVlcnlQYXJhbXNba2V5XSkgewogICAgICAgICAgICBxdWVyeVBhcmFtc1trZXldID0gW107CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB2YWx1ZSA9IHBhaXJbMV0gPyBkZWNvZGVRdWVyeVBhcmFtUGFydChwYWlyWzFdKSA6ICIiOwogICAgICB9CgogICAgICBpZiAoaXNBcnJheSkgewogICAgICAgIHF1ZXJ5UGFyYW1zW2tleV0ucHVzaCh2YWx1ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcXVlcnlQYXJhbXNba2V5XSA9IHZhbHVlOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHF1ZXJ5UGFyYW1zOwogIH07CgogIFJvdXRlUmVjb2duaXplci5wcm90b3R5cGUucmVjb2duaXplID0gZnVuY3Rpb24gcmVjb2duaXplKHBhdGgpIHsKICAgIHZhciByZXN1bHRzOwogICAgdmFyIHN0YXRlcyA9IFt0aGlzLnJvb3RTdGF0ZV07CiAgICB2YXIgcXVlcnlQYXJhbXMgPSB7fTsKICAgIHZhciBpc1NsYXNoRHJvcHBlZCA9IGZhbHNlOwogICAgdmFyIGhhc2hTdGFydCA9IHBhdGguaW5kZXhPZigiIyIpOwoKICAgIGlmIChoYXNoU3RhcnQgIT09IC0xKSB7CiAgICAgIHBhdGggPSBwYXRoLnN1YnN0cigwLCBoYXNoU3RhcnQpOwogICAgfQoKICAgIHZhciBxdWVyeVN0YXJ0ID0gcGF0aC5pbmRleE9mKCI/Iik7CgogICAgaWYgKHF1ZXJ5U3RhcnQgIT09IC0xKSB7CiAgICAgIHZhciBxdWVyeVN0cmluZyA9IHBhdGguc3Vic3RyKHF1ZXJ5U3RhcnQgKyAxLCBwYXRoLmxlbmd0aCk7CiAgICAgIHBhdGggPSBwYXRoLnN1YnN0cigwLCBxdWVyeVN0YXJ0KTsKICAgICAgcXVlcnlQYXJhbXMgPSB0aGlzLnBhcnNlUXVlcnlTdHJpbmcocXVlcnlTdHJpbmcpOwogICAgfQoKICAgIGlmIChwYXRoLmNoYXJBdCgwKSAhPT0gIi8iKSB7CiAgICAgIHBhdGggPSAiLyIgKyBwYXRoOwogICAgfQoKICAgIHZhciBvcmlnaW5hbFBhdGggPSBwYXRoOwoKICAgIGlmIChSb3V0ZVJlY29nbml6ZXIuRU5DT0RFX0FORF9ERUNPREVfUEFUSF9TRUdNRU5UUykgewogICAgICBwYXRoID0gbm9ybWFsaXplUGF0aChwYXRoKTsKICAgIH0gZWxzZSB7CiAgICAgIHBhdGggPSBkZWNvZGVVUkkocGF0aCk7CiAgICAgIG9yaWdpbmFsUGF0aCA9IGRlY29kZVVSSShvcmlnaW5hbFBhdGgpOwogICAgfQoKICAgIHZhciBwYXRoTGVuID0gcGF0aC5sZW5ndGg7CgogICAgaWYgKHBhdGhMZW4gPiAxICYmIHBhdGguY2hhckF0KHBhdGhMZW4gLSAxKSA9PT0gIi8iKSB7CiAgICAgIHBhdGggPSBwYXRoLnN1YnN0cigwLCBwYXRoTGVuIC0gMSk7CiAgICAgIG9yaWdpbmFsUGF0aCA9IG9yaWdpbmFsUGF0aC5zdWJzdHIoMCwgb3JpZ2luYWxQYXRoLmxlbmd0aCAtIDEpOwogICAgICBpc1NsYXNoRHJvcHBlZCA9IHRydWU7CiAgICB9CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRoLmxlbmd0aDsgaSsrKSB7CiAgICAgIHN0YXRlcyA9IHJlY29nbml6ZUNoYXIoc3RhdGVzLCBwYXRoLmNoYXJDb2RlQXQoaSkpOwoKICAgICAgaWYgKCFzdGF0ZXMubGVuZ3RoKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KCiAgICB2YXIgc29sdXRpb25zID0gW107CgogICAgZm9yICh2YXIgaSQxID0gMDsgaSQxIDwgc3RhdGVzLmxlbmd0aDsgaSQxKyspIHsKICAgICAgaWYgKHN0YXRlc1tpJDFdLmhhbmRsZXJzKSB7CiAgICAgICAgc29sdXRpb25zLnB1c2goc3RhdGVzW2kkMV0pOwogICAgICB9CiAgICB9CgogICAgc3RhdGVzID0gc29ydFNvbHV0aW9ucyhzb2x1dGlvbnMpOwogICAgdmFyIHN0YXRlID0gc29sdXRpb25zWzBdOwoKICAgIGlmIChzdGF0ZSAmJiBzdGF0ZS5oYW5kbGVycykgewogICAgICAvLyBpZiBhIHRyYWlsaW5nIHNsYXNoIHdhcyBkcm9wcGVkIGFuZCBhIHN0YXIgc2VnbWVudCBpcyB0aGUgbGFzdCBzZWdtZW50CiAgICAgIC8vIHNwZWNpZmllZCwgcHV0IHRoZSB0cmFpbGluZyBzbGFzaCBiYWNrCiAgICAgIGlmIChpc1NsYXNoRHJvcHBlZCAmJiBzdGF0ZS5wYXR0ZXJuICYmIHN0YXRlLnBhdHRlcm4uc2xpY2UoLTUpID09PSAiKC4rKSQiKSB7CiAgICAgICAgb3JpZ2luYWxQYXRoID0gb3JpZ2luYWxQYXRoICsgIi8iOwogICAgICB9CgogICAgICByZXN1bHRzID0gZmluZEhhbmRsZXIoc3RhdGUsIG9yaWdpbmFsUGF0aCwgcXVlcnlQYXJhbXMpOwogICAgfQoKICAgIHJldHVybiByZXN1bHRzOwogIH07CgogIFJvdXRlUmVjb2duaXplci5WRVJTSU9OID0gIjAuMy40IjsgLy8gU2V0IHRvIGZhbHNlIHRvIG9wdC1vdXQgb2YgZW5jb2RpbmcgYW5kIGRlY29kaW5nIHBhdGggc2VnbWVudHMuCiAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS90aWxkZWlvL3JvdXRlLXJlY29nbml6ZXIvcHVsbC81NQoKICBSb3V0ZVJlY29nbml6ZXIuRU5DT0RFX0FORF9ERUNPREVfUEFUSF9TRUdNRU5UUyA9IHRydWU7CiAgUm91dGVSZWNvZ25pemVyLk5vcm1hbGl6ZXIgPSB7CiAgICBub3JtYWxpemVTZWdtZW50OiBub3JtYWxpemVTZWdtZW50LAogICAgbm9ybWFsaXplUGF0aDogbm9ybWFsaXplUGF0aCwKICAgIGVuY29kZVBhdGhTZWdtZW50OiBlbmNvZGVQYXRoU2VnbWVudAogIH07CiAgUm91dGVSZWNvZ25pemVyLnByb3RvdHlwZS5tYXAgPSBtYXA7CiAgdmFyIF9kZWZhdWx0ID0gUm91dGVSZWNvZ25pemVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CmRlZmluZSgicm91dGVyX2pzIiwgWyJleHBvcnRzIiwgIkBlbWJlci9wb2x5ZmlsbHMiLCAiZW1iZXItYmFiZWwiLCAicnN2cCIsICJyb3V0ZS1yZWNvZ25pemVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3BvbHlmaWxscywgX2VtYmVyQmFiZWwsIF9yc3ZwLCBfcm91dGVSZWNvZ25pemVyKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5sb2dBYm9ydCA9IGxvZ0Fib3J0OwogIF9leHBvcnRzLkludGVybmFsUm91dGVJbmZvID0gX2V4cG9ydHMuVHJhbnNpdGlvbkVycm9yID0gX2V4cG9ydHMuVHJhbnNpdGlvblN0YXRlID0gX2V4cG9ydHMuUVVFUllfUEFSQU1TX1NZTUJPTCA9IF9leHBvcnRzLlBBUkFNU19TWU1CT0wgPSBfZXhwb3J0cy5TVEFURV9TWU1CT0wgPSBfZXhwb3J0cy5JbnRlcm5hbFRyYW5zaXRpb24gPSBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICB2YXIgVHJhbnNpdGlvbkFib3J0ZWRFcnJvciA9IGZ1bmN0aW9uICgpIHsKICAgIFRyYW5zaXRpb25BYm9ydGVkRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFcnJvci5wcm90b3R5cGUpOwogICAgVHJhbnNpdGlvbkFib3J0ZWRFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBUcmFuc2l0aW9uQWJvcnRlZEVycm9yOwoKICAgIGZ1bmN0aW9uIFRyYW5zaXRpb25BYm9ydGVkRXJyb3IobWVzc2FnZSkgewogICAgICB2YXIgZXJyb3IgPSBFcnJvci5jYWxsKHRoaXMsIG1lc3NhZ2UpOwogICAgICB0aGlzLm5hbWUgPSAnVHJhbnNpdGlvbkFib3J0ZWQnOwogICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlIHx8ICdUcmFuc2l0aW9uQWJvcnRlZCc7CgogICAgICBpZiAoRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpIHsKICAgICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBUcmFuc2l0aW9uQWJvcnRlZEVycm9yKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnN0YWNrID0gZXJyb3Iuc3RhY2s7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gVHJhbnNpdGlvbkFib3J0ZWRFcnJvcjsKICB9KCk7CgogIHZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTsKICB2YXIgaGFzT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5OwogIC8qKgogICAgRGV0ZXJtaW5lcyBpZiBhbiBvYmplY3QgaXMgUHJvbWlzZSBieSBjaGVja2luZyBpZiBpdCBpcyAidGhlbmFibGUiLgogICoqLwoKICBmdW5jdGlvbiBpc1Byb21pc2UocCkgewogICAgcmV0dXJuIHAgIT09IG51bGwgJiYgdHlwZW9mIHAgPT09ICdvYmplY3QnICYmIHR5cGVvZiBwLnRoZW4gPT09ICdmdW5jdGlvbic7CiAgfQoKICBmdW5jdGlvbiBtZXJnZShoYXNoLCBvdGhlcikgewogICAgZm9yICh2YXIgcHJvcCBpbiBvdGhlcikgewogICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvdGhlciwgcHJvcCkpIHsKICAgICAgICBoYXNoW3Byb3BdID0gb3RoZXJbcHJvcF07CiAgICAgIH0KICAgIH0KICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogIAogICAgRXh0cmFjdHMgcXVlcnkgcGFyYW1zIGZyb20gdGhlIGVuZCBvZiBhbiBhcnJheQogICoqLwoKCiAgZnVuY3Rpb24gZXh0cmFjdFF1ZXJ5UGFyYW1zKGFycmF5KSB7CiAgICB2YXIgbGVuID0gYXJyYXkgJiYgYXJyYXkubGVuZ3RoLAogICAgICAgIGhlYWQsCiAgICAgICAgcXVlcnlQYXJhbXM7CgogICAgaWYgKGxlbiAmJiBsZW4gPiAwKSB7CiAgICAgIHZhciBvYmogPSBhcnJheVtsZW4gLSAxXTsKCiAgICAgIGlmIChpc1F1ZXJ5UGFyYW1zKG9iaikpIHsKICAgICAgICBxdWVyeVBhcmFtcyA9IG9iai5xdWVyeVBhcmFtczsKICAgICAgICBoZWFkID0gc2xpY2UuY2FsbChhcnJheSwgMCwgbGVuIC0gMSk7CiAgICAgICAgcmV0dXJuIFtoZWFkLCBxdWVyeVBhcmFtc107CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gW2FycmF5LCBudWxsXTsKICB9CgogIGZ1bmN0aW9uIGlzUXVlcnlQYXJhbXMob2JqKSB7CiAgICByZXR1cm4gb2JqICYmIGhhc093blByb3BlcnR5LmNhbGwob2JqLCAncXVlcnlQYXJhbXMnKTsKICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogIAogICAgQ29lcmNlcyBxdWVyeSBwYXJhbSBwcm9wZXJ0aWVzIGFuZCBhcnJheSBlbGVtZW50cyBpbnRvIHN0cmluZ3MuCiAgKiovCgoKICBmdW5jdGlvbiBjb2VyY2VRdWVyeVBhcmFtc1RvU3RyaW5nKHF1ZXJ5UGFyYW1zKSB7CiAgICBmb3IgKHZhciBrZXkgaW4gcXVlcnlQYXJhbXMpIHsKICAgICAgdmFyIHZhbCA9IHF1ZXJ5UGFyYW1zW2tleV07CgogICAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHsKICAgICAgICBxdWVyeVBhcmFtc1trZXldID0gJycgKyB2YWw7CiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSB2YWwubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICB2YWxbaV0gPSAnJyArIHZhbFtpXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgLyoqCiAgICBAcHJpdmF0ZQogICAqLwoKCiAgZnVuY3Rpb24gX2xvZyhyb3V0ZXIpIHsKICAgIGlmICghcm91dGVyLmxvZykgewogICAgICByZXR1cm47CiAgICB9CgogICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiA+IDEgPyBfbGVuIC0gMSA6IDApLCBfa2V5ID0gMTsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICBhcmdzW19rZXkgLSAxXSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgIH0KCiAgICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHsKICAgICAgdmFyIHNlcXVlbmNlID0gYXJnc1swXSwKICAgICAgICAgIG1zZyA9IGFyZ3NbMV07CiAgICAgIHJvdXRlci5sb2coJ1RyYW5zaXRpb24gIycgKyBzZXF1ZW5jZSArICc6ICcgKyBtc2cpOwogICAgfSBlbHNlIHsKICAgICAgdmFyIF9tc2cgPSBhcmdzWzBdOwogICAgICByb3V0ZXIubG9nKF9tc2cpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gaXNQYXJhbShvYmplY3QpIHsKICAgIHJldHVybiB0eXBlb2Ygb2JqZWN0ID09PSAnc3RyaW5nJyB8fCBvYmplY3QgaW5zdGFuY2VvZiBTdHJpbmcgfHwgdHlwZW9mIG9iamVjdCA9PT0gJ251bWJlcicgfHwgb2JqZWN0IGluc3RhbmNlb2YgTnVtYmVyOwogIH0KCiAgZnVuY3Rpb24gZm9yRWFjaChhcnJheSwgY2FsbGJhY2spIHsKICAgIGZvciAodmFyIGkgPSAwLCBsID0gYXJyYXkubGVuZ3RoOyBpIDwgbCAmJiBjYWxsYmFjayhhcnJheVtpXSkgIT09IGZhbHNlOyBpKyspIHsvLyBlbXB0eSBpbnRlbnRpb25hbGx5CiAgICB9CiAgfQoKICBmdW5jdGlvbiBnZXRDaGFuZ2VsaXN0KG9sZE9iamVjdCwgbmV3T2JqZWN0KSB7CiAgICB2YXIga2V5OwogICAgdmFyIHJlc3VsdHMgPSB7CiAgICAgIGFsbDoge30sCiAgICAgIGNoYW5nZWQ6IHt9LAogICAgICByZW1vdmVkOiB7fQogICAgfTsKICAgIG1lcmdlKHJlc3VsdHMuYWxsLCBuZXdPYmplY3QpOwogICAgdmFyIGRpZENoYW5nZSA9IGZhbHNlOwogICAgY29lcmNlUXVlcnlQYXJhbXNUb1N0cmluZyhvbGRPYmplY3QpOwogICAgY29lcmNlUXVlcnlQYXJhbXNUb1N0cmluZyhuZXdPYmplY3QpOyAvLyBDYWxjdWxhdGUgcmVtb3ZhbHMKCiAgICBmb3IgKGtleSBpbiBvbGRPYmplY3QpIHsKICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2xkT2JqZWN0LCBrZXkpKSB7CiAgICAgICAgaWYgKCFoYXNPd25Qcm9wZXJ0eS5jYWxsKG5ld09iamVjdCwga2V5KSkgewogICAgICAgICAgZGlkQ2hhbmdlID0gdHJ1ZTsKICAgICAgICAgIHJlc3VsdHMucmVtb3ZlZFtrZXldID0gb2xkT2JqZWN0W2tleV07CiAgICAgICAgfQogICAgICB9CiAgICB9IC8vIENhbGN1bGF0ZSBjaGFuZ2VzCgoKICAgIGZvciAoa2V5IGluIG5ld09iamVjdCkgewogICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChuZXdPYmplY3QsIGtleSkpIHsKICAgICAgICB2YXIgb2xkRWxlbWVudCA9IG9sZE9iamVjdFtrZXldOwogICAgICAgIHZhciBuZXdFbGVtZW50ID0gbmV3T2JqZWN0W2tleV07CgogICAgICAgIGlmIChpc0FycmF5KG9sZEVsZW1lbnQpICYmIGlzQXJyYXkobmV3RWxlbWVudCkpIHsKICAgICAgICAgIGlmIChvbGRFbGVtZW50Lmxlbmd0aCAhPT0gbmV3RWxlbWVudC5sZW5ndGgpIHsKICAgICAgICAgICAgcmVzdWx0cy5jaGFuZ2VkW2tleV0gPSBuZXdPYmplY3Rba2V5XTsKICAgICAgICAgICAgZGlkQ2hhbmdlID0gdHJ1ZTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gb2xkRWxlbWVudC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgICAgICBpZiAob2xkRWxlbWVudFtpXSAhPT0gbmV3RWxlbWVudFtpXSkgewogICAgICAgICAgICAgICAgcmVzdWx0cy5jaGFuZ2VkW2tleV0gPSBuZXdPYmplY3Rba2V5XTsKICAgICAgICAgICAgICAgIGRpZENoYW5nZSA9IHRydWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChvbGRPYmplY3Rba2V5XSAhPT0gbmV3T2JqZWN0W2tleV0pIHsKICAgICAgICAgIHJlc3VsdHMuY2hhbmdlZFtrZXldID0gbmV3T2JqZWN0W2tleV07CiAgICAgICAgICBkaWRDaGFuZ2UgPSB0cnVlOwogICAgICAgIH0KICAgICAgfQogICAgfQoKICAgIHJldHVybiBkaWRDaGFuZ2UgPyByZXN1bHRzIDogdW5kZWZpbmVkOwogIH0KCiAgZnVuY3Rpb24gaXNBcnJheShvYmopIHsKICAgIHJldHVybiBBcnJheS5pc0FycmF5KG9iaik7CiAgfQoKICBmdW5jdGlvbiBfcHJvbWlzZUxhYmVsKGxhYmVsKSB7CiAgICByZXR1cm4gJ1JvdXRlcjogJyArIGxhYmVsOwogIH0KCiAgdmFyIFNUQVRFX1NZTUJPTCA9ICJfX1NUQVRFX18tMjYxOTg2MDAwMTM0NTkyMC0zMzIydzMiOwogIF9leHBvcnRzLlNUQVRFX1NZTUJPTCA9IFNUQVRFX1NZTUJPTDsKICB2YXIgUEFSQU1TX1NZTUJPTCA9ICJfX1BBUkFNU19fLTI2MTk4NjIzMjk5MjgzMDIwMy0yMzMyMyI7CiAgX2V4cG9ydHMuUEFSQU1TX1NZTUJPTCA9IFBBUkFNU19TWU1CT0w7CiAgdmFyIFFVRVJZX1BBUkFNU19TWU1CT0wgPSAiX19RUFNfXy0yNjE5ODYzOTI5ODI0ODQ0LTMyMzIzIjsKICAvKioKICAgIEEgVHJhbnNpdGlvbiBpcyBhIHRoZW5uYWJsZSAoYSBwcm9taXNlLWxpa2Ugb2JqZWN0KSB0aGF0IHJlcHJlc2VudHMKICAgIGFuIGF0dGVtcHQgdG8gdHJhbnNpdGlvbiB0byBhbm90aGVyIHJvdXRlLiBJdCBjYW4gYmUgYWJvcnRlZCwgZWl0aGVyCiAgICBleHBsaWNpdGx5IHZpYSBgYWJvcnRgIG9yIGJ5IGF0dGVtcHRpbmcgYW5vdGhlciB0cmFuc2l0aW9uIHdoaWxlIGEKICAgIHByZXZpb3VzIG9uZSBpcyBzdGlsbCB1bmRlcndheS4gQW4gYWJvcnRlZCB0cmFuc2l0aW9uIGNhbiBhbHNvCiAgICBiZSBgcmV0cnkoKWBkIGxhdGVyLgogIAogICAgQGNsYXNzIFRyYW5zaXRpb24KICAgIEBjb25zdHJ1Y3RvcgogICAgQHBhcmFtIHtPYmplY3R9IHJvdXRlcgogICAgQHBhcmFtIHtPYmplY3R9IGludGVudAogICAgQHBhcmFtIHtPYmplY3R9IHN0YXRlCiAgICBAcGFyYW0ge09iamVjdH0gZXJyb3IKICAgIEBwcml2YXRlCiAgICovCgogIF9leHBvcnRzLlFVRVJZX1BBUkFNU19TWU1CT0wgPSBRVUVSWV9QQVJBTVNfU1lNQk9MOwoKICB2YXIgVHJhbnNpdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFRyYW5zaXRpb24ocm91dGVyLCBpbnRlbnQsIHN0YXRlLCBlcnJvciwgcHJldmlvdXNUcmFuc2l0aW9uKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICBpZiAoZXJyb3IgPT09IHZvaWQgMCkgewogICAgICAgIGVycm9yID0gdW5kZWZpbmVkOwogICAgICB9CgogICAgICBpZiAocHJldmlvdXNUcmFuc2l0aW9uID09PSB2b2lkIDApIHsKICAgICAgICBwcmV2aW91c1RyYW5zaXRpb24gPSB1bmRlZmluZWQ7CiAgICAgIH0KCiAgICAgIHRoaXMuZnJvbSA9IG51bGw7CiAgICAgIHRoaXMudG8gPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuaXNBYm9ydGVkID0gZmFsc2U7CiAgICAgIHRoaXMuaXNBY3RpdmUgPSB0cnVlOwogICAgICB0aGlzLnVybE1ldGhvZCA9ICd1cGRhdGUnOwogICAgICB0aGlzLnJlc29sdmVJbmRleCA9IDA7CiAgICAgIHRoaXMucXVlcnlQYXJhbXNPbmx5ID0gZmFsc2U7CiAgICAgIHRoaXMuaXNUcmFuc2l0aW9uID0gdHJ1ZTsKICAgICAgdGhpcy5pc0NhdXNlZEJ5QWJvcnRpbmdUcmFuc2l0aW9uID0gZmFsc2U7CiAgICAgIHRoaXMuaXNDYXVzZWRCeUluaXRpYWxUcmFuc2l0aW9uID0gZmFsc2U7CiAgICAgIHRoaXMuaXNDYXVzZWRCeUFib3J0aW5nUmVwbGFjZVRyYW5zaXRpb24gPSBmYWxzZTsKICAgICAgdGhpcy5fdmlzaWJsZVF1ZXJ5UGFyYW1zID0ge307CiAgICAgIHRoaXNbU1RBVEVfU1lNQk9MXSA9IHN0YXRlIHx8IHJvdXRlci5zdGF0ZTsKICAgICAgdGhpcy5pbnRlbnQgPSBpbnRlbnQ7CiAgICAgIHRoaXMucm91dGVyID0gcm91dGVyOwogICAgICB0aGlzLmRhdGEgPSBpbnRlbnQgJiYgaW50ZW50LmRhdGEgfHwge307CiAgICAgIHRoaXMucmVzb2x2ZWRNb2RlbHMgPSB7fTsKICAgICAgdGhpc1tRVUVSWV9QQVJBTVNfU1lNQk9MXSA9IHt9OwogICAgICB0aGlzLnByb21pc2UgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuZXJyb3IgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXNbUEFSQU1TX1NZTUJPTF0gPSB7fTsKICAgICAgdGhpcy5yb3V0ZUluZm9zID0gW107CiAgICAgIHRoaXMudGFyZ2V0TmFtZSA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5waXZvdEhhbmRsZXIgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuc2VxdWVuY2UgPSAtMTsKCiAgICAgIGlmIChlcnJvcikgewogICAgICAgIHRoaXMucHJvbWlzZSA9IF9yc3ZwLlByb21pc2UucmVqZWN0KGVycm9yKTsKICAgICAgICB0aGlzLmVycm9yID0gZXJyb3I7CiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIGlmIHlvdSdyZSBkb2luZyBtdWx0aXBsZSByZWRpcmVjdHMsIG5lZWQgdGhlIG5ldyB0cmFuc2l0aW9uIHRvIGtub3cgaWYgaXQKICAgICAgLy8gaXMgYWN0dWFsbHkgcGFydCBvZiB0aGUgZmlyc3QgdHJhbnNpdGlvbiBvciBub3QuIEFueSBmdXJ0aGVyIHJlZGlyZWN0cwogICAgICAvLyBpbiB0aGUgaW5pdGlhbCB0cmFuc2l0aW9uIGFsc28gbmVlZCB0byBrbm93IGlmIHRoZXkgYXJlIHBhcnQgb2YgdGhlCiAgICAgIC8vIGluaXRpYWwgdHJhbnNpdGlvbgoKCiAgICAgIHRoaXMuaXNDYXVzZWRCeUFib3J0aW5nVHJhbnNpdGlvbiA9ICEhcHJldmlvdXNUcmFuc2l0aW9uOwogICAgICB0aGlzLmlzQ2F1c2VkQnlJbml0aWFsVHJhbnNpdGlvbiA9ICEhcHJldmlvdXNUcmFuc2l0aW9uICYmIChwcmV2aW91c1RyYW5zaXRpb24uaXNDYXVzZWRCeUluaXRpYWxUcmFuc2l0aW9uIHx8IHByZXZpb3VzVHJhbnNpdGlvbi5zZXF1ZW5jZSA9PT0gMCk7IC8vIEV2ZXJ5IHRyYW5zaXRpb24gaW4gdGhlIGNoYWluIGlzIGEgcmVwbGFjZQoKICAgICAgdGhpcy5pc0NhdXNlZEJ5QWJvcnRpbmdSZXBsYWNlVHJhbnNpdGlvbiA9ICEhcHJldmlvdXNUcmFuc2l0aW9uICYmIHByZXZpb3VzVHJhbnNpdGlvbi51cmxNZXRob2QgPT09ICdyZXBsYWNlJyAmJiAoIXByZXZpb3VzVHJhbnNpdGlvbi5pc0NhdXNlZEJ5QWJvcnRpbmdUcmFuc2l0aW9uIHx8IHByZXZpb3VzVHJhbnNpdGlvbi5pc0NhdXNlZEJ5QWJvcnRpbmdSZXBsYWNlVHJhbnNpdGlvbik7CgogICAgICBpZiAoc3RhdGUpIHsKICAgICAgICB0aGlzW1BBUkFNU19TWU1CT0xdID0gc3RhdGUucGFyYW1zOwogICAgICAgIHRoaXNbUVVFUllfUEFSQU1TX1NZTUJPTF0gPSBzdGF0ZS5xdWVyeVBhcmFtczsKICAgICAgICB0aGlzLnJvdXRlSW5mb3MgPSBzdGF0ZS5yb3V0ZUluZm9zOwogICAgICAgIHZhciBsZW4gPSBzdGF0ZS5yb3V0ZUluZm9zLmxlbmd0aDsKCiAgICAgICAgaWYgKGxlbikgewogICAgICAgICAgdGhpcy50YXJnZXROYW1lID0gc3RhdGUucm91dGVJbmZvc1tsZW4gLSAxXS5uYW1lOwogICAgICAgIH0KCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSkgewogICAgICAgICAgdmFyIGhhbmRsZXJJbmZvID0gc3RhdGUucm91dGVJbmZvc1tpXTsgLy8gVE9ETzogdGhpcyBhbGwgc2VlbXMgaGFja3kKCiAgICAgICAgICBpZiAoIWhhbmRsZXJJbmZvLmlzUmVzb2x2ZWQpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5waXZvdEhhbmRsZXIgPSBoYW5kbGVySW5mby5yb3V0ZTsKICAgICAgICB9CgogICAgICAgIHRoaXMuc2VxdWVuY2UgPSByb3V0ZXIuY3VycmVudFNlcXVlbmNlKys7CiAgICAgICAgdGhpcy5wcm9taXNlID0gc3RhdGUucmVzb2x2ZShmdW5jdGlvbiAoKSB7CiAgICAgICAgICBpZiAoX3RoaXMuaXNBYm9ydGVkKSB7CiAgICAgICAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlamVjdChmYWxzZSwgX3Byb21pc2VMYWJlbCgnVHJhbnNpdGlvbiBhYm9ydGVkIC0gcmVqZWN0JykpOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlc29sdmUodHJ1ZSk7CiAgICAgICAgfSwgdGhpcykuY2F0Y2goZnVuY3Rpb24gKHJlc3VsdCkgewogICAgICAgICAgcmV0dXJuIF9yc3ZwLlByb21pc2UucmVqZWN0KF90aGlzLnJvdXRlci50cmFuc2l0aW9uRGlkRXJyb3IocmVzdWx0LCBfdGhpcykpOwogICAgICAgIH0sIF9wcm9taXNlTGFiZWwoJ0hhbmRsZSBBYm9ydCcpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnByb21pc2UgPSBfcnN2cC5Qcm9taXNlLnJlc29sdmUodGhpc1tTVEFURV9TWU1CT0xdKTsKICAgICAgICB0aGlzW1BBUkFNU19TWU1CT0xdID0ge307CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBUaGUgVHJhbnNpdGlvbidzIGludGVybmFsIHByb21pc2UuIENhbGxpbmcgYC50aGVuYCBvbiB0aGlzIHByb3BlcnR5CiAgICAgIGlzIHRoYXQgc2FtZSBhcyBjYWxsaW5nIGAudGhlbmAgb24gdGhlIFRyYW5zaXRpb24gb2JqZWN0IGl0c2VsZiwgYnV0CiAgICAgIHRoaXMgcHJvcGVydHkgaXMgZXhwb3NlZCBmb3Igd2hlbiB5b3Ugd2FudCB0byBwYXNzIGFyb3VuZCBhCiAgICAgIFRyYW5zaXRpb24ncyBwcm9taXNlLCBidXQgbm90IHRoZSBUcmFuc2l0aW9uIG9iamVjdCBpdHNlbGYsIHNpbmNlCiAgICAgIFRyYW5zaXRpb24gb2JqZWN0IGNhbiBiZSBleHRlcm5hbGx5IGBhYm9ydGBlZCwgd2hpbGUgdGhlIHByb21pc2UKICAgICAgY2Fubm90LgogICAgICAgICBAcHJvcGVydHkgcHJvbWlzZQogICAgICBAdHlwZSB7T2JqZWN0fQogICAgICBAcHVibGljCiAgICAgKi8KCiAgICAvKioKICAgICAgQ3VzdG9tIHN0YXRlIGNhbiBiZSBzdG9yZWQgb24gYSBUcmFuc2l0aW9uJ3MgYGRhdGFgIG9iamVjdC4KICAgICAgVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBkZWNvcmF0aW5nIGEgVHJhbnNpdGlvbiB3aXRoaW4gYW4gZWFybGllcgogICAgICBob29rIGFuZCBzaGFyZWQgd2l0aCBhIGxhdGVyIGhvb2suIFByb3BlcnRpZXMgc2V0IG9uIGBkYXRhYCB3aWxsCiAgICAgIGJlIGNvcGllZCB0byBuZXcgdHJhbnNpdGlvbnMgZ2VuZXJhdGVkIGJ5IGNhbGxpbmcgYHJldHJ5YCBvbiB0aGlzCiAgICAgIHRyYW5zaXRpb24uCiAgICAgICAgIEBwcm9wZXJ0eSBkYXRhCiAgICAgIEB0eXBlIHtPYmplY3R9CiAgICAgIEBwdWJsaWMKICAgICAqLwoKICAgIC8qKgogICAgICBBIHN0YW5kYXJkIHByb21pc2UgaG9vayB0aGF0IHJlc29sdmVzIGlmIHRoZSB0cmFuc2l0aW9uCiAgICAgIHN1Y2NlZWRzIGFuZCByZWplY3RzIGlmIGl0IGZhaWxzL3JlZGlyZWN0cy9hYm9ydHMuCiAgICAgICAgIEZvcndhcmRzIHRvIHRoZSBpbnRlcm5hbCBgcHJvbWlzZWAgcHJvcGVydHkgd2hpY2ggeW91IGNhbgogICAgICB1c2UgaW4gc2l0dWF0aW9ucyB3aGVyZSB5b3Ugd2FudCB0byBwYXNzIGFyb3VuZCBhIHRoZW5uYWJsZSwKICAgICAgYnV0IG5vdCB0aGUgVHJhbnNpdGlvbiBpdHNlbGYuCiAgICAgICAgIEBtZXRob2QgdGhlbgogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvbkZ1bGZpbGxlZAogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGVkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBsYWJlbCBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICAgIEByZXR1cm4ge1Byb21pc2V9CiAgICAgIEBwdWJsaWMKICAgICAqLwoKCiAgICB2YXIgX3Byb3RvID0gVHJhbnNpdGlvbi5wcm90b3R5cGU7CgogICAgX3Byb3RvLnRoZW4gPSBmdW5jdGlvbiB0aGVuKG9uRnVsZmlsbGVkLCBvblJlamVjdGVkLCBsYWJlbCkgewogICAgICByZXR1cm4gdGhpcy5wcm9taXNlLnRoZW4ob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQsIGxhYmVsKTsKICAgIH0KICAgIC8qKgogICAgICAgICBGb3J3YXJkcyB0byB0aGUgaW50ZXJuYWwgYHByb21pc2VgIHByb3BlcnR5IHdoaWNoIHlvdSBjYW4KICAgICAgdXNlIGluIHNpdHVhdGlvbnMgd2hlcmUgeW91IHdhbnQgdG8gcGFzcyBhcm91bmQgYSB0aGVubmFibGUsCiAgICAgIGJ1dCBub3QgdGhlIFRyYW5zaXRpb24gaXRzZWxmLgogICAgICAgICBAbWV0aG9kIGNhdGNoCiAgICAgIEBwYXJhbSB7RnVuY3Rpb259IG9uUmVqZWN0aW9uCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBsYWJlbCBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICAgIEByZXR1cm4ge1Byb21pc2V9CiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by5jYXRjaCA9IGZ1bmN0aW9uIF9jYXRjaChvblJlamVjdGlvbiwgbGFiZWwpIHsKICAgICAgcmV0dXJuIHRoaXMucHJvbWlzZS5jYXRjaChvblJlamVjdGlvbiwgbGFiZWwpOwogICAgfQogICAgLyoqCiAgICAgICAgIEZvcndhcmRzIHRvIHRoZSBpbnRlcm5hbCBgcHJvbWlzZWAgcHJvcGVydHkgd2hpY2ggeW91IGNhbgogICAgICB1c2UgaW4gc2l0dWF0aW9ucyB3aGVyZSB5b3Ugd2FudCB0byBwYXNzIGFyb3VuZCBhIHRoZW5uYWJsZSwKICAgICAgYnV0IG5vdCB0aGUgVHJhbnNpdGlvbiBpdHNlbGYuCiAgICAgICAgIEBtZXRob2QgZmluYWxseQogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgICBAcGFyYW0ge1N0cmluZ30gbGFiZWwgb3B0aW9uYWwgc3RyaW5nIGZvciBsYWJlbGluZyB0aGUgcHJvbWlzZS4KICAgICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgICBAcmV0dXJuIHtQcm9taXNlfQogICAgICBAcHVibGljCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZmluYWxseSA9IGZ1bmN0aW9uIF9maW5hbGx5KGNhbGxiYWNrLCBsYWJlbCkgewogICAgICByZXR1cm4gdGhpcy5wcm9taXNlLmZpbmFsbHkoY2FsbGJhY2ssIGxhYmVsKTsKICAgIH0KICAgIC8qKgogICAgICBBYm9ydHMgdGhlIFRyYW5zaXRpb24uIE5vdGUgeW91IGNhbiBhbHNvIGltcGxpY2l0bHkgYWJvcnQgYSB0cmFuc2l0aW9uCiAgICAgIGJ5IGluaXRpYXRpbmcgYW5vdGhlciB0cmFuc2l0aW9uIHdoaWxlIGEgcHJldmlvdXMgb25lIGlzIHVuZGVyd2F5LgogICAgICAgICBAbWV0aG9kIGFib3J0CiAgICAgIEByZXR1cm4ge1RyYW5zaXRpb259IHRoaXMgdHJhbnNpdGlvbgogICAgICBAcHVibGljCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uYWJvcnQgPSBmdW5jdGlvbiBhYm9ydCgpIHsKICAgICAgdGhpcy5yb2xsYmFjaygpOwogICAgICB2YXIgdHJhbnNpdGlvbiA9IG5ldyBUcmFuc2l0aW9uKHRoaXMucm91dGVyLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkKTsKICAgICAgdHJhbnNpdGlvbi50byA9IHRoaXMuZnJvbTsKICAgICAgdHJhbnNpdGlvbi5mcm9tID0gdGhpcy5mcm9tOwogICAgICB0cmFuc2l0aW9uLmlzQWJvcnRlZCA9IHRydWU7CiAgICAgIHRoaXMucm91dGVyLnJvdXRlV2lsbENoYW5nZSh0cmFuc2l0aW9uKTsKICAgICAgdGhpcy5yb3V0ZXIucm91dGVEaWRDaGFuZ2UodHJhbnNpdGlvbik7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICBfcHJvdG8ucm9sbGJhY2sgPSBmdW5jdGlvbiByb2xsYmFjaygpIHsKICAgICAgaWYgKCF0aGlzLmlzQWJvcnRlZCkgewogICAgICAgIF9sb2codGhpcy5yb3V0ZXIsIHRoaXMuc2VxdWVuY2UsIHRoaXMudGFyZ2V0TmFtZSArICc6IHRyYW5zaXRpb24gd2FzIGFib3J0ZWQnKTsKCiAgICAgICAgaWYgKHRoaXMuaW50ZW50ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pbnRlbnQgIT09IG51bGwpIHsKICAgICAgICAgIHRoaXMuaW50ZW50LnByZVRyYW5zaXRpb25TdGF0ZSA9IHRoaXMucm91dGVyLnN0YXRlOwogICAgICAgIH0KCiAgICAgICAgdGhpcy5pc0Fib3J0ZWQgPSB0cnVlOwogICAgICAgIHRoaXMuaXNBY3RpdmUgPSBmYWxzZTsKICAgICAgICB0aGlzLnJvdXRlci5hY3RpdmVUcmFuc2l0aW9uID0gdW5kZWZpbmVkOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZWRpcmVjdCA9IGZ1bmN0aW9uIHJlZGlyZWN0KG5ld1RyYW5zaXRpb24pIHsKICAgICAgdGhpcy5yb2xsYmFjaygpOwogICAgICB0aGlzLnJvdXRlci5yb3V0ZVdpbGxDaGFuZ2UobmV3VHJhbnNpdGlvbik7CiAgICB9CiAgICAvKioKICAgICAgICAgUmV0cmllcyBhIHByZXZpb3VzbHktYWJvcnRlZCB0cmFuc2l0aW9uIChtYWtpbmcgc3VyZSB0byBhYm9ydCB0aGUKICAgICAgdHJhbnNpdGlvbiBpZiBpdCdzIHN0aWxsIGFjdGl2ZSkuIFJldHVybnMgYSBuZXcgdHJhbnNpdGlvbiB0aGF0CiAgICAgIHJlcHJlc2VudHMgdGhlIG5ldyBhdHRlbXB0IHRvIHRyYW5zaXRpb24uCiAgICAgICAgIEBtZXRob2QgcmV0cnkKICAgICAgQHJldHVybiB7VHJhbnNpdGlvbn0gbmV3IHRyYW5zaXRpb24KICAgICAgQHB1YmxpYwogICAgICovCiAgICA7CgogICAgX3Byb3RvLnJldHJ5ID0gZnVuY3Rpb24gcmV0cnkoKSB7CiAgICAgIC8vIFRPRE86IGFkZCB0ZXN0cyBmb3IgbWVyZ2VkIHN0YXRlIHJldHJ5KClzCiAgICAgIHRoaXMuYWJvcnQoKTsKICAgICAgdmFyIG5ld1RyYW5zaXRpb24gPSB0aGlzLnJvdXRlci50cmFuc2l0aW9uQnlJbnRlbnQodGhpcy5pbnRlbnQsIGZhbHNlKTsgLy8gaW5oZXJpdGluZyBhIGBudWxsYCB1cmxNZXRob2QgaXMgbm90IHZhbGlkCiAgICAgIC8vIHRoZSB1cmxNZXRob2QgaXMgb25seSBzZXQgdG8gYG51bGxgIHdoZW4KICAgICAgLy8gdGhlIHRyYW5zaXRpb24gaXMgaW5pdGlhdGVkICphZnRlciogdGhlIHVybAogICAgICAvLyBoYXMgYmVlbiB1cGRhdGVkIChpLmUuIGByb3V0ZXIuaGFuZGxlVVJMYCkKICAgICAgLy8KICAgICAgLy8gaW4gdGhhdCBzY2VuYXJpbywgdGhlIHVybCBtZXRob2QgY2Fubm90IGJlCiAgICAgIC8vIGluaGVyaXRlZCBmb3IgYSBuZXcgdHJhbnNpdGlvbiBiZWNhdXNlIHRoZW4KICAgICAgLy8gdGhlIHVybCB3b3VsZCBub3QgdXBkYXRlIGV2ZW4gdGhvdWdoIGl0IHNob3VsZAoKICAgICAgaWYgKHRoaXMudXJsTWV0aG9kICE9PSBudWxsKSB7CiAgICAgICAgbmV3VHJhbnNpdGlvbi5tZXRob2QodGhpcy51cmxNZXRob2QpOwogICAgICB9CgogICAgICByZXR1cm4gbmV3VHJhbnNpdGlvbjsKICAgIH0KICAgIC8qKgogICAgICAgICBTZXRzIHRoZSBVUkwtY2hhbmdpbmcgbWV0aG9kIHRvIGJlIGVtcGxveWVkIGF0IHRoZSBlbmQgb2YgYQogICAgICBzdWNjZXNzZnVsIHRyYW5zaXRpb24uIEJ5IGRlZmF1bHQsIGEgbmV3IFRyYW5zaXRpb24gd2lsbCBqdXN0CiAgICAgIHVzZSBgdXBkYXRlVVJMYCwgYnV0IHBhc3NpbmcgJ3JlcGxhY2UnIHRvIHRoaXMgbWV0aG9kIHdpbGwKICAgICAgY2F1c2UgdGhlIFVSTCB0byB1cGRhdGUgdXNpbmcgJ3JlcGxhY2VXaXRoJyBpbnN0ZWFkLiBPbWl0dGluZwogICAgICBhIHBhcmFtZXRlciB3aWxsIGRpc2FibGUgdGhlIFVSTCBjaGFuZ2UsIGFsbG93aW5nIGZvciB0cmFuc2l0aW9ucwogICAgICB0aGF0IGRvbid0IHVwZGF0ZSB0aGUgVVJMIGF0IGNvbXBsZXRpb24gKHRoaXMgaXMgYWxzbyB1c2VkIGZvcgogICAgICBoYW5kbGVVUkwsIHNpbmNlIHRoZSBVUkwgaGFzIGFscmVhZHkgY2hhbmdlZCBiZWZvcmUgdGhlCiAgICAgIHRyYW5zaXRpb24gdG9vayBwbGFjZSkuCiAgICAgICAgIEBtZXRob2QgbWV0aG9kCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgdGhlIHR5cGUgb2YgVVJMLWNoYW5naW5nIG1ldGhvZCB0byB1c2UKICAgICAgICBhdCB0aGUgZW5kIG9mIGEgdHJhbnNpdGlvbi4gQWNjZXB0ZWQgdmFsdWVzIGFyZSAncmVwbGFjZScsCiAgICAgICAgZmFsc3kgdmFsdWVzLCBvciBhbnkgb3RoZXIgbm9uLWZhbHN5IHZhbHVlICh3aGljaCBpcwogICAgICAgIGludGVycHJldGVkIGFzIGFuIHVwZGF0ZVVSTCB0cmFuc2l0aW9uKS4KICAgICAgICAgQHJldHVybiB7VHJhbnNpdGlvbn0gdGhpcyB0cmFuc2l0aW9uCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by5tZXRob2QgPSBmdW5jdGlvbiBtZXRob2QoX21ldGhvZCkgewogICAgICB0aGlzLnVybE1ldGhvZCA9IF9tZXRob2Q7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSAvLyBBbGlhcyAndHJpZ2dlcicgYXMgJ3NlbmQnCiAgICA7CgogICAgX3Byb3RvLnNlbmQgPSBmdW5jdGlvbiBzZW5kKGlnbm9yZUZhaWx1cmUsIF9uYW1lLCBlcnIsIHRyYW5zaXRpb24sIGhhbmRsZXIpIHsKICAgICAgaWYgKGlnbm9yZUZhaWx1cmUgPT09IHZvaWQgMCkgewogICAgICAgIGlnbm9yZUZhaWx1cmUgPSBmYWxzZTsKICAgICAgfQoKICAgICAgdGhpcy50cmlnZ2VyKGlnbm9yZUZhaWx1cmUsIF9uYW1lLCBlcnIsIHRyYW5zaXRpb24sIGhhbmRsZXIpOwogICAgfQogICAgLyoqCiAgICAgICAgIEZpcmVzIGFuIGV2ZW50IG9uIHRoZSBjdXJyZW50IGxpc3Qgb2YgcmVzb2x2ZWQvcmVzb2x2aW5nCiAgICAgIGhhbmRsZXJzIHdpdGhpbiB0aGlzIHRyYW5zaXRpb24uIFVzZWZ1bCBmb3IgZmlyaW5nIGV2ZW50cwogICAgICBvbiByb3V0ZSBoaWVyYXJjaGllcyB0aGF0IGhhdmVuJ3QgZnVsbHkgYmVlbiBlbnRlcmVkIHlldC4KICAgICAgICAgTm90ZTogVGhpcyBtZXRob2QgaXMgYWxzbyBhbGlhc2VkIGFzIGBzZW5kYAogICAgICAgICBAbWV0aG9kIHRyaWdnZXIKICAgICAgQHBhcmFtIHtCb29sZWFufSBbaWdub3JlRmFpbHVyZT1mYWxzZV0gYSBib29sZWFuIHNwZWNpZnlpbmcgd2hldGhlciB1bmhhbmRsZWQgZXZlbnRzIHRocm93IGFuIGVycm9yCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBmaXJlCiAgICAgIEBwdWJsaWMKICAgICAqLwogICAgOwoKICAgIF9wcm90by50cmlnZ2VyID0gZnVuY3Rpb24gdHJpZ2dlcihpZ25vcmVGYWlsdXJlLCBuYW1lKSB7CiAgICAgIGlmIChpZ25vcmVGYWlsdXJlID09PSB2b2lkIDApIHsKICAgICAgICBpZ25vcmVGYWlsdXJlID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIC8vIFRPRE86IERlcHJlY2F0ZSB0aGUgY3VycmVudCBzaWduYXR1cmUKICAgICAgaWYgKHR5cGVvZiBpZ25vcmVGYWlsdXJlID09PSAnc3RyaW5nJykgewogICAgICAgIG5hbWUgPSBpZ25vcmVGYWlsdXJlOwogICAgICAgIGlnbm9yZUZhaWx1cmUgPSBmYWxzZTsKICAgICAgfQoKICAgICAgZm9yICh2YXIgX2xlbjIgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW4yID4gMiA/IF9sZW4yIC0gMiA6IDApLCBfa2V5MiA9IDI7IF9rZXkyIDwgX2xlbjI7IF9rZXkyKyspIHsKICAgICAgICBhcmdzW19rZXkyIC0gMl0gPSBhcmd1bWVudHNbX2tleTJdOwogICAgICB9CgogICAgICB0aGlzLnJvdXRlci50cmlnZ2VyRXZlbnQodGhpc1tTVEFURV9TWU1CT0xdLnJvdXRlSW5mb3Muc2xpY2UoMCwgdGhpcy5yZXNvbHZlSW5kZXggKyAxKSwgaWdub3JlRmFpbHVyZSwgbmFtZSwgYXJncyk7CiAgICB9CiAgICAvKioKICAgICAgVHJhbnNpdGlvbnMgYXJlIGFib3J0ZWQgYW5kIHRoZWlyIHByb21pc2VzIHJlamVjdGVkCiAgICAgIHdoZW4gcmVkaXJlY3RzIG9jY3VyOyB0aGlzIG1ldGhvZCByZXR1cm5zIGEgcHJvbWlzZQogICAgICB0aGF0IHdpbGwgZm9sbG93IGFueSByZWRpcmVjdHMgdGhhdCBvY2N1ciBhbmQgZnVsZmlsbAogICAgICB3aXRoIHRoZSB2YWx1ZSBmdWxmaWxsZWQgYnkgYW55IHJlZGlyZWN0aW5nIHRyYW5zaXRpb25zCiAgICAgIHRoYXQgb2NjdXIuCiAgICAgICAgIEBtZXRob2QgZm9sbG93UmVkaXJlY3RzCiAgICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIHdpdGggdGhlIHNhbWUKICAgICAgICB2YWx1ZSB0aGF0IHRoZSBmaW5hbCByZWRpcmVjdGluZyB0cmFuc2l0aW9uIGZ1bGZpbGxzIHdpdGgKICAgICAgQHB1YmxpYwogICAgICovCiAgICA7CgogICAgX3Byb3RvLmZvbGxvd1JlZGlyZWN0cyA9IGZ1bmN0aW9uIGZvbGxvd1JlZGlyZWN0cygpIHsKICAgICAgdmFyIHJvdXRlciA9IHRoaXMucm91dGVyOwogICAgICByZXR1cm4gdGhpcy5wcm9taXNlLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICBpZiAocm91dGVyLmFjdGl2ZVRyYW5zaXRpb24pIHsKICAgICAgICAgIHJldHVybiByb3V0ZXIuYWN0aXZlVHJhbnNpdGlvbi5mb2xsb3dSZWRpcmVjdHMoKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlamVjdChyZWFzb24pOwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiAnVHJhbnNpdGlvbiAoc2VxdWVuY2UgJyArIHRoaXMuc2VxdWVuY2UgKyAnKSc7CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAqLwogICAgOwoKICAgIF9wcm90by5sb2cgPSBmdW5jdGlvbiBsb2cobWVzc2FnZSkgewogICAgICBfbG9nKHRoaXMucm91dGVyLCB0aGlzLnNlcXVlbmNlLCBtZXNzYWdlKTsKICAgIH07CgogICAgcmV0dXJuIFRyYW5zaXRpb247CiAgfSgpOwogIC8qKgogICAgQHByaXZhdGUKICAKICAgIExvZ3MgYW5kIHJldHVybnMgYW4gaW5zdGFuY2Ugb2YgVHJhbnNpdGlvbkFib3J0ZWQuCiAgICovCgoKICBfZXhwb3J0cy5JbnRlcm5hbFRyYW5zaXRpb24gPSBUcmFuc2l0aW9uOwoKICBmdW5jdGlvbiBsb2dBYm9ydCh0cmFuc2l0aW9uKSB7CiAgICBfbG9nKHRyYW5zaXRpb24ucm91dGVyLCB0cmFuc2l0aW9uLnNlcXVlbmNlLCAnZGV0ZWN0ZWQgYWJvcnQuJyk7CgogICAgcmV0dXJuIG5ldyBUcmFuc2l0aW9uQWJvcnRlZEVycm9yKCk7CiAgfQoKICBmdW5jdGlvbiBpc1RyYW5zaXRpb24ob2JqKSB7CiAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgb2JqIGluc3RhbmNlb2YgVHJhbnNpdGlvbiAmJiBvYmouaXNUcmFuc2l0aW9uOwogIH0KCiAgZnVuY3Rpb24gcHJlcGFyZVJlc3VsdChvYmopIHsKICAgIGlmIChpc1RyYW5zaXRpb24ob2JqKSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KCiAgICByZXR1cm4gb2JqOwogIH0KCiAgdmFyIFJPVVRFX0lORk9TID0gbmV3IFdlYWtNYXAoKTsKCiAgZnVuY3Rpb24gdG9SZWFkT25seVJvdXRlSW5mbyhyb3V0ZUluZm9zLCBxdWVyeVBhcmFtcywgaW5jbHVkZUF0dHJpYnV0ZXMpIHsKICAgIGlmIChxdWVyeVBhcmFtcyA9PT0gdm9pZCAwKSB7CiAgICAgIHF1ZXJ5UGFyYW1zID0ge307CiAgICB9CgogICAgaWYgKGluY2x1ZGVBdHRyaWJ1dGVzID09PSB2b2lkIDApIHsKICAgICAgaW5jbHVkZUF0dHJpYnV0ZXMgPSBmYWxzZTsKICAgIH0KCiAgICByZXR1cm4gcm91dGVJbmZvcy5tYXAoZnVuY3Rpb24gKGluZm8sIGkpIHsKICAgICAgdmFyIG5hbWUgPSBpbmZvLm5hbWUsCiAgICAgICAgICBwYXJhbXMgPSBpbmZvLnBhcmFtcywKICAgICAgICAgIHBhcmFtTmFtZXMgPSBpbmZvLnBhcmFtTmFtZXMsCiAgICAgICAgICBjb250ZXh0ID0gaW5mby5jb250ZXh0LAogICAgICAgICAgcm91dGUgPSBpbmZvLnJvdXRlOwoKICAgICAgaWYgKFJPVVRFX0lORk9TLmhhcyhpbmZvKSAmJiBpbmNsdWRlQXR0cmlidXRlcykgewogICAgICAgIHZhciBfcm91dGVJbmZvID0gUk9VVEVfSU5GT1MuZ2V0KGluZm8pOwoKICAgICAgICBfcm91dGVJbmZvID0gYXR0YWNoTWV0YWRhdGEocm91dGUsIF9yb3V0ZUluZm8pOwogICAgICAgIHZhciByb3V0ZUluZm9XaXRoQXR0cmlidXRlID0gY3JlYXRlUm91dGVJbmZvV2l0aEF0dHJpYnV0ZXMoX3JvdXRlSW5mbywgY29udGV4dCk7CiAgICAgICAgUk9VVEVfSU5GT1Muc2V0KGluZm8sIHJvdXRlSW5mb1dpdGhBdHRyaWJ1dGUpOwogICAgICAgIHJldHVybiByb3V0ZUluZm9XaXRoQXR0cmlidXRlOwogICAgICB9CgogICAgICB2YXIgcm91dGVJbmZvID0gewogICAgICAgIGZpbmQ6IGZ1bmN0aW9uIGZpbmQocHJlZGljYXRlLCB0aGlzQXJnKSB7CiAgICAgICAgICB2YXIgcHVibGljSW5mbzsKICAgICAgICAgIHZhciBhcnIgPSBbXTsKCiAgICAgICAgICBpZiAocHJlZGljYXRlLmxlbmd0aCA9PT0gMykgewogICAgICAgICAgICBhcnIgPSByb3V0ZUluZm9zLm1hcChmdW5jdGlvbiAoaW5mbykgewogICAgICAgICAgICAgIHJldHVybiBST1VURV9JTkZPUy5nZXQoaW5mbyk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQoKICAgICAgICAgIGZvciAodmFyIF9pID0gMDsgcm91dGVJbmZvcy5sZW5ndGggPiBfaTsgX2krKykgewogICAgICAgICAgICBwdWJsaWNJbmZvID0gUk9VVEVfSU5GT1MuZ2V0KHJvdXRlSW5mb3NbX2ldKTsKCiAgICAgICAgICAgIGlmIChwcmVkaWNhdGUuY2FsbCh0aGlzQXJnLCBwdWJsaWNJbmZvLCBfaSwgYXJyKSkgewogICAgICAgICAgICAgIHJldHVybiBwdWJsaWNJbmZvOwogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgICAgICB9LAoKICAgICAgICBnZXQgbmFtZSgpIHsKICAgICAgICAgIHJldHVybiBuYW1lOwogICAgICAgIH0sCgogICAgICAgIGdldCBwYXJhbU5hbWVzKCkgewogICAgICAgICAgcmV0dXJuIHBhcmFtTmFtZXM7CiAgICAgICAgfSwKCiAgICAgICAgZ2V0IG1ldGFkYXRhKCkgewogICAgICAgICAgcmV0dXJuIGJ1aWxkUm91dGVJbmZvTWV0YWRhdGEoaW5mby5yb3V0ZSk7CiAgICAgICAgfSwKCiAgICAgICAgZ2V0IHBhcmVudCgpIHsKICAgICAgICAgIHZhciBwYXJlbnQgPSByb3V0ZUluZm9zW2kgLSAxXTsKCiAgICAgICAgICBpZiAocGFyZW50ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIFJPVVRFX0lORk9TLmdldChwYXJlbnQpOwogICAgICAgIH0sCgogICAgICAgIGdldCBjaGlsZCgpIHsKICAgICAgICAgIHZhciBjaGlsZCA9IHJvdXRlSW5mb3NbaSArIDFdOwoKICAgICAgICAgIGlmIChjaGlsZCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBST1VURV9JTkZPUy5nZXQoY2hpbGQpOwogICAgICAgIH0sCgogICAgICAgIGdldCBsb2NhbE5hbWUoKSB7CiAgICAgICAgICB2YXIgcGFydHMgPSB0aGlzLm5hbWUuc3BsaXQoJy4nKTsKICAgICAgICAgIHJldHVybiBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXTsKICAgICAgICB9LAoKICAgICAgICBnZXQgcGFyYW1zKCkgewogICAgICAgICAgcmV0dXJuIHBhcmFtczsKICAgICAgICB9LAoKICAgICAgICBnZXQgcXVlcnlQYXJhbXMoKSB7CiAgICAgICAgICByZXR1cm4gcXVlcnlQYXJhbXM7CiAgICAgICAgfQoKICAgICAgfTsKCiAgICAgIGlmIChpbmNsdWRlQXR0cmlidXRlcykgewogICAgICAgIHJvdXRlSW5mbyA9IGNyZWF0ZVJvdXRlSW5mb1dpdGhBdHRyaWJ1dGVzKHJvdXRlSW5mbywgY29udGV4dCk7CiAgICAgIH0KCiAgICAgIFJPVVRFX0lORk9TLnNldChpbmZvLCByb3V0ZUluZm8pOwogICAgICByZXR1cm4gcm91dGVJbmZvOwogICAgfSk7CiAgfQoKICBmdW5jdGlvbiBjcmVhdGVSb3V0ZUluZm9XaXRoQXR0cmlidXRlcyhyb3V0ZUluZm8sIGNvbnRleHQpIHsKICAgIHZhciBhdHRyaWJ1dGVzID0gewogICAgICBnZXQgYXR0cmlidXRlcygpIHsKICAgICAgICByZXR1cm4gY29udGV4dDsKICAgICAgfQoKICAgIH07CgogICAgaWYgKE9iamVjdC5pc0Zyb3plbihyb3V0ZUluZm8pIHx8IHJvdXRlSW5mby5oYXNPd25Qcm9wZXJ0eSgnYXR0cmlidXRlcycpKSB7CiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKCgwLCBfcG9seWZpbGxzLmFzc2lnbikoe30sIHJvdXRlSW5mbywgYXR0cmlidXRlcykpOwogICAgfQoKICAgIHJldHVybiAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHJvdXRlSW5mbywgYXR0cmlidXRlcyk7CiAgfQoKICBmdW5jdGlvbiBidWlsZFJvdXRlSW5mb01ldGFkYXRhKHJvdXRlKSB7CiAgICBpZiAocm91dGUgIT09IHVuZGVmaW5lZCAmJiByb3V0ZSAhPT0gbnVsbCAmJiByb3V0ZS5idWlsZFJvdXRlSW5mb01ldGFkYXRhICE9PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuIHJvdXRlLmJ1aWxkUm91dGVJbmZvTWV0YWRhdGEoKTsKICAgIH0KCiAgICByZXR1cm4gbnVsbDsKICB9CgogIGZ1bmN0aW9uIGF0dGFjaE1ldGFkYXRhKHJvdXRlLCByb3V0ZUluZm8pIHsKICAgIHZhciBtZXRhZGF0YSA9IHsKICAgICAgZ2V0IG1ldGFkYXRhKCkgewogICAgICAgIHJldHVybiBidWlsZFJvdXRlSW5mb01ldGFkYXRhKHJvdXRlKTsKICAgICAgfQoKICAgIH07CgogICAgaWYgKE9iamVjdC5pc0Zyb3plbihyb3V0ZUluZm8pIHx8IHJvdXRlSW5mby5oYXNPd25Qcm9wZXJ0eSgnbWV0YWRhdGEnKSkgewogICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSgoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCByb3V0ZUluZm8sIG1ldGFkYXRhKSk7CiAgICB9CgogICAgcmV0dXJuICgwLCBfcG9seWZpbGxzLmFzc2lnbikocm91dGVJbmZvLCBtZXRhZGF0YSk7CiAgfQoKICB2YXIgSW50ZXJuYWxSb3V0ZUluZm8gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBJbnRlcm5hbFJvdXRlSW5mbyhyb3V0ZXIsIG5hbWUsIHBhcmFtTmFtZXMsIHJvdXRlKSB7CiAgICAgIHRoaXMuX3JvdXRlUHJvbWlzZSA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5fcm91dGUgPSBudWxsOwogICAgICB0aGlzLnBhcmFtcyA9IHt9OwogICAgICB0aGlzLmlzUmVzb2x2ZWQgPSBmYWxzZTsKICAgICAgdGhpcy5uYW1lID0gbmFtZTsKICAgICAgdGhpcy5wYXJhbU5hbWVzID0gcGFyYW1OYW1lczsKICAgICAgdGhpcy5yb3V0ZXIgPSByb3V0ZXI7CgogICAgICBpZiAocm91dGUpIHsKICAgICAgICB0aGlzLl9wcm9jZXNzUm91dGUocm91dGUpOwogICAgICB9CiAgICB9CgogICAgdmFyIF9wcm90bzIgPSBJbnRlcm5hbFJvdXRlSW5mby5wcm90b3R5cGU7CgogICAgX3Byb3RvMi5nZXRNb2RlbCA9IGZ1bmN0aW9uIGdldE1vZGVsKF90cmFuc2l0aW9uKSB7CiAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlc29sdmUodGhpcy5jb250ZXh0KTsKICAgIH07CgogICAgX3Byb3RvMi5zZXJpYWxpemUgPSBmdW5jdGlvbiBzZXJpYWxpemUoX2NvbnRleHQpIHsKICAgICAgcmV0dXJuIHRoaXMucGFyYW1zIHx8IHt9OwogICAgfTsKCiAgICBfcHJvdG8yLnJlc29sdmUgPSBmdW5jdGlvbiByZXNvbHZlKHNob3VsZENvbnRpbnVlLCB0cmFuc2l0aW9uKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgcmV0dXJuIF9yc3ZwLlByb21pc2UucmVzb2x2ZSh0aGlzLnJvdXRlUHJvbWlzZSkudGhlbihmdW5jdGlvbiAocm91dGUpIHsKICAgICAgICByZXR1cm4gX3RoaXMyLmNoZWNrRm9yQWJvcnQoc2hvdWxkQ29udGludWUsIHJvdXRlKTsKICAgICAgfSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIF90aGlzMi5ydW5CZWZvcmVNb2RlbEhvb2sodHJhbnNpdGlvbik7CiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBfdGhpczIuY2hlY2tGb3JBYm9ydChzaG91bGRDb250aW51ZSwgbnVsbCk7CiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBfdGhpczIuZ2V0TW9kZWwodHJhbnNpdGlvbik7CiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKHJlc29sdmVkTW9kZWwpIHsKICAgICAgICByZXR1cm4gX3RoaXMyLmNoZWNrRm9yQWJvcnQoc2hvdWxkQ29udGludWUsIHJlc29sdmVkTW9kZWwpOwogICAgICB9KS50aGVuKGZ1bmN0aW9uIChyZXNvbHZlZE1vZGVsKSB7CiAgICAgICAgcmV0dXJuIF90aGlzMi5ydW5BZnRlck1vZGVsSG9vayh0cmFuc2l0aW9uLCByZXNvbHZlZE1vZGVsKTsKICAgICAgfSkudGhlbihmdW5jdGlvbiAocmVzb2x2ZWRNb2RlbCkgewogICAgICAgIHJldHVybiBfdGhpczIuYmVjb21lUmVzb2x2ZWQodHJhbnNpdGlvbiwgcmVzb2x2ZWRNb2RlbCk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8yLmJlY29tZVJlc29sdmVkID0gZnVuY3Rpb24gYmVjb21lUmVzb2x2ZWQodHJhbnNpdGlvbiwgcmVzb2x2ZWRDb250ZXh0KSB7CiAgICAgIHZhciBwYXJhbXMgPSB0aGlzLnNlcmlhbGl6ZShyZXNvbHZlZENvbnRleHQpOwoKICAgICAgaWYgKHRyYW5zaXRpb24pIHsKICAgICAgICB0aGlzLnN0YXNoUmVzb2x2ZWRNb2RlbCh0cmFuc2l0aW9uLCByZXNvbHZlZENvbnRleHQpOwogICAgICAgIHRyYW5zaXRpb25bUEFSQU1TX1NZTUJPTF0gPSB0cmFuc2l0aW9uW1BBUkFNU19TWU1CT0xdIHx8IHt9OwogICAgICAgIHRyYW5zaXRpb25bUEFSQU1TX1NZTUJPTF1bdGhpcy5uYW1lXSA9IHBhcmFtczsKICAgICAgfQoKICAgICAgdmFyIGNvbnRleHQ7CiAgICAgIHZhciBjb250ZXh0c01hdGNoID0gcmVzb2x2ZWRDb250ZXh0ID09PSB0aGlzLmNvbnRleHQ7CgogICAgICBpZiAoJ2NvbnRleHQnIGluIHRoaXMgfHwgIWNvbnRleHRzTWF0Y2gpIHsKICAgICAgICBjb250ZXh0ID0gcmVzb2x2ZWRDb250ZXh0OwogICAgICB9CgogICAgICB2YXIgY2FjaGVkID0gUk9VVEVfSU5GT1MuZ2V0KHRoaXMpOwogICAgICB2YXIgcmVzb2x2ZWQgPSBuZXcgUmVzb2x2ZWRSb3V0ZUluZm8odGhpcy5yb3V0ZXIsIHRoaXMubmFtZSwgdGhpcy5wYXJhbU5hbWVzLCBwYXJhbXMsIHRoaXMucm91dGUsIGNvbnRleHQpOwoKICAgICAgaWYgKGNhY2hlZCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgUk9VVEVfSU5GT1Muc2V0KHJlc29sdmVkLCBjYWNoZWQpOwogICAgICB9CgogICAgICByZXR1cm4gcmVzb2x2ZWQ7CiAgICB9OwoKICAgIF9wcm90bzIuc2hvdWxkU3VwZXJjZWRlID0gZnVuY3Rpb24gc2hvdWxkU3VwZXJjZWRlKHJvdXRlSW5mbykgewogICAgICAvLyBQcmVmZXIgdGhpcyBuZXdlciByb3V0ZUluZm8gb3ZlciBgb3RoZXJgIGlmOgogICAgICAvLyAxKSBUaGUgb3RoZXIgb25lIGRvZXNuJ3QgZXhpc3QKICAgICAgLy8gMikgVGhlIG5hbWVzIGRvbid0IG1hdGNoCiAgICAgIC8vIDMpIFRoaXMgcm91dGUgaGFzIGEgY29udGV4dCB0aGF0IGRvZXNuJ3QgbWF0Y2gKICAgICAgLy8gICAgdGhlIG90aGVyIG9uZSAob3IgdGhlIG90aGVyIG9uZSBkb2Vzbid0IGhhdmUgb25lKS4KICAgICAgLy8gNCkgVGhpcyByb3V0ZSBoYXMgcGFyYW1ldGVycyB0aGF0IGRvbid0IG1hdGNoIHRoZSBvdGhlci4KICAgICAgaWYgKCFyb3V0ZUluZm8pIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgdmFyIGNvbnRleHRzTWF0Y2ggPSByb3V0ZUluZm8uY29udGV4dCA9PT0gdGhpcy5jb250ZXh0OwogICAgICByZXR1cm4gcm91dGVJbmZvLm5hbWUgIT09IHRoaXMubmFtZSB8fCAnY29udGV4dCcgaW4gdGhpcyAmJiAhY29udGV4dHNNYXRjaCB8fCB0aGlzLmhhc093blByb3BlcnR5KCdwYXJhbXMnKSAmJiAhcGFyYW1zTWF0Y2godGhpcy5wYXJhbXMsIHJvdXRlSW5mby5wYXJhbXMpOwogICAgfTsKCiAgICBfcHJvdG8yLmxvZyA9IGZ1bmN0aW9uIGxvZyh0cmFuc2l0aW9uLCBtZXNzYWdlKSB7CiAgICAgIGlmICh0cmFuc2l0aW9uLmxvZykgewogICAgICAgIHRyYW5zaXRpb24ubG9nKHRoaXMubmFtZSArICc6ICcgKyBtZXNzYWdlKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8yLnVwZGF0ZVJvdXRlID0gZnVuY3Rpb24gdXBkYXRlUm91dGUocm91dGUpIHsKICAgICAgcm91dGUuX2ludGVybmFsTmFtZSA9IHRoaXMubmFtZTsKICAgICAgcmV0dXJuIHRoaXMucm91dGUgPSByb3V0ZTsKICAgIH07CgogICAgX3Byb3RvMi5ydW5CZWZvcmVNb2RlbEhvb2sgPSBmdW5jdGlvbiBydW5CZWZvcmVNb2RlbEhvb2sodHJhbnNpdGlvbikgewogICAgICBpZiAodHJhbnNpdGlvbi50cmlnZ2VyKSB7CiAgICAgICAgdHJhbnNpdGlvbi50cmlnZ2VyKHRydWUsICd3aWxsUmVzb2x2ZU1vZGVsJywgdHJhbnNpdGlvbiwgdGhpcy5yb3V0ZSk7CiAgICAgIH0KCiAgICAgIHZhciByZXN1bHQ7CgogICAgICBpZiAodGhpcy5yb3V0ZSkgewogICAgICAgIGlmICh0aGlzLnJvdXRlLmJlZm9yZU1vZGVsICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJlc3VsdCA9IHRoaXMucm91dGUuYmVmb3JlTW9kZWwodHJhbnNpdGlvbik7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoaXNUcmFuc2l0aW9uKHJlc3VsdCkpIHsKICAgICAgICByZXN1bHQgPSBudWxsOwogICAgICB9CgogICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7CiAgICB9OwoKICAgIF9wcm90bzIucnVuQWZ0ZXJNb2RlbEhvb2sgPSBmdW5jdGlvbiBydW5BZnRlck1vZGVsSG9vayh0cmFuc2l0aW9uLCByZXNvbHZlZE1vZGVsKSB7CiAgICAgIC8vIFN0YXNoIHRoZSByZXNvbHZlZCBtb2RlbCBvbiB0aGUgcGF5bG9hZC4KICAgICAgLy8gVGhpcyBtYWtlcyBpdCBwb3NzaWJsZSBmb3IgdXNlcnMgdG8gc3dhcCBvdXQKICAgICAgLy8gdGhlIHJlc29sdmVkIG1vZGVsIGluIGFmdGVyTW9kZWwuCiAgICAgIHZhciBuYW1lID0gdGhpcy5uYW1lOwogICAgICB0aGlzLnN0YXNoUmVzb2x2ZWRNb2RlbCh0cmFuc2l0aW9uLCByZXNvbHZlZE1vZGVsKTsKICAgICAgdmFyIHJlc3VsdDsKCiAgICAgIGlmICh0aGlzLnJvdXRlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBpZiAodGhpcy5yb3V0ZS5hZnRlck1vZGVsICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJlc3VsdCA9IHRoaXMucm91dGUuYWZ0ZXJNb2RlbChyZXNvbHZlZE1vZGVsLCB0cmFuc2l0aW9uKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJlc3VsdCA9IHByZXBhcmVSZXN1bHQocmVzdWx0KTsKICAgICAgcmV0dXJuIF9yc3ZwLlByb21pc2UucmVzb2x2ZShyZXN1bHQpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIC8vIElnbm9yZSB0aGUgZnVsZmlsbGVkIHZhbHVlIHJldHVybmVkIGZyb20gYWZ0ZXJNb2RlbC4KICAgICAgICAvLyBSZXR1cm4gdGhlIHZhbHVlIHN0YXNoZWQgaW4gcmVzb2x2ZWRNb2RlbHMsIHdoaWNoCiAgICAgICAgLy8gbWlnaHQgaGF2ZSBiZWVuIHN3YXBwZWQgb3V0IGluIGFmdGVyTW9kZWwuCiAgICAgICAgcmV0dXJuIHRyYW5zaXRpb24ucmVzb2x2ZWRNb2RlbHNbbmFtZV07CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8yLmNoZWNrRm9yQWJvcnQgPSBmdW5jdGlvbiBjaGVja0ZvckFib3J0KHNob3VsZENvbnRpbnVlLCB2YWx1ZSkgewogICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZXNvbHZlKHNob3VsZENvbnRpbnVlKCkpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIC8vIFdlIGRvbid0IGNhcmUgYWJvdXQgc2hvdWxkQ29udGludWUncyByZXNvbHZlIHZhbHVlOwogICAgICAgIC8vIHBhc3MgYWxvbmcgdGhlIG9yaWdpbmFsIHZhbHVlIHBhc3NlZCB0byB0aGlzIGZuLgogICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgfSwgbnVsbCk7CiAgICB9OwoKICAgIF9wcm90bzIuc3Rhc2hSZXNvbHZlZE1vZGVsID0gZnVuY3Rpb24gc3Rhc2hSZXNvbHZlZE1vZGVsKHRyYW5zaXRpb24sIHJlc29sdmVkTW9kZWwpIHsKICAgICAgdHJhbnNpdGlvbi5yZXNvbHZlZE1vZGVscyA9IHRyYW5zaXRpb24ucmVzb2x2ZWRNb2RlbHMgfHwge307CiAgICAgIHRyYW5zaXRpb24ucmVzb2x2ZWRNb2RlbHNbdGhpcy5uYW1lXSA9IHJlc29sdmVkTW9kZWw7CiAgICB9OwoKICAgIF9wcm90bzIuZmV0Y2hSb3V0ZSA9IGZ1bmN0aW9uIGZldGNoUm91dGUoKSB7CiAgICAgIHZhciByb3V0ZSA9IHRoaXMucm91dGVyLmdldFJvdXRlKHRoaXMubmFtZSk7CiAgICAgIHJldHVybiB0aGlzLl9wcm9jZXNzUm91dGUocm91dGUpOwogICAgfTsKCiAgICBfcHJvdG8yLl9wcm9jZXNzUm91dGUgPSBmdW5jdGlvbiBfcHJvY2Vzc1JvdXRlKHJvdXRlKSB7CiAgICAgIHZhciBfdGhpczMgPSB0aGlzOwoKICAgICAgLy8gU2V0dXAgYSByb3V0ZVByb21pc2Ugc28gdGhhdCB3ZSBjYW4gd2FpdCBmb3IgYXN5bmNocm9ub3VzbHkgbG9hZGVkIHJvdXRlcwogICAgICB0aGlzLnJvdXRlUHJvbWlzZSA9IF9yc3ZwLlByb21pc2UucmVzb2x2ZShyb3V0ZSk7IC8vIFdhaXQgdW50aWwgdGhlICdyb3V0ZScgcHJvcGVydHkgaGFzIGJlZW4gdXBkYXRlZCB3aGVuIGNoYWluaW5nIHRvIGEgcm91dGUKICAgICAgLy8gdGhhdCBpcyBhIHByb21pc2UKCiAgICAgIGlmIChpc1Byb21pc2Uocm91dGUpKSB7CiAgICAgICAgdGhpcy5yb3V0ZVByb21pc2UgPSB0aGlzLnJvdXRlUHJvbWlzZS50aGVuKGZ1bmN0aW9uIChyKSB7CiAgICAgICAgICByZXR1cm4gX3RoaXMzLnVwZGF0ZVJvdXRlKHIpOwogICAgICAgIH0pOyAvLyBzZXQgdG8gdW5kZWZpbmVkIHRvIGF2b2lkIHJlY3Vyc2l2ZSBsb29wIGluIHRoZSByb3V0ZSBnZXR0ZXIKCiAgICAgICAgcmV0dXJuIHRoaXMucm91dGUgPSB1bmRlZmluZWQ7CiAgICAgIH0gZWxzZSBpZiAocm91dGUpIHsKICAgICAgICByZXR1cm4gdGhpcy51cGRhdGVSb3V0ZShyb3V0ZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9OwoKICAgICgwLCBfZW1iZXJCYWJlbC5jcmVhdGVDbGFzcykoSW50ZXJuYWxSb3V0ZUluZm8sIFt7CiAgICAgIGtleTogInJvdXRlIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgLy8gX3JvdXRlIGNvdWxkIGJlIHNldCB0byBlaXRoZXIgYSByb3V0ZSBvYmplY3Qgb3IgdW5kZWZpbmVkLCBzbyB3ZQogICAgICAgIC8vIGNvbXBhcmUgYWdhaW5zdCBudWxsIHRvIGtub3cgd2hlbiBpdCdzIGJlZW4gc2V0CiAgICAgICAgaWYgKHRoaXMuX3JvdXRlICE9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fcm91dGU7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5mZXRjaFJvdXRlKCk7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHJvdXRlKSB7CiAgICAgICAgdGhpcy5fcm91dGUgPSByb3V0ZTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJyb3V0ZVByb21pc2UiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fcm91dGVQcm9taXNlKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fcm91dGVQcm9taXNlOwogICAgICAgIH0KCiAgICAgICAgdGhpcy5mZXRjaFJvdXRlKCk7CiAgICAgICAgcmV0dXJuIHRoaXMuX3JvdXRlUHJvbWlzZTsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQocm91dGVQcm9taXNlKSB7CiAgICAgICAgdGhpcy5fcm91dGVQcm9taXNlID0gcm91dGVQcm9taXNlOwogICAgICB9CiAgICB9XSk7CiAgICByZXR1cm4gSW50ZXJuYWxSb3V0ZUluZm87CiAgfSgpOwoKICBfZXhwb3J0cy5JbnRlcm5hbFJvdXRlSW5mbyA9IEludGVybmFsUm91dGVJbmZvOwoKICB2YXIgUmVzb2x2ZWRSb3V0ZUluZm8gPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0ludGVybmFsUm91dGVJbmZvKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUmVzb2x2ZWRSb3V0ZUluZm8sIF9JbnRlcm5hbFJvdXRlSW5mbyk7CgogICAgZnVuY3Rpb24gUmVzb2x2ZWRSb3V0ZUluZm8ocm91dGVyLCBuYW1lLCBwYXJhbU5hbWVzLCBwYXJhbXMsIHJvdXRlLCBjb250ZXh0KSB7CiAgICAgIHZhciBfdGhpczQ7CgogICAgICBfdGhpczQgPSBfSW50ZXJuYWxSb3V0ZUluZm8uY2FsbCh0aGlzLCByb3V0ZXIsIG5hbWUsIHBhcmFtTmFtZXMsIHJvdXRlKSB8fCB0aGlzOwogICAgICBfdGhpczQucGFyYW1zID0gcGFyYW1zOwogICAgICBfdGhpczQuaXNSZXNvbHZlZCA9IHRydWU7CiAgICAgIF90aGlzNC5jb250ZXh0ID0gY29udGV4dDsKICAgICAgcmV0dXJuIF90aGlzNDsKICAgIH0KCiAgICB2YXIgX3Byb3RvMyA9IFJlc29sdmVkUm91dGVJbmZvLnByb3RvdHlwZTsKCiAgICBfcHJvdG8zLnJlc29sdmUgPSBmdW5jdGlvbiByZXNvbHZlKF9zaG91bGRDb250aW51ZSwgdHJhbnNpdGlvbikgewogICAgICAvLyBBIFJlc29sdmVkUm91dGVJbmZvIGp1c3QgcmVzb2x2ZWQgd2l0aCBpdHNlbGYuCiAgICAgIGlmICh0cmFuc2l0aW9uICYmIHRyYW5zaXRpb24ucmVzb2x2ZWRNb2RlbHMpIHsKICAgICAgICB0cmFuc2l0aW9uLnJlc29sdmVkTW9kZWxzW3RoaXMubmFtZV0gPSB0aGlzLmNvbnRleHQ7CiAgICAgIH0KCiAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlc29sdmUodGhpcyk7CiAgICB9OwoKICAgIHJldHVybiBSZXNvbHZlZFJvdXRlSW5mbzsKICB9KEludGVybmFsUm91dGVJbmZvKTsKCiAgdmFyIFVucmVzb2x2ZWRSb3V0ZUluZm9CeVBhcmFtID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9JbnRlcm5hbFJvdXRlSW5mbzIpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShVbnJlc29sdmVkUm91dGVJbmZvQnlQYXJhbSwgX0ludGVybmFsUm91dGVJbmZvMik7CgogICAgZnVuY3Rpb24gVW5yZXNvbHZlZFJvdXRlSW5mb0J5UGFyYW0ocm91dGVyLCBuYW1lLCBwYXJhbU5hbWVzLCBwYXJhbXMsIHJvdXRlKSB7CiAgICAgIHZhciBfdGhpczU7CgogICAgICBfdGhpczUgPSBfSW50ZXJuYWxSb3V0ZUluZm8yLmNhbGwodGhpcywgcm91dGVyLCBuYW1lLCBwYXJhbU5hbWVzLCByb3V0ZSkgfHwgdGhpczsKICAgICAgX3RoaXM1LnBhcmFtcyA9IHt9OwogICAgICBfdGhpczUucGFyYW1zID0gcGFyYW1zOwogICAgICByZXR1cm4gX3RoaXM1OwogICAgfQoKICAgIHZhciBfcHJvdG80ID0gVW5yZXNvbHZlZFJvdXRlSW5mb0J5UGFyYW0ucHJvdG90eXBlOwoKICAgIF9wcm90bzQuZ2V0TW9kZWwgPSBmdW5jdGlvbiBnZXRNb2RlbCh0cmFuc2l0aW9uKSB7CiAgICAgIHZhciBmdWxsUGFyYW1zID0gdGhpcy5wYXJhbXM7CgogICAgICBpZiAodHJhbnNpdGlvbiAmJiB0cmFuc2l0aW9uW1FVRVJZX1BBUkFNU19TWU1CT0xdKSB7CiAgICAgICAgZnVsbFBhcmFtcyA9IHt9OwogICAgICAgIG1lcmdlKGZ1bGxQYXJhbXMsIHRoaXMucGFyYW1zKTsKICAgICAgICBmdWxsUGFyYW1zLnF1ZXJ5UGFyYW1zID0gdHJhbnNpdGlvbltRVUVSWV9QQVJBTVNfU1lNQk9MXTsKICAgICAgfQoKICAgICAgdmFyIHJvdXRlID0gdGhpcy5yb3V0ZTsKICAgICAgdmFyIHJlc3VsdCA9IHVuZGVmaW5lZDsKCiAgICAgIGlmIChyb3V0ZS5kZXNlcmlhbGl6ZSkgewogICAgICAgIHJlc3VsdCA9IHJvdXRlLmRlc2VyaWFsaXplKGZ1bGxQYXJhbXMsIHRyYW5zaXRpb24pOwogICAgICB9IGVsc2UgaWYgKHJvdXRlLm1vZGVsKSB7CiAgICAgICAgcmVzdWx0ID0gcm91dGUubW9kZWwoZnVsbFBhcmFtcywgdHJhbnNpdGlvbik7CiAgICAgIH0KCiAgICAgIGlmIChyZXN1bHQgJiYgaXNUcmFuc2l0aW9uKHJlc3VsdCkpIHsKICAgICAgICByZXN1bHQgPSB1bmRlZmluZWQ7CiAgICAgIH0KCiAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlc29sdmUocmVzdWx0KTsKICAgIH07CgogICAgcmV0dXJuIFVucmVzb2x2ZWRSb3V0ZUluZm9CeVBhcmFtOwogIH0oSW50ZXJuYWxSb3V0ZUluZm8pOwoKICB2YXIgVW5yZXNvbHZlZFJvdXRlSW5mb0J5T2JqZWN0ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9JbnRlcm5hbFJvdXRlSW5mbzMpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShVbnJlc29sdmVkUm91dGVJbmZvQnlPYmplY3QsIF9JbnRlcm5hbFJvdXRlSW5mbzMpOwoKICAgIGZ1bmN0aW9uIFVucmVzb2x2ZWRSb3V0ZUluZm9CeU9iamVjdChyb3V0ZXIsIG5hbWUsIHBhcmFtTmFtZXMsIGNvbnRleHQpIHsKICAgICAgdmFyIF90aGlzNjsKCiAgICAgIF90aGlzNiA9IF9JbnRlcm5hbFJvdXRlSW5mbzMuY2FsbCh0aGlzLCByb3V0ZXIsIG5hbWUsIHBhcmFtTmFtZXMpIHx8IHRoaXM7CiAgICAgIF90aGlzNi5jb250ZXh0ID0gY29udGV4dDsKICAgICAgX3RoaXM2LnNlcmlhbGl6ZXIgPSBfdGhpczYucm91dGVyLmdldFNlcmlhbGl6ZXIobmFtZSk7CiAgICAgIHJldHVybiBfdGhpczY7CiAgICB9CgogICAgdmFyIF9wcm90bzUgPSBVbnJlc29sdmVkUm91dGVJbmZvQnlPYmplY3QucHJvdG90eXBlOwoKICAgIF9wcm90bzUuZ2V0TW9kZWwgPSBmdW5jdGlvbiBnZXRNb2RlbCh0cmFuc2l0aW9uKSB7CiAgICAgIGlmICh0aGlzLnJvdXRlci5sb2cgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHRoaXMucm91dGVyLmxvZyh0aGlzLm5hbWUgKyAnOiByZXNvbHZpbmcgcHJvdmlkZWQgbW9kZWwnKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9JbnRlcm5hbFJvdXRlSW5mbzMucHJvdG90eXBlLmdldE1vZGVsLmNhbGwodGhpcywgdHJhbnNpdGlvbik7CiAgICB9CiAgICAvKioKICAgICAgQHByaXZhdGUKICAgICAgICAgU2VyaWFsaXplcyBhIHJvdXRlIHVzaW5nIGl0cyBjdXN0b20gYHNlcmlhbGl6ZWAgbWV0aG9kIG9yCiAgICAgIGJ5IGEgZGVmYXVsdCB0aGF0IGxvb2tzIHVwIHRoZSBleHBlY3RlZCBwcm9wZXJ0eSBuYW1lIGZyb20KICAgICAgdGhlIGR5bmFtaWMgc2VnbWVudC4KICAgICAgICAgQHBhcmFtIHtPYmplY3R9IG1vZGVsIHRoZSBtb2RlbCB0byBiZSBzZXJpYWxpemVkIGZvciB0aGlzIHJvdXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90bzUuc2VyaWFsaXplID0gZnVuY3Rpb24gc2VyaWFsaXplKG1vZGVsKSB7CiAgICAgIHZhciBwYXJhbU5hbWVzID0gdGhpcy5wYXJhbU5hbWVzLAogICAgICAgICAgY29udGV4dCA9IHRoaXMuY29udGV4dDsKCiAgICAgIGlmICghbW9kZWwpIHsKICAgICAgICBtb2RlbCA9IGNvbnRleHQ7CiAgICAgIH0KCiAgICAgIHZhciBvYmplY3QgPSB7fTsKCiAgICAgIGlmIChpc1BhcmFtKG1vZGVsKSkgewogICAgICAgIG9iamVjdFtwYXJhbU5hbWVzWzBdXSA9IG1vZGVsOwogICAgICAgIHJldHVybiBvYmplY3Q7CiAgICAgIH0gLy8gVXNlIGN1c3RvbSBzZXJpYWxpemUgaWYgaXQgZXhpc3RzLgoKCiAgICAgIGlmICh0aGlzLnNlcmlhbGl6ZXIpIHsKICAgICAgICAvLyBpbnZva2UgdGhpcy5zZXJpYWxpemVyIHVuYm91bmQgKGdldFNlcmlhbGl6ZXIgcmV0dXJucyBhIHN0YXRlbGVzcyBmdW5jdGlvbikKICAgICAgICByZXR1cm4gdGhpcy5zZXJpYWxpemVyLmNhbGwobnVsbCwgbW9kZWwsIHBhcmFtTmFtZXMpOwogICAgICB9IGVsc2UgaWYgKHRoaXMucm91dGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGlmICh0aGlzLnJvdXRlLnNlcmlhbGl6ZSkgewogICAgICAgICAgcmV0dXJuIHRoaXMucm91dGUuc2VyaWFsaXplKG1vZGVsLCBwYXJhbU5hbWVzKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChwYXJhbU5hbWVzLmxlbmd0aCAhPT0gMSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIG5hbWUgPSBwYXJhbU5hbWVzWzBdOwoKICAgICAgaWYgKC9faWQkLy50ZXN0KG5hbWUpKSB7CiAgICAgICAgb2JqZWN0W25hbWVdID0gbW9kZWwuaWQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgb2JqZWN0W25hbWVdID0gbW9kZWw7CiAgICAgIH0KCiAgICAgIHJldHVybiBvYmplY3Q7CiAgICB9OwoKICAgIHJldHVybiBVbnJlc29sdmVkUm91dGVJbmZvQnlPYmplY3Q7CiAgfShJbnRlcm5hbFJvdXRlSW5mbyk7CgogIGZ1bmN0aW9uIHBhcmFtc01hdGNoKGEsIGIpIHsKICAgIGlmICghYSAhPT0gIWIpIHsKICAgICAgLy8gT25seSBvbmUgaXMgbnVsbC4KICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIGlmICghYSkgewogICAgICAvLyBCb3RoIG11c3QgYmUgbnVsbC4KICAgICAgcmV0dXJuIHRydWU7CiAgICB9IC8vIE5vdGU6IHRoaXMgYXNzdW1lcyB0aGF0IGJvdGggcGFyYW1zIGhhdmUgdGhlIHNhbWUKICAgIC8vIG51bWJlciBvZiBrZXlzLCBidXQgc2luY2Ugd2UncmUgY29tcGFyaW5nIHRoZQogICAgLy8gc2FtZSByb3V0ZXMsIHRoZXkgc2hvdWxkLgoKCiAgICBmb3IgKHZhciBrIGluIGEpIHsKICAgICAgaWYgKGEuaGFzT3duUHJvcGVydHkoaykgJiYgYVtrXSAhPT0gYltrXSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiB0cnVlOwogIH0KCiAgdmFyIFRyYW5zaXRpb25JbnRlbnQgPSBmdW5jdGlvbiBUcmFuc2l0aW9uSW50ZW50KHJvdXRlciwgZGF0YSkgewogICAgaWYgKGRhdGEgPT09IHZvaWQgMCkgewogICAgICBkYXRhID0ge307CiAgICB9CgogICAgdGhpcy5yb3V0ZXIgPSByb3V0ZXI7CiAgICB0aGlzLmRhdGEgPSBkYXRhOwogIH07CgogIHZhciBUcmFuc2l0aW9uU3RhdGUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBUcmFuc2l0aW9uU3RhdGUoKSB7CiAgICAgIHRoaXMucm91dGVJbmZvcyA9IFtdOwogICAgICB0aGlzLnF1ZXJ5UGFyYW1zID0ge307CiAgICAgIHRoaXMucGFyYW1zID0ge307CiAgICB9CgogICAgdmFyIF9wcm90bzYgPSBUcmFuc2l0aW9uU3RhdGUucHJvdG90eXBlOwoKICAgIF9wcm90bzYucHJvbWlzZUxhYmVsID0gZnVuY3Rpb24gcHJvbWlzZUxhYmVsKGxhYmVsKSB7CiAgICAgIHZhciB0YXJnZXROYW1lID0gJyc7CiAgICAgIGZvckVhY2godGhpcy5yb3V0ZUluZm9zLCBmdW5jdGlvbiAocm91dGVJbmZvKSB7CiAgICAgICAgaWYgKHRhcmdldE5hbWUgIT09ICcnKSB7CiAgICAgICAgICB0YXJnZXROYW1lICs9ICcuJzsKICAgICAgICB9CgogICAgICAgIHRhcmdldE5hbWUgKz0gcm91dGVJbmZvLm5hbWU7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0pOwogICAgICByZXR1cm4gX3Byb21pc2VMYWJlbCgiJyIgKyB0YXJnZXROYW1lICsgIic6ICIgKyBsYWJlbCk7CiAgICB9OwoKICAgIF9wcm90bzYucmVzb2x2ZSA9IGZ1bmN0aW9uIHJlc29sdmUoc2hvdWxkQ29udGludWUsIHRyYW5zaXRpb24pIHsKICAgICAgLy8gRmlyc3QsIGNhbGN1bGF0ZSBwYXJhbXMgZm9yIHRoaXMgc3RhdGUuIFRoaXMgaXMgdXNlZnVsCiAgICAgIC8vIGluZm9ybWF0aW9uIHRvIHByb3ZpZGUgdG8gdGhlIHZhcmlvdXMgcm91dGUgaG9va3MuCiAgICAgIHZhciBwYXJhbXMgPSB0aGlzLnBhcmFtczsKICAgICAgZm9yRWFjaCh0aGlzLnJvdXRlSW5mb3MsIGZ1bmN0aW9uIChyb3V0ZUluZm8pIHsKICAgICAgICBwYXJhbXNbcm91dGVJbmZvLm5hbWVdID0gcm91dGVJbmZvLnBhcmFtcyB8fCB7fTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfSk7CiAgICAgIHRyYW5zaXRpb24ucmVzb2x2ZUluZGV4ID0gMDsKICAgICAgdmFyIGN1cnJlbnRTdGF0ZSA9IHRoaXM7CiAgICAgIHZhciB3YXNBYm9ydGVkID0gZmFsc2U7IC8vIFRoZSBwcmVsdWRlIFJTVlAucmVzb2x2ZSgpIGFzeW5jcyB1cyBpbnRvIHRoZSBwcm9taXNlIGxhbmQuCgogICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZXNvbHZlKG51bGwsIHRoaXMucHJvbWlzZUxhYmVsKCdTdGFydCB0cmFuc2l0aW9uJykpLnRoZW4ocmVzb2x2ZU9uZVJvdXRlSW5mbywgbnVsbCwgdGhpcy5wcm9taXNlTGFiZWwoJ1Jlc29sdmUgcm91dGUnKSkuY2F0Y2goaGFuZGxlRXJyb3IsIHRoaXMucHJvbWlzZUxhYmVsKCdIYW5kbGUgZXJyb3InKSk7CgogICAgICBmdW5jdGlvbiBpbm5lclNob3VsZENvbnRpbnVlKCkgewogICAgICAgIHJldHVybiBfcnN2cC5Qcm9taXNlLnJlc29sdmUoc2hvdWxkQ29udGludWUoKSwgY3VycmVudFN0YXRlLnByb21pc2VMYWJlbCgnQ2hlY2sgaWYgc2hvdWxkIGNvbnRpbnVlJykpLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgIC8vIFdlIGRpc3Rpbmd1aXNoIGJldHdlZW4gZXJyb3JzIHRoYXQgb2NjdXJyZWQKICAgICAgICAgIC8vIGR1cmluZyByZXNvbHV0aW9uIChlLmcuIGJlZm9yZSJNb2RlbC9tb2RlbC9hZnRlck1vZGVsKSwKICAgICAgICAgIC8vIGFuZCBhYm9ydHMgZHVlIHRvIGEgcmVqZWN0aW5nIHByb21pc2UgZnJvbSBzaG91bGRDb250aW51ZSgpLgogICAgICAgICAgd2FzQWJvcnRlZCA9IHRydWU7CiAgICAgICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZWplY3QocmVhc29uKTsKICAgICAgICB9LCBjdXJyZW50U3RhdGUucHJvbWlzZUxhYmVsKCdIYW5kbGUgYWJvcnQnKSk7CiAgICAgIH0KCiAgICAgIGZ1bmN0aW9uIGhhbmRsZUVycm9yKGVycm9yKSB7CiAgICAgICAgLy8gVGhpcyBpcyB0aGUgb25seSBwb3NzaWJsZQogICAgICAgIC8vIHJlamVjdCB2YWx1ZSBvZiBUcmFuc2l0aW9uU3RhdGUjcmVzb2x2ZQogICAgICAgIHZhciByb3V0ZUluZm9zID0gY3VycmVudFN0YXRlLnJvdXRlSW5mb3M7CiAgICAgICAgdmFyIGVycm9ySGFuZGxlckluZGV4ID0gdHJhbnNpdGlvbi5yZXNvbHZlSW5kZXggPj0gcm91dGVJbmZvcy5sZW5ndGggPyByb3V0ZUluZm9zLmxlbmd0aCAtIDEgOiB0cmFuc2l0aW9uLnJlc29sdmVJbmRleDsKICAgICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZWplY3QobmV3IFRyYW5zaXRpb25FcnJvcihlcnJvciwgY3VycmVudFN0YXRlLnJvdXRlSW5mb3NbZXJyb3JIYW5kbGVySW5kZXhdLnJvdXRlLCB3YXNBYm9ydGVkLCBjdXJyZW50U3RhdGUpKTsKICAgICAgfQoKICAgICAgZnVuY3Rpb24gcHJvY2VlZChyZXNvbHZlZFJvdXRlSW5mbykgewogICAgICAgIHZhciB3YXNBbHJlYWR5UmVzb2x2ZWQgPSBjdXJyZW50U3RhdGUucm91dGVJbmZvc1t0cmFuc2l0aW9uLnJlc29sdmVJbmRleF0uaXNSZXNvbHZlZDsgLy8gU3dhcCB0aGUgcHJldmlvdXNseSB1bnJlc29sdmVkIHJvdXRlSW5mbyB3aXRoCiAgICAgICAgLy8gdGhlIHJlc29sdmVkIHJvdXRlSW5mbwoKICAgICAgICBjdXJyZW50U3RhdGUucm91dGVJbmZvc1t0cmFuc2l0aW9uLnJlc29sdmVJbmRleCsrXSA9IHJlc29sdmVkUm91dGVJbmZvOwoKICAgICAgICBpZiAoIXdhc0FscmVhZHlSZXNvbHZlZCkgewogICAgICAgICAgLy8gQ2FsbCB0aGUgcmVkaXJlY3QgaG9vay4gVGhlIHJlYXNvbiB3ZSBjYWxsIGl0IGhlcmUKICAgICAgICAgIC8vIHZzLiBhZnRlck1vZGVsIGlzIHNvIHRoYXQgcmVkaXJlY3RzIGludG8gY2hpbGQKICAgICAgICAgIC8vIHJvdXRlcyBkb24ndCByZS1ydW4gdGhlIG1vZGVsIGhvb2tzIGZvciB0aGlzCiAgICAgICAgICAvLyBhbHJlYWR5LXJlc29sdmVkIHJvdXRlLgogICAgICAgICAgdmFyIHJvdXRlID0gcmVzb2x2ZWRSb3V0ZUluZm8ucm91dGU7CgogICAgICAgICAgaWYgKHJvdXRlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgaWYgKHJvdXRlLnJlZGlyZWN0KSB7CiAgICAgICAgICAgICAgcm91dGUucmVkaXJlY3QocmVzb2x2ZWRSb3V0ZUluZm8uY29udGV4dCwgdHJhbnNpdGlvbik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IC8vIFByb2NlZWQgYWZ0ZXIgZW5zdXJpbmcgdGhhdCB0aGUgcmVkaXJlY3QgaG9vawogICAgICAgIC8vIGRpZG4ndCBhYm9ydCB0aGlzIHRyYW5zaXRpb24gYnkgdHJhbnNpdGlvbmluZyBlbHNld2hlcmUuCgoKICAgICAgICByZXR1cm4gaW5uZXJTaG91bGRDb250aW51ZSgpLnRoZW4ocmVzb2x2ZU9uZVJvdXRlSW5mbywgbnVsbCwgY3VycmVudFN0YXRlLnByb21pc2VMYWJlbCgnUmVzb2x2ZSByb3V0ZScpKTsKICAgICAgfQoKICAgICAgZnVuY3Rpb24gcmVzb2x2ZU9uZVJvdXRlSW5mbygpIHsKICAgICAgICBpZiAodHJhbnNpdGlvbi5yZXNvbHZlSW5kZXggPT09IGN1cnJlbnRTdGF0ZS5yb3V0ZUluZm9zLmxlbmd0aCkgewogICAgICAgICAgLy8gVGhpcyBpcyBpcyB0aGUgb25seSBwb3NzaWJsZQogICAgICAgICAgLy8gZnVsZmlsbCB2YWx1ZSBvZiBUcmFuc2l0aW9uU3RhdGUjcmVzb2x2ZQogICAgICAgICAgcmV0dXJuIGN1cnJlbnRTdGF0ZTsKICAgICAgICB9CgogICAgICAgIHZhciByb3V0ZUluZm8gPSBjdXJyZW50U3RhdGUucm91dGVJbmZvc1t0cmFuc2l0aW9uLnJlc29sdmVJbmRleF07CiAgICAgICAgcmV0dXJuIHJvdXRlSW5mby5yZXNvbHZlKGlubmVyU2hvdWxkQ29udGludWUsIHRyYW5zaXRpb24pLnRoZW4ocHJvY2VlZCwgbnVsbCwgY3VycmVudFN0YXRlLnByb21pc2VMYWJlbCgnUHJvY2VlZCcpKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gVHJhbnNpdGlvblN0YXRlOwogIH0oKTsKCiAgX2V4cG9ydHMuVHJhbnNpdGlvblN0YXRlID0gVHJhbnNpdGlvblN0YXRlOwoKICB2YXIgVHJhbnNpdGlvbkVycm9yID0gZnVuY3Rpb24gVHJhbnNpdGlvbkVycm9yKGVycm9yLCByb3V0ZSwgd2FzQWJvcnRlZCwgc3RhdGUpIHsKICAgIHRoaXMuZXJyb3IgPSBlcnJvcjsKICAgIHRoaXMucm91dGUgPSByb3V0ZTsKICAgIHRoaXMud2FzQWJvcnRlZCA9IHdhc0Fib3J0ZWQ7CiAgICB0aGlzLnN0YXRlID0gc3RhdGU7CiAgfTsKCiAgX2V4cG9ydHMuVHJhbnNpdGlvbkVycm9yID0gVHJhbnNpdGlvbkVycm9yOwoKICB2YXIgTmFtZWRUcmFuc2l0aW9uSW50ZW50ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9UcmFuc2l0aW9uSW50ZW50KSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoTmFtZWRUcmFuc2l0aW9uSW50ZW50LCBfVHJhbnNpdGlvbkludGVudCk7CgogICAgZnVuY3Rpb24gTmFtZWRUcmFuc2l0aW9uSW50ZW50KHJvdXRlciwgbmFtZSwgcGl2b3RIYW5kbGVyLCBjb250ZXh0cywgcXVlcnlQYXJhbXMsIGRhdGEpIHsKICAgICAgdmFyIF90aGlzNzsKCiAgICAgIGlmIChjb250ZXh0cyA9PT0gdm9pZCAwKSB7CiAgICAgICAgY29udGV4dHMgPSBbXTsKICAgICAgfQoKICAgICAgaWYgKHF1ZXJ5UGFyYW1zID09PSB2b2lkIDApIHsKICAgICAgICBxdWVyeVBhcmFtcyA9IHt9OwogICAgICB9CgogICAgICBfdGhpczcgPSBfVHJhbnNpdGlvbkludGVudC5jYWxsKHRoaXMsIHJvdXRlciwgZGF0YSkgfHwgdGhpczsKICAgICAgX3RoaXM3LnByZVRyYW5zaXRpb25TdGF0ZSA9IHVuZGVmaW5lZDsKICAgICAgX3RoaXM3Lm5hbWUgPSBuYW1lOwogICAgICBfdGhpczcucGl2b3RIYW5kbGVyID0gcGl2b3RIYW5kbGVyOwogICAgICBfdGhpczcuY29udGV4dHMgPSBjb250ZXh0czsKICAgICAgX3RoaXM3LnF1ZXJ5UGFyYW1zID0gcXVlcnlQYXJhbXM7CiAgICAgIHJldHVybiBfdGhpczc7CiAgICB9CgogICAgdmFyIF9wcm90bzcgPSBOYW1lZFRyYW5zaXRpb25JbnRlbnQucHJvdG90eXBlOwoKICAgIF9wcm90bzcuYXBwbHlUb1N0YXRlID0gZnVuY3Rpb24gYXBwbHlUb1N0YXRlKG9sZFN0YXRlLCBpc0ludGVybWVkaWF0ZSkgewogICAgICAvLyBUT0RPOiBXVEYgZml4IG1lCiAgICAgIHZhciBwYXJ0aXRpb25lZEFyZ3MgPSBleHRyYWN0UXVlcnlQYXJhbXMoW3RoaXMubmFtZV0uY29uY2F0KHRoaXMuY29udGV4dHMpKSwKICAgICAgICAgIHB1cmVBcmdzID0gcGFydGl0aW9uZWRBcmdzWzBdLAogICAgICAgICAgaGFuZGxlcnMgPSB0aGlzLnJvdXRlci5yZWNvZ25pemVyLmhhbmRsZXJzRm9yKHB1cmVBcmdzWzBdKTsKICAgICAgdmFyIHRhcmdldFJvdXRlTmFtZSA9IGhhbmRsZXJzW2hhbmRsZXJzLmxlbmd0aCAtIDFdLmhhbmRsZXI7CiAgICAgIHJldHVybiB0aGlzLmFwcGx5VG9IYW5kbGVycyhvbGRTdGF0ZSwgaGFuZGxlcnMsIHRhcmdldFJvdXRlTmFtZSwgaXNJbnRlcm1lZGlhdGUsIGZhbHNlKTsKICAgIH07CgogICAgX3Byb3RvNy5hcHBseVRvSGFuZGxlcnMgPSBmdW5jdGlvbiBhcHBseVRvSGFuZGxlcnMob2xkU3RhdGUsIHBhcnNlZEhhbmRsZXJzLCB0YXJnZXRSb3V0ZU5hbWUsIGlzSW50ZXJtZWRpYXRlLCBjaGVja2luZ0lmQWN0aXZlKSB7CiAgICAgIHZhciBpLCBsZW47CiAgICAgIHZhciBuZXdTdGF0ZSA9IG5ldyBUcmFuc2l0aW9uU3RhdGUoKTsKICAgICAgdmFyIG9iamVjdHMgPSB0aGlzLmNvbnRleHRzLnNsaWNlKDApOwogICAgICB2YXIgaW52YWxpZGF0ZUluZGV4ID0gcGFyc2VkSGFuZGxlcnMubGVuZ3RoOyAvLyBQaXZvdCBoYW5kbGVycyBhcmUgcHJvdmlkZWQgZm9yIHJlZnJlc2ggdHJhbnNpdGlvbnMKCiAgICAgIGlmICh0aGlzLnBpdm90SGFuZGxlcikgewogICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IHBhcnNlZEhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgICAgICBpZiAocGFyc2VkSGFuZGxlcnNbaV0uaGFuZGxlciA9PT0gdGhpcy5waXZvdEhhbmRsZXIuX2ludGVybmFsTmFtZSkgewogICAgICAgICAgICBpbnZhbGlkYXRlSW5kZXggPSBpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGZvciAoaSA9IHBhcnNlZEhhbmRsZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgdmFyIHJlc3VsdCA9IHBhcnNlZEhhbmRsZXJzW2ldOwogICAgICAgIHZhciBuYW1lID0gcmVzdWx0LmhhbmRsZXI7CiAgICAgICAgdmFyIG9sZEhhbmRsZXJJbmZvID0gb2xkU3RhdGUucm91dGVJbmZvc1tpXTsKICAgICAgICB2YXIgbmV3SGFuZGxlckluZm8gPSBudWxsOwoKICAgICAgICBpZiAocmVzdWx0Lm5hbWVzLmxlbmd0aCA+IDApIHsKICAgICAgICAgIGlmIChpID49IGludmFsaWRhdGVJbmRleCkgewogICAgICAgICAgICBuZXdIYW5kbGVySW5mbyA9IHRoaXMuY3JlYXRlUGFyYW1IYW5kbGVySW5mbyhuYW1lLCByZXN1bHQubmFtZXMsIG9iamVjdHMsIG9sZEhhbmRsZXJJbmZvKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG5ld0hhbmRsZXJJbmZvID0gdGhpcy5nZXRIYW5kbGVySW5mb0ZvckR5bmFtaWNTZWdtZW50KG5hbWUsIHJlc3VsdC5uYW1lcywgb2JqZWN0cywgb2xkSGFuZGxlckluZm8sIHRhcmdldFJvdXRlTmFtZSwgaSk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vIFRoaXMgcm91dGUgaGFzIG5vIGR5bmFtaWMgc2VnbWVudC4KICAgICAgICAgIC8vIFRoZXJlZm9yZSB0cmVhdCBhcyBhIHBhcmFtLWJhc2VkIGhhbmRsZXJJbmZvCiAgICAgICAgICAvLyB3aXRoIGVtcHR5IHBhcmFtcy4gVGhpcyB3aWxsIGNhdXNlIHRoZSBgbW9kZWxgCiAgICAgICAgICAvLyBob29rIHRvIGJlIGNhbGxlZCB3aXRoIGVtcHR5IHBhcmFtcywgd2hpY2ggaXMgZGVzaXJhYmxlLgogICAgICAgICAgbmV3SGFuZGxlckluZm8gPSB0aGlzLmNyZWF0ZVBhcmFtSGFuZGxlckluZm8obmFtZSwgcmVzdWx0Lm5hbWVzLCBvYmplY3RzLCBvbGRIYW5kbGVySW5mbyk7CiAgICAgICAgfQoKICAgICAgICBpZiAoY2hlY2tpbmdJZkFjdGl2ZSkgewogICAgICAgICAgLy8gSWYgd2UncmUgcGVyZm9ybWluZyBhbiBpc0FjdGl2ZSBjaGVjaywgd2Ugd2FudCB0bwogICAgICAgICAgLy8gc2VyaWFsaXplIFVSTCBwYXJhbXMgd2l0aCB0aGUgcHJvdmlkZWQgY29udGV4dCwgYnV0CiAgICAgICAgICAvLyBpZ25vcmUgbWlzbWF0Y2hlcyBiZXR3ZWVuIG9sZCBhbmQgbmV3IGNvbnRleHQuCiAgICAgICAgICBuZXdIYW5kbGVySW5mbyA9IG5ld0hhbmRsZXJJbmZvLmJlY29tZVJlc29sdmVkKG51bGwsIG5ld0hhbmRsZXJJbmZvLmNvbnRleHQpOwogICAgICAgICAgdmFyIG9sZENvbnRleHQgPSBvbGRIYW5kbGVySW5mbyAmJiBvbGRIYW5kbGVySW5mby5jb250ZXh0OwoKICAgICAgICAgIGlmIChyZXN1bHQubmFtZXMubGVuZ3RoID4gMCAmJiBvbGRIYW5kbGVySW5mby5jb250ZXh0ICE9PSB1bmRlZmluZWQgJiYgbmV3SGFuZGxlckluZm8uY29udGV4dCA9PT0gb2xkQ29udGV4dCkgewogICAgICAgICAgICAvLyBJZiBjb250ZXh0cyBtYXRjaCBpbiBpc0FjdGl2ZSB0ZXN0LCBhc3N1bWUgcGFyYW1zIGFsc28gbWF0Y2guCiAgICAgICAgICAgIC8vIFRoaXMgYWxsb3dzIGZvciBmbGV4aWJpbGl0eSBpbiBub3QgcmVxdWlyaW5nIHRoYXQgZXZlcnkgbGFzdAogICAgICAgICAgICAvLyBoYW5kbGVyIHByb3ZpZGUgYSBgc2VyaWFsaXplYCBtZXRob2QKICAgICAgICAgICAgbmV3SGFuZGxlckluZm8ucGFyYW1zID0gb2xkSGFuZGxlckluZm8gJiYgb2xkSGFuZGxlckluZm8ucGFyYW1zOwogICAgICAgICAgfQoKICAgICAgICAgIG5ld0hhbmRsZXJJbmZvLmNvbnRleHQgPSBvbGRDb250ZXh0OwogICAgICAgIH0KCiAgICAgICAgdmFyIGhhbmRsZXJUb1VzZSA9IG9sZEhhbmRsZXJJbmZvOwoKICAgICAgICBpZiAoaSA+PSBpbnZhbGlkYXRlSW5kZXggfHwgbmV3SGFuZGxlckluZm8uc2hvdWxkU3VwZXJjZWRlKG9sZEhhbmRsZXJJbmZvKSkgewogICAgICAgICAgaW52YWxpZGF0ZUluZGV4ID0gTWF0aC5taW4oaSwgaW52YWxpZGF0ZUluZGV4KTsKICAgICAgICAgIGhhbmRsZXJUb1VzZSA9IG5ld0hhbmRsZXJJbmZvOwogICAgICAgIH0KCiAgICAgICAgaWYgKGlzSW50ZXJtZWRpYXRlICYmICFjaGVja2luZ0lmQWN0aXZlKSB7CiAgICAgICAgICBoYW5kbGVyVG9Vc2UgPSBoYW5kbGVyVG9Vc2UuYmVjb21lUmVzb2x2ZWQobnVsbCwgaGFuZGxlclRvVXNlLmNvbnRleHQpOwogICAgICAgIH0KCiAgICAgICAgbmV3U3RhdGUucm91dGVJbmZvcy51bnNoaWZ0KGhhbmRsZXJUb1VzZSk7CiAgICAgIH0KCiAgICAgIGlmIChvYmplY3RzLmxlbmd0aCA+IDApIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vcmUgY29udGV4dCBvYmplY3RzIHdlcmUgcGFzc2VkIHRoYW4gdGhlcmUgYXJlIGR5bmFtaWMgc2VnbWVudHMgZm9yIHRoZSByb3V0ZTogJyArIHRhcmdldFJvdXRlTmFtZSk7CiAgICAgIH0KCiAgICAgIGlmICghaXNJbnRlcm1lZGlhdGUpIHsKICAgICAgICB0aGlzLmludmFsaWRhdGVDaGlsZHJlbihuZXdTdGF0ZS5yb3V0ZUluZm9zLCBpbnZhbGlkYXRlSW5kZXgpOwogICAgICB9CgogICAgICBtZXJnZShuZXdTdGF0ZS5xdWVyeVBhcmFtcywgdGhpcy5xdWVyeVBhcmFtcyB8fCB7fSk7CiAgICAgIHJldHVybiBuZXdTdGF0ZTsKICAgIH07CgogICAgX3Byb3RvNy5pbnZhbGlkYXRlQ2hpbGRyZW4gPSBmdW5jdGlvbiBpbnZhbGlkYXRlQ2hpbGRyZW4oaGFuZGxlckluZm9zLCBpbnZhbGlkYXRlSW5kZXgpIHsKICAgICAgZm9yICh2YXIgaSA9IGludmFsaWRhdGVJbmRleCwgbCA9IGhhbmRsZXJJbmZvcy5sZW5ndGg7IGkgPCBsOyArK2kpIHsKICAgICAgICB2YXIgaGFuZGxlckluZm8gPSBoYW5kbGVySW5mb3NbaV07CgogICAgICAgIGlmIChoYW5kbGVySW5mby5pc1Jlc29sdmVkKSB7CiAgICAgICAgICB2YXIgX2hhbmRsZXJJbmZvcyRpID0gaGFuZGxlckluZm9zW2ldLAogICAgICAgICAgICAgIG5hbWUgPSBfaGFuZGxlckluZm9zJGkubmFtZSwKICAgICAgICAgICAgICBwYXJhbXMgPSBfaGFuZGxlckluZm9zJGkucGFyYW1zLAogICAgICAgICAgICAgIHJvdXRlID0gX2hhbmRsZXJJbmZvcyRpLnJvdXRlLAogICAgICAgICAgICAgIHBhcmFtTmFtZXMgPSBfaGFuZGxlckluZm9zJGkucGFyYW1OYW1lczsKICAgICAgICAgIGhhbmRsZXJJbmZvc1tpXSA9IG5ldyBVbnJlc29sdmVkUm91dGVJbmZvQnlQYXJhbSh0aGlzLnJvdXRlciwgbmFtZSwgcGFyYW1OYW1lcywgcGFyYW1zLCByb3V0ZSk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzcuZ2V0SGFuZGxlckluZm9Gb3JEeW5hbWljU2VnbWVudCA9IGZ1bmN0aW9uIGdldEhhbmRsZXJJbmZvRm9yRHluYW1pY1NlZ21lbnQobmFtZSwgbmFtZXMsIG9iamVjdHMsIG9sZEhhbmRsZXJJbmZvLCBfdGFyZ2V0Um91dGVOYW1lLCBpKSB7CiAgICAgIHZhciBvYmplY3RUb1VzZTsKCiAgICAgIGlmIChvYmplY3RzLmxlbmd0aCA+IDApIHsKICAgICAgICAvLyBVc2UgdGhlIG9iamVjdHMgcHJvdmlkZWQgZm9yIHRoaXMgdHJhbnNpdGlvbi4KICAgICAgICBvYmplY3RUb1VzZSA9IG9iamVjdHNbb2JqZWN0cy5sZW5ndGggLSAxXTsKCiAgICAgICAgaWYgKGlzUGFyYW0ob2JqZWN0VG9Vc2UpKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVQYXJhbUhhbmRsZXJJbmZvKG5hbWUsIG5hbWVzLCBvYmplY3RzLCBvbGRIYW5kbGVySW5mbyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9iamVjdHMucG9wKCk7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKG9sZEhhbmRsZXJJbmZvICYmIG9sZEhhbmRsZXJJbmZvLm5hbWUgPT09IG5hbWUpIHsKICAgICAgICAvLyBSZXVzZSB0aGUgbWF0Y2hpbmcgb2xkSGFuZGxlckluZm8KICAgICAgICByZXR1cm4gb2xkSGFuZGxlckluZm87CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaWYgKHRoaXMucHJlVHJhbnNpdGlvblN0YXRlKSB7CiAgICAgICAgICB2YXIgcHJlVHJhbnNpdGlvbkhhbmRsZXJJbmZvID0gdGhpcy5wcmVUcmFuc2l0aW9uU3RhdGUucm91dGVJbmZvc1tpXTsKICAgICAgICAgIG9iamVjdFRvVXNlID0gcHJlVHJhbnNpdGlvbkhhbmRsZXJJbmZvICYmIHByZVRyYW5zaXRpb25IYW5kbGVySW5mby5jb250ZXh0OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBJZGVhbGx5IHdlIHNob3VsZCB0aHJvdyB0aGlzIGVycm9yIHRvIHByb3ZpZGUgbWF4aW1hbAogICAgICAgICAgLy8gaW5mb3JtYXRpb24gdG8gdGhlIHVzZXIgdGhhdCBub3QgZW5vdWdoIGNvbnRleHQgb2JqZWN0cwogICAgICAgICAgLy8gd2VyZSBwcm92aWRlZCwgYnV0IHRoaXMgcHJvdmVzIHRvbyBjdW1iZXJzb21lIGluIEVtYmVyCiAgICAgICAgICAvLyBpbiBjYXNlcyB3aGVyZSBpbm5lciB0ZW1wbGF0ZSBoZWxwZXJzIGFyZSBldmFsdWF0ZWQKICAgICAgICAgIC8vIGJlZm9yZSBwYXJlbnQgaGVscGVycyB1bi1yZW5kZXIsIGluIHdoaWNoIGNhc2VzIHRoaXMKICAgICAgICAgIC8vIGVycm9yIHNvbWV3aGF0IHByZW1hdHVyZWx5IGZpcmVzLgogICAgICAgICAgLy90aHJvdyBuZXcgRXJyb3IoIk5vdCBlbm91Z2ggY29udGV4dCBvYmplY3RzIHdlcmUgcHJvdmlkZWQgdG8gY29tcGxldGUgYSB0cmFuc2l0aW9uIHRvICIgKyB0YXJnZXRSb3V0ZU5hbWUgKyAiLiBTcGVjaWZpY2FsbHksIHRoZSAiICsgbmFtZSArICIgcm91dGUgbmVlZHMgYW4gb2JqZWN0IHRoYXQgY2FuIGJlIHNlcmlhbGl6ZWQgaW50byBpdHMgZHluYW1pYyBVUkwgc2VnbWVudHMgWyIgKyBuYW1lcy5qb2luKCcsICcpICsgIl0iKTsKICAgICAgICAgIHJldHVybiBvbGRIYW5kbGVySW5mbzsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXcgVW5yZXNvbHZlZFJvdXRlSW5mb0J5T2JqZWN0KHRoaXMucm91dGVyLCBuYW1lLCBuYW1lcywgb2JqZWN0VG9Vc2UpOwogICAgfTsKCiAgICBfcHJvdG83LmNyZWF0ZVBhcmFtSGFuZGxlckluZm8gPSBmdW5jdGlvbiBjcmVhdGVQYXJhbUhhbmRsZXJJbmZvKG5hbWUsIG5hbWVzLCBvYmplY3RzLCBvbGRIYW5kbGVySW5mbykgewogICAgICB2YXIgcGFyYW1zID0ge307IC8vIFNvYWsgdXAgYWxsIHRoZSBwcm92aWRlZCBzdHJpbmcvbnVtYmVycwoKICAgICAgdmFyIG51bU5hbWVzID0gbmFtZXMubGVuZ3RoOwogICAgICB2YXIgbWlzc2luZ1BhcmFtcyA9IFtdOwoKICAgICAgd2hpbGUgKG51bU5hbWVzLS0pIHsKICAgICAgICAvLyBPbmx5IHVzZSBvbGQgcGFyYW1zIGlmIHRoZSBuYW1lcyBtYXRjaCB3aXRoIHRoZSBuZXcgaGFuZGxlcgogICAgICAgIHZhciBvbGRQYXJhbXMgPSBvbGRIYW5kbGVySW5mbyAmJiBuYW1lID09PSBvbGRIYW5kbGVySW5mby5uYW1lICYmIG9sZEhhbmRsZXJJbmZvLnBhcmFtcyB8fCB7fTsKICAgICAgICB2YXIgcGVlayA9IG9iamVjdHNbb2JqZWN0cy5sZW5ndGggLSAxXTsKICAgICAgICB2YXIgcGFyYW1OYW1lID0gbmFtZXNbbnVtTmFtZXNdOwoKICAgICAgICBpZiAoaXNQYXJhbShwZWVrKSkgewogICAgICAgICAgcGFyYW1zW3BhcmFtTmFtZV0gPSAnJyArIG9iamVjdHMucG9wKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vIElmIHdlJ3JlIGhlcmUsIHRoaXMgbWVhbnMgb25seSBzb21lIG9mIHRoZSBwYXJhbXMKICAgICAgICAgIC8vIHdlcmUgc3RyaW5nL251bWJlciBwYXJhbXMsIHNvIHRyeSBhbmQgdXNlIGEgcGFyYW0KICAgICAgICAgIC8vIHZhbHVlIGZyb20gYSBwcmV2aW91cyBoYW5kbGVyLgogICAgICAgICAgaWYgKG9sZFBhcmFtcy5oYXNPd25Qcm9wZXJ0eShwYXJhbU5hbWUpKSB7CiAgICAgICAgICAgIHBhcmFtc1twYXJhbU5hbWVdID0gb2xkUGFyYW1zW3BhcmFtTmFtZV07CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBtaXNzaW5nUGFyYW1zLnB1c2gocGFyYW1OYW1lKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChtaXNzaW5nUGFyYW1zLmxlbmd0aCA+IDApIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIllvdSBkaWRuJ3QgcHJvdmlkZSBlbm91Z2ggc3RyaW5nL251bWVyaWMgcGFyYW1ldGVycyB0byBzYXRpc2Z5IGFsbCBvZiB0aGUgZHluYW1pYyBzZWdtZW50cyBmb3Igcm91dGUgIiArIG5hbWUgKyAiLiIgKyAoIiBNaXNzaW5nIHBhcmFtczogIiArIG1pc3NpbmdQYXJhbXMpKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5ldyBVbnJlc29sdmVkUm91dGVJbmZvQnlQYXJhbSh0aGlzLnJvdXRlciwgbmFtZSwgbmFtZXMsIHBhcmFtcyk7CiAgICB9OwoKICAgIHJldHVybiBOYW1lZFRyYW5zaXRpb25JbnRlbnQ7CiAgfShUcmFuc2l0aW9uSW50ZW50KTsKCiAgdmFyIFVucmVjb2duaXplZFVSTEVycm9yID0gZnVuY3Rpb24gKCkgewogICAgVW5yZWNvZ25pemVkVVJMRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFcnJvci5wcm90b3R5cGUpOwogICAgVW5yZWNvZ25pemVkVVJMRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gVW5yZWNvZ25pemVkVVJMRXJyb3I7CgogICAgZnVuY3Rpb24gVW5yZWNvZ25pemVkVVJMRXJyb3IobWVzc2FnZSkgewogICAgICB2YXIgZXJyb3IgPSBFcnJvci5jYWxsKHRoaXMsIG1lc3NhZ2UpOwogICAgICB0aGlzLm5hbWUgPSAnVW5yZWNvZ25pemVkVVJMRXJyb3InOwogICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlIHx8ICdVbnJlY29nbml6ZWRVUkwnOwoKICAgICAgaWYgKEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKSB7CiAgICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgVW5yZWNvZ25pemVkVVJMRXJyb3IpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuc3RhY2sgPSBlcnJvci5zdGFjazsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBVbnJlY29nbml6ZWRVUkxFcnJvcjsKICB9KCk7CgogIHZhciBVUkxUcmFuc2l0aW9uSW50ZW50ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9UcmFuc2l0aW9uSW50ZW50MikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKFVSTFRyYW5zaXRpb25JbnRlbnQsIF9UcmFuc2l0aW9uSW50ZW50Mik7CgogICAgZnVuY3Rpb24gVVJMVHJhbnNpdGlvbkludGVudChyb3V0ZXIsIHVybCwgZGF0YSkgewogICAgICB2YXIgX3RoaXM4OwoKICAgICAgX3RoaXM4ID0gX1RyYW5zaXRpb25JbnRlbnQyLmNhbGwodGhpcywgcm91dGVyLCBkYXRhKSB8fCB0aGlzOwogICAgICBfdGhpczgudXJsID0gdXJsOwogICAgICBfdGhpczgucHJlVHJhbnNpdGlvblN0YXRlID0gdW5kZWZpbmVkOwogICAgICByZXR1cm4gX3RoaXM4OwogICAgfQoKICAgIHZhciBfcHJvdG84ID0gVVJMVHJhbnNpdGlvbkludGVudC5wcm90b3R5cGU7CgogICAgX3Byb3RvOC5hcHBseVRvU3RhdGUgPSBmdW5jdGlvbiBhcHBseVRvU3RhdGUob2xkU3RhdGUpIHsKICAgICAgdmFyIG5ld1N0YXRlID0gbmV3IFRyYW5zaXRpb25TdGF0ZSgpOwogICAgICB2YXIgcmVzdWx0cyA9IHRoaXMucm91dGVyLnJlY29nbml6ZXIucmVjb2duaXplKHRoaXMudXJsKSwKICAgICAgICAgIGksCiAgICAgICAgICBsZW47CgogICAgICBpZiAoIXJlc3VsdHMpIHsKICAgICAgICB0aHJvdyBuZXcgVW5yZWNvZ25pemVkVVJMRXJyb3IodGhpcy51cmwpOwogICAgICB9CgogICAgICB2YXIgc3RhdGVzRGlmZmVyID0gZmFsc2U7CiAgICAgIHZhciBfdXJsID0gdGhpcy51cmw7IC8vIENoZWNrcyBpZiBhIGhhbmRsZXIgaXMgYWNjZXNzaWJsZSBieSBVUkwuIElmIGl0IGlzIG5vdCwgYW4gZXJyb3IgaXMgdGhyb3duLgogICAgICAvLyBGb3IgdGhlIGNhc2Ugd2hlcmUgdGhlIGhhbmRsZXIgaXMgbG9hZGVkIGFzeW5jaHJvbm91c2x5LCB0aGUgZXJyb3Igd2lsbCBiZQogICAgICAvLyB0aHJvd24gb25jZSBpdCBpcyBsb2FkZWQuCgogICAgICBmdW5jdGlvbiBjaGVja0hhbmRsZXJBY2Nlc3NpYmlsaXR5KGhhbmRsZXIpIHsKICAgICAgICBpZiAoaGFuZGxlciAmJiBoYW5kbGVyLmluYWNjZXNzaWJsZUJ5VVJMKSB7CiAgICAgICAgICB0aHJvdyBuZXcgVW5yZWNvZ25pemVkVVJMRXJyb3IoX3VybCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gaGFuZGxlcjsKICAgICAgfQoKICAgICAgZm9yIChpID0gMCwgbGVuID0gcmVzdWx0cy5sZW5ndGg7IGkgPCBsZW47ICsraSkgewogICAgICAgIHZhciByZXN1bHQgPSByZXN1bHRzW2ldOwogICAgICAgIHZhciBuYW1lID0gcmVzdWx0LmhhbmRsZXI7CiAgICAgICAgdmFyIHBhcmFtTmFtZXMgPSBbXTsKCiAgICAgICAgaWYgKHRoaXMucm91dGVyLnJlY29nbml6ZXIuaGFzUm91dGUobmFtZSkpIHsKICAgICAgICAgIHBhcmFtTmFtZXMgPSB0aGlzLnJvdXRlci5yZWNvZ25pemVyLmhhbmRsZXJzRm9yKG5hbWUpW2ldLm5hbWVzOwogICAgICAgIH0KCiAgICAgICAgdmFyIG5ld1JvdXRlSW5mbyA9IG5ldyBVbnJlc29sdmVkUm91dGVJbmZvQnlQYXJhbSh0aGlzLnJvdXRlciwgbmFtZSwgcGFyYW1OYW1lcywgcmVzdWx0LnBhcmFtcyk7CiAgICAgICAgdmFyIHJvdXRlID0gbmV3Um91dGVJbmZvLnJvdXRlOwoKICAgICAgICBpZiAocm91dGUpIHsKICAgICAgICAgIGNoZWNrSGFuZGxlckFjY2Vzc2liaWxpdHkocm91dGUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAvLyBJZiB0aGUgaGFubGRlciBpcyBiZWluZyBsb2FkZWQgYXN5bmNocm9ub3VzbHksIGNoZWNrIGlmIHdlIGNhbgogICAgICAgICAgLy8gYWNjZXNzIGl0IGFmdGVyIGl0IGhhcyByZXNvbHZlZAogICAgICAgICAgbmV3Um91dGVJbmZvLnJvdXRlUHJvbWlzZSA9IG5ld1JvdXRlSW5mby5yb3V0ZVByb21pc2UudGhlbihjaGVja0hhbmRsZXJBY2Nlc3NpYmlsaXR5KTsKICAgICAgICB9CgogICAgICAgIHZhciBvbGRSb3V0ZUluZm8gPSBvbGRTdGF0ZS5yb3V0ZUluZm9zW2ldOwoKICAgICAgICBpZiAoc3RhdGVzRGlmZmVyIHx8IG5ld1JvdXRlSW5mby5zaG91bGRTdXBlcmNlZGUob2xkUm91dGVJbmZvKSkgewogICAgICAgICAgc3RhdGVzRGlmZmVyID0gdHJ1ZTsKICAgICAgICAgIG5ld1N0YXRlLnJvdXRlSW5mb3NbaV0gPSBuZXdSb3V0ZUluZm87CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG5ld1N0YXRlLnJvdXRlSW5mb3NbaV0gPSBvbGRSb3V0ZUluZm87CiAgICAgICAgfQogICAgICB9CgogICAgICBtZXJnZShuZXdTdGF0ZS5xdWVyeVBhcmFtcywgcmVzdWx0cy5xdWVyeVBhcmFtcyk7CiAgICAgIHJldHVybiBuZXdTdGF0ZTsKICAgIH07CgogICAgcmV0dXJuIFVSTFRyYW5zaXRpb25JbnRlbnQ7CiAgfShUcmFuc2l0aW9uSW50ZW50KTsKCiAgdmFyIFJvdXRlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJvdXRlcihsb2dnZXIpIHsKICAgICAgdGhpcy5fbGFzdFF1ZXJ5UGFyYW1zID0ge307CiAgICAgIHRoaXMuc3RhdGUgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMub2xkU3RhdGUgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuYWN0aXZlVHJhbnNpdGlvbiA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5jdXJyZW50Um91dGVJbmZvcyA9IHVuZGVmaW5lZDsKICAgICAgdGhpcy5fY2hhbmdlZFF1ZXJ5UGFyYW1zID0gdW5kZWZpbmVkOwogICAgICB0aGlzLmN1cnJlbnRTZXF1ZW5jZSA9IDA7CiAgICAgIHRoaXMubG9nID0gbG9nZ2VyOwogICAgICB0aGlzLnJlY29nbml6ZXIgPSBuZXcgX3JvdXRlUmVjb2duaXplci5kZWZhdWx0KCk7CiAgICAgIHRoaXMucmVzZXQoKTsKICAgIH0KICAgIC8qKgogICAgICBUaGUgbWFpbiBlbnRyeSBwb2ludCBpbnRvIHRoZSByb3V0ZXIuIFRoZSBBUEkgaXMgZXNzZW50aWFsbHkKICAgICAgdGhlIHNhbWUgYXMgdGhlIGBtYXBgIG1ldGhvZCBpbiBgcm91dGUtcmVjb2duaXplcmAuCiAgICAgICAgIFRoaXMgbWV0aG9kIGV4dHJhY3RzIHRoZSBTdHJpbmcgaGFuZGxlciBhdCB0aGUgbGFzdCBgLnRvKClgCiAgICAgIGNhbGwgYW5kIHVzZXMgaXQgYXMgdGhlIG5hbWUgb2YgdGhlIHdob2xlIHJvdXRlLgogICAgICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgKi8KCgogICAgdmFyIF9wcm90bzkgPSBSb3V0ZXIucHJvdG90eXBlOwoKICAgIF9wcm90bzkubWFwID0gZnVuY3Rpb24gbWFwKGNhbGxiYWNrKSB7CiAgICAgIHRoaXMucmVjb2duaXplci5tYXAoY2FsbGJhY2ssIGZ1bmN0aW9uIChyZWNvZ25pemVyLCByb3V0ZXMpIHsKICAgICAgICBmb3IgKHZhciBpID0gcm91dGVzLmxlbmd0aCAtIDEsIHByb2NlZWQgPSB0cnVlOyBpID49IDAgJiYgcHJvY2VlZDsgLS1pKSB7CiAgICAgICAgICB2YXIgcm91dGUgPSByb3V0ZXNbaV07CiAgICAgICAgICB2YXIgaGFuZGxlciA9IHJvdXRlLmhhbmRsZXI7CiAgICAgICAgICByZWNvZ25pemVyLmFkZChyb3V0ZXMsIHsKICAgICAgICAgICAgYXM6IGhhbmRsZXIKICAgICAgICAgIH0pOwogICAgICAgICAgcHJvY2VlZCA9IHJvdXRlLnBhdGggPT09ICcvJyB8fCByb3V0ZS5wYXRoID09PSAnJyB8fCBoYW5kbGVyLnNsaWNlKC02KSA9PT0gJy5pbmRleCc7CiAgICAgICAgfQogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvOS5oYXNSb3V0ZSA9IGZ1bmN0aW9uIGhhc1JvdXRlKHJvdXRlKSB7CiAgICAgIHJldHVybiB0aGlzLnJlY29nbml6ZXIuaGFzUm91dGUocm91dGUpOwogICAgfTsKCiAgICBfcHJvdG85LnF1ZXJ5UGFyYW1zVHJhbnNpdGlvbiA9IGZ1bmN0aW9uIHF1ZXJ5UGFyYW1zVHJhbnNpdGlvbihjaGFuZ2VsaXN0LCB3YXNUcmFuc2l0aW9uaW5nLCBvbGRTdGF0ZSwgbmV3U3RhdGUpIHsKICAgICAgdmFyIF90aGlzOSA9IHRoaXM7CgogICAgICB0aGlzLmZpcmVRdWVyeVBhcmFtRGlkQ2hhbmdlKG5ld1N0YXRlLCBjaGFuZ2VsaXN0KTsKCiAgICAgIGlmICghd2FzVHJhbnNpdGlvbmluZyAmJiB0aGlzLmFjdGl2ZVRyYW5zaXRpb24pIHsKICAgICAgICAvLyBPbmUgb2YgdGhlIHJvdXRlcyBpbiBxdWVyeVBhcmFtc0RpZENoYW5nZQogICAgICAgIC8vIGNhdXNlZCBhIHRyYW5zaXRpb24uIEp1c3QgcmV0dXJuIHRoYXQgdHJhbnNpdGlvbi4KICAgICAgICByZXR1cm4gdGhpcy5hY3RpdmVUcmFuc2l0aW9uOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIFJ1bm5pbmcgcXVlcnlQYXJhbXNEaWRDaGFuZ2UgZGlkbid0IGNoYW5nZSBhbnl0aGluZy4KICAgICAgICAvLyBKdXN0IHVwZGF0ZSBxdWVyeSBwYXJhbXMgYW5kIGJlIG9uIG91ciB3YXkuCiAgICAgICAgLy8gV2UgaGF2ZSB0byByZXR1cm4gYSBub29wIHRyYW5zaXRpb24gdGhhdCB3aWxsCiAgICAgICAgLy8gcGVyZm9ybSBhIFVSTCB1cGRhdGUgYXQgdGhlIGVuZC4gVGhpcyBnaXZlcwogICAgICAgIC8vIHRoZSB1c2VyIHRoZSBhYmlsaXR5IHRvIHNldCB0aGUgdXJsIHVwZGF0ZQogICAgICAgIC8vIG1ldGhvZCAoZGVmYXVsdCBpcyByZXBsYWNlU3RhdGUpLgogICAgICAgIHZhciBuZXdUcmFuc2l0aW9uID0gbmV3IFRyYW5zaXRpb24odGhpcywgdW5kZWZpbmVkLCB1bmRlZmluZWQpOwogICAgICAgIG5ld1RyYW5zaXRpb24ucXVlcnlQYXJhbXNPbmx5ID0gdHJ1ZTsKICAgICAgICBvbGRTdGF0ZS5xdWVyeVBhcmFtcyA9IHRoaXMuZmluYWxpemVRdWVyeVBhcmFtQ2hhbmdlKG5ld1N0YXRlLnJvdXRlSW5mb3MsIG5ld1N0YXRlLnF1ZXJ5UGFyYW1zLCBuZXdUcmFuc2l0aW9uKTsKICAgICAgICBuZXdUcmFuc2l0aW9uW1FVRVJZX1BBUkFNU19TWU1CT0xdID0gbmV3U3RhdGUucXVlcnlQYXJhbXM7CiAgICAgICAgdGhpcy50b1JlYWRPbmx5SW5mb3MobmV3VHJhbnNpdGlvbiwgbmV3U3RhdGUpOwogICAgICAgIHRoaXMucm91dGVXaWxsQ2hhbmdlKG5ld1RyYW5zaXRpb24pOwogICAgICAgIG5ld1RyYW5zaXRpb24ucHJvbWlzZSA9IG5ld1RyYW5zaXRpb24ucHJvbWlzZS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHsKICAgICAgICAgIF90aGlzOS5fdXBkYXRlVVJMKG5ld1RyYW5zaXRpb24sIG9sZFN0YXRlKTsKCiAgICAgICAgICBfdGhpczkuZGlkVHJhbnNpdGlvbihfdGhpczkuY3VycmVudFJvdXRlSW5mb3MpOwoKICAgICAgICAgIF90aGlzOS50b0luZm9zKG5ld1RyYW5zaXRpb24sIG5ld1N0YXRlLnJvdXRlSW5mb3MsIHRydWUpOwoKICAgICAgICAgIF90aGlzOS5yb3V0ZURpZENoYW5nZShuZXdUcmFuc2l0aW9uKTsKCiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0sIG51bGwsIF9wcm9taXNlTGFiZWwoJ1RyYW5zaXRpb24gY29tcGxldGUnKSk7CiAgICAgICAgcmV0dXJuIG5ld1RyYW5zaXRpb247CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvOS50cmFuc2l0aW9uQnlJbnRlbnQgPSBmdW5jdGlvbiB0cmFuc2l0aW9uQnlJbnRlbnQoaW50ZW50LCBpc0ludGVybWVkaWF0ZSkgewogICAgICB0cnkgewogICAgICAgIHJldHVybiB0aGlzLmdldFRyYW5zaXRpb25CeUludGVudChpbnRlbnQsIGlzSW50ZXJtZWRpYXRlKTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIHJldHVybiBuZXcgVHJhbnNpdGlvbih0aGlzLCBpbnRlbnQsIHVuZGVmaW5lZCwgZSwgdW5kZWZpbmVkKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG85LnJlY29nbml6ZSA9IGZ1bmN0aW9uIHJlY29nbml6ZSh1cmwpIHsKICAgICAgdmFyIGludGVudCA9IG5ldyBVUkxUcmFuc2l0aW9uSW50ZW50KHRoaXMsIHVybCk7CiAgICAgIHZhciBuZXdTdGF0ZSA9IHRoaXMuZ2VuZXJhdGVOZXdTdGF0ZShpbnRlbnQpOwoKICAgICAgaWYgKG5ld1N0YXRlID09PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIG5ld1N0YXRlOwogICAgICB9CgogICAgICB2YXIgcmVhZG9ubHlJbmZvcyA9IHRvUmVhZE9ubHlSb3V0ZUluZm8obmV3U3RhdGUucm91dGVJbmZvcywgbmV3U3RhdGUucXVlcnlQYXJhbXMpOwogICAgICByZXR1cm4gcmVhZG9ubHlJbmZvc1tyZWFkb25seUluZm9zLmxlbmd0aCAtIDFdOwogICAgfTsKCiAgICBfcHJvdG85LnJlY29nbml6ZUFuZExvYWQgPSBmdW5jdGlvbiByZWNvZ25pemVBbmRMb2FkKHVybCkgewogICAgICB2YXIgaW50ZW50ID0gbmV3IFVSTFRyYW5zaXRpb25JbnRlbnQodGhpcywgdXJsKTsKICAgICAgdmFyIG5ld1N0YXRlID0gdGhpcy5nZW5lcmF0ZU5ld1N0YXRlKGludGVudCk7CgogICAgICBpZiAobmV3U3RhdGUgPT09IG51bGwpIHsKICAgICAgICByZXR1cm4gX3JzdnAuUHJvbWlzZS5yZWplY3QoIlVSTCAiICsgdXJsICsgIiB3YXMgbm90IHJlY29nbml6ZWQiKTsKICAgICAgfQoKICAgICAgdmFyIG5ld1RyYW5zaXRpb24gPSBuZXcgVHJhbnNpdGlvbih0aGlzLCBpbnRlbnQsIG5ld1N0YXRlLCB1bmRlZmluZWQpOwogICAgICByZXR1cm4gbmV3VHJhbnNpdGlvbi50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgcm91dGVJbmZvc1dpdGhBdHRyaWJ1dGVzID0gdG9SZWFkT25seVJvdXRlSW5mbyhuZXdTdGF0ZS5yb3V0ZUluZm9zLCBuZXdUcmFuc2l0aW9uW1FVRVJZX1BBUkFNU19TWU1CT0xdLCB0cnVlKTsKICAgICAgICByZXR1cm4gcm91dGVJbmZvc1dpdGhBdHRyaWJ1dGVzW3JvdXRlSW5mb3NXaXRoQXR0cmlidXRlcy5sZW5ndGggLSAxXTsKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90bzkuZ2VuZXJhdGVOZXdTdGF0ZSA9IGZ1bmN0aW9uIGdlbmVyYXRlTmV3U3RhdGUoaW50ZW50KSB7CiAgICAgIHRyeSB7CiAgICAgICAgcmV0dXJuIGludGVudC5hcHBseVRvU3RhdGUodGhpcy5zdGF0ZSwgZmFsc2UpOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvOS5nZXRUcmFuc2l0aW9uQnlJbnRlbnQgPSBmdW5jdGlvbiBnZXRUcmFuc2l0aW9uQnlJbnRlbnQoaW50ZW50LCBpc0ludGVybWVkaWF0ZSkgewogICAgICB2YXIgX3RoaXMxMCA9IHRoaXM7CgogICAgICB2YXIgd2FzVHJhbnNpdGlvbmluZyA9ICEhdGhpcy5hY3RpdmVUcmFuc2l0aW9uOwogICAgICB2YXIgb2xkU3RhdGUgPSB3YXNUcmFuc2l0aW9uaW5nID8gdGhpcy5hY3RpdmVUcmFuc2l0aW9uW1NUQVRFX1NZTUJPTF0gOiB0aGlzLnN0YXRlOwogICAgICB2YXIgbmV3VHJhbnNpdGlvbjsKICAgICAgdmFyIG5ld1N0YXRlID0gaW50ZW50LmFwcGx5VG9TdGF0ZShvbGRTdGF0ZSwgaXNJbnRlcm1lZGlhdGUpOwogICAgICB2YXIgcXVlcnlQYXJhbUNoYW5nZWxpc3QgPSBnZXRDaGFuZ2VsaXN0KG9sZFN0YXRlLnF1ZXJ5UGFyYW1zLCBuZXdTdGF0ZS5xdWVyeVBhcmFtcyk7CgogICAgICBpZiAocm91dGVJbmZvc0VxdWFsKG5ld1N0YXRlLnJvdXRlSW5mb3MsIG9sZFN0YXRlLnJvdXRlSW5mb3MpKSB7CiAgICAgICAgLy8gVGhpcyBpcyBhIG5vLW9wIHRyYW5zaXRpb24uIFNlZSBpZiBxdWVyeSBwYXJhbXMgY2hhbmdlZC4KICAgICAgICBpZiAocXVlcnlQYXJhbUNoYW5nZWxpc3QpIHsKICAgICAgICAgIHZhciBfbmV3VHJhbnNpdGlvbiA9IHRoaXMucXVlcnlQYXJhbXNUcmFuc2l0aW9uKHF1ZXJ5UGFyYW1DaGFuZ2VsaXN0LCB3YXNUcmFuc2l0aW9uaW5nLCBvbGRTdGF0ZSwgbmV3U3RhdGUpOwoKICAgICAgICAgIF9uZXdUcmFuc2l0aW9uLnF1ZXJ5UGFyYW1zT25seSA9IHRydWU7CiAgICAgICAgICByZXR1cm4gX25ld1RyYW5zaXRpb247CiAgICAgICAgfSAvLyBOby1vcC4gTm8gbmVlZCB0byBjcmVhdGUgYSBuZXcgdHJhbnNpdGlvbi4KCgogICAgICAgIHJldHVybiB0aGlzLmFjdGl2ZVRyYW5zaXRpb24gfHwgbmV3IFRyYW5zaXRpb24odGhpcywgdW5kZWZpbmVkLCB1bmRlZmluZWQpOwogICAgICB9CgogICAgICBpZiAoaXNJbnRlcm1lZGlhdGUpIHsKICAgICAgICB2YXIgdHJhbnNpdGlvbiA9IG5ldyBUcmFuc2l0aW9uKHRoaXMsIHVuZGVmaW5lZCwgdW5kZWZpbmVkKTsKICAgICAgICB0aGlzLnRvUmVhZE9ubHlJbmZvcyh0cmFuc2l0aW9uLCBuZXdTdGF0ZSk7CiAgICAgICAgdGhpcy5zZXR1cENvbnRleHRzKG5ld1N0YXRlKTsKICAgICAgICB0aGlzLnJvdXRlV2lsbENoYW5nZSh0cmFuc2l0aW9uKTsKICAgICAgICByZXR1cm4gdGhpcy5hY3RpdmVUcmFuc2l0aW9uOwogICAgICB9IC8vIENyZWF0ZSBhIG5ldyB0cmFuc2l0aW9uIHRvIHRoZSBkZXN0aW5hdGlvbiByb3V0ZS4KCgogICAgICBuZXdUcmFuc2l0aW9uID0gbmV3IFRyYW5zaXRpb24odGhpcywgaW50ZW50LCBuZXdTdGF0ZSwgdW5kZWZpbmVkLCB0aGlzLmFjdGl2ZVRyYW5zaXRpb24pOyAvLyB0cmFuc2l0aW9uIGlzIHRvIHNhbWUgcm91dGUgd2l0aCBzYW1lIHBhcmFtcywgb25seSBxdWVyeSBwYXJhbXMgZGlmZmVyLgogICAgICAvLyBub3QgY2F1Z2h0IGFib3ZlIHByb2JhYmx5IGJlY2F1c2UgcmVmcmVzaCgpIGhhcyBiZWVuIHVzZWQKCiAgICAgIGlmIChyb3V0ZUluZm9zU2FtZUV4Y2VwdFF1ZXJ5UGFyYW1zKG5ld1N0YXRlLnJvdXRlSW5mb3MsIG9sZFN0YXRlLnJvdXRlSW5mb3MpKSB7CiAgICAgICAgbmV3VHJhbnNpdGlvbi5xdWVyeVBhcmFtc09ubHkgPSB0cnVlOwogICAgICB9CgogICAgICB0aGlzLnRvUmVhZE9ubHlJbmZvcyhuZXdUcmFuc2l0aW9uLCBuZXdTdGF0ZSk7IC8vIEFib3J0IGFuZCB1c3VycCBhbnkgcHJldmlvdXNseSBhY3RpdmUgdHJhbnNpdGlvbi4KCiAgICAgIGlmICh0aGlzLmFjdGl2ZVRyYW5zaXRpb24pIHsKICAgICAgICB0aGlzLmFjdGl2ZVRyYW5zaXRpb24ucmVkaXJlY3QobmV3VHJhbnNpdGlvbik7CiAgICAgIH0KCiAgICAgIHRoaXMuYWN0aXZlVHJhbnNpdGlvbiA9IG5ld1RyYW5zaXRpb247IC8vIFRyYW5zaXRpb24gcHJvbWlzZXMgYnkgZGVmYXVsdCByZXNvbHZlIHdpdGggcmVzb2x2ZWQgc3RhdGUuCiAgICAgIC8vIEZvciBvdXIgcHVycG9zZXMsIHN3YXAgb3V0IHRoZSBwcm9taXNlIHRvIHJlc29sdmUKICAgICAgLy8gYWZ0ZXIgdGhlIHRyYW5zaXRpb24gaGFzIGJlZW4gZmluYWxpemVkLgoKICAgICAgbmV3VHJhbnNpdGlvbi5wcm9taXNlID0gbmV3VHJhbnNpdGlvbi5wcm9taXNlLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkgewogICAgICAgIHJldHVybiBfdGhpczEwLmZpbmFsaXplVHJhbnNpdGlvbihuZXdUcmFuc2l0aW9uLCByZXN1bHQpOwogICAgICB9LCBudWxsLCBfcHJvbWlzZUxhYmVsKCdTZXR0bGUgdHJhbnNpdGlvbiBwcm9taXNlIHdoZW4gdHJhbnNpdGlvbiBpcyBmaW5hbGl6ZWQnKSk7CgogICAgICBpZiAoIXdhc1RyYW5zaXRpb25pbmcpIHsKICAgICAgICB0aGlzLm5vdGlmeUV4aXN0aW5nSGFuZGxlcnMobmV3U3RhdGUsIG5ld1RyYW5zaXRpb24pOwogICAgICB9CgogICAgICB0aGlzLmZpcmVRdWVyeVBhcmFtRGlkQ2hhbmdlKG5ld1N0YXRlLCBxdWVyeVBhcmFtQ2hhbmdlbGlzdCk7CiAgICAgIHJldHVybiBuZXdUcmFuc2l0aW9uOwogICAgfQogICAgLyoqCiAgICBAcHJpdmF0ZQogICAgICAgQmVnaW5zIGFuZCByZXR1cm5zIGEgVHJhbnNpdGlvbiBiYXNlZCBvbiB0aGUgcHJvdmlkZWQKICAgIGFyZ3VtZW50cy4gQWNjZXB0cyBhcmd1bWVudHMgaW4gdGhlIGZvcm0gb2YgYm90aCBVUkwKICAgIHRyYW5zaXRpb25zIGFuZCBuYW1lZCB0cmFuc2l0aW9ucy4KICAgICAgIEBwYXJhbSB7Um91dGVyfSByb3V0ZXIKICAgIEBwYXJhbSB7QXJyYXlbT2JqZWN0XX0gYXJncyBhcmd1bWVudHMgcGFzc2VkIHRvIHRyYW5zaXRpb25UbywKICAgICAgcmVwbGFjZVdpdGgsIG9yIGhhbmRsZVVSTAogICAgKi8KICAgIDsKCiAgICBfcHJvdG85LmRvVHJhbnNpdGlvbiA9IGZ1bmN0aW9uIGRvVHJhbnNpdGlvbihuYW1lLCBtb2RlbHNBcnJheSwgaXNJbnRlcm1lZGlhdGUpIHsKICAgICAgaWYgKG1vZGVsc0FycmF5ID09PSB2b2lkIDApIHsKICAgICAgICBtb2RlbHNBcnJheSA9IFtdOwogICAgICB9CgogICAgICBpZiAoaXNJbnRlcm1lZGlhdGUgPT09IHZvaWQgMCkgewogICAgICAgIGlzSW50ZXJtZWRpYXRlID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIHZhciBsYXN0QXJnID0gbW9kZWxzQXJyYXlbbW9kZWxzQXJyYXkubGVuZ3RoIC0gMV07CiAgICAgIHZhciBxdWVyeVBhcmFtcyA9IHt9OwoKICAgICAgaWYgKGxhc3RBcmcgIT09IHVuZGVmaW5lZCAmJiBsYXN0QXJnLmhhc093blByb3BlcnR5KCdxdWVyeVBhcmFtcycpKSB7CiAgICAgICAgcXVlcnlQYXJhbXMgPSBtb2RlbHNBcnJheS5wb3AoKS5xdWVyeVBhcmFtczsKICAgICAgfQoKICAgICAgdmFyIGludGVudDsKCiAgICAgIGlmIChuYW1lID09PSB1bmRlZmluZWQpIHsKICAgICAgICBfbG9nKHRoaXMsICdVcGRhdGluZyBxdWVyeSBwYXJhbXMnKTsgLy8gQSBxdWVyeSBwYXJhbSB1cGRhdGUgaXMgcmVhbGx5IGp1c3QgYSB0cmFuc2l0aW9uCiAgICAgICAgLy8gaW50byB0aGUgcm91dGUgeW91J3JlIGFscmVhZHkgb24uCgoKICAgICAgICB2YXIgcm91dGVJbmZvcyA9IHRoaXMuc3RhdGUucm91dGVJbmZvczsKICAgICAgICBpbnRlbnQgPSBuZXcgTmFtZWRUcmFuc2l0aW9uSW50ZW50KHRoaXMsIHJvdXRlSW5mb3Nbcm91dGVJbmZvcy5sZW5ndGggLSAxXS5uYW1lLCB1bmRlZmluZWQsIFtdLCBxdWVyeVBhcmFtcyk7CiAgICAgIH0gZWxzZSBpZiAobmFtZS5jaGFyQXQoMCkgPT09ICcvJykgewogICAgICAgIF9sb2codGhpcywgJ0F0dGVtcHRpbmcgVVJMIHRyYW5zaXRpb24gdG8gJyArIG5hbWUpOwoKICAgICAgICBpbnRlbnQgPSBuZXcgVVJMVHJhbnNpdGlvbkludGVudCh0aGlzLCBuYW1lKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBfbG9nKHRoaXMsICdBdHRlbXB0aW5nIHRyYW5zaXRpb24gdG8gJyArIG5hbWUpOwoKICAgICAgICBpbnRlbnQgPSBuZXcgTmFtZWRUcmFuc2l0aW9uSW50ZW50KHRoaXMsIG5hbWUsIHVuZGVmaW5lZCwgbW9kZWxzQXJyYXksIHF1ZXJ5UGFyYW1zKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMudHJhbnNpdGlvbkJ5SW50ZW50KGludGVudCwgaXNJbnRlcm1lZGlhdGUpOwogICAgfQogICAgLyoqCiAgICBAcHJpdmF0ZQogICAgICAgVXBkYXRlcyB0aGUgVVJMIChpZiBuZWNlc3NhcnkpIGFuZCBjYWxscyBgc2V0dXBDb250ZXh0c2AKICAgIHRvIHVwZGF0ZSB0aGUgcm91dGVyJ3MgYXJyYXkgb2YgYGN1cnJlbnRSb3V0ZUluZm9zYC4KICAgICovCiAgICA7CgogICAgX3Byb3RvOS5maW5hbGl6ZVRyYW5zaXRpb24gPSBmdW5jdGlvbiBmaW5hbGl6ZVRyYW5zaXRpb24odHJhbnNpdGlvbiwgbmV3U3RhdGUpIHsKICAgICAgdHJ5IHsKICAgICAgICBfbG9nKHRyYW5zaXRpb24ucm91dGVyLCB0cmFuc2l0aW9uLnNlcXVlbmNlLCAnUmVzb2x2ZWQgYWxsIG1vZGVscyBvbiBkZXN0aW5hdGlvbiByb3V0ZTsgZmluYWxpemluZyB0cmFuc2l0aW9uLicpOwoKICAgICAgICB2YXIgcm91dGVJbmZvcyA9IG5ld1N0YXRlLnJvdXRlSW5mb3M7IC8vIFJ1biBhbGwgdGhlIG5lY2Vzc2FyeSBlbnRlci9zZXR1cC9leGl0IGhvb2tzCgogICAgICAgIHRoaXMuc2V0dXBDb250ZXh0cyhuZXdTdGF0ZSwgdHJhbnNpdGlvbik7IC8vIENoZWNrIGlmIGEgcmVkaXJlY3Qgb2NjdXJyZWQgaW4gZW50ZXIvc2V0dXAKCiAgICAgICAgaWYgKHRyYW5zaXRpb24uaXNBYm9ydGVkKSB7CiAgICAgICAgICAvLyBUT0RPOiBjbGVhbmVyIHdheT8gZGlzdGluZ3Vpc2ggYi93IHRhcmdldFJvdXRlSW5mb3M/CiAgICAgICAgICB0aGlzLnN0YXRlLnJvdXRlSW5mb3MgPSB0aGlzLmN1cnJlbnRSb3V0ZUluZm9zOwogICAgICAgICAgcmV0dXJuIF9yc3ZwLlByb21pc2UucmVqZWN0KGxvZ0Fib3J0KHRyYW5zaXRpb24pKTsKICAgICAgICB9CgogICAgICAgIHRoaXMuX3VwZGF0ZVVSTCh0cmFuc2l0aW9uLCBuZXdTdGF0ZSk7CgogICAgICAgIHRyYW5zaXRpb24uaXNBY3RpdmUgPSBmYWxzZTsKICAgICAgICB0aGlzLmFjdGl2ZVRyYW5zaXRpb24gPSB1bmRlZmluZWQ7CiAgICAgICAgdGhpcy50cmlnZ2VyRXZlbnQodGhpcy5jdXJyZW50Um91dGVJbmZvcywgdHJ1ZSwgJ2RpZFRyYW5zaXRpb24nLCBbXSk7CiAgICAgICAgdGhpcy5kaWRUcmFuc2l0aW9uKHRoaXMuY3VycmVudFJvdXRlSW5mb3MpOwogICAgICAgIHRoaXMudG9JbmZvcyh0cmFuc2l0aW9uLCBuZXdTdGF0ZS5yb3V0ZUluZm9zLCB0cnVlKTsKICAgICAgICB0aGlzLnJvdXRlRGlkQ2hhbmdlKHRyYW5zaXRpb24pOwoKICAgICAgICBfbG9nKHRoaXMsIHRyYW5zaXRpb24uc2VxdWVuY2UsICdUUkFOU0lUSU9OIENPTVBMRVRFLicpOyAvLyBSZXNvbHZlIHdpdGggdGhlIGZpbmFsIHJvdXRlLgoKCiAgICAgICAgcmV0dXJuIHJvdXRlSW5mb3Nbcm91dGVJbmZvcy5sZW5ndGggLSAxXS5yb3V0ZTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBUcmFuc2l0aW9uQWJvcnRlZEVycm9yKSkgewogICAgICAgICAgdmFyIGluZm9zID0gdHJhbnNpdGlvbltTVEFURV9TWU1CT0xdLnJvdXRlSW5mb3M7CiAgICAgICAgICB0cmFuc2l0aW9uLnRyaWdnZXIodHJ1ZSwgJ2Vycm9yJywgZSwgdHJhbnNpdGlvbiwgaW5mb3NbaW5mb3MubGVuZ3RoIC0gMV0ucm91dGUpOwogICAgICAgICAgdHJhbnNpdGlvbi5hYm9ydCgpOwogICAgICAgIH0KCiAgICAgICAgdGhyb3cgZTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICBAcHJpdmF0ZQogICAgICAgVGFrZXMgYW4gQXJyYXkgb2YgYFJvdXRlSW5mb2BzLCBmaWd1cmVzIG91dCB3aGljaCBvbmVzIGFyZQogICAgZXhpdGluZywgZW50ZXJpbmcsIG9yIGNoYW5naW5nIGNvbnRleHRzLCBhbmQgY2FsbHMgdGhlCiAgICBwcm9wZXIgcm91dGUgaG9va3MuCiAgICAgICBGb3IgZXhhbXBsZSwgY29uc2lkZXIgdGhlIGZvbGxvd2luZyB0cmVlIG9mIHJvdXRlcy4gRWFjaCByb3V0ZSBpcwogICAgZm9sbG93ZWQgYnkgdGhlIFVSTCBzZWdtZW50IGl0IGhhbmRsZXMuCiAgICAgICBgYGAKICAgIHx+aW5kZXggKCIvIikKICAgIHwgfH5wb3N0cyAoIi9wb3N0cyIpCiAgICB8IHwgfC1zaG93UG9zdCAoIi86aWQiKQogICAgfCB8IHwtbmV3UG9zdCAoIi9uZXciKQogICAgfCB8IHwtZWRpdFBvc3QgKCIvZWRpdCIpCiAgICB8IHx+YWJvdXQgKCIvYWJvdXQvOmlkIikKICAgIGBgYAogICAgICAgQ29uc2lkZXIgdGhlIGZvbGxvd2luZyB0cmFuc2l0aW9uczoKICAgICAgIDEuIEEgVVJMIHRyYW5zaXRpb24gdG8gYC9wb3N0cy8xYC4KICAgICAgIDEuIFRyaWdnZXJzIHRoZSBgKm1vZGVsYCBjYWxsYmFja3Mgb24gdGhlCiAgICAgICAgICBgaW5kZXhgLCBgcG9zdHNgLCBhbmQgYHNob3dQb3N0YCByb3V0ZXMKICAgICAgIDIuIFRyaWdnZXJzIHRoZSBgZW50ZXJgIGNhbGxiYWNrIG9uIHRoZSBzYW1lCiAgICAgICAzLiBUcmlnZ2VycyB0aGUgYHNldHVwYCBjYWxsYmFjayBvbiB0aGUgc2FtZQogICAgMi4gQSBkaXJlY3QgdHJhbnNpdGlvbiB0byBgbmV3UG9zdGAKICAgICAgIDEuIFRyaWdnZXJzIHRoZSBgZXhpdGAgY2FsbGJhY2sgb24gYHNob3dQb3N0YAogICAgICAgMi4gVHJpZ2dlcnMgdGhlIGBlbnRlcmAgY2FsbGJhY2sgb24gYG5ld1Bvc3RgCiAgICAgICAzLiBUcmlnZ2VycyB0aGUgYHNldHVwYCBjYWxsYmFjayBvbiBgbmV3UG9zdGAKICAgIDMuIEEgZGlyZWN0IHRyYW5zaXRpb24gdG8gYGFib3V0YCB3aXRoIGEgc3BlY2lmaWVkCiAgICAgICBjb250ZXh0IG9iamVjdAogICAgICAgMS4gVHJpZ2dlcnMgdGhlIGBleGl0YCBjYWxsYmFjayBvbiBgbmV3UG9zdGAKICAgICAgICAgIGFuZCBgcG9zdHNgCiAgICAgICAyLiBUcmlnZ2VycyB0aGUgYHNlcmlhbGl6ZWAgY2FsbGJhY2sgb24gYGFib3V0YAogICAgICAgMy4gVHJpZ2dlcnMgdGhlIGBlbnRlcmAgY2FsbGJhY2sgb24gYGFib3V0YAogICAgICAgNC4gVHJpZ2dlcnMgdGhlIGBzZXR1cGAgY2FsbGJhY2sgb24gYGFib3V0YAogICAgICAgQHBhcmFtIHtSb3V0ZXJ9IHRyYW5zaXRpb24KICAgIEBwYXJhbSB7VHJhbnNpdGlvblN0YXRlfSBuZXdTdGF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG85LnNldHVwQ29udGV4dHMgPSBmdW5jdGlvbiBzZXR1cENvbnRleHRzKG5ld1N0YXRlLCB0cmFuc2l0aW9uKSB7CiAgICAgIHZhciBwYXJ0aXRpb24gPSB0aGlzLnBhcnRpdGlvblJvdXRlcyh0aGlzLnN0YXRlLCBuZXdTdGF0ZSk7CiAgICAgIHZhciBpLCBsLCByb3V0ZTsKCiAgICAgIGZvciAoaSA9IDAsIGwgPSBwYXJ0aXRpb24uZXhpdGVkLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICAgIHJvdXRlID0gcGFydGl0aW9uLmV4aXRlZFtpXS5yb3V0ZTsKICAgICAgICBkZWxldGUgcm91dGUuY29udGV4dDsKCiAgICAgICAgaWYgKHJvdXRlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGlmIChyb3V0ZS5faW50ZXJuYWxSZXNldCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHJvdXRlLl9pbnRlcm5hbFJlc2V0KHRydWUsIHRyYW5zaXRpb24pOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChyb3V0ZS5leGl0ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgcm91dGUuZXhpdCh0cmFuc2l0aW9uKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciBvbGRTdGF0ZSA9IHRoaXMub2xkU3RhdGUgPSB0aGlzLnN0YXRlOwogICAgICB0aGlzLnN0YXRlID0gbmV3U3RhdGU7CiAgICAgIHZhciBjdXJyZW50Um91dGVJbmZvcyA9IHRoaXMuY3VycmVudFJvdXRlSW5mb3MgPSBwYXJ0aXRpb24udW5jaGFuZ2VkLnNsaWNlKCk7CgogICAgICB0cnkgewogICAgICAgIGZvciAoaSA9IDAsIGwgPSBwYXJ0aXRpb24ucmVzZXQubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICByb3V0ZSA9IHBhcnRpdGlvbi5yZXNldFtpXS5yb3V0ZTsKCiAgICAgICAgICBpZiAocm91dGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBpZiAocm91dGUuX2ludGVybmFsUmVzZXQgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIHJvdXRlLl9pbnRlcm5hbFJlc2V0KGZhbHNlLCB0cmFuc2l0aW9uKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZm9yIChpID0gMCwgbCA9IHBhcnRpdGlvbi51cGRhdGVkQ29udGV4dC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgIHRoaXMucm91dGVFbnRlcmVkT3JVcGRhdGVkKGN1cnJlbnRSb3V0ZUluZm9zLCBwYXJ0aXRpb24udXBkYXRlZENvbnRleHRbaV0sIGZhbHNlLCB0cmFuc2l0aW9uKTsKICAgICAgICB9CgogICAgICAgIGZvciAoaSA9IDAsIGwgPSBwYXJ0aXRpb24uZW50ZXJlZC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgIHRoaXMucm91dGVFbnRlcmVkT3JVcGRhdGVkKGN1cnJlbnRSb3V0ZUluZm9zLCBwYXJ0aXRpb24uZW50ZXJlZFtpXSwgdHJ1ZSwgdHJhbnNpdGlvbik7CiAgICAgICAgfQogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgdGhpcy5zdGF0ZSA9IG9sZFN0YXRlOwogICAgICAgIHRoaXMuY3VycmVudFJvdXRlSW5mb3MgPSBvbGRTdGF0ZS5yb3V0ZUluZm9zOwogICAgICAgIHRocm93IGU7CiAgICAgIH0KCiAgICAgIHRoaXMuc3RhdGUucXVlcnlQYXJhbXMgPSB0aGlzLmZpbmFsaXplUXVlcnlQYXJhbUNoYW5nZShjdXJyZW50Um91dGVJbmZvcywgbmV3U3RhdGUucXVlcnlQYXJhbXMsIHRyYW5zaXRpb24pOwogICAgfQogICAgLyoqCiAgICBAcHJpdmF0ZQogICAgICAgRmlyZXMgcXVlcnlQYXJhbXNEaWRDaGFuZ2UgZXZlbnQKICAgICovCiAgICA7CgogICAgX3Byb3RvOS5maXJlUXVlcnlQYXJhbURpZENoYW5nZSA9IGZ1bmN0aW9uIGZpcmVRdWVyeVBhcmFtRGlkQ2hhbmdlKG5ld1N0YXRlLCBxdWVyeVBhcmFtQ2hhbmdlbGlzdCkgewogICAgICAvLyBJZiBxdWVyeVBhcmFtcyBjaGFuZ2VkIHRyaWdnZXIgZXZlbnQKICAgICAgaWYgKHF1ZXJ5UGFyYW1DaGFuZ2VsaXN0KSB7CiAgICAgICAgLy8gVGhpcyBpcyBhIGxpdHRsZSBoYWNreSBidXQgd2UgbmVlZCBzb21lIHdheSBvZiBzdG9yaW5nCiAgICAgICAgLy8gY2hhbmdlZCBxdWVyeSBwYXJhbXMgZ2l2ZW4gdGhhdCBubyBhY3RpdmVUcmFuc2l0aW9uCiAgICAgICAgLy8gaXMgZ3VhcmFudGVlZCB0byBoYXZlIG9jY3VycmVkLgogICAgICAgIHRoaXMuX2NoYW5nZWRRdWVyeVBhcmFtcyA9IHF1ZXJ5UGFyYW1DaGFuZ2VsaXN0LmFsbDsKICAgICAgICB0aGlzLnRyaWdnZXJFdmVudChuZXdTdGF0ZS5yb3V0ZUluZm9zLCB0cnVlLCAncXVlcnlQYXJhbXNEaWRDaGFuZ2UnLCBbcXVlcnlQYXJhbUNoYW5nZWxpc3QuY2hhbmdlZCwgcXVlcnlQYXJhbUNoYW5nZWxpc3QuYWxsLCBxdWVyeVBhcmFtQ2hhbmdlbGlzdC5yZW1vdmVkXSk7CiAgICAgICAgdGhpcy5fY2hhbmdlZFF1ZXJ5UGFyYW1zID0gdW5kZWZpbmVkOwogICAgICB9CiAgICB9CiAgICAvKioKICAgIEBwcml2YXRlCiAgICAgICBIZWxwZXIgbWV0aG9kIHVzZWQgYnkgc2V0dXBDb250ZXh0cy4gSGFuZGxlcyBlcnJvcnMgb3IgcmVkaXJlY3RzCiAgICB0aGF0IG1heSBoYXBwZW4gaW4gZW50ZXIvc2V0dXAuCiAgICAqLwogICAgOwoKICAgIF9wcm90bzkucm91dGVFbnRlcmVkT3JVcGRhdGVkID0gZnVuY3Rpb24gcm91dGVFbnRlcmVkT3JVcGRhdGVkKGN1cnJlbnRSb3V0ZUluZm9zLCByb3V0ZUluZm8sIGVudGVyLCB0cmFuc2l0aW9uKSB7CiAgICAgIHZhciByb3V0ZSA9IHJvdXRlSW5mby5yb3V0ZSwKICAgICAgICAgIGNvbnRleHQgPSByb3V0ZUluZm8uY29udGV4dDsKCiAgICAgIGZ1bmN0aW9uIF9yb3V0ZUVudGVyZWRPclVwZGF0ZWQocm91dGUpIHsKICAgICAgICBpZiAoZW50ZXIpIHsKICAgICAgICAgIGlmIChyb3V0ZS5lbnRlciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHJvdXRlLmVudGVyKHRyYW5zaXRpb24pOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKHRyYW5zaXRpb24gJiYgdHJhbnNpdGlvbi5pc0Fib3J0ZWQpIHsKICAgICAgICAgIHRocm93IG5ldyBUcmFuc2l0aW9uQWJvcnRlZEVycm9yKCk7CiAgICAgICAgfQoKICAgICAgICByb3V0ZS5jb250ZXh0ID0gY29udGV4dDsKCiAgICAgICAgaWYgKHJvdXRlLmNvbnRleHREaWRDaGFuZ2UgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcm91dGUuY29udGV4dERpZENoYW5nZSgpOwogICAgICAgIH0KCiAgICAgICAgaWYgKHJvdXRlLnNldHVwICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJvdXRlLnNldHVwKGNvbnRleHQsIHRyYW5zaXRpb24pOwogICAgICAgIH0KCiAgICAgICAgaWYgKHRyYW5zaXRpb24gJiYgdHJhbnNpdGlvbi5pc0Fib3J0ZWQpIHsKICAgICAgICAgIHRocm93IG5ldyBUcmFuc2l0aW9uQWJvcnRlZEVycm9yKCk7CiAgICAgICAgfQoKICAgICAgICBjdXJyZW50Um91dGVJbmZvcy5wdXNoKHJvdXRlSW5mbyk7CiAgICAgICAgcmV0dXJuIHJvdXRlOwogICAgICB9IC8vIElmIHRoZSByb3V0ZSBkb2Vzbid0IGV4aXN0LCBpdCBtZWFucyB3ZSBoYXZlbid0IHJlc29sdmVkIHRoZSByb3V0ZSBwcm9taXNlIHlldAoKCiAgICAgIGlmIChyb3V0ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcm91dGVJbmZvLnJvdXRlUHJvbWlzZSA9IHJvdXRlSW5mby5yb3V0ZVByb21pc2UudGhlbihfcm91dGVFbnRlcmVkT3JVcGRhdGVkKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBfcm91dGVFbnRlcmVkT3JVcGRhdGVkKHJvdXRlKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICAvKioKICAgIEBwcml2YXRlCiAgICAgICBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuIHRyYW5zaXRpb25pbmcgZnJvbSBvbmUgVVJMIHRvCiAgICBhbm90aGVyIHRvIGRldGVybWluZSB3aGljaCByb3V0ZXMgYXJlIG5vIGxvbmdlciBhY3RpdmUsCiAgICB3aGljaCByb3V0ZXMgYXJlIG5ld2x5IGFjdGl2ZSwgYW5kIHdoaWNoIHJvdXRlcyByZW1haW4KICAgIGFjdGl2ZSBidXQgaGF2ZSB0aGVpciBjb250ZXh0IGNoYW5nZWQuCiAgICAgICBUYWtlIGEgbGlzdCBvZiBvbGQgcm91dGVzIGFuZCBuZXcgcm91dGVzIGFuZCBwYXJ0aXRpb24KICAgIHRoZW0gaW50byBmb3VyIGJ1Y2tldHM6CiAgICAgICAqIHVuY2hhbmdlZDogdGhlIHJvdXRlIHdhcyBhY3RpdmUgaW4gYm90aCB0aGUgb2xkIGFuZAogICAgICBuZXcgVVJMLCBhbmQgaXRzIGNvbnRleHQgcmVtYWlucyB0aGUgc2FtZQogICAgKiB1cGRhdGVkIGNvbnRleHQ6IHRoZSByb3V0ZSB3YXMgYWN0aXZlIGluIGJvdGggdGhlCiAgICAgIG9sZCBhbmQgbmV3IFVSTCwgYnV0IGl0cyBjb250ZXh0IGNoYW5nZWQuIFRoZSByb3V0ZSdzCiAgICAgIGBzZXR1cGAgbWV0aG9kLCBpZiBhbnksIHdpbGwgYmUgY2FsbGVkIHdpdGggdGhlIG5ldwogICAgICBjb250ZXh0LgogICAgKiBleGl0ZWQ6IHRoZSByb3V0ZSB3YXMgYWN0aXZlIGluIHRoZSBvbGQgVVJMLCBidXQgaXMKICAgICAgbm8gbG9uZ2VyIGFjdGl2ZS4KICAgICogZW50ZXJlZDogdGhlIHJvdXRlIHdhcyBub3QgYWN0aXZlIGluIHRoZSBvbGQgVVJMLCBidXQKICAgICAgaXMgbm93IGFjdGl2ZS4KICAgICAgIFRoZSBQYXJ0aXRpb25lZFJvdXRlcyBzdHJ1Y3R1cmUgaGFzIGZvdXIgZmllbGRzOgogICAgICAgKiBgdXBkYXRlZENvbnRleHRgOiBhIGxpc3Qgb2YgYFJvdXRlSW5mb2Agb2JqZWN0cyB0aGF0CiAgICAgIHJlcHJlc2VudCByb3V0ZXMgdGhhdCByZW1haW4gYWN0aXZlIGJ1dCBoYXZlIGEgY2hhbmdlZAogICAgICBjb250ZXh0CiAgICAqIGBlbnRlcmVkYDogYSBsaXN0IG9mIGBSb3V0ZUluZm9gIG9iamVjdHMgdGhhdCByZXByZXNlbnQKICAgICAgcm91dGVzIHRoYXQgYXJlIG5ld2x5IGFjdGl2ZQogICAgKiBgZXhpdGVkYDogYSBsaXN0IG9mIGBSb3V0ZUluZm9gIG9iamVjdHMgdGhhdCBhcmUgbm8KICAgICAgbG9uZ2VyIGFjdGl2ZS4KICAgICogYHVuY2hhbmdlZGA6IGEgbGlzdCBvZiBgUm91dGVJbmZvYCBvYmplY3RzIHRoYXQgcmVtYWluIGFjdGl2ZS4KICAgICAgIEBwYXJhbSB7QXJyYXlbSW50ZXJuYWxSb3V0ZUluZm9dfSBvbGRSb3V0ZXMgYSBsaXN0IG9mIHRoZSByb3V0ZQogICAgICBpbmZvcm1hdGlvbiBmb3IgdGhlIHByZXZpb3VzIFVSTCAob3IgYFtdYCBpZiB0aGlzIGlzIHRoZQogICAgICBmaXJzdCBoYW5kbGVkIHRyYW5zaXRpb24pCiAgICBAcGFyYW0ge0FycmF5W0ludGVybmFsUm91dGVJbmZvXX0gbmV3Um91dGVzIGEgbGlzdCBvZiB0aGUgcm91dGUKICAgICAgaW5mb3JtYXRpb24gZm9yIHRoZSBuZXcgVVJMCiAgICAgICBAcmV0dXJuIHtQYXJ0aXRpb259CiAgICAqLwogICAgOwoKICAgIF9wcm90bzkucGFydGl0aW9uUm91dGVzID0gZnVuY3Rpb24gcGFydGl0aW9uUm91dGVzKG9sZFN0YXRlLCBuZXdTdGF0ZSkgewogICAgICB2YXIgb2xkUm91dGVJbmZvcyA9IG9sZFN0YXRlLnJvdXRlSW5mb3M7CiAgICAgIHZhciBuZXdSb3V0ZUluZm9zID0gbmV3U3RhdGUucm91dGVJbmZvczsKICAgICAgdmFyIHJvdXRlcyA9IHsKICAgICAgICB1cGRhdGVkQ29udGV4dDogW10sCiAgICAgICAgZXhpdGVkOiBbXSwKICAgICAgICBlbnRlcmVkOiBbXSwKICAgICAgICB1bmNoYW5nZWQ6IFtdLAogICAgICAgIHJlc2V0OiBbXQogICAgICB9OwogICAgICB2YXIgcm91dGVDaGFuZ2VkLAogICAgICAgICAgY29udGV4dENoYW5nZWQgPSBmYWxzZSwKICAgICAgICAgIGksCiAgICAgICAgICBsOwoKICAgICAgZm9yIChpID0gMCwgbCA9IG5ld1JvdXRlSW5mb3MubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgdmFyIG9sZFJvdXRlSW5mbyA9IG9sZFJvdXRlSW5mb3NbaV0sCiAgICAgICAgICAgIG5ld1JvdXRlSW5mbyA9IG5ld1JvdXRlSW5mb3NbaV07CgogICAgICAgIGlmICghb2xkUm91dGVJbmZvIHx8IG9sZFJvdXRlSW5mby5yb3V0ZSAhPT0gbmV3Um91dGVJbmZvLnJvdXRlKSB7CiAgICAgICAgICByb3V0ZUNoYW5nZWQgPSB0cnVlOwogICAgICAgIH0KCiAgICAgICAgaWYgKHJvdXRlQ2hhbmdlZCkgewogICAgICAgICAgcm91dGVzLmVudGVyZWQucHVzaChuZXdSb3V0ZUluZm8pOwoKICAgICAgICAgIGlmIChvbGRSb3V0ZUluZm8pIHsKICAgICAgICAgICAgcm91dGVzLmV4aXRlZC51bnNoaWZ0KG9sZFJvdXRlSW5mbyk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChjb250ZXh0Q2hhbmdlZCB8fCBvbGRSb3V0ZUluZm8uY29udGV4dCAhPT0gbmV3Um91dGVJbmZvLmNvbnRleHQpIHsKICAgICAgICAgIGNvbnRleHRDaGFuZ2VkID0gdHJ1ZTsKICAgICAgICAgIHJvdXRlcy51cGRhdGVkQ29udGV4dC5wdXNoKG5ld1JvdXRlSW5mbyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJvdXRlcy51bmNoYW5nZWQucHVzaChvbGRSb3V0ZUluZm8pOwogICAgICAgIH0KICAgICAgfQoKICAgICAgZm9yIChpID0gbmV3Um91dGVJbmZvcy5sZW5ndGgsIGwgPSBvbGRSb3V0ZUluZm9zLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICAgIHJvdXRlcy5leGl0ZWQudW5zaGlmdChvbGRSb3V0ZUluZm9zW2ldKTsKICAgICAgfQoKICAgICAgcm91dGVzLnJlc2V0ID0gcm91dGVzLnVwZGF0ZWRDb250ZXh0LnNsaWNlKCk7CiAgICAgIHJvdXRlcy5yZXNldC5yZXZlcnNlKCk7CiAgICAgIHJldHVybiByb3V0ZXM7CiAgICB9OwoKICAgIF9wcm90bzkuX3VwZGF0ZVVSTCA9IGZ1bmN0aW9uIF91cGRhdGVVUkwodHJhbnNpdGlvbiwgc3RhdGUpIHsKICAgICAgdmFyIHVybE1ldGhvZCA9IHRyYW5zaXRpb24udXJsTWV0aG9kOwoKICAgICAgaWYgKCF1cmxNZXRob2QpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciByb3V0ZUluZm9zID0gc3RhdGUucm91dGVJbmZvczsKICAgICAgdmFyIHJvdXRlTmFtZSA9IHJvdXRlSW5mb3Nbcm91dGVJbmZvcy5sZW5ndGggLSAxXS5uYW1lOwogICAgICB2YXIgcGFyYW1zID0ge307CgogICAgICBmb3IgKHZhciBpID0gcm91dGVJbmZvcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgewogICAgICAgIHZhciByb3V0ZUluZm8gPSByb3V0ZUluZm9zW2ldOwogICAgICAgIG1lcmdlKHBhcmFtcywgcm91dGVJbmZvLnBhcmFtcyk7CgogICAgICAgIGlmIChyb3V0ZUluZm8ucm91dGUuaW5hY2Nlc3NpYmxlQnlVUkwpIHsKICAgICAgICAgIHVybE1ldGhvZCA9IG51bGw7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAodXJsTWV0aG9kKSB7CiAgICAgICAgcGFyYW1zLnF1ZXJ5UGFyYW1zID0gdHJhbnNpdGlvbi5fdmlzaWJsZVF1ZXJ5UGFyYW1zIHx8IHN0YXRlLnF1ZXJ5UGFyYW1zOwogICAgICAgIHZhciB1cmwgPSB0aGlzLnJlY29nbml6ZXIuZ2VuZXJhdGUocm91dGVOYW1lLCBwYXJhbXMpOyAvLyB0cmFuc2l0aW9ucyBkdXJpbmcgdGhlIGluaXRpYWwgdHJhbnNpdGlvbiBtdXN0IGFsd2F5cyB1c2UgcmVwbGFjZVVSTC4KICAgICAgICAvLyBXaGVuIHRoZSBhcHAgYm9vdHMsIHlvdSBhcmUgYXQgYSB1cmwsIGUuZy4gL2Zvby4gSWYgc29tZSByb3V0ZQogICAgICAgIC8vIHJlZGlyZWN0cyB0byBiYXIgYXMgcGFydCBvZiB0aGUgaW5pdGlhbCB0cmFuc2l0aW9uLCB5b3UgZG9uJ3Qgd2FudCB0bwogICAgICAgIC8vIGFkZCBhIGhpc3RvcnkgZW50cnkgZm9yIC9mb28uIElmIHlvdSBkbywgcHJlc3NpbmcgYmFjayB3aWxsIGltbWVkaWF0ZWx5CiAgICAgICAgLy8gaGl0IHRoZSByZWRpcmVjdCBhZ2FpbiBhbmQgdGFrZSB5b3UgYmFjayB0byAvYmFyLCB0aHVzIGtpbGxpbmcgdGhlIGJhY2sKICAgICAgICAvLyBidXR0b24KCiAgICAgICAgdmFyIGluaXRpYWwgPSB0cmFuc2l0aW9uLmlzQ2F1c2VkQnlJbml0aWFsVHJhbnNpdGlvbjsgLy8gc2F5IHlvdSBhcmUgYXQgLyBhbmQgeW91IGNsaWNrIGEgbGluayB0byByb3V0ZSAvZm9vLiBJbiAvZm9vJ3MKICAgICAgICAvLyByb3V0ZSwgdGhlIHRyYW5zaXRpb24gaXMgYWJvcnRlZCB1c2luZyByZXBsYWNld2l0aCgnL2JhcicpLgogICAgICAgIC8vIEJlY2F1c2UgdGhlIGN1cnJlbnQgdXJsIGlzIHN0aWxsIC8sIHRoZSBoaXN0b3J5IGVudHJ5IGZvciAvIGlzCiAgICAgICAgLy8gcmVtb3ZlZCBmcm9tIHRoZSBoaXN0b3J5LiBDbGlja2luZyBiYWNrIHdpbGwgdGFrZSB5b3UgdG8gdGhlIHBhZ2UKICAgICAgICAvLyB5b3Ugd2VyZSBvbiBiZWZvcmUgLywgd2hpY2ggaXMgb2Z0ZW4gbm90IGV2ZW4gdGhlIGFwcCwgdGh1cyBraWxsaW5nCiAgICAgICAgLy8gdGhlIGJhY2sgYnV0dG9uLiBUaGF0J3Mgd2h5IHVwZGF0ZVVSTCBpcyBhbHdheXMgY29ycmVjdCBmb3IgYW4KICAgICAgICAvLyBhYm9ydGluZyB0cmFuc2l0aW9uIHRoYXQncyBub3QgdGhlIGluaXRpYWwgdHJhbnNpdGlvbgoKICAgICAgICB2YXIgcmVwbGFjZUFuZE5vdEFib3J0aW5nID0gdXJsTWV0aG9kID09PSAncmVwbGFjZScgJiYgIXRyYW5zaXRpb24uaXNDYXVzZWRCeUFib3J0aW5nVHJhbnNpdGlvbjsgLy8gYmVjYXVzZSBjYWxsaW5nIHJlZnJlc2ggY2F1c2VzIGFuIGFib3J0ZWQgdHJhbnNpdGlvbiwgdGhpcyBuZWVkcyB0byBiZQogICAgICAgIC8vIHNwZWNpYWwgY2FzZWQgLSBpZiB0aGUgaW5pdGlhbCB0cmFuc2l0aW9uIGlzIGEgcmVwbGFjZSB0cmFuc2l0aW9uLCB0aGUKICAgICAgICAvLyB1cmxNZXRob2Qgc2hvdWxkIGJlIGhvbm9yZWQgaGVyZS4KCiAgICAgICAgdmFyIGlzUXVlcnlQYXJhbXNSZWZyZXNoVHJhbnNpdGlvbiA9IHRyYW5zaXRpb24ucXVlcnlQYXJhbXNPbmx5ICYmIHVybE1ldGhvZCA9PT0gJ3JlcGxhY2UnOyAvLyBzYXkgeW91IGFyZSBhdCAvIGFuZCB5b3UgYSBgcmVwbGFjZVdpdGgoL2ZvbylgIGlzIGNhbGxlZC4gVGhlbiwgdGhhdAogICAgICAgIC8vIHRyYW5zaXRpb24gaXMgYWJvcnRlZCB3aXRoIGByZXBsYWNlV2l0aCgvYmFyKWAuIEF0IHRoZSBlbmQsIHdlIHNob3VsZAogICAgICAgIC8vIGVuZCB1cCB3aXRoIC9iYXIgcmVwbGFjaW5nIC8uIFdlIGFyZSByZXBsYWNpbmcgdGhlIHJlcGxhY2UuIFdlIG9ubHkKICAgICAgICAvLyB3aWxsIHJlcGxhY2UgdGhlIGluaXRpYWwgcm91dGUgaWYgYWxsIHN1YnNlcXVlbnQgYWJvcnRzIGFyZSBhbHNvCiAgICAgICAgLy8gcmVwbGFjZXMuIEhvd2V2ZXIsIHRoZXJlIGlzIHNvbWUgYW1iaWd1aXR5IGFyb3VuZCB0aGUgY29ycmVjdCBiZWhhdmlvcgogICAgICAgIC8vIGhlcmUuCgogICAgICAgIHZhciByZXBsYWNpbmdSZXBsYWNlID0gdXJsTWV0aG9kID09PSAncmVwbGFjZScgJiYgdHJhbnNpdGlvbi5pc0NhdXNlZEJ5QWJvcnRpbmdSZXBsYWNlVHJhbnNpdGlvbjsKCiAgICAgICAgaWYgKGluaXRpYWwgfHwgcmVwbGFjZUFuZE5vdEFib3J0aW5nIHx8IGlzUXVlcnlQYXJhbXNSZWZyZXNoVHJhbnNpdGlvbiB8fCByZXBsYWNpbmdSZXBsYWNlKSB7CiAgICAgICAgICB0aGlzLnJlcGxhY2VVUkwodXJsKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhpcy51cGRhdGVVUkwodXJsKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvOS5maW5hbGl6ZVF1ZXJ5UGFyYW1DaGFuZ2UgPSBmdW5jdGlvbiBmaW5hbGl6ZVF1ZXJ5UGFyYW1DaGFuZ2UocmVzb2x2ZWRIYW5kbGVycywgbmV3UXVlcnlQYXJhbXMsIHRyYW5zaXRpb24pIHsKICAgICAgLy8gV2UgZmlyZSBhIGZpbmFsaXplUXVlcnlQYXJhbUNoYW5nZSBldmVudCB3aGljaAogICAgICAvLyBnaXZlcyB0aGUgbmV3IHJvdXRlIGhpZXJhcmNoeSBhIGNoYW5jZSB0byB0ZWxsCiAgICAgIC8vIHVzIHdoaWNoIHF1ZXJ5IHBhcmFtcyBpdCdzIGNvbnN1bWluZyBhbmQgd2hhdAogICAgICAvLyB0aGVpciBmaW5hbCB2YWx1ZXMgYXJlLiBJZiBhIHF1ZXJ5IHBhcmFtIGlzCiAgICAgIC8vIG5vIGxvbmdlciBjb25zdW1lZCBpbiB0aGUgZmluYWwgcm91dGUgaGllcmFyY2h5LAogICAgICAvLyBpdHMgc2VyaWFsaXplZCBzZWdtZW50IHdpbGwgYmUgcmVtb3ZlZAogICAgICAvLyBmcm9tIHRoZSBVUkwuCiAgICAgIGZvciAodmFyIGsgaW4gbmV3UXVlcnlQYXJhbXMpIHsKICAgICAgICBpZiAobmV3UXVlcnlQYXJhbXMuaGFzT3duUHJvcGVydHkoaykgJiYgbmV3UXVlcnlQYXJhbXNba10gPT09IG51bGwpIHsKICAgICAgICAgIGRlbGV0ZSBuZXdRdWVyeVBhcmFtc1trXTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciBmaW5hbFF1ZXJ5UGFyYW1zQXJyYXkgPSBbXTsKICAgICAgdGhpcy50cmlnZ2VyRXZlbnQocmVzb2x2ZWRIYW5kbGVycywgdHJ1ZSwgJ2ZpbmFsaXplUXVlcnlQYXJhbUNoYW5nZScsIFtuZXdRdWVyeVBhcmFtcywgZmluYWxRdWVyeVBhcmFtc0FycmF5LCB0cmFuc2l0aW9uXSk7CgogICAgICBpZiAodHJhbnNpdGlvbikgewogICAgICAgIHRyYW5zaXRpb24uX3Zpc2libGVRdWVyeVBhcmFtcyA9IHt9OwogICAgICB9CgogICAgICB2YXIgZmluYWxRdWVyeVBhcmFtcyA9IHt9OwoKICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGZpbmFsUXVlcnlQYXJhbXNBcnJheS5sZW5ndGg7IGkgPCBsZW47ICsraSkgewogICAgICAgIHZhciBxcCA9IGZpbmFsUXVlcnlQYXJhbXNBcnJheVtpXTsKICAgICAgICBmaW5hbFF1ZXJ5UGFyYW1zW3FwLmtleV0gPSBxcC52YWx1ZTsKCiAgICAgICAgaWYgKHRyYW5zaXRpb24gJiYgcXAudmlzaWJsZSAhPT0gZmFsc2UpIHsKICAgICAgICAgIHRyYW5zaXRpb24uX3Zpc2libGVRdWVyeVBhcmFtc1txcC5rZXldID0gcXAudmFsdWU7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gZmluYWxRdWVyeVBhcmFtczsKICAgIH07CgogICAgX3Byb3RvOS50b1JlYWRPbmx5SW5mb3MgPSBmdW5jdGlvbiB0b1JlYWRPbmx5SW5mb3MobmV3VHJhbnNpdGlvbiwgbmV3U3RhdGUpIHsKICAgICAgdmFyIG9sZFJvdXRlSW5mb3MgPSB0aGlzLnN0YXRlLnJvdXRlSW5mb3M7CiAgICAgIHRoaXMuZnJvbUluZm9zKG5ld1RyYW5zaXRpb24sIG9sZFJvdXRlSW5mb3MpOwogICAgICB0aGlzLnRvSW5mb3MobmV3VHJhbnNpdGlvbiwgbmV3U3RhdGUucm91dGVJbmZvcyk7CiAgICAgIHRoaXMuX2xhc3RRdWVyeVBhcmFtcyA9IG5ld1N0YXRlLnF1ZXJ5UGFyYW1zOwogICAgfTsKCiAgICBfcHJvdG85LmZyb21JbmZvcyA9IGZ1bmN0aW9uIGZyb21JbmZvcyhuZXdUcmFuc2l0aW9uLCBvbGRSb3V0ZUluZm9zKSB7CiAgICAgIGlmIChuZXdUcmFuc2l0aW9uICE9PSB1bmRlZmluZWQgJiYgb2xkUm91dGVJbmZvcy5sZW5ndGggPiAwKSB7CiAgICAgICAgdmFyIGZyb21JbmZvcyA9IHRvUmVhZE9ubHlSb3V0ZUluZm8ob2xkUm91dGVJbmZvcywgKDAsIF9wb2x5ZmlsbHMuYXNzaWduKSh7fSwgdGhpcy5fbGFzdFF1ZXJ5UGFyYW1zKSwgdHJ1ZSk7CiAgICAgICAgbmV3VHJhbnNpdGlvbi5mcm9tID0gZnJvbUluZm9zW2Zyb21JbmZvcy5sZW5ndGggLSAxXSB8fCBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzkudG9JbmZvcyA9IGZ1bmN0aW9uIHRvSW5mb3MobmV3VHJhbnNpdGlvbiwgbmV3Um91dGVJbmZvcywgaW5jbHVkZUF0dHJpYnV0ZXMpIHsKICAgICAgaWYgKGluY2x1ZGVBdHRyaWJ1dGVzID09PSB2b2lkIDApIHsKICAgICAgICBpbmNsdWRlQXR0cmlidXRlcyA9IGZhbHNlOwogICAgICB9CgogICAgICBpZiAobmV3VHJhbnNpdGlvbiAhPT0gdW5kZWZpbmVkICYmIG5ld1JvdXRlSW5mb3MubGVuZ3RoID4gMCkgewogICAgICAgIHZhciB0b0luZm9zID0gdG9SZWFkT25seVJvdXRlSW5mbyhuZXdSb3V0ZUluZm9zLCAoMCwgX3BvbHlmaWxscy5hc3NpZ24pKHt9LCBuZXdUcmFuc2l0aW9uW1FVRVJZX1BBUkFNU19TWU1CT0xdKSwgaW5jbHVkZUF0dHJpYnV0ZXMpOwogICAgICAgIG5ld1RyYW5zaXRpb24udG8gPSB0b0luZm9zW3RvSW5mb3MubGVuZ3RoIC0gMV0gfHwgbnVsbDsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG85Lm5vdGlmeUV4aXN0aW5nSGFuZGxlcnMgPSBmdW5jdGlvbiBub3RpZnlFeGlzdGluZ0hhbmRsZXJzKG5ld1N0YXRlLCBuZXdUcmFuc2l0aW9uKSB7CiAgICAgIHZhciBvbGRSb3V0ZUluZm9zID0gdGhpcy5zdGF0ZS5yb3V0ZUluZm9zLAogICAgICAgICAgaSwKICAgICAgICAgIG9sZFJvdXRlSW5mb0xlbiwKICAgICAgICAgIG9sZEhhbmRsZXIsCiAgICAgICAgICBuZXdSb3V0ZUluZm87CiAgICAgIG9sZFJvdXRlSW5mb0xlbiA9IG9sZFJvdXRlSW5mb3MubGVuZ3RoOwoKICAgICAgZm9yIChpID0gMDsgaSA8IG9sZFJvdXRlSW5mb0xlbjsgaSsrKSB7CiAgICAgICAgb2xkSGFuZGxlciA9IG9sZFJvdXRlSW5mb3NbaV07CiAgICAgICAgbmV3Um91dGVJbmZvID0gbmV3U3RhdGUucm91dGVJbmZvc1tpXTsKCiAgICAgICAgaWYgKCFuZXdSb3V0ZUluZm8gfHwgb2xkSGFuZGxlci5uYW1lICE9PSBuZXdSb3V0ZUluZm8ubmFtZSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICBpZiAoIW5ld1JvdXRlSW5mby5pc1Jlc29sdmVkKSB7fQogICAgICB9CgogICAgICB0aGlzLnRyaWdnZXJFdmVudChvbGRSb3V0ZUluZm9zLCB0cnVlLCAnd2lsbFRyYW5zaXRpb24nLCBbbmV3VHJhbnNpdGlvbl0pOwogICAgICB0aGlzLnJvdXRlV2lsbENoYW5nZShuZXdUcmFuc2l0aW9uKTsKICAgICAgdGhpcy53aWxsVHJhbnNpdGlvbihvbGRSb3V0ZUluZm9zLCBuZXdTdGF0ZS5yb3V0ZUluZm9zLCBuZXdUcmFuc2l0aW9uKTsKICAgIH0KICAgIC8qKgogICAgICBDbGVhcnMgdGhlIGN1cnJlbnQgYW5kIHRhcmdldCByb3V0ZSByb3V0ZXMgYW5kIHRyaWdnZXJzIGV4aXQKICAgICAgb24gZWFjaCBvZiB0aGVtIHN0YXJ0aW5nIGF0IHRoZSBsZWFmIGFuZCB0cmF2ZXJzaW5nIHVwIHRocm91Z2gKICAgICAgaXRzIGFuY2VzdG9ycy4KICAgICovCiAgICA7CgogICAgX3Byb3RvOS5yZXNldCA9IGZ1bmN0aW9uIHJlc2V0KCkgewogICAgICBpZiAodGhpcy5zdGF0ZSkgewogICAgICAgIGZvckVhY2godGhpcy5zdGF0ZS5yb3V0ZUluZm9zLnNsaWNlKCkucmV2ZXJzZSgpLCBmdW5jdGlvbiAocm91dGVJbmZvKSB7CiAgICAgICAgICB2YXIgcm91dGUgPSByb3V0ZUluZm8ucm91dGU7CgogICAgICAgICAgaWYgKHJvdXRlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgaWYgKHJvdXRlLmV4aXQgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIHJvdXRlLmV4aXQoKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0pOwogICAgICB9CgogICAgICB0aGlzLm9sZFN0YXRlID0gdW5kZWZpbmVkOwogICAgICB0aGlzLnN0YXRlID0gbmV3IFRyYW5zaXRpb25TdGF0ZSgpOwogICAgICB0aGlzLmN1cnJlbnRSb3V0ZUluZm9zID0gdW5kZWZpbmVkOwogICAgfQogICAgLyoqCiAgICAgIGxldCBoYW5kbGVyID0gcm91dGVJbmZvLmhhbmRsZXI7CiAgICAgIFRoZSBlbnRyeSBwb2ludCBmb3IgaGFuZGxpbmcgYSBjaGFuZ2UgdG8gdGhlIFVSTCAodXN1YWxseQogICAgICB2aWEgdGhlIGJhY2sgYW5kIGZvcndhcmQgYnV0dG9uKS4KICAgICAgICAgUmV0dXJucyBhbiBBcnJheSBvZiBoYW5kbGVycyBhbmQgdGhlIHBhcmFtZXRlcnMgYXNzb2NpYXRlZAogICAgICB3aXRoIHRob3NlIHBhcmFtZXRlcnMuCiAgICAgICAgIEBwYXJhbSB7U3RyaW5nfSB1cmwgYSBVUkwgdG8gcHJvY2VzcwogICAgICAgICBAcmV0dXJuIHtBcnJheX0gYW4gQXJyYXkgb2YgYFtoYW5kbGVyLCBwYXJhbWV0ZXJdYCB0dXBsZXMKICAgICovCiAgICA7CgogICAgX3Byb3RvOS5oYW5kbGVVUkwgPSBmdW5jdGlvbiBoYW5kbGVVUkwodXJsKSB7CiAgICAgIC8vIFBlcmZvcm0gYSBVUkwtYmFzZWQgdHJhbnNpdGlvbiwgYnV0IGRvbid0IGNoYW5nZQogICAgICAvLyB0aGUgVVJMIGFmdGVyd2FyZCwgc2luY2UgaXQgYWxyZWFkeSBoYXBwZW5lZC4KICAgICAgaWYgKHVybC5jaGFyQXQoMCkgIT09ICcvJykgewogICAgICAgIHVybCA9ICcvJyArIHVybDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuZG9UcmFuc2l0aW9uKHVybCkubWV0aG9kKG51bGwpOwogICAgfQogICAgLyoqCiAgICAgIFRyYW5zaXRpb24gaW50byB0aGUgc3BlY2lmaWVkIG5hbWVkIHJvdXRlLgogICAgICAgICBJZiBuZWNlc3NhcnksIHRyaWdnZXIgdGhlIGV4aXQgY2FsbGJhY2sgb24gYW55IHJvdXRlcwogICAgICB0aGF0IGFyZSBubyBsb25nZXIgcmVwcmVzZW50ZWQgYnkgdGhlIHRhcmdldCByb3V0ZS4KICAgICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIHJvdXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90bzkudHJhbnNpdGlvblRvID0gZnVuY3Rpb24gdHJhbnNpdGlvblRvKG5hbWUpIHsKICAgICAgZm9yICh2YXIgX2xlbjMgPSBhcmd1bWVudHMubGVuZ3RoLCBjb250ZXh0cyA9IG5ldyBBcnJheShfbGVuMyA+IDEgPyBfbGVuMyAtIDEgOiAwKSwgX2tleTMgPSAxOyBfa2V5MyA8IF9sZW4zOyBfa2V5MysrKSB7CiAgICAgICAgY29udGV4dHNbX2tleTMgLSAxXSA9IGFyZ3VtZW50c1tfa2V5M107CiAgICAgIH0KCiAgICAgIGlmICh0eXBlb2YgbmFtZSA9PT0gJ29iamVjdCcpIHsKICAgICAgICBjb250ZXh0cy5wdXNoKG5hbWUpOwogICAgICAgIHJldHVybiB0aGlzLmRvVHJhbnNpdGlvbih1bmRlZmluZWQsIGNvbnRleHRzLCBmYWxzZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLmRvVHJhbnNpdGlvbihuYW1lLCBjb250ZXh0cyk7CiAgICB9OwoKICAgIF9wcm90bzkuaW50ZXJtZWRpYXRlVHJhbnNpdGlvblRvID0gZnVuY3Rpb24gaW50ZXJtZWRpYXRlVHJhbnNpdGlvblRvKG5hbWUpIHsKICAgICAgZm9yICh2YXIgX2xlbjQgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW40ID4gMSA/IF9sZW40IC0gMSA6IDApLCBfa2V5NCA9IDE7IF9rZXk0IDwgX2xlbjQ7IF9rZXk0KyspIHsKICAgICAgICBhcmdzW19rZXk0IC0gMV0gPSBhcmd1bWVudHNbX2tleTRdOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5kb1RyYW5zaXRpb24obmFtZSwgYXJncywgdHJ1ZSk7CiAgICB9OwoKICAgIF9wcm90bzkucmVmcmVzaCA9IGZ1bmN0aW9uIHJlZnJlc2gocGl2b3RSb3V0ZSkgewogICAgICB2YXIgcHJldmlvdXNUcmFuc2l0aW9uID0gdGhpcy5hY3RpdmVUcmFuc2l0aW9uOwogICAgICB2YXIgc3RhdGUgPSBwcmV2aW91c1RyYW5zaXRpb24gPyBwcmV2aW91c1RyYW5zaXRpb25bU1RBVEVfU1lNQk9MXSA6IHRoaXMuc3RhdGU7CiAgICAgIHZhciByb3V0ZUluZm9zID0gc3RhdGUucm91dGVJbmZvczsKCiAgICAgIGlmIChwaXZvdFJvdXRlID09PSB1bmRlZmluZWQpIHsKICAgICAgICBwaXZvdFJvdXRlID0gcm91dGVJbmZvc1swXS5yb3V0ZTsKICAgICAgfQoKICAgICAgX2xvZyh0aGlzLCAnU3RhcnRpbmcgYSByZWZyZXNoIHRyYW5zaXRpb24nKTsKCiAgICAgIHZhciBuYW1lID0gcm91dGVJbmZvc1tyb3V0ZUluZm9zLmxlbmd0aCAtIDFdLm5hbWU7CiAgICAgIHZhciBpbnRlbnQgPSBuZXcgTmFtZWRUcmFuc2l0aW9uSW50ZW50KHRoaXMsIG5hbWUsIHBpdm90Um91dGUsIFtdLCB0aGlzLl9jaGFuZ2VkUXVlcnlQYXJhbXMgfHwgc3RhdGUucXVlcnlQYXJhbXMpOwogICAgICB2YXIgbmV3VHJhbnNpdGlvbiA9IHRoaXMudHJhbnNpdGlvbkJ5SW50ZW50KGludGVudCwgZmFsc2UpOyAvLyBpZiB0aGUgcHJldmlvdXMgdHJhbnNpdGlvbiBpcyBhIHJlcGxhY2UgdHJhbnNpdGlvbiwgdGhhdCBuZWVkcyB0byBiZSBwcmVzZXJ2ZWQKCiAgICAgIGlmIChwcmV2aW91c1RyYW5zaXRpb24gJiYgcHJldmlvdXNUcmFuc2l0aW9uLnVybE1ldGhvZCA9PT0gJ3JlcGxhY2UnKSB7CiAgICAgICAgbmV3VHJhbnNpdGlvbi5tZXRob2QocHJldmlvdXNUcmFuc2l0aW9uLnVybE1ldGhvZCk7CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXdUcmFuc2l0aW9uOwogICAgfQogICAgLyoqCiAgICAgIElkZW50aWNhbCB0byBgdHJhbnNpdGlvblRvYCBleGNlcHQgdGhhdCB0aGUgY3VycmVudCBVUkwgd2lsbCBiZSByZXBsYWNlZAogICAgICBpZiBwb3NzaWJsZS4KICAgICAgICAgVGhpcyBtZXRob2QgaXMgaW50ZW5kZWQgcHJpbWFyaWx5IGZvciB1c2Ugd2l0aCBgcmVwbGFjZVN0YXRlYC4KICAgICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIHJvdXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90bzkucmVwbGFjZVdpdGggPSBmdW5jdGlvbiByZXBsYWNlV2l0aChuYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLmRvVHJhbnNpdGlvbihuYW1lKS5tZXRob2QoJ3JlcGxhY2UnKTsKICAgIH0KICAgIC8qKgogICAgICBUYWtlIGEgbmFtZWQgcm91dGUgYW5kIGNvbnRleHQgb2JqZWN0cyBhbmQgZ2VuZXJhdGUgYQogICAgICBVUkwuCiAgICAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSByb3V0ZSB0byBnZW5lcmF0ZQogICAgICAgIGEgVVJMIGZvcgogICAgICBAcGFyYW0gey4uLk9iamVjdH0gb2JqZWN0cyBhIGxpc3Qgb2Ygb2JqZWN0cyB0byBzZXJpYWxpemUKICAgICAgICAgQHJldHVybiB7U3RyaW5nfSBhIFVSTAogICAgKi8KICAgIDsKCiAgICBfcHJvdG85LmdlbmVyYXRlID0gZnVuY3Rpb24gZ2VuZXJhdGUocm91dGVOYW1lKSB7CiAgICAgIGZvciAodmFyIF9sZW41ID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuNSA+IDEgPyBfbGVuNSAtIDEgOiAwKSwgX2tleTUgPSAxOyBfa2V5NSA8IF9sZW41OyBfa2V5NSsrKSB7CiAgICAgICAgYXJnc1tfa2V5NSAtIDFdID0gYXJndW1lbnRzW19rZXk1XTsKICAgICAgfQoKICAgICAgdmFyIHBhcnRpdGlvbmVkQXJncyA9IGV4dHJhY3RRdWVyeVBhcmFtcyhhcmdzKSwKICAgICAgICAgIHN1cHBsaWVkUGFyYW1zID0gcGFydGl0aW9uZWRBcmdzWzBdLAogICAgICAgICAgcXVlcnlQYXJhbXMgPSBwYXJ0aXRpb25lZEFyZ3NbMV07IC8vIENvbnN0cnVjdCBhIFRyYW5zaXRpb25JbnRlbnQgd2l0aCB0aGUgcHJvdmlkZWQgcGFyYW1zCiAgICAgIC8vIGFuZCBhcHBseSBpdCB0byB0aGUgcHJlc2VudCBzdGF0ZSBvZiB0aGUgcm91dGVyLgoKICAgICAgdmFyIGludGVudCA9IG5ldyBOYW1lZFRyYW5zaXRpb25JbnRlbnQodGhpcywgcm91dGVOYW1lLCB1bmRlZmluZWQsIHN1cHBsaWVkUGFyYW1zKTsKICAgICAgdmFyIHN0YXRlID0gaW50ZW50LmFwcGx5VG9TdGF0ZSh0aGlzLnN0YXRlLCBmYWxzZSk7CiAgICAgIHZhciBwYXJhbXMgPSB7fTsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBzdGF0ZS5yb3V0ZUluZm9zLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgICAgdmFyIHJvdXRlSW5mbyA9IHN0YXRlLnJvdXRlSW5mb3NbaV07CiAgICAgICAgdmFyIHJvdXRlUGFyYW1zID0gcm91dGVJbmZvLnNlcmlhbGl6ZSgpOwogICAgICAgIG1lcmdlKHBhcmFtcywgcm91dGVQYXJhbXMpOwogICAgICB9CgogICAgICBwYXJhbXMucXVlcnlQYXJhbXMgPSBxdWVyeVBhcmFtczsKICAgICAgcmV0dXJuIHRoaXMucmVjb2duaXplci5nZW5lcmF0ZShyb3V0ZU5hbWUsIHBhcmFtcyk7CiAgICB9OwoKICAgIF9wcm90bzkuYXBwbHlJbnRlbnQgPSBmdW5jdGlvbiBhcHBseUludGVudChyb3V0ZU5hbWUsIGNvbnRleHRzKSB7CiAgICAgIHZhciBpbnRlbnQgPSBuZXcgTmFtZWRUcmFuc2l0aW9uSW50ZW50KHRoaXMsIHJvdXRlTmFtZSwgdW5kZWZpbmVkLCBjb250ZXh0cyk7CiAgICAgIHZhciBzdGF0ZSA9IHRoaXMuYWN0aXZlVHJhbnNpdGlvbiAmJiB0aGlzLmFjdGl2ZVRyYW5zaXRpb25bU1RBVEVfU1lNQk9MXSB8fCB0aGlzLnN0YXRlOwogICAgICByZXR1cm4gaW50ZW50LmFwcGx5VG9TdGF0ZShzdGF0ZSwgZmFsc2UpOwogICAgfTsKCiAgICBfcHJvdG85LmlzQWN0aXZlSW50ZW50ID0gZnVuY3Rpb24gaXNBY3RpdmVJbnRlbnQocm91dGVOYW1lLCBjb250ZXh0cywgcXVlcnlQYXJhbXMsIF9zdGF0ZSkgewogICAgICB2YXIgc3RhdGUgPSBfc3RhdGUgfHwgdGhpcy5zdGF0ZSwKICAgICAgICAgIHRhcmdldFJvdXRlSW5mb3MgPSBzdGF0ZS5yb3V0ZUluZm9zLAogICAgICAgICAgcm91dGVJbmZvLAogICAgICAgICAgbGVuOwoKICAgICAgaWYgKCF0YXJnZXRSb3V0ZUluZm9zLmxlbmd0aCkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgdmFyIHRhcmdldEhhbmRsZXIgPSB0YXJnZXRSb3V0ZUluZm9zW3RhcmdldFJvdXRlSW5mb3MubGVuZ3RoIC0gMV0ubmFtZTsKICAgICAgdmFyIHJlY29nSGFuZGxlcnMgPSB0aGlzLnJlY29nbml6ZXIuaGFuZGxlcnNGb3IodGFyZ2V0SGFuZGxlcik7CiAgICAgIHZhciBpbmRleCA9IDA7CgogICAgICBmb3IgKGxlbiA9IHJlY29nSGFuZGxlcnMubGVuZ3RoOyBpbmRleCA8IGxlbjsgKytpbmRleCkgewogICAgICAgIHJvdXRlSW5mbyA9IHRhcmdldFJvdXRlSW5mb3NbaW5kZXhdOwoKICAgICAgICBpZiAocm91dGVJbmZvLm5hbWUgPT09IHJvdXRlTmFtZSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoaW5kZXggPT09IHJlY29nSGFuZGxlcnMubGVuZ3RoKSB7CiAgICAgICAgLy8gVGhlIHByb3ZpZGVkIHJvdXRlIG5hbWUgaXNuJ3QgZXZlbiBpbiB0aGUgcm91dGUgaGllcmFyY2h5LgogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgdmFyIHRlc3RTdGF0ZSA9IG5ldyBUcmFuc2l0aW9uU3RhdGUoKTsKICAgICAgdGVzdFN0YXRlLnJvdXRlSW5mb3MgPSB0YXJnZXRSb3V0ZUluZm9zLnNsaWNlKDAsIGluZGV4ICsgMSk7CiAgICAgIHJlY29nSGFuZGxlcnMgPSByZWNvZ0hhbmRsZXJzLnNsaWNlKDAsIGluZGV4ICsgMSk7CiAgICAgIHZhciBpbnRlbnQgPSBuZXcgTmFtZWRUcmFuc2l0aW9uSW50ZW50KHRoaXMsIHRhcmdldEhhbmRsZXIsIHVuZGVmaW5lZCwgY29udGV4dHMpOwogICAgICB2YXIgbmV3U3RhdGUgPSBpbnRlbnQuYXBwbHlUb0hhbmRsZXJzKHRlc3RTdGF0ZSwgcmVjb2dIYW5kbGVycywgdGFyZ2V0SGFuZGxlciwgdHJ1ZSwgdHJ1ZSk7CiAgICAgIHZhciByb3V0ZXNFcXVhbCA9IHJvdXRlSW5mb3NFcXVhbChuZXdTdGF0ZS5yb3V0ZUluZm9zLCB0ZXN0U3RhdGUucm91dGVJbmZvcyk7CgogICAgICBpZiAoIXF1ZXJ5UGFyYW1zIHx8ICFyb3V0ZXNFcXVhbCkgewogICAgICAgIHJldHVybiByb3V0ZXNFcXVhbDsKICAgICAgfSAvLyBHZXQgYSBoYXNoIG9mIFFQcyB0aGF0IHdpbGwgc3RpbGwgYmUgYWN0aXZlIG9uIG5ldyByb3V0ZQoKCiAgICAgIHZhciBhY3RpdmVRUHNPbk5ld0hhbmRsZXIgPSB7fTsKICAgICAgbWVyZ2UoYWN0aXZlUVBzT25OZXdIYW5kbGVyLCBxdWVyeVBhcmFtcyk7CiAgICAgIHZhciBhY3RpdmVRdWVyeVBhcmFtcyA9IHN0YXRlLnF1ZXJ5UGFyYW1zOwoKICAgICAgZm9yICh2YXIga2V5IGluIGFjdGl2ZVF1ZXJ5UGFyYW1zKSB7CiAgICAgICAgaWYgKGFjdGl2ZVF1ZXJ5UGFyYW1zLmhhc093blByb3BlcnR5KGtleSkgJiYgYWN0aXZlUVBzT25OZXdIYW5kbGVyLmhhc093blByb3BlcnR5KGtleSkpIHsKICAgICAgICAgIGFjdGl2ZVFQc09uTmV3SGFuZGxlcltrZXldID0gYWN0aXZlUXVlcnlQYXJhbXNba2V5XTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiByb3V0ZXNFcXVhbCAmJiAhZ2V0Q2hhbmdlbGlzdChhY3RpdmVRUHNPbk5ld0hhbmRsZXIsIHF1ZXJ5UGFyYW1zKTsKICAgIH07CgogICAgX3Byb3RvOS5pc0FjdGl2ZSA9IGZ1bmN0aW9uIGlzQWN0aXZlKHJvdXRlTmFtZSkgewogICAgICBmb3IgKHZhciBfbGVuNiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjYgPiAxID8gX2xlbjYgLSAxIDogMCksIF9rZXk2ID0gMTsgX2tleTYgPCBfbGVuNjsgX2tleTYrKykgewogICAgICAgIGFyZ3NbX2tleTYgLSAxXSA9IGFyZ3VtZW50c1tfa2V5Nl07CiAgICAgIH0KCiAgICAgIHZhciBwYXJ0aXRpb25lZEFyZ3MgPSBleHRyYWN0UXVlcnlQYXJhbXMoYXJncyk7CiAgICAgIHJldHVybiB0aGlzLmlzQWN0aXZlSW50ZW50KHJvdXRlTmFtZSwgcGFydGl0aW9uZWRBcmdzWzBdLCBwYXJ0aXRpb25lZEFyZ3NbMV0pOwogICAgfTsKCiAgICBfcHJvdG85LnRyaWdnZXIgPSBmdW5jdGlvbiB0cmlnZ2VyKG5hbWUpIHsKICAgICAgZm9yICh2YXIgX2xlbjcgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gbmV3IEFycmF5KF9sZW43ID4gMSA/IF9sZW43IC0gMSA6IDApLCBfa2V5NyA9IDE7IF9rZXk3IDwgX2xlbjc7IF9rZXk3KyspIHsKICAgICAgICBhcmdzW19rZXk3IC0gMV0gPSBhcmd1bWVudHNbX2tleTddOwogICAgICB9CgogICAgICB0aGlzLnRyaWdnZXJFdmVudCh0aGlzLmN1cnJlbnRSb3V0ZUluZm9zLCBmYWxzZSwgbmFtZSwgYXJncyk7CiAgICB9OwoKICAgIHJldHVybiBSb3V0ZXI7CiAgfSgpOwoKICBmdW5jdGlvbiByb3V0ZUluZm9zRXF1YWwocm91dGVJbmZvcywgb3RoZXJSb3V0ZUluZm9zKSB7CiAgICBpZiAocm91dGVJbmZvcy5sZW5ndGggIT09IG90aGVyUm91dGVJbmZvcy5sZW5ndGgpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSByb3V0ZUluZm9zLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgIGlmIChyb3V0ZUluZm9zW2ldICE9PSBvdGhlclJvdXRlSW5mb3NbaV0pIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKICB9CgogIGZ1bmN0aW9uIHJvdXRlSW5mb3NTYW1lRXhjZXB0UXVlcnlQYXJhbXMocm91dGVJbmZvcywgb3RoZXJSb3V0ZUluZm9zKSB7CiAgICBpZiAocm91dGVJbmZvcy5sZW5ndGggIT09IG90aGVyUm91dGVJbmZvcy5sZW5ndGgpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSByb3V0ZUluZm9zLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgIGlmIChyb3V0ZUluZm9zW2ldLm5hbWUgIT09IG90aGVyUm91dGVJbmZvc1tpXS5uYW1lKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CgogICAgICBpZiAoIXBhcmFtc0VxdWFsKHJvdXRlSW5mb3NbaV0ucGFyYW1zLCBvdGhlclJvdXRlSW5mb3NbaV0ucGFyYW1zKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiB0cnVlOwogIH0KCiAgZnVuY3Rpb24gcGFyYW1zRXF1YWwocGFyYW1zLCBvdGhlclBhcmFtcykgewogICAgaWYgKCFwYXJhbXMgJiYgIW90aGVyUGFyYW1zKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSBlbHNlIGlmICghcGFyYW1zICYmICEhb3RoZXJQYXJhbXMgfHwgISFwYXJhbXMgJiYgIW90aGVyUGFyYW1zKSB7CiAgICAgIC8vIG9uZSBpcyBmYWxzeSBidXQgb3RoZXIgaXMgbm90OwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhwYXJhbXMpOwogICAgdmFyIG90aGVyS2V5cyA9IE9iamVjdC5rZXlzKG90aGVyUGFyYW1zKTsKCiAgICBpZiAoa2V5cy5sZW5ndGggIT09IG90aGVyS2V5cy5sZW5ndGgpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBrZXlzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgIHZhciBrZXkgPSBrZXlzW2ldOwoKICAgICAgaWYgKHBhcmFtc1trZXldICE9PSBvdGhlclBhcmFtc1trZXldKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIHRydWU7CiAgfQoKICB2YXIgX2RlZmF1bHQgPSBSb3V0ZXI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKZGVmaW5lKCJyc3ZwIiwgWyJleHBvcnRzIiwgImVtYmVyLWJhYmVsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2VtYmVyQmFiZWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmFzYXAgPSBhc2FwOwogIF9leHBvcnRzLmFsbCA9IGFsbCQxOwogIF9leHBvcnRzLmFsbFNldHRsZWQgPSBhbGxTZXR0bGVkOwogIF9leHBvcnRzLnJhY2UgPSByYWNlJDE7CiAgX2V4cG9ydHMuaGFzaCA9IGhhc2g7CiAgX2V4cG9ydHMuaGFzaFNldHRsZWQgPSBoYXNoU2V0dGxlZDsKICBfZXhwb3J0cy5yZXRocm93ID0gcmV0aHJvdzsKICBfZXhwb3J0cy5kZWZlciA9IGRlZmVyOwogIF9leHBvcnRzLmRlbm9kZWlmeSA9IGRlbm9kZWlmeTsKICBfZXhwb3J0cy5jb25maWd1cmUgPSBjb25maWd1cmU7CiAgX2V4cG9ydHMub24gPSBvbjsKICBfZXhwb3J0cy5vZmYgPSBvZmY7CiAgX2V4cG9ydHMucmVzb2x2ZSA9IHJlc29sdmUkMjsKICBfZXhwb3J0cy5yZWplY3QgPSByZWplY3QkMjsKICBfZXhwb3J0cy5tYXAgPSBtYXA7CiAgX2V4cG9ydHMuZmlsdGVyID0gZmlsdGVyOwogIF9leHBvcnRzLmFzeW5jID0gX2V4cG9ydHMuRXZlbnRUYXJnZXQgPSBfZXhwb3J0cy5Qcm9taXNlID0gX2V4cG9ydHMuY2FzdCA9IF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIGZ1bmN0aW9uIGNhbGxiYWNrc0ZvcihvYmplY3QpIHsKICAgIHZhciBjYWxsYmFja3MgPSBvYmplY3QuX3Byb21pc2VDYWxsYmFja3M7CgogICAgaWYgKCFjYWxsYmFja3MpIHsKICAgICAgY2FsbGJhY2tzID0gb2JqZWN0Ll9wcm9taXNlQ2FsbGJhY2tzID0ge307CiAgICB9CgogICAgcmV0dXJuIGNhbGxiYWNrczsKICB9CiAgLyoqCiAgICBAY2xhc3MgRXZlbnRUYXJnZXQKICAgIEBmb3IgcnN2cAogICAgQHB1YmxpYwogICovCgoKICB2YXIgRXZlbnRUYXJnZXQgPSB7CiAgICAvKioKICAgICAgYEV2ZW50VGFyZ2V0Lm1peGluYCBleHRlbmRzIGFuIG9iamVjdCB3aXRoIEV2ZW50VGFyZ2V0IG1ldGhvZHMuIEZvcgogICAgICBFeGFtcGxlOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgRXZlbnRUYXJnZXQgZnJvbSAncnN2cCc7CiAgICAgICBsZXQgb2JqZWN0ID0ge307CiAgICAgICBFdmVudFRhcmdldC5taXhpbihvYmplY3QpOwogICAgICAgb2JqZWN0Lm9uKCdmaW5pc2hlZCcsIGZ1bmN0aW9uKGV2ZW50KSB7CiAgICAgICAgLy8gaGFuZGxlIGV2ZW50CiAgICAgIH0pOwogICAgICAgb2JqZWN0LnRyaWdnZXIoJ2ZpbmlzaGVkJywgeyBkZXRhaWw6IHZhbHVlIH0pOwogICAgICBgYGAKICAgICAgIGBFdmVudFRhcmdldC5taXhpbmAgYWxzbyB3b3JrcyB3aXRoIHByb3RvdHlwZXM6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGltcG9ydCBFdmVudFRhcmdldCBmcm9tICdyc3ZwJzsKICAgICAgIGxldCBQZXJzb24gPSBmdW5jdGlvbigpIHt9OwogICAgICBFdmVudFRhcmdldC5taXhpbihQZXJzb24ucHJvdG90eXBlKTsKICAgICAgIGxldCB5ZWh1ZGEgPSBuZXcgUGVyc29uKCk7CiAgICAgIGxldCB0b20gPSBuZXcgUGVyc29uKCk7CiAgICAgICB5ZWh1ZGEub24oJ3Bva2UnLCBmdW5jdGlvbihldmVudCkgewogICAgICAgIGNvbnNvbGUubG9nKCdZZWh1ZGEgc2F5cyBPVycpOwogICAgICB9KTsKICAgICAgIHRvbS5vbigncG9rZScsIGZ1bmN0aW9uKGV2ZW50KSB7CiAgICAgICAgY29uc29sZS5sb2coJ1RvbSBzYXlzIE9XJyk7CiAgICAgIH0pOwogICAgICAgeWVodWRhLnRyaWdnZXIoJ3Bva2UnKTsKICAgICAgdG9tLnRyaWdnZXIoJ3Bva2UnKTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIG1peGluCiAgICAgIEBmb3IgcnN2cAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge09iamVjdH0gb2JqZWN0IG9iamVjdCB0byBleHRlbmQgd2l0aCBFdmVudFRhcmdldCBtZXRob2RzCiAgICAqLwogICAgbWl4aW46IGZ1bmN0aW9uIG1peGluKG9iamVjdCkgewogICAgICBvYmplY3Qub24gPSB0aGlzLm9uOwogICAgICBvYmplY3Qub2ZmID0gdGhpcy5vZmY7CiAgICAgIG9iamVjdC50cmlnZ2VyID0gdGhpcy50cmlnZ2VyOwogICAgICBvYmplY3QuX3Byb21pc2VDYWxsYmFja3MgPSB1bmRlZmluZWQ7CiAgICAgIHJldHVybiBvYmplY3Q7CiAgICB9LAoKICAgIC8qKgogICAgICBSZWdpc3RlcnMgYSBjYWxsYmFjayB0byBiZSBleGVjdXRlZCB3aGVuIGBldmVudE5hbWVgIGlzIHRyaWdnZXJlZAogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBvYmplY3Qub24oJ2V2ZW50JywgZnVuY3Rpb24oZXZlbnRJbmZvKXsKICAgICAgICAvLyBoYW5kbGUgdGhlIGV2ZW50CiAgICAgIH0pOwogICAgICAgb2JqZWN0LnRyaWdnZXIoJ2V2ZW50Jyk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBvbgogICAgICBAZm9yIEV2ZW50VGFyZ2V0CiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBldmVudE5hbWUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gbGlzdGVuIGZvcgogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgdHJpZ2dlcmVkLgogICAgKi8KICAgIG9uOiBmdW5jdGlvbiBvbihldmVudE5hbWUsIGNhbGxiYWNrKSB7CiAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09ICdmdW5jdGlvbicpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYWxsYmFjayBtdXN0IGJlIGEgZnVuY3Rpb24nKTsKICAgICAgfQoKICAgICAgdmFyIGFsbENhbGxiYWNrcyA9IGNhbGxiYWNrc0Zvcih0aGlzKTsKICAgICAgdmFyIGNhbGxiYWNrcyA9IGFsbENhbGxiYWNrc1tldmVudE5hbWVdOwoKICAgICAgaWYgKCFjYWxsYmFja3MpIHsKICAgICAgICBjYWxsYmFja3MgPSBhbGxDYWxsYmFja3NbZXZlbnROYW1lXSA9IFtdOwogICAgICB9CgogICAgICBpZiAoY2FsbGJhY2tzLmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkgewogICAgICAgIGNhbGxiYWNrcy5wdXNoKGNhbGxiYWNrKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgWW91IGNhbiB1c2UgYG9mZmAgdG8gc3RvcCBmaXJpbmcgYSBwYXJ0aWN1bGFyIGNhbGxiYWNrIGZvciBhbiBldmVudDoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgZnVuY3Rpb24gZG9TdHVmZigpIHsgLy8gZG8gc3R1ZmYhIH0KICAgICAgb2JqZWN0Lm9uKCdzdHVmZicsIGRvU3R1ZmYpOwogICAgICAgb2JqZWN0LnRyaWdnZXIoJ3N0dWZmJyk7IC8vIGRvU3R1ZmYgd2lsbCBiZSBjYWxsZWQKICAgICAgIC8vIFVucmVnaXN0ZXIgT05MWSB0aGUgZG9TdHVmZiBjYWxsYmFjawogICAgICBvYmplY3Qub2ZmKCdzdHVmZicsIGRvU3R1ZmYpOwogICAgICBvYmplY3QudHJpZ2dlcignc3R1ZmYnKTsgLy8gZG9TdHVmZiB3aWxsIE5PVCBiZSBjYWxsZWQKICAgICAgYGBgCiAgICAgICBJZiB5b3UgZG9uJ3QgcGFzcyBhIGBjYWxsYmFja2AgYXJndW1lbnQgdG8gYG9mZmAsIEFMTCBjYWxsYmFja3MgZm9yIHRoZQogICAgICBldmVudCB3aWxsIG5vdCBiZSBleGVjdXRlZCB3aGVuIHRoZSBldmVudCBmaXJlcy4gRm9yIGV4YW1wbGU6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBjYWxsYmFjazEgPSBmdW5jdGlvbigpe307CiAgICAgIGxldCBjYWxsYmFjazIgPSBmdW5jdGlvbigpe307CiAgICAgICBvYmplY3Qub24oJ3N0dWZmJywgY2FsbGJhY2sxKTsKICAgICAgb2JqZWN0Lm9uKCdzdHVmZicsIGNhbGxiYWNrMik7CiAgICAgICBvYmplY3QudHJpZ2dlcignc3R1ZmYnKTsgLy8gY2FsbGJhY2sxIGFuZCBjYWxsYmFjazIgd2lsbCBiZSBleGVjdXRlZC4KICAgICAgIG9iamVjdC5vZmYoJ3N0dWZmJyk7CiAgICAgIG9iamVjdC50cmlnZ2VyKCdzdHVmZicpOyAvLyBjYWxsYmFjazEgYW5kIGNhbGxiYWNrMiB3aWxsIG5vdCBiZSBleGVjdXRlZCEKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIG9mZgogICAgICBAZm9yIHJzdnAKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZSBldmVudCB0byBzdG9wIGxpc3RlbmluZyB0bwogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBbY2FsbGJhY2tdIG9wdGlvbmFsIGFyZ3VtZW50LiBJZiBnaXZlbiwgb25seSB0aGUgZnVuY3Rpb24KICAgICAgZ2l2ZW4gd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIGV2ZW50J3MgY2FsbGJhY2sgcXVldWUuIElmIG5vIGBjYWxsYmFja2AKICAgICAgYXJndW1lbnQgaXMgZ2l2ZW4sIGFsbCBjYWxsYmFja3Mgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIGV2ZW50J3MgY2FsbGJhY2sKICAgICAgcXVldWUuCiAgICAqLwogICAgb2ZmOiBmdW5jdGlvbiBvZmYoZXZlbnROYW1lLCBjYWxsYmFjaykgewogICAgICB2YXIgYWxsQ2FsbGJhY2tzID0gY2FsbGJhY2tzRm9yKHRoaXMpOwoKICAgICAgaWYgKCFjYWxsYmFjaykgewogICAgICAgIGFsbENhbGxiYWNrc1tldmVudE5hbWVdID0gW107CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgY2FsbGJhY2tzID0gYWxsQ2FsbGJhY2tzW2V2ZW50TmFtZV07CiAgICAgIHZhciBpbmRleCA9IGNhbGxiYWNrcy5pbmRleE9mKGNhbGxiYWNrKTsKCiAgICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGluZGV4LCAxKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgVXNlIGB0cmlnZ2VyYCB0byBmaXJlIGN1c3RvbSBldmVudHMuIEZvciBleGFtcGxlOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBvYmplY3Qub24oJ2ZvbycsIGZ1bmN0aW9uKCl7CiAgICAgICAgY29uc29sZS5sb2coJ2ZvbyBldmVudCBoYXBwZW5lZCEnKTsKICAgICAgfSk7CiAgICAgIG9iamVjdC50cmlnZ2VyKCdmb28nKTsKICAgICAgLy8gJ2ZvbyBldmVudCBoYXBwZW5lZCEnIGxvZ2dlZCB0byB0aGUgY29uc29sZQogICAgICBgYGAKICAgICAgIFlvdSBjYW4gYWxzbyBwYXNzIGEgdmFsdWUgYXMgYSBzZWNvbmQgYXJndW1lbnQgdG8gYHRyaWdnZXJgIHRoYXQgd2lsbCBiZQogICAgICBwYXNzZWQgYXMgYW4gYXJndW1lbnQgdG8gYWxsIGV2ZW50IGxpc3RlbmVycyBmb3IgdGhlIGV2ZW50OgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBvYmplY3Qub24oJ2ZvbycsIGZ1bmN0aW9uKHZhbHVlKXsKICAgICAgICBjb25zb2xlLmxvZyh2YWx1ZS5uYW1lKTsKICAgICAgfSk7CiAgICAgICBvYmplY3QudHJpZ2dlcignZm9vJywgeyBuYW1lOiAnYmFyJyB9KTsKICAgICAgLy8gJ2JhcicgbG9nZ2VkIHRvIHRoZSBjb25zb2xlCiAgICAgIGBgYAogICAgICAgQG1ldGhvZCB0cmlnZ2VyCiAgICAgIEBmb3IgcnN2cAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGJlIHRyaWdnZXJlZAogICAgICBAcGFyYW0geyp9IFtvcHRpb25zXSBvcHRpb25hbCB2YWx1ZSB0byBiZSBwYXNzZWQgdG8gYW55IGV2ZW50IGhhbmRsZXJzIGZvcgogICAgICB0aGUgZ2l2ZW4gYGV2ZW50TmFtZWAKICAgICovCiAgICB0cmlnZ2VyOiBmdW5jdGlvbiB0cmlnZ2VyKGV2ZW50TmFtZSwgb3B0aW9ucywgbGFiZWwpIHsKICAgICAgdmFyIGFsbENhbGxiYWNrcyA9IGNhbGxiYWNrc0Zvcih0aGlzKTsKICAgICAgdmFyIGNhbGxiYWNrcyA9IGFsbENhbGxiYWNrc1tldmVudE5hbWVdOwoKICAgICAgaWYgKGNhbGxiYWNrcykgewogICAgICAgIC8vIERvbid0IGNhY2hlIHRoZSBjYWxsYmFja3MubGVuZ3RoIHNpbmNlIGl0IG1heSBncm93CiAgICAgICAgdmFyIGNhbGxiYWNrOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNhbGxiYWNrcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgY2FsbGJhY2sgPSBjYWxsYmFja3NbaV07CiAgICAgICAgICBjYWxsYmFjayhvcHRpb25zLCBsYWJlbCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfTsKICBfZXhwb3J0cy5FdmVudFRhcmdldCA9IEV2ZW50VGFyZ2V0OwogIHZhciBjb25maWcgPSB7CiAgICBpbnN0cnVtZW50OiBmYWxzZQogIH07CiAgRXZlbnRUYXJnZXRbJ21peGluJ10oY29uZmlnKTsKCiAgZnVuY3Rpb24gY29uZmlndXJlKG5hbWUsIHZhbHVlKSB7CiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgewogICAgICBjb25maWdbbmFtZV0gPSB2YWx1ZTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBjb25maWdbbmFtZV07CiAgICB9CiAgfQoKICB2YXIgcXVldWUgPSBbXTsKCiAgZnVuY3Rpb24gc2NoZWR1bGVGbHVzaCgpIHsKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgewogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHF1ZXVlLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGVudHJ5ID0gcXVldWVbaV07CiAgICAgICAgdmFyIHBheWxvYWQgPSBlbnRyeS5wYXlsb2FkOwogICAgICAgIHBheWxvYWQuZ3VpZCA9IHBheWxvYWQua2V5ICsgcGF5bG9hZC5pZDsKICAgICAgICBwYXlsb2FkLmNoaWxkR3VpZCA9IHBheWxvYWQua2V5ICsgcGF5bG9hZC5jaGlsZElkOwoKICAgICAgICBpZiAocGF5bG9hZC5lcnJvcikgewogICAgICAgICAgcGF5bG9hZC5zdGFjayA9IHBheWxvYWQuZXJyb3Iuc3RhY2s7CiAgICAgICAgfQoKICAgICAgICBjb25maWdbJ3RyaWdnZXInXShlbnRyeS5uYW1lLCBlbnRyeS5wYXlsb2FkKTsKICAgICAgfQoKICAgICAgcXVldWUubGVuZ3RoID0gMDsKICAgIH0sIDUwKTsKICB9CgogIGZ1bmN0aW9uIGluc3RydW1lbnQoZXZlbnROYW1lLCBwcm9taXNlLCBjaGlsZCkgewogICAgaWYgKDEgPT09IHF1ZXVlLnB1c2goewogICAgICBuYW1lOiBldmVudE5hbWUsCiAgICAgIHBheWxvYWQ6IHsKICAgICAgICBrZXk6IHByb21pc2UuX2d1aWRLZXksCiAgICAgICAgaWQ6IHByb21pc2UuX2lkLAogICAgICAgIGV2ZW50TmFtZTogZXZlbnROYW1lLAogICAgICAgIGRldGFpbDogcHJvbWlzZS5fcmVzdWx0LAogICAgICAgIGNoaWxkSWQ6IGNoaWxkICYmIGNoaWxkLl9pZCwKICAgICAgICBsYWJlbDogcHJvbWlzZS5fbGFiZWwsCiAgICAgICAgdGltZVN0YW1wOiBEYXRlLm5vdygpLAogICAgICAgIGVycm9yOiBjb25maWdbImluc3RydW1lbnQtd2l0aC1zdGFjayJdID8gbmV3IEVycm9yKHByb21pc2UuX2xhYmVsKSA6IG51bGwKICAgICAgfQogICAgfSkpIHsKICAgICAgc2NoZWR1bGVGbHVzaCgpOwogICAgfQogIH0KICAvKioKICAgIGBQcm9taXNlLnJlc29sdmVgIHJldHVybnMgYSBwcm9taXNlIHRoYXQgd2lsbCBiZWNvbWUgcmVzb2x2ZWQgd2l0aCB0aGUKICAgIHBhc3NlZCBgdmFsdWVgLiBJdCBpcyBzaG9ydGhhbmQgZm9yIHRoZSBmb2xsb3dpbmc6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXsKICAgICAgcmVzb2x2ZSgxKTsKICAgIH0pOwogIAogICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXsKICAgICAgLy8gdmFsdWUgPT09IDEKICAgIH0pOwogICAgYGBgCiAgCiAgICBJbnN0ZWFkIG9mIHdyaXRpbmcgdGhlIGFib3ZlLCB5b3VyIGNvZGUgbm93IHNpbXBseSBiZWNvbWVzIHRoZSBmb2xsb3dpbmc6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlID0gUlNWUC5Qcm9taXNlLnJlc29sdmUoMSk7CiAgCiAgICBwcm9taXNlLnRoZW4oZnVuY3Rpb24odmFsdWUpewogICAgICAvLyB2YWx1ZSA9PT0gMQogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgcmVzb2x2ZQogICAgQGZvciBQcm9taXNlCiAgICBAc3RhdGljCiAgICBAcGFyYW0geyp9IG9iamVjdCB2YWx1ZSB0aGF0IHRoZSByZXR1cm5lZCBwcm9taXNlIHdpbGwgYmUgcmVzb2x2ZWQgd2l0aAogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGZvciBpZGVudGlmeWluZyB0aGUgcmV0dXJuZWQgcHJvbWlzZS4KICAgIFVzZWZ1bCBmb3IgdG9vbGluZy4KICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IHdpbGwgYmVjb21lIGZ1bGZpbGxlZCB3aXRoIHRoZSBnaXZlbgogICAgYHZhbHVlYAogICovCgoKICBmdW5jdGlvbiByZXNvbHZlJCQxKG9iamVjdCwgbGFiZWwpIHsKICAgIC8qanNoaW50IHZhbGlkdGhpczp0cnVlICovCiAgICB2YXIgQ29uc3RydWN0b3IgPSB0aGlzOwoKICAgIGlmIChvYmplY3QgJiYgdHlwZW9mIG9iamVjdCA9PT0gJ29iamVjdCcgJiYgb2JqZWN0LmNvbnN0cnVjdG9yID09PSBDb25zdHJ1Y3RvcikgewogICAgICByZXR1cm4gb2JqZWN0OwogICAgfQoKICAgIHZhciBwcm9taXNlID0gbmV3IENvbnN0cnVjdG9yKG5vb3AsIGxhYmVsKTsKICAgIHJlc29sdmUkMShwcm9taXNlLCBvYmplY3QpOwogICAgcmV0dXJuIHByb21pc2U7CiAgfQoKICBmdW5jdGlvbiB3aXRoT3duUHJvbWlzZSgpIHsKICAgIHJldHVybiBuZXcgVHlwZUVycm9yKCdBIHByb21pc2VzIGNhbGxiYWNrIGNhbm5vdCByZXR1cm4gdGhhdCBzYW1lIHByb21pc2UuJyk7CiAgfQoKICBmdW5jdGlvbiBvYmplY3RPckZ1bmN0aW9uKHgpIHsKICAgIHZhciB0eXBlID0gdHlwZW9mIHg7CiAgICByZXR1cm4geCAhPT0gbnVsbCAmJiAodHlwZSA9PT0gJ29iamVjdCcgfHwgdHlwZSA9PT0gJ2Z1bmN0aW9uJyk7CiAgfQoKICBmdW5jdGlvbiBub29wKCkge30KCiAgdmFyIFBFTkRJTkcgPSB2b2lkIDA7CiAgdmFyIEZVTEZJTExFRCA9IDE7CiAgdmFyIFJFSkVDVEVEID0gMjsKCiAgZnVuY3Rpb24gdHJ5VGhlbih0aGVuJCQxLCB2YWx1ZSwgZnVsZmlsbG1lbnRIYW5kbGVyLCByZWplY3Rpb25IYW5kbGVyKSB7CiAgICB0cnkgewogICAgICB0aGVuJCQxLmNhbGwodmFsdWUsIGZ1bGZpbGxtZW50SGFuZGxlciwgcmVqZWN0aW9uSGFuZGxlcik7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHJldHVybiBlOwogICAgfQogIH0KCiAgZnVuY3Rpb24gaGFuZGxlRm9yZWlnblRoZW5hYmxlKHByb21pc2UsIHRoZW5hYmxlLCB0aGVuJCQxKSB7CiAgICBjb25maWcuYXN5bmMoZnVuY3Rpb24gKHByb21pc2UpIHsKICAgICAgdmFyIHNlYWxlZCA9IGZhbHNlOwogICAgICB2YXIgZXJyb3IgPSB0cnlUaGVuKHRoZW4kJDEsIHRoZW5hYmxlLCBmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgICBpZiAoc2VhbGVkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBzZWFsZWQgPSB0cnVlOwoKICAgICAgICBpZiAodGhlbmFibGUgPT09IHZhbHVlKSB7CiAgICAgICAgICBmdWxmaWxsKHByb21pc2UsIHZhbHVlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzb2x2ZSQxKHByb21pc2UsIHZhbHVlKTsKICAgICAgICB9CiAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICBpZiAoc2VhbGVkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBzZWFsZWQgPSB0cnVlOwogICAgICAgIHJlamVjdChwcm9taXNlLCByZWFzb24pOwogICAgICB9LCAnU2V0dGxlOiAnICsgKHByb21pc2UuX2xhYmVsIHx8ICcgdW5rbm93biBwcm9taXNlJykpOwoKICAgICAgaWYgKCFzZWFsZWQgJiYgZXJyb3IpIHsKICAgICAgICBzZWFsZWQgPSB0cnVlOwogICAgICAgIHJlamVjdChwcm9taXNlLCBlcnJvcik7CiAgICAgIH0KICAgIH0sIHByb21pc2UpOwogIH0KCiAgZnVuY3Rpb24gaGFuZGxlT3duVGhlbmFibGUocHJvbWlzZSwgdGhlbmFibGUpIHsKICAgIGlmICh0aGVuYWJsZS5fc3RhdGUgPT09IEZVTEZJTExFRCkgewogICAgICBmdWxmaWxsKHByb21pc2UsIHRoZW5hYmxlLl9yZXN1bHQpOwogICAgfSBlbHNlIGlmICh0aGVuYWJsZS5fc3RhdGUgPT09IFJFSkVDVEVEKSB7CiAgICAgIHRoZW5hYmxlLl9vbkVycm9yID0gbnVsbDsKICAgICAgcmVqZWN0KHByb21pc2UsIHRoZW5hYmxlLl9yZXN1bHQpOwogICAgfSBlbHNlIHsKICAgICAgc3Vic2NyaWJlKHRoZW5hYmxlLCB1bmRlZmluZWQsIGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgIGlmICh0aGVuYWJsZSA9PT0gdmFsdWUpIHsKICAgICAgICAgIGZ1bGZpbGwocHJvbWlzZSwgdmFsdWUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXNvbHZlJDEocHJvbWlzZSwgdmFsdWUpOwogICAgICAgIH0KICAgICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgIHJldHVybiByZWplY3QocHJvbWlzZSwgcmVhc29uKTsKICAgICAgfSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBoYW5kbGVNYXliZVRoZW5hYmxlKHByb21pc2UsIG1heWJlVGhlbmFibGUsIHRoZW4kJDEpIHsKICAgIHZhciBpc093blRoZW5hYmxlID0gbWF5YmVUaGVuYWJsZS5jb25zdHJ1Y3RvciA9PT0gcHJvbWlzZS5jb25zdHJ1Y3RvciAmJiB0aGVuJCQxID09PSB0aGVuICYmIHByb21pc2UuY29uc3RydWN0b3IucmVzb2x2ZSA9PT0gcmVzb2x2ZSQkMTsKCiAgICBpZiAoaXNPd25UaGVuYWJsZSkgewogICAgICBoYW5kbGVPd25UaGVuYWJsZShwcm9taXNlLCBtYXliZVRoZW5hYmxlKTsKICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoZW4kJDEgPT09ICdmdW5jdGlvbicpIHsKICAgICAgaGFuZGxlRm9yZWlnblRoZW5hYmxlKHByb21pc2UsIG1heWJlVGhlbmFibGUsIHRoZW4kJDEpOwogICAgfSBlbHNlIHsKICAgICAgZnVsZmlsbChwcm9taXNlLCBtYXliZVRoZW5hYmxlKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHJlc29sdmUkMShwcm9taXNlLCB2YWx1ZSkgewogICAgaWYgKHByb21pc2UgPT09IHZhbHVlKSB7CiAgICAgIGZ1bGZpbGwocHJvbWlzZSwgdmFsdWUpOwogICAgfSBlbHNlIGlmIChvYmplY3RPckZ1bmN0aW9uKHZhbHVlKSkgewogICAgICB2YXIgdGhlbiQkMTsKCiAgICAgIHRyeSB7CiAgICAgICAgdGhlbiQkMSA9IHZhbHVlLnRoZW47CiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgcmVqZWN0KHByb21pc2UsIGVycm9yKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGhhbmRsZU1heWJlVGhlbmFibGUocHJvbWlzZSwgdmFsdWUsIHRoZW4kJDEpOwogICAgfSBlbHNlIHsKICAgICAgZnVsZmlsbChwcm9taXNlLCB2YWx1ZSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBwdWJsaXNoUmVqZWN0aW9uKHByb21pc2UpIHsKICAgIGlmIChwcm9taXNlLl9vbkVycm9yKSB7CiAgICAgIHByb21pc2UuX29uRXJyb3IocHJvbWlzZS5fcmVzdWx0KTsKICAgIH0KCiAgICBwdWJsaXNoKHByb21pc2UpOwogIH0KCiAgZnVuY3Rpb24gZnVsZmlsbChwcm9taXNlLCB2YWx1ZSkgewogICAgaWYgKHByb21pc2UuX3N0YXRlICE9PSBQRU5ESU5HKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBwcm9taXNlLl9yZXN1bHQgPSB2YWx1ZTsKICAgIHByb21pc2UuX3N0YXRlID0gRlVMRklMTEVEOwoKICAgIGlmIChwcm9taXNlLl9zdWJzY3JpYmVycy5sZW5ndGggPT09IDApIHsKICAgICAgaWYgKGNvbmZpZy5pbnN0cnVtZW50KSB7CiAgICAgICAgaW5zdHJ1bWVudCgnZnVsZmlsbGVkJywgcHJvbWlzZSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGNvbmZpZy5hc3luYyhwdWJsaXNoLCBwcm9taXNlKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHJlamVjdChwcm9taXNlLCByZWFzb24pIHsKICAgIGlmIChwcm9taXNlLl9zdGF0ZSAhPT0gUEVORElORykgewogICAgICByZXR1cm47CiAgICB9CgogICAgcHJvbWlzZS5fc3RhdGUgPSBSRUpFQ1RFRDsKICAgIHByb21pc2UuX3Jlc3VsdCA9IHJlYXNvbjsKICAgIGNvbmZpZy5hc3luYyhwdWJsaXNoUmVqZWN0aW9uLCBwcm9taXNlKTsKICB9CgogIGZ1bmN0aW9uIHN1YnNjcmliZShwYXJlbnQsIGNoaWxkLCBvbkZ1bGZpbGxtZW50LCBvblJlamVjdGlvbikgewogICAgdmFyIHN1YnNjcmliZXJzID0gcGFyZW50Ll9zdWJzY3JpYmVyczsKICAgIHZhciBsZW5ndGggPSBzdWJzY3JpYmVycy5sZW5ndGg7CiAgICBwYXJlbnQuX29uRXJyb3IgPSBudWxsOwogICAgc3Vic2NyaWJlcnNbbGVuZ3RoXSA9IGNoaWxkOwogICAgc3Vic2NyaWJlcnNbbGVuZ3RoICsgRlVMRklMTEVEXSA9IG9uRnVsZmlsbG1lbnQ7CiAgICBzdWJzY3JpYmVyc1tsZW5ndGggKyBSRUpFQ1RFRF0gPSBvblJlamVjdGlvbjsKCiAgICBpZiAobGVuZ3RoID09PSAwICYmIHBhcmVudC5fc3RhdGUpIHsKICAgICAgY29uZmlnLmFzeW5jKHB1Ymxpc2gsIHBhcmVudCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBwdWJsaXNoKHByb21pc2UpIHsKICAgIHZhciBzdWJzY3JpYmVycyA9IHByb21pc2UuX3N1YnNjcmliZXJzOwogICAgdmFyIHNldHRsZWQgPSBwcm9taXNlLl9zdGF0ZTsKCiAgICBpZiAoY29uZmlnLmluc3RydW1lbnQpIHsKICAgICAgaW5zdHJ1bWVudChzZXR0bGVkID09PSBGVUxGSUxMRUQgPyAnZnVsZmlsbGVkJyA6ICdyZWplY3RlZCcsIHByb21pc2UpOwogICAgfQoKICAgIGlmIChzdWJzY3JpYmVycy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIHZhciBjaGlsZCwKICAgICAgICBjYWxsYmFjaywKICAgICAgICByZXN1bHQgPSBwcm9taXNlLl9yZXN1bHQ7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdWJzY3JpYmVycy5sZW5ndGg7IGkgKz0gMykgewogICAgICBjaGlsZCA9IHN1YnNjcmliZXJzW2ldOwogICAgICBjYWxsYmFjayA9IHN1YnNjcmliZXJzW2kgKyBzZXR0bGVkXTsKCiAgICAgIGlmIChjaGlsZCkgewogICAgICAgIGludm9rZUNhbGxiYWNrKHNldHRsZWQsIGNoaWxkLCBjYWxsYmFjaywgcmVzdWx0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjYWxsYmFjayhyZXN1bHQpOwogICAgICB9CiAgICB9CgogICAgcHJvbWlzZS5fc3Vic2NyaWJlcnMubGVuZ3RoID0gMDsKICB9CgogIGZ1bmN0aW9uIGludm9rZUNhbGxiYWNrKHN0YXRlLCBwcm9taXNlLCBjYWxsYmFjaywgcmVzdWx0KSB7CiAgICB2YXIgaGFzQ2FsbGJhY2sgPSB0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbic7CiAgICB2YXIgdmFsdWUsCiAgICAgICAgc3VjY2VlZGVkID0gdHJ1ZSwKICAgICAgICBlcnJvcjsKCiAgICBpZiAoaGFzQ2FsbGJhY2spIHsKICAgICAgdHJ5IHsKICAgICAgICB2YWx1ZSA9IGNhbGxiYWNrKHJlc3VsdCk7CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBzdWNjZWVkZWQgPSBmYWxzZTsKICAgICAgICBlcnJvciA9IGU7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhbHVlID0gcmVzdWx0OwogICAgfQoKICAgIGlmIChwcm9taXNlLl9zdGF0ZSAhPT0gUEVORElORykgey8vIG5vb3AKICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IHByb21pc2UpIHsKICAgICAgcmVqZWN0KHByb21pc2UsIHdpdGhPd25Qcm9taXNlKCkpOwogICAgfSBlbHNlIGlmIChzdWNjZWVkZWQgPT09IGZhbHNlKSB7CiAgICAgIHJlamVjdChwcm9taXNlLCBlcnJvcik7CiAgICB9IGVsc2UgaWYgKGhhc0NhbGxiYWNrKSB7CiAgICAgIHJlc29sdmUkMShwcm9taXNlLCB2YWx1ZSk7CiAgICB9IGVsc2UgaWYgKHN0YXRlID09PSBGVUxGSUxMRUQpIHsKICAgICAgZnVsZmlsbChwcm9taXNlLCB2YWx1ZSk7CiAgICB9IGVsc2UgaWYgKHN0YXRlID09PSBSRUpFQ1RFRCkgewogICAgICByZWplY3QocHJvbWlzZSwgdmFsdWUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gaW5pdGlhbGl6ZVByb21pc2UocHJvbWlzZSwgcmVzb2x2ZXIpIHsKICAgIHZhciByZXNvbHZlZCA9IGZhbHNlOwoKICAgIHRyeSB7CiAgICAgIHJlc29sdmVyKGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgIGlmIChyZXNvbHZlZCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgcmVzb2x2ZWQgPSB0cnVlOwogICAgICAgIHJlc29sdmUkMShwcm9taXNlLCB2YWx1ZSk7CiAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICBpZiAocmVzb2x2ZWQpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHJlc29sdmVkID0gdHJ1ZTsKICAgICAgICByZWplY3QocHJvbWlzZSwgcmVhc29uKTsKICAgICAgfSk7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHJlamVjdChwcm9taXNlLCBlKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIHRoZW4ob25GdWxmaWxsbWVudCwgb25SZWplY3Rpb24sIGxhYmVsKSB7CiAgICB2YXIgcGFyZW50ID0gdGhpczsKICAgIHZhciBzdGF0ZSA9IHBhcmVudC5fc3RhdGU7CgogICAgaWYgKHN0YXRlID09PSBGVUxGSUxMRUQgJiYgIW9uRnVsZmlsbG1lbnQgfHwgc3RhdGUgPT09IFJFSkVDVEVEICYmICFvblJlamVjdGlvbikgewogICAgICBjb25maWcuaW5zdHJ1bWVudCAmJiBpbnN0cnVtZW50KCdjaGFpbmVkJywgcGFyZW50LCBwYXJlbnQpOwogICAgICByZXR1cm4gcGFyZW50OwogICAgfQoKICAgIHBhcmVudC5fb25FcnJvciA9IG51bGw7CiAgICB2YXIgY2hpbGQgPSBuZXcgcGFyZW50LmNvbnN0cnVjdG9yKG5vb3AsIGxhYmVsKTsKICAgIHZhciByZXN1bHQgPSBwYXJlbnQuX3Jlc3VsdDsKICAgIGNvbmZpZy5pbnN0cnVtZW50ICYmIGluc3RydW1lbnQoJ2NoYWluZWQnLCBwYXJlbnQsIGNoaWxkKTsKCiAgICBpZiAoc3RhdGUgPT09IFBFTkRJTkcpIHsKICAgICAgc3Vic2NyaWJlKHBhcmVudCwgY2hpbGQsIG9uRnVsZmlsbG1lbnQsIG9uUmVqZWN0aW9uKTsKICAgIH0gZWxzZSB7CiAgICAgIHZhciBjYWxsYmFjayA9IHN0YXRlID09PSBGVUxGSUxMRUQgPyBvbkZ1bGZpbGxtZW50IDogb25SZWplY3Rpb247CiAgICAgIGNvbmZpZy5hc3luYyhmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIGludm9rZUNhbGxiYWNrKHN0YXRlLCBjaGlsZCwgY2FsbGJhY2ssIHJlc3VsdCk7CiAgICAgIH0pOwogICAgfQoKICAgIHJldHVybiBjaGlsZDsKICB9CgogIHZhciBFbnVtZXJhdG9yID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRW51bWVyYXRvcihDb25zdHJ1Y3RvciwgaW5wdXQsIGFib3J0T25SZWplY3QsIGxhYmVsKSB7CiAgICAgIHRoaXMuX2luc3RhbmNlQ29uc3RydWN0b3IgPSBDb25zdHJ1Y3RvcjsKICAgICAgdGhpcy5wcm9taXNlID0gbmV3IENvbnN0cnVjdG9yKG5vb3AsIGxhYmVsKTsKICAgICAgdGhpcy5fYWJvcnRPblJlamVjdCA9IGFib3J0T25SZWplY3Q7CiAgICAgIHRoaXMuX2lzVXNpbmdPd25Qcm9taXNlID0gQ29uc3RydWN0b3IgPT09IFByb21pc2U7CiAgICAgIHRoaXMuX2lzVXNpbmdPd25SZXNvbHZlID0gQ29uc3RydWN0b3IucmVzb2x2ZSA9PT0gcmVzb2x2ZSQkMTsKCiAgICAgIHRoaXMuX2luaXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gRW51bWVyYXRvci5wcm90b3R5cGU7CgogICAgX3Byb3RvLl9pbml0ID0gZnVuY3Rpb24gX2luaXQoQ29uc3RydWN0b3IsIGlucHV0KSB7CiAgICAgIHZhciBsZW4gPSBpbnB1dC5sZW5ndGggfHwgMDsKICAgICAgdGhpcy5sZW5ndGggPSBsZW47CiAgICAgIHRoaXMuX3JlbWFpbmluZyA9IGxlbjsKICAgICAgdGhpcy5fcmVzdWx0ID0gbmV3IEFycmF5KGxlbik7CgogICAgICB0aGlzLl9lbnVtZXJhdGUoaW5wdXQpOwogICAgfTsKCiAgICBfcHJvdG8uX2VudW1lcmF0ZSA9IGZ1bmN0aW9uIF9lbnVtZXJhdGUoaW5wdXQpIHsKICAgICAgdmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoOwogICAgICB2YXIgcHJvbWlzZSA9IHRoaXMucHJvbWlzZTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBwcm9taXNlLl9zdGF0ZSA9PT0gUEVORElORyAmJiBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICB0aGlzLl9lYWNoRW50cnkoaW5wdXRbaV0sIGksIHRydWUpOwogICAgICB9CgogICAgICB0aGlzLl9jaGVja0Z1bGxmaWxsbWVudCgpOwogICAgfTsKCiAgICBfcHJvdG8uX2NoZWNrRnVsbGZpbGxtZW50ID0gZnVuY3Rpb24gX2NoZWNrRnVsbGZpbGxtZW50KCkgewogICAgICBpZiAodGhpcy5fcmVtYWluaW5nID09PSAwKSB7CiAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuX3Jlc3VsdDsKICAgICAgICBmdWxmaWxsKHRoaXMucHJvbWlzZSwgcmVzdWx0KTsKICAgICAgICB0aGlzLl9yZXN1bHQgPSBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fc2V0dGxlTWF5YmVUaGVuYWJsZSA9IGZ1bmN0aW9uIF9zZXR0bGVNYXliZVRoZW5hYmxlKGVudHJ5LCBpLCBmaXJzdFBhc3MpIHsKICAgICAgdmFyIGMgPSB0aGlzLl9pbnN0YW5jZUNvbnN0cnVjdG9yOwoKICAgICAgaWYgKHRoaXMuX2lzVXNpbmdPd25SZXNvbHZlKSB7CiAgICAgICAgdmFyIHRoZW4kJDEsCiAgICAgICAgICAgIGVycm9yLAogICAgICAgICAgICBzdWNjZWVkZWQgPSB0cnVlOwoKICAgICAgICB0cnkgewogICAgICAgICAgdGhlbiQkMSA9IGVudHJ5LnRoZW47CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgc3VjY2VlZGVkID0gZmFsc2U7CiAgICAgICAgICBlcnJvciA9IGU7CiAgICAgICAgfQoKICAgICAgICBpZiAodGhlbiQkMSA9PT0gdGhlbiAmJiBlbnRyeS5fc3RhdGUgIT09IFBFTkRJTkcpIHsKICAgICAgICAgIGVudHJ5Ll9vbkVycm9yID0gbnVsbDsKCiAgICAgICAgICB0aGlzLl9zZXR0bGVkQXQoZW50cnkuX3N0YXRlLCBpLCBlbnRyeS5fcmVzdWx0LCBmaXJzdFBhc3MpOwogICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoZW4kJDEgIT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIHRoaXMuX3NldHRsZWRBdChGVUxGSUxMRUQsIGksIGVudHJ5LCBmaXJzdFBhc3MpOwogICAgICAgIH0gZWxzZSBpZiAodGhpcy5faXNVc2luZ093blByb21pc2UpIHsKICAgICAgICAgIHZhciBwcm9taXNlID0gbmV3IGMobm9vcCk7CgogICAgICAgICAgaWYgKHN1Y2NlZWRlZCA9PT0gZmFsc2UpIHsKICAgICAgICAgICAgcmVqZWN0KHByb21pc2UsIGVycm9yKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGhhbmRsZU1heWJlVGhlbmFibGUocHJvbWlzZSwgZW50cnksIHRoZW4kJDEpOwoKICAgICAgICAgICAgdGhpcy5fd2lsbFNldHRsZUF0KHByb21pc2UsIGksIGZpcnN0UGFzcyk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuX3dpbGxTZXR0bGVBdChuZXcgYyhmdW5jdGlvbiAocmVzb2x2ZSkgewogICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShlbnRyeSk7CiAgICAgICAgICB9KSwgaSwgZmlyc3RQYXNzKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fd2lsbFNldHRsZUF0KGMucmVzb2x2ZShlbnRyeSksIGksIGZpcnN0UGFzcyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9lYWNoRW50cnkgPSBmdW5jdGlvbiBfZWFjaEVudHJ5KGVudHJ5LCBpLCBmaXJzdFBhc3MpIHsKICAgICAgaWYgKGVudHJ5ICE9PSBudWxsICYmIHR5cGVvZiBlbnRyeSA9PT0gJ29iamVjdCcpIHsKICAgICAgICB0aGlzLl9zZXR0bGVNYXliZVRoZW5hYmxlKGVudHJ5LCBpLCBmaXJzdFBhc3MpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuX3NldFJlc3VsdEF0KEZVTEZJTExFRCwgaSwgZW50cnksIGZpcnN0UGFzcyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9zZXR0bGVkQXQgPSBmdW5jdGlvbiBfc2V0dGxlZEF0KHN0YXRlLCBpLCB2YWx1ZSwgZmlyc3RQYXNzKSB7CiAgICAgIHZhciBwcm9taXNlID0gdGhpcy5wcm9taXNlOwoKICAgICAgaWYgKHByb21pc2UuX3N0YXRlID09PSBQRU5ESU5HKSB7CiAgICAgICAgaWYgKHRoaXMuX2Fib3J0T25SZWplY3QgJiYgc3RhdGUgPT09IFJFSkVDVEVEKSB7CiAgICAgICAgICByZWplY3QocHJvbWlzZSwgdmFsdWUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9zZXRSZXN1bHRBdChzdGF0ZSwgaSwgdmFsdWUsIGZpcnN0UGFzcyk7CgogICAgICAgICAgdGhpcy5fY2hlY2tGdWxsZmlsbG1lbnQoKTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9zZXRSZXN1bHRBdCA9IGZ1bmN0aW9uIF9zZXRSZXN1bHRBdChzdGF0ZSwgaSwgdmFsdWUsIGZpcnN0UGFzcykgewogICAgICB0aGlzLl9yZW1haW5pbmctLTsKICAgICAgdGhpcy5fcmVzdWx0W2ldID0gdmFsdWU7CiAgICB9OwoKICAgIF9wcm90by5fd2lsbFNldHRsZUF0ID0gZnVuY3Rpb24gX3dpbGxTZXR0bGVBdChwcm9taXNlLCBpLCBmaXJzdFBhc3MpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHN1YnNjcmliZShwcm9taXNlLCB1bmRlZmluZWQsIGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgIHJldHVybiBfdGhpcy5fc2V0dGxlZEF0KEZVTEZJTExFRCwgaSwgdmFsdWUsIGZpcnN0UGFzcyk7CiAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICByZXR1cm4gX3RoaXMuX3NldHRsZWRBdChSRUpFQ1RFRCwgaSwgcmVhc29uLCBmaXJzdFBhc3MpOwogICAgICB9KTsKICAgIH07CgogICAgcmV0dXJuIEVudW1lcmF0b3I7CiAgfSgpOwoKICBmdW5jdGlvbiBzZXRTZXR0bGVkUmVzdWx0KHN0YXRlLCBpLCB2YWx1ZSkgewogICAgdGhpcy5fcmVtYWluaW5nLS07CgogICAgaWYgKHN0YXRlID09PSBGVUxGSUxMRUQpIHsKICAgICAgdGhpcy5fcmVzdWx0W2ldID0gewogICAgICAgIHN0YXRlOiAnZnVsZmlsbGVkJywKICAgICAgICB2YWx1ZTogdmFsdWUKICAgICAgfTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuX3Jlc3VsdFtpXSA9IHsKICAgICAgICBzdGF0ZTogJ3JlamVjdGVkJywKICAgICAgICByZWFzb246IHZhbHVlCiAgICAgIH07CiAgICB9CiAgfQogIC8qKgogICAgYFByb21pc2UuYWxsYCBhY2NlcHRzIGFuIGFycmF5IG9mIHByb21pc2VzLCBhbmQgcmV0dXJucyBhIG5ldyBwcm9taXNlIHdoaWNoCiAgICBpcyBmdWxmaWxsZWQgd2l0aCBhbiBhcnJheSBvZiBmdWxmaWxsbWVudCB2YWx1ZXMgZm9yIHRoZSBwYXNzZWQgcHJvbWlzZXMsIG9yCiAgICByZWplY3RlZCB3aXRoIHRoZSByZWFzb24gb2YgdGhlIGZpcnN0IHBhc3NlZCBwcm9taXNlIHRvIGJlIHJlamVjdGVkLiBJdCBjYXN0cyBhbGwKICAgIGVsZW1lbnRzIG9mIHRoZSBwYXNzZWQgaXRlcmFibGUgdG8gcHJvbWlzZXMgYXMgaXQgcnVucyB0aGlzIGFsZ29yaXRobS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSwgeyByZXNvbHZlIH0gZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgcHJvbWlzZTEgPSByZXNvbHZlKDEpOwogICAgbGV0IHByb21pc2UyID0gcmVzb2x2ZSgyKTsKICAgIGxldCBwcm9taXNlMyA9IHJlc29sdmUoMyk7CiAgICBsZXQgcHJvbWlzZXMgPSBbIHByb21pc2UxLCBwcm9taXNlMiwgcHJvbWlzZTMgXTsKICAKICAgIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKGZ1bmN0aW9uKGFycmF5KXsKICAgICAgLy8gVGhlIGFycmF5IGhlcmUgd291bGQgYmUgWyAxLCAyLCAzIF07CiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgYW55IG9mIHRoZSBgcHJvbWlzZXNgIGdpdmVuIHRvIGBSU1ZQLmFsbGAgYXJlIHJlamVjdGVkLCB0aGUgZmlyc3QgcHJvbWlzZQogICAgdGhhdCBpcyByZWplY3RlZCB3aWxsIGJlIGdpdmVuIGFzIGFuIGFyZ3VtZW50IHRvIHRoZSByZXR1cm5lZCBwcm9taXNlcydzCiAgICByZWplY3Rpb24gaGFuZGxlci4gRm9yIGV4YW1wbGU6CiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IFByb21pc2UsIHsgcmVzb2x2ZSwgcmVqZWN0IH0gZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgcHJvbWlzZTEgPSByZXNvbHZlKDEpOwogICAgbGV0IHByb21pc2UyID0gcmVqZWN0KG5ldyBFcnJvcigiMiIpKTsKICAgIGxldCBwcm9taXNlMyA9IHJlamVjdChuZXcgRXJyb3IoIjMiKSk7CiAgICBsZXQgcHJvbWlzZXMgPSBbIHByb21pc2UxLCBwcm9taXNlMiwgcHJvbWlzZTMgXTsKICAKICAgIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKGZ1bmN0aW9uKGFycmF5KXsKICAgICAgLy8gQ29kZSBoZXJlIG5ldmVyIHJ1bnMgYmVjYXVzZSB0aGVyZSBhcmUgcmVqZWN0ZWQgcHJvbWlzZXMhCiAgICB9LCBmdW5jdGlvbihlcnJvcikgewogICAgICAvLyBlcnJvci5tZXNzYWdlID09PSAiMiIKICAgIH0pOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGFsbAogICAgQGZvciBQcm9taXNlCiAgICBAcGFyYW0ge0FycmF5fSBlbnRyaWVzIGFycmF5IG9mIHByb21pc2VzCiAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCB3aGVuIGFsbCBgcHJvbWlzZXNgIGhhdmUgYmVlbgogICAgZnVsZmlsbGVkLCBvciByZWplY3RlZCBpZiBhbnkgb2YgdGhlbSBiZWNvbWUgcmVqZWN0ZWQuCiAgICBAc3RhdGljCiAgKi8KCgogIGZ1bmN0aW9uIGFsbChlbnRyaWVzLCBsYWJlbCkgewogICAgaWYgKCFBcnJheS5pc0FycmF5KGVudHJpZXMpKSB7CiAgICAgIHJldHVybiB0aGlzLnJlamVjdChuZXcgVHlwZUVycm9yKCJQcm9taXNlLmFsbCBtdXN0IGJlIGNhbGxlZCB3aXRoIGFuIGFycmF5IiksIGxhYmVsKTsKICAgIH0KCiAgICByZXR1cm4gbmV3IEVudW1lcmF0b3IodGhpcywgZW50cmllcywgdHJ1ZQogICAgLyogYWJvcnQgb24gcmVqZWN0ICovCiAgICAsIGxhYmVsKS5wcm9taXNlOwogIH0KICAvKioKICAgIGBQcm9taXNlLnJhY2VgIHJldHVybnMgYSBuZXcgcHJvbWlzZSB3aGljaCBpcyBzZXR0bGVkIGluIHRoZSBzYW1lIHdheSBhcyB0aGUKICAgIGZpcnN0IHBhc3NlZCBwcm9taXNlIHRvIHNldHRsZS4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlMSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7CiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKXsKICAgICAgICByZXNvbHZlKCdwcm9taXNlIDEnKTsKICAgICAgfSwgMjAwKTsKICAgIH0pOwogIAogICAgbGV0IHByb21pc2UyID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXsKICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpewogICAgICAgIHJlc29sdmUoJ3Byb21pc2UgMicpOwogICAgICB9LCAxMDApOwogICAgfSk7CiAgCiAgICBQcm9taXNlLnJhY2UoW3Byb21pc2UxLCBwcm9taXNlMl0pLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXsKICAgICAgLy8gcmVzdWx0ID09PSAncHJvbWlzZSAyJyBiZWNhdXNlIGl0IHdhcyByZXNvbHZlZCBiZWZvcmUgcHJvbWlzZTEKICAgICAgLy8gd2FzIHJlc29sdmVkLgogICAgfSk7CiAgICBgYGAKICAKICAgIGBQcm9taXNlLnJhY2VgIGlzIGRldGVybWluaXN0aWMgaW4gdGhhdCBvbmx5IHRoZSBzdGF0ZSBvZiB0aGUgZmlyc3QKICAgIHNldHRsZWQgcHJvbWlzZSBtYXR0ZXJzLiBGb3IgZXhhbXBsZSwgZXZlbiBpZiBvdGhlciBwcm9taXNlcyBnaXZlbiB0byB0aGUKICAgIGBwcm9taXNlc2AgYXJyYXkgYXJndW1lbnQgYXJlIHJlc29sdmVkLCBidXQgdGhlIGZpcnN0IHNldHRsZWQgcHJvbWlzZSBoYXMKICAgIGJlY29tZSByZWplY3RlZCBiZWZvcmUgdGhlIG90aGVyIHByb21pc2VzIGJlY2FtZSBmdWxmaWxsZWQsIHRoZSByZXR1cm5lZAogICAgcHJvbWlzZSB3aWxsIGJlY29tZSByZWplY3RlZDoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBQcm9taXNlIGZyb20gJ3JzdnAnOwogIAogICAgbGV0IHByb21pc2UxID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXsKICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpewogICAgICAgIHJlc29sdmUoJ3Byb21pc2UgMScpOwogICAgICB9LCAyMDApOwogICAgfSk7CiAgCiAgICBsZXQgcHJvbWlzZTIgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpewogICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7CiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcigncHJvbWlzZSAyJykpOwogICAgICB9LCAxMDApOwogICAgfSk7CiAgCiAgICBQcm9taXNlLnJhY2UoW3Byb21pc2UxLCBwcm9taXNlMl0pLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXsKICAgICAgLy8gQ29kZSBoZXJlIG5ldmVyIHJ1bnMKICAgIH0sIGZ1bmN0aW9uKHJlYXNvbil7CiAgICAgIC8vIHJlYXNvbi5tZXNzYWdlID09PSAncHJvbWlzZSAyJyBiZWNhdXNlIHByb21pc2UgMiBiZWNhbWUgcmVqZWN0ZWQgYmVmb3JlCiAgICAgIC8vIHByb21pc2UgMSBiZWNhbWUgZnVsZmlsbGVkCiAgICB9KTsKICAgIGBgYAogIAogICAgQW4gZXhhbXBsZSByZWFsLXdvcmxkIHVzZSBjYXNlIGlzIGltcGxlbWVudGluZyB0aW1lb3V0czoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBQcm9taXNlIGZyb20gJ3JzdnAnOwogIAogICAgUHJvbWlzZS5yYWNlKFthamF4KCdmb28uanNvbicpLCB0aW1lb3V0KDUwMDApXSkKICAgIGBgYAogIAogICAgQG1ldGhvZCByYWNlCiAgICBAZm9yIFByb21pc2UKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7QXJyYXl9IGVudHJpZXMgYXJyYXkgb2YgcHJvbWlzZXMgdG8gb2JzZXJ2ZQogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGZvciBkZXNjcmliaW5nIHRoZSBwcm9taXNlIHJldHVybmVkLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHdoaWNoIHNldHRsZXMgaW4gdGhlIHNhbWUgd2F5IGFzIHRoZSBmaXJzdCBwYXNzZWQKICAgIHByb21pc2UgdG8gc2V0dGxlLgogICovCgoKICBmdW5jdGlvbiByYWNlKGVudHJpZXMsIGxhYmVsKSB7CiAgICAvKmpzaGludCB2YWxpZHRoaXM6dHJ1ZSAqLwogICAgdmFyIENvbnN0cnVjdG9yID0gdGhpczsKICAgIHZhciBwcm9taXNlID0gbmV3IENvbnN0cnVjdG9yKG5vb3AsIGxhYmVsKTsKCiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZW50cmllcykpIHsKICAgICAgcmVqZWN0KHByb21pc2UsIG5ldyBUeXBlRXJyb3IoJ1Byb21pc2UucmFjZSBtdXN0IGJlIGNhbGxlZCB3aXRoIGFuIGFycmF5JykpOwogICAgICByZXR1cm4gcHJvbWlzZTsKICAgIH0KCiAgICBmb3IgKHZhciBpID0gMDsgcHJvbWlzZS5fc3RhdGUgPT09IFBFTkRJTkcgJiYgaSA8IGVudHJpZXMubGVuZ3RoOyBpKyspIHsKICAgICAgc3Vic2NyaWJlKENvbnN0cnVjdG9yLnJlc29sdmUoZW50cmllc1tpXSksIHVuZGVmaW5lZCwgZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHJlc29sdmUkMShwcm9taXNlLCB2YWx1ZSk7CiAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICByZXR1cm4gcmVqZWN0KHByb21pc2UsIHJlYXNvbik7CiAgICAgIH0pOwogICAgfQoKICAgIHJldHVybiBwcm9taXNlOwogIH0KICAvKioKICAgIGBQcm9taXNlLnJlamVjdGAgcmV0dXJucyBhIHByb21pc2UgcmVqZWN0ZWQgd2l0aCB0aGUgcGFzc2VkIGByZWFzb25gLgogICAgSXQgaXMgc2hvcnRoYW5kIGZvciB0aGUgZm9sbG93aW5nOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IFByb21pc2UgZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7CiAgICAgIHJlamVjdChuZXcgRXJyb3IoJ1dIT09QUycpKTsKICAgIH0pOwogIAogICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXsKICAgICAgLy8gQ29kZSBoZXJlIGRvZXNuJ3QgcnVuIGJlY2F1c2UgdGhlIHByb21pc2UgaXMgcmVqZWN0ZWQhCiAgICB9LCBmdW5jdGlvbihyZWFzb24pewogICAgICAvLyByZWFzb24ubWVzc2FnZSA9PT0gJ1dIT09QUycKICAgIH0pOwogICAgYGBgCiAgCiAgICBJbnN0ZWFkIG9mIHdyaXRpbmcgdGhlIGFib3ZlLCB5b3VyIGNvZGUgbm93IHNpbXBseSBiZWNvbWVzIHRoZSBmb2xsb3dpbmc6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlID0gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdXSE9PUFMnKSk7CiAgCiAgICBwcm9taXNlLnRoZW4oZnVuY3Rpb24odmFsdWUpewogICAgICAvLyBDb2RlIGhlcmUgZG9lc24ndCBydW4gYmVjYXVzZSB0aGUgcHJvbWlzZSBpcyByZWplY3RlZCEKICAgIH0sIGZ1bmN0aW9uKHJlYXNvbil7CiAgICAgIC8vIHJlYXNvbi5tZXNzYWdlID09PSAnV0hPT1BTJwogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgcmVqZWN0CiAgICBAZm9yIFByb21pc2UKICAgIEBzdGF0aWMKICAgIEBwYXJhbSB7Kn0gcmVhc29uIHZhbHVlIHRoYXQgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoLgogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGZvciBpZGVudGlmeWluZyB0aGUgcmV0dXJuZWQgcHJvbWlzZS4KICAgIFVzZWZ1bCBmb3IgdG9vbGluZy4KICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSByZWplY3RlZCB3aXRoIHRoZSBnaXZlbiBgcmVhc29uYC4KICAqLwoKCiAgZnVuY3Rpb24gcmVqZWN0JDEocmVhc29uLCBsYWJlbCkgewogICAgLypqc2hpbnQgdmFsaWR0aGlzOnRydWUgKi8KICAgIHZhciBDb25zdHJ1Y3RvciA9IHRoaXM7CiAgICB2YXIgcHJvbWlzZSA9IG5ldyBDb25zdHJ1Y3Rvcihub29wLCBsYWJlbCk7CiAgICByZWplY3QocHJvbWlzZSwgcmVhc29uKTsKICAgIHJldHVybiBwcm9taXNlOwogIH0KCiAgdmFyIGd1aWRLZXkgPSAncnN2cF8nICsgRGF0ZS5ub3coKSArICctJzsKICB2YXIgY291bnRlciA9IDA7CgogIGZ1bmN0aW9uIG5lZWRzUmVzb2x2ZXIoKSB7CiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdZb3UgbXVzdCBwYXNzIGEgcmVzb2x2ZXIgZnVuY3Rpb24gYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHRvIHRoZSBwcm9taXNlIGNvbnN0cnVjdG9yJyk7CiAgfQoKICBmdW5jdGlvbiBuZWVkc05ldygpIHsKICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIkZhaWxlZCB0byBjb25zdHJ1Y3QgJ1Byb21pc2UnOiBQbGVhc2UgdXNlIHRoZSAnbmV3JyBvcGVyYXRvciwgdGhpcyBvYmplY3QgY29uc3RydWN0b3IgY2Fubm90IGJlIGNhbGxlZCBhcyBhIGZ1bmN0aW9uLiIpOwogIH0KICAvKioKICAgIFByb21pc2Ugb2JqZWN0cyByZXByZXNlbnQgdGhlIGV2ZW50dWFsIHJlc3VsdCBvZiBhbiBhc3luY2hyb25vdXMgb3BlcmF0aW9uLiBUaGUKICAgIHByaW1hcnkgd2F5IG9mIGludGVyYWN0aW5nIHdpdGggYSBwcm9taXNlIGlzIHRocm91Z2ggaXRzIGB0aGVuYCBtZXRob2QsIHdoaWNoCiAgICByZWdpc3RlcnMgY2FsbGJhY2tzIHRvIHJlY2VpdmUgZWl0aGVyIGEgcHJvbWlzZeKAmXMgZXZlbnR1YWwgdmFsdWUgb3IgdGhlIHJlYXNvbgogICAgd2h5IHRoZSBwcm9taXNlIGNhbm5vdCBiZSBmdWxmaWxsZWQuCiAgCiAgICBUZXJtaW5vbG9neQogICAgLS0tLS0tLS0tLS0KICAKICAgIC0gYHByb21pc2VgIGlzIGFuIG9iamVjdCBvciBmdW5jdGlvbiB3aXRoIGEgYHRoZW5gIG1ldGhvZCB3aG9zZSBiZWhhdmlvciBjb25mb3JtcyB0byB0aGlzIHNwZWNpZmljYXRpb24uCiAgICAtIGB0aGVuYWJsZWAgaXMgYW4gb2JqZWN0IG9yIGZ1bmN0aW9uIHRoYXQgZGVmaW5lcyBhIGB0aGVuYCBtZXRob2QuCiAgICAtIGB2YWx1ZWAgaXMgYW55IGxlZ2FsIEphdmFTY3JpcHQgdmFsdWUgKGluY2x1ZGluZyB1bmRlZmluZWQsIGEgdGhlbmFibGUsIG9yIGEgcHJvbWlzZSkuCiAgICAtIGBleGNlcHRpb25gIGlzIGEgdmFsdWUgdGhhdCBpcyB0aHJvd24gdXNpbmcgdGhlIHRocm93IHN0YXRlbWVudC4KICAgIC0gYHJlYXNvbmAgaXMgYSB2YWx1ZSB0aGF0IGluZGljYXRlcyB3aHkgYSBwcm9taXNlIHdhcyByZWplY3RlZC4KICAgIC0gYHNldHRsZWRgIHRoZSBmaW5hbCByZXN0aW5nIHN0YXRlIG9mIGEgcHJvbWlzZSwgZnVsZmlsbGVkIG9yIHJlamVjdGVkLgogIAogICAgQSBwcm9taXNlIGNhbiBiZSBpbiBvbmUgb2YgdGhyZWUgc3RhdGVzOiBwZW5kaW5nLCBmdWxmaWxsZWQsIG9yIHJlamVjdGVkLgogIAogICAgUHJvbWlzZXMgdGhhdCBhcmUgZnVsZmlsbGVkIGhhdmUgYSBmdWxmaWxsbWVudCB2YWx1ZSBhbmQgYXJlIGluIHRoZSBmdWxmaWxsZWQKICAgIHN0YXRlLiAgUHJvbWlzZXMgdGhhdCBhcmUgcmVqZWN0ZWQgaGF2ZSBhIHJlamVjdGlvbiByZWFzb24gYW5kIGFyZSBpbiB0aGUKICAgIHJlamVjdGVkIHN0YXRlLiAgQSBmdWxmaWxsbWVudCB2YWx1ZSBpcyBuZXZlciBhIHRoZW5hYmxlLgogIAogICAgUHJvbWlzZXMgY2FuIGFsc28gYmUgc2FpZCB0byAqcmVzb2x2ZSogYSB2YWx1ZS4gIElmIHRoaXMgdmFsdWUgaXMgYWxzbyBhCiAgICBwcm9taXNlLCB0aGVuIHRoZSBvcmlnaW5hbCBwcm9taXNlJ3Mgc2V0dGxlZCBzdGF0ZSB3aWxsIG1hdGNoIHRoZSB2YWx1ZSdzCiAgICBzZXR0bGVkIHN0YXRlLiAgU28gYSBwcm9taXNlIHRoYXQgKnJlc29sdmVzKiBhIHByb21pc2UgdGhhdCByZWplY3RzIHdpbGwKICAgIGl0c2VsZiByZWplY3QsIGFuZCBhIHByb21pc2UgdGhhdCAqcmVzb2x2ZXMqIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIHdpbGwKICAgIGl0c2VsZiBmdWxmaWxsLgogIAogIAogICAgQmFzaWMgVXNhZ2U6CiAgICAtLS0tLS0tLS0tLS0KICAKICAgIGBgYGpzCiAgICBsZXQgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkgewogICAgICAvLyBvbiBzdWNjZXNzCiAgICAgIHJlc29sdmUodmFsdWUpOwogIAogICAgICAvLyBvbiBmYWlsdXJlCiAgICAgIHJlamVjdChyZWFzb24pOwogICAgfSk7CiAgCiAgICBwcm9taXNlLnRoZW4oZnVuY3Rpb24odmFsdWUpIHsKICAgICAgLy8gb24gZnVsZmlsbG1lbnQKICAgIH0sIGZ1bmN0aW9uKHJlYXNvbikgewogICAgICAvLyBvbiByZWplY3Rpb24KICAgIH0pOwogICAgYGBgCiAgCiAgICBBZHZhbmNlZCBVc2FnZToKICAgIC0tLS0tLS0tLS0tLS0tLQogIAogICAgUHJvbWlzZXMgc2hpbmUgd2hlbiBhYnN0cmFjdGluZyBhd2F5IGFzeW5jaHJvbm91cyBpbnRlcmFjdGlvbnMgc3VjaCBhcwogICAgYFhNTEh0dHBSZXF1ZXN0YHMuCiAgCiAgICBgYGBqcwogICAgZnVuY3Rpb24gZ2V0SlNPTih1cmwpIHsKICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7CiAgICAgICAgbGV0IHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpOwogIAogICAgICAgIHhoci5vcGVuKCdHRVQnLCB1cmwpOwogICAgICAgIHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBoYW5kbGVyOwogICAgICAgIHhoci5yZXNwb25zZVR5cGUgPSAnanNvbic7CiAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoJ0FjY2VwdCcsICdhcHBsaWNhdGlvbi9qc29uJyk7CiAgICAgICAgeGhyLnNlbmQoKTsKICAKICAgICAgICBmdW5jdGlvbiBoYW5kbGVyKCkgewogICAgICAgICAgaWYgKHRoaXMucmVhZHlTdGF0ZSA9PT0gdGhpcy5ET05FKSB7CiAgICAgICAgICAgIGlmICh0aGlzLnN0YXR1cyA9PT0gMjAwKSB7CiAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLnJlc3BvbnNlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdnZXRKU09OOiBgJyArIHVybCArICdgIGZhaWxlZCB3aXRoIHN0YXR1czogWycgKyB0aGlzLnN0YXR1cyArICddJykpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgfSk7CiAgICB9CiAgCiAgICBnZXRKU09OKCcvcG9zdHMuanNvbicpLnRoZW4oZnVuY3Rpb24oanNvbikgewogICAgICAvLyBvbiBmdWxmaWxsbWVudAogICAgfSwgZnVuY3Rpb24ocmVhc29uKSB7CiAgICAgIC8vIG9uIHJlamVjdGlvbgogICAgfSk7CiAgICBgYGAKICAKICAgIFVubGlrZSBjYWxsYmFja3MsIHByb21pc2VzIGFyZSBncmVhdCBjb21wb3NhYmxlIHByaW1pdGl2ZXMuCiAgCiAgICBgYGBqcwogICAgUHJvbWlzZS5hbGwoWwogICAgICBnZXRKU09OKCcvcG9zdHMnKSwKICAgICAgZ2V0SlNPTignL2NvbW1lbnRzJykKICAgIF0pLnRoZW4oZnVuY3Rpb24odmFsdWVzKXsKICAgICAgdmFsdWVzWzBdIC8vID0+IHBvc3RzSlNPTgogICAgICB2YWx1ZXNbMV0gLy8gPT4gY29tbWVudHNKU09OCiAgCiAgICAgIHJldHVybiB2YWx1ZXM7CiAgICB9KTsKICAgIGBgYAogIAogICAgQGNsYXNzIFByb21pc2UKICAgIEBwdWJsaWMKICAgIEBwYXJhbSB7ZnVuY3Rpb259IHJlc29sdmVyCiAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQGNvbnN0cnVjdG9yCiAgKi8KCgogIHZhciBQcm9taXNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUHJvbWlzZShyZXNvbHZlciwgbGFiZWwpIHsKICAgICAgdGhpcy5faWQgPSBjb3VudGVyKys7CiAgICAgIHRoaXMuX2xhYmVsID0gbGFiZWw7CiAgICAgIHRoaXMuX3N0YXRlID0gdW5kZWZpbmVkOwogICAgICB0aGlzLl9yZXN1bHQgPSB1bmRlZmluZWQ7CiAgICAgIHRoaXMuX3N1YnNjcmliZXJzID0gW107CiAgICAgIGNvbmZpZy5pbnN0cnVtZW50ICYmIGluc3RydW1lbnQoJ2NyZWF0ZWQnLCB0aGlzKTsKCiAgICAgIGlmIChub29wICE9PSByZXNvbHZlcikgewogICAgICAgIHR5cGVvZiByZXNvbHZlciAhPT0gJ2Z1bmN0aW9uJyAmJiBuZWVkc1Jlc29sdmVyKCk7CiAgICAgICAgdGhpcyBpbnN0YW5jZW9mIFByb21pc2UgPyBpbml0aWFsaXplUHJvbWlzZSh0aGlzLCByZXNvbHZlcikgOiBuZWVkc05ldygpOwogICAgICB9CiAgICB9CgogICAgdmFyIF9wcm90bzIgPSBQcm9taXNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8yLl9vbkVycm9yID0gZnVuY3Rpb24gX29uRXJyb3IocmVhc29uKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgY29uZmlnLmFmdGVyKGZ1bmN0aW9uICgpIHsKICAgICAgICBpZiAoX3RoaXMyLl9vbkVycm9yKSB7CiAgICAgICAgICBjb25maWcudHJpZ2dlcignZXJyb3InLCByZWFzb24sIF90aGlzMi5fbGFiZWwpOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CiAgICAvKioKICAgICAgYGNhdGNoYCBpcyBzaW1wbHkgc3VnYXIgZm9yIGB0aGVuKHVuZGVmaW5lZCwgb25SZWplY3Rpb24pYCB3aGljaCBtYWtlcyBpdCB0aGUgc2FtZQogICAgICBhcyB0aGUgY2F0Y2ggYmxvY2sgb2YgYSB0cnkvY2F0Y2ggc3RhdGVtZW50LgogICAgCiAgICAgIGBgYGpzCiAgICAgIGZ1bmN0aW9uIGZpbmRBdXRob3IoKXsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkblwndCBmaW5kIHRoYXQgYXV0aG9yJyk7CiAgICAgIH0KICAgIAogICAgICAvLyBzeW5jaHJvbm91cwogICAgICB0cnkgewogICAgICAgIGZpbmRBdXRob3IoKTsKICAgICAgfSBjYXRjaChyZWFzb24pIHsKICAgICAgICAvLyBzb21ldGhpbmcgd2VudCB3cm9uZwogICAgICB9CiAgICAKICAgICAgLy8gYXN5bmMgd2l0aCBwcm9taXNlcwogICAgICBmaW5kQXV0aG9yKCkuY2F0Y2goZnVuY3Rpb24ocmVhc29uKXsKICAgICAgICAvLyBzb21ldGhpbmcgd2VudCB3cm9uZwogICAgICB9KTsKICAgICAgYGBgCiAgICAKICAgICAgQG1ldGhvZCBjYXRjaAogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGlvbgogICAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICAgIEByZXR1cm4ge1Byb21pc2V9CiAgICAqLwogICAgOwoKICAgIF9wcm90bzIuY2F0Y2ggPSBmdW5jdGlvbiBfY2F0Y2gob25SZWplY3Rpb24sIGxhYmVsKSB7CiAgICAgIHJldHVybiB0aGlzLnRoZW4odW5kZWZpbmVkLCBvblJlamVjdGlvbiwgbGFiZWwpOwogICAgfQogICAgLyoqCiAgICAgIGBmaW5hbGx5YCB3aWxsIGJlIGludm9rZWQgcmVnYXJkbGVzcyBvZiB0aGUgcHJvbWlzZSdzIGZhdGUganVzdCBhcyBuYXRpdmUKICAgICAgdHJ5L2NhdGNoL2ZpbmFsbHkgYmVoYXZlcwogICAgCiAgICAgIFN5bmNocm9ub3VzIGV4YW1wbGU6CiAgICAKICAgICAgYGBganMKICAgICAgZmluZEF1dGhvcigpIHsKICAgICAgICBpZiAoTWF0aC5yYW5kb20oKSA+IDAuNSkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgQXV0aG9yKCk7CiAgICAgIH0KICAgIAogICAgICB0cnkgewogICAgICAgIHJldHVybiBmaW5kQXV0aG9yKCk7IC8vIHN1Y2NlZWQgb3IgZmFpbAogICAgICB9IGNhdGNoKGVycm9yKSB7CiAgICAgICAgcmV0dXJuIGZpbmRPdGhlckF1dGhvcigpOwogICAgICB9IGZpbmFsbHkgewogICAgICAgIC8vIGFsd2F5cyBydW5zCiAgICAgICAgLy8gZG9lc24ndCBhZmZlY3QgdGhlIHJldHVybiB2YWx1ZQogICAgICB9CiAgICAgIGBgYAogICAgCiAgICAgIEFzeW5jaHJvbm91cyBleGFtcGxlOgogICAgCiAgICAgIGBgYGpzCiAgICAgIGZpbmRBdXRob3IoKS5jYXRjaChmdW5jdGlvbihyZWFzb24pewogICAgICAgIHJldHVybiBmaW5kT3RoZXJBdXRob3IoKTsKICAgICAgfSkuZmluYWxseShmdW5jdGlvbigpewogICAgICAgIC8vIGF1dGhvciB3YXMgZWl0aGVyIGZvdW5kLCBvciBub3QKICAgICAgfSk7CiAgICAgIGBgYAogICAgCiAgICAgIEBtZXRob2QgZmluYWxseQogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjawogICAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICAgIEByZXR1cm4ge1Byb21pc2V9CiAgICAqLwogICAgOwoKICAgIF9wcm90bzIuZmluYWxseSA9IGZ1bmN0aW9uIF9maW5hbGx5KGNhbGxiYWNrLCBsYWJlbCkgewogICAgICB2YXIgcHJvbWlzZSA9IHRoaXM7CiAgICAgIHZhciBjb25zdHJ1Y3RvciA9IHByb21pc2UuY29uc3RydWN0b3I7CgogICAgICBpZiAodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgICAgIHJldHVybiBjb25zdHJ1Y3Rvci5yZXNvbHZlKGNhbGxiYWNrKCkpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgICB9KTsKICAgICAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICByZXR1cm4gY29uc3RydWN0b3IucmVzb2x2ZShjYWxsYmFjaygpKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgdGhyb3cgcmVhc29uOwogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBwcm9taXNlLnRoZW4oY2FsbGJhY2ssIGNhbGxiYWNrKTsKICAgIH07CgogICAgcmV0dXJuIFByb21pc2U7CiAgfSgpOwoKICBfZXhwb3J0cy5Qcm9taXNlID0gUHJvbWlzZTsKICBQcm9taXNlLmNhc3QgPSByZXNvbHZlJCQxOyAvLyBkZXByZWNhdGVkCgogIFByb21pc2UuYWxsID0gYWxsOwogIFByb21pc2UucmFjZSA9IHJhY2U7CiAgUHJvbWlzZS5yZXNvbHZlID0gcmVzb2x2ZSQkMTsKICBQcm9taXNlLnJlamVjdCA9IHJlamVjdCQxOwogIFByb21pc2UucHJvdG90eXBlLl9ndWlkS2V5ID0gZ3VpZEtleTsKICAvKioKICAgIFRoZSBwcmltYXJ5IHdheSBvZiBpbnRlcmFjdGluZyB3aXRoIGEgcHJvbWlzZSBpcyB0aHJvdWdoIGl0cyBgdGhlbmAgbWV0aG9kLAogICAgd2hpY2ggcmVnaXN0ZXJzIGNhbGxiYWNrcyB0byByZWNlaXZlIGVpdGhlciBhIHByb21pc2UncyBldmVudHVhbCB2YWx1ZSBvciB0aGUKICAgIHJlYXNvbiB3aHkgdGhlIHByb21pc2UgY2Fubm90IGJlIGZ1bGZpbGxlZC4KICAKICAgIGBgYGpzCiAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24odXNlcil7CiAgICAgIC8vIHVzZXIgaXMgYXZhaWxhYmxlCiAgICB9LCBmdW5jdGlvbihyZWFzb24pewogICAgICAvLyB1c2VyIGlzIHVuYXZhaWxhYmxlLCBhbmQgeW91IGFyZSBnaXZlbiB0aGUgcmVhc29uIHdoeQogICAgfSk7CiAgICBgYGAKICAKICAgIENoYWluaW5nCiAgICAtLS0tLS0tLQogIAogICAgVGhlIHJldHVybiB2YWx1ZSBvZiBgdGhlbmAgaXMgaXRzZWxmIGEgcHJvbWlzZS4gIFRoaXMgc2Vjb25kLCAnZG93bnN0cmVhbScKICAgIHByb21pc2UgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBmaXJzdCBwcm9taXNlJ3MgZnVsZmlsbG1lbnQKICAgIG9yIHJlamVjdGlvbiBoYW5kbGVyLCBvciByZWplY3RlZCBpZiB0aGUgaGFuZGxlciB0aHJvd3MgYW4gZXhjZXB0aW9uLgogIAogICAgYGBganMKICAgIGZpbmRVc2VyKCkudGhlbihmdW5jdGlvbiAodXNlcikgewogICAgICByZXR1cm4gdXNlci5uYW1lOwogICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICByZXR1cm4gJ2RlZmF1bHQgbmFtZSc7CiAgICB9KS50aGVuKGZ1bmN0aW9uICh1c2VyTmFtZSkgewogICAgICAvLyBJZiBgZmluZFVzZXJgIGZ1bGZpbGxlZCwgYHVzZXJOYW1lYCB3aWxsIGJlIHRoZSB1c2VyJ3MgbmFtZSwgb3RoZXJ3aXNlIGl0CiAgICAgIC8vIHdpbGwgYmUgYCdkZWZhdWx0IG5hbWUnYAogICAgfSk7CiAgCiAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24gKHVzZXIpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdGb3VuZCB1c2VyLCBidXQgc3RpbGwgdW5oYXBweScpOwogICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ2BmaW5kVXNlcmAgcmVqZWN0ZWQgYW5kIHdlXCdyZSB1bmhhcHB5Jyk7CiAgICB9KS50aGVuKGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAvLyBuZXZlciByZWFjaGVkCiAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgIC8vIGlmIGBmaW5kVXNlcmAgZnVsZmlsbGVkLCBgcmVhc29uYCB3aWxsIGJlICdGb3VuZCB1c2VyLCBidXQgc3RpbGwgdW5oYXBweScuCiAgICAgIC8vIElmIGBmaW5kVXNlcmAgcmVqZWN0ZWQsIGByZWFzb25gIHdpbGwgYmUgJ2BmaW5kVXNlcmAgcmVqZWN0ZWQgYW5kIHdlXCdyZSB1bmhhcHB5Jy4KICAgIH0pOwogICAgYGBgCiAgICBJZiB0aGUgZG93bnN0cmVhbSBwcm9taXNlIGRvZXMgbm90IHNwZWNpZnkgYSByZWplY3Rpb24gaGFuZGxlciwgcmVqZWN0aW9uIHJlYXNvbnMgd2lsbCBiZSBwcm9wYWdhdGVkIGZ1cnRoZXIgZG93bnN0cmVhbS4KICAKICAgIGBgYGpzCiAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24gKHVzZXIpIHsKICAgICAgdGhyb3cgbmV3IFBlZGFnb2dpY2FsRXhjZXB0aW9uKCdVcHN0cmVhbSBlcnJvcicpOwogICAgfSkudGhlbihmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgLy8gbmV2ZXIgcmVhY2hlZAogICAgfSkudGhlbihmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgLy8gbmV2ZXIgcmVhY2hlZAogICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAvLyBUaGUgYFBlZGdhZ29jaWFsRXhjZXB0aW9uYCBpcyBwcm9wYWdhdGVkIGFsbCB0aGUgd2F5IGRvd24gdG8gaGVyZQogICAgfSk7CiAgICBgYGAKICAKICAgIEFzc2ltaWxhdGlvbgogICAgLS0tLS0tLS0tLS0tCiAgCiAgICBTb21ldGltZXMgdGhlIHZhbHVlIHlvdSB3YW50IHRvIHByb3BhZ2F0ZSB0byBhIGRvd25zdHJlYW0gcHJvbWlzZSBjYW4gb25seSBiZQogICAgcmV0cmlldmVkIGFzeW5jaHJvbm91c2x5LiBUaGlzIGNhbiBiZSBhY2hpZXZlZCBieSByZXR1cm5pbmcgYSBwcm9taXNlIGluIHRoZQogICAgZnVsZmlsbG1lbnQgb3IgcmVqZWN0aW9uIGhhbmRsZXIuIFRoZSBkb3duc3RyZWFtIHByb21pc2Ugd2lsbCB0aGVuIGJlIHBlbmRpbmcKICAgIHVudGlsIHRoZSByZXR1cm5lZCBwcm9taXNlIGlzIHNldHRsZWQuIFRoaXMgaXMgY2FsbGVkICphc3NpbWlsYXRpb24qLgogIAogICAgYGBganMKICAgIGZpbmRVc2VyKCkudGhlbihmdW5jdGlvbiAodXNlcikgewogICAgICByZXR1cm4gZmluZENvbW1lbnRzQnlBdXRob3IodXNlcik7CiAgICB9KS50aGVuKGZ1bmN0aW9uIChjb21tZW50cykgewogICAgICAvLyBUaGUgdXNlcidzIGNvbW1lbnRzIGFyZSBub3cgYXZhaWxhYmxlCiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgdGhlIGFzc2ltbGlhdGVkIHByb21pc2UgcmVqZWN0cywgdGhlbiB0aGUgZG93bnN0cmVhbSBwcm9taXNlIHdpbGwgYWxzbyByZWplY3QuCiAgCiAgICBgYGBqcwogICAgZmluZFVzZXIoKS50aGVuKGZ1bmN0aW9uICh1c2VyKSB7CiAgICAgIHJldHVybiBmaW5kQ29tbWVudHNCeUF1dGhvcih1c2VyKTsKICAgIH0pLnRoZW4oZnVuY3Rpb24gKGNvbW1lbnRzKSB7CiAgICAgIC8vIElmIGBmaW5kQ29tbWVudHNCeUF1dGhvcmAgZnVsZmlsbHMsIHdlJ2xsIGhhdmUgdGhlIHZhbHVlIGhlcmUKICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgLy8gSWYgYGZpbmRDb21tZW50c0J5QXV0aG9yYCByZWplY3RzLCB3ZSdsbCBoYXZlIHRoZSByZWFzb24gaGVyZQogICAgfSk7CiAgICBgYGAKICAKICAgIFNpbXBsZSBFeGFtcGxlCiAgICAtLS0tLS0tLS0tLS0tLQogIAogICAgU3luY2hyb25vdXMgRXhhbXBsZQogIAogICAgYGBgamF2YXNjcmlwdAogICAgbGV0IHJlc3VsdDsKICAKICAgIHRyeSB7CiAgICAgIHJlc3VsdCA9IGZpbmRSZXN1bHQoKTsKICAgICAgLy8gc3VjY2VzcwogICAgfSBjYXRjaChyZWFzb24pIHsKICAgICAgLy8gZmFpbHVyZQogICAgfQogICAgYGBgCiAgCiAgICBFcnJiYWNrIEV4YW1wbGUKICAKICAgIGBgYGpzCiAgICBmaW5kUmVzdWx0KGZ1bmN0aW9uKHJlc3VsdCwgZXJyKXsKICAgICAgaWYgKGVycikgewogICAgICAgIC8vIGZhaWx1cmUKICAgICAgfSBlbHNlIHsKICAgICAgICAvLyBzdWNjZXNzCiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBQcm9taXNlIEV4YW1wbGU7CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBmaW5kUmVzdWx0KCkudGhlbihmdW5jdGlvbihyZXN1bHQpewogICAgICAvLyBzdWNjZXNzCiAgICB9LCBmdW5jdGlvbihyZWFzb24pewogICAgICAvLyBmYWlsdXJlCiAgICB9KTsKICAgIGBgYAogIAogICAgQWR2YW5jZWQgRXhhbXBsZQogICAgLS0tLS0tLS0tLS0tLS0KICAKICAgIFN5bmNocm9ub3VzIEV4YW1wbGUKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCBhdXRob3IsIGJvb2tzOwogIAogICAgdHJ5IHsKICAgICAgYXV0aG9yID0gZmluZEF1dGhvcigpOwogICAgICBib29rcyAgPSBmaW5kQm9va3NCeUF1dGhvcihhdXRob3IpOwogICAgICAvLyBzdWNjZXNzCiAgICB9IGNhdGNoKHJlYXNvbikgewogICAgICAvLyBmYWlsdXJlCiAgICB9CiAgICBgYGAKICAKICAgIEVycmJhY2sgRXhhbXBsZQogIAogICAgYGBganMKICAKICAgIGZ1bmN0aW9uIGZvdW5kQm9va3MoYm9va3MpIHsKICAKICAgIH0KICAKICAgIGZ1bmN0aW9uIGZhaWx1cmUocmVhc29uKSB7CiAgCiAgICB9CiAgCiAgICBmaW5kQXV0aG9yKGZ1bmN0aW9uKGF1dGhvciwgZXJyKXsKICAgICAgaWYgKGVycikgewogICAgICAgIGZhaWx1cmUoZXJyKTsKICAgICAgICAvLyBmYWlsdXJlCiAgICAgIH0gZWxzZSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGZpbmRCb29va3NCeUF1dGhvcihhdXRob3IsIGZ1bmN0aW9uKGJvb2tzLCBlcnIpIHsKICAgICAgICAgICAgaWYgKGVycikgewogICAgICAgICAgICAgIGZhaWx1cmUoZXJyKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgZm91bmRCb29rcyhib29rcyk7CiAgICAgICAgICAgICAgfSBjYXRjaChyZWFzb24pIHsKICAgICAgICAgICAgICAgIGZhaWx1cmUocmVhc29uKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0gY2F0Y2goZXJyb3IpIHsKICAgICAgICAgIGZhaWx1cmUoZXJyKTsKICAgICAgICB9CiAgICAgICAgLy8gc3VjY2VzcwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgUHJvbWlzZSBFeGFtcGxlOwogIAogICAgYGBgamF2YXNjcmlwdAogICAgZmluZEF1dGhvcigpLgogICAgICB0aGVuKGZpbmRCb29rc0J5QXV0aG9yKS4KICAgICAgdGhlbihmdW5jdGlvbihib29rcyl7CiAgICAgICAgLy8gZm91bmQgYm9va3MKICAgIH0pLmNhdGNoKGZ1bmN0aW9uKHJlYXNvbil7CiAgICAgIC8vIHNvbWV0aGluZyB3ZW50IHdyb25nCiAgICB9KTsKICAgIGBgYAogIAogICAgQG1ldGhvZCB0aGVuCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvbkZ1bGZpbGxtZW50CiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGlvbgogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGZvciBsYWJlbGluZyB0aGUgcHJvbWlzZS4KICAgIFVzZWZ1bCBmb3IgdG9vbGluZy4KICAgIEByZXR1cm4ge1Byb21pc2V9CiAgKi8KCiAgUHJvbWlzZS5wcm90b3R5cGUudGhlbiA9IHRoZW47CgogIGZ1bmN0aW9uIG1ha2VPYmplY3QoXywgYXJndW1lbnROYW1lcykgewogICAgdmFyIG9iaiA9IHt9OwogICAgdmFyIGxlbmd0aCA9IF8ubGVuZ3RoOwogICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkobGVuZ3RoKTsKCiAgICBmb3IgKHZhciB4ID0gMDsgeCA8IGxlbmd0aDsgeCsrKSB7CiAgICAgIGFyZ3NbeF0gPSBfW3hdOwogICAgfQoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnROYW1lcy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgbmFtZSA9IGFyZ3VtZW50TmFtZXNbaV07CiAgICAgIG9ialtuYW1lXSA9IGFyZ3NbaSArIDFdOwogICAgfQoKICAgIHJldHVybiBvYmo7CiAgfQoKICBmdW5jdGlvbiBhcnJheVJlc3VsdChfKSB7CiAgICB2YXIgbGVuZ3RoID0gXy5sZW5ndGg7CiAgICB2YXIgYXJncyA9IG5ldyBBcnJheShsZW5ndGggLSAxKTsKCiAgICBmb3IgKHZhciBpID0gMTsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIGFyZ3NbaSAtIDFdID0gX1tpXTsKICAgIH0KCiAgICByZXR1cm4gYXJnczsKICB9CgogIGZ1bmN0aW9uIHdyYXBUaGVuYWJsZShfdGhlbiwgcHJvbWlzZSkgewogICAgcmV0dXJuIHsKICAgICAgdGhlbjogZnVuY3Rpb24gdGhlbihvbkZ1bEZpbGxtZW50LCBvblJlamVjdGlvbikgewogICAgICAgIHJldHVybiBfdGhlbi5jYWxsKHByb21pc2UsIG9uRnVsRmlsbG1lbnQsIG9uUmVqZWN0aW9uKTsKICAgICAgfQogICAgfTsKICB9CiAgLyoqCiAgICBgZGVub2RlaWZ5YCB0YWtlcyBhICdub2RlLXN0eWxlJyBmdW5jdGlvbiBhbmQgcmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQKICAgIHdpbGwgcmV0dXJuIGFuIGBQcm9taXNlYC4gWW91IGNhbiB1c2UgYGRlbm9kZWlmeWAgaW4gTm9kZS5qcyBvciB0aGUKICAgIGJyb3dzZXIgd2hlbiB5b3UnZCBwcmVmZXIgdG8gdXNlIHByb21pc2VzIG92ZXIgdXNpbmcgY2FsbGJhY2tzLiBGb3IgZXhhbXBsZSwKICAgIGBkZW5vZGVpZnlgIHRyYW5zZm9ybXMgdGhlIGZvbGxvd2luZzoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCBmcyA9IHJlcXVpcmUoJ2ZzJyk7CiAgCiAgICBmcy5yZWFkRmlsZSgnbXlmaWxlLnR4dCcsIGZ1bmN0aW9uKGVyciwgZGF0YSl7CiAgICAgIGlmIChlcnIpIHJldHVybiBoYW5kbGVFcnJvcihlcnIpOwogICAgICBoYW5kbGVEYXRhKGRhdGEpOwogICAgfSk7CiAgICBgYGAKICAKICAgIGludG86CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBsZXQgZnMgPSByZXF1aXJlKCdmcycpOwogICAgbGV0IHJlYWRGaWxlID0gZGVub2RlaWZ5KGZzLnJlYWRGaWxlKTsKICAKICAgIHJlYWRGaWxlKCdteWZpbGUudHh0JykudGhlbihoYW5kbGVEYXRhLCBoYW5kbGVFcnJvcik7CiAgICBgYGAKICAKICAgIElmIHRoZSBub2RlIGZ1bmN0aW9uIGhhcyBtdWx0aXBsZSBzdWNjZXNzIHBhcmFtZXRlcnMsIHRoZW4gYGRlbm9kZWlmeWAKICAgIGp1c3QgcmV0dXJucyB0aGUgZmlyc3Qgb25lOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgbGV0IHJlcXVlc3QgPSBkZW5vZGVpZnkocmVxdWlyZSgncmVxdWVzdCcpKTsKICAKICAgIHJlcXVlc3QoJ2h0dHA6Ly9leGFtcGxlLmNvbScpLnRoZW4oZnVuY3Rpb24ocmVzKSB7CiAgICAgIC8vIC4uLgogICAgfSk7CiAgICBgYGAKICAKICAgIEhvd2V2ZXIsIGlmIHlvdSBuZWVkIGFsbCBzdWNjZXNzIHBhcmFtZXRlcnMsIHNldHRpbmcgYGRlbm9kZWlmeWAncwogICAgc2Vjb25kIHBhcmFtZXRlciB0byBgdHJ1ZWAgY2F1c2VzIGl0IHRvIHJldHVybiBhbGwgc3VjY2VzcyBwYXJhbWV0ZXJzCiAgICBhcyBhbiBhcnJheToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCByZXF1ZXN0ID0gZGVub2RlaWZ5KHJlcXVpcmUoJ3JlcXVlc3QnKSwgdHJ1ZSk7CiAgCiAgICByZXF1ZXN0KCdodHRwOi8vZXhhbXBsZS5jb20nKS50aGVuKGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAvLyByZXN1bHRbMF0gLT4gcmVzCiAgICAgIC8vIHJlc3VsdFsxXSAtPiBib2R5CiAgICB9KTsKICAgIGBgYAogIAogICAgT3IgaWYgeW91IHBhc3MgaXQgYW4gYXJyYXkgd2l0aCBuYW1lcyBpdCByZXR1cm5zIHRoZSBwYXJhbWV0ZXJzIGFzIGEgaGFzaDoKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCByZXF1ZXN0ID0gZGVub2RlaWZ5KHJlcXVpcmUoJ3JlcXVlc3QnKSwgWydyZXMnLCAnYm9keSddKTsKICAKICAgIHJlcXVlc3QoJ2h0dHA6Ly9leGFtcGxlLmNvbScpLnRoZW4oZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgIC8vIHJlc3VsdC5yZXMKICAgICAgLy8gcmVzdWx0LmJvZHkKICAgIH0pOwogICAgYGBgCiAgCiAgICBTb21ldGltZXMgeW91IG5lZWQgdG8gcmV0YWluIHRoZSBgdGhpc2A6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBsZXQgYXBwID0gcmVxdWlyZSgnZXhwcmVzcycpKCk7CiAgICBsZXQgcmVuZGVyID0gZGVub2RlaWZ5KGFwcC5yZW5kZXIuYmluZChhcHApKTsKICAgIGBgYAogIAogICAgVGhlIGRlbm9kaWZpZWQgZnVuY3Rpb24gaW5oZXJpdHMgZnJvbSB0aGUgb3JpZ2luYWwgZnVuY3Rpb24uIEl0IHdvcmtzIGluIGFsbAogICAgZW52aXJvbm1lbnRzLCBleGNlcHQgSUUgMTAgYW5kIGJlbG93LiBDb25zZXF1ZW50bHkgYWxsIHByb3BlcnRpZXMgb2YgdGhlIG9yaWdpbmFsCiAgICBmdW5jdGlvbiBhcmUgYXZhaWxhYmxlIHRvIHlvdS4gSG93ZXZlciwgYW55IHByb3BlcnRpZXMgeW91IGNoYW5nZSBvbiB0aGUKICAgIGRlbm9kZWlmaWVkIGZ1bmN0aW9uIHdvbid0IGJlIGNoYW5nZWQgb24gdGhlIG9yaWdpbmFsIGZ1bmN0aW9uLiBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgbGV0IHJlcXVlc3QgPSBkZW5vZGVpZnkocmVxdWlyZSgncmVxdWVzdCcpKSwKICAgICAgICBjb29raWVKYXIgPSByZXF1ZXN0LmphcigpOyAvLyA8LSBJbmhlcml0YW5jZSBpcyB1c2VkIGhlcmUKICAKICAgIHJlcXVlc3QoJ2h0dHA6Ly9leGFtcGxlLmNvbScsIHtqYXI6IGNvb2tpZUphcn0pLnRoZW4oZnVuY3Rpb24ocmVzKSB7CiAgICAgIC8vIGNvb2tpZUphci5jb29raWVzIGhvbGRzIG5vdyB0aGUgY29va2llcyByZXR1cm5lZCBieSBleGFtcGxlLmNvbQogICAgfSk7CiAgICBgYGAKICAKICAgIFVzaW5nIGBkZW5vZGVpZnlgIG1ha2VzIGl0IGVhc2llciB0byBjb21wb3NlIGFzeW5jaHJvbm91cyBvcGVyYXRpb25zIGluc3RlYWQKICAgIG9mIHVzaW5nIGNhbGxiYWNrcy4gRm9yIGV4YW1wbGUsIGluc3RlYWQgb2Y6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBsZXQgZnMgPSByZXF1aXJlKCdmcycpOwogIAogICAgZnMucmVhZEZpbGUoJ215ZmlsZS50eHQnLCBmdW5jdGlvbihlcnIsIGRhdGEpewogICAgICBpZiAoZXJyKSB7IC4uLiB9IC8vIEhhbmRsZSBlcnJvcgogICAgICBmcy53cml0ZUZpbGUoJ215ZmlsZTIudHh0JywgZGF0YSwgZnVuY3Rpb24oZXJyKXsKICAgICAgICBpZiAoZXJyKSB7IC4uLiB9IC8vIEhhbmRsZSBlcnJvcgogICAgICAgIGNvbnNvbGUubG9nKCdkb25lJykKICAgICAgfSk7CiAgICB9KTsKICAgIGBgYAogIAogICAgeW91IGNhbiBjaGFpbiB0aGUgb3BlcmF0aW9ucyB0b2dldGhlciB1c2luZyBgdGhlbmAgZnJvbSB0aGUgcmV0dXJuZWQgcHJvbWlzZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCBmcyA9IHJlcXVpcmUoJ2ZzJyk7CiAgICBsZXQgcmVhZEZpbGUgPSBkZW5vZGVpZnkoZnMucmVhZEZpbGUpOwogICAgbGV0IHdyaXRlRmlsZSA9IGRlbm9kZWlmeShmcy53cml0ZUZpbGUpOwogIAogICAgcmVhZEZpbGUoJ215ZmlsZS50eHQnKS50aGVuKGZ1bmN0aW9uKGRhdGEpewogICAgICByZXR1cm4gd3JpdGVGaWxlKCdteWZpbGUyLnR4dCcsIGRhdGEpOwogICAgfSkudGhlbihmdW5jdGlvbigpewogICAgICBjb25zb2xlLmxvZygnZG9uZScpCiAgICB9KS5jYXRjaChmdW5jdGlvbihlcnJvcil7CiAgICAgIC8vIEhhbmRsZSBlcnJvcgogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgZGVub2RlaWZ5CiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIHJzdnAKICAgIEBwYXJhbSB7RnVuY3Rpb259IG5vZGVGdW5jIGEgJ25vZGUtc3R5bGUnIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSBjYWxsYmFjayBhcwogICAgaXRzIGxhc3QgYXJndW1lbnQuIFRoZSBjYWxsYmFjayBleHBlY3RzIGFuIGVycm9yIHRvIGJlIHBhc3NlZCBhcyBpdHMgZmlyc3QKICAgIGFyZ3VtZW50IChpZiBhbiBlcnJvciBvY2N1cnJlZCwgb3RoZXJ3aXNlIG51bGwpLCBhbmQgdGhlIHZhbHVlIGZyb20gdGhlCiAgICBvcGVyYXRpb24gYXMgaXRzIHNlY29uZCBhcmd1bWVudCAoJ2Z1bmN0aW9uKGVyciwgdmFsdWUpeyB9JykuCiAgICBAcGFyYW0ge0Jvb2xlYW58QXJyYXl9IFtvcHRpb25zXSBBbiBvcHRpb25hbCBwYXJhbXRlciB0aGF0IGlmIHNldAogICAgdG8gYHRydWVgIGNhdXNlcyB0aGUgcHJvbWlzZSB0byBmdWxmaWxsIHdpdGggdGhlIGNhbGxiYWNrJ3Mgc3VjY2VzcyBhcmd1bWVudHMKICAgIGFzIGFuIGFycmF5LiBUaGlzIGlzIHVzZWZ1bCBpZiB0aGUgbm9kZSBmdW5jdGlvbiBoYXMgbXVsdGlwbGUgc3VjY2VzcwogICAgcGFyYW10ZXJzLiBJZiB5b3Ugc2V0IHRoaXMgcGFyYW10ZXIgdG8gYW4gYXJyYXkgd2l0aCBuYW1lcywgdGhlIHByb21pc2Ugd2lsbAogICAgZnVsZmlsbCB3aXRoIGEgaGFzaCB3aXRoIHRoZXNlIG5hbWVzIGFzIGtleXMgYW5kIHRoZSBzdWNjZXNzIHBhcmFtZXRlcnMgYXMKICAgIHZhbHVlcy4KICAgIEByZXR1cm4ge0Z1bmN0aW9ufSBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYG5vZGVGdW5jYCB0byByZXR1cm4gYSBgUHJvbWlzZWAKICAqLwoKCiAgZnVuY3Rpb24gZGVub2RlaWZ5KG5vZGVGdW5jLCBvcHRpb25zKSB7CiAgICB2YXIgZm4gPSBmdW5jdGlvbiBmbigpIHsKICAgICAgdmFyIGwgPSBhcmd1bWVudHMubGVuZ3RoOwogICAgICB2YXIgYXJncyA9IG5ldyBBcnJheShsICsgMSk7CiAgICAgIHZhciBwcm9taXNlSW5wdXQgPSBmYWxzZTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgKytpKSB7CiAgICAgICAgdmFyIGFyZyA9IGFyZ3VtZW50c1tpXTsgLy8gVE9ETzogdGhpcyBjb2RlIHJlYWxseSBuZWVkcyB0byBiZSBjbGVhbmVkIHVwCgogICAgICAgIGlmICghcHJvbWlzZUlucHV0KSB7CiAgICAgICAgICBpZiAoYXJnICE9PSBudWxsICYmIHR5cGVvZiBhcmcgPT09ICdvYmplY3QnKSB7CiAgICAgICAgICAgIGlmIChhcmcuY29uc3RydWN0b3IgPT09IFByb21pc2UpIHsKICAgICAgICAgICAgICBwcm9taXNlSW5wdXQgPSB0cnVlOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBwcm9taXNlSW5wdXQgPSBhcmcudGhlbjsKICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgdmFyIHAgPSBuZXcgUHJvbWlzZShub29wKTsKICAgICAgICAgICAgICAgIHJlamVjdChwLCBlcnJvcik7CiAgICAgICAgICAgICAgICByZXR1cm4gcDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHByb21pc2VJbnB1dCA9IGZhbHNlOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChwcm9taXNlSW5wdXQgJiYgcHJvbWlzZUlucHV0ICE9PSB0cnVlKSB7CiAgICAgICAgICAgIGFyZyA9IHdyYXBUaGVuYWJsZShwcm9taXNlSW5wdXQsIGFyZyk7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBhcmdzW2ldID0gYXJnOwogICAgICB9CgogICAgICB2YXIgcHJvbWlzZSA9IG5ldyBQcm9taXNlKG5vb3ApOwoKICAgICAgYXJnc1tsXSA9IGZ1bmN0aW9uIChlcnIsIHZhbCkgewogICAgICAgIGlmIChlcnIpIHsKICAgICAgICAgIHJlamVjdChwcm9taXNlLCBlcnIpOwogICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICByZXNvbHZlJDEocHJvbWlzZSwgdmFsKTsKICAgICAgICB9IGVsc2UgaWYgKG9wdGlvbnMgPT09IHRydWUpIHsKICAgICAgICAgIHJlc29sdmUkMShwcm9taXNlLCBhcnJheVJlc3VsdChhcmd1bWVudHMpKTsKICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucykpIHsKICAgICAgICAgIHJlc29sdmUkMShwcm9taXNlLCBtYWtlT2JqZWN0KGFyZ3VtZW50cywgb3B0aW9ucykpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXNvbHZlJDEocHJvbWlzZSwgdmFsKTsKICAgICAgICB9CiAgICAgIH07CgogICAgICBpZiAocHJvbWlzZUlucHV0KSB7CiAgICAgICAgcmV0dXJuIGhhbmRsZVByb21pc2VJbnB1dChwcm9taXNlLCBhcmdzLCBub2RlRnVuYywgdGhpcyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGhhbmRsZVZhbHVlSW5wdXQocHJvbWlzZSwgYXJncywgbm9kZUZ1bmMsIHRoaXMpOwogICAgICB9CiAgICB9OwoKICAgIGZuLl9fcHJvdG9fXyA9IG5vZGVGdW5jOwogICAgcmV0dXJuIGZuOwogIH0KCiAgZnVuY3Rpb24gaGFuZGxlVmFsdWVJbnB1dChwcm9taXNlLCBhcmdzLCBub2RlRnVuYywgc2VsZikgewogICAgdHJ5IHsKICAgICAgbm9kZUZ1bmMuYXBwbHkoc2VsZiwgYXJncyk7CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgICByZWplY3QocHJvbWlzZSwgZXJyb3IpOwogICAgfQoKICAgIHJldHVybiBwcm9taXNlOwogIH0KCiAgZnVuY3Rpb24gaGFuZGxlUHJvbWlzZUlucHV0KHByb21pc2UsIGFyZ3MsIG5vZGVGdW5jLCBzZWxmKSB7CiAgICByZXR1cm4gUHJvbWlzZS5hbGwoYXJncykudGhlbihmdW5jdGlvbiAoYXJncykgewogICAgICByZXR1cm4gaGFuZGxlVmFsdWVJbnB1dChwcm9taXNlLCBhcmdzLCBub2RlRnVuYywgc2VsZik7CiAgICB9KTsKICB9CiAgLyoqCiAgICBUaGlzIGlzIGEgY29udmVuaWVudCBhbGlhcyBmb3IgYFByb21pc2UuYWxsYC4KICAKICAgIEBtZXRob2QgYWxsCiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIHJzdnAKICAgIEBwYXJhbSB7QXJyYXl9IGFycmF5IEFycmF5IG9mIHByb21pc2VzLgogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gQW4gb3B0aW9uYWwgbGFiZWwuIFRoaXMgaXMgdXNlZnVsCiAgICBmb3IgdG9vbGluZy4KICAqLwoKCiAgZnVuY3Rpb24gYWxsJDEoYXJyYXksIGxhYmVsKSB7CiAgICByZXR1cm4gUHJvbWlzZS5hbGwoYXJyYXksIGxhYmVsKTsKICB9CiAgLyoqCiAgQG1vZHVsZSByc3ZwCiAgQHB1YmxpYwogICoqLwoKCiAgdmFyIEFsbFNldHRsZWQgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0VudW1lcmF0b3IpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShBbGxTZXR0bGVkLCBfRW51bWVyYXRvcik7CgogICAgZnVuY3Rpb24gQWxsU2V0dGxlZChDb25zdHJ1Y3RvciwgZW50cmllcywgbGFiZWwpIHsKICAgICAgcmV0dXJuIF9FbnVtZXJhdG9yLmNhbGwodGhpcywgQ29uc3RydWN0b3IsIGVudHJpZXMsIGZhbHNlCiAgICAgIC8qIGRvbid0IGFib3J0IG9uIHJlamVjdCAqLwogICAgICAsIGxhYmVsKSB8fCB0aGlzOwogICAgfQoKICAgIHJldHVybiBBbGxTZXR0bGVkOwogIH0oRW51bWVyYXRvcik7CgogIEFsbFNldHRsZWQucHJvdG90eXBlLl9zZXRSZXN1bHRBdCA9IHNldFNldHRsZWRSZXN1bHQ7CiAgLyoqCiAgYFJTVlAuYWxsU2V0dGxlZGAgaXMgc2ltaWxhciB0byBgUlNWUC5hbGxgLCBidXQgaW5zdGVhZCBvZiBpbXBsZW1lbnRpbmcKICBhIGZhaWwtZmFzdCBtZXRob2QsIGl0IHdhaXRzIHVudGlsIGFsbCB0aGUgcHJvbWlzZXMgaGF2ZSByZXR1cm5lZCBhbmQKICBzaG93cyB5b3UgYWxsIHRoZSByZXN1bHRzLiBUaGlzIGlzIHVzZWZ1bCBpZiB5b3Ugd2FudCB0byBoYW5kbGUgbXVsdGlwbGUKICBwcm9taXNlcycgZmFpbHVyZSBzdGF0ZXMgdG9nZXRoZXIgYXMgYSBzZXQuCiAgIFJldHVybnMgYSBwcm9taXNlIHRoYXQgaXMgZnVsZmlsbGVkIHdoZW4gYWxsIHRoZSBnaXZlbiBwcm9taXNlcyBoYXZlIGJlZW4KICBzZXR0bGVkLiBUaGUgcmV0dXJuIHByb21pc2UgaXMgZnVsZmlsbGVkIHdpdGggYW4gYXJyYXkgb2YgdGhlIHN0YXRlcyBvZgogIHRoZSBwcm9taXNlcyBwYXNzZWQgaW50byB0aGUgYHByb21pc2VzYCBhcnJheSBhcmd1bWVudC4KICAgRWFjaCBzdGF0ZSBvYmplY3Qgd2lsbCBlaXRoZXIgaW5kaWNhdGUgZnVsZmlsbG1lbnQgb3IgcmVqZWN0aW9uLCBhbmQKICBwcm92aWRlIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlIG9yIHJlYXNvbi4gVGhlIHN0YXRlcyB3aWxsIHRha2Ugb25lIG9mCiAgdGhlIGZvbGxvd2luZyBmb3JtYXRzOgogICBgYGBqYXZhc2NyaXB0CiAgeyBzdGF0ZTogJ2Z1bGZpbGxlZCcsIHZhbHVlOiB2YWx1ZSB9CiAgICBvcgogIHsgc3RhdGU6ICdyZWplY3RlZCcsIHJlYXNvbjogcmVhc29uIH0KICBgYGAKICAgRXhhbXBsZToKICAgYGBgamF2YXNjcmlwdAogIGxldCBwcm9taXNlMSA9IFJTVlAuUHJvbWlzZS5yZXNvbHZlKDEpOwogIGxldCBwcm9taXNlMiA9IFJTVlAuUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCcyJykpOwogIGxldCBwcm9taXNlMyA9IFJTVlAuUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCczJykpOwogIGxldCBwcm9taXNlcyA9IFsgcHJvbWlzZTEsIHByb21pc2UyLCBwcm9taXNlMyBdOwogICBSU1ZQLmFsbFNldHRsZWQocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oYXJyYXkpewogICAgLy8gYXJyYXkgPT0gWwogICAgLy8gICB7IHN0YXRlOiAnZnVsZmlsbGVkJywgdmFsdWU6IDEgfSwKICAgIC8vICAgeyBzdGF0ZTogJ3JlamVjdGVkJywgcmVhc29uOiBFcnJvciB9LAogICAgLy8gICB7IHN0YXRlOiAncmVqZWN0ZWQnLCByZWFzb246IEVycm9yIH0KICAgIC8vIF0KICAgIC8vIE5vdGUgdGhhdCBmb3IgdGhlIHNlY29uZCBpdGVtLCByZWFzb24ubWVzc2FnZSB3aWxsIGJlICcyJywgYW5kIGZvciB0aGUKICAgIC8vIHRoaXJkIGl0ZW0sIHJlYXNvbi5tZXNzYWdlIHdpbGwgYmUgJzMnLgogIH0sIGZ1bmN0aW9uKGVycm9yKSB7CiAgICAvLyBOb3QgcnVuLiAoVGhpcyBibG9jayB3b3VsZCBvbmx5IGJlIGNhbGxlZCBpZiBhbGxTZXR0bGVkIGhhZCBmYWlsZWQsCiAgICAvLyBmb3IgaW5zdGFuY2UgaWYgcGFzc2VkIGFuIGluY29ycmVjdCBhcmd1bWVudCB0eXBlLikKICB9KTsKICBgYGAKICAgQG1ldGhvZCBhbGxTZXR0bGVkCiAgQHB1YmxpYwogIEBzdGF0aWMKICBAZm9yIHJzdnAKICBAcGFyYW0ge0FycmF5fSBlbnRyaWVzCiAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gLSBvcHRpb25hbCBzdHJpbmcgdGhhdCBkZXNjcmliZXMgdGhlIHByb21pc2UuCiAgVXNlZnVsIGZvciB0b29saW5nLgogIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UgdGhhdCBpcyBmdWxmaWxsZWQgd2l0aCBhbiBhcnJheSBvZiB0aGUgc2V0dGxlZAogIHN0YXRlcyBvZiB0aGUgY29uc3RpdHVlbnQgcHJvbWlzZXMuCiAgKi8KCiAgZnVuY3Rpb24gYWxsU2V0dGxlZChlbnRyaWVzLCBsYWJlbCkgewogICAgaWYgKCFBcnJheS5pc0FycmF5KGVudHJpZXMpKSB7CiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgVHlwZUVycm9yKCJQcm9taXNlLmFsbFNldHRsZWQgbXVzdCBiZSBjYWxsZWQgd2l0aCBhbiBhcnJheSIpLCBsYWJlbCk7CiAgICB9CgogICAgcmV0dXJuIG5ldyBBbGxTZXR0bGVkKFByb21pc2UsIGVudHJpZXMsIGxhYmVsKS5wcm9taXNlOwogIH0KICAvKioKICAgIFRoaXMgaXMgYSBjb252ZW5pZW50IGFsaWFzIGZvciBgUHJvbWlzZS5yYWNlYC4KICAKICAgIEBtZXRob2QgcmFjZQogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQGZvciByc3ZwCiAgICBAcGFyYW0ge0FycmF5fSBhcnJheSBBcnJheSBvZiBwcm9taXNlcy4KICAgIEBwYXJhbSB7U3RyaW5nfSBbbGFiZWxdIEFuIG9wdGlvbmFsIGxhYmVsLiBUaGlzIGlzIHVzZWZ1bAogICAgZm9yIHRvb2xpbmcuCiAgICovCgoKICBmdW5jdGlvbiByYWNlJDEoYXJyYXksIGxhYmVsKSB7CiAgICByZXR1cm4gUHJvbWlzZS5yYWNlKGFycmF5LCBsYWJlbCk7CiAgfQoKICB2YXIgUHJvbWlzZUhhc2ggPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0VudW1lcmF0b3IyKSB7CiAgICAoMCwgX2VtYmVyQmFiZWwuaW5oZXJpdHNMb29zZSkoUHJvbWlzZUhhc2gsIF9FbnVtZXJhdG9yMik7CgogICAgZnVuY3Rpb24gUHJvbWlzZUhhc2goQ29uc3RydWN0b3IsIG9iamVjdCwgYWJvcnRPblJlamVjdCwgbGFiZWwpIHsKICAgICAgaWYgKGFib3J0T25SZWplY3QgPT09IHZvaWQgMCkgewogICAgICAgIGFib3J0T25SZWplY3QgPSB0cnVlOwogICAgICB9CgogICAgICByZXR1cm4gX0VudW1lcmF0b3IyLmNhbGwodGhpcywgQ29uc3RydWN0b3IsIG9iamVjdCwgYWJvcnRPblJlamVjdCwgbGFiZWwpIHx8IHRoaXM7CiAgICB9CgogICAgdmFyIF9wcm90bzMgPSBQcm9taXNlSGFzaC5wcm90b3R5cGU7CgogICAgX3Byb3RvMy5faW5pdCA9IGZ1bmN0aW9uIF9pbml0KENvbnN0cnVjdG9yLCBvYmplY3QpIHsKICAgICAgdGhpcy5fcmVzdWx0ID0ge307CgogICAgICB0aGlzLl9lbnVtZXJhdGUob2JqZWN0KTsKICAgIH07CgogICAgX3Byb3RvMy5fZW51bWVyYXRlID0gZnVuY3Rpb24gX2VudW1lcmF0ZShpbnB1dCkgewogICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGlucHV0KTsKICAgICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoOwogICAgICB2YXIgcHJvbWlzZSA9IHRoaXMucHJvbWlzZTsKICAgICAgdGhpcy5fcmVtYWluaW5nID0gbGVuZ3RoOwogICAgICB2YXIga2V5LCB2YWw7CgogICAgICBmb3IgKHZhciBpID0gMDsgcHJvbWlzZS5fc3RhdGUgPT09IFBFTkRJTkcgJiYgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAga2V5ID0ga2V5c1tpXTsKICAgICAgICB2YWwgPSBpbnB1dFtrZXldOwoKICAgICAgICB0aGlzLl9lYWNoRW50cnkodmFsLCBrZXksIHRydWUpOwogICAgICB9CgogICAgICB0aGlzLl9jaGVja0Z1bGxmaWxsbWVudCgpOwogICAgfTsKCiAgICByZXR1cm4gUHJvbWlzZUhhc2g7CiAgfShFbnVtZXJhdG9yKTsKICAvKioKICAgIGBoYXNoYCBpcyBzaW1pbGFyIHRvIGBhbGxgLCBidXQgdGFrZXMgYW4gb2JqZWN0IGluc3RlYWQgb2YgYW4gYXJyYXkKICAgIGZvciBpdHMgYHByb21pc2VzYCBhcmd1bWVudC4KICAKICAgIFJldHVybnMgYSBwcm9taXNlIHRoYXQgaXMgZnVsZmlsbGVkIHdoZW4gYWxsIHRoZSBnaXZlbiBwcm9taXNlcyBoYXZlIGJlZW4KICAgIGZ1bGZpbGxlZCwgb3IgcmVqZWN0ZWQgaWYgYW55IG9mIHRoZW0gYmVjb21lIHJlamVjdGVkLiBUaGUgcmV0dXJuZWQgcHJvbWlzZQogICAgaXMgZnVsZmlsbGVkIHdpdGggYSBoYXNoIHRoYXQgaGFzIHRoZSBzYW1lIGtleSBuYW1lcyBhcyB0aGUgYHByb21pc2VzYCBvYmplY3QKICAgIGFyZ3VtZW50LiBJZiBhbnkgb2YgdGhlIHZhbHVlcyBpbiB0aGUgb2JqZWN0IGFyZSBub3QgcHJvbWlzZXMsIHRoZXkgd2lsbAogICAgc2ltcGx5IGJlIGNvcGllZCBvdmVyIHRvIHRoZSBmdWxmaWxsZWQgb2JqZWN0LgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGxldCBwcm9taXNlcyA9IHsKICAgICAgbXlQcm9taXNlOiByZXNvbHZlKDEpLAogICAgICB5b3VyUHJvbWlzZTogcmVzb2x2ZSgyKSwKICAgICAgdGhlaXJQcm9taXNlOiByZXNvbHZlKDMpLAogICAgICBub3RBUHJvbWlzZTogNAogICAgfTsKICAKICAgIGhhc2gocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oaGFzaCl7CiAgICAgIC8vIGhhc2ggaGVyZSBpcyBhbiBvYmplY3QgdGhhdCBsb29rcyBsaWtlOgogICAgICAvLyB7CiAgICAgIC8vICAgbXlQcm9taXNlOiAxLAogICAgICAvLyAgIHlvdXJQcm9taXNlOiAyLAogICAgICAvLyAgIHRoZWlyUHJvbWlzZTogMywKICAgICAgLy8gICBub3RBUHJvbWlzZTogNAogICAgICAvLyB9CiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgYW55IG9mIHRoZSBgcHJvbWlzZXNgIGdpdmVuIHRvIGBoYXNoYCBhcmUgcmVqZWN0ZWQsIHRoZSBmaXJzdCBwcm9taXNlCiAgICB0aGF0IGlzIHJlamVjdGVkIHdpbGwgYmUgZ2l2ZW4gYXMgdGhlIHJlYXNvbiB0byB0aGUgcmVqZWN0aW9uIGhhbmRsZXIuCiAgCiAgICBFeGFtcGxlOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgbGV0IHByb21pc2VzID0gewogICAgICBteVByb21pc2U6IHJlc29sdmUoMSksCiAgICAgIHJlamVjdGVkUHJvbWlzZTogcmVqZWN0KG5ldyBFcnJvcigncmVqZWN0ZWRQcm9taXNlJykpLAogICAgICBhbm90aGVyUmVqZWN0ZWRQcm9taXNlOiByZWplY3QobmV3IEVycm9yKCdhbm90aGVyUmVqZWN0ZWRQcm9taXNlJykpLAogICAgfTsKICAKICAgIGhhc2gocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oaGFzaCl7CiAgICAgIC8vIENvZGUgaGVyZSBuZXZlciBydW5zIGJlY2F1c2UgdGhlcmUgYXJlIHJlamVjdGVkIHByb21pc2VzIQogICAgfSwgZnVuY3Rpb24ocmVhc29uKSB7CiAgICAgIC8vIHJlYXNvbi5tZXNzYWdlID09PSAncmVqZWN0ZWRQcm9taXNlJwogICAgfSk7CiAgICBgYGAKICAKICAgIEFuIGltcG9ydGFudCBub3RlOiBgaGFzaGAgaXMgaW50ZW5kZWQgZm9yIHBsYWluIEphdmFTY3JpcHQgb2JqZWN0cyB0aGF0CiAgICBhcmUganVzdCBhIHNldCBvZiBrZXlzIGFuZCB2YWx1ZXMuIGBoYXNoYCB3aWxsIE5PVCBwcmVzZXJ2ZSBwcm90b3R5cGUKICAgIGNoYWlucy4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBoYXNoLCByZXNvbHZlIH0gZnJvbSAncnN2cCc7CiAgICBmdW5jdGlvbiBNeUNvbnN0cnVjdG9yKCl7CiAgICAgIHRoaXMuZXhhbXBsZSA9IHJlc29sdmUoJ0V4YW1wbGUnKTsKICAgIH0KICAKICAgIE15Q29uc3RydWN0b3IucHJvdG90eXBlID0gewogICAgICBwcm90b1Byb3BlcnR5OiByZXNvbHZlKCdQcm90byBQcm9wZXJ0eScpCiAgICB9OwogIAogICAgbGV0IG15T2JqZWN0ID0gbmV3IE15Q29uc3RydWN0b3IoKTsKICAKICAgIGhhc2gobXlPYmplY3QpLnRoZW4oZnVuY3Rpb24oaGFzaCl7CiAgICAgIC8vIHByb3RvUHJvcGVydHkgd2lsbCBub3QgYmUgcHJlc2VudCwgaW5zdGVhZCB5b3Ugd2lsbCBqdXN0IGhhdmUgYW4KICAgICAgLy8gb2JqZWN0IHRoYXQgbG9va3MgbGlrZToKICAgICAgLy8gewogICAgICAvLyAgIGV4YW1wbGU6ICdFeGFtcGxlJwogICAgICAvLyB9CiAgICAgIC8vCiAgICAgIC8vIGhhc2guaGFzT3duUHJvcGVydHkoJ3Byb3RvUHJvcGVydHknKTsgLy8gZmFsc2UKICAgICAgLy8gJ3VuZGVmaW5lZCcgPT09IHR5cGVvZiBoYXNoLnByb3RvUHJvcGVydHkKICAgIH0pOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGhhc2gKICAgIEBwdWJsaWMKICAgIEBzdGF0aWMKICAgIEBmb3IgcnN2cAogICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdAogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIHRoYXQgZGVzY3JpYmVzIHRoZSBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCB3aGVuIGFsbCBwcm9wZXJ0aWVzIG9mIGBwcm9taXNlc2AKICAgIGhhdmUgYmVlbiBmdWxmaWxsZWQsIG9yIHJlamVjdGVkIGlmIGFueSBvZiB0aGVtIGJlY29tZSByZWplY3RlZC4KICAqLwoKCiAgZnVuY3Rpb24gaGFzaChvYmplY3QsIGxhYmVsKSB7CiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG9iamVjdCwgbGFiZWwpLnRoZW4oZnVuY3Rpb24gKG9iamVjdCkgewogICAgICBpZiAob2JqZWN0ID09PSBudWxsIHx8IHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnKSB7CiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiUHJvbWlzZS5oYXNoIG11c3QgYmUgY2FsbGVkIHdpdGggYW4gb2JqZWN0Iik7CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXcgUHJvbWlzZUhhc2goUHJvbWlzZSwgb2JqZWN0LCBsYWJlbCkucHJvbWlzZTsKICAgIH0pOwogIH0KCiAgdmFyIEhhc2hTZXR0bGVkID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Qcm9taXNlSGFzaCkgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEhhc2hTZXR0bGVkLCBfUHJvbWlzZUhhc2gpOwoKICAgIGZ1bmN0aW9uIEhhc2hTZXR0bGVkKENvbnN0cnVjdG9yLCBvYmplY3QsIGxhYmVsKSB7CiAgICAgIHJldHVybiBfUHJvbWlzZUhhc2guY2FsbCh0aGlzLCBDb25zdHJ1Y3Rvciwgb2JqZWN0LCBmYWxzZSwgbGFiZWwpIHx8IHRoaXM7CiAgICB9CgogICAgcmV0dXJuIEhhc2hTZXR0bGVkOwogIH0oUHJvbWlzZUhhc2gpOwoKICBIYXNoU2V0dGxlZC5wcm90b3R5cGUuX3NldFJlc3VsdEF0ID0gc2V0U2V0dGxlZFJlc3VsdDsKICAvKioKICAgIGBoYXNoU2V0dGxlZGAgaXMgc2ltaWxhciB0byBgYWxsU2V0dGxlZGAsIGJ1dCB0YWtlcyBhbiBvYmplY3QKICAgIGluc3RlYWQgb2YgYW4gYXJyYXkgZm9yIGl0cyBgcHJvbWlzZXNgIGFyZ3VtZW50LgogIAogICAgVW5saWtlIGBhbGxgIG9yIGBoYXNoYCwgd2hpY2ggaW1wbGVtZW50IGEgZmFpbC1mYXN0IG1ldGhvZCwKICAgIGJ1dCBsaWtlIGBhbGxTZXR0bGVkYCwgYGhhc2hTZXR0bGVkYCB3YWl0cyB1bnRpbCBhbGwgdGhlCiAgICBjb25zdGl0dWVudCBwcm9taXNlcyBoYXZlIHJldHVybmVkIGFuZCB0aGVuIHNob3dzIHlvdSBhbGwgdGhlIHJlc3VsdHMKICAgIHdpdGggdGhlaXIgc3RhdGVzIGFuZCB2YWx1ZXMvcmVhc29ucy4gVGhpcyBpcyB1c2VmdWwgaWYgeW91IHdhbnQgdG8KICAgIGhhbmRsZSBtdWx0aXBsZSBwcm9taXNlcycgZmFpbHVyZSBzdGF0ZXMgdG9nZXRoZXIgYXMgYSBzZXQuCiAgCiAgICBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCB3aGVuIGFsbCB0aGUgZ2l2ZW4gcHJvbWlzZXMgaGF2ZSBiZWVuCiAgICBzZXR0bGVkLCBvciByZWplY3RlZCBpZiB0aGUgcGFzc2VkIHBhcmFtZXRlcnMgYXJlIGludmFsaWQuCiAgCiAgICBUaGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBmdWxmaWxsZWQgd2l0aCBhIGhhc2ggdGhhdCBoYXMgdGhlIHNhbWUga2V5IG5hbWVzIGFzCiAgICB0aGUgYHByb21pc2VzYCBvYmplY3QgYXJndW1lbnQuIElmIGFueSBvZiB0aGUgdmFsdWVzIGluIHRoZSBvYmplY3QgYXJlIG5vdAogICAgcHJvbWlzZXMsIHRoZXkgd2lsbCBiZSBjb3BpZWQgb3ZlciB0byB0aGUgZnVsZmlsbGVkIG9iamVjdCBhbmQgbWFya2VkIHdpdGggc3RhdGUKICAgICdmdWxmaWxsZWQnLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGhhc2hTZXR0bGVkLCByZXNvbHZlIH0gZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgcHJvbWlzZXMgPSB7CiAgICAgIG15UHJvbWlzZTogcmVzb2x2ZSgxKSwKICAgICAgeW91clByb21pc2U6IHJlc29sdmUoMiksCiAgICAgIHRoZWlyUHJvbWlzZTogcmVzb2x2ZSgzKSwKICAgICAgbm90QVByb21pc2U6IDQKICAgIH07CiAgCiAgICBoYXNoU2V0dGxlZChwcm9taXNlcykudGhlbihmdW5jdGlvbihoYXNoKXsKICAgICAgLy8gaGFzaCBoZXJlIGlzIGFuIG9iamVjdCB0aGF0IGxvb2tzIGxpa2U6CiAgICAgIC8vIHsKICAgICAgLy8gICBteVByb21pc2U6IHsgc3RhdGU6ICdmdWxmaWxsZWQnLCB2YWx1ZTogMSB9LAogICAgICAvLyAgIHlvdXJQcm9taXNlOiB7IHN0YXRlOiAnZnVsZmlsbGVkJywgdmFsdWU6IDIgfSwKICAgICAgLy8gICB0aGVpclByb21pc2U6IHsgc3RhdGU6ICdmdWxmaWxsZWQnLCB2YWx1ZTogMyB9LAogICAgICAvLyAgIG5vdEFQcm9taXNlOiB7IHN0YXRlOiAnZnVsZmlsbGVkJywgdmFsdWU6IDQgfQogICAgICAvLyB9CiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgYW55IG9mIHRoZSBgcHJvbWlzZXNgIGdpdmVuIHRvIGBoYXNoYCBhcmUgcmVqZWN0ZWQsIHRoZSBzdGF0ZSB3aWxsCiAgICBiZSBzZXQgdG8gJ3JlamVjdGVkJyBhbmQgdGhlIHJlYXNvbiBmb3IgcmVqZWN0aW9uIHByb3ZpZGVkLgogIAogICAgRXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGhhc2hTZXR0bGVkLCByZWplY3QsIHJlc29sdmUgfSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlcyA9IHsKICAgICAgbXlQcm9taXNlOiByZXNvbHZlKDEpLAogICAgICByZWplY3RlZFByb21pc2U6IHJlamVjdChuZXcgRXJyb3IoJ3JlamVjdGlvbicpKSwKICAgICAgYW5vdGhlclJlamVjdGVkUHJvbWlzZTogcmVqZWN0KG5ldyBFcnJvcignbW9yZSByZWplY3Rpb24nKSksCiAgICB9OwogIAogICAgaGFzaFNldHRsZWQocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oaGFzaCl7CiAgICAgIC8vIGhhc2ggaGVyZSBpcyBhbiBvYmplY3QgdGhhdCBsb29rcyBsaWtlOgogICAgICAvLyB7CiAgICAgIC8vICAgbXlQcm9taXNlOiAgICAgICAgICAgICAgeyBzdGF0ZTogJ2Z1bGZpbGxlZCcsIHZhbHVlOiAxIH0sCiAgICAgIC8vICAgcmVqZWN0ZWRQcm9taXNlOiAgICAgICAgeyBzdGF0ZTogJ3JlamVjdGVkJywgcmVhc29uOiBFcnJvciB9LAogICAgICAvLyAgIGFub3RoZXJSZWplY3RlZFByb21pc2U6IHsgc3RhdGU6ICdyZWplY3RlZCcsIHJlYXNvbjogRXJyb3IgfSwKICAgICAgLy8gfQogICAgICAvLyBOb3RlIHRoYXQgZm9yIHJlamVjdGVkUHJvbWlzZSwgcmVhc29uLm1lc3NhZ2UgPT0gJ3JlamVjdGlvbicsCiAgICAgIC8vIGFuZCBmb3IgYW5vdGhlclJlamVjdGVkUHJvbWlzZSwgcmVhc29uLm1lc3NhZ2UgPT0gJ21vcmUgcmVqZWN0aW9uJy4KICAgIH0pOwogICAgYGBgCiAgCiAgICBBbiBpbXBvcnRhbnQgbm90ZTogYGhhc2hTZXR0bGVkYCBpcyBpbnRlbmRlZCBmb3IgcGxhaW4gSmF2YVNjcmlwdCBvYmplY3RzIHRoYXQKICAgIGFyZSBqdXN0IGEgc2V0IG9mIGtleXMgYW5kIHZhbHVlcy4gYGhhc2hTZXR0bGVkYCB3aWxsIE5PVCBwcmVzZXJ2ZSBwcm90b3R5cGUKICAgIGNoYWlucy4KICAKICAgIEV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgUHJvbWlzZSwgeyBoYXNoU2V0dGxlZCwgcmVzb2x2ZSB9IGZyb20gJ3JzdnAnOwogIAogICAgZnVuY3Rpb24gTXlDb25zdHJ1Y3RvcigpewogICAgICB0aGlzLmV4YW1wbGUgPSByZXNvbHZlKCdFeGFtcGxlJyk7CiAgICB9CiAgCiAgICBNeUNvbnN0cnVjdG9yLnByb3RvdHlwZSA9IHsKICAgICAgcHJvdG9Qcm9wZXJ0eTogUHJvbWlzZS5yZXNvbHZlKCdQcm90byBQcm9wZXJ0eScpCiAgICB9OwogIAogICAgbGV0IG15T2JqZWN0ID0gbmV3IE15Q29uc3RydWN0b3IoKTsKICAKICAgIGhhc2hTZXR0bGVkKG15T2JqZWN0KS50aGVuKGZ1bmN0aW9uKGhhc2gpewogICAgICAvLyBwcm90b1Byb3BlcnR5IHdpbGwgbm90IGJlIHByZXNlbnQsIGluc3RlYWQgeW91IHdpbGwganVzdCBoYXZlIGFuCiAgICAgIC8vIG9iamVjdCB0aGF0IGxvb2tzIGxpa2U6CiAgICAgIC8vIHsKICAgICAgLy8gICBleGFtcGxlOiB7IHN0YXRlOiAnZnVsZmlsbGVkJywgdmFsdWU6ICdFeGFtcGxlJyB9CiAgICAgIC8vIH0KICAgICAgLy8KICAgICAgLy8gaGFzaC5oYXNPd25Qcm9wZXJ0eSgncHJvdG9Qcm9wZXJ0eScpOyAvLyBmYWxzZQogICAgICAvLyAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIGhhc2gucHJvdG9Qcm9wZXJ0eQogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgaGFzaFNldHRsZWQKICAgIEBwdWJsaWMKICAgIEBmb3IgcnN2cAogICAgQHBhcmFtIHtPYmplY3R9IG9iamVjdAogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIHRoYXQgZGVzY3JpYmVzIHRoZSBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCB3aGVuIHdoZW4gYWxsIHByb3BlcnRpZXMgb2YgYHByb21pc2VzYAogICAgaGF2ZSBiZWVuIHNldHRsZWQuCiAgICBAc3RhdGljCiAgKi8KCiAgZnVuY3Rpb24gaGFzaFNldHRsZWQob2JqZWN0LCBsYWJlbCkgewogICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShvYmplY3QsIGxhYmVsKS50aGVuKGZ1bmN0aW9uIChvYmplY3QpIHsKICAgICAgaWYgKG9iamVjdCA9PT0gbnVsbCB8fCB0eXBlb2Ygb2JqZWN0ICE9PSAnb2JqZWN0JykgewogICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoImhhc2hTZXR0bGVkIG11c3QgYmUgY2FsbGVkIHdpdGggYW4gb2JqZWN0Iik7CiAgICAgIH0KCiAgICAgIHJldHVybiBuZXcgSGFzaFNldHRsZWQoUHJvbWlzZSwgb2JqZWN0LCBmYWxzZSwgbGFiZWwpLnByb21pc2U7CiAgICB9KTsKICB9CiAgLyoqCiAgICBgcmV0aHJvd2Agd2lsbCByZXRocm93IGFuIGVycm9yIG9uIHRoZSBuZXh0IHR1cm4gb2YgdGhlIEphdmFTY3JpcHQgZXZlbnQKICAgIGxvb3AgaW4gb3JkZXIgdG8gYWlkIGRlYnVnZ2luZy4KICAKICAgIFByb21pc2VzIEErIHNwZWNpZmllcyB0aGF0IGFueSBleGNlcHRpb25zIHRoYXQgb2NjdXIgd2l0aCBhIHByb21pc2UgbXVzdCBiZQogICAgY2F1Z2h0IGJ5IHRoZSBwcm9taXNlcyBpbXBsZW1lbnRhdGlvbiBhbmQgYnViYmxlZCB0byB0aGUgbGFzdCBoYW5kbGVyLiBGb3IKICAgIHRoaXMgcmVhc29uLCBpdCBpcyByZWNvbW1lbmRlZCB0aGF0IHlvdSBhbHdheXMgc3BlY2lmeSBhIHNlY29uZCByZWplY3Rpb24KICAgIGhhbmRsZXIgZnVuY3Rpb24gdG8gYHRoZW5gLiBIb3dldmVyLCBgcmV0aHJvd2Agd2lsbCB0aHJvdyB0aGUgZXhjZXB0aW9uCiAgICBvdXRzaWRlIG9mIHRoZSBwcm9taXNlLCBzbyBpdCBidWJibGVzIHVwIHRvIHlvdXIgY29uc29sZSBpZiBpbiB0aGUgYnJvd3NlciwKICAgIG9yIGRvbWFpbi9jYXVzZSB1bmNhdWdodCBleGNlcHRpb24gaW4gTm9kZS4gYHJldGhyb3dgIHdpbGwgYWxzbyB0aHJvdyB0aGUKICAgIGVycm9yIGFnYWluIHNvIHRoZSBlcnJvciBjYW4gYmUgaGFuZGxlZCBieSB0aGUgcHJvbWlzZSBwZXIgdGhlIHNwZWMuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyByZXRocm93IH0gZnJvbSAncnN2cCc7CiAgCiAgICBmdW5jdGlvbiB0aHJvd3MoKXsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdXaG9vcHMhJyk7CiAgICB9CiAgCiAgICBsZXQgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7CiAgICAgIHRocm93cygpOwogICAgfSk7CiAgCiAgICBwcm9taXNlLmNhdGNoKHJldGhyb3cpLnRoZW4oZnVuY3Rpb24oKXsKICAgICAgLy8gQ29kZSBoZXJlIGRvZXNuJ3QgcnVuIGJlY2F1c2UgdGhlIHByb21pc2UgYmVjYW1lIHJlamVjdGVkIGR1ZSB0byBhbgogICAgICAvLyBlcnJvciEKICAgIH0sIGZ1bmN0aW9uIChlcnIpewogICAgICAvLyBoYW5kbGUgdGhlIGVycm9yIGhlcmUKICAgIH0pOwogICAgYGBgCiAgCiAgICBUaGUgJ1dob29wcycgZXJyb3Igd2lsbCBiZSB0aHJvd24gb24gdGhlIG5leHQgdHVybiBvZiB0aGUgZXZlbnQgbG9vcAogICAgYW5kIHlvdSBjYW4gd2F0Y2ggZm9yIGl0IGluIHlvdXIgY29uc29sZS4gWW91IGNhbiBhbHNvIGhhbmRsZSBpdCB1c2luZyBhCiAgICByZWplY3Rpb24gaGFuZGxlciBnaXZlbiB0byBgLnRoZW5gIG9yIGAuY2F0Y2hgIG9uIHRoZSByZXR1cm5lZCBwcm9taXNlLgogIAogICAgQG1ldGhvZCByZXRocm93CiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIHJzdnAKICAgIEBwYXJhbSB7RXJyb3J9IHJlYXNvbiByZWFzb24gdGhlIHByb21pc2UgYmVjYW1lIHJlamVjdGVkLgogICAgQHRocm93cyBFcnJvcgogICAgQHN0YXRpYwogICovCgoKICBmdW5jdGlvbiByZXRocm93KHJlYXNvbikgewogICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7CiAgICAgIHRocm93IHJlYXNvbjsKICAgIH0pOwogICAgdGhyb3cgcmVhc29uOwogIH0KICAvKioKICAgIGBkZWZlcmAgcmV0dXJucyBhbiBvYmplY3Qgc2ltaWxhciB0byBqUXVlcnkncyBgJC5EZWZlcnJlZGAuCiAgICBgZGVmZXJgIHNob3VsZCBiZSB1c2VkIHdoZW4gcG9ydGluZyBvdmVyIGNvZGUgcmVsaWFudCBvbiBgJC5EZWZlcnJlZGAncwogICAgaW50ZXJmYWNlLiBOZXcgY29kZSBzaG91bGQgdXNlIHRoZSBgUHJvbWlzZWAgY29uc3RydWN0b3IgaW5zdGVhZC4KICAKICAgIFRoZSBvYmplY3QgcmV0dXJuZWQgZnJvbSBgZGVmZXJgIGlzIGEgcGxhaW4gb2JqZWN0IHdpdGggdGhyZWUgcHJvcGVydGllczoKICAKICAgICogcHJvbWlzZSAtIGFuIGBQcm9taXNlYC4KICAgICogcmVqZWN0IC0gYSBmdW5jdGlvbiB0aGF0IGNhdXNlcyB0aGUgYHByb21pc2VgIHByb3BlcnR5IG9uIHRoaXMgb2JqZWN0IHRvCiAgICAgIGJlY29tZSByZWplY3RlZAogICAgKiByZXNvbHZlIC0gYSBmdW5jdGlvbiB0aGF0IGNhdXNlcyB0aGUgYHByb21pc2VgIHByb3BlcnR5IG9uIHRoaXMgb2JqZWN0IHRvCiAgICAgIGJlY29tZSBmdWxmaWxsZWQuCiAgCiAgICBFeGFtcGxlOgogIAogICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgZGVmZXJyZWQgPSBkZWZlcigpOwogIAogICAgIGRlZmVycmVkLnJlc29sdmUoIlN1Y2Nlc3MhIik7CiAgCiAgICAgZGVmZXJyZWQucHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXsKICAgICAgIC8vIHZhbHVlIGhlcmUgaXMgIlN1Y2Nlc3MhIgogICAgIH0pOwogICAgIGBgYAogIAogICAgQG1ldGhvZCBkZWZlcgogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQGZvciByc3ZwCiAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7T2JqZWN0fQogICAqLwoKCiAgZnVuY3Rpb24gZGVmZXIobGFiZWwpIHsKICAgIHZhciBkZWZlcnJlZCA9IHsKICAgICAgcmVzb2x2ZTogdW5kZWZpbmVkLAogICAgICByZWplY3Q6IHVuZGVmaW5lZAogICAgfTsKICAgIGRlZmVycmVkLnByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7CiAgICAgIGRlZmVycmVkLnJlc29sdmUgPSByZXNvbHZlOwogICAgICBkZWZlcnJlZC5yZWplY3QgPSByZWplY3Q7CiAgICB9LCBsYWJlbCk7CiAgICByZXR1cm4gZGVmZXJyZWQ7CiAgfQoKICB2YXIgTWFwRW51bWVyYXRvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfRW51bWVyYXRvcjMpIHsKICAgICgwLCBfZW1iZXJCYWJlbC5pbmhlcml0c0xvb3NlKShNYXBFbnVtZXJhdG9yLCBfRW51bWVyYXRvcjMpOwoKICAgIGZ1bmN0aW9uIE1hcEVudW1lcmF0b3IoQ29uc3RydWN0b3IsIGVudHJpZXMsIG1hcEZuLCBsYWJlbCkgewogICAgICByZXR1cm4gX0VudW1lcmF0b3IzLmNhbGwodGhpcywgQ29uc3RydWN0b3IsIGVudHJpZXMsIHRydWUsIGxhYmVsLCBtYXBGbikgfHwgdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvNCA9IE1hcEVudW1lcmF0b3IucHJvdG90eXBlOwoKICAgIF9wcm90bzQuX2luaXQgPSBmdW5jdGlvbiBfaW5pdChDb25zdHJ1Y3RvciwgaW5wdXQsIGJvb2wsIGxhYmVsLCBtYXBGbikgewogICAgICB2YXIgbGVuID0gaW5wdXQubGVuZ3RoIHx8IDA7CiAgICAgIHRoaXMubGVuZ3RoID0gbGVuOwogICAgICB0aGlzLl9yZW1haW5pbmcgPSBsZW47CiAgICAgIHRoaXMuX3Jlc3VsdCA9IG5ldyBBcnJheShsZW4pOwogICAgICB0aGlzLl9tYXBGbiA9IG1hcEZuOwoKICAgICAgdGhpcy5fZW51bWVyYXRlKGlucHV0KTsKICAgIH07CgogICAgX3Byb3RvNC5fc2V0UmVzdWx0QXQgPSBmdW5jdGlvbiBfc2V0UmVzdWx0QXQoc3RhdGUsIGksIHZhbHVlLCBmaXJzdFBhc3MpIHsKICAgICAgaWYgKGZpcnN0UGFzcykgewogICAgICAgIHRyeSB7CiAgICAgICAgICB0aGlzLl9lYWNoRW50cnkodGhpcy5fbWFwRm4odmFsdWUsIGkpLCBpLCBmYWxzZSk7CiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgIHRoaXMuX3NldHRsZWRBdChSRUpFQ1RFRCwgaSwgZXJyb3IsIGZhbHNlKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fcmVtYWluaW5nLS07CiAgICAgICAgdGhpcy5fcmVzdWx0W2ldID0gdmFsdWU7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIE1hcEVudW1lcmF0b3I7CiAgfShFbnVtZXJhdG9yKTsKICAvKioKICAgYG1hcGAgaXMgc2ltaWxhciB0byBKYXZhU2NyaXB0J3MgbmF0aXZlIGBtYXBgIG1ldGhvZC4gYG1hcEZuYCBpcyBlYWdlcmx5IGNhbGxlZAogICAgbWVhbmluZyB0aGF0IGFzIHNvb24gYXMgYW55IHByb21pc2UgcmVzb2x2ZXMgaXRzIHZhbHVlIHdpbGwgYmUgcGFzc2VkIHRvIGBtYXBGbmAuCiAgICBgbWFwYCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHdpbGwgYmVjb21lIGZ1bGZpbGxlZCB3aXRoIHRoZSByZXN1bHQgb2YgcnVubmluZwogICAgYG1hcEZuYCBvbiB0aGUgdmFsdWVzIHRoZSBwcm9taXNlcyBiZWNvbWUgZnVsZmlsbGVkIHdpdGguCiAgCiAgICBGb3IgZXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IG1hcCwgcmVzb2x2ZSB9IGZyb20gJ3JzdnAnOwogIAogICAgbGV0IHByb21pc2UxID0gcmVzb2x2ZSgxKTsKICAgIGxldCBwcm9taXNlMiA9IHJlc29sdmUoMik7CiAgICBsZXQgcHJvbWlzZTMgPSByZXNvbHZlKDMpOwogICAgbGV0IHByb21pc2VzID0gWyBwcm9taXNlMSwgcHJvbWlzZTIsIHByb21pc2UzIF07CiAgCiAgICBsZXQgbWFwRm4gPSBmdW5jdGlvbihpdGVtKXsKICAgICAgcmV0dXJuIGl0ZW0gKyAxOwogICAgfTsKICAKICAgIG1hcChwcm9taXNlcywgbWFwRm4pLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXsKICAgICAgLy8gcmVzdWx0IGlzIFsgMiwgMywgNCBdCiAgICB9KTsKICAgIGBgYAogIAogICAgSWYgYW55IG9mIHRoZSBgcHJvbWlzZXNgIGdpdmVuIHRvIGBtYXBgIGFyZSByZWplY3RlZCwgdGhlIGZpcnN0IHByb21pc2UKICAgIHRoYXQgaXMgcmVqZWN0ZWQgd2lsbCBiZSBnaXZlbiBhcyBhbiBhcmd1bWVudCB0byB0aGUgcmV0dXJuZWQgcHJvbWlzZSdzCiAgICByZWplY3Rpb24gaGFuZGxlci4gRm9yIGV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBtYXAsIHJlamVjdCwgcmVzb2x2ZSB9IGZyb20gJ3JzdnAnOwogIAogICAgbGV0IHByb21pc2UxID0gcmVzb2x2ZSgxKTsKICAgIGxldCBwcm9taXNlMiA9IHJlamVjdChuZXcgRXJyb3IoJzInKSk7CiAgICBsZXQgcHJvbWlzZTMgPSByZWplY3QobmV3IEVycm9yKCczJykpOwogICAgbGV0IHByb21pc2VzID0gWyBwcm9taXNlMSwgcHJvbWlzZTIsIHByb21pc2UzIF07CiAgCiAgICBsZXQgbWFwRm4gPSBmdW5jdGlvbihpdGVtKXsKICAgICAgcmV0dXJuIGl0ZW0gKyAxOwogICAgfTsKICAKICAgIG1hcChwcm9taXNlcywgbWFwRm4pLnRoZW4oZnVuY3Rpb24oYXJyYXkpewogICAgICAvLyBDb2RlIGhlcmUgbmV2ZXIgcnVucyBiZWNhdXNlIHRoZXJlIGFyZSByZWplY3RlZCBwcm9taXNlcyEKICAgIH0sIGZ1bmN0aW9uKHJlYXNvbikgewogICAgICAvLyByZWFzb24ubWVzc2FnZSA9PT0gJzInCiAgICB9KTsKICAgIGBgYAogIAogICAgYG1hcGAgd2lsbCBhbHNvIHdhaXQgaWYgYSBwcm9taXNlIGlzIHJldHVybmVkIGZyb20gYG1hcEZuYC4gRm9yIGV4YW1wbGUsCiAgICBzYXkgeW91IHdhbnQgdG8gZ2V0IGFsbCBjb21tZW50cyBmcm9tIGEgc2V0IG9mIGJsb2cgcG9zdHMsIGJ1dCB5b3UgbmVlZAogICAgdGhlIGJsb2cgcG9zdHMgZmlyc3QgYmVjYXVzZSB0aGV5IGNvbnRhaW4gYSB1cmwgdG8gdGhvc2UgY29tbWVudHMuCiAgCiAgICBgYGBqYXZzY3JpcHQKICAgIGltcG9ydCB7IG1hcCB9IGZyb20gJ3JzdnAnOwogIAogICAgbGV0IG1hcEZuID0gZnVuY3Rpb24oYmxvZ1Bvc3QpewogICAgICAvLyBnZXRDb21tZW50cyBkb2VzIHNvbWUgYWpheCBhbmQgcmV0dXJucyBhbiBQcm9taXNlIHRoYXQgaXMgZnVsZmlsbGVkCiAgICAgIC8vIHdpdGggc29tZSBjb21tZW50cyBkYXRhCiAgICAgIHJldHVybiBnZXRDb21tZW50cyhibG9nUG9zdC5jb21tZW50c191cmwpOwogICAgfTsKICAKICAgIC8vIGdldEJsb2dQb3N0cyBkb2VzIHNvbWUgYWpheCBhbmQgcmV0dXJucyBhbiBQcm9taXNlIHRoYXQgaXMgZnVsZmlsbGVkCiAgICAvLyB3aXRoIHNvbWUgYmxvZyBwb3N0IGRhdGEKICAgIG1hcChnZXRCbG9nUG9zdHMoKSwgbWFwRm4pLnRoZW4oZnVuY3Rpb24oY29tbWVudHMpewogICAgICAvLyBjb21tZW50cyBpcyB0aGUgcmVzdWx0IG9mIGFza2luZyB0aGUgc2VydmVyIGZvciB0aGUgY29tbWVudHMKICAgICAgLy8gb2YgYWxsIGJsb2cgcG9zdHMgcmV0dXJuZWQgZnJvbSBnZXRCbG9nUG9zdHMoKQogICAgfSk7CiAgICBgYGAKICAKICAgIEBtZXRob2QgbWFwCiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIHJzdnAKICAgIEBwYXJhbSB7QXJyYXl9IHByb21pc2VzCiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBtYXBGbiBmdW5jdGlvbiB0byBiZSBjYWxsZWQgb24gZWFjaCBmdWxmaWxsZWQgcHJvbWlzZS4KICAgIEBwYXJhbSB7U3RyaW5nfSBbbGFiZWxdIG9wdGlvbmFsIHN0cmluZyBmb3IgbGFiZWxpbmcgdGhlIHByb21pc2UuCiAgICBVc2VmdWwgZm9yIHRvb2xpbmcuCiAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHRoYXQgaXMgZnVsZmlsbGVkIHdpdGggdGhlIHJlc3VsdCBvZiBjYWxsaW5nCiAgICBgbWFwRm5gIG9uIGVhY2ggZnVsZmlsbGVkIHByb21pc2Ugb3IgdmFsdWUgd2hlbiB0aGV5IGJlY29tZSBmdWxmaWxsZWQuCiAgICAgVGhlIHByb21pc2Ugd2lsbCBiZSByZWplY3RlZCBpZiBhbnkgb2YgdGhlIGdpdmVuIGBwcm9taXNlc2AgYmVjb21lIHJlamVjdGVkLgogICovCgoKICBmdW5jdGlvbiBtYXAocHJvbWlzZXMsIG1hcEZuLCBsYWJlbCkgewogICAgaWYgKHR5cGVvZiBtYXBGbiAhPT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IFR5cGVFcnJvcigibWFwIGV4cGVjdHMgYSBmdW5jdGlvbiBhcyBhIHNlY29uZCBhcmd1bWVudCIpLCBsYWJlbCk7CiAgICB9CgogICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwcm9taXNlcywgbGFiZWwpLnRoZW4oZnVuY3Rpb24gKHByb21pc2VzKSB7CiAgICAgIGlmICghQXJyYXkuaXNBcnJheShwcm9taXNlcykpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJtYXAgbXVzdCBiZSBjYWxsZWQgd2l0aCBhbiBhcnJheSIpOwogICAgICB9CgogICAgICByZXR1cm4gbmV3IE1hcEVudW1lcmF0b3IoUHJvbWlzZSwgcHJvbWlzZXMsIG1hcEZuLCBsYWJlbCkucHJvbWlzZTsKICAgIH0pOwogIH0KICAvKioKICAgIFRoaXMgaXMgYSBjb252ZW5pZW50IGFsaWFzIGZvciBgUHJvbWlzZS5yZXNvbHZlYC4KICAKICAgIEBtZXRob2QgcmVzb2x2ZQogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQGZvciByc3ZwCiAgICBAcGFyYW0geyp9IHZhbHVlIHZhbHVlIHRoYXQgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCBiZSByZXNvbHZlZCB3aXRoCiAgICBAcGFyYW0ge1N0cmluZ30gW2xhYmVsXSBvcHRpb25hbCBzdHJpbmcgZm9yIGlkZW50aWZ5aW5nIHRoZSByZXR1cm5lZCBwcm9taXNlLgogICAgVXNlZnVsIGZvciB0b29saW5nLgogICAgQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHRoYXQgd2lsbCBiZWNvbWUgZnVsZmlsbGVkIHdpdGggdGhlIGdpdmVuCiAgICBgdmFsdWVgCiAgKi8KCgogIGZ1bmN0aW9uIHJlc29sdmUkMih2YWx1ZSwgbGFiZWwpIHsKICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodmFsdWUsIGxhYmVsKTsKICB9CiAgLyoqCiAgICBUaGlzIGlzIGEgY29udmVuaWVudCBhbGlhcyBmb3IgYFByb21pc2UucmVqZWN0YC4KICAKICAgIEBtZXRob2QgcmVqZWN0CiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIHJzdnAKICAgIEBwYXJhbSB7Kn0gcmVhc29uIHZhbHVlIHRoYXQgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoLgogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGZvciBpZGVudGlmeWluZyB0aGUgcmV0dXJuZWQgcHJvbWlzZS4KICAgIFVzZWZ1bCBmb3IgdG9vbGluZy4KICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSByZWplY3RlZCB3aXRoIHRoZSBnaXZlbiBgcmVhc29uYC4KICAqLwoKCiAgZnVuY3Rpb24gcmVqZWN0JDIocmVhc29uLCBsYWJlbCkgewogICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHJlYXNvbiwgbGFiZWwpOwogIH0KCiAgdmFyIEVNUFRZX09CSkVDVCA9IHt9OwoKICB2YXIgRmlsdGVyRW51bWVyYXRvciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfTWFwRW51bWVyYXRvcikgewogICAgKDAsIF9lbWJlckJhYmVsLmluaGVyaXRzTG9vc2UpKEZpbHRlckVudW1lcmF0b3IsIF9NYXBFbnVtZXJhdG9yKTsKCiAgICBmdW5jdGlvbiBGaWx0ZXJFbnVtZXJhdG9yKCkgewogICAgICByZXR1cm4gX01hcEVudW1lcmF0b3IuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG81ID0gRmlsdGVyRW51bWVyYXRvci5wcm90b3R5cGU7CgogICAgX3Byb3RvNS5fY2hlY2tGdWxsZmlsbG1lbnQgPSBmdW5jdGlvbiBfY2hlY2tGdWxsZmlsbG1lbnQoKSB7CiAgICAgIGlmICh0aGlzLl9yZW1haW5pbmcgPT09IDAgJiYgdGhpcy5fcmVzdWx0ICE9PSBudWxsKSB7CiAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuX3Jlc3VsdC5maWx0ZXIoZnVuY3Rpb24gKHZhbCkgewogICAgICAgICAgcmV0dXJuIHZhbCAhPT0gRU1QVFlfT0JKRUNUOwogICAgICAgIH0pOwoKICAgICAgICBmdWxmaWxsKHRoaXMucHJvbWlzZSwgcmVzdWx0KTsKICAgICAgICB0aGlzLl9yZXN1bHQgPSBudWxsOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90bzUuX3NldFJlc3VsdEF0ID0gZnVuY3Rpb24gX3NldFJlc3VsdEF0KHN0YXRlLCBpLCB2YWx1ZSwgZmlyc3RQYXNzKSB7CiAgICAgIGlmIChmaXJzdFBhc3MpIHsKICAgICAgICB0aGlzLl9yZXN1bHRbaV0gPSB2YWx1ZTsKICAgICAgICB2YXIgdmFsLAogICAgICAgICAgICBzdWNjZWVkZWQgPSB0cnVlOwoKICAgICAgICB0cnkgewogICAgICAgICAgdmFsID0gdGhpcy5fbWFwRm4odmFsdWUsIGkpOwogICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICBzdWNjZWVkZWQgPSBmYWxzZTsKCiAgICAgICAgICB0aGlzLl9zZXR0bGVkQXQoUkVKRUNURUQsIGksIGVycm9yLCBmYWxzZSk7CiAgICAgICAgfQoKICAgICAgICBpZiAoc3VjY2VlZGVkKSB7CiAgICAgICAgICB0aGlzLl9lYWNoRW50cnkodmFsLCBpLCBmYWxzZSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuX3JlbWFpbmluZy0tOwoKICAgICAgICBpZiAoIXZhbHVlKSB7CiAgICAgICAgICB0aGlzLl9yZXN1bHRbaV0gPSBFTVBUWV9PQkpFQ1Q7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBGaWx0ZXJFbnVtZXJhdG9yOwogIH0oTWFwRW51bWVyYXRvcik7CiAgLyoqCiAgIGBmaWx0ZXJgIGlzIHNpbWlsYXIgdG8gSmF2YVNjcmlwdCdzIG5hdGl2ZSBgZmlsdGVyYCBtZXRob2QuCiAgIGBmaWx0ZXJGbmAgaXMgZWFnZXJseSBjYWxsZWQgbWVhbmluZyB0aGF0IGFzIHNvb24gYXMgYW55IHByb21pc2UKICAgIHJlc29sdmVzIGl0cyB2YWx1ZSB3aWxsIGJlIHBhc3NlZCB0byBgZmlsdGVyRm5gLiBgZmlsdGVyYCByZXR1cm5zCiAgICBhIHByb21pc2UgdGhhdCB3aWxsIGJlY29tZSBmdWxmaWxsZWQgd2l0aCB0aGUgcmVzdWx0IG9mIHJ1bm5pbmcKICAgIGBmaWx0ZXJGbmAgb24gdGhlIHZhbHVlcyB0aGUgcHJvbWlzZXMgYmVjb21lIGZ1bGZpbGxlZCB3aXRoLgogIAogICAgRm9yIGV4YW1wbGU6CiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICBpbXBvcnQgeyBmaWx0ZXIsIHJlc29sdmUgfSBmcm9tICdyc3ZwJzsKICAKICAgIGxldCBwcm9taXNlMSA9IHJlc29sdmUoMSk7CiAgICBsZXQgcHJvbWlzZTIgPSByZXNvbHZlKDIpOwogICAgbGV0IHByb21pc2UzID0gcmVzb2x2ZSgzKTsKICAKICAgIGxldCBwcm9taXNlcyA9IFtwcm9taXNlMSwgcHJvbWlzZTIsIHByb21pc2UzXTsKICAKICAgIGxldCBmaWx0ZXJGbiA9IGZ1bmN0aW9uKGl0ZW0pewogICAgICByZXR1cm4gaXRlbSA+IDE7CiAgICB9OwogIAogICAgZmlsdGVyKHByb21pc2VzLCBmaWx0ZXJGbikudGhlbihmdW5jdGlvbihyZXN1bHQpewogICAgICAvLyByZXN1bHQgaXMgWyAyLCAzIF0KICAgIH0pOwogICAgYGBgCiAgCiAgICBJZiBhbnkgb2YgdGhlIGBwcm9taXNlc2AgZ2l2ZW4gdG8gYGZpbHRlcmAgYXJlIHJlamVjdGVkLCB0aGUgZmlyc3QgcHJvbWlzZQogICAgdGhhdCBpcyByZWplY3RlZCB3aWxsIGJlIGdpdmVuIGFzIGFuIGFyZ3VtZW50IHRvIHRoZSByZXR1cm5lZCBwcm9taXNlJ3MKICAgIHJlamVjdGlvbiBoYW5kbGVyLiBGb3IgZXhhbXBsZToKICAKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCB7IGZpbHRlciwgcmVqZWN0LCByZXNvbHZlIH0gZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgcHJvbWlzZTEgPSByZXNvbHZlKDEpOwogICAgbGV0IHByb21pc2UyID0gcmVqZWN0KG5ldyBFcnJvcignMicpKTsKICAgIGxldCBwcm9taXNlMyA9IHJlamVjdChuZXcgRXJyb3IoJzMnKSk7CiAgICBsZXQgcHJvbWlzZXMgPSBbIHByb21pc2UxLCBwcm9taXNlMiwgcHJvbWlzZTMgXTsKICAKICAgIGxldCBmaWx0ZXJGbiA9IGZ1bmN0aW9uKGl0ZW0pewogICAgICByZXR1cm4gaXRlbSA+IDE7CiAgICB9OwogIAogICAgZmlsdGVyKHByb21pc2VzLCBmaWx0ZXJGbikudGhlbihmdW5jdGlvbihhcnJheSl7CiAgICAgIC8vIENvZGUgaGVyZSBuZXZlciBydW5zIGJlY2F1c2UgdGhlcmUgYXJlIHJlamVjdGVkIHByb21pc2VzIQogICAgfSwgZnVuY3Rpb24ocmVhc29uKSB7CiAgICAgIC8vIHJlYXNvbi5tZXNzYWdlID09PSAnMicKICAgIH0pOwogICAgYGBgCiAgCiAgICBgZmlsdGVyYCB3aWxsIGFsc28gd2FpdCBmb3IgYW55IHByb21pc2VzIHJldHVybmVkIGZyb20gYGZpbHRlckZuYC4KICAgIEZvciBpbnN0YW5jZSwgeW91IG1heSB3YW50IHRvIGZldGNoIGEgbGlzdCBvZiB1c2VycyB0aGVuIHJldHVybiBhIHN1YnNldAogICAgb2YgdGhvc2UgdXNlcnMgYmFzZWQgb24gc29tZSBhc3luY2hyb25vdXMgb3BlcmF0aW9uOgogIAogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IHsgZmlsdGVyLCByZXNvbHZlIH0gZnJvbSAncnN2cCc7CiAgCiAgICBsZXQgYWxpY2UgPSB7IG5hbWU6ICdhbGljZScgfTsKICAgIGxldCBib2IgICA9IHsgbmFtZTogJ2JvYicgfTsKICAgIGxldCB1c2VycyA9IFsgYWxpY2UsIGJvYiBdOwogIAogICAgbGV0IHByb21pc2VzID0gdXNlcnMubWFwKGZ1bmN0aW9uKHVzZXIpewogICAgICByZXR1cm4gcmVzb2x2ZSh1c2VyKTsKICAgIH0pOwogIAogICAgbGV0IGZpbHRlckZuID0gZnVuY3Rpb24odXNlcil7CiAgICAgIC8vIEhlcmUsIEFsaWNlIGhhcyBwZXJtaXNzaW9ucyB0byBjcmVhdGUgYSBibG9nIHBvc3QsIGJ1dCBCb2IgZG9lcyBub3QuCiAgICAgIHJldHVybiBnZXRQcml2aWxlZ2VzRm9yVXNlcih1c2VyKS50aGVuKGZ1bmN0aW9uKHByaXZzKXsKICAgICAgICByZXR1cm4gcHJpdnMuY2FuX2NyZWF0ZV9ibG9nX3Bvc3QgPT09IHRydWU7CiAgICAgIH0pOwogICAgfTsKICAgIGZpbHRlcihwcm9taXNlcywgZmlsdGVyRm4pLnRoZW4oZnVuY3Rpb24odXNlcnMpewogICAgICAvLyB0cnVlLCBiZWNhdXNlIHRoZSBzZXJ2ZXIgdG9sZCB1cyBvbmx5IEFsaWNlIGNhbiBjcmVhdGUgYSBibG9nIHBvc3QuCiAgICAgIHVzZXJzLmxlbmd0aCA9PT0gMTsKICAgICAgLy8gZmFsc2UsIGJlY2F1c2UgQWxpY2UgaXMgdGhlIG9ubHkgdXNlciBwcmVzZW50IGluIGB1c2Vyc2AKICAgICAgdXNlcnNbMF0gPT09IGJvYjsKICAgIH0pOwogICAgYGBgCiAgCiAgICBAbWV0aG9kIGZpbHRlcgogICAgQHB1YmxpYwogICAgQHN0YXRpYwogICAgQGZvciByc3ZwCiAgICBAcGFyYW0ge0FycmF5fSBwcm9taXNlcwogICAgQHBhcmFtIHtGdW5jdGlvbn0gZmlsdGVyRm4gLSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgb24gZWFjaCByZXNvbHZlZCB2YWx1ZSB0bwogICAgZmlsdGVyIHRoZSBmaW5hbCByZXN1bHRzLgogICAgQHBhcmFtIHtTdHJpbmd9IFtsYWJlbF0gb3B0aW9uYWwgc3RyaW5nIGRlc2NyaWJpbmcgdGhlIHByb21pc2UuIFVzZWZ1bCBmb3IKICAgIHRvb2xpbmcuCiAgICBAcmV0dXJuIHtQcm9taXNlfQogICovCgoKICBmdW5jdGlvbiBmaWx0ZXIocHJvbWlzZXMsIGZpbHRlckZuLCBsYWJlbCkgewogICAgaWYgKHR5cGVvZiBmaWx0ZXJGbiAhPT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IFR5cGVFcnJvcigiZmlsdGVyIGV4cGVjdHMgZnVuY3Rpb24gYXMgYSBzZWNvbmQgYXJndW1lbnQiKSwgbGFiZWwpOwogICAgfQoKICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocHJvbWlzZXMsIGxhYmVsKS50aGVuKGZ1bmN0aW9uIChwcm9taXNlcykgewogICAgICBpZiAoIUFycmF5LmlzQXJyYXkocHJvbWlzZXMpKSB7CiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiZmlsdGVyIG11c3QgYmUgY2FsbGVkIHdpdGggYW4gYXJyYXkiKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5ldyBGaWx0ZXJFbnVtZXJhdG9yKFByb21pc2UsIHByb21pc2VzLCBmaWx0ZXJGbiwgbGFiZWwpLnByb21pc2U7CiAgICB9KTsKICB9CgogIHZhciBsZW4gPSAwOwogIHZhciB2ZXJ0eE5leHQ7CgogIGZ1bmN0aW9uIGFzYXAoY2FsbGJhY2ssIGFyZykgewogICAgcXVldWUkMVtsZW5dID0gY2FsbGJhY2s7CiAgICBxdWV1ZSQxW2xlbiArIDFdID0gYXJnOwogICAgbGVuICs9IDI7CgogICAgaWYgKGxlbiA9PT0gMikgewogICAgICAvLyBJZiBsZW4gaXMgMSwgdGhhdCBtZWFucyB0aGF0IHdlIG5lZWQgdG8gc2NoZWR1bGUgYW4gYXN5bmMgZmx1c2guCiAgICAgIC8vIElmIGFkZGl0aW9uYWwgY2FsbGJhY2tzIGFyZSBxdWV1ZWQgYmVmb3JlIHRoZSBxdWV1ZSBpcyBmbHVzaGVkLCB0aGV5CiAgICAgIC8vIHdpbGwgYmUgcHJvY2Vzc2VkIGJ5IHRoaXMgZmx1c2ggdGhhdCB3ZSBhcmUgc2NoZWR1bGluZy4KICAgICAgc2NoZWR1bGVGbHVzaCQxKCk7CiAgICB9CiAgfQoKICB2YXIgYnJvd3NlcldpbmRvdyA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93IDogdW5kZWZpbmVkOwogIHZhciBicm93c2VyR2xvYmFsID0gYnJvd3NlcldpbmRvdyB8fCB7fTsKICB2YXIgQnJvd3Nlck11dGF0aW9uT2JzZXJ2ZXIgPSBicm93c2VyR2xvYmFsLk11dGF0aW9uT2JzZXJ2ZXIgfHwgYnJvd3Nlckdsb2JhbC5XZWJLaXRNdXRhdGlvbk9ic2VydmVyOwogIHZhciBpc05vZGUgPSB0eXBlb2Ygc2VsZiA9PT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmIHt9LnRvU3RyaW5nLmNhbGwocHJvY2VzcykgPT09ICdbb2JqZWN0IHByb2Nlc3NdJzsgLy8gdGVzdCBmb3Igd2ViIHdvcmtlciBidXQgbm90IGluIElFMTAKCiAgdmFyIGlzV29ya2VyID0gdHlwZW9mIFVpbnQ4Q2xhbXBlZEFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgaW1wb3J0U2NyaXB0cyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIE1lc3NhZ2VDaGFubmVsICE9PSAndW5kZWZpbmVkJzsgLy8gbm9kZQoKICBmdW5jdGlvbiB1c2VOZXh0VGljaygpIHsKICAgIHZhciBuZXh0VGljayA9IHByb2Nlc3MubmV4dFRpY2s7IC8vIG5vZGUgdmVyc2lvbiAwLjEwLnggZGlzcGxheXMgYSBkZXByZWNhdGlvbiB3YXJuaW5nIHdoZW4gbmV4dFRpY2sgaXMgdXNlZCByZWN1cnNpdmVseQogICAgLy8gc2V0SW1tZWRpYXRlIHNob3VsZCBiZSB1c2VkIGluc3RlYWQgaW5zdGVhZAoKICAgIHZhciB2ZXJzaW9uID0gcHJvY2Vzcy52ZXJzaW9ucy5ub2RlLm1hdGNoKC9eKD86KFxkKylcLik/KD86KFxkKylcLik/KFwqfFxkKykkLyk7CgogICAgaWYgKEFycmF5LmlzQXJyYXkodmVyc2lvbikgJiYgdmVyc2lvblsxXSA9PT0gJzAnICYmIHZlcnNpb25bMl0gPT09ICcxMCcpIHsKICAgICAgbmV4dFRpY2sgPSBzZXRJbW1lZGlhdGU7CiAgICB9CgogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIG5leHRUaWNrKGZsdXNoKTsKICAgIH07CiAgfSAvLyB2ZXJ0eAoKCiAgZnVuY3Rpb24gdXNlVmVydHhUaW1lcigpIHsKICAgIGlmICh0eXBlb2YgdmVydHhOZXh0ICE9PSAndW5kZWZpbmVkJykgewogICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgIHZlcnR4TmV4dChmbHVzaCk7CiAgICAgIH07CiAgICB9CgogICAgcmV0dXJuIHVzZVNldFRpbWVvdXQoKTsKICB9CgogIGZ1bmN0aW9uIHVzZU11dGF0aW9uT2JzZXJ2ZXIoKSB7CiAgICB2YXIgaXRlcmF0aW9ucyA9IDA7CiAgICB2YXIgb2JzZXJ2ZXIgPSBuZXcgQnJvd3Nlck11dGF0aW9uT2JzZXJ2ZXIoZmx1c2gpOwogICAgdmFyIG5vZGUgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJyk7CiAgICBvYnNlcnZlci5vYnNlcnZlKG5vZGUsIHsKICAgICAgY2hhcmFjdGVyRGF0YTogdHJ1ZQogICAgfSk7CiAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gbm9kZS5kYXRhID0gaXRlcmF0aW9ucyA9ICsraXRlcmF0aW9ucyAlIDI7CiAgICB9OwogIH0gLy8gd2ViIHdvcmtlcgoKCiAgZnVuY3Rpb24gdXNlTWVzc2FnZUNoYW5uZWwoKSB7CiAgICB2YXIgY2hhbm5lbCA9IG5ldyBNZXNzYWdlQ2hhbm5lbCgpOwogICAgY2hhbm5lbC5wb3J0MS5vbm1lc3NhZ2UgPSBmbHVzaDsKICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBjaGFubmVsLnBvcnQyLnBvc3RNZXNzYWdlKDApOwogICAgfTsKICB9CgogIGZ1bmN0aW9uIHVzZVNldFRpbWVvdXQoKSB7CiAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gc2V0VGltZW91dChmbHVzaCwgMSk7CiAgICB9OwogIH0KCiAgdmFyIHF1ZXVlJDEgPSBuZXcgQXJyYXkoMTAwMCk7CgogIGZ1bmN0aW9uIGZsdXNoKCkgewogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkgKz0gMikgewogICAgICB2YXIgY2FsbGJhY2sgPSBxdWV1ZSQxW2ldOwogICAgICB2YXIgYXJnID0gcXVldWUkMVtpICsgMV07CiAgICAgIGNhbGxiYWNrKGFyZyk7CiAgICAgIHF1ZXVlJDFbaV0gPSB1bmRlZmluZWQ7CiAgICAgIHF1ZXVlJDFbaSArIDFdID0gdW5kZWZpbmVkOwogICAgfQoKICAgIGxlbiA9IDA7CiAgfQoKICBmdW5jdGlvbiBhdHRlbXB0VmVydGV4KCkgewogICAgdHJ5IHsKICAgICAgdmFyIHZlcnR4ID0gRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKS5yZXF1aXJlKCd2ZXJ0eCcpOwoKICAgICAgdmVydHhOZXh0ID0gdmVydHgucnVuT25Mb29wIHx8IHZlcnR4LnJ1bk9uQ29udGV4dDsKICAgICAgcmV0dXJuIHVzZVZlcnR4VGltZXIoKTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgcmV0dXJuIHVzZVNldFRpbWVvdXQoKTsKICAgIH0KICB9CgogIHZhciBzY2hlZHVsZUZsdXNoJDE7IC8vIERlY2lkZSB3aGF0IGFzeW5jIG1ldGhvZCB0byB1c2UgdG8gdHJpZ2dlcmluZyBwcm9jZXNzaW5nIG9mIHF1ZXVlZCBjYWxsYmFja3M6CgogIGlmIChpc05vZGUpIHsKICAgIHNjaGVkdWxlRmx1c2gkMSA9IHVzZU5leHRUaWNrKCk7CiAgfSBlbHNlIGlmIChCcm93c2VyTXV0YXRpb25PYnNlcnZlcikgewogICAgc2NoZWR1bGVGbHVzaCQxID0gdXNlTXV0YXRpb25PYnNlcnZlcigpOwogIH0gZWxzZSBpZiAoaXNXb3JrZXIpIHsKICAgIHNjaGVkdWxlRmx1c2gkMSA9IHVzZU1lc3NhZ2VDaGFubmVsKCk7CiAgfSBlbHNlIGlmIChicm93c2VyV2luZG93ID09PSB1bmRlZmluZWQgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicpIHsKICAgIHNjaGVkdWxlRmx1c2gkMSA9IGF0dGVtcHRWZXJ0ZXgoKTsKICB9IGVsc2UgewogICAgc2NoZWR1bGVGbHVzaCQxID0gdXNlU2V0VGltZW91dCgpOwogIH0gLy8gZGVmYXVsdHMKCgogIGNvbmZpZy5hc3luYyA9IGFzYXA7CgogIGNvbmZpZy5hZnRlciA9IGZ1bmN0aW9uIChjYikgewogICAgcmV0dXJuIHNldFRpbWVvdXQoY2IsIDApOwogIH07CgogIHZhciBjYXN0ID0gcmVzb2x2ZSQyOwogIF9leHBvcnRzLmNhc3QgPSBjYXN0OwoKICB2YXIgYXN5bmMgPSBmdW5jdGlvbiBhc3luYyhjYWxsYmFjaywgYXJnKSB7CiAgICByZXR1cm4gY29uZmlnLmFzeW5jKGNhbGxiYWNrLCBhcmcpOwogIH07CgogIF9leHBvcnRzLmFzeW5jID0gYXN5bmM7CgogIGZ1bmN0aW9uIG9uKCkgewogICAgY29uZmlnLm9uLmFwcGx5KGNvbmZpZywgYXJndW1lbnRzKTsKICB9CgogIGZ1bmN0aW9uIG9mZigpIHsKICAgIGNvbmZpZy5vZmYuYXBwbHkoY29uZmlnLCBhcmd1bWVudHMpOwogIH0gLy8gU2V0IHVwIGluc3RydW1lbnRhdGlvbiB0aHJvdWdoIGB3aW5kb3cuX19QUk9NSVNFX0lOVFJVTUVOVEFUSU9OX19gCgoKICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHdpbmRvd1snX19QUk9NSVNFX0lOU1RSVU1FTlRBVElPTl9fJ10gPT09ICdvYmplY3QnKSB7CiAgICB2YXIgY2FsbGJhY2tzID0gd2luZG93WydfX1BST01JU0VfSU5TVFJVTUVOVEFUSU9OX18nXTsKICAgIGNvbmZpZ3VyZSgnaW5zdHJ1bWVudCcsIHRydWUpOwoKICAgIGZvciAodmFyIGV2ZW50TmFtZSBpbiBjYWxsYmFja3MpIHsKICAgICAgaWYgKGNhbGxiYWNrcy5oYXNPd25Qcm9wZXJ0eShldmVudE5hbWUpKSB7CiAgICAgICAgb24oZXZlbnROYW1lLCBjYWxsYmFja3NbZXZlbnROYW1lXSk7CiAgICAgIH0KICAgIH0KICB9IC8vIHRoZSBkZWZhdWx0IGV4cG9ydCBoZXJlIGlzIGZvciBiYWNrd2FyZHMgY29tcGF0OgogIC8vICAgaHR0cHM6Ly9naXRodWIuY29tL3RpbGRlaW8vcnN2cC5qcy9pc3N1ZXMvNDM0CgoKICB2YXIgcnN2cCA9IHsKICAgIGFzYXA6IGFzYXAsCiAgICBjYXN0OiBjYXN0LAogICAgUHJvbWlzZTogUHJvbWlzZSwKICAgIEV2ZW50VGFyZ2V0OiBFdmVudFRhcmdldCwKICAgIGFsbDogYWxsJDEsCiAgICBhbGxTZXR0bGVkOiBhbGxTZXR0bGVkLAogICAgcmFjZTogcmFjZSQxLAogICAgaGFzaDogaGFzaCwKICAgIGhhc2hTZXR0bGVkOiBoYXNoU2V0dGxlZCwKICAgIHJldGhyb3c6IHJldGhyb3csCiAgICBkZWZlcjogZGVmZXIsCiAgICBkZW5vZGVpZnk6IGRlbm9kZWlmeSwKICAgIGNvbmZpZ3VyZTogY29uZmlndXJlLAogICAgb246IG9uLAogICAgb2ZmOiBvZmYsCiAgICByZXNvbHZlOiByZXNvbHZlJDIsCiAgICByZWplY3Q6IHJlamVjdCQyLAogICAgbWFwOiBtYXAsCiAgICBhc3luYzogYXN5bmMsCiAgICBmaWx0ZXI6IGZpbHRlcgogIH07CiAgdmFyIF9kZWZhdWx0ID0gcnN2cDsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwpyZXF1aXJlKCdlbWJlcicpOwp9KCkpOwovLyMgc291cmNlTWFwcGluZ1VSTD1lbWJlci5tYXAKCjtkZWZpbmUoJ0BlbWJlci1kYXRhL2FkYXB0ZXIvLXByaXZhdGUnLCBbJ2V4cG9ydHMnLCAncmVxdWlyZScsICdlbWJlci1pbmZsZWN0b3InXSwgZnVuY3Rpb24gKGV4cG9ydHMsIHJlcXVpcmUsIGVtYmVySW5mbGVjdG9yKSB7ICd1c2Ugc3RyaWN0JzsKCiAgdmFyIHJlcXVpcmVfX2RlZmF1bHQgPSAnZGVmYXVsdCcgaW4gcmVxdWlyZSA/IHJlcXVpcmVbJ2RlZmF1bHQnXSA6IHJlcXVpcmU7CgogIHZhciBuZXdsaW5lID0gL1xyP1xuLzsKICBmdW5jdGlvbiBwYXJzZVJlc3BvbnNlSGVhZGVycyhoZWFkZXJzU3RyaW5nKSB7CiAgICB2YXIgaGVhZGVycyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CgogICAgaWYgKCFoZWFkZXJzU3RyaW5nKSB7CiAgICAgIHJldHVybiBoZWFkZXJzOwogICAgfQoKICAgIHZhciBoZWFkZXJQYWlycyA9IGhlYWRlcnNTdHJpbmcuc3BsaXQobmV3bGluZSk7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoZWFkZXJQYWlycy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgaGVhZGVyID0gaGVhZGVyUGFpcnNbaV07CiAgICAgIHZhciBqID0gMDsKICAgICAgdmFyIGZvdW5kU2VwID0gZmFsc2U7CgogICAgICBmb3IgKDsgaiA8IGhlYWRlci5sZW5ndGg7IGorKykgewogICAgICAgIGlmIChoZWFkZXIuY2hhckNvZGVBdChqKSA9PT0gNTgKICAgICAgICAvKiAnOicgKi8KICAgICAgICApIHsKICAgICAgICAgICAgZm91bmRTZXAgPSB0cnVlOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKGZvdW5kU2VwID09PSBmYWxzZSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CgogICAgICB2YXIgZmllbGQgPSBoZWFkZXIuc3Vic3RyaW5nKDAsIGopLnRyaW0oKTsKICAgICAgdmFyIHZhbHVlID0gaGVhZGVyLnN1YnN0cmluZyhqICsgMSwgaGVhZGVyLmxlbmd0aCkudHJpbSgpOwoKICAgICAgaWYgKHZhbHVlKSB7CiAgICAgICAgdmFyIGxvd2VyQ2FzZWRGaWVsZCA9IGZpZWxkLnRvTG93ZXJDYXNlKCk7CiAgICAgICAgaGVhZGVyc1tsb3dlckNhc2VkRmllbGRdID0gdmFsdWU7CiAgICAgICAgaGVhZGVyc1tmaWVsZF0gPSB2YWx1ZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBoZWFkZXJzOwogIH0KCiAgLyoKICAgKiBGdW5jdGlvbiB0aGF0IGFsd2F5cyBhdHRlbXB0cyB0byBwYXJzZSB0aGUgcmVzcG9uc2UgYXMganNvbiwgYW5kIGlmIGFuIGVycm9yIGlzIHRocm93biwKICAgKiByZXR1cm5zIGB1bmRlZmluZWRgIGlmIHRoZSByZXNwb25zZSBpcyBzdWNjZXNzZnVsIGFuZCBoYXMgYSBzdGF0dXMgY29kZSBvZiAyMDQgKE5vIENvbnRlbnQpLAogICAqIG9yIDIwNSAoUmVzZXQgQ29udGVudCkgb3IgaWYgdGhlIHJlcXVlc3QgbWV0aG9kIHdhcyAnSEVBRCcsIGFuZCB0aGUgcGxhaW4gcGF5bG9hZCBvdGhlcndpc2UuCiAgICovCiAgZnVuY3Rpb24gZGV0ZXJtaW5lQm9keVByb21pc2UocmVzcG9uc2UsIHJlcXVlc3REYXRhKSB7CiAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpLnRoZW4oZnVuY3Rpb24gKHBheWxvYWQpIHsKICAgICAgdmFyIHJldCA9IHBheWxvYWQ7CgogICAgICB0cnkgewogICAgICAgIHJldCA9IEpTT04ucGFyc2UocGF5bG9hZCk7CiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgaWYgKCEoZXJyb3IgaW5zdGFuY2VvZiBTeW50YXhFcnJvcikpIHsKICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgIH0KCiAgICAgICAgdmFyIHN0YXR1cyA9IHJlc3BvbnNlLnN0YXR1czsKCiAgICAgICAgaWYgKHJlc3BvbnNlLm9rICYmIChzdGF0dXMgPT09IDIwNCB8fCBzdGF0dXMgPT09IDIwNSB8fCByZXF1ZXN0RGF0YS5tZXRob2QgPT09ICdIRUFEJykpIHsKICAgICAgICAgIHJldCA9IHVuZGVmaW5lZDsKICAgICAgICB9IGVsc2UgewoKCiAgICAgICAgICBjb25zb2xlLndhcm4oJ1RoaXMgcmVzcG9uc2Ugd2FzIHVuYWJsZSB0byBiZSBwYXJzZWQgYXMganNvbi4nLCBwYXlsb2FkKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiByZXQ7CiAgICB9KTsKICB9CgogIHZhciBSQlJBQ0tFVCA9IC9cW1xdJC87CgogIGZ1bmN0aW9uIGlzUGxhaW5PYmplY3Qob2JqKSB7CiAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IE9iamVjdF0nOwogIH0KICAvKgogICAqIEhlbHBlciBmdW5jdGlvbiB0aGF0IHR1cm5zIHRoZSBkYXRhL2JvZHkgb2YgYSByZXF1ZXN0IGludG8gYSBxdWVyeSBwYXJhbSBzdHJpbmcuCiAgICogVGhpcyBpcyBkaXJlY3RseSBjb3BpZWQgZnJvbSBqUXVlcnkucGFyYW0uCiAgICovCgoKICBmdW5jdGlvbiBzZXJpYWxpemVRdWVyeVBhcmFtcyhxdWVyeVBhcmFtc09iamVjdCkgewogICAgdmFyIHMgPSBbXTsKCiAgICBmdW5jdGlvbiBidWlsZFBhcmFtcyhwcmVmaXgsIG9iaikgewogICAgICB2YXIgaSwgbGVuLCBrZXk7CgogICAgICBpZiAocHJlZml4KSB7CiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkgewogICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gb2JqLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgICAgICAgIGlmIChSQlJBQ0tFVC50ZXN0KHByZWZpeCkpIHsKICAgICAgICAgICAgICBhZGQocywgcHJlZml4LCBvYmpbaV0pOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGJ1aWxkUGFyYW1zKHByZWZpeCArICdbJyArICh0eXBlb2Ygb2JqW2ldID09PSAnb2JqZWN0JyA/IGkgOiAnJykgKyAnXScsIG9ialtpXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGlzUGxhaW5PYmplY3Qob2JqKSkgewogICAgICAgICAgZm9yIChrZXkgaW4gb2JqKSB7CiAgICAgICAgICAgIGJ1aWxkUGFyYW1zKHByZWZpeCArICdbJyArIGtleSArICddJywgb2JqW2tleV0pOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBhZGQocywgcHJlZml4LCBvYmopOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHsKICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBvYmoubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHsKICAgICAgICAgIGFkZChzLCBvYmpbaV0ubmFtZSwgb2JqW2ldLnZhbHVlKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yIChrZXkgaW4gb2JqKSB7CiAgICAgICAgICBidWlsZFBhcmFtcyhrZXksIG9ialtrZXldKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBzOwogICAgfQoKICAgIHJldHVybiBidWlsZFBhcmFtcygnJywgcXVlcnlQYXJhbXNPYmplY3QpLmpvaW4oJyYnKS5yZXBsYWNlKC8lMjAvZywgJysnKTsKICB9CiAgLyoKICAgKiBQYXJ0IG9mIHRoZSBgc2VyaWFsaXplUXVlcnlQYXJhbXNgIGhlbHBlciBmdW5jdGlvbi4KICAgKi8KCiAgZnVuY3Rpb24gYWRkKHMsIGssIHYpIHsKICAgIC8vIFN0cmlwIG91dCBrZXlzIHdpdGggdW5kZWZpbmVkIHZhbHVlIGFuZCByZXBsYWNlIG51bGwgdmFsdWVzIHdpdGgKICAgIC8vIGVtcHR5IHN0cmluZ3MgKG1pbWljcyBqUXVlcnkuYWpheCkKICAgIGlmICh2ID09PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuOwogICAgfSBlbHNlIGlmICh2ID09PSBudWxsKSB7CiAgICAgIHYgPSAnJzsKICAgIH0KCiAgICB2ID0gdHlwZW9mIHYgPT09ICdmdW5jdGlvbicgPyB2KCkgOiB2OwogICAgc1tzLmxlbmd0aF0gPSBlbmNvZGVVUklDb21wb25lbnQoaykgKyAiPSIgKyBlbmNvZGVVUklDb21wb25lbnQodik7CiAgfQoKICB2YXIgX2ZldGNoID0gbnVsbDsKICBmdW5jdGlvbiBnZXRGZXRjaEZ1bmN0aW9uKCkgewogICAgaWYgKF9mZXRjaCAhPT0gbnVsbCkgewogICAgICByZXR1cm4gX2ZldGNoKCk7CiAgICB9CgogICAgaWYgKHJlcXVpcmUuaGFzKCdmZXRjaCcpKSB7CiAgICAgIC8vIHVzZSBgZmV0Y2hgIG1vZHVsZSBieSBkZWZhdWx0LCB0aGlzIGlzIGNvbW1vbmx5IHByb3ZpZGVkIGJ5IGVtYmVyLWZldGNoCiAgICAgIHZhciBmZXRjaEZuID0gcmVxdWlyZV9fZGVmYXVsdCgnZmV0Y2gnKS5kZWZhdWx0OwoKICAgICAgX2ZldGNoID0gZnVuY3Rpb24gX2ZldGNoKCkgewogICAgICAgIHJldHVybiBmZXRjaEZuOwogICAgICB9OwogICAgfSBlbHNlIGlmICh0eXBlb2YgZmV0Y2ggPT09ICdmdW5jdGlvbicpIHsKICAgICAgLy8gZmFsbGJhY2sgdG8gdXNpbmcgZ2xvYmFsIGZldGNoCiAgICAgIF9mZXRjaCA9IGZ1bmN0aW9uIF9mZXRjaCgpIHsKICAgICAgICByZXR1cm4gZmV0Y2g7CiAgICAgIH07CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBmaW5kIHRoZSBgZmV0Y2hgIG1vZHVsZSBvciB0aGUgYGZldGNoYCBnbG9iYWwuIERpZCB5b3UgbWVhbiB0byBpbnN0YWxsIHRoZSBgZW1iZXItZmV0Y2hgIGFkZG9uPycpOwogICAgfQoKICAgIHJldHVybiBfZmV0Y2goKTsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9hZGFwdGVyCiAgKi8KCiAgLyoqCiAgICAjIyBVc2luZyBCdWlsZFVSTE1peGluCgogICAgVG8gdXNlIFVSTCBidWlsZGluZywgaW5jbHVkZSB0aGUgbWl4aW4gd2hlbiBleHRlbmRpbmcgYW4gYWRhcHRlciwgYW5kIGNhbGwgYGJ1aWxkVVJMYCB3aGVyZSBuZWVkZWQuCiAgICBUaGUgZGVmYXVsdCBiZWhhdmlvdXIgaXMgZGVzaWduZWQgZm9yIFJFU1RBZGFwdGVyLgoKICAgICMjIyBFeGFtcGxlCgogICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IEFkYXB0ZXIsIHsgQnVpbGRVUkxNaXhpbiB9IGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwoKICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKEJ1aWxkVVJMTWl4aW4sIHsKICAgICAgZmluZFJlY29yZDogZnVuY3Rpb24oc3RvcmUsIHR5cGUsIGlkLCBzbmFwc2hvdCkgewogICAgICAgIHZhciB1cmwgPSB0aGlzLmJ1aWxkVVJMKHR5cGUubW9kZWxOYW1lLCBpZCwgc25hcHNob3QsICdmaW5kUmVjb3JkJyk7CiAgICAgICAgcmV0dXJuIHRoaXMuYWpheCh1cmwsICdHRVQnKTsKICAgICAgfQogICAgfSk7CiAgICBgYGAKCiAgICAjIyMgQXR0cmlidXRlcwoKICAgIFRoZSBgaG9zdGAgYW5kIGBuYW1lc3BhY2VgIGF0dHJpYnV0ZXMgd2lsbCBiZSB1c2VkIGlmIGRlZmluZWQsIGFuZCBhcmUgb3B0aW9uYWwuCgogICAgQGNsYXNzIEJ1aWxkVVJMTWl4aW4KICAqLwoKICB2YXIgYnVpbGRVcmxNaXhpbiA9IEVtYmVyLk1peGluLmNyZWF0ZSh7CiAgICAvKioKICAgICAgQnVpbGRzIGEgVVJMIGZvciBhIGdpdmVuIHR5cGUgYW5kIG9wdGlvbmFsIElELgogICAgICAgQnkgZGVmYXVsdCwgaXQgcGx1cmFsaXplcyB0aGUgdHlwZSdzIG5hbWUgKGZvciBleGFtcGxlLCAncG9zdCcKICAgICAgYmVjb21lcyAncG9zdHMnIGFuZCAncGVyc29uJyBiZWNvbWVzICdwZW9wbGUnKS4gVG8gb3ZlcnJpZGUgdGhlCiAgICAgIHBsdXJhbGl6YXRpb24gc2VlIFtwYXRoRm9yVHlwZV0oQnVpbGRVcmxNaXhpbi9tZXRob2RzL3BhdGhGb3JUeXBlP2FuY2hvcj1wYXRoRm9yVHlwZSkuCiAgICAgICBJZiBhbiBJRCBpcyBzcGVjaWZpZWQsIGl0IGFkZHMgdGhlIElEIHRvIHRoZSBwYXRoIGdlbmVyYXRlZAogICAgICBmb3IgdGhlIHR5cGUsIHNlcGFyYXRlZCBieSBhIGAvYC4KICAgICAgIFdoZW4gY2FsbGVkIGJ5IGBSRVNUQWRhcHRlci5maW5kTWFueSgpYCB0aGUgYGlkYCBhbmQgYHNuYXBzaG90YCBwYXJhbWV0ZXJzCiAgICAgIHdpbGwgYmUgYXJyYXlzIG9mIGlkcyBhbmQgc25hcHNob3RzLgogICAgICAgQG1ldGhvZCBidWlsZFVSTAogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7KFN0cmluZ3xBcnJheXxPYmplY3QpfSBpZCBzaW5nbGUgaWQgb3IgYXJyYXkgb2YgaWRzIG9yIHF1ZXJ5CiAgICAgIEBwYXJhbSB7KFNuYXBzaG90fFNuYXBzaG90UmVjb3JkQXJyYXkpfSBzbmFwc2hvdCBzaW5nbGUgc25hcHNob3Qgb3IgYXJyYXkgb2Ygc25hcHNob3RzCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcGFyYW0ge09iamVjdH0gcXVlcnkgb2JqZWN0IG9mIHF1ZXJ5IHBhcmFtZXRlcnMgdG8gc2VuZCBmb3IgcXVlcnkgcmVxdWVzdHMuCiAgICAgIEByZXR1cm4ge1N0cmluZ30gdXJsCiAgICAqLwogICAgYnVpbGRVUkw6IGZ1bmN0aW9uIGJ1aWxkVVJMKG1vZGVsTmFtZSwgaWQsIHNuYXBzaG90LCByZXF1ZXN0VHlwZSwgcXVlcnkpIHsKICAgICAgc3dpdGNoIChyZXF1ZXN0VHlwZSkgewogICAgICAgIGNhc2UgJ2ZpbmRSZWNvcmQnOgogICAgICAgICAgcmV0dXJuIHRoaXMudXJsRm9yRmluZFJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCk7CgogICAgICAgIGNhc2UgJ2ZpbmRBbGwnOgogICAgICAgICAgcmV0dXJuIHRoaXMudXJsRm9yRmluZEFsbChtb2RlbE5hbWUsIHNuYXBzaG90KTsKCiAgICAgICAgY2FzZSAncXVlcnknOgogICAgICAgICAgcmV0dXJuIHRoaXMudXJsRm9yUXVlcnkocXVlcnksIG1vZGVsTmFtZSk7CgogICAgICAgIGNhc2UgJ3F1ZXJ5UmVjb3JkJzoKICAgICAgICAgIHJldHVybiB0aGlzLnVybEZvclF1ZXJ5UmVjb3JkKHF1ZXJ5LCBtb2RlbE5hbWUpOwoKICAgICAgICBjYXNlICdmaW5kTWFueSc6CiAgICAgICAgICByZXR1cm4gdGhpcy51cmxGb3JGaW5kTWFueShpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCk7CgogICAgICAgIGNhc2UgJ2ZpbmRIYXNNYW55JzoKICAgICAgICAgIHJldHVybiB0aGlzLnVybEZvckZpbmRIYXNNYW55KGlkLCBtb2RlbE5hbWUsIHNuYXBzaG90KTsKCiAgICAgICAgY2FzZSAnZmluZEJlbG9uZ3NUbyc6CiAgICAgICAgICByZXR1cm4gdGhpcy51cmxGb3JGaW5kQmVsb25nc1RvKGlkLCBtb2RlbE5hbWUsIHNuYXBzaG90KTsKCiAgICAgICAgY2FzZSAnY3JlYXRlUmVjb3JkJzoKICAgICAgICAgIHJldHVybiB0aGlzLnVybEZvckNyZWF0ZVJlY29yZChtb2RlbE5hbWUsIHNuYXBzaG90KTsKCiAgICAgICAgY2FzZSAndXBkYXRlUmVjb3JkJzoKICAgICAgICAgIHJldHVybiB0aGlzLnVybEZvclVwZGF0ZVJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCk7CgogICAgICAgIGNhc2UgJ2RlbGV0ZVJlY29yZCc6CiAgICAgICAgICByZXR1cm4gdGhpcy51cmxGb3JEZWxldGVSZWNvcmQoaWQsIG1vZGVsTmFtZSwgc25hcHNob3QpOwoKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgcmV0dXJuIHRoaXMuX2J1aWxkVVJMKG1vZGVsTmFtZSwgaWQpOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIF9idWlsZFVSTAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBpZAogICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybAogICAgKi8KICAgIF9idWlsZFVSTDogZnVuY3Rpb24gX2J1aWxkVVJMKG1vZGVsTmFtZSwgaWQpIHsKICAgICAgdmFyIHBhdGg7CiAgICAgIHZhciB1cmwgPSBbXTsKICAgICAgdmFyIGhvc3QgPSBFbWJlci5nZXQodGhpcywgJ2hvc3QnKTsKICAgICAgdmFyIHByZWZpeCA9IHRoaXMudXJsUHJlZml4KCk7CgogICAgICBpZiAobW9kZWxOYW1lKSB7CiAgICAgICAgcGF0aCA9IHRoaXMucGF0aEZvclR5cGUobW9kZWxOYW1lKTsKCiAgICAgICAgaWYgKHBhdGgpIHsKICAgICAgICAgIHVybC5wdXNoKHBhdGgpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKGlkKSB7CiAgICAgICAgdXJsLnB1c2goZW5jb2RlVVJJQ29tcG9uZW50KGlkKSk7CiAgICAgIH0KCiAgICAgIGlmIChwcmVmaXgpIHsKICAgICAgICB1cmwudW5zaGlmdChwcmVmaXgpOwogICAgICB9CgogICAgICB1cmwgPSB1cmwuam9pbignLycpOwoKICAgICAgaWYgKCFob3N0ICYmIHVybCAmJiB1cmwuY2hhckF0KDApICE9PSAnLycpIHsKICAgICAgICB1cmwgPSAnLycgKyB1cmw7CiAgICAgIH0KCiAgICAgIHJldHVybiB1cmw7CiAgICB9LAoKICAgIC8qKgogICAgIEJ1aWxkcyBhIFVSTCBmb3IgYSBgc3RvcmUuZmluZFJlY29yZCh0eXBlLCBpZClgIGNhbGwuCiAgICAgIEV4YW1wbGU6CiAgICAgIGBgYGFwcC9hZGFwdGVycy91c2VyLmpzCiAgICAgaW1wb3J0IEpTT05BUElBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvanNvbi1hcGknOwogICAgICBleHBvcnQgZGVmYXVsdCBKU09OQVBJQWRhcHRlci5leHRlbmQoewogICAgICAgdXJsRm9yRmluZFJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICAgICBsZXQgYmFzZVVybCA9IHRoaXMuYnVpbGRVUkwobW9kZWxOYW1lLCBpZCwgc25hcHNob3QpOwogICAgICAgICByZXR1cm4gYCR7YmFzZVVybH0vdXNlcnMvJHtzbmFwc2hvdC5hZGFwdGVyT3B0aW9ucy51c2VyX2lkfS9wbGF5bGlzdHMvJHtpZH1gOwogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIHVybEZvckZpbmRSZWNvcmQKICAgICBAcGFyYW0ge1N0cmluZ30gaWQKICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybAogICAgICAqLwogICAgdXJsRm9yRmluZFJlY29yZDogZnVuY3Rpb24gdXJsRm9yRmluZFJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICB9LAoKICAgIC8qKgogICAgIEJ1aWxkcyBhIFVSTCBmb3IgYSBgc3RvcmUuZmluZEFsbCh0eXBlKWAgY2FsbC4KICAgICAgRXhhbXBsZToKICAgICAgYGBgYXBwL2FkYXB0ZXJzL2NvbW1lbnQuanMKICAgICBpbXBvcnQgSlNPTkFQSUFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9qc29uLWFwaSc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05BUElBZGFwdGVyLmV4dGVuZCh7CiAgICAgICB1cmxGb3JGaW5kQWxsKG1vZGVsTmFtZSwgc25hcHNob3QpIHsKICAgICAgICAgcmV0dXJuICdkYXRhL2NvbW1lbnRzLmpzb24nOwogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIHVybEZvckZpbmRBbGwKICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgQHBhcmFtIHtTbmFwc2hvdFJlY29yZEFycmF5fSBzbmFwc2hvdAogICAgIEByZXR1cm4ge1N0cmluZ30gdXJsCiAgICAgKi8KICAgIHVybEZvckZpbmRBbGw6IGZ1bmN0aW9uIHVybEZvckZpbmRBbGwobW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lKTsKICAgIH0sCgogICAgLyoqCiAgICAgQnVpbGRzIGEgVVJMIGZvciBhIGBzdG9yZS5xdWVyeSh0eXBlLCBxdWVyeSlgIGNhbGwuCiAgICAgIEV4YW1wbGU6CiAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgICBleHBvcnQgZGVmYXVsdCBSRVNUQWRhcHRlci5leHRlbmQoewogICAgICAgaG9zdDogJ2h0dHBzOi8vYXBpLmdpdGh1Yi5jb20nLAogICAgICAgdXJsRm9yUXVlcnkgKHF1ZXJ5LCBtb2RlbE5hbWUpIHsKICAgICAgICAgc3dpdGNoKG1vZGVsTmFtZSkgewogICAgICAgICAgIGNhc2UgJ3JlcG8nOgogICAgICAgICAgICAgcmV0dXJuIGBodHRwczovL2FwaS5naXRodWIuY29tL29yZ3MvJHtxdWVyeS5vcmdJZH0vcmVwb3NgOwogICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICByZXR1cm4gdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICAgfQogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIHVybEZvclF1ZXJ5CiAgICAgQHBhcmFtIHtPYmplY3R9IHF1ZXJ5CiAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgIEByZXR1cm4ge1N0cmluZ30gdXJsCiAgICAgKi8KICAgIHVybEZvclF1ZXJ5OiBmdW5jdGlvbiB1cmxGb3JRdWVyeShxdWVyeSwgbW9kZWxOYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLl9idWlsZFVSTChtb2RlbE5hbWUpOwogICAgfSwKCiAgICAvKioKICAgICBCdWlsZHMgYSBVUkwgZm9yIGEgYHN0b3JlLnF1ZXJ5UmVjb3JkKHR5cGUsIHF1ZXJ5KWAgY2FsbC4KICAgICAgRXhhbXBsZToKICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgaW1wb3J0IFJFU1RBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgICB1cmxGb3JRdWVyeVJlY29yZCh7IHNsdWcgfSwgbW9kZWxOYW1lKSB7CiAgICAgICAgIGxldCBiYXNlVXJsID0gdGhpcy5idWlsZFVSTCgpOwogICAgICAgICByZXR1cm4gYCR7YmFzZVVybH0vJHtlbmNvZGVVUklDb21wb25lbnQoc2x1Zyl9YDsKICAgICAgIH0KICAgICB9KTsKICAgICBgYGAKICAgICAgQG1ldGhvZCB1cmxGb3JRdWVyeVJlY29yZAogICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeQogICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybAogICAgICovCiAgICB1cmxGb3JRdWVyeVJlY29yZDogZnVuY3Rpb24gdXJsRm9yUXVlcnlSZWNvcmQocXVlcnksIG1vZGVsTmFtZSkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lKTsKICAgIH0sCgogICAgLyoqCiAgICAgQnVpbGRzIGEgVVJMIGZvciBjb2FsZXNjaW5nIG11bHRpcGxlIGBzdG9yZS5maW5kUmVjb3JkKHR5cGUsIGlkKWAKICAgICByZWNvcmRzIGludG8gMSByZXF1ZXN0IHdoZW4gdGhlIGFkYXB0ZXIncyBgY29hbGVzY2VGaW5kUmVxdWVzdHNgCiAgICAgcHJvcGVydHkgaXMgYHRydWVgLgogICAgICBFeGFtcGxlOgogICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICBpbXBvcnQgUkVTVEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9yZXN0JzsKICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgIHVybEZvckZpbmRNYW55KGlkcywgbW9kZWxOYW1lKSB7CiAgICAgICAgIGxldCBiYXNlVXJsID0gdGhpcy5idWlsZFVSTCgpOwogICAgICAgICByZXR1cm4gYCR7YmFzZVVybH0vY29hbGVzY2VgOwogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIHVybEZvckZpbmRNYW55CiAgICAgQHBhcmFtIHtBcnJheX0gaWRzCiAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgIEBwYXJhbSB7QXJyYXl9IHNuYXBzaG90cwogICAgIEByZXR1cm4ge1N0cmluZ30gdXJsCiAgICAgKi8KICAgIHVybEZvckZpbmRNYW55OiBmdW5jdGlvbiB1cmxGb3JGaW5kTWFueShpZHMsIG1vZGVsTmFtZSwgc25hcHNob3RzKSB7CiAgICAgIHJldHVybiB0aGlzLl9idWlsZFVSTChtb2RlbE5hbWUpOwogICAgfSwKCiAgICAvKioKICAgICBCdWlsZHMgYSBVUkwgZm9yIGZldGNoaW5nIGFuIGFzeW5jIGBoYXNNYW55YCByZWxhdGlvbnNoaXAgd2hlbiBhIFVSTAogICAgIGlzIG5vdCBwcm92aWRlZCBieSB0aGUgc2VydmVyLgogICAgICBFeGFtcGxlOgogICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICBpbXBvcnQgSlNPTkFQSUFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9qc29uLWFwaSc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05BUElBZGFwdGVyLmV4dGVuZCh7CiAgICAgICB1cmxGb3JGaW5kSGFzTWFueShpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICAgICBsZXQgYmFzZVVybCA9IHRoaXMuYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICAgICAgIHJldHVybiBgJHtiYXNlVXJsfS9yZWxhdGlvbnNoaXBzYDsKICAgICAgIH0KICAgICB9KTsKICAgICBgYGAKICAgICAgQG1ldGhvZCB1cmxGb3JGaW5kSGFzTWFueQogICAgIEBwYXJhbSB7U3RyaW5nfSBpZAogICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgIEByZXR1cm4ge1N0cmluZ30gdXJsCiAgICAgKi8KICAgIHVybEZvckZpbmRIYXNNYW55OiBmdW5jdGlvbiB1cmxGb3JGaW5kSGFzTWFueShpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICB9LAoKICAgIC8qKgogICAgIEJ1aWxkcyBhIFVSTCBmb3IgZmV0Y2hpbmcgYW4gYXN5bmMgYGJlbG9uZ3NUb2AgcmVsYXRpb25zaGlwIHdoZW4gYSB1cmwKICAgICBpcyBub3QgcHJvdmlkZWQgYnkgdGhlIHNlcnZlci4KICAgICAgRXhhbXBsZToKICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgaW1wb3J0IEpTT05BUElBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvanNvbi1hcGknOwogICAgICBleHBvcnQgZGVmYXVsdCBKU09OQVBJQWRhcHRlci5leHRlbmQoewogICAgICAgdXJsRm9yRmluZEJlbG9uZ3NUbyhpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICAgICBsZXQgYmFzZVVybCA9IHRoaXMuYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICAgICAgIHJldHVybiBgJHtiYXNlVXJsfS9yZWxhdGlvbnNoaXBzYDsKICAgICAgIH0KICAgICB9KTsKICAgICBgYGAKICAgICAgQG1ldGhvZCB1cmxGb3JGaW5kQmVsb25nc1RvCiAgICAgQHBhcmFtIHtTdHJpbmd9IGlkCiAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgQHJldHVybiB7U3RyaW5nfSB1cmwKICAgICAqLwogICAgdXJsRm9yRmluZEJlbG9uZ3NUbzogZnVuY3Rpb24gdXJsRm9yRmluZEJlbG9uZ3NUbyhpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICB9LAoKICAgIC8qKgogICAgIEJ1aWxkcyBhIFVSTCBmb3IgYSBgcmVjb3JkLnNhdmUoKWAgY2FsbCB3aGVuIHRoZSByZWNvcmQgd2FzIGNyZWF0ZWQKICAgICBsb2NhbGx5IHVzaW5nIGBzdG9yZS5jcmVhdGVSZWNvcmQoKWAuCiAgICAgIEV4YW1wbGU6CiAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgICBleHBvcnQgZGVmYXVsdCBSRVNUQWRhcHRlci5leHRlbmQoewogICAgICAgdXJsRm9yQ3JlYXRlUmVjb3JkKG1vZGVsTmFtZSwgc25hcHNob3QpIHsKICAgICAgICAgcmV0dXJuIHRoaXMuX3N1cGVyKC4uLmFyZ3VtZW50cykgKyAnL25ldyc7CiAgICAgICB9CiAgICAgfSk7CiAgICAgYGBgCiAgICAgIEBtZXRob2QgdXJsRm9yQ3JlYXRlUmVjb3JkCiAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgQHJldHVybiB7U3RyaW5nfSB1cmwKICAgICAqLwogICAgdXJsRm9yQ3JlYXRlUmVjb3JkOiBmdW5jdGlvbiB1cmxGb3JDcmVhdGVSZWNvcmQobW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lKTsKICAgIH0sCgogICAgLyoqCiAgICAgQnVpbGRzIGEgVVJMIGZvciBhIGByZWNvcmQuc2F2ZSgpYCBjYWxsIHdoZW4gdGhlIHJlY29yZCBoYXMgYmVlbiB1cGRhdGVkIGxvY2FsbHkuCiAgICAgIEV4YW1wbGU6CiAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgICBleHBvcnQgZGVmYXVsdCBSRVNUQWRhcHRlci5leHRlbmQoewogICAgICAgdXJsRm9yVXBkYXRlUmVjb3JkKGlkLCBtb2RlbE5hbWUsIHNuYXBzaG90KSB7CiAgICAgICAgIHJldHVybiBgLyR7aWR9L2ZlZWQ/YWNjZXNzX3Rva2VuPSR7c25hcHNob3QuYWRhcHRlck9wdGlvbnMudG9rZW59YDsKICAgICAgIH0KICAgICB9KTsKICAgICBgYGAKICAgICAgQG1ldGhvZCB1cmxGb3JVcGRhdGVSZWNvcmQKICAgICBAcGFyYW0ge1N0cmluZ30gaWQKICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybAogICAgICovCiAgICB1cmxGb3JVcGRhdGVSZWNvcmQ6IGZ1bmN0aW9uIHVybEZvclVwZGF0ZVJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGRVUkwobW9kZWxOYW1lLCBpZCk7CiAgICB9LAoKICAgIC8qKgogICAgIEJ1aWxkcyBhIFVSTCBmb3IgYSBgcmVjb3JkLnNhdmUoKWAgY2FsbCB3aGVuIHRoZSByZWNvcmQgaGFzIGJlZW4gZGVsZXRlZCBsb2NhbGx5LgogICAgICBFeGFtcGxlOgogICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICBpbXBvcnQgUkVTVEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9yZXN0JzsKICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgIHVybEZvckRlbGV0ZVJlY29yZChpZCwgbW9kZWxOYW1lLCBzbmFwc2hvdCkgewogICAgICAgICByZXR1cm4gdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKSArICcvZGVzdHJveSc7CiAgICAgICB9CiAgICAgfSk7CiAgICAgYGBgCiAgICAgIEBtZXRob2QgdXJsRm9yRGVsZXRlUmVjb3JkCiAgICAgQHBhcmFtIHtTdHJpbmd9IGlkCiAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgQHJldHVybiB7U3RyaW5nfSB1cmwKICAgICAqLwogICAgdXJsRm9yRGVsZXRlUmVjb3JkOiBmdW5jdGlvbiB1cmxGb3JEZWxldGVSZWNvcmQoaWQsIG1vZGVsTmFtZSwgc25hcHNob3QpIHsKICAgICAgcmV0dXJuIHRoaXMuX2J1aWxkVVJMKG1vZGVsTmFtZSwgaWQpOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCB1cmxQcmVmaXgKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IHBhdGgKICAgICAgQHBhcmFtIHtTdHJpbmd9IHBhcmVudFVSTAogICAgICBAcmV0dXJuIHtTdHJpbmd9IHVybFByZWZpeAogICAgKi8KICAgIHVybFByZWZpeDogZnVuY3Rpb24gdXJsUHJlZml4KHBhdGgsIHBhcmVudFVSTCkgewogICAgICB2YXIgaG9zdCA9IEVtYmVyLmdldCh0aGlzLCAnaG9zdCcpOwogICAgICB2YXIgbmFtZXNwYWNlID0gRW1iZXIuZ2V0KHRoaXMsICduYW1lc3BhY2UnKTsKCiAgICAgIGlmICghaG9zdCB8fCBob3N0ID09PSAnLycpIHsKICAgICAgICBob3N0ID0gJyc7CiAgICAgIH0KCiAgICAgIGlmIChwYXRoKSB7CiAgICAgICAgLy8gUHJvdG9jb2wgcmVsYXRpdmUgdXJsCiAgICAgICAgaWYgKC9eXC9cLy8udGVzdChwYXRoKSB8fCAvaHR0cChzKT86XC9cLy8udGVzdChwYXRoKSkgewogICAgICAgICAgLy8gRG8gbm90aGluZywgdGhlIGZ1bGwgaG9zdCBpcyBhbHJlYWR5IGluY2x1ZGVkLgogICAgICAgICAgcmV0dXJuIHBhdGg7IC8vIEFic29sdXRlIHBhdGgKICAgICAgICB9IGVsc2UgaWYgKHBhdGguY2hhckF0KDApID09PSAnLycpIHsKICAgICAgICAgIHJldHVybiAiIiArIGhvc3QgKyBwYXRoOyAvLyBSZWxhdGl2ZSBwYXRoCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBwYXJlbnRVUkwgKyAiLyIgKyBwYXRoOwogICAgICAgIH0KICAgICAgfSAvLyBObyBwYXRoIHByb3ZpZGVkCgoKICAgICAgdmFyIHVybCA9IFtdOwoKICAgICAgaWYgKGhvc3QpIHsKICAgICAgICB1cmwucHVzaChob3N0KTsKICAgICAgfQoKICAgICAgaWYgKG5hbWVzcGFjZSkgewogICAgICAgIHVybC5wdXNoKG5hbWVzcGFjZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB1cmwuam9pbignLycpOwogICAgfSwKCiAgICAvKioKICAgICAgRGV0ZXJtaW5lcyB0aGUgcGF0aG5hbWUgZm9yIGEgZ2l2ZW4gdHlwZS4KICAgICAgIEJ5IGRlZmF1bHQsIGl0IHBsdXJhbGl6ZXMgdGhlIHR5cGUncyBuYW1lIChmb3IgZXhhbXBsZSwKICAgICAgJ3Bvc3QnIGJlY29tZXMgJ3Bvc3RzJyBhbmQgJ3BlcnNvbicgYmVjb21lcyAncGVvcGxlJykuCiAgICAgICAjIyMgUGF0aG5hbWUgY3VzdG9taXphdGlvbgogICAgICAgRm9yIGV4YW1wbGUsIGlmIHlvdSBoYXZlIGFuIG9iamVjdCBgTGluZUl0ZW1gIHdpdGggYW4KICAgICAgZW5kcG9pbnQgb2YgYC9saW5lX2l0ZW1zL2AuCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJFU1RBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCc7CiAgICAgIGltcG9ydCB7IGRlY2FtZWxpemUgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAgICAgaW1wb3J0IHsgcGx1cmFsaXplIH0gZnJvbSAnZW1iZXItaW5mbGVjdG9yJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgcGF0aEZvclR5cGU6IGZ1bmN0aW9uKG1vZGVsTmFtZSkgewogICAgICAgICAgdmFyIGRlY2FtZWxpemVkID0gZGVjYW1lbGl6ZShtb2RlbE5hbWUpOwogICAgICAgICAgcmV0dXJuIHBsdXJhbGl6ZShkZWNhbWVsaXplZCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHBhdGhGb3JUeXBlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHJldHVybiB7U3RyaW5nfSBwYXRoCiAgICAqKi8KICAgIHBhdGhGb3JUeXBlOiBmdW5jdGlvbiBwYXRoRm9yVHlwZShtb2RlbE5hbWUpIHsKICAgICAgdmFyIGNhbWVsaXplZCA9IEVtYmVyLlN0cmluZy5jYW1lbGl6ZShtb2RlbE5hbWUpOwogICAgICByZXR1cm4gZW1iZXJJbmZsZWN0b3IucGx1cmFsaXplKGNhbWVsaXplZCk7CiAgICB9CiAgfSk7CgogIGZ1bmN0aW9uIHNlcmlhbGl6ZUludG9IYXNoKHN0b3JlLCBtb2RlbENsYXNzLCBzbmFwc2hvdCwgb3B0aW9ucykgewogICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICBvcHRpb25zID0gewogICAgICAgIGluY2x1ZGVJZDogdHJ1ZQogICAgICB9OwogICAgfQoKICAgIHZhciBzZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcihtb2RlbENsYXNzLm1vZGVsTmFtZSk7CgogICAgaWYgKHR5cGVvZiBzZXJpYWxpemVyLnNlcmlhbGl6ZUludG9IYXNoID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIHZhciBkYXRhID0ge307CiAgICAgIHNlcmlhbGl6ZXIuc2VyaWFsaXplSW50b0hhc2goZGF0YSwgbW9kZWxDbGFzcywgc25hcHNob3QsIG9wdGlvbnMpOwogICAgICByZXR1cm4gZGF0YTsKICAgIH0KCiAgICByZXR1cm4gc2VyaWFsaXplci5zZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpOwogIH0KCiAgZXhwb3J0cy5CdWlsZFVSTE1peGluID0gYnVpbGRVcmxNaXhpbjsKICBleHBvcnRzLmRldGVybWluZUJvZHlQcm9taXNlID0gZGV0ZXJtaW5lQm9keVByb21pc2U7CiAgZXhwb3J0cy5mZXRjaCA9IGdldEZldGNoRnVuY3Rpb247CiAgZXhwb3J0cy5wYXJzZVJlc3BvbnNlSGVhZGVycyA9IHBhcnNlUmVzcG9uc2VIZWFkZXJzOwogIGV4cG9ydHMuc2VyaWFsaXplSW50b0hhc2ggPSBzZXJpYWxpemVJbnRvSGFzaDsKICBleHBvcnRzLnNlcmlhbGl6ZVF1ZXJ5UGFyYW1zID0gc2VyaWFsaXplUXVlcnlQYXJhbXM7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7Cgp9KTsKCjtkZWZpbmUoIkBlbWJlci1kYXRhL2FkYXB0ZXIvZXJyb3IiLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvc3RvcmUvLXByaXZhdGUiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfcHJpdmF0ZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZXJyb3JzSGFzaFRvQXJyYXkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJpdmF0ZS5lcnJvcnNIYXNoVG9BcnJheTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJlcnJvcnNBcnJheVRvSGFzaCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9wcml2YXRlLmVycm9yc0FycmF5VG9IYXNoOwogICAgfQogIH0pOwogIF9leHBvcnRzLlNlcnZlckVycm9yID0gX2V4cG9ydHMuQ29uZmxpY3RFcnJvciA9IF9leHBvcnRzLk5vdEZvdW5kRXJyb3IgPSBfZXhwb3J0cy5Gb3JiaWRkZW5FcnJvciA9IF9leHBvcnRzLlVuYXV0aG9yaXplZEVycm9yID0gX2V4cG9ydHMuQWJvcnRFcnJvciA9IF9leHBvcnRzLlRpbWVvdXRFcnJvciA9IF9leHBvcnRzLkludmFsaWRFcnJvciA9IF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9hZGFwdGVyCiAgKi8KCiAgLyoqCiAgICBBIGBBZGFwdGVyRXJyb3JgIGlzIHVzZWQgYnkgYW4gYWRhcHRlciB0byBzaWduYWwgdGhhdCBhbiBlcnJvciBvY2N1cnJlZAogICAgZHVyaW5nIGEgcmVxdWVzdCB0byBhbiBleHRlcm5hbCBBUEkuIEl0IGluZGljYXRlcyBhIGdlbmVyaWMgZXJyb3IsIGFuZAogICAgc3ViY2xhc3NlcyBhcmUgdXNlZCB0byBpbmRpY2F0ZSBzcGVjaWZpYyBlcnJvciBzdGF0ZXMuIFRoZSBmb2xsb3dpbmcKICAgIHN1YmNsYXNzZXMgYXJlIHByb3ZpZGVkOgogIAogICAgLSBgSW52YWxpZEVycm9yYAogICAgLSBgVGltZW91dEVycm9yYAogICAgLSBgQWJvcnRFcnJvcmAKICAgIC0gYFVuYXV0aG9yaXplZEVycm9yYAogICAgLSBgRm9yYmlkZGVuRXJyb3JgCiAgICAtIGBOb3RGb3VuZEVycm9yYAogICAgLSBgQ29uZmxpY3RFcnJvcmAKICAgIC0gYFNlcnZlckVycm9yYAogIAogICAgVG8gY3JlYXRlIGEgY3VzdG9tIGVycm9yIHRvIHNpZ25hbCBhIHNwZWNpZmljIGVycm9yIHN0YXRlIGluIGNvbW11bmljYXRpbmcKICAgIHdpdGggYW4gZXh0ZXJuYWwgQVBJLCBleHRlbmQgdGhlIGBBZGFwdGVyRXJyb3JgLiBGb3IgZXhhbXBsZSwgaWYgdGhlCiAgICBleHRlcm5hbCBBUEkgZXhjbHVzaXZlbHkgdXNlZCBIVFRQIGA1MDMgU2VydmljZSBVbmF2YWlsYWJsZWAgdG8gaW5kaWNhdGUKICAgIGl0IHdhcyBjbG9zZWQgZm9yIG1haW50ZW5hbmNlOgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL21haW50ZW5hbmNlLWVycm9yLmpzCiAgICBpbXBvcnQgQWRhcHRlckVycm9yIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvZXJyb3InOwogIAogICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlckVycm9yLmV4dGVuZCh7IG1lc3NhZ2U6ICJEb3duIGZvciBtYWludGVuYW5jZS4iIH0pOwogICAgYGBgCiAgCiAgICBUaGlzIGVycm9yIHdvdWxkIHRoZW4gYmUgcmV0dXJuZWQgYnkgYW4gYWRhcHRlcidzIGBoYW5kbGVSZXNwb25zZWAgbWV0aG9kOgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgSlNPTkFQSUFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9qc29uLWFwaSc7CiAgICBpbXBvcnQgTWFpbnRlbmFuY2VFcnJvciBmcm9tICcuL21haW50ZW5hbmNlLWVycm9yJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IEpTT05BUElBZGFwdGVyLmV4dGVuZCh7CiAgICAgIGhhbmRsZVJlc3BvbnNlKHN0YXR1cykgewogICAgICAgIGlmICg1MDMgPT09IHN0YXR1cykgewogICAgICAgICAgcmV0dXJuIG5ldyBNYWludGVuYW5jZUVycm9yKCk7CiAgICAgICAgfQogIAogICAgICAgIHJldHVybiB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQW5kIGNhbiB0aGVuIGJlIGRldGVjdGVkIGluIGFuIGFwcGxpY2F0aW9uIGFuZCB1c2VkIHRvIHNlbmQgdGhlIHVzZXIgdG8gYW4KICAgIGB1bmRlci1tYWludGVuYW5jZWAgcm91dGU6CiAgCiAgICBgYGBhcHAvcm91dGVzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgaW1wb3J0IE1haW50ZW5hbmNlRXJyb3IgZnJvbSAnLi4vYWRhcHRlcnMvbWFpbnRlbmFuY2UtZXJyb3InOwogIAogICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgYWN0aW9uczogewogICAgICAgIGVycm9yKGVycm9yLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBNYWludGVuYW5jZUVycm9yKSB7CiAgICAgICAgICAgIHRoaXMudHJhbnNpdGlvblRvKCd1bmRlci1tYWludGVuYW5jZScpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CiAgCiAgICAgICAgICAvLyAuLi5vdGhlciBlcnJvciBoYW5kbGluZyBsb2dpYwogICAgICAgIH0KICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBBZGFwdGVyRXJyb3IKICAqLwogIGZ1bmN0aW9uIEFkYXB0ZXJFcnJvcihlcnJvcnMsIG1lc3NhZ2UpIHsKICAgIGlmIChtZXNzYWdlID09PSB2b2lkIDApIHsKICAgICAgbWVzc2FnZSA9ICdBZGFwdGVyIG9wZXJhdGlvbiBmYWlsZWQnOwogICAgfQoKICAgIHRoaXMuaXNBZGFwdGVyRXJyb3IgPSB0cnVlOwogICAgdmFyIGVycm9yID0gRW1iZXIuRXJyb3IuY2FsbCh0aGlzLCBtZXNzYWdlKTsgLy8gaW4gZW1iZXIgMy44KyBFcnJvciBpcyBhIE5hdGl2ZSBFcnJvciBhbmQgd2UgZG9uJ3QKICAgIC8vIGdhaW4gdGhlc2UgYXV0b21hdGljYWxseSBmcm9tIHRoZSBFbWJlckVycm9yLmNhbGwKCiAgICBpZiAoZXJyb3IpIHsKICAgICAgdGhpcy5zdGFjayA9IGVycm9yLnN0YWNrOwogICAgICB0aGlzLmRlc2NyaXB0aW9uID0gZXJyb3IuZGVzY3JpcHRpb247CiAgICAgIHRoaXMuZmlsZU5hbWUgPSBlcnJvci5maWxlTmFtZTsKICAgICAgdGhpcy5saW5lTnVtYmVyID0gZXJyb3IubGluZU51bWJlcjsKICAgICAgdGhpcy5tZXNzYWdlID0gZXJyb3IubWVzc2FnZTsKICAgICAgdGhpcy5uYW1lID0gZXJyb3IubmFtZTsKICAgICAgdGhpcy5udW1iZXIgPSBlcnJvci5udW1iZXI7CiAgICB9CgogICAgdGhpcy5lcnJvcnMgPSBlcnJvcnMgfHwgW3sKICAgICAgdGl0bGU6ICdBZGFwdGVyIEVycm9yJywKICAgICAgZGV0YWlsOiBtZXNzYWdlCiAgICB9XTsKICB9CgogIHZhciBfZGVmYXVsdCA9IEFkYXB0ZXJFcnJvcjsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7CgogIGZ1bmN0aW9uIGV4dGVuZEZuKEVycm9yQ2xhc3MpIHsKICAgIHJldHVybiBmdW5jdGlvbiAoX3RlbXApIHsKICAgICAgdmFyIF9yZWYgPSBfdGVtcCA9PT0gdm9pZCAwID8ge30gOiBfdGVtcCwKICAgICAgICAgIGRlZmF1bHRNZXNzYWdlID0gX3JlZi5tZXNzYWdlOwoKICAgICAgcmV0dXJuIGV4dGVuZChFcnJvckNsYXNzLCBkZWZhdWx0TWVzc2FnZSk7CiAgICB9OwogIH0KCiAgZnVuY3Rpb24gZXh0ZW5kKFBhcmVudEVycm9yQ2xhc3MsIGRlZmF1bHRNZXNzYWdlKSB7CiAgICB2YXIgRXJyb3JDbGFzcyA9IGZ1bmN0aW9uIEVycm9yQ2xhc3MoZXJyb3JzLCBtZXNzYWdlKSB7CiAgICAgIChmYWxzZSAmJiAhKEFycmF5LmlzQXJyYXkoZXJyb3JzIHx8IFtdKSkgJiYgRW1iZXIuYXNzZXJ0KCdgQWRhcHRlckVycm9yYCBleHBlY3RzIGpzb24tYXBpIGZvcm1hdHRlZCBlcnJvcnMgYXJyYXkuJywgQXJyYXkuaXNBcnJheShlcnJvcnMgfHwgW10pKSk7CiAgICAgIFBhcmVudEVycm9yQ2xhc3MuY2FsbCh0aGlzLCBlcnJvcnMsIG1lc3NhZ2UgfHwgZGVmYXVsdE1lc3NhZ2UpOwogICAgfTsKCiAgICBFcnJvckNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoUGFyZW50RXJyb3JDbGFzcy5wcm90b3R5cGUpOwogICAgRXJyb3JDbGFzcy5leHRlbmQgPSBleHRlbmRGbihFcnJvckNsYXNzKTsKICAgIHJldHVybiBFcnJvckNsYXNzOwogIH0KCiAgQWRhcHRlckVycm9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRW1iZXIuRXJyb3IucHJvdG90eXBlKTsKICBBZGFwdGVyRXJyb3IucHJvdG90eXBlLmNvZGUgPSAnQWRhcHRlckVycm9yJzsKICBBZGFwdGVyRXJyb3IuZXh0ZW5kID0gZXh0ZW5kRm4oQWRhcHRlckVycm9yKTsKICAvKioKICAgIEEgYEludmFsaWRFcnJvcmAgaXMgdXNlZCBieSBhbiBhZGFwdGVyIHRvIHNpZ25hbCB0aGUgZXh0ZXJuYWwgQVBJCiAgICB3YXMgdW5hYmxlIHRvIHByb2Nlc3MgYSByZXF1ZXN0IGJlY2F1c2UgdGhlIGNvbnRlbnQgd2FzIG5vdAogICAgc2VtYW50aWNhbGx5IGNvcnJlY3Qgb3IgbWVhbmluZ2Z1bCBwZXIgdGhlIEFQSS4gVXN1YWxseSwgdGhpcyBtZWFucyBhCiAgICByZWNvcmQgZmFpbGVkIHNvbWUgZm9ybSBvZiBzZXJ2ZXItc2lkZSB2YWxpZGF0aW9uLiBXaGVuIGEgcHJvbWlzZQogICAgZnJvbSBhbiBhZGFwdGVyIGlzIHJlamVjdGVkIHdpdGggYSBgSW52YWxpZEVycm9yYCB0aGUgcmVjb3JkIHdpbGwKICAgIHRyYW5zaXRpb24gdG8gdGhlIGBpbnZhbGlkYCBzdGF0ZSBhbmQgdGhlIGVycm9ycyB3aWxsIGJlIHNldCB0byB0aGUKICAgIGBlcnJvcnNgIHByb3BlcnR5IG9uIHRoZSByZWNvcmQuCiAgCiAgICBGb3IgRW1iZXIgRGF0YSB0byBjb3JyZWN0bHkgbWFwIGVycm9ycyB0byB0aGVpciBjb3JyZXNwb25kaW5nCiAgICBwcm9wZXJ0aWVzIG9uIHRoZSBtb2RlbCwgRW1iZXIgRGF0YSBleHBlY3RzIGVhY2ggZXJyb3IgdG8gYmUKICAgIGEgdmFsaWQgSlNPTi1BUEkgZXJyb3Igb2JqZWN0IHdpdGggYSBgc291cmNlL3BvaW50ZXJgIHRoYXQgbWF0Y2hlcwogICAgdGhlIHByb3BlcnR5IG5hbWUuIEZvciBleGFtcGxlLCBpZiB5b3UgaGFkIGEgUG9zdCBtb2RlbCB0aGF0CiAgICBsb29rZWQgbGlrZSB0aGlzLgogIAogICAgYGBgYXBwL21vZGVscy9wb3N0LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHRpdGxlOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgY29udGVudDogYXR0cignc3RyaW5nJykKICAgIH0pOwogICAgYGBgCiAgCiAgICBUbyBzaG93IGFuIGVycm9yIGZyb20gdGhlIHNlcnZlciByZWxhdGVkIHRvIHRoZSBgdGl0bGVgIGFuZAogICAgYGNvbnRlbnRgIHByb3BlcnRpZXMgeW91ciBhZGFwdGVyIGNvdWxkIHJldHVybiBhIHByb21pc2UgdGhhdAogICAgcmVqZWN0cyB3aXRoIGEgYEludmFsaWRFcnJvcmAgb2JqZWN0IHRoYXQgbG9va3MgbGlrZSB0aGlzOgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL3Bvc3QuanMKICAgIGltcG9ydCBSU1ZQIGZyb20gJ1JTVlAnOwogICAgaW1wb3J0IFJFU1RBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCc7CiAgICBpbXBvcnQgeyBJbnZhbGlkRXJyb3IgfSBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL2Vycm9yJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgIHVwZGF0ZVJlY29yZCgpIHsKICAgICAgICAvLyBGaWN0aW9uYWwgYWRhcHRlciB0aGF0IGFsd2F5cyByZWplY3RzCiAgICAgICAgcmV0dXJuIFJTVlAucmVqZWN0KG5ldyBJbnZhbGlkRXJyb3IoWwogICAgICAgICAgewogICAgICAgICAgICBkZXRhaWw6ICdNdXN0IGJlIHVuaXF1ZScsCiAgICAgICAgICAgIHNvdXJjZTogeyBwb2ludGVyOiAnL2RhdGEvYXR0cmlidXRlcy90aXRsZScgfQogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgZGV0YWlsOiAnTXVzdCBub3QgYmUgYmxhbmsnLAogICAgICAgICAgICBzb3VyY2U6IHsgcG9pbnRlcjogJy9kYXRhL2F0dHJpYnV0ZXMvY29udGVudCd9CiAgICAgICAgICB9CiAgICAgICAgXSkpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgWW91ciBiYWNrZW5kIG1heSB1c2UgZGlmZmVyZW50IHByb3BlcnR5IG5hbWVzIGZvciB5b3VyIHJlY29yZHMgdGhlCiAgICBzdG9yZSB3aWxsIGF0dGVtcHQgdG8gZXh0cmFjdCBhbmQgbm9ybWFsaXplIHRoZSBlcnJvcnMgdXNpbmcgdGhlCiAgICBzZXJpYWxpemVyJ3MgYGV4dHJhY3RFcnJvcnNgIG1ldGhvZCBiZWZvcmUgdGhlIGVycm9ycyBnZXQgYWRkZWQgdG8KICAgIHRoZSBtb2RlbC4gQXMgYSByZXN1bHQsIGl0IGlzIHNhZmUgZm9yIHRoZSBgSW52YWxpZEVycm9yYCB0bwogICAgd3JhcCB0aGUgZXJyb3IgcGF5bG9hZCB1bmFsdGVyZWQuCiAgCiAgICBAY2xhc3MgSW52YWxpZEVycm9yCiAgICBAZXh0ZW5kcyBBZGFwdGVyRXJyb3IKICAqLwoKICB2YXIgSW52YWxpZEVycm9yID0gZXh0ZW5kKEFkYXB0ZXJFcnJvciwgJ1RoZSBhZGFwdGVyIHJlamVjdGVkIHRoZSBjb21taXQgYmVjYXVzZSBpdCB3YXMgaW52YWxpZCcpOwogIF9leHBvcnRzLkludmFsaWRFcnJvciA9IEludmFsaWRFcnJvcjsKICBJbnZhbGlkRXJyb3IucHJvdG90eXBlLmNvZGUgPSAnSW52YWxpZEVycm9yJzsKICAvKioKICAgIEEgYFRpbWVvdXRFcnJvcmAgaXMgdXNlZCBieSBhbiBhZGFwdGVyIHRvIHNpZ25hbCB0aGF0IGEgcmVxdWVzdAogICAgdG8gdGhlIGV4dGVybmFsIEFQSSBoYXMgdGltZWQgb3V0LiBJLmUuIG5vIHJlc3BvbnNlIHdhcyByZWNlaXZlZCBmcm9tCiAgICB0aGUgZXh0ZXJuYWwgQVBJIHdpdGhpbiBhbiBhbGxvd2VkIHRpbWUgcGVyaW9kLgogIAogICAgQW4gZXhhbXBsZSB1c2UgY2FzZSB3b3VsZCBiZSB0byB3YXJuIHRoZSB1c2VyIHRvIGNoZWNrIHRoZWlyIGludGVybmV0CiAgICBjb25uZWN0aW9uIGlmIGFuIGFkYXB0ZXIgb3BlcmF0aW9uIGhhcyB0aW1lZCBvdXQ6CiAgCiAgICBgYGBhcHAvcm91dGVzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgaW1wb3J0IHsgVGltZW91dEVycm9yIH0gZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9lcnJvcic7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICBhY3Rpb25zOiB7CiAgICAgICAgZXJyb3IoZXJyb3IsIHRyYW5zaXRpb24pIHsKICAgICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFRpbWVvdXRFcnJvcikgewogICAgICAgICAgICAvLyBhbGVydCB0aGUgdXNlcgogICAgICAgICAgICBhbGVydCgnQXJlIHlvdSBzdGlsbCBjb25uZWN0ZWQgdG8gdGhlIGludGVybmV0PycpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CiAgCiAgICAgICAgICAvLyAuLi5vdGhlciBlcnJvciBoYW5kbGluZyBsb2dpYwogICAgICAgIH0KICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBUaW1lb3V0RXJyb3IKICAgIEBleHRlbmRzIEFkYXB0ZXJFcnJvcgogICovCgogIHZhciBUaW1lb3V0RXJyb3IgPSBleHRlbmQoQWRhcHRlckVycm9yLCAnVGhlIGFkYXB0ZXIgb3BlcmF0aW9uIHRpbWVkIG91dCcpOwogIF9leHBvcnRzLlRpbWVvdXRFcnJvciA9IFRpbWVvdXRFcnJvcjsKICBUaW1lb3V0RXJyb3IucHJvdG90eXBlLmNvZGUgPSAnVGltZW91dEVycm9yJzsKICAvKioKICAgIEEgYEFib3J0RXJyb3JgIGlzIHVzZWQgYnkgYW4gYWRhcHRlciB0byBzaWduYWwgdGhhdCBhIHJlcXVlc3QgdG8KICAgIHRoZSBleHRlcm5hbCBBUEkgd2FzIGFib3J0ZWQuIEZvciBleGFtcGxlLCB0aGlzIGNhbiBvY2N1ciBpZiB0aGUgdXNlcgogICAgbmF2aWdhdGVzIGF3YXkgZnJvbSB0aGUgY3VycmVudCBwYWdlIGFmdGVyIGEgcmVxdWVzdCB0byB0aGUgZXh0ZXJuYWwgQVBJCiAgICBoYXMgYmVlbiBpbml0aWF0ZWQgYnV0IGJlZm9yZSBhIHJlc3BvbnNlIGhhcyBiZWVuIHJlY2VpdmVkLgogIAogICAgQGNsYXNzIEFib3J0RXJyb3IKICAgIEBleHRlbmRzIEFkYXB0ZXJFcnJvcgogICovCgogIHZhciBBYm9ydEVycm9yID0gZXh0ZW5kKEFkYXB0ZXJFcnJvciwgJ1RoZSBhZGFwdGVyIG9wZXJhdGlvbiB3YXMgYWJvcnRlZCcpOwogIF9leHBvcnRzLkFib3J0RXJyb3IgPSBBYm9ydEVycm9yOwogIEFib3J0RXJyb3IucHJvdG90eXBlLmNvZGUgPSAnQWJvcnRFcnJvcic7CiAgLyoqCiAgICBBIGBVbmF1dGhvcml6ZWRFcnJvcmAgZXF1YXRlcyB0byBhIEhUVFAgYDQwMSBVbmF1dGhvcml6ZWRgIHJlc3BvbnNlCiAgICBzdGF0dXMuIEl0IGlzIHVzZWQgYnkgYW4gYWRhcHRlciB0byBzaWduYWwgdGhhdCBhIHJlcXVlc3QgdG8gdGhlIGV4dGVybmFsCiAgICBBUEkgd2FzIHJlamVjdGVkIGJlY2F1c2UgYXV0aG9yaXphdGlvbiBpcyByZXF1aXJlZCBhbmQgaGFzIGZhaWxlZCBvciBoYXMgbm90CiAgICB5ZXQgYmVlbiBwcm92aWRlZC4KICAKICAgIEFuIGV4YW1wbGUgdXNlIGNhc2Ugd291bGQgYmUgdG8gcmVkaXJlY3QgdGhlIHVzZXIgdG8gYSBsb2dpbiByb3V0ZSBpZiBhCiAgICByZXF1ZXN0IGlzIHVuYXV0aG9yaXplZDoKICAKICAgIGBgYGFwcC9yb3V0ZXMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICBpbXBvcnQgeyBVbmF1dGhvcml6ZWRFcnJvciB9IGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvZXJyb3InOwogIAogICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgYWN0aW9uczogewogICAgICAgIGVycm9yKGVycm9yLCB0cmFuc2l0aW9uKSB7CiAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBVbmF1dGhvcml6ZWRFcnJvcikgewogICAgICAgICAgICAvLyBnbyB0byB0aGUgc2lnbiBpbiByb3V0ZQogICAgICAgICAgICB0aGlzLnRyYW5zaXRpb25UbygnbG9naW4nKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgfQogIAogICAgICAgICAgLy8gLi4ub3RoZXIgZXJyb3IgaGFuZGxpbmcgbG9naWMKICAgICAgICB9CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBAY2xhc3MgVW5hdXRob3JpemVkRXJyb3IKICAgIEBleHRlbmRzIEFkYXB0ZXJFcnJvcgogICovCgogIHZhciBVbmF1dGhvcml6ZWRFcnJvciA9IGV4dGVuZChBZGFwdGVyRXJyb3IsICdUaGUgYWRhcHRlciBvcGVyYXRpb24gaXMgdW5hdXRob3JpemVkJyk7CiAgX2V4cG9ydHMuVW5hdXRob3JpemVkRXJyb3IgPSBVbmF1dGhvcml6ZWRFcnJvcjsKICBVbmF1dGhvcml6ZWRFcnJvci5wcm90b3R5cGUuY29kZSA9ICdVbmF1dGhvcml6ZWRFcnJvcic7CiAgLyoqCiAgICBBIGBGb3JiaWRkZW5FcnJvcmAgZXF1YXRlcyB0byBhIEhUVFAgYDQwMyBGb3JiaWRkZW5gIHJlc3BvbnNlIHN0YXR1cy4KICAgIEl0IGlzIHVzZWQgYnkgYW4gYWRhcHRlciB0byBzaWduYWwgdGhhdCBhIHJlcXVlc3QgdG8gdGhlIGV4dGVybmFsIEFQSSB3YXMKICAgIHZhbGlkIGJ1dCB0aGUgc2VydmVyIGlzIHJlZnVzaW5nIHRvIHJlc3BvbmQgdG8gaXQuIElmIGF1dGhvcml6YXRpb24gd2FzCiAgICBwcm92aWRlZCBhbmQgaXMgdmFsaWQsIHRoZW4gdGhlIGF1dGhlbnRpY2F0ZWQgdXNlciBkb2VzIG5vdCBoYXZlIHRoZQogICAgbmVjZXNzYXJ5IHBlcm1pc3Npb25zIGZvciB0aGUgcmVxdWVzdC4KICAKICAgIEBjbGFzcyBGb3JiaWRkZW5FcnJvcgogICAgQGV4dGVuZHMgQWRhcHRlckVycm9yCiAgKi8KCiAgdmFyIEZvcmJpZGRlbkVycm9yID0gZXh0ZW5kKEFkYXB0ZXJFcnJvciwgJ1RoZSBhZGFwdGVyIG9wZXJhdGlvbiBpcyBmb3JiaWRkZW4nKTsKICBfZXhwb3J0cy5Gb3JiaWRkZW5FcnJvciA9IEZvcmJpZGRlbkVycm9yOwogIEZvcmJpZGRlbkVycm9yLnByb3RvdHlwZS5jb2RlID0gJ0ZvcmJpZGRlbkVycm9yJzsKICAvKioKICAgIEEgYE5vdEZvdW5kRXJyb3JgIGVxdWF0ZXMgdG8gYSBIVFRQIGA0MDQgTm90IEZvdW5kYCByZXNwb25zZSBzdGF0dXMuCiAgICBJdCBpcyB1c2VkIGJ5IGFuIGFkYXB0ZXIgdG8gc2lnbmFsIHRoYXQgYSByZXF1ZXN0IHRvIHRoZSBleHRlcm5hbCBBUEkKICAgIHdhcyByZWplY3RlZCBiZWNhdXNlIHRoZSByZXNvdXJjZSBjb3VsZCBub3QgYmUgZm91bmQgb24gdGhlIEFQSS4KICAKICAgIEFuIGV4YW1wbGUgdXNlIGNhc2Ugd291bGQgYmUgdG8gZGV0ZWN0IGlmIHRoZSB1c2VyIGhhcyBlbnRlcmVkIGEgcm91dGUKICAgIGZvciBhIHNwZWNpZmljIG1vZGVsIHRoYXQgZG9lcyBub3QgZXhpc3QuIEZvciBleGFtcGxlOgogIAogICAgYGBgYXBwL3JvdXRlcy9wb3N0LmpzCiAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgaW1wb3J0IHsgTm90Rm91bmRFcnJvciB9IGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvZXJyb3InOwogIAogICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgbW9kZWwocGFyYW1zKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KCdzdG9yZScpLmZpbmRSZWNvcmQoJ3Bvc3QnLCBwYXJhbXMucG9zdF9pZCk7CiAgICAgIH0sCiAgCiAgICAgIGFjdGlvbnM6IHsKICAgICAgICBlcnJvcihlcnJvciwgdHJhbnNpdGlvbikgewogICAgICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgTm90Rm91bmRFcnJvcikgewogICAgICAgICAgICAvLyByZWRpcmVjdCB0byBhIGxpc3Qgb2YgYWxsIHBvc3RzIGluc3RlYWQKICAgICAgICAgICAgdGhpcy50cmFuc2l0aW9uVG8oJ3Bvc3RzJyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvLyBvdGhlcndpc2UgbGV0IHRoZSBlcnJvciBidWJibGUKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgQGNsYXNzIE5vdEZvdW5kRXJyb3IKICAgIEBleHRlbmRzIEFkYXB0ZXJFcnJvcgogICovCgogIHZhciBOb3RGb3VuZEVycm9yID0gZXh0ZW5kKEFkYXB0ZXJFcnJvciwgJ1RoZSBhZGFwdGVyIGNvdWxkIG5vdCBmaW5kIHRoZSByZXNvdXJjZScpOwogIF9leHBvcnRzLk5vdEZvdW5kRXJyb3IgPSBOb3RGb3VuZEVycm9yOwogIE5vdEZvdW5kRXJyb3IucHJvdG90eXBlLmNvZGUgPSAnTm90Rm91bmRFcnJvcic7CiAgLyoqCiAgICBBIGBDb25mbGljdEVycm9yYCBlcXVhdGVzIHRvIGEgSFRUUCBgNDA5IENvbmZsaWN0YCByZXNwb25zZSBzdGF0dXMuCiAgICBJdCBpcyB1c2VkIGJ5IGFuIGFkYXB0ZXIgdG8gaW5kaWNhdGUgdGhhdCB0aGUgcmVxdWVzdCBjb3VsZCBub3QgYmUgcHJvY2Vzc2VkCiAgICBiZWNhdXNlIG9mIGEgY29uZmxpY3QgaW4gdGhlIHJlcXVlc3QuIEFuIGV4YW1wbGUgc2NlbmFyaW8gd291bGQgYmUgd2hlbgogICAgY3JlYXRpbmcgYSByZWNvcmQgd2l0aCBhIGNsaWVudC1nZW5lcmF0ZWQgSUQgYnV0IHRoYXQgSUQgaXMgYWxyZWFkeSBrbm93bgogICAgdG8gdGhlIGV4dGVybmFsIEFQSS4KICAKICAgIEBjbGFzcyBDb25mbGljdEVycm9yCiAgICBAZXh0ZW5kcyBBZGFwdGVyRXJyb3IKICAqLwoKICB2YXIgQ29uZmxpY3RFcnJvciA9IGV4dGVuZChBZGFwdGVyRXJyb3IsICdUaGUgYWRhcHRlciBvcGVyYXRpb24gZmFpbGVkIGR1ZSB0byBhIGNvbmZsaWN0Jyk7CiAgX2V4cG9ydHMuQ29uZmxpY3RFcnJvciA9IENvbmZsaWN0RXJyb3I7CiAgQ29uZmxpY3RFcnJvci5wcm90b3R5cGUuY29kZSA9ICdDb25mbGljdEVycm9yJzsKICAvKioKICAgIEEgYFNlcnZlckVycm9yYCBlcXVhdGVzIHRvIGEgSFRUUCBgNTAwIEludGVybmFsIFNlcnZlciBFcnJvcmAgcmVzcG9uc2UKICAgIHN0YXR1cy4gSXQgaXMgdXNlZCBieSB0aGUgYWRhcHRlciB0byBpbmRpY2F0ZSB0aGF0IGEgcmVxdWVzdCBoYXMgZmFpbGVkCiAgICBiZWNhdXNlIG9mIGFuIGVycm9yIGluIHRoZSBleHRlcm5hbCBBUEkuCiAgCiAgICBAY2xhc3MgU2VydmVyRXJyb3IKICAgIEBleHRlbmRzIEFkYXB0ZXJFcnJvcgogICovCgogIHZhciBTZXJ2ZXJFcnJvciA9IGV4dGVuZChBZGFwdGVyRXJyb3IsICdUaGUgYWRhcHRlciBvcGVyYXRpb24gZmFpbGVkIGR1ZSB0byBhIHNlcnZlciBlcnJvcicpOwogIF9leHBvcnRzLlNlcnZlckVycm9yID0gU2VydmVyRXJyb3I7CiAgU2VydmVyRXJyb3IucHJvdG90eXBlLmNvZGUgPSAnU2VydmVyRXJyb3InOwp9KTsKO2RlZmluZSgiQGVtYmVyLWRhdGEvYWRhcHRlci9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9hZGFwdGVyLy1wcml2YXRlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3ByaXZhdGUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkJ1aWxkVVJMTWl4aW4iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJpdmF0ZS5CdWlsZFVSTE1peGluOwogICAgfQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAgQW4gYWRhcHRlciBpcyBhbiBvYmplY3QgdGhhdCByZWNlaXZlcyByZXF1ZXN0cyBmcm9tIGEgc3RvcmUgYW5kCiAgICB0cmFuc2xhdGVzIHRoZW0gaW50byB0aGUgYXBwcm9wcmlhdGUgYWN0aW9uIHRvIHRha2UgYWdhaW5zdCB5b3VyCiAgICBwZXJzaXN0ZW5jZSBsYXllci4gVGhlIHBlcnNpc3RlbmNlIGxheWVyIGlzIHVzdWFsbHkgYW4gSFRUUCBBUEkgYnV0CiAgICBtYXkgYmUgYW55dGhpbmcsIHN1Y2ggYXMgdGhlIGJyb3dzZXIncyBsb2NhbCBzdG9yYWdlLiBUeXBpY2FsbHkgdGhlCiAgICBhZGFwdGVyIGlzIG5vdCBpbnZva2VkIGRpcmVjdGx5IGluc3RlYWQgaXRzIGZ1bmN0aW9uYWxpdHkgaXMgYWNjZXNzZWQKICAgIHRocm91Z2ggdGhlIGBzdG9yZWAuCiAgCiAgICAjIyMgQ3JlYXRpbmcgYW4gQWRhcHRlcgogIAogICAgQ3JlYXRlIGEgbmV3IHN1YmNsYXNzIG9mIGBBZGFwdGVyYCBpbiB0aGUgYGFwcC9hZGFwdGVyc2AgZm9sZGVyOgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgLy8gLi4ueW91ciBjb2RlIGhlcmUKICAgIH0pOwogICAgYGBgCiAgCiAgICBNb2RlbC1zcGVjaWZpYyBhZGFwdGVycyBjYW4gYmUgY3JlYXRlZCBieSBwdXR0aW5nIHlvdXIgYWRhcHRlcgogICAgY2xhc3MgaW4gYW4gYGFwcC9hZGFwdGVycy9gICsgYG1vZGVsLW5hbWVgICsgYC5qc2AgZmlsZSBvZiB0aGUgYXBwbGljYXRpb24uCiAgCiAgICBgYGBhcHAvYWRhcHRlcnMvcG9zdC5qcwogICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgIC8vIC4uLlBvc3Qtc3BlY2lmaWMgYWRhcHRlciBjb2RlIGdvZXMgaGVyZQogICAgfSk7CiAgICBgYGAKICAKICAgIGBBZGFwdGVyYCBpcyBhbiBhYnN0cmFjdCBiYXNlIGNsYXNzIHRoYXQgeW91IHNob3VsZCBvdmVycmlkZSBpbiB5b3VyCiAgICBhcHBsaWNhdGlvbiB0byBjdXN0b21pemUgaXQgZm9yIHlvdXIgYmFja2VuZC4gVGhlIG1pbmltdW0gc2V0IG9mIG1ldGhvZHMKICAgIHRoYXQgeW91IHNob3VsZCBpbXBsZW1lbnQgaXM6CiAgCiAgICAgICogYGZpbmRSZWNvcmQoKWAKICAgICAgKiBgY3JlYXRlUmVjb3JkKClgCiAgICAgICogYHVwZGF0ZVJlY29yZCgpYAogICAgICAqIGBkZWxldGVSZWNvcmQoKWAKICAgICAgKiBgZmluZEFsbCgpYAogICAgICAqIGBxdWVyeSgpYAogIAogICAgVG8gaW1wcm92ZSB0aGUgbmV0d29yayBwZXJmb3JtYW5jZSBvZiB5b3VyIGFwcGxpY2F0aW9uLCB5b3UgY2FuIG9wdGltaXplCiAgICB5b3VyIGFkYXB0ZXIgYnkgb3ZlcnJpZGluZyB0aGVzZSBsb3dlci1sZXZlbCBtZXRob2RzOgogIAogICAgICAqIGBmaW5kTWFueSgpYAogIAogIAogICAgRm9yIGFuIGV4YW1wbGUgb2YgdGhlIGltcGxlbWVudGF0aW9uLCBzZWUgYFJFU1RBZGFwdGVyYCwgdGhlCiAgICBpbmNsdWRlZCBSRVNUIGFkYXB0ZXIuCiAgCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL2FkYXB0ZXIKICAgIEBjbGFzcyBBZGFwdGVyCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICovCiAgdmFyIF9kZWZhdWx0ID0gRW1iZXIuT2JqZWN0LmV4dGVuZCh7CiAgICAvKioKICAgICAgSWYgeW91IHdvdWxkIGxpa2UgeW91ciBhZGFwdGVyIHRvIHVzZSBhIGN1c3RvbSBzZXJpYWxpemVyIHlvdSBjYW4KICAgICAgc2V0IHRoZSBgZGVmYXVsdFNlcmlhbGl6ZXJgIHByb3BlcnR5IHRvIGJlIHRoZSBuYW1lIG9mIHRoZSBjdXN0b20KICAgICAgc2VyaWFsaXplci4KICAgICAgIE5vdGUgdGhlIGBkZWZhdWx0U2VyaWFsaXplcmAgc2VyaWFsaXplciBoYXMgYSBsb3dlciBwcmlvcml0eSB0aGFuCiAgICAgIGEgbW9kZWwgc3BlY2lmaWMgc2VyaWFsaXplciAoaS5lLiBgUG9zdFNlcmlhbGl6ZXJgKSBvciB0aGUKICAgICAgYGFwcGxpY2F0aW9uYCBzZXJpYWxpemVyLgogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2RqYW5nby5qcwogICAgICBpbXBvcnQgQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBkZWZhdWx0U2VyaWFsaXplcjogJ2RqYW5nbycKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQGRlcHJlY2F0ZWQKICAgICAgQHByb3BlcnR5IGRlZmF1bHRTZXJpYWxpemVyCiAgICAgIEB0eXBlIHtTdHJpbmd9CiAgICAqLwogICAgZGVmYXVsdFNlcmlhbGl6ZXI6ICctZGVmYXVsdCcsCgogICAgLyoqCiAgICAgIFRoZSBgZmluZFJlY29yZCgpYCBtZXRob2QgaXMgaW52b2tlZCB3aGVuIHRoZSBzdG9yZSBpcyBhc2tlZCBmb3IgYSByZWNvcmQgdGhhdAogICAgICBoYXMgbm90IHByZXZpb3VzbHkgYmVlbiBsb2FkZWQuIEluIHJlc3BvbnNlIHRvIGBmaW5kUmVjb3JkKClgIGJlaW5nIGNhbGxlZCwgeW91CiAgICAgIHNob3VsZCBxdWVyeSB5b3VyIHBlcnNpc3RlbmNlIGxheWVyIGZvciBhIHJlY29yZCB3aXRoIHRoZSBnaXZlbiBJRC4gVGhlIGBmaW5kUmVjb3JkYAogICAgICBtZXRob2Qgc2hvdWxkIHJldHVybiBhIHByb21pc2UgdGhhdCB3aWxsIHJlc29sdmUgdG8gYSBKYXZhU2NyaXB0IG9iamVjdCB0aGF0IHdpbGwgYmUKICAgICAgbm9ybWFsaXplZCBieSB0aGUgc2VyaWFsaXplci4KICAgICAgIEhlcmUgaXMgYW4gZXhhbXBsZSBvZiB0aGUgYGZpbmRSZWNvcmRgIGltcGxlbWVudGF0aW9uOgogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICBpbXBvcnQgUlNWUCBmcm9tICdSU1ZQJzsKICAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBmaW5kUmVjb3JkKHN0b3JlLCB0eXBlLCBpZCwgc25hcHNob3QpIHsKICAgICAgICAgIHJldHVybiBuZXcgUlNWUC5Qcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgICAgICAkLmdldEpTT04oYC8ke3R5cGUubW9kZWxOYW1lfS8ke2lkfWApLnRoZW4oZnVuY3Rpb24oZGF0YSkgewogICAgICAgICAgICAgIHJlc29sdmUoZGF0YSk7CiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGpxWEhSKSB7CiAgICAgICAgICAgICAgcmVqZWN0KGpxWEhSKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZmluZFJlY29yZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBpZAogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgZmluZFJlY29yZDogbnVsbCwKCiAgICAvKioKICAgICAgVGhlIGBmaW5kQWxsKClgIG1ldGhvZCBpcyB1c2VkIHRvIHJldHJpZXZlIGFsbCByZWNvcmRzIGZvciBhIGdpdmVuIHR5cGUuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CiAgICAgIGltcG9ydCBSU1ZQIGZyb20gJ1JTVlAnOwogICAgICBpbXBvcnQgJCBmcm9tICdqcXVlcnknOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlci5leHRlbmQoewogICAgICAgIGZpbmRBbGwoc3RvcmUsIHR5cGUpIHsKICAgICAgICAgIHJldHVybiBuZXcgUlNWUC5Qcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgICAgICAkLmdldEpTT04oYC8ke3R5cGUubW9kZWxOYW1lfWApLnRoZW4oZnVuY3Rpb24oZGF0YSkgewogICAgICAgICAgICAgIHJlc29sdmUoZGF0YSk7CiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGpxWEhSKSB7CiAgICAgICAgICAgICAgcmVqZWN0KGpxWEhSKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZmluZEFsbAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlCiAgICAgIEBwYXJhbSB7dW5kZWZpbmVkfSBuZXZlclNldCBhIHZhbHVlIGlzIG5ldmVyIHByb3ZpZGVkIHRvIHRoaXMgYXJndW1lbnQKICAgICAgQHBhcmFtIHtTbmFwc2hvdFJlY29yZEFycmF5fSBzbmFwc2hvdFJlY29yZEFycmF5CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBmaW5kQWxsOiBudWxsLAoKICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgd2hlbiB5b3UgY2FsbCBgcXVlcnlgIG9uIHRoZSBzdG9yZS4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyJzsKICAgICAgaW1wb3J0IFJTVlAgZnJvbSAnUlNWUCc7CiAgICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgcXVlcnkoc3RvcmUsIHR5cGUsIHF1ZXJ5KSB7CiAgICAgICAgICByZXR1cm4gbmV3IFJTVlAuUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICAgICAgJC5nZXRKU09OKGAvJHt0eXBlLm1vZGVsTmFtZX1gLCBxdWVyeSkudGhlbihmdW5jdGlvbihkYXRhKSB7CiAgICAgICAgICAgICAgcmVzb2x2ZShkYXRhKTsKICAgICAgICAgICAgfSwgZnVuY3Rpb24oanFYSFIpIHsKICAgICAgICAgICAgICByZWplY3QoanFYSFIpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBxdWVyeQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBxdWVyeQogICAgICBAcGFyYW0ge0FkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheX0gcmVjb3JkQXJyYXkKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIHF1ZXJ5OiBudWxsLAoKICAgIC8qKgogICAgICBUaGUgYHF1ZXJ5UmVjb3JkKClgIG1ldGhvZCBpcyBpbnZva2VkIHdoZW4gdGhlIHN0b3JlIGlzIGFza2VkIGZvciBhIHNpbmdsZQogICAgICByZWNvcmQgdGhyb3VnaCBhIHF1ZXJ5IG9iamVjdC4KICAgICAgIEluIHJlc3BvbnNlIHRvIGBxdWVyeVJlY29yZCgpYCBiZWluZyBjYWxsZWQsIHlvdSBzaG91bGQgYWx3YXlzIGZldGNoIGZyZXNoCiAgICAgIGRhdGEuIE9uY2UgZm91bmQsIHlvdSBjYW4gYXN5bmNocm9ub3VzbHkgY2FsbCB0aGUgc3RvcmUncyBgcHVzaCgpYCBtZXRob2QKICAgICAgdG8gcHVzaCB0aGUgcmVjb3JkIGludG8gdGhlIHN0b3JlLgogICAgICAgSGVyZSBpcyBhbiBleGFtcGxlIGBxdWVyeVJlY29yZGAgaW1wbGVtZW50YXRpb246CiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IEFkYXB0ZXIsIHsgQnVpbGRVUkxNaXhpbiB9IGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICBpbXBvcnQgUlNWUCBmcm9tICdSU1ZQJzsKICAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKEJ1aWxkVVJMTWl4aW4sIHsKICAgICAgICBxdWVyeVJlY29yZChzdG9yZSwgdHlwZSwgcXVlcnkpIHsKICAgICAgICAgIHJldHVybiBuZXcgUlNWUC5Qcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgICAgICAkLmdldEpTT04oYC8ke3R5cGUubW9kZWxOYW1lfWAsIHF1ZXJ5KS50aGVuKGZ1bmN0aW9uKGRhdGEpIHsKICAgICAgICAgICAgICByZXNvbHZlKGRhdGEpOwogICAgICAgICAgICB9LCBmdW5jdGlvbihqcVhIUikgewogICAgICAgICAgICAgIHJlamVjdChqcVhIUik7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHF1ZXJ5UmVjb3JkCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7c3ViY2xhc3Mgb2YgTW9kZWx9IHR5cGUKICAgICAgQHBhcmFtIHtPYmplY3R9IHF1ZXJ5CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBxdWVyeVJlY29yZDogbnVsbCwKCiAgICAvKioKICAgICAgSWYgdGhlIGdsb2JhbGx5IHVuaXF1ZSBJRHMgZm9yIHlvdXIgcmVjb3JkcyBzaG91bGQgYmUgZ2VuZXJhdGVkIG9uIHRoZSBjbGllbnQsCiAgICAgIGltcGxlbWVudCB0aGUgYGdlbmVyYXRlSWRGb3JSZWNvcmQoKWAgbWV0aG9kLiBUaGlzIG1ldGhvZCB3aWxsIGJlIGludm9rZWQKICAgICAgZWFjaCB0aW1lIHlvdSBjcmVhdGUgYSBuZXcgcmVjb3JkLCBhbmQgdGhlIHZhbHVlIHJldHVybmVkIGZyb20gaXQgd2lsbCBiZQogICAgICBhc3NpZ25lZCB0byB0aGUgcmVjb3JkJ3MgYHByaW1hcnlLZXlgLgogICAgICAgTW9zdCB0cmFkaXRpb25hbCBSRVNULWxpa2UgSFRUUCBBUElzIHdpbGwgbm90IHVzZSB0aGlzIG1ldGhvZC4gSW5zdGVhZCwgdGhlIElECiAgICAgIG9mIHRoZSByZWNvcmQgd2lsbCBiZSBzZXQgYnkgdGhlIHNlcnZlciwgYW5kIHlvdXIgYWRhcHRlciB3aWxsIHVwZGF0ZSB0aGUgc3RvcmUKICAgICAgd2l0aCB0aGUgbmV3IElEIHdoZW4gaXQgY2FsbHMgYGRpZENyZWF0ZVJlY29yZCgpYC4gT25seSBpbXBsZW1lbnQgdGhpcyBtZXRob2QgaWYKICAgICAgeW91IGludGVuZCB0byBnZW5lcmF0ZSByZWNvcmQgSURzIG9uIHRoZSBjbGllbnQtc2lkZS4KICAgICAgIFRoZSBgZ2VuZXJhdGVJZEZvclJlY29yZCgpYCBtZXRob2Qgd2lsbCBiZSBpbnZva2VkIHdpdGggdGhlIHJlcXVlc3Rpbmcgc3RvcmUgYXMKICAgICAgdGhlIGZpcnN0IHBhcmFtZXRlciBhbmQgdGhlIG5ld2x5IGNyZWF0ZWQgcmVjb3JkIGFzIHRoZSBzZWNvbmQgcGFyYW1ldGVyOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyJzsKICAgICAgaW1wb3J0IHsgdjQgfSBmcm9tICd1dWlkJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBnZW5lcmF0ZUlkRm9yUmVjb3JkKHN0b3JlLCB0eXBlLCBpbnB1dFByb3BlcnRpZXMpIHsKICAgICAgICAgIHJldHVybiB2NCgpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBnZW5lcmF0ZUlkRm9yUmVjb3JkCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGUgICB0aGUgTW9kZWwgY2xhc3Mgb2YgdGhlIHJlY29yZAogICAgICBAcGFyYW0ge09iamVjdH0gaW5wdXRQcm9wZXJ0aWVzIGEgaGFzaCBvZiBwcm9wZXJ0aWVzIHRvIHNldCBvbiB0aGUKICAgICAgICBuZXdseSBjcmVhdGVkIHJlY29yZC4KICAgICAgQHJldHVybiB7KFN0cmluZ3xOdW1iZXIpfSBpZAogICAgKi8KICAgIGdlbmVyYXRlSWRGb3JSZWNvcmQ6IG51bGwsCgogICAgLyoqCiAgICAgIFByb3hpZXMgdG8gdGhlIHNlcmlhbGl6ZXIncyBgc2VyaWFsaXplYCBtZXRob2QuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgY3JlYXRlUmVjb3JkKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCkgewogICAgICAgICAgbGV0IGRhdGEgPSB0aGlzLnNlcmlhbGl6ZShzbmFwc2hvdCwgeyBpbmNsdWRlSWQ6IHRydWUgfSk7CiAgICAgICAgICBsZXQgdXJsID0gYC8ke3R5cGUubW9kZWxOYW1lfWA7CiAgICAgICAgICAgLy8gLi4uCiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZQogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcGFyYW0ge09iamVjdH0gICBvcHRpb25zCiAgICAgIEByZXR1cm4ge09iamVjdH0gc2VyaWFsaXplZCBzbmFwc2hvdAogICAgKi8KICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gc2VyaWFsaXplKHNuYXBzaG90LCBvcHRpb25zKSB7CiAgICAgIHJldHVybiBzbmFwc2hvdC5zZXJpYWxpemUob3B0aW9ucyk7CiAgICB9LAoKICAgIC8qKgogICAgICBJbXBsZW1lbnQgdGhpcyBtZXRob2QgaW4gYSBzdWJjbGFzcyB0byBoYW5kbGUgdGhlIGNyZWF0aW9uIG9mCiAgICAgIG5ldyByZWNvcmRzLgogICAgICAgU2VyaWFsaXplcyB0aGUgcmVjb3JkIGFuZCBzZW5kcyBpdCB0byB0aGUgc2VydmVyLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICBpbXBvcnQgeyBydW4gfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgICAgIGltcG9ydCBSU1ZQIGZyb20gJ1JTVlAnOwogICAgICBpbXBvcnQgJCBmcm9tICdqcXVlcnknOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlci5leHRlbmQoewogICAgICAgIGNyZWF0ZVJlY29yZChzdG9yZSwgdHlwZSwgc25hcHNob3QpIHsKICAgICAgICAgIGxldCBkYXRhID0gdGhpcy5zZXJpYWxpemUoc25hcHNob3QsIHsgaW5jbHVkZUlkOiB0cnVlIH0pOwogICAgICAgICAgIHJldHVybiBuZXcgUlNWUC5Qcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgICAgICAkLmFqYXgoewogICAgICAgICAgICAgIHR5cGU6ICdQT1NUJywKICAgICAgICAgICAgICB1cmw6IGAvJHt0eXBlLm1vZGVsTmFtZX1gLAogICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsCiAgICAgICAgICAgICAgZGF0YTogZGF0YQogICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uKGRhdGEpIHsKICAgICAgICAgICAgICBydW4obnVsbCwgcmVzb2x2ZSwgZGF0YSk7CiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGpxWEhSKSB7CiAgICAgICAgICAgICAganFYSFIudGhlbiA9IG51bGw7IC8vIHRhbWUgalF1ZXJ5J3MgaWxsIG1hbm5lcmVkIHByb21pc2VzCiAgICAgICAgICAgICAgcnVuKG51bGwsIHJlamVjdCwganFYSFIpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBjcmVhdGVSZWNvcmQKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZSAgIHRoZSBNb2RlbCBjbGFzcyBvZiB0aGUgcmVjb3JkCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBjcmVhdGVSZWNvcmQ6IG51bGwsCgogICAgLyoqCiAgICAgIEltcGxlbWVudCB0aGlzIG1ldGhvZCBpbiBhIHN1YmNsYXNzIHRvIGhhbmRsZSB0aGUgdXBkYXRpbmcgb2YKICAgICAgYSByZWNvcmQuCiAgICAgICBTZXJpYWxpemVzIHRoZSByZWNvcmQgdXBkYXRlIGFuZCBzZW5kcyBpdCB0byB0aGUgc2VydmVyLgogICAgICAgVGhlIHVwZGF0ZVJlY29yZCBtZXRob2QgaXMgZXhwZWN0ZWQgdG8gcmV0dXJuIGEgcHJvbWlzZSB0aGF0IHdpbGwKICAgICAgcmVzb2x2ZSB3aXRoIHRoZSBzZXJpYWxpemVkIHJlY29yZC4gVGhpcyBhbGxvd3MgdGhlIGJhY2tlbmQgdG8KICAgICAgaW5mb3JtIHRoZSBFbWJlciBEYXRhIHN0b3JlIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoaXMgcmVjb3JkIGFmdGVyCiAgICAgIHRoZSB1cGRhdGUuIElmIGl0IGlzIG5vdCBwb3NzaWJsZSB0byByZXR1cm4gYSBzZXJpYWxpemVkIHJlY29yZAogICAgICB0aGUgdXBkYXRlUmVjb3JkIHByb21pc2UgY2FuIGFsc28gcmVzb2x2ZSB3aXRoIGB1bmRlZmluZWRgIGFuZCB0aGUKICAgICAgRW1iZXIgRGF0YSBzdG9yZSB3aWxsIGFzc3VtZSBhbGwgb2YgdGhlIHVwZGF0ZXMgd2VyZSBzdWNjZXNzZnVsbHkKICAgICAgYXBwbGllZCBvbiB0aGUgYmFja2VuZC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyJzsKICAgICAgaW1wb3J0IHsgcnVuIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogICAgICBpbXBvcnQgUlNWUCBmcm9tICdSU1ZQJzsKICAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICB1cGRhdGVSZWNvcmQoc3RvcmUsIHR5cGUsIHNuYXBzaG90KSB7CiAgICAgICAgICBsZXQgZGF0YSA9IHRoaXMuc2VyaWFsaXplKHNuYXBzaG90LCB7IGluY2x1ZGVJZDogdHJ1ZSB9KTsKICAgICAgICAgIGxldCBpZCA9IHNuYXBzaG90LmlkOwogICAgICAgICAgIHJldHVybiBuZXcgUlNWUC5Qcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgICAgICAkLmFqYXgoewogICAgICAgICAgICAgIHR5cGU6ICdQVVQnLAogICAgICAgICAgICAgIHVybDogYC8ke3R5cGUubW9kZWxOYW1lfS8ke2lkfWAsCiAgICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJywKICAgICAgICAgICAgICBkYXRhOiBkYXRhCiAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24oZGF0YSkgewogICAgICAgICAgICAgIHJ1bihudWxsLCByZXNvbHZlLCBkYXRhKTsKICAgICAgICAgICAgfSwgZnVuY3Rpb24oanFYSFIpIHsKICAgICAgICAgICAgICBqcVhIUi50aGVuID0gbnVsbDsgLy8gdGFtZSBqUXVlcnkncyBpbGwgbWFubmVyZWQgcHJvbWlzZXMKICAgICAgICAgICAgICBydW4obnVsbCwgcmVqZWN0LCBqcVhIUik7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHVwZGF0ZVJlY29yZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlICAgdGhlIE1vZGVsIGNsYXNzIG9mIHRoZSByZWNvcmQKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIHVwZGF0ZVJlY29yZDogbnVsbCwKCiAgICAvKioKICAgICAgSW1wbGVtZW50IHRoaXMgbWV0aG9kIGluIGEgc3ViY2xhc3MgdG8gaGFuZGxlIHRoZSBkZWxldGlvbiBvZgogICAgICBhIHJlY29yZC4KICAgICAgIFNlbmRzIGEgZGVsZXRlIHJlcXVlc3QgZm9yIHRoZSByZWNvcmQgdG8gdGhlIHNlcnZlci4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyJzsKICAgICAgaW1wb3J0IHsgcnVuIH0gZnJvbSAnQGVtYmVyL3J1bmxvb3AnOwogICAgICBpbXBvcnQgUlNWUCBmcm9tICdSU1ZQJzsKICAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBkZWxldGVSZWNvcmQoc3RvcmUsIHR5cGUsIHNuYXBzaG90KSB7CiAgICAgICAgICBsZXQgZGF0YSA9IHRoaXMuc2VyaWFsaXplKHNuYXBzaG90LCB7IGluY2x1ZGVJZDogdHJ1ZSB9KTsKICAgICAgICAgIGxldCBpZCA9IHNuYXBzaG90LmlkOwogICAgICAgICAgIHJldHVybiBuZXcgUlNWUC5Qcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgICAgICAkLmFqYXgoewogICAgICAgICAgICAgIHR5cGU6ICdERUxFVEUnLAogICAgICAgICAgICAgIHVybDogYC8ke3R5cGUubW9kZWxOYW1lfS8ke2lkfWAsCiAgICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJywKICAgICAgICAgICAgICBkYXRhOiBkYXRhCiAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24oZGF0YSkgewogICAgICAgICAgICAgIHJ1bihudWxsLCByZXNvbHZlLCBkYXRhKTsKICAgICAgICAgICAgfSwgZnVuY3Rpb24oanFYSFIpIHsKICAgICAgICAgICAgICBqcVhIUi50aGVuID0gbnVsbDsgLy8gdGFtZSBqUXVlcnkncyBpbGwgbWFubmVyZWQgcHJvbWlzZXMKICAgICAgICAgICAgICBydW4obnVsbCwgcmVqZWN0LCBqcVhIUik7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGRlbGV0ZVJlY29yZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlICAgdGhlIE1vZGVsIGNsYXNzIG9mIHRoZSByZWNvcmQKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIGRlbGV0ZVJlY29yZDogbnVsbCwKCiAgICAvKioKICAgICAgQnkgZGVmYXVsdCB0aGUgc3RvcmUgd2lsbCB0cnkgdG8gY29hbGVzY2UgYWxsIGBmZXRjaFJlY29yZGAgY2FsbHMgd2l0aGluIHRoZSBzYW1lIHJ1bmxvb3AKICAgICAgaW50byBhcyBmZXcgcmVxdWVzdHMgYXMgcG9zc2libGUgYnkgY2FsbGluZyBncm91cFJlY29yZHNGb3JGaW5kTWFueSBhbmQgcGFzc2luZyBpdCBpbnRvIGEgZmluZE1hbnkgY2FsbC4KICAgICAgWW91IGNhbiBvcHQgb3V0IG9mIHRoaXMgYmVoYXZpb3VyIGJ5IGVpdGhlciBub3QgaW1wbGVtZW50aW5nIHRoZSBmaW5kTWFueSBob29rIG9yIGJ5IHNldHRpbmcKICAgICAgY29hbGVzY2VGaW5kUmVxdWVzdHMgdG8gZmFsc2UuCiAgICAgICBAcHJvcGVydHkgY29hbGVzY2VGaW5kUmVxdWVzdHMKICAgICAgQHR5cGUge2Jvb2xlYW59CiAgICAqLwogICAgY29hbGVzY2VGaW5kUmVxdWVzdHM6IHRydWUsCgogICAgLyoqCiAgICAgIFRoZSBzdG9yZSB3aWxsIGNhbGwgYGZpbmRNYW55YCBpbnN0ZWFkIG9mIG11bHRpcGxlIGBmaW5kUmVjb3JkYAogICAgICByZXF1ZXN0cyB0byBmaW5kIG11bHRpcGxlIHJlY29yZHMgYXQgb25jZSBpZiBjb2FsZXNjZUZpbmRSZXF1ZXN0cwogICAgICBpcyB0cnVlLgogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICBpbXBvcnQgeyBydW4gfSBmcm9tICdAZW1iZXIvcnVubG9vcCc7CiAgICAgIGltcG9ydCBSU1ZQIGZyb20gJ1JTVlAnOwogICAgICBpbXBvcnQgJCBmcm9tICdqcXVlcnknOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlci5leHRlbmQoewogICAgICAgIGZpbmRNYW55KHN0b3JlLCB0eXBlLCBpZHMsIHNuYXBzaG90cykgewogICAgICAgICAgcmV0dXJuIG5ldyBSU1ZQLlByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7CiAgICAgICAgICAgICQuYWpheCh7CiAgICAgICAgICAgICAgdHlwZTogJ0dFVCcsCiAgICAgICAgICAgICAgdXJsOiBgLyR7dHlwZS5tb2RlbE5hbWV9L2AsCiAgICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJywKICAgICAgICAgICAgICBkYXRhOiB7IGZpbHRlcjogeyBpZDogaWRzLmpvaW4oJywnKSB9IH0KICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbihkYXRhKSB7CiAgICAgICAgICAgICAgcnVuKG51bGwsIHJlc29sdmUsIGRhdGEpOwogICAgICAgICAgICB9LCBmdW5jdGlvbihqcVhIUikgewogICAgICAgICAgICAgIGpxWEhSLnRoZW4gPSBudWxsOyAvLyB0YW1lIGpRdWVyeSdzIGlsbCBtYW5uZXJlZCBwcm9taXNlcwogICAgICAgICAgICAgIHJ1bihudWxsLCByZWplY3QsIGpxWEhSKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZmluZE1hbnkKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZSAgIHRoZSBNb2RlbCBjbGFzcyBvZiB0aGUgcmVjb3JkcwogICAgICBAcGFyYW0ge0FycmF5fSAgICBpZHMKICAgICAgQHBhcmFtIHtBcnJheX0gc25hcHNob3RzCiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBmaW5kTWFueTogbnVsbCwKCiAgICAvKioKICAgICAgT3JnYW5pemUgcmVjb3JkcyBpbnRvIGdyb3VwcywgZWFjaCBvZiB3aGljaCBpcyB0byBiZSBwYXNzZWQgdG8gc2VwYXJhdGUKICAgICAgY2FsbHMgdG8gYGZpbmRNYW55YC4KICAgICAgIEZvciBleGFtcGxlLCBpZiB5b3VyIEFQSSBoYXMgbmVzdGVkIFVSTHMgdGhhdCBkZXBlbmQgb24gdGhlIHBhcmVudCwgeW91IHdpbGwKICAgICAgd2FudCB0byBncm91cCByZWNvcmRzIGJ5IHRoZWlyIHBhcmVudC4KICAgICAgIFRoZSBkZWZhdWx0IGltcGxlbWVudGF0aW9uIHJldHVybnMgdGhlIHJlY29yZHMgYXMgYSBzaW5nbGUgZ3JvdXAuCiAgICAgICBAbWV0aG9kIGdyb3VwUmVjb3Jkc0ZvckZpbmRNYW55CiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7QXJyYXl9IHNuYXBzaG90cwogICAgICBAcmV0dXJuIHtBcnJheX0gIGFuIGFycmF5IG9mIGFycmF5cyBvZiByZWNvcmRzLCBlYWNoIG9mIHdoaWNoIGlzIHRvIGJlCiAgICAgICAgICAgICAgICAgICAgICAgIGxvYWRlZCBzZXBhcmF0ZWx5IGJ5IGBmaW5kTWFueWAuCiAgICAqLwogICAgZ3JvdXBSZWNvcmRzRm9yRmluZE1hbnk6IGZ1bmN0aW9uIGdyb3VwUmVjb3Jkc0ZvckZpbmRNYW55KHN0b3JlLCBzbmFwc2hvdHMpIHsKICAgICAgcmV0dXJuIFtzbmFwc2hvdHNdOwogICAgfSwKCiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgdXNlZCBieSB0aGUgc3RvcmUgdG8gZGV0ZXJtaW5lIGlmIHRoZSBzdG9yZSBzaG91bGQKICAgICAgcmVsb2FkIGEgcmVjb3JkIGZyb20gdGhlIGFkYXB0ZXIgd2hlbiBhIHJlY29yZCBpcyByZXF1ZXN0ZWQgYnkKICAgICAgYHN0b3JlLmZpbmRSZWNvcmRgLgogICAgICAgSWYgdGhpcyBtZXRob2QgcmV0dXJucyBgdHJ1ZWAsIHRoZSBzdG9yZSB3aWxsIHJlLWZldGNoIGEgcmVjb3JkIGZyb20KICAgICAgdGhlIGFkYXB0ZXIuIElmIHRoaXMgbWV0aG9kIHJldHVybnMgYGZhbHNlYCwgdGhlIHN0b3JlIHdpbGwgcmVzb2x2ZQogICAgICBpbW1lZGlhdGVseSB1c2luZyB0aGUgY2FjaGVkIHJlY29yZC4KICAgICAgIEZvciBleGFtcGxlLCBpZiB5b3UgYXJlIGJ1aWxkaW5nIGFuIGV2ZW50cyB0aWNrZXRpbmcgc3lzdGVtLCBpbiB3aGljaCB1c2VycwogICAgICBjYW4gb25seSByZXNlcnZlIHRpY2tldHMgZm9yIDIwIG1pbnV0ZXMgYXQgYSB0aW1lLCBhbmQgd2FudCB0byBlbnN1cmUgdGhhdAogICAgICBpbiBlYWNoIHJvdXRlIHlvdSBoYXZlIGRhdGEgdGhhdCBpcyBubyBtb3JlIHRoYW4gMjAgbWludXRlcyBvbGQgeW91IGNvdWxkCiAgICAgIHdyaXRlOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBzaG91bGRSZWxvYWRSZWNvcmQoc3RvcmUsIHRpY2tldFNuYXBzaG90KSB7CiAgICAgICAgbGV0IGxhc3RBY2Nlc3NlZEF0ID0gdGlja2V0U25hcHNob3QuYXR0cignbGFzdEFjY2Vzc2VkQXQnKTsKICAgICAgICBsZXQgdGltZURpZmYgPSBtb21lbnQoKS5kaWZmKGxhc3RBY2Nlc3NlZEF0LCAnbWludXRlcycpOwogICAgICAgICBpZiAodGltZURpZmYgPiAyMCkgewogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBUaGlzIG1ldGhvZCB3b3VsZCBlbnN1cmUgdGhhdCB3aGVuZXZlciB5b3UgZG8gYHN0b3JlLmZpbmRSZWNvcmQoJ3RpY2tldCcsCiAgICAgIGlkKWAgeW91IHdpbGwgYWx3YXlzIGdldCBhIHRpY2tldCB0aGF0IGlzIG5vIG1vcmUgdGhhbiAyMCBtaW51dGVzIG9sZC4gSW4KICAgICAgY2FzZSB0aGUgY2FjaGVkIHZlcnNpb24gaXMgbW9yZSB0aGFuIDIwIG1pbnV0ZXMgb2xkLCBgZmluZFJlY29yZGAgd2lsbCBub3QKICAgICAgcmVzb2x2ZSB1bnRpbCB5b3UgZmV0Y2hlZCB0aGUgbGF0ZXN0IHZlcnNpb24uCiAgICAgICBCeSBkZWZhdWx0IHRoaXMgaG9vayByZXR1cm5zIGBmYWxzZWAsIGFzIG1vc3QgVUlzIHNob3VsZCBub3QgYmxvY2sgdXNlcgogICAgICBpbnRlcmFjdGlvbnMgd2hpbGUgd2FpdGluZyBvbiBkYXRhIHVwZGF0ZS4KICAgICAgIE5vdGUgdGhhdCwgd2l0aCBkZWZhdWx0IHNldHRpbmdzLCBgc2hvdWxkQmFja2dyb3VuZFJlbG9hZFJlY29yZGAgd2lsbCBhbHdheXMKICAgICAgcmUtZmV0Y2ggdGhlIHJlY29yZHMgaW4gdGhlIGJhY2tncm91bmQgZXZlbiBpZiBgc2hvdWxkUmVsb2FkUmVjb3JkYCByZXR1cm5zCiAgICAgIGBmYWxzZWAuIFlvdSBjYW4gb3ZlcnJpZGUgYHNob3VsZEJhY2tncm91bmRSZWxvYWRSZWNvcmRgIGlmIHRoaXMgZG9lcyBub3QKICAgICAgc3VpdCB5b3VyIHVzZSBjYXNlLgogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIHNob3VsZFJlbG9hZFJlY29yZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcmV0dXJuIHtCb29sZWFufQogICAgKi8KICAgIHNob3VsZFJlbG9hZFJlY29yZDogZnVuY3Rpb24gc2hvdWxkUmVsb2FkUmVjb3JkKHN0b3JlLCBzbmFwc2hvdCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9LAoKICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBpcyB1c2VkIGJ5IHRoZSBzdG9yZSB0byBkZXRlcm1pbmUgaWYgdGhlIHN0b3JlIHNob3VsZAogICAgICByZWxvYWQgYWxsIHJlY29yZHMgZnJvbSB0aGUgYWRhcHRlciB3aGVuIHJlY29yZHMgYXJlIHJlcXVlc3RlZCBieQogICAgICBgc3RvcmUuZmluZEFsbGAuCiAgICAgICBJZiB0aGlzIG1ldGhvZCByZXR1cm5zIGB0cnVlYCwgdGhlIHN0b3JlIHdpbGwgcmUtZmV0Y2ggYWxsIHJlY29yZHMgZnJvbQogICAgICB0aGUgYWRhcHRlci4gSWYgdGhpcyBtZXRob2QgcmV0dXJucyBgZmFsc2VgLCB0aGUgc3RvcmUgd2lsbCByZXNvbHZlCiAgICAgIGltbWVkaWF0ZWx5IHVzaW5nIHRoZSBjYWNoZWQgcmVjb3Jkcy4KICAgICAgIEZvciBleGFtcGxlLCBpZiB5b3UgYXJlIGJ1aWxkaW5nIGFuIGV2ZW50cyB0aWNrZXRpbmcgc3lzdGVtLCBpbiB3aGljaCB1c2VycwogICAgICBjYW4gb25seSByZXNlcnZlIHRpY2tldHMgZm9yIDIwIG1pbnV0ZXMgYXQgYSB0aW1lLCBhbmQgd2FudCB0byBlbnN1cmUgdGhhdAogICAgICBpbiBlYWNoIHJvdXRlIHlvdSBoYXZlIGRhdGEgdGhhdCBpcyBubyBtb3JlIHRoYW4gMjAgbWludXRlcyBvbGQgeW91IGNvdWxkCiAgICAgIHdyaXRlOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBzaG91bGRSZWxvYWRBbGwoc3RvcmUsIHNuYXBzaG90QXJyYXkpIHsKICAgICAgICBsZXQgc25hcHNob3RzID0gc25hcHNob3RBcnJheS5zbmFwc2hvdHMoKTsKICAgICAgICAgcmV0dXJuIHNuYXBzaG90cy5hbnkoKHRpY2tldFNuYXBzaG90KSA9PiB7CiAgICAgICAgICBsZXQgbGFzdEFjY2Vzc2VkQXQgPSB0aWNrZXRTbmFwc2hvdC5hdHRyKCdsYXN0QWNjZXNzZWRBdCcpOwogICAgICAgICAgbGV0IHRpbWVEaWZmID0gbW9tZW50KCkuZGlmZihsYXN0QWNjZXNzZWRBdCwgJ21pbnV0ZXMnKTsKICAgICAgICAgICBpZiAodGltZURpZmYgPiAyMCkgewogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQogICAgICBgYGAKICAgICAgIFRoaXMgbWV0aG9kIHdvdWxkIGVuc3VyZSB0aGF0IHdoZW5ldmVyIHlvdSBkbyBgc3RvcmUuZmluZEFsbCgndGlja2V0JylgIHlvdQogICAgICB3aWxsIGFsd2F5cyBnZXQgYSBsaXN0IG9mIHRpY2tldHMgdGhhdCBhcmUgbm8gbW9yZSB0aGFuIDIwIG1pbnV0ZXMgb2xkLiBJbgogICAgICBjYXNlIGEgY2FjaGVkIHZlcnNpb24gaXMgbW9yZSB0aGFuIDIwIG1pbnV0ZXMgb2xkLCBgZmluZEFsbGAgd2lsbCBub3QKICAgICAgcmVzb2x2ZSB1bnRpbCB5b3UgZmV0Y2hlZCB0aGUgbGF0ZXN0IHZlcnNpb25zLgogICAgICAgQnkgZGVmYXVsdCwgdGhpcyBtZXRob2QgcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHBhc3NlZCBgc25hcHNob3RSZWNvcmRBcnJheWAKICAgICAgaXMgZW1wdHkgKG1lYW5pbmcgdGhhdCB0aGVyZSBhcmUgbm8gcmVjb3JkcyBsb2NhbGx5IGF2YWlsYWJsZSB5ZXQpLAogICAgICBvdGhlcndpc2UsIGl0IHJldHVybnMgYGZhbHNlYC4KICAgICAgIE5vdGUgdGhhdCwgd2l0aCBkZWZhdWx0IHNldHRpbmdzLCBgc2hvdWxkQmFja2dyb3VuZFJlbG9hZEFsbGAgd2lsbCBhbHdheXMKICAgICAgcmUtZmV0Y2ggYWxsIHRoZSByZWNvcmRzIGluIHRoZSBiYWNrZ3JvdW5kIGV2ZW4gaWYgYHNob3VsZFJlbG9hZEFsbGAgcmV0dXJucwogICAgICBgZmFsc2VgLiBZb3UgY2FuIG92ZXJyaWRlIGBzaG91bGRCYWNrZ3JvdW5kUmVsb2FkQWxsYCBpZiB0aGlzIGRvZXMgbm90IHN1aXQKICAgICAgeW91ciB1c2UgY2FzZS4KICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBzaG91bGRSZWxvYWRBbGwKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtTbmFwc2hvdFJlY29yZEFycmF5fSBzbmFwc2hvdFJlY29yZEFycmF5CiAgICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICAqLwogICAgc2hvdWxkUmVsb2FkQWxsOiBmdW5jdGlvbiBzaG91bGRSZWxvYWRBbGwoc3RvcmUsIHNuYXBzaG90UmVjb3JkQXJyYXkpIHsKICAgICAgcmV0dXJuICFzbmFwc2hvdFJlY29yZEFycmF5Lmxlbmd0aDsKICAgIH0sCgogICAgLyoqCiAgICAgIFRoaXMgbWV0aG9kIGlzIHVzZWQgYnkgdGhlIHN0b3JlIHRvIGRldGVybWluZSBpZiB0aGUgc3RvcmUgc2hvdWxkCiAgICAgIHJlbG9hZCBhIHJlY29yZCBhZnRlciB0aGUgYHN0b3JlLmZpbmRSZWNvcmRgIG1ldGhvZCByZXNvbHZlcyBhCiAgICAgIGNhY2hlZCByZWNvcmQuCiAgICAgICBUaGlzIG1ldGhvZCBpcyAqb25seSogY2hlY2tlZCBieSB0aGUgc3RvcmUgd2hlbiB0aGUgc3RvcmUgaXMKICAgICAgcmV0dXJuaW5nIGEgY2FjaGVkIHJlY29yZC4KICAgICAgIElmIHRoaXMgbWV0aG9kIHJldHVybnMgYHRydWVgIHRoZSBzdG9yZSB3aWxsIHJlLWZldGNoIGEgcmVjb3JkIGZyb20KICAgICAgdGhlIGFkYXB0ZXIuCiAgICAgICBGb3IgZXhhbXBsZSwgaWYgeW91IGRvIG5vdCB3YW50IHRvIGZldGNoIGNvbXBsZXggZGF0YSBvdmVyIGEgbW9iaWxlCiAgICAgIGNvbm5lY3Rpb24sIG9yIGlmIHRoZSBuZXR3b3JrIGlzIGRvd24sIHlvdSBjYW4gaW1wbGVtZW50CiAgICAgIGBzaG91bGRCYWNrZ3JvdW5kUmVsb2FkUmVjb3JkYCBhcyBmb2xsb3dzOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBzaG91bGRCYWNrZ3JvdW5kUmVsb2FkUmVjb3JkKHN0b3JlLCBzbmFwc2hvdCkgewogICAgICAgIGxldCB7IGRvd25saW5rLCBlZmZlY3RpdmVUeXBlIH0gPSBuYXZpZ2F0b3IuY29ubmVjdGlvbjsKICAgICAgICAgcmV0dXJuIGRvd25saW5rID4gMCAmJiBlZmZlY3RpdmVUeXBlID09PSAnNGcnOwogICAgICB9CiAgICAgIGBgYAogICAgICAgQnkgZGVmYXVsdCwgdGhpcyBob29rIHJldHVybnMgYHRydWVgIHNvIHRoZSBkYXRhIGZvciB0aGUgcmVjb3JkIGlzIHVwZGF0ZWQKICAgICAgaW4gdGhlIGJhY2tncm91bmQuCiAgICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgc2hvdWxkQmFja2dyb3VuZFJlbG9hZFJlY29yZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcmV0dXJuIHtCb29sZWFufQogICAgKi8KICAgIHNob3VsZEJhY2tncm91bmRSZWxvYWRSZWNvcmQ6IGZ1bmN0aW9uIHNob3VsZEJhY2tncm91bmRSZWxvYWRSZWNvcmQoc3RvcmUsIHNuYXBzaG90KSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSwKCiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgdXNlZCBieSB0aGUgc3RvcmUgdG8gZGV0ZXJtaW5lIGlmIHRoZSBzdG9yZSBzaG91bGQKICAgICAgcmVsb2FkIGEgcmVjb3JkIGFycmF5IGFmdGVyIHRoZSBgc3RvcmUuZmluZEFsbGAgbWV0aG9kIHJlc29sdmVzCiAgICAgIHdpdGggYSBjYWNoZWQgcmVjb3JkIGFycmF5LgogICAgICAgVGhpcyBtZXRob2QgaXMgKm9ubHkqIGNoZWNrZWQgYnkgdGhlIHN0b3JlIHdoZW4gdGhlIHN0b3JlIGlzCiAgICAgIHJldHVybmluZyBhIGNhY2hlZCByZWNvcmQgYXJyYXkuCiAgICAgICBJZiB0aGlzIG1ldGhvZCByZXR1cm5zIGB0cnVlYCB0aGUgc3RvcmUgd2lsbCByZS1mZXRjaCBhbGwgcmVjb3JkcwogICAgICBmcm9tIHRoZSBhZGFwdGVyLgogICAgICAgRm9yIGV4YW1wbGUsIGlmIHlvdSBkbyBub3Qgd2FudCB0byBmZXRjaCBjb21wbGV4IGRhdGEgb3ZlciBhIG1vYmlsZQogICAgICBjb25uZWN0aW9uLCBvciBpZiB0aGUgbmV0d29yayBpcyBkb3duLCB5b3UgY2FuIGltcGxlbWVudAogICAgICBgc2hvdWxkQmFja2dyb3VuZFJlbG9hZEFsbGAgYXMgZm9sbG93czoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc2hvdWxkQmFja2dyb3VuZFJlbG9hZEFsbChzdG9yZSwgc25hcHNob3RBcnJheSkgewogICAgICAgIGxldCB7IGRvd25saW5rLCBlZmZlY3RpdmVUeXBlIH0gPSBuYXZpZ2F0b3IuY29ubmVjdGlvbjsKICAgICAgICAgcmV0dXJuIGRvd25saW5rID4gMCAmJiBlZmZlY3RpdmVUeXBlID09PSAnNGcnOwogICAgICB9CiAgICAgIGBgYAogICAgICAgQnkgZGVmYXVsdCB0aGlzIG1ldGhvZCByZXR1cm5zIGB0cnVlYCwgaW5kaWNhdGluZyB0aGF0IGEgYmFja2dyb3VuZCByZWxvYWQKICAgICAgc2hvdWxkIGFsd2F5cyBiZSB0cmlnZ2VyZWQuCiAgICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgc2hvdWxkQmFja2dyb3VuZFJlbG9hZEFsbAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge1NuYXBzaG90UmVjb3JkQXJyYXl9IHNuYXBzaG90UmVjb3JkQXJyYXkKICAgICAgQHJldHVybiB7Qm9vbGVhbn0KICAgICovCiAgICBzaG91bGRCYWNrZ3JvdW5kUmVsb2FkQWxsOiBmdW5jdGlvbiBzaG91bGRCYWNrZ3JvdW5kUmVsb2FkQWxsKHN0b3JlLCBzbmFwc2hvdFJlY29yZEFycmF5KSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogIH0pOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwo7ZGVmaW5lKCJAZW1iZXItZGF0YS9hZGFwdGVyL2pzb24tYXBpIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCIsICJlbWJlci1pbmZsZWN0b3IiLCAiQGVtYmVyLWRhdGEvYWRhcHRlci8tcHJpdmF0ZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9yZXN0LCBfZW1iZXJJbmZsZWN0b3IsIF9wcml2YXRlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgIFRoZSBgSlNPTkFQSUFkYXB0ZXJgIGlzIHRoZSBkZWZhdWx0IGFkYXB0ZXIgdXNlZCBieSBFbWJlciBEYXRhLiBJdAogICAgaXMgcmVzcG9uc2libGUgZm9yIHRyYW5zZm9ybWluZyB0aGUgc3RvcmUncyByZXF1ZXN0cyBpbnRvIEhUVFAKICAgIHJlcXVlc3RzIHRoYXQgZm9sbG93IHRoZSBbSlNPTiBBUEldKGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvKQogICAgZm9ybWF0LgogIAogICAgIyMgSlNPTiBBUEkgQ29udmVudGlvbnMKICAKICAgIFRoZSBKU09OQVBJQWRhcHRlciB1c2VzIEpTT04gQVBJIGNvbnZlbnRpb25zIGZvciBidWlsZGluZyB0aGUgVVJMCiAgICBmb3IgYSByZWNvcmQgYW5kIHNlbGVjdGluZyB0aGUgSFRUUCB2ZXJiIHRvIHVzZSB3aXRoIGEgcmVxdWVzdC4gVGhlCiAgICBhY3Rpb25zIHlvdSBjYW4gdGFrZSBvbiBhIHJlY29yZCBtYXAgb250byB0aGUgZm9sbG93aW5nIFVSTHMgaW4gdGhlCiAgICBKU09OIEFQSSBhZGFwdGVyOgogIAogIDx0YWJsZT4KICAgIDx0cj4KICAgICAgPHRoPgogICAgICAgIEFjdGlvbgogICAgICA8L3RoPgogICAgICA8dGg+CiAgICAgICAgSFRUUCBWZXJiCiAgICAgIDwvdGg+CiAgICAgIDx0aD4KICAgICAgICBVUkwKICAgICAgPC90aD4KICAgIDwvdHI+CiAgICA8dHI+CiAgICAgIDx0aD4KICAgICAgICBgc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIDEyMylgCiAgICAgIDwvdGg+CiAgICAgIDx0ZD4KICAgICAgICBHRVQKICAgICAgPC90ZD4KICAgICAgPHRkPgogICAgICAgIC9wb3N0cy8xMjMKICAgICAgPC90ZD4KICAgIDwvdHI+CiAgICA8dHI+CiAgICAgIDx0aD4KICAgICAgICBgc3RvcmUuZmluZEFsbCgncG9zdCcpYAogICAgICA8L3RoPgogICAgICA8dGQ+CiAgICAgICAgR0VUCiAgICAgIDwvdGQ+CiAgICAgIDx0ZD4KICAgICAgICAvcG9zdHMKICAgICAgPC90ZD4KICAgIDwvdHI+CiAgICA8dHI+CiAgICAgIDx0aD4KICAgICAgICBVcGRhdGUgYHBvc3RSZWNvcmQuc2F2ZSgpYAogICAgICA8L3RoPgogICAgICA8dGQ+CiAgICAgICAgUEFUQ0gKICAgICAgPC90ZD4KICAgICAgPHRkPgogICAgICAgIC9wb3N0cy8xMjMKICAgICAgPC90ZD4KICAgIDwvdHI+CiAgICA8dHI+CiAgICAgIDx0aD4KICAgICAgICBDcmVhdGUgYHN0b3JlLmNyZWF0ZVJlY29yZCgncG9zdCcpLnNhdmUoKWAKICAgICAgPC90aD4KICAgICAgPHRkPgogICAgICAgIFBPU1QKICAgICAgPC90ZD4KICAgICAgPHRkPgogICAgICAgIC9wb3N0cwogICAgICA8L3RkPgogICAgPC90cj4KICAgIDx0cj4KICAgICAgPHRoPgogICAgICAgIERlbGV0ZSBgcG9zdFJlY29yZC5kZXN0cm95UmVjb3JkKClgCiAgICAgIDwvdGg+CiAgICAgIDx0ZD4KICAgICAgICBERUxFVEUKICAgICAgPC90ZD4KICAgICAgPHRkPgogICAgICAgIC9wb3N0cy8xMjMKICAgICAgPC90ZD4KICAgIDwvdHI+CiAgPC90YWJsZT4KICAKICAgICMjIFN1Y2Nlc3MgYW5kIGZhaWx1cmUKICAKICAgIFRoZSBKU09OQVBJQWRhcHRlciB3aWxsIGNvbnNpZGVyIGEgc3VjY2VzcyBhbnkgcmVzcG9uc2Ugd2l0aCBhCiAgICBzdGF0dXMgY29kZSBvZiB0aGUgMnh4IGZhbWlseSAoIlN1Y2Nlc3MiKSwgYXMgd2VsbCBhcyAzMDQgKCJOb3QKICAgIE1vZGlmaWVkIikuIEFueSBvdGhlciBzdGF0dXMgY29kZSB3aWxsIGJlIGNvbnNpZGVyZWQgYSBmYWlsdXJlLgogIAogICAgT24gc3VjY2VzcywgdGhlIHJlcXVlc3QgcHJvbWlzZSB3aWxsIGJlIHJlc29sdmVkIHdpdGggdGhlIGZ1bGwKICAgIHJlc3BvbnNlIHBheWxvYWQuCiAgCiAgICBGYWlsZWQgcmVzcG9uc2VzIHdpdGggc3RhdHVzIGNvZGUgNDIyICgiVW5wcm9jZXNzYWJsZSBFbnRpdHkiKSB3aWxsCiAgICBiZSBjb25zaWRlcmVkICJpbnZhbGlkIi4gVGhlIHJlc3BvbnNlIHdpbGwgYmUgZGlzY2FyZGVkLCBleGNlcHQgZm9yCiAgICB0aGUgYGVycm9yc2Aga2V5LiBUaGUgcmVxdWVzdCBwcm9taXNlIHdpbGwgYmUgcmVqZWN0ZWQgd2l0aCBhCiAgICBgSW52YWxpZEVycm9yYC4gVGhpcyBlcnJvciBvYmplY3Qgd2lsbCBlbmNhcHN1bGF0ZSB0aGUgc2F2ZWQKICAgIGBlcnJvcnNgIHZhbHVlLgogIAogICAgQW55IG90aGVyIHN0YXR1cyBjb2RlcyB3aWxsIGJlIHRyZWF0ZWQgYXMgYW4gYWRhcHRlciBlcnJvci4gVGhlCiAgICByZXF1ZXN0IHByb21pc2Ugd2lsbCBiZSByZWplY3RlZCwgc2ltaWxhcmx5IHRvIHRoZSBpbnZhbGlkIGNhc2UsCiAgICBidXQgd2l0aCBhbiBpbnN0YW5jZSBvZiBgQWRhcHRlckVycm9yYCBpbnN0ZWFkLgogIAogICAgIyMjIEVuZHBvaW50IHBhdGggY3VzdG9taXphdGlvbgogIAogICAgRW5kcG9pbnQgcGF0aHMgY2FuIGJlIHByZWZpeGVkIHdpdGggYSBgbmFtZXNwYWNlYCBieSBzZXR0aW5nIHRoZQogICAgbmFtZXNwYWNlIHByb3BlcnR5IG9uIHRoZSBhZGFwdGVyOgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgSlNPTkFQSUFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9qc29uLWFwaSc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBKU09OQVBJQWRhcHRlci5leHRlbmQoewogICAgICBuYW1lc3BhY2U6ICdhcGkvMScKICAgIH0pOwogICAgYGBgCiAgICBSZXF1ZXN0cyBmb3IgdGhlIGBwZXJzb25gIG1vZGVsIHdvdWxkIG5vdyB0YXJnZXQgYC9hcGkvMS9wZW9wbGUvMWAuCiAgCiAgICAjIyMgSG9zdCBjdXN0b21pemF0aW9uCiAgCiAgICBBbiBhZGFwdGVyIGNhbiB0YXJnZXQgb3RoZXIgaG9zdHMgYnkgc2V0dGluZyB0aGUgYGhvc3RgIHByb3BlcnR5LgogIAogICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgSlNPTkFQSUFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9qc29uLWFwaSc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBKU09OQVBJQWRhcHRlci5leHRlbmQoewogICAgICBob3N0OiAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nCiAgICB9KTsKICAgIGBgYAogIAogICAgUmVxdWVzdHMgZm9yIHRoZSBgcGVyc29uYCBtb2RlbCB3b3VsZCBub3cgdGFyZ2V0CiAgICBgaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20vcGVvcGxlLzFgLgogIAogICAgQHNpbmNlIDEuMTMuMAogICAgQGNsYXNzIEpTT05BUElBZGFwdGVyCiAgICBAY29uc3RydWN0b3IKICAgIEBleHRlbmRzIFJFU1RBZGFwdGVyCiAgKi8KICB2YXIgSlNPTkFQSUFkYXB0ZXIgPSBfcmVzdC5kZWZhdWx0LmV4dGVuZCh7CiAgICBkZWZhdWx0U2VyaWFsaXplcjogJy1qc29uLWFwaScsCiAgICBfZGVmYXVsdENvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vdm5kLmFwaStqc29uJywKCiAgICAvKioKICAgICAgQG1ldGhvZCBhamF4T3B0aW9ucwogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gdXJsCiAgICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlIFRoZSByZXF1ZXN0IHR5cGUgR0VULCBQT1NULCBQVVQsIERFTEVURSBldGMuCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICovCiAgICBhamF4T3B0aW9uczogZnVuY3Rpb24gYWpheE9wdGlvbnModXJsLCB0eXBlLCBvcHRpb25zKSB7CiAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsKICAgICAgICBvcHRpb25zID0ge307CiAgICAgIH0KCiAgICAgIHZhciBoYXNoID0gdGhpcy5fc3VwZXIodXJsLCB0eXBlLCBvcHRpb25zKTsKCiAgICAgIGhhc2guaGVhZGVyc1snQWNjZXB0J10gPSBoYXNoLmhlYWRlcnNbJ0FjY2VwdCddIHx8ICdhcHBsaWNhdGlvbi92bmQuYXBpK2pzb24nOwogICAgICByZXR1cm4gaGFzaDsKICAgIH0sCgogICAgLyoqCiAgICAgIEJ5IGRlZmF1bHQgdGhlIEpTT05BUElBZGFwdGVyIHdpbGwgc2VuZCBlYWNoIGZpbmQgcmVxdWVzdCBjb21pbmcgZnJvbSBhIGBzdG9yZS5maW5kYAogICAgICBvciBmcm9tIGFjY2Vzc2luZyBhIHJlbGF0aW9uc2hpcCBzZXBhcmF0ZWx5IHRvIHRoZSBzZXJ2ZXIuIElmIHlvdXIgc2VydmVyIHN1cHBvcnRzIHBhc3NpbmcKICAgICAgaWRzIGFzIGEgcXVlcnkgc3RyaW5nLCB5b3UgY2FuIHNldCBjb2FsZXNjZUZpbmRSZXF1ZXN0cyB0byB0cnVlIHRvIGNvYWxlc2NlIGFsbCBmaW5kIHJlcXVlc3RzCiAgICAgIHdpdGhpbiBhIHNpbmdsZSBydW5sb29wLgogICAgICAgRm9yIGV4YW1wbGUsIGlmIHlvdSBoYXZlIGFuIGluaXRpYWwgcGF5bG9hZCBvZjoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIGlkOiAxLAogICAgICAgICAgdHlwZTogJ3Bvc3QnLAogICAgICAgICAgcmVsYXRpb25zaGlwOiB7CiAgICAgICAgICAgIGNvbW1lbnRzOiB7CiAgICAgICAgICAgICAgZGF0YTogWwogICAgICAgICAgICAgICAgeyBpZDogMSwgdHlwZTogJ2NvbW1lbnQnIH0sCiAgICAgICAgICAgICAgICB7IGlkOiAyLCB0eXBlOiAnY29tbWVudCcgfQogICAgICAgICAgICAgIF0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBgYGAKICAgICAgIEJ5IGRlZmF1bHQgY2FsbGluZyBgcG9zdC5nZXQoJ2NvbW1lbnRzJylgIHdpbGwgdHJpZ2dlciB0aGUgZm9sbG93aW5nIHJlcXVlc3RzKGFzc3VtaW5nIHRoZQogICAgICBjb21tZW50cyBoYXZlbid0IGJlZW4gbG9hZGVkIGJlZm9yZSk6CiAgICAgICBgYGAKICAgICAgR0VUIC9jb21tZW50cy8xCiAgICAgIEdFVCAvY29tbWVudHMvMgogICAgICBgYGAKICAgICAgIElmIHlvdSBzZXQgY29hbGVzY2VGaW5kUmVxdWVzdHMgdG8gYHRydWVgIGl0IHdpbGwgaW5zdGVhZCB0cmlnZ2VyIHRoZSBmb2xsb3dpbmcgcmVxdWVzdDoKICAgICAgIGBgYAogICAgICBHRVQgL2NvbW1lbnRzP2ZpbHRlcltpZF09MSwyCiAgICAgIGBgYAogICAgICAgU2V0dGluZyBjb2FsZXNjZUZpbmRSZXF1ZXN0cyB0byBgdHJ1ZWAgYWxzbyB3b3JrcyBmb3IgYHN0b3JlLmZpbmRgIHJlcXVlc3RzIGFuZCBgYmVsb25nc1RvYAogICAgICByZWxhdGlvbnNoaXBzIGFjY2Vzc2VkIHdpdGhpbiB0aGUgc2FtZSBydW5sb29wLiBJZiB5b3Ugc2V0IGBjb2FsZXNjZUZpbmRSZXF1ZXN0czogdHJ1ZWAKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc3RvcmUuZmluZFJlY29yZCgnY29tbWVudCcsIDEpOwogICAgICBzdG9yZS5maW5kUmVjb3JkKCdjb21tZW50JywgMik7CiAgICAgIGBgYAogICAgICAgd2lsbCBhbHNvIHNlbmQgYSByZXF1ZXN0IHRvOiBgR0VUIC9jb21tZW50cz9maWx0ZXJbaWRdPTEsMmAKICAgICAgIE5vdGU6IFJlcXVlc3RzIGNvYWxlc2NpbmcgcmVseSBvbiBVUkwgYnVpbGRpbmcgc3RyYXRlZ3kuIFNvIGlmIHlvdSBvdmVycmlkZSBgYnVpbGRVUkxgIGluIHlvdXIgYXBwCiAgICAgIGBncm91cFJlY29yZHNGb3JGaW5kTWFueWAgbW9yZSBsaWtlbHkgc2hvdWxkIGJlIG92ZXJyaWRkZW4gYXMgd2VsbCBpbiBvcmRlciBmb3IgY29hbGVzY2luZyB0byB3b3JrLgogICAgICAgQHByb3BlcnR5IGNvYWxlc2NlRmluZFJlcXVlc3RzCiAgICAgIEB0eXBlIHtib29sZWFufQogICAgKi8KICAgIGNvYWxlc2NlRmluZFJlcXVlc3RzOiBmYWxzZSwKICAgIGZpbmRNYW55OiBmdW5jdGlvbiBmaW5kTWFueShzdG9yZSwgdHlwZSwgaWRzLCBzbmFwc2hvdHMpIHsKICAgICAgdmFyIHVybCA9IHRoaXMuYnVpbGRVUkwodHlwZS5tb2RlbE5hbWUsIGlkcywgc25hcHNob3RzLCAnZmluZE1hbnknKTsKICAgICAgcmV0dXJuIHRoaXMuYWpheCh1cmwsICdHRVQnLCB7CiAgICAgICAgZGF0YTogewogICAgICAgICAgZmlsdGVyOiB7CiAgICAgICAgICAgIGlkOiBpZHMuam9pbignLCcpCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgIH0sCiAgICBwYXRoRm9yVHlwZTogZnVuY3Rpb24gcGF0aEZvclR5cGUobW9kZWxOYW1lKSB7CiAgICAgIHZhciBkYXNoZXJpemVkID0gRW1iZXIuU3RyaW5nLmRhc2hlcml6ZShtb2RlbE5hbWUpOwogICAgICByZXR1cm4gKDAsIF9lbWJlckluZmxlY3Rvci5wbHVyYWxpemUpKGRhc2hlcml6ZWQpOwogICAgfSwKICAgIHVwZGF0ZVJlY29yZDogZnVuY3Rpb24gdXBkYXRlUmVjb3JkKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCkgewogICAgICB2YXIgZGF0YSA9ICgwLCBfcHJpdmF0ZS5zZXJpYWxpemVJbnRvSGFzaCkoc3RvcmUsIHR5cGUsIHNuYXBzaG90KTsKICAgICAgdmFyIHVybCA9IHRoaXMuYnVpbGRVUkwodHlwZS5tb2RlbE5hbWUsIHNuYXBzaG90LmlkLCBzbmFwc2hvdCwgJ3VwZGF0ZVJlY29yZCcpOwogICAgICByZXR1cm4gdGhpcy5hamF4KHVybCwgJ1BBVENIJywgewogICAgICAgIGRhdGE6IGRhdGEKICAgICAgfSk7CiAgICB9CiAgfSk7CgogIHZhciBfZGVmYXVsdCA9IEpTT05BUElBZGFwdGVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CjtkZWZpbmUoIkBlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9hZGFwdGVyIiwgIkBlbWJlci1kYXRhL2FkYXB0ZXIvLXByaXZhdGUiLCAiQGVtYmVyLWRhdGEvYWRhcHRlci9lcnJvciJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9hZGFwdGVyLCBfcHJpdmF0ZSwgX2Vycm9yKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5mZXRjaE9wdGlvbnMgPSBmZXRjaE9wdGlvbnM7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKICB2YXIgUHJvbWlzZSA9IEVtYmVyLlJTVlAuUHJvbWlzZTsKICB2YXIgaGFzSlF1ZXJ5ID0gdHlwZW9mIGpRdWVyeSAhPT0gJ3VuZGVmaW5lZCc7CiAgdmFyIGhhc05hamF4ID0gdHlwZW9mIG5hamF4ICE9PSAndW5kZWZpbmVkJzsKICAvKioKICAgIFRoZSBSRVNUIGFkYXB0ZXIgYWxsb3dzIHlvdXIgc3RvcmUgdG8gY29tbXVuaWNhdGUgd2l0aCBhbiBIVFRQIHNlcnZlciBieQogICAgdHJhbnNtaXR0aW5nIEpTT04gdmlhIFhIUi4gTW9zdCBFbWJlci5qcyBhcHBzIHRoYXQgY29uc3VtZSBhIEpTT04gQVBJCiAgICBzaG91bGQgdXNlIHRoZSBSRVNUIGFkYXB0ZXIuCiAgCiAgICBUaGlzIGFkYXB0ZXIgaXMgZGVzaWduZWQgYXJvdW5kIHRoZSBpZGVhIHRoYXQgdGhlIEpTT04gZXhjaGFuZ2VkIHdpdGgKICAgIHRoZSBzZXJ2ZXIgc2hvdWxkIGJlIGNvbnZlbnRpb25hbC4KICAKICAgICMjIFN1Y2Nlc3MgYW5kIGZhaWx1cmUKICAKICAgIFRoZSBSRVNUIGFkYXB0ZXIgd2lsbCBjb25zaWRlciBhIHN1Y2Nlc3MgYW55IHJlc3BvbnNlIHdpdGggYSBzdGF0dXMgY29kZQogICAgb2YgdGhlIDJ4eCBmYW1pbHkgKCJTdWNjZXNzIiksIGFzIHdlbGwgYXMgMzA0ICgiTm90IE1vZGlmaWVkIikuIEFueSBvdGhlcgogICAgc3RhdHVzIGNvZGUgd2lsbCBiZSBjb25zaWRlcmVkIGEgZmFpbHVyZS4KICAKICAgIE9uIHN1Y2Nlc3MsIHRoZSByZXF1ZXN0IHByb21pc2Ugd2lsbCBiZSByZXNvbHZlZCB3aXRoIHRoZSBmdWxsIHJlc3BvbnNlCiAgICBwYXlsb2FkLgogIAogICAgRmFpbGVkIHJlc3BvbnNlcyB3aXRoIHN0YXR1cyBjb2RlIDQyMiAoIlVucHJvY2Vzc2FibGUgRW50aXR5Iikgd2lsbCBiZQogICAgY29uc2lkZXJlZCAiaW52YWxpZCIuIFRoZSByZXNwb25zZSB3aWxsIGJlIGRpc2NhcmRlZCwgZXhjZXB0IGZvciB0aGUKICAgIGBlcnJvcnNgIGtleS4gVGhlIHJlcXVlc3QgcHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkIHdpdGggYSBgSW52YWxpZEVycm9yYC4KICAgIFRoaXMgZXJyb3Igb2JqZWN0IHdpbGwgZW5jYXBzdWxhdGUgdGhlIHNhdmVkIGBlcnJvcnNgIHZhbHVlLgogIAogICAgQW55IG90aGVyIHN0YXR1cyBjb2RlcyB3aWxsIGJlIHRyZWF0ZWQgYXMgYW4gImFkYXB0ZXIgZXJyb3IiLiBUaGUgcmVxdWVzdAogICAgcHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkLCBzaW1pbGFybHkgdG8gdGhlICJpbnZhbGlkIiBjYXNlLCBidXQgd2l0aAogICAgYW4gaW5zdGFuY2Ugb2YgYEFkYXB0ZXJFcnJvcmAgaW5zdGVhZC4KICAKICAgICMjIEpTT04gU3RydWN0dXJlCiAgCiAgICBUaGUgUkVTVCBhZGFwdGVyIGV4cGVjdHMgdGhlIEpTT04gcmV0dXJuZWQgZnJvbSB5b3VyIHNlcnZlciB0byBmb2xsb3cKICAgIHRoZXNlIGNvbnZlbnRpb25zLgogIAogICAgIyMjIE9iamVjdCBSb290CiAgCiAgICBUaGUgSlNPTiBwYXlsb2FkIHNob3VsZCBiZSBhbiBvYmplY3QgdGhhdCBjb250YWlucyB0aGUgcmVjb3JkIGluc2lkZSBhCiAgICByb290IHByb3BlcnR5LiBGb3IgZXhhbXBsZSwgaW4gcmVzcG9uc2UgdG8gYSBgR0VUYCByZXF1ZXN0IGZvcgogICAgYC9wb3N0cy8xYCwgdGhlIEpTT04gc2hvdWxkIGxvb2sgbGlrZSB0aGlzOgogIAogICAgYGBganMKICAgIHsKICAgICAgInBvc3RzIjogewogICAgICAgICJpZCI6IDEsCiAgICAgICAgInRpdGxlIjogIkknbSBSdW5uaW5nIHRvIFJlZm9ybSB0aGUgVzNDJ3MgVGFnIiwKICAgICAgICAiYXV0aG9yIjogIlllaHVkYSBLYXR6IgogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIFNpbWlsYXJseSwgaW4gcmVzcG9uc2UgdG8gYSBgR0VUYCByZXF1ZXN0IGZvciBgL3Bvc3RzYCwgdGhlIEpTT04gc2hvdWxkCiAgICBsb29rIGxpa2UgdGhpczoKICAKICAgIGBgYGpzCiAgICB7CiAgICAgICJwb3N0cyI6IFsKICAgICAgICB7CiAgICAgICAgICAiaWQiOiAxLAogICAgICAgICAgInRpdGxlIjogIkknbSBSdW5uaW5nIHRvIFJlZm9ybSB0aGUgVzNDJ3MgVGFnIiwKICAgICAgICAgICJhdXRob3IiOiAiWWVodWRhIEthdHoiCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAiaWQiOiAyLAogICAgICAgICAgInRpdGxlIjogIlJhaWxzIGlzIG9tYWthc2UiLAogICAgICAgICAgImF1dGhvciI6ICJEMkgiCiAgICAgICAgfQogICAgICBdCiAgICB9CiAgICBgYGAKICAKICAgIE5vdGUgdGhhdCB0aGUgb2JqZWN0IHJvb3QgY2FuIGJlIHBsdXJhbGl6ZWQgZm9yIGJvdGggYSBzaW5nbGUtb2JqZWN0IHJlc3BvbnNlCiAgICBhbmQgYW4gYXJyYXkgcmVzcG9uc2U6IHRoZSBSRVNUIGFkYXB0ZXIgaXMgbm90IHN0cmljdCBvbiB0aGlzLiBGdXJ0aGVyLCBpZiB0aGUKICAgIEhUVFAgc2VydmVyIHJlc3BvbmRzIHRvIGEgYEdFVGAgcmVxdWVzdCB0byBgL3Bvc3RzLzFgIChlLmcuIHRoZSByZXNwb25zZSB0byBhCiAgICBgZmluZFJlY29yZGAgcXVlcnkpIHdpdGggbW9yZSB0aGFuIG9uZSBvYmplY3QgaW4gdGhlIGFycmF5LCBFbWJlciBEYXRhIHdpbGwKICAgIG9ubHkgZGlzcGxheSB0aGUgb2JqZWN0IHdpdGggdGhlIG1hdGNoaW5nIElELgogIAogICAgIyMjIENvbnZlbnRpb25hbCBOYW1lcwogIAogICAgQXR0cmlidXRlIG5hbWVzIGluIHlvdXIgSlNPTiBwYXlsb2FkIHNob3VsZCBiZSB0aGUgY2FtZWxDYXNlZCB2ZXJzaW9ucyBvZgogICAgdGhlIGF0dHJpYnV0ZXMgaW4geW91ciBFbWJlci5qcyBtb2RlbHMuCiAgCiAgICBGb3IgZXhhbXBsZSwgaWYgeW91IGhhdmUgYSBgUGVyc29uYCBtb2RlbDoKICAKICAgIGBgYGFwcC9tb2RlbHMvcGVyc29uLmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIGZpcnN0TmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgIGxhc3ROYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgb2NjdXBhdGlvbjogYXR0cignc3RyaW5nJykKICAgIH0pOwogICAgYGBgCiAgCiAgICBUaGUgSlNPTiByZXR1cm5lZCBzaG91bGQgbG9vayBsaWtlIHRoaXM6CiAgCiAgICBgYGBqcwogICAgewogICAgICAicGVvcGxlIjogewogICAgICAgICJpZCI6IDUsCiAgICAgICAgImZpcnN0TmFtZSI6ICJaYXBob2QiLAogICAgICAgICJsYXN0TmFtZSI6ICJCZWVibGVicm94IiwKICAgICAgICAib2NjdXBhdGlvbiI6ICJQcmVzaWRlbnQiCiAgICAgIH0KICAgIH0KICAgIGBgYAogIAogICAgIyMjIyBSZWxhdGlvbnNoaXBzCiAgCiAgICBSZWxhdGlvbnNoaXBzIGFyZSB1c3VhbGx5IHJlcHJlc2VudGVkIGJ5IGlkcyB0byB0aGUgcmVjb3JkIGluIHRoZQogICAgcmVsYXRpb25zaGlwLiBUaGUgcmVsYXRlZCByZWNvcmRzIGNhbiB0aGVuIGJlIHNpZGVsb2FkZWQgaW4gdGhlCiAgICByZXNwb25zZSB1bmRlciBhIGtleSBmb3IgdGhlIHR5cGUuCiAgCiAgICBgYGBqcwogICAgewogICAgICAicG9zdHMiOiB7CiAgICAgICAgImlkIjogNSwKICAgICAgICAidGl0bGUiOiAiSSdtIFJ1bm5pbmcgdG8gUmVmb3JtIHRoZSBXM0MncyBUYWciLAogICAgICAgICJhdXRob3IiOiAiWWVodWRhIEthdHoiLAogICAgICAgICJjb21tZW50cyI6IFsxLCAyXQogICAgICB9LAogICAgICAiY29tbWVudHMiOiBbewogICAgICAgICJpZCI6IDEsCiAgICAgICAgImF1dGhvciI6ICJVc2VyIDEiLAogICAgICAgICJtZXNzYWdlIjogIkZpcnN0ISIsCiAgICAgIH0sIHsKICAgICAgICAiaWQiOiAyLAogICAgICAgICJhdXRob3IiOiAiVXNlciAyIiwKICAgICAgICAibWVzc2FnZSI6ICJHb29kIEx1Y2shIiwKICAgICAgfV0KICAgIH0KICAgIGBgYAogIAogICAgSWYgdGhlIHJlY29yZHMgaW4gdGhlIHJlbGF0aW9uc2hpcCBhcmUgbm90IGtub3duIHdoZW4gdGhlIHJlc3BvbnNlCiAgICBpcyBzZXJpYWxpemVkIGl0J3MgYWxzbyBwb3NzaWJsZSB0byByZXByZXNlbnQgdGhlIHJlbGF0aW9uc2hpcCBhcyBhCiAgICBVUkwgdXNpbmcgdGhlIGBsaW5rc2Aga2V5IGluIHRoZSByZXNwb25zZS4gRW1iZXIgRGF0YSB3aWxsIGZldGNoCiAgICB0aGlzIFVSTCB0byByZXNvbHZlIHRoZSByZWxhdGlvbnNoaXAgd2hlbiBpdCBpcyBhY2Nlc3NlZCBmb3IgdGhlCiAgICBmaXJzdCB0aW1lLgogIAogICAgYGBganMKICAgIHsKICAgICAgInBvc3RzIjogewogICAgICAgICJpZCI6IDUsCiAgICAgICAgInRpdGxlIjogIkknbSBSdW5uaW5nIHRvIFJlZm9ybSB0aGUgVzNDJ3MgVGFnIiwKICAgICAgICAiYXV0aG9yIjogIlllaHVkYSBLYXR6IiwKICAgICAgICAibGlua3MiOiB7CiAgICAgICAgICAiY29tbWVudHMiOiAiL3Bvc3RzLzUvY29tbWVudHMiCiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgICMjIyBFcnJvcnMKICAKICAgIElmIGEgcmVzcG9uc2UgaXMgY29uc2lkZXJlZCBhIGZhaWx1cmUsIHRoZSBKU09OIHBheWxvYWQgaXMgZXhwZWN0ZWQgdG8gaW5jbHVkZQogICAgYSB0b3AtbGV2ZWwga2V5IGBlcnJvcnNgLCBkZXRhaWxpbmcgYW55IHNwZWNpZmljIGlzc3Vlcy4gRm9yIGV4YW1wbGU6CiAgCiAgICBgYGBqcwogICAgewogICAgICAiZXJyb3JzIjogewogICAgICAgICJtc2ciOiAiU29tZXRoaW5nIHdlbnQgd3JvbmciCiAgICAgIH0KICAgIH0KICAgIGBgYAogIAogICAgVGhpcyBhZGFwdGVyIGRvZXMgbm90IG1ha2UgYW55IGFzc3VtcHRpb25zIGFzIHRvIHRoZSBmb3JtYXQgb2YgdGhlIGBlcnJvcnNgCiAgICBvYmplY3QuIEl0IHdpbGwgc2ltcGx5IGJlIHBhc3NlZCBhbG9uZyBhcyBpcywgd3JhcHBlZCBpbiBhbiBpbnN0YW5jZQogICAgb2YgYEludmFsaWRFcnJvcmAgb3IgYEFkYXB0ZXJFcnJvcmAuIFRoZSBzZXJpYWxpemVyIGNhbiBpbnRlcnByZXQgaXQKICAgIGFmdGVyd2FyZHMuCiAgCiAgICAjIyBDdXN0b21pemF0aW9uCiAgCiAgICAjIyMgRW5kcG9pbnQgcGF0aCBjdXN0b21pemF0aW9uCiAgCiAgICBFbmRwb2ludCBwYXRocyBjYW4gYmUgcHJlZml4ZWQgd2l0aCBhIGBuYW1lc3BhY2VgIGJ5IHNldHRpbmcgdGhlIG5hbWVzcGFjZQogICAgcHJvcGVydHkgb24gdGhlIGFkYXB0ZXI6CiAgCiAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgbmFtZXNwYWNlOiAnYXBpLzEnCiAgICB9KTsKICAgIGBgYAogICAgUmVxdWVzdHMgZm9yIHRoZSBgUGVyc29uYCBtb2RlbCB3b3VsZCBub3cgdGFyZ2V0IGAvYXBpLzEvcGVvcGxlLzFgLgogIAogICAgIyMjIEhvc3QgY3VzdG9taXphdGlvbgogIAogICAgQW4gYWRhcHRlciBjYW4gdGFyZ2V0IG90aGVyIGhvc3RzIGJ5IHNldHRpbmcgdGhlIGBob3N0YCBwcm9wZXJ0eS4KICAKICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgaW1wb3J0IFJFU1RBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCc7CiAgCiAgICBleHBvcnQgZGVmYXVsdCBSRVNUQWRhcHRlci5leHRlbmQoewogICAgICBob3N0OiAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nCiAgICB9KTsKICAgIGBgYAogIAogICAgIyMjIEhlYWRlcnMgY3VzdG9taXphdGlvbgogIAogICAgU29tZSBBUElzIHJlcXVpcmUgSFRUUCBoZWFkZXJzLCBlLmcuIHRvIHByb3ZpZGUgYW4gQVBJIGtleS4gQXJiaXRyYXJ5CiAgICBoZWFkZXJzIGNhbiBiZSBzZXQgYXMga2V5L3ZhbHVlIHBhaXJzIG9uIHRoZSBgUkVTVEFkYXB0ZXJgJ3MgYGhlYWRlcnNgCiAgICBvYmplY3QgYW5kIEVtYmVyIERhdGEgd2lsbCBzZW5kIHRoZW0gYWxvbmcgd2l0aCBlYWNoIGFqYXggcmVxdWVzdC4KICAKICAKICAgIGBgYGFwcC9hZGFwdGVycy9hcHBsaWNhdGlvbi5qcwogICAgaW1wb3J0IFJFU1RBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCc7CiAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgaGVhZGVyczogY29tcHV0ZWQoZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICdBUElfS0VZJzogJ3NlY3JldCBrZXknLAogICAgICAgICAgJ0FOT1RIRVJfSEVBREVSJzogJ1NvbWUgaGVhZGVyIHZhbHVlJwogICAgICAgIH07CiAgICAgIH0KICAgIH0pOwogICAgYGBgCiAgCiAgICBgaGVhZGVyc2AgY2FuIGFsc28gYmUgdXNlZCBhcyBhIGNvbXB1dGVkIHByb3BlcnR5IHRvIHN1cHBvcnQgZHluYW1pYwogICAgaGVhZGVycy4gSW4gdGhlIGV4YW1wbGUgYmVsb3csIHRoZSBgc2Vzc2lvbmAgb2JqZWN0IGhhcyBiZWVuCiAgICBpbmplY3RlZCBpbnRvIGFuIGFkYXB0ZXIgYnkgRW1iZXIncyBjb250YWluZXIuCiAgCiAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgaW1wb3J0IHsgY29tcHV0ZWQgfSBmcm9tICdAZW1iZXIvb2JqZWN0JzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RBZGFwdGVyLmV4dGVuZCh7CiAgICAgIGhlYWRlcnM6IGNvbXB1dGVkKCdzZXNzaW9uLmF1dGhUb2tlbicsIGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiB7CiAgICAgICAgICAnQVBJX0tFWSc6IHRoaXMuZ2V0KCdzZXNzaW9uLmF1dGhUb2tlbicpLAogICAgICAgICAgJ0FOT1RIRVJfSEVBREVSJzogJ1NvbWUgaGVhZGVyIHZhbHVlJwogICAgICAgIH07CiAgICAgIH0pCiAgICB9KTsKICAgIGBgYAogIAogICAgSW4gc29tZSBjYXNlcywgeW91ciBkeW5hbWljIGhlYWRlcnMgbWF5IHJlcXVpcmUgZGF0YSBmcm9tIHNvbWUKICAgIG9iamVjdCBvdXRzaWRlIG9mIEVtYmVyJ3Mgb2JzZXJ2ZXIgc3lzdGVtIChmb3IgZXhhbXBsZQogICAgYGRvY3VtZW50LmNvb2tpZWApLiBZb3UgY2FuIHVzZSB0aGUKICAgIFt2b2xhdGlsZV0oL2FwaS9jbGFzc2VzL0VtYmVyLkNvbXB1dGVkUHJvcGVydHkuaHRtbD9hbmNob3I9dm9sYXRpbGUpCiAgICBmdW5jdGlvbiB0byBzZXQgdGhlIHByb3BlcnR5IGludG8gYSBub24tY2FjaGVkIG1vZGUgY2F1c2luZyB0aGUgaGVhZGVycyB0bwogICAgYmUgcmVjb21wdXRlZCB3aXRoIGV2ZXJ5IHJlcXVlc3QuCiAgCiAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgaW1wb3J0IHsgZ2V0IH0gZnJvbSAnQGVtYmVyL29iamVjdCc7CiAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgaGVhZGVyczogY29tcHV0ZWQoZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICdBUElfS0VZJzogZ2V0KGRvY3VtZW50LmNvb2tpZS5tYXRjaCgvYXBpS2V5XD0oW147XSopLyksICcxJyksCiAgICAgICAgICAnQU5PVEhFUl9IRUFERVInOiAnU29tZSBoZWFkZXIgdmFsdWUnCiAgICAgICAgfTsKICAgICAgfSkudm9sYXRpbGUoKQogICAgfSk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBSRVNUQWRhcHRlcgogICAgQGNvbnN0cnVjdG9yCiAgICBAZXh0ZW5kcyBBZGFwdGVyCiAgICBAdXNlcyBCdWlsZFVSTE1peGluCiAgKi8KCiAgdmFyIFJFU1RBZGFwdGVyID0gX2FkYXB0ZXIuZGVmYXVsdC5leHRlbmQoX2FkYXB0ZXIuQnVpbGRVUkxNaXhpbiwgewogICAgZGVmYXVsdFNlcmlhbGl6ZXI6ICctcmVzdCcsCiAgICBfZGVmYXVsdENvbnRlbnRUeXBlOiAnYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOCcsCiAgICBmYXN0Ym9vdDogRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gRW1iZXIuZ2V0T3duZXIodGhpcykubG9va3VwKCdzZXJ2aWNlOmZhc3Rib290Jyk7CiAgICB9KSwKICAgIHVzZUZldGNoOiBFbWJlci5jb21wdXRlZChmdW5jdGlvbiAoKSB7CiAgICAgIHZhciBFTlYgPSBFbWJlci5nZXRPd25lcih0aGlzKS5yZXNvbHZlUmVnaXN0cmF0aW9uKCdjb25maWc6ZW52aXJvbm1lbnQnKTsgLy8gVE9ETzogaHR0cHM6Ly9naXRodWIuY29tL2VtYmVyanMvZGF0YS9pc3N1ZXMvNjA5MwoKICAgICAgdmFyIGpRdWVyeUludGVncmF0aW9uRGlzYWJsZWQgPSBFTlYgJiYgRU5WLkVtYmVyRU5WICYmIEVOVi5FbWJlckVOVi5fSlFVRVJZX0lOVEVHUkFUSU9OID09PSBmYWxzZTsKCiAgICAgIGlmIChqUXVlcnlJbnRlZ3JhdGlvbkRpc2FibGVkKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0gZWxzZSBpZiAoaGFzTmFqYXggfHwgaGFzSlF1ZXJ5KSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICB9KSwKCiAgICAvKioKICAgICAgQnkgZGVmYXVsdCwgdGhlIFJFU1RBZGFwdGVyIHdpbGwgc2VuZCB0aGUgcXVlcnkgcGFyYW1zIHNvcnRlZCBhbHBoYWJldGljYWxseSB0byB0aGUKICAgICAgc2VydmVyLgogICAgICAgRm9yIGV4YW1wbGU6CiAgICAgICBgYGBqcwogICAgICBzdG9yZS5xdWVyeSgncG9zdHMnLCB7IHNvcnQ6ICdwcmljZScsIGNhdGVnb3J5OiAncGV0cycgfSk7CiAgICAgIGBgYAogICAgICAgd2lsbCBnZW5lcmF0ZSBhIHJlcXVlc3RzIGxpa2UgdGhpcyBgL3Bvc3RzP2NhdGVnb3J5PXBldHMmc29ydD1wcmljZWAsIGV2ZW4gaWYgdGhlCiAgICAgIHBhcmFtZXRlcnMgd2VyZSBzcGVjaWZpZWQgaW4gYSBkaWZmZXJlbnQgb3JkZXIuCiAgICAgICBUaGF0IHdheSB0aGUgZ2VuZXJhdGVkIFVSTCB3aWxsIGJlIGRldGVybWluaXN0aWMgYW5kIHRoYXQgc2ltcGxpZmllcyBjYWNoaW5nIG1lY2hhbmlzbXMKICAgICAgaW4gdGhlIGJhY2tlbmQuCiAgICAgICBTZXR0aW5nIGBzb3J0UXVlcnlQYXJhbXNgIHRvIGEgZmFsc2V5IHZhbHVlIHdpbGwgcmVzcGVjdCB0aGUgb3JpZ2luYWwgb3JkZXIuCiAgICAgICBJbiBjYXNlIHlvdSB3YW50IHRvIHNvcnQgdGhlIHF1ZXJ5IHBhcmFtZXRlcnMgd2l0aCBhIGRpZmZlcmVudCBjcml0ZXJpYSwgc2V0CiAgICAgIGBzb3J0UXVlcnlQYXJhbXNgIHRvIHlvdXIgY3VzdG9tIHNvcnQgZnVuY3Rpb24uCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJFU1RBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSRVNUQWRhcHRlci5leHRlbmQoewogICAgICAgIHNvcnRRdWVyeVBhcmFtcyhwYXJhbXMpIHsKICAgICAgICAgIGxldCBzb3J0ZWRLZXlzID0gT2JqZWN0LmtleXMocGFyYW1zKS5zb3J0KCkucmV2ZXJzZSgpOwogICAgICAgICAgbGV0IGxlbiA9IHNvcnRlZEtleXMubGVuZ3RoLCBuZXdQYXJhbXMgPSB7fTsKICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgICAgICAgIG5ld1BhcmFtc1tzb3J0ZWRLZXlzW2ldXSA9IHBhcmFtc1tzb3J0ZWRLZXlzW2ldXTsKICAgICAgICAgIH0KICAgICAgICAgICByZXR1cm4gbmV3UGFyYW1zOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzb3J0UXVlcnlQYXJhbXMKICAgICAgQHBhcmFtIHtPYmplY3R9IG9iagogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgc29ydFF1ZXJ5UGFyYW1zOiBmdW5jdGlvbiBzb3J0UXVlcnlQYXJhbXMob2JqKSB7CiAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqKTsKICAgICAgdmFyIGxlbiA9IGtleXMubGVuZ3RoOwoKICAgICAgaWYgKGxlbiA8IDIpIHsKICAgICAgICByZXR1cm4gb2JqOwogICAgICB9CgogICAgICB2YXIgbmV3UXVlcnlQYXJhbXMgPSB7fTsKICAgICAgdmFyIHNvcnRlZEtleXMgPSBrZXlzLnNvcnQoKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgICBuZXdRdWVyeVBhcmFtc1tzb3J0ZWRLZXlzW2ldXSA9IG9ialtzb3J0ZWRLZXlzW2ldXTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5ld1F1ZXJ5UGFyYW1zOwogICAgfSwKCiAgICAvKioKICAgICAgQnkgZGVmYXVsdCB0aGUgUkVTVEFkYXB0ZXIgd2lsbCBzZW5kIGVhY2ggZmluZCByZXF1ZXN0IGNvbWluZyBmcm9tIGEgYHN0b3JlLmZpbmRgCiAgICAgIG9yIGZyb20gYWNjZXNzaW5nIGEgcmVsYXRpb25zaGlwIHNlcGFyYXRlbHkgdG8gdGhlIHNlcnZlci4gSWYgeW91ciBzZXJ2ZXIgc3VwcG9ydHMgcGFzc2luZwogICAgICBpZHMgYXMgYSBxdWVyeSBzdHJpbmcsIHlvdSBjYW4gc2V0IGNvYWxlc2NlRmluZFJlcXVlc3RzIHRvIHRydWUgdG8gY29hbGVzY2UgYWxsIGZpbmQgcmVxdWVzdHMKICAgICAgd2l0aGluIGEgc2luZ2xlIHJ1bmxvb3AuCiAgICAgICBGb3IgZXhhbXBsZSwgaWYgeW91IGhhdmUgYW4gaW5pdGlhbCBwYXlsb2FkIG9mOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICB7CiAgICAgICAgcG9zdDogewogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICBjb21tZW50czogWzEsIDJdCiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgQnkgZGVmYXVsdCBjYWxsaW5nIGBwb3N0LmdldCgnY29tbWVudHMnKWAgd2lsbCB0cmlnZ2VyIHRoZSBmb2xsb3dpbmcgcmVxdWVzdHMoYXNzdW1pbmcgdGhlCiAgICAgIGNvbW1lbnRzIGhhdmVuJ3QgYmVlbiBsb2FkZWQgYmVmb3JlKToKICAgICAgIGBgYAogICAgICBHRVQgL2NvbW1lbnRzLzEKICAgICAgR0VUIC9jb21tZW50cy8yCiAgICAgIGBgYAogICAgICAgSWYgeW91IHNldCBjb2FsZXNjZUZpbmRSZXF1ZXN0cyB0byBgdHJ1ZWAgaXQgd2lsbCBpbnN0ZWFkIHRyaWdnZXIgdGhlIGZvbGxvd2luZyByZXF1ZXN0OgogICAgICAgYGBgCiAgICAgIEdFVCAvY29tbWVudHM/aWRzW109MSZpZHNbXT0yCiAgICAgIGBgYAogICAgICAgU2V0dGluZyBjb2FsZXNjZUZpbmRSZXF1ZXN0cyB0byBgdHJ1ZWAgYWxzbyB3b3JrcyBmb3IgYHN0b3JlLmZpbmRgIHJlcXVlc3RzIGFuZCBgYmVsb25nc1RvYAogICAgICByZWxhdGlvbnNoaXBzIGFjY2Vzc2VkIHdpdGhpbiB0aGUgc2FtZSBydW5sb29wLiBJZiB5b3Ugc2V0IGBjb2FsZXNjZUZpbmRSZXF1ZXN0czogdHJ1ZWAKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc3RvcmUuZmluZFJlY29yZCgnY29tbWVudCcsIDEpOwogICAgICBzdG9yZS5maW5kUmVjb3JkKCdjb21tZW50JywgMik7CiAgICAgIGBgYAogICAgICAgd2lsbCBhbHNvIHNlbmQgYSByZXF1ZXN0IHRvOiBgR0VUIC9jb21tZW50cz9pZHNbXT0xJmlkc1tdPTJgCiAgICAgICBOb3RlOiBSZXF1ZXN0cyBjb2FsZXNjaW5nIHJlbHkgb24gVVJMIGJ1aWxkaW5nIHN0cmF0ZWd5LiBTbyBpZiB5b3Ugb3ZlcnJpZGUgYGJ1aWxkVVJMYCBpbiB5b3VyIGFwcAogICAgICBgZ3JvdXBSZWNvcmRzRm9yRmluZE1hbnlgIG1vcmUgbGlrZWx5IHNob3VsZCBiZSBvdmVycmlkZGVuIGFzIHdlbGwgaW4gb3JkZXIgZm9yIGNvYWxlc2NpbmcgdG8gd29yay4KICAgICAgIEBwcm9wZXJ0eSBjb2FsZXNjZUZpbmRSZXF1ZXN0cwogICAgICBAdHlwZSB7Ym9vbGVhbn0KICAgICovCiAgICBjb2FsZXNjZUZpbmRSZXF1ZXN0czogZmFsc2UsCgogICAgLyoqCiAgICAgIEVuZHBvaW50IHBhdGhzIGNhbiBiZSBwcmVmaXhlZCB3aXRoIGEgYG5hbWVzcGFjZWAgYnkgc2V0dGluZyB0aGUgbmFtZXNwYWNlCiAgICAgIHByb3BlcnR5IG9uIHRoZSBhZGFwdGVyOgogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBuYW1lc3BhY2U6ICdhcGkvMScKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgUmVxdWVzdHMgZm9yIHRoZSBgUG9zdGAgbW9kZWwgd291bGQgbm93IHRhcmdldCBgL2FwaS8xL3Bvc3QvYC4KICAgICAgIEBwcm9wZXJ0eSBuYW1lc3BhY2UKICAgICAgQHR5cGUge1N0cmluZ30KICAgICovCgogICAgLyoqCiAgICAgIEFuIGFkYXB0ZXIgY2FuIHRhcmdldCBvdGhlciBob3N0cyBieSBzZXR0aW5nIHRoZSBgaG9zdGAgcHJvcGVydHkuCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJFU1RBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSRVNUQWRhcHRlci5leHRlbmQoewogICAgICAgIGhvc3Q6ICdodHRwczovL2FwaS5leGFtcGxlLmNvbScKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgUmVxdWVzdHMgZm9yIHRoZSBgUG9zdGAgbW9kZWwgd291bGQgbm93IHRhcmdldCBgaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20vcG9zdC9gLgogICAgICAgQHByb3BlcnR5IGhvc3QKICAgICAgQHR5cGUge1N0cmluZ30KICAgICovCgogICAgLyoqCiAgICAgIFNvbWUgQVBJcyByZXF1aXJlIEhUVFAgaGVhZGVycywgZS5nLiB0byBwcm92aWRlIGFuIEFQSQogICAgICBrZXkuIEFyYml0cmFyeSBoZWFkZXJzIGNhbiBiZSBzZXQgYXMga2V5L3ZhbHVlIHBhaXJzIG9uIHRoZQogICAgICBgUkVTVEFkYXB0ZXJgJ3MgYGhlYWRlcnNgIG9iamVjdCBhbmQgRW1iZXIgRGF0YSB3aWxsIHNlbmQgdGhlbQogICAgICBhbG9uZyB3aXRoIGVhY2ggYWpheCByZXF1ZXN0LiBGb3IgZHluYW1pYyBoZWFkZXJzIHNlZSBbaGVhZGVycwogICAgICBjdXN0b21pemF0aW9uXSgvZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvUkVTVEFkYXB0ZXIpLgogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBSRVNUQWRhcHRlciBmcm9tICdAZW1iZXItZGF0YS9hZGFwdGVyL3Jlc3QnOwogICAgICBpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBoZWFkZXJzOiBjb21wdXRlZChmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICdBUElfS0VZJzogJ3NlY3JldCBrZXknLAogICAgICAgICAgICAnQU5PVEhFUl9IRUFERVInOiAnU29tZSBoZWFkZXIgdmFsdWUnCiAgICAgICAgICB9OwogICAgICAgIH0pCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBoZWFkZXJzCiAgICAgIEB0eXBlIHtPYmplY3R9CiAgICAgKi8KCiAgICAvKioKICAgICAgQ2FsbGVkIGJ5IHRoZSBzdG9yZSBpbiBvcmRlciB0byBmZXRjaCB0aGUgSlNPTiBmb3IgYSBnaXZlbgogICAgICB0eXBlIGFuZCBJRC4KICAgICAgIFRoZSBgZmluZFJlY29yZGAgbWV0aG9kIG1ha2VzIGFuIEFqYXggcmVxdWVzdCB0byBhIFVSTCBjb21wdXRlZCBieQogICAgICBgYnVpbGRVUkxgLCBhbmQgcmV0dXJucyBhIHByb21pc2UgZm9yIHRoZSByZXN1bHRpbmcgcGF5bG9hZC4KICAgICAgIFRoaXMgbWV0aG9kIHBlcmZvcm1zIGFuIEhUVFAgYEdFVGAgcmVxdWVzdCB3aXRoIHRoZSBpZCBwcm92aWRlZCBhcyBwYXJ0IG9mIHRoZSBxdWVyeSBzdHJpbmcuCiAgICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2QgZmluZFJlY29yZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBpZAogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgZmluZFJlY29yZDogZnVuY3Rpb24gZmluZFJlY29yZChzdG9yZSwgdHlwZSwgaWQsIHNuYXBzaG90KSB7CiAgICAgIHZhciB1cmwgPSB0aGlzLmJ1aWxkVVJMKHR5cGUubW9kZWxOYW1lLCBpZCwgc25hcHNob3QsICdmaW5kUmVjb3JkJyk7CiAgICAgIHZhciBxdWVyeSA9IHRoaXMuYnVpbGRRdWVyeShzbmFwc2hvdCk7CiAgICAgIHJldHVybiB0aGlzLmFqYXgodXJsLCAnR0VUJywgewogICAgICAgIGRhdGE6IHF1ZXJ5CiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICAgQ2FsbGVkIGJ5IHRoZSBzdG9yZSBpbiBvcmRlciB0byBmZXRjaCBhIEpTT04gYXJyYXkgZm9yIGFsbAogICAgICBvZiB0aGUgcmVjb3JkcyBmb3IgYSBnaXZlbiB0eXBlLgogICAgICAgVGhlIGBmaW5kQWxsYCBtZXRob2QgbWFrZXMgYW4gQWpheCAoSFRUUCBHRVQpIHJlcXVlc3QgdG8gYSBVUkwgY29tcHV0ZWQgYnkgYGJ1aWxkVVJMYCwgYW5kIHJldHVybnMgYQogICAgICBwcm9taXNlIGZvciB0aGUgcmVzdWx0aW5nIHBheWxvYWQuCiAgICAgICBAbWV0aG9kIGZpbmRBbGwKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZQogICAgICBAcGFyYW0ge3VuZGVmaW5lZH0gbmV2ZXJTZXQgYSB2YWx1ZSBpcyBuZXZlciBwcm92aWRlZCB0byB0aGlzIGFyZ3VtZW50CiAgICAgIEBwYXJhbSB7U25hcHNob3RSZWNvcmRBcnJheX0gc25hcHNob3RSZWNvcmRBcnJheQogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgZmluZEFsbDogZnVuY3Rpb24gZmluZEFsbChzdG9yZSwgdHlwZSwgc2luY2VUb2tlbiwgc25hcHNob3RSZWNvcmRBcnJheSkgewogICAgICB2YXIgcXVlcnkgPSB0aGlzLmJ1aWxkUXVlcnkoc25hcHNob3RSZWNvcmRBcnJheSk7CiAgICAgIHZhciB1cmwgPSB0aGlzLmJ1aWxkVVJMKHR5cGUubW9kZWxOYW1lLCBudWxsLCBzbmFwc2hvdFJlY29yZEFycmF5LCAnZmluZEFsbCcpOwoKICAgICAgaWYgKHNpbmNlVG9rZW4pIHsKICAgICAgICBxdWVyeS5zaW5jZSA9IHNpbmNlVG9rZW47CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLmFqYXgodXJsLCAnR0VUJywgewogICAgICAgIGRhdGE6IHF1ZXJ5CiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICAgQ2FsbGVkIGJ5IHRoZSBzdG9yZSBpbiBvcmRlciB0byBmZXRjaCBhIEpTT04gYXJyYXkgZm9yCiAgICAgIHRoZSByZWNvcmRzIHRoYXQgbWF0Y2ggYSBwYXJ0aWN1bGFyIHF1ZXJ5LgogICAgICAgVGhlIGBxdWVyeWAgbWV0aG9kIG1ha2VzIGFuIEFqYXggKEhUVFAgR0VUKSByZXF1ZXN0IHRvIGEgVVJMCiAgICAgIGNvbXB1dGVkIGJ5IGBidWlsZFVSTGAsIGFuZCByZXR1cm5zIGEgcHJvbWlzZSBmb3IgdGhlIHJlc3VsdGluZwogICAgICBwYXlsb2FkLgogICAgICAgVGhlIGBxdWVyeWAgYXJndW1lbnQgaXMgYSBzaW1wbGUgSmF2YVNjcmlwdCBvYmplY3QgdGhhdCB3aWxsIGJlIHBhc3NlZCBkaXJlY3RseQogICAgICB0byB0aGUgc2VydmVyIGFzIHBhcmFtZXRlcnMuCiAgICAgICBAbWV0aG9kIHF1ZXJ5CiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGUKICAgICAgQHBhcmFtIHtPYmplY3R9IHF1ZXJ5CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBxdWVyeTogZnVuY3Rpb24gcXVlcnkoc3RvcmUsIHR5cGUsIF9xdWVyeSkgewogICAgICB2YXIgdXJsID0gdGhpcy5idWlsZFVSTCh0eXBlLm1vZGVsTmFtZSwgbnVsbCwgbnVsbCwgJ3F1ZXJ5JywgX3F1ZXJ5KTsKCiAgICAgIGlmICh0aGlzLnNvcnRRdWVyeVBhcmFtcykgewogICAgICAgIF9xdWVyeSA9IHRoaXMuc29ydFF1ZXJ5UGFyYW1zKF9xdWVyeSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLmFqYXgodXJsLCAnR0VUJywgewogICAgICAgIGRhdGE6IF9xdWVyeQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIENhbGxlZCBieSB0aGUgc3RvcmUgaW4gb3JkZXIgdG8gZmV0Y2ggYSBKU09OIG9iamVjdCBmb3IKICAgICAgdGhlIHJlY29yZCB0aGF0IG1hdGNoZXMgYSBwYXJ0aWN1bGFyIHF1ZXJ5LgogICAgICAgVGhlIGBxdWVyeVJlY29yZGAgbWV0aG9kIG1ha2VzIGFuIEFqYXggKEhUVFAgR0VUKSByZXF1ZXN0IHRvIGEgVVJMCiAgICAgIGNvbXB1dGVkIGJ5IGBidWlsZFVSTGAsIGFuZCByZXR1cm5zIGEgcHJvbWlzZSBmb3IgdGhlIHJlc3VsdGluZwogICAgICBwYXlsb2FkLgogICAgICAgVGhlIGBxdWVyeWAgYXJndW1lbnQgaXMgYSBzaW1wbGUgSmF2YVNjcmlwdCBvYmplY3QgdGhhdCB3aWxsIGJlIHBhc3NlZCBkaXJlY3RseQogICAgICB0byB0aGUgc2VydmVyIGFzIHBhcmFtZXRlcnMuCiAgICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2QgcXVlcnlSZWNvcmQKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZQogICAgICBAcGFyYW0ge09iamVjdH0gcXVlcnkKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIHF1ZXJ5UmVjb3JkOiBmdW5jdGlvbiBxdWVyeVJlY29yZChzdG9yZSwgdHlwZSwgcXVlcnkpIHsKICAgICAgdmFyIHVybCA9IHRoaXMuYnVpbGRVUkwodHlwZS5tb2RlbE5hbWUsIG51bGwsIG51bGwsICdxdWVyeVJlY29yZCcsIHF1ZXJ5KTsKCiAgICAgIGlmICh0aGlzLnNvcnRRdWVyeVBhcmFtcykgewogICAgICAgIHF1ZXJ5ID0gdGhpcy5zb3J0UXVlcnlQYXJhbXMocXVlcnkpOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5hamF4KHVybCwgJ0dFVCcsIHsKICAgICAgICBkYXRhOiBxdWVyeQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIENhbGxlZCBieSB0aGUgc3RvcmUgaW4gb3JkZXIgdG8gZmV0Y2ggc2V2ZXJhbCByZWNvcmRzIHRvZ2V0aGVyIGlmIGBjb2FsZXNjZUZpbmRSZXF1ZXN0c2AgaXMgdHJ1ZQogICAgICAgRm9yIGV4YW1wbGUsIGlmIHRoZSBvcmlnaW5hbCBwYXlsb2FkIGxvb2tzIGxpa2U6CiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgImlkIjogMSwKICAgICAgICAidGl0bGUiOiAiUmFpbHMgaXMgb21ha2FzZSIsCiAgICAgICAgImNvbW1lbnRzIjogWyAxLCAyLCAzIF0KICAgICAgfQogICAgICBgYGAKICAgICAgIFRoZSBJRHMgd2lsbCBiZSBwYXNzZWQgYXMgYSBVUkwtZW5jb2RlZCBBcnJheSBvZiBJRHMsIGluIHRoaXMgZm9ybToKICAgICAgIGBgYAogICAgICBpZHNbXT0xJmlkc1tdPTImaWRzW109MwogICAgICBgYGAKICAgICAgIE1hbnkgc2VydmVycywgc3VjaCBhcyBSYWlscyBhbmQgUEhQLCB3aWxsIGF1dG9tYXRpY2FsbHkgY29udmVydCB0aGlzIFVSTC1lbmNvZGVkIGFycmF5CiAgICAgIGludG8gYW4gQXJyYXkgZm9yIHlvdSBvbiB0aGUgc2VydmVyLXNpZGUuIElmIHlvdSB3YW50IHRvIGVuY29kZSB0aGUKICAgICAgSURzLCBkaWZmZXJlbnRseSwganVzdCBvdmVycmlkZSB0aGlzIChvbmUtbGluZSkgbWV0aG9kLgogICAgICAgVGhlIGBmaW5kTWFueWAgbWV0aG9kIG1ha2VzIGFuIEFqYXggKEhUVFAgR0VUKSByZXF1ZXN0IHRvIGEgVVJMIGNvbXB1dGVkIGJ5IGBidWlsZFVSTGAsIGFuZCByZXR1cm5zIGEKICAgICAgcHJvbWlzZSBmb3IgdGhlIHJlc3VsdGluZyBwYXlsb2FkLgogICAgICAgQG1ldGhvZCBmaW5kTWFueQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlCiAgICAgIEBwYXJhbSB7QXJyYXl9IGlkcwogICAgICBAcGFyYW0ge0FycmF5fSBzbmFwc2hvdHMKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIGZpbmRNYW55OiBmdW5jdGlvbiBmaW5kTWFueShzdG9yZSwgdHlwZSwgaWRzLCBzbmFwc2hvdHMpIHsKICAgICAgdmFyIHVybCA9IHRoaXMuYnVpbGRVUkwodHlwZS5tb2RlbE5hbWUsIGlkcywgc25hcHNob3RzLCAnZmluZE1hbnknKTsKICAgICAgcmV0dXJuIHRoaXMuYWpheCh1cmwsICdHRVQnLCB7CiAgICAgICAgZGF0YTogewogICAgICAgICAgaWRzOiBpZHMKICAgICAgICB9CiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICAgQ2FsbGVkIGJ5IHRoZSBzdG9yZSBpbiBvcmRlciB0byBmZXRjaCBhIEpTT04gYXJyYXkgZm9yCiAgICAgIHRoZSB1bmxvYWRlZCByZWNvcmRzIGluIGEgaGFzLW1hbnkgcmVsYXRpb25zaGlwIHRoYXQgd2VyZSBvcmlnaW5hbGx5CiAgICAgIHNwZWNpZmllZCBhcyBhIFVSTCAoaW5zaWRlIG9mIGBsaW5rc2ApLgogICAgICAgRm9yIGV4YW1wbGUsIGlmIHlvdXIgb3JpZ2luYWwgcGF5bG9hZCBsb29rcyBsaWtlIHRoaXM6CiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgInBvc3QiOiB7CiAgICAgICAgICAiaWQiOiAxLAogICAgICAgICAgInRpdGxlIjogIlJhaWxzIGlzIG9tYWthc2UiLAogICAgICAgICAgImxpbmtzIjogeyAiY29tbWVudHMiOiAiL3Bvc3RzLzEvY29tbWVudHMiIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBUaGlzIG1ldGhvZCB3aWxsIGJlIGNhbGxlZCB3aXRoIHRoZSBwYXJlbnQgcmVjb3JkIGFuZCBgL3Bvc3RzLzEvY29tbWVudHNgLgogICAgICAgVGhlIGBmaW5kSGFzTWFueWAgbWV0aG9kIHdpbGwgbWFrZSBhbiBBamF4IChIVFRQIEdFVCkgcmVxdWVzdCB0byB0aGUgb3JpZ2luYWxseSBzcGVjaWZpZWQgVVJMLgogICAgICAgVGhlIGZvcm1hdCBvZiB5b3VyIGBsaW5rc2AgdmFsdWUgd2lsbCBpbmZsdWVuY2UgdGhlIGZpbmFsIHJlcXVlc3QgVVJMIHZpYSB0aGUgYHVybFByZWZpeGAgbWV0aG9kOgogICAgICAgKiBMaW5rcyBiZWdpbm5pbmcgd2l0aCBgLy9gLCBgaHR0cDovL2AsIGBodHRwczovL2AsIHdpbGwgYmUgdXNlZCBhcyBpcywgd2l0aCBubyBmdXJ0aGVyIG1hbmlwdWxhdGlvbi4KICAgICAgICogTGlua3MgYmVnaW5uaW5nIHdpdGggYSBzaW5nbGUgYC9gIHdpbGwgaGF2ZSB0aGUgY3VycmVudCBhZGFwdGVyJ3MgYGhvc3RgIHZhbHVlIHByZXBlbmRlZCB0byBpdC4KICAgICAgICogTGlua3Mgd2l0aCBubyBiZWdpbm5pbmcgYC9gIHdpbGwgaGF2ZSBhIHBhcmVudFVSTCBwcmVwZW5kZWQgdG8gaXQsIHZpYSB0aGUgY3VycmVudCBhZGFwdGVyJ3MgYGJ1aWxkVVJMYC4KICAgICAgIEBtZXRob2QgZmluZEhhc01hbnkKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHBhcmFtIHtTdHJpbmd9IHVybAogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwIG1ldGEgb2JqZWN0IGRlc2NyaWJpbmcgdGhlIHJlbGF0aW9uc2hpcAogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgZmluZEhhc01hbnk6IGZ1bmN0aW9uIGZpbmRIYXNNYW55KHN0b3JlLCBzbmFwc2hvdCwgdXJsLCByZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIGlkID0gc25hcHNob3QuaWQ7CiAgICAgIHZhciB0eXBlID0gc25hcHNob3QubW9kZWxOYW1lOwogICAgICB1cmwgPSB0aGlzLnVybFByZWZpeCh1cmwsIHRoaXMuYnVpbGRVUkwodHlwZSwgaWQsIHNuYXBzaG90LCAnZmluZEhhc01hbnknKSk7CiAgICAgIHJldHVybiB0aGlzLmFqYXgodXJsLCAnR0VUJyk7CiAgICB9LAoKICAgIC8qKgogICAgICBDYWxsZWQgYnkgdGhlIHN0b3JlIGluIG9yZGVyIHRvIGZldGNoIHRoZSBKU09OIGZvciB0aGUgdW5sb2FkZWQgcmVjb3JkIGluIGEKICAgICAgYmVsb25ncy10byByZWxhdGlvbnNoaXAgdGhhdCB3YXMgb3JpZ2luYWxseSBzcGVjaWZpZWQgYXMgYSBVUkwgKGluc2lkZSBvZgogICAgICBgbGlua3NgKS4KICAgICAgIEZvciBleGFtcGxlLCBpZiB5b3VyIG9yaWdpbmFsIHBheWxvYWQgbG9va3MgbGlrZSB0aGlzOgogICAgICAgYGBganMKICAgICAgewogICAgICAgICJwZXJzb24iOiB7CiAgICAgICAgICAiaWQiOiAxLAogICAgICAgICAgIm5hbWUiOiAiVG9tIERhbGUiLAogICAgICAgICAgImxpbmtzIjogeyAiZ3JvdXAiOiAiL3Blb3BsZS8xL2dyb3VwIiB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgVGhpcyBtZXRob2Qgd2lsbCBiZSBjYWxsZWQgd2l0aCB0aGUgcGFyZW50IHJlY29yZCBhbmQgYC9wZW9wbGUvMS9ncm91cGAuCiAgICAgICBUaGUgYGZpbmRCZWxvbmdzVG9gIG1ldGhvZCB3aWxsIG1ha2UgYW4gQWpheCAoSFRUUCBHRVQpIHJlcXVlc3QgdG8gdGhlIG9yaWdpbmFsbHkgc3BlY2lmaWVkIFVSTC4KICAgICAgIFRoZSBmb3JtYXQgb2YgeW91ciBgbGlua3NgIHZhbHVlIHdpbGwgaW5mbHVlbmNlIHRoZSBmaW5hbCByZXF1ZXN0IFVSTCB2aWEgdGhlIGB1cmxQcmVmaXhgIG1ldGhvZDoKICAgICAgICogTGlua3MgYmVnaW5uaW5nIHdpdGggYC8vYCwgYGh0dHA6Ly9gLCBgaHR0cHM6Ly9gLCB3aWxsIGJlIHVzZWQgYXMgaXMsIHdpdGggbm8gZnVydGhlciBtYW5pcHVsYXRpb24uCiAgICAgICAqIExpbmtzIGJlZ2lubmluZyB3aXRoIGEgc2luZ2xlIGAvYCB3aWxsIGhhdmUgdGhlIGN1cnJlbnQgYWRhcHRlcidzIGBob3N0YCB2YWx1ZSBwcmVwZW5kZWQgdG8gaXQuCiAgICAgICAqIExpbmtzIHdpdGggbm8gYmVnaW5uaW5nIGAvYCB3aWxsIGhhdmUgYSBwYXJlbnRVUkwgcHJlcGVuZGVkIHRvIGl0LCB2aWEgdGhlIGN1cnJlbnQgYWRhcHRlcidzIGBidWlsZFVSTGAuCiAgICAgICBAbWV0aG9kIGZpbmRCZWxvbmdzVG8KICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHBhcmFtIHtTdHJpbmd9IHVybAogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwIG1ldGEgb2JqZWN0IGRlc2NyaWJpbmcgdGhlIHJlbGF0aW9uc2hpcAogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgZmluZEJlbG9uZ3NUbzogZnVuY3Rpb24gZmluZEJlbG9uZ3NUbyhzdG9yZSwgc25hcHNob3QsIHVybCwgcmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBpZCA9IHNuYXBzaG90LmlkOwogICAgICB2YXIgdHlwZSA9IHNuYXBzaG90Lm1vZGVsTmFtZTsKICAgICAgdXJsID0gdGhpcy51cmxQcmVmaXgodXJsLCB0aGlzLmJ1aWxkVVJMKHR5cGUsIGlkLCBzbmFwc2hvdCwgJ2ZpbmRCZWxvbmdzVG8nKSk7CiAgICAgIHJldHVybiB0aGlzLmFqYXgodXJsLCAnR0VUJyk7CiAgICB9LAoKICAgIC8qKgogICAgICBDYWxsZWQgYnkgdGhlIHN0b3JlIHdoZW4gYSBuZXdseSBjcmVhdGVkIHJlY29yZCBpcwogICAgICBzYXZlZCB2aWEgdGhlIGBzYXZlYCBtZXRob2Qgb24gYSBtb2RlbCByZWNvcmQgaW5zdGFuY2UuCiAgICAgICBUaGUgYGNyZWF0ZVJlY29yZGAgbWV0aG9kIHNlcmlhbGl6ZXMgdGhlIHJlY29yZCBhbmQgbWFrZXMgYW4gQWpheCAoSFRUUCBQT1NUKSByZXF1ZXN0CiAgICAgIHRvIGEgVVJMIGNvbXB1dGVkIGJ5IGBidWlsZFVSTGAuCiAgICAgICBTZWUgYHNlcmlhbGl6ZWAgZm9yIGluZm9ybWF0aW9uIG9uIGhvdyB0byBjdXN0b21pemUgdGhlIHNlcmlhbGl6ZWQgZm9ybQogICAgICBvZiBhIHJlY29yZC4KICAgICAgIEBtZXRob2QgY3JlYXRlUmVjb3JkCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIGNyZWF0ZVJlY29yZDogZnVuY3Rpb24gY3JlYXRlUmVjb3JkKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCkgewogICAgICB2YXIgdXJsID0gdGhpcy5idWlsZFVSTCh0eXBlLm1vZGVsTmFtZSwgbnVsbCwgc25hcHNob3QsICdjcmVhdGVSZWNvcmQnKTsKICAgICAgdmFyIGRhdGEgPSAoMCwgX3ByaXZhdGUuc2VyaWFsaXplSW50b0hhc2gpKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCk7CiAgICAgIHJldHVybiB0aGlzLmFqYXgodXJsLCAnUE9TVCcsIHsKICAgICAgICBkYXRhOiBkYXRhCiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICAgQ2FsbGVkIGJ5IHRoZSBzdG9yZSB3aGVuIGFuIGV4aXN0aW5nIHJlY29yZCBpcyBzYXZlZAogICAgICB2aWEgdGhlIGBzYXZlYCBtZXRob2Qgb24gYSBtb2RlbCByZWNvcmQgaW5zdGFuY2UuCiAgICAgICBUaGUgYHVwZGF0ZVJlY29yZGAgbWV0aG9kIHNlcmlhbGl6ZXMgdGhlIHJlY29yZCBhbmQgbWFrZXMgYW4gQWpheCAoSFRUUCBQVVQpIHJlcXVlc3QKICAgICAgdG8gYSBVUkwgY29tcHV0ZWQgYnkgYGJ1aWxkVVJMYC4KICAgICAgIFNlZSBgc2VyaWFsaXplYCBmb3IgaW5mb3JtYXRpb24gb24gaG93IHRvIGN1c3RvbWl6ZSB0aGUgc2VyaWFsaXplZCBmb3JtCiAgICAgIG9mIGEgcmVjb3JkLgogICAgICAgQG1ldGhvZCB1cGRhdGVSZWNvcmQKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZQogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgdXBkYXRlUmVjb3JkOiBmdW5jdGlvbiB1cGRhdGVSZWNvcmQoc3RvcmUsIHR5cGUsIHNuYXBzaG90KSB7CiAgICAgIHZhciBkYXRhID0gKDAsIF9wcml2YXRlLnNlcmlhbGl6ZUludG9IYXNoKShzdG9yZSwgdHlwZSwgc25hcHNob3QsIHt9KTsKICAgICAgdmFyIGlkID0gc25hcHNob3QuaWQ7CiAgICAgIHZhciB1cmwgPSB0aGlzLmJ1aWxkVVJMKHR5cGUubW9kZWxOYW1lLCBpZCwgc25hcHNob3QsICd1cGRhdGVSZWNvcmQnKTsKICAgICAgcmV0dXJuIHRoaXMuYWpheCh1cmwsICdQVVQnLCB7CiAgICAgICAgZGF0YTogZGF0YQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIENhbGxlZCBieSB0aGUgc3RvcmUgd2hlbiBhIHJlY29yZCBpcyBkZWxldGVkLgogICAgICAgVGhlIGBkZWxldGVSZWNvcmRgIG1ldGhvZCAgbWFrZXMgYW4gQWpheCAoSFRUUCBERUxFVEUpIHJlcXVlc3QgdG8gYSBVUkwgY29tcHV0ZWQgYnkgYGJ1aWxkVVJMYC4KICAgICAgIEBtZXRob2QgZGVsZXRlUmVjb3JkCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHR5cGUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIGRlbGV0ZVJlY29yZDogZnVuY3Rpb24gZGVsZXRlUmVjb3JkKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCkgewogICAgICB2YXIgaWQgPSBzbmFwc2hvdC5pZDsKICAgICAgcmV0dXJuIHRoaXMuYWpheCh0aGlzLmJ1aWxkVVJMKHR5cGUubW9kZWxOYW1lLCBpZCwgc25hcHNob3QsICdkZWxldGVSZWNvcmQnKSwgJ0RFTEVURScpOwogICAgfSwKICAgIF9zdHJpcElERnJvbVVSTDogZnVuY3Rpb24gX3N0cmlwSURGcm9tVVJMKHN0b3JlLCBzbmFwc2hvdCkgewogICAgICB2YXIgdXJsID0gdGhpcy5idWlsZFVSTChzbmFwc2hvdC5tb2RlbE5hbWUsIHNuYXBzaG90LmlkLCBzbmFwc2hvdCk7CiAgICAgIHZhciBleHBhbmRlZFVSTCA9IHVybC5zcGxpdCgnLycpOyAvLyBDYXNlIHdoZW4gdGhlIHVybCBpcyBvZiB0aGUgZm9ybWF0IC4uLnNvbWV0aGluZy86aWQKICAgICAgLy8gV2UgYXJlIGRlY29kZVVSSUNvbXBvbmVudC1pbmcgdGhlIGxhc3RTZWdtZW50IGJlY2F1c2UgaWYgaXQgcmVwcmVzZW50cwogICAgICAvLyB0aGUgaWQsIGl0IGhhcyBiZWVuIGVuY29kZVVSSUNvbXBvbmVudC1pZmllZCB3aXRoaW4gYGJ1aWxkVVJMYC4gSWYgd2UKICAgICAgLy8gZG9uJ3QgZG8gdGhpcywgdGhlbiByZWNvcmRzIHdpdGggaWQgaGF2aW5nIHNwZWNpYWwgY2hhcmFjdGVycyBhcmUgbm90CiAgICAgIC8vIGNvYWxlc2NlZCBjb3JyZWN0bHkgKHNlZSBHSCAjNDE5MCBmb3IgdGhlIHJlcG9ydGVkIGJ1ZykKCiAgICAgIHZhciBsYXN0U2VnbWVudCA9IGV4cGFuZGVkVVJMW2V4cGFuZGVkVVJMLmxlbmd0aCAtIDFdOwogICAgICB2YXIgaWQgPSBzbmFwc2hvdC5pZDsKCiAgICAgIGlmIChkZWNvZGVVUklDb21wb25lbnQobGFzdFNlZ21lbnQpID09PSBpZCkgewogICAgICAgIGV4cGFuZGVkVVJMW2V4cGFuZGVkVVJMLmxlbmd0aCAtIDFdID0gJyc7CiAgICAgIH0gZWxzZSBpZiAoZW5kc1dpdGgobGFzdFNlZ21lbnQsICc/aWQ9JyArIGlkKSkgewogICAgICAgIC8vQ2FzZSB3aGVuIHRoZSB1cmwgaXMgb2YgdGhlIGZvcm1hdCAuLi5zb21ldGhpbmc/aWQ9OmlkCiAgICAgICAgZXhwYW5kZWRVUkxbZXhwYW5kZWRVUkwubGVuZ3RoIC0gMV0gPSBsYXN0U2VnbWVudC5zdWJzdHJpbmcoMCwgbGFzdFNlZ21lbnQubGVuZ3RoIC0gaWQubGVuZ3RoIC0gMSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBleHBhbmRlZFVSTC5qb2luKCcvJyk7CiAgICB9LAogICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy80MTcxNDIvd2hhdC1pcy10aGUtbWF4aW11bS1sZW5ndGgtb2YtYS11cmwtaW4tZGlmZmVyZW50LWJyb3dzZXJzCiAgICBtYXhVUkxMZW5ndGg6IDIwNDgsCgogICAgLyoqCiAgICAgIE9yZ2FuaXplIHJlY29yZHMgaW50byBncm91cHMsIGVhY2ggb2Ygd2hpY2ggaXMgdG8gYmUgcGFzc2VkIHRvIHNlcGFyYXRlCiAgICAgIGNhbGxzIHRvIGBmaW5kTWFueWAuCiAgICAgICBUaGlzIGltcGxlbWVudGF0aW9uIGdyb3VwcyB0b2dldGhlciByZWNvcmRzIHRoYXQgaGF2ZSB0aGUgc2FtZSBiYXNlIFVSTCBidXQKICAgICAgZGlmZmVyaW5nIGlkcy4gRm9yIGV4YW1wbGUgYC9jb21tZW50cy8xYCBhbmQgYC9jb21tZW50cy8yYCB3aWxsIGJlIGdyb3VwZWQgdG9nZXRoZXIKICAgICAgYmVjYXVzZSB3ZSBrbm93IGZpbmRNYW55IGNhbiBjb2FsZXNjZSB0aGVtIHRvZ2V0aGVyIGFzIGAvY29tbWVudHM/aWRzW109MSZpZHNbXT0yYAogICAgICAgSXQgYWxzbyBzdXBwb3J0cyB1cmxzIHdoZXJlIGlkcyBhcmUgcGFzc2VkIGFzIGEgcXVlcnkgcGFyYW0sIHN1Y2ggYXMgYC9jb21tZW50cz9pZD0xYAogICAgICBidXQgbm90IHRob3NlIHdoZXJlIHRoZXJlIGlzIG1vcmUgdGhhbiAxIHF1ZXJ5IHBhcmFtIHN1Y2ggYXMgYC9jb21tZW50cz9pZD0yJm5hbWU9RGF2aWRgCiAgICAgIEN1cnJlbnRseSBvbmx5IHRoZSBxdWVyeSBwYXJhbSBvZiBgaWRgIGlzIHN1cHBvcnRlZC4gSWYgeW91IG5lZWQgdG8gc3VwcG9ydCBvdGhlcnMsIHBsZWFzZQogICAgICBvdmVycmlkZSB0aGlzIG9yIHRoZSBgX3N0cmlwSURGcm9tVVJMYCBtZXRob2QuCiAgICAgICBJdCBkb2VzIG5vdCBncm91cCByZWNvcmRzIHRoYXQgaGF2ZSBkaWZmZXJpbmcgYmFzZSB1cmxzLCBzdWNoIGFzIGZvciBleGFtcGxlOiBgL3Bvc3RzLzEvY29tbWVudHMvMmAKICAgICAgYW5kIGAvcG9zdHMvMi9jb21tZW50cy8zYAogICAgICAgQG1ldGhvZCBncm91cFJlY29yZHNGb3JGaW5kTWFueQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge0FycmF5fSBzbmFwc2hvdHMKICAgICAgQHJldHVybiB7QXJyYXl9ICBhbiBhcnJheSBvZiBhcnJheXMgb2YgcmVjb3JkcywgZWFjaCBvZiB3aGljaCBpcyB0byBiZQogICAgICAgICAgICAgICAgICAgICAgICBsb2FkZWQgc2VwYXJhdGVseSBieSBgZmluZE1hbnlgLgogICAgKi8KICAgIGdyb3VwUmVjb3Jkc0ZvckZpbmRNYW55OiBmdW5jdGlvbiBncm91cFJlY29yZHNGb3JGaW5kTWFueShzdG9yZSwgc25hcHNob3RzKSB7CiAgICAgIHZhciBncm91cHMgPSBuZXcgTWFwKCk7CiAgICAgIHZhciBhZGFwdGVyID0gdGhpczsKICAgICAgdmFyIG1heFVSTExlbmd0aCA9IHRoaXMubWF4VVJMTGVuZ3RoOwogICAgICBzbmFwc2hvdHMuZm9yRWFjaChmdW5jdGlvbiAoc25hcHNob3QpIHsKICAgICAgICB2YXIgYmFzZVVybCA9IGFkYXB0ZXIuX3N0cmlwSURGcm9tVVJMKHN0b3JlLCBzbmFwc2hvdCk7CgogICAgICAgIGlmICghZ3JvdXBzLmhhcyhiYXNlVXJsKSkgewogICAgICAgICAgZ3JvdXBzLnNldChiYXNlVXJsLCBbXSk7CiAgICAgICAgfQoKICAgICAgICBncm91cHMuZ2V0KGJhc2VVcmwpLnB1c2goc25hcHNob3QpOwogICAgICB9KTsKCiAgICAgIGZ1bmN0aW9uIHNwbGl0R3JvdXBUb0ZpdEluVXJsKGdyb3VwLCBtYXhVUkxMZW5ndGgsIHBhcmFtTmFtZUxlbmd0aCkgewogICAgICAgIHZhciBpZHNTaXplID0gMDsKCiAgICAgICAgdmFyIGJhc2VVcmwgPSBhZGFwdGVyLl9zdHJpcElERnJvbVVSTChzdG9yZSwgZ3JvdXBbMF0pOwoKICAgICAgICB2YXIgc3BsaXRHcm91cHMgPSBbW11dOwogICAgICAgIGdyb3VwLmZvckVhY2goZnVuY3Rpb24gKHNuYXBzaG90KSB7CiAgICAgICAgICB2YXIgYWRkaXRpb25hbExlbmd0aCA9IGVuY29kZVVSSUNvbXBvbmVudChzbmFwc2hvdC5pZCkubGVuZ3RoICsgcGFyYW1OYW1lTGVuZ3RoOwoKICAgICAgICAgIGlmIChiYXNlVXJsLmxlbmd0aCArIGlkc1NpemUgKyBhZGRpdGlvbmFsTGVuZ3RoID49IG1heFVSTExlbmd0aCkgewogICAgICAgICAgICBpZHNTaXplID0gMDsKICAgICAgICAgICAgc3BsaXRHcm91cHMucHVzaChbXSk7CiAgICAgICAgICB9CgogICAgICAgICAgaWRzU2l6ZSArPSBhZGRpdGlvbmFsTGVuZ3RoOwogICAgICAgICAgdmFyIGxhc3RHcm91cEluZGV4ID0gc3BsaXRHcm91cHMubGVuZ3RoIC0gMTsKICAgICAgICAgIHNwbGl0R3JvdXBzW2xhc3RHcm91cEluZGV4XS5wdXNoKHNuYXBzaG90KTsKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gc3BsaXRHcm91cHM7CiAgICAgIH0KCiAgICAgIHZhciBncm91cHNBcnJheSA9IFtdOwogICAgICBncm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZ3JvdXAsIGtleSkgewogICAgICAgIHZhciBwYXJhbU5hbWVMZW5ndGggPSAnJmlkcyU1QiU1RD0nLmxlbmd0aDsKICAgICAgICB2YXIgc3BsaXRHcm91cHMgPSBzcGxpdEdyb3VwVG9GaXRJblVybChncm91cCwgbWF4VVJMTGVuZ3RoLCBwYXJhbU5hbWVMZW5ndGgpOwogICAgICAgIHNwbGl0R3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHNwbGl0R3JvdXApIHsKICAgICAgICAgIHJldHVybiBncm91cHNBcnJheS5wdXNoKHNwbGl0R3JvdXApOwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgcmV0dXJuIGdyb3Vwc0FycmF5OwogICAgfSwKCiAgICAvKioKICAgICAgVGFrZXMgYW4gYWpheCByZXNwb25zZSwgYW5kIHJldHVybnMgdGhlIGpzb24gcGF5bG9hZCBvciBhbiBlcnJvci4KICAgICAgIEJ5IGRlZmF1bHQgdGhpcyBob29rIGp1c3QgcmV0dXJucyB0aGUganNvbiBwYXlsb2FkIHBhc3NlZCB0byBpdC4KICAgICAgWW91IG1pZ2h0IHdhbnQgdG8gb3ZlcnJpZGUgaXQgaW4gdHdvIGNhc2VzOgogICAgICAgMS4gWW91ciBBUEkgbWlnaHQgcmV0dXJuIHVzZWZ1bCByZXN1bHRzIGluIHRoZSByZXNwb25zZSBoZWFkZXJzLgogICAgICBSZXNwb25zZSBoZWFkZXJzIGFyZSBwYXNzZWQgaW4gYXMgdGhlIHNlY29uZCBhcmd1bWVudC4KICAgICAgIDIuIFlvdXIgQVBJIG1pZ2h0IHJldHVybiBlcnJvcnMgYXMgc3VjY2Vzc2Z1bCByZXNwb25zZXMgd2l0aCBzdGF0dXMgY29kZQogICAgICAyMDAgYW5kIGFuIEVycm9ycyB0ZXh0IG9yIG9iamVjdC4gWW91IGNhbiByZXR1cm4gYSBgSW52YWxpZEVycm9yYCBvciBhCiAgICAgIGBBZGFwdGVyRXJyb3JgIChvciBhIHN1YiBjbGFzcykgZnJvbSB0aGlzIGhvb2sgYW5kIGl0IHdpbGwgYXV0b21hdGljYWxseQogICAgICByZWplY3QgdGhlIHByb21pc2UgYW5kIHB1dCB5b3VyIHJlY29yZCBpbnRvIHRoZSBpbnZhbGlkIG9yIGVycm9yIHN0YXRlLgogICAgICAgUmV0dXJuaW5nIGEgYEludmFsaWRFcnJvcmAgZnJvbSB0aGlzIG1ldGhvZCB3aWxsIGNhdXNlIHRoZQogICAgICByZWNvcmQgdG8gdHJhbnNpdGlvbiBpbnRvIHRoZSBgaW52YWxpZGAgc3RhdGUgYW5kIG1ha2UgdGhlCiAgICAgIGBlcnJvcnNgIG9iamVjdCBhdmFpbGFibGUgb24gdGhlIHJlY29yZC4gV2hlbiByZXR1cm5pbmcgYW4KICAgICAgYEludmFsaWRFcnJvcmAgdGhlIHN0b3JlIHdpbGwgYXR0ZW1wdCB0byBub3JtYWxpemUgdGhlIGVycm9yIGRhdGEKICAgICAgcmV0dXJuZWQgZnJvbSB0aGUgc2VydmVyIHVzaW5nIHRoZSBzZXJpYWxpemVyJ3MgYGV4dHJhY3RFcnJvcnNgCiAgICAgIG1ldGhvZC4KICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBoYW5kbGVSZXNwb25zZQogICAgICBAcGFyYW0gIHtOdW1iZXJ9IHN0YXR1cwogICAgICBAcGFyYW0gIHtPYmplY3R9IGhlYWRlcnMKICAgICAgQHBhcmFtICB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSAge09iamVjdH0gcmVxdWVzdERhdGEgLSB0aGUgb3JpZ2luYWwgcmVxdWVzdCBpbmZvcm1hdGlvbgogICAgICBAcmV0dXJuIHtPYmplY3QgfCBBZGFwdGVyRXJyb3J9IHJlc3BvbnNlCiAgICAqLwogICAgaGFuZGxlUmVzcG9uc2U6IGZ1bmN0aW9uIGhhbmRsZVJlc3BvbnNlKHN0YXR1cywgaGVhZGVycywgcGF5bG9hZCwgcmVxdWVzdERhdGEpIHsKICAgICAgaWYgKHRoaXMuaXNTdWNjZXNzKHN0YXR1cywgaGVhZGVycywgcGF5bG9hZCkpIHsKICAgICAgICByZXR1cm4gcGF5bG9hZDsKICAgICAgfSBlbHNlIGlmICh0aGlzLmlzSW52YWxpZChzdGF0dXMsIGhlYWRlcnMsIHBheWxvYWQpKSB7CiAgICAgICAgcmV0dXJuIG5ldyBfZXJyb3IuSW52YWxpZEVycm9yKHBheWxvYWQuZXJyb3JzKTsKICAgICAgfQoKICAgICAgdmFyIGVycm9ycyA9IHRoaXMubm9ybWFsaXplRXJyb3JSZXNwb25zZShzdGF0dXMsIGhlYWRlcnMsIHBheWxvYWQpOwogICAgICB2YXIgZGV0YWlsZWRNZXNzYWdlID0gdGhpcy5nZW5lcmF0ZWREZXRhaWxlZE1lc3NhZ2Uoc3RhdHVzLCBoZWFkZXJzLCBwYXlsb2FkLCByZXF1ZXN0RGF0YSk7CgogICAgICBzd2l0Y2ggKHN0YXR1cykgewogICAgICAgIGNhc2UgNDAxOgogICAgICAgICAgcmV0dXJuIG5ldyBfZXJyb3IuVW5hdXRob3JpemVkRXJyb3IoZXJyb3JzLCBkZXRhaWxlZE1lc3NhZ2UpOwoKICAgICAgICBjYXNlIDQwMzoKICAgICAgICAgIHJldHVybiBuZXcgX2Vycm9yLkZvcmJpZGRlbkVycm9yKGVycm9ycywgZGV0YWlsZWRNZXNzYWdlKTsKCiAgICAgICAgY2FzZSA0MDQ6CiAgICAgICAgICByZXR1cm4gbmV3IF9lcnJvci5Ob3RGb3VuZEVycm9yKGVycm9ycywgZGV0YWlsZWRNZXNzYWdlKTsKCiAgICAgICAgY2FzZSA0MDk6CiAgICAgICAgICByZXR1cm4gbmV3IF9lcnJvci5Db25mbGljdEVycm9yKGVycm9ycywgZGV0YWlsZWRNZXNzYWdlKTsKCiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIGlmIChzdGF0dXMgPj0gNTAwKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgX2Vycm9yLlNlcnZlckVycm9yKGVycm9ycywgZGV0YWlsZWRNZXNzYWdlKTsKICAgICAgICAgIH0KCiAgICAgIH0KCiAgICAgIHJldHVybiBuZXcgX2Vycm9yLmRlZmF1bHQoZXJyb3JzLCBkZXRhaWxlZE1lc3NhZ2UpOwogICAgfSwKCiAgICAvKioKICAgICAgRGVmYXVsdCBgaGFuZGxlUmVzcG9uc2VgIGltcGxlbWVudGF0aW9uIHVzZXMgdGhpcyBob29rIHRvIGRlY2lkZSBpZiB0aGUKICAgICAgcmVzcG9uc2UgaXMgYSBzdWNjZXNzLgogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIGlzU3VjY2VzcwogICAgICBAcGFyYW0gIHtOdW1iZXJ9IHN0YXR1cwogICAgICBAcGFyYW0gIHtPYmplY3R9IGhlYWRlcnMKICAgICAgQHBhcmFtICB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICAqLwogICAgaXNTdWNjZXNzOiBmdW5jdGlvbiBpc1N1Y2Nlc3Moc3RhdHVzLCBoZWFkZXJzLCBwYXlsb2FkKSB7CiAgICAgIHJldHVybiBzdGF0dXMgPj0gMjAwICYmIHN0YXR1cyA8IDMwMCB8fCBzdGF0dXMgPT09IDMwNDsKICAgIH0sCgogICAgLyoqCiAgICAgIERlZmF1bHQgYGhhbmRsZVJlc3BvbnNlYCBpbXBsZW1lbnRhdGlvbiB1c2VzIHRoaXMgaG9vayB0byBkZWNpZGUgaWYgdGhlCiAgICAgIHJlc3BvbnNlIGlzIGFuIGludmFsaWQgZXJyb3IuCiAgICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2QgaXNJbnZhbGlkCiAgICAgIEBwYXJhbSAge051bWJlcn0gc3RhdHVzCiAgICAgIEBwYXJhbSAge09iamVjdH0gaGVhZGVycwogICAgICBAcGFyYW0gIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHJldHVybiB7Qm9vbGVhbn0KICAgICovCiAgICBpc0ludmFsaWQ6IGZ1bmN0aW9uIGlzSW52YWxpZChzdGF0dXMsIGhlYWRlcnMsIHBheWxvYWQpIHsKICAgICAgcmV0dXJuIHN0YXR1cyA9PT0gNDIyOwogICAgfSwKCiAgICAvKioKICAgICAgVGFrZXMgYSBVUkwsIGFuIEhUVFAgbWV0aG9kIGFuZCBhIGhhc2ggb2YgZGF0YSwgYW5kIG1ha2VzIGFuCiAgICAgIEhUVFAgcmVxdWVzdC4KICAgICAgIFdoZW4gdGhlIHNlcnZlciByZXNwb25kcyB3aXRoIGEgcGF5bG9hZCwgRW1iZXIgRGF0YSB3aWxsIGNhbGwgaW50byBgZXh0cmFjdFNpbmdsZWAKICAgICAgb3IgYGV4dHJhY3RBcnJheWAgKGRlcGVuZGluZyBvbiB3aGV0aGVyIHRoZSBvcmlnaW5hbCBxdWVyeSB3YXMgZm9yIG9uZSByZWNvcmQgb3IKICAgICAgbWFueSByZWNvcmRzKS4KICAgICAgIEJ5IGRlZmF1bHQsIGBhamF4YCBtZXRob2QgaGFzIHRoZSBmb2xsb3dpbmcgYmVoYXZpb3I6CiAgICAgICAqIEl0IHNldHMgdGhlIHJlc3BvbnNlIGBkYXRhVHlwZWAgdG8gYCJqc29uImAKICAgICAgKiBJZiB0aGUgSFRUUCBtZXRob2QgaXMgbm90IGAiR0VUImAsIGl0IHNldHMgdGhlIGBDb250ZW50LVR5cGVgIHRvIGJlCiAgICAgICAgYGFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9dXRmLThgCiAgICAgICogSWYgdGhlIEhUVFAgbWV0aG9kIGlzIG5vdCBgIkdFVCJgLCBpdCBzdHJpbmdpZmllcyB0aGUgZGF0YSBwYXNzZWQgaW4uIFRoZQogICAgICAgIGRhdGEgaXMgdGhlIHNlcmlhbGl6ZWQgcmVjb3JkIGluIHRoZSBjYXNlIG9mIGEgc2F2ZS4KICAgICAgKiBSZWdpc3RlcnMgc3VjY2VzcyBhbmQgZmFpbHVyZSBoYW5kbGVycy4KICAgICAgIEBtZXRob2QgYWpheAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gdXJsCiAgICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlIFRoZSByZXF1ZXN0IHR5cGUgR0VULCBQT1NULCBQVVQsIERFTEVURSBldGMuCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICBhamF4OiBmdW5jdGlvbiBhamF4KHVybCwgdHlwZSwgb3B0aW9ucykgewogICAgICB2YXIgYWRhcHRlciA9IHRoaXM7CiAgICAgIHZhciB1c2VGZXRjaCA9IEVtYmVyLmdldCh0aGlzLCAndXNlRmV0Y2gnKTsKICAgICAgdmFyIHJlcXVlc3REYXRhID0gewogICAgICAgIHVybDogdXJsLAogICAgICAgIG1ldGhvZDogdHlwZQogICAgICB9OwogICAgICB2YXIgaGFzaCA9IGFkYXB0ZXIuYWpheE9wdGlvbnModXJsLCB0eXBlLCBvcHRpb25zKTsKCiAgICAgIGlmICh1c2VGZXRjaCkgewogICAgICAgIHJldHVybiB0aGlzLl9mZXRjaFJlcXVlc3QoaGFzaCkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHsKICAgICAgICAgIHJldHVybiBFbWJlci5SU1ZQLmhhc2goewogICAgICAgICAgICByZXNwb25zZTogcmVzcG9uc2UsCiAgICAgICAgICAgIHBheWxvYWQ6ICgwLCBfcHJpdmF0ZS5kZXRlcm1pbmVCb2R5UHJvbWlzZSkocmVzcG9uc2UsIHJlcXVlc3REYXRhKQogICAgICAgICAgfSk7CiAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoX3JlZikgewogICAgICAgICAgdmFyIHJlc3BvbnNlID0gX3JlZi5yZXNwb25zZSwKICAgICAgICAgICAgICBwYXlsb2FkID0gX3JlZi5wYXlsb2FkOwoKICAgICAgICAgIGlmIChyZXNwb25zZS5vaykgewogICAgICAgICAgICByZXR1cm4gZmV0Y2hTdWNjZXNzSGFuZGxlcihhZGFwdGVyLCBwYXlsb2FkLCByZXNwb25zZSwgcmVxdWVzdERhdGEpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGhyb3cgZmV0Y2hFcnJvckhhbmRsZXIoYWRhcHRlciwgcGF5bG9hZCwgcmVzcG9uc2UsIG51bGwsIHJlcXVlc3REYXRhKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICBoYXNoLnN1Y2Nlc3MgPSBmdW5jdGlvbiAocGF5bG9hZCwgdGV4dFN0YXR1cywganFYSFIpIHsKICAgICAgICAgIHZhciByZXNwb25zZSA9IGFqYXhTdWNjZXNzSGFuZGxlcihhZGFwdGVyLCBwYXlsb2FkLCBqcVhIUiwgcmVxdWVzdERhdGEpOwogICAgICAgICAgRW1iZXIucnVuLmpvaW4obnVsbCwgcmVzb2x2ZSwgcmVzcG9uc2UpOwogICAgICAgIH07CgogICAgICAgIGhhc2guZXJyb3IgPSBmdW5jdGlvbiAoanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7CiAgICAgICAgICB2YXIgZXJyb3IgPSBhamF4RXJyb3JIYW5kbGVyKGFkYXB0ZXIsIGpxWEhSLCBlcnJvclRocm93biwgcmVxdWVzdERhdGEpOwogICAgICAgICAgRW1iZXIucnVuLmpvaW4obnVsbCwgcmVqZWN0LCBlcnJvcik7CiAgICAgICAgfTsKCiAgICAgICAgYWRhcHRlci5fYWpheChoYXNoKTsKICAgICAgfSwgJ0RTOiBSRVNUQWRhcHRlciNhamF4ICcgKyB0eXBlICsgJyB0byAnICsgdXJsKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBtZXRob2QgX2FqYXhSZXF1ZXN0CiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIGpRdWVyeSBhamF4IG9wdGlvbnMgdG8gYmUgdXNlZCBmb3IgdGhlIGFqYXggcmVxdWVzdAogICAgKi8KICAgIF9hamF4UmVxdWVzdDogZnVuY3Rpb24gX2FqYXhSZXF1ZXN0KG9wdGlvbnMpIHsKICAgICAgalF1ZXJ5LmFqYXgob3B0aW9ucyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIF9uYWpheFJlcXVlc3QKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgalF1ZXJ5IGFqYXggb3B0aW9ucyB0byBiZSB1c2VkIGZvciB0aGUgbmFqYXggcmVxdWVzdAogICAgKi8KICAgIF9uYWpheFJlcXVlc3Q6IGZ1bmN0aW9uIF9uYWpheFJlcXVlc3Qob3B0aW9ucykgewogICAgICBpZiAoaGFzTmFqYXgpIHsKICAgICAgICBuYWpheChvcHRpb25zKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25hamF4IGRvZXMgbm90IHNlZW0gdG8gYmUgZGVmaW5lZCBpbiB5b3VyIGFwcC4gRGlkIHlvdSBvdmVycmlkZSBpdCB2aWEgYGFkZE9yT3ZlcnJpZGVTYW5kYm94R2xvYmFsc2AgaW4gdGhlIGZhc3Rib290IHNlcnZlcj8nKTsKICAgICAgfQogICAgfSwKICAgIF9mZXRjaFJlcXVlc3Q6IGZ1bmN0aW9uIF9mZXRjaFJlcXVlc3Qob3B0aW9ucykgewogICAgICB2YXIgZmV0Y2hGdW5jdGlvbiA9ICgwLCBfcHJpdmF0ZS5mZXRjaCkoKTsKCiAgICAgIGlmIChmZXRjaEZ1bmN0aW9uKSB7CiAgICAgICAgcmV0dXJuIGZldGNoRnVuY3Rpb24ob3B0aW9ucy51cmwsIG9wdGlvbnMpOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IGZpbmQgdGhlIGBmZXRjaGAgbW9kdWxlIG9yIHRoZSBgZmV0Y2hgIGdsb2JhbC4gRGlkIHlvdSBtZWFuIHRvIGluc3RhbGwgdGhlIGBlbWJlci1mZXRjaGAgYWRkb24/Jyk7CiAgICAgIH0KICAgIH0sCiAgICBfYWpheDogZnVuY3Rpb24gX2FqYXgob3B0aW9ucykgewogICAgICBpZiAoRW1iZXIuZ2V0KHRoaXMsICd1c2VGZXRjaCcpKSB7CiAgICAgICAgdGhpcy5fZmV0Y2hSZXF1ZXN0KG9wdGlvbnMpOwogICAgICB9IGVsc2UgaWYgKEVtYmVyLmdldCh0aGlzLCAnZmFzdGJvb3QuaXNGYXN0Qm9vdCcpKSB7CiAgICAgICAgdGhpcy5fbmFqYXhSZXF1ZXN0KG9wdGlvbnMpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuX2FqYXhSZXF1ZXN0KG9wdGlvbnMpOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIGFqYXhPcHRpb25zCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSB1cmwKICAgICAgQHBhcmFtIHtTdHJpbmd9IHR5cGUgVGhlIHJlcXVlc3QgdHlwZSBHRVQsIFBPU1QsIFBVVCwgREVMRVRFIGV0Yy4KICAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgKi8KICAgIGFqYXhPcHRpb25zOiBmdW5jdGlvbiBhamF4T3B0aW9ucyh1cmwsIG1ldGhvZCwgb3B0aW9ucykgewogICAgICBvcHRpb25zID0gRW1iZXIuYXNzaWduKHsKICAgICAgICB1cmw6IHVybCwKICAgICAgICBtZXRob2Q6IG1ldGhvZCwKICAgICAgICB0eXBlOiBtZXRob2QKICAgICAgfSwgb3B0aW9ucyk7CiAgICAgIHZhciBoZWFkZXJzID0gRW1iZXIuZ2V0KHRoaXMsICdoZWFkZXJzJyk7CgogICAgICBpZiAoaGVhZGVycyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgb3B0aW9ucy5oZWFkZXJzID0gRW1iZXIuYXNzaWduKHt9LCBvcHRpb25zLmhlYWRlcnMsIGhlYWRlcnMpOwogICAgICB9IGVsc2UgaWYgKCFvcHRpb25zLmhlYWRlcnMpIHsKICAgICAgICBvcHRpb25zLmhlYWRlcnMgPSB7fTsKICAgICAgfQoKICAgICAgdmFyIGNvbnRlbnRUeXBlID0gb3B0aW9ucy5jb250ZW50VHlwZSB8fCB0aGlzLl9kZWZhdWx0Q29udGVudFR5cGU7CgogICAgICBpZiAoRW1iZXIuZ2V0KHRoaXMsICd1c2VGZXRjaCcpKSB7CiAgICAgICAgaWYgKG9wdGlvbnMuZGF0YSAmJiBvcHRpb25zLnR5cGUgIT09ICdHRVQnKSB7CiAgICAgICAgICBpZiAoIW9wdGlvbnMuaGVhZGVyc1snQ29udGVudC1UeXBlJ10gJiYgIW9wdGlvbnMuaGVhZGVyc1snY29udGVudC10eXBlJ10pIHsKICAgICAgICAgICAgb3B0aW9ucy5oZWFkZXJzWydjb250ZW50LXR5cGUnXSA9IGNvbnRlbnRUeXBlOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgb3B0aW9ucyA9IGZldGNoT3B0aW9ucyhvcHRpb25zLCB0aGlzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAvLyBHRVQgcmVxdWVzdHMgd2l0aG91dCBhIGJvZHkgc2hvdWxkIG5vdCBoYXZlIGEgY29udGVudC10eXBlIGhlYWRlcgogICAgICAgIC8vIGFuZCBtYXkgYmUgdW5leHBlY3RlZCBieSBhIHNlcnZlcgogICAgICAgIGlmIChvcHRpb25zLmRhdGEgJiYgb3B0aW9ucy50eXBlICE9PSAnR0VUJykgewogICAgICAgICAgb3B0aW9ucyA9IEVtYmVyLmFzc2lnbihvcHRpb25zLCB7CiAgICAgICAgICAgIGNvbnRlbnRUeXBlOiBjb250ZW50VHlwZQogICAgICAgICAgfSk7CiAgICAgICAgfQoKICAgICAgICBvcHRpb25zID0gX2FqYXhPcHRpb25zKG9wdGlvbnMsIHRoaXMpOwogICAgICB9CgogICAgICBvcHRpb25zLnVybCA9IHRoaXMuX2FqYXhVUkwob3B0aW9ucy51cmwpOwogICAgICByZXR1cm4gb3B0aW9uczsKICAgIH0sCiAgICBfYWpheFVSTDogZnVuY3Rpb24gX2FqYXhVUkwodXJsKSB7CiAgICAgIGlmIChFbWJlci5nZXQodGhpcywgJ2Zhc3Rib290LmlzRmFzdEJvb3QnKSkgewogICAgICAgIHZhciBodHRwUmVnZXggPSAvXmh0dHBzPzpcL1wvLzsKICAgICAgICB2YXIgcHJvdG9jb2xSZWxhdGl2ZVJlZ2V4ID0gL15cL1wvLzsKICAgICAgICB2YXIgcHJvdG9jb2wgPSBFbWJlci5nZXQodGhpcywgJ2Zhc3Rib290LnJlcXVlc3QucHJvdG9jb2wnKTsKICAgICAgICB2YXIgaG9zdCA9IEVtYmVyLmdldCh0aGlzLCAnZmFzdGJvb3QucmVxdWVzdC5ob3N0Jyk7CgogICAgICAgIGlmIChwcm90b2NvbFJlbGF0aXZlUmVnZXgudGVzdCh1cmwpKSB7CiAgICAgICAgICByZXR1cm4gIiIgKyBwcm90b2NvbCArIHVybDsKICAgICAgICB9IGVsc2UgaWYgKCFodHRwUmVnZXgudGVzdCh1cmwpKSB7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICByZXR1cm4gcHJvdG9jb2wgKyAiLy8iICsgaG9zdCArIHVybDsKICAgICAgICAgIH0gY2F0Y2ggKGZiRXJyb3IpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgYXJlIHVzaW5nIEVtYmVyIERhdGEgd2l0aCBubyBob3N0IGRlZmluZWQgaW4geW91ciBhZGFwdGVyLiBUaGlzIHdpbGwgYXR0ZW1wdCB0byB1c2UgdGhlIGhvc3Qgb2YgdGhlIEZhc3RCb290IHJlcXVlc3QsIHdoaWNoIGlzIG5vdCBjb25maWd1cmVkIGZvciB0aGUgY3VycmVudCBob3N0IG9mIHRoaXMgcmVxdWVzdC4gUGxlYXNlIHNldCB0aGUgaG9zdFdoaXRlbGlzdCBwcm9wZXJ0eSBmb3IgaW4geW91ciBlbnZpcm9ubWVudC5qcy4gRmFzdEJvb3QgRXJyb3I6ICcgKyBmYkVycm9yLm1lc3NhZ2UpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHVybDsKICAgIH0sCgogICAgLyoqCiAgICAgIEBtZXRob2QgcGFyc2VFcnJvclJlc3BvbnNlCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXNwb25zZVRleHQKICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgKi8KICAgIHBhcnNlRXJyb3JSZXNwb25zZTogZnVuY3Rpb24gcGFyc2VFcnJvclJlc3BvbnNlKHJlc3BvbnNlVGV4dCkgewogICAgICB2YXIganNvbiA9IHJlc3BvbnNlVGV4dDsKCiAgICAgIHRyeSB7CiAgICAgICAganNvbiA9IEpTT04ucGFyc2UocmVzcG9uc2VUZXh0KTsKICAgICAgfSBjYXRjaCAoZSkgey8vIGlnbm9yZWQKICAgICAgfQoKICAgICAgcmV0dXJuIGpzb247CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIG5vcm1hbGl6ZUVycm9yUmVzcG9uc2UKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtICB7TnVtYmVyfSBzdGF0dXMKICAgICAgQHBhcmFtICB7T2JqZWN0fSBoZWFkZXJzCiAgICAgIEBwYXJhbSAge09iamVjdH0gcGF5bG9hZAogICAgICBAcmV0dXJuIHtBcnJheX0gZXJyb3JzIHBheWxvYWQKICAgICovCiAgICBub3JtYWxpemVFcnJvclJlc3BvbnNlOiBmdW5jdGlvbiBub3JtYWxpemVFcnJvclJlc3BvbnNlKHN0YXR1cywgaGVhZGVycywgcGF5bG9hZCkgewogICAgICBpZiAocGF5bG9hZCAmJiB0eXBlb2YgcGF5bG9hZCA9PT0gJ29iamVjdCcgJiYgcGF5bG9hZC5lcnJvcnMpIHsKICAgICAgICByZXR1cm4gcGF5bG9hZC5lcnJvcnM7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIFt7CiAgICAgICAgICBzdGF0dXM6ICIiICsgc3RhdHVzLAogICAgICAgICAgdGl0bGU6ICdUaGUgYmFja2VuZCByZXNwb25kZWQgd2l0aCBhbiBlcnJvcicsCiAgICAgICAgICBkZXRhaWw6ICIiICsgcGF5bG9hZAogICAgICAgIH1dOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBHZW5lcmF0ZXMgYSBkZXRhaWxlZCAoImZyaWVuZGx5IikgZXJyb3IgbWVzc2FnZSwgd2l0aCBwbGVudHkKICAgICAgb2YgaW5mb3JtYXRpb24gZm9yIGRlYnVnZ2luZyAoZ29vZCBsdWNrISkKICAgICAgIEBtZXRob2QgZ2VuZXJhdGVkRGV0YWlsZWRNZXNzYWdlCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSAge051bWJlcn0gc3RhdHVzCiAgICAgIEBwYXJhbSAge09iamVjdH0gaGVhZGVycwogICAgICBAcGFyYW0gIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtICB7T2JqZWN0fSByZXF1ZXN0RGF0YQogICAgICBAcmV0dXJuIHtTdHJpbmd9IGRldGFpbGVkIGVycm9yIG1lc3NhZ2UKICAgICovCiAgICBnZW5lcmF0ZWREZXRhaWxlZE1lc3NhZ2U6IGZ1bmN0aW9uIGdlbmVyYXRlZERldGFpbGVkTWVzc2FnZShzdGF0dXMsIGhlYWRlcnMsIHBheWxvYWQsIHJlcXVlc3REYXRhKSB7CiAgICAgIHZhciBzaG9ydGVuZWRQYXlsb2FkOwogICAgICB2YXIgcGF5bG9hZENvbnRlbnRUeXBlID0gaGVhZGVyc1snY29udGVudC10eXBlJ10gfHwgJ0VtcHR5IENvbnRlbnQtVHlwZSc7CgogICAgICBpZiAocGF5bG9hZENvbnRlbnRUeXBlID09PSAndGV4dC9odG1sJyAmJiBwYXlsb2FkLmxlbmd0aCA+IDI1MCkgewogICAgICAgIHNob3J0ZW5lZFBheWxvYWQgPSAnW09taXR0ZWQgTGVuZ3RoeSBIVE1MXSc7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgc2hvcnRlbmVkUGF5bG9hZCA9IHBheWxvYWQ7CiAgICAgIH0KCiAgICAgIHZhciByZXF1ZXN0RGVzY3JpcHRpb24gPSByZXF1ZXN0RGF0YS5tZXRob2QgKyAnICcgKyByZXF1ZXN0RGF0YS51cmw7CiAgICAgIHZhciBwYXlsb2FkRGVzY3JpcHRpb24gPSAnUGF5bG9hZCAoJyArIHBheWxvYWRDb250ZW50VHlwZSArICcpJzsKICAgICAgcmV0dXJuIFsnRW1iZXIgRGF0YSBSZXF1ZXN0ICcgKyByZXF1ZXN0RGVzY3JpcHRpb24gKyAnIHJldHVybmVkIGEgJyArIHN0YXR1cywgcGF5bG9hZERlc2NyaXB0aW9uLCBzaG9ydGVuZWRQYXlsb2FkXS5qb2luKCdcbicpOwogICAgfSwKICAgIC8vIEBzaW5jZSAyLjUuMAogICAgYnVpbGRRdWVyeTogZnVuY3Rpb24gYnVpbGRRdWVyeShzbmFwc2hvdCkgewogICAgICB2YXIgcXVlcnkgPSB7fTsKCiAgICAgIGlmIChzbmFwc2hvdCkgewogICAgICAgIHZhciBpbmNsdWRlID0gc25hcHNob3QuaW5jbHVkZTsKCiAgICAgICAgaWYgKGluY2x1ZGUpIHsKICAgICAgICAgIHF1ZXJ5LmluY2x1ZGUgPSBpbmNsdWRlOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHF1ZXJ5OwogICAgfQogIH0pOwoKICBmdW5jdGlvbiBhamF4U3VjY2VzcyhhZGFwdGVyLCBwYXlsb2FkLCByZXF1ZXN0RGF0YSwgcmVzcG9uc2VEYXRhKSB7CiAgICB2YXIgcmVzcG9uc2U7CgogICAgdHJ5IHsKICAgICAgcmVzcG9uc2UgPSBhZGFwdGVyLmhhbmRsZVJlc3BvbnNlKHJlc3BvbnNlRGF0YS5zdGF0dXMsIHJlc3BvbnNlRGF0YS5oZWFkZXJzLCBwYXlsb2FkLCByZXF1ZXN0RGF0YSk7CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IpOwogICAgfQoKICAgIGlmIChyZXNwb25zZSAmJiByZXNwb25zZS5pc0FkYXB0ZXJFcnJvcikgewogICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QocmVzcG9uc2UpOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIHJlc3BvbnNlOwogICAgfQogIH0KCiAgZnVuY3Rpb24gYWpheEVycm9yKGFkYXB0ZXIsIHBheWxvYWQsIHJlcXVlc3REYXRhLCByZXNwb25zZURhdGEpIHsKICAgIHZhciBlcnJvcjsKCiAgICBpZiAocmVzcG9uc2VEYXRhLmVycm9yVGhyb3duIGluc3RhbmNlb2YgRXJyb3IpIHsKICAgICAgZXJyb3IgPSByZXNwb25zZURhdGEuZXJyb3JUaHJvd247CiAgICB9IGVsc2UgaWYgKHJlc3BvbnNlRGF0YS50ZXh0U3RhdHVzID09PSAndGltZW91dCcpIHsKICAgICAgZXJyb3IgPSBuZXcgX2Vycm9yLlRpbWVvdXRFcnJvcigpOwogICAgfSBlbHNlIGlmIChyZXNwb25zZURhdGEudGV4dFN0YXR1cyA9PT0gJ2Fib3J0JyB8fCByZXNwb25zZURhdGEuc3RhdHVzID09PSAwKSB7CiAgICAgIGVycm9yID0gaGFuZGxlQWJvcnQocmVxdWVzdERhdGEsIHJlc3BvbnNlRGF0YSk7CiAgICB9IGVsc2UgewogICAgICB0cnkgewogICAgICAgIGVycm9yID0gYWRhcHRlci5oYW5kbGVSZXNwb25zZShyZXNwb25zZURhdGEuc3RhdHVzLCByZXNwb25zZURhdGEuaGVhZGVycywgcGF5bG9hZCB8fCByZXNwb25zZURhdGEuZXJyb3JUaHJvd24sIHJlcXVlc3REYXRhKTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGVycm9yID0gZTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBlcnJvcjsKICB9IC8vIEFkYXB0ZXIgYWJvcnQgZXJyb3IgdG8gaW5jbHVkZSBhbnkgcmVsZXZlbnQgaW5mbywgZS5nLiByZXF1ZXN0L3Jlc3BvbnNlOgoKCiAgZnVuY3Rpb24gaGFuZGxlQWJvcnQocmVxdWVzdERhdGEsIHJlc3BvbnNlRGF0YSkgewogICAgdmFyIG1ldGhvZCA9IHJlcXVlc3REYXRhLm1ldGhvZCwKICAgICAgICB1cmwgPSByZXF1ZXN0RGF0YS51cmwsCiAgICAgICAgZXJyb3JUaHJvd24gPSByZXF1ZXN0RGF0YS5lcnJvclRocm93bjsKICAgIHZhciBzdGF0dXMgPSByZXNwb25zZURhdGEuc3RhdHVzOwogICAgdmFyIG1zZyA9ICJSZXF1ZXN0IGZhaWxlZDogIiArIG1ldGhvZCArICIgIiArIHVybCArICIgIiArIChlcnJvclRocm93biB8fCAnJyk7CiAgICB2YXIgZXJyb3JzID0gW3sKICAgICAgdGl0bGU6ICdBZGFwdGVyIEVycm9yJywKICAgICAgZGV0YWlsOiBtc2cudHJpbSgpLAogICAgICBzdGF0dXM6IHN0YXR1cwogICAgfV07CiAgICByZXR1cm4gbmV3IF9lcnJvci5BYm9ydEVycm9yKGVycm9ycyk7CiAgfSAvL0Zyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yODA2MzQvZW5kc3dpdGgtaW4tamF2YXNjcmlwdAoKCiAgZnVuY3Rpb24gZW5kc1dpdGgoc3RyaW5nLCBzdWZmaXgpIHsKICAgIGlmICh0eXBlb2YgU3RyaW5nLnByb3RvdHlwZS5lbmRzV2l0aCAhPT0gJ2Z1bmN0aW9uJykgewogICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2Yoc3VmZml4LCBzdHJpbmcubGVuZ3RoIC0gc3VmZml4Lmxlbmd0aCkgIT09IC0xOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXgpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZmV0Y2hTdWNjZXNzSGFuZGxlcihhZGFwdGVyLCBwYXlsb2FkLCByZXNwb25zZSwgcmVxdWVzdERhdGEpIHsKICAgIHZhciByZXNwb25zZURhdGEgPSBmZXRjaFJlc3BvbnNlRGF0YShyZXNwb25zZSk7CiAgICByZXR1cm4gYWpheFN1Y2Nlc3MoYWRhcHRlciwgcGF5bG9hZCwgcmVxdWVzdERhdGEsIHJlc3BvbnNlRGF0YSk7CiAgfQoKICBmdW5jdGlvbiBmZXRjaEVycm9ySGFuZGxlcihhZGFwdGVyLCBwYXlsb2FkLCByZXNwb25zZSwgZXJyb3JUaHJvd24sIHJlcXVlc3REYXRhKSB7CiAgICB2YXIgcmVzcG9uc2VEYXRhID0gZmV0Y2hSZXNwb25zZURhdGEocmVzcG9uc2UpOwogICAgcmVzcG9uc2VEYXRhLmVycm9yVGhyb3duID0gZXJyb3JUaHJvd247CiAgICByZXR1cm4gYWpheEVycm9yKGFkYXB0ZXIsIHBheWxvYWQsIHJlcXVlc3REYXRhLCByZXNwb25zZURhdGEpOwogIH0KCiAgZnVuY3Rpb24gYWpheFN1Y2Nlc3NIYW5kbGVyKGFkYXB0ZXIsIHBheWxvYWQsIGpxWEhSLCByZXF1ZXN0RGF0YSkgewogICAgdmFyIHJlc3BvbnNlRGF0YSA9IGFqYXhSZXNwb25zZURhdGEoanFYSFIpOwogICAgcmV0dXJuIGFqYXhTdWNjZXNzKGFkYXB0ZXIsIHBheWxvYWQsIHJlcXVlc3REYXRhLCByZXNwb25zZURhdGEpOwogIH0KCiAgZnVuY3Rpb24gYWpheEVycm9ySGFuZGxlcihhZGFwdGVyLCBqcVhIUiwgZXJyb3JUaHJvd24sIHJlcXVlc3REYXRhKSB7CiAgICB2YXIgcmVzcG9uc2VEYXRhID0gYWpheFJlc3BvbnNlRGF0YShqcVhIUik7CiAgICByZXNwb25zZURhdGEuZXJyb3JUaHJvd24gPSBlcnJvclRocm93bjsKICAgIHZhciBwYXlsb2FkID0gYWRhcHRlci5wYXJzZUVycm9yUmVzcG9uc2UoanFYSFIucmVzcG9uc2VUZXh0KTsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgdmFyIG1lc3NhZ2UgPSAiVGhlIHNlcnZlciByZXR1cm5lZCBhbiBlbXB0eSBzdHJpbmcgZm9yICIgKyByZXF1ZXN0RGF0YS5tZXRob2QgKyAiICIgKyByZXF1ZXN0RGF0YS51cmwgKyAiLCB3aGljaCBjYW5ub3QgYmUgcGFyc2VkIGludG8gYSB2YWxpZCBKU09OLiBSZXR1cm4gZWl0aGVyIG51bGwgb3Ige30uIjsKICAgICAgdmFyIHZhbGlkSlNPTlN0cmluZyA9ICEocmVzcG9uc2VEYXRhLnRleHRTdGF0dXMgPT09ICdwYXJzZXJlcnJvcicgJiYgcGF5bG9hZCA9PT0gJycpOwogICAgICAoZmFsc2UgJiYgRW1iZXIud2FybihtZXNzYWdlLCB2YWxpZEpTT05TdHJpbmcsIHsKICAgICAgICBpZDogJ2RzLmFkYXB0ZXIucmV0dXJuZWQtZW1wdHktc3RyaW5nLWFzLUpTT04nCiAgICAgIH0pKTsKICAgIH0KCiAgICByZXR1cm4gYWpheEVycm9yKGFkYXB0ZXIsIHBheWxvYWQsIHJlcXVlc3REYXRhLCByZXNwb25zZURhdGEpOwogIH0KCiAgZnVuY3Rpb24gZmV0Y2hSZXNwb25zZURhdGEocmVzcG9uc2UpIHsKICAgIHJldHVybiB7CiAgICAgIHN0YXR1czogcmVzcG9uc2Uuc3RhdHVzLAogICAgICB0ZXh0U3RhdHVzOiByZXNwb25zZS50ZXh0U3RhdHVzLAogICAgICBoZWFkZXJzOiBoZWFkZXJzVG9PYmplY3QocmVzcG9uc2UuaGVhZGVycykKICAgIH07CiAgfQoKICBmdW5jdGlvbiBhamF4UmVzcG9uc2VEYXRhKGpxWEhSKSB7CiAgICByZXR1cm4gewogICAgICBzdGF0dXM6IGpxWEhSLnN0YXR1cywKICAgICAgdGV4dFN0YXR1czoganFYSFIuc3RhdHVzVGV4dCwKICAgICAgaGVhZGVyczogKDAsIF9wcml2YXRlLnBhcnNlUmVzcG9uc2VIZWFkZXJzKShqcVhIUi5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKSkKICAgIH07CiAgfQoKICBmdW5jdGlvbiBoZWFkZXJzVG9PYmplY3QoaGVhZGVycykgewogICAgdmFyIGhlYWRlcnNPYmplY3QgPSB7fTsKCiAgICBpZiAoaGVhZGVycykgewogICAgICBoZWFkZXJzLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHsKICAgICAgICByZXR1cm4gaGVhZGVyc09iamVjdFtrZXldID0gdmFsdWU7CiAgICAgIH0pOwogICAgfQoKICAgIHJldHVybiBoZWFkZXJzT2JqZWN0OwogIH0KICAvKioKICAgKiBIZWxwZXIgZnVuY3Rpb24gdGhhdCB0cmFuc2xhdGVzIHRoZSBvcHRpb25zIHBhc3NlZCB0byBgalF1ZXJ5LmFqYXhgIGludG8gYSBmb3JtYXQgdGhhdCBgZmV0Y2hgIGV4cGVjdHMuCiAgICogQHBhcmFtIHtPYmplY3R9IF9vcHRpb25zCiAgICogQHBhcmFtIHtBZGFwdGVyfSBhZGFwdGVyCiAgICogQHJldHVybnMge09iamVjdH0KICAgKi8KCgogIGZ1bmN0aW9uIGZldGNoT3B0aW9ucyhvcHRpb25zLCBhZGFwdGVyKSB7CiAgICBvcHRpb25zLmNyZWRlbnRpYWxzID0gJ3NhbWUtb3JpZ2luJzsKCiAgICBpZiAob3B0aW9ucy5kYXRhKSB7CiAgICAgIC8vIEdFVCBhbmQgSEVBRCByZXF1ZXN0cyBjYW4ndCBoYXZlIGEgYGJvZHlgCiAgICAgIGlmIChvcHRpb25zLm1ldGhvZCA9PT0gJ0dFVCcgfHwgb3B0aW9ucy5tZXRob2QgPT09ICdIRUFEJykgewogICAgICAgIC8vIElmIG5vIG9wdGlvbnMgYXJlIHBhc3NlZCwgRW1iZXIgRGF0YSBzZXRzIGBkYXRhYCB0byBhbiBlbXB0eSBvYmplY3QsIHdoaWNoIHdlIHRlc3QgZm9yLgogICAgICAgIGlmIChPYmplY3Qua2V5cyhvcHRpb25zLmRhdGEpLmxlbmd0aCkgewogICAgICAgICAgLy8gVGVzdCBpZiB0aGVyZSBhcmUgYWxyZWFkeSBxdWVyeSBwYXJhbXMgaW4gdGhlIHVybCAobWltaWNzIGpRdWV5LmFqYXgpLgogICAgICAgICAgdmFyIHF1ZXJ5UGFyYW1EZWxpbWl0ZXIgPSBvcHRpb25zLnVybC5pbmRleE9mKCc/JykgPiAtMSA/ICcmJyA6ICc/JzsKICAgICAgICAgIG9wdGlvbnMudXJsICs9ICIiICsgcXVlcnlQYXJhbURlbGltaXRlciArICgwLCBfcHJpdmF0ZS5zZXJpYWxpemVRdWVyeVBhcmFtcykob3B0aW9ucy5kYXRhKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gTk9URTogYSByZXF1ZXN0J3MgYm9keSBjYW5ub3QgYmUgYW4gb2JqZWN0LCBzbyB3ZSBzdHJpbmdpZnkgaXQgaWYgaXQgaXMuCiAgICAgICAgLy8gSlNPTi5zdHJpbmdpZnkgcmVtb3ZlcyBrZXlzIHdpdGggdmFsdWVzIG9mIGB1bmRlZmluZWRgIChtaW1pY3MgalF1ZXJ5LmFqYXgpLgogICAgICAgIC8vIElmIHRoZSBkYXRhIGlzIG5vdCBhIFBPSk8gKGl0J3MgYSBTdHJpbmcsIEZvcm1EYXRhLCBldGMpLCB3ZSBqdXN0IHNldCBpdC4KICAgICAgICAvLyBJZiB0aGUgZGF0YSBpcyBhIHN0cmluZywgd2UgYXNzdW1lIGl0J3MgYSBzdHJpbmdpZmllZCBvYmplY3QuCgogICAgICAgIC8qIFdlIGNoZWNrIGZvciBPYmplY3RzIHRoaXMgd2F5IGJlY2F1c2Ugd2Ugd2FudCB0aGUgbG9naWMgaW5zaWRlIHRoZSBjb25zZXF1ZW50IHRvIHJ1bgogICAgICAgICAqIGlmIGBvcHRpb25zLmRhdGFgIGlzIGEgUE9KTywgbm90IGlmIGl0IGlzIGEgZGF0YSBzdHJ1Y3R1cmUgd2hvc2UgYHR5cGVvZmAgcmV0dXJucyAib2JqZWN0IgogICAgICAgICAqIHdoZW4gaXQncyBub3QgKEFycmF5LCBGb3JtRGF0YSwgZXRjKS4gVGhlIHJlYXNvbiB3ZSBkb24ndCB1c2UgYG9wdGlvbnMuZGF0YS5jb25zdHJ1Y3RvcmAKICAgICAgICAgKiB0byBjaGVjayBpcyBpbiBjYXNlIGBkYXRhYCBpcyBhbiBvYmplY3Qgd2l0aCBubyBwcm90b3R5cGUgKGUuZy4gY3JlYXRlZCB3aXRoIG51bGwpLgogICAgICAgICAqLwogICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob3B0aW9ucy5kYXRhKSA9PT0gJ1tvYmplY3QgT2JqZWN0XScpIHsKICAgICAgICAgIG9wdGlvbnMuYm9keSA9IEpTT04uc3RyaW5naWZ5KG9wdGlvbnMuZGF0YSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG9wdGlvbnMuYm9keSA9IG9wdGlvbnMuZGF0YTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gb3B0aW9uczsKICB9CgogIGZ1bmN0aW9uIF9hamF4T3B0aW9ucyhvcHRpb25zLCBhZGFwdGVyKSB7CiAgICBvcHRpb25zLmRhdGFUeXBlID0gJ2pzb24nOwogICAgb3B0aW9ucy5jb250ZXh0ID0gYWRhcHRlcjsKCiAgICBpZiAob3B0aW9ucy5kYXRhICYmIG9wdGlvbnMudHlwZSAhPT0gJ0dFVCcpIHsKICAgICAgb3B0aW9ucy5kYXRhID0gSlNPTi5zdHJpbmdpZnkob3B0aW9ucy5kYXRhKTsKICAgIH0KCiAgICBvcHRpb25zLmJlZm9yZVNlbmQgPSBmdW5jdGlvbiAoeGhyKSB7CiAgICAgIE9iamVjdC5rZXlzKG9wdGlvbnMuaGVhZGVycykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgcmV0dXJuIHhoci5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgb3B0aW9ucy5oZWFkZXJzW2tleV0pOwogICAgICB9KTsKICAgIH07CgogICAgcmV0dXJuIG9wdGlvbnM7CiAgfQoKICB2YXIgX2RlZmF1bHQgPSBSRVNUQWRhcHRlcjsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwo7ZGVmaW5lKCJAZW1iZXItZGF0YS9jYW5hcnktZmVhdHVyZXMvZGVmYXVsdC1mZWF0dXJlcyIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9jYW5hcnktZmVhdHVyZXMKICAqLwoKICAvKgogICAgVGhpcyBsaXN0IG9mIGZlYXR1cmVzIGlzIHVzZWQgYm90aCBhdCBidWlsZCB0aW1lIChieSBgQGVtYmVyLWRhdGEvcHJpdmF0ZS1idWlsZC1pbmZyYWApCiAgICBhbmQgYXQgcnVudGltZSAoYnkgYEBlbWJlci1kYXRhL2NhbmFyeS1mZWF0dXJlc2ApLgogIAogICAgVGhlIHZhbGlkIHZhbHVlcyBhcmU6CiAgCiAgICAtIHRydWUgLSBUaGUgZmVhdHVyZSBpcyBlbmFibGVkIGF0IGFsbCB0aW1lcywgYW5kIGNhbm5vdCBiZSBkaXNhYmxlZC4KICAgIC0gZmFsc2UgLSBUaGUgZmVhdHVyZSBpcyBkaXNhYmxlZCBhdCBhbGwgdGltZXMsIGFuZCBjYW5ub3QgYmUgZW5hYmxlZC4KICAgIC0gbnVsbCAtIFRoZSBmZWF0dXJlIGlzIGRpc2FibGVkIGJ5IGRlZmF1bHQsIGJ1dCBjYW4gYmUgZW5hYmxlZCBhdCBydW50aW1lIHZpYSBgRW1iZXJEYXRhRU5WYC4KICAqLwogIHZhciBfZGVmYXVsdCA9IHsKICAgIFNBTVBMRV9GRUFUVVJFX0ZMQUc6IG51bGwsCiAgICBSRUNPUkRfREFUQV9FUlJPUlM6IG51bGwsCiAgICBSRUNPUkRfREFUQV9TVEFURTogbnVsbCwKICAgIElERU5USUZJRVJTOiB0cnVlLAogICAgUkVRVUVTVF9TRVJWSUNFOiBudWxsLAogICAgQ1VTVE9NX01PREVMX0NMQVNTOiBudWxsLAogICAgRlVMTF9MSU5LU19PTl9SRUxBVElPTlNISVBTOiBudWxsCiAgfTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7Cn0pOwo7ZGVmaW5lKCJAZW1iZXItZGF0YS9jYW5hcnktZmVhdHVyZXMvaW5kZXgiLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvY2FuYXJ5LWZlYXR1cmVzL2RlZmF1bHQtZmVhdHVyZXMiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZGVmYXVsdEZlYXR1cmVzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5GVUxMX0xJTktTX09OX1JFTEFUSU9OU0hJUFMgPSBfZXhwb3J0cy5DVVNUT01fTU9ERUxfQ0xBU1MgPSBfZXhwb3J0cy5JREVOVElGSUVSUyA9IF9leHBvcnRzLlJFUVVFU1RfU0VSVklDRSA9IF9leHBvcnRzLlJFQ09SRF9EQVRBX1NUQVRFID0gX2V4cG9ydHMuUkVDT1JEX0RBVEFfRVJST1JTID0gX2V4cG9ydHMuU0FNUExFX0ZFQVRVUkVfRkxBRyA9IF9leHBvcnRzLkZFQVRVUkVTID0gdm9pZCAwOwoKICBmdW5jdGlvbiBfdHlwZW9mKG9iaikgeyBpZiAodHlwZW9mIFN5bWJvbCA9PT0gImZ1bmN0aW9uIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSAic3ltYm9sIikgeyBfdHlwZW9mID0gZnVuY3Rpb24gX3R5cGVvZihvYmopIHsgcmV0dXJuIHR5cGVvZiBvYmo7IH07IH0gZWxzZSB7IF90eXBlb2YgPSBmdW5jdGlvbiBfdHlwZW9mKG9iaikgeyByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09ICJmdW5jdGlvbiIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gInN5bWJvbCIgOiB0eXBlb2Ygb2JqOyB9OyB9IHJldHVybiBfdHlwZW9mKG9iaik7IH0KCiAgdmFyIEVOViA9ICh0eXBlb2YgRW1iZXJEYXRhRU5WID09PSAidW5kZWZpbmVkIiA/ICJ1bmRlZmluZWQiIDogX3R5cGVvZihFbWJlckRhdGFFTlYpKSA9PT0gJ29iamVjdCcgJiYgRW1iZXJEYXRhRU5WICE9PSBudWxsID8gRW1iZXJEYXRhRU5WIDoge307CgogIGZ1bmN0aW9uIGZlYXR1cmVWYWx1ZSh2YWx1ZSkgewogICAgaWYgKEVOVi5FTkFCTEVfT1BUSU9OQUxfRkVBVFVSRVMgJiYgdmFsdWUgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgcmV0dXJuIHZhbHVlOwogIH0KCiAgdmFyIEZFQVRVUkVTID0gRW1iZXIuYXNzaWduKHt9LCBfZGVmYXVsdEZlYXR1cmVzLmRlZmF1bHQsIEVOVi5GRUFUVVJFUyk7CiAgX2V4cG9ydHMuRkVBVFVSRVMgPSBGRUFUVVJFUzsKICB2YXIgU0FNUExFX0ZFQVRVUkVfRkxBRyA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5TQU1QTEVfRkVBVFVSRV9GTEFHKTsKICBfZXhwb3J0cy5TQU1QTEVfRkVBVFVSRV9GTEFHID0gU0FNUExFX0ZFQVRVUkVfRkxBRzsKICB2YXIgUkVDT1JEX0RBVEFfRVJST1JTID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLlJFQ09SRF9EQVRBX0VSUk9SUyk7CiAgX2V4cG9ydHMuUkVDT1JEX0RBVEFfRVJST1JTID0gUkVDT1JEX0RBVEFfRVJST1JTOwogIHZhciBSRUNPUkRfREFUQV9TVEFURSA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5SRUNPUkRfREFUQV9TVEFURSk7CiAgX2V4cG9ydHMuUkVDT1JEX0RBVEFfU1RBVEUgPSBSRUNPUkRfREFUQV9TVEFURTsKICB2YXIgUkVRVUVTVF9TRVJWSUNFID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLlJFUVVFU1RfU0VSVklDRSk7CiAgX2V4cG9ydHMuUkVRVUVTVF9TRVJWSUNFID0gUkVRVUVTVF9TRVJWSUNFOwogIHZhciBJREVOVElGSUVSUyA9IGZlYXR1cmVWYWx1ZShGRUFUVVJFUy5JREVOVElGSUVSUyk7CiAgX2V4cG9ydHMuSURFTlRJRklFUlMgPSBJREVOVElGSUVSUzsKICB2YXIgQ1VTVE9NX01PREVMX0NMQVNTID0gZmVhdHVyZVZhbHVlKEZFQVRVUkVTLkNVU1RPTV9NT0RFTF9DTEFTUyk7CiAgX2V4cG9ydHMuQ1VTVE9NX01PREVMX0NMQVNTID0gQ1VTVE9NX01PREVMX0NMQVNTOwogIHZhciBGVUxMX0xJTktTX09OX1JFTEFUSU9OU0hJUFMgPSBmZWF0dXJlVmFsdWUoRkVBVFVSRVMuRlVMTF9MSU5LU19PTl9SRUxBVElPTlNISVBTKTsKICBfZXhwb3J0cy5GVUxMX0xJTktTX09OX1JFTEFUSU9OU0hJUFMgPSBGVUxMX0xJTktTX09OX1JFTEFUSU9OU0hJUFM7Cn0pOwo7ZGVmaW5lKCJAZW1iZXItZGF0YS9kZWJ1Zy9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9kZWJ1Zy9zZXR1cCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9zZXR1cCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDsKCiAgLyoqCiAgICBJbXBsZW1lbnRzIGBAZW1iZXIvZGVidWcvZGF0YS1hZGFwdGVyYCB3aXRoIGZvciBFbWJlckRhdGEKICAgIGludGVncmF0aW9uIHdpdGggdGhlIGVtYmVyLWluc3BlY3Rvci4KICAKICAgIEBjbGFzcyBJbnNwZWN0b3JEZWJ1Z0FkYXB0ZXIKICAgIEBleHRlbmRzIERhdGFBZGFwdGVyCiAgICBAcHJpdmF0ZQogICovCiAgdmFyIF9kZWZhdWx0ID0gRW1iZXIuRGF0YUFkYXB0ZXIuZXh0ZW5kKHsKICAgIHN0b3JlOiBFbWJlci5pbmplY3Quc2VydmljZSgnc3RvcmUnKSwKCiAgICAvKioKICAgICAgU3BlY2lmaWVzIGhvdyByZWNvcmRzIGNhbiBiZSBmaWx0ZXJlZCBiYXNlZCBvbiB0aGUgc3RhdGUgb2YgdGhlIHJlY29yZAogICAgICBSZWNvcmRzIHJldHVybmVkIHdpbGwgbmVlZCB0byBoYXZlIGEgYGZpbHRlclZhbHVlc2AKICAgICAgcHJvcGVydHkgd2l0aCBhIGtleSBmb3IgZXZlcnkgbmFtZSBpbiB0aGUgcmV0dXJuZWQgYXJyYXkKICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBnZXRGaWx0ZXJzCiAgICAgIEByZXR1cm4ge0FycmF5fSBMaXN0IG9mIG9iamVjdHMgZGVmaW5pbmcgZmlsdGVycwogICAgICAgVGhlIG9iamVjdCBzaG91bGQgaGF2ZSBhIGBuYW1lYCBhbmQgYGRlc2NgIHByb3BlcnR5CiAgICAqLwogICAgZ2V0RmlsdGVyczogZnVuY3Rpb24gZ2V0RmlsdGVycygpIHsKICAgICAgcmV0dXJuIFt7CiAgICAgICAgbmFtZTogJ2lzTmV3JywKICAgICAgICBkZXNjOiAnTmV3JwogICAgICB9LCB7CiAgICAgICAgbmFtZTogJ2lzTW9kaWZpZWQnLAogICAgICAgIGRlc2M6ICdNb2RpZmllZCcKICAgICAgfSwgewogICAgICAgIG5hbWU6ICdpc0NsZWFuJywKICAgICAgICBkZXNjOiAnQ2xlYW4nCiAgICAgIH1dOwogICAgfSwKICAgIF9uYW1lVG9DbGFzczogZnVuY3Rpb24gX25hbWVUb0NsYXNzKHR5cGUpIHsKICAgICAgcmV0dXJuIEVtYmVyLmdldCh0aGlzLCAnc3RvcmUnKS5tb2RlbEZvcih0eXBlKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEZldGNoIHRoZSBtb2RlbCB0eXBlcyBhbmQgb2JzZXJ2ZSB0aGVtIGZvciBjaGFuZ2VzLgogICAgICBNYWludGFpbnMgdGhlIGxpc3Qgb2YgbW9kZWwgdHlwZXMgd2l0aG91dCBuZWVkaW5nIHRoZSBNb2RlbCBwYWNrYWdlIGZvciBkZXRlY3Rpb24uCiAgICAgIEBwdWJsaWMKICAgICAgQG1ldGhvZCB3YXRjaE1vZGVsVHlwZXMKICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gdHlwZXNBZGRlZCBDYWxsYmFjayB0byBjYWxsIHRvIGFkZCB0eXBlcy4KICAgICAgVGFrZXMgYW4gYXJyYXkgb2Ygb2JqZWN0cyBjb250YWluaW5nIHdyYXBwZWQgdHlwZXMgKHJldHVybmVkIGZyb20gYHdyYXBNb2RlbFR5cGVgKS4KICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gdHlwZXNVcGRhdGVkIENhbGxiYWNrIHRvIGNhbGwgd2hlbiBhIHR5cGUgaGFzIGNoYW5nZWQuCiAgICAgIFRha2VzIGFuIGFycmF5IG9mIG9iamVjdHMgY29udGFpbmluZyB3cmFwcGVkIHR5cGVzLgogICAgICBAcmV0dXJuIHtGdW5jdGlvbn0gTWV0aG9kIHRvIGNhbGwgdG8gcmVtb3ZlIGFsbCBvYnNlcnZlcnMKICAgICovCiAgICB3YXRjaE1vZGVsVHlwZXM6IGZ1bmN0aW9uIHdhdGNoTW9kZWxUeXBlcyh0eXBlc0FkZGVkLCB0eXBlc1VwZGF0ZWQpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHZhciBzdG9yZSA9IEVtYmVyLmdldCh0aGlzLCAnc3RvcmUnKTsKICAgICAgdmFyIF9fY3JlYXRlUmVjb3JkRGF0YSA9IHN0b3JlLl9jcmVhdGVSZWNvcmREYXRhOwogICAgICB2YXIgX3JlbGVhc2VNZXRob2RzID0gW107CiAgICAgIHZhciBkaXNjb3ZlcmVkVHlwZXMgPSAoMCwgX3NldHVwLnR5cGVzTWFwRm9yKShzdG9yZSk7IC8vIEFkZCBhbnkgbW9kZWxzIHRoYXQgd2VyZSBhZGRlZCBkdXJpbmcgaW5pdGlhbGl6YXRpb24gb2YgdGhlIGFwcCwgYmVmb3JlIHRoZSBpbnNwZWN0b3Igd2FzIG9wZW5lZAoKICAgICAgZGlzY292ZXJlZFR5cGVzLmZvckVhY2goZnVuY3Rpb24gKF8sIHR5cGUpIHsKICAgICAgICBfdGhpcy53YXRjaFR5cGVJZlVuc2VlbihzdG9yZSwgZGlzY292ZXJlZFR5cGVzLCB0eXBlLCB0eXBlc0FkZGVkLCB0eXBlc1VwZGF0ZWQsIF9yZWxlYXNlTWV0aG9kcyk7CiAgICAgIH0pOyAvLyBPdmVyd3JpdGUgX2NyZWF0ZVJlY29yZERhdGEgc28gbmV3bHkgYWRkZWQgbW9kZWxzIHdpbGwgZ2V0IGFkZGVkIHRvIHRoZSBsaXN0CgogICAgICBzdG9yZS5fY3JlYXRlUmVjb3JkRGF0YSA9IGZ1bmN0aW9uIChpZGVudGlmaWVyKSB7CiAgICAgICAgX3RoaXMud2F0Y2hUeXBlSWZVbnNlZW4oc3RvcmUsIGRpc2NvdmVyZWRUeXBlcywgaWRlbnRpZmllci50eXBlLCB0eXBlc0FkZGVkLCB0eXBlc1VwZGF0ZWQsIF9yZWxlYXNlTWV0aG9kcyk7CgogICAgICAgIHJldHVybiBfX2NyZWF0ZVJlY29yZERhdGEuY2FsbChzdG9yZSwgaWRlbnRpZmllcik7CiAgICAgIH07CgogICAgICB2YXIgcmVsZWFzZSA9IGZ1bmN0aW9uIHJlbGVhc2UoKSB7CiAgICAgICAgX3JlbGVhc2VNZXRob2RzLmZvckVhY2goZnVuY3Rpb24gKGZuKSB7CiAgICAgICAgICByZXR1cm4gZm4oKTsKICAgICAgICB9KTsKCiAgICAgICAgc3RvcmUuX2NyZWF0ZVJlY29yZERhdGEgPSBfX2NyZWF0ZVJlY29yZERhdGE7IC8vIHJlc2V0IHRoZSBsaXN0IHNvIHRoZSBtb2RlbHMgY2FuIGJlIGFkZGVkIGlmIHRoZSBpbnNwZWN0b3IgaXMgcmUtb3BlbmVkCiAgICAgICAgLy8gdGhlIGVudHJpZXMgYXJlIHNldCB0byBmYWxzZSBpbnN0ZWFkIG9mIHJlbW92ZWQsIHNpbmNlIHRoZSBtb2RlbHMgc3RpbGwgZXhpc3QgaW4gdGhlIGFwcAogICAgICAgIC8vIHdlIGp1c3QgbmVlZCB0aGUgaW5zcGVjdG9yIHRvIGJlY29tZSBhd2FyZSBvZiB0aGVtCgogICAgICAgIGRpc2NvdmVyZWRUeXBlcy5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7CiAgICAgICAgICBkaXNjb3ZlcmVkVHlwZXMuc2V0KGtleSwgZmFsc2UpOwogICAgICAgIH0pOwoKICAgICAgICBfdGhpcy5yZWxlYXNlTWV0aG9kcy5yZW1vdmVPYmplY3QocmVsZWFzZSk7CiAgICAgIH07CgogICAgICB0aGlzLnJlbGVhc2VNZXRob2RzLnB1c2hPYmplY3QocmVsZWFzZSk7CiAgICAgIHJldHVybiByZWxlYXNlOwogICAgfSwKCiAgICAvKioKICAgICAqIExvb3Agb3ZlciB0aGUgZGlzY292ZXJlZCB0eXBlcyBhbmQgdXNlIHRoZSBjYWxsYmFja3MgZnJvbSB3YXRjaE1vZGVsVHlwZXMgdG8gbm90aWZ5CiAgICAgKiB0aGUgY29uc3VtZXIgb2YgdGhpcyBhZGFwdGVyIGFib3V0IHRoZSBtZG9lbHMuCiAgICAgKgogICAgICogQHBhcmFtIHtzdG9yZX0gc3RvcmUKICAgICAqIEBwYXJhbSB7TWFwfSBkaXNjb3ZlcmVkVHlwZXMKICAgICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlCiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB0eXBlc0FkZGVkCiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB0eXBlc1VwZGF0ZWQKICAgICAqIEBwYXJhbSB7QXJyYXl9IHJlbGVhc2VNZXRob2RzCiAgICAgKi8KICAgIHdhdGNoVHlwZUlmVW5zZWVuOiBmdW5jdGlvbiB3YXRjaFR5cGVJZlVuc2VlbihzdG9yZSwgZGlzY292ZXJlZFR5cGVzLCB0eXBlLCB0eXBlc0FkZGVkLCB0eXBlc1VwZGF0ZWQsIHJlbGVhc2VNZXRob2RzKSB7CiAgICAgIGlmIChkaXNjb3ZlcmVkVHlwZXMuZ2V0KHR5cGUpICE9PSB0cnVlKSB7CiAgICAgICAgdmFyIGtsYXNzID0gc3RvcmUubW9kZWxGb3IodHlwZSk7CiAgICAgICAgdmFyIHdyYXBwZWQgPSB0aGlzLndyYXBNb2RlbFR5cGUoa2xhc3MsIHR5cGUpOwogICAgICAgIHJlbGVhc2VNZXRob2RzLnB1c2godGhpcy5vYnNlcnZlTW9kZWxUeXBlKHR5cGUsIHR5cGVzVXBkYXRlZCkpOwogICAgICAgIHR5cGVzQWRkZWQoW3dyYXBwZWRdKTsKICAgICAgICBkaXNjb3ZlcmVkVHlwZXMuc2V0KHR5cGUsIHRydWUpOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBDcmVhdGVzIGEgaHVtYW4gcmVhZGFibGUgc3RyaW5nIHVzZWQgZm9yIGNvbHVtbiBoZWFkZXJzCiAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgY29sdW1uTmFtZVRvRGVzYwogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgYXR0cmlidXRlIG5hbWUKICAgICAgQHJldHVybiB7U3RyaW5nfSBIdW1hbiByZWFkYWJsZSBzdHJpbmcgYmFzZWQgb24gdGhlIGF0dHJpYnV0ZSBuYW1lCiAgICAqLwogICAgY29sdW1uTmFtZVRvRGVzYzogZnVuY3Rpb24gY29sdW1uTmFtZVRvRGVzYyhuYW1lKSB7CiAgICAgIHJldHVybiBFbWJlci5TdHJpbmcuY2FwaXRhbGl6ZShFbWJlci5TdHJpbmcudW5kZXJzY29yZShuYW1lKS5yZXBsYWNlKC9fL2csICcgJykudHJpbSgpKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEdldCB0aGUgY29sdW1ucyBmb3IgYSBnaXZlbiBtb2RlbCB0eXBlCiAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgY29sdW1uc0ZvclR5cGUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZUNsYXNzCiAgICAgIEByZXR1cm4ge0FycmF5fSBBbiBhcnJheSBvZiBjb2x1bW5zIG9mIHRoZSBmb2xsb3dpbmcgZm9ybWF0OgogICAgICAgbmFtZToge1N0cmluZ30gVGhlIG5hbWUgb2YgdGhlIGNvbHVtbgogICAgICAgZGVzYzoge1N0cmluZ30gSHVtYW5pemVkIGRlc2NyaXB0aW9uICh3aGF0IHdvdWxkIHNob3cgaW4gYSB0YWJsZSBjb2x1bW4gbmFtZSkKICAgICovCiAgICBjb2x1bW5zRm9yVHlwZTogZnVuY3Rpb24gY29sdW1uc0ZvclR5cGUodHlwZUNsYXNzKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgdmFyIGNvbHVtbnMgPSBbewogICAgICAgIG5hbWU6ICdpZCcsCiAgICAgICAgZGVzYzogJ0lkJwogICAgICB9XTsKICAgICAgdmFyIGNvdW50ID0gMDsKICAgICAgdmFyIHNlbGYgPSB0aGlzOwogICAgICBFbWJlci5nZXQodHlwZUNsYXNzLCAnYXR0cmlidXRlcycpLmZvckVhY2goZnVuY3Rpb24gKG1ldGEsIG5hbWUpIHsKICAgICAgICBpZiAoY291bnQrKyA+IHNlbGYuYXR0cmlidXRlTGltaXQpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CgogICAgICAgIHZhciBkZXNjID0gX3RoaXMyLmNvbHVtbk5hbWVUb0Rlc2MobmFtZSk7CgogICAgICAgIGNvbHVtbnMucHVzaCh7CiAgICAgICAgICBuYW1lOiBuYW1lLAogICAgICAgICAgZGVzYzogZGVzYwogICAgICAgIH0pOwogICAgICB9KTsKICAgICAgcmV0dXJuIGNvbHVtbnM7CiAgICB9LAoKICAgIC8qKgogICAgICBGZXRjaGVzIGFsbCBsb2FkZWQgcmVjb3JkcyBmb3IgYSBnaXZlbiB0eXBlCiAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZ2V0UmVjb3JkcwogICAgICBAcGFyYW0ge01vZGVsfSBtb2RlbENsYXNzIG9mIHRoZSByZWNvcmQKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZSBvZiB0aGUgcmVjb3JkCiAgICAgIEByZXR1cm4ge0FycmF5fSBBbiBhcnJheSBvZiBNb2RlbCByZWNvcmRzCiAgICAgICBUaGlzIGFycmF5IHdpbGwgYmUgb2JzZXJ2ZWQgZm9yIGNoYW5nZXMsCiAgICAgICBzbyBpdCBzaG91bGQgdXBkYXRlIHdoZW4gbmV3IHJlY29yZHMgYXJlIGFkZGVkL3JlbW92ZWQKICAgICovCiAgICBnZXRSZWNvcmRzOiBmdW5jdGlvbiBnZXRSZWNvcmRzKG1vZGVsQ2xhc3MsIG1vZGVsTmFtZSkgewogICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHsKICAgICAgICAvLyBMZWdhY3kgRW1iZXIuanMgPCAxLjEzIHN1cHBvcnQKICAgICAgICB2YXIgY29udGFpbmVyS2V5ID0gbW9kZWxDbGFzcy5fZGVidWdDb250YWluZXJLZXk7CgogICAgICAgIGlmIChjb250YWluZXJLZXkpIHsKICAgICAgICAgIHZhciBtYXRjaCA9IGNvbnRhaW5lcktleS5tYXRjaCgvbW9kZWw6KC4qKS8pOwoKICAgICAgICAgIGlmIChtYXRjaCAhPT0gbnVsbCkgewogICAgICAgICAgICBtb2RlbE5hbWUgPSBtYXRjaFsxXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIChmYWxzZSAmJiAhKCEhbW9kZWxOYW1lKSAmJiBFbWJlci5hc3NlcnQoJ0Nhbm5vdCBmaW5kIG1vZGVsIG5hbWUuIFBsZWFzZSB1cGdyYWRlIHRvIEVtYmVyLmpzID49IDEuMTMgZm9yIEVtYmVyIEluc3BlY3RvciBzdXBwb3J0JywgISFtb2RlbE5hbWUpKTsKICAgICAgcmV0dXJuIHRoaXMuZ2V0KCdzdG9yZScpLnBlZWtBbGwobW9kZWxOYW1lKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEdldHMgdGhlIHZhbHVlcyBmb3IgZWFjaCBjb2x1bW4KICAgICAgVGhpcyBpcyB0aGUgYXR0cmlidXRlIHZhbHVlcyBmb3IgYSBnaXZlbiByZWNvcmQKICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBnZXRSZWNvcmRDb2x1bW5WYWx1ZXMKICAgICAgQHBhcmFtIHtNb2RlbH0gcmVjb3JkIHRvIGdldCB2YWx1ZXMgZnJvbQogICAgICBAcmV0dXJuIHtPYmplY3R9IEtleXMgc2hvdWxkIG1hdGNoIGNvbHVtbiBuYW1lcyBkZWZpbmVkIGJ5IHRoZSBtb2RlbCB0eXBlCiAgICAqLwogICAgZ2V0UmVjb3JkQ29sdW1uVmFsdWVzOiBmdW5jdGlvbiBnZXRSZWNvcmRDb2x1bW5WYWx1ZXMocmVjb3JkKSB7CiAgICAgIHZhciBfdGhpczMgPSB0aGlzOwoKICAgICAgdmFyIGNvdW50ID0gMDsKICAgICAgdmFyIGNvbHVtblZhbHVlcyA9IHsKICAgICAgICBpZDogRW1iZXIuZ2V0KHJlY29yZCwgJ2lkJykKICAgICAgfTsKICAgICAgcmVjb3JkLmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24gKGtleSkgewogICAgICAgIGlmIChjb3VudCsrID4gX3RoaXMzLmF0dHJpYnV0ZUxpbWl0KSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICBjb2x1bW5WYWx1ZXNba2V5XSA9IEVtYmVyLmdldChyZWNvcmQsIGtleSk7CiAgICAgIH0pOwogICAgICByZXR1cm4gY29sdW1uVmFsdWVzOwogICAgfSwKCiAgICAvKioKICAgICAgUmV0dXJucyBrZXl3b3JkcyB0byBtYXRjaCB3aGVuIHNlYXJjaGluZyByZWNvcmRzCiAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZ2V0UmVjb3JkS2V5d29yZHMKICAgICAgQHBhcmFtIHtNb2RlbH0gcmVjb3JkCiAgICAgIEByZXR1cm4ge0FycmF5fSBSZWxldmFudCBrZXl3b3JkcyBmb3Igc2VhcmNoIGJhc2VkIG9uIHRoZSByZWNvcmQncyBhdHRyaWJ1dGUgdmFsdWVzCiAgICAqLwogICAgZ2V0UmVjb3JkS2V5d29yZHM6IGZ1bmN0aW9uIGdldFJlY29yZEtleXdvcmRzKHJlY29yZCkgewogICAgICB2YXIga2V5d29yZHMgPSBbXTsKICAgICAgdmFyIGtleXMgPSBFbWJlci5BKFsnaWQnXSk7CiAgICAgIHJlY29yZC5lYWNoQXR0cmlidXRlKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICByZXR1cm4ga2V5cy5wdXNoKGtleSk7CiAgICAgIH0pOwogICAgICBrZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgIHJldHVybiBrZXl3b3Jkcy5wdXNoKEVtYmVyLmdldChyZWNvcmQsIGtleSkpOwogICAgICB9KTsKICAgICAgcmV0dXJuIGtleXdvcmRzOwogICAgfSwKCiAgICAvKioKICAgICAgUmV0dXJucyB0aGUgdmFsdWVzIG9mIGZpbHRlcnMgZGVmaW5lZCBieSBgZ2V0RmlsdGVyc2AKICAgICAgVGhlc2UgcmVmbGVjdCB0aGUgc3RhdGUgb2YgdGhlIHJlY29yZAogICAgICBAcHJpdmF0ZQogICAgICBAbWV0aG9kIGdldFJlY29yZEZpbHRlclZhbHVlcwogICAgICBAcGFyYW0ge01vZGVsfSByZWNvcmQKICAgICAgQHJldHVybiB7T2JqZWN0fSBUaGUgcmVjb3JkIHN0YXRlIGZpbHRlciB2YWx1ZXMKICAgICovCiAgICBnZXRSZWNvcmRGaWx0ZXJWYWx1ZXM6IGZ1bmN0aW9uIGdldFJlY29yZEZpbHRlclZhbHVlcyhyZWNvcmQpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBpc05ldzogcmVjb3JkLmdldCgnaXNOZXcnKSwKICAgICAgICBpc01vZGlmaWVkOiByZWNvcmQuZ2V0KCdoYXNEaXJ0eUF0dHJpYnV0ZXMnKSAmJiAhcmVjb3JkLmdldCgnaXNOZXcnKSwKICAgICAgICBpc0NsZWFuOiAhcmVjb3JkLmdldCgnaGFzRGlydHlBdHRyaWJ1dGVzJykKICAgICAgfTsKICAgIH0sCgogICAgLyoqCiAgICAgIFJldHVybnMgYSBjb2xvciB0aGF0IHJlcHJlc2VudHMgdGhlIHJlY29yZCdzIHN0YXRlCiAgICAgIEBwcml2YXRlCiAgICAgIEBtZXRob2QgZ2V0UmVjb3JkQ29sb3IKICAgICAgQHBhcmFtIHtNb2RlbH0gcmVjb3JkCiAgICAgIEByZXR1cm4ge1N0cmluZ30gVGhlIHJlY29yZCBjb2xvcgogICAgICAgIFBvc3NpYmxlIG9wdGlvbnM6IGJsYWNrLCBibHVlLCBncmVlbgogICAgKi8KICAgIGdldFJlY29yZENvbG9yOiBmdW5jdGlvbiBnZXRSZWNvcmRDb2xvcihyZWNvcmQpIHsKICAgICAgdmFyIGNvbG9yID0gJ2JsYWNrJzsKCiAgICAgIGlmIChyZWNvcmQuZ2V0KCdpc05ldycpKSB7CiAgICAgICAgY29sb3IgPSAnZ3JlZW4nOwogICAgICB9IGVsc2UgaWYgKHJlY29yZC5nZXQoJ2hhc0RpcnR5QXR0cmlidXRlcycpKSB7CiAgICAgICAgY29sb3IgPSAnYmx1ZSc7CiAgICAgIH0KCiAgICAgIHJldHVybiBjb2xvcjsKICAgIH0sCgogICAgLyoqCiAgICAgIE9ic2VydmVzIGFsbCByZWxldmFudCBwcm9wZXJ0aWVzIGFuZCByZS1zZW5kcyB0aGUgd3JhcHBlZCByZWNvcmQKICAgICAgd2hlbiBhIGNoYW5nZSBvY2N1cnMKICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBvYnNlcnZlclJlY29yZAogICAgICBAcGFyYW0ge01vZGVsfSByZWNvcmQKICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gcmVjb3JkVXBkYXRlZCBDYWxsYmFjayB1c2VkIHRvIG5vdGlmeSBjaGFuZ2VzCiAgICAgIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgZnVuY3Rpb24gdG8gY2FsbCB0byByZW1vdmUgYWxsIG9ic2VydmVycwogICAgKi8KICAgIG9ic2VydmVSZWNvcmQ6IGZ1bmN0aW9uIG9ic2VydmVSZWNvcmQocmVjb3JkLCByZWNvcmRVcGRhdGVkKSB7CiAgICAgIHZhciByZWxlYXNlTWV0aG9kcyA9IEVtYmVyLkEoKTsKICAgICAgdmFyIGtleXNUb09ic2VydmUgPSBFbWJlci5BKFsnaWQnLCAnaXNOZXcnLCAnaGFzRGlydHlBdHRyaWJ1dGVzJ10pOwogICAgICByZWNvcmQuZWFjaEF0dHJpYnV0ZShmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgcmV0dXJuIGtleXNUb09ic2VydmUucHVzaChrZXkpOwogICAgICB9KTsKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzOwogICAgICBrZXlzVG9PYnNlcnZlLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgIHZhciBoYW5kbGVyID0gZnVuY3Rpb24gaGFuZGxlcigpIHsKICAgICAgICAgIHJlY29yZFVwZGF0ZWQoYWRhcHRlci53cmFwUmVjb3JkKHJlY29yZCkpOwogICAgICAgIH07CgogICAgICAgIEVtYmVyLmFkZE9ic2VydmVyKHJlY29yZCwga2V5LCBoYW5kbGVyKTsKICAgICAgICByZWxlYXNlTWV0aG9kcy5wdXNoKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIEVtYmVyLnJlbW92ZU9ic2VydmVyKHJlY29yZCwga2V5LCBoYW5kbGVyKTsKICAgICAgICB9KTsKICAgICAgfSk7CgogICAgICB2YXIgcmVsZWFzZSA9IGZ1bmN0aW9uIHJlbGVhc2UoKSB7CiAgICAgICAgcmVsZWFzZU1ldGhvZHMuZm9yRWFjaChmdW5jdGlvbiAoZm4pIHsKICAgICAgICAgIHJldHVybiBmbigpOwogICAgICAgIH0pOwogICAgICB9OwoKICAgICAgcmV0dXJuIHJlbGVhc2U7CiAgICB9CiAgfSk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CjtkZWZpbmUoIkBlbWJlci1kYXRhL2RlYnVnL3NldHVwIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3N0b3JlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3N0b3JlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy50eXBlc01hcEZvciA9IHR5cGVzTWFwRm9yOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CiAgdmFyIFN0b3JlVHlwZXNNYXAgPSBuZXcgV2Vha01hcCgpOwoKICBmdW5jdGlvbiB0eXBlc01hcEZvcihzdG9yZSkgewogICAgdmFyIHR5cGVzTWFwID0gU3RvcmVUeXBlc01hcC5nZXQoc3RvcmUpOwoKICAgIGlmICh0eXBlc01hcCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHR5cGVzTWFwID0gbmV3IE1hcCgpOwogICAgICBTdG9yZVR5cGVzTWFwLnNldChzdG9yZSwgdHlwZXNNYXApOwogICAgfQoKICAgIHJldHVybiB0eXBlc01hcDsKICB9IC8vIG92ZXJyaWRlIF9jcmVhdGVSZWNvcmREYXRhIHRvIGFkZCB0aGUga25vd24gbW9kZWxzIHRvIHRoZSB0eXBlc01hcAoKCiAgdmFyIF9fY3JlYXRlUmVjb3JkRGF0YSA9IF9zdG9yZS5kZWZhdWx0LnByb3RvdHlwZS5fY3JlYXRlUmVjb3JkRGF0YTsKCiAgX3N0b3JlLmRlZmF1bHQucHJvdG90eXBlLl9jcmVhdGVSZWNvcmREYXRhID0gZnVuY3Rpb24gKGlkZW50aWZpZXIpIHsKICAgIHZhciB0eXBlc01hcCA9IHR5cGVzTWFwRm9yKHRoaXMpOwoKICAgIGlmICghdHlwZXNNYXAuaGFzKGlkZW50aWZpZXIudHlwZSkpIHsKICAgICAgdHlwZXNNYXAuc2V0KGlkZW50aWZpZXIudHlwZSwgZmFsc2UpOwogICAgfQoKICAgIHJldHVybiBfX2NyZWF0ZVJlY29yZERhdGEuY2FsbCh0aGlzLCBpZGVudGlmaWVyKTsKICB9OwoKICB2YXIgX2RlZmF1bHQgPSB7CiAgICBuYW1lOiAnQGVtYmVyLWRhdGEvZGF0YS1hZGFwdGVyJywKICAgIGluaXRpYWxpemU6IGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7fQogIH07CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKO2RlZmluZSgnQGVtYmVyLWRhdGEvbW9kZWwvLXByaXZhdGUnLCBbJ2V4cG9ydHMnLCAnQGVtYmVyLWRhdGEvc3RvcmUvLXByaXZhdGUnLCAnQGVtYmVyLWRhdGEvY2FuYXJ5LWZlYXR1cmVzJywgJ0BlbWJlci1kYXRhL3N0b3JlJ10sIGZ1bmN0aW9uIChleHBvcnRzLCBQcml2YXRlLCBjYW5hcnlGZWF0dXJlcywgc3RvcmUpIHsgJ3VzZSBzdHJpY3QnOwoKICBmdW5jdGlvbiBpc0VsZW1lbnREZXNjcmlwdG9yKGFyZ3MpIHsKICAgIHZhciBtYXliZVRhcmdldCA9IGFyZ3NbMF0sCiAgICAgICAgbWF5YmVLZXkgPSBhcmdzWzFdLAogICAgICAgIG1heWJlRGVzYyA9IGFyZ3NbMl07CiAgICByZXR1cm4gKC8vIEVuc3VyZSB3ZSBoYXZlIHRoZSByaWdodCBudW1iZXIgb2YgYXJncwogICAgICBhcmdzLmxlbmd0aCA9PT0gMyAmJiAoIC8vIE1ha2Ugc3VyZSB0aGUgdGFyZ2V0IGlzIGEgY2xhc3Mgb3Igb2JqZWN0IChwcm90b3R5cGUpCiAgICAgIHR5cGVvZiBtYXliZVRhcmdldCA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgbWF5YmVUYXJnZXQgPT09ICdvYmplY3QnICYmIG1heWJlVGFyZ2V0ICE9PSBudWxsKSAmJiAvLyBNYWtlIHN1cmUgdGhlIGtleSBpcyBhIHN0cmluZwogICAgICB0eXBlb2YgbWF5YmVLZXkgPT09ICdzdHJpbmcnICYmICggLy8gTWFrZSBzdXJlIHRoZSBkZXNjcmlwdG9yIGlzIHRoZSByaWdodCBzaGFwZQogICAgICB0eXBlb2YgbWF5YmVEZXNjID09PSAnb2JqZWN0JyAmJiBtYXliZURlc2MgIT09IG51bGwgJiYgJ2VudW1lcmFibGUnIGluIG1heWJlRGVzYyAmJiAnY29uZmlndXJhYmxlJyBpbiBtYXliZURlc2MgfHwgLy8gVFMgY29tcGF0aWJpbGl0eQogICAgICBtYXliZURlc2MgPT09IHVuZGVmaW5lZCkKICAgICk7CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVkTWFjcm9XaXRoT3B0aW9uYWxQYXJhbXMoZm4pIHsKICAgIHsKICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgbWF5YmVEZXNjID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykgewogICAgICAgICAgbWF5YmVEZXNjW19rZXldID0gYXJndW1lbnRzW19rZXldOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGlzRWxlbWVudERlc2NyaXB0b3IobWF5YmVEZXNjKSA/IGZuKCkuYXBwbHkodm9pZCAwLCBtYXliZURlc2MpIDogZm4uYXBwbHkodm9pZCAwLCBtYXliZURlc2MpOwogICAgICB9OwogICAgfQogIH0KCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL21vZGVsCiAgKi8KCiAgZnVuY3Rpb24gZ2V0RGVmYXVsdFZhbHVlKHJlY29yZCwgb3B0aW9ucywga2V5KSB7CiAgICBpZiAodHlwZW9mIG9wdGlvbnMuZGVmYXVsdFZhbHVlID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIHJldHVybiBvcHRpb25zLmRlZmF1bHRWYWx1ZS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgfSBlbHNlIHsKICAgICAgdmFyIGRlZmF1bHRWYWx1ZSA9IG9wdGlvbnMuZGVmYXVsdFZhbHVlOwogICAgICByZXR1cm4gZGVmYXVsdFZhbHVlOwogICAgfQogIH0KCiAgZnVuY3Rpb24gaGFzVmFsdWUoaW50ZXJuYWxNb2RlbCwga2V5KSB7CiAgICByZXR1cm4gUHJpdmF0ZS5yZWNvcmREYXRhRm9yKGludGVybmFsTW9kZWwpLmhhc0F0dHIoa2V5KTsKICB9CiAgLyoqCiAgICBgYXR0cmAgZGVmaW5lcyBhbiBhdHRyaWJ1dGUgb24gYSBbTW9kZWxdKC9lbWJlci1kYXRhL3JlbGVhc2UvY2xhc3Nlcy9Nb2RlbCkuCiAgICBCeSBkZWZhdWx0LCBhdHRyaWJ1dGVzIGFyZSBwYXNzZWQgdGhyb3VnaCBhcy1pcywgaG93ZXZlciB5b3UgY2FuIHNwZWNpZnkgYW4KICAgIG9wdGlvbmFsIHR5cGUgdG8gaGF2ZSB0aGUgdmFsdWUgYXV0b21hdGljYWxseSB0cmFuc2Zvcm1lZC4KICAgIEVtYmVyIERhdGEgc2hpcHMgd2l0aCBmb3VyIGJhc2ljIHRyYW5zZm9ybSB0eXBlczogYHN0cmluZ2AsIGBudW1iZXJgLAogICAgYGJvb2xlYW5gIGFuZCBgZGF0ZWAuIFlvdSBjYW4gZGVmaW5lIHlvdXIgb3duIHRyYW5zZm9ybXMgYnkgc3ViY2xhc3NpbmcKICAgIFtUcmFuc2Zvcm1dKC9lbWJlci1kYXRhL3JlbGVhc2UvY2xhc3Nlcy9UcmFuc2Zvcm0pLgoKICAgIE5vdGUgdGhhdCB5b3UgY2Fubm90IHVzZSBgYXR0cmAgdG8gZGVmaW5lIGFuIGF0dHJpYnV0ZSBvZiBgaWRgLgoKICAgIGBhdHRyYCB0YWtlcyBhbiBvcHRpb25hbCBoYXNoIGFzIGEgc2Vjb25kIHBhcmFtZXRlciwgY3VycmVudGx5CiAgICBzdXBwb3J0ZWQgb3B0aW9ucyBhcmU6CgogICAgLSBgZGVmYXVsdFZhbHVlYDogUGFzcyBhIHN0cmluZyBvciBhIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB0byBzZXQgdGhlIGF0dHJpYnV0ZQogICAgdG8gYSBkZWZhdWx0IHZhbHVlIGlmIG5vbmUgaXMgc3VwcGxpZWQuCgogICAgRXhhbXBsZQoKICAgIGBgYGFwcC9tb2RlbHMvdXNlci5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgdXNlcm5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICBlbWFpbDogYXR0cignc3RyaW5nJyksCiAgICAgIHZlcmlmaWVkOiBhdHRyKCdib29sZWFuJywgeyBkZWZhdWx0VmFsdWU6IGZhbHNlIH0pCiAgICB9KTsKICAgIGBgYAoKICAgIERlZmF1bHQgdmFsdWUgY2FuIGFsc28gYmUgYSBmdW5jdGlvbi4gVGhpcyBpcyB1c2VmdWwgaXQgeW91IHdhbnQgdG8gcmV0dXJuCiAgICBhIG5ldyBvYmplY3QgZm9yIGVhY2ggYXR0cmlidXRlLgoKICAgIGBgYGFwcC9tb2RlbHMvdXNlci5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgdXNlcm5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICBlbWFpbDogYXR0cignc3RyaW5nJyksCiAgICAgIHNldHRpbmdzOiBhdHRyKHsKICAgICAgICBkZWZhdWx0VmFsdWUoKSB7CiAgICAgICAgICByZXR1cm4ge307CiAgICAgICAgfQogICAgICB9KQogICAgfSk7CiAgICBgYGAKCiAgICBUaGUgYG9wdGlvbnNgIGhhc2ggaXMgcGFzc2VkIGFzIHNlY29uZCBhcmd1bWVudCB0byBhIHRyYW5zZm9ybXMnCiAgICBgc2VyaWFsaXplYCBhbmQgYGRlc2VyaWFsaXplYCBtZXRob2QuIFRoaXMgYWxsb3dzIHRvIGNvbmZpZ3VyZSBhCiAgICB0cmFuc2Zvcm1hdGlvbiBhbmQgYWRhcHQgdGhlIGNvcnJlc3BvbmRpbmcgdmFsdWUsIGJhc2VkIG9uIHRoZSBjb25maWc6CgogICAgYGBgYXBwL21vZGVscy9wb3N0LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICB0ZXh0OiBhdHRyKCd0ZXh0JywgewogICAgICAgIHVwcGVyY2FzZTogdHJ1ZQogICAgICB9KQogICAgfSk7CiAgICBgYGAKCiAgICBgYGBhcHAvdHJhbnNmb3Jtcy90ZXh0LmpzCiAgICBpbXBvcnQgVHJhbnNmb3JtIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvdHJhbnNmb3JtJzsKCiAgICBleHBvcnQgZGVmYXVsdCBUcmFuc2Zvcm0uZXh0ZW5kKHsKICAgICAgc2VyaWFsaXplKHZhbHVlLCBvcHRpb25zKSB7CiAgICAgICAgaWYgKG9wdGlvbnMudXBwZXJjYXNlKSB7CiAgICAgICAgICByZXR1cm4gdmFsdWUudG9VcHBlckNhc2UoKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgfSwKCiAgICAgIGRlc2VyaWFsaXplKHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICB9CiAgICB9KQogICAgYGBgCgogICAgQG1ldGhvZCBhdHRyCiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci1kYXRhL21vZGVsCiAgICBAcGFyYW0ge1N0cmluZ3xPYmplY3R9IHR5cGUgdGhlIGF0dHJpYnV0ZSB0eXBlCiAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBhIGhhc2ggb2Ygb3B0aW9ucwogICAgQHJldHVybiB7QXR0cmlidXRlfQogICovCgoKICBmdW5jdGlvbiBhdHRyKHR5cGUsIG9wdGlvbnMpIHsKICAgIGlmICh0eXBlb2YgdHlwZSA9PT0gJ29iamVjdCcpIHsKICAgICAgb3B0aW9ucyA9IHR5cGU7CiAgICAgIHR5cGUgPSB1bmRlZmluZWQ7CiAgICB9IGVsc2UgewogICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTsKICAgIH0KCiAgICB2YXIgbWV0YSA9IHsKICAgICAgdHlwZTogdHlwZSwKICAgICAgaXNBdHRyaWJ1dGU6IHRydWUsCiAgICAgIGtpbmQ6ICdhdHRyaWJ1dGUnLAogICAgICBvcHRpb25zOiBvcHRpb25zCiAgICB9OwogICAgcmV0dXJuIEVtYmVyLmNvbXB1dGVkKHsKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoa2V5KSB7CgogICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gdGhpcy5faW50ZXJuYWxNb2RlbDsKCiAgICAgICAgaWYgKGhhc1ZhbHVlKGludGVybmFsTW9kZWwsIGtleSkpIHsKICAgICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLmdldEF0dHJpYnV0ZVZhbHVlKGtleSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBnZXREZWZhdWx0VmFsdWUodGhpcywgb3B0aW9ucywga2V5KTsKICAgICAgICB9CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUpIHsKCiAgICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX0VSUk9SUykgewogICAgICAgICAgdmFyIG9sZFZhbHVlID0gdGhpcy5faW50ZXJuYWxNb2RlbC5fcmVjb3JkRGF0YS5nZXRBdHRyKGtleSk7CgogICAgICAgICAgaWYgKG9sZFZhbHVlICE9PSB2YWx1ZSkgewogICAgICAgICAgICB2YXIgZXJyb3JzID0gdGhpcy5nZXQoJ2Vycm9ycycpOwoKICAgICAgICAgICAgaWYgKGVycm9ycy5nZXQoa2V5KSkgewogICAgICAgICAgICAgIGVycm9ycy5yZW1vdmUoa2V5KTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdGhpcy5fbWFya0ludmFsaWRSZXF1ZXN0QXNDbGVhbigpOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMuX2ludGVybmFsTW9kZWwuc2V0RGlydHlBdHRyaWJ1dGUoa2V5LCB2YWx1ZSk7CiAgICAgIH0KICAgIH0pLm1ldGEobWV0YSk7CiAgfQoKICB2YXIgYXR0ciQxID0gY29tcHV0ZWRNYWNyb1dpdGhPcHRpb25hbFBhcmFtcyhhdHRyKTsKCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL21vZGVsCiAgKi8KCiAgLyoqCiAgICBgYmVsb25nc1RvYCBpcyB1c2VkIHRvIGRlZmluZSBPbmUtVG8tT25lIGFuZCBPbmUtVG8tTWFueQogICAgcmVsYXRpb25zaGlwcyBvbiBhIFtNb2RlbF0oL2VtYmVyLWRhdGEvcmVsZWFzZS9jbGFzc2VzL01vZGVsKS4KCgogICAgYGJlbG9uZ3NUb2AgdGFrZXMgYW4gb3B0aW9uYWwgaGFzaCBhcyBhIHNlY29uZCBwYXJhbWV0ZXIsIGN1cnJlbnRseQogICAgc3VwcG9ydGVkIG9wdGlvbnMgYXJlOgoKICAgIC0gYGFzeW5jYDogQSBib29sZWFuIHZhbHVlIHVzZWQgdG8gZXhwbGljaXRseSBkZWNsYXJlIHRoaXMgdG8gYmUgYW4gYXN5bmMgcmVsYXRpb25zaGlwLiBUaGUgZGVmYXVsdCBpcyB0cnVlLgogICAgLSBgaW52ZXJzZWA6IEEgc3RyaW5nIHVzZWQgdG8gaWRlbnRpZnkgdGhlIGludmVyc2UgcHJvcGVydHkgb24gYQogICAgICByZWxhdGVkIG1vZGVsIGluIGEgT25lLVRvLU1hbnkgcmVsYXRpb25zaGlwLiBTZWUgW0V4cGxpY2l0IEludmVyc2VzXSgjZXhwbGljaXQtaW52ZXJzZXMpCiAgICAtIGBwb2x5bW9ycGhpY2AgQSBib29sZWFuIHZhbHVlIHRvIG1hcmsgdGhlIHJlbGF0aW9uc2hpcCBhcyBwb2x5bW9ycGhpYwoKICAgICMjIyMgT25lLVRvLU9uZQogICAgVG8gZGVjbGFyZSBhIG9uZS10by1vbmUgcmVsYXRpb25zaGlwIGJldHdlZW4gdHdvIG1vZGVscywgdXNlCiAgICBgYmVsb25nc1RvYDoKCiAgICBgYGBhcHAvbW9kZWxzL3VzZXIuanMKICAgIGltcG9ydCBNb2RlbCwgeyBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgcHJvZmlsZTogYmVsb25nc1RvKCdwcm9maWxlJykKICAgIH0pOwogICAgYGBgCgogICAgYGBgYXBwL21vZGVscy9wcm9maWxlLmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHVzZXI6IGJlbG9uZ3NUbygndXNlcicpCiAgICB9KTsKICAgIGBgYAoKICAgICMjIyMgT25lLVRvLU1hbnkKICAgIFRvIGRlY2xhcmUgYSBvbmUtdG8tbWFueSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0d28gbW9kZWxzLCB1c2UKICAgIGBiZWxvbmdzVG9gIGluIGNvbWJpbmF0aW9uIHdpdGggYGhhc01hbnlgLCBsaWtlIHRoaXM6CgogICAgYGBgYXBwL21vZGVscy9wb3N0LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBjb21tZW50czogaGFzTWFueSgnY29tbWVudCcpCiAgICB9KTsKICAgIGBgYAoKICAgIGBgYGFwcC9tb2RlbHMvY29tbWVudC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBwb3N0OiBiZWxvbmdzVG8oJ3Bvc3QnKQogICAgfSk7CiAgICBgYGAKCiAgICBZb3UgY2FuIGF2b2lkIHBhc3NpbmcgYSBzdHJpbmcgYXMgdGhlIGZpcnN0IHBhcmFtZXRlci4gSW4gdGhhdCBjYXNlIEVtYmVyIERhdGEKICAgIHdpbGwgaW5mZXIgdGhlIHR5cGUgZnJvbSB0aGUga2V5IG5hbWUuCgogICAgYGBgYXBwL21vZGVscy9jb21tZW50LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHBvc3Q6IGJlbG9uZ3NUbygpCiAgICB9KTsKICAgIGBgYAoKICAgIHdpbGwgbG9va3VwIGZvciBhIFBvc3QgdHlwZS4KCiAgICAjIyMjIFN5bmMgcmVsYXRpb25zaGlwcwoKICAgIEVtYmVyIERhdGEgcmVzb2x2ZXMgc3luYyByZWxhdGlvbnNoaXBzIHdpdGggdGhlIHJlbGF0ZWQgcmVzb3VyY2VzCiAgICBhdmFpbGFibGUgaW4gaXRzIGxvY2FsIHN0b3JlLCBoZW5jZSBpdCBpcyBleHBlY3RlZCB0aGVzZSByZXNvdXJjZXMKICAgIHRvIGJlIGxvYWRlZCBiZWZvcmUgb3IgYWxvbmctc2lkZSB0aGUgcHJpbWFyeSByZXNvdXJjZS4KCiAgICBgYGBhcHAvbW9kZWxzL2NvbW1lbnQuanMKICAgIGltcG9ydCBNb2RlbCwgeyBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgcG9zdDogYmVsb25nc1RvKCdwb3N0JywgewogICAgICAgIGFzeW5jOiBmYWxzZQogICAgICB9KQogICAgfSk7CiAgICBgYGAKCiAgICBJbiBjb250cmFzdCB0byBhc3luYyByZWxhdGlvbnNoaXAsIGFjY2Vzc2luZyBhIHN5bmMgcmVsYXRpb25zaGlwCiAgICB3aWxsIGFsd2F5cyByZXR1cm4gdGhlIHJlY29yZCAoTW9kZWwgaW5zdGFuY2UpIGZvciB0aGUgZXhpc3RpbmcKICAgIGxvY2FsIHJlc291cmNlLCBvciBudWxsLiBCdXQgaXQgd2lsbCBlcnJvciBvbiBhY2Nlc3Mgd2hlbgogICAgYSByZWxhdGVkIHJlc291cmNlIGlzIGtub3duIHRvIGV4aXN0IGFuZCBpdCBoYXMgbm90IGJlZW4gbG9hZGVkLgoKICAgIGBgYAogICAgbGV0IHBvc3QgPSBjb21tZW50LmdldCgncG9zdCcpOwoKICAgIGBgYAoKICAgIEBtZXRob2QgYmVsb25nc1RvCiAgICBAcHVibGljCiAgICBAc3RhdGljCiAgICBAZm9yIEBlbWJlci1kYXRhL21vZGVsCiAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lIChvcHRpb25hbCkgdHlwZSBvZiB0aGUgcmVsYXRpb25zaGlwCiAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAob3B0aW9uYWwpIGEgaGFzaCBvZiBvcHRpb25zCiAgICBAcmV0dXJuIHtFbWJlci5jb21wdXRlZH0gcmVsYXRpb25zaGlwCiAgKi8KCiAgZnVuY3Rpb24gYmVsb25nc1RvKG1vZGVsTmFtZSwgb3B0aW9ucykgewogICAgdmFyIG9wdHMsIHVzZXJFbnRlcmVkTW9kZWxOYW1lOwoKICAgIGlmICh0eXBlb2YgbW9kZWxOYW1lID09PSAnb2JqZWN0JykgewogICAgICBvcHRzID0gbW9kZWxOYW1lOwogICAgICB1c2VyRW50ZXJlZE1vZGVsTmFtZSA9IHVuZGVmaW5lZDsKICAgIH0gZWxzZSB7CiAgICAgIG9wdHMgPSBvcHRpb25zOwogICAgICB1c2VyRW50ZXJlZE1vZGVsTmFtZSA9IG1vZGVsTmFtZTsKICAgIH0KCiAgICBpZiAodHlwZW9mIHVzZXJFbnRlcmVkTW9kZWxOYW1lID09PSAnc3RyaW5nJykgewogICAgICB1c2VyRW50ZXJlZE1vZGVsTmFtZSA9IHN0b3JlLm5vcm1hbGl6ZU1vZGVsTmFtZSh1c2VyRW50ZXJlZE1vZGVsTmFtZSk7CiAgICB9CiAgICBvcHRzID0gb3B0cyB8fCB7fTsKICAgIHZhciBtZXRhID0gewogICAgICB0eXBlOiB1c2VyRW50ZXJlZE1vZGVsTmFtZSwKICAgICAgaXNSZWxhdGlvbnNoaXA6IHRydWUsCiAgICAgIG9wdGlvbnM6IG9wdHMsCiAgICAgIGtpbmQ6ICdiZWxvbmdzVG8nLAogICAgICBuYW1lOiAnQmVsb25ncyBUbycsCiAgICAgIGtleTogbnVsbAogICAgfTsKICAgIHJldHVybiBFbWJlci5jb21wdXRlZCh7CiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KGtleSkgewoKICAgICAgICByZXR1cm4gdGhpcy5faW50ZXJuYWxNb2RlbC5nZXRCZWxvbmdzVG8oa2V5KTsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5LCB2YWx1ZSkgewoKICAgICAgICB0aGlzLl9pbnRlcm5hbE1vZGVsLnNldERpcnR5QmVsb25nc1RvKGtleSwgdmFsdWUpOwoKICAgICAgICByZXR1cm4gdGhpcy5faW50ZXJuYWxNb2RlbC5nZXRCZWxvbmdzVG8oa2V5KTsKICAgICAgfQogICAgfSkubWV0YShtZXRhKTsKICB9CgogIHZhciBiZWxvbmdzVG8kMSA9IGNvbXB1dGVkTWFjcm9XaXRoT3B0aW9uYWxQYXJhbXMoYmVsb25nc1RvKTsKCiAgLyoqCiAgICBgaGFzTWFueWAgaXMgdXNlZCB0byBkZWZpbmUgT25lLVRvLU1hbnkgYW5kIE1hbnktVG8tTWFueQogICAgcmVsYXRpb25zaGlwcyBvbiBhIFtNb2RlbF0oL2VtYmVyLWRhdGEvcmVsZWFzZS9jbGFzc2VzL01vZGVsKS4KCiAgICBgaGFzTWFueWAgdGFrZXMgYW4gb3B0aW9uYWwgaGFzaCBhcyBhIHNlY29uZCBwYXJhbWV0ZXIsIGN1cnJlbnRseQogICAgc3VwcG9ydGVkIG9wdGlvbnMgYXJlOgoKICAgIC0gYGFzeW5jYDogQSBib29sZWFuIHZhbHVlIHVzZWQgdG8gZXhwbGljaXRseSBkZWNsYXJlIHRoaXMgdG8gYmUgYW4gYXN5bmMgcmVsYXRpb25zaGlwLiBUaGUgZGVmYXVsdCBpcyB0cnVlLgogICAgLSBgaW52ZXJzZWA6IEEgc3RyaW5nIHVzZWQgdG8gaWRlbnRpZnkgdGhlIGludmVyc2UgcHJvcGVydHkgb24gYSByZWxhdGVkIG1vZGVsLgogICAgLSBgcG9seW1vcnBoaWNgIEEgYm9vbGVhbiB2YWx1ZSB0byBtYXJrIHRoZSByZWxhdGlvbnNoaXAgYXMgcG9seW1vcnBoaWMKCiAgICAjIyMjIE9uZS1Uby1NYW55CiAgICBUbyBkZWNsYXJlIGEgb25lLXRvLW1hbnkgcmVsYXRpb25zaGlwIGJldHdlZW4gdHdvIG1vZGVscywgdXNlCiAgICBgYmVsb25nc1RvYCBpbiBjb21iaW5hdGlvbiB3aXRoIGBoYXNNYW55YCwgbGlrZSB0aGlzOgoKICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgY29tbWVudHM6IGhhc01hbnkoJ2NvbW1lbnQnKQogICAgfSk7CiAgICBgYGAKCiAgICBgYGBhcHAvbW9kZWxzL2NvbW1lbnQuanMKICAgIGltcG9ydCBNb2RlbCwgeyBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgcG9zdDogYmVsb25nc1RvKCdwb3N0JykKICAgIH0pOwogICAgYGBgCgogICAgIyMjIyBNYW55LVRvLU1hbnkKICAgIFRvIGRlY2xhcmUgYSBtYW55LXRvLW1hbnkgcmVsYXRpb25zaGlwIGJldHdlZW4gdHdvIG1vZGVscywgdXNlCiAgICBgaGFzTWFueWA6CgogICAgYGBgYXBwL21vZGVscy9wb3N0LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICB0YWdzOiBoYXNNYW55KCd0YWcnKQogICAgfSk7CiAgICBgYGAKCiAgICBgYGBhcHAvbW9kZWxzL3RhZy5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgcG9zdHM6IGhhc01hbnkoJ3Bvc3QnKQogICAgfSk7CiAgICBgYGAKCiAgICBZb3UgY2FuIGF2b2lkIHBhc3NpbmcgYSBzdHJpbmcgYXMgdGhlIGZpcnN0IHBhcmFtZXRlci4gSW4gdGhhdCBjYXNlIEVtYmVyIERhdGEKICAgIHdpbGwgaW5mZXIgdGhlIHR5cGUgZnJvbSB0aGUgc2luZ3VsYXJpemVkIGtleSBuYW1lLgoKICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgdGFnczogaGFzTWFueSgpCiAgICB9KTsKICAgIGBgYAoKICAgIHdpbGwgbG9va3VwIGZvciBhIFRhZyB0eXBlLgoKICAgICMjIyMgRXhwbGljaXQgSW52ZXJzZXMKCiAgICBFbWJlciBEYXRhIHdpbGwgZG8gaXRzIGJlc3QgdG8gZGlzY292ZXIgd2hpY2ggcmVsYXRpb25zaGlwcyBtYXAgdG8KICAgIG9uZSBhbm90aGVyLiBJbiB0aGUgb25lLXRvLW1hbnkgY29kZSBhYm92ZSwgZm9yIGV4YW1wbGUsIEVtYmVyIERhdGEKICAgIGNhbiBmaWd1cmUgb3V0IHRoYXQgY2hhbmdpbmcgdGhlIGBjb21tZW50c2AgcmVsYXRpb25zaGlwIHNob3VsZCB1cGRhdGUKICAgIHRoZSBgcG9zdGAgcmVsYXRpb25zaGlwIG9uIHRoZSBpbnZlcnNlIGJlY2F1c2UgcG9zdCBpcyB0aGUgb25seQogICAgcmVsYXRpb25zaGlwIHRvIHRoYXQgbW9kZWwuCgogICAgSG93ZXZlciwgc29tZXRpbWVzIHlvdSBtYXkgaGF2ZSBtdWx0aXBsZSBgYmVsb25nc1RvYC9gaGFzTWFueWAgZm9yIHRoZQogICAgc2FtZSB0eXBlLiBZb3UgY2FuIHNwZWNpZnkgd2hpY2ggcHJvcGVydHkgb24gdGhlIHJlbGF0ZWQgbW9kZWwgaXMKICAgIHRoZSBpbnZlcnNlIHVzaW5nIGBoYXNNYW55YCdzIGBpbnZlcnNlYCBvcHRpb246CgogICAgYGBgYXBwL21vZGVscy9jb21tZW50LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIG9uZVBvc3Q6IGJlbG9uZ3NUbygncG9zdCcpLAogICAgICB0d29Qb3N0OiBiZWxvbmdzVG8oJ3Bvc3QnKSwKICAgICAgcmVkUG9zdDogYmVsb25nc1RvKCdwb3N0JyksCiAgICAgIGJsdWVQb3N0OiBiZWxvbmdzVG8oJ3Bvc3QnKQogICAgfSk7CiAgICBgYGAKCiAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIGNvbW1lbnRzOiBoYXNNYW55KCdjb21tZW50JywgewogICAgICAgIGludmVyc2U6ICdyZWRQb3N0JwogICAgICB9KQogICAgfSk7CiAgICBgYGAKCiAgICBZb3UgY2FuIGFsc28gc3BlY2lmeSBhbiBpbnZlcnNlIG9uIGEgYGJlbG9uZ3NUb2AsIHdoaWNoIHdvcmtzIGhvdwogICAgeW91J2QgZXhwZWN0LgoKICAgICMjIyMgU3luYyByZWxhdGlvbnNoaXBzCgogICAgRW1iZXIgRGF0YSByZXNvbHZlcyBzeW5jIHJlbGF0aW9uc2hpcHMgd2l0aCB0aGUgcmVsYXRlZCByZXNvdXJjZXMKICAgIGF2YWlsYWJsZSBpbiBpdHMgbG9jYWwgc3RvcmUsIGhlbmNlIGl0IGlzIGV4cGVjdGVkIHRoZXNlIHJlc291cmNlcwogICAgdG8gYmUgbG9hZGVkIGJlZm9yZSBvciBhbG9uZy1zaWRlIHRoZSBwcmltYXJ5IHJlc291cmNlLgoKICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgY29tbWVudHM6IGhhc01hbnkoJ2NvbW1lbnQnLCB7CiAgICAgICAgYXN5bmM6IGZhbHNlCiAgICAgIH0pCiAgICB9KTsKICAgIGBgYAoKICAgIEluIGNvbnRyYXN0IHRvIGFzeW5jIHJlbGF0aW9uc2hpcCwgYWNjZXNzaW5nIGEgc3luYyByZWxhdGlvbnNoaXAKICAgIHdpbGwgYWx3YXlzIHJldHVybiBhIFtNYW55QXJyYXldKC9lbWJlci1kYXRhL3JlbGVhc2UvY2xhc3Nlcy9NYW55QXJyYXkpIGluc3RhbmNlCiAgICBjb250YWluaW5nIHRoZSBleGlzdGluZyBsb2NhbCByZXNvdXJjZXMuIEJ1dCBpdCB3aWxsIGVycm9yIG9uIGFjY2VzcwogICAgd2hlbiBhbnkgb2YgdGhlIGtub3duIHJlbGF0ZWQgcmVzb3VyY2VzIGhhdmUgbm90IGJlZW4gbG9hZGVkLgoKICAgIGBgYAogICAgcG9zdC5nZXQoJ2NvbW1lbnRzJykuZm9yRWFjaCgoY29tbWVudCkgPT4gewoKICAgIH0pOwoKICAgIGBgYAoKICAgIElmIHlvdSBhcmUgdXNpbmcgYGxpbmtzYCB3aXRoIHN5bmMgcmVsYXRpb25zaGlwcywgeW91IGhhdmUgdG8gdXNlCiAgICBgcmVmLnJlbG9hZGAgdG8gZmV0Y2ggdGhlIHJlc291cmNlcy4KCiAgICBAbWV0aG9kIGhhc01hbnkKICAgIEBwdWJsaWMKICAgIEBzdGF0aWMKICAgIEBmb3IgQGVtYmVyLWRhdGEvbW9kZWwKICAgIEBwYXJhbSB7U3RyaW5nfSB0eXBlIChvcHRpb25hbCkgdHlwZSBvZiB0aGUgcmVsYXRpb25zaGlwCiAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAob3B0aW9uYWwpIGEgaGFzaCBvZiBvcHRpb25zCiAgICBAcmV0dXJuIHtFbWJlci5jb21wdXRlZH0gcmVsYXRpb25zaGlwCiAgKi8KCiAgZnVuY3Rpb24gaGFzTWFueSh0eXBlLCBvcHRpb25zKSB7CiAgICBpZiAodHlwZW9mIHR5cGUgPT09ICdvYmplY3QnKSB7CiAgICAgIG9wdGlvbnMgPSB0eXBlOwogICAgICB0eXBlID0gdW5kZWZpbmVkOwogICAgfQogICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307CgogICAgaWYgKHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJykgewogICAgICB0eXBlID0gc3RvcmUubm9ybWFsaXplTW9kZWxOYW1lKHR5cGUpOwogICAgfSAvLyBNZXRhZGF0YSBhYm91dCByZWxhdGlvbnNoaXBzIGlzIHN0b3JlZCBvbiB0aGUgbWV0YSBvZgogICAgLy8gdGhlIHJlbGF0aW9uc2hpcC4gVGhpcyBpcyB1c2VkIGZvciBpbnRyb3NwZWN0aW9uIGFuZAogICAgLy8gc2VyaWFsaXphdGlvbi4gTm90ZSB0aGF0IGBrZXlgIGlzIHBvcHVsYXRlZCBsYXppbHkKICAgIC8vIHRoZSBmaXJzdCB0aW1lIHRoZSBDUCBpcyBjYWxsZWQuCgoKICAgIHZhciBtZXRhID0gewogICAgICB0eXBlOiB0eXBlLAogICAgICBvcHRpb25zOiBvcHRpb25zLAogICAgICBpc1JlbGF0aW9uc2hpcDogdHJ1ZSwKICAgICAga2luZDogJ2hhc01hbnknLAogICAgICBuYW1lOiAnSGFzIE1hbnknLAogICAgICBrZXk6IG51bGwKICAgIH07CiAgICByZXR1cm4gRW1iZXIuY29tcHV0ZWQoewogICAgICBnZXQ6IGZ1bmN0aW9uIGdldChrZXkpIHsKCiAgICAgICAgcmV0dXJuIHRoaXMuX2ludGVybmFsTW9kZWwuZ2V0SGFzTWFueShrZXkpOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldChrZXksIHJlY29yZHMpIHsKCiAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSB0aGlzLl9pbnRlcm5hbE1vZGVsOwogICAgICAgIGludGVybmFsTW9kZWwuc2V0RGlydHlIYXNNYW55KGtleSwgcmVjb3Jkcyk7CiAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwuZ2V0SGFzTWFueShrZXkpOwogICAgICB9CiAgICB9KS5tZXRhKG1ldGEpOwogIH0KCiAgdmFyIGhhc01hbnkkMSA9IGNvbXB1dGVkTWFjcm9XaXRoT3B0aW9uYWxQYXJhbXMoaGFzTWFueSk7CgogIHZhciBjaGFuZ2VQcm9wZXJ0aWVzID0gRW1iZXIuY2hhbmdlUHJvcGVydGllczsKCiAgZnVuY3Rpb24gaXNJbnZhbGlkRXJyb3IoZXJyb3IpIHsKICAgIHJldHVybiBlcnJvciAmJiBlcnJvci5pc0FkYXB0ZXJFcnJvciA9PT0gdHJ1ZSAmJiBlcnJvci5jb2RlID09PSAnSW52YWxpZEVycm9yJzsKICB9CgogIGZ1bmN0aW9uIGZpbmRQb3NzaWJsZUludmVyc2VzKHR5cGUsIGludmVyc2VUeXBlLCBuYW1lLCByZWxhdGlvbnNoaXBzU29GYXIpIHsKICAgIHZhciBwb3NzaWJsZVJlbGF0aW9uc2hpcHMgPSByZWxhdGlvbnNoaXBzU29GYXIgfHwgW107CiAgICB2YXIgcmVsYXRpb25zaGlwTWFwID0gRW1iZXIuZ2V0KGludmVyc2VUeXBlLCAncmVsYXRpb25zaGlwcycpOwoKICAgIGlmICghcmVsYXRpb25zaGlwTWFwKSB7CiAgICAgIHJldHVybiBwb3NzaWJsZVJlbGF0aW9uc2hpcHM7CiAgICB9CgogICAgdmFyIHJlbGF0aW9uc2hpcHNGb3JUeXBlID0gcmVsYXRpb25zaGlwTWFwLmdldCh0eXBlLm1vZGVsTmFtZSk7CiAgICB2YXIgcmVsYXRpb25zaGlwcyA9IEFycmF5LmlzQXJyYXkocmVsYXRpb25zaGlwc0ZvclR5cGUpID8gcmVsYXRpb25zaGlwc0ZvclR5cGUuZmlsdGVyKGZ1bmN0aW9uIChyZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIG9wdGlvbnNGb3JSZWxhdGlvbnNoaXAgPSBpbnZlcnNlVHlwZS5tZXRhRm9yUHJvcGVydHkocmVsYXRpb25zaGlwLm5hbWUpLm9wdGlvbnM7CgogICAgICBpZiAoIW9wdGlvbnNGb3JSZWxhdGlvbnNoaXAuaW52ZXJzZSAmJiBvcHRpb25zRm9yUmVsYXRpb25zaGlwLmludmVyc2UgIT09IG51bGwpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgcmV0dXJuIG5hbWUgPT09IG9wdGlvbnNGb3JSZWxhdGlvbnNoaXAuaW52ZXJzZTsKICAgIH0pIDogbnVsbDsKCiAgICBpZiAocmVsYXRpb25zaGlwcykgewogICAgICBwb3NzaWJsZVJlbGF0aW9uc2hpcHMucHVzaC5hcHBseShwb3NzaWJsZVJlbGF0aW9uc2hpcHMsIHJlbGF0aW9uc2hpcHMpOwogICAgfSAvL1JlY3Vyc2UgdG8gc3VwcG9ydCBwb2x5bW9ycGhpc20KCgogICAgaWYgKHR5cGUuc3VwZXJjbGFzcykgewogICAgICBmaW5kUG9zc2libGVJbnZlcnNlcyh0eXBlLnN1cGVyY2xhc3MsIGludmVyc2VUeXBlLCBuYW1lLCBwb3NzaWJsZVJlbGF0aW9uc2hpcHMpOwogICAgfQoKICAgIHJldHVybiBwb3NzaWJsZVJlbGF0aW9uc2hpcHM7CiAgfQoKICB2YXIgcmV0cmlldmVGcm9tQ3VycmVudFN0YXRlID0gRW1iZXIuY29tcHV0ZWQoJ2N1cnJlbnRTdGF0ZScsIGZ1bmN0aW9uIChrZXkpIHsKICAgIHJldHVybiBFbWJlci5nZXQodGhpcy5faW50ZXJuYWxNb2RlbC5jdXJyZW50U3RhdGUsIGtleSk7CiAgfSkucmVhZE9ubHkoKTsKICB2YXIgaXNWYWxpZFJlY29yZERhdGEgPSBFbWJlci5jb21wdXRlZCgnZXJyb3JzLmxlbmd0aCcsIGZ1bmN0aW9uIChrZXkpIHsKICAgIHJldHVybiAhKHRoaXMuZ2V0KCdlcnJvcnMubGVuZ3RoJykgPiAwKTsKICB9KS5yZWFkT25seSgpOwogIHZhciBpc1ZhbGlkID0gY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfRVJST1JTID8gaXNWYWxpZFJlY29yZERhdGEgOiByZXRyaWV2ZUZyb21DdXJyZW50U3RhdGU7CiAgdmFyIGlzRGVsZXRlZENQOwoKICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfU1RBVEUpIHsKICAgIGlzRGVsZXRlZENQID0gRW1iZXIuY29tcHV0ZWQoJ2N1cnJlbnRTdGF0ZScsIGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIHJkID0gUHJpdmF0ZS5yZWNvcmREYXRhRm9yKHRoaXMpOwoKICAgICAgaWYgKHJkLmlzRGVsZXRlZCkgewogICAgICAgIHJldHVybiByZC5pc0RlbGV0ZWQoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRW1iZXIuZ2V0KHRoaXMuX2ludGVybmFsTW9kZWwuY3VycmVudFN0YXRlLCAnaXNEZWxldGVkJyk7CiAgICAgIH0KICAgIH0pLnJlYWRPbmx5KCk7CiAgfSBlbHNlIHsKICAgIGlzRGVsZXRlZENQID0gcmV0cmlldmVGcm9tQ3VycmVudFN0YXRlOwogIH0KCiAgdmFyIGlzTmV3Q1A7CgogIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9TVEFURSkgewogICAgaXNOZXdDUCA9IEVtYmVyLmNvbXB1dGVkKCdjdXJyZW50U3RhdGUnLCBmdW5jdGlvbiAoKSB7CiAgICAgIHZhciByZCA9IFByaXZhdGUucmVjb3JkRGF0YUZvcih0aGlzKTsKCiAgICAgIGlmIChyZC5pc05ldykgewogICAgICAgIHJldHVybiByZC5pc05ldygpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFbWJlci5nZXQodGhpcy5faW50ZXJuYWxNb2RlbC5jdXJyZW50U3RhdGUsICdpc05ldycpOwogICAgICB9CiAgICB9KS5yZWFkT25seSgpOwogIH0gZWxzZSB7CiAgICBpc05ld0NQID0gcmV0cmlldmVGcm9tQ3VycmVudFN0YXRlOwogIH0KCiAgdmFyIGFkYXB0ZXJFcnJvcjsKCiAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgYWRhcHRlckVycm9yID0gRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgICB2YXIgcmVxdWVzdCA9IHRoaXMuX2xhc3RFcnJvcjsKCiAgICAgIGlmICghcmVxdWVzdCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICByZXR1cm4gcmVxdWVzdC5zdGF0ZSA9PT0gJ3JlamVjdGVkJyAmJiByZXF1ZXN0LnJlc3BvbnNlLmRhdGE7CiAgICB9KTsKICB9IGVsc2UgewogICAgYWRhcHRlckVycm9yID0gbnVsbDsKICB9CgogIHZhciBpc0Vycm9yOwoKICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICBpc0Vycm9yID0gRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgICB2YXIgZXJyb3JSZXEgPSB0aGlzLl9lcnJvclJlcXVlc3RzW3RoaXMuX2Vycm9yUmVxdWVzdHMubGVuZ3RoIC0gMV07CgogICAgICBpZiAoIWVycm9yUmVxKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICB9KTsKICB9IGVsc2UgewogICAgaXNFcnJvciA9IGZhbHNlOwogIH0KCiAgdmFyIGlzUmVsb2FkaW5nOwoKICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICBpc1JlbG9hZGluZyA9IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIHJlcXVlc3RzID0gdGhpcy5zdG9yZS5nZXRSZXF1ZXN0U3RhdGVTZXJ2aWNlKCkuZ2V0UGVuZGluZ1JlcXVlc3RzRm9yUmVjb3JkKFByaXZhdGUucmVjb3JkSWRlbnRpZmllckZvcih0aGlzKSk7CiAgICAgIHJldHVybiAhIXJlcXVlc3RzLmZpbmQoZnVuY3Rpb24gKHJlcSkgewogICAgICAgIHJldHVybiByZXEucmVxdWVzdC5kYXRhWzBdLm9wdGlvbnMuaXNSZWxvYWRpbmc7CiAgICAgIH0pOwogICAgfSk7CiAgfSBlbHNlIHsKICAgIGlzUmVsb2FkaW5nID0gZmFsc2U7CiAgfQogIC8qKgogICAgQGNsYXNzIE1vZGVsCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL21vZGVsCiAgICBAZXh0ZW5kcyBFbWJlck9iamVjdAogICAgQHVzZXMgRW1iZXJEYXRhLkRlcHJlY2F0ZWRFdmVudGVkCiAgKi8KCgogIHZhciBNb2RlbCA9IEVtYmVyLk9iamVjdC5leHRlbmQoUHJpdmF0ZS5EZXByZWNhdGVkRXZlbnRlZCwgewogICAgaW5pdDogZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfRVJST1JTKSB7CiAgICAgICAgdGhpcy5faW52YWxpZFJlcXVlc3RzID0gW107CiAgICAgIH0KCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICB0aGlzLnN0b3JlLmdldFJlcXVlc3RTdGF0ZVNlcnZpY2UoKS5zdWJzY3JpYmVGb3JSZWNvcmQodGhpcy5faW50ZXJuYWxNb2RlbC5pZGVudGlmaWVyLCBmdW5jdGlvbiAocmVxdWVzdCkgewogICAgICAgICAgaWYgKHJlcXVlc3Quc3RhdGUgPT09ICdyZWplY3RlZCcpIHsKICAgICAgICAgICAgLy8gVE9ETyBmaWx0ZXIgb3V0IHF1ZXJpZXMKICAgICAgICAgICAgX3RoaXMuX2xhc3RFcnJvciA9IHJlcXVlc3Q7CgogICAgICAgICAgICBpZiAoIShyZXF1ZXN0LnJlc3BvbnNlICYmIGlzSW52YWxpZEVycm9yKHJlcXVlc3QucmVzcG9uc2UuZGF0YSkpKSB7CiAgICAgICAgICAgICAgX3RoaXMuX2Vycm9yUmVxdWVzdHMucHVzaChyZXF1ZXN0KTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBfdGhpcy5faW52YWxpZFJlcXVlc3RzLnB1c2gocmVxdWVzdCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSBpZiAocmVxdWVzdC5zdGF0ZSA9PT0gJ2Z1bGZpbGxlZCcpIHsKICAgICAgICAgICAgX3RoaXMuX2ludmFsaWRSZXF1ZXN0cyA9IFtdOwogICAgICAgICAgICBfdGhpcy5fZXJyb3JSZXF1ZXN0cyA9IFtdOwogICAgICAgICAgICBfdGhpcy5fbGFzdEVycm9yID0gbnVsbDsKICAgICAgICAgIH0KCiAgICAgICAgICBfdGhpcy5fbm90aWZ5TmV0d29ya0NoYW5nZXMoKTsKICAgICAgICB9KTsKICAgICAgICB0aGlzLl9lcnJvclJlcXVlc3RzID0gW107CiAgICAgICAgdGhpcy5fbGFzdEVycm9yID0gbnVsbDsKICAgICAgfQogICAgfSwKICAgIF9ub3RpZnlOZXR3b3JrQ2hhbmdlczogZnVuY3Rpb24gX25vdGlmeU5ldHdvcmtDaGFuZ2VzKCkgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICBbJ2lzU2F2aW5nJywgJ2lzVmFsaWQnLCAnaXNFcnJvcicsICdhZGFwdGVyRXJyb3InLCAnaXNSZWxvYWRpbmcnXS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgIHJldHVybiBfdGhpczIubm90aWZ5UHJvcGVydHlDaGFuZ2Uoa2V5KTsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBbJ2lzVmFsaWQnXS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgIHJldHVybiBfdGhpczIubm90aWZ5UHJvcGVydHlDaGFuZ2Uoa2V5KTsKICAgICAgICB9KTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgSWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAgdGhlIHJlY29yZCBpcyBpbiB0aGUgYGVtcHR5YAogICAgICBzdGF0ZS4gRW1wdHkgaXMgdGhlIGZpcnN0IHN0YXRlIGFsbCByZWNvcmRzIGVudGVyIGFmdGVyIHRoZXkgaGF2ZQogICAgICBiZWVuIGNyZWF0ZWQuIE1vc3QgcmVjb3JkcyBjcmVhdGVkIGJ5IHRoZSBzdG9yZSB3aWxsIHF1aWNrbHkKICAgICAgdHJhbnNpdGlvbiB0byB0aGUgYGxvYWRpbmdgIHN0YXRlIGlmIGRhdGEgbmVlZHMgdG8gYmUgZmV0Y2hlZCBmcm9tCiAgICAgIHRoZSBzZXJ2ZXIgb3IgdGhlIGBjcmVhdGVkYCBzdGF0ZSBpZiB0aGUgcmVjb3JkIGlzIGNyZWF0ZWQgb24gdGhlCiAgICAgIGNsaWVudC4gQSByZWNvcmQgY2FuIGFsc28gZW50ZXIgdGhlIGVtcHR5IHN0YXRlIGlmIHRoZSBhZGFwdGVyIGlzCiAgICAgIHVuYWJsZSB0byBsb2NhdGUgdGhlIHJlY29yZC4KICAgICAgIEBwcm9wZXJ0eSBpc0VtcHR5CiAgICAgIEB0eXBlIHtCb29sZWFufQogICAgICBAcmVhZE9ubHkKICAgICovCiAgICBpc0VtcHR5OiByZXRyaWV2ZUZyb21DdXJyZW50U3RhdGUsCgogICAgLyoqCiAgICAgIElmIHRoaXMgcHJvcGVydHkgaXMgYHRydWVgIHRoZSByZWNvcmQgaXMgaW4gdGhlIGBsb2FkaW5nYCBzdGF0ZS4gQQogICAgICByZWNvcmQgZW50ZXJzIHRoaXMgc3RhdGUgd2hlbiB0aGUgc3RvcmUgYXNrcyB0aGUgYWRhcHRlciBmb3IgaXRzCiAgICAgIGRhdGEuIEl0IHJlbWFpbnMgaW4gdGhpcyBzdGF0ZSB1bnRpbCB0aGUgYWRhcHRlciBwcm92aWRlcyB0aGUKICAgICAgcmVxdWVzdGVkIGRhdGEuCiAgICAgICBAcHJvcGVydHkgaXNMb2FkaW5nCiAgICAgIEB0eXBlIHtCb29sZWFufQogICAgICBAcmVhZE9ubHkKICAgICovCiAgICBpc0xvYWRpbmc6IHJldHJpZXZlRnJvbUN1cnJlbnRTdGF0ZSwKCiAgICAvKioKICAgICAgSWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAgdGhlIHJlY29yZCBpcyBpbiB0aGUgYGxvYWRlZGAgc3RhdGUuIEEKICAgICAgcmVjb3JkIGVudGVycyB0aGlzIHN0YXRlIHdoZW4gaXRzIGRhdGEgaXMgcG9wdWxhdGVkLiBNb3N0IG9mIGEKICAgICAgcmVjb3JkJ3MgbGlmZWN5Y2xlIGlzIHNwZW50IGluc2lkZSBzdWJzdGF0ZXMgb2YgdGhlIGBsb2FkZWRgCiAgICAgIHN0YXRlLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgcmVjb3JkID0gc3RvcmUuY3JlYXRlUmVjb3JkKCdtb2RlbCcpOwogICAgICByZWNvcmQuZ2V0KCdpc0xvYWRlZCcpOyAvLyB0cnVlCiAgICAgICBzdG9yZS5maW5kUmVjb3JkKCdtb2RlbCcsIDEpLnRoZW4oZnVuY3Rpb24obW9kZWwpIHsKICAgICAgICBtb2RlbC5nZXQoJ2lzTG9hZGVkJyk7IC8vIHRydWUKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQHByb3BlcnR5IGlzTG9hZGVkCiAgICAgIEB0eXBlIHtCb29sZWFufQogICAgICBAcmVhZE9ubHkKICAgICovCiAgICBpc0xvYWRlZDogcmV0cmlldmVGcm9tQ3VycmVudFN0YXRlLAoKICAgIC8qKgogICAgICBJZiB0aGlzIHByb3BlcnR5IGlzIGB0cnVlYCB0aGUgcmVjb3JkIGlzIGluIHRoZSBgZGlydHlgIHN0YXRlLiBUaGUKICAgICAgcmVjb3JkIGhhcyBsb2NhbCBjaGFuZ2VzIHRoYXQgaGF2ZSBub3QgeWV0IGJlZW4gc2F2ZWQgYnkgdGhlCiAgICAgIGFkYXB0ZXIuIFRoaXMgaW5jbHVkZXMgcmVjb3JkcyB0aGF0IGhhdmUgYmVlbiBjcmVhdGVkIChidXQgbm90IHlldAogICAgICBzYXZlZCkgb3IgZGVsZXRlZC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IHJlY29yZCA9IHN0b3JlLmNyZWF0ZVJlY29yZCgnbW9kZWwnKTsKICAgICAgcmVjb3JkLmdldCgnaGFzRGlydHlBdHRyaWJ1dGVzJyk7IC8vIHRydWUKICAgICAgIHN0b3JlLmZpbmRSZWNvcmQoJ21vZGVsJywgMSkudGhlbihmdW5jdGlvbihtb2RlbCkgewogICAgICAgIG1vZGVsLmdldCgnaGFzRGlydHlBdHRyaWJ1dGVzJyk7IC8vIGZhbHNlCiAgICAgICAgbW9kZWwuc2V0KCdmb28nLCAnc29tZSB2YWx1ZScpOwogICAgICAgIG1vZGVsLmdldCgnaGFzRGlydHlBdHRyaWJ1dGVzJyk7IC8vIHRydWUKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAcHJvcGVydHkgaGFzRGlydHlBdHRyaWJ1dGVzCiAgICAgIEB0eXBlIHtCb29sZWFufQogICAgICBAcmVhZE9ubHkKICAgICovCiAgICBoYXNEaXJ0eUF0dHJpYnV0ZXM6IEVtYmVyLmNvbXB1dGVkKCdjdXJyZW50U3RhdGUuaXNEaXJ0eScsIGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIHRoaXMuZ2V0KCdjdXJyZW50U3RhdGUuaXNEaXJ0eScpOwogICAgfSksCgogICAgLyoqCiAgICAgIElmIHRoaXMgcHJvcGVydHkgaXMgYHRydWVgIHRoZSByZWNvcmQgaXMgaW4gdGhlIGBzYXZpbmdgIHN0YXRlLiBBCiAgICAgIHJlY29yZCBlbnRlcnMgdGhlIHNhdmluZyBzdGF0ZSB3aGVuIGBzYXZlYCBpcyBjYWxsZWQsIGJ1dCB0aGUKICAgICAgYWRhcHRlciBoYXMgbm90IHlldCBhY2tub3dsZWRnZWQgdGhhdCB0aGUgY2hhbmdlcyBoYXZlIGJlZW4KICAgICAgcGVyc2lzdGVkIHRvIHRoZSBiYWNrZW5kLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgcmVjb3JkID0gc3RvcmUuY3JlYXRlUmVjb3JkKCdtb2RlbCcpOwogICAgICByZWNvcmQuZ2V0KCdpc1NhdmluZycpOyAvLyBmYWxzZQogICAgICBsZXQgcHJvbWlzZSA9IHJlY29yZC5zYXZlKCk7CiAgICAgIHJlY29yZC5nZXQoJ2lzU2F2aW5nJyk7IC8vIHRydWUKICAgICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKCkgewogICAgICAgIHJlY29yZC5nZXQoJ2lzU2F2aW5nJyk7IC8vIGZhbHNlCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBpc1NhdmluZwogICAgICBAdHlwZSB7Qm9vbGVhbn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgaXNTYXZpbmc6IHJldHJpZXZlRnJvbUN1cnJlbnRTdGF0ZSwKCiAgICAvKioKICAgICAgSWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAgdGhlIHJlY29yZCBpcyBpbiB0aGUgYGRlbGV0ZWRgIHN0YXRlCiAgICAgIGFuZCBoYXMgYmVlbiBtYXJrZWQgZm9yIGRlbGV0aW9uLiBXaGVuIGBpc0RlbGV0ZWRgIGlzIHRydWUgYW5kCiAgICAgIGBoYXNEaXJ0eUF0dHJpYnV0ZXNgIGlzIHRydWUsIHRoZSByZWNvcmQgaXMgZGVsZXRlZCBsb2NhbGx5IGJ1dCB0aGUgZGVsZXRpb24KICAgICAgd2FzIG5vdCB5ZXQgcGVyc2lzdGVkLiBXaGVuIGBpc1NhdmluZ2AgaXMgdHJ1ZSwgdGhlIGNoYW5nZSBpcwogICAgICBpbi1mbGlnaHQuIFdoZW4gYm90aCBgaGFzRGlydHlBdHRyaWJ1dGVzYCBhbmQgYGlzU2F2aW5nYCBhcmUgZmFsc2UsIHRoZQogICAgICBjaGFuZ2UgaGFzIHBlcnNpc3RlZC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IHJlY29yZCA9IHN0b3JlLmNyZWF0ZVJlY29yZCgnbW9kZWwnKTsKICAgICAgcmVjb3JkLmdldCgnaXNEZWxldGVkJyk7ICAgIC8vIGZhbHNlCiAgICAgIHJlY29yZC5kZWxldGVSZWNvcmQoKTsKICAgICAgIC8vIExvY2FsbHkgZGVsZXRlZAogICAgICByZWNvcmQuZ2V0KCdpc0RlbGV0ZWQnKTsgICAgICAgICAgIC8vIHRydWUKICAgICAgcmVjb3JkLmdldCgnaGFzRGlydHlBdHRyaWJ1dGVzJyk7ICAvLyB0cnVlCiAgICAgIHJlY29yZC5nZXQoJ2lzU2F2aW5nJyk7ICAgICAgICAgICAgLy8gZmFsc2UKICAgICAgIC8vIFBlcnNpc3RpbmcgdGhlIGRlbGV0aW9uCiAgICAgIGxldCBwcm9taXNlID0gcmVjb3JkLnNhdmUoKTsKICAgICAgcmVjb3JkLmdldCgnaXNEZWxldGVkJyk7ICAgIC8vIHRydWUKICAgICAgcmVjb3JkLmdldCgnaXNTYXZpbmcnKTsgICAgIC8vIHRydWUKICAgICAgIC8vIERlbGV0aW9uIFBlcnNpc3RlZAogICAgICBwcm9taXNlLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgICAgcmVjb3JkLmdldCgnaXNEZWxldGVkJyk7ICAgICAgICAgIC8vIHRydWUKICAgICAgICByZWNvcmQuZ2V0KCdpc1NhdmluZycpOyAgICAgICAgICAgLy8gZmFsc2UKICAgICAgICByZWNvcmQuZ2V0KCdoYXNEaXJ0eUF0dHJpYnV0ZXMnKTsgLy8gZmFsc2UKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQHByb3BlcnR5IGlzRGVsZXRlZAogICAgICBAdHlwZSB7Qm9vbGVhbn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgaXNEZWxldGVkOiBpc0RlbGV0ZWRDUCwKCiAgICAvKioKICAgICAgSWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAgdGhlIHJlY29yZCBpcyBpbiB0aGUgYG5ld2Agc3RhdGUuIEEKICAgICAgcmVjb3JkIHdpbGwgYmUgaW4gdGhlIGBuZXdgIHN0YXRlIHdoZW4gaXQgaGFzIGJlZW4gY3JlYXRlZCBvbiB0aGUKICAgICAgY2xpZW50IGFuZCB0aGUgYWRhcHRlciBoYXMgbm90IHlldCByZXBvcnQgdGhhdCBpdCB3YXMgc3VjY2Vzc2Z1bGx5CiAgICAgIHNhdmVkLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgcmVjb3JkID0gc3RvcmUuY3JlYXRlUmVjb3JkKCdtb2RlbCcpOwogICAgICByZWNvcmQuZ2V0KCdpc05ldycpOyAvLyB0cnVlCiAgICAgICByZWNvcmQuc2F2ZSgpLnRoZW4oZnVuY3Rpb24obW9kZWwpIHsKICAgICAgICBtb2RlbC5nZXQoJ2lzTmV3Jyk7IC8vIGZhbHNlCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBpc05ldwogICAgICBAdHlwZSB7Qm9vbGVhbn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgaXNOZXc6IGlzTmV3Q1AsCgogICAgLyoqCiAgICAgIElmIHRoaXMgcHJvcGVydHkgaXMgYHRydWVgIHRoZSByZWNvcmQgaXMgaW4gdGhlIGB2YWxpZGAgc3RhdGUuCiAgICAgICBBIHJlY29yZCB3aWxsIGJlIGluIHRoZSBgdmFsaWRgIHN0YXRlIHdoZW4gdGhlIGFkYXB0ZXIgZGlkIG5vdCByZXBvcnQgYW55CiAgICAgIHNlcnZlci1zaWRlIHZhbGlkYXRpb24gZmFpbHVyZXMuCiAgICAgICBAcHJvcGVydHkgaXNWYWxpZAogICAgICBAdHlwZSB7Qm9vbGVhbn0KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgaXNWYWxpZDogaXNWYWxpZCwKICAgIF9tYXJrSW52YWxpZFJlcXVlc3RBc0NsZWFuOiBmdW5jdGlvbiBfbWFya0ludmFsaWRSZXF1ZXN0QXNDbGVhbigpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX0VSUk9SUykgewogICAgICAgIHRoaXMuX2ludmFsaWRSZXF1ZXN0cyA9IFtdOwoKICAgICAgICB0aGlzLl9ub3RpZnlOZXR3b3JrQ2hhbmdlcygpOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBJZiB0aGUgcmVjb3JkIGlzIGluIHRoZSBkaXJ0eSBzdGF0ZSB0aGlzIHByb3BlcnR5IHdpbGwgcmVwb3J0IHdoYXQKICAgICAga2luZCBvZiBjaGFuZ2UgaGFzIGNhdXNlZCBpdCB0byBtb3ZlIGludG8gdGhlIGRpcnR5CiAgICAgIHN0YXRlLiBQb3NzaWJsZSB2YWx1ZXMgYXJlOgogICAgICAgLSBgY3JlYXRlZGAgVGhlIHJlY29yZCBoYXMgYmVlbiBjcmVhdGVkIGJ5IHRoZSBjbGllbnQgYW5kIG5vdCB5ZXQgc2F2ZWQgdG8gdGhlIGFkYXB0ZXIuCiAgICAgIC0gYHVwZGF0ZWRgIFRoZSByZWNvcmQgaGFzIGJlZW4gdXBkYXRlZCBieSB0aGUgY2xpZW50IGFuZCBub3QgeWV0IHNhdmVkIHRvIHRoZSBhZGFwdGVyLgogICAgICAtIGBkZWxldGVkYCBUaGUgcmVjb3JkIGhhcyBiZWVuIGRlbGV0ZWQgYnkgdGhlIGNsaWVudCBhbmQgbm90IHlldCBzYXZlZCB0byB0aGUgYWRhcHRlci4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IHJlY29yZCA9IHN0b3JlLmNyZWF0ZVJlY29yZCgnbW9kZWwnKTsKICAgICAgcmVjb3JkLmdldCgnZGlydHlUeXBlJyk7IC8vICdjcmVhdGVkJwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBkaXJ0eVR5cGUKICAgICAgQHR5cGUge1N0cmluZ30KICAgICAgQHJlYWRPbmx5CiAgICAqLwogICAgZGlydHlUeXBlOiByZXRyaWV2ZUZyb21DdXJyZW50U3RhdGUsCgogICAgLyoqCiAgICAgIElmIGB0cnVlYCB0aGUgYWRhcHRlciByZXBvcnRlZCB0aGF0IGl0IHdhcyB1bmFibGUgdG8gc2F2ZSBsb2NhbAogICAgICBjaGFuZ2VzIHRvIHRoZSBiYWNrZW5kIGZvciBhbnkgcmVhc29uIG90aGVyIHRoYW4gYSBzZXJ2ZXItc2lkZQogICAgICB2YWxpZGF0aW9uIGVycm9yLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICByZWNvcmQuZ2V0KCdpc0Vycm9yJyk7IC8vIGZhbHNlCiAgICAgIHJlY29yZC5zZXQoJ2ZvbycsICd2YWxpZCB2YWx1ZScpOwogICAgICByZWNvcmQuc2F2ZSgpLnRoZW4obnVsbCwgZnVuY3Rpb24oKSB7CiAgICAgICAgcmVjb3JkLmdldCgnaXNFcnJvcicpOyAvLyB0cnVlCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBpc0Vycm9yCiAgICAgIEB0eXBlIHtCb29sZWFufQogICAgICBAcmVhZE9ubHkKICAgICovCiAgICBpc0Vycm9yOiBpc0Vycm9yLAogICAgX21hcmtFcnJvclJlcXVlc3RBc0NsZWFuOiBmdW5jdGlvbiBfbWFya0Vycm9yUmVxdWVzdEFzQ2xlYW4oKSB7CiAgICAgIHRoaXMuX2Vycm9yUmVxdWVzdHMgPSBbXTsKICAgICAgdGhpcy5fbGFzdEVycm9yID0gbnVsbDsKCiAgICAgIHRoaXMuX25vdGlmeU5ldHdvcmtDaGFuZ2VzKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBJZiBgdHJ1ZWAgdGhlIHN0b3JlIGlzIGF0dGVtcHRpbmcgdG8gcmVsb2FkIHRoZSByZWNvcmQgZnJvbSB0aGUgYWRhcHRlci4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgcmVjb3JkLmdldCgnaXNSZWxvYWRpbmcnKTsgLy8gZmFsc2UKICAgICAgcmVjb3JkLnJlbG9hZCgpOwogICAgICByZWNvcmQuZ2V0KCdpc1JlbG9hZGluZycpOyAvLyB0cnVlCiAgICAgIGBgYAogICAgICAgQHByb3BlcnR5IGlzUmVsb2FkaW5nCiAgICAgIEB0eXBlIHtCb29sZWFufQogICAgICBAcmVhZE9ubHkKICAgICovCiAgICBpc1JlbG9hZGluZzogaXNSZWxvYWRpbmcsCgogICAgLyoqCiAgICAgIEFsbCBlbWJlciBtb2RlbHMgaGF2ZSBhbiBpZCBwcm9wZXJ0eS4gVGhpcyBpcyBhbiBpZGVudGlmaWVyCiAgICAgIG1hbmFnZWQgYnkgYW4gZXh0ZXJuYWwgc291cmNlLiBUaGVzZSBhcmUgYWx3YXlzIGNvZXJjZWQgdG8gYmUKICAgICAgc3RyaW5ncyBiZWZvcmUgYmVpbmcgdXNlZCBpbnRlcm5hbGx5LiBOb3RlIHdoZW4gZGVjbGFyaW5nIHRoZQogICAgICBhdHRyaWJ1dGVzIGZvciBhIG1vZGVsIGl0IGlzIGFuIGVycm9yIHRvIGRlY2xhcmUgYW4gaWQKICAgICAgYXR0cmlidXRlLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgcmVjb3JkID0gc3RvcmUuY3JlYXRlUmVjb3JkKCdtb2RlbCcpOwogICAgICByZWNvcmQuZ2V0KCdpZCcpOyAvLyBudWxsCiAgICAgICBzdG9yZS5maW5kUmVjb3JkKCdtb2RlbCcsIDEpLnRoZW4oZnVuY3Rpb24obW9kZWwpIHsKICAgICAgICBtb2RlbC5nZXQoJ2lkJyk7IC8vICcxJwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAcHJvcGVydHkgaWQKICAgICAgQHR5cGUge1N0cmluZ30KICAgICovCgogICAgLyoqCiAgICAgIEBwcm9wZXJ0eSBjdXJyZW50U3RhdGUKICAgICAgQHByaXZhdGUKICAgICAgQHR5cGUge09iamVjdH0KICAgICovCiAgICBjdXJyZW50U3RhdGU6IFByaXZhdGUuUm9vdFN0YXRlLmVtcHR5LAogICAgLy8gZGVmaW5lZCBoZXJlIHRvIGF2b2lkIHRyaWdnZXJpbmcgc2V0VW5rbm93blByb3BlcnR5CgogICAgLyoqCiAgICAgQHByb3BlcnR5IF9pbnRlcm5hbE1vZGVsCiAgICAgQHByaXZhdGUKICAgICBAdHlwZSB7T2JqZWN0fQogICAgICovCiAgICBfaW50ZXJuYWxNb2RlbDogbnVsbCwKICAgIC8vIGRlZmluZWQgaGVyZSB0byBhdm9pZCB0cmlnZ2VyaW5nIHNldFVua25vd25Qcm9wZXJ0eQoKICAgIC8qKgogICAgIEBwcm9wZXJ0eSByZWNvcmREYXRhCiAgICAgQHByaXZhdGUKICAgICBAdHlwZSB1bmRlZmluZWQgKHJlc2VydmVkKQogICAgICovCiAgICAvLyB3aWxsIGJlIGRlZmluZWQgaGVyZSB0byBhdm9pZCB0cmlnZ2VyaW5nIHNldFVua25vd25Qcm9wZXJ0eQoKICAgIC8qKgogICAgIEBwcm9wZXJ0eSBzdG9yZQogICAgICovCiAgICBzdG9yZTogbnVsbCwKICAgIC8vIGRlZmluZWQgaGVyZSB0byBhdm9pZCB0cmlnZ2VyaW5nIHNldFVua25vd25Qcm9wZXJ0eQoKICAgIC8qKgogICAgICBXaGVuIHRoZSByZWNvcmQgaXMgaW4gdGhlIGBpbnZhbGlkYCBzdGF0ZSB0aGlzIG9iamVjdCB3aWxsIGNvbnRhaW4KICAgICAgYW55IGVycm9ycyByZXR1cm5lZCBieSB0aGUgYWRhcHRlci4gV2hlbiBwcmVzZW50IHRoZSBlcnJvcnMgaGFzaAogICAgICBjb250YWlucyBrZXlzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGludmFsaWQgcHJvcGVydHkgbmFtZXMKICAgICAgYW5kIHZhbHVlcyB3aGljaCBhcmUgYXJyYXlzIG9mIEphdmFzY3JpcHQgb2JqZWN0cyB3aXRoIHR3byBrZXlzOgogICAgICAgLSBgbWVzc2FnZWAgQSBzdHJpbmcgY29udGFpbmluZyB0aGUgZXJyb3IgbWVzc2FnZSBmcm9tIHRoZSBiYWNrZW5kCiAgICAgIC0gYGF0dHJpYnV0ZWAgVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IGFzc29jaWF0ZWQgd2l0aCB0aGlzIGVycm9yIG1lc3NhZ2UKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgcmVjb3JkLmdldCgnZXJyb3JzLmxlbmd0aCcpOyAvLyAwCiAgICAgIHJlY29yZC5zZXQoJ2ZvbycsICdpbnZhbGlkIHZhbHVlJyk7CiAgICAgIHJlY29yZC5zYXZlKCkuY2F0Y2goZnVuY3Rpb24oKSB7CiAgICAgICAgcmVjb3JkLmdldCgnZXJyb3JzJykuZ2V0KCdmb28nKTsKICAgICAgICAvLyBbe21lc3NhZ2U6ICdmb28gc2hvdWxkIGJlIGEgbnVtYmVyLicsIGF0dHJpYnV0ZTogJ2Zvbyd9XQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBUaGUgYGVycm9yc2AgcHJvcGVydHkgdXMgdXNlZnVsIGZvciBkaXNwbGF5aW5nIGVycm9yIG1lc3NhZ2VzIHRvCiAgICAgIHRoZSB1c2VyLgogICAgICAgYGBgaGFuZGxlYmFycwogICAgICA8bGFiZWw+VXNlcm5hbWU6IHt7aW5wdXQgdmFsdWU9dXNlcm5hbWV9fSA8L2xhYmVsPgogICAgICB7eyNlYWNoIG1vZGVsLmVycm9ycy51c2VybmFtZSBhcyB8ZXJyb3J8fX0KICAgICAgICA8ZGl2IGNsYXNzPSJlcnJvciI+CiAgICAgICAgICB7e2Vycm9yLm1lc3NhZ2V9fQogICAgICAgIDwvZGl2PgogICAgICB7ey9lYWNofX0KICAgICAgPGxhYmVsPkVtYWlsOiB7e2lucHV0IHZhbHVlPWVtYWlsfX0gPC9sYWJlbD4KICAgICAge3sjZWFjaCBtb2RlbC5lcnJvcnMuZW1haWwgYXMgfGVycm9yfH19CiAgICAgICAgPGRpdiBjbGFzcz0iZXJyb3IiPgogICAgICAgICAge3tlcnJvci5tZXNzYWdlfX0KICAgICAgICA8L2Rpdj4KICAgICAge3svZWFjaH19CiAgICAgIGBgYAogICAgICAgIFlvdSBjYW4gYWxzbyBhY2Nlc3MgdGhlIHNwZWNpYWwgYG1lc3NhZ2VzYCBwcm9wZXJ0eSBvbiB0aGUgZXJyb3IKICAgICAgb2JqZWN0IHRvIGdldCBhbiBhcnJheSBvZiBhbGwgdGhlIGVycm9yIHN0cmluZ3MuCiAgICAgICBgYGBoYW5kbGViYXJzCiAgICAgIHt7I2VhY2ggbW9kZWwuZXJyb3JzLm1lc3NhZ2VzIGFzIHxtZXNzYWdlfH19CiAgICAgICAgPGRpdiBjbGFzcz0iZXJyb3IiPgogICAgICAgICAge3ttZXNzYWdlfX0KICAgICAgICA8L2Rpdj4KICAgICAge3svZWFjaH19CiAgICAgIGBgYAogICAgICAgQHByb3BlcnR5IGVycm9ycwogICAgICBAdHlwZSB7RXJyb3JzfQogICAgKi8KICAgIGVycm9yczogRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHZhciBlcnJvcnMgPSBQcml2YXRlLkVycm9ycy5jcmVhdGUoKTsKCiAgICAgIGVycm9ycy5fcmVnaXN0ZXJIYW5kbGVycyhmdW5jdGlvbiAoKSB7CiAgICAgICAgX3RoaXMzLnNlbmQoJ2JlY2FtZUludmFsaWQnKTsKICAgICAgfSwgZnVuY3Rpb24gKCkgewogICAgICAgIF90aGlzMy5zZW5kKCdiZWNhbWVWYWxpZCcpOwogICAgICB9KTsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9FUlJPUlMpIHsKICAgICAgICB2YXIgcmVjb3JkRGF0YSA9IFByaXZhdGUucmVjb3JkRGF0YUZvcih0aGlzKTsKICAgICAgICB2YXIganNvbkFwaUVycm9yczsKCiAgICAgICAgaWYgKHJlY29yZERhdGEuZ2V0RXJyb3JzKSB7CiAgICAgICAgICBqc29uQXBpRXJyb3JzID0gcmVjb3JkRGF0YS5nZXRFcnJvcnMoKTsKCiAgICAgICAgICBpZiAoanNvbkFwaUVycm9ycykgewogICAgICAgICAgICB2YXIgZXJyb3JzSGFzaCA9IFByaXZhdGUuZXJyb3JzQXJyYXlUb0hhc2goanNvbkFwaUVycm9ycyk7CiAgICAgICAgICAgIHZhciBlcnJvcktleXMgPSBPYmplY3Qua2V5cyhlcnJvcnNIYXNoKTsKCiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXJyb3JLZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgZXJyb3JzLl9hZGQoZXJyb3JLZXlzW2ldLCBlcnJvcnNIYXNoW2Vycm9yS2V5c1tpXV0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gZXJyb3JzOwogICAgfSkucmVhZE9ubHkoKSwKICAgIGludmFsaWRFcnJvcnNDaGFuZ2VkOiBmdW5jdGlvbiBpbnZhbGlkRXJyb3JzQ2hhbmdlZChqc29uQXBpRXJyb3JzKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9FUlJPUlMpIHsKICAgICAgICB0aGlzLl9jbGVhckVycm9yTWVzc2FnZXMoKTsKCiAgICAgICAgdmFyIGVycm9ycyA9IFByaXZhdGUuZXJyb3JzQXJyYXlUb0hhc2goanNvbkFwaUVycm9ycyk7CiAgICAgICAgdmFyIGVycm9yS2V5cyA9IE9iamVjdC5rZXlzKGVycm9ycyk7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXJyb3JLZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICB0aGlzLl9hZGRFcnJvck1lc3NhZ2VUb0F0dHJpYnV0ZShlcnJvcktleXNbaV0sIGVycm9yc1tlcnJvcktleXNbaV1dKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0sCiAgICBfYWRkRXJyb3JNZXNzYWdlVG9BdHRyaWJ1dGU6IGZ1bmN0aW9uIF9hZGRFcnJvck1lc3NhZ2VUb0F0dHJpYnV0ZShhdHRyaWJ1dGUsIG1lc3NhZ2UpIHsKICAgICAgdGhpcy5nZXQoJ2Vycm9ycycpLl9hZGQoYXR0cmlidXRlLCBtZXNzYWdlKTsKICAgIH0sCiAgICBfY2xlYXJFcnJvck1lc3NhZ2VzOiBmdW5jdGlvbiBfY2xlYXJFcnJvck1lc3NhZ2VzKCkgewogICAgICB0aGlzLmdldCgnZXJyb3JzJykuX2NsZWFyKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBUaGlzIHByb3BlcnR5IGhvbGRzIHRoZSBgQWRhcHRlckVycm9yYCBvYmplY3Qgd2l0aCB3aGljaAogICAgICBsYXN0IGFkYXB0ZXIgb3BlcmF0aW9uIHdhcyByZWplY3RlZC4KICAgICAgIEBwcm9wZXJ0eSBhZGFwdGVyRXJyb3IKICAgICAgQHR5cGUge0FkYXB0ZXJFcnJvcn0KICAgICovCiAgICBhZGFwdGVyRXJyb3I6IGFkYXB0ZXJFcnJvciwKCiAgICAvKioKICAgICAgQ3JlYXRlIGEgSlNPTiByZXByZXNlbnRhdGlvbiBvZiB0aGUgcmVjb3JkLCB1c2luZyB0aGUgc2VyaWFsaXphdGlvbgogICAgICBzdHJhdGVneSBvZiB0aGUgc3RvcmUncyBhZGFwdGVyLgogICAgICBgc2VyaWFsaXplYCB0YWtlcyBhbiBvcHRpb25hbCBoYXNoIGFzIGEgcGFyYW1ldGVyLCBjdXJyZW50bHkKICAgICAgc3VwcG9ydGVkIG9wdGlvbnMgYXJlOgogICAgICAtIGBpbmNsdWRlSWRgOiBgdHJ1ZWAgaWYgdGhlIHJlY29yZCdzIElEIHNob3VsZCBiZSBpbmNsdWRlZCBpbiB0aGUKICAgICAgICBKU09OIHJlcHJlc2VudGF0aW9uLgogICAgICAgQG1ldGhvZCBzZXJpYWxpemUKICAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAgQHJldHVybiB7T2JqZWN0fSBhbiBvYmplY3Qgd2hvc2UgdmFsdWVzIGFyZSBwcmltaXRpdmUgSlNPTiB2YWx1ZXMgb25seQogICAgKi8KICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gc2VyaWFsaXplKG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMuX2ludGVybmFsTW9kZWwuY3JlYXRlU25hcHNob3QoKS5zZXJpYWxpemUob3B0aW9ucyk7CiAgICB9LAoKICAgIC8qKgogICAgICBVc2UgW0pTT05TZXJpYWxpemVyXShKU09OU2VyaWFsaXplci5odG1sKSB0bwogICAgICBnZXQgdGhlIEpTT04gcmVwcmVzZW50YXRpb24gb2YgYSByZWNvcmQuCiAgICAgICBgdG9KU09OYCB0YWtlcyBhbiBvcHRpb25hbCBoYXNoIGFzIGEgcGFyYW1ldGVyLCBjdXJyZW50bHkKICAgICAgc3VwcG9ydGVkIG9wdGlvbnMgYXJlOgogICAgICAgLSBgaW5jbHVkZUlkYDogYHRydWVgIGlmIHRoZSByZWNvcmQncyBJRCBzaG91bGQgYmUgaW5jbHVkZWQgaW4gdGhlCiAgICAgICAgSlNPTiByZXByZXNlbnRhdGlvbi4KICAgICAgIEBtZXRob2QgdG9KU09OCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgIEByZXR1cm4ge09iamVjdH0gQSBKU09OIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBvYmplY3QuCiAgICAqLwogICAgdG9KU09OOiBmdW5jdGlvbiB0b0pTT04ob3B0aW9ucykgewoKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSB0aGlzLl9pbnRlcm5hbE1vZGVsLnN0b3JlLnNlcmlhbGl6ZXJGb3IoJy1kZWZhdWx0Jyk7CgogICAgICB2YXIgc25hcHNob3QgPSB0aGlzLl9pbnRlcm5hbE1vZGVsLmNyZWF0ZVNuYXBzaG90KCk7CgogICAgICByZXR1cm4gc2VyaWFsaXplci5zZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpOwogICAgfSwKCiAgICAvKioKICAgICAgRmlyZWQgd2hlbiB0aGUgcmVjb3JkIGlzIHJlYWR5IHRvIGJlIGludGVyYWN0ZWQgd2l0aCwKICAgICAgdGhhdCBpcyBlaXRoZXIgbG9hZGVkIGZyb20gdGhlIHNlcnZlciBvciBjcmVhdGVkIGxvY2FsbHkuCiAgICAgICBAZXZlbnQgcmVhZHkKICAgICovCiAgICByZWFkeTogbnVsbCwKCiAgICAvKioKICAgICAgRmlyZWQgd2hlbiB0aGUgcmVjb3JkIGlzIGxvYWRlZCBmcm9tIHRoZSBzZXJ2ZXIuCiAgICAgICBAZXZlbnQgZGlkTG9hZAogICAgKi8KICAgIGRpZExvYWQ6IG51bGwsCgogICAgLyoqCiAgICAgIEZpcmVkIHdoZW4gdGhlIHJlY29yZCBpcyB1cGRhdGVkLgogICAgICAgQGV2ZW50IGRpZFVwZGF0ZQogICAgKi8KICAgIGRpZFVwZGF0ZTogbnVsbCwKCiAgICAvKioKICAgICAgRmlyZWQgd2hlbiBhIG5ldyByZWNvcmQgaXMgY29tbWl0ZWQgdG8gdGhlIHNlcnZlci4KICAgICAgIEBldmVudCBkaWRDcmVhdGUKICAgICovCiAgICBkaWRDcmVhdGU6IG51bGwsCgogICAgLyoqCiAgICAgIEZpcmVkIHdoZW4gdGhlIHJlY29yZCBpcyBkZWxldGVkLgogICAgICAgQGV2ZW50IGRpZERlbGV0ZQogICAgKi8KICAgIGRpZERlbGV0ZTogbnVsbCwKCiAgICAvKioKICAgICAgRmlyZWQgd2hlbiB0aGUgcmVjb3JkIGJlY29tZXMgaW52YWxpZC4KICAgICAgIEBldmVudCBiZWNhbWVJbnZhbGlkCiAgICAqLwogICAgYmVjYW1lSW52YWxpZDogbnVsbCwKCiAgICAvKioKICAgICAgRmlyZWQgd2hlbiB0aGUgcmVjb3JkIGVudGVycyB0aGUgZXJyb3Igc3RhdGUuCiAgICAgICBAZXZlbnQgYmVjYW1lRXJyb3IKICAgICovCiAgICBiZWNhbWVFcnJvcjogbnVsbCwKCiAgICAvKioKICAgICAgRmlyZWQgd2hlbiB0aGUgcmVjb3JkIGlzIHJvbGxlZCBiYWNrLgogICAgICAgQGV2ZW50IHJvbGxlZEJhY2sKICAgICovCiAgICByb2xsZWRCYWNrOiBudWxsLAogICAgLy9UT0RPIERvIHdlIHdhbnQgdG8gZGVwcmVjYXRlIHRoZXNlPwoKICAgIC8qKgogICAgICBAbWV0aG9kIHNlbmQKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUKICAgICAgQHBhcmFtIHtPYmplY3R9IGNvbnRleHQKICAgICovCiAgICBzZW5kOiBmdW5jdGlvbiBzZW5kKG5hbWUsIGNvbnRleHQpIHsKICAgICAgcmV0dXJuIHRoaXMuX2ludGVybmFsTW9kZWwuc2VuZChuYW1lLCBjb250ZXh0KTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBtZXRob2QgdHJhbnNpdGlvblRvCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lCiAgICAqLwogICAgdHJhbnNpdGlvblRvOiBmdW5jdGlvbiB0cmFuc2l0aW9uVG8obmFtZSkgewogICAgICByZXR1cm4gdGhpcy5faW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8obmFtZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBNYXJrcyB0aGUgcmVjb3JkIGFzIGRlbGV0ZWQgYnV0IGRvZXMgbm90IHNhdmUgaXQuIFlvdSBtdXN0IGNhbGwKICAgICAgYHNhdmVgIGFmdGVyd2FyZHMgaWYgeW91IHdhbnQgdG8gcGVyc2lzdCBpdC4gWW91IG1pZ2h0IHVzZSB0aGlzCiAgICAgIG1ldGhvZCBpZiB5b3Ugd2FudCB0byBhbGxvdyB0aGUgdXNlciB0byBzdGlsbCBgcm9sbGJhY2tBdHRyaWJ1dGVzKClgCiAgICAgIGFmdGVyIGEgZGVsZXRlIHdhcyBtYWRlLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3JvdXRlcy9tb2RlbC9kZWxldGUuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgc29mdERlbGV0ZSgpIHsKICAgICAgICAgICAgdGhpcy5nZXQoJ2NvbnRyb2xsZXIubW9kZWwnKS5kZWxldGVSZWNvcmQoKTsKICAgICAgICAgIH0sCiAgICAgICAgICBjb25maXJtKCkgewogICAgICAgICAgICB0aGlzLmdldCgnY29udHJvbGxlci5tb2RlbCcpLnNhdmUoKTsKICAgICAgICAgIH0sCiAgICAgICAgICB1bmRvKCkgewogICAgICAgICAgICB0aGlzLmdldCgnY29udHJvbGxlci5tb2RlbCcpLnJvbGxiYWNrQXR0cmlidXRlcygpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBkZWxldGVSZWNvcmQKICAgICovCiAgICBkZWxldGVSZWNvcmQ6IGZ1bmN0aW9uIGRlbGV0ZVJlY29yZCgpIHsKICAgICAgdGhpcy5faW50ZXJuYWxNb2RlbC5kZWxldGVSZWNvcmQoKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFNhbWUgYXMgYGRlbGV0ZVJlY29yZGAsIGJ1dCBzYXZlcyB0aGUgcmVjb3JkIGltbWVkaWF0ZWx5LgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3JvdXRlcy9tb2RlbC9kZWxldGUuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgYWN0aW9uczogewogICAgICAgICAgZGVsZXRlKCkgewogICAgICAgICAgICB0aGlzLmdldCgnY29udHJvbGxlci5tb2RlbCcpLmRlc3Ryb3lSZWNvcmQoKS50aGVuKGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIGNvbnRyb2xsZXIudHJhbnNpdGlvblRvUm91dGUoJ21vZGVsLmluZGV4Jyk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgSWYgeW91IHBhc3MgYW4gb2JqZWN0IG9uIHRoZSBgYWRhcHRlck9wdGlvbnNgIHByb3BlcnR5IG9mIHRoZSBvcHRpb25zCiAgICAgIGFyZ3VtZW50IGl0IHdpbGwgYmUgcGFzc2VkIHRvIHlvdXIgYWRhcHRlciB2aWEgdGhlIHNuYXBzaG90CiAgICAgICBgYGBqcwogICAgICByZWNvcmQuZGVzdHJveVJlY29yZCh7IGFkYXB0ZXJPcHRpb25zOiB7IHN1YnNjcmliZTogZmFsc2UgfSB9KTsKICAgICAgYGBgCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvcG9zdC5qcwogICAgICBpbXBvcnQgTXlDdXN0b21BZGFwdGVyIGZyb20gJy4vY3VzdG9tLWFkYXB0ZXInOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTXlDdXN0b21BZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgZGVsZXRlUmVjb3JkKHN0b3JlLCB0eXBlLCBzbmFwc2hvdCkgewogICAgICAgICAgaWYgKHNuYXBzaG90LmFkYXB0ZXJPcHRpb25zLnN1YnNjcmliZSkgewogICAgICAgICAgICAvLyAuLi4KICAgICAgICAgIH0KICAgICAgICAgIC8vIC4uLgogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBkZXN0cm95UmVjb3JkCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IHdpbGwgYmUgcmVzb2x2ZWQgd2hlbiB0aGUgYWRhcHRlciByZXR1cm5zCiAgICAgIHN1Y2Nlc3NmdWxseSBvciByZWplY3RlZCBpZiB0aGUgYWRhcHRlciByZXR1cm5zIHdpdGggYW4gZXJyb3IuCiAgICAqLwogICAgZGVzdHJveVJlY29yZDogZnVuY3Rpb24gZGVzdHJveVJlY29yZChvcHRpb25zKSB7CiAgICAgIHRoaXMuZGVsZXRlUmVjb3JkKCk7CiAgICAgIHJldHVybiB0aGlzLnNhdmUob3B0aW9ucyk7CiAgICB9LAoKICAgIC8qKgogICAgICBVbmxvYWRzIHRoZSByZWNvcmQgZnJvbSB0aGUgc3RvcmUuIFRoaXMgd2lsbCBub3Qgc2VuZCBhIGRlbGV0ZSByZXF1ZXN0CiAgICAgIHRvIHlvdXIgc2VydmVyLCBpdCBqdXN0IHVubG9hZHMgdGhlIHJlY29yZCBmcm9tIG1lbW9yeS4KICAgICAgIEBtZXRob2QgdW5sb2FkUmVjb3JkCiAgICAqLwogICAgdW5sb2FkUmVjb3JkOiBmdW5jdGlvbiB1bmxvYWRSZWNvcmQoKSB7CiAgICAgIGlmICh0aGlzLmlzRGVzdHJveWVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9pbnRlcm5hbE1vZGVsLnVubG9hZFJlY29yZCgpOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBfbm90aWZ5UHJvcGVydGllcwogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ub3RpZnlQcm9wZXJ0aWVzOiBmdW5jdGlvbiBfbm90aWZ5UHJvcGVydGllcyhrZXlzKSB7CiAgICAgIHZhciBfdGhpczQgPSB0aGlzOwoKICAgICAgLy8gY2hhbmdlUHJvcGVydGllcyBkZWZlcnMgbm90aWZpY2F0aW9ucyB1bnRpbCBhZnRlciB0aGUgZGVsZWdhdGUKICAgICAgLy8gYW5kIHByb3RlY3RzIHdpdGggYSB0cnkuLi5maW5hbGx5IGJsb2NrCiAgICAgIC8vIHByZXZpb3VzbHkgdXNlZCBiZWdpbi4uLmVuZFByb3BlcnR5Q2hhbmdlcyBidXQgdGhpcyBpcyBwcml2YXRlIEFQSQogICAgICBjaGFuZ2VQcm9wZXJ0aWVzKGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIga2V5OwoKICAgICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0ga2V5cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAga2V5ID0ga2V5c1tpXTsKCiAgICAgICAgICBfdGhpczQubm90aWZ5UHJvcGVydHlDaGFuZ2Uoa2V5KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICAgUmV0dXJucyBhbiBvYmplY3QsIHdob3NlIGtleXMgYXJlIGNoYW5nZWQgcHJvcGVydGllcywgYW5kIHZhbHVlIGlzCiAgICAgIGFuIFtvbGRQcm9wLCBuZXdQcm9wXSBhcnJheS4KICAgICAgIFRoZSBhcnJheSByZXByZXNlbnRzIHRoZSBkaWZmIG9mIHRoZSBjYW5vbmljYWwgc3RhdGUgd2l0aCB0aGUgbG9jYWwgc3RhdGUKICAgICAgb2YgdGhlIG1vZGVsLiBOb3RlOiBpZiB0aGUgbW9kZWwgaXMgY3JlYXRlZCBsb2NhbGx5LCB0aGUgY2Fub25pY2FsIHN0YXRlIGlzCiAgICAgIGVtcHR5IHNpbmNlIHRoZSBhZGFwdGVyIGhhc24ndCBhY2tub3dsZWRnZWQgdGhlIGF0dHJpYnV0ZXMgeWV0OgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL21vZGVscy9tYXNjb3QuanMKICAgICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIG5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICAgIGlzQWRtaW46IGF0dHIoJ2Jvb2xlYW4nLCB7CiAgICAgICAgICBkZWZhdWx0VmFsdWU6IGZhbHNlCiAgICAgICAgfSkKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgbWFzY290ID0gc3RvcmUuY3JlYXRlUmVjb3JkKCdtYXNjb3QnKTsKICAgICAgIG1hc2NvdC5jaGFuZ2VkQXR0cmlidXRlcygpOyAvLyB7fQogICAgICAgbWFzY290LnNldCgnbmFtZScsICdUb21zdGVyJyk7CiAgICAgIG1hc2NvdC5jaGFuZ2VkQXR0cmlidXRlcygpOyAvLyB7IG5hbWU6IFt1bmRlZmluZWQsICdUb21zdGVyJ10gfQogICAgICAgbWFzY290LnNldCgnaXNBZG1pbicsIHRydWUpOwogICAgICBtYXNjb3QuY2hhbmdlZEF0dHJpYnV0ZXMoKTsgLy8geyBpc0FkbWluOiBbdW5kZWZpbmVkLCB0cnVlXSwgbmFtZTogW3VuZGVmaW5lZCwgJ1RvbXN0ZXInXSB9CiAgICAgICBtYXNjb3Quc2F2ZSgpLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgICAgbWFzY290LmNoYW5nZWRBdHRyaWJ1dGVzKCk7IC8vIHt9CiAgICAgICAgIG1hc2NvdC5zZXQoJ2lzQWRtaW4nLCBmYWxzZSk7CiAgICAgICAgbWFzY290LmNoYW5nZWRBdHRyaWJ1dGVzKCk7IC8vIHsgaXNBZG1pbjogW3RydWUsIGZhbHNlXSB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgY2hhbmdlZEF0dHJpYnV0ZXMKICAgICAgQHJldHVybiB7T2JqZWN0fSBhbiBvYmplY3QsIHdob3NlIGtleXMgYXJlIGNoYW5nZWQgcHJvcGVydGllcywKICAgICAgICBhbmQgdmFsdWUgaXMgYW4gW29sZFByb3AsIG5ld1Byb3BdIGFycmF5LgogICAgKi8KICAgIGNoYW5nZWRBdHRyaWJ1dGVzOiBmdW5jdGlvbiBjaGFuZ2VkQXR0cmlidXRlcygpIHsKICAgICAgcmV0dXJuIHRoaXMuX2ludGVybmFsTW9kZWwuY2hhbmdlZEF0dHJpYnV0ZXMoKTsKICAgIH0sCgogICAgLyoqCiAgICAgIElmIHRoZSBtb2RlbCBgaGFzRGlydHlBdHRyaWJ1dGVzYCB0aGlzIGZ1bmN0aW9uIHdpbGwgZGlzY2FyZCBhbnkgdW5zYXZlZAogICAgICBjaGFuZ2VzLiBJZiB0aGUgbW9kZWwgYGlzTmV3YCBpdCB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgc3RvcmUuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHJlY29yZC5nZXQoJ25hbWUnKTsgLy8gJ1VudGl0bGVkIERvY3VtZW50JwogICAgICByZWNvcmQuc2V0KCduYW1lJywgJ0RvYyAxJyk7CiAgICAgIHJlY29yZC5nZXQoJ25hbWUnKTsgLy8gJ0RvYyAxJwogICAgICByZWNvcmQucm9sbGJhY2tBdHRyaWJ1dGVzKCk7CiAgICAgIHJlY29yZC5nZXQoJ25hbWUnKTsgLy8gJ1VudGl0bGVkIERvY3VtZW50JwogICAgICBgYGAKICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCByb2xsYmFja0F0dHJpYnV0ZXMKICAgICovCiAgICByb2xsYmFja0F0dHJpYnV0ZXM6IGZ1bmN0aW9uIHJvbGxiYWNrQXR0cmlidXRlcygpIHsKICAgICAgdGhpcy5faW50ZXJuYWxNb2RlbC5yb2xsYmFja0F0dHJpYnV0ZXMoKTsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9FUlJPUlMpIHsKICAgICAgICB0aGlzLl9tYXJrSW52YWxpZFJlcXVlc3RBc0NsZWFuKCk7CiAgICAgIH0KCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICB0aGlzLl9tYXJrRXJyb3JSZXF1ZXN0QXNDbGVhbigpOwogICAgICB9CiAgICB9LAoKICAgIC8qCiAgICAgIEBtZXRob2QgX2NyZWF0ZVNuYXBzaG90CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX2NyZWF0ZVNuYXBzaG90OiBmdW5jdGlvbiBfY3JlYXRlU25hcHNob3QoKSB7CiAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsLmNyZWF0ZVNuYXBzaG90KCk7CiAgICB9LAogICAgdG9TdHJpbmdFeHRlbnNpb246IGZ1bmN0aW9uIHRvU3RyaW5nRXh0ZW5zaW9uKCkgewogICAgICAvLyB0aGUgX2ludGVybmFsTW9kZWwgZ3VhcmQgZXhpc3RzLCBiZWNhdXNlIHNvbWUgZGV2LW9ubHkgZGVwcmVjYXRpb24gY29kZQogICAgICAvLyAoYWRkTGlzdGVuZXIgdmlhIHZhbGlkYXRlUHJvcGVydHlJbmplY3Rpb25zKSBpbnZva2VzIHRvU3RyaW5nIGJlZm9yZSB0aGUKICAgICAgLy8gb2JqZWN0IGlzIHJlYWwuCiAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsICYmIHRoaXMuX2ludGVybmFsTW9kZWwuaWQ7CiAgICB9LAoKICAgIC8qKgogICAgICBTYXZlIHRoZSByZWNvcmQgYW5kIHBlcnNpc3QgYW55IGNoYW5nZXMgdG8gdGhlIHJlY29yZCB0byBhbgogICAgICBleHRlcm5hbCBzb3VyY2UgdmlhIHRoZSBhZGFwdGVyLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICByZWNvcmQuc2V0KCduYW1lJywgJ1RvbXN0ZXInKTsKICAgICAgcmVjb3JkLnNhdmUoKS50aGVuKGZ1bmN0aW9uKCkgewogICAgICAgIC8vIFN1Y2Nlc3MgY2FsbGJhY2sKICAgICAgfSwgZnVuY3Rpb24oKSB7CiAgICAgICAgLy8gRXJyb3IgY2FsbGJhY2sKICAgICAgfSk7CiAgICAgIGBgYAogICAgICBJZiB5b3UgcGFzcyBhbiBvYmplY3QgdXNpbmcgdGhlIGBhZGFwdGVyT3B0aW9uc2AgcHJvcGVydHkgb2YgdGhlIG9wdGlvbnMKICAgICBhcmd1bWVudCBpdCB3aWxsIGJlIHBhc3NlZCB0byB5b3VyIGFkYXB0ZXIgdmlhIHRoZSBzbmFwc2hvdC4KICAgICAgIGBgYGpzCiAgICAgIHJlY29yZC5zYXZlKHsgYWRhcHRlck9wdGlvbnM6IHsgc3Vic2NyaWJlOiBmYWxzZSB9IH0pOwogICAgICBgYGAKICAgICAgIGBgYGFwcC9hZGFwdGVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBNeUN1c3RvbUFkYXB0ZXIgZnJvbSAnLi9jdXN0b20tYWRhcHRlcic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBNeUN1c3RvbUFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICB1cGRhdGVSZWNvcmQoc3RvcmUsIHR5cGUsIHNuYXBzaG90KSB7CiAgICAgICAgICBpZiAoc25hcHNob3QuYWRhcHRlck9wdGlvbnMuc3Vic2NyaWJlKSB7CiAgICAgICAgICAgIC8vIC4uLgogICAgICAgICAgfQogICAgICAgICAgLy8gLi4uCiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHNhdmUKICAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAgQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHRoYXQgd2lsbCBiZSByZXNvbHZlZCB3aGVuIHRoZSBhZGFwdGVyIHJldHVybnMKICAgICAgc3VjY2Vzc2Z1bGx5IG9yIHJlamVjdGVkIGlmIHRoZSBhZGFwdGVyIHJldHVybnMgd2l0aCBhbiBlcnJvci4KICAgICovCiAgICBzYXZlOiBmdW5jdGlvbiBzYXZlKG9wdGlvbnMpIHsKICAgICAgdmFyIF90aGlzNSA9IHRoaXM7CgogICAgICByZXR1cm4gUHJpdmF0ZS5Qcm9taXNlT2JqZWN0LmNyZWF0ZSh7CiAgICAgICAgcHJvbWlzZTogdGhpcy5faW50ZXJuYWxNb2RlbC5zYXZlKG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuIF90aGlzNTsKICAgICAgICB9KQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIFJlbG9hZCB0aGUgcmVjb3JkIGZyb20gdGhlIGFkYXB0ZXIuCiAgICAgICBUaGlzIHdpbGwgb25seSB3b3JrIGlmIHRoZSByZWNvcmQgaGFzIGFscmVhZHkgZmluaXNoZWQgbG9hZGluZy4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9yb3V0ZXMvbW9kZWwvdmlldy5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICByZWxvYWQoKSB7CiAgICAgICAgICAgIHRoaXMuY29udHJvbGxlci5nZXQoJ21vZGVsJykucmVsb2FkKCkudGhlbihmdW5jdGlvbihtb2RlbCkgewogICAgICAgICAgICAgIC8vIGRvIHNvbWV0aGluZyB3aXRoIHRoZSByZWxvYWRlZCBtb2RlbAogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgcmVsb2FkCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIG9wdGlvbmFsLCBtYXkgaW5jbHVkZSBgYWRhcHRlck9wdGlvbnNgIGhhc2ggd2hpY2ggd2lsbCBiZSBwYXNzZWQgdG8gYWRhcHRlciByZXF1ZXN0CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IHdpbGwgYmUgcmVzb2x2ZWQgd2l0aCB0aGUgcmVjb3JkIHdoZW4gdGhlCiAgICAgIGFkYXB0ZXIgcmV0dXJucyBzdWNjZXNzZnVsbHkgb3IgcmVqZWN0ZWQgaWYgdGhlIGFkYXB0ZXIgcmV0dXJucwogICAgICB3aXRoIGFuIGVycm9yLgogICAgKi8KICAgIHJlbG9hZDogZnVuY3Rpb24gcmVsb2FkKG9wdGlvbnMpIHsKICAgICAgdmFyIF90aGlzNiA9IHRoaXM7CgogICAgICB2YXIgd3JhcHBlZEFkYXB0ZXJPcHRpb25zOwoKICAgICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnb2JqZWN0JyAmJiBvcHRpb25zICE9PSBudWxsICYmIG9wdGlvbnMuYWRhcHRlck9wdGlvbnMpIHsKICAgICAgICB3cmFwcGVkQWRhcHRlck9wdGlvbnMgPSB7CiAgICAgICAgICBhZGFwdGVyT3B0aW9uczogb3B0aW9ucy5hZGFwdGVyT3B0aW9ucwogICAgICAgIH07CiAgICAgIH0KCiAgICAgIHJldHVybiBQcml2YXRlLlByb21pc2VPYmplY3QuY3JlYXRlKHsKICAgICAgICBwcm9taXNlOiB0aGlzLl9pbnRlcm5hbE1vZGVsLnJlbG9hZCh3cmFwcGVkQWRhcHRlck9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuIF90aGlzNjsKICAgICAgICB9KQogICAgICB9KTsKICAgIH0sCgogICAgLyoqCiAgICAgIE92ZXJyaWRlIHRoZSBkZWZhdWx0IGV2ZW50IGZpcmluZyBmcm9tIEVtYmVyLkV2ZW50ZWQgdG8KICAgICAgYWxzbyBjYWxsIG1ldGhvZHMgd2l0aCB0aGUgZ2l2ZW4gbmFtZS4KICAgICAgIEBtZXRob2QgdHJpZ2dlcgogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZQogICAgKi8KICAgIHRyaWdnZXI6IGZ1bmN0aW9uIHRyaWdnZXIobmFtZSkgewogICAgICB2YXIgZm4gPSB0aGlzW25hbWVdOwoKICAgICAgaWYgKHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIHZhciBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoOwogICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGxlbmd0aCAtIDEpOwoKICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTsKICAgICAgICB9CgogICAgICAgIGZuLmFwcGx5KHRoaXMsIGFyZ3MpOwogICAgICB9CgogICAgICB2YXIgX2hhc0V2ZW50ID0gIHRoaXMuaGFzKG5hbWUpOwoKICAgICAgaWYgKF9oYXNFdmVudCkgewogICAgICAgIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICAgIH0KICAgIH0sCiAgICBhdHRyOiBmdW5jdGlvbiBhdHRyKCkgewogICAgfSwKCiAgICAvKioKICAgICAgR2V0IHRoZSByZWZlcmVuY2UgZm9yIHRoZSBzcGVjaWZpZWQgYmVsb25nc1RvIHJlbGF0aW9uc2hpcC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9tb2RlbHMvYmxvZy5qcwogICAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICB1c2VyOiBiZWxvbmdzVG8oeyBhc3luYzogdHJ1ZSB9KQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBibG9nID0gc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ2Jsb2cnLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgIHVzZXI6IHsKICAgICAgICAgICAgICBkYXRhOiB7IHR5cGU6ICd1c2VyJywgaWQ6IDEgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgbGV0IHVzZXJSZWYgPSBibG9nLmJlbG9uZ3NUbygndXNlcicpOwogICAgICAgLy8gY2hlY2sgaWYgdGhlIHVzZXIgcmVsYXRpb25zaGlwIGlzIGxvYWRlZAogICAgICBsZXQgaXNMb2FkZWQgPSB1c2VyUmVmLnZhbHVlKCkgIT09IG51bGw7CiAgICAgICAvLyBnZXQgdGhlIHJlY29yZCBvZiB0aGUgcmVmZXJlbmNlIChudWxsIGlmIG5vdCB5ZXQgYXZhaWxhYmxlKQogICAgICBsZXQgdXNlciA9IHVzZXJSZWYudmFsdWUoKTsKICAgICAgIC8vIGdldCB0aGUgaWRlbnRpZmllciBvZiB0aGUgcmVmZXJlbmNlCiAgICAgIGlmICh1c2VyUmVmLnJlbW90ZVR5cGUoKSA9PT0gImlkIikgewogICAgICAgIGxldCBpZCA9IHVzZXJSZWYuaWQoKTsKICAgICAgfSBlbHNlIGlmICh1c2VyUmVmLnJlbW90ZVR5cGUoKSA9PT0gImxpbmsiKSB7CiAgICAgICAgbGV0IGxpbmsgPSB1c2VyUmVmLmxpbmsoKTsKICAgICAgfQogICAgICAgLy8gbG9hZCB1c2VyICh2aWEgc3RvcmUuZmluZFJlY29yZCBvciBzdG9yZS5maW5kQmVsb25nc1RvKQogICAgICB1c2VyUmVmLmxvYWQoKS50aGVuKC4uLikKICAgICAgIC8vIG9yIHRyaWdnZXIgYSByZWxvYWQKICAgICAgdXNlclJlZi5yZWxvYWQoKS50aGVuKC4uLikKICAgICAgIC8vIHByb3ZpZGUgZGF0YSBmb3IgcmVmZXJlbmNlCiAgICAgIHVzZXJSZWYucHVzaCh7CiAgICAgICAgdHlwZTogJ3VzZXInLAogICAgICAgIGlkOiAxLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIHVzZXJuYW1lOiAiQHVzZXIiCiAgICAgICAgfQogICAgICB9KS50aGVuKGZ1bmN0aW9uKHVzZXIpIHsKICAgICAgICB1c2VyUmVmLnZhbHVlKCkgPT09IHVzZXI7CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgYmVsb25nc1RvCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIG9mIHRoZSByZWxhdGlvbnNoaXAKICAgICAgQHNpbmNlIDIuNS4wCiAgICAgIEByZXR1cm4ge0JlbG9uZ3NUb1JlZmVyZW5jZX0gcmVmZXJlbmNlIGZvciB0aGlzIHJlbGF0aW9uc2hpcAogICAgKi8KICAgIGJlbG9uZ3NUbzogZnVuY3Rpb24gYmVsb25nc1RvKG5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXMuX2ludGVybmFsTW9kZWwucmVmZXJlbmNlRm9yKCdiZWxvbmdzVG8nLCBuYW1lKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEdldCB0aGUgcmVmZXJlbmNlIGZvciB0aGUgc3BlY2lmaWVkIGhhc01hbnkgcmVsYXRpb25zaGlwLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL21vZGVscy9ibG9nLmpzCiAgICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICBjb21tZW50czogaGFzTWFueSh7IGFzeW5jOiB0cnVlIH0pCiAgICAgIH0pOwogICAgICAgbGV0IGJsb2cgPSBzdG9yZS5wdXNoKHsKICAgICAgICBkYXRhOiB7CiAgICAgICAgICB0eXBlOiAnYmxvZycsCiAgICAgICAgICBpZDogMSwKICAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICAgY29tbWVudHM6IHsKICAgICAgICAgICAgICBkYXRhOiBbCiAgICAgICAgICAgICAgICB7IHR5cGU6ICdjb21tZW50JywgaWQ6IDEgfSwKICAgICAgICAgICAgICAgIHsgdHlwZTogJ2NvbW1lbnQnLCBpZDogMiB9CiAgICAgICAgICAgICAgXQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgbGV0IGNvbW1lbnRzUmVmID0gYmxvZy5oYXNNYW55KCdjb21tZW50cycpOwogICAgICAgLy8gY2hlY2sgaWYgdGhlIGNvbW1lbnRzIGFyZSBsb2FkZWQgYWxyZWFkeQogICAgICBsZXQgaXNMb2FkZWQgPSBjb21tZW50c1JlZi52YWx1ZSgpICE9PSBudWxsOwogICAgICAgLy8gZ2V0IHRoZSByZWNvcmRzIG9mIHRoZSByZWZlcmVuY2UgKG51bGwgaWYgbm90IHlldCBhdmFpbGFibGUpCiAgICAgIGxldCBjb21tZW50cyA9IGNvbW1lbnRzUmVmLnZhbHVlKCk7CiAgICAgICAvLyBnZXQgdGhlIGlkZW50aWZpZXIgb2YgdGhlIHJlZmVyZW5jZQogICAgICBpZiAoY29tbWVudHNSZWYucmVtb3RlVHlwZSgpID09PSAiaWRzIikgewogICAgICAgIGxldCBpZHMgPSBjb21tZW50c1JlZi5pZHMoKTsKICAgICAgfSBlbHNlIGlmIChjb21tZW50c1JlZi5yZW1vdGVUeXBlKCkgPT09ICJsaW5rIikgewogICAgICAgIGxldCBsaW5rID0gY29tbWVudHNSZWYubGluaygpOwogICAgICB9CiAgICAgICAvLyBsb2FkIGNvbW1lbnRzICh2aWEgc3RvcmUuZmluZE1hbnkgb3Igc3RvcmUuZmluZEhhc01hbnkpCiAgICAgIGNvbW1lbnRzUmVmLmxvYWQoKS50aGVuKC4uLikKICAgICAgIC8vIG9yIHRyaWdnZXIgYSByZWxvYWQKICAgICAgY29tbWVudHNSZWYucmVsb2FkKCkudGhlbiguLi4pCiAgICAgICAvLyBwcm92aWRlIGRhdGEgZm9yIHJlZmVyZW5jZQogICAgICBjb21tZW50c1JlZi5wdXNoKFt7IHR5cGU6ICdjb21tZW50JywgaWQ6IDEgfSwgeyB0eXBlOiAnY29tbWVudCcsIGlkOiAyIH1dKS50aGVuKGZ1bmN0aW9uKGNvbW1lbnRzKSB7CiAgICAgICAgY29tbWVudHNSZWYudmFsdWUoKSA9PT0gY29tbWVudHM7CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgaGFzTWFueQogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiB0aGUgcmVsYXRpb25zaGlwCiAgICAgIEBzaW5jZSAyLjUuMAogICAgICBAcmV0dXJuIHtIYXNNYW55UmVmZXJlbmNlfSByZWZlcmVuY2UgZm9yIHRoaXMgcmVsYXRpb25zaGlwCiAgICAqLwogICAgaGFzTWFueTogZnVuY3Rpb24gaGFzTWFueShuYW1lKSB7CiAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsLnJlZmVyZW5jZUZvcignaGFzTWFueScsIG5hbWUpOwogICAgfSwKCiAgICAvKioKICAgICBQcm92aWRlcyBpbmZvIGFib3V0IHRoZSBtb2RlbCBmb3IgZGVidWdnaW5nIHB1cnBvc2VzCiAgICAgYnkgZ3JvdXBpbmcgdGhlIHByb3BlcnRpZXMgaW50byBtb3JlIHNlbWFudGljIGdyb3Vwcy4KICAgICAgTWVhbnQgdG8gYmUgdXNlZCBieSBkZWJ1Z2dpbmcgdG9vbHMgc3VjaCBhcyB0aGUgQ2hyb21lIEVtYmVyIEV4dGVuc2lvbi4KICAgICAgLSBHcm91cHMgYWxsIGF0dHJpYnV0ZXMgaW4gIkF0dHJpYnV0ZXMiIGdyb3VwLgogICAgIC0gR3JvdXBzIGFsbCBiZWxvbmdzVG8gcmVsYXRpb25zaGlwcyBpbiAiQmVsb25ncyBUbyIgZ3JvdXAuCiAgICAgLSBHcm91cHMgYWxsIGhhc01hbnkgcmVsYXRpb25zaGlwcyBpbiAiSGFzIE1hbnkiIGdyb3VwLgogICAgIC0gR3JvdXBzIGFsbCBmbGFncyBpbiAiRmxhZ3MiIGdyb3VwLgogICAgIC0gRmxhZ3MgcmVsYXRpb25zaGlwIENQcyBhcyBleHBlbnNpdmUgcHJvcGVydGllcy4KICAgICAgQG1ldGhvZCBfZGVidWdJbmZvCiAgICAgQGZvciBNb2RlbAogICAgIEBwcml2YXRlCiAgICAgKi8KICAgIF9kZWJ1Z0luZm86IGZ1bmN0aW9uIF9kZWJ1Z0luZm8oKSB7CiAgICAgIHZhciBhdHRyaWJ1dGVzID0gWydpZCddOwogICAgICB2YXIgcmVsYXRpb25zaGlwcyA9IHt9OwogICAgICB2YXIgZXhwZW5zaXZlUHJvcGVydGllcyA9IFtdOwogICAgICB0aGlzLmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24gKG5hbWUsIG1ldGEpIHsKICAgICAgICByZXR1cm4gYXR0cmlidXRlcy5wdXNoKG5hbWUpOwogICAgICB9KTsKICAgICAgdmFyIGdyb3VwcyA9IFt7CiAgICAgICAgbmFtZTogJ0F0dHJpYnV0ZXMnLAogICAgICAgIHByb3BlcnRpZXM6IGF0dHJpYnV0ZXMsCiAgICAgICAgZXhwYW5kOiB0cnVlCiAgICAgIH1dOwogICAgICB0aGlzLmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24gKG5hbWUsIHJlbGF0aW9uc2hpcCkgewogICAgICAgIHZhciBwcm9wZXJ0aWVzID0gcmVsYXRpb25zaGlwc1tyZWxhdGlvbnNoaXAua2luZF07CgogICAgICAgIGlmIChwcm9wZXJ0aWVzID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHByb3BlcnRpZXMgPSByZWxhdGlvbnNoaXBzW3JlbGF0aW9uc2hpcC5raW5kXSA9IFtdOwogICAgICAgICAgZ3JvdXBzLnB1c2goewogICAgICAgICAgICBuYW1lOiByZWxhdGlvbnNoaXAua2luZCwKICAgICAgICAgICAgcHJvcGVydGllczogcHJvcGVydGllcywKICAgICAgICAgICAgZXhwYW5kOiB0cnVlCiAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIHByb3BlcnRpZXMucHVzaChuYW1lKTsKICAgICAgICBleHBlbnNpdmVQcm9wZXJ0aWVzLnB1c2gobmFtZSk7CiAgICAgIH0pOwogICAgICBncm91cHMucHVzaCh7CiAgICAgICAgbmFtZTogJ0ZsYWdzJywKICAgICAgICBwcm9wZXJ0aWVzOiBbJ2lzTG9hZGVkJywgJ2hhc0RpcnR5QXR0cmlidXRlcycsICdpc1NhdmluZycsICdpc0RlbGV0ZWQnLCAnaXNFcnJvcicsICdpc05ldycsICdpc1ZhbGlkJ10KICAgICAgfSk7CiAgICAgIHJldHVybiB7CiAgICAgICAgcHJvcGVydHlJbmZvOiB7CiAgICAgICAgICAvLyBpbmNsdWRlIGFsbCBvdGhlciBtaXhpbnMgLyBwcm9wZXJ0aWVzIChub3QganVzdCB0aGUgZ3JvdXBlZCBvbmVzKQogICAgICAgICAgaW5jbHVkZU90aGVyUHJvcGVydGllczogdHJ1ZSwKICAgICAgICAgIGdyb3VwczogZ3JvdXBzLAogICAgICAgICAgLy8gZG9uJ3QgcHJlLWNhbGN1bGF0ZSB1bmxlc3MgY2FjaGVkCiAgICAgICAgICBleHBlbnNpdmVQcm9wZXJ0aWVzOiBleHBlbnNpdmVQcm9wZXJ0aWVzCiAgICAgICAgfQogICAgICB9OwogICAgfSwKICAgIG5vdGlmeUJlbG9uZ3NUb0NoYW5nZTogZnVuY3Rpb24gbm90aWZ5QmVsb25nc1RvQ2hhbmdlKGtleSkgewogICAgICB0aGlzLm5vdGlmeVByb3BlcnR5Q2hhbmdlKGtleSk7CiAgICB9LAoKICAgIC8qKgogICAgIEdpdmVuIGEgY2FsbGJhY2ssIGl0ZXJhdGVzIG92ZXIgZWFjaCBvZiB0aGUgcmVsYXRpb25zaGlwcyBpbiB0aGUgbW9kZWwsCiAgICAgaW52b2tpbmcgdGhlIGNhbGxiYWNrIHdpdGggdGhlIG5hbWUgb2YgZWFjaCByZWxhdGlvbnNoaXAgYW5kIGl0cyByZWxhdGlvbnNoaXAKICAgICBkZXNjcmlwdG9yLgogICAgICAgVGhlIGNhbGxiYWNrIG1ldGhvZCB5b3UgcHJvdmlkZSBzaG91bGQgaGF2ZSB0aGUgZm9sbG93aW5nIHNpZ25hdHVyZSAoYWxsCiAgICAgcGFyYW1ldGVycyBhcmUgb3B0aW9uYWwpOgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgZnVuY3Rpb24obmFtZSwgZGVzY3JpcHRvcik7CiAgICAgYGBgCiAgICAgIC0gYG5hbWVgIHRoZSBuYW1lIG9mIHRoZSBjdXJyZW50IHByb3BlcnR5IGluIHRoZSBpdGVyYXRpb24KICAgICAtIGBkZXNjcmlwdG9yYCB0aGUgbWV0YSBvYmplY3QgdGhhdCBkZXNjcmliZXMgdGhpcyByZWxhdGlvbnNoaXAKICAgICAgVGhlIHJlbGF0aW9uc2hpcCBkZXNjcmlwdG9yIGFyZ3VtZW50IGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcy4KICAgICAgLSAqKmtleSoqIDxzcGFuIGNsYXNzPSJ0eXBlIj5TdHJpbmc8L3NwYW4+IHRoZSBuYW1lIG9mIHRoaXMgcmVsYXRpb25zaGlwIG9uIHRoZSBNb2RlbAogICAgIC0gKipraW5kKiogPHNwYW4gY2xhc3M9InR5cGUiPlN0cmluZzwvc3Bhbj4gImhhc01hbnkiIG9yICJiZWxvbmdzVG8iCiAgICAgLSAqKm9wdGlvbnMqKiA8c3BhbiBjbGFzcz0idHlwZSI+T2JqZWN0PC9zcGFuPiB0aGUgb3JpZ2luYWwgb3B0aW9ucyBoYXNoIHBhc3NlZCB3aGVuIHRoZSByZWxhdGlvbnNoaXAgd2FzIGRlY2xhcmVkCiAgICAgLSAqKnBhcmVudFR5cGUqKiA8c3BhbiBjbGFzcz0idHlwZSI+TW9kZWw8L3NwYW4+IHRoZSB0eXBlIG9mIHRoZSBNb2RlbCB0aGF0IG93bnMgdGhpcyByZWxhdGlvbnNoaXAKICAgICAtICoqdHlwZSoqIDxzcGFuIGNsYXNzPSJ0eXBlIj5TdHJpbmc8L3NwYW4+IHRoZSB0eXBlIG5hbWUgb2YgdGhlIHJlbGF0ZWQgTW9kZWwKICAgICAgTm90ZSB0aGF0IGluIGFkZGl0aW9uIHRvIGEgY2FsbGJhY2ssIHlvdSBjYW4gYWxzbyBwYXNzIGFuIG9wdGlvbmFsIHRhcmdldAogICAgIG9iamVjdCB0aGF0IHdpbGwgYmUgc2V0IGFzIGB0aGlzYCBvbiB0aGUgY29udGV4dC4KICAgICAgRXhhbXBsZQogICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICBpbXBvcnQgSlNPTlNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgc2VyaWFsaXplOiBmdW5jdGlvbihyZWNvcmQsIG9wdGlvbnMpIHsKICAgICAgICBsZXQganNvbiA9IHt9OwogICAgICAgICByZWNvcmQuZWFjaFJlbGF0aW9uc2hpcChmdW5jdGlvbihuYW1lLCBkZXNjcmlwdG9yKSB7CiAgICAgICAgICBpZiAoZGVzY3JpcHRvci5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgICAgICAgbGV0IHNlcmlhbGl6ZWRIYXNNYW55TmFtZSA9IG5hbWUudG9VcHBlckNhc2UoKSArICdfSURTJzsKICAgICAgICAgICAganNvbltzZXJpYWxpemVkSGFzTWFueU5hbWVdID0gcmVjb3JkLmdldChuYW1lKS5tYXBCeSgnaWQnKTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgICAgcmV0dXJuIGpzb247CiAgICAgIH0KICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIGVhY2hSZWxhdGlvbnNoaXAKICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayB0aGUgY2FsbGJhY2sgdG8gaW52b2tlCiAgICAgQHBhcmFtIHthbnl9IGJpbmRpbmcgdGhlIHZhbHVlIHRvIHdoaWNoIHRoZSBjYWxsYmFjaydzIGB0aGlzYCBzaG91bGQgYmUgYm91bmQKICAgICAqLwogICAgZWFjaFJlbGF0aW9uc2hpcDogZnVuY3Rpb24gZWFjaFJlbGF0aW9uc2hpcChjYWxsYmFjaywgYmluZGluZykgewogICAgICB0aGlzLmNvbnN0cnVjdG9yLmVhY2hSZWxhdGlvbnNoaXAoY2FsbGJhY2ssIGJpbmRpbmcpOwogICAgfSwKICAgIHJlbGF0aW9uc2hpcEZvcjogZnVuY3Rpb24gcmVsYXRpb25zaGlwRm9yKG5hbWUpIHsKICAgICAgcmV0dXJuIEVtYmVyLmdldCh0aGlzLmNvbnN0cnVjdG9yLCAncmVsYXRpb25zaGlwc0J5TmFtZScpLmdldChuYW1lKTsKICAgIH0sCiAgICBpbnZlcnNlRm9yOiBmdW5jdGlvbiBpbnZlcnNlRm9yKGtleSkgewogICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci5pbnZlcnNlRm9yKGtleSwgdGhpcy5faW50ZXJuYWxNb2RlbC5zdG9yZSk7CiAgICB9LAogICAgbm90aWZ5SGFzTWFueUFkZGVkOiBmdW5jdGlvbiBub3RpZnlIYXNNYW55QWRkZWQoa2V5KSB7CiAgICAgIC8vV2UgbmVlZCB0byBub3RpZnlQcm9wZXJ0eUNoYW5nZSBpbiB0aGUgYWRkaW5nIGNhc2UgYmVjYXVzZSB3ZSBuZWVkIHRvIG1ha2Ugc3VyZQogICAgICAvL3dlIGZldGNoIHRoZSBuZXdseSBhZGRlZCByZWNvcmQgaW4gY2FzZSBpdCBpcyB1bmxvYWRlZAogICAgICAvL1RPRE8oSWdvcik6IENvbnNpZGVyIHdoZXRoZXIgd2UgY291bGQgZG8gdGhpcyBvbmx5IGlmIHRoZSByZWNvcmQgc3RhdGUgaXMgdW5sb2FkZWQKICAgICAgdGhpcy5ub3RpZnlQcm9wZXJ0eUNoYW5nZShrZXkpOwogICAgfSwKICAgIGVhY2hBdHRyaWJ1dGU6IGZ1bmN0aW9uIGVhY2hBdHRyaWJ1dGUoY2FsbGJhY2ssIGJpbmRpbmcpIHsKICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5lYWNoQXR0cmlidXRlKGNhbGxiYWNrLCBiaW5kaW5nKTsKICAgIH0KICB9KTsKICAvKioKICAgQHByb3BlcnR5IGRhdGEKICAgQHByaXZhdGUKICAgQGRlcHJlY2F0ZWQKICAgQHR5cGUge09iamVjdH0KICAgKi8KCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE1vZGVsLnByb3RvdHlwZSwgJ2RhdGEnLCB7CiAgICBjb25maWd1cmFibGU6IGZhbHNlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLnJlY29yZERhdGFGb3IodGhpcykuX2RhdGE7CiAgICB9CiAgfSk7CiAgdmFyIElEX0RFU0NSSVBUT1IgPSB7CiAgICBjb25maWd1cmFibGU6IGZhbHNlLAogICAgc2V0OiBmdW5jdGlvbiBzZXQoaWQpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRJZCA9IFByaXZhdGUuY29lcmNlSWQoaWQpOwoKICAgICAgaWYgKG5vcm1hbGl6ZWRJZCAhPT0gbnVsbCkgewogICAgICAgIHRoaXMuX2ludGVybmFsTW9kZWwuc2V0SWQobm9ybWFsaXplZElkKTsKICAgICAgfQogICAgfSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAvLyB0aGUgX2ludGVybmFsTW9kZWwgZ3VhcmQgZXhpc3RzLCBiZWNhdXNlIHNvbWUgZGV2LW9ubHkgZGVwcmVjYXRpb24gY29kZQogICAgICAvLyAoYWRkTGlzdGVuZXIgdmlhIHZhbGlkYXRlUHJvcGVydHlJbmplY3Rpb25zKSBpbnZva2VzIHRvU3RyaW5nIGJlZm9yZSB0aGUKICAgICAgLy8gb2JqZWN0IGlzIHJlYWwuCiAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsICYmIHRoaXMuX2ludGVybmFsTW9kZWwuaWQ7CiAgICB9CiAgfTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoTW9kZWwucHJvdG90eXBlLCAnaWQnLCBJRF9ERVNDUklQVE9SKTsKCiAgTW9kZWwucmVvcGVuQ2xhc3MoewogICAgaXNNb2RlbDogdHJ1ZSwKCiAgICAvKioKICAgICAgQ3JlYXRlIHNob3VsZCBvbmx5IGV2ZXIgYmUgY2FsbGVkIGJ5IHRoZSBzdG9yZS4gVG8gY3JlYXRlIGFuIGluc3RhbmNlIG9mIGEKICAgICAgYE1vZGVsYCBpbiBhIGRpcnR5IHN0YXRlIHVzZSBgc3RvcmUuY3JlYXRlUmVjb3JkYC4KICAgICAgVG8gY3JlYXRlIGluc3RhbmNlcyBvZiBgTW9kZWxgIGluIGEgY2xlYW4gc3RhdGUsIHVzZSBgc3RvcmUucHVzaGAKICAgICAgIEBtZXRob2QgY3JlYXRlCiAgICAgIEBwcml2YXRlCiAgICAgIEBzdGF0aWMKICAgICovCgogICAgLyoqCiAgICAgUmVwcmVzZW50cyB0aGUgbW9kZWwncyBjbGFzcyBuYW1lIGFzIGEgc3RyaW5nLiBUaGlzIGNhbiBiZSB1c2VkIHRvIGxvb2sgdXAgdGhlIG1vZGVsJ3MgY2xhc3MgbmFtZSB0aHJvdWdoCiAgICAgYFN0b3JlYCdzIG1vZGVsRm9yIG1ldGhvZC4KICAgICAgYG1vZGVsTmFtZWAgaXMgZ2VuZXJhdGVkIGZvciB5b3UgYnkgRW1iZXIgRGF0YS4gSXQgd2lsbCBiZSBhIGxvd2VyY2FzZWQsIGRhc2hlcml6ZWQgc3RyaW5nLgogICAgIEZvciBleGFtcGxlOgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgc3RvcmUubW9kZWxGb3IoJ3Bvc3QnKS5tb2RlbE5hbWU7IC8vICdwb3N0JwogICAgIHN0b3JlLm1vZGVsRm9yKCdibG9nLXBvc3QnKS5tb2RlbE5hbWU7IC8vICdibG9nLXBvc3QnCiAgICAgYGBgCiAgICAgIFRoZSBtb3N0IGNvbW1vbiBwbGFjZSB5b3UnbGwgd2FudCB0byBhY2Nlc3MgYG1vZGVsTmFtZWAgaXMgaW4geW91ciBzZXJpYWxpemVyJ3MgYHBheWxvYWRLZXlGcm9tTW9kZWxOYW1lYCBtZXRob2QuIEZvciBleGFtcGxlLCB0byBjaGFuZ2UgcGF5bG9hZAogICAgIGtleXMgdG8gdW5kZXJzY29yZSAoaW5zdGVhZCBvZiBkYXNoZXJpemVkKSwgeW91IG1pZ2h0IHVzZSB0aGUgZm9sbG93aW5nIGNvZGU6CiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKICAgICBpbXBvcnQgeyB1bmRlcnNjb3JlIH0gZnJvbSAnQGVtYmVyL3N0cmluZyc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IGNvbnN0IFBvc3RTZXJpYWxpemVyID0gUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgIHBheWxvYWRLZXlGcm9tTW9kZWxOYW1lKG1vZGVsTmFtZSkgewogICAgICAgICByZXR1cm4gdW5kZXJzY29yZShtb2RlbE5hbWUpOwogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgIEBwcm9wZXJ0eSBtb2RlbE5hbWUKICAgICBAdHlwZSBTdHJpbmcKICAgICBAcmVhZG9ubHkKICAgICBAc3RhdGljCiAgICAqLwogICAgbW9kZWxOYW1lOiBudWxsLAoKICAgIC8qCiAgICAgVGhlc2UgY2xhc3MgbWV0aG9kcyBiZWxvdyBwcm92aWRlIHJlbGF0aW9uc2hpcAogICAgIGludHJvc3BlY3Rpb24gYWJpbGl0aWVzIGFib3V0IHJlbGF0aW9uc2hpcHMuCiAgICAgIEEgbm90ZSBhYm91dCB0aGUgY29tcHV0ZWQgcHJvcGVydGllcyBjb250YWluZWQgaGVyZToKICAgICAgKipUaGVzZSBwcm9wZXJ0aWVzIGFyZSBlZmZlY3RpdmVseSBzZWFsZWQgb25jZSBjYWxsZWQgZm9yIHRoZSBmaXJzdCB0aW1lLioqCiAgICAgVG8gYXZvaWQgcmVwZWF0ZWRseSBkb2luZyBleHBlbnNpdmUgaXRlcmF0aW9uIG92ZXIgYSBtb2RlbCdzIGZpZWxkcywgdGhlc2UKICAgICB2YWx1ZXMgYXJlIGNvbXB1dGVkIG9uY2UgYW5kIHRoZW4gY2FjaGVkIGZvciB0aGUgcmVtYWluZGVyIG9mIHRoZSBydW50aW1lIG9mCiAgICAgeW91ciBhcHBsaWNhdGlvbi4KICAgICAgSWYgeW91ciBhcHBsaWNhdGlvbiBuZWVkcyB0byBtb2RpZnkgYSBjbGFzcyBhZnRlciBpdHMgaW5pdGlhbCBkZWZpbml0aW9uCiAgICAgKGZvciBleGFtcGxlLCB1c2luZyBgcmVvcGVuKClgIHRvIGFkZCBhZGRpdGlvbmFsIGF0dHJpYnV0ZXMpLCBtYWtlIHN1cmUgeW91CiAgICAgZG8gaXQgYmVmb3JlIHVzaW5nIHlvdXIgbW9kZWwgd2l0aCB0aGUgc3RvcmUsIHdoaWNoIHVzZXMgdGhlc2UgcHJvcGVydGllcwogICAgIGV4dGVuc2l2ZWx5LgogICAgICovCgogICAgLyoqCiAgICAgRm9yIGEgZ2l2ZW4gcmVsYXRpb25zaGlwIG5hbWUsIHJldHVybnMgdGhlIG1vZGVsIHR5cGUgb2YgdGhlIHJlbGF0aW9uc2hpcC4KICAgICAgRm9yIGV4YW1wbGUsIGlmIHlvdSBkZWZpbmUgYSBtb2RlbCBsaWtlIHRoaXM6CiAgICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIGNvbW1lbnRzOiBoYXNNYW55KCdjb21tZW50JykKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIENhbGxpbmcgYHN0b3JlLm1vZGVsRm9yKCdwb3N0JykudHlwZUZvclJlbGF0aW9uc2hpcCgnY29tbWVudHMnLCBzdG9yZSlgIHdpbGwgcmV0dXJuIGBDb21tZW50YC4KICAgICAgQG1ldGhvZCB0eXBlRm9yUmVsYXRpb25zaGlwCiAgICAgQHN0YXRpYwogICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIHRoZSBuYW1lIG9mIHRoZSByZWxhdGlvbnNoaXAKICAgICBAcGFyYW0ge3N0b3JlfSBzdG9yZSBhbiBpbnN0YW5jZSBvZiBTdG9yZQogICAgIEByZXR1cm4ge01vZGVsfSB0aGUgdHlwZSBvZiB0aGUgcmVsYXRpb25zaGlwLCBvciB1bmRlZmluZWQKICAgICAqLwogICAgdHlwZUZvclJlbGF0aW9uc2hpcDogZnVuY3Rpb24gdHlwZUZvclJlbGF0aW9uc2hpcChuYW1lLCBzdG9yZSkgewogICAgICB2YXIgcmVsYXRpb25zaGlwID0gRW1iZXIuZ2V0KHRoaXMsICdyZWxhdGlvbnNoaXBzQnlOYW1lJykuZ2V0KG5hbWUpOwogICAgICByZXR1cm4gcmVsYXRpb25zaGlwICYmIHN0b3JlLm1vZGVsRm9yKHJlbGF0aW9uc2hpcC50eXBlKTsKICAgIH0sCiAgICBpbnZlcnNlTWFwOiBFbWJlci5jb21wdXRlZChmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgfSksCgogICAgLyoqCiAgICAgRmluZCB0aGUgcmVsYXRpb25zaGlwIHdoaWNoIGlzIHRoZSBpbnZlcnNlIG9mIHRoZSBvbmUgYXNrZWQgZm9yLgogICAgICBGb3IgZXhhbXBsZSwgaWYgeW91IGRlZmluZSBtb2RlbHMgbGlrZSB0aGlzOgogICAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICBjb21tZW50czogaGFzTWFueSgnbWVzc2FnZScpCiAgICAgIH0pOwogICAgIGBgYAogICAgICBgYGBhcHAvbW9kZWxzL21lc3NhZ2UuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIG93bmVyOiBiZWxvbmdzVG8oJ3Bvc3QnKQogICAgICB9KTsKICAgICBgYGAKICAgICAgYGBgIGpzCiAgICAgc3RvcmUubW9kZWxGb3IoJ3Bvc3QnKS5pbnZlcnNlRm9yKCdjb21tZW50cycsIHN0b3JlKSAvLyB7IHR5cGU6IEFwcC5NZXNzYWdlLCBuYW1lOiAnb3duZXInLCBraW5kOiAnYmVsb25nc1RvJyB9CiAgICAgc3RvcmUubW9kZWxGb3IoJ21lc3NhZ2UnKS5pbnZlcnNlRm9yKCdvd25lcicsIHN0b3JlKSAvLyB7IHR5cGU6IEFwcC5Qb3N0LCBuYW1lOiAnY29tbWVudHMnLCBraW5kOiAnaGFzTWFueScgfQogICAgIGBgYAogICAgICBAbWV0aG9kIGludmVyc2VGb3IKICAgICBAc3RhdGljCiAgICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIG5hbWUgb2YgdGhlIHJlbGF0aW9uc2hpcAogICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgQHJldHVybiB7T2JqZWN0fSB0aGUgaW52ZXJzZSByZWxhdGlvbnNoaXAsIG9yIG51bGwKICAgICAqLwogICAgaW52ZXJzZUZvcjogZnVuY3Rpb24gaW52ZXJzZUZvcihuYW1lLCBzdG9yZSkgewogICAgICB2YXIgaW52ZXJzZU1hcCA9IEVtYmVyLmdldCh0aGlzLCAnaW52ZXJzZU1hcCcpOwoKICAgICAgaWYgKGludmVyc2VNYXBbbmFtZV0pIHsKICAgICAgICByZXR1cm4gaW52ZXJzZU1hcFtuYW1lXTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgaW52ZXJzZSA9IHRoaXMuX2ZpbmRJbnZlcnNlRm9yKG5hbWUsIHN0b3JlKTsKCiAgICAgICAgaW52ZXJzZU1hcFtuYW1lXSA9IGludmVyc2U7CiAgICAgICAgcmV0dXJuIGludmVyc2U7CiAgICAgIH0KICAgIH0sCiAgICAvL0NhbGN1bGF0ZSB0aGUgaW52ZXJzZSwgaWdub3JpbmcgdGhlIGNhY2hlCiAgICBfZmluZEludmVyc2VGb3I6IGZ1bmN0aW9uIF9maW5kSW52ZXJzZUZvcihuYW1lLCBzdG9yZSkgewogICAgICB2YXIgaW52ZXJzZVR5cGUgPSB0aGlzLnR5cGVGb3JSZWxhdGlvbnNoaXAobmFtZSwgc3RvcmUpOwoKICAgICAgaWYgKCFpbnZlcnNlVHlwZSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgcHJvcGVydHlNZXRhID0gdGhpcy5tZXRhRm9yUHJvcGVydHkobmFtZSk7IC8vSWYgaW52ZXJzZSBpcyBtYW51YWxseSBzcGVjaWZpZWQgdG8gYmUgbnVsbCwgbGlrZSAgYGNvbW1lbnRzOiBoYXNNYW55KCdtZXNzYWdlJywgeyBpbnZlcnNlOiBudWxsIH0pYAoKICAgICAgdmFyIG9wdGlvbnMgPSBwcm9wZXJ0eU1ldGEub3B0aW9uczsKCiAgICAgIGlmIChvcHRpb25zLmludmVyc2UgPT09IG51bGwpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIGludmVyc2VOYW1lLCBpbnZlcnNlS2luZCwgaW52ZXJzZSwgaW52ZXJzZU9wdGlvbnM7IC8vSWYgaW52ZXJzZSBpcyBzcGVjaWZpZWQgbWFudWFsbHksIHJldHVybiB0aGUgaW52ZXJzZQoKICAgICAgaWYgKG9wdGlvbnMuaW52ZXJzZSkgewogICAgICAgIGludmVyc2VOYW1lID0gb3B0aW9ucy5pbnZlcnNlOwogICAgICAgIGludmVyc2UgPSBFbWJlci5nZXQoaW52ZXJzZVR5cGUsICdyZWxhdGlvbnNoaXBzQnlOYW1lJykuZ2V0KGludmVyc2VOYW1lKTsKCiAgICAgICAgaW52ZXJzZUtpbmQgPSBpbnZlcnNlLmtpbmQ7CiAgICAgICAgaW52ZXJzZU9wdGlvbnMgPSBpbnZlcnNlLm9wdGlvbnM7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy9ObyBpbnZlcnNlIHdhcyBzcGVjaWZpZWQgbWFudWFsbHksIHdlIG5lZWQgdG8gdXNlIGEgaGV1cmlzdGljIHRvIGd1ZXNzIG9uZQogICAgICAgIGlmIChwcm9wZXJ0eU1ldGEudHlwZSA9PT0gcHJvcGVydHlNZXRhLnBhcmVudE1vZGVsTmFtZSkgOwoKICAgICAgICB2YXIgcG9zc2libGVSZWxhdGlvbnNoaXBzID0gZmluZFBvc3NpYmxlSW52ZXJzZXModGhpcywgaW52ZXJzZVR5cGUsIG5hbWUpOwoKICAgICAgICBpZiAocG9zc2libGVSZWxhdGlvbnNoaXBzLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQoKICAgICAgICB2YXIgZmlsdGVyZWRSZWxhdGlvbnNoaXBzID0gcG9zc2libGVSZWxhdGlvbnNoaXBzLmZpbHRlcihmdW5jdGlvbiAocG9zc2libGVSZWxhdGlvbnNoaXApIHsKICAgICAgICAgIHZhciBvcHRpb25zRm9yUmVsYXRpb25zaGlwID0gaW52ZXJzZVR5cGUubWV0YUZvclByb3BlcnR5KHBvc3NpYmxlUmVsYXRpb25zaGlwLm5hbWUpLm9wdGlvbnM7CiAgICAgICAgICByZXR1cm4gbmFtZSA9PT0gb3B0aW9uc0ZvclJlbGF0aW9uc2hpcC5pbnZlcnNlOwogICAgICAgIH0pOwoKICAgICAgICBpZiAoZmlsdGVyZWRSZWxhdGlvbnNoaXBzLmxlbmd0aCA9PT0gMSkgewogICAgICAgICAgcG9zc2libGVSZWxhdGlvbnNoaXBzID0gZmlsdGVyZWRSZWxhdGlvbnNoaXBzOwogICAgICAgIH0KICAgICAgICBpbnZlcnNlTmFtZSA9IHBvc3NpYmxlUmVsYXRpb25zaGlwc1swXS5uYW1lOwogICAgICAgIGludmVyc2VLaW5kID0gcG9zc2libGVSZWxhdGlvbnNoaXBzWzBdLmtpbmQ7CiAgICAgICAgaW52ZXJzZU9wdGlvbnMgPSBwb3NzaWJsZVJlbGF0aW9uc2hpcHNbMF0ub3B0aW9uczsKICAgICAgfQogICAgICByZXR1cm4gewogICAgICAgIHR5cGU6IGludmVyc2VUeXBlLAogICAgICAgIG5hbWU6IGludmVyc2VOYW1lLAogICAgICAgIGtpbmQ6IGludmVyc2VLaW5kLAogICAgICAgIG9wdGlvbnM6IGludmVyc2VPcHRpb25zCiAgICAgIH07CiAgICB9LAoKICAgIC8qKgogICAgIFRoZSBtb2RlbCdzIHJlbGF0aW9uc2hpcHMgYXMgYSBtYXAsIGtleWVkIG9uIHRoZSB0eXBlIG9mIHRoZQogICAgIHJlbGF0aW9uc2hpcC4gVGhlIHZhbHVlIG9mIGVhY2ggZW50cnkgaXMgYW4gYXJyYXkgY29udGFpbmluZyBhIGRlc2NyaXB0b3IKICAgICBmb3IgZWFjaCByZWxhdGlvbnNoaXAgd2l0aCB0aGF0IHR5cGUsIGRlc2NyaWJpbmcgdGhlIG5hbWUgb2YgdGhlIHJlbGF0aW9uc2hpcAogICAgIGFzIHdlbGwgYXMgdGhlIHR5cGUuCiAgICAgIEZvciBleGFtcGxlLCBnaXZlbiB0aGUgZm9sbG93aW5nIG1vZGVsIGRlZmluaXRpb246CiAgICAgIGBgYGFwcC9tb2RlbHMvYmxvZy5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBiZWxvbmdzVG8sIGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdXNlcnM6IGhhc01hbnkoJ3VzZXInKSwKICAgICAgICBvd25lcjogYmVsb25nc1RvKCd1c2VyJyksCiAgICAgICAgcG9zdHM6IGhhc01hbnkoJ3Bvc3QnKQogICAgICB9KTsKICAgICBgYGAKICAgICAgVGhpcyBjb21wdXRlZCBwcm9wZXJ0eSB3b3VsZCByZXR1cm4gYSBtYXAgZGVzY3JpYmluZyB0aGVzZQogICAgIHJlbGF0aW9uc2hpcHMsIGxpa2UgdGhpczoKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGltcG9ydCBFbWJlciBmcm9tICdlbWJlcic7CiAgICAgaW1wb3J0IEJsb2cgZnJvbSAnYXBwL21vZGVscy9ibG9nJzsKICAgICBpbXBvcnQgVXNlciBmcm9tICdhcHAvbW9kZWxzL3VzZXInOwogICAgIGltcG9ydCBQb3N0IGZyb20gJ2FwcC9tb2RlbHMvcG9zdCc7CiAgICAgIGxldCByZWxhdGlvbnNoaXBzID0gRW1iZXIuZ2V0KEJsb2csICdyZWxhdGlvbnNoaXBzJyk7CiAgICAgcmVsYXRpb25zaGlwcy5nZXQoJ3VzZXInKTsKICAgICAvLz0+IFsgeyBuYW1lOiAndXNlcnMnLCBraW5kOiAnaGFzTWFueScgfSwKICAgICAvLyAgICAgeyBuYW1lOiAnb3duZXInLCBraW5kOiAnYmVsb25nc1RvJyB9IF0KICAgICByZWxhdGlvbnNoaXBzLmdldCgncG9zdCcpOwogICAgIC8vPT4gWyB7IG5hbWU6ICdwb3N0cycsIGtpbmQ6ICdoYXNNYW55JyB9IF0KICAgICBgYGAKICAgICAgQHByb3BlcnR5IHJlbGF0aW9uc2hpcHMKICAgICBAc3RhdGljCiAgICAgQHR5cGUgTWFwCiAgICAgQHJlYWRPbmx5CiAgICAgKi8KICAgIHJlbGF0aW9uc2hpcHM6IFByaXZhdGUucmVsYXRpb25zaGlwc0Rlc2NyaXB0b3IsCgogICAgLyoqCiAgICAgQSBoYXNoIGNvbnRhaW5pbmcgbGlzdHMgb2YgdGhlIG1vZGVsJ3MgcmVsYXRpb25zaGlwcywgZ3JvdXBlZAogICAgIGJ5IHRoZSByZWxhdGlvbnNoaXAga2luZC4gRm9yIGV4YW1wbGUsIGdpdmVuIGEgbW9kZWwgd2l0aCB0aGlzCiAgICAgZGVmaW5pdGlvbjoKICAgICAgYGBgYXBwL21vZGVscy9ibG9nLmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbywgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICB1c2VyczogaGFzTWFueSgndXNlcicpLAogICAgICAgIG93bmVyOiBiZWxvbmdzVG8oJ3VzZXInKSwKICAgICAgICAgcG9zdHM6IGhhc01hbnkoJ3Bvc3QnKQogICAgICB9KTsKICAgICBgYGAKICAgICAgVGhpcyBwcm9wZXJ0eSB3b3VsZCBjb250YWluIHRoZSBmb2xsb3dpbmc6CiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBpbXBvcnQgRW1iZXIgZnJvbSAnZW1iZXInOwogICAgIGltcG9ydCBCbG9nIGZyb20gJ2FwcC9tb2RlbHMvYmxvZyc7CiAgICAgIGxldCByZWxhdGlvbnNoaXBOYW1lcyA9IEVtYmVyLmdldChCbG9nLCAncmVsYXRpb25zaGlwTmFtZXMnKTsKICAgICByZWxhdGlvbnNoaXBOYW1lcy5oYXNNYW55OwogICAgIC8vPT4gWyd1c2VycycsICdwb3N0cyddCiAgICAgcmVsYXRpb25zaGlwTmFtZXMuYmVsb25nc1RvOwogICAgIC8vPT4gWydvd25lciddCiAgICAgYGBgCiAgICAgIEBwcm9wZXJ0eSByZWxhdGlvbnNoaXBOYW1lcwogICAgIEBzdGF0aWMKICAgICBAdHlwZSBPYmplY3QKICAgICBAcmVhZE9ubHkKICAgICAqLwogICAgcmVsYXRpb25zaGlwTmFtZXM6IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIG5hbWVzID0gewogICAgICAgIGhhc01hbnk6IFtdLAogICAgICAgIGJlbG9uZ3NUbzogW10KICAgICAgfTsKICAgICAgdGhpcy5lYWNoQ29tcHV0ZWRQcm9wZXJ0eShmdW5jdGlvbiAobmFtZSwgbWV0YSkgewogICAgICAgIGlmIChtZXRhLmlzUmVsYXRpb25zaGlwKSB7CiAgICAgICAgICBuYW1lc1ttZXRhLmtpbmRdLnB1c2gobmFtZSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIG5hbWVzOwogICAgfSksCgogICAgLyoqCiAgICAgQW4gYXJyYXkgb2YgdHlwZXMgZGlyZWN0bHkgcmVsYXRlZCB0byBhIG1vZGVsLiBFYWNoIHR5cGUgd2lsbCBiZQogICAgIGluY2x1ZGVkIG9uY2UsIHJlZ2FyZGxlc3Mgb2YgdGhlIG51bWJlciBvZiByZWxhdGlvbnNoaXBzIGl0IGhhcyB3aXRoCiAgICAgdGhlIG1vZGVsLgogICAgICBGb3IgZXhhbXBsZSwgZ2l2ZW4gYSBtb2RlbCB3aXRoIHRoaXMgZGVmaW5pdGlvbjoKICAgICAgYGBgYXBwL21vZGVscy9ibG9nLmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbywgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICB1c2VyczogaGFzTWFueSgndXNlcicpLAogICAgICAgIG93bmVyOiBiZWxvbmdzVG8oJ3VzZXInKSwKICAgICAgICAgcG9zdHM6IGhhc01hbnkoJ3Bvc3QnKQogICAgICB9KTsKICAgICBgYGAKICAgICAgVGhpcyBwcm9wZXJ0eSB3b3VsZCBjb250YWluIHRoZSBmb2xsb3dpbmc6CiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBpbXBvcnQgRW1iZXIgZnJvbSAnZW1iZXInOwogICAgIGltcG9ydCBCbG9nIGZyb20gJ2FwcC9tb2RlbHMvYmxvZyc7CiAgICAgIGxldCByZWxhdGVkVHlwZXMgPSBFbWJlci5nZXQoQmxvZywgJ3JlbGF0ZWRUeXBlcycpOwogICAgIC8vPT4gWyBVc2VyLCBQb3N0IF0KICAgICBgYGAKICAgICAgQHByb3BlcnR5IHJlbGF0ZWRUeXBlcwogICAgIEBzdGF0aWMKICAgICBAdHlwZSBFbWJlci5BcnJheQogICAgIEByZWFkT25seQogICAgICovCiAgICByZWxhdGVkVHlwZXM6IFByaXZhdGUucmVsYXRlZFR5cGVzRGVzY3JpcHRvciwKCiAgICAvKioKICAgICBBIG1hcCB3aG9zZSBrZXlzIGFyZSB0aGUgcmVsYXRpb25zaGlwcyBvZiBhIG1vZGVsIGFuZCB3aG9zZSB2YWx1ZXMgYXJlCiAgICAgcmVsYXRpb25zaGlwIGRlc2NyaXB0b3JzLgogICAgICBGb3IgZXhhbXBsZSwgZ2l2ZW4gYSBtb2RlbCB3aXRoIHRoaXMKICAgICBkZWZpbml0aW9uOgogICAgICBgYGBhcHAvbW9kZWxzL2Jsb2cuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvLCBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIHVzZXJzOiBoYXNNYW55KCd1c2VyJyksCiAgICAgICAgb3duZXI6IGJlbG9uZ3NUbygndXNlcicpLAogICAgICAgICBwb3N0czogaGFzTWFueSgncG9zdCcpCiAgICAgIH0pOwogICAgIGBgYAogICAgICBUaGlzIHByb3BlcnR5IHdvdWxkIGNvbnRhaW4gdGhlIGZvbGxvd2luZzoKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGltcG9ydCBFbWJlciBmcm9tICdlbWJlcic7CiAgICAgaW1wb3J0IEJsb2cgZnJvbSAnYXBwL21vZGVscy9ibG9nJzsKICAgICAgbGV0IHJlbGF0aW9uc2hpcHNCeU5hbWUgPSBFbWJlci5nZXQoQmxvZywgJ3JlbGF0aW9uc2hpcHNCeU5hbWUnKTsKICAgICByZWxhdGlvbnNoaXBzQnlOYW1lLmdldCgndXNlcnMnKTsKICAgICAvLz0+IHsga2V5OiAndXNlcnMnLCBraW5kOiAnaGFzTWFueScsIHR5cGU6ICd1c2VyJywgb3B0aW9uczogT2JqZWN0LCBpc1JlbGF0aW9uc2hpcDogdHJ1ZSB9CiAgICAgcmVsYXRpb25zaGlwc0J5TmFtZS5nZXQoJ293bmVyJyk7CiAgICAgLy89PiB7IGtleTogJ293bmVyJywga2luZDogJ2JlbG9uZ3NUbycsIHR5cGU6ICd1c2VyJywgb3B0aW9uczogT2JqZWN0LCBpc1JlbGF0aW9uc2hpcDogdHJ1ZSB9CiAgICAgYGBgCiAgICAgIEBwcm9wZXJ0eSByZWxhdGlvbnNoaXBzQnlOYW1lCiAgICAgQHN0YXRpYwogICAgIEB0eXBlIE1hcAogICAgIEByZWFkT25seQogICAgICovCiAgICByZWxhdGlvbnNoaXBzQnlOYW1lOiBQcml2YXRlLnJlbGF0aW9uc2hpcHNCeU5hbWVEZXNjcmlwdG9yLAogICAgcmVsYXRpb25zaGlwc09iamVjdDogUHJpdmF0ZS5yZWxhdGlvbnNoaXBzT2JqZWN0RGVzY3JpcHRvciwKCiAgICAvKioKICAgICBBIG1hcCB3aG9zZSBrZXlzIGFyZSB0aGUgZmllbGRzIG9mIHRoZSBtb2RlbCBhbmQgd2hvc2UgdmFsdWVzIGFyZSBzdHJpbmdzCiAgICAgZGVzY3JpYmluZyB0aGUga2luZCBvZiB0aGUgZmllbGQuIEEgbW9kZWwncyBmaWVsZHMgYXJlIHRoZSB1bmlvbiBvZiBhbGwgb2YgaXRzCiAgICAgYXR0cmlidXRlcyBhbmQgcmVsYXRpb25zaGlwcy4KICAgICAgRm9yIGV4YW1wbGU6CiAgICAgIGBgYGFwcC9tb2RlbHMvYmxvZy5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyLCBiZWxvbmdzVG8sIGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdXNlcnM6IGhhc01hbnkoJ3VzZXInKSwKICAgICAgICBvd25lcjogYmVsb25nc1RvKCd1c2VyJyksCiAgICAgICAgIHBvc3RzOiBoYXNNYW55KCdwb3N0JyksCiAgICAgICAgIHRpdGxlOiBhdHRyKCdzdHJpbmcnKQogICAgICB9KTsKICAgICBgYGAKICAgICAgYGBganMKICAgICBpbXBvcnQgRW1iZXIgZnJvbSAnZW1iZXInOwogICAgIGltcG9ydCBCbG9nIGZyb20gJ2FwcC9tb2RlbHMvYmxvZyc7CiAgICAgIGxldCBmaWVsZHMgPSBFbWJlci5nZXQoQmxvZywgJ2ZpZWxkcycpOwogICAgIGZpZWxkcy5mb3JFYWNoKGZ1bmN0aW9uKGtpbmQsIGZpZWxkKSB7CiAgICAgICAgY29uc29sZS5sb2coZmllbGQsIGtpbmQpOwogICAgICB9KTsKICAgICAgLy8gcHJpbnRzOgogICAgIC8vIHVzZXJzLCBoYXNNYW55CiAgICAgLy8gb3duZXIsIGJlbG9uZ3NUbwogICAgIC8vIHBvc3RzLCBoYXNNYW55CiAgICAgLy8gdGl0bGUsIGF0dHJpYnV0ZQogICAgIGBgYAogICAgICBAcHJvcGVydHkgZmllbGRzCiAgICAgQHN0YXRpYwogICAgIEB0eXBlIE1hcAogICAgIEByZWFkT25seQogICAgICovCiAgICBmaWVsZHM6IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIG1hcCA9IG5ldyBNYXAoKTsKICAgICAgdGhpcy5lYWNoQ29tcHV0ZWRQcm9wZXJ0eShmdW5jdGlvbiAobmFtZSwgbWV0YSkgewogICAgICAgIGlmIChtZXRhLmlzUmVsYXRpb25zaGlwKSB7CiAgICAgICAgICBtYXAuc2V0KG5hbWUsIG1ldGEua2luZCk7CiAgICAgICAgfSBlbHNlIGlmIChtZXRhLmlzQXR0cmlidXRlKSB7CiAgICAgICAgICBtYXAuc2V0KG5hbWUsICdhdHRyaWJ1dGUnKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gbWFwOwogICAgfSkucmVhZE9ubHkoKSwKCiAgICAvKioKICAgICBHaXZlbiBhIGNhbGxiYWNrLCBpdGVyYXRlcyBvdmVyIGVhY2ggb2YgdGhlIHJlbGF0aW9uc2hpcHMgaW4gdGhlIG1vZGVsLAogICAgIGludm9raW5nIHRoZSBjYWxsYmFjayB3aXRoIHRoZSBuYW1lIG9mIGVhY2ggcmVsYXRpb25zaGlwIGFuZCBpdHMgcmVsYXRpb25zaGlwCiAgICAgZGVzY3JpcHRvci4KICAgICAgQG1ldGhvZCBlYWNoUmVsYXRpb25zaGlwCiAgICAgQHN0YXRpYwogICAgIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIHRoZSBjYWxsYmFjayB0byBpbnZva2UKICAgICBAcGFyYW0ge2FueX0gYmluZGluZyB0aGUgdmFsdWUgdG8gd2hpY2ggdGhlIGNhbGxiYWNrJ3MgYHRoaXNgIHNob3VsZCBiZSBib3VuZAogICAgICovCiAgICBlYWNoUmVsYXRpb25zaGlwOiBmdW5jdGlvbiBlYWNoUmVsYXRpb25zaGlwKGNhbGxiYWNrLCBiaW5kaW5nKSB7CiAgICAgIEVtYmVyLmdldCh0aGlzLCAncmVsYXRpb25zaGlwc0J5TmFtZScpLmZvckVhY2goZnVuY3Rpb24gKHJlbGF0aW9uc2hpcCwgbmFtZSkgewogICAgICAgIGNhbGxiYWNrLmNhbGwoYmluZGluZywgbmFtZSwgcmVsYXRpb25zaGlwKTsKICAgICAgfSk7CiAgICB9LAoKICAgIC8qKgogICAgIEdpdmVuIGEgY2FsbGJhY2ssIGl0ZXJhdGVzIG92ZXIgZWFjaCBvZiB0aGUgdHlwZXMgcmVsYXRlZCB0byBhIG1vZGVsLAogICAgIGludm9raW5nIHRoZSBjYWxsYmFjayB3aXRoIHRoZSByZWxhdGVkIHR5cGUncyBjbGFzcy4gRWFjaCB0eXBlIHdpbGwgYmUKICAgICByZXR1cm5lZCBqdXN0IG9uY2UsIHJlZ2FyZGxlc3Mgb2YgaG93IG1hbnkgZGlmZmVyZW50IHJlbGF0aW9uc2hpcHMgaXQgaGFzCiAgICAgd2l0aCBhIG1vZGVsLgogICAgICBAbWV0aG9kIGVhY2hSZWxhdGVkVHlwZQogICAgIEBzdGF0aWMKICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayB0aGUgY2FsbGJhY2sgdG8gaW52b2tlCiAgICAgQHBhcmFtIHthbnl9IGJpbmRpbmcgdGhlIHZhbHVlIHRvIHdoaWNoIHRoZSBjYWxsYmFjaydzIGB0aGlzYCBzaG91bGQgYmUgYm91bmQKICAgICAqLwogICAgZWFjaFJlbGF0ZWRUeXBlOiBmdW5jdGlvbiBlYWNoUmVsYXRlZFR5cGUoY2FsbGJhY2ssIGJpbmRpbmcpIHsKICAgICAgdmFyIHJlbGF0aW9uc2hpcFR5cGVzID0gRW1iZXIuZ2V0KHRoaXMsICdyZWxhdGVkVHlwZXMnKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVsYXRpb25zaGlwVHlwZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgdHlwZSA9IHJlbGF0aW9uc2hpcFR5cGVzW2ldOwogICAgICAgIGNhbGxiYWNrLmNhbGwoYmluZGluZywgdHlwZSk7CiAgICAgIH0KICAgIH0sCiAgICBkZXRlcm1pbmVSZWxhdGlvbnNoaXBUeXBlOiBmdW5jdGlvbiBkZXRlcm1pbmVSZWxhdGlvbnNoaXBUeXBlKGtub3duU2lkZSwgc3RvcmUpIHsKICAgICAgdmFyIGtub3duS2V5ID0ga25vd25TaWRlLmtleTsKICAgICAgdmFyIGtub3duS2luZCA9IGtub3duU2lkZS5raW5kOwogICAgICB2YXIgaW52ZXJzZSA9IHRoaXMuaW52ZXJzZUZvcihrbm93bktleSwgc3RvcmUpOyAvLyBsZXQga2V5OwoKICAgICAgdmFyIG90aGVyS2luZDsKCiAgICAgIGlmICghaW52ZXJzZSkgewogICAgICAgIHJldHVybiBrbm93bktpbmQgPT09ICdiZWxvbmdzVG8nID8gJ29uZVRvTm9uZScgOiAnbWFueVRvTm9uZSc7CiAgICAgIH0gLy8ga2V5ID0gaW52ZXJzZS5uYW1lOwoKCiAgICAgIG90aGVyS2luZCA9IGludmVyc2Uua2luZDsKCiAgICAgIGlmIChvdGhlcktpbmQgPT09ICdiZWxvbmdzVG8nKSB7CiAgICAgICAgcmV0dXJuIGtub3duS2luZCA9PT0gJ2JlbG9uZ3NUbycgPyAnb25lVG9PbmUnIDogJ21hbnlUb09uZSc7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGtub3duS2luZCA9PT0gJ2JlbG9uZ3NUbycgPyAnb25lVG9NYW55JyA6ICdtYW55VG9NYW55JzsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICBBIG1hcCB3aG9zZSBrZXlzIGFyZSB0aGUgYXR0cmlidXRlcyBvZiB0aGUgbW9kZWwgKHByb3BlcnRpZXMKICAgICBkZXNjcmliZWQgYnkgYXR0cikgYW5kIHdob3NlIHZhbHVlcyBhcmUgdGhlIG1ldGEgb2JqZWN0IGZvciB0aGUKICAgICBwcm9wZXJ0eS4KICAgICAgRXhhbXBsZQogICAgICBgYGBhcHAvbW9kZWxzL3BlcnNvbi5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIGZpcnN0TmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgICAgbGFzdE5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICAgIGJpcnRoZGF5OiBhdHRyKCdkYXRlJykKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBpbXBvcnQgRW1iZXIgZnJvbSAnZW1iZXInOwogICAgIGltcG9ydCBQZXJzb24gZnJvbSAnYXBwL21vZGVscy9wZXJzb24nOwogICAgICBsZXQgYXR0cmlidXRlcyA9IEVtYmVyLmdldChQZXJzb24sICdhdHRyaWJ1dGVzJykKICAgICAgYXR0cmlidXRlcy5mb3JFYWNoKGZ1bmN0aW9uKG1ldGEsIG5hbWUpIHsKICAgICAgICBjb25zb2xlLmxvZyhuYW1lLCBtZXRhKTsKICAgICAgfSk7CiAgICAgIC8vIHByaW50czoKICAgICAvLyBmaXJzdE5hbWUge3R5cGU6ICJzdHJpbmciLCBpc0F0dHJpYnV0ZTogdHJ1ZSwgb3B0aW9uczogT2JqZWN0LCBwYXJlbnRUeXBlOiBmdW5jdGlvbiwgbmFtZTogImZpcnN0TmFtZSJ9CiAgICAgLy8gbGFzdE5hbWUge3R5cGU6ICJzdHJpbmciLCBpc0F0dHJpYnV0ZTogdHJ1ZSwgb3B0aW9uczogT2JqZWN0LCBwYXJlbnRUeXBlOiBmdW5jdGlvbiwgbmFtZTogImxhc3ROYW1lIn0KICAgICAvLyBiaXJ0aGRheSB7dHlwZTogImRhdGUiLCBpc0F0dHJpYnV0ZTogdHJ1ZSwgb3B0aW9uczogT2JqZWN0LCBwYXJlbnRUeXBlOiBmdW5jdGlvbiwgbmFtZTogImJpcnRoZGF5In0KICAgICBgYGAKICAgICAgQHByb3BlcnR5IGF0dHJpYnV0ZXMKICAgICBAc3RhdGljCiAgICAgQHR5cGUge01hcH0KICAgICBAcmVhZE9ubHkKICAgICAqLwogICAgYXR0cmlidXRlczogRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewoKICAgICAgdmFyIG1hcCA9IG5ldyBNYXAoKTsKICAgICAgdGhpcy5lYWNoQ29tcHV0ZWRQcm9wZXJ0eShmdW5jdGlvbiAobmFtZSwgbWV0YSkgewogICAgICAgIGlmIChtZXRhLmlzQXR0cmlidXRlKSB7CiAgICAgICAgICBtZXRhLm5hbWUgPSBuYW1lOwogICAgICAgICAgbWFwLnNldChuYW1lLCBtZXRhKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gbWFwOwogICAgfSkucmVhZE9ubHkoKSwKCiAgICAvKioKICAgICBBIG1hcCB3aG9zZSBrZXlzIGFyZSB0aGUgYXR0cmlidXRlcyBvZiB0aGUgbW9kZWwgKHByb3BlcnRpZXMKICAgICBkZXNjcmliZWQgYnkgYXR0cikgYW5kIHdob3NlIHZhbHVlcyBhcmUgdHlwZSBvZiB0cmFuc2Zvcm1hdGlvbgogICAgIGFwcGxpZWQgdG8gZWFjaCBhdHRyaWJ1dGUuIFRoaXMgbWFwIGRvZXMgbm90IGluY2x1ZGUgYW55CiAgICAgYXR0cmlidXRlcyB0aGF0IGRvIG5vdCBoYXZlIGFuIHRyYW5zZm9ybWF0aW9uIHR5cGUuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgYXBwL21vZGVscy9wZXJzb24uanMKICAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICBmaXJzdE5hbWU6IGF0dHIoKSwKICAgICAgICBsYXN0TmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgICAgYmlydGhkYXk6IGF0dHIoJ2RhdGUnKQogICAgICB9KTsKICAgICBgYGAKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGltcG9ydCBFbWJlciBmcm9tICdlbWJlcic7CiAgICAgaW1wb3J0IFBlcnNvbiBmcm9tICdhcHAvbW9kZWxzL3BlcnNvbic7CiAgICAgIGxldCB0cmFuc2Zvcm1lZEF0dHJpYnV0ZXMgPSBFbWJlci5nZXQoUGVyc29uLCAndHJhbnNmb3JtZWRBdHRyaWJ1dGVzJykKICAgICAgdHJhbnNmb3JtZWRBdHRyaWJ1dGVzLmZvckVhY2goZnVuY3Rpb24oZmllbGQsIHR5cGUpIHsKICAgICAgICBjb25zb2xlLmxvZyhmaWVsZCwgdHlwZSk7CiAgICAgIH0pOwogICAgICAvLyBwcmludHM6CiAgICAgLy8gbGFzdE5hbWUgc3RyaW5nCiAgICAgLy8gYmlydGhkYXkgZGF0ZQogICAgIGBgYAogICAgICBAcHJvcGVydHkgdHJhbnNmb3JtZWRBdHRyaWJ1dGVzCiAgICAgQHN0YXRpYwogICAgIEB0eXBlIHtNYXB9CiAgICAgQHJlYWRPbmx5CiAgICAgKi8KICAgIHRyYW5zZm9ybWVkQXR0cmlidXRlczogRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgICB2YXIgbWFwID0gbmV3IE1hcCgpOwogICAgICB0aGlzLmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24gKGtleSwgbWV0YSkgewogICAgICAgIGlmIChtZXRhLnR5cGUpIHsKICAgICAgICAgIG1hcC5zZXQoa2V5LCBtZXRhLnR5cGUpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiBtYXA7CiAgICB9KS5yZWFkT25seSgpLAoKICAgIC8qKgogICAgIEl0ZXJhdGVzIHRocm91Z2ggdGhlIGF0dHJpYnV0ZXMgb2YgdGhlIG1vZGVsLCBjYWxsaW5nIHRoZSBwYXNzZWQgZnVuY3Rpb24gb24gZWFjaAogICAgIGF0dHJpYnV0ZS4KICAgICAgVGhlIGNhbGxiYWNrIG1ldGhvZCB5b3UgcHJvdmlkZSBzaG91bGQgaGF2ZSB0aGUgZm9sbG93aW5nIHNpZ25hdHVyZSAoYWxsCiAgICAgcGFyYW1ldGVycyBhcmUgb3B0aW9uYWwpOgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgZnVuY3Rpb24obmFtZSwgbWV0YSk7CiAgICAgYGBgCiAgICAgIC0gYG5hbWVgIHRoZSBuYW1lIG9mIHRoZSBjdXJyZW50IHByb3BlcnR5IGluIHRoZSBpdGVyYXRpb24KICAgICAtIGBtZXRhYCB0aGUgbWV0YSBvYmplY3QgZm9yIHRoZSBhdHRyaWJ1dGUgcHJvcGVydHkgaW4gdGhlIGl0ZXJhdGlvbgogICAgICBOb3RlIHRoYXQgaW4gYWRkaXRpb24gdG8gYSBjYWxsYmFjaywgeW91IGNhbiBhbHNvIHBhc3MgYW4gb3B0aW9uYWwgdGFyZ2V0CiAgICAgb2JqZWN0IHRoYXQgd2lsbCBiZSBzZXQgYXMgYHRoaXNgIG9uIHRoZSBjb250ZXh0LgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgbGV0IFBlcnNvbiA9IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgZmlyc3ROYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgICBsYXN0TmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgICAgYmlydGhkYXk6IGF0dHIoJ2RhdGUnKQogICAgICB9KTsKICAgICAgUGVyc29uLmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24obmFtZSwgbWV0YSkgewogICAgICAgIGNvbnNvbGUubG9nKG5hbWUsIG1ldGEpOwogICAgICB9KTsKICAgICAgLy8gcHJpbnRzOgogICAgIC8vIGZpcnN0TmFtZSB7dHlwZTogInN0cmluZyIsIGlzQXR0cmlidXRlOiB0cnVlLCBvcHRpb25zOiBPYmplY3QsIHBhcmVudFR5cGU6IGZ1bmN0aW9uLCBuYW1lOiAiZmlyc3ROYW1lIn0KICAgICAvLyBsYXN0TmFtZSB7dHlwZTogInN0cmluZyIsIGlzQXR0cmlidXRlOiB0cnVlLCBvcHRpb25zOiBPYmplY3QsIHBhcmVudFR5cGU6IGZ1bmN0aW9uLCBuYW1lOiAibGFzdE5hbWUifQogICAgIC8vIGJpcnRoZGF5IHt0eXBlOiAiZGF0ZSIsIGlzQXR0cmlidXRlOiB0cnVlLCBvcHRpb25zOiBPYmplY3QsIHBhcmVudFR5cGU6IGZ1bmN0aW9uLCBuYW1lOiAiYmlydGhkYXkifQogICAgIGBgYAogICAgICBAbWV0aG9kIGVhY2hBdHRyaWJ1dGUKICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgY2FsbGJhY2sgdG8gZXhlY3V0ZQogICAgIEBwYXJhbSB7T2JqZWN0fSBbYmluZGluZ10gdGhlIHZhbHVlIHRvIHdoaWNoIHRoZSBjYWxsYmFjaydzIGB0aGlzYCBzaG91bGQgYmUgYm91bmQKICAgICBAc3RhdGljCiAgICAgKi8KICAgIGVhY2hBdHRyaWJ1dGU6IGZ1bmN0aW9uIGVhY2hBdHRyaWJ1dGUoY2FsbGJhY2ssIGJpbmRpbmcpIHsKICAgICAgRW1iZXIuZ2V0KHRoaXMsICdhdHRyaWJ1dGVzJykuZm9yRWFjaChmdW5jdGlvbiAobWV0YSwgbmFtZSkgewogICAgICAgIGNhbGxiYWNrLmNhbGwoYmluZGluZywgbmFtZSwgbWV0YSk7CiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICBJdGVyYXRlcyB0aHJvdWdoIHRoZSB0cmFuc2Zvcm1lZEF0dHJpYnV0ZXMgb2YgdGhlIG1vZGVsLCBjYWxsaW5nCiAgICAgdGhlIHBhc3NlZCBmdW5jdGlvbiBvbiBlYWNoIGF0dHJpYnV0ZS4gTm90ZSB0aGUgY2FsbGJhY2sgd2lsbCBub3QgYmUKICAgICBjYWxsZWQgZm9yIGFueSBhdHRyaWJ1dGVzIHRoYXQgZG8gbm90IGhhdmUgYW4gdHJhbnNmb3JtYXRpb24gdHlwZS4KICAgICAgVGhlIGNhbGxiYWNrIG1ldGhvZCB5b3UgcHJvdmlkZSBzaG91bGQgaGF2ZSB0aGUgZm9sbG93aW5nIHNpZ25hdHVyZSAoYWxsCiAgICAgcGFyYW1ldGVycyBhcmUgb3B0aW9uYWwpOgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgZnVuY3Rpb24obmFtZSwgdHlwZSk7CiAgICAgYGBgCiAgICAgIC0gYG5hbWVgIHRoZSBuYW1lIG9mIHRoZSBjdXJyZW50IHByb3BlcnR5IGluIHRoZSBpdGVyYXRpb24KICAgICAtIGB0eXBlYCBhIHN0cmluZyBjb250YWluaW5nIHRoZSBuYW1lIG9mIHRoZSB0eXBlIG9mIHRyYW5zZm9ybWVkCiAgICAgYXBwbGllZCB0byB0aGUgYXR0cmlidXRlCiAgICAgIE5vdGUgdGhhdCBpbiBhZGRpdGlvbiB0byBhIGNhbGxiYWNrLCB5b3UgY2FuIGFsc28gcGFzcyBhbiBvcHRpb25hbCB0YXJnZXQKICAgICBvYmplY3QgdGhhdCB3aWxsIGJlIHNldCBhcyBgdGhpc2Agb24gdGhlIGNvbnRleHQuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICBsZXQgUGVyc29uID0gTW9kZWwuZXh0ZW5kKHsKICAgICAgICBmaXJzdE5hbWU6IGF0dHIoKSwKICAgICAgICBsYXN0TmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgICAgYmlydGhkYXk6IGF0dHIoJ2RhdGUnKQogICAgICB9KTsKICAgICAgUGVyc29uLmVhY2hUcmFuc2Zvcm1lZEF0dHJpYnV0ZShmdW5jdGlvbihuYW1lLCB0eXBlKSB7CiAgICAgICAgY29uc29sZS5sb2cobmFtZSwgdHlwZSk7CiAgICAgIH0pOwogICAgICAvLyBwcmludHM6CiAgICAgLy8gbGFzdE5hbWUgc3RyaW5nCiAgICAgLy8gYmlydGhkYXkgZGF0ZQogICAgIGBgYAogICAgICBAbWV0aG9kIGVhY2hUcmFuc2Zvcm1lZEF0dHJpYnV0ZQogICAgIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBjYWxsYmFjayB0byBleGVjdXRlCiAgICAgQHBhcmFtIHtPYmplY3R9IFtiaW5kaW5nXSB0aGUgdmFsdWUgdG8gd2hpY2ggdGhlIGNhbGxiYWNrJ3MgYHRoaXNgIHNob3VsZCBiZSBib3VuZAogICAgIEBzdGF0aWMKICAgICAqLwogICAgZWFjaFRyYW5zZm9ybWVkQXR0cmlidXRlOiBmdW5jdGlvbiBlYWNoVHJhbnNmb3JtZWRBdHRyaWJ1dGUoY2FsbGJhY2ssIGJpbmRpbmcpIHsKICAgICAgRW1iZXIuZ2V0KHRoaXMsICd0cmFuc2Zvcm1lZEF0dHJpYnV0ZXMnKS5mb3JFYWNoKGZ1bmN0aW9uICh0eXBlLCBuYW1lKSB7CiAgICAgICAgY2FsbGJhY2suY2FsbChiaW5kaW5nLCBuYW1lLCB0eXBlKTsKICAgICAgfSk7CiAgICB9LAoKICAgIC8qKgogICAgIFJldHVybnMgdGhlIG5hbWUgb2YgdGhlIG1vZGVsIGNsYXNzLgogICAgICBAbWV0aG9kIHRvU3RyaW5nCiAgICAgQHN0YXRpYwogICAgICovCiAgICB0b1N0cmluZzogZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiAibW9kZWw6IiArIEVtYmVyLmdldCh0aGlzLCAnbW9kZWxOYW1lJyk7CiAgICB9CiAgfSk7CgogIGV4cG9ydHMuTW9kZWwgPSBNb2RlbDsKICBleHBvcnRzLmF0dHIgPSBhdHRyJDE7CiAgZXhwb3J0cy5iZWxvbmdzVG8gPSBiZWxvbmdzVG8kMTsKICBleHBvcnRzLmhhc01hbnkgPSBoYXNNYW55JDE7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7Cgp9KTsKCjtkZWZpbmUoIkBlbWJlci1kYXRhL21vZGVsL2luZGV4IiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL21vZGVsLy1wcml2YXRlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3ByaXZhdGUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlZmF1bHQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJpdmF0ZS5Nb2RlbDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJhdHRyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUuYXR0cjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJiZWxvbmdzVG8iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJpdmF0ZS5iZWxvbmdzVG87CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiaGFzTWFueSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9wcml2YXRlLmhhc01hbnk7CiAgICB9CiAgfSk7Cn0pOwo7ZGVmaW5lKCdAZW1iZXItZGF0YS9yZWNvcmQtZGF0YS8tcHJpdmF0ZScsIFsnZXhwb3J0cycsICdAZW1iZXItZGF0YS9zdG9yZS8tcHJpdmF0ZScsICdAZW1iZXIvb3JkZXJlZC1zZXQnLCAnQGVtYmVyLWRhdGEvY2FuYXJ5LWZlYXR1cmVzJ10sIGZ1bmN0aW9uIChleHBvcnRzLCBQcml2YXRlLCBFbWJlck9yZGVyZWRTZXQsIGNhbmFyeUZlYXR1cmVzKSB7ICd1c2Ugc3RyaWN0JzsKCiAgRW1iZXJPcmRlcmVkU2V0ID0gRW1iZXJPcmRlcmVkU2V0ICYmIEVtYmVyT3JkZXJlZFNldC5oYXNPd25Qcm9wZXJ0eSgnZGVmYXVsdCcpID8gRW1iZXJPcmRlcmVkU2V0WydkZWZhdWx0J10gOiBFbWJlck9yZGVyZWRTZXQ7CgogIGZ1bmN0aW9uIHJlbGF0aW9uc2hpcHNGb3IoaW5zdGFuY2UpIHsKICAgIHZhciByZWNvcmREYXRhID0gUHJpdmF0ZS5yZWNvcmREYXRhRm9yKGluc3RhbmNlKSB8fCBpbnN0YW5jZTsKICAgIHJldHVybiByZWNvcmREYXRhLl9yZWxhdGlvbnNoaXBzOwogIH0KICBmdW5jdGlvbiByZWxhdGlvbnNoaXBTdGF0ZUZvcihpbnN0YW5jZSwgcHJvcGVydHlOYW1lKSB7CiAgICByZXR1cm4gcmVsYXRpb25zaGlwc0ZvcihpbnN0YW5jZSkuZ2V0KHByb3BlcnR5TmFtZSk7CiAgfQogIGZ1bmN0aW9uIGltcGxpY2l0UmVsYXRpb25zaGlwc0ZvcihpbnN0YW5jZSkgewogICAgdmFyIHJlY29yZERhdGEgPSBQcml2YXRlLnJlY29yZERhdGFGb3IoaW5zdGFuY2UpIHx8IGluc3RhbmNlOwogICAgcmV0dXJuIHJlY29yZERhdGEuX2ltcGxpY2l0UmVsYXRpb25zaGlwczsKICB9CiAgZnVuY3Rpb24gaW1wbGljaXRSZWxhdGlvbnNoaXBTdGF0ZUZvcihpbnN0YW5jZSwgcHJvcGVydHlOYW1lKSB7CiAgICByZXR1cm4gaW1wbGljaXRSZWxhdGlvbnNoaXBzRm9yKGluc3RhbmNlKVtwcm9wZXJ0eU5hbWVdOwogIH0KCiAgZnVuY3Rpb24gX2luaGVyaXRzTG9vc2Uoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzLnByb3RvdHlwZSk7IHN1YkNsYXNzLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IHN1YkNsYXNzOyBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9CgogIHZhciBFbWJlckRhdGFPcmRlcmVkU2V0ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9FbWJlck9yZGVyZWRTZXQpIHsKICAgIF9pbmhlcml0c0xvb3NlKEVtYmVyRGF0YU9yZGVyZWRTZXQsIF9FbWJlck9yZGVyZWRTZXQpOwoKICAgIGZ1bmN0aW9uIEVtYmVyRGF0YU9yZGVyZWRTZXQoKSB7CiAgICAgIHJldHVybiBfRW1iZXJPcmRlcmVkU2V0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgIH0KCiAgICBFbWJlckRhdGFPcmRlcmVkU2V0LmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgcmV0dXJuIG5ldyB0aGlzKCk7CiAgICB9OwoKICAgIHZhciBfcHJvdG8gPSBFbWJlckRhdGFPcmRlcmVkU2V0LnByb3RvdHlwZTsKCiAgICBfcHJvdG8uYWRkV2l0aEluZGV4ID0gZnVuY3Rpb24gYWRkV2l0aEluZGV4KG9iaiwgaWR4KSB7CiAgICAgIHZhciBndWlkID0gRW1iZXIuZ3VpZEZvcihvYmopOwogICAgICB2YXIgcHJlc2VuY2VTZXQgPSB0aGlzLnByZXNlbmNlU2V0OwogICAgICB2YXIgbGlzdCA9IHRoaXMubGlzdDsKCiAgICAgIGlmIChwcmVzZW5jZVNldFtndWlkXSA9PT0gdHJ1ZSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgcHJlc2VuY2VTZXRbZ3VpZF0gPSB0cnVlOwoKICAgICAgaWYgKGlkeCA9PT0gdW5kZWZpbmVkIHx8IGlkeCA9PT0gbnVsbCkgewogICAgICAgIGxpc3QucHVzaChvYmopOwogICAgICB9IGVsc2UgewogICAgICAgIGxpc3Quc3BsaWNlKGlkeCwgMCwgb2JqKTsKICAgICAgfQoKICAgICAgdGhpcy5zaXplICs9IDE7CiAgICAgIHJldHVybiB0aGlzOwogICAgfTsKCiAgICByZXR1cm4gRW1iZXJEYXRhT3JkZXJlZFNldDsKICB9KEVtYmVyT3JkZXJlZFNldCk7CgogIC8qCiAgICBUaGlzIG1ldGhvZCBub3JtYWxpemVzIGEgbGluayB0byBhbiAibGlua3Mgb2JqZWN0Ii4gSWYgdGhlIHBhc3NlZCBsaW5rIGlzCiAgICBhbHJlYWR5IGFuIG9iamVjdCBpdCdzIHJldHVybmVkIHdpdGhvdXQgYW55IG1vZGlmaWNhdGlvbnMuCgogICAgU2VlIGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2RvY3VtZW50LWxpbmtzIGZvciBtb3JlIGluZm9ybWF0aW9uLgoKICAgIEBtZXRob2QgX25vcm1hbGl6ZUxpbmsKICAgIEBpbnRlcm5hbAogICAgQHBhcmFtIHtTdHJpbmd9IGxpbmsKICAgIEByZXR1cm4ge09iamVjdHxudWxsfQogICovCiAgZnVuY3Rpb24gX25vcm1hbGl6ZUxpbmsobGluaykgewogICAgc3dpdGNoICh0eXBlb2YgbGluaykgewogICAgICBjYXNlICdvYmplY3QnOgogICAgICAgIHJldHVybiBsaW5rOwoKICAgICAgY2FzZSAnc3RyaW5nJzoKICAgICAgICByZXR1cm4gewogICAgICAgICAgaHJlZjogbGluawogICAgICAgIH07CiAgICB9CgogICAgcmV0dXJuIG51bGw7CiAgfQoKICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgidmFsdWUiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfQoKICBmdW5jdGlvbiBfY3JlYXRlQ2xhc3MoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfQoKICB2YXIgUmVsYXRpb25zaGlwID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUmVsYXRpb25zaGlwKHN0b3JlLCBpbnZlcnNlS2V5LCByZWxhdGlvbnNoaXBNZXRhLCByZWNvcmREYXRhLCBpbnZlcnNlSXNBc3luYykgewogICAgICB0aGlzLmludmVyc2VJc0FzeW5jID0gdm9pZCAwOwogICAgICB0aGlzLmtpbmQgPSB2b2lkIDA7CiAgICAgIHRoaXMucmVjb3JkRGF0YSA9IHZvaWQgMDsKICAgICAgdGhpcy5tZW1iZXJzID0gdm9pZCAwOwogICAgICB0aGlzLmNhbm9uaWNhbE1lbWJlcnMgPSB2b2lkIDA7CiAgICAgIHRoaXMuc3RvcmUgPSB2b2lkIDA7CiAgICAgIHRoaXMua2V5ID0gdm9pZCAwOwogICAgICB0aGlzLmludmVyc2VLZXkgPSB2b2lkIDA7CiAgICAgIHRoaXMuaXNBc3luYyA9IHZvaWQgMDsKICAgICAgdGhpcy5pc1BvbHltb3JwaGljID0gdm9pZCAwOwogICAgICB0aGlzLnJlbGF0aW9uc2hpcE1ldGEgPSB2b2lkIDA7CiAgICAgIHRoaXMuaW52ZXJzZUtleUZvckltcGxpY2l0ID0gdm9pZCAwOwogICAgICB0aGlzLm1ldGEgPSB2b2lkIDA7CiAgICAgIHRoaXMuX19pbnZlcnNlTWV0YSA9IHZvaWQgMDsKICAgICAgdGhpcy5fdGVtcE1vZGVsTmFtZSA9IHZvaWQgMDsKICAgICAgdGhpcy5zaG91bGRGb3JjZVJlbG9hZCA9IGZhbHNlOwogICAgICB0aGlzLnJlbGF0aW9uc2hpcElzU3RhbGUgPSB2b2lkIDA7CiAgICAgIHRoaXMuaGFzRGVtYXRlcmlhbGl6ZWRJbnZlcnNlID0gdm9pZCAwOwogICAgICB0aGlzLmhhc0FueVJlbGF0aW9uc2hpcERhdGEgPSB2b2lkIDA7CiAgICAgIHRoaXMucmVsYXRpb25zaGlwSXNFbXB0eSA9IHZvaWQgMDsKICAgICAgdGhpcy5oYXNGYWlsZWRMb2FkQXR0ZW1wdCA9IGZhbHNlOwogICAgICB0aGlzLmxpbmtzID0gdm9pZCAwOwogICAgICB0aGlzLndpbGxTeW5jID0gdm9pZCAwOwogICAgICB0aGlzLmludmVyc2VJc0FzeW5jID0gaW52ZXJzZUlzQXN5bmM7CiAgICAgIHRoaXMua2luZCA9IHJlbGF0aW9uc2hpcE1ldGEua2luZDsKICAgICAgdmFyIGFzeW5jID0gcmVsYXRpb25zaGlwTWV0YS5vcHRpb25zLmFzeW5jOwogICAgICB2YXIgcG9seW1vcnBoaWMgPSByZWxhdGlvbnNoaXBNZXRhLm9wdGlvbnMucG9seW1vcnBoaWM7CiAgICAgIHRoaXMucmVjb3JkRGF0YSA9IHJlY29yZERhdGE7CiAgICAgIHRoaXMubWVtYmVycyA9IG5ldyBFbWJlckRhdGFPcmRlcmVkU2V0KCk7CiAgICAgIHRoaXMuY2Fub25pY2FsTWVtYmVycyA9IG5ldyBFbWJlckRhdGFPcmRlcmVkU2V0KCk7CiAgICAgIHRoaXMuc3RvcmUgPSBzdG9yZTsKICAgICAgdGhpcy5rZXkgPSByZWxhdGlvbnNoaXBNZXRhLmtleSB8fCBudWxsOwogICAgICB0aGlzLmludmVyc2VLZXkgPSBpbnZlcnNlS2V5OwogICAgICB0aGlzLmlzQXN5bmMgPSB0eXBlb2YgYXN5bmMgPT09ICd1bmRlZmluZWQnID8gdHJ1ZSA6IGFzeW5jOwogICAgICB0aGlzLmlzUG9seW1vcnBoaWMgPSB0eXBlb2YgcG9seW1vcnBoaWMgPT09ICd1bmRlZmluZWQnID8gZmFsc2UgOiBwb2x5bW9ycGhpYzsKICAgICAgdGhpcy5yZWxhdGlvbnNoaXBNZXRhID0gcmVsYXRpb25zaGlwTWV0YTsgLy9UaGlzIHByb2JhYmx5IGJyZWFrcyBmb3IgcG9seW1vcnBoaWMgcmVsYXRpb25zaGlwIGluIGNvbXBsZXggc2NlbmFyaW9zLCBkdWUgdG8KICAgICAgLy9tdWx0aXBsZSBwb3NzaWJsZSBtb2RlbE5hbWVzCgogICAgICB0aGlzLmludmVyc2VLZXlGb3JJbXBsaWNpdCA9IHRoaXMuX3RlbXBNb2RlbE5hbWUgKyB0aGlzLmtleTsKICAgICAgdGhpcy5tZXRhID0gbnVsbDsKICAgICAgdGhpcy5fX2ludmVyc2VNZXRhID0gdW5kZWZpbmVkOwogICAgICAvKgogICAgICAgVGhpcyBmbGFnIGZvcmNlcyBmZXRjaC4gYHRydWVgIGZvciBhIHNpbmdsZSByZXF1ZXN0IG9uY2UgYHJlbG9hZCgpYAogICAgICAgICBoYXMgYmVlbiBjYWxsZWQgYGZhbHNlYCBhdCBhbGwgb3RoZXIgdGltZXMuCiAgICAgICovCiAgICAgIC8vIHRoaXMuc2hvdWxkRm9yY2VSZWxvYWQgPSBmYWxzZTsKCiAgICAgIC8qCiAgICAgICAgIFRoaXMgZmxhZyBpbmRpY2F0ZXMgd2hldGhlciB3ZSBzaG91bGQKICAgICAgICAgIHJlLWZldGNoIHRoZSByZWxhdGlvbnNoaXAgdGhlIG5leHQgdGltZQogICAgICAgICAgaXQgaXMgYWNjZXNzZWQuCiAgICAgICAgICAgVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGlzIGZsYWcgYW5kIGBzaG91bGRGb3JjZVJlbG9hZGAKICAgICAgICAgIGlzIGluIGhvdyB3ZSB0cmVhdCB0aGUgcHJlc2VuY2Ugb2YgcGFydGlhbGx5IG1pc3NpbmcgZGF0YToKICAgICAgICAgICAgLSBmb3IgYSBmb3JjZWQgcmVsb2FkLCB3ZSB3aWxsIHJlbG9hZCB0aGUgbGluayBvciBFVkVSWSByZWNvcmQKICAgICAgICAgICAgLSBmb3IgYSBzdGFsZSByZWxvYWQsIHdlIHdpbGwgcmVsb2FkIHRoZSBsaW5rIChpZiBwcmVzZW50KSBlbHNlIG9ubHkgTUlTU0lORyByZWNvcmRzCiAgICAgICAgICAgSWRlYWxseSB0aGVzZSBmbGFncyBjb3VsZCBiZSBtZXJnZWQsIGJ1dCBiZWNhdXNlIHdlIGRvbid0IGdpdmUgdGhlCiAgICAgICAgICByZXF1ZXN0IGxheWVyIHRoZSBvcHRpb24gb2YgZGVjaWRpbmcgaG93IHRvIHJlc29sdmUgdGhlIGRhdGEgYmVpbmcgcXVlcmllZAogICAgICAgICAgd2UgYXJlIGZvcmNlZCB0byBkaWZmZXJlbnRpYXRlIGZvciBub3cuCiAgICAgICAgICAgSXQgaXMgYWxzbyBwb3NzaWJsZSBmb3IgYSByZWxhdGlvbnNoaXAgdG8gcmVtYWluIHN0YWxlIGFmdGVyIGEgZm9yY2VkIHJlbG9hZDsgaG93ZXZlciwKICAgICAgICAgIGluIHRoaXMgY2FzZSBgaGFzRmFpbGVkTG9hZEF0dGVtcHRgIG91Z2h0IHRvIGJlIGB0cnVlYC4KICAgICAgICAgZmFsc2Ugd2hlbgogICAgICAgICAgPT4gcmVjb3JkRGF0YS5pc05ldygpIG9uIGluaXRpYWwgc2V0dXAKICAgICAgICAgID0+IGEgcHJldmlvdXNseSB0cmlnZ2VyZWQgcmVxdWVzdCBoYXMgcmVzb2x2ZWQKICAgICAgICAgID0+IHdlIGdldCByZWxhdGlvbnNoaXAgZGF0YSB2aWEgcHVzaAogICAgICAgICB0cnVlIHdoZW4KICAgICAgICAgID0+ICFyZWNvcmREYXRhLmlzTmV3KCkgb24gaW5pdGlhbCBzZXR1cAogICAgICAgICAgPT4gYW4gaW52ZXJzZSBoYXMgYmVlbiB1bmxvYWRlZAogICAgICAgICAgPT4gd2UgZ2V0IGEgbmV3IGxpbmsgZm9yIHRoZSByZWxhdGlvbnNoaXAKICAgICAgICAgVE9ETyBAcnVuc3BpcmVkIHVuc2tpcCB0aGUgYWNjZXB0YW5jZSB0ZXN0cyBhbmQgZml4IHRoZXNlIGZsYWdzCiAgICAgICAqLwoKICAgICAgdGhpcy5yZWxhdGlvbnNoaXBJc1N0YWxlID0gZmFsc2U7CiAgICAgIC8qCiAgICAgICBUaGlzIGZsYWcgaW5kaWNhdGVzIHdoZXRoZXIgd2Ugc2hvdWxkCiAgICAgICAgKipwYXJ0aWFsbHkqKiByZS1mZXRjaCB0aGUgcmVsYXRpb25zaGlwIHRoZQogICAgICAgIG5leHQgdGltZSBpdCBpcyBhY2Nlc3NlZC4KICAgICAgIGZhbHNlIHdoZW4KICAgICAgICA9PiBpbml0aWFsIHNldHVwCiAgICAgICAgPT4gYSBwcmV2aW91c2x5IHRyaWdnZXJlZCByZXF1ZXN0IGhhcyByZXNvbHZlZAogICAgICAgdHJ1ZSB3aGVuCiAgICAgICAgPT4gYW4gaW52ZXJzZSBoYXMgYmVlbiB1bmxvYWRlZAogICAgICAqLwoKICAgICAgdGhpcy5oYXNEZW1hdGVyaWFsaXplZEludmVyc2UgPSBmYWxzZTsKICAgICAgLyoKICAgICAgICBUaGlzIGZsYWcgaW5kaWNhdGVzIHdoZXRoZXIgd2Ugc2hvdWxkIGNvbnNpZGVyIHRoZSBjb250ZW50CiAgICAgICAgIG9mIHRoaXMgcmVsYXRpb25zaGlwICJrbm93biIuCiAgICAgICAgIElmIHdlIGhhdmUgbm8gcmVsYXRpb25zaGlwIGtub3dsZWRnZSwgYW5kIHRoZSByZWxhdGlvbnNoaXAKICAgICAgICAgaXMgYGFzeW5jYCwgd2Ugd2lsbCBhdHRlbXB0IHRvIGZldGNoIHRoZSByZWxhdGlvbnNoaXAgb24KICAgICAgICAgYWNjZXNzIGlmIGl0IGlzIGFsc28gc3RhbGUuCiAgICAgICAgU25hcHNob3QgdXNlcyB0aGlzIHRvIHRlbGwgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB1bmtub3duCiAgICAgICAgKGB1bmRlZmluZWRgKSBvciBlbXB0eSAoYG51bGxgKS4gVGhlIHJlYXNvbiBmb3IgdGhpcyBpcyB0aGF0CiAgICAgICAgd2Ugd291bGRuJ3Qgd2FudCB0byBzZXJpYWxpemUgIHVua25vd24gcmVsYXRpb25zaGlwcyBhcyBgbnVsbGAKICAgICAgICBhcyB0aGF0IG1pZ2h0IG92ZXJ3cml0ZSByZW1vdGUgc3RhdGUuCiAgICAgICAgIEFsbCByZWxhdGlvbnNoaXBzIGZvciBhIG5ld2x5IGNyZWF0ZWQgKGBzdG9yZS5jcmVhdGVSZWNvcmQoKWApIGFyZQogICAgICAgICBjb25zaWRlcmVkIGtub3duIChgaGFzQW55UmVsYXRpb25zaGlwRGF0YSA9PT0gdHJ1ZWApLgogICAgICAgICB0cnVlIHdoZW4KICAgICAgICAgID0+IHdlIHJlY2VpdmUgYSBwdXNoIHdpdGggZWl0aGVyIG5ldyBkYXRhIG9yIGV4cGxpY2l0IGVtcHR5IChgW11gIG9yIGBudWxsYCkKICAgICAgICAgID0+IHRoZSByZWxhdGlvbnNoaXAgaXMgYSBiZWxvbmdzVG8gYW5kIHdlIGhhdmUgcmVjZWl2ZWQgZGF0YSBmcm9tCiAgICAgICAgICAgICAgIHRoZSBvdGhlciBzaWRlLgogICAgICAgICBmYWxzZSB3aGVuCiAgICAgICAgICA9PiB3ZSBoYXZlIHJlY2VpdmVkIG5vIHNpZ25hbCBhYm91dCB3aGF0IGRhdGEgYmVsb25ncyBpbiB0aGlzIHJlbGF0aW9uc2hpcAogICAgICAgICAgPT4gdGhlIHJlbGF0aW9uc2hpcCBpcyBhIGhhc01hbnkgYW5kIHdlIGhhdmUgb25seSByZWNlaXZlZCBkYXRhIGZyb20KICAgICAgICAgICAgICB0aGUgb3RoZXIgc2lkZS4KICAgICAgICovCgogICAgICB0aGlzLmhhc0FueVJlbGF0aW9uc2hpcERhdGEgPSBmYWxzZTsKICAgICAgLyoKICAgICAgICBGbGFnIHRoYXQgaW5kaWNhdGVzIHdoZXRoZXIgYW4gZW1wdHkgcmVsYXRpb25zaGlwIGlzIGV4cGxpY2l0bHkgZW1wdHkKICAgICAgICAgIChzaWduYWxlZCBieSBwdXNoIGdpdmluZyB1cyBhbiBlbXB0eSBhcnJheSBvciBudWxsIHJlbGF0aW9uc2hpcCkKICAgICAgICAgIGUuZy4gYW4gQVBJIHJlc3BvbnNlIGhhcyB0b2xkIHVzIHRoYXQgdGhpcyByZWxhdGlvbnNoaXAgaXMgZW1wdHkuCiAgICAgICAgIFRodXMgZmFyLCBpdCBkb2VzIG5vdCBhcHBlYXIgdGhhdCB3ZSBhY3R1YWxseSBuZWVkIHRoaXMgZmxhZzsgaG93ZXZlciwKICAgICAgICAgIEBydW5zcGlyZWQgaGFzIGZvdW5kIGl0IGludmFsdWFibGUgd2hlbiBkZWJ1Z2dpbmcgcmVsYXRpb25zaGlwIHRlc3RzCiAgICAgICAgICB0byBkZXRlcm1pbmUgd2hldGhlciAoYW5kIHdoeSBpZiBzbykgd2UgYXJlIGluIGFuIGluY29ycmVjdCBzdGF0ZS4KICAgICAgICAgdHJ1ZSB3aGVuCiAgICAgICAgICA9PiB3ZSByZWNlaXZlIGEgcHVzaCB3aXRoIGV4cGxpY2l0IGVtcHR5IChgW11gIG9yIGBudWxsYCkKICAgICAgICAgID0+IHdlIGhhdmUgcmVjZWl2ZWQgbm8gc2lnbmFsIGFib3V0IHdoYXQgZGF0YSBiZWxvbmdzIGluIHRoaXMgcmVsYXRpb25zaGlwCiAgICAgICAgICA9PiBvbiBpbml0aWFsIGNyZWF0ZSAoYXMgbm8gc2lnbmFsIGlzIGtub3duIHlldCkKICAgICAgICAgZmFsc2UgYXQgYWxsIG90aGVyIHRpbWVzCiAgICAgICAqLwoKICAgICAgdGhpcy5yZWxhdGlvbnNoaXBJc0VtcHR5ID0gdHJ1ZTsKICAgICAgLyoKICAgICAgICBGbGFnIGRlZiBoZXJlIGZvciByZWZlcmVuY2UsIGRlZmluZWQgYXMgZ2V0dGVyIGluIGhhcy1tYW55LmpzIC8gYmVsb25ncy10by5qcwogICAgICAgICB0cnVlIHdoZW4KICAgICAgICAgID0+IGhhc0FueVJlbGF0aW9uc2hpcERhdGEgaXMgdHJ1ZQogICAgICAgICAgQU5ECiAgICAgICAgICA9PiBtZW1iZXJzIChOT1QgY2Fub25pY2FsTWVtYmVycykgQGVhY2ggIWlzRW1wdHkKICAgICAgICAgVE9ETywgY29uc2lkZXIgY2hhbmdpbmcgdGhlIGNvbmRpdGlvbmFsIGhlcmUgZnJvbSAhaXNFbXB0eSB0byAhaGlkZGVuRnJvbVJlY29yZEFycmF5cwogICAgICAqLwogICAgICAvLyBUT0RPIGRvIHdlIHdhbnQgdGhpcyBhbnltb3JlPyBTZWVtcyBzb21ld2hhdCB1c2VmdWwKICAgICAgLy8gICBlc3BlY2lhbGx5IGlmIHdlIHJlbmFtZSB0byBgaGFzVXBkYXRlZExpbmtgCiAgICAgIC8vICAgd2hpY2ggd291bGQgdGVsbCB1cyBzbGlnaHRseSBtb3JlIGFib3V0IHdoeSB0aGUKICAgICAgLy8gICByZWxhdGlvbnNoaXAgaXMgc3RhbGUKICAgICAgLy8gdGhpcy51cGRhdGVkTGluayA9IGZhbHNlOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBSZWxhdGlvbnNoaXAucHJvdG90eXBlOwoKICAgIF9wcm90by5faW52ZXJzZUlzQXN5bmMgPSBmdW5jdGlvbiBfaW52ZXJzZUlzQXN5bmMoKSB7CiAgICAgIHJldHVybiAhIXRoaXMuaW52ZXJzZUlzQXN5bmM7CiAgICB9OwoKICAgIF9wcm90by5faW52ZXJzZUlzU3luYyA9IGZ1bmN0aW9uIF9pbnZlcnNlSXNTeW5jKCkgewogICAgICByZXR1cm4gISEodGhpcy5pbnZlcnNlS2V5ICYmICF0aGlzLmludmVyc2VJc0FzeW5jKTsKICAgIH07CgogICAgX3Byb3RvLl9oYXNTdXBwb3J0Rm9ySW1wbGljaXRSZWxhdGlvbnNoaXBzID0gZnVuY3Rpb24gX2hhc1N1cHBvcnRGb3JJbXBsaWNpdFJlbGF0aW9uc2hpcHMocmVjb3JkRGF0YSkgewogICAgICByZXR1cm4gcmVjb3JkRGF0YS5faW1wbGljaXRSZWxhdGlvbnNoaXBzICE9PSB1bmRlZmluZWQgJiYgcmVjb3JkRGF0YS5faW1wbGljaXRSZWxhdGlvbnNoaXBzICE9PSBudWxsOwogICAgfTsKCiAgICBfcHJvdG8uX2hhc1N1cHBvcnRGb3JSZWxhdGlvbnNoaXBzID0gZnVuY3Rpb24gX2hhc1N1cHBvcnRGb3JSZWxhdGlvbnNoaXBzKHJlY29yZERhdGEpIHsKICAgICAgcmV0dXJuIHJlY29yZERhdGEuX3JlbGF0aW9uc2hpcHMgIT09IHVuZGVmaW5lZCAmJiByZWNvcmREYXRhLl9yZWxhdGlvbnNoaXBzICE9PSBudWxsOwogICAgfTsKCiAgICBfcHJvdG8ucmVjb3JkRGF0YURpZERlbWF0ZXJpYWxpemUgPSBmdW5jdGlvbiByZWNvcmREYXRhRGlkRGVtYXRlcmlhbGl6ZSgpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHZhciBpbnZlcnNlS2V5ID0gdGhpcy5pbnZlcnNlS2V5OwoKICAgICAgaWYgKCFpbnZlcnNlS2V5KSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIHdlIGFjdHVhbGx5IHdhbnQgYSB1bmlvbiBvZiBtZW1iZXJzIGFuZCBjYW5vbmljYWxNZW1iZXJzCiAgICAgIC8vIHRoZXkgc2hvdWxkIGJlIGRpc2pvaW50IGJ1dCBjdXJyZW50bHkgYXJlIG5vdCBkdWUgdG8gYSBidWcKCgogICAgICB0aGlzLmZvckFsbE1lbWJlcnMoZnVuY3Rpb24gKGludmVyc2VSZWNvcmREYXRhKSB7CiAgICAgICAgaWYgKCFfdGhpcy5faGFzU3VwcG9ydEZvclJlbGF0aW9uc2hpcHMoaW52ZXJzZVJlY29yZERhdGEpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICB2YXIgcmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwU3RhdGVGb3IoaW52ZXJzZVJlY29yZERhdGEsIGludmVyc2VLZXkpOwoKICAgICAgICB2YXIgYmVsb25nc1RvUmVsYXRpb25zaGlwID0gaW52ZXJzZVJlY29yZERhdGEuZ2V0QmVsb25nc1RvKGludmVyc2VLZXkpLl9yZWxhdGlvbnNoaXA7IC8vIEZvciBjYW5vbmljYWwgbWVtYmVycywgaXQgaXMgcG9zc2libGUgdGhhdCBpbnZlcnNlUmVjb3JkRGF0YSBoYXMgYWxyZWFkeSBiZWVuIGFzc29jaWF0ZWQgdG8KICAgICAgICAvLyB0byBhbm90aGVyIHJlY29yZC4gRm9yIHN1Y2ggY2FzZXMsIGRvIG5vdCBkZW1hdGVyaWFsaXplIHRoZSBpbnZlcnNlUmVjb3JkRGF0YQoKCiAgICAgICAgaWYgKCFiZWxvbmdzVG9SZWxhdGlvbnNoaXAgfHwgIWJlbG9uZ3NUb1JlbGF0aW9uc2hpcC5pbnZlcnNlUmVjb3JkRGF0YSB8fCBfdGhpcy5yZWNvcmREYXRhID09PSBiZWxvbmdzVG9SZWxhdGlvbnNoaXAuaW52ZXJzZVJlY29yZERhdGEpIHsKICAgICAgICAgIHJlbGF0aW9uc2hpcC5pbnZlcnNlRGlkRGVtYXRlcmlhbGl6ZShfdGhpcy5yZWNvcmREYXRhKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8uZm9yQWxsTWVtYmVycyA9IGZ1bmN0aW9uIGZvckFsbE1lbWJlcnMoY2FsbGJhY2spIHsKICAgICAgdmFyIHNlZW4gPSBPYmplY3QuY3JlYXRlKG51bGwpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLm1lbWJlcnMubGlzdC5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBpbnZlcnNlSW50ZXJuYWxNb2RlbCA9IHRoaXMubWVtYmVycy5saXN0W2ldOwogICAgICAgIHZhciBpZCA9IEVtYmVyLmd1aWRGb3IoaW52ZXJzZUludGVybmFsTW9kZWwpOwoKICAgICAgICBpZiAoIXNlZW5baWRdKSB7CiAgICAgICAgICBzZWVuW2lkXSA9IHRydWU7CiAgICAgICAgICBjYWxsYmFjayhpbnZlcnNlSW50ZXJuYWxNb2RlbCk7CiAgICAgICAgfQogICAgICB9CgogICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgdGhpcy5jYW5vbmljYWxNZW1iZXJzLmxpc3QubGVuZ3RoOyBfaSsrKSB7CiAgICAgICAgdmFyIF9pbnZlcnNlSW50ZXJuYWxNb2RlbCA9IHRoaXMuY2Fub25pY2FsTWVtYmVycy5saXN0W19pXTsKCiAgICAgICAgdmFyIF9pZCA9IEVtYmVyLmd1aWRGb3IoX2ludmVyc2VJbnRlcm5hbE1vZGVsKTsKCiAgICAgICAgaWYgKCFzZWVuW19pZF0pIHsKICAgICAgICAgIHNlZW5bX2lkXSA9IHRydWU7CiAgICAgICAgICBjYWxsYmFjayhfaW52ZXJzZUludGVybmFsTW9kZWwpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uaW52ZXJzZURpZERlbWF0ZXJpYWxpemUgPSBmdW5jdGlvbiBpbnZlcnNlRGlkRGVtYXRlcmlhbGl6ZShpbnZlcnNlUmVjb3JkRGF0YSkgewogICAgICBpZiAoIXRoaXMuaXNBc3luYyB8fCBpbnZlcnNlUmVjb3JkRGF0YSAmJiBpbnZlcnNlUmVjb3JkRGF0YS5pc05ldygpKSB7CiAgICAgICAgLy8gdW5sb2FkaW5nIGludmVyc2Ugb2YgYSBzeW5jIHJlbGF0aW9uc2hpcCBpcyB0cmVhdGVkIGFzIGEgY2xpZW50LXNpZGUKICAgICAgICAvLyBkZWxldGUsIHNvIGFjdHVhbGx5IHJlbW92ZSB0aGUgbW9kZWxzIGRvbid0IG1lcmVseSBpbnZhbGlkYXRlIHRoZSBjcAogICAgICAgIC8vIGNhY2hlLgogICAgICAgIC8vIGlmIHRoZSByZWNvcmQgYmVpbmcgdW5sb2FkZWQgb25seSBleGlzdHMgb24gdGhlIGNsaWVudCwgd2Ugc2ltaWxhcmx5CiAgICAgICAgLy8gdHJlYXQgaXQgYXMgYSBjbGllbnQgc2lkZSBkZWxldGUKICAgICAgICB0aGlzLnJlbW92ZVJlY29yZERhdGFGcm9tT3duKGludmVyc2VSZWNvcmREYXRhKTsKICAgICAgICB0aGlzLnJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tT3duKGludmVyc2VSZWNvcmREYXRhKTsKICAgICAgICB0aGlzLnNldFJlbGF0aW9uc2hpcElzRW1wdHkodHJ1ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5zZXRIYXNEZW1hdGVyaWFsaXplZEludmVyc2UodHJ1ZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnVwZGF0ZU1ldGEgPSBmdW5jdGlvbiB1cGRhdGVNZXRhKG1ldGEpIHsKICAgICAgdGhpcy5tZXRhID0gbWV0YTsKICAgIH07CgogICAgX3Byb3RvLmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7CiAgICAgIHZhciBtZW1iZXJzID0gdGhpcy5tZW1iZXJzLmxpc3Q7CgogICAgICB3aGlsZSAobWVtYmVycy5sZW5ndGggPiAwKSB7CiAgICAgICAgdmFyIG1lbWJlciA9IG1lbWJlcnNbMF07CiAgICAgICAgdGhpcy5yZW1vdmVSZWNvcmREYXRhKG1lbWJlcik7CiAgICAgIH0KCiAgICAgIHZhciBjYW5vbmljYWxNZW1iZXJzID0gdGhpcy5jYW5vbmljYWxNZW1iZXJzLmxpc3Q7CgogICAgICB3aGlsZSAoY2Fub25pY2FsTWVtYmVycy5sZW5ndGggPiAwKSB7CiAgICAgICAgdmFyIF9tZW1iZXIgPSBjYW5vbmljYWxNZW1iZXJzWzBdOwogICAgICAgIHRoaXMucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YShfbWVtYmVyKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ucmVtb3ZlQWxsUmVjb3JkRGF0YXNGcm9tT3duID0gZnVuY3Rpb24gcmVtb3ZlQWxsUmVjb3JkRGF0YXNGcm9tT3duKCkgewogICAgICB0aGlzLnNldFJlbGF0aW9uc2hpcElzU3RhbGUodHJ1ZSk7CiAgICAgIHRoaXMubWVtYmVycy5jbGVhcigpOwogICAgfTsKCiAgICBfcHJvdG8ucmVtb3ZlQWxsQ2Fub25pY2FsUmVjb3JkRGF0YXNGcm9tT3duID0gZnVuY3Rpb24gcmVtb3ZlQWxsQ2Fub25pY2FsUmVjb3JkRGF0YXNGcm9tT3duKCkgewogICAgICB0aGlzLmNhbm9uaWNhbE1lbWJlcnMuY2xlYXIoKTsKICAgICAgdGhpcy5mbHVzaENhbm9uaWNhbExhdGVyKCk7CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVSZWNvcmREYXRhcyA9IGZ1bmN0aW9uIHJlbW92ZVJlY29yZERhdGFzKHJlY29yZERhdGFzKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgcmVjb3JkRGF0YXMuZm9yRWFjaChmdW5jdGlvbiAocmVjb3JkRGF0YSkgewogICAgICAgIHJldHVybiBfdGhpczIucmVtb3ZlUmVjb3JkRGF0YShyZWNvcmREYXRhKTsKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5hZGRSZWNvcmREYXRhcyA9IGZ1bmN0aW9uIGFkZFJlY29yZERhdGFzKHJlY29yZERhdGFzLCBpZHgpIHsKICAgICAgdmFyIF90aGlzMyA9IHRoaXM7CgogICAgICByZWNvcmREYXRhcy5mb3JFYWNoKGZ1bmN0aW9uIChyZWNvcmREYXRhKSB7CiAgICAgICAgX3RoaXMzLmFkZFJlY29yZERhdGEocmVjb3JkRGF0YSwgaWR4KTsKCiAgICAgICAgaWYgKGlkeCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBpZHgrKzsKICAgICAgICB9CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8uYWRkQ2Fub25pY2FsUmVjb3JkRGF0YXMgPSBmdW5jdGlvbiBhZGRDYW5vbmljYWxSZWNvcmREYXRhcyhyZWNvcmREYXRhcywgaWR4KSB7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVjb3JkRGF0YXMubGVuZ3RoOyBpKyspIHsKICAgICAgICBpZiAoaWR4ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHRoaXMuYWRkQ2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhc1tpXSwgaSArIGlkeCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuYWRkQ2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhc1tpXSk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5hZGRDYW5vbmljYWxSZWNvcmREYXRhID0gZnVuY3Rpb24gYWRkQ2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhLCBpZHgpIHsKICAgICAgaWYgKCF0aGlzLmNhbm9uaWNhbE1lbWJlcnMuaGFzKHJlY29yZERhdGEpKSB7CiAgICAgICAgdGhpcy5jYW5vbmljYWxNZW1iZXJzLmFkZChyZWNvcmREYXRhKTsKICAgICAgICB0aGlzLnNldHVwSW52ZXJzZVJlbGF0aW9uc2hpcChyZWNvcmREYXRhKTsKICAgICAgfQoKICAgICAgdGhpcy5mbHVzaENhbm9uaWNhbExhdGVyKCk7CiAgICAgIHRoaXMuc2V0SGFzQW55UmVsYXRpb25zaGlwRGF0YSh0cnVlKTsKICAgIH07CgogICAgX3Byb3RvLnNldHVwSW52ZXJzZVJlbGF0aW9uc2hpcCA9IGZ1bmN0aW9uIHNldHVwSW52ZXJzZVJlbGF0aW9uc2hpcChyZWNvcmREYXRhKSB7CiAgICAgIGlmICh0aGlzLmludmVyc2VLZXkpIHsKICAgICAgICBpZiAoIXRoaXMuX2hhc1N1cHBvcnRGb3JSZWxhdGlvbnNoaXBzKHJlY29yZERhdGEpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICB2YXIgcmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwU3RhdGVGb3IocmVjb3JkRGF0YSwgdGhpcy5pbnZlcnNlS2V5KTsgLy8gaWYgd2UgaGF2ZSBvbmx5IGp1c3QgaW5pdGlhbGl6ZWQgdGhlIGludmVyc2UgcmVsYXRpb25zaGlwLCB0aGVuIGl0CiAgICAgICAgLy8gYWxyZWFkeSBoYXMgdGhpcy5yZWNvcmREYXRhIGluIGl0cyBjYW5vbmljYWxNZW1iZXJzLCBzbyBza2lwIHRoZQogICAgICAgIC8vIHVubmVjZXNzYXJ5IHdvcmsuICBUaGUgZXhjZXB0aW9uIHRvIHRoaXMgaXMgcG9seW1vcnBoaWMKICAgICAgICAvLyByZWxhdGlvbnNoaXBzIHdob3NlIG1lbWJlcnMgYXJlIGRldGVybWluZWQgYnkgdGhlaXIgaW52ZXJzZSwgYXMgdGhvc2UKICAgICAgICAvLyByZWxhdGlvbnNoaXBzIGNhbm5vdCBlZmZpY2llbnRseSBmaW5kIHRoZWlyIGludmVyc2UgcGF5bG9hZHMuCgogICAgICAgIHJlbGF0aW9uc2hpcC5hZGRDYW5vbmljYWxSZWNvcmREYXRhKHRoaXMucmVjb3JkRGF0YSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaWYgKCF0aGlzLl9oYXNTdXBwb3J0Rm9ySW1wbGljaXRSZWxhdGlvbnNoaXBzKHJlY29yZERhdGEpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICB2YXIgcmVsYXRpb25zaGlwcyA9IHJlY29yZERhdGEuX2ltcGxpY2l0UmVsYXRpb25zaGlwczsKICAgICAgICB2YXIgX3JlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcHNbdGhpcy5pbnZlcnNlS2V5Rm9ySW1wbGljaXRdOwoKICAgICAgICBpZiAoIV9yZWxhdGlvbnNoaXApIHsKICAgICAgICAgIF9yZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXBzW3RoaXMuaW52ZXJzZUtleUZvckltcGxpY2l0XSA9IG5ldyBSZWxhdGlvbnNoaXAodGhpcy5zdG9yZSwgdGhpcy5rZXksIHsKICAgICAgICAgICAgb3B0aW9uczogewogICAgICAgICAgICAgIGFzeW5jOiB0aGlzLmlzQXN5bmMKICAgICAgICAgICAgfQogICAgICAgICAgfSwgcmVjb3JkRGF0YSk7CiAgICAgICAgfQoKICAgICAgICBfcmVsYXRpb25zaGlwLmFkZENhbm9uaWNhbFJlY29yZERhdGEodGhpcy5yZWNvcmREYXRhKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YXMgPSBmdW5jdGlvbiByZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhcyhyZWNvcmREYXRhcywgaWR4KSB7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVjb3JkRGF0YXMubGVuZ3RoOyBpKyspIHsKICAgICAgICBpZiAoaWR4ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHRoaXMucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhc1tpXSwgaSArIGlkeCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhc1tpXSk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhID0gZnVuY3Rpb24gcmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhLCBpZHgpIHsKICAgICAgaWYgKHRoaXMuY2Fub25pY2FsTWVtYmVycy5oYXMocmVjb3JkRGF0YSkpIHsKICAgICAgICB0aGlzLnJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tT3duKHJlY29yZERhdGEpOwoKICAgICAgICBpZiAodGhpcy5pbnZlcnNlS2V5KSB7CiAgICAgICAgICB0aGlzLnJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tSW52ZXJzZShyZWNvcmREYXRhKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKHRoaXMuX2hhc1N1cHBvcnRGb3JJbXBsaWNpdFJlbGF0aW9uc2hpcHMocmVjb3JkRGF0YSkgJiYgcmVjb3JkRGF0YS5faW1wbGljaXRSZWxhdGlvbnNoaXBzW3RoaXMuaW52ZXJzZUtleUZvckltcGxpY2l0XSkgewogICAgICAgICAgICByZWNvcmREYXRhLl9pbXBsaWNpdFJlbGF0aW9uc2hpcHNbdGhpcy5pbnZlcnNlS2V5Rm9ySW1wbGljaXRdLnJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGEodGhpcy5yZWNvcmREYXRhKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHRoaXMuZmx1c2hDYW5vbmljYWxMYXRlcigpOwogICAgfTsKCiAgICBfcHJvdG8uYWRkUmVjb3JkRGF0YSA9IGZ1bmN0aW9uIGFkZFJlY29yZERhdGEocmVjb3JkRGF0YSwgaWR4KSB7CiAgICAgIGlmICghdGhpcy5tZW1iZXJzLmhhcyhyZWNvcmREYXRhKSkgewogICAgICAgIHRoaXMubWVtYmVycy5hZGRXaXRoSW5kZXgocmVjb3JkRGF0YSwgaWR4KTsKICAgICAgICB0aGlzLm5vdGlmeVJlY29yZFJlbGF0aW9uc2hpcEFkZGVkKHJlY29yZERhdGEsIGlkeCk7CgogICAgICAgIGlmICh0aGlzLl9oYXNTdXBwb3J0Rm9yUmVsYXRpb25zaGlwcyhyZWNvcmREYXRhKSAmJiB0aGlzLmludmVyc2VLZXkpIHsKICAgICAgICAgIHJlbGF0aW9uc2hpcFN0YXRlRm9yKHJlY29yZERhdGEsIHRoaXMuaW52ZXJzZUtleSkuYWRkUmVjb3JkRGF0YSh0aGlzLnJlY29yZERhdGEpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAodGhpcy5faGFzU3VwcG9ydEZvckltcGxpY2l0UmVsYXRpb25zaGlwcyhyZWNvcmREYXRhKSkgewogICAgICAgICAgICBpZiAoIXJlY29yZERhdGEuX2ltcGxpY2l0UmVsYXRpb25zaGlwc1t0aGlzLmludmVyc2VLZXlGb3JJbXBsaWNpdF0pIHsKICAgICAgICAgICAgICByZWNvcmREYXRhLl9pbXBsaWNpdFJlbGF0aW9uc2hpcHNbdGhpcy5pbnZlcnNlS2V5Rm9ySW1wbGljaXRdID0gbmV3IFJlbGF0aW9uc2hpcCh0aGlzLnN0b3JlLCB0aGlzLmtleSwgewogICAgICAgICAgICAgICAgb3B0aW9uczogewogICAgICAgICAgICAgICAgICBhc3luYzogdGhpcy5pc0FzeW5jCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSwgcmVjb3JkRGF0YSwgdGhpcy5pc0FzeW5jKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgcmVjb3JkRGF0YS5faW1wbGljaXRSZWxhdGlvbnNoaXBzW3RoaXMuaW52ZXJzZUtleUZvckltcGxpY2l0XS5hZGRSZWNvcmREYXRhKHRoaXMucmVjb3JkRGF0YSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICB0aGlzLnNldEhhc0FueVJlbGF0aW9uc2hpcERhdGEodHJ1ZSk7CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVSZWNvcmREYXRhID0gZnVuY3Rpb24gcmVtb3ZlUmVjb3JkRGF0YShyZWNvcmREYXRhKSB7CiAgICAgIGlmICh0aGlzLm1lbWJlcnMuaGFzKHJlY29yZERhdGEpKSB7CiAgICAgICAgdGhpcy5yZW1vdmVSZWNvcmREYXRhRnJvbU93bihyZWNvcmREYXRhKTsKCiAgICAgICAgaWYgKHRoaXMuaW52ZXJzZUtleSkgewogICAgICAgICAgdGhpcy5yZW1vdmVSZWNvcmREYXRhRnJvbUludmVyc2UocmVjb3JkRGF0YSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmICh0aGlzLl9oYXNTdXBwb3J0Rm9ySW1wbGljaXRSZWxhdGlvbnNoaXBzKHJlY29yZERhdGEpICYmIHJlY29yZERhdGEuX2ltcGxpY2l0UmVsYXRpb25zaGlwc1t0aGlzLmludmVyc2VLZXlGb3JJbXBsaWNpdF0pIHsKICAgICAgICAgICAgcmVjb3JkRGF0YS5faW1wbGljaXRSZWxhdGlvbnNoaXBzW3RoaXMuaW52ZXJzZUtleUZvckltcGxpY2l0XS5yZW1vdmVSZWNvcmREYXRhKHRoaXMucmVjb3JkRGF0YSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVSZWNvcmREYXRhRnJvbUludmVyc2UgPSBmdW5jdGlvbiByZW1vdmVSZWNvcmREYXRhRnJvbUludmVyc2UocmVjb3JkRGF0YSkgewogICAgICBpZiAoIXRoaXMuX2hhc1N1cHBvcnRGb3JSZWxhdGlvbnNoaXBzKHJlY29yZERhdGEpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAodGhpcy5pbnZlcnNlS2V5KSB7CiAgICAgICAgdmFyIGludmVyc2VSZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXBTdGF0ZUZvcihyZWNvcmREYXRhLCB0aGlzLmludmVyc2VLZXkpOyAvL05lZWQgdG8gY2hlY2sgZm9yIGV4aXN0ZW5jZSwgYXMgdGhlIHJlY29yZCBtaWdodCB1bmxvYWRpbmcgYXQgdGhlIG1vbWVudAoKICAgICAgICBpZiAoaW52ZXJzZVJlbGF0aW9uc2hpcCkgewogICAgICAgICAgaW52ZXJzZVJlbGF0aW9uc2hpcC5yZW1vdmVSZWNvcmREYXRhRnJvbU93bih0aGlzLnJlY29yZERhdGEpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ucmVtb3ZlUmVjb3JkRGF0YUZyb21Pd24gPSBmdW5jdGlvbiByZW1vdmVSZWNvcmREYXRhRnJvbU93bihyZWNvcmREYXRhLCBpZHgpIHsKICAgICAgdGhpcy5tZW1iZXJzLmRlbGV0ZShyZWNvcmREYXRhKTsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tSW52ZXJzZSA9IGZ1bmN0aW9uIHJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tSW52ZXJzZShyZWNvcmREYXRhKSB7CiAgICAgIGlmICghdGhpcy5faGFzU3VwcG9ydEZvclJlbGF0aW9uc2hpcHMocmVjb3JkRGF0YSkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmludmVyc2VLZXkpIHsKICAgICAgICB2YXIgaW52ZXJzZVJlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcFN0YXRlRm9yKHJlY29yZERhdGEsIHRoaXMuaW52ZXJzZUtleSk7IC8vTmVlZCB0byBjaGVjayBmb3IgZXhpc3RlbmNlLCBhcyB0aGUgcmVjb3JkIG1pZ2h0IHVubG9hZGluZyBhdCB0aGUgbW9tZW50CgogICAgICAgIGlmIChpbnZlcnNlUmVsYXRpb25zaGlwKSB7CiAgICAgICAgICBpbnZlcnNlUmVsYXRpb25zaGlwLnJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tT3duKHRoaXMucmVjb3JkRGF0YSk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhRnJvbU93biA9IGZ1bmN0aW9uIHJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tT3duKHJlY29yZERhdGEsIGlkeCkgewogICAgICB0aGlzLmNhbm9uaWNhbE1lbWJlcnMuZGVsZXRlKHJlY29yZERhdGEpOwogICAgICB0aGlzLmZsdXNoQ2Fub25pY2FsTGF0ZXIoKTsKICAgIH0KICAgIC8qCiAgICAgIENhbGwgdGhpcyBtZXRob2Qgb25jZSBhIHJlY29yZCBkZWxldGlvbiBoYXMgYmVlbiBwZXJzaXN0ZWQKICAgICAgdG8gcHVyZ2UgaXQgZnJvbSBCT1RIIGN1cnJlbnQgYW5kIGNhbm9uaWNhbCBzdGF0ZSBvZiBhbGwKICAgICAgcmVsYXRpb25zaGlwcy4KICAgICAgIEBtZXRob2QgcmVtb3ZlQ29tcGxldGVseUZyb21JbnZlcnNlCiAgICAgIEBwcml2YXRlCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVtb3ZlQ29tcGxldGVseUZyb21JbnZlcnNlID0gZnVuY3Rpb24gcmVtb3ZlQ29tcGxldGVseUZyb21JbnZlcnNlKCkgewogICAgICB2YXIgX3RoaXM0ID0gdGhpczsKCiAgICAgIGlmICghdGhpcy5pbnZlcnNlS2V5ICYmICF0aGlzLmludmVyc2VLZXlGb3JJbXBsaWNpdCkgewogICAgICAgIHJldHVybjsKICAgICAgfSAvLyB3ZSBhY3R1YWxseSB3YW50IGEgdW5pb24gb2YgbWVtYmVycyBhbmQgY2Fub25pY2FsTWVtYmVycwogICAgICAvLyB0aGV5IHNob3VsZCBiZSBkaXNqb2ludCBidXQgY3VycmVudGx5IGFyZSBub3QgZHVlIHRvIGEgYnVnCgoKICAgICAgdmFyIHNlZW4gPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB2YXIgcmVjb3JkRGF0YSA9IHRoaXMucmVjb3JkRGF0YTsKICAgICAgdmFyIHVubG9hZDsKCiAgICAgIGlmICh0aGlzLmludmVyc2VLZXkpIHsKICAgICAgICB1bmxvYWQgPSBmdW5jdGlvbiB1bmxvYWQoaW52ZXJzZVJlY29yZERhdGEpIHsKICAgICAgICAgIHZhciBpZCA9IEVtYmVyLmd1aWRGb3IoaW52ZXJzZVJlY29yZERhdGEpOwoKICAgICAgICAgIGlmIChfdGhpczQuX2hhc1N1cHBvcnRGb3JSZWxhdGlvbnNoaXBzKGludmVyc2VSZWNvcmREYXRhKSAmJiBzZWVuW2lkXSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGlmIChfdGhpczQuaW52ZXJzZUtleSkgewogICAgICAgICAgICAgIHZhciByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXBTdGF0ZUZvcihpbnZlcnNlUmVjb3JkRGF0YSwgX3RoaXM0LmludmVyc2VLZXkpOwogICAgICAgICAgICAgIHJlbGF0aW9uc2hpcC5yZW1vdmVDb21wbGV0ZWx5RnJvbU93bihyZWNvcmREYXRhKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgc2VlbltpZF0gPSB0cnVlOwogICAgICAgICAgfQogICAgICAgIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdW5sb2FkID0gZnVuY3Rpb24gdW5sb2FkKGludmVyc2VSZWNvcmREYXRhKSB7CiAgICAgICAgICB2YXIgaWQgPSBFbWJlci5ndWlkRm9yKGludmVyc2VSZWNvcmREYXRhKTsKCiAgICAgICAgICBpZiAoX3RoaXM0Ll9oYXNTdXBwb3J0Rm9ySW1wbGljaXRSZWxhdGlvbnNoaXBzKGludmVyc2VSZWNvcmREYXRhKSAmJiBzZWVuW2lkXSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHZhciByZWxhdGlvbnNoaXAgPSBpbXBsaWNpdFJlbGF0aW9uc2hpcFN0YXRlRm9yKGludmVyc2VSZWNvcmREYXRhLCBfdGhpczQuaW52ZXJzZUtleUZvckltcGxpY2l0KTsKICAgICAgICAgICAgcmVsYXRpb25zaGlwLnJlbW92ZUNvbXBsZXRlbHlGcm9tT3duKHJlY29yZERhdGEpOwogICAgICAgICAgICBzZWVuW2lkXSA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgfQoKICAgICAgdGhpcy5tZW1iZXJzLmZvckVhY2godW5sb2FkKTsKICAgICAgdGhpcy5jYW5vbmljYWxNZW1iZXJzLmZvckVhY2godW5sb2FkKTsKCiAgICAgIGlmICghdGhpcy5pc0FzeW5jKSB7CiAgICAgICAgdGhpcy5jbGVhcigpOwogICAgICB9CiAgICB9CiAgICAvKgogICAgICBSZW1vdmVzIHRoZSBnaXZlbiBSZWNvcmREYXRhIGZyb20gQk9USCBjYW5vbmljYWwgQU5EIGN1cnJlbnQgc3RhdGUuCiAgICAgICBUaGlzIG1ldGhvZCBpcyB1c2VmdWwgd2hlbiBlaXRoZXIgYSBkZWxldGlvbiBvciBhIHJvbGxiYWNrIG9uIGEgbmV3IHJlY29yZAogICAgICBuZWVkcyB0byBlbnRpcmVseSBwdXJnZSBpdHNlbGYgZnJvbSBhbiBpbnZlcnNlIHJlbGF0aW9uc2hpcC4KICAgICAqLwogICAgOwoKICAgIF9wcm90by5yZW1vdmVDb21wbGV0ZWx5RnJvbU93biA9IGZ1bmN0aW9uIHJlbW92ZUNvbXBsZXRlbHlGcm9tT3duKHJlY29yZERhdGEpIHsKICAgICAgdGhpcy5jYW5vbmljYWxNZW1iZXJzLmRlbGV0ZShyZWNvcmREYXRhKTsKICAgICAgdGhpcy5tZW1iZXJzLmRlbGV0ZShyZWNvcmREYXRhKTsKICAgIH07CgogICAgX3Byb3RvLmZsdXNoQ2Fub25pY2FsID0gZnVuY3Rpb24gZmx1c2hDYW5vbmljYWwoKSB7CiAgICAgIHZhciBsaXN0ID0gdGhpcy5tZW1iZXJzLmxpc3Q7CiAgICAgIHRoaXMud2lsbFN5bmMgPSBmYWxzZTsgLy9hIGhhY2sgZm9yIG5vdCByZW1vdmluZyBuZXcgUmVjb3JkRGF0YXMKICAgICAgLy9UT0RPIHJlbW92ZSBvbmNlIHdlIGhhdmUgcHJvcGVyIGRpZmZpbmcKCiAgICAgIHZhciBuZXdSZWNvcmREYXRhcyA9IFtdOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgLy8gVE9ETyBJZ29yIGRlYWwgd2l0aCB0aGlzCiAgICAgICAgaWYgKGxpc3RbaV0uaXNOZXcoKSkgewogICAgICAgICAgbmV3UmVjb3JkRGF0YXMucHVzaChsaXN0W2ldKTsKICAgICAgICB9CiAgICAgIH0gLy9UT0RPKElnb3IpIG1ha2UgdGhpcyBsZXNzIGFieXNtYWxseSBzbG93CgoKICAgICAgdGhpcy5tZW1iZXJzID0gdGhpcy5jYW5vbmljYWxNZW1iZXJzLmNvcHkoKTsKCiAgICAgIGZvciAodmFyIF9pMiA9IDA7IF9pMiA8IG5ld1JlY29yZERhdGFzLmxlbmd0aDsgX2kyKyspIHsKICAgICAgICB0aGlzLm1lbWJlcnMuYWRkKG5ld1JlY29yZERhdGFzW19pMl0pOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5mbHVzaENhbm9uaWNhbExhdGVyID0gZnVuY3Rpb24gZmx1c2hDYW5vbmljYWxMYXRlcigpIHsKICAgICAgaWYgKHRoaXMud2lsbFN5bmMpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMud2lsbFN5bmMgPSB0cnVlOyAvLyBSZWFjaGluZyBiYWNrIGludG8gdGhlIHN0b3JlIHRvIHVzZSBFRCdzIHJ1bmxvb3AKCiAgICAgIHRoaXMuc3RvcmUuX3VwZGF0ZVJlbGF0aW9uc2hpcFN0YXRlKHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG8udXBkYXRlTGlua3MgPSBmdW5jdGlvbiB1cGRhdGVMaW5rcyhsaW5rcykgewogICAgICB0aGlzLmxpbmtzID0gbGlua3M7CiAgICB9OwoKICAgIF9wcm90by51cGRhdGVSZWNvcmREYXRhc0Zyb21BZGFwdGVyID0gZnVuY3Rpb24gdXBkYXRlUmVjb3JkRGF0YXNGcm9tQWRhcHRlcihyZWNvcmREYXRhcykgewogICAgICB0aGlzLnNldEhhc0FueVJlbGF0aW9uc2hpcERhdGEodHJ1ZSk7IC8vVE9ETyhJZ29yKSBtb3ZlIHRoaXMgdG8gYSBwcm9wZXIgcGxhY2UKICAgICAgLy9UT0RPIE9uY2Ugd2UgaGF2ZSBhZGFwdGVyIHN1cHBvcnQsIHdlIG5lZWQgdG8gaGFuZGxlIHVwZGF0ZWQgYW5kIGNhbm9uaWNhbCBjaGFuZ2VzCgogICAgICB0aGlzLmNvbXB1dGVDaGFuZ2VzKHJlY29yZERhdGFzKTsKICAgIH07CgogICAgX3Byb3RvLmNvbXB1dGVDaGFuZ2VzID0gZnVuY3Rpb24gY29tcHV0ZUNoYW5nZXMocmVjb3JkRGF0YXMpIHt9OwoKICAgIF9wcm90by5ub3RpZnlSZWNvcmRSZWxhdGlvbnNoaXBBZGRlZCA9IGZ1bmN0aW9uIG5vdGlmeVJlY29yZFJlbGF0aW9uc2hpcEFkZGVkKHJlY29yZERhdGEsIGlkeHMpIHt9OwoKICAgIF9wcm90by5zZXRIYXNBbnlSZWxhdGlvbnNoaXBEYXRhID0gZnVuY3Rpb24gc2V0SGFzQW55UmVsYXRpb25zaGlwRGF0YSh2YWx1ZSkgewogICAgICB0aGlzLmhhc0FueVJlbGF0aW9uc2hpcERhdGEgPSB2YWx1ZTsKICAgIH07CgogICAgX3Byb3RvLnNldEhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSA9IGZ1bmN0aW9uIHNldEhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSh2YWx1ZSkgewogICAgICB0aGlzLmhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSA9IHZhbHVlOwogICAgfTsKCiAgICBfcHJvdG8uc2V0UmVsYXRpb25zaGlwSXNTdGFsZSA9IGZ1bmN0aW9uIHNldFJlbGF0aW9uc2hpcElzU3RhbGUodmFsdWUpIHsKICAgICAgdGhpcy5yZWxhdGlvbnNoaXBJc1N0YWxlID0gdmFsdWU7CiAgICB9OwoKICAgIF9wcm90by5zZXRSZWxhdGlvbnNoaXBJc0VtcHR5ID0gZnVuY3Rpb24gc2V0UmVsYXRpb25zaGlwSXNFbXB0eSh2YWx1ZSkgewogICAgICB0aGlzLnJlbGF0aW9uc2hpcElzRW1wdHkgPSB2YWx1ZTsKICAgIH07CgogICAgX3Byb3RvLnNldFNob3VsZEZvcmNlUmVsb2FkID0gZnVuY3Rpb24gc2V0U2hvdWxkRm9yY2VSZWxvYWQodmFsdWUpIHsKICAgICAgdGhpcy5zaG91bGRGb3JjZVJlbG9hZCA9IHZhbHVlOwogICAgfTsKCiAgICBfcHJvdG8uc2V0SGFzRmFpbGVkTG9hZEF0dGVtcHQgPSBmdW5jdGlvbiBzZXRIYXNGYWlsZWRMb2FkQXR0ZW1wdCh2YWx1ZSkgewogICAgICB0aGlzLmhhc0ZhaWxlZExvYWRBdHRlbXB0ID0gdmFsdWU7CiAgICB9CiAgICAvKgogICAgIGBwdXNoYCBmb3IgYSByZWxhdGlvbnNoaXAgYWxsb3dzIHRoZSBzdG9yZSB0byBwdXNoIGEgSlNPTiBBUEkgUmVsYXRpb25zaGlwCiAgICAgT2JqZWN0IG9udG8gdGhlIHJlbGF0aW9uc2hpcC4gVGhlIHJlbGF0aW9uc2hpcCB3aWxsIHRoZW4gZXh0cmFjdCBhbmQgc2V0IHRoZQogICAgIG1ldGEsIGRhdGEgYW5kIGxpbmtzIG9mIHRoYXQgcmVsYXRpb25zaGlwLgogICAgICBgcHVzaGAgdXNlIGB1cGRhdGVNZXRhYCwgYHVwZGF0ZURhdGFgIGFuZCBgdXBkYXRlTGlua2AgdG8gdXBkYXRlIHRoZSBzdGF0ZQogICAgIG9mIHRoZSByZWxhdGlvbnNoaXAuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucHVzaCA9IGZ1bmN0aW9uIHB1c2gocGF5bG9hZCwgaW5pdGlhbCkgewogICAgICB2YXIgaGFzUmVsYXRpb25zaGlwRGF0YVByb3BlcnR5ID0gZmFsc2U7CiAgICAgIHZhciBoYXNMaW5rID0gZmFsc2U7CgogICAgICBpZiAocGF5bG9hZC5tZXRhKSB7CiAgICAgICAgdGhpcy51cGRhdGVNZXRhKHBheWxvYWQubWV0YSk7CiAgICAgIH0KCiAgICAgIGlmIChwYXlsb2FkLmRhdGEgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGhhc1JlbGF0aW9uc2hpcERhdGFQcm9wZXJ0eSA9IHRydWU7CiAgICAgICAgdGhpcy51cGRhdGVEYXRhKHBheWxvYWQuZGF0YSwgaW5pdGlhbCk7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5pc0FzeW5jID09PSBmYWxzZSAmJiAhdGhpcy5oYXNBbnlSZWxhdGlvbnNoaXBEYXRhKSB7CiAgICAgICAgaGFzUmVsYXRpb25zaGlwRGF0YVByb3BlcnR5ID0gdHJ1ZTsKICAgICAgICB2YXIgZGF0YSA9IHRoaXMua2luZCA9PT0gJ2hhc01hbnknID8gW10gOiBudWxsOwogICAgICAgIHRoaXMudXBkYXRlRGF0YShkYXRhLCBpbml0aWFsKTsKICAgICAgfQoKICAgICAgaWYgKHBheWxvYWQubGlua3MpIHsKICAgICAgICB2YXIgb3JpZ2luYWxMaW5rcyA9IHRoaXMubGlua3M7CiAgICAgICAgdGhpcy51cGRhdGVMaW5rcyhwYXlsb2FkLmxpbmtzKTsKCiAgICAgICAgaWYgKHBheWxvYWQubGlua3MucmVsYXRlZCkgewogICAgICAgICAgdmFyIHJlbGF0ZWRMaW5rID0gX25vcm1hbGl6ZUxpbmsocGF5bG9hZC5saW5rcy5yZWxhdGVkKTsKCiAgICAgICAgICB2YXIgY3VycmVudExpbmsgPSBvcmlnaW5hbExpbmtzICYmIG9yaWdpbmFsTGlua3MucmVsYXRlZCA/IF9ub3JtYWxpemVMaW5rKG9yaWdpbmFsTGlua3MucmVsYXRlZCkgOiBudWxsOwogICAgICAgICAgdmFyIGN1cnJlbnRMaW5rSHJlZiA9IGN1cnJlbnRMaW5rID8gY3VycmVudExpbmsuaHJlZiA6IG51bGw7CgogICAgICAgICAgaWYgKHJlbGF0ZWRMaW5rICYmIHJlbGF0ZWRMaW5rLmhyZWYgJiYgcmVsYXRlZExpbmsuaHJlZiAhPT0gY3VycmVudExpbmtIcmVmKSB7CiAgICAgICAgICAgIGhhc0xpbmsgPSB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICAvKgogICAgICAgRGF0YSBiZWluZyBwdXNoZWQgaW50byB0aGUgcmVsYXRpb25zaGlwIG1pZ2h0IGNvbnRhaW4gb25seSBkYXRhIG9yIGxpbmtzLAogICAgICAgb3IgYSBjb21iaW5hdGlvbiBvZiBib3RoLgogICAgICAgIElGIGNvbnRhaW5zIG9ubHkgZGF0YQogICAgICAgSUYgY29udGFpbnMgYm90aCBsaW5rcyBhbmQgZGF0YQogICAgICAgIHJlbGF0aW9uc2hpcElzRW1wdHkgLT4gdHJ1ZSBpZiBpcyBlbXB0eSBhcnJheSAoaGFzLW1hbnkpIG9yIGlzIG51bGwgKGJlbG9uZ3MtdG8pCiAgICAgICAgaGFzQW55UmVsYXRpb25zaGlwRGF0YSAtPiB0cnVlCiAgICAgICAgaGFzRGVtYXRlcmlhbGl6ZWRJbnZlcnNlIC0+IGZhbHNlCiAgICAgICAgcmVsYXRpb25zaGlwSXNTdGFsZSAtPiBmYWxzZQogICAgICAgIGFsbEludmVyc2VSZWNvcmRzQXJlTG9hZGVkIC0+IHJ1bi1jaGVjay10by1kZXRlcm1pbmUKICAgICAgICBJRiBjb250YWlucyBvbmx5IGxpbmtzCiAgICAgICAgcmVsYXRpb25zaGlwSXNTdGFsZSAtPiB0cnVlCiAgICAgICAqLwoKCiAgICAgIHRoaXMuc2V0SGFzRmFpbGVkTG9hZEF0dGVtcHQoZmFsc2UpOwoKICAgICAgaWYgKGhhc1JlbGF0aW9uc2hpcERhdGFQcm9wZXJ0eSkgewogICAgICAgIHZhciByZWxhdGlvbnNoaXBJc0VtcHR5ID0gcGF5bG9hZC5kYXRhID09PSBudWxsIHx8IEFycmF5LmlzQXJyYXkocGF5bG9hZC5kYXRhKSAmJiBwYXlsb2FkLmRhdGEubGVuZ3RoID09PSAwOwogICAgICAgIHRoaXMuc2V0SGFzQW55UmVsYXRpb25zaGlwRGF0YSh0cnVlKTsKICAgICAgICB0aGlzLnNldFJlbGF0aW9uc2hpcElzU3RhbGUoZmFsc2UpOwogICAgICAgIHRoaXMuc2V0SGFzRGVtYXRlcmlhbGl6ZWRJbnZlcnNlKGZhbHNlKTsKICAgICAgICB0aGlzLnNldFJlbGF0aW9uc2hpcElzRW1wdHkocmVsYXRpb25zaGlwSXNFbXB0eSk7CiAgICAgIH0gZWxzZSBpZiAoaGFzTGluaykgewogICAgICAgIHRoaXMuc2V0UmVsYXRpb25zaGlwSXNTdGFsZSh0cnVlKTsKCiAgICAgICAgaWYgKCFpbml0aWFsKSB7CiAgICAgICAgICB2YXIgcmVjb3JkRGF0YSA9IHRoaXMucmVjb3JkRGF0YTsKICAgICAgICAgIHZhciBzdG9yZVdyYXBwZXIgPSB0aGlzLnJlY29yZERhdGEuc3RvcmVXcmFwcGVyOwoKICAgICAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICAgICAgc3RvcmVXcmFwcGVyLm5vdGlmeUJlbG9uZ3NUb0NoYW5nZShyZWNvcmREYXRhLm1vZGVsTmFtZSwgcmVjb3JkRGF0YS5pZCwgcmVjb3JkRGF0YS5jbGllbnRJZCwgdGhpcy5rZXkpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RvcmVXcmFwcGVyLm5vdGlmeVByb3BlcnR5Q2hhbmdlKHJlY29yZERhdGEubW9kZWxOYW1lLCByZWNvcmREYXRhLmlkLCByZWNvcmREYXRhLmNsaWVudElkLCAvLyBXZSBrbm93IHdlIGFyZSBub3QgYW4gaW1wbGljaXQgcmVsYXRpb25zaGlwIGhlcmUKICAgICAgICAgICAgdGhpcy5rZXkpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ubG9jYWxTdGF0ZUlzRW1wdHkgPSBmdW5jdGlvbiBsb2NhbFN0YXRlSXNFbXB0eSgpIHt9OwoKICAgIF9wcm90by51cGRhdGVEYXRhID0gZnVuY3Rpb24gdXBkYXRlRGF0YShwYXlsb2FkLCBpbml0aWFsKSB7fTsKCiAgICBfcHJvdG8uZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7fTsKCiAgICBfY3JlYXRlQ2xhc3MoUmVsYXRpb25zaGlwLCBbewogICAgICBrZXk6ICJpc05ldyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLnJlY29yZERhdGEuaXNOZXcoKTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJfaW52ZXJzZU1ldGEiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fX2ludmVyc2VNZXRhID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHZhciBpbnZlcnNlTWV0YSA9IG51bGw7CgogICAgICAgICAgaWYgKHRoaXMuaW52ZXJzZUtleSkgewogICAgICAgICAgICAvLyBXZSBrbm93IHdlIGhhdmUgYSBmdWxsIGludmVyc2UgcmVsYXRpb25zaGlwCiAgICAgICAgICAgIHZhciB0eXBlID0gdGhpcy5yZWxhdGlvbnNoaXBNZXRhLnR5cGU7CiAgICAgICAgICAgIHZhciBpbnZlcnNlTW9kZWxDbGFzcyA9IHRoaXMuc3RvcmUubW9kZWxGb3IodHlwZSk7CiAgICAgICAgICAgIHZhciBpbnZlcnNlUmVsYXRpb25zaGlwcyA9IEVtYmVyLmdldChpbnZlcnNlTW9kZWxDbGFzcywgJ3JlbGF0aW9uc2hpcHNCeU5hbWUnKTsKICAgICAgICAgICAgaW52ZXJzZU1ldGEgPSBpbnZlcnNlUmVsYXRpb25zaGlwcy5nZXQodGhpcy5pbnZlcnNlS2V5KTsKICAgICAgICAgIH0KCiAgICAgICAgICB0aGlzLl9faW52ZXJzZU1ldGEgPSBpbnZlcnNlTWV0YTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9faW52ZXJzZU1ldGE7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gUmVsYXRpb25zaGlwOwogIH0oKTsKCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXMkMSh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgidmFsdWUiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfQoKICBmdW5jdGlvbiBfY3JlYXRlQ2xhc3MkMShDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDEoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQxKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfQoKICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZSQxKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcy5wcm90b3R5cGUpOyBzdWJDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBzdWJDbGFzczsgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfQogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIHZhciBNYW55UmVsYXRpb25zaGlwID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9SZWxhdGlvbnNoaXApIHsKICAgIF9pbmhlcml0c0xvb3NlJDEoTWFueVJlbGF0aW9uc2hpcCwgX1JlbGF0aW9uc2hpcCk7CgogICAgZnVuY3Rpb24gTWFueVJlbGF0aW9uc2hpcChzdG9yZSwgaW52ZXJzZUtleSwgcmVsYXRpb25zaGlwTWV0YSwgcmVjb3JkRGF0YSwgaW52ZXJzZUlzQXN5bmMpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfUmVsYXRpb25zaGlwLmNhbGwodGhpcywgc3RvcmUsIGludmVyc2VLZXksIHJlbGF0aW9uc2hpcE1ldGEsIHJlY29yZERhdGEsIGludmVyc2VJc0FzeW5jKSB8fCB0aGlzOwogICAgICBfdGhpcy5jYW5vbmljYWxTdGF0ZSA9IHZvaWQgMDsKICAgICAgX3RoaXMuY3VycmVudFN0YXRlID0gdm9pZCAwOwogICAgICBfdGhpcy5fd2lsbFVwZGF0ZU1hbnlBcnJheSA9IHZvaWQgMDsKICAgICAgX3RoaXMuX3BlbmRpbmdNYW55QXJyYXlVcGRhdGVzID0gdm9pZCAwOwogICAgICBfdGhpcy5rZXkgPSB2b2lkIDA7CiAgICAgIF90aGlzLmNhbm9uaWNhbFN0YXRlID0gW107CiAgICAgIF90aGlzLmN1cnJlbnRTdGF0ZSA9IFtdOwogICAgICBfdGhpcy5fd2lsbFVwZGF0ZU1hbnlBcnJheSA9IGZhbHNlOwogICAgICBfdGhpcy5fcGVuZGluZ01hbnlBcnJheVVwZGF0ZXMgPSBudWxsOwogICAgICBfdGhpcy5rZXkgPSByZWxhdGlvbnNoaXBNZXRhLmtleTsKICAgICAgcmV0dXJuIF90aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBNYW55UmVsYXRpb25zaGlwLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uYWRkQ2Fub25pY2FsUmVjb3JkRGF0YSA9IGZ1bmN0aW9uIGFkZENhbm9uaWNhbFJlY29yZERhdGEocmVjb3JkRGF0YSwgaWR4KSB7CiAgICAgIGlmICh0aGlzLmNhbm9uaWNhbE1lbWJlcnMuaGFzKHJlY29yZERhdGEpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAoaWR4ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLmNhbm9uaWNhbFN0YXRlLnNwbGljZShpZHgsIDAsIHJlY29yZERhdGEpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuY2Fub25pY2FsU3RhdGUucHVzaChyZWNvcmREYXRhKTsKICAgICAgfQoKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUuYWRkQ2Fub25pY2FsUmVjb3JkRGF0YS5jYWxsKHRoaXMsIHJlY29yZERhdGEsIGlkeCk7CiAgICB9OwoKICAgIF9wcm90by5pbnZlcnNlRGlkRGVtYXRlcmlhbGl6ZSA9IGZ1bmN0aW9uIGludmVyc2VEaWREZW1hdGVyaWFsaXplKGludmVyc2VSZWNvcmREYXRhKSB7CiAgICAgIF9SZWxhdGlvbnNoaXAucHJvdG90eXBlLmludmVyc2VEaWREZW1hdGVyaWFsaXplLmNhbGwodGhpcywgaW52ZXJzZVJlY29yZERhdGEpOwoKICAgICAgaWYgKHRoaXMuaXNBc3luYykgewogICAgICAgIHRoaXMubm90aWZ5TWFueUFycmF5SXNTdGFsZSgpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5hZGRSZWNvcmREYXRhID0gZnVuY3Rpb24gYWRkUmVjb3JkRGF0YShyZWNvcmREYXRhLCBpZHgpIHsKICAgICAgaWYgKHRoaXMubWVtYmVycy5oYXMocmVjb3JkRGF0YSkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gLy8gVE9ETyBUeXBlIHRoaXMKCgogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5hZGRSZWNvcmREYXRhLmNhbGwodGhpcywgcmVjb3JkRGF0YSwgaWR4KTsgLy8gbWFrZSBsYXp5IGxhdGVyCgoKICAgICAgaWYgKGlkeCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgaWR4ID0gdGhpcy5jdXJyZW50U3RhdGUubGVuZ3RoOwogICAgICB9CgogICAgICB0aGlzLmN1cnJlbnRTdGF0ZS5zcGxpY2UoaWR4LCAwLCByZWNvcmREYXRhKTsgLy8gVE9ETyBJZ29yIGNvbnNpZGVyIG1ha2luZyBkaXJlY3QgdG8gcmVtb3ZlIHRoZSBpbmRpcmVjdGlvbgogICAgICAvLyBXZSBhcmUgbm90IGxhemlseSBhY2Nlc3NpbmcgdGhlIG1hbnlBcnJheSBoZXJlIGJlY2F1c2UgdGhlIGNoYW5nZSBpcyBjb21pbmcgZnJvbSBhcHAgc2lkZQogICAgICAvLyB0aGlzLm1hbnlBcnJheS5mbHVzaENhbm9uaWNhbCh0aGlzLmN1cnJlbnRTdGF0ZSk7CgogICAgICB0aGlzLm5vdGlmeUhhc01hbnlDaGFuZ2UoKTsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tT3duID0gZnVuY3Rpb24gcmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YUZyb21Pd24ocmVjb3JkRGF0YSwgaWR4KSB7CiAgICAgIHZhciBpID0gaWR4OwoKICAgICAgaWYgKCF0aGlzLmNhbm9uaWNhbE1lbWJlcnMuaGFzKHJlY29yZERhdGEpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAoaSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgaSA9IHRoaXMuY2Fub25pY2FsU3RhdGUuaW5kZXhPZihyZWNvcmREYXRhKTsKICAgICAgfQoKICAgICAgaWYgKGkgPiAtMSkgewogICAgICAgIHRoaXMuY2Fub25pY2FsU3RhdGUuc3BsaWNlKGksIDEpOwogICAgICB9CgogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhRnJvbU93bi5jYWxsKHRoaXMsIHJlY29yZERhdGEsIGlkeCk7IC8vVE9ETyhJZ29yKSBGaWd1cmUgb3V0IHdoYXQgdG8gZG8gaGVyZQoKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUFsbENhbm9uaWNhbFJlY29yZERhdGFzRnJvbU93biA9IGZ1bmN0aW9uIHJlbW92ZUFsbENhbm9uaWNhbFJlY29yZERhdGFzRnJvbU93bigpIHsKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUucmVtb3ZlQWxsQ2Fub25pY2FsUmVjb3JkRGF0YXNGcm9tT3duLmNhbGwodGhpcyk7CgogICAgICB0aGlzLmNhbm9uaWNhbE1lbWJlcnMuY2xlYXIoKTsKICAgICAgdGhpcy5jYW5vbmljYWxTdGF0ZS5zcGxpY2UoMCwgdGhpcy5jYW5vbmljYWxTdGF0ZS5sZW5ndGgpOwoKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUucmVtb3ZlQWxsQ2Fub25pY2FsUmVjb3JkRGF0YXNGcm9tT3duLmNhbGwodGhpcyk7CiAgICB9IC8vVE9ETyhJZ29yKSBETyBXRSBORUVEIFRISVM/CiAgICA7CgogICAgX3Byb3RvLnJlbW92ZUNvbXBsZXRlbHlGcm9tT3duID0gZnVuY3Rpb24gcmVtb3ZlQ29tcGxldGVseUZyb21Pd24ocmVjb3JkRGF0YSkgewogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5yZW1vdmVDb21wbGV0ZWx5RnJvbU93bi5jYWxsKHRoaXMsIHJlY29yZERhdGEpOyAvLyBUT0RPIFNrRVBUSUNBTAoKCiAgICAgIHZhciBjYW5vbmljYWxJbmRleCA9IHRoaXMuY2Fub25pY2FsU3RhdGUuaW5kZXhPZihyZWNvcmREYXRhKTsKCiAgICAgIGlmIChjYW5vbmljYWxJbmRleCAhPT0gLTEpIHsKICAgICAgICB0aGlzLmNhbm9uaWNhbFN0YXRlLnNwbGljZShjYW5vbmljYWxJbmRleCwgMSk7CiAgICAgIH0KCiAgICAgIHRoaXMucmVtb3ZlUmVjb3JkRGF0YUZyb21Pd24ocmVjb3JkRGF0YSk7CiAgICB9OwoKICAgIF9wcm90by5mbHVzaENhbm9uaWNhbCA9IGZ1bmN0aW9uIGZsdXNoQ2Fub25pY2FsKCkgewogICAgICB2YXIgdG9TZXQgPSB0aGlzLmNhbm9uaWNhbFN0YXRlOyAvL2EgaGFjayBmb3Igbm90IHJlbW92aW5nIG5ldyByZWNvcmRzCiAgICAgIC8vVE9ETyByZW1vdmUgb25jZSB3ZSBoYXZlIHByb3BlciBkaWZmaW5nCgogICAgICB2YXIgbmV3UmVjb3JkRGF0YXMgPSB0aGlzLmN1cnJlbnRTdGF0ZS5maWx0ZXIoIC8vIG9ubHkgYWRkIG5ldyBpbnRlcm5hbE1vZGVscyB3aGljaCBhcmUgbm90IHlldCBpbiB0aGUgY2Fub25pY2FsIHN0YXRlIG9mIHRoaXMKICAgICAgLy8gcmVsYXRpb25zaGlwIChhIG5ldyBpbnRlcm5hbE1vZGVsIGNhbiBiZSBpbiB0aGUgY2Fub25pY2FsIHN0YXRlIGlmIGl0IGhhcwogICAgICAvLyBiZWVuICdhY2tub3dsZWdlZCcgdG8gYmUgaW4gdGhlIHJlbGF0aW9uc2hpcCB2aWEgYSBzdG9yZS5wdXNoKQogICAgICAvL1RPRE8gSWdvciBkZWFsIHdpdGggdGhpcwogICAgICBmdW5jdGlvbiAocmVjb3JkRGF0YSkgewogICAgICAgIHJldHVybiByZWNvcmREYXRhLmlzTmV3KCkgJiYgdG9TZXQuaW5kZXhPZihyZWNvcmREYXRhKSA9PT0gLTE7CiAgICAgIH0pOwogICAgICB0b1NldCA9IHRvU2V0LmNvbmNhdChuZXdSZWNvcmREYXRhcyk7CiAgICAgIC8qCiAgICAgIGlmICh0aGlzLl9tYW55QXJyYXkpIHsKICAgICAgICB0aGlzLl9tYW55QXJyYXkuZmx1c2hDYW5vbmljYWwodG9TZXQpOwogICAgICB9CiAgICAgICovCgogICAgICB0aGlzLmN1cnJlbnRTdGF0ZSA9IHRvU2V0OwoKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUuZmx1c2hDYW5vbmljYWwuY2FsbCh0aGlzKTsgLy8gT25jZSB3ZSBjbGVhbiB1cCBhbGwgdGhlIGZsdXNoaW5nLCB3ZSB3aWxsIGJlIGxlZnQgd2l0aCBhdCBsZWFzdCB0aGUgbm90aWZ5aW5nIHBhcnQKCgogICAgICB0aGlzLm5vdGlmeUhhc01hbnlDaGFuZ2UoKTsKICAgIH0gLy9UT0RPKElnb3IpIGlkeCBub3QgdXNlZCBjdXJyZW50bHksIGZpeAogICAgOwoKICAgIF9wcm90by5yZW1vdmVSZWNvcmREYXRhRnJvbU93biA9IGZ1bmN0aW9uIHJlbW92ZVJlY29yZERhdGFGcm9tT3duKHJlY29yZERhdGEsIGlkeCkgewogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5yZW1vdmVSZWNvcmREYXRhRnJvbU93bi5jYWxsKHRoaXMsIHJlY29yZERhdGEsIGlkeCk7CgogICAgICB2YXIgaW5kZXggPSBpZHggfHwgdGhpcy5jdXJyZW50U3RhdGUuaW5kZXhPZihyZWNvcmREYXRhKTsgLy9UT0RPIElHT1IgREFWSUQgSU5WRVNUSUdBVEUKCiAgICAgIGlmIChpbmRleCA9PT0gLTEpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuY3VycmVudFN0YXRlLnNwbGljZShpbmRleCwgMSk7IC8vIFRPRE8gSWdvciBjb25zaWRlciBtYWtpbmcgZGlyZWN0IHRvIHJlbW92ZSB0aGUgaW5kaXJlY3Rpb24KICAgICAgLy8gV2UgYXJlIG5vdCBsYXppbHkgYWNjZXNzaW5nIHRoZSBtYW55QXJyYXkgaGVyZSBiZWNhdXNlIHRoZSBjaGFuZ2UgaXMgY29taW5nIGZyb20gYXBwIHNpZGUKCiAgICAgIHRoaXMubm90aWZ5SGFzTWFueUNoYW5nZSgpOyAvLyB0aGlzLm1hbnlBcnJheS5mbHVzaENhbm9uaWNhbCh0aGlzLmN1cnJlbnRTdGF0ZSk7CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlSZWNvcmRSZWxhdGlvbnNoaXBBZGRlZCA9IGZ1bmN0aW9uIG5vdGlmeVJlY29yZFJlbGF0aW9uc2hpcEFkZGVkKCkgewogICAgICB0aGlzLm5vdGlmeUhhc01hbnlDaGFuZ2UoKTsKICAgIH07CgogICAgX3Byb3RvLmNvbXB1dGVDaGFuZ2VzID0gZnVuY3Rpb24gY29tcHV0ZUNoYW5nZXMocmVjb3JkRGF0YXMpIHsKICAgICAgaWYgKHJlY29yZERhdGFzID09PSB2b2lkIDApIHsKICAgICAgICByZWNvcmREYXRhcyA9IFtdOwogICAgICB9CgogICAgICB2YXIgbWVtYmVycyA9IHRoaXMuY2Fub25pY2FsTWVtYmVyczsKICAgICAgdmFyIHJlY29yZERhdGFzVG9SZW1vdmUgPSBbXTsKICAgICAgdmFyIHJlY29yZERhdGFzU2V0ID0gc2V0Rm9yQXJyYXkocmVjb3JkRGF0YXMpOwogICAgICBtZW1iZXJzLmZvckVhY2goZnVuY3Rpb24gKG1lbWJlcikgewogICAgICAgIGlmIChyZWNvcmREYXRhc1NldC5oYXMobWVtYmVyKSkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgcmVjb3JkRGF0YXNUb1JlbW92ZS5wdXNoKG1lbWJlcik7CiAgICAgIH0pOwogICAgICB0aGlzLnJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFzKHJlY29yZERhdGFzVG9SZW1vdmUpOwoKICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSByZWNvcmREYXRhcy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICB2YXIgcmVjb3JkRGF0YSA9IHJlY29yZERhdGFzW2ldOwogICAgICAgIHRoaXMucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhKTsKICAgICAgICB0aGlzLmFkZENhbm9uaWNhbFJlY29yZERhdGEocmVjb3JkRGF0YSwgaSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnNldEluaXRpYWxSZWNvcmREYXRhcyA9IGZ1bmN0aW9uIHNldEluaXRpYWxSZWNvcmREYXRhcyhyZWNvcmREYXRhcykgewogICAgICBpZiAoQXJyYXkuaXNBcnJheShyZWNvcmREYXRhcykgPT09IGZhbHNlIHx8ICFyZWNvcmREYXRhcyB8fCByZWNvcmREYXRhcy5sZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVjb3JkRGF0YXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgcmVjb3JkRGF0YSA9IHJlY29yZERhdGFzW2ldOwoKICAgICAgICBpZiAodGhpcy5jYW5vbmljYWxNZW1iZXJzLmhhcyhyZWNvcmREYXRhKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICB0aGlzLmNhbm9uaWNhbE1lbWJlcnMuYWRkKHJlY29yZERhdGEpOwogICAgICAgIHRoaXMubWVtYmVycy5hZGQocmVjb3JkRGF0YSk7CiAgICAgICAgdGhpcy5zZXR1cEludmVyc2VSZWxhdGlvbnNoaXAocmVjb3JkRGF0YSk7CiAgICAgIH0KCiAgICAgIHRoaXMuY2Fub25pY2FsU3RhdGUgPSB0aGlzLmNhbm9uaWNhbE1lbWJlcnMudG9BcnJheSgpOwogICAgfQogICAgLyoKICAgICAgVGhpcyBpcyBlc3NlbnRpYWxseSBhICJzeW5jIiB2ZXJzaW9uIG9mCiAgICAgICAgbm90aWZ5SGFzTWFueUNoYW5nZS4gV2Ugc2hvdWxkIHdvcmsgdG8gdW5pZnkKICAgICAgICB0aGVzZSB3b3JsZHMKICAgICAgICAgLSBAcnVuc3BpcmVkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5ub3RpZnlNYW55QXJyYXlJc1N0YWxlID0gZnVuY3Rpb24gbm90aWZ5TWFueUFycmF5SXNTdGFsZSgpIHsKICAgICAgdmFyIHJlY29yZERhdGEgPSB0aGlzLnJlY29yZERhdGE7CiAgICAgIHZhciBzdG9yZVdyYXBwZXIgPSByZWNvcmREYXRhLnN0b3JlV3JhcHBlcjsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICBzdG9yZVdyYXBwZXIubm90aWZ5SGFzTWFueUNoYW5nZShyZWNvcmREYXRhLm1vZGVsTmFtZSwgcmVjb3JkRGF0YS5pZCwgcmVjb3JkRGF0YS5jbGllbnRJZCwgdGhpcy5rZXkpOwogICAgICB9IGVsc2UgewogICAgICAgIHN0b3JlV3JhcHBlci5ub3RpZnlQcm9wZXJ0eUNoYW5nZShyZWNvcmREYXRhLm1vZGVsTmFtZSwgcmVjb3JkRGF0YS5pZCwgcmVjb3JkRGF0YS5jbGllbnRJZCwgdGhpcy5rZXkpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlIYXNNYW55Q2hhbmdlID0gZnVuY3Rpb24gbm90aWZ5SGFzTWFueUNoYW5nZSgpIHsKICAgICAgdmFyIHJlY29yZERhdGEgPSB0aGlzLnJlY29yZERhdGE7CiAgICAgIHZhciBzdG9yZVdyYXBwZXIgPSByZWNvcmREYXRhLnN0b3JlV3JhcHBlcjsKICAgICAgc3RvcmVXcmFwcGVyLm5vdGlmeUhhc01hbnlDaGFuZ2UocmVjb3JkRGF0YS5tb2RlbE5hbWUsIHJlY29yZERhdGEuaWQsIHJlY29yZERhdGEuY2xpZW50SWQsIHRoaXMua2V5KTsKICAgIH07CgogICAgX3Byb3RvLmdldERhdGEgPSBmdW5jdGlvbiBnZXREYXRhKCkgewogICAgICB2YXIgcGF5bG9hZCA9IHt9OwoKICAgICAgaWYgKHRoaXMuaGFzQW55UmVsYXRpb25zaGlwRGF0YSkgewogICAgICAgIHBheWxvYWQuZGF0YSA9IHRoaXMuY3VycmVudFN0YXRlLm1hcChmdW5jdGlvbiAocmVjb3JkRGF0YSkgewogICAgICAgICAgcmV0dXJuIHJlY29yZERhdGEuZ2V0UmVzb3VyY2VJZGVudGlmaWVyKCk7CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmxpbmtzKSB7CiAgICAgICAgcGF5bG9hZC5saW5rcyA9IHRoaXMubGlua3M7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLm1ldGEpIHsKICAgICAgICBwYXlsb2FkLm1ldGEgPSB0aGlzLm1ldGE7CiAgICAgIH0gLy8gVE9ETyBAcnVuc3BpcmVkOiB0aGUgQGlnb3IgcmVmYWN0b3IgaXMgdG9vIGxpbWl0aW5nIGZvciByZWxhdGlvbnNoaXAgc3RhdGUKICAgICAgLy8gICB3ZSBzaG91bGQgcmVjb25zaWRlciB3aGVyZSB3ZSBmZXRjaCBmcm9tLgoKCiAgICAgIHBheWxvYWQuX3JlbGF0aW9uc2hpcCA9IHRoaXM7CiAgICAgIHJldHVybiBwYXlsb2FkOwogICAgfTsKCiAgICBfcHJvdG8udXBkYXRlRGF0YSA9IGZ1bmN0aW9uIHVwZGF0ZURhdGEoZGF0YSwgaW5pdGlhbCkgewogICAgICB2YXIgcmVjb3JkRGF0YXM7CgogICAgICBpZiAoRW1iZXIuaXNOb25lKGRhdGEpKSB7CiAgICAgICAgcmVjb3JkRGF0YXMgPSB1bmRlZmluZWQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmVjb3JkRGF0YXMgPSBuZXcgQXJyYXkoZGF0YS5sZW5ndGgpOwoKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHJlY29yZERhdGFzW2ldID0gdGhpcy5yZWNvcmREYXRhLnN0b3JlV3JhcHBlci5yZWNvcmREYXRhRm9yKGRhdGFbaV0udHlwZSwgZGF0YVtpXS5pZCk7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoaW5pdGlhbCkgewogICAgICAgIHRoaXMuc2V0SW5pdGlhbFJlY29yZERhdGFzKHJlY29yZERhdGFzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnVwZGF0ZVJlY29yZERhdGFzRnJvbUFkYXB0ZXIocmVjb3JkRGF0YXMpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIEZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIGFsbCBpbnZlcnNlIHJlY29yZHMgYXJlIGF2YWlsYWJsZQogICAgICoKICAgICAqIHRydWUgaWYgaW52ZXJzZSByZWNvcmRzIGV4aXN0IGFuZCBhcmUgYWxsIGxvYWRlZCAoYWxsIG5vdCBlbXB0eSkKICAgICAqIHRydWUgaWYgdGhlcmUgYXJlIG5vIGludmVyc2UgcmVjb3JkcwogICAgICogZmFsc2UgaWYgdGhlIGludmVyc2UgcmVjb3JkcyBleGlzdCBhbmQgYW55IGFyZSBub3QgbG9hZGVkIChhbnkgZW1wdHkpCiAgICAgKgogICAgICogQHJldHVybiB7Ym9vbGVhbn0KICAgICAqLwogICAgOwoKICAgIF9jcmVhdGVDbGFzcyQxKE1hbnlSZWxhdGlvbnNoaXAsIFt7CiAgICAgIGtleTogImFsbEludmVyc2VSZWNvcmRzQXJlTG9hZGVkIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgLy8gY2hlY2sgY3VycmVudFN0YXRlIGZvciB1bmxvYWRlZCByZWNvcmRzCiAgICAgICAgdmFyIGhhc0VtcHR5UmVjb3JkcyA9IHRoaXMuY3VycmVudFN0YXRlLnJlZHVjZShmdW5jdGlvbiAoaGFzRW1wdHlNb2RlbCwgaSkgewogICAgICAgICAgcmV0dXJuIGhhc0VtcHR5TW9kZWwgfHwgaS5pc0VtcHR5KCk7CiAgICAgICAgfSwgZmFsc2UpOyAvLyBjaGVjayB1bi1zeW5jZWQgc3RhdGUgZm9yIHVubG9hZGVkIHJlY29yZHMKCiAgICAgICAgaWYgKCFoYXNFbXB0eVJlY29yZHMgJiYgdGhpcy53aWxsU3luYykgewogICAgICAgICAgaGFzRW1wdHlSZWNvcmRzID0gdGhpcy5jYW5vbmljYWxTdGF0ZS5yZWR1Y2UoZnVuY3Rpb24gKGhhc0VtcHR5TW9kZWwsIGkpIHsKICAgICAgICAgICAgcmV0dXJuIGhhc0VtcHR5TW9kZWwgfHwgIWkuaXNFbXB0eSgpOwogICAgICAgICAgfSwgZmFsc2UpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuICFoYXNFbXB0eVJlY29yZHM7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gTWFueVJlbGF0aW9uc2hpcDsKICB9KFJlbGF0aW9uc2hpcCk7CgogIGZ1bmN0aW9uIHNldEZvckFycmF5KGFycmF5KSB7CiAgICB2YXIgc2V0ID0gbmV3IEVtYmVyRGF0YU9yZGVyZWRTZXQoKTsKCiAgICBpZiAoYXJyYXkpIHsKICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBhcnJheS5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICBzZXQuYWRkKGFycmF5W2ldKTsKICAgICAgfQogICAgfQoKICAgIHJldHVybiBzZXQ7CiAgfQoKICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyQyKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyQyKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMkMihDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDIoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIGZ1bmN0aW9uIF9pbmhlcml0c0xvb3NlJDIoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzLnByb3RvdHlwZSk7IHN1YkNsYXNzLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IHN1YkNsYXNzOyBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9CgogIHZhciBCZWxvbmdzVG9SZWxhdGlvbnNoaXAgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1JlbGF0aW9uc2hpcCkgewogICAgX2luaGVyaXRzTG9vc2UkMihCZWxvbmdzVG9SZWxhdGlvbnNoaXAsIF9SZWxhdGlvbnNoaXApOwoKICAgIGZ1bmN0aW9uIEJlbG9uZ3NUb1JlbGF0aW9uc2hpcChzdG9yZSwgaW52ZXJzZUtleSwgcmVsYXRpb25zaGlwTWV0YSwgcmVjb3JkRGF0YSwgaW52ZXJzZUlzQXN5bmMpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfUmVsYXRpb25zaGlwLmNhbGwodGhpcywgc3RvcmUsIGludmVyc2VLZXksIHJlbGF0aW9uc2hpcE1ldGEsIHJlY29yZERhdGEsIGludmVyc2VJc0FzeW5jKSB8fCB0aGlzOwogICAgICBfdGhpcy5pbnZlcnNlUmVjb3JkRGF0YSA9IHZvaWQgMDsKICAgICAgX3RoaXMuY2Fub25pY2FsU3RhdGUgPSB2b2lkIDA7CiAgICAgIF90aGlzLmtleSA9IHZvaWQgMDsKICAgICAgX3RoaXMua2V5ID0gcmVsYXRpb25zaGlwTWV0YS5rZXk7CiAgICAgIF90aGlzLmludmVyc2VSZWNvcmREYXRhID0gbnVsbDsKICAgICAgX3RoaXMuY2Fub25pY2FsU3RhdGUgPSBudWxsOwogICAgICBfdGhpcy5rZXkgPSByZWxhdGlvbnNoaXBNZXRhLmtleTsKICAgICAgcmV0dXJuIF90aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBCZWxvbmdzVG9SZWxhdGlvbnNoaXAucHJvdG90eXBlOwoKICAgIF9wcm90by5zZXRSZWNvcmREYXRhID0gZnVuY3Rpb24gc2V0UmVjb3JkRGF0YShyZWNvcmREYXRhKSB7CiAgICAgIGlmIChyZWNvcmREYXRhKSB7CiAgICAgICAgdGhpcy5hZGRSZWNvcmREYXRhKHJlY29yZERhdGEpOwogICAgICB9IGVsc2UgaWYgKHRoaXMuaW52ZXJzZVJlY29yZERhdGEpIHsKICAgICAgICB0aGlzLnJlbW92ZVJlY29yZERhdGEodGhpcy5pbnZlcnNlUmVjb3JkRGF0YSk7CiAgICAgIH0KCiAgICAgIHRoaXMuc2V0SGFzQW55UmVsYXRpb25zaGlwRGF0YSh0cnVlKTsKICAgICAgdGhpcy5zZXRSZWxhdGlvbnNoaXBJc1N0YWxlKGZhbHNlKTsKICAgICAgdGhpcy5zZXRSZWxhdGlvbnNoaXBJc0VtcHR5KGZhbHNlKTsKICAgIH07CgogICAgX3Byb3RvLnNldENhbm9uaWNhbFJlY29yZERhdGEgPSBmdW5jdGlvbiBzZXRDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGEpIHsKICAgICAgaWYgKHJlY29yZERhdGEpIHsKICAgICAgICB0aGlzLmFkZENhbm9uaWNhbFJlY29yZERhdGEocmVjb3JkRGF0YSk7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5jYW5vbmljYWxTdGF0ZSkgewogICAgICAgIHRoaXMucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YSh0aGlzLmNhbm9uaWNhbFN0YXRlKTsKICAgICAgfQoKICAgICAgdGhpcy5mbHVzaENhbm9uaWNhbExhdGVyKCk7CiAgICB9OwoKICAgIF9wcm90by5zZXRJbml0aWFsQ2Fub25pY2FsUmVjb3JkRGF0YSA9IGZ1bmN0aW9uIHNldEluaXRpYWxDYW5vbmljYWxSZWNvcmREYXRhKHJlY29yZERhdGEpIHsKICAgICAgaWYgKCFyZWNvcmREYXRhKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9IC8vIFdoZW4gd2UgaW5pdGlhbGl6ZSBhIGJlbG9uZ3NUbyByZWxhdGlvbnNoaXAsIHdlIHdhbnQgdG8gYXZvaWQgd29yayBsaWtlCiAgICAgIC8vIG5vdGlmeWluZyBvdXIgaW50ZXJuYWxNb2RlbCB0aGF0IHdlJ3ZlICJjaGFuZ2VkIiBhbmQgZXhjZXNzaXZlIHRocmFzaCBvbgogICAgICAvLyBzZXR0aW5nIHVwIGludmVyc2UgcmVsYXRpb25zaGlwcwoKCiAgICAgIHRoaXMuY2Fub25pY2FsTWVtYmVycy5hZGQocmVjb3JkRGF0YSk7CiAgICAgIHRoaXMubWVtYmVycy5hZGQocmVjb3JkRGF0YSk7CiAgICAgIHRoaXMuaW52ZXJzZVJlY29yZERhdGEgPSB0aGlzLmNhbm9uaWNhbFN0YXRlID0gcmVjb3JkRGF0YTsKICAgICAgdGhpcy5zZXR1cEludmVyc2VSZWxhdGlvbnNoaXAocmVjb3JkRGF0YSk7CiAgICB9OwoKICAgIF9wcm90by5hZGRDYW5vbmljYWxSZWNvcmREYXRhID0gZnVuY3Rpb24gYWRkQ2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhKSB7CiAgICAgIGlmICh0aGlzLmNhbm9uaWNhbE1lbWJlcnMuaGFzKHJlY29yZERhdGEpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAodGhpcy5jYW5vbmljYWxTdGF0ZSkgewogICAgICAgIHRoaXMucmVtb3ZlQ2Fub25pY2FsUmVjb3JkRGF0YSh0aGlzLmNhbm9uaWNhbFN0YXRlKTsKICAgICAgfQoKICAgICAgdGhpcy5jYW5vbmljYWxTdGF0ZSA9IHJlY29yZERhdGE7CgogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5hZGRDYW5vbmljYWxSZWNvcmREYXRhLmNhbGwodGhpcywgcmVjb3JkRGF0YSk7CgogICAgICB0aGlzLnNldEhhc0FueVJlbGF0aW9uc2hpcERhdGEodHJ1ZSk7CiAgICAgIHRoaXMuc2V0UmVsYXRpb25zaGlwSXNFbXB0eShmYWxzZSk7CiAgICB9OwoKICAgIF9wcm90by5pbnZlcnNlRGlkRGVtYXRlcmlhbGl6ZSA9IGZ1bmN0aW9uIGludmVyc2VEaWREZW1hdGVyaWFsaXplKCkgewogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5pbnZlcnNlRGlkRGVtYXRlcmlhbGl6ZS5jYWxsKHRoaXMsIHRoaXMuaW52ZXJzZVJlY29yZERhdGEpOwoKICAgICAgdGhpcy5ub3RpZnlCZWxvbmdzVG9DaGFuZ2UoKTsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUNvbXBsZXRlbHlGcm9tT3duID0gZnVuY3Rpb24gcmVtb3ZlQ29tcGxldGVseUZyb21Pd24ocmVjb3JkRGF0YSkgewogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5yZW1vdmVDb21wbGV0ZWx5RnJvbU93bi5jYWxsKHRoaXMsIHJlY29yZERhdGEpOwoKICAgICAgaWYgKHRoaXMuY2Fub25pY2FsU3RhdGUgPT09IHJlY29yZERhdGEpIHsKICAgICAgICB0aGlzLmNhbm9uaWNhbFN0YXRlID0gbnVsbDsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuaW52ZXJzZVJlY29yZERhdGEgPT09IHJlY29yZERhdGEpIHsKICAgICAgICB0aGlzLmludmVyc2VSZWNvcmREYXRhID0gbnVsbDsKICAgICAgICB0aGlzLm5vdGlmeUJlbG9uZ3NUb0NoYW5nZSgpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVDb21wbGV0ZWx5RnJvbUludmVyc2UgPSBmdW5jdGlvbiByZW1vdmVDb21wbGV0ZWx5RnJvbUludmVyc2UoKSB7CiAgICAgIF9SZWxhdGlvbnNoaXAucHJvdG90eXBlLnJlbW92ZUNvbXBsZXRlbHlGcm9tSW52ZXJzZS5jYWxsKHRoaXMpOwoKICAgICAgdGhpcy5pbnZlcnNlUmVjb3JkRGF0YSA9IG51bGw7CiAgICB9OwoKICAgIF9wcm90by5mbHVzaENhbm9uaWNhbCA9IGZ1bmN0aW9uIGZsdXNoQ2Fub25pY2FsKCkgewogICAgICAvL3RlbXBvcmFyeSBmaXggdG8gbm90IHJlbW92ZSBuZXdseSBjcmVhdGVkIHJlY29yZHMgaWYgc2VydmVyIHJldHVybmVkIG51bGwuCiAgICAgIC8vVE9ETyByZW1vdmUgb25jZSB3ZSBoYXZlIHByb3BlciBkaWZmaW5nCiAgICAgIGlmICh0aGlzLmludmVyc2VSZWNvcmREYXRhICYmIHRoaXMuaW52ZXJzZVJlY29yZERhdGEuaXNOZXcoKSAmJiAhdGhpcy5jYW5vbmljYWxTdGF0ZSkgewogICAgICAgIHRoaXMud2lsbFN5bmMgPSBmYWxzZTsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmludmVyc2VSZWNvcmREYXRhICE9PSB0aGlzLmNhbm9uaWNhbFN0YXRlKSB7CiAgICAgICAgdGhpcy5pbnZlcnNlUmVjb3JkRGF0YSA9IHRoaXMuY2Fub25pY2FsU3RhdGU7CiAgICAgICAgdGhpcy5ub3RpZnlCZWxvbmdzVG9DaGFuZ2UoKTsKICAgICAgfQoKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUuZmx1c2hDYW5vbmljYWwuY2FsbCh0aGlzKTsKICAgIH07CgogICAgX3Byb3RvLmFkZFJlY29yZERhdGEgPSBmdW5jdGlvbiBhZGRSZWNvcmREYXRhKHJlY29yZERhdGEpIHsKICAgICAgaWYgKHRoaXMubWVtYmVycy5oYXMocmVjb3JkRGF0YSkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gLy8gVE9ETyBJZ29yIGNsZWFudXAKCgogICAgICBpZiAodGhpcy5pbnZlcnNlUmVjb3JkRGF0YSkgewogICAgICAgIHRoaXMucmVtb3ZlUmVjb3JkRGF0YSh0aGlzLmludmVyc2VSZWNvcmREYXRhKTsKICAgICAgfQoKICAgICAgdGhpcy5pbnZlcnNlUmVjb3JkRGF0YSA9IHJlY29yZERhdGE7CgogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5hZGRSZWNvcmREYXRhLmNhbGwodGhpcywgcmVjb3JkRGF0YSk7CgogICAgICB0aGlzLm5vdGlmeUJlbG9uZ3NUb0NoYW5nZSgpOwogICAgfTsKCiAgICBfcHJvdG8ucmVtb3ZlUmVjb3JkRGF0YUZyb21Pd24gPSBmdW5jdGlvbiByZW1vdmVSZWNvcmREYXRhRnJvbU93bihyZWNvcmREYXRhKSB7CiAgICAgIGlmICghdGhpcy5tZW1iZXJzLmhhcyhyZWNvcmREYXRhKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5pbnZlcnNlUmVjb3JkRGF0YSA9IG51bGw7CgogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5yZW1vdmVSZWNvcmREYXRhRnJvbU93bi5jYWxsKHRoaXMsIHJlY29yZERhdGEpOwoKICAgICAgdGhpcy5ub3RpZnlCZWxvbmdzVG9DaGFuZ2UoKTsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUFsbFJlY29yZERhdGFzRnJvbU93biA9IGZ1bmN0aW9uIHJlbW92ZUFsbFJlY29yZERhdGFzRnJvbU93bigpIHsKICAgICAgX1JlbGF0aW9uc2hpcC5wcm90b3R5cGUucmVtb3ZlQWxsUmVjb3JkRGF0YXNGcm9tT3duLmNhbGwodGhpcyk7CgogICAgICB0aGlzLmludmVyc2VSZWNvcmREYXRhID0gbnVsbDsKICAgICAgdGhpcy5ub3RpZnlCZWxvbmdzVG9DaGFuZ2UoKTsKICAgIH07CgogICAgX3Byb3RvLm5vdGlmeUJlbG9uZ3NUb0NoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeUJlbG9uZ3NUb0NoYW5nZSgpIHsKICAgICAgdmFyIHJlY29yZERhdGEgPSB0aGlzLnJlY29yZERhdGE7CiAgICAgIHZhciBzdG9yZVdyYXBwZXIgPSB0aGlzLnJlY29yZERhdGEuc3RvcmVXcmFwcGVyOwogICAgICBzdG9yZVdyYXBwZXIubm90aWZ5QmVsb25nc1RvQ2hhbmdlKHJlY29yZERhdGEubW9kZWxOYW1lLCByZWNvcmREYXRhLmlkLCByZWNvcmREYXRhLmNsaWVudElkLCB0aGlzLmtleSk7CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhRnJvbU93biA9IGZ1bmN0aW9uIHJlbW92ZUNhbm9uaWNhbFJlY29yZERhdGFGcm9tT3duKHJlY29yZERhdGEpIHsKICAgICAgaWYgKCF0aGlzLmNhbm9uaWNhbE1lbWJlcnMuaGFzKHJlY29yZERhdGEpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLmNhbm9uaWNhbFN0YXRlID0gbnVsbDsKICAgICAgdGhpcy5zZXRIYXNBbnlSZWxhdGlvbnNoaXBEYXRhKHRydWUpOwogICAgICB0aGlzLnNldFJlbGF0aW9uc2hpcElzRW1wdHkodHJ1ZSk7CgogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5yZW1vdmVDYW5vbmljYWxSZWNvcmREYXRhRnJvbU93bi5jYWxsKHRoaXMsIHJlY29yZERhdGEpOwogICAgfTsKCiAgICBfcHJvdG8ucmVtb3ZlQWxsQ2Fub25pY2FsUmVjb3JkRGF0YXNGcm9tT3duID0gZnVuY3Rpb24gcmVtb3ZlQWxsQ2Fub25pY2FsUmVjb3JkRGF0YXNGcm9tT3duKCkgewogICAgICBfUmVsYXRpb25zaGlwLnByb3RvdHlwZS5yZW1vdmVBbGxDYW5vbmljYWxSZWNvcmREYXRhc0Zyb21Pd24uY2FsbCh0aGlzKTsKCiAgICAgIHRoaXMuY2Fub25pY2FsU3RhdGUgPSBudWxsOwogICAgfTsKCiAgICBfcHJvdG8uZ2V0RGF0YSA9IGZ1bmN0aW9uIGdldERhdGEoKSB7CiAgICAgIHZhciBkYXRhOwogICAgICB2YXIgcGF5bG9hZCA9IHt9OwoKICAgICAgaWYgKHRoaXMuaW52ZXJzZVJlY29yZERhdGEpIHsKICAgICAgICBkYXRhID0gdGhpcy5pbnZlcnNlUmVjb3JkRGF0YS5nZXRSZXNvdXJjZUlkZW50aWZpZXIoKTsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuaW52ZXJzZVJlY29yZERhdGEgPT09IG51bGwgJiYgdGhpcy5oYXNBbnlSZWxhdGlvbnNoaXBEYXRhKSB7CiAgICAgICAgZGF0YSA9IG51bGw7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmxpbmtzKSB7CiAgICAgICAgcGF5bG9hZC5saW5rcyA9IHRoaXMubGlua3M7CiAgICAgIH0KCiAgICAgIGlmIChkYXRhICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBwYXlsb2FkLmRhdGEgPSBkYXRhOwogICAgICB9CgogICAgICBpZiAodGhpcy5tZXRhKSB7CiAgICAgICAgcGF5bG9hZC5tZXRhID0gdGhpcy5tZXRhOwogICAgICB9CgogICAgICBwYXlsb2FkLl9yZWxhdGlvbnNoaXAgPSB0aGlzOwogICAgICByZXR1cm4gcGF5bG9hZDsKICAgIH0KICAgIC8qKgogICAgICogRmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgYWxsIGludmVyc2UgcmVjb3JkcyBhcmUgYXZhaWxhYmxlCiAgICAgKgogICAgICogdHJ1ZSBpZiB0aGUgaW52ZXJzZSBleGlzdHMgYW5kIGlzIGxvYWRlZCAobm90IGVtcHR5KQogICAgICogdHJ1ZSBpZiB0aGVyZSBpcyBubyBpbnZlcnNlCiAgICAgKiBmYWxzZSBpZiB0aGUgaW52ZXJzZSBleGlzdHMgYW5kIGlzIG5vdCBsb2FkZWQgKGVtcHR5KQogICAgICoKICAgICAqIEByZXR1cm4ge2Jvb2xlYW59CiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8udXBkYXRlRGF0YSA9IGZ1bmN0aW9uIHVwZGF0ZURhdGEoZGF0YSwgaW5pdGlhbCkgewogICAgICB2YXIgcmVjb3JkRGF0YTsKCiAgICAgIGlmIChFbWJlci5pc05vbmUoZGF0YSkpIHsKICAgICAgICByZWNvcmREYXRhID0gbnVsbDsKICAgICAgfQoKICAgICAgaWYgKHJlY29yZERhdGEgIT09IG51bGwpIHsKICAgICAgICByZWNvcmREYXRhID0gdGhpcy5yZWNvcmREYXRhLnN0b3JlV3JhcHBlci5yZWNvcmREYXRhRm9yKGRhdGEudHlwZSwgZGF0YS5pZCk7CiAgICAgIH0KCiAgICAgIGlmIChpbml0aWFsKSB7CiAgICAgICAgdGhpcy5zZXRJbml0aWFsQ2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnNldENhbm9uaWNhbFJlY29yZERhdGEocmVjb3JkRGF0YSk7CiAgICAgIH0KICAgIH07CgogICAgX2NyZWF0ZUNsYXNzJDIoQmVsb25nc1RvUmVsYXRpb25zaGlwLCBbewogICAgICBrZXk6ICJhbGxJbnZlcnNlUmVjb3Jkc0FyZUxvYWRlZCIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHZhciByZWNvcmREYXRhID0gdGhpcy5pbnZlcnNlUmVjb3JkRGF0YTsKICAgICAgICB2YXIgaXNFbXB0eSA9IHJlY29yZERhdGEgIT09IG51bGwgJiYgcmVjb3JkRGF0YS5pc0VtcHR5KCk7CiAgICAgICAgcmV0dXJuICFpc0VtcHR5OwogICAgICB9CiAgICB9XSk7CgogICAgcmV0dXJuIEJlbG9uZ3NUb1JlbGF0aW9uc2hpcDsKICB9KFJlbGF0aW9uc2hpcCk7CgogIGZ1bmN0aW9uIGNyZWF0ZVJlbGF0aW9uc2hpcEZvcihyZWxhdGlvbnNoaXBNZXRhLCBzdG9yZSwgcmVjb3JkRGF0YSwga2V5KSB7CiAgICB2YXIgaW52ZXJzZUtleSA9IHJlY29yZERhdGEuc3RvcmVXcmFwcGVyLmludmVyc2VGb3JSZWxhdGlvbnNoaXAocmVjb3JkRGF0YS5tb2RlbE5hbWUsIGtleSk7CiAgICB2YXIgaW52ZXJzZUlzQXN5bmMgPSByZWNvcmREYXRhLnN0b3JlV3JhcHBlci5pbnZlcnNlSXNBc3luY0ZvclJlbGF0aW9uc2hpcChyZWNvcmREYXRhLm1vZGVsTmFtZSwga2V5KTsKCiAgICBpZiAocmVsYXRpb25zaGlwTWV0YS5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgcmV0dXJuIG5ldyBNYW55UmVsYXRpb25zaGlwKHN0b3JlLCBpbnZlcnNlS2V5LCByZWxhdGlvbnNoaXBNZXRhLCByZWNvcmREYXRhLCBpbnZlcnNlSXNBc3luYyk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gbmV3IEJlbG9uZ3NUb1JlbGF0aW9uc2hpcChzdG9yZSwgaW52ZXJzZUtleSwgcmVsYXRpb25zaGlwTWV0YSwgcmVjb3JkRGF0YSwgaW52ZXJzZUlzQXN5bmMpOwogICAgfQogIH0KCiAgdmFyIFJlbGF0aW9uc2hpcHMgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBSZWxhdGlvbnNoaXBzKHJlY29yZERhdGEpIHsKICAgICAgdGhpcy5yZWNvcmREYXRhID0gcmVjb3JkRGF0YTsKICAgICAgdGhpcy5fc3RvcmUgPSB2b2lkIDA7CiAgICAgIHRoaXMuX3N0b3JlV3JhcHBlciA9IHZvaWQgMDsKICAgICAgdGhpcy5pbml0aWFsaXplZFJlbGF0aW9uc2hpcHMgPSB2b2lkIDA7CiAgICAgIHRoaXMuaW5pdGlhbGl6ZWRSZWxhdGlvbnNoaXBzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGhpcy5fc3RvcmVXcmFwcGVyID0gUHJpdmF0ZS51cGdyYWRlRm9ySW50ZXJuYWwocmVjb3JkRGF0YS5zdG9yZVdyYXBwZXIpOwogICAgICB0aGlzLl9zdG9yZSA9IHRoaXMuX3N0b3JlV3JhcHBlci5fc3RvcmU7CiAgICB9CgogICAgdmFyIF9wcm90byA9IFJlbGF0aW9uc2hpcHMucHJvdG90eXBlOwoKICAgIF9wcm90by5oYXMgPSBmdW5jdGlvbiBoYXMoa2V5KSB7CiAgICAgIHJldHVybiAhIXRoaXMuaW5pdGlhbGl6ZWRSZWxhdGlvbnNoaXBzW2tleV07CiAgICB9OwoKICAgIF9wcm90by5mb3JFYWNoID0gZnVuY3Rpb24gZm9yRWFjaChjYikgewogICAgICB2YXIgcmVscyA9IHRoaXMuaW5pdGlhbGl6ZWRSZWxhdGlvbnNoaXBzOwogICAgICBPYmplY3Qua2V5cyhyZWxzKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7CiAgICAgICAgY2IobmFtZSwgcmVsc1tuYW1lXSk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8uZ2V0ID0gZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICB2YXIgcmVsYXRpb25zaGlwcyA9IHRoaXMuaW5pdGlhbGl6ZWRSZWxhdGlvbnNoaXBzOwogICAgICB2YXIgcmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwc1trZXldOwoKICAgICAgaWYgKCFyZWxhdGlvbnNoaXApIHsKICAgICAgICB2YXIgX3JlY29yZERhdGEgPSB0aGlzLnJlY29yZERhdGE7CiAgICAgICAgdmFyIHJlbCA9IHRoaXMucmVjb3JkRGF0YS5zdG9yZVdyYXBwZXIucmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IodGhpcy5yZWNvcmREYXRhLm1vZGVsTmFtZSlba2V5XTsKCiAgICAgICAgaWYgKHJlbCkgewogICAgICAgICAgcmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwc1trZXldID0gY3JlYXRlUmVsYXRpb25zaGlwRm9yKHJlbCwgdGhpcy5fc3RvcmUsIF9yZWNvcmREYXRhLCBrZXkpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcDsKICAgIH07CgogICAgcmV0dXJuIFJlbGF0aW9uc2hpcHM7CiAgfSgpOwoKICAvLyBVc2VkIGJ5IHRoZSBzdG9yZSB0byBub3JtYWxpemUgSURzIGVudGVyaW5nIHRoZSBzdG9yZS4gIERlc3BpdGUgdGhlIGZhY3QKICAvLyB0aGF0IGRldmVsb3BlcnMgbWF5IHByb3ZpZGUgSURzIGFzIG51bWJlcnMgKGUuZy4sIGBzdG9yZS5maW5kUmVjb3JkKCdwZXJzb24nLCAxKWApLAogIC8vIGl0IGlzIGltcG9ydGFudCB0aGF0IGludGVybmFsbHkgd2UgdXNlIHN0cmluZ3MsIHNpbmNlIElEcyBtYXkgYmUgc2VyaWFsaXplZAogIC8vIGFuZCBsb3NlIHR5cGUgaW5mb3JtYXRpb24uICBGb3IgZXhhbXBsZSwgRW1iZXIncyByb3V0ZXIgbWF5IHB1dCBhIHJlY29yZCdzCiAgLy8gSUQgaW50byB0aGUgVVJMLCBhbmQgaWYgd2UgbGF0ZXIgdHJ5IHRvIGRlc2VyaWFsaXplIHRoYXQgVVJMIGFuZCBmaW5kIHRoZQogIC8vIGNvcnJlc3BvbmRpbmcgcmVjb3JkLCB3ZSB3aWxsIG5vdCBrbm93IGlmIGl0IGlzIGEgc3RyaW5nIG9yIGEgbnVtYmVyLgogIGZ1bmN0aW9uIGNvZXJjZUlkKGlkKSB7CiAgICBpZiAoaWQgPT09IG51bGwgfHwgaWQgPT09IHVuZGVmaW5lZCB8fCBpZCA9PT0gJycpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CgogICAgaWYgKHR5cGVvZiBpZCA9PT0gJ3N0cmluZycpIHsKICAgICAgcmV0dXJuIGlkOwogICAgfQoKICAgIGlmICh0eXBlb2YgaWQgPT09ICdzeW1ib2wnKSB7CiAgICAgIHJldHVybiBpZC50b1N0cmluZygpOwogICAgfQoKICAgIHJldHVybiAnJyArIGlkOwogIH0KCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXMkMyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgidmFsdWUiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfQoKICBmdW5jdGlvbiBfY3JlYXRlQ2xhc3MkMyhDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfQogIHZhciBuZXh0QmZzSWQgPSAxOwoKICB2YXIgUmVjb3JkRGF0YURlZmF1bHQgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBSZWNvcmREYXRhRGVmYXVsdChhcmcxLCBhcmcyKSB7CiAgICAgIHRoaXMuX2Vycm9ycyA9IHZvaWQgMDsKICAgICAgdGhpcy5fX3JlbGF0aW9uc2hpcHMgPSB2b2lkIDA7CiAgICAgIHRoaXMuX19pbXBsaWNpdFJlbGF0aW9uc2hpcHMgPSB2b2lkIDA7CiAgICAgIHRoaXMubW9kZWxOYW1lID0gdm9pZCAwOwogICAgICB0aGlzLmNsaWVudElkID0gdm9pZCAwOwogICAgICB0aGlzLmlkID0gdm9pZCAwOwogICAgICB0aGlzLmlzRGVzdHJveWVkID0gdm9pZCAwOwogICAgICB0aGlzLl9pc05ldyA9IHZvaWQgMDsKICAgICAgdGhpcy5fYmZzSWQgPSB2b2lkIDA7CiAgICAgIHRoaXMuX19hdHRyaWJ1dGVzID0gdm9pZCAwOwogICAgICB0aGlzLl9faW5GbGlnaHRBdHRyaWJ1dGVzID0gdm9pZCAwOwogICAgICB0aGlzLl9fZGF0YSA9IHZvaWQgMDsKICAgICAgdGhpcy5fc2NoZWR1bGVkRGVzdHJveSA9IHZvaWQgMDsKICAgICAgdGhpcy5faXNEZWxldGVkID0gdm9pZCAwOwogICAgICB0aGlzLl9pc0RlbGV0aW9uQ29tbWl0ZWQgPSB2b2lkIDA7CiAgICAgIHRoaXMuaWRlbnRpZmllciA9IHZvaWQgMDsKICAgICAgdGhpcy5zdG9yZVdyYXBwZXIgPSB2b2lkIDA7CgogICAgICB7CiAgICAgICAgdmFyIF9pZGVudGlmaWVyID0gYXJndW1lbnRzWzBdLAogICAgICAgICAgICBfc3RvcmVXcmFwcGVyID0gYXJndW1lbnRzWzFdOwogICAgICAgIHRoaXMuaWRlbnRpZmllciA9IF9pZGVudGlmaWVyOwogICAgICAgIHRoaXMubW9kZWxOYW1lID0gX2lkZW50aWZpZXIudHlwZTsKICAgICAgICB0aGlzLmNsaWVudElkID0gX2lkZW50aWZpZXIubGlkOwogICAgICAgIHRoaXMuaWQgPSBfaWRlbnRpZmllci5pZDsKICAgICAgICB0aGlzLnN0b3JlV3JhcHBlciA9IF9zdG9yZVdyYXBwZXI7CiAgICAgIH0KCiAgICAgIHRoaXMuX19yZWxhdGlvbnNoaXBzID0gbnVsbDsKICAgICAgdGhpcy5fX2ltcGxpY2l0UmVsYXRpb25zaGlwcyA9IG51bGw7CiAgICAgIHRoaXMuaXNEZXN0cm95ZWQgPSBmYWxzZTsKICAgICAgdGhpcy5faXNOZXcgPSBmYWxzZTsKICAgICAgdGhpcy5faXNEZWxldGVkID0gZmFsc2U7IC8vIFVzZWQgZHVyaW5nIHRoZSBtYXJrIHBoYXNlIG9mIHVubG9hZGluZyB0byBhdm9pZCBjaGVja2luZyB0aGUgc2FtZSBpbnRlcm5hbAogICAgICAvLyBtb2RlbCB0d2ljZSBpbiB0aGUgc2FtZSBzY2FuCgogICAgICB0aGlzLl9iZnNJZCA9IDA7CiAgICAgIHRoaXMucmVzZXQoKTsKICAgIH0gLy8gUFVCTElDIEFQSQoKCiAgICB2YXIgX3Byb3RvID0gUmVjb3JkRGF0YURlZmF1bHQucHJvdG90eXBlOwoKICAgIF9wcm90by5nZXRSZXNvdXJjZUlkZW50aWZpZXIgPSBmdW5jdGlvbiBnZXRSZXNvdXJjZUlkZW50aWZpZXIoKSB7CiAgICAgIHJldHVybiAgdGhpcy5pZGVudGlmaWVyIDsKICAgIH07CgogICAgX3Byb3RvLnB1c2hEYXRhID0gZnVuY3Rpb24gcHVzaERhdGEoZGF0YSwgY2FsY3VsYXRlQ2hhbmdlKSB7CiAgICAgIHZhciBjaGFuZ2VkS2V5czsKCiAgICAgIGlmICh0aGlzLl9pc05ldykgewogICAgICAgIHRoaXMuX2lzTmV3ID0gZmFsc2U7CiAgICAgICAgdGhpcy5ub3RpZnlTdGF0ZUNoYW5nZSgpOwogICAgICB9CgogICAgICBpZiAoY2FsY3VsYXRlQ2hhbmdlKSB7CiAgICAgICAgY2hhbmdlZEtleXMgPSB0aGlzLl9jaGFuZ2VkS2V5cyhkYXRhLmF0dHJpYnV0ZXMpOwogICAgICB9CgogICAgICBFbWJlci5hc3NpZ24odGhpcy5fZGF0YSwgZGF0YS5hdHRyaWJ1dGVzKTsKCiAgICAgIGlmICh0aGlzLl9fYXR0cmlidXRlcykgewogICAgICAgIC8vIG9ubHkgZG8gaWYgd2UgaGF2ZSBhdHRyaWJ1dGUgY2hhbmdlcwogICAgICAgIHRoaXMuX3VwZGF0ZUNoYW5nZWRBdHRyaWJ1dGVzKCk7CiAgICAgIH0KCiAgICAgIGlmIChkYXRhLnJlbGF0aW9uc2hpcHMpIHsKICAgICAgICB0aGlzLl9zZXR1cFJlbGF0aW9uc2hpcHMoZGF0YSk7CiAgICAgIH0KCiAgICAgIGlmIChkYXRhLmlkKSB7CiAgICAgICAgdGhpcy5pZCA9IGNvZXJjZUlkKGRhdGEuaWQpOwogICAgICB9CgogICAgICByZXR1cm4gY2hhbmdlZEtleXM7CiAgICB9OwoKICAgIF9wcm90by53aWxsQ29tbWl0ID0gZnVuY3Rpb24gd2lsbENvbW1pdCgpIHsKICAgICAgdGhpcy5faW5GbGlnaHRBdHRyaWJ1dGVzID0gdGhpcy5fYXR0cmlidXRlczsKICAgICAgdGhpcy5fYXR0cmlidXRlcyA9IG51bGw7CiAgICB9OwoKICAgIF9wcm90by5oYXNDaGFuZ2VkQXR0cmlidXRlcyA9IGZ1bmN0aW9uIGhhc0NoYW5nZWRBdHRyaWJ1dGVzKCkgewogICAgICByZXR1cm4gdGhpcy5fX2F0dHJpYnV0ZXMgIT09IG51bGwgJiYgT2JqZWN0LmtleXModGhpcy5fX2F0dHJpYnV0ZXMpLmxlbmd0aCA+IDA7CiAgICB9OwoKICAgIF9wcm90by5fY2xlYXJFcnJvcnMgPSBmdW5jdGlvbiBfY2xlYXJFcnJvcnMoKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9FUlJPUlMpIHsKICAgICAgICBpZiAodGhpcy5fZXJyb3JzKSB7CiAgICAgICAgICB0aGlzLl9lcnJvcnMgPSB1bmRlZmluZWQ7CiAgICAgICAgICB0aGlzLnN0b3JlV3JhcHBlci5ub3RpZnlFcnJvcnNDaGFuZ2UodGhpcy5tb2RlbE5hbWUsIHRoaXMuaWQsIHRoaXMuY2xpZW50SWQpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uZ2V0RXJyb3JzID0gZnVuY3Rpb24gZ2V0RXJyb3JzKCkgewoKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX0VSUk9SUykgewogICAgICAgIHZhciBlcnJvcnMgPSB0aGlzLl9lcnJvcnMgfHwgW107CiAgICAgICAgcmV0dXJuIGVycm9yczsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gW107CiAgICAgIH0KICAgIH0gLy8gdGhpcyBpcyBhIGhhY2sgYmMgd2UgZG9uJ3QgaGF2ZSBhY2Nlc3MgdG8gdGhlIHN0YXRlIG1hY2hpbmUKICAgIC8vICAgYW5kIHJlbGF0aW9uc2hpcHMgbmVlZCB0aGlzIGluZm8gYW5kIEBydW5zcGlyZWQgZGlkbid0IHNlZQogICAgLy8gICBob3cgdG8gZ2V0IGl0IGp1c3QgeWV0IGZyb20gc3RvcmVXcmFwcGVyLgogICAgOwoKICAgIF9wcm90by5pc0VtcHR5ID0gZnVuY3Rpb24gaXNFbXB0eSgpIHsKICAgICAgcmV0dXJuIHRoaXMuX19hdHRyaWJ1dGVzID09PSBudWxsICYmIHRoaXMuX19pbkZsaWdodEF0dHJpYnV0ZXMgPT09IG51bGwgJiYgdGhpcy5fX2RhdGEgPT09IG51bGw7CiAgICB9OwoKICAgIF9wcm90by5kZWxldGVSZWNvcmQgPSBmdW5jdGlvbiBkZWxldGVSZWNvcmQoKSB7CiAgICAgIHRoaXMuX2lzRGVsZXRlZCA9IHRydWU7CiAgICAgIHRoaXMubm90aWZ5U3RhdGVDaGFuZ2UoKTsKICAgIH07CgogICAgX3Byb3RvLmlzRGVsZXRlZCA9IGZ1bmN0aW9uIGlzRGVsZXRlZCgpIHsKICAgICAgcmV0dXJuIHRoaXMuX2lzRGVsZXRlZDsKICAgIH07CgogICAgX3Byb3RvLnNldElzRGVsZXRlZCA9IGZ1bmN0aW9uIHNldElzRGVsZXRlZChpc0RlbGV0ZWQpIHsKICAgICAgdGhpcy5faXNEZWxldGVkID0gaXNEZWxldGVkOwoKICAgICAgaWYgKHRoaXMuX2lzTmV3KSB7CiAgICAgICAgdGhpcy5fZGVsZXRpb25Db25maXJtZWQoKTsKICAgICAgfQoKICAgICAgdGhpcy5ub3RpZnlTdGF0ZUNoYW5nZSgpOwogICAgfTsKCiAgICBfcHJvdG8uaXNEZWxldGlvbkNvbW1pdHRlZCA9IGZ1bmN0aW9uIGlzRGVsZXRpb25Db21taXR0ZWQoKSB7CiAgICAgIHJldHVybiB0aGlzLl9pc0RlbGV0aW9uQ29tbWl0ZWQ7CiAgICB9OwoKICAgIF9wcm90by5yZXNldCA9IGZ1bmN0aW9uIHJlc2V0KCkgewogICAgICB0aGlzLl9fYXR0cmlidXRlcyA9IG51bGw7CiAgICAgIHRoaXMuX19pbkZsaWdodEF0dHJpYnV0ZXMgPSBudWxsOwogICAgICB0aGlzLl9fZGF0YSA9IG51bGw7CiAgICAgIHRoaXMuX2Vycm9ycyA9IHVuZGVmaW5lZDsKICAgIH07CgogICAgX3Byb3RvLl9zZXR1cFJlbGF0aW9uc2hpcHMgPSBmdW5jdGlvbiBfc2V0dXBSZWxhdGlvbnNoaXBzKGRhdGEpIHsKICAgICAgdmFyIHJlbGF0aW9uc2hpcHMgPSB0aGlzLnN0b3JlV3JhcHBlci5yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcih0aGlzLm1vZGVsTmFtZSk7CiAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMocmVsYXRpb25zaGlwcyk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgcmVsYXRpb25zaGlwTmFtZSA9IGtleXNbaV07CgogICAgICAgIGlmICghZGF0YS5yZWxhdGlvbnNoaXBzW3JlbGF0aW9uc2hpcE5hbWVdKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9IC8vIGluIGRlYnVnLCBhc3NlcnQgcGF5bG9hZCB2YWxpZGl0eSBlYWdlcmx5CgoKICAgICAgICB2YXIgcmVsYXRpb25zaGlwRGF0YSA9IGRhdGEucmVsYXRpb25zaGlwc1tyZWxhdGlvbnNoaXBOYW1lXTsKCiAgICAgICAgdmFyIHJlbGF0aW9uc2hpcCA9IHRoaXMuX3JlbGF0aW9uc2hpcHMuZ2V0KHJlbGF0aW9uc2hpcE5hbWUpOwoKICAgICAgICByZWxhdGlvbnNoaXAucHVzaChyZWxhdGlvbnNoaXBEYXRhKTsKICAgICAgfQogICAgfQogICAgLyoKICAgICAgQ2hlY2tzIGlmIHRoZSBhdHRyaWJ1dGVzIHdoaWNoIGFyZSBjb25zaWRlcmVkIGFzIGNoYW5nZWQgYXJlIHN0aWxsCiAgICAgIGRpZmZlcmVudCB0byB0aGUgc3RhdGUgd2hpY2ggaXMgYWNrbm93bGVkZ2VkIGJ5IHRoZSBzZXJ2ZXIuCiAgICAgICBUaGlzIG1ldGhvZCBpcyBuZWVkZWQgd2hlbiBkYXRhIGZvciB0aGUgaW50ZXJuYWwgbW9kZWwgaXMgcHVzaGVkIGFuZCB0aGUKICAgICAgcHVzaGVkIGRhdGEgbWlnaHQgYWNrbm93bGVkZ2UgZGlydHkgYXR0cmlidXRlcyBhcyBjb25maXJtZWQuCiAgICAgICBAbWV0aG9kIHVwZGF0ZUNoYW5nZWRBdHRyaWJ1dGVzCiAgICAgIEBwcml2YXRlCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3VwZGF0ZUNoYW5nZWRBdHRyaWJ1dGVzID0gZnVuY3Rpb24gX3VwZGF0ZUNoYW5nZWRBdHRyaWJ1dGVzKCkgewogICAgICB2YXIgY2hhbmdlZEF0dHJpYnV0ZXMgPSB0aGlzLmNoYW5nZWRBdHRyaWJ1dGVzKCk7CiAgICAgIHZhciBjaGFuZ2VkQXR0cmlidXRlTmFtZXMgPSBPYmplY3Qua2V5cyhjaGFuZ2VkQXR0cmlidXRlcyk7CiAgICAgIHZhciBhdHRycyA9IHRoaXMuX2F0dHJpYnV0ZXM7CgogICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gY2hhbmdlZEF0dHJpYnV0ZU5hbWVzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGF0dHJpYnV0ZSA9IGNoYW5nZWRBdHRyaWJ1dGVOYW1lc1tpXTsKICAgICAgICB2YXIgZGF0YSA9IGNoYW5nZWRBdHRyaWJ1dGVzW2F0dHJpYnV0ZV07CiAgICAgICAgdmFyIG9sZERhdGEgPSBkYXRhWzBdOwogICAgICAgIHZhciBuZXdEYXRhID0gZGF0YVsxXTsKCiAgICAgICAgaWYgKG9sZERhdGEgPT09IG5ld0RhdGEpIHsKICAgICAgICAgIGRlbGV0ZSBhdHRyc1thdHRyaWJ1dGVdOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgLyoKICAgICAgUmV0dXJucyBhbiBvYmplY3QsIHdob3NlIGtleXMgYXJlIGNoYW5nZWQgcHJvcGVydGllcywgYW5kIHZhbHVlIGlzIGFuCiAgICAgIFtvbGRQcm9wLCBuZXdQcm9wXSBhcnJheS4KICAgICAgIEBtZXRob2QgY2hhbmdlZEF0dHJpYnV0ZXMKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmNoYW5nZWRBdHRyaWJ1dGVzID0gZnVuY3Rpb24gY2hhbmdlZEF0dHJpYnV0ZXMoKSB7CiAgICAgIHZhciBvbGREYXRhID0gdGhpcy5fZGF0YTsKICAgICAgdmFyIGN1cnJlbnREYXRhID0gdGhpcy5fYXR0cmlidXRlczsKICAgICAgdmFyIGluRmxpZ2h0RGF0YSA9IHRoaXMuX2luRmxpZ2h0QXR0cmlidXRlczsKICAgICAgdmFyIG5ld0RhdGEgPSBFbWJlci5hc3NpZ24oe30sIGluRmxpZ2h0RGF0YSwgY3VycmVudERhdGEpOwogICAgICB2YXIgZGlmZkRhdGEgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB2YXIgbmV3RGF0YUtleXMgPSBPYmplY3Qua2V5cyhuZXdEYXRhKTsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBuZXdEYXRhS2V5cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgIHZhciBfa2V5ID0gbmV3RGF0YUtleXNbaV07CiAgICAgICAgZGlmZkRhdGFbX2tleV0gPSBbb2xkRGF0YVtfa2V5XSwgbmV3RGF0YVtfa2V5XV07CiAgICAgIH0KCiAgICAgIHJldHVybiBkaWZmRGF0YTsKICAgIH07CgogICAgX3Byb3RvLmlzTmV3ID0gZnVuY3Rpb24gaXNOZXcoKSB7CiAgICAgIHJldHVybiB0aGlzLl9pc05ldzsKICAgIH07CgogICAgX3Byb3RvLnJvbGxiYWNrQXR0cmlidXRlcyA9IGZ1bmN0aW9uIHJvbGxiYWNrQXR0cmlidXRlcygpIHsKICAgICAgdmFyIGRpcnR5S2V5czsKICAgICAgdGhpcy5faXNEZWxldGVkID0gZmFsc2U7CgogICAgICBpZiAodGhpcy5oYXNDaGFuZ2VkQXR0cmlidXRlcygpKSB7CiAgICAgICAgZGlydHlLZXlzID0gT2JqZWN0LmtleXModGhpcy5fYXR0cmlidXRlcyk7CiAgICAgICAgdGhpcy5fYXR0cmlidXRlcyA9IG51bGw7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLmlzTmV3KCkpIHsKICAgICAgICB0aGlzLnJlbW92ZUZyb21JbnZlcnNlUmVsYXRpb25zaGlwcyh0cnVlKTsKICAgICAgICB0aGlzLl9pc0RlbGV0ZWQgPSB0cnVlOwogICAgICAgIHRoaXMuX2lzTmV3ID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIHRoaXMuX2luRmxpZ2h0QXR0cmlidXRlcyA9IG51bGw7CgogICAgICB0aGlzLl9jbGVhckVycm9ycygpOwoKICAgICAgdGhpcy5ub3RpZnlTdGF0ZUNoYW5nZSgpOwogICAgICByZXR1cm4gZGlydHlLZXlzOwogICAgfTsKCiAgICBfcHJvdG8uX2RlbGV0aW9uQ29uZmlybWVkID0gZnVuY3Rpb24gX2RlbGV0aW9uQ29uZmlybWVkKCkgewogICAgICB0aGlzLnJlbW92ZUZyb21JbnZlcnNlUmVsYXRpb25zaGlwcygpOwogICAgfTsKCiAgICBfcHJvdG8uZGlkQ29tbWl0ID0gZnVuY3Rpb24gZGlkQ29tbWl0KGRhdGEpIHsKICAgICAgaWYgKHRoaXMuX2lzRGVsZXRlZCkgewogICAgICAgIHRoaXMuX2RlbGV0aW9uQ29uZmlybWVkKCk7CgogICAgICAgIHRoaXMuX2lzRGVsZXRpb25Db21taXRlZCA9IHRydWU7CiAgICAgIH0KCiAgICAgIHRoaXMuX2lzTmV3ID0gZmFsc2U7CiAgICAgIHZhciBuZXdDYW5vbmljYWxBdHRyaWJ1dGVzID0gbnVsbDsKCiAgICAgIGlmIChkYXRhKSB7CiAgICAgICAgLy8gdGhpcy5zdG9yZS5faW50ZXJuYWxNb2RlbERpZFJlY2VpdmVSZWxhdGlvbnNoaXBEYXRhKHRoaXMubW9kZWxOYW1lLCB0aGlzLmlkLCBkYXRhLnJlbGF0aW9uc2hpcHMpOwogICAgICAgIGlmIChkYXRhLnJlbGF0aW9uc2hpcHMpIHsKICAgICAgICAgIHRoaXMuX3NldHVwUmVsYXRpb25zaGlwcyhkYXRhKTsKICAgICAgICB9CgogICAgICAgIGlmIChkYXRhLmlkKSB7CiAgICAgICAgICAvLyBkaWRDb21taXQgcHJvdmlkZWQgYW4gSUQsIG5vdGlmeSB0aGUgc3RvcmUgb2YgaXQKICAgICAgICAgIHRoaXMuc3RvcmVXcmFwcGVyLnNldFJlY29yZElkKHRoaXMubW9kZWxOYW1lLCBkYXRhLmlkLCB0aGlzLmNsaWVudElkKTsKICAgICAgICAgIHRoaXMuaWQgPSBjb2VyY2VJZChkYXRhLmlkKTsKICAgICAgICB9CgogICAgICAgIG5ld0Nhbm9uaWNhbEF0dHJpYnV0ZXMgPSBkYXRhLmF0dHJpYnV0ZXMgfHwgbnVsbDsKICAgICAgfQoKICAgICAgdmFyIGNoYW5nZWRLZXlzID0gdGhpcy5fY2hhbmdlZEtleXMobmV3Q2Fub25pY2FsQXR0cmlidXRlcyk7CgogICAgICBFbWJlci5hc3NpZ24odGhpcy5fZGF0YSwgdGhpcy5fX2luRmxpZ2h0QXR0cmlidXRlcywgbmV3Q2Fub25pY2FsQXR0cmlidXRlcyk7CiAgICAgIHRoaXMuX2luRmxpZ2h0QXR0cmlidXRlcyA9IG51bGw7CgogICAgICB0aGlzLl91cGRhdGVDaGFuZ2VkQXR0cmlidXRlcygpOwoKICAgICAgdGhpcy5fY2xlYXJFcnJvcnMoKTsKCiAgICAgIHRoaXMubm90aWZ5U3RhdGVDaGFuZ2UoKTsKICAgICAgcmV0dXJuIGNoYW5nZWRLZXlzOwogICAgfTsKCiAgICBfcHJvdG8ubm90aWZ5U3RhdGVDaGFuZ2UgPSBmdW5jdGlvbiBub3RpZnlTdGF0ZUNoYW5nZSgpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX1NUQVRFKSB7CiAgICAgICAgdGhpcy5zdG9yZVdyYXBwZXIubm90aWZ5U3RhdGVDaGFuZ2UodGhpcy5tb2RlbE5hbWUsIHRoaXMuaWQsIHRoaXMuY2xpZW50SWQpOwogICAgICB9CiAgICB9IC8vIGdldCBSZXNvdXJjZUlkZW50aWZpZXJzIGZvciAiY3VycmVudCBzdGF0ZSIKICAgIDsKCiAgICBfcHJvdG8uZ2V0SGFzTWFueSA9IGZ1bmN0aW9uIGdldEhhc01hbnkoa2V5KSB7CiAgICAgIHJldHVybiB0aGlzLl9yZWxhdGlvbnNoaXBzLmdldChrZXkpLmdldERhdGEoKTsKICAgIH0gLy8gc2V0IGEgbmV3ICJjdXJyZW50IHN0YXRlIiB2aWEgUmVzb3VyY2VJZGVudGlmaWVycwogICAgOwoKICAgIF9wcm90by5zZXREaXJ0eUhhc01hbnkgPSBmdW5jdGlvbiBzZXREaXJ0eUhhc01hbnkoa2V5LCByZWNvcmREYXRhcykgewogICAgICB2YXIgcmVsYXRpb25zaGlwID0gdGhpcy5fcmVsYXRpb25zaGlwcy5nZXQoa2V5KTsKCiAgICAgIHJlbGF0aW9uc2hpcC5jbGVhcigpOwogICAgICByZWxhdGlvbnNoaXAuYWRkUmVjb3JkRGF0YXMocmVjb3JkRGF0YXMpOwogICAgfSAvLyBhcHBlbmQgdG8gImN1cnJlbnQgc3RhdGUiIHZpYSBSZWNvcmREYXRhcwogICAgOwoKICAgIF9wcm90by5hZGRUb0hhc01hbnkgPSBmdW5jdGlvbiBhZGRUb0hhc01hbnkoa2V5LCByZWNvcmREYXRhcywgaWR4KSB7CiAgICAgIHRoaXMuX3JlbGF0aW9uc2hpcHMuZ2V0KGtleSkuYWRkUmVjb3JkRGF0YXMocmVjb3JkRGF0YXMsIGlkeCk7CiAgICB9IC8vIHJlbW92ZSBmcm9tICJjdXJyZW50IHN0YXRlIiB2aWEgUmVjb3JkRGF0YXMKICAgIDsKCiAgICBfcHJvdG8ucmVtb3ZlRnJvbUhhc01hbnkgPSBmdW5jdGlvbiByZW1vdmVGcm9tSGFzTWFueShrZXksIHJlY29yZERhdGFzKSB7CiAgICAgIHRoaXMuX3JlbGF0aW9uc2hpcHMuZ2V0KGtleSkucmVtb3ZlUmVjb3JkRGF0YXMocmVjb3JkRGF0YXMpOwogICAgfTsKCiAgICBfcHJvdG8uY29tbWl0V2FzUmVqZWN0ZWQgPSBmdW5jdGlvbiBjb21taXRXYXNSZWplY3RlZChpZGVudGlmaWVyLCBlcnJvcnMpIHsKICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh0aGlzLl9pbkZsaWdodEF0dHJpYnV0ZXMpOwoKICAgICAgaWYgKGtleXMubGVuZ3RoID4gMCkgewogICAgICAgIHZhciBhdHRycyA9IHRoaXMuX2F0dHJpYnV0ZXM7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgaWYgKGF0dHJzW2tleXNbaV1dID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgYXR0cnNba2V5c1tpXV0gPSB0aGlzLl9pbkZsaWdodEF0dHJpYnV0ZXNba2V5c1tpXV07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICB0aGlzLl9pbkZsaWdodEF0dHJpYnV0ZXMgPSBudWxsOwoKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX0VSUk9SUykgewogICAgICAgIGlmIChlcnJvcnMpIHsKICAgICAgICAgIHRoaXMuX2Vycm9ycyA9IGVycm9yczsKICAgICAgICB9CgogICAgICAgIHRoaXMuc3RvcmVXcmFwcGVyLm5vdGlmeUVycm9yc0NoYW5nZSh0aGlzLm1vZGVsTmFtZSwgdGhpcy5pZCwgdGhpcy5jbGllbnRJZCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmdldEJlbG9uZ3NUbyA9IGZ1bmN0aW9uIGdldEJlbG9uZ3NUbyhrZXkpIHsKICAgICAgcmV0dXJuIHRoaXMuX3JlbGF0aW9uc2hpcHMuZ2V0KGtleSkuZ2V0RGF0YSgpOwogICAgfTsKCiAgICBfcHJvdG8uc2V0RGlydHlCZWxvbmdzVG8gPSBmdW5jdGlvbiBzZXREaXJ0eUJlbG9uZ3NUbyhrZXksIHJlY29yZERhdGEpIHsKICAgICAgdGhpcy5fcmVsYXRpb25zaGlwcy5nZXQoa2V5KS5zZXRSZWNvcmREYXRhKHJlY29yZERhdGEpOwogICAgfTsKCiAgICBfcHJvdG8uc2V0RGlydHlBdHRyaWJ1dGUgPSBmdW5jdGlvbiBzZXREaXJ0eUF0dHJpYnV0ZShrZXksIHZhbHVlKSB7CiAgICAgIHZhciBvcmlnaW5hbFZhbHVlOyAvLyBBZGQgdGhlIG5ldyB2YWx1ZSB0byB0aGUgY2hhbmdlZCBhdHRyaWJ1dGVzIGhhc2gKCiAgICAgIHRoaXMuX2F0dHJpYnV0ZXNba2V5XSA9IHZhbHVlOwoKICAgICAgaWYgKGtleSBpbiB0aGlzLl9pbkZsaWdodEF0dHJpYnV0ZXMpIHsKICAgICAgICBvcmlnaW5hbFZhbHVlID0gdGhpcy5faW5GbGlnaHRBdHRyaWJ1dGVzW2tleV07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgb3JpZ2luYWxWYWx1ZSA9IHRoaXMuX2RhdGFba2V5XTsKICAgICAgfSAvLyBJZiB3ZSB3ZW50IGJhY2sgdG8gb3VyIG9yaWdpbmFsIHZhbHVlLCB3ZSBzaG91bGRuJ3Qga2VlcCB0aGUgYXR0cmlidXRlIGFyb3VuZCBhbnltb3JlCgoKICAgICAgaWYgKHZhbHVlID09PSBvcmlnaW5hbFZhbHVlKSB7CiAgICAgICAgZGVsZXRlIHRoaXMuX2F0dHJpYnV0ZXNba2V5XTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uZ2V0QXR0ciA9IGZ1bmN0aW9uIGdldEF0dHIoa2V5KSB7CiAgICAgIGlmIChrZXkgaW4gdGhpcy5fYXR0cmlidXRlcykgewogICAgICAgIHJldHVybiB0aGlzLl9hdHRyaWJ1dGVzW2tleV07CiAgICAgIH0gZWxzZSBpZiAoa2V5IGluIHRoaXMuX2luRmxpZ2h0QXR0cmlidXRlcykgewogICAgICAgIHJldHVybiB0aGlzLl9pbkZsaWdodEF0dHJpYnV0ZXNba2V5XTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gdGhpcy5fZGF0YVtrZXldOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5oYXNBdHRyID0gZnVuY3Rpb24gaGFzQXR0cihrZXkpIHsKICAgICAgcmV0dXJuIGtleSBpbiB0aGlzLl9hdHRyaWJ1dGVzIHx8IGtleSBpbiB0aGlzLl9pbkZsaWdodEF0dHJpYnV0ZXMgfHwga2V5IGluIHRoaXMuX2RhdGE7CiAgICB9OwoKICAgIF9wcm90by51bmxvYWRSZWNvcmQgPSBmdW5jdGlvbiB1bmxvYWRSZWNvcmQoKSB7CiAgICAgIGlmICh0aGlzLmlzRGVzdHJveWVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9kZXN0cm95UmVsYXRpb25zaGlwcygpOwoKICAgICAgdGhpcy5yZXNldCgpOwoKICAgICAgaWYgKCF0aGlzLl9zY2hlZHVsZWREZXN0cm95KSB7CiAgICAgICAgdGhpcy5fc2NoZWR1bGVkRGVzdHJveSA9IEVtYmVyLnJ1bi5iYWNrYnVybmVyLnNjaGVkdWxlKCdkZXN0cm95JywgdGhpcywgJ19jbGVhbnVwT3JwaGFuZWRSZWNvcmREYXRhcycpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fY2xlYW51cE9ycGhhbmVkUmVjb3JkRGF0YXMgPSBmdW5jdGlvbiBfY2xlYW51cE9ycGhhbmVkUmVjb3JkRGF0YXMoKSB7CiAgICAgIHZhciByZWxhdGVkUmVjb3JkRGF0YXMgPSB0aGlzLl9hbGxSZWxhdGVkUmVjb3JkRGF0YXMoKTsKCiAgICAgIGlmIChhcmVBbGxNb2RlbHNVbmxvYWRlZChyZWxhdGVkUmVjb3JkRGF0YXMpKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZWxhdGVkUmVjb3JkRGF0YXMubGVuZ3RoOyArK2kpIHsKICAgICAgICAgIHZhciByZWNvcmREYXRhID0gcmVsYXRlZFJlY29yZERhdGFzW2ldOwoKICAgICAgICAgIGlmICghcmVjb3JkRGF0YS5pc0Rlc3Ryb3llZCkgewogICAgICAgICAgICByZWNvcmREYXRhLmRlc3Ryb3koKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHRoaXMuX3NjaGVkdWxlZERlc3Ryb3kgPSBudWxsOwogICAgfTsKCiAgICBfcHJvdG8uZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3JlbGF0aW9uc2hpcHMuZm9yRWFjaChmdW5jdGlvbiAobmFtZSwgcmVsKSB7CiAgICAgICAgcmV0dXJuIHJlbC5kZXN0cm95KCk7CiAgICAgIH0pOwoKICAgICAgdGhpcy5pc0Rlc3Ryb3llZCA9IHRydWU7CiAgICAgIHRoaXMuc3RvcmVXcmFwcGVyLmRpc2Nvbm5lY3RSZWNvcmQodGhpcy5tb2RlbE5hbWUsIHRoaXMuaWQsIHRoaXMuY2xpZW50SWQpOwogICAgfTsKCiAgICBfcHJvdG8uaXNSZWNvcmRJblVzZSA9IGZ1bmN0aW9uIGlzUmVjb3JkSW5Vc2UoKSB7CiAgICAgIHJldHVybiB0aGlzLnN0b3JlV3JhcHBlci5pc1JlY29yZEluVXNlKHRoaXMubW9kZWxOYW1lLCB0aGlzLmlkLCB0aGlzLmNsaWVudElkKTsKICAgIH0KICAgIC8qKgogICAgICBDb21wdXRlcyB0aGUgc2V0IG9mIGludGVybmFsIG1vZGVscyByZWFjaGFibGUgZnJvbSBgdGhpc2AgYWNyb3NzIGV4YWN0bHkgb25lCiAgICAgIHJlbGF0aW9uc2hpcC4KICAgICAgIEByZXR1cm4ge0FycmF5fSBBbiBhcnJheSBjb250YWluaW5nIHRoZSBpbnRlcm5hbCBtb2RlbHMgdGhhdCBgdGhpc2AgYmVsb25ncwogICAgICB0byBvciBoYXMgbWFueS4KICAgICAqLwogICAgOwoKICAgIF9wcm90by5fZGlyZWN0bHlSZWxhdGVkUmVjb3JkRGF0YXMgPSBmdW5jdGlvbiBfZGlyZWN0bHlSZWxhdGVkUmVjb3JkRGF0YXMoKSB7CiAgICAgIHZhciBhcnJheSA9IFtdOwoKICAgICAgdGhpcy5fcmVsYXRpb25zaGlwcy5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lLCByZWwpIHsKICAgICAgICB2YXIgbWVtYmVycyA9IHJlbC5tZW1iZXJzLmxpc3Q7CiAgICAgICAgdmFyIGNhbm9uaWNhbE1lbWJlcnMgPSByZWwuY2Fub25pY2FsTWVtYmVycy5saXN0OwogICAgICAgIGFycmF5ID0gYXJyYXkuY29uY2F0KG1lbWJlcnMsIGNhbm9uaWNhbE1lbWJlcnMpOwogICAgICB9KTsKCiAgICAgIHJldHVybiBhcnJheTsKICAgIH0KICAgIC8qKgogICAgICBDb21wdXRlcyB0aGUgc2V0IG9mIGludGVybmFsIG1vZGVscyByZWFjaGFibGUgZnJvbSB0aGlzIGludGVybmFsIG1vZGVsLgogICAgICAgUmVhY2hhYmlsaXR5IGlzIGRldGVybWluZWQgb3ZlciB0aGUgcmVsYXRpb25zaGlwIGdyYXBoIChpZSBhIGdyYXBoIHdoZXJlCiAgICAgIG5vZGVzIGFyZSBpbnRlcm5hbCBtb2RlbHMgYW5kIGVkZ2VzIGFyZSBiZWxvbmdzIHRvIG9yIGhhcyBtYW55CiAgICAgIHJlbGF0aW9uc2hpcHMpLgogICAgICAgQHJldHVybiB7QXJyYXl9IEFuIGFycmF5IGluY2x1ZGluZyBgdGhpc2AgYW5kIGFsbCBpbnRlcm5hbCBtb2RlbHMgcmVhY2hhYmxlCiAgICAgIGZyb20gYHRoaXNgLgogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX2FsbFJlbGF0ZWRSZWNvcmREYXRhcyA9IGZ1bmN0aW9uIF9hbGxSZWxhdGVkUmVjb3JkRGF0YXMoKSB7CiAgICAgIHZhciBhcnJheSA9IFtdOwogICAgICB2YXIgcXVldWUgPSBbXTsKICAgICAgdmFyIGJmc0lkID0gbmV4dEJmc0lkKys7CiAgICAgIHF1ZXVlLnB1c2godGhpcyk7CiAgICAgIHRoaXMuX2Jmc0lkID0gYmZzSWQ7CgogICAgICB3aGlsZSAocXVldWUubGVuZ3RoID4gMCkgewogICAgICAgIHZhciBub2RlID0gcXVldWUuc2hpZnQoKTsKICAgICAgICBhcnJheS5wdXNoKG5vZGUpOwoKICAgICAgICB2YXIgcmVsYXRlZCA9IG5vZGUuX2RpcmVjdGx5UmVsYXRlZFJlY29yZERhdGFzKCk7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVsYXRlZC5sZW5ndGg7ICsraSkgewogICAgICAgICAgdmFyIHJlY29yZERhdGEgPSByZWxhdGVkW2ldOwoKICAgICAgICAgIGlmIChyZWNvcmREYXRhIGluc3RhbmNlb2YgUmVjb3JkRGF0YURlZmF1bHQpIHsKCiAgICAgICAgICAgIGlmIChyZWNvcmREYXRhLl9iZnNJZCA8IGJmc0lkKSB7CiAgICAgICAgICAgICAgcXVldWUucHVzaChyZWNvcmREYXRhKTsKICAgICAgICAgICAgICByZWNvcmREYXRhLl9iZnNJZCA9IGJmc0lkOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gYXJyYXk7CiAgICB9OwoKICAgIF9wcm90by5pc0F0dHJEaXJ0eSA9IGZ1bmN0aW9uIGlzQXR0ckRpcnR5KGtleSkgewogICAgICBpZiAodGhpcy5fYXR0cmlidXRlc1trZXldID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIHZhciBvcmlnaW5hbFZhbHVlOwoKICAgICAgaWYgKHRoaXMuX2luRmxpZ2h0QXR0cmlidXRlc1trZXldICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBvcmlnaW5hbFZhbHVlID0gdGhpcy5faW5GbGlnaHRBdHRyaWJ1dGVzW2tleV07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgb3JpZ2luYWxWYWx1ZSA9IHRoaXMuX2RhdGFba2V5XTsKICAgICAgfQoKICAgICAgcmV0dXJuIG9yaWdpbmFsVmFsdWUgIT09IHRoaXMuX2F0dHJpYnV0ZXNba2V5XTsKICAgIH07CgogICAgLyoqCiAgICAgKiBSZWNlaXZlcyBvcHRpb25zIHBhc3NlZCB0byBgc3RvcmUuY3JlYXRlUmVjb3JkYCBhbmQgaXMgZ2l2ZW4gdGhlIG9wcG9ydHVuaXR5CiAgICAgKiB0byBoYW5kbGUgdGhlbS4KICAgICAqCiAgICAgKiBUaGUgcmV0dXJuIHZhbHVlIGlzIGFuIG9iamVjdCBvZiBvcHRpb25zIHRvIHBhc3MgdG8gYFJlY29yZC5jcmVhdGUoKWAKICAgICAqCiAgICAgKiBAcGFyYW0gb3B0aW9ucwogICAgICogQHByaXZhdGUKICAgICAqLwogICAgX3Byb3RvLl9pbml0UmVjb3JkQ3JlYXRlT3B0aW9ucyA9IGZ1bmN0aW9uIF9pbml0UmVjb3JkQ3JlYXRlT3B0aW9ucyhvcHRpb25zKSB7CiAgICAgIHZhciBjcmVhdGVPcHRpb25zID0ge307CgogICAgICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdmFyIF9tb2RlbE5hbWUyID0gdGhpcy5tb2RlbE5hbWUsCiAgICAgICAgICAgIF9zdG9yZVdyYXBwZXI0ID0gdGhpcy5zdG9yZVdyYXBwZXI7CgogICAgICAgIHZhciBhdHRyaWJ1dGVEZWZzID0gX3N0b3JlV3JhcHBlcjQuYXR0cmlidXRlc0RlZmluaXRpb25Gb3IoX21vZGVsTmFtZTIpOwoKICAgICAgICB2YXIgcmVsYXRpb25zaGlwRGVmcyA9IF9zdG9yZVdyYXBwZXI0LnJlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKF9tb2RlbE5hbWUyKTsKCiAgICAgICAgdmFyIHJlbGF0aW9uc2hpcHMgPSB0aGlzLl9yZWxhdGlvbnNoaXBzOwogICAgICAgIHZhciBwcm9wZXJ0eU5hbWVzID0gT2JqZWN0LmtleXMob3B0aW9ucyk7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcGVydHlOYW1lcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgdmFyIG5hbWUgPSBwcm9wZXJ0eU5hbWVzW2ldOwogICAgICAgICAgdmFyIHByb3BlcnR5VmFsdWUgPSBvcHRpb25zW25hbWVdOwoKICAgICAgICAgIGlmIChuYW1lID09PSAnaWQnKSB7CiAgICAgICAgICAgIHRoaXMuaWQgPSBwcm9wZXJ0eVZhbHVlOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KCiAgICAgICAgICB2YXIgZmllbGRUeXBlID0gcmVsYXRpb25zaGlwRGVmc1tuYW1lXSB8fCBhdHRyaWJ1dGVEZWZzW25hbWVdOwogICAgICAgICAgdmFyIGtpbmQgPSBmaWVsZFR5cGUgIT09IHVuZGVmaW5lZCA/IGZpZWxkVHlwZS5raW5kIDogbnVsbDsKICAgICAgICAgIHZhciByZWxhdGlvbnNoaXAgPSB2b2lkIDA7CgogICAgICAgICAgc3dpdGNoIChraW5kKSB7CiAgICAgICAgICAgIGNhc2UgJ2F0dHJpYnV0ZSc6CiAgICAgICAgICAgICAgdGhpcy5zZXREaXJ0eUF0dHJpYnV0ZShuYW1lLCBwcm9wZXJ0eVZhbHVlKTsKICAgICAgICAgICAgICBicmVhazsKCiAgICAgICAgICAgIGNhc2UgJ2JlbG9uZ3NUbyc6CiAgICAgICAgICAgICAgdGhpcy5zZXREaXJ0eUJlbG9uZ3NUbyhuYW1lLCBwcm9wZXJ0eVZhbHVlKTsKICAgICAgICAgICAgICByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXBzLmdldChuYW1lKTsKICAgICAgICAgICAgICByZWxhdGlvbnNoaXAuc2V0SGFzQW55UmVsYXRpb25zaGlwRGF0YSh0cnVlKTsKICAgICAgICAgICAgICByZWxhdGlvbnNoaXAuc2V0UmVsYXRpb25zaGlwSXNFbXB0eShmYWxzZSk7CiAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICBjYXNlICdoYXNNYW55JzoKICAgICAgICAgICAgICB0aGlzLnNldERpcnR5SGFzTWFueShuYW1lLCBwcm9wZXJ0eVZhbHVlKTsKICAgICAgICAgICAgICByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXBzLmdldChuYW1lKTsKICAgICAgICAgICAgICByZWxhdGlvbnNoaXAuc2V0SGFzQW55UmVsYXRpb25zaGlwRGF0YSh0cnVlKTsKICAgICAgICAgICAgICByZWxhdGlvbnNoaXAuc2V0UmVsYXRpb25zaGlwSXNFbXB0eShmYWxzZSk7CiAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgIC8vIHJlZmxlY3QgYmFjayAocGFzcy10aHJ1KSB1bmtub3duIHByb3BlcnRpZXMKICAgICAgICAgICAgICBjcmVhdGVPcHRpb25zW25hbWVdID0gcHJvcGVydHlWYWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBjcmVhdGVPcHRpb25zOwogICAgfQogICAgLyoKICAgICAgICBUT0RPIElHT1IgQU5EIERBVklEIHRoaXMgc2hvdWxkbid0IGJlIHB1YmxpYwogICAgIFRoaXMgbWV0aG9kIHNob3VsZCBvbmx5IGJlIGNhbGxlZCBieSByZWNvcmRzIGluIHRoZSBgaXNOZXcoKWAgc3RhdGUgT1Igb25jZSB0aGUgcmVjb3JkCiAgICAgaGFzIGJlZW4gZGVsZXRlZCBhbmQgdGhhdCBkZWxldGlvbiBoYXMgYmVlbiBwZXJzaXN0ZWQuCiAgICAgIEl0IHdpbGwgcmVtb3ZlIHRoaXMgcmVjb3JkIGZyb20gYW55IGFzc29jaWF0ZWQgcmVsYXRpb25zaGlwcy4KICAgICAgSWYgYGlzTmV3YCBpcyB0cnVlIChkZWZhdWx0IGZhbHNlKSwgaXQgd2lsbCBhbHNvIGNvbXBsZXRlbHkgcmVzZXQgYWxsCiAgICAgIHJlbGF0aW9uc2hpcHMgdG8gYW4gZW1wdHkgc3RhdGUgYXMgd2VsbC4KICAgICAgIEBtZXRob2QgcmVtb3ZlRnJvbUludmVyc2VSZWxhdGlvbnNoaXBzCiAgICAgIEBwYXJhbSB7Qm9vbGVhbn0gaXNOZXcgd2hldGhlciB0byB1bmxvYWQgZnJvbSB0aGUgYGlzTmV3YCBwZXJzcGVjdGl2ZQogICAgICBAcHJpdmF0ZQogICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlbW92ZUZyb21JbnZlcnNlUmVsYXRpb25zaGlwcyA9IGZ1bmN0aW9uIHJlbW92ZUZyb21JbnZlcnNlUmVsYXRpb25zaGlwcyhpc05ldykgewogICAgICBpZiAoaXNOZXcgPT09IHZvaWQgMCkgewogICAgICAgIGlzTmV3ID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIHRoaXMuX3JlbGF0aW9uc2hpcHMuZm9yRWFjaChmdW5jdGlvbiAobmFtZSwgcmVsKSB7CiAgICAgICAgcmVsLnJlbW92ZUNvbXBsZXRlbHlGcm9tSW52ZXJzZSgpOwoKICAgICAgICBpZiAoaXNOZXcgPT09IHRydWUpIHsKICAgICAgICAgIHJlbC5jbGVhcigpOwogICAgICAgIH0KICAgICAgfSk7CgogICAgICB2YXIgaW1wbGljaXRSZWxhdGlvbnNoaXBzID0gdGhpcy5faW1wbGljaXRSZWxhdGlvbnNoaXBzOwogICAgICB0aGlzLl9faW1wbGljaXRSZWxhdGlvbnNoaXBzID0gbnVsbDsKICAgICAgT2JqZWN0LmtleXMoaW1wbGljaXRSZWxhdGlvbnNoaXBzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICB2YXIgcmVsID0gaW1wbGljaXRSZWxhdGlvbnNoaXBzW2tleV07CiAgICAgICAgcmVsLnJlbW92ZUNvbXBsZXRlbHlGcm9tSW52ZXJzZSgpOwoKICAgICAgICBpZiAoaXNOZXcgPT09IHRydWUpIHsKICAgICAgICAgIHJlbC5jbGVhcigpOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5fZGVzdHJveVJlbGF0aW9uc2hpcHMgPSBmdW5jdGlvbiBfZGVzdHJveVJlbGF0aW9uc2hpcHMoKSB7CiAgICAgIHZhciByZWxhdGlvbnNoaXBzID0gdGhpcy5fcmVsYXRpb25zaGlwczsKICAgICAgcmVsYXRpb25zaGlwcy5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lLCByZWwpIHsKICAgICAgICByZXR1cm4gZGVzdHJveVJlbGF0aW9uc2hpcChyZWwpOwogICAgICB9KTsKICAgICAgdmFyIGltcGxpY2l0UmVsYXRpb25zaGlwcyA9IHRoaXMuX2ltcGxpY2l0UmVsYXRpb25zaGlwczsKICAgICAgdGhpcy5fX2ltcGxpY2l0UmVsYXRpb25zaGlwcyA9IG51bGw7CiAgICAgIE9iamVjdC5rZXlzKGltcGxpY2l0UmVsYXRpb25zaGlwcykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgdmFyIHJlbCA9IGltcGxpY2l0UmVsYXRpb25zaGlwc1trZXldOwogICAgICAgIGRlc3Ryb3lSZWxhdGlvbnNoaXAocmVsKTsKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5jbGllbnREaWRDcmVhdGUgPSBmdW5jdGlvbiBjbGllbnREaWRDcmVhdGUoKSB7CiAgICAgIHRoaXMuX2lzTmV3ID0gdHJ1ZTsKICAgIH0KICAgIC8qCiAgICAgIEVtYmVyIERhdGEgaGFzIDMgYnVja2V0cyBmb3Igc3RvcmluZyB0aGUgdmFsdWUgb2YgYW4gYXR0cmlidXRlIG9uIGFuIGludGVybmFsTW9kZWwuCiAgICAgICBgX2RhdGFgIGhvbGRzIGFsbCBvZiB0aGUgYXR0cmlidXRlcyB0aGF0IGhhdmUgYmVlbiBhY2tub3dsZWRnZWQgYnkKICAgICAgYSBiYWNrZW5kIHZpYSB0aGUgYWRhcHRlci4gV2hlbiByb2xsYmFja0F0dHJpYnV0ZXMgaXMgY2FsbGVkIG9uIGEgbW9kZWwgYWxsCiAgICAgIGF0dHJpYnV0ZXMgd2lsbCByZXZlcnQgdG8gdGhlIHJlY29yZCdzIHN0YXRlIGluIGBfZGF0YWAuCiAgICAgICBgX2F0dHJpYnV0ZXNgIGhvbGRzIGFueSBjaGFuZ2UgdGhlIHVzZXIgaGFzIG1hZGUgdG8gYW4gYXR0cmlidXRlCiAgICAgIHRoYXQgaGFzIG5vdCBiZWVuIGFja25vd2xlZGdlZCBieSB0aGUgYWRhcHRlci4gQW55IHZhbHVlcyBpbgogICAgICBgX2F0dHJpYnV0ZXNgIGFyZSBoYXZlIHByaW9yaXR5IG92ZXIgdmFsdWVzIGluIGBfZGF0YWAuCiAgICAgICBgX2luRmxpZ2h0QXR0cmlidXRlc2AuIFdoZW4gYSByZWNvcmQgaXMgYmVpbmcgc3luY2VkIHdpdGggdGhlCiAgICAgIGJhY2tlbmQgdGhlIHZhbHVlcyBpbiBgX2F0dHJpYnV0ZXNgIGFyZSBjb3BpZWQgdG8KICAgICAgYF9pbkZsaWdodEF0dHJpYnV0ZXNgLiBUaGlzIHdheSBpZiB0aGUgYmFja2VuZCBhY2tub3dsZWRnZXMgdGhlCiAgICAgIHNhdmUgYnV0IGRvZXMgbm90IHJldHVybiB0aGUgbmV3IHN0YXRlIEVtYmVyIERhdGEgY2FuIGNvcHkgdGhlCiAgICAgIHZhbHVlcyBmcm9tIGBfaW5GbGlnaHRBdHRyaWJ1dGVzYCB0byBgX2RhdGFgLiBXaXRob3V0IGhhdmluZyB0bwogICAgICB3b3JyeSBhYm91dCBjaGFuZ2VzIG1hZGUgdG8gYF9hdHRyaWJ1dGVzYCB3aGlsZSB0aGUgc2F2ZSB3YXMKICAgICAgaGFwcGVuaWduLgogICAgICAgIENoYW5nZWQga2V5cyBidWlsZHMgYSBsaXN0IG9mIGFsbCBvZiB0aGUgdmFsdWVzIHRoYXQgbWF5IGhhdmUgYmVlbgogICAgICBjaGFuZ2VkIGJ5IHRoZSBiYWNrZW5kIGFmdGVyIGEgc3VjY2Vzc2Z1bCBzYXZlLgogICAgICAgSXQgZG9lcyB0aGlzIGJ5IGl0ZXJhdGluZyBvdmVyIGVhY2gga2V5LCB2YWx1ZSBwYWlyIGluIHRoZSBwYXlsb2FkCiAgICAgIHJldHVybmVkIGZyb20gdGhlIHNlcnZlciBhZnRlciBhIHNhdmUuIElmIHRoZSBga2V5YCBpcyBmb3VuZCBpbgogICAgICBgX2F0dHJpYnV0ZXNgIHRoZW4gdGhlIHVzZXIgaGFzIGEgbG9jYWwgY2hhbmdlZCB0byB0aGUgYXR0cmlidXRlCiAgICAgIHRoYXQgaGFzIG5vdCBiZWVuIHN5bmNlZCB3aXRoIHRoZSBzZXJ2ZXIgYW5kIHRoZSBrZXkgaXMgbm90CiAgICAgIGluY2x1ZGVkIGluIHRoZSBsaXN0IG9mIGNoYW5nZWQga2V5cy4KICAgIAogICAgICBJZiB0aGUgdmFsdWUsIGZvciBhIGtleSBkaWZmZXJzIGZyb20gdGhlIHZhbHVlIGluIHdoYXQgRW1iZXIgRGF0YQogICAgICBiZWxpZXZlcyB0byBiZSB0aGUgdHJ1dGggYWJvdXQgdGhlIGJhY2tlbmQgc3RhdGUgKEEgbWVyZ2VyIG9mIHRoZQogICAgICBgX2RhdGFgIGFuZCBgX2luRmxpZ2h0QXR0cmlidXRlc2Agb2JqZWN0cyB3aGVyZQogICAgICBgX2luRmxpZ2h0QXR0cmlidXRlc2AgaGFzIHByaW9yaXR5KSB0aGVuIHRoYXQgbWVhbnMgdGhlIGJhY2tlbmQKICAgICAgaGFzIHVwZGF0ZWQgdGhlIHZhbHVlIGFuZCB0aGUga2V5IGlzIGFkZGVkIHRvIHRoZSBsaXN0IG9mIGNoYW5nZWQKICAgICAga2V5cy4KICAgICAgIEBtZXRob2QgX2NoYW5nZWRLZXlzCiAgICAgIEBwcml2YXRlCiAgICAqLwoKICAgIC8qCiAgICAgICAgVE9ETyBJR09SIERBVklECiAgICAgICAgVGhlcmUgc2VlbXMgdG8gYmUgYSBwb3RlbnRpYWwgYnVnIGhlcmUsIHdoZXJlIHdlIHdpbGwgcmV0dXJuIGtleXMgdGhhdCBhcmUgbm90CiAgICAgICAgaW4gdGhlIHNjaGVtYQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX2NoYW5nZWRLZXlzID0gZnVuY3Rpb24gX2NoYW5nZWRLZXlzKHVwZGF0ZXMpIHsKICAgICAgdmFyIGNoYW5nZWRLZXlzID0gW107CgogICAgICBpZiAodXBkYXRlcykgewogICAgICAgIHZhciBvcmlnaW5hbCwgaSwgdmFsdWUsIF9rZXkyOwoKICAgICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHVwZGF0ZXMpOwogICAgICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDsKICAgICAgICB2YXIgaGFzQXR0cnMgPSB0aGlzLmhhc0NoYW5nZWRBdHRyaWJ1dGVzKCk7CiAgICAgICAgdmFyIGF0dHJzOwoKICAgICAgICBpZiAoaGFzQXR0cnMpIHsKICAgICAgICAgIGF0dHJzID0gdGhpcy5fYXR0cmlidXRlczsKICAgICAgICB9CgogICAgICAgIG9yaWdpbmFsID0gRW1iZXIuYXNzaWduKE9iamVjdC5jcmVhdGUobnVsbCksIHRoaXMuX2RhdGEsIHRoaXMuX19pbkZsaWdodEF0dHJpYnV0ZXMpOwoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgIF9rZXkyID0ga2V5c1tpXTsKICAgICAgICAgIHZhbHVlID0gdXBkYXRlc1tfa2V5Ml07IC8vIEEgdmFsdWUgaW4gX2F0dHJpYnV0ZXMgbWVhbnMgdGhlIHVzZXIgaGFzIGEgbG9jYWwgY2hhbmdlIHRvCiAgICAgICAgICAvLyB0aGlzIGF0dHJpYnV0ZXMuIFdlIG5ldmVyIG92ZXJyaWRlIHRoaXMgdmFsdWUgd2hlbiBtZXJnaW5nCiAgICAgICAgICAvLyB1cGRhdGVzIGZyb20gdGhlIGJhY2tlbmQgc28gd2Ugc2hvdWxkIG5vdCBzZW50IGEgY2hhbmdlCiAgICAgICAgICAvLyBub3RpZmljYXRpb24gaWYgdGhlIHNlcnZlciB2YWx1ZSBkaWZmZXJzIGZyb20gdGhlIG9yaWdpbmFsLgoKICAgICAgICAgIGlmIChoYXNBdHRycyA9PT0gdHJ1ZSAmJiBhdHRyc1tfa2V5Ml0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoIUVtYmVyLmlzRXF1YWwob3JpZ2luYWxbX2tleTJdLCB2YWx1ZSkpIHsKICAgICAgICAgICAgY2hhbmdlZEtleXMucHVzaChfa2V5Mik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gY2hhbmdlZEtleXM7CiAgICB9OwoKICAgIF9wcm90by50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gIjwiICsgdGhpcy5tb2RlbE5hbWUgKyAiOiIgKyB0aGlzLmlkICsgIj4iOwogICAgfTsKCiAgICBfY3JlYXRlQ2xhc3MkMyhSZWNvcmREYXRhRGVmYXVsdCwgW3sKICAgICAga2V5OiAiX2F0dHJpYnV0ZXMiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fX2F0dHJpYnV0ZXMgPT09IG51bGwpIHsKICAgICAgICAgIHRoaXMuX19hdHRyaWJ1dGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9fYXR0cmlidXRlczsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQodikgewogICAgICAgIHRoaXMuX19hdHRyaWJ1dGVzID0gdjsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJfcmVsYXRpb25zaGlwcyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIGlmICh0aGlzLl9fcmVsYXRpb25zaGlwcyA9PT0gbnVsbCkgewogICAgICAgICAgdGhpcy5fX3JlbGF0aW9uc2hpcHMgPSBuZXcgUmVsYXRpb25zaGlwcyh0aGlzKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9fcmVsYXRpb25zaGlwczsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJfZGF0YSIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIGlmICh0aGlzLl9fZGF0YSA9PT0gbnVsbCkgewogICAgICAgICAgdGhpcy5fX2RhdGEgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMuX19kYXRhOwogICAgICB9LAogICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2KSB7CiAgICAgICAgdGhpcy5fX2RhdGEgPSB2OwogICAgICB9CiAgICAgIC8qCiAgICAgICBpbXBsaWNpdCByZWxhdGlvbnNoaXBzIGFyZSByZWxhdGlvbnNoaXAgd2hpY2ggaGF2ZSBub3QgYmVlbiBkZWNsYXJlZCBidXQgdGhlIGludmVyc2Ugc2lkZSBleGlzdHMgb24KICAgICAgIGFub3RoZXIgcmVjb3JkIHNvbWV3aGVyZQogICAgICAgRm9yIGV4YW1wbGUgaWYgdGhlcmUgd2FzCiAgICAgICAgYGBgYXBwL21vZGVscy9jb21tZW50LmpzCiAgICAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgICBuYW1lOiBhdHRyKCkKICAgICAgIH0pOwogICAgICAgYGBgCiAgICAgICAgYnV0IHRoZXJlIGlzIGFsc28KICAgICAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyLCBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgIG5hbWU6IGF0dHIoKSwKICAgICAgICAgY29tbWVudHM6IGhhc01hbnkoJ2NvbW1lbnQnKQogICAgICAgfSk7CiAgICAgICBgYGAKICAgICAgICB3b3VsZCBoYXZlIGEgaW1wbGljaXQgcG9zdCByZWxhdGlvbnNoaXAgaW4gb3JkZXIgdG8gYmUgZG8gdGhpbmdzIGxpa2UgcmVtb3ZlIG91cnNlbHZlcyBmcm9tIHRoZSBwb3N0CiAgICAgICB3aGVuIHdlIGFyZSBkZWxldGVkCiAgICAgICovCgogICAgfSwgewogICAgICBrZXk6ICJfaW1wbGljaXRSZWxhdGlvbnNoaXBzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMuX19pbXBsaWNpdFJlbGF0aW9uc2hpcHMgPT09IG51bGwpIHsKICAgICAgICAgIHZhciByZWxhdGlvbnNoaXBzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgIHRoaXMuX19pbXBsaWNpdFJlbGF0aW9uc2hpcHMgPSByZWxhdGlvbnNoaXBzOwogICAgICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcHM7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fX2ltcGxpY2l0UmVsYXRpb25zaGlwczsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJfaW5GbGlnaHRBdHRyaWJ1dGVzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMuX19pbkZsaWdodEF0dHJpYnV0ZXMgPT09IG51bGwpIHsKICAgICAgICAgIHRoaXMuX19pbkZsaWdodEF0dHJpYnV0ZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMuX19pbkZsaWdodEF0dHJpYnV0ZXM7CiAgICAgIH0sCiAgICAgIHNldDogZnVuY3Rpb24gc2V0KHYpIHsKICAgICAgICB0aGlzLl9faW5GbGlnaHRBdHRyaWJ1dGVzID0gdjsKICAgICAgfQogICAgfV0pOwoKICAgIHJldHVybiBSZWNvcmREYXRhRGVmYXVsdDsKICB9KCk7CiAgLy8gcmVsYXRpb25zaGlwIG9mIHRoZSBkZW1hdGVyaWFsaXphdGlvbjogdGhpcyBpcyBkb25lIHNvIHRoZSByZWxhdGlvbnNoaXAgY2FuCiAgLy8gbm90aWZ5IGl0cyBpbnZlcnNlIHdoaWNoIG5lZWRzIHRvIHVwZGF0ZSBzdGF0ZQogIC8vCiAgLy8gSWYgdGhlIGludmVyc2UgaXMgc3luYywgdW5sb2FkaW5nIHRoaXMgcmVjb3JkIGlzIHRyZWF0ZWQgYXMgYSBjbGllbnQtc2lkZQogIC8vIGRlbGV0ZSwgc28gd2UgcmVtb3ZlIHRoZSBpbnZlcnNlIHJlY29yZHMgZnJvbSB0aGlzIHJlbGF0aW9uc2hpcCB0bwogIC8vIGRpc2Nvbm5lY3QgdGhlIGdyYXBoLiAgQmVjYXVzZSBpdCdzIG5vdCBhc3luYywgd2UgZG9uJ3QgbmVlZCB0byBrZWVwIGFyb3VuZAogIC8vIHRoZSBpbnRlcm5hbE1vZGVsIGFzIGFuIGlkLXdyYXBwZXIgZm9yIHJlZmVyZW5jZXMgYW5kIGJlY2F1c2UgdGhlIGdyYXBoIGlzCiAgLy8gZGlzY29ubmVjdGVkIHdlIGNhbiBhY3R1YWxseSBkZXN0cm95IHRoZSBpbnRlcm5hbE1vZGVsIHdoZW4gY2hlY2tpbmcgZm9yCiAgLy8gb3JwaGFuZWQgbW9kZWxzLgoKCiAgZnVuY3Rpb24gZGVzdHJveVJlbGF0aW9uc2hpcChyZWwpIHsKICAgIHJlbC5yZWNvcmREYXRhRGlkRGVtYXRlcmlhbGl6ZSgpOwoKICAgIGlmIChyZWwuX2ludmVyc2VJc1N5bmMoKSkgewogICAgICByZWwucmVtb3ZlQWxsUmVjb3JkRGF0YXNGcm9tT3duKCk7CiAgICAgIHJlbC5yZW1vdmVBbGxDYW5vbmljYWxSZWNvcmREYXRhc0Zyb21Pd24oKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGFyZUFsbE1vZGVsc1VubG9hZGVkKHJlY29yZERhdGFzKSB7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlY29yZERhdGFzLmxlbmd0aDsgKytpKSB7CiAgICAgIGlmIChyZWNvcmREYXRhc1tpXS5pc1JlY29yZEluVXNlKCkpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKICB9CgogIGV4cG9ydHMuQmVsb25nc1RvUmVsYXRpb25zaGlwID0gQmVsb25nc1RvUmVsYXRpb25zaGlwOwogIGV4cG9ydHMuTWFueVJlbGF0aW9uc2hpcCA9IE1hbnlSZWxhdGlvbnNoaXA7CiAgZXhwb3J0cy5SZWNvcmREYXRhID0gUmVjb3JkRGF0YURlZmF1bHQ7CiAgZXhwb3J0cy5SZWxhdGlvbnNoaXAgPSBSZWxhdGlvbnNoaXA7CiAgZXhwb3J0cy5yZWxhdGlvbnNoaXBTdGF0ZUZvciA9IHJlbGF0aW9uc2hpcFN0YXRlRm9yOwogIGV4cG9ydHMucmVsYXRpb25zaGlwc0ZvciA9IHJlbGF0aW9uc2hpcHNGb3I7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7Cgp9KTsKCjtkZWZpbmUoJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvLXByaXZhdGUnLCBbJ2V4cG9ydHMnXSwgZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc2VyaWFsaXplcgogICovCgogIC8qKgogICAgIyMgVXNpbmcgRW1iZWRkZWQgUmVjb3JkcwoKICAgIGBFbWJlZGRlZFJlY29yZHNNaXhpbmAgc3VwcG9ydHMgc2VyaWFsaXppbmcgZW1iZWRkZWQgcmVjb3Jkcy4KCiAgICBUbyBzZXQgdXAgZW1iZWRkZWQgcmVjb3JkcywgaW5jbHVkZSB0aGUgbWl4aW4gd2hlbiBleHRlbmRpbmcgYSBzZXJpYWxpemVyLAogICAgdGhlbiBkZWZpbmUgYW5kIGNvbmZpZ3VyZSBlbWJlZGRlZCAobW9kZWwpIHJlbGF0aW9uc2hpcHMuCgogICAgTm90ZSB0aGF0IGVtYmVkZGVkIHJlY29yZHMgd2lsbCBzZXJpYWxpemUgd2l0aCB0aGUgc2VyaWFsaXplciBmb3IgdGhlaXIgbW9kZWwgaW5zdGVhZCBvZiB0aGUgc2VyaWFsaXplciBpbiB3aGljaCB0aGV5IGFyZSBkZWZpbmVkLgoKICAgIEJlbG93IGlzIGFuIGV4YW1wbGUgb2YgYSBwZXItdHlwZSBzZXJpYWxpemVyIChgcG9zdGAgdHlwZSkuCgogICAgYGBgYXBwL3NlcmlhbGl6ZXJzL3Bvc3QuanMKICAgIGltcG9ydCBSRVNUU2VyaWFsaXplciwgeyBFbWJlZGRlZFJlY29yZHNNaXhpbiB9IGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CgogICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKEVtYmVkZGVkUmVjb3Jkc01peGluLCB7CiAgICAgIGF0dHJzOiB7CiAgICAgICAgYXV0aG9yOiB7IGVtYmVkZGVkOiAnYWx3YXlzJyB9LAogICAgICAgIGNvbW1lbnRzOiB7IHNlcmlhbGl6ZTogJ2lkcycgfQogICAgICB9CiAgICB9KTsKICAgIGBgYAogICAgTm90ZSB0aGF0IHRoaXMgdXNlIG9mIGB7IGVtYmVkZGVkOiAnYWx3YXlzJyB9YCBpcyB1bnJlbGF0ZWQgdG8KICAgIHRoZSBgeyBlbWJlZGRlZDogJ2Fsd2F5cycgfWAgdGhhdCBpcyBkZWZpbmVkIGFzIGFuIG9wdGlvbiBvbiBgYXR0cmAgYXMgcGFydCBvZgogICAgZGVmaW5pbmcgYSBtb2RlbCB3aGlsZSB3b3JraW5nIHdpdGggdGhlIGBBY3RpdmVNb2RlbFNlcmlhbGl6ZXJgLiAgTmV2ZXJ0aGVsZXNzLAogICAgdXNpbmcgYHsgZW1iZWRkZWQ6ICdhbHdheXMnIH1gIGFzIGFuIG9wdGlvbiB0byBgYXR0cmAgaXMgbm90IGEgdmFsaWQgd2F5IHRvIHNldCB1cAogICAgZW1iZWRkZWQgcmVjb3Jkcy4KCiAgICBUaGUgYGF0dHJzYCBvcHRpb24gZm9yIGEgcmVzb3VyY2UgYHsgZW1iZWRkZWQ6ICdhbHdheXMnIH1gIGlzIHNob3J0aGFuZCBmb3I6CgogICAgYGBganMKICAgIHsKICAgICAgc2VyaWFsaXplOiAncmVjb3JkcycsCiAgICAgIGRlc2VyaWFsaXplOiAncmVjb3JkcycKICAgIH0KICAgIGBgYAoKICAgICMjIyBDb25maWd1cmluZyBBdHRycwoKICAgIEEgcmVzb3VyY2UncyBgYXR0cnNgIG9wdGlvbiBtYXkgYmUgc2V0IHRvIHVzZSBgaWRzYCwgYHJlY29yZHNgIG9yIGZhbHNlIGZvciB0aGUKICAgIGBzZXJpYWxpemVgICBhbmQgYGRlc2VyaWFsaXplYCBzZXR0aW5ncy4KCiAgICBUaGUgYGF0dHJzYCBwcm9wZXJ0eSBjYW4gYmUgc2V0IG9uIHRoZSBgQXBwbGljYXRpb25TZXJpYWxpemVyYCBvciBhIHBlci10eXBlCiAgICBzZXJpYWxpemVyLgoKICAgIEluIHRoZSBjYXNlIHdoZXJlIGVtYmVkZGVkIEpTT04gaXMgZXhwZWN0ZWQgd2hpbGUgZXh0cmFjdGluZyBhIHBheWxvYWQgKHJlYWRpbmcpCiAgICB0aGUgc2V0dGluZyBpcyBgZGVzZXJpYWxpemU6ICdyZWNvcmRzJ2AsIHRoZXJlIGlzIG5vIG5lZWQgdG8gdXNlIGBpZHNgIHdoZW4KICAgIGV4dHJhY3RpbmcgYXMgdGhhdCBpcyB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgd2l0aG91dCB0aGlzIG1peGluIGlmIHlvdSBhcmUgdXNpbmcKICAgIHRoZSB2YW5pbGxhIGBFbWJlZGRlZFJlY29yZHNNaXhpbmAuIExpa2V3aXNlLCB0byBlbWJlZCBKU09OIGluIHRoZSBwYXlsb2FkIHdoaWxlCiAgICBzZXJpYWxpemluZyBgc2VyaWFsaXplOiAncmVjb3JkcydgIGlzIHRoZSBzZXR0aW5nIHRvIHVzZS4gVGhlcmUgaXMgYW4gb3B0aW9uIG9mCiAgICBub3QgZW1iZWRkaW5nIEpTT04gaW4gdGhlIHNlcmlhbGl6ZWQgcGF5bG9hZCBieSB1c2luZyBgc2VyaWFsaXplOiAnaWRzJ2AuIElmIHlvdQogICAgZG8gbm90IHdhbnQgdGhlIHJlbGF0aW9uc2hpcCBzZW50IGF0IGFsbCwgeW91IGNhbiB1c2UgYHNlcmlhbGl6ZTogZmFsc2VgLgoKCiAgICAjIyMgRW1iZWRkZWRSZWNvcmRzTWl4aW4gZGVmYXVsdHMKICAgIElmIHlvdSBkbyBub3Qgb3ZlcndyaXRlIGBhdHRyc2AgZm9yIGEgc3BlY2lmaWMgcmVsYXRpb25zaGlwLCB0aGUgYEVtYmVkZGVkUmVjb3Jkc01peGluYAogICAgd2lsbCBiZWhhdmUgaW4gdGhlIGZvbGxvd2luZyB3YXk6CgogICAgQmVsb25nc1RvOiBgeyBzZXJpYWxpemU6ICdpZCcsIGRlc2VyaWFsaXplOiAnaWQnIH1gCiAgICBIYXNNYW55OiAgIGB7IHNlcmlhbGl6ZTogZmFsc2UsIGRlc2VyaWFsaXplOiAnaWRzJyB9YAoKICAgICMjIyBNb2RlbCBSZWxhdGlvbnNoaXBzCgogICAgRW1iZWRkZWQgcmVjb3JkcyBtdXN0IGhhdmUgYSBtb2RlbCBkZWZpbmVkIHRvIGJlIGV4dHJhY3RlZCBhbmQgc2VyaWFsaXplZC4gTm90ZSB0aGF0CiAgICB3aGVuIGRlZmluaW5nIGFueSByZWxhdGlvbnNoaXBzIG9uIHlvdXIgbW9kZWwgc3VjaCBhcyBgYmVsb25nc1RvYCBhbmQgYGhhc01hbnlgLCB5b3UKICAgIHNob3VsZCBub3QgYm90aCBzcGVjaWZ5IGBhc3luYzogdHJ1ZWAgYW5kIGFsc28gaW5kaWNhdGUgdGhyb3VnaCB0aGUgc2VyaWFsaXplcidzCiAgICBgYXR0cnNgIGF0dHJpYnV0ZSB0aGF0IHRoZSByZWxhdGVkIG1vZGVsIHNob3VsZCBiZSBlbWJlZGRlZCBmb3IgZGVzZXJpYWxpemF0aW9uLgogICAgSWYgYSBtb2RlbCBpcyBkZWNsYXJlZCBlbWJlZGRlZCBmb3IgZGVzZXJpYWxpemF0aW9uIChgZW1iZWRkZWQ6ICdhbHdheXMnYCBvciBgZGVzZXJpYWxpemU6ICdyZWNvcmRzJ2ApLAogICAgdGhlbiBkbyBub3QgdXNlIGBhc3luYzogdHJ1ZWAuCgogICAgVG8gc3VjY2Vzc2Z1bGx5IGV4dHJhY3QgYW5kIHNlcmlhbGl6ZSBlbWJlZGRlZCByZWNvcmRzIHRoZSBtb2RlbCByZWxhdGlvbnNoaXBzCiAgICBtdXN0IGJlIHNldCB1cCBjb3JyZWN0bHkuIFNlZSB0aGUKICAgIFtkZWZpbmluZyByZWxhdGlvbnNoaXBzXShodHRwczovL2d1aWRlcy5lbWJlcmpzLmNvbS9jdXJyZW50L21vZGVscy9yZWxhdGlvbnNoaXBzKQogICAgc2VjdGlvbiBvZiB0aGUgKipEZWZpbmluZyBNb2RlbHMqKiBndWlkZSBwYWdlLgoKICAgIFJlY29yZHMgd2l0aG91dCBhbiBgaWRgIHByb3BlcnR5IGFyZSBub3QgY29uc2lkZXJlZCBlbWJlZGRlZCByZWNvcmRzLCBtb2RlbAogICAgaW5zdGFuY2VzIG11c3QgaGF2ZSBhbiBgaWRgIHByb3BlcnR5IHRvIGJlIHVzZWQgd2l0aCBFbWJlciBEYXRhLgoKICAgICMjIyBFeGFtcGxlIEpTT04gcGF5bG9hZHMsIE1vZGVscyBhbmQgU2VyaWFsaXplcnMKCiAgICAqKldoZW4gY3VzdG9taXppbmcgYSBzZXJpYWxpemVyIGl0IGlzIGltcG9ydGFudCB0byBncm9rIHdoYXQgdGhlIGN1c3RvbWl6YXRpb25zCiAgICBhcmUuIFBsZWFzZSByZWFkIHRoZSBkb2NzIGZvciB0aGUgbWV0aG9kcyB0aGlzIG1peGluIHByb3ZpZGVzLCBpbiBjYXNlIHlvdSBuZWVkCiAgICB0byBtb2RpZnkgaXQgdG8gZml0IHlvdXIgc3BlY2lmaWMgbmVlZHMuKioKCiAgICBGb3IgZXhhbXBsZSwgcmV2aWV3IHRoZSBkb2NzIGZvciBlYWNoIG1ldGhvZCBvZiB0aGlzIG1peGluOgogICAgKiBbbm9ybWFsaXplXSgvZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvRW1iZWRkZWRSZWNvcmRzTWl4aW4vbWV0aG9kcy9ub3JtYWxpemU/YW5jaG9yPW5vcm1hbGl6ZSkKICAgICogW3NlcmlhbGl6ZUJlbG9uZ3NUb10oL2VtYmVyLWRhdGEvcmVsZWFzZS9jbGFzc2VzL0VtYmVkZGVkUmVjb3Jkc01peGluL21ldGhvZHMvc2VyaWFsaXplQmVsb25nc1RvP2FuY2hvcj1zZXJpYWxpemVCZWxvbmdzVG8pCiAgICAqIFtzZXJpYWxpemVIYXNNYW55XSgvZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvRW1iZWRkZWRSZWNvcmRzTWl4aW4vbWV0aG9kcy9zZXJpYWxpemVIYXNNYW55P2FuY2hvcj1zZXJpYWxpemVIYXNNYW55KQoKICAgIEBjbGFzcyBFbWJlZGRlZFJlY29yZHNNaXhpbgogICovCiAgdmFyIGVtYmVkZGVkUmVjb3Jkc01peGluID0gRW1iZXIuTWl4aW4uY3JlYXRlKHsKICAgIC8qKgogICAgICBOb3JtYWxpemUgdGhlIHJlY29yZCBhbmQgcmVjdXJzaXZlbHkgbm9ybWFsaXplL2V4dHJhY3QgYWxsIHRoZSBlbWJlZGRlZCByZWNvcmRzCiAgICAgIHdoaWxlIHB1c2hpbmcgdGhlbSBpbnRvIHRoZSBzdG9yZSBhcyB0aGV5IGFyZSBlbmNvdW50ZXJlZAogICAgICAgQSBwYXlsb2FkIHdpdGggYW4gYXR0ciBjb25maWd1cmVkIGZvciBlbWJlZGRlZCByZWNvcmRzIG5lZWRzIHRvIGJlIGV4dHJhY3RlZDoKICAgICAgIGBgYGpzCiAgICAgIHsKICAgICAgICAicG9zdCI6IHsKICAgICAgICAgICJpZCI6ICIxIgogICAgICAgICAgInRpdGxlIjogIlJhaWxzIGlzIG9tYWthc2UiLAogICAgICAgICAgImNvbW1lbnRzIjogW3sKICAgICAgICAgICAgImlkIjogIjEiLAogICAgICAgICAgICAiYm9keSI6ICJSYWlscyBpcyB1bmFnaSIKICAgICAgICAgIH0sIHsKICAgICAgICAgICAgImlkIjogIjIiLAogICAgICAgICAgICAiYm9keSI6ICJPbWFrYXNlIE9fbyIKICAgICAgICAgIH1dCiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgIEBtZXRob2Qgbm9ybWFsaXplCiAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZUNsYXNzCiAgICAgQHBhcmFtIHtPYmplY3R9IGhhc2ggdG8gYmUgbm9ybWFsaXplZAogICAgIEBwYXJhbSB7U3RyaW5nfSBwcm9wIHRoZSBoYXNoIGhhcyBiZWVuIHJlZmVyZW5jZWQgYnkKICAgICBAcmV0dXJuIHtPYmplY3R9IHRoZSBub3JtYWxpemVkIGhhc2gKICAgICoqLwogICAgbm9ybWFsaXplOiBmdW5jdGlvbiBub3JtYWxpemUodHlwZUNsYXNzLCBoYXNoLCBwcm9wKSB7CiAgICAgIHZhciBub3JtYWxpemVkSGFzaCA9IHRoaXMuX3N1cGVyKHR5cGVDbGFzcywgaGFzaCwgcHJvcCk7CgogICAgICByZXR1cm4gdGhpcy5fZXh0cmFjdEVtYmVkZGVkUmVjb3Jkcyh0aGlzLCB0aGlzLnN0b3JlLCB0eXBlQ2xhc3MsIG5vcm1hbGl6ZWRIYXNoKTsKICAgIH0sCiAgICBrZXlGb3JSZWxhdGlvbnNoaXA6IGZ1bmN0aW9uIGtleUZvclJlbGF0aW9uc2hpcChrZXksIHR5cGVDbGFzcywgbWV0aG9kKSB7CiAgICAgIGlmIChtZXRob2QgPT09ICdzZXJpYWxpemUnICYmIHRoaXMuaGFzU2VyaWFsaXplUmVjb3Jkc09wdGlvbihrZXkpIHx8IG1ldGhvZCA9PT0gJ2Rlc2VyaWFsaXplJyAmJiB0aGlzLmhhc0Rlc2VyaWFsaXplUmVjb3Jkc09wdGlvbihrZXkpKSB7CiAgICAgICAgcmV0dXJuIHRoaXMua2V5Rm9yQXR0cmlidXRlKGtleSwgbWV0aG9kKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gdGhpcy5fc3VwZXIoa2V5LCB0eXBlQ2xhc3MsIG1ldGhvZCkgfHwga2V5OwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBTZXJpYWxpemUgYGJlbG9uZ3NUb2AgcmVsYXRpb25zaGlwIHdoZW4gaXQgaXMgY29uZmlndXJlZCBhcyBhbiBlbWJlZGRlZCBvYmplY3QuCiAgICAgICBUaGlzIGV4YW1wbGUgb2YgYW4gYXV0aG9yIG1vZGVsIGJlbG9uZ3MgdG8gYSBwb3N0IG1vZGVsOgogICAgICAgYGBganMKICAgICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIsIGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgIFBvc3QgPSBNb2RlbC5leHRlbmQoewogICAgICAgIHRpdGxlOiAgICBhdHRyKCdzdHJpbmcnKSwKICAgICAgICBib2R5OiAgICAgYXR0cignc3RyaW5nJyksCiAgICAgICAgYXV0aG9yOiAgIGJlbG9uZ3NUbygnYXV0aG9yJykKICAgICAgfSk7CiAgICAgICBBdXRob3IgPSBNb2RlbC5leHRlbmQoewogICAgICAgIG5hbWU6ICAgICBhdHRyKCdzdHJpbmcnKSwKICAgICAgICBwb3N0OiAgICAgYmVsb25nc1RvKCdwb3N0JykKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVXNlIGEgY3VzdG9tICh0eXBlKSBzZXJpYWxpemVyIGZvciB0aGUgcG9zdCBtb2RlbCB0byBjb25maWd1cmUgZW1iZWRkZWQgYXV0aG9yCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIsIHsgRW1iZWRkZWRSZWNvcmRzTWl4aW4gfSBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKEVtYmVkZGVkUmVjb3Jkc01peGluLCB7CiAgICAgICAgYXR0cnM6IHsKICAgICAgICAgIGF1dGhvcjogeyBlbWJlZGRlZDogJ2Fsd2F5cycgfQogICAgICAgIH0KICAgICAgfSkKICAgICAgYGBgCiAgICAgICBBIHBheWxvYWQgd2l0aCBhbiBhdHRyaWJ1dGUgY29uZmlndXJlZCBmb3IgZW1iZWRkZWQgcmVjb3JkcyBjYW4gc2VyaWFsaXplCiAgICAgIHRoZSByZWNvcmRzIHRvZ2V0aGVyIHVuZGVyIHRoZSByb290IGF0dHJpYnV0ZSdzIHBheWxvYWQ6CiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgInBvc3QiOiB7CiAgICAgICAgICAiaWQiOiAiMSIKICAgICAgICAgICJ0aXRsZSI6ICJSYWlscyBpcyBvbWFrYXNlIiwKICAgICAgICAgICJhdXRob3IiOiB7CiAgICAgICAgICAgICJpZCI6ICIyIgogICAgICAgICAgICAibmFtZSI6ICJkaGgiCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXJpYWxpemVCZWxvbmdzVG8KICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHBhcmFtIHtPYmplY3R9IGpzb24KICAgICAgQHBhcmFtIHtPYmplY3R9IHJlbGF0aW9uc2hpcAogICAgKi8KICAgIHNlcmlhbGl6ZUJlbG9uZ3NUbzogZnVuY3Rpb24gc2VyaWFsaXplQmVsb25nc1RvKHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIGF0dHIgPSByZWxhdGlvbnNoaXAua2V5OwoKICAgICAgaWYgKHRoaXMubm9TZXJpYWxpemVPcHRpb25TcGVjaWZpZWQoYXR0cikpIHsKICAgICAgICB0aGlzLl9zdXBlcihzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKTsKCiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgaW5jbHVkZUlkcyA9IHRoaXMuaGFzU2VyaWFsaXplSWRzT3B0aW9uKGF0dHIpOwogICAgICB2YXIgaW5jbHVkZVJlY29yZHMgPSB0aGlzLmhhc1NlcmlhbGl6ZVJlY29yZHNPcHRpb24oYXR0cik7CiAgICAgIHZhciBlbWJlZGRlZFNuYXBzaG90ID0gc25hcHNob3QuYmVsb25nc1RvKGF0dHIpOwoKICAgICAgaWYgKGluY2x1ZGVJZHMpIHsKICAgICAgICB2YXIgc2VyaWFsaXplZEtleSA9IHRoaXMuX2dldE1hcHBlZEtleShyZWxhdGlvbnNoaXAua2V5LCBzbmFwc2hvdC50eXBlKTsKCiAgICAgICAgaWYgKHNlcmlhbGl6ZWRLZXkgPT09IHJlbGF0aW9uc2hpcC5rZXkgJiYgdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXApIHsKICAgICAgICAgIHNlcmlhbGl6ZWRLZXkgPSB0aGlzLmtleUZvclJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXAua2V5LCByZWxhdGlvbnNoaXAua2luZCwgJ3NlcmlhbGl6ZScpOwogICAgICAgIH0KCiAgICAgICAgaWYgKCFlbWJlZGRlZFNuYXBzaG90KSB7CiAgICAgICAgICBqc29uW3NlcmlhbGl6ZWRLZXldID0gbnVsbDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAganNvbltzZXJpYWxpemVkS2V5XSA9IGVtYmVkZGVkU25hcHNob3QuaWQ7CgogICAgICAgICAgaWYgKHJlbGF0aW9uc2hpcC5vcHRpb25zLnBvbHltb3JwaGljKSB7CiAgICAgICAgICAgIHRoaXMuc2VyaWFsaXplUG9seW1vcnBoaWNUeXBlKHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChpbmNsdWRlUmVjb3JkcykgewogICAgICAgIHRoaXMuX3NlcmlhbGl6ZUVtYmVkZGVkQmVsb25nc1RvKHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApOwogICAgICB9CiAgICB9LAogICAgX3NlcmlhbGl6ZUVtYmVkZGVkQmVsb25nc1RvOiBmdW5jdGlvbiBfc2VyaWFsaXplRW1iZWRkZWRCZWxvbmdzVG8oc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCkgewogICAgICB2YXIgZW1iZWRkZWRTbmFwc2hvdCA9IHNuYXBzaG90LmJlbG9uZ3NUbyhyZWxhdGlvbnNoaXAua2V5KTsKCiAgICAgIHZhciBzZXJpYWxpemVkS2V5ID0gdGhpcy5fZ2V0TWFwcGVkS2V5KHJlbGF0aW9uc2hpcC5rZXksIHNuYXBzaG90LnR5cGUpOwoKICAgICAgaWYgKHNlcmlhbGl6ZWRLZXkgPT09IHJlbGF0aW9uc2hpcC5rZXkgJiYgdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXApIHsKICAgICAgICBzZXJpYWxpemVkS2V5ID0gdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXAocmVsYXRpb25zaGlwLmtleSwgcmVsYXRpb25zaGlwLmtpbmQsICdzZXJpYWxpemUnKTsKICAgICAgfQoKICAgICAgaWYgKCFlbWJlZGRlZFNuYXBzaG90KSB7CiAgICAgICAganNvbltzZXJpYWxpemVkS2V5XSA9IG51bGw7CiAgICAgIH0gZWxzZSB7CiAgICAgICAganNvbltzZXJpYWxpemVkS2V5XSA9IGVtYmVkZGVkU25hcHNob3Quc2VyaWFsaXplKHsKICAgICAgICAgIGluY2x1ZGVJZDogdHJ1ZQogICAgICAgIH0pOwogICAgICAgIHRoaXMucmVtb3ZlRW1iZWRkZWRGb3JlaWduS2V5KHNuYXBzaG90LCBlbWJlZGRlZFNuYXBzaG90LCByZWxhdGlvbnNoaXAsIGpzb25bc2VyaWFsaXplZEtleV0pOwoKICAgICAgICBpZiAocmVsYXRpb25zaGlwLm9wdGlvbnMucG9seW1vcnBoaWMpIHsKICAgICAgICAgIHRoaXMuc2VyaWFsaXplUG9seW1vcnBoaWNUeXBlKHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApOwogICAgICAgIH0KICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgU2VyaWFsaXplcyBgaGFzTWFueWAgcmVsYXRpb25zaGlwcyB3aGVuIGl0IGlzIGNvbmZpZ3VyZWQgYXMgZW1iZWRkZWQgb2JqZWN0cy4KICAgICAgIFRoaXMgZXhhbXBsZSBvZiBhIHBvc3QgbW9kZWwgaGFzIG1hbnkgY29tbWVudHM6CiAgICAgICBgYGBqcwogICAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciwgYmVsb25nc1RvLCBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgUG9zdCA9IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdGl0bGU6ICAgIGF0dHIoJ3N0cmluZycpLAogICAgICAgIGJvZHk6ICAgICBhdHRyKCdzdHJpbmcnKSwKICAgICAgICBjb21tZW50czogaGFzTWFueSgnY29tbWVudCcpCiAgICAgIH0pOwogICAgICAgQ29tbWVudCA9IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgYm9keTogICAgIGF0dHIoJ3N0cmluZycpLAogICAgICAgIHBvc3Q6ICAgICBiZWxvbmdzVG8oJ3Bvc3QnKQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBVc2UgYSBjdXN0b20gKHR5cGUpIHNlcmlhbGl6ZXIgZm9yIHRoZSBwb3N0IG1vZGVsIHRvIGNvbmZpZ3VyZSBlbWJlZGRlZCBjb21tZW50cwogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL3Bvc3QuanMKICAgICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyLCB7IEVtYmVkZGVkUmVjb3Jkc01peGluIH0gZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZChFbWJlZGRlZFJlY29yZHNNaXhpbiwgewogICAgICAgIGF0dHJzOiB7CiAgICAgICAgICBjb21tZW50czogeyBlbWJlZGRlZDogJ2Fsd2F5cycgfQogICAgICAgIH0KICAgICAgfSkKICAgICAgYGBgCiAgICAgICBBIHBheWxvYWQgd2l0aCBhbiBhdHRyaWJ1dGUgY29uZmlndXJlZCBmb3IgZW1iZWRkZWQgcmVjb3JkcyBjYW4gc2VyaWFsaXplCiAgICAgIHRoZSByZWNvcmRzIHRvZ2V0aGVyIHVuZGVyIHRoZSByb290IGF0dHJpYnV0ZSdzIHBheWxvYWQ6CiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgInBvc3QiOiB7CiAgICAgICAgICAiaWQiOiAiMSIKICAgICAgICAgICJ0aXRsZSI6ICJSYWlscyBpcyBvbWFrYXNlIiwKICAgICAgICAgICJib2R5IjogIkkgd2FudCB0aGlzIGZvciBteSBPUk0sIEkgd2FudCB0aGF0IGZvciBteSB0ZW1wbGF0ZSBsYW5ndWFnZS4uLiIKICAgICAgICAgICJjb21tZW50cyI6IFt7CiAgICAgICAgICAgICJpZCI6ICIxIiwKICAgICAgICAgICAgImJvZHkiOiAiUmFpbHMgaXMgdW5hZ2kiCiAgICAgICAgICB9LCB7CiAgICAgICAgICAgICJpZCI6ICIyIiwKICAgICAgICAgICAgImJvZHkiOiAiT21ha2FzZSBPX28iCiAgICAgICAgICB9XQogICAgICAgIH0KICAgICAgfQogICAgICBgYGAKICAgICAgIFRoZSBhdHRycyBvcHRpb25zIG9iamVjdCBjYW4gdXNlIG1vcmUgc3BlY2lmaWMgaW5zdHJ1Y3Rpb24gZm9yIGV4dHJhY3RpbmcgYW5kCiAgICAgIHNlcmlhbGl6aW5nLiBXaGVuIHNlcmlhbGl6aW5nLCBhbiBvcHRpb24gdG8gZW1iZWQgYGlkc2AsIGBpZHMtYW5kLXR5cGVzYCBvciBgcmVjb3Jkc2AgY2FuIGJlIHNldC4KICAgICAgV2hlbiBleHRyYWN0aW5nIHRoZSBvbmx5IG9wdGlvbiBpcyBgcmVjb3Jkc2AuCiAgICAgICBTbyBgeyBlbWJlZGRlZDogJ2Fsd2F5cycgfWAgaXMgc2hvcnRoYW5kIGZvcjoKICAgICAgYHsgc2VyaWFsaXplOiAncmVjb3JkcycsIGRlc2VyaWFsaXplOiAncmVjb3JkcycgfWAKICAgICAgIFRvIGVtYmVkIHRoZSBgaWRzYCBmb3IgYSByZWxhdGVkIG9iamVjdCAodXNpbmcgYSBoYXNNYW55IHJlbGF0aW9uc2hpcCk6CiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIsIHsgRW1iZWRkZWRSZWNvcmRzTWl4aW4gfSBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXIuZXh0ZW5kKEVtYmVkZGVkUmVjb3Jkc01peGluLCB7CiAgICAgICAgYXR0cnM6IHsKICAgICAgICAgIGNvbW1lbnRzOiB7IHNlcmlhbGl6ZTogJ2lkcycsIGRlc2VyaWFsaXplOiAncmVjb3JkcycgfQogICAgICAgIH0KICAgICAgfSkKICAgICAgYGBgCiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgInBvc3QiOiB7CiAgICAgICAgICAiaWQiOiAiMSIKICAgICAgICAgICJ0aXRsZSI6ICJSYWlscyBpcyBvbWFrYXNlIiwKICAgICAgICAgICJib2R5IjogIkkgd2FudCB0aGlzIGZvciBteSBPUk0sIEkgd2FudCB0aGF0IGZvciBteSB0ZW1wbGF0ZSBsYW5ndWFnZS4uLiIKICAgICAgICAgICJjb21tZW50cyI6IFsiMSIsICIyIl0KICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBUbyBlbWJlZCB0aGUgcmVsYXRpb25zaGlwIGFzIGEgY29sbGVjdGlvbiBvZiBvYmplY3RzIHdpdGggYGlkYCBhbmQgYHR5cGVgIGtleXMsIHNldAogICAgICBgaWRzLWFuZC10eXBlc2AgZm9yIHRoZSByZWxhdGVkIG9iamVjdC4KICAgICAgIFRoaXMgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCBmb3IgcG9seW1vcnBoaWMgcmVsYXRpb25zaGlwcyB3aGVyZSByZWNvcmRzIGRvbid0IHNoYXJlCiAgICAgIHRoZSBzYW1lIHRhYmxlIGFuZCB0aGUgYGlkYCBpcyBub3QgZW5vdWdoIGluZm9ybWF0aW9uLgogICAgICAgRm9yIGV4YW1wbGUgaGF2aW5nIGEgdXNlciB0aGF0IGhhcyBtYW55IHBldHM6CiAgICAgICBgYGBqcwogICAgICBVc2VyID0gTW9kZWwuZXh0ZW5kKHsKICAgICAgICBuYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgICBwZXRzOiBoYXNNYW55KCdwZXQnLCB7IHBvbHltb3JwaGljOiB0cnVlIH0pCiAgICAgIH0pOwogICAgICAgUGV0ID0gTW9kZWwuZXh0ZW5kKHsKICAgICAgICBuYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgfSk7CiAgICAgICBDYXQgPSBQZXQuZXh0ZW5kKHsKICAgICAgICAvLyAuLi4KICAgICAgfSk7CiAgICAgICBQYXJyb3QgPSBQZXQuZXh0ZW5kKHsKICAgICAgICAvLyAuLi4KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL3VzZXIuanMKICAgICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyLCB7IEVtYmVkZGVkUmVjb3Jkc01peGluIH0gZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZChFbWJlZGRlZFJlY29yZHNNaXhpbiwgewogICAgICAgIGF0dHJzOiB7CiAgICAgICAgICBwZXRzOiB7IHNlcmlhbGl6ZTogJ2lkcy1hbmQtdHlwZXMnLCBkZXNlcmlhbGl6ZTogJ3JlY29yZHMnIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIGBgYGpzCiAgICAgIHsKICAgICAgICAidXNlciI6IHsKICAgICAgICAgICJpZCI6ICIxIgogICAgICAgICAgIm5hbWUiOiAiQmVydGluIE9zYm9ybmUiLAogICAgICAgICAgInBldHMiOiBbCiAgICAgICAgICAgIHsgImlkIjogIjEiLCAidHlwZSI6ICJDYXQiIH0sCiAgICAgICAgICAgIHsgImlkIjogIjEiLCAidHlwZSI6ICJQYXJyb3QifQogICAgICAgICAgXQogICAgICAgIH0KICAgICAgfQogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc2VyaWFsaXplSGFzTWFueQogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcGFyYW0ge09iamVjdH0ganNvbgogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwCiAgICAqLwogICAgc2VyaWFsaXplSGFzTWFueTogZnVuY3Rpb24gc2VyaWFsaXplSGFzTWFueShzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBhdHRyID0gcmVsYXRpb25zaGlwLmtleTsKCiAgICAgIGlmICh0aGlzLm5vU2VyaWFsaXplT3B0aW9uU3BlY2lmaWVkKGF0dHIpKSB7CiAgICAgICAgdGhpcy5fc3VwZXIoc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCk7CgogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuaGFzU2VyaWFsaXplSWRzT3B0aW9uKGF0dHIpKSB7CiAgICAgICAgdmFyIHNlcmlhbGl6ZWRLZXkgPSB0aGlzLl9nZXRNYXBwZWRLZXkocmVsYXRpb25zaGlwLmtleSwgc25hcHNob3QudHlwZSk7CgogICAgICAgIGlmIChzZXJpYWxpemVkS2V5ID09PSByZWxhdGlvbnNoaXAua2V5ICYmIHRoaXMua2V5Rm9yUmVsYXRpb25zaGlwKSB7CiAgICAgICAgICBzZXJpYWxpemVkS2V5ID0gdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXAocmVsYXRpb25zaGlwLmtleSwgcmVsYXRpb25zaGlwLmtpbmQsICdzZXJpYWxpemUnKTsKICAgICAgICB9CgogICAgICAgIGpzb25bc2VyaWFsaXplZEtleV0gPSBzbmFwc2hvdC5oYXNNYW55KGF0dHIsIHsKICAgICAgICAgIGlkczogdHJ1ZQogICAgICAgIH0pOwogICAgICB9IGVsc2UgaWYgKHRoaXMuaGFzU2VyaWFsaXplUmVjb3Jkc09wdGlvbihhdHRyKSkgewogICAgICAgIHRoaXMuX3NlcmlhbGl6ZUVtYmVkZGVkSGFzTWFueShzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAodGhpcy5oYXNTZXJpYWxpemVJZHNBbmRUeXBlc09wdGlvbihhdHRyKSkgewogICAgICAgICAgdGhpcy5fc2VyaWFsaXplSGFzTWFueUFzSWRzQW5kVHlwZXMoc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCk7CiAgICAgICAgfQogICAgICB9CiAgICB9LAoKICAgIC8qCiAgICAgIFNlcmlhbGl6ZXMgYSBoYXNNYW55IHJlbGF0aW9uc2hpcCBhcyBhbiBhcnJheSBvZiBvYmplY3RzIGNvbnRhaW5pbmcgb25seSBgaWRgIGFuZCBgdHlwZWAKICAgICAga2V5cy4KICAgICAgVGhpcyBoYXMgaXRzIHVzZSBjYXNlIG9uIHBvbHltb3JwaGljIGhhc01hbnkgcmVsYXRpb25zaGlwcyB3aGVyZSB0aGUgc2VydmVyIGlzIG5vdCBzdG9yaW5nCiAgICAgIGFsbCByZWNvcmRzIGluIHRoZSBzYW1lIHRhYmxlIHVzaW5nIFNUSSwgYW5kIHRoZXJlZm9yZSB0aGUgYGlkYCBpcyBub3QgZW5vdWdoIGluZm9ybWF0aW9uCiAgICAgICBUT0RPOiBNYWtlIHRoZSBkZWZhdWx0IGluIEVtYmVyLWRhdGEgMy4wPz8KICAgICovCiAgICBfc2VyaWFsaXplSGFzTWFueUFzSWRzQW5kVHlwZXM6IGZ1bmN0aW9uIF9zZXJpYWxpemVIYXNNYW55QXNJZHNBbmRUeXBlcyhzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBzZXJpYWxpemVkS2V5ID0gdGhpcy5rZXlGb3JBdHRyaWJ1dGUocmVsYXRpb25zaGlwLmtleSwgJ3NlcmlhbGl6ZScpOwogICAgICB2YXIgaGFzTWFueSA9IHNuYXBzaG90Lmhhc01hbnkocmVsYXRpb25zaGlwLmtleSk7CiAgICAgIGpzb25bc2VyaWFsaXplZEtleV0gPSBFbWJlci5BKGhhc01hbnkpLm1hcChmdW5jdGlvbiAocmVjb3JkU25hcHNob3QpIHsKICAgICAgICAvLwogICAgICAgIC8vIEknbSBzdXJlIEknbSBiZWluZyB1dHRlcmx5IG5haXZlIGhlcmUuIFByb3BhYmx5IGlkIGlzIGEgY29uZmlndXJhdGUgcHJvcGVydHkgYW5kCiAgICAgICAgLy8gdHlwZSB0b28sIGFuZCB0aGUgbW9kZWxOYW1lIGhhcyB0byBiZSBub3JtYWxpemVkIHNvbWVob3cuCiAgICAgICAgLy8KICAgICAgICByZXR1cm4gewogICAgICAgICAgaWQ6IHJlY29yZFNuYXBzaG90LmlkLAogICAgICAgICAgdHlwZTogcmVjb3JkU25hcHNob3QubW9kZWxOYW1lCiAgICAgICAgfTsKICAgICAgfSk7CiAgICB9LAogICAgX3NlcmlhbGl6ZUVtYmVkZGVkSGFzTWFueTogZnVuY3Rpb24gX3NlcmlhbGl6ZUVtYmVkZGVkSGFzTWFueShzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBzZXJpYWxpemVkS2V5ID0gdGhpcy5fZ2V0TWFwcGVkS2V5KHJlbGF0aW9uc2hpcC5rZXksIHNuYXBzaG90LnR5cGUpOwoKICAgICAgaWYgKHNlcmlhbGl6ZWRLZXkgPT09IHJlbGF0aW9uc2hpcC5rZXkgJiYgdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXApIHsKICAgICAgICBzZXJpYWxpemVkS2V5ID0gdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXAocmVsYXRpb25zaGlwLmtleSwgcmVsYXRpb25zaGlwLmtpbmQsICdzZXJpYWxpemUnKTsKICAgICAgfQogICAgICBqc29uW3NlcmlhbGl6ZWRLZXldID0gdGhpcy5fZ2VuZXJhdGVTZXJpYWxpemVkSGFzTWFueShzbmFwc2hvdCwgcmVsYXRpb25zaGlwKTsKICAgIH0sCgogICAgLyoKICAgICAgUmV0dXJucyBhbiBhcnJheSBvZiBlbWJlZGRlZCByZWNvcmRzIHNlcmlhbGl6ZWQgdG8gSlNPTgogICAgKi8KICAgIF9nZW5lcmF0ZVNlcmlhbGl6ZWRIYXNNYW55OiBmdW5jdGlvbiBfZ2VuZXJhdGVTZXJpYWxpemVkSGFzTWFueShzbmFwc2hvdCwgcmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBoYXNNYW55ID0gc25hcHNob3QuaGFzTWFueShyZWxhdGlvbnNoaXAua2V5KTsKICAgICAgdmFyIG1hbnlBcnJheSA9IEVtYmVyLkEoaGFzTWFueSk7CiAgICAgIHZhciByZXQgPSBuZXcgQXJyYXkobWFueUFycmF5Lmxlbmd0aCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1hbnlBcnJheS5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBlbWJlZGRlZFNuYXBzaG90ID0gbWFueUFycmF5W2ldOwogICAgICAgIHZhciBlbWJlZGRlZEpzb24gPSBlbWJlZGRlZFNuYXBzaG90LnNlcmlhbGl6ZSh7CiAgICAgICAgICBpbmNsdWRlSWQ6IHRydWUKICAgICAgICB9KTsKICAgICAgICB0aGlzLnJlbW92ZUVtYmVkZGVkRm9yZWlnbktleShzbmFwc2hvdCwgZW1iZWRkZWRTbmFwc2hvdCwgcmVsYXRpb25zaGlwLCBlbWJlZGRlZEpzb24pOwogICAgICAgIHJldFtpXSA9IGVtYmVkZGVkSnNvbjsKICAgICAgfQoKICAgICAgcmV0dXJuIHJldDsKICAgIH0sCgogICAgLyoqCiAgICAgIFdoZW4gc2VyaWFsaXppbmcgYW4gZW1iZWRkZWQgcmVjb3JkLCBtb2RpZnkgdGhlIHByb3BlcnR5IChpbiB0aGUgYEpTT05gIHBheWxvYWQpCiAgICAgIHRoYXQgcmVmZXJzIHRvIHRoZSBwYXJlbnQgcmVjb3JkIChmb3JlaWduIGtleSBmb3IgdGhlIHJlbGF0aW9uc2hpcCkuCiAgICAgICBTZXJpYWxpemluZyBhIGBiZWxvbmdzVG9gIHJlbGF0aW9uc2hpcCByZW1vdmVzIHRoZSBwcm9wZXJ0eSB0aGF0IHJlZmVycyB0byB0aGUKICAgICAgcGFyZW50IHJlY29yZAogICAgICAgU2VyaWFsaXppbmcgYSBgaGFzTWFueWAgcmVsYXRpb25zaGlwIGRvZXMgbm90IHJlbW92ZSB0aGUgcHJvcGVydHkgdGhhdCByZWZlcnMgdG8KICAgICAgdGhlIHBhcmVudCByZWNvcmQuCiAgICAgICBAbWV0aG9kIHJlbW92ZUVtYmVkZGVkRm9yZWlnbktleQogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcGFyYW0ge1NuYXBzaG90fSBlbWJlZGRlZFNuYXBzaG90CiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZWxhdGlvbnNoaXAKICAgICAgQHBhcmFtIHtPYmplY3R9IGpzb24KICAgICovCiAgICByZW1vdmVFbWJlZGRlZEZvcmVpZ25LZXk6IGZ1bmN0aW9uIHJlbW92ZUVtYmVkZGVkRm9yZWlnbktleShzbmFwc2hvdCwgZW1iZWRkZWRTbmFwc2hvdCwgcmVsYXRpb25zaGlwLCBqc29uKSB7CiAgICAgIGlmIChyZWxhdGlvbnNoaXAua2luZCA9PT0gJ2JlbG9uZ3NUbycpIHsKICAgICAgICB2YXIgcGFyZW50UmVjb3JkID0gc25hcHNob3QudHlwZS5pbnZlcnNlRm9yKHJlbGF0aW9uc2hpcC5rZXksIHRoaXMuc3RvcmUpOwoKICAgICAgICBpZiAocGFyZW50UmVjb3JkKSB7CiAgICAgICAgICB2YXIgbmFtZSA9IHBhcmVudFJlY29yZC5uYW1lOwogICAgICAgICAgdmFyIGVtYmVkZGVkU2VyaWFsaXplciA9IHRoaXMuc3RvcmUuc2VyaWFsaXplckZvcihlbWJlZGRlZFNuYXBzaG90Lm1vZGVsTmFtZSk7CiAgICAgICAgICB2YXIgcGFyZW50S2V5ID0gZW1iZWRkZWRTZXJpYWxpemVyLmtleUZvclJlbGF0aW9uc2hpcChuYW1lLCBwYXJlbnRSZWNvcmQua2luZCwgJ2Rlc2VyaWFsaXplJyk7CgogICAgICAgICAgaWYgKHBhcmVudEtleSkgewogICAgICAgICAgICBkZWxldGUganNvbltwYXJlbnRLZXldOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICAvKmVsc2UgaWYgKHJlbGF0aW9uc2hpcC5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgcmV0dXJuOwogICAgICB9Ki8KCiAgICB9LAogICAgLy8gY2hlY2tzIGNvbmZpZyBmb3IgYXR0cnMgb3B0aW9uIHRvIGVtYmVkZGVkIChhbHdheXMpIC0gc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZQogICAgaGFzRW1iZWRkZWRBbHdheXNPcHRpb246IGZ1bmN0aW9uIGhhc0VtYmVkZGVkQWx3YXlzT3B0aW9uKGF0dHIpIHsKICAgICAgdmFyIG9wdGlvbiA9IHRoaXMuYXR0cnNPcHRpb24oYXR0cik7CiAgICAgIHJldHVybiBvcHRpb24gJiYgb3B0aW9uLmVtYmVkZGVkID09PSAnYWx3YXlzJzsKICAgIH0sCiAgICAvLyBjaGVja3MgY29uZmlnIGZvciBhdHRycyBvcHRpb24gdG8gc2VyaWFsaXplIGlkcwogICAgaGFzU2VyaWFsaXplUmVjb3Jkc09wdGlvbjogZnVuY3Rpb24gaGFzU2VyaWFsaXplUmVjb3Jkc09wdGlvbihhdHRyKSB7CiAgICAgIHZhciBhbHdheXNFbWJlZCA9IHRoaXMuaGFzRW1iZWRkZWRBbHdheXNPcHRpb24oYXR0cik7CiAgICAgIHZhciBvcHRpb24gPSB0aGlzLmF0dHJzT3B0aW9uKGF0dHIpOwogICAgICByZXR1cm4gYWx3YXlzRW1iZWQgfHwgb3B0aW9uICYmIG9wdGlvbi5zZXJpYWxpemUgPT09ICdyZWNvcmRzJzsKICAgIH0sCiAgICAvLyBjaGVja3MgY29uZmlnIGZvciBhdHRycyBvcHRpb24gdG8gc2VyaWFsaXplIHJlY29yZHMKICAgIGhhc1NlcmlhbGl6ZUlkc09wdGlvbjogZnVuY3Rpb24gaGFzU2VyaWFsaXplSWRzT3B0aW9uKGF0dHIpIHsKICAgICAgdmFyIG9wdGlvbiA9IHRoaXMuYXR0cnNPcHRpb24oYXR0cik7CiAgICAgIHJldHVybiBvcHRpb24gJiYgKG9wdGlvbi5zZXJpYWxpemUgPT09ICdpZHMnIHx8IG9wdGlvbi5zZXJpYWxpemUgPT09ICdpZCcpOwogICAgfSwKICAgIC8vIGNoZWNrcyBjb25maWcgZm9yIGF0dHJzIG9wdGlvbiB0byBzZXJpYWxpemUgcmVjb3JkcyBhcyBvYmplY3RzIGNvbnRhaW5pbmcgaWQgYW5kIHR5cGVzCiAgICBoYXNTZXJpYWxpemVJZHNBbmRUeXBlc09wdGlvbjogZnVuY3Rpb24gaGFzU2VyaWFsaXplSWRzQW5kVHlwZXNPcHRpb24oYXR0cikgewogICAgICB2YXIgb3B0aW9uID0gdGhpcy5hdHRyc09wdGlvbihhdHRyKTsKICAgICAgcmV0dXJuIG9wdGlvbiAmJiAob3B0aW9uLnNlcmlhbGl6ZSA9PT0gJ2lkcy1hbmQtdHlwZXMnIHx8IG9wdGlvbi5zZXJpYWxpemUgPT09ICdpZC1hbmQtdHlwZScpOwogICAgfSwKICAgIC8vIGNoZWNrcyBjb25maWcgZm9yIGF0dHJzIG9wdGlvbiB0byBzZXJpYWxpemUgcmVjb3JkcwogICAgbm9TZXJpYWxpemVPcHRpb25TcGVjaWZpZWQ6IGZ1bmN0aW9uIG5vU2VyaWFsaXplT3B0aW9uU3BlY2lmaWVkKGF0dHIpIHsKICAgICAgdmFyIG9wdGlvbiA9IHRoaXMuYXR0cnNPcHRpb24oYXR0cik7CiAgICAgIHJldHVybiAhKG9wdGlvbiAmJiAob3B0aW9uLnNlcmlhbGl6ZSB8fCBvcHRpb24uZW1iZWRkZWQpKTsKICAgIH0sCiAgICAvLyBjaGVja3MgY29uZmlnIGZvciBhdHRycyBvcHRpb24gdG8gZGVzZXJpYWxpemUgcmVjb3JkcwogICAgLy8gYSBkZWZpbmVkIG9wdGlvbiBvYmplY3QgZm9yIGEgcmVzb3VyY2UgaXMgdHJlYXRlZCB0aGUgc2FtZSBhcwogICAgLy8gYGRlc2VyaWFsaXplOiAncmVjb3JkcydgCiAgICBoYXNEZXNlcmlhbGl6ZVJlY29yZHNPcHRpb246IGZ1bmN0aW9uIGhhc0Rlc2VyaWFsaXplUmVjb3Jkc09wdGlvbihhdHRyKSB7CiAgICAgIHZhciBhbHdheXNFbWJlZCA9IHRoaXMuaGFzRW1iZWRkZWRBbHdheXNPcHRpb24oYXR0cik7CiAgICAgIHZhciBvcHRpb24gPSB0aGlzLmF0dHJzT3B0aW9uKGF0dHIpOwogICAgICByZXR1cm4gYWx3YXlzRW1iZWQgfHwgb3B0aW9uICYmIG9wdGlvbi5kZXNlcmlhbGl6ZSA9PT0gJ3JlY29yZHMnOwogICAgfSwKICAgIGF0dHJzT3B0aW9uOiBmdW5jdGlvbiBhdHRyc09wdGlvbihhdHRyKSB7CiAgICAgIHZhciBhdHRycyA9IHRoaXMuZ2V0KCdhdHRycycpOwogICAgICByZXR1cm4gYXR0cnMgJiYgKGF0dHJzW0VtYmVyLlN0cmluZy5jYW1lbGl6ZShhdHRyKV0gfHwgYXR0cnNbYXR0cl0pOwogICAgfSwKCiAgICAvKioKICAgICBAbWV0aG9kIF9leHRyYWN0RW1iZWRkZWRSZWNvcmRzCiAgICAgQHByaXZhdGUKICAgICovCiAgICBfZXh0cmFjdEVtYmVkZGVkUmVjb3JkczogZnVuY3Rpb24gX2V4dHJhY3RFbWJlZGRlZFJlY29yZHMoc2VyaWFsaXplciwgc3RvcmUsIHR5cGVDbGFzcywgcGFydGlhbCkgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgdHlwZUNsYXNzLmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24gKGtleSwgcmVsYXRpb25zaGlwKSB7CiAgICAgICAgaWYgKHNlcmlhbGl6ZXIuaGFzRGVzZXJpYWxpemVSZWNvcmRzT3B0aW9uKGtleSkpIHsKICAgICAgICAgIGlmIChyZWxhdGlvbnNoaXAua2luZCA9PT0gJ2hhc01hbnknKSB7CiAgICAgICAgICAgIF90aGlzLl9leHRyYWN0RW1iZWRkZWRIYXNNYW55KHN0b3JlLCBrZXksIHBhcnRpYWwsIHJlbGF0aW9uc2hpcCk7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKHJlbGF0aW9uc2hpcC5raW5kID09PSAnYmVsb25nc1RvJykgewogICAgICAgICAgICBfdGhpcy5fZXh0cmFjdEVtYmVkZGVkQmVsb25nc1RvKHN0b3JlLCBrZXksIHBhcnRpYWwsIHJlbGF0aW9uc2hpcCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIHBhcnRpYWw7CiAgICB9LAoKICAgIC8qKgogICAgIEBtZXRob2QgX2V4dHJhY3RFbWJlZGRlZEhhc01hbnkKICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9leHRyYWN0RW1iZWRkZWRIYXNNYW55OiBmdW5jdGlvbiBfZXh0cmFjdEVtYmVkZGVkSGFzTWFueShzdG9yZSwga2V5LCBoYXNoLCByZWxhdGlvbnNoaXBNZXRhKSB7CiAgICAgIHZhciByZWxhdGlvbnNoaXBIYXNoID0gRW1iZXIuZ2V0KGhhc2gsICJkYXRhLnJlbGF0aW9uc2hpcHMuIiArIGtleSArICIuZGF0YSIpOwoKICAgICAgaWYgKCFyZWxhdGlvbnNoaXBIYXNoKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgaGFzTWFueSA9IG5ldyBBcnJheShyZWxhdGlvbnNoaXBIYXNoLmxlbmd0aCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbGF0aW9uc2hpcEhhc2gubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgaXRlbSA9IHJlbGF0aW9uc2hpcEhhc2hbaV07CgogICAgICAgIHZhciBfdGhpcyRfbm9ybWFsaXplRW1iZWQgPSB0aGlzLl9ub3JtYWxpemVFbWJlZGRlZFJlbGF0aW9uc2hpcChzdG9yZSwgcmVsYXRpb25zaGlwTWV0YSwgaXRlbSksCiAgICAgICAgICAgIGRhdGEgPSBfdGhpcyRfbm9ybWFsaXplRW1iZWQuZGF0YSwKICAgICAgICAgICAgaW5jbHVkZWQgPSBfdGhpcyRfbm9ybWFsaXplRW1iZWQuaW5jbHVkZWQ7CgogICAgICAgIGhhc2guaW5jbHVkZWQgPSBoYXNoLmluY2x1ZGVkIHx8IFtdOwogICAgICAgIGhhc2guaW5jbHVkZWQucHVzaChkYXRhKTsKCiAgICAgICAgaWYgKGluY2x1ZGVkKSB7CiAgICAgICAgICB2YXIgX2hhc2gkaW5jbHVkZWQ7CgogICAgICAgICAgKF9oYXNoJGluY2x1ZGVkID0gaGFzaC5pbmNsdWRlZCkucHVzaC5hcHBseShfaGFzaCRpbmNsdWRlZCwgaW5jbHVkZWQpOwogICAgICAgIH0KCiAgICAgICAgaGFzTWFueVtpXSA9IHsKICAgICAgICAgIGlkOiBkYXRhLmlkLAogICAgICAgICAgdHlwZTogZGF0YS50eXBlCiAgICAgICAgfTsKICAgICAgfQoKICAgICAgdmFyIHJlbGF0aW9uc2hpcCA9IHsKICAgICAgICBkYXRhOiBoYXNNYW55CiAgICAgIH07CiAgICAgIEVtYmVyLnNldChoYXNoLCAiZGF0YS5yZWxhdGlvbnNoaXBzLiIgKyBrZXksIHJlbGF0aW9uc2hpcCk7CiAgICB9LAoKICAgIC8qKgogICAgIEBtZXRob2QgX2V4dHJhY3RFbWJlZGRlZEJlbG9uZ3NUbwogICAgIEBwcml2YXRlCiAgICAqLwogICAgX2V4dHJhY3RFbWJlZGRlZEJlbG9uZ3NUbzogZnVuY3Rpb24gX2V4dHJhY3RFbWJlZGRlZEJlbG9uZ3NUbyhzdG9yZSwga2V5LCBoYXNoLCByZWxhdGlvbnNoaXBNZXRhKSB7CiAgICAgIHZhciByZWxhdGlvbnNoaXBIYXNoID0gRW1iZXIuZ2V0KGhhc2gsICJkYXRhLnJlbGF0aW9uc2hpcHMuIiArIGtleSArICIuZGF0YSIpOwoKICAgICAgaWYgKCFyZWxhdGlvbnNoaXBIYXNoKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgX3RoaXMkX25vcm1hbGl6ZUVtYmVkMiA9IHRoaXMuX25vcm1hbGl6ZUVtYmVkZGVkUmVsYXRpb25zaGlwKHN0b3JlLCByZWxhdGlvbnNoaXBNZXRhLCByZWxhdGlvbnNoaXBIYXNoKSwKICAgICAgICAgIGRhdGEgPSBfdGhpcyRfbm9ybWFsaXplRW1iZWQyLmRhdGEsCiAgICAgICAgICBpbmNsdWRlZCA9IF90aGlzJF9ub3JtYWxpemVFbWJlZDIuaW5jbHVkZWQ7CgogICAgICBoYXNoLmluY2x1ZGVkID0gaGFzaC5pbmNsdWRlZCB8fCBbXTsKICAgICAgaGFzaC5pbmNsdWRlZC5wdXNoKGRhdGEpOwoKICAgICAgaWYgKGluY2x1ZGVkKSB7CiAgICAgICAgdmFyIF9oYXNoJGluY2x1ZGVkMjsKCiAgICAgICAgKF9oYXNoJGluY2x1ZGVkMiA9IGhhc2guaW5jbHVkZWQpLnB1c2guYXBwbHkoX2hhc2gkaW5jbHVkZWQyLCBpbmNsdWRlZCk7CiAgICAgIH0KCiAgICAgIHZhciBiZWxvbmdzVG8gPSB7CiAgICAgICAgaWQ6IGRhdGEuaWQsCiAgICAgICAgdHlwZTogZGF0YS50eXBlCiAgICAgIH07CiAgICAgIHZhciByZWxhdGlvbnNoaXAgPSB7CiAgICAgICAgZGF0YTogYmVsb25nc1RvCiAgICAgIH07CiAgICAgIEVtYmVyLnNldChoYXNoLCAiZGF0YS5yZWxhdGlvbnNoaXBzLiIgKyBrZXksIHJlbGF0aW9uc2hpcCk7CiAgICB9LAoKICAgIC8qKgogICAgIEBtZXRob2QgX25vcm1hbGl6ZUVtYmVkZGVkUmVsYXRpb25zaGlwCiAgICAgQHByaXZhdGUKICAgICovCiAgICBfbm9ybWFsaXplRW1iZWRkZWRSZWxhdGlvbnNoaXA6IGZ1bmN0aW9uIF9ub3JtYWxpemVFbWJlZGRlZFJlbGF0aW9uc2hpcChzdG9yZSwgcmVsYXRpb25zaGlwTWV0YSwgcmVsYXRpb25zaGlwSGFzaCkgewogICAgICB2YXIgbW9kZWxOYW1lID0gcmVsYXRpb25zaGlwTWV0YS50eXBlOwoKICAgICAgaWYgKHJlbGF0aW9uc2hpcE1ldGEub3B0aW9ucy5wb2x5bW9ycGhpYykgewogICAgICAgIG1vZGVsTmFtZSA9IHJlbGF0aW9uc2hpcEhhc2gudHlwZTsKICAgICAgfQoKICAgICAgdmFyIG1vZGVsQ2xhc3MgPSBzdG9yZS5tb2RlbEZvcihtb2RlbE5hbWUpOwogICAgICB2YXIgc2VyaWFsaXplciA9IHN0b3JlLnNlcmlhbGl6ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIHNlcmlhbGl6ZXIubm9ybWFsaXplKG1vZGVsQ2xhc3MsIHJlbGF0aW9uc2hpcEhhc2gsIG51bGwpOwogICAgfSwKICAgIGlzRW1iZWRkZWRSZWNvcmRzTWl4aW46IHRydWUKICB9KTsKCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3NlcmlhbGl6ZXIKICAqLwoKICAvKgogICAgQ2hlY2sgaWYgdGhlIHBhc3NlZCBtb2RlbCBoYXMgYSBgdHlwZWAgYXR0cmlidXRlIG9yIGEgcmVsYXRpb25zaGlwIG5hbWVkIGB0eXBlYC4KCiAgICBAbWV0aG9kIG1vZGVsSGFzQXR0cmlidXRlT3JSZWxhdGlvbnNoaXBOYW1lZFR5cGUKICAgIEBwYXJhbSBtb2RlbENsYXNzCiAgICovCiAgZnVuY3Rpb24gbW9kZWxIYXNBdHRyaWJ1dGVPclJlbGF0aW9uc2hpcE5hbWVkVHlwZShtb2RlbENsYXNzKSB7CiAgICByZXR1cm4gRW1iZXIuZ2V0KG1vZGVsQ2xhc3MsICdhdHRyaWJ1dGVzJykuaGFzKCd0eXBlJykgfHwgRW1iZXIuZ2V0KG1vZGVsQ2xhc3MsICdyZWxhdGlvbnNoaXBzQnlOYW1lJykuaGFzKCd0eXBlJyk7CiAgfQoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc2VyaWFsaXplcgogICovCgogIC8qKgogICAgVGhlIGBUcmFuc2Zvcm1gIGNsYXNzIGlzIHVzZWQgdG8gc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZSBtb2RlbAogICAgYXR0cmlidXRlcyB3aGVuIHRoZXkgYXJlIHNhdmVkIG9yIGxvYWRlZCBmcm9tIGFuCiAgICBhZGFwdGVyLiBTdWJjbGFzc2luZyBgVHJhbnNmb3JtYCBpcyB1c2VmdWwgZm9yIGNyZWF0aW5nIGN1c3RvbQogICAgYXR0cmlidXRlcy4gQWxsIHN1YmNsYXNzZXMgb2YgYFRyYW5zZm9ybWAgbXVzdCBpbXBsZW1lbnQgYQogICAgYHNlcmlhbGl6ZWAgYW5kIGEgYGRlc2VyaWFsaXplYCBtZXRob2QuCgogICAgRXhhbXBsZQoKICAgIGBgYGFwcC90cmFuc2Zvcm1zL3RlbXBlcmF0dXJlLmpzCiAgICBpbXBvcnQgVHJhbnNmb3JtIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvdHJhbnNmb3JtJzsKCiAgICAvLyBDb252ZXJ0cyBjZW50aWdyYWRlIGluIHRoZSBKU09OIHRvIGZhaHJlbmhlaXQgaW4gdGhlIGFwcAogICAgZXhwb3J0IGRlZmF1bHQgVHJhbnNmb3JtLmV4dGVuZCh7CiAgICAgIGRlc2VyaWFsaXplKHNlcmlhbGl6ZWQsIG9wdGlvbnMpIHsKICAgICAgICByZXR1cm4gKHNlcmlhbGl6ZWQgKiAgMS44KSArIDMyOwogICAgICB9LAoKICAgICAgc2VyaWFsaXplKGRlc2VyaWFsaXplZCwgb3B0aW9ucykgewogICAgICAgIHJldHVybiAoZGVzZXJpYWxpemVkIC0gMzIpIC8gMS44OwogICAgICB9CiAgICB9KTsKICAgIGBgYAoKICAgIFVzYWdlCgogICAgYGBgYXBwL21vZGVscy9yZXF1aXJlbWVudC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgbmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgIHRlbXBlcmF0dXJlOiBhdHRyKCd0ZW1wZXJhdHVyZScpCiAgICB9KTsKICAgIGBgYAoKICAgIFRoZSBvcHRpb25zIHBhc3NlZCBpbnRvIHRoZSBgYXR0cmAgZnVuY3Rpb24gd2hlbiB0aGUgYXR0cmlidXRlIGlzCiAgICBkZWNsYXJlZCBvbiB0aGUgbW9kZWwgaXMgYWxzbyBhdmFpbGFibGUgaW4gdGhlIHRyYW5zZm9ybS4KCiAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHRpdGxlOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgbWFya2Rvd246IGF0dHIoJ21hcmtkb3duJywgewogICAgICAgIG1hcmtkb3duOiB7CiAgICAgICAgICBnZm06IGZhbHNlLAogICAgICAgICAgc2FuaXRpemU6IHRydWUKICAgICAgICB9CiAgICAgIH0pCiAgICB9KTsKICAgIGBgYAoKICAgIGBgYGFwcC90cmFuc2Zvcm1zL21hcmtkb3duLmpzCiAgICBpbXBvcnQgVHJhbnNmb3JtIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvdHJhbnNmb3JtJzsKCiAgICBleHBvcnQgZGVmYXVsdCBUcmFuc2Zvcm0uZXh0ZW5kKHsKICAgICAgc2VyaWFsaXplKGRlc2VyaWFsaXplZCwgb3B0aW9ucykgewogICAgICAgIHJldHVybiBkZXNlcmlhbGl6ZWQucmF3OwogICAgICB9LAoKICAgICAgZGVzZXJpYWxpemUoc2VyaWFsaXplZCwgb3B0aW9ucykgewogICAgICAgIHZhciBtYXJrZG93bk9wdGlvbnMgPSBvcHRpb25zLm1hcmtkb3duIHx8IHt9OwoKICAgICAgICByZXR1cm4gbWFya2VkKHNlcmlhbGl6ZWQsIG1hcmtkb3duT3B0aW9ucyk7CiAgICAgIH0KICAgIH0pOwogICAgYGBgCgogICAgQGNsYXNzIFRyYW5zZm9ybQogICAqLwogIHZhciBUcmFuc2Zvcm0gPSBFbWJlci5PYmplY3QuZXh0ZW5kKHsKICAgIC8qKgogICAgICBXaGVuIGdpdmVuIGEgZGVzZXJpYWxpemVkIHZhbHVlIGZyb20gYSByZWNvcmQgYXR0cmlidXRlIHRoaXMKICAgICAgbWV0aG9kIG11c3QgcmV0dXJuIHRoZSBzZXJpYWxpemVkIHZhbHVlLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBpbXBvcnQgeyBpc0VtcHR5IH0gZnJvbSAnQGVtYmVyL3V0aWxzJzsKICAgICAgIHNlcmlhbGl6ZShkZXNlcmlhbGl6ZWQsIG9wdGlvbnMpIHsKICAgICAgICByZXR1cm4gaXNFbXB0eShkZXNlcmlhbGl6ZWQpID8gbnVsbCA6IE51bWJlcihkZXNlcmlhbGl6ZWQpOwogICAgICB9CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXJpYWxpemUKICAgICAgQHBhcmFtIGRlc2VyaWFsaXplZCBUaGUgZGVzZXJpYWxpemVkIHZhbHVlCiAgICAgIEBwYXJhbSBvcHRpb25zIGhhc2ggb2Ygb3B0aW9ucyBwYXNzZWQgdG8gYGF0dHJgCiAgICAgIEByZXR1cm4gVGhlIHNlcmlhbGl6ZWQgdmFsdWUKICAgICovCiAgICBzZXJpYWxpemU6IG51bGwsCgogICAgLyoqCiAgICAgIFdoZW4gZ2l2ZW4gYSBzZXJpYWxpemVkIHZhbHVlIGZyb20gYSBKU09OIG9iamVjdCB0aGlzIG1ldGhvZCBtdXN0CiAgICAgIHJldHVybiB0aGUgZGVzZXJpYWxpemVkIHZhbHVlIGZvciB0aGUgcmVjb3JkIGF0dHJpYnV0ZS4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgZGVzZXJpYWxpemUoc2VyaWFsaXplZCwgb3B0aW9ucykgewogICAgICAgIHJldHVybiBlbXB0eShzZXJpYWxpemVkKSA/IG51bGwgOiBOdW1iZXIoc2VyaWFsaXplZCk7CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGRlc2VyaWFsaXplCiAgICAgIEBwYXJhbSBzZXJpYWxpemVkIFRoZSBzZXJpYWxpemVkIHZhbHVlCiAgICAgIEBwYXJhbSBvcHRpb25zIGhhc2ggb2Ygb3B0aW9ucyBwYXNzZWQgdG8gYGF0dHJgCiAgICAgIEByZXR1cm4gVGhlIGRlc2VyaWFsaXplZCB2YWx1ZQogICAgKi8KICAgIGRlc2VyaWFsaXplOiBudWxsCiAgfSk7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zZXJpYWxpemVyCiAgKi8KCiAgLyoqCiAgICBUaGUgYEJvb2xlYW5UcmFuc2Zvcm1gIGNsYXNzIGlzIHVzZWQgdG8gc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZQogICAgYm9vbGVhbiBhdHRyaWJ1dGVzIG9uIEVtYmVyIERhdGEgcmVjb3JkIG9iamVjdHMuIFRoaXMgdHJhbnNmb3JtIGlzCiAgICB1c2VkIHdoZW4gYGJvb2xlYW5gIGlzIHBhc3NlZCBhcyB0aGUgdHlwZSBwYXJhbWV0ZXIgdG8gdGhlCiAgICBbYXR0cl0oL2VtYmVyLWRhdGEvcmVsZWFzZS9mdW5jdGlvbnMvQGVtYmVyLWRhdGElMkZtb2RlbC9hdHRyKSBmdW5jdGlvbi4KCiAgICBVc2FnZQoKICAgIGBgYGFwcC9tb2RlbHMvdXNlci5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgaXNBZG1pbjogYXR0cignYm9vbGVhbicpLAogICAgICBuYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgZW1haWw6IGF0dHIoJ3N0cmluZycpCiAgICB9KTsKICAgIGBgYAoKICAgIEJ5IGRlZmF1bHQsIHRoZSBib29sZWFuIHRyYW5zZm9ybSBvbmx5IGFsbG93cyBmb3IgdmFsdWVzIG9mIGB0cnVlYCBvcgogICAgYGZhbHNlYC4gWW91IGNhbiBvcHQgaW50byBhbGxvd2luZyBgbnVsbGAgdmFsdWVzIGZvcgogICAgYm9vbGVhbiBhdHRyaWJ1dGVzIHZpYSBgYXR0cignYm9vbGVhbicsIHsgYWxsb3dOdWxsOiB0cnVlIH0pYAoKICAgIGBgYGFwcC9tb2RlbHMvdXNlci5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgZW1haWw6IGF0dHIoJ3N0cmluZycpLAogICAgICB1c2VybmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgIHdhbnRzV2Vla2x5RW1haWw6IGF0dHIoJ2Jvb2xlYW4nLCB7IGFsbG93TnVsbDogdHJ1ZSB9KQogICAgfSk7CiAgICBgYGAKCiAgICBAY2xhc3MgQm9vbGVhblRyYW5zZm9ybQogICAgQGV4dGVuZHMgVHJhbnNmb3JtCiAgICovCgogIHZhciBib29sZWFuID0gVHJhbnNmb3JtLmV4dGVuZCh7CiAgICBkZXNlcmlhbGl6ZTogZnVuY3Rpb24gZGVzZXJpYWxpemUoc2VyaWFsaXplZCwgb3B0aW9ucykgewogICAgICBpZiAoRW1iZXIuaXNOb25lKHNlcmlhbGl6ZWQpICYmIG9wdGlvbnMuYWxsb3dOdWxsID09PSB0cnVlKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KCiAgICAgIHZhciB0eXBlID0gdHlwZW9mIHNlcmlhbGl6ZWQ7CgogICAgICBpZiAodHlwZSA9PT0gJ2Jvb2xlYW4nKSB7CiAgICAgICAgcmV0dXJuIHNlcmlhbGl6ZWQ7CiAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHsKICAgICAgICByZXR1cm4gL14odHJ1ZXx0fDEpJC9pLnRlc3Qoc2VyaWFsaXplZCk7CiAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ251bWJlcicpIHsKICAgICAgICByZXR1cm4gc2VyaWFsaXplZCA9PT0gMTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0sCiAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIHNlcmlhbGl6ZShkZXNlcmlhbGl6ZWQsIG9wdGlvbnMpIHsKICAgICAgaWYgKEVtYmVyLmlzTm9uZShkZXNlcmlhbGl6ZWQpICYmIG9wdGlvbnMuYWxsb3dOdWxsID09PSB0cnVlKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KCiAgICAgIHJldHVybiBCb29sZWFuKGRlc2VyaWFsaXplZCk7CiAgICB9CiAgfSk7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zZXJpYWxpemVyCiAgKi8KCiAgLyoqCiAgIFRoZSBgRGF0ZVRyYW5zZm9ybWAgY2xhc3MgaXMgdXNlZCB0byBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplCiAgIGRhdGUgYXR0cmlidXRlcyBvbiBFbWJlciBEYXRhIHJlY29yZCBvYmplY3RzLiBUaGlzIHRyYW5zZm9ybSBpcyB1c2VkCiAgIHdoZW4gYGRhdGVgIGlzIHBhc3NlZCBhcyB0aGUgdHlwZSBwYXJhbWV0ZXIgdG8gdGhlCiAgIFthdHRyXSgvZW1iZXItZGF0YS9yZWxlYXNlL2Z1bmN0aW9ucy9AZW1iZXItZGF0YSUyRm1vZGVsL2F0dHIpIGZ1bmN0aW9uLiBJdCB1c2VzIHRoZSBbYElTTyA4NjAxYF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPXzg2MDEpCiAgIHN0YW5kYXJkLgoKICAgYGBgYXBwL21vZGVscy9zY29yZS5qcwogICBpbXBvcnQgTW9kZWwsIHsgYXR0ciwgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgdmFsdWU6IGF0dHIoJ251bWJlcicpLAogICAgICBwbGF5ZXI6IGJlbG9uZ3NUbygncGxheWVyJyksCiAgICAgIGRhdGU6IGF0dHIoJ2RhdGUnKQogICAgfSk7CiAgIGBgYAoKICAgQGNsYXNzIERhdGVUcmFuc2Zvcm0KICAgQGV4dGVuZHMgVHJhbnNmb3JtCiAgICovCgogIHZhciBkYXRlID0gVHJhbnNmb3JtLmV4dGVuZCh7CiAgICBkZXNlcmlhbGl6ZTogZnVuY3Rpb24gZGVzZXJpYWxpemUoc2VyaWFsaXplZCkgewogICAgICB2YXIgdHlwZSA9IHR5cGVvZiBzZXJpYWxpemVkOwoKICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgdmFyIG9mZnNldCA9IHNlcmlhbGl6ZWQuaW5kZXhPZignKycpOwoKICAgICAgICBpZiAob2Zmc2V0ICE9PSAtMSAmJiBzZXJpYWxpemVkLmxlbmd0aCAtIDUgPT09IG9mZnNldCkgewogICAgICAgICAgb2Zmc2V0ICs9IDM7CiAgICAgICAgICByZXR1cm4gbmV3IERhdGUoc2VyaWFsaXplZC5zbGljZSgwLCBvZmZzZXQpICsgJzonICsgc2VyaWFsaXplZC5zbGljZShvZmZzZXQpKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiBuZXcgRGF0ZShzZXJpYWxpemVkKTsKICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJykgewogICAgICAgIHJldHVybiBuZXcgRGF0ZShzZXJpYWxpemVkKTsKICAgICAgfSBlbHNlIGlmIChzZXJpYWxpemVkID09PSBudWxsIHx8IHNlcmlhbGl6ZWQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIC8vIGlmIHRoZSB2YWx1ZSBpcyBudWxsIHJldHVybiBudWxsCiAgICAgICAgLy8gaWYgdGhlIHZhbHVlIGlzIG5vdCBwcmVzZW50IGluIHRoZSBkYXRhIHJldHVybiB1bmRlZmluZWQKICAgICAgICByZXR1cm4gc2VyaWFsaXplZDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfSwKICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gc2VyaWFsaXplKGRhdGUpIHsKICAgICAgaWYgKGRhdGUgaW5zdGFuY2VvZiBEYXRlICYmICFpc05hTihkYXRlKSkgewogICAgICAgIHJldHVybiBkYXRlLnRvSVNPU3RyaW5nKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH0KICB9KTsKCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3NlcmlhbGl6ZXIKICAqLwoKICBmdW5jdGlvbiBpc051bWJlcih2YWx1ZSkgewogICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZSAmJiB2YWx1ZSAhPT0gSW5maW5pdHkgJiYgdmFsdWUgIT09IC1JbmZpbml0eTsKICB9CiAgLyoqCiAgICBUaGUgYE51bWJlclRyYW5zZm9ybWAgY2xhc3MgaXMgdXNlZCB0byBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplCiAgICBudW1lcmljIGF0dHJpYnV0ZXMgb24gRW1iZXIgRGF0YSByZWNvcmQgb2JqZWN0cy4gVGhpcyB0cmFuc2Zvcm0gaXMKICAgIHVzZWQgd2hlbiBgbnVtYmVyYCBpcyBwYXNzZWQgYXMgdGhlIHR5cGUgcGFyYW1ldGVyIHRvIHRoZQogICAgW2F0dHJdKC9lbWJlci1kYXRhL3JlbGVhc2UvZnVuY3Rpb25zL0BlbWJlci1kYXRhJTJGbW9kZWwvYXR0cikgZnVuY3Rpb24uCgogICAgVXNhZ2UKCiAgICBgYGBhcHAvbW9kZWxzL3Njb3JlLmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciwgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwoKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIHZhbHVlOiBhdHRyKCdudW1iZXInKSwKICAgICAgcGxheWVyOiBiZWxvbmdzVG8oJ3BsYXllcicpLAogICAgICBkYXRlOiBhdHRyKCdkYXRlJykKICAgIH0pOwogICAgYGBgCgogICAgQGNsYXNzIE51bWJlclRyYW5zZm9ybQogICAgQGV4dGVuZHMgVHJhbnNmb3JtCiAgICovCgoKICB2YXIgbnVtYmVyID0gVHJhbnNmb3JtLmV4dGVuZCh7CiAgICBkZXNlcmlhbGl6ZTogZnVuY3Rpb24gZGVzZXJpYWxpemUoc2VyaWFsaXplZCkgewogICAgICB2YXIgdHJhbnNmb3JtZWQ7CgogICAgICBpZiAoc2VyaWFsaXplZCA9PT0gJycgfHwgc2VyaWFsaXplZCA9PT0gbnVsbCB8fCBzZXJpYWxpemVkID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0cmFuc2Zvcm1lZCA9IE51bWJlcihzZXJpYWxpemVkKTsKICAgICAgICByZXR1cm4gaXNOdW1iZXIodHJhbnNmb3JtZWQpID8gdHJhbnNmb3JtZWQgOiBudWxsOwogICAgICB9CiAgICB9LAogICAgc2VyaWFsaXplOiBmdW5jdGlvbiBzZXJpYWxpemUoZGVzZXJpYWxpemVkKSB7CiAgICAgIHZhciB0cmFuc2Zvcm1lZDsKCiAgICAgIGlmIChkZXNlcmlhbGl6ZWQgPT09ICcnIHx8IGRlc2VyaWFsaXplZCA9PT0gbnVsbCB8fCBkZXNlcmlhbGl6ZWQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9IGVsc2UgewogICAgICAgIHRyYW5zZm9ybWVkID0gTnVtYmVyKGRlc2VyaWFsaXplZCk7CiAgICAgICAgcmV0dXJuIGlzTnVtYmVyKHRyYW5zZm9ybWVkKSA/IHRyYW5zZm9ybWVkIDogbnVsbDsKICAgICAgfQogICAgfQogIH0pOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc2VyaWFsaXplcgogICovCgogIC8qKgogICAgVGhlIGBTdHJpbmdUcmFuc2Zvcm1gIGNsYXNzIGlzIHVzZWQgdG8gc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZQogICAgc3RyaW5nIGF0dHJpYnV0ZXMgb24gRW1iZXIgRGF0YSByZWNvcmQgb2JqZWN0cy4gVGhpcyB0cmFuc2Zvcm0gaXMKICAgIHVzZWQgd2hlbiBgc3RyaW5nYCBpcyBwYXNzZWQgYXMgdGhlIHR5cGUgcGFyYW1ldGVyIHRvIHRoZQogICAgW2F0dHJdKC9lbWJlci1kYXRhL3JlbGVhc2UvZnVuY3Rpb25zL0BlbWJlci1kYXRhJTJGbW9kZWwvYXR0cikgZnVuY3Rpb24uCgogICAgVXNhZ2UKCiAgICBgYGBhcHAvbW9kZWxzL3VzZXIuanMKICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyLCBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgaXNBZG1pbjogYXR0cignYm9vbGVhbicpLAogICAgICBuYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgZW1haWw6IGF0dHIoJ3N0cmluZycpCiAgICB9KTsKICAgIGBgYAoKICAgIEBjbGFzcyBTdHJpbmdUcmFuc2Zvcm0KICAgIEBleHRlbmRzIFRyYW5zZm9ybQogICAqLwoKICB2YXIgc3RyaW5nID0gVHJhbnNmb3JtLmV4dGVuZCh7CiAgICBkZXNlcmlhbGl6ZTogZnVuY3Rpb24gZGVzZXJpYWxpemUoc2VyaWFsaXplZCkgewogICAgICByZXR1cm4gRW1iZXIuaXNOb25lKHNlcmlhbGl6ZWQpID8gbnVsbCA6IFN0cmluZyhzZXJpYWxpemVkKTsKICAgIH0sCiAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIHNlcmlhbGl6ZShkZXNlcmlhbGl6ZWQpIHsKICAgICAgcmV0dXJuIEVtYmVyLmlzTm9uZShkZXNlcmlhbGl6ZWQpID8gbnVsbCA6IFN0cmluZyhkZXNlcmlhbGl6ZWQpOwogICAgfQogIH0pOwoKICBleHBvcnRzLkJvb2xlYW5UcmFuc2Zvcm0gPSBib29sZWFuOwogIGV4cG9ydHMuRGF0ZVRyYW5zZm9ybSA9IGRhdGU7CiAgZXhwb3J0cy5FbWJlZGRlZFJlY29yZHNNaXhpbiA9IGVtYmVkZGVkUmVjb3Jkc01peGluOwogIGV4cG9ydHMuTnVtYmVyVHJhbnNmb3JtID0gbnVtYmVyOwogIGV4cG9ydHMuU3RyaW5nVHJhbnNmb3JtID0gc3RyaW5nOwogIGV4cG9ydHMuVHJhbnNmb3JtID0gVHJhbnNmb3JtOwogIGV4cG9ydHMubW9kZWxIYXNBdHRyaWJ1dGVPclJlbGF0aW9uc2hpcE5hbWVkVHlwZSA9IG1vZGVsSGFzQXR0cmlidXRlT3JSZWxhdGlvbnNoaXBOYW1lZFR5cGU7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7Cgp9KTsKCjtkZWZpbmUoIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvaW5kZXgiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgIGBTZXJpYWxpemVyYCBpcyBhbiBhYnN0cmFjdCBiYXNlIGNsYXNzIHRoYXQgeW91IHNob3VsZCBvdmVycmlkZSBpbiB5b3VyCiAgICBhcHBsaWNhdGlvbiB0byBjdXN0b21pemUgaXQgZm9yIHlvdXIgYmFja2VuZC4gVGhlIG1pbmltdW0gc2V0IG9mIG1ldGhvZHMKICAgIHRoYXQgeW91IHNob3VsZCBpbXBsZW1lbnQgaXM6CiAgCiAgICAgICogYG5vcm1hbGl6ZVJlc3BvbnNlKClgCiAgICAgICogYHNlcmlhbGl6ZSgpYAogIAogICAgQW5kIHlvdSBjYW4gb3B0aW9uYWxseSBvdmVycmlkZSB0aGUgZm9sbG93aW5nIG1ldGhvZHM6CiAgCiAgICAgICogYG5vcm1hbGl6ZSgpYAogIAogICAgRm9yIGFuIGV4YW1wbGUgaW1wbGVtZW50YXRpb24sIHNlZQogICAgW0pTT05TZXJpYWxpemVyXShKU09OU2VyaWFsaXplciksIHRoZSBpbmNsdWRlZCBKU09OIHNlcmlhbGl6ZXIuCiAgCiAgICBAY2xhc3MgU2VyaWFsaXplcgogICAgQGV4dGVuZHMgRW1iZXJPYmplY3QKICAqLwogIHZhciBfZGVmYXVsdCA9IEVtYmVyLk9iamVjdC5leHRlbmQoewogICAgLyoqCiAgICAgIFRoZSBgc3RvcmVgIHByb3BlcnR5IGlzIHRoZSBhcHBsaWNhdGlvbidzIGBzdG9yZWAgdGhhdCBjb250YWlucwogICAgICBhbGwgcmVjb3Jkcy4gSXQgY2FuIGJlIHVzZWQgdG8gbG9vayB1cCBzZXJpYWxpemVycyBmb3Igb3RoZXIgbW9kZWwKICAgICAgdHlwZXMgdGhhdCBtYXkgYmUgbmVzdGVkIGluc2lkZSB0aGUgcGF5bG9hZCByZXNwb25zZS4KICAgICAgIEV4YW1wbGU6CiAgICAgICBgYGBqcwogICAgICBTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgZXh0cmFjdFJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXBNb2RlbE5hbWUsIHJlbGF0aW9uc2hpcEhhc2gpIHsKICAgICAgICAgIHZhciBtb2RlbENsYXNzID0gdGhpcy5zdG9yZS5tb2RlbEZvcihyZWxhdGlvbnNoaXBNb2RlbE5hbWUpOwogICAgICAgICAgdmFyIHJlbGF0aW9uc2hpcFNlcmlhbGl6ZXIgPSB0aGlzLnN0b3JlLnNlcmlhbGl6ZXJGb3IocmVsYXRpb25zaGlwTW9kZWxOYW1lKTsKICAgICAgICAgIHJldHVybiByZWxhdGlvbnNoaXBTZXJpYWxpemVyLm5vcm1hbGl6ZShtb2RlbENsYXNzLCByZWxhdGlvbnNoaXBIYXNoKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBzdG9yZQogICAgICBAdHlwZSB7U3RvcmV9CiAgICAgIEBwdWJsaWMKICAgICovCgogICAgLyoqCiAgICAgIFRoZSBgbm9ybWFsaXplUmVzcG9uc2VgIG1ldGhvZCBpcyB1c2VkIHRvIG5vcm1hbGl6ZSBhIHBheWxvYWQgZnJvbSB0aGUKICAgICAgc2VydmVyIHRvIGEgSlNPTi1BUEkgRG9jdW1lbnQuCiAgICAgICBodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0LyNkb2N1bWVudC1zdHJ1Y3R1cmUKICAgICAgIEV4YW1wbGU6CiAgICAgICBgYGBqcwogICAgICBTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgbm9ybWFsaXplUmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgICAgIGlmIChyZXF1ZXN0VHlwZSA9PT0gJ2ZpbmRSZWNvcmQnKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZShwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gcGF5bG9hZC5yZWR1Y2UoZnVuY3Rpb24oZG9jdW1lbnRIYXNoLCBpdGVtKSB7CiAgICAgICAgICAgICAgbGV0IHsgZGF0YSwgaW5jbHVkZWQgfSA9IHRoaXMubm9ybWFsaXplKHByaW1hcnlNb2RlbENsYXNzLCBpdGVtKTsKICAgICAgICAgICAgICBkb2N1bWVudEhhc2guaW5jbHVkZWQucHVzaCguLi5pbmNsdWRlZCk7CiAgICAgICAgICAgICAgZG9jdW1lbnRIYXNoLmRhdGEucHVzaChkYXRhKTsKICAgICAgICAgICAgICByZXR1cm4gZG9jdW1lbnRIYXNoOwogICAgICAgICAgICB9LCB7IGRhdGE6IFtdLCBpbmNsdWRlZDogW10gfSkKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBub3JtYWxpemVSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAqLwogICAgbm9ybWFsaXplUmVzcG9uc2U6IG51bGwsCgogICAgLyoqCiAgICAgIFRoZSBgc2VyaWFsaXplYCBtZXRob2QgaXMgdXNlZCB3aGVuIGEgcmVjb3JkIGlzIHNhdmVkIGluIG9yZGVyIHRvIGNvbnZlcnQKICAgICAgdGhlIHJlY29yZCBpbnRvIHRoZSBmb3JtIHRoYXQgeW91ciBleHRlcm5hbCBkYXRhIHNvdXJjZSBleHBlY3RzLgogICAgICAgYHNlcmlhbGl6ZWAgdGFrZXMgYW4gb3B0aW9uYWwgYG9wdGlvbnNgIGhhc2ggd2l0aCBhIHNpbmdsZSBvcHRpb246CiAgICAgICAtIGBpbmNsdWRlSWRgOiBJZiB0aGlzIGlzIGB0cnVlYCwgYHNlcmlhbGl6ZWAgc2hvdWxkIGluY2x1ZGUgdGhlIElECiAgICAgICAgaW4gdGhlIHNlcmlhbGl6ZWQgb2JqZWN0IGl0IGJ1aWxkcy4KICAgICAgIEV4YW1wbGU6CiAgICAgICBgYGBqcwogICAgICBTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgc2VyaWFsaXplKHNuYXBzaG90LCBvcHRpb25zKSB7CiAgICAgICAgICB2YXIganNvbiA9IHsKICAgICAgICAgICAgaWQ6IHNuYXBzaG90LmlkCiAgICAgICAgICB9OwogICAgICAgICAgIHNuYXBzaG90LmVhY2hBdHRyaWJ1dGUoKGtleSwgYXR0cmlidXRlKSA9PiB7CiAgICAgICAgICAgIGpzb25ba2V5XSA9IHNuYXBzaG90LmF0dHIoa2V5KTsKICAgICAgICAgIH0pOwogICAgICAgICAgIHNuYXBzaG90LmVhY2hSZWxhdGlvbnNoaXAoKGtleSwgcmVsYXRpb25zaGlwKSA9PiB7CiAgICAgICAgICAgIGlmIChyZWxhdGlvbnNoaXAua2luZCA9PT0gJ2JlbG9uZ3NUbycpIHsKICAgICAgICAgICAgICBqc29uW2tleV0gPSBzbmFwc2hvdC5iZWxvbmdzVG8oa2V5LCB7IGlkOiB0cnVlIH0pOwogICAgICAgICAgICB9IGVsc2UgaWYgKHJlbGF0aW9uc2hpcC5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgICAgICAgICBqc29uW2tleV0gPSBzbmFwc2hvdC5oYXNNYW55KGtleSwgeyBpZHM6IHRydWUgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgICAgIHJldHVybiBqc29uOwogICAgICAgIH0sCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc2VyaWFsaXplCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10KICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgKi8KICAgIHNlcmlhbGl6ZTogbnVsbCwKCiAgICAvKioKICAgICAgVGhlIGBub3JtYWxpemVgIG1ldGhvZCBpcyB1c2VkIHRvIGNvbnZlcnQgYSBwYXlsb2FkIHJlY2VpdmVkIGZyb20geW91cgogICAgICBleHRlcm5hbCBkYXRhIHNvdXJjZSBpbnRvIHRoZSBub3JtYWxpemVkIGZvcm0gYHN0b3JlLnB1c2goKWAgZXhwZWN0cy4gWW91CiAgICAgIHNob3VsZCBvdmVycmlkZSB0aGlzIG1ldGhvZCwgbXVuZ2UgdGhlIGhhc2ggYW5kIHJldHVybiB0aGUgbm9ybWFsaXplZAogICAgICBwYXlsb2FkLgogICAgICAgRXhhbXBsZToKICAgICAgIGBgYGpzCiAgICAgIFNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBub3JtYWxpemUobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKSB7CiAgICAgICAgICB2YXIgZGF0YSA9IHsKICAgICAgICAgICAgaWQ6ICAgICAgICAgICAgcmVzb3VyY2VIYXNoLmlkLAogICAgICAgICAgICB0eXBlOiAgICAgICAgICBtb2RlbENsYXNzLm1vZGVsTmFtZSwKICAgICAgICAgICAgYXR0cmlidXRlczogICAgcmVzb3VyY2VIYXNoCiAgICAgICAgICB9OwogICAgICAgICAgcmV0dXJuIHsgZGF0YTogZGF0YSB9OwogICAgICAgIH0KICAgICAgfSkKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIG5vcm1hbGl6ZQogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IGhhc2gKICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgKi8KICAgIG5vcm1hbGl6ZTogZnVuY3Rpb24gbm9ybWFsaXplKHR5cGVDbGFzcywgaGFzaCkgewogICAgICByZXR1cm4gaGFzaDsKICAgIH0KICB9KTsKCiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKO2RlZmluZSgiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uLWFwaSIsIFsiZXhwb3J0cyIsICJlbWJlci1pbmZsZWN0b3IiLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uIiwgIkBlbWJlci1kYXRhL3N0b3JlIiwgIkBlbWJlci1kYXRhL2NhbmFyeS1mZWF0dXJlcyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlckluZmxlY3RvciwgX2pzb24sIF9zdG9yZSwgX2NhbmFyeUZlYXR1cmVzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgIEVtYmVyIERhdGEgMi4wIFNlcmlhbGl6ZXI6CiAgCiAgICBJbiBFbWJlciBEYXRhIGEgU2VyaWFsaXplciBpcyB1c2VkIHRvIHNlcmlhbGl6ZSBhbmQgZGVzZXJpYWxpemUKICAgIHJlY29yZHMgd2hlbiB0aGV5IGFyZSB0cmFuc2ZlcnJlZCBpbiBhbmQgb3V0IG9mIGFuIGV4dGVybmFsIHNvdXJjZS4KICAgIFRoaXMgcHJvY2VzcyBpbnZvbHZlcyBub3JtYWxpemluZyBwcm9wZXJ0eSBuYW1lcywgdHJhbnNmb3JtaW5nCiAgICBhdHRyaWJ1dGUgdmFsdWVzIGFuZCBzZXJpYWxpemluZyByZWxhdGlvbnNoaXBzLgogIAogICAgYEpTT05BUElTZXJpYWxpemVyYCBzdXBwb3J0cyB0aGUgaHR0cDovL2pzb25hcGkub3JnLyBzcGVjIGFuZCBpcyB0aGUKICAgIHNlcmlhbGl6ZXIgcmVjb21tZW5kZWQgYnkgRW1iZXIgRGF0YS4KICAKICAgIFRoaXMgc2VyaWFsaXplciBub3JtYWxpemVzIGEgSlNPTiBBUEkgcGF5bG9hZCB0aGF0IGxvb2tzIGxpa2U6CiAgCiAgICBgYGBhcHAvbW9kZWxzL3BsYXllci5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIsIGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgIG5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICBza2lsbDogYXR0cignc3RyaW5nJyksCiAgICAgIGdhbWVzUGxheWVkOiBhdHRyKCdudW1iZXInKSwKICAgICAgY2x1YjogYmVsb25nc1RvKCdjbHViJykKICAgIH0pOwogICAgYGBgCiAgCiAgICBgYGBhcHAvbW9kZWxzL2NsdWIuanMKICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyLCBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgbmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgIGxvY2F0aW9uOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgcGxheWVyczogaGFzTWFueSgncGxheWVyJykKICAgIH0pOwogICAgYGBgCiAgCiAgICBgYGBqcwogICAgICB7CiAgICAgICAgImRhdGEiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJhdHRyaWJ1dGVzIjogewogICAgICAgICAgICAgICJuYW1lIjogIkJlbmZpY2EiLAogICAgICAgICAgICAgICJsb2NhdGlvbiI6ICJQb3J0dWdhbCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgImlkIjogIjEiLAogICAgICAgICAgICAicmVsYXRpb25zaGlwcyI6IHsKICAgICAgICAgICAgICAicGxheWVycyI6IHsKICAgICAgICAgICAgICAgICJkYXRhIjogWwogICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgImlkIjogIjMiLAogICAgICAgICAgICAgICAgICAgICJ0eXBlIjogInBsYXllcnMiCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIF0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJ0eXBlIjogImNsdWJzIgogICAgICAgICAgfQogICAgICAgIF0sCiAgICAgICAgImluY2x1ZGVkIjogWwogICAgICAgICAgewogICAgICAgICAgICAiYXR0cmlidXRlcyI6IHsKICAgICAgICAgICAgICAibmFtZSI6ICJFdXNlYmlvIFNpbHZhIEZlcnJlaXJhIiwKICAgICAgICAgICAgICAic2tpbGwiOiAiUm9ja2V0IHNob3QiLAogICAgICAgICAgICAgICJnYW1lcy1wbGF5ZWQiOiA0MzEKICAgICAgICAgICAgfSwKICAgICAgICAgICAgImlkIjogIjMiLAogICAgICAgICAgICAicmVsYXRpb25zaGlwcyI6IHsKICAgICAgICAgICAgICAiY2x1YiI6IHsKICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAiaWQiOiAiMSIsCiAgICAgICAgICAgICAgICAgICJ0eXBlIjogImNsdWJzIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgInR5cGUiOiAicGxheWVycyIKICAgICAgICAgIH0KICAgICAgICBdCiAgICAgIH0KICAgIGBgYAogIAogICAgdG8gdGhlIGZvcm1hdCB0aGF0IHRoZSBFbWJlciBEYXRhIHN0b3JlIGV4cGVjdHMuCiAgCiAgICAjIyMgQ3VzdG9taXppbmcgbWV0YQogIAogICAgU2luY2UgYSBKU09OIEFQSSBEb2N1bWVudCBjYW4gaGF2ZSBtZXRhIGRlZmluZWQgaW4gbXVsdGlwbGUgbG9jYXRpb25zIHlvdSBjYW4KICAgIHVzZSB0aGUgc3BlY2lmaWMgc2VyaWFsaXplciBob29rcyBpZiB5b3UgbmVlZCB0byBjdXN0b21pemUgdGhlIG1ldGEuCiAgCiAgICBPbmUgc2NlbmFyaW8gd291bGQgYmUgdG8gY2FtZWxDYXNlIHRoZSBtZXRhIGtleXMgb2YgeW91ciBwYXlsb2FkLiBUaGUgZXhhbXBsZQogICAgYmVsb3cgc2hvd3MgaG93IHRoaXMgY291bGQgYmUgZG9uZSB1c2luZyBgbm9ybWFsaXplQXJyYXlSZXNwb25zZWAgYW5kCiAgICBgZXh0cmFjdFJlbGF0aW9uc2hpcGAuCiAgCiAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgIGV4cG9ydCBkZWZhdWx0IEpTT05BUElTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgIG5vcm1hbGl6ZUFycmF5UmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgICBsZXQgbm9ybWFsaXplZERvY3VtZW50ID0gdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAKICAgICAgICAvLyBDdXN0b21pemUgZG9jdW1lbnQgbWV0YQogICAgICAgIG5vcm1hbGl6ZWREb2N1bWVudC5tZXRhID0gY2FtZWxDYXNlS2V5cyhub3JtYWxpemVkRG9jdW1lbnQubWV0YSk7CiAgCiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWREb2N1bWVudDsKICAgICAgfSwKICAKICAgICAgZXh0cmFjdFJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXBIYXNoKSB7CiAgICAgICAgbGV0IG5vcm1hbGl6ZWRSZWxhdGlvbnNoaXAgPSB0aGlzLl9zdXBlciguLi5hcmd1bWVudHMpOwogIAogICAgICAgIC8vIEN1c3RvbWl6ZSByZWxhdGlvbnNoaXAgbWV0YQogICAgICAgIG5vcm1hbGl6ZWRSZWxhdGlvbnNoaXAubWV0YSA9IGNhbWVsQ2FzZUtleXMobm9ybWFsaXplZFJlbGF0aW9uc2hpcC5tZXRhKTsKICAKICAgICAgICByZXR1cm4gbm9ybWFsaXplZFJlbGF0aW9uc2hpcDsKICAgICAgfQogICAgfSk7CiAgICBgYGAKICAKICAgIEBzaW5jZSAxLjEzLjAKICAgIEBjbGFzcyBKU09OQVBJU2VyaWFsaXplcgogICAgQGV4dGVuZHMgSlNPTlNlcmlhbGl6ZXIKICAqLwogIHZhciBKU09OQVBJU2VyaWFsaXplciA9IF9qc29uLmRlZmF1bHQuZXh0ZW5kKHsKICAgIC8qKgogICAgICBAbWV0aG9kIF9ub3JtYWxpemVEb2N1bWVudEhlbHBlcgogICAgICBAcGFyYW0ge09iamVjdH0gZG9jdW1lbnRIYXNoCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICAgQHByaXZhdGUKICAgICovCiAgICBfbm9ybWFsaXplRG9jdW1lbnRIZWxwZXI6IGZ1bmN0aW9uIF9ub3JtYWxpemVEb2N1bWVudEhlbHBlcihkb2N1bWVudEhhc2gpIHsKICAgICAgaWYgKEVtYmVyLnR5cGVPZihkb2N1bWVudEhhc2guZGF0YSkgPT09ICdvYmplY3QnKSB7CiAgICAgICAgZG9jdW1lbnRIYXNoLmRhdGEgPSB0aGlzLl9ub3JtYWxpemVSZXNvdXJjZUhlbHBlcihkb2N1bWVudEhhc2guZGF0YSk7CiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShkb2N1bWVudEhhc2guZGF0YSkpIHsKICAgICAgICB2YXIgcmV0ID0gbmV3IEFycmF5KGRvY3VtZW50SGFzaC5kYXRhLmxlbmd0aCk7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZG9jdW1lbnRIYXNoLmRhdGEubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHZhciBkYXRhID0gZG9jdW1lbnRIYXNoLmRhdGFbaV07CiAgICAgICAgICByZXRbaV0gPSB0aGlzLl9ub3JtYWxpemVSZXNvdXJjZUhlbHBlcihkYXRhKTsKICAgICAgICB9CgogICAgICAgIGRvY3VtZW50SGFzaC5kYXRhID0gcmV0OwogICAgICB9CgogICAgICBpZiAoQXJyYXkuaXNBcnJheShkb2N1bWVudEhhc2guaW5jbHVkZWQpKSB7CiAgICAgICAgdmFyIF9yZXQgPSBuZXcgQXJyYXkoKTsKCiAgICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGRvY3VtZW50SGFzaC5pbmNsdWRlZC5sZW5ndGg7IF9pKyspIHsKICAgICAgICAgIHZhciBpbmNsdWRlZCA9IGRvY3VtZW50SGFzaC5pbmNsdWRlZFtfaV07CgogICAgICAgICAgdmFyIG5vcm1hbGl6ZWQgPSB0aGlzLl9ub3JtYWxpemVSZXNvdXJjZUhlbHBlcihpbmNsdWRlZCk7CgogICAgICAgICAgaWYgKG5vcm1hbGl6ZWQgIT09IG51bGwpIHsKICAgICAgICAgICAgLy8gY2FuIGJlIG51bGwgd2hlbiB1bmtub3duIHR5cGUgaXMgZW5jb3VudGVyZWQKICAgICAgICAgICAgX3JldC5wdXNoKG5vcm1hbGl6ZWQpOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZG9jdW1lbnRIYXNoLmluY2x1ZGVkID0gX3JldDsKICAgICAgfQoKICAgICAgcmV0dXJuIGRvY3VtZW50SGFzaDsKICAgIH0sCgogICAgLyoqCiAgICAgIEBtZXRob2QgX25vcm1hbGl6ZVJlbGF0aW9uc2hpcERhdGFIZWxwZXIKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlbGF0aW9uc2hpcERhdGFIYXNoCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICAgQHByaXZhdGUKICAgICovCiAgICBfbm9ybWFsaXplUmVsYXRpb25zaGlwRGF0YUhlbHBlcjogZnVuY3Rpb24gX25vcm1hbGl6ZVJlbGF0aW9uc2hpcERhdGFIZWxwZXIocmVsYXRpb25zaGlwRGF0YUhhc2gpIHsKICAgICAgcmVsYXRpb25zaGlwRGF0YUhhc2gudHlwZSA9IHRoaXMubW9kZWxOYW1lRnJvbVBheWxvYWRLZXkocmVsYXRpb25zaGlwRGF0YUhhc2gudHlwZSk7CiAgICAgIHJldHVybiByZWxhdGlvbnNoaXBEYXRhSGFzaDsKICAgIH0sCgogICAgLyoqCiAgICAgIEBtZXRob2QgX25vcm1hbGl6ZVJlc291cmNlSGVscGVyCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZXNvdXJjZUhhc2gKICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ub3JtYWxpemVSZXNvdXJjZUhlbHBlcjogZnVuY3Rpb24gX25vcm1hbGl6ZVJlc291cmNlSGVscGVyKHJlc291cmNlSGFzaCkgewogICAgICAoZmFsc2UgJiYgISghRW1iZXIuaXNOb25lKHJlc291cmNlSGFzaC50eXBlKSkgJiYgRW1iZXIuYXNzZXJ0KHRoaXMud2Fybk1lc3NhZ2VGb3JVbmRlZmluZWRUeXBlKCksICFFbWJlci5pc05vbmUocmVzb3VyY2VIYXNoLnR5cGUpLCB7CiAgICAgICAgaWQ6ICdkcy5zZXJpYWxpemVyLnR5cGUtaXMtdW5kZWZpbmVkJwogICAgICB9KSk7CiAgICAgIHZhciBtb2RlbE5hbWUsIHVzZWRMb29rdXA7CiAgICAgIG1vZGVsTmFtZSA9IHRoaXMubW9kZWxOYW1lRnJvbVBheWxvYWRLZXkocmVzb3VyY2VIYXNoLnR5cGUpOwogICAgICB1c2VkTG9va3VwID0gJ21vZGVsTmFtZUZyb21QYXlsb2FkS2V5JzsKCiAgICAgIGlmICghdGhpcy5zdG9yZS5faGFzTW9kZWxGb3IobW9kZWxOYW1lKSkgewogICAgICAgIChmYWxzZSAmJiBFbWJlci53YXJuKHRoaXMud2Fybk1lc3NhZ2VOb01vZGVsRm9yVHlwZShtb2RlbE5hbWUsIHJlc291cmNlSGFzaC50eXBlLCB1c2VkTG9va3VwKSwgZmFsc2UsIHsKICAgICAgICAgIGlkOiAnZHMuc2VyaWFsaXplci5tb2RlbC1mb3ItdHlwZS1taXNzaW5nJwogICAgICAgIH0pKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIG1vZGVsQ2xhc3MgPSB0aGlzLnN0b3JlLm1vZGVsRm9yKG1vZGVsTmFtZSk7CiAgICAgIHZhciBzZXJpYWxpemVyID0gdGhpcy5zdG9yZS5zZXJpYWxpemVyRm9yKG1vZGVsTmFtZSk7CgogICAgICB2YXIgX3NlcmlhbGl6ZXIkbm9ybWFsaXplID0gc2VyaWFsaXplci5ub3JtYWxpemUobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKSwKICAgICAgICAgIGRhdGEgPSBfc2VyaWFsaXplciRub3JtYWxpemUuZGF0YTsKCiAgICAgIHJldHVybiBkYXRhOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBwdXNoUGF5bG9hZAogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgKi8KICAgIHB1c2hQYXlsb2FkOiBmdW5jdGlvbiBwdXNoUGF5bG9hZChzdG9yZSwgcGF5bG9hZCkgewogICAgICB2YXIgbm9ybWFsaXplZFBheWxvYWQgPSB0aGlzLl9ub3JtYWxpemVEb2N1bWVudEhlbHBlcihwYXlsb2FkKTsKCiAgICAgIHN0b3JlLnB1c2gobm9ybWFsaXplZFBheWxvYWQpOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBfbm9ybWFsaXplUmVzcG9uc2UKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gcHJpbWFyeU1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgICBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFR5cGUKICAgICAgQHBhcmFtIHtCb29sZWFufSBpc1NpbmdsZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX25vcm1hbGl6ZVJlc3BvbnNlOiBmdW5jdGlvbiBfbm9ybWFsaXplUmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUsIGlzU2luZ2xlKSB7CiAgICAgIHZhciBub3JtYWxpemVkUGF5bG9hZCA9IHRoaXMuX25vcm1hbGl6ZURvY3VtZW50SGVscGVyKHBheWxvYWQpOwoKICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRQYXlsb2FkOwogICAgfSwKICAgIG5vcm1hbGl6ZVF1ZXJ5UmVjb3JkUmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZVF1ZXJ5UmVjb3JkUmVzcG9uc2UoKSB7CiAgICAgIHZhciBub3JtYWxpemVkID0gdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgIChmYWxzZSAmJiAhKCFBcnJheS5pc0FycmF5KG5vcm1hbGl6ZWQuZGF0YSkpICYmIEVtYmVyLmFzc2VydCgnRXhwZWN0ZWQgdGhlIHByaW1hcnkgZGF0YSByZXR1cm5lZCBieSB0aGUgc2VyaWFsaXplciBmb3IgYSBgcXVlcnlSZWNvcmRgIHJlc3BvbnNlIHRvIGJlIGEgc2luZ2xlIG9iamVjdCBidXQgaW5zdGVhZCBpdCB3YXMgYW4gYXJyYXkuJywgIUFycmF5LmlzQXJyYXkobm9ybWFsaXplZC5kYXRhKSwgewogICAgICAgIGlkOiAnZHMuc2VyaWFsaXplci5qc29uLWFwaS5xdWVyeVJlY29yZC1hcnJheS1yZXNwb25zZScKICAgICAgfSkpOwogICAgICByZXR1cm4gbm9ybWFsaXplZDsKICAgIH0sCiAgICBleHRyYWN0QXR0cmlidXRlczogZnVuY3Rpb24gZXh0cmFjdEF0dHJpYnV0ZXMobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICB2YXIgYXR0cmlidXRlcyA9IHt9OwoKICAgICAgaWYgKHJlc291cmNlSGFzaC5hdHRyaWJ1dGVzKSB7CiAgICAgICAgbW9kZWxDbGFzcy5lYWNoQXR0cmlidXRlKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgIHZhciBhdHRyaWJ1dGVLZXkgPSBfdGhpcy5rZXlGb3JBdHRyaWJ1dGUoa2V5LCAnZGVzZXJpYWxpemUnKTsKCiAgICAgICAgICBpZiAocmVzb3VyY2VIYXNoLmF0dHJpYnV0ZXNbYXR0cmlidXRlS2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGF0dHJpYnV0ZXNba2V5XSA9IHJlc291cmNlSGFzaC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZUtleV07CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICAgKSB7CiAgICAgICAgICAgIGlmIChyZXNvdXJjZUhhc2guYXR0cmlidXRlc1thdHRyaWJ1dGVLZXldID09PSB1bmRlZmluZWQgJiYgcmVzb3VyY2VIYXNoLmF0dHJpYnV0ZXNba2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmIEVtYmVyLmFzc2VydCgiWW91ciBwYXlsb2FkIGZvciAnIiArIG1vZGVsQ2xhc3MubW9kZWxOYW1lICsgIicgY29udGFpbnMgJyIgKyBrZXkgKyAiJywgYnV0IHlvdXIgc2VyaWFsaXplciBpcyBzZXR1cCB0byBsb29rIGZvciAnIiArIGF0dHJpYnV0ZUtleSArICInLiBUaGlzIGlzIG1vc3QgbGlrZWx5IGJlY2F1c2UgRW1iZXIgRGF0YSdzIEpTT04gQVBJIHNlcmlhbGl6ZXIgZGFzaGVyaXplcyBhdHRyaWJ1dGUga2V5cyBieSBkZWZhdWx0LiBZb3Ugc2hvdWxkIHN1YmNsYXNzIEpTT05BUElTZXJpYWxpemVyIGFuZCBpbXBsZW1lbnQgJ2tleUZvckF0dHJpYnV0ZShrZXkpIHsgcmV0dXJuIGtleTsgfScgdG8gcHJldmVudCBFbWJlciBEYXRhIGZyb20gY3VzdG9taXppbmcgeW91ciBhdHRyaWJ1dGUga2V5cy4iLCBmYWxzZSkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBhdHRyaWJ1dGVzOwogICAgfSwKCiAgICAvKioKICAgICAgIFJldHVybnMgYSByZWxhdGlvbnNoaXAgZm9ybWF0dGVkIGFzIGEgSlNPTi1BUEkgInJlbGF0aW9uc2hpcCBvYmplY3QiLgogICAgICAgIGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2RvY3VtZW50LXJlc291cmNlLW9iamVjdC1yZWxhdGlvbnNoaXBzCiAgICAgICAgQG1ldGhvZCBleHRyYWN0UmVsYXRpb25zaGlwCiAgICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwSGFzaAogICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgKi8KICAgIGV4dHJhY3RSZWxhdGlvbnNoaXA6IGZ1bmN0aW9uIGV4dHJhY3RSZWxhdGlvbnNoaXAocmVsYXRpb25zaGlwSGFzaCkgewogICAgICBpZiAoRW1iZXIudHlwZU9mKHJlbGF0aW9uc2hpcEhhc2guZGF0YSkgPT09ICdvYmplY3QnKSB7CiAgICAgICAgcmVsYXRpb25zaGlwSGFzaC5kYXRhID0gdGhpcy5fbm9ybWFsaXplUmVsYXRpb25zaGlwRGF0YUhlbHBlcihyZWxhdGlvbnNoaXBIYXNoLmRhdGEpOwogICAgICB9CgogICAgICBpZiAoQXJyYXkuaXNBcnJheShyZWxhdGlvbnNoaXBIYXNoLmRhdGEpKSB7CiAgICAgICAgdmFyIHJldCA9IG5ldyBBcnJheShyZWxhdGlvbnNoaXBIYXNoLmRhdGEubGVuZ3RoKTsKCiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZWxhdGlvbnNoaXBIYXNoLmRhdGEubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHZhciBkYXRhID0gcmVsYXRpb25zaGlwSGFzaC5kYXRhW2ldOwogICAgICAgICAgcmV0W2ldID0gdGhpcy5fbm9ybWFsaXplUmVsYXRpb25zaGlwRGF0YUhlbHBlcihkYXRhKTsKICAgICAgICB9CgogICAgICAgIHJlbGF0aW9uc2hpcEhhc2guZGF0YSA9IHJldDsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcEhhc2g7CiAgICB9LAoKICAgIC8qKgogICAgICAgUmV0dXJucyB0aGUgcmVzb3VyY2UncyByZWxhdGlvbnNoaXBzIGZvcm1hdHRlZCBhcyBhIEpTT04tQVBJICJyZWxhdGlvbnNoaXBzIG9iamVjdCIuCiAgICAgICAgaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdC8jZG9jdW1lbnQtcmVzb3VyY2Utb2JqZWN0LXJlbGF0aW9uc2hpcHMKICAgICAgICBAbWV0aG9kIGV4dHJhY3RSZWxhdGlvbnNoaXBzCiAgICAgICBAcGFyYW0ge09iamVjdH0gbW9kZWxDbGFzcwogICAgICAgQHBhcmFtIHtPYmplY3R9IHJlc291cmNlSGFzaAogICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgKi8KICAgIGV4dHJhY3RSZWxhdGlvbnNoaXBzOiBmdW5jdGlvbiBleHRyYWN0UmVsYXRpb25zaGlwcyhtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICB2YXIgcmVsYXRpb25zaGlwcyA9IHt9OwoKICAgICAgaWYgKHJlc291cmNlSGFzaC5yZWxhdGlvbnNoaXBzKSB7CiAgICAgICAgbW9kZWxDbGFzcy5lYWNoUmVsYXRpb25zaGlwKGZ1bmN0aW9uIChrZXksIHJlbGF0aW9uc2hpcE1ldGEpIHsKICAgICAgICAgIHZhciByZWxhdGlvbnNoaXBLZXkgPSBfdGhpczIua2V5Rm9yUmVsYXRpb25zaGlwKGtleSwgcmVsYXRpb25zaGlwTWV0YS5raW5kLCAnZGVzZXJpYWxpemUnKTsKCiAgICAgICAgICBpZiAocmVzb3VyY2VIYXNoLnJlbGF0aW9uc2hpcHNbcmVsYXRpb25zaGlwS2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHZhciByZWxhdGlvbnNoaXBIYXNoID0gcmVzb3VyY2VIYXNoLnJlbGF0aW9uc2hpcHNbcmVsYXRpb25zaGlwS2V5XTsKICAgICAgICAgICAgcmVsYXRpb25zaGlwc1trZXldID0gX3RoaXMyLmV4dHJhY3RSZWxhdGlvbnNoaXAocmVsYXRpb25zaGlwSGFzaCk7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKGZhbHNlCiAgICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICAgKSB7CiAgICAgICAgICAgIGlmIChyZXNvdXJjZUhhc2gucmVsYXRpb25zaGlwc1tyZWxhdGlvbnNoaXBLZXldID09PSB1bmRlZmluZWQgJiYgcmVzb3VyY2VIYXNoLnJlbGF0aW9uc2hpcHNba2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgKGZhbHNlICYmICEoZmFsc2UpICYmIEVtYmVyLmFzc2VydCgiWW91ciBwYXlsb2FkIGZvciAnIiArIG1vZGVsQ2xhc3MubW9kZWxOYW1lICsgIicgY29udGFpbnMgJyIgKyBrZXkgKyAiJywgYnV0IHlvdXIgc2VyaWFsaXplciBpcyBzZXR1cCB0byBsb29rIGZvciAnIiArIHJlbGF0aW9uc2hpcEtleSArICInLiBUaGlzIGlzIG1vc3QgbGlrZWx5IGJlY2F1c2UgRW1iZXIgRGF0YSdzIEpTT04gQVBJIHNlcmlhbGl6ZXIgZGFzaGVyaXplcyByZWxhdGlvbnNoaXAga2V5cyBieSBkZWZhdWx0LiBZb3Ugc2hvdWxkIHN1YmNsYXNzIEpTT05BUElTZXJpYWxpemVyIGFuZCBpbXBsZW1lbnQgJ2tleUZvclJlbGF0aW9uc2hpcChrZXkpIHsgcmV0dXJuIGtleTsgfScgdG8gcHJldmVudCBFbWJlciBEYXRhIGZyb20gY3VzdG9taXppbmcgeW91ciByZWxhdGlvbnNoaXAga2V5cy4iLCBmYWxzZSkpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiByZWxhdGlvbnNoaXBzOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBfZXh0cmFjdFR5cGUKICAgICAgQHBhcmFtIHtNb2RlbH0gbW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcmVzb3VyY2VIYXNoCiAgICAgIEByZXR1cm4ge1N0cmluZ30KICAgICAgQHByaXZhdGUKICAgICovCiAgICBfZXh0cmFjdFR5cGU6IGZ1bmN0aW9uIF9leHRyYWN0VHlwZShtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpIHsKICAgICAgcmV0dXJuIHRoaXMubW9kZWxOYW1lRnJvbVBheWxvYWRLZXkocmVzb3VyY2VIYXNoLnR5cGUpOwogICAgfSwKCiAgICAvKioKICAgICAgRGFzaGVyaXplcyBhbmQgc2luZ3VsYXJpemVzIHRoZSBtb2RlbCBuYW1lIGluIHRoZSBwYXlsb2FkIHRvIG1hdGNoCiAgICAgIHRoZSBmb3JtYXQgRW1iZXIgRGF0YSB1c2VzIGludGVybmFsbHkgZm9yIHRoZSBtb2RlbCBuYW1lLgogICAgICAgRm9yIGV4YW1wbGUgdGhlIGtleSBgcG9zdHNgIHdvdWxkIGJlIGNvbnZlcnRlZCB0byBgcG9zdGAgYW5kIHRoZQogICAgICBrZXkgYHN0dWRlbnRBc3Nlc21lbnRzYCB3b3VsZCBiZSBjb252ZXJ0ZWQgdG8gYHN0dWRlbnQtYXNzZXNtZW50YC4KICAgICAgIEBtZXRob2QgbW9kZWxOYW1lRnJvbVBheWxvYWRLZXkKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleQogICAgICBAcmV0dXJuIHtTdHJpbmd9IHRoZSBtb2RlbCdzIG1vZGVsTmFtZQogICAgKi8KICAgIC8vIFRPRE8gQGRlcHJlY2F0ZWQgVXNlIG1vZGVsTmFtZUZyb21QYXlsb2FkVHlwZSBpbnN0ZWFkCiAgICBtb2RlbE5hbWVGcm9tUGF5bG9hZEtleTogZnVuY3Rpb24gbW9kZWxOYW1lRnJvbVBheWxvYWRLZXkoa2V5KSB7CiAgICAgIHJldHVybiAoMCwgX2VtYmVySW5mbGVjdG9yLnNpbmd1bGFyaXplKSgoMCwgX3N0b3JlLm5vcm1hbGl6ZU1vZGVsTmFtZSkoa2V5KSk7CiAgICB9LAoKICAgIC8qKgogICAgICBDb252ZXJ0cyB0aGUgbW9kZWwgbmFtZSB0byBhIHBsdXJhbGl6ZWQgdmVyc2lvbiBvZiB0aGUgbW9kZWwgbmFtZS4KICAgICAgIEZvciBleGFtcGxlIGBwb3N0YCB3b3VsZCBiZSBjb252ZXJ0ZWQgdG8gYHBvc3RzYCBhbmQKICAgICAgYHN0dWRlbnQtYXNzZXNtZW50YCB3b3VsZCBiZSBjb252ZXJ0ZWQgdG8gYHN0dWRlbnQtYXNzZXNtZW50c2AuCiAgICAgICBAbWV0aG9kIHBheWxvYWRLZXlGcm9tTW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHJldHVybiB7U3RyaW5nfQogICAgKi8KICAgIC8vIFRPRE8gQGRlcHJlY2F0ZWQgVXNlIHBheWxvYWRUeXBlRnJvbU1vZGVsTmFtZSBpbnN0ZWFkCiAgICBwYXlsb2FkS2V5RnJvbU1vZGVsTmFtZTogZnVuY3Rpb24gcGF5bG9hZEtleUZyb21Nb2RlbE5hbWUobW9kZWxOYW1lKSB7CiAgICAgIHJldHVybiAoMCwgX2VtYmVySW5mbGVjdG9yLnBsdXJhbGl6ZSkobW9kZWxOYW1lKTsKICAgIH0sCiAgICBub3JtYWxpemU6IGZ1bmN0aW9uIG5vcm1hbGl6ZShtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpIHsKICAgICAgaWYgKHJlc291cmNlSGFzaC5hdHRyaWJ1dGVzKSB7CiAgICAgICAgdGhpcy5ub3JtYWxpemVVc2luZ0RlY2xhcmVkTWFwcGluZyhtb2RlbENsYXNzLCByZXNvdXJjZUhhc2guYXR0cmlidXRlcyk7CiAgICAgIH0KCiAgICAgIGlmIChyZXNvdXJjZUhhc2gucmVsYXRpb25zaGlwcykgewogICAgICAgIHRoaXMubm9ybWFsaXplVXNpbmdEZWNsYXJlZE1hcHBpbmcobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoLnJlbGF0aW9uc2hpcHMpOwogICAgICB9CgogICAgICB2YXIgZGF0YSA9IHsKICAgICAgICBpZDogdGhpcy5leHRyYWN0SWQobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKSwKICAgICAgICB0eXBlOiB0aGlzLl9leHRyYWN0VHlwZShtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpLAogICAgICAgIGF0dHJpYnV0ZXM6IHRoaXMuZXh0cmFjdEF0dHJpYnV0ZXMobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKSwKICAgICAgICByZWxhdGlvbnNoaXBzOiB0aGlzLmV4dHJhY3RSZWxhdGlvbnNoaXBzKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCkKICAgICAgfTsKICAgICAgdGhpcy5hcHBseVRyYW5zZm9ybXMobW9kZWxDbGFzcywgZGF0YS5hdHRyaWJ1dGVzKTsKICAgICAgcmV0dXJuIHsKICAgICAgICBkYXRhOiBkYXRhCiAgICAgIH07CiAgICB9LAoKICAgIC8qKgogICAgICBga2V5Rm9yQXR0cmlidXRlYCBjYW4gYmUgdXNlZCB0byBkZWZpbmUgcnVsZXMgZm9yIGhvdyB0byBjb252ZXJ0IGFuCiAgICAgIGF0dHJpYnV0ZSBuYW1lIGluIHlvdXIgbW9kZWwgdG8gYSBrZXkgaW4geW91ciBKU09OLgogICAgICBCeSBkZWZhdWx0IGBKU09OQVBJU2VyaWFsaXplcmAgZm9sbG93cyB0aGUgZm9ybWF0IHVzZWQgb24gdGhlIGV4YW1wbGVzIG9mCiAgICAgIGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQgYW5kIHVzZXMgZGFzaGVzIGFzIHRoZSB3b3JkIHNlcGFyYXRvciBpbiB0aGUgSlNPTgogICAgICBhdHRyaWJ1dGUga2V5cy4KICAgICAgIFRoaXMgYmVoYXZpb3VyIGNhbiBiZSBlYXNpbHkgY3VzdG9taXplZCBieSBleHRlbmRpbmcgdGhpcyBtZXRob2QuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IEpTT05BUElTZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbi1hcGknOwogICAgICBpbXBvcnQgeyBkYXNoZXJpemUgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05BUElTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAga2V5Rm9yQXR0cmlidXRlKGF0dHIsIG1ldGhvZCkgewogICAgICAgICAgcmV0dXJuIGRhc2hlcml6ZShhdHRyKS50b1VwcGVyQ2FzZSgpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBrZXlGb3JBdHRyaWJ1dGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleQogICAgICBAcGFyYW0ge1N0cmluZ30gbWV0aG9kCiAgICAgIEByZXR1cm4ge1N0cmluZ30gbm9ybWFsaXplZCBrZXkKICAgICovCiAgICBrZXlGb3JBdHRyaWJ1dGU6IGZ1bmN0aW9uIGtleUZvckF0dHJpYnV0ZShrZXksIG1ldGhvZCkgewogICAgICByZXR1cm4gRW1iZXIuU3RyaW5nLmRhc2hlcml6ZShrZXkpOwogICAgfSwKCiAgICAvKioKICAgICBga2V5Rm9yUmVsYXRpb25zaGlwYCBjYW4gYmUgdXNlZCB0byBkZWZpbmUgYSBjdXN0b20ga2V5IHdoZW4KICAgICBzZXJpYWxpemluZyBhbmQgZGVzZXJpYWxpemluZyByZWxhdGlvbnNoaXAgcHJvcGVydGllcy4KICAgICBCeSBkZWZhdWx0IGBKU09OQVBJU2VyaWFsaXplcmAgZm9sbG93cyB0aGUgZm9ybWF0IHVzZWQgb24gdGhlIGV4YW1wbGVzIG9mCiAgICAgaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdCBhbmQgdXNlcyBkYXNoZXMgYXMgd29yZCBzZXBhcmF0b3JzIGluCiAgICAgcmVsYXRpb25zaGlwIHByb3BlcnRpZXMuCiAgICAgIFRoaXMgYmVoYXZpb3VyIGNhbiBiZSBlYXNpbHkgY3VzdG9taXplZCBieSBleHRlbmRpbmcgdGhpcyBtZXRob2QuCiAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBKU09OQVBJU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24tYXBpJzsKICAgICAgaW1wb3J0IHsgdW5kZXJzY29yZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTkFQSVNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBrZXlGb3JSZWxhdGlvbnNoaXAoa2V5LCByZWxhdGlvbnNoaXAsIG1ldGhvZCkgewogICAgICAgICAgcmV0dXJuIHVuZGVyc2NvcmUoa2V5KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICBAbWV0aG9kIGtleUZvclJlbGF0aW9uc2hpcAogICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkKICAgICBAcGFyYW0ge1N0cmluZ30gdHlwZUNsYXNzCiAgICAgQHBhcmFtIHtTdHJpbmd9IG1ldGhvZAogICAgIEByZXR1cm4ge1N0cmluZ30gbm9ybWFsaXplZCBrZXkKICAgICovCiAgICBrZXlGb3JSZWxhdGlvbnNoaXA6IGZ1bmN0aW9uIGtleUZvclJlbGF0aW9uc2hpcChrZXksIHR5cGVDbGFzcywgbWV0aG9kKSB7CiAgICAgIHJldHVybiBFbWJlci5TdHJpbmcuZGFzaGVyaXplKGtleSk7CiAgICB9LAogICAgc2VyaWFsaXplOiBmdW5jdGlvbiBzZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpIHsKICAgICAgdmFyIGRhdGEgPSB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgZGF0YS50eXBlID0gdGhpcy5wYXlsb2FkS2V5RnJvbU1vZGVsTmFtZShzbmFwc2hvdC5tb2RlbE5hbWUpOwogICAgICByZXR1cm4gewogICAgICAgIGRhdGE6IGRhdGEKICAgICAgfTsKICAgIH0sCiAgICBzZXJpYWxpemVBdHRyaWJ1dGU6IGZ1bmN0aW9uIHNlcmlhbGl6ZUF0dHJpYnV0ZShzbmFwc2hvdCwganNvbiwga2V5LCBhdHRyaWJ1dGUpIHsKICAgICAgdmFyIHR5cGUgPSBhdHRyaWJ1dGUudHlwZTsKCiAgICAgIGlmICh0aGlzLl9jYW5TZXJpYWxpemUoa2V5KSkgewogICAgICAgIGpzb24uYXR0cmlidXRlcyA9IGpzb24uYXR0cmlidXRlcyB8fCB7fTsKICAgICAgICB2YXIgdmFsdWUgPSBzbmFwc2hvdC5hdHRyKGtleSk7CgogICAgICAgIGlmICh0eXBlKSB7CiAgICAgICAgICB2YXIgdHJhbnNmb3JtID0gdGhpcy50cmFuc2Zvcm1Gb3IodHlwZSk7CiAgICAgICAgICB2YWx1ZSA9IHRyYW5zZm9ybS5zZXJpYWxpemUodmFsdWUsIGF0dHJpYnV0ZS5vcHRpb25zKTsKICAgICAgICB9CgogICAgICAgIHZhciBwYXlsb2FkS2V5ID0gdGhpcy5fZ2V0TWFwcGVkS2V5KGtleSwgc25hcHNob3QudHlwZSk7CgogICAgICAgIGlmIChwYXlsb2FkS2V5ID09PSBrZXkpIHsKICAgICAgICAgIHBheWxvYWRLZXkgPSB0aGlzLmtleUZvckF0dHJpYnV0ZShrZXksICdzZXJpYWxpemUnKTsKICAgICAgICB9CgogICAgICAgIGpzb24uYXR0cmlidXRlc1twYXlsb2FkS2V5XSA9IHZhbHVlOwogICAgICB9CiAgICB9LAogICAgc2VyaWFsaXplQmVsb25nc1RvOiBmdW5jdGlvbiBzZXJpYWxpemVCZWxvbmdzVG8oc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCkgewogICAgICB2YXIga2V5ID0gcmVsYXRpb25zaGlwLmtleTsKCiAgICAgIGlmICh0aGlzLl9jYW5TZXJpYWxpemUoa2V5KSkgewogICAgICAgIHZhciBiZWxvbmdzVG8gPSBzbmFwc2hvdC5iZWxvbmdzVG8oa2V5KTsKICAgICAgICB2YXIgYmVsb25nc1RvSXNOb3ROZXc7CgogICAgICAgIGlmIChfY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICBiZWxvbmdzVG9Jc05vdE5ldyA9IGJlbG9uZ3NUbyAmJiAhYmVsb25nc1RvLmlzTmV3OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBiZWxvbmdzVG9Jc05vdE5ldyA9IGJlbG9uZ3NUbyAmJiBiZWxvbmdzVG8ucmVjb3JkICYmICFiZWxvbmdzVG8ucmVjb3JkLmdldCgnaXNOZXcnKTsKICAgICAgICB9CgogICAgICAgIGlmIChiZWxvbmdzVG8gPT09IG51bGwgfHwgYmVsb25nc1RvSXNOb3ROZXcpIHsKICAgICAgICAgIGpzb24ucmVsYXRpb25zaGlwcyA9IGpzb24ucmVsYXRpb25zaGlwcyB8fCB7fTsKCiAgICAgICAgICB2YXIgcGF5bG9hZEtleSA9IHRoaXMuX2dldE1hcHBlZEtleShrZXksIHNuYXBzaG90LnR5cGUpOwoKICAgICAgICAgIGlmIChwYXlsb2FkS2V5ID09PSBrZXkpIHsKICAgICAgICAgICAgcGF5bG9hZEtleSA9IHRoaXMua2V5Rm9yUmVsYXRpb25zaGlwKGtleSwgJ2JlbG9uZ3NUbycsICdzZXJpYWxpemUnKTsKICAgICAgICAgIH0KCiAgICAgICAgICB2YXIgZGF0YSA9IG51bGw7CgogICAgICAgICAgaWYgKGJlbG9uZ3NUbykgewogICAgICAgICAgICB2YXIgcGF5bG9hZFR5cGUgPSB0aGlzLnBheWxvYWRLZXlGcm9tTW9kZWxOYW1lKGJlbG9uZ3NUby5tb2RlbE5hbWUpOwogICAgICAgICAgICBkYXRhID0gewogICAgICAgICAgICAgIHR5cGU6IHBheWxvYWRUeXBlLAogICAgICAgICAgICAgIGlkOiBiZWxvbmdzVG8uaWQKICAgICAgICAgICAgfTsKICAgICAgICAgIH0KCiAgICAgICAgICBqc29uLnJlbGF0aW9uc2hpcHNbcGF5bG9hZEtleV0gPSB7CiAgICAgICAgICAgIGRhdGE6IGRhdGEKICAgICAgICAgIH07CiAgICAgICAgfQogICAgICB9CiAgICB9LAogICAgc2VyaWFsaXplSGFzTWFueTogZnVuY3Rpb24gc2VyaWFsaXplSGFzTWFueShzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKSB7CiAgICAgIHZhciBrZXkgPSByZWxhdGlvbnNoaXAua2V5OwoKICAgICAgaWYgKHRoaXMuc2hvdWxkU2VyaWFsaXplSGFzTWFueShzbmFwc2hvdCwga2V5LCByZWxhdGlvbnNoaXApKSB7CiAgICAgICAgdmFyIGhhc01hbnkgPSBzbmFwc2hvdC5oYXNNYW55KGtleSk7CgogICAgICAgIGlmIChoYXNNYW55ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGpzb24ucmVsYXRpb25zaGlwcyA9IGpzb24ucmVsYXRpb25zaGlwcyB8fCB7fTsKCiAgICAgICAgICB2YXIgcGF5bG9hZEtleSA9IHRoaXMuX2dldE1hcHBlZEtleShrZXksIHNuYXBzaG90LnR5cGUpOwoKICAgICAgICAgIGlmIChwYXlsb2FkS2V5ID09PSBrZXkgJiYgdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXApIHsKICAgICAgICAgICAgcGF5bG9hZEtleSA9IHRoaXMua2V5Rm9yUmVsYXRpb25zaGlwKGtleSwgJ2hhc01hbnknLCAnc2VyaWFsaXplJyk7CiAgICAgICAgICB9IC8vIG9ubHkgc2VyaWFsaXplIGhhcyBtYW55IHJlbGF0aW9uc2hpcHMgdGhhdCBhcmUgbm90IG5ldwoKCiAgICAgICAgICB2YXIgbm9uTmV3SGFzTWFueSA9IGhhc01hbnkuZmlsdGVyKGZ1bmN0aW9uIChpdGVtKSB7CiAgICAgICAgICAgIHJldHVybiBpdGVtLnJlY29yZCAmJiAhaXRlbS5yZWNvcmQuZ2V0KCdpc05ldycpOwogICAgICAgICAgfSk7CiAgICAgICAgICB2YXIgZGF0YSA9IG5ldyBBcnJheShub25OZXdIYXNNYW55Lmxlbmd0aCk7CgogICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub25OZXdIYXNNYW55Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHZhciBpdGVtID0gaGFzTWFueVtpXTsKICAgICAgICAgICAgdmFyIHBheWxvYWRUeXBlID0gdGhpcy5wYXlsb2FkS2V5RnJvbU1vZGVsTmFtZShpdGVtLm1vZGVsTmFtZSk7CiAgICAgICAgICAgIGRhdGFbaV0gPSB7CiAgICAgICAgICAgICAgdHlwZTogcGF5bG9hZFR5cGUsCiAgICAgICAgICAgICAgaWQ6IGl0ZW0uaWQKICAgICAgICAgICAgfTsKICAgICAgICAgIH0KCiAgICAgICAgICBqc29uLnJlbGF0aW9uc2hpcHNbcGF5bG9hZEtleV0gPSB7CiAgICAgICAgICAgIGRhdGE6IGRhdGEKICAgICAgICAgIH07CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfSk7CgogIGlmIChmYWxzZQogIC8qIERFQlVHICovCiAgKSB7CiAgICBKU09OQVBJU2VyaWFsaXplci5yZW9wZW4oewogICAgICB3aWxsTWVyZ2VNaXhpbjogZnVuY3Rpb24gd2lsbE1lcmdlTWl4aW4ocHJvcHMpIHsKICAgICAgICB2YXIgY29uc3RydWN0b3IgPSB0aGlzLmNvbnN0cnVjdG9yOwogICAgICAgIChmYWxzZSAmJiBFbWJlci53YXJuKCJZb3UndmUgZGVmaW5lZCAnZXh0cmFjdE1ldGEnIGluICIgKyBjb25zdHJ1Y3Rvci50b1N0cmluZygpICsgIiB3aGljaCBpcyBub3QgdXNlZCBmb3Igc2VyaWFsaXplcnMgZXh0ZW5kaW5nIEpTT05BUElTZXJpYWxpemVyLiBSZWFkIG1vcmUgYXQgaHR0cHM6Ly9hcGkuZW1iZXJqcy5jb20vZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvSlNPTkFQSVNlcmlhbGl6ZXIgb24gaG93IHRvIGN1c3RvbWl6ZSBtZXRhIHdoZW4gdXNpbmcgSlNPTiBBUEkuIiwgRW1iZXIuaXNOb25lKHByb3BzLmV4dHJhY3RNZXRhKSB8fCBwcm9wcy5leHRyYWN0TWV0YSA9PT0gX2pzb24uZGVmYXVsdC5wcm90b3R5cGUuZXh0cmFjdE1ldGEsIHsKICAgICAgICAgIGlkOiAnZHMuc2VyaWFsaXplci5qc29uLWFwaS5leHRyYWN0TWV0YScKICAgICAgICB9KSk7CiAgICAgICAgKGZhbHNlICYmIEVtYmVyLndhcm4oJ1RoZSBKU09OQVBJU2VyaWFsaXplciBkb2VzIG5vdCB3b3JrIHdpdGggdGhlIEVtYmVkZGVkUmVjb3Jkc01peGluIGJlY2F1c2UgdGhlIEpTT04gQVBJIHNwZWMgZG9lcyBub3QgZGVzY3JpYmUgaG93IHRvIGZvcm1hdCBlbWJlZGRlZCByZXNvdXJjZXMuJywgIXByb3BzLmlzRW1iZWRkZWRSZWNvcmRzTWl4aW4sIHsKICAgICAgICAgIGlkOiAnZHMuc2VyaWFsaXplci5lbWJlZGRlZC1yZWNvcmRzLW1peGluLW5vdC1zdXBwb3J0ZWQnCiAgICAgICAgfSkpOwogICAgICB9LAogICAgICB3YXJuTWVzc2FnZUZvclVuZGVmaW5lZFR5cGU6IGZ1bmN0aW9uIHdhcm5NZXNzYWdlRm9yVW5kZWZpbmVkVHlwZSgpIHsKICAgICAgICByZXR1cm4gJ0VuY291bnRlcmVkIGEgcmVzb3VyY2Ugb2JqZWN0IHdpdGggYW4gdW5kZWZpbmVkIHR5cGUgKHJlc29sdmVkIHJlc291cmNlIHVzaW5nICcgKyB0aGlzLmNvbnN0cnVjdG9yLnRvU3RyaW5nKCkgKyAnKSc7CiAgICAgIH0sCiAgICAgIHdhcm5NZXNzYWdlTm9Nb2RlbEZvclR5cGU6IGZ1bmN0aW9uIHdhcm5NZXNzYWdlTm9Nb2RlbEZvclR5cGUobW9kZWxOYW1lLCBvcmlnaW5hbFR5cGUsIHVzZWRMb29rdXApIHsKICAgICAgICByZXR1cm4gIkVuY291bnRlcmVkIGEgcmVzb3VyY2Ugb2JqZWN0IHdpdGggdHlwZSBcIiIgKyBvcmlnaW5hbFR5cGUgKyAiXCIsIGJ1dCBubyBtb2RlbCB3YXMgZm91bmQgZm9yIG1vZGVsIG5hbWUgXCIiICsgbW9kZWxOYW1lICsgIlwiIChyZXNvbHZlZCBtb2RlbCBuYW1lIHVzaW5nICciICsgdGhpcy5jb25zdHJ1Y3Rvci50b1N0cmluZygpICsgIi4iICsgdXNlZExvb2t1cCArICIoXCIiICsgb3JpZ2luYWxUeXBlICsgIlwiKScpLiI7CiAgICAgIH0KICAgIH0pOwogIH0KCiAgdmFyIF9kZWZhdWx0ID0gSlNPTkFQSVNlcmlhbGl6ZXI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKO2RlZmluZSgiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIiLCAiQGVtYmVyLWRhdGEvc3RvcmUvLXByaXZhdGUiLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplci8tcHJpdmF0ZSIsICJAZW1iZXItZGF0YS9zdG9yZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9zZXJpYWxpemVyLCBfcHJpdmF0ZSwgX3ByaXZhdGUyLCBfc3RvcmUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zZXJpYWxpemVyCiAgKi8KCiAgLyoqCiAgICBFbWJlciBEYXRhIDIuMCBTZXJpYWxpemVyOgogIAogICAgSW4gRW1iZXIgRGF0YSBhIFNlcmlhbGl6ZXIgaXMgdXNlZCB0byBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplCiAgICByZWNvcmRzIHdoZW4gdGhleSBhcmUgdHJhbnNmZXJyZWQgaW4gYW5kIG91dCBvZiBhbiBleHRlcm5hbCBzb3VyY2UuCiAgICBUaGlzIHByb2Nlc3MgaW52b2x2ZXMgbm9ybWFsaXppbmcgcHJvcGVydHkgbmFtZXMsIHRyYW5zZm9ybWluZwogICAgYXR0cmlidXRlIHZhbHVlcyBhbmQgc2VyaWFsaXppbmcgcmVsYXRpb25zaGlwcy4KICAKICAgIEJ5IGRlZmF1bHQsIEVtYmVyIERhdGEgdXNlcyBhbmQgcmVjb21tZW5kcyB0aGUgYEpTT05BUElTZXJpYWxpemVyYC4KICAKICAgIGBKU09OU2VyaWFsaXplcmAgaXMgdXNlZnVsIGZvciBzaW1wbGVyIG9yIGxlZ2FjeSBiYWNrZW5kcyB0aGF0IG1heQogICAgbm90IHN1cHBvcnQgdGhlIGh0dHA6Ly9qc29uYXBpLm9yZy8gc3BlYy4KICAKICAgIEZvciBleGFtcGxlLCBnaXZlbiB0aGUgZm9sbG93aW5nIGBVc2VyYCBtb2RlbCBhbmQgSlNPTiBwYXlsb2FkOgogIAogICAgYGBgYXBwL21vZGVscy91c2VyLmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciwgYmVsb25nc1RvLCBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogIAogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgZnJpZW5kczogaGFzTWFueSgndXNlcicpLAogICAgICBob3VzZTogYmVsb25nc1RvKCdsb2NhdGlvbicpLAogIAogICAgICBuYW1lOiBhdHRyKCdzdHJpbmcnKQogICAgfSk7CiAgICBgYGAKICAKICAgIGBgYGpzCiAgICB7CiAgICAgIGlkOiAxLAogICAgICBuYW1lOiAnU2ViYXN0aWFuJywKICAgICAgZnJpZW5kczogWzMsIDRdLAogICAgICBsaW5rczogewogICAgICAgIGhvdXNlOiAnL2hvdXNlcy9sZWZrYWRhJwogICAgICB9CiAgICB9CiAgICBgYGAKICAKICAgIGBKU09OU2VyaWFsaXplcmAgd2lsbCBub3JtYWxpemUgdGhlIEpTT04gcGF5bG9hZCB0byB0aGUgSlNPTiBBUEkgZm9ybWF0IHRoYXQgdGhlCiAgICBFbWJlciBEYXRhIHN0b3JlIGV4cGVjdHMuCiAgCiAgICBZb3UgY2FuIGN1c3RvbWl6ZSBob3cgSlNPTlNlcmlhbGl6ZXIgcHJvY2Vzc2VzIGl0cyBwYXlsb2FkIGJ5IHBhc3Npbmcgb3B0aW9ucyBpbgogICAgdGhlIGBhdHRyc2AgaGFzaCBvciBieSBzdWJjbGFzc2luZyB0aGUgYEpTT05TZXJpYWxpemVyYCBhbmQgb3ZlcnJpZGluZyBob29rczoKICAKICAgICAgLSBUbyBjdXN0b21pemUgaG93IGEgc2luZ2xlIHJlY29yZCBpcyBub3JtYWxpemVkLCB1c2UgdGhlIGBub3JtYWxpemVgIGhvb2suCiAgICAgIC0gVG8gY3VzdG9taXplIGhvdyBgSlNPTlNlcmlhbGl6ZXJgIG5vcm1hbGl6ZXMgdGhlIHdob2xlIHNlcnZlciByZXNwb25zZSwgdXNlIHRoZQogICAgICAgIGBub3JtYWxpemVSZXNwb25zZWAgaG9vay4KICAgICAgLSBUbyBjdXN0b21pemUgaG93IGBKU09OU2VyaWFsaXplcmAgbm9ybWFsaXplcyBhIHNwZWNpZmljIHJlc3BvbnNlIGZyb20gdGhlIHNlcnZlciwKICAgICAgICB1c2Ugb25lIG9mIHRoZSBtYW55IHNwZWNpZmljIGBub3JtYWxpemVSZXNwb25zZWAgaG9va3MuCiAgICAgIC0gVG8gY3VzdG9taXplIGhvdyBgSlNPTlNlcmlhbGl6ZXJgIG5vcm1hbGl6ZXMgeW91ciBpZCwgYXR0cmlidXRlcyBvciByZWxhdGlvbnNoaXBzLAogICAgICAgIHVzZSB0aGUgYGV4dHJhY3RJZGAsIGBleHRyYWN0QXR0cmlidXRlc2AgYW5kIGBleHRyYWN0UmVsYXRpb25zaGlwc2AgaG9va3MuCiAgCiAgICBUaGUgYEpTT05TZXJpYWxpemVyYCBub3JtYWxpemF0aW9uIHByb2Nlc3MgZm9sbG93cyB0aGVzZSBzdGVwczoKICAKICAgICAgLSBgbm9ybWFsaXplUmVzcG9uc2VgIC0gZW50cnkgbWV0aG9kIHRvIHRoZSBzZXJpYWxpemVyLgogICAgICAtIGBub3JtYWxpemVDcmVhdGVSZWNvcmRSZXNwb25zZWAgLSBhIGBub3JtYWxpemVSZXNwb25zZWAgZm9yIGEgc3BlY2lmaWMgb3BlcmF0aW9uIGlzIGNhbGxlZC4KICAgICAgLSBgbm9ybWFsaXplU2luZ2xlUmVzcG9uc2VgfGBub3JtYWxpemVBcnJheVJlc3BvbnNlYCAtIGZvciBtZXRob2RzIGxpa2UgYGNyZWF0ZVJlY29yZGAgd2UgZXhwZWN0CiAgICAgICAgYSBzaW5nbGUgcmVjb3JkIGJhY2ssIHdoaWxlIGZvciBtZXRob2RzIGxpa2UgYGZpbmRBbGxgIHdlIGV4cGVjdCBtdWx0aXBsZSByZWNvcmRzIGJhY2suCiAgICAgIC0gYG5vcm1hbGl6ZWAgLSBgbm9ybWFsaXplQXJyYXlgIGl0ZXJhdGVzIGFuZCBjYWxscyBgbm9ybWFsaXplYCBmb3IgZWFjaCBvZiBpdHMgcmVjb3JkcyB3aGlsZSBgbm9ybWFsaXplU2luZ2xlYAogICAgICAgIGNhbGxzIGl0IG9uY2UuIFRoaXMgaXMgdGhlIG1ldGhvZCB5b3UgbW9zdCBsaWtlbHkgd2FudCB0byBzdWJjbGFzcy4KICAgICAgLSBgZXh0cmFjdElkYCB8IGBleHRyYWN0QXR0cmlidXRlc2AgfCBgZXh0cmFjdFJlbGF0aW9uc2hpcHNgIC0gYG5vcm1hbGl6ZWAgZGVsZWdhdGVzIHRvIHRoZXNlIG1ldGhvZHMgdG8KICAgICAgICB0dXJuIHRoZSByZWNvcmQgcGF5bG9hZCBpbnRvIHRoZSBKU09OIEFQSSBmb3JtYXQuCiAgCiAgICBAY2xhc3MgSlNPTlNlcmlhbGl6ZXIKICAgIEBleHRlbmRzIFNlcmlhbGl6ZXIKICAqLwogIHZhciBKU09OU2VyaWFsaXplciA9IF9zZXJpYWxpemVyLmRlZmF1bHQuZXh0ZW5kKHsKICAgIC8qKgogICAgICBUaGUgYHByaW1hcnlLZXlgIGlzIHVzZWQgd2hlbiBzZXJpYWxpemluZyBhbmQgZGVzZXJpYWxpemluZwogICAgICBkYXRhLiBFbWJlciBEYXRhIGFsd2F5cyB1c2VzIHRoZSBgaWRgIHByb3BlcnR5IHRvIHN0b3JlIHRoZSBpZCBvZgogICAgICB0aGUgcmVjb3JkLiBUaGUgZXh0ZXJuYWwgc291cmNlIG1heSBub3QgYWx3YXlzIGZvbGxvdyB0aGlzCiAgICAgIGNvbnZlbnRpb24uIEluIHRoZXNlIGNhc2VzIGl0IGlzIHVzZWZ1bCB0byBvdmVycmlkZSB0aGUKICAgICAgYHByaW1hcnlLZXlgIHByb3BlcnR5IHRvIG1hdGNoIHRoZSBgcHJpbWFyeUtleWAgb2YgeW91ciBleHRlcm5hbAogICAgICBzdG9yZS4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgSlNPTlNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05TZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgcHJpbWFyeUtleTogJ19pZCcKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQHByb3BlcnR5IHByaW1hcnlLZXkKICAgICAgQHR5cGUge1N0cmluZ30KICAgICAgQGRlZmF1bHQgJ2lkJwogICAgKi8KICAgIHByaW1hcnlLZXk6ICdpZCcsCgogICAgLyoqCiAgICAgIFRoZSBgYXR0cnNgIG9iamVjdCBjYW4gYmUgdXNlZCB0byBkZWNsYXJlIGEgc2ltcGxlIG1hcHBpbmcgYmV0d2VlbgogICAgICBwcm9wZXJ0eSBuYW1lcyBvbiBgTW9kZWxgIHJlY29yZHMgYW5kIHBheWxvYWQga2V5cyBpbiB0aGUKICAgICAgc2VyaWFsaXplZCBKU09OIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIHJlY29yZC4gQW4gb2JqZWN0IHdpdGggdGhlCiAgICAgIHByb3BlcnR5IGBrZXlgIGNhbiBhbHNvIGJlIHVzZWQgdG8gZGVzaWduYXRlIHRoZSBhdHRyaWJ1dGUncyBrZXkgb24KICAgICAgdGhlIHJlc3BvbnNlIHBheWxvYWQuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvbW9kZWxzL3BlcnNvbi5qcwogICAgICBpbXBvcnQgTW9kZWwsIHsgYXR0ciB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgZmlyc3ROYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgICBsYXN0TmFtZTogYXR0cignc3RyaW5nJyksCiAgICAgICAgb2NjdXBhdGlvbjogYXR0cignc3RyaW5nJyksCiAgICAgICAgYWRtaW46IGF0dHIoJ2Jvb2xlYW4nKQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcGVyc29uLmpzCiAgICAgIGltcG9ydCBKU09OU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24nOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBhdHRyczogewogICAgICAgICAgYWRtaW46ICdpc19hZG1pbicsCiAgICAgICAgICBvY2N1cGF0aW9uOiB7IGtleTogJ2NhcmVlcicgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgWW91IGNhbiBhbHNvIHJlbW92ZSBhdHRyaWJ1dGVzIGFuZCByZWxhdGlvbnNoaXBzIGJ5IHNldHRpbmcgdGhlIGBzZXJpYWxpemVgCiAgICAgIGtleSB0byBgZmFsc2VgIGluIHlvdXIgbWFwcGluZyBvYmplY3QuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcGVyc29uLmpzCiAgICAgIGltcG9ydCBKU09OU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24nOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBhdHRyczogewogICAgICAgICAgYWRtaW46IHsgc2VyaWFsaXplOiBmYWxzZSB9LAogICAgICAgICAgb2NjdXBhdGlvbjogeyBrZXk6ICdjYXJlZXInIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFdoZW4gc2VyaWFsaXplZDoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgewogICAgICAgICJmaXJzdE5hbWUiOiAiSGFycnkiLAogICAgICAgICJsYXN0TmFtZSI6ICJIb3VkaW5pIiwKICAgICAgICAiY2FyZWVyIjogIm1hZ2ljaWFuIgogICAgICB9CiAgICAgIGBgYAogICAgICAgTm90ZSB0aGF0IHRoZSBgYWRtaW5gIGlzIG5vdyBub3QgaW5jbHVkZWQgaW4gdGhlIHBheWxvYWQuCiAgICAgICBTZXR0aW5nIGBzZXJpYWxpemVgIHRvIGB0cnVlYCBlbmZvcmNlcyBzZXJpYWxpemF0aW9uIGZvciBoYXNNYW55CiAgICAgIHJlbGF0aW9uc2hpcHMgZXZlbiBpZiBpdCdzIG5laXRoZXIgYSBtYW55LXRvLW1hbnkgbm9yIG1hbnktdG8tbm9uZQogICAgICByZWxhdGlvbnNoaXAuCiAgICAgICBAcHJvcGVydHkgYXR0cnMKICAgICAgQHR5cGUge09iamVjdH0KICAgICovCiAgICBtZXJnZWRQcm9wZXJ0aWVzOiBbJ2F0dHJzJ10sCgogICAgLyoqCiAgICAgR2l2ZW4gYSBzdWJjbGFzcyBvZiBgTW9kZWxgIGFuZCBhIEpTT04gb2JqZWN0IHRoaXMgbWV0aG9kIHdpbGwKICAgICBpdGVyYXRlIHRocm91Z2ggZWFjaCBhdHRyaWJ1dGUgb2YgdGhlIGBNb2RlbGAgYW5kIGludm9rZSB0aGUKICAgICBgVHJhbnNmb3JtI2Rlc2VyaWFsaXplYCBtZXRob2Qgb24gdGhlIG1hdGNoaW5nIHByb3BlcnR5IG9mIHRoZQogICAgIEpTT04gb2JqZWN0LiAgVGhpcyBtZXRob2QgaXMgdHlwaWNhbGx5IGNhbGxlZCBhZnRlciB0aGUKICAgICBzZXJpYWxpemVyJ3MgYG5vcm1hbGl6ZWAgbWV0aG9kLgogICAgICBAbWV0aG9kIGFwcGx5VHJhbnNmb3JtcwogICAgIEBwcml2YXRlCiAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZUNsYXNzCiAgICAgQHBhcmFtIHtPYmplY3R9IGRhdGEgVGhlIGRhdGEgdG8gdHJhbnNmb3JtCiAgICAgQHJldHVybiB7T2JqZWN0fSBkYXRhIFRoZSB0cmFuc2Zvcm1lZCBkYXRhIG9iamVjdAogICAgKi8KICAgIGFwcGx5VHJhbnNmb3JtczogZnVuY3Rpb24gYXBwbHlUcmFuc2Zvcm1zKHR5cGVDbGFzcywgZGF0YSkgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgdmFyIGF0dHJpYnV0ZXMgPSBFbWJlci5nZXQodHlwZUNsYXNzLCAnYXR0cmlidXRlcycpOwogICAgICB0eXBlQ2xhc3MuZWFjaFRyYW5zZm9ybWVkQXR0cmlidXRlKGZ1bmN0aW9uIChrZXksIHR5cGVDbGFzcykgewogICAgICAgIGlmIChkYXRhW2tleV0gPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgdmFyIHRyYW5zZm9ybSA9IF90aGlzLnRyYW5zZm9ybUZvcih0eXBlQ2xhc3MpOwoKICAgICAgICB2YXIgdHJhbnNmb3JtTWV0YSA9IGF0dHJpYnV0ZXMuZ2V0KGtleSk7CiAgICAgICAgZGF0YVtrZXldID0gdHJhbnNmb3JtLmRlc2VyaWFsaXplKGRhdGFba2V5XSwgdHJhbnNmb3JtTWV0YS5vcHRpb25zKTsKICAgICAgfSk7CiAgICAgIHJldHVybiBkYXRhOwogICAgfSwKCiAgICAvKioKICAgICAgVGhlIGBub3JtYWxpemVSZXNwb25zZWAgbWV0aG9kIGlzIHVzZWQgdG8gbm9ybWFsaXplIGEgcGF5bG9hZCBmcm9tIHRoZQogICAgICBzZXJ2ZXIgdG8gYSBKU09OLUFQSSBEb2N1bWVudC4KICAgICAgIGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2RvY3VtZW50LXN0cnVjdHVyZQogICAgICAgVGhpcyBtZXRob2QgZGVsZWdhdGVzIHRvIGEgbW9yZSBzcGVjaWZpYyBub3JtYWxpemUgbWV0aG9kIGJhc2VkIG9uCiAgICAgIHRoZSBgcmVxdWVzdFR5cGVgLgogICAgICAgVG8gb3ZlcnJpZGUgdGhpcyBtZXRob2Qgd2l0aCBhIGN1c3RvbSBvbmUsIG1ha2Ugc3VyZSB0byBjYWxsCiAgICAgIGByZXR1cm4gdGhpcy5fc3VwZXIoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpYCB3aXRoIHlvdXIKICAgICAgcHJlLXByb2Nlc3NlZCBkYXRhLgogICAgICAgSGVyZSdzIGFuIGV4YW1wbGUgb2YgdXNpbmcgYG5vcm1hbGl6ZVJlc3BvbnNlYCBtYW51YWxseToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc29ja2V0Lm9uKCdtZXNzYWdlJywgZnVuY3Rpb24obWVzc2FnZSkgewogICAgICAgIHZhciBkYXRhID0gbWVzc2FnZS5kYXRhOwogICAgICAgIHZhciBtb2RlbENsYXNzID0gc3RvcmUubW9kZWxGb3IoZGF0YS5tb2RlbE5hbWUpOwogICAgICAgIHZhciBzZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcihkYXRhLm1vZGVsTmFtZSk7CiAgICAgICAgdmFyIG5vcm1hbGl6ZWQgPSBzZXJpYWxpemVyLm5vcm1hbGl6ZVNpbmdsZVJlc3BvbnNlKHN0b3JlLCBtb2RlbENsYXNzLCBkYXRhLCBkYXRhLmlkKTsKICAgICAgICAgc3RvcmUucHVzaChub3JtYWxpemVkKTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIG5vcm1hbGl6ZVJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICovCiAgICBub3JtYWxpemVSZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplUmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgc3dpdGNoIChyZXF1ZXN0VHlwZSkgewogICAgICAgIGNhc2UgJ2ZpbmRSZWNvcmQnOgogICAgICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplRmluZFJlY29yZFJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAgIGNhc2UgJ3F1ZXJ5UmVjb3JkJzoKICAgICAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZVF1ZXJ5UmVjb3JkUmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgICAgY2FzZSAnZmluZEFsbCc6CiAgICAgICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVGaW5kQWxsUmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgICAgY2FzZSAnZmluZEJlbG9uZ3NUbyc6CiAgICAgICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVGaW5kQmVsb25nc1RvUmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgICAgY2FzZSAnZmluZEhhc01hbnknOgogICAgICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplRmluZEhhc01hbnlSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgICBjYXNlICdmaW5kTWFueSc6CiAgICAgICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVGaW5kTWFueVJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAgIGNhc2UgJ3F1ZXJ5JzoKICAgICAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZVF1ZXJ5UmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKCiAgICAgICAgY2FzZSAnY3JlYXRlUmVjb3JkJzoKICAgICAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZUNyZWF0ZVJlY29yZFJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CgogICAgICAgIGNhc2UgJ2RlbGV0ZVJlY29yZCc6CiAgICAgICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVEZWxldGVSZWNvcmRSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgICBjYXNlICd1cGRhdGVSZWNvcmQnOgogICAgICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplVXBkYXRlUmVjb3JkUmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIG5vcm1hbGl6ZUZpbmRSZWNvcmRSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAqLwogICAgbm9ybWFsaXplRmluZFJlY29yZFJlc3BvbnNlOiBmdW5jdGlvbiBub3JtYWxpemVGaW5kUmVjb3JkUmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplU2luZ2xlUmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBub3JtYWxpemVRdWVyeVJlY29yZFJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICovCiAgICBub3JtYWxpemVRdWVyeVJlY29yZFJlc3BvbnNlOiBmdW5jdGlvbiBub3JtYWxpemVRdWVyeVJlY29yZFJlc3BvbnNlKHN0b3JlLCBwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCwgaWQsIHJlcXVlc3RUeXBlKSB7CiAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZVNpbmdsZVJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplRmluZEFsbFJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICovCiAgICBub3JtYWxpemVGaW5kQWxsUmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZUZpbmRBbGxSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVBcnJheVJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplRmluZEJlbG9uZ3NUb1Jlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICovCiAgICBub3JtYWxpemVGaW5kQmVsb25nc1RvUmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZUZpbmRCZWxvbmdzVG9SZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVTaW5nbGVSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfSwKCiAgICAvKioKICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIG5vcm1hbGl6ZUZpbmRIYXNNYW55UmVzcG9uc2UKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gcHJpbWFyeU1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgICBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFR5cGUKICAgICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICAgKi8KICAgIG5vcm1hbGl6ZUZpbmRIYXNNYW55UmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZUZpbmRIYXNNYW55UmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplQXJyYXlSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfSwKCiAgICAvKioKICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIG5vcm1hbGl6ZUZpbmRNYW55UmVzcG9uc2UKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gcHJpbWFyeU1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgICBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFR5cGUKICAgICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICAgKi8KICAgIG5vcm1hbGl6ZUZpbmRNYW55UmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZUZpbmRNYW55UmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplQXJyYXlSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfSwKCiAgICAvKioKICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIG5vcm1hbGl6ZVF1ZXJ5UmVzcG9uc2UKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gcHJpbWFyeU1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgICBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFR5cGUKICAgICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICAgKi8KICAgIG5vcm1hbGl6ZVF1ZXJ5UmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZVF1ZXJ5UmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplQXJyYXlSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfSwKCiAgICAvKioKICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIG5vcm1hbGl6ZUNyZWF0ZVJlY29yZFJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICovCiAgICBub3JtYWxpemVDcmVhdGVSZWNvcmRSZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplQ3JlYXRlUmVjb3JkUmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplU2F2ZVJlc3BvbnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qKgogICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplRGVsZXRlUmVjb3JkUmVzcG9uc2UKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gcHJpbWFyeU1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgICBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFR5cGUKICAgICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICAgKi8KICAgIG5vcm1hbGl6ZURlbGV0ZVJlY29yZFJlc3BvbnNlOiBmdW5jdGlvbiBub3JtYWxpemVEZWxldGVSZWNvcmRSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVTYXZlUmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBub3JtYWxpemVVcGRhdGVSZWNvcmRSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAqLwogICAgbm9ybWFsaXplVXBkYXRlUmVjb3JkUmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZVVwZGF0ZVJlY29yZFJlc3BvbnNlKHN0b3JlLCBwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCwgaWQsIHJlcXVlc3RUeXBlKSB7CiAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZVNhdmVSZXNwb25zZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfSwKCiAgICAvKioKICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIG5vcm1hbGl6ZVNhdmVSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAqLwogICAgbm9ybWFsaXplU2F2ZVJlc3BvbnNlOiBmdW5jdGlvbiBub3JtYWxpemVTYXZlUmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplU2luZ2xlUmVzcG9uc2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBub3JtYWxpemVTaW5nbGVSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAqLwogICAgbm9ybWFsaXplU2luZ2xlUmVzcG9uc2U6IGZ1bmN0aW9uIG5vcm1hbGl6ZVNpbmdsZVJlc3BvbnNlKHN0b3JlLCBwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCwgaWQsIHJlcXVlc3RUeXBlKSB7CiAgICAgIHJldHVybiB0aGlzLl9ub3JtYWxpemVSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSwgdHJ1ZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2Qgbm9ybWFsaXplQXJyYXlSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgICAqLwogICAgbm9ybWFsaXplQXJyYXlSZXNwb25zZTogZnVuY3Rpb24gbm9ybWFsaXplQXJyYXlSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgICByZXR1cm4gdGhpcy5fbm9ybWFsaXplUmVzcG9uc2Uoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkLCBpZCwgcmVxdWVzdFR5cGUsIGZhbHNlKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBtZXRob2QgX25vcm1hbGl6ZVJlc3BvbnNlCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IHByaW1hcnlNb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gaWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICAgIEBwYXJhbSB7Qm9vbGVhbn0gaXNTaW5nbGUKICAgICAgQHJldHVybiB7T2JqZWN0fSBKU09OLUFQSSBEb2N1bWVudAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIF9ub3JtYWxpemVSZXNwb25zZTogZnVuY3Rpb24gX25vcm1hbGl6ZVJlc3BvbnNlKHN0b3JlLCBwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCwgaWQsIHJlcXVlc3RUeXBlLCBpc1NpbmdsZSkgewogICAgICB2YXIgZG9jdW1lbnRIYXNoID0gewogICAgICAgIGRhdGE6IG51bGwsCiAgICAgICAgaW5jbHVkZWQ6IFtdCiAgICAgIH07CiAgICAgIHZhciBtZXRhID0gdGhpcy5leHRyYWN0TWV0YShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQpOwoKICAgICAgaWYgKG1ldGEpIHsKICAgICAgICAoZmFsc2UgJiYgIShFbWJlci50eXBlT2YobWV0YSkgPT09ICdvYmplY3QnKSAmJiBFbWJlci5hc3NlcnQoJ1RoZSBgbWV0YWAgcmV0dXJuZWQgZnJvbSBgZXh0cmFjdE1ldGFgIGhhcyB0byBiZSBhbiBvYmplY3QsIG5vdCAiJyArIEVtYmVyLnR5cGVPZihtZXRhKSArICciLicsIEVtYmVyLnR5cGVPZihtZXRhKSA9PT0gJ29iamVjdCcpKTsKICAgICAgICBkb2N1bWVudEhhc2gubWV0YSA9IG1ldGE7CiAgICAgIH0KCiAgICAgIGlmIChpc1NpbmdsZSkgewogICAgICAgIHZhciBfdGhpcyRub3JtYWxpemUgPSB0aGlzLm5vcm1hbGl6ZShwcmltYXJ5TW9kZWxDbGFzcywgcGF5bG9hZCksCiAgICAgICAgICAgIGRhdGEgPSBfdGhpcyRub3JtYWxpemUuZGF0YSwKICAgICAgICAgICAgaW5jbHVkZWQgPSBfdGhpcyRub3JtYWxpemUuaW5jbHVkZWQ7CgogICAgICAgIGRvY3VtZW50SGFzaC5kYXRhID0gZGF0YTsKCiAgICAgICAgaWYgKGluY2x1ZGVkKSB7CiAgICAgICAgICBkb2N1bWVudEhhc2guaW5jbHVkZWQgPSBpbmNsdWRlZDsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIHJldCA9IG5ldyBBcnJheShwYXlsb2FkLmxlbmd0aCk7CgogICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gcGF5bG9hZC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgIHZhciBpdGVtID0gcGF5bG9hZFtpXTsKCiAgICAgICAgICB2YXIgX3RoaXMkbm9ybWFsaXplMiA9IHRoaXMubm9ybWFsaXplKHByaW1hcnlNb2RlbENsYXNzLCBpdGVtKSwKICAgICAgICAgICAgICBfZGF0YSA9IF90aGlzJG5vcm1hbGl6ZTIuZGF0YSwKICAgICAgICAgICAgICBfaW5jbHVkZWQgPSBfdGhpcyRub3JtYWxpemUyLmluY2x1ZGVkOwoKICAgICAgICAgIGlmIChfaW5jbHVkZWQpIHsKICAgICAgICAgICAgdmFyIF9kb2N1bWVudEhhc2gkaW5jbHVkZTsKCiAgICAgICAgICAgIChfZG9jdW1lbnRIYXNoJGluY2x1ZGUgPSBkb2N1bWVudEhhc2guaW5jbHVkZWQpLnB1c2guYXBwbHkoX2RvY3VtZW50SGFzaCRpbmNsdWRlLCBfaW5jbHVkZWQpOwogICAgICAgICAgfQoKICAgICAgICAgIHJldFtpXSA9IF9kYXRhOwogICAgICAgIH0KCiAgICAgICAgZG9jdW1lbnRIYXNoLmRhdGEgPSByZXQ7CiAgICAgIH0KCiAgICAgIHJldHVybiBkb2N1bWVudEhhc2g7CiAgICB9LAoKICAgIC8qKgogICAgICBOb3JtYWxpemVzIGEgcGFydCBvZiB0aGUgSlNPTiBwYXlsb2FkIHJldHVybmVkIGJ5CiAgICAgIHRoZSBzZXJ2ZXIuIFlvdSBzaG91bGQgb3ZlcnJpZGUgdGhpcyBtZXRob2QsIG11bmdlIHRoZSBoYXNoCiAgICAgIGFuZCBjYWxsIHN1cGVyIGlmIHlvdSBoYXZlIGdlbmVyaWMgbm9ybWFsaXphdGlvbiB0byBkby4KICAgICAgIEl0IHRha2VzIHRoZSB0eXBlIG9mIHRoZSByZWNvcmQgdGhhdCBpcyBiZWluZyBub3JtYWxpemVkCiAgICAgIChhcyBhIE1vZGVsIGNsYXNzKSwgdGhlIHByb3BlcnR5IHdoZXJlIHRoZSBoYXNoIHdhcwogICAgICBvcmlnaW5hbGx5IGZvdW5kLCBhbmQgdGhlIGhhc2ggdG8gbm9ybWFsaXplLgogICAgICAgWW91IGNhbiB1c2UgdGhpcyBtZXRob2QsIGZvciBleGFtcGxlLCB0byBub3JtYWxpemUgdW5kZXJzY29yZWQga2V5cyB0byBjYW1lbGl6ZWQKICAgICAgb3Igb3RoZXIgZ2VuZXJhbC1wdXJwb3NlIG5vcm1hbGl6YXRpb25zLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBKU09OU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24nOwogICAgICBpbXBvcnQgeyB1bmRlcnNjb3JlIH0gZnJvbSAnQGVtYmVyL3N0cmluZyc7CiAgICAgIGltcG9ydCB7IGdldCB9IGZyb20gJ0BlbWJlci9vYmplY3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBub3JtYWxpemUodHlwZUNsYXNzLCBoYXNoKSB7CiAgICAgICAgICB2YXIgZmllbGRzID0gZ2V0KHR5cGVDbGFzcywgJ2ZpZWxkcycpOwogICAgICAgICAgIGZpZWxkcy5mb3JFYWNoKGZ1bmN0aW9uKHR5cGUsIGZpZWxkKSB7CiAgICAgICAgICAgIHZhciBwYXlsb2FkRmllbGQgPSB1bmRlcnNjb3JlKGZpZWxkKTsKICAgICAgICAgICAgaWYgKGZpZWxkID09PSBwYXlsb2FkRmllbGQpIHsgcmV0dXJuOyB9CiAgICAgICAgICAgICBoYXNoW2ZpZWxkXSA9IGhhc2hbcGF5bG9hZEZpZWxkXTsKICAgICAgICAgICAgZGVsZXRlIGhhc2hbcGF5bG9hZEZpZWxkXTsKICAgICAgICAgIH0pOwogICAgICAgICAgIHJldHVybiB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBub3JtYWxpemUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZUNsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBoYXNoCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICovCiAgICBub3JtYWxpemU6IGZ1bmN0aW9uIG5vcm1hbGl6ZShtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpIHsKICAgICAgdmFyIGRhdGEgPSBudWxsOwoKICAgICAgaWYgKHJlc291cmNlSGFzaCkgewogICAgICAgIHRoaXMubm9ybWFsaXplVXNpbmdEZWNsYXJlZE1hcHBpbmcobW9kZWxDbGFzcywgcmVzb3VyY2VIYXNoKTsKCiAgICAgICAgaWYgKEVtYmVyLnR5cGVPZihyZXNvdXJjZUhhc2gubGlua3MpID09PSAnb2JqZWN0JykgewogICAgICAgICAgdGhpcy5ub3JtYWxpemVVc2luZ0RlY2xhcmVkTWFwcGluZyhtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gubGlua3MpOwogICAgICAgIH0KCiAgICAgICAgZGF0YSA9IHsKICAgICAgICAgIGlkOiB0aGlzLmV4dHJhY3RJZChtb2RlbENsYXNzLCByZXNvdXJjZUhhc2gpLAogICAgICAgICAgdHlwZTogbW9kZWxDbGFzcy5tb2RlbE5hbWUsCiAgICAgICAgICBhdHRyaWJ1dGVzOiB0aGlzLmV4dHJhY3RBdHRyaWJ1dGVzKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCksCiAgICAgICAgICByZWxhdGlvbnNoaXBzOiB0aGlzLmV4dHJhY3RSZWxhdGlvbnNoaXBzKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCkKICAgICAgICB9OwogICAgICAgIHRoaXMuYXBwbHlUcmFuc2Zvcm1zKG1vZGVsQ2xhc3MsIGRhdGEuYXR0cmlidXRlcyk7CiAgICAgIH0KCiAgICAgIHJldHVybiB7CiAgICAgICAgZGF0YTogZGF0YQogICAgICB9OwogICAgfSwKCiAgICAvKioKICAgICAgUmV0dXJucyB0aGUgcmVzb3VyY2UncyBJRC4KICAgICAgIEBtZXRob2QgZXh0cmFjdElkCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBtb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZXNvdXJjZUhhc2gKICAgICAgQHJldHVybiB7U3RyaW5nfQogICAgKi8KICAgIGV4dHJhY3RJZDogZnVuY3Rpb24gZXh0cmFjdElkKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCkgewogICAgICB2YXIgcHJpbWFyeUtleSA9IEVtYmVyLmdldCh0aGlzLCAncHJpbWFyeUtleScpOwogICAgICB2YXIgaWQgPSByZXNvdXJjZUhhc2hbcHJpbWFyeUtleV07CiAgICAgIHJldHVybiAoMCwgX3ByaXZhdGUuY29lcmNlSWQpKGlkKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFJldHVybnMgdGhlIHJlc291cmNlJ3MgYXR0cmlidXRlcyBmb3JtYXR0ZWQgYXMgYSBKU09OLUFQSSAiYXR0cmlidXRlcyBvYmplY3QiLgogICAgICAgaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdC8jZG9jdW1lbnQtcmVzb3VyY2Utb2JqZWN0LWF0dHJpYnV0ZXMKICAgICAgIEBtZXRob2QgZXh0cmFjdEF0dHJpYnV0ZXMKICAgICAgQHBhcmFtIHtPYmplY3R9IG1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlc291cmNlSGFzaAogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgZXh0cmFjdEF0dHJpYnV0ZXM6IGZ1bmN0aW9uIGV4dHJhY3RBdHRyaWJ1dGVzKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCkgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIHZhciBhdHRyaWJ1dGVLZXk7CiAgICAgIHZhciBhdHRyaWJ1dGVzID0ge307CiAgICAgIG1vZGVsQ2xhc3MuZWFjaEF0dHJpYnV0ZShmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgYXR0cmlidXRlS2V5ID0gX3RoaXMyLmtleUZvckF0dHJpYnV0ZShrZXksICdkZXNlcmlhbGl6ZScpOwoKICAgICAgICBpZiAocmVzb3VyY2VIYXNoW2F0dHJpYnV0ZUtleV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgYXR0cmlidXRlc1trZXldID0gcmVzb3VyY2VIYXNoW2F0dHJpYnV0ZUtleV07CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIGF0dHJpYnV0ZXM7CiAgICB9LAoKICAgIC8qKgogICAgICBSZXR1cm5zIGEgcmVsYXRpb25zaGlwIGZvcm1hdHRlZCBhcyBhIEpTT04tQVBJICJyZWxhdGlvbnNoaXAgb2JqZWN0Ii4KICAgICAgIGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2RvY3VtZW50LXJlc291cmNlLW9iamVjdC1yZWxhdGlvbnNoaXBzCiAgICAgICBAbWV0aG9kIGV4dHJhY3RSZWxhdGlvbnNoaXAKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlbGF0aW9uc2hpcE1vZGVsTmFtZQogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwSGFzaAogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgZXh0cmFjdFJlbGF0aW9uc2hpcDogZnVuY3Rpb24gZXh0cmFjdFJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXBNb2RlbE5hbWUsIHJlbGF0aW9uc2hpcEhhc2gpIHsKICAgICAgaWYgKEVtYmVyLmlzTm9uZShyZWxhdGlvbnNoaXBIYXNoKSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIC8qCiAgICAgICAgV2hlbiBgcmVsYXRpb25zaGlwSGFzaGAgaXMgYW4gb2JqZWN0IGl0IHVzdWFsbHkgbWVhbnMgdGhhdCB0aGUgcmVsYXRpb25zaGlwCiAgICAgICAgaXMgcG9seW1vcnBoaWMuIEl0IGNvdWxkIGhvd2V2ZXIgYWxzbyBiZSBlbWJlZGRlZCByZXNvdXJjZXMgdGhhdCB0aGUKICAgICAgICBFbWJlZGRlZFJlY29yZHNNaXhpbiBoYXMgYmUgYWJsZSB0byBwcm9jZXNzLgogICAgICAqLwoKCiAgICAgIGlmIChFbWJlci50eXBlT2YocmVsYXRpb25zaGlwSGFzaCkgPT09ICdvYmplY3QnKSB7CiAgICAgICAgaWYgKHJlbGF0aW9uc2hpcEhhc2guaWQpIHsKICAgICAgICAgIHJlbGF0aW9uc2hpcEhhc2guaWQgPSAoMCwgX3ByaXZhdGUuY29lcmNlSWQpKHJlbGF0aW9uc2hpcEhhc2guaWQpOwogICAgICAgIH0KCiAgICAgICAgdmFyIG1vZGVsQ2xhc3MgPSB0aGlzLnN0b3JlLm1vZGVsRm9yKHJlbGF0aW9uc2hpcE1vZGVsTmFtZSk7CgogICAgICAgIGlmIChyZWxhdGlvbnNoaXBIYXNoLnR5cGUgJiYgISgwLCBfcHJpdmF0ZTIubW9kZWxIYXNBdHRyaWJ1dGVPclJlbGF0aW9uc2hpcE5hbWVkVHlwZSkobW9kZWxDbGFzcykpIHsKICAgICAgICAgIHJlbGF0aW9uc2hpcEhhc2gudHlwZSA9IHRoaXMubW9kZWxOYW1lRnJvbVBheWxvYWRLZXkocmVsYXRpb25zaGlwSGFzaC50eXBlKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiByZWxhdGlvbnNoaXBIYXNoOwogICAgICB9CgogICAgICByZXR1cm4gewogICAgICAgIGlkOiAoMCwgX3ByaXZhdGUuY29lcmNlSWQpKHJlbGF0aW9uc2hpcEhhc2gpLAogICAgICAgIHR5cGU6IHJlbGF0aW9uc2hpcE1vZGVsTmFtZQogICAgICB9OwogICAgfSwKCiAgICAvKioKICAgICAgUmV0dXJucyBhIHBvbHltb3JwaGljIHJlbGF0aW9uc2hpcCBmb3JtYXR0ZWQgYXMgYSBKU09OLUFQSSAicmVsYXRpb25zaGlwIG9iamVjdCIuCiAgICAgICBodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0LyNkb2N1bWVudC1yZXNvdXJjZS1vYmplY3QtcmVsYXRpb25zaGlwcwogICAgICAgYHJlbGF0aW9uc2hpcE9wdGlvbnNgIGlzIGEgaGFzaCB3aGljaCBjb250YWlucyBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHRoZQogICAgICBwb2x5bW9ycGhpYyByZWxhdGlvbnNoaXAgd2hpY2ggc2hvdWxkIGJlIGV4dHJhY3RlZDoKICAgICAgICAtIGByZXNvdXJjZUhhc2hgIGNvbXBsZXRlIGhhc2ggb2YgdGhlIHJlc291cmNlIHRoZSByZWxhdGlvbnNoaXAgc2hvdWxkIGJlCiAgICAgICAgICBleHRyYWN0ZWQgZnJvbQogICAgICAgIC0gYHJlbGF0aW9uc2hpcEtleWAga2V5IHVuZGVyIHdoaWNoIHRoZSB2YWx1ZSBmb3IgdGhlIHJlbGF0aW9uc2hpcCBpcwogICAgICAgICAgZXh0cmFjdGVkIGZyb20gdGhlIHJlc291cmNlSGFzaAogICAgICAgIC0gYHJlbGF0aW9uc2hpcE1ldGFgIG1ldGEgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHJlbGF0aW9uc2hpcAogICAgICAgQG1ldGhvZCBleHRyYWN0UG9seW1vcnBoaWNSZWxhdGlvbnNoaXAKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlbGF0aW9uc2hpcE1vZGVsTmFtZQogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwSGFzaAogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwT3B0aW9ucwogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgZXh0cmFjdFBvbHltb3JwaGljUmVsYXRpb25zaGlwOiBmdW5jdGlvbiBleHRyYWN0UG9seW1vcnBoaWNSZWxhdGlvbnNoaXAocmVsYXRpb25zaGlwTW9kZWxOYW1lLCByZWxhdGlvbnNoaXBIYXNoLCByZWxhdGlvbnNoaXBPcHRpb25zKSB7CiAgICAgIHJldHVybiB0aGlzLmV4dHJhY3RSZWxhdGlvbnNoaXAocmVsYXRpb25zaGlwTW9kZWxOYW1lLCByZWxhdGlvbnNoaXBIYXNoKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFJldHVybnMgdGhlIHJlc291cmNlJ3MgcmVsYXRpb25zaGlwcyBmb3JtYXR0ZWQgYXMgYSBKU09OLUFQSSAicmVsYXRpb25zaGlwcyBvYmplY3QiLgogICAgICAgaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdC8jZG9jdW1lbnQtcmVzb3VyY2Utb2JqZWN0LXJlbGF0aW9uc2hpcHMKICAgICAgIEBtZXRob2QgZXh0cmFjdFJlbGF0aW9uc2hpcHMKICAgICAgQHBhcmFtIHtPYmplY3R9IG1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHJlc291cmNlSGFzaAogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAqLwogICAgZXh0cmFjdFJlbGF0aW9uc2hpcHM6IGZ1bmN0aW9uIGV4dHJhY3RSZWxhdGlvbnNoaXBzKG1vZGVsQ2xhc3MsIHJlc291cmNlSGFzaCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHZhciByZWxhdGlvbnNoaXBzID0ge307CiAgICAgIG1vZGVsQ2xhc3MuZWFjaFJlbGF0aW9uc2hpcChmdW5jdGlvbiAoa2V5LCByZWxhdGlvbnNoaXBNZXRhKSB7CiAgICAgICAgdmFyIHJlbGF0aW9uc2hpcCA9IG51bGw7CgogICAgICAgIHZhciByZWxhdGlvbnNoaXBLZXkgPSBfdGhpczMua2V5Rm9yUmVsYXRpb25zaGlwKGtleSwgcmVsYXRpb25zaGlwTWV0YS5raW5kLCAnZGVzZXJpYWxpemUnKTsKCiAgICAgICAgaWYgKHJlc291cmNlSGFzaFtyZWxhdGlvbnNoaXBLZXldICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHZhciBkYXRhID0gbnVsbDsKICAgICAgICAgIHZhciByZWxhdGlvbnNoaXBIYXNoID0gcmVzb3VyY2VIYXNoW3JlbGF0aW9uc2hpcEtleV07CgogICAgICAgICAgaWYgKHJlbGF0aW9uc2hpcE1ldGEua2luZCA9PT0gJ2JlbG9uZ3NUbycpIHsKICAgICAgICAgICAgaWYgKHJlbGF0aW9uc2hpcE1ldGEub3B0aW9ucy5wb2x5bW9ycGhpYykgewogICAgICAgICAgICAgIC8vIGV4dHJhY3RpbmcgYSBwb2x5bW9ycGhpYyBiZWxvbmdzVG8gbWF5IG5lZWQgbW9yZSBpbmZvcm1hdGlvbgogICAgICAgICAgICAgIC8vIHRoYW4gdGhlIHR5cGUgYW5kIHRoZSBoYXNoICh3aGljaCBtaWdodCBvbmx5IGJlIGFuIGlkKSBmb3IgdGhlCiAgICAgICAgICAgICAgLy8gcmVsYXRpb25zaGlwLCBoZW5jZSB3ZSBwYXNzIHRoZSBrZXksIHJlc291cmNlIGFuZAogICAgICAgICAgICAgIC8vIHJlbGF0aW9uc2hpcE1ldGEgdG9vCiAgICAgICAgICAgICAgZGF0YSA9IF90aGlzMy5leHRyYWN0UG9seW1vcnBoaWNSZWxhdGlvbnNoaXAocmVsYXRpb25zaGlwTWV0YS50eXBlLCByZWxhdGlvbnNoaXBIYXNoLCB7CiAgICAgICAgICAgICAgICBrZXk6IGtleSwKICAgICAgICAgICAgICAgIHJlc291cmNlSGFzaDogcmVzb3VyY2VIYXNoLAogICAgICAgICAgICAgICAgcmVsYXRpb25zaGlwTWV0YTogcmVsYXRpb25zaGlwTWV0YQogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGRhdGEgPSBfdGhpczMuZXh0cmFjdFJlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXBNZXRhLnR5cGUsIHJlbGF0aW9uc2hpcEhhc2gpOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgaWYgKHJlbGF0aW9uc2hpcE1ldGEua2luZCA9PT0gJ2hhc01hbnknKSB7CiAgICAgICAgICAgIGlmICghRW1iZXIuaXNOb25lKHJlbGF0aW9uc2hpcEhhc2gpKSB7CiAgICAgICAgICAgICAgZGF0YSA9IG5ldyBBcnJheShyZWxhdGlvbnNoaXBIYXNoLmxlbmd0aCk7CgogICAgICAgICAgICAgIGlmIChyZWxhdGlvbnNoaXBNZXRhLm9wdGlvbnMucG9seW1vcnBoaWMpIHsKICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gcmVsYXRpb25zaGlwSGFzaC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgICAgICAgICAgdmFyIGl0ZW0gPSByZWxhdGlvbnNoaXBIYXNoW2ldOwogICAgICAgICAgICAgICAgICBkYXRhW2ldID0gX3RoaXMzLmV4dHJhY3RQb2x5bW9ycGhpY1JlbGF0aW9uc2hpcChyZWxhdGlvbnNoaXBNZXRhLnR5cGUsIGl0ZW0sIHsKICAgICAgICAgICAgICAgICAgICBrZXk6IGtleSwKICAgICAgICAgICAgICAgICAgICByZXNvdXJjZUhhc2g6IHJlc291cmNlSGFzaCwKICAgICAgICAgICAgICAgICAgICByZWxhdGlvbnNoaXBNZXRhOiByZWxhdGlvbnNoaXBNZXRhCiAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9sID0gcmVsYXRpb25zaGlwSGFzaC5sZW5ndGg7IF9pIDwgX2w7IF9pKyspIHsKICAgICAgICAgICAgICAgICAgdmFyIF9pdGVtID0gcmVsYXRpb25zaGlwSGFzaFtfaV07CiAgICAgICAgICAgICAgICAgIGRhdGFbX2ldID0gX3RoaXMzLmV4dHJhY3RSZWxhdGlvbnNoaXAocmVsYXRpb25zaGlwTWV0YS50eXBlLCBfaXRlbSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CgogICAgICAgICAgcmVsYXRpb25zaGlwID0gewogICAgICAgICAgICBkYXRhOiBkYXRhCiAgICAgICAgICB9OwogICAgICAgIH0KCiAgICAgICAgdmFyIGxpbmtLZXkgPSBfdGhpczMua2V5Rm9yTGluayhrZXksIHJlbGF0aW9uc2hpcE1ldGEua2luZCk7CgogICAgICAgIGlmIChyZXNvdXJjZUhhc2gubGlua3MgJiYgcmVzb3VyY2VIYXNoLmxpbmtzW2xpbmtLZXldICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHZhciByZWxhdGVkID0gcmVzb3VyY2VIYXNoLmxpbmtzW2xpbmtLZXldOwogICAgICAgICAgcmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwIHx8IHt9OwogICAgICAgICAgcmVsYXRpb25zaGlwLmxpbmtzID0gewogICAgICAgICAgICByZWxhdGVkOiByZWxhdGVkCiAgICAgICAgICB9OwogICAgICAgIH0KCiAgICAgICAgaWYgKHJlbGF0aW9uc2hpcCkgewogICAgICAgICAgcmVsYXRpb25zaGlwc1trZXldID0gcmVsYXRpb25zaGlwOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiByZWxhdGlvbnNoaXBzOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBtb2RlbE5hbWVGcm9tUGF5bG9hZEtleQogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5CiAgICAgIEByZXR1cm4ge1N0cmluZ30gdGhlIG1vZGVsJ3MgbW9kZWxOYW1lCiAgICAqLwogICAgLy8gVE9ETyBAZGVwcmVjYXRlZCBVc2UgbW9kZWxOYW1lRnJvbVBheWxvYWRUeXBlIGluc3RlYWQKICAgIG1vZGVsTmFtZUZyb21QYXlsb2FkS2V5OiBmdW5jdGlvbiBtb2RlbE5hbWVGcm9tUGF5bG9hZEtleShrZXkpIHsKICAgICAgcmV0dXJuICgwLCBfc3RvcmUubm9ybWFsaXplTW9kZWxOYW1lKShrZXkpOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBub3JtYWxpemVSZWxhdGlvbnNoaXBzCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgbm9ybWFsaXplUmVsYXRpb25zaGlwczogZnVuY3Rpb24gbm9ybWFsaXplUmVsYXRpb25zaGlwcyh0eXBlQ2xhc3MsIGhhc2gpIHsKICAgICAgdmFyIF90aGlzNCA9IHRoaXM7CgogICAgICB2YXIgcGF5bG9hZEtleTsKCiAgICAgIGlmICh0aGlzLmtleUZvclJlbGF0aW9uc2hpcCkgewogICAgICAgIHR5cGVDbGFzcy5lYWNoUmVsYXRpb25zaGlwKGZ1bmN0aW9uIChrZXksIHJlbGF0aW9uc2hpcCkgewogICAgICAgICAgcGF5bG9hZEtleSA9IF90aGlzNC5rZXlGb3JSZWxhdGlvbnNoaXAoa2V5LCByZWxhdGlvbnNoaXAua2luZCwgJ2Rlc2VyaWFsaXplJyk7CgogICAgICAgICAgaWYgKGtleSA9PT0gcGF5bG9hZEtleSkgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKGhhc2hbcGF5bG9hZEtleV0gPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CgogICAgICAgICAgaGFzaFtrZXldID0gaGFzaFtwYXlsb2FkS2V5XTsKICAgICAgICAgIGRlbGV0ZSBoYXNoW3BheWxvYWRLZXldOwogICAgICAgIH0pOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBAbWV0aG9kIG5vcm1hbGl6ZVVzaW5nRGVjbGFyZWRNYXBwaW5nCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgbm9ybWFsaXplVXNpbmdEZWNsYXJlZE1hcHBpbmc6IGZ1bmN0aW9uIG5vcm1hbGl6ZVVzaW5nRGVjbGFyZWRNYXBwaW5nKG1vZGVsQ2xhc3MsIGhhc2gpIHsKICAgICAgdmFyIGF0dHJzID0gRW1iZXIuZ2V0KHRoaXMsICdhdHRycycpOwogICAgICB2YXIgbm9ybWFsaXplZEtleTsKICAgICAgdmFyIHBheWxvYWRLZXk7CgogICAgICBpZiAoYXR0cnMpIHsKICAgICAgICBmb3IgKHZhciBrZXkgaW4gYXR0cnMpIHsKICAgICAgICAgIG5vcm1hbGl6ZWRLZXkgPSBwYXlsb2FkS2V5ID0gdGhpcy5fZ2V0TWFwcGVkS2V5KGtleSwgbW9kZWxDbGFzcyk7CgogICAgICAgICAgaWYgKGhhc2hbcGF5bG9hZEtleV0gPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoRW1iZXIuZ2V0KG1vZGVsQ2xhc3MsICdhdHRyaWJ1dGVzJykuaGFzKGtleSkpIHsKICAgICAgICAgICAgbm9ybWFsaXplZEtleSA9IHRoaXMua2V5Rm9yQXR0cmlidXRlKGtleSk7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKEVtYmVyLmdldChtb2RlbENsYXNzLCAncmVsYXRpb25zaGlwc0J5TmFtZScpLmhhcyhrZXkpKSB7CiAgICAgICAgICAgIG5vcm1hbGl6ZWRLZXkgPSB0aGlzLmtleUZvclJlbGF0aW9uc2hpcChrZXkpOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChwYXlsb2FkS2V5ICE9PSBub3JtYWxpemVkS2V5KSB7CiAgICAgICAgICAgIGhhc2hbbm9ybWFsaXplZEtleV0gPSBoYXNoW3BheWxvYWRLZXldOwogICAgICAgICAgICBkZWxldGUgaGFzaFtwYXlsb2FkS2V5XTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIExvb2tzIHVwIHRoZSBwcm9wZXJ0eSBrZXkgdGhhdCB3YXMgc2V0IGJ5IHRoZSBjdXN0b20gYGF0dHJgIG1hcHBpbmcKICAgICAgcGFzc2VkIHRvIHRoZSBzZXJpYWxpemVyLgogICAgICAgQG1ldGhvZCBfZ2V0TWFwcGVkS2V5CiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkKICAgICAgQHJldHVybiB7U3RyaW5nfSBrZXkKICAgICovCiAgICBfZ2V0TWFwcGVkS2V5OiBmdW5jdGlvbiBfZ2V0TWFwcGVkS2V5KGtleSwgbW9kZWxDbGFzcykgewogICAgICAoZmFsc2UgJiYgRW1iZXIud2FybignVGhlcmUgaXMgbm8gYXR0cmlidXRlIG9yIHJlbGF0aW9uc2hpcCB3aXRoIHRoZSBuYW1lIGAnICsga2V5ICsgJ2Agb24gYCcgKyBtb2RlbENsYXNzLm1vZGVsTmFtZSArICdgLiBDaGVjayB5b3VyIHNlcmlhbGl6ZXJzIGF0dHJzIGhhc2guJywgRW1iZXIuZ2V0KG1vZGVsQ2xhc3MsICdhdHRyaWJ1dGVzJykuaGFzKGtleSkgfHwgRW1iZXIuZ2V0KG1vZGVsQ2xhc3MsICdyZWxhdGlvbnNoaXBzQnlOYW1lJykuaGFzKGtleSksIHsKICAgICAgICBpZDogJ2RzLnNlcmlhbGl6ZXIubm8tbWFwcGVkLWF0dHJzLWtleScKICAgICAgfSkpOwogICAgICB2YXIgYXR0cnMgPSBFbWJlci5nZXQodGhpcywgJ2F0dHJzJyk7CiAgICAgIHZhciBtYXBwZWRLZXk7CgogICAgICBpZiAoYXR0cnMgJiYgYXR0cnNba2V5XSkgewogICAgICAgIG1hcHBlZEtleSA9IGF0dHJzW2tleV07IC8vV2UgbmVlZCB0byBhY2NvdW50IGZvciBib3RoIHRoZSB7IHRpdGxlOiAncG9zdF90aXRsZScgfSBhbmQKICAgICAgICAvL3sgdGl0bGU6IHsga2V5OiAncG9zdF90aXRsZScgfX0gZm9ybXMKCiAgICAgICAgaWYgKG1hcHBlZEtleS5rZXkpIHsKICAgICAgICAgIG1hcHBlZEtleSA9IG1hcHBlZEtleS5rZXk7CiAgICAgICAgfQoKICAgICAgICBpZiAodHlwZW9mIG1hcHBlZEtleSA9PT0gJ3N0cmluZycpIHsKICAgICAgICAgIGtleSA9IG1hcHBlZEtleTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBrZXk7CiAgICB9LAoKICAgIC8qKgogICAgICBDaGVjayBhdHRycy5rZXkuc2VyaWFsaXplIHByb3BlcnR5IHRvIGluZm9ybSBpZiB0aGUgYGtleWAKICAgICAgY2FuIGJlIHNlcmlhbGl6ZWQKICAgICAgIEBtZXRob2QgX2NhblNlcmlhbGl6ZQogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5CiAgICAgIEByZXR1cm4ge2Jvb2xlYW59IHRydWUgaWYgdGhlIGtleSBjYW4gYmUgc2VyaWFsaXplZAogICAgKi8KICAgIF9jYW5TZXJpYWxpemU6IGZ1bmN0aW9uIF9jYW5TZXJpYWxpemUoa2V5KSB7CiAgICAgIHZhciBhdHRycyA9IEVtYmVyLmdldCh0aGlzLCAnYXR0cnMnKTsKICAgICAgcmV0dXJuICFhdHRycyB8fCAhYXR0cnNba2V5XSB8fCBhdHRyc1trZXldLnNlcmlhbGl6ZSAhPT0gZmFsc2U7CiAgICB9LAoKICAgIC8qKgogICAgICBXaGVuIGF0dHJzLmtleS5zZXJpYWxpemUgaXMgc2V0IHRvIHRydWUgdGhlbgogICAgICBpdCB0YWtlcyBwcmlvcml0eSBvdmVyIHRoZSBvdGhlciBjaGVja3MgYW5kIHRoZSByZWxhdGVkCiAgICAgIGF0dHJpYnV0ZS9yZWxhdGlvbnNoaXAgd2lsbCBiZSBzZXJpYWxpemVkCiAgICAgICBAbWV0aG9kIF9tdXN0U2VyaWFsaXplCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkKICAgICAgQHJldHVybiB7Ym9vbGVhbn0gdHJ1ZSBpZiB0aGUga2V5IG11c3QgYmUgc2VyaWFsaXplZAogICAgKi8KICAgIF9tdXN0U2VyaWFsaXplOiBmdW5jdGlvbiBfbXVzdFNlcmlhbGl6ZShrZXkpIHsKICAgICAgdmFyIGF0dHJzID0gRW1iZXIuZ2V0KHRoaXMsICdhdHRycycpOwogICAgICByZXR1cm4gYXR0cnMgJiYgYXR0cnNba2V5XSAmJiBhdHRyc1trZXldLnNlcmlhbGl6ZSA9PT0gdHJ1ZTsKICAgIH0sCgogICAgLyoqCiAgICAgIENoZWNrIGlmIHRoZSBnaXZlbiBoYXNNYW55IHJlbGF0aW9uc2hpcCBzaG91bGQgYmUgc2VyaWFsaXplZAogICAgICAgQnkgZGVmYXVsdCBvbmx5IG1hbnktdG8tbWFueSBhbmQgbWFueS10by1ub25lIHJlbGF0aW9uc2hpcHMgYXJlIHNlcmlhbGl6ZWQuCiAgICAgIFRoaXMgY291bGQgYmUgY29uZmlndXJlZCBwZXIgcmVsYXRpb25zaGlwIGJ5IFNlcmlhbGl6ZXIncyBgYXR0cnNgIG9iamVjdC4KICAgICAgIEBtZXRob2Qgc2hvdWxkU2VyaWFsaXplSGFzTWFueQogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZWxhdGlvbnNoaXBUeXBlCiAgICAgIEByZXR1cm4ge2Jvb2xlYW59IHRydWUgaWYgdGhlIGhhc01hbnkgcmVsYXRpb25zaGlwIHNob3VsZCBiZSBzZXJpYWxpemVkCiAgICAqLwogICAgc2hvdWxkU2VyaWFsaXplSGFzTWFueTogZnVuY3Rpb24gc2hvdWxkU2VyaWFsaXplSGFzTWFueShzbmFwc2hvdCwga2V5LCByZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIHJlbGF0aW9uc2hpcFR5cGUgPSBzbmFwc2hvdC50eXBlLmRldGVybWluZVJlbGF0aW9uc2hpcFR5cGUocmVsYXRpb25zaGlwLCB0aGlzLnN0b3JlKTsKCiAgICAgIGlmICh0aGlzLl9tdXN0U2VyaWFsaXplKGtleSkpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuX2NhblNlcmlhbGl6ZShrZXkpICYmIChyZWxhdGlvbnNoaXBUeXBlID09PSAnbWFueVRvTm9uZScgfHwgcmVsYXRpb25zaGlwVHlwZSA9PT0gJ21hbnlUb01hbnknKTsKICAgIH0sCiAgICAvLyBTRVJJQUxJWkUKCiAgICAvKioKICAgICAgQ2FsbGVkIHdoZW4gYSByZWNvcmQgaXMgc2F2ZWQgaW4gb3JkZXIgdG8gY29udmVydCB0aGUKICAgICAgcmVjb3JkIGludG8gSlNPTi4KICAgICAgIEJ5IGRlZmF1bHQsIGl0IGNyZWF0ZXMgYSBKU09OIG9iamVjdCB3aXRoIGEga2V5IGZvcgogICAgICBlYWNoIGF0dHJpYnV0ZSBhbmQgYmVsb25nc1RvIHJlbGF0aW9uc2hpcC4KICAgICAgIEZvciBleGFtcGxlLCBjb25zaWRlciB0aGlzIG1vZGVsOgogICAgICAgYGBgYXBwL21vZGVscy9jb21tZW50LmpzCiAgICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyLCBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIHRpdGxlOiBhdHRyKCksCiAgICAgICAgYm9keTogYXR0cigpLAogICAgICAgICBhdXRob3I6IGJlbG9uZ3NUbygndXNlcicpCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRoZSBkZWZhdWx0IHNlcmlhbGl6YXRpb24gd291bGQgY3JlYXRlIGEgSlNPTiBvYmplY3QgbGlrZToKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgewogICAgICAgICJ0aXRsZSI6ICJSYWlscyBpcyB1bmFnaSIsCiAgICAgICAgImJvZHkiOiAiUmFpbHM/IE9tYWthc2U/IE9fTyIsCiAgICAgICAgImF1dGhvciI6IDEyCiAgICAgIH0KICAgICAgYGBgCiAgICAgICBCeSBkZWZhdWx0LCBhdHRyaWJ1dGVzIGFyZSBwYXNzZWQgdGhyb3VnaCBhcy1pcywgdW5sZXNzCiAgICAgIHlvdSBzcGVjaWZpZWQgYW4gYXR0cmlidXRlIHR5cGUgKGBhdHRyKCdkYXRlJylgKS4gSWYKICAgICAgeW91IHNwZWNpZnkgYSB0cmFuc2Zvcm0sIHRoZSBKYXZhU2NyaXB0IHZhbHVlIHdpbGwgYmUKICAgICAgc2VyaWFsaXplZCB3aGVuIGluc2VydGVkIGludG8gdGhlIEpTT04gaGFzaC4KICAgICAgIEJ5IGRlZmF1bHQsIGJlbG9uZ3MtdG8gcmVsYXRpb25zaGlwcyBhcmUgY29udmVydGVkIGludG8KICAgICAgSURzIHdoZW4gaW5zZXJ0ZWQgaW50byB0aGUgSlNPTiBoYXNoLgogICAgICAgIyMgSURzCiAgICAgICBgc2VyaWFsaXplYCB0YWtlcyBhbiBvcHRpb25zIGhhc2ggd2l0aCBhIHNpbmdsZSBvcHRpb246CiAgICAgIGBpbmNsdWRlSWRgLiBJZiB0aGlzIG9wdGlvbiBpcyBgdHJ1ZWAsIGBzZXJpYWxpemVgIHdpbGwsCiAgICAgIGJ5IGRlZmF1bHQgaW5jbHVkZSB0aGUgSUQgaW4gdGhlIEpTT04gb2JqZWN0IGl0IGJ1aWxkcy4KICAgICAgIFRoZSBhZGFwdGVyIHBhc3NlcyBpbiBgaW5jbHVkZUlkOiB0cnVlYCB3aGVuIHNlcmlhbGl6aW5nCiAgICAgIGEgcmVjb3JkIGZvciBgY3JlYXRlUmVjb3JkYCwgYnV0IG5vdCBmb3IgYHVwZGF0ZVJlY29yZGAuCiAgICAgICAjIyBDdXN0b21pemF0aW9uCiAgICAgICBZb3VyIHNlcnZlciBtYXkgZXhwZWN0IGEgZGlmZmVyZW50IEpTT04gZm9ybWF0IHRoYW4gdGhlCiAgICAgIGJ1aWx0LWluIHNlcmlhbGl6YXRpb24gZm9ybWF0LgogICAgICAgSW4gdGhhdCBjYXNlLCB5b3UgY2FuIGltcGxlbWVudCBgc2VyaWFsaXplYCB5b3Vyc2VsZiBhbmQKICAgICAgcmV0dXJuIGEgSlNPTiBoYXNoIG9mIHlvdXIgY2hvb3NpbmcuCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgSlNPTlNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05TZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgc2VyaWFsaXplKHNuYXBzaG90LCBvcHRpb25zKSB7CiAgICAgICAgICB2YXIganNvbiA9IHsKICAgICAgICAgICAgUE9TVF9UVEw6IHNuYXBzaG90LmF0dHIoJ3RpdGxlJyksCiAgICAgICAgICAgIFBPU1RfQkRZOiBzbmFwc2hvdC5hdHRyKCdib2R5JyksCiAgICAgICAgICAgIFBPU1RfQ01TOiBzbmFwc2hvdC5oYXNNYW55KCdjb21tZW50cycsIHsgaWRzOiB0cnVlIH0pCiAgICAgICAgICB9OwogICAgICAgICAgIGlmIChvcHRpb25zLmluY2x1ZGVJZCkgewogICAgICAgICAgICBqc29uLlBPU1RfSURfID0gc25hcHNob3QuaWQ7CiAgICAgICAgICB9CiAgICAgICAgICAgcmV0dXJuIGpzb247CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAjIyBDdXN0b21pemluZyBhbiBBcHAtV2lkZSBTZXJpYWxpemVyCiAgICAgICBJZiB5b3Ugd2FudCB0byBkZWZpbmUgYSBzZXJpYWxpemVyIGZvciB5b3VyIGVudGlyZQogICAgICBhcHBsaWNhdGlvbiwgeW91J2xsIHByb2JhYmx5IHdhbnQgdG8gdXNlIGBlYWNoQXR0cmlidXRlYAogICAgICBhbmQgYGVhY2hSZWxhdGlvbnNoaXBgIG9uIHRoZSByZWNvcmQuCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IEpTT05TZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbic7CiAgICAgIGltcG9ydCB7IHNpbmd1bGFyaXplIH0gZnJvbSAnZW1iZXItaW5mbGVjdG9yJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05TZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgc2VyaWFsaXplKHNuYXBzaG90LCBvcHRpb25zKSB7CiAgICAgICAgICB2YXIganNvbiA9IHt9OwogICAgICAgICAgIHNuYXBzaG90LmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24obmFtZSkgewogICAgICAgICAgICBqc29uW3NlcnZlckF0dHJpYnV0ZU5hbWUobmFtZSldID0gc25hcHNob3QuYXR0cihuYW1lKTsKICAgICAgICAgIH0pOwogICAgICAgICAgIHNuYXBzaG90LmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24obmFtZSwgcmVsYXRpb25zaGlwKSB7CiAgICAgICAgICAgIGlmIChyZWxhdGlvbnNoaXAua2luZCA9PT0gJ2hhc01hbnknKSB7CiAgICAgICAgICAgICAganNvbltzZXJ2ZXJIYXNNYW55TmFtZShuYW1lKV0gPSBzbmFwc2hvdC5oYXNNYW55KG5hbWUsIHsgaWRzOiB0cnVlIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICAgICBpZiAob3B0aW9ucy5pbmNsdWRlSWQpIHsKICAgICAgICAgICAganNvbi5JRF8gPSBzbmFwc2hvdC5pZDsKICAgICAgICAgIH0KICAgICAgICAgICByZXR1cm4ganNvbjsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgZnVuY3Rpb24gc2VydmVyQXR0cmlidXRlTmFtZShhdHRyaWJ1dGUpIHsKICAgICAgICByZXR1cm4gYXR0cmlidXRlLnVuZGVyc2NvcmUoKS50b1VwcGVyQ2FzZSgpOwogICAgICB9CiAgICAgICBmdW5jdGlvbiBzZXJ2ZXJIYXNNYW55TmFtZShuYW1lKSB7CiAgICAgICAgcmV0dXJuIHNlcnZlckF0dHJpYnV0ZU5hbWUoc2luZ3VsYXJpemUobmFtZSkpICsgIl9JRFMiOwogICAgICB9CiAgICAgIGBgYAogICAgICAgVGhpcyBzZXJpYWxpemVyIHdpbGwgZ2VuZXJhdGUgSlNPTiB0aGF0IGxvb2tzIGxpa2UgdGhpczoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgewogICAgICAgICJUSVRMRSI6ICJSYWlscyBpcyBvbWFrYXNlIiwKICAgICAgICAiQk9EWSI6ICJZZXAuIE9tYWthc2UuIiwKICAgICAgICAiQ09NTUVOVF9JRFMiOiBbIDEsIDIsIDMgXQogICAgICB9CiAgICAgIGBgYAogICAgICAgIyMgVHdlYWtpbmcgdGhlIERlZmF1bHQgSlNPTgogICAgICAgSWYgeW91IGp1c3Qgd2FudCB0byBkbyBzb21lIHNtYWxsIHR3ZWFrcyBvbiB0aGUgZGVmYXVsdCBKU09OLAogICAgICB5b3UgY2FuIGNhbGwgc3VwZXIgZmlyc3QgYW5kIG1ha2UgdGhlIHR3ZWFrcyBvbiB0aGUgcmV0dXJuZWQKICAgICAgSlNPTi4KICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBKU09OU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24nOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBzZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpIHsKICAgICAgICAgIHZhciBqc29uID0gdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICAgICBqc29uLnN1YmplY3QgPSBqc29uLnRpdGxlOwogICAgICAgICAgZGVsZXRlIGpzb24udGl0bGU7CiAgICAgICAgICAgcmV0dXJuIGpzb247CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZQogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgICBAcmV0dXJuIHtPYmplY3R9IGpzb24KICAgICovCiAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIHNlcmlhbGl6ZShzbmFwc2hvdCwgb3B0aW9ucykgewogICAgICB2YXIgX3RoaXM1ID0gdGhpczsKCiAgICAgIHZhciBqc29uID0ge307CgogICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLmluY2x1ZGVJZCkgewogICAgICAgIHZhciBpZCA9IHNuYXBzaG90LmlkOwoKICAgICAgICBpZiAoaWQpIHsKICAgICAgICAgIGpzb25bRW1iZXIuZ2V0KHRoaXMsICdwcmltYXJ5S2V5JyldID0gaWQ7CiAgICAgICAgfQogICAgICB9CgogICAgICBzbmFwc2hvdC5lYWNoQXR0cmlidXRlKGZ1bmN0aW9uIChrZXksIGF0dHJpYnV0ZSkgewogICAgICAgIF90aGlzNS5zZXJpYWxpemVBdHRyaWJ1dGUoc25hcHNob3QsIGpzb24sIGtleSwgYXR0cmlidXRlKTsKICAgICAgfSk7CiAgICAgIHNuYXBzaG90LmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24gKGtleSwgcmVsYXRpb25zaGlwKSB7CiAgICAgICAgaWYgKHJlbGF0aW9uc2hpcC5raW5kID09PSAnYmVsb25nc1RvJykgewogICAgICAgICAgX3RoaXM1LnNlcmlhbGl6ZUJlbG9uZ3NUbyhzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKTsKICAgICAgICB9IGVsc2UgaWYgKHJlbGF0aW9uc2hpcC5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgICAgIF90aGlzNS5zZXJpYWxpemVIYXNNYW55KHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiBqc29uOwogICAgfSwKCiAgICAvKioKICAgICAgWW91IGNhbiB1c2UgdGhpcyBtZXRob2QgdG8gY3VzdG9taXplIGhvdyBhIHNlcmlhbGl6ZWQgcmVjb3JkIGlzIGFkZGVkIHRvIHRoZSBjb21wbGV0ZQogICAgICBKU09OIGhhc2ggdG8gYmUgc2VudCB0byB0aGUgc2VydmVyLiBCeSBkZWZhdWx0IHRoZSBKU09OIFNlcmlhbGl6ZXIgZG9lcyBub3QgbmFtZXNwYWNlCiAgICAgIHRoZSBwYXlsb2FkIGFuZCBqdXN0IHNlbmRzIHRoZSByYXcgc2VyaWFsaXplZCBKU09OIG9iamVjdC4KICAgICAgSWYgeW91ciBzZXJ2ZXIgZXhwZWN0cyBuYW1lc3BhY2VkIGtleXMsIHlvdSBzaG91bGQgY29uc2lkZXIgdXNpbmcgdGhlIFJFU1RTZXJpYWxpemVyLgogICAgICBPdGhlcndpc2UgeW91IGNhbiBvdmVycmlkZSB0aGlzIG1ldGhvZCB0byBjdXN0b21pemUgaG93IHRoZSByZWNvcmQgaXMgYWRkZWQgdG8gdGhlIGhhc2guCiAgICAgIFRoZSBoYXNoIHByb3BlcnR5IHNob3VsZCBiZSBtb2RpZmllZCBieSByZWZlcmVuY2UuCiAgICAgICBGb3IgZXhhbXBsZSwgeW91ciBzZXJ2ZXIgbWF5IGV4cGVjdCB1bmRlcnNjb3JlZCByb290IG9iamVjdHMuCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CiAgICAgIGltcG9ydCB7IGRlY2FtZWxpemUgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgc2VyaWFsaXplSW50b0hhc2goZGF0YSwgdHlwZSwgc25hcHNob3QsIG9wdGlvbnMpIHsKICAgICAgICAgIHZhciByb290ID0gZGVjYW1lbGl6ZSh0eXBlLm1vZGVsTmFtZSk7CiAgICAgICAgICBkYXRhW3Jvb3RdID0gdGhpcy5zZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXJpYWxpemVJbnRvSGFzaAogICAgICBAcGFyYW0ge09iamVjdH0gaGFzaAogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlQ2xhc3MKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICovCiAgICBzZXJpYWxpemVJbnRvSGFzaDogZnVuY3Rpb24gc2VyaWFsaXplSW50b0hhc2goaGFzaCwgdHlwZUNsYXNzLCBzbmFwc2hvdCwgb3B0aW9ucykgewogICAgICBFbWJlci5hc3NpZ24oaGFzaCwgdGhpcy5zZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpKTsKICAgIH0sCgogICAgLyoqCiAgICAgIGBzZXJpYWxpemVBdHRyaWJ1dGVgIGNhbiBiZSB1c2VkIHRvIGN1c3RvbWl6ZSBob3cgYGF0dHJgCiAgICAgIHByb3BlcnRpZXMgYXJlIHNlcmlhbGl6ZWQKICAgICAgIEZvciBleGFtcGxlIGlmIHlvdSB3YW50ZWQgdG8gZW5zdXJlIGFsbCB5b3VyIGF0dHJpYnV0ZXMgd2VyZSBhbHdheXMKICAgICAgc2VyaWFsaXplZCBhcyBwcm9wZXJ0aWVzIG9uIGFuIGBhdHRyaWJ1dGVzYCBvYmplY3QgeW91IGNvdWxkCiAgICAgIHdyaXRlOgogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBKU09OU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24nOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBzZXJpYWxpemVBdHRyaWJ1dGUoc25hcHNob3QsIGpzb24sIGtleSwgYXR0cmlidXRlcykgewogICAgICAgICAganNvbi5hdHRyaWJ1dGVzID0ganNvbi5hdHRyaWJ1dGVzIHx8IHt9OwogICAgICAgICAgdGhpcy5fc3VwZXIoc25hcHNob3QsIGpzb24uYXR0cmlidXRlcywga2V5LCBhdHRyaWJ1dGVzKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc2VyaWFsaXplQXR0cmlidXRlCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEBwYXJhbSB7T2JqZWN0fSBqc29uCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBrZXkKICAgICAgQHBhcmFtIHtPYmplY3R9IGF0dHJpYnV0ZQogICAgKi8KICAgIHNlcmlhbGl6ZUF0dHJpYnV0ZTogZnVuY3Rpb24gc2VyaWFsaXplQXR0cmlidXRlKHNuYXBzaG90LCBqc29uLCBrZXksIGF0dHJpYnV0ZSkgewogICAgICBpZiAodGhpcy5fY2FuU2VyaWFsaXplKGtleSkpIHsKICAgICAgICB2YXIgdHlwZSA9IGF0dHJpYnV0ZS50eXBlOwogICAgICAgIHZhciB2YWx1ZSA9IHNuYXBzaG90LmF0dHIoa2V5KTsKCiAgICAgICAgaWYgKHR5cGUpIHsKICAgICAgICAgIHZhciB0cmFuc2Zvcm0gPSB0aGlzLnRyYW5zZm9ybUZvcih0eXBlKTsKICAgICAgICAgIHZhbHVlID0gdHJhbnNmb3JtLnNlcmlhbGl6ZSh2YWx1ZSwgYXR0cmlidXRlLm9wdGlvbnMpOwogICAgICAgIH0gLy8gaWYgcHJvdmlkZWQsIHVzZSB0aGUgbWFwcGluZyBwcm92aWRlZCBieSBgYXR0cnNgIGluCiAgICAgICAgLy8gdGhlIHNlcmlhbGl6ZXIKCgogICAgICAgIHZhciBwYXlsb2FkS2V5ID0gdGhpcy5fZ2V0TWFwcGVkS2V5KGtleSwgc25hcHNob3QudHlwZSk7CgogICAgICAgIGlmIChwYXlsb2FkS2V5ID09PSBrZXkgJiYgdGhpcy5rZXlGb3JBdHRyaWJ1dGUpIHsKICAgICAgICAgIHBheWxvYWRLZXkgPSB0aGlzLmtleUZvckF0dHJpYnV0ZShrZXksICdzZXJpYWxpemUnKTsKICAgICAgICB9CgogICAgICAgIGpzb25bcGF5bG9hZEtleV0gPSB2YWx1ZTsKICAgICAgfQogICAgfSwKCiAgICAvKioKICAgICAgYHNlcmlhbGl6ZUJlbG9uZ3NUb2AgY2FuIGJlIHVzZWQgdG8gY3VzdG9taXplIGhvdyBgYmVsb25nc1RvYAogICAgICBwcm9wZXJ0aWVzIGFyZSBzZXJpYWxpemVkLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL3Bvc3QuanMKICAgICAgaW1wb3J0IEpTT05TZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbic7CiAgICAgIGltcG9ydCB7IGlzTm9uZSB9IGZyb20gJ0BlbWJlci91dGlscyc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIHNlcmlhbGl6ZUJlbG9uZ3NUbyhzbmFwc2hvdCwganNvbiwgcmVsYXRpb25zaGlwKSB7CiAgICAgICAgICB2YXIga2V5ID0gcmVsYXRpb25zaGlwLmtleTsKICAgICAgICAgIHZhciBiZWxvbmdzVG8gPSBzbmFwc2hvdC5iZWxvbmdzVG8oa2V5KTsKICAgICAgICAgICBrZXkgPSB0aGlzLmtleUZvclJlbGF0aW9uc2hpcCA/IHRoaXMua2V5Rm9yUmVsYXRpb25zaGlwKGtleSwgImJlbG9uZ3NUbyIsICJzZXJpYWxpemUiKSA6IGtleTsKICAgICAgICAgICBqc29uW2tleV0gPSBpc05vbmUoYmVsb25nc1RvKSA/IGJlbG9uZ3NUbyA6IGJlbG9uZ3NUby5yZWNvcmQudG9KU09OKCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHNlcmlhbGl6ZUJlbG9uZ3NUbwogICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgICBAcGFyYW0ge09iamVjdH0ganNvbgogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwCiAgICAqLwogICAgc2VyaWFsaXplQmVsb25nc1RvOiBmdW5jdGlvbiBzZXJpYWxpemVCZWxvbmdzVG8oc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCkgewogICAgICB2YXIga2V5ID0gcmVsYXRpb25zaGlwLmtleTsKCiAgICAgIGlmICh0aGlzLl9jYW5TZXJpYWxpemUoa2V5KSkgewogICAgICAgIHZhciBiZWxvbmdzVG9JZCA9IHNuYXBzaG90LmJlbG9uZ3NUbyhrZXksIHsKICAgICAgICAgIGlkOiB0cnVlCiAgICAgICAgfSk7IC8vIGlmIHByb3ZpZGVkLCB1c2UgdGhlIG1hcHBpbmcgcHJvdmlkZWQgYnkgYGF0dHJzYCBpbgogICAgICAgIC8vIHRoZSBzZXJpYWxpemVyCgogICAgICAgIHZhciBwYXlsb2FkS2V5ID0gdGhpcy5fZ2V0TWFwcGVkS2V5KGtleSwgc25hcHNob3QudHlwZSk7CgogICAgICAgIGlmIChwYXlsb2FkS2V5ID09PSBrZXkgJiYgdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXApIHsKICAgICAgICAgIHBheWxvYWRLZXkgPSB0aGlzLmtleUZvclJlbGF0aW9uc2hpcChrZXksICdiZWxvbmdzVG8nLCAnc2VyaWFsaXplJyk7CiAgICAgICAgfSAvL05lZWQgdG8gY2hlY2sgd2hldGhlciB0aGUgaWQgaXMgdGhlcmUgZm9yIG5ldyZhc3luYyByZWNvcmRzCgoKICAgICAgICBpZiAoRW1iZXIuaXNOb25lKGJlbG9uZ3NUb0lkKSkgewogICAgICAgICAganNvbltwYXlsb2FkS2V5XSA9IG51bGw7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGpzb25bcGF5bG9hZEtleV0gPSBiZWxvbmdzVG9JZDsKICAgICAgICB9CgogICAgICAgIGlmIChyZWxhdGlvbnNoaXAub3B0aW9ucy5wb2x5bW9ycGhpYykgewogICAgICAgICAgdGhpcy5zZXJpYWxpemVQb2x5bW9ycGhpY1R5cGUoc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCk7CiAgICAgICAgfQogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgIGBzZXJpYWxpemVIYXNNYW55YCBjYW4gYmUgdXNlZCB0byBjdXN0b21pemUgaG93IGBoYXNNYW55YAogICAgIHByb3BlcnRpZXMgYXJlIHNlcmlhbGl6ZWQuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL3Bvc3QuanMKICAgICBpbXBvcnQgSlNPTlNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uJzsKICAgICBpbXBvcnQgRFMgZnJvbSAnZW1iZXItZGF0YSc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05TZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICBzZXJpYWxpemVIYXNNYW55KHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApIHsKICAgICAgICAgdmFyIGtleSA9IHJlbGF0aW9uc2hpcC5rZXk7CiAgICAgICAgIGlmIChrZXkgPT09ICdjb21tZW50cycpIHsKICAgICAgICAgICByZXR1cm47CiAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICAgfQogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIHNlcmlhbGl6ZUhhc01hbnkKICAgICBAcGFyYW0ge1NuYXBzaG90fSBzbmFwc2hvdAogICAgIEBwYXJhbSB7T2JqZWN0fSBqc29uCiAgICAgQHBhcmFtIHtPYmplY3R9IHJlbGF0aW9uc2hpcAogICAgKi8KICAgIHNlcmlhbGl6ZUhhc01hbnk6IGZ1bmN0aW9uIHNlcmlhbGl6ZUhhc01hbnkoc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCkgewogICAgICB2YXIga2V5ID0gcmVsYXRpb25zaGlwLmtleTsKCiAgICAgIGlmICh0aGlzLnNob3VsZFNlcmlhbGl6ZUhhc01hbnkoc25hcHNob3QsIGtleSwgcmVsYXRpb25zaGlwKSkgewogICAgICAgIHZhciBoYXNNYW55ID0gc25hcHNob3QuaGFzTWFueShrZXksIHsKICAgICAgICAgIGlkczogdHJ1ZQogICAgICAgIH0pOwoKICAgICAgICBpZiAoaGFzTWFueSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAvLyBpZiBwcm92aWRlZCwgdXNlIHRoZSBtYXBwaW5nIHByb3ZpZGVkIGJ5IGBhdHRyc2AgaW4KICAgICAgICAgIC8vIHRoZSBzZXJpYWxpemVyCiAgICAgICAgICB2YXIgcGF5bG9hZEtleSA9IHRoaXMuX2dldE1hcHBlZEtleShrZXksIHNuYXBzaG90LnR5cGUpOwoKICAgICAgICAgIGlmIChwYXlsb2FkS2V5ID09PSBrZXkgJiYgdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXApIHsKICAgICAgICAgICAgcGF5bG9hZEtleSA9IHRoaXMua2V5Rm9yUmVsYXRpb25zaGlwKGtleSwgJ2hhc01hbnknLCAnc2VyaWFsaXplJyk7CiAgICAgICAgICB9CgogICAgICAgICAganNvbltwYXlsb2FkS2V5XSA9IGhhc01hbnk7IC8vIFRPRE8gc3VwcG9ydCBmb3IgcG9seW1vcnBoaWMgbWFueVRvTm9uZSBhbmQgbWFueVRvTWFueSByZWxhdGlvbnNoaXBzCiAgICAgICAgfQogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBZb3UgY2FuIHVzZSB0aGlzIG1ldGhvZCB0byBjdXN0b21pemUgaG93IHBvbHltb3JwaGljIG9iamVjdHMgYXJlCiAgICAgIHNlcmlhbGl6ZWQuIE9iamVjdHMgYXJlIGNvbnNpZGVyZWQgdG8gYmUgcG9seW1vcnBoaWMgaWYKICAgICAgYHsgcG9seW1vcnBoaWM6IHRydWUgfWAgaXMgcGFzcyBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IHRvIHRoZQogICAgICBgYmVsb25nc1RvYCBmdW5jdGlvbi4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9jb21tZW50LmpzCiAgICAgIGltcG9ydCBKU09OU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24nOwogICAgICBpbXBvcnQgeyBpc05vbmUgfSBmcm9tICdAZW1iZXIvdXRpbHMnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBzZXJpYWxpemVQb2x5bW9ycGhpY1R5cGUoc25hcHNob3QsIGpzb24sIHJlbGF0aW9uc2hpcCkgewogICAgICAgICAgdmFyIGtleSA9IHJlbGF0aW9uc2hpcC5rZXk7CiAgICAgICAgICB2YXIgYmVsb25nc1RvID0gc25hcHNob3QuYmVsb25nc1RvKGtleSk7CiAgICAgICAgICAga2V5ID0gdGhpcy5rZXlGb3JBdHRyaWJ1dGUgPyB0aGlzLmtleUZvckF0dHJpYnV0ZShrZXksICdzZXJpYWxpemUnKSA6IGtleTsKICAgICAgICAgICBpZiAoaXNOb25lKGJlbG9uZ3NUbykpIHsKICAgICAgICAgICAganNvbltrZXkgKyAnX3R5cGUnXSA9IG51bGw7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBqc29uW2tleSArICdfdHlwZSddID0gYmVsb25nc1RvLm1vZGVsTmFtZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc2VyaWFsaXplUG9seW1vcnBoaWNUeXBlCiAgICAgIEBwYXJhbSB7U25hcHNob3R9IHNuYXBzaG90CiAgICAgIEBwYXJhbSB7T2JqZWN0fSBqc29uCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZWxhdGlvbnNoaXAKICAgICovCiAgICBzZXJpYWxpemVQb2x5bW9ycGhpY1R5cGU6IGZ1bmN0aW9uIHNlcmlhbGl6ZVBvbHltb3JwaGljVHlwZSgpIHt9LAoKICAgIC8qKgogICAgICBgZXh0cmFjdE1ldGFgIGlzIHVzZWQgdG8gZGVzZXJpYWxpemUgYW55IG1ldGEgaW5mb3JtYXRpb24gaW4gdGhlCiAgICAgIGFkYXB0ZXIgcGF5bG9hZC4gQnkgZGVmYXVsdCBFbWJlciBEYXRhIGV4cGVjdHMgbWV0YSBpbmZvcm1hdGlvbiB0bwogICAgICBiZSBsb2NhdGVkIG9uIHRoZSBgbWV0YWAgcHJvcGVydHkgb2YgdGhlIHBheWxvYWQgb2JqZWN0LgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL3Bvc3QuanMKICAgICAgaW1wb3J0IEpTT05TZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIGV4dHJhY3RNZXRhKHN0b3JlLCB0eXBlQ2xhc3MsIHBheWxvYWQpIHsKICAgICAgICAgIGlmIChwYXlsb2FkICYmIHBheWxvYWQuaGFzT3duUHJvcGVydHkoJ19wYWdpbmF0aW9uJykpIHsKICAgICAgICAgICAgbGV0IG1ldGEgPSBwYXlsb2FkLl9wYWdpbmF0aW9uOwogICAgICAgICAgICBkZWxldGUgcGF5bG9hZC5fcGFnaW5hdGlvbjsKICAgICAgICAgICAgcmV0dXJuIG1ldGE7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGV4dHJhY3RNZXRhCiAgICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICAgIEBwYXJhbSB7TW9kZWx9IG1vZGVsQ2xhc3MKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICovCiAgICBleHRyYWN0TWV0YTogZnVuY3Rpb24gZXh0cmFjdE1ldGEoc3RvcmUsIG1vZGVsQ2xhc3MsIHBheWxvYWQpIHsKICAgICAgaWYgKHBheWxvYWQgJiYgcGF5bG9hZFsnbWV0YSddICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB2YXIgbWV0YSA9IHBheWxvYWQubWV0YTsKICAgICAgICBkZWxldGUgcGF5bG9hZC5tZXRhOwogICAgICAgIHJldHVybiBtZXRhOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBgZXh0cmFjdEVycm9yc2AgaXMgdXNlZCB0byBleHRyYWN0IG1vZGVsIGVycm9ycyB3aGVuIGEgY2FsbAogICAgICB0byBgTW9kZWwjc2F2ZWAgZmFpbHMgd2l0aCBhbiBgSW52YWxpZEVycm9yYC4gQnkgZGVmYXVsdAogICAgICBFbWJlciBEYXRhIGV4cGVjdHMgZXJyb3IgaW5mb3JtYXRpb24gdG8gYmUgbG9jYXRlZCBvbiB0aGUgYGVycm9yc2AKICAgICAgcHJvcGVydHkgb2YgdGhlIHBheWxvYWQgb2JqZWN0LgogICAgICAgVGhpcyBzZXJpYWxpemVyIGV4cGVjdHMgdGhpcyBgZXJyb3JzYCBvYmplY3QgdG8gYmUgYW4gQXJyYXkgc2ltaWxhcgogICAgICB0byB0aGUgZm9sbG93aW5nLCBjb21wbGlhbnQgd2l0aCB0aGUgaHR0cHM6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2Vycm9ycyBzcGVjaWZpY2F0aW9uOgogICAgICAgYGBganMKICAgICAgewogICAgICAgICJlcnJvcnMiOiBbCiAgICAgICAgICB7CiAgICAgICAgICAgICJkZXRhaWwiOiAiVGhpcyB1c2VybmFtZSBpcyBhbHJlYWR5IHRha2VuISIsCiAgICAgICAgICAgICJzb3VyY2UiOiB7CiAgICAgICAgICAgICAgInBvaW50ZXIiOiAiZGF0YS9hdHRyaWJ1dGVzL3VzZXJuYW1lIgogICAgICAgICAgICB9CiAgICAgICAgICB9LCB7CiAgICAgICAgICAgICJkZXRhaWwiOiAiRG9lc24ndCBsb29rIGxpa2UgYSB2YWxpZCBlbWFpbC4iLAogICAgICAgICAgICAic291cmNlIjogewogICAgICAgICAgICAgICJwb2ludGVyIjogImRhdGEvYXR0cmlidXRlcy9lbWFpbCIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIF0KICAgICAgfQogICAgICBgYGAKICAgICAgIFRoZSBrZXkgYGRldGFpbGAgcHJvdmlkZXMgYSB0ZXh0dWFsIGRlc2NyaXB0aW9uIG9mIHRoZSBwcm9ibGVtLgogICAgICBBbHRlcm5hdGl2ZWx5LCB0aGUga2V5IGB0aXRsZWAgY2FuIGJlIHVzZWQgZm9yIHRoZSBzYW1lIHB1cnBvc2UuCiAgICAgICBUaGUgbmVzdGVkIGtleXMgYHNvdXJjZS5wb2ludGVyYCBkZXRhaWwgd2hpY2ggc3BlY2lmaWMgZWxlbWVudAogICAgICBvZiB0aGUgcmVxdWVzdCBkYXRhIHdhcyBpbnZhbGlkLgogICAgICAgTm90ZSB0aGF0IEpTT04tQVBJIGFsc28gYWxsb3dzIGZvciBvYmplY3QtbGV2ZWwgZXJyb3JzIHRvIGJlIHBsYWNlZAogICAgICBpbiBhbiBvYmplY3Qgd2l0aCBwb2ludGVyIGBkYXRhYCwgc2lnbmlmeWluZyB0aGF0IHRoZSBwcm9ibGVtCiAgICAgIGNhbm5vdCBiZSB0cmFjZWQgdG8gYSBzcGVjaWZpYyBhdHRyaWJ1dGU6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHsKICAgICAgICAiZXJyb3JzIjogWwogICAgICAgICAgewogICAgICAgICAgICAiZGV0YWlsIjogIlNvbWUgZ2VuZXJpYyBub24gcHJvcGVydHkgZXJyb3IgbWVzc2FnZSIsCiAgICAgICAgICAgICJzb3VyY2UiOiB7CiAgICAgICAgICAgICAgInBvaW50ZXIiOiAiZGF0YSIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIF0KICAgICAgfQogICAgICBgYGAKICAgICAgIFdoZW4gdHVybiBpbnRvIGEgYEVycm9yc2Agb2JqZWN0LCB5b3UgY2FuIHJlYWQgdGhlc2UgZXJyb3JzCiAgICAgIHRocm91Z2ggdGhlIHByb3BlcnR5IGBiYXNlYDoKICAgICAgIGBgYGhhbmRsZWJhcnMKICAgICAge3sjZWFjaCBtb2RlbC5lcnJvcnMuYmFzZSBhcyB8ZXJyb3J8fX0KICAgICAgICA8ZGl2IGNsYXNzPSJlcnJvciI+CiAgICAgICAgICB7e2Vycm9yLm1lc3NhZ2V9fQogICAgICAgIDwvZGl2PgogICAgICB7ey9lYWNofX0KICAgICAgYGBgCiAgICAgICBFeGFtcGxlIG9mIGFsdGVybmF0aXZlIGltcGxlbWVudGF0aW9uLCBvdmVycmlkaW5nIHRoZSBkZWZhdWx0CiAgICAgIGJlaGF2aW9yIHRvIGRlYWwgd2l0aCBhIGRpZmZlcmVudCBmb3JtYXQgb2YgZXJyb3JzOgogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL3Bvc3QuanMKICAgICAgaW1wb3J0IERTIGZyb20gJ2VtYmVyLWRhdGEnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBleHRyYWN0RXJyb3JzKHN0b3JlLCB0eXBlQ2xhc3MsIHBheWxvYWQsIGlkKSB7CiAgICAgICAgICBpZiAocGF5bG9hZCAmJiB0eXBlb2YgcGF5bG9hZCA9PT0gJ29iamVjdCcgJiYgcGF5bG9hZC5fcHJvYmxlbXMpIHsKICAgICAgICAgICAgcGF5bG9hZCA9IHBheWxvYWQuX3Byb2JsZW1zOwogICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZUVycm9ycyh0eXBlQ2xhc3MsIHBheWxvYWQpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHBheWxvYWQ7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGV4dHJhY3RFcnJvcnMKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtNb2RlbH0gdHlwZUNsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEBwYXJhbSB7KFN0cmluZ3xOdW1iZXIpfSBpZAogICAgICBAcmV0dXJuIHtPYmplY3R9IGpzb24gVGhlIGRlc2VyaWFsaXplZCBlcnJvcnMKICAgICovCiAgICBleHRyYWN0RXJyb3JzOiBmdW5jdGlvbiBleHRyYWN0RXJyb3JzKHN0b3JlLCB0eXBlQ2xhc3MsIHBheWxvYWQsIGlkKSB7CiAgICAgIHZhciBfdGhpczYgPSB0aGlzOwoKICAgICAgaWYgKHBheWxvYWQgJiYgdHlwZW9mIHBheWxvYWQgPT09ICdvYmplY3QnICYmIHBheWxvYWQuZXJyb3JzKSB7CiAgICAgICAgcGF5bG9hZCA9ICgwLCBfcHJpdmF0ZS5lcnJvcnNBcnJheVRvSGFzaCkocGF5bG9hZC5lcnJvcnMpOwogICAgICAgIHRoaXMubm9ybWFsaXplVXNpbmdEZWNsYXJlZE1hcHBpbmcodHlwZUNsYXNzLCBwYXlsb2FkKTsKICAgICAgICB0eXBlQ2xhc3MuZWFjaEF0dHJpYnV0ZShmdW5jdGlvbiAobmFtZSkgewogICAgICAgICAgdmFyIGtleSA9IF90aGlzNi5rZXlGb3JBdHRyaWJ1dGUobmFtZSwgJ2Rlc2VyaWFsaXplJyk7CgogICAgICAgICAgaWYgKGtleSAhPT0gbmFtZSAmJiBwYXlsb2FkW2tleV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBwYXlsb2FkW25hbWVdID0gcGF5bG9hZFtrZXldOwogICAgICAgICAgICBkZWxldGUgcGF5bG9hZFtrZXldOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgIHR5cGVDbGFzcy5lYWNoUmVsYXRpb25zaGlwKGZ1bmN0aW9uIChuYW1lKSB7CiAgICAgICAgICB2YXIga2V5ID0gX3RoaXM2LmtleUZvclJlbGF0aW9uc2hpcChuYW1lLCAnZGVzZXJpYWxpemUnKTsKCiAgICAgICAgICBpZiAoa2V5ICE9PSBuYW1lICYmIHBheWxvYWRba2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHBheWxvYWRbbmFtZV0gPSBwYXlsb2FkW2tleV07CiAgICAgICAgICAgIGRlbGV0ZSBwYXlsb2FkW2tleV07CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBwYXlsb2FkOwogICAgfSwKCiAgICAvKioKICAgICAgYGtleUZvckF0dHJpYnV0ZWAgY2FuIGJlIHVzZWQgdG8gZGVmaW5lIHJ1bGVzIGZvciBob3cgdG8gY29udmVydCBhbgogICAgICBhdHRyaWJ1dGUgbmFtZSBpbiB5b3VyIG1vZGVsIHRvIGEga2V5IGluIHlvdXIgSlNPTi4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9zZXJpYWxpemVycy9hcHBsaWNhdGlvbi5qcwogICAgICBpbXBvcnQgSlNPTlNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uJzsKICAgICAgaW1wb3J0IHsgdW5kZXJzY29yZSB9IGZyb20gJ0BlbWJlci9zdHJpbmcnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTlNlcmlhbGl6ZXIuZXh0ZW5kKHsKICAgICAgICBrZXlGb3JBdHRyaWJ1dGUoYXR0ciwgbWV0aG9kKSB7CiAgICAgICAgICByZXR1cm4gdW5kZXJzY29yZShhdHRyKS50b1VwcGVyQ2FzZSgpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBrZXlGb3JBdHRyaWJ1dGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleQogICAgICBAcGFyYW0ge1N0cmluZ30gbWV0aG9kCiAgICAgIEByZXR1cm4ge1N0cmluZ30gbm9ybWFsaXplZCBrZXkKICAgICovCiAgICBrZXlGb3JBdHRyaWJ1dGU6IGZ1bmN0aW9uIGtleUZvckF0dHJpYnV0ZShrZXksIG1ldGhvZCkgewogICAgICByZXR1cm4ga2V5OwogICAgfSwKCiAgICAvKioKICAgICAgYGtleUZvclJlbGF0aW9uc2hpcGAgY2FuIGJlIHVzZWQgdG8gZGVmaW5lIGEgY3VzdG9tIGtleSB3aGVuCiAgICAgIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHJlbGF0aW9uc2hpcCBwcm9wZXJ0aWVzLiBCeSBkZWZhdWx0CiAgICAgIGBKU09OU2VyaWFsaXplcmAgZG9lcyBub3QgcHJvdmlkZSBhbiBpbXBsZW1lbnRhdGlvbiBvZiB0aGlzIG1ldGhvZC4KICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL3Bvc3QuanMKICAgICAgICBpbXBvcnQgSlNPTlNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uJzsKICAgICAgICBpbXBvcnQgeyB1bmRlcnNjb3JlIH0gZnJvbSAnQGVtYmVyL3N0cmluZyc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05TZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgICBrZXlGb3JSZWxhdGlvbnNoaXAoa2V5LCByZWxhdGlvbnNoaXAsIG1ldGhvZCkgewogICAgICAgICAgICByZXR1cm4gYHJlbF8ke3VuZGVyc2NvcmUoa2V5KX1gOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgIGBgYAogICAgICAgQG1ldGhvZCBrZXlGb3JSZWxhdGlvbnNoaXAKICAgICAgQHBhcmFtIHtTdHJpbmd9IGtleQogICAgICBAcGFyYW0ge1N0cmluZ30gdHlwZUNsYXNzCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QKICAgICAgQHJldHVybiB7U3RyaW5nfSBub3JtYWxpemVkIGtleQogICAgKi8KICAgIGtleUZvclJlbGF0aW9uc2hpcDogZnVuY3Rpb24ga2V5Rm9yUmVsYXRpb25zaGlwKGtleSwgdHlwZUNsYXNzLCBtZXRob2QpIHsKICAgICAgcmV0dXJuIGtleTsKICAgIH0sCgogICAgLyoqCiAgICAgYGtleUZvckxpbmtgIGNhbiBiZSB1c2VkIHRvIGRlZmluZSBhIGN1c3RvbSBrZXkgd2hlbiBkZXNlcmlhbGl6aW5nIGxpbmsKICAgICBwcm9wZXJ0aWVzLgogICAgICBAbWV0aG9kIGtleUZvckxpbmsKICAgICBAcGFyYW0ge1N0cmluZ30ga2V5CiAgICAgQHBhcmFtIHtTdHJpbmd9IGtpbmQgYGJlbG9uZ3NUb2Agb3IgYGhhc01hbnlgCiAgICAgQHJldHVybiB7U3RyaW5nfSBub3JtYWxpemVkIGtleQogICAgKi8KICAgIGtleUZvckxpbms6IGZ1bmN0aW9uIGtleUZvckxpbmsoa2V5LCBraW5kKSB7CiAgICAgIHJldHVybiBrZXk7CiAgICB9LAogICAgLy8gSEVMUEVSUwoKICAgIC8qKgogICAgIEBtZXRob2QgdHJhbnNmb3JtRm9yCiAgICAgQHByaXZhdGUKICAgICBAcGFyYW0ge1N0cmluZ30gYXR0cmlidXRlVHlwZQogICAgIEBwYXJhbSB7Qm9vbGVhbn0gc2tpcEFzc2VydGlvbgogICAgIEByZXR1cm4ge1RyYW5zZm9ybX0gdHJhbnNmb3JtCiAgICAqLwogICAgdHJhbnNmb3JtRm9yOiBmdW5jdGlvbiB0cmFuc2Zvcm1Gb3IoYXR0cmlidXRlVHlwZSwgc2tpcEFzc2VydGlvbikgewogICAgICB2YXIgdHJhbnNmb3JtID0gRW1iZXIuZ2V0T3duZXIodGhpcykubG9va3VwKCd0cmFuc2Zvcm06JyArIGF0dHJpYnV0ZVR5cGUpOwogICAgICAoZmFsc2UgJiYgIShza2lwQXNzZXJ0aW9uIHx8ICEhdHJhbnNmb3JtKSAmJiBFbWJlci5hc3NlcnQoIlVuYWJsZSB0byBmaW5kIHRoZSB0cmFuc2Zvcm0gZm9yIGBhdHRyKCciICsgYXR0cmlidXRlVHlwZSArICInKWAiLCBza2lwQXNzZXJ0aW9uIHx8ICEhdHJhbnNmb3JtKSk7CiAgICAgIHJldHVybiB0cmFuc2Zvcm07CiAgICB9CiAgfSk7CgogIHZhciBfZGVmYXVsdCA9IEpTT05TZXJpYWxpemVyOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CjtkZWZpbmUoIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCIsIFsiZXhwb3J0cyIsICJlbWJlci1pbmZsZWN0b3IiLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uIiwgIkBlbWJlci1kYXRhL3N0b3JlLy1wcml2YXRlIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvLXByaXZhdGUiLCAiQGVtYmVyLWRhdGEvc3RvcmUiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfZW1iZXJJbmZsZWN0b3IsIF9qc29uLCBfcHJpdmF0ZSwgX3ByaXZhdGUyLCBfc3RvcmUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkVtYmVkZGVkUmVjb3Jkc01peGluIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUyLkVtYmVkZGVkUmVjb3Jkc01peGluOwogICAgfQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIC8qKgogICAgTm9ybWFsbHksIGFwcGxpY2F0aW9ucyB3aWxsIHVzZSB0aGUgYFJFU1RTZXJpYWxpemVyYCBieSBpbXBsZW1lbnRpbmcKICAgIHRoZSBgbm9ybWFsaXplYCBtZXRob2QuCiAgCiAgICBUaGlzIGFsbG93cyB5b3UgdG8gZG8gd2hhdGV2ZXIga2luZCBvZiBtdW5naW5nIHlvdSBuZWVkIGFuZCBpcwogICAgZXNwZWNpYWxseSB1c2VmdWwgaWYgeW91ciBzZXJ2ZXIgaXMgaW5jb25zaXN0ZW50IGFuZCB5b3UgbmVlZCB0bwogICAgZG8gbXVuZ2luZyBkaWZmZXJlbnRseSBmb3IgbWFueSBkaWZmZXJlbnQga2luZHMgb2YgcmVzcG9uc2VzLgogIAogICAgU2VlIHRoZSBgbm9ybWFsaXplYCBkb2N1bWVudGF0aW9uIGZvciBtb3JlIGluZm9ybWF0aW9uLgogIAogICAgIyMgQWNyb3NzIHRoZSBCb2FyZCBOb3JtYWxpemF0aW9uCiAgCiAgICBUaGVyZSBhcmUgYWxzbyBhIG51bWJlciBvZiBob29rcyB0aGF0IHlvdSBtaWdodCBmaW5kIHVzZWZ1bCB0byBkZWZpbmUKICAgIGFjcm9zcy10aGUtYm9hcmQgcnVsZXMgZm9yIHlvdXIgcGF5bG9hZC4gVGhlc2UgcnVsZXMgd2lsbCBiZSB1c2VmdWwKICAgIGlmIHlvdXIgc2VydmVyIGlzIGNvbnNpc3RlbnQsIG9yIGlmIHlvdSdyZSBidWlsZGluZyBhbiBhZGFwdGVyIGZvcgogICAgYW4gaW5mcmFzdHJ1Y3R1cmUgc2VydmljZSwgbGlrZSBGaXJlYmFzZSwgYW5kIHdhbnQgdG8gZW5jb2RlIHNlcnZpY2UKICAgIGNvbnZlbnRpb25zLgogIAogICAgRm9yIGV4YW1wbGUsIGlmIGFsbCBvZiB5b3VyIGtleXMgYXJlIHVuZGVyc2NvcmVkIGFuZCBhbGwtY2FwcywgYnV0CiAgICBvdGhlcndpc2UgY29uc2lzdGVudCB3aXRoIHRoZSBuYW1lcyB5b3UgdXNlIGluIHlvdXIgbW9kZWxzLCB5b3UKICAgIGNhbiBpbXBsZW1lbnQgYWNyb3NzLXRoZS1ib2FyZCBydWxlcyBmb3IgaG93IHRvIGNvbnZlcnQgYW4gYXR0cmlidXRlCiAgICBuYW1lIGluIHlvdXIgbW9kZWwgdG8gYSBrZXkgaW4geW91ciBKU09OLgogIAogICAgYGBgYXBwL3NlcmlhbGl6ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKICAgIGltcG9ydCB7IHVuZGVyc2NvcmUgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAKICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgIGtleUZvckF0dHJpYnV0ZShhdHRyLCBtZXRob2QpIHsKICAgICAgICByZXR1cm4gdW5kZXJzY29yZShhdHRyKS50b1VwcGVyQ2FzZSgpOwogICAgICB9CiAgICB9KTsKICAgIGBgYAogIAogICAgWW91IGNhbiBhbHNvIGltcGxlbWVudCBga2V5Rm9yUmVsYXRpb25zaGlwYCwgd2hpY2ggdGFrZXMgdGhlIG5hbWUKICAgIG9mIHRoZSByZWxhdGlvbnNoaXAgYXMgdGhlIGZpcnN0IHBhcmFtZXRlciwgdGhlIGtpbmQgb2YKICAgIHJlbGF0aW9uc2hpcCAoYGhhc01hbnlgIG9yIGBiZWxvbmdzVG9gKSBhcyB0aGUgc2Vjb25kIHBhcmFtZXRlciwgYW5kCiAgICB0aGUgbWV0aG9kIChgc2VyaWFsaXplYCBvciBgZGVzZXJpYWxpemVgKSBhcyB0aGUgdGhpcmQgcGFyYW1ldGVyLgogIAogICAgQGNsYXNzIFJFU1RTZXJpYWxpemVyCiAgICBAZXh0ZW5kcyBKU09OU2VyaWFsaXplcgogICovCiAgdmFyIFJFU1RTZXJpYWxpemVyID0gX2pzb24uZGVmYXVsdC5leHRlbmQoewogICAgLyoqCiAgICAgYGtleUZvclBvbHltb3JwaGljVHlwZWAgY2FuIGJlIHVzZWQgdG8gZGVmaW5lIGEgY3VzdG9tIGtleSB3aGVuCiAgICAgc2VyaWFsaXppbmcgYW5kIGRlc2VyaWFsaXppbmcgYSBwb2x5bW9ycGhpYyB0eXBlLiBCeSBkZWZhdWx0LCB0aGUKICAgICByZXR1cm5lZCBrZXkgaXMgYCR7a2V5fVR5cGVgLgogICAgICBFeGFtcGxlCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAga2V5Rm9yUG9seW1vcnBoaWNUeXBlKGtleSwgcmVsYXRpb25zaGlwKSB7CiAgICAgICAgICB2YXIgcmVsYXRpb25zaGlwS2V5ID0gdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXAoa2V5KTsKICAgICAgICAgICByZXR1cm4gJ3R5cGUtJyArIHJlbGF0aW9uc2hpcEtleTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgQG1ldGhvZCBrZXlGb3JQb2x5bW9ycGhpY1R5cGUKICAgICBAcGFyYW0ge1N0cmluZ30ga2V5CiAgICAgQHBhcmFtIHtTdHJpbmd9IHR5cGVDbGFzcwogICAgIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QKICAgICBAcmV0dXJuIHtTdHJpbmd9IG5vcm1hbGl6ZWQga2V5CiAgICAqLwogICAga2V5Rm9yUG9seW1vcnBoaWNUeXBlOiBmdW5jdGlvbiBrZXlGb3JQb2x5bW9ycGhpY1R5cGUoa2V5LCB0eXBlQ2xhc3MsIG1ldGhvZCkgewogICAgICB2YXIgcmVsYXRpb25zaGlwS2V5ID0gdGhpcy5rZXlGb3JSZWxhdGlvbnNoaXAoa2V5KTsKICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcEtleSArICJUeXBlIjsKICAgIH0sCgogICAgLyoqCiAgICAgIE5vcm1hbGl6ZXMgYSBwYXJ0IG9mIHRoZSBKU09OIHBheWxvYWQgcmV0dXJuZWQgYnkKICAgICAgdGhlIHNlcnZlci4gWW91IHNob3VsZCBvdmVycmlkZSB0aGlzIG1ldGhvZCwgbXVuZ2UgdGhlIGhhc2gKICAgICAgYW5kIGNhbGwgc3VwZXIgaWYgeW91IGhhdmUgZ2VuZXJpYyBub3JtYWxpemF0aW9uIHRvIGRvLgogICAgICAgSXQgdGFrZXMgdGhlIHR5cGUgb2YgdGhlIHJlY29yZCB0aGF0IGlzIGJlaW5nIG5vcm1hbGl6ZWQKICAgICAgKGFzIGEgTW9kZWwgY2xhc3MpLCB0aGUgcHJvcGVydHkgd2hlcmUgdGhlIGhhc2ggd2FzCiAgICAgIG9yaWdpbmFsbHkgZm91bmQsIGFuZCB0aGUgaGFzaCB0byBub3JtYWxpemUuCiAgICAgICBGb3IgZXhhbXBsZSwgaWYgeW91IGhhdmUgYSBwYXlsb2FkIHRoYXQgbG9va3MgbGlrZSB0aGlzOgogICAgICAgYGBganMKICAgICAgewogICAgICAgICJwb3N0IjogewogICAgICAgICAgImlkIjogMSwKICAgICAgICAgICJ0aXRsZSI6ICJSYWlscyBpcyBvbWFrYXNlIiwKICAgICAgICAgICJjb21tZW50cyI6IFsgMSwgMiBdCiAgICAgICAgfSwKICAgICAgICAiY29tbWVudHMiOiBbewogICAgICAgICAgImlkIjogMSwKICAgICAgICAgICJib2R5IjogIkZJUlNUIgogICAgICAgIH0sIHsKICAgICAgICAgICJpZCI6IDIsCiAgICAgICAgICAiYm9keSI6ICJSYWlscyBpcyB1bmFnaSIKICAgICAgICB9XQogICAgICB9CiAgICAgIGBgYAogICAgICAgVGhlIGBub3JtYWxpemVgIG1ldGhvZCB3aWxsIGJlIGNhbGxlZCB0aHJlZSB0aW1lczoKICAgICAgICogV2l0aCBgQXBwLlBvc3RgLCBgInBvc3RzImAgYW5kIGB7IGlkOiAxLCB0aXRsZTogIlJhaWxzIGlzIG9tYWthc2UiLCAuLi4gfWAKICAgICAgKiBXaXRoIGBBcHAuQ29tbWVudGAsIGAiY29tbWVudHMiYCBhbmQgYHsgaWQ6IDEsIGJvZHk6ICJGSVJTVCIgfWAKICAgICAgKiBXaXRoIGBBcHAuQ29tbWVudGAsIGAiY29tbWVudHMiYCBhbmQgYHsgaWQ6IDIsIGJvZHk6ICJSYWlscyBpcyB1bmFnaSIgfWAKICAgICAgIFlvdSBjYW4gdXNlIHRoaXMgbWV0aG9kLCBmb3IgZXhhbXBsZSwgdG8gbm9ybWFsaXplIHVuZGVyc2NvcmVkIGtleXMgdG8gY2FtZWxpemVkCiAgICAgIG9yIG90aGVyIGdlbmVyYWwtcHVycG9zZSBub3JtYWxpemF0aW9ucy4gWW91IHdpbGwgb25seSBuZWVkIHRvIGltcGxlbWVudAogICAgICBgbm9ybWFsaXplYCBhbmQgbWFuaXB1bGF0ZSB0aGUgcGF5bG9hZCBhcyBkZXNpcmVkLgogICAgICAgRm9yIGV4YW1wbGUsIGlmIHRoZSBgSURzYCB1bmRlciBgImNvbW1lbnRzImAgYXJlIHByb3ZpZGVkIGFzIGBfaWRgIGluc3RlYWQgb2YKICAgICAgYGlkYCwgeW91IGNhbiBzcGVjaWZ5IGhvdyB0byBub3JtYWxpemUganVzdCB0aGUgY29tbWVudHM6CiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgbm9ybWFsaXplKG1vZGVsLCBoYXNoLCBwcm9wKSB7CiAgICAgICAgICBpZiAocHJvcCA9PT0gJ2NvbW1lbnRzJykgewogICAgICAgICAgICBoYXNoLmlkID0gaGFzaC5faWQ7CiAgICAgICAgICAgIGRlbGV0ZSBoYXNoLl9pZDsKICAgICAgICAgIH0KICAgICAgICAgICByZXR1cm4gdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIE9uIGVhY2ggY2FsbCB0byB0aGUgYG5vcm1hbGl6ZWAgbWV0aG9kLCB0aGUgdGhpcmQgcGFyYW1ldGVyIChgcHJvcGApIGlzIGFsd2F5cwogICAgICBvbmUgb2YgdGhlIGtleXMgdGhhdCB3ZXJlIGluIHRoZSBvcmlnaW5hbCBwYXlsb2FkIG9yIGluIHRoZSByZXN1bHQgb2YgYW5vdGhlcgogICAgICBub3JtYWxpemF0aW9uIGFzIGBub3JtYWxpemVSZXNwb25zZWAuCiAgICAgICBAbWV0aG9kIG5vcm1hbGl6ZQogICAgICBAcGFyYW0ge01vZGVsfSBtb2RlbENsYXNzCiAgICAgIEBwYXJhbSB7T2JqZWN0fSByZXNvdXJjZUhhc2gKICAgICAgQHBhcmFtIHtTdHJpbmd9IHByb3AKICAgICAgQHJldHVybiB7T2JqZWN0fQogICAgKi8KCiAgICAvKioKICAgICAgTm9ybWFsaXplcyBhbiBhcnJheSBvZiByZXNvdXJjZSBwYXlsb2FkcyBhbmQgcmV0dXJucyBhIEpTT04tQVBJIERvY3VtZW50CiAgICAgIHdpdGggcHJpbWFyeSBkYXRhIGFuZCwgaWYgYW55LCBpbmNsdWRlZCBkYXRhIGFzIGB7IGRhdGEsIGluY2x1ZGVkIH1gLgogICAgICAgQG1ldGhvZCBfbm9ybWFsaXplQXJyYXkKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0ge09iamVjdH0gYXJyYXlIYXNoCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBwcm9wCiAgICAgIEByZXR1cm4ge09iamVjdH0KICAgICAgQHByaXZhdGUKICAgICovCiAgICBfbm9ybWFsaXplQXJyYXk6IGZ1bmN0aW9uIF9ub3JtYWxpemVBcnJheShzdG9yZSwgbW9kZWxOYW1lLCBhcnJheUhhc2gsIHByb3ApIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHZhciBkb2N1bWVudEhhc2ggPSB7CiAgICAgICAgZGF0YTogW10sCiAgICAgICAgaW5jbHVkZWQ6IFtdCiAgICAgIH07CiAgICAgIHZhciBtb2RlbENsYXNzID0gc3RvcmUubW9kZWxGb3IobW9kZWxOYW1lKTsKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBzdG9yZS5zZXJpYWxpemVyRm9yKG1vZGVsTmFtZSk7CiAgICAgIEVtYmVyLm1ha2VBcnJheShhcnJheUhhc2gpLmZvckVhY2goZnVuY3Rpb24gKGhhc2gpIHsKICAgICAgICB2YXIgX3RoaXMkX25vcm1hbGl6ZVBvbHltID0gX3RoaXMuX25vcm1hbGl6ZVBvbHltb3JwaGljUmVjb3JkKHN0b3JlLCBoYXNoLCBwcm9wLCBtb2RlbENsYXNzLCBzZXJpYWxpemVyKSwKICAgICAgICAgICAgZGF0YSA9IF90aGlzJF9ub3JtYWxpemVQb2x5bS5kYXRhLAogICAgICAgICAgICBpbmNsdWRlZCA9IF90aGlzJF9ub3JtYWxpemVQb2x5bS5pbmNsdWRlZDsKCiAgICAgICAgZG9jdW1lbnRIYXNoLmRhdGEucHVzaChkYXRhKTsKCiAgICAgICAgaWYgKGluY2x1ZGVkKSB7CiAgICAgICAgICB2YXIgX2RvY3VtZW50SGFzaCRpbmNsdWRlOwoKICAgICAgICAgIChfZG9jdW1lbnRIYXNoJGluY2x1ZGUgPSBkb2N1bWVudEhhc2guaW5jbHVkZWQpLnB1c2guYXBwbHkoX2RvY3VtZW50SGFzaCRpbmNsdWRlLCBpbmNsdWRlZCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgcmV0dXJuIGRvY3VtZW50SGFzaDsKICAgIH0sCiAgICBfbm9ybWFsaXplUG9seW1vcnBoaWNSZWNvcmQ6IGZ1bmN0aW9uIF9ub3JtYWxpemVQb2x5bW9ycGhpY1JlY29yZChzdG9yZSwgaGFzaCwgcHJvcCwgcHJpbWFyeU1vZGVsQ2xhc3MsIHByaW1hcnlTZXJpYWxpemVyKSB7CiAgICAgIHZhciBzZXJpYWxpemVyID0gcHJpbWFyeVNlcmlhbGl6ZXI7CiAgICAgIHZhciBtb2RlbENsYXNzID0gcHJpbWFyeU1vZGVsQ2xhc3M7CiAgICAgIHZhciBwcmltYXJ5SGFzVHlwZUF0dHJpYnV0ZSA9ICgwLCBfcHJpdmF0ZTIubW9kZWxIYXNBdHRyaWJ1dGVPclJlbGF0aW9uc2hpcE5hbWVkVHlwZSkocHJpbWFyeU1vZGVsQ2xhc3MpOwoKICAgICAgaWYgKCFwcmltYXJ5SGFzVHlwZUF0dHJpYnV0ZSAmJiBoYXNoLnR5cGUpIHsKICAgICAgICAvLyBTdXBwb3J0IHBvbHltb3JwaGljIHJlY29yZHMgaW4gYXN5bmMgcmVsYXRpb25zaGlwcwogICAgICAgIHZhciBtb2RlbE5hbWUgPSB0aGlzLm1vZGVsTmFtZUZyb21QYXlsb2FkS2V5KGhhc2gudHlwZSk7CgogICAgICAgIGlmIChzdG9yZS5faGFzTW9kZWxGb3IobW9kZWxOYW1lKSkgewogICAgICAgICAgc2VyaWFsaXplciA9IHN0b3JlLnNlcmlhbGl6ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgICAgIG1vZGVsQ2xhc3MgPSBzdG9yZS5tb2RlbEZvcihtb2RlbE5hbWUpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHNlcmlhbGl6ZXIubm9ybWFsaXplKG1vZGVsQ2xhc3MsIGhhc2gsIHByb3ApOwogICAgfSwKCiAgICAvKgogICAgICBAbWV0aG9kIF9ub3JtYWxpemVSZXNwb25zZQogICAgICBAcGFyYW0ge1N0b3JlfSBzdG9yZQogICAgICBAcGFyYW0ge01vZGVsfSBwcmltYXJ5TW9kZWxDbGFzcwogICAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgICBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGlkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VHlwZQogICAgICBAcGFyYW0ge0Jvb2xlYW59IGlzU2luZ2xlCiAgICAgIEByZXR1cm4ge09iamVjdH0gSlNPTi1BUEkgRG9jdW1lbnQKICAgICAgQHByaXZhdGUKICAgICovCiAgICBfbm9ybWFsaXplUmVzcG9uc2U6IGZ1bmN0aW9uIF9ub3JtYWxpemVSZXNwb25zZShzdG9yZSwgcHJpbWFyeU1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSwgaXNTaW5nbGUpIHsKICAgICAgdmFyIGRvY3VtZW50SGFzaCA9IHsKICAgICAgICBkYXRhOiBudWxsLAogICAgICAgIGluY2x1ZGVkOiBbXQogICAgICB9OwogICAgICB2YXIgbWV0YSA9IHRoaXMuZXh0cmFjdE1ldGEoc3RvcmUsIHByaW1hcnlNb2RlbENsYXNzLCBwYXlsb2FkKTsKCiAgICAgIGlmIChtZXRhKSB7CiAgICAgICAgKGZhbHNlICYmICEoRW1iZXIudHlwZU9mKG1ldGEpID09PSAnb2JqZWN0JykgJiYgRW1iZXIuYXNzZXJ0KCdUaGUgYG1ldGFgIHJldHVybmVkIGZyb20gYGV4dHJhY3RNZXRhYCBoYXMgdG8gYmUgYW4gb2JqZWN0LCBub3QgIicgKyBFbWJlci50eXBlT2YobWV0YSkgKyAnIi4nLCBFbWJlci50eXBlT2YobWV0YSkgPT09ICdvYmplY3QnKSk7CiAgICAgICAgZG9jdW1lbnRIYXNoLm1ldGEgPSBtZXRhOwogICAgICB9CgogICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHBheWxvYWQpOwoKICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgcHJvcCA9IGtleXNbaV07CiAgICAgICAgdmFyIG1vZGVsTmFtZSA9IHByb3A7CiAgICAgICAgdmFyIGZvcmNlZFNlY29uZGFyeSA9IGZhbHNlOwogICAgICAgIC8qCiAgICAgICAgICBJZiB5b3Ugd2FudCB0byBwcm92aWRlIHNpZGVsb2FkZWQgcmVjb3JkcyBvZiB0aGUgc2FtZSB0eXBlIHRoYXQgdGhlCiAgICAgICAgICBwcmltYXJ5IGRhdGEgeW91IGNhbiBkbyB0aGF0IGJ5IHByZWZpeGluZyB0aGUga2V5IHdpdGggYF9gLgogICAgICAgICAgIEV4YW1wbGUKICAgICAgICAgICBgYGAKICAgICAgICAgIHsKICAgICAgICAgICAgdXNlcnM6IFsKICAgICAgICAgICAgICB7IGlkOiAxLCB0aXRsZTogJ1RvbScsIG1hbmFnZXI6IDMgfSwKICAgICAgICAgICAgICB7IGlkOiAyLCB0aXRsZTogJ1llaHVkYScsIG1hbmFnZXI6IDMgfQogICAgICAgICAgICBdLAogICAgICAgICAgICBfdXNlcnM6IFsKICAgICAgICAgICAgICB7IGlkOiAzLCB0aXRsZTogJ1RvbXN0ZXInIH0KICAgICAgICAgICAgXQogICAgICAgICAgfQogICAgICAgICAgYGBgCiAgICAgICAgICAgVGhpcyBmb3JjZXMgYF91c2Vyc2AgdG8gYmUgYWRkZWQgdG8gYGluY2x1ZGVkYCBpbnN0ZWFkIG9mIGBkYXRhYC4KICAgICAgICAgKi8KCiAgICAgICAgaWYgKHByb3AuY2hhckF0KDApID09PSAnXycpIHsKICAgICAgICAgIGZvcmNlZFNlY29uZGFyeSA9IHRydWU7CiAgICAgICAgICBtb2RlbE5hbWUgPSBwcm9wLnN1YnN0cigxKTsKICAgICAgICB9CgogICAgICAgIHZhciB0eXBlTmFtZSA9IHRoaXMubW9kZWxOYW1lRnJvbVBheWxvYWRLZXkobW9kZWxOYW1lKTsKCiAgICAgICAgaWYgKCFzdG9yZS5faGFzTW9kZWxGb3IodHlwZU5hbWUpKSB7CiAgICAgICAgICAoZmFsc2UgJiYgRW1iZXIud2Fybih0aGlzLndhcm5NZXNzYWdlTm9Nb2RlbEZvcktleShtb2RlbE5hbWUsIHR5cGVOYW1lKSwgZmFsc2UsIHsKICAgICAgICAgICAgaWQ6ICdkcy5zZXJpYWxpemVyLm1vZGVsLWZvci1rZXktbWlzc2luZycKICAgICAgICAgIH0pKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KCiAgICAgICAgdmFyIGlzUHJpbWFyeSA9ICFmb3JjZWRTZWNvbmRhcnkgJiYgdGhpcy5pc1ByaW1hcnlUeXBlKHN0b3JlLCB0eXBlTmFtZSwgcHJpbWFyeU1vZGVsQ2xhc3MpOwogICAgICAgIHZhciB2YWx1ZSA9IHBheWxvYWRbcHJvcF07CgogICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICBpZiAoZmFsc2UKICAgICAgICAvKiBERUJVRyAqLwogICAgICAgICkgewogICAgICAgICAgdmFyIGlzUXVlcnlSZWNvcmRBbkFycmF5ID0gcmVxdWVzdFR5cGUgPT09ICdxdWVyeVJlY29yZCcgJiYgaXNQcmltYXJ5ICYmIEFycmF5LmlzQXJyYXkodmFsdWUpOwogICAgICAgICAgdmFyIG1lc3NhZ2UgPSAnVGhlIGFkYXB0ZXIgcmV0dXJuZWQgYW4gYXJyYXkgZm9yIHRoZSBwcmltYXJ5IGRhdGEgb2YgYSBgcXVlcnlSZWNvcmRgIHJlc3BvbnNlLiBUaGlzIGlzIGRlcHJlY2F0ZWQgYXMgYHF1ZXJ5UmVjb3JkYCBzaG91bGQgcmV0dXJuIGEgc2luZ2xlIHJlY29yZC4nOwogICAgICAgICAgKGZhbHNlICYmICEoIWlzUXVlcnlSZWNvcmRBbkFycmF5KSAmJiBFbWJlci5kZXByZWNhdGUobWVzc2FnZSwgIWlzUXVlcnlSZWNvcmRBbkFycmF5LCB7CiAgICAgICAgICAgIGlkOiAnZHMuc2VyaWFsaXplci5yZXN0LnF1ZXJ5UmVjb3JkLWFycmF5LXJlc3BvbnNlJywKICAgICAgICAgICAgdW50aWw6ICczLjAnLAogICAgICAgICAgICB1cmw6ICdodHRwczovL2RlcHJlY2F0aW9ucy5lbWJlcmpzLmNvbS9lbWJlci1kYXRhL3YyLngvI3RvY19zdG9yZS1xdWVyeXJlY29yZC1hcnJheS1yZXNwb25zZS13aXRoLXJlc3RzZXJpYWxpemVyJwogICAgICAgICAgfSkpOwogICAgICAgIH0KICAgICAgICAvKgogICAgICAgICAgU3VwcG9ydCBwcmltYXJ5IGRhdGEgYXMgYW4gb2JqZWN0IGluc3RlYWQgb2YgYW4gYXJyYXkuCiAgICAgICAgICAgRXhhbXBsZQogICAgICAgICAgIGBgYAogICAgICAgICAgewogICAgICAgICAgICB1c2VyOiB7IGlkOiAxLCB0aXRsZTogJ1RvbScsIG1hbmFnZXI6IDMgfQogICAgICAgICAgfQogICAgICAgICAgYGBgCiAgICAgICAgICovCgoKICAgICAgICBpZiAoaXNQcmltYXJ5ICYmICFBcnJheS5pc0FycmF5KHZhbHVlKSkgewogICAgICAgICAgdmFyIF90aGlzJF9ub3JtYWxpemVQb2x5bTIgPSB0aGlzLl9ub3JtYWxpemVQb2x5bW9ycGhpY1JlY29yZChzdG9yZSwgdmFsdWUsIHByb3AsIHByaW1hcnlNb2RlbENsYXNzLCB0aGlzKSwKICAgICAgICAgICAgICBfZGF0YSA9IF90aGlzJF9ub3JtYWxpemVQb2x5bTIuZGF0YSwKICAgICAgICAgICAgICBfaW5jbHVkZWQgPSBfdGhpcyRfbm9ybWFsaXplUG9seW0yLmluY2x1ZGVkOwoKICAgICAgICAgIGRvY3VtZW50SGFzaC5kYXRhID0gX2RhdGE7CgogICAgICAgICAgaWYgKF9pbmNsdWRlZCkgewogICAgICAgICAgICB2YXIgX2RvY3VtZW50SGFzaCRpbmNsdWRlMjsKCiAgICAgICAgICAgIChfZG9jdW1lbnRIYXNoJGluY2x1ZGUyID0gZG9jdW1lbnRIYXNoLmluY2x1ZGVkKS5wdXNoLmFwcGx5KF9kb2N1bWVudEhhc2gkaW5jbHVkZTIsIF9pbmNsdWRlZCk7CiAgICAgICAgICB9CgogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICB2YXIgX3RoaXMkX25vcm1hbGl6ZUFycmF5ID0gdGhpcy5fbm9ybWFsaXplQXJyYXkoc3RvcmUsIHR5cGVOYW1lLCB2YWx1ZSwgcHJvcCksCiAgICAgICAgICAgIGRhdGEgPSBfdGhpcyRfbm9ybWFsaXplQXJyYXkuZGF0YSwKICAgICAgICAgICAgaW5jbHVkZWQgPSBfdGhpcyRfbm9ybWFsaXplQXJyYXkuaW5jbHVkZWQ7CgogICAgICAgIGlmIChpbmNsdWRlZCkgewogICAgICAgICAgdmFyIF9kb2N1bWVudEhhc2gkaW5jbHVkZTM7CgogICAgICAgICAgKF9kb2N1bWVudEhhc2gkaW5jbHVkZTMgPSBkb2N1bWVudEhhc2guaW5jbHVkZWQpLnB1c2guYXBwbHkoX2RvY3VtZW50SGFzaCRpbmNsdWRlMywgaW5jbHVkZWQpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGlzU2luZ2xlKSB7CiAgICAgICAgICBkYXRhLmZvckVhY2goZnVuY3Rpb24gKHJlc291cmNlKSB7CiAgICAgICAgICAgIC8qCiAgICAgICAgICAgICAgRmlndXJlcyBvdXQgaWYgdGhpcyBpcyB0aGUgcHJpbWFyeSByZWNvcmQgb3Igbm90LgogICAgICAgICAgICAgICBJdCdzIGVpdGhlcjoKICAgICAgICAgICAgICAgMS4gVGhlIHJlY29yZCB3aXRoIHRoZSBzYW1lIElEIGFzIHRoZSBvcmlnaW5hbCByZXF1ZXN0CiAgICAgICAgICAgICAgMi4gSWYgaXQncyBhIG5ld2x5IGNyZWF0ZWQgcmVjb3JkIHdpdGhvdXQgYW4gSUQsIHRoZSBmaXJzdCByZWNvcmQKICAgICAgICAgICAgICAgICBpbiB0aGUgYXJyYXkKICAgICAgICAgICAgICovCiAgICAgICAgICAgIHZhciBpc1VwZGF0ZWRSZWNvcmQgPSBpc1ByaW1hcnkgJiYgKDAsIF9wcml2YXRlLmNvZXJjZUlkKShyZXNvdXJjZS5pZCkgPT09IGlkOwogICAgICAgICAgICB2YXIgaXNGaXJzdENyZWF0ZWRSZWNvcmQgPSBpc1ByaW1hcnkgJiYgIWlkICYmICFkb2N1bWVudEhhc2guZGF0YTsKCiAgICAgICAgICAgIGlmIChpc0ZpcnN0Q3JlYXRlZFJlY29yZCB8fCBpc1VwZGF0ZWRSZWNvcmQpIHsKICAgICAgICAgICAgICBkb2N1bWVudEhhc2guZGF0YSA9IHJlc291cmNlOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGRvY3VtZW50SGFzaC5pbmNsdWRlZC5wdXNoKHJlc291cmNlKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChpc1ByaW1hcnkpIHsKICAgICAgICAgICAgZG9jdW1lbnRIYXNoLmRhdGEgPSBkYXRhOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKGRhdGEpIHsKICAgICAgICAgICAgICB2YXIgX2RvY3VtZW50SGFzaCRpbmNsdWRlNDsKCiAgICAgICAgICAgICAgKF9kb2N1bWVudEhhc2gkaW5jbHVkZTQgPSBkb2N1bWVudEhhc2guaW5jbHVkZWQpLnB1c2guYXBwbHkoX2RvY3VtZW50SGFzaCRpbmNsdWRlNCwgZGF0YSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBkb2N1bWVudEhhc2g7CiAgICB9LAogICAgaXNQcmltYXJ5VHlwZTogZnVuY3Rpb24gaXNQcmltYXJ5VHlwZShzdG9yZSwgdHlwZU5hbWUsIHByaW1hcnlUeXBlQ2xhc3MpIHsKICAgICAgcmV0dXJuIHN0b3JlLm1vZGVsRm9yKHR5cGVOYW1lKSA9PT0gcHJpbWFyeVR5cGVDbGFzczsKICAgIH0sCgogICAgLyoqCiAgICAgIFRoaXMgbWV0aG9kIGFsbG93cyB5b3UgdG8gcHVzaCBhIHBheWxvYWQgY29udGFpbmluZyB0b3AtbGV2ZWwKICAgICAgY29sbGVjdGlvbnMgb2YgcmVjb3JkcyBvcmdhbml6ZWQgcGVyIHR5cGUuCiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgInBvc3RzIjogW3sKICAgICAgICAgICJpZCI6ICIxIiwKICAgICAgICAgICJ0aXRsZSI6ICJSYWlscyBpcyBvbWFrYXNlIiwKICAgICAgICAgICJhdXRob3IiLCAiMSIsCiAgICAgICAgICAiY29tbWVudHMiOiBbICIxIiBdCiAgICAgICAgfV0sCiAgICAgICAgImNvbW1lbnRzIjogW3sKICAgICAgICAgICJpZCI6ICIxIiwKICAgICAgICAgICJib2R5IjogIkZJUlNUIgogICAgICAgIH1dLAogICAgICAgICJ1c2VycyI6IFt7CiAgICAgICAgICAiaWQiOiAiMSIsCiAgICAgICAgICAibmFtZSI6ICJAZDJoIgogICAgICAgIH1dCiAgICAgIH0KICAgICAgYGBgCiAgICAgICBJdCB3aWxsIGZpcnN0IG5vcm1hbGl6ZSB0aGUgcGF5bG9hZCwgc28geW91IGNhbiB1c2UgdGhpcyB0byBwdXNoCiAgICAgIGluIGRhdGEgc3RyZWFtaW5nIGluIGZyb20geW91ciBzZXJ2ZXIgc3RydWN0dXJlZCB0aGUgc2FtZSB3YXkKICAgICAgdGhhdCBmZXRjaGVzIGFuZCBzYXZlcyBhcmUgc3RydWN0dXJlZC4KICAgICAgIEBtZXRob2QgcHVzaFBheWxvYWQKICAgICAgQHBhcmFtIHtTdG9yZX0gc3RvcmUKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQKICAgICovCiAgICBwdXNoUGF5bG9hZDogZnVuY3Rpb24gcHVzaFBheWxvYWQoc3RvcmUsIHBheWxvYWQpIHsKICAgICAgdmFyIGRvY3VtZW50SGFzaCA9IHsKICAgICAgICBkYXRhOiBbXSwKICAgICAgICBpbmNsdWRlZDogW10KICAgICAgfTsKCiAgICAgIGZvciAodmFyIHByb3AgaW4gcGF5bG9hZCkgewogICAgICAgIHZhciBtb2RlbE5hbWUgPSB0aGlzLm1vZGVsTmFtZUZyb21QYXlsb2FkS2V5KHByb3ApOwoKICAgICAgICBpZiAoIXN0b3JlLl9oYXNNb2RlbEZvcihtb2RlbE5hbWUpKSB7CiAgICAgICAgICAoZmFsc2UgJiYgRW1iZXIud2Fybih0aGlzLndhcm5NZXNzYWdlTm9Nb2RlbEZvcktleShwcm9wLCBtb2RlbE5hbWUpLCBmYWxzZSwgewogICAgICAgICAgICBpZDogJ2RzLnNlcmlhbGl6ZXIubW9kZWwtZm9yLWtleS1taXNzaW5nJwogICAgICAgICAgfSkpOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICB2YXIgdHlwZSA9IHN0b3JlLm1vZGVsRm9yKG1vZGVsTmFtZSk7CiAgICAgICAgdmFyIHR5cGVTZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcih0eXBlLm1vZGVsTmFtZSk7CiAgICAgICAgRW1iZXIubWFrZUFycmF5KHBheWxvYWRbcHJvcF0pLmZvckVhY2goZnVuY3Rpb24gKGhhc2gpIHsKICAgICAgICAgIHZhciBfdHlwZVNlcmlhbGl6ZXIkbm9ybWEgPSB0eXBlU2VyaWFsaXplci5ub3JtYWxpemUodHlwZSwgaGFzaCwgcHJvcCksCiAgICAgICAgICAgICAgZGF0YSA9IF90eXBlU2VyaWFsaXplciRub3JtYS5kYXRhLAogICAgICAgICAgICAgIGluY2x1ZGVkID0gX3R5cGVTZXJpYWxpemVyJG5vcm1hLmluY2x1ZGVkOwoKICAgICAgICAgIGRvY3VtZW50SGFzaC5kYXRhLnB1c2goZGF0YSk7CgogICAgICAgICAgaWYgKGluY2x1ZGVkKSB7CiAgICAgICAgICAgIHZhciBfZG9jdW1lbnRIYXNoJGluY2x1ZGU1OwoKICAgICAgICAgICAgKF9kb2N1bWVudEhhc2gkaW5jbHVkZTUgPSBkb2N1bWVudEhhc2guaW5jbHVkZWQpLnB1c2guYXBwbHkoX2RvY3VtZW50SGFzaCRpbmNsdWRlNSwgaW5jbHVkZWQpOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CgogICAgICBzdG9yZS5wdXNoKGRvY3VtZW50SGFzaCk7CiAgICB9LAoKICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBpcyB1c2VkIHRvIGNvbnZlcnQgZWFjaCBKU09OIHJvb3Qga2V5IGluIHRoZSBwYXlsb2FkCiAgICAgIGludG8gYSBtb2RlbE5hbWUgdGhhdCBpdCBjYW4gdXNlIHRvIGxvb2sgdXAgdGhlIGFwcHJvcHJpYXRlIG1vZGVsIGZvcgogICAgICB0aGF0IHBhcnQgb2YgdGhlIHBheWxvYWQuCiAgICAgICBGb3IgZXhhbXBsZSwgeW91ciBzZXJ2ZXIgbWF5IHNlbmQgYSBtb2RlbCBuYW1lIHRoYXQgZG9lcyBub3QgY29ycmVzcG9uZCB3aXRoCiAgICAgIHRoZSBuYW1lIG9mIHRoZSBtb2RlbCBpbiB5b3VyIGFwcC4gTGV0J3MgdGFrZSBhIGxvb2sgYXQgYW4gZXhhbXBsZSBtb2RlbCwKICAgICAgYW5kIGFuIGV4YW1wbGUgcGF5bG9hZDoKICAgICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgICBpbXBvcnQgTW9kZWwgZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgYGBgamF2YXNjcmlwdAogICAgICAgIHsKICAgICAgICAgICJibG9nL3Bvc3QiOiB7CiAgICAgICAgICAgICJpZCI6ICIxCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICBgYGAKICAgICAgIEVtYmVyIERhdGEgaXMgZ29pbmcgdG8gbm9ybWFsaXplIHRoZSBwYXlsb2FkJ3Mgcm9vdCBrZXkgZm9yIHRoZSBtb2RlbE5hbWUuIEFzIGEgcmVzdWx0LAogICAgICBpdCB3aWxsIHRyeSB0byBsb29rIHVwIHRoZSAiYmxvZy9wb3N0IiBtb2RlbC4gU2luY2Ugd2UgZG9uJ3QgaGF2ZSBhIG1vZGVsIGNhbGxlZCAiYmxvZy9wb3N0IgogICAgICAob3IgYSBmaWxlIGNhbGxlZCBhcHAvbW9kZWxzL2Jsb2cvcG9zdC5qcyBpbiBlbWJlci1jbGkpLCBFbWJlciBEYXRhIHdpbGwgdGhyb3cgYW4gZXJyb3IKICAgICAgYmVjYXVzZSBpdCBjYW5ub3QgZmluZCB0aGUgImJsb2cvcG9zdCIgbW9kZWwuCiAgICAgICBTaW5jZSB3ZSB3YW50IHRvIHJlbW92ZSB0aGlzIG5hbWVzcGFjZSwgd2UgY2FuIGRlZmluZSBhIHNlcmlhbGl6ZXIgZm9yIHRoZSBhcHBsaWNhdGlvbiB0aGF0IHdpbGwKICAgICAgcmVtb3ZlICJibG9nLyIgZnJvbSB0aGUgcGF5bG9hZCBrZXkgd2hlbnZlciBpdCdzIGVuY291bnRlcmVkIGJ5IEVtYmVyIERhdGE6CiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSRVNUU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIG1vZGVsTmFtZUZyb21QYXlsb2FkS2V5KHBheWxvYWRLZXkpIHsKICAgICAgICAgIGlmIChwYXlsb2FkS2V5ID09PSAnYmxvZy9wb3N0JykgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fc3VwZXIocGF5bG9hZEtleS5yZXBsYWNlKCdibG9nLycsICcnKSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgIHJldHVybiB0aGlzLl9zdXBlcihwYXlsb2FkS2V5KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEFmdGVyIHJlZnJlc2hpbmcsIEVtYmVyIERhdGEgd2lsbCBhcHByb3ByaWF0ZWx5IGxvb2sgdXAgdGhlICJwb3N0IiBtb2RlbC4KICAgICAgIEJ5IGRlZmF1bHQgdGhlIG1vZGVsTmFtZSBmb3IgYSBtb2RlbCBpcyBpdHMKICAgICAgbmFtZSBpbiBkYXNoZXJpemVkIGZvcm0uIFRoaXMgbWVhbnMgdGhhdCBhIHBheWxvYWQga2V5IGxpa2UgImJsb2dQb3N0IiB3b3VsZCBiZQogICAgICBub3JtYWxpemVkIHRvICJibG9nLXBvc3QiIHdoZW4gRW1iZXIgRGF0YSBsb29rcyB1cCB0aGUgbW9kZWwuIFVzdWFsbHksIEVtYmVyIERhdGEKICAgICAgY2FuIHVzZSB0aGUgY29ycmVjdCBpbmZsZWN0aW9uIHRvIGRvIHRoaXMgZm9yIHlvdS4gTW9zdCBvZiB0aGUgdGltZSwgeW91IHdvbid0CiAgICAgIG5lZWQgdG8gb3ZlcnJpZGUgYG1vZGVsTmFtZUZyb21QYXlsb2FkS2V5YCBmb3IgdGhpcyBwdXJwb3NlLgogICAgICAgQG1ldGhvZCBtb2RlbE5hbWVGcm9tUGF5bG9hZEtleQogICAgICBAcGFyYW0ge1N0cmluZ30ga2V5CiAgICAgIEByZXR1cm4ge1N0cmluZ30gdGhlIG1vZGVsJ3MgbW9kZWxOYW1lCiAgICAqLwogICAgbW9kZWxOYW1lRnJvbVBheWxvYWRLZXk6IGZ1bmN0aW9uIG1vZGVsTmFtZUZyb21QYXlsb2FkS2V5KGtleSkgewogICAgICByZXR1cm4gKDAsIF9lbWJlckluZmxlY3Rvci5zaW5ndWxhcml6ZSkoKDAsIF9zdG9yZS5ub3JtYWxpemVNb2RlbE5hbWUpKGtleSkpOwogICAgfSwKICAgIC8vIFNFUklBTElaRQoKICAgIC8qKgogICAgICBDYWxsZWQgd2hlbiBhIHJlY29yZCBpcyBzYXZlZCBpbiBvcmRlciB0byBjb252ZXJ0IHRoZQogICAgICByZWNvcmQgaW50byBKU09OLgogICAgICAgQnkgZGVmYXVsdCwgaXQgY3JlYXRlcyBhIEpTT04gb2JqZWN0IHdpdGggYSBrZXkgZm9yCiAgICAgIGVhY2ggYXR0cmlidXRlIGFuZCBiZWxvbmdzVG8gcmVsYXRpb25zaGlwLgogICAgICAgRm9yIGV4YW1wbGUsIGNvbnNpZGVyIHRoaXMgbW9kZWw6CiAgICAgICBgYGBhcHAvbW9kZWxzL2NvbW1lbnQuanMKICAgICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIsIGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdGl0bGU6IGF0dHIoKSwKICAgICAgICBib2R5OiBhdHRyKCksCiAgICAgICAgIGF1dGhvcjogYmVsb25nc1RvKCd1c2VyJykKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVGhlIGRlZmF1bHQgc2VyaWFsaXphdGlvbiB3b3VsZCBjcmVhdGUgYSBKU09OIG9iamVjdCBsaWtlOgogICAgICAgYGBganMKICAgICAgewogICAgICAgICJ0aXRsZSI6ICJSYWlscyBpcyB1bmFnaSIsCiAgICAgICAgImJvZHkiOiAiUmFpbHM/IE9tYWthc2U/IE9fTyIsCiAgICAgICAgImF1dGhvciI6IDEyCiAgICAgIH0KICAgICAgYGBgCiAgICAgICBCeSBkZWZhdWx0LCBhdHRyaWJ1dGVzIGFyZSBwYXNzZWQgdGhyb3VnaCBhcy1pcywgdW5sZXNzCiAgICAgIHlvdSBzcGVjaWZpZWQgYW4gYXR0cmlidXRlIHR5cGUgKGBhdHRyKCdkYXRlJylgKS4gSWYKICAgICAgeW91IHNwZWNpZnkgYSB0cmFuc2Zvcm0sIHRoZSBKYXZhU2NyaXB0IHZhbHVlIHdpbGwgYmUKICAgICAgc2VyaWFsaXplZCB3aGVuIGluc2VydGVkIGludG8gdGhlIEpTT04gaGFzaC4KICAgICAgIEJ5IGRlZmF1bHQsIGJlbG9uZ3MtdG8gcmVsYXRpb25zaGlwcyBhcmUgY29udmVydGVkIGludG8KICAgICAgSURzIHdoZW4gaW5zZXJ0ZWQgaW50byB0aGUgSlNPTiBoYXNoLgogICAgICAgIyMgSURzCiAgICAgICBgc2VyaWFsaXplYCB0YWtlcyBhbiBvcHRpb25zIGhhc2ggd2l0aCBhIHNpbmdsZSBvcHRpb246CiAgICAgIGBpbmNsdWRlSWRgLiBJZiB0aGlzIG9wdGlvbiBpcyBgdHJ1ZWAsIGBzZXJpYWxpemVgIHdpbGwsCiAgICAgIGJ5IGRlZmF1bHQgaW5jbHVkZSB0aGUgSUQgaW4gdGhlIEpTT04gb2JqZWN0IGl0IGJ1aWxkcy4KICAgICAgIFRoZSBhZGFwdGVyIHBhc3NlcyBpbiBgaW5jbHVkZUlkOiB0cnVlYCB3aGVuIHNlcmlhbGl6aW5nCiAgICAgIGEgcmVjb3JkIGZvciBgY3JlYXRlUmVjb3JkYCwgYnV0IG5vdCBmb3IgYHVwZGF0ZVJlY29yZGAuCiAgICAgICAjIyBDdXN0b21pemF0aW9uCiAgICAgICBZb3VyIHNlcnZlciBtYXkgZXhwZWN0IGEgZGlmZmVyZW50IEpTT04gZm9ybWF0IHRoYW4gdGhlCiAgICAgIGJ1aWx0LWluIHNlcmlhbGl6YXRpb24gZm9ybWF0LgogICAgICAgSW4gdGhhdCBjYXNlLCB5b3UgY2FuIGltcGxlbWVudCBgc2VyaWFsaXplYCB5b3Vyc2VsZiBhbmQKICAgICAgcmV0dXJuIGEgSlNPTiBoYXNoIG9mIHlvdXIgY2hvb3NpbmcuCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgUkVTVFNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0JzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgc2VyaWFsaXplKHNuYXBzaG90LCBvcHRpb25zKSB7CiAgICAgICAgICB2YXIganNvbiA9IHsKICAgICAgICAgICAgUE9TVF9UVEw6IHNuYXBzaG90LmF0dHIoJ3RpdGxlJyksCiAgICAgICAgICAgIFBPU1RfQkRZOiBzbmFwc2hvdC5hdHRyKCdib2R5JyksCiAgICAgICAgICAgIFBPU1RfQ01TOiBzbmFwc2hvdC5oYXNNYW55KCdjb21tZW50cycsIHsgaWRzOiB0cnVlIH0pCiAgICAgICAgICB9OwogICAgICAgICAgIGlmIChvcHRpb25zLmluY2x1ZGVJZCkgewogICAgICAgICAgICBqc29uLlBPU1RfSURfID0gc25hcHNob3QuaWQ7CiAgICAgICAgICB9CiAgICAgICAgICAgcmV0dXJuIGpzb247CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICAjIyBDdXN0b21pemluZyBhbiBBcHAtV2lkZSBTZXJpYWxpemVyCiAgICAgICBJZiB5b3Ugd2FudCB0byBkZWZpbmUgYSBzZXJpYWxpemVyIGZvciB5b3VyIGVudGlyZQogICAgICBhcHBsaWNhdGlvbiwgeW91J2xsIHByb2JhYmx5IHdhbnQgdG8gdXNlIGBlYWNoQXR0cmlidXRlYAogICAgICBhbmQgYGVhY2hSZWxhdGlvbnNoaXBgIG9uIHRoZSByZWNvcmQuCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CiAgICAgIGltcG9ydCB7IHBsdXJhbGl6ZSB9IGZyb20gJ2VtYmVyLWluZmxlY3Rvcic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSRVNUU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIHNlcmlhbGl6ZShzbmFwc2hvdCwgb3B0aW9ucykgewogICAgICAgICAgdmFyIGpzb24gPSB7fTsKICAgICAgICAgICBzbmFwc2hvdC5lYWNoQXR0cmlidXRlKGZ1bmN0aW9uKG5hbWUpIHsKICAgICAgICAgICAganNvbltzZXJ2ZXJBdHRyaWJ1dGVOYW1lKG5hbWUpXSA9IHNuYXBzaG90LmF0dHIobmFtZSk7CiAgICAgICAgICB9KTsKICAgICAgICAgICBzbmFwc2hvdC5lYWNoUmVsYXRpb25zaGlwKGZ1bmN0aW9uKG5hbWUsIHJlbGF0aW9uc2hpcCkgewogICAgICAgICAgICBpZiAocmVsYXRpb25zaGlwLmtpbmQgPT09ICdoYXNNYW55JykgewogICAgICAgICAgICAgIGpzb25bc2VydmVySGFzTWFueU5hbWUobmFtZSldID0gc25hcHNob3QuaGFzTWFueShuYW1lLCB7IGlkczogdHJ1ZSB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgICAgaWYgKG9wdGlvbnMuaW5jbHVkZUlkKSB7CiAgICAgICAgICAgIGpzb24uSURfID0gc25hcHNob3QuaWQ7CiAgICAgICAgICB9CiAgICAgICAgICAgcmV0dXJuIGpzb247CiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGZ1bmN0aW9uIHNlcnZlckF0dHJpYnV0ZU5hbWUoYXR0cmlidXRlKSB7CiAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZS51bmRlcnNjb3JlKCkudG9VcHBlckNhc2UoKTsKICAgICAgfQogICAgICAgZnVuY3Rpb24gc2VydmVySGFzTWFueU5hbWUobmFtZSkgewogICAgICAgIHJldHVybiBzZXJ2ZXJBdHRyaWJ1dGVOYW1lKHNpbmd1bGFyaXplKG5hbWUpKSArICJfSURTIjsKICAgICAgfQogICAgICBgYGAKICAgICAgIFRoaXMgc2VyaWFsaXplciB3aWxsIGdlbmVyYXRlIEpTT04gdGhhdCBsb29rcyBsaWtlIHRoaXM6CiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgIlRJVExFIjogIlJhaWxzIGlzIG9tYWthc2UiLAogICAgICAgICJCT0RZIjogIlllcC4gT21ha2FzZS4iLAogICAgICAgICJDT01NRU5UX0lEUyI6IFsgMSwgMiwgMyBdCiAgICAgIH0KICAgICAgYGBgCiAgICAgICAjIyBUd2Vha2luZyB0aGUgRGVmYXVsdCBKU09OCiAgICAgICBJZiB5b3UganVzdCB3YW50IHRvIGRvIHNvbWUgc21hbGwgdHdlYWtzIG9uIHRoZSBkZWZhdWx0IEpTT04sCiAgICAgIHlvdSBjYW4gY2FsbCBzdXBlciBmaXJzdCBhbmQgbWFrZSB0aGUgdHdlYWtzIG9uIHRoZSByZXR1cm5lZAogICAgICBKU09OLgogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL3Bvc3QuanMKICAgICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSRVNUU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIHNlcmlhbGl6ZShzbmFwc2hvdCwgb3B0aW9ucykgewogICAgICAgICAgdmFyIGpzb24gPSB0aGlzLl9zdXBlcihzbmFwc2hvdCwgb3B0aW9ucyk7CiAgICAgICAgICAganNvbi5zdWJqZWN0ID0ganNvbi50aXRsZTsKICAgICAgICAgIGRlbGV0ZSBqc29uLnRpdGxlOwogICAgICAgICAgIHJldHVybiBqc29uOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXJpYWxpemUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAgQHJldHVybiB7T2JqZWN0fSBqc29uCiAgICAqLwogICAgc2VyaWFsaXplOiBmdW5jdGlvbiBzZXJpYWxpemUoc25hcHNob3QsIG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKICAgIC8qKgogICAgICBZb3UgY2FuIHVzZSB0aGlzIG1ldGhvZCB0byBjdXN0b21pemUgdGhlIHJvb3Qga2V5cyBzZXJpYWxpemVkIGludG8gdGhlIEpTT04uCiAgICAgIFRoZSBoYXNoIHByb3BlcnR5IHNob3VsZCBiZSBtb2RpZmllZCBieSByZWZlcmVuY2UgKHBvc3NpYmx5IHVzaW5nIHNvbWV0aGluZyBsaWtlIF8uZXh0ZW5kKQogICAgICBCeSBkZWZhdWx0IHRoZSBSRVNUIFNlcmlhbGl6ZXIgc2VuZHMgdGhlIG1vZGVsTmFtZSBvZiBhIG1vZGVsLCB3aGljaCBpcyBhIGNhbWVsaXplZAogICAgICB2ZXJzaW9uIG9mIHRoZSBuYW1lLgogICAgICAgRm9yIGV4YW1wbGUsIHlvdXIgc2VydmVyIG1heSBleHBlY3QgdW5kZXJzY29yZWQgcm9vdCBvYmplY3RzLgogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBSRVNUU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgICBpbXBvcnQgeyBkZWNhbWVsaXplIH0gZnJvbSAnQGVtYmVyL3N0cmluZyc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSRVNUU2VyaWFsaXplci5leHRlbmQoewogICAgICAgIHNlcmlhbGl6ZUludG9IYXNoKGRhdGEsIHR5cGUsIHJlY29yZCwgb3B0aW9ucykgewogICAgICAgICAgdmFyIHJvb3QgPSBkZWNhbWVsaXplKHR5cGUubW9kZWxOYW1lKTsKICAgICAgICAgIGRhdGFbcm9vdF0gPSB0aGlzLnNlcmlhbGl6ZShyZWNvcmQsIG9wdGlvbnMpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXJpYWxpemVJbnRvSGFzaAogICAgICBAcGFyYW0ge09iamVjdH0gaGFzaAogICAgICBAcGFyYW0ge01vZGVsfSB0eXBlQ2xhc3MKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICovCiAgICBzZXJpYWxpemVJbnRvSGFzaDogZnVuY3Rpb24gc2VyaWFsaXplSW50b0hhc2goaGFzaCwgdHlwZUNsYXNzLCBzbmFwc2hvdCwgb3B0aW9ucykgewogICAgICB2YXIgbm9ybWFsaXplZFJvb3RLZXkgPSB0aGlzLnBheWxvYWRLZXlGcm9tTW9kZWxOYW1lKHR5cGVDbGFzcy5tb2RlbE5hbWUpOwogICAgICBoYXNoW25vcm1hbGl6ZWRSb290S2V5XSA9IHRoaXMuc2VyaWFsaXplKHNuYXBzaG90LCBvcHRpb25zKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFlvdSBjYW4gdXNlIGBwYXlsb2FkS2V5RnJvbU1vZGVsTmFtZWAgdG8gb3ZlcnJpZGUgdGhlIHJvb3Qga2V5IGZvciBhbiBvdXRnb2luZwogICAgICByZXF1ZXN0LiBCeSBkZWZhdWx0LCB0aGUgUkVTVFNlcmlhbGl6ZXIgcmV0dXJucyBhIGNhbWVsaXplZCB2ZXJzaW9uIG9mIHRoZQogICAgICBtb2RlbCdzIG5hbWUuCiAgICAgICBGb3IgYSBtb2RlbCBjYWxsZWQgVGFjb1BhcnR5LCBpdHMgYG1vZGVsTmFtZWAgd291bGQgYmUgdGhlIHN0cmluZyBgdGFjby1wYXJ0eWAuIFRoZSBSRVNUU2VyaWFsaXplcgogICAgICB3aWxsIHNlbmQgaXQgdG8gdGhlIHNlcnZlciB3aXRoIGB0YWNvUGFydHlgIGFzIHRoZSByb290IGtleSBpbiB0aGUgSlNPTiBwYXlsb2FkOgogICAgICAgYGBganMKICAgICAgewogICAgICAgICJ0YWNvUGFydHkiOiB7CiAgICAgICAgICAiaWQiOiAiMSIsCiAgICAgICAgICAibG9jYXRpb24iOiAiTWF0dGhldyBCZWFsZSdzIEhvdXNlIgogICAgICAgIH0KICAgICAgfQogICAgICBgYGAKICAgICAgIEZvciBleGFtcGxlLCB5b3VyIHNlcnZlciBtYXkgZXhwZWN0IGRhc2hlcml6ZWQgcm9vdCBvYmplY3RzOgogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBSRVNUU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgICBpbXBvcnQgeyBkYXNoZXJpemUgfSBmcm9tICdAZW1iZXIvc3RyaW5nJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJFU1RTZXJpYWxpemVyLmV4dGVuZCh7CiAgICAgICAgcGF5bG9hZEtleUZyb21Nb2RlbE5hbWUobW9kZWxOYW1lKSB7CiAgICAgICAgICByZXR1cm4gZGFzaGVyaXplKG1vZGVsTmFtZSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBHaXZlbiBhIGBUYWNvUGFydHlgIG1vZGVsLCBjYWxsaW5nIGBzYXZlYCBvbiBpdCB3b3VsZCBwcm9kdWNlIGFuIG91dGdvaW5nCiAgICAgIHJlcXVlc3QgbGlrZToKICAgICAgIGBgYGpzCiAgICAgIHsKICAgICAgICAidGFjby1wYXJ0eSI6IHsKICAgICAgICAgICJpZCI6ICIxIiwKICAgICAgICAgICJsb2NhdGlvbiI6ICJNYXR0aGV3IEJlYWxlJ3MgSG91c2UiCiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBwYXlsb2FkS2V5RnJvbU1vZGVsTmFtZQogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEByZXR1cm4ge1N0cmluZ30KICAgICovCiAgICBwYXlsb2FkS2V5RnJvbU1vZGVsTmFtZTogZnVuY3Rpb24gcGF5bG9hZEtleUZyb21Nb2RlbE5hbWUobW9kZWxOYW1lKSB7CiAgICAgIHJldHVybiBFbWJlci5TdHJpbmcuY2FtZWxpemUobW9kZWxOYW1lKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFlvdSBjYW4gdXNlIHRoaXMgbWV0aG9kIHRvIGN1c3RvbWl6ZSBob3cgcG9seW1vcnBoaWMgb2JqZWN0cyBhcmUgc2VyaWFsaXplZC4KICAgICAgQnkgZGVmYXVsdCB0aGUgUkVTVCBTZXJpYWxpemVyIGNyZWF0ZXMgdGhlIGtleSBieSBhcHBlbmRpbmcgYFR5cGVgIHRvCiAgICAgIHRoZSBhdHRyaWJ1dGUgYW5kIHZhbHVlIGZyb20gdGhlIG1vZGVsJ3MgY2FtZWxjYXNlZCBtb2RlbCBuYW1lLgogICAgICAgQG1ldGhvZCBzZXJpYWxpemVQb2x5bW9ycGhpY1R5cGUKICAgICAgQHBhcmFtIHtTbmFwc2hvdH0gc25hcHNob3QKICAgICAgQHBhcmFtIHtPYmplY3R9IGpzb24KICAgICAgQHBhcmFtIHtPYmplY3R9IHJlbGF0aW9uc2hpcAogICAgKi8KICAgIHNlcmlhbGl6ZVBvbHltb3JwaGljVHlwZTogZnVuY3Rpb24gc2VyaWFsaXplUG9seW1vcnBoaWNUeXBlKHNuYXBzaG90LCBqc29uLCByZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIGtleSA9IHJlbGF0aW9uc2hpcC5rZXk7CiAgICAgIHZhciB0eXBlS2V5ID0gdGhpcy5rZXlGb3JQb2x5bW9ycGhpY1R5cGUoa2V5LCByZWxhdGlvbnNoaXAudHlwZSwgJ3NlcmlhbGl6ZScpOwogICAgICB2YXIgYmVsb25nc1RvID0gc25hcHNob3QuYmVsb25nc1RvKGtleSk7CgogICAgICBpZiAoRW1iZXIuaXNOb25lKGJlbG9uZ3NUbykpIHsKICAgICAgICBqc29uW3R5cGVLZXldID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICBqc29uW3R5cGVLZXldID0gRW1iZXIuU3RyaW5nLmNhbWVsaXplKGJlbG9uZ3NUby5tb2RlbE5hbWUpOwogICAgICB9CiAgICB9LAoKICAgIC8qKgogICAgICBZb3UgY2FuIHVzZSB0aGlzIG1ldGhvZCB0byBjdXN0b21pemUgaG93IGEgcG9seW1vcnBoaWMgcmVsYXRpb25zaGlwIHNob3VsZAogICAgICBiZSBleHRyYWN0ZWQuCiAgICAgICBAbWV0aG9kIGV4dHJhY3RQb2x5bW9ycGhpY1JlbGF0aW9uc2hpcAogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwVHlwZQogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwSGFzaAogICAgICBAcGFyYW0ge09iamVjdH0gcmVsYXRpb25zaGlwT3B0aW9ucwogICAgICBAcmV0dXJuIHtPYmplY3R9CiAgICAgKi8KICAgIGV4dHJhY3RQb2x5bW9ycGhpY1JlbGF0aW9uc2hpcDogZnVuY3Rpb24gZXh0cmFjdFBvbHltb3JwaGljUmVsYXRpb25zaGlwKHJlbGF0aW9uc2hpcFR5cGUsIHJlbGF0aW9uc2hpcEhhc2gsIHJlbGF0aW9uc2hpcE9wdGlvbnMpIHsKICAgICAgdmFyIGtleSA9IHJlbGF0aW9uc2hpcE9wdGlvbnMua2V5LAogICAgICAgICAgcmVzb3VyY2VIYXNoID0gcmVsYXRpb25zaGlwT3B0aW9ucy5yZXNvdXJjZUhhc2gsCiAgICAgICAgICByZWxhdGlvbnNoaXBNZXRhID0gcmVsYXRpb25zaGlwT3B0aW9ucy5yZWxhdGlvbnNoaXBNZXRhOyAvLyBBIHBvbHltb3JwaGljIGJlbG9uZ3NUbyByZWxhdGlvbnNoaXAgY2FuIGJlIHByZXNlbnQgaW4gdGhlIHBheWxvYWQKICAgICAgLy8gZWl0aGVyIGluIHRoZSBmb3JtIHdoZXJlIHRoZSBgaWRgIGFuZCB0aGUgYHR5cGVgIGFyZSBnaXZlbjoKICAgICAgLy8KICAgICAgLy8gICB7CiAgICAgIC8vICAgICBtZXNzYWdlOiB7IGlkOiAxLCB0eXBlOiAncG9zdCcgfQogICAgICAvLyAgIH0KICAgICAgLy8KICAgICAgLy8gb3IgYnkgdGhlIGBpZGAgYW5kIGEgYDxyZWxhdGlvbnNoaXA+VHlwZWAgYXR0cmlidXRlOgogICAgICAvLwogICAgICAvLyAgIHsKICAgICAgLy8gICAgIG1lc3NhZ2U6IDEsCiAgICAgIC8vICAgICBtZXNzYWdlVHlwZTogJ3Bvc3QnCiAgICAgIC8vICAgfQogICAgICAvLwogICAgICAvLyBUaGUgbmV4dCBjb2RlIGNoZWNrcyBpZiB0aGUgbGF0dGVyIGNhc2UgaXMgcHJlc2VudCBhbmQgcmV0dXJucyB0aGUKICAgICAgLy8gY29ycmVzcG9uZGluZyBKU09OLUFQSSByZXByZXNlbnRhdGlvbi4gVGhlIGZvcm1lciBjYXNlIGlzIGhhbmRsZWQgd2l0aGluCiAgICAgIC8vIHRoZSBiYXNlIGNsYXNzIEpTT05TZXJpYWxpemVyLgoKICAgICAgdmFyIGlzUG9seW1vcnBoaWMgPSByZWxhdGlvbnNoaXBNZXRhLm9wdGlvbnMucG9seW1vcnBoaWM7CiAgICAgIHZhciB0eXBlUHJvcGVydHkgPSB0aGlzLmtleUZvclBvbHltb3JwaGljVHlwZShrZXksIHJlbGF0aW9uc2hpcFR5cGUsICdkZXNlcmlhbGl6ZScpOwoKICAgICAgaWYgKGlzUG9seW1vcnBoaWMgJiYgcmVzb3VyY2VIYXNoW3R5cGVQcm9wZXJ0eV0gIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgcmVsYXRpb25zaGlwSGFzaCAhPT0gJ29iamVjdCcpIHsKICAgICAgICB2YXIgdHlwZSA9IHRoaXMubW9kZWxOYW1lRnJvbVBheWxvYWRLZXkocmVzb3VyY2VIYXNoW3R5cGVQcm9wZXJ0eV0pOwogICAgICAgIHJldHVybiB7CiAgICAgICAgICBpZDogcmVsYXRpb25zaGlwSGFzaCwKICAgICAgICAgIHR5cGU6IHR5cGUKICAgICAgICB9OwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0KICB9KTsKCiAgaWYgKGZhbHNlCiAgLyogREVCVUcgKi8KICApIHsKICAgIFJFU1RTZXJpYWxpemVyLnJlb3Blbih7CiAgICAgIHdhcm5NZXNzYWdlTm9Nb2RlbEZvcktleTogZnVuY3Rpb24gd2Fybk1lc3NhZ2VOb01vZGVsRm9yS2V5KHByb3AsIHR5cGVLZXkpIHsKICAgICAgICByZXR1cm4gJ0VuY291bnRlcmVkICInICsgcHJvcCArICciIGluIHBheWxvYWQsIGJ1dCBubyBtb2RlbCB3YXMgZm91bmQgZm9yIG1vZGVsIG5hbWUgIicgKyB0eXBlS2V5ICsgJyIgKHJlc29sdmVkIG1vZGVsIG5hbWUgdXNpbmcgJyArIHRoaXMuY29uc3RydWN0b3IudG9TdHJpbmcoKSArICcubW9kZWxOYW1lRnJvbVBheWxvYWRLZXkoIicgKyBwcm9wICsgJyIpKSc7CiAgICAgIH0KICAgIH0pOwogIH0KCiAgdmFyIF9kZWZhdWx0ID0gUkVTVFNlcmlhbGl6ZXI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKO2RlZmluZSgiQGVtYmVyLWRhdGEvc2VyaWFsaXplci90cmFuc2Zvcm0iLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplci8tcHJpdmF0ZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9wcml2YXRlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc2VyaWFsaXplcgogICovCiAgdmFyIF9kZWZhdWx0ID0gX3ByaXZhdGUuVHJhbnNmb3JtOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CjtkZWZpbmUoJ0BlbWJlci1kYXRhL3N0b3JlLy1wcml2YXRlJywgWydleHBvcnRzJywgJ3JlcXVpcmUnLCAnQGVtYmVyLWRhdGEvY2FuYXJ5LWZlYXR1cmVzJywgJ2VtYmVyLWluZmxlY3RvciddLCBmdW5jdGlvbiAoZXhwb3J0cywgcmVxdWlyZSwgY2FuYXJ5RmVhdHVyZXMsIGVtYmVySW5mbGVjdG9yKSB7ICd1c2Ugc3RyaWN0JzsKCiAgdmFyIHJlcXVpcmVfX2RlZmF1bHQgPSAnZGVmYXVsdCcgaW4gcmVxdWlyZSA/IHJlcXVpcmVbJ2RlZmF1bHQnXSA6IHJlcXVpcmU7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIHZhciBEZXByZWNhdGVkRXZlbnRlZCA9ICBFbWJlci5FdmVudGVkOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICAvKioKICAgIEhvbGRzIHZhbGlkYXRpb24gZXJyb3JzIGZvciBhIGdpdmVuIHJlY29yZCwgb3JnYW5pemVkIGJ5IGF0dHJpYnV0ZSBuYW1lcy4KCiAgICBFdmVyeSBgTW9kZWxgIGhhcyBhbiBgZXJyb3JzYCBwcm9wZXJ0eSB0aGF0IGlzIGFuIGluc3RhbmNlIG9mCiAgICBgRXJyb3JzYC4gVGhpcyBjYW4gYmUgdXNlZCB0byBkaXNwbGF5IHZhbGlkYXRpb24gZXJyb3IKICAgIG1lc3NhZ2VzIHJldHVybmVkIGZyb20gdGhlIHNlcnZlciB3aGVuIGEgYHJlY29yZC5zYXZlKClgIHJlamVjdHMuCgogICAgRm9yIEV4YW1wbGUsIGlmIHlvdSBoYWQgYSBgVXNlcmAgbW9kZWwgdGhhdCBsb29rZWQgbGlrZSB0aGlzOgoKICAgIGBgYGFwcC9tb2RlbHMvdXNlci5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGF0dHIgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CgogICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgdXNlcm5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICBlbWFpbDogYXR0cignc3RyaW5nJykKICAgIH0pOwogICAgYGBgCiAgICBBbmQgeW91IGF0dGVtcHRlZCB0byBzYXZlIGEgcmVjb3JkIHRoYXQgZGlkIG5vdCB2YWxpZGF0ZSBvbiB0aGUgYmFja2VuZDoKCiAgICBgYGBqYXZhc2NyaXB0CiAgICBsZXQgdXNlciA9IHN0b3JlLmNyZWF0ZVJlY29yZCgndXNlcicsIHsKICAgICAgdXNlcm5hbWU6ICd0b21zdGVyJywKICAgICAgZW1haWw6ICdpbnZhbGlkRW1haWwnCiAgICB9KTsKICAgIHVzZXIuc2F2ZSgpOwogICAgYGBgCgogICAgWW91ciBiYWNrZW5kIHdvdWxkIGJlIGV4cGVjdGVkIHRvIHJldHVybiBhbiBlcnJvciByZXNwb25zZSB0aGF0IGRlc2NyaWJlZAogICAgdGhlIHByb2JsZW0sIHNvIHRoYXQgZXJyb3IgbWVzc2FnZXMgY2FuIGJlIGdlbmVyYXRlZCBvbiB0aGUgYXBwLgoKICAgIEFQSSByZXNwb25zZXMgd2lsbCBiZSB0cmFuc2xhdGVkIGludG8gaW5zdGFuY2VzIG9mIGBFcnJvcnNgIGRpZmZlcmVudGx5LAogICAgZGVwZW5kaW5nIG9uIHRoZSBzcGVjaWZpYyBjb21iaW5hdGlvbiBvZiBhZGFwdGVyIGFuZCBzZXJpYWxpemVyIHVzZWQuIFlvdQogICAgbWF5IHdhbnQgdG8gY2hlY2sgdGhlIGRvY3VtZW50YXRpb24gb3IgdGhlIHNvdXJjZSBjb2RlIG9mIHRoZSBsaWJyYXJpZXMKICAgIHRoYXQgeW91IGFyZSB1c2luZywgdG8ga25vdyBob3cgdGhleSBleHBlY3QgZXJyb3JzIHRvIGJlIGNvbW11bmljYXRlZC4KCiAgICBFcnJvcnMgY2FuIGJlIGRpc3BsYXllZCB0byB0aGUgdXNlciBieSBhY2Nlc3NpbmcgdGhlaXIgcHJvcGVydHkgbmFtZQogICAgdG8gZ2V0IGFuIGFycmF5IG9mIGFsbCB0aGUgZXJyb3Igb2JqZWN0cyBmb3IgdGhhdCBwcm9wZXJ0eS4gRWFjaAogICAgZXJyb3Igb2JqZWN0IGlzIGEgSmF2YVNjcmlwdCBvYmplY3Qgd2l0aCB0d28ga2V5czoKCiAgICAtIGBtZXNzYWdlYCBBIHN0cmluZyBjb250YWluaW5nIHRoZSBlcnJvciBtZXNzYWdlIGZyb20gdGhlIGJhY2tlbmQKICAgIC0gYGF0dHJpYnV0ZWAgVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IGFzc29jaWF0ZWQgd2l0aCB0aGlzIGVycm9yIG1lc3NhZ2UKCiAgICBgYGBoYW5kbGViYXJzCiAgICA8bGFiZWw+VXNlcm5hbWU6IHt7aW5wdXQgdmFsdWU9dXNlcm5hbWV9fSA8L2xhYmVsPgogICAge3sjZWFjaCBtb2RlbC5lcnJvcnMudXNlcm5hbWUgYXMgfGVycm9yfH19CiAgICAgIDxkaXYgY2xhc3M9ImVycm9yIj4KICAgICAgICB7e2Vycm9yLm1lc3NhZ2V9fQogICAgICA8L2Rpdj4KICAgIHt7L2VhY2h9fQoKICAgIDxsYWJlbD5FbWFpbDoge3tpbnB1dCB2YWx1ZT1lbWFpbH19IDwvbGFiZWw+CiAgICB7eyNlYWNoIG1vZGVsLmVycm9ycy5lbWFpbCBhcyB8ZXJyb3J8fX0KICAgICAgPGRpdiBjbGFzcz0iZXJyb3IiPgogICAgICAgIHt7ZXJyb3IubWVzc2FnZX19CiAgICAgIDwvZGl2PgogICAge3svZWFjaH19CiAgICBgYGAKCiAgICBZb3UgY2FuIGFsc28gYWNjZXNzIHRoZSBzcGVjaWFsIGBtZXNzYWdlc2AgcHJvcGVydHkgb24gdGhlIGVycm9yCiAgICBvYmplY3QgdG8gZ2V0IGFuIGFycmF5IG9mIGFsbCB0aGUgZXJyb3Igc3RyaW5ncy4KCiAgICBgYGBoYW5kbGViYXJzCiAgICB7eyNlYWNoIG1vZGVsLmVycm9ycy5tZXNzYWdlcyBhcyB8bWVzc2FnZXx9fQogICAgICA8ZGl2IGNsYXNzPSJlcnJvciI+CiAgICAgICAge3ttZXNzYWdlfX0KICAgICAgPC9kaXY+CiAgICB7ey9lYWNofX0KICAgIGBgYAoKICAgIEBjbGFzcyBFcnJvcnMKICAgIEBleHRlbmRzIEVtYmVyLkFycmF5UHJveHkKICAgIEB1c2VzIEVtYmVyLkV2ZW50ZWQKICAgKi8KICB2YXIgZXJyb3JzID0gRW1iZXIuQXJyYXlQcm94eS5leHRlbmQoRGVwcmVjYXRlZEV2ZW50ZWQsIHsKICAgIC8qKgogICAgICBSZWdpc3RlciB3aXRoIHRhcmdldCBoYW5kbGVyCiAgICAgICBAbWV0aG9kIF9yZWdpc3RlckhhbmRsZXJzCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX3JlZ2lzdGVySGFuZGxlcnM6IGZ1bmN0aW9uIF9yZWdpc3RlckhhbmRsZXJzKGJlY2FtZUludmFsaWQsIGJlY2FtZVZhbGlkKSB7CiAgICAgIHRoaXMuX3JlZ2lzdGVyZWRIYW5kbGVycyA9IHsKICAgICAgICBiZWNhbWVJbnZhbGlkOiBiZWNhbWVJbnZhbGlkLAogICAgICAgIGJlY2FtZVZhbGlkOiBiZWNhbWVWYWxpZAogICAgICB9OwogICAgfSwKCiAgICAvKioKICAgICAgQHByb3BlcnR5IGVycm9yc0J5QXR0cmlidXRlTmFtZQogICAgICBAdHlwZSB7TWFwV2l0aERlZmF1bHR9CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgZXJyb3JzQnlBdHRyaWJ1dGVOYW1lOiBFbWJlci5jb21wdXRlZChmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBuZXcgTWFwKCk7CiAgICB9KSwKCiAgICAvKioKICAgICAgUmV0dXJucyBlcnJvcnMgZm9yIGEgZ2l2ZW4gYXR0cmlidXRlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCB1c2VyID0gc3RvcmUuY3JlYXRlUmVjb3JkKCd1c2VyJywgewogICAgICAgIHVzZXJuYW1lOiAndG9tc3RlcicsCiAgICAgICAgZW1haWw6ICdpbnZhbGlkRW1haWwnCiAgICAgIH0pOwogICAgICB1c2VyLnNhdmUoKS5jYXRjaChmdW5jdGlvbigpewogICAgICAgIHVzZXIuZ2V0KCdlcnJvcnMnKS5lcnJvcnNGb3IoJ2VtYWlsJyk7IC8vIHJldHVybnM6CiAgICAgICAgLy8gW3thdHRyaWJ1dGU6ICJlbWFpbCIsIG1lc3NhZ2U6ICJEb2Vzbid0IGxvb2sgbGlrZSBhIHZhbGlkIGVtYWlsLiJ9XQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGVycm9yc0ZvcgogICAgICBAcGFyYW0ge1N0cmluZ30gYXR0cmlidXRlCiAgICAgIEByZXR1cm4ge0FycmF5fQogICAgKi8KICAgIGVycm9yc0ZvcjogZnVuY3Rpb24gZXJyb3JzRm9yKGF0dHJpYnV0ZSkgewogICAgICB2YXIgbWFwID0gRW1iZXIuZ2V0KHRoaXMsICdlcnJvcnNCeUF0dHJpYnV0ZU5hbWUnKTsKCiAgICAgIGlmICghbWFwLmhhcyhhdHRyaWJ1dGUpKSB7CiAgICAgICAgbWFwLnNldChhdHRyaWJ1dGUsIEVtYmVyLkEoKSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBtYXAuZ2V0KGF0dHJpYnV0ZSk7CiAgICB9LAoKICAgIC8qKgogICAgICBBbiBhcnJheSBjb250YWluaW5nIGFsbCBvZiB0aGUgZXJyb3IgbWVzc2FnZXMgZm9yIHRoaXMKICAgICAgcmVjb3JkLiBUaGlzIGlzIHVzZWZ1bCBmb3IgZGlzcGxheWluZyBhbGwgZXJyb3JzIHRvIHRoZSB1c2VyLgogICAgICAgYGBgaGFuZGxlYmFycwogICAgICB7eyNlYWNoIG1vZGVsLmVycm9ycy5tZXNzYWdlcyBhcyB8bWVzc2FnZXx9fQogICAgICAgIDxkaXYgY2xhc3M9ImVycm9yIj4KICAgICAgICAgIHt7bWVzc2FnZX19CiAgICAgICAgPC9kaXY+CiAgICAgIHt7L2VhY2h9fQogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBtZXNzYWdlcwogICAgICBAdHlwZSB7QXJyYXl9CiAgICAqLwogICAgbWVzc2FnZXM6IEVtYmVyLmNvbXB1dGVkLm1hcEJ5KCdjb250ZW50JywgJ21lc3NhZ2UnKSwKCiAgICAvKioKICAgICAgQHByb3BlcnR5IGNvbnRlbnQKICAgICAgQHR5cGUge0FycmF5fQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGNvbnRlbnQ6IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIEVtYmVyLkEoKTsKICAgIH0pLAoKICAgIC8qKgogICAgICBAbWV0aG9kIHVua25vd25Qcm9wZXJ0eQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIHVua25vd25Qcm9wZXJ0eTogZnVuY3Rpb24gdW5rbm93blByb3BlcnR5KGF0dHJpYnV0ZSkgewogICAgICB2YXIgZXJyb3JzID0gdGhpcy5lcnJvcnNGb3IoYXR0cmlidXRlKTsKCiAgICAgIGlmIChlcnJvcnMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgICAgfQoKICAgICAgcmV0dXJuIGVycm9yczsKICAgIH0sCgogICAgLyoqCiAgICAgIFRvdGFsIG51bWJlciBvZiBlcnJvcnMuCiAgICAgICBAcHJvcGVydHkgbGVuZ3RoCiAgICAgIEB0eXBlIHtOdW1iZXJ9CiAgICAgIEByZWFkT25seQogICAgKi8KCiAgICAvKioKICAgICAgQHByb3BlcnR5IGlzRW1wdHkKICAgICAgQHR5cGUge0Jvb2xlYW59CiAgICAgIEByZWFkT25seQogICAgKi8KICAgIGlzRW1wdHk6IEVtYmVyLmNvbXB1dGVkLm5vdCgnbGVuZ3RoJykucmVhZE9ubHkoKSwKCiAgICAvKioKICAgICBNYW51YWxseSBhZGRzIGVycm9ycyB0byB0aGUgcmVjb3JkLiBUaGlzIHdpbGwgdHJpZ2VyIHRoZSBgYmVjYW1lSW52YWxpZGAgZXZlbnQvIGxpZmVjeWNsZSBtZXRob2Qgb24KICAgICAgdGhlIHJlY29yZCBhbmQgdHJhbnNpdGlvbiB0aGUgcmVjb3JkIGludG8gYW4gYGludmFsaWRgIHN0YXRlLgogICAgICBFeGFtcGxlCiAgICAgYGBgamF2YXNjcmlwdAogICAgICBsZXQgZXJyb3JzID0gZ2V0KHVzZXIsICdlcnJvcnMnKTsKICAgICAgIC8vIGFkZCBtdWx0aXBsZSBlcnJvcnMKICAgICAgZXJyb3JzLmFkZCgncGFzc3dvcmQnLCBbCiAgICAgICAgJ011c3QgYmUgYXQgbGVhc3QgMTIgY2hhcmFjdGVycycsCiAgICAgICAgJ011c3QgY29udGFpbiBhdCBsZWFzdCBvbmUgc3ltYm9sJywKICAgICAgICAnQ2Fubm90IGNvbnRhaW4geW91ciBuYW1lJwogICAgICBdKTsKICAgICAgIGVycm9ycy5lcnJvcnNGb3IoJ3Bhc3N3b3JkJyk7CiAgICAgIC8vID0+CiAgICAgIC8vIFsKICAgICAgLy8gICB7IGF0dHJpYnV0ZTogJ3Bhc3N3b3JkJywgbWVzc2FnZTogJ011c3QgYmUgYXQgbGVhc3QgMTIgY2hhcmFjdGVycycgfSwKICAgICAgLy8gICB7IGF0dHJpYnV0ZTogJ3Bhc3N3b3JkJywgbWVzc2FnZTogJ011c3QgY29udGFpbiBhdCBsZWFzdCBvbmUgc3ltYm9sJyB9LAogICAgICAvLyAgIHsgYXR0cmlidXRlOiAncGFzc3dvcmQnLCBtZXNzYWdlOiAnQ2Fubm90IGNvbnRhaW4geW91ciBuYW1lJyB9LAogICAgICAvLyBdCiAgICAgICAvLyBhZGQgYSBzaW5nbGUgZXJyb3IKICAgICAgZXJyb3JzLmFkZCgndXNlcm5hbWUnLCAnVGhpcyBmaWVsZCBpcyByZXF1aXJlZCcpOwogICAgICAgZXJyb3JzLmVycm9yc0ZvcigncGFzc3dvcmQnKTsKICAgICAgLy8gPT4KICAgICAgLy8gWwogICAgICAvLyAgIHsgYXR0cmlidXRlOiAndXNlcm5hbWUnLCBtZXNzYWdlOiAnVGhpcyBmaWVsZCBpcyByZXF1aXJlZCcgfSwKICAgICAgLy8gXQogICAgIGBgYAogICAgQG1ldGhvZCBhZGQKICAgIEBwYXJhbSB7c3RyaW5nfSBhdHRyaWJ1dGUgLSB0aGUgcHJvcGVydHkgbmFtZSBvZiBhbiBhdHRyaWJ1dGUgb3IgcmVsYXRpb25zaGlwCiAgICBAcGFyYW0ge3N0cmluZ1tdfHN0cmluZ30gbWVzc2FnZXMgLSBhbiBlcnJvciBtZXNzYWdlIG9yIGFycmF5IG9mIGVycm9yIG1lc3NhZ2VzIGZvciB0aGUgYXR0cmlidXRlCiAgICAgKi8KICAgIGFkZDogZnVuY3Rpb24gYWRkKGF0dHJpYnV0ZSwgbWVzc2FnZXMpIHsKICAgICAgdmFyIHdhc0VtcHR5ID0gRW1iZXIuZ2V0KHRoaXMsICdpc0VtcHR5Jyk7CgogICAgICB0aGlzLl9hZGQoYXR0cmlidXRlLCBtZXNzYWdlcyk7CgogICAgICBpZiAod2FzRW1wdHkgJiYgIUVtYmVyLmdldCh0aGlzLCAnaXNFbXB0eScpKSB7CiAgICAgICAgdGhpcy5fcmVnaXN0ZXJlZEhhbmRsZXJzICYmIHRoaXMuX3JlZ2lzdGVyZWRIYW5kbGVycy5iZWNhbWVJbnZhbGlkKCk7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIEFkZHMgZXJyb3IgbWVzc2FnZXMgdG8gYSBnaXZlbiBhdHRyaWJ1dGUgd2l0aG91dCBzZW5kaW5nIGV2ZW50LgogICAgICAgQG1ldGhvZCBfYWRkCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX2FkZDogZnVuY3Rpb24gX2FkZChhdHRyaWJ1dGUsIG1lc3NhZ2VzKSB7CiAgICAgIG1lc3NhZ2VzID0gdGhpcy5fZmluZE9yQ3JlYXRlTWVzc2FnZXMoYXR0cmlidXRlLCBtZXNzYWdlcyk7CiAgICAgIHRoaXMuYWRkT2JqZWN0cyhtZXNzYWdlcyk7CiAgICAgIHRoaXMuZXJyb3JzRm9yKGF0dHJpYnV0ZSkuYWRkT2JqZWN0cyhtZXNzYWdlcyk7CiAgICAgIHRoaXMubm90aWZ5UHJvcGVydHlDaGFuZ2UoYXR0cmlidXRlKTsKICAgIH0sCgogICAgLyoqCiAgICAgIEBtZXRob2QgX2ZpbmRPckNyZWF0ZU1lc3NhZ2VzCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX2ZpbmRPckNyZWF0ZU1lc3NhZ2VzOiBmdW5jdGlvbiBfZmluZE9yQ3JlYXRlTWVzc2FnZXMoYXR0cmlidXRlLCBtZXNzYWdlcykgewogICAgICB2YXIgZXJyb3JzID0gdGhpcy5lcnJvcnNGb3IoYXR0cmlidXRlKTsKICAgICAgdmFyIG1lc3NhZ2VzQXJyYXkgPSBFbWJlci5tYWtlQXJyYXkobWVzc2FnZXMpOwoKICAgICAgdmFyIF9tZXNzYWdlcyA9IG5ldyBBcnJheShtZXNzYWdlc0FycmF5Lmxlbmd0aCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2VzQXJyYXkubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgbWVzc2FnZSA9IG1lc3NhZ2VzQXJyYXlbaV07CiAgICAgICAgdmFyIGVyciA9IGVycm9ycy5maW5kQnkoJ21lc3NhZ2UnLCBtZXNzYWdlKTsKCiAgICAgICAgaWYgKGVycikgewogICAgICAgICAgX21lc3NhZ2VzW2ldID0gZXJyOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBfbWVzc2FnZXNbaV0gPSB7CiAgICAgICAgICAgIGF0dHJpYnV0ZTogYXR0cmlidXRlLAogICAgICAgICAgICBtZXNzYWdlOiBtZXNzYWdlCiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIF9tZXNzYWdlczsKICAgIH0sCgogICAgLyoqCiAgICAgTWFudWFsbHkgcmVtb3ZlcyBhbGwgZXJyb3JzIGZvciBhIGdpdmVuIG1lbWJlciBmcm9tIHRoZSByZWNvcmQuCiAgICAgICBUaGlzIHdpbGwgdHJhbnNpdGlvbiB0aGUgcmVjb3JkIGludG8gYSBgdmFsaWRgIHN0YXRlLCBhbmQKICAgICAgdHJpZ2dlcnMgdGhlIGBiZWNhbWVWYWxpZGAgZXZlbnQgYW5kIGxpZmVjeWNsZSBtZXRob2QuCiAgICAgIEV4YW1wbGU6CiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IGVycm9ycyA9IGdldCgndXNlcicsIGVycm9ycyk7CiAgICAgIGVycm9ycy5hZGQoJ3Bob25lJywgWydlcnJvci0xJywgJ2Vycm9yLTInXSk7CiAgICAgICBlcnJvcnMuZXJyb3JzRm9yKCdwaG9uZScpOwogICAgICAvLyA9PgogICAgICAvLyBbCiAgICAgIC8vICAgeyBhdHRyaWJ1dGU6ICdwaG9uZScsIG1lc3NhZ2U6ICdlcnJvci0xJyB9LAogICAgICAvLyAgIHsgYXR0cmlidXRlOiAncGhvbmUnLCBtZXNzYWdlOiAnZXJyb3ItMicgfSwKICAgICAgLy8gXQogICAgICAgZXJyb3JzLnJlbW92ZSgncGhvbmUnKTsKICAgICAgIGVycm9ycy5lcnJvcnNGb3IoJ3Bob25lJyk7CiAgICAgIC8vID0+IHVuZGVmaW5lZAogICAgIGBgYAogICAgIEBtZXRob2QgcmVtb3ZlCiAgICAgQHBhcmFtIHtzdHJpbmd9IG1lbWJlciAtIHRoZSBwcm9wZXJ0eSBuYW1lIG9mIGFuIGF0dHJpYnV0ZSBvciByZWxhdGlvbnNoaXAKICAgICAqLwogICAgcmVtb3ZlOiBmdW5jdGlvbiByZW1vdmUoYXR0cmlidXRlKSB7CiAgICAgIGlmIChFbWJlci5nZXQodGhpcywgJ2lzRW1wdHknKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5fcmVtb3ZlKGF0dHJpYnV0ZSk7CgogICAgICBpZiAoRW1iZXIuZ2V0KHRoaXMsICdpc0VtcHR5JykpIHsKICAgICAgICB0aGlzLl9yZWdpc3RlcmVkSGFuZGxlcnMgJiYgdGhpcy5fcmVnaXN0ZXJlZEhhbmRsZXJzLmJlY2FtZVZhbGlkKCk7CiAgICAgIH0KICAgIH0sCgogICAgLyoqCiAgICAgIFJlbW92ZXMgYWxsIGVycm9yIG1lc3NhZ2VzIGZyb20gdGhlIGdpdmVuIGF0dHJpYnV0ZSB3aXRob3V0IHNlbmRpbmcgZXZlbnQuCiAgICAgICBAbWV0aG9kIF9yZW1vdmUKICAgICAgQHByaXZhdGUKICAgICovCiAgICBfcmVtb3ZlOiBmdW5jdGlvbiBfcmVtb3ZlKGF0dHJpYnV0ZSkgewogICAgICBpZiAoRW1iZXIuZ2V0KHRoaXMsICdpc0VtcHR5JykpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBjb250ZW50ID0gdGhpcy5yZWplY3RCeSgnYXR0cmlidXRlJywgYXR0cmlidXRlKTsKICAgICAgRW1iZXIuZ2V0KHRoaXMsICdjb250ZW50Jykuc2V0T2JqZWN0cyhjb250ZW50KTsKICAgICAgRW1iZXIuZ2V0KHRoaXMsICdlcnJvcnNCeUF0dHJpYnV0ZU5hbWUnKS5kZWxldGUoYXR0cmlidXRlKTsKICAgICAgdGhpcy5ub3RpZnlQcm9wZXJ0eUNoYW5nZShhdHRyaWJ1dGUpOwogICAgICB0aGlzLm5vdGlmeVByb3BlcnR5Q2hhbmdlKCdsZW5ndGgnKTsKICAgIH0sCgogICAgLyoqCiAgICAgTWFudWFsbHkgY2xlYXJzIGFsbCBlcnJvcnMgZm9yIHRoZSByZWNvcmQuCiAgICAgICBUaGlzIHdpbGwgdHJhbnNpdGlvbiB0aGUgcmVjb3JkIGludG8gYSBgdmFsaWRgIHN0YXRlLCBhbmQKICAgICAgIHdpbGwgdHJpZ2dlciB0aGUgYGJlY2FtZVZhbGlkYCBldmVudCBhbmQgbGlmZWN5Y2xlIG1ldGhvZC4KICAgICBFeGFtcGxlOgogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IGVycm9ycyA9IGdldCgndXNlcicsIGVycm9ycyk7CiAgICAgZXJyb3JzLmFkZCgndXNlcm5hbWUnLCBbJ2Vycm9yLWEnXSk7CiAgICAgZXJyb3JzLmFkZCgncGhvbmUnLCBbJ2Vycm9yLTEnLCAnZXJyb3ItMiddKTsKICAgICAgZXJyb3JzLmVycm9yc0ZvcigndXNlcm5hbWUnKTsKICAgICAvLyA9PgogICAgIC8vIFsKICAgICAvLyAgIHsgYXR0cmlidXRlOiAndXNlcm5hbWUnLCBtZXNzYWdlOiAnZXJyb3ItYScgfSwKICAgICAvLyBdCiAgICAgIGVycm9ycy5lcnJvcnNGb3IoJ3Bob25lJyk7CiAgICAgLy8gPT4KICAgICAvLyBbCiAgICAgLy8gICB7IGF0dHJpYnV0ZTogJ3Bob25lJywgbWVzc2FnZTogJ2Vycm9yLTEnIH0sCiAgICAgLy8gICB7IGF0dHJpYnV0ZTogJ3Bob25lJywgbWVzc2FnZTogJ2Vycm9yLTInIH0sCiAgICAgLy8gXQogICAgICBlcnJvcnMuY2xlYXIoKTsKICAgICAgZXJyb3JzLmVycm9yc0ZvcigndXNlcm5hbWUnKTsKICAgICAvLyA9PiB1bmRlZmluZWQKICAgICAgZXJyb3JzLmVycm9yc0ZvcigncGhvbmUnKTsKICAgICAvLyA9PiB1bmRlZmluZWQKICAgICAgZXJyb3JzLmdldCgnbWVzc2FnZXMnKQogICAgIC8vID0+IFtdCiAgICAgYGBgCiAgICAgQG1ldGhvZCByZW1vdmUKICAgICAqLwogICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCkgewogICAgICBpZiAoRW1iZXIuZ2V0KHRoaXMsICdpc0VtcHR5JykpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuX2NsZWFyKCk7CgogICAgICB0aGlzLl9yZWdpc3RlcmVkSGFuZGxlcnMgJiYgdGhpcy5fcmVnaXN0ZXJlZEhhbmRsZXJzLmJlY2FtZVZhbGlkKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBSZW1vdmVzIGFsbCBlcnJvciBtZXNzYWdlcy4KICAgICAgdG8gdGhlIHJlY29yZC4KICAgICAgIEBtZXRob2QgX2NsZWFyCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX2NsZWFyOiBmdW5jdGlvbiBfY2xlYXIoKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CgogICAgICBpZiAoRW1iZXIuZ2V0KHRoaXMsICdpc0VtcHR5JykpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBlcnJvcnNCeUF0dHJpYnV0ZU5hbWUgPSBFbWJlci5nZXQodGhpcywgJ2Vycm9yc0J5QXR0cmlidXRlTmFtZScpOwogICAgICB2YXIgYXR0cmlidXRlcyA9IFtdOwogICAgICBlcnJvcnNCeUF0dHJpYnV0ZU5hbWUuZm9yRWFjaChmdW5jdGlvbiAoXywgYXR0cmlidXRlKSB7CiAgICAgICAgYXR0cmlidXRlcy5wdXNoKGF0dHJpYnV0ZSk7CiAgICAgIH0pOwogICAgICBlcnJvcnNCeUF0dHJpYnV0ZU5hbWUuY2xlYXIoKTsKICAgICAgYXR0cmlidXRlcy5mb3JFYWNoKGZ1bmN0aW9uIChhdHRyaWJ1dGUpIHsKICAgICAgICBfdGhpcy5ub3RpZnlQcm9wZXJ0eUNoYW5nZShhdHRyaWJ1dGUpOwogICAgICB9KTsKICAgICAgRW1iZXIuQXJyYXlQcm94eS5wcm90b3R5cGUuY2xlYXIuY2FsbCh0aGlzKTsKICAgIH0sCgogICAgLyoqCiAgICAgIENoZWNrcyBpZiB0aGVyZSBhcmUgZXJyb3IgbWVzc2FnZXMgZm9yIHRoZSBnaXZlbiBhdHRyaWJ1dGUuCiAgICAgICBgYGBhcHAvcm91dGVzL3VzZXIvZWRpdC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBhY3Rpb25zOiB7CiAgICAgICAgICBzYXZlOiBmdW5jdGlvbih1c2VyKSB7CiAgICAgICAgICAgIGlmICh1c2VyLmdldCgnZXJyb3JzJykuaGFzKCdlbWFpbCcpKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGFsZXJ0KCdQbGVhc2UgdXBkYXRlIHlvdXIgZW1haWwgYmVmb3JlIGF0dGVtcHRpbmcgdG8gc2F2ZS4nKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB1c2VyLnNhdmUoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgaGFzCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBhdHRyaWJ1dGUKICAgICAgQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiB0aGVyZSBzb21lIGVycm9ycyBvbiBnaXZlbiBhdHRyaWJ1dGUKICAgICovCiAgICBoYXM6IGZ1bmN0aW9uIGhhcyhhdHRyaWJ1dGUpIHsKICAgICAgcmV0dXJuIHRoaXMuZXJyb3JzRm9yKGF0dHJpYnV0ZSkubGVuZ3RoID4gMDsKICAgIH0KICB9KTsKCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KICAvLyBBbGwgbW9kZWxOYW1lcyBhcmUgZGFzaGVyaXplZCBpbnRlcm5hbGx5LiBDaGFuZ2luZyB0aGlzIGZ1bmN0aW9uIG1heQogIC8vIHJlcXVpcmUgY2hhbmdlcyB0byBvdGhlciBub3JtYWxpemF0aW9uIGhvb2tzIChzdWNoIGFzIHR5cGVGb3JSb290KS4KCiAgLyoqCiAgIFRoaXMgbWV0aG9kIG5vcm1hbGl6ZXMgYSBtb2RlbE5hbWUgaW50byB0aGUgZm9ybWF0IEVtYmVyIERhdGEgdXNlcwogICBpbnRlcm5hbGx5LgoKICAgIEBtZXRob2Qgbm9ybWFsaXplTW9kZWxOYW1lCiAgICBAcHVibGljCiAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICBAcmV0dXJuIHtTdHJpbmd9IG5vcm1hbGl6ZWRNb2RlbE5hbWUKICAqLwogIGZ1bmN0aW9uIG5vcm1hbGl6ZU1vZGVsTmFtZShtb2RlbE5hbWUpIHsKICAgIHJldHVybiBFbWJlci5TdHJpbmcuZGFzaGVyaXplKG1vZGVsTmFtZSk7CiAgfQoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICAvKioKICAgKiBUaGlzIHN5bWJvbCBwcm92aWRlcyBhIFN5bWJvbCByZXBsYWNlbWVudCBmb3IgYnJvd3NlcnMgdGhhdCBkbyBub3QgaGF2ZSBpdAogICAqIChlZy4gSUUgMTEpLgogICAqCiAgICogVGhlIHJlcGxhY2VtZW50IGlzIGRpZmZlcmVudCBmcm9tIHRoZSBuYXRpdmUgU3ltYm9sIGluIHNvbWUgd2F5cy4gSXQgaXMgYQogICAqIGZ1bmN0aW9uIHRoYXQgcHJvZHVjZXMgYW4gb3V0cHV0OgogICAqIC0gaXRlcmFibGU7CiAgICogLSB0aGF0IGlzIGEgc3RyaW5nLCBub3QgYSBzeW1ib2wuCiAgICoKICAgKiBAaW50ZXJuYWwKICAgKi8KICB2YXIgc3ltYm9sID0gdHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgPyBTeW1ib2wgOiBmdW5jdGlvbiAoa2V5KSB7CiAgICByZXR1cm4gIl9fIiArIGtleSArIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIERhdGUubm93KCkpICsgIl9fIjsKICB9OwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICAvKioKICAgKiBVc2UgdGhpcyBicmFuZCB0byBhc3NpZ24gYSBzdHJpbmcga2V5IHRvIGFuIGludGVyZmFjZQogICAqIGZvciBtYXBwaW5nIHRoZSBpbnRlcmZhY2UgdG8gYSB0aWdodGx5IGNvdXBsZWQgaW50ZXJuYWwKICAgKiBjbGFzcyBpbXBsZW1lbnRhdGlvbi4KICAgKgogICAqIFRoaXMgYWxsb3dzIHVzIHRvIGV4cG9zZSB0aGUgaW50ZXJmYWNlIHB1YmxpY2x5IGJ1dAogICAqIHNlYW1sZXNzbHkgdXBncmFkZSB0aGVzZSBpbnRlcmZhY2VzIGZvciBvdXIgb3duIHVzZQogICAqIGludGVybmFsbHkgd2hlbiBpbnRlcm5hbCBtZXRob2RzIGFuZCBwcm9wZXJ0aWVzIGFyZQogICAqIG5lZWRlZC4KICAgKgogICAqIEBpbnRlcm5hbAogICAqLwoKICB2YXIgQlJBTkRfU1lNQk9MID0gc3ltYm9sKCdERUJVRy10cy1icmFuZCcpOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICAvKioKICAgKiBDYXN0cyBhIHB1YmxpYyBpbnRlcmZhY2UgdG8gdGhlIG1hdGNoaW5nIGludGVybmFsIGNsYXNzIGltcGxlbWVudGF0aW9uCiAgICoKICAgKiBAaW50ZXJuYWwKICAgKi8KICBmdW5jdGlvbiB1cGdyYWRlRm9ySW50ZXJuYWwoZXh0ZXJuYWwpIHsKICAgIHJldHVybiBleHRlcm5hbDsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCiAgLy8gVXNlZCBieSB0aGUgc3RvcmUgdG8gbm9ybWFsaXplIElEcyBlbnRlcmluZyB0aGUgc3RvcmUuICBEZXNwaXRlIHRoZSBmYWN0CiAgLy8gdGhhdCBkZXZlbG9wZXJzIG1heSBwcm92aWRlIElEcyBhcyBudW1iZXJzIChlLmcuLCBgc3RvcmUuZmluZFJlY29yZCgncGVyc29uJywgMSlgKSwKICAvLyBpdCBpcyBpbXBvcnRhbnQgdGhhdCBpbnRlcm5hbGx5IHdlIHVzZSBzdHJpbmdzLCBzaW5jZSBJRHMgbWF5IGJlIHNlcmlhbGl6ZWQKICAvLyBhbmQgbG9zZSB0eXBlIGluZm9ybWF0aW9uLiAgRm9yIGV4YW1wbGUsIEVtYmVyJ3Mgcm91dGVyIG1heSBwdXQgYSByZWNvcmQncwogIC8vIElEIGludG8gdGhlIFVSTCwgYW5kIGlmIHdlIGxhdGVyIHRyeSB0byBkZXNlcmlhbGl6ZSB0aGF0IFVSTCBhbmQgZmluZCB0aGUKICAvLyBjb3JyZXNwb25kaW5nIHJlY29yZCwgd2Ugd2lsbCBub3Qga25vdyBpZiBpdCBpcyBhIHN0cmluZyBvciBhIG51bWJlci4KICBmdW5jdGlvbiBjb2VyY2VJZChpZCkgewogICAgaWYgKGlkID09PSBudWxsIHx8IGlkID09PSB1bmRlZmluZWQgfHwgaWQgPT09ICcnKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQoKICAgIGlmICh0eXBlb2YgaWQgPT09ICdzdHJpbmcnKSB7CiAgICAgIHJldHVybiBpZDsKICAgIH0KCiAgICBpZiAodHlwZW9mIGlkID09PSAnc3ltYm9sJykgewogICAgICByZXR1cm4gaWQudG9TdHJpbmcoKTsKICAgIH0KCiAgICByZXR1cm4gJycgKyBpZDsKICB9CgogIGZ1bmN0aW9uIGVuc3VyZVN0cmluZ0lkKGlkKSB7CiAgICB2YXIgbm9ybWFsaXplZCA9IG51bGw7CgogICAgaWYgKHR5cGVvZiBpZCA9PT0gJ3N0cmluZycpIHsKICAgICAgbm9ybWFsaXplZCA9IGlkLmxlbmd0aCA+IDAgPyBpZCA6IG51bGw7CiAgICB9IGVsc2UgaWYgKHR5cGVvZiBpZCA9PT0gJ251bWJlcicgJiYgIWlzTmFOKGlkKSkgewogICAgICBub3JtYWxpemVkID0gJycgKyBpZDsKICAgIH0KCiAgICByZXR1cm4gbm9ybWFsaXplZDsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCiAgLy8gc3VwcG9ydCBJRTExCiAgdmFyIENSWVBUTyA9IGZ1bmN0aW9uICgpIHsKICAgIHZhciBoYXNXaW5kb3cgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJzsKICAgIHZhciBpc0Zhc3RCb290ID0gdHlwZW9mIEZhc3RCb290ICE9PSAndW5kZWZpbmVkJzsKCiAgICBpZiAoaXNGYXN0Qm9vdCkgewogICAgICByZXR1cm4gewogICAgICAgIGdldFJhbmRvbVZhbHVlczogZnVuY3Rpb24gZ2V0UmFuZG9tVmFsdWVzKGJ1ZmZlcikgewogICAgICAgICAgcmV0dXJuIEZhc3RCb290LnJlcXVpcmUoJ2NyeXB0bycpLnJhbmRvbUZpbGxTeW5jKGJ1ZmZlcik7CiAgICAgICAgfQogICAgICB9OwogICAgfSBlbHNlIGlmIChoYXNXaW5kb3cgJiYgdHlwZW9mIHdpbmRvdy5jcnlwdG8gIT09ICd1bmRlZmluZWQnKSB7CiAgICAgIHJldHVybiB3aW5kb3cuY3J5cHRvOwogICAgfSBlbHNlIGlmIChoYXNXaW5kb3cgJiYgdHlwZW9mIHdpbmRvdy5tc0NyeXB0byAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHdpbmRvdy5tc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMgPT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuIHdpbmRvdy5tc0NyeXB0bzsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignZW1iZXItZGF0YTogQ2Fubm90IGZpbmQgYSB2YWxpZCB3YXkgdG8gZ2VuZXJhdGUgbG9jYWwgaWRlbnRpZmllcnMnKTsKICAgIH0KICB9KCk7IC8vIHdlIG1pZ2h0IGJlIGFibGUgdG8gb3B0aW1pemUgdGhpcyBieSByZXF1ZXN0aW5nIG1vcmUgYnl0ZXMgdGhhbiB3ZSBuZWVkIGF0IGEgdGltZQoKCiAgZnVuY3Rpb24gcm5nKCkgewogICAgLy8gV0hBVFdHIGNyeXB0byBSTkcgLSBodHRwOi8vd2lraS53aGF0d2cub3JnL3dpa2kvQ3J5cHRvCiAgICB2YXIgcm5kczggPSBuZXcgVWludDhBcnJheSgxNik7CiAgICByZXR1cm4gQ1JZUFRPLmdldFJhbmRvbVZhbHVlcyhybmRzOCk7CiAgfQogIC8qKgogICAqIENvbnZlcnQgYXJyYXkgb2YgMTYgYnl0ZSB2YWx1ZXMgdG8gVVVJRCBzdHJpbmcgZm9ybWF0IG9mIHRoZSBmb3JtOgogICAqIFhYWFhYWFhYLVhYWFgtWFhYWC1YWFhYLVhYWFhYWFhYWFhYWAogICAqLwoKCiAgdmFyIGJ5dGVUb0hleCA9IFtdOwoKICBmb3IgKHZhciBpID0gMDsgaSA8IDI1NjsgKytpKSB7CiAgICBieXRlVG9IZXhbaV0gPSAoaSArIDB4MTAwKS50b1N0cmluZygxNikuc3Vic3RyKDEpOwogIH0KCiAgZnVuY3Rpb24gYnl0ZXNUb1V1aWQoYnVmKSB7CiAgICB2YXIgYnRoID0gYnl0ZVRvSGV4OyAvLyBqb2luIHVzZWQgdG8gZml4IG1lbW9yeSBpc3N1ZSBjYXVzZWQgYnkgY29uY2F0ZW5hdGlvbjogaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MzE3NSNjNAoKICAgIHJldHVybiBbYnRoW2J1ZlswXV0sIGJ0aFtidWZbMV1dLCBidGhbYnVmWzJdXSwgYnRoW2J1ZlszXV0sICctJywgYnRoW2J1Zls0XV0sIGJ0aFtidWZbNV1dLCAnLScsIGJ0aFtidWZbNl1dLCBidGhbYnVmWzddXSwgJy0nLCBidGhbYnVmWzhdXSwgYnRoW2J1Zls5XV0sICctJywgYnRoW2J1ZlsxMF1dLCBidGhbYnVmWzExXV0sIGJ0aFtidWZbMTJdXSwgYnRoW2J1ZlsxM11dLCBidGhbYnVmWzE0XV0sIGJ0aFtidWZbMTVdXV0uam9pbignJyk7CiAgfQoKICBmdW5jdGlvbiB1dWlkdjQoKSB7CiAgICB2YXIgcm5kcyA9IHJuZygpOyAvLyBQZXIgNC40LCBzZXQgYml0cyBmb3IgdmVyc2lvbiBhbmQgYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgCgogICAgcm5kc1s2XSA9IHJuZHNbNl0gJiAweDBmIHwgMHg0MDsKICAgIHJuZHNbOF0gPSBybmRzWzhdICYgMHgzZiB8IDB4ODA7CiAgICByZXR1cm4gYnl0ZXNUb1V1aWQocm5kcyk7CiAgfQoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwogIHZhciBJREVOVElGSUVSUyA9IG5ldyBXZWFrTWFwKCk7CiAgZnVuY3Rpb24gaXNTdGFibGVJZGVudGlmaWVyKGlkZW50aWZpZXIpIHsKICAgIHJldHVybiBJREVOVElGSUVSUy5oYXMoaWRlbnRpZmllcik7CiAgfQogIGZ1bmN0aW9uIG1hcmtTdGFibGVJZGVudGlmaWVyKGlkZW50aWZpZXIpIHsKICAgIElERU5USUZJRVJTLnNldChpZGVudGlmaWVyLCAnaXMtaWRlbnRpZmllcicpOwogIH0KICBmdW5jdGlvbiB1bm1hcmtTdGFibGVJZGVudGlmaWVyKGlkZW50aWZpZXIpIHsKICAgIElERU5USUZJRVJTLmRlbGV0ZShpZGVudGlmaWVyKTsKICB9CgogIGZ1bmN0aW9uIGlzTm9uRW1wdHlTdHJpbmcoc3RyKSB7CiAgICByZXR1cm4gdHlwZW9mIHN0ciA9PT0gJ3N0cmluZycgJiYgc3RyLmxlbmd0aCA+IDA7CiAgfQoKICB2YXIgY29uZmlndXJlZEZvcmdldE1ldGhvZDsKICB2YXIgY29uZmlndXJlZEdlbmVyYXRpb25NZXRob2Q7CiAgdmFyIGNvbmZpZ3VyZWRSZXNldE1ldGhvZDsKICB2YXIgY29uZmlndXJlZFVwZGF0ZU1ldGhvZDsKICBmdW5jdGlvbiBzZXRJZGVudGlmaWVyR2VuZXJhdGlvbk1ldGhvZChtZXRob2QpIHsKICAgIGNvbmZpZ3VyZWRHZW5lcmF0aW9uTWV0aG9kID0gbWV0aG9kOwogIH0KICBmdW5jdGlvbiBzZXRJZGVudGlmaWVyVXBkYXRlTWV0aG9kKG1ldGhvZCkgewogICAgY29uZmlndXJlZFVwZGF0ZU1ldGhvZCA9IG1ldGhvZDsKICB9CiAgZnVuY3Rpb24gc2V0SWRlbnRpZmllckZvcmdldE1ldGhvZChtZXRob2QpIHsKICAgIGNvbmZpZ3VyZWRGb3JnZXRNZXRob2QgPSBtZXRob2Q7CiAgfQogIGZ1bmN0aW9uIHNldElkZW50aWZpZXJSZXNldE1ldGhvZChtZXRob2QpIHsKICAgIGNvbmZpZ3VyZWRSZXNldE1ldGhvZCA9IG1ldGhvZDsKICB9CgogIGZ1bmN0aW9uIGRlZmF1bHRHZW5lcmF0aW9uTWV0aG9kKGRhdGEsIGJ1Y2tldCkgewogICAgaWYgKGlzTm9uRW1wdHlTdHJpbmcoZGF0YS5saWQpKSB7CiAgICAgIHJldHVybiBkYXRhLmxpZDsKICAgIH0KCiAgICB2YXIgdHlwZSA9IGRhdGEudHlwZSwKICAgICAgICBpZCA9IGRhdGEuaWQ7CgogICAgaWYgKGlzTm9uRW1wdHlTdHJpbmcoaWQpKSB7CiAgICAgIHJldHVybiAiQGVtYmVyLWRhdGE6bGlkLSIgKyBub3JtYWxpemVNb2RlbE5hbWUodHlwZSkgKyAiLSIgKyBpZDsKICAgIH0KCiAgICByZXR1cm4gdXVpZHY0KCk7CiAgfQoKICB2YXIgSWRlbnRpZmllckNhY2hlcyA9IG5ldyBXZWFrTWFwKCk7CiAgZnVuY3Rpb24gaWRlbnRpZmllckNhY2hlRm9yKHN0b3JlKSB7CiAgICB2YXIgY2FjaGUgPSBJZGVudGlmaWVyQ2FjaGVzLmdldChzdG9yZSk7CgogICAgaWYgKGNhY2hlID09PSB1bmRlZmluZWQpIHsKICAgICAgY2FjaGUgPSBuZXcgSWRlbnRpZmllckNhY2hlKCk7CiAgICAgIElkZW50aWZpZXJDYWNoZXMuc2V0KHN0b3JlLCBjYWNoZSk7CiAgICB9CgogICAgcmV0dXJuIGNhY2hlOwogIH0KCiAgZnVuY3Rpb24gZGVmYXVsdEVtcHR5Q2FsbGJhY2soKSB7fQoKICB2YXIgSWRlbnRpZmllckNhY2hlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgLy8gVHlwZXNjcmlwdCBzdGlsbCBsZWFrcyBwcml2YXRlIHByb3BlcnRpZXMgaW4gdGhlIGZpbmFsCiAgICAvLyBjb21waWxlZCBjbGFzcywgc28gd2UgbWF5IHdhbnQgdG8gbW92ZSB0aGVzZSBmcm9tIF91bmRlcnNjb3JlCiAgICAvLyB0byBhIFdlYWtNYXAgdG8gYXZvaWQgbGVha2luZwogICAgLy8gY3VycmVudGx5IHdlIGxlYWsgdGhpcyBmb3IgdGVzdCBwdXJwb3NlcwogICAgZnVuY3Rpb24gSWRlbnRpZmllckNhY2hlKCkgewogICAgICB0aGlzLl9jYWNoZSA9IHsKICAgICAgICBsaWRzOiBPYmplY3QuY3JlYXRlKG51bGwpLAogICAgICAgIHR5cGVzOiBPYmplY3QuY3JlYXRlKG51bGwpCiAgICAgIH07CiAgICAgIHRoaXMuX2dlbmVyYXRlID0gdm9pZCAwOwogICAgICB0aGlzLl91cGRhdGUgPSB2b2lkIDA7CiAgICAgIHRoaXMuX2ZvcmdldCA9IHZvaWQgMDsKICAgICAgdGhpcy5fcmVzZXQgPSB2b2lkIDA7CiAgICAgIHRoaXMuX21lcmdlID0gdm9pZCAwOwogICAgICAvLyB3ZSBjYWNoZSB0aGUgdXNlciBjb25maWd1cmVkR2VuZXJhdGlvbk1ldGhvZCBhdCBpbml0IGJlY2F1c2UgaXQgbXVzdAogICAgICAvLyBiZSBjb25maWd1cmVkIHByaW9yIGFuZCBpcyBub3QgYWxsb3dlZCB0byBiZSBjaGFuZ2VkCiAgICAgIHRoaXMuX2dlbmVyYXRlID0gY29uZmlndXJlZEdlbmVyYXRpb25NZXRob2QgfHwgZGVmYXVsdEdlbmVyYXRpb25NZXRob2Q7CiAgICAgIHRoaXMuX3VwZGF0ZSA9IGNvbmZpZ3VyZWRVcGRhdGVNZXRob2QgfHwgZGVmYXVsdEVtcHR5Q2FsbGJhY2s7CiAgICAgIHRoaXMuX2ZvcmdldCA9IGNvbmZpZ3VyZWRGb3JnZXRNZXRob2QgfHwgZGVmYXVsdEVtcHR5Q2FsbGJhY2s7CiAgICAgIHRoaXMuX3Jlc2V0ID0gY29uZmlndXJlZFJlc2V0TWV0aG9kIHx8IGRlZmF1bHRFbXB0eUNhbGxiYWNrOwogICAgICB0aGlzLl9tZXJnZSA9IGRlZmF1bHRFbXB0eUNhbGxiYWNrOwogICAgfQogICAgLyoqCiAgICAgKiBob29rIHRvIGFsbG93IG1hbmFnZW1lbnQgb2YgbWVyZ2UgY29uZmxpY3RzIHdpdGggaWRlbnRpZmllcnMuCiAgICAgKgogICAgICogd2UgYWxsb3cgbGF0ZSBiaW5kaW5nIG9mIHRoaXMgcHJpdmF0ZSBpbnRlcm5hbCBtZXJnZSBzbyB0aGF0IGBpbnRlcm5hbE1vZGVsRmFjdG9yeWAKICAgICAqIGNhbiBpbnNlcnQgaXRzZWxmIGhlcmUgdG8gaGFuZGxlIGVsaW1pbmF0aW9uIG9mIGR1cGxpY2F0ZXMKICAgICAqCiAgICAgKiBAaW50ZXJuYWwKICAgICAqLwoKCiAgICB2YXIgX3Byb3RvID0gSWRlbnRpZmllckNhY2hlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uX19jb25maWd1cmVNZXJnZSA9IGZ1bmN0aW9uIF9fY29uZmlndXJlTWVyZ2UobWV0aG9kKSB7CiAgICAgIHRoaXMuX21lcmdlID0gbWV0aG9kIHx8IGRlZmF1bHRFbXB0eUNhbGxiYWNrOwogICAgfQogICAgLyoqCiAgICAgKiBAaW50ZXJuYWwKICAgICAqLwogICAgOwoKICAgIF9wcm90by5fZ2V0UmVjb3JkSWRlbnRpZmllciA9IGZ1bmN0aW9uIF9nZXRSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlLCBzaG91bGRHZW5lcmF0ZSkgewogICAgICBpZiAoc2hvdWxkR2VuZXJhdGUgPT09IHZvaWQgMCkgewogICAgICAgIHNob3VsZEdlbmVyYXRlID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIC8vIHNob3J0IGNpcmN1aXQgaWYgd2UncmUgYWxyZWFkeSB0aGUgc3RhYmxlIHZlcnNpb24KICAgICAgaWYgKGlzU3RhYmxlSWRlbnRpZmllcihyZXNvdXJjZSkpIHsKCiAgICAgICAgcmV0dXJuIHJlc291cmNlOwogICAgICB9IC8vIGB0eXBlYCBtdXN0IGFsd2F5cyBiZSBwcmVzZW50CgogICAgICB2YXIgdHlwZSA9IG5vcm1hbGl6ZU1vZGVsTmFtZShyZXNvdXJjZS50eXBlKTsKICAgICAgdmFyIGtleU9wdGlvbnMgPSBnZXRUeXBlSW5kZXgodGhpcy5fY2FjaGUudHlwZXMsIHR5cGUpOwogICAgICB2YXIgaWRlbnRpZmllcjsKICAgICAgdmFyIGxpZCA9IGNvZXJjZUlkKHJlc291cmNlLmxpZCk7CiAgICAgIHZhciBpZCA9IGNvZXJjZUlkKHJlc291cmNlLmlkKTsgLy8gZ28gc3RyYWlnaHQgZm9yIHRoZSBzdGFibGUgUmVjb3JkSWRlbnRpZmllciBrZXknZCB0byBgbGlkYAoKICAgICAgaWYgKGxpZCAhPT0gbnVsbCkgewogICAgICAgIGlkZW50aWZpZXIgPSBrZXlPcHRpb25zLmxpZFtsaWRdOwogICAgICB9IC8vIHdlIG1heSBoYXZlIG5vdCBzZWVuIHRoaXMgcmVzb3VyY2UgYmVmb3JlCiAgICAgIC8vIGJ1dCBqdXN0IGluIGNhc2Ugd2UgY2hlY2sgb3VyIG93biBzZWNvbmRhcnkgbG9va3VwIChgaWRgKQoKCiAgICAgIGlmIChpZGVudGlmaWVyID09PSB1bmRlZmluZWQgJiYgaWQgIT09IG51bGwpIHsKICAgICAgICBpZGVudGlmaWVyID0ga2V5T3B0aW9ucy5pZFtpZF07CiAgICAgIH0KCiAgICAgIGlmIChpZGVudGlmaWVyID09PSB1bmRlZmluZWQpIHsKICAgICAgICAvLyB3ZSBoYXZlIGRlZmluaXRlbHkgbm90IHNlZW4gdGhpcyByZXNvdXJjZSBiZWZvcmUKICAgICAgICAvLyBzbyB3ZSBhbGxvdyB0aGUgdXNlciBjb25maWd1cmVkIGBHZW5lcmF0aW9uTWV0aG9kYCB0byB0ZWxsIHVzCiAgICAgICAgdmFyIG5ld0xpZCA9IHRoaXMuX2dlbmVyYXRlKHJlc291cmNlLCAncmVjb3JkJyk7IC8vIHdlIGRvIHRoaXMgX2V2ZW5fIHdoZW4gYGxpZGAgaXMgcHJlc2VudCBiZWNhdXNlIHNlY29uZGFyeSBsb29rdXBzCiAgICAgICAgLy8gbWF5IG5lZWQgdG8gYmUgcG9wdWxhdGVkLCBidXQgd2UgZW5mb3JjZSBub3QgZ2l2aW5nIHVzIHNvbWV0aGluZwogICAgICAgIC8vIGRpZmZlcmVudCB0aGFuIGV4cGVjdGVkCgoKICAgICAgICBpZiAobGlkICE9PSBudWxsICYmIG5ld0xpZCAhPT0gbGlkKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIllvdSBzaG91bGQgbm90IGNoYW5nZSB0aGUgPGxpZD4gb2YgYSBSZWNvcmRJZGVudGlmaWVyIik7CiAgICAgICAgfSBlbHNlIGlmIChsaWQgPT09IG51bGwpIHsKICAgICAgICAgIC8vIGFsbG93IGNvbmZpZ3VyYXRpb24gdG8gdGVsbCB1cyB0aGF0IHdlIGhhdmUKICAgICAgICAgIC8vIHNlZW4gdGhpcyBgbGlkYCBiZWZvcmUuIEUuZy4gYSBzZWNvbmRhcnkgbG9va3VwCiAgICAgICAgICAvLyBjb25uZWN0cyB0aGlzIHJlc291cmNlIHRvIGEgcHJldmlvdXNseSBzZWVuCiAgICAgICAgICAvLyByZXNvdXJjZS4KICAgICAgICAgIGlkZW50aWZpZXIgPSBrZXlPcHRpb25zLmxpZFtuZXdMaWRdOwogICAgICAgIH0KCiAgICAgICAgaWYgKHNob3VsZEdlbmVyYXRlID09PSB0cnVlKSB7CiAgICAgICAgICBpZiAoaWRlbnRpZmllciA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIC8vIGlmIHdlIHN0aWxsIGRvbid0IGhhdmUgYW4gaWRlbnRpZmllciwgdGltZSB0byBnZW5lcmF0ZSBvbmUKICAgICAgICAgICAgaWRlbnRpZmllciA9IG1ha2VTdGFibGVSZWNvcmRJZGVudGlmaWVyKGlkLCB0eXBlLCBuZXdMaWQpOyAvLyBwb3B1bGF0ZSBvdXIgdW5pcXVlIHRhYmxlCgogICAgICAgICAgICB0aGlzLl9jYWNoZS5saWRzW2lkZW50aWZpZXIubGlkXSA9IGlkZW50aWZpZXI7IC8vIHBvcHVsYXRlIG91ciBwcmltYXJ5IGxvb2t1cCB0YWJsZQogICAgICAgICAgICAvLyBUT0RPIGNvbnNpZGVyIGhhdmluZyB0aGUgYGxpZGAgY2FjaGUgYmUKICAgICAgICAgICAgLy8gb25lIGxldmVsIHVwCgogICAgICAgICAgICBrZXlPcHRpb25zLmxpZFtpZGVudGlmaWVyLmxpZF0gPSBpZGVudGlmaWVyOyAvLyBUT0RPIGV4aXN0cyB0ZW1wb3JhcmlseSB0byBzdXBwb3J0IGBwZWVrQWxsYAogICAgICAgICAgICAvLyBidXQgbGlrZWx5IHRvIG1vdmUKCiAgICAgICAgICAgIGtleU9wdGlvbnMuX2FsbElkZW50aWZpZXJzLnB1c2goaWRlbnRpZmllcik7CiAgICAgICAgICB9IC8vIHBvcHVsYXRlIG91ciBvd24gc2Vjb25kYXJ5IGxvb2t1cCB0YWJsZQogICAgICAgICAgLy8gZXZlbiBmb3IgdGhlICJzdWNjZXNzZnVsIiBzZWNvbmRhcnkgbG9va3VwCiAgICAgICAgICAvLyBieSBgX2dlbmVyYXRlKClgLCBzaW5jZSB3ZSBtaXNzZWQgdGhlIGNhY2hlCiAgICAgICAgICAvLyBwcmV2aW91c2x5CiAgICAgICAgICAvLyB3ZSB1c2UgaWRlbnRpZmllci5pZCBpbnN0ZWFkIG9mIGlkIGhlcmUKICAgICAgICAgIC8vIGJlY2F1c2UgdGhleSBtYXkgbm90IG1hdGNoIGFuZCB3ZSBwcmVmZXIKICAgICAgICAgIC8vIHdoYXQgd2UndmUgc2V0IHZpYSByZXNvdXJjZSBkYXRhCgoKICAgICAgICAgIGlmIChpZGVudGlmaWVyLmlkICE9PSBudWxsKSB7CiAgICAgICAgICAgIGtleU9wdGlvbnMuaWRbaWRlbnRpZmllci5pZF0gPSBpZGVudGlmaWVyOyAvLyBUT0RPIGFsbG93IGZpbGxpbmcgb3V0IG9mIGBpZGAgaGVyZQogICAgICAgICAgICAvLyBmb3IgdGhlIGB1c2VybmFtZWAgbm9uLWNsaWVudCBjcmVhdGVkCiAgICAgICAgICAgIC8vIGNhc2UuCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gaWRlbnRpZmllcjsKICAgIH0KICAgIC8qKgogICAgICogYWxsb3dzIHVzIHRvIHBlZWsgd2l0aG91dCBnZW5lcmF0aW5nIHdoZW4gbmVlZGVkCiAgICAgKiB1c2VmdWwgZm9yIHRoZSAiY3JlYXRlIiBjYXNlIHdoZW4gd2UgbmVlZCB0byBzZWUgaWYKICAgICAqIHdlIGFyZSBhY2NpZGVudGFsbHkgb3ZlcndyaXR0aW5nIHNvbWV0aGluZwogICAgICoKICAgICAqIEBpbnRlcm5hbAogICAgICovCiAgICA7CgogICAgX3Byb3RvLnBlZWtSZWNvcmRJZGVudGlmaWVyID0gZnVuY3Rpb24gcGVla1JlY29yZElkZW50aWZpZXIocmVzb3VyY2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2dldFJlY29yZElkZW50aWZpZXIocmVzb3VyY2UsIGZhbHNlKTsKICAgIH0KICAgIC8qCiAgICAgIFJldHVybnMgdGhlIElkZW50aWZpZXIgZm9yIHRoZSBnaXZlbiBSZXNvdXJjZSwgY3JlYXRlcyBvbmUgaWYgaXQgZG9lcyBub3QgeWV0IGV4aXN0LgogICAgICAgU3BlY2lmaWNhbGx5IHRoaXMgbWVhbnMgdGhhdCB3ZToKICAgICAgIC0gdmFsaWRhdGUgdGhlIGBpZGAgYHR5cGVgIGFuZCBgbGlkYCBjb21ibyBhZ2FpbnN0IGtub3duIGlkZW50aWZpZXJzCiAgICAgIC0gcmV0dXJuIGFuIG9iamVjdCB3aXRoIGFuIGBsaWRgIHRoYXQgaXMgc3RhYmxlIChyZXBlYXRlZCBjYWxscyB3aXRoIHRoZSBzYW1lCiAgICAgICAgYGlkYCArIGB0eXBlYCBvciBgbGlkYCB3aWxsIHJldHVybiB0aGUgc2FtZSBgbGlkYCB2YWx1ZSkKICAgICAgLSB0aGlzIHJlZmVyZW50aWFsIHN0YWJpbGl0eSBvZiB0aGUgb2JqZWN0IGl0c2VsZiBpcyBndWFyYW50ZWVkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIgPSBmdW5jdGlvbiBnZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UpIHsKICAgICAgcmV0dXJuIHRoaXMuX2dldFJlY29yZElkZW50aWZpZXIocmVzb3VyY2UsIHRydWUpOwogICAgfQogICAgLyoKICAgICBSZXR1cm5zIGEgbmV3IElkZW50aWZpZXIgZm9yIHRoZSBzdXBwbGllZCBkYXRhLiBDYWxsIHRoaXMgbWV0aG9kIHRvIGdlbmVyYXRlCiAgICAgYW4gaWRlbnRpZmllciB3aGVuIGEgbmV3IHJlc291cmNlIGlzIGJlaW5nIGNyZWF0ZWQgbG9jYWwgdG8gdGhlIGNsaWVudCBhbmQKICAgICBwb3RlbnRpYWxseSBkb2VzIG5vdCBoYXZlIGFuIGBpZGAuCiAgICAgIERlbGVnYXRlcyBnZW5lcmF0aW9uIHRvIHRoZSB1c2VyIHN1cHBsaWVkIGBHZW5lcmF0ZU1ldGhvZGAgaWYgb25lIGhhcyBiZWVuIHByb3ZpZGVkCiAgICAgd2l0aCB0aGUgc2lnbmF0dXJlIGBnZW5lcmF0ZU1ldGhvZCh7IHR5cGUgfSwgJ3JlY29yZCcpYC4KICAgICAqLwogICAgOwoKICAgIF9wcm90by5jcmVhdGVJZGVudGlmaWVyRm9yTmV3UmVjb3JkID0gZnVuY3Rpb24gY3JlYXRlSWRlbnRpZmllckZvck5ld1JlY29yZChkYXRhKSB7CiAgICAgIHZhciBuZXdMaWQgPSB0aGlzLl9nZW5lcmF0ZShkYXRhLCAncmVjb3JkJyk7CgogICAgICB2YXIgaWRlbnRpZmllciA9IG1ha2VTdGFibGVSZWNvcmRJZGVudGlmaWVyKGRhdGEuaWQgfHwgbnVsbCwgZGF0YS50eXBlLCBuZXdMaWQpOwogICAgICB2YXIga2V5T3B0aW9ucyA9IGdldFR5cGVJbmRleCh0aGlzLl9jYWNoZS50eXBlcywgZGF0YS50eXBlKTsgLy8gcG9wdWxhdGUgb3VyIHVuaXF1ZSB0YWJsZQoKICAgICAgdGhpcy5fY2FjaGUubGlkc1tpZGVudGlmaWVyLmxpZF0gPSBpZGVudGlmaWVyOyAvLyBwb3B1bGF0ZSB0aGUgdHlwZStsaWQgY2FjaGUKCiAgICAgIGtleU9wdGlvbnMubGlkW25ld0xpZF0gPSBpZGVudGlmaWVyOyAvLyBlbnN1cmUgYSBwZWVrQWxsIHNlZXMgb3VyIG5ldyBpZGVudGlmaWVyIHRvbwogICAgICAvLyBUT0RPIG1vdmUgdGhpcyBvdXR0YSBoZXJlPwoKICAgICAga2V5T3B0aW9ucy5fYWxsSWRlbnRpZmllcnMucHVzaChpZGVudGlmaWVyKTsKCiAgICAgIHJldHVybiBpZGVudGlmaWVyOwogICAgfQogICAgLyoKICAgICBQcm92aWRlcyB0aGUgb3Bwb3J0dW5pdHkgdG8gdXBkYXRlIHNlY29uZGFyeSBsb29rdXAgdGFibGVzIGZvciBleGlzdGluZyBpZGVudGlmaWVycwogICAgIENhbGxlZCBhZnRlciBhbiBpZGVudGlmaWVyIGNyZWF0ZWQgd2l0aCBgY3JlYXRlSWRlbnRpZmllckZvck5ld1JlY29yZGAgaGFzIGJlZW4KICAgICBjb21taXR0ZWQuCiAgICAgIEFzc2lnbmVkIGBpZGAgdG8gYW4gYElkZW50aWZpZXJgIGlmIGBpZGAgaGFzIG5vdCBwcmV2aW91c2x5IGV4aXN0ZWQ7IGhvd2V2ZXIsCiAgICAgYXR0ZW1wdGluZyB0byBjaGFuZ2UgdGhlIGBpZGAgb3IgY2FsbGluZyB1cGRhdGUgd2l0aG91dCBwcm92aWRpbmcgYW4gYGlkYCB3aGVuCiAgICAgb25lIGlzIG1pc3Npbmcgd2lsbCB0aHJvdyBhbiBlcnJvci4KICAgICAgIC0gc2V0cyBgaWRgIChpZiBgaWRgIHdhcyBwcmV2aW91c2x5IGBudWxsYCkKICAgICAgLSBgbGlkYCBhbmQgYHR5cGVgIE1VU1QgTk9UIGJlIGFsdGVyZWQgcG9zdCBjcmVhdGlvbgogICAgICAgSWYgYSBtZXJnZSBvY2N1cnMsIGl0IGlzIHBvc3NpYmxlIHRoZSByZXR1cm5lZCBpZGVudGlmaWVyIGRvZXMgbm90IG1hdGNoIHRoZSBvcmlnaW5hbGx5CiAgICAgIHByb3ZpZGVkIGlkZW50aWZpZXIuIEluIHRoaXMgY2FzZSB0aGUgYWJhbmRvbmVkIGlkZW50aWZpZXIgd2lsbCBnbyB0aHJvdWdoIHRoZSB1c3VhbAogICAgICBgZm9yZ2V0UmVjb3JkSWRlbnRpZmllcmAgY29kZXBhdGhzLgogICAgKi8KICAgIDsKCiAgICBfcHJvdG8udXBkYXRlUmVjb3JkSWRlbnRpZmllciA9IGZ1bmN0aW9uIHVwZGF0ZVJlY29yZElkZW50aWZpZXIoaWRlbnRpZmllck9iamVjdCwgZGF0YSkgewogICAgICB2YXIgaWRlbnRpZmllciA9IHRoaXMuZ2V0T3JDcmVhdGVSZWNvcmRJZGVudGlmaWVyKGlkZW50aWZpZXJPYmplY3QpOwogICAgICB2YXIgaWQgPSBpZGVudGlmaWVyLmlkOwogICAgICB2YXIgbmV3SWQgPSBjb2VyY2VJZChkYXRhLmlkKTsKICAgICAgdmFyIGtleU9wdGlvbnMgPSBnZXRUeXBlSW5kZXgodGhpcy5fY2FjaGUudHlwZXMsIGlkZW50aWZpZXIudHlwZSk7CiAgICAgIHZhciBleGlzdGluZ0lkZW50aWZpZXIgPSBkZXRlY3RNZXJnZShrZXlPcHRpb25zLCBpZGVudGlmaWVyLCBuZXdJZCk7CgogICAgICBpZiAoZXhpc3RpbmdJZGVudGlmaWVyKSB7CiAgICAgICAgaWRlbnRpZmllciA9IHRoaXMuX21lcmdlUmVjb3JkSWRlbnRpZmllcnMoa2V5T3B0aW9ucywgaWRlbnRpZmllciwgZXhpc3RpbmdJZGVudGlmaWVyLCBkYXRhLCBuZXdJZCk7CiAgICAgIH0KCiAgICAgIGlkID0gaWRlbnRpZmllci5pZDsKICAgICAgcGVyZm9ybVJlY29yZElkZW50aWZpZXJVcGRhdGUoaWRlbnRpZmllciwgZGF0YSwgdGhpcy5fdXBkYXRlKTsKICAgICAgbmV3SWQgPSBpZGVudGlmaWVyLmlkOyAvLyBhZGQgdG8gb3VyIG93biBzZWNvbmRhcnkgbG9va3VwIHRhYmxlCgogICAgICBpZiAoaWQgIT09IG5ld0lkICYmIG5ld0lkICE9PSBudWxsKSB7CiAgICAgICAgdmFyIF9rZXlPcHRpb25zID0gZ2V0VHlwZUluZGV4KHRoaXMuX2NhY2hlLnR5cGVzLCBpZGVudGlmaWVyLnR5cGUpOwoKICAgICAgICBfa2V5T3B0aW9ucy5pZFtuZXdJZF0gPSBpZGVudGlmaWVyOwoKICAgICAgICBpZiAoaWQgIT09IG51bGwpIHsKICAgICAgICAgIGRlbGV0ZSBfa2V5T3B0aW9ucy5pZFtpZF07CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gaWRlbnRpZmllcjsKICAgIH07CgogICAgX3Byb3RvLl9tZXJnZVJlY29yZElkZW50aWZpZXJzID0gZnVuY3Rpb24gX21lcmdlUmVjb3JkSWRlbnRpZmllcnMoa2V5T3B0aW9ucywgaWRlbnRpZmllciwgZXhpc3RpbmdJZGVudGlmaWVyLCBkYXRhLCBuZXdJZCkgewogICAgICAvLyBkZWxlZ2F0ZSBkZXRlcm1pbmluZyB3aGljaCBpZGVudGlmaWVyIHRvIGtlZXAgdG8gdGhlIGNvbmZpZ3VyZWQgTWVyZ2VNZXRob2QKICAgICAgdmFyIGtlcHQgPSB0aGlzLl9tZXJnZShpZGVudGlmaWVyLCBleGlzdGluZ0lkZW50aWZpZXIsIGRhdGEpOwoKICAgICAgdmFyIGFiYW5kb25lZCA9IGtlcHQgPT09IGlkZW50aWZpZXIgPyBleGlzdGluZ0lkZW50aWZpZXIgOiBpZGVudGlmaWVyOyAvLyBjbGVhbnVwIHRoZSBpZGVudGlmaWVyIHdlIG5vIGxvbmdlciBuZWVkCgogICAgICB0aGlzLmZvcmdldFJlY29yZElkZW50aWZpZXIoYWJhbmRvbmVkKTsgLy8gZW5zdXJlIGEgc2Vjb25kYXJ5IGNhY2hlIGVudHJ5IGZvciB0aGlzIGlkIGZvciB0aGUgaWRlbnRpZmllciB3ZSBkbyBrZWVwCgogICAgICBrZXlPcHRpb25zLmlkW25ld0lkXSA9IGtlcHQ7IC8vIG1ha2Ugc3VyZSB0aGF0IHRoZSBgbGlkYCBvbiB0aGUgZGF0YSB3ZSBhcmUgcHJvY2Vzc2luZyBtYXRjaGVzIHRoZSBsaWQgd2Uga2VwdAoKICAgICAgZGF0YS5saWQgPSBrZXB0LmxpZDsKICAgICAgcmV0dXJuIGtlcHQ7CiAgICB9CiAgICAvKgogICAgIFByb3ZpZGVzIHRoZSBvcHBvcnR1bml0eSB0byBlbGltaW5hdGUgYW4gaWRlbnRpZmllciBmcm9tIHNlY29uZGFyeSBsb29rdXAgdGFibGVzCiAgICAgYXMgd2VsbCBhcyBlbGltaW5hdGVzIGl0IGZyb20gZW1iZXItZGF0YSdzIG93biBsb29rdXAgdGFibGVzIGFuZCBib29rIGtlZXBpbmcuCiAgICAgIFVzZWZ1bCB3aGVuIGEgcmVjb3JkIGhhcyBiZWVuIGRlbGV0ZWQgYW5kIHRoZSBkZWxldGlvbiBoYXMgYmVlbiBwZXJzaXN0ZWQgYW5kCiAgICAgd2UgZG8gbm90IGNhcmUgYWJvdXQgdGhlIHJlY29yZCBhbnltb3JlLiBFc3BlY2lhbGx5IHVzZWZ1bCB3aGVuIGFuIGBpZGAgb2YgYQogICAgIGRlbGV0ZWQgcmVjb3JkIG1pZ2h0IGJlIHJldXNlZCBsYXRlciBmb3IgYSBuZXcgcmVjb3JkLgogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZm9yZ2V0UmVjb3JkSWRlbnRpZmllciA9IGZ1bmN0aW9uIGZvcmdldFJlY29yZElkZW50aWZpZXIoaWRlbnRpZmllck9iamVjdCkgewogICAgICB2YXIgaWRlbnRpZmllciA9IHRoaXMuZ2V0T3JDcmVhdGVSZWNvcmRJZGVudGlmaWVyKGlkZW50aWZpZXJPYmplY3QpOwogICAgICB2YXIga2V5T3B0aW9ucyA9IGdldFR5cGVJbmRleCh0aGlzLl9jYWNoZS50eXBlcywgaWRlbnRpZmllci50eXBlKTsKCiAgICAgIGlmIChpZGVudGlmaWVyLmlkICE9PSBudWxsKSB7CiAgICAgICAgZGVsZXRlIGtleU9wdGlvbnMuaWRbaWRlbnRpZmllci5pZF07CiAgICAgIH0KCiAgICAgIGRlbGV0ZSB0aGlzLl9jYWNoZS5saWRzW2lkZW50aWZpZXIubGlkXTsKICAgICAgZGVsZXRlIGtleU9wdGlvbnMubGlkW2lkZW50aWZpZXIubGlkXTsKCiAgICAgIHZhciBpbmRleCA9IGtleU9wdGlvbnMuX2FsbElkZW50aWZpZXJzLmluZGV4T2YoaWRlbnRpZmllcik7CgogICAgICBrZXlPcHRpb25zLl9hbGxJZGVudGlmaWVycy5zcGxpY2UoaW5kZXgsIDEpOwoKICAgICAgdW5tYXJrU3RhYmxlSWRlbnRpZmllcihpZGVudGlmaWVyT2JqZWN0KTsKCiAgICAgIHRoaXMuX2ZvcmdldChpZGVudGlmaWVyLCAncmVjb3JkJyk7CiAgICB9OwoKICAgIF9wcm90by5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdGhpcy5fcmVzZXQoKTsKICAgIH07CgogICAgcmV0dXJuIElkZW50aWZpZXJDYWNoZTsKICB9KCk7CgogIGZ1bmN0aW9uIGdldFR5cGVJbmRleCh0eXBlTWFwLCB0eXBlKSB7CiAgICB2YXIgdHlwZUluZGV4ID0gdHlwZU1hcFt0eXBlXTsKCiAgICBpZiAodHlwZUluZGV4ID09PSB1bmRlZmluZWQpIHsKICAgICAgdHlwZUluZGV4ID0gewogICAgICAgIGxpZDogT2JqZWN0LmNyZWF0ZShudWxsKSwKICAgICAgICBpZDogT2JqZWN0LmNyZWF0ZShudWxsKSwKICAgICAgICBfYWxsSWRlbnRpZmllcnM6IFtdCiAgICAgIH07CiAgICAgIHR5cGVNYXBbdHlwZV0gPSB0eXBlSW5kZXg7CiAgICB9CgogICAgcmV0dXJuIHR5cGVJbmRleDsKICB9CgogIGZ1bmN0aW9uIG1ha2VTdGFibGVSZWNvcmRJZGVudGlmaWVyKGlkLCB0eXBlLCBsaWQsIGJ1Y2tldCwgY2xpZW50T3JpZ2luYXRlZCkgewoKICAgIHZhciByZWNvcmRJZGVudGlmaWVyID0gewogICAgICBsaWQ6IGxpZCwKICAgICAgaWQ6IGlkLAogICAgICB0eXBlOiB0eXBlCiAgICB9OwogICAgbWFya1N0YWJsZUlkZW50aWZpZXIocmVjb3JkSWRlbnRpZmllcik7CgogICAgcmV0dXJuIHJlY29yZElkZW50aWZpZXI7CiAgfQoKICBmdW5jdGlvbiBwZXJmb3JtUmVjb3JkSWRlbnRpZmllclVwZGF0ZShpZGVudGlmaWVyLCBkYXRhLCB1cGRhdGVGbikgewogICAgdmFyIGlkID0gZGF0YS5pZCwKICAgICAgICBsaWQgPSBkYXRhLmxpZDsKICAgIHZhciB0eXBlID0gbm9ybWFsaXplTW9kZWxOYW1lKGRhdGEudHlwZSk7CgogICAgewogICAgICB1cGRhdGVGbihpZGVudGlmaWVyLCBkYXRhLCAncmVjb3JkJyk7CiAgICB9IC8vIHVwZ3JhZGUgdGhlIElELCB0aGlzIGlzIGEgIm9uZSB0aW1lIG9ubHkiIGFiaWxpdHkKICAgIC8vIGZvciB0aGUgbXVsdGlwbGUtY2FjaGUta2V5IHNjZW5hcmlvIHdlICJjb3VsZCIKICAgIC8vIHVzZSBhIGhldXJpc3RpYyB0byBndWVzcyB0aGUgYmVzdCBpZCBmb3IgZGlzcGxheQogICAgLy8gKHVzdWFsbHkgd2hlbiBgZGF0YS5pZGAgaXMgYXZhaWxhYmxlIGFuZCBgZGF0YS5hdHRyaWJ1dGVzYCBpcyBub3QpCgoKICAgIGlmIChpZCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGlkZW50aWZpZXIuaWQgPSBjb2VyY2VJZChpZCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBkZXRlY3RNZXJnZShrZXlPcHRpb25zLCBpZGVudGlmaWVyLCBuZXdJZCkgewogICAgdmFyIGlkID0gaWRlbnRpZmllci5pZDsKCiAgICBpZiAoaWQgIT09IG51bGwgJiYgaWQgIT09IG5ld0lkICYmIG5ld0lkICE9PSBudWxsKSB7CiAgICAgIHZhciBleGlzdGluZ0lkZW50aWZpZXIgPSBrZXlPcHRpb25zLmlkW25ld0lkXTsKICAgICAgcmV0dXJuIGV4aXN0aW5nSWRlbnRpZmllciAhPT0gdW5kZWZpbmVkID8gZXhpc3RpbmdJZGVudGlmaWVyIDogZmFsc2U7CiAgICB9CgogICAgcmV0dXJuIGZhbHNlOwogIH0KCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KICAvKgogICAgVGhpcyBmaWxlIGVuY2Fwc3VsYXRlcyB0aGUgdmFyaW91cyBzdGF0ZXMgdGhhdCBhIHJlY29yZCBjYW4gdHJhbnNpdGlvbgogICAgdGhyb3VnaCBkdXJpbmcgaXRzIGxpZmVjeWNsZS4KICAqLwoKICAvKioKICAgICMjIyBTdGF0ZQoKICAgIEVhY2ggcmVjb3JkIGhhcyBhIGBjdXJyZW50U3RhdGVgIHByb3BlcnR5IHRoYXQgZXhwbGljaXRseSB0cmFja3Mgd2hhdAogICAgc3RhdGUgYSByZWNvcmQgaXMgaW4gYXQgYW55IGdpdmVuIHRpbWUuIEZvciBpbnN0YW5jZSwgaWYgYSByZWNvcmQgaXMKICAgIG5ld2x5IGNyZWF0ZWQgYW5kIGhhcyBub3QgeWV0IGJlZW4gc2VudCB0byB0aGUgYWRhcHRlciB0byBiZSBzYXZlZCwKICAgIGl0IHdvdWxkIGJlIGluIHRoZSBgcm9vdC5sb2FkZWQuY3JlYXRlZC51bmNvbW1pdHRlZGAgc3RhdGUuICBJZiBhCiAgICByZWNvcmQgaGFzIGhhZCBsb2NhbCBtb2RpZmljYXRpb25zIG1hZGUgdG8gaXQgdGhhdCBhcmUgaW4gdGhlCiAgICBwcm9jZXNzIG9mIGJlaW5nIHNhdmVkLCB0aGUgcmVjb3JkIHdvdWxkIGJlIGluIHRoZQogICAgYHJvb3QubG9hZGVkLnVwZGF0ZWQuaW5GbGlnaHRgIHN0YXRlLiAoVGhpcyBzdGF0ZSBwYXRoIHdpbGwgYmUKICAgIGV4cGxhaW5lZCBpbiBtb3JlIGRldGFpbCBiZWxvdy4pCgogICAgRXZlbnRzIGFyZSBzZW50IGJ5IHRoZSByZWNvcmQgb3IgaXRzIHN0b3JlIHRvIHRoZSByZWNvcmQncwogICAgYGN1cnJlbnRTdGF0ZWAgcHJvcGVydHkuIEhvdyB0aGUgc3RhdGUgcmVhY3RzIHRvIHRoZXNlIGV2ZW50cyBpcwogICAgZGVwZW5kZW50IG9uIHdoaWNoIHN0YXRlIGl0IGlzIGluLiBJbiBzb21lIHN0YXRlcywgY2VydGFpbiBldmVudHMKICAgIHdpbGwgYmUgaW52YWxpZCBhbmQgd2lsbCBjYXVzZSBhbiBleGNlcHRpb24gdG8gYmUgcmFpc2VkLgoKICAgIFN0YXRlcyBhcmUgaGllcmFyY2hpY2FsIGFuZCBldmVyeSBzdGF0ZSBpcyBhIHN1Yi1zdGF0ZSBvZiB0aGUKICAgIGBSb290U3RhdGVgLiBGb3IgZXhhbXBsZSwgYSByZWNvcmQgY2FuIGJlIGluIHRoZQogICAgYHJvb3QuZGVsZXRlZC51bmNvbW1pdHRlZGAgc3RhdGUgdGhlbiB0cmFuc2l0aW9ucyBpbnRvIHRoZQogICAgYHJvb3QuZGVsZXRlZC5pbkZsaWdodGAgc3RhdGUuIElmIGEgY2hpbGQgc3RhdGUgZG9lcyBub3QgaW1wbGVtZW50CiAgICBhbiBldmVudCBoYW5kbGVyLCB0aGUgc3RhdGUgbWFuYWdlciB3aWxsIGF0dGVtcHQgdG8gaW52b2tlIHRoZSBldmVudAogICAgb24gYWxsIHBhcmVudCBzdGF0ZXMgdW50aWwgdGhlIHJvb3Qgc3RhdGUgaXMgcmVhY2hlZC4gVGhlIHN0YXRlCiAgICBoaWVyYXJjaHkgb2YgYSByZWNvcmQgaXMgZGVzY3JpYmVkIGluIHRlcm1zIG9mIGEgcGF0aCBzdHJpbmcuIFlvdQogICAgY2FuIGRldGVybWluZSBhIHJlY29yZCdzIGN1cnJlbnQgc3RhdGUgYnkgZ2V0dGluZyB0aGUgc3RhdGUncwogICAgYHN0YXRlTmFtZWAgcHJvcGVydHk6CgogICAgYGBgamF2YXNjcmlwdAogICAgcmVjb3JkLmdldCgnY3VycmVudFN0YXRlLnN0YXRlTmFtZScpOwogICAgLy89PiAicm9vdC5jcmVhdGVkLnVuY29tbWl0dGVkIgogICAgIGBgYAoKICAgIFRoZSBoaWVyYXJjaHkgb2YgdmFsaWQgc3RhdGVzIHRoYXQgc2hpcCB3aXRoIGVtYmVyIGRhdGEgbG9va3MgbGlrZQogICAgdGhpczoKCiAgICBgYGB0ZXh0CiAgICAqIHJvb3QKICAgICAgKiBkZWxldGVkCiAgICAgICAgKiBzYXZlZAogICAgICAgICogdW5jb21taXR0ZWQKICAgICAgICAqIGluRmxpZ2h0CiAgICAgICogZW1wdHkKICAgICAgKiBsb2FkZWQKICAgICAgICAqIGNyZWF0ZWQKICAgICAgICAgICogdW5jb21taXR0ZWQKICAgICAgICAgICogaW5GbGlnaHQKICAgICAgICAqIHNhdmVkCiAgICAgICAgKiB1cGRhdGVkCiAgICAgICAgICAqIHVuY29tbWl0dGVkCiAgICAgICAgICAqIGluRmxpZ2h0CiAgICAgICogbG9hZGluZwogICAgYGBgCgogICAgVGhlIGBNb2RlbGAgc3RhdGVzIGFyZSB0aGVtc2VsdmVzIHN0YXRlbGVzcy4gV2hhdCB0aGF0IG1lYW5zIGlzCiAgICB0aGF0LCB0aGUgaGllcmFyY2hpY2FsIHN0YXRlcyB0aGF0IGVhY2ggb2YgKnRob3NlKiBwb2ludHMgdG8gaXMgYQogICAgc2hhcmVkIGRhdGEgc3RydWN0dXJlLiBGb3IgcGVyZm9ybWFuY2UgcmVhc29ucywgaW5zdGVhZCBvZiBlYWNoCiAgICByZWNvcmQgZ2V0dGluZyBpdHMgb3duIGNvcHkgb2YgdGhlIGhpZXJhcmNoeSBvZiBzdGF0ZXMsIGVhY2ggcmVjb3JkCiAgICBwb2ludHMgdG8gdGhpcyBnbG9iYWwsIGltbXV0YWJsZSBzaGFyZWQgaW5zdGFuY2UuIEhvdyBkb2VzIGEgc3RhdGUKICAgIGtub3cgd2hpY2ggcmVjb3JkIGl0IHNob3VsZCBiZSBhY3Rpbmcgb24/IFdlIHBhc3MgdGhlIHJlY29yZAogICAgaW5zdGFuY2UgaW50byB0aGUgc3RhdGUncyBldmVudCBoYW5kbGVycyBhcyB0aGUgZmlyc3QgYXJndW1lbnQuCgogICAgVGhlIHJlY29yZCBwYXNzZWQgYXMgdGhlIGZpcnN0IHBhcmFtZXRlciBpcyB3aGVyZSB5b3Ugc2hvdWxkIHN0YXNoCiAgICBzdGF0ZSBhYm91dCB0aGUgcmVjb3JkIGlmIG5lZWRlZDsgeW91IHNob3VsZCBuZXZlciBzdG9yZSBkYXRhIG9uIHRoZSBzdGF0ZQogICAgb2JqZWN0IGl0c2VsZi4KCiAgICAjIyMgRXZlbnRzIGFuZCBGbGFncwoKICAgIEEgc3RhdGUgbWF5IGltcGxlbWVudCB6ZXJvIG9yIG1vcmUgZXZlbnRzIGFuZCBmbGFncy4KCiAgICAjIyMjIEV2ZW50cwoKICAgIEV2ZW50cyBhcmUgbmFtZWQgZnVuY3Rpb25zIHRoYXQgYXJlIGludm9rZWQgd2hlbiBzZW50IHRvIGEgcmVjb3JkLiBUaGUKICAgIHJlY29yZCB3aWxsIGZpcnN0IGxvb2sgZm9yIGEgbWV0aG9kIHdpdGggdGhlIGdpdmVuIG5hbWUgb24gdGhlCiAgICBjdXJyZW50IHN0YXRlLiBJZiBubyBtZXRob2QgaXMgZm91bmQsIGl0IHdpbGwgc2VhcmNoIHRoZSBjdXJyZW50CiAgICBzdGF0ZSdzIHBhcmVudCwgYW5kIHRoZW4gaXRzIGdyYW5kcGFyZW50LCBhbmQgc28gb24gdW50aWwgcmVhY2hpbmcKICAgIHRoZSB0b3Agb2YgdGhlIGhpZXJhcmNoeS4gSWYgdGhlIHJvb3QgaXMgcmVhY2hlZCB3aXRob3V0IGFuIGV2ZW50CiAgICBoYW5kbGVyIGJlaW5nIGZvdW5kLCBhbiBleGNlcHRpb24gd2lsbCBiZSByYWlzZWQuIFRoaXMgY2FuIGJlIHZlcnkKICAgIGhlbHBmdWwgd2hlbiBkZWJ1Z2dpbmcgbmV3IGZlYXR1cmVzLgoKICAgIEhlcmUncyBhbiBleGFtcGxlIGltcGxlbWVudGF0aW9uIG9mIGEgc3RhdGUgd2l0aCBhIGBteUV2ZW50YCBldmVudCBoYW5kbGVyOgoKICAgIGBgYGphdmFzY3JpcHQKICAgIGFTdGF0ZTogU3RhdGUuY3JlYXRlKHsKICAgICAgbXlFdmVudDogZnVuY3Rpb24obWFuYWdlciwgcGFyYW0pIHsKICAgICAgICBjb25zb2xlLmxvZygiUmVjZWl2ZWQgbXlFdmVudCB3aXRoIiwgcGFyYW0pOwogICAgICB9CiAgICB9KQogICAgYGBgCgogICAgVG8gdHJpZ2dlciB0aGlzIGV2ZW50OgoKICAgIGBgYGphdmFzY3JpcHQKICAgIHJlY29yZC5zZW5kKCdteUV2ZW50JywgJ2ZvbycpOwogICAgLy89PiAiUmVjZWl2ZWQgbXlFdmVudCB3aXRoIGZvbyIKICAgIGBgYAoKICAgIE5vdGUgdGhhdCBhbiBvcHRpb25hbCBwYXJhbWV0ZXIgY2FuIGJlIHNlbnQgdG8gYSByZWNvcmQncyBgc2VuZCgpYCBtZXRob2QsCiAgICB3aGljaCB3aWxsIGJlIHBhc3NlZCBhcyB0aGUgc2Vjb25kIHBhcmFtZXRlciB0byB0aGUgZXZlbnQgaGFuZGxlci4KCiAgICBFdmVudHMgc2hvdWxkIHRyYW5zaXRpb24gdG8gYSBkaWZmZXJlbnQgc3RhdGUgaWYgYXBwcm9wcmlhdGUuIFRoaXMgY2FuIGJlCiAgICBkb25lIGJ5IGNhbGxpbmcgdGhlIHJlY29yZCdzIGB0cmFuc2l0aW9uVG8oKWAgbWV0aG9kIHdpdGggYSBwYXRoIHRvIHRoZQogICAgZGVzaXJlZCBzdGF0ZS4gVGhlIHN0YXRlIG1hbmFnZXIgd2lsbCBhdHRlbXB0IHRvIHJlc29sdmUgdGhlIHN0YXRlIHBhdGgKICAgIHJlbGF0aXZlIHRvIHRoZSBjdXJyZW50IHN0YXRlLiBJZiBubyBzdGF0ZSBpcyBmb3VuZCBhdCB0aGF0IHBhdGgsIGl0IHdpbGwKICAgIGF0dGVtcHQgdG8gcmVzb2x2ZSBpdCByZWxhdGl2ZSB0byB0aGUgY3VycmVudCBzdGF0ZSdzIHBhcmVudCwgYW5kIHRoZW4gaXRzCiAgICBwYXJlbnQsIGFuZCBzbyBvbiB1bnRpbCB0aGUgcm9vdCBpcyByZWFjaGVkLiBGb3IgZXhhbXBsZSwgaW1hZ2luZSBhIGhpZXJhcmNoeQogICAgbGlrZSB0aGlzOgoKICAgICAgICAqIGNyZWF0ZWQKICAgICAgICAgICogdW5jb21taXR0ZWQgPC0tIGN1cnJlbnRTdGF0ZQogICAgICAgICAgKiBpbkZsaWdodAogICAgICAgICogdXBkYXRlZAogICAgICAgICAgKiBpbkZsaWdodAoKICAgIElmIHdlIGFyZSBjdXJyZW50bHkgaW4gdGhlIGB1bmNvbW1pdHRlZGAgc3RhdGUsIGNhbGxpbmcKICAgIGB0cmFuc2l0aW9uVG8oJ2luRmxpZ2h0JylgIHdvdWxkIHRyYW5zaXRpb24gdG8gdGhlIGBjcmVhdGVkLmluRmxpZ2h0YCBzdGF0ZSwKICAgIHdoaWxlIGNhbGxpbmcgYHRyYW5zaXRpb25UbygndXBkYXRlZC5pbkZsaWdodCcpYCB3b3VsZCB0cmFuc2l0aW9uIHRvCiAgICB0aGUgYHVwZGF0ZWQuaW5GbGlnaHRgIHN0YXRlLgoKICAgIFJlbWVtYmVyIHRoYXQgKm9ubHkgZXZlbnRzKiBzaG91bGQgZXZlciBjYXVzZSBhIHN0YXRlIHRyYW5zaXRpb24uIFlvdSBzaG91bGQKICAgIG5ldmVyIGNhbGwgYHRyYW5zaXRpb25UbygpYCBmcm9tIG91dHNpZGUgYSBzdGF0ZSdzIGV2ZW50IGhhbmRsZXIuIElmIHlvdSBhcmUKICAgIHRlbXB0ZWQgdG8gZG8gc28sIGNyZWF0ZSBhIG5ldyBldmVudCBhbmQgc2VuZCB0aGF0IHRvIHRoZSBzdGF0ZSBtYW5hZ2VyLgoKICAgICMjIyMgRmxhZ3MKCiAgICBGbGFncyBhcmUgQm9vbGVhbiB2YWx1ZXMgdGhhdCBjYW4gYmUgdXNlZCB0byBpbnRyb3NwZWN0IGEgcmVjb3JkJ3MgY3VycmVudAogICAgc3RhdGUgaW4gYSBtb3JlIHVzZXItZnJpZW5kbHkgd2F5IHRoYW4gZXhhbWluaW5nIGl0cyBzdGF0ZSBwYXRoLiBGb3IgZXhhbXBsZSwKICAgIGluc3RlYWQgb2YgZG9pbmcgdGhpczoKCiAgICBgYGBqYXZhc2NyaXB0CiAgICB2YXIgc3RhdGVQYXRoID0gcmVjb3JkLmdldCgnc3RhdGVNYW5hZ2VyLmN1cnJlbnRQYXRoJyk7CiAgICBpZiAoc3RhdGVQYXRoID09PSAnY3JlYXRlZC5pbkZsaWdodCcpIHsKICAgICAgZG9Tb21ldGhpbmcoKTsKICAgIH0KICAgIGBgYAoKICAgIFlvdSBjYW4gc2F5OgoKICAgIGBgYGphdmFzY3JpcHQKICAgIGlmIChyZWNvcmQuZ2V0KCdpc05ldycpICYmIHJlY29yZC5nZXQoJ2lzU2F2aW5nJykpIHsKICAgICAgZG9Tb21ldGhpbmcoKTsKICAgIH0KICAgIGBgYAoKICAgIElmIHlvdXIgc3RhdGUgZG9lcyBub3Qgc2V0IGEgdmFsdWUgZm9yIGEgZ2l2ZW4gZmxhZywgdGhlIHZhbHVlIHdpbGwKICAgIGJlIGluaGVyaXRlZCBmcm9tIGl0cyBwYXJlbnQgKG9yIHRoZSBmaXJzdCBwbGFjZSBpbiB0aGUgc3RhdGUgaGllcmFyY2h5CiAgICB3aGVyZSBpdCBpcyBkZWZpbmVkKS4KCiAgICBUaGUgY3VycmVudCBzZXQgb2YgZmxhZ3MgYXJlIGRlZmluZWQgYmVsb3cuIElmIHlvdSB3YW50IHRvIGFkZCBhIG5ldyBmbGFnLAogICAgaW4gYWRkaXRpb24gdG8gdGhlIGFyZWEgYmVsb3csIHlvdSB3aWxsIGFsc28gbmVlZCB0byBkZWNsYXJlIGl0IGluIHRoZQogICAgYE1vZGVsYCBjbGFzcy4KCgogICAgICogW2lzRW1wdHldKE1vZGVsL3Byb3BlcnRpZXMvaXNFbXB0eT9hbmNob3I9aXNFbXB0eSkKICAgICAqIFtpc0xvYWRpbmddKE1vZGVsL3Byb3BlcnRpZXMvaXNMb2FkaW5nP2FuY2hvcj1pc0xvYWRpbmcpCiAgICAgKiBbaXNMb2FkZWRdKE1vZGVsL3Byb3BlcnRpZXMvaXNMb2FkZWQ/YW5jaG9yPWlzTG9hZGVkKQogICAgICogW2hhc0RpcnR5QXR0cmlidXRlc10oTW9kZWwvcHJvcGVydGllcy9oYXNEaXJ0eUF0dHJpYnV0ZXM/YW5jaG9yPWhhc0RpcnR5QXR0cmlidXRlcykKICAgICAqIFtpc1NhdmluZ10oTW9kZWwvcHJvcGVydGllcy9pc1NhdmluZz9hbmNob3I9aXNTYXZpbmcpCiAgICAgKiBbaXNEZWxldGVkXShNb2RlbC9wcm9wZXJ0aWVzL2lzRGVsZXRlZD9hbmNob3I9aXNEZWxldGVkKQogICAgICogW2lzTmV3XShNb2RlbC9wcm9wZXJ0aWVzL2lzTmV3P2FuY2hvcj1pc05ldykKICAgICAqIFtpc1ZhbGlkXShNb2RlbC9wcm9wZXJ0aWVzL2lzVmFsaWQ/YW5jaG9yPWlzVmFsaWQpCgogICAgQGNsYXNzIFJvb3RTdGF0ZQogICovCgogIGZ1bmN0aW9uIF9kaWRTZXRQcm9wZXJ0eShpbnRlcm5hbE1vZGVsLCBjb250ZXh0KSB7CiAgICBpZiAoY29udGV4dC5pc0RpcnR5KSB7CiAgICAgIGludGVybmFsTW9kZWwuc2VuZCgnYmVjb21lRGlydHknKTsKICAgIH0gZWxzZSB7CiAgICAgIGludGVybmFsTW9kZWwuc2VuZCgncHJvcGVydHlXYXNSZXNldCcpOwogICAgfQoKICAgIGludGVybmFsTW9kZWwudXBkYXRlUmVjb3JkQXJyYXlzKCk7CiAgfSAvLyBJbXBsZW1lbnRhdGlvbiBub3RlczoKICAvLwogIC8vIEVhY2ggc3RhdGUgaGFzIGEgYm9vbGVhbiB2YWx1ZSBmb3IgYWxsIG9mIHRoZSBmb2xsb3dpbmcgZmxhZ3M6CiAgLy8KICAvLyAqIGlzTG9hZGVkOiBUaGUgcmVjb3JkIGhhcyBhIHBvcHVsYXRlZCBgZGF0YWAgcHJvcGVydHkuIFdoZW4gYQogIC8vICAgcmVjb3JkIGlzIGxvYWRlZCB2aWEgYHN0b3JlLmZpbmRgLCBgaXNMb2FkZWRgIGlzIGZhbHNlCiAgLy8gICB1bnRpbCB0aGUgYWRhcHRlciBzZXRzIGl0LiBXaGVuIGEgcmVjb3JkIGlzIGNyZWF0ZWQgbG9jYWxseSwKICAvLyAgIGl0cyBgaXNMb2FkZWRgIHByb3BlcnR5IGlzIGFsd2F5cyB0cnVlLgogIC8vICogaXNEaXJ0eTogVGhlIHJlY29yZCBoYXMgbG9jYWwgY2hhbmdlcyB0aGF0IGhhdmUgbm90IHlldCBiZWVuCiAgLy8gICBzYXZlZCBieSB0aGUgYWRhcHRlci4gVGhpcyBpbmNsdWRlcyByZWNvcmRzIHRoYXQgaGF2ZSBiZWVuCiAgLy8gICBjcmVhdGVkIChidXQgbm90IHlldCBzYXZlZCkgb3IgZGVsZXRlZC4KICAvLyAqIGlzU2F2aW5nOiBUaGUgcmVjb3JkIGhhcyBiZWVuIGNvbW1pdHRlZCwgYnV0CiAgLy8gICB0aGUgYWRhcHRlciBoYXMgbm90IHlldCBhY2tub3dsZWRnZWQgdGhhdCB0aGUgY2hhbmdlcyBoYXZlCiAgLy8gICBiZWVuIHBlcnNpc3RlZCB0byB0aGUgYmFja2VuZC4KICAvLyAqIGlzRGVsZXRlZDogVGhlIHJlY29yZCB3YXMgbWFya2VkIGZvciBkZWxldGlvbi4gV2hlbiBgaXNEZWxldGVkYAogIC8vICAgaXMgdHJ1ZSBhbmQgYGlzRGlydHlgIGlzIHRydWUsIHRoZSByZWNvcmQgaXMgZGVsZXRlZCBsb2NhbGx5CiAgLy8gICBidXQgdGhlIGRlbGV0aW9uIHdhcyBub3QgeWV0IHBlcnNpc3RlZC4gV2hlbiBgaXNTYXZpbmdgIGlzCiAgLy8gICB0cnVlLCB0aGUgY2hhbmdlIGlzIGluLWZsaWdodC4gV2hlbiBib3RoIGBpc0RpcnR5YCBhbmQKICAvLyAgIGBpc1NhdmluZ2AgYXJlIGZhbHNlLCB0aGUgY2hhbmdlIGhhcyBwZXJzaXN0ZWQuCiAgLy8gKiBpc05ldzogVGhlIHJlY29yZCB3YXMgY3JlYXRlZCBvbiB0aGUgY2xpZW50IGFuZCB0aGUgYWRhcHRlcgogIC8vICAgZGlkIG5vdCB5ZXQgcmVwb3J0IHRoYXQgaXQgd2FzIHN1Y2Nlc3NmdWxseSBzYXZlZC4KICAvLyAqIGlzVmFsaWQ6IFRoZSBhZGFwdGVyIGRpZCBub3QgcmVwb3J0IGFueSBzZXJ2ZXItc2lkZSB2YWxpZGF0aW9uCiAgLy8gICBmYWlsdXJlcy4KICAvLyBUaGUgZGlydHkgc3RhdGUgaXMgYSBhYnN0cmFjdCBzdGF0ZSB3aG9zZSBmdW5jdGlvbmFsaXR5IGlzCiAgLy8gc2hhcmVkIGJldHdlZW4gdGhlIGBjcmVhdGVkYCBhbmQgYHVwZGF0ZWRgIHN0YXRlcy4KICAvLwogIC8vIFRoZSBkZWxldGVkIHN0YXRlIHNoYXJlcyB0aGUgYGlzRGlydHlgIGZsYWcgd2l0aCB0aGUKICAvLyBzdWJjbGFzc2VzIG9mIGBEaXJ0eVN0YXRlYCwgYnV0IHdpdGggYSB2ZXJ5IGRpZmZlcmVudAogIC8vIGltcGxlbWVudGF0aW9uLgogIC8vCiAgLy8gRGlydHkgc3RhdGVzIGhhdmUgdGhyZWUgY2hpbGQgc3RhdGVzOgogIC8vCiAgLy8gYHVuY29tbWl0dGVkYDogdGhlIHN0b3JlIGhhcyBub3QgeWV0IGhhbmRlZCBvZmYgdGhlIHJlY29yZAogIC8vICAgdG8gYmUgc2F2ZWQuCiAgLy8gYGluRmxpZ2h0YDogdGhlIHN0b3JlIGhhcyBoYW5kZWQgb2ZmIHRoZSByZWNvcmQgdG8gYmUgc2F2ZWQsCiAgLy8gICBidXQgdGhlIGFkYXB0ZXIgaGFzIG5vdCB5ZXQgYWNrbm93bGVkZ2VkIHN1Y2Nlc3MuCiAgLy8gYGludmFsaWRgOiB0aGUgcmVjb3JkIGhhcyBpbnZhbGlkIGluZm9ybWF0aW9uIGFuZCBjYW5ub3QgYmUKICAvLyAgIHNlbnQgdG8gdGhlIGFkYXB0ZXIgeWV0LgoKCiAgdmFyIERpcnR5U3RhdGUgPSB7CiAgICBpbml0aWFsU3RhdGU6ICd1bmNvbW1pdHRlZCcsCiAgICAvLyBGTEFHUwogICAgaXNEaXJ0eTogdHJ1ZSwKICAgIC8vIFNVQlNUQVRFUwogICAgLy8gV2hlbiBhIHJlY29yZCBmaXJzdCBiZWNvbWVzIGRpcnR5LCBpdCBpcyBgdW5jb21taXR0ZWRgLgogICAgLy8gVGhpcyBtZWFucyB0aGF0IHRoZXJlIGFyZSBsb2NhbCBwZW5kaW5nIGNoYW5nZXMsIGJ1dCB0aGV5CiAgICAvLyBoYXZlIG5vdCB5ZXQgYmVndW4gdG8gYmUgc2F2ZWQsIGFuZCBhcmUgbm90IGludmFsaWQuCiAgICB1bmNvbW1pdHRlZDogewogICAgICAvLyBFVkVOVFMKICAgICAgZGlkU2V0UHJvcGVydHk6IF9kaWRTZXRQcm9wZXJ0eSwKICAgICAgLy9UT0RPKElnb3IpIHJlbG9hZGluZyBub3cgdHJpZ2dlcnMgYQogICAgICAvL2xvYWRpbmdEYXRhIGV2ZW50LCB0aG91Z2ggaXQgc2VlbXMgZmluZT8KICAgICAgbG9hZGluZ0RhdGE6IGZ1bmN0aW9uIGxvYWRpbmdEYXRhKCkge30sCiAgICAgIHByb3BlcnR5V2FzUmVzZXQ6IGZ1bmN0aW9uIHByb3BlcnR5V2FzUmVzZXQoaW50ZXJuYWxNb2RlbCwgbmFtZSkgewogICAgICAgIGlmICghaW50ZXJuYWxNb2RlbC5oYXNDaGFuZ2VkQXR0cmlidXRlcygpKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnNlbmQoJ3JvbGxlZEJhY2snKTsKICAgICAgICB9CiAgICAgIH0sCiAgICAgIHB1c2hlZERhdGE6IGZ1bmN0aW9uIHB1c2hlZERhdGEoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGlmICghaW50ZXJuYWxNb2RlbC5oYXNDaGFuZ2VkQXR0cmlidXRlcygpKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnbG9hZGVkLnNhdmVkJyk7CiAgICAgICAgfQogICAgICB9LAogICAgICBiZWNvbWVEaXJ0eTogZnVuY3Rpb24gYmVjb21lRGlydHkoKSB7fSwKICAgICAgd2lsbENvbW1pdDogZnVuY3Rpb24gd2lsbENvbW1pdChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2luRmxpZ2h0Jyk7CiAgICAgIH0sCiAgICAgIHJlbG9hZFJlY29yZDogZnVuY3Rpb24gcmVsb2FkUmVjb3JkKGludGVybmFsTW9kZWwsIF9yZWYpIHsKICAgICAgICB2YXIgcmVzb2x2ZSA9IF9yZWYucmVzb2x2ZSwKICAgICAgICAgICAgb3B0aW9ucyA9IF9yZWYub3B0aW9uczsKICAgICAgICByZXNvbHZlKGludGVybmFsTW9kZWwuc3RvcmUuX3JlbG9hZFJlY29yZChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKSk7CiAgICAgIH0sCiAgICAgIHJvbGxlZEJhY2s6IGZ1bmN0aW9uIHJvbGxlZEJhY2soaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdsb2FkZWQuc2F2ZWQnKTsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcigncm9sbGVkQmFjaycpOwogICAgICB9LAogICAgICBiZWNhbWVJbnZhbGlkOiBmdW5jdGlvbiBiZWNhbWVJbnZhbGlkKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnaW52YWxpZCcpOwogICAgICB9LAogICAgICByb2xsYmFjazogZnVuY3Rpb24gcm9sbGJhY2soaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwucm9sbGJhY2tBdHRyaWJ1dGVzKCk7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ3JlYWR5Jyk7CiAgICAgIH0KICAgIH0sCiAgICAvLyBPbmNlIGEgcmVjb3JkIGhhcyBiZWVuIGhhbmRlZCBvZmYgdG8gdGhlIGFkYXB0ZXIgdG8gYmUKICAgIC8vIHNhdmVkLCBpdCBpcyBpbiB0aGUgJ2luIGZsaWdodCcgc3RhdGUuIENoYW5nZXMgdG8gdGhlCiAgICAvLyByZWNvcmQgY2Fubm90IGJlIG1hZGUgZHVyaW5nIHRoaXMgd2luZG93LgogICAgaW5GbGlnaHQ6IHsKICAgICAgLy8gRkxBR1MKICAgICAgaXNTYXZpbmc6IHRydWUsCiAgICAgIC8vIEVWRU5UUwogICAgICBkaWRTZXRQcm9wZXJ0eTogX2RpZFNldFByb3BlcnR5LAogICAgICBiZWNvbWVEaXJ0eTogZnVuY3Rpb24gYmVjb21lRGlydHkoKSB7fSwKICAgICAgcHVzaGVkRGF0YTogZnVuY3Rpb24gcHVzaGVkRGF0YSgpIHt9LAogICAgICB1bmxvYWRSZWNvcmQ6IGFzc2VydEFnYWluc3RVbmxvYWRSZWNvcmQsCiAgICAgIC8vIFRPRE86IE1vcmUgcm9idXN0IHNlbWFudGljcyBhcm91bmQgc2F2ZS13aGlsZS1pbi1mbGlnaHQKICAgICAgd2lsbENvbW1pdDogZnVuY3Rpb24gd2lsbENvbW1pdCgpIHt9LAogICAgICBkaWRDb21taXQ6IGZ1bmN0aW9uIGRpZENvbW1pdChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ3NhdmVkJyk7CiAgICAgICAgaW50ZXJuYWxNb2RlbC5zZW5kKCdpbnZva2VMaWZlY3ljbGVDYWxsYmFja3MnLCB0aGlzLmRpcnR5VHlwZSk7CiAgICAgIH0sCiAgICAgIHJvbGxlZEJhY2s6IGZ1bmN0aW9uIHJvbGxlZEJhY2soaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdyb2xsZWRCYWNrJyk7CiAgICAgIH0sCiAgICAgIGJlY2FtZUludmFsaWQ6IGZ1bmN0aW9uIGJlY2FtZUludmFsaWQoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdpbnZhbGlkJyk7CiAgICAgICAgaW50ZXJuYWxNb2RlbC5zZW5kKCdpbnZva2VMaWZlY3ljbGVDYWxsYmFja3MnKTsKICAgICAgfSwKICAgICAgYmVjYW1lRXJyb3I6IGZ1bmN0aW9uIGJlY2FtZUVycm9yKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygndW5jb21taXR0ZWQnKTsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcignYmVjYW1lRXJyb3InLCBpbnRlcm5hbE1vZGVsKTsKICAgICAgfQogICAgfSwKICAgIC8vIEEgcmVjb3JkIGlzIGluIHRoZSBgaW52YWxpZGAgaWYgdGhlIGFkYXB0ZXIgaGFzIGluZGljYXRlZAogICAgLy8gdGhlIHRoZSByZWNvcmQgZmFpbGVkIHNlcnZlci1zaWRlIGludmFsaWRhdGlvbnMuCiAgICBpbnZhbGlkOiB7CiAgICAgIC8vIEZMQUdTCiAgICAgIGlzVmFsaWQ6IGZhbHNlLAogICAgICAvLyBFVkVOVFMKICAgICAgZGVsZXRlUmVjb3JkOiBmdW5jdGlvbiBkZWxldGVSZWNvcmQoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdkZWxldGVkLnVuY29tbWl0dGVkJyk7CiAgICAgIH0sCiAgICAgIGRpZFNldFByb3BlcnR5OiBmdW5jdGlvbiBkaWRTZXRQcm9wZXJ0eShpbnRlcm5hbE1vZGVsLCBjb250ZXh0KSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC5yZW1vdmVFcnJvck1lc3NhZ2VGcm9tQXR0cmlidXRlKGNvbnRleHQubmFtZSk7CgogICAgICAgIF9kaWRTZXRQcm9wZXJ0eShpbnRlcm5hbE1vZGVsLCBjb250ZXh0KTsKCiAgICAgICAgaWYgKCFpbnRlcm5hbE1vZGVsLmhhc0Vycm9ycygpKSB7CiAgICAgICAgICB0aGlzLmJlY2FtZVZhbGlkKGludGVybmFsTW9kZWwpOwogICAgICAgIH0KICAgICAgfSwKICAgICAgYmVjYW1lSW52YWxpZDogZnVuY3Rpb24gYmVjYW1lSW52YWxpZCgpIHt9LAogICAgICBiZWNvbWVEaXJ0eTogZnVuY3Rpb24gYmVjb21lRGlydHkoKSB7fSwKICAgICAgcHVzaGVkRGF0YTogZnVuY3Rpb24gcHVzaGVkRGF0YSgpIHt9LAogICAgICB3aWxsQ29tbWl0OiBmdW5jdGlvbiB3aWxsQ29tbWl0KGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLmNsZWFyRXJyb3JNZXNzYWdlcygpOwogICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdpbkZsaWdodCcpOwogICAgICB9LAogICAgICByb2xsZWRCYWNrOiBmdW5jdGlvbiByb2xsZWRCYWNrKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLmNsZWFyRXJyb3JNZXNzYWdlcygpOwogICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdsb2FkZWQuc2F2ZWQnKTsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcigncmVhZHknKTsKICAgICAgfSwKICAgICAgYmVjYW1lVmFsaWQ6IGZ1bmN0aW9uIGJlY2FtZVZhbGlkKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygndW5jb21taXR0ZWQnKTsKICAgICAgfSwKICAgICAgaW52b2tlTGlmZWN5Y2xlQ2FsbGJhY2tzOiBmdW5jdGlvbiBpbnZva2VMaWZlY3ljbGVDYWxsYmFja3MoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdiZWNhbWVJbnZhbGlkJywgaW50ZXJuYWxNb2RlbCk7CiAgICAgIH0KICAgIH0KICB9OyAvLyBUaGUgY3JlYXRlZCBhbmQgdXBkYXRlZCBzdGF0ZXMgYXJlIGNyZWF0ZWQgb3V0c2lkZSB0aGUgc3RhdGUKICAvLyBjaGFydCBzbyB3ZSBjYW4gcmVvcGVuIHRoZWlyIHN1YnN0YXRlcyBhbmQgYWRkIG1peGlucyBhcwogIC8vIG5lY2Vzc2FyeS4KCiAgZnVuY3Rpb24gZGVlcENsb25lKG9iamVjdCkgewogICAgdmFyIGNsb25lID0ge307CiAgICB2YXIgdmFsdWU7CgogICAgZm9yICh2YXIgcHJvcCBpbiBvYmplY3QpIHsKICAgICAgdmFsdWUgPSBvYmplY3RbcHJvcF07CgogICAgICBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JykgewogICAgICAgIGNsb25lW3Byb3BdID0gZGVlcENsb25lKHZhbHVlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjbG9uZVtwcm9wXSA9IHZhbHVlOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIGNsb25lOwogIH0KCiAgZnVuY3Rpb24gbWl4aW4ob3JpZ2luYWwsIGhhc2gpIHsKICAgIGZvciAodmFyIHByb3AgaW4gaGFzaCkgewogICAgICBvcmlnaW5hbFtwcm9wXSA9IGhhc2hbcHJvcF07CiAgICB9CgogICAgcmV0dXJuIG9yaWdpbmFsOwogIH0KCiAgZnVuY3Rpb24gZGlydHlTdGF0ZShvcHRpb25zKSB7CiAgICB2YXIgbmV3U3RhdGUgPSBkZWVwQ2xvbmUoRGlydHlTdGF0ZSk7CiAgICByZXR1cm4gbWl4aW4obmV3U3RhdGUsIG9wdGlvbnMpOwogIH0KCiAgdmFyIGNyZWF0ZWRTdGF0ZSA9IGRpcnR5U3RhdGUoewogICAgZGlydHlUeXBlOiAnY3JlYXRlZCcsCiAgICAvLyBGTEFHUwogICAgaXNOZXc6IHRydWUKICB9KTsKCiAgY3JlYXRlZFN0YXRlLmludmFsaWQucm9sbGVkQmFjayA9IGZ1bmN0aW9uIChpbnRlcm5hbE1vZGVsKSB7CiAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnZGVsZXRlZC5zYXZlZCcpOwogICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ3JvbGxlZEJhY2snKTsKICB9OwoKICBjcmVhdGVkU3RhdGUudW5jb21taXR0ZWQucm9sbGVkQmFjayA9IGZ1bmN0aW9uIChpbnRlcm5hbE1vZGVsKSB7CiAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnZGVsZXRlZC5zYXZlZCcpOwogICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ3JvbGxlZEJhY2snKTsKICB9OwoKICB2YXIgdXBkYXRlZFN0YXRlID0gZGlydHlTdGF0ZSh7CiAgICBkaXJ0eVR5cGU6ICd1cGRhdGVkJwogIH0pOwoKICBmdW5jdGlvbiBjcmVhdGVkU3RhdGVEZWxldGVSZWNvcmQoaW50ZXJuYWxNb2RlbCkgewogICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2RlbGV0ZWQuc2F2ZWQnKTsKICAgIGludGVybmFsTW9kZWwuc2VuZCgnaW52b2tlTGlmZWN5Y2xlQ2FsbGJhY2tzJyk7CiAgfQoKICBjcmVhdGVkU3RhdGUudW5jb21taXR0ZWQuZGVsZXRlUmVjb3JkID0gY3JlYXRlZFN0YXRlRGVsZXRlUmVjb3JkOwogIGNyZWF0ZWRTdGF0ZS5pbnZhbGlkLmRlbGV0ZVJlY29yZCA9IGNyZWF0ZWRTdGF0ZURlbGV0ZVJlY29yZDsKCiAgY3JlYXRlZFN0YXRlLnVuY29tbWl0dGVkLnJvbGxiYWNrID0gZnVuY3Rpb24gKGludGVybmFsTW9kZWwpIHsKICAgIERpcnR5U3RhdGUudW5jb21taXR0ZWQucm9sbGJhY2suYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdkZWxldGVkLnNhdmVkJyk7CiAgfTsKCiAgY3JlYXRlZFN0YXRlLnVuY29tbWl0dGVkLnB1c2hlZERhdGEgPSBmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2xvYWRlZC51cGRhdGVkLnVuY29tbWl0dGVkJyk7CiAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcignZGlkTG9hZCcpOwogIH07CgogIGNyZWF0ZWRTdGF0ZS51bmNvbW1pdHRlZC5wcm9wZXJ0eVdhc1Jlc2V0ID0gZnVuY3Rpb24gKCkge307CgogIGZ1bmN0aW9uIGFzc2VydEFnYWluc3RVbmxvYWRSZWNvcmQoaW50ZXJuYWxNb2RlbCkgewogIH0KCiAgdXBkYXRlZFN0YXRlLmludmFsaWQuYmVjYW1lVmFsaWQgPSBmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgLy8gd2UncmUgZWFnZXJseSB0cmFuc2l0aW9uIGludG8gdGhlIGxvYWRlZC5zYXZlZCBzdGF0ZSwgZXZlbiB0aG91Z2ggd2UgY291bGQKICAgIC8vIGJlIHN0aWxsIGRpcnR5OyBidXQgdGhlIHNldHVwIGhvb2sgb2YgdGhlIGxvYWRlZC5zYXZlZCBzdGF0ZSBjaGVja3MgZm9yCiAgICAvLyBkaXJ0eSBhdHRyaWJ1dGVzIGFuZCB0cmFuc2l0aW9ucyBpbnRvIHRoZSBjb3JyZXNwb25kaW5nIGRpcnR5IHN0YXRlCiAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnbG9hZGVkLnNhdmVkJyk7CiAgfTsKCiAgdXBkYXRlZFN0YXRlLmluRmxpZ2h0LnVubG9hZFJlY29yZCA9IGFzc2VydEFnYWluc3RVbmxvYWRSZWNvcmQ7CgogIHVwZGF0ZWRTdGF0ZS51bmNvbW1pdHRlZC5kZWxldGVSZWNvcmQgPSBmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2RlbGV0ZWQudW5jb21taXR0ZWQnKTsKICB9OwoKICB1cGRhdGVkU3RhdGUuaW52YWxpZC5yb2xsZWRCYWNrID0gZnVuY3Rpb24gKGludGVybmFsTW9kZWwpIHsKICAgIGludGVybmFsTW9kZWwuY2xlYXJFcnJvck1lc3NhZ2VzKCk7CiAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnbG9hZGVkLnNhdmVkJyk7CiAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcigncm9sbGVkQmFjaycpOwogIH07CgogIHZhciBSb290U3RhdGUgPSB7CiAgICAvLyBGTEFHUwogICAgaXNFbXB0eTogZmFsc2UsCiAgICBpc0xvYWRpbmc6IGZhbHNlLAogICAgaXNMb2FkZWQ6IGZhbHNlLAogICAgaXNEaXJ0eTogZmFsc2UsCiAgICBpc1NhdmluZzogZmFsc2UsCiAgICBpc0RlbGV0ZWQ6IGZhbHNlLAogICAgaXNOZXc6IGZhbHNlLAogICAgaXNWYWxpZDogdHJ1ZSwKICAgIC8vIERFRkFVTFQgRVZFTlRTCiAgICAvLyBUcnlpbmcgdG8gcm9sbCBiYWNrIGlmIHlvdSdyZSBub3QgaW4gdGhlIGRpcnR5IHN0YXRlCiAgICAvLyBkb2Vzbid0IGNoYW5nZSB5b3VyIHN0YXRlLiBGb3IgZXhhbXBsZSwgaWYgeW91J3JlIGluIHRoZQogICAgLy8gaW4tZmxpZ2h0IHN0YXRlLCByb2xsaW5nIGJhY2sgdGhlIHJlY29yZCBkb2Vzbid0IG1vdmUKICAgIC8vIHlvdSBvdXQgb2YgdGhlIGluLWZsaWdodCBzdGF0ZS4KICAgIHJvbGxlZEJhY2s6IGZ1bmN0aW9uIHJvbGxlZEJhY2soKSB7fSwKICAgIHVubG9hZFJlY29yZDogZnVuY3Rpb24gdW5sb2FkUmVjb3JkKGludGVybmFsTW9kZWwpIHt9LAogICAgcHJvcGVydHlXYXNSZXNldDogZnVuY3Rpb24gcHJvcGVydHlXYXNSZXNldCgpIHt9LAogICAgLy8gU1VCU1RBVEVTCiAgICAvLyBBIHJlY29yZCBiZWdpbnMgaXRzIGxpZmVjeWNsZSBpbiB0aGUgYGVtcHR5YCBzdGF0ZS4KICAgIC8vIElmIGl0cyBkYXRhIHdpbGwgY29tZSBmcm9tIHRoZSBhZGFwdGVyLCBpdCB3aWxsCiAgICAvLyB0cmFuc2l0aW9uIGludG8gdGhlIGBsb2FkaW5nYCBzdGF0ZS4gT3RoZXJ3aXNlLCBpZgogICAgLy8gdGhlIHJlY29yZCBpcyBiZWluZyBjcmVhdGVkIG9uIHRoZSBjbGllbnQsIGl0IHdpbGwKICAgIC8vIHRyYW5zaXRpb24gaW50byB0aGUgYGNyZWF0ZWRgIHN0YXRlLgogICAgZW1wdHk6IHsKICAgICAgaXNFbXB0eTogdHJ1ZSwKICAgICAgLy8gRVZFTlRTCiAgICAgIGxvYWRpbmdEYXRhOiBmdW5jdGlvbiBsb2FkaW5nRGF0YShpbnRlcm5hbE1vZGVsLCBwcm9taXNlKSB7CiAgICAgICAgaWYgKCFjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICAgIGludGVybmFsTW9kZWwuX3Byb21pc2VQcm94eSA9IHByb21pc2U7CiAgICAgICAgfQoKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnbG9hZGluZycpOwogICAgICB9LAogICAgICBsb2FkZWREYXRhOiBmdW5jdGlvbiBsb2FkZWREYXRhKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnbG9hZGVkLmNyZWF0ZWQudW5jb21taXR0ZWQnKTsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcigncmVhZHknKTsKICAgICAgfSwKICAgICAgcHVzaGVkRGF0YTogZnVuY3Rpb24gcHVzaGVkRGF0YShpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2xvYWRlZC5zYXZlZCcpOwogICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdkaWRMb2FkJyk7CiAgICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ3JlYWR5Jyk7CiAgICAgIH0sCiAgICAgIC8vIFJlY29yZCBpcyBhbHJlYWR5IGluIGFuIGVtcHR5IHN0YXRlLCB0cmlnZ2VyaW5nIHRyYW5zaXRpb24gdG8gZW1wdHkgaGVyZQogICAgICAvLyBwcm9kdWNlIGFuIGVycm9yLgogICAgICBub3RGb3VuZDogZnVuY3Rpb24gbm90Rm91bmQoKSB7fQogICAgfSwKICAgIC8vIEEgcmVjb3JkIGVudGVycyB0aGlzIHN0YXRlIHdoZW4gdGhlIHN0b3JlIGFza3MKICAgIC8vIHRoZSBhZGFwdGVyIGZvciBpdHMgZGF0YS4gSXQgcmVtYWlucyBpbiB0aGlzIHN0YXRlCiAgICAvLyB1bnRpbCB0aGUgYWRhcHRlciBwcm92aWRlcyB0aGUgcmVxdWVzdGVkIGRhdGEuCiAgICAvLwogICAgLy8gVXN1YWxseSwgdGhpcyBwcm9jZXNzIGlzIGFzeW5jaHJvbm91cywgdXNpbmcgYW4KICAgIC8vIFhIUiB0byByZXRyaWV2ZSB0aGUgZGF0YS4KICAgIGxvYWRpbmc6IHsKICAgICAgLy8gRkxBR1MKICAgICAgaXNMb2FkaW5nOiB0cnVlLAogICAgICBleGl0OiBmdW5jdGlvbiBleGl0KGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLl9wcm9taXNlUHJveHkgPSBudWxsOwogICAgICB9LAogICAgICBsb2FkaW5nRGF0YTogZnVuY3Rpb24gbG9hZGluZ0RhdGEoKSB7fSwKICAgICAgLy8gRVZFTlRTCiAgICAgIHB1c2hlZERhdGE6IGZ1bmN0aW9uIHB1c2hlZERhdGEoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdsb2FkZWQuc2F2ZWQnKTsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcignZGlkTG9hZCcpOwogICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdyZWFkeScpOyAvL1RPRE8gdGhpcyBzZWVtcyBvdXQgb2YgcGxhY2UgaGVyZQoKICAgICAgICBpbnRlcm5hbE1vZGVsLmRpZENsZWFuRXJyb3IoKTsKICAgICAgfSwKICAgICAgYmVjYW1lRXJyb3I6IGZ1bmN0aW9uIGJlY2FtZUVycm9yKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcignYmVjYW1lRXJyb3InLCBpbnRlcm5hbE1vZGVsKTsKICAgICAgfSwKICAgICAgbm90Rm91bmQ6IGZ1bmN0aW9uIG5vdEZvdW5kKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25UbygnZW1wdHknKTsKICAgICAgfQogICAgfSwKICAgIC8vIEEgcmVjb3JkIGVudGVycyB0aGlzIHN0YXRlIHdoZW4gaXRzIGRhdGEgaXMgcG9wdWxhdGVkLgogICAgLy8gTW9zdCBvZiBhIHJlY29yZCdzIGxpZmVjeWNsZSBpcyBzcGVudCBpbnNpZGUgc3Vic3RhdGVzCiAgICAvLyBvZiB0aGUgYGxvYWRlZGAgc3RhdGUuCiAgICBsb2FkZWQ6IHsKICAgICAgaW5pdGlhbFN0YXRlOiAnc2F2ZWQnLAogICAgICAvLyBGTEFHUwogICAgICBpc0xvYWRlZDogdHJ1ZSwKICAgICAgLy9UT0RPKElnb3IpIFJlbG9hZGluZyBub3cgdHJpZ2dlcnMgYSBsb2FkaW5nRGF0YSBldmVudCwKICAgICAgLy9idXQgaXQgc2hvdWxkIGJlIG9rPwogICAgICBsb2FkaW5nRGF0YTogZnVuY3Rpb24gbG9hZGluZ0RhdGEoKSB7fSwKICAgICAgLy8gU1VCU1RBVEVTCiAgICAgIC8vIElmIHRoZXJlIGFyZSBubyBsb2NhbCBjaGFuZ2VzIHRvIGEgcmVjb3JkLCBpdCByZW1haW5zCiAgICAgIC8vIGluIHRoZSBgc2F2ZWRgIHN0YXRlLgogICAgICBzYXZlZDogewogICAgICAgIHNldHVwOiBmdW5jdGlvbiBzZXR1cChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbC5oYXNDaGFuZ2VkQXR0cmlidXRlcygpKSB7CiAgICAgICAgICAgIGludGVybmFsTW9kZWwuYWRhcHRlckRpZERpcnR5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvLyBFVkVOVFMKICAgICAgICBkaWRTZXRQcm9wZXJ0eTogX2RpZFNldFByb3BlcnR5LAogICAgICAgIHB1c2hlZERhdGE6IGZ1bmN0aW9uIHB1c2hlZERhdGEoKSB7fSwKICAgICAgICBiZWNvbWVEaXJ0eTogZnVuY3Rpb24gYmVjb21lRGlydHkoaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ3VwZGF0ZWQudW5jb21taXR0ZWQnKTsKICAgICAgICB9LAogICAgICAgIHdpbGxDb21taXQ6IGZ1bmN0aW9uIHdpbGxDb21taXQoaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ3VwZGF0ZWQuaW5GbGlnaHQnKTsKICAgICAgICB9LAogICAgICAgIHJlbG9hZFJlY29yZDogZnVuY3Rpb24gcmVsb2FkUmVjb3JkKGludGVybmFsTW9kZWwsIF9yZWYyKSB7CiAgICAgICAgICB2YXIgcmVzb2x2ZSA9IF9yZWYyLnJlc29sdmUsCiAgICAgICAgICAgICAgb3B0aW9ucyA9IF9yZWYyLm9wdGlvbnM7CgogICAgICAgICAgaWYgKCFjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICAgICAgcmVzb2x2ZShpbnRlcm5hbE1vZGVsLnN0b3JlLl9yZWxvYWRSZWNvcmQoaW50ZXJuYWxNb2RlbCwgb3B0aW9ucykpOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgZGVsZXRlUmVjb3JkOiBmdW5jdGlvbiBkZWxldGVSZWNvcmQoaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2RlbGV0ZWQudW5jb21taXR0ZWQnKTsKICAgICAgICB9LAogICAgICAgIHVubG9hZFJlY29yZDogZnVuY3Rpb24gdW5sb2FkUmVjb3JkKGludGVybmFsTW9kZWwpIHt9LAogICAgICAgIGRpZENvbW1pdDogZnVuY3Rpb24gZGlkQ29tbWl0KCkge30sCiAgICAgICAgLy8gbG9hZGVkLnNhdmVkLm5vdEZvdW5kIHdvdWxkIGJlIHRyaWdnZXJlZCBieSBhIGZhaWxlZAogICAgICAgIC8vIGByZWxvYWQoKWAgb24gYW4gdW5jaGFuZ2VkIHJlY29yZAogICAgICAgIG5vdEZvdW5kOiBmdW5jdGlvbiBub3RGb3VuZCgpIHt9CiAgICAgIH0sCiAgICAgIC8vIEEgcmVjb3JkIGlzIGluIHRoaXMgc3RhdGUgYWZ0ZXIgaXQgaGFzIGJlZW4gbG9jYWxseQogICAgICAvLyBjcmVhdGVkIGJ1dCBiZWZvcmUgdGhlIGFkYXB0ZXIgaGFzIGluZGljYXRlZCB0aGF0CiAgICAgIC8vIGl0IGhhcyBiZWVuIHNhdmVkLgogICAgICBjcmVhdGVkOiBjcmVhdGVkU3RhdGUsCiAgICAgIC8vIEEgcmVjb3JkIGlzIGluIHRoaXMgc3RhdGUgaWYgaXQgaGFzIGFscmVhZHkgYmVlbgogICAgICAvLyBzYXZlZCB0byB0aGUgc2VydmVyLCBidXQgdGhlcmUgYXJlIG5ldyBsb2NhbCBjaGFuZ2VzCiAgICAgIC8vIHRoYXQgaGF2ZSBub3QgeWV0IGJlZW4gc2F2ZWQuCiAgICAgIHVwZGF0ZWQ6IHVwZGF0ZWRTdGF0ZQogICAgfSwKICAgIC8vIEEgcmVjb3JkIGlzIGluIHRoaXMgc3RhdGUgaWYgaXQgd2FzIGRlbGV0ZWQgZnJvbSB0aGUgc3RvcmUuCiAgICBkZWxldGVkOiB7CiAgICAgIGluaXRpYWxTdGF0ZTogJ3VuY29tbWl0dGVkJywKICAgICAgZGlydHlUeXBlOiAnZGVsZXRlZCcsCiAgICAgIC8vIEZMQUdTCiAgICAgIGlzRGVsZXRlZDogdHJ1ZSwKICAgICAgaXNMb2FkZWQ6IHRydWUsCiAgICAgIGlzRGlydHk6IHRydWUsCiAgICAgIC8vIFRSQU5TSVRJT05TCiAgICAgIHNldHVwOiBmdW5jdGlvbiBzZXR1cChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC51cGRhdGVSZWNvcmRBcnJheXMoKTsKICAgICAgfSwKICAgICAgLy8gU1VCU1RBVEVTCiAgICAgIC8vIFdoZW4gYSByZWNvcmQgaXMgZGVsZXRlZCwgaXQgZW50ZXJzIHRoZSBgc3RhcnRgCiAgICAgIC8vIHN0YXRlLiBJdCB3aWxsIGV4aXQgdGhpcyBzdGF0ZSB3aGVuIHRoZSByZWNvcmQKICAgICAgLy8gc3RhcnRzIHRvIGNvbW1pdC4KICAgICAgdW5jb21taXR0ZWQ6IHsKICAgICAgICAvLyBFVkVOVFMKICAgICAgICB3aWxsQ29tbWl0OiBmdW5jdGlvbiB3aWxsQ29tbWl0KGludGVybmFsTW9kZWwpIHsKICAgICAgICAgIGludGVybmFsTW9kZWwudHJhbnNpdGlvblRvKCdpbkZsaWdodCcpOwogICAgICAgIH0sCiAgICAgICAgcm9sbGJhY2s6IGZ1bmN0aW9uIHJvbGxiYWNrKGludGVybmFsTW9kZWwpIHsKICAgICAgICAgIGludGVybmFsTW9kZWwucm9sbGJhY2tBdHRyaWJ1dGVzKCk7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcigncmVhZHknKTsKICAgICAgICB9LAogICAgICAgIHB1c2hlZERhdGE6IGZ1bmN0aW9uIHB1c2hlZERhdGEoKSB7fSwKICAgICAgICBiZWNvbWVEaXJ0eTogZnVuY3Rpb24gYmVjb21lRGlydHkoKSB7fSwKICAgICAgICBkZWxldGVSZWNvcmQ6IGZ1bmN0aW9uIGRlbGV0ZVJlY29yZCgpIHt9LAogICAgICAgIHJvbGxlZEJhY2s6IGZ1bmN0aW9uIHJvbGxlZEJhY2soaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2xvYWRlZC5zYXZlZCcpOwogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ3JlYWR5Jyk7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcigncm9sbGVkQmFjaycpOwogICAgICAgIH0KICAgICAgfSwKICAgICAgLy8gQWZ0ZXIgYSByZWNvcmQgc3RhcnRzIGNvbW1pdHRpbmcsIGJ1dAogICAgICAvLyBiZWZvcmUgdGhlIGFkYXB0ZXIgaW5kaWNhdGVzIHRoYXQgdGhlIGRlbGV0aW9uCiAgICAgIC8vIGhhcyBzYXZlZCB0byB0aGUgc2VydmVyLCBhIHJlY29yZCBpcyBpbiB0aGUKICAgICAgLy8gYGluRmxpZ2h0YCBzdWJzdGF0ZSBvZiBgZGVsZXRlZGAuCiAgICAgIGluRmxpZ2h0OiB7CiAgICAgICAgLy8gRkxBR1MKICAgICAgICBpc1NhdmluZzogdHJ1ZSwKICAgICAgICAvLyBFVkVOVFMKICAgICAgICB1bmxvYWRSZWNvcmQ6IGFzc2VydEFnYWluc3RVbmxvYWRSZWNvcmQsCiAgICAgICAgLy8gVE9ETzogTW9yZSByb2J1c3Qgc2VtYW50aWNzIGFyb3VuZCBzYXZlLXdoaWxlLWluLWZsaWdodAogICAgICAgIHdpbGxDb21taXQ6IGZ1bmN0aW9uIHdpbGxDb21taXQoKSB7fSwKICAgICAgICBkaWRDb21taXQ6IGZ1bmN0aW9uIGRpZENvbW1pdChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyYW5zaXRpb25Ubygnc2F2ZWQnKTsKICAgICAgICAgIGludGVybmFsTW9kZWwuc2VuZCgnaW52b2tlTGlmZWN5Y2xlQ2FsbGJhY2tzJyk7CiAgICAgICAgfSwKICAgICAgICBiZWNhbWVFcnJvcjogZnVuY3Rpb24gYmVjYW1lRXJyb3IoaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ3VuY29tbWl0dGVkJyk7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcignYmVjYW1lRXJyb3InLCBpbnRlcm5hbE1vZGVsKTsKICAgICAgICB9LAogICAgICAgIGJlY2FtZUludmFsaWQ6IGZ1bmN0aW9uIGJlY2FtZUludmFsaWQoaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2ludmFsaWQnKTsKICAgICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdiZWNhbWVJbnZhbGlkJywgaW50ZXJuYWxNb2RlbCk7CiAgICAgICAgfQogICAgICB9LAogICAgICAvLyBPbmNlIHRoZSBhZGFwdGVyIGluZGljYXRlcyB0aGF0IHRoZSBkZWxldGlvbiBoYXMKICAgICAgLy8gYmVlbiBzYXZlZCwgdGhlIHJlY29yZCBlbnRlcnMgdGhlIGBzYXZlZGAgc3Vic3RhdGUKICAgICAgLy8gb2YgYGRlbGV0ZWRgLgogICAgICBzYXZlZDogewogICAgICAgIC8vIEZMQUdTCiAgICAgICAgaXNEaXJ0eTogZmFsc2UsCiAgICAgICAgc2V0dXA6IGZ1bmN0aW9uIHNldHVwKGludGVybmFsTW9kZWwpIHsKICAgICAgICAgIGludGVybmFsTW9kZWwucmVtb3ZlRnJvbUludmVyc2VSZWxhdGlvbnNoaXBzKCk7CiAgICAgICAgfSwKICAgICAgICBpbnZva2VMaWZlY3ljbGVDYWxsYmFja3M6IGZ1bmN0aW9uIGludm9rZUxpZmVjeWNsZUNhbGxiYWNrcyhpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcignZGlkRGVsZXRlJywgaW50ZXJuYWxNb2RlbCk7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcignZGlkQ29tbWl0JywgaW50ZXJuYWxNb2RlbCk7CiAgICAgICAgfSwKICAgICAgICB3aWxsQ29tbWl0OiBmdW5jdGlvbiB3aWxsQ29tbWl0KCkge30sCiAgICAgICAgZGlkQ29tbWl0OiBmdW5jdGlvbiBkaWRDb21taXQoKSB7fSwKICAgICAgICBwdXNoZWREYXRhOiBmdW5jdGlvbiBwdXNoZWREYXRhKCkge30KICAgICAgfSwKICAgICAgaW52YWxpZDogewogICAgICAgIGlzVmFsaWQ6IGZhbHNlLAogICAgICAgIGRpZFNldFByb3BlcnR5OiBmdW5jdGlvbiBkaWRTZXRQcm9wZXJ0eShpbnRlcm5hbE1vZGVsLCBjb250ZXh0KSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLnJlbW92ZUVycm9yTWVzc2FnZUZyb21BdHRyaWJ1dGUoY29udGV4dC5uYW1lKTsKCiAgICAgICAgICBfZGlkU2V0UHJvcGVydHkoaW50ZXJuYWxNb2RlbCwgY29udGV4dCk7CgogICAgICAgICAgaWYgKCFpbnRlcm5hbE1vZGVsLmhhc0Vycm9ycygpKSB7CiAgICAgICAgICAgIHRoaXMuYmVjYW1lVmFsaWQoaW50ZXJuYWxNb2RlbCk7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICBiZWNhbWVJbnZhbGlkOiBmdW5jdGlvbiBiZWNhbWVJbnZhbGlkKCkge30sCiAgICAgICAgYmVjb21lRGlydHk6IGZ1bmN0aW9uIGJlY29tZURpcnR5KCkge30sCiAgICAgICAgZGVsZXRlUmVjb3JkOiBmdW5jdGlvbiBkZWxldGVSZWNvcmQoKSB7fSwKICAgICAgICB3aWxsQ29tbWl0OiBmdW5jdGlvbiB3aWxsQ29tbWl0KCkge30sCiAgICAgICAgcm9sbGVkQmFjazogZnVuY3Rpb24gcm9sbGVkQmFjayhpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLmNsZWFyRXJyb3JNZXNzYWdlcygpOwogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ2xvYWRlZC5zYXZlZCcpOwogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmlnZ2VyTGF0ZXIoJ3JlYWR5Jyk7CiAgICAgICAgfSwKICAgICAgICBiZWNhbWVWYWxpZDogZnVuY3Rpb24gYmVjYW1lVmFsaWQoaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC50cmFuc2l0aW9uVG8oJ3VuY29tbWl0dGVkJyk7CiAgICAgICAgfQogICAgICB9CiAgICB9LAogICAgaW52b2tlTGlmZWN5Y2xlQ2FsbGJhY2tzOiBmdW5jdGlvbiBpbnZva2VMaWZlY3ljbGVDYWxsYmFja3MoaW50ZXJuYWxNb2RlbCwgZGlydHlUeXBlKSB7CiAgICAgIGlmIChkaXJ0eVR5cGUgPT09ICdjcmVhdGVkJykgewogICAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdkaWRDcmVhdGUnLCBpbnRlcm5hbE1vZGVsKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnRyaWdnZXJMYXRlcignZGlkVXBkYXRlJywgaW50ZXJuYWxNb2RlbCk7CiAgICAgIH0KCiAgICAgIGludGVybmFsTW9kZWwudHJpZ2dlckxhdGVyKCdkaWRDb21taXQnLCBpbnRlcm5hbE1vZGVsKTsKICAgIH0KICB9OwoKICBmdW5jdGlvbiB3aXJlU3RhdGUob2JqZWN0LCBwYXJlbnQsIG5hbWUpIHsKICAgIC8vIFRPRE86IFVzZSBPYmplY3QuY3JlYXRlIGFuZCBjb3B5IGluc3RlYWQKICAgIG9iamVjdCA9IG1peGluKHBhcmVudCA/IE9iamVjdC5jcmVhdGUocGFyZW50KSA6IHt9LCBvYmplY3QpOwogICAgb2JqZWN0LnBhcmVudFN0YXRlID0gcGFyZW50OwogICAgb2JqZWN0LnN0YXRlTmFtZSA9IG5hbWU7CgogICAgZm9yICh2YXIgcHJvcCBpbiBvYmplY3QpIHsKICAgICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wKSB8fCBwcm9wID09PSAncGFyZW50U3RhdGUnIHx8IHByb3AgPT09ICdzdGF0ZU5hbWUnKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KCiAgICAgIGlmICh0eXBlb2Ygb2JqZWN0W3Byb3BdID09PSAnb2JqZWN0JykgewogICAgICAgIG9iamVjdFtwcm9wXSA9IHdpcmVTdGF0ZShvYmplY3RbcHJvcF0sIG9iamVjdCwgbmFtZSArICcuJyArIHByb3ApOwogICAgICB9CiAgICB9CgogICAgcmV0dXJuIG9iamVjdDsKICB9CgogIHZhciBSb290U3RhdGUkMSA9IHdpcmVTdGF0ZShSb290U3RhdGUsIG51bGwsICdyb290Jyk7CgogIC8qCiAgICogUmV0dXJucyB0aGUgUmVjb3JkRGF0YSBpbnN0YW5jZSBhc3NvY2lhdGVkIHdpdGggYSBnaXZlbgogICAqIE1vZGVsIG9yIEludGVybmFsTW9kZWwuCiAgICoKICAgKiBJbnRlbnRpb25hbGx5ICJsb29zZSIgdG8gYWxsb3cgYW55dGhpbmcgd2l0aCBhbiBfaW50ZXJuYWxNb2RlbAogICAqIHByb3BlcnR5IHVudGlsIEludGVybmFsTW9kZWwgaXMgZWxpbWluYXRlZC4KICAgKgogICAqIEludGVudGlvbmFsbHkgbm90IHR5cGVkIHRvIGBJbnRlcm5hbE1vZGVsYCBkdWUgdG8gY2lyY3VsYXIgZGVwZW5kZW5jeQogICAqICB3aGljaCB0aGF0IGNyZWF0ZXMuCiAgICoKICAgKiBPdmVydGltZSwgdGhpcyBzaG91bGQgc2hpZnQgdG8gYSAid2Vha21hcCIgYmFzZWQgbG9va3VwIGluIHRoZQogICAqICAiRW1iZXIuZ2V0T3duZXIob2JqKSIgc3R5bGUuCiAgICovCiAgZnVuY3Rpb24gcmVjb3JkRGF0YUZvcihpbnN0YW5jZSkgewogICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnN0YW5jZS5faW50ZXJuYWxNb2RlbCB8fCBpbnN0YW5jZS5pbnRlcm5hbE1vZGVsIHx8IGluc3RhbmNlOwogICAgcmV0dXJuIGludGVybmFsTW9kZWwuX3JlY29yZERhdGEgfHwgbnVsbDsKICB9CgogIGZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyhDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIGZ1bmN0aW9uIHJlbGF0aW9uc2hpcHNGb3IoaW5zdGFuY2UpIHsKICAgIHZhciByZWNvcmREYXRhID0gcmVjb3JkRGF0YUZvcihpbnN0YW5jZSkgfHwgaW5zdGFuY2U7CiAgICByZXR1cm4gcmVjb3JkRGF0YS5fcmVsYXRpb25zaGlwczsKICB9CgogIGZ1bmN0aW9uIHJlbGF0aW9uc2hpcFN0YXRlRm9yKGluc3RhbmNlLCBwcm9wZXJ0eU5hbWUpIHsKICAgIHJldHVybiByZWxhdGlvbnNoaXBzRm9yKGluc3RhbmNlKS5nZXQocHJvcGVydHlOYW1lKTsKICB9CiAgLyoqCiAgICBAY2xhc3MgU25hcHNob3QKICAgIEBwcml2YXRlCiAgICBAY29uc3RydWN0b3IKICAgIEBwYXJhbSB7TW9kZWx9IGludGVybmFsTW9kZWwgVGhlIG1vZGVsIHRvIGNyZWF0ZSBhIHNuYXBzaG90IGZyb20KICAqLwoKCiAgdmFyIFNuYXBzaG90ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gU25hcHNob3Qob3B0aW9ucywgaWRlbnRpZmllciwgc3RvcmUpIHsKICAgICAgdGhpcy5fX2F0dHJpYnV0ZXMgPSBudWxsOwogICAgICB0aGlzLl9iZWxvbmdzVG9SZWxhdGlvbnNoaXBzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGhpcy5fYmVsb25nc1RvSWRzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGhpcy5faGFzTWFueVJlbGF0aW9uc2hpcHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9oYXNNYW55SWRzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKCiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gdGhpcy5faW50ZXJuYWxNb2RlbCA9IHN0b3JlLl9pbnRlcm5hbE1vZGVsRm9yUmVzb3VyY2UoaWRlbnRpZmllcik7CgogICAgICB0aGlzLl9zdG9yZSA9IHN0b3JlOwogICAgICB0aGlzLm1vZGVsTmFtZSA9IGlkZW50aWZpZXIudHlwZTsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICB0aGlzLmlkZW50aWZpZXIgPSBpZGVudGlmaWVyOwogICAgICB9CiAgICAgIC8qCiAgICAgICAgSWYgdGhlIGludGVybmFsTW9kZWwgZG9lcyBub3QgeWV0IGhhdmUgYSByZWNvcmQsIHRoZW4gd2UgYXJlCiAgICAgICAgbGlrZWx5IGEgc25hcHNob3QgYmVpbmcgcHJvdmlkZWQgdG8gYSBmaW5kIHJlcXVlc3QsIHNvIHdlCiAgICAgICAgcG9wdWxhdGUgX19hdHRyaWJ1dGVzIGxhemlseS4gRWxzZSwgdG8gcHJlc2VydmUgdGhlICJtb21lbnQKICAgICAgICBpbiB0aW1lIiBpbiB3aGljaCBhIHNuYXBzaG90IGlzIGNyZWF0ZWQsIHdlIGdyZWVkaWx5IGdyYWIKICAgICAgICB0aGUgdmFsdWVzLgogICAgICAgKi8KCgogICAgICBpZiAoaW50ZXJuYWxNb2RlbC5oYXNSZWNvcmQpIHsKICAgICAgICB0aGlzLl9hdHRyaWJ1dGVzOwogICAgICB9CiAgICAgIC8qKk8KICAgICAgIFRoZSBpZCBvZiB0aGUgc25hcHNob3QncyB1bmRlcmx5aW5nIHJlY29yZAogICAgICAgIEV4YW1wbGUKICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgICAvLyBzdG9yZS5wdXNoKCdwb3N0JywgeyBpZDogMSwgYXV0aG9yOiAnVG9tc3RlcicsIHRpdGxlOiAnRW1iZXIuanMgcm9ja3MnIH0pOwogICAgICAgcG9zdFNuYXBzaG90LmlkOyAvLyA9PiAnMScKICAgICAgIGBgYAogICAgICAgIEBwcm9wZXJ0eSBpZAogICAgICAgQHR5cGUge1N0cmluZ30KICAgICAgICovCgoKICAgICAgdGhpcy5pZCA9IGlkZW50aWZpZXIuaWQ7CiAgICAgIC8qKgogICAgICAgQSBoYXNoIG9mIGFkYXB0ZXIgb3B0aW9ucwogICAgICAgQHByb3BlcnR5IGFkYXB0ZXJPcHRpb25zCiAgICAgICBAdHlwZSB7T2JqZWN0fQogICAgICAgKi8KCiAgICAgIHRoaXMuYWRhcHRlck9wdGlvbnMgPSBvcHRpb25zLmFkYXB0ZXJPcHRpb25zOwogICAgICB0aGlzLmluY2x1ZGUgPSBvcHRpb25zLmluY2x1ZGU7CiAgICAgIC8qKgogICAgICAgVGhlIG5hbWUgb2YgdGhlIHR5cGUgb2YgdGhlIHVuZGVybHlpbmcgcmVjb3JkIGZvciB0aGlzIHNuYXBzaG90LCBhcyBhIHN0cmluZy4KICAgICAgICBAcHJvcGVydHkgbW9kZWxOYW1lCiAgICAgICBAdHlwZSB7U3RyaW5nfQogICAgICAgKi8KCiAgICAgIHRoaXMubW9kZWxOYW1lID0gaW50ZXJuYWxNb2RlbC5tb2RlbE5hbWU7CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbC5oYXNSZWNvcmQpIHsKICAgICAgICB0aGlzLl9jaGFuZ2VkQXR0cmlidXRlcyA9IHJlY29yZERhdGFGb3IoaW50ZXJuYWxNb2RlbCkuY2hhbmdlZEF0dHJpYnV0ZXMoKTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgVGhlIHVuZGVybHlpbmcgcmVjb3JkIGZvciB0aGlzIHNuYXBzaG90LiBDYW4gYmUgdXNlZCB0byBhY2Nlc3MgbWV0aG9kcyBhbmQKICAgICBwcm9wZXJ0aWVzIGRlZmluZWQgb24gdGhlIHJlY29yZC4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IGpzb24gPSBzbmFwc2hvdC5yZWNvcmQudG9KU09OKCk7CiAgICAgYGBgCiAgICAgIEBwcm9wZXJ0eSByZWNvcmQKICAgICBAdHlwZSB7TW9kZWx9CiAgICAgKi8KCgogICAgdmFyIF9wcm90byA9IFNuYXBzaG90LnByb3RvdHlwZTsKCiAgICAvKioKICAgICBSZXR1cm5zIHRoZSB2YWx1ZSBvZiBhbiBhdHRyaWJ1dGUuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgamF2YXNjcmlwdAogICAgIC8vIHN0b3JlLnB1c2goJ3Bvc3QnLCB7IGlkOiAxLCBhdXRob3I6ICdUb21zdGVyJywgdGl0bGU6ICdFbWJlci5qcyByb2NrcycgfSk7CiAgICAgcG9zdFNuYXBzaG90LmF0dHIoJ2F1dGhvcicpOyAvLyA9PiAnVG9tc3RlcicKICAgICBwb3N0U25hcHNob3QuYXR0cigndGl0bGUnKTsgLy8gPT4gJ0VtYmVyLmpzIHJvY2tzJwogICAgIGBgYAogICAgICBOb3RlOiBWYWx1ZXMgYXJlIGxvYWRlZCBlYWdlcmx5IGFuZCBjYWNoZWQgd2hlbiB0aGUgc25hcHNob3QgaXMgY3JlYXRlZC4KICAgICAgQG1ldGhvZCBhdHRyCiAgICAgQHBhcmFtIHtTdHJpbmd9IGtleU5hbWUKICAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSBhdHRyaWJ1dGUgdmFsdWUgb3IgdW5kZWZpbmVkCiAgICAgKi8KICAgIF9wcm90by5hdHRyID0gZnVuY3Rpb24gYXR0cihrZXlOYW1lKSB7CiAgICAgIGlmIChrZXlOYW1lIGluIHRoaXMuX2F0dHJpYnV0ZXMpIHsKICAgICAgICByZXR1cm4gdGhpcy5fYXR0cmlidXRlc1trZXlOYW1lXTsKICAgICAgfQoKICAgICAgdGhyb3cgbmV3IEVtYmVyLkVycm9yKCJNb2RlbCAnIiArIEVtYmVyLmluc3BlY3QodGhpcy5yZWNvcmQpICsgIicgaGFzIG5vIGF0dHJpYnV0ZSBuYW1lZCAnIiArIGtleU5hbWUgKyAiJyBkZWZpbmVkLiIpOwogICAgfQogICAgLyoqCiAgICAgUmV0dXJucyBhbGwgYXR0cmlidXRlcyBhbmQgdGhlaXIgY29ycmVzcG9uZGluZyB2YWx1ZXMuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgamF2YXNjcmlwdAogICAgIC8vIHN0b3JlLnB1c2goJ3Bvc3QnLCB7IGlkOiAxLCBhdXRob3I6ICdUb21zdGVyJywgdGl0bGU6ICdFbWJlci5qcyByb2NrcycgfSk7CiAgICAgcG9zdFNuYXBzaG90LmF0dHJpYnV0ZXMoKTsgLy8gPT4geyBhdXRob3I6ICdUb21zdGVyJywgdGl0bGU6ICdFbWJlci5qcyByb2NrcycgfQogICAgIGBgYAogICAgICBAbWV0aG9kIGF0dHJpYnV0ZXMKICAgICBAcmV0dXJuIHtPYmplY3R9IEFsbCBhdHRyaWJ1dGVzIG9mIHRoZSBjdXJyZW50IHNuYXBzaG90CiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uYXR0cmlidXRlcyA9IGZ1bmN0aW9uIGF0dHJpYnV0ZXMoKSB7CiAgICAgIHJldHVybiBFbWJlci5hc3NpZ24oe30sIHRoaXMuX2F0dHJpYnV0ZXMpOwogICAgfQogICAgLyoqCiAgICAgUmV0dXJucyBhbGwgY2hhbmdlZCBhdHRyaWJ1dGVzIGFuZCB0aGVpciBvbGQgYW5kIG5ldyB2YWx1ZXMuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgamF2YXNjcmlwdAogICAgIC8vIHN0b3JlLnB1c2goJ3Bvc3QnLCB7IGlkOiAxLCBhdXRob3I6ICdUb21zdGVyJywgdGl0bGU6ICdFbWJlci5qcyByb2NrcycgfSk7CiAgICAgcG9zdE1vZGVsLnNldCgndGl0bGUnLCAnRW1iZXIuanMgcm9ja3MhJyk7CiAgICAgcG9zdFNuYXBzaG90LmNoYW5nZWRBdHRyaWJ1dGVzKCk7IC8vID0+IHsgdGl0bGU6IFsnRW1iZXIuanMgcm9ja3MnLCAnRW1iZXIuanMgcm9ja3MhJ10gfQogICAgIGBgYAogICAgICBAbWV0aG9kIGNoYW5nZWRBdHRyaWJ1dGVzCiAgICAgQHJldHVybiB7T2JqZWN0fSBBbGwgY2hhbmdlZCBhdHRyaWJ1dGVzIG9mIHRoZSBjdXJyZW50IHNuYXBzaG90CiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uY2hhbmdlZEF0dHJpYnV0ZXMgPSBmdW5jdGlvbiBjaGFuZ2VkQXR0cmlidXRlcygpIHsKICAgICAgdmFyIGNoYW5nZWRBdHRyaWJ1dGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdmFyIGNoYW5nZWRBdHRyaWJ1dGVLZXlzID0gT2JqZWN0LmtleXModGhpcy5fY2hhbmdlZEF0dHJpYnV0ZXMpOwoKICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGNoYW5nZWRBdHRyaWJ1dGVLZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGtleSA9IGNoYW5nZWRBdHRyaWJ1dGVLZXlzW2ldOwogICAgICAgIGNoYW5nZWRBdHRyaWJ1dGVzW2tleV0gPSB0aGlzLl9jaGFuZ2VkQXR0cmlidXRlc1trZXldLnNsaWNlKCk7CiAgICAgIH0KCiAgICAgIHJldHVybiBjaGFuZ2VkQXR0cmlidXRlczsKICAgIH0KICAgIC8qKgogICAgIFJldHVybnMgdGhlIGN1cnJlbnQgdmFsdWUgb2YgYSBiZWxvbmdzVG8gcmVsYXRpb25zaGlwLgogICAgICBgYmVsb25nc1RvYCB0YWtlcyBhbiBvcHRpb25hbCBoYXNoIG9mIG9wdGlvbnMgYXMgYSBzZWNvbmQgcGFyYW1ldGVyLAogICAgIGN1cnJlbnRseSBzdXBwb3J0ZWQgb3B0aW9ucyBhcmU6CiAgICAgIC0gYGlkYDogc2V0IHRvIGB0cnVlYCBpZiB5b3Ugb25seSB3YW50IHRoZSBJRCBvZiB0aGUgcmVsYXRlZCByZWNvcmQgdG8gYmUKICAgICByZXR1cm5lZC4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgLy8gc3RvcmUucHVzaCgncG9zdCcsIHsgaWQ6IDEsIHRpdGxlOiAnSGVsbG8gV29ybGQnIH0pOwogICAgIC8vIHN0b3JlLmNyZWF0ZVJlY29yZCgnY29tbWVudCcsIHsgYm9keTogJ0xvcmVtIGlwc3VtJywgcG9zdDogcG9zdCB9KTsKICAgICBjb21tZW50U25hcHNob3QuYmVsb25nc1RvKCdwb3N0Jyk7IC8vID0+IFNuYXBzaG90CiAgICAgY29tbWVudFNuYXBzaG90LmJlbG9uZ3NUbygncG9zdCcsIHsgaWQ6IHRydWUgfSk7IC8vID0+ICcxJwogICAgICAvLyBzdG9yZS5wdXNoKCdjb21tZW50JywgeyBpZDogMSwgYm9keTogJ0xvcmVtIGlwc3VtJyB9KTsKICAgICBjb21tZW50U25hcHNob3QuYmVsb25nc1RvKCdwb3N0Jyk7IC8vID0+IHVuZGVmaW5lZAogICAgIGBgYAogICAgICBDYWxsaW5nIGBiZWxvbmdzVG9gIHdpbGwgcmV0dXJuIGEgbmV3IFNuYXBzaG90IGFzIGxvbmcgYXMgdGhlcmUncyBhbnkga25vd24KICAgICBkYXRhIGZvciB0aGUgcmVsYXRpb25zaGlwIGF2YWlsYWJsZSwgc3VjaCBhcyBhbiBJRC4gSWYgdGhlIHJlbGF0aW9uc2hpcCBpcwogICAgIGtub3duIGJ1dCB1bnNldCwgYGJlbG9uZ3NUb2Agd2lsbCByZXR1cm4gYG51bGxgLiBJZiB0aGUgY29udGVudHMgb2YgdGhlCiAgICAgcmVsYXRpb25zaGlwIGlzIHVua25vd24gYGJlbG9uZ3NUb2Agd2lsbCByZXR1cm4gYHVuZGVmaW5lZGAuCiAgICAgIE5vdGU6IFJlbGF0aW9uc2hpcHMgYXJlIGxvYWRlZCBsYXppbHkgYW5kIGNhY2hlZCB1cG9uIGZpcnN0IGFjY2Vzcy4KICAgICAgQG1ldGhvZCBiZWxvbmdzVG8KICAgICBAcGFyYW0ge1N0cmluZ30ga2V5TmFtZQogICAgIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10KICAgICBAcmV0dXJuIHsoU25hcHNob3R8U3RyaW5nfG51bGx8dW5kZWZpbmVkKX0gQSBzbmFwc2hvdCBvciBJRCBvZiBhIGtub3duCiAgICAgcmVsYXRpb25zaGlwIG9yIG51bGwgaWYgdGhlIHJlbGF0aW9uc2hpcCBpcyBrbm93biBidXQgdW5zZXQuIHVuZGVmaW5lZAogICAgIHdpbGwgYmUgcmV0dXJuZWQgaWYgdGhlIGNvbnRlbnRzIG9mIHRoZSByZWxhdGlvbnNoaXAgaXMgdW5rbm93bi4KICAgICAqLwogICAgOwoKICAgIF9wcm90by5iZWxvbmdzVG8gPSBmdW5jdGlvbiBiZWxvbmdzVG8oa2V5TmFtZSwgb3B0aW9ucykgewogICAgICB2YXIgaWQgPSBvcHRpb25zICYmIG9wdGlvbnMuaWQ7CiAgICAgIHZhciByZWxhdGlvbnNoaXA7CiAgICAgIHZhciBpbnZlcnNlSW50ZXJuYWxNb2RlbDsKICAgICAgdmFyIHJlc3VsdDsKICAgICAgdmFyIHN0b3JlID0gdGhpcy5faW50ZXJuYWxNb2RlbC5zdG9yZTsKCiAgICAgIGlmIChpZCAmJiBrZXlOYW1lIGluIHRoaXMuX2JlbG9uZ3NUb0lkcykgewogICAgICAgIHJldHVybiB0aGlzLl9iZWxvbmdzVG9JZHNba2V5TmFtZV07CiAgICAgIH0KCiAgICAgIGlmICghaWQgJiYga2V5TmFtZSBpbiB0aGlzLl9iZWxvbmdzVG9SZWxhdGlvbnNoaXBzKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2JlbG9uZ3NUb1JlbGF0aW9uc2hpcHNba2V5TmFtZV07CiAgICAgIH0KCiAgICAgIHZhciByZWxhdGlvbnNoaXBNZXRhID0gc3RvcmUuX3JlbGF0aW9uc2hpcE1ldGFGb3IodGhpcy5tb2RlbE5hbWUsIG51bGwsIGtleU5hbWUpOwoKICAgICAgaWYgKCEocmVsYXRpb25zaGlwTWV0YSAmJiByZWxhdGlvbnNoaXBNZXRhLmtpbmQgPT09ICdiZWxvbmdzVG8nKSkgewogICAgICAgIHRocm93IG5ldyBFbWJlci5FcnJvcigiTW9kZWwgJyIgKyBFbWJlci5pbnNwZWN0KHRoaXMucmVjb3JkKSArICInIGhhcyBubyBiZWxvbmdzVG8gcmVsYXRpb25zaGlwIG5hbWVkICciICsga2V5TmFtZSArICInIGRlZmluZWQuIik7CiAgICAgIH0KCiAgICAgIHJlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcFN0YXRlRm9yKHRoaXMsIGtleU5hbWUpOwogICAgICB2YXIgdmFsdWUgPSByZWxhdGlvbnNoaXAuZ2V0RGF0YSgpOwogICAgICB2YXIgZGF0YSA9IHZhbHVlICYmIHZhbHVlLmRhdGE7CiAgICAgIGludmVyc2VJbnRlcm5hbE1vZGVsID0gZGF0YSAmJiBzdG9yZS5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlKGRhdGEpOwoKICAgICAgaWYgKHZhbHVlICYmIHZhbHVlLmRhdGEgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGlmIChpbnZlcnNlSW50ZXJuYWxNb2RlbCAmJiAhaW52ZXJzZUludGVybmFsTW9kZWwuaXNEZWxldGVkKCkpIHsKICAgICAgICAgIGlmIChpZCkgewogICAgICAgICAgICByZXN1bHQgPSBFbWJlci5nZXQoaW52ZXJzZUludGVybmFsTW9kZWwsICdpZCcpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmVzdWx0ID0gaW52ZXJzZUludGVybmFsTW9kZWwuY3JlYXRlU25hcHNob3QoKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzdWx0ID0gbnVsbDsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChpZCkgewogICAgICAgIHRoaXMuX2JlbG9uZ3NUb0lkc1trZXlOYW1lXSA9IHJlc3VsdDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLl9iZWxvbmdzVG9SZWxhdGlvbnNoaXBzW2tleU5hbWVdID0gcmVzdWx0OwogICAgICB9CgogICAgICByZXR1cm4gcmVzdWx0OwogICAgfQogICAgLyoqCiAgICAgUmV0dXJucyB0aGUgY3VycmVudCB2YWx1ZSBvZiBhIGhhc01hbnkgcmVsYXRpb25zaGlwLgogICAgICBgaGFzTWFueWAgdGFrZXMgYW4gb3B0aW9uYWwgaGFzaCBvZiBvcHRpb25zIGFzIGEgc2Vjb25kIHBhcmFtZXRlciwKICAgICBjdXJyZW50bHkgc3VwcG9ydGVkIG9wdGlvbnMgYXJlOgogICAgICAtIGBpZHNgOiBzZXQgdG8gYHRydWVgIGlmIHlvdSBvbmx5IHdhbnQgdGhlIElEcyBvZiB0aGUgcmVsYXRlZCByZWNvcmRzIHRvIGJlCiAgICAgcmV0dXJuZWQuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgamF2YXNjcmlwdAogICAgIC8vIHN0b3JlLnB1c2goJ3Bvc3QnLCB7IGlkOiAxLCB0aXRsZTogJ0hlbGxvIFdvcmxkJywgY29tbWVudHM6IFsyLCAzXSB9KTsKICAgICBwb3N0U25hcHNob3QuaGFzTWFueSgnY29tbWVudHMnKTsgLy8gPT4gW1NuYXBzaG90LCBTbmFwc2hvdF0KICAgICBwb3N0U25hcHNob3QuaGFzTWFueSgnY29tbWVudHMnLCB7IGlkczogdHJ1ZSB9KTsgLy8gPT4gWycyJywgJzMnXQogICAgICAvLyBzdG9yZS5wdXNoKCdwb3N0JywgeyBpZDogMSwgdGl0bGU6ICdIZWxsbyBXb3JsZCcgfSk7CiAgICAgcG9zdFNuYXBzaG90Lmhhc01hbnkoJ2NvbW1lbnRzJyk7IC8vID0+IHVuZGVmaW5lZAogICAgIGBgYAogICAgICBOb3RlOiBSZWxhdGlvbnNoaXBzIGFyZSBsb2FkZWQgbGF6aWx5IGFuZCBjYWNoZWQgdXBvbiBmaXJzdCBhY2Nlc3MuCiAgICAgIEBtZXRob2QgaGFzTWFueQogICAgIEBwYXJhbSB7U3RyaW5nfSBrZXlOYW1lCiAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXQogICAgIEByZXR1cm4geyhBcnJheXx1bmRlZmluZWQpfSBBbiBhcnJheSBvZiBzbmFwc2hvdHMgb3IgSURzIG9mIGEga25vd24KICAgICByZWxhdGlvbnNoaXAgb3IgYW4gZW1wdHkgYXJyYXkgaWYgdGhlIHJlbGF0aW9uc2hpcCBpcyBrbm93biBidXQgdW5zZXQuCiAgICAgdW5kZWZpbmVkIHdpbGwgYmUgcmV0dXJuZWQgaWYgdGhlIGNvbnRlbnRzIG9mIHRoZSByZWxhdGlvbnNoaXAgaXMgdW5rbm93bi4KICAgICAqLwogICAgOwoKICAgIF9wcm90by5oYXNNYW55ID0gZnVuY3Rpb24gaGFzTWFueShrZXlOYW1lLCBvcHRpb25zKSB7CiAgICAgIHZhciBpZHMgPSBvcHRpb25zICYmIG9wdGlvbnMuaWRzOwogICAgICB2YXIgcmVsYXRpb25zaGlwOwogICAgICB2YXIgcmVzdWx0czsKCiAgICAgIGlmIChpZHMgJiYga2V5TmFtZSBpbiB0aGlzLl9oYXNNYW55SWRzKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2hhc01hbnlJZHNba2V5TmFtZV07CiAgICAgIH0KCiAgICAgIGlmICghaWRzICYmIGtleU5hbWUgaW4gdGhpcy5faGFzTWFueVJlbGF0aW9uc2hpcHMpIHsKICAgICAgICByZXR1cm4gdGhpcy5faGFzTWFueVJlbGF0aW9uc2hpcHNba2V5TmFtZV07CiAgICAgIH0KCiAgICAgIHZhciBzdG9yZSA9IHRoaXMuX2ludGVybmFsTW9kZWwuc3RvcmU7CgogICAgICB2YXIgcmVsYXRpb25zaGlwTWV0YSA9IHN0b3JlLl9yZWxhdGlvbnNoaXBNZXRhRm9yKHRoaXMubW9kZWxOYW1lLCBudWxsLCBrZXlOYW1lKTsKCiAgICAgIGlmICghKHJlbGF0aW9uc2hpcE1ldGEgJiYgcmVsYXRpb25zaGlwTWV0YS5raW5kID09PSAnaGFzTWFueScpKSB7CiAgICAgICAgdGhyb3cgbmV3IEVtYmVyLkVycm9yKCJNb2RlbCAnIiArIEVtYmVyLmluc3BlY3QodGhpcy5yZWNvcmQpICsgIicgaGFzIG5vIGhhc01hbnkgcmVsYXRpb25zaGlwIG5hbWVkICciICsga2V5TmFtZSArICInIGRlZmluZWQuIik7CiAgICAgIH0KCiAgICAgIHJlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcFN0YXRlRm9yKHRoaXMsIGtleU5hbWUpOwogICAgICB2YXIgdmFsdWUgPSByZWxhdGlvbnNoaXAuZ2V0RGF0YSgpOwoKICAgICAgaWYgKHZhbHVlLmRhdGEpIHsKICAgICAgICByZXN1bHRzID0gW107CiAgICAgICAgdmFsdWUuZGF0YS5mb3JFYWNoKGZ1bmN0aW9uIChtZW1iZXIpIHsKICAgICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gc3RvcmUuX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShtZW1iZXIpOwoKICAgICAgICAgIGlmICghaW50ZXJuYWxNb2RlbC5pc0RlbGV0ZWQoKSkgewogICAgICAgICAgICBpZiAoaWRzKSB7CiAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKG1lbWJlci5pZCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKGludGVybmFsTW9kZWwuY3JlYXRlU25hcHNob3QoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQoKICAgICAgaWYgKGlkcykgewogICAgICAgIHRoaXMuX2hhc01hbnlJZHNba2V5TmFtZV0gPSByZXN1bHRzOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuX2hhc01hbnlSZWxhdGlvbnNoaXBzW2tleU5hbWVdID0gcmVzdWx0czsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlc3VsdHM7CiAgICB9CiAgICAvKioKICAgICAgSXRlcmF0ZXMgdGhyb3VnaCBhbGwgdGhlIGF0dHJpYnV0ZXMgb2YgdGhlIG1vZGVsLCBjYWxsaW5nIHRoZSBwYXNzZWQKICAgICAgZnVuY3Rpb24gb24gZWFjaCBhdHRyaWJ1dGUuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHNuYXBzaG90LmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24obmFtZSwgbWV0YSkgewogICAgICAgIC8vIC4uLgogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIGVhY2hBdHRyaWJ1dGUKICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgdGhlIGNhbGxiYWNrIHRvIGV4ZWN1dGUKICAgICAgQHBhcmFtIHtPYmplY3R9IFtiaW5kaW5nXSB0aGUgdmFsdWUgdG8gd2hpY2ggdGhlIGNhbGxiYWNrJ3MgYHRoaXNgIHNob3VsZCBiZSBib3VuZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZWFjaEF0dHJpYnV0ZSA9IGZ1bmN0aW9uIGVhY2hBdHRyaWJ1dGUoY2FsbGJhY2ssIGJpbmRpbmcpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgIHZhciBhdHRyRGVmcyA9IHRoaXMuX3N0b3JlLl9hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvcih0aGlzLm1vZGVsTmFtZSwgdGhpcy5pZGVudGlmaWVyKTsKCiAgICAgICAgT2JqZWN0LmtleXMoYXR0ckRlZnMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgY2FsbGJhY2suY2FsbChiaW5kaW5nLCBrZXksIGF0dHJEZWZzW2tleV0pOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMucmVjb3JkLmVhY2hBdHRyaWJ1dGUoY2FsbGJhY2ssIGJpbmRpbmcpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgSXRlcmF0ZXMgdGhyb3VnaCBhbGwgdGhlIHJlbGF0aW9uc2hpcHMgb2YgdGhlIG1vZGVsLCBjYWxsaW5nIHRoZSBwYXNzZWQKICAgICAgZnVuY3Rpb24gb24gZWFjaCByZWxhdGlvbnNoaXAuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHNuYXBzaG90LmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24obmFtZSwgcmVsYXRpb25zaGlwKSB7CiAgICAgICAgLy8gLi4uCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgZWFjaFJlbGF0aW9uc2hpcAogICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayB0aGUgY2FsbGJhY2sgdG8gZXhlY3V0ZQogICAgICBAcGFyYW0ge09iamVjdH0gW2JpbmRpbmddIHRoZSB2YWx1ZSB0byB3aGljaCB0aGUgY2FsbGJhY2sncyBgdGhpc2Agc2hvdWxkIGJlIGJvdW5kCiAgICAqLwogICAgOwoKICAgIF9wcm90by5lYWNoUmVsYXRpb25zaGlwID0gZnVuY3Rpb24gZWFjaFJlbGF0aW9uc2hpcChjYWxsYmFjaywgYmluZGluZykgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgdmFyIHJlbGF0aW9uc2hpcERlZnMgPSB0aGlzLl9zdG9yZS5fcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IodGhpcy5tb2RlbE5hbWUsIHRoaXMuaWRlbnRpZmllcik7CgogICAgICAgIE9iamVjdC5rZXlzKHJlbGF0aW9uc2hpcERlZnMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgY2FsbGJhY2suY2FsbChiaW5kaW5nLCBrZXksIHJlbGF0aW9uc2hpcERlZnNba2V5XSk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5yZWNvcmQuZWFjaFJlbGF0aW9uc2hpcChjYWxsYmFjaywgYmluZGluZyk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBTZXJpYWxpemVzIHRoZSBzbmFwc2hvdCB1c2luZyB0aGUgc2VyaWFsaXplciBmb3IgdGhlIG1vZGVsLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlci5leHRlbmQoewogICAgICAgIGNyZWF0ZVJlY29yZChzdG9yZSwgdHlwZSwgc25hcHNob3QpIHsKICAgICAgICAgIHZhciBkYXRhID0gc25hcHNob3Quc2VyaWFsaXplKHsgaW5jbHVkZUlkOiB0cnVlIH0pOwogICAgICAgICAgdmFyIHVybCA9IGAvJHt0eXBlLm1vZGVsTmFtZX1gOwogICAgICAgICAgIHJldHVybiBmZXRjaCh1cmwsIHsKICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsCiAgICAgICAgICAgIGJvZHk6IGRhdGEsCiAgICAgICAgICB9KS50aGVuKChyZXNwb25zZSkgPT4gcmVzcG9uc2UuanNvbigpKQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzZXJpYWxpemUKICAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMKICAgICAgQHJldHVybiB7T2JqZWN0fSBhbiBvYmplY3Qgd2hvc2UgdmFsdWVzIGFyZSBwcmltaXRpdmUgSlNPTiB2YWx1ZXMgb25seQogICAgICovCiAgICA7CgogICAgX3Byb3RvLnNlcmlhbGl6ZSA9IGZ1bmN0aW9uIHNlcmlhbGl6ZShvcHRpb25zKSB7CiAgICAgIHJldHVybiB0aGlzLnJlY29yZC5zdG9yZS5zZXJpYWxpemVyRm9yKHRoaXMubW9kZWxOYW1lKS5zZXJpYWxpemUodGhpcywgb3B0aW9ucyk7CiAgICB9OwoKICAgIF9jcmVhdGVDbGFzcyhTbmFwc2hvdCwgW3sKICAgICAga2V5OiAicmVjb3JkIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2ludGVybmFsTW9kZWwuZ2V0UmVjb3JkKCk7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiX2F0dHJpYnV0ZXMiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgICB2YXIgYXR0cmlidXRlcyA9IHRoaXMuX19hdHRyaWJ1dGVzOwoKICAgICAgICBpZiAoYXR0cmlidXRlcyA9PT0gbnVsbCkgewogICAgICAgICAgdmFyIHJlY29yZCA9IHRoaXMucmVjb3JkOwogICAgICAgICAgYXR0cmlidXRlcyA9IHRoaXMuX19hdHRyaWJ1dGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgIHZhciBhdHRyczsKCiAgICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICAgIGF0dHJzID0gT2JqZWN0LmtleXModGhpcy5fc3RvcmUuX2F0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKHRoaXMubW9kZWxOYW1lLCB0aGlzLmlkZW50aWZpZXIpKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGF0dHJzID0gT2JqZWN0LmtleXModGhpcy5fc3RvcmUuX2F0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKHRoaXMubW9kZWxOYW1lLCByZWNvcmQuaWQpKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICAgIGF0dHJzLmZvckVhY2goZnVuY3Rpb24gKGtleU5hbWUpIHsKICAgICAgICAgICAgICBpZiAoX3RoaXMudHlwZS5pc01vZGVsKSB7CiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzW2tleU5hbWVdID0gRW1iZXIuZ2V0KHJlY29yZCwga2V5TmFtZSk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXNba2V5TmFtZV0gPSByZWNvcmREYXRhRm9yKF90aGlzLl9pbnRlcm5hbE1vZGVsKS5nZXRBdHRyKGtleU5hbWUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZWNvcmQuZWFjaEF0dHJpYnV0ZShmdW5jdGlvbiAoa2V5TmFtZSkgewogICAgICAgICAgICAgIHJldHVybiBhdHRyaWJ1dGVzW2tleU5hbWVdID0gRW1iZXIuZ2V0KHJlY29yZCwga2V5TmFtZSk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZXM7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICBUaGUgdHlwZSBvZiB0aGUgdW5kZXJseWluZyByZWNvcmQgZm9yIHRoaXMgc25hcHNob3QsIGFzIGEgTW9kZWwuCiAgICAgICAgQHByb3BlcnR5IHR5cGUKICAgICAgIEB0eXBlIHtNb2RlbH0KICAgICAgICovCgogICAgfSwgewogICAgICBrZXk6ICJ0eXBlIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgLy8gVE9ETyBAcnVuc3BpcmVkIHdlIHNob3VsZCBkZXByZWNhdGUgdGhpcyBpbiBmYXZvciBvZiBtb2RlbENsYXNzIGJ1dCBvbmx5IG9uY2UKICAgICAgICAvLyB3ZSd2ZSBjbGVhbmVkIHVwIHRoZSBpbnRlcm5hbHMgZW5vdWdoIHRoYXQgYSBwdWJsaWMgY2hhbmdlIHRvIGZvbGxvdyBzdWl0ZSBpcwogICAgICAgIC8vIHVuY29udHJvdmVyc2lhbC4KICAgICAgICByZXR1cm4gdGhpcy5faW50ZXJuYWxNb2RlbC5tb2RlbENsYXNzOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImlzTmV3IiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKCFjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaXNOZXcgaXMgb25seSBhdmFpbGFibGUgd2hlbiBjdXN0b20gbW9kZWwgY2xhc3MgZmYgaXMgb24nKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9pbnRlcm5hbE1vZGVsLmlzTmV3KCk7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gU25hcHNob3Q7CiAgfSgpOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICAvKgogICAgQSBgUHJvbWlzZUFycmF5YCBpcyBhbiBvYmplY3QgdGhhdCBhY3RzIGxpa2UgYm90aCBhbiBgRW1iZXIuQXJyYXlgCiAgICBhbmQgYSBwcm9taXNlLiBXaGVuIHRoZSBwcm9taXNlIGlzIHJlc29sdmVkIHRoZSByZXN1bHRpbmcgdmFsdWUKICAgIHdpbGwgYmUgc2V0IHRvIHRoZSBgUHJvbWlzZUFycmF5YCdzIGBjb250ZW50YCBwcm9wZXJ0eS4gVGhpcyBtYWtlcwogICAgaXQgZWFzeSB0byBjcmVhdGUgZGF0YSBiaW5kaW5ncyB3aXRoIHRoZSBgUHJvbWlzZUFycmF5YCB0aGF0IHdpbGwgYmUKICAgIHVwZGF0ZWQgd2hlbiB0aGUgcHJvbWlzZSByZXNvbHZlcy4KCiAgICBGb3IgbW9yZSBpbmZvcm1hdGlvbiBzZWUgdGhlIFtFbWJlci5Qcm9taXNlUHJveHlNaXhpbgogICAgZG9jdW1lbnRhdGlvbl0oL2FwaS9jbGFzc2VzL0VtYmVyLlByb21pc2VQcm94eU1peGluLmh0bWwpLgoKICAgIEV4YW1wbGUKCiAgICBgYGBqYXZhc2NyaXB0CiAgICBsZXQgcHJvbWlzZUFycmF5ID0gUHJvbWlzZUFycmF5LmNyZWF0ZSh7CiAgICAgIHByb21pc2U6ICQuZ2V0SlNPTignL3NvbWUvcmVtb3RlL2RhdGEuanNvbicpCiAgICB9KTsKCiAgICBwcm9taXNlQXJyYXkuZ2V0KCdsZW5ndGgnKTsgLy8gMAoKICAgIHByb21pc2VBcnJheS50aGVuKGZ1bmN0aW9uKCkgewogICAgICBwcm9taXNlQXJyYXkuZ2V0KCdsZW5ndGgnKTsgLy8gMTAwCiAgICB9KTsKICAgIGBgYAoKICAgIEBjbGFzcyBQcm9taXNlQXJyYXkKICAgIEBleHRlbmRzIEVtYmVyLkFycmF5UHJveHkKICAgIEB1c2VzIEVtYmVyLlByb21pc2VQcm94eU1peGluCiAgKi8KCiAgdmFyIFByb21pc2VBcnJheSA9IEVtYmVyLkFycmF5UHJveHkuZXh0ZW5kKEVtYmVyLlByb21pc2VQcm94eU1peGluLCB7CiAgICBtZXRhOiBFbWJlci5jb21wdXRlZC5yZWFkcygnY29udGVudC5tZXRhJykKICB9KTsKICAvKgogICAgQSBgUHJvbWlzZU9iamVjdGAgaXMgYW4gb2JqZWN0IHRoYXQgYWN0cyBsaWtlIGJvdGggYW4gYEVtYmVyT2JqZWN0YAogICAgYW5kIGEgcHJvbWlzZS4gV2hlbiB0aGUgcHJvbWlzZSBpcyByZXNvbHZlZCwgdGhlbiB0aGUgcmVzdWx0aW5nIHZhbHVlCiAgICB3aWxsIGJlIHNldCB0byB0aGUgYFByb21pc2VPYmplY3RgJ3MgYGNvbnRlbnRgIHByb3BlcnR5LiBUaGlzIG1ha2VzCiAgICBpdCBlYXN5IHRvIGNyZWF0ZSBkYXRhIGJpbmRpbmdzIHdpdGggdGhlIGBQcm9taXNlT2JqZWN0YCB0aGF0IHdpbGwKICAgIGJlIHVwZGF0ZWQgd2hlbiB0aGUgcHJvbWlzZSByZXNvbHZlcy4KCiAgICBGb3IgbW9yZSBpbmZvcm1hdGlvbiBzZWUgdGhlIFtFbWJlci5Qcm9taXNlUHJveHlNaXhpbgogICAgZG9jdW1lbnRhdGlvbl0oL2FwaS9jbGFzc2VzL0VtYmVyLlByb21pc2VQcm94eU1peGluLmh0bWwpLgoKICAgIEV4YW1wbGUKCiAgICBgYGBqYXZhc2NyaXB0CiAgICBsZXQgcHJvbWlzZU9iamVjdCA9IFByb21pc2VPYmplY3QuY3JlYXRlKHsKICAgICAgcHJvbWlzZTogJC5nZXRKU09OKCcvc29tZS9yZW1vdGUvZGF0YS5qc29uJykKICAgIH0pOwoKICAgIHByb21pc2VPYmplY3QuZ2V0KCduYW1lJyk7IC8vIG51bGwKCiAgICBwcm9taXNlT2JqZWN0LnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgIHByb21pc2VPYmplY3QuZ2V0KCduYW1lJyk7IC8vICdUb21zdGVyJwogICAgfSk7CiAgICBgYGAKCiAgICBAY2xhc3MgUHJvbWlzZU9iamVjdAogICAgQGV4dGVuZHMgRW1iZXIuT2JqZWN0UHJveHkKICAgIEB1c2VzIEVtYmVyLlByb21pc2VQcm94eU1peGluCiAgKi8KCiAgdmFyIFByb21pc2VPYmplY3QgPSBFbWJlci5PYmplY3RQcm94eS5leHRlbmQoRW1iZXIuUHJvbWlzZVByb3h5TWl4aW4pOwogIGZ1bmN0aW9uIHByb21pc2VPYmplY3QocHJvbWlzZSwgbGFiZWwpIHsKICAgIHJldHVybiBQcm9taXNlT2JqZWN0LmNyZWF0ZSh7CiAgICAgIHByb21pc2U6IEVtYmVyLlJTVlAuUHJvbWlzZS5yZXNvbHZlKHByb21pc2UsIGxhYmVsKQogICAgfSk7CiAgfQogIGZ1bmN0aW9uIHByb21pc2VBcnJheShwcm9taXNlLCBsYWJlbCkgewogICAgcmV0dXJuIFByb21pc2VBcnJheS5jcmVhdGUoewogICAgICBwcm9taXNlOiBFbWJlci5SU1ZQLlByb21pc2UucmVzb2x2ZShwcm9taXNlLCBsYWJlbCkKICAgIH0pOwogIH0KICB2YXIgUHJvbWlzZUJlbG9uZ3NUbyA9IFByb21pc2VPYmplY3QuZXh0ZW5kKHsKICAgIC8vIHdlIGRvbid0IHByb3h5IG1ldGEgYmVjYXVzZSB3ZSB3b3VsZCBuZWVkIHRvIHByb3h5IGl0IHRvIHRoZSByZWxhdGlvbnNoaXAgc3RhdGUgY29udGFpbmVyCiAgICAvLyAgaG93ZXZlciwgbWV0YSBvbiByZWxhdGlvbnNoaXBzIGRvZXMgbm90IHRyaWdnZXIgY2hhbmdlIG5vdGlmaWNhdGlvbnMuCiAgICAvLyAgaWYgeW91IG5lZWQgcmVsYXRpb25zaGlwIG1ldGEsIHlvdSBzaG91bGQgZG8gYHJlY29yZC5iZWxvbmdzVG8ocmVsYXRpb25zaGlwTmFtZSkubWV0YSgpYAogICAgbWV0YTogRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgfSksCiAgICByZWxvYWQ6IGZ1bmN0aW9uIHJlbG9hZChvcHRpb25zKSB7CiAgICAgIHZhciBfdGhpcyA9IHRoaXM7CiAgICAgIHZhciBfdGhpcyRfYmVsb25nc1RvU3RhdGUgPSB0aGlzLl9iZWxvbmdzVG9TdGF0ZSwKICAgICAgICAgIGtleSA9IF90aGlzJF9iZWxvbmdzVG9TdGF0ZS5rZXksCiAgICAgICAgICBzdG9yZSA9IF90aGlzJF9iZWxvbmdzVG9TdGF0ZS5zdG9yZSwKICAgICAgICAgIG9yaWdpbmF0aW5nSW50ZXJuYWxNb2RlbCA9IF90aGlzJF9iZWxvbmdzVG9TdGF0ZS5vcmlnaW5hdGluZ0ludGVybmFsTW9kZWw7CiAgICAgIHJldHVybiBzdG9yZS5yZWxvYWRCZWxvbmdzVG8odGhpcywgb3JpZ2luYXRpbmdJbnRlcm5hbE1vZGVsLCBrZXksIG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBfdGhpczsKICAgICAgfSk7CiAgICB9CiAgfSk7CiAgZnVuY3Rpb24gcHJveHlUb0NvbnRlbnQobWV0aG9kKSB7CiAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICB2YXIgX0VtYmVyR2V0OwoKICAgICAgcmV0dXJuIChfRW1iZXJHZXQgPSBFbWJlci5nZXQodGhpcywgJ2NvbnRlbnQnKSlbbWV0aG9kXS5hcHBseShfRW1iZXJHZXQsIGFyZ3VtZW50cyk7CiAgICB9OwogIH0KICAvKgogICAgQSBQcm9taXNlTWFueUFycmF5IGlzIGEgUHJvbWlzZUFycmF5IHRoYXQgYWxzbyBwcm94aWVzIGNlcnRhaW4gbWV0aG9kIGNhbGxzCiAgICB0byB0aGUgdW5kZXJseWluZyBtYW55QXJyYXkuCiAgICBSaWdodCBub3cgd2UgcHJveHk6CgogICAgICAqIGByZWxvYWQoKWAKICAgICAgKiBgY3JlYXRlUmVjb3JkKClgCiAgICAgICogYG9uKClgCiAgICAgICogYG9uZSgpYAogICAgICAqIGB0cmlnZ2VyKClgCiAgICAgICogYG9mZigpYAogICAgICAqIGBoYXMoKWAKCiAgICBAY2xhc3MgUHJvbWlzZU1hbnlBcnJheQogICAgQGV4dGVuZHMgRW1iZXIuQXJyYXlQcm94eQogICovCgogIHZhciBQcm9taXNlTWFueUFycmF5ID0gUHJvbWlzZUFycmF5LmV4dGVuZCh7CiAgICBsaW5rczogY2FuYXJ5RmVhdHVyZXMuRlVMTF9MSU5LU19PTl9SRUxBVElPTlNISVBTID8gRW1iZXIuY29tcHV0ZWQucmVhZHMoJ2NvbnRlbnQubGlua3MnKSA6IHVuZGVmaW5lZCwKICAgIHJlbG9hZDogZnVuY3Rpb24gcmVsb2FkKG9wdGlvbnMpIHsKICAgICAgdGhpcy5zZXQoJ3Byb21pc2UnLCB0aGlzLmdldCgnY29udGVudCcpLnJlbG9hZChvcHRpb25zKSk7CiAgICAgIHJldHVybiB0aGlzOwogICAgfSwKICAgIGNyZWF0ZVJlY29yZDogcHJveHlUb0NvbnRlbnQoJ2NyZWF0ZVJlY29yZCcpLAogICAgb246IHByb3h5VG9Db250ZW50KCdvbicpLAogICAgb25lOiBwcm94eVRvQ29udGVudCgnb25lJyksCiAgICB0cmlnZ2VyOiBwcm94eVRvQ29udGVudCgndHJpZ2dlcicpLAogICAgb2ZmOiBwcm94eVRvQ29udGVudCgnb2ZmJyksCiAgICBoYXM6IHByb3h5VG9Db250ZW50KCdoYXMnKQogIH0pOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwogIGZ1bmN0aW9uIF9iaW5kKGZuKSB7CiAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuID4gMSA/IF9sZW4gLSAxIDogMCksIF9rZXkgPSAxOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgIGFyZ3NbX2tleSAtIDFdID0gYXJndW1lbnRzW19rZXldOwogICAgfQoKICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBmbi5hcHBseSh1bmRlZmluZWQsIGFyZ3MpOwogICAgfTsKICB9CiAgZnVuY3Rpb24gX2d1YXJkKHByb21pc2UsIHRlc3QpIHsKICAgIHZhciBndWFyZGVkID0gcHJvbWlzZS5maW5hbGx5KGZ1bmN0aW9uICgpIHsKICAgICAgaWYgKCF0ZXN0KCkpIHsKICAgICAgICBndWFyZGVkLl9zdWJzY3JpYmVycy5sZW5ndGggPSAwOwogICAgICB9CiAgICB9KTsKICAgIHJldHVybiBndWFyZGVkOwogIH0KICBmdW5jdGlvbiBfb2JqZWN0SXNBbGl2ZShvYmplY3QpIHsKICAgIHJldHVybiAhKEVtYmVyLmdldChvYmplY3QsICdpc0Rlc3Ryb3llZCcpIHx8IEVtYmVyLmdldChvYmplY3QsICdpc0Rlc3Ryb3lpbmcnKSk7CiAgfQogIGZ1bmN0aW9uIGd1YXJkRGVzdHJveWVkU3RvcmUocHJvbWlzZSwgc3RvcmUsIGxhYmVsKSB7CgogICAgdmFyIHdyYXBwZXJQcm9taXNlID0gRW1iZXIuUlNWUC5yZXNvbHZlKHByb21pc2UsIGxhYmVsKS50aGVuKGZ1bmN0aW9uICh2KSB7CiAgICAgIHJldHVybiBwcm9taXNlOwogICAgfSk7CiAgICByZXR1cm4gX2d1YXJkKHdyYXBwZXJQcm9taXNlLCBmdW5jdGlvbiAoKSB7CgogICAgICByZXR1cm4gX29iamVjdElzQWxpdmUoc3RvcmUpOwogICAgfSk7CiAgfQoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICAvKioKICAgIEBtZXRob2QgZGlmZkFycmF5CiAgICBAcHJpdmF0ZQogICAgQHBhcmFtIHtBcnJheX0gb2xkQXJyYXkgdGhlIG9sZCBhcnJheQogICAgQHBhcmFtIHtBcnJheX0gbmV3QXJyYXkgdGhlIG5ldyBhcnJheQogICAgQHJldHVybiB7aGFzaH0gewogICAgICAgIGZpcnN0Q2hhbmdlSW5kZXg6IDxpbnRlZ2VyPiwgIC8vIG51bGwgaWYgbm8gY2hhbmdlCiAgICAgICAgYWRkZWRDb3VudDogPGludGVnZXI+LCAgICAgICAgLy8gMCBpZiBubyBjaGFuZ2UKICAgICAgICByZW1vdmVkQ291bnQ6IDxpbnRlZ2VyPiAgICAgICAvLyAwIGlmIG5vIGNoYW5nZQogICAgICB9CiAgKi8KICBmdW5jdGlvbiBkaWZmQXJyYXkob2xkQXJyYXksIG5ld0FycmF5KSB7CiAgICB2YXIgb2xkTGVuZ3RoID0gb2xkQXJyYXkubGVuZ3RoOwogICAgdmFyIG5ld0xlbmd0aCA9IG5ld0FycmF5Lmxlbmd0aDsKICAgIHZhciBzaG9ydGVzdExlbmd0aCA9IE1hdGgubWluKG9sZExlbmd0aCwgbmV3TGVuZ3RoKTsKICAgIHZhciBmaXJzdENoYW5nZUluZGV4ID0gbnVsbDsgLy8gbnVsbCBzaWduaWZpZXMgbm8gY2hhbmdlcwogICAgLy8gZmluZCB0aGUgZmlyc3QgY2hhbmdlCgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaG9ydGVzdExlbmd0aDsgaSsrKSB7CiAgICAgIC8vIGNvbXBhcmUgZWFjaCBpdGVtIGluIHRoZSBhcnJheQogICAgICBpZiAob2xkQXJyYXlbaV0gIT09IG5ld0FycmF5W2ldKSB7CiAgICAgICAgZmlyc3RDaGFuZ2VJbmRleCA9IGk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KCiAgICBpZiAoZmlyc3RDaGFuZ2VJbmRleCA9PT0gbnVsbCAmJiBuZXdMZW5ndGggIT09IG9sZExlbmd0aCkgewogICAgICAvLyBubyBjaGFuZ2UgZm91bmQgaW4gdGhlIG92ZXJsYXBwaW5nIGJsb2NrCiAgICAgIC8vIGFuZCBhcnJheSBsZW5ndGhzIGRpZmZlciwKICAgICAgLy8gc28gY2hhbmdlIHN0YXJ0cyBhdCBlbmQgb2Ygb3ZlcmxhcAogICAgICBmaXJzdENoYW5nZUluZGV4ID0gc2hvcnRlc3RMZW5ndGg7CiAgICB9CgogICAgdmFyIGFkZGVkQ291bnQgPSAwOwogICAgdmFyIHJlbW92ZWRDb3VudCA9IDA7CgogICAgaWYgKGZpcnN0Q2hhbmdlSW5kZXggIT09IG51bGwpIHsKICAgICAgLy8gd2UgZm91bmQgYSBjaGFuZ2UsIGZpbmQgdGhlIGVuZCBvZiB0aGUgY2hhbmdlCiAgICAgIHZhciB1bmNoYW5nZWRFbmRCbG9ja0xlbmd0aCA9IHNob3J0ZXN0TGVuZ3RoIC0gZmlyc3RDaGFuZ2VJbmRleDsgLy8gd2FsayBiYWNrIGZyb20gdGhlIGVuZCBvZiBib3RoIGFycmF5cyB1bnRpbCB3ZSBmaW5kIGEgY2hhbmdlCgogICAgICBmb3IgKHZhciBfaSA9IDE7IF9pIDw9IHNob3J0ZXN0TGVuZ3RoOyBfaSsrKSB7CiAgICAgICAgLy8gY29tcGFyZSBlYWNoIGl0ZW0gaW4gdGhlIGFycmF5CiAgICAgICAgaWYgKG9sZEFycmF5W29sZExlbmd0aCAtIF9pXSAhPT0gbmV3QXJyYXlbbmV3TGVuZ3RoIC0gX2ldKSB7CiAgICAgICAgICB1bmNoYW5nZWRFbmRCbG9ja0xlbmd0aCA9IF9pIC0gMTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQoKICAgICAgYWRkZWRDb3VudCA9IG5ld0xlbmd0aCAtIHVuY2hhbmdlZEVuZEJsb2NrTGVuZ3RoIC0gZmlyc3RDaGFuZ2VJbmRleDsKICAgICAgcmVtb3ZlZENvdW50ID0gb2xkTGVuZ3RoIC0gdW5jaGFuZ2VkRW5kQmxvY2tMZW5ndGggLSBmaXJzdENoYW5nZUluZGV4OwogICAgfQoKICAgIHJldHVybiB7CiAgICAgIGZpcnN0Q2hhbmdlSW5kZXg6IGZpcnN0Q2hhbmdlSW5kZXgsCiAgICAgIGFkZGVkQ291bnQ6IGFkZGVkQ291bnQsCiAgICAgIHJlbW92ZWRDb3VudDogcmVtb3ZlZENvdW50CiAgICB9OwogIH0KCiAgLy9pbXBvcnQgRXZlbnRlZCBmcm9tICdAZW1iZXIvb2JqZWN0L2V2ZW50ZWQnOwogIC8qKgogICAgQSBgTWFueUFycmF5YCBpcyBhIGBNdXRhYmxlQXJyYXlgIHRoYXQgcmVwcmVzZW50cyB0aGUgY29udGVudHMgb2YgYSBoYXMtbWFueQogICAgcmVsYXRpb25zaGlwLgoKICAgIFRoZSBgTWFueUFycmF5YCBpcyBpbnN0YW50aWF0ZWQgbGF6aWx5IHRoZSBmaXJzdCB0aW1lIHRoZSByZWxhdGlvbnNoaXAgaXMKICAgIHJlcXVlc3RlZC4KCiAgICAjIyMgSW52ZXJzZXMKCiAgICBPZnRlbiwgdGhlIHJlbGF0aW9uc2hpcHMgaW4gRW1iZXIgRGF0YSBhcHBsaWNhdGlvbnMgd2lsbCBoYXZlCiAgICBhbiBpbnZlcnNlLiBGb3IgZXhhbXBsZSwgaW1hZ2luZSB0aGUgZm9sbG93aW5nIG1vZGVscyBhcmUKICAgIGRlZmluZWQ6CgogICAgYGBgYXBwL21vZGVscy9wb3N0LmpzCiAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBjb21tZW50czogaGFzTWFueSgnY29tbWVudCcpCiAgICB9KTsKICAgIGBgYAoKICAgIGBgYGFwcC9tb2RlbHMvY29tbWVudC5qcwogICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKCiAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICBwb3N0OiBiZWxvbmdzVG8oJ3Bvc3QnKQogICAgfSk7CiAgICBgYGAKCiAgICBJZiB5b3UgY3JlYXRlZCBhIG5ldyBpbnN0YW5jZSBvZiBgUG9zdGAgYW5kIGFkZGVkCiAgICBhIGBDb21tZW50YCByZWNvcmQgdG8gaXRzIGBjb21tZW50c2AgaGFzLW1hbnkKICAgIHJlbGF0aW9uc2hpcCwgeW91IHdvdWxkIGV4cGVjdCB0aGUgY29tbWVudCdzIGBwb3N0YAogICAgcHJvcGVydHkgdG8gYmUgc2V0IHRvIHRoZSBwb3N0IHRoYXQgY29udGFpbmVkCiAgICB0aGUgaGFzLW1hbnkuCgogICAgV2UgY2FsbCB0aGUgcmVjb3JkIHRvIHdoaWNoIGEgcmVsYXRpb25zaGlwIGJlbG9uZ3MtdG8gdGhlCiAgICByZWxhdGlvbnNoaXAncyBfb3duZXJfLgoKICAgIEBjbGFzcyBNYW55QXJyYXkKICAgIEBleHRlbmRzIEVtYmVyT2JqZWN0CiAgICBAdXNlcyBFbWJlci5NdXRhYmxlQXJyYXksIEVtYmVyRGF0YS5EZXByZWNhdGVkRXZlbnQKICAqLwoKICB2YXIgTWFueUFycmF5ID0gRW1iZXIuT2JqZWN0LmV4dGVuZChFbWJlci5NdXRhYmxlQXJyYXksIERlcHJlY2F0ZWRFdmVudGVkLCB7CiAgICAvLyBoZXJlIHRvIG1ha2UgVFMgaGFwcHkKICAgIF9pbnZlcnNlSXNBc3luYzogZmFsc2UsCiAgICBpc0xvYWRlZDogZmFsc2UsCiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgICAvKioKICAgICAgVGhlIGxvYWRpbmcgc3RhdGUgb2YgdGhpcyBhcnJheQogICAgICAgQHByb3BlcnR5IHtCb29sZWFufSBpc0xvYWRlZAogICAgICAqLwoKCiAgICAgIHRoaXMuaXNMb2FkZWQgPSB0aGlzLmlzTG9hZGVkIHx8IGZhbHNlOwogICAgICB0aGlzLmxlbmd0aCA9IDA7CiAgICAgIC8qKgogICAgICBVc2VkIGZvciBhc3luYyBgaGFzTWFueWAgYXJyYXlzCiAgICAgIHRvIGtlZXAgdHJhY2sgb2Ygd2hlbiB0aGV5IHdpbGwgcmVzb2x2ZS4KICAgICAgIEBwcm9wZXJ0eSB7RW1iZXIuUlNWUC5Qcm9taXNlfSBwcm9taXNlCiAgICAgIEBwcml2YXRlCiAgICAgICovCgogICAgICB0aGlzLnByb21pc2UgPSBudWxsOwogICAgICAvKioKICAgICAgTWV0YWRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZSByZXF1ZXN0IGZvciBhc3luYyBoYXNNYW55IHJlbGF0aW9uc2hpcHMuCiAgICAgICBFeGFtcGxlCiAgICAgICBHaXZlbiB0aGF0IHRoZSBzZXJ2ZXIgcmV0dXJucyB0aGUgZm9sbG93aW5nIEpTT04gcGF5bG9hZCB3aGVuIGZldGNoaW5nIGEKICAgICAgaGFzTWFueSByZWxhdGlvbnNoaXA6CiAgICAgICBgYGBqcwogICAgICB7CiAgICAgICAgImNvbW1lbnRzIjogW3sKICAgICAgICAgICJpZCI6IDEsCiAgICAgICAgICAiY29tbWVudCI6ICJUaGlzIGlzIHRoZSBmaXJzdCBjb21tZW50IiwKICAgICAgICB9LCB7CiAgICAgIC8vIC4uLgogICAgICAgIH1dLAogICAgICAgICAibWV0YSI6IHsKICAgICAgICAgICJwYWdlIjogMSwKICAgICAgICAgICJ0b3RhbCI6IDUKICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBZb3UgY2FuIHRoZW4gYWNjZXNzIHRoZSBtZXRhZGF0YSB2aWEgdGhlIGBtZXRhYCBwcm9wZXJ0eToKICAgICAgIGBgYGpzCiAgICAgIHBvc3QuZ2V0KCdjb21tZW50cycpLnRoZW4oZnVuY3Rpb24oY29tbWVudHMpIHsKICAgICAgICB2YXIgbWV0YSA9IGNvbW1lbnRzLmdldCgnbWV0YScpOwogICAgICAgLy8gbWV0YS5wYWdlID0+IDEKICAgICAgLy8gbWV0YS50b3RhbCA9PiA1CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSB7T2JqZWN0fSBtZXRhCiAgICAgIEBwdWJsaWMKICAgICAgKi8KICAgICAgLy8gVE9ETyB0aGlzIGlzIGxpa2VseSBicm9rZW4gaW4gb3VyIHJlZmFjdG9yCgogICAgICB0aGlzLm1ldGEgPSB0aGlzLm1ldGEgfHwgbnVsbDsKICAgICAgLyoqCiAgICAgIGB0cnVlYCBpZiB0aGUgcmVsYXRpb25zaGlwIGlzIHBvbHltb3JwaGljLCBgZmFsc2VgIG90aGVyd2lzZS4KICAgICAgIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gaXNQb2x5bW9ycGhpYwogICAgICBAcHJpdmF0ZQogICAgICAqLwoKICAgICAgdGhpcy5pc1BvbHltb3JwaGljID0gdGhpcy5pc1BvbHltb3JwaGljIHx8IGZhbHNlOwogICAgICAvKioKICAgICAgVGhlIHJlbGF0aW9uc2hpcCB3aGljaCBtYW5hZ2VzIHRoaXMgYXJyYXkuCiAgICAgICBAcHJvcGVydHkge01hbnlSZWxhdGlvbnNoaXB9IHJlbGF0aW9uc2hpcAogICAgICBAcHJpdmF0ZQogICAgICAqLwoKICAgICAgdGhpcy5jdXJyZW50U3RhdGUgPSBbXTsKICAgICAgdGhpcy5mbHVzaENhbm9uaWNhbCh0aGlzLmluaXRpYWxTdGF0ZSwgZmFsc2UpOwogICAgfSwKICAgIC8vIFRPRE86IGlmKERFQlVHKQogICAgYW55VW5sb2FkZWQ6IGZ1bmN0aW9uIGFueVVubG9hZGVkKCkgewogICAgICAvLyBVc2UgYGZpbHRlclswXWAgYXMgb3Bwb3NlZCB0byBgZmluZGAgYmVjYXVzZSBvZiBJRTExCiAgICAgIHZhciB1bmxvYWRlZCA9IHRoaXMuY3VycmVudFN0YXRlLmZpbHRlcihmdW5jdGlvbiAoaW0pIHsKICAgICAgICByZXR1cm4gaW0uX2lzRGVtYXRlcmlhbGl6aW5nIHx8ICFpbS5pc0xvYWRlZCgpOwogICAgICB9KVswXTsKICAgICAgcmV0dXJuICEhdW5sb2FkZWQ7CiAgICB9LAogICAgcmVtb3ZlVW5sb2FkZWRJbnRlcm5hbE1vZGVsOiBmdW5jdGlvbiByZW1vdmVVbmxvYWRlZEludGVybmFsTW9kZWwoKSB7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jdXJyZW50U3RhdGUubGVuZ3RoOyArK2kpIHsKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IHRoaXMuY3VycmVudFN0YXRlW2ldOwogICAgICAgIHZhciBzaG91bGRSZW1vdmUgPSB2b2lkIDA7CgogICAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICAgIHNob3VsZFJlbW92ZSA9IGludGVybmFsTW9kZWwuX2lzRGVtYXRlcmlhbGl6aW5nOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzaG91bGRSZW1vdmUgPSBpbnRlcm5hbE1vZGVsLl9pc0RlbWF0ZXJpYWxpemluZyB8fCAhaW50ZXJuYWxNb2RlbC5pc0xvYWRlZCgpOwogICAgICAgIH0KCiAgICAgICAgaWYgKHNob3VsZFJlbW92ZSkgewogICAgICAgICAgdGhpcy5hcnJheUNvbnRlbnRXaWxsQ2hhbmdlKGksIDEsIDApOwogICAgICAgICAgdGhpcy5jdXJyZW50U3RhdGUuc3BsaWNlKGksIDEpOwogICAgICAgICAgdGhpcy5zZXQoJ2xlbmd0aCcsIHRoaXMuY3VycmVudFN0YXRlLmxlbmd0aCk7CiAgICAgICAgICB0aGlzLmFycmF5Q29udGVudERpZENoYW5nZShpLCAxLCAwKTsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfSwKICAgIG9iamVjdEF0OiBmdW5jdGlvbiBvYmplY3RBdChpbmRleCkgewogICAgICAvLyBUT0RPIHdlIGxpa2VseSBuZWVkIHRvIGZvcmNlIGZsdXNoIGhlcmUKCiAgICAgIC8qCiAgICAgIGlmICh0aGlzLnJlbGF0aW9uc2hpcC5fd2lsbFVwZGF0ZU1hbnlBcnJheSkgewogICAgICAgIHRoaXMucmVsYXRpb25zaGlwLl9mbHVzaFBlbmRpbmdNYW55QXJyYXlVcGRhdGVzKCk7CiAgICAgIH0KICAgICAgKi8KICAgICAgdmFyIGludGVybmFsTW9kZWwgPSB0aGlzLmN1cnJlbnRTdGF0ZVtpbmRleF07CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5nZXRSZWNvcmQoKTsKICAgIH0sCiAgICBmbHVzaENhbm9uaWNhbDogZnVuY3Rpb24gZmx1c2hDYW5vbmljYWwodG9TZXQsIGlzSW5pdGlhbGl6ZWQpIHsKICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgPT09IHZvaWQgMCkgewogICAgICAgIGlzSW5pdGlhbGl6ZWQgPSB0cnVlOwogICAgICB9CgogICAgICAvLyBJdOKAmXMgcG9zc2libGUgdGhlIHBhcmVudCBzaWRlIG9mIHRoZSByZWxhdGlvbnNoaXAgbWF5IGhhdmUgYmVlbiB1bmxvYWRlZCBieSB0aGlzIHBvaW50CiAgICAgIGlmICghX29iamVjdElzQWxpdmUodGhpcykpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gLy8gZGlmZiB0byBmaW5kIGNoYW5nZXMKCgogICAgICB2YXIgZGlmZiA9IGRpZmZBcnJheSh0aGlzLmN1cnJlbnRTdGF0ZSwgdG9TZXQpOwoKICAgICAgaWYgKGRpZmYuZmlyc3RDaGFuZ2VJbmRleCAhPT0gbnVsbCkgewogICAgICAgIC8vIGl0J3MgbnVsbCBpZiBubyBjaGFuZ2UgZm91bmQKICAgICAgICAvLyB3ZSBmb3VuZCBhIGNoYW5nZQogICAgICAgIHRoaXMuYXJyYXlDb250ZW50V2lsbENoYW5nZShkaWZmLmZpcnN0Q2hhbmdlSW5kZXgsIGRpZmYucmVtb3ZlZENvdW50LCBkaWZmLmFkZGVkQ291bnQpOwogICAgICAgIHRoaXMuc2V0KCdsZW5ndGgnLCB0b1NldC5sZW5ndGgpOwogICAgICAgIHRoaXMuY3VycmVudFN0YXRlID0gdG9TZXQuc2xpY2UoKTsKICAgICAgICB0aGlzLmFycmF5Q29udGVudERpZENoYW5nZShkaWZmLmZpcnN0Q2hhbmdlSW5kZXgsIGRpZmYucmVtb3ZlZENvdW50LCBkaWZmLmFkZGVkQ291bnQpOwoKICAgICAgICBpZiAoaXNJbml0aWFsaXplZCAmJiBkaWZmLmFkZGVkQ291bnQgPiAwKSB7CiAgICAgICAgICAvL25vdGlmeSBvbmx5IG9uIGFkZGl0aW9ucwogICAgICAgICAgLy9UT0RPIG9ubHkgbm90aWZ5IGlmIHVubG9hZGVkCiAgICAgICAgICB0aGlzLmludGVybmFsTW9kZWwubWFueUFycmF5UmVjb3JkQWRkZWQodGhpcy5nZXQoJ2tleScpKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0sCiAgICByZXBsYWNlOiBmdW5jdGlvbiByZXBsYWNlKGlkeCwgYW10LCBvYmplY3RzKSB7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsczsKCiAgICAgIGlmIChhbXQgPiAwKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbHMgPSB0aGlzLmN1cnJlbnRTdGF0ZS5zbGljZShpZHgsIGlkeCArIGFtdCk7CiAgICAgICAgdGhpcy5nZXQoJ3JlY29yZERhdGEnKS5yZW1vdmVGcm9tSGFzTWFueSh0aGlzLmdldCgna2V5JyksIGludGVybmFsTW9kZWxzLm1hcChmdW5jdGlvbiAoaW0pIHsKICAgICAgICAgIHJldHVybiByZWNvcmREYXRhRm9yKGltKTsKICAgICAgICB9KSk7CiAgICAgIH0KCiAgICAgIGlmIChvYmplY3RzKSB7CiAgICAgICAgdGhpcy5nZXQoJ3JlY29yZERhdGEnKS5hZGRUb0hhc01hbnkodGhpcy5nZXQoJ2tleScpLCBvYmplY3RzLm1hcChmdW5jdGlvbiAob2JqKSB7CiAgICAgICAgICByZXR1cm4gcmVjb3JkRGF0YUZvcihvYmopOwogICAgICAgIH0pLCBpZHgpOwogICAgICB9CgogICAgICB0aGlzLnJldHJpZXZlTGF0ZXN0KCk7CiAgICB9LAogICAgLy8gT2sgdGhpcyBpcyBraW5kYSBmdW5reSBiZWNhdXNlIGlmIGJ1Z2d5IHdlIG1pZ2h0IGxvc2UgcG9zaXRpb25zLCBldGMuCiAgICAvLyBidXQgY3VycmVudCBjb2RlIGlzIHRoaXMgd2F5IHNvIHNob3VsZG4ndCBiZSB0b28gYmlnIG9mIGEgcHJvYmxlbQogICAgcmV0cmlldmVMYXRlc3Q6IGZ1bmN0aW9uIHJldHJpZXZlTGF0ZXN0KCkgewogICAgICB2YXIganNvbkFwaSA9IHRoaXMuZ2V0KCdyZWNvcmREYXRhJykuZ2V0SGFzTWFueSh0aGlzLmdldCgna2V5JykpOyAvLyBUT0RPIHRoaXMgaXMgb2RkLCB3aHkgc2hvdWxkIE1hbnlBcnJheSBldmVyIHRlbGwgaXRzZWxmIHRvIHJlc3luYz8KCiAgICAgIHZhciBpbnRlcm5hbE1vZGVscyA9IHRoaXMuc3RvcmUuX2dldEhhc01hbnlCeUpzb25BcGlSZXNvdXJjZShqc29uQXBpKTsKCiAgICAgIGlmIChqc29uQXBpLm1ldGEpIHsKICAgICAgICB0aGlzLnNldCgnbWV0YScsIGpzb25BcGkubWV0YSk7CiAgICAgIH0KCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5GVUxMX0xJTktTX09OX1JFTEFUSU9OU0hJUFMpIHsKICAgICAgICBpZiAoanNvbkFwaS5saW5rcykgewogICAgICAgICAgdGhpcy5zZXQoJ2xpbmtzJywganNvbkFwaS5saW5rcyk7CiAgICAgICAgfQogICAgICB9CgogICAgICB0aGlzLmZsdXNoQ2Fub25pY2FsKGludGVybmFsTW9kZWxzLCB0cnVlKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFJlbG9hZHMgYWxsIG9mIHRoZSByZWNvcmRzIGluIHRoZSBtYW55QXJyYXkuIElmIHRoZSBtYW55QXJyYXkKICAgICAgaG9sZHMgYSByZWxhdGlvbnNoaXAgdGhhdCB3YXMgb3JpZ2luYWxseSBmZXRjaGVkIHVzaW5nIGEgbGlua3MgdXJsCiAgICAgIEVtYmVyIERhdGEgd2lsbCByZXZpc2l0IHRoZSBvcmlnaW5hbCBsaW5rcyB1cmwgdG8gcmVwb3B1bGF0ZSB0aGUKICAgICAgcmVsYXRpb25zaGlwLgogICAgICAgSWYgdGhlIG1hbnlBcnJheSBob2xkcyB0aGUgcmVzdWx0IG9mIGEgYHN0b3JlLnF1ZXJ5KClgIHJlbG9hZCB3aWxsCiAgICAgIHJlLXJ1biB0aGUgb3JpZ2luYWwgcXVlcnkuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHZhciB1c2VyID0gc3RvcmUucGVla1JlY29yZCgndXNlcicsIDEpCiAgICAgIHVzZXIubG9naW4oKS50aGVuKGZ1bmN0aW9uKCkgewogICAgICAgIHVzZXIuZ2V0KCdwZXJtaXNzaW9ucycpLnRoZW4oZnVuY3Rpb24ocGVybWlzc2lvbnMpIHsKICAgICAgICAgIHJldHVybiBwZXJtaXNzaW9ucy5yZWxvYWQoKTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCByZWxvYWQKICAgICAgQHB1YmxpYwogICAgKi8KICAgIHJlbG9hZDogZnVuY3Rpb24gcmVsb2FkKG9wdGlvbnMpIHsKICAgICAgLy8gVE9ETyB0aGlzIGlzIG9kZCwgd2UgZG9uJ3QgYXNrIHRoZSBzdG9yZSBmb3IgYW55dGhpbmcgZWxzZSBsaWtlIHRoaXM/CiAgICAgIHJldHVybiB0aGlzLmdldCgnc3RvcmUnKS5yZWxvYWRNYW55QXJyYXkodGhpcywgdGhpcy5nZXQoJ2ludGVybmFsTW9kZWwnKSwgdGhpcy5nZXQoJ2tleScpLCBvcHRpb25zKTsKICAgIH0sCgogICAgLyoqCiAgICAgIFNhdmVzIGFsbCBvZiB0aGUgcmVjb3JkcyBpbiB0aGUgYE1hbnlBcnJheWAuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0b3JlLmZpbmRSZWNvcmQoJ2luYm94JywgMSkudGhlbihmdW5jdGlvbihpbmJveCkgewogICAgICAgIGluYm94LmdldCgnbWVzc2FnZXMnKS50aGVuKGZ1bmN0aW9uKG1lc3NhZ2VzKSB7CiAgICAgICAgICBtZXNzYWdlcy5mb3JFYWNoKGZ1bmN0aW9uKG1lc3NhZ2UpIHsKICAgICAgICAgICAgbWVzc2FnZS5zZXQoJ2lzUmVhZCcsIHRydWUpOwogICAgICAgICAgfSk7CiAgICAgICAgICBtZXNzYWdlcy5zYXZlKCkKICAgICAgICB9KTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzYXZlCiAgICAgIEByZXR1cm4ge1Byb21pc2VBcnJheX0gcHJvbWlzZQogICAgKi8KICAgIHNhdmU6IGZ1bmN0aW9uIHNhdmUoKSB7CiAgICAgIHZhciBtYW55QXJyYXkgPSB0aGlzOwogICAgICB2YXIgcHJvbWlzZUxhYmVsID0gJ0RTOiBNYW55QXJyYXkjc2F2ZSAnICsgRW1iZXIuZ2V0KHRoaXMsICd0eXBlJyk7CiAgICAgIHZhciBwcm9taXNlID0gRW1iZXIuUlNWUC5hbGwodGhpcy5pbnZva2UoJ3NhdmUnKSwgcHJvbWlzZUxhYmVsKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gbWFueUFycmF5OwogICAgICB9LCBudWxsLCAnRFM6IE1hbnlBcnJheSNzYXZlIHJldHVybiBNYW55QXJyYXknKTsKICAgICAgcmV0dXJuIFByb21pc2VBcnJheS5jcmVhdGUoewogICAgICAgIHByb21pc2U6IHByb21pc2UKICAgICAgfSk7CiAgICB9LAoKICAgIC8qKgogICAgICBDcmVhdGUgYSBjaGlsZCByZWNvcmQgd2l0aGluIHRoZSBvd25lcgogICAgICAgQG1ldGhvZCBjcmVhdGVSZWNvcmQKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtPYmplY3R9IGhhc2gKICAgICAgQHJldHVybiB7TW9kZWx9IHJlY29yZAogICAgKi8KICAgIGNyZWF0ZVJlY29yZDogZnVuY3Rpb24gY3JlYXRlUmVjb3JkKGhhc2gpIHsKICAgICAgdmFyIHN0b3JlID0gRW1iZXIuZ2V0KHRoaXMsICdzdG9yZScpOwogICAgICB2YXIgdHlwZSA9IEVtYmVyLmdldCh0aGlzLCAndHlwZScpOwogICAgICB2YXIgcmVjb3JkID0gc3RvcmUuY3JlYXRlUmVjb3JkKHR5cGUubW9kZWxOYW1lLCBoYXNoKTsKICAgICAgdGhpcy5wdXNoT2JqZWN0KHJlY29yZCk7CiAgICAgIHJldHVybiByZWNvcmQ7CiAgICB9CiAgfSk7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCiAgdmFyIFNPVVJDRV9QT0lOVEVSX1JFR0VYUCA9IC9eXC8/ZGF0YVwvKGF0dHJpYnV0ZXN8cmVsYXRpb25zaGlwcylcLyguKikvOwogIHZhciBTT1VSQ0VfUE9JTlRFUl9QUklNQVJZX1JFR0VYUCA9IC9eXC8/ZGF0YS87CiAgdmFyIFBSSU1BUllfQVRUUklCVVRFX0tFWSA9ICdiYXNlJzsKICAvKioKICAgIENvbnZlcnQgYW4gaGFzaCBvZiBlcnJvcnMgaW50byBhbiBhcnJheSB3aXRoIGVycm9ycyBpbiBKU09OLUFQSSBmb3JtYXQuCiAgICAgYGBgamF2YXNjcmlwdAogICAgaW1wb3J0IERTIGZyb20gJ2VtYmVyLWRhdGEnOwogICAgIGNvbnN0IHsgZXJyb3JzSGFzaFRvQXJyYXkgfSA9IERTOwogICAgIGxldCBlcnJvcnMgPSB7CiAgICAgIGJhc2U6ICdJbnZhbGlkIGF0dHJpYnV0ZXMgb24gc2F2aW5nIHRoaXMgcmVjb3JkJywKICAgICAgbmFtZTogJ011c3QgYmUgcHJlc2VudCcsCiAgICAgIGFnZTogWydNdXN0IGJlIHByZXNlbnQnLCAnTXVzdCBiZSBhIG51bWJlciddCiAgICB9OwogICAgIGxldCBlcnJvcnNBcnJheSA9IGVycm9yc0hhc2hUb0FycmF5KGVycm9ycyk7CiAgICAvLyBbCiAgICAvLyAgIHsKICAgIC8vICAgICB0aXRsZTogIkludmFsaWQgRG9jdW1lbnQiLAogICAgLy8gICAgIGRldGFpbDogIkludmFsaWQgYXR0cmlidXRlcyBvbiBzYXZpbmcgdGhpcyByZWNvcmQiLAogICAgLy8gICAgIHNvdXJjZTogeyBwb2ludGVyOiAiL2RhdGEiIH0KICAgIC8vICAgfSwKICAgIC8vICAgewogICAgLy8gICAgIHRpdGxlOiAiSW52YWxpZCBBdHRyaWJ1dGUiLAogICAgLy8gICAgIGRldGFpbDogIk11c3QgYmUgcHJlc2VudCIsCiAgICAvLyAgICAgc291cmNlOiB7IHBvaW50ZXI6ICIvZGF0YS9hdHRyaWJ1dGVzL25hbWUiIH0KICAgIC8vICAgfSwKICAgIC8vICAgewogICAgLy8gICAgIHRpdGxlOiAiSW52YWxpZCBBdHRyaWJ1dGUiLAogICAgLy8gICAgIGRldGFpbDogIk11c3QgYmUgcHJlc2VudCIsCiAgICAvLyAgICAgc291cmNlOiB7IHBvaW50ZXI6ICIvZGF0YS9hdHRyaWJ1dGVzL2FnZSIgfQogICAgLy8gICB9LAogICAgLy8gICB7CiAgICAvLyAgICAgdGl0bGU6ICJJbnZhbGlkIEF0dHJpYnV0ZSIsCiAgICAvLyAgICAgZGV0YWlsOiAiTXVzdCBiZSBhIG51bWJlciIsCiAgICAvLyAgICAgc291cmNlOiB7IHBvaW50ZXI6ICIvZGF0YS9hdHRyaWJ1dGVzL2FnZSIgfQogICAgLy8gICB9CiAgICAvLyBdCiAgICBgYGAKICAgIEBtZXRob2QgZXJyb3JzSGFzaFRvQXJyYXkKICAgIEBwdWJsaWMKICAgIEBwYXJhbSB7T2JqZWN0fSBlcnJvcnMgaGFzaCB3aXRoIGVycm9ycyBhcyBwcm9wZXJ0aWVzCiAgICBAcmV0dXJuIHtBcnJheX0gYXJyYXkgb2YgZXJyb3JzIGluIEpTT04tQVBJIGZvcm1hdAogICovCgogIGZ1bmN0aW9uIGVycm9yc0hhc2hUb0FycmF5KGVycm9ycykgewogICAgdmFyIG91dCA9IFtdOwoKICAgIGlmIChFbWJlci5pc1ByZXNlbnQoZXJyb3JzKSkgewogICAgICBPYmplY3Qua2V5cyhlcnJvcnMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgIHZhciBtZXNzYWdlcyA9IEVtYmVyLm1ha2VBcnJheShlcnJvcnNba2V5XSk7CgogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHZhciB0aXRsZSA9ICdJbnZhbGlkIEF0dHJpYnV0ZSc7CiAgICAgICAgICB2YXIgcG9pbnRlciA9ICIvZGF0YS9hdHRyaWJ1dGVzLyIgKyBrZXk7CgogICAgICAgICAgaWYgKGtleSA9PT0gUFJJTUFSWV9BVFRSSUJVVEVfS0VZKSB7CiAgICAgICAgICAgIHRpdGxlID0gJ0ludmFsaWQgRG9jdW1lbnQnOwogICAgICAgICAgICBwb2ludGVyID0gIi9kYXRhIjsKICAgICAgICAgIH0KCiAgICAgICAgICBvdXQucHVzaCh7CiAgICAgICAgICAgIHRpdGxlOiB0aXRsZSwKICAgICAgICAgICAgZGV0YWlsOiBtZXNzYWdlc1tpXSwKICAgICAgICAgICAgc291cmNlOiB7CiAgICAgICAgICAgICAgcG9pbnRlcjogcG9pbnRlcgogICAgICAgICAgICB9CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQoKICAgIHJldHVybiBvdXQ7CiAgfQogIC8qKgogICAgQ29udmVydCBhbiBhcnJheSBvZiBlcnJvcnMgaW4gSlNPTi1BUEkgZm9ybWF0IGludG8gYW4gb2JqZWN0LgoKICAgIGBgYGphdmFzY3JpcHQKICAgIGltcG9ydCBEUyBmcm9tICdlbWJlci1kYXRhJzsKCiAgICBjb25zdCB7IGVycm9yc0FycmF5VG9IYXNoIH0gPSBEUzsKCiAgICBsZXQgZXJyb3JzQXJyYXkgPSBbCiAgICAgIHsKICAgICAgICB0aXRsZTogJ0ludmFsaWQgQXR0cmlidXRlJywKICAgICAgICBkZXRhaWw6ICdNdXN0IGJlIHByZXNlbnQnLAogICAgICAgIHNvdXJjZTogeyBwb2ludGVyOiAnL2RhdGEvYXR0cmlidXRlcy9uYW1lJyB9CiAgICAgIH0sCiAgICAgIHsKICAgICAgICB0aXRsZTogJ0ludmFsaWQgQXR0cmlidXRlJywKICAgICAgICBkZXRhaWw6ICdNdXN0IGJlIHByZXNlbnQnLAogICAgICAgIHNvdXJjZTogeyBwb2ludGVyOiAnL2RhdGEvYXR0cmlidXRlcy9hZ2UnIH0KICAgICAgfSwKICAgICAgewogICAgICAgIHRpdGxlOiAnSW52YWxpZCBBdHRyaWJ1dGUnLAogICAgICAgIGRldGFpbDogJ011c3QgYmUgYSBudW1iZXInLAogICAgICAgIHNvdXJjZTogeyBwb2ludGVyOiAnL2RhdGEvYXR0cmlidXRlcy9hZ2UnIH0KICAgICAgfQogICAgXTsKCiAgICBsZXQgZXJyb3JzID0gZXJyb3JzQXJyYXlUb0hhc2goZXJyb3JzQXJyYXkpOwogICAgLy8gewogICAgLy8gICAibmFtZSI6IFsiTXVzdCBiZSBwcmVzZW50Il0sCiAgICAvLyAgICJhZ2UiOiAgWyJNdXN0IGJlIHByZXNlbnQiLCAibXVzdCBiZSBhIG51bWJlciJdCiAgICAvLyB9CiAgICBgYGAKCiAgICBAbWV0aG9kIGVycm9yc0FycmF5VG9IYXNoCiAgICBAcHVibGljCiAgICBAcGFyYW0ge0FycmF5fSBlcnJvcnMgYXJyYXkgb2YgZXJyb3JzIGluIEpTT04tQVBJIGZvcm1hdAogICAgQHJldHVybiB7T2JqZWN0fQogICovCgogIGZ1bmN0aW9uIGVycm9yc0FycmF5VG9IYXNoKGVycm9ycykgewogICAgdmFyIG91dCA9IHt9OwoKICAgIGlmIChFbWJlci5pc1ByZXNlbnQoZXJyb3JzKSkgewogICAgICBlcnJvcnMuZm9yRWFjaChmdW5jdGlvbiAoZXJyb3IpIHsKICAgICAgICBpZiAoZXJyb3Iuc291cmNlICYmIGVycm9yLnNvdXJjZS5wb2ludGVyKSB7CiAgICAgICAgICB2YXIga2V5ID0gZXJyb3Iuc291cmNlLnBvaW50ZXIubWF0Y2goU09VUkNFX1BPSU5URVJfUkVHRVhQKTsKCiAgICAgICAgICBpZiAoa2V5KSB7CiAgICAgICAgICAgIGtleSA9IGtleVsyXTsKICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3Iuc291cmNlLnBvaW50ZXIuc2VhcmNoKFNPVVJDRV9QT0lOVEVSX1BSSU1BUllfUkVHRVhQKSAhPT0gLTEpIHsKICAgICAgICAgICAga2V5ID0gUFJJTUFSWV9BVFRSSUJVVEVfS0VZOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChrZXkpIHsKICAgICAgICAgICAgb3V0W2tleV0gPSBvdXRba2V5XSB8fCBbXTsKICAgICAgICAgICAgb3V0W2tleV0ucHVzaChlcnJvci5kZXRhaWwgfHwgZXJyb3IudGl0bGUpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICB9CgogICAgcmV0dXJuIG91dDsKICB9CgogIGZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0aWVzJDEodGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoInZhbHVlIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0KCiAgZnVuY3Rpb24gX2NyZWF0ZUNsYXNzJDEoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQxKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMkMShDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH0KCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KCiAgLyoqCiAgICBAY2xhc3MgU25hcHNob3RSZWNvcmRBcnJheQogICAgQHByaXZhdGUKICAgIEBjb25zdHJ1Y3RvcgogICAgQHBhcmFtIHtBcnJheX0gc25hcHNob3RzIEFuIGFycmF5IG9mIHNuYXBzaG90cwogICAgQHBhcmFtIHtPYmplY3R9IG1ldGEKICAqLwogIHZhciBTbmFwc2hvdFJlY29yZEFycmF5ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gU25hcHNob3RSZWNvcmRBcnJheShyZWNvcmRBcnJheSwgbWV0YSwgb3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICAvKioKICAgICAgICBBbiBhcnJheSBvZiBzbmFwc2hvdHMKICAgICAgICBAcHJpdmF0ZQogICAgICAgIEBwcm9wZXJ0eSBfc25hcHNob3RzCiAgICAgICAgQHR5cGUge0FycmF5fQogICAgICAqLwogICAgICB0aGlzLl9zbmFwc2hvdHMgPSBudWxsOwogICAgICAvKioKICAgICAgICBBbiBhcnJheSBvZiByZWNvcmRzCiAgICAgICAgQHByaXZhdGUKICAgICAgICBAcHJvcGVydHkgX3JlY29yZEFycmF5CiAgICAgICAgQHR5cGUge0FycmF5fQogICAgICAqLwoKICAgICAgdGhpcy5fcmVjb3JkQXJyYXkgPSByZWNvcmRBcnJheTsKICAgICAgLyoqCiAgICAgICAgTnVtYmVyIG9mIHJlY29yZHMgaW4gdGhlIGFycmF5CiAgICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL2FkYXB0ZXJzL3Bvc3QuanMKICAgICAgICBpbXBvcnQgSlNPTkFQSUFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlci9qc29uLWFwaSc7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05BUElBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgICBzaG91bGRSZWxvYWRBbGwoc3RvcmUsIHNuYXBzaG90UmVjb3JkQXJyYXkpIHsKICAgICAgICAgICAgcmV0dXJuICFzbmFwc2hvdFJlY29yZEFycmF5Lmxlbmd0aDsKICAgICAgICAgIH0sCiAgICAgICAgfSk7CiAgICAgICAgYGBgCiAgICAgICAgIEBwcm9wZXJ0eSBsZW5ndGgKICAgICAgICBAdHlwZSB7TnVtYmVyfQogICAgICAqLwoKICAgICAgdGhpcy5sZW5ndGggPSByZWNvcmRBcnJheS5nZXQoJ2xlbmd0aCcpOwogICAgICB0aGlzLl90eXBlID0gbnVsbDsKICAgICAgLyoqCiAgICAgICAgTWV0YSBvYmplY3RzIGZvciB0aGUgcmVjb3JkIGFycmF5LgogICAgICAgICBFeGFtcGxlCiAgICAgICAgIGBgYGFwcC9hZGFwdGVycy9wb3N0LmpzCiAgICAgICAgaW1wb3J0IEpTT05BUElBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvanNvbi1hcGknOwogICAgICAgICBleHBvcnQgZGVmYXVsdCBKU09OQVBJQWRhcHRlci5leHRlbmQoewogICAgICAgICAgc2hvdWxkUmVsb2FkQWxsKHN0b3JlLCBzbmFwc2hvdFJlY29yZEFycmF5KSB7CiAgICAgICAgICAgIHZhciBsYXN0UmVxdWVzdFRpbWUgPSBzbmFwc2hvdFJlY29yZEFycmF5Lm1ldGEubGFzdFJlcXVlc3RUaW1lOwogICAgICAgICAgICB2YXIgdHdlbnR5TWludXRlcyA9IDIwICogNjAgKiAxMDAwOwogICAgICAgICAgICByZXR1cm4gRGF0ZS5ub3coKSA+IGxhc3RSZXF1ZXN0VGltZSArIHR3ZW50eU1pbnV0ZXM7CiAgICAgICAgICB9LAogICAgICAgIH0pOwogICAgICAgIGBgYAogICAgICAgICBAcHJvcGVydHkgbWV0YQogICAgICAgIEB0eXBlIHtPYmplY3R9CiAgICAgICovCgogICAgICB0aGlzLm1ldGEgPSBtZXRhOwogICAgICAvKioKICAgICAgICBBIGhhc2ggb2YgYWRhcHRlciBvcHRpb25zIHBhc3NlZCBpbnRvIHRoZSBzdG9yZSBtZXRob2QgZm9yIHRoaXMgcmVxdWVzdC4KICAgICAgICAgRXhhbXBsZQogICAgICAgICBgYGBhcHAvYWRhcHRlcnMvcG9zdC5qcwogICAgICAgIGltcG9ydCBNeUN1c3RvbUFkYXB0ZXIgZnJvbSAnLi9jdXN0b20tYWRhcHRlcic7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IE15Q3VzdG9tQWRhcHRlci5leHRlbmQoewogICAgICAgICAgZmluZEFsbChzdG9yZSwgdHlwZSwgc2luY2VUb2tlbiwgc25hcHNob3RSZWNvcmRBcnJheSkgewogICAgICAgICAgICBpZiAoc25hcHNob3RSZWNvcmRBcnJheS5hZGFwdGVyT3B0aW9ucy5zdWJzY3JpYmUpIHsKICAgICAgICAgICAgICAvLyAuLi4KICAgICAgICAgICAgfQogICAgICAgICAgICAvLyAuLi4KICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgICBgYGAKICAgICAgICAgQHByb3BlcnR5IGFkYXB0ZXJPcHRpb25zCiAgICAgICAgQHR5cGUge09iamVjdH0KICAgICAgKi8KCiAgICAgIHRoaXMuYWRhcHRlck9wdGlvbnMgPSBvcHRpb25zLmFkYXB0ZXJPcHRpb25zOwogICAgICAvKioKICAgICAgICBUaGUgcmVsYXRpb25zaGlwcyB0byBpbmNsdWRlIGZvciB0aGlzIHJlcXVlc3QuCiAgICAgICAgIEV4YW1wbGUKICAgICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgICAgaW1wb3J0IEFkYXB0ZXIgZnJvbSAnQGVtYmVyLWRhdGEvYWRhcHRlcic7CiAgICAgICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICAgIGZpbmRBbGwoc3RvcmUsIHR5cGUsIHNuYXBzaG90UmVjb3JkQXJyYXkpIHsKICAgICAgICAgICAgdmFyIHVybCA9IGAvJHt0eXBlLm1vZGVsTmFtZX0/aW5jbHVkZT0ke2VuY29kZVVSSUNvbXBvbmVudChzbmFwc2hvdFJlY29yZEFycmF5LmluY2x1ZGUpfWA7CiAgICAgICAgICAgICByZXR1cm4gZmV0Y2godXJsKS50aGVuKChyZXNwb25zZSkgPT4gcmVzcG9uc2UuanNvbigpKQogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgICBAcHJvcGVydHkgaW5jbHVkZQogICAgICAgIEB0eXBlIHtTdHJpbmd8QXJyYXl9CiAgICAgICovCgogICAgICB0aGlzLmluY2x1ZGUgPSBvcHRpb25zLmluY2x1ZGU7CiAgICB9CiAgICAvKioKICAgICAgVGhlIHR5cGUgb2YgdGhlIHVuZGVybHlpbmcgcmVjb3JkcyBmb3IgdGhlIHNuYXBzaG90cyBpbiB0aGUgYXJyYXksIGFzIGEgTW9kZWwKICAgICAgQHByb3BlcnR5IHR5cGUKICAgICAgQHR5cGUge01vZGVsfQogICAgKi8KCgogICAgdmFyIF9wcm90byA9IFNuYXBzaG90UmVjb3JkQXJyYXkucHJvdG90eXBlOwoKICAgIC8qKgogICAgICBHZXQgc25hcHNob3RzIG9mIHRoZSB1bmRlcmx5aW5nIHJlY29yZCBhcnJheQogICAgICAgRXhhbXBsZQogICAgICAgYGBgYXBwL2FkYXB0ZXJzL3Bvc3QuanMKICAgICAgaW1wb3J0IEpTT05BUElBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXIvanNvbi1hcGknOwogICAgICAgZXhwb3J0IGRlZmF1bHQgSlNPTkFQSUFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBzaG91bGRSZWxvYWRBbGwoc3RvcmUsIHNuYXBzaG90QXJyYXkpIHsKICAgICAgICAgIHZhciBzbmFwc2hvdHMgPSBzbmFwc2hvdEFycmF5LnNuYXBzaG90cygpOwogICAgICAgICAgIHJldHVybiBzbmFwc2hvdHMuYW55KGZ1bmN0aW9uKHRpY2tldFNuYXBzaG90KSB7CiAgICAgICAgICAgIHZhciB0aW1lRGlmZiA9IG1vbWVudCgpLmRpZmYodGlja2V0U25hcHNob3QuYXR0cignbGFzdEFjY2Vzc2VkQXQnKSwgJ21pbnV0ZXMnKTsKICAgICAgICAgICAgaWYgKHRpbWVEaWZmID4gMjApIHsKICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBzbmFwc2hvdHMKICAgICAgQHJldHVybiB7QXJyYXl9IEFycmF5IG9mIHNuYXBzaG90cwogICAgKi8KICAgIF9wcm90by5zbmFwc2hvdHMgPSBmdW5jdGlvbiBzbmFwc2hvdHMoKSB7CiAgICAgIGlmICh0aGlzLl9zbmFwc2hvdHMgIT09IG51bGwpIHsKICAgICAgICByZXR1cm4gdGhpcy5fc25hcHNob3RzOwogICAgICB9CgogICAgICB0aGlzLl9zbmFwc2hvdHMgPSB0aGlzLl9yZWNvcmRBcnJheS5fdGFrZVNuYXBzaG90KCk7CiAgICAgIHJldHVybiB0aGlzLl9zbmFwc2hvdHM7CiAgICB9OwoKICAgIF9jcmVhdGVDbGFzcyQxKFNuYXBzaG90UmVjb3JkQXJyYXksIFt7CiAgICAgIGtleTogInR5cGUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5fdHlwZSB8fCAodGhpcy5fdHlwZSA9IHRoaXMuX3JlY29yZEFycmF5LmdldCgndHlwZScpKTsKICAgICAgfQogICAgICAvKioKICAgICAgICBUaGUgbW9kZWxOYW1lIG9mIHRoZSB1bmRlcmx5aW5nIHJlY29yZHMgZm9yIHRoZSBzbmFwc2hvdHMgaW4gdGhlIGFycmF5LCBhcyBhIE1vZGVsCiAgICAgICAgQHByb3BlcnR5IHR5cGUKICAgICAgICBAdHlwZSB7TW9kZWx9CiAgICAgICovCgogICAgfSwgewogICAgICBrZXk6ICJtb2RlbE5hbWUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5fcmVjb3JkQXJyYXkubW9kZWxOYW1lOwogICAgICB9CiAgICB9XSk7CgogICAgcmV0dXJuIFNuYXBzaG90UmVjb3JkQXJyYXk7CiAgfSgpOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwogIC8qKgogICAgQSByZWNvcmQgYXJyYXkgaXMgYW4gYXJyYXkgdGhhdCBjb250YWlucyByZWNvcmRzIG9mIGEgY2VydGFpbiBtb2RlbE5hbWUuIFRoZSByZWNvcmQKICAgIGFycmF5IG1hdGVyaWFsaXplcyByZWNvcmRzIGFzIG5lZWRlZCB3aGVuIHRoZXkgYXJlIHJldHJpZXZlZCBmb3IgdGhlIGZpcnN0CiAgICB0aW1lLiBZb3Ugc2hvdWxkIG5vdCBjcmVhdGUgcmVjb3JkIGFycmF5cyB5b3Vyc2VsZi4gSW5zdGVhZCwgYW4gaW5zdGFuY2Ugb2YKICAgIGBSZWNvcmRBcnJheWAgb3IgaXRzIHN1YmNsYXNzZXMgd2lsbCBiZSByZXR1cm5lZCBieSB5b3VyIGFwcGxpY2F0aW9uJ3Mgc3RvcmUKICAgIGluIHJlc3BvbnNlIHRvIHF1ZXJpZXMuCgogICAgQGNsYXNzIFJlY29yZEFycmF5CiAgICBAZXh0ZW5kcyBBcnJheVByb3h5CiAgICBAdXNlcyBFbWJlci5FdmVudGVkCiAgKi8KCiAgdmFyIFJlY29yZEFycmF5ID0gRW1iZXIuQXJyYXlQcm94eS5leHRlbmQoRGVwcmVjYXRlZEV2ZW50ZWQsIHsKICAgIGluaXQ6IGZ1bmN0aW9uIGluaXQoKSB7CgogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgICAvKioKICAgICAgICBUaGUgYXJyYXkgb2YgY2xpZW50IGlkcyBiYWNraW5nIHRoZSByZWNvcmQgYXJyYXkuIFdoZW4gYQogICAgICAgIHJlY29yZCBpcyByZXF1ZXN0ZWQgZnJvbSB0aGUgcmVjb3JkIGFycmF5LCB0aGUgcmVjb3JkCiAgICAgICAgZm9yIHRoZSBjbGllbnQgaWQgYXQgdGhlIHNhbWUgaW5kZXggaXMgbWF0ZXJpYWxpemVkLCBpZgogICAgICAgIG5lY2Vzc2FyeSwgYnkgdGhlIHN0b3JlLgogICAgICAgICBAcHJvcGVydHkgY29udGVudAogICAgICAgIEBwcml2YXRlCiAgICAgICAgQHR5cGUgRW1iZXIuQXJyYXkKICAgICAgICAqLwoKCiAgICAgIHRoaXMuc2V0KCdjb250ZW50JywgdGhpcy5jb250ZW50IHx8IG51bGwpOwogICAgICAvKioKICAgICAgVGhlIGZsYWcgdG8gc2lnbmFsIGEgYFJlY29yZEFycmF5YCBpcyBmaW5pc2hlZCBsb2FkaW5nIGRhdGEuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHZhciBwZW9wbGUgPSBzdG9yZS5wZWVrQWxsKCdwZXJzb24nKTsKICAgICAgcGVvcGxlLmdldCgnaXNMb2FkZWQnKTsgLy8gdHJ1ZQogICAgICBgYGAKICAgICAgIEBwcm9wZXJ0eSBpc0xvYWRlZAogICAgICBAdHlwZSBCb29sZWFuCiAgICAgICovCgogICAgICB0aGlzLmlzTG9hZGVkID0gdGhpcy5pc0xvYWRlZCB8fCBmYWxzZTsKICAgICAgLyoqCiAgICAgIFRoZSBmbGFnIHRvIHNpZ25hbCBhIGBSZWNvcmRBcnJheWAgaXMgY3VycmVudGx5IGxvYWRpbmcgZGF0YS4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgdmFyIHBlb3BsZSA9IHN0b3JlLnBlZWtBbGwoJ3BlcnNvbicpOwogICAgICBwZW9wbGUuZ2V0KCdpc1VwZGF0aW5nJyk7IC8vIGZhbHNlCiAgICAgIHBlb3BsZS51cGRhdGUoKTsKICAgICAgcGVvcGxlLmdldCgnaXNVcGRhdGluZycpOyAvLyB0cnVlCiAgICAgIGBgYAogICAgICAgQHByb3BlcnR5IGlzVXBkYXRpbmcKICAgICAgQHR5cGUgQm9vbGVhbgogICAgICAqLwoKICAgICAgdGhpcy5pc1VwZGF0aW5nID0gZmFsc2U7CiAgICAgIC8qKgogICAgICBUaGUgc3RvcmUgdGhhdCBjcmVhdGVkIHRoaXMgcmVjb3JkIGFycmF5LgogICAgICAgQHByb3BlcnR5IHN0b3JlCiAgICAgIEBwcml2YXRlCiAgICAgIEB0eXBlIFN0b3JlCiAgICAgICovCgogICAgICB0aGlzLnN0b3JlID0gdGhpcy5zdG9yZSB8fCBudWxsOwogICAgICB0aGlzLl91cGRhdGluZ1Byb21pc2UgPSBudWxsOwogICAgfSwKICAgIHJlcGxhY2U6IGZ1bmN0aW9uIHJlcGxhY2UoKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiVGhlIHJlc3VsdCBvZiBhIHNlcnZlciBxdWVyeSAoZm9yIGFsbCAiICsgdGhpcy5tb2RlbE5hbWUgKyAiIHR5cGVzKSBpcyBpbW11dGFibGUuIFRvIG1vZGlmeSBjb250ZW50cywgdXNlIHRvQXJyYXkoKSIpOwogICAgfSwKCiAgICAvKioKICAgICBUaGUgbW9kZWxDbGFzcyByZXByZXNlbnRlZCBieSB0aGlzIHJlY29yZCBhcnJheS4KICAgICAgQHByb3BlcnR5IHR5cGUKICAgICBAdHlwZSBNb2RlbAogICAgICovCiAgICB0eXBlOiBFbWJlci5jb21wdXRlZCgnbW9kZWxOYW1lJywgZnVuY3Rpb24gKCkgewogICAgICBpZiAoIXRoaXMubW9kZWxOYW1lKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLnN0b3JlLm1vZGVsRm9yKHRoaXMubW9kZWxOYW1lKTsKICAgIH0pLnJlYWRPbmx5KCksCgogICAgLyoqCiAgICAgIFJldHJpZXZlcyBhbiBvYmplY3QgZnJvbSB0aGUgY29udGVudCBieSBpbmRleC4KICAgICAgIEBtZXRob2Qgb2JqZWN0QXRDb250ZW50CiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7TnVtYmVyfSBpbmRleAogICAgICBAcmV0dXJuIHtNb2RlbH0gcmVjb3JkCiAgICAqLwogICAgb2JqZWN0QXRDb250ZW50OiBmdW5jdGlvbiBvYmplY3RBdENvbnRlbnQoaW5kZXgpIHsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBFbWJlci5nZXQodGhpcywgJ2NvbnRlbnQnKS5vYmplY3RBdChpbmRleCk7CiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsICYmIGludGVybmFsTW9kZWwuZ2V0UmVjb3JkKCk7CiAgICB9LAoKICAgIC8qKgogICAgICBVc2VkIHRvIGdldCB0aGUgbGF0ZXN0IHZlcnNpb24gb2YgYWxsIG9mIHRoZSByZWNvcmRzIGluIHRoaXMgYXJyYXkKICAgICAgZnJvbSB0aGUgYWRhcHRlci4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgdmFyIHBlb3BsZSA9IHN0b3JlLnBlZWtBbGwoJ3BlcnNvbicpOwogICAgICBwZW9wbGUuZ2V0KCdpc1VwZGF0aW5nJyk7IC8vIGZhbHNlCiAgICAgICBwZW9wbGUudXBkYXRlKCkudGhlbihmdW5jdGlvbigpIHsKICAgICAgICBwZW9wbGUuZ2V0KCdpc1VwZGF0aW5nJyk7IC8vIGZhbHNlCiAgICAgIH0pOwogICAgICAgcGVvcGxlLmdldCgnaXNVcGRhdGluZycpOyAvLyB0cnVlCiAgICAgIGBgYAogICAgICAgQG1ldGhvZCB1cGRhdGUKICAgICovCiAgICB1cGRhdGU6IGZ1bmN0aW9uIHVwZGF0ZSgpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICBpZiAoRW1iZXIuZ2V0KHRoaXMsICdpc1VwZGF0aW5nJykpIHsKICAgICAgICByZXR1cm4gdGhpcy5fdXBkYXRpbmdQcm9taXNlOwogICAgICB9CgogICAgICB0aGlzLnNldCgnaXNVcGRhdGluZycsIHRydWUpOwoKICAgICAgdmFyIHVwZGF0aW5nUHJvbWlzZSA9IHRoaXMuX3VwZGF0ZSgpLmZpbmFsbHkoZnVuY3Rpb24gKCkgewogICAgICAgIF90aGlzMi5fdXBkYXRpbmdQcm9taXNlID0gbnVsbDsKCiAgICAgICAgaWYgKF90aGlzMi5nZXQoJ2lzRGVzdHJveWluZycpIHx8IF90aGlzMi5nZXQoJ2lzRGVzdHJveWVkJykpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIF90aGlzMi5zZXQoJ2lzVXBkYXRpbmcnLCBmYWxzZSk7CiAgICAgIH0pOwoKICAgICAgdGhpcy5fdXBkYXRpbmdQcm9taXNlID0gdXBkYXRpbmdQcm9taXNlOwogICAgICByZXR1cm4gdXBkYXRpbmdQcm9taXNlOwogICAgfSwKCiAgICAvKgogICAgICBVcGRhdGUgdGhpcyBSZWNvcmRBcnJheSBhbmQgcmV0dXJuIGEgcHJvbWlzZSB3aGljaCByZXNvbHZlcyBvbmNlIHRoZSB1cGRhdGUKICAgICAgaXMgZmluaXNoZWQuCiAgICAgKi8KICAgIF91cGRhdGU6IGZ1bmN0aW9uIF91cGRhdGUoKSB7CiAgICAgIHJldHVybiB0aGlzLnN0b3JlLmZpbmRBbGwodGhpcy5tb2RlbE5hbWUsIHsKICAgICAgICByZWxvYWQ6IHRydWUKICAgICAgfSk7CiAgICB9LAoKICAgIC8qKgogICAgICBBZGRzIGFuIGludGVybmFsIG1vZGVsIHRvIHRoZSBgUmVjb3JkQXJyYXlgIHdpdGhvdXQgZHVwbGljYXRlcwogICAgICAgQG1ldGhvZCBfcHVzaEludGVybmFsTW9kZWxzCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7SW50ZXJuYWxNb2RlbH0gaW50ZXJuYWxNb2RlbAogICAgKi8KICAgIF9wdXNoSW50ZXJuYWxNb2RlbHM6IGZ1bmN0aW9uIF9wdXNoSW50ZXJuYWxNb2RlbHMoaW50ZXJuYWxNb2RlbHMpIHsKICAgICAgLy8gcHVzaE9iamVjdHMgYmVjYXVzZSB0aGUgaW50ZXJuYWxNb2RlbHMuX3JlY29yZEFycmF5cyBzZXQgd2FzIGFscmVhZHkKICAgICAgLy8gY29uc3VsdGVkIGZvciBpbmNsdXNpb24sIHNvIGFkZE9iamVjdCBhbmQgaXRzIG9uIC5jb250YWlucyBjYWxsIGlzIG5vdAogICAgICAvLyByZXF1aXJlZC4KICAgICAgRW1iZXIuZ2V0KHRoaXMsICdjb250ZW50JykucHVzaE9iamVjdHMoaW50ZXJuYWxNb2RlbHMpOwogICAgfSwKCiAgICAvKioKICAgICAgUmVtb3ZlcyBhbiBpbnRlcm5hbE1vZGVsIHRvIHRoZSBgUmVjb3JkQXJyYXlgLgogICAgICAgQG1ldGhvZCByZW1vdmVJbnRlcm5hbE1vZGVsCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7SW50ZXJuYWxNb2RlbH0gaW50ZXJuYWxNb2RlbAogICAgKi8KICAgIF9yZW1vdmVJbnRlcm5hbE1vZGVsczogZnVuY3Rpb24gX3JlbW92ZUludGVybmFsTW9kZWxzKGludGVybmFsTW9kZWxzKSB7CiAgICAgIEVtYmVyLmdldCh0aGlzLCAnY29udGVudCcpLnJlbW92ZU9iamVjdHMoaW50ZXJuYWxNb2RlbHMpOwogICAgfSwKCiAgICAvKioKICAgICAgU2F2ZXMgYWxsIG9mIHRoZSByZWNvcmRzIGluIHRoZSBgUmVjb3JkQXJyYXlgLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICB2YXIgbWVzc2FnZXMgPSBzdG9yZS5wZWVrQWxsKCdtZXNzYWdlJyk7CiAgICAgIG1lc3NhZ2VzLmZvckVhY2goZnVuY3Rpb24obWVzc2FnZSkgewogICAgICAgIG1lc3NhZ2Uuc2V0KCdoYXNCZWVuU2VlbicsIHRydWUpOwogICAgICB9KTsKICAgICAgbWVzc2FnZXMuc2F2ZSgpOwogICAgICBgYGAKICAgICAgIEBtZXRob2Qgc2F2ZQogICAgICBAcmV0dXJuIHtQcm9taXNlQXJyYXl9IHByb21pc2UKICAgICovCiAgICBzYXZlOiBmdW5jdGlvbiBzYXZlKCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHZhciBwcm9taXNlTGFiZWwgPSAiRFM6IFJlY29yZEFycmF5I3NhdmUgIiArIHRoaXMubW9kZWxOYW1lOwogICAgICB2YXIgcHJvbWlzZSA9IEVtYmVyLlJTVlAuUHJvbWlzZS5hbGwodGhpcy5pbnZva2UoJ3NhdmUnKSwgcHJvbWlzZUxhYmVsKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gX3RoaXMzOwogICAgICB9LCBudWxsLCAnRFM6IFJlY29yZEFycmF5I3NhdmUgcmV0dXJuIFJlY29yZEFycmF5Jyk7CiAgICAgIHJldHVybiBQcm9taXNlQXJyYXkuY3JlYXRlKHsKICAgICAgICBwcm9taXNlOiBwcm9taXNlCiAgICAgIH0pOwogICAgfSwKICAgIF9kaXNzb2NpYXRlRnJvbU93blJlY29yZHM6IGZ1bmN0aW9uIF9kaXNzb2NpYXRlRnJvbU93blJlY29yZHMoKSB7CiAgICAgIHZhciBfdGhpczQgPSB0aGlzOwoKICAgICAgdGhpcy5nZXQoJ2NvbnRlbnQnKS5mb3JFYWNoKGZ1bmN0aW9uIChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgdmFyIHJlY29yZEFycmF5cyA9IGludGVybmFsTW9kZWwuX19yZWNvcmRBcnJheXM7CgogICAgICAgIGlmIChyZWNvcmRBcnJheXMpIHsKICAgICAgICAgIHJlY29yZEFycmF5cy5kZWxldGUoX3RoaXM0KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBfdW5yZWdpc3RlckZyb21NYW5hZ2VyCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX3VucmVnaXN0ZXJGcm9tTWFuYWdlcjogZnVuY3Rpb24gX3VucmVnaXN0ZXJGcm9tTWFuYWdlcigpIHsKICAgICAgdGhpcy5tYW5hZ2VyLnVucmVnaXN0ZXJSZWNvcmRBcnJheSh0aGlzKTsKICAgIH0sCiAgICB3aWxsRGVzdHJveTogZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIHRoaXMuX3VucmVnaXN0ZXJGcm9tTWFuYWdlcigpOwoKICAgICAgdGhpcy5fZGlzc29jaWF0ZUZyb21Pd25SZWNvcmRzKCk7IC8vIFRPRE86IHdlIHNob3VsZCBub3QgZG8gd29yayBkdXJpbmcgZGVzdHJveToKICAgICAgLy8gICAqIHdoZW4gb2JqZWN0cyBhcmUgZGVzdHJveWVkLCB0aGV5IHNob3VsZCBzaW1wbHkgYmUgbGVmdCB0byBkbwogICAgICAvLyAgICogaWYgbG9naWMgZXJyb3JzIGRvIHRvIHRoaXMsIHRoYXQgbG9naWMgbmVlZHMgdG8gYmUgbW9yZSBjYXJlZnVsIGR1cmluZwogICAgICAvLyAgICB0ZWFyZG93biAoZW1iZXIgcHJvdmlkZXMgaXNEZXN0cm95aW5nL2lzRGVzdHJveWVkKSBmb3IgdGhpcyByZWFzb24KICAgICAgLy8gICAqIHRoZSBleGNlcHRpb24gYmVpbmc6IGlmIGFuIGRvbWluYXRvciBoYXMgYSByZWZlcmVuY2UgdG8gdGhpcyBvYmplY3QsCiAgICAgIC8vICAgICBhbmQgbXVzdCBiZSBpbmZvcm1lZCB0byByZWxlYXNlIGUuZy4gZS5nLiByZW1vdmluZyBpdHNlbGYgZnJvbSB0aAogICAgICAvLyAgICAgcmVjb3JkQXJyYXlNYW5hbmdlcgoKCiAgICAgIEVtYmVyLnNldCh0aGlzLCAnY29udGVudCcsIG51bGwpOwogICAgICBFbWJlci5zZXQodGhpcywgJ2xlbmd0aCcsIDApOwoKICAgICAgdGhpcy5fc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgIH0sCgogICAgLyoKICAgICAgQG1ldGhvZCBfY3JlYXRlU25hcHNob3QKICAgICAgQHByaXZhdGUKICAgICovCiAgICBfY3JlYXRlU25hcHNob3Q6IGZ1bmN0aW9uIF9jcmVhdGVTbmFwc2hvdChvcHRpb25zKSB7CiAgICAgIC8vIHRoaXMgaXMgcHJpdmF0ZSBmb3IgdXNlcnMsIGJ1dCBwdWJsaWMgZm9yIGVtYmVyLWRhdGEgaW50ZXJuYWxzCiAgICAgIHJldHVybiBuZXcgU25hcHNob3RSZWNvcmRBcnJheSh0aGlzLCB0aGlzLmdldCgnbWV0YScpLCBvcHRpb25zKTsKICAgIH0sCgogICAgLyoKICAgICAgQG1ldGhvZCBfdGFrZVNuYXBzaG90CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX3Rha2VTbmFwc2hvdDogZnVuY3Rpb24gX3Rha2VTbmFwc2hvdCgpIHsKICAgICAgcmV0dXJuIEVtYmVyLmdldCh0aGlzLCAnY29udGVudCcpLm1hcChmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLmNyZWF0ZVNuYXBzaG90KCk7CiAgICAgIH0pOwogICAgfQogIH0pOwoKICBmdW5jdGlvbiBpc1Jlc291cmNlSWRlbnRpZmVyV2l0aFJlbGF0ZWRMaW5rcyh2YWx1ZSkgewogICAgcmV0dXJuIHZhbHVlICYmIHZhbHVlLmxpbmtzICYmIHZhbHVlLmxpbmtzLnJlbGF0ZWQ7CiAgfQogIC8qKgogICAgVGhpcyBpcyB0aGUgYmFzZUNsYXNzIGZvciB0aGUgZGlmZmVyZW50IFJlZmVyZW5jZXMKICAgIGxpa2UgUmVjb3JkUmVmZXJlbmNlL0hhc01hbnlSZWZlcmVuY2UvQmVsb25nc1RvUmVmZXJlbmNlCgogICBAY2xhc3MgUmVmZXJlbmNlCiAgICovCgoKICB2YXIgUmVmZXJlbmNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUmVmZXJlbmNlKHN0b3JlLCBpbnRlcm5hbE1vZGVsKSB7CiAgICAgIHRoaXMuc3RvcmUgPSBzdG9yZTsKICAgICAgdGhpcy5pbnRlcm5hbE1vZGVsID0gaW50ZXJuYWxNb2RlbDsKICAgICAgdGhpcy5yZWNvcmREYXRhID0gdm9pZCAwOwogICAgICB0aGlzLnJlY29yZERhdGEgPSByZWNvcmREYXRhRm9yKHRoaXMpOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBSZWZlcmVuY2UucHJvdG90eXBlOwoKICAgIF9wcm90by5fcmVzb3VyY2UgPSBmdW5jdGlvbiBfcmVzb3VyY2UoKSB7fQogICAgLyoqCiAgICAgVGhpcyByZXR1cm5zIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50cyBob3cgdGhlIHJlZmVyZW5jZSB3aWxsIGJlCiAgICAgbG9va2VkIHVwIHdoZW4gaXQgaXMgbG9hZGVkLiBJZiB0aGUgcmVsYXRpb25zaGlwIGhhcyBhIGxpbmsgaXQgd2lsbAogICAgIHVzZSB0aGUgImxpbmsiIG90aGVyd2lzZSBpdCBkZWZhdWx0cyB0byAiaWQiLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgY29tbWVudHM6IGhhc01hbnkoeyBhc3luYzogdHJ1ZSB9KQogICAgIH0pOwogICAgIGBgYAogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHBvc3QgPSBzdG9yZS5wdXNoKHsKICAgICAgIGRhdGE6IHsKICAgICAgICAgdHlwZTogJ3Bvc3QnLAogICAgICAgICBpZDogMSwKICAgICAgICAgcmVsYXRpb25zaGlwczogewogICAgICAgICAgIGNvbW1lbnRzOiB7CiAgICAgICAgICAgICBkYXRhOiBbeyB0eXBlOiAnY29tbWVudCcsIGlkOiAxIH1dCiAgICAgICAgICAgfQogICAgICAgICB9CiAgICAgICB9CiAgICAgfSk7CiAgICAgIGxldCBjb21tZW50c1JlZiA9IHBvc3QuaGFzTWFueSgnY29tbWVudHMnKTsKICAgICAgLy8gZ2V0IHRoZSBpZGVudGlmaWVyIG9mIHRoZSByZWZlcmVuY2UKICAgICBpZiAoY29tbWVudHNSZWYucmVtb3RlVHlwZSgpID09PSAiaWRzIikgewogICAgICAgbGV0IGlkcyA9IGNvbW1lbnRzUmVmLmlkcygpOwogICAgIH0gZWxzZSBpZiAoY29tbWVudHNSZWYucmVtb3RlVHlwZSgpID09PSAibGluayIpIHsKICAgICAgIGxldCBsaW5rID0gY29tbWVudHNSZWYubGluaygpOwogICAgIH0KICAgICBgYGAKICAgICAgQG1ldGhvZCByZW1vdGVUeXBlCiAgICAgQHJldHVybiB7U3RyaW5nfSBUaGUgbmFtZSBvZiB0aGUgcmVtb3RlIHR5cGUuIFRoaXMgc2hvdWxkIGVpdGhlciBiZSAibGluayIgb3IgImlkcyIKICAgICAqLwogICAgOwoKICAgIF9wcm90by5yZW1vdGVUeXBlID0gZnVuY3Rpb24gcmVtb3RlVHlwZSgpIHsKICAgICAgdmFyIHZhbHVlID0gdGhpcy5fcmVzb3VyY2UoKTsKCiAgICAgIGlmIChpc1Jlc291cmNlSWRlbnRpZmVyV2l0aFJlbGF0ZWRMaW5rcyh2YWx1ZSkpIHsKICAgICAgICByZXR1cm4gJ2xpbmsnOwogICAgICB9CgogICAgICByZXR1cm4gJ2lkJzsKICAgIH0KICAgIC8qKgogICAgIFRoZSBsaW5rIEVtYmVyIERhdGEgd2lsbCB1c2UgdG8gZmV0Y2ggb3IgcmVsb2FkIHRoaXMgYmVsb25ncy10bwogICAgIHJlbGF0aW9uc2hpcC4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgLy8gbW9kZWxzL2Jsb2cuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdXNlcjogYmVsb25nc1RvKHsgYXN5bmM6IHRydWUgfSkKICAgICAgfSk7CiAgICAgIGxldCBibG9nID0gc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ2Jsb2cnLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgIHVzZXI6IHsKICAgICAgICAgICAgICBsaW5rczogewogICAgICAgICAgICAgICAgcmVsYXRlZDogJy9hcnRpY2xlcy8xL2F1dGhvcicKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgIGxldCB1c2VyUmVmID0gYmxvZy5iZWxvbmdzVG8oJ3VzZXInKTsKICAgICAgLy8gZ2V0IHRoZSBpZGVudGlmaWVyIG9mIHRoZSByZWZlcmVuY2UKICAgICBpZiAodXNlclJlZi5yZW1vdGVUeXBlKCkgPT09ICJsaW5rIikgewogICAgICAgIGxldCBsaW5rID0gdXNlclJlZi5saW5rKCk7CiAgICAgIH0KICAgICBgYGAKICAgICAgQG1ldGhvZCBsaW5rCiAgICAgQHJldHVybiB7U3RyaW5nfSBUaGUgbGluayBFbWJlciBEYXRhIHdpbGwgdXNlIHRvIGZldGNoIG9yIHJlbG9hZCB0aGlzIGJlbG9uZ3MtdG8gcmVsYXRpb25zaGlwLgogICAgICovCiAgICA7CgogICAgX3Byb3RvLmxpbmsgPSBmdW5jdGlvbiBsaW5rKCkgewogICAgICB2YXIgbGluazsKCiAgICAgIHZhciByZXNvdXJjZSA9IHRoaXMuX3Jlc291cmNlKCk7CgogICAgICBpZiAoaXNSZXNvdXJjZUlkZW50aWZlcldpdGhSZWxhdGVkTGlua3MocmVzb3VyY2UpKSB7CiAgICAgICAgaWYgKHJlc291cmNlLmxpbmtzKSB7CiAgICAgICAgICBsaW5rID0gcmVzb3VyY2UubGlua3MucmVsYXRlZDsKICAgICAgICAgIGxpbmsgPSAhbGluayB8fCB0eXBlb2YgbGluayA9PT0gJ3N0cmluZycgPyBsaW5rIDogbGluay5ocmVmOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGxpbmsgfHwgbnVsbDsKICAgIH0KICAgIC8qKgogICAgIFRoZSBtZXRhIGRhdGEgZm9yIHRoZSBiZWxvbmdzLXRvIHJlbGF0aW9uc2hpcC4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgLy8gbW9kZWxzL2Jsb2cuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdXNlcjogYmVsb25nc1RvKHsgYXN5bmM6IHRydWUgfSkKICAgICAgfSk7CiAgICAgIGxldCBibG9nID0gc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ2Jsb2cnLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgIHVzZXI6IHsKICAgICAgICAgICAgICBsaW5rczogewogICAgICAgICAgICAgICAgcmVsYXRlZDogewogICAgICAgICAgICAgICAgICBocmVmOiAnL2FydGljbGVzLzEvYXV0aG9yJwogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIG1ldGE6IHsKICAgICAgICAgICAgICAgICAgbGFzdFVwZGF0ZWQ6IDE0NTgwMTQ0MDAwMDAKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBsZXQgdXNlclJlZiA9IGJsb2cuYmVsb25nc1RvKCd1c2VyJyk7CiAgICAgIHVzZXJSZWYubWV0YSgpIC8vIHsgbGFzdFVwZGF0ZWQ6IDE0NTgwMTQ0MDAwMDAgfQogICAgIGBgYAogICAgICBAbWV0aG9kIG1ldGEKICAgICBAcmV0dXJuIHtPYmplY3R9IFRoZSBtZXRhIGluZm9ybWF0aW9uIGZvciB0aGUgYmVsb25ncy10byByZWxhdGlvbnNoaXAuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ubWV0YSA9IGZ1bmN0aW9uIG1ldGEoKSB7CiAgICAgIHZhciBtZXRhID0gbnVsbDsKCiAgICAgIHZhciByZXNvdXJjZSA9IHRoaXMuX3Jlc291cmNlKCk7CgogICAgICBpZiAocmVzb3VyY2UgJiYgcmVzb3VyY2UubWV0YSAmJiB0eXBlb2YgcmVzb3VyY2UubWV0YSA9PT0gJ29iamVjdCcpIHsKICAgICAgICBtZXRhID0gcmVzb3VyY2UubWV0YTsKICAgICAgfQoKICAgICAgcmV0dXJuIG1ldGE7CiAgICB9OwoKICAgIHJldHVybiBSZWZlcmVuY2U7CiAgfSgpOwoKICBpZiAoY2FuYXJ5RmVhdHVyZXMuRlVMTF9MSU5LU19PTl9SRUxBVElPTlNISVBTKSB7CiAgICBSZWZlcmVuY2UucHJvdG90eXBlLmxpbmtzID0gZnVuY3Rpb24gbGlua3MoKSB7CiAgICAgIHZhciByZXNvdXJjZSA9IHRoaXMuX3Jlc291cmNlKCk7CgogICAgICByZXR1cm4gcmVzb3VyY2UgJiYgcmVzb3VyY2UubGlua3MgPyByZXNvdXJjZS5saW5rcyA6IG51bGw7CiAgICB9OwogIH0KCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXMkMih0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgidmFsdWUiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfQoKICBmdW5jdGlvbiBfY3JlYXRlQ2xhc3MkMihDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDIoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQyKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfQoKICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZShzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MucHJvdG90eXBlKTsgc3ViQ2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gc3ViQ2xhc3M7IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH0KCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KCiAgLyoqCiAgICAgQSBgUmVjb3JkUmVmZXJlbmNlYCBpcyBhIGxvdy1sZXZlbCBBUEkgdGhhdCBhbGxvd3MgdXNlcnMgYW5kCiAgICAgYWRkb24gYXV0aG9ycyB0byBwZXJmb3JtIG1ldGEtb3BlcmF0aW9ucyBvbiBhIHJlY29yZC4KCiAgICAgQGNsYXNzIFJlY29yZFJlZmVyZW5jZQogICAgIEBleHRlbmRzIFJlZmVyZW5jZQogICovCiAgdmFyIFJlY29yZFJlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfUmVmZXJlbmNlKSB7CiAgICBfaW5oZXJpdHNMb29zZShSZWNvcmRSZWZlcmVuY2UsIF9SZWZlcmVuY2UpOwoKICAgIGZ1bmN0aW9uIFJlY29yZFJlZmVyZW5jZSgpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgICAgfQoKICAgICAgX3RoaXMgPSBfUmVmZXJlbmNlLmNhbGwuYXBwbHkoX1JlZmVyZW5jZSwgW3RoaXNdLmNvbmNhdChhcmdzKSkgfHwgdGhpczsKICAgICAgX3RoaXMudHlwZSA9IF90aGlzLmludGVybmFsTW9kZWwubW9kZWxOYW1lOwogICAgICByZXR1cm4gX3RoaXM7CiAgICB9CgogICAgdmFyIF9wcm90byA9IFJlY29yZFJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgLyoqCiAgICAgICBUaGUgYGlkYCBvZiB0aGUgcmVjb3JkIHRoYXQgdGhpcyByZWZlcmVuY2UgcmVmZXJzIHRvLgogICAgICAgIFRvZ2V0aGVyLCB0aGUgYHR5cGVgIGFuZCBgaWRgIHByb3BlcnRpZXMgZm9ybSBhIGNvbXBvc2l0ZSBrZXkgZm9yCiAgICAgICB0aGUgaWRlbnRpdHkgbWFwLgogICAgICAgIEV4YW1wbGUKICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgICBsZXQgdXNlclJlZiA9IHN0b3JlLmdldFJlZmVyZW5jZSgndXNlcicsIDEpOwogICAgICAgIHVzZXJSZWYuaWQoKTsgLy8gJzEnCiAgICAgICBgYGAKICAgICAgICBAbWV0aG9kIGlkCiAgICAgICBAcmV0dXJuIHtTdHJpbmd9IFRoZSBpZCBvZiB0aGUgcmVjb3JkLgogICAgKi8KICAgIF9wcm90by5pZCA9IGZ1bmN0aW9uIGlkKCkgewogICAgICByZXR1cm4gdGhpcy5faWQ7CiAgICB9CiAgICAvKioKICAgICAgIEhvdyB0aGUgcmVmZXJlbmNlIHdpbGwgYmUgbG9va2VkIHVwIHdoZW4gaXQgaXMgbG9hZGVkLiBDdXJyZW50bHkKICAgICAgIHRoaXMgYWx3YXlzIHJldHVybnMgYGlkZW50aXR5YCB0byBzaWduaWZ5IHRoYXQgYSByZWNvcmQgd2lsbCBiZQogICAgICAgbG9hZGVkIGJ5IGl0cyBgdHlwZWAgYW5kIGBpZGAuCiAgICAgICAgRXhhbXBsZQogICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgIGNvbnN0IHVzZXJSZWYgPSBzdG9yZS5nZXRSZWZlcmVuY2UoJ3VzZXInLCAxKTsKICAgICAgICB1c2VyUmVmLnJlbW90ZVR5cGUoKTsgLy8gJ2lkZW50aXR5JwogICAgICAgYGBgCiAgICAgICAgQG1ldGhvZCByZW1vdGVUeXBlCiAgICAgICBAcmV0dXJuIHtTdHJpbmd9ICdpZGVudGl0eScKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlbW90ZVR5cGUgPSBmdW5jdGlvbiByZW1vdGVUeXBlKCkgewogICAgICByZXR1cm4gJ2lkZW50aXR5JzsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIEFQSSBhbGxvd3MgeW91IHRvIHByb3ZpZGUgYSByZWZlcmVuY2Ugd2l0aCBuZXcgZGF0YS4gVGhlCiAgICAgIHNpbXBsZXN0IHVzYWdlIG9mIHRoaXMgQVBJIGlzIHNpbWlsYXIgdG8gYHN0b3JlLnB1c2hgOiB5b3UgcHJvdmlkZSBhCiAgICAgIG5vcm1hbGl6ZWQgaGFzaCBvZiBkYXRhIGFuZCB0aGUgb2JqZWN0IHJlcHJlc2VudGVkIGJ5IHRoZSByZWZlcmVuY2UKICAgICAgd2lsbCB1cGRhdGUuCiAgICAgICBJZiB5b3UgcGFzcyBhIHByb21pc2UgdG8gYHB1c2hgLCBFbWJlciBEYXRhIHdpbGwgbm90IGFzayB0aGUgYWRhcHRlcgogICAgICBmb3IgdGhlIGRhdGEgaWYgYW5vdGhlciBhdHRlbXB0IHRvIGZldGNoIGl0IGlzIG1hZGUgaW4gdGhlCiAgICAgIGludGVyaW0uIFdoZW4gdGhlIHByb21pc2UgcmVzb2x2ZXMsIHRoZSB1bmRlcmx5aW5nIG9iamVjdCBpcyB1cGRhdGVkCiAgICAgIHdpdGggdGhlIG5ldyBkYXRhLCBhbmQgdGhlIHByb21pc2UgcmV0dXJuZWQgYnkgKnRoaXMgZnVuY3Rpb24qIGlzIHJlc29sdmVkCiAgICAgIHdpdGggdGhhdCBvYmplY3QuCiAgICAgICBGb3IgZXhhbXBsZSwgYHJlY29yZFJlZmVyZW5jZS5wdXNoKHByb21pc2UpYCB3aWxsIGJlIHJlc29sdmVkIHdpdGggYQogICAgICByZWNvcmQuCiAgICAgICAgRXhhbXBsZQogICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgIGxldCB1c2VyUmVmID0gc3RvcmUuZ2V0UmVmZXJlbmNlKCd1c2VyJywgMSk7CiAgICAgICAgLy8gcHJvdmlkZSBkYXRhIGZvciByZWZlcmVuY2UKICAgICAgIHVzZXJSZWYucHVzaCh7CiAgICAgICAgIGRhdGE6IHsKICAgICAgICAgICBpZDogIjEiLAogICAgICAgICAgIHR5cGU6ICJ1c2VyIiwKICAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgICB1c2VybmFtZTogIkB1c2VyIgogICAgICAgICAgIH0KICAgICAgICAgfQogICAgICAgfSkudGhlbihmdW5jdGlvbih1c2VyKSB7CiAgICAgICAgIHVzZXJSZWYudmFsdWUoKSA9PT0gdXNlcjsKICAgICAgIH0pOwogICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHB1c2gKICAgICAgQHBhcmFtIG9iamVjdE9yUHJvbWlzZSBhIEpTT046QVBJIFJlc291cmNlRG9jdW1lbnQgb3IgYSBwcm9taXNlIHJlc29sdmluZyB0byBvbmUKICAgICAgQHJldHVybiBhIHByb21pc2UgZm9yIHRoZSB2YWx1ZSAocmVjb3JkIG9yIHJlbGF0aW9uc2hpcCkKICAgICovCiAgICA7CgogICAgX3Byb3RvLnB1c2ggPSBmdW5jdGlvbiBwdXNoKG9iamVjdE9yUHJvbWlzZSkgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIHJldHVybiBFbWJlci5SU1ZQLnJlc29sdmUob2JqZWN0T3JQcm9taXNlKS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgICAgcmV0dXJuIF90aGlzMi5zdG9yZS5wdXNoKGRhdGEpOwogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICBJZiB0aGUgZW50aXR5IHJlZmVycmVkIHRvIGJ5IHRoZSByZWZlcmVuY2UgaXMgYWxyZWFkeSBsb2FkZWQsIGl0IGlzCiAgICAgIHByZXNlbnQgYXMgYHJlZmVyZW5jZS52YWx1ZWAuIE90aGVyd2lzZSB0aGUgdmFsdWUgcmV0dXJuZWQgYnkgdGhpcyBmdW5jdGlvbgogICAgICBpcyBgbnVsbGAuCiAgICAgICAgRXhhbXBsZQogICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgIGxldCB1c2VyUmVmID0gc3RvcmUuZ2V0UmVmZXJlbmNlKCd1c2VyJywgMSk7CiAgICAgICAgdXNlclJlZi52YWx1ZSgpOyAvLyB1c2VyCiAgICAgICBgYGAKICAgICAgICBAbWV0aG9kIHZhbHVlCiAgICAgICBAcmV0dXJuIHtNb2RlbH0gdGhlIHJlY29yZCBmb3IgdGhpcyBSZWNvcmRSZWZlcmVuY2UKICAgICovCiAgICA7CgogICAgX3Byb3RvLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIGlmICh0aGlzLmludGVybmFsTW9kZWwuaGFzUmVjb3JkKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxNb2RlbC5nZXRSZWNvcmQoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICAvKioKICAgICAgIFRyaWdnZXJzIGEgZmV0Y2ggZm9yIHRoZSBiYWNraW5nIGVudGl0eSBiYXNlZCBvbiBpdHMgYHJlbW90ZVR5cGVgCiAgICAgICAoc2VlIGByZW1vdGVUeXBlYCBkZWZpbml0aW9ucyBwZXIgcmVmZXJlbmNlIHR5cGUpLgogICAgICAgIEV4YW1wbGUKICAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgICBsZXQgdXNlclJlZiA9IHN0b3JlLmdldFJlZmVyZW5jZSgndXNlcicsIDEpOwogICAgICAgIC8vIGxvYWQgdXNlciAodmlhIHN0b3JlLmZpbmQpCiAgICAgICB1c2VyUmVmLmxvYWQoKS50aGVuKC4uLikKICAgICAgIGBgYAogICAgICAgIEBtZXRob2QgbG9hZAogICAgICAgQHJldHVybiB7UHJvbWlzZTxyZWNvcmQ+fSB0aGUgcmVjb3JkIGZvciB0aGlzIFJlY29yZFJlZmVyZW5jZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ubG9hZCA9IGZ1bmN0aW9uIGxvYWQoKSB7CiAgICAgIGlmICh0aGlzLl9pZCAhPT0gbnVsbCkgewogICAgICAgIHJldHVybiB0aGlzLnN0b3JlLmZpbmRSZWNvcmQodGhpcy50eXBlLCB0aGlzLl9pZCk7CiAgICAgIH0KCiAgICAgIHRocm93IG5ldyBFcnJvcigiVW5hYmxlIHRvIGZldGNoIHJlY29yZCBvZiB0eXBlICIgKyB0aGlzLnR5cGUgKyAiIHdpdGhvdXQgYW4gaWQiKTsKICAgIH0KICAgIC8qKgogICAgICAgUmVsb2FkcyB0aGUgcmVjb3JkIGlmIGl0IGlzIGFscmVhZHkgbG9hZGVkLiBJZiB0aGUgcmVjb3JkIGlzIG5vdAogICAgICAgbG9hZGVkIGl0IHdpbGwgbG9hZCB0aGUgcmVjb3JkIHZpYSBgc3RvcmUuZmluZFJlY29yZGAKICAgICAgICBFeGFtcGxlCiAgICAgICAgYGBgamF2YXNjcmlwdAogICAgICAgbGV0IHVzZXJSZWYgPSBzdG9yZS5nZXRSZWZlcmVuY2UoJ3VzZXInLCAxKTsKICAgICAgICAvLyBvciB0cmlnZ2VyIGEgcmVsb2FkCiAgICAgICB1c2VyUmVmLnJlbG9hZCgpLnRoZW4oLi4uKQogICAgICAgYGBgCiAgICAgICAgQG1ldGhvZCByZWxvYWQKICAgICAgIEByZXR1cm4ge1Byb21pc2U8cmVjb3JkPn0gdGhlIHJlY29yZCBmb3IgdGhpcyBSZWNvcmRSZWZlcmVuY2UKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlbG9hZCA9IGZ1bmN0aW9uIHJlbG9hZCgpIHsKICAgICAgdmFyIHJlY29yZCA9IHRoaXMudmFsdWUoKTsKCiAgICAgIGlmIChyZWNvcmQpIHsKICAgICAgICByZXR1cm4gcmVjb3JkLnJlbG9hZCgpOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5sb2FkKCk7CiAgICB9OwoKICAgIF9jcmVhdGVDbGFzcyQyKFJlY29yZFJlZmVyZW5jZSwgW3sKICAgICAga2V5OiAiX2lkIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxNb2RlbC5pZDsKICAgICAgfQogICAgfV0pOwoKICAgIHJldHVybiBSZWNvcmRSZWZlcmVuY2U7CiAgfShSZWZlcmVuY2UpOwoKICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZSQxKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcy5wcm90b3R5cGUpOyBzdWJDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBzdWJDbGFzczsgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfQogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICBBIGBCZWxvbmdzVG9SZWZlcmVuY2VgIGlzIGEgbG93LWxldmVsIEFQSSB0aGF0IGFsbG93cyB1c2VycyBhbmQKICAgYWRkb24gYXV0aG9ycyB0byBwZXJmb3JtIG1ldGEtb3BlcmF0aW9ucyBvbiBhIGJlbG9uZ3MtdG8KICAgcmVsYXRpb25zaGlwLgoKICAgQGNsYXNzIEJlbG9uZ3NUb1JlZmVyZW5jZQogICBAZXh0ZW5kcyBSZWZlcmVuY2UKICAgKi8KCiAgdmFyIEJlbG9uZ3NUb1JlZmVyZW5jZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfUmVmZXJlbmNlKSB7CiAgICBfaW5oZXJpdHNMb29zZSQxKEJlbG9uZ3NUb1JlZmVyZW5jZSwgX1JlZmVyZW5jZSk7CgogICAgZnVuY3Rpb24gQmVsb25nc1RvUmVmZXJlbmNlKHN0b3JlLCBwYXJlbnRJbnRlcm5hbE1vZGVsLCBiZWxvbmdzVG9SZWxhdGlvbnNoaXAsIGtleSkgewogICAgICB2YXIgX3RoaXM7CgogICAgICBfdGhpcyA9IF9SZWZlcmVuY2UuY2FsbCh0aGlzLCBzdG9yZSwgcGFyZW50SW50ZXJuYWxNb2RlbCkgfHwgdGhpczsKICAgICAgX3RoaXMua2V5ID0ga2V5OwogICAgICBfdGhpcy5iZWxvbmdzVG9SZWxhdGlvbnNoaXAgPSBiZWxvbmdzVG9SZWxhdGlvbnNoaXA7CiAgICAgIF90aGlzLnR5cGUgPSBiZWxvbmdzVG9SZWxhdGlvbnNoaXAucmVsYXRpb25zaGlwTWV0YS50eXBlOwogICAgICBfdGhpcy5wYXJlbnQgPSBwYXJlbnRJbnRlcm5hbE1vZGVsLnJlY29yZFJlZmVyZW5jZTsKICAgICAgX3RoaXMucGFyZW50SW50ZXJuYWxNb2RlbCA9IHBhcmVudEludGVybmFsTW9kZWw7IC8vIFRPRE8gaW52ZXJzZQoKICAgICAgcmV0dXJuIF90aGlzOwogICAgfQogICAgLyoqCiAgICAgVGhlIGBpZGAgb2YgdGhlIHJlY29yZCB0aGF0IHRoaXMgcmVmZXJlbmNlIHJlZmVycyB0by4gVG9nZXRoZXIsIHRoZQogICAgIGB0eXBlKClgIGFuZCBgaWQoKWAgbWV0aG9kcyBmb3JtIGEgY29tcG9zaXRlIGtleSBmb3IgdGhlIGlkZW50aXR5CiAgICAgbWFwLiBUaGlzIGNhbiBiZSB1c2VkIHRvIGFjY2VzcyB0aGUgaWQgb2YgYW4gYXN5bmMgcmVsYXRpb25zaGlwCiAgICAgd2l0aG91dCB0cmlnZ2VyaW5nIGEgZmV0Y2ggdGhhdCB3b3VsZCBub3JtYWxseSBoYXBwZW4gaWYgeW91CiAgICAgYXR0ZW1wdGVkIHRvIHVzZSBgcmVjb3JkLmdldCgncmVsYXRpb25zaGlwLmlkJylgLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAvLyBtb2RlbHMvYmxvZy5qcwogICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdXNlcjogYmVsb25nc1RvKHsgYXN5bmM6IHRydWUgfSkKICAgICAgfSk7CiAgICAgIGxldCBibG9nID0gc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ2Jsb2cnLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgIHVzZXI6IHsKICAgICAgICAgICAgICBkYXRhOiB7IHR5cGU6ICd1c2VyJywgaWQ6IDEgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICBsZXQgdXNlclJlZiA9IGJsb2cuYmVsb25nc1RvKCd1c2VyJyk7CiAgICAgIC8vIGdldCB0aGUgaWRlbnRpZmllciBvZiB0aGUgcmVmZXJlbmNlCiAgICAgaWYgKHVzZXJSZWYucmVtb3RlVHlwZSgpID09PSAiaWQiKSB7CiAgICAgICAgbGV0IGlkID0gdXNlclJlZi5pZCgpOwogICAgICB9CiAgICAgYGBgCiAgICAgIEBtZXRob2QgaWQKICAgICBAcmV0dXJuIHtTdHJpbmd9IFRoZSBpZCBvZiB0aGUgcmVjb3JkIGluIHRoaXMgYmVsb25nc1RvIHJlbGF0aW9uc2hpcC4KICAgICAqLwoKCiAgICB2YXIgX3Byb3RvID0gQmVsb25nc1RvUmVmZXJlbmNlLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uaWQgPSBmdW5jdGlvbiBpZCgpIHsKICAgICAgdmFyIGlkID0gbnVsbDsKCiAgICAgIHZhciByZXNvdXJjZSA9IHRoaXMuX3Jlc291cmNlKCk7CgogICAgICBpZiAocmVzb3VyY2UgJiYgcmVzb3VyY2UuZGF0YSAmJiByZXNvdXJjZS5kYXRhLmlkKSB7CiAgICAgICAgaWQgPSByZXNvdXJjZS5kYXRhLmlkOwogICAgICB9CgogICAgICByZXR1cm4gaWQ7CiAgICB9OwoKICAgIF9wcm90by5fcmVzb3VyY2UgPSBmdW5jdGlvbiBfcmVzb3VyY2UoKSB7CiAgICAgIHJldHVybiB0aGlzLnJlY29yZERhdGEuZ2V0QmVsb25nc1RvKHRoaXMua2V5KTsKICAgIH0KICAgIC8qKgogICAgIGBwdXNoYCBjYW4gYmUgdXNlZCB0byB1cGRhdGUgdGhlIGRhdGEgaW4gdGhlIHJlbGF0aW9uc2hpcCBhbmQgRW1iZXIKICAgICBEYXRhIHdpbGwgdHJlYXQgdGhlIG5ldyBkYXRhIGFzIHRoZSBjb25hbmljYWwgdmFsdWUgb2YgdGhpcwogICAgIHJlbGF0aW9uc2hpcCBvbiB0aGUgYmFja2VuZC4KICAgICAgRXhhbXBsZQogICAgICBgYGBhcHAvbW9kZWxzL2Jsb2cuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgYmVsb25nc1RvIH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgIHVzZXI6IGJlbG9uZ3NUbyh7IGFzeW5jOiB0cnVlIH0pCiAgICAgIH0pOwogICAgICBsZXQgYmxvZyA9IHN0b3JlLnB1c2goewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIHR5cGU6ICdibG9nJywKICAgICAgICAgIGlkOiAxLAogICAgICAgICAgcmVsYXRpb25zaGlwczogewogICAgICAgICAgICB1c2VyOiB7CiAgICAgICAgICAgICAgZGF0YTogeyB0eXBlOiAndXNlcicsIGlkOiAxIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgbGV0IHVzZXJSZWYgPSBibG9nLmJlbG9uZ3NUbygndXNlcicpOwogICAgICAvLyBwcm92aWRlIGRhdGEgZm9yIHJlZmVyZW5jZQogICAgIHVzZXJSZWYucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ3VzZXInLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgIHVzZXJuYW1lOiAiQHVzZXIiCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KS50aGVuKGZ1bmN0aW9uKHVzZXIpIHsKICAgICAgICB1c2VyUmVmLnZhbHVlKCkgPT09IHVzZXI7CiAgICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIHB1c2gKICAgICBAcGFyYW0ge09iamVjdHxQcm9taXNlfSBvYmplY3RPclByb21pc2UgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBKU09OQVBJIGRvY3VtZW50IG9iamVjdCBkZXNjcmliaW5nIHRoZSBuZXcgdmFsdWUgb2YgdGhpcyByZWxhdGlvbnNoaXAuCiAgICAgQHJldHVybiB7UHJvbWlzZTxyZWNvcmQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBuZXcgdmFsdWUgaW4gdGhpcyBiZWxvbmdzLXRvIHJlbGF0aW9uc2hpcC4KICAgICAqLwogICAgOwoKICAgIF9wcm90by5wdXNoID0gZnVuY3Rpb24gcHVzaChvYmplY3RPclByb21pc2UpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICAvLyBUT0RPIGRlcHJlY2F0ZSB0aGVuYWJsZSBzdXBwb3J0CiAgICAgIHJldHVybiBFbWJlci5SU1ZQLnJlc29sdmUob2JqZWN0T3JQcm9taXNlKS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgICAgdmFyIHJlY29yZDsgLy8gVE9ETyBkZXByZWNhdGUgZGF0YSBhcyBNb2RlbAoKICAgICAgICBpZiAocGVla1JlY29yZElkZW50aWZpZXIoZGF0YSkpIHsKICAgICAgICAgIHJlY29yZCA9IGRhdGE7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlY29yZCA9IF90aGlzMi5zdG9yZS5wdXNoKGRhdGEpOwogICAgICAgIH0KCiAgICAgICAgLy9UT0RPIElnb3IgY2xlYW51cCwgbWF5YmUgbW92ZSB0byByZWxhdGlvbnNoaXAgcHVzaAogICAgICAgIF90aGlzMi5iZWxvbmdzVG9SZWxhdGlvbnNoaXAuc2V0Q2Fub25pY2FsUmVjb3JkRGF0YShyZWNvcmREYXRhRm9yKHJlY29yZCkpOwoKICAgICAgICByZXR1cm4gcmVjb3JkOwogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgIGB2YWx1ZSgpYCBzeW5jaHJvbm91c2x5IHJldHVybnMgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIGJlbG9uZ3MtdG8KICAgICByZWxhdGlvbnNoaXAuIFVubGlrZSBgcmVjb3JkLmdldCgncmVsYXRpb25zaGlwTmFtZScpYCwgY2FsbGluZwogICAgIGB2YWx1ZSgpYCBvbiBhIHJlZmVyZW5jZSBkb2VzIG5vdCB0cmlnZ2VyIGEgZmV0Y2ggaWYgdGhlIGFzeW5jCiAgICAgcmVsYXRpb25zaGlwIGlzIG5vdCB5ZXQgbG9hZGVkLiBJZiB0aGUgcmVsYXRpb25zaGlwIGlzIG5vdCBsb2FkZWQKICAgICBpdCB3aWxsIGFsd2F5cyByZXR1cm4gYG51bGxgLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAvLyBtb2RlbHMvYmxvZy5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICAgdXNlcjogYmVsb25nc1RvKHsgYXN5bmM6IHRydWUgfSkKICAgICAgfSk7CiAgICAgIGxldCBibG9nID0gc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ2Jsb2cnLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgIHVzZXI6IHsKICAgICAgICAgICAgICBkYXRhOiB7IHR5cGU6ICd1c2VyJywgaWQ6IDEgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICBsZXQgdXNlclJlZiA9IGJsb2cuYmVsb25nc1RvKCd1c2VyJyk7CiAgICAgIHVzZXJSZWYudmFsdWUoKTsgLy8gbnVsbAogICAgICAvLyBwcm92aWRlIGRhdGEgZm9yIHJlZmVyZW5jZQogICAgIHVzZXJSZWYucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgdHlwZTogJ3VzZXInLAogICAgICAgICAgaWQ6IDEsCiAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgIHVzZXJuYW1lOiAiQHVzZXIiCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KS50aGVuKGZ1bmN0aW9uKHVzZXIpIHsKICAgICAgICB1c2VyUmVmLnZhbHVlKCk7IC8vIHVzZXIKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIEBtZXRob2QgdmFsdWUKICAgICBAcmV0dXJuIHtNb2RlbH0gdGhlIHJlY29yZCBpbiB0aGlzIHJlbGF0aW9uc2hpcAogICAgICovCiAgICA7CgogICAgX3Byb3RvLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7CiAgICAgIHZhciBzdG9yZSA9IHRoaXMucGFyZW50SW50ZXJuYWxNb2RlbC5zdG9yZTsKCiAgICAgIHZhciByZXNvdXJjZSA9IHRoaXMuX3Jlc291cmNlKCk7CgogICAgICBpZiAocmVzb3VyY2UgJiYgcmVzb3VyY2UuZGF0YSkgewogICAgICAgIHZhciBpbnZlcnNlSW50ZXJuYWxNb2RlbCA9IHN0b3JlLl9pbnRlcm5hbE1vZGVsRm9yUmVzb3VyY2UocmVzb3VyY2UuZGF0YSk7CgogICAgICAgIGlmIChpbnZlcnNlSW50ZXJuYWxNb2RlbCAmJiBpbnZlcnNlSW50ZXJuYWxNb2RlbC5pc0xvYWRlZCgpKSB7CiAgICAgICAgICByZXR1cm4gaW52ZXJzZUludGVybmFsTW9kZWwuZ2V0UmVjb3JkKCk7CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIC8qKgogICAgIExvYWRzIGEgcmVjb3JkIGluIGEgYmVsb25ncy10byByZWxhdGlvbnNoaXAgaWYgaXQgaXMgbm90IGFscmVhZHkKICAgICBsb2FkZWQuIElmIHRoZSByZWxhdGlvbnNoaXAgaXMgYWxyZWFkeSBsb2FkZWQgdGhpcyBtZXRob2QgZG9lcyBub3QKICAgICB0cmlnZ2VyIGEgbmV3IGxvYWQuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgamF2YXNjcmlwdAogICAgIC8vIG1vZGVscy9ibG9nLmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGJlbG9uZ3NUbyB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICB1c2VyOiBiZWxvbmdzVG8oeyBhc3luYzogdHJ1ZSB9KQogICAgICB9KTsKICAgICAgbGV0IGJsb2cgPSBzdG9yZS5wdXNoKHsKICAgICAgICBkYXRhOiB7CiAgICAgICAgICB0eXBlOiAnYmxvZycsCiAgICAgICAgICBpZDogMSwKICAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICAgdXNlcjogewogICAgICAgICAgICAgIGRhdGE6IHsgdHlwZTogJ3VzZXInLCBpZDogMSB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgIGxldCB1c2VyUmVmID0gYmxvZy5iZWxvbmdzVG8oJ3VzZXInKTsKICAgICAgdXNlclJlZi52YWx1ZSgpOyAvLyBudWxsCiAgICAgIHVzZXJSZWYubG9hZCgpLnRoZW4oZnVuY3Rpb24odXNlcikgewogICAgICAgIHVzZXJSZWYudmFsdWUoKSA9PT0gdXNlcgogICAgICB9KTsKICAgICBgYGAKICAgICAgWW91IG1heSBhbHNvIHBhc3MgaW4gYW4gb3B0aW9ucyBvYmplY3Qgd2hvc2UgcHJvcGVydGllcyB3aWxsIGJlCiAgICAgZmVkIGZvcndhcmQuIFRoaXMgZW5hYmxlcyB5b3UgdG8gcGFzcyBgYWRhcHRlck9wdGlvbnNgIGludG8gdGhlCiAgICAgcmVxdWVzdCBnaXZlbiB0byB0aGUgYWRhcHRlciB2aWEgdGhlIHJlZmVyZW5jZS4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgdXNlclJlZi5sb2FkKHsgYWRhcHRlck9wdGlvbnM6IHsgaXNQcml2YXRlOiB0cnVlIH0gfSkudGhlbihmdW5jdGlvbih1c2VyKSB7CiAgICAgICB1c2VyUmVmLnZhbHVlKCkgPT09IHVzZXI7CiAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYGFwcC9hZGFwdGVycy91c2VyLmpzCiAgICAgZXhwb3J0IGRlZmF1bHQgQXBwbGljYXRpb25BZGFwdGVyLmV4dGVuZCh7CiAgICAgICBmaW5kUmVjb3JkKHN0b3JlLCB0eXBlLCBpZCwgc25hcHNob3QpIHsKICAgICAgICAgLy8gSW4gdGhlIGFkYXB0ZXIgeW91IHdpbGwgaGF2ZSBhY2Nlc3MgdG8gYWRhcHRlck9wdGlvbnMuCiAgICAgICAgIGxldCBhZGFwdGVyT3B0aW9ucyA9IHNuYXBzaG90LmFkYXB0ZXJPcHRpb25zOwogICAgICAgfQogICAgIH0pOwogICAgIGBgYAogICAgICBAbWV0aG9kIGxvYWQKICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyB0aGUgb3B0aW9ucyB0byBwYXNzIGluLgogICAgIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHJlY29yZCBpbiB0aGlzIGJlbG9uZ3MtdG8gcmVsYXRpb25zaGlwLgogICAgICovCiAgICA7CgogICAgX3Byb3RvLmxvYWQgPSBmdW5jdGlvbiBsb2FkKG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMucGFyZW50SW50ZXJuYWxNb2RlbC5nZXRCZWxvbmdzVG8odGhpcy5rZXksIG9wdGlvbnMpOwogICAgfQogICAgLyoqCiAgICAgVHJpZ2dlcnMgYSByZWxvYWQgb2YgdGhlIHZhbHVlIGluIHRoaXMgcmVsYXRpb25zaGlwLiBJZiB0aGUKICAgICByZW1vdGVUeXBlIGlzIGAibGluayJgIEVtYmVyIERhdGEgd2lsbCB1c2UgdGhlIHJlbGF0aW9uc2hpcCBsaW5rIHRvCiAgICAgcmVsb2FkIHRoZSByZWxhdGlvbnNoaXAuIE90aGVyd2lzZSBpdCB3aWxsIHJlbG9hZCB0aGUgcmVjb3JkIGJ5IGl0cwogICAgIGlkLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICAvLyBtb2RlbHMvYmxvZy5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBiZWxvbmdzVG8gfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICB1c2VyOiBiZWxvbmdzVG8oeyBhc3luYzogdHJ1ZSB9KQogICAgICB9KTsKICAgICAgbGV0IGJsb2cgPSBzdG9yZS5wdXNoKHsKICAgICAgICBkYXRhOiB7CiAgICAgICAgICB0eXBlOiAnYmxvZycsCiAgICAgICAgICBpZDogMSwKICAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICAgdXNlcjogewogICAgICAgICAgICAgIGRhdGE6IHsgdHlwZTogJ3VzZXInLCBpZDogMSB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgIGxldCB1c2VyUmVmID0gYmxvZy5iZWxvbmdzVG8oJ3VzZXInKTsKICAgICAgdXNlclJlZi5yZWxvYWQoKS50aGVuKGZ1bmN0aW9uKHVzZXIpIHsKICAgICAgICB1c2VyUmVmLnZhbHVlKCkgPT09IHVzZXIKICAgICAgfSk7CiAgICAgYGBgCiAgICAgIFlvdSBtYXkgYWxzbyBwYXNzIGluIGFuIG9wdGlvbnMgb2JqZWN0IHdob3NlIHByb3BlcnRpZXMgd2lsbCBiZQogICAgIGZlZCBmb3J3YXJkLiBUaGlzIGVuYWJsZXMgeW91IHRvIHBhc3MgYGFkYXB0ZXJPcHRpb25zYCBpbnRvIHRoZQogICAgIHJlcXVlc3QgZ2l2ZW4gdG8gdGhlIGFkYXB0ZXIgdmlhIHRoZSByZWZlcmVuY2UuIEEgZnVsbCBleGFtcGxlCiAgICAgY2FuIGJlIGZvdW5kIGluIHRoZSBgbG9hZGAgbWV0aG9kLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICB1c2VyUmVmLnJlbG9hZCh7IGFkYXB0ZXJPcHRpb25zOiB7IGlzUHJpdmF0ZTogdHJ1ZSB9IH0pCiAgICAgYGBgCiAgICAgIEBtZXRob2QgcmVsb2FkCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgdGhlIG9wdGlvbnMgdG8gcGFzcyBpbi4KICAgICBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSByZWNvcmQgaW4gdGhpcyBiZWxvbmdzLXRvIHJlbGF0aW9uc2hpcCBhZnRlciB0aGUgcmVsb2FkIGhhcyBjb21wbGV0ZWQuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVsb2FkID0gZnVuY3Rpb24gcmVsb2FkKG9wdGlvbnMpIHsKICAgICAgdmFyIF90aGlzMyA9IHRoaXM7CgogICAgICByZXR1cm4gdGhpcy5wYXJlbnRJbnRlcm5hbE1vZGVsLnJlbG9hZEJlbG9uZ3NUbyh0aGlzLmtleSwgb3B0aW9ucykudGhlbihmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIHJldHVybiBfdGhpczMudmFsdWUoKTsKICAgICAgfSk7CiAgICB9OwoKICAgIHJldHVybiBCZWxvbmdzVG9SZWZlcmVuY2U7CiAgfShSZWZlcmVuY2UpOwoKICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZSQyKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcy5wcm90b3R5cGUpOyBzdWJDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBzdWJDbGFzczsgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfQogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICBBIGBIYXNNYW55UmVmZXJlbmNlYCBpcyBhIGxvdy1sZXZlbCBBUEkgdGhhdCBhbGxvd3MgdXNlcnMgYW5kIGFkZG9uCiAgIGF1dGhvcnMgdG8gcGVyZm9ybSBtZXRhLW9wZXJhdGlvbnMgb24gYSBoYXMtbWFueSByZWxhdGlvbnNoaXAuCgogICBAY2xhc3MgSGFzTWFueVJlZmVyZW5jZQogICBAZXh0ZW5kcyBSZWZlcmVuY2UKICAgKi8KCiAgdmFyIEhhc01hbnlSZWZlcmVuY2UgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX1JlZmVyZW5jZSkgewogICAgX2luaGVyaXRzTG9vc2UkMihIYXNNYW55UmVmZXJlbmNlLCBfUmVmZXJlbmNlKTsKCiAgICBmdW5jdGlvbiBIYXNNYW55UmVmZXJlbmNlKHN0b3JlLCBwYXJlbnRJbnRlcm5hbE1vZGVsLCBoYXNNYW55UmVsYXRpb25zaGlwLCBrZXkpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfUmVmZXJlbmNlLmNhbGwodGhpcywgc3RvcmUsIHBhcmVudEludGVybmFsTW9kZWwpIHx8IHRoaXM7CiAgICAgIF90aGlzLmtleSA9IGtleTsKICAgICAgX3RoaXMuaGFzTWFueVJlbGF0aW9uc2hpcCA9IGhhc01hbnlSZWxhdGlvbnNoaXA7CiAgICAgIF90aGlzLnR5cGUgPSBoYXNNYW55UmVsYXRpb25zaGlwLnJlbGF0aW9uc2hpcE1ldGEudHlwZTsKICAgICAgX3RoaXMucGFyZW50ID0gcGFyZW50SW50ZXJuYWxNb2RlbC5yZWNvcmRSZWZlcmVuY2U7CiAgICAgIF90aGlzLnBhcmVudEludGVybmFsTW9kZWwgPSBwYXJlbnRJbnRlcm5hbE1vZGVsOyAvLyBUT0RPIGludmVyc2UKCiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gSGFzTWFueVJlZmVyZW5jZS5wcm90b3R5cGU7CgogICAgX3Byb3RvLl9yZXNvdXJjZSA9IGZ1bmN0aW9uIF9yZXNvdXJjZSgpIHsKICAgICAgcmV0dXJuIHRoaXMucmVjb3JkRGF0YS5nZXRIYXNNYW55KHRoaXMua2V5KTsKICAgIH0KICAgIC8qKgogICAgIFRoaXMgcmV0dXJucyBhIHN0cmluZyB0aGF0IHJlcHJlc2VudHMgaG93IHRoZSByZWZlcmVuY2Ugd2lsbCBiZQogICAgIGxvb2tlZCB1cCB3aGVuIGl0IGlzIGxvYWRlZC4gSWYgdGhlIHJlbGF0aW9uc2hpcCBoYXMgYSBsaW5rIGl0IHdpbGwKICAgICB1c2UgdGhlICJsaW5rIiBvdGhlcndpc2UgaXQgZGVmYXVsdHMgdG8gImlkIi4KICAgICAgRXhhbXBsZQogICAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgY29tbWVudHM6IGhhc01hbnkoeyBhc3luYzogdHJ1ZSB9KQogICAgIH0pOwogICAgIGBgYAogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHBvc3QgPSBzdG9yZS5wdXNoKHsKICAgICAgIGRhdGE6IHsKICAgICAgICAgdHlwZTogJ3Bvc3QnLAogICAgICAgICBpZDogMSwKICAgICAgICAgcmVsYXRpb25zaGlwczogewogICAgICAgICAgIGNvbW1lbnRzOiB7CiAgICAgICAgICAgICBkYXRhOiBbeyB0eXBlOiAnY29tbWVudCcsIGlkOiAxIH1dCiAgICAgICAgICAgfQogICAgICAgICB9CiAgICAgICB9CiAgICAgfSk7CiAgICAgIGxldCBjb21tZW50c1JlZiA9IHBvc3QuaGFzTWFueSgnY29tbWVudHMnKTsKICAgICAgLy8gZ2V0IHRoZSBpZGVudGlmaWVyIG9mIHRoZSByZWZlcmVuY2UKICAgICBpZiAoY29tbWVudHNSZWYucmVtb3RlVHlwZSgpID09PSAiaWRzIikgewogICAgICAgbGV0IGlkcyA9IGNvbW1lbnRzUmVmLmlkcygpOwogICAgIH0gZWxzZSBpZiAoY29tbWVudHNSZWYucmVtb3RlVHlwZSgpID09PSAibGluayIpIHsKICAgICAgIGxldCBsaW5rID0gY29tbWVudHNSZWYubGluaygpOwogICAgIH0KICAgICBgYGAKICAgICAgQG1ldGhvZCByZW1vdGVUeXBlCiAgICAgQHJldHVybiB7U3RyaW5nfSBUaGUgbmFtZSBvZiB0aGUgcmVtb3RlIHR5cGUuIFRoaXMgc2hvdWxkIGVpdGhlciBiZSBgbGlua2Agb3IgYGlkc2AKICAgICAqLwogICAgOwoKICAgIF9wcm90by5yZW1vdGVUeXBlID0gZnVuY3Rpb24gcmVtb3RlVHlwZSgpIHsKICAgICAgdmFyIHZhbHVlID0gdGhpcy5fcmVzb3VyY2UoKTsKCiAgICAgIGlmICh2YWx1ZSAmJiB2YWx1ZS5saW5rcyAmJiB2YWx1ZS5saW5rcy5yZWxhdGVkKSB7CiAgICAgICAgcmV0dXJuICdsaW5rJzsKICAgICAgfQoKICAgICAgcmV0dXJuICdpZHMnOwogICAgfQogICAgLyoqCiAgICAgYGlkcygpYCByZXR1cm5zIGFuIGFycmF5IG9mIHRoZSByZWNvcmQgSURzIGluIHRoaXMgcmVsYXRpb25zaGlwLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICBjb21tZW50czogaGFzTWFueSh7IGFzeW5jOiB0cnVlIH0pCiAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcG9zdCA9IHN0b3JlLnB1c2goewogICAgICAgZGF0YTogewogICAgICAgICB0eXBlOiAncG9zdCcsCiAgICAgICAgIGlkOiAxLAogICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgY29tbWVudHM6IHsKICAgICAgICAgICAgIGRhdGE6IFt7IHR5cGU6ICdjb21tZW50JywgaWQ6IDEgfV0KICAgICAgICAgICB9CiAgICAgICAgIH0KICAgICAgIH0KICAgICB9KTsKICAgICAgbGV0IGNvbW1lbnRzUmVmID0gcG9zdC5oYXNNYW55KCdjb21tZW50cycpOwogICAgICBjb21tZW50c1JlZi5pZHMoKTsgLy8gWycxJ10KICAgICBgYGAKICAgICAgQG1ldGhvZCBpZHMKICAgICBAcmV0dXJuIHtBcnJheX0gVGhlIGlkcyBpbiB0aGlzIGhhcy1tYW55IHJlbGF0aW9uc2hpcAogICAgICovCiAgICA7CgogICAgX3Byb3RvLmlkcyA9IGZ1bmN0aW9uIGlkcygpIHsKICAgICAgdmFyIHJlc291cmNlID0gdGhpcy5fcmVzb3VyY2UoKTsKCiAgICAgIHZhciBpZHMgPSBbXTsKCiAgICAgIGlmIChyZXNvdXJjZS5kYXRhKSB7CiAgICAgICAgaWRzID0gcmVzb3VyY2UuZGF0YS5tYXAoZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgICAgIHJldHVybiBkYXRhLmlkOwogICAgICAgIH0pOwogICAgICB9CgogICAgICByZXR1cm4gaWRzOwogICAgfQogICAgLyoqCiAgICAgYHB1c2hgIGNhbiBiZSB1c2VkIHRvIHVwZGF0ZSB0aGUgZGF0YSBpbiB0aGUgcmVsYXRpb25zaGlwIGFuZCBFbWJlcgogICAgIERhdGEgd2lsbCB0cmVhdCB0aGUgbmV3IGRhdGEgYXMgdGhlIGNhbm9uaWNhbCB2YWx1ZSBvZiB0aGlzCiAgICAgcmVsYXRpb25zaGlwIG9uIHRoZSBiYWNrZW5kLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICBjb21tZW50czogaGFzTWFueSh7IGFzeW5jOiB0cnVlIH0pCiAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYAogICAgIGxldCBwb3N0ID0gc3RvcmUucHVzaCh7CiAgICAgICBkYXRhOiB7CiAgICAgICAgIHR5cGU6ICdwb3N0JywKICAgICAgICAgaWQ6IDEsCiAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICBjb21tZW50czogewogICAgICAgICAgICAgZGF0YTogW3sgdHlwZTogJ2NvbW1lbnQnLCBpZDogMSB9XQogICAgICAgICAgIH0KICAgICAgICAgfQogICAgICAgfQogICAgIH0pOwogICAgICBsZXQgY29tbWVudHNSZWYgPSBwb3N0Lmhhc01hbnkoJ2NvbW1lbnRzJyk7CiAgICAgIGNvbW1lbnRzUmVmLmlkcygpOyAvLyBbJzEnXQogICAgICBjb21tZW50c1JlZi5wdXNoKFsKICAgICBbeyB0eXBlOiAnY29tbWVudCcsIGlkOiAyIH1dLAogICAgIFt7IHR5cGU6ICdjb21tZW50JywgaWQ6IDMgfV0sCiAgICAgXSkKICAgICAgY29tbWVudHNSZWYuaWRzKCk7IC8vIFsnMicsICczJ10KICAgICBgYGAKICAgICAgQG1ldGhvZCBwdXNoCiAgICAgQHBhcmFtIHtBcnJheXxQcm9taXNlfSBvYmplY3RPclByb21pc2UgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBKU09OQVBJIGRvY3VtZW50IG9iamVjdCBkZXNjcmliaW5nIHRoZSBuZXcgdmFsdWUgb2YgdGhpcyByZWxhdGlvbnNoaXAuCiAgICAgQHJldHVybiB7TWFueUFycmF5fQogICAgICovCiAgICA7CgogICAgX3Byb3RvLnB1c2ggPSBmdW5jdGlvbiBwdXNoKG9iamVjdE9yUHJvbWlzZSkgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKCiAgICAgIHJldHVybiBFbWJlci5SU1ZQLnJlc29sdmUob2JqZWN0T3JQcm9taXNlKS50aGVuKGZ1bmN0aW9uIChwYXlsb2FkKSB7CiAgICAgICAgdmFyIGFycmF5ID0gcGF5bG9hZDsKCiAgICAgICAgaWYgKHR5cGVvZiBwYXlsb2FkID09PSAnb2JqZWN0JyAmJiBwYXlsb2FkLmRhdGEpIHsKICAgICAgICAgIGFycmF5ID0gcGF5bG9hZC5kYXRhOwogICAgICAgIH0KCiAgICAgICAgdmFyIGludGVybmFsTW9kZWxzID0gYXJyYXkubWFwKGZ1bmN0aW9uIChvYmopIHsKICAgICAgICAgIHZhciByZWNvcmQgPSBfdGhpczIuc3RvcmUucHVzaChvYmopOwoKICAgICAgICAgIHJldHVybiByZWNvcmREYXRhRm9yKHJlY29yZCk7CiAgICAgICAgfSk7CgogICAgICAgIF90aGlzMi5oYXNNYW55UmVsYXRpb25zaGlwLmNvbXB1dGVDaGFuZ2VzKGludGVybmFsTW9kZWxzKTsKCiAgICAgICAgcmV0dXJuIF90aGlzMi5pbnRlcm5hbE1vZGVsLmdldEhhc01hbnkoX3RoaXMyLmhhc01hbnlSZWxhdGlvbnNoaXAua2V5KTsgLy8gVE9ETyBJR09SIGl0IHNlZW1zIHdyb25nIHRoYXQgd2Ugd2VyZSByZXR1cm5pbmcgdGhlIG1hbnkgYXJyYXkgaGVyZQogICAgICAgIC8vcmV0dXJuIHRoaXMuaGFzTWFueVJlbGF0aW9uc2hpcC5tYW55QXJyYXk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8uX2lzTG9hZGVkID0gZnVuY3Rpb24gX2lzTG9hZGVkKCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHZhciBoYXNSZWxhdGlvbnNoaXBEYXRhUHJvcGVydHkgPSBFbWJlci5nZXQodGhpcy5oYXNNYW55UmVsYXRpb25zaGlwLCAnaGFzQW55UmVsYXRpb25zaGlwRGF0YScpOwoKICAgICAgaWYgKCFoYXNSZWxhdGlvbnNoaXBEYXRhUHJvcGVydHkpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIHZhciBtZW1iZXJzID0gdGhpcy5oYXNNYW55UmVsYXRpb25zaGlwLm1lbWJlcnMudG9BcnJheSgpOyAvL1RPRE8gSWdvciBjbGVhbnVwCgogICAgICByZXR1cm4gbWVtYmVycy5ldmVyeShmdW5jdGlvbiAocmVjb3JkRGF0YSkgewogICAgICAgIHZhciBzdG9yZSA9IF90aGlzMy5wYXJlbnRJbnRlcm5hbE1vZGVsLnN0b3JlOwoKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IHN0b3JlLl9pbnRlcm5hbE1vZGVsRm9yUmVzb3VyY2UocmVjb3JkRGF0YS5nZXRSZXNvdXJjZUlkZW50aWZpZXIoKSk7CgogICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLmlzTG9hZGVkKCkgPT09IHRydWU7CiAgICAgIH0pOwogICAgfQogICAgLyoqCiAgICAgYHZhbHVlKClgIHN5bmNocm9ub3VzbHkgcmV0dXJucyB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgaGFzLW1hbnkKICAgICByZWxhdGlvbnNoaXAuIFVubGlrZSBgcmVjb3JkLmdldCgncmVsYXRpb25zaGlwTmFtZScpYCwgY2FsbGluZwogICAgIGB2YWx1ZSgpYCBvbiBhIHJlZmVyZW5jZSBkb2VzIG5vdCB0cmlnZ2VyIGEgZmV0Y2ggaWYgdGhlIGFzeW5jCiAgICAgcmVsYXRpb25zaGlwIGlzIG5vdCB5ZXQgbG9hZGVkLiBJZiB0aGUgcmVsYXRpb25zaGlwIGlzIG5vdCBsb2FkZWQKICAgICBpdCB3aWxsIGFsd2F5cyByZXR1cm4gYG51bGxgLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGFwcC9tb2RlbHMvcG9zdC5qcwogICAgIGltcG9ydCBNb2RlbCwgeyBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgIGV4cG9ydCBkZWZhdWx0IE1vZGVsLmV4dGVuZCh7CiAgICAgICBjb21tZW50czogaGFzTWFueSh7IGFzeW5jOiB0cnVlIH0pCiAgICAgfSk7CiAgICAgYGBgCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBsZXQgcG9zdCA9IHN0b3JlLnB1c2goewogICAgICAgZGF0YTogewogICAgICAgICB0eXBlOiAncG9zdCcsCiAgICAgICAgIGlkOiAxLAogICAgICAgICByZWxhdGlvbnNoaXBzOiB7CiAgICAgICAgICAgY29tbWVudHM6IHsKICAgICAgICAgICAgIGRhdGE6IFt7IHR5cGU6ICdjb21tZW50JywgaWQ6IDEgfV0KICAgICAgICAgICB9CiAgICAgICAgIH0KICAgICAgIH0KICAgICB9KTsKICAgICAgbGV0IGNvbW1lbnRzUmVmID0gcG9zdC5oYXNNYW55KCdjb21tZW50cycpOwogICAgICBwb3N0LmdldCgnY29tbWVudHMnKS50aGVuKGZ1bmN0aW9uKGNvbW1lbnRzKSB7CiAgICAgICBjb21tZW50c1JlZi52YWx1ZSgpID09PSBjb21tZW50cwogICAgIH0pCiAgICAgYGBgCiAgICAgIEBtZXRob2QgdmFsdWUKICAgICBAcmV0dXJuIHtNYW55QXJyYXl9CiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8udmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHsKICAgICAgaWYgKHRoaXMuX2lzTG9hZGVkKCkpIHsKICAgICAgICByZXR1cm4gdGhpcy5pbnRlcm5hbE1vZGVsLmdldE1hbnlBcnJheSh0aGlzLmtleSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgLyoqCiAgICAgTG9hZHMgdGhlIHJlbGF0aW9uc2hpcCBpZiBpdCBpcyBub3QgYWxyZWFkeSBsb2FkZWQuICBJZiB0aGUKICAgICByZWxhdGlvbnNoaXAgaXMgYWxyZWFkeSBsb2FkZWQgdGhpcyBtZXRob2QgZG9lcyBub3QgdHJpZ2dlciBhIG5ldwogICAgIGxvYWQuIFRoaXMgY2F1c2VzIGEgcmVxdWVzdCB0byB0aGUgc3BlY2lmaWVkCiAgICAgcmVsYXRpb25zaGlwIGxpbmsgb3IgcmVsb2FkcyBhbGwgaXRlbXMgY3VycmVudGx5IGluIHRoZSByZWxhdGlvbnNoaXAuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgYXBwL21vZGVscy9wb3N0LmpzCiAgICAgaW1wb3J0IE1vZGVsLCB7IGhhc01hbnkgfSBmcm9tICdAZW1iZXItZGF0YS9tb2RlbCc7CiAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgIGNvbW1lbnRzOiBoYXNNYW55KHsgYXN5bmM6IHRydWUgfSkKICAgICB9KTsKICAgICBgYGAKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGxldCBwb3N0ID0gc3RvcmUucHVzaCh7CiAgICAgICBkYXRhOiB7CiAgICAgICAgIHR5cGU6ICdwb3N0JywKICAgICAgICAgaWQ6IDEsCiAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICBjb21tZW50czogewogICAgICAgICAgICAgZGF0YTogW3sgdHlwZTogJ2NvbW1lbnQnLCBpZDogMSB9XQogICAgICAgICAgIH0KICAgICAgICAgfQogICAgICAgfQogICAgIH0pOwogICAgICBsZXQgY29tbWVudHNSZWYgPSBwb3N0Lmhhc01hbnkoJ2NvbW1lbnRzJyk7CiAgICAgIGNvbW1lbnRzUmVmLmxvYWQoKS50aGVuKGZ1bmN0aW9uKGNvbW1lbnRzKSB7CiAgICAgICAvLy4uLgogICAgIH0pOwogICAgIGBgYAogICAgICBZb3UgbWF5IGFsc28gcGFzcyBpbiBhbiBvcHRpb25zIG9iamVjdCB3aG9zZSBwcm9wZXJ0aWVzIHdpbGwgYmUKICAgICBmZWQgZm9yd2FyZC4gVGhpcyBlbmFibGVzIHlvdSB0byBwYXNzIGBhZGFwdGVyT3B0aW9uc2AgaW50byB0aGUKICAgICByZXF1ZXN0IGdpdmVuIHRvIHRoZSBhZGFwdGVyIHZpYSB0aGUgcmVmZXJlbmNlLgogICAgICBFeGFtcGxlCiAgICAgIGBgYGphdmFzY3JpcHQKICAgICBjb21tZW50c1JlZi5sb2FkKHsgYWRhcHRlck9wdGlvbnM6IHsgaXNQcml2YXRlOiB0cnVlIH0gfSkKICAgICAgIC50aGVuKGZ1bmN0aW9uKGNvbW1lbnRzKSB7CiAgICAgICAgIC8vLi4uCiAgICAgICB9KTsKICAgICBgYGAKICAgICAgYGBgYXBwL2FkYXB0ZXJzL2NvbW1lbnQuanMKICAgICBleHBvcnQgZGVmYXVsdCBBcHBsaWNhdGlvbkFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgIGZpbmRNYW55KHN0b3JlLCB0eXBlLCBpZCwgc25hcHNob3RzKSB7CiAgICAgICAgIC8vIEluIHRoZSBhZGFwdGVyIHlvdSB3aWxsIGhhdmUgYWNjZXNzIHRvIGFkYXB0ZXJPcHRpb25zLgogICAgICAgICBsZXQgYWRhcHRlck9wdGlvbnMgPSBzbmFwc2hvdHNbMF0uYWRhcHRlck9wdGlvbnM7CiAgICAgICB9CiAgICAgfSk7CiAgICAgYGBgCiAgICAgIEBtZXRob2QgbG9hZAogICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIHRoZSBvcHRpb25zIHRvIHBhc3MgaW4uCiAgICAgQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgTWFueUFycmF5IGluCiAgICAgdGhpcyBoYXMtbWFueSByZWxhdGlvbnNoaXAuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ubG9hZCA9IGZ1bmN0aW9uIGxvYWQob3B0aW9ucykgewogICAgICByZXR1cm4gdGhpcy5pbnRlcm5hbE1vZGVsLmdldEhhc01hbnkodGhpcy5rZXksIG9wdGlvbnMpOwogICAgfQogICAgLyoqCiAgICAgUmVsb2FkcyB0aGlzIGhhcy1tYW55IHJlbGF0aW9uc2hpcC4gVGhpcyBjYXVzZXMgYSByZXF1ZXN0IHRvIHRoZSBzcGVjaWZpZWQKICAgICByZWxhdGlvbnNoaXAgbGluayBvciByZWxvYWRzIGFsbCBpdGVtcyBjdXJyZW50bHkgaW4gdGhlIHJlbGF0aW9uc2hpcC4KICAgICAgRXhhbXBsZQogICAgICBgYGBhcHAvbW9kZWxzL3Bvc3QuanMKICAgICBpbXBvcnQgTW9kZWwsIHsgaGFzTWFueSB9IGZyb20gJ0BlbWJlci1kYXRhL21vZGVsJzsKICAgICBleHBvcnQgZGVmYXVsdCBNb2RlbC5leHRlbmQoewogICAgICAgY29tbWVudHM6IGhhc01hbnkoeyBhc3luYzogdHJ1ZSB9KQogICAgIH0pOwogICAgIGBgYAogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgbGV0IHBvc3QgPSBzdG9yZS5wdXNoKHsKICAgICAgIGRhdGE6IHsKICAgICAgICAgdHlwZTogJ3Bvc3QnLAogICAgICAgICBpZDogMSwKICAgICAgICAgcmVsYXRpb25zaGlwczogewogICAgICAgICAgIGNvbW1lbnRzOiB7CiAgICAgICAgICAgICBkYXRhOiBbeyB0eXBlOiAnY29tbWVudCcsIGlkOiAxIH1dCiAgICAgICAgICAgfQogICAgICAgICB9CiAgICAgICB9CiAgICAgfSk7CiAgICAgIGxldCBjb21tZW50c1JlZiA9IHBvc3QuaGFzTWFueSgnY29tbWVudHMnKTsKICAgICAgY29tbWVudHNSZWYucmVsb2FkKCkudGhlbihmdW5jdGlvbihjb21tZW50cykgewogICAgICAgLy8uLi4KICAgICB9KTsKICAgICBgYGAKICAgICAgWW91IG1heSBhbHNvIHBhc3MgaW4gYW4gb3B0aW9ucyBvYmplY3Qgd2hvc2UgcHJvcGVydGllcyB3aWxsIGJlCiAgICAgZmVkIGZvcndhcmQuIFRoaXMgZW5hYmxlcyB5b3UgdG8gcGFzcyBgYWRhcHRlck9wdGlvbnNgIGludG8gdGhlCiAgICAgcmVxdWVzdCBnaXZlbiB0byB0aGUgYWRhcHRlciB2aWEgdGhlIHJlZmVyZW5jZS4gQSBmdWxsIGV4YW1wbGUKICAgICBjYW4gYmUgZm91bmQgaW4gdGhlIGBsb2FkYCBtZXRob2QuCiAgICAgIEV4YW1wbGUKICAgICAgYGBgamF2YXNjcmlwdAogICAgIGNvbW1lbnRzUmVmLnJlbG9hZCh7IGFkYXB0ZXJPcHRpb25zOiB7IGlzUHJpdmF0ZTogdHJ1ZSB9IH0pCiAgICAgYGBgCiAgICAgIEBtZXRob2QgcmVsb2FkCiAgICAgQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgdGhlIG9wdGlvbnMgdG8gcGFzcyBpbi4KICAgICBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBNYW55QXJyYXkgaW4gdGhpcyBoYXMtbWFueSByZWxhdGlvbnNoaXAuCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVsb2FkID0gZnVuY3Rpb24gcmVsb2FkKG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxNb2RlbC5yZWxvYWRIYXNNYW55KHRoaXMua2V5LCBvcHRpb25zKTsKICAgIH07CgogICAgcmV0dXJuIEhhc01hbnlSZWZlcmVuY2U7CiAgfShSZWZlcmVuY2UpOwoKICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyQzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyQzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMkMyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIC8vIG9uY2UgdGhlIHByZXNlbnRhdGlvbiBsb2dpYyBpcyBtb3ZlZCBpbnRvIHRoZSBNb2RlbCBwYWNrYWdlIHdlIGNhbiBtYWtlCiAgLy8gZWxpbWluYXRlIHRoZXNlIGxvc3N5IGFuZCByZWR1bmRhbnQgaGVscGVycwogIGZ1bmN0aW9uIHJlbGF0aW9uc2hpcHNGb3IkMShpbnN0YW5jZSkgewogICAgdmFyIHJlY29yZERhdGEgPSByZWNvcmREYXRhRm9yKGluc3RhbmNlKTsKICAgIHJldHVybiByZWNvcmREYXRhLl9yZWxhdGlvbnNoaXBzOwogIH0KCiAgZnVuY3Rpb24gcmVsYXRpb25zaGlwU3RhdGVGb3IkMShpbnN0YW5jZSwgcHJvcGVydHlOYW1lKSB7CiAgICByZXR1cm4gcmVsYXRpb25zaGlwc0ZvciQxKGluc3RhbmNlKS5nZXQocHJvcGVydHlOYW1lKTsKICB9CgogIHZhciBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7CiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KICAvLyBtb3ZlIHRvIFRTIGhhY2tzIG1vZHVsZSB0aGF0IHdlIGNhbiBkZWxldGUgd2hlbiB0aGlzIGlzIG5vIGxvbmdlciBhIG5lY2Vzc2FyeSByZWNhc3QKCiAgLy8gVE9ETyB0aGlzIHNob3VsZCBiZSBpbnRlZ3JhdGVkIHdpdGggdGhlIGNvZGUgcmVtb3ZhbCBzbyB3ZSBjYW4gdXNlIGl0IHRvZ2V0aGVyIHdpdGggdGhlIGlmIGNvbmRpdGlvbgogIC8vIGFuZCBub3QgYWxvbmdzaWRlIGl0CiAgZnVuY3Rpb24gaXNOb3RDdXN0b21Nb2RlbENsYXNzKHN0b3JlKSB7CiAgICByZXR1cm4gIWNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUzsKICB9CgogIC8qCiAgICBUaGUgVHJhbnNpdGlvbkNoYWluTWFwIGNhY2hlcyB0aGUgYHN0YXRlLmVudGVyc2AsIGBzdGF0ZS5zZXR1cHNgLCBhbmQgZmluYWwgc3RhdGUgcmVhY2hlZAogICAgd2hlbiB0cmFuc2l0aW9uaW5nIGZyb20gb25lIHN0YXRlIHRvIGFub3RoZXIsIHNvIHRoYXQgZnV0dXJlIHRyYW5zaXRpb25zIGNhbiByZXBsYXkgdGhlCiAgICB0cmFuc2l0aW9uIHdpdGhvdXQgbmVlZGluZyB0byB3YWxrIHRoZSBzdGF0ZSB0cmVlLCBjb2xsZWN0IHRoZXNlIGhvb2sgY2FsbHMgYW5kIGRldGVybWluZQogICAgIHRoZSBzdGF0ZSB0byB0cmFuc2l0aW9uIGludG8uCgogICAgIEEgZnV0dXJlIG9wdGltaXphdGlvbiB3b3VsZCBiZSB0byBidWlsZCBhIHNpbmdsZSBjaGFpbmVkIG1ldGhvZCBvdXQgb2YgdGhlIGNvbGxlY3RlZCBlbnRlcnMKICAgICBhbmQgc2V0dXBzLiBJdCBtYXkgYWxzbyBiZSBmYXN0ZXIgdG8gZG8gYSB0d28gbGV2ZWwgY2FjaGUgKGZyb206IHsgdG8gfSkgaW5zdGVhZCBvZiBjYWNoaW5nIGJhc2VkCiAgICAgb24gYSBrZXkgdGhhdCBhZGRzIHRoZSB0d28gdG9nZXRoZXIuCiAgICovCiAgdmFyIFRyYW5zaXRpb25DaGFpbk1hcCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CgogIHZhciBfZXh0cmFjdFBpdm90TmFtZUNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKCiAgdmFyIF9zcGxpdE9uRG90Q2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwoKICBmdW5jdGlvbiBzcGxpdE9uRG90KG5hbWUpIHsKICAgIHJldHVybiBfc3BsaXRPbkRvdENhY2hlW25hbWVdIHx8IChfc3BsaXRPbkRvdENhY2hlW25hbWVdID0gbmFtZS5zcGxpdCgnLicpKTsKICB9CgogIGZ1bmN0aW9uIGV4dHJhY3RQaXZvdE5hbWUobmFtZSkgewogICAgcmV0dXJuIF9leHRyYWN0UGl2b3ROYW1lQ2FjaGVbbmFtZV0gfHwgKF9leHRyYWN0UGl2b3ROYW1lQ2FjaGVbbmFtZV0gPSBzcGxpdE9uRG90KG5hbWUpWzBdKTsKICB9CiAgLyoKICAgIGBJbnRlcm5hbE1vZGVsYCBpcyB0aGUgTW9kZWwgY2xhc3MgdGhhdCB3ZSB1c2UgaW50ZXJuYWxseSBpbnNpZGUgRW1iZXIgRGF0YSB0byByZXByZXNlbnQgbW9kZWxzLgogICAgSW50ZXJuYWwgRUQgbWV0aG9kcyBzaG91bGQgb25seSBkZWFsIHdpdGggYEludGVybmFsTW9kZWxgIG9iamVjdHMuIEl0IGlzIGEgZmFzdCwgcGxhaW4gSmF2YXNjcmlwdCBjbGFzcy4KCiAgICBXZSBleHBvc2UgYE1vZGVsYCB0byBhcHBsaWNhdGlvbiBjb2RlLCBieSBtYXRlcmlhbGl6aW5nIGEgYE1vZGVsYCBmcm9tIGBJbnRlcm5hbE1vZGVsYCBsYXppbHksIGFzCiAgICBhIHBlcmZvcm1hbmNlIG9wdGltaXphdGlvbi4KCiAgICBgSW50ZXJuYWxNb2RlbGAgc2hvdWxkIG5ldmVyIGJlIGV4cG9zZWQgdG8gYXBwbGljYXRpb24gY29kZS4gQXQgdGhlIGJvdW5kYXJpZXMgb2YgdGhlIHN5c3RlbSwgaW4gcGxhY2VzCiAgICBsaWtlIGBmaW5kYCwgYHB1c2hgLCBldGMuIHdlIGNvbnZlcnQgYmV0d2VlbiBNb2RlbHMgYW5kIEludGVybmFsTW9kZWxzLgoKICAgIFdlIG5lZWQgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIHByb3BlcnRpZXMgZnJvbSBgSW50ZXJuYWxNb2RlbGAgYXJlIGNvcnJlY3RseSBleHBvc2VkL3Byb3hpZWQgb24gYE1vZGVsYAogICAgaWYgdGhleSBhcmUgbmVlZGVkLgoKICAgIEBwcml2YXRlCiAgICBAY2xhc3MgSW50ZXJuYWxNb2RlbAogICovCgoKICB2YXIgSW50ZXJuYWxNb2RlbCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIC8vIE5vdCB0eXBlZCB5ZXQKICAgIC8vIFRoZSBwcmV2aW91cyBNYW55QXJyYXlzIGZvciB0aGlzIHJlbGF0aW9uc2hpcCB3aGljaCB3aWxsIGJlIGRlc3Ryb3llZCB3aGVuCiAgICAvLyB3ZSBjcmVhdGUgYSBuZXcgTWFueUFycmF5LCBidXQgaW4gdGhlIGludGVyaW0gdGhlIHJldGFpbmVkIHZlcnNpb24gd2lsbCBiZQogICAgLy8gdXBkYXRlZCBpZiBpbnZlcnNlIGludGVybmFsIG1vZGVscyBhcmUgdW5sb2FkZWQuCiAgICBmdW5jdGlvbiBJbnRlcm5hbE1vZGVsKHN0b3JlLCBpZGVudGlmaWVyKSB7CiAgICAgIHRoaXMuc3RvcmUgPSBzdG9yZTsKICAgICAgdGhpcy5pZGVudGlmaWVyID0gaWRlbnRpZmllcjsKICAgICAgdGhpcy5faWQgPSB2b2lkIDA7CiAgICAgIHRoaXMubW9kZWxOYW1lID0gdm9pZCAwOwogICAgICB0aGlzLmNsaWVudElkID0gdm9pZCAwOwogICAgICB0aGlzLl9fcmVjb3JkRGF0YSA9IHZvaWQgMDsKICAgICAgdGhpcy5faXNEZXN0cm95ZWQgPSB2b2lkIDA7CiAgICAgIHRoaXMuaXNFcnJvciA9IHZvaWQgMDsKICAgICAgdGhpcy5fcGVuZGluZ1JlY29yZEFycmF5TWFuYWdlckZsdXNoID0gdm9pZCAwOwogICAgICB0aGlzLl9pc0RlbWF0ZXJpYWxpemluZyA9IHZvaWQgMDsKICAgICAgdGhpcy5pc1JlbG9hZGluZyA9IHZvaWQgMDsKICAgICAgdGhpcy5fZG9Ob3REZXN0cm95ID0gdm9pZCAwOwogICAgICB0aGlzLmlzRGVzdHJveWluZyA9IHZvaWQgMDsKICAgICAgdGhpcy5fcHJvbWlzZVByb3h5ID0gdm9pZCAwOwogICAgICB0aGlzLl9yZWNvcmQgPSB2b2lkIDA7CiAgICAgIHRoaXMuX3NjaGVkdWxlZERlc3Ryb3kgPSB2b2lkIDA7CiAgICAgIHRoaXMuX21vZGVsQ2xhc3MgPSB2b2lkIDA7CiAgICAgIHRoaXMuX19kZWZlcnJlZFRyaWdnZXJzID0gdm9pZCAwOwogICAgICB0aGlzLl9fcmVjb3JkQXJyYXlzID0gdm9pZCAwOwogICAgICB0aGlzLl9yZWZlcmVuY2VzID0gdm9pZCAwOwogICAgICB0aGlzLl9yZWNvcmRSZWZlcmVuY2UgPSB2b2lkIDA7CiAgICAgIHRoaXMuX21hbnlBcnJheUNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGhpcy5fcmV0YWluZWRNYW55QXJyYXlDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHRoaXMuX3JlbGF0aW9uc2hpcFByb21pc2VzQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGhpcy5jdXJyZW50U3RhdGUgPSB2b2lkIDA7CiAgICAgIHRoaXMuZXJyb3IgPSB2b2lkIDA7CiAgICAgIHRoaXMuX2lkID0gaWRlbnRpZmllci5pZDsKICAgICAgdGhpcy5tb2RlbE5hbWUgPSBpZGVudGlmaWVyLnR5cGU7CiAgICAgIHRoaXMuY2xpZW50SWQgPSBpZGVudGlmaWVyLmxpZDsKICAgICAgdGhpcy5fX3JlY29yZERhdGEgPSBudWxsOyAvLyB0aGlzIGVuc3VyZSBvcmRlcmVkIHNldCBjYW4gcXVpY2tseSBpZGVudGlmeSB0aGlzIGFzIHVuaXF1ZQoKICAgICAgdGhpc1tFbWJlci5HVUlEX0tFWV0gPSBpZGVudGlmaWVyLmxpZDsKICAgICAgdGhpcy5fcHJvbWlzZVByb3h5ID0gbnVsbDsKICAgICAgdGhpcy5fcmVjb3JkID0gbnVsbDsKICAgICAgdGhpcy5faXNEZXN0cm95ZWQgPSBmYWxzZTsKICAgICAgdGhpcy5pc0Vycm9yID0gZmFsc2U7CiAgICAgIHRoaXMuX3BlbmRpbmdSZWNvcmRBcnJheU1hbmFnZXJGbHVzaCA9IGZhbHNlOyAvLyB1c2VkIGJ5IHRoZSByZWNvcmRBcnJheU1hbmFnZXIKICAgICAgLy8gRHVyaW5nIGRlbWF0ZXJpYWxpemF0aW9uIHdlIGRvbid0IHdhbnQgdG8gcmVtYXRlcmlhbGl6ZSB0aGUgcmVjb3JkLiAgVGhlCiAgICAgIC8vIHJlYXNvbiB0aGlzIG1pZ2h0IGhhcHBlbiBpcyB0aGF0IGRlbWF0ZXJpYWxpemF0aW9uIHJlbW92ZXMgcmVjb3JkcyBmcm9tCiAgICAgIC8vIHJlY29yZCBhcnJheXMsICBhbmQgRW1iZXIgYXJyYXlzIHdpbGwgYWx3YXlzIGBvYmplY3RBdCgwKWAgYW5kCiAgICAgIC8vIGBvYmplY3RBdChsZW4gLSAxKWAgdG8gdGVzdCB3aGV0aGVyIG9yIG5vdCBgZmlyc3RPYmplY3RgIG9yIGBsYXN0T2JqZWN0YAogICAgICAvLyBoYXZlIGNoYW5nZWQuCgogICAgICB0aGlzLl9pc0RlbWF0ZXJpYWxpemluZyA9IGZhbHNlOwogICAgICB0aGlzLl9zY2hlZHVsZWREZXN0cm95ID0gbnVsbDsKICAgICAgdGhpcy5yZXNldFJlY29yZCgpOyAvLyBjYWNoZXMgZm9yIGxhenkgZ2V0dGVycwoKICAgICAgdGhpcy5fbW9kZWxDbGFzcyA9IG51bGw7CiAgICAgIHRoaXMuX19kZWZlcnJlZFRyaWdnZXJzID0gbnVsbDsKICAgICAgdGhpcy5fX3JlY29yZEFycmF5cyA9IG51bGw7CiAgICAgIHRoaXMuX3JlZmVyZW5jZXMgPSBudWxsOwogICAgICB0aGlzLl9yZWNvcmRSZWZlcmVuY2UgPSBudWxsOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBJbnRlcm5hbE1vZGVsLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uaXNIaWRkZW5Gcm9tUmVjb3JkQXJyYXlzID0gZnVuY3Rpb24gaXNIaWRkZW5Gcm9tUmVjb3JkQXJyYXlzKCkgewogICAgICAvLyBEdXJpbmcgZGVtYXRlcmlhbGl6YXRpb24gd2UgZG9uJ3Qgd2FudCB0byByZW1hdGVyaWFsaXplIHRoZSByZWNvcmQuCiAgICAgIC8vIHJlY29yZFdhc0RlbGV0ZWQgY2FuIGNhdXNlIG90aGVyIHJlY29yZHMgdG8gcmVtYXRlcmlhbGl6ZSBiZWNhdXNlIGl0CiAgICAgIC8vIHJlbW92ZXMgdGhlIGludGVybmFsIG1vZGVsIGZyb20gdGhlIGFycmF5IGFuZCBFbWJlciBhcnJheXMgd2lsbCBhbHdheXMKICAgICAgLy8gYG9iamVjdEF0KDApYCBhbmQgYG9iamVjdEF0KGxlbiAtMSlgIHRvIGNoZWNrIHdoZXRoZXIgYGZpcnN0T2JqZWN0YCBvcgogICAgICAvLyBgbGFzdE9iamVjdGAgaGF2ZSBjaGFuZ2VkLiAgV2hlbiB0aGlzIGhhcHBlbnMgd2UgZG9uJ3Qgd2FudCB0aG9zZQogICAgICAvLyBtb2RlbHMgdG8gcmVtYXRlcmlhbGl6ZSB0aGVpciByZWNvcmRzLgogICAgICAvLyBlYWdlciBjaGVja3MgdG8gYXZvaWQgaW5zdGFudGlhdGluZyByZWNvcmQgZGF0YSBpZiB3ZSBhcmUgZW1wdHkgb3IgbG9hZGluZwogICAgICBpZiAodGhpcy5pc0VtcHR5KCkpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQoKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX1NUQVRFKSB7CiAgICAgICAgaWYgKHRoaXMuaXNMb2FkaW5nKCkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHZhciBpc1JlY29yZEZ1bGx5RGVsZXRlZDsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9TVEFURSkgewogICAgICAgIGlzUmVjb3JkRnVsbHlEZWxldGVkID0gdGhpcy5faXNSZWNvcmRGdWxseURlbGV0ZWQoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpc1JlY29yZEZ1bGx5RGVsZXRlZCA9IHRoaXMuY3VycmVudFN0YXRlLnN0YXRlTmFtZSA9PT0gJ3Jvb3QuZGVsZXRlZC5zYXZlZCc7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLl9pc0RlbWF0ZXJpYWxpemluZyB8fCB0aGlzLmhhc1NjaGVkdWxlZERlc3Ryb3koKSB8fCB0aGlzLmlzRGVzdHJveWVkIHx8IGlzUmVjb3JkRnVsbHlEZWxldGVkOwogICAgfTsKCiAgICBfcHJvdG8uX2lzUmVjb3JkRnVsbHlEZWxldGVkID0gZnVuY3Rpb24gX2lzUmVjb3JkRnVsbHlEZWxldGVkKCkgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfU1RBVEUpIHsKICAgICAgICBpZiAodGhpcy5fcmVjb3JkRGF0YS5pc0RlbGV0aW9uQ29tbWl0dGVkICYmIHRoaXMuX3JlY29yZERhdGEuaXNEZWxldGlvbkNvbW1pdHRlZCgpKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX3JlY29yZERhdGEuaXNOZXcgJiYgdGhpcy5fcmVjb3JkRGF0YS5pc0RlbGV0ZWQgJiYgdGhpcy5fcmVjb3JkRGF0YS5pc05ldygpICYmIHRoaXMuX3JlY29yZERhdGEuaXNEZWxldGVkKCkpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50U3RhdGUuc3RhdGVOYW1lID09PSAncm9vdC5kZWxldGVkLnNhdmVkJzsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gYXNzZXJ0IGhlcmUKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmlzUmVjb3JkSW5Vc2UgPSBmdW5jdGlvbiBpc1JlY29yZEluVXNlKCkgewogICAgICB2YXIgcmVjb3JkID0gdGhpcy5fcmVjb3JkOwogICAgICByZXR1cm4gcmVjb3JkICYmICEocmVjb3JkLmdldCgnaXNEZXN0cm95ZWQnKSB8fCByZWNvcmQuZ2V0KCdpc0Rlc3Ryb3lpbmcnKSk7CiAgICB9OwoKICAgIF9wcm90by5pc0VtcHR5ID0gZnVuY3Rpb24gaXNFbXB0eSgpIHsKICAgICAgcmV0dXJuIHRoaXMuY3VycmVudFN0YXRlLmlzRW1wdHk7CiAgICB9OwoKICAgIF9wcm90by5pc0xvYWRpbmcgPSBmdW5jdGlvbiBpc0xvYWRpbmcoKSB7CiAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5pc0xvYWRpbmc7CiAgICB9OwoKICAgIF9wcm90by5pc0xvYWRlZCA9IGZ1bmN0aW9uIGlzTG9hZGVkKCkgewogICAgICByZXR1cm4gdGhpcy5jdXJyZW50U3RhdGUuaXNMb2FkZWQ7CiAgICB9OwoKICAgIF9wcm90by5oYXNEaXJ0eUF0dHJpYnV0ZXMgPSBmdW5jdGlvbiBoYXNEaXJ0eUF0dHJpYnV0ZXMoKSB7CiAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5oYXNEaXJ0eUF0dHJpYnV0ZXM7CiAgICB9OwoKICAgIF9wcm90by5pc1NhdmluZyA9IGZ1bmN0aW9uIGlzU2F2aW5nKCkgewogICAgICByZXR1cm4gdGhpcy5jdXJyZW50U3RhdGUuaXNTYXZpbmc7CiAgICB9OwoKICAgIF9wcm90by5pc0RlbGV0ZWQgPSBmdW5jdGlvbiBpc0RlbGV0ZWQoKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9TVEFURSkgewogICAgICAgIGlmICh0aGlzLl9yZWNvcmREYXRhLmlzRGVsZXRlZCkgewogICAgICAgICAgcmV0dXJuIHRoaXMuX3JlY29yZERhdGEuaXNEZWxldGVkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5pc0RlbGV0ZWQ7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5pc0RlbGV0ZWQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmlzTmV3ID0gZnVuY3Rpb24gaXNOZXcoKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9TVEFURSkgewogICAgICAgIGlmICh0aGlzLl9yZWNvcmREYXRhLmlzTmV3KSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fcmVjb3JkRGF0YS5pc05ldygpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50U3RhdGUuaXNOZXc7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTdGF0ZS5pc05ldzsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uaXNWYWxpZCA9IGZ1bmN0aW9uIGlzVmFsaWQoKSB7CiAgICAgIGlmICghY2FuYXJ5RmVhdHVyZXMuUkVDT1JEX0RBVEFfRVJST1JTKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudFN0YXRlLmlzVmFsaWQ7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmRpcnR5VHlwZSA9IGZ1bmN0aW9uIGRpcnR5VHlwZSgpIHsKICAgICAgcmV0dXJuIHRoaXMuY3VycmVudFN0YXRlLmRpcnR5VHlwZTsKICAgIH07CgogICAgX3Byb3RvLmdldFJlY29yZCA9IGZ1bmN0aW9uIGdldFJlY29yZChwcm9wZXJ0aWVzKSB7CiAgICAgIGlmICghdGhpcy5fcmVjb3JkICYmICF0aGlzLl9pc0RlbWF0ZXJpYWxpemluZykgewogICAgICAgIHZhciBfc3RvcmUgPSB0aGlzLnN0b3JlOwoKICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICB0aGlzLl9yZWNvcmQgPSBfc3RvcmUuX2luc3RhbnRpYXRlUmVjb3JkKHRoaXMsIHRoaXMubW9kZWxOYW1lLCB0aGlzLl9yZWNvcmREYXRhLCB0aGlzLmlkZW50aWZpZXIsIHByb3BlcnRpZXMpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoaXNOb3RDdXN0b21Nb2RlbENsYXNzKCkpIHsKICAgICAgICAgICAgLy8gbG9va3VwRmFjdG9yeSBzaG91bGQgcmVhbGx5IHJldHVybiBhbiBvYmplY3QgdGhhdCBjcmVhdGVzCiAgICAgICAgICAgIC8vIGluc3RhbmNlcyB3aXRoIHRoZSBpbmplY3Rpb25zIGFwcGxpZWQKICAgICAgICAgICAgdmFyIGNyZWF0ZU9wdGlvbnMgPSB7CiAgICAgICAgICAgICAgc3RvcmU6IF9zdG9yZSwKICAgICAgICAgICAgICBfaW50ZXJuYWxNb2RlbDogdGhpcywKICAgICAgICAgICAgICBjdXJyZW50U3RhdGU6IHRoaXMuY3VycmVudFN0YXRlCiAgICAgICAgICAgIH07CgogICAgICAgICAgICBpZiAoIWNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgICAgICAgICAgIGNyZWF0ZU9wdGlvbnMuaXNFcnJvciA9IHRoaXMuaXNFcnJvcjsKICAgICAgICAgICAgICBjcmVhdGVPcHRpb25zLmFkYXB0ZXJFcnJvciA9IHRoaXMuZXJyb3I7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzICE9PSB1bmRlZmluZWQpIHsKCiAgICAgICAgICAgICAgaWYgKCdpZCcgaW4gcHJvcGVydGllcykgewogICAgICAgICAgICAgICAgdmFyIGlkID0gY29lcmNlSWQocHJvcGVydGllcy5pZCk7CgogICAgICAgICAgICAgICAgaWYgKGlkICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIHRoaXMuc2V0SWQoaWQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0gLy8gY29udmVydCByZWxhdGlvbnNoaXAgUmVjb3JkcyB0byBSZWNvcmREYXRhcyBiZWZvcmUgcGFzc2luZyB0byBSZWNvcmREYXRhCgoKICAgICAgICAgICAgICB2YXIgZGVmcyA9IF9zdG9yZS5fcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IodGhpcy5tb2RlbE5hbWUpOwoKICAgICAgICAgICAgICBpZiAoZGVmcyAhPT0gbnVsbCkgewogICAgICAgICAgICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKTsKICAgICAgICAgICAgICAgIHZhciByZWxhdGlvbnNoaXBWYWx1ZTsKCiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgICAgdmFyIHByb3AgPSBrZXlzW2ldOwogICAgICAgICAgICAgICAgICB2YXIgZGVmID0gZGVmc1twcm9wXTsKCiAgICAgICAgICAgICAgICAgIGlmIChkZWYgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgICAgIGlmIChkZWYua2luZCA9PT0gJ2hhc01hbnknKSB7CgogICAgICAgICAgICAgICAgICAgICAgcmVsYXRpb25zaGlwVmFsdWUgPSBleHRyYWN0UmVjb3JkRGF0YXNGcm9tUmVjb3Jkcyhwcm9wZXJ0aWVzW3Byb3BdKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgcmVsYXRpb25zaGlwVmFsdWUgPSBleHRyYWN0UmVjb3JkRGF0YUZyb21SZWNvcmQocHJvcGVydGllc1twcm9wXSk7CiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzW3Byb3BdID0gcmVsYXRpb25zaGlwVmFsdWU7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHZhciBhZGRpdGlvbmFsQ3JlYXRlT3B0aW9ucyA9IHRoaXMuX3JlY29yZERhdGEuX2luaXRSZWNvcmRDcmVhdGVPcHRpb25zKHByb3BlcnRpZXMpOwoKICAgICAgICAgICAgRW1iZXIuYXNzaWduKGNyZWF0ZU9wdGlvbnMsIGFkZGl0aW9uYWxDcmVhdGVPcHRpb25zKTsgLy8gZW5zdXJlIHRoYXQgYGdldE93bmVyKHRoaXMpYCB3b3JrcyBpbnNpZGUgYSBtb2RlbCBpbnN0YW5jZQoKICAgICAgICAgICAgRW1iZXIuc2V0T3duZXIoY3JlYXRlT3B0aW9ucywgRW1iZXIuZ2V0T3duZXIoX3N0b3JlKSk7CiAgICAgICAgICAgIHRoaXMuX3JlY29yZCA9IF9zdG9yZS5fbW9kZWxGYWN0b3J5Rm9yKHRoaXMubW9kZWxOYW1lKS5jcmVhdGUoY3JlYXRlT3B0aW9ucyk7CiAgICAgICAgICAgIHNldFJlY29yZElkZW50aWZpZXIodGhpcy5fcmVjb3JkLCB0aGlzLmlkZW50aWZpZXIpOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgdGhpcy5fdHJpZ2dlckRlZmVycmVkVHJpZ2dlcnMoKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuX3JlY29yZDsKICAgIH07CgogICAgX3Byb3RvLnJlc2V0UmVjb3JkID0gZnVuY3Rpb24gcmVzZXRSZWNvcmQoKSB7CiAgICAgIHRoaXMuX3JlY29yZCA9IG51bGw7CiAgICAgIHRoaXMuaXNSZWxvYWRpbmcgPSBmYWxzZTsKICAgICAgdGhpcy5lcnJvciA9IG51bGw7CiAgICAgIHRoaXMuY3VycmVudFN0YXRlID0gUm9vdFN0YXRlJDEuZW1wdHk7CiAgICB9OwoKICAgIF9wcm90by5kZW1hdGVyaWFsaXplUmVjb3JkID0gZnVuY3Rpb24gZGVtYXRlcmlhbGl6ZVJlY29yZCgpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHRoaXMuX2lzRGVtYXRlcmlhbGl6aW5nID0gdHJ1ZTsgLy8gVE9ETyBJR09SIGFkZCBhIHRlc3QgdGhhdCBmYWlscyB3aGVuIHRoaXMgaXMgbWlzc2luZywgc29tZXRoaW5nIHRoYXQgaW52b2x2ZXMgY2FuY2VsaWluZyBhIGRlc3Ryb3kKICAgICAgLy8gYW5kIHRoZSBkZXN0cm95IG5vdCBoYXBwZW5pbmcsIGFuZCB0aGVuIGxhdGVyIG9uIHRyeWluZyB0byBkZXN0cm95CgogICAgICB0aGlzLl9kb05vdERlc3Ryb3kgPSBmYWxzZTsKCiAgICAgIGlmICh0aGlzLl9yZWNvcmQpIHsKICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICB0aGlzLnN0b3JlLnRlYXJkb3duUmVjb3JkKHRoaXMuX3JlY29yZCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuX3JlY29yZC5kZXN0cm95KCk7CiAgICAgICAgfQoKICAgICAgICBPYmplY3Qua2V5cyh0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgIGlmIChfdGhpcy5fcmVsYXRpb25zaGlwUHJveHlDYWNoZVtrZXldLmRlc3Ryb3kpIHsKICAgICAgICAgICAgX3RoaXMuX3JlbGF0aW9uc2hpcFByb3h5Q2FjaGVba2V5XS5kZXN0cm95KCk7CiAgICAgICAgICB9CgogICAgICAgICAgZGVsZXRlIF90aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlW2tleV07CiAgICAgICAgfSk7CiAgICAgICAgT2JqZWN0LmtleXModGhpcy5fbWFueUFycmF5Q2FjaGUpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgdmFyIG1hbnlBcnJheSA9IF90aGlzLl9yZXRhaW5lZE1hbnlBcnJheUNhY2hlW2tleV0gPSBfdGhpcy5fbWFueUFycmF5Q2FjaGVba2V5XTsKICAgICAgICAgIGRlbGV0ZSBfdGhpcy5fbWFueUFycmF5Q2FjaGVba2V5XTsKCiAgICAgICAgICBpZiAobWFueUFycmF5ICYmICFtYW55QXJyYXkuX2ludmVyc2VJc0FzeW5jKSB7CiAgICAgICAgICAgIC8qCiAgICAgICAgICAgICAgSWYgdGhlIG1hbnlBcnJheSBpcyBmb3IgYSBzeW5jIHJlbGF0aW9uc2hpcCwgd2Ugc2hvdWxkIGNsZWFyIGl0CiAgICAgICAgICAgICAgICB0byBwcmVzZXJ2ZSB0aGUgc2VtYW50aWNzIG9mIGNsaWVudC1zaWRlIGRlbGV0ZS4KICAgICAgICAgICAgICAgSXQgaXMgbGlrZWx5IGluIHRoaXMgY2FzZSBpbnN0ZWFkIG9mIHJldGFpbmluZyB3ZSBzaG91bGQgZGVzdHJveQogICAgICAgICAgICAgICAgLSBAcnVuc3BpcmVkCiAgICAgICAgICAgICovCiAgICAgICAgICAgIG1hbnlBcnJheS5jbGVhcigpOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9IC8vIG1vdmUgdG8gYW4gZW1wdHkgbmV2ZXItbG9hZGVkIHN0YXRlCgoKICAgICAgdGhpcy5fcmVjb3JkRGF0YS51bmxvYWRSZWNvcmQoKTsKCiAgICAgIHRoaXMucmVzZXRSZWNvcmQoKTsKICAgICAgdGhpcy51cGRhdGVSZWNvcmRBcnJheXMoKTsKICAgIH07CgogICAgX3Byb3RvLmRlbGV0ZVJlY29yZCA9IGZ1bmN0aW9uIGRlbGV0ZVJlY29yZCgpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX1NUQVRFKSB7CiAgICAgICAgaWYgKHRoaXMuX3JlY29yZERhdGEuc2V0SXNEZWxldGVkKSB7CiAgICAgICAgICB0aGlzLl9yZWNvcmREYXRhLnNldElzRGVsZXRlZCh0cnVlKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHRoaXMuc2VuZCgnZGVsZXRlUmVjb3JkJyk7CiAgICB9OwoKICAgIF9wcm90by5zYXZlID0gZnVuY3Rpb24gc2F2ZShvcHRpb25zKSB7CiAgICAgIHZhciBwcm9taXNlTGFiZWwgPSAnRFM6IE1vZGVsI3NhdmUgJyArIHRoaXM7CiAgICAgIHZhciByZXNvbHZlciA9IEVtYmVyLlJTVlAuZGVmZXIocHJvbWlzZUxhYmVsKTsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICAvLyBDYXN0aW5nIHRvIG5hcnJvdyBkdWUgdG8gdGhlIGZlYXR1cmUgZmxhZyBwYXRocyBpbnNpZGUgc2NoZWR1bGVTYXZlCiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuc2NoZWR1bGVTYXZlKHRoaXMsIHJlc29sdmVyLCBvcHRpb25zKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnN0b3JlLnNjaGVkdWxlU2F2ZSh0aGlzLCByZXNvbHZlciwgb3B0aW9ucyk7CiAgICAgICAgcmV0dXJuIHJlc29sdmVyLnByb21pc2U7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnN0YXJ0ZWRSZWxvYWRpbmcgPSBmdW5jdGlvbiBzdGFydGVkUmVsb2FkaW5nKCkgewogICAgICB0aGlzLmlzUmVsb2FkaW5nID0gdHJ1ZTsKCiAgICAgIGlmICh0aGlzLmhhc1JlY29yZCkgewogICAgICAgIEVtYmVyLnNldCh0aGlzLl9yZWNvcmQsICdpc1JlbG9hZGluZycsIHRydWUpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5maW5pc2hlZFJlbG9hZGluZyA9IGZ1bmN0aW9uIGZpbmlzaGVkUmVsb2FkaW5nKCkgewogICAgICB0aGlzLmlzUmVsb2FkaW5nID0gZmFsc2U7CgogICAgICBpZiAodGhpcy5oYXNSZWNvcmQpIHsKICAgICAgICBFbWJlci5zZXQodGhpcy5fcmVjb3JkLCAnaXNSZWxvYWRpbmcnLCBmYWxzZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLnJlbG9hZCA9IGZ1bmN0aW9uIHJlbG9hZChvcHRpb25zKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICBpZiAoIW9wdGlvbnMpIHsKICAgICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgICB9CgogICAgICAgIHRoaXMuc3RhcnRlZFJlbG9hZGluZygpOwogICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gdGhpczsKICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5zdG9yZS5fcmVsb2FkUmVjb3JkKGludGVybmFsTW9kZWwsIG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgLy9UT0RPIE5PVyBzZWVtcyBsaWtlIHdlIHNob3VsZG4ndCBuZWVkIHRvIGRvIHRoaXMKICAgICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsOwogICAgICAgIH0sIGZ1bmN0aW9uIChlcnJvcikgewogICAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgICAgfSwgJ0RTOiBNb2RlbCNyZWxvYWQgY29tcGxldGUsIHVwZGF0ZSBmbGFncycpLmZpbmFsbHkoZnVuY3Rpb24gKCkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC5maW5pc2hlZFJlbG9hZGluZygpOwogICAgICAgICAgaW50ZXJuYWxNb2RlbC51cGRhdGVSZWNvcmRBcnJheXMoKTsKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnN0YXJ0ZWRSZWxvYWRpbmcoKTsKCiAgICAgICAgdmFyIF9pbnRlcm5hbE1vZGVsID0gdGhpczsKCiAgICAgICAgdmFyIHByb21pc2VMYWJlbCA9ICdEUzogTW9kZWwjcmVsb2FkIG9mICcgKyB0aGlzOwogICAgICAgIHJldHVybiBuZXcgRW1iZXIuUlNWUC5Qcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7CiAgICAgICAgICBfaW50ZXJuYWxNb2RlbC5zZW5kKCdyZWxvYWRSZWNvcmQnLCB7CiAgICAgICAgICAgIHJlc29sdmU6IHJlc29sdmUsCiAgICAgICAgICAgIG9wdGlvbnM6IG9wdGlvbnMKICAgICAgICAgIH0pOwogICAgICAgIH0sIHByb21pc2VMYWJlbCkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICBfaW50ZXJuYWxNb2RlbC5kaWRDbGVhbkVycm9yKCk7CgogICAgICAgICAgcmV0dXJuIF9pbnRlcm5hbE1vZGVsOwogICAgICAgIH0sIGZ1bmN0aW9uIChlcnJvcikgewogICAgICAgICAgX2ludGVybmFsTW9kZWwuZGlkRXJyb3IoZXJyb3IpOwoKICAgICAgICAgIHRocm93IGVycm9yOwogICAgICAgIH0sICdEUzogTW9kZWwjcmVsb2FkIGNvbXBsZXRlLCB1cGRhdGUgZmxhZ3MnKS5maW5hbGx5KGZ1bmN0aW9uICgpIHsKICAgICAgICAgIF9pbnRlcm5hbE1vZGVsLmZpbmlzaGVkUmVsb2FkaW5nKCk7CgogICAgICAgICAgX2ludGVybmFsTW9kZWwudXBkYXRlUmVjb3JkQXJyYXlzKCk7CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIC8qCiAgICAgIFVubG9hZCB0aGUgcmVjb3JkIGZvciB0aGlzIGludGVybmFsIG1vZGVsLiBUaGlzIHdpbGwgY2F1c2UgdGhlIHJlY29yZCB0byBiZQogICAgICBkZXN0cm95ZWQgYW5kIGZyZWVkIHVwIGZvciBnYXJiYWdlIGNvbGxlY3Rpb24uIEl0IHdpbGwgYWxzbyBkbyBhIGNoZWNrCiAgICAgIGZvciBjbGVhbmluZyB1cCBpbnRlcm5hbCBtb2RlbHMuCiAgICAgICBUaGlzIGNoZWNrIGlzIHBlcmZvcm1lZCBieSBmaXJzdCBjb21wdXRpbmcgdGhlIHNldCBvZiByZWxhdGVkIGludGVybmFsCiAgICAgIG1vZGVscy4gSWYgYWxsIHJlY29yZHMgaW4gdGhpcyBzZXQgYXJlIHVubG9hZGVkLCB0aGVuIHRoZSBlbnRpcmUgc2V0IGlzCiAgICAgIGRlc3Ryb3llZC4gT3RoZXJ3aXNlLCBub3RoaW5nIGluIHRoZSBzZXQgaXMgZGVzdHJveWVkLgogICAgICAgVGhpcyBtZWFucyB0aGF0IHRoaXMgaW50ZXJuYWwgbW9kZWwgd2lsbCBiZSBmcmVlZCB1cCBmb3IgZ2FyYmFnZSBjb2xsZWN0aW9uCiAgICAgIG9uY2UgYWxsIG1vZGVscyB0aGF0IHJlZmVyIHRvIGl0IHZpYSBzb21lIHJlbGF0aW9uc2hpcCBhcmUgYWxzbyB1bmxvYWRlZC4KICAgICovCiAgICA7CgogICAgX3Byb3RvLnVubG9hZFJlY29yZCA9IGZ1bmN0aW9uIHVubG9hZFJlY29yZCgpIHsKICAgICAgaWYgKHRoaXMuaXNEZXN0cm95ZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHRoaXMuc2VuZCgndW5sb2FkUmVjb3JkJyk7CiAgICAgIHRoaXMuZGVtYXRlcmlhbGl6ZVJlY29yZCgpOwoKICAgICAgaWYgKHRoaXMuX3NjaGVkdWxlZERlc3Ryb3kgPT09IG51bGwpIHsKICAgICAgICB0aGlzLl9zY2hlZHVsZWREZXN0cm95ID0gRW1iZXIucnVuLmJhY2tidXJuZXIuc2NoZWR1bGUoJ2Rlc3Ryb3knLCB0aGlzLCAnX2NoZWNrRm9yT3JwaGFuZWRJbnRlcm5hbE1vZGVscycpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5oYXNTY2hlZHVsZWREZXN0cm95ID0gZnVuY3Rpb24gaGFzU2NoZWR1bGVkRGVzdHJveSgpIHsKICAgICAgcmV0dXJuICEhdGhpcy5fc2NoZWR1bGVkRGVzdHJveTsKICAgIH07CgogICAgX3Byb3RvLmNhbmNlbERlc3Ryb3kgPSBmdW5jdGlvbiBjYW5jZWxEZXN0cm95KCkgewogICAgICB0aGlzLl9kb05vdERlc3Ryb3kgPSB0cnVlOwogICAgICB0aGlzLl9pc0RlbWF0ZXJpYWxpemluZyA9IGZhbHNlOwogICAgICBFbWJlci5ydW4uY2FuY2VsKHRoaXMuX3NjaGVkdWxlZERlc3Ryb3kpOwogICAgICB0aGlzLl9zY2hlZHVsZWREZXN0cm95ID0gbnVsbDsKICAgIH0gLy8gdHlwaWNhbGx5LCB3ZSBwcmVmZXIgdG8gYXN5bmMgZGVzdHJveSB0aGlzIGxldHMgdXMgYmF0Y2ggY2xlYW51cCB3b3JrLgogICAgLy8gVW5mb3J0dW5hdGVseSwgc29tZSBzY2VuYXJpb3Mgd2hlcmUgdGhhdCBpcyBub3QgcG9zc2libGUuIFN1Y2ggYXM6CiAgICAvLwogICAgLy8gYGBganMKICAgIC8vIGNvbnN0IHJlY29yZCA9IHN0b3JlLmZpbmQo4oCYcmVjb3Jk4oCZLCAxKTsKICAgIC8vIHJlY29yZC51bmxvYWRSZWNvcmQoKTsKICAgIC8vIHN0b3JlLmNyZWF0ZVJlY29yZCjigJhyZWNvcmTigJksIDEpOwogICAgLy8gYGBgCiAgICAvLwogICAgLy8gSW4gdGhvc2Ugc2NlbmFyaW9zLCB3ZSBtYWtlIHRoYXQgbW9kZWwncyBjbGVhbnVwIHdvcmssIHN5bmMuCiAgICAvLwogICAgOwoKICAgIF9wcm90by5kZXN0cm95U3luYyA9IGZ1bmN0aW9uIGRlc3Ryb3lTeW5jKCkgewogICAgICBpZiAodGhpcy5faXNEZW1hdGVyaWFsaXppbmcpIHsKICAgICAgICB0aGlzLmNhbmNlbERlc3Ryb3koKTsKICAgICAgfQoKICAgICAgdGhpcy5fY2hlY2tGb3JPcnBoYW5lZEludGVybmFsTW9kZWxzKCk7CgogICAgICBpZiAodGhpcy5pc0Rlc3Ryb3llZCB8fCB0aGlzLmlzRGVzdHJveWluZykgewogICAgICAgIHJldHVybjsKICAgICAgfSAvLyBqdXN0IGluLWNhc2Ugd2UgYXJlIG5vdCBvbmUgb2YgdGhlIG9ycGhhbmVkLCB3ZSBzaG91bGQgc3RpbGwKICAgICAgLy8gc3RpbGwgZGVzdHJveSBvdXJzZWx2ZXMKCgogICAgICB0aGlzLmRlc3Ryb3koKTsKICAgIH07CgogICAgX3Byb3RvLl9jaGVja0Zvck9ycGhhbmVkSW50ZXJuYWxNb2RlbHMgPSBmdW5jdGlvbiBfY2hlY2tGb3JPcnBoYW5lZEludGVybmFsTW9kZWxzKCkgewogICAgICB0aGlzLl9pc0RlbWF0ZXJpYWxpemluZyA9IGZhbHNlOwogICAgICB0aGlzLl9zY2hlZHVsZWREZXN0cm95ID0gbnVsbDsKCiAgICAgIGlmICh0aGlzLmlzRGVzdHJveWVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5lYWNoUmVsYXRpb25zaGlwID0gZnVuY3Rpb24gZWFjaFJlbGF0aW9uc2hpcChjYWxsYmFjaywgYmluZGluZykgewogICAgICByZXR1cm4gdGhpcy5tb2RlbENsYXNzLmVhY2hSZWxhdGlvbnNoaXAoY2FsbGJhY2ssIGJpbmRpbmcpOwogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRCZWxvbmdzVG8gPSBmdW5jdGlvbiBfZmluZEJlbG9uZ3NUbyhrZXksIHJlc291cmNlLCByZWxhdGlvbnNoaXBNZXRhLCBvcHRpb25zKSB7CiAgICAgIHZhciBfdGhpczIgPSB0aGlzOwoKICAgICAgLy8gVE9ETyBAcnVuc3BpcmVkIGZvbGxvdyB1cCBpZiBwYXJlbnQgaXNOZXcgdGhlbiB3ZSBzaG91bGQgbm90IGJlIGF0dGVtcHRpbmcgbG9hZCBoZXJlCiAgICAgIHJldHVybiB0aGlzLnN0b3JlLl9maW5kQmVsb25nc1RvQnlKc29uQXBpUmVzb3VyY2UocmVzb3VyY2UsIHRoaXMsIHJlbGF0aW9uc2hpcE1ldGEsIG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKGludGVybmFsTW9kZWwpIHsKICAgICAgICByZXR1cm4gaGFuZGxlQ29tcGxldGVkUmVsYXRpb25zaGlwUmVxdWVzdChfdGhpczIsIGtleSwgcmVzb3VyY2UuX3JlbGF0aW9uc2hpcCwgaW50ZXJuYWxNb2RlbCwgbnVsbCk7CiAgICAgIH0sIGZ1bmN0aW9uIChlKSB7CiAgICAgICAgcmV0dXJuIGhhbmRsZUNvbXBsZXRlZFJlbGF0aW9uc2hpcFJlcXVlc3QoX3RoaXMyLCBrZXksIHJlc291cmNlLl9yZWxhdGlvbnNoaXAsIG51bGwsIGUpOwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvLmdldEJlbG9uZ3NUbyA9IGZ1bmN0aW9uIGdldEJlbG9uZ3NUbyhrZXksIG9wdGlvbnMpIHsKICAgICAgdmFyIHJlc291cmNlID0gdGhpcy5fcmVjb3JkRGF0YS5nZXRCZWxvbmdzVG8oa2V5KTsKCiAgICAgIHZhciBpZGVudGlmaWVyID0gcmVzb3VyY2UgJiYgcmVzb3VyY2UuZGF0YSA/IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzLnN0b3JlKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UuZGF0YSkgOiBudWxsOwoKICAgICAgdmFyIHJlbGF0aW9uc2hpcE1ldGEgPSB0aGlzLnN0b3JlLl9yZWxhdGlvbnNoaXBNZXRhRm9yKHRoaXMubW9kZWxOYW1lLCBudWxsLCBrZXkpOwoKICAgICAgdmFyIHN0b3JlID0gdGhpcy5zdG9yZTsKICAgICAgdmFyIGFzeW5jID0gcmVsYXRpb25zaGlwTWV0YS5vcHRpb25zLmFzeW5jOwogICAgICB2YXIgaXNBc3luYyA9IHR5cGVvZiBhc3luYyA9PT0gJ3VuZGVmaW5lZCcgPyB0cnVlIDogYXN5bmM7CiAgICAgIHZhciBfYmVsb25nc1RvU3RhdGUgPSB7CiAgICAgICAga2V5OiBrZXksCiAgICAgICAgc3RvcmU6IHN0b3JlLAogICAgICAgIG9yaWdpbmF0aW5nSW50ZXJuYWxNb2RlbDogdGhpcywKICAgICAgICBtb2RlbE5hbWU6IHJlbGF0aW9uc2hpcE1ldGEudHlwZQogICAgICB9OwoKICAgICAgaWYgKGlzQXN5bmMpIHsKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGlkZW50aWZpZXIgIT09IG51bGwgPyBzdG9yZS5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlKGlkZW50aWZpZXIpIDogbnVsbDsKCiAgICAgICAgaWYgKHJlc291cmNlLl9yZWxhdGlvbnNoaXAuaGFzRmFpbGVkTG9hZEF0dGVtcHQpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlW2tleV07CiAgICAgICAgfQoKICAgICAgICB2YXIgcHJvbWlzZSA9IHRoaXMuX2ZpbmRCZWxvbmdzVG8oa2V5LCByZXNvdXJjZSwgcmVsYXRpb25zaGlwTWV0YSwgb3B0aW9ucyk7CgogICAgICAgIHJldHVybiB0aGlzLl91cGRhdGVQcm9taXNlUHJveHlGb3IoJ2JlbG9uZ3NUbycsIGtleSwgewogICAgICAgICAgcHJvbWlzZTogcHJvbWlzZSwKICAgICAgICAgIGNvbnRlbnQ6IGludGVybmFsTW9kZWwgPyBpbnRlcm5hbE1vZGVsLmdldFJlY29yZCgpIDogbnVsbCwKICAgICAgICAgIF9iZWxvbmdzVG9TdGF0ZTogX2JlbG9uZ3NUb1N0YXRlCiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaWYgKGlkZW50aWZpZXIgPT09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB2YXIgX2ludGVybmFsTW9kZWwyID0gc3RvcmUuX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShpZGVudGlmaWVyKTsKCiAgICAgICAgICB2YXIgdG9SZXR1cm4gPSBfaW50ZXJuYWxNb2RlbDIuZ2V0UmVjb3JkKCk7CiAgICAgICAgICByZXR1cm4gdG9SZXR1cm47CiAgICAgICAgfQogICAgICB9CiAgICB9IC8vIFRPRE8gSWdvciBjb25zaWRlciBnZXR0aW5nIHJpZCBvZiBpbml0aWFsIHN0YXRlCiAgICA7CgogICAgX3Byb3RvLmdldE1hbnlBcnJheSA9IGZ1bmN0aW9uIGdldE1hbnlBcnJheShrZXksIGlzQXN5bmMpIHsKICAgICAgaWYgKGlzQXN5bmMgPT09IHZvaWQgMCkgewogICAgICAgIGlzQXN5bmMgPSBmYWxzZTsKICAgICAgfQoKICAgICAgdmFyIHJlbGF0aW9uc2hpcE1ldGEgPSB0aGlzLnN0b3JlLl9yZWxhdGlvbnNoaXBNZXRhRm9yKHRoaXMubW9kZWxOYW1lLCBudWxsLCBrZXkpOwoKICAgICAgdmFyIGpzb25BcGkgPSB0aGlzLl9yZWNvcmREYXRhLmdldEhhc01hbnkoa2V5KTsKCiAgICAgIHZhciBtYW55QXJyYXkgPSB0aGlzLl9tYW55QXJyYXlDYWNoZVtrZXldOwoKICAgICAgaWYgKCFtYW55QXJyYXkpIHsKICAgICAgICB2YXIgaW5pdGlhbFN0YXRlID0gdGhpcy5zdG9yZS5fZ2V0SGFzTWFueUJ5SnNvbkFwaVJlc291cmNlKGpzb25BcGkpOyAvLyBUT0RPIG1vdmUgdGhpcyB0byBhIHB1YmxpYyBhcGkKCgogICAgICAgIHZhciBpbnZlcnNlSXNBc3luYyA9IGpzb25BcGkuX3JlbGF0aW9uc2hpcCA/IGpzb25BcGkuX3JlbGF0aW9uc2hpcC5faW52ZXJzZUlzQXN5bmMoKSA6IGZhbHNlOwogICAgICAgIG1hbnlBcnJheSA9IE1hbnlBcnJheS5jcmVhdGUoewogICAgICAgICAgc3RvcmU6IHRoaXMuc3RvcmUsCiAgICAgICAgICB0eXBlOiB0aGlzLnN0b3JlLm1vZGVsRm9yKHJlbGF0aW9uc2hpcE1ldGEudHlwZSksCiAgICAgICAgICByZWNvcmREYXRhOiB0aGlzLl9yZWNvcmREYXRhLAogICAgICAgICAgbWV0YToganNvbkFwaS5tZXRhLAogICAgICAgICAgbGlua3M6IGNhbmFyeUZlYXR1cmVzLkZVTExfTElOS1NfT05fUkVMQVRJT05TSElQUyA/IGpzb25BcGkubGlua3MgOiB1bmRlZmluZWQsCiAgICAgICAgICBrZXk6IGtleSwKICAgICAgICAgIGlzUG9seW1vcnBoaWM6IHJlbGF0aW9uc2hpcE1ldGEub3B0aW9ucy5wb2x5bW9ycGhpYywKICAgICAgICAgIGluaXRpYWxTdGF0ZTogaW5pdGlhbFN0YXRlLnNsaWNlKCksCiAgICAgICAgICBfaW52ZXJzZUlzQXN5bmM6IGludmVyc2VJc0FzeW5jLAogICAgICAgICAgaW50ZXJuYWxNb2RlbDogdGhpcywKICAgICAgICAgIGlzTG9hZGVkOiAhaXNBc3luYwogICAgICAgIH0pOwogICAgICAgIHRoaXMuX21hbnlBcnJheUNhY2hlW2tleV0gPSBtYW55QXJyYXk7CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLl9yZXRhaW5lZE1hbnlBcnJheUNhY2hlW2tleV0pIHsKICAgICAgICB0aGlzLl9yZXRhaW5lZE1hbnlBcnJheUNhY2hlW2tleV0uZGVzdHJveSgpOwoKICAgICAgICBkZWxldGUgdGhpcy5fcmV0YWluZWRNYW55QXJyYXlDYWNoZVtrZXldOwogICAgICB9CgogICAgICByZXR1cm4gbWFueUFycmF5OwogICAgfTsKCiAgICBfcHJvdG8uZmV0Y2hBc3luY0hhc01hbnkgPSBmdW5jdGlvbiBmZXRjaEFzeW5jSGFzTWFueShrZXksIHJlbGF0aW9uc2hpcE1ldGEsIGpzb25BcGksIG1hbnlBcnJheSwgb3B0aW9ucykgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIC8vIFRPRE8gQHJ1bnNwaXJlZCBmb2xsb3cgdXAgaWYgcGFyZW50IGlzTmV3IHRoZW4gd2Ugc2hvdWxkIG5vdCBiZSBhdHRlbXB0aW5nIGxvYWQgaGVyZQogICAgICB2YXIgbG9hZGluZ1Byb21pc2UgPSB0aGlzLl9yZWxhdGlvbnNoaXBQcm9taXNlc0NhY2hlW2tleV07CgogICAgICBpZiAobG9hZGluZ1Byb21pc2UpIHsKICAgICAgICByZXR1cm4gbG9hZGluZ1Byb21pc2U7CiAgICAgIH0KCiAgICAgIGxvYWRpbmdQcm9taXNlID0gdGhpcy5zdG9yZS5fZmluZEhhc01hbnlCeUpzb25BcGlSZXNvdXJjZShqc29uQXBpLCB0aGlzLCByZWxhdGlvbnNoaXBNZXRhLCBvcHRpb25zKS50aGVuKGZ1bmN0aW9uIChpbml0aWFsU3RhdGUpIHsKICAgICAgICAvLyBUT0RPIHdoeSBkb24ndCB3ZSBkbyB0aGlzIGluIHRoZSBzdG9yZSBtZXRob2QKICAgICAgICBtYW55QXJyYXkucmV0cmlldmVMYXRlc3QoKTsKICAgICAgICBtYW55QXJyYXkuc2V0KCdpc0xvYWRlZCcsIHRydWUpOwogICAgICAgIHJldHVybiBtYW55QXJyYXk7CiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKG1hbnlBcnJheSkgewogICAgICAgIHJldHVybiBoYW5kbGVDb21wbGV0ZWRSZWxhdGlvbnNoaXBSZXF1ZXN0KF90aGlzMywga2V5LCBqc29uQXBpLl9yZWxhdGlvbnNoaXAsIG1hbnlBcnJheSwgbnVsbCk7CiAgICAgIH0sIGZ1bmN0aW9uIChlKSB7CiAgICAgICAgcmV0dXJuIGhhbmRsZUNvbXBsZXRlZFJlbGF0aW9uc2hpcFJlcXVlc3QoX3RoaXMzLCBrZXksIGpzb25BcGkuX3JlbGF0aW9uc2hpcCwgbnVsbCwgZSk7CiAgICAgIH0pOwogICAgICB0aGlzLl9yZWxhdGlvbnNoaXBQcm9taXNlc0NhY2hlW2tleV0gPSBsb2FkaW5nUHJvbWlzZTsKICAgICAgcmV0dXJuIGxvYWRpbmdQcm9taXNlOwogICAgfTsKCiAgICBfcHJvdG8uZ2V0SGFzTWFueSA9IGZ1bmN0aW9uIGdldEhhc01hbnkoa2V5LCBvcHRpb25zKSB7CiAgICAgIHZhciBqc29uQXBpID0gdGhpcy5fcmVjb3JkRGF0YS5nZXRIYXNNYW55KGtleSk7CgogICAgICB2YXIgcmVsYXRpb25zaGlwTWV0YSA9IHRoaXMuc3RvcmUuX3JlbGF0aW9uc2hpcE1ldGFGb3IodGhpcy5tb2RlbE5hbWUsIG51bGwsIGtleSk7CgogICAgICB2YXIgYXN5bmMgPSByZWxhdGlvbnNoaXBNZXRhLm9wdGlvbnMuYXN5bmM7CiAgICAgIHZhciBpc0FzeW5jID0gdHlwZW9mIGFzeW5jID09PSAndW5kZWZpbmVkJyA/IHRydWUgOiBhc3luYzsKICAgICAgdmFyIG1hbnlBcnJheSA9IHRoaXMuZ2V0TWFueUFycmF5KGtleSwgaXNBc3luYyk7CgogICAgICBpZiAoaXNBc3luYykgewogICAgICAgIGlmIChqc29uQXBpLl9yZWxhdGlvbnNoaXAuaGFzRmFpbGVkTG9hZEF0dGVtcHQpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9yZWxhdGlvbnNoaXBQcm94eUNhY2hlW2tleV07CiAgICAgICAgfQoKICAgICAgICB2YXIgcHJvbWlzZSA9IHRoaXMuZmV0Y2hBc3luY0hhc01hbnkoa2V5LCByZWxhdGlvbnNoaXBNZXRhLCBqc29uQXBpLCBtYW55QXJyYXksIG9wdGlvbnMpOwogICAgICAgIHJldHVybiB0aGlzLl91cGRhdGVQcm9taXNlUHJveHlGb3IoJ2hhc01hbnknLCBrZXksIHsKICAgICAgICAgIHByb21pc2U6IHByb21pc2UsCiAgICAgICAgICBjb250ZW50OiBtYW55QXJyYXkKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbWFueUFycmF5OwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fdXBkYXRlUHJvbWlzZVByb3h5Rm9yID0gZnVuY3Rpb24gX3VwZGF0ZVByb21pc2VQcm94eUZvcihraW5kLCBrZXksIGFyZ3MpIHsKICAgICAgdmFyIHByb21pc2VQcm94eSA9IHRoaXMuX3JlbGF0aW9uc2hpcFByb3h5Q2FjaGVba2V5XTsKCiAgICAgIGlmIChwcm9taXNlUHJveHkpIHsKICAgICAgICBpZiAoYXJncy5jb250ZW50ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIC8vIHRoaXMgdXNhZ2Ugb2YgYGFueWAgY2FuIGJlIHJlbW92ZWQgd2hlbiBgQHR5cGVzL2VtYmVyX29iamVjdGAgcHJveHkgYWxsb3dzIGBudWxsYCBmb3IgY29udGVudAogICAgICAgICAgcHJvbWlzZVByb3h5LnNldCgnY29udGVudCcsIGFyZ3MuY29udGVudCk7CiAgICAgICAgfQoKICAgICAgICBwcm9taXNlUHJveHkuc2V0KCdwcm9taXNlJywgYXJncy5wcm9taXNlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIga2xhc3MgPSBraW5kID09PSAnaGFzTWFueScgPyBQcm9taXNlTWFueUFycmF5IDogUHJvbWlzZUJlbG9uZ3NUbzsgLy8gdGhpcyB1c2FnZSBvZiBgYW55YCBjYW4gYmUgcmVtb3ZlZCB3aGVuIGBAdHlwZXMvZW1iZXJfb2JqZWN0YCBwcm94eSBhbGxvd3MgYG51bGxgIGZvciBjb250ZW50CgogICAgICAgIHRoaXMuX3JlbGF0aW9uc2hpcFByb3h5Q2FjaGVba2V5XSA9IGtsYXNzLmNyZWF0ZShhcmdzKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuX3JlbGF0aW9uc2hpcFByb3h5Q2FjaGVba2V5XTsKICAgIH07CgogICAgX3Byb3RvLnJlbG9hZEhhc01hbnkgPSBmdW5jdGlvbiByZWxvYWRIYXNNYW55KGtleSwgb3B0aW9ucykgewogICAgICB2YXIgbG9hZGluZ1Byb21pc2UgPSB0aGlzLl9yZWxhdGlvbnNoaXBQcm9taXNlc0NhY2hlW2tleV07CgogICAgICBpZiAobG9hZGluZ1Byb21pc2UpIHsKICAgICAgICByZXR1cm4gbG9hZGluZ1Byb21pc2U7CiAgICAgIH0KCiAgICAgIHZhciBqc29uQXBpID0gdGhpcy5fcmVjb3JkRGF0YS5nZXRIYXNNYW55KGtleSk7IC8vIFRPRE8gbW92ZSB0aGlzIHRvIGEgcHVibGljIGFwaQoKCiAgICAgIGlmIChqc29uQXBpLl9yZWxhdGlvbnNoaXApIHsKICAgICAgICBqc29uQXBpLl9yZWxhdGlvbnNoaXAuc2V0SGFzRmFpbGVkTG9hZEF0dGVtcHQoZmFsc2UpOwoKICAgICAgICBqc29uQXBpLl9yZWxhdGlvbnNoaXAuc2V0U2hvdWxkRm9yY2VSZWxvYWQodHJ1ZSk7CiAgICAgIH0KCiAgICAgIHZhciByZWxhdGlvbnNoaXBNZXRhID0gdGhpcy5zdG9yZS5fcmVsYXRpb25zaGlwTWV0YUZvcih0aGlzLm1vZGVsTmFtZSwgbnVsbCwga2V5KTsKCiAgICAgIHZhciBtYW55QXJyYXkgPSB0aGlzLmdldE1hbnlBcnJheShrZXkpOwogICAgICB2YXIgcHJvbWlzZSA9IHRoaXMuZmV0Y2hBc3luY0hhc01hbnkoa2V5LCByZWxhdGlvbnNoaXBNZXRhLCBqc29uQXBpLCBtYW55QXJyYXksIG9wdGlvbnMpOwoKICAgICAgaWYgKHRoaXMuX3JlbGF0aW9uc2hpcFByb3h5Q2FjaGVba2V5XSkgewogICAgICAgIHJldHVybiB0aGlzLl91cGRhdGVQcm9taXNlUHJveHlGb3IoJ2hhc01hbnknLCBrZXksIHsKICAgICAgICAgIHByb21pc2U6IHByb21pc2UKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIHByb21pc2U7CiAgICB9OwoKICAgIF9wcm90by5yZWxvYWRCZWxvbmdzVG8gPSBmdW5jdGlvbiByZWxvYWRCZWxvbmdzVG8oa2V5LCBvcHRpb25zKSB7CiAgICAgIHZhciBsb2FkaW5nUHJvbWlzZSA9IHRoaXMuX3JlbGF0aW9uc2hpcFByb21pc2VzQ2FjaGVba2V5XTsKCiAgICAgIGlmIChsb2FkaW5nUHJvbWlzZSkgewogICAgICAgIHJldHVybiBsb2FkaW5nUHJvbWlzZTsKICAgICAgfQoKICAgICAgdmFyIHJlc291cmNlID0gdGhpcy5fcmVjb3JkRGF0YS5nZXRCZWxvbmdzVG8oa2V5KTsgLy8gVE9ETyBtb3ZlIHRoaXMgdG8gYSBwdWJsaWMgYXBpCgoKICAgICAgaWYgKHJlc291cmNlLl9yZWxhdGlvbnNoaXApIHsKICAgICAgICByZXNvdXJjZS5fcmVsYXRpb25zaGlwLnNldEhhc0ZhaWxlZExvYWRBdHRlbXB0KGZhbHNlKTsKCiAgICAgICAgcmVzb3VyY2UuX3JlbGF0aW9uc2hpcC5zZXRTaG91bGRGb3JjZVJlbG9hZCh0cnVlKTsKICAgICAgfQoKICAgICAgdmFyIHJlbGF0aW9uc2hpcE1ldGEgPSB0aGlzLnN0b3JlLl9yZWxhdGlvbnNoaXBNZXRhRm9yKHRoaXMubW9kZWxOYW1lLCBudWxsLCBrZXkpOwoKICAgICAgdmFyIHByb21pc2UgPSB0aGlzLl9maW5kQmVsb25nc1RvKGtleSwgcmVzb3VyY2UsIHJlbGF0aW9uc2hpcE1ldGEsIG9wdGlvbnMpOwoKICAgICAgaWYgKHRoaXMuX3JlbGF0aW9uc2hpcFByb3h5Q2FjaGVba2V5XSkgewogICAgICAgIHJldHVybiB0aGlzLl91cGRhdGVQcm9taXNlUHJveHlGb3IoJ2JlbG9uZ3NUbycsIGtleSwgewogICAgICAgICAgcHJvbWlzZTogcHJvbWlzZQogICAgICAgIH0pOwogICAgICB9CgogICAgICByZXR1cm4gcHJvbWlzZTsKICAgIH07CgogICAgX3Byb3RvLmRlc3Ryb3lGcm9tUmVjb3JkRGF0YSA9IGZ1bmN0aW9uIGRlc3Ryb3lGcm9tUmVjb3JkRGF0YSgpIHsKICAgICAgaWYgKHRoaXMuX2RvTm90RGVzdHJveSkgewogICAgICAgIHRoaXMuX2RvTm90RGVzdHJveSA9IGZhbHNlOwogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5kZXN0cm95KCk7CiAgICB9OwoKICAgIF9wcm90by5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdmFyIF90aGlzNCA9IHRoaXM7CiAgICAgIHRoaXMuaXNEZXN0cm95aW5nID0gdHJ1ZTsKICAgICAgT2JqZWN0LmtleXModGhpcy5fcmV0YWluZWRNYW55QXJyYXlDYWNoZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgX3RoaXM0Ll9yZXRhaW5lZE1hbnlBcnJheUNhY2hlW2tleV0uZGVzdHJveSgpOwoKICAgICAgICBkZWxldGUgX3RoaXM0Ll9yZXRhaW5lZE1hbnlBcnJheUNhY2hlW2tleV07CiAgICAgIH0pOwogICAgICBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzLnN0b3JlKS5yZW1vdmUodGhpcyk7CiAgICAgIHRoaXMuX2lzRGVzdHJveWVkID0gdHJ1ZTsKICAgIH07CgogICAgX3Byb3RvLmVhY2hBdHRyaWJ1dGUgPSBmdW5jdGlvbiBlYWNoQXR0cmlidXRlKGNhbGxiYWNrLCBiaW5kaW5nKSB7CiAgICAgIHJldHVybiB0aGlzLm1vZGVsQ2xhc3MuZWFjaEF0dHJpYnV0ZShjYWxsYmFjaywgYmluZGluZyk7CiAgICB9OwoKICAgIF9wcm90by5pbnZlcnNlRm9yID0gZnVuY3Rpb24gaW52ZXJzZUZvcihrZXkpIHsKICAgICAgcmV0dXJuIHRoaXMubW9kZWxDbGFzcy5pbnZlcnNlRm9yKGtleSk7CiAgICB9OwoKICAgIF9wcm90by5zZXR1cERhdGEgPSBmdW5jdGlvbiBzZXR1cERhdGEoZGF0YSkgewogICAgICB2YXIgY2hhbmdlZEtleXMgPSB0aGlzLl9yZWNvcmREYXRhLnB1c2hEYXRhKGRhdGEsIHRoaXMuaGFzUmVjb3JkKTsKCiAgICAgIGlmICh0aGlzLmhhc1JlY29yZCkgewogICAgICAgIHRoaXMuX3JlY29yZC5fbm90aWZ5UHJvcGVydGllcyhjaGFuZ2VkS2V5cyk7CiAgICAgIH0KCiAgICAgIHRoaXMucHVzaGVkRGF0YSgpOwogICAgfTsKCiAgICBfcHJvdG8uZ2V0QXR0cmlidXRlVmFsdWUgPSBmdW5jdGlvbiBnZXRBdHRyaWJ1dGVWYWx1ZShrZXkpIHsKICAgICAgcmV0dXJuIHRoaXMuX3JlY29yZERhdGEuZ2V0QXR0cihrZXkpOwogICAgfTsKCiAgICBfcHJvdG8uc2V0RGlydHlIYXNNYW55ID0gZnVuY3Rpb24gc2V0RGlydHlIYXNNYW55KGtleSwgcmVjb3JkcykgewogICAgICByZXR1cm4gdGhpcy5fcmVjb3JkRGF0YS5zZXREaXJ0eUhhc01hbnkoa2V5LCBleHRyYWN0UmVjb3JkRGF0YXNGcm9tUmVjb3JkcyhyZWNvcmRzKSk7CiAgICB9OwoKICAgIF9wcm90by5zZXREaXJ0eUJlbG9uZ3NUbyA9IGZ1bmN0aW9uIHNldERpcnR5QmVsb25nc1RvKGtleSwgdmFsdWUpIHsKICAgICAgcmV0dXJuIHRoaXMuX3JlY29yZERhdGEuc2V0RGlydHlCZWxvbmdzVG8oa2V5LCBleHRyYWN0UmVjb3JkRGF0YUZyb21SZWNvcmQodmFsdWUpKTsKICAgIH07CgogICAgX3Byb3RvLnNldERpcnR5QXR0cmlidXRlID0gZnVuY3Rpb24gc2V0RGlydHlBdHRyaWJ1dGUoa2V5LCB2YWx1ZSkgewogICAgICBpZiAodGhpcy5pc0RlbGV0ZWQoKSkgewogICAgICAgIHRocm93IG5ldyBFbWJlci5FcnJvcigiQXR0ZW1wdGVkIHRvIHNldCAnIiArIGtleSArICInIHRvICciICsgdmFsdWUgKyAiJyBvbiB0aGUgZGVsZXRlZCByZWNvcmQgIiArIHRoaXMpOwogICAgICB9CgogICAgICB2YXIgY3VycmVudFZhbHVlID0gdGhpcy5nZXRBdHRyaWJ1dGVWYWx1ZShrZXkpOwoKICAgICAgaWYgKGN1cnJlbnRWYWx1ZSAhPT0gdmFsdWUpIHsKICAgICAgICB0aGlzLl9yZWNvcmREYXRhLnNldERpcnR5QXR0cmlidXRlKGtleSwgdmFsdWUpOwoKICAgICAgICB2YXIgaXNEaXJ0eSA9IHRoaXMuX3JlY29yZERhdGEuaXNBdHRyRGlydHkoa2V5KTsKCiAgICAgICAgdGhpcy5zZW5kKCdkaWRTZXRQcm9wZXJ0eScsIHsKICAgICAgICAgIG5hbWU6IGtleSwKICAgICAgICAgIGlzRGlydHk6IGlzRGlydHkKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfTsKCiAgICAvKgogICAgICBAbWV0aG9kIGNyZWF0ZVNuYXBzaG90CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX3Byb3RvLmNyZWF0ZVNuYXBzaG90ID0gZnVuY3Rpb24gY3JlYXRlU25hcHNob3Qob3B0aW9ucykgewogICAgICByZXR1cm4gbmV3IFNuYXBzaG90KG9wdGlvbnMgfHwge30sIHRoaXMuaWRlbnRpZmllciwgdGhpcy5zdG9yZSk7CiAgICB9CiAgICAvKgogICAgICBAbWV0aG9kIGxvYWRpbmdEYXRhCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ubG9hZGluZ0RhdGEgPSBmdW5jdGlvbiBsb2FkaW5nRGF0YShwcm9taXNlKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICB0aGlzLnNlbmQoJ2xvYWRpbmdEYXRhJyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5zZW5kKCdsb2FkaW5nRGF0YScsIHByb21pc2UpOwogICAgICB9CiAgICB9CiAgICAvKgogICAgICBAbWV0aG9kIGxvYWRlZERhdGEKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmxvYWRlZERhdGEgPSBmdW5jdGlvbiBsb2FkZWREYXRhKCkgewogICAgICB0aGlzLnNlbmQoJ2xvYWRlZERhdGEnKTsKICAgIH0KICAgIC8qCiAgICAgIEBtZXRob2Qgbm90Rm91bmQKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLm5vdEZvdW5kID0gZnVuY3Rpb24gbm90Rm91bmQoKSB7CiAgICAgIHRoaXMuc2VuZCgnbm90Rm91bmQnKTsKICAgIH0KICAgIC8qCiAgICAgIEBtZXRob2QgcHVzaGVkRGF0YQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucHVzaGVkRGF0YSA9IGZ1bmN0aW9uIHB1c2hlZERhdGEoKSB7CiAgICAgIHRoaXMuc2VuZCgncHVzaGVkRGF0YScpOwogICAgfTsKCiAgICBfcHJvdG8uaGFzQ2hhbmdlZEF0dHJpYnV0ZXMgPSBmdW5jdGlvbiBoYXNDaGFuZ2VkQXR0cmlidXRlcygpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgICAgIGlmICghdGhpcy5fX3JlY29yZERhdGEpIHsKICAgICAgICAgIC8vIG5vIG5lZWQgdG8gY2FsY3VsYXRlIGNoYW5nZWQgYXR0cmlidXRlcyB3aGVuIGNhbGxpbmcgYGZpbmRSZWNvcmRgCiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGlmICh0aGlzLmlzTG9hZGluZygpICYmICF0aGlzLmlzUmVsb2FkaW5nKSB7CiAgICAgICAgICAvLyBubyBuZWVkIHRvIGNhbGN1bGF0ZSBjaGFuZ2VkIGF0dHJpYnV0ZXMgd2hlbiBjYWxsaW5nIGBmaW5kUmVjb3JkYAogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuX3JlY29yZERhdGEuaGFzQ2hhbmdlZEF0dHJpYnV0ZXMoKTsKICAgIH0KICAgIC8qCiAgICAgIFJldHVybnMgYW4gb2JqZWN0LCB3aG9zZSBrZXlzIGFyZSBjaGFuZ2VkIHByb3BlcnRpZXMsIGFuZCB2YWx1ZSBpcyBhbgogICAgICBbb2xkUHJvcCwgbmV3UHJvcF0gYXJyYXkuCiAgICAgICBAbWV0aG9kIGNoYW5nZWRBdHRyaWJ1dGVzCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5jaGFuZ2VkQXR0cmlidXRlcyA9IGZ1bmN0aW9uIGNoYW5nZWRBdHRyaWJ1dGVzKCkgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgaWYgKCF0aGlzLl9fcmVjb3JkRGF0YSkgewogICAgICAgICAgLy8gbm8gbmVlZCB0byBjYWxjdWxhdGUgY2hhbmdlZCBhdHRyaWJ1dGVzIHdoZW4gY2FsbGluZyBgZmluZFJlY29yZGAKICAgICAgICAgIHJldHVybiB7fTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaWYgKHRoaXMuaXNMb2FkaW5nKCkgJiYgIXRoaXMuaXNSZWxvYWRpbmcpIHsKICAgICAgICAgIC8vIG5vIG5lZWQgdG8gY2FsY3VsYXRlIGNoYW5nZWQgYXR0cmlidXRlcyB3aGVuIGNhbGxpbmcgYGZpbmRSZWNvcmRgCiAgICAgICAgICByZXR1cm4ge307CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fcmVjb3JkRGF0YS5jaGFuZ2VkQXR0cmlidXRlcygpOwogICAgfQogICAgLyoKICAgICAgQG1ldGhvZCBhZGFwdGVyV2lsbENvbW1pdAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uYWRhcHRlcldpbGxDb21taXQgPSBmdW5jdGlvbiBhZGFwdGVyV2lsbENvbW1pdCgpIHsKICAgICAgdGhpcy5fcmVjb3JkRGF0YS53aWxsQ29tbWl0KCk7CgogICAgICB0aGlzLnNlbmQoJ3dpbGxDb21taXQnKTsKICAgIH0KICAgIC8qCiAgICAgIEBtZXRob2QgYWRhcHRlckRpZERpcnR5CiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5hZGFwdGVyRGlkRGlydHkgPSBmdW5jdGlvbiBhZGFwdGVyRGlkRGlydHkoKSB7CiAgICAgIHRoaXMuc2VuZCgnYmVjb21lRGlydHknKTsKICAgICAgdGhpcy51cGRhdGVSZWNvcmRBcnJheXMoKTsKICAgIH0KICAgIC8qCiAgICAgIEBtZXRob2Qgc2VuZAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge1N0cmluZ30gbmFtZQogICAgICBAcGFyYW0ge09iamVjdH0gY29udGV4dAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uc2VuZCA9IGZ1bmN0aW9uIHNlbmQobmFtZSwgY29udGV4dCkgewogICAgICB2YXIgY3VycmVudFN0YXRlID0gdGhpcy5jdXJyZW50U3RhdGU7CgogICAgICBpZiAoIWN1cnJlbnRTdGF0ZVtuYW1lXSkgewogICAgICAgIHRoaXMuX3VuaGFuZGxlZEV2ZW50KGN1cnJlbnRTdGF0ZSwgbmFtZSwgY29udGV4dCk7CiAgICAgIH0KCiAgICAgIHJldHVybiBjdXJyZW50U3RhdGVbbmFtZV0odGhpcywgY29udGV4dCk7CiAgICB9OwoKICAgIF9wcm90by5tYW55QXJyYXlSZWNvcmRBZGRlZCA9IGZ1bmN0aW9uIG1hbnlBcnJheVJlY29yZEFkZGVkKGtleSkgewogICAgICBpZiAodGhpcy5oYXNSZWNvcmQpIHsKICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICB0aGlzLnN0b3JlLl9ub3RpZmljYXRpb25NYW5hZ2VyLm5vdGlmeSh0aGlzLmlkZW50aWZpZXIsICdyZWxhdGlvbnNoaXBzJyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuX3JlY29yZC5ub3RpZnlIYXNNYW55QWRkZWQoa2V5KTsKICAgICAgICB9CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLm5vdGlmeUhhc01hbnlDaGFuZ2UgPSBmdW5jdGlvbiBub3RpZnlIYXNNYW55Q2hhbmdlKGtleSkgewogICAgICBpZiAodGhpcy5oYXNSZWNvcmQpIHsKICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICB0aGlzLnN0b3JlLl9ub3RpZmljYXRpb25NYW5hZ2VyLm5vdGlmeSh0aGlzLmlkZW50aWZpZXIsICdyZWxhdGlvbnNoaXBzJyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBtYW55QXJyYXkgPSB0aGlzLl9tYW55QXJyYXlDYWNoZVtrZXldOwoKICAgICAgICAgIGlmIChtYW55QXJyYXkpIHsKICAgICAgICAgICAgLy8gVE9ETzogdGhpcyB3aWxsICJyZXN1cnJlY3QiIHByZXZpb3VzbHkgdW5sb2FkZWQgcmVjb3JkcwogICAgICAgICAgICAvLyBzZWUgdGVzdCAnMTptYW55IGFzeW5jIHVubG9hZCBtYW55IHNpZGUnCiAgICAgICAgICAgIC8vICBpbiBgdGVzdHMvaW50ZWdyYXRpb24vcmVjb3Jkcy91bmxvYWQtdGVzdC5qc2AKICAgICAgICAgICAgLy8gIHByb2JhYmx5IHdlIGRvbid0IHdhbnQgdG8gcmV0cmlldmUgbGF0ZXN0IGVhZ2VybHkgd2hlbiBub3RpZnloYXNtYW55IGNoYW5nZWQKICAgICAgICAgICAgLy8gIGJ1dCByYXRoZXIgbGF6aWx5IHdoZW4gc29tZW9uZSBhY3R1YWxseSBhc2tzIGZvciBhIG1hbnlhcnJheQogICAgICAgICAgICAvLwogICAgICAgICAgICAvLyAgdGhhdCBzYWlkLCBhbHNvIG5vdCBjbGVhciB3aHkgd2UgaGF2ZW4ndCBtb3ZlZCB0aGlzIHRvIHJldGFpbmVkbWFueWFycmF5IHNvIG1heWJlIHRoYXQncyB0aGUgYml0IHRoYXQncyBqdXN0IG5vdCB3b3JraWduCiAgICAgICAgICAgIG1hbnlBcnJheS5yZXRyaWV2ZUxhdGVzdCgpOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgdGhpcy51cGRhdGVSZWNvcmRBcnJheXMoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ubm90aWZ5QmVsb25nc1RvQ2hhbmdlID0gZnVuY3Rpb24gbm90aWZ5QmVsb25nc1RvQ2hhbmdlKGtleSkgewogICAgICBpZiAodGhpcy5oYXNSZWNvcmQpIHsKICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICB0aGlzLnN0b3JlLl9ub3RpZmljYXRpb25NYW5hZ2VyLm5vdGlmeSh0aGlzLmlkZW50aWZpZXIsICdyZWxhdGlvbnNoaXBzJyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuX3JlY29yZC5ub3RpZnlCZWxvbmdzVG9DaGFuZ2Uoa2V5LCB0aGlzLl9yZWNvcmQpOwogICAgICAgIH0KCiAgICAgICAgdGhpcy51cGRhdGVSZWNvcmRBcnJheXMoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uaGFzTWFueVJlbW92YWxDaGVjayA9IGZ1bmN0aW9uIGhhc01hbnlSZW1vdmFsQ2hlY2soa2V5KSB7CiAgICAgIHZhciBtYW55QXJyYXkgPSB0aGlzLl9tYW55QXJyYXlDYWNoZVtrZXldIHx8IHRoaXMuX3JldGFpbmVkTWFueUFycmF5Q2FjaGVba2V5XTsKICAgICAgdmFyIGRpZFJlbW92ZVVubG9hZGVkTW9kZWwgPSBmYWxzZTsKCiAgICAgIGlmIChtYW55QXJyYXkpIHsKICAgICAgICBkaWRSZW1vdmVVbmxvYWRlZE1vZGVsID0gbWFueUFycmF5LnJlbW92ZVVubG9hZGVkSW50ZXJuYWxNb2RlbCgpOwoKICAgICAgICBpZiAodGhpcy5fbWFueUFycmF5Q2FjaGVba2V5XSAmJiBkaWRSZW1vdmVVbmxvYWRlZE1vZGVsKSB7CiAgICAgICAgICB0aGlzLl9yZXRhaW5lZE1hbnlBcnJheUNhY2hlW2tleV0gPSB0aGlzLl9tYW55QXJyYXlDYWNoZVtrZXldOwogICAgICAgICAgZGVsZXRlIHRoaXMuX21hbnlBcnJheUNhY2hlW2tleV07CiAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gZGlkUmVtb3ZlVW5sb2FkZWRNb2RlbDsKICAgIH07CgogICAgX3Byb3RvLm5vdGlmeVByb3BlcnR5Q2hhbmdlID0gZnVuY3Rpb24gbm90aWZ5UHJvcGVydHlDaGFuZ2Uoa2V5KSB7CiAgICAgIGlmICh0aGlzLmhhc1JlY29yZCkgewogICAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICAgIHRoaXMuc3RvcmUuX25vdGlmaWNhdGlvbk1hbmFnZXIubm90aWZ5KHRoaXMuaWRlbnRpZmllciwgJ3Byb3BlcnR5Jyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuX3JlY29yZC5ub3RpZnlQcm9wZXJ0eUNoYW5nZShrZXkpOwogICAgICAgIH0KCiAgICAgICAgdGhpcy51cGRhdGVSZWNvcmRBcnJheXMoKTsKICAgICAgfQoKICAgICAgaWYgKCFjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICB2YXIgbWFueUFycmF5ID0gdGhpcy5fbWFueUFycmF5Q2FjaGVba2V5XSB8fCB0aGlzLl9yZXRhaW5lZE1hbnlBcnJheUNhY2hlW2tleV07CgogICAgICAgIGlmIChtYW55QXJyYXkpIHsKICAgICAgICAgIHZhciBkaWRSZW1vdmVVbmxvYWRlZE1vZGVsID0gbWFueUFycmF5LnJlbW92ZVVubG9hZGVkSW50ZXJuYWxNb2RlbCgpOwoKICAgICAgICAgIGlmICh0aGlzLl9tYW55QXJyYXlDYWNoZVtrZXldICYmIGRpZFJlbW92ZVVubG9hZGVkTW9kZWwpIHsKICAgICAgICAgICAgdGhpcy5fcmV0YWluZWRNYW55QXJyYXlDYWNoZVtrZXldID0gdGhpcy5fbWFueUFycmF5Q2FjaGVba2V5XTsKICAgICAgICAgICAgZGVsZXRlIHRoaXMuX21hbnlBcnJheUNhY2hlW2tleV07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlTdGF0ZUNoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeVN0YXRlQ2hhbmdlKGtleSkgewoKICAgICAgaWYgKHRoaXMuaGFzUmVjb3JkKSB7CiAgICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgICAgdGhpcy5zdG9yZS5fbm90aWZpY2F0aW9uTWFuYWdlci5ub3RpZnkodGhpcy5pZGVudGlmaWVyLCAnc3RhdGUnKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKCFrZXkgfHwga2V5ID09PSAnaXNOZXcnKSB7CiAgICAgICAgICAgIHRoaXMuZ2V0UmVjb3JkKCkubm90aWZ5UHJvcGVydHlDaGFuZ2UoJ2lzTmV3Jyk7CiAgICAgICAgICB9CgogICAgICAgICAgaWYgKCFrZXkgfHwga2V5ID09PSAnaXNEZWxldGVkJykgewogICAgICAgICAgICB0aGlzLmdldFJlY29yZCgpLm5vdGlmeVByb3BlcnR5Q2hhbmdlKCdpc0RlbGV0ZWQnKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmICgha2V5IHx8IGtleSA9PT0gJ2lzRGVsZXRpb25Db21taXR0ZWQnKSB7CiAgICAgICAgdGhpcy51cGRhdGVSZWNvcmRBcnJheXMoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uZGlkQ3JlYXRlUmVjb3JkID0gZnVuY3Rpb24gZGlkQ3JlYXRlUmVjb3JkKCkgewogICAgICB0aGlzLl9yZWNvcmREYXRhLmNsaWVudERpZENyZWF0ZSgpOwogICAgfTsKCiAgICBfcHJvdG8ucm9sbGJhY2tBdHRyaWJ1dGVzID0gZnVuY3Rpb24gcm9sbGJhY2tBdHRyaWJ1dGVzKCkgewogICAgICB2YXIgZGlydHlLZXlzID0gdGhpcy5fcmVjb3JkRGF0YS5yb2xsYmFja0F0dHJpYnV0ZXMoKTsKCiAgICAgIGlmIChFbWJlci5nZXQodGhpcywgJ2lzRXJyb3InKSkgewogICAgICAgIHRoaXMuZGlkQ2xlYW5FcnJvcigpOwogICAgICB9CgogICAgICB0aGlzLnNlbmQoJ3JvbGxlZEJhY2snKTsKCiAgICAgIGlmICh0aGlzLl9yZWNvcmQgJiYgZGlydHlLZXlzICYmIGRpcnR5S2V5cy5sZW5ndGggPiAwKSB7CiAgICAgICAgdGhpcy5fcmVjb3JkLl9ub3RpZnlQcm9wZXJ0aWVzKGRpcnR5S2V5cyk7CiAgICAgIH0KICAgIH0KICAgIC8qCiAgICAgIEBtZXRob2QgdHJhbnNpdGlvblRvCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lCiAgICAqLwogICAgOwoKICAgIF9wcm90by50cmFuc2l0aW9uVG8gPSBmdW5jdGlvbiB0cmFuc2l0aW9uVG8obmFtZSkgewogICAgICAvLyBQT1NTSUJMRSBUT0RPOiBSZW1vdmUgdGhpcyBjb2RlIGFuZCByZXBsYWNlIHdpdGgKICAgICAgLy8gYWx3YXlzIGhhdmluZyBkaXJlY3QgcmVmZXJlbmNlIHRvIHN0YXRlIG9iamVjdHMKICAgICAgdmFyIHBpdm90TmFtZSA9IGV4dHJhY3RQaXZvdE5hbWUobmFtZSk7CiAgICAgIHZhciBzdGF0ZSA9IHRoaXMuY3VycmVudFN0YXRlOwogICAgICB2YXIgdHJhbnNpdGlvbk1hcElkID0gc3RhdGUuc3RhdGVOYW1lICsgIi0+IiArIG5hbWU7CgogICAgICBkbyB7CiAgICAgICAgaWYgKHN0YXRlLmV4aXQpIHsKICAgICAgICAgIHN0YXRlLmV4aXQodGhpcyk7CiAgICAgICAgfQoKICAgICAgICBzdGF0ZSA9IHN0YXRlLnBhcmVudFN0YXRlOwogICAgICB9IHdoaWxlICghc3RhdGVbcGl2b3ROYW1lXSk7CgogICAgICB2YXIgc2V0dXBzOwogICAgICB2YXIgZW50ZXJzOwogICAgICB2YXIgaTsKICAgICAgdmFyIGw7CiAgICAgIHZhciBtYXAgPSBUcmFuc2l0aW9uQ2hhaW5NYXBbdHJhbnNpdGlvbk1hcElkXTsKCiAgICAgIGlmIChtYXApIHsKICAgICAgICBzZXR1cHMgPSBtYXAuc2V0dXBzOwogICAgICAgIGVudGVycyA9IG1hcC5lbnRlcnM7CiAgICAgICAgc3RhdGUgPSBtYXAuc3RhdGU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgc2V0dXBzID0gW107CiAgICAgICAgZW50ZXJzID0gW107CiAgICAgICAgdmFyIHBhdGggPSBzcGxpdE9uRG90KG5hbWUpOwoKICAgICAgICBmb3IgKGkgPSAwLCBsID0gcGF0aC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgIHN0YXRlID0gc3RhdGVbcGF0aFtpXV07CgogICAgICAgICAgaWYgKHN0YXRlLmVudGVyKSB7CiAgICAgICAgICAgIGVudGVycy5wdXNoKHN0YXRlKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoc3RhdGUuc2V0dXApIHsKICAgICAgICAgICAgc2V0dXBzLnB1c2goc3RhdGUpOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgVHJhbnNpdGlvbkNoYWluTWFwW3RyYW5zaXRpb25NYXBJZF0gPSB7CiAgICAgICAgICBzZXR1cHM6IHNldHVwcywKICAgICAgICAgIGVudGVyczogZW50ZXJzLAogICAgICAgICAgc3RhdGU6IHN0YXRlCiAgICAgICAgfTsKICAgICAgfQoKICAgICAgZm9yIChpID0gMCwgbCA9IGVudGVycy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICBlbnRlcnNbaV0uZW50ZXIodGhpcyk7CiAgICAgIH0KCiAgICAgIHRoaXMuY3VycmVudFN0YXRlID0gc3RhdGU7CgogICAgICBpZiAodGhpcy5oYXNSZWNvcmQpIHsKICAgICAgICBFbWJlci5zZXQodGhpcy5fcmVjb3JkLCAnY3VycmVudFN0YXRlJywgc3RhdGUpOwogICAgICB9CgogICAgICBmb3IgKGkgPSAwLCBsID0gc2V0dXBzLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICAgIHNldHVwc1tpXS5zZXR1cCh0aGlzKTsKICAgICAgfQoKICAgICAgdGhpcy51cGRhdGVSZWNvcmRBcnJheXMoKTsKICAgIH07CgogICAgX3Byb3RvLl91bmhhbmRsZWRFdmVudCA9IGZ1bmN0aW9uIF91bmhhbmRsZWRFdmVudChzdGF0ZSwgbmFtZSwgY29udGV4dCkgewogICAgICB2YXIgZXJyb3JNZXNzYWdlID0gJ0F0dGVtcHRlZCB0byBoYW5kbGUgZXZlbnQgYCcgKyBuYW1lICsgJ2AgJzsKICAgICAgZXJyb3JNZXNzYWdlICs9ICdvbiAnICsgU3RyaW5nKHRoaXMpICsgJyB3aGlsZSBpbiBzdGF0ZSAnOwogICAgICBlcnJvck1lc3NhZ2UgKz0gc3RhdGUuc3RhdGVOYW1lICsgJy4gJzsKCiAgICAgIGlmIChjb250ZXh0ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBlcnJvck1lc3NhZ2UgKz0gJ0NhbGxlZCB3aXRoICcgKyBFbWJlci5pbnNwZWN0KGNvbnRleHQpICsgJy4nOwogICAgICB9CgogICAgICB0aHJvdyBuZXcgRW1iZXIuRXJyb3IoZXJyb3JNZXNzYWdlKTsKICAgIH07CgogICAgX3Byb3RvLnRyaWdnZXJMYXRlciA9IGZ1bmN0aW9uIHRyaWdnZXJMYXRlcigpIHsKICAgICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuX2RlZmVycmVkVHJpZ2dlcnMucHVzaChhcmdzKSAhPT0gMSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5zdG9yZS5fdXBkYXRlSW50ZXJuYWxNb2RlbCh0aGlzKTsKICAgIH07CgogICAgX3Byb3RvLl90cmlnZ2VyRGVmZXJyZWRUcmlnZ2VycyA9IGZ1bmN0aW9uIF90cmlnZ2VyRGVmZXJyZWRUcmlnZ2VycygpIHsKICAgICAgLy9UT0RPOiBCZWZvcmUgMS4wIHdlIHdhbnQgdG8gcmVtb3ZlIGFsbCB0aGUgZXZlbnRzIHRoYXQgaGFwcGVuIG9uIHRoZSBwcmUgbWF0ZXJpYWxpemVkIHJlY29yZCwKICAgICAgLy9idXQgZm9yIG5vdywgd2UgcXVldWUgdXAgYWxsIHRoZSBldmVudHMgdHJpZ2dlcmVkIGJlZm9yZSB0aGUgcmVjb3JkIHdhcyBtYXRlcmlhbGl6ZWQsIGFuZCBmbHVzaAogICAgICAvL3RoZW0gb25jZSB3ZSBoYXZlIHRoZSByZWNvcmQKICAgICAgaWYgKCF0aGlzLmhhc1JlY29yZCkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIHRyaWdnZXJzID0gdGhpcy5fZGVmZXJyZWRUcmlnZ2VyczsKICAgICAgdmFyIHJlY29yZCA9IHRoaXMuX3JlY29yZDsKICAgICAgdmFyIHRyaWdnZXIgPSByZWNvcmQudHJpZ2dlcjsgLy8gVE9ETyBJZ29yIG1ha2UgbmljZXIgY2hlY2sKCiAgICAgIGlmICh0cmlnZ2VyICYmIHR5cGVvZiB0cmlnZ2VyID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSB0cmlnZ2Vycy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgIHZhciBldmVudE5hbWUgPSB0cmlnZ2Vyc1tpXTsKICAgICAgICAgIHRyaWdnZXIuYXBwbHkocmVjb3JkLCBldmVudE5hbWUpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgdHJpZ2dlcnMubGVuZ3RoID0gMDsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZUZyb21JbnZlcnNlUmVsYXRpb25zaGlwcyA9IGZ1bmN0aW9uIHJlbW92ZUZyb21JbnZlcnNlUmVsYXRpb25zaGlwcyhpc05ldykgewogICAgICBpZiAoaXNOZXcgPT09IHZvaWQgMCkgewogICAgICAgIGlzTmV3ID0gZmFsc2U7CiAgICAgIH0KCiAgICAgIHRoaXMuX3JlY29yZERhdGEucmVtb3ZlRnJvbUludmVyc2VSZWxhdGlvbnNoaXBzKGlzTmV3KTsKICAgIH0KICAgIC8qCiAgICAgIFdoZW4gYSBmaW5kIHJlcXVlc3QgaXMgdHJpZ2dlcmVkIG9uIHRoZSBzdG9yZSwgdGhlIHVzZXIgY2FuIG9wdGlvbmFsbHkgcGFzcyBpbgogICAgICBhdHRyaWJ1dGVzIGFuZCByZWxhdGlvbnNoaXBzIHRvIGJlIHByZWxvYWRlZC4gVGhlc2UgYXJlIG1lYW50IHRvIGJlaGF2ZSBhcyBpZiB0aGV5CiAgICAgIGNhbWUgYmFjayBmcm9tIHRoZSBzZXJ2ZXIsIGV4Y2VwdCB0aGUgdXNlciBvYnRhaW5lZCB0aGVtIG91dCBvZiBiYW5kIGFuZCBpcyBpbmZvcm1pbmcKICAgICAgdGhlIHN0b3JlIG9mIHRoZWlyIGV4aXN0ZW5jZS4gVGhlIG1vc3QgY29tbW9uIHVzZSBjYXNlIGlzIGZvciBzdXBwb3J0aW5nIGNsaWVudCBzaWRlCiAgICAgIG5lc3RlZCBVUkxzLCBzdWNoIGFzIGAvcG9zdHMvMS9jb21tZW50cy8yYCBzbyB0aGUgdXNlciBjYW4gZG8KICAgICAgYHN0b3JlLmZpbmRSZWNvcmQoJ2NvbW1lbnQnLCAyLCB7IHByZWxvYWQ6IHsgcG9zdDogMSB9IH0pYCB3aXRob3V0IGhhdmluZyB0byBmZXRjaCB0aGUgcG9zdC4KICAgICAgIFByZWxvYWRlZCBkYXRhIGNhbiBiZSBhdHRyaWJ1dGVzIGFuZCByZWxhdGlvbnNoaXBzIHBhc3NlZCBpbiBlaXRoZXIgYXMgSURzIG9yIGFzIGFjdHVhbAogICAgICBtb2RlbHMuCiAgICAgICBAbWV0aG9kIHByZWxvYWREYXRhCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwcmVsb2FkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5wcmVsb2FkRGF0YSA9IGZ1bmN0aW9uIHByZWxvYWREYXRhKHByZWxvYWQpIHsKICAgICAgdmFyIF90aGlzNSA9IHRoaXM7CgogICAgICB2YXIganNvblBheWxvYWQgPSB7fTsgLy9UT0RPKElnb3IpIGNvbnNpZGVyIHRoZSBwb2x5bW9ycGhpYyBjYXNlCgogICAgICBPYmplY3Qua2V5cyhwcmVsb2FkKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICB2YXIgcHJlbG9hZFZhbHVlID0gRW1iZXIuZ2V0KHByZWxvYWQsIGtleSk7CgogICAgICAgIHZhciByZWxhdGlvbnNoaXBNZXRhID0gX3RoaXM1Lm1vZGVsQ2xhc3MubWV0YUZvclByb3BlcnR5KGtleSk7CgogICAgICAgIGlmIChyZWxhdGlvbnNoaXBNZXRhLmlzUmVsYXRpb25zaGlwKSB7CiAgICAgICAgICBpZiAoIWpzb25QYXlsb2FkLnJlbGF0aW9uc2hpcHMpIHsKICAgICAgICAgICAganNvblBheWxvYWQucmVsYXRpb25zaGlwcyA9IHt9OwogICAgICAgICAgfQoKICAgICAgICAgIGpzb25QYXlsb2FkLnJlbGF0aW9uc2hpcHNba2V5XSA9IF90aGlzNS5fcHJlbG9hZFJlbGF0aW9uc2hpcChrZXksIHByZWxvYWRWYWx1ZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmICghanNvblBheWxvYWQuYXR0cmlidXRlcykgewogICAgICAgICAgICBqc29uUGF5bG9hZC5hdHRyaWJ1dGVzID0ge307CiAgICAgICAgICB9CgogICAgICAgICAganNvblBheWxvYWQuYXR0cmlidXRlc1trZXldID0gcHJlbG9hZFZhbHVlOwogICAgICAgIH0KICAgICAgfSk7CgogICAgICB0aGlzLl9yZWNvcmREYXRhLnB1c2hEYXRhKGpzb25QYXlsb2FkKTsKICAgIH07CgogICAgX3Byb3RvLl9wcmVsb2FkUmVsYXRpb25zaGlwID0gZnVuY3Rpb24gX3ByZWxvYWRSZWxhdGlvbnNoaXAoa2V5LCBwcmVsb2FkVmFsdWUpIHsKICAgICAgdmFyIF90aGlzNiA9IHRoaXM7CgogICAgICB2YXIgcmVsYXRpb25zaGlwTWV0YSA9IHRoaXMubW9kZWxDbGFzcy5tZXRhRm9yUHJvcGVydHkoa2V5KTsKICAgICAgdmFyIG1vZGVsQ2xhc3MgPSByZWxhdGlvbnNoaXBNZXRhLnR5cGU7CiAgICAgIHZhciBkYXRhOwoKICAgICAgaWYgKHJlbGF0aW9uc2hpcE1ldGEua2luZCA9PT0gJ2hhc01hbnknKSB7CiAgICAgICAgZGF0YSA9IHByZWxvYWRWYWx1ZS5tYXAoZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gX3RoaXM2Ll9jb252ZXJ0UHJlbG9hZFJlbGF0aW9uc2hpcFRvSlNPTih2YWx1ZSwgbW9kZWxDbGFzcyk7CiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZGF0YSA9IHRoaXMuX2NvbnZlcnRQcmVsb2FkUmVsYXRpb25zaGlwVG9KU09OKHByZWxvYWRWYWx1ZSwgbW9kZWxDbGFzcyk7CiAgICAgIH0KCiAgICAgIHJldHVybiB7CiAgICAgICAgZGF0YTogZGF0YQogICAgICB9OwogICAgfTsKCiAgICBfcHJvdG8uX2NvbnZlcnRQcmVsb2FkUmVsYXRpb25zaGlwVG9KU09OID0gZnVuY3Rpb24gX2NvbnZlcnRQcmVsb2FkUmVsYXRpb25zaGlwVG9KU09OKHZhbHVlLCBtb2RlbENsYXNzKSB7CiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHsKICAgICAgICByZXR1cm4gewogICAgICAgICAgdHlwZTogbW9kZWxDbGFzcywKICAgICAgICAgIGlkOiB2YWx1ZQogICAgICAgIH07CiAgICAgIH0KCiAgICAgIHZhciBpbnRlcm5hbE1vZGVsOwoKICAgICAgaWYgKHZhbHVlLl9pbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbCA9IHZhbHVlLl9pbnRlcm5hbE1vZGVsOwogICAgICB9IGVsc2UgewogICAgICAgIGludGVybmFsTW9kZWwgPSB2YWx1ZTsKICAgICAgfSAvLyBUT0RPIElHT1IgREFWSUQgYXNzZXJ0IGlmIG5vIGlkIGlzIHByZXNlbnQKCgogICAgICByZXR1cm4gewogICAgICAgIHR5cGU6IGludGVybmFsTW9kZWwubW9kZWxOYW1lLAogICAgICAgIGlkOiBpbnRlcm5hbE1vZGVsLmlkCiAgICAgIH07CiAgICB9CiAgICAvKgogICAgICBVc2VkIHRvIG5vdGlmeSB0aGUgc3RvcmUgdG8gdXBkYXRlIEZpbHRlcmVkUmVjb3JkQXJyYXkgbWVtYmVyc2hpcC4KICAgICAgIEBtZXRob2QgdXBkYXRlUmVjb3JkQXJyYXlzCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by51cGRhdGVSZWNvcmRBcnJheXMgPSBmdW5jdGlvbiB1cGRhdGVSZWNvcmRBcnJheXMoKSB7CiAgICAgIC8vIEB0cy1pZ25vcmU6IFN0b3JlIGlzIHVudHlwZWQgYW5kIHR5cGVzY3JpcHQgZG9lcyBub3QgZGV0ZWN0IGluc3RhbmNlIHByb3BzIHNldCBpbiBgaW5pdGAKICAgICAgdGhpcy5zdG9yZS5yZWNvcmRBcnJheU1hbmFnZXIucmVjb3JkRGlkQ2hhbmdlKHRoaXMpOwogICAgfTsKCiAgICBfcHJvdG8uc2V0SWQgPSBmdW5jdGlvbiBzZXRJZChpZCkgewoKICAgICAgdmFyIGRpZENoYW5nZSA9IGlkICE9PSB0aGlzLl9pZDsKICAgICAgdGhpcy5faWQgPSBpZDsKCiAgICAgIGlmIChkaWRDaGFuZ2UgJiYgaWQgIT09IG51bGwpIHsKICAgICAgICB0aGlzLnN0b3JlLnNldFJlY29yZElkKHRoaXMubW9kZWxOYW1lLCBpZCwgdGhpcy5jbGllbnRJZCk7CiAgICAgIH0KCiAgICAgIGlmIChkaWRDaGFuZ2UgJiYgdGhpcy5oYXNSZWNvcmQpIHsKICAgICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgICB0aGlzLnN0b3JlLl9ub3RpZmljYXRpb25NYW5hZ2VyLm5vdGlmeSh0aGlzLmlkZW50aWZpZXIsICdpZGVudGl0eScpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLm5vdGlmeVByb3BlcnR5Q2hhbmdlKCdpZCcpOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uZGlkRXJyb3IgPSBmdW5jdGlvbiBkaWRFcnJvcihlcnJvcikgewogICAgICBpZiAoIWNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgICAgIHRoaXMuZXJyb3IgPSBlcnJvcjsKICAgICAgICB0aGlzLmlzRXJyb3IgPSB0cnVlOwoKICAgICAgICBpZiAodGhpcy5oYXNSZWNvcmQpIHsKICAgICAgICAgIHRoaXMuX3JlY29yZC5zZXRQcm9wZXJ0aWVzKHsKICAgICAgICAgICAgaXNFcnJvcjogdHJ1ZSwKICAgICAgICAgICAgYWRhcHRlckVycm9yOiBlcnJvcgogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5kaWRDbGVhbkVycm9yID0gZnVuY3Rpb24gZGlkQ2xlYW5FcnJvcigpIHsKICAgICAgaWYgKCFjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICB0aGlzLmVycm9yID0gbnVsbDsKICAgICAgICB0aGlzLmlzRXJyb3IgPSBmYWxzZTsKCiAgICAgICAgaWYgKHRoaXMuaGFzUmVjb3JkKSB7CiAgICAgICAgICB0aGlzLl9yZWNvcmQuc2V0UHJvcGVydGllcyh7CiAgICAgICAgICAgIGlzRXJyb3I6IGZhbHNlLAogICAgICAgICAgICBhZGFwdGVyRXJyb3I6IG51bGwKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgLyoKICAgICAgSWYgdGhlIGFkYXB0ZXIgZGlkIG5vdCByZXR1cm4gYSBoYXNoIGluIHJlc3BvbnNlIHRvIGEgY29tbWl0LAogICAgICBtZXJnZSB0aGUgY2hhbmdlZCBhdHRyaWJ1dGVzIGFuZCByZWxhdGlvbnNoaXBzIGludG8gdGhlIGV4aXN0aW5nCiAgICAgIHNhdmVkIGRhdGEuCiAgICAgICBAbWV0aG9kIGFkYXB0ZXJEaWRDb21taXQKICAgICovCiAgICA7CgogICAgX3Byb3RvLmFkYXB0ZXJEaWRDb21taXQgPSBmdW5jdGlvbiBhZGFwdGVyRGlkQ29tbWl0KGRhdGEpIHsKICAgICAgdGhpcy5kaWRDbGVhbkVycm9yKCk7CgogICAgICB2YXIgY2hhbmdlZEtleXMgPSB0aGlzLl9yZWNvcmREYXRhLmRpZENvbW1pdChkYXRhKTsKCiAgICAgIHRoaXMuc2VuZCgnZGlkQ29tbWl0Jyk7CiAgICAgIHRoaXMudXBkYXRlUmVjb3JkQXJyYXlzKCk7CgogICAgICBpZiAoIWRhdGEpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICB0aGlzLnN0b3JlLl9ub3RpZmljYXRpb25NYW5hZ2VyLm5vdGlmeSh0aGlzLmlkZW50aWZpZXIsICdhdHRyaWJ1dGVzJyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fcmVjb3JkLl9ub3RpZnlQcm9wZXJ0aWVzKGNoYW5nZWRLZXlzKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uYWRkRXJyb3JNZXNzYWdlVG9BdHRyaWJ1dGUgPSBmdW5jdGlvbiBhZGRFcnJvck1lc3NhZ2VUb0F0dHJpYnV0ZShhdHRyaWJ1dGUsIG1lc3NhZ2UpIHsKICAgICAgRW1iZXIuZ2V0KHRoaXMuZ2V0UmVjb3JkKCksICdlcnJvcnMnKS5fYWRkKGF0dHJpYnV0ZSwgbWVzc2FnZSk7CiAgICB9OwoKICAgIF9wcm90by5yZW1vdmVFcnJvck1lc3NhZ2VGcm9tQXR0cmlidXRlID0gZnVuY3Rpb24gcmVtb3ZlRXJyb3JNZXNzYWdlRnJvbUF0dHJpYnV0ZShhdHRyaWJ1dGUpIHsKICAgICAgRW1iZXIuZ2V0KHRoaXMuZ2V0UmVjb3JkKCksICdlcnJvcnMnKS5fcmVtb3ZlKGF0dHJpYnV0ZSk7CiAgICB9OwoKICAgIF9wcm90by5jbGVhckVycm9yTWVzc2FnZXMgPSBmdW5jdGlvbiBjbGVhckVycm9yTWVzc2FnZXMoKSB7CiAgICAgIEVtYmVyLmdldCh0aGlzLmdldFJlY29yZCgpLCAnZXJyb3JzJykuX2NsZWFyKCk7CiAgICB9OwoKICAgIF9wcm90by5oYXNFcnJvcnMgPSBmdW5jdGlvbiBoYXNFcnJvcnMoKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9FUlJPUlMpIHsKICAgICAgICBpZiAodGhpcy5fcmVjb3JkRGF0YS5nZXRFcnJvcnMpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9yZWNvcmREYXRhLmdldEVycm9ycyggdGhpcy5pZGVudGlmaWVyICkubGVuZ3RoID4gMDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFyIGVycm9ycyA9IEVtYmVyLmdldCh0aGlzLmdldFJlY29yZCgpLCAnZXJyb3JzJyk7CiAgICAgICAgICByZXR1cm4gZXJyb3JzLmdldCgnbGVuZ3RoJykgPiAwOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgX2Vycm9ycyA9IEVtYmVyLmdldCh0aGlzLmdldFJlY29yZCgpLCAnZXJyb3JzJyk7CgogICAgICAgIHJldHVybiBfZXJyb3JzLmdldCgnbGVuZ3RoJykgPiAwOwogICAgICB9CiAgICB9IC8vIEZPUiBVU0UgRFVSSU5HIENPTU1JVCBQUk9DRVNTCgogICAgLyoKICAgICAgQG1ldGhvZCBhZGFwdGVyRGlkSW52YWxpZGF0ZQogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uYWRhcHRlckRpZEludmFsaWRhdGUgPSBmdW5jdGlvbiBhZGFwdGVyRGlkSW52YWxpZGF0ZShwYXJzZWRFcnJvcnMsIGVycm9yKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRUNPUkRfREFUQV9FUlJPUlMpIHsKICAgICAgICB2YXIgYXR0cmlidXRlOwoKICAgICAgICBpZiAoZXJyb3IgJiYgcGFyc2VkRXJyb3JzKSB7CiAgICAgICAgICBpZiAoIXRoaXMuX3JlY29yZERhdGEuZ2V0RXJyb3JzKSB7CiAgICAgICAgICAgIGZvciAoYXR0cmlidXRlIGluIHBhcnNlZEVycm9ycykgewogICAgICAgICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKHBhcnNlZEVycm9ycywgYXR0cmlidXRlKSkgewogICAgICAgICAgICAgICAgdGhpcy5hZGRFcnJvck1lc3NhZ2VUb0F0dHJpYnV0ZShhdHRyaWJ1dGUsIHBhcnNlZEVycm9yc1thdHRyaWJ1dGVdKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KCiAgICAgICAgICB2YXIganNvbkFwaUVycm9ycyA9IGVycm9yc0hhc2hUb0FycmF5KHBhcnNlZEVycm9ycyk7CiAgICAgICAgICB0aGlzLnNlbmQoJ2JlY2FtZUludmFsaWQnKTsKCiAgICAgICAgICBpZiAoanNvbkFwaUVycm9ycy5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAganNvbkFwaUVycm9ycyA9IFt7CiAgICAgICAgICAgICAgdGl0bGU6ICdJbnZhbGlkIEVycm9yJywKICAgICAgICAgICAgICBkZXRhaWw6ICcnLAogICAgICAgICAgICAgIHNvdXJjZTogewogICAgICAgICAgICAgICAgcG9pbnRlcjogJy9kYXRhJwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfV07CiAgICAgICAgICB9CgogICAgICAgICAgdGhpcy5fcmVjb3JkRGF0YS5jb21taXRXYXNSZWplY3RlZCggdGhpcy5pZGVudGlmaWVyICwganNvbkFwaUVycm9ycyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuc2VuZCgnYmVjYW1lRXJyb3InKTsKCiAgICAgICAgICB0aGlzLl9yZWNvcmREYXRhLmNvbW1pdFdhc1JlamVjdGVkKCB0aGlzLmlkZW50aWZpZXIgKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIF9hdHRyaWJ1dGU7CgogICAgICAgIGZvciAoX2F0dHJpYnV0ZSBpbiBwYXJzZWRFcnJvcnMpIHsKICAgICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKHBhcnNlZEVycm9ycywgX2F0dHJpYnV0ZSkpIHsKICAgICAgICAgICAgdGhpcy5hZGRFcnJvck1lc3NhZ2VUb0F0dHJpYnV0ZShfYXR0cmlidXRlLCBwYXJzZWRFcnJvcnNbX2F0dHJpYnV0ZV0pOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgdGhpcy5zZW5kKCdiZWNhbWVJbnZhbGlkJyk7CgogICAgICAgIHRoaXMuX3JlY29yZERhdGEuY29tbWl0V2FzUmVqZWN0ZWQoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ubm90aWZ5RXJyb3JzQ2hhbmdlID0gZnVuY3Rpb24gbm90aWZ5RXJyb3JzQ2hhbmdlKCkgewogICAgICB2YXIgaW52YWxpZEVycm9yczsKCiAgICAgIGlmICh0aGlzLl9yZWNvcmREYXRhLmdldEVycm9ycykgewogICAgICAgIGludmFsaWRFcnJvcnMgPSB0aGlzLl9yZWNvcmREYXRhLmdldEVycm9ycyggdGhpcy5pZGVudGlmaWVyICkgfHwgW107CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLm5vdGlmeUludmFsaWRFcnJvcnNDaGFuZ2UoaW52YWxpZEVycm9ycyk7CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlJbnZhbGlkRXJyb3JzQ2hhbmdlID0gZnVuY3Rpb24gbm90aWZ5SW52YWxpZEVycm9yc0NoYW5nZShqc29uQXBpRXJyb3JzKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICB0aGlzLnN0b3JlLl9ub3RpZmljYXRpb25NYW5hZ2VyLm5vdGlmeSh0aGlzLmlkZW50aWZpZXIsICdlcnJvcnMnKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLmdldFJlY29yZCgpLmludmFsaWRFcnJvcnNDaGFuZ2VkKGpzb25BcGlFcnJvcnMpOwogICAgICB9CiAgICB9CiAgICAvKgogICAgICBAbWV0aG9kIGFkYXB0ZXJEaWRFcnJvcgogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uYWRhcHRlckRpZEVycm9yID0gZnVuY3Rpb24gYWRhcHRlckRpZEVycm9yKGVycm9yKSB7CiAgICAgIHRoaXMuc2VuZCgnYmVjYW1lRXJyb3InKTsKICAgICAgdGhpcy5kaWRFcnJvcihlcnJvcik7CgogICAgICB0aGlzLl9yZWNvcmREYXRhLmNvbW1pdFdhc1JlamVjdGVkKCk7CiAgICB9OwoKICAgIF9wcm90by50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gIjwiICsgdGhpcy5tb2RlbE5hbWUgKyAiOiIgKyB0aGlzLmlkICsgIj4iOwogICAgfTsKCiAgICBfcHJvdG8ucmVmZXJlbmNlRm9yID0gZnVuY3Rpb24gcmVmZXJlbmNlRm9yKGtpbmQsIG5hbWUpIHsKICAgICAgdmFyIHJlZmVyZW5jZSA9IHRoaXMucmVmZXJlbmNlc1tuYW1lXTsKCiAgICAgIGlmICghcmVmZXJlbmNlKSB7CiAgICAgICAgLy8gVE9ETyBJR09SIEFORCBEQVZJRCBSRUZBQ1RPUgogICAgICAgIHZhciByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXBTdGF0ZUZvciQxKHRoaXMsIG5hbWUpOwoKICAgICAgICB2YXIgcmVsYXRpb25zaGlwS2luZCA9IHJlbGF0aW9uc2hpcC5yZWxhdGlvbnNoaXBNZXRhLmtpbmQ7CgogICAgICAgIGlmIChyZWxhdGlvbnNoaXBLaW5kID09PSAnYmVsb25nc1RvJykgewogICAgICAgICAgcmVmZXJlbmNlID0gbmV3IEJlbG9uZ3NUb1JlZmVyZW5jZSh0aGlzLnN0b3JlLCB0aGlzLCByZWxhdGlvbnNoaXAsIG5hbWUpOwogICAgICAgIH0gZWxzZSBpZiAocmVsYXRpb25zaGlwS2luZCA9PT0gJ2hhc01hbnknKSB7CiAgICAgICAgICByZWZlcmVuY2UgPSBuZXcgSGFzTWFueVJlZmVyZW5jZSh0aGlzLnN0b3JlLCB0aGlzLCByZWxhdGlvbnNoaXAsIG5hbWUpOwogICAgICAgIH0KCiAgICAgICAgdGhpcy5yZWZlcmVuY2VzW25hbWVdID0gcmVmZXJlbmNlOwogICAgICB9CgogICAgICByZXR1cm4gcmVmZXJlbmNlOwogICAgfTsKCiAgICBfY3JlYXRlQ2xhc3MkMyhJbnRlcm5hbE1vZGVsLCBbewogICAgICBrZXk6ICJpZCIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHsKICAgICAgICAgIHJldHVybiB0aGlzLmlkZW50aWZpZXIuaWQ7IC8vIHx8IHRoaXMuX2lkOwogICAgICAgIH0KICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQodmFsdWUpIHsKICAgICAgICB7CiAgICAgICAgICBpZiAodmFsdWUgIT09IHRoaXMuX2lkKSB7CiAgICAgICAgICAgIHZhciBuZXdJZGVudGlmaWVyID0gewogICAgICAgICAgICAgIHR5cGU6IHRoaXMuaWRlbnRpZmllci50eXBlLAogICAgICAgICAgICAgIGxpZDogdGhpcy5pZGVudGlmaWVyLmxpZCwKICAgICAgICAgICAgICBpZDogdmFsdWUKICAgICAgICAgICAgfTsKICAgICAgICAgICAgaWRlbnRpZmllckNhY2hlRm9yKHRoaXMuc3RvcmUpLnVwZGF0ZVJlY29yZElkZW50aWZpZXIodGhpcy5pZGVudGlmaWVyLCBuZXdJZGVudGlmaWVyKTsgLy8gVE9ETyBTaG93IGRlcHJlY2F0aW9uIGZvciBwcml2YXRlIGFwaQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJtb2RlbENsYXNzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgaWYgKHRoaXMuc3RvcmUubW9kZWxGb3IpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9tb2RlbENsYXNzIHx8ICh0aGlzLl9tb2RlbENsYXNzID0gdGhpcy5zdG9yZS5tb2RlbEZvcih0aGlzLm1vZGVsTmFtZSkpOwogICAgICAgIH0KICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJ0eXBlIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMubW9kZWxDbGFzczsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJyZWNvcmRSZWZlcmVuY2UiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fcmVjb3JkUmVmZXJlbmNlID09PSBudWxsKSB7CiAgICAgICAgICB0aGlzLl9yZWNvcmRSZWZlcmVuY2UgPSBuZXcgUmVjb3JkUmVmZXJlbmNlKHRoaXMuc3RvcmUsIHRoaXMpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMuX3JlY29yZFJlZmVyZW5jZTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJfcmVjb3JkRGF0YSIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIGlmICh0aGlzLl9fcmVjb3JkRGF0YSA9PT0gbnVsbCkgewogICAgICAgICAgdmFyIHJlY29yZERhdGEgPSB0aGlzLnN0b3JlLl9jcmVhdGVSZWNvcmREYXRhKHRoaXMuaWRlbnRpZmllcik7CgogICAgICAgICAgdGhpcy5fcmVjb3JkRGF0YSA9IHJlY29yZERhdGE7CiAgICAgICAgICByZXR1cm4gcmVjb3JkRGF0YTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9fcmVjb3JkRGF0YTsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiBzZXQobmV3VmFsdWUpIHsKICAgICAgICB0aGlzLl9fcmVjb3JkRGF0YSA9IG5ld1ZhbHVlOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogIl9yZWNvcmRBcnJheXMiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fX3JlY29yZEFycmF5cyA9PT0gbnVsbCkgewogICAgICAgICAgdGhpcy5fX3JlY29yZEFycmF5cyA9IG5ldyBTZXQoKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9fcmVjb3JkQXJyYXlzOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInJlZmVyZW5jZXMiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fcmVmZXJlbmNlcyA9PT0gbnVsbCkgewogICAgICAgICAgdGhpcy5fcmVmZXJlbmNlcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fcmVmZXJlbmNlczsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJfZGVmZXJyZWRUcmlnZ2VycyIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIGlmICh0aGlzLl9fZGVmZXJyZWRUcmlnZ2VycyA9PT0gbnVsbCkgewogICAgICAgICAgdGhpcy5fX2RlZmVycmVkVHJpZ2dlcnMgPSBbXTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzLl9fZGVmZXJyZWRUcmlnZ2VyczsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJpc0Rlc3Ryb3llZCIsCiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICAgIHJldHVybiB0aGlzLl9pc0Rlc3Ryb3llZDsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJoYXNSZWNvcmQiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gISF0aGlzLl9yZWNvcmQ7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gSW50ZXJuYWxNb2RlbDsKICB9KCk7CgogIGZ1bmN0aW9uIGhhbmRsZUNvbXBsZXRlZFJlbGF0aW9uc2hpcFJlcXVlc3QoaW50ZXJuYWxNb2RlbCwga2V5LCByZWxhdGlvbnNoaXAsIHZhbHVlLCBlcnJvcikgewogICAgZGVsZXRlIGludGVybmFsTW9kZWwuX3JlbGF0aW9uc2hpcFByb21pc2VzQ2FjaGVba2V5XTsKICAgIHJlbGF0aW9uc2hpcC5zZXRTaG91bGRGb3JjZVJlbG9hZChmYWxzZSk7CgogICAgaWYgKGVycm9yKSB7CiAgICAgIHJlbGF0aW9uc2hpcC5zZXRIYXNGYWlsZWRMb2FkQXR0ZW1wdCh0cnVlKTsKICAgICAgdmFyIHByb3h5ID0gaW50ZXJuYWxNb2RlbC5fcmVsYXRpb25zaGlwUHJveHlDYWNoZVtrZXldOyAvLyBiZWxvbmdzVG8gcmVsYXRpb25zaGlwcyBhcmUgc29tZXRpbWVzIHVubG9hZGVkCiAgICAgIC8vIHdoZW4gYSBsb2FkIGZhaWxzLCBpbiB0aGlzIGNhc2Ugd2UgbmVlZAogICAgICAvLyB0byBtYWtlIHN1cmUgdGhhdCB3ZSBhcmVuJ3QgcHJveHlpbmcKICAgICAgLy8gdG8gZGVzdHJveWVkIGNvbnRlbnQKICAgICAgLy8gZm9yIHRoZSBzeW5jIGJlbG9uZ3NUbyByZWxvYWQgY2FzZSB0aGVyZSB3aWxsIGJlIG5vIHByb3h5CiAgICAgIC8vIGZvciB0aGUgYXN5bmMgcmVsb2FkIGNhc2UgdGhlcmUgd2lsbCBiZSBubyBwcm94eSBpZiB0aGUgdWkKICAgICAgLy8gaGFzIG5ldmVyIGJlZW4gYWNjZXNzZWQKCiAgICAgIGlmIChwcm94eSAmJiByZWxhdGlvbnNoaXAua2luZCA9PT0gJ2JlbG9uZ3NUbycpIHsKICAgICAgICBpZiAocHJveHkuY29udGVudCAmJiBwcm94eS5jb250ZW50LmlzRGVzdHJveWluZykgewogICAgICAgICAgcHJveHkuc2V0KCdjb250ZW50JywgbnVsbCk7CiAgICAgICAgfQogICAgICB9CgogICAgICB0aHJvdyBlcnJvcjsKICAgIH0KCiAgICByZWxhdGlvbnNoaXAuc2V0SGFzRmFpbGVkTG9hZEF0dGVtcHQoZmFsc2UpOyAvLyBvbmx5IHNldCB0byBub3Qgc3RhbGUgaWYgbm8gZXJyb3IgaXMgdGhyb3duCgogICAgcmVsYXRpb25zaGlwLnNldFJlbGF0aW9uc2hpcElzU3RhbGUoZmFsc2UpOwogICAgcmV0dXJuIHZhbHVlOwogIH0KICBmdW5jdGlvbiBleHRyYWN0UmVjb3JkRGF0YXNGcm9tUmVjb3JkcyhyZWNvcmRzKSB7CiAgICByZXR1cm4gcmVjb3Jkcy5tYXAoZXh0cmFjdFJlY29yZERhdGFGcm9tUmVjb3JkKTsKICB9CiAgZnVuY3Rpb24gZXh0cmFjdFJlY29yZERhdGFGcm9tUmVjb3JkKHJlY29yZE9yUHJvbWlzZVJlY29yZCkgewogICAgaWYgKCFyZWNvcmRPclByb21pc2VSZWNvcmQpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CgogICAgaWYgKHJlY29yZE9yUHJvbWlzZVJlY29yZC50aGVuKSB7CiAgICAgIHZhciBjb250ZW50ID0gcmVjb3JkT3JQcm9taXNlUmVjb3JkLmdldCAmJiByZWNvcmRPclByb21pc2VSZWNvcmQuZ2V0KCdjb250ZW50Jyk7CiAgICAgIHJldHVybiBjb250ZW50ID8gcmVjb3JkRGF0YUZvcihjb250ZW50KSA6IG51bGw7CiAgICB9CgogICAgcmV0dXJuIHJlY29yZERhdGFGb3IocmVjb3JkT3JQcm9taXNlUmVjb3JkKTsKICB9CgogIGZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0aWVzJDQodGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoInZhbHVlIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0KCiAgZnVuY3Rpb24gX2NyZWF0ZUNsYXNzJDQoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQ0KENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMkNChDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH0KCiAgLyoqCiAgICBAbW9kdWxlIEBlbWJlci1kYXRhL3N0b3JlCiAgKi8KCiAgLyoqCiAgIGBJbnRlcm5hbE1vZGVsTWFwYCBpcyBhIGN1c3RvbSBzdG9yYWdlIG1hcCBmb3IgaW50ZXJuYWxNb2RlbHMgb2YgYSBnaXZlbiBtb2RlbE5hbWUKICAgdXNlZCBieSBgSWRlbnRpdHlNYXBgLgoKICAgSXQgd2FzIGV4dHJhY3RlZCBmcm9tIGFuIGltcGxpY2l0IHBvam8gYmFzZWQgImludGVybmFsTW9kZWwgbWFwIiBhbmQgcHJlc2VydmVzCiAgIHRoYXQgaW50ZXJmYWNlIHdoaWxlIHdlIHdvcmsgdG93YXJkcyBhIG1vcmUgb2ZmaWNpYWwgQVBJLgoKICAgQGNsYXNzIEludGVybmFsTW9kZWxNYXAKICAgQHByaXZhdGUKICAgKi8KICB2YXIgSW50ZXJuYWxNb2RlbE1hcCA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIEludGVybmFsTW9kZWxNYXAobW9kZWxOYW1lKSB7CiAgICAgIHRoaXMubW9kZWxOYW1lID0gbW9kZWxOYW1lOwogICAgICB0aGlzLl9pZFRvTW9kZWwgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9tb2RlbHMgPSBbXTsKICAgICAgdGhpcy5fbWV0YWRhdGEgPSBudWxsOwogICAgfQogICAgLyoqCiAgICAgKiBAbWV0aG9kIGdldAogICAgICogQHBhcmFtIGlkIHtTdHJpbmd9CiAgICAgKiBAcmV0dXJuIHtJbnRlcm5hbE1vZGVsfQogICAgICovCgoKICAgIHZhciBfcHJvdG8gPSBJbnRlcm5hbE1vZGVsTWFwLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uZ2V0ID0gZnVuY3Rpb24gZ2V0KGlkKSB7CiAgICAgIHJldHVybiB0aGlzLl9pZFRvTW9kZWxbaWRdIHx8IG51bGw7CiAgICB9OwoKICAgIF9wcm90by5oYXMgPSBmdW5jdGlvbiBoYXMoaWQpIHsKICAgICAgcmV0dXJuICEhdGhpcy5faWRUb01vZGVsW2lkXTsKICAgIH07CgogICAgX3Byb3RvLnNldCA9IGZ1bmN0aW9uIHNldChpZCwgaW50ZXJuYWxNb2RlbCkgewogICAgICB0aGlzLl9pZFRvTW9kZWxbaWRdID0gaW50ZXJuYWxNb2RlbDsKICAgIH07CgogICAgX3Byb3RvLmFkZCA9IGZ1bmN0aW9uIGFkZChpbnRlcm5hbE1vZGVsLCBpZCkgewoKICAgICAgaWYgKGlkKSB7CiAgICAgICAgdGhpcy5faWRUb01vZGVsW2lkXSA9IGludGVybmFsTW9kZWw7CiAgICAgIH0KCiAgICAgIHRoaXMuX21vZGVscy5wdXNoKGludGVybmFsTW9kZWwpOwogICAgfTsKCiAgICBfcHJvdG8ucmVtb3ZlID0gZnVuY3Rpb24gcmVtb3ZlKGludGVybmFsTW9kZWwsIGlkKSB7CiAgICAgIGRlbGV0ZSB0aGlzLl9pZFRvTW9kZWxbaWRdOwoKICAgICAgdmFyIGxvYyA9IHRoaXMuX21vZGVscy5pbmRleE9mKGludGVybmFsTW9kZWwpOwoKICAgICAgaWYgKGxvYyAhPT0gLTEpIHsKICAgICAgICB0aGlzLl9tb2RlbHMuc3BsaWNlKGxvYywgMSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmNvbnRhaW5zID0gZnVuY3Rpb24gY29udGFpbnMoaW50ZXJuYWxNb2RlbCkgewogICAgICByZXR1cm4gdGhpcy5fbW9kZWxzLmluZGV4T2YoaW50ZXJuYWxNb2RlbCkgIT09IC0xOwogICAgfQogICAgLyoqCiAgICAgQW4gYXJyYXkgb2YgYWxsIG1vZGVscyBvZiB0aGlzIG1vZGVsTmFtZQogICAgIEBwcm9wZXJ0eSBtb2RlbHMKICAgICBAdHlwZSBBcnJheQogICAgICovCiAgICA7CgogICAgLyoqCiAgICAgRGVzdHJveSBhbGwgbW9kZWxzIGluIHRoZSBpbnRlcm5hbE1vZGVsVGVzdCBhbmQgd2lwZSBtZXRhZGF0YS4KICAgICAgQG1ldGhvZCBjbGVhcgogICAgICovCiAgICBfcHJvdG8uY2xlYXIgPSBmdW5jdGlvbiBjbGVhcigpIHsKICAgICAgdmFyIGludGVybmFsTW9kZWxzID0gdGhpcy5fbW9kZWxzOwogICAgICB0aGlzLl9tb2RlbHMgPSBbXTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW50ZXJuYWxNb2RlbHMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxzW2ldOwogICAgICAgIGludGVybmFsTW9kZWwudW5sb2FkUmVjb3JkKCk7CiAgICAgIH0KCiAgICAgIHRoaXMuX21ldGFkYXRhID0gbnVsbDsKICAgIH07CgogICAgX2NyZWF0ZUNsYXNzJDQoSW50ZXJuYWxNb2RlbE1hcCwgW3sKICAgICAga2V5OiAibGVuZ3RoIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX21vZGVscy5sZW5ndGg7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAibW9kZWxzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX21vZGVsczsKICAgICAgfQogICAgICAvKioKICAgICAgICogbWV0YSBpbmZvcm1hdGlvbiBhYm91dCBpbnRlcm5hbE1vZGVscwogICAgICAgKiBAcHJvcGVydHkgbWV0YWRhdGEKICAgICAgICogQHR5cGUgT2JqZWN0CiAgICAgICAqLwoKICAgIH0sIHsKICAgICAga2V5OiAibWV0YWRhdGEiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5fbWV0YWRhdGEgfHwgKHRoaXMuX21ldGFkYXRhID0gT2JqZWN0LmNyZWF0ZShudWxsKSk7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gSW50ZXJuYWxNb2RlbE1hcDsKICB9KCk7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIC8qKgogICBgSWRlbnRpdHlNYXBgIGlzIGEgY3VzdG9tIHN0b3JhZ2UgbWFwIGZvciByZWNvcmRzIGJ5IG1vZGVsTmFtZQogICB1c2VkIGJ5IGBTdG9yZWAuCgogICBAY2xhc3MgSWRlbnRpdHlNYXAKICAgQHByaXZhdGUKICAgKi8KICB2YXIgSWRlbnRpdHlNYXAgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBJZGVudGl0eU1hcCgpIHsKICAgICAgdGhpcy5fbWFwID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gSWRlbnRpdHlNYXAucHJvdG90eXBlOwoKICAgIC8qKgogICAgIFJldHJpZXZlcyB0aGUgYEludGVybmFsTW9kZWxNYXBgIGZvciBhIGdpdmVuIG1vZGVsTmFtZSwKICAgICBjcmVhdGluZyBvbmUgaWYgb25lIGRpZCBub3QgYWxyZWFkeSBleGlzdC4gVGhpcyBpcwogICAgIHNpbWlsYXIgdG8gYGdldFdpdGhEZWZhdWx0YCBvciBgZ2V0YCBvbiBhIGBNYXBXaXRoRGVmYXVsdGAKICAgICAgQG1ldGhvZCByZXRyaWV2ZQogICAgIEBwYXJhbSBtb2RlbE5hbWUgYSBwcmV2aW91c2x5IG5vcm1hbGl6ZWQgbW9kZWxOYW1lCiAgICAgQHJldHVybiB7SW50ZXJuYWxNb2RlbE1hcH0gdGhlIEludGVybmFsTW9kZWxNYXAgZm9yIHRoZSBnaXZlbiBtb2RlbE5hbWUKICAgICAqLwogICAgX3Byb3RvLnJldHJpZXZlID0gZnVuY3Rpb24gcmV0cmlldmUobW9kZWxOYW1lKSB7CiAgICAgIHZhciBtYXAgPSB0aGlzLl9tYXBbbW9kZWxOYW1lXTsKCiAgICAgIGlmIChtYXAgPT09IHVuZGVmaW5lZCkgewogICAgICAgIG1hcCA9IHRoaXMuX21hcFttb2RlbE5hbWVdID0gbmV3IEludGVybmFsTW9kZWxNYXAobW9kZWxOYW1lKTsKICAgICAgfQoKICAgICAgcmV0dXJuIG1hcDsKICAgIH0KICAgIC8qKgogICAgIENsZWFycyB0aGUgY29udGVudHMgb2YgYWxsIGtub3duIGBSZWNvcmRNYXBzYCwgYnV0IGRvZXMKICAgICBub3QgcmVtb3ZlIHRoZSBJbnRlcm5hbE1vZGVsTWFwIGluc3RhbmNlcy4KICAgICAgQG1ldGhvZCBjbGVhcgogICAgICovCiAgICA7CgogICAgX3Byb3RvLmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7CiAgICAgIHZhciBtYXAgPSB0aGlzLl9tYXA7CiAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMobWFwKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBrZXkgPSBrZXlzW2ldOwogICAgICAgIG1hcFtrZXldLmNsZWFyKCk7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIElkZW50aXR5TWFwOwogIH0oKTsKCiAgZnVuY3Rpb24gY29uc3RydWN0UmVzb3VyY2UodHlwZSwgaWQsIGxpZCkgewogICAgdmFyIHRydWVJZCA9IGNvZXJjZUlkKGlkKTsKCiAgICBpZiAoIWlzTm9uRW1wdHlTdHJpbmcodHJ1ZUlkKSkgewogICAgICBpZiAoaXNOb25FbXB0eVN0cmluZyhsaWQpKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHR5cGU6IHR5cGUsCiAgICAgICAgICBpZDogdHJ1ZUlkLAogICAgICAgICAgbGlkOiBsaWQKICAgICAgICB9OwogICAgICB9CgogICAgICB0aHJvdyBuZXcgRXJyb3IoIkV4cGVjdGVkIGVpdGhlciBpZCBvciBsaWQgdG8gYmUgYSB2YWxpZCBzdHJpbmciKTsKICAgIH0KCiAgICBpZiAoaXNOb25FbXB0eVN0cmluZyhsaWQpKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgdHlwZTogdHlwZSwKICAgICAgICBpZDogdHJ1ZUlkLAogICAgICAgIGxpZDogbGlkCiAgICAgIH07CiAgICB9CgogICAgcmV0dXJuIHsKICAgICAgdHlwZTogdHlwZSwKICAgICAgaWQ6IHRydWVJZAogICAgfTsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIHZhciBGYWN0b3J5Q2FjaGUgPSBuZXcgV2Vha01hcCgpOwogIHZhciBSZWNvcmRDYWNoZSA9IG5ldyBXZWFrTWFwKCk7CiAgZnVuY3Rpb24gcGVla1JlY29yZElkZW50aWZpZXIocmVjb3JkKSB7CiAgICByZXR1cm4gUmVjb3JkQ2FjaGUuZ2V0KHJlY29yZCk7CiAgfQogIGZ1bmN0aW9uIHJlY29yZElkZW50aWZpZXJGb3IocmVjb3JkKSB7CiAgICB2YXIgaWRlbnRpZmllciA9IFJlY29yZENhY2hlLmdldChyZWNvcmQpOwoKICAgIHJldHVybiBpZGVudGlmaWVyOwogIH0KICBmdW5jdGlvbiBzZXRSZWNvcmRJZGVudGlmaWVyKHJlY29yZCwgaWRlbnRpZmllcikgewogICAgLyoKICAgIEl0IHdvdWxkIGJlIG5pY2UgdG8gZG8gYSByZXZlcnNlIGNoZWNrIGhlcmUgdGhhdCBhbiBpZGVudGlmaWVyIGhhcyBub3QKICAgIHByZXZpb3VzbHkgYmVlbiBhc3NpZ25lZCBhIHJlY29yZDsgaG93ZXZlciwgdW5sb2FkICsgcmVtYXRlcmlhbGl6YXRpb24KICAgIHByZXZlbnRzIHVzIGZyb20gaGF2aW5nIGEgZ3JlYXQgd2F5IG9mIGRvaW5nIHNvIHdoZW4gQ3VzdG9tUmVjb3JkQ2xhc3NlcwogICAgZG9uJ3QgbmVjZXNzYXJpbHkgZ2l2ZSB1cyBhY2Nlc3MgdG8gYSBgaXNEZXN0cm95ZWRgIGZvciBkZW1hdGVyaWFsaXplZAogICAgaW5zdGFuY2UuCiAgICAqLwoKCiAgICBSZWNvcmRDYWNoZS5zZXQocmVjb3JkLCBpZGVudGlmaWVyKTsKICB9CiAgZnVuY3Rpb24gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3Ioc3RvcmUpIHsKICAgIHZhciBmYWN0b3J5ID0gRmFjdG9yeUNhY2hlLmdldChzdG9yZSk7CgogICAgaWYgKGZhY3RvcnkgPT09IHVuZGVmaW5lZCkgewogICAgICBmYWN0b3J5ID0gbmV3IEludGVybmFsTW9kZWxGYWN0b3J5KHN0b3JlKTsKICAgICAgRmFjdG9yeUNhY2hlLnNldChzdG9yZSwgZmFjdG9yeSk7CiAgICB9CgogICAgcmV0dXJuIGZhY3Rvcnk7CiAgfQogIC8qKgogICAqIFRoZSBJbnRlcm5hbE1vZGVsRmFjdG9yeSBoYW5kbGVzIHRoZSBsaWZlY3lsZSBvZgogICAqIGluc3RhbnRpYXRpbmcsIGNhY2hpbmcsIGFuZCBkZXN0cm95aW5nIEludGVybmFsTW9kZWwKICAgKiBpbnN0YW5jZXMuCiAgICoKICAgKiBAaW50ZXJuYWwKICAgKi8KCiAgdmFyIEludGVybmFsTW9kZWxGYWN0b3J5ID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gSW50ZXJuYWxNb2RlbEZhY3Rvcnkoc3RvcmUpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHRoaXMuc3RvcmUgPSBzdG9yZTsKICAgICAgdGhpcy5faWRlbnRpdHlNYXAgPSB2b2lkIDA7CiAgICAgIHRoaXMuX25ld2x5Q3JlYXRlZCA9IHZvaWQgMDsKICAgICAgdGhpcy5pZGVudGlmaWVyQ2FjaGUgPSB2b2lkIDA7CiAgICAgIHRoaXMuaWRlbnRpZmllckNhY2hlID0gaWRlbnRpZmllckNhY2hlRm9yKHN0b3JlKTsKCiAgICAgIHRoaXMuaWRlbnRpZmllckNhY2hlLl9fY29uZmlndXJlTWVyZ2UoZnVuY3Rpb24gKGlkZW50aWZpZXIsIG1hdGNoZWRJZGVudGlmaWVyLCByZXNvdXJjZURhdGEpIHsKICAgICAgICB2YXIgaW50ZW5kZWRJZGVudGlmaWVyID0gaWRlbnRpZmllci5pZCA9PT0gcmVzb3VyY2VEYXRhLmlkID8gaWRlbnRpZmllciA6IG1hdGNoZWRJZGVudGlmaWVyOwogICAgICAgIHZhciBhbHRJZGVudGlmaWVyID0gaWRlbnRpZmllci5pZCA9PT0gcmVzb3VyY2VEYXRhLmlkID8gbWF0Y2hlZElkZW50aWZpZXIgOiBpZGVudGlmaWVyOyAvLyBjaGVjayBmb3IgZHVwbGljYXRlIEludGVybmFsTW9kZWwncwoKICAgICAgICB2YXIgbWFwID0gX3RoaXMubW9kZWxNYXBGb3IoaWRlbnRpZmllci50eXBlKTsKCiAgICAgICAgdmFyIGltID0gbWFwLmdldChpbnRlbmRlZElkZW50aWZpZXIubGlkKTsKICAgICAgICB2YXIgb3RoZXJJbSA9IG1hcC5nZXQoYWx0SWRlbnRpZmllci5saWQpOyAvLyB3ZSBjYW5ub3QgbWVyZ2UgaW50ZXJuYWxNb2RlbHMgd2hlbiBib3RoIGhhdmUgcmVjb3JkcwogICAgICAgIC8vICh0aGlzIG1heSBub3QgYmUgc3RyaWN0bHkgdHJ1ZSwgd2UgY291bGQgcHJvYmFibHkgc3dhcCB0aGUgaW50ZXJuYWxNb2RlbCB0aGUgcmVjb3JkIHBvaW50cyBhdCkKCiAgICAgICAgaWYgKGltICYmIG90aGVySW0gJiYgaW0uaGFzUmVjb3JkICYmIG90aGVySW0uaGFzUmVjb3JkKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkZhaWxlZCB0byB1cGRhdGUgdGhlICdpZCcgZm9yIHRoZSBSZWNvcmRJZGVudGlmaWVyICciICsgaWRlbnRpZmllciArICInIHRvICciICsgcmVzb3VyY2VEYXRhLmlkICsgIicsIGJlY2F1c2UgdGhhdCBpZCBpcyBhbHJlYWR5IGluIHVzZSBieSAnIiArIG1hdGNoZWRJZGVudGlmaWVyICsgIiciKTsKICAgICAgICB9IC8vIHJlbW92ZSBvdGhlckltIGZyb20gY2FjaGUKCgogICAgICAgIGlmIChvdGhlckltKSB7CiAgICAgICAgICBtYXAucmVtb3ZlKG90aGVySW0sIGFsdElkZW50aWZpZXIubGlkKTsKICAgICAgICB9CgogICAgICAgIGlmIChpbSA9PT0gbnVsbCAmJiBvdGhlckltID09PSBudWxsKSB7CiAgICAgICAgICAvLyBub3RoaW5nIG1vcmUgdG8gZG8KICAgICAgICAgIHJldHVybiBpbnRlbmRlZElkZW50aWZpZXI7IC8vIG9ubHkgdGhlIG90aGVyIGhhcyBhbiBJbnRlcm5hbE1vZGVsCiAgICAgICAgICAvLyBPUiBvbmx5IHRoZSBvdGhlciBoYXMgYSBSZWNvcmQKICAgICAgICB9IGVsc2UgaWYgKGltID09PSBudWxsICYmIG90aGVySW0gIT09IG51bGwgfHwgaW0gJiYgIWltLmhhc1JlY29yZCAmJiBvdGhlckltICYmIG90aGVySW0uaGFzUmVjb3JkKSB7CiAgICAgICAgICBpZiAoaW0pIHsKICAgICAgICAgICAgLy8gVE9ETyBjaGVjayBpZiB3ZSBhcmUgcmV0YWluZWQgaW4gYW55IGFzeW5jIHJlbGF0aW9uc2hpcHMKICAgICAgICAgICAgbWFwLnJlbW92ZShpbSwgaW50ZW5kZWRJZGVudGlmaWVyLmxpZCk7IC8vIGltLmRlc3Ryb3koKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpbSA9IG90aGVySW07IC8vIFRPRE8gZG8gd2UgbmVlZCB0byBub3RpZnkgdGhlIGlkIGNoYW5nZT8KCiAgICAgICAgICBpbS5faWQgPSBpbnRlbmRlZElkZW50aWZpZXIuaWQ7CiAgICAgICAgICBtYXAuYWRkKGltLCBpbnRlbmRlZElkZW50aWZpZXIubGlkKTsgLy8ganVzdCB1c2UgaW0KICAgICAgICB9CgogICAgICAgIHJldHVybiBpbnRlbmRlZElkZW50aWZpZXI7CiAgICAgIH0pOwoKICAgICAgdGhpcy5faWRlbnRpdHlNYXAgPSBuZXcgSWRlbnRpdHlNYXAoKTsKICAgIH0KICAgIC8qKgogICAgICogUmV0cmlldmUgdGhlIEludGVybmFsTW9kZWwgZm9yIGEgZ2l2ZW4geyB0eXBlLCBpZCwgbGlkIH0uCiAgICAgKgogICAgICogSWYgYW4gSW50ZXJuYWxNb2RlbCBkb2VzIG5vdCBleGlzdCwgaXQgaW5zdGFudGlhdGVzIG9uZS4KICAgICAqCiAgICAgKiBJZiBhbiBJbnRlcm5hbE1vZGVsIGRvZXMgZXhpc3QgYnVzIGhhcyBhIHNjaGVkdWxlZCBkZXN0cm95LAogICAgICogICB0aGUgc2NoZWR1bGVkIGRlc3Ryb3kgd2lsbCBiZSBjYW5jZWxsZWQuCiAgICAgKgogICAgICogQGludGVybmFsCiAgICAgKi8KCgogICAgdmFyIF9wcm90byA9IEludGVybmFsTW9kZWxGYWN0b3J5LnByb3RvdHlwZTsKCiAgICBfcHJvdG8ubG9va3VwID0gZnVuY3Rpb24gbG9va3VwKHJlc291cmNlLCBkYXRhKSB7CiAgICAgIGlmICggZGF0YSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgLy8gaWYgd2UndmUgYmVlbiBnaXZlbiBkYXRhIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGxvb2t1cAogICAgICAgIC8vIHdlIG11c3QgZmlyc3QgZ2l2ZSBzZWNvbmRhcnktY2FjaGVzIGZvciBMSURzIHRoZQogICAgICAgIC8vIG9wcG9ydHVuaXR5IHRvIHBvcHVsYXRlIGJhc2VkIG9uIGl0CiAgICAgICAgdGhpcy5pZGVudGlmaWVyQ2FjaGUuZ2V0T3JDcmVhdGVSZWNvcmRJZGVudGlmaWVyKGRhdGEpOwogICAgICB9CgogICAgICB2YXIgaWRlbnRpZmllciA9IHRoaXMuaWRlbnRpZmllckNhY2hlLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihyZXNvdXJjZSk7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gdGhpcy5wZWVrKGlkZW50aWZpZXIpOwoKICAgICAgaWYgKGludGVybmFsTW9kZWwpIHsKICAgICAgICAvLyB1bmxvYWRSZWNvcmQgaXMgYXN5bmMsIGlmIG9uZSBhdHRlbXB0cyB0byB1bmxvYWQgKyB0aGVuIHN5bmMgcHVzaCwKICAgICAgICAvLyAgIHdlIG11c3QgZW5zdXJlIHRoZSB1bmxvYWQgaXMgY2FuY2VsZWQgYmVmb3JlIGNvbnRpbnVpbmcKICAgICAgICAvLyAgIFRoZSBjcmVhdGVSZWNvcmQgcGF0aCB3aWxsIHRha2UgX2V4aXN0aW5nSW50ZXJuYWxNb2RlbEZvcklkKCkKICAgICAgICAvLyAgIHdoaWNoIHdpbGwgY2FsbCBgZGVzdHJveVN5bmNgIGluc3RlYWQgZm9yIHRoaXMgdW5sb2FkICsgdGhlbgogICAgICAgIC8vICAgc3luYyBjcmVhdGVSZWNvcmQgc2NlbmFyaW8uIE9uY2Ugd2UgaGF2ZSB0cnVlIGNsaWVudC1zaWRlCiAgICAgICAgLy8gICBkZWxldGUgc2lnbmFsaW5nLCB3ZSBzaG91bGQgbmV2ZXIgY2FsbCBkZXN0cm95U3luYwogICAgICAgIGlmIChpbnRlcm5hbE1vZGVsLmhhc1NjaGVkdWxlZERlc3Ryb3koKSkgewogICAgICAgICAgaW50ZXJuYWxNb2RlbC5jYW5jZWxEZXN0cm95KCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbDsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuX2J1aWxkKGlkZW50aWZpZXIsIGZhbHNlKTsKICAgIH0KICAgIC8qKgogICAgICogUGVlayB0aGUgSW50ZXJuYWxNb2RlbCBmb3IgYSBnaXZlbiB7IHR5cGUsIGlkLCBsaWQgfS4KICAgICAqCiAgICAgKiBJZiBhbiBJbnRlcm5hbE1vZGVsIGRvZXMgbm90IGV4aXN0LCByZXR1cm4gYG51bGxgLgogICAgICoKICAgICAqIEBpbnRlcm5hbAogICAgICovCiAgICA7CgogICAgX3Byb3RvLnBlZWsgPSBmdW5jdGlvbiBwZWVrKGlkZW50aWZpZXIpIHsKICAgICAgewogICAgICAgIHJldHVybiB0aGlzLm1vZGVsTWFwRm9yKGlkZW50aWZpZXIudHlwZSkuZ2V0KGlkZW50aWZpZXIubGlkKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uZ2V0QnlSZXNvdXJjZSA9IGZ1bmN0aW9uIGdldEJ5UmVzb3VyY2UocmVzb3VyY2UpIHsKICAgICAgewogICAgICAgIHZhciBub3JtYWxpemVkUmVzb3VyY2UgPSBjb25zdHJ1Y3RSZXNvdXJjZShyZXNvdXJjZS50eXBlLCByZXNvdXJjZS5pZCwgcmVzb3VyY2UubGlkKTsKICAgICAgICByZXR1cm4gdGhpcy5sb29rdXAobm9ybWFsaXplZFJlc291cmNlKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uc2V0UmVjb3JkSWQgPSBmdW5jdGlvbiBzZXRSZWNvcmRJZCh0eXBlLCBpZCwgbGlkKSB7CiAgICAgIHZhciByZXNvdXJjZSA9IHsKICAgICAgICB0eXBlOiB0eXBlLAogICAgICAgIGlkOiBudWxsLAogICAgICAgIGxpZDogbGlkCiAgICAgIH07CiAgICAgIHZhciBpZGVudGlmaWVyID0gdGhpcy5pZGVudGlmaWVyQ2FjaGUuZ2V0T3JDcmVhdGVSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlKTsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSB0aGlzLnBlZWsoaWRlbnRpZmllcik7CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbCA9PT0gbnVsbCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiQ2Fubm90IHNldCB0aGUgaWQgIiArIGlkICsgIiBvbiB0aGUgcmVjb3JkICIgKyB0eXBlICsgIjoiICsgbGlkICsgIiBhcyB0aGVyZSBpcyBubyBzdWNoIHJlY29yZCBpbiB0aGUgY2FjaGUuIik7CiAgICAgIH0KCiAgICAgIHZhciBvbGRJZCA9IGludGVybmFsTW9kZWwuaWQ7CiAgICAgIHZhciBtb2RlbE5hbWUgPSBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZTsgLy8gSUQgYWJzb2x1dGVseSBjYW4ndCBiZSBtaXNzaW5nIGlmIHRoZSBvbGRJRCBpcyBlbXB0eSAobWlzc2luZyBJZCBpbiByZXNwb25zZSBmb3IgYSBuZXcgcmVjb3JkKQogICAgICAvLyBob3dldmVyLCB0aGlzIGlzIG1vcmUgdGhhbiBsaWtlbHkgYSBkZXZlbG9wZXIgZXJyb3IuCgogICAgICBpZiAob2xkSWQgIT09IG51bGwgJiYgaWQgPT09IG51bGwpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBleGlzdGluZ0ludGVybmFsTW9kZWwgPSB0aGlzLnBlZWtCeUlkKG1vZGVsTmFtZSwgaWQpOwoKICAgICAgaWYgKGlkZW50aWZpZXIuaWQgPT09IG51bGwpIHsKICAgICAgICB0aGlzLmlkZW50aWZpZXJDYWNoZS51cGRhdGVSZWNvcmRJZGVudGlmaWVyKGlkZW50aWZpZXIsIHsKICAgICAgICAgIHR5cGU6IHR5cGUsCiAgICAgICAgICBpZDogaWQKICAgICAgICB9KTsKICAgICAgfQoKICAgICAgaW50ZXJuYWxNb2RlbC5zZXRJZChpZCk7CiAgICB9OwoKICAgIF9wcm90by5wZWVrQnlJZCA9IGZ1bmN0aW9uIHBlZWtCeUlkKHR5cGUsIGlkKSB7CiAgICAgIHZhciBpZGVudGlmaWVyID0gdGhpcy5pZGVudGlmaWVyQ2FjaGUucGVla1JlY29yZElkZW50aWZpZXIoewogICAgICAgIHR5cGU6IHR5cGUsCiAgICAgICAgaWQ6IGlkCiAgICAgIH0pOwogICAgICB2YXIgaW50ZXJuYWxNb2RlbDsKCiAgICAgIHsKICAgICAgICBpbnRlcm5hbE1vZGVsID0gaWRlbnRpZmllciA/IHRoaXMubW9kZWxNYXBGb3IodHlwZSkuZ2V0KGlkZW50aWZpZXIubGlkKSA6IG51bGw7CiAgICAgIH0KCiAgICAgIGlmIChpbnRlcm5hbE1vZGVsICYmIGludGVybmFsTW9kZWwuaGFzU2NoZWR1bGVkRGVzdHJveSgpKSB7CiAgICAgICAgLy8gdW5sb2FkUmVjb3JkIGlzIGFzeW5jLCBpZiBvbmUgYXR0ZW1wdHMgdG8gdW5sb2FkICsgdGhlbiBzeW5jIGNyZWF0ZSwKICAgICAgICAvLyAgIHdlIG11c3QgZW5zdXJlIHRoZSB1bmxvYWQgaXMgY29tcGxldGUgYmVmb3JlIHN0YXJ0aW5nIHRoZSBjcmVhdGUKICAgICAgICAvLyAgIFRoZSBwdXNoIHBhdGggd2lsbCB0YWtlIHRoaXMubG9va3VwKCkKICAgICAgICAvLyAgIHdoaWNoIHdpbGwgY2FsbCBgY2FuY2VsRGVzdHJveWAgaW5zdGVhZCBmb3IgdGhpcyB1bmxvYWQgKyB0aGVuCiAgICAgICAgLy8gICBzeW5jIHB1c2ggc2NlbmFyaW8uIE9uY2Ugd2UgaGF2ZSB0cnVlIGNsaWVudC1zaWRlCiAgICAgICAgLy8gICBkZWxldGUgc2lnbmFsaW5nLCB3ZSBzaG91bGQgbmV2ZXIgY2FsbCBkZXN0cm95U3luYwogICAgICAgIGludGVybmFsTW9kZWwuZGVzdHJveVN5bmMoKTsKICAgICAgICBpbnRlcm5hbE1vZGVsID0gbnVsbDsKICAgICAgfQoKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWw7CiAgICB9OwoKICAgIF9wcm90by5idWlsZCA9IGZ1bmN0aW9uIGJ1aWxkKG5ld1Jlc291cmNlSW5mbykgewogICAgICByZXR1cm4gdGhpcy5fYnVpbGQobmV3UmVzb3VyY2VJbmZvLCB0cnVlKTsKICAgIH07CgogICAgX3Byb3RvLl9idWlsZCA9IGZ1bmN0aW9uIF9idWlsZChyZXNvdXJjZSwgaXNDcmVhdGUpIHsKICAgICAgaWYgKGlzQ3JlYXRlID09PSB2b2lkIDApIHsKICAgICAgICBpc0NyZWF0ZSA9IGZhbHNlOwogICAgICB9CgogICAgICBpZiAoaXNDcmVhdGUgPT09IHRydWUgJiYgcmVzb3VyY2UuaWQpIHsKICAgICAgICB2YXIgZXhpc3RpbmdJbnRlcm5hbE1vZGVsID0gdGhpcy5wZWVrQnlJZChyZXNvdXJjZS50eXBlLCByZXNvdXJjZS5pZCk7CiAgICAgIH0KCiAgICAgIHZhciBpZGVudGlmaWVyQ2FjaGUgPSB0aGlzLmlkZW50aWZpZXJDYWNoZTsKICAgICAgdmFyIGlkZW50aWZpZXI7CgogICAgICBpZiAoaXNDcmVhdGUgPT09IHRydWUpIHsKICAgICAgICBpZGVudGlmaWVyID0gaWRlbnRpZmllckNhY2hlLmNyZWF0ZUlkZW50aWZpZXJGb3JOZXdSZWNvcmQocmVzb3VyY2UpOwogICAgICB9IGVsc2UgewogICAgICAgIGlkZW50aWZpZXIgPSByZXNvdXJjZTsKICAgICAgfSAvLyBsb29rdXBGYWN0b3J5IHNob3VsZCByZWFsbHkgcmV0dXJuIGFuIG9iamVjdCB0aGF0IGNyZWF0ZXMKICAgICAgLy8gaW5zdGFuY2VzIHdpdGggdGhlIGluamVjdGlvbnMgYXBwbGllZAoKCiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gbmV3IEludGVybmFsTW9kZWwodGhpcy5zdG9yZSwgaWRlbnRpZmllcik7CgogICAgICB7CiAgICAgICAgdGhpcy5tb2RlbE1hcEZvcihyZXNvdXJjZS50eXBlKS5hZGQoaW50ZXJuYWxNb2RlbCwgaWRlbnRpZmllci5saWQpOwogICAgICB9CgogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbDsKICAgIH07CgogICAgX3Byb3RvLnJlbW92ZSA9IGZ1bmN0aW9uIHJlbW92ZShpbnRlcm5hbE1vZGVsKSB7CiAgICAgIHZhciByZWNvcmRNYXAgPSB0aGlzLm1vZGVsTWFwRm9yKGludGVybmFsTW9kZWwubW9kZWxOYW1lKTsKICAgICAgdmFyIGNsaWVudElkID0gaW50ZXJuYWxNb2RlbC5pZGVudGlmaWVyLmxpZDsKCiAgICAgIHsKICAgICAgICByZWNvcmRNYXAucmVtb3ZlKGludGVybmFsTW9kZWwsIGNsaWVudElkKTsKICAgICAgfQoKICAgICAgdmFyIGlkZW50aWZpZXIgPSBpbnRlcm5hbE1vZGVsLmlkZW50aWZpZXI7CiAgICAgIHRoaXMuaWRlbnRpZmllckNhY2hlLmZvcmdldFJlY29yZElkZW50aWZpZXIoaWRlbnRpZmllcik7CiAgICB9OwoKICAgIF9wcm90by5tb2RlbE1hcEZvciA9IGZ1bmN0aW9uIG1vZGVsTWFwRm9yKHR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMuX2lkZW50aXR5TWFwLnJldHJpZXZlKHR5cGUpOwogICAgfTsKCiAgICBfcHJvdG8uX25ld2x5Q3JlYXRlZE1vZGVsc0ZvciA9IGZ1bmN0aW9uIF9uZXdseUNyZWF0ZWRNb2RlbHNGb3IodHlwZSkgewogICAgICByZXR1cm4gdGhpcy5fbmV3bHlDcmVhdGVkLnJldHJpZXZlKHR5cGUpOwogICAgfTsKCiAgICBfcHJvdG8uY2xlYXIgPSBmdW5jdGlvbiBjbGVhcih0eXBlKSB7CiAgICAgIGlmICh0eXBlID09PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLl9pZGVudGl0eU1hcC5jbGVhcigpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMubW9kZWxNYXBGb3IodHlwZSkuY2xlYXIoKTsKICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gSW50ZXJuYWxNb2RlbEZhY3Rvcnk7CiAgfSgpOwoKICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyQ1KHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyQ1KENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMkNShDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDUoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIHZhciBSZWNvcmREYXRhU3RvcmVXcmFwcGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUmVjb3JkRGF0YVN0b3JlV3JhcHBlcihfc3RvcmUpIHsKICAgICAgdGhpcy5fc3RvcmUgPSBfc3RvcmU7CiAgICAgIHRoaXNbQlJBTkRfU1lNQk9MXSA9IHZvaWQgMDsKICAgICAgdGhpcy5fd2lsbFVwZGF0ZU1hbnlBcnJheXMgPSB2b2lkIDA7CiAgICAgIHRoaXMuX3BlbmRpbmdNYW55QXJyYXlVcGRhdGVzID0gdm9pZCAwOwogICAgICB0aGlzLl93aWxsVXBkYXRlTWFueUFycmF5cyA9IGZhbHNlOwogICAgICB0aGlzLl9wZW5kaW5nTWFueUFycmF5VXBkYXRlcyA9IFtdOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBSZWNvcmREYXRhU3RvcmVXcmFwcGVyLnByb3RvdHlwZTsKCiAgICAvKioKICAgICAqIEV4aXN0cyBzbyB0aGF0IERlZmF1bHRSZWNvcmREYXRhIGNhbiBjaGVjayBmb3IgbW9kZWwgdHlwZXMKICAgICAqIGluIERFQlVHIGZvciByZWxhdGlvbnNoaXBzLiBTaG91bGQgYmUgcmVmYWN0b3JlZCBhd2F5LgogICAgICoKICAgICAqIEBpbnRlcm5hbAogICAgICovCiAgICBfcHJvdG8uX2hhc01vZGVsRm9yID0gZnVuY3Rpb24gX2hhc01vZGVsRm9yKHR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMuX3N0b3JlLl9oYXNNb2RlbEZvcih0eXBlKTsKICAgIH0KICAgIC8qKgogICAgICogQGludGVybmFsCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3NjaGVkdWxlTWFueUFycmF5VXBkYXRlID0gZnVuY3Rpb24gX3NjaGVkdWxlTWFueUFycmF5VXBkYXRlKGlkZW50aWZpZXIsIGtleSkgewogICAgICB2YXIgX3RoaXMgPSB0aGlzOwoKICAgICAgdmFyIHBlbmRpbmcgPSB0aGlzLl9wZW5kaW5nTWFueUFycmF5VXBkYXRlcyA9IHRoaXMuX3BlbmRpbmdNYW55QXJyYXlVcGRhdGVzIHx8IFtdOwogICAgICBwZW5kaW5nLnB1c2goaWRlbnRpZmllciwga2V5KTsKCiAgICAgIGlmICh0aGlzLl93aWxsVXBkYXRlTWFueUFycmF5cyA9PT0gdHJ1ZSkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdGhpcy5fd2lsbFVwZGF0ZU1hbnlBcnJheXMgPSB0cnVlOwogICAgICB2YXIgYmFja2J1cm5lciA9IHRoaXMuX3N0b3JlLl9iYWNrYnVybmVyOwogICAgICBiYWNrYnVybmVyLmpvaW4oZnVuY3Rpb24gKCkgewogICAgICAgIGJhY2tidXJuZXIuc2NoZWR1bGUoJ3N5bmNSZWxhdGlvbnNoaXBzJywgX3RoaXMsIF90aGlzLl9mbHVzaFBlbmRpbmdNYW55QXJyYXlVcGRhdGVzKTsKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlFcnJvcnNDaGFuZ2UgPSBmdW5jdGlvbiBub3RpZnlFcnJvcnNDaGFuZ2UodHlwZSwgaWQsIGxpZCkgewogICAgICB2YXIgcmVzb3VyY2UgPSBjb25zdHJ1Y3RSZXNvdXJjZSh0eXBlLCBpZCwgbGlkKTsKICAgICAgdmFyIGlkZW50aWZpZXIgPSBpZGVudGlmaWVyQ2FjaGVGb3IodGhpcy5fc3RvcmUpLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihyZXNvdXJjZSk7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcy5fc3RvcmUpLnBlZWsoaWRlbnRpZmllcik7CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwubm90aWZ5RXJyb3JzQ2hhbmdlKCk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9mbHVzaFBlbmRpbmdNYW55QXJyYXlVcGRhdGVzID0gZnVuY3Rpb24gX2ZsdXNoUGVuZGluZ01hbnlBcnJheVVwZGF0ZXMoKSB7CiAgICAgIGlmICh0aGlzLl93aWxsVXBkYXRlTWFueUFycmF5cyA9PT0gZmFsc2UpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIHZhciBwZW5kaW5nID0gdGhpcy5fcGVuZGluZ01hbnlBcnJheVVwZGF0ZXM7CiAgICAgIHRoaXMuX3BlbmRpbmdNYW55QXJyYXlVcGRhdGVzID0gW107CiAgICAgIHRoaXMuX3dpbGxVcGRhdGVNYW55QXJyYXlzID0gZmFsc2U7CiAgICAgIHZhciBmYWN0b3J5ID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcy5fc3RvcmUpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwZW5kaW5nLmxlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgdmFyIGlkZW50aWZpZXIgPSBwZW5kaW5nW2ldOwogICAgICAgIHZhciBfa2V5ID0gcGVuZGluZ1tpICsgMV07CiAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBmYWN0b3J5LnBlZWsoaWRlbnRpZmllcik7CgogICAgICAgIGlmIChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsLm5vdGlmeUhhc01hbnlDaGFuZ2UoX2tleSk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvciA9IGZ1bmN0aW9uIGF0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKHR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMuX3N0b3JlLl9hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvcih0eXBlKTsKICAgIH07CgogICAgX3Byb3RvLnJlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yID0gZnVuY3Rpb24gcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IodHlwZSkgewogICAgICByZXR1cm4gdGhpcy5fc3RvcmUuX3JlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKHR5cGUpOwogICAgfTsKCiAgICBfcHJvdG8uaW52ZXJzZUZvclJlbGF0aW9uc2hpcCA9IGZ1bmN0aW9uIGludmVyc2VGb3JSZWxhdGlvbnNoaXAodHlwZSwga2V5KSB7CiAgICAgIHZhciBtb2RlbENsYXNzID0gdGhpcy5fc3RvcmUubW9kZWxGb3IodHlwZSk7CgogICAgICB2YXIgZGVmaW5pdGlvbiA9IHVwZ3JhZGVGb3JJbnRlcm5hbCh0aGlzLnJlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKHR5cGUpW2tleV0pOwoKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgIGlmIChkZWZpbml0aW9uLmludmVyc2UgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcmV0dXJuIGRlZmluaXRpb24uaW52ZXJzZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgLy9UT0RPIGFkZCBhIHRlc3QgZm9yIHRoaXMgYnJhbmNoCiAgICAgICAgICBpZiAoIWRlZmluaXRpb24uX2ludmVyc2VLZXkpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIGRlZmluaXRpb24uX2ludmVyc2VLZXkodGhpcy5fc3RvcmUsIG1vZGVsQ2xhc3MpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gZGVmaW5pdGlvbi5faW52ZXJzZUtleSh0aGlzLl9zdG9yZSwgbW9kZWxDbGFzcyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmludmVyc2VJc0FzeW5jRm9yUmVsYXRpb25zaGlwID0gZnVuY3Rpb24gaW52ZXJzZUlzQXN5bmNGb3JSZWxhdGlvbnNoaXAodHlwZSwga2V5KSB7CiAgICAgIHZhciBtb2RlbENsYXNzID0gdGhpcy5fc3RvcmUubW9kZWxGb3IodHlwZSk7CgogICAgICB2YXIgZGVmaW5pdGlvbiA9IHVwZ3JhZGVGb3JJbnRlcm5hbCh0aGlzLnJlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKHR5cGUpW2tleV0pOwoKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgIGlmIChkZWZpbml0aW9uLmludmVyc2UgPT09IG51bGwpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CgogICAgICAgIGlmIChkZWZpbml0aW9uLmludmVyc2VJc0FzeW5jICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHJldHVybiAhIWRlZmluaXRpb24uaW52ZXJzZUlzQXN5bmM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBkZWZpbml0aW9uLl9pbnZlcnNlSXNBc3luYyh0aGlzLl9zdG9yZSwgbW9kZWxDbGFzcyk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBkZWZpbml0aW9uLl9pbnZlcnNlSXNBc3luYyh0aGlzLl9zdG9yZSwgbW9kZWxDbGFzcyk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLm5vdGlmeVByb3BlcnR5Q2hhbmdlID0gZnVuY3Rpb24gbm90aWZ5UHJvcGVydHlDaGFuZ2UodHlwZSwgaWQsIGxpZCwga2V5KSB7CiAgICAgIHZhciByZXNvdXJjZSA9IGNvbnN0cnVjdFJlc291cmNlKHR5cGUsIGlkLCBsaWQpOwogICAgICB2YXIgaWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzLl9zdG9yZSkuZ2V0T3JDcmVhdGVSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlKTsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzLl9zdG9yZSkucGVlayhpZGVudGlmaWVyKTsKCiAgICAgIGlmIChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC5ub3RpZnlQcm9wZXJ0eUNoYW5nZShrZXkpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlIYXNNYW55Q2hhbmdlID0gZnVuY3Rpb24gbm90aWZ5SGFzTWFueUNoYW5nZSh0eXBlLCBpZCwgbGlkLCBrZXkpIHsKICAgICAgdmFyIHJlc291cmNlID0gY29uc3RydWN0UmVzb3VyY2UodHlwZSwgaWQsIGxpZCk7CiAgICAgIHZhciBpZGVudGlmaWVyID0gaWRlbnRpZmllckNhY2hlRm9yKHRoaXMuX3N0b3JlKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UpOwoKICAgICAgdGhpcy5fc2NoZWR1bGVNYW55QXJyYXlVcGRhdGUoaWRlbnRpZmllciwga2V5KTsKICAgIH07CgogICAgX3Byb3RvLm5vdGlmeUJlbG9uZ3NUb0NoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeUJlbG9uZ3NUb0NoYW5nZSh0eXBlLCBpZCwgbGlkLCBrZXkpIHsKICAgICAgdmFyIHJlc291cmNlID0gY29uc3RydWN0UmVzb3VyY2UodHlwZSwgaWQsIGxpZCk7CiAgICAgIHZhciBpZGVudGlmaWVyID0gaWRlbnRpZmllckNhY2hlRm9yKHRoaXMuX3N0b3JlKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UpOwogICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMuX3N0b3JlKS5wZWVrKGlkZW50aWZpZXIpOwoKICAgICAgaWYgKGludGVybmFsTW9kZWwpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLm5vdGlmeUJlbG9uZ3NUb0NoYW5nZShrZXkpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5ub3RpZnlTdGF0ZUNoYW5nZSA9IGZ1bmN0aW9uIG5vdGlmeVN0YXRlQ2hhbmdlKHR5cGUsIGlkLCBsaWQsIGtleSkgewogICAgICB2YXIgcmVzb3VyY2UgPSBjb25zdHJ1Y3RSZXNvdXJjZSh0eXBlLCBpZCwgbGlkKTsKICAgICAgdmFyIGlkZW50aWZpZXIgPSBpZGVudGlmaWVyQ2FjaGVGb3IodGhpcy5fc3RvcmUpLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihyZXNvdXJjZSk7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcy5fc3RvcmUpLnBlZWsoaWRlbnRpZmllcik7CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIGludGVybmFsTW9kZWwubm90aWZ5U3RhdGVDaGFuZ2Uoa2V5KTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ucmVjb3JkRGF0YUZvciA9IGZ1bmN0aW9uIHJlY29yZERhdGFGb3IodHlwZSwgaWQsIGxpZCkgewogICAgICB2YXIgaWRlbnRpZmllcjsKICAgICAgdmFyIGlzQ3JlYXRlID0gZmFsc2U7CgogICAgICBpZiAoIWlkICYmICFsaWQpIHsKICAgICAgICBpc0NyZWF0ZSA9IHRydWU7CiAgICAgICAgaWRlbnRpZmllciA9IHsKICAgICAgICAgIHR5cGU6IHR5cGUKICAgICAgICB9OwogICAgICB9IGVsc2UgewogICAgICAgIHZhciByZXNvdXJjZSA9IGNvbnN0cnVjdFJlc291cmNlKHR5cGUsIGlkLCBsaWQpOwogICAgICAgIGlkZW50aWZpZXIgPSBpZGVudGlmaWVyQ2FjaGVGb3IodGhpcy5fc3RvcmUpLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcihyZXNvdXJjZSk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLl9zdG9yZS5yZWNvcmREYXRhRm9yKGlkZW50aWZpZXIsIGlzQ3JlYXRlKTsKICAgIH07CgogICAgX3Byb3RvLnNldFJlY29yZElkID0gZnVuY3Rpb24gc2V0UmVjb3JkSWQodHlwZSwgaWQsIGxpZCkgewogICAgICB0aGlzLl9zdG9yZS5zZXRSZWNvcmRJZCh0eXBlLCBpZCwgbGlkKTsKICAgIH07CgogICAgX3Byb3RvLmlzUmVjb3JkSW5Vc2UgPSBmdW5jdGlvbiBpc1JlY29yZEluVXNlKHR5cGUsIGlkLCBsaWQpIHsKICAgICAgdmFyIHJlc291cmNlID0gY29uc3RydWN0UmVzb3VyY2UodHlwZSwgaWQsIGxpZCk7CiAgICAgIHZhciBpZGVudGlmaWVyID0gaWRlbnRpZmllckNhY2hlRm9yKHRoaXMuX3N0b3JlKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UpOwogICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMuX3N0b3JlKS5wZWVrKGlkZW50aWZpZXIpOwoKICAgICAgaWYgKCFpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CgogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5pc1JlY29yZEluVXNlKCk7CiAgICB9OwoKICAgIF9wcm90by5kaXNjb25uZWN0UmVjb3JkID0gZnVuY3Rpb24gZGlzY29ubmVjdFJlY29yZCh0eXBlLCBpZCwgbGlkKSB7CiAgICAgIHZhciByZXNvdXJjZSA9IGNvbnN0cnVjdFJlc291cmNlKHR5cGUsIGlkLCBsaWQpOwogICAgICB2YXIgaWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzLl9zdG9yZSkuZ2V0T3JDcmVhdGVSZWNvcmRJZGVudGlmaWVyKHJlc291cmNlKTsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzLl9zdG9yZSkucGVlayhpZGVudGlmaWVyKTsKCiAgICAgIGlmIChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC5kZXN0cm95RnJvbVJlY29yZERhdGEoKTsKICAgICAgfQogICAgfTsKCiAgICBfY3JlYXRlQ2xhc3MkNShSZWNvcmREYXRhU3RvcmVXcmFwcGVyLCBbewogICAgICBrZXk6ICJpZGVudGlmaWVyQ2FjaGUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKCiAgICAgICAgcmV0dXJuIGlkZW50aWZpZXJDYWNoZUZvcih0aGlzLl9zdG9yZSk7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gUmVjb3JkRGF0YVN0b3JlV3JhcHBlcjsKICB9KCk7CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCiAgLyoKICAgIFRoaXMgaXMgYSBoZWxwZXIgbWV0aG9kIHRoYXQgYWx3YXlzIHJldHVybnMgYSBKU09OLUFQSSBEb2N1bWVudC4KCiAgICBAbWV0aG9kIG5vcm1hbGl6ZVJlc3BvbnNlSGVscGVyCiAgICBAcGFyYW0ge1NlcmlhbGl6ZXJ9IHNlcmlhbGl6ZXIKICAgIEBwYXJhbSB7U3RvcmV9IHN0b3JlCiAgICBAcGFyYW0ge3N1YmNsYXNzIG9mIE1vZGVsfSBtb2RlbENsYXNzCiAgICBAcGFyYW0ge09iamVjdH0gcGF5bG9hZAogICAgQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpZAogICAgQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RUeXBlCiAgICBAcmV0dXJuIHtPYmplY3R9IEpTT04tQVBJIERvY3VtZW50CiAgKi8KCiAgZnVuY3Rpb24gbm9ybWFsaXplUmVzcG9uc2VIZWxwZXIoc2VyaWFsaXplciwgc3RvcmUsIG1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSkgewogICAgdmFyIG5vcm1hbGl6ZWRSZXNwb25zZSA9IHNlcmlhbGl6ZXIubm9ybWFsaXplUmVzcG9uc2Uoc3RvcmUsIG1vZGVsQ2xhc3MsIHBheWxvYWQsIGlkLCByZXF1ZXN0VHlwZSk7CiAgICByZXR1cm4gbm9ybWFsaXplZFJlc3BvbnNlOwogIH0KCiAgdmFyIFJlcXVlc3RTdGF0ZUVudW07CgogIChmdW5jdGlvbiAoUmVxdWVzdFN0YXRlRW51bSkgewogICAgUmVxdWVzdFN0YXRlRW51bVsicGVuZGluZyJdID0gInBlbmRpbmciOwogICAgUmVxdWVzdFN0YXRlRW51bVsiZnVsZmlsbGVkIl0gPSAiZnVsZmlsbGVkIjsKICAgIFJlcXVlc3RTdGF0ZUVudW1bInJlamVjdGVkIl0gPSAicmVqZWN0ZWQiOwogIH0pKFJlcXVlc3RTdGF0ZUVudW0gfHwgKFJlcXVlc3RTdGF0ZUVudW0gPSB7fSkpOwoKICB2YXIgVG91Y2hpbmcgPSBzeW1ib2woJ3RvdWNoaW5nJyk7CiAgdmFyIFJlcXVlc3RQcm9taXNlID0gc3ltYm9sKCdwcm9taXNlJyk7CgogIGZ1bmN0aW9uIGhhc1JlY29yZElkZW50aWZpZXIob3ApIHsKICAgIHJldHVybiAncmVjb3JkSWRlbnRpZmllcicgaW4gb3A7CiAgfQoKICB2YXIgUmVxdWVzdENhY2hlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gUmVxdWVzdENhY2hlKCkgewogICAgICB0aGlzLl9wZW5kaW5nID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGhpcy5fZG9uZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHRoaXMuX3N1YnNjcmlwdGlvbnMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBSZXF1ZXN0Q2FjaGUucHJvdG90eXBlOwoKICAgIF9wcm90by5lbnF1ZXVlID0gZnVuY3Rpb24gZW5xdWV1ZShwcm9taXNlLCBxdWVyeVJlcXVlc3QpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHZhciBxdWVyeSA9IHF1ZXJ5UmVxdWVzdC5kYXRhWzBdOwoKICAgICAgaWYgKGhhc1JlY29yZElkZW50aWZpZXIocXVlcnkpKSB7CiAgICAgICAgdmFyIF9yZXF1ZXN0OwoKICAgICAgICB2YXIgX2xpZCA9IHF1ZXJ5LnJlY29yZElkZW50aWZpZXIubGlkOwogICAgICAgIHZhciB0eXBlID0gcXVlcnkub3AgPT09ICdzYXZlUmVjb3JkJyA/ICdtdXRhdGlvbicgOiAncXVlcnknOwoKICAgICAgICBpZiAoIXRoaXMuX3BlbmRpbmdbX2xpZF0pIHsKICAgICAgICAgIHRoaXMuX3BlbmRpbmdbX2xpZF0gPSBbXTsKICAgICAgICB9CgogICAgICAgIHZhciByZXF1ZXN0ID0gKF9yZXF1ZXN0ID0gewogICAgICAgICAgc3RhdGU6IFJlcXVlc3RTdGF0ZUVudW0ucGVuZGluZywKICAgICAgICAgIHJlcXVlc3Q6IHF1ZXJ5UmVxdWVzdCwKICAgICAgICAgIHR5cGU6IHR5cGUKICAgICAgICB9LCBfcmVxdWVzdFtUb3VjaGluZ10gPSBbcXVlcnkucmVjb3JkSWRlbnRpZmllcl0sIF9yZXF1ZXN0W1JlcXVlc3RQcm9taXNlXSA9IHByb21pc2UsIF9yZXF1ZXN0KTsKCiAgICAgICAgdGhpcy5fcGVuZGluZ1tfbGlkXS5wdXNoKHJlcXVlc3QpOwoKICAgICAgICB0aGlzLl90cmlnZ2VyU3Vic2NyaXB0aW9ucyhyZXF1ZXN0KTsKCiAgICAgICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHsKICAgICAgICAgIHZhciBfZmluYWxpemVkUmVxdWVzdDsKCiAgICAgICAgICBfdGhpcy5fZGVxdWV1ZShfbGlkLCByZXF1ZXN0KTsKCiAgICAgICAgICB2YXIgZmluYWxpemVkUmVxdWVzdCA9IChfZmluYWxpemVkUmVxdWVzdCA9IHsKICAgICAgICAgICAgc3RhdGU6IFJlcXVlc3RTdGF0ZUVudW0uZnVsZmlsbGVkLAogICAgICAgICAgICByZXF1ZXN0OiBxdWVyeVJlcXVlc3QsCiAgICAgICAgICAgIHR5cGU6IHR5cGUKICAgICAgICAgIH0sIF9maW5hbGl6ZWRSZXF1ZXN0W1RvdWNoaW5nXSA9IHJlcXVlc3RbVG91Y2hpbmddLCBfZmluYWxpemVkUmVxdWVzdC5yZXNwb25zZSA9IHsKICAgICAgICAgICAgZGF0YTogcmVzdWx0CiAgICAgICAgICB9LCBfZmluYWxpemVkUmVxdWVzdCk7CgogICAgICAgICAgX3RoaXMuX2FkZERvbmUoZmluYWxpemVkUmVxdWVzdCk7CgogICAgICAgICAgX3RoaXMuX3RyaWdnZXJTdWJzY3JpcHRpb25zKGZpbmFsaXplZFJlcXVlc3QpOwogICAgICAgIH0sIGZ1bmN0aW9uIChlcnJvcikgewogICAgICAgICAgdmFyIF9maW5hbGl6ZWRSZXF1ZXN0MjsKCiAgICAgICAgICBfdGhpcy5fZGVxdWV1ZShfbGlkLCByZXF1ZXN0KTsKCiAgICAgICAgICB2YXIgZmluYWxpemVkUmVxdWVzdCA9IChfZmluYWxpemVkUmVxdWVzdDIgPSB7CiAgICAgICAgICAgIHN0YXRlOiBSZXF1ZXN0U3RhdGVFbnVtLnJlamVjdGVkLAogICAgICAgICAgICByZXF1ZXN0OiBxdWVyeVJlcXVlc3QsCiAgICAgICAgICAgIHR5cGU6IHR5cGUKICAgICAgICAgIH0sIF9maW5hbGl6ZWRSZXF1ZXN0MltUb3VjaGluZ10gPSByZXF1ZXN0W1RvdWNoaW5nXSwgX2ZpbmFsaXplZFJlcXVlc3QyLnJlc3BvbnNlID0gewogICAgICAgICAgICBkYXRhOiBlcnJvciAmJiBlcnJvci5lcnJvcgogICAgICAgICAgfSwgX2ZpbmFsaXplZFJlcXVlc3QyKTsKCiAgICAgICAgICBfdGhpcy5fYWRkRG9uZShmaW5hbGl6ZWRSZXF1ZXN0KTsKCiAgICAgICAgICBfdGhpcy5fdHJpZ2dlclN1YnNjcmlwdGlvbnMoZmluYWxpemVkUmVxdWVzdCk7CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl90cmlnZ2VyU3Vic2NyaXB0aW9ucyA9IGZ1bmN0aW9uIF90cmlnZ2VyU3Vic2NyaXB0aW9ucyhyZXEpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICByZXFbVG91Y2hpbmddLmZvckVhY2goZnVuY3Rpb24gKGlkZW50aWZpZXIpIHsKICAgICAgICBpZiAoX3RoaXMyLl9zdWJzY3JpcHRpb25zW2lkZW50aWZpZXIubGlkXSkgewogICAgICAgICAgX3RoaXMyLl9zdWJzY3JpcHRpb25zW2lkZW50aWZpZXIubGlkXS5mb3JFYWNoKGZ1bmN0aW9uIChjYWxsYmFjaykgewogICAgICAgICAgICByZXR1cm4gY2FsbGJhY2socmVxKTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5fZGVxdWV1ZSA9IGZ1bmN0aW9uIF9kZXF1ZXVlKGxpZCwgcmVxdWVzdCkgewogICAgICB0aGlzLl9wZW5kaW5nW2xpZF0gPSB0aGlzLl9wZW5kaW5nW2xpZF0uZmlsdGVyKGZ1bmN0aW9uIChyZXEpIHsKICAgICAgICByZXR1cm4gcmVxICE9PSByZXF1ZXN0OwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvLl9hZGREb25lID0gZnVuY3Rpb24gX2FkZERvbmUocmVxdWVzdCkgewogICAgICB2YXIgX3RoaXMzID0gdGhpczsKCiAgICAgIHJlcXVlc3RbVG91Y2hpbmddLmZvckVhY2goZnVuY3Rpb24gKGlkZW50aWZpZXIpIHsKICAgICAgICBpZiAoIV90aGlzMy5fZG9uZVtpZGVudGlmaWVyLmxpZF0pIHsKICAgICAgICAgIF90aGlzMy5fZG9uZVtpZGVudGlmaWVyLmxpZF0gPSBbXTsKICAgICAgICB9IC8vIFRPRE8gYWRkIHN1cHBvcnQgZm9yIG11bHRpcGxlCgoKICAgICAgICB2YXIgcmVxdWVzdERhdGFPcCA9IHJlcXVlc3QucmVxdWVzdC5kYXRhWzBdLm9wOwogICAgICAgIF90aGlzMy5fZG9uZVtpZGVudGlmaWVyLmxpZF0gPSBfdGhpczMuX2RvbmVbaWRlbnRpZmllci5saWRdLmZpbHRlcihmdW5jdGlvbiAocmVxKSB7CiAgICAgICAgICAvLyBUT0RPIGFkZCBzdXBwb3J0IGZvciBtdWx0aXBsZQogICAgICAgICAgdmFyIGRhdGE7CgogICAgICAgICAgaWYgKHJlcS5yZXF1ZXN0LmRhdGEgaW5zdGFuY2VvZiBBcnJheSkgewogICAgICAgICAgICBkYXRhID0gcmVxLnJlcXVlc3QuZGF0YVswXTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGRhdGEgPSByZXEucmVxdWVzdC5kYXRhOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiBkYXRhLm9wICE9PSByZXF1ZXN0RGF0YU9wOwogICAgICAgIH0pOwoKICAgICAgICBfdGhpczMuX2RvbmVbaWRlbnRpZmllci5saWRdLnB1c2gocmVxdWVzdCk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8uc3Vic2NyaWJlRm9yUmVjb3JkID0gZnVuY3Rpb24gc3Vic2NyaWJlRm9yUmVjb3JkKGlkZW50aWZpZXIsIGNhbGxiYWNrKSB7CiAgICAgIGlmICghdGhpcy5fc3Vic2NyaXB0aW9uc1tpZGVudGlmaWVyLmxpZF0pIHsKICAgICAgICB0aGlzLl9zdWJzY3JpcHRpb25zW2lkZW50aWZpZXIubGlkXSA9IFtdOwogICAgICB9CgogICAgICB0aGlzLl9zdWJzY3JpcHRpb25zW2lkZW50aWZpZXIubGlkXS5wdXNoKGNhbGxiYWNrKTsKICAgIH07CgogICAgX3Byb3RvLmdldFBlbmRpbmdSZXF1ZXN0c0ZvclJlY29yZCA9IGZ1bmN0aW9uIGdldFBlbmRpbmdSZXF1ZXN0c0ZvclJlY29yZChpZGVudGlmaWVyKSB7CiAgICAgIGlmICh0aGlzLl9wZW5kaW5nW2lkZW50aWZpZXIubGlkXSkgewogICAgICAgIHJldHVybiB0aGlzLl9wZW5kaW5nW2lkZW50aWZpZXIubGlkXTsKICAgICAgfQoKICAgICAgcmV0dXJuIFtdOwogICAgfTsKCiAgICBfcHJvdG8uZ2V0TGFzdFJlcXVlc3RGb3JSZWNvcmQgPSBmdW5jdGlvbiBnZXRMYXN0UmVxdWVzdEZvclJlY29yZChpZGVudGlmaWVyKSB7CiAgICAgIHZhciByZXF1ZXN0cyA9IHRoaXMuX2RvbmVbaWRlbnRpZmllci5saWRdOwoKICAgICAgaWYgKHJlcXVlc3RzKSB7CiAgICAgICAgcmV0dXJuIHJlcXVlc3RzW3JlcXVlc3RzLmxlbmd0aCAtIDFdOwogICAgICB9CgogICAgICByZXR1cm4gbnVsbDsKICAgIH07CgogICAgcmV0dXJuIFJlcXVlc3RDYWNoZTsKICB9KCk7CgogIHZhciBlbWJlclJ1biA9IEVtYmVyLnJ1bi5iYWNrYnVybmVyOwogIHZhciBTYXZlT3AgPSBzeW1ib2woJ1NhdmVPcCcpOwoKICB2YXIgRmV0Y2hNYW5hZ2VyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgLy8gc2F2ZXMgd2hpY2ggYXJlIHBlbmRpbmcgaW4gdGhlIHJ1bmxvb3AKICAgIC8vIGZldGNoZXMgcGVuZGluZyBpbiB0aGUgcnVubG9vcCwgd2FpdGluZyB0byBiZSBjb2FsZXNjZWQKICAgIGZ1bmN0aW9uIEZldGNoTWFuYWdlcihfc3RvcmUpIHsKICAgICAgdGhpcy5fc3RvcmUgPSBfc3RvcmU7CiAgICAgIHRoaXMuaXNEZXN0cm95ZWQgPSB2b2lkIDA7CiAgICAgIHRoaXMucmVxdWVzdENhY2hlID0gdm9pZCAwOwogICAgICB0aGlzLl9wZW5kaW5nU2F2ZSA9IHZvaWQgMDsKICAgICAgdGhpcy5fcGVuZGluZ0ZldGNoID0gdm9pZCAwOwogICAgICAvLyB1c2VkIHRvIGtlZXAgdHJhY2sgb2YgYWxsIHRoZSBmaW5kIHJlcXVlc3RzIHRoYXQgbmVlZCB0byBiZSBjb2FsZXNjZWQKICAgICAgdGhpcy5fcGVuZGluZ0ZldGNoID0gbmV3IE1hcCgpOwogICAgICB0aGlzLl9wZW5kaW5nU2F2ZSA9IFtdOwogICAgICB0aGlzLnJlcXVlc3RDYWNoZSA9IG5ldyBSZXF1ZXN0Q2FjaGUoKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgYnkgYHJlY29yZC5zYXZlYCwgYW5kIGdldHMgcGFzc2VkIGEKICAgICAgcmVzb2x2ZXIgZm9yIHRoZSBwcm9taXNlIHRoYXQgYHJlY29yZC5zYXZlYCByZXR1cm5zLgogICAgICAgSXQgc2NoZWR1bGVzIHNhdmluZyB0byBoYXBwZW4gYXQgdGhlIGVuZCBvZiB0aGUgcnVuIGxvb3AuCiAgICAqLwoKCiAgICB2YXIgX3Byb3RvID0gRmV0Y2hNYW5hZ2VyLnByb3RvdHlwZTsKCiAgICBfcHJvdG8uc2NoZWR1bGVTYXZlID0gZnVuY3Rpb24gc2NoZWR1bGVTYXZlKGlkZW50aWZpZXIsIG9wdGlvbnMpIHsKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgfQoKICAgICAgdmFyIHByb21pc2VMYWJlbCA9ICdEUzogTW9kZWwjc2F2ZSAnICsgdGhpczsKICAgICAgdmFyIHJlc29sdmVyID0gRW1iZXIuUlNWUC5kZWZlcihwcm9taXNlTGFiZWwpOwogICAgICB2YXIgcXVlcnkgPSB7CiAgICAgICAgb3A6ICdzYXZlUmVjb3JkJywKICAgICAgICByZWNvcmRJZGVudGlmaWVyOiBpZGVudGlmaWVyLAogICAgICAgIG9wdGlvbnM6IG9wdGlvbnMKICAgICAgfTsKICAgICAgdmFyIHF1ZXJ5UmVxdWVzdCA9IHsKICAgICAgICBkYXRhOiBbcXVlcnldCiAgICAgIH07CiAgICAgIHZhciBzbmFwc2hvdCA9IG5ldyBTbmFwc2hvdChvcHRpb25zLCBpZGVudGlmaWVyLCB0aGlzLl9zdG9yZSk7CiAgICAgIHZhciBwZW5kaW5nU2F2ZUl0ZW0gPSB7CiAgICAgICAgc25hcHNob3Q6IHNuYXBzaG90LAogICAgICAgIHJlc29sdmVyOiByZXNvbHZlciwKICAgICAgICBpZGVudGlmaWVyOiBpZGVudGlmaWVyLAogICAgICAgIG9wdGlvbnM6IG9wdGlvbnMsCiAgICAgICAgcXVlcnlSZXF1ZXN0OiBxdWVyeVJlcXVlc3QKICAgICAgfTsKCiAgICAgIHRoaXMuX3BlbmRpbmdTYXZlLnB1c2gocGVuZGluZ1NhdmVJdGVtKTsKCiAgICAgIGVtYmVyUnVuLnNjaGVkdWxlT25jZSgnYWN0aW9ucycsIHRoaXMsIHRoaXMuX2ZsdXNoUGVuZGluZ1NhdmVzKTsKICAgICAgdGhpcy5yZXF1ZXN0Q2FjaGUuZW5xdWV1ZShyZXNvbHZlci5wcm9taXNlLCBwZW5kaW5nU2F2ZUl0ZW0ucXVlcnlSZXF1ZXN0KTsKICAgICAgcmV0dXJuIHJlc29sdmVyLnByb21pc2U7CiAgICB9OwoKICAgIF9wcm90by5fZmx1c2hQZW5kaW5nU2F2ZSA9IGZ1bmN0aW9uIF9mbHVzaFBlbmRpbmdTYXZlKHBlbmRpbmcpIHsKICAgICAgdmFyIHNuYXBzaG90ID0gcGVuZGluZy5zbmFwc2hvdCwKICAgICAgICAgIHJlc29sdmVyID0gcGVuZGluZy5yZXNvbHZlciwKICAgICAgICAgIGlkZW50aWZpZXIgPSBwZW5kaW5nLmlkZW50aWZpZXIsCiAgICAgICAgICBvcHRpb25zID0gcGVuZGluZy5vcHRpb25zOwoKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLl9zdG9yZS5hZGFwdGVyRm9yKGlkZW50aWZpZXIudHlwZSk7CgogICAgICB2YXIgb3BlcmF0aW9uID0gb3B0aW9uc1tTYXZlT3BdOwogICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IHNuYXBzaG90Ll9pbnRlcm5hbE1vZGVsOwogICAgICB2YXIgbW9kZWxOYW1lID0gc25hcHNob3QubW9kZWxOYW1lOwogICAgICB2YXIgc3RvcmUgPSB0aGlzLl9zdG9yZTsKICAgICAgdmFyIG1vZGVsQ2xhc3MgPSBzdG9yZS5tb2RlbEZvcihtb2RlbE5hbWUpOwogICAgICB2YXIgcHJvbWlzZSA9IEVtYmVyLlJTVlAuUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIGFkYXB0ZXJbb3BlcmF0aW9uXShzdG9yZSwgbW9kZWxDbGFzcywgc25hcHNob3QpOwogICAgICB9KTsKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBzdG9yZS5zZXJpYWxpemVyRm9yKG1vZGVsTmFtZSk7CiAgICAgIHZhciBsYWJlbCA9ICJEUzogRXh0cmFjdCBhbmQgbm90aWZ5IGFib3V0ICIgKyBvcGVyYXRpb24gKyAiIGNvbXBsZXRpb24gb2YgIiArIGludGVybmFsTW9kZWw7CiAgICAgIHByb21pc2UgPSBndWFyZERlc3Ryb3llZFN0b3JlKHByb21pc2UsIHN0b3JlLCBsYWJlbCk7CiAgICAgIHByb21pc2UgPSBfZ3VhcmQocHJvbWlzZSwgX2JpbmQoX29iamVjdElzQWxpdmUsIGludGVybmFsTW9kZWwpKTsKICAgICAgcHJvbWlzZSA9IHByb21pc2UudGhlbihmdW5jdGlvbiAoYWRhcHRlclBheWxvYWQpIHsKICAgICAgICBpZiAoYWRhcHRlclBheWxvYWQpIHsKICAgICAgICAgIHJldHVybiBub3JtYWxpemVSZXNwb25zZUhlbHBlcihzZXJpYWxpemVyLCBzdG9yZSwgbW9kZWxDbGFzcywgYWRhcHRlclBheWxvYWQsIHNuYXBzaG90LmlkLCBvcGVyYXRpb24pOwogICAgICAgIH0KICAgICAgfSwgZnVuY3Rpb24gKGVycm9yKSB7CiAgICAgICAgaWYgKGVycm9yICYmIGVycm9yLmlzQWRhcHRlckVycm9yID09PSB0cnVlICYmIGVycm9yLmNvZGUgPT09ICdJbnZhbGlkRXJyb3InKSB7CiAgICAgICAgICB2YXIgcGFyc2VkRXJyb3JzID0gZXJyb3IuZXJyb3JzOwoKICAgICAgICAgIGlmICh0eXBlb2Ygc2VyaWFsaXplci5leHRyYWN0RXJyb3JzID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICAgIHBhcnNlZEVycm9ycyA9IHNlcmlhbGl6ZXIuZXh0cmFjdEVycm9ycyhzdG9yZSwgbW9kZWxDbGFzcywgZXJyb3IsIHNuYXBzaG90LmlkKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHBhcnNlZEVycm9ycyA9IGVycm9yc0FycmF5VG9IYXNoKGVycm9yLmVycm9ycyk7CiAgICAgICAgICB9CgogICAgICAgICAgdGhyb3cgewogICAgICAgICAgICBlcnJvcjogZXJyb3IsCiAgICAgICAgICAgIHBhcnNlZEVycm9yczogcGFyc2VkRXJyb3JzCiAgICAgICAgICB9OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aHJvdyB7CiAgICAgICAgICAgIGVycm9yOiBlcnJvcgogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgIH0sIGxhYmVsKTsKICAgICAgcmVzb2x2ZXIucmVzb2x2ZShwcm9taXNlKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgYXQgdGhlIGVuZCBvZiB0aGUgcnVuIGxvb3AsIGFuZAogICAgICBmbHVzaGVzIGFueSByZWNvcmRzIHBhc3NlZCBpbnRvIGBzY2hlZHVsZVNhdmVgCiAgICAgICBAbWV0aG9kIGZsdXNoUGVuZGluZ1NhdmUKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9mbHVzaFBlbmRpbmdTYXZlcyA9IGZ1bmN0aW9uIF9mbHVzaFBlbmRpbmdTYXZlcygpIHsKICAgICAgdmFyIHBlbmRpbmcgPSB0aGlzLl9wZW5kaW5nU2F2ZS5zbGljZSgpOwoKICAgICAgdGhpcy5fcGVuZGluZ1NhdmUgPSBbXTsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBqID0gcGVuZGluZy5sZW5ndGg7IGkgPCBqOyBpKyspIHsKICAgICAgICB2YXIgcGVuZGluZ0l0ZW0gPSBwZW5kaW5nW2ldOwoKICAgICAgICB0aGlzLl9mbHVzaFBlbmRpbmdTYXZlKHBlbmRpbmdJdGVtKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uc2NoZWR1bGVGZXRjaCA9IGZ1bmN0aW9uIHNjaGVkdWxlRmV0Y2goaWRlbnRpZmllciwgb3B0aW9ucywgc2hvdWxkVHJhY2UpIHsKICAgICAgLy8gVE9ETyBQcm9iYWJseSB0aGUgc3RvcmUgc2hvdWxkIHBhc3MgaW4gdGhlIHF1ZXJ5IG9iamVjdAogICAgICB2YXIgcXVlcnkgPSB7CiAgICAgICAgb3A6ICdmaW5kUmVjb3JkJywKICAgICAgICByZWNvcmRJZGVudGlmaWVyOiBpZGVudGlmaWVyLAogICAgICAgIG9wdGlvbnM6IG9wdGlvbnMKICAgICAgfTsKICAgICAgdmFyIHF1ZXJ5UmVxdWVzdCA9IHsKICAgICAgICBkYXRhOiBbcXVlcnldCiAgICAgIH07CgogICAgICB2YXIgcGVuZGluZ0ZldGNoZXMgPSB0aGlzLl9wZW5kaW5nRmV0Y2guZ2V0KGlkZW50aWZpZXIudHlwZSk7IC8vIFdlIGFscmVhZHkgaGF2ZSBhIHBlbmRpbmcgZmV0Y2ggZm9yIHRoaXMKCgogICAgICBpZiAocGVuZGluZ0ZldGNoZXMpIHsKICAgICAgICB2YXIgbWF0Y2hpbmdQZW5kaW5nRmV0Y2ggPSBwZW5kaW5nRmV0Y2hlcy5maW5kKGZ1bmN0aW9uIChmZXRjaCkgewogICAgICAgICAgcmV0dXJuIGZldGNoLmlkZW50aWZpZXIuaWQgPT09IGlkZW50aWZpZXIuaWQ7CiAgICAgICAgfSk7CgogICAgICAgIGlmIChtYXRjaGluZ1BlbmRpbmdGZXRjaCkgewogICAgICAgICAgcmV0dXJuIG1hdGNoaW5nUGVuZGluZ0ZldGNoLnJlc29sdmVyLnByb21pc2U7CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgaWQgPSBpZGVudGlmaWVyLmlkOwogICAgICB2YXIgbW9kZWxOYW1lID0gaWRlbnRpZmllci50eXBlOwogICAgICB2YXIgcmVzb2x2ZXIgPSBFbWJlci5SU1ZQLmRlZmVyKCJGZXRjaGluZyAiICsgbW9kZWxOYW1lICsgIicgd2l0aCBpZDogIiArIGlkKTsKICAgICAgdmFyIHBlbmRpbmdGZXRjaEl0ZW0gPSB7CiAgICAgICAgaWRlbnRpZmllcjogaWRlbnRpZmllciwKICAgICAgICByZXNvbHZlcjogcmVzb2x2ZXIsCiAgICAgICAgb3B0aW9uczogb3B0aW9ucywKICAgICAgICBxdWVyeVJlcXVlc3Q6IHF1ZXJ5UmVxdWVzdAogICAgICB9OwoKICAgICAgdmFyIHByb21pc2UgPSByZXNvbHZlci5wcm9taXNlOwoKICAgICAgaWYgKHRoaXMuX3BlbmRpbmdGZXRjaC5zaXplID09PSAwKSB7CiAgICAgICAgZW1iZXJSdW4uc2NoZWR1bGUoJ2FjdGlvbnMnLCB0aGlzLCB0aGlzLmZsdXNoQWxsUGVuZGluZ0ZldGNoZXMpOwogICAgICB9CgogICAgICB2YXIgZmV0Y2hlcyA9IHRoaXMuX3BlbmRpbmdGZXRjaDsKCiAgICAgIGlmICghZmV0Y2hlcy5oYXMobW9kZWxOYW1lKSkgewogICAgICAgIGZldGNoZXMuc2V0KG1vZGVsTmFtZSwgW10pOwogICAgICB9CgogICAgICBmZXRjaGVzLmdldChtb2RlbE5hbWUpLnB1c2gocGVuZGluZ0ZldGNoSXRlbSk7CiAgICAgIHRoaXMucmVxdWVzdENhY2hlLmVucXVldWUocHJvbWlzZSwgcGVuZGluZ0ZldGNoSXRlbS5xdWVyeVJlcXVlc3QpOwogICAgICByZXR1cm4gcHJvbWlzZTsKICAgIH07CgogICAgX3Byb3RvLl9mZXRjaFJlY29yZCA9IGZ1bmN0aW9uIF9mZXRjaFJlY29yZChmZXRjaEl0ZW0pIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIHZhciBpZGVudGlmaWVyID0gZmV0Y2hJdGVtLmlkZW50aWZpZXI7CiAgICAgIHZhciBtb2RlbE5hbWUgPSBpZGVudGlmaWVyLnR5cGU7CgogICAgICB2YXIgYWRhcHRlciA9IHRoaXMuX3N0b3JlLmFkYXB0ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgdmFyIHNuYXBzaG90ID0gbmV3IFNuYXBzaG90KGZldGNoSXRlbS5vcHRpb25zLCBpZGVudGlmaWVyLCB0aGlzLl9zdG9yZSk7CgogICAgICB2YXIga2xhc3MgPSB0aGlzLl9zdG9yZS5tb2RlbEZvcihpZGVudGlmaWVyLnR5cGUpOwoKICAgICAgdmFyIHByb21pc2UgPSBFbWJlci5SU1ZQLlByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBhZGFwdGVyLmZpbmRSZWNvcmQoX3RoaXMuX3N0b3JlLCBrbGFzcywgaWRlbnRpZmllci5pZCwgc25hcHNob3QpOwogICAgICB9KTsKICAgICAgdmFyIGlkID0gaWRlbnRpZmllci5pZDsKICAgICAgdmFyIGxhYmVsID0gIkRTOiBIYW5kbGUgQWRhcHRlciNmaW5kUmVjb3JkIG9mICciICsgbW9kZWxOYW1lICsgIicgd2l0aCBpZDogJyIgKyBpZCArICInIjsKICAgICAgcHJvbWlzZSA9IGd1YXJkRGVzdHJveWVkU3RvcmUocHJvbWlzZSwgdGhpcy5fc3RvcmUsIGxhYmVsKTsKICAgICAgcHJvbWlzZSA9IHByb21pc2UudGhlbihmdW5jdGlvbiAoYWRhcHRlclBheWxvYWQpIHsKCiAgICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBfdGhpcy5fc3RvcmUuc2VyaWFsaXplckZvcihtb2RlbE5hbWUpOwoKICAgICAgICB2YXIgcGF5bG9hZCA9IG5vcm1hbGl6ZVJlc3BvbnNlSGVscGVyKHNlcmlhbGl6ZXIsIF90aGlzLl9zdG9yZSwga2xhc3MsIGFkYXB0ZXJQYXlsb2FkLCBpZCwgJ2ZpbmRSZWNvcmQnKTsKICAgICAgICByZXR1cm4gcGF5bG9hZDsKICAgICAgfSwgZnVuY3Rpb24gKGVycm9yKSB7CiAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgIH0sICJEUzogRXh0cmFjdCBwYXlsb2FkIG9mICciICsgbW9kZWxOYW1lICsgIiciKTsKICAgICAgZmV0Y2hJdGVtLnJlc29sdmVyLnJlc29sdmUocHJvbWlzZSk7CiAgICB9IC8vIFRPRE8gc2hvdWxkIHByb2JhYmx5IHJlZmFjdG9yIGV4cGVjdGVkU25hcHNob3RzIHRvIGJlIGlkZW50aWZpZXJzCiAgICA7CgogICAgX3Byb3RvLmhhbmRsZUZvdW5kUmVjb3JkcyA9IGZ1bmN0aW9uIGhhbmRsZUZvdW5kUmVjb3JkcyhzZWVraW5nLCBjb2FsZXNjZWRQYXlsb2FkLCBleHBlY3RlZFNuYXBzaG90cykgewogICAgICAvLyByZXNvbHZlIGZvdW5kIHJlY29yZHMKICAgICAgdmFyIGZvdW5kID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdmFyIHBheWxvYWRzID0gY29hbGVzY2VkUGF5bG9hZC5kYXRhOwogICAgICB2YXIgY29hbGVzY2VkSW5jbHVkZWQgPSBjb2FsZXNjZWRQYXlsb2FkLmluY2x1ZGVkIHx8IFtdOwoKICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBwYXlsb2Fkcy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICB2YXIgcGF5bG9hZCA9IHBheWxvYWRzW2ldOwogICAgICAgIHZhciBwYWlyID0gc2Vla2luZ1twYXlsb2FkLmlkXTsKICAgICAgICBmb3VuZFtwYXlsb2FkLmlkXSA9IHBheWxvYWQ7CiAgICAgICAgdmFyIGluY2x1ZGVkID0gY29hbGVzY2VkSW5jbHVkZWQuY29uY2F0KHBheWxvYWRzKTsgLy8gVE9ETyByZW1vdmUgb3JpZ2luYWwgZGF0YSBmcm9tIGluY2x1ZGVkCgogICAgICAgIGlmIChwYWlyKSB7CiAgICAgICAgICB2YXIgcmVzb2x2ZXIgPSBwYWlyLnJlc29sdmVyOwogICAgICAgICAgcmVzb2x2ZXIucmVzb2x2ZSh7CiAgICAgICAgICAgIGRhdGE6IHBheWxvYWQsCiAgICAgICAgICAgIGluY2x1ZGVkOiBpbmNsdWRlZAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9IC8vIHJlamVjdCBtaXNzaW5nIHJlY29yZHMKICAgICAgLy8gVE9ETyBOT1cgY2xlYW4gdGhpcyB1cCB0byByZWZlciB0byBwYXlsb2FkcwoKCiAgICAgIHZhciBtaXNzaW5nU25hcHNob3RzID0gW107CgogICAgICBmb3IgKHZhciBfaSA9IDAsIF9sID0gZXhwZWN0ZWRTbmFwc2hvdHMubGVuZ3RoOyBfaSA8IF9sOyBfaSsrKSB7CiAgICAgICAgdmFyIHNuYXBzaG90ID0gZXhwZWN0ZWRTbmFwc2hvdHNbX2ldOwoKICAgICAgICBpZiAoIWZvdW5kW3NuYXBzaG90LmlkXSkgewogICAgICAgICAgbWlzc2luZ1NuYXBzaG90cy5wdXNoKHNuYXBzaG90KTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChtaXNzaW5nU25hcHNob3RzLmxlbmd0aCkgewogICAgICAgIHRoaXMucmVqZWN0RmV0Y2hlZEl0ZW1zKHNlZWtpbmcsIG1pc3NpbmdTbmFwc2hvdHMpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZWplY3RGZXRjaGVkSXRlbXMgPSBmdW5jdGlvbiByZWplY3RGZXRjaGVkSXRlbXMoc2Vla2luZywgc25hcHNob3RzLCBlcnJvcikgewogICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHNuYXBzaG90cy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICB2YXIgaWRlbnRpZmllciA9IHNuYXBzaG90c1tpXTsKICAgICAgICB2YXIgcGFpciA9IHNlZWtpbmdbaWRlbnRpZmllci5pZF07CgogICAgICAgIGlmIChwYWlyKSB7CiAgICAgICAgICBwYWlyLnJlc29sdmVyLnJlamVjdChlcnJvciB8fCBuZXcgRXJyb3IoIkV4cGVjdGVkOiAnPCIgKyBpZGVudGlmaWVyLm1vZGVsTmFtZSArICI6IiArIGlkZW50aWZpZXIuaWQgKyAiPicgdG8gYmUgcHJlc2VudCBpbiB0aGUgYWRhcHRlciBwcm92aWRlZCBwYXlsb2FkLCBidXQgaXQgd2FzIG5vdCBmb3VuZC4iKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fZmluZE1hbnkgPSBmdW5jdGlvbiBfZmluZE1hbnkoYWRhcHRlciwgc3RvcmUsIG1vZGVsTmFtZSwgc25hcHNob3RzLCBpZGVudGlmaWVycywgb3B0aW9uc01hcCkgewogICAgICB2YXIgbW9kZWxDbGFzcyA9IHN0b3JlLm1vZGVsRm9yKG1vZGVsTmFtZSk7IC8vIGBhZGFwdGVyLmZpbmRNYW55YCBnZXRzIHRoZSBtb2RlbENsYXNzIHN0aWxsCgogICAgICB2YXIgaWRzID0gc25hcHNob3RzLm1hcChmdW5jdGlvbiAocykgewogICAgICAgIHJldHVybiBzLmlkOwogICAgICB9KTsKICAgICAgdmFyIHByb21pc2UgPSBhZGFwdGVyLmZpbmRNYW55KHN0b3JlLCBtb2RlbENsYXNzLCBpZHMsIEVtYmVyLkEoc25hcHNob3RzKSk7CiAgICAgIHZhciBsYWJlbCA9ICJEUzogSGFuZGxlIEFkYXB0ZXIjZmluZE1hbnkgb2YgJyIgKyBtb2RlbE5hbWUgKyAiJyI7CgogICAgICBpZiAocHJvbWlzZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdhZGFwdGVyLmZpbmRNYW55IHJldHVybmVkIHVuZGVmaW5lZCwgdGhpcyB3YXMgdmVyeSBsaWtlbHkgYSBtaXN0YWtlJyk7CiAgICAgIH0KCiAgICAgIHByb21pc2UgPSBndWFyZERlc3Ryb3llZFN0b3JlKHByb21pc2UsIHN0b3JlLCBsYWJlbCk7CiAgICAgIHJldHVybiBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKGFkYXB0ZXJQYXlsb2FkKSB7CiAgICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBzdG9yZS5zZXJpYWxpemVyRm9yKG1vZGVsTmFtZSk7CiAgICAgICAgdmFyIHBheWxvYWQgPSBub3JtYWxpemVSZXNwb25zZUhlbHBlcihzZXJpYWxpemVyLCBzdG9yZSwgbW9kZWxDbGFzcywgYWRhcHRlclBheWxvYWQsIG51bGwsICdmaW5kTWFueScpOwogICAgICAgIHJldHVybiBwYXlsb2FkOwogICAgICB9LCBudWxsLCAiRFM6IEV4dHJhY3QgcGF5bG9hZCBvZiAiICsgbW9kZWxOYW1lKTsKICAgIH07CgogICAgX3Byb3RvLl9wcm9jZXNzQ29hbGVzY2VkR3JvdXAgPSBmdW5jdGlvbiBfcHJvY2Vzc0NvYWxlc2NlZEdyb3VwKHNlZWtpbmcsIGdyb3VwLCBhZGFwdGVyLCBvcHRpb25zTWFwLCBtb2RlbE5hbWUpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICAvL1RPRE8gY2hlY2sgd2hhdCBoYXBwZW5lZCB3aXRoIGlkZW50aWZpZXJzIGhlcmUKICAgICAgdmFyIHRvdGFsSW5Hcm91cCA9IGdyb3VwLmxlbmd0aDsKICAgICAgdmFyIGlkcyA9IG5ldyBBcnJheSh0b3RhbEluR3JvdXApOwogICAgICB2YXIgZ3JvdXBlZFNuYXBzaG90cyA9IG5ldyBBcnJheSh0b3RhbEluR3JvdXApOwoKICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCB0b3RhbEluR3JvdXA7IGorKykgewogICAgICAgIGdyb3VwZWRTbmFwc2hvdHNbal0gPSBncm91cFtqXTsKICAgICAgICBpZHNbal0gPSBncm91cGVkU25hcHNob3RzW2pdLmlkOwogICAgICB9CgogICAgICB2YXIgc3RvcmUgPSB0aGlzLl9zdG9yZTsKCiAgICAgIGlmICh0b3RhbEluR3JvdXAgPiAxKSB7CiAgICAgICAgdGhpcy5fZmluZE1hbnkoYWRhcHRlciwgc3RvcmUsIG1vZGVsTmFtZSwgZ3JvdXAsIGdyb3VwZWRTbmFwc2hvdHMsIG9wdGlvbnNNYXApLnRoZW4oZnVuY3Rpb24gKHBheWxvYWRzKSB7CiAgICAgICAgICBfdGhpczIuaGFuZGxlRm91bmRSZWNvcmRzKHNlZWtpbmcsIHBheWxvYWRzLCBncm91cGVkU25hcHNob3RzKTsKICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHsKICAgICAgICAgIF90aGlzMi5yZWplY3RGZXRjaGVkSXRlbXMoc2Vla2luZywgZ3JvdXBlZFNuYXBzaG90cywgZXJyb3IpOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgaWYgKGlkcy5sZW5ndGggPT09IDEpIHsKICAgICAgICB2YXIgcGFpciA9IHNlZWtpbmdbZ3JvdXBlZFNuYXBzaG90c1swXS5pZF07CgogICAgICAgIHRoaXMuX2ZldGNoUmVjb3JkKHBhaXIpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fZmx1c2hQZW5kaW5nRmV0Y2hGb3JUeXBlID0gZnVuY3Rpb24gX2ZsdXNoUGVuZGluZ0ZldGNoRm9yVHlwZShwZW5kaW5nRmV0Y2hJdGVtcywgbW9kZWxOYW1lKSB7CiAgICAgIHZhciBhZGFwdGVyID0gdGhpcy5fc3RvcmUuYWRhcHRlckZvcihtb2RlbE5hbWUpOwoKICAgICAgdmFyIHNob3VsZENvYWxlc2NlID0gISFhZGFwdGVyLmZpbmRNYW55ICYmIGFkYXB0ZXIuY29hbGVzY2VGaW5kUmVxdWVzdHM7CiAgICAgIHZhciB0b3RhbEl0ZW1zID0gcGVuZGluZ0ZldGNoSXRlbXMubGVuZ3RoOwogICAgICB2YXIgaWRlbnRpZmllcnMgPSBuZXcgQXJyYXkodG90YWxJdGVtcyk7CiAgICAgIHZhciBzZWVraW5nID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdmFyIG9wdGlvbnNNYXAgPSBuZXcgV2Vha01hcCgpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0b3RhbEl0ZW1zOyBpKyspIHsKICAgICAgICB2YXIgcGVuZGluZ0l0ZW0gPSBwZW5kaW5nRmV0Y2hJdGVtc1tpXTsKICAgICAgICB2YXIgaWRlbnRpZmllciA9IHBlbmRpbmdJdGVtLmlkZW50aWZpZXI7CiAgICAgICAgaWRlbnRpZmllcnNbaV0gPSBpZGVudGlmaWVyOwogICAgICAgIG9wdGlvbnNNYXAuc2V0KGlkZW50aWZpZXIsIHBlbmRpbmdJdGVtLm9wdGlvbnMpOwogICAgICAgIHNlZWtpbmdbaWRlbnRpZmllci5pZF0gPSBwZW5kaW5nSXRlbTsKICAgICAgfQoKICAgICAgaWYgKHNob3VsZENvYWxlc2NlKSB7CiAgICAgICAgLy8gVE9ETzogSW1wcm92ZSByZWNvcmRzID0+IHNuYXBzaG90cyA9PiByZWNvcmRzID0+IHNuYXBzaG90cwogICAgICAgIC8vCiAgICAgICAgLy8gV2Ugd2FudCB0byBwcm92aWRlIHJlY29yZHMgdG8gYWxsIHN0b3JlIG1ldGhvZHMgYW5kIHNuYXBzaG90cyB0byBhbGwKICAgICAgICAvLyBhZGFwdGVyIG1ldGhvZHMuIFRvIG1ha2Ugc3VyZSB3ZSdyZSBkb2luZyB0aGF0IHdlJ3JlIHByb3ZpZGluZyBhbiBhcnJheQogICAgICAgIC8vIG9mIHNuYXBzaG90cyB0byBhZGFwdGVyLmdyb3VwUmVjb3Jkc0ZvckZpbmRNYW55KCksIHdoaWNoIGluIHR1cm4gd2lsbAogICAgICAgIC8vIHJldHVybiBncm91cGVkIHNuYXBzaG90cyBpbnN0ZWFkIG9mIGdyb3VwZWQgcmVjb3Jkcy4KICAgICAgICAvLwogICAgICAgIC8vIEJ1dCBzaW5jZSB0aGUgX2ZpbmRNYW55KCkgZmluZGVyIGlzIGEgc3RvcmUgbWV0aG9kIHdlIG5lZWQgdG8gZ2V0IHRoZQogICAgICAgIC8vIHJlY29yZHMgZnJvbSB0aGUgZ3JvdXBlZCBzbmFwc2hvdHMgZXZlbiB0aG91Z2ggdGhlIF9maW5kTWFueSgpIGZpbmRlcgogICAgICAgIC8vIHdpbGwgb25jZSBhZ2FpbiBjb252ZXJ0IHRoZSByZWNvcmRzIHRvIHNuYXBzaG90cyBmb3IgYWRhcHRlci5maW5kTWFueSgpCiAgICAgICAgdmFyIHNuYXBzaG90cyA9IG5ldyBBcnJheSh0b3RhbEl0ZW1zKTsKCiAgICAgICAgZm9yICh2YXIgX2kyID0gMDsgX2kyIDwgdG90YWxJdGVtczsgX2kyKyspIHsKICAgICAgICAgIHZhciBvcHRpb25zID0gb3B0aW9uc01hcC5nZXQoaWRlbnRpZmllcnNbX2kyXSk7CiAgICAgICAgICBzbmFwc2hvdHNbX2kyXSA9IG5ldyBTbmFwc2hvdChvcHRpb25zLCBpZGVudGlmaWVyc1tfaTJdLCB0aGlzLl9zdG9yZSk7CiAgICAgICAgfQoKICAgICAgICB2YXIgZ3JvdXBzID0gYWRhcHRlci5ncm91cFJlY29yZHNGb3JGaW5kTWFueSh0aGlzLCBzbmFwc2hvdHMpOwoKICAgICAgICBmb3IgKHZhciBfaTMgPSAwLCBsID0gZ3JvdXBzLmxlbmd0aDsgX2kzIDwgbDsgX2kzKyspIHsKICAgICAgICAgIHRoaXMuX3Byb2Nlc3NDb2FsZXNjZWRHcm91cChzZWVraW5nLCBncm91cHNbX2kzXSwgYWRhcHRlciwgb3B0aW9uc01hcCwgbW9kZWxOYW1lKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yICh2YXIgX2k0ID0gMDsgX2k0IDwgdG90YWxJdGVtczsgX2k0KyspIHsKICAgICAgICAgIHRoaXMuX2ZldGNoUmVjb3JkKHBlbmRpbmdGZXRjaEl0ZW1zW19pNF0pOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uZmx1c2hBbGxQZW5kaW5nRmV0Y2hlcyA9IGZ1bmN0aW9uIGZsdXNoQWxsUGVuZGluZ0ZldGNoZXMoKSB7CiAgICAgIGlmICh0aGlzLmlzRGVzdHJveWVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9wZW5kaW5nRmV0Y2guZm9yRWFjaCh0aGlzLl9mbHVzaFBlbmRpbmdGZXRjaEZvclR5cGUsIHRoaXMpOwoKICAgICAgdGhpcy5fcGVuZGluZ0ZldGNoLmNsZWFyKCk7CiAgICB9OwoKICAgIF9wcm90by5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHsKICAgICAgdGhpcy5pc0Rlc3Ryb3llZCA9IHRydWU7CiAgICB9OwoKICAgIHJldHVybiBGZXRjaE1hbmFnZXI7CiAgfSgpOwoKICBmdW5jdGlvbiBfZmluZChhZGFwdGVyLCBzdG9yZSwgbW9kZWxDbGFzcywgaWQsIGludGVybmFsTW9kZWwsIG9wdGlvbnMpIHsKCiAgICB2YXIgc25hcHNob3QgPSBpbnRlcm5hbE1vZGVsLmNyZWF0ZVNuYXBzaG90KG9wdGlvbnMpOwogICAgdmFyIG1vZGVsTmFtZSA9IGludGVybmFsTW9kZWwubW9kZWxOYW1lOwogICAgdmFyIHByb21pc2UgPSBFbWJlci5SU1ZQLlByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gYWRhcHRlci5maW5kUmVjb3JkKHN0b3JlLCBtb2RlbENsYXNzLCBpZCwgc25hcHNob3QpOwogICAgfSk7CiAgICB2YXIgbGFiZWwgPSAiRFM6IEhhbmRsZSBBZGFwdGVyI2ZpbmRSZWNvcmQgb2YgJyIgKyBtb2RlbE5hbWUgKyAiJyB3aXRoIGlkOiAnIiArIGlkICsgIiciOwogICAgdmFyIGlkZW50aWZpZXIgPSBpbnRlcm5hbE1vZGVsLmlkZW50aWZpZXI7CiAgICBwcm9taXNlID0gZ3VhcmREZXN0cm95ZWRTdG9yZShwcm9taXNlLCBzdG9yZSwgbGFiZWwpOwogICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAoYWRhcHRlclBheWxvYWQpIHsKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBzdG9yZS5zZXJpYWxpemVyRm9yKG1vZGVsTmFtZSk7CiAgICAgIHZhciBwYXlsb2FkID0gbm9ybWFsaXplUmVzcG9uc2VIZWxwZXIoc2VyaWFsaXplciwgc3RvcmUsIG1vZGVsQ2xhc3MsIGFkYXB0ZXJQYXlsb2FkLCBpZCwgJ2ZpbmRSZWNvcmQnKTsKCiAgICAgIHsKICAgICAgICAvLyBlbnN1cmUgdGhhdCByZWdhcmRsZXNzIG9mIGlkIHJldHVybmVkIHdlIGFzc2lnbiB0byB0aGUgY29ycmVjdCByZWNvcmQKICAgICAgICBwYXlsb2FkLmRhdGEubGlkID0gaWRlbnRpZmllci5saWQ7CiAgICAgIH0KCiAgICAgIHJldHVybiBzdG9yZS5fcHVzaChwYXlsb2FkKTsKICAgIH0sIGZ1bmN0aW9uIChlcnJvcikgewogICAgICBpbnRlcm5hbE1vZGVsLm5vdEZvdW5kKCk7CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbC5pc0VtcHR5KCkpIHsKICAgICAgICBpbnRlcm5hbE1vZGVsLnVubG9hZFJlY29yZCgpOwogICAgICB9CgogICAgICB0aHJvdyBlcnJvcjsKICAgIH0sICJEUzogRXh0cmFjdCBwYXlsb2FkIG9mICciICsgbW9kZWxOYW1lICsgIiciKTsKICB9CiAgZnVuY3Rpb24gX2ZpbmRNYW55KGFkYXB0ZXIsIHN0b3JlLCBtb2RlbE5hbWUsIGlkcywgaW50ZXJuYWxNb2RlbHMsIG9wdGlvbnNNYXApIHsKICAgIHZhciBzbmFwc2hvdHMgPSBFbWJlci5BKGludGVybmFsTW9kZWxzLm1hcChmdW5jdGlvbiAoaW50ZXJuYWxNb2RlbCkgewogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdChvcHRpb25zTWFwLmdldChpbnRlcm5hbE1vZGVsKSk7CiAgICB9KSk7CiAgICB2YXIgbW9kZWxDbGFzcyA9IHN0b3JlLm1vZGVsRm9yKG1vZGVsTmFtZSk7IC8vIGBhZGFwdGVyLmZpbmRNYW55YCBnZXRzIHRoZSBtb2RlbENsYXNzIHN0aWxsCgogICAgdmFyIHByb21pc2UgPSBhZGFwdGVyLmZpbmRNYW55KHN0b3JlLCBtb2RlbENsYXNzLCBpZHMsIHNuYXBzaG90cyk7CiAgICB2YXIgbGFiZWwgPSAiRFM6IEhhbmRsZSBBZGFwdGVyI2ZpbmRNYW55IG9mICciICsgbW9kZWxOYW1lICsgIiciOwoKICAgIGlmIChwcm9taXNlID09PSB1bmRlZmluZWQpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdhZGFwdGVyLmZpbmRNYW55IHJldHVybmVkIHVuZGVmaW5lZCwgdGhpcyB3YXMgdmVyeSBsaWtlbHkgYSBtaXN0YWtlJyk7CiAgICB9CgogICAgcHJvbWlzZSA9IGd1YXJkRGVzdHJveWVkU3RvcmUocHJvbWlzZSwgc3RvcmUsIGxhYmVsKTsKICAgIHJldHVybiBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKGFkYXB0ZXJQYXlsb2FkKSB7CiAgICAgIHZhciBzZXJpYWxpemVyID0gc3RvcmUuc2VyaWFsaXplckZvcihtb2RlbE5hbWUpOwogICAgICB2YXIgcGF5bG9hZCA9IG5vcm1hbGl6ZVJlc3BvbnNlSGVscGVyKHNlcmlhbGl6ZXIsIHN0b3JlLCBtb2RlbENsYXNzLCBhZGFwdGVyUGF5bG9hZCwgbnVsbCwgJ2ZpbmRNYW55Jyk7CiAgICAgIHJldHVybiBzdG9yZS5fcHVzaChwYXlsb2FkKTsKICAgIH0sIG51bGwsICJEUzogRXh0cmFjdCBwYXlsb2FkIG9mICIgKyBtb2RlbE5hbWUpOwogIH0KCiAgZnVuY3Rpb24gaXRlcmF0ZURhdGEoZGF0YSwgZm4pIHsKICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7CiAgICAgIHJldHVybiBkYXRhLm1hcChmbik7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gZm4oZGF0YSk7CiAgICB9CiAgfSAvLyBzeW5jCiAgLy8gaXRlcmF0ZSBvdmVyIHJlY29yZHMgaW4gcGF5bG9hZC5kYXRhCiAgLy8gZm9yIGVhY2ggcmVjb3JkCiAgLy8gICBhc3NlcnQgdGhhdCByZWNvcmQucmVsYXRpb25zaGlwc1tpbnZlcnNlXSBpcyBlaXRoZXIgdW5kZWZpbmVkIChzbyB3ZSBjYW4gZml4IGl0KQogIC8vICAgICBvciBwcm92aWRlIGEgZGF0YToge2lkLCB0eXBlfSB0aGF0IG1hdGNoZXMgdGhlIHJlY29yZCB0aGF0IHJlcXVlc3RlZCBpdAogIC8vICAgcmV0dXJuIHRoZSByZWxhdGlvbnNoaXAgZGF0YSBmb3IgdGhlIHBhcmVudAoKCiAgZnVuY3Rpb24gc3luY1JlbGF0aW9uc2hpcERhdGFGcm9tTGluayhzdG9yZSwgcGF5bG9hZCwgcGFyZW50SW50ZXJuYWxNb2RlbCwgcmVsYXRpb25zaGlwKSB7CiAgICB2YXIgX3JlbGF0aW9uc2hpcHM7CgogICAgLy8gZW5zdXJlIHRoZSByaWdodCBoYW5kIHNpZGUgKGluY29taW5nIHBheWxvYWQpIHBvaW50cyB0byB0aGUgcGFyZW50IHJlY29yZCB0aGF0CiAgICAvLyByZXF1ZXN0ZWQgdGhpcyByZWxhdGlvbnNoaXAKICAgIHZhciByZWxhdGlvbnNoaXBEYXRhID0gaXRlcmF0ZURhdGEocGF5bG9hZC5kYXRhLCBmdW5jdGlvbiAoZGF0YSwgaW5kZXgpIHsKICAgICAgdmFyIGlkID0gZGF0YS5pZCwKICAgICAgICAgIHR5cGUgPSBkYXRhLnR5cGU7CiAgICAgIGVuc3VyZVJlbGF0aW9uc2hpcElzU2V0VG9QYXJlbnQoZGF0YSwgcGFyZW50SW50ZXJuYWxNb2RlbCwgc3RvcmUsIHJlbGF0aW9uc2hpcCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgaWQ6IGlkLAogICAgICAgIHR5cGU6IHR5cGUKICAgICAgfTsKICAgIH0pOyAvLyBub3csIHB1c2ggdGhlIGxlZnQgaGFuZCBzaWRlICh0aGUgcGFyZW50IHJlY29yZCkgdG8gZW5zdXJlIHRoaW5ncyBhcmUgaW4gc3luYywgc2luY2UKICAgIC8vIHRoZSBwYXlsb2FkIHdpbGwgYmUgcHVzaGVkIHdpdGggc3RvcmUuX3B1c2gKCiAgICB2YXIgcGFyZW50UGF5bG9hZCA9IHsKICAgICAgaWQ6IHBhcmVudEludGVybmFsTW9kZWwuaWQsCiAgICAgIHR5cGU6IHBhcmVudEludGVybmFsTW9kZWwubW9kZWxOYW1lLAogICAgICByZWxhdGlvbnNoaXBzOiAoX3JlbGF0aW9uc2hpcHMgPSB7fSwgX3JlbGF0aW9uc2hpcHNbcmVsYXRpb25zaGlwLmtleV0gPSB7CiAgICAgICAgbWV0YTogcGF5bG9hZC5tZXRhLAogICAgICAgIGxpbmtzOiBwYXlsb2FkLmxpbmtzLAogICAgICAgIGRhdGE6IHJlbGF0aW9uc2hpcERhdGEKICAgICAgfSwgX3JlbGF0aW9uc2hpcHMpCiAgICB9OwoKICAgIGlmICghQXJyYXkuaXNBcnJheShwYXlsb2FkLmluY2x1ZGVkKSkgewogICAgICBwYXlsb2FkLmluY2x1ZGVkID0gW107CiAgICB9CgogICAgcGF5bG9hZC5pbmNsdWRlZC5wdXNoKHBhcmVudFBheWxvYWQpOwogICAgcmV0dXJuIHBheWxvYWQ7CiAgfQoKICBmdW5jdGlvbiBlbnN1cmVSZWxhdGlvbnNoaXBJc1NldFRvUGFyZW50KHBheWxvYWQsIHBhcmVudEludGVybmFsTW9kZWwsIHN0b3JlLCBwYXJlbnRSZWxhdGlvbnNoaXAsIGluZGV4KSB7CiAgICB2YXIgaWQgPSBwYXlsb2FkLmlkLAogICAgICAgIHR5cGUgPSBwYXlsb2FkLnR5cGU7CgogICAgaWYgKCFwYXlsb2FkLnJlbGF0aW9uc2hpcHMpIHsKICAgICAgcGF5bG9hZC5yZWxhdGlvbnNoaXBzID0ge307CiAgICB9CgogICAgdmFyIHJlbGF0aW9uc2hpcHMgPSBwYXlsb2FkLnJlbGF0aW9uc2hpcHM7CiAgICB2YXIgaW52ZXJzZSA9IGdldEludmVyc2Uoc3RvcmUsIHBhcmVudEludGVybmFsTW9kZWwsIHBhcmVudFJlbGF0aW9uc2hpcCwgdHlwZSk7CgogICAgaWYgKGludmVyc2UpIHsKICAgICAgdmFyIGludmVyc2VLZXkgPSBpbnZlcnNlLmludmVyc2VLZXksCiAgICAgICAgICBraW5kID0gaW52ZXJzZS5raW5kOwogICAgICB2YXIgcmVsYXRpb25zaGlwRGF0YSA9IHJlbGF0aW9uc2hpcHNbaW52ZXJzZUtleV0gJiYgcmVsYXRpb25zaGlwc1tpbnZlcnNlS2V5XS5kYXRhOwoKICAgICAgaWYgKGtpbmQgIT09ICdoYXNNYW55JyB8fCB0eXBlb2YgcmVsYXRpb25zaGlwRGF0YSAhPT0gJ3VuZGVmaW5lZCcpIHsKICAgICAgICByZWxhdGlvbnNoaXBzW2ludmVyc2VLZXldID0gcmVsYXRpb25zaGlwc1tpbnZlcnNlS2V5XSB8fCB7fTsKICAgICAgICByZWxhdGlvbnNoaXBzW2ludmVyc2VLZXldLmRhdGEgPSBmaXhSZWxhdGlvbnNoaXBEYXRhKHJlbGF0aW9uc2hpcERhdGEsIGtpbmQsIHBhcmVudEludGVybmFsTW9kZWwpOwogICAgICB9CiAgICB9CiAgfQoKICBmdW5jdGlvbiBnZXRJbnZlcnNlKHN0b3JlLCBwYXJlbnRJbnRlcm5hbE1vZGVsLCBwYXJlbnRSZWxhdGlvbnNoaXAsIHR5cGUpIHsKICAgIHJldHVybiByZWNvcmREYXRhRmluZEludmVyc2VSZWxhdGlvbnNoaXBJbmZvKHN0b3JlLCBwYXJlbnRJbnRlcm5hbE1vZGVsLCBwYXJlbnRSZWxhdGlvbnNoaXAsIHR5cGUpOwogIH0KCiAgZnVuY3Rpb24gcmVjb3JkRGF0YUZpbmRJbnZlcnNlUmVsYXRpb25zaGlwSW5mbyhfcmVmLCBwYXJlbnRJbnRlcm5hbE1vZGVsLCBwYXJlbnRSZWxhdGlvbnNoaXAsIHR5cGUpIHsKICAgIHZhciBfc3RvcmVXcmFwcGVyID0gX3JlZi5fc3RvcmVXcmFwcGVyOwogICAgdmFyIGxoc19yZWxhdGlvbnNoaXBOYW1lID0gcGFyZW50UmVsYXRpb25zaGlwLm5hbWU7CiAgICB2YXIgbW9kZWxOYW1lID0gcGFyZW50SW50ZXJuYWxNb2RlbC5tb2RlbE5hbWU7CgogICAgdmFyIGludmVyc2VLZXkgPSBfc3RvcmVXcmFwcGVyLmludmVyc2VGb3JSZWxhdGlvbnNoaXAobW9kZWxOYW1lLCBsaHNfcmVsYXRpb25zaGlwTmFtZSk7CgogICAgaWYgKGludmVyc2VLZXkpIHsKICAgICAgdmFyIGtpbmQgPSBfc3RvcmVXcmFwcGVyLnJlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKHR5cGUpW2ludmVyc2VLZXldLm1ldGEua2luZDsKCiAgICAgIHJldHVybiB7CiAgICAgICAgaW52ZXJzZUtleTogaW52ZXJzZUtleSwKICAgICAgICBraW5kOiBraW5kCiAgICAgIH07CiAgICB9CiAgfQoKICBmdW5jdGlvbiBmaXhSZWxhdGlvbnNoaXBEYXRhKHJlbGF0aW9uc2hpcERhdGEsIHJlbGF0aW9uc2hpcEtpbmQsIF9yZWYyKSB7CiAgICB2YXIgaWQgPSBfcmVmMi5pZCwKICAgICAgICBtb2RlbE5hbWUgPSBfcmVmMi5tb2RlbE5hbWU7CiAgICB2YXIgcGFyZW50UmVsYXRpb25zaGlwRGF0YSA9IHsKICAgICAgaWQ6IGlkLAogICAgICB0eXBlOiBtb2RlbE5hbWUKICAgIH07CiAgICB2YXIgcGF5bG9hZDsKCiAgICBpZiAocmVsYXRpb25zaGlwS2luZCA9PT0gJ2hhc01hbnknKSB7CiAgICAgIHBheWxvYWQgPSByZWxhdGlvbnNoaXBEYXRhIHx8IFtdOwogICAgICBwYXlsb2FkLnB1c2gocGFyZW50UmVsYXRpb25zaGlwRGF0YSk7CiAgICB9IGVsc2UgewogICAgICBwYXlsb2FkID0gcmVsYXRpb25zaGlwRGF0YSB8fCB7fTsKICAgICAgRW1iZXIuYXNzaWduKHBheWxvYWQsIHBhcmVudFJlbGF0aW9uc2hpcERhdGEpOwogICAgfQoKICAgIHJldHVybiBwYXlsb2FkOwogIH0KCiAgZnVuY3Rpb24gX2ZpbmRIYXNNYW55KGFkYXB0ZXIsIHN0b3JlLCBpbnRlcm5hbE1vZGVsLCBsaW5rLCByZWxhdGlvbnNoaXAsIG9wdGlvbnMpIHsKICAgIHZhciBzbmFwc2hvdCA9IGludGVybmFsTW9kZWwuY3JlYXRlU25hcHNob3Qob3B0aW9ucyk7CiAgICB2YXIgbW9kZWxDbGFzcyA9IHN0b3JlLm1vZGVsRm9yKHJlbGF0aW9uc2hpcC50eXBlKTsKICAgIHZhciB1c2VMaW5rID0gIWxpbmsgfHwgdHlwZW9mIGxpbmsgPT09ICdzdHJpbmcnOwogICAgdmFyIHJlbGF0ZWRMaW5rID0gdXNlTGluayA/IGxpbmsgOiBsaW5rLmhyZWY7CiAgICB2YXIgcHJvbWlzZSA9IGFkYXB0ZXIuZmluZEhhc01hbnkoc3RvcmUsIHNuYXBzaG90LCByZWxhdGVkTGluaywgcmVsYXRpb25zaGlwKTsKICAgIHZhciBsYWJlbCA9ICJEUzogSGFuZGxlIEFkYXB0ZXIjZmluZEhhc01hbnkgb2YgJyIgKyBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZSArICInIDogJyIgKyByZWxhdGlvbnNoaXAudHlwZSArICInIjsKICAgIHByb21pc2UgPSBndWFyZERlc3Ryb3llZFN0b3JlKHByb21pc2UsIHN0b3JlLCBsYWJlbCk7CiAgICBwcm9taXNlID0gX2d1YXJkKHByb21pc2UsIF9iaW5kKF9vYmplY3RJc0FsaXZlLCBpbnRlcm5hbE1vZGVsKSk7CiAgICByZXR1cm4gcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChhZGFwdGVyUGF5bG9hZCkgewogICAgICB2YXIgc2VyaWFsaXplciA9IHN0b3JlLnNlcmlhbGl6ZXJGb3IocmVsYXRpb25zaGlwLnR5cGUpOwogICAgICB2YXIgcGF5bG9hZCA9IG5vcm1hbGl6ZVJlc3BvbnNlSGVscGVyKHNlcmlhbGl6ZXIsIHN0b3JlLCBtb2RlbENsYXNzLCBhZGFwdGVyUGF5bG9hZCwgbnVsbCwgJ2ZpbmRIYXNNYW55Jyk7CiAgICAgIHBheWxvYWQgPSBzeW5jUmVsYXRpb25zaGlwRGF0YUZyb21MaW5rKHN0b3JlLCBwYXlsb2FkLCBpbnRlcm5hbE1vZGVsLCByZWxhdGlvbnNoaXApOwoKICAgICAgdmFyIGludGVybmFsTW9kZWxBcnJheSA9IHN0b3JlLl9wdXNoKHBheWxvYWQpOwoKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWxBcnJheTsKICAgIH0sIG51bGwsICJEUzogRXh0cmFjdCBwYXlsb2FkIG9mICciICsgaW50ZXJuYWxNb2RlbC5tb2RlbE5hbWUgKyAiJyA6IGhhc01hbnkgJyIgKyByZWxhdGlvbnNoaXAudHlwZSArICInIik7CiAgfQogIGZ1bmN0aW9uIF9maW5kQmVsb25nc1RvKGFkYXB0ZXIsIHN0b3JlLCBpbnRlcm5hbE1vZGVsLCBsaW5rLCByZWxhdGlvbnNoaXAsIG9wdGlvbnMpIHsKICAgIHZhciBzbmFwc2hvdCA9IGludGVybmFsTW9kZWwuY3JlYXRlU25hcHNob3Qob3B0aW9ucyk7CiAgICB2YXIgbW9kZWxDbGFzcyA9IHN0b3JlLm1vZGVsRm9yKHJlbGF0aW9uc2hpcC50eXBlKTsKICAgIHZhciB1c2VMaW5rID0gIWxpbmsgfHwgdHlwZW9mIGxpbmsgPT09ICdzdHJpbmcnOwogICAgdmFyIHJlbGF0ZWRMaW5rID0gdXNlTGluayA/IGxpbmsgOiBsaW5rLmhyZWY7CiAgICB2YXIgcHJvbWlzZSA9IGFkYXB0ZXIuZmluZEJlbG9uZ3NUbyhzdG9yZSwgc25hcHNob3QsIHJlbGF0ZWRMaW5rLCByZWxhdGlvbnNoaXApOwogICAgdmFyIGxhYmVsID0gIkRTOiBIYW5kbGUgQWRhcHRlciNmaW5kQmVsb25nc1RvIG9mICIgKyBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZSArICIgOiAiICsgcmVsYXRpb25zaGlwLnR5cGU7CiAgICBwcm9taXNlID0gZ3VhcmREZXN0cm95ZWRTdG9yZShwcm9taXNlLCBzdG9yZSwgbGFiZWwpOwogICAgcHJvbWlzZSA9IF9ndWFyZChwcm9taXNlLCBfYmluZChfb2JqZWN0SXNBbGl2ZSwgaW50ZXJuYWxNb2RlbCkpOwogICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAoYWRhcHRlclBheWxvYWQpIHsKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBzdG9yZS5zZXJpYWxpemVyRm9yKHJlbGF0aW9uc2hpcC50eXBlKTsKICAgICAgdmFyIHBheWxvYWQgPSBub3JtYWxpemVSZXNwb25zZUhlbHBlcihzZXJpYWxpemVyLCBzdG9yZSwgbW9kZWxDbGFzcywgYWRhcHRlclBheWxvYWQsIG51bGwsICdmaW5kQmVsb25nc1RvJyk7CgogICAgICBpZiAoIXBheWxvYWQuZGF0YSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICBwYXlsb2FkID0gc3luY1JlbGF0aW9uc2hpcERhdGFGcm9tTGluayhzdG9yZSwgcGF5bG9hZCwgaW50ZXJuYWxNb2RlbCwgcmVsYXRpb25zaGlwKTsKICAgICAgcmV0dXJuIHN0b3JlLl9wdXNoKHBheWxvYWQpOwogICAgfSwgbnVsbCwgIkRTOiBFeHRyYWN0IHBheWxvYWQgb2YgIiArIGludGVybmFsTW9kZWwubW9kZWxOYW1lICsgIiA6ICIgKyByZWxhdGlvbnNoaXAudHlwZSk7CiAgfQogIGZ1bmN0aW9uIF9maW5kQWxsKGFkYXB0ZXIsIHN0b3JlLCBtb2RlbE5hbWUsIG9wdGlvbnMpIHsKICAgIHZhciBtb2RlbENsYXNzID0gc3RvcmUubW9kZWxGb3IobW9kZWxOYW1lKTsgLy8gYWRhcHRlci5maW5kQWxsIGRlcGVuZHMgb24gdGhlIGNsYXNzCgogICAgdmFyIHJlY29yZEFycmF5ID0gc3RvcmUucGVla0FsbChtb2RlbE5hbWUpOwoKICAgIHZhciBzbmFwc2hvdEFycmF5ID0gcmVjb3JkQXJyYXkuX2NyZWF0ZVNuYXBzaG90KG9wdGlvbnMpOwoKICAgIHZhciBwcm9taXNlID0gRW1iZXIuUlNWUC5Qcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIGFkYXB0ZXIuZmluZEFsbChzdG9yZSwgbW9kZWxDbGFzcywgbnVsbCwgc25hcHNob3RBcnJheSk7CiAgICB9KTsKICAgIHZhciBsYWJlbCA9ICdEUzogSGFuZGxlIEFkYXB0ZXIjZmluZEFsbCBvZiAnICsgbW9kZWxDbGFzczsKICAgIHByb21pc2UgPSBndWFyZERlc3Ryb3llZFN0b3JlKHByb21pc2UsIHN0b3JlLCBsYWJlbCk7CiAgICByZXR1cm4gcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChhZGFwdGVyUGF5bG9hZCkgewogICAgICB2YXIgc2VyaWFsaXplciA9IHN0b3JlLnNlcmlhbGl6ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgdmFyIHBheWxvYWQgPSBub3JtYWxpemVSZXNwb25zZUhlbHBlcihzZXJpYWxpemVyLCBzdG9yZSwgbW9kZWxDbGFzcywgYWRhcHRlclBheWxvYWQsIG51bGwsICdmaW5kQWxsJyk7CgogICAgICBzdG9yZS5fcHVzaChwYXlsb2FkKTsKCiAgICAgIHN0b3JlLl9kaWRVcGRhdGVBbGwobW9kZWxOYW1lKTsKCiAgICAgIHJldHVybiByZWNvcmRBcnJheTsKICAgIH0sIG51bGwsICdEUzogRXh0cmFjdCBwYXlsb2FkIG9mIGZpbmRBbGwgJHttb2RlbE5hbWV9Jyk7CiAgfQogIGZ1bmN0aW9uIF9xdWVyeShhZGFwdGVyLCBzdG9yZSwgbW9kZWxOYW1lLCBxdWVyeSwgcmVjb3JkQXJyYXksIG9wdGlvbnMpIHsKICAgIHZhciBtb2RlbENsYXNzID0gc3RvcmUubW9kZWxGb3IobW9kZWxOYW1lKTsgLy8gYWRhcHRlci5xdWVyeSBuZWVkcyB0aGUgY2xhc3MKCiAgICByZWNvcmRBcnJheSA9IHJlY29yZEFycmF5IHx8IHN0b3JlLnJlY29yZEFycmF5TWFuYWdlci5jcmVhdGVBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXkobW9kZWxOYW1lLCBxdWVyeSk7CiAgICB2YXIgcHJvbWlzZSA9IEVtYmVyLlJTVlAuUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBhZGFwdGVyLnF1ZXJ5KHN0b3JlLCBtb2RlbENsYXNzLCBxdWVyeSwgcmVjb3JkQXJyYXksIG9wdGlvbnMpOwogICAgfSk7CiAgICB2YXIgbGFiZWwgPSAiRFM6IEhhbmRsZSBBZGFwdGVyI3F1ZXJ5IG9mICIgKyBtb2RlbE5hbWU7CiAgICBwcm9taXNlID0gZ3VhcmREZXN0cm95ZWRTdG9yZShwcm9taXNlLCBzdG9yZSwgbGFiZWwpOwogICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAoYWRhcHRlclBheWxvYWQpIHsKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBzdG9yZS5zZXJpYWxpemVyRm9yKG1vZGVsTmFtZSk7CiAgICAgIHZhciBwYXlsb2FkID0gbm9ybWFsaXplUmVzcG9uc2VIZWxwZXIoc2VyaWFsaXplciwgc3RvcmUsIG1vZGVsQ2xhc3MsIGFkYXB0ZXJQYXlsb2FkLCBudWxsLCAncXVlcnknKTsKCiAgICAgIHZhciBpbnRlcm5hbE1vZGVscyA9IHN0b3JlLl9wdXNoKHBheWxvYWQpOwoKICAgICAgaWYgKHJlY29yZEFycmF5KSB7CiAgICAgICAgcmVjb3JkQXJyYXkuX3NldEludGVybmFsTW9kZWxzKGludGVybmFsTW9kZWxzLCBwYXlsb2FkKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZWNvcmRBcnJheSA9IHN0b3JlLnJlY29yZEFycmF5TWFuYWdlci5jcmVhdGVBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXkobW9kZWxOYW1lLCBxdWVyeSwgaW50ZXJuYWxNb2RlbHMsIHBheWxvYWQpOwogICAgICB9CgogICAgICByZXR1cm4gcmVjb3JkQXJyYXk7CiAgICB9LCBudWxsLCAiRFM6IEV4dHJhY3QgcGF5bG9hZCBvZiBxdWVyeSAiICsgbW9kZWxOYW1lKTsKICB9CiAgZnVuY3Rpb24gX3F1ZXJ5UmVjb3JkKGFkYXB0ZXIsIHN0b3JlLCBtb2RlbE5hbWUsIHF1ZXJ5LCBvcHRpb25zKSB7CiAgICB2YXIgbW9kZWxDbGFzcyA9IHN0b3JlLm1vZGVsRm9yKG1vZGVsTmFtZSk7IC8vIGFkYXB0ZXIucXVlcnlSZWNvcmQgbmVlZHMgdGhlIGNsYXNzCgogICAgdmFyIHByb21pc2UgPSBFbWJlci5SU1ZQLlByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gYWRhcHRlci5xdWVyeVJlY29yZChzdG9yZSwgbW9kZWxDbGFzcywgcXVlcnksIG9wdGlvbnMpOwogICAgfSk7CiAgICB2YXIgbGFiZWwgPSAiRFM6IEhhbmRsZSBBZGFwdGVyI3F1ZXJ5UmVjb3JkIG9mICIgKyBtb2RlbE5hbWU7CiAgICBwcm9taXNlID0gZ3VhcmREZXN0cm95ZWRTdG9yZShwcm9taXNlLCBzdG9yZSwgbGFiZWwpOwogICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAoYWRhcHRlclBheWxvYWQpIHsKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBzdG9yZS5zZXJpYWxpemVyRm9yKG1vZGVsTmFtZSk7CiAgICAgIHZhciBwYXlsb2FkID0gbm9ybWFsaXplUmVzcG9uc2VIZWxwZXIoc2VyaWFsaXplciwgc3RvcmUsIG1vZGVsQ2xhc3MsIGFkYXB0ZXJQYXlsb2FkLCBudWxsLCAncXVlcnlSZWNvcmQnKTsKICAgICAgcmV0dXJuIHN0b3JlLl9wdXNoKHBheWxvYWQpOwogICAgfSwgbnVsbCwgIkRTOiBFeHRyYWN0IHBheWxvYWQgb2YgcXVlcnlSZWNvcmQgIiArIG1vZGVsTmFtZSk7CiAgfQoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICAvKioKICAgIFJlcHJlc2VudHMgYW4gb3JkZXJlZCBsaXN0IG9mIHJlY29yZHMgd2hvc2Ugb3JkZXIgYW5kIG1lbWJlcnNoaXAgaXMKICAgIGRldGVybWluZWQgYnkgdGhlIGFkYXB0ZXIuIEZvciBleGFtcGxlLCBhIHF1ZXJ5IHNlbnQgdG8gdGhlIGFkYXB0ZXIKICAgIG1heSB0cmlnZ2VyIGEgc2VhcmNoIG9uIHRoZSBzZXJ2ZXIsIHdob3NlIHJlc3VsdHMgd291bGQgYmUgbG9hZGVkCiAgICBpbnRvIGFuIGluc3RhbmNlIG9mIHRoZSBgQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5YC4KCiAgICAtLS0KCiAgICBJZiB5b3Ugd2FudCB0byB1cGRhdGUgdGhlIGFycmF5IGFuZCBnZXQgdGhlIGxhdGVzdCByZWNvcmRzIGZyb20gdGhlCiAgICBhZGFwdGVyLCB5b3UgY2FuIGludm9rZSBbYHVwZGF0ZSgpYF0oQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5L21ldGhvZHMvdXBkYXRlP2FuY2hvcj11cGRhdGUpOgoKICAgIEV4YW1wbGUKCiAgICBgYGBqYXZhc2NyaXB0CiAgICAvLyBHRVQgL3VzZXJzP2lzQWRtaW49dHJ1ZQogICAgc3RvcmUucXVlcnkoJ3VzZXInLCB7IGlzQWRtaW46IHRydWUgfSkudGhlbihmdW5jdGlvbihhZG1pbnMpIHsKCiAgICAgIGFkbWlucy50aGVuKGZ1bmN0aW9uKCkgewogICAgICAgIGNvbnNvbGUubG9nKGFkbWlucy5nZXQoImxlbmd0aCIpKTsgLy8gNDIKICAgICAgfSk7CgogICAgICAvLyBzb21ld2hlcmUgbGF0ZXIgaW4gdGhlIGFwcCBjb2RlLCB3aGVuIG5ldyBhZG1pbnMgaGF2ZSBiZWVuIGNyZWF0ZWQKICAgICAgLy8gaW4gdGhlIG1lYW50aW1lCiAgICAgIC8vCiAgICAgIC8vIEdFVCAvdXNlcnM/aXNBZG1pbj10cnVlCiAgICAgIGFkbWlucy51cGRhdGUoKS50aGVuKGZ1bmN0aW9uKCkgewogICAgICAgIGFkbWlucy5nZXQoJ2lzVXBkYXRpbmcnKTsgLy8gZmFsc2UKICAgICAgICBjb25zb2xlLmxvZyhhZG1pbnMuZ2V0KCJsZW5ndGgiKSk7IC8vIDEyMwogICAgICB9KTsKCiAgICAgIGFkbWlucy5nZXQoJ2lzVXBkYXRpbmcnKTsgLy8gdHJ1ZQogICAgfQogICAgYGBgCgogICAgQGNsYXNzIEFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheQogICAgQGV4dGVuZHMgUmVjb3JkQXJyYXkKICAqLwogIHZhciBBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXkgPSBSZWNvcmRBcnJheS5leHRlbmQoewogICAgaW5pdDogZnVuY3Rpb24gaW5pdCgpIHsKCiAgICAgIC8vIHllcyB3ZSBhcmUgdG91Y2hpbmcgYHRoaXNgIGJlZm9yZSBzdXBlciwgYnV0IEFycmF5UHJveHkgaGFzIGEgYnVnIHRoYXQgcmVxdWlyZXMgdGhpcy4KICAgICAgdGhpcy5zZXQoJ2NvbnRlbnQnLCB0aGlzLmdldCgnY29udGVudCcpIHx8IEVtYmVyLkEoKSk7CgogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgdGhpcy5xdWVyeSA9IHRoaXMucXVlcnkgfHwgbnVsbDsKICAgICAgdGhpcy5saW5rcyA9IHRoaXMubGlua3MgfHwgbnVsbDsKICAgIH0sCiAgICByZXBsYWNlOiBmdW5jdGlvbiByZXBsYWNlKCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIlRoZSByZXN1bHQgb2YgYSBzZXJ2ZXIgcXVlcnkgKG9uICIgKyB0aGlzLm1vZGVsTmFtZSArICIpIGlzIGltbXV0YWJsZS4iKTsKICAgIH0sCiAgICBfdXBkYXRlOiBmdW5jdGlvbiBfdXBkYXRlKCkgewogICAgICB2YXIgc3RvcmUgPSBFbWJlci5nZXQodGhpcywgJ3N0b3JlJyk7CiAgICAgIHZhciBxdWVyeSA9IEVtYmVyLmdldCh0aGlzLCAncXVlcnknKTsKICAgICAgcmV0dXJuIHN0b3JlLl9xdWVyeSh0aGlzLm1vZGVsTmFtZSwgcXVlcnksIHRoaXMpOwogICAgfSwKCiAgICAvKioKICAgICAgQG1ldGhvZCBfc2V0SW50ZXJuYWxNb2RlbHMKICAgICAgQHBhcmFtIHtBcnJheX0gaW50ZXJuYWxNb2RlbHMKICAgICAgQHBhcmFtIHtPYmplY3R9IHBheWxvYWQgbm9ybWFsaXplZCBwYXlsb2FkCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgX3NldEludGVybmFsTW9kZWxzOiBmdW5jdGlvbiBfc2V0SW50ZXJuYWxNb2RlbHMoaW50ZXJuYWxNb2RlbHMsIHBheWxvYWQpIHsKICAgICAgLy8gVE9ETzogaW5pdGlhbCBsb2FkIHNob3VsZCBub3QgY2F1c2UgY2hhbmdlIGV2ZW50cyBhdCBhbGwsIG9ubHkKICAgICAgLy8gc3Vic2VxdWVudC4gVGhpcyByZXF1aXJlcyBjaGFuZ2luZyB0aGUgcHVibGljIGFwaSBvZiBhZGFwdGVyLnF1ZXJ5LCBidXQKICAgICAgLy8gaG9wZWZ1bGx5IHdlIGNhbiBkbyB0aGF0IHNvb24uCiAgICAgIHRoaXMuZ2V0KCdjb250ZW50Jykuc2V0T2JqZWN0cyhpbnRlcm5hbE1vZGVscyk7CiAgICAgIHRoaXMuc2V0UHJvcGVydGllcyh7CiAgICAgICAgaXNMb2FkZWQ6IHRydWUsCiAgICAgICAgaXNVcGRhdGluZzogZmFsc2UsCiAgICAgICAgbWV0YTogRW1iZXIuYXNzaWduKHt9LCBwYXlsb2FkLm1ldGEpLAogICAgICAgIGxpbmtzOiBFbWJlci5hc3NpZ24oe30sIHBheWxvYWQubGlua3MpCiAgICAgIH0pOwoKICAgICAgdGhpcy5tYW5hZ2VyLl9hc3NvY2lhdGVXaXRoUmVjb3JkQXJyYXkoaW50ZXJuYWxNb2RlbHMsIHRoaXMpOwoKICAgICAgdmFyIF9oYXNEaWRMb2FkID0gIHRoaXMuaGFzKCdkaWRMb2FkJyk7CgogICAgICBpZiAoX2hhc0RpZExvYWQpIHsKICAgICAgICAvLyBUT0RPOiBzaG91bGQgdHJpZ2dlcmluZyBkaWRMb2FkIGV2ZW50IGJlIHRoZSBsYXN0IGFjdGlvbiBvZiB0aGUgcnVuTG9vcD8KICAgICAgICBFbWJlci5ydW4ub25jZSh0aGlzLCAndHJpZ2dlcicsICdkaWRMb2FkJyk7CiAgICAgIH0KICAgIH0KICB9KTsKCiAgdmFyIGVtYmVyUnVuJDEgPSBFbWJlci5ydW4uYmFja2J1cm5lcjsKICAvKioKICAgIEBjbGFzcyBSZWNvcmRBcnJheU1hbmFnZXIKICAgIEBwcml2YXRlCiAgKi8KCiAgdmFyIFJlY29yZEFycmF5TWFuYWdlciA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJlY29yZEFycmF5TWFuYWdlcihvcHRpb25zKSB7CiAgICAgIHRoaXMuc3RvcmUgPSBvcHRpb25zLnN0b3JlOwogICAgICB0aGlzLmlzRGVzdHJveWluZyA9IGZhbHNlOwogICAgICB0aGlzLmlzRGVzdHJveWVkID0gZmFsc2U7CiAgICAgIHRoaXMuX2xpdmVSZWNvcmRBcnJheXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9wZW5kaW5nID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGhpcy5fYWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5cyA9IFtdOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBSZWNvcmRBcnJheU1hbmFnZXIucHJvdG90eXBlOwoKICAgIF9wcm90by5yZWNvcmREaWRDaGFuZ2UgPSBmdW5jdGlvbiByZWNvcmREaWRDaGFuZ2UoaW50ZXJuYWxNb2RlbCkgewogICAgICAvLyBUT0RPOiBjaGFuZ2UgbmFtZQogICAgICAvLyBUT0RPOiB0cmFjayB0aGF0IGl0IHdhcyBhbHNvIGEgY2hhbmdlCiAgICAgIHRoaXMuaW50ZXJuYWxNb2RlbERpZENoYW5nZShpbnRlcm5hbE1vZGVsKTsKICAgIH07CgogICAgX3Byb3RvLnJlY29yZFdhc0xvYWRlZCA9IGZ1bmN0aW9uIHJlY29yZFdhc0xvYWRlZChpbnRlcm5hbE1vZGVsKSB7CiAgICAgIC8vIFRPRE86IGNoYW5nZSBuYW1lCiAgICAgIC8vIFRPRE86IHRyYWNrIHRoYXQgaXQgd2FzIGFsc28gdGhhdCBpdCB3YXMgZmlyc3QgbG9hZGVkCiAgICAgIHRoaXMuaW50ZXJuYWxNb2RlbERpZENoYW5nZShpbnRlcm5hbE1vZGVsKTsKICAgIH07CgogICAgX3Byb3RvLmludGVybmFsTW9kZWxEaWRDaGFuZ2UgPSBmdW5jdGlvbiBpbnRlcm5hbE1vZGVsRGlkQ2hhbmdlKGludGVybmFsTW9kZWwpIHsKICAgICAgdmFyIG1vZGVsTmFtZSA9IGludGVybmFsTW9kZWwubW9kZWxOYW1lOwoKICAgICAgaWYgKGludGVybmFsTW9kZWwuX3BlbmRpbmdSZWNvcmRBcnJheU1hbmFnZXJGbHVzaCkgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgaW50ZXJuYWxNb2RlbC5fcGVuZGluZ1JlY29yZEFycmF5TWFuYWdlckZsdXNoID0gdHJ1ZTsKICAgICAgdmFyIHBlbmRpbmcgPSB0aGlzLl9wZW5kaW5nOwogICAgICB2YXIgbW9kZWxzID0gcGVuZGluZ1ttb2RlbE5hbWVdID0gcGVuZGluZ1ttb2RlbE5hbWVdIHx8IFtdOwoKICAgICAgaWYgKG1vZGVscy5wdXNoKGludGVybmFsTW9kZWwpICE9PSAxKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBlbWJlclJ1biQxLnNjaGVkdWxlKCdhY3Rpb25zJywgdGhpcywgdGhpcy5fZmx1c2gpOwogICAgfTsKCiAgICBfcHJvdG8uX2ZsdXNoUGVuZGluZ0ludGVybmFsTW9kZWxzRm9yTW9kZWxOYW1lID0gZnVuY3Rpb24gX2ZsdXNoUGVuZGluZ0ludGVybmFsTW9kZWxzRm9yTW9kZWxOYW1lKG1vZGVsTmFtZSwgaW50ZXJuYWxNb2RlbHMpIHsKICAgICAgdmFyIG1vZGVsc1RvUmVtb3ZlID0gW107CgogICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGludGVybmFsTW9kZWxzLmxlbmd0aDsgaisrKSB7CiAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsc1tqXTsgLy8gbWFyayBpbnRlcm5hbE1vZGVscywgc28gdGhleSBjYW4gb25jZSBhZ2FpbiBiZSBwcm9jZXNzZWQgYnkgdGhlCiAgICAgICAgLy8gcmVjb3JkQXJyYXlNYW5hZ2VyCgogICAgICAgIGludGVybmFsTW9kZWwuX3BlbmRpbmdSZWNvcmRBcnJheU1hbmFnZXJGbHVzaCA9IGZhbHNlOyAvLyBidWlsZCB1cCBhIHNldCBvZiBtb2RlbHMgdG8gZW5zdXJlIHdlIGhhdmUgcHVyZ2VkIGNvcnJlY3RseTsKCiAgICAgICAgaWYgKGludGVybmFsTW9kZWwuaXNIaWRkZW5Gcm9tUmVjb3JkQXJyYXlzKCkpIHsKICAgICAgICAgIG1vZGVsc1RvUmVtb3ZlLnB1c2goaW50ZXJuYWxNb2RlbCk7CiAgICAgICAgfQogICAgICB9CgogICAgICB2YXIgYXJyYXkgPSB0aGlzLl9saXZlUmVjb3JkQXJyYXlzW21vZGVsTmFtZV07CgogICAgICBpZiAoYXJyYXkpIHsKICAgICAgICAvLyBUT0RPOiBza2lwIGlmIGl0IG9ubHkgY2hhbmdlZAogICAgICAgIC8vIHByb2Nlc3MgbGl2ZVJlY29yZEFycmF5cwogICAgICAgIHRoaXMudXBkYXRlTGl2ZVJlY29yZEFycmF5KGFycmF5LCBpbnRlcm5hbE1vZGVscyk7CiAgICAgIH0gLy8gcHJvY2VzcyBhZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXlzCgoKICAgICAgaWYgKG1vZGVsc1RvUmVtb3ZlLmxlbmd0aCA+IDApIHsKICAgICAgICByZW1vdmVGcm9tQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5cyhtb2RlbHNUb1JlbW92ZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9mbHVzaCA9IGZ1bmN0aW9uIF9mbHVzaCgpIHsKICAgICAgdmFyIHBlbmRpbmcgPSB0aGlzLl9wZW5kaW5nOwogICAgICB0aGlzLl9wZW5kaW5nID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKCiAgICAgIGZvciAodmFyIG1vZGVsTmFtZSBpbiBwZW5kaW5nKSB7CiAgICAgICAgdGhpcy5fZmx1c2hQZW5kaW5nSW50ZXJuYWxNb2RlbHNGb3JNb2RlbE5hbWUobW9kZWxOYW1lLCBwZW5kaW5nW21vZGVsTmFtZV0pOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by51cGRhdGVMaXZlUmVjb3JkQXJyYXkgPSBmdW5jdGlvbiB1cGRhdGVMaXZlUmVjb3JkQXJyYXkoYXJyYXksIGludGVybmFsTW9kZWxzKSB7CiAgICAgIHJldHVybiBfdXBkYXRlTGl2ZVJlY29yZEFycmF5KGFycmF5LCBpbnRlcm5hbE1vZGVscyk7CiAgICB9OwoKICAgIF9wcm90by5fc3luY0xpdmVSZWNvcmRBcnJheSA9IGZ1bmN0aW9uIF9zeW5jTGl2ZVJlY29yZEFycmF5KGFycmF5LCBtb2RlbE5hbWUpIHsKICAgICAgdmFyIHBlbmRpbmcgPSB0aGlzLl9wZW5kaW5nW21vZGVsTmFtZV07CiAgICAgIHZhciBoYXNQZW5kaW5nQ2hhbmdlcyA9IEFycmF5LmlzQXJyYXkocGVuZGluZyk7CiAgICAgIHZhciBoYXNOb1BvdGVudGlhbERlbGV0aW9ucyA9ICFoYXNQZW5kaW5nQ2hhbmdlcyB8fCBwZW5kaW5nLmxlbmd0aCA9PT0gMDsKICAgICAgdmFyIG1hcCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMuc3RvcmUpLm1vZGVsTWFwRm9yKG1vZGVsTmFtZSk7CiAgICAgIHZhciBoYXNOb0luc2VydGlvbnNPclJlbW92YWxzID0gRW1iZXIuZ2V0KG1hcCwgJ2xlbmd0aCcpID09PSBFbWJlci5nZXQoYXJyYXksICdsZW5ndGgnKTsKICAgICAgLyoKICAgICAgICBJZGVhbGx5IHRoZSByZWNvcmRBcnJheU1hbmFnZXIgaGFzIGtub3dsZWRnZSBvZiB0aGUgY2hhbmdlcyB0byBiZSBhcHBsaWVkIHRvCiAgICAgICAgbGl2ZVJlY29yZEFycmF5cywgYW5kIGlzIGNhcGFibGUgb2Ygc3RyYXRlZ2ljYWxseSBmbHVzaGluZyB0aG9zZSBjaGFuZ2VzIGFuZCBhcHBseWluZwogICAgICAgIHNtYWxsIGRpZmZzIGlmIGRlc2lyZWQuICBIb3dldmVyLCB1bnRpbCB3ZSd2ZSByZWZhY3RvcmVkIHJlY29yZEFycmF5TWFuYWdlciwgdGhpcyBkaXJ0eQogICAgICAgIGNoZWNrIHByZXZlbnRzIHVzIGZyb20gdW5uZWNlc3NhcmlseSB3aXBpbmcgb3V0IGxpdmUgcmVjb3JkIGFycmF5cyByZXR1cm5lZCBieSBwZWVrQWxsLgogICAgICAgICovCgogICAgICBpZiAoaGFzTm9Qb3RlbnRpYWxEZWxldGlvbnMgJiYgaGFzTm9JbnNlcnRpb25zT3JSZW1vdmFscykgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgaWYgKGhhc1BlbmRpbmdDaGFuZ2VzKSB7CiAgICAgICAgdGhpcy5fZmx1c2hQZW5kaW5nSW50ZXJuYWxNb2RlbHNGb3JNb2RlbE5hbWUobW9kZWxOYW1lLCBwZW5kaW5nKTsKCiAgICAgICAgZGVsZXRlIHRoaXMuX3BlbmRpbmdbbW9kZWxOYW1lXTsKICAgICAgfQoKICAgICAgdmFyIGludGVybmFsTW9kZWxzID0gdGhpcy5fdmlzaWJsZUludGVybmFsTW9kZWxzQnlUeXBlKG1vZGVsTmFtZSk7CgogICAgICB2YXIgbW9kZWxzVG9BZGQgPSBbXTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW50ZXJuYWxNb2RlbHMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxzW2ldOwogICAgICAgIHZhciByZWNvcmRBcnJheXMgPSBpbnRlcm5hbE1vZGVsLl9yZWNvcmRBcnJheXM7CgogICAgICAgIGlmIChyZWNvcmRBcnJheXMuaGFzKGFycmF5KSA9PT0gZmFsc2UpIHsKICAgICAgICAgIHJlY29yZEFycmF5cy5hZGQoYXJyYXkpOwogICAgICAgICAgbW9kZWxzVG9BZGQucHVzaChpbnRlcm5hbE1vZGVsKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGlmIChtb2RlbHNUb0FkZC5sZW5ndGgpIHsKICAgICAgICBhcnJheS5fcHVzaEludGVybmFsTW9kZWxzKG1vZGVsc1RvQWRkKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2RpZFVwZGF0ZUFsbCA9IGZ1bmN0aW9uIF9kaWRVcGRhdGVBbGwobW9kZWxOYW1lKSB7CiAgICAgIHZhciByZWNvcmRBcnJheSA9IHRoaXMuX2xpdmVSZWNvcmRBcnJheXNbbW9kZWxOYW1lXTsKCiAgICAgIGlmIChyZWNvcmRBcnJheSkgewogICAgICAgIEVtYmVyLnNldChyZWNvcmRBcnJheSwgJ2lzVXBkYXRpbmcnLCBmYWxzZSk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBHZXQgdGhlIGBSZWNvcmRBcnJheWAgZm9yIGEgbW9kZWxOYW1lLCB3aGljaCBjb250YWlucyBhbGwgbG9hZGVkIHJlY29yZHMgb2YKICAgICAgZ2l2ZW4gbW9kZWxOYW1lLgogICAgICAgQG1ldGhvZCBsaXZlUmVjb3JkQXJyYXlGb3IKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcmV0dXJuIHtSZWNvcmRBcnJheX0KICAgICovCiAgICA7CgogICAgX3Byb3RvLmxpdmVSZWNvcmRBcnJheUZvciA9IGZ1bmN0aW9uIGxpdmVSZWNvcmRBcnJheUZvcihtb2RlbE5hbWUpIHsKICAgICAgdmFyIGFycmF5ID0gdGhpcy5fbGl2ZVJlY29yZEFycmF5c1ttb2RlbE5hbWVdOwoKICAgICAgaWYgKGFycmF5KSB7CiAgICAgICAgLy8gaWYgdGhlIGFycmF5IGFscmVhZHkgZXhpc3RzLCBzeW5jaHJvbml6ZQogICAgICAgIHRoaXMuX3N5bmNMaXZlUmVjb3JkQXJyYXkoYXJyYXksIG1vZGVsTmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gaWYgdGhlIGFycmF5IGlzIGJlaW5nIG5ld2x5IGNyZWF0ZWQgbWVyZWx5IGNyZWF0ZSBpdCB3aXRoIGl0cyBpbml0aWFsCiAgICAgICAgLy8gY29udGVudCBhbHJlYWR5IHNldC4gVGhpcyBwcmV2ZW50cyB1bm5lZWRlZCBjaGFuZ2UgZXZlbnRzLgogICAgICAgIHZhciBpbnRlcm5hbE1vZGVscyA9IHRoaXMuX3Zpc2libGVJbnRlcm5hbE1vZGVsc0J5VHlwZShtb2RlbE5hbWUpOwoKICAgICAgICBhcnJheSA9IHRoaXMuY3JlYXRlUmVjb3JkQXJyYXkobW9kZWxOYW1lLCBpbnRlcm5hbE1vZGVscyk7CiAgICAgICAgdGhpcy5fbGl2ZVJlY29yZEFycmF5c1ttb2RlbE5hbWVdID0gYXJyYXk7CiAgICAgIH0KCiAgICAgIHJldHVybiBhcnJheTsKICAgIH07CgogICAgX3Byb3RvLl92aXNpYmxlSW50ZXJuYWxNb2RlbHNCeVR5cGUgPSBmdW5jdGlvbiBfdmlzaWJsZUludGVybmFsTW9kZWxzQnlUeXBlKG1vZGVsTmFtZSkgewogICAgICB2YXIgYWxsID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcy5zdG9yZSkubW9kZWxNYXBGb3IobW9kZWxOYW1lKS5fbW9kZWxzOwoKICAgICAgdmFyIHZpc2libGUgPSBbXTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYWxsLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIG1vZGVsID0gYWxsW2ldOwoKICAgICAgICBpZiAobW9kZWwuaXNIaWRkZW5Gcm9tUmVjb3JkQXJyYXlzKCkgPT09IGZhbHNlKSB7CiAgICAgICAgICB2aXNpYmxlLnB1c2gobW9kZWwpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIHZpc2libGU7CiAgICB9CiAgICAvKioKICAgICAgQ3JlYXRlIGEgYFJlY29yZEFycmF5YCBmb3IgYSBtb2RlbE5hbWUuCiAgICAgICBAbWV0aG9kIGNyZWF0ZVJlY29yZEFycmF5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHBhcmFtIHtBcnJheX0gX2NvbnRlbnQgKG9wdGlvbmFsfHByaXZhdGUpCiAgICAgIEByZXR1cm4ge1JlY29yZEFycmF5fQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uY3JlYXRlUmVjb3JkQXJyYXkgPSBmdW5jdGlvbiBjcmVhdGVSZWNvcmRBcnJheShtb2RlbE5hbWUsIGNvbnRlbnQpIHsKICAgICAgdmFyIGFycmF5ID0gUmVjb3JkQXJyYXkuY3JlYXRlKHsKICAgICAgICBtb2RlbE5hbWU6IG1vZGVsTmFtZSwKICAgICAgICBjb250ZW50OiBFbWJlci5BKGNvbnRlbnQgfHwgW10pLAogICAgICAgIHN0b3JlOiB0aGlzLnN0b3JlLAogICAgICAgIGlzTG9hZGVkOiB0cnVlLAogICAgICAgIG1hbmFnZXI6IHRoaXMKICAgICAgfSk7CgogICAgICBpZiAoQXJyYXkuaXNBcnJheShjb250ZW50KSkgewogICAgICAgIGFzc29jaWF0ZVdpdGhSZWNvcmRBcnJheShjb250ZW50LCBhcnJheSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBhcnJheTsKICAgIH0KICAgIC8qKgogICAgICBDcmVhdGUgYSBgQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5YCBmb3IgYSBtb2RlbE5hbWUgd2l0aCBnaXZlbiBxdWVyeS4KICAgICAgIEBtZXRob2QgY3JlYXRlQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5CiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHBhcmFtIHtPYmplY3R9IHF1ZXJ5CiAgICAgIEByZXR1cm4ge0FkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheX0KICAgICovCiAgICA7CgogICAgX3Byb3RvLmNyZWF0ZUFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheSA9IGZ1bmN0aW9uIGNyZWF0ZUFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheShtb2RlbE5hbWUsIHF1ZXJ5LCBpbnRlcm5hbE1vZGVscywgcGF5bG9hZCkgewogICAgICB2YXIgYXJyYXk7CgogICAgICBpZiAoQXJyYXkuaXNBcnJheShpbnRlcm5hbE1vZGVscykpIHsKICAgICAgICBhcnJheSA9IEFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheS5jcmVhdGUoewogICAgICAgICAgbW9kZWxOYW1lOiBtb2RlbE5hbWUsCiAgICAgICAgICBxdWVyeTogcXVlcnksCiAgICAgICAgICBjb250ZW50OiBFbWJlci5BKGludGVybmFsTW9kZWxzKSwKICAgICAgICAgIHN0b3JlOiB0aGlzLnN0b3JlLAogICAgICAgICAgbWFuYWdlcjogdGhpcywKICAgICAgICAgIGlzTG9hZGVkOiB0cnVlLAogICAgICAgICAgaXNVcGRhdGluZzogZmFsc2UsCiAgICAgICAgICBtZXRhOiBFbWJlci5hc3NpZ24oe30sIHBheWxvYWQubWV0YSksCiAgICAgICAgICBsaW5rczogRW1iZXIuYXNzaWduKHt9LCBwYXlsb2FkLmxpbmtzKQogICAgICAgIH0pOwogICAgICAgIGFzc29jaWF0ZVdpdGhSZWNvcmRBcnJheShpbnRlcm5hbE1vZGVscywgYXJyYXkpOwogICAgICB9IGVsc2UgewogICAgICAgIGFycmF5ID0gQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5LmNyZWF0ZSh7CiAgICAgICAgICBtb2RlbE5hbWU6IG1vZGVsTmFtZSwKICAgICAgICAgIHF1ZXJ5OiBxdWVyeSwKICAgICAgICAgIGNvbnRlbnQ6IEVtYmVyLkEoKSwKICAgICAgICAgIHN0b3JlOiB0aGlzLnN0b3JlLAogICAgICAgICAgbWFuYWdlcjogdGhpcwogICAgICAgIH0pOwogICAgICB9CgogICAgICB0aGlzLl9hZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXlzLnB1c2goYXJyYXkpOwoKICAgICAgcmV0dXJuIGFycmF5OwogICAgfQogICAgLyoqCiAgICAgIFVucmVnaXN0ZXIgYSBSZWNvcmRBcnJheS4KICAgICAgU28gbWFuYWdlciB3aWxsIG5vdCB1cGRhdGUgdGhpcyBhcnJheS4KICAgICAgIEBtZXRob2QgdW5yZWdpc3RlclJlY29yZEFycmF5CiAgICAgIEBwYXJhbSB7UmVjb3JkQXJyYXl9IGFycmF5CiAgICAqLwogICAgOwoKICAgIF9wcm90by51bnJlZ2lzdGVyUmVjb3JkQXJyYXkgPSBmdW5jdGlvbiB1bnJlZ2lzdGVyUmVjb3JkQXJyYXkoYXJyYXkpIHsKICAgICAgdmFyIG1vZGVsTmFtZSA9IGFycmF5Lm1vZGVsTmFtZTsgLy8gcmVtb3ZlIGZyb20gYWRhcHRlciBwb3B1bGF0ZWQgcmVjb3JkIGFycmF5CgogICAgICB2YXIgcmVtb3ZlZEZyb21BZGFwdGVyUG9wdWxhdGVkID0gcmVtb3ZlKHRoaXMuX2FkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheXMsIGFycmF5KTsKCiAgICAgIGlmICghcmVtb3ZlZEZyb21BZGFwdGVyUG9wdWxhdGVkKSB7CiAgICAgICAgdmFyIGxpdmVSZWNvcmRBcnJheUZvclR5cGUgPSB0aGlzLl9saXZlUmVjb3JkQXJyYXlzW21vZGVsTmFtZV07IC8vIHVucmVnaXN0ZXIgbGl2ZSByZWNvcmQgYXJyYXkKCiAgICAgICAgaWYgKGxpdmVSZWNvcmRBcnJheUZvclR5cGUpIHsKICAgICAgICAgIGlmIChhcnJheSA9PT0gbGl2ZVJlY29yZEFycmF5Rm9yVHlwZSkgewogICAgICAgICAgICBkZWxldGUgdGhpcy5fbGl2ZVJlY29yZEFycmF5c1ttb2RlbE5hbWVdOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2Fzc29jaWF0ZVdpdGhSZWNvcmRBcnJheSA9IGZ1bmN0aW9uIF9hc3NvY2lhdGVXaXRoUmVjb3JkQXJyYXkoaW50ZXJuYWxNb2RlbHMsIGFycmF5KSB7CiAgICAgIGFzc29jaWF0ZVdpdGhSZWNvcmRBcnJheShpbnRlcm5hbE1vZGVscywgYXJyYXkpOwogICAgfTsKCiAgICBfcHJvdG8ud2lsbERlc3Ryb3kgPSBmdW5jdGlvbiB3aWxsRGVzdHJveSgpIHsKICAgICAgdmFyIF90aGlzID0gdGhpczsKCiAgICAgIE9iamVjdC5rZXlzKHRoaXMuX2xpdmVSZWNvcmRBcnJheXMpLmZvckVhY2goZnVuY3Rpb24gKG1vZGVsTmFtZSkgewogICAgICAgIHJldHVybiBfdGhpcy5fbGl2ZVJlY29yZEFycmF5c1ttb2RlbE5hbWVdLmRlc3Ryb3koKTsKICAgICAgfSk7CgogICAgICB0aGlzLl9hZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXlzLmZvckVhY2goZGVzdHJveSk7CgogICAgICB0aGlzLmlzRGVzdHJveWVkID0gdHJ1ZTsKICAgIH07CgogICAgX3Byb3RvLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkgewogICAgICB0aGlzLmlzRGVzdHJveWluZyA9IHRydWU7CiAgICAgIGVtYmVyUnVuJDEuc2NoZWR1bGUoJ2FjdGlvbnMnLCB0aGlzLCB0aGlzLndpbGxEZXN0cm95KTsKICAgIH07CgogICAgcmV0dXJuIFJlY29yZEFycmF5TWFuYWdlcjsKICB9KCk7CgogIGZ1bmN0aW9uIGRlc3Ryb3koZW50cnkpIHsKICAgIGVudHJ5LmRlc3Ryb3koKTsKICB9CgogIGZ1bmN0aW9uIHJlbW92ZShhcnJheSwgaXRlbSkgewogICAgdmFyIGluZGV4ID0gYXJyYXkuaW5kZXhPZihpdGVtKTsKCiAgICBpZiAoaW5kZXggIT09IC0xKSB7CiAgICAgIGFycmF5LnNwbGljZShpbmRleCwgMSk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIHJldHVybiBmYWxzZTsKICB9CgogIGZ1bmN0aW9uIF91cGRhdGVMaXZlUmVjb3JkQXJyYXkoYXJyYXksIGludGVybmFsTW9kZWxzKSB7CiAgICB2YXIgbW9kZWxzVG9BZGQgPSBbXTsKICAgIHZhciBtb2RlbHNUb1JlbW92ZSA9IFtdOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW50ZXJuYWxNb2RlbHMubGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsc1tpXTsKICAgICAgdmFyIGlzRGVsZXRlZCA9IGludGVybmFsTW9kZWwuaXNIaWRkZW5Gcm9tUmVjb3JkQXJyYXlzKCk7CiAgICAgIHZhciByZWNvcmRBcnJheXMgPSBpbnRlcm5hbE1vZGVsLl9yZWNvcmRBcnJheXM7CgogICAgICBpZiAoIWlzRGVsZXRlZCAmJiAhaW50ZXJuYWxNb2RlbC5pc0VtcHR5KCkpIHsKICAgICAgICBpZiAoIXJlY29yZEFycmF5cy5oYXMoYXJyYXkpKSB7CiAgICAgICAgICBtb2RlbHNUb0FkZC5wdXNoKGludGVybmFsTW9kZWwpOwogICAgICAgICAgcmVjb3JkQXJyYXlzLmFkZChhcnJheSk7CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoaXNEZWxldGVkKSB7CiAgICAgICAgbW9kZWxzVG9SZW1vdmUucHVzaChpbnRlcm5hbE1vZGVsKTsKICAgICAgICByZWNvcmRBcnJheXMuZGVsZXRlKGFycmF5KTsKICAgICAgfQogICAgfQoKICAgIGlmIChtb2RlbHNUb0FkZC5sZW5ndGggPiAwKSB7CiAgICAgIGFycmF5Ll9wdXNoSW50ZXJuYWxNb2RlbHMobW9kZWxzVG9BZGQpOwogICAgfQoKICAgIGlmIChtb2RlbHNUb1JlbW92ZS5sZW5ndGggPiAwKSB7CiAgICAgIGFycmF5Ll9yZW1vdmVJbnRlcm5hbE1vZGVscyhtb2RlbHNUb1JlbW92ZSk7CiAgICB9IC8vIHJldHVybiB3aGV0aGVyIHdlIHBlcmZvcm1lZCBhbiB1cGRhdGUuCiAgICAvLyBOZWNlc3NhcnkgdW50aWwgMy41IGFsbG93cyB1cyB0byBmaW5pc2ggb2ZmIGVtYmVyLWRhdGEtZmlsdGVyIHN1cHBvcnQuCgoKICAgIHJldHVybiAobW9kZWxzVG9BZGQubGVuZ3RoIHx8IG1vZGVsc1RvUmVtb3ZlLmxlbmd0aCkgPiAwOwogIH0KCiAgZnVuY3Rpb24gcmVtb3ZlRnJvbUFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheXMoaW50ZXJuYWxNb2RlbHMpIHsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW50ZXJuYWxNb2RlbHMubGVuZ3RoOyBpKyspIHsKICAgICAgcmVtb3ZlRnJvbUFsbChpbnRlcm5hbE1vZGVsc1tpXSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiByZW1vdmVGcm9tQWxsKGludGVybmFsTW9kZWwpIHsKICAgIHZhciByZWNvcmRBcnJheXMgPSBpbnRlcm5hbE1vZGVsLl9yZWNvcmRBcnJheXM7CiAgICByZWNvcmRBcnJheXMuZm9yRWFjaChmdW5jdGlvbiAocmVjb3JkQXJyYXkpIHsKICAgICAgcmVjb3JkQXJyYXkuX3JlbW92ZUludGVybmFsTW9kZWxzKFtpbnRlcm5hbE1vZGVsXSk7CiAgICB9KTsKICAgIHJlY29yZEFycmF5cy5jbGVhcigpOwogIH0KCiAgZnVuY3Rpb24gYXNzb2NpYXRlV2l0aFJlY29yZEFycmF5KGludGVybmFsTW9kZWxzLCBhcnJheSkgewogICAgZm9yICh2YXIgaSA9IDAsIGwgPSBpbnRlcm5hbE1vZGVscy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsc1tpXTsKCiAgICAgIGludGVybmFsTW9kZWwuX3JlY29yZEFycmF5cy5hZGQoYXJyYXkpOwogICAgfQogIH0KCiAgdmFyIGJhY2tidXJuZXIgPSBuZXcgRW1iZXIuX0JhY2tidXJuZXIoWydub3JtYWxpemVSZWxhdGlvbnNoaXBzJywgJ3N5bmNSZWxhdGlvbnNoaXBzJywgJ2ZpbmlzaGVkJ10pOwoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwoKICAvKioKICAgKiBHZXQgdGhlIG1hdGVyaWFsaXplZCBtb2RlbCBmcm9tIHRoZSBpbnRlcm5hbE1vZGVsL3Byb21pc2UKICAgKiB0aGF0IHJldHVybnMgYW4gaW50ZXJuYWwgbW9kZWwgYW5kIHJldHVybiBpdCBpbiBhIHByb21pc2VPYmplY3QuCiAgICoKICAgKiBVc2VmdWwgZm9yIHJldHVybmluZyBmcm9tIGZpbmQgbWV0aG9kcwogICAqCiAgICogQGludGVybmFsCiAgICovCiAgZnVuY3Rpb24gcHJvbWlzZVJlY29yZChpbnRlcm5hbE1vZGVsUHJvbWlzZSwgbGFiZWwpIHsKICAgIHZhciB0b1JldHVybiA9IGludGVybmFsTW9kZWxQcm9taXNlLnRoZW4oZnVuY3Rpb24gKGludGVybmFsTW9kZWwpIHsKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwuZ2V0UmVjb3JkKCk7CiAgICB9KTsKICAgIHJldHVybiBwcm9taXNlT2JqZWN0KHRvUmV0dXJuLCBsYWJlbCk7CiAgfQoKICB2YXIgQ2FjaGUgPSBuZXcgV2Vha01hcCgpOwogIHZhciBUb2tlbnMgPSBuZXcgV2Vha01hcCgpOwogIC8qCiAgICBDdXJyZW50bHkgb25seSBzdXBwb3J0IGEgc2luZ2xlIGNhbGxiYWNrIHBlciBpZGVudGlmaWVyCiAgKi8KCiAgdmFyIE5vdGlmaWNhdGlvbk1hbmFnZXIgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBOb3RpZmljYXRpb25NYW5hZ2VyKHN0b3JlKSB7CiAgICAgIHRoaXMuc3RvcmUgPSBzdG9yZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gTm90aWZpY2F0aW9uTWFuYWdlci5wcm90b3R5cGU7CgogICAgX3Byb3RvLnN1YnNjcmliZSA9IGZ1bmN0aW9uIHN1YnNjcmliZShpZGVudGlmaWVyLCBjYWxsYmFjaykgewogICAgICB2YXIgc3RhYmxlSWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzLnN0b3JlKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIoaWRlbnRpZmllcik7CiAgICAgIENhY2hlLnNldChzdGFibGVJZGVudGlmaWVyLCBjYWxsYmFjayk7CiAgICAgIHZhciB1bnN1YlRva2VuID0gbmV3IE9iamVjdCgpOwogICAgICBUb2tlbnMuc2V0KHVuc3ViVG9rZW4sIHN0YWJsZUlkZW50aWZpZXIpOwogICAgICByZXR1cm4gaWRlbnRpZmllcjsKICAgIH07CgogICAgX3Byb3RvLm5vdGlmeSA9IGZ1bmN0aW9uIG5vdGlmeShpZGVudGlmaWVyLCB2YWx1ZSkgewogICAgICB2YXIgc3RhYmxlSWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzLnN0b3JlKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIoaWRlbnRpZmllcik7CiAgICAgIHZhciBjYWxsYmFjayA9IENhY2hlLmdldChzdGFibGVJZGVudGlmaWVyKTsKCiAgICAgIGlmICghY2FsbGJhY2spIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KCiAgICAgIGNhbGxiYWNrKHN0YWJsZUlkZW50aWZpZXIsIHZhbHVlKTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9OwoKICAgIHJldHVybiBOb3RpZmljYXRpb25NYW5hZ2VyOwogIH0oKTsKCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXMkNih0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgidmFsdWUiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfQoKICBmdW5jdGlvbiBfY3JlYXRlQ2xhc3MkNihDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDYoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQ2KENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfQoKICAvLyBNaW1pY3MgdGhlIHN0YXRpYyBhcGlzIG9mIERTTW9kZWwKICB2YXIgU2hpbU1vZGVsQ2xhc3MgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoKSB7CiAgICAvLyBUT0RPIE1heWJlIGV4cG9zZSB0aGUgY2xhc3MgaGVyZT8KICAgIGZ1bmN0aW9uIFNoaW1Nb2RlbENsYXNzKF9fc3RvcmUsIG1vZGVsTmFtZSkgewogICAgICB0aGlzLl9fc3RvcmUgPSBfX3N0b3JlOwogICAgICB0aGlzLm1vZGVsTmFtZSA9IG1vZGVsTmFtZTsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gU2hpbU1vZGVsQ2xhc3MucHJvdG90eXBlOwoKICAgIF9wcm90by5lYWNoQXR0cmlidXRlID0gZnVuY3Rpb24gZWFjaEF0dHJpYnV0ZShjYWxsYmFjaywgYmluZGluZykgewogICAgICB2YXIgYXR0ckRlZnMgPSB0aGlzLl9fc3RvcmUuX2F0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKHRoaXMubW9kZWxOYW1lKTsKCiAgICAgIE9iamVjdC5rZXlzKGF0dHJEZWZzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICBjYWxsYmFjay5jYWxsKGJpbmRpbmcsIGtleSwgYXR0ckRlZnNba2V5XSk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8uZWFjaFJlbGF0aW9uc2hpcCA9IGZ1bmN0aW9uIGVhY2hSZWxhdGlvbnNoaXAoY2FsbGJhY2ssIGJpbmRpbmcpIHsKICAgICAgdmFyIHJlbGF0aW9uc2hpcERlZnMgPSB0aGlzLl9fc3RvcmUuX3JlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKHRoaXMubW9kZWxOYW1lKTsKCiAgICAgIE9iamVjdC5rZXlzKHJlbGF0aW9uc2hpcERlZnMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgIGNhbGxiYWNrLmNhbGwoYmluZGluZywga2V5LCByZWxhdGlvbnNoaXBEZWZzW2tleV0pOwogICAgICB9KTsKICAgIH07CgogICAgX3Byb3RvLmVhY2hUcmFuc2Zvcm1lZEF0dHJpYnV0ZSA9IGZ1bmN0aW9uIGVhY2hUcmFuc2Zvcm1lZEF0dHJpYnV0ZShjYWxsYmFjaywgYmluZGluZykgewogICAgICB2YXIgcmVsYXRpb25zaGlwRGVmcyA9IHRoaXMuX19zdG9yZS5fcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IodGhpcy5tb2RlbE5hbWUpOwoKICAgICAgT2JqZWN0LmtleXMocmVsYXRpb25zaGlwRGVmcykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgaWYgKHJlbGF0aW9uc2hpcERlZnNba2V5XS50eXBlKSB7CiAgICAgICAgICBjYWxsYmFjay5jYWxsKGJpbmRpbmcsIGtleSwgcmVsYXRpb25zaGlwRGVmc1trZXldKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfTsKCiAgICBfY3JlYXRlQ2xhc3MkNihTaGltTW9kZWxDbGFzcywgW3sKICAgICAga2V5OiAiZmllbGRzIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIGF0dHJzID0gdGhpcy5fX3N0b3JlLl9hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvcih0aGlzLm1vZGVsTmFtZSk7CgogICAgICAgIHZhciByZWxhdGlvbnNoaXBzID0gdGhpcy5fX3N0b3JlLl9yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcih0aGlzLm1vZGVsTmFtZSk7CgogICAgICAgIHZhciBmaWVsZHMgPSBuZXcgTWFwKCk7CiAgICAgICAgT2JqZWN0LmtleXMoYXR0cnMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgcmV0dXJuIGZpZWxkcy5zZXQoa2V5LCAnYXR0cmlidXRlJyk7CiAgICAgICAgfSk7CiAgICAgICAgT2JqZWN0LmtleXMocmVsYXRpb25zaGlwcykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgICByZXR1cm4gZmllbGRzLnNldChrZXksIHJlbGF0aW9uc2hpcHNba2V5XS5raW5kKTsKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gZmllbGRzOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogImF0dHJpYnV0ZXMiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICB2YXIgYXR0cnMgPSB0aGlzLl9fc3RvcmUuX2F0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKHRoaXMubW9kZWxOYW1lKTsKCiAgICAgICAgcmV0dXJuIG5ldyBNYXAoT2JqZWN0LmVudHJpZXMoYXR0cnMpKTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJyZWxhdGlvbnNoaXBzQnlOYW1lIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgdmFyIHJlbGF0aW9uc2hpcHMgPSB0aGlzLl9fc3RvcmUuX3JlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKHRoaXMubW9kZWxOYW1lKTsKCiAgICAgICAgcmV0dXJuIG5ldyBNYXAoT2JqZWN0LmVudHJpZXMocmVsYXRpb25zaGlwcykpOwogICAgICB9CiAgICB9XSk7CgogICAgcmV0dXJuIFNoaW1Nb2RlbENsYXNzOwogIH0oKTsKCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXMkNyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgidmFsdWUiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfQoKICBmdW5jdGlvbiBfY3JlYXRlQ2xhc3MkNyhDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDcoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQ3KENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfQoKICBmdW5jdGlvbiBfYXNzZXJ0VGhpc0luaXRpYWxpemVkKHNlbGYpIHsgaWYgKHNlbGYgPT09IHZvaWQgMCkgeyB0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZCIpOyB9IHJldHVybiBzZWxmOyB9CgogIGZ1bmN0aW9uIF9pbmhlcml0c0xvb3NlJDMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzLnByb3RvdHlwZSk7IHN1YkNsYXNzLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IHN1YkNsYXNzOyBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9CiAgdmFyIGVtYmVyUnVuJDIgPSBFbWJlci5ydW4uYmFja2J1cm5lcjsKICB2YXIgRU5WID0gRW1iZXIuRU5WOwogIHZhciBIQVNfU0VSSUFMSVpFUl9QQUNLQUdFID0gcmVxdWlyZS5oYXMoJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXInKTsKICB2YXIgSEFTX0FEQVBURVJfUEFDS0FHRSA9IHJlcXVpcmUuaGFzKCdAZW1iZXItZGF0YS9hZGFwdGVyJyk7CiAgdmFyIEhBU19NT0RFTF9QQUNLQUdFID0gcmVxdWlyZS5oYXMoJ0BlbWJlci1kYXRhL21vZGVsJyk7CgogIHZhciBfTW9kZWw7CgogIGZ1bmN0aW9uIGdldE1vZGVsKCkgewogICAgaWYgKEhBU19NT0RFTF9QQUNLQUdFKSB7CiAgICAgIF9Nb2RlbCA9IF9Nb2RlbCB8fCByZXF1aXJlX19kZWZhdWx0KCdAZW1iZXItZGF0YS9tb2RlbCcpLmRlZmF1bHQ7CiAgICB9CgogICAgcmV0dXJuIF9Nb2RlbDsKICB9CiAgLyoqCiAgICBUaGUgc3RvcmUgY29udGFpbnMgYWxsIG9mIHRoZSBkYXRhIGZvciByZWNvcmRzIGxvYWRlZCBmcm9tIHRoZSBzZXJ2ZXIuCiAgICBJdCBpcyBhbHNvIHJlc3BvbnNpYmxlIGZvciBjcmVhdGluZyBpbnN0YW5jZXMgb2YgYE1vZGVsYCB0aGF0IHdyYXAKICAgIHRoZSBpbmRpdmlkdWFsIGRhdGEgZm9yIGEgcmVjb3JkLCBzbyB0aGF0IHRoZXkgY2FuIGJlIGJvdW5kIHRvIGluIHlvdXIKICAgIEhhbmRsZWJhcnMgdGVtcGxhdGVzLgoKICAgIERlZmluZSB5b3VyIGFwcGxpY2F0aW9uJ3Mgc3RvcmUgbGlrZSB0aGlzOgoKICAgIGBgYGFwcC9zZXJ2aWNlcy9zdG9yZS5qcwogICAgaW1wb3J0IFN0b3JlIGZyb20gJ0BlbWJlci1kYXRhL3N0b3JlJzsKCiAgICBleHBvcnQgZGVmYXVsdCBTdG9yZS5leHRlbmQoewogICAgfSk7CiAgICBgYGAKCiAgICBNb3N0IEVtYmVyLmpzIGFwcGxpY2F0aW9ucyB3aWxsIG9ubHkgaGF2ZSBhIHNpbmdsZSBgU3RvcmVgIHRoYXQgaXMKICAgIGF1dG9tYXRpY2FsbHkgY3JlYXRlZCBieSB0aGVpciBgRW1iZXIuQXBwbGljYXRpb25gLgoKICAgIFlvdSBjYW4gcmV0cmlldmUgbW9kZWxzIGZyb20gdGhlIHN0b3JlIGluIHNldmVyYWwgd2F5cy4gVG8gcmV0cmlldmUgYSByZWNvcmQKICAgIGZvciBhIHNwZWNpZmljIGlkLCB1c2UgYFN0b3JlYCdzIGBmaW5kUmVjb3JkKClgIG1ldGhvZDoKCiAgICBgYGBqYXZhc2NyaXB0CiAgICBzdG9yZS5maW5kUmVjb3JkKCdwZXJzb24nLCAxMjMpLnRoZW4oZnVuY3Rpb24gKHBlcnNvbikgewogICAgfSk7CiAgICBgYGAKCiAgICBCeSBkZWZhdWx0LCB0aGUgc3RvcmUgd2lsbCB0YWxrIHRvIHlvdXIgYmFja2VuZCB1c2luZyBhIHN0YW5kYXJkCiAgICBSRVNUIG1lY2hhbmlzbS4gWW91IGNhbiBjdXN0b21pemUgaG93IHRoZSBzdG9yZSB0YWxrcyB0byB5b3VyCiAgICBiYWNrZW5kIGJ5IHNwZWNpZnlpbmcgYSBjdXN0b20gYWRhcHRlcjoKCiAgICBgYGBhcHAvYWRhcHRlcnMvYXBwbGljYXRpb24uanMKICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwoKICAgIGV4cG9ydCBkZWZhdWx0IEFkYXB0ZXIuZXh0ZW5kKHsKICAgIH0pOwogICAgYGBgCgogICAgWW91IGNhbiBsZWFybiBtb3JlIGFib3V0IHdyaXRpbmcgYSBjdXN0b20gYWRhcHRlciBieSByZWFkaW5nIHRoZSBgQWRhcHRlcmAKICAgIGRvY3VtZW50YXRpb24uCgogICAgIyMjIFN0b3JlIGNyZWF0ZVJlY29yZCgpIHZzLiBwdXNoKCkgdnMuIHB1c2hQYXlsb2FkKCkKCiAgICBUaGUgc3RvcmUgcHJvdmlkZXMgbXVsdGlwbGUgd2F5cyB0byBjcmVhdGUgbmV3IHJlY29yZCBvYmplY3RzLiBUaGV5IGhhdmUKICAgIHNvbWUgc3VidGxlIGRpZmZlcmVuY2VzIGluIHRoZWlyIHVzZSB3aGljaCBhcmUgZGV0YWlsZWQgYmVsb3c6CgogICAgW2NyZWF0ZVJlY29yZF0oU3RvcmUvbWV0aG9kcy9jcmVhdGVSZWNvcmQ/YW5jaG9yPWNyZWF0ZVJlY29yZCkgaXMgdXNlZCBmb3IgY3JlYXRpbmcgbmV3CiAgICByZWNvcmRzIG9uIHRoZSBjbGllbnQgc2lkZS4gVGhpcyB3aWxsIHJldHVybiBhIG5ldyByZWNvcmQgaW4gdGhlCiAgICBgY3JlYXRlZC51bmNvbW1pdHRlZGAgc3RhdGUuIEluIG9yZGVyIHRvIHBlcnNpc3QgdGhpcyByZWNvcmQgdG8gdGhlCiAgICBiYWNrZW5kLCB5b3Ugd2lsbCBuZWVkIHRvIGNhbGwgYHJlY29yZC5zYXZlKClgLgoKICAgIFtwdXNoXShTdG9yZS9tZXRob2RzL3B1c2g/YW5jaG9yPXB1c2gpIGlzIHVzZWQgdG8gbm90aWZ5IEVtYmVyIERhdGEncyBzdG9yZSBvZiBuZXcgb3IKICAgIHVwZGF0ZWQgcmVjb3JkcyB0aGF0IGV4aXN0IGluIHRoZSBiYWNrZW5kLiBUaGlzIHdpbGwgcmV0dXJuIGEgcmVjb3JkCiAgICBpbiB0aGUgYGxvYWRlZC5zYXZlZGAgc3RhdGUuIFRoZSBwcmltYXJ5IHVzZS1jYXNlIGZvciBgc3RvcmUjcHVzaGAgaXMKICAgIHRvIG5vdGlmeSBFbWJlciBEYXRhIGFib3V0IHJlY29yZCB1cGRhdGVzIChmdWxsIG9yIHBhcnRpYWwpIHRoYXQgaGFwcGVuCiAgICBvdXRzaWRlIG9mIHRoZSBub3JtYWwgYWRhcHRlciBtZXRob2RzIChmb3IgZXhhbXBsZQogICAgW1NTRV0oaHR0cDovL2Rldi53My5vcmcvaHRtbDUvZXZlbnRzb3VyY2UvKSBvciBbV2ViCiAgICBTb2NrZXRzXShodHRwOi8vd3d3LnczLm9yZy9UUi8yMDA5L1dELXdlYnNvY2tldHMtMjAwOTEyMjIvKSkuCgogICAgW3B1c2hQYXlsb2FkXShTdG9yZS9tZXRob2RzL3B1c2hQYXlsb2FkP2FuY2hvcj1wdXNoUGF5bG9hZCkgaXMgYSBjb252ZW5pZW5jZSB3cmFwcGVyIGZvcgogICAgYHN0b3JlI3B1c2hgIHRoYXQgd2lsbCBkZXNlcmlhbGl6ZSBwYXlsb2FkcyBpZiB0aGUKICAgIFNlcmlhbGl6ZXIgaW1wbGVtZW50cyBhIGBwdXNoUGF5bG9hZGAgbWV0aG9kLgoKICAgIE5vdGU6IFdoZW4gY3JlYXRpbmcgYSBuZXcgcmVjb3JkIHVzaW5nIGFueSBvZiB0aGUgYWJvdmUgbWV0aG9kcwogICAgRW1iZXIgRGF0YSB3aWxsIHVwZGF0ZSBgUmVjb3JkQXJyYXlgcyBzdWNoIGFzIHRob3NlIHJldHVybmVkIGJ5CiAgICBgc3RvcmUjcGVla0FsbCgpYCBvciBgc3RvcmUjZmluZEFsbCgpYC4gVGhpcyBtZWFucyBhbnkKICAgIGRhdGEgYmluZGluZ3Mgb3IgY29tcHV0ZWQgcHJvcGVydGllcyB0aGF0IGRlcGVuZCBvbiB0aGUgUmVjb3JkQXJyYXkKICAgIHdpbGwgYXV0b21hdGljYWxseSBiZSBzeW5jZWQgdG8gaW5jbHVkZSB0aGUgbmV3IG9yIHVwZGF0ZWQgcmVjb3JkCiAgICB2YWx1ZXMuCgogICAgQGNsYXNzIFN0b3JlCiAgICBAZXh0ZW5kcyBFbWJlci5TZXJ2aWNlCiAgKi8KCgogIHZhciBDb3JlU3RvcmUgPQogIC8qI19fUFVSRV9fKi8KICBmdW5jdGlvbiAoX0VtYmVyU2VydmljZSkgewogICAgX2luaGVyaXRzTG9vc2UkMyhDb3JlU3RvcmUsIF9FbWJlclNlcnZpY2UpOwoKICAgIC8qKgogICAgICogRW1iZXJEYXRhIHNwZWNpZmljIGJhY2tidXJuZXIgaW5zdGFuY2UKICAgICAqLwoKICAgIC8qCiAgICAgIEVtYmVyIERhdGEgdXNlcyBzZXZlcmFsIHNwZWNpYWxpemVkIG1pY3JvLXF1ZXVlcyBmb3Igb3JnYW5pemluZwogICAgICBhbmQgY29hbGVzY2luZyBzaW1pbGFyIGFzeW5jIHdvcmsuCiAgICAgICBUaGVzZSBxdWV1ZXMgYXJlIGN1cnJlbnRseSBjb250cm9sbGVkIGJ5IGEgZmx1c2ggc2NoZWR1bGVkIGludG8KICAgICAgZW1iZXItZGF0YSdzIGN1c3RvbSBiYWNrYnVybmVyIGluc3RhbmNlLgogICAgICAqLwogICAgLy8gdXNlZCBmb3IgY29hbGVzY2luZyByZWNvcmQgc2F2ZSByZXF1ZXN0cwogICAgLy8gdXNlZCBmb3IgY29hbGVzY2luZyByZWxhdGlvbnNoaXAgdXBkYXRlcwogICAgLy8gdXNlZCBmb3IgY29hbGVzY2luZyBpbnRlcm5hbCBtb2RlbCB1cGRhdGVzCiAgICAvLyB1c2VkIHRvIGtlZXAgdHJhY2sgb2YgYWxsIHRoZSBmaW5kIHJlcXVlc3RzIHRoYXQgbmVlZCB0byBiZSBjb2FsZXNjZWQKICAgIC8vIERFQlVHLW9ubHkgcHJvcGVydGllcwoKICAgIC8qKgogICAgICBUaGUgZGVmYXVsdCBhZGFwdGVyIHRvIHVzZSB0byBjb21tdW5pY2F0ZSB0byBhIGJhY2tlbmQgc2VydmVyIG9yCiAgICAgIG90aGVyIHBlcnNpc3RlbmNlIGxheWVyLiBUaGlzIHdpbGwgYmUgb3ZlcnJpZGRlbiBieSBhbiBhcHBsaWNhdGlvbgogICAgICBhZGFwdGVyIGlmIHByZXNlbnQuCiAgICAgICBJZiB5b3Ugd2FudCB0byBzcGVjaWZ5IGBhcHAvYWRhcHRlcnMvY3VzdG9tLmpzYCBhcyBhIHN0cmluZywgZG86CiAgICAgICBgYGBqcwogICAgICBpbXBvcnQgU3RvcmUgZnJvbSAnQGVtYmVyLWRhdGEvc3RvcmUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgU3RvcmUuZXh0ZW5kKHsKICAgICAgICBpbml0KCkgewogICAgICAgICAgdGhpcy5fc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICAgIHRoaXMuYWRhcHRlciA9ICdjdXN0b20nOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQHByb3BlcnR5IGFkYXB0ZXIKICAgICAgQGRlZmF1bHQgJy1qc29uLWFwaScKICAgICAgQHR5cGUge1N0cmluZ30KICAgICovCgogICAgLyoqCiAgICBUaGlzIHByb3BlcnR5IHJldHVybnMgdGhlIGFkYXB0ZXIsIGFmdGVyIHJlc29sdmluZyBhIHBvc3NpYmxlCiAgICBzdHJpbmcga2V5LgogICAgIElmIHRoZSBzdXBwbGllZCBgYWRhcHRlcmAgd2FzIGEgY2xhc3MsIG9yIGEgU3RyaW5nIHByb3BlcnR5CiAgICBwYXRoIHJlc29sdmVkIHRvIGEgY2xhc3MsIHRoaXMgcHJvcGVydHkgd2lsbCBpbnN0YW50aWF0ZSB0aGUKICAgIGNsYXNzLgogICAgIFRoaXMgcHJvcGVydHkgaXMgY2FjaGVhYmxlLCBzbyB0aGUgc2FtZSBpbnN0YW5jZSBvZiBhIHNwZWNpZmllZAogICAgYWRhcHRlciBjbGFzcyBzaG91bGQgYmUgdXNlZCBmb3IgdGhlIGxpZmV0aW1lIG9mIHRoZSBzdG9yZS4KICAgICBAcHJvcGVydHkgZGVmYXVsdEFkYXB0ZXIKICAgIEBwcml2YXRlCiAgICBAcmV0dXJuIEFkYXB0ZXIKICAgICovCgogICAgLyoqCiAgICAgIEBtZXRob2QgaW5pdAogICAgICBAcHJpdmF0ZQogICAgKi8KICAgIGZ1bmN0aW9uIENvcmVTdG9yZSgpIHsKICAgICAgdmFyIF90aGlzOwoKICAgICAgX3RoaXMgPSBfRW1iZXJTZXJ2aWNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpczsKICAgICAgX3RoaXMuX2JhY2tidXJuZXIgPSBiYWNrYnVybmVyOwogICAgICBfdGhpcy5yZWNvcmRBcnJheU1hbmFnZXIgPSBuZXcgUmVjb3JkQXJyYXlNYW5hZ2VyKHsKICAgICAgICBzdG9yZTogX2Fzc2VydFRoaXNJbml0aWFsaXplZChfdGhpcykKICAgICAgfSk7CiAgICAgIF90aGlzLl9ub3RpZmljYXRpb25NYW5hZ2VyID0gdm9pZCAwOwogICAgICBfdGhpcy5fYWRhcHRlckNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgX3RoaXMuX3NlcmlhbGl6ZXJDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIF90aGlzLl9zdG9yZVdyYXBwZXIgPSBuZXcgUmVjb3JkRGF0YVN0b3JlV3JhcHBlcihfYXNzZXJ0VGhpc0luaXRpYWxpemVkKF90aGlzKSk7CiAgICAgIF90aGlzLl9wZW5kaW5nU2F2ZSA9IFtdOwogICAgICBfdGhpcy5fdXBkYXRlZFJlbGF0aW9uc2hpcHMgPSBbXTsKICAgICAgX3RoaXMuX3VwZGF0ZWRJbnRlcm5hbE1vZGVscyA9IFtdOwogICAgICBfdGhpcy5fcGVuZGluZ0ZldGNoID0gbmV3IE1hcCgpOwogICAgICBfdGhpcy5fZmV0Y2hNYW5hZ2VyID0gdm9pZCAwOwogICAgICBfdGhpcy5fc2NoZW1hRGVmaW5pdGlvblNlcnZpY2UgPSB2b2lkIDA7CiAgICAgIF90aGlzLl90cmFja2VkQXN5bmNSZXF1ZXN0cyA9IHZvaWQgMDsKICAgICAgX3RoaXMuc2hvdWxkQXNzZXJ0TWV0aG9kQ2FsbHNPbkRlc3Ryb3llZFN0b3JlID0gZmFsc2U7CiAgICAgIF90aGlzLnNob3VsZFRyYWNrQXN5bmNSZXF1ZXN0cyA9IGZhbHNlOwogICAgICBfdGhpcy5nZW5lcmF0ZVN0YWNrVHJhY2VzRm9yVHJhY2tlZFJlcXVlc3RzID0gZmFsc2U7CiAgICAgIF90aGlzLl90cmFja0FzeW5jUmVxdWVzdFN0YXJ0ID0gdm9pZCAwOwogICAgICBfdGhpcy5fdHJhY2tBc3luY1JlcXVlc3RFbmQgPSB2b2lkIDA7CiAgICAgIF90aGlzLl9fYXN5bmNXYWl0ZXIgPSB2b2lkIDA7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgX3RoaXMuX2ZldGNoTWFuYWdlciA9IG5ldyBGZXRjaE1hbmFnZXIoX2Fzc2VydFRoaXNJbml0aWFsaXplZChfdGhpcykpOwogICAgICB9CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgX3RoaXMuX25vdGlmaWNhdGlvbk1hbmFnZXIgPSBuZXcgTm90aWZpY2F0aW9uTWFuYWdlcihfYXNzZXJ0VGhpc0luaXRpYWxpemVkKF90aGlzKSk7CiAgICAgICAgX3RoaXMuX19yZWNvcmREYXRhRm9yID0gX3RoaXMuX19yZWNvcmREYXRhRm9yLmJpbmQoX2Fzc2VydFRoaXNJbml0aWFsaXplZChfdGhpcykpOwogICAgICB9CgogICAgICByZXR1cm4gX3RoaXM7CiAgICB9CgogICAgdmFyIF9wcm90byA9IENvcmVTdG9yZS5wcm90b3R5cGU7CgogICAgX3Byb3RvLmdldFJlcXVlc3RTdGF0ZVNlcnZpY2UgPSBmdW5jdGlvbiBnZXRSZXF1ZXN0U3RhdGVTZXJ2aWNlKCkgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2ZldGNoTWFuYWdlci5yZXF1ZXN0Q2FjaGU7CiAgICAgIH0KCiAgICAgIHRocm93IG5ldyBFcnJvcignUmVxdWVzdFNlcnZpY2UgaXMgbm90IGF2YWlsYWJsZSB1bmxlc3MgdGhlIGZlYXR1cmUgZmxhZyBpcyBvbiBhbmQgcnVubmluZyBvbiBhIGNhbmFyeSBidWlsZCcpOwogICAgfTsKCiAgICBfcHJvdG8uX2luc3RhbnRpYXRlUmVjb3JkID0gZnVuY3Rpb24gX2luc3RhbnRpYXRlUmVjb3JkKGludGVybmFsTW9kZWwsIG1vZGVsTmFtZSwgcmVjb3JkRGF0YSwgaWRlbnRpZmllciwgcHJvcGVydGllcykgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgLy8gYXNzZXJ0IGhlcmUKICAgICAgICBpZiAocHJvcGVydGllcyAhPT0gdW5kZWZpbmVkKSB7CgogICAgICAgICAgaWYgKCdpZCcgaW4gcHJvcGVydGllcykgewogICAgICAgICAgICBpbnRlcm5hbE1vZGVsLnNldElkKHByb3BlcnRpZXMuaWQpOwogICAgICAgICAgfSAvLyBjb252ZXJ0IHJlbGF0aW9uc2hpcCBSZWNvcmRzIHRvIFJlY29yZERhdGFzIGJlZm9yZSBwYXNzaW5nIHRvIFJlY29yZERhdGEKCgogICAgICAgICAgdmFyIGRlZnMgPSB0aGlzLl9yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcihtb2RlbE5hbWUpOwoKICAgICAgICAgIGlmIChkZWZzICE9PSBudWxsKSB7CiAgICAgICAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyk7CiAgICAgICAgICAgIHZhciByZWxhdGlvbnNoaXBWYWx1ZTsKCiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgIHZhciBwcm9wID0ga2V5c1tpXTsKICAgICAgICAgICAgICB2YXIgZGVmID0gZGVmc1twcm9wXTsKCiAgICAgICAgICAgICAgaWYgKGRlZiAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICBpZiAoZGVmLmtpbmQgPT09ICdoYXNNYW55JykgewoKICAgICAgICAgICAgICAgICAgcmVsYXRpb25zaGlwVmFsdWUgPSBleHRyYWN0UmVjb3JkRGF0YXNGcm9tUmVjb3Jkcyhwcm9wZXJ0aWVzW3Byb3BdKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIHJlbGF0aW9uc2hpcFZhbHVlID0gZXh0cmFjdFJlY29yZERhdGFGcm9tUmVjb3JkKHByb3BlcnRpZXNbcHJvcF0pOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIHByb3BlcnRpZXNbcHJvcF0gPSByZWxhdGlvbnNoaXBWYWx1ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IC8vIFRPRE8gZ3VhcmQgYWdhaW5zdCBpbml0UmVjb3JkT3B0aW9ucyBubyBiZWluZyB0aGVyZQoKCiAgICAgICAgdmFyIGNyZWF0ZU9wdGlvbnMgPSByZWNvcmREYXRhLl9pbml0UmVjb3JkQ3JlYXRlT3B0aW9ucyhwcm9wZXJ0aWVzKTsgLy9UT0RPIElnb3IgcGFzcyBhIHdyYXBwZXIgaW5zdGVhZCBvZiBSRAoKCiAgICAgICAgdmFyIF9yZWNvcmQgPSB0aGlzLmluc3RhbnRpYXRlUmVjb3JkKGlkZW50aWZpZXIsIGNyZWF0ZU9wdGlvbnMsIHRoaXMuX19yZWNvcmREYXRhRm9yLCB0aGlzLl9ub3RpZmljYXRpb25NYW5hZ2VyKTsKCiAgICAgICAgc2V0UmVjb3JkSWRlbnRpZmllcihfcmVjb3JkLCBpZGVudGlmaWVyKTsgLy9yZWNvcmRUb0ludGVybmFsTW9kZWxNYXAuc2V0KHJlY29yZCwgaW50ZXJuYWxNb2RlbCk7CgogICAgICAgIHJldHVybiBfcmVjb3JkOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcignc2hvdWxkIG5vdCBiZSBoZXJlLCBjdXN0b20gbW9kZWwgY2xhc3MgZmYgZXJyb3InKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2ludGVybmFsRGVsZXRlUmVjb3JkID0gZnVuY3Rpb24gX2ludGVybmFsRGVsZXRlUmVjb3JkKGludGVybmFsTW9kZWwpIHsKICAgICAgaW50ZXJuYWxNb2RlbC5kZWxldGVSZWNvcmQoKTsKICAgIH0gLy8gRmVhdHVyZUZsYWdnZWQgaW4gdGhlIERTTW9kZWxTdG9yZSBjbGFhcwogICAgOwoKICAgIF9wcm90by5fYXR0cmlidXRlc0RlZmluaXRpb25Gb3IgPSBmdW5jdGlvbiBfYXR0cmlidXRlc0RlZmluaXRpb25Gb3IobW9kZWxOYW1lLCBpZGVudGlmaWVyKSB7CiAgICAgIGlmIChpZGVudGlmaWVyKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UoKS5hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvcihpZGVudGlmaWVyKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gdGhpcy5nZXRTY2hlbWFEZWZpbml0aW9uU2VydmljZSgpLmF0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKG1vZGVsTmFtZSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvciA9IGZ1bmN0aW9uIF9yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcihtb2RlbE5hbWUsIGlkZW50aWZpZXIpIHsKICAgICAgaWYgKGlkZW50aWZpZXIpIHsKICAgICAgICByZXR1cm4gdGhpcy5nZXRTY2hlbWFEZWZpbml0aW9uU2VydmljZSgpLnJlbGF0aW9uc2hpcHNEZWZpbml0aW9uRm9yKGlkZW50aWZpZXIpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0aGlzLmdldFNjaGVtYURlZmluaXRpb25TZXJ2aWNlKCkucmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IobW9kZWxOYW1lKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8ucmVnaXN0ZXJTY2hlbWFEZWZpbml0aW9uU2VydmljZSA9IGZ1bmN0aW9uIHJlZ2lzdGVyU2NoZW1hRGVmaW5pdGlvblNlcnZpY2Uoc2NoZW1hKSB7CiAgICAgIHRoaXMuX3NjaGVtYURlZmluaXRpb25TZXJ2aWNlID0gc2NoZW1hOwogICAgfTsKCiAgICBfcHJvdG8uZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UgPSBmdW5jdGlvbiBnZXRTY2hlbWFEZWZpbml0aW9uU2VydmljZSgpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgIHJldHVybiB0aGlzLl9zY2hlbWFEZWZpbml0aW9uU2VydmljZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25lZWQgdG8gZW5hYmxlIENVU1RPTV9NT0RFTF9DTEFTUyBmZWF0dXJlIGZsYWcgaW4gb3JkZXIgdG8gYWNjZXNzIFNjaGVtYURlZmluaXRpb25TZXJ2aWNlJyk7CiAgICAgIH0KICAgIH0gLy8gVE9ETyBEb3VibGUgY2hlY2sgdGhpcyByZXR1cm4gdmFsdWUgaXMgY29ycmVjdAogICAgOwoKICAgIF9wcm90by5fcmVsYXRpb25zaGlwTWV0YUZvciA9IGZ1bmN0aW9uIF9yZWxhdGlvbnNoaXBNZXRhRm9yKG1vZGVsTmFtZSwgaWQsIGtleSkgewogICAgICByZXR1cm4gdGhpcy5fcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IobW9kZWxOYW1lKVtrZXldOwogICAgfTsKCiAgICBfcHJvdG8ubW9kZWxGb3IgPSBmdW5jdGlvbiBtb2RlbEZvcihtb2RlbE5hbWUpIHsKCiAgICAgIHJldHVybiBuZXcgU2hpbU1vZGVsQ2xhc3ModGhpcywgbW9kZWxOYW1lKTsKICAgIH0gLy8gRmVhdHVyZSBGbGFnZ2VkIGluIERTTW9kZWxTdG9yZQoKICAgIC8qCiAgICBSZXR1cm5zIHdoZXRoZXIgYSBNb2RlbENsYXNzIGV4aXN0cyBmb3IgYSBnaXZlbiBtb2RlbE5hbWUKICAgIFRoaXMgZXhpc3RzIGZvciBsZWdhY3kgc3VwcG9ydCBmb3IgdGhlIFJFU1RTZXJpYWxpemVyLAogICAgd2hpY2ggZHVlIHRvIGhvdyBpdCBtdXN0IGd1ZXNzIHdoZXRoZXIgYSBrZXkgaXMgYSBtb2RlbAogICAgbXVzdCBxdWVyeSBmb3Igd2hldGhlciBhIG1hdGNoIGV4aXN0cy4KICAgICBXZSBzaG91bGQgaW52ZXN0aWdhdGUgYW4gUkZDIHRvIG1ha2UgdGhpcyBwdWJsaWMgb3IgcmVtb3ZpbmcKICAgIHRoaXMgcmVxdWlyZW1lbnQuCiAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9oYXNNb2RlbEZvciA9IGZ1bmN0aW9uIF9oYXNNb2RlbEZvcihtb2RlbE5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXMuZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UoKS5kb2VzVHlwZUV4aXN0KG1vZGVsTmFtZSk7CiAgICB9IC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLgogICAgLy8gLiBDUkVBVEUgTkVXIFJFQ09SRCAuCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4KCiAgICAvKioKICAgICAgQ3JlYXRlIGEgbmV3IHJlY29yZCBpbiB0aGUgY3VycmVudCBzdG9yZS4gVGhlIHByb3BlcnRpZXMgcGFzc2VkCiAgICAgIHRvIHRoaXMgbWV0aG9kIGFyZSBzZXQgb24gdGhlIG5ld2x5IGNyZWF0ZWQgcmVjb3JkLgogICAgICAgVG8gY3JlYXRlIGEgbmV3IGluc3RhbmNlIG9mIGEgYFBvc3RgOgogICAgICAgYGBganMKICAgICAgc3RvcmUuY3JlYXRlUmVjb3JkKCdwb3N0JywgewogICAgICAgIHRpdGxlOiAnRW1iZXIgaXMgYXdlc29tZSEnCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRvIGNyZWF0ZSBhIG5ldyBpbnN0YW5jZSBvZiBhIGBQb3N0YCB0aGF0IGhhcyBhIHJlbGF0aW9uc2hpcCB3aXRoIGEgYFVzZXJgIHJlY29yZDoKICAgICAgIGBgYGpzCiAgICAgIGxldCB1c2VyID0gdGhpcy5zdG9yZS5wZWVrUmVjb3JkKCd1c2VyJywgMSk7CiAgICAgIHN0b3JlLmNyZWF0ZVJlY29yZCgncG9zdCcsIHsKICAgICAgICB0aXRsZTogJ0VtYmVyIGlzIGF3ZXNvbWUhJywKICAgICAgICB1c2VyOiB1c2VyCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBtZXRob2QgY3JlYXRlUmVjb3JkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHBhcmFtIHtPYmplY3R9IGlucHV0UHJvcGVydGllcyBhIGhhc2ggb2YgcHJvcGVydGllcyB0byBzZXQgb24gdGhlCiAgICAgICAgbmV3bHkgY3JlYXRlZCByZWNvcmQuCiAgICAgIEByZXR1cm4ge01vZGVsfSByZWNvcmQKICAgICovCiAgICA7CgogICAgX3Byb3RvLmNyZWF0ZVJlY29yZCA9IGZ1bmN0aW9uIGNyZWF0ZVJlY29yZChtb2RlbE5hbWUsIGlucHV0UHJvcGVydGllcykgewogICAgICB2YXIgX3RoaXMyID0gdGhpczsKICAgICAgLy8gICBjYWxscyB0byBgY3JlYXRlUmVjb3JkYC4gVGhlIHJ1biBsb29wIHVzYWdlIGhlcmUgaXMgYmVjYXVzZSB3ZSBiYXRjaCB0aGUgam9pbmluZyBhbmQgdXBkYXRpbmcKICAgICAgLy8gICBvZiByZWNvcmQtYXJyYXlzIHZpYSBlbWJlcidzIHJ1biBsb29wLCBub3Qgb3VyIG93bi4KICAgICAgLy8KICAgICAgLy8gICB0byByZW1vdmUgdGhpcywgd2Ugd291bGQgbmVlZCB0byBtb3ZlIHRvIGEgbmV3IGBhc3luY2AgQVBJLgoKICAgICAgcmV0dXJuIGVtYmVyUnVuJDIuam9pbihmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIF90aGlzMi5fYmFja2J1cm5lci5qb2luKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHZhciBub3JtYWxpemVkTW9kZWxOYW1lID0gbm9ybWFsaXplTW9kZWxOYW1lKG1vZGVsTmFtZSk7CiAgICAgICAgICB2YXIgcHJvcGVydGllcyA9IEVtYmVyLmFzc2lnbih7fSwgaW5wdXRQcm9wZXJ0aWVzKTsgLy8gSWYgdGhlIHBhc3NlZCBwcm9wZXJ0aWVzIGRvIG5vdCBpbmNsdWRlIGEgcHJpbWFyeSBrZXksCiAgICAgICAgICAvLyBnaXZlIHRoZSBhZGFwdGVyIGFuIG9wcG9ydHVuaXR5IHRvIGdlbmVyYXRlIG9uZS4gVHlwaWNhbGx5LAogICAgICAgICAgLy8gY2xpZW50LXNpZGUgSUQgZ2VuZXJhdG9ycyB3aWxsIHVzZSBzb21ldGhpbmcgbGlrZSB1dWlkLmpzCiAgICAgICAgICAvLyB0byBhdm9pZCBjb25mbGljdHMuCgogICAgICAgICAgaWYgKEVtYmVyLmlzTm9uZShwcm9wZXJ0aWVzLmlkKSkgewogICAgICAgICAgICBwcm9wZXJ0aWVzLmlkID0gX3RoaXMyLl9nZW5lcmF0ZUlkKG5vcm1hbGl6ZWRNb2RlbE5hbWUsIHByb3BlcnRpZXMpOwogICAgICAgICAgfSAvLyBDb2VyY2UgSUQgdG8gYSBzdHJpbmcKCgogICAgICAgICAgcHJvcGVydGllcy5pZCA9IGNvZXJjZUlkKHByb3BlcnRpZXMuaWQpOwogICAgICAgICAgdmFyIGZhY3RvcnkgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcihfdGhpczIpOwogICAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBmYWN0b3J5LmJ1aWxkKHsKICAgICAgICAgICAgdHlwZTogbm9ybWFsaXplZE1vZGVsTmFtZSwKICAgICAgICAgICAgaWQ6IHByb3BlcnRpZXMuaWQKICAgICAgICAgIH0pOwogICAgICAgICAgaW50ZXJuYWxNb2RlbC5sb2FkZWREYXRhKCk7IC8vIFRPRE8gdGhpcyBleGlzdHMganVzdCB0byBwcm94eSBgaXNOZXdgIHRvIFJlY29yZERhdGEgd2hpY2ggaXMgd2VpcmQKCiAgICAgICAgICBpbnRlcm5hbE1vZGVsLmRpZENyZWF0ZVJlY29yZCgpOwogICAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwuZ2V0UmVjb3JkKHByb3BlcnRpZXMpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0KICAgIC8qKgogICAgICBJZiBwb3NzaWJsZSwgdGhpcyBtZXRob2QgYXNrcyB0aGUgYWRhcHRlciB0byBnZW5lcmF0ZSBhbiBJRCBmb3IKICAgICAgYSBuZXdseSBjcmVhdGVkIHJlY29yZC4KICAgICAgIEBtZXRob2QgX2dlbmVyYXRlSWQKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0ge09iamVjdH0gcHJvcGVydGllcyBmcm9tIHRoZSBuZXcgcmVjb3JkCiAgICAgIEByZXR1cm4ge1N0cmluZ30gaWYgdGhlIGFkYXB0ZXIgY2FuIGdlbmVyYXRlIG9uZSwgYW4gSUQKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9nZW5lcmF0ZUlkID0gZnVuY3Rpb24gX2dlbmVyYXRlSWQobW9kZWxOYW1lLCBwcm9wZXJ0aWVzKSB7CiAgICAgIHZhciBhZGFwdGVyID0gdGhpcy5hZGFwdGVyRm9yKG1vZGVsTmFtZSk7CgogICAgICBpZiAoYWRhcHRlciAmJiBhZGFwdGVyLmdlbmVyYXRlSWRGb3JSZWNvcmQpIHsKICAgICAgICByZXR1cm4gYWRhcHRlci5nZW5lcmF0ZUlkRm9yUmVjb3JkKHRoaXMsIG1vZGVsTmFtZSwgcHJvcGVydGllcyk7CiAgICAgIH0KCiAgICAgIHJldHVybiBudWxsOwogICAgfSAvLyAuLi4uLi4uLi4uLi4uLi4uLgogICAgLy8gLiBERUxFVEUgUkVDT1JEIC4KICAgIC8vIC4uLi4uLi4uLi4uLi4uLi4uCgogICAgLyoqCiAgICAgIEZvciBzeW1tZXRyeSwgYSByZWNvcmQgY2FuIGJlIGRlbGV0ZWQgdmlhIHRoZSBzdG9yZS4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IHBvc3QgPSBzdG9yZS5jcmVhdGVSZWNvcmQoJ3Bvc3QnLCB7CiAgICAgICAgdGl0bGU6ICdFbWJlciBpcyBhd2Vzb21lIScKICAgICAgfSk7CiAgICAgICBzdG9yZS5kZWxldGVSZWNvcmQocG9zdCk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBkZWxldGVSZWNvcmQKICAgICAgQHBhcmFtIHtNb2RlbH0gcmVjb3JkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5kZWxldGVSZWNvcmQgPSBmdW5jdGlvbiBkZWxldGVSZWNvcmQocmVjb3JkKSB7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgaWYgKEhBU19NT0RFTF9QQUNLQUdFICYmIHJlY29yZCBpbnN0YW5jZW9mIGdldE1vZGVsKCkpIHsKICAgICAgICAgIHJldHVybiByZWNvcmQuZGVsZXRlUmVjb3JkKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZhciBfaWRlbnRpZmllciA9IHJlY29yZElkZW50aWZpZXJGb3IocmVjb3JkKTsKCiAgICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLnBlZWsoX2lkZW50aWZpZXIpOwogICAgICAgICAgaW50ZXJuYWxNb2RlbC5kZWxldGVSZWNvcmQoKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmVjb3JkLmRlbGV0ZVJlY29yZCgpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgRm9yIHN5bW1ldHJ5LCBhIHJlY29yZCBjYW4gYmUgdW5sb2FkZWQgdmlhIHRoZSBzdG9yZS4KICAgICAgVGhpcyB3aWxsIGNhdXNlIHRoZSByZWNvcmQgdG8gYmUgZGVzdHJveWVkIGFuZCBmcmVlZCB1cCBmb3IgZ2FyYmFnZSBjb2xsZWN0aW9uLgogICAgICAgRXhhbXBsZQogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBzdG9yZS5maW5kUmVjb3JkKCdwb3N0JywgMSkudGhlbihmdW5jdGlvbihwb3N0KSB7CiAgICAgICAgc3RvcmUudW5sb2FkUmVjb3JkKHBvc3QpOwogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHVubG9hZFJlY29yZAogICAgICBAcGFyYW0ge01vZGVsfSByZWNvcmQKICAgICovCiAgICA7CgogICAgX3Byb3RvLnVubG9hZFJlY29yZCA9IGZ1bmN0aW9uIHVubG9hZFJlY29yZChyZWNvcmQpIHsKCiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICBpZiAoSEFTX01PREVMX1BBQ0tBR0UgJiYgcmVjb3JkIGluc3RhbmNlb2YgZ2V0TW9kZWwoKSkgewogICAgICAgICAgcmV0dXJuIHJlY29yZC51bmxvYWRSZWNvcmQoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFyIF9pZGVudGlmaWVyMiA9IHJlY29yZElkZW50aWZpZXJGb3IocmVjb3JkKTsKCiAgICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLnBlZWsoX2lkZW50aWZpZXIyKTsKICAgICAgICAgIGludGVybmFsTW9kZWwudW5sb2FkUmVjb3JkKCk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHJlY29yZC51bmxvYWRSZWNvcmQoKTsKICAgICAgfQogICAgfSAvLyAuLi4uLi4uLi4uLi4uLi4uCiAgICAvLyAuIEZJTkQgUkVDT1JEUyAuCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4uCgogICAgLyoqCiAgICAgIEBtZXRob2QgZmluZAogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7U3RyaW5nfEludGVnZXJ9IGlkCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zCiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLmZpbmQgPSBmdW5jdGlvbiBmaW5kKG1vZGVsTmFtZSwgaWQsIG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIHRoaXMuZmluZFJlY29yZChtb2RlbE5hbWUsIGlkKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCByZXR1cm5zIGEgcmVjb3JkIGZvciBhIGdpdmVuIHR5cGUgYW5kIGlkIGNvbWJpbmF0aW9uLgogICAgICAgVGhlIGBmaW5kUmVjb3JkYCBtZXRob2Qgd2lsbCBhbHdheXMgcmVzb2x2ZSBpdHMgcHJvbWlzZSB3aXRoIHRoZSBzYW1lCiAgICAgIG9iamVjdCBmb3IgYSBnaXZlbiB0eXBlIGFuZCBgaWRgLgogICAgICAgVGhlIGBmaW5kUmVjb3JkYCBtZXRob2Qgd2lsbCBhbHdheXMgcmV0dXJuIGEgKipwcm9taXNlKiogdGhhdCB3aWxsIGJlCiAgICAgIHJlc29sdmVkIHdpdGggdGhlIHJlY29yZC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBtb2RlbChwYXJhbXMpIHsKICAgICAgICAgIHJldHVybiB0aGlzLnN0b3JlLmZpbmRSZWNvcmQoJ3Bvc3QnLCBwYXJhbXMucG9zdF9pZCk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBJZiB0aGUgcmVjb3JkIGlzIG5vdCB5ZXQgYXZhaWxhYmxlLCB0aGUgc3RvcmUgd2lsbCBhc2sgdGhlIGFkYXB0ZXIncyBgZmluZGAKICAgICAgbWV0aG9kIHRvIGZpbmQgdGhlIG5lY2Vzc2FyeSBkYXRhLiBJZiB0aGUgcmVjb3JkIGlzIGFscmVhZHkgcHJlc2VudCBpbiB0aGUKICAgICAgc3RvcmUsIGl0IGRlcGVuZHMgb24gdGhlIHJlbG9hZCBiZWhhdmlvciBfd2hlbl8gdGhlIHJldHVybmVkIHByb21pc2UKICAgICAgcmVzb2x2ZXMuCiAgICAgICAjIyMgUHJlbG9hZGluZwogICAgICAgWW91IGNhbiBvcHRpb25hbGx5IGBwcmVsb2FkYCBzcGVjaWZpYyBhdHRyaWJ1dGVzIGFuZCByZWxhdGlvbnNoaXBzIHRoYXQgeW91IGtub3cgb2YKICAgICAgYnkgcGFzc2luZyB0aGVtIHZpYSB0aGUgcGFzc2VkIGBvcHRpb25zYC4KICAgICAgIEZvciBleGFtcGxlLCBpZiB5b3VyIEVtYmVyIHJvdXRlIGxvb2tzIGxpa2UgYC9wb3N0cy8xL2NvbW1lbnRzLzJgIGFuZCB5b3VyIEFQSSByb3V0ZQogICAgICBmb3IgdGhlIGNvbW1lbnQgYWxzbyBsb29rcyBsaWtlIGAvcG9zdHMvMS9jb21tZW50cy8yYCBpZiB5b3Ugd2FudCB0byBmZXRjaCB0aGUgY29tbWVudAogICAgICB3aXRob3V0IGZldGNoaW5nIHRoZSBwb3N0IHlvdSBjYW4gcGFzcyBpbiB0aGUgcG9zdCB0byB0aGUgYGZpbmRSZWNvcmRgIGNhbGw6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0b3JlLmZpbmRSZWNvcmQoJ2NvbW1lbnQnLCAyLCB7IHByZWxvYWQ6IHsgcG9zdDogMSB9IH0pOwogICAgICBgYGAKICAgICAgIElmIHlvdSBoYXZlIGFjY2VzcyB0byB0aGUgcG9zdCBtb2RlbCB5b3UgY2FuIGFsc28gcGFzcyB0aGUgbW9kZWwgaXRzZWxmOgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBzdG9yZS5maW5kUmVjb3JkKCdwb3N0JywgMSkudGhlbihmdW5jdGlvbiAobXlQb3N0TW9kZWwpIHsKICAgICAgICBzdG9yZS5maW5kUmVjb3JkKCdjb21tZW50JywgMiwgeyBwb3N0OiBteVBvc3RNb2RlbCB9KTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgIyMjIFJlbG9hZGluZwogICAgICAgVGhlIHJlbG9hZCBiZWhhdmlvciBpcyBjb25maWd1cmVkIGVpdGhlciB2aWEgdGhlIHBhc3NlZCBgb3B0aW9uc2AgaGFzaCBvcgogICAgICB0aGUgcmVzdWx0IG9mIHRoZSBhZGFwdGVyJ3MgYHNob3VsZFJlbG9hZFJlY29yZGAuCiAgICAgICBJZiBgeyByZWxvYWQ6IHRydWUgfWAgaXMgcGFzc2VkIG9yIGBhZGFwdGVyLnNob3VsZFJlbG9hZFJlY29yZGAgZXZhbHVhdGVzCiAgICAgIHRvIGB0cnVlYCwgdGhlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSByZXNvbHZlcyBvbmNlIHRoZSBhZGFwdGVyIHJldHVybnMKICAgICAgZGF0YSwgcmVnYXJkbGVzcyBpZiB0aGUgcmVxdWVzdGVkIHJlY29yZCBpcyBhbHJlYWR5IGluIHRoZSBzdG9yZToKICAgICAgIGBgYGpzCiAgICAgIHN0b3JlLnB1c2goewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIGlkOiAxLAogICAgICAgICAgdHlwZTogJ3Bvc3QnLAogICAgICAgICAgcmV2aXNpb246IDEKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgLy8gYWRhcHRlciNmaW5kUmVjb3JkIHJlc29sdmVzIHdpdGgKICAgICAgLy8gWwogICAgICAvLyAgIHsKICAgICAgLy8gICAgIGlkOiAxLAogICAgICAvLyAgICAgdHlwZTogJ3Bvc3QnLAogICAgICAvLyAgICAgcmV2aXNpb246IDIKICAgICAgLy8gICB9CiAgICAgIC8vIF0KICAgICAgc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIDEsIHsgcmVsb2FkOiB0cnVlIH0pLnRoZW4oZnVuY3Rpb24ocG9zdCkgewogICAgICAgIHBvc3QuZ2V0KCdyZXZpc2lvbicpOyAvLyAyCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIElmIG5vIHJlbG9hZCBpcyBpbmRpY2F0ZWQgdmlhIHRoZSBhYm92ZSBtZW50aW9uZWQgd2F5cywgdGhlbiB0aGUgcHJvbWlzZQogICAgICBpbW1lZGlhdGVseSByZXNvbHZlcyB3aXRoIHRoZSBjYWNoZWQgdmVyc2lvbiBpbiB0aGUgc3RvcmUuCiAgICAgICAjIyMgQmFja2dyb3VuZCBSZWxvYWRpbmcKICAgICAgIE9wdGlvbmFsbHksIGlmIGBhZGFwdGVyLnNob3VsZEJhY2tncm91bmRSZWxvYWRSZWNvcmRgIGV2YWx1YXRlcyB0byBgdHJ1ZWAsCiAgICAgIHRoZW4gYSBiYWNrZ3JvdW5kIHJlbG9hZCBpcyBzdGFydGVkLCB3aGljaCB1cGRhdGVzIHRoZSByZWNvcmRzJyBkYXRhLCBvbmNlCiAgICAgIGl0IGlzIGF2YWlsYWJsZToKICAgICAgIGBgYGpzCiAgICAgIC8vIGFwcC9hZGFwdGVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBBcHBsaWNhdGlvbkFkYXB0ZXIgZnJvbSAiLi9hcHBsaWNhdGlvbiI7CiAgICAgICBleHBvcnQgZGVmYXVsdCBBcHBsaWNhdGlvbkFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBzaG91bGRSZWxvYWRSZWNvcmQoc3RvcmUsIHNuYXBzaG90KSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfSwKICAgICAgICAgc2hvdWxkQmFja2dyb3VuZFJlbG9hZFJlY29yZChzdG9yZSwgc25hcHNob3QpIHsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICAvLyAuLi4KICAgICAgIHN0b3JlLnB1c2goewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIGlkOiAxLAogICAgICAgICAgdHlwZTogJ3Bvc3QnLAogICAgICAgICAgcmV2aXNpb246IDEKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgbGV0IGJsb2dQb3N0ID0gc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIDEpLnRoZW4oZnVuY3Rpb24ocG9zdCkgewogICAgICAgIHBvc3QuZ2V0KCdyZXZpc2lvbicpOyAvLyAxCiAgICAgIH0pOwogICAgICAgLy8gbGF0ZXIsIG9uY2UgYWRhcHRlciNmaW5kUmVjb3JkIHJlc29sdmVkIHdpdGgKICAgICAgLy8gWwogICAgICAvLyAgIHsKICAgICAgLy8gICAgIGlkOiAxLAogICAgICAvLyAgICAgdHlwZTogJ3Bvc3QnLAogICAgICAvLyAgICAgcmV2aXNpb246IDIKICAgICAgLy8gICB9CiAgICAgIC8vIF0KICAgICAgIGJsb2dQb3N0LmdldCgncmV2aXNpb24nKTsgLy8gMgogICAgICBgYGAKICAgICAgIElmIHlvdSB3b3VsZCBsaWtlIHRvIGZvcmNlIG9yIHByZXZlbnQgYmFja2dyb3VuZCByZWxvYWRpbmcsIHlvdSBjYW4gc2V0IGEKICAgICAgYm9vbGVhbiB2YWx1ZSBmb3IgYGJhY2tncm91bmRSZWxvYWRgIGluIHRoZSBvcHRpb25zIG9iamVjdCBmb3IKICAgICAgYGZpbmRSZWNvcmRgLgogICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0L2VkaXQuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgbW9kZWwocGFyYW1zKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5zdG9yZS5maW5kUmVjb3JkKCdwb3N0JywgcGFyYW1zLnBvc3RfaWQsIHsgYmFja2dyb3VuZFJlbG9hZDogZmFsc2UgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBJZiB5b3UgcGFzcyBhbiBvYmplY3Qgb24gdGhlIGBhZGFwdGVyT3B0aW9uc2AgcHJvcGVydHkgb2YgdGhlIG9wdGlvbnMKICAgICAgYXJndW1lbnQgaXQgd2lsbCBiZSBwYXNzZWQgdG8geW91IGFkYXB0ZXIgdmlhIHRoZSBzbmFwc2hvdAogICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0L2VkaXQuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgbW9kZWwocGFyYW1zKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5zdG9yZS5maW5kUmVjb3JkKCdwb3N0JywgcGFyYW1zLnBvc3RfaWQsIHsKICAgICAgICAgICAgYWRhcHRlck9wdGlvbnM6IHsgc3Vic2NyaWJlOiBmYWxzZSB9CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIGBgYGFwcC9hZGFwdGVycy9wb3N0LmpzCiAgICAgIGltcG9ydCBNeUN1c3RvbUFkYXB0ZXIgZnJvbSAnLi9jdXN0b20tYWRhcHRlcic7CiAgICAgICBleHBvcnQgZGVmYXVsdCBNeUN1c3RvbUFkYXB0ZXIuZXh0ZW5kKHsKICAgICAgICBmaW5kUmVjb3JkKHN0b3JlLCB0eXBlLCBpZCwgc25hcHNob3QpIHsKICAgICAgICAgIGlmIChzbmFwc2hvdC5hZGFwdGVyT3B0aW9ucy5zdWJzY3JpYmUpIHsKICAgICAgICAgICAgLy8gLi4uCiAgICAgICAgICB9CiAgICAgICAgICAvLyAuLi4KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFNlZSBbcGVla1JlY29yZF0oU3RvcmUvbWV0aG9kcy9wZWVrUmVjb3JkP2FuY2hvcj1wZWVrUmVjb3JkKSB0byBnZXQgdGhlIGNhY2hlZCB2ZXJzaW9uIG9mIGEgcmVjb3JkLgogICAgICAgIyMjIFJldHJpZXZpbmcgUmVsYXRlZCBNb2RlbCBSZWNvcmRzCiAgICAgICBJZiB5b3UgdXNlIGFuIGFkYXB0ZXIgc3VjaCBhcyBFbWJlcidzIGRlZmF1bHQKICAgICAgW2BKU09OQVBJQWRhcHRlcmBdKC9lbWJlci1kYXRhL3JlbGVhc2UvY2xhc3Nlcy9KU09OQVBJQWRhcHRlcikKICAgICAgdGhhdCBzdXBwb3J0cyB0aGUgW0pTT04gQVBJIHNwZWNpZmljYXRpb25dKGh0dHA6Ly9qc29uYXBpLm9yZy8pIGFuZCBpZiB5b3VyIHNlcnZlcgogICAgICBlbmRwb2ludCBzdXBwb3J0cyB0aGUgdXNlIG9mIGFuCiAgICAgIFsnaW5jbHVkZScgcXVlcnkgcGFyYW1ldGVyXShodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0LyNmZXRjaGluZy1pbmNsdWRlcyksCiAgICAgIHlvdSBjYW4gdXNlIGBmaW5kUmVjb3JkKClgIHRvIGF1dG9tYXRpY2FsbHkgcmV0cmlldmUgYWRkaXRpb25hbCByZWNvcmRzIHJlbGF0ZWQgdG8KICAgICAgdGhlIG9uZSB5b3UgcmVxdWVzdCBieSBzdXBwbHlpbmcgYW4gYGluY2x1ZGVgIHBhcmFtZXRlciBpbiB0aGUgYG9wdGlvbnNgIG9iamVjdC4KICAgICAgIEZvciBleGFtcGxlLCBnaXZlbiBhIGBwb3N0YCBtb2RlbCB0aGF0IGhhcyBhIGBoYXNNYW55YCByZWxhdGlvbnNoaXAgd2l0aCBhIGBjb21tZW50YAogICAgICBtb2RlbCwgd2hlbiB3ZSByZXRyaWV2ZSBhIHNwZWNpZmljIHBvc3Qgd2UgY2FuIGhhdmUgdGhlIHNlcnZlciBhbHNvIHJldHVybiB0aGF0IHBvc3QncwogICAgICBjb21tZW50cyBpbiB0aGUgc2FtZSByZXF1ZXN0OgogICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0LmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIG1vZGVsKHBhcmFtcykgewogICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZmluZFJlY29yZCgncG9zdCcsIHBhcmFtcy5wb3N0X2lkLCB7IGluY2x1ZGU6ICdjb21tZW50cycgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGBgYAogICAgICBJbiB0aGlzIGNhc2UsIHRoZSBwb3N0J3MgY29tbWVudHMgd291bGQgdGhlbiBiZSBhdmFpbGFibGUgaW4geW91ciB0ZW1wbGF0ZSBhcwogICAgICBgbW9kZWwuY29tbWVudHNgLgogICAgICAgTXVsdGlwbGUgcmVsYXRpb25zaGlwcyBjYW4gYmUgcmVxdWVzdGVkIHVzaW5nIGFuIGBpbmNsdWRlYCBwYXJhbWV0ZXIgY29uc2lzdGluZyBvZiBhCiAgICAgIGNvbW1hLXNlcGFyYXRlZCBsaXN0ICh3aXRob3V0IHdoaXRlLXNwYWNlKSB3aGlsZSBuZXN0ZWQgcmVsYXRpb25zaGlwcyBjYW4gYmUgc3BlY2lmaWVkCiAgICAgIHVzaW5nIGEgZG90LXNlcGFyYXRlZCBzZXF1ZW5jZSBvZiByZWxhdGlvbnNoaXAgbmFtZXMuIFNvIHRvIHJlcXVlc3QgYm90aCB0aGUgcG9zdCdzCiAgICAgIGNvbW1lbnRzIGFuZCB0aGUgYXV0aG9ycyBvZiB0aG9zZSBjb21tZW50cyB0aGUgcmVxdWVzdCB3b3VsZCBsb29rIGxpa2UgdGhpczoKICAgICAgIGBgYGFwcC9yb3V0ZXMvcG9zdC5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBtb2RlbChwYXJhbXMpIHsKICAgICAgICAgIHJldHVybiB0aGlzLnN0b3JlLmZpbmRSZWNvcmQoJ3Bvc3QnLCBwYXJhbXMucG9zdF9pZCwgeyBpbmNsdWRlOiAnY29tbWVudHMsY29tbWVudHMuYXV0aG9yJyB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgYGBgCiAgICAgICBAc2luY2UgMS4xMy4wCiAgICAgIEBtZXRob2QgZmluZFJlY29yZAogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7KFN0cmluZ3xJbnRlZ2VyKX0gaWQKICAgICAgQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXQogICAgICBAcGFyYW0ge09iamVjdH0gcHJlbG9hZCAtIG9wdGlvbmFsIHNldCBvZiBhdHRyaWJ1dGVzIGFuZCByZWxhdGlvbnNoaXBzIHBhc3NlZCBpbiBlaXRoZXIgYXMgSURzIG9yIGFzIGFjdHVhbCBtb2RlbHMKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZmluZFJlY29yZCA9IGZ1bmN0aW9uIGZpbmRSZWNvcmQobW9kZWxOYW1lLCBpZCwgb3B0aW9ucykgewogICAgICB2YXIgdHlwZSA9IG5vcm1hbGl6ZU1vZGVsTmFtZShtb2RlbE5hbWUpOwogICAgICB2YXIgbm9ybWFsaXplZElkID0gZW5zdXJlU3RyaW5nSWQoaWQpOwogICAgICB2YXIgcmVzb3VyY2UgPSBjb25zdHJ1Y3RSZXNvdXJjZSh0eXBlLCBub3JtYWxpemVkSWQpOwogICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLmxvb2t1cChyZXNvdXJjZSk7CiAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9OwoKICAgICAgaWYgKCF0aGlzLmhhc1JlY29yZEZvcklkKHR5cGUsIG5vcm1hbGl6ZWRJZCkpIHsKICAgICAgICByZXR1cm4gdGhpcy5fZmluZEJ5SW50ZXJuYWxNb2RlbChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKTsKICAgICAgfQoKICAgICAgdmFyIGZldGNoZWRJbnRlcm5hbE1vZGVsID0gdGhpcy5fZmluZFJlY29yZChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKTsKCiAgICAgIHJldHVybiBwcm9taXNlUmVjb3JkKGZldGNoZWRJbnRlcm5hbE1vZGVsLCAiRFM6IFN0b3JlI2ZpbmRSZWNvcmQgIiArIHR5cGUgKyAiIHdpdGggaWQ6ICIgKyBpZCk7CiAgICB9OwoKICAgIF9wcm90by5fZmluZFJlY29yZCA9IGZ1bmN0aW9uIF9maW5kUmVjb3JkKGludGVybmFsTW9kZWwsIG9wdGlvbnMpIHsKICAgICAgLy8gUmVmZXRjaCBpZiB0aGUgcmVsb2FkIG9wdGlvbiBpcyBwYXNzZWQKICAgICAgaWYgKG9wdGlvbnMucmVsb2FkKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3NjaGVkdWxlRmV0Y2goaW50ZXJuYWxNb2RlbCwgb3B0aW9ucyk7CiAgICAgIH0KCiAgICAgIHZhciBzbmFwc2hvdCA9IGludGVybmFsTW9kZWwuY3JlYXRlU25hcHNob3Qob3B0aW9ucyk7CiAgICAgIHZhciBhZGFwdGVyID0gdGhpcy5hZGFwdGVyRm9yKGludGVybmFsTW9kZWwubW9kZWxOYW1lKTsgLy8gUmVmZXRjaCB0aGUgcmVjb3JkIGlmIHRoZSBhZGFwdGVyIHRoaW5rcyB0aGUgcmVjb3JkIGlzIHN0YWxlCgogICAgICBpZiAoYWRhcHRlci5zaG91bGRSZWxvYWRSZWNvcmQodGhpcywgc25hcHNob3QpKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3NjaGVkdWxlRmV0Y2goaW50ZXJuYWxNb2RlbCwgb3B0aW9ucyk7CiAgICAgIH0KCiAgICAgIGlmIChvcHRpb25zLmJhY2tncm91bmRSZWxvYWQgPT09IGZhbHNlKSB7CiAgICAgICAgcmV0dXJuIEVtYmVyLlJTVlAuUHJvbWlzZS5yZXNvbHZlKGludGVybmFsTW9kZWwpOwogICAgICB9IC8vIFRyaWdnZXIgdGhlIGJhY2tncm91bmQgcmVmZXRjaCBpZiBiYWNrZ3JvdW5kUmVsb2FkIG9wdGlvbiBpcyBwYXNzZWQKCgogICAgICBpZiAob3B0aW9ucy5iYWNrZ3JvdW5kUmVsb2FkIHx8IGFkYXB0ZXIuc2hvdWxkQmFja2dyb3VuZFJlbG9hZFJlY29yZCh0aGlzLCBzbmFwc2hvdCkpIHsKICAgICAgICB0aGlzLl9zY2hlZHVsZUZldGNoKGludGVybmFsTW9kZWwsIG9wdGlvbnMpOwogICAgICB9IC8vIFJldHVybiB0aGUgY2FjaGVkIHJlY29yZAoKCiAgICAgIHJldHVybiBFbWJlci5SU1ZQLlByb21pc2UucmVzb2x2ZShpbnRlcm5hbE1vZGVsKTsKICAgIH07CgogICAgX3Byb3RvLl9maW5kQnlJbnRlcm5hbE1vZGVsID0gZnVuY3Rpb24gX2ZpbmRCeUludGVybmFsTW9kZWwoaW50ZXJuYWxNb2RlbCwgb3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICBpZiAob3B0aW9ucy5wcmVsb2FkKSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC5wcmVsb2FkRGF0YShvcHRpb25zLnByZWxvYWQpOwogICAgICB9CgogICAgICB2YXIgZmV0Y2hlZEludGVybmFsTW9kZWwgPSB0aGlzLl9maW5kRW1wdHlJbnRlcm5hbE1vZGVsKGludGVybmFsTW9kZWwsIG9wdGlvbnMpOwoKICAgICAgcmV0dXJuIHByb21pc2VSZWNvcmQoZmV0Y2hlZEludGVybmFsTW9kZWwsICJEUzogU3RvcmUjZmluZFJlY29yZCAiICsgaW50ZXJuYWxNb2RlbC5tb2RlbE5hbWUgKyAiIHdpdGggaWQ6ICIgKyBpbnRlcm5hbE1vZGVsLmlkKTsKICAgIH07CgogICAgX3Byb3RvLl9maW5kRW1wdHlJbnRlcm5hbE1vZGVsID0gZnVuY3Rpb24gX2ZpbmRFbXB0eUludGVybmFsTW9kZWwoaW50ZXJuYWxNb2RlbCwgb3B0aW9ucykgewogICAgICBpZiAoaW50ZXJuYWxNb2RlbC5pc0VtcHR5KCkpIHsKICAgICAgICByZXR1cm4gdGhpcy5fc2NoZWR1bGVGZXRjaChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKTsKICAgICAgfSAvL1RPRE8gZG91YmxlIGNoZWNrIGFib3V0IHJlbG9hZGluZwoKCiAgICAgIGlmICghY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgaWYgKGludGVybmFsTW9kZWwuaXNMb2FkaW5nKCkpIHsKICAgICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLl9wcm9taXNlUHJveHk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGlmIChpbnRlcm5hbE1vZGVsLmlzTG9hZGluZygpKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fc2NoZWR1bGVGZXRjaChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIHJldHVybiBFbWJlci5SU1ZQLlByb21pc2UucmVzb2x2ZShpbnRlcm5hbE1vZGVsKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBtYWtlcyBhIHNlcmllcyBvZiByZXF1ZXN0cyB0byB0aGUgYWRhcHRlcidzIGBmaW5kYCBtZXRob2QKICAgICAgYW5kIHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgb25jZSB0aGV5IGFyZSBhbGwgbG9hZGVkLgogICAgICAgQHByaXZhdGUKICAgICAgQG1ldGhvZCBmaW5kQnlJZHMKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0ge0FycmF5fSBpZHMKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZmluZEJ5SWRzID0gZnVuY3Rpb24gZmluZEJ5SWRzKG1vZGVsTmFtZSwgaWRzKSB7CiAgICAgIHZhciBwcm9taXNlcyA9IG5ldyBBcnJheShpZHMubGVuZ3RoKTsKICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKCiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaWRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgcHJvbWlzZXNbaV0gPSB0aGlzLmZpbmRSZWNvcmQobm9ybWFsaXplZE1vZGVsTmFtZSwgaWRzW2ldKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHByb21pc2VBcnJheShFbWJlci5SU1ZQLmFsbChwcm9taXNlcykudGhlbihFbWJlci5BLCBudWxsLCAiRFM6IFN0b3JlI2ZpbmRCeUlkcyBvZiAiICsgbm9ybWFsaXplZE1vZGVsTmFtZSArICIgY29tcGxldGUiKSk7CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIGJ5IGBmaW5kUmVjb3JkYCBpZiBpdCBkaXNjb3ZlcnMgdGhhdCBhIHBhcnRpY3VsYXIKICAgICAgdHlwZS9pZCBwYWlyIGhhc24ndCBiZWVuIGxvYWRlZCB5ZXQgdG8ga2ljayBvZmYgYSByZXF1ZXN0IHRvIHRoZQogICAgICBhZGFwdGVyLgogICAgICAgQG1ldGhvZCBfZmV0Y2hSZWNvcmQKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtJbnRlcm5hbE1vZGVsfSBpbnRlcm5hbE1vZGVsIG1vZGVsCiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICAqLwogICAgOwoKICAgIF9wcm90by5fZmV0Y2hSZWNvcmQgPSBmdW5jdGlvbiBfZmV0Y2hSZWNvcmQoaW50ZXJuYWxNb2RlbCwgb3B0aW9ucykgewogICAgICB2YXIgbW9kZWxOYW1lID0gaW50ZXJuYWxNb2RlbC5tb2RlbE5hbWU7CiAgICAgIHZhciBhZGFwdGVyID0gdGhpcy5hZGFwdGVyRm9yKG1vZGVsTmFtZSk7CiAgICAgIHJldHVybiBfZmluZChhZGFwdGVyLCB0aGlzLCBpbnRlcm5hbE1vZGVsLnR5cGUsIGludGVybmFsTW9kZWwuaWQsIGludGVybmFsTW9kZWwsIG9wdGlvbnMpOwogICAgfTsKCiAgICBfcHJvdG8uX3NjaGVkdWxlRmV0Y2hNYW55ID0gZnVuY3Rpb24gX3NjaGVkdWxlRmV0Y2hNYW55KGludGVybmFsTW9kZWxzLCBvcHRpb25zKSB7CiAgICAgIHZhciBmZXRjaGVzID0gbmV3IEFycmF5KGludGVybmFsTW9kZWxzLmxlbmd0aCk7CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGludGVybmFsTW9kZWxzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgZmV0Y2hlc1tpXSA9IHRoaXMuX3NjaGVkdWxlRmV0Y2goaW50ZXJuYWxNb2RlbHNbaV0sIG9wdGlvbnMpOwogICAgICB9CgogICAgICByZXR1cm4gRW1iZXIuUlNWUC5Qcm9taXNlLmFsbChmZXRjaGVzKTsKICAgIH07CgogICAgX3Byb3RvLl9zY2hlZHVsZUZldGNoVGhyb3VnaEZldGNoTWFuYWdlciA9IGZ1bmN0aW9uIF9zY2hlZHVsZUZldGNoVGhyb3VnaEZldGNoTWFuYWdlcihpbnRlcm5hbE1vZGVsLCBvcHRpb25zKSB7CiAgICAgIHZhciBfdGhpczMgPSB0aGlzOwoKICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgewogICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgfQoKICAgICAgdmFyIGdlbmVyYXRlU3RhY2tUcmFjZSA9IHRoaXMuZ2VuZXJhdGVTdGFja1RyYWNlc0ZvclRyYWNrZWRSZXF1ZXN0czsgLy8gVE9ETyAgcmVtb3ZlIHRoaXMgb25jZSB3ZSBkb250IHJlbHkgb24gc3RhdGUgbWFjaGluZQoKICAgICAgaW50ZXJuYWxNb2RlbC5sb2FkaW5nRGF0YSgpOwogICAgICB2YXIgaWRlbnRpZmllciA9IGludGVybmFsTW9kZWwuaWRlbnRpZmllcjsKCiAgICAgIHZhciBwcm9taXNlID0gdGhpcy5fZmV0Y2hNYW5hZ2VyLnNjaGVkdWxlRmV0Y2goaW50ZXJuYWxNb2RlbC5pZGVudGlmaWVyLCBvcHRpb25zLCBnZW5lcmF0ZVN0YWNrVHJhY2UpOwoKICAgICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAocGF5bG9hZCkgewogICAgICAgIHsKICAgICAgICAgIC8vIGVuc3VyZSB0aGF0IHJlZ2FyZGxlc3Mgb2YgaWQgcmV0dXJuZWQgd2UgYXNzaWduIHRvIHRoZSBjb3JyZWN0IHJlY29yZAogICAgICAgICAgaWYgKHBheWxvYWQuZGF0YSAmJiAhQXJyYXkuaXNBcnJheShwYXlsb2FkLmRhdGEpKSB7CiAgICAgICAgICAgIHBheWxvYWQuZGF0YS5saWQgPSBpZGVudGlmaWVyLmxpZDsKICAgICAgICAgIH0KICAgICAgICB9IC8vIFJldHVybmluZyB0aGlzLl9wdXNoIGhlcmUsIGJyZWFrcyB0eXBpbmcgYnV0IG5vdCBhbnkgdGVzdHMsIGludmVzc3RpZ2F0ZSBwb3RlbnRpYWwgbWlzc2luZyB0ZXN0cwoKCiAgICAgICAgdmFyIHBvdGVudGlhbGx5TmV3SW0gPSBfdGhpczMuX3B1c2gocGF5bG9hZCk7CgogICAgICAgIGlmIChwb3RlbnRpYWxseU5ld0ltICYmICFBcnJheS5pc0FycmF5KHBvdGVudGlhbGx5TmV3SW0pKSB7CiAgICAgICAgICByZXR1cm4gcG90ZW50aWFsbHlOZXdJbTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWw7CiAgICAgICAgfQogICAgICB9LCBmdW5jdGlvbiAoZXJyb3IpIHsKICAgICAgICAvLyBUT0RPICByZW1vdmUgdGhpcyBvbmNlIHdlIGRvbnQgcmVseSBvbiBzdGF0ZSBtYWNoaW5lCiAgICAgICAgaW50ZXJuYWxNb2RlbC5ub3RGb3VuZCgpOwoKICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbC5pc0VtcHR5KCkpIHsKICAgICAgICAgIGludGVybmFsTW9kZWwudW5sb2FkUmVjb3JkKCk7CiAgICAgICAgfQoKICAgICAgICB0aHJvdyBlcnJvcjsKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5fc2NoZWR1bGVGZXRjaCA9IGZ1bmN0aW9uIF9zY2hlZHVsZUZldGNoKGludGVybmFsTW9kZWwsIG9wdGlvbnMpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgICAgIHJldHVybiB0aGlzLl9zY2hlZHVsZUZldGNoVGhyb3VnaEZldGNoTWFuYWdlcihpbnRlcm5hbE1vZGVsLCBvcHRpb25zKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbC5fcHJvbWlzZVByb3h5KSB7CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5fcHJvbWlzZVByb3h5OwogICAgICAgIH0KCiAgICAgICAgdmFyIGlkID0gaW50ZXJuYWxNb2RlbC5pZCwKICAgICAgICAgICAgbW9kZWxOYW1lID0gaW50ZXJuYWxNb2RlbC5tb2RlbE5hbWU7CiAgICAgICAgdmFyIHJlc29sdmVyID0gRW1iZXIuUlNWUC5kZWZlcigiRmV0Y2hpbmcgIiArIG1vZGVsTmFtZSArICInIHdpdGggaWQ6ICIgKyBpZCk7CiAgICAgICAgdmFyIHBlbmRpbmdGZXRjaEl0ZW0gPSB7CiAgICAgICAgICBpbnRlcm5hbE1vZGVsOiBpbnRlcm5hbE1vZGVsLAogICAgICAgICAgcmVzb2x2ZXI6IHJlc29sdmVyLAogICAgICAgICAgb3B0aW9uczogb3B0aW9ucwogICAgICAgIH07CgogICAgICAgIHZhciBwcm9taXNlID0gcmVzb2x2ZXIucHJvbWlzZTsKICAgICAgICBpbnRlcm5hbE1vZGVsLmxvYWRpbmdEYXRhKHByb21pc2UpOwoKICAgICAgICBpZiAodGhpcy5fcGVuZGluZ0ZldGNoLnNpemUgPT09IDApIHsKICAgICAgICAgIGVtYmVyUnVuJDIuc2NoZWR1bGUoJ2FjdGlvbnMnLCB0aGlzLCB0aGlzLmZsdXNoQWxsUGVuZGluZ0ZldGNoZXMpOwogICAgICAgIH0KCiAgICAgICAgdmFyIGZldGNoZXMgPSB0aGlzLl9wZW5kaW5nRmV0Y2g7CiAgICAgICAgdmFyIHBlbmRpbmcgPSBmZXRjaGVzLmdldChtb2RlbE5hbWUpOwoKICAgICAgICBpZiAocGVuZGluZyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBwZW5kaW5nID0gW107CiAgICAgICAgICBmZXRjaGVzLnNldChtb2RlbE5hbWUsIHBlbmRpbmcpOwogICAgICAgIH0KCiAgICAgICAgcGVuZGluZy5wdXNoKHBlbmRpbmdGZXRjaEl0ZW0pOwogICAgICAgIHJldHVybiBwcm9taXNlOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5mbHVzaEFsbFBlbmRpbmdGZXRjaGVzID0gZnVuY3Rpb24gZmx1c2hBbGxQZW5kaW5nRmV0Y2hlcygpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgICAgIHJldHVybjsgLy9hc3NlcnQgaGVyZQogICAgICB9IGVsc2UgewogICAgICAgIGlmICh0aGlzLmlzRGVzdHJveWVkIHx8IHRoaXMuaXNEZXN0cm95aW5nKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICB0aGlzLl9wZW5kaW5nRmV0Y2guZm9yRWFjaCh0aGlzLl9mbHVzaFBlbmRpbmdGZXRjaEZvclR5cGUsIHRoaXMpOwoKICAgICAgICB0aGlzLl9wZW5kaW5nRmV0Y2guY2xlYXIoKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uX2ZsdXNoUGVuZGluZ0ZldGNoRm9yVHlwZSA9IGZ1bmN0aW9uIF9mbHVzaFBlbmRpbmdGZXRjaEZvclR5cGUocGVuZGluZ0ZldGNoSXRlbXMsIG1vZGVsTmFtZSkgewogICAgICB2YXIgc3RvcmUgPSB0aGlzOwogICAgICB2YXIgYWRhcHRlciA9IHN0b3JlLmFkYXB0ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgdmFyIHNob3VsZENvYWxlc2NlID0gISFhZGFwdGVyLmZpbmRNYW55ICYmIGFkYXB0ZXIuY29hbGVzY2VGaW5kUmVxdWVzdHM7CiAgICAgIHZhciB0b3RhbEl0ZW1zID0gcGVuZGluZ0ZldGNoSXRlbXMubGVuZ3RoOwogICAgICB2YXIgaW50ZXJuYWxNb2RlbHMgPSBuZXcgQXJyYXkodG90YWxJdGVtcyk7CiAgICAgIHZhciBzZWVraW5nID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdmFyIG9wdGlvbnNNYXAgPSBuZXcgV2Vha01hcCgpOwoKICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IHRvdGFsSXRlbXM7IF9pKyspIHsKICAgICAgICB2YXIgcGVuZGluZ0l0ZW0gPSBwZW5kaW5nRmV0Y2hJdGVtc1tfaV07CiAgICAgICAgdmFyIF9pbnRlcm5hbE1vZGVsID0gcGVuZGluZ0l0ZW0uaW50ZXJuYWxNb2RlbDsKICAgICAgICBpbnRlcm5hbE1vZGVsc1tfaV0gPSBfaW50ZXJuYWxNb2RlbDsKICAgICAgICBvcHRpb25zTWFwLnNldChfaW50ZXJuYWxNb2RlbCwgcGVuZGluZ0l0ZW0ub3B0aW9ucyk7IC8vIFdlIGNhbiByZW1vdmUgdGhpcyAibm90IG51bGwiIGNhc3Qgb25jZSB3ZSBoYXZlIGVub3VnaCB0eXBpbmcKICAgICAgICAvLyB0byBrbm93IHdlIGFyZSBvbmx5IGRlYWxpbmcgd2l0aCBFeGlzdGluZ1Jlc291cmNlSWRlbnRpZmllck9iamVjdHMKCiAgICAgICAgc2Vla2luZ1tfaW50ZXJuYWxNb2RlbC5pZF0gPSBwZW5kaW5nSXRlbTsKICAgICAgfQoKICAgICAgZnVuY3Rpb24gX2ZldGNoUmVjb3JkKHJlY29yZFJlc29sdmVyUGFpcikgewogICAgICAgIHZhciByZWNvcmRGZXRjaCA9IHN0b3JlLl9mZXRjaFJlY29yZChyZWNvcmRSZXNvbHZlclBhaXIuaW50ZXJuYWxNb2RlbCwgcmVjb3JkUmVzb2x2ZXJQYWlyLm9wdGlvbnMpOwoKICAgICAgICByZWNvcmRSZXNvbHZlclBhaXIucmVzb2x2ZXIucmVzb2x2ZShyZWNvcmRGZXRjaCk7CiAgICAgIH0KCiAgICAgIGZ1bmN0aW9uIGhhbmRsZUZvdW5kUmVjb3Jkcyhmb3VuZEludGVybmFsTW9kZWxzLCBleHBlY3RlZEludGVybmFsTW9kZWxzKSB7CiAgICAgICAgLy8gcmVzb2x2ZSBmb3VuZCByZWNvcmRzCiAgICAgICAgdmFyIGZvdW5kID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKCiAgICAgICAgZm9yICh2YXIgX2kyID0gMCwgX2wgPSBmb3VuZEludGVybmFsTW9kZWxzLmxlbmd0aDsgX2kyIDwgX2w7IF9pMisrKSB7CiAgICAgICAgICB2YXIgX2ludGVybmFsTW9kZWwyID0gZm91bmRJbnRlcm5hbE1vZGVsc1tfaTJdOyAvLyBXZSBjYW4gcmVtb3ZlIHRoaXMgIm5vdCBudWxsIiBjYXN0IG9uY2Ugd2UgaGF2ZSBlbm91Z2ggdHlwaW5nCiAgICAgICAgICAvLyB0byBrbm93IHdlIGFyZSBvbmx5IGRlYWxpbmcgd2l0aCBFeGlzdGluZ1Jlc291cmNlSWRlbnRpZmllck9iamVjdHMKCiAgICAgICAgICB2YXIgX3BhaXIgPSBzZWVraW5nW19pbnRlcm5hbE1vZGVsMi5pZF07CiAgICAgICAgICBmb3VuZFtfaW50ZXJuYWxNb2RlbDIuaWRdID0gX2ludGVybmFsTW9kZWwyOwoKICAgICAgICAgIGlmIChfcGFpcikgewogICAgICAgICAgICB2YXIgcmVzb2x2ZXIgPSBfcGFpci5yZXNvbHZlcjsKICAgICAgICAgICAgcmVzb2x2ZXIucmVzb2x2ZShfaW50ZXJuYWxNb2RlbDIpOwogICAgICAgICAgfQogICAgICAgIH0gLy8gcmVqZWN0IG1pc3NpbmcgcmVjb3JkcwoKCiAgICAgICAgdmFyIG1pc3NpbmdJbnRlcm5hbE1vZGVscyA9IFtdOwoKICAgICAgICBmb3IgKHZhciBfaTMgPSAwLCBfbDIgPSBleHBlY3RlZEludGVybmFsTW9kZWxzLmxlbmd0aDsgX2kzIDwgX2wyOyBfaTMrKykgewogICAgICAgICAgdmFyIF9pbnRlcm5hbE1vZGVsMyA9IGV4cGVjdGVkSW50ZXJuYWxNb2RlbHNbX2kzXTsgLy8gV2UgY2FuIHJlbW92ZSB0aGlzICJub3QgbnVsbCIgY2FzdCBvbmNlIHdlIGhhdmUgZW5vdWdoIHR5cGluZwogICAgICAgICAgLy8gdG8ga25vdyB3ZSBhcmUgb25seSBkZWFsaW5nIHdpdGggRXhpc3RpbmdSZXNvdXJjZUlkZW50aWZpZXJPYmplY3RzCgogICAgICAgICAgaWYgKCFmb3VuZFtfaW50ZXJuYWxNb2RlbDMuaWRdKSB7CiAgICAgICAgICAgIG1pc3NpbmdJbnRlcm5hbE1vZGVscy5wdXNoKF9pbnRlcm5hbE1vZGVsMyk7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBpZiAobWlzc2luZ0ludGVybmFsTW9kZWxzLmxlbmd0aCkgewogICAgICAgICAgcmVqZWN0SW50ZXJuYWxNb2RlbHMobWlzc2luZ0ludGVybmFsTW9kZWxzKTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGZ1bmN0aW9uIHJlamVjdEludGVybmFsTW9kZWxzKGludGVybmFsTW9kZWxzLCBlcnJvcikgewogICAgICAgIGZvciAodmFyIF9pNCA9IDAsIF9sMyA9IGludGVybmFsTW9kZWxzLmxlbmd0aDsgX2k0IDwgX2wzOyBfaTQrKykgewogICAgICAgICAgdmFyIF9pbnRlcm5hbE1vZGVsNCA9IGludGVybmFsTW9kZWxzW19pNF07IC8vIFdlIGNhbiByZW1vdmUgdGhpcyAibm90IG51bGwiIGNhc3Qgb25jZSB3ZSBoYXZlIGVub3VnaCB0eXBpbmcKICAgICAgICAgIC8vIHRvIGtub3cgd2UgYXJlIG9ubHkgZGVhbGluZyB3aXRoIEV4aXN0aW5nUmVzb3VyY2VJZGVudGlmaWVyT2JqZWN0cwoKICAgICAgICAgIHZhciBfcGFpcjIgPSBzZWVraW5nW19pbnRlcm5hbE1vZGVsNC5pZF07CgogICAgICAgICAgaWYgKF9wYWlyMikgewogICAgICAgICAgICBfcGFpcjIucmVzb2x2ZXIucmVqZWN0KGVycm9yIHx8IG5ldyBFcnJvcigiRXhwZWN0ZWQ6ICciICsgX2ludGVybmFsTW9kZWw0ICsgIicgdG8gYmUgcHJlc2VudCBpbiB0aGUgYWRhcHRlciBwcm92aWRlZCBwYXlsb2FkLCBidXQgaXQgd2FzIG5vdCBmb3VuZC4iKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CgogICAgICBpZiAoc2hvdWxkQ29hbGVzY2UpIHsKICAgICAgICAvLyBUT0RPOiBJbXByb3ZlIHJlY29yZHMgPT4gc25hcHNob3RzID0+IHJlY29yZHMgPT4gc25hcHNob3RzCiAgICAgICAgLy8KICAgICAgICAvLyBXZSB3YW50IHRvIHByb3ZpZGUgcmVjb3JkcyB0byBhbGwgc3RvcmUgbWV0aG9kcyBhbmQgc25hcHNob3RzIHRvIGFsbAogICAgICAgIC8vIGFkYXB0ZXIgbWV0aG9kcy4gVG8gbWFrZSBzdXJlIHdlJ3JlIGRvaW5nIHRoYXQgd2UncmUgcHJvdmlkaW5nIGFuIGFycmF5CiAgICAgICAgLy8gb2Ygc25hcHNob3RzIHRvIGFkYXB0ZXIuZ3JvdXBSZWNvcmRzRm9yRmluZE1hbnkoKSwgd2hpY2ggaW4gdHVybiB3aWxsCiAgICAgICAgLy8gcmV0dXJuIGdyb3VwZWQgc25hcHNob3RzIGluc3RlYWQgb2YgZ3JvdXBlZCByZWNvcmRzLgogICAgICAgIC8vCiAgICAgICAgLy8gQnV0IHNpbmNlIHRoZSBfZmluZE1hbnkoKSBmaW5kZXIgaXMgYSBzdG9yZSBtZXRob2Qgd2UgbmVlZCB0byBnZXQgdGhlCiAgICAgICAgLy8gcmVjb3JkcyBmcm9tIHRoZSBncm91cGVkIHNuYXBzaG90cyBldmVuIHRob3VnaCB0aGUgX2ZpbmRNYW55KCkgZmluZGVyCiAgICAgICAgLy8gd2lsbCBvbmNlIGFnYWluIGNvbnZlcnQgdGhlIHJlY29yZHMgdG8gc25hcHNob3RzIGZvciBhZGFwdGVyLmZpbmRNYW55KCkKICAgICAgICB2YXIgc25hcHNob3RzID0gbmV3IEFycmF5KHRvdGFsSXRlbXMpOwoKICAgICAgICBmb3IgKHZhciBfaTUgPSAwOyBfaTUgPCB0b3RhbEl0ZW1zOyBfaTUrKykgewogICAgICAgICAgc25hcHNob3RzW19pNV0gPSBpbnRlcm5hbE1vZGVsc1tfaTVdLmNyZWF0ZVNuYXBzaG90KG9wdGlvbnNNYXAuZ2V0KGludGVybmFsTW9kZWwpKTsKICAgICAgICB9CgogICAgICAgIHZhciBncm91cHMgPSBhZGFwdGVyLmdyb3VwUmVjb3Jkc0ZvckZpbmRNYW55KHRoaXMsIHNuYXBzaG90cyk7CgogICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gZ3JvdXBzLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICAgICAgdmFyIGdyb3VwID0gZ3JvdXBzW2ldOwogICAgICAgICAgdmFyIHRvdGFsSW5Hcm91cCA9IGdyb3Vwc1tpXS5sZW5ndGg7CiAgICAgICAgICB2YXIgaWRzID0gbmV3IEFycmF5KHRvdGFsSW5Hcm91cCk7CiAgICAgICAgICB2YXIgZ3JvdXBlZEludGVybmFsTW9kZWxzID0gbmV3IEFycmF5KHRvdGFsSW5Hcm91cCk7CgogICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCB0b3RhbEluR3JvdXA7IGorKykgewogICAgICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGdyb3VwW2pdLl9pbnRlcm5hbE1vZGVsOwogICAgICAgICAgICBncm91cGVkSW50ZXJuYWxNb2RlbHNbal0gPSBpbnRlcm5hbE1vZGVsOwogICAgICAgICAgICBpZHNbal0gPSBpbnRlcm5hbE1vZGVsLmlkOwogICAgICAgICAgfQoKICAgICAgICAgIGlmICh0b3RhbEluR3JvdXAgPiAxKSB7CiAgICAgICAgICAgIChmdW5jdGlvbiAoZ3JvdXBlZEludGVybmFsTW9kZWxzKSB7CiAgICAgICAgICAgICAgX2ZpbmRNYW55KGFkYXB0ZXIsIHN0b3JlLCBtb2RlbE5hbWUsIGlkcywgZ3JvdXBlZEludGVybmFsTW9kZWxzLCBvcHRpb25zTWFwKS50aGVuKGZ1bmN0aW9uIChmb3VuZEludGVybmFsTW9kZWxzKSB7CiAgICAgICAgICAgICAgICBoYW5kbGVGb3VuZFJlY29yZHMoZm91bmRJbnRlcm5hbE1vZGVscywgZ3JvdXBlZEludGVybmFsTW9kZWxzKTsKICAgICAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHsKICAgICAgICAgICAgICAgIHJlamVjdEludGVybmFsTW9kZWxzKGdyb3VwZWRJbnRlcm5hbE1vZGVscywgZXJyb3IpOwogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9KShncm91cGVkSW50ZXJuYWxNb2RlbHMpOwogICAgICAgICAgfSBlbHNlIGlmIChpZHMubGVuZ3RoID09PSAxKSB7CiAgICAgICAgICAgIHZhciBwYWlyID0gc2Vla2luZ1tncm91cGVkSW50ZXJuYWxNb2RlbHNbMF0uaWRdOwoKICAgICAgICAgICAgX2ZldGNoUmVjb3JkKHBhaXIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBmb3IgKHZhciBfaTYgPSAwOyBfaTYgPCB0b3RhbEl0ZW1zOyBfaTYrKykgewogICAgICAgICAgX2ZldGNoUmVjb3JkKHBlbmRpbmdGZXRjaEl0ZW1zW19pNl0pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgLyoqCiAgICAgIEdldCB0aGUgcmVmZXJlbmNlIGZvciB0aGUgc3BlY2lmaWVkIHJlY29yZC4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgbGV0IHVzZXJSZWYgPSBzdG9yZS5nZXRSZWZlcmVuY2UoJ3VzZXInLCAxKTsKICAgICAgIC8vIGNoZWNrIGlmIHRoZSB1c2VyIGlzIGxvYWRlZAogICAgICBsZXQgaXNMb2FkZWQgPSB1c2VyUmVmLnZhbHVlKCkgIT09IG51bGw7CiAgICAgICAvLyBnZXQgdGhlIHJlY29yZCBvZiB0aGUgcmVmZXJlbmNlIChudWxsIGlmIG5vdCB5ZXQgYXZhaWxhYmxlKQogICAgICBsZXQgdXNlciA9IHVzZXJSZWYudmFsdWUoKTsKICAgICAgIC8vIGdldCB0aGUgaWRlbnRpZmllciBvZiB0aGUgcmVmZXJlbmNlCiAgICAgIGlmICh1c2VyUmVmLnJlbW90ZVR5cGUoKSA9PT0gJ2lkJykgewogICAgICBsZXQgaWQgPSB1c2VyUmVmLmlkKCk7CiAgICAgIH0KICAgICAgIC8vIGxvYWQgdXNlciAodmlhIHN0b3JlLmZpbmQpCiAgICAgIHVzZXJSZWYubG9hZCgpLnRoZW4oLi4uKQogICAgICAgLy8gb3IgdHJpZ2dlciBhIHJlbG9hZAogICAgICB1c2VyUmVmLnJlbG9hZCgpLnRoZW4oLi4uKQogICAgICAgLy8gcHJvdmlkZSBkYXRhIGZvciByZWZlcmVuY2UKICAgICAgdXNlclJlZi5wdXNoKHsgaWQ6IDEsIHVzZXJuYW1lOiAnQHVzZXInIH0pLnRoZW4oZnVuY3Rpb24odXNlcikgewogICAgICAgIHVzZXJSZWYudmFsdWUoKSA9PT0gdXNlcjsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBnZXRSZWZlcmVuY2UKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0ge1N0cmluZ3xJbnRlZ2VyfSBpZAogICAgICBAc2luY2UgMi41LjAKICAgICAgQHJldHVybiB7UmVjb3JkUmVmZXJlbmNlfQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZ2V0UmVmZXJlbmNlID0gZnVuY3Rpb24gZ2V0UmVmZXJlbmNlKG1vZGVsTmFtZSwgaWQpIHsKCiAgICAgIHZhciB0eXBlID0gbm9ybWFsaXplTW9kZWxOYW1lKG1vZGVsTmFtZSk7CiAgICAgIHZhciBub3JtYWxpemVkSWQgPSBlbnN1cmVTdHJpbmdJZChpZCk7CiAgICAgIHZhciByZXNvdXJjZSA9IGNvbnN0cnVjdFJlc291cmNlKHR5cGUsIG5vcm1hbGl6ZWRJZCk7CiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5sb29rdXAocmVzb3VyY2UpLnJlY29yZFJlZmVyZW5jZTsKICAgIH0KICAgIC8qKgogICAgICBHZXQgYSByZWNvcmQgYnkgYSBnaXZlbiB0eXBlIGFuZCBJRCB3aXRob3V0IHRyaWdnZXJpbmcgYSBmZXRjaC4KICAgICAgIFRoaXMgbWV0aG9kIHdpbGwgc3luY2hyb25vdXNseSByZXR1cm4gdGhlIHJlY29yZCBpZiBpdCBpcyBhdmFpbGFibGUgaW4gdGhlIHN0b3JlLAogICAgICBvdGhlcndpc2UgaXQgd2lsbCByZXR1cm4gYG51bGxgLiBBIHJlY29yZCBpcyBhdmFpbGFibGUgaWYgaXQgaGFzIGJlZW4gZmV0Y2hlZCBlYXJsaWVyLCBvcgogICAgICBwdXNoZWQgbWFudWFsbHkgaW50byB0aGUgc3RvcmUuCiAgICAgICBTZWUgW2ZpbmRSZWNvcmRdKFN0b3JlL21ldGhvZHMvZmluZFJlY29yZD9hbmNob3I9ZmluZFJlY29yZCkgaWYgeW91IHdvdWxkIGxpa2UgdG8gcmVxdWVzdCB0aGlzIHJlY29yZCBmcm9tIHRoZSBiYWNrZW5kLgogICAgICAgX05vdGU6IFRoaXMgaXMgYSBzeW5jaHJvbm91cyBtZXRob2QgYW5kIGRvZXMgbm90IHJldHVybiBhIHByb21pc2UuXwogICAgICAgYGBganMKICAgICAgbGV0IHBvc3QgPSBzdG9yZS5wZWVrUmVjb3JkKCdwb3N0JywgMSk7CiAgICAgICBwb3N0LmdldCgnaWQnKTsgLy8gMQogICAgICBgYGAKICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBwZWVrUmVjb3JkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHBhcmFtIHtTdHJpbmd8SW50ZWdlcn0gaWQKICAgICAgQHJldHVybiB7TW9kZWx8bnVsbH0gcmVjb3JkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5wZWVrUmVjb3JkID0gZnVuY3Rpb24gcGVla1JlY29yZChtb2RlbE5hbWUsIGlkKSB7CiAgICAgIHZhciB0eXBlID0gbm9ybWFsaXplTW9kZWxOYW1lKG1vZGVsTmFtZSk7CiAgICAgIHZhciBub3JtYWxpemVkSWQgPSBlbnN1cmVTdHJpbmdJZChpZCk7CgogICAgICBpZiAodGhpcy5oYXNSZWNvcmRGb3JJZCh0eXBlLCBub3JtYWxpemVkSWQpKSB7CiAgICAgICAgdmFyIHJlc291cmNlID0gY29uc3RydWN0UmVzb3VyY2UodHlwZSwgbm9ybWFsaXplZElkKTsKICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcykubG9va3VwKHJlc291cmNlKS5nZXRSZWNvcmQoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBieSB0aGUgcmVjb3JkJ3MgYHJlbG9hZGAgbWV0aG9kLgogICAgICAgVGhpcyBtZXRob2QgY2FsbHMgdGhlIGFkYXB0ZXIncyBgZmluZGAgbWV0aG9kLCB3aGljaCByZXR1cm5zIGEgcHJvbWlzZS4gV2hlbgogICAgICAqKnRoYXQqKiBwcm9taXNlIHJlc29sdmVzLCBgX3JlbG9hZFJlY29yZGAgd2lsbCByZXNvbHZlIHRoZSBwcm9taXNlIHJldHVybmVkCiAgICAgIGJ5IHRoZSByZWNvcmQncyBgcmVsb2FkYC4KICAgICAgIEBtZXRob2QgX3JlbG9hZFJlY29yZAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge01vZGVsfSBpbnRlcm5hbE1vZGVsCiAgICAgIEBwYXJhbSBvcHRpb25zIG9wdGlvbmFsIHRvIGluY2x1ZGUgYWRhcHRlck9wdGlvbnMKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uX3JlbG9hZFJlY29yZCA9IGZ1bmN0aW9uIF9yZWxvYWRSZWNvcmQoaW50ZXJuYWxNb2RlbCwgb3B0aW9ucykgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgb3B0aW9ucy5pc1JlbG9hZGluZyA9IHRydWU7CiAgICAgIH0KCiAgICAgIHZhciBpZCA9IGludGVybmFsTW9kZWwuaWQsCiAgICAgICAgICBtb2RlbE5hbWUgPSBpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZTsKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIHRoaXMuX3NjaGVkdWxlRmV0Y2goaW50ZXJuYWxNb2RlbCwgb3B0aW9ucyk7CiAgICB9CiAgICAvKioKICAgICBUaGlzIG1ldGhvZCByZXR1cm5zIHRydWUgaWYgYSByZWNvcmQgZm9yIGEgZ2l2ZW4gbW9kZWxOYW1lIGFuZCBpZCBpcyBhbHJlYWR5CiAgICAgbG9hZGVkIGluIHRoZSBzdG9yZS4gVXNlIHRoaXMgZnVuY3Rpb24gdG8ga25vdyBiZWZvcmVoYW5kIGlmIGEgZmluZFJlY29yZCgpCiAgICAgd2lsbCByZXN1bHQgaW4gYSByZXF1ZXN0IG9yIHRoYXQgaXQgd2lsbCBiZSBhIGNhY2hlIGhpdC4KICAgICAgRXhhbXBsZQogICAgICBgYGBqYXZhc2NyaXB0CiAgICAgc3RvcmUuaGFzUmVjb3JkRm9ySWQoJ3Bvc3QnLCAxKTsgLy8gZmFsc2UKICAgICBzdG9yZS5maW5kUmVjb3JkKCdwb3N0JywgMSkudGhlbihmdW5jdGlvbigpIHsKICAgICAgIHN0b3JlLmhhc1JlY29yZEZvcklkKCdwb3N0JywgMSk7IC8vIHRydWUKICAgICB9KTsKICAgICBgYGAKICAgICAgIEBtZXRob2QgaGFzUmVjb3JkRm9ySWQKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0geyhTdHJpbmd8SW50ZWdlcil9IGlkCiAgICAgIEByZXR1cm4ge0Jvb2xlYW59CiAgICAqLwogICAgOwoKICAgIF9wcm90by5oYXNSZWNvcmRGb3JJZCA9IGZ1bmN0aW9uIGhhc1JlY29yZEZvcklkKG1vZGVsTmFtZSwgaWQpIHsKICAgICAgdmFyIHR5cGUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgdmFyIHRydWVJZCA9IGVuc3VyZVN0cmluZ0lkKGlkKTsKICAgICAgdmFyIHJlc291cmNlID0gewogICAgICAgIHR5cGU6IHR5cGUsCiAgICAgICAgaWQ6IHRydWVJZAogICAgICB9OwogICAgICB2YXIgaWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzKS5wZWVrUmVjb3JkSWRlbnRpZmllcihyZXNvdXJjZSk7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gaWRlbnRpZmllciAmJiBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5wZWVrKGlkZW50aWZpZXIpOwogICAgICByZXR1cm4gISFpbnRlcm5hbE1vZGVsICYmIGludGVybmFsTW9kZWwuaXNMb2FkZWQoKTsKICAgIH0KICAgIC8qKgogICAgICBSZXR1cm5zIGlkIHJlY29yZCBmb3IgYSBnaXZlbiB0eXBlIGFuZCBJRC4gSWYgb25lIGlzbid0IGFscmVhZHkgbG9hZGVkLAogICAgICBpdCBidWlsZHMgYSBuZXcgcmVjb3JkIGFuZCBsZWF2ZXMgaXQgaW4gdGhlIGBlbXB0eWAgc3RhdGUuCiAgICAgICBAbWV0aG9kIHJlY29yZEZvcklkCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHBhcmFtIHsoU3RyaW5nfEludGVnZXIpfSBpZAogICAgICBAcmV0dXJuIHtNb2RlbH0gcmVjb3JkCiAgICAqLwogICAgOwoKICAgIF9wcm90by5yZWNvcmRGb3JJZCA9IGZ1bmN0aW9uIHJlY29yZEZvcklkKG1vZGVsTmFtZSwgaWQpIHsKICAgICAgdmFyIHJlc291cmNlID0gY29uc3RydWN0UmVzb3VyY2UobW9kZWxOYW1lLCBlbnN1cmVTdHJpbmdJZChpZCkpOwogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcykubG9va3VwKHJlc291cmNlKS5nZXRSZWNvcmQoKTsKICAgIH0KICAgIC8qKgogICAgICBAbWV0aG9kIGZpbmRNYW55CiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7QXJyYXl9IGludGVybmFsTW9kZWxzCiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICA7CgogICAgX3Byb3RvLmZpbmRNYW55ID0gZnVuY3Rpb24gZmluZE1hbnkoaW50ZXJuYWxNb2RlbHMsIG9wdGlvbnMpIHsKCiAgICAgIHZhciBmaW5kcyA9IG5ldyBBcnJheShpbnRlcm5hbE1vZGVscy5sZW5ndGgpOwoKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbnRlcm5hbE1vZGVscy5sZW5ndGg7IGkrKykgewogICAgICAgIGZpbmRzW2ldID0gdGhpcy5fZmluZEVtcHR5SW50ZXJuYWxNb2RlbChpbnRlcm5hbE1vZGVsc1tpXSwgb3B0aW9ucyk7CiAgICAgIH0KCiAgICAgIHJldHVybiBFbWJlci5SU1ZQLlByb21pc2UuYWxsKGZpbmRzKTsKICAgIH0KICAgIC8qKgogICAgICBJZiBhIHJlbGF0aW9uc2hpcCB3YXMgb3JpZ2luYWxseSBwb3B1bGF0ZWQgYnkgdGhlIGFkYXB0ZXIgYXMgYSBsaW5rCiAgICAgIChhcyBvcHBvc2VkIHRvIGEgbGlzdCBvZiBJRHMpLCB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgd2hlbiB0aGUKICAgICAgcmVsYXRpb25zaGlwIGlzIGZldGNoZWQuCiAgICAgICBUaGUgbGluayAod2hpY2ggaXMgdXN1YWxseSBhIFVSTCkgaXMgcGFzc2VkIHRocm91Z2ggdW5jaGFuZ2VkLCBzbyB0aGUKICAgICAgYWRhcHRlciBjYW4gbWFrZSB3aGF0ZXZlciByZXF1ZXN0IGl0IHdhbnRzLgogICAgICAgVGhlIHVzdWFsIHVzZS1jYXNlIGlzIGZvciB0aGUgc2VydmVyIHRvIHJlZ2lzdGVyIGEgVVJMIGFzIGEgbGluaywgYW5kCiAgICAgIHRoZW4gdXNlIHRoYXQgVVJMIGluIHRoZSBmdXR1cmUgdG8gbWFrZSBhIHJlcXVlc3QgZm9yIHRoZSByZWxhdGlvbnNoaXAuCiAgICAgICBAbWV0aG9kIGZpbmRIYXNNYW55CiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7SW50ZXJuYWxNb2RlbH0gaW50ZXJuYWxNb2RlbAogICAgICBAcGFyYW0ge2FueX0gbGluawogICAgICBAcGFyYW0geyhSZWxhdGlvbnNoaXApfSByZWxhdGlvbnNoaXAKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZmluZEhhc01hbnkgPSBmdW5jdGlvbiBmaW5kSGFzTWFueShpbnRlcm5hbE1vZGVsLCBsaW5rLCByZWxhdGlvbnNoaXAsIG9wdGlvbnMpIHsKCiAgICAgIHZhciBhZGFwdGVyID0gdGhpcy5hZGFwdGVyRm9yKGludGVybmFsTW9kZWwubW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIF9maW5kSGFzTWFueShhZGFwdGVyLCB0aGlzLCBpbnRlcm5hbE1vZGVsLCBsaW5rLCByZWxhdGlvbnNoaXAsIG9wdGlvbnMpOwogICAgfTsKCiAgICBfcHJvdG8uX2ZpbmRIYXNNYW55QnlKc29uQXBpUmVzb3VyY2UgPSBmdW5jdGlvbiBfZmluZEhhc01hbnlCeUpzb25BcGlSZXNvdXJjZShyZXNvdXJjZSwgcGFyZW50SW50ZXJuYWxNb2RlbCwgcmVsYXRpb25zaGlwTWV0YSwgb3B0aW9ucykgewogICAgICB2YXIgX3RoaXM0ID0gdGhpczsKCiAgICAgIGlmICghcmVzb3VyY2UpIHsKICAgICAgICByZXR1cm4gRW1iZXIuUlNWUC5yZXNvbHZlKFtdKTsKICAgICAgfQoKICAgICAgdmFyIF9yZXNvdXJjZSRfcmVsYXRpb25zaCA9IHJlc291cmNlLl9yZWxhdGlvbnNoaXAsCiAgICAgICAgICByZWxhdGlvbnNoaXBJc1N0YWxlID0gX3Jlc291cmNlJF9yZWxhdGlvbnNoLnJlbGF0aW9uc2hpcElzU3RhbGUsCiAgICAgICAgICBhbGxJbnZlcnNlUmVjb3Jkc0FyZUxvYWRlZCA9IF9yZXNvdXJjZSRfcmVsYXRpb25zaC5hbGxJbnZlcnNlUmVjb3Jkc0FyZUxvYWRlZCwKICAgICAgICAgIGhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSA9IF9yZXNvdXJjZSRfcmVsYXRpb25zaC5oYXNEZW1hdGVyaWFsaXplZEludmVyc2UsCiAgICAgICAgICBoYXNBbnlSZWxhdGlvbnNoaXBEYXRhID0gX3Jlc291cmNlJF9yZWxhdGlvbnNoLmhhc0FueVJlbGF0aW9uc2hpcERhdGEsCiAgICAgICAgICByZWxhdGlvbnNoaXBJc0VtcHR5ID0gX3Jlc291cmNlJF9yZWxhdGlvbnNoLnJlbGF0aW9uc2hpcElzRW1wdHksCiAgICAgICAgICBzaG91bGRGb3JjZVJlbG9hZCA9IF9yZXNvdXJjZSRfcmVsYXRpb25zaC5zaG91bGRGb3JjZVJlbG9hZDsKICAgICAgdmFyIHNob3VsZEZpbmRWaWFMaW5rID0gcmVzb3VyY2UubGlua3MgJiYgcmVzb3VyY2UubGlua3MucmVsYXRlZCAmJiAoc2hvdWxkRm9yY2VSZWxvYWQgfHwgaGFzRGVtYXRlcmlhbGl6ZWRJbnZlcnNlIHx8IHJlbGF0aW9uc2hpcElzU3RhbGUgfHwgIWFsbEludmVyc2VSZWNvcmRzQXJlTG9hZGVkICYmICFyZWxhdGlvbnNoaXBJc0VtcHR5KTsgLy8gZmV0Y2ggdmlhIGxpbmsKCiAgICAgIGlmIChzaG91bGRGaW5kVmlhTGluaykgewogICAgICAgIHJldHVybiB0aGlzLmZpbmRIYXNNYW55KHBhcmVudEludGVybmFsTW9kZWwsIHJlc291cmNlLmxpbmtzLnJlbGF0ZWQsIHJlbGF0aW9uc2hpcE1ldGEsIG9wdGlvbnMpOwogICAgICB9CgogICAgICB2YXIgcHJlZmVyTG9jYWxDYWNoZSA9IGhhc0FueVJlbGF0aW9uc2hpcERhdGEgJiYgIXJlbGF0aW9uc2hpcElzRW1wdHk7CiAgICAgIHZhciBoYXNMb2NhbFBhcnRpYWxEYXRhID0gaGFzRGVtYXRlcmlhbGl6ZWRJbnZlcnNlIHx8IHJlbGF0aW9uc2hpcElzRW1wdHkgJiYgQXJyYXkuaXNBcnJheShyZXNvdXJjZS5kYXRhKSAmJiByZXNvdXJjZS5kYXRhLmxlbmd0aCA+IDA7IC8vIGZldGNoIHVzaW5nIGRhdGEsIHB1bGxpbmcgZnJvbSBsb2NhbCBjYWNoZSBpZiBwb3NzaWJsZQoKICAgICAgaWYgKCFzaG91bGRGb3JjZVJlbG9hZCAmJiAhcmVsYXRpb25zaGlwSXNTdGFsZSAmJiAocHJlZmVyTG9jYWxDYWNoZSB8fCBoYXNMb2NhbFBhcnRpYWxEYXRhKSkgewogICAgICAgIHZhciBpbnRlcm5hbE1vZGVscyA9IHJlc291cmNlLmRhdGEubWFwKGZ1bmN0aW9uIChqc29uKSB7CiAgICAgICAgICByZXR1cm4gX3RoaXM0Ll9pbnRlcm5hbE1vZGVsRm9yUmVzb3VyY2UoanNvbik7CiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIHRoaXMuZmluZE1hbnkoaW50ZXJuYWxNb2RlbHMsIG9wdGlvbnMpOwogICAgICB9CgogICAgICB2YXIgaGFzRGF0YSA9IGhhc0FueVJlbGF0aW9uc2hpcERhdGEgJiYgIXJlbGF0aW9uc2hpcElzRW1wdHk7IC8vIGZldGNoIGJ5IGRhdGEKCiAgICAgIGlmIChoYXNEYXRhIHx8IGhhc0xvY2FsUGFydGlhbERhdGEpIHsKICAgICAgICB2YXIgX2ludGVybmFsTW9kZWxzID0gcmVzb3VyY2UuZGF0YS5tYXAoZnVuY3Rpb24gKGpzb24pIHsKICAgICAgICAgIHJldHVybiBfdGhpczQuX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShqc29uKTsKICAgICAgICB9KTsKCiAgICAgICAgcmV0dXJuIHRoaXMuX3NjaGVkdWxlRmV0Y2hNYW55KF9pbnRlcm5hbE1vZGVscywgb3B0aW9ucyk7CiAgICAgIH0gLy8gd2Ugd2VyZSBleHBsaWNpdGx5IHRvbGQgd2UgaGF2ZSBubyBkYXRhIGFuZCBubyBsaW5rcy4KICAgICAgLy8gICBUT0RPIGlmIHRoZSByZWxhdGlvbnNoaXBJc1N0YWxlLCBzaG91bGQgd2UgaGl0IHRoZSBhZGFwdGVyIGFueXdheT8KCgogICAgICByZXR1cm4gRW1iZXIuUlNWUC5yZXNvbHZlKFtdKTsKICAgIH07CgogICAgX3Byb3RvLl9nZXRIYXNNYW55QnlKc29uQXBpUmVzb3VyY2UgPSBmdW5jdGlvbiBfZ2V0SGFzTWFueUJ5SnNvbkFwaVJlc291cmNlKHJlc291cmNlKSB7CiAgICAgIHZhciBfdGhpczUgPSB0aGlzOwoKICAgICAgdmFyIGludGVybmFsTW9kZWxzID0gW107CgogICAgICBpZiAocmVzb3VyY2UgJiYgcmVzb3VyY2UuZGF0YSkgewogICAgICAgIGludGVybmFsTW9kZWxzID0gcmVzb3VyY2UuZGF0YS5tYXAoZnVuY3Rpb24gKHJlZmVyZW5jZSkgewogICAgICAgICAgcmV0dXJuIF90aGlzNS5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlKHJlZmVyZW5jZSk7CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsczsKICAgIH0KICAgIC8qKgogICAgICBAbWV0aG9kIGZpbmRCZWxvbmdzVG8KICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtJbnRlcm5hbE1vZGVsfSBpbnRlcm5hbE1vZGVsCiAgICAgIEBwYXJhbSB7YW55fSBsaW5rCiAgICAgIEBwYXJhbSB7UmVsYXRpb25zaGlwfSByZWxhdGlvbnNoaXAKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uZmluZEJlbG9uZ3NUbyA9IGZ1bmN0aW9uIGZpbmRCZWxvbmdzVG8oaW50ZXJuYWxNb2RlbCwgbGluaywgcmVsYXRpb25zaGlwLCBvcHRpb25zKSB7CgogICAgICB2YXIgYWRhcHRlciA9IHRoaXMuYWRhcHRlckZvcihpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZSk7CiAgICAgIHJldHVybiBfZmluZEJlbG9uZ3NUbyhhZGFwdGVyLCB0aGlzLCBpbnRlcm5hbE1vZGVsLCBsaW5rLCByZWxhdGlvbnNoaXAsIG9wdGlvbnMpOwogICAgfTsKCiAgICBfcHJvdG8uX2ZldGNoQmVsb25nc1RvTGlua0Zyb21SZXNvdXJjZSA9IGZ1bmN0aW9uIF9mZXRjaEJlbG9uZ3NUb0xpbmtGcm9tUmVzb3VyY2UocmVzb3VyY2UsIHBhcmVudEludGVybmFsTW9kZWwsIHJlbGF0aW9uc2hpcE1ldGEsIG9wdGlvbnMpIHsKICAgICAgaWYgKCFyZXNvdXJjZSB8fCAhcmVzb3VyY2UubGlua3MgfHwgIXJlc291cmNlLmxpbmtzLnJlbGF0ZWQpIHsKICAgICAgICAvLyBzaG91bGQgd2Ugd2FybiBoZXJlLCBub3Qgc3VyZSBjYXVzZSBpdHMgYW4gaW50ZXJuYWwgbWV0aG9kCiAgICAgICAgcmV0dXJuIEVtYmVyLlJTVlAucmVzb2x2ZShudWxsKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXMuZmluZEJlbG9uZ3NUbyhwYXJlbnRJbnRlcm5hbE1vZGVsLCByZXNvdXJjZS5saW5rcy5yZWxhdGVkLCByZWxhdGlvbnNoaXBNZXRhLCBvcHRpb25zKS50aGVuKGZ1bmN0aW9uIChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwgPyBpbnRlcm5hbE1vZGVsLmdldFJlY29yZCgpIDogbnVsbDsKICAgICAgfSk7CiAgICB9OwoKICAgIF9wcm90by5fZmluZEJlbG9uZ3NUb0J5SnNvbkFwaVJlc291cmNlID0gZnVuY3Rpb24gX2ZpbmRCZWxvbmdzVG9CeUpzb25BcGlSZXNvdXJjZShyZXNvdXJjZSwgcGFyZW50SW50ZXJuYWxNb2RlbCwgcmVsYXRpb25zaGlwTWV0YSwgb3B0aW9ucykgewogICAgICBpZiAoIXJlc291cmNlKSB7CiAgICAgICAgcmV0dXJuIEVtYmVyLlJTVlAucmVzb2x2ZShudWxsKTsKICAgICAgfQoKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSByZXNvdXJjZS5kYXRhID8gdGhpcy5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlKHJlc291cmNlLmRhdGEpIDogbnVsbDsKICAgICAgdmFyIF9yZXNvdXJjZSRfcmVsYXRpb25zaDIgPSByZXNvdXJjZS5fcmVsYXRpb25zaGlwLAogICAgICAgICAgcmVsYXRpb25zaGlwSXNTdGFsZSA9IF9yZXNvdXJjZSRfcmVsYXRpb25zaDIucmVsYXRpb25zaGlwSXNTdGFsZSwKICAgICAgICAgIGFsbEludmVyc2VSZWNvcmRzQXJlTG9hZGVkID0gX3Jlc291cmNlJF9yZWxhdGlvbnNoMi5hbGxJbnZlcnNlUmVjb3Jkc0FyZUxvYWRlZCwKICAgICAgICAgIGhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSA9IF9yZXNvdXJjZSRfcmVsYXRpb25zaDIuaGFzRGVtYXRlcmlhbGl6ZWRJbnZlcnNlLAogICAgICAgICAgaGFzQW55UmVsYXRpb25zaGlwRGF0YSA9IF9yZXNvdXJjZSRfcmVsYXRpb25zaDIuaGFzQW55UmVsYXRpb25zaGlwRGF0YSwKICAgICAgICAgIHJlbGF0aW9uc2hpcElzRW1wdHkgPSBfcmVzb3VyY2UkX3JlbGF0aW9uc2gyLnJlbGF0aW9uc2hpcElzRW1wdHksCiAgICAgICAgICBzaG91bGRGb3JjZVJlbG9hZCA9IF9yZXNvdXJjZSRfcmVsYXRpb25zaDIuc2hvdWxkRm9yY2VSZWxvYWQ7CiAgICAgIHZhciBzaG91bGRGaW5kVmlhTGluayA9IHJlc291cmNlLmxpbmtzICYmIHJlc291cmNlLmxpbmtzLnJlbGF0ZWQgJiYgKHNob3VsZEZvcmNlUmVsb2FkIHx8IGhhc0RlbWF0ZXJpYWxpemVkSW52ZXJzZSB8fCByZWxhdGlvbnNoaXBJc1N0YWxlIHx8ICFhbGxJbnZlcnNlUmVjb3Jkc0FyZUxvYWRlZCAmJiAhcmVsYXRpb25zaGlwSXNFbXB0eSk7CgogICAgICBpZiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgIC8vIHNob3J0IGNpcmN1aXQgaWYgd2UgYXJlIGFscmVhZHkgbG9hZGluZwogICAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5SRVFVRVNUX1NFUlZJQ0UpIHsKICAgICAgICAgIC8vIFRlbXBvcmFyeSBmaXggZm9yIHJlcXVlc3RzIGFscmVhZHkgbG9hZGluZyB1bnRpbCB3ZSBtb3ZlIHRoaXMgaW5zaWRlIHRoZSBmZXRjaCBtYW5hZ2VyCiAgICAgICAgICB2YXIgcGVuZGluZ1JlcXVlc3RzID0gdGhpcy5nZXRSZXF1ZXN0U3RhdGVTZXJ2aWNlKCkuZ2V0UGVuZGluZ1JlcXVlc3RzRm9yUmVjb3JkKGludGVybmFsTW9kZWwuaWRlbnRpZmllcikuZmlsdGVyKGZ1bmN0aW9uIChyZXEpIHsKICAgICAgICAgICAgcmV0dXJuIHJlcS50eXBlID09PSAncXVlcnknOwogICAgICAgICAgfSk7CgogICAgICAgICAgaWYgKHBlbmRpbmdSZXF1ZXN0cy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIHJldHVybiBwZW5kaW5nUmVxdWVzdHNbMF1bUmVxdWVzdFByb21pc2VdLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLmdldFJlY29yZCgpOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKGludGVybmFsTW9kZWwuaXNMb2FkaW5nKCkpIHsKICAgICAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwuX3Byb21pc2VQcm94eS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5nZXRSZWNvcmQoKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IC8vIGZldGNoIHZpYSBsaW5rCgoKICAgICAgaWYgKHNob3VsZEZpbmRWaWFMaW5rKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX2ZldGNoQmVsb25nc1RvTGlua0Zyb21SZXNvdXJjZShyZXNvdXJjZSwgcGFyZW50SW50ZXJuYWxNb2RlbCwgcmVsYXRpb25zaGlwTWV0YSwgb3B0aW9ucyk7CiAgICAgIH0KCiAgICAgIHZhciBwcmVmZXJMb2NhbENhY2hlID0gaGFzQW55UmVsYXRpb25zaGlwRGF0YSAmJiBhbGxJbnZlcnNlUmVjb3Jkc0FyZUxvYWRlZCAmJiAhcmVsYXRpb25zaGlwSXNFbXB0eTsKICAgICAgdmFyIGhhc0xvY2FsUGFydGlhbERhdGEgPSBoYXNEZW1hdGVyaWFsaXplZEludmVyc2UgfHwgcmVsYXRpb25zaGlwSXNFbXB0eSAmJiByZXNvdXJjZS5kYXRhOyAvLyBudWxsIGlzIGV4cGxpY2l0IGVtcHR5LCB1bmRlZmluZWQgaXMgIndlIGRvbid0IGtub3cgYW55dGhpbmciCgogICAgICB2YXIgbG9jYWxEYXRhSXNFbXB0eSA9IHJlc291cmNlLmRhdGEgPT09IHVuZGVmaW5lZCB8fCByZXNvdXJjZS5kYXRhID09PSBudWxsOyAvLyBmZXRjaCB1c2luZyBkYXRhLCBwdWxsaW5nIGZyb20gbG9jYWwgY2FjaGUgaWYgcG9zc2libGUKCiAgICAgIGlmICghc2hvdWxkRm9yY2VSZWxvYWQgJiYgIXJlbGF0aW9uc2hpcElzU3RhbGUgJiYgKHByZWZlckxvY2FsQ2FjaGUgfHwgaGFzTG9jYWxQYXJ0aWFsRGF0YSkpIHsKICAgICAgICAvKgogICAgICAgICAgV2UgaGF2ZSBjYW5vbmljYWwgZGF0YSwgYnV0IG91ciBsb2NhbCBzdGF0ZSBpcyBlbXB0eQogICAgICAgICAqLwogICAgICAgIGlmIChsb2NhbERhdGFJc0VtcHR5KSB7CiAgICAgICAgICByZXR1cm4gRW1iZXIuUlNWUC5yZXNvbHZlKG51bGwpOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRoaXMuX2ZpbmRCeUludGVybmFsTW9kZWwoaW50ZXJuYWxNb2RlbCwgb3B0aW9ucyk7CiAgICAgIH0KCiAgICAgIHZhciByZXNvdXJjZUlzTG9jYWwgPSAhbG9jYWxEYXRhSXNFbXB0eSAmJiByZXNvdXJjZS5kYXRhLmlkID09PSBudWxsOwoKICAgICAgaWYgKGludGVybmFsTW9kZWwgJiYgcmVzb3VyY2VJc0xvY2FsKSB7CiAgICAgICAgcmV0dXJuIEVtYmVyLlJTVlAucmVzb2x2ZShpbnRlcm5hbE1vZGVsLmdldFJlY29yZCgpKTsKICAgICAgfSAvLyBmZXRjaCBieSBkYXRhCgoKICAgICAgaWYgKGludGVybmFsTW9kZWwgJiYgIWxvY2FsRGF0YUlzRW1wdHkpIHsKICAgICAgICByZXR1cm4gdGhpcy5fc2NoZWR1bGVGZXRjaChpbnRlcm5hbE1vZGVsLCBvcHRpb25zKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLmdldFJlY29yZCgpOwogICAgICAgIH0pOwogICAgICB9IC8vIHdlIHdlcmUgZXhwbGljaXRseSB0b2xkIHdlIGhhdmUgbm8gZGF0YSBhbmQgbm8gbGlua3MuCiAgICAgIC8vICAgVE9ETyBpZiB0aGUgcmVsYXRpb25zaGlwSXNTdGFsZSwgc2hvdWxkIHdlIGhpdCB0aGUgYWRhcHRlciBhbnl3YXk/CgoKICAgICAgcmV0dXJuIEVtYmVyLlJTVlAucmVzb2x2ZShudWxsKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBkZWxlZ2F0ZXMgYSBxdWVyeSB0byB0aGUgYWRhcHRlci4gVGhpcyBpcyB0aGUgb25lIHBsYWNlIHdoZXJlCiAgICAgIGFkYXB0ZXItbGV2ZWwgc2VtYW50aWNzIGFyZSBleHBvc2VkIHRvIHRoZSBhcHBsaWNhdGlvbi4KICAgICAgIEVhY2ggdGltZSB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgYSBuZXcgcmVxdWVzdCBpcyBtYWRlIHRocm91Z2ggdGhlIGFkYXB0ZXIuCiAgICAgICBFeHBvc2luZyBxdWVyaWVzIHRoaXMgd2F5IHNlZW1zIHByZWZlcmFibGUgdG8gY3JlYXRpbmcgYW4gYWJzdHJhY3QgcXVlcnkKICAgICAgbGFuZ3VhZ2UgZm9yIGFsbCBzZXJ2ZXItc2lkZSBxdWVyaWVzLCBhbmQgdGhlbiByZXF1aXJlIGFsbCBhZGFwdGVycyB0bwogICAgICBpbXBsZW1lbnQgdGhlbS4KICAgICAgIC0tLQogICAgICAgSWYgeW91IGRvIHNvbWV0aGluZyBsaWtlIHRoaXM6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0b3JlLnF1ZXJ5KCdwZXJzb24nLCB7IHBhZ2U6IDEgfSk7CiAgICAgIGBgYAogICAgICAgVGhlIHJlcXVlc3QgbWFkZSB0byB0aGUgc2VydmVyIHdpbGwgbG9vayBzb21ldGhpbmcgbGlrZSB0aGlzOgogICAgICAgYGBgCiAgICAgIEdFVCAiL2FwaS92MS9wZXJzb24/cGFnZT0xIgogICAgICBgYGAKICAgICAgIC0tLQogICAgICAgSWYgeW91IGRvIHNvbWV0aGluZyBsaWtlIHRoaXM6CiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIHN0b3JlLnF1ZXJ5KCdwZXJzb24nLCB7IGlkczogWzEsIDIsIDNdIH0pOwogICAgICBgYGAKICAgICAgIFRoZSByZXF1ZXN0IG1hZGUgdG8gdGhlIHNlcnZlciB3aWxsIGxvb2sgc29tZXRoaW5nIGxpa2UgdGhpczoKICAgICAgIGBgYAogICAgICBHRVQgIi9hcGkvdjEvcGVyc29uP2lkcyU1QiU1RD0xJmlkcyU1QiU1RD0yJmlkcyU1QiU1RD0zIgogICAgICBkZWNvZGVkOiAiL2FwaS92MS9wZXJzb24/aWRzW109MSZpZHNbXT0yJmlkc1tdPTMiCiAgICAgIGBgYAogICAgICAgVGhpcyBtZXRob2QgcmV0dXJucyBhIHByb21pc2UsIHdoaWNoIGlzIHJlc29sdmVkIHdpdGggYW4KICAgICAgW2BBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXlgXSgvZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5KQogICAgICBvbmNlIHRoZSBzZXJ2ZXIgcmV0dXJucy4KICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBxdWVyeQogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7YW55fSBxdWVyeSBhbiBvcGFxdWUgcXVlcnkgdG8gYmUgdXNlZCBieSB0aGUgYWRhcHRlcgogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBvcHRpb25hbCwgbWF5IGluY2x1ZGUgYGFkYXB0ZXJPcHRpb25zYCBoYXNoIHdoaWNoIHdpbGwgYmUgcGFzc2VkIHRvIGFkYXB0ZXIucXVlcnkKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucXVlcnkgPSBmdW5jdGlvbiBxdWVyeShtb2RlbE5hbWUsIF9xdWVyeTIsIG9wdGlvbnMpIHsKICAgICAgdmFyIGFkYXB0ZXJPcHRpb25zV3JhcHBlciA9IHt9OwoKICAgICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5hZGFwdGVyT3B0aW9ucykgewogICAgICAgIGFkYXB0ZXJPcHRpb25zV3JhcHBlci5hZGFwdGVyT3B0aW9ucyA9IG9wdGlvbnMuYWRhcHRlck9wdGlvbnM7CiAgICAgIH0KCiAgICAgIHZhciBub3JtYWxpemVkTW9kZWxOYW1lID0gbm9ybWFsaXplTW9kZWxOYW1lKG1vZGVsTmFtZSk7CiAgICAgIHJldHVybiB0aGlzLl9xdWVyeShub3JtYWxpemVkTW9kZWxOYW1lLCBfcXVlcnkyLCBudWxsLCBhZGFwdGVyT3B0aW9uc1dyYXBwZXIpOwogICAgfTsKCiAgICBfcHJvdG8uX3F1ZXJ5ID0gZnVuY3Rpb24gX3F1ZXJ5JDEobW9kZWxOYW1lLCBxdWVyeSwgYXJyYXksIG9wdGlvbnMpIHsKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXJGb3IobW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIHByb21pc2VBcnJheShfcXVlcnkoYWRhcHRlciwgdGhpcywgbW9kZWxOYW1lLCBxdWVyeSwgYXJyYXksIG9wdGlvbnMpKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBtYWtlcyBhIHJlcXVlc3QgZm9yIG9uZSByZWNvcmQsIHdoZXJlIHRoZSBgaWRgIGlzIG5vdCBrbm93bgogICAgICBiZWZvcmVoYW5kIChpZiB0aGUgYGlkYCBpcyBrbm93biwgdXNlIFtgZmluZFJlY29yZGBdKFN0b3JlL21ldGhvZHMvZmluZFJlY29yZD9hbmNob3I9ZmluZFJlY29yZCkKICAgICAgaW5zdGVhZCkuCiAgICAgICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB3aGVuIGl0IGlzIGNlcnRhaW4gdGhhdCB0aGUgc2VydmVyIHdpbGwgcmV0dXJuIGEKICAgICAgc2luZ2xlIG9iamVjdCBmb3IgdGhlIHByaW1hcnkgZGF0YS4KICAgICAgIEVhY2ggdGltZSB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgYSBuZXcgcmVxdWVzdCBpcyBtYWRlIHRocm91Z2ggdGhlIGFkYXB0ZXIuCiAgICAgICBMZXQncyBhc3N1bWUgb3VyIEFQSSBwcm92aWRlcyBhbiBlbmRwb2ludCBmb3IgdGhlIGN1cnJlbnRseSBsb2dnZWQgaW4gdXNlcgogICAgICB2aWE6CiAgICAgICBgYGAKICAgICAgLy8gR0VUIC9hcGkvY3VycmVudF91c2VyCiAgICAgIHsKICAgICAgICB1c2VyOiB7CiAgICAgICAgICBpZDogMTIzNCwKICAgICAgICAgIHVzZXJuYW1lOiAnYWRtaW4nCiAgICAgICAgfQogICAgICB9CiAgICAgIGBgYAogICAgICAgU2luY2UgdGhlIHNwZWNpZmljIGBpZGAgb2YgdGhlIGB1c2VyYCBpcyBub3Qga25vd24gYmVmb3JlaGFuZCwgd2UgY2FuIHVzZQogICAgICBgcXVlcnlSZWNvcmRgIHRvIGdldCB0aGUgdXNlcjoKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc3RvcmUucXVlcnlSZWNvcmQoJ3VzZXInLCB7fSkudGhlbihmdW5jdGlvbih1c2VyKSB7CiAgICAgICAgbGV0IHVzZXJuYW1lID0gdXNlci5nZXQoJ3VzZXJuYW1lJyk7CiAgICAgICAgY29uc29sZS5sb2coYEN1cnJlbnRseSBsb2dnZWQgaW4gYXMgJHt1c2VybmFtZX1gKTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgVGhlIHJlcXVlc3QgaXMgbWFkZSB0aHJvdWdoIHRoZSBhZGFwdGVycycgYHF1ZXJ5UmVjb3JkYDoKICAgICAgIGBgYGFwcC9hZGFwdGVycy91c2VyLmpzCiAgICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeSc7CiAgICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlci5leHRlbmQoewogICAgICAgIHF1ZXJ5UmVjb3JkKG1vZGVsTmFtZSwgcXVlcnkpIHsKICAgICAgICAgIHJldHVybiAkLmdldEpTT04oJy9hcGkvY3VycmVudF91c2VyJyk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBOb3RlOiB0aGUgcHJpbWFyeSB1c2UgY2FzZSBmb3IgYHN0b3JlLnF1ZXJ5UmVjb3JkYCBpcyB3aGVuIGEgc2luZ2xlIHJlY29yZAogICAgICBpcyBxdWVyaWVkIGFuZCB0aGUgYGlkYCBpcyBub3Qga25vd24gYmVmb3JlaGFuZC4gSW4gYWxsIG90aGVyIGNhc2VzCiAgICAgIGBzdG9yZS5xdWVyeWAgYW5kIHVzaW5nIHRoZSBmaXJzdCBpdGVtIG9mIHRoZSBhcnJheSBpcyBsaWtlbHkgdGhlIHByZWZlcnJlZAogICAgICB3YXk6CiAgICAgICBgYGAKICAgICAgLy8gR0VUIC91c2Vycz91c2VybmFtZT11bmlxdWUKICAgICAgewogICAgICAgIGRhdGE6IFt7CiAgICAgICAgICBpZDogMTIzNCwKICAgICAgICAgIHR5cGU6ICd1c2VyJywKICAgICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgICAgdXNlcm5hbWU6ICJ1bmlxdWUiCiAgICAgICAgICB9CiAgICAgICAgfV0KICAgICAgfQogICAgICBgYGAKICAgICAgIGBgYGphdmFzY3JpcHQKICAgICAgc3RvcmUucXVlcnkoJ3VzZXInLCB7IHVzZXJuYW1lOiAndW5pcXVlJyB9KS50aGVuKGZ1bmN0aW9uKHVzZXJzKSB7CiAgICAgICAgcmV0dXJuIHVzZXJzLmdldCgnZmlyc3RPYmplY3QnKTsKICAgICAgfSkudGhlbihmdW5jdGlvbih1c2VyKSB7CiAgICAgICAgbGV0IGlkID0gdXNlci5nZXQoJ2lkJyk7CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRoaXMgbWV0aG9kIHJldHVybnMgYSBwcm9taXNlLCB3aGljaCByZXNvbHZlcyB3aXRoIHRoZSBmb3VuZCByZWNvcmQuCiAgICAgICBJZiB0aGUgYWRhcHRlciByZXR1cm5zIG5vIGRhdGEgZm9yIHRoZSBwcmltYXJ5IGRhdGEgb2YgdGhlIHBheWxvYWQsIHRoZW4KICAgICAgYHF1ZXJ5UmVjb3JkYCByZXNvbHZlcyB3aXRoIGBudWxsYDoKICAgICAgIGBgYAogICAgICAvLyBHRVQgL3VzZXJzP3VzZXJuYW1lPXVuaXF1ZQogICAgICB7CiAgICAgICAgZGF0YTogbnVsbAogICAgICB9CiAgICAgIGBgYAogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBzdG9yZS5xdWVyeVJlY29yZCgndXNlcicsIHsgdXNlcm5hbWU6ICd1bmlxdWUnIH0pLnRoZW4oZnVuY3Rpb24odXNlcikgewogICAgICAgIGNvbnNvbGUubG9nKHVzZXIpOyAvLyBudWxsCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBxdWVyeVJlY29yZAogICAgICBAcGFyYW0ge1N0cmluZ30gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7YW55fSBxdWVyeSBhbiBvcGFxdWUgcXVlcnkgdG8gYmUgdXNlZCBieSB0aGUgYWRhcHRlcgogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBvcHRpb25hbCwgbWF5IGluY2x1ZGUgYGFkYXB0ZXJPcHRpb25zYCBoYXNoIHdoaWNoIHdpbGwgYmUgcGFzc2VkIHRvIGFkYXB0ZXIucXVlcnlSZWNvcmQKICAgICAgQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aXRoIHRoZSBmb3VuZCByZWNvcmQgb3IgYG51bGxgCiAgICAqLwogICAgOwoKICAgIF9wcm90by5xdWVyeVJlY29yZCA9IGZ1bmN0aW9uIHF1ZXJ5UmVjb3JkKG1vZGVsTmFtZSwgcXVlcnksIG9wdGlvbnMpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgdmFyIGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXJGb3Iobm9ybWFsaXplZE1vZGVsTmFtZSk7CiAgICAgIHZhciBhZGFwdGVyT3B0aW9uc1dyYXBwZXIgPSB7fTsKCiAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuYWRhcHRlck9wdGlvbnMpIHsKICAgICAgICBhZGFwdGVyT3B0aW9uc1dyYXBwZXIuYWRhcHRlck9wdGlvbnMgPSBvcHRpb25zLmFkYXB0ZXJPcHRpb25zOwogICAgICB9CiAgICAgIHJldHVybiBwcm9taXNlT2JqZWN0KF9xdWVyeVJlY29yZChhZGFwdGVyLCB0aGlzLCBub3JtYWxpemVkTW9kZWxOYW1lLCBxdWVyeSwgYWRhcHRlck9wdGlvbnNXcmFwcGVyKS50aGVuKGZ1bmN0aW9uIChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgLy8gdGhlIHByb21pc2UgcmV0dXJuZWQgYnkgc3RvcmUucXVlcnlSZWNvcmQgaXMgZXhwZWN0ZWQgdG8gcmVzb2x2ZSB3aXRoCiAgICAgICAgLy8gYW4gaW5zdGFuY2Ugb2YgTW9kZWwKICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbCkgewogICAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwuZ2V0UmVjb3JkKCk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfSkpOwogICAgfQogICAgLyoqCiAgICAgIGBmaW5kQWxsYCBhc2tzIHRoZSBhZGFwdGVyJ3MgYGZpbmRBbGxgIG1ldGhvZCB0byBmaW5kIHRoZSByZWNvcmRzIGZvciB0aGUKICAgICAgZ2l2ZW4gdHlwZSwgYW5kIHJldHVybnMgYSBwcm9taXNlIHdoaWNoIHdpbGwgcmVzb2x2ZSB3aXRoIGFsbCByZWNvcmRzIG9mCiAgICAgIHRoaXMgdHlwZSBwcmVzZW50IGluIHRoZSBzdG9yZSwgZXZlbiBpZiB0aGUgYWRhcHRlciBvbmx5IHJldHVybnMgYSBzdWJzZXQKICAgICAgb2YgdGhlbS4KICAgICAgIGBgYGFwcC9yb3V0ZXMvYXV0aG9ycy5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBtb2RlbChwYXJhbXMpIHsKICAgICAgICAgIHJldHVybiB0aGlzLnN0b3JlLmZpbmRBbGwoJ2F1dGhvcicpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgX1doZW5fIHRoZSByZXR1cm5lZCBwcm9taXNlIHJlc29sdmVzIGRlcGVuZHMgb24gdGhlIHJlbG9hZCBiZWhhdmlvciwKICAgICAgY29uZmlndXJlZCB2aWEgdGhlIHBhc3NlZCBgb3B0aW9uc2AgaGFzaCBhbmQgdGhlIHJlc3VsdCBvZiB0aGUgYWRhcHRlcidzCiAgICAgIGBzaG91bGRSZWxvYWRBbGxgIG1ldGhvZC4KICAgICAgICMjIyBSZWxvYWRpbmcKICAgICAgIElmIGB7IHJlbG9hZDogdHJ1ZSB9YCBpcyBwYXNzZWQgb3IgYGFkYXB0ZXIuc2hvdWxkUmVsb2FkQWxsYCBldmFsdWF0ZXMgdG8KICAgICAgYHRydWVgLCB0aGVuIHRoZSByZXR1cm5lZCBwcm9taXNlIHJlc29sdmVzIG9uY2UgdGhlIGFkYXB0ZXIgcmV0dXJucyBkYXRhLAogICAgICByZWdhcmRsZXNzIGlmIHRoZXJlIGFyZSBhbHJlYWR5IHJlY29yZHMgaW4gdGhlIHN0b3JlOgogICAgICAgYGBganMKICAgICAgc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogewogICAgICAgICAgaWQ6ICdmaXJzdCcsCiAgICAgICAgICB0eXBlOiAnYXV0aG9yJwogICAgICAgIH0KICAgICAgfSk7CiAgICAgICAvLyBhZGFwdGVyI2ZpbmRBbGwgcmVzb2x2ZXMgd2l0aAogICAgICAvLyBbCiAgICAgIC8vICAgewogICAgICAvLyAgICAgaWQ6ICdzZWNvbmQnLAogICAgICAvLyAgICAgdHlwZTogJ2F1dGhvcicKICAgICAgLy8gICB9CiAgICAgIC8vIF0KICAgICAgc3RvcmUuZmluZEFsbCgnYXV0aG9yJywgeyByZWxvYWQ6IHRydWUgfSkudGhlbihmdW5jdGlvbihhdXRob3JzKSB7CiAgICAgICAgYXV0aG9ycy5nZXRFYWNoKCdpZCcpOyAvLyBbJ2ZpcnN0JywgJ3NlY29uZCddCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIElmIG5vIHJlbG9hZCBpcyBpbmRpY2F0ZWQgdmlhIHRoZSBhYm92ZSBtZW50aW9uZWQgd2F5cywgdGhlbiB0aGUgcHJvbWlzZQogICAgICBpbW1lZGlhdGVseSByZXNvbHZlcyB3aXRoIGFsbCB0aGUgcmVjb3JkcyBjdXJyZW50bHkgbG9hZGVkIGluIHRoZSBzdG9yZS4KICAgICAgICMjIyBCYWNrZ3JvdW5kIFJlbG9hZGluZwogICAgICAgT3B0aW9uYWxseSwgaWYgYGFkYXB0ZXIuc2hvdWxkQmFja2dyb3VuZFJlbG9hZEFsbGAgZXZhbHVhdGVzIHRvIGB0cnVlYCwKICAgICAgdGhlbiBhIGJhY2tncm91bmQgcmVsb2FkIGlzIHN0YXJ0ZWQuIE9uY2UgdGhpcyByZXNvbHZlcywgdGhlIGFycmF5IHdpdGgKICAgICAgd2hpY2ggdGhlIHByb21pc2UgcmVzb2x2ZXMsIGlzIHVwZGF0ZWQgYXV0b21hdGljYWxseSBzbyBpdCBjb250YWlucyBhbGwgdGhlCiAgICAgIHJlY29yZHMgaW4gdGhlIHN0b3JlOgogICAgICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBBZGFwdGVyIGZyb20gJ0BlbWJlci1kYXRhL2FkYXB0ZXInOwogICAgICBleHBvcnQgZGVmYXVsdCBBZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgc2hvdWxkUmVsb2FkQWxsKHN0b3JlLCBzbmFwc2hvdHNBcnJheSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0sCiAgICAgICAgIHNob3VsZEJhY2tncm91bmRSZWxvYWRBbGwoc3RvcmUsIHNuYXBzaG90c0FycmF5KSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgLy8gLi4uCiAgICAgICBzdG9yZS5wdXNoKHsKICAgICAgICBkYXRhOiB7CiAgICAgICAgICBpZDogJ2ZpcnN0JywKICAgICAgICAgIHR5cGU6ICdhdXRob3InCiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGxldCBhbGxBdXRob3JzOwogICAgICBzdG9yZS5maW5kQWxsKCdhdXRob3InKS50aGVuKGZ1bmN0aW9uKGF1dGhvcnMpIHsKICAgICAgICBhdXRob3JzLmdldEVhY2goJ2lkJyk7IC8vIFsnZmlyc3QnXQogICAgICAgICBhbGxBdXRob3JzID0gYXV0aG9yczsKICAgICAgfSk7CiAgICAgICAvLyBsYXRlciwgb25jZSBhZGFwdGVyI2ZpbmRBbGwgcmVzb2x2ZWQgd2l0aAogICAgICAvLyBbCiAgICAgIC8vICAgewogICAgICAvLyAgICAgaWQ6ICdzZWNvbmQnLAogICAgICAvLyAgICAgdHlwZTogJ2F1dGhvcicKICAgICAgLy8gICB9CiAgICAgIC8vIF0KICAgICAgIGFsbEF1dGhvcnMuZ2V0RWFjaCgnaWQnKTsgLy8gWydmaXJzdCcsICdzZWNvbmQnXQogICAgICBgYGAKICAgICAgIElmIHlvdSB3b3VsZCBsaWtlIHRvIGZvcmNlIG9yIHByZXZlbnQgYmFja2dyb3VuZCByZWxvYWRpbmcsIHlvdSBjYW4gc2V0IGEKICAgICAgYm9vbGVhbiB2YWx1ZSBmb3IgYGJhY2tncm91bmRSZWxvYWRgIGluIHRoZSBvcHRpb25zIG9iamVjdCBmb3IKICAgICAgYGZpbmRBbGxgLgogICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0L2VkaXQuanMKICAgICAgaW1wb3J0IFJvdXRlIGZyb20gJ0BlbWJlci9yb3V0aW5nL3JvdXRlJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IFJvdXRlLmV4dGVuZCh7CiAgICAgICAgbW9kZWwoKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5zdG9yZS5maW5kQWxsKCdwb3N0JywgeyBiYWNrZ3JvdW5kUmVsb2FkOiBmYWxzZSB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIElmIHlvdSBwYXNzIGFuIG9iamVjdCBvbiB0aGUgYGFkYXB0ZXJPcHRpb25zYCBwcm9wZXJ0eSBvZiB0aGUgb3B0aW9ucwogICAgICBhcmd1bWVudCBpdCB3aWxsIGJlIHBhc3NlZCB0byB5b3UgYWRhcHRlciB2aWEgdGhlIGBzbmFwc2hvdFJlY29yZEFycmF5YAogICAgICAgYGBgYXBwL3JvdXRlcy9wb3N0cy5qcwogICAgICBpbXBvcnQgUm91dGUgZnJvbSAnQGVtYmVyL3JvdXRpbmcvcm91dGUnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUm91dGUuZXh0ZW5kKHsKICAgICAgICBtb2RlbChwYXJhbXMpIHsKICAgICAgICAgIHJldHVybiB0aGlzLnN0b3JlLmZpbmRBbGwoJ3Bvc3QnLCB7CiAgICAgICAgICAgIGFkYXB0ZXJPcHRpb25zOiB7IHN1YnNjcmliZTogZmFsc2UgfQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBgYGBhcHAvYWRhcHRlcnMvcG9zdC5qcwogICAgICBpbXBvcnQgTXlDdXN0b21BZGFwdGVyIGZyb20gJy4vY3VzdG9tLWFkYXB0ZXInOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTXlDdXN0b21BZGFwdGVyLmV4dGVuZCh7CiAgICAgICAgZmluZEFsbChzdG9yZSwgdHlwZSwgc2luY2VUb2tlbiwgc25hcHNob3RSZWNvcmRBcnJheSkgewogICAgICAgICAgaWYgKHNuYXBzaG90UmVjb3JkQXJyYXkuYWRhcHRlck9wdGlvbnMuc3Vic2NyaWJlKSB7CiAgICAgICAgICAgIC8vIC4uLgogICAgICAgICAgfQogICAgICAgICAgLy8gLi4uCiAgICAgICAgfQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBTZWUgW3BlZWtBbGxdKFN0b3JlL21ldGhvZHMvcGVla0FsbD9hbmNob3I9cGVla0FsbCkgdG8gZ2V0IGFuIGFycmF5IG9mIGN1cnJlbnQgcmVjb3JkcyBpbiB0aGUKICAgICAgc3RvcmUsIHdpdGhvdXQgd2FpdGluZyB1bnRpbCBhIHJlbG9hZCBpcyBmaW5pc2hlZC4KICAgICAgICMjIyBSZXRyaWV2aW5nIFJlbGF0ZWQgTW9kZWwgUmVjb3JkcwogICAgICAgSWYgeW91IHVzZSBhbiBhZGFwdGVyIHN1Y2ggYXMgRW1iZXIncyBkZWZhdWx0CiAgICAgIFtgSlNPTkFQSUFkYXB0ZXJgXSgvZW1iZXItZGF0YS9yZWxlYXNlL2NsYXNzZXMvSlNPTkFQSUFkYXB0ZXIpCiAgICAgIHRoYXQgc3VwcG9ydHMgdGhlIFtKU09OIEFQSSBzcGVjaWZpY2F0aW9uXShodHRwOi8vanNvbmFwaS5vcmcvKSBhbmQgaWYgeW91ciBzZXJ2ZXIKICAgICAgZW5kcG9pbnQgc3VwcG9ydHMgdGhlIHVzZSBvZiBhbgogICAgICBbJ2luY2x1ZGUnIHF1ZXJ5IHBhcmFtZXRlcl0oaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdC8jZmV0Y2hpbmctaW5jbHVkZXMpLAogICAgICB5b3UgY2FuIHVzZSBgZmluZEFsbCgpYCB0byBhdXRvbWF0aWNhbGx5IHJldHJpZXZlIGFkZGl0aW9uYWwgcmVjb3JkcyByZWxhdGVkIHRvCiAgICAgIHRob3NlIHJlcXVlc3RlZCBieSBzdXBwbHlpbmcgYW4gYGluY2x1ZGVgIHBhcmFtZXRlciBpbiB0aGUgYG9wdGlvbnNgIG9iamVjdC4KICAgICAgIEZvciBleGFtcGxlLCBnaXZlbiBhIGBwb3N0YCBtb2RlbCB0aGF0IGhhcyBhIGBoYXNNYW55YCByZWxhdGlvbnNoaXAgd2l0aCBhIGBjb21tZW50YAogICAgICBtb2RlbCwgd2hlbiB3ZSByZXRyaWV2ZSBhbGwgb2YgdGhlIHBvc3QgcmVjb3JkcyB3ZSBjYW4gaGF2ZSB0aGUgc2VydmVyIGFsc28gcmV0dXJuCiAgICAgIGFsbCBvZiB0aGUgcG9zdHMnIGNvbW1lbnRzIGluIHRoZSBzYW1lIHJlcXVlc3Q6CiAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3RzLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIG1vZGVsKCkgewogICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZmluZEFsbCgncG9zdCcsIHsgaW5jbHVkZTogJ2NvbW1lbnRzJyB9KTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICAgYGBgCiAgICAgIE11bHRpcGxlIHJlbGF0aW9uc2hpcHMgY2FuIGJlIHJlcXVlc3RlZCB1c2luZyBhbiBgaW5jbHVkZWAgcGFyYW1ldGVyIGNvbnNpc3Rpbmcgb2YgYQogICAgICBjb21tYS1zZXBhcmF0ZWQgbGlzdCAod2l0aG91dCB3aGl0ZS1zcGFjZSkgd2hpbGUgbmVzdGVkIHJlbGF0aW9uc2hpcHMgY2FuIGJlIHNwZWNpZmllZAogICAgICB1c2luZyBhIGRvdC1zZXBhcmF0ZWQgc2VxdWVuY2Ugb2YgcmVsYXRpb25zaGlwIG5hbWVzLiBTbyB0byByZXF1ZXN0IGJvdGggdGhlIHBvc3RzJwogICAgICBjb21tZW50cyBhbmQgdGhlIGF1dGhvcnMgb2YgdGhvc2UgY29tbWVudHMgdGhlIHJlcXVlc3Qgd291bGQgbG9vayBsaWtlIHRoaXM6CiAgICAgICBgYGBhcHAvcm91dGVzL3Bvc3RzLmpzCiAgICAgIGltcG9ydCBSb3V0ZSBmcm9tICdAZW1iZXIvcm91dGluZy9yb3V0ZSc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSb3V0ZS5leHRlbmQoewogICAgICAgIG1vZGVsKCkgewogICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmUuZmluZEFsbCgncG9zdCcsIHsgaW5jbHVkZTogJ2NvbW1lbnRzLGNvbW1lbnRzLmF1dGhvcicgfSk7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgIGBgYAogICAgICAgU2VlIFtxdWVyeV0oU3RvcmUvbWV0aG9kcy9xdWVyeT9hbmNob3I9cXVlcnkpIHRvIG9ubHkgZ2V0IGEgc3Vic2V0IG9mIHJlY29yZHMgZnJvbSB0aGUgc2VydmVyLgogICAgICAgQHNpbmNlIDEuMTMuMAogICAgICBAbWV0aG9kIGZpbmRBbGwKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgICBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5maW5kQWxsID0gZnVuY3Rpb24gZmluZEFsbChtb2RlbE5hbWUsIG9wdGlvbnMpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKCiAgICAgIHZhciBmZXRjaCA9IHRoaXMuX2ZldGNoQWxsKG5vcm1hbGl6ZWRNb2RlbE5hbWUsIHRoaXMucGVla0FsbChub3JtYWxpemVkTW9kZWxOYW1lKSwgb3B0aW9ucyk7CgogICAgICByZXR1cm4gZmV0Y2g7CiAgICB9CiAgICAvKioKICAgICAgQG1ldGhvZCBfZmV0Y2hBbGwKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtNb2RlbH0gbW9kZWxOYW1lCiAgICAgIEBwYXJhbSB7UmVjb3JkQXJyYXl9IGFycmF5CiAgICAgIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9mZXRjaEFsbCA9IGZ1bmN0aW9uIF9mZXRjaEFsbChtb2RlbE5hbWUsIGFycmF5LCBvcHRpb25zKSB7CiAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsKICAgICAgICBvcHRpb25zID0ge307CiAgICAgIH0KCiAgICAgIHZhciBhZGFwdGVyID0gdGhpcy5hZGFwdGVyRm9yKG1vZGVsTmFtZSk7CgogICAgICBpZiAob3B0aW9ucy5yZWxvYWQpIHsKICAgICAgICBFbWJlci5zZXQoYXJyYXksICdpc1VwZGF0aW5nJywgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIHByb21pc2VBcnJheShfZmluZEFsbChhZGFwdGVyLCB0aGlzLCBtb2RlbE5hbWUsIG9wdGlvbnMpKTsKICAgICAgfQoKICAgICAgdmFyIHNuYXBzaG90QXJyYXkgPSBhcnJheS5fY3JlYXRlU25hcHNob3Qob3B0aW9ucyk7CgogICAgICBpZiAoYWRhcHRlci5zaG91bGRSZWxvYWRBbGwodGhpcywgc25hcHNob3RBcnJheSkpIHsKICAgICAgICBFbWJlci5zZXQoYXJyYXksICdpc1VwZGF0aW5nJywgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIHByb21pc2VBcnJheShfZmluZEFsbChhZGFwdGVyLCB0aGlzLCBtb2RlbE5hbWUsIG9wdGlvbnMpKTsKICAgICAgfQoKICAgICAgaWYgKG9wdGlvbnMuYmFja2dyb3VuZFJlbG9hZCA9PT0gZmFsc2UpIHsKICAgICAgICByZXR1cm4gcHJvbWlzZUFycmF5KEVtYmVyLlJTVlAuUHJvbWlzZS5yZXNvbHZlKGFycmF5KSk7CiAgICAgIH0KCiAgICAgIGlmIChvcHRpb25zLmJhY2tncm91bmRSZWxvYWQgfHwgYWRhcHRlci5zaG91bGRCYWNrZ3JvdW5kUmVsb2FkQWxsKHRoaXMsIHNuYXBzaG90QXJyYXkpKSB7CiAgICAgICAgRW1iZXIuc2V0KGFycmF5LCAnaXNVcGRhdGluZycsIHRydWUpOwoKICAgICAgICBfZmluZEFsbChhZGFwdGVyLCB0aGlzLCBtb2RlbE5hbWUsIG9wdGlvbnMpOwogICAgICB9CgogICAgICByZXR1cm4gcHJvbWlzZUFycmF5KEVtYmVyLlJTVlAuUHJvbWlzZS5yZXNvbHZlKGFycmF5KSk7CiAgICB9CiAgICAvKioKICAgICAgQG1ldGhvZCBfZGlkVXBkYXRlQWxsCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHByaXZhdGUKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9kaWRVcGRhdGVBbGwgPSBmdW5jdGlvbiBfZGlkVXBkYXRlQWxsKG1vZGVsTmFtZSkgewogICAgICB0aGlzLnJlY29yZEFycmF5TWFuYWdlci5fZGlkVXBkYXRlQWxsKG1vZGVsTmFtZSk7CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgcmV0dXJucyBhIGZpbHRlcmVkIGFycmF5IHRoYXQgY29udGFpbnMgYWxsIG9mIHRoZQogICAgICBrbm93biByZWNvcmRzIGZvciBhIGdpdmVuIHR5cGUgaW4gdGhlIHN0b3JlLgogICAgICAgTm90ZSB0aGF0IGJlY2F1c2UgaXQncyBqdXN0IGEgZmlsdGVyLCB0aGUgcmVzdWx0IHdpbGwgY29udGFpbiBhbnkKICAgICAgbG9jYWxseSBjcmVhdGVkIHJlY29yZHMgb2YgdGhlIHR5cGUsIGhvd2V2ZXIsIGl0IHdpbGwgbm90IG1ha2UgYQogICAgICByZXF1ZXN0IHRvIHRoZSBiYWNrZW5kIHRvIHJldHJpZXZlIGFkZGl0aW9uYWwgcmVjb3Jkcy4gSWYgeW91CiAgICAgIHdvdWxkIGxpa2UgdG8gcmVxdWVzdCBhbGwgdGhlIHJlY29yZHMgZnJvbSB0aGUgYmFja2VuZCBwbGVhc2UgdXNlCiAgICAgIFtzdG9yZS5maW5kQWxsXShTdG9yZS9tZXRob2RzL2ZpbmRBbGw/YW5jaG9yPWZpbmRBbGwpLgogICAgICAgQWxzbyBub3RlIHRoYXQgbXVsdGlwbGUgY2FsbHMgdG8gYHBlZWtBbGxgIGZvciBhIGdpdmVuIHR5cGUgd2lsbCBhbHdheXMKICAgICAgcmV0dXJuIHRoZSBzYW1lIGBSZWNvcmRBcnJheWAuCiAgICAgICBFeGFtcGxlCiAgICAgICBgYGBqYXZhc2NyaXB0CiAgICAgIGxldCBsb2NhbFBvc3RzID0gc3RvcmUucGVla0FsbCgncG9zdCcpOwogICAgICBgYGAKICAgICAgIEBzaW5jZSAxLjEzLjAKICAgICAgQG1ldGhvZCBwZWVrQWxsCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHJldHVybiB7UmVjb3JkQXJyYXl9CiAgICAqLwogICAgOwoKICAgIF9wcm90by5wZWVrQWxsID0gZnVuY3Rpb24gcGVla0FsbChtb2RlbE5hbWUpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIHRoaXMucmVjb3JkQXJyYXlNYW5hZ2VyLmxpdmVSZWNvcmRBcnJheUZvcihub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCB1bmxvYWRzIGFsbCByZWNvcmRzIGluIHRoZSBzdG9yZS4KICAgICAgSXQgc2NoZWR1bGVzIHVubG9hZGluZyB0byBoYXBwZW4gZHVyaW5nIHRoZSBuZXh0IHJ1biBsb29wLgogICAgICAgT3B0aW9uYWxseSB5b3UgY2FuIHBhc3MgYSB0eXBlIHdoaWNoIHVubG9hZCBhbGwgcmVjb3JkcyBmb3IgYSBnaXZlbiB0eXBlLgogICAgICAgYGBgamF2YXNjcmlwdAogICAgICBzdG9yZS51bmxvYWRBbGwoKTsKICAgICAgc3RvcmUudW5sb2FkQWxsKCdwb3N0Jyk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCB1bmxvYWRBbGwKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZQogICAgKi8KICAgIDsKCiAgICBfcHJvdG8udW5sb2FkQWxsID0gZnVuY3Rpb24gdW5sb2FkQWxsKG1vZGVsTmFtZSkgewogICAgICB2YXIgZmFjdG9yeSA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpOwoKICAgICAgaWYgKG1vZGVsTmFtZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZmFjdG9yeS5jbGVhcigpOwogICAgICB9IGVsc2UgewogICAgICAgIHZhciBub3JtYWxpemVkTW9kZWxOYW1lID0gbm9ybWFsaXplTW9kZWxOYW1lKG1vZGVsTmFtZSk7CiAgICAgICAgZmFjdG9yeS5jbGVhcihub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uZmlsdGVyID0gZnVuY3Rpb24gZmlsdGVyKCkgewogICAgfSAvLyAuLi4uLi4uLi4uLi4uLgogICAgLy8gLiBQRVJTSVNUSU5HIC4KICAgIC8vIC4uLi4uLi4uLi4uLi4uCgogICAgLyoqCiAgICAgIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBieSBgcmVjb3JkLnNhdmVgLCBhbmQgZ2V0cyBwYXNzZWQgYQogICAgICByZXNvbHZlciBmb3IgdGhlIHByb21pc2UgdGhhdCBgcmVjb3JkLnNhdmVgIHJldHVybnMuCiAgICAgICBJdCBzY2hlZHVsZXMgc2F2aW5nIHRvIGhhcHBlbiBhdCB0aGUgZW5kIG9mIHRoZSBydW4gbG9vcC4KICAgICAgIEBtZXRob2Qgc2NoZWR1bGVTYXZlCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7SW50ZXJuYWxNb2RlbH0gaW50ZXJuYWxNb2RlbAogICAgICBAcGFyYW0ge1Jlc29sdmVyfSByZXNvbHZlcgogICAgICBAcGFyYW0ge09iamVjdH0gb3B0aW9ucwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8uc2NoZWR1bGVTYXZlID0gZnVuY3Rpb24gc2NoZWR1bGVTYXZlKGludGVybmFsTW9kZWwsIHJlc29sdmVyLCBvcHRpb25zKSB7CiAgICAgIHZhciBfdGhpczYgPSB0aGlzOwoKICAgICAgdmFyIHNuYXBzaG90ID0gaW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdChvcHRpb25zKTsKCiAgICAgIGlmIChpbnRlcm5hbE1vZGVsLl9pc1JlY29yZEZ1bGx5RGVsZXRlZCgpKSB7CiAgICAgICAgcmVzb2x2ZXIucmVzb2x2ZSgpOwogICAgICAgIHJldHVybiByZXNvbHZlci5wcm9taXNlOwogICAgICB9CgogICAgICBpbnRlcm5hbE1vZGVsLmFkYXB0ZXJXaWxsQ29tbWl0KCk7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuUkVRVUVTVF9TRVJWSUNFKSB7CiAgICAgICAgaWYgKCFvcHRpb25zKSB7CiAgICAgICAgICBvcHRpb25zID0ge307CiAgICAgICAgfQoKICAgICAgICB2YXIgcmVjb3JkRGF0YSA9IGludGVybmFsTW9kZWwuX3JlY29yZERhdGE7CiAgICAgICAgdmFyIG9wZXJhdGlvbiA9ICd1cGRhdGVSZWNvcmQnOyAvLyBUT0RPIGhhbmRsZSBtaXNzaW5nIGlzTmV3CgogICAgICAgIGlmIChyZWNvcmREYXRhLmlzTmV3ICYmIHJlY29yZERhdGEuaXNOZXcoKSkgewogICAgICAgICAgb3BlcmF0aW9uID0gJ2NyZWF0ZVJlY29yZCc7CiAgICAgICAgfSBlbHNlIGlmIChyZWNvcmREYXRhLmlzRGVsZXRlZCAmJiByZWNvcmREYXRhLmlzRGVsZXRlZCgpKSB7CiAgICAgICAgICBvcGVyYXRpb24gPSAnZGVsZXRlUmVjb3JkJzsKICAgICAgICB9CgogICAgICAgIG9wdGlvbnNbU2F2ZU9wXSA9IG9wZXJhdGlvbjsKCiAgICAgICAgdmFyIGZldGNoTWFuYWdlclByb21pc2UgPSB0aGlzLl9mZXRjaE1hbmFnZXIuc2NoZWR1bGVTYXZlKGludGVybmFsTW9kZWwuaWRlbnRpZmllciwgb3B0aW9ucyk7CgogICAgICAgIHZhciBwcm9taXNlID0gZmV0Y2hNYW5hZ2VyUHJvbWlzZS50aGVuKGZ1bmN0aW9uIChwYXlsb2FkKSB7CiAgICAgICAgICAvKgogICAgICAgICAgTm90ZSB0byBmdXR1cmUgc3BlbHVua2VycyBob3BpbmcgdG8gb3B0aW1pemUuCiAgICAgICAgICBXZSByZWx5IG9uIHRoaXMgYHJ1bmAgdG8gY3JlYXRlIGEgcnVuIGxvb3AgaWYgbmVlZGVkCiAgICAgICAgICB0aGF0IGBzdG9yZS5fcHVzaGAgYW5kIGBzdG9yZS5kaWRTYXZlUmVjb3JkYCB3aWxsIGJvdGggc2hhcmUuCiAgICAgICAgICBXZSB1c2UgYGpvaW5gIGJlY2F1c2UgaXQgaXMgb2Z0ZW4gdGhlIGNhc2UgdGhhdCB3ZQogICAgICAgICAgaGF2ZSBhbiBvdXRlciBydW4gbG9vcCBhdmFpbGFibGUgc3RpbGwgZnJvbSB0aGUgZmlyc3QKICAgICAgICAgIGNhbGwgdG8gYHN0b3JlLl9wdXNoYDsKICAgICAgICAgICovCiAgICAgICAgICBfdGhpczYuX2JhY2tidXJuZXIuam9pbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIHZhciBkYXRhID0gcGF5bG9hZCAmJiBwYXlsb2FkLmRhdGE7CgogICAgICAgICAgICBfdGhpczYuZGlkU2F2ZVJlY29yZChpbnRlcm5hbE1vZGVsLCB7CiAgICAgICAgICAgICAgZGF0YTogZGF0YQogICAgICAgICAgICB9LCBvcGVyYXRpb24pOwoKICAgICAgICAgICAgaWYgKHBheWxvYWQgJiYgcGF5bG9hZC5pbmNsdWRlZCkgewogICAgICAgICAgICAgIF90aGlzNi5fcHVzaCh7CiAgICAgICAgICAgICAgICBkYXRhOiBudWxsLAogICAgICAgICAgICAgICAgaW5jbHVkZWQ6IHBheWxvYWQuaW5jbHVkZWQKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgfSk7CiAgICAgICAgfSwgZnVuY3Rpb24gKF9yZWYpIHsKICAgICAgICAgIHZhciBlcnJvciA9IF9yZWYuZXJyb3IsCiAgICAgICAgICAgICAgcGFyc2VkRXJyb3JzID0gX3JlZi5wYXJzZWRFcnJvcnM7CgogICAgICAgICAgX3RoaXM2LnJlY29yZFdhc0ludmFsaWQoaW50ZXJuYWxNb2RlbCwgcGFyc2VkRXJyb3JzLCBlcnJvcik7CgogICAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIHByb21pc2U7CiAgICAgIH0KCiAgICAgIHRoaXMuX3BlbmRpbmdTYXZlLnB1c2goewogICAgICAgIHNuYXBzaG90OiBzbmFwc2hvdCwKICAgICAgICByZXNvbHZlcjogcmVzb2x2ZXIKICAgICAgfSk7CgogICAgICBlbWJlclJ1biQyLnNjaGVkdWxlT25jZSgnYWN0aW9ucycsIHRoaXMsIHRoaXMuZmx1c2hQZW5kaW5nU2F2ZSk7CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIGF0IHRoZSBlbmQgb2YgdGhlIHJ1biBsb29wLCBhbmQKICAgICAgZmx1c2hlcyBhbnkgcmVjb3JkcyBwYXNzZWQgaW50byBgc2NoZWR1bGVTYXZlYAogICAgICAgQG1ldGhvZCBmbHVzaFBlbmRpbmdTYXZlCiAgICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5mbHVzaFBlbmRpbmdTYXZlID0gZnVuY3Rpb24gZmx1c2hQZW5kaW5nU2F2ZSgpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFUVVFU1RfU0VSVklDRSkgewogICAgICAgIC8vIGFzc2VydCBoZXJlCiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB2YXIgcGVuZGluZyA9IHRoaXMuX3BlbmRpbmdTYXZlLnNsaWNlKCk7CgogICAgICB0aGlzLl9wZW5kaW5nU2F2ZSA9IFtdOwoKICAgICAgZm9yICh2YXIgaSA9IDAsIGogPSBwZW5kaW5nLmxlbmd0aDsgaSA8IGo7IGkrKykgewogICAgICAgIHZhciBwZW5kaW5nSXRlbSA9IHBlbmRpbmdbaV07CiAgICAgICAgdmFyIHNuYXBzaG90ID0gcGVuZGluZ0l0ZW0uc25hcHNob3Q7CiAgICAgICAgdmFyIHJlc29sdmVyID0gcGVuZGluZ0l0ZW0ucmVzb2x2ZXI7CiAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBzbmFwc2hvdC5faW50ZXJuYWxNb2RlbDsKICAgICAgICB2YXIgYWRhcHRlciA9IHRoaXMuYWRhcHRlckZvcihpbnRlcm5hbE1vZGVsLm1vZGVsTmFtZSk7CiAgICAgICAgdmFyIG9wZXJhdGlvbiA9IHZvaWQgMDsKCiAgICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX1NUQVRFKSB7CiAgICAgICAgICAvLyBUT0RPIG1vdmUgdGhpcyBvdXQgb2YgaW50ZXJuYWxNb2RlbAogICAgICAgICAgaWYgKGludGVybmFsTW9kZWwuaXNOZXcoKSkgewogICAgICAgICAgICBvcGVyYXRpb24gPSAnY3JlYXRlUmVjb3JkJzsKICAgICAgICAgIH0gZWxzZSBpZiAoaW50ZXJuYWxNb2RlbC5pc0RlbGV0ZWQoKSkgewogICAgICAgICAgICBvcGVyYXRpb24gPSAnZGVsZXRlUmVjb3JkJzsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG9wZXJhdGlvbiA9ICd1cGRhdGVSZWNvcmQnOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoaW50ZXJuYWxNb2RlbC5jdXJyZW50U3RhdGUuc3RhdGVOYW1lID09PSAncm9vdC5kZWxldGVkLnNhdmVkJykgewogICAgICAgICAgICByZXNvbHZlci5yZXNvbHZlKCk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfSBlbHNlIGlmIChpbnRlcm5hbE1vZGVsLmlzTmV3KCkpIHsKICAgICAgICAgICAgb3BlcmF0aW9uID0gJ2NyZWF0ZVJlY29yZCc7CiAgICAgICAgICB9IGVsc2UgaWYgKGludGVybmFsTW9kZWwuaXNEZWxldGVkKCkpIHsKICAgICAgICAgICAgb3BlcmF0aW9uID0gJ2RlbGV0ZVJlY29yZCc7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvcGVyYXRpb24gPSAndXBkYXRlUmVjb3JkJzsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJlc29sdmVyLnJlc29sdmUoX2NvbW1pdChhZGFwdGVyLCB0aGlzLCBvcGVyYXRpb24sIHNuYXBzaG90KSk7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgb25jZSB0aGUgcHJvbWlzZSByZXR1cm5lZCBieSBhbgogICAgICBhZGFwdGVyJ3MgYGNyZWF0ZVJlY29yZGAsIGB1cGRhdGVSZWNvcmRgIG9yIGBkZWxldGVSZWNvcmRgCiAgICAgIGlzIHJlc29sdmVkLgogICAgICAgSWYgdGhlIGRhdGEgcHJvdmlkZXMgYSBzZXJ2ZXItZ2VuZXJhdGVkIElELCBpdCB3aWxsCiAgICAgIHVwZGF0ZSB0aGUgcmVjb3JkIGFuZCB0aGUgc3RvcmUncyBpbmRleGVzLgogICAgICAgQG1ldGhvZCBkaWRTYXZlUmVjb3JkCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7SW50ZXJuYWxNb2RlbH0gaW50ZXJuYWxNb2RlbCB0aGUgaW4tZmxpZ2h0IGludGVybmFsIG1vZGVsCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBkYXRhIG9wdGlvbmFsIGRhdGEgKHNlZSBhYm92ZSkKICAgICAgQHBhcmFtIHtzdHJpbmd9IG9wIHRoZSBhZGFwdGVyIG9wZXJhdGlvbiB0aGF0IHdhcyBjb21taXR0ZWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLmRpZFNhdmVSZWNvcmQgPSBmdW5jdGlvbiBkaWRTYXZlUmVjb3JkKGludGVybmFsTW9kZWwsIGRhdGFBcmcsIG9wKSB7CgogICAgICB2YXIgZGF0YTsKCiAgICAgIGlmIChkYXRhQXJnKSB7CiAgICAgICAgZGF0YSA9IGRhdGFBcmcuZGF0YTsKICAgICAgfQoKICAgICAgewogICAgICAgIHZhciBjYWNoZSA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzKTsKICAgICAgICB2YXIgX2lkZW50aWZpZXIzID0gaW50ZXJuYWxNb2RlbC5pZGVudGlmaWVyOwoKICAgICAgICBpZiAob3AgIT09ICdkZWxldGVSZWNvcmQnICYmIGRhdGEpIHsKICAgICAgICAgIGNhY2hlLnVwZGF0ZVJlY29yZElkZW50aWZpZXIoX2lkZW50aWZpZXIzLCBkYXRhKTsKICAgICAgICB9CiAgICAgIH0gLy9XZSBmaXJzdCBtYWtlIHN1cmUgdGhlIHByaW1hcnkgZGF0YSBoYXMgYmVlbiB1cGRhdGVkCiAgICAgIC8vVE9ETyB0cnkgdG8gbW92ZSBub3RpZmljYXRpb24gdG8gdGhlIHVzZXIgdG8gdGhlIGVuZCBvZiB0aGUgcnVubG9vcAoKCiAgICAgIGludGVybmFsTW9kZWwuYWRhcHRlckRpZENvbW1pdChkYXRhKTsKICAgIH0KICAgIC8qKgogICAgICBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgb25jZSB0aGUgcHJvbWlzZSByZXR1cm5lZCBieSBhbgogICAgICBhZGFwdGVyJ3MgYGNyZWF0ZVJlY29yZGAsIGB1cGRhdGVSZWNvcmRgIG9yIGBkZWxldGVSZWNvcmRgCiAgICAgIGlzIHJlamVjdGVkIHdpdGggYSBgSW52YWxpZEVycm9yYC4KICAgICAgIEBtZXRob2QgcmVjb3JkV2FzSW52YWxpZAogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge0ludGVybmFsTW9kZWx9IGludGVybmFsTW9kZWwKICAgICAgQHBhcmFtIHtPYmplY3R9IGVycm9ycwogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVjb3JkV2FzSW52YWxpZCA9IGZ1bmN0aW9uIHJlY29yZFdhc0ludmFsaWQoaW50ZXJuYWxNb2RlbCwgcGFyc2VkRXJyb3JzLCBlcnJvcikgewoKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLlJFQ09SRF9EQVRBX0VSUk9SUykgewogICAgICAgIGludGVybmFsTW9kZWwuYWRhcHRlckRpZEludmFsaWRhdGUocGFyc2VkRXJyb3JzLCBlcnJvcik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbC5hZGFwdGVyRGlkSW52YWxpZGF0ZShwYXJzZWRFcnJvcnMpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAgVGhpcyBtZXRob2QgaXMgY2FsbGVkIG9uY2UgdGhlIHByb21pc2UgcmV0dXJuZWQgYnkgYW4KICAgICAgYWRhcHRlcidzIGBjcmVhdGVSZWNvcmRgLCBgdXBkYXRlUmVjb3JkYCBvciBgZGVsZXRlUmVjb3JkYAogICAgICBpcyByZWplY3RlZCAod2l0aCBhbnl0aGluZyBvdGhlciB0aGFuIGEgYEludmFsaWRFcnJvcmApLgogICAgICAgQG1ldGhvZCByZWNvcmRXYXNFcnJvcgogICAgICBAcHJpdmF0ZQogICAgICBAcGFyYW0ge0ludGVybmFsTW9kZWx9IGludGVybmFsTW9kZWwKICAgICAgQHBhcmFtIHtFcnJvcn0gZXJyb3IKICAgICovCiAgICA7CgogICAgX3Byb3RvLnJlY29yZFdhc0Vycm9yID0gZnVuY3Rpb24gcmVjb3JkV2FzRXJyb3IoaW50ZXJuYWxNb2RlbCwgZXJyb3IpIHsKCiAgICAgIGludGVybmFsTW9kZWwuYWRhcHRlckRpZEVycm9yKGVycm9yKTsKICAgIH0KICAgIC8qKgogICAgICBTZXRzIG5ld2x5IHJlY2VpdmVkIElEIGZyb20gdGhlIGFkYXB0ZXIncyBgY3JlYXRlUmVjb3JkYCwgYHVwZGF0ZVJlY29yZGAKICAgICAgb3IgYGRlbGV0ZVJlY29yZGAuCiAgICAgICBAbWV0aG9kIHNldFJlY29yZElkCiAgICAgIEBwcml2YXRlCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHBhcmFtIHtzdHJpbmd9IG5ld0lkCiAgICAgIEBwYXJhbSB7c3RyaW5nfSBjbGllbnRJZAogICAgICovCiAgICA7CgogICAgX3Byb3RvLnNldFJlY29yZElkID0gZnVuY3Rpb24gc2V0UmVjb3JkSWQobW9kZWxOYW1lLCBuZXdJZCwgY2xpZW50SWQpIHsKCiAgICAgIGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLnNldFJlY29yZElkKG1vZGVsTmFtZSwgbmV3SWQsIGNsaWVudElkKTsKICAgIH0gLy8gLi4uLi4uLi4uLi4uLi4uLgogICAgLy8gLiBMT0FESU5HIERBVEEgLgogICAgLy8gLi4uLi4uLi4uLi4uLi4uLgoKICAgIC8qKgogICAgICBUaGlzIGludGVybmFsIG1ldGhvZCBpcyB1c2VkIGJ5IGBwdXNoYC4KICAgICAgIEBtZXRob2QgX2xvYWQKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtPYmplY3R9IGRhdGEKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9sb2FkID0gZnVuY3Rpb24gX2xvYWQoZGF0YSkgewogICAgICB2YXIgcmVzb3VyY2UgPSBjb25zdHJ1Y3RSZXNvdXJjZShub3JtYWxpemVNb2RlbE5hbWUoZGF0YS50eXBlKSwgZW5zdXJlU3RyaW5nSWQoZGF0YS5pZCksIGNvZXJjZUlkKGRhdGEubGlkKSk7CiAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcykubG9va3VwKHJlc291cmNlLCBkYXRhKTsgLy8gc3RvcmUucHVzaCB3aWxsIGJlIGZyb20gZW1wdHkKICAgICAgLy8gZmluZFJlY29yZCB3aWxsIGJlIGZyb20gcm9vdC5sb2FkaW5nCiAgICAgIC8vIGFsbCBlbHNlIHdpbGwgYmUgdXBkYXRlcwoKICAgICAgdmFyIGlzTG9hZGluZyA9IGludGVybmFsTW9kZWwuY3VycmVudFN0YXRlLnN0YXRlTmFtZSA9PT0gJ3Jvb3QubG9hZGluZyc7CiAgICAgIHZhciBpc1VwZGF0ZSA9IGludGVybmFsTW9kZWwuY3VycmVudFN0YXRlLmlzRW1wdHkgPT09IGZhbHNlICYmICFpc0xvYWRpbmc7CgogICAgICB7CiAgICAgICAgLy8gZXhjbHVkZSBzdG9yZS5wdXNoIChyb290LmVtcHR5KSBjYXNlCiAgICAgICAgaWYgKGlzVXBkYXRlIHx8IGlzTG9hZGluZykgewogICAgICAgICAgdmFyIF9pZGVudGlmaWVyNCA9IGludGVybmFsTW9kZWwuaWRlbnRpZmllcjsKICAgICAgICAgIHZhciB1cGRhdGVkSWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzKS51cGRhdGVSZWNvcmRJZGVudGlmaWVyKF9pZGVudGlmaWVyNCwgZGF0YSk7CgogICAgICAgICAgaWYgKHVwZGF0ZWRJZGVudGlmaWVyICE9PSBfaWRlbnRpZmllcjQpIHsKICAgICAgICAgICAgLy8gd2UgZW5jb3VudGVyZWQgYSBtZXJnZSBvZiBpZGVudGlmaWVycyBpbiB3aGljaAogICAgICAgICAgICAvLyB0d28gaWRlbnRpZmllcnMgKGFuZCBsaWtlbHkgdHdvIGludGVybmFsTW9kZWxzKQogICAgICAgICAgICAvLyBleGlzdGVkIGZvciB0aGUgc2FtZSByZXNvdXJjZS4gTm93IHRoYXQgd2UgaGF2ZQogICAgICAgICAgICAvLyBkZXRlcm1pbmVkIHRoZSBjb3JyZWN0IGlkZW50aWZpZXIgdG8gdXNlLCBtYWtlIHN1cmUKICAgICAgICAgICAgLy8gdGhhdCB3ZSBhbHNvIHVzZSB0aGUgY29ycmVjdCBpbnRlcm5hbE1vZGVsLgogICAgICAgICAgICBfaWRlbnRpZmllcjQgPSB1cGRhdGVkSWRlbnRpZmllcjsKICAgICAgICAgICAgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLmxvb2t1cChfaWRlbnRpZmllcjQpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQoKICAgICAgaW50ZXJuYWxNb2RlbC5zZXR1cERhdGEoZGF0YSk7CgogICAgICBpZiAoaXNVcGRhdGUpIHsKICAgICAgICB0aGlzLnJlY29yZEFycmF5TWFuYWdlci5yZWNvcmREaWRDaGFuZ2UoaW50ZXJuYWxNb2RlbCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5yZWNvcmRBcnJheU1hbmFnZXIucmVjb3JkV2FzTG9hZGVkKGludGVybmFsTW9kZWwpOwogICAgICB9CgogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbDsKICAgIH0KICAgIC8qKgogICAgICBQdXNoIHNvbWUgZGF0YSBmb3IgYSBnaXZlbiB0eXBlIGludG8gdGhlIHN0b3JlLgogICAgICAgVGhpcyBtZXRob2QgZXhwZWN0cyBub3JtYWxpemVkIFtKU09OIEFQSV0oaHR0cDovL2pzb25hcGkub3JnLykgZG9jdW1lbnQuIFRoaXMgbWVhbnMgeW91IGhhdmUgdG8gZm9sbG93IFtKU09OIEFQSSBzcGVjaWZpY2F0aW9uXShodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0Lykgd2l0aCBmZXcgbWlub3IgYWRqdXN0bWVudHM6CiAgICAgIC0gcmVjb3JkJ3MgYHR5cGVgIHNob3VsZCBhbHdheXMgYmUgaW4gc2luZ3VsYXIsIGRhc2hlcml6ZWQgZm9ybQogICAgICAtIG1lbWJlcnMgKHByb3BlcnRpZXMpIHNob3VsZCBiZSBjYW1lbENhc2VkCiAgICAgICBbWW91ciBwcmltYXJ5IGRhdGEgc2hvdWxkIGJlIHdyYXBwZWQgaW5zaWRlIGBkYXRhYCBwcm9wZXJ0eV0oaHR0cDovL2pzb25hcGkub3JnL2Zvcm1hdC8jZG9jdW1lbnQtdG9wLWxldmVsKToKICAgICAgIGBgYGpzCiAgICAgIHN0b3JlLnB1c2goewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIC8vIHByaW1hcnkgZGF0YSBmb3Igc2luZ2xlIHJlY29yZCBvZiB0eXBlIGBQZXJzb25gCiAgICAgICAgICBpZDogJzEnLAogICAgICAgICAgdHlwZTogJ3BlcnNvbicsCiAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgIGZpcnN0TmFtZTogJ0RhbmllbCcsCiAgICAgICAgICAgIGxhc3ROYW1lOiAnS21haycKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFtEZW1vLl0oaHR0cDovL2VtYmVyLXR3aWRkbGUuY29tL2ZiOTlmMThjZDNiNGQzZTJhNGM3KQogICAgICAgYGRhdGFgIHByb3BlcnR5IGNhbiBhbHNvIGhvbGQgYW4gYXJyYXkgKG9mIHJlY29yZHMpOgogICAgICAgYGBganMKICAgICAgc3RvcmUucHVzaCh7CiAgICAgICAgZGF0YTogWwogICAgICAgICAgLy8gYW4gYXJyYXkgb2YgcmVjb3JkcwogICAgICAgICAgewogICAgICAgICAgICBpZDogJzEnLAogICAgICAgICAgICB0eXBlOiAncGVyc29uJywKICAgICAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgICAgIGZpcnN0TmFtZTogJ0RhbmllbCcsCiAgICAgICAgICAgICAgbGFzdE5hbWU6ICdLbWFrJwogICAgICAgICAgICB9CiAgICAgICAgICB9LAogICAgICAgICAgewogICAgICAgICAgICBpZDogJzInLAogICAgICAgICAgICB0eXBlOiAncGVyc29uJywKICAgICAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgICAgIGZpcnN0TmFtZTogJ1RvbScsCiAgICAgICAgICAgICAgbGFzdE5hbWU6ICdEYWxlJwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9KTsKICAgICAgYGBgCiAgICAgICBbRGVtby5dKGh0dHA6Ly9lbWJlci10d2lkZGxlLmNvbS82OWNkYmVhYTM3MDIxNTlkYzM1NSkKICAgICAgIFRoZXJlIGFyZSBzb21lIHR5cGljYWwgcHJvcGVydGllcyBmb3IgYEpTT05BUElgIHBheWxvYWQ6CiAgICAgICogYGlkYCAtIG1hbmRhdG9yeSwgdW5pcXVlIHJlY29yZCdzIGtleQogICAgICAqIGB0eXBlYCAtIG1hbmRhdG9yeSBzdHJpbmcgd2hpY2ggbWF0Y2hlcyBgbW9kZWxgJ3MgZGFzaGVyaXplZCBuYW1lIGluIHNpbmd1bGFyIGZvcm0KICAgICAgKiBgYXR0cmlidXRlc2AgLSBvYmplY3Qgd2hpY2ggaG9sZHMgZGF0YSBmb3IgcmVjb3JkIGF0dHJpYnV0ZXMgLSBgYXR0cmAncyBkZWNsYXJlZCBpbiBtb2RlbAogICAgICAqIGByZWxhdGlvbnNoaXBzYCAtIG9iamVjdCB3aGljaCBtdXN0IGNvbnRhaW4gYW55IG9mIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyB1bmRlciBlYWNoIHJlbGF0aW9uc2hpcHMnIHJlc3BlY3RpdmUga2V5IChleGFtcGxlIHBhdGggaXMgYHJlbGF0aW9uc2hpcHMuYWNoaWV2ZW1lbnRzLmRhdGFgKToKICAgICAgICAtIFtgbGlua3NgXShodHRwOi8vanNvbmFwaS5vcmcvZm9ybWF0LyNkb2N1bWVudC1saW5rcykKICAgICAgICAtIFtgZGF0YWBdKGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2RvY3VtZW50LXJlc291cmNlLW9iamVjdC1saW5rYWdlKSAtIHBsYWNlIGZvciBwcmltYXJ5IGRhdGEKICAgICAgICAtIFtgbWV0YWBdKGh0dHA6Ly9qc29uYXBpLm9yZy9mb3JtYXQvI2RvY3VtZW50LW1ldGEpIC0gb2JqZWN0IHdoaWNoIGNvbnRhaW5zIG1ldGEtaW5mb3JtYXRpb24gYWJvdXQgcmVsYXRpb25zaGlwCiAgICAgICBGb3IgdGhpcyBtb2RlbDoKICAgICAgIGBgYGFwcC9tb2RlbHMvcGVyc29uLmpzCiAgICAgIGltcG9ydCBNb2RlbCwgeyBhdHRyLCBoYXNNYW55IH0gZnJvbSAnQGVtYmVyLWRhdGEvbW9kZWwnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgTW9kZWwuZXh0ZW5kKHsKICAgICAgICBmaXJzdE5hbWU6IGF0dHIoJ3N0cmluZycpLAogICAgICAgIGxhc3ROYW1lOiBhdHRyKCdzdHJpbmcnKSwKICAgICAgICAgY2hpbGRyZW46IGhhc01hbnkoJ3BlcnNvbicpCiAgICAgIH0pOwogICAgICBgYGAKICAgICAgIFRvIHJlcHJlc2VudCB0aGUgY2hpbGRyZW4gYXMgSURzOgogICAgICAgYGBganMKICAgICAgewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIGlkOiAnMScsCiAgICAgICAgICB0eXBlOiAncGVyc29uJywKICAgICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgICAgZmlyc3ROYW1lOiAnVG9tJywKICAgICAgICAgICAgbGFzdE5hbWU6ICdEYWxlJwogICAgICAgICAgfSwKICAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICAgY2hpbGRyZW46IHsKICAgICAgICAgICAgICBkYXRhOiBbCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgIGlkOiAnMicsCiAgICAgICAgICAgICAgICAgIHR5cGU6ICdwZXJzb24nCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICBpZDogJzMnLAogICAgICAgICAgICAgICAgICB0eXBlOiAncGVyc29uJwogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgaWQ6ICc0JywKICAgICAgICAgICAgICAgICAgdHlwZTogJ3BlcnNvbicKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBdCiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBbRGVtby5dKGh0dHA6Ly9lbWJlci10d2lkZGxlLmNvbS8zNDNlMTczNWUwMzQwOTFmNWJkZSkKICAgICAgIFRvIHJlcHJlc2VudCB0aGUgY2hpbGRyZW4gcmVsYXRpb25zaGlwIGFzIGEgVVJMOgogICAgICAgYGBganMKICAgICAgewogICAgICAgIGRhdGE6IHsKICAgICAgICAgIGlkOiAnMScsCiAgICAgICAgICB0eXBlOiAncGVyc29uJywKICAgICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgICAgZmlyc3ROYW1lOiAnVG9tJywKICAgICAgICAgICAgbGFzdE5hbWU6ICdEYWxlJwogICAgICAgICAgfSwKICAgICAgICAgIHJlbGF0aW9uc2hpcHM6IHsKICAgICAgICAgICAgY2hpbGRyZW46IHsKICAgICAgICAgICAgICBsaW5rczogewogICAgICAgICAgICAgICAgcmVsYXRlZDogJy9wZW9wbGUvMS9jaGlsZHJlbicKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgYGBgCiAgICAgICBJZiB5b3UncmUgc3RyZWFtaW5nIGRhdGEgb3IgaW1wbGVtZW50aW5nIGFuIGFkYXB0ZXIsIG1ha2Ugc3VyZQogICAgICB0aGF0IHlvdSBoYXZlIGNvbnZlcnRlZCB0aGUgaW5jb21pbmcgZGF0YSBpbnRvIHRoaXMgZm9ybS4gVGhlCiAgICAgIHN0b3JlJ3MgW25vcm1hbGl6ZV0oU3RvcmUvbWV0aG9kcy9ub3JtYWxpemU/YW5jaG9yPW5vcm1hbGl6ZSkgbWV0aG9kIGlzIGEgY29udmVuaWVuY2UKICAgICAgaGVscGVyIGZvciBjb252ZXJ0aW5nIGEganNvbiBwYXlsb2FkIGludG8gdGhlIGZvcm0gRW1iZXIgRGF0YQogICAgICBleHBlY3RzLgogICAgICAgYGBganMKICAgICAgc3RvcmUucHVzaChzdG9yZS5ub3JtYWxpemUoJ3BlcnNvbicsIGRhdGEpKTsKICAgICAgYGBgCiAgICAgICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCBib3RoIHRvIHB1c2ggaW4gYnJhbmQgbmV3CiAgICAgIHJlY29yZHMsIGFzIHdlbGwgYXMgdG8gdXBkYXRlIGV4aXN0aW5nIHJlY29yZHMuCiAgICAgICBAbWV0aG9kIHB1c2gKICAgICAgQHBhcmFtIHtPYmplY3R9IGRhdGEKICAgICAgQHJldHVybiB0aGUgcmVjb3JkKHMpIHRoYXQgd2FzIGNyZWF0ZWQgb3IKICAgICAgICB1cGRhdGVkLgogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucHVzaCA9IGZ1bmN0aW9uIHB1c2goZGF0YSkgewoKICAgICAgdmFyIHB1c2hlZCA9IHRoaXMuX3B1c2goZGF0YSk7CgogICAgICBpZiAoQXJyYXkuaXNBcnJheShwdXNoZWQpKSB7CiAgICAgICAgdmFyIHJlY29yZHMgPSBwdXNoZWQubWFwKGZ1bmN0aW9uIChpbnRlcm5hbE1vZGVsKSB7CiAgICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5nZXRSZWNvcmQoKTsKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gcmVjb3JkczsKICAgICAgfQoKICAgICAgaWYgKHB1c2hlZCA9PT0gbnVsbCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CgogICAgICB2YXIgcmVjb3JkID0gcHVzaGVkLmdldFJlY29yZCgpOwogICAgICByZXR1cm4gcmVjb3JkOwogICAgfQogICAgLyoKICAgICAgUHVzaCBzb21lIGRhdGEgaW4gdGhlIGZvcm0gb2YgYSBqc29uLWFwaSBkb2N1bWVudCBpbnRvIHRoZSBzdG9yZSwKICAgICAgd2l0aG91dCBjcmVhdGluZyBtYXRlcmlhbGl6ZWQgcmVjb3Jkcy4KICAgICAgIEBtZXRob2QgX3B1c2gKICAgICAgQHByaXZhdGUKICAgICAgQHBhcmFtIHtPYmplY3R9IGpzb25BcGlEb2MKICAgICAgQHJldHVybiB7SW50ZXJuYWxNb2RlbHxBcnJheTxJbnRlcm5hbE1vZGVsPn0gcHVzaGVkIEludGVybmFsTW9kZWwocykKICAgICovCiAgICA7CgogICAgX3Byb3RvLl9wdXNoID0gZnVuY3Rpb24gX3B1c2goanNvbkFwaURvYykgewogICAgICB2YXIgX3RoaXM3ID0gdGhpczsKCiAgICAgIHZhciBpbnRlcm5hbE1vZGVsT3JNb2RlbHMgPSB0aGlzLl9iYWNrYnVybmVyLmpvaW4oZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBpbmNsdWRlZCA9IGpzb25BcGlEb2MuaW5jbHVkZWQ7CiAgICAgICAgdmFyIGksIGxlbmd0aDsKCiAgICAgICAgaWYgKGluY2x1ZGVkKSB7CiAgICAgICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBpbmNsdWRlZC5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICBfdGhpczcuX3B1c2hJbnRlcm5hbE1vZGVsKGluY2x1ZGVkW2ldKTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGlmIChBcnJheS5pc0FycmF5KGpzb25BcGlEb2MuZGF0YSkpIHsKICAgICAgICAgIGxlbmd0aCA9IGpzb25BcGlEb2MuZGF0YS5sZW5ndGg7CiAgICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbHMgPSBuZXcgQXJyYXkobGVuZ3RoKTsKCiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgaW50ZXJuYWxNb2RlbHNbaV0gPSBfdGhpczcuX3B1c2hJbnRlcm5hbE1vZGVsKGpzb25BcGlEb2MuZGF0YVtpXSk7CiAgICAgICAgICB9CgogICAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWxzOwogICAgICAgIH0KCiAgICAgICAgaWYgKGpzb25BcGlEb2MuZGF0YSA9PT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIHJldHVybiBfdGhpczcuX3B1c2hJbnRlcm5hbE1vZGVsKGpzb25BcGlEb2MuZGF0YSk7CiAgICAgIH0pOyAvLyB0aGlzIHR5cGVjYXN0IGlzIG5lY2Vzc2FyeSBiZWNhdXNlIGBiYWNrYnVybmVyLmpvaW5gIGlzIG1pc3R5cGVkIHRvIHJldHVybiB2b2lkCgoKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWxPck1vZGVsczsKICAgIH07CgogICAgX3Byb3RvLl9wdXNoSW50ZXJuYWxNb2RlbCA9IGZ1bmN0aW9uIF9wdXNoSW50ZXJuYWxNb2RlbChkYXRhKSB7CiAgICAgIHZhciBtb2RlbE5hbWUgPSBkYXRhLnR5cGU7CgoKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSB0aGlzLl9sb2FkKGRhdGEpOyAvLyAgICB0aGlzLl9zZXR1cFJlbGF0aW9uc2hpcHNGb3JNb2RlbChpbnRlcm5hbE1vZGVsLCBkYXRhKTsKCgogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbDsKICAgIH0KICAgIC8qKgogICAgICBQdXNoIHNvbWUgcmF3IGRhdGEgaW50byB0aGUgc3RvcmUuCiAgICAgICBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCBib3RoIHRvIHB1c2ggaW4gYnJhbmQgbmV3CiAgICAgIHJlY29yZHMsIGFzIHdlbGwgYXMgdG8gdXBkYXRlIGV4aXN0aW5nIHJlY29yZHMuIFlvdQogICAgICBjYW4gcHVzaCBpbiBtb3JlIHRoYW4gb25lIHR5cGUgb2Ygb2JqZWN0IGF0IG9uY2UuCiAgICAgIEFsbCBvYmplY3RzIHNob3VsZCBiZSBpbiB0aGUgZm9ybWF0IGV4cGVjdGVkIGJ5IHRoZQogICAgICBzZXJpYWxpemVyLgogICAgICAgYGBgYXBwL3NlcmlhbGl6ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICAgIGltcG9ydCBSRVNUU2VyaWFsaXplciBmcm9tICdAZW1iZXItZGF0YS9zZXJpYWxpemVyL3Jlc3QnOwogICAgICAgZXhwb3J0IGRlZmF1bHQgUkVTVFNlcmlhbGl6ZXI7CiAgICAgIGBgYAogICAgICAgYGBganMKICAgICAgbGV0IHB1c2hEYXRhID0gewogICAgICAgIHBvc3RzOiBbCiAgICAgICAgICB7IGlkOiAxLCBwb3N0VGl0bGU6ICJHcmVhdCBwb3N0IiwgY29tbWVudElkczogWzJdIH0KICAgICAgICBdLAogICAgICAgIGNvbW1lbnRzOiBbCiAgICAgICAgICB7IGlkOiAyLCBjb21tZW50Qm9keTogIkluc2lnaHRmdWwgY29tbWVudCIgfQogICAgICAgIF0KICAgICAgfQogICAgICAgc3RvcmUucHVzaFBheWxvYWQocHVzaERhdGEpOwogICAgICBgYGAKICAgICAgIEJ5IGRlZmF1bHQsIHRoZSBkYXRhIHdpbGwgYmUgZGVzZXJpYWxpemVkIHVzaW5nIGEgZGVmYXVsdAogICAgICBzZXJpYWxpemVyICh0aGUgYXBwbGljYXRpb24gc2VyaWFsaXplciBpZiBpdCBleGlzdHMpLgogICAgICAgQWx0ZXJuYXRpdmVseSwgYHB1c2hQYXlsb2FkYCB3aWxsIGFjY2VwdCBhIG1vZGVsIHR5cGUgd2hpY2gKICAgICAgd2lsbCBkZXRlcm1pbmUgd2hpY2ggc2VyaWFsaXplciB3aWxsIHByb2Nlc3MgdGhlIHBheWxvYWQuCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvYXBwbGljYXRpb24uanMKICAgICAgaW1wb3J0IFJFU1RTZXJpYWxpemVyIGZyb20gJ0BlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCc7CiAgICAgICBleHBvcnQgZGVmYXVsdCBSRVNUU2VyaWFsaXplcjsKICAgICAgYGBgCiAgICAgICBgYGBhcHAvc2VyaWFsaXplcnMvcG9zdC5qcwogICAgICBpbXBvcnQgSlNPTlNlcmlhbGl6ZXIgZnJvbSAnQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uJzsKICAgICAgIGV4cG9ydCBkZWZhdWx0IEpTT05TZXJpYWxpemVyOwogICAgICBgYGAKICAgICAgIGBgYGpzCiAgICAgIHN0b3JlLnB1c2hQYXlsb2FkKHB1c2hEYXRhKTsgLy8gV2lsbCB1c2UgdGhlIGFwcGxpY2F0aW9uIHNlcmlhbGl6ZXIKICAgICAgc3RvcmUucHVzaFBheWxvYWQoJ3Bvc3QnLCBwdXNoRGF0YSk7IC8vIFdpbGwgdXNlIHRoZSBwb3N0IHNlcmlhbGl6ZXIKICAgICAgYGBgCiAgICAgICBAbWV0aG9kIHB1c2hQYXlsb2FkCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUgT3B0aW9uYWxseSwgYSBtb2RlbCB0eXBlIHVzZWQgdG8gZGV0ZXJtaW5lIHdoaWNoIHNlcmlhbGl6ZXIgd2lsbCBiZSB1c2VkCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBpbnB1dFBheWxvYWQKICAgICovCiAgICA7CgogICAgX3Byb3RvLnB1c2hQYXlsb2FkID0gZnVuY3Rpb24gcHVzaFBheWxvYWQobW9kZWxOYW1lLCBpbnB1dFBheWxvYWQpIHsKCiAgICAgIHZhciBzZXJpYWxpemVyOwogICAgICB2YXIgcGF5bG9hZDsKCiAgICAgIGlmICghaW5wdXRQYXlsb2FkKSB7CiAgICAgICAgcGF5bG9hZCA9IG1vZGVsTmFtZTsKICAgICAgICBzZXJpYWxpemVyID0gdGhpcy5zZXJpYWxpemVyRm9yKCdhcHBsaWNhdGlvbicpOwogICAgICB9IGVsc2UgewogICAgICAgIHBheWxvYWQgPSBpbnB1dFBheWxvYWQ7CiAgICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgICBzZXJpYWxpemVyID0gdGhpcy5zZXJpYWxpemVyRm9yKG5vcm1hbGl6ZWRNb2RlbE5hbWUpOwogICAgICB9CiAgICAgIHNlcmlhbGl6ZXIucHVzaFBheWxvYWQodGhpcywgcGF5bG9hZCk7CiAgICB9OwoKICAgIF9wcm90by5yZWxvYWRNYW55QXJyYXkgPSBmdW5jdGlvbiByZWxvYWRNYW55QXJyYXkobWFueUFycmF5LCBpbnRlcm5hbE1vZGVsLCBrZXksIG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwucmVsb2FkSGFzTWFueShrZXksIG9wdGlvbnMpOwogICAgfTsKCiAgICBfcHJvdG8ucmVsb2FkQmVsb25nc1RvID0gZnVuY3Rpb24gcmVsb2FkQmVsb25nc1RvKGJlbG9uZ3NUb1Byb3h5LCBpbnRlcm5hbE1vZGVsLCBrZXksIG9wdGlvbnMpIHsKICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwucmVsb2FkQmVsb25nc1RvKGtleSwgb3B0aW9ucyk7CiAgICB9OwoKICAgIF9wcm90by5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlID0gZnVuY3Rpb24gX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShyZXNvdXJjZSkgewogICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbEZhY3RvcnlGb3IodGhpcykuZ2V0QnlSZXNvdXJjZShyZXNvdXJjZSk7CiAgICB9CiAgICAvKioKICAgICAqIFRPRE8gT25seSBuZWVkZWQgdGVtcG9yYXJpbHkgZm9yIHRlc3Qgc3VwcG9ydAogICAgICoKICAgICAqIEBpbnRlcm5hbAogICAgICovCiAgICA7CgogICAgX3Byb3RvLl9pbnRlcm5hbE1vZGVsRm9ySWQgPSBmdW5jdGlvbiBfaW50ZXJuYWxNb2RlbEZvcklkKHR5cGUsIGlkLCBsaWQpIHsKICAgICAgdmFyIHJlc291cmNlID0gY29uc3RydWN0UmVzb3VyY2UodHlwZSwgaWQsIGxpZCk7CiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5sb29rdXAocmVzb3VyY2UpOwogICAgfTsKCiAgICBfcHJvdG8uc2VyaWFsaXplUmVjb3JkID0gZnVuY3Rpb24gc2VyaWFsaXplUmVjb3JkKHJlY29yZCwgb3B0aW9ucykgewogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgdmFyIF9pZGVudGlmaWVyNSA9IHJlY29yZElkZW50aWZpZXJGb3IocmVjb3JkKTsKCiAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5wZWVrKF9pZGVudGlmaWVyNSk7IC8vIFRPRE8gd2UgdXNlZCB0byBjaGVjayBpZiB0aGUgcmVjb3JkIHdhcyBkZXN0cm95ZWQgaGVyZQoKICAgICAgICByZXR1cm4gaW50ZXJuYWxNb2RlbC5jcmVhdGVTbmFwc2hvdChvcHRpb25zKS5zZXJpYWxpemUob3B0aW9ucyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdzZXJpYWxpemVSZWNvcmQgaXMgb25seSBhdmFpbGFibGUgd2hlbiBDVVNUT01fTU9ERUxfQ0xBU1MgZmYgaXMgb24nKTsKICAgICAgfQogICAgfTsKCiAgICBfcHJvdG8uc2F2ZVJlY29yZCA9IGZ1bmN0aW9uIHNhdmVSZWNvcmQocmVjb3JkLCBvcHRpb25zKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICB2YXIgX2lkZW50aWZpZXI2ID0gcmVjb3JkSWRlbnRpZmllckZvcihyZWNvcmQpOwoKICAgICAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLnBlZWsoX2lkZW50aWZpZXI2KTsgLy8gVE9ETyB3ZSB1c2VkIHRvIGNoZWNrIGlmIHRoZSByZWNvcmQgd2FzIGRlc3Ryb3llZCBoZXJlCiAgICAgICAgLy8gQ2FzdGluZyBjYW4gYmUgcmVtb3ZlZCBvbmNlIFJFUVVFU1RfU0VSVklDRSBmZiBpcyB0dXJuZWQgb24KICAgICAgICAvLyBiZWNhdXNlIGEgYFJlY29yZGAgaXMgcHJvdmlkZWQgdGhlcmUgd2lsbCBhbHdheXMgYmUgYSBtYXRjaGluZyBpbnRlcm5hbE1vZGVsCgogICAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsLnNhdmUob3B0aW9ucykudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gcmVjb3JkOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcignc2F2ZVJlY29yZCBpcyBvbmx5IGF2YWlsYWJsZSB3aGVuIENVU1RPTV9NT0RFTF9DTEFTUyBmZiBpcyBvbicpOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5yZWxhdGlvbnNoaXBSZWZlcmVuY2VGb3IgPSBmdW5jdGlvbiByZWxhdGlvbnNoaXBSZWZlcmVuY2VGb3IoaWRlbnRpZmllciwga2V5KSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICB2YXIgc3RhYmxlSWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIoaWRlbnRpZmllcik7CiAgICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5wZWVrKHN0YWJsZUlkZW50aWZpZXIpOyAvLyBUT0RPIHdlIHVzZWQgdG8gY2hlY2sgaWYgdGhlIHJlY29yZCB3YXMgZGVzdHJveWVkIGhlcmUKCiAgICAgICAgcmV0dXJuIGludGVybmFsTW9kZWwucmVmZXJlbmNlRm9yKG51bGwsIGtleSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZWxhdGlvbnNoaXBSZWZlcmVuY2VGb3IgaXMgb25seSBhdmFpbGFibGUgd2hlbiBDVVNUT01fTU9ERUxfQ0xBU1MgZmYgaXMgb24nKTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiBAaW50ZXJuYWwKICAgICAqLwogICAgOwoKICAgIF9wcm90by5fY3JlYXRlUmVjb3JkRGF0YSA9IGZ1bmN0aW9uIF9jcmVhdGVSZWNvcmREYXRhKGlkZW50aWZpZXIpIHsKICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlUmVjb3JkRGF0YUZvcihpZGVudGlmaWVyLnR5cGUsIGlkZW50aWZpZXIuaWQsIGlkZW50aWZpZXIubGlkLCB0aGlzLl9zdG9yZVdyYXBwZXIpOwogICAgfQogICAgLyoqCiAgICAgKiBJbnN0YW50aWF0aW9uIGhvb2sgYWxsb3dpbmcgYXBwbGljYXRpb25zIG9yIGFkZG9ucyB0byBjb25maWd1cmUgdGhlIHN0b3JlCiAgICAgKiB0byB1dGlsaXplIGEgY3VzdG9tIFJlY29yZERhdGEgaW1wbGVtZW50YXRpb24uCiAgICAgKgogICAgICogQHBhcmFtIG1vZGVsTmFtZQogICAgICogQHBhcmFtIGlkCiAgICAgKiBAcGFyYW0gY2xpZW50SWQKICAgICAqIEBwYXJhbSBzdG9yZVdyYXBwZXIKICAgICAqLwogICAgOwoKICAgIF9wcm90by5jcmVhdGVSZWNvcmREYXRhRm9yID0gZnVuY3Rpb24gY3JlYXRlUmVjb3JkRGF0YUZvcihtb2RlbE5hbWUsIGlkLCBjbGllbnRJZCwgc3RvcmVXcmFwcGVyKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiRXhwZWN0ZWQgc3RvcmUuY3JlYXRlUmVjb3JkRGF0YUZvciB0byBiZSBpbXBsZW1lbnRlZCBidXQgaXQgd2Fzbid0Iik7CiAgICB9CiAgICAvKioKICAgICAqIEBpbnRlcm5hbAogICAgICovCiAgICA7CgogICAgX3Byb3RvLl9fcmVjb3JkRGF0YUZvciA9IGZ1bmN0aW9uIF9fcmVjb3JkRGF0YUZvcihyZXNvdXJjZSkgewogICAgICB2YXIgaWRlbnRpZmllciA9IGlkZW50aWZpZXJDYWNoZUZvcih0aGlzKS5nZXRPckNyZWF0ZVJlY29yZElkZW50aWZpZXIocmVzb3VyY2UpOwogICAgICByZXR1cm4gdGhpcy5yZWNvcmREYXRhRm9yKGlkZW50aWZpZXIsIGZhbHNlKTsKICAgIH0KICAgIC8qKgogICAgICogQGludGVybmFsCiAgICAgKi8KICAgIDsKCiAgICBfcHJvdG8ucmVjb3JkRGF0YUZvciA9IGZ1bmN0aW9uIHJlY29yZERhdGFGb3IkMShpZGVudGlmaWVyLCBpc0NyZWF0ZSkgewogICAgICB2YXIgaW50ZXJuYWxNb2RlbDsKCiAgICAgIGlmIChpc0NyZWF0ZSA9PT0gdHJ1ZSkgewogICAgICAgIGludGVybmFsTW9kZWwgPSBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5idWlsZCh7CiAgICAgICAgICB0eXBlOiBpZGVudGlmaWVyLnR5cGUsCiAgICAgICAgICBpZDogbnVsbAogICAgICAgIH0pOwogICAgICAgIGludGVybmFsTW9kZWwubG9hZGVkRGF0YSgpOwogICAgICAgIGludGVybmFsTW9kZWwuZGlkQ3JlYXRlUmVjb3JkKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaW50ZXJuYWxNb2RlbCA9IGludGVybmFsTW9kZWxGYWN0b3J5Rm9yKHRoaXMpLmxvb2t1cChpZGVudGlmaWVyKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlY29yZERhdGFGb3IoaW50ZXJuYWxNb2RlbCk7CiAgICB9CiAgICAvKioKICAgICAgYG5vcm1hbGl6ZWAgY29udmVydHMgYSBqc29uIHBheWxvYWQgaW50byB0aGUgbm9ybWFsaXplZCBmb3JtIHRoYXQKICAgICAgW3B1c2hdKFN0b3JlL21ldGhvZHMvcHVzaD9hbmNob3I9cHVzaCkgZXhwZWN0cy4KICAgICAgIEV4YW1wbGUKICAgICAgIGBgYGpzCiAgICAgIHNvY2tldC5vbignbWVzc2FnZScsIGZ1bmN0aW9uKG1lc3NhZ2UpIHsKICAgICAgICBsZXQgbW9kZWxOYW1lID0gbWVzc2FnZS5tb2RlbDsKICAgICAgICBsZXQgZGF0YSA9IG1lc3NhZ2UuZGF0YTsKICAgICAgICBzdG9yZS5wdXNoKHN0b3JlLm5vcm1hbGl6ZShtb2RlbE5hbWUsIGRhdGEpKTsKICAgICAgfSk7CiAgICAgIGBgYAogICAgICAgQG1ldGhvZCBub3JtYWxpemUKICAgICAgQHBhcmFtIHtTdHJpbmd9IG1vZGVsTmFtZSBUaGUgbmFtZSBvZiB0aGUgbW9kZWwgdHlwZSBmb3IgdGhpcyBwYXlsb2FkCiAgICAgIEBwYXJhbSB7T2JqZWN0fSBwYXlsb2FkCiAgICAgIEByZXR1cm4ge09iamVjdH0gVGhlIG5vcm1hbGl6ZWQgcGF5bG9hZAogICAgKi8KICAgIDsKCiAgICBfcHJvdG8ubm9ybWFsaXplID0gZnVuY3Rpb24gbm9ybWFsaXplKG1vZGVsTmFtZSwgcGF5bG9hZCkgewogICAgICB2YXIgbm9ybWFsaXplZE1vZGVsTmFtZSA9IG5vcm1hbGl6ZU1vZGVsTmFtZShtb2RlbE5hbWUpOwogICAgICB2YXIgc2VyaWFsaXplciA9IHRoaXMuc2VyaWFsaXplckZvcihub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgdmFyIG1vZGVsID0gdGhpcy5tb2RlbEZvcihub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIHNlcmlhbGl6ZXIubm9ybWFsaXplKG1vZGVsLCBwYXlsb2FkKTsKICAgIH07CgogICAgX3Byb3RvLm5ld0NsaWVudElkID0gZnVuY3Rpb24gbmV3Q2xpZW50SWQoKSB7CiAgICAgIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlByaXZhdGUgQVBJIFJlbW92ZWQiKTsKICAgICAgfQogICAgfSAvL0NhbGxlZCBieSB0aGUgc3RhdGUgbWFjaGluZSB0byBub3RpZnkgdGhlIHN0b3JlIHRoYXQgdGhlIHJlY29yZCBpcyByZWFkeSB0byBiZSBpbnRlcmFjdGVkIHdpdGgKICAgIDsKCiAgICBfcHJvdG8ucmVjb3JkV2FzTG9hZGVkID0gZnVuY3Rpb24gcmVjb3JkV2FzTG9hZGVkKHJlY29yZCkgewoKICAgICAgdGhpcy5yZWNvcmRBcnJheU1hbmFnZXIucmVjb3JkV2FzTG9hZGVkKHJlY29yZCk7CiAgICB9IC8vIC4uLi4uLi4uLi4uLi4uLgogICAgLy8gLiBERVNUUlVDVElPTiAuCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4KCiAgICAvKioKICAgICAqIFRPRE8gcmVtb3ZlIHRlc3QgdXNhZ2UKICAgICAqCiAgICAgKiBAaW50ZXJuYWwKICAgICAqLwogICAgOwoKICAgIF9wcm90by5faW50ZXJuYWxNb2RlbHNGb3IgPSBmdW5jdGlvbiBfaW50ZXJuYWxNb2RlbHNGb3IobW9kZWxOYW1lKSB7CiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsRmFjdG9yeUZvcih0aGlzKS5tb2RlbE1hcEZvcihtb2RlbE5hbWUpOwogICAgfSAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uCiAgICAvLyAuIFBFUi1UWVBFIEFEQVBURVJTCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uCgogICAgLyoqCiAgICAgIFJldHVybnMgYW4gaW5zdGFuY2Ugb2YgdGhlIGFkYXB0ZXIgZm9yIGEgZ2l2ZW4gdHlwZS4gRm9yCiAgICAgIGV4YW1wbGUsIGBhZGFwdGVyRm9yKCdwZXJzb24nKWAgd2lsbCByZXR1cm4gYW4gaW5zdGFuY2Ugb2YKICAgICAgYEFwcC5QZXJzb25BZGFwdGVyYC4KICAgICAgIElmIG5vIGBBcHAuUGVyc29uQWRhcHRlcmAgaXMgZm91bmQsIHRoaXMgbWV0aG9kIHdpbGwgbG9vawogICAgICBmb3IgYW4gYEFwcC5BcHBsaWNhdGlvbkFkYXB0ZXJgICh0aGUgZGVmYXVsdCBhZGFwdGVyIGZvcgogICAgICB5b3VyIGVudGlyZSBhcHBsaWNhdGlvbikuCiAgICAgICBJZiBubyBgQXBwLkFwcGxpY2F0aW9uQWRhcHRlcmAgaXMgZm91bmQsIGl0IHdpbGwgcmV0dXJuCiAgICAgIHRoZSB2YWx1ZSBvZiB0aGUgYGRlZmF1bHRBZGFwdGVyYC4KICAgICAgIEBtZXRob2QgYWRhcHRlckZvcgogICAgICBAcHVibGljCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgICAgQHJldHVybiBBZGFwdGVyCiAgICAqLwogICAgOwoKICAgIF9wcm90by5hZGFwdGVyRm9yID0gZnVuY3Rpb24gYWRhcHRlckZvcihtb2RlbE5hbWUpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgdmFyIF9hZGFwdGVyQ2FjaGUgPSB0aGlzLl9hZGFwdGVyQ2FjaGU7CiAgICAgIHZhciBhZGFwdGVyID0gX2FkYXB0ZXJDYWNoZVtub3JtYWxpemVkTW9kZWxOYW1lXTsKCiAgICAgIGlmIChhZGFwdGVyKSB7CiAgICAgICAgcmV0dXJuIGFkYXB0ZXI7CiAgICAgIH0KCiAgICAgIHZhciBvd25lciA9IEVtYmVyLmdldE93bmVyKHRoaXMpOwogICAgICBhZGFwdGVyID0gb3duZXIubG9va3VwKCJhZGFwdGVyOiIgKyBub3JtYWxpemVkTW9kZWxOYW1lKTsgLy8gaW4gcHJvZHVjdGlvbiB0aGlzIGlzIGhhbmRsZWQgYnkgdGhlIHJlLWV4cG9ydAoKICAgICAgaWYgKGFkYXB0ZXIgIT09IHVuZGVmaW5lZCkgewogICAgICAgIEVtYmVyLnNldChhZGFwdGVyLCAnc3RvcmUnLCB0aGlzKTsKICAgICAgICBfYWRhcHRlckNhY2hlW25vcm1hbGl6ZWRNb2RlbE5hbWVdID0gYWRhcHRlcjsKICAgICAgICByZXR1cm4gYWRhcHRlcjsKICAgICAgfSAvLyBubyBhZGFwdGVyIGZvdW5kIGZvciB0aGUgc3BlY2lmaWMgbW9kZWwsIGZhbGxiYWNrIGFuZCBjaGVjayBmb3IgYXBwbGljYXRpb24gYWRhcHRlcgoKCiAgICAgIGFkYXB0ZXIgPSBfYWRhcHRlckNhY2hlLmFwcGxpY2F0aW9uIHx8IG93bmVyLmxvb2t1cCgnYWRhcHRlcjphcHBsaWNhdGlvbicpOwoKICAgICAgaWYgKGFkYXB0ZXIgIT09IHVuZGVmaW5lZCkgewogICAgICAgIEVtYmVyLnNldChhZGFwdGVyLCAnc3RvcmUnLCB0aGlzKTsKICAgICAgICBfYWRhcHRlckNhY2hlW25vcm1hbGl6ZWRNb2RlbE5hbWVdID0gYWRhcHRlcjsKICAgICAgICBfYWRhcHRlckNhY2hlLmFwcGxpY2F0aW9uID0gYWRhcHRlcjsKICAgICAgICByZXR1cm4gYWRhcHRlcjsKICAgICAgfSAvLyBubyBtb2RlbCBzcGVjaWZpYyBhZGFwdGVyIG9yIGFwcGxpY2F0aW9uIGFkYXB0ZXIsIGNoZWNrIGZvciBhbiBgYWRhcHRlcmAKICAgICAgLy8gcHJvcGVydHkgZGVmaW5lZCBvbiB0aGUgc3RvcmUKCgogICAgICB2YXIgYWRhcHRlck5hbWUgPSB0aGlzLmFkYXB0ZXIgfHwgJy1qc29uLWFwaSc7CiAgICAgIGFkYXB0ZXIgPSBhZGFwdGVyTmFtZSA/IF9hZGFwdGVyQ2FjaGVbYWRhcHRlck5hbWVdIHx8IG93bmVyLmxvb2t1cCgiYWRhcHRlcjoiICsgYWRhcHRlck5hbWUpIDogdW5kZWZpbmVkOyAvLyBpbiBwcm9kdWN0aW9uIHRoaXMgaXMgaGFuZGxlZCBieSB0aGUgcmUtZXhwb3J0CgogICAgICBpZiAoYWRhcHRlciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgRW1iZXIuc2V0KGFkYXB0ZXIsICdzdG9yZScsIHRoaXMpOwogICAgICAgIF9hZGFwdGVyQ2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV0gPSBhZGFwdGVyOwogICAgICAgIF9hZGFwdGVyQ2FjaGVbYWRhcHRlck5hbWVdID0gYWRhcHRlcjsKICAgICAgICByZXR1cm4gYWRhcHRlcjsKICAgICAgfSAvLyBmaW5hbCBmYWxsYmFjaywgbm8gbW9kZWwgc3BlY2lmaWMgYWRhcHRlciwgbm8gYXBwbGljYXRpb24gYWRhcHRlciwgbm8KICAgICAgLy8gYGFkYXB0ZXJgIHByb3BlcnR5IG9uIHN0b3JlOiB1c2UganNvbi1hcGkgYWRhcHRlcgoKCiAgICAgIGFkYXB0ZXIgPSBfYWRhcHRlckNhY2hlWyctanNvbi1hcGknXSB8fCBvd25lci5sb29rdXAoJ2FkYXB0ZXI6LWpzb24tYXBpJyk7CiAgICAgIEVtYmVyLnNldChhZGFwdGVyLCAnc3RvcmUnLCB0aGlzKTsKICAgICAgX2FkYXB0ZXJDYWNoZVtub3JtYWxpemVkTW9kZWxOYW1lXSA9IGFkYXB0ZXI7CiAgICAgIF9hZGFwdGVyQ2FjaGVbJy1qc29uLWFwaSddID0gYWRhcHRlcjsKICAgICAgcmV0dXJuIGFkYXB0ZXI7CiAgICB9IC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgogICAgLy8gLiBSRUNPUkQgQ0hBTkdFIE5PVElGSUNBVElPTiAuCiAgICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4KCiAgICAvKioKICAgICAgUmV0dXJucyBhbiBpbnN0YW5jZSBvZiB0aGUgc2VyaWFsaXplciBmb3IgYSBnaXZlbiB0eXBlLiBGb3IKICAgICAgZXhhbXBsZSwgYHNlcmlhbGl6ZXJGb3IoJ3BlcnNvbicpYCB3aWxsIHJldHVybiBhbiBpbnN0YW5jZSBvZgogICAgICBgQXBwLlBlcnNvblNlcmlhbGl6ZXJgLgogICAgICAgSWYgbm8gYEFwcC5QZXJzb25TZXJpYWxpemVyYCBpcyBmb3VuZCwgdGhpcyBtZXRob2Qgd2lsbCBsb29rCiAgICAgIGZvciBhbiBgQXBwLkFwcGxpY2F0aW9uU2VyaWFsaXplcmAgKHRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgZm9yCiAgICAgIHlvdXIgZW50aXJlIGFwcGxpY2F0aW9uKS4KICAgICAgIGlmIG5vIGBBcHAuQXBwbGljYXRpb25TZXJpYWxpemVyYCBpcyBmb3VuZCwgaXQgd2lsbCBhdHRlbXB0CiAgICAgIHRvIGdldCB0aGUgYGRlZmF1bHRTZXJpYWxpemVyYCBmcm9tIHRoZSBgUGVyc29uQWRhcHRlcmAKICAgICAgKGBhZGFwdGVyRm9yKCdwZXJzb24nKWApLgogICAgICAgSWYgYSBzZXJpYWxpemVyIGNhbm5vdCBiZSBmb3VuZCBvbiB0aGUgYWRhcHRlciwgaXQgd2lsbCBmYWxsIGJhY2sKICAgICAgdG8gYW4gaW5zdGFuY2Ugb2YgYEpTT05TZXJpYWxpemVyYC4KICAgICAgIEBtZXRob2Qgc2VyaWFsaXplckZvcgogICAgICBAcHVibGljCiAgICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUgdGhlIHJlY29yZCB0byBzZXJpYWxpemUKICAgICAgQHJldHVybiB7U2VyaWFsaXplcn0KICAgICovCiAgICA7CgogICAgX3Byb3RvLnNlcmlhbGl6ZXJGb3IgPSBmdW5jdGlvbiBzZXJpYWxpemVyRm9yKG1vZGVsTmFtZSkgewogICAgICB2YXIgbm9ybWFsaXplZE1vZGVsTmFtZSA9IG5vcm1hbGl6ZU1vZGVsTmFtZShtb2RlbE5hbWUpOwogICAgICB2YXIgX3NlcmlhbGl6ZXJDYWNoZSA9IHRoaXMuX3NlcmlhbGl6ZXJDYWNoZTsKICAgICAgdmFyIHNlcmlhbGl6ZXIgPSBfc2VyaWFsaXplckNhY2hlW25vcm1hbGl6ZWRNb2RlbE5hbWVdOwoKICAgICAgaWYgKHNlcmlhbGl6ZXIpIHsKICAgICAgICByZXR1cm4gc2VyaWFsaXplcjsKICAgICAgfQoKICAgICAgdmFyIG93bmVyID0gRW1iZXIuZ2V0T3duZXIodGhpcyk7CiAgICAgIHNlcmlhbGl6ZXIgPSBvd25lci5sb29rdXAoInNlcmlhbGl6ZXI6IiArIG5vcm1hbGl6ZWRNb2RlbE5hbWUpOyAvLyBpbiBwcm9kdWN0aW9uIHRoaXMgaXMgaGFuZGxlZCBieSB0aGUgcmUtZXhwb3J0CgogICAgICBpZiAoc2VyaWFsaXplciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgRW1iZXIuc2V0KHNlcmlhbGl6ZXIsICdzdG9yZScsIHRoaXMpOwogICAgICAgIF9zZXJpYWxpemVyQ2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV0gPSBzZXJpYWxpemVyOwogICAgICAgIHJldHVybiBzZXJpYWxpemVyOwogICAgICB9IC8vIG5vIHNlcmlhbGl6ZXIgZm91bmQgZm9yIHRoZSBzcGVjaWZpYyBtb2RlbCwgZmFsbGJhY2sgYW5kIGNoZWNrIGZvciBhcHBsaWNhdGlvbiBzZXJpYWxpemVyCgoKICAgICAgc2VyaWFsaXplciA9IF9zZXJpYWxpemVyQ2FjaGUuYXBwbGljYXRpb24gfHwgb3duZXIubG9va3VwKCdzZXJpYWxpemVyOmFwcGxpY2F0aW9uJyk7CgogICAgICBpZiAoc2VyaWFsaXplciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgRW1iZXIuc2V0KHNlcmlhbGl6ZXIsICdzdG9yZScsIHRoaXMpOwogICAgICAgIF9zZXJpYWxpemVyQ2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV0gPSBzZXJpYWxpemVyOwogICAgICAgIF9zZXJpYWxpemVyQ2FjaGUuYXBwbGljYXRpb24gPSBzZXJpYWxpemVyOwogICAgICAgIHJldHVybiBzZXJpYWxpemVyOwogICAgICB9IC8vIG5vIG1vZGVsIHNwZWNpZmljIHNlcmlhbGl6ZXIgb3IgYXBwbGljYXRpb24gc2VyaWFsaXplciwgY2hlY2sgZm9yIHRoZSBgZGVmYXVsdFNlcmlhbGl6ZXJgCiAgICAgIC8vIHByb3BlcnR5IGRlZmluZWQgb24gdGhlIGFkYXB0ZXIKCgogICAgICB2YXIgYWRhcHRlciA9IHRoaXMuYWRhcHRlckZvcihtb2RlbE5hbWUpOwogICAgICB2YXIgc2VyaWFsaXplck5hbWUgPSBFbWJlci5nZXQoYWRhcHRlciwgJ2RlZmF1bHRTZXJpYWxpemVyJyk7CiAgICAgIHNlcmlhbGl6ZXIgPSBzZXJpYWxpemVyTmFtZSA/IF9zZXJpYWxpemVyQ2FjaGVbc2VyaWFsaXplck5hbWVdIHx8IG93bmVyLmxvb2t1cCgic2VyaWFsaXplcjoiICsgc2VyaWFsaXplck5hbWUpIDogdW5kZWZpbmVkOyAvLyBpbiBwcm9kdWN0aW9uIHRoaXMgaXMgaGFuZGxlZCBieSB0aGUgcmUtZXhwb3J0CgogICAgICBpZiAoc2VyaWFsaXplciAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgRW1iZXIuc2V0KHNlcmlhbGl6ZXIsICdzdG9yZScsIHRoaXMpOwogICAgICAgIF9zZXJpYWxpemVyQ2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV0gPSBzZXJpYWxpemVyOwogICAgICAgIF9zZXJpYWxpemVyQ2FjaGVbc2VyaWFsaXplck5hbWVdID0gc2VyaWFsaXplcjsKICAgICAgICByZXR1cm4gc2VyaWFsaXplcjsKICAgICAgfSAvLyBmaW5hbCBmYWxsYmFjaywgbm8gbW9kZWwgc3BlY2lmaWMgc2VyaWFsaXplciwgbm8gYXBwbGljYXRpb24gc2VyaWFsaXplciwgbm8KICAgICAgLy8gYHNlcmlhbGl6ZXJgIHByb3BlcnR5IG9uIHN0b3JlOiB1c2UgdGhlIGNvbnZlbmllbmNlIEpTT05TZXJpYWxpemVyCgoKICAgICAgc2VyaWFsaXplciA9IF9zZXJpYWxpemVyQ2FjaGVbJy1kZWZhdWx0J10gfHwgb3duZXIubG9va3VwKCdzZXJpYWxpemVyOi1kZWZhdWx0Jyk7CiAgICAgIEVtYmVyLnNldChzZXJpYWxpemVyLCAnc3RvcmUnLCB0aGlzKTsKICAgICAgX3NlcmlhbGl6ZXJDYWNoZVtub3JtYWxpemVkTW9kZWxOYW1lXSA9IHNlcmlhbGl6ZXI7CiAgICAgIF9zZXJpYWxpemVyQ2FjaGVbJy1kZWZhdWx0J10gPSBzZXJpYWxpemVyOwogICAgICByZXR1cm4gc2VyaWFsaXplcjsKICAgIH07CgogICAgX3Byb3RvLndpbGxEZXN0cm95ID0gZnVuY3Rpb24gd2lsbERlc3Ryb3koKSB7CiAgICAgIF9FbWJlclNlcnZpY2UucHJvdG90eXBlLndpbGxEZXN0cm95LmNhbGwodGhpcyk7CgogICAgICB0aGlzLnJlY29yZEFycmF5TWFuYWdlci5kZXN0cm95KCk7IC8vIENoZWNrIGlmIHdlIG5lZWQgdG8gbnVsbCB0aGlzIG91dAogICAgICAvLyB0aGlzLl9hZGFwdGVyQ2FjaGUgPSBudWxsOwogICAgICAvLyB0aGlzLl9zZXJpYWxpemVyQ2FjaGUgPSBudWxsOwoKICAgICAgaWRlbnRpZmllckNhY2hlRm9yKHRoaXMpLmRlc3Ryb3koKTsKICAgICAgdGhpcy51bmxvYWRBbGwoKTsKICAgIH07CgogICAgX3Byb3RvLl91cGRhdGVSZWxhdGlvbnNoaXBTdGF0ZSA9IGZ1bmN0aW9uIF91cGRhdGVSZWxhdGlvbnNoaXBTdGF0ZShyZWxhdGlvbnNoaXApIHsKICAgICAgdmFyIF90aGlzOCA9IHRoaXM7CgogICAgICBpZiAodGhpcy5fdXBkYXRlZFJlbGF0aW9uc2hpcHMucHVzaChyZWxhdGlvbnNoaXApICE9PSAxKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0aGlzLl9iYWNrYnVybmVyLmpvaW4oZnVuY3Rpb24gKCkgewogICAgICAgIF90aGlzOC5fYmFja2J1cm5lci5zY2hlZHVsZSgnc3luY1JlbGF0aW9uc2hpcHMnLCBfdGhpczgsIF90aGlzOC5fZmx1c2hVcGRhdGVkUmVsYXRpb25zaGlwcyk7CiAgICAgIH0pOwogICAgfTsKCiAgICBfcHJvdG8uX2ZsdXNoVXBkYXRlZFJlbGF0aW9uc2hpcHMgPSBmdW5jdGlvbiBfZmx1c2hVcGRhdGVkUmVsYXRpb25zaGlwcygpIHsKICAgICAgdmFyIHVwZGF0ZWQgPSB0aGlzLl91cGRhdGVkUmVsYXRpb25zaGlwczsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gdXBkYXRlZC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICB1cGRhdGVkW2ldLmZsdXNoQ2Fub25pY2FsKCk7CiAgICAgIH0KCiAgICAgIHVwZGF0ZWQubGVuZ3RoID0gMDsKICAgIH07CgogICAgX3Byb3RvLl91cGRhdGVJbnRlcm5hbE1vZGVsID0gZnVuY3Rpb24gX3VwZGF0ZUludGVybmFsTW9kZWwoaW50ZXJuYWxNb2RlbCkgewogICAgICBpZiAodGhpcy5fdXBkYXRlZEludGVybmFsTW9kZWxzLnB1c2goaW50ZXJuYWxNb2RlbCkgIT09IDEpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGVtYmVyUnVuJDIuc2NoZWR1bGUoJ2FjdGlvbnMnLCB0aGlzLCB0aGlzLl9mbHVzaFVwZGF0ZWRJbnRlcm5hbE1vZGVscyk7CiAgICB9OwoKICAgIF9wcm90by5fZmx1c2hVcGRhdGVkSW50ZXJuYWxNb2RlbHMgPSBmdW5jdGlvbiBfZmx1c2hVcGRhdGVkSW50ZXJuYWxNb2RlbHMoKSB7CiAgICAgIHZhciB1cGRhdGVkID0gdGhpcy5fdXBkYXRlZEludGVybmFsTW9kZWxzOwoKICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSB1cGRhdGVkLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICAgIHVwZGF0ZWRbaV0uX3RyaWdnZXJEZWZlcnJlZFRyaWdnZXJzKCk7CiAgICAgIH0KCiAgICAgIHVwZGF0ZWQubGVuZ3RoID0gMDsKICAgIH07CgogICAgX2NyZWF0ZUNsYXNzJDcoQ29yZVN0b3JlLCBbewogICAgICBrZXk6ICJpZGVudGlmaWVyQ2FjaGUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKCiAgICAgICAgcmV0dXJuIGlkZW50aWZpZXJDYWNoZUZvcih0aGlzKTsKICAgICAgfQogICAgfV0pOwoKICAgIHJldHVybiBDb3JlU3RvcmU7CiAgfShFbWJlci5TZXJ2aWNlKTsKCiAgRW1iZXIuZGVmaW5lUHJvcGVydHkoQ29yZVN0b3JlLnByb3RvdHlwZSwgJ2RlZmF1bHRBZGFwdGVyJywgRW1iZXIuY29tcHV0ZWQoJ2FkYXB0ZXInLCBmdW5jdGlvbiAoKSB7CiAgICB2YXIgYWRhcHRlciA9IHRoaXMuYWRhcHRlciB8fCAnLWpzb24tYXBpJzsKICAgIHJldHVybiB0aGlzLmFkYXB0ZXJGb3IoYWRhcHRlcik7CiAgfSkpOwoKICBmdW5jdGlvbiBfY29tbWl0KGFkYXB0ZXIsIHN0b3JlLCBvcGVyYXRpb24sIHNuYXBzaG90KSB7CiAgICB2YXIgaW50ZXJuYWxNb2RlbCA9IHNuYXBzaG90Ll9pbnRlcm5hbE1vZGVsOwogICAgdmFyIG1vZGVsTmFtZSA9IHNuYXBzaG90Lm1vZGVsTmFtZTsKICAgIHZhciBtb2RlbENsYXNzID0gc3RvcmUubW9kZWxGb3IobW9kZWxOYW1lKTsKICAgIHZhciBwcm9taXNlID0gRW1iZXIuUlNWUC5Qcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIGFkYXB0ZXJbb3BlcmF0aW9uXShzdG9yZSwgbW9kZWxDbGFzcywgc25hcHNob3QpOwogICAgfSk7CiAgICB2YXIgc2VyaWFsaXplciA9IHN0b3JlLnNlcmlhbGl6ZXJGb3IobW9kZWxOYW1lKTsKICAgIHZhciBsYWJlbCA9ICJEUzogRXh0cmFjdCBhbmQgbm90aWZ5IGFib3V0ICIgKyBvcGVyYXRpb24gKyAiIGNvbXBsZXRpb24gb2YgIiArIGludGVybmFsTW9kZWw7CiAgICBwcm9taXNlID0gZ3VhcmREZXN0cm95ZWRTdG9yZShwcm9taXNlLCBzdG9yZSwgbGFiZWwpOwogICAgcHJvbWlzZSA9IF9ndWFyZChwcm9taXNlLCBfYmluZChfb2JqZWN0SXNBbGl2ZSwgaW50ZXJuYWxNb2RlbCkpOwogICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAoYWRhcHRlclBheWxvYWQpIHsKICAgICAgLyoKICAgICAgTm90ZSB0byBmdXR1cmUgc3BlbHVua2VycyBob3BpbmcgdG8gb3B0aW1pemUuCiAgICAgIFdlIHJlbHkgb24gdGhpcyBgcnVuYCB0byBjcmVhdGUgYSBydW4gbG9vcCBpZiBuZWVkZWQKICAgICAgdGhhdCBgc3RvcmUuX3B1c2hgIGFuZCBgc3RvcmUuZGlkU2F2ZVJlY29yZGAgd2lsbCBib3RoIHNoYXJlLgogICAgICAgV2UgdXNlIGBqb2luYCBiZWNhdXNlIGl0IGlzIG9mdGVuIHRoZSBjYXNlIHRoYXQgd2UKICAgICAgaGF2ZSBhbiBvdXRlciBydW4gbG9vcCBhdmFpbGFibGUgc3RpbGwgZnJvbSB0aGUgZmlyc3QKICAgICAgY2FsbCB0byBgc3RvcmUuX3B1c2hgOwogICAgICAqLwogICAgICBzdG9yZS5fYmFja2J1cm5lci5qb2luKGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgcGF5bG9hZCwgZGF0YSwgc2lkZWxvYWRlZDsKCiAgICAgICAgaWYgKGFkYXB0ZXJQYXlsb2FkKSB7CiAgICAgICAgICBwYXlsb2FkID0gbm9ybWFsaXplUmVzcG9uc2VIZWxwZXIoc2VyaWFsaXplciwgc3RvcmUsIG1vZGVsQ2xhc3MsIGFkYXB0ZXJQYXlsb2FkLCBzbmFwc2hvdC5pZCwgb3BlcmF0aW9uKTsKCiAgICAgICAgICBpZiAocGF5bG9hZC5pbmNsdWRlZCkgewogICAgICAgICAgICBzaWRlbG9hZGVkID0gcGF5bG9hZC5pbmNsdWRlZDsKICAgICAgICAgIH0KCiAgICAgICAgICBkYXRhID0gcGF5bG9hZC5kYXRhOwogICAgICAgIH0KCiAgICAgICAgc3RvcmUuZGlkU2F2ZVJlY29yZChpbnRlcm5hbE1vZGVsLCB7CiAgICAgICAgICBkYXRhOiBkYXRhCiAgICAgICAgfSwgb3BlcmF0aW9uKTsgLy8gc2VlbXMgcmlza3ksIGJ1dCBpZiB0aGUgdGVzdHMgcGFzcyBtaWdodCBiZSBmaW5lPwoKICAgICAgICBpZiAoc2lkZWxvYWRlZCkgewogICAgICAgICAgc3RvcmUuX3B1c2goewogICAgICAgICAgICBkYXRhOiBudWxsLAogICAgICAgICAgICBpbmNsdWRlZDogc2lkZWxvYWRlZAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9KTsKCiAgICAgIHJldHVybiBpbnRlcm5hbE1vZGVsOwogICAgfSwgZnVuY3Rpb24gKGVycm9yKSB7CiAgICAgIGlmIChlcnJvciAmJiBlcnJvci5pc0FkYXB0ZXJFcnJvciA9PT0gdHJ1ZSAmJiBlcnJvci5jb2RlID09PSAnSW52YWxpZEVycm9yJykgewogICAgICAgIHZhciBwYXJzZWRFcnJvcnM7CgogICAgICAgIGlmICh0eXBlb2Ygc2VyaWFsaXplci5leHRyYWN0RXJyb3JzID09PSAnZnVuY3Rpb24nKSB7CiAgICAgICAgICBwYXJzZWRFcnJvcnMgPSBzZXJpYWxpemVyLmV4dHJhY3RFcnJvcnMoc3RvcmUsIG1vZGVsQ2xhc3MsIGVycm9yLCBzbmFwc2hvdC5pZCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHBhcnNlZEVycm9ycyA9IGVycm9yc0FycmF5VG9IYXNoKGVycm9yLmVycm9ycyk7CiAgICAgICAgfQoKICAgICAgICBzdG9yZS5yZWNvcmRXYXNJbnZhbGlkKGludGVybmFsTW9kZWwsIHBhcnNlZEVycm9ycywgZXJyb3IpOwogICAgICB9IGVsc2UgewogICAgICAgIHN0b3JlLnJlY29yZFdhc0Vycm9yKGludGVybmFsTW9kZWwsIGVycm9yKTsKICAgICAgfQoKICAgICAgdGhyb3cgZXJyb3I7CiAgICB9LCBsYWJlbCk7CiAgfQoKICB2YXIgSEFTX01PREVMX1BBQ0tBR0UkMSA9IHJlcXVpcmUuaGFzKCdAZW1iZXItZGF0YS9tb2RlbCcpOwoKICB2YXIgX01vZGVsJDE7CgogIGZ1bmN0aW9uIGdldE1vZGVsJDEoKSB7CiAgICBpZiAoSEFTX01PREVMX1BBQ0tBR0UkMSkgewogICAgICBfTW9kZWwkMSA9IF9Nb2RlbCQxIHx8IHJlcXVpcmVfX2RlZmF1bHQoJ0BlbWJlci1kYXRhL21vZGVsJykuZGVmYXVsdDsKICAgIH0KCiAgICByZXR1cm4gX01vZGVsJDE7CiAgfQoKICB2YXIgRFNNb2RlbFNjaGVtYURlZmluaXRpb25TZXJ2aWNlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gRFNNb2RlbFNjaGVtYURlZmluaXRpb25TZXJ2aWNlKHN0b3JlKSB7CiAgICAgIHRoaXMuc3RvcmUgPSBzdG9yZTsKICAgICAgdGhpcy5fbW9kZWxGYWN0b3J5Q2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9yZWxhdGlvbnNoaXBzRGVmQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLl9hdHRyaWJ1dGVzRGVmQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgfSAvLyBGb2xsb3dpbmcgdGhlIGV4aXN0aW5nIFJEIGltcGxlbWVudGF0aW9uCgoKICAgIHZhciBfcHJvdG8gPSBEU01vZGVsU2NoZW1hRGVmaW5pdGlvblNlcnZpY2UucHJvdG90eXBlOwoKICAgIF9wcm90by5hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvciA9IGZ1bmN0aW9uIGF0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKGlkZW50aWZpZXIpIHsKICAgICAgdmFyIG1vZGVsTmFtZSwgYXR0cmlidXRlczsKCiAgICAgIGlmICh0eXBlb2YgaWRlbnRpZmllciA9PT0gJ3N0cmluZycpIHsKICAgICAgICBtb2RlbE5hbWUgPSBpZGVudGlmaWVyOwogICAgICB9IGVsc2UgewogICAgICAgIG1vZGVsTmFtZSA9IGlkZW50aWZpZXIudHlwZTsKICAgICAgfQoKICAgICAgYXR0cmlidXRlcyA9IHRoaXMuX2F0dHJpYnV0ZXNEZWZDYWNoZVttb2RlbE5hbWVdOwoKICAgICAgaWYgKGF0dHJpYnV0ZXMgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhciBtb2RlbENsYXNzID0gdGhpcy5zdG9yZS5tb2RlbEZvcihtb2RlbE5hbWUpOwogICAgICAgIHZhciBhdHRyaWJ1dGVNYXAgPSBFbWJlci5nZXQobW9kZWxDbGFzcywgJ2F0dHJpYnV0ZXMnKTsKICAgICAgICBhdHRyaWJ1dGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICBhdHRyaWJ1dGVNYXAuZm9yRWFjaChmdW5jdGlvbiAobWV0YSwgbmFtZSkgewogICAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZXNbbmFtZV0gPSBtZXRhOwogICAgICAgIH0pOwogICAgICAgIHRoaXMuX2F0dHJpYnV0ZXNEZWZDYWNoZVttb2RlbE5hbWVdID0gYXR0cmlidXRlczsKICAgICAgfQoKICAgICAgcmV0dXJuIGF0dHJpYnV0ZXM7CiAgICB9IC8vIEZvbGxvd2luZyB0aGUgZXhpc3RpbmcgUkQgaW1wbGVtZW50YXRpb24KICAgIDsKCiAgICBfcHJvdG8ucmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IgPSBmdW5jdGlvbiByZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcihpZGVudGlmaWVyKSB7CiAgICAgIHZhciBtb2RlbE5hbWUsIHJlbGF0aW9uc2hpcHM7CgogICAgICBpZiAodHlwZW9mIGlkZW50aWZpZXIgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgbW9kZWxOYW1lID0gaWRlbnRpZmllcjsKICAgICAgfSBlbHNlIHsKICAgICAgICBtb2RlbE5hbWUgPSBpZGVudGlmaWVyLnR5cGU7CiAgICAgIH0KCiAgICAgIHJlbGF0aW9uc2hpcHMgPSB0aGlzLl9yZWxhdGlvbnNoaXBzRGVmQ2FjaGVbbW9kZWxOYW1lXTsKCiAgICAgIGlmIChyZWxhdGlvbnNoaXBzID09PSB1bmRlZmluZWQpIHsKICAgICAgICB2YXIgbW9kZWxDbGFzcyA9IHRoaXMuc3RvcmUubW9kZWxGb3IobW9kZWxOYW1lKTsKICAgICAgICByZWxhdGlvbnNoaXBzID0gRW1iZXIuZ2V0KG1vZGVsQ2xhc3MsICdyZWxhdGlvbnNoaXBzT2JqZWN0JykgfHwgbnVsbDsKICAgICAgICB0aGlzLl9yZWxhdGlvbnNoaXBzRGVmQ2FjaGVbbW9kZWxOYW1lXSA9IHJlbGF0aW9uc2hpcHM7CiAgICAgIH0KCiAgICAgIHJldHVybiByZWxhdGlvbnNoaXBzOwogICAgfTsKCiAgICBfcHJvdG8uZG9lc1R5cGVFeGlzdCA9IGZ1bmN0aW9uIGRvZXNUeXBlRXhpc3QobW9kZWxOYW1lKSB7CiAgICAgIHZhciBub3JtYWxpemVkTW9kZWxOYW1lID0gbm9ybWFsaXplTW9kZWxOYW1lKG1vZGVsTmFtZSk7CiAgICAgIHZhciBmYWN0b3J5ID0gZ2V0TW9kZWxGYWN0b3J5KHRoaXMuc3RvcmUsIHRoaXMuX21vZGVsRmFjdG9yeUNhY2hlLCBub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgcmV0dXJuIGZhY3RvcnkgIT09IG51bGw7CiAgICB9OwoKICAgIHJldHVybiBEU01vZGVsU2NoZW1hRGVmaW5pdGlvblNlcnZpY2U7CiAgfSgpOwogIC8qKgogICAqCiAgICogQHBhcmFtIHN0b3JlCiAgICogQHBhcmFtIGNhY2hlIG1vZGVsRmFjdG9yeUNhY2hlCiAgICogQHBhcmFtIG5vcm1hbGl6ZWRNb2RlbE5hbWUgYWxyZWFkeSBub3JtYWxpemVkIG1vZGVsTmFtZQogICAqIEByZXR1cm4geyp9CiAgICovCgogIGZ1bmN0aW9uIGdldE1vZGVsRmFjdG9yeShzdG9yZSwgY2FjaGUsIG5vcm1hbGl6ZWRNb2RlbE5hbWUpIHsKICAgIHZhciBmYWN0b3J5ID0gY2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV07CgogICAgaWYgKCFmYWN0b3J5KSB7CiAgICAgIGZhY3RvcnkgPSBfbG9va3VwTW9kZWxGYWN0b3J5KHN0b3JlLCBub3JtYWxpemVkTW9kZWxOYW1lKTsKCiAgICAgIGlmICghZmFjdG9yeSkgewogICAgICAgIC8vU3VwcG9ydCBsb29raW5nIHVwIG1peGlucyBhcyBiYXNlIHR5cGVzIGZvciBwb2x5bW9ycGhpYyByZWxhdGlvbnNoaXBzCiAgICAgICAgZmFjdG9yeSA9IF9tb2RlbEZvck1peGluKHN0b3JlLCBub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgfQoKICAgICAgaWYgKCFmYWN0b3J5KSB7CiAgICAgICAgLy8gd2UgZG9uJ3QgY2FjaGUgbWlzc2VzIGluIGNhc2Ugc29tZW9uZSB3YW50cyB0byByZWdpc3RlciBhIG1pc3NpbmcgbW9kZWwKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQoKICAgICAgdmFyIGtsYXNzID0gZmFjdG9yeS5jbGFzczsgLy8gYXNzZXJ0KGAnJHtpbnNwZWN0KGtsYXNzKX0nIGRvZXMgbm90IGFwcGVhciB0byBiZSBhbiBlbWJlci1kYXRhIG1vZGVsYCwga2xhc3MuaXNNb2RlbCk7CiAgICAgIC8vIFRPRE86IGRlcHJlY2F0ZSB0aGlzCgogICAgICBpZiAoa2xhc3MuaXNNb2RlbCkgewogICAgICAgIHZhciBoYXNPd25Nb2RlbE5hbWVTZXQgPSBrbGFzcy5tb2RlbE5hbWUgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGtsYXNzLCAnbW9kZWxOYW1lJyk7CgogICAgICAgIGlmICghaGFzT3duTW9kZWxOYW1lU2V0KSB7CiAgICAgICAgICBrbGFzcy5tb2RlbE5hbWUgPSBub3JtYWxpemVkTW9kZWxOYW1lOwogICAgICAgIH0KICAgICAgfQoKICAgICAgY2FjaGVbbm9ybWFsaXplZE1vZGVsTmFtZV0gPSBmYWN0b3J5OwogICAgfQoKICAgIHJldHVybiBmYWN0b3J5OwogIH0KICBmdW5jdGlvbiBfbG9va3VwTW9kZWxGYWN0b3J5KHN0b3JlLCBub3JtYWxpemVkTW9kZWxOYW1lKSB7CiAgICB2YXIgb3duZXIgPSBFbWJlci5nZXRPd25lcihzdG9yZSk7CiAgICByZXR1cm4gb3duZXIuZmFjdG9yeUZvcigibW9kZWw6IiArIG5vcm1hbGl6ZWRNb2RlbE5hbWUpOwogIH0KICAvKgogICAgICBJbiBjYXNlIHNvbWVvbmUgZGVmaW5lZCBhIHJlbGF0aW9uc2hpcCB0byBhIG1peGluLCBmb3IgZXhhbXBsZToKICAgICAgYGBgCiAgICAgICAgbGV0IENvbW1lbnQgPSBNb2RlbC5leHRlbmQoewogICAgICAgICAgb3duZXI6IGJlbG9uZ3NUbygnY29tbWVudGFibGUnLiB7IHBvbHltb3JwaGljOiB0cnVlIH0pCiAgICAgICAgfSk7CiAgICAgICAgbGV0IENvbW1lbnRhYmxlID0gRW1iZXIuTWl4aW4uY3JlYXRlKHsKICAgICAgICAgIGNvbW1lbnRzOiBoYXNNYW55KCdjb21tZW50JykKICAgICAgICB9KTsKICAgICAgYGBgCiAgICAgIHdlIHdhbnQgdG8gbG9vayB1cCBhIENvbW1lbnRhYmxlIGNsYXNzIHdoaWNoIGhhcyBhbGwgdGhlIG5lY2Vzc2FyeQogICAgICByZWxhdGlvbnNoaXAgbWV0YWRhdGEuIFRodXMsIHdlIGxvb2sgdXAgdGhlIG1peGluIGFuZCBjcmVhdGUgYSBtb2NrCiAgICAgIE1vZGVsLCBzbyB3ZSBjYW4gYWNjZXNzIHRoZSByZWxhdGlvbnNoaXAgQ1BzIG9mIHRoZSBtaXhpbiAoYGNvbW1lbnRzYCkKICAgICAgaW4gdGhpcyBjYXNlCiAgICAqLwoKICBmdW5jdGlvbiBfbW9kZWxGb3JNaXhpbihzdG9yZSwgbm9ybWFsaXplZE1vZGVsTmFtZSkgewogICAgaWYgKEhBU19NT0RFTF9QQUNLQUdFJDEpIHsKICAgICAgdmFyIG93bmVyID0gRW1iZXIuZ2V0T3duZXIoc3RvcmUpOwogICAgICB2YXIgTWF5YmVNaXhpbiA9IG93bmVyLmZhY3RvcnlGb3IoIm1peGluOiIgKyBub3JtYWxpemVkTW9kZWxOYW1lKTsKICAgICAgdmFyIG1peGluID0gTWF5YmVNaXhpbiAmJiBNYXliZU1peGluLmNsYXNzOwoKICAgICAgaWYgKG1peGluKSB7CiAgICAgICAgdmFyIE1vZGVsRm9yTWl4aW4gPSBnZXRNb2RlbCQxKCkuZXh0ZW5kKG1peGluKTsKICAgICAgICBNb2RlbEZvck1peGluLnJlb3BlbkNsYXNzKHsKICAgICAgICAgIF9faXNNaXhpbjogdHJ1ZSwKICAgICAgICAgIF9fbWl4aW46IG1peGluCiAgICAgICAgfSk7IC8vQ2FjaGUgdGhlIGNsYXNzIGFzIGEgbW9kZWwKCiAgICAgICAgb3duZXIucmVnaXN0ZXIoJ21vZGVsOicgKyBub3JtYWxpemVkTW9kZWxOYW1lLCBNb2RlbEZvck1peGluKTsKICAgICAgfQoKICAgICAgcmV0dXJuIF9sb29rdXBNb2RlbEZhY3Rvcnkoc3RvcmUsIG5vcm1hbGl6ZWRNb2RlbE5hbWUpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gbm90aWZ5Q2hhbmdlcyhpZGVudGlmaWVyLCB2YWx1ZSwgcmVjb3JkLCBzdG9yZSkgewogICAgaWYgKHZhbHVlID09PSAnYXR0cmlidXRlcycpIHsKICAgICAgcmVjb3JkLmVhY2hBdHRyaWJ1dGUoZnVuY3Rpb24gKGtleSkgewogICAgICAgIHZhciBjdXJyZW50VmFsdWUgPSBFbWJlci5jYWNoZUZvcihyZWNvcmQsIGtleSk7CgogICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gc3RvcmUuX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShpZGVudGlmaWVyKTsKCiAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSAhPT0gaW50ZXJuYWxNb2RlbC5fcmVjb3JkRGF0YS5nZXRBdHRyKGtleSkpIHsKICAgICAgICAgIHJlY29yZC5ub3RpZnlQcm9wZXJ0eUNoYW5nZShrZXkpOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAncmVsYXRpb25zaGlwcycpIHsKICAgICAgcmVjb3JkLmVhY2hSZWxhdGlvbnNoaXAoZnVuY3Rpb24gKGtleSwgbWV0YSkgewogICAgICAgIHZhciBpbnRlcm5hbE1vZGVsID0gc3RvcmUuX2ludGVybmFsTW9kZWxGb3JSZXNvdXJjZShpZGVudGlmaWVyKTsKCiAgICAgICAgaWYgKG1ldGEua2luZCA9PT0gJ2JlbG9uZ3NUbycpIHsKICAgICAgICAgIHJlY29yZC5ub3RpZnlQcm9wZXJ0eUNoYW5nZShrZXkpOwogICAgICAgIH0gZWxzZSBpZiAobWV0YS5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgICAgIGlmIChtZXRhLm9wdGlvbnMuYXN5bmMpIHsKICAgICAgICAgICAgcmVjb3JkLm5vdGlmeVByb3BlcnR5Q2hhbmdlKGtleSk7CiAgICAgICAgICAgIGludGVybmFsTW9kZWwuaGFzTWFueVJlbW92YWxDaGVjayhrZXkpOwogICAgICAgICAgfQoKICAgICAgICAgIGlmIChpbnRlcm5hbE1vZGVsLl9tYW55QXJyYXlDYWNoZVtrZXldKSB7CiAgICAgICAgICAgIGludGVybmFsTW9kZWwuX21hbnlBcnJheUNhY2hlW2tleV0ucmV0cmlldmVMYXRlc3QoKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gJ2Vycm9ycycpIHsKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSBzdG9yZS5faW50ZXJuYWxNb2RlbEZvclJlc291cmNlKGlkZW50aWZpZXIpOyAvL1RPRE8gZ3VhcmQKCgogICAgICB2YXIgZXJyb3JzID0gaW50ZXJuYWxNb2RlbC5fcmVjb3JkRGF0YS5nZXRFcnJvcnMoaWRlbnRpZmllcik7CgogICAgICByZWNvcmQuaW52YWxpZEVycm9yc0NoYW5nZWQoZXJyb3JzKTsKICAgIH0gZWxzZSBpZiAodmFsdWUgPT09ICdzdGF0ZScpIHsKICAgICAgcmVjb3JkLm5vdGlmeVByb3BlcnR5Q2hhbmdlKCdpc05ldycpOwogICAgICByZWNvcmQubm90aWZ5UHJvcGVydHlDaGFuZ2UoJ2lzRGVsZXRlZCcpOwogICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gJ2lkZW50aXR5JykgewogICAgICByZWNvcmQubm90aWZ5UHJvcGVydHlDaGFuZ2UoJ2lkJyk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZSQ0KHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcy5wcm90b3R5cGUpOyBzdWJDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBzdWJDbGFzczsgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfQogIC8qKgogICAgVGhlIHN0b3JlIHNlcnZpY2UgY29udGFpbnMgYWxsIG9mIHRoZSBkYXRhIGZvciByZWNvcmRzIGxvYWRlZCBmcm9tIHRoZSBzZXJ2ZXIuCiAgICBJdCBpcyBhbHNvIHJlc3BvbnNpYmxlIGZvciBjcmVhdGluZyBpbnN0YW5jZXMgb2YgYE1vZGVsYCB0aGF0IHdyYXAKICAgIHRoZSBpbmRpdmlkdWFsIGRhdGEgZm9yIGEgcmVjb3JkLCBzbyB0aGF0IHRoZXkgY2FuIGJlIGJvdW5kIHRvIGluIHlvdXIKICAgIEhhbmRsZWJhcnMgdGVtcGxhdGVzLgoKICAgIEJ5IGRlZmF1bHQsIGFwcGxpY2F0aW9ucyB3aWxsIGhhdmUgYSBzaW5nbGUgYFN0b3JlYCBzZXJ2aWNlIHRoYXQgaXMKICAgIGF1dG9tYXRpY2FsbHkgY3JlYXRlZC4KCiAgICBUaGUgc3RvcmUgY2FuIGJlIGN1c3RvbWl6ZWQgYnkgZXh0ZW5kaW5nIHRoZSBzZXJ2aWNlIGluIHRoZSBmb2xsb3dpbmcgbWFubmVyOgoKICAgIGBgYGFwcC9zZXJ2aWNlcy9zdG9yZS5qcwogICAgaW1wb3J0IFN0b3JlIGZyb20gJ0BlbWJlci1kYXRhL3N0b3JlJzsKCiAgICBleHBvcnQgZGVmYXVsdCBjbGFzcyBNeVN0b3JlIGV4dGVuZHMgU3RvcmUge30KICAgIGBgYAoKICAgIFlvdSBjYW4gcmV0cmlldmUgbW9kZWxzIGZyb20gdGhlIHN0b3JlIGluIHNldmVyYWwgd2F5cy4gVG8gcmV0cmlldmUgYSByZWNvcmQKICAgIGZvciBhIHNwZWNpZmljIGlkLCB1c2UgdGhlIGBTdG9yZWAncyBgZmluZFJlY29yZCgpYCBtZXRob2Q6CgogICAgYGBgamF2YXNjcmlwdAogICAgc3RvcmUuZmluZFJlY29yZCgncGVyc29uJywgMTIzKS50aGVuKGZ1bmN0aW9uIChwZXJzb24pIHsKICAgIH0pOwogICAgYGBgCgogICAgQnkgZGVmYXVsdCwgdGhlIHN0b3JlIHdpbGwgdGFsayB0byB5b3VyIGJhY2tlbmQgdXNpbmcgYSBzdGFuZGFyZAogICAgUkVTVCBtZWNoYW5pc20uIFlvdSBjYW4gY3VzdG9taXplIGhvdyB0aGUgc3RvcmUgdGFsa3MgdG8geW91cgogICAgYmFja2VuZCBieSBzcGVjaWZ5aW5nIGEgY3VzdG9tIGFkYXB0ZXI6CgogICAgYGBgYXBwL2FkYXB0ZXJzL2FwcGxpY2F0aW9uLmpzCiAgICBpbXBvcnQgRFMgZnJvbSAnZW1iZXItZGF0YSc7CgogICAgZXhwb3J0IGRlZmF1bHQgQWRhcHRlci5leHRlbmQoewogICAgfSk7CiAgICBgYGAKCiAgICBZb3UgY2FuIGxlYXJuIG1vcmUgYWJvdXQgd3JpdGluZyBhIGN1c3RvbSBhZGFwdGVyIGJ5IHJlYWRpbmcgdGhlIGBBZGFwdGVyYAogICAgZG9jdW1lbnRhdGlvbi4KCiAgICAjIyMgU3RvcmUgY3JlYXRlUmVjb3JkKCkgdnMuIHB1c2goKSB2cy4gcHVzaFBheWxvYWQoKQoKICAgIFRoZSBzdG9yZSBwcm92aWRlcyBtdWx0aXBsZSB3YXlzIHRvIGNyZWF0ZSBuZXcgcmVjb3JkIG9iamVjdHMuIFRoZXkgaGF2ZQogICAgc29tZSBzdWJ0bGUgZGlmZmVyZW5jZXMgaW4gdGhlaXIgdXNlIHdoaWNoIGFyZSBkZXRhaWxlZCBiZWxvdzoKCiAgICBbY3JlYXRlUmVjb3JkXShTdG9yZS9tZXRob2RzL2NyZWF0ZVJlY29yZD9hbmNob3I9Y3JlYXRlUmVjb3JkKSBpcyB1c2VkIGZvciBjcmVhdGluZyBuZXcKICAgIHJlY29yZHMgb24gdGhlIGNsaWVudCBzaWRlLiBUaGlzIHdpbGwgcmV0dXJuIGEgbmV3IHJlY29yZCBpbiB0aGUKICAgIGBjcmVhdGVkLnVuY29tbWl0dGVkYCBzdGF0ZS4gSW4gb3JkZXIgdG8gcGVyc2lzdCB0aGlzIHJlY29yZCB0byB0aGUKICAgIGJhY2tlbmQsIHlvdSB3aWxsIG5lZWQgdG8gY2FsbCBgcmVjb3JkLnNhdmUoKWAuCgogICAgW3B1c2hdKFN0b3JlL21ldGhvZHMvcHVzaD9hbmNob3I9cHVzaCkgaXMgdXNlZCB0byBub3RpZnkgRW1iZXIgRGF0YSdzIHN0b3JlIG9mIG5ldyBvcgogICAgdXBkYXRlZCByZWNvcmRzIHRoYXQgZXhpc3QgaW4gdGhlIGJhY2tlbmQuIFRoaXMgd2lsbCByZXR1cm4gYSByZWNvcmQKICAgIGluIHRoZSBgbG9hZGVkLnNhdmVkYCBzdGF0ZS4gVGhlIHByaW1hcnkgdXNlLWNhc2UgZm9yIGBzdG9yZSNwdXNoYCBpcwogICAgdG8gbm90aWZ5IEVtYmVyIERhdGEgYWJvdXQgcmVjb3JkIHVwZGF0ZXMgKGZ1bGwgb3IgcGFydGlhbCkgdGhhdCBoYXBwZW4KICAgIG91dHNpZGUgb2YgdGhlIG5vcm1hbCBhZGFwdGVyIG1ldGhvZHMgKGZvciBleGFtcGxlCiAgICBbU1NFXShodHRwOi8vZGV2LnczLm9yZy9odG1sNS9ldmVudHNvdXJjZS8pIG9yIFtXZWIKICAgIFNvY2tldHNdKGh0dHA6Ly93d3cudzMub3JnL1RSLzIwMDkvV0Qtd2Vic29ja2V0cy0yMDA5MTIyMi8pKS4KCiAgICBbcHVzaFBheWxvYWRdKFN0b3JlL21ldGhvZHMvcHVzaFBheWxvYWQ/YW5jaG9yPXB1c2hQYXlsb2FkKSBpcyBhIGNvbnZlbmllbmNlIHdyYXBwZXIgZm9yCiAgICBgc3RvcmUjcHVzaGAgdGhhdCB3aWxsIGRlc2VyaWFsaXplIHBheWxvYWRzIGlmIHRoZQogICAgU2VyaWFsaXplciBpbXBsZW1lbnRzIGEgYHB1c2hQYXlsb2FkYCBtZXRob2QuCgogICAgTm90ZTogV2hlbiBjcmVhdGluZyBhIG5ldyByZWNvcmQgdXNpbmcgYW55IG9mIHRoZSBhYm92ZSBtZXRob2RzCiAgICBFbWJlciBEYXRhIHdpbGwgdXBkYXRlIGBSZWNvcmRBcnJheWBzIHN1Y2ggYXMgdGhvc2UgcmV0dXJuZWQgYnkKICAgIGBzdG9yZSNwZWVrQWxsKClgIG9yIGBzdG9yZSNmaW5kQWxsKClgLiBUaGlzIG1lYW5zIGFueQogICAgZGF0YSBiaW5kaW5ncyBvciBjb21wdXRlZCBwcm9wZXJ0aWVzIHRoYXQgZGVwZW5kIG9uIHRoZSBSZWNvcmRBcnJheQogICAgd2lsbCBhdXRvbWF0aWNhbGx5IGJlIHN5bmNlZCB0byBpbmNsdWRlIHRoZSBuZXcgb3IgdXBkYXRlZCByZWNvcmQKICAgIHZhbHVlcy4KCiAgICBAY2xhc3MgU3RvcmUKICAgIEBtYWluIEBlbWJlci1kYXRhL3N0b3JlCiAgICBAZXh0ZW5kcyBFbWJlci5TZXJ2aWNlCiAgKi8KCiAgdmFyIFN0b3JlID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKF9Db3JlU3RvcmUpIHsKICAgIF9pbmhlcml0c0xvb3NlJDQoU3RvcmUsIF9Db3JlU3RvcmUpOwoKICAgIGZ1bmN0aW9uIFN0b3JlKCkgewogICAgICB2YXIgX3RoaXM7CgogICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IG5ldyBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHsKICAgICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldOwogICAgICB9CgogICAgICBfdGhpcyA9IF9Db3JlU3RvcmUuY2FsbC5hcHBseShfQ29yZVN0b3JlLCBbdGhpc10uY29uY2F0KGFyZ3MpKSB8fCB0aGlzOwogICAgICBfdGhpcy5fbW9kZWxGYWN0b3J5Q2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBfdGhpcy5fcmVsYXRpb25zaGlwc0RlZkNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgX3RoaXMuX2F0dHJpYnV0ZXNEZWZDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHJldHVybiBfdGhpczsKICAgIH0KCiAgICB2YXIgX3Byb3RvID0gU3RvcmUucHJvdG90eXBlOwoKICAgIF9wcm90by5pbnN0YW50aWF0ZVJlY29yZCA9IGZ1bmN0aW9uIGluc3RhbnRpYXRlUmVjb3JkKGlkZW50aWZpZXIsIGNyZWF0ZVJlY29yZEFyZ3MsIHJlY29yZERhdGFGb3IsIG5vdGlmaWNhdGlvbk1hbmFnZXIpIHsKICAgICAgdmFyIF90aGlzMiA9IHRoaXM7CgogICAgICB2YXIgbW9kZWxOYW1lID0gaWRlbnRpZmllci50eXBlOwoKICAgICAgdmFyIGludGVybmFsTW9kZWwgPSB0aGlzLl9pbnRlcm5hbE1vZGVsRm9yUmVzb3VyY2UoaWRlbnRpZmllcik7CgogICAgICB2YXIgY3JlYXRlT3B0aW9ucyA9IHsKICAgICAgICBzdG9yZTogdGhpcywKICAgICAgICBfaW50ZXJuYWxNb2RlbDogaW50ZXJuYWxNb2RlbCwKICAgICAgICBjdXJyZW50U3RhdGU6IGludGVybmFsTW9kZWwuY3VycmVudFN0YXRlLAogICAgICAgIGNvbnRhaW5lcjogbnVsbAogICAgICB9OwogICAgICBFbWJlci5hc3NpZ24oY3JlYXRlT3B0aW9ucywgY3JlYXRlUmVjb3JkQXJncyk7IC8vIGVuc3VyZSB0aGF0IGBnZXRPd25lcih0aGlzKWAgd29ya3MgaW5zaWRlIGEgbW9kZWwgaW5zdGFuY2UKCiAgICAgIEVtYmVyLnNldE93bmVyKGNyZWF0ZU9wdGlvbnMsIEVtYmVyLmdldE93bmVyKHRoaXMpKTsKICAgICAgZGVsZXRlIGNyZWF0ZU9wdGlvbnMuY29udGFpbmVyOwoKICAgICAgdmFyIHJlY29yZCA9IHRoaXMuX21vZGVsRmFjdG9yeUZvcihtb2RlbE5hbWUpLmNyZWF0ZShjcmVhdGVPcHRpb25zKTsgLy90b2RvIG9wdGltaXplCgoKICAgICAgbm90aWZpY2F0aW9uTWFuYWdlci5zdWJzY3JpYmUoaWRlbnRpZmllciwgZnVuY3Rpb24gKGlkZW50aWZpZXIsIHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIG5vdGlmeUNoYW5nZXMoaWRlbnRpZmllciwgdmFsdWUsIHJlY29yZCwgX3RoaXMyKTsKICAgICAgfSk7CiAgICAgIHJldHVybiByZWNvcmQ7CiAgICB9OwoKICAgIF9wcm90by50ZWFyZG93blJlY29yZCA9IGZ1bmN0aW9uIHRlYXJkb3duUmVjb3JkKHJlY29yZCkgewogICAgICByZWNvcmQuZGVzdHJveSgpOwogICAgfQogICAgLyoqCiAgICBSZXR1cm5zIHRoZSBtb2RlbCBjbGFzcyBmb3IgdGhlIHBhcnRpY3VsYXIgYG1vZGVsTmFtZWAuCiAgICAgVGhlIGNsYXNzIG9mIGEgbW9kZWwgbWlnaHQgYmUgdXNlZnVsIGlmIHlvdSB3YW50IHRvIGdldCBhIGxpc3Qgb2YgYWxsIHRoZQogICAgcmVsYXRpb25zaGlwIG5hbWVzIG9mIHRoZSBtb2RlbCwgc2VlCiAgICBbYHJlbGF0aW9uc2hpcE5hbWVzYF0oL2VtYmVyLWRhdGEvcmVsZWFzZS9jbGFzc2VzL01vZGVsP2FuY2hvcj1yZWxhdGlvbnNoaXBOYW1lcykKICAgIGZvciBleGFtcGxlLgogICAgIEBtZXRob2QgbW9kZWxGb3IKICAgIEBwYXJhbSB7U3RyaW5nfSBtb2RlbE5hbWUKICAgIEByZXR1cm4ge01vZGVsfQogICAgICAqLwogICAgOwoKICAgIF9wcm90by5tb2RlbEZvciA9IGZ1bmN0aW9uIG1vZGVsRm9yKG1vZGVsTmFtZSkgewoKICAgICAgdmFyIG1heWJlRmFjdG9yeSA9IHRoaXMuX21vZGVsRmFjdG9yeUZvcihtb2RlbE5hbWUpOyAvLyBmb3IgZmFjdG9yRm9yIGZhY3RvcnkvY2xhc3Mgc3BsaXQKCgogICAgICB2YXIga2xhc3MgPSBtYXliZUZhY3RvcnkuY2xhc3MgPyBtYXliZUZhY3RvcnkuY2xhc3MgOiBtYXliZUZhY3Rvcnk7CgogICAgICBpZiAoIWtsYXNzLmlzTW9kZWwpIHsKICAgICAgICByZXR1cm4gbmV3IFNoaW1Nb2RlbENsYXNzKHRoaXMsIG1vZGVsTmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIGtsYXNzOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fbW9kZWxGYWN0b3J5Rm9yID0gZnVuY3Rpb24gX21vZGVsRmFjdG9yeUZvcihtb2RlbE5hbWUpIHsKICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgdmFyIGZhY3RvcnkgPSBnZXRNb2RlbEZhY3RvcnkodGhpcywgdGhpcy5fbW9kZWxGYWN0b3J5Q2FjaGUsIG5vcm1hbGl6ZWRNb2RlbE5hbWUpOwoKICAgICAgaWYgKGZhY3RvcnkgPT09IG51bGwpIHsKICAgICAgICB0aHJvdyBuZXcgRW1iZXIuRXJyb3IoIk5vIG1vZGVsIHdhcyBmb3VuZCBmb3IgJyIgKyBub3JtYWxpemVkTW9kZWxOYW1lICsgIiciKTsKICAgICAgfQoKICAgICAgcmV0dXJuIGZhY3Rvcnk7CiAgICB9CiAgICAvKgogICAgUmV0dXJucyB3aGV0aGVyIGEgTW9kZWxDbGFzcyBleGlzdHMgZm9yIGEgZ2l2ZW4gbW9kZWxOYW1lCiAgICBUaGlzIGV4aXN0cyBmb3IgbGVnYWN5IHN1cHBvcnQgZm9yIHRoZSBSRVNUU2VyaWFsaXplciwKICAgIHdoaWNoIGR1ZSB0byBob3cgaXQgbXVzdCBndWVzcyB3aGV0aGVyIGEga2V5IGlzIGEgbW9kZWwKICAgIG11c3QgcXVlcnkgZm9yIHdoZXRoZXIgYSBtYXRjaCBleGlzdHMuCiAgICAgV2Ugc2hvdWxkIGludmVzdGlnYXRlIGFuIFJGQyB0byBtYWtlIHRoaXMgcHVibGljIG9yIHJlbW92aW5nCiAgICB0aGlzIHJlcXVpcmVtZW50LgogICAgIEBwcml2YXRlCiAgICAqLwogICAgOwoKICAgIF9wcm90by5faGFzTW9kZWxGb3IgPSBmdW5jdGlvbiBfaGFzTW9kZWxGb3IobW9kZWxOYW1lKSB7CgogICAgICBpZiAoY2FuYXJ5RmVhdHVyZXMuQ1VTVE9NX01PREVMX0NMQVNTKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UoKS5kb2VzVHlwZUV4aXN0KG1vZGVsTmFtZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFyIG5vcm1hbGl6ZWRNb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKICAgICAgICB2YXIgZmFjdG9yeSA9IGdldE1vZGVsRmFjdG9yeSh0aGlzLCB0aGlzLl9tb2RlbEZhY3RvcnlDYWNoZSwgbm9ybWFsaXplZE1vZGVsTmFtZSk7CiAgICAgICAgcmV0dXJuIGZhY3RvcnkgIT09IG51bGw7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9yZWxhdGlvbnNoaXBNZXRhRm9yID0gZnVuY3Rpb24gX3JlbGF0aW9uc2hpcE1ldGFGb3IobW9kZWxOYW1lLCBpZCwga2V5KSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICByZXR1cm4gdGhpcy5fcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IobW9kZWxOYW1lKVtrZXldOwogICAgICB9IGVsc2UgewogICAgICAgIHZhciBtb2RlbENsYXNzID0gdGhpcy5tb2RlbEZvcihtb2RlbE5hbWUpOwogICAgICAgIHZhciByZWxhdGlvbnNoaXBzQnlOYW1lID0gRW1iZXIuZ2V0KG1vZGVsQ2xhc3MsICdyZWxhdGlvbnNoaXBzQnlOYW1lJyk7CiAgICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcHNCeU5hbWUuZ2V0KGtleSk7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLl9hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvciA9IGZ1bmN0aW9uIF9hdHRyaWJ1dGVzRGVmaW5pdGlvbkZvcihtb2RlbE5hbWUsIGlkZW50aWZpZXIpIHsKICAgICAgaWYgKGNhbmFyeUZlYXR1cmVzLkNVU1RPTV9NT0RFTF9DTEFTUykgewogICAgICAgIGlmIChpZGVudGlmaWVyKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5nZXRTY2hlbWFEZWZpbml0aW9uU2VydmljZSgpLmF0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKGlkZW50aWZpZXIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5nZXRTY2hlbWFEZWZpbml0aW9uU2VydmljZSgpLmF0dHJpYnV0ZXNEZWZpbml0aW9uRm9yKG1vZGVsTmFtZSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHZhciBhdHRyaWJ1dGVzID0gdGhpcy5fYXR0cmlidXRlc0RlZkNhY2hlW21vZGVsTmFtZV07CgogICAgICAgIGlmIChhdHRyaWJ1dGVzID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHZhciBtb2RlbENsYXNzID0gdGhpcy5tb2RlbEZvcihtb2RlbE5hbWUpOwogICAgICAgICAgdmFyIGF0dHJpYnV0ZU1hcCA9IEVtYmVyLmdldChtb2RlbENsYXNzLCAnYXR0cmlidXRlcycpOwogICAgICAgICAgYXR0cmlidXRlcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgICBhdHRyaWJ1dGVNYXAuZm9yRWFjaChmdW5jdGlvbiAobWV0YSwgbmFtZSkgewogICAgICAgICAgICByZXR1cm4gYXR0cmlidXRlc1tuYW1lXSA9IG1ldGE7CiAgICAgICAgICB9KTsKICAgICAgICAgIHRoaXMuX2F0dHJpYnV0ZXNEZWZDYWNoZVttb2RlbE5hbWVdID0gYXR0cmlidXRlczsKICAgICAgICB9CgogICAgICAgIHJldHVybiBhdHRyaWJ1dGVzOwogICAgICB9CiAgICB9OwoKICAgIF9wcm90by5fcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IgPSBmdW5jdGlvbiBfcmVsYXRpb25zaGlwc0RlZmluaXRpb25Gb3IobW9kZWxOYW1lLCBpZGVudGlmaWVyKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICBpZiAoaWRlbnRpZmllcikgewogICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UoKS5yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcihpZGVudGlmaWVyKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UoKS5yZWxhdGlvbnNoaXBzRGVmaW5pdGlvbkZvcihtb2RlbE5hbWUpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgcmVsYXRpb25zaGlwcyA9IHRoaXMuX3JlbGF0aW9uc2hpcHNEZWZDYWNoZVttb2RlbE5hbWVdOwoKICAgICAgICBpZiAocmVsYXRpb25zaGlwcyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICB2YXIgbW9kZWxDbGFzcyA9IHRoaXMubW9kZWxGb3IobW9kZWxOYW1lKTsKICAgICAgICAgIHJlbGF0aW9uc2hpcHMgPSBFbWJlci5nZXQobW9kZWxDbGFzcywgJ3JlbGF0aW9uc2hpcHNPYmplY3QnKSB8fCBudWxsOwogICAgICAgICAgdGhpcy5fcmVsYXRpb25zaGlwc0RlZkNhY2hlW21vZGVsTmFtZV0gPSByZWxhdGlvbnNoaXBzOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHJlbGF0aW9uc2hpcHM7CiAgICAgIH0KICAgIH07CgogICAgX3Byb3RvLmdldFNjaGVtYURlZmluaXRpb25TZXJ2aWNlID0gZnVuY3Rpb24gZ2V0U2NoZW1hRGVmaW5pdGlvblNlcnZpY2UoKSB7CiAgICAgIGlmIChjYW5hcnlGZWF0dXJlcy5DVVNUT01fTU9ERUxfQ0xBU1MpIHsKICAgICAgICBpZiAoIXRoaXMuX3NjaGVtYURlZmluaXRpb25TZXJ2aWNlKSB7CiAgICAgICAgICB0aGlzLl9zY2hlbWFEZWZpbml0aW9uU2VydmljZSA9IG5ldyBEU01vZGVsU2NoZW1hRGVmaW5pdGlvblNlcnZpY2UodGhpcyk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gdGhpcy5fc2NoZW1hRGVmaW5pdGlvblNlcnZpY2U7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgJ3NjaGVtYSBzZXJ2aWNlIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gY3VzdG9tIG1vZGVsIGNsYXNzIGZlYXR1cmUgZmxhZyBpcyBvbic7CiAgICAgIH0KICAgIH07CgogICAgcmV0dXJuIFN0b3JlOwogIH0oQ29yZVN0b3JlKTsKCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXMkOCh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgidmFsdWUiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfQoKICBmdW5jdGlvbiBfY3JlYXRlQ2xhc3MkOChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzJDgoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyQ4KENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfQoKICAvKioKICAgIEBtb2R1bGUgQGVtYmVyLWRhdGEvc3RvcmUKICAqLwogIGZ1bmN0aW9uIHR5cGVGb3JSZWxhdGlvbnNoaXBNZXRhKG1ldGEpIHsKICAgIHZhciBtb2RlbE5hbWU7CiAgICBtb2RlbE5hbWUgPSBtZXRhLnR5cGUgfHwgbWV0YS5rZXk7CiAgICBtb2RlbE5hbWUgPSBub3JtYWxpemVNb2RlbE5hbWUobW9kZWxOYW1lKTsKCiAgICBpZiAobWV0YS5raW5kID09PSAnaGFzTWFueScpIHsKICAgICAgbW9kZWxOYW1lID0gZW1iZXJJbmZsZWN0b3Iuc2luZ3VsYXJpemUobW9kZWxOYW1lKTsKICAgIH0KCiAgICByZXR1cm4gbW9kZWxOYW1lOwogIH0KCiAgZnVuY3Rpb24gc2hvdWxkRmluZEludmVyc2UocmVsYXRpb25zaGlwTWV0YSkgewogICAgdmFyIG9wdGlvbnMgPSByZWxhdGlvbnNoaXBNZXRhLm9wdGlvbnM7CiAgICByZXR1cm4gIShvcHRpb25zICYmIG9wdGlvbnMuaW52ZXJzZSA9PT0gbnVsbCk7CiAgfQoKICB2YXIgUmVsYXRpb25zaGlwRGVmaW5pdGlvbiA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFJlbGF0aW9uc2hpcERlZmluaXRpb24obWV0YSkgewogICAgICB0aGlzLm1ldGEgPSBtZXRhOwogICAgICB0aGlzW0JSQU5EX1NZTUJPTF0gPSB2b2lkIDA7CiAgICAgIHRoaXMuX3R5cGUgPSAnJzsKICAgICAgdGhpcy5fX2ludmVyc2VLZXkgPSAnJzsKICAgICAgdGhpcy5fX2ludmVyc2VJc0FzeW5jID0gdHJ1ZTsKICAgICAgdGhpcy5fX2hhc0NhbGN1bGF0ZWRJbnZlcnNlID0gZmFsc2U7CiAgICAgIHRoaXMucGFyZW50TW9kZWxOYW1lID0gdm9pZCAwOwogICAgICB0aGlzLmludmVyc2UgPSB2b2lkIDA7CiAgICAgIHRoaXMuaW52ZXJzZUlzQXN5bmMgPSB2b2lkIDA7CiAgICAgIHRoaXMucGFyZW50TW9kZWxOYW1lID0gbWV0YS5wYXJlbnRNb2RlbE5hbWU7CiAgICB9CgogICAgdmFyIF9wcm90byA9IFJlbGF0aW9uc2hpcERlZmluaXRpb24ucHJvdG90eXBlOwoKICAgIF9wcm90by5faW52ZXJzZUtleSA9IGZ1bmN0aW9uIF9pbnZlcnNlS2V5KHN0b3JlLCBtb2RlbENsYXNzKSB7CiAgICAgIGlmICh0aGlzLl9faGFzQ2FsY3VsYXRlZEludmVyc2UgPT09IGZhbHNlKSB7CiAgICAgICAgdGhpcy5fY2FsY3VsYXRlSW52ZXJzZShzdG9yZSwgbW9kZWxDbGFzcyk7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzLl9faW52ZXJzZUtleTsKICAgIH07CgogICAgX3Byb3RvLl9pbnZlcnNlSXNBc3luYyA9IGZ1bmN0aW9uIF9pbnZlcnNlSXNBc3luYyhzdG9yZSwgbW9kZWxDbGFzcykgewogICAgICBpZiAodGhpcy5fX2hhc0NhbGN1bGF0ZWRJbnZlcnNlID09PSBmYWxzZSkgewogICAgICAgIHRoaXMuX2NhbGN1bGF0ZUludmVyc2Uoc3RvcmUsIG1vZGVsQ2xhc3MpOwogICAgICB9CgogICAgICByZXR1cm4gdGhpcy5fX2ludmVyc2VJc0FzeW5jOwogICAgfTsKCiAgICBfcHJvdG8uX2NhbGN1bGF0ZUludmVyc2UgPSBmdW5jdGlvbiBfY2FsY3VsYXRlSW52ZXJzZShzdG9yZSwgbW9kZWxDbGFzcykgewogICAgICB0aGlzLl9faGFzQ2FsY3VsYXRlZEludmVyc2UgPSB0cnVlOwogICAgICB2YXIgaW52ZXJzZUtleSwgaW52ZXJzZUlzQXN5bmM7CiAgICAgIHZhciBpbnZlcnNlID0gbnVsbDsKCiAgICAgIGlmIChzaG91bGRGaW5kSW52ZXJzZSh0aGlzLm1ldGEpKSB7CiAgICAgICAgaW52ZXJzZSA9IG1vZGVsQ2xhc3MuaW52ZXJzZUZvcih0aGlzLmtleSwgc3RvcmUpOwogICAgICB9CgogICAgICBpZiAoaW52ZXJzZSkgewogICAgICAgIGludmVyc2VLZXkgPSBpbnZlcnNlLm5hbWU7CiAgICAgICAgaW52ZXJzZUlzQXN5bmMgPSBpc0ludmVyc2VBc3luYyhpbnZlcnNlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpbnZlcnNlS2V5ID0gbnVsbDsKICAgICAgICBpbnZlcnNlSXNBc3luYyA9IGZhbHNlOwogICAgICB9CgogICAgICB0aGlzLl9faW52ZXJzZUtleSA9IGludmVyc2VLZXk7CiAgICAgIHRoaXMuX19pbnZlcnNlSXNBc3luYyA9IGludmVyc2VJc0FzeW5jOwogICAgfTsKCiAgICBfY3JlYXRlQ2xhc3MkOChSZWxhdGlvbnNoaXBEZWZpbml0aW9uLCBbewogICAgICBrZXk6ICJrZXkiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5tZXRhLmtleTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJraW5kIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMubWV0YS5raW5kOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogInR5cGUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5fdHlwZSkgewogICAgICAgICAgcmV0dXJuIHRoaXMuX3R5cGU7CiAgICAgICAgfQoKICAgICAgICB0aGlzLl90eXBlID0gdHlwZUZvclJlbGF0aW9uc2hpcE1ldGEodGhpcy5tZXRhKTsKICAgICAgICByZXR1cm4gdGhpcy5fdHlwZTsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJvcHRpb25zIiwKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMubWV0YS5vcHRpb25zOwogICAgICB9CiAgICB9LCB7CiAgICAgIGtleTogIm5hbWUiLAogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICByZXR1cm4gdGhpcy5tZXRhLm5hbWU7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gUmVsYXRpb25zaGlwRGVmaW5pdGlvbjsKICB9KCk7CgogIGZ1bmN0aW9uIGlzSW52ZXJzZUFzeW5jKG1ldGEpIHsKICAgIHZhciBpbnZlcnNlQXN5bmMgPSBtZXRhLm9wdGlvbnMgJiYgbWV0YS5vcHRpb25zLmFzeW5jOwogICAgcmV0dXJuIHR5cGVvZiBpbnZlcnNlQXN5bmMgPT09ICd1bmRlZmluZWQnID8gdHJ1ZSA6IGludmVyc2VBc3luYzsKICB9CgogIGZ1bmN0aW9uIHJlbGF0aW9uc2hpcEZyb21NZXRhKG1ldGEpIHsKICAgIHJldHVybiBuZXcgUmVsYXRpb25zaGlwRGVmaW5pdGlvbihtZXRhKTsKICB9CgogIC8qKgogICAgQG1vZHVsZSBAZW1iZXItZGF0YS9zdG9yZQogICovCgogIHZhciByZWxhdGlvbnNoaXBzRGVzY3JpcHRvciA9IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgIHZhciBtYXAgPSBuZXcgTWFwKCk7CiAgICB2YXIgcmVsYXRpb25zaGlwc0J5TmFtZSA9IEVtYmVyLmdldCh0aGlzLCAncmVsYXRpb25zaGlwc0J5TmFtZScpOyAvLyBMb29wIHRocm91Z2ggZWFjaCBjb21wdXRlZCBwcm9wZXJ0eSBvbiB0aGUgY2xhc3MKCiAgICByZWxhdGlvbnNoaXBzQnlOYW1lLmZvckVhY2goZnVuY3Rpb24gKGRlc2MpIHsKICAgICAgdmFyIHR5cGUgPSBkZXNjLnR5cGU7CgogICAgICBpZiAoIW1hcC5oYXModHlwZSkpIHsKICAgICAgICBtYXAuc2V0KHR5cGUsIFtdKTsKICAgICAgfQoKICAgICAgbWFwLmdldCh0eXBlKS5wdXNoKGRlc2MpOwogICAgfSk7CiAgICByZXR1cm4gbWFwOwogIH0pLnJlYWRPbmx5KCk7CiAgdmFyIHJlbGF0ZWRUeXBlc0Rlc2NyaXB0b3IgPSBFbWJlci5jb21wdXRlZChmdW5jdGlvbiAoKSB7CgogICAgdmFyIHBhcmVudE1vZGVsTmFtZSA9IHRoaXMubW9kZWxOYW1lOwogICAgdmFyIHR5cGVzID0gRW1iZXIuQSgpOyAvLyBMb29wIHRocm91Z2ggZWFjaCBjb21wdXRlZCBwcm9wZXJ0eSBvbiB0aGUgY2xhc3MsCiAgICAvLyBhbmQgY3JlYXRlIGFuIGFycmF5IG9mIHRoZSB1bmlxdWUgdHlwZXMgaW52b2x2ZWQKICAgIC8vIGluIHJlbGF0aW9uc2hpcHMKCiAgICB0aGlzLmVhY2hDb21wdXRlZFByb3BlcnR5KGZ1bmN0aW9uIChuYW1lLCBtZXRhKSB7CiAgICAgIGlmIChtZXRhLmlzUmVsYXRpb25zaGlwKSB7CiAgICAgICAgbWV0YS5rZXkgPSBuYW1lOwogICAgICAgIHZhciBtb2RlbE5hbWUgPSB0eXBlRm9yUmVsYXRpb25zaGlwTWV0YShtZXRhKTsKCiAgICAgICAgaWYgKCF0eXBlcy5pbmNsdWRlcyhtb2RlbE5hbWUpKSB7CiAgICAgICAgICB0eXBlcy5wdXNoKG1vZGVsTmFtZSk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICAgIHJldHVybiB0eXBlczsKICB9KS5yZWFkT25seSgpOwogIHZhciByZWxhdGlvbnNoaXBzT2JqZWN0RGVzY3JpcHRvciA9IEVtYmVyLmNvbXB1dGVkKGZ1bmN0aW9uICgpIHsKICAgIHZhciByZWxhdGlvbnNoaXBzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHZhciBtb2RlbE5hbWUgPSB0aGlzLm1vZGVsTmFtZTsKICAgIHRoaXMuZWFjaENvbXB1dGVkUHJvcGVydHkoZnVuY3Rpb24gKG5hbWUsIG1ldGEpIHsKICAgICAgaWYgKG1ldGEuaXNSZWxhdGlvbnNoaXApIHsKICAgICAgICBtZXRhLmtleSA9IG5hbWU7CiAgICAgICAgbWV0YS5uYW1lID0gbmFtZTsKICAgICAgICBtZXRhLnBhcmVudE1vZGVsTmFtZSA9IG1vZGVsTmFtZTsKICAgICAgICByZWxhdGlvbnNoaXBzW25hbWVdID0gcmVsYXRpb25zaGlwRnJvbU1ldGEobWV0YSk7CiAgICAgIH0KICAgIH0pOwogICAgcmV0dXJuIHJlbGF0aW9uc2hpcHM7CiAgfSk7CiAgdmFyIHJlbGF0aW9uc2hpcHNCeU5hbWVEZXNjcmlwdG9yID0gRW1iZXIuY29tcHV0ZWQoZnVuY3Rpb24gKCkgewogICAgdmFyIG1hcCA9IG5ldyBNYXAoKTsKICAgIHZhciByZWxzID0gRW1iZXIuZ2V0KHRoaXMsICdyZWxhdGlvbnNoaXBzT2JqZWN0Jyk7CiAgICB2YXIgcmVsYXRpb25zaGlwcyA9IE9iamVjdC5rZXlzKHJlbHMpOwoKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVsYXRpb25zaGlwcy5sZW5ndGg7IGkrKykgewogICAgICB2YXIga2V5ID0gcmVsYXRpb25zaGlwc1tpXTsKICAgICAgdmFyIHZhbHVlID0gcmVsc1trZXldOwogICAgICBtYXAuc2V0KHZhbHVlLmtleSwgdmFsdWUpOwogICAgfQoKICAgIHJldHVybiBtYXA7CiAgfSkucmVhZE9ubHkoKTsKCiAgZXhwb3J0cy5BZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXkgPSBBZGFwdGVyUG9wdWxhdGVkUmVjb3JkQXJyYXk7CiAgZXhwb3J0cy5EZXByZWNhdGVkRXZlbnRlZCA9IERlcHJlY2F0ZWRFdmVudGVkOwogIGV4cG9ydHMuRXJyb3JzID0gZXJyb3JzOwogIGV4cG9ydHMuSW50ZXJuYWxNb2RlbCA9IEludGVybmFsTW9kZWw7CiAgZXhwb3J0cy5NYW55QXJyYXkgPSBNYW55QXJyYXk7CiAgZXhwb3J0cy5Qcm9taXNlQXJyYXkgPSBQcm9taXNlQXJyYXk7CiAgZXhwb3J0cy5Qcm9taXNlTWFueUFycmF5ID0gUHJvbWlzZU1hbnlBcnJheTsKICBleHBvcnRzLlByb21pc2VPYmplY3QgPSBQcm9taXNlT2JqZWN0OwogIGV4cG9ydHMuUmVjb3JkQXJyYXkgPSBSZWNvcmRBcnJheTsKICBleHBvcnRzLlJlY29yZEFycmF5TWFuYWdlciA9IFJlY29yZEFycmF5TWFuYWdlcjsKICBleHBvcnRzLlJlY29yZERhdGFTdG9yZVdyYXBwZXIgPSBSZWNvcmREYXRhU3RvcmVXcmFwcGVyOwogIGV4cG9ydHMuUm9vdFN0YXRlID0gUm9vdFN0YXRlJDE7CiAgZXhwb3J0cy5TbmFwc2hvdCA9IFNuYXBzaG90OwogIGV4cG9ydHMuU25hcHNob3RSZWNvcmRBcnJheSA9IFNuYXBzaG90UmVjb3JkQXJyYXk7CiAgZXhwb3J0cy5TdG9yZSA9IFN0b3JlOwogIGV4cG9ydHMuX2JpbmQgPSBfYmluZDsKICBleHBvcnRzLl9ndWFyZCA9IF9ndWFyZDsKICBleHBvcnRzLl9vYmplY3RJc0FsaXZlID0gX29iamVjdElzQWxpdmU7CiAgZXhwb3J0cy5jb2VyY2VJZCA9IGNvZXJjZUlkOwogIGV4cG9ydHMuZGlmZkFycmF5ID0gZGlmZkFycmF5OwogIGV4cG9ydHMuZXJyb3JzQXJyYXlUb0hhc2ggPSBlcnJvcnNBcnJheVRvSGFzaDsKICBleHBvcnRzLmVycm9yc0hhc2hUb0FycmF5ID0gZXJyb3JzSGFzaFRvQXJyYXk7CiAgZXhwb3J0cy5ndWFyZERlc3Ryb3llZFN0b3JlID0gZ3VhcmREZXN0cm95ZWRTdG9yZTsKICBleHBvcnRzLmlkZW50aWZpZXJDYWNoZUZvciA9IGlkZW50aWZpZXJDYWNoZUZvcjsKICBleHBvcnRzLm5vcm1hbGl6ZU1vZGVsTmFtZSA9IG5vcm1hbGl6ZU1vZGVsTmFtZTsKICBleHBvcnRzLnJlY29yZERhdGFGb3IgPSByZWNvcmREYXRhRm9yOwogIGV4cG9ydHMucmVjb3JkSWRlbnRpZmllckZvciA9IHJlY29yZElkZW50aWZpZXJGb3I7CiAgZXhwb3J0cy5yZWxhdGVkVHlwZXNEZXNjcmlwdG9yID0gcmVsYXRlZFR5cGVzRGVzY3JpcHRvcjsKICBleHBvcnRzLnJlbGF0aW9uc2hpcHNCeU5hbWVEZXNjcmlwdG9yID0gcmVsYXRpb25zaGlwc0J5TmFtZURlc2NyaXB0b3I7CiAgZXhwb3J0cy5yZWxhdGlvbnNoaXBzRGVzY3JpcHRvciA9IHJlbGF0aW9uc2hpcHNEZXNjcmlwdG9yOwogIGV4cG9ydHMucmVsYXRpb25zaGlwc09iamVjdERlc2NyaXB0b3IgPSByZWxhdGlvbnNoaXBzT2JqZWN0RGVzY3JpcHRvcjsKICBleHBvcnRzLnNldElkZW50aWZpZXJGb3JnZXRNZXRob2QgPSBzZXRJZGVudGlmaWVyRm9yZ2V0TWV0aG9kOwogIGV4cG9ydHMuc2V0SWRlbnRpZmllckdlbmVyYXRpb25NZXRob2QgPSBzZXRJZGVudGlmaWVyR2VuZXJhdGlvbk1ldGhvZDsKICBleHBvcnRzLnNldElkZW50aWZpZXJSZXNldE1ldGhvZCA9IHNldElkZW50aWZpZXJSZXNldE1ldGhvZDsKICBleHBvcnRzLnNldElkZW50aWZpZXJVcGRhdGVNZXRob2QgPSBzZXRJZGVudGlmaWVyVXBkYXRlTWV0aG9kOwogIGV4cG9ydHMudXBncmFkZUZvckludGVybmFsID0gdXBncmFkZUZvckludGVybmFsOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pOwoKfSk7Cgo7ZGVmaW5lKCJAZW1iZXItZGF0YS9zdG9yZS9pbmRleCIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9zdG9yZS8tcHJpdmF0ZSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9wcml2YXRlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJkZWZhdWx0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUuU3RvcmU7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAibm9ybWFsaXplTW9kZWxOYW1lIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUubm9ybWFsaXplTW9kZWxOYW1lOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInNldElkZW50aWZpZXJHZW5lcmF0aW9uTWV0aG9kIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUuc2V0SWRlbnRpZmllckdlbmVyYXRpb25NZXRob2Q7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0SWRlbnRpZmllclVwZGF0ZU1ldGhvZCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9wcml2YXRlLnNldElkZW50aWZpZXJVcGRhdGVNZXRob2Q7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0SWRlbnRpZmllckZvcmdldE1ldGhvZCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9wcml2YXRlLnNldElkZW50aWZpZXJGb3JnZXRNZXRob2Q7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAic2V0SWRlbnRpZmllclJlc2V0TWV0aG9kIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3ByaXZhdGUuc2V0SWRlbnRpZmllclJlc2V0TWV0aG9kOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgInJlY29yZElkZW50aWZpZXJGb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfcHJpdmF0ZS5yZWNvcmRJZGVudGlmaWVyRm9yOwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgnQGVtYmVyL29yZGVyZWQtc2V0L2luZGV4JywgWydleHBvcnRzJ10sIGZ1bmN0aW9uIChleHBvcnRzKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwoKICBmdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7CiAgICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgewogICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24iKTsKICAgIH0KICB9CgogIHZhciBORUVEU19DVVNUT01fT1JERVJFRF9TRVQgPSB0cnVlOwoKICB2YXIgT3JkZXJlZFNldCA9IHZvaWQgMDsKCiAgaWYgKE5FRURTX0NVU1RPTV9PUkRFUkVEX1NFVCkgewogICAgLyoqCiAgICBAY2xhc3MgT3JkZXJlZFNldAogICAgQGNvbnN0cnVjdG9yCiAgICAqLwogICAgT3JkZXJlZFNldCA9IGZ1bmN0aW9uICgpIHsKICAgICAgZnVuY3Rpb24gT3JkZXJlZFNldCgpIHsKICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgT3JkZXJlZFNldCk7CgogICAgICAgIHRoaXMuY2xlYXIoKTsKICAgICAgfQoKICAgICAgLyoqCiAgICAgIEBtZXRob2QgY3JlYXRlCiAgICAgIEBzdGF0aWMKICAgICAgQHJldHVybiB7T3JkZXJlZFNldH0KICAgICAgKi8KCgogICAgICBPcmRlcmVkU2V0LmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSgpIHsKICAgICAgICB2YXIgQ29uc3RydWN0b3IgPSB0aGlzOwogICAgICAgIHJldHVybiBuZXcgQ29uc3RydWN0b3IoKTsKICAgICAgfTsKCiAgICAgIE9yZGVyZWRTZXQucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7CiAgICAgICAgdGhpcy5wcmVzZW5jZVNldCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgdGhpcy5saXN0ID0gW107CiAgICAgICAgdGhpcy5zaXplID0gMDsKICAgICAgfTsKCiAgICAgIE9yZGVyZWRTZXQucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uIGFkZChvYmosIF9ndWlkKSB7CiAgICAgICAgdmFyIGd1aWQgPSBfZ3VpZCB8fCBFbWJlci5ndWlkRm9yKG9iaik7CiAgICAgICAgdmFyIHByZXNlbmNlU2V0ID0gdGhpcy5wcmVzZW5jZVNldDsKICAgICAgICB2YXIgbGlzdCA9IHRoaXMubGlzdDsKCiAgICAgICAgaWYgKHByZXNlbmNlU2V0W2d1aWRdICE9PSB0cnVlKSB7CiAgICAgICAgICBwcmVzZW5jZVNldFtndWlkXSA9IHRydWU7CiAgICAgICAgICB0aGlzLnNpemUgPSBsaXN0LnB1c2gob2JqKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9OwoKICAgICAgT3JkZXJlZFNldC5wcm90b3R5cGUuZGVsZXRlID0gZnVuY3Rpb24gX2RlbGV0ZShvYmosIF9ndWlkKSB7CiAgICAgICAgdmFyIGd1aWQgPSBfZ3VpZCB8fCBFbWJlci5ndWlkRm9yKG9iaik7CiAgICAgICAgdmFyIHByZXNlbmNlU2V0ID0gdGhpcy5wcmVzZW5jZVNldDsKICAgICAgICB2YXIgbGlzdCA9IHRoaXMubGlzdDsKCiAgICAgICAgaWYgKHByZXNlbmNlU2V0W2d1aWRdID09PSB0cnVlKSB7CiAgICAgICAgICBkZWxldGUgcHJlc2VuY2VTZXRbZ3VpZF07CiAgICAgICAgICB2YXIgaW5kZXggPSBsaXN0LmluZGV4T2Yob2JqKTsKICAgICAgICAgIGlmIChpbmRleCA+IC0xKSB7CiAgICAgICAgICAgIGxpc3Quc3BsaWNlKGluZGV4LCAxKTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuc2l6ZSA9IGxpc3QubGVuZ3RoOwogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH07CgogICAgICBPcmRlcmVkU2V0LnByb3RvdHlwZS5pc0VtcHR5ID0gZnVuY3Rpb24gaXNFbXB0eSgpIHsKICAgICAgICByZXR1cm4gdGhpcy5zaXplID09PSAwOwogICAgICB9OwoKICAgICAgT3JkZXJlZFNldC5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24gaGFzKG9iaikgewogICAgICAgIGlmICh0aGlzLnNpemUgPT09IDApIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CgogICAgICAgIHZhciBndWlkID0gRW1iZXIuZ3VpZEZvcihvYmopOwogICAgICAgIHZhciBwcmVzZW5jZVNldCA9IHRoaXMucHJlc2VuY2VTZXQ7CgogICAgICAgIHJldHVybiBwcmVzZW5jZVNldFtndWlkXSA9PT0gdHJ1ZTsKICAgICAgfTsKCiAgICAgIE9yZGVyZWRTZXQucHJvdG90eXBlLmZvckVhY2ggPSBmdW5jdGlvbiBmb3JFYWNoKGZuIC8qLCAuLi50aGlzQXJnKi8pIHsKICAgICAgICAoZmFsc2UgJiYgISh0eXBlb2YgZm4gPT09ICdmdW5jdGlvbicpICYmIEVtYmVyLmFzc2VydChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZm4pICsgJyBpcyBub3QgYSBmdW5jdGlvbicsIHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJykpOwoKCiAgICAgICAgaWYgKHRoaXMuc2l6ZSA9PT0gMCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgdmFyIGxpc3QgPSB0aGlzLmxpc3Q7CgogICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyKSB7CiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgZm4uY2FsbChhcmd1bWVudHNbMV0sIGxpc3RbaV0pOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgbGlzdC5sZW5ndGg7IF9pKyspIHsKICAgICAgICAgICAgZm4obGlzdFtfaV0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfTsKCiAgICAgIE9yZGVyZWRTZXQucHJvdG90eXBlLnRvQXJyYXkgPSBmdW5jdGlvbiB0b0FycmF5KCkgewogICAgICAgIHJldHVybiB0aGlzLmxpc3Quc2xpY2UoKTsKICAgICAgfTsKCiAgICAgIE9yZGVyZWRTZXQucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiBjb3B5KCkgewogICAgICAgIHZhciBDb25zdHJ1Y3RvciA9IHRoaXMuY29uc3RydWN0b3I7CiAgICAgICAgdmFyIHNldCA9IG5ldyBDb25zdHJ1Y3RvcigpOwoKICAgICAgICBzZXQucHJlc2VuY2VTZXQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwoKICAgICAgICBmb3IgKHZhciBwcm9wIGluIHRoaXMucHJlc2VuY2VTZXQpIHsKICAgICAgICAgIC8vIGhhc093blByb3BlcnkgaXMgbm90IG5lZWRlZCBiZWNhdXNlIG9iaiBpcyBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgc2V0LnByZXNlbmNlU2V0W3Byb3BdID0gdGhpcy5wcmVzZW5jZVNldFtwcm9wXTsKICAgICAgICB9CgogICAgICAgIHNldC5saXN0ID0gdGhpcy50b0FycmF5KCk7CiAgICAgICAgc2V0LnNpemUgPSB0aGlzLnNpemU7CgogICAgICAgIHJldHVybiBzZXQ7CiAgICAgIH07CgogICAgICByZXR1cm4gT3JkZXJlZFNldDsKICAgIH0oKTsKICB9IGVsc2UgewogICAgT3JkZXJlZFNldCA9IEVtYmVyLl9fT3JkZXJlZFNldF9fIHx8IEVtYmVyLk9yZGVyZWRTZXQ7CiAgfQoKICBleHBvcnRzLmRlZmF1bHQgPSBPcmRlcmVkU2V0Owp9KTsKO2RlZmluZSgnZW1iZXItY2xpLWFwcC12ZXJzaW9uL2luaXRpYWxpemVyLWZhY3RvcnknLCBbJ2V4cG9ydHMnXSwgZnVuY3Rpb24gKGV4cG9ydHMpIHsKICAndXNlIHN0cmljdCc7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgZXhwb3J0cy5kZWZhdWx0ID0gaW5pdGlhbGl6ZXJGYWN0b3J5OwogIHZhciBsaWJyYXJpZXMgPSBFbWJlci5saWJyYXJpZXM7CiAgZnVuY3Rpb24gaW5pdGlhbGl6ZXJGYWN0b3J5KG5hbWUsIHZlcnNpb24pIHsKICAgIHZhciByZWdpc3RlcmVkID0gZmFsc2U7CgogICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgaWYgKCFyZWdpc3RlcmVkICYmIG5hbWUgJiYgdmVyc2lvbikgewogICAgICAgIHZhciBhcHBOYW1lID0gRW1iZXIuU3RyaW5nLmNsYXNzaWZ5KG5hbWUpOwogICAgICAgIGxpYnJhcmllcy5yZWdpc3RlcihhcHBOYW1lLCB2ZXJzaW9uKTsKICAgICAgICByZWdpc3RlcmVkID0gdHJ1ZTsKICAgICAgfQogICAgfTsKICB9Cn0pOwo7ZGVmaW5lKCJlbWJlci1jbGktYXBwLXZlcnNpb24vdXRpbHMvcmVnZXhwIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChleHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIHZhciB2ZXJzaW9uUmVnRXhwID0gZXhwb3J0cy52ZXJzaW9uUmVnRXhwID0gL1xkK1suXVxkK1suXVxkKy87IC8vIE1hdGNoIGFueSBudW1iZXIgb2YgMyBzZWN0aW9ucyBvZiBkaWdpdHMgc2VwYXJhdGVkIGJ5IC4KICB2YXIgdmVyc2lvbkV4dGVuZGVkUmVnRXhwID0gZXhwb3J0cy52ZXJzaW9uRXh0ZW5kZWRSZWdFeHAgPSAvXGQrWy5dXGQrWy5dXGQrLVthLXpdKihbLl1cZCspPy87IC8vIE1hdGNoIHRoZSBhYm92ZSBidXQgYWxzbyBoeXBoZW4gZm9sbG93ZWQgYnkgYW55IG51bWJlciBvZiBsb3dlcmNhc2UgbGV0dGVycywgdGhlbiBvcHRpb25hbGx5IHBlcmlvZCBhbmQgZGlnaXRzCiAgdmFyIHNoYVJlZ0V4cCA9IGV4cG9ydHMuc2hhUmVnRXhwID0gL1thLXpcZF17OH0kLzsgLy8gTWF0Y2ggOCBsb3dlcmNhc2UgbGV0dGVycyBhbmQgZGlnaXRzLCBhdCB0aGUgZW5kIG9mIHRoZSBzdHJpbmcgb25seSAodG8gYXZvaWQgbWF0Y2hpbmcgd2l0aCB2ZXJzaW9uIGV4dGVuZGVkIHBhcnQpCn0pOwo7ZGVmaW5lKCdlbWJlci1kYXRhLy1wcml2YXRlJywgWydleHBvcnRzJywgJ0BlbWJlci1kYXRhL3N0b3JlLy1wcml2YXRlJywgJ0BlbWJlci1kYXRhL3N0b3JlJywgJ2VtYmVyLWRhdGEvdmVyc2lvbicsICdAZW1iZXItZGF0YS9yZWNvcmQtZGF0YS8tcHJpdmF0ZSddLCBmdW5jdGlvbiAoZXhwb3J0cywgUHJpdmF0ZSwgc3RvcmUsIFZFUlNJT04sIFByaXZhdGUkMSkgeyAndXNlIHN0cmljdCc7CgogIHN0b3JlID0gc3RvcmUgJiYgc3RvcmUuaGFzT3duUHJvcGVydHkoJ2RlZmF1bHQnKSA/IHN0b3JlWydkZWZhdWx0J10gOiBzdG9yZTsKICBWRVJTSU9OID0gVkVSU0lPTiAmJiBWRVJTSU9OLmhhc093blByb3BlcnR5KCdkZWZhdWx0JykgPyBWRVJTSU9OWydkZWZhdWx0J10gOiBWRVJTSU9OOwoKICAvKioKICAgKiBAcHJvcGVydHkgVkVSU0lPTgogICAqIEBwdWJsaWMKICAgKiBAc3RhdGljCiAgICogQGZvciBAZW1iZXItZGF0YQogICAqLwoKICB2YXIgRFMgPSBFbWJlci5OYW1lc3BhY2UuY3JlYXRlKHsKICAgIFZFUlNJT046IFZFUlNJT04sCiAgICBuYW1lOiAnRFMnCiAgfSk7CgogIGlmIChFbWJlci5saWJyYXJpZXMpIHsKICAgIEVtYmVyLmxpYnJhcmllcy5yZWdpc3RlckNvcmVMaWJyYXJ5KCdFbWJlciBEYXRhJywgVkVSU0lPTik7CiAgfQoKICBmdW5jdGlvbiBmZWF0dXJlSXNFbmFibGVkKCkgewogICAgcmV0dXJuIEVtYmVyLkZFQVRVUkVTLmlzRW5hYmxlZC5hcHBseSh2b2lkIDAsIGFyZ3VtZW50cyk7CiAgfQoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ0FkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheScsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIFByaXZhdGUuQWRhcHRlclBvcHVsYXRlZFJlY29yZEFycmF5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnRXJyb3JzJywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5FcnJvcnM7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdJbnRlcm5hbE1vZGVsJywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5JbnRlcm5hbE1vZGVsOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnTWFueUFycmF5JywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5NYW55QXJyYXk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdQcm9taXNlQXJyYXknLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLlByb21pc2VBcnJheTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ1Byb21pc2VNYW55QXJyYXknLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLlByb21pc2VNYW55QXJyYXk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdQcm9taXNlT2JqZWN0JywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5Qcm9taXNlT2JqZWN0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnUmVjb3JkQXJyYXknLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLlJlY29yZEFycmF5OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnUmVjb3JkQXJyYXlNYW5hZ2VyJywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5SZWNvcmRBcnJheU1hbmFnZXI7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdSb290U3RhdGUnLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLlJvb3RTdGF0ZTsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ1NuYXBzaG90JywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZS5TbmFwc2hvdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ1NuYXBzaG90UmVjb3JkQXJyYXknLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLlNuYXBzaG90UmVjb3JkQXJyYXk7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdjb2VyY2VJZCcsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIFByaXZhdGUuY29lcmNlSWQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdub3JtYWxpemVNb2RlbE5hbWUnLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlLm5vcm1hbGl6ZU1vZGVsTmFtZTsKICAgIH0KICB9KTsKICBleHBvcnRzLlN0b3JlID0gc3RvcmU7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdSZWNvcmREYXRhJywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gUHJpdmF0ZSQxLlJlY29yZERhdGE7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdSZWxhdGlvbnNoaXAnLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBQcml2YXRlJDEuUmVsYXRpb25zaGlwOwogICAgfQogIH0pOwogIGV4cG9ydHMuRFMgPSBEUzsKICBleHBvcnRzLmlzRW5hYmxlZCA9IGZlYXR1cmVJc0VuYWJsZWQ7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7Cgp9KTsKCjtkZWZpbmUoImVtYmVyLWRhdGEvYWRhcHRlciIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9hZGFwdGVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2FkYXB0ZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlZmF1bHQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYWRhcHRlci5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9hZGFwdGVycy9lcnJvcnMiLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvYWRhcHRlci9lcnJvciJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lcnJvcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiQWJvcnRFcnJvciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9lcnJvci5BYm9ydEVycm9yOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkFkYXB0ZXJFcnJvciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9lcnJvci5kZWZhdWx0OwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIkNvbmZsaWN0RXJyb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZXJyb3IuQ29uZmxpY3RFcnJvcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJGb3JiaWRkZW5FcnJvciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9lcnJvci5Gb3JiaWRkZW5FcnJvcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJJbnZhbGlkRXJyb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZXJyb3IuSW52YWxpZEVycm9yOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIk5vdEZvdW5kRXJyb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZXJyb3IuTm90Rm91bmRFcnJvcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJTZXJ2ZXJFcnJvciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9lcnJvci5TZXJ2ZXJFcnJvcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJUaW1lb3V0RXJyb3IiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfZXJyb3IuVGltZW91dEVycm9yOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIlVuYXV0aG9yaXplZEVycm9yIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2Vycm9yLlVuYXV0aG9yaXplZEVycm9yOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImVycm9yc0FycmF5VG9IYXNoIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2Vycm9yLmVycm9yc0FycmF5VG9IYXNoOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImVycm9yc0hhc2hUb0FycmF5IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX2Vycm9yLmVycm9yc0hhc2hUb0FycmF5OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9hZGFwdGVycy9qc29uLWFwaSIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9hZGFwdGVyL2pzb24tYXBpIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2pzb25BcGkpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlZmF1bHQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfanNvbkFwaS5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9hZGFwdGVycy9yZXN0IiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9yZXN0KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJkZWZhdWx0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3Jlc3QuZGVmYXVsdDsKICAgIH0KICB9KTsKfSk7CjtkZWZpbmUoImVtYmVyLWRhdGEvYXR0ciIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9tb2RlbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tb2RlbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZGVmYXVsdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9tb2RlbC5hdHRyOwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9pbmRleCIsIFsiZXhwb3J0cyIsICJlbWJlci1kYXRhL3N0b3JlIiwgIkBlbWJlci1kYXRhL3N0b3JlIiwgIkBlbWJlci1kYXRhL2RlYnVnIiwgImVtYmVyLWRhdGEvLXByaXZhdGUiLCAiZW1iZXItaW5mbGVjdG9yIiwgImVtYmVyLWRhdGEvc2V0dXAtY29udGFpbmVyIiwgImVtYmVyLWRhdGEvaW5pdGlhbGl6ZS1zdG9yZS1zZXJ2aWNlIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvdHJhbnNmb3JtIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvLXByaXZhdGUiLCAiQGVtYmVyLWRhdGEvYWRhcHRlciIsICJAZW1iZXItZGF0YS9hZGFwdGVyL2pzb24tYXBpIiwgIkBlbWJlci1kYXRhL2FkYXB0ZXIvcmVzdCIsICJAZW1iZXItZGF0YS9hZGFwdGVyL2Vycm9yIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIiLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uLWFwaSIsICJAZW1iZXItZGF0YS9zZXJpYWxpemVyL2pzb24iLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9yZXN0IiwgIkBlbWJlci1kYXRhL21vZGVsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3N0b3JlLCBfc3RvcmUyLCBfZGVidWcsIF9wcml2YXRlLCBfZW1iZXJJbmZsZWN0b3IsIF9zZXR1cENvbnRhaW5lciwgX2luaXRpYWxpemVTdG9yZVNlcnZpY2UsIF90cmFuc2Zvcm0sIF9wcml2YXRlMiwgX2FkYXB0ZXIsIF9qc29uQXBpLCBfcmVzdCwgX2Vycm9yLCBfc2VyaWFsaXplciwgX2pzb25BcGkyLCBfanNvbiwgX3Jlc3QyLCBfbW9kZWwpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIGlmIChFbWJlci5WRVJTSU9OLm1hdGNoKC9eMVwuKFswLTldfDFbMC0yXSlcLi8pKSB7CiAgICB0aHJvdyBuZXcgRW1iZXIuRXJyb3IoJ0VtYmVyIERhdGEgcmVxdWlyZXMgYXQgbGVhc3QgRW1iZXIgMS4xMy4wLCBidXQgeW91IGhhdmUgJyArIEVtYmVyLlZFUlNJT04gKyAnLiBQbGVhc2UgdXBncmFkZSB5b3VyIHZlcnNpb24gb2YgRW1iZXIsIHRoZW4gdXBncmFkZSBFbWJlciBEYXRhLicpOwogIH0KCiAgX3ByaXZhdGUuRFMuU3RvcmUgPSBfc3RvcmUuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5Qcm9taXNlQXJyYXkgPSBfcHJpdmF0ZS5Qcm9taXNlQXJyYXk7CiAgX3ByaXZhdGUuRFMuUHJvbWlzZU9iamVjdCA9IF9wcml2YXRlLlByb21pc2VPYmplY3Q7CiAgX3ByaXZhdGUuRFMuUHJvbWlzZU1hbnlBcnJheSA9IF9wcml2YXRlLlByb21pc2VNYW55QXJyYXk7CiAgX3ByaXZhdGUuRFMuTW9kZWwgPSBfbW9kZWwuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5Sb290U3RhdGUgPSBfcHJpdmF0ZS5Sb290U3RhdGU7CiAgX3ByaXZhdGUuRFMuYXR0ciA9IF9tb2RlbC5hdHRyOwogIF9wcml2YXRlLkRTLkVycm9ycyA9IF9wcml2YXRlLkVycm9yczsKICBfcHJpdmF0ZS5EUy5JbnRlcm5hbE1vZGVsID0gX3ByaXZhdGUuSW50ZXJuYWxNb2RlbDsKICBfcHJpdmF0ZS5EUy5TbmFwc2hvdCA9IF9wcml2YXRlLlNuYXBzaG90OwogIF9wcml2YXRlLkRTLkFkYXB0ZXIgPSBfYWRhcHRlci5kZWZhdWx0OwogIF9wcml2YXRlLkRTLkFkYXB0ZXJFcnJvciA9IF9lcnJvci5kZWZhdWx0OwogIF9wcml2YXRlLkRTLkludmFsaWRFcnJvciA9IF9lcnJvci5JbnZhbGlkRXJyb3I7CiAgX3ByaXZhdGUuRFMuVGltZW91dEVycm9yID0gX2Vycm9yLlRpbWVvdXRFcnJvcjsKICBfcHJpdmF0ZS5EUy5BYm9ydEVycm9yID0gX2Vycm9yLkFib3J0RXJyb3I7CiAgX3ByaXZhdGUuRFMuVW5hdXRob3JpemVkRXJyb3IgPSBfZXJyb3IuVW5hdXRob3JpemVkRXJyb3I7CiAgX3ByaXZhdGUuRFMuRm9yYmlkZGVuRXJyb3IgPSBfZXJyb3IuRm9yYmlkZGVuRXJyb3I7CiAgX3ByaXZhdGUuRFMuTm90Rm91bmRFcnJvciA9IF9lcnJvci5Ob3RGb3VuZEVycm9yOwogIF9wcml2YXRlLkRTLkNvbmZsaWN0RXJyb3IgPSBfZXJyb3IuQ29uZmxpY3RFcnJvcjsKICBfcHJpdmF0ZS5EUy5TZXJ2ZXJFcnJvciA9IF9lcnJvci5TZXJ2ZXJFcnJvcjsKICBfcHJpdmF0ZS5EUy5lcnJvcnNIYXNoVG9BcnJheSA9IF9lcnJvci5lcnJvcnNIYXNoVG9BcnJheTsKICBfcHJpdmF0ZS5EUy5lcnJvcnNBcnJheVRvSGFzaCA9IF9lcnJvci5lcnJvcnNBcnJheVRvSGFzaDsKICBfcHJpdmF0ZS5EUy5TZXJpYWxpemVyID0gX3NlcmlhbGl6ZXIuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5EZWJ1Z0FkYXB0ZXIgPSBfZGVidWcuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5SZWNvcmRBcnJheSA9IF9wcml2YXRlLlJlY29yZEFycmF5OwogIF9wcml2YXRlLkRTLkFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheSA9IF9wcml2YXRlLkFkYXB0ZXJQb3B1bGF0ZWRSZWNvcmRBcnJheTsKICBfcHJpdmF0ZS5EUy5NYW55QXJyYXkgPSBfcHJpdmF0ZS5NYW55QXJyYXk7CiAgX3ByaXZhdGUuRFMuUmVjb3JkQXJyYXlNYW5hZ2VyID0gX3ByaXZhdGUuUmVjb3JkQXJyYXlNYW5hZ2VyOwogIF9wcml2YXRlLkRTLlJFU1RBZGFwdGVyID0gX3Jlc3QuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5CdWlsZFVSTE1peGluID0gX2FkYXB0ZXIuQnVpbGRVUkxNaXhpbjsKICBfcHJpdmF0ZS5EUy5SRVNUU2VyaWFsaXplciA9IF9yZXN0Mi5kZWZhdWx0OwogIF9wcml2YXRlLkRTLkpTT05TZXJpYWxpemVyID0gX2pzb24uZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5KU09OQVBJQWRhcHRlciA9IF9qc29uQXBpLmRlZmF1bHQ7CiAgX3ByaXZhdGUuRFMuSlNPTkFQSVNlcmlhbGl6ZXIgPSBfanNvbkFwaTIuZGVmYXVsdDsKICBfcHJpdmF0ZS5EUy5UcmFuc2Zvcm0gPSBfdHJhbnNmb3JtLmRlZmF1bHQ7CiAgX3ByaXZhdGUuRFMuRGF0ZVRyYW5zZm9ybSA9IF9wcml2YXRlMi5EYXRlVHJhbnNmb3JtOwogIF9wcml2YXRlLkRTLlN0cmluZ1RyYW5zZm9ybSA9IF9wcml2YXRlMi5TdHJpbmdUcmFuc2Zvcm07CiAgX3ByaXZhdGUuRFMuTnVtYmVyVHJhbnNmb3JtID0gX3ByaXZhdGUyLk51bWJlclRyYW5zZm9ybTsKICBfcHJpdmF0ZS5EUy5Cb29sZWFuVHJhbnNmb3JtID0gX3ByaXZhdGUyLkJvb2xlYW5UcmFuc2Zvcm07CiAgX3ByaXZhdGUuRFMuRW1iZWRkZWRSZWNvcmRzTWl4aW4gPSBfcmVzdDIuRW1iZWRkZWRSZWNvcmRzTWl4aW47CiAgX3ByaXZhdGUuRFMuYmVsb25nc1RvID0gX21vZGVsLmJlbG9uZ3NUbzsKICBfcHJpdmF0ZS5EUy5oYXNNYW55ID0gX21vZGVsLmhhc01hbnk7CiAgX3ByaXZhdGUuRFMuUmVsYXRpb25zaGlwID0gX3ByaXZhdGUuUmVsYXRpb25zaGlwOwogIF9wcml2YXRlLkRTLl9zZXR1cENvbnRhaW5lciA9IF9zZXR1cENvbnRhaW5lci5kZWZhdWx0OwogIF9wcml2YXRlLkRTLl9pbml0aWFsaXplU3RvcmVTZXJ2aWNlID0gX2luaXRpYWxpemVTdG9yZVNlcnZpY2UuZGVmYXVsdDsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX3ByaXZhdGUuRFMsICdub3JtYWxpemVNb2RlbE5hbWUnLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgd3JpdGFibGU6IGZhbHNlLAogICAgY29uZmlndXJhYmxlOiBmYWxzZSwKICAgIHZhbHVlOiBfc3RvcmUyLm5vcm1hbGl6ZU1vZGVsTmFtZQogIH0pOwogIHZhciBfZGVmYXVsdCA9IF9wcml2YXRlLkRTOwogIF9leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsKfSk7CjtkZWZpbmUoImVtYmVyLWRhdGEvaW5pdGlhbGl6ZS1zdG9yZS1zZXJ2aWNlIiwgWyJleHBvcnRzIl0sIGZ1bmN0aW9uIChfZXhwb3J0cykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IGluaXRpYWxpemVTdG9yZVNlcnZpY2U7CgogIC8qCiAgICBDb25maWd1cmVzIGEgcmVnaXN0cnkgZm9yIHVzZSB3aXRoIGFuIEVtYmVyLURhdGEKICAgIHN0b3JlLgogIAogICAgQG1ldGhvZCBpbml0aWFsaXplU3RvcmVTZXJ2aWNlCiAgICBAcGFyYW0ge0VtYmVyLkFwcGxpY2F0aW9uSW5zdGFuY2UgfCBFbWJlci5FbmdpbmVJbnN0YW5jZX0gaW5zdGFuY2UKICAqLwogIGZ1bmN0aW9uIGluaXRpYWxpemVTdG9yZVNlcnZpY2UoaW5zdGFuY2UpIHsKICAgIC8vIGluc3RhbmNlLmxvb2t1cCBzdXBwb3J0cyBFbWJlciAyLjEgYW5kIGhpZ2hlcgogICAgLy8gaW5zdGFuY2UuY29udGFpbmVyIHN1cHBvcnRzIEVtYmVyIDEuMTEgLSAyLjAKICAgIHZhciBjb250YWluZXIgPSBpbnN0YW5jZS5sb29rdXAgPyBpbnN0YW5jZSA6IGluc3RhbmNlLmNvbnRhaW5lcjsgLy8gRWFnZXJseSBnZW5lcmF0ZSB0aGUgc3RvcmUgc28gZGVmYXVsdFN0b3JlIGlzIHBvcHVsYXRlZC4KCiAgICBjb250YWluZXIubG9va3VwKCdzZXJ2aWNlOnN0b3JlJyk7CiAgfQp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9tb2RlbCIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9tb2RlbCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9tb2RlbCkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZGVmYXVsdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9tb2RlbC5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9yZWxhdGlvbnNoaXBzIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL21vZGVsIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX21vZGVsKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJiZWxvbmdzVG8iLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbW9kZWwuYmVsb25nc1RvOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImhhc01hbnkiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfbW9kZWwuaGFzTWFueTsKICAgIH0KICB9KTsKfSk7CjtkZWZpbmUoImVtYmVyLWRhdGEvc2VyaWFsaXplciIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9zZXJpYWxpemVyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3NlcmlhbGl6ZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlZmF1bHQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfc2VyaWFsaXplci5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9zZXJpYWxpemVycy9lbWJlZGRlZC1yZWNvcmRzLW1peGluIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9yZXN0KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJkZWZhdWx0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3Jlc3QuRW1iZWRkZWRSZWNvcmRzTWl4aW47CiAgICB9CiAgfSk7Cn0pOwo7ZGVmaW5lKCJlbWJlci1kYXRhL3NlcmlhbGl6ZXJzL2pzb24tYXBpIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvanNvbi1hcGkiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfanNvbkFwaSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZGVmYXVsdCIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF9qc29uQXBpLmRlZmF1bHQ7CiAgICB9CiAgfSk7Cn0pOwo7ZGVmaW5lKCJlbWJlci1kYXRhL3NlcmlhbGl6ZXJzL2pzb24iLCBbImV4cG9ydHMiLCAiQGVtYmVyLWRhdGEvc2VyaWFsaXplci9qc29uIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX2pzb24pIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlZmF1bHQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfanNvbi5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItZGF0YS9zZXJpYWxpemVycy9yZXN0IiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3NlcmlhbGl6ZXIvcmVzdCJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9yZXN0KSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJkZWZhdWx0IiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3Jlc3QuZGVmYXVsdDsKICAgIH0KICB9KTsKfSk7CjtkZWZpbmUoImVtYmVyLWRhdGEvc2V0dXAtY29udGFpbmVyIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3N0b3JlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3N0b3JlKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gc2V0dXBDb250YWluZXI7CgogIGZ1bmN0aW9uIGluaXRpYWxpemVTdG9yZShhcHBsaWNhdGlvbikgewogICAgLy8gd2UgY2FuIGp1c3QgdXNlIHJlZ2lzdGVyT3B0aW9uc0ZvclR5cGUgd2hlbiB3ZSBubyBsb25nZXIKICAgIC8vIHN1cHBvcnQgKGRlcHJlY2F0ZWQpIHZlcnNpb25zIG9mIEBlbWJlci90ZXN0LWhlbHBlcnMKICAgIC8vIFdlJ3JlIGlzc3VpbmcgYSAicHJpdmF0ZS1hcGkiIGRlcHJlY2F0aW9uIGZvciB1c2VycyBvZiB0aGUKICAgIC8vIGRlcHJlY2F0ZWQgQGVtYmVyL3Rlc3QtaGVscGVycyB2ZXJzaW9ucywgYnV0IHdpbGwga2VlcAogICAgLy8gdGhpcyBmb3IgYXMgbG9uZyBhcyB1bnRpbCA0LjAgYXMgbmVlZGVkCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICAmJiAhYXBwbGljYXRpb24ucmVnaXN0ZXJPcHRpb25zRm9yVHlwZSkgewogICAgICAoZmFsc2UgJiYgIShmYWxzZSkgJiYgRW1iZXIuZGVwcmVjYXRlKCJEZXByZWNhdGVkIHRlc3Qgc3ludGF4IHVzYWdlIGRldGVjdGVkIVxuXG5cdCIgKyAiVGhpcyB0ZXN0IHJlbGllcyBvbiBhIGRlcHJlY2F0ZWQgdGVzdCBzZXR1cCB0aGF0IGlzIG5vIGxvbmdlciBzdXBwb3J0ZWQgYnkgRW1iZXJEYXRhLiIgKyAiIFRvIHJlc29sdmUgdGhpcyB5b3Ugd2lsbCBuZWVkIHRvIGJlIG9uIGEgcmVjZW50IHZlcnNpb24gb2YgQGVtYmVyL3Rlc3QtaGVscGVycyIgKyAiIEFORCB5b3VyIHRlc3RzIG11c3QgdXNlIGBzZXRBcHBsaWNhdGlvbigpYCBpbnN0ZWFkIG9mIGBzZXRSZXNvbHZlcigpYCBhbmQiICsgIiBgbW9kdWxlKClgIHdpdGggYHNldHVwKlRlc3QoKWBpbnN0ZWFkIG9mIGBtb2R1bGVGb3IqKClgLiIsIGZhbHNlLCB7CiAgICAgICAgaWQ6ICdlbWJlci1kYXRhOmxlZ2FjeS10ZXN0LWhlbHBlci1zdXBwb3J0JywKICAgICAgICB1bnRpbDogJzMuMTcnCiAgICAgIH0pKTsKICAgICAgYXBwbGljYXRpb24ub3B0aW9uc0ZvclR5cGUoJ3NlcmlhbGl6ZXInLCB7CiAgICAgICAgc2luZ2xldG9uOiBmYWxzZQogICAgICB9KTsKICAgICAgYXBwbGljYXRpb24ub3B0aW9uc0ZvclR5cGUoJ2FkYXB0ZXInLCB7CiAgICAgICAgc2luZ2xldG9uOiBmYWxzZQogICAgICB9KTsKCiAgICAgIGlmICghYXBwbGljYXRpb24uaGFzKCdzZXJ2aWNlOnN0b3JlJykpIHsKICAgICAgICBhcHBsaWNhdGlvbi5yZWdpc3Rlcignc2VydmljZTpzdG9yZScsIF9zdG9yZS5kZWZhdWx0KTsKICAgICAgfQoKICAgICAgcmV0dXJuOwogICAgfQoKICAgIGFwcGxpY2F0aW9uLnJlZ2lzdGVyT3B0aW9uc0ZvclR5cGUoJ3NlcmlhbGl6ZXInLCB7CiAgICAgIHNpbmdsZXRvbjogZmFsc2UKICAgIH0pOwogICAgYXBwbGljYXRpb24ucmVnaXN0ZXJPcHRpb25zRm9yVHlwZSgnYWRhcHRlcicsIHsKICAgICAgc2luZ2xldG9uOiBmYWxzZQogICAgfSk7CgogICAgaWYgKCFhcHBsaWNhdGlvbi5oYXNSZWdpc3RyYXRpb24oJ3NlcnZpY2U6c3RvcmUnKSkgewogICAgICBhcHBsaWNhdGlvbi5yZWdpc3Rlcignc2VydmljZTpzdG9yZScsIF9zdG9yZS5kZWZhdWx0KTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGluaXRpYWxpemVTdG9yZUluamVjdGlvbnMoYXBwbGljYXRpb24pIHsKICAgIHZhciBpbmplY3QgPSBhcHBsaWNhdGlvbi5pbmplY3QgfHwgYXBwbGljYXRpb24uaW5qZWN0aW9uOwogICAgaW5qZWN0LmNhbGwoYXBwbGljYXRpb24sICdjb250cm9sbGVyJywgJ3N0b3JlJywgJ3NlcnZpY2U6c3RvcmUnKTsKICAgIGluamVjdC5jYWxsKGFwcGxpY2F0aW9uLCAncm91dGUnLCAnc3RvcmUnLCAnc2VydmljZTpzdG9yZScpOwogIH0KCiAgZnVuY3Rpb24gc2V0dXBDb250YWluZXIoYXBwbGljYXRpb24pIHsKICAgIGluaXRpYWxpemVTdG9yZUluamVjdGlvbnMoYXBwbGljYXRpb24pOwogICAgaW5pdGlhbGl6ZVN0b3JlKGFwcGxpY2F0aW9uKTsKICB9Cn0pOwo7ZGVmaW5lKCJlbWJlci1kYXRhL3N0b3JlIiwgWyJleHBvcnRzIiwgIkBlbWJlci1kYXRhL3N0b3JlIiwgIkBlbWJlci1kYXRhL3JlY29yZC1kYXRhLy1wcml2YXRlIiwgIkBlbWJlci1kYXRhL3N0b3JlLy1wcml2YXRlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3N0b3JlLCBfcHJpdmF0ZSwgX3ByaXZhdGUyKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZShzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MucHJvdG90eXBlKTsgc3ViQ2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gc3ViQ2xhc3M7IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH0KCiAgdmFyIERlZmF1bHRTdG9yZSA9CiAgLyojX19QVVJFX18qLwogIGZ1bmN0aW9uIChfU3RvcmUpIHsKICAgIF9pbmhlcml0c0xvb3NlKERlZmF1bHRTdG9yZSwgX1N0b3JlKTsKCiAgICBmdW5jdGlvbiBEZWZhdWx0U3RvcmUoKSB7CiAgICAgIHJldHVybiBfU3RvcmUuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgfQoKICAgIHZhciBfcHJvdG8gPSBEZWZhdWx0U3RvcmUucHJvdG90eXBlOwoKICAgIF9wcm90by5jcmVhdGVSZWNvcmREYXRhRm9yID0gZnVuY3Rpb24gY3JlYXRlUmVjb3JkRGF0YUZvcihtb2RlbE5hbWUsIGlkLCBjbGllbnRJZCwgc3RvcmVXcmFwcGVyKSB7CiAgICAgIGlmICh0cnVlCiAgICAgIC8qIElERU5USUZJRVJTICovCiAgICAgICkgewogICAgICAgIHZhciBpZGVudGlmaWVyID0gKDAsIF9wcml2YXRlMi5pZGVudGlmaWVyQ2FjaGVGb3IpKHRoaXMpLmdldE9yQ3JlYXRlUmVjb3JkSWRlbnRpZmllcih7CiAgICAgICAgICB0eXBlOiBtb2RlbE5hbWUsCiAgICAgICAgICBpZDogaWQsCiAgICAgICAgICBsaWQ6IGNsaWVudElkCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIG5ldyBfcHJpdmF0ZS5SZWNvcmREYXRhKGlkZW50aWZpZXIsIHN0b3JlV3JhcHBlcik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIG5ldyBfcHJpdmF0ZS5SZWNvcmREYXRhKG1vZGVsTmFtZSwgaWQsIGNsaWVudElkLCBzdG9yZVdyYXBwZXIpOwogICAgICB9CiAgICB9OwoKICAgIHJldHVybiBEZWZhdWx0U3RvcmU7CiAgfShfc3RvcmUuZGVmYXVsdCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBEZWZhdWx0U3RvcmU7Cn0pOwo7ZGVmaW5lKCJlbWJlci1kYXRhL3RyYW5zZm9ybSIsIFsiZXhwb3J0cyIsICJAZW1iZXItZGF0YS9zZXJpYWxpemVyL3RyYW5zZm9ybSJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF90cmFuc2Zvcm0pIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImRlZmF1bHQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfdHJhbnNmb3JtLmRlZmF1bHQ7CiAgICB9CiAgfSk7Cn0pOwo7ZGVmaW5lKCJlbWJlci1kYXRhL3ZlcnNpb24iLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwogIHZhciBfZGVmYXVsdCA9ICIzLjE1LjAtYWxwaGEuMSI7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0Owp9KTsKO2RlZmluZSgnZW1iZXItaW5mbGVjdG9yL2luZGV4JywgWydleHBvcnRzJywgJ2VtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtJywgJ2VtYmVyLWluZmxlY3Rvci9saWIvZXh0L3N0cmluZyddLCBmdW5jdGlvbiAoZXhwb3J0cywgX3N5c3RlbSkgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLmRlZmF1bHRSdWxlcyA9IGV4cG9ydHMuc2luZ3VsYXJpemUgPSBleHBvcnRzLnBsdXJhbGl6ZSA9IHVuZGVmaW5lZDsKCgogIF9zeXN0ZW0uSW5mbGVjdG9yLmRlZmF1bHRSdWxlcyA9IF9zeXN0ZW0uZGVmYXVsdFJ1bGVzOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRW1iZXIsICdJbmZsZWN0b3InLCB7CiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgRW1iZXIuZGVwcmVjYXRlKCdFbWJlci5JbmZsZWN0b3IgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGV4cGxpY2l0bHk6IGltcG9ydCBJbmZsZWN0b3IgZnJvbSBcJ2VtYmVyLWluZmxlY3RvclwnOycsIGZhbHNlLCB7CiAgICAgICAgaWQ6ICdlbWJlci1pbmZsZWN0b3IuZ2xvYmFscycsCiAgICAgICAgdW50aWw6ICczLjAuMCcKICAgICAgfSk7CgogICAgICByZXR1cm4gX3N5c3RlbS5JbmZsZWN0b3I7CiAgICB9CiAgfSwgeyBjb25maWd1cmFibGU6IHRydWUgfSk7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFbWJlci5TdHJpbmcsICdzaW5ndWxhcml6ZScsIHsKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICBFbWJlci5kZXByZWNhdGUoJ0VtYmVyLlN0cmluZy5zaW5ndWxhcml6ZSgpIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSBleHBsaWNpdGx5OiBpbXBvcnQgeyBzaW5ndWxhcml6ZSB9IGZyb20gXCdlbWJlci1pbmZsZWN0b3JcJzsnLCBmYWxzZSwgewogICAgICAgIGlkOiAnZW1iZXItaW5mbGVjdG9yLmdsb2JhbHMnLAogICAgICAgIHVudGlsOiAnMy4wLjAnCiAgICAgIH0pOwoKICAgICAgcmV0dXJuIF9zeXN0ZW0uc2luZ3VsYXJpemU7CiAgICB9CiAgfSwgeyBjb25maWd1cmFibGU6IHRydWUgfSk7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFbWJlci5TdHJpbmcsICdwbHVyYWxpemUnLCB7CiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgRW1iZXIuZGVwcmVjYXRlKCdFbWJlci5TdHJpbmcucGx1cmFsaXplKCkgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGV4cGxpY2l0bHk6IGltcG9ydCB7IHBsdXJhbGl6ZSB9IGZyb20gXCdlbWJlci1pbmZsZWN0b3JcJzsnLCBmYWxzZSwgewogICAgICAgIGlkOiAnZW1iZXItaW5mbGVjdG9yLmdsb2JhbHMnLAogICAgICAgIHVudGlsOiAnMy4wLjAnCiAgICAgIH0pOwoKICAgICAgcmV0dXJuIF9zeXN0ZW0ucGx1cmFsaXplOwogICAgfQogIH0sIHsgY29uZmlndXJhYmxlOiB0cnVlIH0pOwoKICBleHBvcnRzLmRlZmF1bHQgPSBfc3lzdGVtLkluZmxlY3RvcjsKICBleHBvcnRzLnBsdXJhbGl6ZSA9IF9zeXN0ZW0ucGx1cmFsaXplOwogIGV4cG9ydHMuc2luZ3VsYXJpemUgPSBfc3lzdGVtLnNpbmd1bGFyaXplOwogIGV4cG9ydHMuZGVmYXVsdFJ1bGVzID0gX3N5c3RlbS5kZWZhdWx0UnVsZXM7Cn0pOwo7ZGVmaW5lKCdlbWJlci1pbmZsZWN0b3IvbGliL2V4dC9zdHJpbmcnLCBbJ2VtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtL3N0cmluZyddLCBmdW5jdGlvbiAoX3N0cmluZykgewogICd1c2Ugc3RyaWN0JzsKCiAgaWYgKEVtYmVyLkVOVi5FWFRFTkRfUFJPVE9UWVBFUyA9PT0gdHJ1ZSB8fCBFbWJlci5FTlYuRVhURU5EX1BST1RPVFlQRVMuU3RyaW5nKSB7CiAgICAvKioKICAgICAgU2VlIHt7I2Nyb3NzTGluayAiRW1iZXIuU3RyaW5nL3BsdXJhbGl6ZSJ9fXt7L2Nyb3NzTGlua319CiAgICAgICBAbWV0aG9kIHBsdXJhbGl6ZQogICAgICBAZm9yIFN0cmluZwogICAgKi8KICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShTdHJpbmcucHJvdG90eXBlLCAncGx1cmFsaXplJywgewogICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgICBFbWJlci5kZXByZWNhdGUoJ1N0cmluZy5wcm90b3R5cGUucGx1cmFsaXplKCkgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGV4cGxpY2l0bHk6IGltcG9ydCB7IHBsdXJhbGl6ZSB9IGZyb20gXCdlbWJlci1pbmZsZWN0b3JcJzsnLCBmYWxzZSwgewogICAgICAgICAgaWQ6ICdlbWJlci1pbmZsZWN0b3IuZ2xvYmFscycsCiAgICAgICAgICB1bnRpbDogJzMuMC4wJwogICAgICAgIH0pOwoKICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgICAgcmV0dXJuICgwLCBfc3RyaW5nLnBsdXJhbGl6ZSkodGhpcyk7CiAgICAgICAgfTsKICAgICAgfQogICAgfSwgeyBjb25maWd1cmFibGU6IHRydWUgfSk7CgogICAgLyoqCiAgICAgIFNlZSB7eyNjcm9zc0xpbmsgIkVtYmVyLlN0cmluZy9zaW5ndWxhcml6ZSJ9fXt7L2Nyb3NzTGlua319CiAgICAgICBAbWV0aG9kIHNpbmd1bGFyaXplCiAgICAgIEBmb3IgU3RyaW5nCiAgICAqLwogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFN0cmluZy5wcm90b3R5cGUsICdzaW5ndWxhcml6ZScsIHsKICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgICAgRW1iZXIuZGVwcmVjYXRlKCdTdHJpbmcucHJvdG90eXBlLnNpbmd1bGFyaXplKCkgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIGV4cGxpY2l0bHk6IGltcG9ydCB7IHNpbmd1bGFyaXplIH0gZnJvbSBcJ2VtYmVyLWluZmxlY3RvclwnOycsIGZhbHNlLCB7CiAgICAgICAgICBpZDogJ2VtYmVyLWluZmxlY3Rvci5nbG9iYWxzJywKICAgICAgICAgIHVudGlsOiAnMy4wLjAnCiAgICAgICAgfSk7CgogICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gKDAsIF9zdHJpbmcuc2luZ3VsYXJpemUpKHRoaXMpOwogICAgICAgIH07CiAgICAgIH0KICAgIH0sIHsgY29uZmlndXJhYmxlOiB0cnVlIH0pOwogIH0KfSk7CjtkZWZpbmUoJ2VtYmVyLWluZmxlY3Rvci9saWIvaGVscGVycy9wbHVyYWxpemUnLCBbJ2V4cG9ydHMnLCAnZW1iZXItaW5mbGVjdG9yJywgJ2VtYmVyLWluZmxlY3Rvci9saWIvdXRpbHMvbWFrZS1oZWxwZXInXSwgZnVuY3Rpb24gKGV4cG9ydHMsIF9lbWJlckluZmxlY3RvciwgX21ha2VIZWxwZXIpIHsKICAndXNlIHN0cmljdCc7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CgogIGZ1bmN0aW9uIF90b0NvbnN1bWFibGVBcnJheShhcnIpIHsKICAgIGlmIChBcnJheS5pc0FycmF5KGFycikpIHsKICAgICAgZm9yICh2YXIgaSA9IDAsIGFycjIgPSBBcnJheShhcnIubGVuZ3RoKTsgaSA8IGFyci5sZW5ndGg7IGkrKykgewogICAgICAgIGFycjJbaV0gPSBhcnJbaV07CiAgICAgIH0KCiAgICAgIHJldHVybiBhcnIyOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIEFycmF5LmZyb20oYXJyKTsKICAgIH0KICB9CgogIGV4cG9ydHMuZGVmYXVsdCA9ICgwLCBfbWFrZUhlbHBlci5kZWZhdWx0KShmdW5jdGlvbiAocGFyYW1zLCBoYXNoKSB7CiAgICB2YXIgZnVsbFBhcmFtcyA9IG5ldyAoRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQuYXBwbHkoQXJyYXksIFtudWxsXS5jb25jYXQoX3RvQ29uc3VtYWJsZUFycmF5KHBhcmFtcykpKSkoKTsKCiAgICBpZiAoZnVsbFBhcmFtcy5sZW5ndGggPT09IDIpIHsKICAgICAgZnVsbFBhcmFtcy5wdXNoKHsgd2l0aG91dENvdW50OiBoYXNoWyJ3aXRob3V0LWNvdW50Il0gfSk7CiAgICB9CgogICAgcmV0dXJuIF9lbWJlckluZmxlY3Rvci5wbHVyYWxpemUuYXBwbHkodW5kZWZpbmVkLCBfdG9Db25zdW1hYmxlQXJyYXkoZnVsbFBhcmFtcykpOwogIH0pOwp9KTsKO2RlZmluZSgnZW1iZXItaW5mbGVjdG9yL2xpYi9oZWxwZXJzL3Npbmd1bGFyaXplJywgWydleHBvcnRzJywgJ2VtYmVyLWluZmxlY3RvcicsICdlbWJlci1pbmZsZWN0b3IvbGliL3V0aWxzL21ha2UtaGVscGVyJ10sIGZ1bmN0aW9uIChleHBvcnRzLCBfZW1iZXJJbmZsZWN0b3IsIF9tYWtlSGVscGVyKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIGV4cG9ydHMuZGVmYXVsdCA9ICgwLCBfbWFrZUhlbHBlci5kZWZhdWx0KShmdW5jdGlvbiAocGFyYW1zKSB7CiAgICByZXR1cm4gKDAsIF9lbWJlckluZmxlY3Rvci5zaW5ndWxhcml6ZSkocGFyYW1zWzBdKTsKICB9KTsKfSk7CjtkZWZpbmUoImVtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtIiwgWyJleHBvcnRzIiwgImVtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtL2luZmxlY3RvciIsICJlbWJlci1pbmZsZWN0b3IvbGliL3N5c3RlbS9zdHJpbmciLCAiZW1iZXItaW5mbGVjdG9yL2xpYi9zeXN0ZW0vaW5mbGVjdGlvbnMiXSwgZnVuY3Rpb24gKGV4cG9ydHMsIF9pbmZsZWN0b3IsIF9zdHJpbmcsIF9pbmZsZWN0aW9ucykgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLmRlZmF1bHRSdWxlcyA9IGV4cG9ydHMucGx1cmFsaXplID0gZXhwb3J0cy5zaW5ndWxhcml6ZSA9IGV4cG9ydHMuSW5mbGVjdG9yID0gdW5kZWZpbmVkOwoKCiAgX2luZmxlY3Rvci5kZWZhdWx0LmluZmxlY3RvciA9IG5ldyBfaW5mbGVjdG9yLmRlZmF1bHQoX2luZmxlY3Rpb25zLmRlZmF1bHQpOwoKICBleHBvcnRzLkluZmxlY3RvciA9IF9pbmZsZWN0b3IuZGVmYXVsdDsKICBleHBvcnRzLnNpbmd1bGFyaXplID0gX3N0cmluZy5zaW5ndWxhcml6ZTsKICBleHBvcnRzLnBsdXJhbGl6ZSA9IF9zdHJpbmcucGx1cmFsaXplOwogIGV4cG9ydHMuZGVmYXVsdFJ1bGVzID0gX2luZmxlY3Rpb25zLmRlZmF1bHQ7Cn0pOwo7ZGVmaW5lKCdlbWJlci1pbmZsZWN0b3IvbGliL3N5c3RlbS9pbmZsZWN0aW9ucycsIFsnZXhwb3J0cyddLCBmdW5jdGlvbiAoZXhwb3J0cykgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLmRlZmF1bHQgPSB7CiAgICBwbHVyYWxzOiBbWy8kLywgJ3MnXSwgWy9zJC9pLCAncyddLCBbL14oYXh8dGVzdClpcyQvaSwgJyQxZXMnXSwgWy8ob2N0b3B8dmlyKXVzJC9pLCAnJDFpJ10sIFsvKG9jdG9wfHZpcilpJC9pLCAnJDFpJ10sIFsvKGFsaWFzfHN0YXR1c3xib251cykkL2ksICckMWVzJ10sIFsvKGJ1KXMkL2ksICckMXNlcyddLCBbLyhidWZmYWx8dG9tYXQpbyQvaSwgJyQxb2VzJ10sIFsvKFt0aV0pdW0kL2ksICckMWEnXSwgWy8oW3RpXSlhJC9pLCAnJDFhJ10sIFsvc2lzJC9pLCAnc2VzJ10sIFsvKD86KFteZl0pZmV8KFtscl0pZikkL2ksICckMSQydmVzJ10sIFsvKGhpdmUpJC9pLCAnJDFzJ10sIFsvKFteYWVpb3V5XXxxdSl5JC9pLCAnJDFpZXMnXSwgWy8oeHxjaHxzc3xzaCkkL2ksICckMWVzJ10sIFsvKG1hdHJ8dmVydHxpbmQpKD86aXh8ZXgpJC9pLCAnJDFpY2VzJ10sIFsvXihtfGwpb3VzZSQvaSwgJyQxaWNlJ10sIFsvXihtfGwpaWNlJC9pLCAnJDFpY2UnXSwgWy9eKG94KSQvaSwgJyQxZW4nXSwgWy9eKG94ZW4pJC9pLCAnJDEnXSwgWy8ocXVpeikkL2ksICckMXplcyddXSwKCiAgICBzaW5ndWxhcjogW1svcyQvaSwgJyddLCBbLyhzcykkL2ksICckMSddLCBbLyhuKWV3cyQvaSwgJyQxZXdzJ10sIFsvKFt0aV0pYSQvaSwgJyQxdW0nXSwgWy8oKGEpbmFseXwoYilhfChkKWlhZ25vfChwKWFyZW50aGV8KHApcm9nbm98KHMpeW5vcHwodCloZSkoc2lzfHNlcykkL2ksICckMXNpcyddLCBbLyheYW5hbHkpKHNpc3xzZXMpJC9pLCAnJDFzaXMnXSwgWy8oW15mXSl2ZXMkL2ksICckMWZlJ10sIFsvKGhpdmUpcyQvaSwgJyQxJ10sIFsvKHRpdmUpcyQvaSwgJyQxJ10sIFsvKFtscl0pdmVzJC9pLCAnJDFmJ10sIFsvKFteYWVpb3V5XXxxdSlpZXMkL2ksICckMXknXSwgWy8ocyllcmllcyQvaSwgJyQxZXJpZXMnXSwgWy8obSlvdmllcyQvaSwgJyQxb3ZpZSddLCBbLyh4fGNofHNzfHNoKWVzJC9pLCAnJDEnXSwgWy9eKG18bClpY2UkL2ksICckMW91c2UnXSwgWy8oYnVzKShlcyk/JC9pLCAnJDEnXSwgWy8obyllcyQvaSwgJyQxJ10sIFsvKHNob2UpcyQvaSwgJyQxJ10sIFsvKGNyaXN8dGVzdCkoaXN8ZXMpJC9pLCAnJDFpcyddLCBbL14oYSl4W2llXXMkL2ksICckMXhpcyddLCBbLyhvY3RvcHx2aXIpKHVzfGkpJC9pLCAnJDF1cyddLCBbLyhhbGlhc3xzdGF0dXN8Ym9udXMpKGVzKT8kL2ksICckMSddLCBbL14ob3gpZW4vaSwgJyQxJ10sIFsvKHZlcnR8aW5kKWljZXMkL2ksICckMWV4J10sIFsvKG1hdHIpaWNlcyQvaSwgJyQxaXgnXSwgWy8ocXVpeil6ZXMkL2ksICckMSddLCBbLyhkYXRhYmFzZSlzJC9pLCAnJDEnXV0sCgogICAgaXJyZWd1bGFyUGFpcnM6IFtbJ3BlcnNvbicsICdwZW9wbGUnXSwgWydtYW4nLCAnbWVuJ10sIFsnY2hpbGQnLCAnY2hpbGRyZW4nXSwgWydzZXgnLCAnc2V4ZXMnXSwgWydtb3ZlJywgJ21vdmVzJ10sIFsnY293JywgJ2tpbmUnXSwgWyd6b21iaWUnLCAnem9tYmllcyddXSwKCiAgICB1bmNvdW50YWJsZTogWydlcXVpcG1lbnQnLCAnaW5mb3JtYXRpb24nLCAncmljZScsICdtb25leScsICdzcGVjaWVzJywgJ3NlcmllcycsICdmaXNoJywgJ3NoZWVwJywgJ2plYW5zJywgJ3BvbGljZSddCiAgfTsKfSk7CjtkZWZpbmUoJ2VtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtL2luZmxlY3RvcicsIFsnZXhwb3J0cyddLCBmdW5jdGlvbiAoZXhwb3J0cykgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKCgogIHZhciBCTEFOS19SRUdFWCA9IC9eXHMqJC87CiAgdmFyIExBU1RfV09SRF9EQVNIRURfUkVHRVggPSAvKFtcdy8tXStbXy9ccy1dKShbYS16XGRdKyQpLzsKICB2YXIgTEFTVF9XT1JEX0NBTUVMSVpFRF9SRUdFWCA9IC8oW1x3L1xzLV0rKShbQS1aXVthLXpcZF0qJCkvOwogIHZhciBDQU1FTElaRURfUkVHRVggPSAvW0EtWl1bYS16XGRdKiQvOwoKICBmdW5jdGlvbiBsb2FkVW5jb3VudGFibGUocnVsZXMsIHVuY291bnRhYmxlKSB7CiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gdW5jb3VudGFibGUubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgcnVsZXMudW5jb3VudGFibGVbdW5jb3VudGFibGVbaV0udG9Mb3dlckNhc2UoKV0gPSB0cnVlOwogICAgfQogIH0KCiAgZnVuY3Rpb24gbG9hZElycmVndWxhcihydWxlcywgaXJyZWd1bGFyUGFpcnMpIHsKICAgIHZhciBwYWlyID0gdm9pZCAwOwoKICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBpcnJlZ3VsYXJQYWlycy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBwYWlyID0gaXJyZWd1bGFyUGFpcnNbaV07CgogICAgICAvL3BsdXJhbGl6aW5nCiAgICAgIHJ1bGVzLmlycmVndWxhcltwYWlyWzBdLnRvTG93ZXJDYXNlKCldID0gcGFpclsxXTsKICAgICAgcnVsZXMuaXJyZWd1bGFyW3BhaXJbMV0udG9Mb3dlckNhc2UoKV0gPSBwYWlyWzFdOwoKICAgICAgLy9zaW5ndWxhcml6aW5nCiAgICAgIHJ1bGVzLmlycmVndWxhckludmVyc2VbcGFpclsxXS50b0xvd2VyQ2FzZSgpXSA9IHBhaXJbMF07CiAgICAgIHJ1bGVzLmlycmVndWxhckludmVyc2VbcGFpclswXS50b0xvd2VyQ2FzZSgpXSA9IHBhaXJbMF07CiAgICB9CiAgfQoKICAvKioKICAgIEluZmxlY3Rvci5FbWJlciBwcm92aWRlcyBhIG1lY2hhbmlzbSBmb3Igc3VwcGx5aW5nIGluZmxlY3Rpb24gcnVsZXMgZm9yIHlvdXIKICAgIGFwcGxpY2F0aW9uLiBFbWJlciBpbmNsdWRlcyBhIGRlZmF1bHQgc2V0IG9mIGluZmxlY3Rpb24gcnVsZXMsIGFuZCBwcm92aWRlcyBhbgogICAgQVBJIGZvciBwcm92aWRpbmcgYWRkaXRpb25hbCBydWxlcy4KICAKICAgIEV4YW1wbGVzOgogIAogICAgQ3JlYXRpbmcgYW4gaW5mbGVjdG9yIHdpdGggbm8gcnVsZXMuCiAgCiAgICBgYGBqcwogICAgdmFyIGluZmxlY3RvciA9IG5ldyBFbWJlci5JbmZsZWN0b3IoKTsKICAgIGBgYAogIAogICAgQ3JlYXRpbmcgYW4gaW5mbGVjdG9yIHdpdGggdGhlIGRlZmF1bHQgZW1iZXIgcnVsZXNldC4KICAKICAgIGBgYGpzCiAgICB2YXIgaW5mbGVjdG9yID0gbmV3IEVtYmVyLkluZmxlY3RvcihFbWJlci5JbmZsZWN0b3IuZGVmYXVsdFJ1bGVzKTsKICAKICAgIGluZmxlY3Rvci5wbHVyYWxpemUoJ2NvdycpOyAvLz0+ICdraW5lJwogICAgaW5mbGVjdG9yLnNpbmd1bGFyaXplKCdraW5lJyk7IC8vPT4gJ2NvdycKICAgIGBgYAogIAogICAgQ3JlYXRpbmcgYW4gaW5mbGVjdG9yIGFuZCBhZGRpbmcgcnVsZXMgbGF0ZXIuCiAgCiAgICBgYGBqYXZhc2NyaXB0CiAgICB2YXIgaW5mbGVjdG9yID0gRW1iZXIuSW5mbGVjdG9yLmluZmxlY3RvcjsKICAKICAgIGluZmxlY3Rvci5wbHVyYWxpemUoJ2FkdmljZScpOyAvLyA9PiAnYWR2aWNlcycKICAgIGluZmxlY3Rvci51bmNvdW50YWJsZSgnYWR2aWNlJyk7CiAgICBpbmZsZWN0b3IucGx1cmFsaXplKCdhZHZpY2UnKTsgLy8gPT4gJ2FkdmljZScKICAKICAgIGluZmxlY3Rvci5wbHVyYWxpemUoJ2Zvcm11bGEnKTsgLy8gPT4gJ2Zvcm11bGFzJwogICAgaW5mbGVjdG9yLmlycmVndWxhcignZm9ybXVsYScsICdmb3JtdWxhZScpOwogICAgaW5mbGVjdG9yLnBsdXJhbGl6ZSgnZm9ybXVsYScpOyAvLyA9PiAnZm9ybXVsYWUnCiAgCiAgICAvLyB5b3Ugd291bGQgbm90IG5lZWQgdG8gYWRkIHRoZXNlIGFzIHRoZXkgYXJlIHRoZSBkZWZhdWx0IHJ1bGVzCiAgICBpbmZsZWN0b3IucGx1cmFsKC8kLywgJ3MnKTsKICAgIGluZmxlY3Rvci5zaW5ndWxhcigvcyQvaSwgJycpOwogICAgYGBgCiAgCiAgICBDcmVhdGluZyBhbiBpbmZsZWN0b3Igd2l0aCBhIG5vbmRlZmF1bHQgcnVsZXNldC4KICAKICAgIGBgYGphdmFzY3JpcHQKICAgIHZhciBydWxlcyA9IHsKICAgICAgcGx1cmFsczogIFsKICAgICAgICBbIC8kLywgJ3MnIF0KICAgICAgXSwKICAgICAgc2luZ3VsYXI6IFsKICAgICAgICBbIC9ccyQvLCAnJyBdCiAgICAgIF0sCiAgICAgIGlycmVndWxhclBhaXJzOiBbCiAgICAgICAgWyAnY293JywgJ2tpbmUnIF0KICAgICAgXSwKICAgICAgdW5jb3VudGFibGU6IFsgJ2Zpc2gnIF0KICAgIH07CiAgCiAgICB2YXIgaW5mbGVjdG9yID0gbmV3IEVtYmVyLkluZmxlY3RvcihydWxlcyk7CiAgICBgYGAKICAKICAgIEBjbGFzcyBJbmZsZWN0b3IKICAgIEBuYW1lc3BhY2UgRW1iZXIKICAqLwogIGZ1bmN0aW9uIEluZmxlY3RvcihydWxlU2V0KSB7CiAgICBydWxlU2V0ID0gcnVsZVNldCB8fCB7fTsKICAgIHJ1bGVTZXQudW5jb3VudGFibGUgPSBydWxlU2V0LnVuY291bnRhYmxlIHx8IG1ha2VEaWN0aW9uYXJ5KCk7CiAgICBydWxlU2V0LmlycmVndWxhclBhaXJzID0gcnVsZVNldC5pcnJlZ3VsYXJQYWlycyB8fCBtYWtlRGljdGlvbmFyeSgpOwoKICAgIHZhciBydWxlcyA9IHRoaXMucnVsZXMgPSB7CiAgICAgIHBsdXJhbHM6IHJ1bGVTZXQucGx1cmFscyB8fCBbXSwKICAgICAgc2luZ3VsYXI6IHJ1bGVTZXQuc2luZ3VsYXIgfHwgW10sCiAgICAgIGlycmVndWxhcjogbWFrZURpY3Rpb25hcnkoKSwKICAgICAgaXJyZWd1bGFySW52ZXJzZTogbWFrZURpY3Rpb25hcnkoKSwKICAgICAgdW5jb3VudGFibGU6IG1ha2VEaWN0aW9uYXJ5KCkKICAgIH07CgogICAgbG9hZFVuY291bnRhYmxlKHJ1bGVzLCBydWxlU2V0LnVuY291bnRhYmxlKTsKICAgIGxvYWRJcnJlZ3VsYXIocnVsZXMsIHJ1bGVTZXQuaXJyZWd1bGFyUGFpcnMpOwoKICAgIHRoaXMuZW5hYmxlQ2FjaGUoKTsKICB9CgogIGlmICghT2JqZWN0LmNyZWF0ZSAmJiAhT2JqZWN0LmNyZWF0ZShudWxsKS5oYXNPd25Qcm9wZXJ0eSkgewogICAgdGhyb3cgbmV3IEVycm9yKCJUaGlzIGJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBPYmplY3QuY3JlYXRlKG51bGwpLCBwbGVhc2UgcG9seWZpbCB3aXRoIGVzNS1zaGFtOiBodHRwOi8vZ2l0LmlvL3lCVTJyZyIpOwogIH0KCiAgZnVuY3Rpb24gbWFrZURpY3Rpb25hcnkoKSB7CiAgICB2YXIgY2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgY2FjaGVbJ19kaWN0J10gPSBudWxsOwogICAgZGVsZXRlIGNhY2hlWydfZGljdCddOwogICAgcmV0dXJuIGNhY2hlOwogIH0KCiAgSW5mbGVjdG9yLnByb3RvdHlwZSA9IHsKICAgIGVuYWJsZUNhY2hlOiBmdW5jdGlvbiBlbmFibGVDYWNoZSgpIHsKICAgICAgdGhpcy5wdXJnZUNhY2hlKCk7CgogICAgICB0aGlzLnNpbmd1bGFyaXplID0gZnVuY3Rpb24gKHdvcmQpIHsKICAgICAgICB0aGlzLl9jYWNoZVVzZWQgPSB0cnVlOwogICAgICAgIHJldHVybiB0aGlzLl9zQ2FjaGVbd29yZF0gfHwgKHRoaXMuX3NDYWNoZVt3b3JkXSA9IHRoaXMuX3Npbmd1bGFyaXplKHdvcmQpKTsKICAgICAgfTsKCiAgICAgIHRoaXMucGx1cmFsaXplID0gZnVuY3Rpb24gKG51bWJlck9yV29yZCwgd29yZCkgewogICAgICAgIHZhciBvcHRpb25zID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiB7fTsKCiAgICAgICAgdGhpcy5fY2FjaGVVc2VkID0gdHJ1ZTsKICAgICAgICB2YXIgY2FjaGVLZXkgPSBbbnVtYmVyT3JXb3JkLCB3b3JkLCBvcHRpb25zLndpdGhvdXRDb3VudF07CiAgICAgICAgcmV0dXJuIHRoaXMuX3BDYWNoZVtjYWNoZUtleV0gfHwgKHRoaXMuX3BDYWNoZVtjYWNoZUtleV0gPSB0aGlzLl9wbHVyYWxpemUobnVtYmVyT3JXb3JkLCB3b3JkLCBvcHRpb25zKSk7CiAgICAgIH07CiAgICB9LAogICAgcHVyZ2VDYWNoZTogZnVuY3Rpb24gcHVyZ2VDYWNoZSgpIHsKICAgICAgdGhpcy5fY2FjaGVVc2VkID0gZmFsc2U7CiAgICAgIHRoaXMuX3NDYWNoZSA9IG1ha2VEaWN0aW9uYXJ5KCk7CiAgICAgIHRoaXMuX3BDYWNoZSA9IG1ha2VEaWN0aW9uYXJ5KCk7CiAgICB9LAogICAgZGlzYWJsZUNhY2hlOiBmdW5jdGlvbiBkaXNhYmxlQ2FjaGUoKSB7CiAgICAgIHRoaXMuX3NDYWNoZSA9IG51bGw7CiAgICAgIHRoaXMuX3BDYWNoZSA9IG51bGw7CiAgICAgIHRoaXMuc2luZ3VsYXJpemUgPSBmdW5jdGlvbiAod29yZCkgewogICAgICAgIHJldHVybiB0aGlzLl9zaW5ndWxhcml6ZSh3b3JkKTsKICAgICAgfTsKCiAgICAgIHRoaXMucGx1cmFsaXplID0gZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiB0aGlzLl9wbHVyYWxpemUuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgICAgfTsKICAgIH0sCiAgICBwbHVyYWw6IGZ1bmN0aW9uIHBsdXJhbChyZWdleCwgc3RyaW5nKSB7CiAgICAgIGlmICh0aGlzLl9jYWNoZVVzZWQpIHsKICAgICAgICB0aGlzLnB1cmdlQ2FjaGUoKTsKICAgICAgfQogICAgICB0aGlzLnJ1bGVzLnBsdXJhbHMucHVzaChbcmVnZXgsIHN0cmluZy50b0xvd2VyQ2FzZSgpXSk7CiAgICB9LAogICAgc2luZ3VsYXI6IGZ1bmN0aW9uIHNpbmd1bGFyKHJlZ2V4LCBzdHJpbmcpIHsKICAgICAgaWYgKHRoaXMuX2NhY2hlVXNlZCkgewogICAgICAgIHRoaXMucHVyZ2VDYWNoZSgpOwogICAgICB9CiAgICAgIHRoaXMucnVsZXMuc2luZ3VsYXIucHVzaChbcmVnZXgsIHN0cmluZy50b0xvd2VyQ2FzZSgpXSk7CiAgICB9LAogICAgdW5jb3VudGFibGU6IGZ1bmN0aW9uIHVuY291bnRhYmxlKHN0cmluZykgewogICAgICBpZiAodGhpcy5fY2FjaGVVc2VkKSB7CiAgICAgICAgdGhpcy5wdXJnZUNhY2hlKCk7CiAgICAgIH0KICAgICAgbG9hZFVuY291bnRhYmxlKHRoaXMucnVsZXMsIFtzdHJpbmcudG9Mb3dlckNhc2UoKV0pOwogICAgfSwKICAgIGlycmVndWxhcjogZnVuY3Rpb24gaXJyZWd1bGFyKHNpbmd1bGFyLCBwbHVyYWwpIHsKICAgICAgaWYgKHRoaXMuX2NhY2hlVXNlZCkgewogICAgICAgIHRoaXMucHVyZ2VDYWNoZSgpOwogICAgICB9CiAgICAgIGxvYWRJcnJlZ3VsYXIodGhpcy5ydWxlcywgW1tzaW5ndWxhciwgcGx1cmFsXV0pOwogICAgfSwKICAgIHBsdXJhbGl6ZTogZnVuY3Rpb24gcGx1cmFsaXplKCkgewogICAgICByZXR1cm4gdGhpcy5fcGx1cmFsaXplLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAogICAgX3BsdXJhbGl6ZTogZnVuY3Rpb24gX3BsdXJhbGl6ZSh3b3JkT3JDb3VudCwgd29yZCkgewogICAgICB2YXIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDoge307CgogICAgICBpZiAod29yZCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaW5mbGVjdCh3b3JkT3JDb3VudCwgdGhpcy5ydWxlcy5wbHVyYWxzLCB0aGlzLnJ1bGVzLmlycmVndWxhcik7CiAgICAgIH0KCiAgICAgIGlmIChwYXJzZUZsb2F0KHdvcmRPckNvdW50KSAhPT0gMSkgewogICAgICAgIHdvcmQgPSB0aGlzLmluZmxlY3Qod29yZCwgdGhpcy5ydWxlcy5wbHVyYWxzLCB0aGlzLnJ1bGVzLmlycmVndWxhcik7CiAgICAgIH0KCiAgICAgIHJldHVybiBvcHRpb25zLndpdGhvdXRDb3VudCA/IHdvcmQgOiB3b3JkT3JDb3VudCArICcgJyArIHdvcmQ7CiAgICB9LAogICAgc2luZ3VsYXJpemU6IGZ1bmN0aW9uIHNpbmd1bGFyaXplKHdvcmQpIHsKICAgICAgcmV0dXJuIHRoaXMuX3Npbmd1bGFyaXplKHdvcmQpOwogICAgfSwKICAgIF9zaW5ndWxhcml6ZTogZnVuY3Rpb24gX3Npbmd1bGFyaXplKHdvcmQpIHsKICAgICAgcmV0dXJuIHRoaXMuaW5mbGVjdCh3b3JkLCB0aGlzLnJ1bGVzLnNpbmd1bGFyLCB0aGlzLnJ1bGVzLmlycmVndWxhckludmVyc2UpOwogICAgfSwKICAgIGluZmxlY3Q6IGZ1bmN0aW9uIGluZmxlY3Qod29yZCwgdHlwZVJ1bGVzLCBpcnJlZ3VsYXIpIHsKICAgICAgdmFyIGluZmxlY3Rpb24gPSB2b2lkIDAsCiAgICAgICAgICBzdWJzdGl0dXRpb24gPSB2b2lkIDAsCiAgICAgICAgICByZXN1bHQgPSB2b2lkIDAsCiAgICAgICAgICBsb3dlcmNhc2UgPSB2b2lkIDAsCiAgICAgICAgICB3b3JkU3BsaXQgPSB2b2lkIDAsCiAgICAgICAgICBsYXN0V29yZCA9IHZvaWQgMCwKICAgICAgICAgIGlzQmxhbmsgPSB2b2lkIDAsCiAgICAgICAgICBpc0NhbWVsaXplZCA9IHZvaWQgMCwKICAgICAgICAgIHJ1bGUgPSB2b2lkIDAsCiAgICAgICAgICBpc1VuY291bnRhYmxlID0gdm9pZCAwOwoKICAgICAgaXNCbGFuayA9ICF3b3JkIHx8IEJMQU5LX1JFR0VYLnRlc3Qod29yZCk7CiAgICAgIGlzQ2FtZWxpemVkID0gQ0FNRUxJWkVEX1JFR0VYLnRlc3Qod29yZCk7CgogICAgICBpZiAoaXNCbGFuaykgewogICAgICAgIHJldHVybiB3b3JkOwogICAgICB9CgogICAgICBsb3dlcmNhc2UgPSB3b3JkLnRvTG93ZXJDYXNlKCk7CiAgICAgIHdvcmRTcGxpdCA9IExBU1RfV09SRF9EQVNIRURfUkVHRVguZXhlYyh3b3JkKSB8fCBMQVNUX1dPUkRfQ0FNRUxJWkVEX1JFR0VYLmV4ZWMod29yZCk7CgogICAgICBpZiAod29yZFNwbGl0KSB7CiAgICAgICAgbGFzdFdvcmQgPSB3b3JkU3BsaXRbMl0udG9Mb3dlckNhc2UoKTsKICAgICAgfQoKICAgICAgaXNVbmNvdW50YWJsZSA9IHRoaXMucnVsZXMudW5jb3VudGFibGVbbG93ZXJjYXNlXSB8fCB0aGlzLnJ1bGVzLnVuY291bnRhYmxlW2xhc3RXb3JkXTsKCiAgICAgIGlmIChpc1VuY291bnRhYmxlKSB7CiAgICAgICAgcmV0dXJuIHdvcmQ7CiAgICAgIH0KCiAgICAgIGZvciAocnVsZSBpbiBpcnJlZ3VsYXIpIHsKICAgICAgICBpZiAobG93ZXJjYXNlLm1hdGNoKHJ1bGUgKyAiJCIpKSB7CiAgICAgICAgICBzdWJzdGl0dXRpb24gPSBpcnJlZ3VsYXJbcnVsZV07CgogICAgICAgICAgaWYgKGlzQ2FtZWxpemVkICYmIGlycmVndWxhcltsYXN0V29yZF0pIHsKICAgICAgICAgICAgc3Vic3RpdHV0aW9uID0gRW1iZXIuU3RyaW5nLmNhcGl0YWxpemUoc3Vic3RpdHV0aW9uKTsKICAgICAgICAgICAgcnVsZSA9IEVtYmVyLlN0cmluZy5jYXBpdGFsaXplKHJ1bGUpOwogICAgICAgICAgfQoKICAgICAgICAgIHJldHVybiB3b3JkLnJlcGxhY2UobmV3IFJlZ0V4cChydWxlLCAnaScpLCBzdWJzdGl0dXRpb24pOwogICAgICAgIH0KICAgICAgfQoKICAgICAgZm9yICh2YXIgaSA9IHR5cGVSdWxlcy5sZW5ndGgsIG1pbiA9IDA7IGkgPiBtaW47IGktLSkgewogICAgICAgIGluZmxlY3Rpb24gPSB0eXBlUnVsZXNbaSAtIDFdOwogICAgICAgIHJ1bGUgPSBpbmZsZWN0aW9uWzBdOwoKICAgICAgICBpZiAocnVsZS50ZXN0KHdvcmQpKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGluZmxlY3Rpb24gPSBpbmZsZWN0aW9uIHx8IFtdOwoKICAgICAgcnVsZSA9IGluZmxlY3Rpb25bMF07CiAgICAgIHN1YnN0aXR1dGlvbiA9IGluZmxlY3Rpb25bMV07CgogICAgICByZXN1bHQgPSB3b3JkLnJlcGxhY2UocnVsZSwgc3Vic3RpdHV0aW9uKTsKCiAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9CiAgfTsKCiAgZXhwb3J0cy5kZWZhdWx0ID0gSW5mbGVjdG9yOwp9KTsKO2RlZmluZSgnZW1iZXItaW5mbGVjdG9yL2xpYi9zeXN0ZW0vc3RyaW5nJywgWydleHBvcnRzJywgJ2VtYmVyLWluZmxlY3Rvci9saWIvc3lzdGVtL2luZmxlY3RvciddLCBmdW5jdGlvbiAoZXhwb3J0cywgX2luZmxlY3RvcikgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLnNpbmd1bGFyaXplID0gZXhwb3J0cy5wbHVyYWxpemUgPSB1bmRlZmluZWQ7CgoKICBmdW5jdGlvbiBwbHVyYWxpemUoKSB7CiAgICB2YXIgX0luZmxlY3RvciRpbmZsZWN0b3I7CgogICAgcmV0dXJuIChfSW5mbGVjdG9yJGluZmxlY3RvciA9IF9pbmZsZWN0b3IuZGVmYXVsdC5pbmZsZWN0b3IpLnBsdXJhbGl6ZS5hcHBseShfSW5mbGVjdG9yJGluZmxlY3RvciwgYXJndW1lbnRzKTsKICB9CgogIGZ1bmN0aW9uIHNpbmd1bGFyaXplKHdvcmQpIHsKICAgIHJldHVybiBfaW5mbGVjdG9yLmRlZmF1bHQuaW5mbGVjdG9yLnNpbmd1bGFyaXplKHdvcmQpOwogIH0KCiAgZXhwb3J0cy5wbHVyYWxpemUgPSBwbHVyYWxpemU7CiAgZXhwb3J0cy5zaW5ndWxhcml6ZSA9IHNpbmd1bGFyaXplOwp9KTsKO2RlZmluZSgnZW1iZXItaW5mbGVjdG9yL2xpYi91dGlscy9tYWtlLWhlbHBlcicsIFsnZXhwb3J0cyddLCBmdW5jdGlvbiAoZXhwb3J0cykgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLmRlZmF1bHQgPSBtYWtlSGVscGVyOwogIGZ1bmN0aW9uIG1ha2VIZWxwZXIoaGVscGVyRnVuY3Rpb24pIHsKICAgIGlmIChFbWJlci5IZWxwZXIpIHsKICAgICAgcmV0dXJuIEVtYmVyLkhlbHBlci5oZWxwZXIoaGVscGVyRnVuY3Rpb24pOwogICAgfQogICAgaWYgKEVtYmVyLkhUTUxCYXJzKSB7CiAgICAgIHJldHVybiBFbWJlci5IVE1MQmFycy5tYWtlQm91bmRIZWxwZXIoaGVscGVyRnVuY3Rpb24pOwogICAgfQogICAgcmV0dXJuIEVtYmVyLkhhbmRsZWJhcnMubWFrZUJvdW5kSGVscGVyKGhlbHBlckZ1bmN0aW9uKTsKICB9Cn0pOwo7ZGVmaW5lKCJlbWJlci1sb2FkLWluaXRpYWxpemVycy9pbmRleCIsIFsiZXhwb3J0cyIsICJyZXF1aXJlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3JlcXVpcmUpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSBsb2FkSW5pdGlhbGl6ZXJzOwoKICBmdW5jdGlvbiByZXNvbHZlSW5pdGlhbGl6ZXIobW9kdWxlTmFtZSkgewogICAgdmFyIG1vZHVsZSA9ICgwLCBfcmVxdWlyZS5kZWZhdWx0KShtb2R1bGVOYW1lLCBudWxsLCBudWxsLCB0cnVlKTsKCiAgICBpZiAoIW1vZHVsZSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IobW9kdWxlTmFtZSArICcgbXVzdCBleHBvcnQgYW4gaW5pdGlhbGl6ZXIuJyk7CiAgICB9CgogICAgdmFyIGluaXRpYWxpemVyID0gbW9kdWxlWydkZWZhdWx0J107CgogICAgaWYgKCFpbml0aWFsaXplci5uYW1lKSB7CiAgICAgIGluaXRpYWxpemVyLm5hbWUgPSBtb2R1bGVOYW1lLnNsaWNlKG1vZHVsZU5hbWUubGFzdEluZGV4T2YoJy8nKSArIDEpOwogICAgfQoKICAgIHJldHVybiBpbml0aWFsaXplcjsKICB9CgogIGZ1bmN0aW9uIHJlZ2lzdGVySW5pdGlhbGl6ZXJzKGFwcCwgbW9kdWxlTmFtZXMpIHsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW9kdWxlTmFtZXMubGVuZ3RoOyBpKyspIHsKICAgICAgYXBwLmluaXRpYWxpemVyKHJlc29sdmVJbml0aWFsaXplcihtb2R1bGVOYW1lc1tpXSkpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gcmVnaXN0ZXJJbnN0YW5jZUluaXRpYWxpemVycyhhcHAsIG1vZHVsZU5hbWVzKSB7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vZHVsZU5hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgIGFwcC5pbnN0YW5jZUluaXRpYWxpemVyKHJlc29sdmVJbml0aWFsaXplcihtb2R1bGVOYW1lc1tpXSkpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gX2VuZHNXaXRoKHN0ciwgc3VmZml4KSB7CiAgICByZXR1cm4gc3RyLmluZGV4T2Yoc3VmZml4LCBzdHIubGVuZ3RoIC0gc3VmZml4Lmxlbmd0aCkgIT09IC0xOwogIH0KICAvKioKICAgKiBDb25maWd1cmUgeW91ciBhcHBsaWNhdGlvbiBhcyBpdCBib290cwogICAqLwoKCiAgZnVuY3Rpb24gbG9hZEluaXRpYWxpemVycyhhcHAsIHByZWZpeCkgewogICAgdmFyIGluaXRpYWxpemVyUHJlZml4ID0gcHJlZml4ICsgJy9pbml0aWFsaXplcnMvJzsKICAgIHZhciBpbnN0YW5jZUluaXRpYWxpemVyUHJlZml4ID0gcHJlZml4ICsgJy9pbnN0YW5jZS1pbml0aWFsaXplcnMvJzsKICAgIHZhciBpbml0aWFsaXplcnMgPSBbXTsKICAgIHZhciBpbnN0YW5jZUluaXRpYWxpemVycyA9IFtdOyAvLyB0aGlzIGlzIDIgcGFzcyBiZWNhdXNlIGdlbmVyYWxseSB0aGUgZmlyc3QgcGFzcyBpcyB0aGUgcHJvYmxlbQogICAgLy8gYW5kIGlzIHJlZHVjZWQsIGFuZCByZXNvbHZlSW5pdGlhbGl6ZXIgaGFzIHBvdGVudGlhbCB0byBkZW9wdAoKICAgIHZhciBtb2R1bGVOYW1lcyA9IE9iamVjdC5rZXlzKHNlbGYucmVxdWlyZWpzLl9lYWtfc2Vlbik7CgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb2R1bGVOYW1lcy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgbW9kdWxlTmFtZSA9IG1vZHVsZU5hbWVzW2ldOwoKICAgICAgaWYgKG1vZHVsZU5hbWUubGFzdEluZGV4T2YoaW5pdGlhbGl6ZXJQcmVmaXgsIDApID09PSAwKSB7CiAgICAgICAgaWYgKCFfZW5kc1dpdGgobW9kdWxlTmFtZSwgJy10ZXN0JykpIHsKICAgICAgICAgIGluaXRpYWxpemVycy5wdXNoKG1vZHVsZU5hbWUpOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChtb2R1bGVOYW1lLmxhc3RJbmRleE9mKGluc3RhbmNlSW5pdGlhbGl6ZXJQcmVmaXgsIDApID09PSAwKSB7CiAgICAgICAgaWYgKCFfZW5kc1dpdGgobW9kdWxlTmFtZSwgJy10ZXN0JykpIHsKICAgICAgICAgIGluc3RhbmNlSW5pdGlhbGl6ZXJzLnB1c2gobW9kdWxlTmFtZSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgcmVnaXN0ZXJJbml0aWFsaXplcnMoYXBwLCBpbml0aWFsaXplcnMpOwogICAgcmVnaXN0ZXJJbnN0YW5jZUluaXRpYWxpemVycyhhcHAsIGluc3RhbmNlSW5pdGlhbGl6ZXJzKTsKICB9Cn0pOwo7LyoKICogVGhpcyBpcyBhIHN0dWIgZmlsZSwgaXQgbXVzdCBiZSBvbiBkaXNrIGIvYyBiYWJlbC1wbHVnaW4tZGVidWctbWFjcm9zCiAqIGRvZXMgbm90IHN0cmlwIHRoZSBtb2R1bGUgcmVxdWlyZSB3aGVuIHRoZSB0cmFuc3BpbGVkIHZhcmlhYmxlIHVzYWdlIGlzCiAqIHN0cmlwcGVkLgogKi8KZGVmaW5lKCJlbWJlci1yZXNvbHZlci9mZWF0dXJlcyIsIFtdLCBmdW5jdGlvbiAoKSB7CiAgInVzZSBzdHJpY3QiOwp9KTsKO2RlZmluZSgnZW1iZXItcmVzb2x2ZXIvaW5kZXgnLCBbJ2V4cG9ydHMnLCAnZW1iZXItcmVzb2x2ZXIvcmVzb2x2ZXJzL2NsYXNzaWMnXSwgZnVuY3Rpb24gKGV4cG9ydHMsIF9jbGFzc2ljKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnZGVmYXVsdCcsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIF9jbGFzc2ljLmRlZmF1bHQ7CiAgICB9CiAgfSk7Cn0pOwo7ZGVmaW5lKCdlbWJlci1yZXNvbHZlci9yZXNvbHZlcicsIFsnZXhwb3J0cycsICdlbWJlci1yZXNvbHZlci9yZXNvbHZlcnMvY2xhc3NpYyddLCBmdW5jdGlvbiAoZXhwb3J0cywgX2NsYXNzaWMpIHsKICAndXNlIHN0cmljdCc7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdkZWZhdWx0JywgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gX2NsYXNzaWMuZGVmYXVsdDsKICAgIH0KICB9KTsKfSk7CjtkZWZpbmUoJ2VtYmVyLXJlc29sdmVyL3Jlc29sdmVycy9jbGFzc2ljL2NvbnRhaW5lci1kZWJ1Zy1hZGFwdGVyJywgWydleHBvcnRzJywgJ2VtYmVyLXJlc29sdmVyL3Jlc29sdmVycy9jbGFzc2ljL2luZGV4J10sIGZ1bmN0aW9uIChleHBvcnRzLCBfaW5kZXgpIHsKICAndXNlIHN0cmljdCc7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CgoKICBmdW5jdGlvbiBnZXRQb2QodHlwZSwga2V5LCBwcmVmaXgpIHsKICAgIHZhciBtYXRjaCA9IGtleS5tYXRjaChuZXcgUmVnRXhwKCdeLz8nICsgcHJlZml4ICsgJy8oLispLycgKyB0eXBlICsgJyQnKSk7CiAgICBpZiAobWF0Y2ggIT09IG51bGwpIHsKICAgICAgcmV0dXJuIG1hdGNoWzFdOwogICAgfQogIH0KCiAgLyoKICAgKiBUaGlzIG1vZHVsZSBkZWZpbmVzIGEgc3ViY2xhc3Mgb2YgRW1iZXIuQ29udGFpbmVyRGVidWdBZGFwdGVyIHRoYXQgYWRkcwogICAqIHN1cHBvcnQgZm9yIHJlc29sdmluZyBmcm9tIG1vZHVsZXMuCiAgICoKICAgKi8KICBleHBvcnRzLmRlZmF1bHQgPSBFbWJlci5Db250YWluZXJEZWJ1Z0FkYXB0ZXIuZXh0ZW5kKHsKICAgIF9tb2R1bGVSZWdpc3RyeTogbnVsbCwKCiAgICBpbml0OiBmdW5jdGlvbiBpbml0KCkgewogICAgICB0aGlzLl9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwoKICAgICAgaWYgKCF0aGlzLl9tb2R1bGVSZWdpc3RyeSkgewogICAgICAgIHRoaXMuX21vZHVsZVJlZ2lzdHJ5ID0gbmV3IF9pbmRleC5Nb2R1bGVSZWdpc3RyeSgpOwogICAgICB9CiAgICB9LAoKCiAgICAvKioKICAgICAgICBUaGUgY29udGFpbmVyIG9mIHRoZSBhcHBsaWNhdGlvbiBiZWluZyBkZWJ1Z2dlZC4KICAgICAgICBUaGlzIHByb3BlcnR5IHdpbGwgYmUgaW5qZWN0ZWQKICAgICAgICBvbiBjcmVhdGlvbi4KICAgICAgICAgQHByb3BlcnR5IGNvbnRhaW5lcgogICAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgICAqLwoKICAgIC8qKgogICAgICAgIFRoZSByZXNvbHZlciBpbnN0YW5jZSBvZiB0aGUgYXBwbGljYXRpb24KICAgICAgICBiZWluZyBkZWJ1Z2dlZC4gVGhpcyBwcm9wZXJ0eSB3aWxsIGJlIGluamVjdGVkCiAgICAgICAgb24gY3JlYXRpb24uCiAgICAgICAgIEBwcm9wZXJ0eSByZXNvbHZlcgogICAgICAgIEBkZWZhdWx0IG51bGwKICAgICAgICAqLwoKICAgIC8qKgogICAgICAgIFJldHVybnMgdHJ1ZSBpZiBpdCBpcyBwb3NzaWJsZSB0byBjYXRhbG9nIGEgbGlzdCBvZiBhdmFpbGFibGUKICAgICAgICBjbGFzc2VzIGluIHRoZSByZXNvbHZlciBmb3IgYSBnaXZlbiB0eXBlLgogICAgICAgICBAbWV0aG9kIGNhbkNhdGFsb2dFbnRyaWVzQnlUeXBlCiAgICAgICAgQHBhcmFtIHtzdHJpbmd9IHR5cGUgVGhlIHR5cGUuIGUuZy4gIm1vZGVsIiwgImNvbnRyb2xsZXIiLCAicm91dGUiCiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gd2hldGhlciBhIGxpc3QgaXMgYXZhaWxhYmxlIGZvciB0aGlzIHR5cGUuCiAgICAgICAgKi8KICAgIGNhbkNhdGFsb2dFbnRyaWVzQnlUeXBlOiBmdW5jdGlvbiBjYW5DYXRhbG9nRW50cmllc0J5VHlwZSh0eXBlKSB7CiAgICAgIGlmICh0eXBlID09PSAnbW9kZWwnKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICB9LAoKCiAgICAvKioKICAgICAgICBSZXR1cm5zIHRoZSBhdmFpbGFibGUgY2xhc3NlcyBhIGdpdmVuIHR5cGUuCiAgICAgICAgIEBtZXRob2QgY2F0YWxvZ0VudHJpZXNCeVR5cGUKICAgICAgICBAcGFyYW0ge3N0cmluZ30gdHlwZSBUaGUgdHlwZS4gZS5nLiAibW9kZWwiLCAiY29udHJvbGxlciIsICJyb3V0ZSIKICAgICAgICBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2YgY2xhc3Nlcy4KICAgICAgICAqLwogICAgY2F0YWxvZ0VudHJpZXNCeVR5cGU6IGZ1bmN0aW9uIGNhdGFsb2dFbnRyaWVzQnlUeXBlKHR5cGUpIHsKICAgICAgdmFyIG1vZHVsZU5hbWVzID0gdGhpcy5fbW9kdWxlUmVnaXN0cnkubW9kdWxlTmFtZXMoKTsKICAgICAgdmFyIHR5cGVzID0gRW1iZXIuQSgpOwoKICAgICAgdmFyIHByZWZpeCA9IHRoaXMubmFtZXNwYWNlLm1vZHVsZVByZWZpeDsKCiAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gbW9kdWxlTmFtZXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgdmFyIGtleSA9IG1vZHVsZU5hbWVzW2ldOwoKICAgICAgICBpZiAoa2V5LmluZGV4T2YodHlwZSkgIT09IC0xKSB7CiAgICAgICAgICAvLyBDaGVjayBpZiBpdCdzIGEgcG9kIG1vZHVsZQogICAgICAgICAgdmFyIG5hbWUgPSBnZXRQb2QodHlwZSwga2V5LCB0aGlzLm5hbWVzcGFjZS5wb2RNb2R1bGVQcmVmaXggfHwgcHJlZml4KTsKICAgICAgICAgIGlmICghbmFtZSkgewogICAgICAgICAgICAvLyBOb3QgcG9kCiAgICAgICAgICAgIG5hbWUgPSBrZXkuc3BsaXQodHlwZSArICdzLycpLnBvcCgpOwoKICAgICAgICAgICAgLy8gU3VwcG9ydCBmb3IgZGlmZmVyZW50IHByZWZpeCAoc3VjaCBhcyBlbWJlci1jbGkgYWRkb25zKS4KICAgICAgICAgICAgLy8gVW5jb21tZW50IHRoZSBjb2RlIGJlbG93IHdoZW4KICAgICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2VtYmVyLWNsaS9lbWJlci1yZXNvbHZlci9wdWxsLzgwIGlzIG1lcmdlZC4KCiAgICAgICAgICAgIC8vbGV0IG1hdGNoID0ga2V5Lm1hdGNoKCdeLz8oLispLycgKyB0eXBlKTsKICAgICAgICAgICAgLy9pZiAobWF0Y2ggJiYgbWF0Y2hbMV0gIT09IHByZWZpeCkgewogICAgICAgICAgICAvLyBEaWZmZXJlbnQgcHJlZml4IHN1Y2ggYXMgYW4gYWRkb24KICAgICAgICAgICAgLy9uYW1lID0gbWF0Y2hbMV0gKyAnQCcgKyBuYW1lOwogICAgICAgICAgICAvL30KICAgICAgICAgIH0KICAgICAgICAgIHR5cGVzLmFkZE9iamVjdChuYW1lKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHR5cGVzOwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgnZW1iZXItcmVzb2x2ZXIvcmVzb2x2ZXJzL2NsYXNzaWMvaW5kZXgnLCBbJ2V4cG9ydHMnLCAnZW1iZXItcmVzb2x2ZXIvdXRpbHMvY2xhc3MtZmFjdG9yeScsICdlbWJlci1yZXNvbHZlci91dGlscy9tYWtlLWRpY3Rpb25hcnknXSwgZnVuY3Rpb24gKGV4cG9ydHMsIF9jbGFzc0ZhY3RvcnksIF9tYWtlRGljdGlvbmFyeSkgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLk1vZHVsZVJlZ2lzdHJ5ID0gdW5kZWZpbmVkOwoKICBmdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7CiAgICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgewogICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24iKTsKICAgIH0KICB9CgogIGlmICh0eXBlb2YgcmVxdWlyZWpzLmVudHJpZXMgPT09ICd1bmRlZmluZWQnKSB7CiAgICByZXF1aXJlanMuZW50cmllcyA9IHJlcXVpcmVqcy5fZWFrX3NlZW47CiAgfQoKICB2YXIgTW9kdWxlUmVnaXN0cnkgPSBleHBvcnRzLk1vZHVsZVJlZ2lzdHJ5ID0gZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gTW9kdWxlUmVnaXN0cnkoZW50cmllcykgewogICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgTW9kdWxlUmVnaXN0cnkpOwoKICAgICAgdGhpcy5fZW50cmllcyA9IGVudHJpZXMgfHwgcmVxdWlyZWpzLmVudHJpZXM7CiAgICB9CgogICAgTW9kdWxlUmVnaXN0cnkucHJvdG90eXBlLm1vZHVsZU5hbWVzID0gZnVuY3Rpb24gbW9kdWxlTmFtZXMoKSB7CiAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl9lbnRyaWVzKTsKICAgIH07CgogICAgTW9kdWxlUmVnaXN0cnkucHJvdG90eXBlLmhhcyA9IGZ1bmN0aW9uIGhhcyhtb2R1bGVOYW1lKSB7CiAgICAgIHJldHVybiBtb2R1bGVOYW1lIGluIHRoaXMuX2VudHJpZXM7CiAgICB9OwoKICAgIE1vZHVsZVJlZ2lzdHJ5LnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiBnZXQobW9kdWxlTmFtZSkgewogICAgICByZXR1cm4gcmVxdWlyZShtb2R1bGVOYW1lKTsKICAgIH07CgogICAgcmV0dXJuIE1vZHVsZVJlZ2lzdHJ5OwogIH0oKTsKCiAgLyoqCiAgICogVGhpcyBtb2R1bGUgZGVmaW5lcyBhIHN1YmNsYXNzIG9mIEVtYmVyLkRlZmF1bHRSZXNvbHZlciB0aGF0IGFkZHMgdHdvCiAgICogaW1wb3J0YW50IGZlYXR1cmVzOgogICAqCiAgICogIDEpIFRoZSByZXNvbHZlciBtYWtlcyB0aGUgY29udGFpbmVyIGF3YXJlIG9mIGVzNiBtb2R1bGVzIHZpYSB0aGUgQU1ECiAgICogICAgIG91dHB1dC4gVGhlIGxvYWRlcidzIF9tb2R1bGVFbnRyaWVzIGlzIGNvbnN1bHRlZCBzbyB0aGF0IGNsYXNzZXMgY2FuIGJlCiAgICogICAgIHJlc29sdmVkIGRpcmVjdGx5IHZpYSB0aGUgbW9kdWxlIGxvYWRlciwgd2l0aG91dCBuZWVkaW5nIGEgbWFudWFsCiAgICogICAgIGBpbXBvcnRgLgogICAqICAyKSBpcyBhYmxlIHRvIHByb3ZpZGUgaW5qZWN0aW9ucyB0byBjbGFzc2VzIHRoYXQgaW1wbGVtZW50IGBleHRlbmRgCiAgICogICAgIChhcyBpcyB0eXBpY2FsIHdpdGggRW1iZXIpLgogICAqLwoKICBmdW5jdGlvbiBwYXJzZU5hbWUoZnVsbE5hbWUpIHsKICAgIGlmIChmdWxsTmFtZS5wYXJzZWROYW1lID09PSB0cnVlKSB7CiAgICAgIHJldHVybiBmdWxsTmFtZTsKICAgIH0KCiAgICB2YXIgcHJlZml4ID0gdm9pZCAwLAogICAgICAgIHR5cGUgPSB2b2lkIDAsCiAgICAgICAgbmFtZSA9IHZvaWQgMDsKICAgIHZhciBmdWxsTmFtZVBhcnRzID0gZnVsbE5hbWUuc3BsaXQoJ0AnKTsKCiAgICBpZiAoZnVsbE5hbWVQYXJ0cy5sZW5ndGggPT09IDIpIHsKICAgICAgdmFyIHByZWZpeFBhcnRzID0gZnVsbE5hbWVQYXJ0c1swXS5zcGxpdCgnOicpOwoKICAgICAgaWYgKHByZWZpeFBhcnRzLmxlbmd0aCA9PT0gMikgewogICAgICAgIGlmIChwcmVmaXhQYXJ0c1sxXS5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHR5cGUgPSBwcmVmaXhQYXJ0c1swXTsKICAgICAgICAgIG5hbWUgPSAnQCcgKyBmdWxsTmFtZVBhcnRzWzFdOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBwcmVmaXggPSBwcmVmaXhQYXJ0c1sxXTsKICAgICAgICAgIHR5cGUgPSBwcmVmaXhQYXJ0c1swXTsKICAgICAgICAgIG5hbWUgPSBmdWxsTmFtZVBhcnRzWzFdOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgbmFtZVBhcnRzID0gZnVsbE5hbWVQYXJ0c1sxXS5zcGxpdCgnOicpOwoKICAgICAgICBwcmVmaXggPSBmdWxsTmFtZVBhcnRzWzBdOwogICAgICAgIHR5cGUgPSBuYW1lUGFydHNbMF07CiAgICAgICAgbmFtZSA9IG5hbWVQYXJ0c1sxXTsKICAgICAgfQoKICAgICAgaWYgKHR5cGUgPT09ICd0ZW1wbGF0ZScgJiYgcHJlZml4Lmxhc3RJbmRleE9mKCdjb21wb25lbnRzLycsIDApID09PSAwKSB7CiAgICAgICAgbmFtZSA9ICdjb21wb25lbnRzLycgKyBuYW1lOwogICAgICAgIHByZWZpeCA9IHByZWZpeC5zbGljZSgxMSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGZ1bGxOYW1lUGFydHMgPSBmdWxsTmFtZS5zcGxpdCgnOicpOwogICAgICB0eXBlID0gZnVsbE5hbWVQYXJ0c1swXTsKICAgICAgbmFtZSA9IGZ1bGxOYW1lUGFydHNbMV07CiAgICB9CgogICAgdmFyIGZ1bGxOYW1lV2l0aG91dFR5cGUgPSBuYW1lOwogICAgdmFyIG5hbWVzcGFjZSA9IEVtYmVyLmdldCh0aGlzLCAnbmFtZXNwYWNlJyk7CiAgICB2YXIgcm9vdCA9IG5hbWVzcGFjZTsKCiAgICByZXR1cm4gewogICAgICBwYXJzZWROYW1lOiB0cnVlLAogICAgICBmdWxsTmFtZTogZnVsbE5hbWUsCiAgICAgIHByZWZpeDogcHJlZml4IHx8IHRoaXMucHJlZml4KHsgdHlwZTogdHlwZSB9KSwKICAgICAgdHlwZTogdHlwZSwKICAgICAgZnVsbE5hbWVXaXRob3V0VHlwZTogZnVsbE5hbWVXaXRob3V0VHlwZSwKICAgICAgbmFtZTogbmFtZSwKICAgICAgcm9vdDogcm9vdCwKICAgICAgcmVzb2x2ZU1ldGhvZE5hbWU6ICJyZXNvbHZlIiArIEVtYmVyLlN0cmluZy5jbGFzc2lmeSh0eXBlKQogICAgfTsKICB9CgogIGZ1bmN0aW9uIHJlc29sdmVPdGhlcihwYXJzZWROYW1lKSB7CiAgICAoZmFsc2UgJiYgISh0aGlzLm5hbWVzcGFjZS5tb2R1bGVQcmVmaXgpICYmIEVtYmVyLmFzc2VydCgnYG1vZHVsZVByZWZpeGAgbXVzdCBiZSBkZWZpbmVkJywgdGhpcy5uYW1lc3BhY2UubW9kdWxlUHJlZml4KSk7CgoKICAgIHZhciBub3JtYWxpemVkTW9kdWxlTmFtZSA9IHRoaXMuZmluZE1vZHVsZU5hbWUocGFyc2VkTmFtZSk7CgogICAgaWYgKG5vcm1hbGl6ZWRNb2R1bGVOYW1lKSB7CiAgICAgIHZhciBkZWZhdWx0RXhwb3J0ID0gdGhpcy5fZXh0cmFjdERlZmF1bHRFeHBvcnQobm9ybWFsaXplZE1vZHVsZU5hbWUsIHBhcnNlZE5hbWUpOwoKICAgICAgaWYgKGRlZmF1bHRFeHBvcnQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcignIEV4cGVjdGVkIHRvIGZpbmQ6IFwnJyArIHBhcnNlZE5hbWUuZnVsbE5hbWUgKyAnXCcgd2l0aGluIFwnJyArIG5vcm1hbGl6ZWRNb2R1bGVOYW1lICsgJ1wnIGJ1dCBnb3QgXCd1bmRlZmluZWRcJy4gRGlkIHlvdSBmb3JnZXQgdG8gXCdleHBvcnQgZGVmYXVsdFwnIHdpdGhpbiBcJycgKyBub3JtYWxpemVkTW9kdWxlTmFtZSArICdcJz8nKTsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuc2hvdWxkV3JhcEluQ2xhc3NGYWN0b3J5KGRlZmF1bHRFeHBvcnQsIHBhcnNlZE5hbWUpKSB7CiAgICAgICAgZGVmYXVsdEV4cG9ydCA9ICgwLCBfY2xhc3NGYWN0b3J5LmRlZmF1bHQpKGRlZmF1bHRFeHBvcnQpOwogICAgICB9CgogICAgICByZXR1cm4gZGVmYXVsdEV4cG9ydDsKICAgIH0KICB9CgogIHZhciBSZXNvbHZlciA9IEVtYmVyLk9iamVjdC5leHRlbmQoewogICAgcmVzb2x2ZU90aGVyOiByZXNvbHZlT3RoZXIsCiAgICBwYXJzZU5hbWU6IHBhcnNlTmFtZSwKICAgIHBsdXJhbGl6ZWRUeXBlczogbnVsbCwKICAgIG1vZHVsZVJlZ2lzdHJ5OiBudWxsLAoKICAgIG1ha2VUb1N0cmluZzogZnVuY3Rpb24gbWFrZVRvU3RyaW5nKGZhY3RvcnksIGZ1bGxOYW1lKSB7CiAgICAgIHJldHVybiAnJyArIHRoaXMubmFtZXNwYWNlLm1vZHVsZVByZWZpeCArICdAJyArIGZ1bGxOYW1lICsgJzonOwogICAgfSwKICAgIHNob3VsZFdyYXBJbkNsYXNzRmFjdG9yeTogZnVuY3Rpb24gc2hvdWxkV3JhcEluQ2xhc3NGYWN0b3J5KCkgLyogbW9kdWxlLCBwYXJzZWROYW1lICovewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9LAogICAgaW5pdDogZnVuY3Rpb24gaW5pdCgpIHsKICAgICAgdGhpcy5fc3VwZXIoKTsKICAgICAgdGhpcy5tb2R1bGVCYXNlZFJlc29sdmVyID0gdHJ1ZTsKCiAgICAgIGlmICghdGhpcy5fbW9kdWxlUmVnaXN0cnkpIHsKICAgICAgICB0aGlzLl9tb2R1bGVSZWdpc3RyeSA9IG5ldyBNb2R1bGVSZWdpc3RyeSgpOwogICAgICB9CgogICAgICB0aGlzLl9ub3JtYWxpemVDYWNoZSA9ICgwLCBfbWFrZURpY3Rpb25hcnkuZGVmYXVsdCkoKTsKCiAgICAgIHRoaXMucGx1cmFsaXplZFR5cGVzID0gdGhpcy5wbHVyYWxpemVkVHlwZXMgfHwgKDAsIF9tYWtlRGljdGlvbmFyeS5kZWZhdWx0KSgpOwoKICAgICAgaWYgKCF0aGlzLnBsdXJhbGl6ZWRUeXBlcy5jb25maWcpIHsKICAgICAgICB0aGlzLnBsdXJhbGl6ZWRUeXBlcy5jb25maWcgPSAnY29uZmlnJzsKICAgICAgfQogICAgICB0aGlzLl9kZXByZWNhdGVkUG9kTW9kdWxlUHJlZml4ID0gZmFsc2U7CiAgICB9LAogICAgbm9ybWFsaXplOiBmdW5jdGlvbiBub3JtYWxpemUoZnVsbE5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXMuX25vcm1hbGl6ZUNhY2hlW2Z1bGxOYW1lXSB8fCAodGhpcy5fbm9ybWFsaXplQ2FjaGVbZnVsbE5hbWVdID0gdGhpcy5fbm9ybWFsaXplKGZ1bGxOYW1lKSk7CiAgICB9LAogICAgcmVzb2x2ZTogZnVuY3Rpb24gcmVzb2x2ZShmdWxsTmFtZSkgewogICAgICB2YXIgcGFyc2VkTmFtZSA9IHRoaXMucGFyc2VOYW1lKGZ1bGxOYW1lKTsKICAgICAgdmFyIHJlc29sdmVNZXRob2ROYW1lID0gcGFyc2VkTmFtZS5yZXNvbHZlTWV0aG9kTmFtZTsKICAgICAgdmFyIHJlc29sdmVkID0gdm9pZCAwOwoKICAgICAgaWYgKHR5cGVvZiB0aGlzW3Jlc29sdmVNZXRob2ROYW1lXSA9PT0gJ2Z1bmN0aW9uJykgewogICAgICAgIHJlc29sdmVkID0gdGhpc1tyZXNvbHZlTWV0aG9kTmFtZV0ocGFyc2VkTmFtZSk7CiAgICAgIH0KCiAgICAgIGlmIChyZXNvbHZlZCA9PSBudWxsKSB7CiAgICAgICAgcmVzb2x2ZWQgPSB0aGlzLnJlc29sdmVPdGhlcihwYXJzZWROYW1lKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHJlc29sdmVkOwogICAgfSwKICAgIF9ub3JtYWxpemU6IGZ1bmN0aW9uIF9ub3JtYWxpemUoZnVsbE5hbWUpIHsKICAgICAgLy8gQSkgQ29udmVydCB1bmRlcnNjb3JlcyB0byBkYXNoZXMKICAgICAgLy8gQikgQ29udmVydCBjYW1lbENhc2UgdG8gZGFzaC1jYXNlLCBleGNlcHQgZm9yIGNvbXBvbmVudHMgKHRoZWlyCiAgICAgIC8vICAgIHRlbXBsYXRlcykgYW5kIGhlbHBlcnMgd2hlcmUgd2Ugd2FudCB0byBhdm9pZCBzaGFkb3dpbmcgY2FtZWxDYXNlCiAgICAgIC8vICAgIGV4cHJlc3Npb25zCiAgICAgIC8vIEMpIHJlcGxhY2UgYC5gIHdpdGggYC9gIGluIG9yZGVyIHRvIG1ha2UgbmVzdGVkIGNvbnRyb2xsZXJzIHdvcmsgaW4gdGhlIGZvbGxvd2luZyBjYXNlcwogICAgICAvLyAgICAgIDEuIGBuZWVkczogWydwb3N0cy9wb3N0J11gCiAgICAgIC8vICAgICAgMi4gYHt7cmVuZGVyICJwb3N0cy9wb3N0In19YAogICAgICAvLyAgICAgIDMuIGB0aGlzLnJlbmRlcigncG9zdHMvcG9zdCcpYCBmcm9tIFJvdXRlCgogICAgICB2YXIgc3BsaXQgPSBmdWxsTmFtZS5zcGxpdCgnOicpOwogICAgICBpZiAoc3BsaXQubGVuZ3RoID4gMSkgewogICAgICAgIHZhciB0eXBlID0gc3BsaXRbMF07CgogICAgICAgIGlmICh0eXBlID09PSAnY29tcG9uZW50JyB8fCB0eXBlID09PSAnaGVscGVyJyB8fCB0eXBlID09PSAndGVtcGxhdGUnICYmIHNwbGl0WzFdLmluZGV4T2YoJ2NvbXBvbmVudHMvJykgPT09IDApIHsKICAgICAgICAgIHJldHVybiB0eXBlICsgJzonICsgc3BsaXRbMV0ucmVwbGFjZSgvXy9nLCAnLScpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gdHlwZSArICc6JyArIEVtYmVyLlN0cmluZy5kYXNoZXJpemUoc3BsaXRbMV0ucmVwbGFjZSgvXC4vZywgJy8nKSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBmdWxsTmFtZTsKICAgICAgfQogICAgfSwKICAgIHBsdXJhbGl6ZTogZnVuY3Rpb24gcGx1cmFsaXplKHR5cGUpIHsKICAgICAgcmV0dXJuIHRoaXMucGx1cmFsaXplZFR5cGVzW3R5cGVdIHx8ICh0aGlzLnBsdXJhbGl6ZWRUeXBlc1t0eXBlXSA9IHR5cGUgKyAncycpOwogICAgfSwKICAgIHBvZEJhc2VkTG9va3VwV2l0aFByZWZpeDogZnVuY3Rpb24gcG9kQmFzZWRMb29rdXBXaXRoUHJlZml4KHBvZFByZWZpeCwgcGFyc2VkTmFtZSkgewogICAgICB2YXIgZnVsbE5hbWVXaXRob3V0VHlwZSA9IHBhcnNlZE5hbWUuZnVsbE5hbWVXaXRob3V0VHlwZTsKCiAgICAgIGlmIChwYXJzZWROYW1lLnR5cGUgPT09ICd0ZW1wbGF0ZScpIHsKICAgICAgICBmdWxsTmFtZVdpdGhvdXRUeXBlID0gZnVsbE5hbWVXaXRob3V0VHlwZS5yZXBsYWNlKC9eY29tcG9uZW50c1wvLywgJycpOwogICAgICB9CgogICAgICByZXR1cm4gcG9kUHJlZml4ICsgJy8nICsgZnVsbE5hbWVXaXRob3V0VHlwZSArICcvJyArIHBhcnNlZE5hbWUudHlwZTsKICAgIH0sCiAgICBwb2RCYXNlZE1vZHVsZU5hbWU6IGZ1bmN0aW9uIHBvZEJhc2VkTW9kdWxlTmFtZShwYXJzZWROYW1lKSB7CiAgICAgIHZhciBwb2RQcmVmaXggPSB0aGlzLm5hbWVzcGFjZS5wb2RNb2R1bGVQcmVmaXggfHwgdGhpcy5uYW1lc3BhY2UubW9kdWxlUHJlZml4OwoKICAgICAgcmV0dXJuIHRoaXMucG9kQmFzZWRMb29rdXBXaXRoUHJlZml4KHBvZFByZWZpeCwgcGFyc2VkTmFtZSk7CiAgICB9LAogICAgcG9kQmFzZWRDb21wb25lbnRzSW5TdWJkaXI6IGZ1bmN0aW9uIHBvZEJhc2VkQ29tcG9uZW50c0luU3ViZGlyKHBhcnNlZE5hbWUpIHsKICAgICAgdmFyIHBvZFByZWZpeCA9IHRoaXMubmFtZXNwYWNlLnBvZE1vZHVsZVByZWZpeCB8fCB0aGlzLm5hbWVzcGFjZS5tb2R1bGVQcmVmaXg7CiAgICAgIHBvZFByZWZpeCA9IHBvZFByZWZpeCArICcvY29tcG9uZW50cyc7CgogICAgICBpZiAocGFyc2VkTmFtZS50eXBlID09PSAnY29tcG9uZW50JyB8fCAvXmNvbXBvbmVudHMvLnRlc3QocGFyc2VkTmFtZS5mdWxsTmFtZVdpdGhvdXRUeXBlKSkgewogICAgICAgIHJldHVybiB0aGlzLnBvZEJhc2VkTG9va3VwV2l0aFByZWZpeChwb2RQcmVmaXgsIHBhcnNlZE5hbWUpOwogICAgICB9CiAgICB9LAogICAgcmVzb2x2ZUVuZ2luZTogZnVuY3Rpb24gcmVzb2x2ZUVuZ2luZShwYXJzZWROYW1lKSB7CiAgICAgIHZhciBlbmdpbmVOYW1lID0gcGFyc2VkTmFtZS5mdWxsTmFtZVdpdGhvdXRUeXBlOwogICAgICB2YXIgZW5naW5lTW9kdWxlID0gZW5naW5lTmFtZSArICcvZW5naW5lJzsKCiAgICAgIGlmICh0aGlzLl9tb2R1bGVSZWdpc3RyeS5oYXMoZW5naW5lTW9kdWxlKSkgewogICAgICAgIHJldHVybiB0aGlzLl9leHRyYWN0RGVmYXVsdEV4cG9ydChlbmdpbmVNb2R1bGUpOwogICAgICB9CiAgICB9LAogICAgcmVzb2x2ZVJvdXRlTWFwOiBmdW5jdGlvbiByZXNvbHZlUm91dGVNYXAocGFyc2VkTmFtZSkgewogICAgICB2YXIgZW5naW5lTmFtZSA9IHBhcnNlZE5hbWUuZnVsbE5hbWVXaXRob3V0VHlwZTsKICAgICAgdmFyIGVuZ2luZVJvdXRlc01vZHVsZSA9IGVuZ2luZU5hbWUgKyAnL3JvdXRlcyc7CgogICAgICBpZiAodGhpcy5fbW9kdWxlUmVnaXN0cnkuaGFzKGVuZ2luZVJvdXRlc01vZHVsZSkpIHsKICAgICAgICB2YXIgcm91dGVNYXAgPSB0aGlzLl9leHRyYWN0RGVmYXVsdEV4cG9ydChlbmdpbmVSb3V0ZXNNb2R1bGUpOwoKICAgICAgICAoZmFsc2UgJiYgIShyb3V0ZU1hcC5pc1JvdXRlTWFwKSAmJiBFbWJlci5hc3NlcnQoJ1RoZSByb3V0ZSBtYXAgZm9yICcgKyBlbmdpbmVOYW1lICsgJyBzaG91bGQgYmUgd3JhcHBlZCBieSBcJ2J1aWxkUm91dGVzXCcgYmVmb3JlIGV4cG9ydGluZy4nLCByb3V0ZU1hcC5pc1JvdXRlTWFwKSk7CgoKICAgICAgICByZXR1cm4gcm91dGVNYXA7CiAgICAgIH0KICAgIH0sCiAgICByZXNvbHZlVGVtcGxhdGU6IGZ1bmN0aW9uIHJlc29sdmVUZW1wbGF0ZShwYXJzZWROYW1lKSB7CiAgICAgIHZhciByZXNvbHZlZCA9IHRoaXMucmVzb2x2ZU90aGVyKHBhcnNlZE5hbWUpOwogICAgICBpZiAocmVzb2x2ZWQgPT0gbnVsbCkgewogICAgICAgIHJlc29sdmVkID0gRW1iZXIuVEVNUExBVEVTW3BhcnNlZE5hbWUuZnVsbE5hbWVXaXRob3V0VHlwZV07CiAgICAgIH0KICAgICAgcmV0dXJuIHJlc29sdmVkOwogICAgfSwKICAgIG1haW5Nb2R1bGVOYW1lOiBmdW5jdGlvbiBtYWluTW9kdWxlTmFtZShwYXJzZWROYW1lKSB7CiAgICAgIGlmIChwYXJzZWROYW1lLmZ1bGxOYW1lV2l0aG91dFR5cGUgPT09ICdtYWluJykgewogICAgICAgIC8vIGlmIHJvdXRlcjptYWluIG9yIGFkYXB0ZXI6bWFpbiBsb29rIGZvciBhIG1vZHVsZSB3aXRoIGp1c3QgdGhlIHR5cGUgZmlyc3QKICAgICAgICByZXR1cm4gcGFyc2VkTmFtZS5wcmVmaXggKyAnLycgKyBwYXJzZWROYW1lLnR5cGU7CiAgICAgIH0KICAgIH0sCiAgICBkZWZhdWx0TW9kdWxlTmFtZTogZnVuY3Rpb24gZGVmYXVsdE1vZHVsZU5hbWUocGFyc2VkTmFtZSkgewogICAgICByZXR1cm4gcGFyc2VkTmFtZS5wcmVmaXggKyAnLycgKyB0aGlzLnBsdXJhbGl6ZShwYXJzZWROYW1lLnR5cGUpICsgJy8nICsgcGFyc2VkTmFtZS5mdWxsTmFtZVdpdGhvdXRUeXBlOwogICAgfSwKICAgIG5lc3RlZENvbG9jYXRpb25Db21wb25lbnRNb2R1bGVOYW1lOiBmdW5jdGlvbiBuZXN0ZWRDb2xvY2F0aW9uQ29tcG9uZW50TW9kdWxlTmFtZShwYXJzZWROYW1lKSB7CiAgICAgIGlmIChwYXJzZWROYW1lLnR5cGUgPT09ICdjb21wb25lbnQnKSB7CiAgICAgICAgcmV0dXJuIHBhcnNlZE5hbWUucHJlZml4ICsgJy8nICsgdGhpcy5wbHVyYWxpemUocGFyc2VkTmFtZS50eXBlKSArICcvJyArIHBhcnNlZE5hbWUuZnVsbE5hbWVXaXRob3V0VHlwZSArICcvaW5kZXgnOwogICAgICB9CiAgICB9LAogICAgcHJlZml4OiBmdW5jdGlvbiBwcmVmaXgocGFyc2VkTmFtZSkgewogICAgICB2YXIgdG1wUHJlZml4ID0gdGhpcy5uYW1lc3BhY2UubW9kdWxlUHJlZml4OwoKICAgICAgaWYgKHRoaXMubmFtZXNwYWNlW3BhcnNlZE5hbWUudHlwZSArICdQcmVmaXgnXSkgewogICAgICAgIHRtcFByZWZpeCA9IHRoaXMubmFtZXNwYWNlW3BhcnNlZE5hbWUudHlwZSArICdQcmVmaXgnXTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRtcFByZWZpeDsKICAgIH0sCgoKICAgIC8qKgogICAgICBBIGxpc3Rpbmcgb2YgZnVuY3Rpb25zIHRvIHRlc3QgZm9yIG1vZHVsZU5hbWUncyBiYXNlZCBvbiB0aGUgcHJvdmlkZWQKICAgICBgcGFyc2VkTmFtZWAuIFRoaXMgYWxsb3dzIGVhc3kgY3VzdG9taXphdGlvbiBvZiBhZGRpdGlvbmFsIG1vZHVsZSBiYXNlZAogICAgIGxvb2t1cCBwYXR0ZXJucy4KICAgICAgQHByb3BlcnR5IG1vZHVsZU5hbWVMb29rdXBQYXR0ZXJucwogICAgIEByZXR1cm5zIHtFbWJlci5BcnJheX0KICAgICAqLwogICAgbW9kdWxlTmFtZUxvb2t1cFBhdHRlcm5zOiBFbWJlci5jb21wdXRlZChmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBbdGhpcy5wb2RCYXNlZE1vZHVsZU5hbWUsIHRoaXMucG9kQmFzZWRDb21wb25lbnRzSW5TdWJkaXIsIHRoaXMubWFpbk1vZHVsZU5hbWUsIHRoaXMuZGVmYXVsdE1vZHVsZU5hbWUsIHRoaXMubmVzdGVkQ29sb2NhdGlvbkNvbXBvbmVudE1vZHVsZU5hbWVdOwogICAgfSkucmVhZE9ubHkoKSwKCiAgICBmaW5kTW9kdWxlTmFtZTogZnVuY3Rpb24gZmluZE1vZHVsZU5hbWUocGFyc2VkTmFtZSwgbG9nZ2luZ0Rpc2FibGVkKSB7CiAgICAgIHZhciBtb2R1bGVOYW1lTG9va3VwUGF0dGVybnMgPSB0aGlzLmdldCgnbW9kdWxlTmFtZUxvb2t1cFBhdHRlcm5zJyk7CiAgICAgIHZhciBtb2R1bGVOYW1lID0gdm9pZCAwOwoKICAgICAgZm9yICh2YXIgaW5kZXggPSAwLCBsZW5ndGggPSBtb2R1bGVOYW1lTG9va3VwUGF0dGVybnMubGVuZ3RoOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykgewogICAgICAgIHZhciBpdGVtID0gbW9kdWxlTmFtZUxvb2t1cFBhdHRlcm5zW2luZGV4XTsKCiAgICAgICAgdmFyIHRtcE1vZHVsZU5hbWUgPSBpdGVtLmNhbGwodGhpcywgcGFyc2VkTmFtZSk7CgogICAgICAgIC8vIGFsbG93IHRyZWF0IGFsbCBkYXNoZWQgYW5kIGFsbCB1bmRlcnNjb3JlZCBhcyB0aGUgc2FtZSB0aGluZwogICAgICAgIC8vIHN1cHBvcnRzIGNvbXBvbmVudHMgd2l0aCBkYXNoZXMgYW5kIG90aGVyIHN0dWZmIHdpdGggdW5kZXJzY29yZXMuCiAgICAgICAgaWYgKHRtcE1vZHVsZU5hbWUpIHsKICAgICAgICAgIHRtcE1vZHVsZU5hbWUgPSB0aGlzLmNob29zZU1vZHVsZU5hbWUodG1wTW9kdWxlTmFtZSwgcGFyc2VkTmFtZSk7CiAgICAgICAgfQoKICAgICAgICBpZiAodG1wTW9kdWxlTmFtZSAmJiB0aGlzLl9tb2R1bGVSZWdpc3RyeS5oYXModG1wTW9kdWxlTmFtZSkpIHsKICAgICAgICAgIG1vZHVsZU5hbWUgPSB0bXBNb2R1bGVOYW1lOwogICAgICAgIH0KCiAgICAgICAgaWYgKCFsb2dnaW5nRGlzYWJsZWQpIHsKICAgICAgICAgIHRoaXMuX2xvZ0xvb2t1cChtb2R1bGVOYW1lLCBwYXJzZWROYW1lLCB0bXBNb2R1bGVOYW1lKTsKICAgICAgICB9CgogICAgICAgIGlmIChtb2R1bGVOYW1lKSB7CiAgICAgICAgICByZXR1cm4gbW9kdWxlTmFtZTsKICAgICAgICB9CiAgICAgIH0KICAgIH0sCiAgICBjaG9vc2VNb2R1bGVOYW1lOiBmdW5jdGlvbiBjaG9vc2VNb2R1bGVOYW1lKG1vZHVsZU5hbWUsIHBhcnNlZE5hbWUpIHsKICAgICAgdmFyIHVuZGVyc2NvcmVkTW9kdWxlTmFtZSA9IEVtYmVyLlN0cmluZy51bmRlcnNjb3JlKG1vZHVsZU5hbWUpOwoKICAgICAgaWYgKG1vZHVsZU5hbWUgIT09IHVuZGVyc2NvcmVkTW9kdWxlTmFtZSAmJiB0aGlzLl9tb2R1bGVSZWdpc3RyeS5oYXMobW9kdWxlTmFtZSkgJiYgdGhpcy5fbW9kdWxlUmVnaXN0cnkuaGFzKHVuZGVyc2NvcmVkTW9kdWxlTmFtZSkpIHsKICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBbWJpZ3VvdXMgbW9kdWxlIG5hbWVzOiBcJycgKyBtb2R1bGVOYW1lICsgJ1wnIGFuZCBcJycgKyB1bmRlcnNjb3JlZE1vZHVsZU5hbWUgKyAnXCcnKTsKICAgICAgfQoKICAgICAgaWYgKHRoaXMuX21vZHVsZVJlZ2lzdHJ5Lmhhcyhtb2R1bGVOYW1lKSkgewogICAgICAgIHJldHVybiBtb2R1bGVOYW1lOwogICAgICB9IGVsc2UgaWYgKHRoaXMuX21vZHVsZVJlZ2lzdHJ5Lmhhcyh1bmRlcnNjb3JlZE1vZHVsZU5hbWUpKSB7CiAgICAgICAgcmV0dXJuIHVuZGVyc2NvcmVkTW9kdWxlTmFtZTsKICAgICAgfQogICAgICAvLyB3b3JrYXJvdW5kIGZvciBkYXNoZXJpemVkIHBhcnRpYWxzOgogICAgICAvLyBzb21ldGhpbmcvc29tZXRoaW5nLy1zb21ldGhpbmcgPT4gc29tZXRoaW5nL3NvbWV0aGluZy9fc29tZXRoaW5nCiAgICAgIHZhciBwYXJ0aWFsaXplZE1vZHVsZU5hbWUgPSBtb2R1bGVOYW1lLnJlcGxhY2UoL1wvLShbXi9dKikkLywgJy9fJDEnKTsKCiAgICAgIGlmICh0aGlzLl9tb2R1bGVSZWdpc3RyeS5oYXMocGFydGlhbGl6ZWRNb2R1bGVOYW1lKSkgewogICAgICAgIChmYWxzZSAmJiAhKGZhbHNlKSAmJiBFbWJlci5kZXByZWNhdGUoJ01vZHVsZXMgc2hvdWxkIG5vdCBjb250YWluIHVuZGVyc2NvcmVzLiAnICsgJ0F0dGVtcHRlZCB0byBsb29rdXAgIicgKyBtb2R1bGVOYW1lICsgJyIgd2hpY2ggJyArICd3YXMgbm90IGZvdW5kLiBQbGVhc2UgcmVuYW1lICInICsgcGFydGlhbGl6ZWRNb2R1bGVOYW1lICsgJyIgJyArICd0byAiJyArIG1vZHVsZU5hbWUgKyAnIiBpbnN0ZWFkLicsIGZhbHNlLCB7IGlkOiAnZW1iZXItcmVzb2x2ZXIudW5kZXJzY29yZWQtbW9kdWxlcycsIHVudGlsOiAnMy4wLjAnIH0pKTsKCgogICAgICAgIHJldHVybiBwYXJ0aWFsaXplZE1vZHVsZU5hbWU7CiAgICAgIH0KCiAgICAgIGlmIChmYWxzZSkgewogICAgICAgIHZhciBpc0NhbWVsQ2FzZUhlbHBlciA9IHBhcnNlZE5hbWUudHlwZSA9PT0gJ2hlbHBlcicgJiYgL1thLXpdK1tBLVpdKy8udGVzdChtb2R1bGVOYW1lKTsKICAgICAgICBpZiAoaXNDYW1lbENhc2VIZWxwZXIpIHsKICAgICAgICAgIHRoaXMuX2NhbWVsQ2FzZUhlbHBlcldhcm5lZE5hbWVzID0gdGhpcy5fY2FtZWxDYXNlSGVscGVyV2FybmVkTmFtZXMgfHwgW107CiAgICAgICAgICB2YXIgYWxyZWFkeVdhcm5lZCA9IHRoaXMuX2NhbWVsQ2FzZUhlbHBlcldhcm5lZE5hbWVzLmluZGV4T2YocGFyc2VkTmFtZS5mdWxsTmFtZSkgPiAtMTsKICAgICAgICAgIGlmICghYWxyZWFkeVdhcm5lZCAmJiB0aGlzLl9tb2R1bGVSZWdpc3RyeS5oYXMoRW1iZXIuU3RyaW5nLmRhc2hlcml6ZShtb2R1bGVOYW1lKSkpIHsKICAgICAgICAgICAgdGhpcy5fY2FtZWxDYXNlSGVscGVyV2FybmVkTmFtZXMucHVzaChwYXJzZWROYW1lLmZ1bGxOYW1lKTsKICAgICAgICAgICAgKGZhbHNlICYmIEVtYmVyLndhcm4oJ0F0dGVtcHRlZCB0byBsb29rdXAgIicgKyBwYXJzZWROYW1lLmZ1bGxOYW1lICsgJyIgd2hpY2ggJyArICd3YXMgbm90IGZvdW5kLiBJbiBwcmV2aW91cyB2ZXJzaW9ucyBvZiBlbWJlci1yZXNvbHZlciwgYSBidWcgd291bGQgaGF2ZSAnICsgJ2NhdXNlZCB0aGUgbW9kdWxlIGF0ICInICsgRW1iZXIuU3RyaW5nLmRhc2hlcml6ZShtb2R1bGVOYW1lKSArICciIHRvIGJlICcgKyAncmV0dXJuZWQgZm9yIHRoaXMgY2FtZWwgY2FzZSBoZWxwZXIgbmFtZS4gVGhpcyBoYXMgYmVlbiBmaXhlZC4gJyArICdVc2UgdGhlIGRhc2hlcml6ZWQgbmFtZSB0byByZXNvbHZlIHRoZSBtb2R1bGUgdGhhdCB3b3VsZCBoYXZlIGJlZW4gJyArICdyZXR1cm5lZCBpbiBwcmV2aW91cyB2ZXJzaW9ucy4nLCBmYWxzZSwgeyBpZDogJ2VtYmVyLXJlc29sdmVyLmNhbWVsY2FzZS1oZWxwZXItbmFtZXMnLCB1bnRpbDogJzMuMC4wJyB9KSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9LAogICAgbG9va3VwRGVzY3JpcHRpb246IGZ1bmN0aW9uIGxvb2t1cERlc2NyaXB0aW9uKGZ1bGxOYW1lKSB7CiAgICAgIHZhciBwYXJzZWROYW1lID0gdGhpcy5wYXJzZU5hbWUoZnVsbE5hbWUpOwoKICAgICAgdmFyIG1vZHVsZU5hbWUgPSB0aGlzLmZpbmRNb2R1bGVOYW1lKHBhcnNlZE5hbWUsIHRydWUpOwoKICAgICAgcmV0dXJuIG1vZHVsZU5hbWU7CiAgICB9LAogICAgX2xvZ0xvb2t1cDogZnVuY3Rpb24gX2xvZ0xvb2t1cChmb3VuZCwgcGFyc2VkTmFtZSwgZGVzY3JpcHRpb24pIHsKICAgICAgaWYgKCFFbWJlci5FTlYuTE9HX01PRFVMRV9SRVNPTFZFUiAmJiAhcGFyc2VkTmFtZS5yb290LkxPR19SRVNPTFZFUikgewogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgdmFyIHBhZGRpbmcgPSB2b2lkIDA7CiAgICAgIHZhciBzeW1ib2wgPSBmb3VuZCA/ICdb4pyTXScgOiAnWyBdJzsKCiAgICAgIGlmIChwYXJzZWROYW1lLmZ1bGxOYW1lLmxlbmd0aCA+IDYwKSB7CiAgICAgICAgcGFkZGluZyA9ICcuJzsKICAgICAgfSBlbHNlIHsKICAgICAgICBwYWRkaW5nID0gbmV3IEFycmF5KDYwIC0gcGFyc2VkTmFtZS5mdWxsTmFtZS5sZW5ndGgpLmpvaW4oJy4nKTsKICAgICAgfQoKICAgICAgaWYgKCFkZXNjcmlwdGlvbikgewogICAgICAgIGRlc2NyaXB0aW9uID0gdGhpcy5sb29rdXBEZXNjcmlwdGlvbihwYXJzZWROYW1lKTsKICAgICAgfQoKICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqLwogICAgICBpZiAoY29uc29sZSAmJiBjb25zb2xlLmluZm8pIHsKICAgICAgICBjb25zb2xlLmluZm8oc3ltYm9sLCBwYXJzZWROYW1lLmZ1bGxOYW1lLCBwYWRkaW5nLCBkZXNjcmlwdGlvbik7CiAgICAgIH0KICAgIH0sCiAgICBrbm93bkZvclR5cGU6IGZ1bmN0aW9uIGtub3duRm9yVHlwZSh0eXBlKSB7CiAgICAgIHZhciBtb2R1bGVLZXlzID0gdGhpcy5fbW9kdWxlUmVnaXN0cnkubW9kdWxlTmFtZXMoKTsKCiAgICAgIHZhciBpdGVtcyA9ICgwLCBfbWFrZURpY3Rpb25hcnkuZGVmYXVsdCkoKTsKICAgICAgZm9yICh2YXIgaW5kZXggPSAwLCBsZW5ndGggPSBtb2R1bGVLZXlzLmxlbmd0aDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHsKICAgICAgICB2YXIgbW9kdWxlTmFtZSA9IG1vZHVsZUtleXNbaW5kZXhdOwogICAgICAgIHZhciBmdWxsbmFtZSA9IHRoaXMudHJhbnNsYXRlVG9Db250YWluZXJGdWxsbmFtZSh0eXBlLCBtb2R1bGVOYW1lKTsKCiAgICAgICAgaWYgKGZ1bGxuYW1lKSB7CiAgICAgICAgICBpdGVtc1tmdWxsbmFtZV0gPSB0cnVlOwogICAgICAgIH0KICAgICAgfQoKICAgICAgcmV0dXJuIGl0ZW1zOwogICAgfSwKICAgIHRyYW5zbGF0ZVRvQ29udGFpbmVyRnVsbG5hbWU6IGZ1bmN0aW9uIHRyYW5zbGF0ZVRvQ29udGFpbmVyRnVsbG5hbWUodHlwZSwgbW9kdWxlTmFtZSkgewogICAgICB2YXIgcHJlZml4ID0gdGhpcy5wcmVmaXgoeyB0eXBlOiB0eXBlIH0pOwoKICAgICAgLy8gTm90ZTogdXNpbmcgc3RyaW5nIG1hbmlwdWxhdGlvbiBoZXJlIHJhdGhlciB0aGFuIHJlZ2V4ZXMgZm9yIGJldHRlciBwZXJmb3JtYW5jZS4KICAgICAgLy8gcG9kIG1vZHVsZXMKICAgICAgLy8gJ14nICsgcHJlZml4ICsgJy8oLispLycgKyB0eXBlICsgJyQnCiAgICAgIHZhciBwb2RQcmVmaXggPSBwcmVmaXggKyAnLyc7CiAgICAgIHZhciBwb2RTdWZmaXggPSAnLycgKyB0eXBlOwogICAgICB2YXIgc3RhcnQgPSBtb2R1bGVOYW1lLmluZGV4T2YocG9kUHJlZml4KTsKICAgICAgdmFyIGVuZCA9IG1vZHVsZU5hbWUuaW5kZXhPZihwb2RTdWZmaXgpOwoKICAgICAgaWYgKHN0YXJ0ID09PSAwICYmIGVuZCA9PT0gbW9kdWxlTmFtZS5sZW5ndGggLSBwb2RTdWZmaXgubGVuZ3RoICYmIG1vZHVsZU5hbWUubGVuZ3RoID4gcG9kUHJlZml4Lmxlbmd0aCArIHBvZFN1ZmZpeC5sZW5ndGgpIHsKICAgICAgICByZXR1cm4gdHlwZSArICc6JyArIG1vZHVsZU5hbWUuc2xpY2Uoc3RhcnQgKyBwb2RQcmVmaXgubGVuZ3RoLCBlbmQpOwogICAgICB9CgogICAgICAvLyBub24tcG9kIG1vZHVsZXMKICAgICAgLy8gJ14nICsgcHJlZml4ICsgJy8nICsgcGx1cmFsaXplZFR5cGUgKyAnLyguKykkJwogICAgICB2YXIgcGx1cmFsaXplZFR5cGUgPSB0aGlzLnBsdXJhbGl6ZSh0eXBlKTsKICAgICAgdmFyIG5vblBvZFByZWZpeCA9IHByZWZpeCArICcvJyArIHBsdXJhbGl6ZWRUeXBlICsgJy8nOwoKICAgICAgaWYgKG1vZHVsZU5hbWUuaW5kZXhPZihub25Qb2RQcmVmaXgpID09PSAwICYmIG1vZHVsZU5hbWUubGVuZ3RoID4gbm9uUG9kUHJlZml4Lmxlbmd0aCkgewogICAgICAgIHJldHVybiB0eXBlICsgJzonICsgbW9kdWxlTmFtZS5zbGljZShub25Qb2RQcmVmaXgubGVuZ3RoKTsKICAgICAgfQogICAgfSwKICAgIF9leHRyYWN0RGVmYXVsdEV4cG9ydDogZnVuY3Rpb24gX2V4dHJhY3REZWZhdWx0RXhwb3J0KG5vcm1hbGl6ZWRNb2R1bGVOYW1lKSB7CiAgICAgIHZhciBtb2R1bGUgPSByZXF1aXJlKG5vcm1hbGl6ZWRNb2R1bGVOYW1lLCBudWxsLCBudWxsLCB0cnVlIC8qIGZvcmNlIHN5bmMgKi8pOwoKICAgICAgaWYgKG1vZHVsZSAmJiBtb2R1bGVbJ2RlZmF1bHQnXSkgewogICAgICAgIG1vZHVsZSA9IG1vZHVsZVsnZGVmYXVsdCddOwogICAgICB9CgogICAgICByZXR1cm4gbW9kdWxlOwogICAgfQogIH0pOwoKICBSZXNvbHZlci5yZW9wZW5DbGFzcyh7CiAgICBtb2R1bGVCYXNlZFJlc29sdmVyOiB0cnVlCiAgfSk7CgogIGV4cG9ydHMuZGVmYXVsdCA9IFJlc29sdmVyOwp9KTsKO2RlZmluZSgnZW1iZXItcmVzb2x2ZXIvdXRpbHMvY2xhc3MtZmFjdG9yeScsIFsnZXhwb3J0cyddLCBmdW5jdGlvbiAoZXhwb3J0cykgewogICd1c2Ugc3RyaWN0JzsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBleHBvcnRzLmRlZmF1bHQgPSBjbGFzc0ZhY3Rvcnk7CiAgZnVuY3Rpb24gY2xhc3NGYWN0b3J5KGtsYXNzKSB7CiAgICByZXR1cm4gewogICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShpbmplY3Rpb25zKSB7CiAgICAgICAgaWYgKHR5cGVvZiBrbGFzcy5leHRlbmQgPT09ICdmdW5jdGlvbicpIHsKICAgICAgICAgIHJldHVybiBrbGFzcy5leHRlbmQoaW5qZWN0aW9ucyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBrbGFzczsKICAgICAgICB9CiAgICAgIH0KICAgIH07CiAgfQp9KTsKO2RlZmluZSgnZW1iZXItcmVzb2x2ZXIvdXRpbHMvbWFrZS1kaWN0aW9uYXJ5JywgWydleHBvcnRzJ10sIGZ1bmN0aW9uIChleHBvcnRzKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIGV4cG9ydHMuZGVmYXVsdCA9IG1ha2VEaWN0aW9uYXJ5OwogIGZ1bmN0aW9uIG1ha2VEaWN0aW9uYXJ5KCkgewogICAgdmFyIGNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGNhY2hlWydfZGljdCddID0gbnVsbDsKICAgIGRlbGV0ZSBjYWNoZVsnX2RpY3QnXTsKICAgIHJldHVybiBjYWNoZTsKICB9Cn0pOwo7ZGVmaW5lKCJlbWJlci10ZXN0LXdhaXRlcnMvYnVpbGQtd2FpdGVyIiwgWyJleHBvcnRzIiwgImVtYmVyLXRlc3Qtd2FpdGVycyIsICJlbWJlci10ZXN0LXdhaXRlcnMvbm9vcC10ZXN0LXdhaXRlciJdLCBmdW5jdGlvbiAoX2V4cG9ydHMsIF9lbWJlclRlc3RXYWl0ZXJzLCBfbm9vcFRlc3RXYWl0ZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSBidWlsZFdhaXRlcjsKCiAgLyoqCiAgICogQnVpbGRzIGFuZCByZXR1cm5zIGEgdGVzdCB3YWl0ZXIuIFRoZSB0eXBlIG9mIHRoZQogICAqIHJldHVybmVkIHdhaXRlciBpcyBkZXBlbmRlbnQgb24gd2hldGhlciB0aGUgYXBwIG9yCiAgICogYWRkb24gaXMgaW4gYERFQlVHYCBtb2RlIG9yIG5vdC4KICAgKgogICAqIEBwYXJhbSBuYW1lIHtzdHJpbmd9IFRoZSBuYW1lIG9mIHRoZSB0ZXN0IHdhaXRlcgogICAqIEByZXR1cm5zIHtJVGVzdFdhaXRlcn0KICAgKgogICAqIEBleGFtcGxlCiAgICoKICAgKiBpbXBvcnQgQ29tcG9uZW50IGZyb20gJ0BlbWJlci9jb21wb25lbnQnOwogICAqIGltcG9ydCB7IGJ1aWxkV2FpdGVyIH0gZnJvbSAnZW1iZXItdGVzdC13YWl0ZXJzJzsKICAgKgogICAqIGlmIChERUJVRykgewogICAqICAgbGV0IHdhaXRlciA9IGJ1aWxkV2FpdGVyKCdmcmllbmQtd2FpdGVyJyk7CiAgICogfQogICAqCiAgICogZXhwb3J0IGRlZmF1bHQgY2xhc3MgRnJpZW5keiBleHRlbmRzIENvbXBvbmVudCB7CiAgICogICBkaWRJbnNlcnRFbGVtZW50KCkgewogICAqICAgICBsZXQgdG9rZW4gPSB3YWl0ZXIuYmVnaW5Bc3luYyh0aGlzKTsKICAgKgogICAqICAgICBzb21lQXN5bmNXb3JrKCkudGhlbigoKSA9PiB7CiAgICogICAgICAgd2FpdGVyLmVuZEFzeW5jKHRva2VuKTsKICAgKiAgICAgfSk7CiAgICogICB9CiAgICogfQogICAqLwogIGZ1bmN0aW9uIGJ1aWxkV2FpdGVyKG5hbWUpIHsKICAgIGlmIChmYWxzZQogICAgLyogREVCVUcgKi8KICAgICkgewogICAgICByZXR1cm4gbmV3IF9lbWJlclRlc3RXYWl0ZXJzLlRlc3RXYWl0ZXIobmFtZSk7CiAgICB9CgogICAgcmV0dXJuIG5ldyBfbm9vcFRlc3RXYWl0ZXIuZGVmYXVsdChuYW1lKTsKICB9Cn0pOwo7ZGVmaW5lKCJlbWJlci10ZXN0LXdhaXRlcnMvaW5kZXgiLCBbImV4cG9ydHMiLCAiZW1iZXItdGVzdC13YWl0ZXJzL3dhaXRlci1tYW5hZ2VyIiwgImVtYmVyLXRlc3Qtd2FpdGVycy90ZXN0LXdhaXRlciIsICJlbWJlci10ZXN0LXdhaXRlcnMvYnVpbGQtd2FpdGVyIiwgImVtYmVyLXRlc3Qtd2FpdGVycy93YWl0LWZvci1wcm9taXNlIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3dhaXRlck1hbmFnZXIsIF90ZXN0V2FpdGVyLCBfYnVpbGRXYWl0ZXIsIF93YWl0Rm9yUHJvbWlzZSkgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAicmVnaXN0ZXIiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfd2FpdGVyTWFuYWdlci5yZWdpc3RlcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJ1bnJlZ2lzdGVyIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3dhaXRlck1hbmFnZXIudW5yZWdpc3RlcjsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJnZXRXYWl0ZXJzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3dhaXRlck1hbmFnZXIuZ2V0V2FpdGVyczsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfcmVzZXQiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfd2FpdGVyTWFuYWdlci5fcmVzZXQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiZ2V0UGVuZGluZ1dhaXRlclN0YXRlIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3dhaXRlck1hbmFnZXIuZ2V0UGVuZGluZ1dhaXRlclN0YXRlOwogICAgfQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgImhhc1BlbmRpbmdXYWl0ZXJzIiwgewogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGdldDogZnVuY3Rpb24gZ2V0KCkgewogICAgICByZXR1cm4gX3dhaXRlck1hbmFnZXIuaGFzUGVuZGluZ1dhaXRlcnM7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiVGVzdFdhaXRlciIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF90ZXN0V2FpdGVyLmRlZmF1bHQ7CiAgICB9CiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiYnVpbGRXYWl0ZXIiLCB7CiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7CiAgICAgIHJldHVybiBfYnVpbGRXYWl0ZXIuZGVmYXVsdDsKICAgIH0KICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJ3YWl0Rm9yUHJvbWlzZSIsIHsKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHsKICAgICAgcmV0dXJuIF93YWl0Rm9yUHJvbWlzZS5kZWZhdWx0OwogICAgfQogIH0pOwp9KTsKO2RlZmluZSgiZW1iZXItdGVzdC13YWl0ZXJzL25vb3AtdGVzdC13YWl0ZXIiLCBbImV4cG9ydHMiXSwgZnVuY3Rpb24gKF9leHBvcnRzKSB7CiAgInVzZSBzdHJpY3QiOwoKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX2V4cG9ydHMsICJfX2VzTW9kdWxlIiwgewogICAgdmFsdWU6IHRydWUKICB9KTsKICBfZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwOwoKICBmdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbiIpOyB9IH0KCiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoInZhbHVlIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0KCiAgZnVuY3Rpb24gX2NyZWF0ZUNsYXNzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH0KCiAgLyoqCiAgICogQSBjbGFzcyBwcm92aWRpbmcgYSBwcm9kdWN0aW9uLCBub29wIHJlcGxhY2VtZW50IGZvciB0aGUge1Rlc3RXYWl0ZXI8VD59IGNsYXNzLgogICAqCiAgICogQHB1YmxpYwogICAqIEBjbGFzcyBUZXN0V2FpdGVyPFQ+CiAgICovCiAgdmFyIE5vb3BUZXN0V2FpdGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gTm9vcFRlc3RXYWl0ZXIobmFtZSkgewogICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgTm9vcFRlc3RXYWl0ZXIpOwoKICAgICAgdGhpcy5uYW1lID0gbmFtZTsKICAgIH0KCiAgICBfY3JlYXRlQ2xhc3MoTm9vcFRlc3RXYWl0ZXIsIFt7CiAgICAgIGtleTogImJlZ2luQXN5bmMiLAogICAgICB2YWx1ZTogZnVuY3Rpb24gYmVnaW5Bc3luYygpIHsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgfSwgewogICAgICBrZXk6ICJlbmRBc3luYyIsCiAgICAgIHZhbHVlOiBmdW5jdGlvbiBlbmRBc3luYygpIHt9CiAgICB9LCB7CiAgICAgIGtleTogIndhaXRVbnRpbCIsCiAgICAgIHZhbHVlOiBmdW5jdGlvbiB3YWl0VW50aWwoKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgIH0sIHsKICAgICAga2V5OiAiZGVidWdJbmZvIiwKICAgICAgdmFsdWU6IGZ1bmN0aW9uIGRlYnVnSW5mbygpIHsKICAgICAgICByZXR1cm4gW107CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gTm9vcFRlc3RXYWl0ZXI7CiAgfSgpOwoKICBfZXhwb3J0cy5kZWZhdWx0ID0gTm9vcFRlc3RXYWl0ZXI7Cn0pOwo7ZGVmaW5lKCJlbWJlci10ZXN0LXdhaXRlcnMvdGVzdC13YWl0ZXIiLCBbImV4cG9ydHMiLCAiZW1iZXItdGVzdC13YWl0ZXJzL3dhaXRlci1tYW5hZ2VyIl0sIGZ1bmN0aW9uIChfZXhwb3J0cywgX3dhaXRlck1hbmFnZXIpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7CgogIGZ1bmN0aW9uIF90b0NvbnN1bWFibGVBcnJheShhcnIpIHsgcmV0dXJuIF9hcnJheVdpdGhvdXRIb2xlcyhhcnIpIHx8IF9pdGVyYWJsZVRvQXJyYXkoYXJyKSB8fCBfbm9uSXRlcmFibGVTcHJlYWQoKTsgfQoKICBmdW5jdGlvbiBfbm9uSXRlcmFibGVTcHJlYWQoKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoIkludmFsaWQgYXR0ZW1wdCB0byBzcHJlYWQgbm9uLWl0ZXJhYmxlIGluc3RhbmNlIik7IH0KCiAgZnVuY3Rpb24gX2l0ZXJhYmxlVG9BcnJheShpdGVyKSB7IGlmIChTeW1ib2wuaXRlcmF0b3IgaW4gT2JqZWN0KGl0ZXIpIHx8IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpdGVyKSA9PT0gIltvYmplY3QgQXJndW1lbnRzXSIpIHJldHVybiBBcnJheS5mcm9tKGl0ZXIpOyB9CgogIGZ1bmN0aW9uIF9hcnJheVdpdGhvdXRIb2xlcyhhcnIpIHsgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgeyBmb3IgKHZhciBpID0gMCwgYXJyMiA9IG5ldyBBcnJheShhcnIubGVuZ3RoKTsgaSA8IGFyci5sZW5ndGg7IGkrKykgeyBhcnIyW2ldID0gYXJyW2ldOyB9IHJldHVybiBhcnIyOyB9IH0KCiAgZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24iKTsgfSB9CgogIGZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCJ2YWx1ZSIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9CgogIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyhDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9CgogIHZhciB0b2tlbiA9IDA7CgogIGZ1bmN0aW9uIGdldE5leHRUb2tlbigpIHsKICAgIHJldHVybiB0b2tlbisrOwogIH0KICAvKioKICAgKiBBIGNsYXNzIHByb3ZpZGluZyBjcmVhdGlvbiwgcmVnaXN0cmF0aW9uIGFuZCBhc3luYyB3YWl0aW5nIGZ1bmN0aW9uYWxpdHkuCiAgICoKICAgKiBAcHVibGljCiAgICogQGNsYXNzIFRlc3RXYWl0ZXI8VD4KICAgKi8KCgogIHZhciBUZXN0V2FpdGVyID0KICAvKiNfX1BVUkVfXyovCiAgZnVuY3Rpb24gKCkgewogICAgLyoqCiAgICAgKiBAcHVibGljCiAgICAgKiBAY29uc3RydWN0b3IKICAgICAqIEBwYXJhbSBuYW1lIHtXYWl0ZXJOYW1lfSB0aGUgbmFtZSBvZiB0aGUgdGVzdCB3YWl0ZXIKICAgICAqLwogICAgZnVuY3Rpb24gVGVzdFdhaXRlcihuYW1lLCBuZXh0VG9rZW4pIHsKICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFRlc3RXYWl0ZXIpOwoKICAgICAgdGhpcy5pc1JlZ2lzdGVyZWQgPSBmYWxzZTsKICAgICAgdGhpcy5pdGVtcyA9IG5ldyBNYXAoKTsKICAgICAgdGhpcy5uYW1lID0gbmFtZTsgLy8gQHRzLWlnbm9yZQoKICAgICAgdGhpcy5uZXh0VG9rZW4gPSBuZXh0VG9rZW4gfHwgZ2V0TmV4dFRva2VuOwogICAgfQogICAgLyoqCiAgICAgKiBXaWxsIHJlZ2lzdGVyIHRoZSB3YWl0ZXIsIGFsbG93aW5nIGl0IHRvIGJlIG9wdGVkIGluIHRvIHBhdXNpbmcgYXN5bmMKICAgICAqIG9wZXJhdGlvbnMgdW50aWwgdGhleSdyZSBjb21wbGV0ZWQgd2l0aGluIHlvdXIgdGVzdHMuIFlvdSBzaG91bGQgaW52b2tlCiAgICAgKiBpdCBhZnRlciBpbnN0YW50aWF0aW5nIHlvdXIgYFRlc3RXYWl0ZXJgIGluc3RhbmNlLgogICAgICoKICAgICAqICoqTm90ZSoqLCBpZiB5b3UgZm9yZ2V0IHRvIHJlZ2lzdGVyIHlvdXIgd2FpdGVyLCBpdCB3aWxsIGJlIHJlZ2lzdGVyZWQKICAgICAqIGZvciB5b3Ugb24gdGhlIGZpcnN0IGludm9jYXRpb24gb2YgYGJlZ2luQXN5bmNgLgogICAgICoKICAgICAqIEBwcml2YXRlCiAgICAgKiBAbWV0aG9kIHJlZ2lzdGVyCiAgICAgKi8KCgogICAgX2NyZWF0ZUNsYXNzKFRlc3RXYWl0ZXIsIFt7CiAgICAgIGtleTogInJlZ2lzdGVyIiwKICAgICAgdmFsdWU6IGZ1bmN0aW9uIHJlZ2lzdGVyKCkgewogICAgICAgIGlmICghdGhpcy5pc1JlZ2lzdGVyZWQpIHsKICAgICAgICAgICgwLCBfd2FpdGVyTWFuYWdlci5yZWdpc3RlcikodGhpcyk7CiAgICAgICAgICB0aGlzLmlzUmVnaXN0ZXJlZCA9IHRydWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIC8qKgogICAgICAgKiBTaG91bGQgYmUgdXNlZCB0byBzaWduYWwgdGhlIGJlZ2lubmluZyBvZiBhbiBhc3luYyBvcGVyYXRpb24gdGhhdAogICAgICAgKiBpcyB0byBiZSB3YWl0ZWQgZm9yLiBJbnZvY2F0aW9uIG9mIHRoaXMgbWV0aG9kIHNob3VsZCBiZSBwYWlyZWQgd2l0aCBhIHN1YnNlcXVlbnQKICAgICAgICogYGVuZEFzeW5jYCBjYWxsIHRvIGluZGljYXRlIHRvIHRoZSB3YWl0ZXIgc3lzdGVtIHRoYXQgdGhlIGFzeW5jIG9wZXJhdGlvbiBpcyBjb21wbGV0ZWQuCiAgICAgICAqCiAgICAgICAqIEBwdWJsaWMKICAgICAgICogQG1ldGhvZCBiZWdpbkFzeW5jCiAgICAgICAqIEBwYXJhbSBpdGVtIHtUfSBUaGUgaXRlbSB0byByZWdpc3RlciBmb3Igd2FpdGluZwogICAgICAgKiBAcGFyYW0gbGFiZWwge3N0cmluZ30gQW4gb3B0aW9uYWwgbGFiZWwgdG8gaWRlbnRpZnkgdGhlIGl0ZW0KICAgICAgICovCgogICAgfSwgewogICAgICBrZXk6ICJiZWdpbkFzeW5jIiwKICAgICAgdmFsdWU6IGZ1bmN0aW9uIGJlZ2luQXN5bmMoKSB7CiAgICAgICAgdmFyIHRva2VuID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiB0aGlzLm5leHRUb2tlbigpOwogICAgICAgIHZhciBsYWJlbCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkOwogICAgICAgIHRoaXMucmVnaXN0ZXIoKTsKCiAgICAgICAgaWYgKHRoaXMuaXRlbXMuaGFzKHRva2VuKSkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJiZWdpbkFzeW5jIGNhbGxlZCBmb3IgIi5jb25jYXQodG9rZW4sICIgYnV0IGl0IGlzIGFscmVhZHkgcGVuZGluZy4iKSk7CiAgICAgICAgfQoKICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoKTsKICAgICAgICB0aGlzLml0ZW1zLnNldCh0b2tlbiwgewogICAgICAgICAgZ2V0IHN0YWNrKCkgewogICAgICAgICAgICByZXR1cm4gZXJyb3Iuc3RhY2s7CiAgICAgICAgICB9LAoKICAgICAgICAgIGxhYmVsOiBsYWJlbAogICAgICAgIH0pOwogICAgICAgIHJldHVybiB0b2tlbjsKICAgICAgfQogICAgICAvKioKICAgICAgICogU2hvdWxkIGJlIHVzZWQgdG8gc2lnbmFsIHRoZSBlbmQgb2YgYW4gYXN5bmMgb3BlcmF0aW9uLiBJbnZvY2F0aW9uIG9mIHRoaXMKICAgICAgICogbWV0aG9kIHNob3VsZCBiZSBwYWlyZWQgd2l0aCBhIHByZWNlZWRpbmcgYGJlZ2luQXN5bmNgIGNhbGwsIHdoaWNoIHdvdWxkIGluZGljYXRlIHRoZQogICAgICAgKiBiZWdpbm5pbmcgb2YgYW4gYXN5bmMgb3BlcmF0aW9uLgogICAgICAgKgogICAgICAgKiBAcHVibGljCiAgICAgICAqIEBtZXRob2QgZW5kQXN5bmMKICAgICAgICogQHBhcmFtIGl0ZW0ge1R9IFRoZSBpdGVtIHRvIHRoYXQgd2FzIHJlZ2lzdGVyZWQgZm9yIHdhaXRpbmcKICAgICAgICovCgogICAgfSwgewogICAgICBrZXk6ICJlbmRBc3luYyIsCiAgICAgIHZhbHVlOiBmdW5jdGlvbiBlbmRBc3luYyh0b2tlbikgewogICAgICAgIGlmICghdGhpcy5pdGVtcy5oYXModG9rZW4pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImVuZEFzeW5jIGNhbGxlZCBmb3IgIi5jb25jYXQodG9rZW4sICIgYnV0IGl0IGlzIG5vdCBjdXJyZW50bHkgcGVuZGluZy4iKSk7CiAgICAgICAgfQoKICAgICAgICB0aGlzLml0ZW1zLmRlbGV0ZSh0b2tlbik7CiAgICAgIH0KICAgICAgLyoqCiAgICAgICAqIFVzZWQgdG8gZGV0ZXJtaW5lIGlmIHRoZSB3YWl0ZXIgc3lzdGVtIHNob3VsZCBzdGlsbCB3YWl0IGZvciBhc3luYwogICAgICAgKiBvcGVyYXRpb25zIHRvIGNvbXBsZXRlLgogICAgICAgKgogICAgICAgKiBAcHVibGljCiAgICAgICAqIEBtZXRob2Qgd2FpdFVudGlsCiAgICAgICAqIEByZXR1cm5zIHtib29sZWFufQogICAgICAgKi8KCiAgICB9LCB7CiAgICAgIGtleTogIndhaXRVbnRpbCIsCiAgICAgIHZhbHVlOiBmdW5jdGlvbiB3YWl0VW50aWwoKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuaXRlbXMuc2l6ZSA9PT0gMDsKICAgICAgfQogICAgICAvKioKICAgICAgICogUmV0dXJucyB0aGUgYGRlYnVnSW5mb2AgZm9yIGVhY2ggaXRlbSB0cmFja2luZyBhc3luYyBvcGVyYXRpb25zIGluIHRoaXMgd2FpdGVyLgogICAgICAgKgogICAgICAgKiBAcHVibGljCiAgICAgICAqIEBtZXRob2QgZGVidWdJbmZvCiAgICAgICAqIEByZXR1cm5zIHtJVGVzdFdhaXRlckRlYnVnSW5mb30KICAgICAgICovCgogICAgfSwgewogICAgICBrZXk6ICJkZWJ1Z0luZm8iLAogICAgICB2YWx1ZTogZnVuY3Rpb24gZGVidWdJbmZvKCkgewogICAgICAgIHJldHVybiBfdG9Db25zdW1hYmxlQXJyYXkodGhpcy5pdGVtcy52YWx1ZXMoKSk7CiAgICAgIH0KICAgIH1dKTsKCiAgICByZXR1cm4gVGVzdFdhaXRlcjsKICB9KCk7CgogIF9leHBvcnRzLmRlZmF1bHQgPSBUZXN0V2FpdGVyOwp9KTsKO2RlZmluZSgiZW1iZXItdGVzdC13YWl0ZXJzL3R5cGVzL2luZGV4IiwgW10sIGZ1bmN0aW9uICgpIHsKICAidXNlIHN0cmljdCI7Cn0pOwo7ZGVmaW5lKCJlbWJlci10ZXN0LXdhaXRlcnMvd2FpdC1mb3ItcHJvbWlzZSIsIFsiZXhwb3J0cyIsICJlbWJlci10ZXN0LXdhaXRlcnMvdGVzdC13YWl0ZXIiXSwgZnVuY3Rpb24gKF9leHBvcnRzLCBfdGVzdFdhaXRlcikgewogICJ1c2Ugc3RyaWN0IjsKCiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KF9leHBvcnRzLCAiX19lc01vZHVsZSIsIHsKICAgIHZhbHVlOiB0cnVlCiAgfSk7CiAgX2V4cG9ydHMuZGVmYXVsdCA9IHdhaXRGb3JQcm9taXNlOwogIHZhciBQUk9NSVNFX1dBSVRFUiA9IG5ldyBfdGVzdFdhaXRlci5kZWZhdWx0KCdwcm9taXNlLXdhaXRlcicpOwogIC8qKgogICAqIEEgY29udmVuaWVudCB1dGlsaXR5IGZ1bmN0aW9uIHRvIHNpbXBsaWZ5IHdhaXRpbmcgZm9yIGEgcHJvbWlzZS4KICAgKgogICAqIEBwdWJsaWMKICAgKiBAcGFyYW0gcHJvbWlzZSB7UHJvbWlzZTxUPn0gVGhlIHByb21pc2UgdG8gdHJhY2sgYXN5bmMgb3BlcmF0aW9ucyBmb3IKICAgKiBAcGFyYW0gbGFiZWwge3N0cmluZ30gQW4gb3B0aW9uYWwgc3RyaW5nIHRvIGlkZW50aWZ5IHRoZSBwcm9taXNlCiAgICoKICAgKiBAZXhhbXBsZQogICAqCiAgICogaW1wb3J0IENvbXBvbmVudCBmcm9tICdAZW1iZXIvY29tcG9uZW50JzsKICAgKiBpbXBvcnQgeyB3YWl0Rm9yUHJvbWlzZSB9IGZyb20gJ2VtYmVyLXRlc3Qtd2FpdGVycyc7CiAgICoKICAgKiBleHBvcnQgZGVmYXVsdCBjbGFzcyBGcmllbmR6IGV4dGVuZHMgQ29tcG9uZW50IHsKICAgKiAgIGRpZEluc2VydEVsZW1lbnQoKSB7CiAgICogICAgIHdhaXRGb3JQcm9taXNlKG5ldyBQcm9taXNlKHJlc29sdmUgPT4gewogICAqICAgICAgIGRvU29tZVdvcmsoKTsKICAgKiAgICAgICByZXNvbHZlKCk7CiAgICogICAgIH0pKTsKICAgKiAgIH0KICAgKiB9CiAgICovCgogIGZ1bmN0aW9uIHdhaXRGb3JQcm9taXNlKHByb21pc2UsIGxhYmVsKSB7CiAgICB2YXIgcmVzdWx0ID0gcHJvbWlzZTsKCiAgICBpZiAoZmFsc2UKICAgIC8qIERFQlVHICovCiAgICApIHsKICAgICAgUFJPTUlTRV9XQUlURVIuYmVnaW5Bc3luYyhwcm9taXNlLCBsYWJlbCk7CiAgICAgIHJlc3VsdCA9IHByb21pc2UudGhlbihmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgICBQUk9NSVNFX1dBSVRFUi5lbmRBc3luYyhwcm9taXNlKTsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0sIGZ1bmN0aW9uIChlcnJvcikgewogICAgICAgIFBST01JU0VfV0FJVEVSLmVuZEFzeW5jKHByb21pc2UpOwogICAgICAgIHRocm93IGVycm9yOwogICAgICB9KTsKICAgIH0KCiAgICByZXR1cm4gcmVzdWx0OwogIH0KfSk7CjtkZWZpbmUoImVtYmVyLXRlc3Qtd2FpdGVycy93YWl0ZXItbWFuYWdlciIsIFsiZXhwb3J0cyJdLCBmdW5jdGlvbiAoX2V4cG9ydHMpIHsKICAidXNlIHN0cmljdCI7CgogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7CiAgICB2YWx1ZTogdHJ1ZQogIH0pOwogIF9leHBvcnRzLnJlZ2lzdGVyID0gcmVnaXN0ZXI7CiAgX2V4cG9ydHMudW5yZWdpc3RlciA9IHVucmVnaXN0ZXI7CiAgX2V4cG9ydHMuZ2V0V2FpdGVycyA9IGdldFdhaXRlcnM7CiAgX2V4cG9ydHMuX3Jlc2V0ID0gX3Jlc2V0OwogIF9leHBvcnRzLmdldFBlbmRpbmdXYWl0ZXJTdGF0ZSA9IGdldFBlbmRpbmdXYWl0ZXJTdGF0ZTsKICBfZXhwb3J0cy5oYXNQZW5kaW5nV2FpdGVycyA9IGhhc1BlbmRpbmdXYWl0ZXJzOwoKICBmdW5jdGlvbiBfdG9Db25zdW1hYmxlQXJyYXkoYXJyKSB7IHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5KGFycikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7IH0KCiAgZnVuY3Rpb24gX25vbkl0ZXJhYmxlU3ByZWFkKCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJJbnZhbGlkIGF0dGVtcHQgdG8gc3ByZWFkIG5vbi1pdGVyYWJsZSBpbnN0YW5jZSIpOyB9CgogIGZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkoaXRlcikgeyBpZiAoU3ltYm9sLml0ZXJhdG9yIGluIE9iamVjdChpdGVyKSB8fCBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaXRlcikgPT09ICJbb2JqZWN0IEFyZ3VtZW50c10iKSByZXR1cm4gQXJyYXkuZnJvbShpdGVyKTsgfQoKICBmdW5jdGlvbiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB7IGlmIChBcnJheS5pc0FycmF5KGFycikpIHsgZm9yICh2YXIgaSA9IDAsIGFycjIgPSBuZXcgQXJyYXkoYXJyLmxlbmd0aCk7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHsgYXJyMltpXSA9IGFycltpXTsgfSByZXR1cm4gYXJyMjsgfSB9CgogIHZhciBXQUlURVJTID0gbmV3IE1hcCgpOwogIC8qKgogICAqIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggbGVnYWN5IHdhaXRlcnMgc3lzdGVtLgogICAqCiAgICogV2Ugd2FudCB0byBhbHdheXMgcmVnaXN0ZXIgYSB3YWl0ZXIgdXNpbmcgdGhlIGxlZ2FjeSB3YWl0ZXIgc3lzdGVtLCBhcyByaWdodAogICAqIG5vdyBpZiBjb25zdW1lcnMgYXJlIG5vdCBvbiB0aGUgcmlnaHQgdmVyc2lvbiBvZiBAZW1iZXIvdGVzdC1oZWxwZXJzLCB1c2luZwogICAqIHRoaXMgYWRkb24gd2lsbCByZXN1bHQgaW4gbm9uZSBvZiB0aGVzZSB3YWl0ZXJzIHdhaXRpbmcuCiAgICovCiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVtYmVyL25ldy1tb2R1bGUtaW1wb3J0cwoKICBpZiAoRW1iZXIuVGVzdCkgewogICAgRW1iZXIuVGVzdC5yZWdpc3RlcldhaXRlcihmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiAhaGFzUGVuZGluZ1dhaXRlcnMoKTsKICAgIH0pOwogIH0KICAvKioKICAgKiBSZWdpc3RlcnMgYSB3YWl0ZXIuCiAgICoKICAgKiBAcHVibGljCiAgICogQHBhcmFtIHdhaXRlciB7SVdhaXRlcn0gQSB0ZXN0IHdhaXRlciBpbnN0YW5jZQogICAqLwoKCiAgZnVuY3Rpb24gcmVnaXN0ZXIod2FpdGVyKSB7CiAgICBXQUlURVJTLnNldCh3YWl0ZXIubmFtZSwgd2FpdGVyKTsKICB9CiAgLyoqCiAgICogVW5yZWdpc3RlcnMgYSB3YWl0ZXIuCiAgICoKICAgKiBAcHVibGljCiAgICogQHBhcmFtIHdhaXRlciB7SVdhaXRlcn0gQSB0ZXN0IHdhaXRlciBpbnN0YW5jZQogICAqLwoKCiAgZnVuY3Rpb24gdW5yZWdpc3Rlcih3YWl0ZXIpIHsKICAgIFdBSVRFUlMuZGVsZXRlKHdhaXRlci5uYW1lKTsKICB9CiAgLyoqCiAgICogR2V0cyBhbiBhcnJheSBvZiBhbGwgd2FpdGVycyBjdXJyZW50IHJlZ2lzdGVyZWQuCiAgICoKICAgKiBAcHVibGljCiAgICogQHJldHVybnMge0lXYWl0ZXJbXX0KICAgKi8KCgogIGZ1bmN0aW9uIGdldFdhaXRlcnMoKSB7CiAgICByZXR1cm4gX3RvQ29uc3VtYWJsZUFycmF5KFdBSVRFUlMudmFsdWVzKCkpOwogIH0KICAvKioKICAgKiBDbGVhcnMgYWxsIHdhaXRlcnMuCiAgICoKICAgKiBAcHVibGljCiAgICovCgoKICBmdW5jdGlvbiBfcmVzZXQoKSB7CiAgICBXQUlURVJTLmNsZWFyKCk7CiAgfQogIC8qKgogICAqIEdldHMgdGhlIGN1cnJlbnQgc3RhdGUgb2YgYWxsIHdhaXRlcnMuIEFueSB3YWl0ZXJzIHdob3NlCiAgICogYHdhaXRVbnRpbGAgbWV0aG9kIHJldHVybnMgZmFsc2Ugd2lsbCBiZSBjb25zaWRlcmVkIGBwZW5kaW5nYC4KICAgKgogICAqIEByZXR1cm5zIHtJUGVuZGluZ1dhaXRlclN0YXRlfSBBbiBvYmplY3QgY29udGFpbmluZyBhIGNvdW50IG9mIGFsbCB3YWl0ZXJzCiAgICogcGVuZGluZyBhbmQgYSBgd2FpdGVyc2Agb2JqZWN0IGNvbnRhaW5pbmcgdGhlIG5hbWUgb2YgYWxsIHBlbmRpbmcgd2FpdGVycwogICAqIGFuZCB0aGVpciBkZWJ1ZyBpbmZvLgogICAqLwoKCiAgZnVuY3Rpb24gZ2V0UGVuZGluZ1dhaXRlclN0YXRlKCkgewogICAgdmFyIHJlc3VsdCA9IHsKICAgICAgcGVuZGluZzogMCwKICAgICAgd2FpdGVyczoge30KICAgIH07CiAgICBXQUlURVJTLmZvckVhY2goZnVuY3Rpb24gKHdhaXRlcikgewogICAgICBpZiAoIXdhaXRlci53YWl0VW50aWwoKSkgewogICAgICAgIHJlc3VsdC5wZW5kaW5nKys7CiAgICAgICAgdmFyIGRlYnVnSW5mbyA9IHdhaXRlci5kZWJ1Z0luZm8oKTsKICAgICAgICByZXN1bHQud2FpdGVyc1t3YWl0ZXIubmFtZV0gPSBkZWJ1Z0luZm8gfHwgdHJ1ZTsKICAgICAgfQogICAgfSk7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICAvKioKICAgKiBEZXRlcm1pbmVzIGlmIHRoZXJlIGFyZSBhbnkgcGVuZGluZyB3YWl0ZXJzLgogICAqCiAgICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGVyZSBhcmUgcGVuZGluZyB3YWl0ZXJzLCBvdGhlcndpc2UgYGZhbHNlYC4KICAgKi8KCgogIGZ1bmN0aW9uIGhhc1BlbmRpbmdXYWl0ZXJzKCkgewogICAgdmFyIHN0YXRlID0gZ2V0UGVuZGluZ1dhaXRlclN0YXRlKCk7CiAgICByZXR1cm4gc3RhdGUucGVuZGluZyA+IDA7CiAgfQp9KTsKOwo=", "encoding": "base64" }, "redirectURL": "", - "headersSize": -1, - "bodySize": -1, - "_transferSize": 2798273 + "headersSize": 162, + "bodySize": 2799137, + "_transferSize": 2799299 }, "cache": {}, "timings": { - "blocked": 4.974999987011776, - "dns": 0.02100000000000002, + "blocked": 4.112999999948894, + "dns": 0.014000000000000012, "ssl": -1, - "connect": 0.6519999999999999, - "send": 0.5310000000000001, - "wait": 0.34799998905882235, - "receive": 91.15400002337992, - "_blocked_queueing": 4.603999987011775 + "connect": 0.7029999999999998, + "send": 0.3460000000000001, + "wait": 1.466999999571708, + "receive": 86.4369999999326, + "_blocked_queueing": 2.7669999999488937 }, "serverIPAddress": "[::1]", "_initiator": { "type": "parser", - "url": "http://localhost:5000/", + "url": "http://localhost:4200/", "lineNumber": 20 }, "_priority": "High", "_resourceType": "script", - "connection": "1053028", - "pageref": "page_4" + "connection": "50828", + "pageref": "page_1" }, { - "startedDateTime": "2019-10-25T21:01:03.342Z", - "time": 9.752000005897134, + "startedDateTime": "2019-10-31T20:32:57.804Z", + "time": 6.334999998469138, "request": { "method": "GET", - "url": "http://localhost:5000/assets/relationship-performance-test-app-8fc45da25f5c547c8074bae505970bfb.js", - "httpVersion": "http/1.1", + "url": "http://localhost:4200/assets/relationship-performance-test-app.js", + "httpVersion": "HTTP/1.1", "headers": [ + { + "name": "Host", + "value": "localhost:4200" + }, + { + "name": "Connection", + "value": "keep-alive" + }, + { + "name": "User-Agent", + "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36" + }, + { + "name": "Accept", + "value": "*/*" + }, + { + "name": "Sec-Fetch-Site", + "value": "same-origin" + }, { "name": "Sec-Fetch-Mode", "value": "no-cors" }, { "name": "Referer", - "value": "http://localhost:5000/" + "value": "http://localhost:4200/" }, { - "name": "User-Agent", - "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36" + "name": "Accept-Encoding", + "value": "gzip, deflate, br" + }, + { + "name": "Accept-Language", + "value": "en-US,en;q=0.9" + }, + { + "name": "Cookie", + "value": "io=wIu7CXtmPvSmDD1VAAAM; amplitude_id_5e201f0eac128f83637a72cc714578f0=eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MjM4NjI4OTk2MiwibGFzdEV2ZW50VGltZSI6MTU3MjM4ODkwNjkxNiwiZXZlbnRJZCI6MTgyLCJpZGVudGlmeUlkIjo5NCwic2VxdWVuY2VOdW1iZXIiOjI3Nn0=" } ], "queryString": [], - "cookies": [], - "headersSize": -1, + "cookies": [ + { + "name": "io", + "value": "wIu7CXtmPvSmDD1VAAAM", + "expires": null, + "httpOnly": false, + "secure": false + }, + { + "name": "amplitude_id_5e201f0eac128f83637a72cc714578f0", + "value": "eyJkZXZpY2VJZCI6IjFjNDI0NTRkLTg5MjgtNDc2OC05MzE3LTJlZjFhZWIyOGEyY1IiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU3MjM4NjI4OTk2MiwibGFzdEV2ZW50VGltZSI6MTU3MjM4ODkwNjkxNiwiZXZlbnRJZCI6MTgyLCJpZGVudGlmeUlkIjo5NCwic2VxdWVuY2VOdW1iZXIiOjI3Nn0=", + "expires": null, + "httpOnly": false, + "secure": false + } + ], + "headersSize": 741, "bodySize": 0 }, "response": { "status": 200, "statusText": "OK", - "httpVersion": "http/1.1", + "httpVersion": "HTTP/1.1", "headers": [ + { + "name": "Host", + "value": "localhost:4200" + }, { "name": "Date", - "value": "Fri, 25 Oct 2019 21:01:03 +0000" + "value": "Thu, 31 Oct 2019 20:32:57 +0000" }, { "name": "Connection", "value": "close" }, { - "name": "Host", - "value": "localhost:5000" + "name": "Content-Type", + "value": "application/javascript" }, { "name": "Content-Length", "value": "22947" - }, - { - "name": "Content-Type", - "value": "application/javascript" } ], "cookies": [], "content": { "size": 22947, "mimeType": "application/javascript", - "text": "'use strict';\n\n\n\n;define(\"relationship-performance-test-app/adapters/-json-api\", [\"exports\", \"@ember-data/adapter/json-api\"], function (_exports, _jsonApi) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _jsonApi.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/adapters/application\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\n function _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\n function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\n function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\n function _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\n function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\n function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\n function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n function _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\n function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\n var ApplicationMockAdapter =\n /*#__PURE__*/\n function (_EmberObject) {\n _inherits(ApplicationMockAdapter, _EmberObject);\n\n function ApplicationMockAdapter() {\n _classCallCheck(this, ApplicationMockAdapter);\n\n return _possibleConstructorReturn(this, _getPrototypeOf(ApplicationMockAdapter).apply(this, arguments));\n }\n\n _createClass(ApplicationMockAdapter, [{\n key: \"findAll\",\n value: function findAll() {\n return Ember.RSVP.resolve(createCarsPayload(10000));\n }\n }, {\n key: \"shouldReloadAll\",\n value: function shouldReloadAll() {\n return false;\n }\n }, {\n key: \"shouldBackgroundReloadAll\",\n value: function shouldBackgroundReloadAll() {\n return false;\n }\n }]);\n\n return ApplicationMockAdapter;\n }(Ember.Object);\n\n _exports.default = ApplicationMockAdapter;\n var COLORS = ['red', 'white', 'black', 'pink', 'green', 'blue', 'yellow', 'orange', 'green', 'teal'];\n var SIZES = ['square', 'rectangle', 'circle', 'oval', 'cube', 'small', 'medium', 'large', 'extra large'];\n var TYPES = ['suv', 'sedan', 'minivan', 'electric', 'hybrid', 'truck', 'sport'];\n var FIXTURE_ID = 0;\n\n function getIndex(index, fixtures) {\n var count = fixtures.length;\n return index % count;\n }\n\n function assignToMany(resource, id) {\n resource.relationships = resource.relationships || {};\n var cars = resource.relationships.cars = resource.relationships.cars || {\n data: []\n };\n cars.data.push({\n type: 'car',\n id: id\n });\n }\n\n function getRelatedResource(fixtures, index, id) {\n var resource = fixtures[getIndex(index, fixtures)];\n assignToMany(resource, id);\n return {\n id: resource.id,\n type: resource.type\n };\n }\n\n function createCarsPayload(n) {\n performance.mark('start-fixture-generation');\n var colors = getColorResources();\n var types = getTypeResources();\n var sizes = getSizeResources();\n var fixture = {\n data: _toConsumableArray(new Array(n)).map(function (v, i) {\n var id = \"urn:car:\".concat(FIXTURE_ID++);\n return {\n id: id,\n type: 'car',\n attributes: {},\n relationships: {\n type: {\n data: getRelatedResource(types, i, id)\n },\n size: {\n data: getRelatedResource(sizes, i, id)\n },\n colors: {\n data: [getRelatedResource(colors, i, id), getRelatedResource(colors, i + 1, id), getRelatedResource(colors, i + 2, id)]\n }\n }\n };\n }),\n included: [].concat(colors, types, sizes)\n };\n performance.mark('end-fixture-generation');\n return fixture;\n }\n\n function getColorResources() {\n return COLORS.map(function (name) {\n return createJsonApiResource(\"urn:color:\".concat(FIXTURE_ID++), 'color', {\n name: name\n });\n });\n }\n\n function getSizeResources() {\n return SIZES.map(function (name) {\n return createJsonApiResource(\"urn:size:\".concat(FIXTURE_ID++), 'size', {\n name: name\n });\n });\n }\n\n function getTypeResources() {\n return TYPES.map(function (name) {\n return createJsonApiResource(\"urn:type:\".concat(FIXTURE_ID++), 'type', {\n name: name\n });\n });\n }\n\n function createJsonApiResource(id, type, attributes) {\n return {\n id: id,\n type: type,\n attributes: attributes\n };\n }\n});\n;define(\"relationship-performance-test-app/app\", [\"exports\", \"relationship-performance-test-app/resolver\", \"ember-load-initializers\", \"relationship-performance-test-app/config/environment\"], function (_exports, _resolver, _emberLoadInitializers, _environment) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var App = Ember.Application.extend({\n modulePrefix: _environment.default.modulePrefix,\n podModulePrefix: _environment.default.podModulePrefix,\n Resolver: _resolver.default\n });\n (0, _emberLoadInitializers.default)(App, _environment.default.modulePrefix);\n var _default = App;\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/data-adapter\", [\"exports\", \"@ember-data/debug\"], function (_exports, _debug) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _debug.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/helpers/app-version\", [\"exports\", \"relationship-performance-test-app/config/environment\", \"ember-cli-app-version/utils/regexp\"], function (_exports, _environment, _regexp) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.appVersion = appVersion;\n _exports.default = void 0;\n\n function appVersion(_) {\n var hash = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var version = _environment.default.APP.version; // e.g. 1.0.0-alpha.1+4jds75hf\n // Allow use of 'hideSha' and 'hideVersion' For backwards compatibility\n\n var versionOnly = hash.versionOnly || hash.hideSha;\n var shaOnly = hash.shaOnly || hash.hideVersion;\n var match = null;\n\n if (versionOnly) {\n if (hash.showExtended) {\n match = version.match(_regexp.versionExtendedRegExp); // 1.0.0-alpha.1\n } // Fallback to just version\n\n\n if (!match) {\n match = version.match(_regexp.versionRegExp); // 1.0.0\n }\n }\n\n if (shaOnly) {\n match = version.match(_regexp.shaRegExp); // 4jds75hf\n }\n\n return match ? match[0] : version;\n }\n\n var _default = Ember.Helper.helper(appVersion);\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/helpers/pluralize\", [\"exports\", \"ember-inflector/lib/helpers/pluralize\"], function (_exports, _pluralize) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var _default = _pluralize.default;\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/helpers/singularize\", [\"exports\", \"ember-inflector/lib/helpers/singularize\"], function (_exports, _singularize) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var _default = _singularize.default;\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/initializers/app-version\", [\"exports\", \"ember-cli-app-version/initializer-factory\", \"relationship-performance-test-app/config/environment\"], function (_exports, _initializerFactory, _environment) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var name, version;\n\n if (_environment.default.APP) {\n name = _environment.default.APP.name;\n version = _environment.default.APP.version;\n }\n\n var _default = {\n name: 'App Version',\n initialize: (0, _initializerFactory.default)(name, version)\n };\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/initializers/container-debug-adapter\", [\"exports\", \"ember-resolver/resolvers/classic/container-debug-adapter\"], function (_exports, _containerDebugAdapter) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var _default = {\n name: 'container-debug-adapter',\n initialize: function initialize() {\n var app = arguments[1] || arguments[0];\n app.register('container-debug-adapter:main', _containerDebugAdapter.default);\n app.inject('container-debug-adapter:main', 'namespace', 'application:main');\n }\n };\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/initializers/ember-data-data-adapter\", [\"exports\", \"@ember-data/debug/setup\"], function (_exports, _setup) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _setup.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/initializers/ember-data\", [\"exports\", \"ember-data/setup-container\", \"ember-data\"], function (_exports, _setupContainer, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n /*\n This code initializes EmberData in an Ember application.\n \n It ensures that the `store` service is automatically injected\n as the `store` property on all routes and controllers.\n */\n var _default = {\n name: 'ember-data',\n initialize: _setupContainer.default\n };\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/initializers/export-application-global\", [\"exports\", \"relationship-performance-test-app/config/environment\"], function (_exports, _environment) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.initialize = initialize;\n _exports.default = void 0;\n\n function initialize() {\n var application = arguments[1] || arguments[0];\n\n if (_environment.default.exportApplicationGlobal !== false) {\n var theGlobal;\n\n if (typeof window !== 'undefined') {\n theGlobal = window;\n } else if (typeof global !== 'undefined') {\n theGlobal = global;\n } else if (typeof self !== 'undefined') {\n theGlobal = self;\n } else {\n // no reasonable global, just bail\n return;\n }\n\n var value = _environment.default.exportApplicationGlobal;\n var globalName;\n\n if (typeof value === 'string') {\n globalName = value;\n } else {\n globalName = Ember.String.classify(_environment.default.modulePrefix);\n }\n\n if (!theGlobal[globalName]) {\n theGlobal[globalName] = application;\n application.reopen({\n willDestroy: function willDestroy() {\n this._super.apply(this, arguments);\n\n delete theGlobal[globalName];\n }\n });\n }\n }\n }\n\n var _default = {\n name: 'export-application-global',\n initialize: initialize\n };\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/instance-initializers/ember-data\", [\"exports\", \"ember-data/initialize-store-service\"], function (_exports, _initializeStoreService) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var _default = {\n name: 'ember-data',\n initialize: _initializeStoreService.default\n };\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/models/car\", [\"exports\", \"ember-data\"], function (_exports, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var Model = _emberData.default.Model,\n belongsTo = _emberData.default.belongsTo,\n hasMany = _emberData.default.hasMany;\n\n var _default = Model.extend({\n type: belongsTo('type', {\n async: false\n }),\n size: belongsTo('size', {\n async: false\n }),\n colors: hasMany('color', {\n async: false\n })\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/models/color\", [\"exports\", \"ember-data\"], function (_exports, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var Model = _emberData.default.Model,\n attr = _emberData.default.attr,\n hasMany = _emberData.default.hasMany;\n\n var _default = Model.extend({\n name: attr('string'),\n cars: hasMany('car', {\n async: false\n })\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/models/size\", [\"exports\", \"ember-data\"], function (_exports, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var Model = _emberData.default.Model,\n attr = _emberData.default.attr,\n hasMany = _emberData.default.hasMany;\n\n var _default = Model.extend({\n name: attr('string'),\n cars: hasMany('car', {\n async: false\n })\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/models/type\", [\"exports\", \"ember-data\"], function (_exports, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var Model = _emberData.default.Model,\n attr = _emberData.default.attr,\n hasMany = _emberData.default.hasMany;\n\n var _default = Model.extend({\n name: attr('string'),\n cars: hasMany('car', {\n async: false\n })\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/resolver\", [\"exports\", \"ember-resolver\"], function (_exports, _emberResolver) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var _default = _emberResolver.default;\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/router\", [\"exports\", \"relationship-performance-test-app/config/environment\"], function (_exports, _environment) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var Router = Ember.Router.extend({\n location: _environment.default.locationType,\n rootURL: _environment.default.rootURL\n });\n Router.map(function () {});\n var _default = Router;\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/routes/application\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n var _default = Ember.Route.extend({\n model: function model() {\n performance.mark('start-find-all');\n return this.store.findAll('car', {\n reload: true\n }).then(function (cars) {\n performance.mark('start-outer-materialization');\n var flattened = cars.map(function (car) {\n // enforce materialization of our relationships\n return {\n name: car.id,\n size: car.size.name,\n type: car.type.name,\n colors: car.colors.map(function (color) {\n return color.name;\n })\n };\n });\n performance.mark('stop-outer-materialization');\n performance.mark('end-find-all');\n return flattened;\n });\n },\n afterModel: function afterModel() {\n if (document.location.href.indexOf('?tracerbench=true') !== -1) {\n document.location.href = 'about:blank';\n }\n }\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/serializers/-default\", [\"exports\", \"@ember-data/serializer/json\"], function (_exports, _json) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _json.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/serializers/-json-api\", [\"exports\", \"@ember-data/serializer/json-api\"], function (_exports, _jsonApi) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _jsonApi.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/serializers/-rest\", [\"exports\", \"@ember-data/serializer/rest\"], function (_exports, _rest) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _rest.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/serializers/application\", [\"exports\", \"ember-data\"], function (_exports, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n var _default = _emberData.default.JSONAPISerializer.extend({\n normalizeResponse: function normalizeResponse(store, primaryModelClass, payload) {\n return payload;\n }\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/services/store\", [\"exports\", \"ember-data/store\"], function (_exports, _store) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _store.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/templates/application\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n var _default = Ember.HTMLBars.template({\n \"id\": \"6nqMC1Ym\",\n \"block\": \"{\\\"symbols\\\":[],\\\"statements\\\":[],\\\"hasEval\\\":false}\",\n \"meta\": {\n \"moduleName\": \"relationship-performance-test-app/templates/application.hbs\"\n }\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/transforms/boolean\", [\"exports\", \"@ember-data/serializer/-private\"], function (_exports, _private) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _private.BooleanTransform;\n }\n });\n});\n;define(\"relationship-performance-test-app/transforms/date\", [\"exports\", \"@ember-data/serializer/-private\"], function (_exports, _private) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _private.DateTransform;\n }\n });\n});\n;define(\"relationship-performance-test-app/transforms/number\", [\"exports\", \"@ember-data/serializer/-private\"], function (_exports, _private) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _private.NumberTransform;\n }\n });\n});\n;define(\"relationship-performance-test-app/transforms/string\", [\"exports\", \"@ember-data/serializer/-private\"], function (_exports, _private) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _private.StringTransform;\n }\n });\n});\n;\n\n;define('relationship-performance-test-app/config/environment', [], function() {\n var prefix = 'relationship-performance-test-app';\ntry {\n var metaName = prefix + '/config/environment';\n var rawConfig = document.querySelector('meta[name=\"' + metaName + '\"]').getAttribute('content');\n var config = JSON.parse(decodeURIComponent(rawConfig));\n\n var exports = { 'default': config };\n\n Object.defineProperty(exports, '__esModule', { value: true });\n\n return exports;\n}\ncatch(err) {\n throw new Error('Could not read config from meta tag with name \"' + metaName + '\".');\n}\n\n});\n\n;\n if (!runningTests) {\n require(\"relationship-performance-test-app/app\")[\"default\"].create({\"name\":\"relationship-performance-test-app\",\"version\":\"3.15.0-alpha.1+5e94a8b2\"});\n }\n \n" + "compression": 0, + "text": "'use strict';\n\n\n\n;define(\"relationship-performance-test-app/adapters/-json-api\", [\"exports\", \"@ember-data/adapter/json-api\"], function (_exports, _jsonApi) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _jsonApi.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/adapters/application\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }\n\n function _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance\"); }\n\n function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter); }\n\n function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }\n\n function _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\n function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\n function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\n function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n function _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\n function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\n var ApplicationMockAdapter =\n /*#__PURE__*/\n function (_EmberObject) {\n _inherits(ApplicationMockAdapter, _EmberObject);\n\n function ApplicationMockAdapter() {\n _classCallCheck(this, ApplicationMockAdapter);\n\n return _possibleConstructorReturn(this, _getPrototypeOf(ApplicationMockAdapter).apply(this, arguments));\n }\n\n _createClass(ApplicationMockAdapter, [{\n key: \"findAll\",\n value: function findAll() {\n return Ember.RSVP.resolve(createCarsPayload(10000));\n }\n }, {\n key: \"shouldReloadAll\",\n value: function shouldReloadAll() {\n return false;\n }\n }, {\n key: \"shouldBackgroundReloadAll\",\n value: function shouldBackgroundReloadAll() {\n return false;\n }\n }]);\n\n return ApplicationMockAdapter;\n }(Ember.Object);\n\n _exports.default = ApplicationMockAdapter;\n var COLORS = ['red', 'white', 'black', 'pink', 'green', 'blue', 'yellow', 'orange', 'green', 'teal'];\n var SIZES = ['square', 'rectangle', 'circle', 'oval', 'cube', 'small', 'medium', 'large', 'extra large'];\n var TYPES = ['suv', 'sedan', 'minivan', 'electric', 'hybrid', 'truck', 'sport'];\n var FIXTURE_ID = 0;\n\n function getIndex(index, fixtures) {\n var count = fixtures.length;\n return index % count;\n }\n\n function assignToMany(resource, id) {\n resource.relationships = resource.relationships || {};\n var cars = resource.relationships.cars = resource.relationships.cars || {\n data: []\n };\n cars.data.push({\n type: 'car',\n id: id\n });\n }\n\n function getRelatedResource(fixtures, index, id) {\n var resource = fixtures[getIndex(index, fixtures)];\n assignToMany(resource, id);\n return {\n id: resource.id,\n type: resource.type\n };\n }\n\n function createCarsPayload(n) {\n performance.mark('start-fixture-generation');\n var colors = getColorResources();\n var types = getTypeResources();\n var sizes = getSizeResources();\n var fixture = {\n data: _toConsumableArray(new Array(n)).map(function (v, i) {\n var id = \"urn:car:\".concat(FIXTURE_ID++);\n return {\n id: id,\n type: 'car',\n attributes: {},\n relationships: {\n type: {\n data: getRelatedResource(types, i, id)\n },\n size: {\n data: getRelatedResource(sizes, i, id)\n },\n colors: {\n data: [getRelatedResource(colors, i, id), getRelatedResource(colors, i + 1, id), getRelatedResource(colors, i + 2, id)]\n }\n }\n };\n }),\n included: [].concat(colors, types, sizes)\n };\n performance.mark('end-fixture-generation');\n return fixture;\n }\n\n function getColorResources() {\n return COLORS.map(function (name) {\n return createJsonApiResource(\"urn:color:\".concat(FIXTURE_ID++), 'color', {\n name: name\n });\n });\n }\n\n function getSizeResources() {\n return SIZES.map(function (name) {\n return createJsonApiResource(\"urn:size:\".concat(FIXTURE_ID++), 'size', {\n name: name\n });\n });\n }\n\n function getTypeResources() {\n return TYPES.map(function (name) {\n return createJsonApiResource(\"urn:type:\".concat(FIXTURE_ID++), 'type', {\n name: name\n });\n });\n }\n\n function createJsonApiResource(id, type, attributes) {\n return {\n id: id,\n type: type,\n attributes: attributes\n };\n }\n});\n;define(\"relationship-performance-test-app/app\", [\"exports\", \"relationship-performance-test-app/resolver\", \"ember-load-initializers\", \"relationship-performance-test-app/config/environment\"], function (_exports, _resolver, _emberLoadInitializers, _environment) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var App = Ember.Application.extend({\n modulePrefix: _environment.default.modulePrefix,\n podModulePrefix: _environment.default.podModulePrefix,\n Resolver: _resolver.default\n });\n (0, _emberLoadInitializers.default)(App, _environment.default.modulePrefix);\n var _default = App;\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/data-adapter\", [\"exports\", \"@ember-data/debug\"], function (_exports, _debug) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _debug.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/helpers/app-version\", [\"exports\", \"relationship-performance-test-app/config/environment\", \"ember-cli-app-version/utils/regexp\"], function (_exports, _environment, _regexp) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.appVersion = appVersion;\n _exports.default = void 0;\n\n function appVersion(_) {\n var hash = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var version = _environment.default.APP.version; // e.g. 1.0.0-alpha.1+4jds75hf\n // Allow use of 'hideSha' and 'hideVersion' For backwards compatibility\n\n var versionOnly = hash.versionOnly || hash.hideSha;\n var shaOnly = hash.shaOnly || hash.hideVersion;\n var match = null;\n\n if (versionOnly) {\n if (hash.showExtended) {\n match = version.match(_regexp.versionExtendedRegExp); // 1.0.0-alpha.1\n } // Fallback to just version\n\n\n if (!match) {\n match = version.match(_regexp.versionRegExp); // 1.0.0\n }\n }\n\n if (shaOnly) {\n match = version.match(_regexp.shaRegExp); // 4jds75hf\n }\n\n return match ? match[0] : version;\n }\n\n var _default = Ember.Helper.helper(appVersion);\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/helpers/pluralize\", [\"exports\", \"ember-inflector/lib/helpers/pluralize\"], function (_exports, _pluralize) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var _default = _pluralize.default;\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/helpers/singularize\", [\"exports\", \"ember-inflector/lib/helpers/singularize\"], function (_exports, _singularize) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var _default = _singularize.default;\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/initializers/app-version\", [\"exports\", \"ember-cli-app-version/initializer-factory\", \"relationship-performance-test-app/config/environment\"], function (_exports, _initializerFactory, _environment) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var name, version;\n\n if (_environment.default.APP) {\n name = _environment.default.APP.name;\n version = _environment.default.APP.version;\n }\n\n var _default = {\n name: 'App Version',\n initialize: (0, _initializerFactory.default)(name, version)\n };\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/initializers/container-debug-adapter\", [\"exports\", \"ember-resolver/resolvers/classic/container-debug-adapter\"], function (_exports, _containerDebugAdapter) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var _default = {\n name: 'container-debug-adapter',\n initialize: function initialize() {\n var app = arguments[1] || arguments[0];\n app.register('container-debug-adapter:main', _containerDebugAdapter.default);\n app.inject('container-debug-adapter:main', 'namespace', 'application:main');\n }\n };\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/initializers/ember-data-data-adapter\", [\"exports\", \"@ember-data/debug/setup\"], function (_exports, _setup) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _setup.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/initializers/ember-data\", [\"exports\", \"ember-data/setup-container\", \"ember-data\"], function (_exports, _setupContainer, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n /*\n This code initializes EmberData in an Ember application.\n \n It ensures that the `store` service is automatically injected\n as the `store` property on all routes and controllers.\n */\n var _default = {\n name: 'ember-data',\n initialize: _setupContainer.default\n };\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/initializers/export-application-global\", [\"exports\", \"relationship-performance-test-app/config/environment\"], function (_exports, _environment) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.initialize = initialize;\n _exports.default = void 0;\n\n function initialize() {\n var application = arguments[1] || arguments[0];\n\n if (_environment.default.exportApplicationGlobal !== false) {\n var theGlobal;\n\n if (typeof window !== 'undefined') {\n theGlobal = window;\n } else if (typeof global !== 'undefined') {\n theGlobal = global;\n } else if (typeof self !== 'undefined') {\n theGlobal = self;\n } else {\n // no reasonable global, just bail\n return;\n }\n\n var value = _environment.default.exportApplicationGlobal;\n var globalName;\n\n if (typeof value === 'string') {\n globalName = value;\n } else {\n globalName = Ember.String.classify(_environment.default.modulePrefix);\n }\n\n if (!theGlobal[globalName]) {\n theGlobal[globalName] = application;\n application.reopen({\n willDestroy: function willDestroy() {\n this._super.apply(this, arguments);\n\n delete theGlobal[globalName];\n }\n });\n }\n }\n }\n\n var _default = {\n name: 'export-application-global',\n initialize: initialize\n };\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/instance-initializers/ember-data\", [\"exports\", \"ember-data/initialize-store-service\"], function (_exports, _initializeStoreService) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var _default = {\n name: 'ember-data',\n initialize: _initializeStoreService.default\n };\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/models/car\", [\"exports\", \"ember-data\"], function (_exports, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var Model = _emberData.default.Model,\n belongsTo = _emberData.default.belongsTo,\n hasMany = _emberData.default.hasMany;\n\n var _default = Model.extend({\n type: belongsTo('type', {\n async: false\n }),\n size: belongsTo('size', {\n async: false\n }),\n colors: hasMany('color', {\n async: false\n })\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/models/color\", [\"exports\", \"ember-data\"], function (_exports, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var Model = _emberData.default.Model,\n attr = _emberData.default.attr,\n hasMany = _emberData.default.hasMany;\n\n var _default = Model.extend({\n name: attr('string'),\n cars: hasMany('car', {\n async: false\n })\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/models/size\", [\"exports\", \"ember-data\"], function (_exports, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var Model = _emberData.default.Model,\n attr = _emberData.default.attr,\n hasMany = _emberData.default.hasMany;\n\n var _default = Model.extend({\n name: attr('string'),\n cars: hasMany('car', {\n async: false\n })\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/models/type\", [\"exports\", \"ember-data\"], function (_exports, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var Model = _emberData.default.Model,\n attr = _emberData.default.attr,\n hasMany = _emberData.default.hasMany;\n\n var _default = Model.extend({\n name: attr('string'),\n cars: hasMany('car', {\n async: false\n })\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/resolver\", [\"exports\", \"ember-resolver\"], function (_exports, _emberResolver) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var _default = _emberResolver.default;\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/router\", [\"exports\", \"relationship-performance-test-app/config/environment\"], function (_exports, _environment) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n var Router = Ember.Router.extend({\n location: _environment.default.locationType,\n rootURL: _environment.default.rootURL\n });\n Router.map(function () {});\n var _default = Router;\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/routes/application\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n var _default = Ember.Route.extend({\n model: function model() {\n performance.mark('start-find-all');\n return this.store.findAll('car', {\n reload: true\n }).then(function (cars) {\n performance.mark('start-outer-materialization');\n var flattened = cars.map(function (car) {\n // enforce materialization of our relationships\n return {\n name: car.id,\n size: car.size.name,\n type: car.type.name,\n colors: car.colors.map(function (color) {\n return color.name;\n })\n };\n });\n performance.mark('stop-outer-materialization');\n performance.mark('end-find-all');\n return flattened;\n });\n },\n afterModel: function afterModel() {\n if (document.location.href.indexOf('?tracerbench=true') !== -1) {\n document.location.href = 'about:blank';\n }\n }\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/serializers/-default\", [\"exports\", \"@ember-data/serializer/json\"], function (_exports, _json) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _json.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/serializers/-json-api\", [\"exports\", \"@ember-data/serializer/json-api\"], function (_exports, _jsonApi) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _jsonApi.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/serializers/-rest\", [\"exports\", \"@ember-data/serializer/rest\"], function (_exports, _rest) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _rest.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/serializers/application\", [\"exports\", \"ember-data\"], function (_exports, _emberData) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n var _default = _emberData.default.JSONAPISerializer.extend({\n normalizeResponse: function normalizeResponse(store, primaryModelClass, payload) {\n return payload;\n }\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/services/store\", [\"exports\", \"ember-data/store\"], function (_exports, _store) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _store.default;\n }\n });\n});\n;define(\"relationship-performance-test-app/templates/application\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n var _default = Ember.HTMLBars.template({\n \"id\": \"6nqMC1Ym\",\n \"block\": \"{\\\"symbols\\\":[],\\\"statements\\\":[],\\\"hasEval\\\":false}\",\n \"meta\": {\n \"moduleName\": \"relationship-performance-test-app/templates/application.hbs\"\n }\n });\n\n _exports.default = _default;\n});\n;define(\"relationship-performance-test-app/transforms/boolean\", [\"exports\", \"@ember-data/serializer/-private\"], function (_exports, _private) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _private.BooleanTransform;\n }\n });\n});\n;define(\"relationship-performance-test-app/transforms/date\", [\"exports\", \"@ember-data/serializer/-private\"], function (_exports, _private) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _private.DateTransform;\n }\n });\n});\n;define(\"relationship-performance-test-app/transforms/number\", [\"exports\", \"@ember-data/serializer/-private\"], function (_exports, _private) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _private.NumberTransform;\n }\n });\n});\n;define(\"relationship-performance-test-app/transforms/string\", [\"exports\", \"@ember-data/serializer/-private\"], function (_exports, _private) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"default\", {\n enumerable: true,\n get: function get() {\n return _private.StringTransform;\n }\n });\n});\n;\n\n;define('relationship-performance-test-app/config/environment', [], function() {\n var prefix = 'relationship-performance-test-app';\ntry {\n var metaName = prefix + '/config/environment';\n var rawConfig = document.querySelector('meta[name=\"' + metaName + '\"]').getAttribute('content');\n var config = JSON.parse(decodeURIComponent(rawConfig));\n\n var exports = { 'default': config };\n\n Object.defineProperty(exports, '__esModule', { value: true });\n\n return exports;\n}\ncatch(err) {\n throw new Error('Could not read config from meta tag with name \"' + metaName + '\".');\n}\n\n});\n\n;\n if (!runningTests) {\n require(\"relationship-performance-test-app/app\")[\"default\"].create({\"name\":\"relationship-performance-test-app\",\"version\":\"3.15.0-alpha.1+e717aaeb\"});\n }\n \n" }, "redirectURL": "", - "headersSize": -1, - "bodySize": -1, + "headersSize": 160, + "bodySize": 22947, "_transferSize": 23107 }, "cache": {}, "timings": { - "blocked": 5.561000000635162, - "dns": 0.01999999999999999, + "blocked": 4.743999999044812, + "dns": 0.010000000000000009, "ssl": -1, - "connect": 0.167, - "send": 0.44799999999999995, - "wait": 0.9319999900590629, - "receive": 2.6240000152029097, - "_blocked_queueing": 5.332000000635162 + "connect": 0.127, + "send": 0.2300000000000002, + "wait": 0.6649999993577365, + "receive": 0.5590000000665896, + "_blocked_queueing": 2.9899999990448123 }, "serverIPAddress": "[::1]", "_initiator": { "type": "parser", - "url": "http://localhost:5000/", + "url": "http://localhost:4200/", "lineNumber": 21 }, "_priority": "High", "_resourceType": "script", - "connection": "1053035", - "pageref": "page_4" + "connection": "50832", + "pageref": "page_1" } ] } diff --git a/packages/unpublished-relationship-performance-test-app/bin/tracerbench.js b/packages/unpublished-relationship-performance-test-app/bin/tracerbench.js index 51f3c250da6..b934cb4dc53 100644 --- a/packages/unpublished-relationship-performance-test-app/bin/tracerbench.js +++ b/packages/unpublished-relationship-performance-test-app/bin/tracerbench.js @@ -1,15 +1,10 @@ const fs = require('fs-extra'); const { InitialRenderBenchmark, Runner } = require('@tracerbench/core'); -// the number of samples TracerBench will run. Higher sample count = more accurate. -// However the duration of the test will increase. The recommendation is somewhere between 30-60 samples. +// The number of samples TracerBench will run. Higher sample count is more accurate. +// However, the duration of the test will increase. The recommendation is somewhere between 30-60 samples. const samplesCount = 2; -// the markers leveraged tuning your web application. additionally this assumes you have tuned -// your web application with the following marker "renderEnd" -// (see "Instrument your web application" above). the full list of available markers is robust, -// especially as it pertains to web application frameworks (ember, react etc). -// as a baseline the `PerformanceTiming` API is fully available const markers = [ { start: 'start-find-all', @@ -43,20 +38,17 @@ const browser = { ], }; -console.log('Visiting the control...'); const control = new InitialRenderBenchmark({ name: 'control', - // serve your control tuned application locally url: 'http://localhost:4200/?tracerbench=true', markers, browser, saveTraces: () => `./tracerbench-results/control-trace.json`, }); -console.log('Visiting the experiment...'); const experiment = new InitialRenderBenchmark({ name: 'experiment', - url: 'http://localhost:4200/?tracerbench=true', + url: 'http://localhost:4201/?tracerbench=true', markers, browser, saveTraces: () => `./tracerbench-results/experiment-trace.json`, @@ -68,7 +60,6 @@ runner .run(samplesCount) .then(results => { fs.writeFileSync(`./tracerbench-results/trace-results.json`, JSON.stringify(results, null, 2)); - console.log('Done!'); }) .catch(err => { console.error(err); diff --git a/packages/unpublished-relationship-performance-test-app/ember-cli-build.js b/packages/unpublished-relationship-performance-test-app/ember-cli-build.js index d322180cb04..8dae2112f89 100644 --- a/packages/unpublished-relationship-performance-test-app/ember-cli-build.js +++ b/packages/unpublished-relationship-performance-test-app/ember-cli-build.js @@ -6,7 +6,9 @@ const EmberApp = require('ember-cli/lib/broccoli/ember-app'); module.exports = function(defaults) { let app = new EmberApp(defaults, { - // Add options here + fingerprint: { + enabled: false, + }, }); // Use `app.import` to add additional libraries to the generated diff --git a/packages/unpublished-relationship-performance-test-app/package.json b/packages/unpublished-relationship-performance-test-app/package.json index 83e89d53521..055822fcb8d 100644 --- a/packages/unpublished-relationship-performance-test-app/package.json +++ b/packages/unpublished-relationship-performance-test-app/package.json @@ -22,7 +22,8 @@ "ember-data": "3.15.0-alpha.1" }, "devDependencies": { - "@ember/optional-features": "^1.0.0", + "@ember/optional-features": "^1.1.0", + "@tracerbench/core": "^2.3.0", "broccoli-asset-rev": "^3.0.0", "ember-cli": "~3.13.1", "ember-cli-app-version": "^3.2.0", @@ -32,16 +33,19 @@ "ember-cli-inject-live-reload": "^2.0.2", "ember-cli-template-lint": "^1.0.0-beta.1", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", - "eslint": "^6.5.1", - "eslint-plugin-ember": "^7.1.0", + "ember-source": "^3.14.1", + "eslint": "^6.6.0", + "eslint-plugin-ember": "^7.3.0", "eslint-plugin-node": "^10.0.0", + "fs-extra": "^8.1.0", + "har-remix": "^2.3.0", "loader.js": "^4.7.0", - "qunit-dom": "^0.9.0" + "qunit-dom": "^0.9.1", + "url": "^0.11.0" }, "engines": { "node": "8.* || >= 10.*" diff --git a/packages/-serializer-encapsulation-test-app/.editorconfig b/packages/unpublished-serializer-encapsulation-test-app/.editorconfig similarity index 100% rename from packages/-serializer-encapsulation-test-app/.editorconfig rename to packages/unpublished-serializer-encapsulation-test-app/.editorconfig diff --git a/packages/-serializer-encapsulation-test-app/.ember-cli b/packages/unpublished-serializer-encapsulation-test-app/.ember-cli similarity index 100% rename from packages/-serializer-encapsulation-test-app/.ember-cli rename to packages/unpublished-serializer-encapsulation-test-app/.ember-cli diff --git a/packages/-serializer-encapsulation-test-app/.gitignore b/packages/unpublished-serializer-encapsulation-test-app/.gitignore similarity index 100% rename from packages/-serializer-encapsulation-test-app/.gitignore rename to packages/unpublished-serializer-encapsulation-test-app/.gitignore diff --git a/packages/-serializer-encapsulation-test-app/.template-lintrc.js b/packages/unpublished-serializer-encapsulation-test-app/.template-lintrc.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/.template-lintrc.js rename to packages/unpublished-serializer-encapsulation-test-app/.template-lintrc.js diff --git a/packages/-serializer-encapsulation-test-app/.watchmanconfig b/packages/unpublished-serializer-encapsulation-test-app/.watchmanconfig similarity index 100% rename from packages/-serializer-encapsulation-test-app/.watchmanconfig rename to packages/unpublished-serializer-encapsulation-test-app/.watchmanconfig diff --git a/packages/-serializer-encapsulation-test-app/README.md b/packages/unpublished-serializer-encapsulation-test-app/README.md similarity index 100% rename from packages/-serializer-encapsulation-test-app/README.md rename to packages/unpublished-serializer-encapsulation-test-app/README.md diff --git a/packages/-serializer-encapsulation-test-app/app/app.js b/packages/unpublished-serializer-encapsulation-test-app/app/app.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/app.js rename to packages/unpublished-serializer-encapsulation-test-app/app/app.js diff --git a/packages/-serializer-encapsulation-test-app/app/components/.gitkeep b/packages/unpublished-serializer-encapsulation-test-app/app/components/.gitkeep similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/components/.gitkeep rename to packages/unpublished-serializer-encapsulation-test-app/app/components/.gitkeep diff --git a/packages/-serializer-encapsulation-test-app/app/controllers/.gitkeep b/packages/unpublished-serializer-encapsulation-test-app/app/controllers/.gitkeep similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/controllers/.gitkeep rename to packages/unpublished-serializer-encapsulation-test-app/app/controllers/.gitkeep diff --git a/packages/-serializer-encapsulation-test-app/app/helpers/.gitkeep b/packages/unpublished-serializer-encapsulation-test-app/app/helpers/.gitkeep similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/helpers/.gitkeep rename to packages/unpublished-serializer-encapsulation-test-app/app/helpers/.gitkeep diff --git a/packages/-serializer-encapsulation-test-app/app/index.html b/packages/unpublished-serializer-encapsulation-test-app/app/index.html similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/index.html rename to packages/unpublished-serializer-encapsulation-test-app/app/index.html diff --git a/packages/-serializer-encapsulation-test-app/app/models/.gitkeep b/packages/unpublished-serializer-encapsulation-test-app/app/models/.gitkeep similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/models/.gitkeep rename to packages/unpublished-serializer-encapsulation-test-app/app/models/.gitkeep diff --git a/packages/-serializer-encapsulation-test-app/app/resolver.js b/packages/unpublished-serializer-encapsulation-test-app/app/resolver.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/resolver.js rename to packages/unpublished-serializer-encapsulation-test-app/app/resolver.js diff --git a/packages/-serializer-encapsulation-test-app/app/router.js b/packages/unpublished-serializer-encapsulation-test-app/app/router.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/router.js rename to packages/unpublished-serializer-encapsulation-test-app/app/router.js diff --git a/packages/-serializer-encapsulation-test-app/app/routes/.gitkeep b/packages/unpublished-serializer-encapsulation-test-app/app/routes/.gitkeep similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/routes/.gitkeep rename to packages/unpublished-serializer-encapsulation-test-app/app/routes/.gitkeep diff --git a/packages/-serializer-encapsulation-test-app/app/services/store.js b/packages/unpublished-serializer-encapsulation-test-app/app/services/store.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/services/store.js rename to packages/unpublished-serializer-encapsulation-test-app/app/services/store.js diff --git a/packages/-serializer-encapsulation-test-app/app/styles/app.css b/packages/unpublished-serializer-encapsulation-test-app/app/styles/app.css similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/styles/app.css rename to packages/unpublished-serializer-encapsulation-test-app/app/styles/app.css diff --git a/packages/-serializer-encapsulation-test-app/app/templates/application.hbs b/packages/unpublished-serializer-encapsulation-test-app/app/templates/application.hbs similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/templates/application.hbs rename to packages/unpublished-serializer-encapsulation-test-app/app/templates/application.hbs diff --git a/packages/-serializer-encapsulation-test-app/app/templates/components/.gitkeep b/packages/unpublished-serializer-encapsulation-test-app/app/templates/components/.gitkeep similarity index 100% rename from packages/-serializer-encapsulation-test-app/app/templates/components/.gitkeep rename to packages/unpublished-serializer-encapsulation-test-app/app/templates/components/.gitkeep diff --git a/packages/-serializer-encapsulation-test-app/config/environment.js b/packages/unpublished-serializer-encapsulation-test-app/config/environment.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/config/environment.js rename to packages/unpublished-serializer-encapsulation-test-app/config/environment.js diff --git a/packages/-serializer-encapsulation-test-app/config/optional-features.json b/packages/unpublished-serializer-encapsulation-test-app/config/optional-features.json similarity index 100% rename from packages/-serializer-encapsulation-test-app/config/optional-features.json rename to packages/unpublished-serializer-encapsulation-test-app/config/optional-features.json diff --git a/packages/-serializer-encapsulation-test-app/config/targets.js b/packages/unpublished-serializer-encapsulation-test-app/config/targets.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/config/targets.js rename to packages/unpublished-serializer-encapsulation-test-app/config/targets.js diff --git a/packages/-serializer-encapsulation-test-app/ember-cli-build.js b/packages/unpublished-serializer-encapsulation-test-app/ember-cli-build.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/ember-cli-build.js rename to packages/unpublished-serializer-encapsulation-test-app/ember-cli-build.js diff --git a/packages/-serializer-encapsulation-test-app/package.json b/packages/unpublished-serializer-encapsulation-test-app/package.json similarity index 83% rename from packages/-serializer-encapsulation-test-app/package.json rename to packages/unpublished-serializer-encapsulation-test-app/package.json index 7650dee5188..ba7af6fcfad 100644 --- a/packages/-serializer-encapsulation-test-app/package.json +++ b/packages/unpublished-serializer-encapsulation-test-app/package.json @@ -25,7 +25,7 @@ "ember-inflector": "^3.0.1" }, "devDependencies": { - "@ember/optional-features": "^1.0.0", + "@ember/optional-features": "^1.1.0", "broccoli-asset-rev": "^3.0.0", "ember-cli": "~3.13.1", "ember-cli-app-version": "^3.2.0", @@ -35,17 +35,16 @@ "ember-cli-inject-live-reload": "^2.0.2", "ember-cli-template-lint": "^1.0.0-beta.1", "ember-export-application-global": "^2.0.0", - "ember-load-initializers": "^2.1.0", + "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", - "ember-qunit": "^4.5.1", - "ember-qunit-assert-helpers": "^0.2.2", + "ember-qunit": "^4.6.0", "ember-resolver": "^5.3.0", - "ember-source": "^3.13.3", - "eslint": "^6.5.1", - "eslint-plugin-ember": "^7.2.0", + "ember-source": "^3.14.1", + "eslint": "^6.6.0", + "eslint-plugin-ember": "^7.3.0", "eslint-plugin-node": "^10.0.0", "loader.js": "^4.7.0", - "qunit-dom": "^0.9.0" + "qunit-dom": "^0.9.1" }, "engines": { "node": "8.* || >= 10.*" diff --git a/packages/-serializer-encapsulation-test-app/public/robots.txt b/packages/unpublished-serializer-encapsulation-test-app/public/robots.txt similarity index 100% rename from packages/-serializer-encapsulation-test-app/public/robots.txt rename to packages/unpublished-serializer-encapsulation-test-app/public/robots.txt diff --git a/packages/-serializer-encapsulation-test-app/testem.js b/packages/unpublished-serializer-encapsulation-test-app/testem.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/testem.js rename to packages/unpublished-serializer-encapsulation-test-app/testem.js diff --git a/packages/-serializer-encapsulation-test-app/tests/helpers/.gitkeep b/packages/unpublished-serializer-encapsulation-test-app/tests/helpers/.gitkeep similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/helpers/.gitkeep rename to packages/unpublished-serializer-encapsulation-test-app/tests/helpers/.gitkeep diff --git a/packages/-serializer-encapsulation-test-app/tests/helpers/test-in-debug.js b/packages/unpublished-serializer-encapsulation-test-app/tests/helpers/test-in-debug.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/helpers/test-in-debug.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/helpers/test-in-debug.js diff --git a/packages/-serializer-encapsulation-test-app/tests/index.html b/packages/unpublished-serializer-encapsulation-test-app/tests/index.html similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/index.html rename to packages/unpublished-serializer-encapsulation-test-app/tests/index.html diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/.gitkeep b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/.gitkeep similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/integration/.gitkeep rename to packages/unpublished-serializer-encapsulation-test-app/tests/integration/.gitkeep diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/create-record-test.js b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/create-record-test.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/integration/create-record-test.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/integration/create-record-test.js diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/delete-record-test.js b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/delete-record-test.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/integration/delete-record-test.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/integration/delete-record-test.js diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/errors-test.js b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/errors-test.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/integration/errors-test.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/integration/errors-test.js diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/normalize-test.js b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/normalize-test.js similarity index 98% rename from packages/-serializer-encapsulation-test-app/tests/integration/normalize-test.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/integration/normalize-test.js index 9de120f7c12..144e3d0a52c 100644 --- a/packages/-serializer-encapsulation-test-app/tests/integration/normalize-test.js +++ b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/normalize-test.js @@ -83,7 +83,7 @@ module('integration/serializer - normalize method forwards to Serializer#normali const store = this.owner.lookup('service:store'); - assert.expectAssertion(() => { + assert.throws(() => { store.normalize('person', { id: '1', type: 'person', diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/push-payload-test.js b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/push-payload-test.js similarity index 98% rename from packages/-serializer-encapsulation-test-app/tests/integration/push-payload-test.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/integration/push-payload-test.js index 488f80ddc6b..cb397fa9ab0 100644 --- a/packages/-serializer-encapsulation-test-app/tests/integration/push-payload-test.js +++ b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/push-payload-test.js @@ -90,7 +90,7 @@ module('integration/push-payload - pushPayload method forwards to Serializer#pus const store = this.owner.lookup('service:store'); - assert.expectAssertion(() => { + assert.throws(() => { store.pushPayload('person', { data: { id: '1', diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/relationships-test.js b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/relationships-test.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/integration/relationships-test.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/integration/relationships-test.js diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/requests-test.js b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/requests-test.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/integration/requests-test.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/integration/requests-test.js diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/serialize-test.js b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/serialize-test.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/integration/serialize-test.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/integration/serialize-test.js diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/smoke-test.js b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/smoke-test.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/integration/smoke-test.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/integration/smoke-test.js diff --git a/packages/-serializer-encapsulation-test-app/tests/integration/update-record-test.js b/packages/unpublished-serializer-encapsulation-test-app/tests/integration/update-record-test.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/integration/update-record-test.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/integration/update-record-test.js diff --git a/packages/-serializer-encapsulation-test-app/tests/test-helper.js b/packages/unpublished-serializer-encapsulation-test-app/tests/test-helper.js similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/test-helper.js rename to packages/unpublished-serializer-encapsulation-test-app/tests/test-helper.js diff --git a/packages/-serializer-encapsulation-test-app/tests/unit/.gitkeep b/packages/unpublished-serializer-encapsulation-test-app/tests/unit/.gitkeep similarity index 100% rename from packages/-serializer-encapsulation-test-app/tests/unit/.gitkeep rename to packages/unpublished-serializer-encapsulation-test-app/tests/unit/.gitkeep diff --git a/packages/-serializer-encapsulation-test-app/vendor/.gitkeep b/packages/unpublished-serializer-encapsulation-test-app/vendor/.gitkeep similarity index 100% rename from packages/-serializer-encapsulation-test-app/vendor/.gitkeep rename to packages/unpublished-serializer-encapsulation-test-app/vendor/.gitkeep diff --git a/packages/-test-infra/.npmignore b/packages/unpublished-test-infra/.npmignore similarity index 100% rename from packages/-test-infra/.npmignore rename to packages/unpublished-test-infra/.npmignore diff --git a/packages/-test-infra/.watchmanconfig b/packages/unpublished-test-infra/.watchmanconfig similarity index 100% rename from packages/-test-infra/.watchmanconfig rename to packages/unpublished-test-infra/.watchmanconfig diff --git a/packages/-test-infra/LICENSE.md b/packages/unpublished-test-infra/LICENSE.md similarity index 100% rename from packages/-test-infra/LICENSE.md rename to packages/unpublished-test-infra/LICENSE.md diff --git a/packages/-test-infra/README.md b/packages/unpublished-test-infra/README.md similarity index 90% rename from packages/-test-infra/README.md rename to packages/unpublished-test-infra/README.md index 1c92180952b..b2547a03cc4 100644 --- a/packages/-test-infra/README.md +++ b/packages/unpublished-test-infra/README.md @@ -1,4 +1,4 @@ -# @ember-data/-test-infra +# @ember-data/unpublished-test-infra !! This is an internal package for use by `@ember-data` only. !! diff --git a/packages/-test-infra/package.json b/packages/unpublished-test-infra/package.json similarity index 86% rename from packages/-test-infra/package.json rename to packages/unpublished-test-infra/package.json index 127b35733d0..65890420069 100644 --- a/packages/-test-infra/package.json +++ b/packages/unpublished-test-infra/package.json @@ -1,6 +1,7 @@ { - "name": "@ember-data/-test-infra", + "name": "@ember-data/unpublished-test-infra", "version": "3.15.0-alpha.1", + "private": true, "description": "The default blueprint for ember-data private packages.", "keywords": [], "repository": "", diff --git a/packages/-test-infra/src/node-test-helpers/fixture.js b/packages/unpublished-test-infra/src/node-test-helpers/fixture.js similarity index 100% rename from packages/-test-infra/src/node-test-helpers/fixture.js rename to packages/unpublished-test-infra/src/node-test-helpers/fixture.js diff --git a/packages/-test-infra/src/node-test-helpers/generate-fake-package-manifest.js b/packages/unpublished-test-infra/src/node-test-helpers/generate-fake-package-manifest.js similarity index 100% rename from packages/-test-infra/src/node-test-helpers/generate-fake-package-manifest.js rename to packages/unpublished-test-infra/src/node-test-helpers/generate-fake-package-manifest.js diff --git a/packages/-test-infra/src/node-test-helpers/setup-test-environment.js b/packages/unpublished-test-infra/src/node-test-helpers/setup-test-environment.js similarity index 100% rename from packages/-test-infra/src/node-test-helpers/setup-test-environment.js rename to packages/unpublished-test-infra/src/node-test-helpers/setup-test-environment.js diff --git a/yarn.lock b/yarn.lock index 31399da716c..f538c45824c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -368,7 +368,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-block-scoping@^7.4.4", "@babel/plugin-transform-block-scoping@^7.6.3": +"@babel/plugin-transform-block-scoping@^7.6.0", "@babel/plugin-transform-block-scoping@^7.6.3": version "7.6.3" resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz#6e854e51fbbaa84351b15d4ddafe342f3a5d542a" integrity sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw== @@ -756,15 +756,15 @@ resolved "https://registry.npmjs.org/@ember/edition-utils/-/edition-utils-1.1.1.tgz#d5732c3da593f202e6e1ac6dbee56a758242403f" integrity sha512-GEhri78jdQp/xxPpM6z08KlB0wrHfnfrJ9dmQk7JeQ4XCiMzXsJci7yooQgg/IcTKCM/PxE/IkGCQAo80adMkw== -"@ember/optional-features@^1.0.0": - version "1.0.0" - resolved "https://registry.npmjs.org/@ember/optional-features/-/optional-features-1.0.0.tgz#8e54ff37f4d9642212b45387f182cf7322aaaab9" - integrity sha512-nPWqiyjkbSLaNd1kA1Y0BYAx+0IzuxdBfOkQyEwNaaB6xvgGpQMiQF/Au5UBlV/S3GEpuL2kFRQj48XMiTBY+w== +"@ember/optional-features@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@ember/optional-features/-/optional-features-1.1.0.tgz#0ff27ba6e9fc1f1e936e024f6a7cc33a96abffba" + integrity sha512-ST3+gIRH2WtgGcOtf42uM9WaXBY4dj4//zoTYV6GPe8cp0XdJEU63oMo9SbE6+0Efp8lvk96LsX+DVDDZy9Rmw== dependencies: chalk "^2.4.2" co "^4.6.0" ember-cli-version-checker "^3.1.3" - glob "^7.1.4" + glob "^7.1.5" inquirer "^6.5.1" mkdirp "^0.5.1" silent-error "^1.1.1" @@ -778,17 +778,17 @@ ember-cli-babel "^6.16.0" ember-compatibility-helpers "^1.1.1" -"@ember/test-helpers@^1.6.0": - version "1.6.1" - resolved "https://registry.npmjs.org/@ember/test-helpers/-/test-helpers-1.6.1.tgz#5eb0b58486524c54f1b617a83e4ab327b7c62f07" - integrity sha512-gXLXR0XdZKfyXHFP+QLpG55TlrDtvrZI6TMQVQxdZwsz589kN8idmc01rDjyy53jx430tZTEsdhJvC2LrHXPwg== +"@ember/test-helpers@^1.7.1": + version "1.7.1" + resolved "https://registry.npmjs.org/@ember/test-helpers/-/test-helpers-1.7.1.tgz#cc22a954b3b46856518f034bd492a74e0482389f" + integrity sha512-+ioumnanSRJzZ0ZH30FIkB0r41UhVyuWQ9R9Yp1phDWJQDLumxg+25WDr40relwcH6z0Cn6LIEzeTVujO/0Rww== dependencies: broccoli-debug "^0.6.5" broccoli-funnel "^2.0.2" ember-assign-polyfill "^2.6.0" ember-cli-babel "^7.7.3" ember-cli-htmlbars-inline-precompile "^2.1.0" - ember-test-waiters "^1.0.0" + ember-test-waiters "^1.1.1" "@embroider/core@0.4.3", "@embroider/core@^0.4.3": version "0.4.3" @@ -1731,6 +1731,85 @@ resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== +"@tracerbench/core@^2.3.0": + version "2.3.0" + resolved "https://registry.npmjs.org/@tracerbench/core/-/core-2.3.0.tgz#07a5783826a79b5510346972e2b41675ab1ce650" + integrity sha512-Rbc8cnNf95yE0r2j5hzAUABV1YOcCx/Yosm1wR9LoE8bV9aQYHwIbEhvsk86EOX81Mcmm3G1qXghIc6k1mdB6Q== + dependencies: + "@types/d3-hierarchy" "^1.1.6" + "@types/node" "*" + array-binsearch "^1.0.1" + chalk "^2.4.2" + chrome-debugging-client "^1.0.3" + d3-hierarchy "^1.1.8" + debug "^4.1.1" + devtools-protocol "0.0.665395" + handlebars "^4.4.3" + silent-error "^1.1.1" + tslib "^1.10.0" + +"@tracerbench/find-chrome@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@tracerbench/find-chrome/-/find-chrome-1.1.0.tgz#ed4eaa40cadd53ec1f44c2a7c9f0eb19d21059f5" + integrity sha512-qYeZ1QtXtdF0OSMMbbO54i4G9L5kxcitJiBbkCLci6tOQht1diXUKWCZyYYWFbXkVd67MpjsXRdhAaSuGoPJnQ== + dependencies: + chrome-launcher "^0.11.2" + +"@tracerbench/har@^2.3.0": + version "2.3.0" + resolved "https://registry.npmjs.org/@tracerbench/har/-/har-2.3.0.tgz#87e8f032b760a2982810d4202f4e12377af5b166" + integrity sha512-Wp/8SK7svoUpfEFpiUGd60VheKOCwdudIPU4R+CK/ADagUMdKHQdjxRljPggKQyq9vDCTM/vC7T5MMQKZU4ErQ== + +"@tracerbench/message-transport@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@tracerbench/message-transport/-/message-transport-1.1.0.tgz#ba5f45706b109f734b9404db9ad9bc06043e91f9" + integrity sha512-fI7+wuvcEWuqiRRraeejNTr3x9mvykfArN1Pu2K9IhEb8Li7mj9XpXgt5fPBCWcBXNTB1amaQsCaxLgknzohPQ== + +"@tracerbench/protocol-connection@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@tracerbench/protocol-connection/-/protocol-connection-1.1.0.tgz#18fa2c7226db58be90e3683f62310917b5ee01ef" + integrity sha512-rE3NoUQzLATy2GY24cbSZa91eYtUr3LlaE2ACLVSmZ4S1WZfX0mUMGpV66NkUneCmiP81h9fEukPmMIB7Nujlg== + dependencies: + "@tracerbench/message-transport" "^1.1.0" + "@tracerbench/protocol-transport" "^1.1.0" + race-cancellation "^0.4.1" + +"@tracerbench/protocol-transport@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@tracerbench/protocol-transport/-/protocol-transport-1.1.0.tgz#41168f1cd871f314de3908880a86856f25f369ae" + integrity sha512-plbZuOemj8kTQUUnygrqZ6zw7RKzC8gjrddmZsDqQd8qeri1RkjR6TWMETkg0/CneN883bs8OuhJQ4bTlZcxsA== + dependencies: + "@tracerbench/message-transport" "^1.1.0" + race-cancellation "^0.4.1" + +"@tracerbench/spawn-chrome@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@tracerbench/spawn-chrome/-/spawn-chrome-1.1.0.tgz#859f046198dd60a2bd64c2332f877f7d03401759" + integrity sha512-w81pOxXEhH1w5E43HVx0Dbv/EwOylttF/pp7joksoE8AGNOOTky++OlPbHongaaIFP7HRFHWYwj++0jOGM54mw== + dependencies: + "@tracerbench/find-chrome" "^1.1.0" + "@tracerbench/spawn" "^1.1.0" + tmp "^0.1.0" + +"@tracerbench/spawn@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@tracerbench/spawn/-/spawn-1.1.0.tgz#5ba9953a05b5fef5d907874c38beee61da5b1a84" + integrity sha512-2aMNzxTUHGjqDrYpuZtPdZuCiNvkCe/I3vDTENFvaLNQcrGuNSHxmM4esmSY1qR60BAmEkfMDWCK9jwNC5gOCQ== + dependencies: + "@tracerbench/message-transport" "^1.1.0" + debug "^4.1.1" + execa "^3.1.0" + race-cancellation "^0.4.1" + +"@tracerbench/websocket-message-transport@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@tracerbench/websocket-message-transport/-/websocket-message-transport-1.1.0.tgz#5ad287e42a50d05eff234dbfa02d5e7ccf17e51b" + integrity sha512-c5Fi5lC8pfbRf4UOXIL7jbSBFZq348lb1gtqE7DykXyXoxIr39cNbGkqoovK6SNx8fk7cPTiVo246ZJFtRxSGw== + dependencies: + "@tracerbench/message-transport" "^1.1.0" + race-cancellation "^0.4.1" + ws "^7.1.2" + "@types/acorn@^4.0.3": version "4.0.5" resolved "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.5.tgz#e29fdf884695e77be4e99e67d748f5147255752d" @@ -1743,6 +1822,11 @@ resolved "https://registry.npmjs.org/@types/broccoli-plugin/-/broccoli-plugin-1.3.0.tgz#38f8462fecaebc4e09a32e4d4ed1b9808f75bbca" integrity sha512-SLk4/hFc2kGvgwNFrpn2O1juxFOllcHAywvlo7VwxfExLzoz1GGJ0oIZCwj5fwSpvHw4AWpZjJ1fUvb62PDayQ== +"@types/d3-hierarchy@^1.1.6": + version "1.1.6" + resolved "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-1.1.6.tgz#4c017521900813ea524c9ecb8d7985ec26a9ad9a" + integrity sha512-vvSaIDf/Ov0o3KwMT+1M8+WbnnlRiGjlGD5uvk83a1mPCTd/E5x12bUJ/oP55+wUY/4Kb5kc67rVpVGJ2KUHxg== + "@types/ember-qunit@^3.4.7": version "3.4.7" resolved "https://registry.npmjs.org/@types/ember-qunit/-/ember-qunit-3.4.7.tgz#57dad9f01ff6136cdadf2a06b7089af91661d3b5" @@ -1828,10 +1912,10 @@ dependencies: "@types/ember__object" "*" -"@types/ember__debug@*", "@types/ember__debug@3.0.5": - version "3.0.5" - resolved "https://registry.npmjs.org/@types/ember__debug/-/ember__debug-3.0.5.tgz#ed7636dec3380a363c02f074d8e0a50cd6d563ab" - integrity sha512-1zXDboNm06c0S12bg7G75eFF21aW1C8QFKZGuQTQ66Xur5nwYHii6R2+t0lylgZTxqeRwjmeEZdROpYUNWexJQ== +"@types/ember__debug@*", "@types/ember__debug@3.0.6": + version "3.0.6" + resolved "https://registry.npmjs.org/@types/ember__debug/-/ember__debug-3.0.6.tgz#fa8bbc58249d8bdeea9be5b4ab8e974b33c39b07" + integrity sha512-he07ArVIGzXw79NDEePawpkQSmiDc9C6Z/K6MkD2sUJdVSFaggGXBKvGh/QdenaP8hdYz36/umXGabq/Z862SA== dependencies: "@types/ember__debug" "*" "@types/ember__engine" "*" @@ -2003,40 +2087,40 @@ resolved "https://registry.npmjs.org/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d" integrity sha1-EHPEvIJHVK49EM+riKsCN7qWTk0= -"@typescript-eslint/eslint-plugin@^2.5.0": - version "2.5.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.5.0.tgz#101d96743ce3365b3223df73d641078c9b775903" - integrity sha512-ddrJZxp5ns1Lh5ofZQYk3P8RyvKfyz/VcRR4ZiJLHO/ljnQAO8YvTfj268+WJOOadn99mvDiqJA65+HAKoeSPA== +"@typescript-eslint/eslint-plugin@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.6.0.tgz#e82ed43fc4527b21bfe35c20a2d6e4ed49fc7957" + integrity sha512-iCcXREU4RciLmLniwKLRPCOFVXrkF7z27XuHq5DrykpREv/mz6ztKAyLg2fdkM0hQC7659p5ZF5uStH7uzAJ/w== dependencies: - "@typescript-eslint/experimental-utils" "2.5.0" + "@typescript-eslint/experimental-utils" "2.6.0" eslint-utils "^1.4.2" functional-red-black-tree "^1.0.1" regexpp "^2.0.1" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@2.5.0": - version "2.5.0" - resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.5.0.tgz#383a97ded9a7940e5053449f6d73995e782b8fb1" - integrity sha512-UgcQGE0GKJVChyRuN1CWqDW8Pnu7+mVst0aWrhiyuUD1J9c+h8woBdT4XddCvhcXDodTDVIfE3DzGHVjp7tUeQ== +"@typescript-eslint/experimental-utils@2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.6.0.tgz#ed70bef72822bff54031ff0615fc888b9e2b6e8a" + integrity sha512-34BAFpNOwHXeqT+AvdalLxOvcPYnCxA5JGmBAFL64RGMdP0u65rXjii7l/nwpgk5aLEE1LaqF+SsCU0/Cb64xA== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.5.0" + "@typescript-eslint/typescript-estree" "2.6.0" eslint-scope "^5.0.0" -"@typescript-eslint/parser@^2.5.0": - version "2.5.0" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.5.0.tgz#858030ddd808fbbe88e03f42e5971efaccb8218a" - integrity sha512-9UBMiAwIDWSl79UyogaBdj3hidzv6exjKUx60OuZuFnJf56tq/UMpdPcX09YmGqE8f4AnAueYtBxV8IcAT3jdQ== +"@typescript-eslint/parser@^2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.6.0.tgz#5106295c6a7056287b4719e24aae8d6293d5af49" + integrity sha512-AvLejMmkcjRTJ2KD72v565W4slSrrzUIzkReu1JN34b8JnsEsxx7S9Xx/qXEuMQas0mkdUfETr0j3zOhq2DIqQ== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.5.0" - "@typescript-eslint/typescript-estree" "2.5.0" + "@typescript-eslint/experimental-utils" "2.6.0" + "@typescript-eslint/typescript-estree" "2.6.0" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/typescript-estree@2.5.0": - version "2.5.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.5.0.tgz#40ada624d6217ef092a3a79ed30d947ad4f212ce" - integrity sha512-AXURyF8NcA3IsnbjNX1v9qbwa0dDoY9YPcKYR2utvMHoUcu3636zrz0gRWtVAyxbPCkhyKuGg6WZIyi2Fc79CA== +"@typescript-eslint/typescript-estree@2.6.0": + version "2.6.0" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.6.0.tgz#d3e9d8e001492e2b9124c4d4bd4e7f03c0fd7254" + integrity sha512-A3lSBVIdj2Gp0lFEL6in2eSPqJ33uAc3Ko+Y4brhjkxzjbzLnwBH22CwsW2sCo+iwogfIyvb56/AJri15H0u5Q== dependencies: debug "^4.1.1" glob "^7.1.4" @@ -2366,6 +2450,13 @@ ansi-escapes@^3.2.0: resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== +ansi-escapes@^4.2.1: + version "4.2.1" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz#4dccdb846c3eee10f6d64dea66273eab90c37228" + integrity sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q== + dependencies: + type-fest "^0.5.2" + ansi-html@^0.0.7: version "0.0.7" resolved "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" @@ -2475,6 +2566,11 @@ array-back@^3.0.1: resolved "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== +array-binsearch@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/array-binsearch/-/array-binsearch-1.0.1.tgz#35586dca04ca9ab259c4c4708435acd1babb08ad" + integrity sha1-NVhtygTKmrJZxMRwhDWs0bq7CK0= + array-differ@^2.0.3: version "2.1.0" resolved "https://registry.npmjs.org/array-differ/-/array-differ-2.1.0.tgz#4b9c1c3f14b906757082925769e8ab904f4801b1" @@ -3688,7 +3784,7 @@ broccoli-file-creator@^2.1.1: broccoli-plugin "^1.1.0" mkdirp "^0.5.1" -broccoli-filter@^1.0.1, broccoli-filter@^1.2.2, broccoli-filter@^1.2.3: +broccoli-filter@^1.2.2, broccoli-filter@^1.2.3: version "1.3.0" resolved "https://registry.npmjs.org/broccoli-filter/-/broccoli-filter-1.3.0.tgz#71e3a8e32a17f309e12261919c5b1006d6766de6" integrity sha512-VXJXw7eBfG82CFxaBDjYmyN7V72D4In2zwLVQJd/h3mBfF3CMdRTsv2L20lmRTtCv1sAHcB+LgMso90e/KYiLw== @@ -4599,6 +4695,31 @@ chownr@^1.1.1, chownr@^1.1.2: resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== +chrome-debugging-client@^1.0.3: + version "1.1.0" + resolved "https://registry.npmjs.org/chrome-debugging-client/-/chrome-debugging-client-1.1.0.tgz#df7040a8386ab0f1285300ba05e2dad85cb85809" + integrity sha512-6NFPeytsmf8WwqusTmrUZJMCLgiFj2zTIWfhYksml8hB6UUnTYwSn+GLV5Drrgf1px6LPeex1iJoVBhiyMIjnw== + dependencies: + "@tracerbench/find-chrome" "^1.1.0" + "@tracerbench/message-transport" "^1.1.0" + "@tracerbench/protocol-connection" "^1.1.0" + "@tracerbench/spawn" "^1.1.0" + "@tracerbench/spawn-chrome" "^1.1.0" + "@tracerbench/websocket-message-transport" "^1.1.0" + debug "^4.1.1" + race-cancellation "^0.4.1" + +chrome-launcher@^0.11.2: + version "0.11.2" + resolved "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.11.2.tgz#c9a248dbccd3a08565553acf61adff879bcc982c" + integrity sha512-jx0kJDCXdB2ARcDMwNCtrf04oY1Up4rOmVu+fqJ5MTPOOIG8EhRcEU9NZfXZc6dMw9FU8o1r21PNp8V2M0zQ+g== + dependencies: + "@types/node" "*" + is-wsl "^2.1.0" + lighthouse-logger "^1.0.0" + mkdirp "0.5.1" + rimraf "^2.6.1" + chrome-trace-event@^1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" @@ -4663,6 +4784,13 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + cli-spinners@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" @@ -5277,6 +5405,11 @@ cyclist@^1.0.1: resolved "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= +d3-hierarchy@^1.1.8: + version "1.1.8" + resolved "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.8.tgz#7a6317bd3ed24e324641b6f1e76e978836b008cc" + integrity sha512-L+GHMSZNwTpiq4rt9GEsNcpLa4M96lXMR8M/nMG9p5hBE0jy6C+3hWtyZMenPQdwla249iJy7Nx0uKt3n+u9+w== + dag-map@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/dag-map/-/dag-map-2.0.2.tgz#9714b472de82a1843de2fba9b6876938cab44c68" @@ -5505,6 +5638,11 @@ detect-libc@^1.0.2: resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +devtools-protocol@0.0.665395: + version "0.0.665395" + resolved "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.665395.tgz#82f57f1e9393a605907d0260972d8b5a023df807" + integrity sha512-yuxo2OYq+RC1PCU7QOqhhHHKojvZvG1A0DoYnsHpIha3P8ZERpHuLkwAkPyFa2ZdLLk7Vq2BhOS2bkPeLZ1ySg== + dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -5744,7 +5882,7 @@ ember-cli-babel-plugin-helpers@^1.0.0, ember-cli-babel-plugin-helpers@^1.1.0: resolved "https://registry.npmjs.org/ember-cli-babel-plugin-helpers/-/ember-cli-babel-plugin-helpers-1.1.0.tgz#de3baedd093163b6c2461f95964888c1676325ac" integrity sha512-Zr4my8Xn+CzO0gIuFNXji0eTRml5AxZUTDQz/wsNJ5AJAtyFWCY4QtKdoELNNbiCVGt1lq5yLiwTm4scGKu6xA== -ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.0.0-beta.7, ember-cli-babel@^6.12.0, ember-cli-babel@^6.16.0, ember-cli-babel@^6.6.0, ember-cli-babel@^6.8.1, ember-cli-babel@^6.8.2, ember-cli-babel@^6.9.0: +ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.0.0-beta.7, ember-cli-babel@^6.12.0, ember-cli-babel@^6.16.0, ember-cli-babel@^6.6.0, ember-cli-babel@^6.8.1, ember-cli-babel@^6.8.2: version "6.18.0" resolved "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-6.18.0.tgz#3f6435fd275172edeff2b634ee7b29ce74318957" integrity sha512-7ceC8joNYxY2wES16iIBlbPSxwKDBhYwC8drU3ZEvuPDMwVv1KzxCNu1fvxyFEBWhwaRNTUxSCsEVoTd9nosGA== @@ -5763,7 +5901,7 @@ ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.0.0-beta.7, ember-cli-babel@^6 ember-cli-version-checker "^2.1.2" semver "^5.5.0" -ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.0, ember-cli-babel@^7.1.2, ember-cli-babel@^7.10.0, ember-cli-babel@^7.12.0, ember-cli-babel@^7.7.0, ember-cli-babel@^7.7.3, ember-cli-babel@^7.8.0: +ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.0, ember-cli-babel@^7.1.2, ember-cli-babel@^7.11.0, ember-cli-babel@^7.12.0, ember-cli-babel@^7.7.3, ember-cli-babel@^7.8.0: version "7.12.0" resolved "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-7.12.0.tgz#064997d199384be8c88d251f30ef67953d3bddc5" integrity sha512-+EGQsbPvh19nNXHCm6rVBx2CdlxQlzxMyhey5hsGViDPriDI4PFYXYaFWdGizDrmZoDcG/Ywpeph3hl0NxGQTg== @@ -5881,7 +6019,7 @@ ember-cli-htmlbars-inline-precompile@^2.1.0: heimdalljs-logger "^0.1.9" silent-error "^1.1.0" -ember-cli-htmlbars@^3.0.1: +ember-cli-htmlbars@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/ember-cli-htmlbars/-/ember-cli-htmlbars-3.1.0.tgz#87806c2a0bca2ab52d4fb8af8e2215c1ca718a99" integrity sha512-cgvRJM73IT0aePUG7oQ/afB7vSRBV3N0wu9BrWhHX2zkR7A7cUBI7KC9VPk6tbctCXoM7BRGsCC4aIjF7yrfXA== @@ -6059,7 +6197,7 @@ ember-cli-typescript-blueprints@^3.0.0: inflection "^1.12.0" silent-error "^1.1.0" -ember-cli-typescript@^2.0.0: +ember-cli-typescript@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/ember-cli-typescript/-/ember-cli-typescript-2.0.2.tgz#464984131fbdc05655eb61d1c3cdd911d3137f0d" integrity sha512-7I5azCTxOgRDN8aSSnJZIKSqr+MGnT+jLTUbBYqF8wu6ojs2DUnTePxUcQMcvNh3Q3B1ySv7Q/uZFSjdU9gSjA== @@ -6243,10 +6381,10 @@ ember-compatibility-helpers@^1.1.1, ember-compatibility-helpers@^1.2.0: ember-cli-version-checker "^2.1.1" semver "^5.4.1" -ember-decorators-polyfill@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/ember-decorators-polyfill/-/ember-decorators-polyfill-1.1.0.tgz#f701d513c2f4dbcd1e7c84af623a8cdaad1dd349" - integrity sha512-ftXzKDJ53HUJu9gq8/6mBNerERKPKGDRBP4b72YZt/CIn1qwaspi0k23YvdwddqTPcmsCWxN+hRMfrRPQBoI4w== +ember-decorators-polyfill@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/ember-decorators-polyfill/-/ember-decorators-polyfill-1.1.1.tgz#6ff8e57a516e04c583451305574020c34e6ad4bc" + integrity sha512-ZIB3uNcquNyRm+eWUbDeeE5BtH/D7oXIX9pdiEHx4TXaTnAY6z4wDrw6Ge0xP9wx/nlC4Qd/i8rdlwBOT5C6lw== dependencies: ember-cli-babel "^7.1.2" ember-cli-version-checker "^3.1.3" @@ -6264,10 +6402,10 @@ ember-export-application-global@^2.0.0: dependencies: ember-cli-babel "^6.0.0-beta.7" -ember-fetch@^6.7.1: - version "6.7.1" - resolved "https://registry.npmjs.org/ember-fetch/-/ember-fetch-6.7.1.tgz#778390bc9993d31cc32d429ae69a591e431e85ac" - integrity sha512-B/s0HZWcIrDDz3wOxvAsWM2SyT4nND274aH3Othzxzax/lOJnGHKbNa+IGLrXKSja+ANeD5P8sVwDaAUw8pzpQ== +ember-fetch@^6.7.2: + version "6.7.2" + resolved "https://registry.npmjs.org/ember-fetch/-/ember-fetch-6.7.2.tgz#82efce4a55a64863104347b71e598208b9acf518" + integrity sha512-+Dd++MJVkCXoqX2DPtFDjuoDMcLk+7fphLq7D8OoXwJq9KQMTff07sH18qhxWXV5Hqknvz3Uwy214g54vOboag== dependencies: abortcontroller-polyfill "^1.3.0" broccoli-concat "^3.2.2" @@ -6289,13 +6427,13 @@ ember-inflector@^3.0.1: dependencies: ember-cli-babel "^6.6.0" -ember-load-initializers@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/ember-load-initializers/-/ember-load-initializers-2.1.0.tgz#b402815ab9c823ff48a1369b52633721987e72d4" - integrity sha512-zvcq35U2EPyjonCPdDBISZbeuxP3OXf+asmj2bNucFwo1ej7gYJCJacy6N8oABEG2EmrU/8jMDoZndWIAGn0cQ== +ember-load-initializers@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/ember-load-initializers/-/ember-load-initializers-2.1.1.tgz#d1a8bead00bc44222b0ab181840869992beb30f5" + integrity sha512-Ho5sBeaZPN3HmZkYkcLrjSBF3DTNmzC5h0DizzDj8cjpnCvaqeofphJDnH41k6kLv/QHMk4pMRISPcwc+bOceQ== dependencies: - ember-cli-babel "^7.10.0" - ember-cli-typescript "^2.0.0" + ember-cli-babel "^7.11.0" + ember-cli-typescript "^2.0.2" ember-maybe-import-regenerator@^0.1.6: version "0.1.6" @@ -6307,26 +6445,18 @@ ember-maybe-import-regenerator@^0.1.6: ember-cli-babel "^6.0.0-beta.4" regenerator-runtime "^0.9.5" -ember-qunit-assert-helpers@^0.2.2: - version "0.2.2" - resolved "https://registry.npmjs.org/ember-qunit-assert-helpers/-/ember-qunit-assert-helpers-0.2.2.tgz#6fec8a33fd0d2c3fb6202f849291a309581727a4" - integrity sha512-P5eAqD753+p/qEeBi6OGpl2EzRxx8O9dUnr6HgyxU9fqQsSNQkJNGZ+ajbtePI8oMDGm+X7uOnf1+BgQ7eJ7qg== - dependencies: - broccoli-filter "^1.0.1" - ember-cli-babel "^6.9.0" - -ember-qunit@^4.5.1: - version "4.5.1" - resolved "https://registry.npmjs.org/ember-qunit/-/ember-qunit-4.5.1.tgz#dc4b0a794fbeb6702a02f28bf19091de0f90fd5a" - integrity sha512-fOxXQLFdellP0yiMd9f3n7pIGggiDo8kBuswdGvsCrqTKq5aB1Cb49eeoNyBDQYGlhcxY0pOGUe+xElppChDBA== +ember-qunit@^4.6.0: + version "4.6.0" + resolved "https://registry.npmjs.org/ember-qunit/-/ember-qunit-4.6.0.tgz#ad79fd3ff00073a8779400cc5a4b44829517590f" + integrity sha512-i5VOGn0RP8XH+5qkYDOZshbqAvO6lHgF65D0gz8vRx4DszCIvJMJO+bbftBTfYMxp6rqG85etAA6pfNxE0DqsQ== dependencies: - "@ember/test-helpers" "^1.6.0" + "@ember/test-helpers" "^1.7.1" broccoli-funnel "^2.0.2" broccoli-merge-trees "^3.0.2" common-tags "^1.4.0" - ember-cli-babel "^7.8.0" + ember-cli-babel "^7.12.0" ember-cli-test-loader "^2.2.0" - qunit "^2.9.2" + qunit "^2.9.3" ember-resolver@^5.3.0: version "5.3.0" @@ -6355,13 +6485,13 @@ ember-router-generator@^2.0.0: "@babel/traverse" "^7.4.5" recast "^0.18.1" -ember-simple-tree@^0.7.0: - version "0.7.0" - resolved "https://registry.npmjs.org/ember-simple-tree/-/ember-simple-tree-0.7.0.tgz#054dcc4d1dc643a7dcf310e58cb9af9f2d03623e" - integrity sha512-hd//Y3m2U7uc+UxcRFBSunyzwtFtyyHz+SxyPTUL7Haejz314+1+z9GeFasMbsCf8J1HzoE0WSFkR+6MvDIOAQ== +ember-simple-tree@^0.7.1: + version "0.7.1" + resolved "https://registry.npmjs.org/ember-simple-tree/-/ember-simple-tree-0.7.1.tgz#fda235a8a05f27a9b61c7c839f3d710a79e20746" + integrity sha512-wDqBKxcIQJz6V/p5xf/XX5fROujNR+6E5cQ1kVYNnlu3Hu9QSCsIqIqhbq5YqBG/eOtqdJtNq+bS5UWS3xi6Dw== dependencies: - ember-cli-babel "^7.7.3" - ember-cli-htmlbars "^3.0.1" + ember-cli-babel "^7.8.0" + ember-cli-htmlbars "^3.1.0" ember-source-channel-url@^1.0.1: version "1.2.0" @@ -6377,22 +6507,22 @@ ember-source-channel-url@^2.0.1: dependencies: got "^8.0.1" -ember-source@^3.13.3: - version "3.13.3" - resolved "https://registry.npmjs.org/ember-source/-/ember-source-3.13.3.tgz#65794f79dec0512d833332575f13c77f9ccae2a1" - integrity sha512-aDmzAwpCa4H6ozd+RbsQs9/Pfo4wbnDVe9eb2D05PH9W6zRpiUa+pTluJsUFDfbi+jYGPQnjty2U/UQYBayFvg== +ember-source@^3.14.1: + version "3.14.1" + resolved "https://registry.npmjs.org/ember-source/-/ember-source-3.14.1.tgz#f11f98dffa7b169a045590203fa15c3ad2098c34" + integrity sha512-UvgjF/I7jANBEjQWdxtL/luXn97ZtIL3QCsJnR7HIcwRg7JuIyz/kaT9gLOGMxWEnwu610gJ+Ic0h0dkgQqg2w== dependencies: "@babel/helper-module-imports" "^7.0.0" - "@babel/plugin-transform-block-scoping" "^7.4.4" + "@babel/plugin-transform-block-scoping" "^7.6.0" "@babel/plugin-transform-object-assign" "^7.2.0" "@ember/edition-utils" "^1.1.1" babel-plugin-debug-macros "^0.3.3" babel-plugin-filter-imports "^3.0.0" - broccoli-concat "^3.7.3" + broccoli-concat "^3.7.4" broccoli-funnel "^2.0.2" broccoli-merge-trees "^3.0.2" chalk "^2.4.2" - ember-cli-babel "^7.7.0" + ember-cli-babel "^7.11.0" ember-cli-get-component-path-option "^1.0.0" ember-cli-is-package-missing "^1.0.0" ember-cli-normalize-entity-name "^1.0.0" @@ -6403,6 +6533,7 @@ ember-source@^3.13.3: inflection "^1.12.0" jquery "^3.4.1" resolve "^1.11.1" + semver "^6.1.1" silent-error "^1.1.1" ember-template-lint@^1.1.0: @@ -6417,7 +6548,7 @@ ember-template-lint@^1.1.0: resolve "^1.1.3" strip-bom "^3.0.0" -ember-test-waiters@^1.0.0: +ember-test-waiters@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/ember-test-waiters/-/ember-test-waiters-1.1.1.tgz#7df6e7a47e0fdca814aa351f7f7f9a006e15fdcd" integrity sha512-ra71ZWTGBGLeDPa308aeAg9+/nYxv2fk4OEzmXdhvbSa5Dtbei94sr5pbLXx2IiK3Re2gDAvDzxg9PVhLy9fig== @@ -6465,6 +6596,11 @@ emoji-regex@^7.0.1: resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -6643,17 +6779,17 @@ escodegen@^1.11.0: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^6.4.0: - version "6.4.0" - resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.4.0.tgz#0a04f147e31d33c6c161b2dd0971418ac52d0477" - integrity sha512-YrKucoFdc7SEko5Sxe4r6ixqXPDP1tunGw91POeZTTRKItf/AMFYt/YLEQtZMkR2LVpAVhcAcZgcWpm1oGPW7w== +eslint-config-prettier@^6.5.0: + version "6.5.0" + resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.5.0.tgz#aaf9a495e2a816865e541bfdbb73a65cc162b3eb" + integrity sha512-cjXp8SbO9VFGW/Z7mbTydqS9to8Z58E5aYhj3e1+Hx7lS9s6gL5ILKNpCqZAFOVYRcSkWPFYljHrEh8QFEK5EQ== dependencies: get-stdin "^6.0.0" -eslint-plugin-ember@^7.1.0, eslint-plugin-ember@^7.2.0: - version "7.2.0" - resolved "https://registry.npmjs.org/eslint-plugin-ember/-/eslint-plugin-ember-7.2.0.tgz#668e20b2ab3442d6ee3ba18c016f37f794eb0104" - integrity sha512-W2Vtep3sbAkNhZOISv3ofMd1LD9fp0QtLR9088Zw5mZkvM9uSGBSENCZfpWdwhvebruOvGpb1r7F1sjC5Qjs0w== +eslint-plugin-ember@^7.3.0: + version "7.3.0" + resolved "https://registry.npmjs.org/eslint-plugin-ember/-/eslint-plugin-ember-7.3.0.tgz#8af2efbedbff376b6da3e080a566eba76180a7df" + integrity sha512-Xx4d+VR6i+/1nuFeNmKSmdXwpl7aCAA1U/fh8ysmopX8d5vFFlBJY5rKP7EQOWe/7hebB6rVn45gAh9Xie4plw== dependencies: "@ember-data/rfc395-data" "^0.0.4" ember-rfc176-data "^0.3.12" @@ -6667,10 +6803,10 @@ eslint-plugin-es@^2.0.0: eslint-utils "^1.4.2" regexpp "^3.0.0" -eslint-plugin-mocha@^6.2.0: - version "6.2.0" - resolved "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-6.2.0.tgz#16ff9ce4d5a6a35af522d5db0ce3c8946566e4c1" - integrity sha512-vE/+tHJVom2BkMOiwkOKcAM5YqGPk3C6gMvQ32DHihKkaXF6vmxtj3UEOg64wP3m8/Zk5V/UmQbFE5nqu1EXSg== +eslint-plugin-mocha@^6.2.1: + version "6.2.1" + resolved "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-6.2.1.tgz#f2ae6d82511291949e440a34b57df773cb4b5ede" + integrity sha512-o3Ibhpczi5MjUVpnlnrpC/+oJYGoHKB5m4bQdRnaAOeFCN3HRkqBisQ2/h0hEuCR4lPxyHP1Qzyjpna8MsOdlA== dependencies: ramda "^0.26.1" @@ -6714,7 +6850,7 @@ eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^1.4.2: +eslint-utils@^1.4.2, eslint-utils@^1.4.3: version "1.4.3" resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== @@ -6726,10 +6862,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@^6.5.1: - version "6.5.1" - resolved "https://registry.npmjs.org/eslint/-/eslint-6.5.1.tgz#828e4c469697d43bb586144be152198b91e96ed6" - integrity sha512-32h99BoLYStT1iq1v2P9uwpyznQ4M2jRiFB6acitKz52Gqn+vPaMDUTB1bYi1WN4Nquj2w+t+bimYUG83DC55A== +eslint@^6.6.0: + version "6.6.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-6.6.0.tgz#4a01a2fb48d32aacef5530ee9c5a78f11a8afd04" + integrity sha512-PpEBq7b6qY/qrOmpYQ/jTMDYfuQMELR4g4WI1M/NaSDDD/bdcMb+dj4Hgks7p41kW2caXsPsEZAEAyAgjVVC0g== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -6738,9 +6874,9 @@ eslint@^6.5.1: debug "^4.0.1" doctrine "^3.0.0" eslint-scope "^5.0.0" - eslint-utils "^1.4.2" + eslint-utils "^1.4.3" eslint-visitor-keys "^1.1.0" - espree "^6.1.1" + espree "^6.1.2" esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^5.0.1" @@ -6750,7 +6886,7 @@ eslint@^6.5.1: ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^6.4.1" + inquirer "^7.0.0" is-glob "^4.0.0" js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" @@ -6774,7 +6910,7 @@ esm@^3.2.25, esm@^3.2.4: resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== -espree@^6.1.1: +espree@^6.1.2: version "6.1.2" resolved "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== @@ -6893,7 +7029,7 @@ execa@^2.0.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -execa@^3.2.0: +execa@^3.1.0, execa@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/execa/-/execa-3.2.0.tgz#18326b79c7ab7fbd6610fd900c1b9e95fa48f90a" integrity sha512-kJJfVbI/lZE1PZYDI5VPxp8zXPO9rtxOkhpZ0jMKha56AI9y2gGVC6bkukStQf0ka5Rh15BA5m7cCCH4jmHqkw== @@ -7153,6 +7289,13 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" +figures@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" + integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" @@ -7938,6 +8081,25 @@ handlebars@^4.0.11, handlebars@^4.0.13, handlebars@^4.0.4, handlebars@^4.3.1, ha optionalDependencies: uglify-js "^3.1.4" +handlebars@^4.4.3: + version "4.5.1" + resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.5.1.tgz#8a01c382c180272260d07f2d1aa3ae745715c7ba" + integrity sha512-C29UoFzHe9yM61lOsIlCE5/mQVGrnIOrOq7maQl76L7tYPCgC1og0Ajt6uWnX4ZTxBPnjw+CUvawphwCfJgUnA== + dependencies: + neo-async "^2.6.0" + optimist "^0.6.1" + source-map "^0.6.1" + optionalDependencies: + uglify-js "^3.1.4" + +har-remix@^2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/har-remix/-/har-remix-2.3.0.tgz#050401da9df00fd101c2dae620ba15a099c20dfd" + integrity sha512-vsdXfy6DRw5hlINdNRUSmo8rRioXA7VbzmjIMtuvBBEQyCac4lgvh8GdzTBl9rI6UpIH9F5ma13kClIPUbchYQ== + dependencies: + "@tracerbench/har" "^2.3.0" + mime-types "^2.1.24" + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -8432,7 +8594,7 @@ inline-source-map-comment@^1.0.5: sum-up "^1.0.1" xtend "^4.0.0" -inquirer@^6, inquirer@^6.2.0, inquirer@^6.4.1, inquirer@^6.5.1: +inquirer@^6, inquirer@^6.2.0, inquirer@^6.5.1: version "6.5.2" resolved "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== @@ -8451,6 +8613,25 @@ inquirer@^6, inquirer@^6.2.0, inquirer@^6.4.1, inquirer@^6.5.1: strip-ansi "^5.1.0" through "^2.3.6" +inquirer@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz#9e2b032dde77da1db5db804758b8fea3a970519a" + integrity sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ== + dependencies: + ansi-escapes "^4.2.1" + chalk "^2.4.2" + cli-cursor "^3.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^4.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + into-stream@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" @@ -8607,6 +8788,11 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-git-url@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-git-url/-/is-git-url-1.0.0.tgz#53f684cd143285b52c3244b4e6f28253527af66b" @@ -8759,6 +8945,11 @@ is-wsl@^1.1.0: resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= +is-wsl@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz#4a1c152d429df3d441669498e2486d3596ebaf1d" + integrity sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog== + isarray@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -9102,6 +9293,14 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lighthouse-logger@^1.0.0: + version "1.2.0" + resolved "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.2.0.tgz#b76d56935e9c137e86a04741f6bb9b2776e886ca" + integrity sha512-wzUvdIeJZhRsG6gpZfmSCfysaxNEr43i+QT+Hie94wvHDKFLi4n7C2GqZ4sTC+PH5b5iktmXJvU87rWvhP3lHw== + dependencies: + debug "^2.6.8" + marky "^1.2.0" + line-stream@0.0.0: version "0.0.0" resolved "https://registry.npmjs.org/line-stream/-/line-stream-0.0.0.tgz#888b7cc7951c6a05ce4d696dd1e6b8262371bb45" @@ -9591,6 +9790,11 @@ markdown-it@^9.0.1: mdurl "^1.0.1" uc.micro "^1.0.5" +marky@^1.2.0: + version "1.2.1" + resolved "https://registry.npmjs.org/marky/-/marky-1.2.1.tgz#a3fcf82ffd357756b8b8affec9fdbf3a30dc1b02" + integrity sha512-md9k+Gxa3qLH6sUKpeC2CNkJK/Ld+bEz5X96nYwloqphQE0CKCVEKco/6jxEZixinqNdz5RFi/KaCyfbMDMAXQ== + matcher-collection@^1.0.0, matcher-collection@^1.0.4, matcher-collection@^1.1.1: version "1.1.2" resolved "https://registry.npmjs.org/matcher-collection/-/matcher-collection-1.1.2.tgz#1076f506f10ca85897b53d14ef54f90a5c426838" @@ -9773,7 +9977,7 @@ mime-db@1.40.0: resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== -mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.19, mime-types@~2.1.19, mime-types@~2.1.24: +mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.19, mime-types@^2.1.24, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.24" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== @@ -10005,7 +10209,7 @@ mute-stream@0.0.7: resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -mute-stream@~0.0.4: +mute-stream@0.0.8, mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== @@ -11241,15 +11445,15 @@ quick-temp@^0.1.2, quick-temp@^0.1.3, quick-temp@^0.1.5, quick-temp@^0.1.8: rimraf "^2.5.4" underscore.string "~3.3.4" -qunit-dom@^0.9.0: - version "0.9.0" - resolved "https://registry.npmjs.org/qunit-dom/-/qunit-dom-0.9.0.tgz#99d15fffbf06059e543bb93dae8fe0a3f42a27b9" - integrity sha512-MvVEoCcf8BHVPD3gXg5GBfNy3JMZ3U3yOha4MB1rFs698EpvxMprOfC+NMEGvOF9Epm6GrsA0BFOdCKHd8Orrw== +qunit-dom@^0.9.1: + version "0.9.1" + resolved "https://registry.npmjs.org/qunit-dom/-/qunit-dom-0.9.1.tgz#d861ff8d2402cc7844874a37df85940d62bfbbdf" + integrity sha512-5MOPPjohXSL+4dE5ZmgWgypqF9XMxJBpobwSVzf/9zNS8PKEdJiRlR09R1Wrc38BTf3Ap2f2YPcNh3H6lEOZ6A== dependencies: broccoli-funnel "^2.0.2" broccoli-merge-trees "^3.0.1" -qunit@^2.9.2, qunit@^2.9.3: +qunit@^2.9.3: version "2.9.3" resolved "https://registry.npmjs.org/qunit/-/qunit-2.9.3.tgz#9522a088e76f0782f70a45db92f2fd14db311bcc" integrity sha512-RH4VYSaVsNRDthMFFboTJAJ8q4kJM5LvOqWponKUYPEAeOcmc/YFV1QsZ7ikknA3TjqliWFJYEV63vvVXaALmQ== @@ -11260,6 +11464,11 @@ qunit@^2.9.2, qunit@^2.9.3: node-watch "0.6.1" resolve "1.9.0" +race-cancellation@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/race-cancellation/-/race-cancellation-0.4.1.tgz#bd1c69bf5b836b56645a4b5b78fb9b973c46eb45" + integrity sha512-TF1vf4q/a5mwER9DoIuniE/qNIRM3Begyoe+21VUKgsyQAT4iIfSqlK7aG4Of1J1wzeATqVwbDP0dwX9GhaGcw== + ramda@^0.26.1: version "0.26.1" resolved "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" @@ -11784,6 +11993,14 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + ret@~0.1.10: version "0.1.15" resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -11978,7 +12195,7 @@ schema-utils@^1.0.0: resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -12561,6 +12778,15 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string-width@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz#ba846d1daa97c3c596155308063e075ed1c99aff" + integrity sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^5.2.0" + string.prototype.trimleft@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" @@ -13121,7 +13347,7 @@ trim-right@^1.0.1: resolved "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: version "1.10.0" resolved "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== @@ -13182,6 +13408,11 @@ type-fest@^0.3.0: resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== +type-fest@^0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" + integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== + type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"