diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..098c18b
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+lambdaResponseValidator/
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f6bb4e7..b8ba044 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
# Change Log
+### [1.0.3] - 2023-12-13
+- Added in new schema checker tool for AWS Lambda response format: [utilities/lambdaResponseValidator/build/Validate.html](utilities/lambdaResponseValidator/build/Validate.html)
+
### [1.0.3] - 2023-11-25
- Update for new schema element "interpretationSource"
- Security updates
diff --git a/src/sharedLibraries/DialogHelpers.ts b/src/sharedLibraries/DialogHelpers.ts
index cd20f80..21d6a81 100644
--- a/src/sharedLibraries/DialogHelpers.ts
+++ b/src/sharedLibraries/DialogHelpers.ts
@@ -7,11 +7,13 @@ import {
LambdaCodeHookSessionState,
Attributes,
LambdaCodeHookSessionStateIntent,
+ CodeHookIntentState
} from "./LexCodeHookInterfaces"
-import { DialogActionType, Message, IntentState } from "@aws-sdk/client-lex-runtime-v2"
+import { DialogActionType, Message } from "@aws-sdk/client-lex-runtime-v2"
const delegate = (sessionState: LambdaCodeHookSessionState, requestAttributes?: Attributes) => {
// Ensure session state dialog action is set to Delegate, pass everything else in as-is
+ // NOTE Delegate doesn't use any passed in messages and will just use the build-time configuration prompts
sessionState.dialogAction = {
type: DialogActionType.DELEGATE,
}
@@ -32,8 +34,7 @@ const fulfillIntent = (
requestAttributes: Attributes,
messages?: Message[]
) => {
- //NOTE Delegate doesn't take the passed in messages and will just use the build-time configuration prompts
- const fulfilledSessionState = updateSessionState(sessionState, IntentState.FULFILLED, DialogActionType.CLOSE)
+ const fulfilledSessionState = updateSessionState(sessionState, CodeHookIntentState.FULFILLED, DialogActionType.CLOSE)
const response: LexCodeHookResponse = {
sessionState: fulfilledSessionState,
@@ -47,7 +48,7 @@ const fulfillIntent = (
const endConversation = (event: LexCodeHookInputEvent, messages?: Message[]) => {
// This indicates a successful completion of the conversation,
// if this is not the case the state should be set to "Failed"
- const sessionState = updateSessionState(event.sessionState, IntentState.FULFILLED, DialogActionType.CLOSE)
+ const sessionState = updateSessionState(event.sessionState, CodeHookIntentState.FULFILLED, DialogActionType.CLOSE)
const response: LexCodeHookResponse = {
sessionState: sessionState,
@@ -90,7 +91,7 @@ const promptForConfirmationOfIntent = (
type: DialogActionType.CONFIRM_INTENT,
}
- intent.state = IntentState.IN_PROGRESS
+ intent.state = CodeHookIntentState.IN_PROGRESS
response.sessionState.intent = intent
return response
@@ -114,7 +115,7 @@ const promptForSlot = (
slotToElicit: slotToElicit,
}
- intent.state = IntentState.IN_PROGRESS
+ intent.state = CodeHookIntentState.IN_PROGRESS
response.sessionState.intent = intent
return response
@@ -122,7 +123,7 @@ const promptForSlot = (
const updateSessionState = (
currentState: LambdaCodeHookSessionState,
- newIntentState: IntentState,
+ newIntentState: CodeHookIntentState,
newDialogActionType: DialogActionType
) => {
const sessionState = currentState
diff --git a/src/sharedLibraries/LexCodeHookInterfaces.ts b/src/sharedLibraries/LexCodeHookInterfaces.ts
index 679336f..17e5836 100644
--- a/src/sharedLibraries/LexCodeHookInterfaces.ts
+++ b/src/sharedLibraries/LexCodeHookInterfaces.ts
@@ -146,15 +146,17 @@ export type Attributes = Record
*/
export interface LambdaCodeHookSessionState extends SessionState {
sessionAttributes: Attributes
- intent?: LambdaCodeHookSessionStateIntent
}
/**
- * The Lambda function event Intent state differs from the API_runtime_Intent
- * because it can optionally include the kendraResponse when the intent is KendraSearchIntent
+ * The Lambda function event Intent state differs from the API_runtime_Intent because
+ * - it can optionally include the kendraResponse when the intent is KendraSearchIntent
+ * - there is a smaller set of states, in progress or waiting states will not be sent to,
+ * and should not be returned from, the Lambda function
*/
export interface LambdaCodeHookSessionStateIntent extends Intent {
kendraResponse?: QueryResult
+ state?: CodeHookIntentState
}
export interface Transcription {
@@ -265,6 +267,14 @@ export const enum InvocationSource {
FULFILLMENT_CODE_HOOK = "FulfillmentCodeHook",
}
+export const enum CodeHookIntentState {
+ FAILED = "Failed",
+ FULFILLED = "Fulfilled",
+ IN_PROGRESS = "InProgress",
+ READY_FOR_FULFILLMENT = "ReadyForFulfillment",
+}
+
+
export const enum InterpretationSource {
BEDROCK= "Bedrock",
LEX = "Lex"
diff --git a/utilities/lambdaResponseValidator/README.md b/utilities/lambdaResponseValidator/README.md
new file mode 100644
index 0000000..42dbc5a
--- /dev/null
+++ b/utilities/lambdaResponseValidator/README.md
@@ -0,0 +1,26 @@
+# Amazon Lex V2 Lambda function response validator
+
+## Using the validator
+You can run the validator locally by opening [./build/Validate.html](./build/Validate.html) in a browser.
+
+You may also opt to host it somewhere, ensure that you also include [./build/validation-bundle.js](./build/validation-bundle.js) alongside it.
+
+The validator runs locally against a schema, and does not transmit data externally.
+It requires the input to be in strict JSON format.
+
+Although it will catch most schema violations, there are some nuances that will not be caught by the validator, and you should review the Amazon Lex [documentation](https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html) for more details on the schema and specifics.
+
+## Why use the validator
+
+If you are getting an error similar to
+
+`Invalid Lambda Response: Received invalid response from Lambda: Cannot construct instance of IntentResponse...` or finding your bot exits unexpectedly when calling a Code Hook then you can use the validator to find the specific problems in your response.
+
+The easiest way to do this is to log out from your Lambda function the exact response you are sending back to Amazon Lex.
+Since the validator requires JSON, logging the object out as JSON format will make things easier for you.
+
+---
+
+
+### Updating the validator
+You will find the source files for the validator in the `./src` directory, and you can update these and run `npm run package` to update the build files.
diff --git a/utilities/lambdaResponseValidator/build/Validate.html b/utilities/lambdaResponseValidator/build/Validate.html
new file mode 100644
index 0000000..c7772c6
--- /dev/null
+++ b/utilities/lambdaResponseValidator/build/Validate.html
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
+
+ Validate Code Hook Response
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Validate
+
+
+
+
Valid
+
Schema violations found
+
+
+
+ Note: All data is processed locally on your browser. Be aware that this tool will catch most schema validations,
+ but there may be other issues with your response that will not be caught here.
+ Review the
documentation for the full
+ requirements.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/utilities/lambdaResponseValidator/build/validation-bundle.js b/utilities/lambdaResponseValidator/build/validation-bundle.js
new file mode 100644
index 0000000..4325171
--- /dev/null
+++ b/utilities/lambdaResponseValidator/build/validation-bundle.js
@@ -0,0 +1,8078 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.validation = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;iA list of contexts active for the request. A context can be activated when a previous intent is fulfilled, or by including the context in the request.
If you don't specify a list of contexts, Amazon Lex V2 will use the current list of contexts for the session. If you specify an empty list, all contexts for the session are cleared.
",
+ "type": "object"
+ },
+ "name": {
+ "description": "The name of the context.
",
+ "type": "string"
+ },
+ "timeToLive": {
+ "$ref": "#/definitions/ActiveContextTimeToLive",
+ "description": "Indicates the number of turns or seconds that the context is active. Once the time to live expires, the context is no longer returned in a response.
"
+ }
+ },
+ "required": [
+ "name",
+ "timeToLive"
+ ],
+ "type": "object"
+ },
+ "ActiveContextTimeToLive": {
+ "additionalProperties": false,
+ "properties": {
+ "timeToLiveInSeconds": {
+ "description": "The number of seconds that the context is active. You can specify between 5 and 86400 seconds (24 hours).
",
+ "type": "number"
+ },
+ "turnsToLive": {
+ "description": "The number of turns that the context is active. You can specify up to 20 turns. Each request and response from the bot is a turn.
",
+ "type": "number"
+ }
+ },
+ "required": [
+ "turnsToLive",
+ "timeToLiveInSeconds"
+ ],
+ "type": "object"
+ },
+ "Attributes": {
+ "additionalProperties": {
+ "type": "string"
+ },
+ "description": "Map of key/value pairs",
+ "type": "object"
+ },
+ "Button": {
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "description": "The text that is displayed on the button.
",
+ "type": "string"
+ },
+ "value": {
+ "description": "The value returned to Amazon Lex V2 when a user chooses the button.
",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "ConfirmationState": {
+ "enum": [
+ "Confirmed",
+ "Denied",
+ "None"
+ ],
+ "type": "string"
+ },
+ "DialogAction": {
+ "additionalProperties": false,
+ "properties": {
+ "slotElicitationStyle": {
+ "$ref": "#/definitions/StyleType",
+ "description": "Configures the slot to use spell-by-letter or spell-by-word style. When you use a style on a slot, users can spell out their input to make it clear to your bot.
For more information, see Using spelling to enter slot values .
"
+ },
+ "slotToElicit": {
+ "description": "The name of the slot that should be elicited from the user. Required if the type of dialogAction is ElicitSlot
",
+ "type": "string"
+ },
+ "subSlotToElicit": {
+ "$ref": "#/definitions/ElicitSubSlot",
+ "description": "The name of the constituent sub slot of the composite slot specified in slotToElicit that should be elicited from the user.
"
+ },
+ "type": {
+ "$ref": "#/definitions/DialogActionType",
+ "description": "The next action that the bot should take in its interaction with the user. The possible values are:
Close
- Indicates that there will not be a response from the user. For example, the statement \"Your order has been placed\" does not require a response.
ConfirmIntent
- The next action is asking the user if the intent is complete and ready to be fulfilled. This is a yes/no question such as \"Place the order?\"
Delegate
- The next action is determined by Amazon Lex V2.
ElicitIntent
- The next action is to elicit an intent from the user.
ElicitSlot
- The next action is to elicit a slot value from the user.
"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "if": {
+ "anyOf": [
+ {
+ "properties": {
+ "type": {
+ "const": "ElicitSlot"
+ }
+ }
+ }
+ ]
+ },
+ "then": {
+ "required": [
+ "slotToElicit"
+ ],
+ "properties": {
+ "slotToElicit": {
+ "minLength": 1
+ }
+ }
+ },
+ "type": "object"
+ },
+ "DialogActionType": {
+ "enum": [
+ "Close",
+ "ConfirmIntent",
+ "Delegate",
+ "ElicitIntent",
+ "ElicitSlot",
+ "None"
+ ],
+ "type": "string"
+ },
+ "ElicitSubSlot": {
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "description": "The name of the slot that should be elicited from the user.
",
+ "type": "string"
+ },
+ "subSlotToElicit": {
+ "$ref": "#/definitions/ElicitSubSlot",
+ "description": "The field is not supported.
"
+ }
+ },
+ "type": "object"
+ },
+ "ImageResponseCard": {
+ "additionalProperties": false,
+ "properties": {
+ "buttons": {
+ "description": "A list of buttons that should be displayed on the response card. The arrangement of the buttons is determined by the platform that displays the button.
",
+ "items": {
+ "$ref": "#/definitions/Button"
+ },
+ "type": "array"
+ },
+ "imageUrl": {
+ "description": "The URL of an image to display on the response card. The image URL must be publicly available so that the platform displaying the response card has access to the image.
",
+ "type": "string"
+ },
+ "subtitle": {
+ "description": "The subtitle to display on the response card. The format of the subtitle is determined by the platform displaying the response card.
",
+ "type": "string"
+ },
+ "title": {
+ "description": "The title to display on the response card. The format of the title is determined by the platform displaying the response card.
",
+ "type": "string"
+ }
+ },
+ "required": [
+ "title"
+ ],
+ "type": "object"
+ },
+ "Intent": {
+ "additionalProperties": false,
+ "properties": {
+ "confirmationState": {
+ "$ref": "#/definitions/ConfirmationState",
+ "description": "Contains information about whether fulfillment of the intent has been confirmed.
"
+ },
+ "name": {
+ "description": "The name of the intent.
",
+ "type": "string"
+ },
+ "slots": {
+ "additionalProperties": {
+ "$ref": "#/definitions/Slot"
+ },
+ "description": "A map of all of the slots for the intent. The name of the slot maps to the value of the slot. If a slot has not been filled, the value is null.
",
+ "type": "object"
+ },
+ "state": {
+ "$ref": "#/definitions/IntentState",
+ "description": "Contains fulfillment information for the intent.
"
+ }
+ },
+ "type": "object"
+ },
+ "IntentState": {
+ "enum": [
+ "Failed",
+ "Fulfilled",
+ "InProgress",
+ "ReadyForFulfillment"
+ ],
+ "type": "string"
+ },
+ "LambdaCodeHookSessionState": {
+ "additionalProperties": false,
+ "description": "The Lambda function event Session state differs from the API_runtime_SessionState because of the format of the Intent",
+ "properties": {
+ "activeContexts": {
+ "description": "One or more contexts that indicate to Amazon Lex V2 the context of a request. When a context is active, Amazon Lex V2 considers intents with the matching context as a trigger as the next intent in a session.
",
+ "items": {
+ "$ref": "#/definitions/ActiveContext"
+ },
+ "type": "array"
+ },
+ "dialogAction": {
+ "$ref": "#/definitions/DialogAction",
+ "description": "The next step that Amazon Lex V2 should take in the conversation with a user.
"
+ },
+ "intent": {
+ "$ref": "#/definitions/Intent",
+ "description": "The active intent that Amazon Lex V2 is processing.
"
+ },
+ "originatingRequestId": {
+ "description": "A unique identifier for a specific request.
",
+ "type": "string"
+ },
+ "runtimeHints": {
+ "$ref": "#/definitions/RuntimeHints",
+ "description": "Hints for phrases that a customer is likely to use for a slot. Amazon Lex V2 uses the hints to help determine the correct value of a slot.
"
+ },
+ "sessionAttributes": {
+ "$ref": "#/definitions/Attributes",
+ "description": "Map of key/value pairs representing session-specific context information. It contains application information passed between Amazon Lex V2 and a client application.
"
+ }
+ },
+ "required": [
+ "sessionAttributes",
+ "dialogAction"
+ ],
+ "type": "object"
+ },
+ "LexCodeHookResponse": {
+ "additionalProperties": false,
+ "properties": {
+ "messages": {
+ "description": "One or more messages that Amazon Lex V2 shows to the customer to perform the next turn of the conversation. If you don't supply messages, Amazon Lex V2 uses the appropriate message defined when the bot was created\n\nRequired if dialogAction.type is ElicitIntent.",
+ "items": {
+ "$ref": "#/definitions/Message"
+ },
+ "type": "array"
+ },
+ "requestAttributes": {
+ "$ref": "#/definitions/Attributes",
+ "description": "Request-specific attributes"
+ },
+ "sessionState": {
+ "$ref": "#/definitions/LambdaCodeHookSessionState",
+ "description": "The current state of the conversation with the user.\n\nThe actual contents of the structure depends on the type of dialog action."
+ }
+ },
+ "required": [
+ "sessionState"
+ ],
+ "if": {
+ "properties": {
+ "sessionState": {
+ "properties": {
+ "dialogAction": {
+ "properties" : {
+ "type": {
+ "const": "ElicitIntent"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "then": {
+ "required": ["messages"],
+ "properties": {
+ "messages": {
+ "minItems": 1
+ }
+ }
+ },
+ "else" : {
+ "required":[]
+ },
+ "type": "object"
+ },
+ "Message": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "content": {
+ "description": "The text of the message.
",
+ "type": "string"
+ },
+ "contentType": {
+ "$ref": "#/definitions/MessageContentType",
+ "description": "Indicates the type of response.
"
+ },
+ "imageResponseCard": {
+ "$ref": "#/definitions/ImageResponseCard",
+ "description": "A card that is shown to the user by a messaging platform. You define the contents of the card, the card is displayed by the platform.
When you use a response card, the response from the user is constrained to the text associated with a button on the card.
"
+ }
+ },
+ "required": [
+ "contentType"
+ ],
+ "if": {
+ "properties": {
+ "contentType": {
+ "const": "ImageResponseCard"
+ }
+ }
+ },
+ "then": {
+ "required": [
+ "imageResponseCard"
+ ]
+ },
+ "else": {
+ "required": [
+ "content"
+ ]
+ }
+ },
+ "MessageContentType": {
+ "enum": [
+ "CustomPayload",
+ "ImageResponseCard",
+ "PlainText",
+ "SSML"
+ ],
+ "type": "string"
+ },
+ "RuntimeHintDetails": {
+ "additionalProperties": false,
+ "properties": {
+ "runtimeHintValues": {
+ "description": "One or more strings that Amazon Lex V2 should look for in the input to the bot. Each phrase is given preference when deciding on slot values.
",
+ "items": {
+ "$ref": "#/definitions/RuntimeHintValue"
+ },
+ "type": "array"
+ },
+ "subSlotHints": {
+ "additionalProperties": {
+ "$ref": "#/definitions/RuntimeHintDetails"
+ },
+ "description": "A map of constituent sub slot names inside a composite slot in the intent and the phrases that should be added for each sub slot. Inside each composite slot hints, this structure provides a mechanism to add granular sub slot phrases. Only sub slot hints are supported for composite slots. The intent name, composite slot name and the constituent sub slot names must exist.
",
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "RuntimeHintValue": {
+ "additionalProperties": false,
+ "properties": {
+ "phrase": {
+ "description": "The phrase that Amazon Lex V2 should look for in the user's input to the bot.
",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "RuntimeHints": {
+ "additionalProperties": false,
+ "properties": {
+ "slotHints": {
+ "additionalProperties": {
+ "additionalProperties": {
+ "$ref": "#/definitions/RuntimeHintDetails"
+ },
+ "type": "object"
+ },
+ "description": "A list of the slots in the intent that should have runtime hints added, and the phrases that should be added for each slot.
The first level of the slotHints
map is the name of the intent. The second level is the name of the slot within the intent. For more information, see Using hints to improve accuracy .
The intent name and slot name must exist.
",
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "Shape": {
+ "enum": [
+ "Composite",
+ "List",
+ "Scalar"
+ ],
+ "type": "string"
+ },
+ "Slot": {
+ "additionalProperties": false,
+ "properties": {
+ "shape": {
+ "$ref": "#/definitions/Shape",
+ "description": "When the shape
value is List
, it indicates that the values
field contains a list of slot values. When the value is Scalar
, it indicates that the value
field contains a single value.
"
+ },
+ "subSlots": {
+ "additionalProperties": {
+ "$ref": "#/definitions/Slot"
+ },
+ "description": "The constituent sub slots of a composite slot.
",
+ "type": "object"
+ },
+ "value": {
+ "$ref": "#/definitions/Value",
+ "description": "The current value of the slot.
"
+ },
+ "values": {
+ "description": "A list of one or more values that the user provided for the slot. For example, if a for a slot that elicits pizza toppings, the values might be \"pepperoni\" and \"pineapple.\"
",
+ "items": {
+ "$ref": "#/definitions/Slot"
+ },
+ "type": "array"
+ }
+ },
+ "type": ["object", "null"]
+ },
+ "StyleType": {
+ "enum": [
+ "Default",
+ "SpellByLetter",
+ "SpellByWord"
+ ],
+ "type": "string"
+ },
+ "Value": {
+ "additionalProperties": false,
+ "properties": {
+ "interpretedValue": {
+ "description": "The value that Amazon Lex V2 determines for the slot. The actual value depends on the setting of the value selection strategy for the bot. You can choose to use the value entered by the user, or you can have Amazon Lex V2 choose the first value in the resolvedValues
list.
",
+ "type": "string"
+ },
+ "originalValue": {
+ "description": "The text of the utterance from the user that was entered for the slot.
",
+ "type": "string"
+ },
+ "resolvedValues": {
+ "description": "A list of additional values that have been recognized for the slot.
",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ }
+ }
+}
+
+},{}],2:[function(require,module,exports){
+/* eslint-disable */
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: MIT-0
+
+const Ajv2019 = require("ajv/dist/2019")
+const schema = require("./LexCodeHookResponseSchema.json")
+const ajv = new Ajv2019({ allErrors: true })
+
+exports.validateInput = function (inputData) {
+ let response = []
+
+ const errors = validateLexLambdaResponse(inputData)
+ for (let i = 0; i < errors.length; i++) {
+ if (errors[i].keyword !== "if" && errors[i].keyword !== "else" && errors[i].keyword !== "then") {
+ let message = ``
+
+ if (errors[i].instancePath === "") {
+ message += errors[i].message
+ } else {
+ message += `${errors[i].instancePath} ${errors[i].message}`
+ }
+
+ if (errors[i].params.allowedValues) {
+ message += `. Allowed values: ${errors[i].params.allowedValues.join(", ")}`
+ }
+ response.push(message)
+ }
+ }
+ return response
+}
+
+function validateLexLambdaResponse(inputData) {
+ const validate = ajv.compile(schema)
+ validate(inputData)
+ console.debug("Validation errors:", validate.errors)
+ return validate.errors || []
+}
+
+},{"./LexCodeHookResponseSchema.json":1,"ajv/dist/2019":3}],3:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.MissingRefError = exports.ValidationError = exports.CodeGen = exports.Name = exports.nil = exports.stringify = exports.str = exports._ = exports.KeywordCxt = void 0;
+const core_1 = require("./core");
+const draft7_1 = require("./vocabularies/draft7");
+const dynamic_1 = require("./vocabularies/dynamic");
+const next_1 = require("./vocabularies/next");
+const unevaluated_1 = require("./vocabularies/unevaluated");
+const discriminator_1 = require("./vocabularies/discriminator");
+const json_schema_2019_09_1 = require("./refs/json-schema-2019-09");
+const META_SCHEMA_ID = "https://json-schema.org/draft/2019-09/schema";
+class Ajv2019 extends core_1.default {
+ constructor(opts = {}) {
+ super({
+ ...opts,
+ dynamicRef: true,
+ next: true,
+ unevaluated: true,
+ });
+ }
+ _addVocabularies() {
+ super._addVocabularies();
+ this.addVocabulary(dynamic_1.default);
+ draft7_1.default.forEach((v) => this.addVocabulary(v));
+ this.addVocabulary(next_1.default);
+ this.addVocabulary(unevaluated_1.default);
+ if (this.opts.discriminator)
+ this.addKeyword(discriminator_1.default);
+ }
+ _addDefaultMetaSchema() {
+ super._addDefaultMetaSchema();
+ const { $data, meta } = this.opts;
+ if (!meta)
+ return;
+ json_schema_2019_09_1.default.call(this, $data);
+ this.refs["http://json-schema.org/schema"] = META_SCHEMA_ID;
+ }
+ defaultMeta() {
+ return (this.opts.defaultMeta =
+ super.defaultMeta() || (this.getSchema(META_SCHEMA_ID) ? META_SCHEMA_ID : undefined));
+ }
+}
+module.exports = exports = Ajv2019;
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.default = Ajv2019;
+var validate_1 = require("./compile/validate");
+Object.defineProperty(exports, "KeywordCxt", { enumerable: true, get: function () { return validate_1.KeywordCxt; } });
+var codegen_1 = require("./compile/codegen");
+Object.defineProperty(exports, "_", { enumerable: true, get: function () { return codegen_1._; } });
+Object.defineProperty(exports, "str", { enumerable: true, get: function () { return codegen_1.str; } });
+Object.defineProperty(exports, "stringify", { enumerable: true, get: function () { return codegen_1.stringify; } });
+Object.defineProperty(exports, "nil", { enumerable: true, get: function () { return codegen_1.nil; } });
+Object.defineProperty(exports, "Name", { enumerable: true, get: function () { return codegen_1.Name; } });
+Object.defineProperty(exports, "CodeGen", { enumerable: true, get: function () { return codegen_1.CodeGen; } });
+var validation_error_1 = require("./runtime/validation_error");
+Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return validation_error_1.default; } });
+var ref_error_1 = require("./compile/ref_error");
+Object.defineProperty(exports, "MissingRefError", { enumerable: true, get: function () { return ref_error_1.default; } });
+
+},{"./compile/codegen":5,"./compile/ref_error":10,"./compile/validate":18,"./core":21,"./refs/json-schema-2019-09":23,"./runtime/validation_error":34,"./vocabularies/discriminator":57,"./vocabularies/draft7":59,"./vocabularies/dynamic":62,"./vocabularies/next":68,"./vocabularies/unevaluated":69}],4:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.regexpCode = exports.getEsmExportName = exports.getProperty = exports.safeStringify = exports.stringify = exports.strConcat = exports.addCodeArg = exports.str = exports._ = exports.nil = exports._Code = exports.Name = exports.IDENTIFIER = exports._CodeOrName = void 0;
+class _CodeOrName {
+}
+exports._CodeOrName = _CodeOrName;
+exports.IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i;
+class Name extends _CodeOrName {
+ constructor(s) {
+ super();
+ if (!exports.IDENTIFIER.test(s))
+ throw new Error("CodeGen: name must be a valid identifier");
+ this.str = s;
+ }
+ toString() {
+ return this.str;
+ }
+ emptyStr() {
+ return false;
+ }
+ get names() {
+ return { [this.str]: 1 };
+ }
+}
+exports.Name = Name;
+class _Code extends _CodeOrName {
+ constructor(code) {
+ super();
+ this._items = typeof code === "string" ? [code] : code;
+ }
+ toString() {
+ return this.str;
+ }
+ emptyStr() {
+ if (this._items.length > 1)
+ return false;
+ const item = this._items[0];
+ return item === "" || item === '""';
+ }
+ get str() {
+ var _a;
+ return ((_a = this._str) !== null && _a !== void 0 ? _a : (this._str = this._items.reduce((s, c) => `${s}${c}`, "")));
+ }
+ get names() {
+ var _a;
+ return ((_a = this._names) !== null && _a !== void 0 ? _a : (this._names = this._items.reduce((names, c) => {
+ if (c instanceof Name)
+ names[c.str] = (names[c.str] || 0) + 1;
+ return names;
+ }, {})));
+ }
+}
+exports._Code = _Code;
+exports.nil = new _Code("");
+function _(strs, ...args) {
+ const code = [strs[0]];
+ let i = 0;
+ while (i < args.length) {
+ addCodeArg(code, args[i]);
+ code.push(strs[++i]);
+ }
+ return new _Code(code);
+}
+exports._ = _;
+const plus = new _Code("+");
+function str(strs, ...args) {
+ const expr = [safeStringify(strs[0])];
+ let i = 0;
+ while (i < args.length) {
+ expr.push(plus);
+ addCodeArg(expr, args[i]);
+ expr.push(plus, safeStringify(strs[++i]));
+ }
+ optimize(expr);
+ return new _Code(expr);
+}
+exports.str = str;
+function addCodeArg(code, arg) {
+ if (arg instanceof _Code)
+ code.push(...arg._items);
+ else if (arg instanceof Name)
+ code.push(arg);
+ else
+ code.push(interpolate(arg));
+}
+exports.addCodeArg = addCodeArg;
+function optimize(expr) {
+ let i = 1;
+ while (i < expr.length - 1) {
+ if (expr[i] === plus) {
+ const res = mergeExprItems(expr[i - 1], expr[i + 1]);
+ if (res !== undefined) {
+ expr.splice(i - 1, 3, res);
+ continue;
+ }
+ expr[i++] = "+";
+ }
+ i++;
+ }
+}
+function mergeExprItems(a, b) {
+ if (b === '""')
+ return a;
+ if (a === '""')
+ return b;
+ if (typeof a == "string") {
+ if (b instanceof Name || a[a.length - 1] !== '"')
+ return;
+ if (typeof b != "string")
+ return `${a.slice(0, -1)}${b}"`;
+ if (b[0] === '"')
+ return a.slice(0, -1) + b.slice(1);
+ return;
+ }
+ if (typeof b == "string" && b[0] === '"' && !(a instanceof Name))
+ return `"${a}${b.slice(1)}`;
+ return;
+}
+function strConcat(c1, c2) {
+ return c2.emptyStr() ? c1 : c1.emptyStr() ? c2 : str `${c1}${c2}`;
+}
+exports.strConcat = strConcat;
+// TODO do not allow arrays here
+function interpolate(x) {
+ return typeof x == "number" || typeof x == "boolean" || x === null
+ ? x
+ : safeStringify(Array.isArray(x) ? x.join(",") : x);
+}
+function stringify(x) {
+ return new _Code(safeStringify(x));
+}
+exports.stringify = stringify;
+function safeStringify(x) {
+ return JSON.stringify(x)
+ .replace(/\u2028/g, "\\u2028")
+ .replace(/\u2029/g, "\\u2029");
+}
+exports.safeStringify = safeStringify;
+function getProperty(key) {
+ return typeof key == "string" && exports.IDENTIFIER.test(key) ? new _Code(`.${key}`) : _ `[${key}]`;
+}
+exports.getProperty = getProperty;
+//Does best effort to format the name properly
+function getEsmExportName(key) {
+ if (typeof key == "string" && exports.IDENTIFIER.test(key)) {
+ return new _Code(`${key}`);
+ }
+ throw new Error(`CodeGen: invalid export name: ${key}, use explicit $id name mapping`);
+}
+exports.getEsmExportName = getEsmExportName;
+function regexpCode(rx) {
+ return new _Code(rx.toString());
+}
+exports.regexpCode = regexpCode;
+
+},{}],5:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.or = exports.and = exports.not = exports.CodeGen = exports.operators = exports.varKinds = exports.ValueScopeName = exports.ValueScope = exports.Scope = exports.Name = exports.regexpCode = exports.stringify = exports.getProperty = exports.nil = exports.strConcat = exports.str = exports._ = void 0;
+const code_1 = require("./code");
+const scope_1 = require("./scope");
+var code_2 = require("./code");
+Object.defineProperty(exports, "_", { enumerable: true, get: function () { return code_2._; } });
+Object.defineProperty(exports, "str", { enumerable: true, get: function () { return code_2.str; } });
+Object.defineProperty(exports, "strConcat", { enumerable: true, get: function () { return code_2.strConcat; } });
+Object.defineProperty(exports, "nil", { enumerable: true, get: function () { return code_2.nil; } });
+Object.defineProperty(exports, "getProperty", { enumerable: true, get: function () { return code_2.getProperty; } });
+Object.defineProperty(exports, "stringify", { enumerable: true, get: function () { return code_2.stringify; } });
+Object.defineProperty(exports, "regexpCode", { enumerable: true, get: function () { return code_2.regexpCode; } });
+Object.defineProperty(exports, "Name", { enumerable: true, get: function () { return code_2.Name; } });
+var scope_2 = require("./scope");
+Object.defineProperty(exports, "Scope", { enumerable: true, get: function () { return scope_2.Scope; } });
+Object.defineProperty(exports, "ValueScope", { enumerable: true, get: function () { return scope_2.ValueScope; } });
+Object.defineProperty(exports, "ValueScopeName", { enumerable: true, get: function () { return scope_2.ValueScopeName; } });
+Object.defineProperty(exports, "varKinds", { enumerable: true, get: function () { return scope_2.varKinds; } });
+exports.operators = {
+ GT: new code_1._Code(">"),
+ GTE: new code_1._Code(">="),
+ LT: new code_1._Code("<"),
+ LTE: new code_1._Code("<="),
+ EQ: new code_1._Code("==="),
+ NEQ: new code_1._Code("!=="),
+ NOT: new code_1._Code("!"),
+ OR: new code_1._Code("||"),
+ AND: new code_1._Code("&&"),
+ ADD: new code_1._Code("+"),
+};
+class Node {
+ optimizeNodes() {
+ return this;
+ }
+ optimizeNames(_names, _constants) {
+ return this;
+ }
+}
+class Def extends Node {
+ constructor(varKind, name, rhs) {
+ super();
+ this.varKind = varKind;
+ this.name = name;
+ this.rhs = rhs;
+ }
+ render({ es5, _n }) {
+ const varKind = es5 ? scope_1.varKinds.var : this.varKind;
+ const rhs = this.rhs === undefined ? "" : ` = ${this.rhs}`;
+ return `${varKind} ${this.name}${rhs};` + _n;
+ }
+ optimizeNames(names, constants) {
+ if (!names[this.name.str])
+ return;
+ if (this.rhs)
+ this.rhs = optimizeExpr(this.rhs, names, constants);
+ return this;
+ }
+ get names() {
+ return this.rhs instanceof code_1._CodeOrName ? this.rhs.names : {};
+ }
+}
+class Assign extends Node {
+ constructor(lhs, rhs, sideEffects) {
+ super();
+ this.lhs = lhs;
+ this.rhs = rhs;
+ this.sideEffects = sideEffects;
+ }
+ render({ _n }) {
+ return `${this.lhs} = ${this.rhs};` + _n;
+ }
+ optimizeNames(names, constants) {
+ if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
+ return;
+ this.rhs = optimizeExpr(this.rhs, names, constants);
+ return this;
+ }
+ get names() {
+ const names = this.lhs instanceof code_1.Name ? {} : { ...this.lhs.names };
+ return addExprNames(names, this.rhs);
+ }
+}
+class AssignOp extends Assign {
+ constructor(lhs, op, rhs, sideEffects) {
+ super(lhs, rhs, sideEffects);
+ this.op = op;
+ }
+ render({ _n }) {
+ return `${this.lhs} ${this.op}= ${this.rhs};` + _n;
+ }
+}
+class Label extends Node {
+ constructor(label) {
+ super();
+ this.label = label;
+ this.names = {};
+ }
+ render({ _n }) {
+ return `${this.label}:` + _n;
+ }
+}
+class Break extends Node {
+ constructor(label) {
+ super();
+ this.label = label;
+ this.names = {};
+ }
+ render({ _n }) {
+ const label = this.label ? ` ${this.label}` : "";
+ return `break${label};` + _n;
+ }
+}
+class Throw extends Node {
+ constructor(error) {
+ super();
+ this.error = error;
+ }
+ render({ _n }) {
+ return `throw ${this.error};` + _n;
+ }
+ get names() {
+ return this.error.names;
+ }
+}
+class AnyCode extends Node {
+ constructor(code) {
+ super();
+ this.code = code;
+ }
+ render({ _n }) {
+ return `${this.code};` + _n;
+ }
+ optimizeNodes() {
+ return `${this.code}` ? this : undefined;
+ }
+ optimizeNames(names, constants) {
+ this.code = optimizeExpr(this.code, names, constants);
+ return this;
+ }
+ get names() {
+ return this.code instanceof code_1._CodeOrName ? this.code.names : {};
+ }
+}
+class ParentNode extends Node {
+ constructor(nodes = []) {
+ super();
+ this.nodes = nodes;
+ }
+ render(opts) {
+ return this.nodes.reduce((code, n) => code + n.render(opts), "");
+ }
+ optimizeNodes() {
+ const { nodes } = this;
+ let i = nodes.length;
+ while (i--) {
+ const n = nodes[i].optimizeNodes();
+ if (Array.isArray(n))
+ nodes.splice(i, 1, ...n);
+ else if (n)
+ nodes[i] = n;
+ else
+ nodes.splice(i, 1);
+ }
+ return nodes.length > 0 ? this : undefined;
+ }
+ optimizeNames(names, constants) {
+ const { nodes } = this;
+ let i = nodes.length;
+ while (i--) {
+ // iterating backwards improves 1-pass optimization
+ const n = nodes[i];
+ if (n.optimizeNames(names, constants))
+ continue;
+ subtractNames(names, n.names);
+ nodes.splice(i, 1);
+ }
+ return nodes.length > 0 ? this : undefined;
+ }
+ get names() {
+ return this.nodes.reduce((names, n) => addNames(names, n.names), {});
+ }
+}
+class BlockNode extends ParentNode {
+ render(opts) {
+ return "{" + opts._n + super.render(opts) + "}" + opts._n;
+ }
+}
+class Root extends ParentNode {
+}
+class Else extends BlockNode {
+}
+Else.kind = "else";
+class If extends BlockNode {
+ constructor(condition, nodes) {
+ super(nodes);
+ this.condition = condition;
+ }
+ render(opts) {
+ let code = `if(${this.condition})` + super.render(opts);
+ if (this.else)
+ code += "else " + this.else.render(opts);
+ return code;
+ }
+ optimizeNodes() {
+ super.optimizeNodes();
+ const cond = this.condition;
+ if (cond === true)
+ return this.nodes; // else is ignored here
+ let e = this.else;
+ if (e) {
+ const ns = e.optimizeNodes();
+ e = this.else = Array.isArray(ns) ? new Else(ns) : ns;
+ }
+ if (e) {
+ if (cond === false)
+ return e instanceof If ? e : e.nodes;
+ if (this.nodes.length)
+ return this;
+ return new If(not(cond), e instanceof If ? [e] : e.nodes);
+ }
+ if (cond === false || !this.nodes.length)
+ return undefined;
+ return this;
+ }
+ optimizeNames(names, constants) {
+ var _a;
+ this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants);
+ if (!(super.optimizeNames(names, constants) || this.else))
+ return;
+ this.condition = optimizeExpr(this.condition, names, constants);
+ return this;
+ }
+ get names() {
+ const names = super.names;
+ addExprNames(names, this.condition);
+ if (this.else)
+ addNames(names, this.else.names);
+ return names;
+ }
+}
+If.kind = "if";
+class For extends BlockNode {
+}
+For.kind = "for";
+class ForLoop extends For {
+ constructor(iteration) {
+ super();
+ this.iteration = iteration;
+ }
+ render(opts) {
+ return `for(${this.iteration})` + super.render(opts);
+ }
+ optimizeNames(names, constants) {
+ if (!super.optimizeNames(names, constants))
+ return;
+ this.iteration = optimizeExpr(this.iteration, names, constants);
+ return this;
+ }
+ get names() {
+ return addNames(super.names, this.iteration.names);
+ }
+}
+class ForRange extends For {
+ constructor(varKind, name, from, to) {
+ super();
+ this.varKind = varKind;
+ this.name = name;
+ this.from = from;
+ this.to = to;
+ }
+ render(opts) {
+ const varKind = opts.es5 ? scope_1.varKinds.var : this.varKind;
+ const { name, from, to } = this;
+ return `for(${varKind} ${name}=${from}; ${name}<${to}; ${name}++)` + super.render(opts);
+ }
+ get names() {
+ const names = addExprNames(super.names, this.from);
+ return addExprNames(names, this.to);
+ }
+}
+class ForIter extends For {
+ constructor(loop, varKind, name, iterable) {
+ super();
+ this.loop = loop;
+ this.varKind = varKind;
+ this.name = name;
+ this.iterable = iterable;
+ }
+ render(opts) {
+ return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
+ }
+ optimizeNames(names, constants) {
+ if (!super.optimizeNames(names, constants))
+ return;
+ this.iterable = optimizeExpr(this.iterable, names, constants);
+ return this;
+ }
+ get names() {
+ return addNames(super.names, this.iterable.names);
+ }
+}
+class Func extends BlockNode {
+ constructor(name, args, async) {
+ super();
+ this.name = name;
+ this.args = args;
+ this.async = async;
+ }
+ render(opts) {
+ const _async = this.async ? "async " : "";
+ return `${_async}function ${this.name}(${this.args})` + super.render(opts);
+ }
+}
+Func.kind = "func";
+class Return extends ParentNode {
+ render(opts) {
+ return "return " + super.render(opts);
+ }
+}
+Return.kind = "return";
+class Try extends BlockNode {
+ render(opts) {
+ let code = "try" + super.render(opts);
+ if (this.catch)
+ code += this.catch.render(opts);
+ if (this.finally)
+ code += this.finally.render(opts);
+ return code;
+ }
+ optimizeNodes() {
+ var _a, _b;
+ super.optimizeNodes();
+ (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNodes();
+ (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNodes();
+ return this;
+ }
+ optimizeNames(names, constants) {
+ var _a, _b;
+ super.optimizeNames(names, constants);
+ (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants);
+ (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants);
+ return this;
+ }
+ get names() {
+ const names = super.names;
+ if (this.catch)
+ addNames(names, this.catch.names);
+ if (this.finally)
+ addNames(names, this.finally.names);
+ return names;
+ }
+}
+class Catch extends BlockNode {
+ constructor(error) {
+ super();
+ this.error = error;
+ }
+ render(opts) {
+ return `catch(${this.error})` + super.render(opts);
+ }
+}
+Catch.kind = "catch";
+class Finally extends BlockNode {
+ render(opts) {
+ return "finally" + super.render(opts);
+ }
+}
+Finally.kind = "finally";
+class CodeGen {
+ constructor(extScope, opts = {}) {
+ this._values = {};
+ this._blockStarts = [];
+ this._constants = {};
+ this.opts = { ...opts, _n: opts.lines ? "\n" : "" };
+ this._extScope = extScope;
+ this._scope = new scope_1.Scope({ parent: extScope });
+ this._nodes = [new Root()];
+ }
+ toString() {
+ return this._root.render(this.opts);
+ }
+ // returns unique name in the internal scope
+ name(prefix) {
+ return this._scope.name(prefix);
+ }
+ // reserves unique name in the external scope
+ scopeName(prefix) {
+ return this._extScope.name(prefix);
+ }
+ // reserves unique name in the external scope and assigns value to it
+ scopeValue(prefixOrName, value) {
+ const name = this._extScope.value(prefixOrName, value);
+ const vs = this._values[name.prefix] || (this._values[name.prefix] = new Set());
+ vs.add(name);
+ return name;
+ }
+ getScopeValue(prefix, keyOrRef) {
+ return this._extScope.getValue(prefix, keyOrRef);
+ }
+ // return code that assigns values in the external scope to the names that are used internally
+ // (same names that were returned by gen.scopeName or gen.scopeValue)
+ scopeRefs(scopeName) {
+ return this._extScope.scopeRefs(scopeName, this._values);
+ }
+ scopeCode() {
+ return this._extScope.scopeCode(this._values);
+ }
+ _def(varKind, nameOrPrefix, rhs, constant) {
+ const name = this._scope.toName(nameOrPrefix);
+ if (rhs !== undefined && constant)
+ this._constants[name.str] = rhs;
+ this._leafNode(new Def(varKind, name, rhs));
+ return name;
+ }
+ // `const` declaration (`var` in es5 mode)
+ const(nameOrPrefix, rhs, _constant) {
+ return this._def(scope_1.varKinds.const, nameOrPrefix, rhs, _constant);
+ }
+ // `let` declaration with optional assignment (`var` in es5 mode)
+ let(nameOrPrefix, rhs, _constant) {
+ return this._def(scope_1.varKinds.let, nameOrPrefix, rhs, _constant);
+ }
+ // `var` declaration with optional assignment
+ var(nameOrPrefix, rhs, _constant) {
+ return this._def(scope_1.varKinds.var, nameOrPrefix, rhs, _constant);
+ }
+ // assignment code
+ assign(lhs, rhs, sideEffects) {
+ return this._leafNode(new Assign(lhs, rhs, sideEffects));
+ }
+ // `+=` code
+ add(lhs, rhs) {
+ return this._leafNode(new AssignOp(lhs, exports.operators.ADD, rhs));
+ }
+ // appends passed SafeExpr to code or executes Block
+ code(c) {
+ if (typeof c == "function")
+ c();
+ else if (c !== code_1.nil)
+ this._leafNode(new AnyCode(c));
+ return this;
+ }
+ // returns code for object literal for the passed argument list of key-value pairs
+ object(...keyValues) {
+ const code = ["{"];
+ for (const [key, value] of keyValues) {
+ if (code.length > 1)
+ code.push(",");
+ code.push(key);
+ if (key !== value || this.opts.es5) {
+ code.push(":");
+ (0, code_1.addCodeArg)(code, value);
+ }
+ }
+ code.push("}");
+ return new code_1._Code(code);
+ }
+ // `if` clause (or statement if `thenBody` and, optionally, `elseBody` are passed)
+ if(condition, thenBody, elseBody) {
+ this._blockNode(new If(condition));
+ if (thenBody && elseBody) {
+ this.code(thenBody).else().code(elseBody).endIf();
+ }
+ else if (thenBody) {
+ this.code(thenBody).endIf();
+ }
+ else if (elseBody) {
+ throw new Error('CodeGen: "else" body without "then" body');
+ }
+ return this;
+ }
+ // `else if` clause - invalid without `if` or after `else` clauses
+ elseIf(condition) {
+ return this._elseNode(new If(condition));
+ }
+ // `else` clause - only valid after `if` or `else if` clauses
+ else() {
+ return this._elseNode(new Else());
+ }
+ // end `if` statement (needed if gen.if was used only with condition)
+ endIf() {
+ return this._endBlockNode(If, Else);
+ }
+ _for(node, forBody) {
+ this._blockNode(node);
+ if (forBody)
+ this.code(forBody).endFor();
+ return this;
+ }
+ // a generic `for` clause (or statement if `forBody` is passed)
+ for(iteration, forBody) {
+ return this._for(new ForLoop(iteration), forBody);
+ }
+ // `for` statement for a range of values
+ forRange(nameOrPrefix, from, to, forBody, varKind = this.opts.es5 ? scope_1.varKinds.var : scope_1.varKinds.let) {
+ const name = this._scope.toName(nameOrPrefix);
+ return this._for(new ForRange(varKind, name, from, to), () => forBody(name));
+ }
+ // `for-of` statement (in es5 mode replace with a normal for loop)
+ forOf(nameOrPrefix, iterable, forBody, varKind = scope_1.varKinds.const) {
+ const name = this._scope.toName(nameOrPrefix);
+ if (this.opts.es5) {
+ const arr = iterable instanceof code_1.Name ? iterable : this.var("_arr", iterable);
+ return this.forRange("_i", 0, (0, code_1._) `${arr}.length`, (i) => {
+ this.var(name, (0, code_1._) `${arr}[${i}]`);
+ forBody(name);
+ });
+ }
+ return this._for(new ForIter("of", varKind, name, iterable), () => forBody(name));
+ }
+ // `for-in` statement.
+ // With option `ownProperties` replaced with a `for-of` loop for object keys
+ forIn(nameOrPrefix, obj, forBody, varKind = this.opts.es5 ? scope_1.varKinds.var : scope_1.varKinds.const) {
+ if (this.opts.ownProperties) {
+ return this.forOf(nameOrPrefix, (0, code_1._) `Object.keys(${obj})`, forBody);
+ }
+ const name = this._scope.toName(nameOrPrefix);
+ return this._for(new ForIter("in", varKind, name, obj), () => forBody(name));
+ }
+ // end `for` loop
+ endFor() {
+ return this._endBlockNode(For);
+ }
+ // `label` statement
+ label(label) {
+ return this._leafNode(new Label(label));
+ }
+ // `break` statement
+ break(label) {
+ return this._leafNode(new Break(label));
+ }
+ // `return` statement
+ return(value) {
+ const node = new Return();
+ this._blockNode(node);
+ this.code(value);
+ if (node.nodes.length !== 1)
+ throw new Error('CodeGen: "return" should have one node');
+ return this._endBlockNode(Return);
+ }
+ // `try` statement
+ try(tryBody, catchCode, finallyCode) {
+ if (!catchCode && !finallyCode)
+ throw new Error('CodeGen: "try" without "catch" and "finally"');
+ const node = new Try();
+ this._blockNode(node);
+ this.code(tryBody);
+ if (catchCode) {
+ const error = this.name("e");
+ this._currNode = node.catch = new Catch(error);
+ catchCode(error);
+ }
+ if (finallyCode) {
+ this._currNode = node.finally = new Finally();
+ this.code(finallyCode);
+ }
+ return this._endBlockNode(Catch, Finally);
+ }
+ // `throw` statement
+ throw(error) {
+ return this._leafNode(new Throw(error));
+ }
+ // start self-balancing block
+ block(body, nodeCount) {
+ this._blockStarts.push(this._nodes.length);
+ if (body)
+ this.code(body).endBlock(nodeCount);
+ return this;
+ }
+ // end the current self-balancing block
+ endBlock(nodeCount) {
+ const len = this._blockStarts.pop();
+ if (len === undefined)
+ throw new Error("CodeGen: not in self-balancing block");
+ const toClose = this._nodes.length - len;
+ if (toClose < 0 || (nodeCount !== undefined && toClose !== nodeCount)) {
+ throw new Error(`CodeGen: wrong number of nodes: ${toClose} vs ${nodeCount} expected`);
+ }
+ this._nodes.length = len;
+ return this;
+ }
+ // `function` heading (or definition if funcBody is passed)
+ func(name, args = code_1.nil, async, funcBody) {
+ this._blockNode(new Func(name, args, async));
+ if (funcBody)
+ this.code(funcBody).endFunc();
+ return this;
+ }
+ // end function definition
+ endFunc() {
+ return this._endBlockNode(Func);
+ }
+ optimize(n = 1) {
+ while (n-- > 0) {
+ this._root.optimizeNodes();
+ this._root.optimizeNames(this._root.names, this._constants);
+ }
+ }
+ _leafNode(node) {
+ this._currNode.nodes.push(node);
+ return this;
+ }
+ _blockNode(node) {
+ this._currNode.nodes.push(node);
+ this._nodes.push(node);
+ }
+ _endBlockNode(N1, N2) {
+ const n = this._currNode;
+ if (n instanceof N1 || (N2 && n instanceof N2)) {
+ this._nodes.pop();
+ return this;
+ }
+ throw new Error(`CodeGen: not in block "${N2 ? `${N1.kind}/${N2.kind}` : N1.kind}"`);
+ }
+ _elseNode(node) {
+ const n = this._currNode;
+ if (!(n instanceof If)) {
+ throw new Error('CodeGen: "else" without "if"');
+ }
+ this._currNode = n.else = node;
+ return this;
+ }
+ get _root() {
+ return this._nodes[0];
+ }
+ get _currNode() {
+ const ns = this._nodes;
+ return ns[ns.length - 1];
+ }
+ set _currNode(node) {
+ const ns = this._nodes;
+ ns[ns.length - 1] = node;
+ }
+}
+exports.CodeGen = CodeGen;
+function addNames(names, from) {
+ for (const n in from)
+ names[n] = (names[n] || 0) + (from[n] || 0);
+ return names;
+}
+function addExprNames(names, from) {
+ return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
+}
+function optimizeExpr(expr, names, constants) {
+ if (expr instanceof code_1.Name)
+ return replaceName(expr);
+ if (!canOptimize(expr))
+ return expr;
+ return new code_1._Code(expr._items.reduce((items, c) => {
+ if (c instanceof code_1.Name)
+ c = replaceName(c);
+ if (c instanceof code_1._Code)
+ items.push(...c._items);
+ else
+ items.push(c);
+ return items;
+ }, []));
+ function replaceName(n) {
+ const c = constants[n.str];
+ if (c === undefined || names[n.str] !== 1)
+ return n;
+ delete names[n.str];
+ return c;
+ }
+ function canOptimize(e) {
+ return (e instanceof code_1._Code &&
+ e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants[c.str] !== undefined));
+ }
+}
+function subtractNames(names, from) {
+ for (const n in from)
+ names[n] = (names[n] || 0) - (from[n] || 0);
+}
+function not(x) {
+ return typeof x == "boolean" || typeof x == "number" || x === null ? !x : (0, code_1._) `!${par(x)}`;
+}
+exports.not = not;
+const andCode = mappend(exports.operators.AND);
+// boolean AND (&&) expression with the passed arguments
+function and(...args) {
+ return args.reduce(andCode);
+}
+exports.and = and;
+const orCode = mappend(exports.operators.OR);
+// boolean OR (||) expression with the passed arguments
+function or(...args) {
+ return args.reduce(orCode);
+}
+exports.or = or;
+function mappend(op) {
+ return (x, y) => (x === code_1.nil ? y : y === code_1.nil ? x : (0, code_1._) `${par(x)} ${op} ${par(y)}`);
+}
+function par(x) {
+ return x instanceof code_1.Name ? x : (0, code_1._) `(${x})`;
+}
+
+},{"./code":4,"./scope":6}],6:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.ValueScope = exports.ValueScopeName = exports.Scope = exports.varKinds = exports.UsedValueState = void 0;
+const code_1 = require("./code");
+class ValueError extends Error {
+ constructor(name) {
+ super(`CodeGen: "code" for ${name} not defined`);
+ this.value = name.value;
+ }
+}
+var UsedValueState;
+(function (UsedValueState) {
+ UsedValueState[UsedValueState["Started"] = 0] = "Started";
+ UsedValueState[UsedValueState["Completed"] = 1] = "Completed";
+})(UsedValueState = exports.UsedValueState || (exports.UsedValueState = {}));
+exports.varKinds = {
+ const: new code_1.Name("const"),
+ let: new code_1.Name("let"),
+ var: new code_1.Name("var"),
+};
+class Scope {
+ constructor({ prefixes, parent } = {}) {
+ this._names = {};
+ this._prefixes = prefixes;
+ this._parent = parent;
+ }
+ toName(nameOrPrefix) {
+ return nameOrPrefix instanceof code_1.Name ? nameOrPrefix : this.name(nameOrPrefix);
+ }
+ name(prefix) {
+ return new code_1.Name(this._newName(prefix));
+ }
+ _newName(prefix) {
+ const ng = this._names[prefix] || this._nameGroup(prefix);
+ return `${prefix}${ng.index++}`;
+ }
+ _nameGroup(prefix) {
+ var _a, _b;
+ if (((_b = (_a = this._parent) === null || _a === void 0 ? void 0 : _a._prefixes) === null || _b === void 0 ? void 0 : _b.has(prefix)) || (this._prefixes && !this._prefixes.has(prefix))) {
+ throw new Error(`CodeGen: prefix "${prefix}" is not allowed in this scope`);
+ }
+ return (this._names[prefix] = { prefix, index: 0 });
+ }
+}
+exports.Scope = Scope;
+class ValueScopeName extends code_1.Name {
+ constructor(prefix, nameStr) {
+ super(nameStr);
+ this.prefix = prefix;
+ }
+ setValue(value, { property, itemIndex }) {
+ this.value = value;
+ this.scopePath = (0, code_1._) `.${new code_1.Name(property)}[${itemIndex}]`;
+ }
+}
+exports.ValueScopeName = ValueScopeName;
+const line = (0, code_1._) `\n`;
+class ValueScope extends Scope {
+ constructor(opts) {
+ super(opts);
+ this._values = {};
+ this._scope = opts.scope;
+ this.opts = { ...opts, _n: opts.lines ? line : code_1.nil };
+ }
+ get() {
+ return this._scope;
+ }
+ name(prefix) {
+ return new ValueScopeName(prefix, this._newName(prefix));
+ }
+ value(nameOrPrefix, value) {
+ var _a;
+ if (value.ref === undefined)
+ throw new Error("CodeGen: ref must be passed in value");
+ const name = this.toName(nameOrPrefix);
+ const { prefix } = name;
+ const valueKey = (_a = value.key) !== null && _a !== void 0 ? _a : value.ref;
+ let vs = this._values[prefix];
+ if (vs) {
+ const _name = vs.get(valueKey);
+ if (_name)
+ return _name;
+ }
+ else {
+ vs = this._values[prefix] = new Map();
+ }
+ vs.set(valueKey, name);
+ const s = this._scope[prefix] || (this._scope[prefix] = []);
+ const itemIndex = s.length;
+ s[itemIndex] = value.ref;
+ name.setValue(value, { property: prefix, itemIndex });
+ return name;
+ }
+ getValue(prefix, keyOrRef) {
+ const vs = this._values[prefix];
+ if (!vs)
+ return;
+ return vs.get(keyOrRef);
+ }
+ scopeRefs(scopeName, values = this._values) {
+ return this._reduceValues(values, (name) => {
+ if (name.scopePath === undefined)
+ throw new Error(`CodeGen: name "${name}" has no value`);
+ return (0, code_1._) `${scopeName}${name.scopePath}`;
+ });
+ }
+ scopeCode(values = this._values, usedValues, getCode) {
+ return this._reduceValues(values, (name) => {
+ if (name.value === undefined)
+ throw new Error(`CodeGen: name "${name}" has no value`);
+ return name.value.code;
+ }, usedValues, getCode);
+ }
+ _reduceValues(values, valueCode, usedValues = {}, getCode) {
+ let code = code_1.nil;
+ for (const prefix in values) {
+ const vs = values[prefix];
+ if (!vs)
+ continue;
+ const nameSet = (usedValues[prefix] = usedValues[prefix] || new Map());
+ vs.forEach((name) => {
+ if (nameSet.has(name))
+ return;
+ nameSet.set(name, UsedValueState.Started);
+ let c = valueCode(name);
+ if (c) {
+ const def = this.opts.es5 ? exports.varKinds.var : exports.varKinds.const;
+ code = (0, code_1._) `${code}${def} ${name} = ${c};${this.opts._n}`;
+ }
+ else if ((c = getCode === null || getCode === void 0 ? void 0 : getCode(name))) {
+ code = (0, code_1._) `${code}${c}${this.opts._n}`;
+ }
+ else {
+ throw new ValueError(name);
+ }
+ nameSet.set(name, UsedValueState.Completed);
+ });
+ }
+ return code;
+ }
+}
+exports.ValueScope = ValueScope;
+
+},{"./code":4}],7:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.extendErrors = exports.resetErrorsCount = exports.reportExtraError = exports.reportError = exports.keyword$DataError = exports.keywordError = void 0;
+const codegen_1 = require("./codegen");
+const util_1 = require("./util");
+const names_1 = require("./names");
+exports.keywordError = {
+ message: ({ keyword }) => (0, codegen_1.str) `must pass "${keyword}" keyword validation`,
+};
+exports.keyword$DataError = {
+ message: ({ keyword, schemaType }) => schemaType
+ ? (0, codegen_1.str) `"${keyword}" keyword must be ${schemaType} ($data)`
+ : (0, codegen_1.str) `"${keyword}" keyword is invalid ($data)`,
+};
+function reportError(cxt, error = exports.keywordError, errorPaths, overrideAllErrors) {
+ const { it } = cxt;
+ const { gen, compositeRule, allErrors } = it;
+ const errObj = errorObjectCode(cxt, error, errorPaths);
+ if (overrideAllErrors !== null && overrideAllErrors !== void 0 ? overrideAllErrors : (compositeRule || allErrors)) {
+ addError(gen, errObj);
+ }
+ else {
+ returnErrors(it, (0, codegen_1._) `[${errObj}]`);
+ }
+}
+exports.reportError = reportError;
+function reportExtraError(cxt, error = exports.keywordError, errorPaths) {
+ const { it } = cxt;
+ const { gen, compositeRule, allErrors } = it;
+ const errObj = errorObjectCode(cxt, error, errorPaths);
+ addError(gen, errObj);
+ if (!(compositeRule || allErrors)) {
+ returnErrors(it, names_1.default.vErrors);
+ }
+}
+exports.reportExtraError = reportExtraError;
+function resetErrorsCount(gen, errsCount) {
+ gen.assign(names_1.default.errors, errsCount);
+ gen.if((0, codegen_1._) `${names_1.default.vErrors} !== null`, () => gen.if(errsCount, () => gen.assign((0, codegen_1._) `${names_1.default.vErrors}.length`, errsCount), () => gen.assign(names_1.default.vErrors, null)));
+}
+exports.resetErrorsCount = resetErrorsCount;
+function extendErrors({ gen, keyword, schemaValue, data, errsCount, it, }) {
+ /* istanbul ignore if */
+ if (errsCount === undefined)
+ throw new Error("ajv implementation error");
+ const err = gen.name("err");
+ gen.forRange("i", errsCount, names_1.default.errors, (i) => {
+ gen.const(err, (0, codegen_1._) `${names_1.default.vErrors}[${i}]`);
+ gen.if((0, codegen_1._) `${err}.instancePath === undefined`, () => gen.assign((0, codegen_1._) `${err}.instancePath`, (0, codegen_1.strConcat)(names_1.default.instancePath, it.errorPath)));
+ gen.assign((0, codegen_1._) `${err}.schemaPath`, (0, codegen_1.str) `${it.errSchemaPath}/${keyword}`);
+ if (it.opts.verbose) {
+ gen.assign((0, codegen_1._) `${err}.schema`, schemaValue);
+ gen.assign((0, codegen_1._) `${err}.data`, data);
+ }
+ });
+}
+exports.extendErrors = extendErrors;
+function addError(gen, errObj) {
+ const err = gen.const("err", errObj);
+ gen.if((0, codegen_1._) `${names_1.default.vErrors} === null`, () => gen.assign(names_1.default.vErrors, (0, codegen_1._) `[${err}]`), (0, codegen_1._) `${names_1.default.vErrors}.push(${err})`);
+ gen.code((0, codegen_1._) `${names_1.default.errors}++`);
+}
+function returnErrors(it, errs) {
+ const { gen, validateName, schemaEnv } = it;
+ if (schemaEnv.$async) {
+ gen.throw((0, codegen_1._) `new ${it.ValidationError}(${errs})`);
+ }
+ else {
+ gen.assign((0, codegen_1._) `${validateName}.errors`, errs);
+ gen.return(false);
+ }
+}
+const E = {
+ keyword: new codegen_1.Name("keyword"),
+ schemaPath: new codegen_1.Name("schemaPath"),
+ params: new codegen_1.Name("params"),
+ propertyName: new codegen_1.Name("propertyName"),
+ message: new codegen_1.Name("message"),
+ schema: new codegen_1.Name("schema"),
+ parentSchema: new codegen_1.Name("parentSchema"),
+};
+function errorObjectCode(cxt, error, errorPaths) {
+ const { createErrors } = cxt.it;
+ if (createErrors === false)
+ return (0, codegen_1._) `{}`;
+ return errorObject(cxt, error, errorPaths);
+}
+function errorObject(cxt, error, errorPaths = {}) {
+ const { gen, it } = cxt;
+ const keyValues = [
+ errorInstancePath(it, errorPaths),
+ errorSchemaPath(cxt, errorPaths),
+ ];
+ extraErrorProps(cxt, error, keyValues);
+ return gen.object(...keyValues);
+}
+function errorInstancePath({ errorPath }, { instancePath }) {
+ const instPath = instancePath
+ ? (0, codegen_1.str) `${errorPath}${(0, util_1.getErrorPath)(instancePath, util_1.Type.Str)}`
+ : errorPath;
+ return [names_1.default.instancePath, (0, codegen_1.strConcat)(names_1.default.instancePath, instPath)];
+}
+function errorSchemaPath({ keyword, it: { errSchemaPath } }, { schemaPath, parentSchema }) {
+ let schPath = parentSchema ? errSchemaPath : (0, codegen_1.str) `${errSchemaPath}/${keyword}`;
+ if (schemaPath) {
+ schPath = (0, codegen_1.str) `${schPath}${(0, util_1.getErrorPath)(schemaPath, util_1.Type.Str)}`;
+ }
+ return [E.schemaPath, schPath];
+}
+function extraErrorProps(cxt, { params, message }, keyValues) {
+ const { keyword, data, schemaValue, it } = cxt;
+ const { opts, propertyName, topSchemaRef, schemaPath } = it;
+ keyValues.push([E.keyword, keyword], [E.params, typeof params == "function" ? params(cxt) : params || (0, codegen_1._) `{}`]);
+ if (opts.messages) {
+ keyValues.push([E.message, typeof message == "function" ? message(cxt) : message]);
+ }
+ if (opts.verbose) {
+ keyValues.push([E.schema, schemaValue], [E.parentSchema, (0, codegen_1._) `${topSchemaRef}${schemaPath}`], [names_1.default.data, data]);
+ }
+ if (propertyName)
+ keyValues.push([E.propertyName, propertyName]);
+}
+
+},{"./codegen":5,"./names":9,"./util":13}],8:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.resolveSchema = exports.getCompilingSchema = exports.resolveRef = exports.compileSchema = exports.SchemaEnv = void 0;
+const codegen_1 = require("./codegen");
+const validation_error_1 = require("../runtime/validation_error");
+const names_1 = require("./names");
+const resolve_1 = require("./resolve");
+const util_1 = require("./util");
+const validate_1 = require("./validate");
+class SchemaEnv {
+ constructor(env) {
+ var _a;
+ this.refs = {};
+ this.dynamicAnchors = {};
+ let schema;
+ if (typeof env.schema == "object")
+ schema = env.schema;
+ this.schema = env.schema;
+ this.schemaId = env.schemaId;
+ this.root = env.root || this;
+ this.baseId = (_a = env.baseId) !== null && _a !== void 0 ? _a : (0, resolve_1.normalizeId)(schema === null || schema === void 0 ? void 0 : schema[env.schemaId || "$id"]);
+ this.schemaPath = env.schemaPath;
+ this.localRefs = env.localRefs;
+ this.meta = env.meta;
+ this.$async = schema === null || schema === void 0 ? void 0 : schema.$async;
+ this.refs = {};
+ }
+}
+exports.SchemaEnv = SchemaEnv;
+// let codeSize = 0
+// let nodeCount = 0
+// Compiles schema in SchemaEnv
+function compileSchema(sch) {
+ // TODO refactor - remove compilations
+ const _sch = getCompilingSchema.call(this, sch);
+ if (_sch)
+ return _sch;
+ const rootId = (0, resolve_1.getFullPath)(this.opts.uriResolver, sch.root.baseId); // TODO if getFullPath removed 1 tests fails
+ const { es5, lines } = this.opts.code;
+ const { ownProperties } = this.opts;
+ const gen = new codegen_1.CodeGen(this.scope, { es5, lines, ownProperties });
+ let _ValidationError;
+ if (sch.$async) {
+ _ValidationError = gen.scopeValue("Error", {
+ ref: validation_error_1.default,
+ code: (0, codegen_1._) `require("ajv/dist/runtime/validation_error").default`,
+ });
+ }
+ const validateName = gen.scopeName("validate");
+ sch.validateName = validateName;
+ const schemaCxt = {
+ gen,
+ allErrors: this.opts.allErrors,
+ data: names_1.default.data,
+ parentData: names_1.default.parentData,
+ parentDataProperty: names_1.default.parentDataProperty,
+ dataNames: [names_1.default.data],
+ dataPathArr: [codegen_1.nil],
+ dataLevel: 0,
+ dataTypes: [],
+ definedProperties: new Set(),
+ topSchemaRef: gen.scopeValue("schema", this.opts.code.source === true
+ ? { ref: sch.schema, code: (0, codegen_1.stringify)(sch.schema) }
+ : { ref: sch.schema }),
+ validateName,
+ ValidationError: _ValidationError,
+ schema: sch.schema,
+ schemaEnv: sch,
+ rootId,
+ baseId: sch.baseId || rootId,
+ schemaPath: codegen_1.nil,
+ errSchemaPath: sch.schemaPath || (this.opts.jtd ? "" : "#"),
+ errorPath: (0, codegen_1._) `""`,
+ opts: this.opts,
+ self: this,
+ };
+ let sourceCode;
+ try {
+ this._compilations.add(sch);
+ (0, validate_1.validateFunctionCode)(schemaCxt);
+ gen.optimize(this.opts.code.optimize);
+ // gen.optimize(1)
+ const validateCode = gen.toString();
+ sourceCode = `${gen.scopeRefs(names_1.default.scope)}return ${validateCode}`;
+ // console.log((codeSize += sourceCode.length), (nodeCount += gen.nodeCount))
+ if (this.opts.code.process)
+ sourceCode = this.opts.code.process(sourceCode, sch);
+ // console.log("\n\n\n *** \n", sourceCode)
+ const makeValidate = new Function(`${names_1.default.self}`, `${names_1.default.scope}`, sourceCode);
+ const validate = makeValidate(this, this.scope.get());
+ this.scope.value(validateName, { ref: validate });
+ validate.errors = null;
+ validate.schema = sch.schema;
+ validate.schemaEnv = sch;
+ if (sch.$async)
+ validate.$async = true;
+ if (this.opts.code.source === true) {
+ validate.source = { validateName, validateCode, scopeValues: gen._values };
+ }
+ if (this.opts.unevaluated) {
+ const { props, items } = schemaCxt;
+ validate.evaluated = {
+ props: props instanceof codegen_1.Name ? undefined : props,
+ items: items instanceof codegen_1.Name ? undefined : items,
+ dynamicProps: props instanceof codegen_1.Name,
+ dynamicItems: items instanceof codegen_1.Name,
+ };
+ if (validate.source)
+ validate.source.evaluated = (0, codegen_1.stringify)(validate.evaluated);
+ }
+ sch.validate = validate;
+ return sch;
+ }
+ catch (e) {
+ delete sch.validate;
+ delete sch.validateName;
+ if (sourceCode)
+ this.logger.error("Error compiling schema, function code:", sourceCode);
+ // console.log("\n\n\n *** \n", sourceCode, this.opts)
+ throw e;
+ }
+ finally {
+ this._compilations.delete(sch);
+ }
+}
+exports.compileSchema = compileSchema;
+function resolveRef(root, baseId, ref) {
+ var _a;
+ ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
+ const schOrFunc = root.refs[ref];
+ if (schOrFunc)
+ return schOrFunc;
+ let _sch = resolve.call(this, root, ref);
+ if (_sch === undefined) {
+ const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref]; // TODO maybe localRefs should hold SchemaEnv
+ const { schemaId } = this.opts;
+ if (schema)
+ _sch = new SchemaEnv({ schema, schemaId, root, baseId });
+ }
+ if (_sch === undefined)
+ return;
+ return (root.refs[ref] = inlineOrCompile.call(this, _sch));
+}
+exports.resolveRef = resolveRef;
+function inlineOrCompile(sch) {
+ if ((0, resolve_1.inlineRef)(sch.schema, this.opts.inlineRefs))
+ return sch.schema;
+ return sch.validate ? sch : compileSchema.call(this, sch);
+}
+// Index of schema compilation in the currently compiled list
+function getCompilingSchema(schEnv) {
+ for (const sch of this._compilations) {
+ if (sameSchemaEnv(sch, schEnv))
+ return sch;
+ }
+}
+exports.getCompilingSchema = getCompilingSchema;
+function sameSchemaEnv(s1, s2) {
+ return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
+}
+// resolve and compile the references ($ref)
+// TODO returns AnySchemaObject (if the schema can be inlined) or validation function
+function resolve(root, // information about the root schema for the current schema
+ref // reference to resolve
+) {
+ let sch;
+ while (typeof (sch = this.refs[ref]) == "string")
+ ref = sch;
+ return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
+}
+// Resolve schema, its root and baseId
+function resolveSchema(root, // root object with properties schema, refs TODO below SchemaEnv is assigned to it
+ref // reference to resolve
+) {
+ const p = this.opts.uriResolver.parse(ref);
+ const refPath = (0, resolve_1._getFullPath)(this.opts.uriResolver, p);
+ let baseId = (0, resolve_1.getFullPath)(this.opts.uriResolver, root.baseId, undefined);
+ // TODO `Object.keys(root.schema).length > 0` should not be needed - but removing breaks 2 tests
+ if (Object.keys(root.schema).length > 0 && refPath === baseId) {
+ return getJsonPointer.call(this, p, root);
+ }
+ const id = (0, resolve_1.normalizeId)(refPath);
+ const schOrRef = this.refs[id] || this.schemas[id];
+ if (typeof schOrRef == "string") {
+ const sch = resolveSchema.call(this, root, schOrRef);
+ if (typeof (sch === null || sch === void 0 ? void 0 : sch.schema) !== "object")
+ return;
+ return getJsonPointer.call(this, p, sch);
+ }
+ if (typeof (schOrRef === null || schOrRef === void 0 ? void 0 : schOrRef.schema) !== "object")
+ return;
+ if (!schOrRef.validate)
+ compileSchema.call(this, schOrRef);
+ if (id === (0, resolve_1.normalizeId)(ref)) {
+ const { schema } = schOrRef;
+ const { schemaId } = this.opts;
+ const schId = schema[schemaId];
+ if (schId)
+ baseId = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schId);
+ return new SchemaEnv({ schema, schemaId, root, baseId });
+ }
+ return getJsonPointer.call(this, p, schOrRef);
+}
+exports.resolveSchema = resolveSchema;
+const PREVENT_SCOPE_CHANGE = new Set([
+ "properties",
+ "patternProperties",
+ "enum",
+ "dependencies",
+ "definitions",
+]);
+function getJsonPointer(parsedRef, { baseId, schema, root }) {
+ var _a;
+ if (((_a = parsedRef.fragment) === null || _a === void 0 ? void 0 : _a[0]) !== "/")
+ return;
+ for (const part of parsedRef.fragment.slice(1).split("/")) {
+ if (typeof schema === "boolean")
+ return;
+ const partSchema = schema[(0, util_1.unescapeFragment)(part)];
+ if (partSchema === undefined)
+ return;
+ schema = partSchema;
+ // TODO PREVENT_SCOPE_CHANGE could be defined in keyword def?
+ const schId = typeof schema === "object" && schema[this.opts.schemaId];
+ if (!PREVENT_SCOPE_CHANGE.has(part) && schId) {
+ baseId = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schId);
+ }
+ }
+ let env;
+ if (typeof schema != "boolean" && schema.$ref && !(0, util_1.schemaHasRulesButRef)(schema, this.RULES)) {
+ const $ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schema.$ref);
+ env = resolveSchema.call(this, root, $ref);
+ }
+ // even though resolution failed we need to return SchemaEnv to throw exception
+ // so that compileAsync loads missing schema.
+ const { schemaId } = this.opts;
+ env = env || new SchemaEnv({ schema, schemaId, root, baseId });
+ if (env.schema !== env.root.schema)
+ return env;
+ return undefined;
+}
+
+},{"../runtime/validation_error":34,"./codegen":5,"./names":9,"./resolve":11,"./util":13,"./validate":18}],9:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("./codegen");
+const names = {
+ // validation function arguments
+ data: new codegen_1.Name("data"),
+ // args passed from referencing schema
+ valCxt: new codegen_1.Name("valCxt"),
+ instancePath: new codegen_1.Name("instancePath"),
+ parentData: new codegen_1.Name("parentData"),
+ parentDataProperty: new codegen_1.Name("parentDataProperty"),
+ rootData: new codegen_1.Name("rootData"),
+ dynamicAnchors: new codegen_1.Name("dynamicAnchors"),
+ // function scoped variables
+ vErrors: new codegen_1.Name("vErrors"),
+ errors: new codegen_1.Name("errors"),
+ this: new codegen_1.Name("this"),
+ // "globals"
+ self: new codegen_1.Name("self"),
+ scope: new codegen_1.Name("scope"),
+ // JTD serialize/parse name for JSON string and position
+ json: new codegen_1.Name("json"),
+ jsonPos: new codegen_1.Name("jsonPos"),
+ jsonLen: new codegen_1.Name("jsonLen"),
+ jsonPart: new codegen_1.Name("jsonPart"),
+};
+exports.default = names;
+
+},{"./codegen":5}],10:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const resolve_1 = require("./resolve");
+class MissingRefError extends Error {
+ constructor(resolver, baseId, ref, msg) {
+ super(msg || `can't resolve reference ${ref} from id ${baseId}`);
+ this.missingRef = (0, resolve_1.resolveUrl)(resolver, baseId, ref);
+ this.missingSchema = (0, resolve_1.normalizeId)((0, resolve_1.getFullPath)(resolver, this.missingRef));
+ }
+}
+exports.default = MissingRefError;
+
+},{"./resolve":11}],11:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.getSchemaRefs = exports.resolveUrl = exports.normalizeId = exports._getFullPath = exports.getFullPath = exports.inlineRef = void 0;
+const util_1 = require("./util");
+const equal = require("fast-deep-equal");
+const traverse = require("json-schema-traverse");
+// TODO refactor to use keyword definitions
+const SIMPLE_INLINED = new Set([
+ "type",
+ "format",
+ "pattern",
+ "maxLength",
+ "minLength",
+ "maxProperties",
+ "minProperties",
+ "maxItems",
+ "minItems",
+ "maximum",
+ "minimum",
+ "uniqueItems",
+ "multipleOf",
+ "required",
+ "enum",
+ "const",
+]);
+function inlineRef(schema, limit = true) {
+ if (typeof schema == "boolean")
+ return true;
+ if (limit === true)
+ return !hasRef(schema);
+ if (!limit)
+ return false;
+ return countKeys(schema) <= limit;
+}
+exports.inlineRef = inlineRef;
+const REF_KEYWORDS = new Set([
+ "$ref",
+ "$recursiveRef",
+ "$recursiveAnchor",
+ "$dynamicRef",
+ "$dynamicAnchor",
+]);
+function hasRef(schema) {
+ for (const key in schema) {
+ if (REF_KEYWORDS.has(key))
+ return true;
+ const sch = schema[key];
+ if (Array.isArray(sch) && sch.some(hasRef))
+ return true;
+ if (typeof sch == "object" && hasRef(sch))
+ return true;
+ }
+ return false;
+}
+function countKeys(schema) {
+ let count = 0;
+ for (const key in schema) {
+ if (key === "$ref")
+ return Infinity;
+ count++;
+ if (SIMPLE_INLINED.has(key))
+ continue;
+ if (typeof schema[key] == "object") {
+ (0, util_1.eachItem)(schema[key], (sch) => (count += countKeys(sch)));
+ }
+ if (count === Infinity)
+ return Infinity;
+ }
+ return count;
+}
+function getFullPath(resolver, id = "", normalize) {
+ if (normalize !== false)
+ id = normalizeId(id);
+ const p = resolver.parse(id);
+ return _getFullPath(resolver, p);
+}
+exports.getFullPath = getFullPath;
+function _getFullPath(resolver, p) {
+ const serialized = resolver.serialize(p);
+ return serialized.split("#")[0] + "#";
+}
+exports._getFullPath = _getFullPath;
+const TRAILING_SLASH_HASH = /#\/?$/;
+function normalizeId(id) {
+ return id ? id.replace(TRAILING_SLASH_HASH, "") : "";
+}
+exports.normalizeId = normalizeId;
+function resolveUrl(resolver, baseId, id) {
+ id = normalizeId(id);
+ return resolver.resolve(baseId, id);
+}
+exports.resolveUrl = resolveUrl;
+const ANCHOR = /^[a-z_][-a-z0-9._]*$/i;
+function getSchemaRefs(schema, baseId) {
+ if (typeof schema == "boolean")
+ return {};
+ const { schemaId, uriResolver } = this.opts;
+ const schId = normalizeId(schema[schemaId] || baseId);
+ const baseIds = { "": schId };
+ const pathPrefix = getFullPath(uriResolver, schId, false);
+ const localRefs = {};
+ const schemaRefs = new Set();
+ traverse(schema, { allKeys: true }, (sch, jsonPtr, _, parentJsonPtr) => {
+ if (parentJsonPtr === undefined)
+ return;
+ const fullPath = pathPrefix + jsonPtr;
+ let baseId = baseIds[parentJsonPtr];
+ if (typeof sch[schemaId] == "string")
+ baseId = addRef.call(this, sch[schemaId]);
+ addAnchor.call(this, sch.$anchor);
+ addAnchor.call(this, sch.$dynamicAnchor);
+ baseIds[jsonPtr] = baseId;
+ function addRef(ref) {
+ // eslint-disable-next-line @typescript-eslint/unbound-method
+ const _resolve = this.opts.uriResolver.resolve;
+ ref = normalizeId(baseId ? _resolve(baseId, ref) : ref);
+ if (schemaRefs.has(ref))
+ throw ambiguos(ref);
+ schemaRefs.add(ref);
+ let schOrRef = this.refs[ref];
+ if (typeof schOrRef == "string")
+ schOrRef = this.refs[schOrRef];
+ if (typeof schOrRef == "object") {
+ checkAmbiguosRef(sch, schOrRef.schema, ref);
+ }
+ else if (ref !== normalizeId(fullPath)) {
+ if (ref[0] === "#") {
+ checkAmbiguosRef(sch, localRefs[ref], ref);
+ localRefs[ref] = sch;
+ }
+ else {
+ this.refs[ref] = fullPath;
+ }
+ }
+ return ref;
+ }
+ function addAnchor(anchor) {
+ if (typeof anchor == "string") {
+ if (!ANCHOR.test(anchor))
+ throw new Error(`invalid anchor "${anchor}"`);
+ addRef.call(this, `#${anchor}`);
+ }
+ }
+ });
+ return localRefs;
+ function checkAmbiguosRef(sch1, sch2, ref) {
+ if (sch2 !== undefined && !equal(sch1, sch2))
+ throw ambiguos(ref);
+ }
+ function ambiguos(ref) {
+ return new Error(`reference "${ref}" resolves to more than one schema`);
+ }
+}
+exports.getSchemaRefs = getSchemaRefs;
+
+},{"./util":13,"fast-deep-equal":85,"json-schema-traverse":86}],12:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.getRules = exports.isJSONType = void 0;
+const _jsonTypes = ["string", "number", "integer", "boolean", "null", "object", "array"];
+const jsonTypes = new Set(_jsonTypes);
+function isJSONType(x) {
+ return typeof x == "string" && jsonTypes.has(x);
+}
+exports.isJSONType = isJSONType;
+function getRules() {
+ const groups = {
+ number: { type: "number", rules: [] },
+ string: { type: "string", rules: [] },
+ array: { type: "array", rules: [] },
+ object: { type: "object", rules: [] },
+ };
+ return {
+ types: { ...groups, integer: true, boolean: true, null: true },
+ rules: [{ rules: [] }, groups.number, groups.string, groups.array, groups.object],
+ post: { rules: [] },
+ all: {},
+ keywords: {},
+ };
+}
+exports.getRules = getRules;
+
+},{}],13:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.checkStrictMode = exports.getErrorPath = exports.Type = exports.useFunc = exports.setEvaluated = exports.evaluatedPropsToName = exports.mergeEvaluated = exports.eachItem = exports.unescapeJsonPointer = exports.escapeJsonPointer = exports.escapeFragment = exports.unescapeFragment = exports.schemaRefOrVal = exports.schemaHasRulesButRef = exports.schemaHasRules = exports.checkUnknownRules = exports.alwaysValidSchema = exports.toHash = void 0;
+const codegen_1 = require("./codegen");
+const code_1 = require("./codegen/code");
+// TODO refactor to use Set
+function toHash(arr) {
+ const hash = {};
+ for (const item of arr)
+ hash[item] = true;
+ return hash;
+}
+exports.toHash = toHash;
+function alwaysValidSchema(it, schema) {
+ if (typeof schema == "boolean")
+ return schema;
+ if (Object.keys(schema).length === 0)
+ return true;
+ checkUnknownRules(it, schema);
+ return !schemaHasRules(schema, it.self.RULES.all);
+}
+exports.alwaysValidSchema = alwaysValidSchema;
+function checkUnknownRules(it, schema = it.schema) {
+ const { opts, self } = it;
+ if (!opts.strictSchema)
+ return;
+ if (typeof schema === "boolean")
+ return;
+ const rules = self.RULES.keywords;
+ for (const key in schema) {
+ if (!rules[key])
+ checkStrictMode(it, `unknown keyword: "${key}"`);
+ }
+}
+exports.checkUnknownRules = checkUnknownRules;
+function schemaHasRules(schema, rules) {
+ if (typeof schema == "boolean")
+ return !schema;
+ for (const key in schema)
+ if (rules[key])
+ return true;
+ return false;
+}
+exports.schemaHasRules = schemaHasRules;
+function schemaHasRulesButRef(schema, RULES) {
+ if (typeof schema == "boolean")
+ return !schema;
+ for (const key in schema)
+ if (key !== "$ref" && RULES.all[key])
+ return true;
+ return false;
+}
+exports.schemaHasRulesButRef = schemaHasRulesButRef;
+function schemaRefOrVal({ topSchemaRef, schemaPath }, schema, keyword, $data) {
+ if (!$data) {
+ if (typeof schema == "number" || typeof schema == "boolean")
+ return schema;
+ if (typeof schema == "string")
+ return (0, codegen_1._) `${schema}`;
+ }
+ return (0, codegen_1._) `${topSchemaRef}${schemaPath}${(0, codegen_1.getProperty)(keyword)}`;
+}
+exports.schemaRefOrVal = schemaRefOrVal;
+function unescapeFragment(str) {
+ return unescapeJsonPointer(decodeURIComponent(str));
+}
+exports.unescapeFragment = unescapeFragment;
+function escapeFragment(str) {
+ return encodeURIComponent(escapeJsonPointer(str));
+}
+exports.escapeFragment = escapeFragment;
+function escapeJsonPointer(str) {
+ if (typeof str == "number")
+ return `${str}`;
+ return str.replace(/~/g, "~0").replace(/\//g, "~1");
+}
+exports.escapeJsonPointer = escapeJsonPointer;
+function unescapeJsonPointer(str) {
+ return str.replace(/~1/g, "/").replace(/~0/g, "~");
+}
+exports.unescapeJsonPointer = unescapeJsonPointer;
+function eachItem(xs, f) {
+ if (Array.isArray(xs)) {
+ for (const x of xs)
+ f(x);
+ }
+ else {
+ f(xs);
+ }
+}
+exports.eachItem = eachItem;
+function makeMergeEvaluated({ mergeNames, mergeToName, mergeValues, resultToName, }) {
+ return (gen, from, to, toName) => {
+ const res = to === undefined
+ ? from
+ : to instanceof codegen_1.Name
+ ? (from instanceof codegen_1.Name ? mergeNames(gen, from, to) : mergeToName(gen, from, to), to)
+ : from instanceof codegen_1.Name
+ ? (mergeToName(gen, to, from), from)
+ : mergeValues(from, to);
+ return toName === codegen_1.Name && !(res instanceof codegen_1.Name) ? resultToName(gen, res) : res;
+ };
+}
+exports.mergeEvaluated = {
+ props: makeMergeEvaluated({
+ mergeNames: (gen, from, to) => gen.if((0, codegen_1._) `${to} !== true && ${from} !== undefined`, () => {
+ gen.if((0, codegen_1._) `${from} === true`, () => gen.assign(to, true), () => gen.assign(to, (0, codegen_1._) `${to} || {}`).code((0, codegen_1._) `Object.assign(${to}, ${from})`));
+ }),
+ mergeToName: (gen, from, to) => gen.if((0, codegen_1._) `${to} !== true`, () => {
+ if (from === true) {
+ gen.assign(to, true);
+ }
+ else {
+ gen.assign(to, (0, codegen_1._) `${to} || {}`);
+ setEvaluated(gen, to, from);
+ }
+ }),
+ mergeValues: (from, to) => (from === true ? true : { ...from, ...to }),
+ resultToName: evaluatedPropsToName,
+ }),
+ items: makeMergeEvaluated({
+ mergeNames: (gen, from, to) => gen.if((0, codegen_1._) `${to} !== true && ${from} !== undefined`, () => gen.assign(to, (0, codegen_1._) `${from} === true ? true : ${to} > ${from} ? ${to} : ${from}`)),
+ mergeToName: (gen, from, to) => gen.if((0, codegen_1._) `${to} !== true`, () => gen.assign(to, from === true ? true : (0, codegen_1._) `${to} > ${from} ? ${to} : ${from}`)),
+ mergeValues: (from, to) => (from === true ? true : Math.max(from, to)),
+ resultToName: (gen, items) => gen.var("items", items),
+ }),
+};
+function evaluatedPropsToName(gen, ps) {
+ if (ps === true)
+ return gen.var("props", true);
+ const props = gen.var("props", (0, codegen_1._) `{}`);
+ if (ps !== undefined)
+ setEvaluated(gen, props, ps);
+ return props;
+}
+exports.evaluatedPropsToName = evaluatedPropsToName;
+function setEvaluated(gen, props, ps) {
+ Object.keys(ps).forEach((p) => gen.assign((0, codegen_1._) `${props}${(0, codegen_1.getProperty)(p)}`, true));
+}
+exports.setEvaluated = setEvaluated;
+const snippets = {};
+function useFunc(gen, f) {
+ return gen.scopeValue("func", {
+ ref: f,
+ code: snippets[f.code] || (snippets[f.code] = new code_1._Code(f.code)),
+ });
+}
+exports.useFunc = useFunc;
+var Type;
+(function (Type) {
+ Type[Type["Num"] = 0] = "Num";
+ Type[Type["Str"] = 1] = "Str";
+})(Type = exports.Type || (exports.Type = {}));
+function getErrorPath(dataProp, dataPropType, jsPropertySyntax) {
+ // let path
+ if (dataProp instanceof codegen_1.Name) {
+ const isNumber = dataPropType === Type.Num;
+ return jsPropertySyntax
+ ? isNumber
+ ? (0, codegen_1._) `"[" + ${dataProp} + "]"`
+ : (0, codegen_1._) `"['" + ${dataProp} + "']"`
+ : isNumber
+ ? (0, codegen_1._) `"/" + ${dataProp}`
+ : (0, codegen_1._) `"/" + ${dataProp}.replace(/~/g, "~0").replace(/\\//g, "~1")`; // TODO maybe use global escapePointer
+ }
+ return jsPropertySyntax ? (0, codegen_1.getProperty)(dataProp).toString() : "/" + escapeJsonPointer(dataProp);
+}
+exports.getErrorPath = getErrorPath;
+function checkStrictMode(it, msg, mode = it.opts.strictSchema) {
+ if (!mode)
+ return;
+ msg = `strict mode: ${msg}`;
+ if (mode === true)
+ throw new Error(msg);
+ it.self.logger.warn(msg);
+}
+exports.checkStrictMode = checkStrictMode;
+
+},{"./codegen":5,"./codegen/code":4}],14:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.shouldUseRule = exports.shouldUseGroup = exports.schemaHasRulesForType = void 0;
+function schemaHasRulesForType({ schema, self }, type) {
+ const group = self.RULES.types[type];
+ return group && group !== true && shouldUseGroup(schema, group);
+}
+exports.schemaHasRulesForType = schemaHasRulesForType;
+function shouldUseGroup(schema, group) {
+ return group.rules.some((rule) => shouldUseRule(schema, rule));
+}
+exports.shouldUseGroup = shouldUseGroup;
+function shouldUseRule(schema, rule) {
+ var _a;
+ return (schema[rule.keyword] !== undefined ||
+ ((_a = rule.definition.implements) === null || _a === void 0 ? void 0 : _a.some((kwd) => schema[kwd] !== undefined)));
+}
+exports.shouldUseRule = shouldUseRule;
+
+},{}],15:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.boolOrEmptySchema = exports.topBoolOrEmptySchema = void 0;
+const errors_1 = require("../errors");
+const codegen_1 = require("../codegen");
+const names_1 = require("../names");
+const boolError = {
+ message: "boolean schema is false",
+};
+function topBoolOrEmptySchema(it) {
+ const { gen, schema, validateName } = it;
+ if (schema === false) {
+ falseSchemaError(it, false);
+ }
+ else if (typeof schema == "object" && schema.$async === true) {
+ gen.return(names_1.default.data);
+ }
+ else {
+ gen.assign((0, codegen_1._) `${validateName}.errors`, null);
+ gen.return(true);
+ }
+}
+exports.topBoolOrEmptySchema = topBoolOrEmptySchema;
+function boolOrEmptySchema(it, valid) {
+ const { gen, schema } = it;
+ if (schema === false) {
+ gen.var(valid, false); // TODO var
+ falseSchemaError(it);
+ }
+ else {
+ gen.var(valid, true); // TODO var
+ }
+}
+exports.boolOrEmptySchema = boolOrEmptySchema;
+function falseSchemaError(it, overrideAllErrors) {
+ const { gen, data } = it;
+ // TODO maybe some other interface should be used for non-keyword validation errors...
+ const cxt = {
+ gen,
+ keyword: "false schema",
+ data,
+ schema: false,
+ schemaCode: false,
+ schemaValue: false,
+ params: {},
+ it,
+ };
+ (0, errors_1.reportError)(cxt, boolError, undefined, overrideAllErrors);
+}
+
+},{"../codegen":5,"../errors":7,"../names":9}],16:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.reportTypeError = exports.checkDataTypes = exports.checkDataType = exports.coerceAndCheckDataType = exports.getJSONTypes = exports.getSchemaTypes = exports.DataType = void 0;
+const rules_1 = require("../rules");
+const applicability_1 = require("./applicability");
+const errors_1 = require("../errors");
+const codegen_1 = require("../codegen");
+const util_1 = require("../util");
+var DataType;
+(function (DataType) {
+ DataType[DataType["Correct"] = 0] = "Correct";
+ DataType[DataType["Wrong"] = 1] = "Wrong";
+})(DataType = exports.DataType || (exports.DataType = {}));
+function getSchemaTypes(schema) {
+ const types = getJSONTypes(schema.type);
+ const hasNull = types.includes("null");
+ if (hasNull) {
+ if (schema.nullable === false)
+ throw new Error("type: null contradicts nullable: false");
+ }
+ else {
+ if (!types.length && schema.nullable !== undefined) {
+ throw new Error('"nullable" cannot be used without "type"');
+ }
+ if (schema.nullable === true)
+ types.push("null");
+ }
+ return types;
+}
+exports.getSchemaTypes = getSchemaTypes;
+function getJSONTypes(ts) {
+ const types = Array.isArray(ts) ? ts : ts ? [ts] : [];
+ if (types.every(rules_1.isJSONType))
+ return types;
+ throw new Error("type must be JSONType or JSONType[]: " + types.join(","));
+}
+exports.getJSONTypes = getJSONTypes;
+function coerceAndCheckDataType(it, types) {
+ const { gen, data, opts } = it;
+ const coerceTo = coerceToTypes(types, opts.coerceTypes);
+ const checkTypes = types.length > 0 &&
+ !(coerceTo.length === 0 && types.length === 1 && (0, applicability_1.schemaHasRulesForType)(it, types[0]));
+ if (checkTypes) {
+ const wrongType = checkDataTypes(types, data, opts.strictNumbers, DataType.Wrong);
+ gen.if(wrongType, () => {
+ if (coerceTo.length)
+ coerceData(it, types, coerceTo);
+ else
+ reportTypeError(it);
+ });
+ }
+ return checkTypes;
+}
+exports.coerceAndCheckDataType = coerceAndCheckDataType;
+const COERCIBLE = new Set(["string", "number", "integer", "boolean", "null"]);
+function coerceToTypes(types, coerceTypes) {
+ return coerceTypes
+ ? types.filter((t) => COERCIBLE.has(t) || (coerceTypes === "array" && t === "array"))
+ : [];
+}
+function coerceData(it, types, coerceTo) {
+ const { gen, data, opts } = it;
+ const dataType = gen.let("dataType", (0, codegen_1._) `typeof ${data}`);
+ const coerced = gen.let("coerced", (0, codegen_1._) `undefined`);
+ if (opts.coerceTypes === "array") {
+ gen.if((0, codegen_1._) `${dataType} == 'object' && Array.isArray(${data}) && ${data}.length == 1`, () => gen
+ .assign(data, (0, codegen_1._) `${data}[0]`)
+ .assign(dataType, (0, codegen_1._) `typeof ${data}`)
+ .if(checkDataTypes(types, data, opts.strictNumbers), () => gen.assign(coerced, data)));
+ }
+ gen.if((0, codegen_1._) `${coerced} !== undefined`);
+ for (const t of coerceTo) {
+ if (COERCIBLE.has(t) || (t === "array" && opts.coerceTypes === "array")) {
+ coerceSpecificType(t);
+ }
+ }
+ gen.else();
+ reportTypeError(it);
+ gen.endIf();
+ gen.if((0, codegen_1._) `${coerced} !== undefined`, () => {
+ gen.assign(data, coerced);
+ assignParentData(it, coerced);
+ });
+ function coerceSpecificType(t) {
+ switch (t) {
+ case "string":
+ gen
+ .elseIf((0, codegen_1._) `${dataType} == "number" || ${dataType} == "boolean"`)
+ .assign(coerced, (0, codegen_1._) `"" + ${data}`)
+ .elseIf((0, codegen_1._) `${data} === null`)
+ .assign(coerced, (0, codegen_1._) `""`);
+ return;
+ case "number":
+ gen
+ .elseIf((0, codegen_1._) `${dataType} == "boolean" || ${data} === null
+ || (${dataType} == "string" && ${data} && ${data} == +${data})`)
+ .assign(coerced, (0, codegen_1._) `+${data}`);
+ return;
+ case "integer":
+ gen
+ .elseIf((0, codegen_1._) `${dataType} === "boolean" || ${data} === null
+ || (${dataType} === "string" && ${data} && ${data} == +${data} && !(${data} % 1))`)
+ .assign(coerced, (0, codegen_1._) `+${data}`);
+ return;
+ case "boolean":
+ gen
+ .elseIf((0, codegen_1._) `${data} === "false" || ${data} === 0 || ${data} === null`)
+ .assign(coerced, false)
+ .elseIf((0, codegen_1._) `${data} === "true" || ${data} === 1`)
+ .assign(coerced, true);
+ return;
+ case "null":
+ gen.elseIf((0, codegen_1._) `${data} === "" || ${data} === 0 || ${data} === false`);
+ gen.assign(coerced, null);
+ return;
+ case "array":
+ gen
+ .elseIf((0, codegen_1._) `${dataType} === "string" || ${dataType} === "number"
+ || ${dataType} === "boolean" || ${data} === null`)
+ .assign(coerced, (0, codegen_1._) `[${data}]`);
+ }
+ }
+}
+function assignParentData({ gen, parentData, parentDataProperty }, expr) {
+ // TODO use gen.property
+ gen.if((0, codegen_1._) `${parentData} !== undefined`, () => gen.assign((0, codegen_1._) `${parentData}[${parentDataProperty}]`, expr));
+}
+function checkDataType(dataType, data, strictNums, correct = DataType.Correct) {
+ const EQ = correct === DataType.Correct ? codegen_1.operators.EQ : codegen_1.operators.NEQ;
+ let cond;
+ switch (dataType) {
+ case "null":
+ return (0, codegen_1._) `${data} ${EQ} null`;
+ case "array":
+ cond = (0, codegen_1._) `Array.isArray(${data})`;
+ break;
+ case "object":
+ cond = (0, codegen_1._) `${data} && typeof ${data} == "object" && !Array.isArray(${data})`;
+ break;
+ case "integer":
+ cond = numCond((0, codegen_1._) `!(${data} % 1) && !isNaN(${data})`);
+ break;
+ case "number":
+ cond = numCond();
+ break;
+ default:
+ return (0, codegen_1._) `typeof ${data} ${EQ} ${dataType}`;
+ }
+ return correct === DataType.Correct ? cond : (0, codegen_1.not)(cond);
+ function numCond(_cond = codegen_1.nil) {
+ return (0, codegen_1.and)((0, codegen_1._) `typeof ${data} == "number"`, _cond, strictNums ? (0, codegen_1._) `isFinite(${data})` : codegen_1.nil);
+ }
+}
+exports.checkDataType = checkDataType;
+function checkDataTypes(dataTypes, data, strictNums, correct) {
+ if (dataTypes.length === 1) {
+ return checkDataType(dataTypes[0], data, strictNums, correct);
+ }
+ let cond;
+ const types = (0, util_1.toHash)(dataTypes);
+ if (types.array && types.object) {
+ const notObj = (0, codegen_1._) `typeof ${data} != "object"`;
+ cond = types.null ? notObj : (0, codegen_1._) `!${data} || ${notObj}`;
+ delete types.null;
+ delete types.array;
+ delete types.object;
+ }
+ else {
+ cond = codegen_1.nil;
+ }
+ if (types.number)
+ delete types.integer;
+ for (const t in types)
+ cond = (0, codegen_1.and)(cond, checkDataType(t, data, strictNums, correct));
+ return cond;
+}
+exports.checkDataTypes = checkDataTypes;
+const typeError = {
+ message: ({ schema }) => `must be ${schema}`,
+ params: ({ schema, schemaValue }) => typeof schema == "string" ? (0, codegen_1._) `{type: ${schema}}` : (0, codegen_1._) `{type: ${schemaValue}}`,
+};
+function reportTypeError(it) {
+ const cxt = getTypeErrorContext(it);
+ (0, errors_1.reportError)(cxt, typeError);
+}
+exports.reportTypeError = reportTypeError;
+function getTypeErrorContext(it) {
+ const { gen, data, schema } = it;
+ const schemaCode = (0, util_1.schemaRefOrVal)(it, schema, "type");
+ return {
+ gen,
+ keyword: "type",
+ data,
+ schema: schema.type,
+ schemaCode,
+ schemaValue: schemaCode,
+ parentSchema: schema,
+ params: {},
+ it,
+ };
+}
+
+},{"../codegen":5,"../errors":7,"../rules":12,"../util":13,"./applicability":14}],17:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.assignDefaults = void 0;
+const codegen_1 = require("../codegen");
+const util_1 = require("../util");
+function assignDefaults(it, ty) {
+ const { properties, items } = it.schema;
+ if (ty === "object" && properties) {
+ for (const key in properties) {
+ assignDefault(it, key, properties[key].default);
+ }
+ }
+ else if (ty === "array" && Array.isArray(items)) {
+ items.forEach((sch, i) => assignDefault(it, i, sch.default));
+ }
+}
+exports.assignDefaults = assignDefaults;
+function assignDefault(it, prop, defaultValue) {
+ const { gen, compositeRule, data, opts } = it;
+ if (defaultValue === undefined)
+ return;
+ const childData = (0, codegen_1._) `${data}${(0, codegen_1.getProperty)(prop)}`;
+ if (compositeRule) {
+ (0, util_1.checkStrictMode)(it, `default is ignored for: ${childData}`);
+ return;
+ }
+ let condition = (0, codegen_1._) `${childData} === undefined`;
+ if (opts.useDefaults === "empty") {
+ condition = (0, codegen_1._) `${condition} || ${childData} === null || ${childData} === ""`;
+ }
+ // `${childData} === undefined` +
+ // (opts.useDefaults === "empty" ? ` || ${childData} === null || ${childData} === ""` : "")
+ gen.if(condition, (0, codegen_1._) `${childData} = ${(0, codegen_1.stringify)(defaultValue)}`);
+}
+
+},{"../codegen":5,"../util":13}],18:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.getData = exports.KeywordCxt = exports.validateFunctionCode = void 0;
+const boolSchema_1 = require("./boolSchema");
+const dataType_1 = require("./dataType");
+const applicability_1 = require("./applicability");
+const dataType_2 = require("./dataType");
+const defaults_1 = require("./defaults");
+const keyword_1 = require("./keyword");
+const subschema_1 = require("./subschema");
+const codegen_1 = require("../codegen");
+const names_1 = require("../names");
+const resolve_1 = require("../resolve");
+const util_1 = require("../util");
+const errors_1 = require("../errors");
+// schema compilation - generates validation function, subschemaCode (below) is used for subschemas
+function validateFunctionCode(it) {
+ if (isSchemaObj(it)) {
+ checkKeywords(it);
+ if (schemaCxtHasRules(it)) {
+ topSchemaObjCode(it);
+ return;
+ }
+ }
+ validateFunction(it, () => (0, boolSchema_1.topBoolOrEmptySchema)(it));
+}
+exports.validateFunctionCode = validateFunctionCode;
+function validateFunction({ gen, validateName, schema, schemaEnv, opts }, body) {
+ if (opts.code.es5) {
+ gen.func(validateName, (0, codegen_1._) `${names_1.default.data}, ${names_1.default.valCxt}`, schemaEnv.$async, () => {
+ gen.code((0, codegen_1._) `"use strict"; ${funcSourceUrl(schema, opts)}`);
+ destructureValCxtES5(gen, opts);
+ gen.code(body);
+ });
+ }
+ else {
+ gen.func(validateName, (0, codegen_1._) `${names_1.default.data}, ${destructureValCxt(opts)}`, schemaEnv.$async, () => gen.code(funcSourceUrl(schema, opts)).code(body));
+ }
+}
+function destructureValCxt(opts) {
+ return (0, codegen_1._) `{${names_1.default.instancePath}="", ${names_1.default.parentData}, ${names_1.default.parentDataProperty}, ${names_1.default.rootData}=${names_1.default.data}${opts.dynamicRef ? (0, codegen_1._) `, ${names_1.default.dynamicAnchors}={}` : codegen_1.nil}}={}`;
+}
+function destructureValCxtES5(gen, opts) {
+ gen.if(names_1.default.valCxt, () => {
+ gen.var(names_1.default.instancePath, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.instancePath}`);
+ gen.var(names_1.default.parentData, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.parentData}`);
+ gen.var(names_1.default.parentDataProperty, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.parentDataProperty}`);
+ gen.var(names_1.default.rootData, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.rootData}`);
+ if (opts.dynamicRef)
+ gen.var(names_1.default.dynamicAnchors, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.dynamicAnchors}`);
+ }, () => {
+ gen.var(names_1.default.instancePath, (0, codegen_1._) `""`);
+ gen.var(names_1.default.parentData, (0, codegen_1._) `undefined`);
+ gen.var(names_1.default.parentDataProperty, (0, codegen_1._) `undefined`);
+ gen.var(names_1.default.rootData, names_1.default.data);
+ if (opts.dynamicRef)
+ gen.var(names_1.default.dynamicAnchors, (0, codegen_1._) `{}`);
+ });
+}
+function topSchemaObjCode(it) {
+ const { schema, opts, gen } = it;
+ validateFunction(it, () => {
+ if (opts.$comment && schema.$comment)
+ commentKeyword(it);
+ checkNoDefault(it);
+ gen.let(names_1.default.vErrors, null);
+ gen.let(names_1.default.errors, 0);
+ if (opts.unevaluated)
+ resetEvaluated(it);
+ typeAndKeywords(it);
+ returnResults(it);
+ });
+ return;
+}
+function resetEvaluated(it) {
+ // TODO maybe some hook to execute it in the end to check whether props/items are Name, as in assignEvaluated
+ const { gen, validateName } = it;
+ it.evaluated = gen.const("evaluated", (0, codegen_1._) `${validateName}.evaluated`);
+ gen.if((0, codegen_1._) `${it.evaluated}.dynamicProps`, () => gen.assign((0, codegen_1._) `${it.evaluated}.props`, (0, codegen_1._) `undefined`));
+ gen.if((0, codegen_1._) `${it.evaluated}.dynamicItems`, () => gen.assign((0, codegen_1._) `${it.evaluated}.items`, (0, codegen_1._) `undefined`));
+}
+function funcSourceUrl(schema, opts) {
+ const schId = typeof schema == "object" && schema[opts.schemaId];
+ return schId && (opts.code.source || opts.code.process) ? (0, codegen_1._) `/*# sourceURL=${schId} */` : codegen_1.nil;
+}
+// schema compilation - this function is used recursively to generate code for sub-schemas
+function subschemaCode(it, valid) {
+ if (isSchemaObj(it)) {
+ checkKeywords(it);
+ if (schemaCxtHasRules(it)) {
+ subSchemaObjCode(it, valid);
+ return;
+ }
+ }
+ (0, boolSchema_1.boolOrEmptySchema)(it, valid);
+}
+function schemaCxtHasRules({ schema, self }) {
+ if (typeof schema == "boolean")
+ return !schema;
+ for (const key in schema)
+ if (self.RULES.all[key])
+ return true;
+ return false;
+}
+function isSchemaObj(it) {
+ return typeof it.schema != "boolean";
+}
+function subSchemaObjCode(it, valid) {
+ const { schema, gen, opts } = it;
+ if (opts.$comment && schema.$comment)
+ commentKeyword(it);
+ updateContext(it);
+ checkAsyncSchema(it);
+ const errsCount = gen.const("_errs", names_1.default.errors);
+ typeAndKeywords(it, errsCount);
+ // TODO var
+ gen.var(valid, (0, codegen_1._) `${errsCount} === ${names_1.default.errors}`);
+}
+function checkKeywords(it) {
+ (0, util_1.checkUnknownRules)(it);
+ checkRefsAndKeywords(it);
+}
+function typeAndKeywords(it, errsCount) {
+ if (it.opts.jtd)
+ return schemaKeywords(it, [], false, errsCount);
+ const types = (0, dataType_1.getSchemaTypes)(it.schema);
+ const checkedTypes = (0, dataType_1.coerceAndCheckDataType)(it, types);
+ schemaKeywords(it, types, !checkedTypes, errsCount);
+}
+function checkRefsAndKeywords(it) {
+ const { schema, errSchemaPath, opts, self } = it;
+ if (schema.$ref && opts.ignoreKeywordsWithRef && (0, util_1.schemaHasRulesButRef)(schema, self.RULES)) {
+ self.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`);
+ }
+}
+function checkNoDefault(it) {
+ const { schema, opts } = it;
+ if (schema.default !== undefined && opts.useDefaults && opts.strictSchema) {
+ (0, util_1.checkStrictMode)(it, "default is ignored in the schema root");
+ }
+}
+function updateContext(it) {
+ const schId = it.schema[it.opts.schemaId];
+ if (schId)
+ it.baseId = (0, resolve_1.resolveUrl)(it.opts.uriResolver, it.baseId, schId);
+}
+function checkAsyncSchema(it) {
+ if (it.schema.$async && !it.schemaEnv.$async)
+ throw new Error("async schema in sync schema");
+}
+function commentKeyword({ gen, schemaEnv, schema, errSchemaPath, opts }) {
+ const msg = schema.$comment;
+ if (opts.$comment === true) {
+ gen.code((0, codegen_1._) `${names_1.default.self}.logger.log(${msg})`);
+ }
+ else if (typeof opts.$comment == "function") {
+ const schemaPath = (0, codegen_1.str) `${errSchemaPath}/$comment`;
+ const rootName = gen.scopeValue("root", { ref: schemaEnv.root });
+ gen.code((0, codegen_1._) `${names_1.default.self}.opts.$comment(${msg}, ${schemaPath}, ${rootName}.schema)`);
+ }
+}
+function returnResults(it) {
+ const { gen, schemaEnv, validateName, ValidationError, opts } = it;
+ if (schemaEnv.$async) {
+ // TODO assign unevaluated
+ gen.if((0, codegen_1._) `${names_1.default.errors} === 0`, () => gen.return(names_1.default.data), () => gen.throw((0, codegen_1._) `new ${ValidationError}(${names_1.default.vErrors})`));
+ }
+ else {
+ gen.assign((0, codegen_1._) `${validateName}.errors`, names_1.default.vErrors);
+ if (opts.unevaluated)
+ assignEvaluated(it);
+ gen.return((0, codegen_1._) `${names_1.default.errors} === 0`);
+ }
+}
+function assignEvaluated({ gen, evaluated, props, items }) {
+ if (props instanceof codegen_1.Name)
+ gen.assign((0, codegen_1._) `${evaluated}.props`, props);
+ if (items instanceof codegen_1.Name)
+ gen.assign((0, codegen_1._) `${evaluated}.items`, items);
+}
+function schemaKeywords(it, types, typeErrors, errsCount) {
+ const { gen, schema, data, allErrors, opts, self } = it;
+ const { RULES } = self;
+ if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES))) {
+ gen.block(() => keywordCode(it, "$ref", RULES.all.$ref.definition)); // TODO typecast
+ return;
+ }
+ if (!opts.jtd)
+ checkStrictTypes(it, types);
+ gen.block(() => {
+ for (const group of RULES.rules)
+ groupKeywords(group);
+ groupKeywords(RULES.post);
+ });
+ function groupKeywords(group) {
+ if (!(0, applicability_1.shouldUseGroup)(schema, group))
+ return;
+ if (group.type) {
+ gen.if((0, dataType_2.checkDataType)(group.type, data, opts.strictNumbers));
+ iterateKeywords(it, group);
+ if (types.length === 1 && types[0] === group.type && typeErrors) {
+ gen.else();
+ (0, dataType_2.reportTypeError)(it);
+ }
+ gen.endIf();
+ }
+ else {
+ iterateKeywords(it, group);
+ }
+ // TODO make it "ok" call?
+ if (!allErrors)
+ gen.if((0, codegen_1._) `${names_1.default.errors} === ${errsCount || 0}`);
+ }
+}
+function iterateKeywords(it, group) {
+ const { gen, schema, opts: { useDefaults }, } = it;
+ if (useDefaults)
+ (0, defaults_1.assignDefaults)(it, group.type);
+ gen.block(() => {
+ for (const rule of group.rules) {
+ if ((0, applicability_1.shouldUseRule)(schema, rule)) {
+ keywordCode(it, rule.keyword, rule.definition, group.type);
+ }
+ }
+ });
+}
+function checkStrictTypes(it, types) {
+ if (it.schemaEnv.meta || !it.opts.strictTypes)
+ return;
+ checkContextTypes(it, types);
+ if (!it.opts.allowUnionTypes)
+ checkMultipleTypes(it, types);
+ checkKeywordTypes(it, it.dataTypes);
+}
+function checkContextTypes(it, types) {
+ if (!types.length)
+ return;
+ if (!it.dataTypes.length) {
+ it.dataTypes = types;
+ return;
+ }
+ types.forEach((t) => {
+ if (!includesType(it.dataTypes, t)) {
+ strictTypesError(it, `type "${t}" not allowed by context "${it.dataTypes.join(",")}"`);
+ }
+ });
+ narrowSchemaTypes(it, types);
+}
+function checkMultipleTypes(it, ts) {
+ if (ts.length > 1 && !(ts.length === 2 && ts.includes("null"))) {
+ strictTypesError(it, "use allowUnionTypes to allow union type keyword");
+ }
+}
+function checkKeywordTypes(it, ts) {
+ const rules = it.self.RULES.all;
+ for (const keyword in rules) {
+ const rule = rules[keyword];
+ if (typeof rule == "object" && (0, applicability_1.shouldUseRule)(it.schema, rule)) {
+ const { type } = rule.definition;
+ if (type.length && !type.some((t) => hasApplicableType(ts, t))) {
+ strictTypesError(it, `missing type "${type.join(",")}" for keyword "${keyword}"`);
+ }
+ }
+ }
+}
+function hasApplicableType(schTs, kwdT) {
+ return schTs.includes(kwdT) || (kwdT === "number" && schTs.includes("integer"));
+}
+function includesType(ts, t) {
+ return ts.includes(t) || (t === "integer" && ts.includes("number"));
+}
+function narrowSchemaTypes(it, withTypes) {
+ const ts = [];
+ for (const t of it.dataTypes) {
+ if (includesType(withTypes, t))
+ ts.push(t);
+ else if (withTypes.includes("integer") && t === "number")
+ ts.push("integer");
+ }
+ it.dataTypes = ts;
+}
+function strictTypesError(it, msg) {
+ const schemaPath = it.schemaEnv.baseId + it.errSchemaPath;
+ msg += ` at "${schemaPath}" (strictTypes)`;
+ (0, util_1.checkStrictMode)(it, msg, it.opts.strictTypes);
+}
+class KeywordCxt {
+ constructor(it, def, keyword) {
+ (0, keyword_1.validateKeywordUsage)(it, def, keyword);
+ this.gen = it.gen;
+ this.allErrors = it.allErrors;
+ this.keyword = keyword;
+ this.data = it.data;
+ this.schema = it.schema[keyword];
+ this.$data = def.$data && it.opts.$data && this.schema && this.schema.$data;
+ this.schemaValue = (0, util_1.schemaRefOrVal)(it, this.schema, keyword, this.$data);
+ this.schemaType = def.schemaType;
+ this.parentSchema = it.schema;
+ this.params = {};
+ this.it = it;
+ this.def = def;
+ if (this.$data) {
+ this.schemaCode = it.gen.const("vSchema", getData(this.$data, it));
+ }
+ else {
+ this.schemaCode = this.schemaValue;
+ if (!(0, keyword_1.validSchemaType)(this.schema, def.schemaType, def.allowUndefined)) {
+ throw new Error(`${keyword} value must be ${JSON.stringify(def.schemaType)}`);
+ }
+ }
+ if ("code" in def ? def.trackErrors : def.errors !== false) {
+ this.errsCount = it.gen.const("_errs", names_1.default.errors);
+ }
+ }
+ result(condition, successAction, failAction) {
+ this.failResult((0, codegen_1.not)(condition), successAction, failAction);
+ }
+ failResult(condition, successAction, failAction) {
+ this.gen.if(condition);
+ if (failAction)
+ failAction();
+ else
+ this.error();
+ if (successAction) {
+ this.gen.else();
+ successAction();
+ if (this.allErrors)
+ this.gen.endIf();
+ }
+ else {
+ if (this.allErrors)
+ this.gen.endIf();
+ else
+ this.gen.else();
+ }
+ }
+ pass(condition, failAction) {
+ this.failResult((0, codegen_1.not)(condition), undefined, failAction);
+ }
+ fail(condition) {
+ if (condition === undefined) {
+ this.error();
+ if (!this.allErrors)
+ this.gen.if(false); // this branch will be removed by gen.optimize
+ return;
+ }
+ this.gen.if(condition);
+ this.error();
+ if (this.allErrors)
+ this.gen.endIf();
+ else
+ this.gen.else();
+ }
+ fail$data(condition) {
+ if (!this.$data)
+ return this.fail(condition);
+ const { schemaCode } = this;
+ this.fail((0, codegen_1._) `${schemaCode} !== undefined && (${(0, codegen_1.or)(this.invalid$data(), condition)})`);
+ }
+ error(append, errorParams, errorPaths) {
+ if (errorParams) {
+ this.setParams(errorParams);
+ this._error(append, errorPaths);
+ this.setParams({});
+ return;
+ }
+ this._error(append, errorPaths);
+ }
+ _error(append, errorPaths) {
+ ;
+ (append ? errors_1.reportExtraError : errors_1.reportError)(this, this.def.error, errorPaths);
+ }
+ $dataError() {
+ (0, errors_1.reportError)(this, this.def.$dataError || errors_1.keyword$DataError);
+ }
+ reset() {
+ if (this.errsCount === undefined)
+ throw new Error('add "trackErrors" to keyword definition');
+ (0, errors_1.resetErrorsCount)(this.gen, this.errsCount);
+ }
+ ok(cond) {
+ if (!this.allErrors)
+ this.gen.if(cond);
+ }
+ setParams(obj, assign) {
+ if (assign)
+ Object.assign(this.params, obj);
+ else
+ this.params = obj;
+ }
+ block$data(valid, codeBlock, $dataValid = codegen_1.nil) {
+ this.gen.block(() => {
+ this.check$data(valid, $dataValid);
+ codeBlock();
+ });
+ }
+ check$data(valid = codegen_1.nil, $dataValid = codegen_1.nil) {
+ if (!this.$data)
+ return;
+ const { gen, schemaCode, schemaType, def } = this;
+ gen.if((0, codegen_1.or)((0, codegen_1._) `${schemaCode} === undefined`, $dataValid));
+ if (valid !== codegen_1.nil)
+ gen.assign(valid, true);
+ if (schemaType.length || def.validateSchema) {
+ gen.elseIf(this.invalid$data());
+ this.$dataError();
+ if (valid !== codegen_1.nil)
+ gen.assign(valid, false);
+ }
+ gen.else();
+ }
+ invalid$data() {
+ const { gen, schemaCode, schemaType, def, it } = this;
+ return (0, codegen_1.or)(wrong$DataType(), invalid$DataSchema());
+ function wrong$DataType() {
+ if (schemaType.length) {
+ /* istanbul ignore if */
+ if (!(schemaCode instanceof codegen_1.Name))
+ throw new Error("ajv implementation error");
+ const st = Array.isArray(schemaType) ? schemaType : [schemaType];
+ return (0, codegen_1._) `${(0, dataType_2.checkDataTypes)(st, schemaCode, it.opts.strictNumbers, dataType_2.DataType.Wrong)}`;
+ }
+ return codegen_1.nil;
+ }
+ function invalid$DataSchema() {
+ if (def.validateSchema) {
+ const validateSchemaRef = gen.scopeValue("validate$data", { ref: def.validateSchema }); // TODO value.code for standalone
+ return (0, codegen_1._) `!${validateSchemaRef}(${schemaCode})`;
+ }
+ return codegen_1.nil;
+ }
+ }
+ subschema(appl, valid) {
+ const subschema = (0, subschema_1.getSubschema)(this.it, appl);
+ (0, subschema_1.extendSubschemaData)(subschema, this.it, appl);
+ (0, subschema_1.extendSubschemaMode)(subschema, appl);
+ const nextContext = { ...this.it, ...subschema, items: undefined, props: undefined };
+ subschemaCode(nextContext, valid);
+ return nextContext;
+ }
+ mergeEvaluated(schemaCxt, toName) {
+ const { it, gen } = this;
+ if (!it.opts.unevaluated)
+ return;
+ if (it.props !== true && schemaCxt.props !== undefined) {
+ it.props = util_1.mergeEvaluated.props(gen, schemaCxt.props, it.props, toName);
+ }
+ if (it.items !== true && schemaCxt.items !== undefined) {
+ it.items = util_1.mergeEvaluated.items(gen, schemaCxt.items, it.items, toName);
+ }
+ }
+ mergeValidEvaluated(schemaCxt, valid) {
+ const { it, gen } = this;
+ if (it.opts.unevaluated && (it.props !== true || it.items !== true)) {
+ gen.if(valid, () => this.mergeEvaluated(schemaCxt, codegen_1.Name));
+ return true;
+ }
+ }
+}
+exports.KeywordCxt = KeywordCxt;
+function keywordCode(it, keyword, def, ruleType) {
+ const cxt = new KeywordCxt(it, def, keyword);
+ if ("code" in def) {
+ def.code(cxt, ruleType);
+ }
+ else if (cxt.$data && def.validate) {
+ (0, keyword_1.funcKeywordCode)(cxt, def);
+ }
+ else if ("macro" in def) {
+ (0, keyword_1.macroKeywordCode)(cxt, def);
+ }
+ else if (def.compile || def.validate) {
+ (0, keyword_1.funcKeywordCode)(cxt, def);
+ }
+}
+const JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
+const RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
+function getData($data, { dataLevel, dataNames, dataPathArr }) {
+ let jsonPointer;
+ let data;
+ if ($data === "")
+ return names_1.default.rootData;
+ if ($data[0] === "/") {
+ if (!JSON_POINTER.test($data))
+ throw new Error(`Invalid JSON-pointer: ${$data}`);
+ jsonPointer = $data;
+ data = names_1.default.rootData;
+ }
+ else {
+ const matches = RELATIVE_JSON_POINTER.exec($data);
+ if (!matches)
+ throw new Error(`Invalid JSON-pointer: ${$data}`);
+ const up = +matches[1];
+ jsonPointer = matches[2];
+ if (jsonPointer === "#") {
+ if (up >= dataLevel)
+ throw new Error(errorMsg("property/index", up));
+ return dataPathArr[dataLevel - up];
+ }
+ if (up > dataLevel)
+ throw new Error(errorMsg("data", up));
+ data = dataNames[dataLevel - up];
+ if (!jsonPointer)
+ return data;
+ }
+ let expr = data;
+ const segments = jsonPointer.split("/");
+ for (const segment of segments) {
+ if (segment) {
+ data = (0, codegen_1._) `${data}${(0, codegen_1.getProperty)((0, util_1.unescapeJsonPointer)(segment))}`;
+ expr = (0, codegen_1._) `${expr} && ${data}`;
+ }
+ }
+ return expr;
+ function errorMsg(pointerType, up) {
+ return `Cannot access ${pointerType} ${up} levels up, current level is ${dataLevel}`;
+ }
+}
+exports.getData = getData;
+
+},{"../codegen":5,"../errors":7,"../names":9,"../resolve":11,"../util":13,"./applicability":14,"./boolSchema":15,"./dataType":16,"./defaults":17,"./keyword":19,"./subschema":20}],19:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.validateKeywordUsage = exports.validSchemaType = exports.funcKeywordCode = exports.macroKeywordCode = void 0;
+const codegen_1 = require("../codegen");
+const names_1 = require("../names");
+const code_1 = require("../../vocabularies/code");
+const errors_1 = require("../errors");
+function macroKeywordCode(cxt, def) {
+ const { gen, keyword, schema, parentSchema, it } = cxt;
+ const macroSchema = def.macro.call(it.self, schema, parentSchema, it);
+ const schemaRef = useKeyword(gen, keyword, macroSchema);
+ if (it.opts.validateSchema !== false)
+ it.self.validateSchema(macroSchema, true);
+ const valid = gen.name("valid");
+ cxt.subschema({
+ schema: macroSchema,
+ schemaPath: codegen_1.nil,
+ errSchemaPath: `${it.errSchemaPath}/${keyword}`,
+ topSchemaRef: schemaRef,
+ compositeRule: true,
+ }, valid);
+ cxt.pass(valid, () => cxt.error(true));
+}
+exports.macroKeywordCode = macroKeywordCode;
+function funcKeywordCode(cxt, def) {
+ var _a;
+ const { gen, keyword, schema, parentSchema, $data, it } = cxt;
+ checkAsyncKeyword(it, def);
+ const validate = !$data && def.compile ? def.compile.call(it.self, schema, parentSchema, it) : def.validate;
+ const validateRef = useKeyword(gen, keyword, validate);
+ const valid = gen.let("valid");
+ cxt.block$data(valid, validateKeyword);
+ cxt.ok((_a = def.valid) !== null && _a !== void 0 ? _a : valid);
+ function validateKeyword() {
+ if (def.errors === false) {
+ assignValid();
+ if (def.modifying)
+ modifyData(cxt);
+ reportErrs(() => cxt.error());
+ }
+ else {
+ const ruleErrs = def.async ? validateAsync() : validateSync();
+ if (def.modifying)
+ modifyData(cxt);
+ reportErrs(() => addErrs(cxt, ruleErrs));
+ }
+ }
+ function validateAsync() {
+ const ruleErrs = gen.let("ruleErrs", null);
+ gen.try(() => assignValid((0, codegen_1._) `await `), (e) => gen.assign(valid, false).if((0, codegen_1._) `${e} instanceof ${it.ValidationError}`, () => gen.assign(ruleErrs, (0, codegen_1._) `${e}.errors`), () => gen.throw(e)));
+ return ruleErrs;
+ }
+ function validateSync() {
+ const validateErrs = (0, codegen_1._) `${validateRef}.errors`;
+ gen.assign(validateErrs, null);
+ assignValid(codegen_1.nil);
+ return validateErrs;
+ }
+ function assignValid(_await = def.async ? (0, codegen_1._) `await ` : codegen_1.nil) {
+ const passCxt = it.opts.passContext ? names_1.default.this : names_1.default.self;
+ const passSchema = !(("compile" in def && !$data) || def.schema === false);
+ gen.assign(valid, (0, codegen_1._) `${_await}${(0, code_1.callValidateCode)(cxt, validateRef, passCxt, passSchema)}`, def.modifying);
+ }
+ function reportErrs(errors) {
+ var _a;
+ gen.if((0, codegen_1.not)((_a = def.valid) !== null && _a !== void 0 ? _a : valid), errors);
+ }
+}
+exports.funcKeywordCode = funcKeywordCode;
+function modifyData(cxt) {
+ const { gen, data, it } = cxt;
+ gen.if(it.parentData, () => gen.assign(data, (0, codegen_1._) `${it.parentData}[${it.parentDataProperty}]`));
+}
+function addErrs(cxt, errs) {
+ const { gen } = cxt;
+ gen.if((0, codegen_1._) `Array.isArray(${errs})`, () => {
+ gen
+ .assign(names_1.default.vErrors, (0, codegen_1._) `${names_1.default.vErrors} === null ? ${errs} : ${names_1.default.vErrors}.concat(${errs})`)
+ .assign(names_1.default.errors, (0, codegen_1._) `${names_1.default.vErrors}.length`);
+ (0, errors_1.extendErrors)(cxt);
+ }, () => cxt.error());
+}
+function checkAsyncKeyword({ schemaEnv }, def) {
+ if (def.async && !schemaEnv.$async)
+ throw new Error("async keyword in sync schema");
+}
+function useKeyword(gen, keyword, result) {
+ if (result === undefined)
+ throw new Error(`keyword "${keyword}" failed to compile`);
+ return gen.scopeValue("keyword", typeof result == "function" ? { ref: result } : { ref: result, code: (0, codegen_1.stringify)(result) });
+}
+function validSchemaType(schema, schemaType, allowUndefined = false) {
+ // TODO add tests
+ return (!schemaType.length ||
+ schemaType.some((st) => st === "array"
+ ? Array.isArray(schema)
+ : st === "object"
+ ? schema && typeof schema == "object" && !Array.isArray(schema)
+ : typeof schema == st || (allowUndefined && typeof schema == "undefined")));
+}
+exports.validSchemaType = validSchemaType;
+function validateKeywordUsage({ schema, opts, self, errSchemaPath }, def, keyword) {
+ /* istanbul ignore if */
+ if (Array.isArray(def.keyword) ? !def.keyword.includes(keyword) : def.keyword !== keyword) {
+ throw new Error("ajv implementation error");
+ }
+ const deps = def.dependencies;
+ if (deps === null || deps === void 0 ? void 0 : deps.some((kwd) => !Object.prototype.hasOwnProperty.call(schema, kwd))) {
+ throw new Error(`parent schema must have dependencies of ${keyword}: ${deps.join(",")}`);
+ }
+ if (def.validateSchema) {
+ const valid = def.validateSchema(schema[keyword]);
+ if (!valid) {
+ const msg = `keyword "${keyword}" value is invalid at path "${errSchemaPath}": ` +
+ self.errorsText(def.validateSchema.errors);
+ if (opts.validateSchema === "log")
+ self.logger.error(msg);
+ else
+ throw new Error(msg);
+ }
+ }
+}
+exports.validateKeywordUsage = validateKeywordUsage;
+
+},{"../../vocabularies/code":53,"../codegen":5,"../errors":7,"../names":9}],20:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.extendSubschemaMode = exports.extendSubschemaData = exports.getSubschema = void 0;
+const codegen_1 = require("../codegen");
+const util_1 = require("../util");
+function getSubschema(it, { keyword, schemaProp, schema, schemaPath, errSchemaPath, topSchemaRef }) {
+ if (keyword !== undefined && schema !== undefined) {
+ throw new Error('both "keyword" and "schema" passed, only one allowed');
+ }
+ if (keyword !== undefined) {
+ const sch = it.schema[keyword];
+ return schemaProp === undefined
+ ? {
+ schema: sch,
+ schemaPath: (0, codegen_1._) `${it.schemaPath}${(0, codegen_1.getProperty)(keyword)}`,
+ errSchemaPath: `${it.errSchemaPath}/${keyword}`,
+ }
+ : {
+ schema: sch[schemaProp],
+ schemaPath: (0, codegen_1._) `${it.schemaPath}${(0, codegen_1.getProperty)(keyword)}${(0, codegen_1.getProperty)(schemaProp)}`,
+ errSchemaPath: `${it.errSchemaPath}/${keyword}/${(0, util_1.escapeFragment)(schemaProp)}`,
+ };
+ }
+ if (schema !== undefined) {
+ if (schemaPath === undefined || errSchemaPath === undefined || topSchemaRef === undefined) {
+ throw new Error('"schemaPath", "errSchemaPath" and "topSchemaRef" are required with "schema"');
+ }
+ return {
+ schema,
+ schemaPath,
+ topSchemaRef,
+ errSchemaPath,
+ };
+ }
+ throw new Error('either "keyword" or "schema" must be passed');
+}
+exports.getSubschema = getSubschema;
+function extendSubschemaData(subschema, it, { dataProp, dataPropType: dpType, data, dataTypes, propertyName }) {
+ if (data !== undefined && dataProp !== undefined) {
+ throw new Error('both "data" and "dataProp" passed, only one allowed');
+ }
+ const { gen } = it;
+ if (dataProp !== undefined) {
+ const { errorPath, dataPathArr, opts } = it;
+ const nextData = gen.let("data", (0, codegen_1._) `${it.data}${(0, codegen_1.getProperty)(dataProp)}`, true);
+ dataContextProps(nextData);
+ subschema.errorPath = (0, codegen_1.str) `${errorPath}${(0, util_1.getErrorPath)(dataProp, dpType, opts.jsPropertySyntax)}`;
+ subschema.parentDataProperty = (0, codegen_1._) `${dataProp}`;
+ subschema.dataPathArr = [...dataPathArr, subschema.parentDataProperty];
+ }
+ if (data !== undefined) {
+ const nextData = data instanceof codegen_1.Name ? data : gen.let("data", data, true); // replaceable if used once?
+ dataContextProps(nextData);
+ if (propertyName !== undefined)
+ subschema.propertyName = propertyName;
+ // TODO something is possibly wrong here with not changing parentDataProperty and not appending dataPathArr
+ }
+ if (dataTypes)
+ subschema.dataTypes = dataTypes;
+ function dataContextProps(_nextData) {
+ subschema.data = _nextData;
+ subschema.dataLevel = it.dataLevel + 1;
+ subschema.dataTypes = [];
+ it.definedProperties = new Set();
+ subschema.parentData = it.data;
+ subschema.dataNames = [...it.dataNames, _nextData];
+ }
+}
+exports.extendSubschemaData = extendSubschemaData;
+function extendSubschemaMode(subschema, { jtdDiscriminator, jtdMetadata, compositeRule, createErrors, allErrors }) {
+ if (compositeRule !== undefined)
+ subschema.compositeRule = compositeRule;
+ if (createErrors !== undefined)
+ subschema.createErrors = createErrors;
+ if (allErrors !== undefined)
+ subschema.allErrors = allErrors;
+ subschema.jtdDiscriminator = jtdDiscriminator; // not inherited
+ subschema.jtdMetadata = jtdMetadata; // not inherited
+}
+exports.extendSubschemaMode = extendSubschemaMode;
+
+},{"../codegen":5,"../util":13}],21:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.CodeGen = exports.Name = exports.nil = exports.stringify = exports.str = exports._ = exports.KeywordCxt = void 0;
+var validate_1 = require("./compile/validate");
+Object.defineProperty(exports, "KeywordCxt", { enumerable: true, get: function () { return validate_1.KeywordCxt; } });
+var codegen_1 = require("./compile/codegen");
+Object.defineProperty(exports, "_", { enumerable: true, get: function () { return codegen_1._; } });
+Object.defineProperty(exports, "str", { enumerable: true, get: function () { return codegen_1.str; } });
+Object.defineProperty(exports, "stringify", { enumerable: true, get: function () { return codegen_1.stringify; } });
+Object.defineProperty(exports, "nil", { enumerable: true, get: function () { return codegen_1.nil; } });
+Object.defineProperty(exports, "Name", { enumerable: true, get: function () { return codegen_1.Name; } });
+Object.defineProperty(exports, "CodeGen", { enumerable: true, get: function () { return codegen_1.CodeGen; } });
+const validation_error_1 = require("./runtime/validation_error");
+const ref_error_1 = require("./compile/ref_error");
+const rules_1 = require("./compile/rules");
+const compile_1 = require("./compile");
+const codegen_2 = require("./compile/codegen");
+const resolve_1 = require("./compile/resolve");
+const dataType_1 = require("./compile/validate/dataType");
+const util_1 = require("./compile/util");
+const $dataRefSchema = require("./refs/data.json");
+const uri_1 = require("./runtime/uri");
+const defaultRegExp = (str, flags) => new RegExp(str, flags);
+defaultRegExp.code = "new RegExp";
+const META_IGNORE_OPTIONS = ["removeAdditional", "useDefaults", "coerceTypes"];
+const EXT_SCOPE_NAMES = new Set([
+ "validate",
+ "serialize",
+ "parse",
+ "wrapper",
+ "root",
+ "schema",
+ "keyword",
+ "pattern",
+ "formats",
+ "validate$data",
+ "func",
+ "obj",
+ "Error",
+]);
+const removedOptions = {
+ errorDataPath: "",
+ format: "`validateFormats: false` can be used instead.",
+ nullable: '"nullable" keyword is supported by default.',
+ jsonPointers: "Deprecated jsPropertySyntax can be used instead.",
+ extendRefs: "Deprecated ignoreKeywordsWithRef can be used instead.",
+ missingRefs: "Pass empty schema with $id that should be ignored to ajv.addSchema.",
+ processCode: "Use option `code: {process: (code, schemaEnv: object) => string}`",
+ sourceCode: "Use option `code: {source: true}`",
+ strictDefaults: "It is default now, see option `strict`.",
+ strictKeywords: "It is default now, see option `strict`.",
+ uniqueItems: '"uniqueItems" keyword is always validated.',
+ unknownFormats: "Disable strict mode or pass `true` to `ajv.addFormat` (or `formats` option).",
+ cache: "Map is used as cache, schema object as key.",
+ serialize: "Map is used as cache, schema object as key.",
+ ajvErrors: "It is default now.",
+};
+const deprecatedOptions = {
+ ignoreKeywordsWithRef: "",
+ jsPropertySyntax: "",
+ unicode: '"minLength"/"maxLength" account for unicode characters by default.',
+};
+const MAX_EXPRESSION = 200;
+// eslint-disable-next-line complexity
+function requiredOptions(o) {
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
+ const s = o.strict;
+ const _optz = (_a = o.code) === null || _a === void 0 ? void 0 : _a.optimize;
+ const optimize = _optz === true || _optz === undefined ? 1 : _optz || 0;
+ const regExp = (_c = (_b = o.code) === null || _b === void 0 ? void 0 : _b.regExp) !== null && _c !== void 0 ? _c : defaultRegExp;
+ const uriResolver = (_d = o.uriResolver) !== null && _d !== void 0 ? _d : uri_1.default;
+ return {
+ strictSchema: (_f = (_e = o.strictSchema) !== null && _e !== void 0 ? _e : s) !== null && _f !== void 0 ? _f : true,
+ strictNumbers: (_h = (_g = o.strictNumbers) !== null && _g !== void 0 ? _g : s) !== null && _h !== void 0 ? _h : true,
+ strictTypes: (_k = (_j = o.strictTypes) !== null && _j !== void 0 ? _j : s) !== null && _k !== void 0 ? _k : "log",
+ strictTuples: (_m = (_l = o.strictTuples) !== null && _l !== void 0 ? _l : s) !== null && _m !== void 0 ? _m : "log",
+ strictRequired: (_p = (_o = o.strictRequired) !== null && _o !== void 0 ? _o : s) !== null && _p !== void 0 ? _p : false,
+ code: o.code ? { ...o.code, optimize, regExp } : { optimize, regExp },
+ loopRequired: (_q = o.loopRequired) !== null && _q !== void 0 ? _q : MAX_EXPRESSION,
+ loopEnum: (_r = o.loopEnum) !== null && _r !== void 0 ? _r : MAX_EXPRESSION,
+ meta: (_s = o.meta) !== null && _s !== void 0 ? _s : true,
+ messages: (_t = o.messages) !== null && _t !== void 0 ? _t : true,
+ inlineRefs: (_u = o.inlineRefs) !== null && _u !== void 0 ? _u : true,
+ schemaId: (_v = o.schemaId) !== null && _v !== void 0 ? _v : "$id",
+ addUsedSchema: (_w = o.addUsedSchema) !== null && _w !== void 0 ? _w : true,
+ validateSchema: (_x = o.validateSchema) !== null && _x !== void 0 ? _x : true,
+ validateFormats: (_y = o.validateFormats) !== null && _y !== void 0 ? _y : true,
+ unicodeRegExp: (_z = o.unicodeRegExp) !== null && _z !== void 0 ? _z : true,
+ int32range: (_0 = o.int32range) !== null && _0 !== void 0 ? _0 : true,
+ uriResolver: uriResolver,
+ };
+}
+class Ajv {
+ constructor(opts = {}) {
+ this.schemas = {};
+ this.refs = {};
+ this.formats = {};
+ this._compilations = new Set();
+ this._loading = {};
+ this._cache = new Map();
+ opts = this.opts = { ...opts, ...requiredOptions(opts) };
+ const { es5, lines } = this.opts.code;
+ this.scope = new codegen_2.ValueScope({ scope: {}, prefixes: EXT_SCOPE_NAMES, es5, lines });
+ this.logger = getLogger(opts.logger);
+ const formatOpt = opts.validateFormats;
+ opts.validateFormats = false;
+ this.RULES = (0, rules_1.getRules)();
+ checkOptions.call(this, removedOptions, opts, "NOT SUPPORTED");
+ checkOptions.call(this, deprecatedOptions, opts, "DEPRECATED", "warn");
+ this._metaOpts = getMetaSchemaOptions.call(this);
+ if (opts.formats)
+ addInitialFormats.call(this);
+ this._addVocabularies();
+ this._addDefaultMetaSchema();
+ if (opts.keywords)
+ addInitialKeywords.call(this, opts.keywords);
+ if (typeof opts.meta == "object")
+ this.addMetaSchema(opts.meta);
+ addInitialSchemas.call(this);
+ opts.validateFormats = formatOpt;
+ }
+ _addVocabularies() {
+ this.addKeyword("$async");
+ }
+ _addDefaultMetaSchema() {
+ const { $data, meta, schemaId } = this.opts;
+ let _dataRefSchema = $dataRefSchema;
+ if (schemaId === "id") {
+ _dataRefSchema = { ...$dataRefSchema };
+ _dataRefSchema.id = _dataRefSchema.$id;
+ delete _dataRefSchema.$id;
+ }
+ if (meta && $data)
+ this.addMetaSchema(_dataRefSchema, _dataRefSchema[schemaId], false);
+ }
+ defaultMeta() {
+ const { meta, schemaId } = this.opts;
+ return (this.opts.defaultMeta = typeof meta == "object" ? meta[schemaId] || meta : undefined);
+ }
+ validate(schemaKeyRef, // key, ref or schema object
+ data // to be validated
+ ) {
+ let v;
+ if (typeof schemaKeyRef == "string") {
+ v = this.getSchema(schemaKeyRef);
+ if (!v)
+ throw new Error(`no schema with key or ref "${schemaKeyRef}"`);
+ }
+ else {
+ v = this.compile(schemaKeyRef);
+ }
+ const valid = v(data);
+ if (!("$async" in v))
+ this.errors = v.errors;
+ return valid;
+ }
+ compile(schema, _meta) {
+ const sch = this._addSchema(schema, _meta);
+ return (sch.validate || this._compileSchemaEnv(sch));
+ }
+ compileAsync(schema, meta) {
+ if (typeof this.opts.loadSchema != "function") {
+ throw new Error("options.loadSchema should be a function");
+ }
+ const { loadSchema } = this.opts;
+ return runCompileAsync.call(this, schema, meta);
+ async function runCompileAsync(_schema, _meta) {
+ await loadMetaSchema.call(this, _schema.$schema);
+ const sch = this._addSchema(_schema, _meta);
+ return sch.validate || _compileAsync.call(this, sch);
+ }
+ async function loadMetaSchema($ref) {
+ if ($ref && !this.getSchema($ref)) {
+ await runCompileAsync.call(this, { $ref }, true);
+ }
+ }
+ async function _compileAsync(sch) {
+ try {
+ return this._compileSchemaEnv(sch);
+ }
+ catch (e) {
+ if (!(e instanceof ref_error_1.default))
+ throw e;
+ checkLoaded.call(this, e);
+ await loadMissingSchema.call(this, e.missingSchema);
+ return _compileAsync.call(this, sch);
+ }
+ }
+ function checkLoaded({ missingSchema: ref, missingRef }) {
+ if (this.refs[ref]) {
+ throw new Error(`AnySchema ${ref} is loaded but ${missingRef} cannot be resolved`);
+ }
+ }
+ async function loadMissingSchema(ref) {
+ const _schema = await _loadSchema.call(this, ref);
+ if (!this.refs[ref])
+ await loadMetaSchema.call(this, _schema.$schema);
+ if (!this.refs[ref])
+ this.addSchema(_schema, ref, meta);
+ }
+ async function _loadSchema(ref) {
+ const p = this._loading[ref];
+ if (p)
+ return p;
+ try {
+ return await (this._loading[ref] = loadSchema(ref));
+ }
+ finally {
+ delete this._loading[ref];
+ }
+ }
+ }
+ // Adds schema to the instance
+ addSchema(schema, // If array is passed, `key` will be ignored
+ key, // Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
+ _meta, // true if schema is a meta-schema. Used internally, addMetaSchema should be used instead.
+ _validateSchema = this.opts.validateSchema // false to skip schema validation. Used internally, option validateSchema should be used instead.
+ ) {
+ if (Array.isArray(schema)) {
+ for (const sch of schema)
+ this.addSchema(sch, undefined, _meta, _validateSchema);
+ return this;
+ }
+ let id;
+ if (typeof schema === "object") {
+ const { schemaId } = this.opts;
+ id = schema[schemaId];
+ if (id !== undefined && typeof id != "string") {
+ throw new Error(`schema ${schemaId} must be string`);
+ }
+ }
+ key = (0, resolve_1.normalizeId)(key || id);
+ this._checkUnique(key);
+ this.schemas[key] = this._addSchema(schema, _meta, key, _validateSchema, true);
+ return this;
+ }
+ // Add schema that will be used to validate other schemas
+ // options in META_IGNORE_OPTIONS are alway set to false
+ addMetaSchema(schema, key, // schema key
+ _validateSchema = this.opts.validateSchema // false to skip schema validation, can be used to override validateSchema option for meta-schema
+ ) {
+ this.addSchema(schema, key, true, _validateSchema);
+ return this;
+ }
+ // Validate schema against its meta-schema
+ validateSchema(schema, throwOrLogError) {
+ if (typeof schema == "boolean")
+ return true;
+ let $schema;
+ $schema = schema.$schema;
+ if ($schema !== undefined && typeof $schema != "string") {
+ throw new Error("$schema must be a string");
+ }
+ $schema = $schema || this.opts.defaultMeta || this.defaultMeta();
+ if (!$schema) {
+ this.logger.warn("meta-schema not available");
+ this.errors = null;
+ return true;
+ }
+ const valid = this.validate($schema, schema);
+ if (!valid && throwOrLogError) {
+ const message = "schema is invalid: " + this.errorsText();
+ if (this.opts.validateSchema === "log")
+ this.logger.error(message);
+ else
+ throw new Error(message);
+ }
+ return valid;
+ }
+ // Get compiled schema by `key` or `ref`.
+ // (`key` that was passed to `addSchema` or full schema reference - `schema.$id` or resolved id)
+ getSchema(keyRef) {
+ let sch;
+ while (typeof (sch = getSchEnv.call(this, keyRef)) == "string")
+ keyRef = sch;
+ if (sch === undefined) {
+ const { schemaId } = this.opts;
+ const root = new compile_1.SchemaEnv({ schema: {}, schemaId });
+ sch = compile_1.resolveSchema.call(this, root, keyRef);
+ if (!sch)
+ return;
+ this.refs[keyRef] = sch;
+ }
+ return (sch.validate || this._compileSchemaEnv(sch));
+ }
+ // Remove cached schema(s).
+ // If no parameter is passed all schemas but meta-schemas are removed.
+ // If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed.
+ // Even if schema is referenced by other schemas it still can be removed as other schemas have local references.
+ removeSchema(schemaKeyRef) {
+ if (schemaKeyRef instanceof RegExp) {
+ this._removeAllSchemas(this.schemas, schemaKeyRef);
+ this._removeAllSchemas(this.refs, schemaKeyRef);
+ return this;
+ }
+ switch (typeof schemaKeyRef) {
+ case "undefined":
+ this._removeAllSchemas(this.schemas);
+ this._removeAllSchemas(this.refs);
+ this._cache.clear();
+ return this;
+ case "string": {
+ const sch = getSchEnv.call(this, schemaKeyRef);
+ if (typeof sch == "object")
+ this._cache.delete(sch.schema);
+ delete this.schemas[schemaKeyRef];
+ delete this.refs[schemaKeyRef];
+ return this;
+ }
+ case "object": {
+ const cacheKey = schemaKeyRef;
+ this._cache.delete(cacheKey);
+ let id = schemaKeyRef[this.opts.schemaId];
+ if (id) {
+ id = (0, resolve_1.normalizeId)(id);
+ delete this.schemas[id];
+ delete this.refs[id];
+ }
+ return this;
+ }
+ default:
+ throw new Error("ajv.removeSchema: invalid parameter");
+ }
+ }
+ // add "vocabulary" - a collection of keywords
+ addVocabulary(definitions) {
+ for (const def of definitions)
+ this.addKeyword(def);
+ return this;
+ }
+ addKeyword(kwdOrDef, def // deprecated
+ ) {
+ let keyword;
+ if (typeof kwdOrDef == "string") {
+ keyword = kwdOrDef;
+ if (typeof def == "object") {
+ this.logger.warn("these parameters are deprecated, see docs for addKeyword");
+ def.keyword = keyword;
+ }
+ }
+ else if (typeof kwdOrDef == "object" && def === undefined) {
+ def = kwdOrDef;
+ keyword = def.keyword;
+ if (Array.isArray(keyword) && !keyword.length) {
+ throw new Error("addKeywords: keyword must be string or non-empty array");
+ }
+ }
+ else {
+ throw new Error("invalid addKeywords parameters");
+ }
+ checkKeyword.call(this, keyword, def);
+ if (!def) {
+ (0, util_1.eachItem)(keyword, (kwd) => addRule.call(this, kwd));
+ return this;
+ }
+ keywordMetaschema.call(this, def);
+ const definition = {
+ ...def,
+ type: (0, dataType_1.getJSONTypes)(def.type),
+ schemaType: (0, dataType_1.getJSONTypes)(def.schemaType),
+ };
+ (0, util_1.eachItem)(keyword, definition.type.length === 0
+ ? (k) => addRule.call(this, k, definition)
+ : (k) => definition.type.forEach((t) => addRule.call(this, k, definition, t)));
+ return this;
+ }
+ getKeyword(keyword) {
+ const rule = this.RULES.all[keyword];
+ return typeof rule == "object" ? rule.definition : !!rule;
+ }
+ // Remove keyword
+ removeKeyword(keyword) {
+ // TODO return type should be Ajv
+ const { RULES } = this;
+ delete RULES.keywords[keyword];
+ delete RULES.all[keyword];
+ for (const group of RULES.rules) {
+ const i = group.rules.findIndex((rule) => rule.keyword === keyword);
+ if (i >= 0)
+ group.rules.splice(i, 1);
+ }
+ return this;
+ }
+ // Add format
+ addFormat(name, format) {
+ if (typeof format == "string")
+ format = new RegExp(format);
+ this.formats[name] = format;
+ return this;
+ }
+ errorsText(errors = this.errors, // optional array of validation errors
+ { separator = ", ", dataVar = "data" } = {} // optional options with properties `separator` and `dataVar`
+ ) {
+ if (!errors || errors.length === 0)
+ return "No errors";
+ return errors
+ .map((e) => `${dataVar}${e.instancePath} ${e.message}`)
+ .reduce((text, msg) => text + separator + msg);
+ }
+ $dataMetaSchema(metaSchema, keywordsJsonPointers) {
+ const rules = this.RULES.all;
+ metaSchema = JSON.parse(JSON.stringify(metaSchema));
+ for (const jsonPointer of keywordsJsonPointers) {
+ const segments = jsonPointer.split("/").slice(1); // first segment is an empty string
+ let keywords = metaSchema;
+ for (const seg of segments)
+ keywords = keywords[seg];
+ for (const key in rules) {
+ const rule = rules[key];
+ if (typeof rule != "object")
+ continue;
+ const { $data } = rule.definition;
+ const schema = keywords[key];
+ if ($data && schema)
+ keywords[key] = schemaOrData(schema);
+ }
+ }
+ return metaSchema;
+ }
+ _removeAllSchemas(schemas, regex) {
+ for (const keyRef in schemas) {
+ const sch = schemas[keyRef];
+ if (!regex || regex.test(keyRef)) {
+ if (typeof sch == "string") {
+ delete schemas[keyRef];
+ }
+ else if (sch && !sch.meta) {
+ this._cache.delete(sch.schema);
+ delete schemas[keyRef];
+ }
+ }
+ }
+ }
+ _addSchema(schema, meta, baseId, validateSchema = this.opts.validateSchema, addSchema = this.opts.addUsedSchema) {
+ let id;
+ const { schemaId } = this.opts;
+ if (typeof schema == "object") {
+ id = schema[schemaId];
+ }
+ else {
+ if (this.opts.jtd)
+ throw new Error("schema must be object");
+ else if (typeof schema != "boolean")
+ throw new Error("schema must be object or boolean");
+ }
+ let sch = this._cache.get(schema);
+ if (sch !== undefined)
+ return sch;
+ baseId = (0, resolve_1.normalizeId)(id || baseId);
+ const localRefs = resolve_1.getSchemaRefs.call(this, schema, baseId);
+ sch = new compile_1.SchemaEnv({ schema, schemaId, meta, baseId, localRefs });
+ this._cache.set(sch.schema, sch);
+ if (addSchema && !baseId.startsWith("#")) {
+ // TODO atm it is allowed to overwrite schemas without id (instead of not adding them)
+ if (baseId)
+ this._checkUnique(baseId);
+ this.refs[baseId] = sch;
+ }
+ if (validateSchema)
+ this.validateSchema(schema, true);
+ return sch;
+ }
+ _checkUnique(id) {
+ if (this.schemas[id] || this.refs[id]) {
+ throw new Error(`schema with key or id "${id}" already exists`);
+ }
+ }
+ _compileSchemaEnv(sch) {
+ if (sch.meta)
+ this._compileMetaSchema(sch);
+ else
+ compile_1.compileSchema.call(this, sch);
+ /* istanbul ignore if */
+ if (!sch.validate)
+ throw new Error("ajv implementation error");
+ return sch.validate;
+ }
+ _compileMetaSchema(sch) {
+ const currentOpts = this.opts;
+ this.opts = this._metaOpts;
+ try {
+ compile_1.compileSchema.call(this, sch);
+ }
+ finally {
+ this.opts = currentOpts;
+ }
+ }
+}
+exports.default = Ajv;
+Ajv.ValidationError = validation_error_1.default;
+Ajv.MissingRefError = ref_error_1.default;
+function checkOptions(checkOpts, options, msg, log = "error") {
+ for (const key in checkOpts) {
+ const opt = key;
+ if (opt in options)
+ this.logger[log](`${msg}: option ${key}. ${checkOpts[opt]}`);
+ }
+}
+function getSchEnv(keyRef) {
+ keyRef = (0, resolve_1.normalizeId)(keyRef); // TODO tests fail without this line
+ return this.schemas[keyRef] || this.refs[keyRef];
+}
+function addInitialSchemas() {
+ const optsSchemas = this.opts.schemas;
+ if (!optsSchemas)
+ return;
+ if (Array.isArray(optsSchemas))
+ this.addSchema(optsSchemas);
+ else
+ for (const key in optsSchemas)
+ this.addSchema(optsSchemas[key], key);
+}
+function addInitialFormats() {
+ for (const name in this.opts.formats) {
+ const format = this.opts.formats[name];
+ if (format)
+ this.addFormat(name, format);
+ }
+}
+function addInitialKeywords(defs) {
+ if (Array.isArray(defs)) {
+ this.addVocabulary(defs);
+ return;
+ }
+ this.logger.warn("keywords option as map is deprecated, pass array");
+ for (const keyword in defs) {
+ const def = defs[keyword];
+ if (!def.keyword)
+ def.keyword = keyword;
+ this.addKeyword(def);
+ }
+}
+function getMetaSchemaOptions() {
+ const metaOpts = { ...this.opts };
+ for (const opt of META_IGNORE_OPTIONS)
+ delete metaOpts[opt];
+ return metaOpts;
+}
+const noLogs = { log() { }, warn() { }, error() { } };
+function getLogger(logger) {
+ if (logger === false)
+ return noLogs;
+ if (logger === undefined)
+ return console;
+ if (logger.log && logger.warn && logger.error)
+ return logger;
+ throw new Error("logger must implement log, warn and error methods");
+}
+const KEYWORD_NAME = /^[a-z_$][a-z0-9_$:-]*$/i;
+function checkKeyword(keyword, def) {
+ const { RULES } = this;
+ (0, util_1.eachItem)(keyword, (kwd) => {
+ if (RULES.keywords[kwd])
+ throw new Error(`Keyword ${kwd} is already defined`);
+ if (!KEYWORD_NAME.test(kwd))
+ throw new Error(`Keyword ${kwd} has invalid name`);
+ });
+ if (!def)
+ return;
+ if (def.$data && !("code" in def || "validate" in def)) {
+ throw new Error('$data keyword must have "code" or "validate" function');
+ }
+}
+function addRule(keyword, definition, dataType) {
+ var _a;
+ const post = definition === null || definition === void 0 ? void 0 : definition.post;
+ if (dataType && post)
+ throw new Error('keyword with "post" flag cannot have "type"');
+ const { RULES } = this;
+ let ruleGroup = post ? RULES.post : RULES.rules.find(({ type: t }) => t === dataType);
+ if (!ruleGroup) {
+ ruleGroup = { type: dataType, rules: [] };
+ RULES.rules.push(ruleGroup);
+ }
+ RULES.keywords[keyword] = true;
+ if (!definition)
+ return;
+ const rule = {
+ keyword,
+ definition: {
+ ...definition,
+ type: (0, dataType_1.getJSONTypes)(definition.type),
+ schemaType: (0, dataType_1.getJSONTypes)(definition.schemaType),
+ },
+ };
+ if (definition.before)
+ addBeforeRule.call(this, ruleGroup, rule, definition.before);
+ else
+ ruleGroup.rules.push(rule);
+ RULES.all[keyword] = rule;
+ (_a = definition.implements) === null || _a === void 0 ? void 0 : _a.forEach((kwd) => this.addKeyword(kwd));
+}
+function addBeforeRule(ruleGroup, rule, before) {
+ const i = ruleGroup.rules.findIndex((_rule) => _rule.keyword === before);
+ if (i >= 0) {
+ ruleGroup.rules.splice(i, 0, rule);
+ }
+ else {
+ ruleGroup.rules.push(rule);
+ this.logger.warn(`rule ${before} is not defined`);
+ }
+}
+function keywordMetaschema(def) {
+ let { metaSchema } = def;
+ if (metaSchema === undefined)
+ return;
+ if (def.$data && this.opts.$data)
+ metaSchema = schemaOrData(metaSchema);
+ def.validateSchema = this.compile(metaSchema, true);
+}
+const $dataRef = {
+ $ref: "https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#",
+};
+function schemaOrData(schema) {
+ return { anyOf: [schema, $dataRef] };
+}
+
+},{"./compile":8,"./compile/codegen":5,"./compile/ref_error":10,"./compile/resolve":11,"./compile/rules":12,"./compile/util":13,"./compile/validate":18,"./compile/validate/dataType":16,"./refs/data.json":22,"./runtime/uri":33,"./runtime/validation_error":34}],22:[function(require,module,exports){
+module.exports={
+ "$id": "https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#",
+ "description": "Meta-schema for $data reference (JSON AnySchema extension proposal)",
+ "type": "object",
+ "required": ["$data"],
+ "properties": {
+ "$data": {
+ "type": "string",
+ "anyOf": [{"format": "relative-json-pointer"}, {"format": "json-pointer"}]
+ }
+ },
+ "additionalProperties": false
+}
+
+},{}],23:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const metaSchema = require("./schema.json");
+const applicator = require("./meta/applicator.json");
+const content = require("./meta/content.json");
+const core = require("./meta/core.json");
+const format = require("./meta/format.json");
+const metadata = require("./meta/meta-data.json");
+const validation = require("./meta/validation.json");
+const META_SUPPORT_DATA = ["/properties"];
+function addMetaSchema2019($data) {
+ ;
+ [
+ metaSchema,
+ applicator,
+ content,
+ core,
+ with$data(this, format),
+ metadata,
+ with$data(this, validation),
+ ].forEach((sch) => this.addMetaSchema(sch, undefined, false));
+ return this;
+ function with$data(ajv, sch) {
+ return $data ? ajv.$dataMetaSchema(sch, META_SUPPORT_DATA) : sch;
+ }
+}
+exports.default = addMetaSchema2019;
+
+},{"./meta/applicator.json":24,"./meta/content.json":25,"./meta/core.json":26,"./meta/format.json":27,"./meta/meta-data.json":28,"./meta/validation.json":29,"./schema.json":30}],24:[function(require,module,exports){
+module.exports={
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "https://json-schema.org/draft/2019-09/meta/applicator",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2019-09/vocab/applicator": true
+ },
+ "$recursiveAnchor": true,
+
+ "title": "Applicator vocabulary meta-schema",
+ "type": ["object", "boolean"],
+ "properties": {
+ "additionalItems": {"$recursiveRef": "#"},
+ "unevaluatedItems": {"$recursiveRef": "#"},
+ "items": {
+ "anyOf": [{"$recursiveRef": "#"}, {"$ref": "#/$defs/schemaArray"}]
+ },
+ "contains": {"$recursiveRef": "#"},
+ "additionalProperties": {"$recursiveRef": "#"},
+ "unevaluatedProperties": {"$recursiveRef": "#"},
+ "properties": {
+ "type": "object",
+ "additionalProperties": {"$recursiveRef": "#"},
+ "default": {}
+ },
+ "patternProperties": {
+ "type": "object",
+ "additionalProperties": {"$recursiveRef": "#"},
+ "propertyNames": {"format": "regex"},
+ "default": {}
+ },
+ "dependentSchemas": {
+ "type": "object",
+ "additionalProperties": {
+ "$recursiveRef": "#"
+ }
+ },
+ "propertyNames": {"$recursiveRef": "#"},
+ "if": {"$recursiveRef": "#"},
+ "then": {"$recursiveRef": "#"},
+ "else": {"$recursiveRef": "#"},
+ "allOf": {"$ref": "#/$defs/schemaArray"},
+ "anyOf": {"$ref": "#/$defs/schemaArray"},
+ "oneOf": {"$ref": "#/$defs/schemaArray"},
+ "not": {"$recursiveRef": "#"}
+ },
+ "$defs": {
+ "schemaArray": {
+ "type": "array",
+ "minItems": 1,
+ "items": {"$recursiveRef": "#"}
+ }
+ }
+}
+
+},{}],25:[function(require,module,exports){
+module.exports={
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "https://json-schema.org/draft/2019-09/meta/content",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2019-09/vocab/content": true
+ },
+ "$recursiveAnchor": true,
+
+ "title": "Content vocabulary meta-schema",
+
+ "type": ["object", "boolean"],
+ "properties": {
+ "contentMediaType": {"type": "string"},
+ "contentEncoding": {"type": "string"},
+ "contentSchema": {"$recursiveRef": "#"}
+ }
+}
+
+},{}],26:[function(require,module,exports){
+module.exports={
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "https://json-schema.org/draft/2019-09/meta/core",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2019-09/vocab/core": true
+ },
+ "$recursiveAnchor": true,
+
+ "title": "Core vocabulary meta-schema",
+ "type": ["object", "boolean"],
+ "properties": {
+ "$id": {
+ "type": "string",
+ "format": "uri-reference",
+ "$comment": "Non-empty fragments not allowed.",
+ "pattern": "^[^#]*#?$"
+ },
+ "$schema": {
+ "type": "string",
+ "format": "uri"
+ },
+ "$anchor": {
+ "type": "string",
+ "pattern": "^[A-Za-z][-A-Za-z0-9.:_]*$"
+ },
+ "$ref": {
+ "type": "string",
+ "format": "uri-reference"
+ },
+ "$recursiveRef": {
+ "type": "string",
+ "format": "uri-reference"
+ },
+ "$recursiveAnchor": {
+ "type": "boolean",
+ "default": false
+ },
+ "$vocabulary": {
+ "type": "object",
+ "propertyNames": {
+ "type": "string",
+ "format": "uri"
+ },
+ "additionalProperties": {
+ "type": "boolean"
+ }
+ },
+ "$comment": {
+ "type": "string"
+ },
+ "$defs": {
+ "type": "object",
+ "additionalProperties": {"$recursiveRef": "#"},
+ "default": {}
+ }
+ }
+}
+
+},{}],27:[function(require,module,exports){
+module.exports={
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "https://json-schema.org/draft/2019-09/meta/format",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2019-09/vocab/format": true
+ },
+ "$recursiveAnchor": true,
+
+ "title": "Format vocabulary meta-schema",
+ "type": ["object", "boolean"],
+ "properties": {
+ "format": {"type": "string"}
+ }
+}
+
+},{}],28:[function(require,module,exports){
+module.exports={
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "https://json-schema.org/draft/2019-09/meta/meta-data",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2019-09/vocab/meta-data": true
+ },
+ "$recursiveAnchor": true,
+
+ "title": "Meta-data vocabulary meta-schema",
+
+ "type": ["object", "boolean"],
+ "properties": {
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": true,
+ "deprecated": {
+ "type": "boolean",
+ "default": false
+ },
+ "readOnly": {
+ "type": "boolean",
+ "default": false
+ },
+ "writeOnly": {
+ "type": "boolean",
+ "default": false
+ },
+ "examples": {
+ "type": "array",
+ "items": true
+ }
+ }
+}
+
+},{}],29:[function(require,module,exports){
+module.exports={
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "https://json-schema.org/draft/2019-09/meta/validation",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2019-09/vocab/validation": true
+ },
+ "$recursiveAnchor": true,
+
+ "title": "Validation vocabulary meta-schema",
+ "type": ["object", "boolean"],
+ "properties": {
+ "multipleOf": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "maximum": {
+ "type": "number"
+ },
+ "exclusiveMaximum": {
+ "type": "number"
+ },
+ "minimum": {
+ "type": "number"
+ },
+ "exclusiveMinimum": {
+ "type": "number"
+ },
+ "maxLength": {"$ref": "#/$defs/nonNegativeInteger"},
+ "minLength": {"$ref": "#/$defs/nonNegativeIntegerDefault0"},
+ "pattern": {
+ "type": "string",
+ "format": "regex"
+ },
+ "maxItems": {"$ref": "#/$defs/nonNegativeInteger"},
+ "minItems": {"$ref": "#/$defs/nonNegativeIntegerDefault0"},
+ "uniqueItems": {
+ "type": "boolean",
+ "default": false
+ },
+ "maxContains": {"$ref": "#/$defs/nonNegativeInteger"},
+ "minContains": {
+ "$ref": "#/$defs/nonNegativeInteger",
+ "default": 1
+ },
+ "maxProperties": {"$ref": "#/$defs/nonNegativeInteger"},
+ "minProperties": {"$ref": "#/$defs/nonNegativeIntegerDefault0"},
+ "required": {"$ref": "#/$defs/stringArray"},
+ "dependentRequired": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/stringArray"
+ }
+ },
+ "const": true,
+ "enum": {
+ "type": "array",
+ "items": true
+ },
+ "type": {
+ "anyOf": [
+ {"$ref": "#/$defs/simpleTypes"},
+ {
+ "type": "array",
+ "items": {"$ref": "#/$defs/simpleTypes"},
+ "minItems": 1,
+ "uniqueItems": true
+ }
+ ]
+ }
+ },
+ "$defs": {
+ "nonNegativeInteger": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "nonNegativeIntegerDefault0": {
+ "$ref": "#/$defs/nonNegativeInteger",
+ "default": 0
+ },
+ "simpleTypes": {
+ "enum": ["array", "boolean", "integer", "null", "number", "object", "string"]
+ },
+ "stringArray": {
+ "type": "array",
+ "items": {"type": "string"},
+ "uniqueItems": true,
+ "default": []
+ }
+ }
+}
+
+},{}],30:[function(require,module,exports){
+module.exports={
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "https://json-schema.org/draft/2019-09/schema",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2019-09/vocab/core": true,
+ "https://json-schema.org/draft/2019-09/vocab/applicator": true,
+ "https://json-schema.org/draft/2019-09/vocab/validation": true,
+ "https://json-schema.org/draft/2019-09/vocab/meta-data": true,
+ "https://json-schema.org/draft/2019-09/vocab/format": false,
+ "https://json-schema.org/draft/2019-09/vocab/content": true
+ },
+ "$recursiveAnchor": true,
+
+ "title": "Core and Validation specifications meta-schema",
+ "allOf": [
+ {"$ref": "meta/core"},
+ {"$ref": "meta/applicator"},
+ {"$ref": "meta/validation"},
+ {"$ref": "meta/meta-data"},
+ {"$ref": "meta/format"},
+ {"$ref": "meta/content"}
+ ],
+ "type": ["object", "boolean"],
+ "properties": {
+ "definitions": {
+ "$comment": "While no longer an official keyword as it is replaced by $defs, this keyword is retained in the meta-schema to prevent incompatible extensions as it remains in common use.",
+ "type": "object",
+ "additionalProperties": {"$recursiveRef": "#"},
+ "default": {}
+ },
+ "dependencies": {
+ "$comment": "\"dependencies\" is no longer a keyword, but schema authors should avoid redefining it to facilitate a smooth transition to \"dependentSchemas\" and \"dependentRequired\"",
+ "type": "object",
+ "additionalProperties": {
+ "anyOf": [{"$recursiveRef": "#"}, {"$ref": "meta/validation#/$defs/stringArray"}]
+ }
+ }
+ }
+}
+
+},{}],31:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+// https://github.com/ajv-validator/ajv/issues/889
+const equal = require("fast-deep-equal");
+equal.code = 'require("ajv/dist/runtime/equal").default';
+exports.default = equal;
+
+},{"fast-deep-equal":85}],32:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+// https://mathiasbynens.be/notes/javascript-encoding
+// https://github.com/bestiejs/punycode.js - punycode.ucs2.decode
+function ucs2length(str) {
+ const len = str.length;
+ let length = 0;
+ let pos = 0;
+ let value;
+ while (pos < len) {
+ length++;
+ value = str.charCodeAt(pos++);
+ if (value >= 0xd800 && value <= 0xdbff && pos < len) {
+ // high surrogate, and there is a next character
+ value = str.charCodeAt(pos);
+ if ((value & 0xfc00) === 0xdc00)
+ pos++; // low surrogate
+ }
+ }
+ return length;
+}
+exports.default = ucs2length;
+ucs2length.code = 'require("ajv/dist/runtime/ucs2length").default';
+
+},{}],33:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const uri = require("uri-js");
+uri.code = 'require("ajv/dist/runtime/uri").default';
+exports.default = uri;
+
+},{"uri-js":87}],34:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+class ValidationError extends Error {
+ constructor(errors) {
+ super("validation failed");
+ this.errors = errors;
+ this.ajv = this.validation = true;
+ }
+}
+exports.default = ValidationError;
+
+},{}],35:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.validateAdditionalItems = void 0;
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const error = {
+ message: ({ params: { len } }) => (0, codegen_1.str) `must NOT have more than ${len} items`,
+ params: ({ params: { len } }) => (0, codegen_1._) `{limit: ${len}}`,
+};
+const def = {
+ keyword: "additionalItems",
+ type: "array",
+ schemaType: ["boolean", "object"],
+ before: "uniqueItems",
+ error,
+ code(cxt) {
+ const { parentSchema, it } = cxt;
+ const { items } = parentSchema;
+ if (!Array.isArray(items)) {
+ (0, util_1.checkStrictMode)(it, '"additionalItems" is ignored when "items" is not an array of schemas');
+ return;
+ }
+ validateAdditionalItems(cxt, items);
+ },
+};
+function validateAdditionalItems(cxt, items) {
+ const { gen, schema, data, keyword, it } = cxt;
+ it.items = true;
+ const len = gen.const("len", (0, codegen_1._) `${data}.length`);
+ if (schema === false) {
+ cxt.setParams({ len: items.length });
+ cxt.pass((0, codegen_1._) `${len} <= ${items.length}`);
+ }
+ else if (typeof schema == "object" && !(0, util_1.alwaysValidSchema)(it, schema)) {
+ const valid = gen.var("valid", (0, codegen_1._) `${len} <= ${items.length}`); // TODO var
+ gen.if((0, codegen_1.not)(valid), () => validateItems(valid));
+ cxt.ok(valid);
+ }
+ function validateItems(valid) {
+ gen.forRange("i", items.length, len, (i) => {
+ cxt.subschema({ keyword, dataProp: i, dataPropType: util_1.Type.Num }, valid);
+ if (!it.allErrors)
+ gen.if((0, codegen_1.not)(valid), () => gen.break());
+ });
+ }
+}
+exports.validateAdditionalItems = validateAdditionalItems;
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13}],36:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const code_1 = require("../code");
+const codegen_1 = require("../../compile/codegen");
+const names_1 = require("../../compile/names");
+const util_1 = require("../../compile/util");
+const error = {
+ message: "must NOT have additional properties",
+ params: ({ params }) => (0, codegen_1._) `{additionalProperty: ${params.additionalProperty}}`,
+};
+const def = {
+ keyword: "additionalProperties",
+ type: ["object"],
+ schemaType: ["boolean", "object"],
+ allowUndefined: true,
+ trackErrors: true,
+ error,
+ code(cxt) {
+ const { gen, schema, parentSchema, data, errsCount, it } = cxt;
+ /* istanbul ignore if */
+ if (!errsCount)
+ throw new Error("ajv implementation error");
+ const { allErrors, opts } = it;
+ it.props = true;
+ if (opts.removeAdditional !== "all" && (0, util_1.alwaysValidSchema)(it, schema))
+ return;
+ const props = (0, code_1.allSchemaProperties)(parentSchema.properties);
+ const patProps = (0, code_1.allSchemaProperties)(parentSchema.patternProperties);
+ checkAdditionalProperties();
+ cxt.ok((0, codegen_1._) `${errsCount} === ${names_1.default.errors}`);
+ function checkAdditionalProperties() {
+ gen.forIn("key", data, (key) => {
+ if (!props.length && !patProps.length)
+ additionalPropertyCode(key);
+ else
+ gen.if(isAdditional(key), () => additionalPropertyCode(key));
+ });
+ }
+ function isAdditional(key) {
+ let definedProp;
+ if (props.length > 8) {
+ // TODO maybe an option instead of hard-coded 8?
+ const propsSchema = (0, util_1.schemaRefOrVal)(it, parentSchema.properties, "properties");
+ definedProp = (0, code_1.isOwnProperty)(gen, propsSchema, key);
+ }
+ else if (props.length) {
+ definedProp = (0, codegen_1.or)(...props.map((p) => (0, codegen_1._) `${key} === ${p}`));
+ }
+ else {
+ definedProp = codegen_1.nil;
+ }
+ if (patProps.length) {
+ definedProp = (0, codegen_1.or)(definedProp, ...patProps.map((p) => (0, codegen_1._) `${(0, code_1.usePattern)(cxt, p)}.test(${key})`));
+ }
+ return (0, codegen_1.not)(definedProp);
+ }
+ function deleteAdditional(key) {
+ gen.code((0, codegen_1._) `delete ${data}[${key}]`);
+ }
+ function additionalPropertyCode(key) {
+ if (opts.removeAdditional === "all" || (opts.removeAdditional && schema === false)) {
+ deleteAdditional(key);
+ return;
+ }
+ if (schema === false) {
+ cxt.setParams({ additionalProperty: key });
+ cxt.error();
+ if (!allErrors)
+ gen.break();
+ return;
+ }
+ if (typeof schema == "object" && !(0, util_1.alwaysValidSchema)(it, schema)) {
+ const valid = gen.name("valid");
+ if (opts.removeAdditional === "failing") {
+ applyAdditionalSchema(key, valid, false);
+ gen.if((0, codegen_1.not)(valid), () => {
+ cxt.reset();
+ deleteAdditional(key);
+ });
+ }
+ else {
+ applyAdditionalSchema(key, valid);
+ if (!allErrors)
+ gen.if((0, codegen_1.not)(valid), () => gen.break());
+ }
+ }
+ }
+ function applyAdditionalSchema(key, valid, errors) {
+ const subschema = {
+ keyword: "additionalProperties",
+ dataProp: key,
+ dataPropType: util_1.Type.Str,
+ };
+ if (errors === false) {
+ Object.assign(subschema, {
+ compositeRule: true,
+ createErrors: false,
+ allErrors: false,
+ });
+ }
+ cxt.subschema(subschema, valid);
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/names":9,"../../compile/util":13,"../code":53}],37:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const util_1 = require("../../compile/util");
+const def = {
+ keyword: "allOf",
+ schemaType: "array",
+ code(cxt) {
+ const { gen, schema, it } = cxt;
+ /* istanbul ignore if */
+ if (!Array.isArray(schema))
+ throw new Error("ajv implementation error");
+ const valid = gen.name("valid");
+ schema.forEach((sch, i) => {
+ if ((0, util_1.alwaysValidSchema)(it, sch))
+ return;
+ const schCxt = cxt.subschema({ keyword: "allOf", schemaProp: i }, valid);
+ cxt.ok(valid);
+ cxt.mergeEvaluated(schCxt);
+ });
+ },
+};
+exports.default = def;
+
+},{"../../compile/util":13}],38:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const code_1 = require("../code");
+const def = {
+ keyword: "anyOf",
+ schemaType: "array",
+ trackErrors: true,
+ code: code_1.validateUnion,
+ error: { message: "must match a schema in anyOf" },
+};
+exports.default = def;
+
+},{"../code":53}],39:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const error = {
+ message: ({ params: { min, max } }) => max === undefined
+ ? (0, codegen_1.str) `must contain at least ${min} valid item(s)`
+ : (0, codegen_1.str) `must contain at least ${min} and no more than ${max} valid item(s)`,
+ params: ({ params: { min, max } }) => max === undefined ? (0, codegen_1._) `{minContains: ${min}}` : (0, codegen_1._) `{minContains: ${min}, maxContains: ${max}}`,
+};
+const def = {
+ keyword: "contains",
+ type: "array",
+ schemaType: ["object", "boolean"],
+ before: "uniqueItems",
+ trackErrors: true,
+ error,
+ code(cxt) {
+ const { gen, schema, parentSchema, data, it } = cxt;
+ let min;
+ let max;
+ const { minContains, maxContains } = parentSchema;
+ if (it.opts.next) {
+ min = minContains === undefined ? 1 : minContains;
+ max = maxContains;
+ }
+ else {
+ min = 1;
+ }
+ const len = gen.const("len", (0, codegen_1._) `${data}.length`);
+ cxt.setParams({ min, max });
+ if (max === undefined && min === 0) {
+ (0, util_1.checkStrictMode)(it, `"minContains" == 0 without "maxContains": "contains" keyword ignored`);
+ return;
+ }
+ if (max !== undefined && min > max) {
+ (0, util_1.checkStrictMode)(it, `"minContains" > "maxContains" is always invalid`);
+ cxt.fail();
+ return;
+ }
+ if ((0, util_1.alwaysValidSchema)(it, schema)) {
+ let cond = (0, codegen_1._) `${len} >= ${min}`;
+ if (max !== undefined)
+ cond = (0, codegen_1._) `${cond} && ${len} <= ${max}`;
+ cxt.pass(cond);
+ return;
+ }
+ it.items = true;
+ const valid = gen.name("valid");
+ if (max === undefined && min === 1) {
+ validateItems(valid, () => gen.if(valid, () => gen.break()));
+ }
+ else if (min === 0) {
+ gen.let(valid, true);
+ if (max !== undefined)
+ gen.if((0, codegen_1._) `${data}.length > 0`, validateItemsWithCount);
+ }
+ else {
+ gen.let(valid, false);
+ validateItemsWithCount();
+ }
+ cxt.result(valid, () => cxt.reset());
+ function validateItemsWithCount() {
+ const schValid = gen.name("_valid");
+ const count = gen.let("count", 0);
+ validateItems(schValid, () => gen.if(schValid, () => checkLimits(count)));
+ }
+ function validateItems(_valid, block) {
+ gen.forRange("i", 0, len, (i) => {
+ cxt.subschema({
+ keyword: "contains",
+ dataProp: i,
+ dataPropType: util_1.Type.Num,
+ compositeRule: true,
+ }, _valid);
+ block();
+ });
+ }
+ function checkLimits(count) {
+ gen.code((0, codegen_1._) `${count}++`);
+ if (max === undefined) {
+ gen.if((0, codegen_1._) `${count} >= ${min}`, () => gen.assign(valid, true).break());
+ }
+ else {
+ gen.if((0, codegen_1._) `${count} > ${max}`, () => gen.assign(valid, false).break());
+ if (min === 1)
+ gen.assign(valid, true);
+ else
+ gen.if((0, codegen_1._) `${count} >= ${min}`, () => gen.assign(valid, true));
+ }
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13}],40:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.validateSchemaDeps = exports.validatePropertyDeps = exports.error = void 0;
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const code_1 = require("../code");
+exports.error = {
+ message: ({ params: { property, depsCount, deps } }) => {
+ const property_ies = depsCount === 1 ? "property" : "properties";
+ return (0, codegen_1.str) `must have ${property_ies} ${deps} when property ${property} is present`;
+ },
+ params: ({ params: { property, depsCount, deps, missingProperty } }) => (0, codegen_1._) `{property: ${property},
+ missingProperty: ${missingProperty},
+ depsCount: ${depsCount},
+ deps: ${deps}}`, // TODO change to reference
+};
+const def = {
+ keyword: "dependencies",
+ type: "object",
+ schemaType: "object",
+ error: exports.error,
+ code(cxt) {
+ const [propDeps, schDeps] = splitDependencies(cxt);
+ validatePropertyDeps(cxt, propDeps);
+ validateSchemaDeps(cxt, schDeps);
+ },
+};
+function splitDependencies({ schema }) {
+ const propertyDeps = {};
+ const schemaDeps = {};
+ for (const key in schema) {
+ if (key === "__proto__")
+ continue;
+ const deps = Array.isArray(schema[key]) ? propertyDeps : schemaDeps;
+ deps[key] = schema[key];
+ }
+ return [propertyDeps, schemaDeps];
+}
+function validatePropertyDeps(cxt, propertyDeps = cxt.schema) {
+ const { gen, data, it } = cxt;
+ if (Object.keys(propertyDeps).length === 0)
+ return;
+ const missing = gen.let("missing");
+ for (const prop in propertyDeps) {
+ const deps = propertyDeps[prop];
+ if (deps.length === 0)
+ continue;
+ const hasProperty = (0, code_1.propertyInData)(gen, data, prop, it.opts.ownProperties);
+ cxt.setParams({
+ property: prop,
+ depsCount: deps.length,
+ deps: deps.join(", "),
+ });
+ if (it.allErrors) {
+ gen.if(hasProperty, () => {
+ for (const depProp of deps) {
+ (0, code_1.checkReportMissingProp)(cxt, depProp);
+ }
+ });
+ }
+ else {
+ gen.if((0, codegen_1._) `${hasProperty} && (${(0, code_1.checkMissingProp)(cxt, deps, missing)})`);
+ (0, code_1.reportMissingProp)(cxt, missing);
+ gen.else();
+ }
+ }
+}
+exports.validatePropertyDeps = validatePropertyDeps;
+function validateSchemaDeps(cxt, schemaDeps = cxt.schema) {
+ const { gen, data, keyword, it } = cxt;
+ const valid = gen.name("valid");
+ for (const prop in schemaDeps) {
+ if ((0, util_1.alwaysValidSchema)(it, schemaDeps[prop]))
+ continue;
+ gen.if((0, code_1.propertyInData)(gen, data, prop, it.opts.ownProperties), () => {
+ const schCxt = cxt.subschema({ keyword, schemaProp: prop }, valid);
+ cxt.mergeValidEvaluated(schCxt, valid);
+ }, () => gen.var(valid, true) // TODO var
+ );
+ cxt.ok(valid);
+ }
+}
+exports.validateSchemaDeps = validateSchemaDeps;
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13,"../code":53}],41:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const dependencies_1 = require("./dependencies");
+const def = {
+ keyword: "dependentSchemas",
+ type: "object",
+ schemaType: "object",
+ code: (cxt) => (0, dependencies_1.validateSchemaDeps)(cxt),
+};
+exports.default = def;
+
+},{"./dependencies":40}],42:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const error = {
+ message: ({ params }) => (0, codegen_1.str) `must match "${params.ifClause}" schema`,
+ params: ({ params }) => (0, codegen_1._) `{failingKeyword: ${params.ifClause}}`,
+};
+const def = {
+ keyword: "if",
+ schemaType: ["object", "boolean"],
+ trackErrors: true,
+ error,
+ code(cxt) {
+ const { gen, parentSchema, it } = cxt;
+ if (parentSchema.then === undefined && parentSchema.else === undefined) {
+ (0, util_1.checkStrictMode)(it, '"if" without "then" and "else" is ignored');
+ }
+ const hasThen = hasSchema(it, "then");
+ const hasElse = hasSchema(it, "else");
+ if (!hasThen && !hasElse)
+ return;
+ const valid = gen.let("valid", true);
+ const schValid = gen.name("_valid");
+ validateIf();
+ cxt.reset();
+ if (hasThen && hasElse) {
+ const ifClause = gen.let("ifClause");
+ cxt.setParams({ ifClause });
+ gen.if(schValid, validateClause("then", ifClause), validateClause("else", ifClause));
+ }
+ else if (hasThen) {
+ gen.if(schValid, validateClause("then"));
+ }
+ else {
+ gen.if((0, codegen_1.not)(schValid), validateClause("else"));
+ }
+ cxt.pass(valid, () => cxt.error(true));
+ function validateIf() {
+ const schCxt = cxt.subschema({
+ keyword: "if",
+ compositeRule: true,
+ createErrors: false,
+ allErrors: false,
+ }, schValid);
+ cxt.mergeEvaluated(schCxt);
+ }
+ function validateClause(keyword, ifClause) {
+ return () => {
+ const schCxt = cxt.subschema({ keyword }, schValid);
+ gen.assign(valid, schValid);
+ cxt.mergeValidEvaluated(schCxt, valid);
+ if (ifClause)
+ gen.assign(ifClause, (0, codegen_1._) `${keyword}`);
+ else
+ cxt.setParams({ ifClause: keyword });
+ };
+ }
+ },
+};
+function hasSchema(it, keyword) {
+ const schema = it.schema[keyword];
+ return schema !== undefined && !(0, util_1.alwaysValidSchema)(it, schema);
+}
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13}],43:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const additionalItems_1 = require("./additionalItems");
+const prefixItems_1 = require("./prefixItems");
+const items_1 = require("./items");
+const items2020_1 = require("./items2020");
+const contains_1 = require("./contains");
+const dependencies_1 = require("./dependencies");
+const propertyNames_1 = require("./propertyNames");
+const additionalProperties_1 = require("./additionalProperties");
+const properties_1 = require("./properties");
+const patternProperties_1 = require("./patternProperties");
+const not_1 = require("./not");
+const anyOf_1 = require("./anyOf");
+const oneOf_1 = require("./oneOf");
+const allOf_1 = require("./allOf");
+const if_1 = require("./if");
+const thenElse_1 = require("./thenElse");
+function getApplicator(draft2020 = false) {
+ const applicator = [
+ // any
+ not_1.default,
+ anyOf_1.default,
+ oneOf_1.default,
+ allOf_1.default,
+ if_1.default,
+ thenElse_1.default,
+ // object
+ propertyNames_1.default,
+ additionalProperties_1.default,
+ dependencies_1.default,
+ properties_1.default,
+ patternProperties_1.default,
+ ];
+ // array
+ if (draft2020)
+ applicator.push(prefixItems_1.default, items2020_1.default);
+ else
+ applicator.push(additionalItems_1.default, items_1.default);
+ applicator.push(contains_1.default);
+ return applicator;
+}
+exports.default = getApplicator;
+
+},{"./additionalItems":35,"./additionalProperties":36,"./allOf":37,"./anyOf":38,"./contains":39,"./dependencies":40,"./if":42,"./items":44,"./items2020":45,"./not":46,"./oneOf":47,"./patternProperties":48,"./prefixItems":49,"./properties":50,"./propertyNames":51,"./thenElse":52}],44:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.validateTuple = void 0;
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const code_1 = require("../code");
+const def = {
+ keyword: "items",
+ type: "array",
+ schemaType: ["object", "array", "boolean"],
+ before: "uniqueItems",
+ code(cxt) {
+ const { schema, it } = cxt;
+ if (Array.isArray(schema))
+ return validateTuple(cxt, "additionalItems", schema);
+ it.items = true;
+ if ((0, util_1.alwaysValidSchema)(it, schema))
+ return;
+ cxt.ok((0, code_1.validateArray)(cxt));
+ },
+};
+function validateTuple(cxt, extraItems, schArr = cxt.schema) {
+ const { gen, parentSchema, data, keyword, it } = cxt;
+ checkStrictTuple(parentSchema);
+ if (it.opts.unevaluated && schArr.length && it.items !== true) {
+ it.items = util_1.mergeEvaluated.items(gen, schArr.length, it.items);
+ }
+ const valid = gen.name("valid");
+ const len = gen.const("len", (0, codegen_1._) `${data}.length`);
+ schArr.forEach((sch, i) => {
+ if ((0, util_1.alwaysValidSchema)(it, sch))
+ return;
+ gen.if((0, codegen_1._) `${len} > ${i}`, () => cxt.subschema({
+ keyword,
+ schemaProp: i,
+ dataProp: i,
+ }, valid));
+ cxt.ok(valid);
+ });
+ function checkStrictTuple(sch) {
+ const { opts, errSchemaPath } = it;
+ const l = schArr.length;
+ const fullTuple = l === sch.minItems && (l === sch.maxItems || sch[extraItems] === false);
+ if (opts.strictTuples && !fullTuple) {
+ const msg = `"${keyword}" is ${l}-tuple, but minItems or maxItems/${extraItems} are not specified or different at path "${errSchemaPath}"`;
+ (0, util_1.checkStrictMode)(it, msg, opts.strictTuples);
+ }
+ }
+}
+exports.validateTuple = validateTuple;
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13,"../code":53}],45:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const code_1 = require("../code");
+const additionalItems_1 = require("./additionalItems");
+const error = {
+ message: ({ params: { len } }) => (0, codegen_1.str) `must NOT have more than ${len} items`,
+ params: ({ params: { len } }) => (0, codegen_1._) `{limit: ${len}}`,
+};
+const def = {
+ keyword: "items",
+ type: "array",
+ schemaType: ["object", "boolean"],
+ before: "uniqueItems",
+ error,
+ code(cxt) {
+ const { schema, parentSchema, it } = cxt;
+ const { prefixItems } = parentSchema;
+ it.items = true;
+ if ((0, util_1.alwaysValidSchema)(it, schema))
+ return;
+ if (prefixItems)
+ (0, additionalItems_1.validateAdditionalItems)(cxt, prefixItems);
+ else
+ cxt.ok((0, code_1.validateArray)(cxt));
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13,"../code":53,"./additionalItems":35}],46:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const util_1 = require("../../compile/util");
+const def = {
+ keyword: "not",
+ schemaType: ["object", "boolean"],
+ trackErrors: true,
+ code(cxt) {
+ const { gen, schema, it } = cxt;
+ if ((0, util_1.alwaysValidSchema)(it, schema)) {
+ cxt.fail();
+ return;
+ }
+ const valid = gen.name("valid");
+ cxt.subschema({
+ keyword: "not",
+ compositeRule: true,
+ createErrors: false,
+ allErrors: false,
+ }, valid);
+ cxt.failResult(valid, () => cxt.reset(), () => cxt.error());
+ },
+ error: { message: "must NOT be valid" },
+};
+exports.default = def;
+
+},{"../../compile/util":13}],47:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const error = {
+ message: "must match exactly one schema in oneOf",
+ params: ({ params }) => (0, codegen_1._) `{passingSchemas: ${params.passing}}`,
+};
+const def = {
+ keyword: "oneOf",
+ schemaType: "array",
+ trackErrors: true,
+ error,
+ code(cxt) {
+ const { gen, schema, parentSchema, it } = cxt;
+ /* istanbul ignore if */
+ if (!Array.isArray(schema))
+ throw new Error("ajv implementation error");
+ if (it.opts.discriminator && parentSchema.discriminator)
+ return;
+ const schArr = schema;
+ const valid = gen.let("valid", false);
+ const passing = gen.let("passing", null);
+ const schValid = gen.name("_valid");
+ cxt.setParams({ passing });
+ // TODO possibly fail straight away (with warning or exception) if there are two empty always valid schemas
+ gen.block(validateOneOf);
+ cxt.result(valid, () => cxt.reset(), () => cxt.error(true));
+ function validateOneOf() {
+ schArr.forEach((sch, i) => {
+ let schCxt;
+ if ((0, util_1.alwaysValidSchema)(it, sch)) {
+ gen.var(schValid, true);
+ }
+ else {
+ schCxt = cxt.subschema({
+ keyword: "oneOf",
+ schemaProp: i,
+ compositeRule: true,
+ }, schValid);
+ }
+ if (i > 0) {
+ gen
+ .if((0, codegen_1._) `${schValid} && ${valid}`)
+ .assign(valid, false)
+ .assign(passing, (0, codegen_1._) `[${passing}, ${i}]`)
+ .else();
+ }
+ gen.if(schValid, () => {
+ gen.assign(valid, true);
+ gen.assign(passing, i);
+ if (schCxt)
+ cxt.mergeEvaluated(schCxt, codegen_1.Name);
+ });
+ });
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13}],48:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const code_1 = require("../code");
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const util_2 = require("../../compile/util");
+const def = {
+ keyword: "patternProperties",
+ type: "object",
+ schemaType: "object",
+ code(cxt) {
+ const { gen, schema, data, parentSchema, it } = cxt;
+ const { opts } = it;
+ const patterns = (0, code_1.allSchemaProperties)(schema);
+ const alwaysValidPatterns = patterns.filter((p) => (0, util_1.alwaysValidSchema)(it, schema[p]));
+ if (patterns.length === 0 ||
+ (alwaysValidPatterns.length === patterns.length &&
+ (!it.opts.unevaluated || it.props === true))) {
+ return;
+ }
+ const checkProperties = opts.strictSchema && !opts.allowMatchingProperties && parentSchema.properties;
+ const valid = gen.name("valid");
+ if (it.props !== true && !(it.props instanceof codegen_1.Name)) {
+ it.props = (0, util_2.evaluatedPropsToName)(gen, it.props);
+ }
+ const { props } = it;
+ validatePatternProperties();
+ function validatePatternProperties() {
+ for (const pat of patterns) {
+ if (checkProperties)
+ checkMatchingProperties(pat);
+ if (it.allErrors) {
+ validateProperties(pat);
+ }
+ else {
+ gen.var(valid, true); // TODO var
+ validateProperties(pat);
+ gen.if(valid);
+ }
+ }
+ }
+ function checkMatchingProperties(pat) {
+ for (const prop in checkProperties) {
+ if (new RegExp(pat).test(prop)) {
+ (0, util_1.checkStrictMode)(it, `property ${prop} matches pattern ${pat} (use allowMatchingProperties)`);
+ }
+ }
+ }
+ function validateProperties(pat) {
+ gen.forIn("key", data, (key) => {
+ gen.if((0, codegen_1._) `${(0, code_1.usePattern)(cxt, pat)}.test(${key})`, () => {
+ const alwaysValid = alwaysValidPatterns.includes(pat);
+ if (!alwaysValid) {
+ cxt.subschema({
+ keyword: "patternProperties",
+ schemaProp: pat,
+ dataProp: key,
+ dataPropType: util_2.Type.Str,
+ }, valid);
+ }
+ if (it.opts.unevaluated && props !== true) {
+ gen.assign((0, codegen_1._) `${props}[${key}]`, true);
+ }
+ else if (!alwaysValid && !it.allErrors) {
+ // can short-circuit if `unevaluatedProperties` is not supported (opts.next === false)
+ // or if all properties were evaluated (props === true)
+ gen.if((0, codegen_1.not)(valid), () => gen.break());
+ }
+ });
+ });
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13,"../code":53}],49:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const items_1 = require("./items");
+const def = {
+ keyword: "prefixItems",
+ type: "array",
+ schemaType: ["array"],
+ before: "uniqueItems",
+ code: (cxt) => (0, items_1.validateTuple)(cxt, "items"),
+};
+exports.default = def;
+
+},{"./items":44}],50:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const validate_1 = require("../../compile/validate");
+const code_1 = require("../code");
+const util_1 = require("../../compile/util");
+const additionalProperties_1 = require("./additionalProperties");
+const def = {
+ keyword: "properties",
+ type: "object",
+ schemaType: "object",
+ code(cxt) {
+ const { gen, schema, parentSchema, data, it } = cxt;
+ if (it.opts.removeAdditional === "all" && parentSchema.additionalProperties === undefined) {
+ additionalProperties_1.default.code(new validate_1.KeywordCxt(it, additionalProperties_1.default, "additionalProperties"));
+ }
+ const allProps = (0, code_1.allSchemaProperties)(schema);
+ for (const prop of allProps) {
+ it.definedProperties.add(prop);
+ }
+ if (it.opts.unevaluated && allProps.length && it.props !== true) {
+ it.props = util_1.mergeEvaluated.props(gen, (0, util_1.toHash)(allProps), it.props);
+ }
+ const properties = allProps.filter((p) => !(0, util_1.alwaysValidSchema)(it, schema[p]));
+ if (properties.length === 0)
+ return;
+ const valid = gen.name("valid");
+ for (const prop of properties) {
+ if (hasDefault(prop)) {
+ applyPropertySchema(prop);
+ }
+ else {
+ gen.if((0, code_1.propertyInData)(gen, data, prop, it.opts.ownProperties));
+ applyPropertySchema(prop);
+ if (!it.allErrors)
+ gen.else().var(valid, true);
+ gen.endIf();
+ }
+ cxt.it.definedProperties.add(prop);
+ cxt.ok(valid);
+ }
+ function hasDefault(prop) {
+ return it.opts.useDefaults && !it.compositeRule && schema[prop].default !== undefined;
+ }
+ function applyPropertySchema(prop) {
+ cxt.subschema({
+ keyword: "properties",
+ schemaProp: prop,
+ dataProp: prop,
+ }, valid);
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/util":13,"../../compile/validate":18,"../code":53,"./additionalProperties":36}],51:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const error = {
+ message: "property name must be valid",
+ params: ({ params }) => (0, codegen_1._) `{propertyName: ${params.propertyName}}`,
+};
+const def = {
+ keyword: "propertyNames",
+ type: "object",
+ schemaType: ["object", "boolean"],
+ error,
+ code(cxt) {
+ const { gen, schema, data, it } = cxt;
+ if ((0, util_1.alwaysValidSchema)(it, schema))
+ return;
+ const valid = gen.name("valid");
+ gen.forIn("key", data, (key) => {
+ cxt.setParams({ propertyName: key });
+ cxt.subschema({
+ keyword: "propertyNames",
+ data: key,
+ dataTypes: ["string"],
+ propertyName: key,
+ compositeRule: true,
+ }, valid);
+ gen.if((0, codegen_1.not)(valid), () => {
+ cxt.error(true);
+ if (!it.allErrors)
+ gen.break();
+ });
+ });
+ cxt.ok(valid);
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13}],52:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const util_1 = require("../../compile/util");
+const def = {
+ keyword: ["then", "else"],
+ schemaType: ["object", "boolean"],
+ code({ keyword, parentSchema, it }) {
+ if (parentSchema.if === undefined)
+ (0, util_1.checkStrictMode)(it, `"${keyword}" without "if" is ignored`);
+ },
+};
+exports.default = def;
+
+},{"../../compile/util":13}],53:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.validateUnion = exports.validateArray = exports.usePattern = exports.callValidateCode = exports.schemaProperties = exports.allSchemaProperties = exports.noPropertyInData = exports.propertyInData = exports.isOwnProperty = exports.hasPropFunc = exports.reportMissingProp = exports.checkMissingProp = exports.checkReportMissingProp = void 0;
+const codegen_1 = require("../compile/codegen");
+const util_1 = require("../compile/util");
+const names_1 = require("../compile/names");
+const util_2 = require("../compile/util");
+function checkReportMissingProp(cxt, prop) {
+ const { gen, data, it } = cxt;
+ gen.if(noPropertyInData(gen, data, prop, it.opts.ownProperties), () => {
+ cxt.setParams({ missingProperty: (0, codegen_1._) `${prop}` }, true);
+ cxt.error();
+ });
+}
+exports.checkReportMissingProp = checkReportMissingProp;
+function checkMissingProp({ gen, data, it: { opts } }, properties, missing) {
+ return (0, codegen_1.or)(...properties.map((prop) => (0, codegen_1.and)(noPropertyInData(gen, data, prop, opts.ownProperties), (0, codegen_1._) `${missing} = ${prop}`)));
+}
+exports.checkMissingProp = checkMissingProp;
+function reportMissingProp(cxt, missing) {
+ cxt.setParams({ missingProperty: missing }, true);
+ cxt.error();
+}
+exports.reportMissingProp = reportMissingProp;
+function hasPropFunc(gen) {
+ return gen.scopeValue("func", {
+ // eslint-disable-next-line @typescript-eslint/unbound-method
+ ref: Object.prototype.hasOwnProperty,
+ code: (0, codegen_1._) `Object.prototype.hasOwnProperty`,
+ });
+}
+exports.hasPropFunc = hasPropFunc;
+function isOwnProperty(gen, data, property) {
+ return (0, codegen_1._) `${hasPropFunc(gen)}.call(${data}, ${property})`;
+}
+exports.isOwnProperty = isOwnProperty;
+function propertyInData(gen, data, property, ownProperties) {
+ const cond = (0, codegen_1._) `${data}${(0, codegen_1.getProperty)(property)} !== undefined`;
+ return ownProperties ? (0, codegen_1._) `${cond} && ${isOwnProperty(gen, data, property)}` : cond;
+}
+exports.propertyInData = propertyInData;
+function noPropertyInData(gen, data, property, ownProperties) {
+ const cond = (0, codegen_1._) `${data}${(0, codegen_1.getProperty)(property)} === undefined`;
+ return ownProperties ? (0, codegen_1.or)(cond, (0, codegen_1.not)(isOwnProperty(gen, data, property))) : cond;
+}
+exports.noPropertyInData = noPropertyInData;
+function allSchemaProperties(schemaMap) {
+ return schemaMap ? Object.keys(schemaMap).filter((p) => p !== "__proto__") : [];
+}
+exports.allSchemaProperties = allSchemaProperties;
+function schemaProperties(it, schemaMap) {
+ return allSchemaProperties(schemaMap).filter((p) => !(0, util_1.alwaysValidSchema)(it, schemaMap[p]));
+}
+exports.schemaProperties = schemaProperties;
+function callValidateCode({ schemaCode, data, it: { gen, topSchemaRef, schemaPath, errorPath }, it }, func, context, passSchema) {
+ const dataAndSchema = passSchema ? (0, codegen_1._) `${schemaCode}, ${data}, ${topSchemaRef}${schemaPath}` : data;
+ const valCxt = [
+ [names_1.default.instancePath, (0, codegen_1.strConcat)(names_1.default.instancePath, errorPath)],
+ [names_1.default.parentData, it.parentData],
+ [names_1.default.parentDataProperty, it.parentDataProperty],
+ [names_1.default.rootData, names_1.default.rootData],
+ ];
+ if (it.opts.dynamicRef)
+ valCxt.push([names_1.default.dynamicAnchors, names_1.default.dynamicAnchors]);
+ const args = (0, codegen_1._) `${dataAndSchema}, ${gen.object(...valCxt)}`;
+ return context !== codegen_1.nil ? (0, codegen_1._) `${func}.call(${context}, ${args})` : (0, codegen_1._) `${func}(${args})`;
+}
+exports.callValidateCode = callValidateCode;
+const newRegExp = (0, codegen_1._) `new RegExp`;
+function usePattern({ gen, it: { opts } }, pattern) {
+ const u = opts.unicodeRegExp ? "u" : "";
+ const { regExp } = opts.code;
+ const rx = regExp(pattern, u);
+ return gen.scopeValue("pattern", {
+ key: rx.toString(),
+ ref: rx,
+ code: (0, codegen_1._) `${regExp.code === "new RegExp" ? newRegExp : (0, util_2.useFunc)(gen, regExp)}(${pattern}, ${u})`,
+ });
+}
+exports.usePattern = usePattern;
+function validateArray(cxt) {
+ const { gen, data, keyword, it } = cxt;
+ const valid = gen.name("valid");
+ if (it.allErrors) {
+ const validArr = gen.let("valid", true);
+ validateItems(() => gen.assign(validArr, false));
+ return validArr;
+ }
+ gen.var(valid, true);
+ validateItems(() => gen.break());
+ return valid;
+ function validateItems(notValid) {
+ const len = gen.const("len", (0, codegen_1._) `${data}.length`);
+ gen.forRange("i", 0, len, (i) => {
+ cxt.subschema({
+ keyword,
+ dataProp: i,
+ dataPropType: util_1.Type.Num,
+ }, valid);
+ gen.if((0, codegen_1.not)(valid), notValid);
+ });
+ }
+}
+exports.validateArray = validateArray;
+function validateUnion(cxt) {
+ const { gen, schema, keyword, it } = cxt;
+ /* istanbul ignore if */
+ if (!Array.isArray(schema))
+ throw new Error("ajv implementation error");
+ const alwaysValid = schema.some((sch) => (0, util_1.alwaysValidSchema)(it, sch));
+ if (alwaysValid && !it.opts.unevaluated)
+ return;
+ const valid = gen.let("valid", false);
+ const schValid = gen.name("_valid");
+ gen.block(() => schema.forEach((_sch, i) => {
+ const schCxt = cxt.subschema({
+ keyword,
+ schemaProp: i,
+ compositeRule: true,
+ }, schValid);
+ gen.assign(valid, (0, codegen_1._) `${valid} || ${schValid}`);
+ const merged = cxt.mergeValidEvaluated(schCxt, schValid);
+ // can short-circuit if `unevaluatedProperties/Items` not supported (opts.unevaluated !== true)
+ // or if all properties and items were evaluated (it.props === true && it.items === true)
+ if (!merged)
+ gen.if((0, codegen_1.not)(valid));
+ }));
+ cxt.result(valid, () => cxt.reset(), () => cxt.error(true));
+}
+exports.validateUnion = validateUnion;
+
+},{"../compile/codegen":5,"../compile/names":9,"../compile/util":13}],54:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const def = {
+ keyword: "id",
+ code() {
+ throw new Error('NOT SUPPORTED: keyword "id", use "$id" for schema ID');
+ },
+};
+exports.default = def;
+
+},{}],55:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const id_1 = require("./id");
+const ref_1 = require("./ref");
+const core = [
+ "$schema",
+ "$id",
+ "$defs",
+ "$vocabulary",
+ { keyword: "$comment" },
+ "definitions",
+ id_1.default,
+ ref_1.default,
+];
+exports.default = core;
+
+},{"./id":54,"./ref":56}],56:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.callRef = exports.getValidate = void 0;
+const ref_error_1 = require("../../compile/ref_error");
+const code_1 = require("../code");
+const codegen_1 = require("../../compile/codegen");
+const names_1 = require("../../compile/names");
+const compile_1 = require("../../compile");
+const util_1 = require("../../compile/util");
+const def = {
+ keyword: "$ref",
+ schemaType: "string",
+ code(cxt) {
+ const { gen, schema: $ref, it } = cxt;
+ const { baseId, schemaEnv: env, validateName, opts, self } = it;
+ const { root } = env;
+ if (($ref === "#" || $ref === "#/") && baseId === root.baseId)
+ return callRootRef();
+ const schOrEnv = compile_1.resolveRef.call(self, root, baseId, $ref);
+ if (schOrEnv === undefined)
+ throw new ref_error_1.default(it.opts.uriResolver, baseId, $ref);
+ if (schOrEnv instanceof compile_1.SchemaEnv)
+ return callValidate(schOrEnv);
+ return inlineRefSchema(schOrEnv);
+ function callRootRef() {
+ if (env === root)
+ return callRef(cxt, validateName, env, env.$async);
+ const rootName = gen.scopeValue("root", { ref: root });
+ return callRef(cxt, (0, codegen_1._) `${rootName}.validate`, root, root.$async);
+ }
+ function callValidate(sch) {
+ const v = getValidate(cxt, sch);
+ callRef(cxt, v, sch, sch.$async);
+ }
+ function inlineRefSchema(sch) {
+ const schName = gen.scopeValue("schema", opts.code.source === true ? { ref: sch, code: (0, codegen_1.stringify)(sch) } : { ref: sch });
+ const valid = gen.name("valid");
+ const schCxt = cxt.subschema({
+ schema: sch,
+ dataTypes: [],
+ schemaPath: codegen_1.nil,
+ topSchemaRef: schName,
+ errSchemaPath: $ref,
+ }, valid);
+ cxt.mergeEvaluated(schCxt);
+ cxt.ok(valid);
+ }
+ },
+};
+function getValidate(cxt, sch) {
+ const { gen } = cxt;
+ return sch.validate
+ ? gen.scopeValue("validate", { ref: sch.validate })
+ : (0, codegen_1._) `${gen.scopeValue("wrapper", { ref: sch })}.validate`;
+}
+exports.getValidate = getValidate;
+function callRef(cxt, v, sch, $async) {
+ const { gen, it } = cxt;
+ const { allErrors, schemaEnv: env, opts } = it;
+ const passCxt = opts.passContext ? names_1.default.this : codegen_1.nil;
+ if ($async)
+ callAsyncRef();
+ else
+ callSyncRef();
+ function callAsyncRef() {
+ if (!env.$async)
+ throw new Error("async schema referenced by sync schema");
+ const valid = gen.let("valid");
+ gen.try(() => {
+ gen.code((0, codegen_1._) `await ${(0, code_1.callValidateCode)(cxt, v, passCxt)}`);
+ addEvaluatedFrom(v); // TODO will not work with async, it has to be returned with the result
+ if (!allErrors)
+ gen.assign(valid, true);
+ }, (e) => {
+ gen.if((0, codegen_1._) `!(${e} instanceof ${it.ValidationError})`, () => gen.throw(e));
+ addErrorsFrom(e);
+ if (!allErrors)
+ gen.assign(valid, false);
+ });
+ cxt.ok(valid);
+ }
+ function callSyncRef() {
+ cxt.result((0, code_1.callValidateCode)(cxt, v, passCxt), () => addEvaluatedFrom(v), () => addErrorsFrom(v));
+ }
+ function addErrorsFrom(source) {
+ const errs = (0, codegen_1._) `${source}.errors`;
+ gen.assign(names_1.default.vErrors, (0, codegen_1._) `${names_1.default.vErrors} === null ? ${errs} : ${names_1.default.vErrors}.concat(${errs})`); // TODO tagged
+ gen.assign(names_1.default.errors, (0, codegen_1._) `${names_1.default.vErrors}.length`);
+ }
+ function addEvaluatedFrom(source) {
+ var _a;
+ if (!it.opts.unevaluated)
+ return;
+ const schEvaluated = (_a = sch === null || sch === void 0 ? void 0 : sch.validate) === null || _a === void 0 ? void 0 : _a.evaluated;
+ // TODO refactor
+ if (it.props !== true) {
+ if (schEvaluated && !schEvaluated.dynamicProps) {
+ if (schEvaluated.props !== undefined) {
+ it.props = util_1.mergeEvaluated.props(gen, schEvaluated.props, it.props);
+ }
+ }
+ else {
+ const props = gen.var("props", (0, codegen_1._) `${source}.evaluated.props`);
+ it.props = util_1.mergeEvaluated.props(gen, props, it.props, codegen_1.Name);
+ }
+ }
+ if (it.items !== true) {
+ if (schEvaluated && !schEvaluated.dynamicItems) {
+ if (schEvaluated.items !== undefined) {
+ it.items = util_1.mergeEvaluated.items(gen, schEvaluated.items, it.items);
+ }
+ }
+ else {
+ const items = gen.var("items", (0, codegen_1._) `${source}.evaluated.items`);
+ it.items = util_1.mergeEvaluated.items(gen, items, it.items, codegen_1.Name);
+ }
+ }
+ }
+}
+exports.callRef = callRef;
+exports.default = def;
+
+},{"../../compile":8,"../../compile/codegen":5,"../../compile/names":9,"../../compile/ref_error":10,"../../compile/util":13,"../code":53}],57:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const types_1 = require("../discriminator/types");
+const compile_1 = require("../../compile");
+const util_1 = require("../../compile/util");
+const error = {
+ message: ({ params: { discrError, tagName } }) => discrError === types_1.DiscrError.Tag
+ ? `tag "${tagName}" must be string`
+ : `value of tag "${tagName}" must be in oneOf`,
+ params: ({ params: { discrError, tag, tagName } }) => (0, codegen_1._) `{error: ${discrError}, tag: ${tagName}, tagValue: ${tag}}`,
+};
+const def = {
+ keyword: "discriminator",
+ type: "object",
+ schemaType: "object",
+ error,
+ code(cxt) {
+ const { gen, data, schema, parentSchema, it } = cxt;
+ const { oneOf } = parentSchema;
+ if (!it.opts.discriminator) {
+ throw new Error("discriminator: requires discriminator option");
+ }
+ const tagName = schema.propertyName;
+ if (typeof tagName != "string")
+ throw new Error("discriminator: requires propertyName");
+ if (schema.mapping)
+ throw new Error("discriminator: mapping is not supported");
+ if (!oneOf)
+ throw new Error("discriminator: requires oneOf keyword");
+ const valid = gen.let("valid", false);
+ const tag = gen.const("tag", (0, codegen_1._) `${data}${(0, codegen_1.getProperty)(tagName)}`);
+ gen.if((0, codegen_1._) `typeof ${tag} == "string"`, () => validateMapping(), () => cxt.error(false, { discrError: types_1.DiscrError.Tag, tag, tagName }));
+ cxt.ok(valid);
+ function validateMapping() {
+ const mapping = getMapping();
+ gen.if(false);
+ for (const tagValue in mapping) {
+ gen.elseIf((0, codegen_1._) `${tag} === ${tagValue}`);
+ gen.assign(valid, applyTagSchema(mapping[tagValue]));
+ }
+ gen.else();
+ cxt.error(false, { discrError: types_1.DiscrError.Mapping, tag, tagName });
+ gen.endIf();
+ }
+ function applyTagSchema(schemaProp) {
+ const _valid = gen.name("valid");
+ const schCxt = cxt.subschema({ keyword: "oneOf", schemaProp }, _valid);
+ cxt.mergeEvaluated(schCxt, codegen_1.Name);
+ return _valid;
+ }
+ function getMapping() {
+ var _a;
+ const oneOfMapping = {};
+ const topRequired = hasRequired(parentSchema);
+ let tagRequired = true;
+ for (let i = 0; i < oneOf.length; i++) {
+ let sch = oneOf[i];
+ if ((sch === null || sch === void 0 ? void 0 : sch.$ref) && !(0, util_1.schemaHasRulesButRef)(sch, it.self.RULES)) {
+ sch = compile_1.resolveRef.call(it.self, it.schemaEnv.root, it.baseId, sch === null || sch === void 0 ? void 0 : sch.$ref);
+ if (sch instanceof compile_1.SchemaEnv)
+ sch = sch.schema;
+ }
+ const propSch = (_a = sch === null || sch === void 0 ? void 0 : sch.properties) === null || _a === void 0 ? void 0 : _a[tagName];
+ if (typeof propSch != "object") {
+ throw new Error(`discriminator: oneOf subschemas (or referenced schemas) must have "properties/${tagName}"`);
+ }
+ tagRequired = tagRequired && (topRequired || hasRequired(sch));
+ addMappings(propSch, i);
+ }
+ if (!tagRequired)
+ throw new Error(`discriminator: "${tagName}" must be required`);
+ return oneOfMapping;
+ function hasRequired({ required }) {
+ return Array.isArray(required) && required.includes(tagName);
+ }
+ function addMappings(sch, i) {
+ if (sch.const) {
+ addMapping(sch.const, i);
+ }
+ else if (sch.enum) {
+ for (const tagValue of sch.enum) {
+ addMapping(tagValue, i);
+ }
+ }
+ else {
+ throw new Error(`discriminator: "properties/${tagName}" must have "const" or "enum"`);
+ }
+ }
+ function addMapping(tagValue, i) {
+ if (typeof tagValue != "string" || tagValue in oneOfMapping) {
+ throw new Error(`discriminator: "${tagName}" values must be unique strings`);
+ }
+ oneOfMapping[tagValue] = i;
+ }
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile":8,"../../compile/codegen":5,"../../compile/util":13,"../discriminator/types":58}],58:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.DiscrError = void 0;
+var DiscrError;
+(function (DiscrError) {
+ DiscrError["Tag"] = "tag";
+ DiscrError["Mapping"] = "mapping";
+})(DiscrError = exports.DiscrError || (exports.DiscrError = {}));
+
+},{}],59:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const core_1 = require("./core");
+const validation_1 = require("./validation");
+const applicator_1 = require("./applicator");
+const format_1 = require("./format");
+const metadata_1 = require("./metadata");
+const draft7Vocabularies = [
+ core_1.default,
+ validation_1.default,
+ (0, applicator_1.default)(),
+ format_1.default,
+ metadata_1.metadataVocabulary,
+ metadata_1.contentVocabulary,
+];
+exports.default = draft7Vocabularies;
+
+},{"./applicator":43,"./core":55,"./format":66,"./metadata":67,"./validation":75}],60:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.dynamicAnchor = void 0;
+const codegen_1 = require("../../compile/codegen");
+const names_1 = require("../../compile/names");
+const compile_1 = require("../../compile");
+const ref_1 = require("../core/ref");
+const def = {
+ keyword: "$dynamicAnchor",
+ schemaType: "string",
+ code: (cxt) => dynamicAnchor(cxt, cxt.schema),
+};
+function dynamicAnchor(cxt, anchor) {
+ const { gen, it } = cxt;
+ it.schemaEnv.root.dynamicAnchors[anchor] = true;
+ const v = (0, codegen_1._) `${names_1.default.dynamicAnchors}${(0, codegen_1.getProperty)(anchor)}`;
+ const validate = it.errSchemaPath === "#" ? it.validateName : _getValidate(cxt);
+ gen.if((0, codegen_1._) `!${v}`, () => gen.assign(v, validate));
+}
+exports.dynamicAnchor = dynamicAnchor;
+function _getValidate(cxt) {
+ const { schemaEnv, schema, self } = cxt.it;
+ const { root, baseId, localRefs, meta } = schemaEnv.root;
+ const { schemaId } = self.opts;
+ const sch = new compile_1.SchemaEnv({ schema, schemaId, root, baseId, localRefs, meta });
+ compile_1.compileSchema.call(self, sch);
+ return (0, ref_1.getValidate)(cxt, sch);
+}
+exports.default = def;
+
+},{"../../compile":8,"../../compile/codegen":5,"../../compile/names":9,"../core/ref":56}],61:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.dynamicRef = void 0;
+const codegen_1 = require("../../compile/codegen");
+const names_1 = require("../../compile/names");
+const ref_1 = require("../core/ref");
+const def = {
+ keyword: "$dynamicRef",
+ schemaType: "string",
+ code: (cxt) => dynamicRef(cxt, cxt.schema),
+};
+function dynamicRef(cxt, ref) {
+ const { gen, keyword, it } = cxt;
+ if (ref[0] !== "#")
+ throw new Error(`"${keyword}" only supports hash fragment reference`);
+ const anchor = ref.slice(1);
+ if (it.allErrors) {
+ _dynamicRef();
+ }
+ else {
+ const valid = gen.let("valid", false);
+ _dynamicRef(valid);
+ cxt.ok(valid);
+ }
+ function _dynamicRef(valid) {
+ // TODO the assumption here is that `recursiveRef: #` always points to the root
+ // of the schema object, which is not correct, because there may be $id that
+ // makes # point to it, and the target schema may not contain dynamic/recursiveAnchor.
+ // Because of that 2 tests in recursiveRef.json fail.
+ // This is a similar problem to #815 (`$id` doesn't alter resolution scope for `{ "$ref": "#" }`).
+ // (This problem is not tested in JSON-Schema-Test-Suite)
+ if (it.schemaEnv.root.dynamicAnchors[anchor]) {
+ const v = gen.let("_v", (0, codegen_1._) `${names_1.default.dynamicAnchors}${(0, codegen_1.getProperty)(anchor)}`);
+ gen.if(v, _callRef(v, valid), _callRef(it.validateName, valid));
+ }
+ else {
+ _callRef(it.validateName, valid)();
+ }
+ }
+ function _callRef(validate, valid) {
+ return valid
+ ? () => gen.block(() => {
+ (0, ref_1.callRef)(cxt, validate);
+ gen.let(valid, true);
+ })
+ : () => (0, ref_1.callRef)(cxt, validate);
+ }
+}
+exports.dynamicRef = dynamicRef;
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/names":9,"../core/ref":56}],62:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const dynamicAnchor_1 = require("./dynamicAnchor");
+const dynamicRef_1 = require("./dynamicRef");
+const recursiveAnchor_1 = require("./recursiveAnchor");
+const recursiveRef_1 = require("./recursiveRef");
+const dynamic = [dynamicAnchor_1.default, dynamicRef_1.default, recursiveAnchor_1.default, recursiveRef_1.default];
+exports.default = dynamic;
+
+},{"./dynamicAnchor":60,"./dynamicRef":61,"./recursiveAnchor":63,"./recursiveRef":64}],63:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const dynamicAnchor_1 = require("./dynamicAnchor");
+const util_1 = require("../../compile/util");
+const def = {
+ keyword: "$recursiveAnchor",
+ schemaType: "boolean",
+ code(cxt) {
+ if (cxt.schema)
+ (0, dynamicAnchor_1.dynamicAnchor)(cxt, "");
+ else
+ (0, util_1.checkStrictMode)(cxt.it, "$recursiveAnchor: false is ignored");
+ },
+};
+exports.default = def;
+
+},{"../../compile/util":13,"./dynamicAnchor":60}],64:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const dynamicRef_1 = require("./dynamicRef");
+const def = {
+ keyword: "$recursiveRef",
+ schemaType: "string",
+ code: (cxt) => (0, dynamicRef_1.dynamicRef)(cxt, cxt.schema),
+};
+exports.default = def;
+
+},{"./dynamicRef":61}],65:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const error = {
+ message: ({ schemaCode }) => (0, codegen_1.str) `must match format "${schemaCode}"`,
+ params: ({ schemaCode }) => (0, codegen_1._) `{format: ${schemaCode}}`,
+};
+const def = {
+ keyword: "format",
+ type: ["number", "string"],
+ schemaType: "string",
+ $data: true,
+ error,
+ code(cxt, ruleType) {
+ const { gen, data, $data, schema, schemaCode, it } = cxt;
+ const { opts, errSchemaPath, schemaEnv, self } = it;
+ if (!opts.validateFormats)
+ return;
+ if ($data)
+ validate$DataFormat();
+ else
+ validateFormat();
+ function validate$DataFormat() {
+ const fmts = gen.scopeValue("formats", {
+ ref: self.formats,
+ code: opts.code.formats,
+ });
+ const fDef = gen.const("fDef", (0, codegen_1._) `${fmts}[${schemaCode}]`);
+ const fType = gen.let("fType");
+ const format = gen.let("format");
+ // TODO simplify
+ gen.if((0, codegen_1._) `typeof ${fDef} == "object" && !(${fDef} instanceof RegExp)`, () => gen.assign(fType, (0, codegen_1._) `${fDef}.type || "string"`).assign(format, (0, codegen_1._) `${fDef}.validate`), () => gen.assign(fType, (0, codegen_1._) `"string"`).assign(format, fDef));
+ cxt.fail$data((0, codegen_1.or)(unknownFmt(), invalidFmt()));
+ function unknownFmt() {
+ if (opts.strictSchema === false)
+ return codegen_1.nil;
+ return (0, codegen_1._) `${schemaCode} && !${format}`;
+ }
+ function invalidFmt() {
+ const callFormat = schemaEnv.$async
+ ? (0, codegen_1._) `(${fDef}.async ? await ${format}(${data}) : ${format}(${data}))`
+ : (0, codegen_1._) `${format}(${data})`;
+ const validData = (0, codegen_1._) `(typeof ${format} == "function" ? ${callFormat} : ${format}.test(${data}))`;
+ return (0, codegen_1._) `${format} && ${format} !== true && ${fType} === ${ruleType} && !${validData}`;
+ }
+ }
+ function validateFormat() {
+ const formatDef = self.formats[schema];
+ if (!formatDef) {
+ unknownFormat();
+ return;
+ }
+ if (formatDef === true)
+ return;
+ const [fmtType, format, fmtRef] = getFormat(formatDef);
+ if (fmtType === ruleType)
+ cxt.pass(validCondition());
+ function unknownFormat() {
+ if (opts.strictSchema === false) {
+ self.logger.warn(unknownMsg());
+ return;
+ }
+ throw new Error(unknownMsg());
+ function unknownMsg() {
+ return `unknown format "${schema}" ignored in schema at path "${errSchemaPath}"`;
+ }
+ }
+ function getFormat(fmtDef) {
+ const code = fmtDef instanceof RegExp
+ ? (0, codegen_1.regexpCode)(fmtDef)
+ : opts.code.formats
+ ? (0, codegen_1._) `${opts.code.formats}${(0, codegen_1.getProperty)(schema)}`
+ : undefined;
+ const fmt = gen.scopeValue("formats", { key: schema, ref: fmtDef, code });
+ if (typeof fmtDef == "object" && !(fmtDef instanceof RegExp)) {
+ return [fmtDef.type || "string", fmtDef.validate, (0, codegen_1._) `${fmt}.validate`];
+ }
+ return ["string", fmtDef, fmt];
+ }
+ function validCondition() {
+ if (typeof formatDef == "object" && !(formatDef instanceof RegExp) && formatDef.async) {
+ if (!schemaEnv.$async)
+ throw new Error("async format in sync schema");
+ return (0, codegen_1._) `await ${fmtRef}(${data})`;
+ }
+ return typeof format == "function" ? (0, codegen_1._) `${fmtRef}(${data})` : (0, codegen_1._) `${fmtRef}.test(${data})`;
+ }
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5}],66:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const format_1 = require("./format");
+const format = [format_1.default];
+exports.default = format;
+
+},{"./format":65}],67:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.contentVocabulary = exports.metadataVocabulary = void 0;
+exports.metadataVocabulary = [
+ "title",
+ "description",
+ "default",
+ "deprecated",
+ "readOnly",
+ "writeOnly",
+ "examples",
+];
+exports.contentVocabulary = [
+ "contentMediaType",
+ "contentEncoding",
+ "contentSchema",
+];
+
+},{}],68:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const dependentRequired_1 = require("./validation/dependentRequired");
+const dependentSchemas_1 = require("./applicator/dependentSchemas");
+const limitContains_1 = require("./validation/limitContains");
+const next = [dependentRequired_1.default, dependentSchemas_1.default, limitContains_1.default];
+exports.default = next;
+
+},{"./applicator/dependentSchemas":41,"./validation/dependentRequired":73,"./validation/limitContains":76}],69:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const unevaluatedProperties_1 = require("./unevaluatedProperties");
+const unevaluatedItems_1 = require("./unevaluatedItems");
+const unevaluated = [unevaluatedProperties_1.default, unevaluatedItems_1.default];
+exports.default = unevaluated;
+
+},{"./unevaluatedItems":70,"./unevaluatedProperties":71}],70:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const error = {
+ message: ({ params: { len } }) => (0, codegen_1.str) `must NOT have more than ${len} items`,
+ params: ({ params: { len } }) => (0, codegen_1._) `{limit: ${len}}`,
+};
+const def = {
+ keyword: "unevaluatedItems",
+ type: "array",
+ schemaType: ["boolean", "object"],
+ error,
+ code(cxt) {
+ const { gen, schema, data, it } = cxt;
+ const items = it.items || 0;
+ if (items === true)
+ return;
+ const len = gen.const("len", (0, codegen_1._) `${data}.length`);
+ if (schema === false) {
+ cxt.setParams({ len: items });
+ cxt.fail((0, codegen_1._) `${len} > ${items}`);
+ }
+ else if (typeof schema == "object" && !(0, util_1.alwaysValidSchema)(it, schema)) {
+ const valid = gen.var("valid", (0, codegen_1._) `${len} <= ${items}`);
+ gen.if((0, codegen_1.not)(valid), () => validateItems(valid, items));
+ cxt.ok(valid);
+ }
+ it.items = true;
+ function validateItems(valid, from) {
+ gen.forRange("i", from, len, (i) => {
+ cxt.subschema({ keyword: "unevaluatedItems", dataProp: i, dataPropType: util_1.Type.Num }, valid);
+ if (!it.allErrors)
+ gen.if((0, codegen_1.not)(valid), () => gen.break());
+ });
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13}],71:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const names_1 = require("../../compile/names");
+const error = {
+ message: "must NOT have unevaluated properties",
+ params: ({ params }) => (0, codegen_1._) `{unevaluatedProperty: ${params.unevaluatedProperty}}`,
+};
+const def = {
+ keyword: "unevaluatedProperties",
+ type: "object",
+ schemaType: ["boolean", "object"],
+ trackErrors: true,
+ error,
+ code(cxt) {
+ const { gen, schema, data, errsCount, it } = cxt;
+ /* istanbul ignore if */
+ if (!errsCount)
+ throw new Error("ajv implementation error");
+ const { allErrors, props } = it;
+ if (props instanceof codegen_1.Name) {
+ gen.if((0, codegen_1._) `${props} !== true`, () => gen.forIn("key", data, (key) => gen.if(unevaluatedDynamic(props, key), () => unevaluatedPropCode(key))));
+ }
+ else if (props !== true) {
+ gen.forIn("key", data, (key) => props === undefined
+ ? unevaluatedPropCode(key)
+ : gen.if(unevaluatedStatic(props, key), () => unevaluatedPropCode(key)));
+ }
+ it.props = true;
+ cxt.ok((0, codegen_1._) `${errsCount} === ${names_1.default.errors}`);
+ function unevaluatedPropCode(key) {
+ if (schema === false) {
+ cxt.setParams({ unevaluatedProperty: key });
+ cxt.error();
+ if (!allErrors)
+ gen.break();
+ return;
+ }
+ if (!(0, util_1.alwaysValidSchema)(it, schema)) {
+ const valid = gen.name("valid");
+ cxt.subschema({
+ keyword: "unevaluatedProperties",
+ dataProp: key,
+ dataPropType: util_1.Type.Str,
+ }, valid);
+ if (!allErrors)
+ gen.if((0, codegen_1.not)(valid), () => gen.break());
+ }
+ }
+ function unevaluatedDynamic(evaluatedProps, key) {
+ return (0, codegen_1._) `!${evaluatedProps} || !${evaluatedProps}[${key}]`;
+ }
+ function unevaluatedStatic(evaluatedProps, key) {
+ const ps = [];
+ for (const p in evaluatedProps) {
+ if (evaluatedProps[p] === true)
+ ps.push((0, codegen_1._) `${key} !== ${p}`);
+ }
+ return (0, codegen_1.and)(...ps);
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/names":9,"../../compile/util":13}],72:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const equal_1 = require("../../runtime/equal");
+const error = {
+ message: "must be equal to constant",
+ params: ({ schemaCode }) => (0, codegen_1._) `{allowedValue: ${schemaCode}}`,
+};
+const def = {
+ keyword: "const",
+ $data: true,
+ error,
+ code(cxt) {
+ const { gen, data, $data, schemaCode, schema } = cxt;
+ if ($data || (schema && typeof schema == "object")) {
+ cxt.fail$data((0, codegen_1._) `!${(0, util_1.useFunc)(gen, equal_1.default)}(${data}, ${schemaCode})`);
+ }
+ else {
+ cxt.fail((0, codegen_1._) `${schema} !== ${data}`);
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13,"../../runtime/equal":31}],73:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const dependencies_1 = require("../applicator/dependencies");
+const def = {
+ keyword: "dependentRequired",
+ type: "object",
+ schemaType: "object",
+ error: dependencies_1.error,
+ code: (cxt) => (0, dependencies_1.validatePropertyDeps)(cxt),
+};
+exports.default = def;
+
+},{"../applicator/dependencies":40}],74:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const equal_1 = require("../../runtime/equal");
+const error = {
+ message: "must be equal to one of the allowed values",
+ params: ({ schemaCode }) => (0, codegen_1._) `{allowedValues: ${schemaCode}}`,
+};
+const def = {
+ keyword: "enum",
+ schemaType: "array",
+ $data: true,
+ error,
+ code(cxt) {
+ const { gen, data, $data, schema, schemaCode, it } = cxt;
+ if (!$data && schema.length === 0)
+ throw new Error("enum must have non-empty array");
+ const useLoop = schema.length >= it.opts.loopEnum;
+ let eql;
+ const getEql = () => (eql !== null && eql !== void 0 ? eql : (eql = (0, util_1.useFunc)(gen, equal_1.default)));
+ let valid;
+ if (useLoop || $data) {
+ valid = gen.let("valid");
+ cxt.block$data(valid, loopEnum);
+ }
+ else {
+ /* istanbul ignore if */
+ if (!Array.isArray(schema))
+ throw new Error("ajv implementation error");
+ const vSchema = gen.const("vSchema", schemaCode);
+ valid = (0, codegen_1.or)(...schema.map((_x, i) => equalCode(vSchema, i)));
+ }
+ cxt.pass(valid);
+ function loopEnum() {
+ gen.assign(valid, false);
+ gen.forOf("v", schemaCode, (v) => gen.if((0, codegen_1._) `${getEql()}(${data}, ${v})`, () => gen.assign(valid, true).break()));
+ }
+ function equalCode(vSchema, i) {
+ const sch = schema[i];
+ return typeof sch === "object" && sch !== null
+ ? (0, codegen_1._) `${getEql()}(${data}, ${vSchema}[${i}])`
+ : (0, codegen_1._) `${data} === ${sch}`;
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13,"../../runtime/equal":31}],75:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const limitNumber_1 = require("./limitNumber");
+const multipleOf_1 = require("./multipleOf");
+const limitLength_1 = require("./limitLength");
+const pattern_1 = require("./pattern");
+const limitProperties_1 = require("./limitProperties");
+const required_1 = require("./required");
+const limitItems_1 = require("./limitItems");
+const uniqueItems_1 = require("./uniqueItems");
+const const_1 = require("./const");
+const enum_1 = require("./enum");
+const validation = [
+ // number
+ limitNumber_1.default,
+ multipleOf_1.default,
+ // string
+ limitLength_1.default,
+ pattern_1.default,
+ // object
+ limitProperties_1.default,
+ required_1.default,
+ // array
+ limitItems_1.default,
+ uniqueItems_1.default,
+ // any
+ { keyword: "type", schemaType: ["string", "array"] },
+ { keyword: "nullable", schemaType: "boolean" },
+ const_1.default,
+ enum_1.default,
+];
+exports.default = validation;
+
+},{"./const":72,"./enum":74,"./limitItems":77,"./limitLength":78,"./limitNumber":79,"./limitProperties":80,"./multipleOf":81,"./pattern":82,"./required":83,"./uniqueItems":84}],76:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const util_1 = require("../../compile/util");
+const def = {
+ keyword: ["maxContains", "minContains"],
+ type: "array",
+ schemaType: "number",
+ code({ keyword, parentSchema, it }) {
+ if (parentSchema.contains === undefined) {
+ (0, util_1.checkStrictMode)(it, `"${keyword}" without "contains" is ignored`);
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/util":13}],77:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const error = {
+ message({ keyword, schemaCode }) {
+ const comp = keyword === "maxItems" ? "more" : "fewer";
+ return (0, codegen_1.str) `must NOT have ${comp} than ${schemaCode} items`;
+ },
+ params: ({ schemaCode }) => (0, codegen_1._) `{limit: ${schemaCode}}`,
+};
+const def = {
+ keyword: ["maxItems", "minItems"],
+ type: "array",
+ schemaType: "number",
+ $data: true,
+ error,
+ code(cxt) {
+ const { keyword, data, schemaCode } = cxt;
+ const op = keyword === "maxItems" ? codegen_1.operators.GT : codegen_1.operators.LT;
+ cxt.fail$data((0, codegen_1._) `${data}.length ${op} ${schemaCode}`);
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5}],78:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const ucs2length_1 = require("../../runtime/ucs2length");
+const error = {
+ message({ keyword, schemaCode }) {
+ const comp = keyword === "maxLength" ? "more" : "fewer";
+ return (0, codegen_1.str) `must NOT have ${comp} than ${schemaCode} characters`;
+ },
+ params: ({ schemaCode }) => (0, codegen_1._) `{limit: ${schemaCode}}`,
+};
+const def = {
+ keyword: ["maxLength", "minLength"],
+ type: "string",
+ schemaType: "number",
+ $data: true,
+ error,
+ code(cxt) {
+ const { keyword, data, schemaCode, it } = cxt;
+ const op = keyword === "maxLength" ? codegen_1.operators.GT : codegen_1.operators.LT;
+ const len = it.opts.unicode === false ? (0, codegen_1._) `${data}.length` : (0, codegen_1._) `${(0, util_1.useFunc)(cxt.gen, ucs2length_1.default)}(${data})`;
+ cxt.fail$data((0, codegen_1._) `${len} ${op} ${schemaCode}`);
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13,"../../runtime/ucs2length":32}],79:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const ops = codegen_1.operators;
+const KWDs = {
+ maximum: { okStr: "<=", ok: ops.LTE, fail: ops.GT },
+ minimum: { okStr: ">=", ok: ops.GTE, fail: ops.LT },
+ exclusiveMaximum: { okStr: "<", ok: ops.LT, fail: ops.GTE },
+ exclusiveMinimum: { okStr: ">", ok: ops.GT, fail: ops.LTE },
+};
+const error = {
+ message: ({ keyword, schemaCode }) => (0, codegen_1.str) `must be ${KWDs[keyword].okStr} ${schemaCode}`,
+ params: ({ keyword, schemaCode }) => (0, codegen_1._) `{comparison: ${KWDs[keyword].okStr}, limit: ${schemaCode}}`,
+};
+const def = {
+ keyword: Object.keys(KWDs),
+ type: "number",
+ schemaType: "number",
+ $data: true,
+ error,
+ code(cxt) {
+ const { keyword, data, schemaCode } = cxt;
+ cxt.fail$data((0, codegen_1._) `${data} ${KWDs[keyword].fail} ${schemaCode} || isNaN(${data})`);
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5}],80:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const error = {
+ message({ keyword, schemaCode }) {
+ const comp = keyword === "maxProperties" ? "more" : "fewer";
+ return (0, codegen_1.str) `must NOT have ${comp} than ${schemaCode} properties`;
+ },
+ params: ({ schemaCode }) => (0, codegen_1._) `{limit: ${schemaCode}}`,
+};
+const def = {
+ keyword: ["maxProperties", "minProperties"],
+ type: "object",
+ schemaType: "number",
+ $data: true,
+ error,
+ code(cxt) {
+ const { keyword, data, schemaCode } = cxt;
+ const op = keyword === "maxProperties" ? codegen_1.operators.GT : codegen_1.operators.LT;
+ cxt.fail$data((0, codegen_1._) `Object.keys(${data}).length ${op} ${schemaCode}`);
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5}],81:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const codegen_1 = require("../../compile/codegen");
+const error = {
+ message: ({ schemaCode }) => (0, codegen_1.str) `must be multiple of ${schemaCode}`,
+ params: ({ schemaCode }) => (0, codegen_1._) `{multipleOf: ${schemaCode}}`,
+};
+const def = {
+ keyword: "multipleOf",
+ type: "number",
+ schemaType: "number",
+ $data: true,
+ error,
+ code(cxt) {
+ const { gen, data, schemaCode, it } = cxt;
+ // const bdt = bad$DataType(schemaCode, def.schemaType, $data)
+ const prec = it.opts.multipleOfPrecision;
+ const res = gen.let("res");
+ const invalid = prec
+ ? (0, codegen_1._) `Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}`
+ : (0, codegen_1._) `${res} !== parseInt(${res})`;
+ cxt.fail$data((0, codegen_1._) `(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid}))`);
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5}],82:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const code_1 = require("../code");
+const codegen_1 = require("../../compile/codegen");
+const error = {
+ message: ({ schemaCode }) => (0, codegen_1.str) `must match pattern "${schemaCode}"`,
+ params: ({ schemaCode }) => (0, codegen_1._) `{pattern: ${schemaCode}}`,
+};
+const def = {
+ keyword: "pattern",
+ type: "string",
+ schemaType: "string",
+ $data: true,
+ error,
+ code(cxt) {
+ const { data, $data, schema, schemaCode, it } = cxt;
+ // TODO regexp should be wrapped in try/catchs
+ const u = it.opts.unicodeRegExp ? "u" : "";
+ const regExp = $data ? (0, codegen_1._) `(new RegExp(${schemaCode}, ${u}))` : (0, code_1.usePattern)(cxt, schema);
+ cxt.fail$data((0, codegen_1._) `!${regExp}.test(${data})`);
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../code":53}],83:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const code_1 = require("../code");
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const error = {
+ message: ({ params: { missingProperty } }) => (0, codegen_1.str) `must have required property '${missingProperty}'`,
+ params: ({ params: { missingProperty } }) => (0, codegen_1._) `{missingProperty: ${missingProperty}}`,
+};
+const def = {
+ keyword: "required",
+ type: "object",
+ schemaType: "array",
+ $data: true,
+ error,
+ code(cxt) {
+ const { gen, schema, schemaCode, data, $data, it } = cxt;
+ const { opts } = it;
+ if (!$data && schema.length === 0)
+ return;
+ const useLoop = schema.length >= opts.loopRequired;
+ if (it.allErrors)
+ allErrorsMode();
+ else
+ exitOnErrorMode();
+ if (opts.strictRequired) {
+ const props = cxt.parentSchema.properties;
+ const { definedProperties } = cxt.it;
+ for (const requiredKey of schema) {
+ if ((props === null || props === void 0 ? void 0 : props[requiredKey]) === undefined && !definedProperties.has(requiredKey)) {
+ const schemaPath = it.schemaEnv.baseId + it.errSchemaPath;
+ const msg = `required property "${requiredKey}" is not defined at "${schemaPath}" (strictRequired)`;
+ (0, util_1.checkStrictMode)(it, msg, it.opts.strictRequired);
+ }
+ }
+ }
+ function allErrorsMode() {
+ if (useLoop || $data) {
+ cxt.block$data(codegen_1.nil, loopAllRequired);
+ }
+ else {
+ for (const prop of schema) {
+ (0, code_1.checkReportMissingProp)(cxt, prop);
+ }
+ }
+ }
+ function exitOnErrorMode() {
+ const missing = gen.let("missing");
+ if (useLoop || $data) {
+ const valid = gen.let("valid", true);
+ cxt.block$data(valid, () => loopUntilMissing(missing, valid));
+ cxt.ok(valid);
+ }
+ else {
+ gen.if((0, code_1.checkMissingProp)(cxt, schema, missing));
+ (0, code_1.reportMissingProp)(cxt, missing);
+ gen.else();
+ }
+ }
+ function loopAllRequired() {
+ gen.forOf("prop", schemaCode, (prop) => {
+ cxt.setParams({ missingProperty: prop });
+ gen.if((0, code_1.noPropertyInData)(gen, data, prop, opts.ownProperties), () => cxt.error());
+ });
+ }
+ function loopUntilMissing(missing, valid) {
+ cxt.setParams({ missingProperty: missing });
+ gen.forOf(missing, schemaCode, () => {
+ gen.assign(valid, (0, code_1.propertyInData)(gen, data, missing, opts.ownProperties));
+ gen.if((0, codegen_1.not)(valid), () => {
+ cxt.error();
+ gen.break();
+ });
+ }, codegen_1.nil);
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13,"../code":53}],84:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const dataType_1 = require("../../compile/validate/dataType");
+const codegen_1 = require("../../compile/codegen");
+const util_1 = require("../../compile/util");
+const equal_1 = require("../../runtime/equal");
+const error = {
+ message: ({ params: { i, j } }) => (0, codegen_1.str) `must NOT have duplicate items (items ## ${j} and ${i} are identical)`,
+ params: ({ params: { i, j } }) => (0, codegen_1._) `{i: ${i}, j: ${j}}`,
+};
+const def = {
+ keyword: "uniqueItems",
+ type: "array",
+ schemaType: "boolean",
+ $data: true,
+ error,
+ code(cxt) {
+ const { gen, data, $data, schema, parentSchema, schemaCode, it } = cxt;
+ if (!$data && !schema)
+ return;
+ const valid = gen.let("valid");
+ const itemTypes = parentSchema.items ? (0, dataType_1.getSchemaTypes)(parentSchema.items) : [];
+ cxt.block$data(valid, validateUniqueItems, (0, codegen_1._) `${schemaCode} === false`);
+ cxt.ok(valid);
+ function validateUniqueItems() {
+ const i = gen.let("i", (0, codegen_1._) `${data}.length`);
+ const j = gen.let("j");
+ cxt.setParams({ i, j });
+ gen.assign(valid, true);
+ gen.if((0, codegen_1._) `${i} > 1`, () => (canOptimize() ? loopN : loopN2)(i, j));
+ }
+ function canOptimize() {
+ return itemTypes.length > 0 && !itemTypes.some((t) => t === "object" || t === "array");
+ }
+ function loopN(i, j) {
+ const item = gen.name("item");
+ const wrongType = (0, dataType_1.checkDataTypes)(itemTypes, item, it.opts.strictNumbers, dataType_1.DataType.Wrong);
+ const indices = gen.const("indices", (0, codegen_1._) `{}`);
+ gen.for((0, codegen_1._) `;${i}--;`, () => {
+ gen.let(item, (0, codegen_1._) `${data}[${i}]`);
+ gen.if(wrongType, (0, codegen_1._) `continue`);
+ if (itemTypes.length > 1)
+ gen.if((0, codegen_1._) `typeof ${item} == "string"`, (0, codegen_1._) `${item} += "_"`);
+ gen
+ .if((0, codegen_1._) `typeof ${indices}[${item}] == "number"`, () => {
+ gen.assign(j, (0, codegen_1._) `${indices}[${item}]`);
+ cxt.error();
+ gen.assign(valid, false).break();
+ })
+ .code((0, codegen_1._) `${indices}[${item}] = ${i}`);
+ });
+ }
+ function loopN2(i, j) {
+ const eql = (0, util_1.useFunc)(gen, equal_1.default);
+ const outer = gen.name("outer");
+ gen.label(outer).for((0, codegen_1._) `;${i}--;`, () => gen.for((0, codegen_1._) `${j} = ${i}; ${j}--;`, () => gen.if((0, codegen_1._) `${eql}(${data}[${i}], ${data}[${j}])`, () => {
+ cxt.error();
+ gen.assign(valid, false).break(outer);
+ })));
+ }
+ },
+};
+exports.default = def;
+
+},{"../../compile/codegen":5,"../../compile/util":13,"../../compile/validate/dataType":16,"../../runtime/equal":31}],85:[function(require,module,exports){
+'use strict';
+
+// do not edit .js files directly - edit src/index.jst
+
+
+
+module.exports = function equal(a, b) {
+ if (a === b) return true;
+
+ if (a && b && typeof a == 'object' && typeof b == 'object') {
+ if (a.constructor !== b.constructor) return false;
+
+ var length, i, keys;
+ if (Array.isArray(a)) {
+ length = a.length;
+ if (length != b.length) return false;
+ for (i = length; i-- !== 0;)
+ if (!equal(a[i], b[i])) return false;
+ return true;
+ }
+
+
+
+ if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
+ if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
+ if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
+
+ keys = Object.keys(a);
+ length = keys.length;
+ if (length !== Object.keys(b).length) return false;
+
+ for (i = length; i-- !== 0;)
+ if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
+
+ for (i = length; i-- !== 0;) {
+ var key = keys[i];
+
+ if (!equal(a[key], b[key])) return false;
+ }
+
+ return true;
+ }
+
+ // true if both NaN, false otherwise
+ return a!==a && b!==b;
+};
+
+},{}],86:[function(require,module,exports){
+'use strict';
+
+var traverse = module.exports = function (schema, opts, cb) {
+ // Legacy support for v0.3.1 and earlier.
+ if (typeof opts == 'function') {
+ cb = opts;
+ opts = {};
+ }
+
+ cb = opts.cb || cb;
+ var pre = (typeof cb == 'function') ? cb : cb.pre || function() {};
+ var post = cb.post || function() {};
+
+ _traverse(opts, pre, post, schema, '', schema);
+};
+
+
+traverse.keywords = {
+ additionalItems: true,
+ items: true,
+ contains: true,
+ additionalProperties: true,
+ propertyNames: true,
+ not: true,
+ if: true,
+ then: true,
+ else: true
+};
+
+traverse.arrayKeywords = {
+ items: true,
+ allOf: true,
+ anyOf: true,
+ oneOf: true
+};
+
+traverse.propsKeywords = {
+ $defs: true,
+ definitions: true,
+ properties: true,
+ patternProperties: true,
+ dependencies: true
+};
+
+traverse.skipKeywords = {
+ default: true,
+ enum: true,
+ const: true,
+ required: true,
+ maximum: true,
+ minimum: true,
+ exclusiveMaximum: true,
+ exclusiveMinimum: true,
+ multipleOf: true,
+ maxLength: true,
+ minLength: true,
+ pattern: true,
+ format: true,
+ maxItems: true,
+ minItems: true,
+ uniqueItems: true,
+ maxProperties: true,
+ minProperties: true
+};
+
+
+function _traverse(opts, pre, post, schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) {
+ if (schema && typeof schema == 'object' && !Array.isArray(schema)) {
+ pre(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex);
+ for (var key in schema) {
+ var sch = schema[key];
+ if (Array.isArray(sch)) {
+ if (key in traverse.arrayKeywords) {
+ for (var i=0; i 1) {
+ sets[0] = sets[0].slice(0, -1);
+ var xl = sets.length - 1;
+ for (var x = 1; x < xl; ++x) {
+ sets[x] = sets[x].slice(1, -1);
+ }
+ sets[xl] = sets[xl].slice(1);
+ return sets.join('');
+ } else {
+ return sets[0];
+ }
+}
+function subexp(str) {
+ return "(?:" + str + ")";
+}
+function typeOf(o) {
+ return o === undefined ? "undefined" : o === null ? "null" : Object.prototype.toString.call(o).split(" ").pop().split("]").shift().toLowerCase();
+}
+function toUpperCase(str) {
+ return str.toUpperCase();
+}
+function toArray(obj) {
+ return obj !== undefined && obj !== null ? obj instanceof Array ? obj : typeof obj.length !== "number" || obj.split || obj.setInterval || obj.call ? [obj] : Array.prototype.slice.call(obj) : [];
+}
+function assign(target, source) {
+ var obj = target;
+ if (source) {
+ for (var key in source) {
+ obj[key] = source[key];
+ }
+ }
+ return obj;
+}
+
+function buildExps(isIRI) {
+ var ALPHA$$ = "[A-Za-z]",
+ CR$ = "[\\x0D]",
+ DIGIT$$ = "[0-9]",
+ DQUOTE$$ = "[\\x22]",
+ HEXDIG$$ = merge(DIGIT$$, "[A-Fa-f]"),
+ //case-insensitive
+ LF$$ = "[\\x0A]",
+ SP$$ = "[\\x20]",
+ PCT_ENCODED$ = subexp(subexp("%[EFef]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%[89A-Fa-f]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%" + HEXDIG$$ + HEXDIG$$)),
+ //expanded
+ GEN_DELIMS$$ = "[\\:\\/\\?\\#\\[\\]\\@]",
+ SUB_DELIMS$$ = "[\\!\\$\\&\\'\\(\\)\\*\\+\\,\\;\\=]",
+ RESERVED$$ = merge(GEN_DELIMS$$, SUB_DELIMS$$),
+ UCSCHAR$$ = isIRI ? "[\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]" : "[]",
+ //subset, excludes bidi control characters
+ IPRIVATE$$ = isIRI ? "[\\uE000-\\uF8FF]" : "[]",
+ //subset
+ UNRESERVED$$ = merge(ALPHA$$, DIGIT$$, "[\\-\\.\\_\\~]", UCSCHAR$$),
+ SCHEME$ = subexp(ALPHA$$ + merge(ALPHA$$, DIGIT$$, "[\\+\\-\\.]") + "*"),
+ USERINFO$ = subexp(subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\:]")) + "*"),
+ DEC_OCTET$ = subexp(subexp("25[0-5]") + "|" + subexp("2[0-4]" + DIGIT$$) + "|" + subexp("1" + DIGIT$$ + DIGIT$$) + "|" + subexp("[1-9]" + DIGIT$$) + "|" + DIGIT$$),
+ DEC_OCTET_RELAXED$ = subexp(subexp("25[0-5]") + "|" + subexp("2[0-4]" + DIGIT$$) + "|" + subexp("1" + DIGIT$$ + DIGIT$$) + "|" + subexp("0?[1-9]" + DIGIT$$) + "|0?0?" + DIGIT$$),
+ //relaxed parsing rules
+ IPV4ADDRESS$ = subexp(DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$),
+ H16$ = subexp(HEXDIG$$ + "{1,4}"),
+ LS32$ = subexp(subexp(H16$ + "\\:" + H16$) + "|" + IPV4ADDRESS$),
+ IPV6ADDRESS1$ = subexp(subexp(H16$ + "\\:") + "{6}" + LS32$),
+ // 6( h16 ":" ) ls32
+ IPV6ADDRESS2$ = subexp("\\:\\:" + subexp(H16$ + "\\:") + "{5}" + LS32$),
+ // "::" 5( h16 ":" ) ls32
+ IPV6ADDRESS3$ = subexp(subexp(H16$) + "?\\:\\:" + subexp(H16$ + "\\:") + "{4}" + LS32$),
+ //[ h16 ] "::" 4( h16 ":" ) ls32
+ IPV6ADDRESS4$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,1}" + H16$) + "?\\:\\:" + subexp(H16$ + "\\:") + "{3}" + LS32$),
+ //[ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+ IPV6ADDRESS5$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,2}" + H16$) + "?\\:\\:" + subexp(H16$ + "\\:") + "{2}" + LS32$),
+ //[ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+ IPV6ADDRESS6$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,3}" + H16$) + "?\\:\\:" + H16$ + "\\:" + LS32$),
+ //[ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
+ IPV6ADDRESS7$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,4}" + H16$) + "?\\:\\:" + LS32$),
+ //[ *4( h16 ":" ) h16 ] "::" ls32
+ IPV6ADDRESS8$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,5}" + H16$) + "?\\:\\:" + H16$),
+ //[ *5( h16 ":" ) h16 ] "::" h16
+ IPV6ADDRESS9$ = subexp(subexp(subexp(H16$ + "\\:") + "{0,6}" + H16$) + "?\\:\\:"),
+ //[ *6( h16 ":" ) h16 ] "::"
+ IPV6ADDRESS$ = subexp([IPV6ADDRESS1$, IPV6ADDRESS2$, IPV6ADDRESS3$, IPV6ADDRESS4$, IPV6ADDRESS5$, IPV6ADDRESS6$, IPV6ADDRESS7$, IPV6ADDRESS8$, IPV6ADDRESS9$].join("|")),
+ ZONEID$ = subexp(subexp(UNRESERVED$$ + "|" + PCT_ENCODED$) + "+"),
+ //RFC 6874
+ IPV6ADDRZ$ = subexp(IPV6ADDRESS$ + "\\%25" + ZONEID$),
+ //RFC 6874
+ IPV6ADDRZ_RELAXED$ = subexp(IPV6ADDRESS$ + subexp("\\%25|\\%(?!" + HEXDIG$$ + "{2})") + ZONEID$),
+ //RFC 6874, with relaxed parsing rules
+ IPVFUTURE$ = subexp("[vV]" + HEXDIG$$ + "+\\." + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\:]") + "+"),
+ IP_LITERAL$ = subexp("\\[" + subexp(IPV6ADDRZ_RELAXED$ + "|" + IPV6ADDRESS$ + "|" + IPVFUTURE$) + "\\]"),
+ //RFC 6874
+ REG_NAME$ = subexp(subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$)) + "*"),
+ HOST$ = subexp(IP_LITERAL$ + "|" + IPV4ADDRESS$ + "(?!" + REG_NAME$ + ")" + "|" + REG_NAME$),
+ PORT$ = subexp(DIGIT$$ + "*"),
+ AUTHORITY$ = subexp(subexp(USERINFO$ + "@") + "?" + HOST$ + subexp("\\:" + PORT$) + "?"),
+ PCHAR$ = subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@]")),
+ SEGMENT$ = subexp(PCHAR$ + "*"),
+ SEGMENT_NZ$ = subexp(PCHAR$ + "+"),
+ SEGMENT_NZ_NC$ = subexp(subexp(PCT_ENCODED$ + "|" + merge(UNRESERVED$$, SUB_DELIMS$$, "[\\@]")) + "+"),
+ PATH_ABEMPTY$ = subexp(subexp("\\/" + SEGMENT$) + "*"),
+ PATH_ABSOLUTE$ = subexp("\\/" + subexp(SEGMENT_NZ$ + PATH_ABEMPTY$) + "?"),
+ //simplified
+ PATH_NOSCHEME$ = subexp(SEGMENT_NZ_NC$ + PATH_ABEMPTY$),
+ //simplified
+ PATH_ROOTLESS$ = subexp(SEGMENT_NZ$ + PATH_ABEMPTY$),
+ //simplified
+ PATH_EMPTY$ = "(?!" + PCHAR$ + ")",
+ PATH$ = subexp(PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$),
+ QUERY$ = subexp(subexp(PCHAR$ + "|" + merge("[\\/\\?]", IPRIVATE$$)) + "*"),
+ FRAGMENT$ = subexp(subexp(PCHAR$ + "|[\\/\\?]") + "*"),
+ HIER_PART$ = subexp(subexp("\\/\\/" + AUTHORITY$ + PATH_ABEMPTY$) + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$),
+ URI$ = subexp(SCHEME$ + "\\:" + HIER_PART$ + subexp("\\?" + QUERY$) + "?" + subexp("\\#" + FRAGMENT$) + "?"),
+ RELATIVE_PART$ = subexp(subexp("\\/\\/" + AUTHORITY$ + PATH_ABEMPTY$) + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_EMPTY$),
+ RELATIVE$ = subexp(RELATIVE_PART$ + subexp("\\?" + QUERY$) + "?" + subexp("\\#" + FRAGMENT$) + "?"),
+ URI_REFERENCE$ = subexp(URI$ + "|" + RELATIVE$),
+ ABSOLUTE_URI$ = subexp(SCHEME$ + "\\:" + HIER_PART$ + subexp("\\?" + QUERY$) + "?"),
+ GENERIC_REF$ = "^(" + SCHEME$ + ")\\:" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?" + subexp("\\#(" + FRAGMENT$ + ")") + "?$",
+ RELATIVE_REF$ = "^(){0}" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?" + subexp("\\#(" + FRAGMENT$ + ")") + "?$",
+ ABSOLUTE_REF$ = "^(" + SCHEME$ + ")\\:" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?$",
+ SAMEDOC_REF$ = "^" + subexp("\\#(" + FRAGMENT$ + ")") + "?$",
+ AUTHORITY_REF$ = "^" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?$";
+ return {
+ NOT_SCHEME: new RegExp(merge("[^]", ALPHA$$, DIGIT$$, "[\\+\\-\\.]"), "g"),
+ NOT_USERINFO: new RegExp(merge("[^\\%\\:]", UNRESERVED$$, SUB_DELIMS$$), "g"),
+ NOT_HOST: new RegExp(merge("[^\\%\\[\\]\\:]", UNRESERVED$$, SUB_DELIMS$$), "g"),
+ NOT_PATH: new RegExp(merge("[^\\%\\/\\:\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"),
+ NOT_PATH_NOSCHEME: new RegExp(merge("[^\\%\\/\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"),
+ NOT_QUERY: new RegExp(merge("[^\\%]", UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@\\/\\?]", IPRIVATE$$), "g"),
+ NOT_FRAGMENT: new RegExp(merge("[^\\%]", UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@\\/\\?]"), "g"),
+ ESCAPE: new RegExp(merge("[^]", UNRESERVED$$, SUB_DELIMS$$), "g"),
+ UNRESERVED: new RegExp(UNRESERVED$$, "g"),
+ OTHER_CHARS: new RegExp(merge("[^\\%]", UNRESERVED$$, RESERVED$$), "g"),
+ PCT_ENCODED: new RegExp(PCT_ENCODED$, "g"),
+ IPV4ADDRESS: new RegExp("^(" + IPV4ADDRESS$ + ")$"),
+ IPV6ADDRESS: new RegExp("^\\[?(" + IPV6ADDRESS$ + ")" + subexp(subexp("\\%25|\\%(?!" + HEXDIG$$ + "{2})") + "(" + ZONEID$ + ")") + "?\\]?$") //RFC 6874, with relaxed parsing rules
+ };
+}
+var URI_PROTOCOL = buildExps(false);
+
+var IRI_PROTOCOL = buildExps(true);
+
+var slicedToArray = function () {
+ function sliceIterator(arr, i) {
+ var _arr = [];
+ var _n = true;
+ var _d = false;
+ var _e = undefined;
+
+ try {
+ for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
+ _arr.push(_s.value);
+
+ if (i && _arr.length === i) break;
+ }
+ } catch (err) {
+ _d = true;
+ _e = err;
+ } finally {
+ try {
+ if (!_n && _i["return"]) _i["return"]();
+ } finally {
+ if (_d) throw _e;
+ }
+ }
+
+ return _arr;
+ }
+
+ return function (arr, i) {
+ if (Array.isArray(arr)) {
+ return arr;
+ } else if (Symbol.iterator in Object(arr)) {
+ return sliceIterator(arr, i);
+ } else {
+ throw new TypeError("Invalid attempt to destructure non-iterable instance");
+ }
+ };
+}();
+
+
+
+
+
+
+
+
+
+
+
+
+
+var toConsumableArray = function (arr) {
+ if (Array.isArray(arr)) {
+ for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
+
+ return arr2;
+ } else {
+ return Array.from(arr);
+ }
+};
+
+/** Highest positive signed 32-bit float value */
+
+var maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1
+
+/** Bootstring parameters */
+var base = 36;
+var tMin = 1;
+var tMax = 26;
+var skew = 38;
+var damp = 700;
+var initialBias = 72;
+var initialN = 128; // 0x80
+var delimiter = '-'; // '\x2D'
+
+/** Regular expressions */
+var regexPunycode = /^xn--/;
+var regexNonASCII = /[^\0-\x7E]/; // non-ASCII chars
+var regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g; // RFC 3490 separators
+
+/** Error messages */
+var errors = {
+ 'overflow': 'Overflow: input needs wider integers to process',
+ 'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+ 'invalid-input': 'Invalid input'
+};
+
+/** Convenience shortcuts */
+var baseMinusTMin = base - tMin;
+var floor = Math.floor;
+var stringFromCharCode = String.fromCharCode;
+
+/*--------------------------------------------------------------------------*/
+
+/**
+ * A generic error utility function.
+ * @private
+ * @param {String} type The error type.
+ * @returns {Error} Throws a `RangeError` with the applicable error message.
+ */
+function error$1(type) {
+ throw new RangeError(errors[type]);
+}
+
+/**
+ * A generic `Array#map` utility function.
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} callback The function that gets called for every array
+ * item.
+ * @returns {Array} A new array of values returned by the callback function.
+ */
+function map(array, fn) {
+ var result = [];
+ var length = array.length;
+ while (length--) {
+ result[length] = fn(array[length]);
+ }
+ return result;
+}
+
+/**
+ * A simple `Array#map`-like wrapper to work with domain name strings or email
+ * addresses.
+ * @private
+ * @param {String} domain The domain name or email address.
+ * @param {Function} callback The function that gets called for every
+ * character.
+ * @returns {Array} A new string of characters returned by the callback
+ * function.
+ */
+function mapDomain(string, fn) {
+ var parts = string.split('@');
+ var result = '';
+ if (parts.length > 1) {
+ // In email addresses, only the domain name should be punycoded. Leave
+ // the local part (i.e. everything up to `@`) intact.
+ result = parts[0] + '@';
+ string = parts[1];
+ }
+ // Avoid `split(regex)` for IE8 compatibility. See #17.
+ string = string.replace(regexSeparators, '\x2E');
+ var labels = string.split('.');
+ var encoded = map(labels, fn).join('.');
+ return result + encoded;
+}
+
+/**
+ * Creates an array containing the numeric code points of each Unicode
+ * character in the string. While JavaScript uses UCS-2 internally,
+ * this function will convert a pair of surrogate halves (each of which
+ * UCS-2 exposes as separate characters) into a single code point,
+ * matching UTF-16.
+ * @see `punycode.ucs2.encode`
+ * @see
+ * @memberOf punycode.ucs2
+ * @name decode
+ * @param {String} string The Unicode input string (UCS-2).
+ * @returns {Array} The new array of code points.
+ */
+function ucs2decode(string) {
+ var output = [];
+ var counter = 0;
+ var length = string.length;
+ while (counter < length) {
+ var value = string.charCodeAt(counter++);
+ if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
+ // It's a high surrogate, and there is a next character.
+ var extra = string.charCodeAt(counter++);
+ if ((extra & 0xFC00) == 0xDC00) {
+ // Low surrogate.
+ output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
+ } else {
+ // It's an unmatched surrogate; only append this code unit, in case the
+ // next code unit is the high surrogate of a surrogate pair.
+ output.push(value);
+ counter--;
+ }
+ } else {
+ output.push(value);
+ }
+ }
+ return output;
+}
+
+/**
+ * Creates a string based on an array of numeric code points.
+ * @see `punycode.ucs2.decode`
+ * @memberOf punycode.ucs2
+ * @name encode
+ * @param {Array} codePoints The array of numeric code points.
+ * @returns {String} The new Unicode string (UCS-2).
+ */
+var ucs2encode = function ucs2encode(array) {
+ return String.fromCodePoint.apply(String, toConsumableArray(array));
+};
+
+/**
+ * Converts a basic code point into a digit/integer.
+ * @see `digitToBasic()`
+ * @private
+ * @param {Number} codePoint The basic numeric code point value.
+ * @returns {Number} The numeric value of a basic code point (for use in
+ * representing integers) in the range `0` to `base - 1`, or `base` if
+ * the code point does not represent a value.
+ */
+var basicToDigit = function basicToDigit(codePoint) {
+ if (codePoint - 0x30 < 0x0A) {
+ return codePoint - 0x16;
+ }
+ if (codePoint - 0x41 < 0x1A) {
+ return codePoint - 0x41;
+ }
+ if (codePoint - 0x61 < 0x1A) {
+ return codePoint - 0x61;
+ }
+ return base;
+};
+
+/**
+ * Converts a digit/integer into a basic code point.
+ * @see `basicToDigit()`
+ * @private
+ * @param {Number} digit The numeric value of a basic code point.
+ * @returns {Number} The basic code point whose value (when used for
+ * representing integers) is `digit`, which needs to be in the range
+ * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+ * used; else, the lowercase form is used. The behavior is undefined
+ * if `flag` is non-zero and `digit` has no uppercase form.
+ */
+var digitToBasic = function digitToBasic(digit, flag) {
+ // 0..25 map to ASCII a..z or A..Z
+ // 26..35 map to ASCII 0..9
+ return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+};
+
+/**
+ * Bias adaptation function as per section 3.4 of RFC 3492.
+ * https://tools.ietf.org/html/rfc3492#section-3.4
+ * @private
+ */
+var adapt = function adapt(delta, numPoints, firstTime) {
+ var k = 0;
+ delta = firstTime ? floor(delta / damp) : delta >> 1;
+ delta += floor(delta / numPoints);
+ for (; /* no initialization */delta > baseMinusTMin * tMax >> 1; k += base) {
+ delta = floor(delta / baseMinusTMin);
+ }
+ return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+};
+
+/**
+ * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+ * symbols.
+ * @memberOf punycode
+ * @param {String} input The Punycode string of ASCII-only symbols.
+ * @returns {String} The resulting string of Unicode symbols.
+ */
+var decode = function decode(input) {
+ // Don't use UCS-2.
+ var output = [];
+ var inputLength = input.length;
+ var i = 0;
+ var n = initialN;
+ var bias = initialBias;
+
+ // Handle the basic code points: let `basic` be the number of input code
+ // points before the last delimiter, or `0` if there is none, then copy
+ // the first basic code points to the output.
+
+ var basic = input.lastIndexOf(delimiter);
+ if (basic < 0) {
+ basic = 0;
+ }
+
+ for (var j = 0; j < basic; ++j) {
+ // if it's not a basic code point
+ if (input.charCodeAt(j) >= 0x80) {
+ error$1('not-basic');
+ }
+ output.push(input.charCodeAt(j));
+ }
+
+ // Main decoding loop: start just after the last delimiter if any basic code
+ // points were copied; start at the beginning otherwise.
+
+ for (var index = basic > 0 ? basic + 1 : 0; index < inputLength;) /* no final expression */{
+
+ // `index` is the index of the next character to be consumed.
+ // Decode a generalized variable-length integer into `delta`,
+ // which gets added to `i`. The overflow checking is easier
+ // if we increase `i` as we go, then subtract off its starting
+ // value at the end to obtain `delta`.
+ var oldi = i;
+ for (var w = 1, k = base;; /* no condition */k += base) {
+
+ if (index >= inputLength) {
+ error$1('invalid-input');
+ }
+
+ var digit = basicToDigit(input.charCodeAt(index++));
+
+ if (digit >= base || digit > floor((maxInt - i) / w)) {
+ error$1('overflow');
+ }
+
+ i += digit * w;
+ var t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
+
+ if (digit < t) {
+ break;
+ }
+
+ var baseMinusT = base - t;
+ if (w > floor(maxInt / baseMinusT)) {
+ error$1('overflow');
+ }
+
+ w *= baseMinusT;
+ }
+
+ var out = output.length + 1;
+ bias = adapt(i - oldi, out, oldi == 0);
+
+ // `i` was supposed to wrap around from `out` to `0`,
+ // incrementing `n` each time, so we'll fix that now:
+ if (floor(i / out) > maxInt - n) {
+ error$1('overflow');
+ }
+
+ n += floor(i / out);
+ i %= out;
+
+ // Insert `n` at position `i` of the output.
+ output.splice(i++, 0, n);
+ }
+
+ return String.fromCodePoint.apply(String, output);
+};
+
+/**
+ * Converts a string of Unicode symbols (e.g. a domain name label) to a
+ * Punycode string of ASCII-only symbols.
+ * @memberOf punycode
+ * @param {String} input The string of Unicode symbols.
+ * @returns {String} The resulting Punycode string of ASCII-only symbols.
+ */
+var encode = function encode(input) {
+ var output = [];
+
+ // Convert the input in UCS-2 to an array of Unicode code points.
+ input = ucs2decode(input);
+
+ // Cache the length.
+ var inputLength = input.length;
+
+ // Initialize the state.
+ var n = initialN;
+ var delta = 0;
+ var bias = initialBias;
+
+ // Handle the basic code points.
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = input[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var _currentValue2 = _step.value;
+
+ if (_currentValue2 < 0x80) {
+ output.push(stringFromCharCode(_currentValue2));
+ }
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ var basicLength = output.length;
+ var handledCPCount = basicLength;
+
+ // `handledCPCount` is the number of code points that have been handled;
+ // `basicLength` is the number of basic code points.
+
+ // Finish the basic string with a delimiter unless it's empty.
+ if (basicLength) {
+ output.push(delimiter);
+ }
+
+ // Main encoding loop:
+ while (handledCPCount < inputLength) {
+
+ // All non-basic code points < n have been handled already. Find the next
+ // larger one:
+ var m = maxInt;
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = input[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ var currentValue = _step2.value;
+
+ if (currentValue >= n && currentValue < m) {
+ m = currentValue;
+ }
+ }
+
+ // Increase `delta` enough to advance the decoder's state to ,
+ // but guard against overflow.
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+
+ var handledCPCountPlusOne = handledCPCount + 1;
+ if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+ error$1('overflow');
+ }
+
+ delta += (m - n) * handledCPCountPlusOne;
+ n = m;
+
+ var _iteratorNormalCompletion3 = true;
+ var _didIteratorError3 = false;
+ var _iteratorError3 = undefined;
+
+ try {
+ for (var _iterator3 = input[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+ var _currentValue = _step3.value;
+
+ if (_currentValue < n && ++delta > maxInt) {
+ error$1('overflow');
+ }
+ if (_currentValue == n) {
+ // Represent delta as a generalized variable-length integer.
+ var q = delta;
+ for (var k = base;; /* no condition */k += base) {
+ var t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
+ if (q < t) {
+ break;
+ }
+ var qMinusT = q - t;
+ var baseMinusT = base - t;
+ output.push(stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)));
+ q = floor(qMinusT / baseMinusT);
+ }
+
+ output.push(stringFromCharCode(digitToBasic(q, 0)));
+ bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+ delta = 0;
+ ++handledCPCount;
+ }
+ }
+ } catch (err) {
+ _didIteratorError3 = true;
+ _iteratorError3 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion3 && _iterator3.return) {
+ _iterator3.return();
+ }
+ } finally {
+ if (_didIteratorError3) {
+ throw _iteratorError3;
+ }
+ }
+ }
+
+ ++delta;
+ ++n;
+ }
+ return output.join('');
+};
+
+/**
+ * Converts a Punycode string representing a domain name or an email address
+ * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+ * it doesn't matter if you call it on a string that has already been
+ * converted to Unicode.
+ * @memberOf punycode
+ * @param {String} input The Punycoded domain name or email address to
+ * convert to Unicode.
+ * @returns {String} The Unicode representation of the given Punycode
+ * string.
+ */
+var toUnicode = function toUnicode(input) {
+ return mapDomain(input, function (string) {
+ return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string;
+ });
+};
+
+/**
+ * Converts a Unicode string representing a domain name or an email address to
+ * Punycode. Only the non-ASCII parts of the domain name will be converted,
+ * i.e. it doesn't matter if you call it with a domain that's already in
+ * ASCII.
+ * @memberOf punycode
+ * @param {String} input The domain name or email address to convert, as a
+ * Unicode string.
+ * @returns {String} The Punycode representation of the given domain name or
+ * email address.
+ */
+var toASCII = function toASCII(input) {
+ return mapDomain(input, function (string) {
+ return regexNonASCII.test(string) ? 'xn--' + encode(string) : string;
+ });
+};
+
+/*--------------------------------------------------------------------------*/
+
+/** Define the public API */
+var punycode = {
+ /**
+ * A string representing the current Punycode.js version number.
+ * @memberOf punycode
+ * @type String
+ */
+ 'version': '2.1.0',
+ /**
+ * An object of methods to convert from JavaScript's internal character
+ * representation (UCS-2) to Unicode code points, and back.
+ * @see
+ * @memberOf punycode
+ * @type Object
+ */
+ 'ucs2': {
+ 'decode': ucs2decode,
+ 'encode': ucs2encode
+ },
+ 'decode': decode,
+ 'encode': encode,
+ 'toASCII': toASCII,
+ 'toUnicode': toUnicode
+};
+
+/**
+ * URI.js
+ *
+ * @fileoverview An RFC 3986 compliant, scheme extendable URI parsing/validating/resolving library for JavaScript.
+ * @author Gary Court
+ * @see http://github.com/garycourt/uri-js
+ */
+/**
+ * Copyright 2011 Gary Court. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of Gary Court.
+ */
+var SCHEMES = {};
+function pctEncChar(chr) {
+ var c = chr.charCodeAt(0);
+ var e = void 0;
+ if (c < 16) e = "%0" + c.toString(16).toUpperCase();else if (c < 128) e = "%" + c.toString(16).toUpperCase();else if (c < 2048) e = "%" + (c >> 6 | 192).toString(16).toUpperCase() + "%" + (c & 63 | 128).toString(16).toUpperCase();else e = "%" + (c >> 12 | 224).toString(16).toUpperCase() + "%" + (c >> 6 & 63 | 128).toString(16).toUpperCase() + "%" + (c & 63 | 128).toString(16).toUpperCase();
+ return e;
+}
+function pctDecChars(str) {
+ var newStr = "";
+ var i = 0;
+ var il = str.length;
+ while (i < il) {
+ var c = parseInt(str.substr(i + 1, 2), 16);
+ if (c < 128) {
+ newStr += String.fromCharCode(c);
+ i += 3;
+ } else if (c >= 194 && c < 224) {
+ if (il - i >= 6) {
+ var c2 = parseInt(str.substr(i + 4, 2), 16);
+ newStr += String.fromCharCode((c & 31) << 6 | c2 & 63);
+ } else {
+ newStr += str.substr(i, 6);
+ }
+ i += 6;
+ } else if (c >= 224) {
+ if (il - i >= 9) {
+ var _c = parseInt(str.substr(i + 4, 2), 16);
+ var c3 = parseInt(str.substr(i + 7, 2), 16);
+ newStr += String.fromCharCode((c & 15) << 12 | (_c & 63) << 6 | c3 & 63);
+ } else {
+ newStr += str.substr(i, 9);
+ }
+ i += 9;
+ } else {
+ newStr += str.substr(i, 3);
+ i += 3;
+ }
+ }
+ return newStr;
+}
+function _normalizeComponentEncoding(components, protocol) {
+ function decodeUnreserved(str) {
+ var decStr = pctDecChars(str);
+ return !decStr.match(protocol.UNRESERVED) ? str : decStr;
+ }
+ if (components.scheme) components.scheme = String(components.scheme).replace(protocol.PCT_ENCODED, decodeUnreserved).toLowerCase().replace(protocol.NOT_SCHEME, "");
+ if (components.userinfo !== undefined) components.userinfo = String(components.userinfo).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_USERINFO, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
+ if (components.host !== undefined) components.host = String(components.host).replace(protocol.PCT_ENCODED, decodeUnreserved).toLowerCase().replace(protocol.NOT_HOST, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
+ if (components.path !== undefined) components.path = String(components.path).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(components.scheme ? protocol.NOT_PATH : protocol.NOT_PATH_NOSCHEME, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
+ if (components.query !== undefined) components.query = String(components.query).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_QUERY, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
+ if (components.fragment !== undefined) components.fragment = String(components.fragment).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_FRAGMENT, pctEncChar).replace(protocol.PCT_ENCODED, toUpperCase);
+ return components;
+}
+
+function _stripLeadingZeros(str) {
+ return str.replace(/^0*(.*)/, "$1") || "0";
+}
+function _normalizeIPv4(host, protocol) {
+ var matches = host.match(protocol.IPV4ADDRESS) || [];
+
+ var _matches = slicedToArray(matches, 2),
+ address = _matches[1];
+
+ if (address) {
+ return address.split(".").map(_stripLeadingZeros).join(".");
+ } else {
+ return host;
+ }
+}
+function _normalizeIPv6(host, protocol) {
+ var matches = host.match(protocol.IPV6ADDRESS) || [];
+
+ var _matches2 = slicedToArray(matches, 3),
+ address = _matches2[1],
+ zone = _matches2[2];
+
+ if (address) {
+ var _address$toLowerCase$ = address.toLowerCase().split('::').reverse(),
+ _address$toLowerCase$2 = slicedToArray(_address$toLowerCase$, 2),
+ last = _address$toLowerCase$2[0],
+ first = _address$toLowerCase$2[1];
+
+ var firstFields = first ? first.split(":").map(_stripLeadingZeros) : [];
+ var lastFields = last.split(":").map(_stripLeadingZeros);
+ var isLastFieldIPv4Address = protocol.IPV4ADDRESS.test(lastFields[lastFields.length - 1]);
+ var fieldCount = isLastFieldIPv4Address ? 7 : 8;
+ var lastFieldsStart = lastFields.length - fieldCount;
+ var fields = Array(fieldCount);
+ for (var x = 0; x < fieldCount; ++x) {
+ fields[x] = firstFields[x] || lastFields[lastFieldsStart + x] || '';
+ }
+ if (isLastFieldIPv4Address) {
+ fields[fieldCount - 1] = _normalizeIPv4(fields[fieldCount - 1], protocol);
+ }
+ var allZeroFields = fields.reduce(function (acc, field, index) {
+ if (!field || field === "0") {
+ var lastLongest = acc[acc.length - 1];
+ if (lastLongest && lastLongest.index + lastLongest.length === index) {
+ lastLongest.length++;
+ } else {
+ acc.push({ index: index, length: 1 });
+ }
+ }
+ return acc;
+ }, []);
+ var longestZeroFields = allZeroFields.sort(function (a, b) {
+ return b.length - a.length;
+ })[0];
+ var newHost = void 0;
+ if (longestZeroFields && longestZeroFields.length > 1) {
+ var newFirst = fields.slice(0, longestZeroFields.index);
+ var newLast = fields.slice(longestZeroFields.index + longestZeroFields.length);
+ newHost = newFirst.join(":") + "::" + newLast.join(":");
+ } else {
+ newHost = fields.join(":");
+ }
+ if (zone) {
+ newHost += "%" + zone;
+ }
+ return newHost;
+ } else {
+ return host;
+ }
+}
+var URI_PARSE = /^(?:([^:\/?#]+):)?(?:\/\/((?:([^\/?#@]*)@)?(\[[^\/?#\]]+\]|[^\/?#:]*)(?:\:(\d*))?))?([^?#]*)(?:\?([^#]*))?(?:#((?:.|\n|\r)*))?/i;
+var NO_MATCH_IS_UNDEFINED = "".match(/(){0}/)[1] === undefined;
+function parse(uriString) {
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+
+ var components = {};
+ var protocol = options.iri !== false ? IRI_PROTOCOL : URI_PROTOCOL;
+ if (options.reference === "suffix") uriString = (options.scheme ? options.scheme + ":" : "") + "//" + uriString;
+ var matches = uriString.match(URI_PARSE);
+ if (matches) {
+ if (NO_MATCH_IS_UNDEFINED) {
+ //store each component
+ components.scheme = matches[1];
+ components.userinfo = matches[3];
+ components.host = matches[4];
+ components.port = parseInt(matches[5], 10);
+ components.path = matches[6] || "";
+ components.query = matches[7];
+ components.fragment = matches[8];
+ //fix port number
+ if (isNaN(components.port)) {
+ components.port = matches[5];
+ }
+ } else {
+ //IE FIX for improper RegExp matching
+ //store each component
+ components.scheme = matches[1] || undefined;
+ components.userinfo = uriString.indexOf("@") !== -1 ? matches[3] : undefined;
+ components.host = uriString.indexOf("//") !== -1 ? matches[4] : undefined;
+ components.port = parseInt(matches[5], 10);
+ components.path = matches[6] || "";
+ components.query = uriString.indexOf("?") !== -1 ? matches[7] : undefined;
+ components.fragment = uriString.indexOf("#") !== -1 ? matches[8] : undefined;
+ //fix port number
+ if (isNaN(components.port)) {
+ components.port = uriString.match(/\/\/(?:.|\n)*\:(?:\/|\?|\#|$)/) ? matches[4] : undefined;
+ }
+ }
+ if (components.host) {
+ //normalize IP hosts
+ components.host = _normalizeIPv6(_normalizeIPv4(components.host, protocol), protocol);
+ }
+ //determine reference type
+ if (components.scheme === undefined && components.userinfo === undefined && components.host === undefined && components.port === undefined && !components.path && components.query === undefined) {
+ components.reference = "same-document";
+ } else if (components.scheme === undefined) {
+ components.reference = "relative";
+ } else if (components.fragment === undefined) {
+ components.reference = "absolute";
+ } else {
+ components.reference = "uri";
+ }
+ //check for reference errors
+ if (options.reference && options.reference !== "suffix" && options.reference !== components.reference) {
+ components.error = components.error || "URI is not a " + options.reference + " reference.";
+ }
+ //find scheme handler
+ var schemeHandler = SCHEMES[(options.scheme || components.scheme || "").toLowerCase()];
+ //check if scheme can't handle IRIs
+ if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
+ //if host component is a domain name
+ if (components.host && (options.domainHost || schemeHandler && schemeHandler.domainHost)) {
+ //convert Unicode IDN -> ASCII IDN
+ try {
+ components.host = punycode.toASCII(components.host.replace(protocol.PCT_ENCODED, pctDecChars).toLowerCase());
+ } catch (e) {
+ components.error = components.error || "Host's domain name can not be converted to ASCII via punycode: " + e;
+ }
+ }
+ //convert IRI -> URI
+ _normalizeComponentEncoding(components, URI_PROTOCOL);
+ } else {
+ //normalize encodings
+ _normalizeComponentEncoding(components, protocol);
+ }
+ //perform scheme specific parsing
+ if (schemeHandler && schemeHandler.parse) {
+ schemeHandler.parse(components, options);
+ }
+ } else {
+ components.error = components.error || "URI can not be parsed.";
+ }
+ return components;
+}
+
+function _recomposeAuthority(components, options) {
+ var protocol = options.iri !== false ? IRI_PROTOCOL : URI_PROTOCOL;
+ var uriTokens = [];
+ if (components.userinfo !== undefined) {
+ uriTokens.push(components.userinfo);
+ uriTokens.push("@");
+ }
+ if (components.host !== undefined) {
+ //normalize IP hosts, add brackets and escape zone separator for IPv6
+ uriTokens.push(_normalizeIPv6(_normalizeIPv4(String(components.host), protocol), protocol).replace(protocol.IPV6ADDRESS, function (_, $1, $2) {
+ return "[" + $1 + ($2 ? "%25" + $2 : "") + "]";
+ }));
+ }
+ if (typeof components.port === "number" || typeof components.port === "string") {
+ uriTokens.push(":");
+ uriTokens.push(String(components.port));
+ }
+ return uriTokens.length ? uriTokens.join("") : undefined;
+}
+
+var RDS1 = /^\.\.?\//;
+var RDS2 = /^\/\.(\/|$)/;
+var RDS3 = /^\/\.\.(\/|$)/;
+var RDS5 = /^\/?(?:.|\n)*?(?=\/|$)/;
+function removeDotSegments(input) {
+ var output = [];
+ while (input.length) {
+ if (input.match(RDS1)) {
+ input = input.replace(RDS1, "");
+ } else if (input.match(RDS2)) {
+ input = input.replace(RDS2, "/");
+ } else if (input.match(RDS3)) {
+ input = input.replace(RDS3, "/");
+ output.pop();
+ } else if (input === "." || input === "..") {
+ input = "";
+ } else {
+ var im = input.match(RDS5);
+ if (im) {
+ var s = im[0];
+ input = input.slice(s.length);
+ output.push(s);
+ } else {
+ throw new Error("Unexpected dot segment condition");
+ }
+ }
+ }
+ return output.join("");
+}
+
+function serialize(components) {
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+
+ var protocol = options.iri ? IRI_PROTOCOL : URI_PROTOCOL;
+ var uriTokens = [];
+ //find scheme handler
+ var schemeHandler = SCHEMES[(options.scheme || components.scheme || "").toLowerCase()];
+ //perform scheme specific serialization
+ if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(components, options);
+ if (components.host) {
+ //if host component is an IPv6 address
+ if (protocol.IPV6ADDRESS.test(components.host)) {}
+ //TODO: normalize IPv6 address as per RFC 5952
+
+ //if host component is a domain name
+ else if (options.domainHost || schemeHandler && schemeHandler.domainHost) {
+ //convert IDN via punycode
+ try {
+ components.host = !options.iri ? punycode.toASCII(components.host.replace(protocol.PCT_ENCODED, pctDecChars).toLowerCase()) : punycode.toUnicode(components.host);
+ } catch (e) {
+ components.error = components.error || "Host's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e;
+ }
+ }
+ }
+ //normalize encoding
+ _normalizeComponentEncoding(components, protocol);
+ if (options.reference !== "suffix" && components.scheme) {
+ uriTokens.push(components.scheme);
+ uriTokens.push(":");
+ }
+ var authority = _recomposeAuthority(components, options);
+ if (authority !== undefined) {
+ if (options.reference !== "suffix") {
+ uriTokens.push("//");
+ }
+ uriTokens.push(authority);
+ if (components.path && components.path.charAt(0) !== "/") {
+ uriTokens.push("/");
+ }
+ }
+ if (components.path !== undefined) {
+ var s = components.path;
+ if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
+ s = removeDotSegments(s);
+ }
+ if (authority === undefined) {
+ s = s.replace(/^\/\//, "/%2F"); //don't allow the path to start with "//"
+ }
+ uriTokens.push(s);
+ }
+ if (components.query !== undefined) {
+ uriTokens.push("?");
+ uriTokens.push(components.query);
+ }
+ if (components.fragment !== undefined) {
+ uriTokens.push("#");
+ uriTokens.push(components.fragment);
+ }
+ return uriTokens.join(""); //merge tokens into a string
+}
+
+function resolveComponents(base, relative) {
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
+ var skipNormalization = arguments[3];
+
+ var target = {};
+ if (!skipNormalization) {
+ base = parse(serialize(base, options), options); //normalize base components
+ relative = parse(serialize(relative, options), options); //normalize relative components
+ }
+ options = options || {};
+ if (!options.tolerant && relative.scheme) {
+ target.scheme = relative.scheme;
+ //target.authority = relative.authority;
+ target.userinfo = relative.userinfo;
+ target.host = relative.host;
+ target.port = relative.port;
+ target.path = removeDotSegments(relative.path || "");
+ target.query = relative.query;
+ } else {
+ if (relative.userinfo !== undefined || relative.host !== undefined || relative.port !== undefined) {
+ //target.authority = relative.authority;
+ target.userinfo = relative.userinfo;
+ target.host = relative.host;
+ target.port = relative.port;
+ target.path = removeDotSegments(relative.path || "");
+ target.query = relative.query;
+ } else {
+ if (!relative.path) {
+ target.path = base.path;
+ if (relative.query !== undefined) {
+ target.query = relative.query;
+ } else {
+ target.query = base.query;
+ }
+ } else {
+ if (relative.path.charAt(0) === "/") {
+ target.path = removeDotSegments(relative.path);
+ } else {
+ if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
+ target.path = "/" + relative.path;
+ } else if (!base.path) {
+ target.path = relative.path;
+ } else {
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
+ }
+ target.path = removeDotSegments(target.path);
+ }
+ target.query = relative.query;
+ }
+ //target.authority = base.authority;
+ target.userinfo = base.userinfo;
+ target.host = base.host;
+ target.port = base.port;
+ }
+ target.scheme = base.scheme;
+ }
+ target.fragment = relative.fragment;
+ return target;
+}
+
+function resolve(baseURI, relativeURI, options) {
+ var schemelessOptions = assign({ scheme: 'null' }, options);
+ return serialize(resolveComponents(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true), schemelessOptions);
+}
+
+function normalize(uri, options) {
+ if (typeof uri === "string") {
+ uri = serialize(parse(uri, options), options);
+ } else if (typeOf(uri) === "object") {
+ uri = parse(serialize(uri, options), options);
+ }
+ return uri;
+}
+
+function equal(uriA, uriB, options) {
+ if (typeof uriA === "string") {
+ uriA = serialize(parse(uriA, options), options);
+ } else if (typeOf(uriA) === "object") {
+ uriA = serialize(uriA, options);
+ }
+ if (typeof uriB === "string") {
+ uriB = serialize(parse(uriB, options), options);
+ } else if (typeOf(uriB) === "object") {
+ uriB = serialize(uriB, options);
+ }
+ return uriA === uriB;
+}
+
+function escapeComponent(str, options) {
+ return str && str.toString().replace(!options || !options.iri ? URI_PROTOCOL.ESCAPE : IRI_PROTOCOL.ESCAPE, pctEncChar);
+}
+
+function unescapeComponent(str, options) {
+ return str && str.toString().replace(!options || !options.iri ? URI_PROTOCOL.PCT_ENCODED : IRI_PROTOCOL.PCT_ENCODED, pctDecChars);
+}
+
+var handler = {
+ scheme: "http",
+ domainHost: true,
+ parse: function parse(components, options) {
+ //report missing host
+ if (!components.host) {
+ components.error = components.error || "HTTP URIs must have a host.";
+ }
+ return components;
+ },
+ serialize: function serialize(components, options) {
+ var secure = String(components.scheme).toLowerCase() === "https";
+ //normalize the default port
+ if (components.port === (secure ? 443 : 80) || components.port === "") {
+ components.port = undefined;
+ }
+ //normalize the empty path
+ if (!components.path) {
+ components.path = "/";
+ }
+ //NOTE: We do not parse query strings for HTTP URIs
+ //as WWW Form Url Encoded query strings are part of the HTML4+ spec,
+ //and not the HTTP spec.
+ return components;
+ }
+};
+
+var handler$1 = {
+ scheme: "https",
+ domainHost: handler.domainHost,
+ parse: handler.parse,
+ serialize: handler.serialize
+};
+
+function isSecure(wsComponents) {
+ return typeof wsComponents.secure === 'boolean' ? wsComponents.secure : String(wsComponents.scheme).toLowerCase() === "wss";
+}
+//RFC 6455
+var handler$2 = {
+ scheme: "ws",
+ domainHost: true,
+ parse: function parse(components, options) {
+ var wsComponents = components;
+ //indicate if the secure flag is set
+ wsComponents.secure = isSecure(wsComponents);
+ //construct resouce name
+ wsComponents.resourceName = (wsComponents.path || '/') + (wsComponents.query ? '?' + wsComponents.query : '');
+ wsComponents.path = undefined;
+ wsComponents.query = undefined;
+ return wsComponents;
+ },
+ serialize: function serialize(wsComponents, options) {
+ //normalize the default port
+ if (wsComponents.port === (isSecure(wsComponents) ? 443 : 80) || wsComponents.port === "") {
+ wsComponents.port = undefined;
+ }
+ //ensure scheme matches secure flag
+ if (typeof wsComponents.secure === 'boolean') {
+ wsComponents.scheme = wsComponents.secure ? 'wss' : 'ws';
+ wsComponents.secure = undefined;
+ }
+ //reconstruct path from resource name
+ if (wsComponents.resourceName) {
+ var _wsComponents$resourc = wsComponents.resourceName.split('?'),
+ _wsComponents$resourc2 = slicedToArray(_wsComponents$resourc, 2),
+ path = _wsComponents$resourc2[0],
+ query = _wsComponents$resourc2[1];
+
+ wsComponents.path = path && path !== '/' ? path : undefined;
+ wsComponents.query = query;
+ wsComponents.resourceName = undefined;
+ }
+ //forbid fragment component
+ wsComponents.fragment = undefined;
+ return wsComponents;
+ }
+};
+
+var handler$3 = {
+ scheme: "wss",
+ domainHost: handler$2.domainHost,
+ parse: handler$2.parse,
+ serialize: handler$2.serialize
+};
+
+var O = {};
+var isIRI = true;
+//RFC 3986
+var UNRESERVED$$ = "[A-Za-z0-9\\-\\.\\_\\~" + (isIRI ? "\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF" : "") + "]";
+var HEXDIG$$ = "[0-9A-Fa-f]"; //case-insensitive
+var PCT_ENCODED$ = subexp(subexp("%[EFef]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%[89A-Fa-f]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%" + HEXDIG$$ + HEXDIG$$)); //expanded
+//RFC 5322, except these symbols as per RFC 6068: @ : / ? # [ ] & ; =
+//const ATEXT$$ = "[A-Za-z0-9\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~]";
+//const WSP$$ = "[\\x20\\x09]";
+//const OBS_QTEXT$$ = "[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]"; //(%d1-8 / %d11-12 / %d14-31 / %d127)
+//const QTEXT$$ = merge("[\\x21\\x23-\\x5B\\x5D-\\x7E]", OBS_QTEXT$$); //%d33 / %d35-91 / %d93-126 / obs-qtext
+//const VCHAR$$ = "[\\x21-\\x7E]";
+//const WSP$$ = "[\\x20\\x09]";
+//const OBS_QP$ = subexp("\\\\" + merge("[\\x00\\x0D\\x0A]", OBS_QTEXT$$)); //%d0 / CR / LF / obs-qtext
+//const FWS$ = subexp(subexp(WSP$$ + "*" + "\\x0D\\x0A") + "?" + WSP$$ + "+");
+//const QUOTED_PAIR$ = subexp(subexp("\\\\" + subexp(VCHAR$$ + "|" + WSP$$)) + "|" + OBS_QP$);
+//const QUOTED_STRING$ = subexp('\\"' + subexp(FWS$ + "?" + QCONTENT$) + "*" + FWS$ + "?" + '\\"');
+var ATEXT$$ = "[A-Za-z0-9\\!\\$\\%\\'\\*\\+\\-\\^\\_\\`\\{\\|\\}\\~]";
+var QTEXT$$ = "[\\!\\$\\%\\'\\(\\)\\*\\+\\,\\-\\.0-9\\<\\>A-Z\\x5E-\\x7E]";
+var VCHAR$$ = merge(QTEXT$$, "[\\\"\\\\]");
+var SOME_DELIMS$$ = "[\\!\\$\\'\\(\\)\\*\\+\\,\\;\\:\\@]";
+var UNRESERVED = new RegExp(UNRESERVED$$, "g");
+var PCT_ENCODED = new RegExp(PCT_ENCODED$, "g");
+var NOT_LOCAL_PART = new RegExp(merge("[^]", ATEXT$$, "[\\.]", '[\\"]', VCHAR$$), "g");
+var NOT_HFNAME = new RegExp(merge("[^]", UNRESERVED$$, SOME_DELIMS$$), "g");
+var NOT_HFVALUE = NOT_HFNAME;
+function decodeUnreserved(str) {
+ var decStr = pctDecChars(str);
+ return !decStr.match(UNRESERVED) ? str : decStr;
+}
+var handler$4 = {
+ scheme: "mailto",
+ parse: function parse$$1(components, options) {
+ var mailtoComponents = components;
+ var to = mailtoComponents.to = mailtoComponents.path ? mailtoComponents.path.split(",") : [];
+ mailtoComponents.path = undefined;
+ if (mailtoComponents.query) {
+ var unknownHeaders = false;
+ var headers = {};
+ var hfields = mailtoComponents.query.split("&");
+ for (var x = 0, xl = hfields.length; x < xl; ++x) {
+ var hfield = hfields[x].split("=");
+ switch (hfield[0]) {
+ case "to":
+ var toAddrs = hfield[1].split(",");
+ for (var _x = 0, _xl = toAddrs.length; _x < _xl; ++_x) {
+ to.push(toAddrs[_x]);
+ }
+ break;
+ case "subject":
+ mailtoComponents.subject = unescapeComponent(hfield[1], options);
+ break;
+ case "body":
+ mailtoComponents.body = unescapeComponent(hfield[1], options);
+ break;
+ default:
+ unknownHeaders = true;
+ headers[unescapeComponent(hfield[0], options)] = unescapeComponent(hfield[1], options);
+ break;
+ }
+ }
+ if (unknownHeaders) mailtoComponents.headers = headers;
+ }
+ mailtoComponents.query = undefined;
+ for (var _x2 = 0, _xl2 = to.length; _x2 < _xl2; ++_x2) {
+ var addr = to[_x2].split("@");
+ addr[0] = unescapeComponent(addr[0]);
+ if (!options.unicodeSupport) {
+ //convert Unicode IDN -> ASCII IDN
+ try {
+ addr[1] = punycode.toASCII(unescapeComponent(addr[1], options).toLowerCase());
+ } catch (e) {
+ mailtoComponents.error = mailtoComponents.error || "Email address's domain name can not be converted to ASCII via punycode: " + e;
+ }
+ } else {
+ addr[1] = unescapeComponent(addr[1], options).toLowerCase();
+ }
+ to[_x2] = addr.join("@");
+ }
+ return mailtoComponents;
+ },
+ serialize: function serialize$$1(mailtoComponents, options) {
+ var components = mailtoComponents;
+ var to = toArray(mailtoComponents.to);
+ if (to) {
+ for (var x = 0, xl = to.length; x < xl; ++x) {
+ var toAddr = String(to[x]);
+ var atIdx = toAddr.lastIndexOf("@");
+ var localPart = toAddr.slice(0, atIdx).replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_LOCAL_PART, pctEncChar);
+ var domain = toAddr.slice(atIdx + 1);
+ //convert IDN via punycode
+ try {
+ domain = !options.iri ? punycode.toASCII(unescapeComponent(domain, options).toLowerCase()) : punycode.toUnicode(domain);
+ } catch (e) {
+ components.error = components.error || "Email address's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e;
+ }
+ to[x] = localPart + "@" + domain;
+ }
+ components.path = to.join(",");
+ }
+ var headers = mailtoComponents.headers = mailtoComponents.headers || {};
+ if (mailtoComponents.subject) headers["subject"] = mailtoComponents.subject;
+ if (mailtoComponents.body) headers["body"] = mailtoComponents.body;
+ var fields = [];
+ for (var name in headers) {
+ if (headers[name] !== O[name]) {
+ fields.push(name.replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFNAME, pctEncChar) + "=" + headers[name].replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFVALUE, pctEncChar));
+ }
+ }
+ if (fields.length) {
+ components.query = fields.join("&");
+ }
+ return components;
+ }
+};
+
+var URN_PARSE = /^([^\:]+)\:(.*)/;
+//RFC 2141
+var handler$5 = {
+ scheme: "urn",
+ parse: function parse$$1(components, options) {
+ var matches = components.path && components.path.match(URN_PARSE);
+ var urnComponents = components;
+ if (matches) {
+ var scheme = options.scheme || urnComponents.scheme || "urn";
+ var nid = matches[1].toLowerCase();
+ var nss = matches[2];
+ var urnScheme = scheme + ":" + (options.nid || nid);
+ var schemeHandler = SCHEMES[urnScheme];
+ urnComponents.nid = nid;
+ urnComponents.nss = nss;
+ urnComponents.path = undefined;
+ if (schemeHandler) {
+ urnComponents = schemeHandler.parse(urnComponents, options);
+ }
+ } else {
+ urnComponents.error = urnComponents.error || "URN can not be parsed.";
+ }
+ return urnComponents;
+ },
+ serialize: function serialize$$1(urnComponents, options) {
+ var scheme = options.scheme || urnComponents.scheme || "urn";
+ var nid = urnComponents.nid;
+ var urnScheme = scheme + ":" + (options.nid || nid);
+ var schemeHandler = SCHEMES[urnScheme];
+ if (schemeHandler) {
+ urnComponents = schemeHandler.serialize(urnComponents, options);
+ }
+ var uriComponents = urnComponents;
+ var nss = urnComponents.nss;
+ uriComponents.path = (nid || options.nid) + ":" + nss;
+ return uriComponents;
+ }
+};
+
+var UUID = /^[0-9A-Fa-f]{8}(?:\-[0-9A-Fa-f]{4}){3}\-[0-9A-Fa-f]{12}$/;
+//RFC 4122
+var handler$6 = {
+ scheme: "urn:uuid",
+ parse: function parse(urnComponents, options) {
+ var uuidComponents = urnComponents;
+ uuidComponents.uuid = uuidComponents.nss;
+ uuidComponents.nss = undefined;
+ if (!options.tolerant && (!uuidComponents.uuid || !uuidComponents.uuid.match(UUID))) {
+ uuidComponents.error = uuidComponents.error || "UUID is not valid.";
+ }
+ return uuidComponents;
+ },
+ serialize: function serialize(uuidComponents, options) {
+ var urnComponents = uuidComponents;
+ //normalize UUID
+ urnComponents.nss = (uuidComponents.uuid || "").toLowerCase();
+ return urnComponents;
+ }
+};
+
+SCHEMES[handler.scheme] = handler;
+SCHEMES[handler$1.scheme] = handler$1;
+SCHEMES[handler$2.scheme] = handler$2;
+SCHEMES[handler$3.scheme] = handler$3;
+SCHEMES[handler$4.scheme] = handler$4;
+SCHEMES[handler$5.scheme] = handler$5;
+SCHEMES[handler$6.scheme] = handler$6;
+
+exports.SCHEMES = SCHEMES;
+exports.pctEncChar = pctEncChar;
+exports.pctDecChars = pctDecChars;
+exports.parse = parse;
+exports.removeDotSegments = removeDotSegments;
+exports.serialize = serialize;
+exports.resolveComponents = resolveComponents;
+exports.resolve = resolve;
+exports.normalize = normalize;
+exports.equal = equal;
+exports.escapeComponent = escapeComponent;
+exports.unescapeComponent = unescapeComponent;
+
+Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
+
+
+},{}]},{},[2])(2)
+});
+
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJMZXhDb2RlSG9va1Jlc3BvbnNlU2NoZW1hLmpzb24iLCJWYWxpZGF0ZUxhbWJkYVJlc3BvbnNlLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0LzIwMTkuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvY29tcGlsZS9jb2RlZ2VuL2NvZGUuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvY29tcGlsZS9jb2RlZ2VuL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L2NvbXBpbGUvY29kZWdlbi9zY29wZS5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC9jb21waWxlL2Vycm9ycy5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC9jb21waWxlL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L2NvbXBpbGUvbmFtZXMuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvY29tcGlsZS9yZWZfZXJyb3IuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvY29tcGlsZS9yZXNvbHZlLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L2NvbXBpbGUvcnVsZXMuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvY29tcGlsZS91dGlsLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L2NvbXBpbGUvdmFsaWRhdGUvYXBwbGljYWJpbGl0eS5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC9jb21waWxlL3ZhbGlkYXRlL2Jvb2xTY2hlbWEuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvY29tcGlsZS92YWxpZGF0ZS9kYXRhVHlwZS5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC9jb21waWxlL3ZhbGlkYXRlL2RlZmF1bHRzLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L2NvbXBpbGUvdmFsaWRhdGUvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvY29tcGlsZS92YWxpZGF0ZS9rZXl3b3JkLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L2NvbXBpbGUvdmFsaWRhdGUvc3Vic2NoZW1hLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L2NvcmUuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvcmVmcy9kYXRhLmpzb24iLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvcmVmcy9qc29uLXNjaGVtYS0yMDE5LTA5L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3JlZnMvanNvbi1zY2hlbWEtMjAxOS0wOS9tZXRhL2FwcGxpY2F0b3IuanNvbiIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC9yZWZzL2pzb24tc2NoZW1hLTIwMTktMDkvbWV0YS9jb250ZW50Lmpzb24iLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvcmVmcy9qc29uLXNjaGVtYS0yMDE5LTA5L21ldGEvY29yZS5qc29uIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3JlZnMvanNvbi1zY2hlbWEtMjAxOS0wOS9tZXRhL2Zvcm1hdC5qc29uIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3JlZnMvanNvbi1zY2hlbWEtMjAxOS0wOS9tZXRhL21ldGEtZGF0YS5qc29uIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3JlZnMvanNvbi1zY2hlbWEtMjAxOS0wOS9tZXRhL3ZhbGlkYXRpb24uanNvbiIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC9yZWZzL2pzb24tc2NoZW1hLTIwMTktMDkvc2NoZW1hLmpzb24iLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvcnVudGltZS9lcXVhbC5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC9ydW50aW1lL3VjczJsZW5ndGguanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvcnVudGltZS91cmkuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3QvcnVudGltZS92YWxpZGF0aW9uX2Vycm9yLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy9hcHBsaWNhdG9yL2FkZGl0aW9uYWxJdGVtcy5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvYXBwbGljYXRvci9hZGRpdGlvbmFsUHJvcGVydGllcy5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvYXBwbGljYXRvci9hbGxPZi5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvYXBwbGljYXRvci9hbnlPZi5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvYXBwbGljYXRvci9jb250YWlucy5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvYXBwbGljYXRvci9kZXBlbmRlbmNpZXMuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL2FwcGxpY2F0b3IvZGVwZW5kZW50U2NoZW1hcy5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvYXBwbGljYXRvci9pZi5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvYXBwbGljYXRvci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvYXBwbGljYXRvci9pdGVtcy5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvYXBwbGljYXRvci9pdGVtczIwMjAuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL2FwcGxpY2F0b3Ivbm90LmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy9hcHBsaWNhdG9yL29uZU9mLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy9hcHBsaWNhdG9yL3BhdHRlcm5Qcm9wZXJ0aWVzLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy9hcHBsaWNhdG9yL3ByZWZpeEl0ZW1zLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy9hcHBsaWNhdG9yL3Byb3BlcnRpZXMuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL2FwcGxpY2F0b3IvcHJvcGVydHlOYW1lcy5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvYXBwbGljYXRvci90aGVuRWxzZS5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvY29kZS5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvY29yZS9pZC5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvY29yZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvY29yZS9yZWYuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL2Rpc2NyaW1pbmF0b3IvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL2Rpc2NyaW1pbmF0b3IvdHlwZXMuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL2RyYWZ0Ny5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvZHluYW1pYy9keW5hbWljQW5jaG9yLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy9keW5hbWljL2R5bmFtaWNSZWYuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL2R5bmFtaWMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL2R5bmFtaWMvcmVjdXJzaXZlQW5jaG9yLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy9keW5hbWljL3JlY3Vyc2l2ZVJlZi5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvZm9ybWF0L2Zvcm1hdC5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvZm9ybWF0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy9tZXRhZGF0YS5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvbmV4dC5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvdW5ldmFsdWF0ZWQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL3VuZXZhbHVhdGVkL3VuZXZhbHVhdGVkSXRlbXMuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL3VuZXZhbHVhdGVkL3VuZXZhbHVhdGVkUHJvcGVydGllcy5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvdmFsaWRhdGlvbi9jb25zdC5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvdmFsaWRhdGlvbi9kZXBlbmRlbnRSZXF1aXJlZC5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvdmFsaWRhdGlvbi9lbnVtLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy92YWxpZGF0aW9uL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy92YWxpZGF0aW9uL2xpbWl0Q29udGFpbnMuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL3ZhbGlkYXRpb24vbGltaXRJdGVtcy5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvdmFsaWRhdGlvbi9saW1pdExlbmd0aC5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvdmFsaWRhdGlvbi9saW1pdE51bWJlci5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvdmFsaWRhdGlvbi9saW1pdFByb3BlcnRpZXMuanMiLCJub2RlX21vZHVsZXMvYWp2L2Rpc3Qvdm9jYWJ1bGFyaWVzL3ZhbGlkYXRpb24vbXVsdGlwbGVPZi5qcyIsIm5vZGVfbW9kdWxlcy9hanYvZGlzdC92b2NhYnVsYXJpZXMvdmFsaWRhdGlvbi9wYXR0ZXJuLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy92YWxpZGF0aW9uL3JlcXVpcmVkLmpzIiwibm9kZV9tb2R1bGVzL2Fqdi9kaXN0L3ZvY2FidWxhcmllcy92YWxpZGF0aW9uL3VuaXF1ZUl0ZW1zLmpzIiwibm9kZV9tb2R1bGVzL2Zhc3QtZGVlcC1lcXVhbC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9qc29uLXNjaGVtYS10cmF2ZXJzZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy91cmktanMvZGlzdC9lczUvdXJpLmFsbC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDemNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDek1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4bUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsIm1vZHVsZS5leHBvcnRzPXtcbiAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9MZXhDb2RlSG9va1Jlc3BvbnNlXCIsXG4gIFwiJHNjaGVtYVwiOiBcImh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMTktMDkvc2NoZW1hXCIsXG4gIFwiZGVmaW5pdGlvbnNcIjoge1xuICAgIFwiQWN0aXZlQ29udGV4dFwiOiB7XG4gICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IGZhbHNlLFxuICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgXCJjb250ZXh0QXR0cmlidXRlc1wiOiB7XG4gICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPkEgbGlzdCBvZiBjb250ZXh0cyBhY3RpdmUgZm9yIHRoZSByZXF1ZXN0LiBBIGNvbnRleHQgY2FuIGJlIGFjdGl2YXRlZCB3aGVuIGEgcHJldmlvdXMgaW50ZW50IGlzIGZ1bGZpbGxlZCwgb3IgYnkgaW5jbHVkaW5nIHRoZSBjb250ZXh0IGluIHRoZSByZXF1ZXN0LjwvcD4gPHA+SWYgeW91IGRvbid0IHNwZWNpZnkgYSBsaXN0IG9mIGNvbnRleHRzLCBBbWF6b24gTGV4IFYyIHdpbGwgdXNlIHRoZSBjdXJyZW50IGxpc3Qgb2YgY29udGV4dHMgZm9yIHRoZSBzZXNzaW9uLiBJZiB5b3Ugc3BlY2lmeSBhbiBlbXB0eSBsaXN0LCBhbGwgY29udGV4dHMgZm9yIHRoZSBzZXNzaW9uIGFyZSBjbGVhcmVkLiA8L3A+XCIsXG4gICAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCJcbiAgICAgICAgfSxcbiAgICAgICAgXCJuYW1lXCI6IHtcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+VGhlIG5hbWUgb2YgdGhlIGNvbnRleHQuPC9wPlwiLFxuICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiXG4gICAgICAgIH0sXG4gICAgICAgIFwidGltZVRvTGl2ZVwiOiB7XG4gICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9BY3RpdmVDb250ZXh0VGltZVRvTGl2ZVwiLFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5JbmRpY2F0ZXMgdGhlIG51bWJlciBvZiB0dXJucyBvciBzZWNvbmRzIHRoYXQgdGhlIGNvbnRleHQgaXMgYWN0aXZlLiBPbmNlIHRoZSB0aW1lIHRvIGxpdmUgZXhwaXJlcywgdGhlIGNvbnRleHQgaXMgbm8gbG9uZ2VyIHJldHVybmVkIGluIGEgcmVzcG9uc2UuPC9wPlwiXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBcInJlcXVpcmVkXCI6IFtcbiAgICAgICAgXCJuYW1lXCIsXG4gICAgICAgIFwidGltZVRvTGl2ZVwiXG4gICAgICBdLFxuICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCJcbiAgICB9LFxuICAgIFwiQWN0aXZlQ29udGV4dFRpbWVUb0xpdmVcIjoge1xuICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiBmYWxzZSxcbiAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgIFwidGltZVRvTGl2ZUluU2Vjb25kc1wiOiB7XG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPlRoZSBudW1iZXIgb2Ygc2Vjb25kcyB0aGF0IHRoZSBjb250ZXh0IGlzIGFjdGl2ZS4gWW91IGNhbiBzcGVjaWZ5IGJldHdlZW4gNSBhbmQgODY0MDAgc2Vjb25kcyAoMjQgaG91cnMpLjwvcD5cIixcbiAgICAgICAgICBcInR5cGVcIjogXCJudW1iZXJcIlxuICAgICAgICB9LFxuICAgICAgICBcInR1cm5zVG9MaXZlXCI6IHtcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+VGhlIG51bWJlciBvZiB0dXJucyB0aGF0IHRoZSBjb250ZXh0IGlzIGFjdGl2ZS4gWW91IGNhbiBzcGVjaWZ5IHVwIHRvIDIwIHR1cm5zLiBFYWNoIHJlcXVlc3QgYW5kIHJlc3BvbnNlIGZyb20gdGhlIGJvdCBpcyBhIHR1cm4uPC9wPlwiLFxuICAgICAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBcInJlcXVpcmVkXCI6IFtcbiAgICAgICAgXCJ0dXJuc1RvTGl2ZVwiLFxuICAgICAgICBcInRpbWVUb0xpdmVJblNlY29uZHNcIlxuICAgICAgXSxcbiAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiXG4gICAgfSxcbiAgICBcIkF0dHJpYnV0ZXNcIjoge1xuICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiXG4gICAgICB9LFxuICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIk1hcCBvZiBrZXkvdmFsdWUgcGFpcnNcIixcbiAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiXG4gICAgfSxcbiAgICBcIkJ1dHRvblwiOiB7XG4gICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IGZhbHNlLFxuICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgXCJ0ZXh0XCI6IHtcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+VGhlIHRleHQgdGhhdCBpcyBkaXNwbGF5ZWQgb24gdGhlIGJ1dHRvbi48L3A+XCIsXG4gICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCJcbiAgICAgICAgfSxcbiAgICAgICAgXCJ2YWx1ZVwiOiB7XG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPlRoZSB2YWx1ZSByZXR1cm5lZCB0byBBbWF6b24gTGV4IFYyIHdoZW4gYSB1c2VyIGNob29zZXMgdGhlIGJ1dHRvbi48L3A+XCIsXG4gICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCJcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiXG4gICAgfSxcbiAgICBcIkNvbmZpcm1hdGlvblN0YXRlXCI6IHtcbiAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgIFwiQ29uZmlybWVkXCIsXG4gICAgICAgIFwiRGVuaWVkXCIsXG4gICAgICAgIFwiTm9uZVwiXG4gICAgICBdLFxuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCJcbiAgICB9LFxuICAgIFwiRGlhbG9nQWN0aW9uXCI6IHtcbiAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogZmFsc2UsXG4gICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICBcInNsb3RFbGljaXRhdGlvblN0eWxlXCI6IHtcbiAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL1N0eWxlVHlwZVwiLFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5Db25maWd1cmVzIHRoZSBzbG90IHRvIHVzZSBzcGVsbC1ieS1sZXR0ZXIgb3Igc3BlbGwtYnktd29yZCBzdHlsZS4gV2hlbiB5b3UgdXNlIGEgc3R5bGUgb24gYSBzbG90LCB1c2VycyBjYW4gc3BlbGwgb3V0IHRoZWlyIGlucHV0IHRvIG1ha2UgaXQgY2xlYXIgdG8geW91ciBib3QuPC9wPiA8dWw+IDxsaT4gPHA+U3BlbGwgYnkgbGV0dGVyIC0gXFxcImJcXFwiIFxcXCJvXFxcIiBcXFwiYlxcXCI8L3A+IDwvbGk+IDxsaT4gPHA+U3BlbGwgYnkgd29yZCAtIFxcXCJiIGFzIGluIGJveVxcXCIgXFxcIm8gYXMgaW4gb3NjYXJcXFwiIFxcXCJiIGFzIGluIGJveVxcXCI8L3A+IDwvbGk+IDwvdWw+IDxwPkZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWUgPGEgaHJlZj1cXFwiaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2xleHYyL2xhdGVzdC9kZy91c2luZy1zcGVsbGluZy5odG1sXFxcIj4gVXNpbmcgc3BlbGxpbmcgdG8gZW50ZXIgc2xvdCB2YWx1ZXMgPC9hPi48L3A+XCJcbiAgICAgICAgfSxcbiAgICAgICAgXCJzbG90VG9FbGljaXRcIjoge1xuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5UaGUgbmFtZSBvZiB0aGUgc2xvdCB0aGF0IHNob3VsZCBiZSBlbGljaXRlZCBmcm9tIHRoZSB1c2VyLiBSZXF1aXJlZCBpZiB0aGUgdHlwZSBvZiBkaWFsb2dBY3Rpb24gaXMgRWxpY2l0U2xvdDwvcD5cIixcbiAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgICAgICB9LFxuICAgICAgICBcInN1YlNsb3RUb0VsaWNpdFwiOiB7XG4gICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9FbGljaXRTdWJTbG90XCIsXG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPlRoZSBuYW1lIG9mIHRoZSBjb25zdGl0dWVudCBzdWIgc2xvdCBvZiB0aGUgY29tcG9zaXRlIHNsb3Qgc3BlY2lmaWVkIGluIHNsb3RUb0VsaWNpdCB0aGF0IHNob3VsZCBiZSBlbGljaXRlZCBmcm9tIHRoZSB1c2VyLjwvcD5cIlxuICAgICAgICB9LFxuICAgICAgICBcInR5cGVcIjoge1xuICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvRGlhbG9nQWN0aW9uVHlwZVwiLFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5UaGUgbmV4dCBhY3Rpb24gdGhhdCB0aGUgYm90IHNob3VsZCB0YWtlIGluIGl0cyBpbnRlcmFjdGlvbiB3aXRoIHRoZSB1c2VyLiBUaGUgcG9zc2libGUgdmFsdWVzIGFyZTo8L3A+IDx1bD4gPGxpPiA8cD4gIDxjb2RlPkNsb3NlPC9jb2RlPiAtIEluZGljYXRlcyB0aGF0IHRoZXJlIHdpbGwgbm90IGJlIGEgcmVzcG9uc2UgZnJvbSB0aGUgdXNlci4gRm9yIGV4YW1wbGUsIHRoZSBzdGF0ZW1lbnQgXFxcIllvdXIgb3JkZXIgaGFzIGJlZW4gcGxhY2VkXFxcIiBkb2VzIG5vdCByZXF1aXJlIGEgcmVzcG9uc2UuPC9wPiA8L2xpPiA8bGk+IDxwPiAgPGNvZGU+Q29uZmlybUludGVudDwvY29kZT4gLSBUaGUgbmV4dCBhY3Rpb24gaXMgYXNraW5nIHRoZSB1c2VyIGlmIHRoZSBpbnRlbnQgaXMgY29tcGxldGUgYW5kIHJlYWR5IHRvIGJlIGZ1bGZpbGxlZC4gVGhpcyBpcyBhIHllcy9ubyBxdWVzdGlvbiBzdWNoIGFzIFxcXCJQbGFjZSB0aGUgb3JkZXI/XFxcIjwvcD4gPC9saT4gPGxpPiA8cD4gIDxjb2RlPkRlbGVnYXRlPC9jb2RlPiAtIFRoZSBuZXh0IGFjdGlvbiBpcyBkZXRlcm1pbmVkIGJ5IEFtYXpvbiBMZXggVjIuPC9wPiA8L2xpPiA8bGk+IDxwPiAgPGNvZGU+RWxpY2l0SW50ZW50PC9jb2RlPiAtIFRoZSBuZXh0IGFjdGlvbiBpcyB0byBlbGljaXQgYW4gaW50ZW50IGZyb20gdGhlIHVzZXIuPC9wPiA8L2xpPiA8bGk+IDxwPiAgPGNvZGU+RWxpY2l0U2xvdDwvY29kZT4gLSBUaGUgbmV4dCBhY3Rpb24gaXMgdG8gZWxpY2l0IGEgc2xvdCB2YWx1ZSBmcm9tIHRoZSB1c2VyLjwvcD4gPC9saT4gPC91bD5cIlxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgXCJyZXF1aXJlZFwiOiBbXG4gICAgICAgIFwidHlwZVwiXG4gICAgICBdLFxuICAgICAgXCJpZlwiOiB7XG4gICAgICAgIFwiYW55T2ZcIjogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwidHlwZVwiOiB7XG4gICAgICAgICAgICAgICAgXCJjb25zdFwiOiBcIkVsaWNpdFNsb3RcIlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgXCJ0aGVuXCI6IHtcbiAgICAgICAgXCJyZXF1aXJlZFwiOiBbXG4gICAgICAgICAgXCJzbG90VG9FbGljaXRcIlxuICAgICAgICBdLFxuICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgIFwic2xvdFRvRWxpY2l0XCI6IHtcbiAgICAgICAgICAgIFwibWluTGVuZ3RoXCI6IDFcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBcInR5cGVcIjogXCJvYmplY3RcIlxuICAgIH0sXG4gICAgXCJEaWFsb2dBY3Rpb25UeXBlXCI6IHtcbiAgICAgIFwiZW51bVwiOiBbXG4gICAgICAgIFwiQ2xvc2VcIixcbiAgICAgICAgXCJDb25maXJtSW50ZW50XCIsXG4gICAgICAgIFwiRGVsZWdhdGVcIixcbiAgICAgICAgXCJFbGljaXRJbnRlbnRcIixcbiAgICAgICAgXCJFbGljaXRTbG90XCIsXG4gICAgICAgIFwiTm9uZVwiXG4gICAgICBdLFxuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCJcbiAgICB9LFxuICAgIFwiRWxpY2l0U3ViU2xvdFwiOiB7XG4gICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IGZhbHNlLFxuICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgXCJuYW1lXCI6IHtcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+VGhlIG5hbWUgb2YgdGhlIHNsb3QgdGhhdCBzaG91bGQgYmUgZWxpY2l0ZWQgZnJvbSB0aGUgdXNlci48L3A+XCIsXG4gICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCJcbiAgICAgICAgfSxcbiAgICAgICAgXCJzdWJTbG90VG9FbGljaXRcIjoge1xuICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvRWxpY2l0U3ViU2xvdFwiLFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5UaGUgZmllbGQgaXMgbm90IHN1cHBvcnRlZC48L3A+XCJcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiXG4gICAgfSxcbiAgICBcIkltYWdlUmVzcG9uc2VDYXJkXCI6IHtcbiAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogZmFsc2UsXG4gICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICBcImJ1dHRvbnNcIjoge1xuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5BIGxpc3Qgb2YgYnV0dG9ucyB0aGF0IHNob3VsZCBiZSBkaXNwbGF5ZWQgb24gdGhlIHJlc3BvbnNlIGNhcmQuIFRoZSBhcnJhbmdlbWVudCBvZiB0aGUgYnV0dG9ucyBpcyBkZXRlcm1pbmVkIGJ5IHRoZSBwbGF0Zm9ybSB0aGF0IGRpc3BsYXlzIHRoZSBidXR0b24uPC9wPlwiLFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9CdXR0b25cIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ0eXBlXCI6IFwiYXJyYXlcIlxuICAgICAgICB9LFxuICAgICAgICBcImltYWdlVXJsXCI6IHtcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+VGhlIFVSTCBvZiBhbiBpbWFnZSB0byBkaXNwbGF5IG9uIHRoZSByZXNwb25zZSBjYXJkLiBUaGUgaW1hZ2UgVVJMIG11c3QgYmUgcHVibGljbHkgYXZhaWxhYmxlIHNvIHRoYXQgdGhlIHBsYXRmb3JtIGRpc3BsYXlpbmcgdGhlIHJlc3BvbnNlIGNhcmQgaGFzIGFjY2VzcyB0byB0aGUgaW1hZ2UuPC9wPlwiLFxuICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiXG4gICAgICAgIH0sXG4gICAgICAgIFwic3VidGl0bGVcIjoge1xuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5UaGUgc3VidGl0bGUgdG8gZGlzcGxheSBvbiB0aGUgcmVzcG9uc2UgY2FyZC4gVGhlIGZvcm1hdCBvZiB0aGUgc3VidGl0bGUgaXMgZGV0ZXJtaW5lZCBieSB0aGUgcGxhdGZvcm0gZGlzcGxheWluZyB0aGUgcmVzcG9uc2UgY2FyZC48L3A+XCIsXG4gICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCJcbiAgICAgICAgfSxcbiAgICAgICAgXCJ0aXRsZVwiOiB7XG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPlRoZSB0aXRsZSB0byBkaXNwbGF5IG9uIHRoZSByZXNwb25zZSBjYXJkLiBUaGUgZm9ybWF0IG9mIHRoZSB0aXRsZSBpcyBkZXRlcm1pbmVkIGJ5IHRoZSBwbGF0Zm9ybSBkaXNwbGF5aW5nIHRoZSByZXNwb25zZSBjYXJkLjwvcD5cIixcbiAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgXCJyZXF1aXJlZFwiOiBbXG4gICAgICAgIFwidGl0bGVcIlxuICAgICAgXSxcbiAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiXG4gICAgfSxcbiAgICBcIkludGVudFwiOiB7XG4gICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IGZhbHNlLFxuICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgXCJjb25maXJtYXRpb25TdGF0ZVwiOiB7XG4gICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9Db25maXJtYXRpb25TdGF0ZVwiLFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5Db250YWlucyBpbmZvcm1hdGlvbiBhYm91dCB3aGV0aGVyIGZ1bGZpbGxtZW50IG9mIHRoZSBpbnRlbnQgaGFzIGJlZW4gY29uZmlybWVkLjwvcD5cIlxuICAgICAgICB9LFxuICAgICAgICBcIm5hbWVcIjoge1xuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5UaGUgbmFtZSBvZiB0aGUgaW50ZW50LjwvcD5cIixcbiAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgICAgICB9LFxuICAgICAgICBcInNsb3RzXCI6IHtcbiAgICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvU2xvdFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+QSBtYXAgb2YgYWxsIG9mIHRoZSBzbG90cyBmb3IgdGhlIGludGVudC4gVGhlIG5hbWUgb2YgdGhlIHNsb3QgbWFwcyB0byB0aGUgdmFsdWUgb2YgdGhlIHNsb3QuIElmIGEgc2xvdCBoYXMgbm90IGJlZW4gZmlsbGVkLCB0aGUgdmFsdWUgaXMgbnVsbC48L3A+XCIsXG4gICAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCJcbiAgICAgICAgfSxcbiAgICAgICAgXCJzdGF0ZVwiOiB7XG4gICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9JbnRlbnRTdGF0ZVwiLFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5Db250YWlucyBmdWxmaWxsbWVudCBpbmZvcm1hdGlvbiBmb3IgdGhlIGludGVudC4gPC9wPlwiXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBcInR5cGVcIjogXCJvYmplY3RcIlxuICAgIH0sXG4gICAgXCJJbnRlbnRTdGF0ZVwiOiB7XG4gICAgICBcImVudW1cIjogW1xuICAgICAgICBcIkZhaWxlZFwiLFxuICAgICAgICBcIkZ1bGZpbGxlZFwiLFxuICAgICAgICBcIkluUHJvZ3Jlc3NcIixcbiAgICAgICAgXCJSZWFkeUZvckZ1bGZpbGxtZW50XCJcbiAgICAgIF0sXG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgIH0sXG4gICAgXCJMYW1iZGFDb2RlSG9va1Nlc3Npb25TdGF0ZVwiOiB7XG4gICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IGZhbHNlLFxuICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIlRoZSBMYW1iZGEgZnVuY3Rpb24gZXZlbnQgU2Vzc2lvbiBzdGF0ZSBkaWZmZXJzIGZyb20gdGhlIEFQSV9ydW50aW1lX1Nlc3Npb25TdGF0ZSBiZWNhdXNlIG9mIHRoZSBmb3JtYXQgb2YgdGhlIEludGVudFwiLFxuICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgXCJhY3RpdmVDb250ZXh0c1wiOiB7XG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPk9uZSBvciBtb3JlIGNvbnRleHRzIHRoYXQgaW5kaWNhdGUgdG8gQW1hem9uIExleCBWMiB0aGUgY29udGV4dCBvZiBhIHJlcXVlc3QuIFdoZW4gYSBjb250ZXh0IGlzIGFjdGl2ZSwgQW1hem9uIExleCBWMiBjb25zaWRlcnMgaW50ZW50cyB3aXRoIHRoZSBtYXRjaGluZyBjb250ZXh0IGFzIGEgdHJpZ2dlciBhcyB0aGUgbmV4dCBpbnRlbnQgaW4gYSBzZXNzaW9uLjwvcD5cIixcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvQWN0aXZlQ29udGV4dFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiXG4gICAgICAgIH0sXG4gICAgICAgIFwiZGlhbG9nQWN0aW9uXCI6IHtcbiAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL0RpYWxvZ0FjdGlvblwiLFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5UaGUgbmV4dCBzdGVwIHRoYXQgQW1hem9uIExleCBWMiBzaG91bGQgdGFrZSBpbiB0aGUgY29udmVyc2F0aW9uIHdpdGggYSB1c2VyLjwvcD5cIlxuICAgICAgICB9LFxuICAgICAgICBcImludGVudFwiOiB7XG4gICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9JbnRlbnRcIixcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+VGhlIGFjdGl2ZSBpbnRlbnQgdGhhdCBBbWF6b24gTGV4IFYyIGlzIHByb2Nlc3NpbmcuPC9wPlwiXG4gICAgICAgIH0sXG4gICAgICAgIFwib3JpZ2luYXRpbmdSZXF1ZXN0SWRcIjoge1xuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5BIHVuaXF1ZSBpZGVudGlmaWVyIGZvciBhIHNwZWNpZmljIHJlcXVlc3QuPC9wPlwiLFxuICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiXG4gICAgICAgIH0sXG4gICAgICAgIFwicnVudGltZUhpbnRzXCI6IHtcbiAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL1J1bnRpbWVIaW50c1wiLFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5IaW50cyBmb3IgcGhyYXNlcyB0aGF0IGEgY3VzdG9tZXIgaXMgbGlrZWx5IHRvIHVzZSBmb3IgYSBzbG90LiBBbWF6b24gTGV4IFYyIHVzZXMgdGhlIGhpbnRzIHRvIGhlbHAgZGV0ZXJtaW5lIHRoZSBjb3JyZWN0IHZhbHVlIG9mIGEgc2xvdC48L3A+XCJcbiAgICAgICAgfSxcbiAgICAgICAgXCJzZXNzaW9uQXR0cmlidXRlc1wiOiB7XG4gICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9BdHRyaWJ1dGVzXCIsXG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPk1hcCBvZiBrZXkvdmFsdWUgcGFpcnMgcmVwcmVzZW50aW5nIHNlc3Npb24tc3BlY2lmaWMgY29udGV4dCBpbmZvcm1hdGlvbi4gSXQgY29udGFpbnMgYXBwbGljYXRpb24gaW5mb3JtYXRpb24gcGFzc2VkIGJldHdlZW4gQW1hem9uIExleCBWMiBhbmQgYSBjbGllbnQgYXBwbGljYXRpb24uPC9wPlwiXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBcInJlcXVpcmVkXCI6IFtcbiAgICAgICAgXCJzZXNzaW9uQXR0cmlidXRlc1wiLFxuICAgICAgICBcImRpYWxvZ0FjdGlvblwiXG4gICAgICBdLFxuICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCJcbiAgICB9LFxuICAgIFwiTGV4Q29kZUhvb2tSZXNwb25zZVwiOiB7XG4gICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IGZhbHNlLFxuICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgXCJtZXNzYWdlc1wiOiB7XG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIk9uZSBvciBtb3JlIG1lc3NhZ2VzIHRoYXQgQW1hem9uIExleCBWMiBzaG93cyB0byB0aGUgY3VzdG9tZXIgdG8gcGVyZm9ybSB0aGUgbmV4dCB0dXJuIG9mIHRoZSBjb252ZXJzYXRpb24uIElmIHlvdSBkb24ndCBzdXBwbHkgbWVzc2FnZXMsIEFtYXpvbiBMZXggVjIgdXNlcyB0aGUgYXBwcm9wcmlhdGUgbWVzc2FnZSBkZWZpbmVkIHdoZW4gdGhlIGJvdCB3YXMgY3JlYXRlZFxcblxcblJlcXVpcmVkIGlmIGRpYWxvZ0FjdGlvbi50eXBlIGlzIEVsaWNpdEludGVudC5cIixcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvTWVzc2FnZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiXG4gICAgICAgIH0sXG4gICAgICAgIFwicmVxdWVzdEF0dHJpYnV0ZXNcIjoge1xuICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvQXR0cmlidXRlc1wiLFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJSZXF1ZXN0LXNwZWNpZmljIGF0dHJpYnV0ZXNcIlxuICAgICAgICB9LFxuICAgICAgICBcInNlc3Npb25TdGF0ZVwiOiB7XG4gICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9MYW1iZGFDb2RlSG9va1Nlc3Npb25TdGF0ZVwiLFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCJUaGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgY29udmVyc2F0aW9uIHdpdGggdGhlIHVzZXIuXFxuXFxuVGhlIGFjdHVhbCBjb250ZW50cyBvZiB0aGUgc3RydWN0dXJlIGRlcGVuZHMgb24gdGhlIHR5cGUgb2YgZGlhbG9nIGFjdGlvbi5cIlxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgXCJyZXF1aXJlZFwiOiBbXG4gICAgICAgIFwic2Vzc2lvblN0YXRlXCJcbiAgICAgIF0sXG4gICAgICBcImlmXCI6IHtcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcInNlc3Npb25TdGF0ZVwiOiB7XG4gICAgICAgICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICAgICAgICBcImRpYWxvZ0FjdGlvblwiOiB7XG4gICAgICAgICAgICAgICAgXCJwcm9wZXJ0aWVzXCIgOiB7XG4gICAgICAgICAgICAgICAgICBcInR5cGVcIjoge1xuICAgICAgICAgICAgICAgICAgICBcImNvbnN0XCI6IFwiRWxpY2l0SW50ZW50XCJcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgXCJ0aGVuXCI6IHtcbiAgICAgICAgXCJyZXF1aXJlZFwiOiBbXCJtZXNzYWdlc1wiXSxcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcIm1lc3NhZ2VzXCI6IHtcbiAgICAgICAgICAgIFwibWluSXRlbXNcIjogMVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIFwiZWxzZVwiIDoge1xuICAgICAgICBcInJlcXVpcmVkXCI6W11cbiAgICAgIH0sXG4gICAgICBcInR5cGVcIjogXCJvYmplY3RcIlxuICAgIH0sXG4gICAgXCJNZXNzYWdlXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiBmYWxzZSxcbiAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgIFwiY29udGVudFwiOiB7XG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPlRoZSB0ZXh0IG9mIHRoZSBtZXNzYWdlLjwvcD5cIixcbiAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgICAgICB9LFxuICAgICAgICBcImNvbnRlbnRUeXBlXCI6IHtcbiAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL01lc3NhZ2VDb250ZW50VHlwZVwiLFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5JbmRpY2F0ZXMgdGhlIHR5cGUgb2YgcmVzcG9uc2UuPC9wPlwiXG4gICAgICAgIH0sXG4gICAgICAgIFwiaW1hZ2VSZXNwb25zZUNhcmRcIjoge1xuICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvSW1hZ2VSZXNwb25zZUNhcmRcIixcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+QSBjYXJkIHRoYXQgaXMgc2hvd24gdG8gdGhlIHVzZXIgYnkgYSBtZXNzYWdpbmcgcGxhdGZvcm0uIFlvdSBkZWZpbmUgdGhlIGNvbnRlbnRzIG9mIHRoZSBjYXJkLCB0aGUgY2FyZCBpcyBkaXNwbGF5ZWQgYnkgdGhlIHBsYXRmb3JtLiA8L3A+IDxwPldoZW4geW91IHVzZSBhIHJlc3BvbnNlIGNhcmQsIHRoZSByZXNwb25zZSBmcm9tIHRoZSB1c2VyIGlzIGNvbnN0cmFpbmVkIHRvIHRoZSB0ZXh0IGFzc29jaWF0ZWQgd2l0aCBhIGJ1dHRvbiBvbiB0aGUgY2FyZC48L3A+XCJcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIFwicmVxdWlyZWRcIjogW1xuICAgICAgICBcImNvbnRlbnRUeXBlXCJcbiAgICAgIF0sXG4gICAgICBcImlmXCI6IHtcbiAgICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICBcImNvbnRlbnRUeXBlXCI6IHtcbiAgICAgICAgICAgIFwiY29uc3RcIjogXCJJbWFnZVJlc3BvbnNlQ2FyZFwiXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgXCJ0aGVuXCI6IHtcbiAgICAgICAgXCJyZXF1aXJlZFwiOiBbXG4gICAgICAgICAgXCJpbWFnZVJlc3BvbnNlQ2FyZFwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBcImVsc2VcIjoge1xuICAgICAgICBcInJlcXVpcmVkXCI6IFtcbiAgICAgICAgICBcImNvbnRlbnRcIlxuICAgICAgICBdXG4gICAgICB9XG4gICAgfSxcbiAgICBcIk1lc3NhZ2VDb250ZW50VHlwZVwiOiB7XG4gICAgICBcImVudW1cIjogW1xuICAgICAgICBcIkN1c3RvbVBheWxvYWRcIixcbiAgICAgICAgXCJJbWFnZVJlc3BvbnNlQ2FyZFwiLFxuICAgICAgICBcIlBsYWluVGV4dFwiLFxuICAgICAgICBcIlNTTUxcIlxuICAgICAgXSxcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiXG4gICAgfSxcbiAgICBcIlJ1bnRpbWVIaW50RGV0YWlsc1wiOiB7XG4gICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IGZhbHNlLFxuICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgXCJydW50aW1lSGludFZhbHVlc1wiOiB7XG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPk9uZSBvciBtb3JlIHN0cmluZ3MgdGhhdCBBbWF6b24gTGV4IFYyIHNob3VsZCBsb29rIGZvciBpbiB0aGUgaW5wdXQgdG8gdGhlIGJvdC4gRWFjaCBwaHJhc2UgaXMgZ2l2ZW4gcHJlZmVyZW5jZSB3aGVuIGRlY2lkaW5nIG9uIHNsb3QgdmFsdWVzLjwvcD5cIixcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvUnVudGltZUhpbnRWYWx1ZVwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiXG4gICAgICAgIH0sXG4gICAgICAgIFwic3ViU2xvdEhpbnRzXCI6IHtcbiAgICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvUnVudGltZUhpbnREZXRhaWxzXCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5BIG1hcCBvZiBjb25zdGl0dWVudCBzdWIgc2xvdCBuYW1lcyBpbnNpZGUgYSBjb21wb3NpdGUgc2xvdCBpbiB0aGUgaW50ZW50IGFuZCB0aGUgcGhyYXNlcyB0aGF0IHNob3VsZCBiZSBhZGRlZCBmb3IgZWFjaCBzdWIgc2xvdC4gSW5zaWRlIGVhY2ggY29tcG9zaXRlIHNsb3QgaGludHMsIHRoaXMgc3RydWN0dXJlIHByb3ZpZGVzIGEgbWVjaGFuaXNtIHRvIGFkZCBncmFudWxhciBzdWIgc2xvdCBwaHJhc2VzLiBPbmx5IHN1YiBzbG90IGhpbnRzIGFyZSBzdXBwb3J0ZWQgZm9yIGNvbXBvc2l0ZSBzbG90cy4gVGhlIGludGVudCBuYW1lLCBjb21wb3NpdGUgc2xvdCBuYW1lIGFuZCB0aGUgY29uc3RpdHVlbnQgc3ViIHNsb3QgbmFtZXMgbXVzdCBleGlzdC48L3A+XCIsXG4gICAgICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCJcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiXG4gICAgfSxcbiAgICBcIlJ1bnRpbWVIaW50VmFsdWVcIjoge1xuICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiBmYWxzZSxcbiAgICAgIFwicHJvcGVydGllc1wiOiB7XG4gICAgICAgIFwicGhyYXNlXCI6IHtcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+VGhlIHBocmFzZSB0aGF0IEFtYXpvbiBMZXggVjIgc2hvdWxkIGxvb2sgZm9yIGluIHRoZSB1c2VyJ3MgaW5wdXQgdG8gdGhlIGJvdC48L3A+XCIsXG4gICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCJcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiXG4gICAgfSxcbiAgICBcIlJ1bnRpbWVIaW50c1wiOiB7XG4gICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IGZhbHNlLFxuICAgICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgXCJzbG90SGludHNcIjoge1xuICAgICAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1xuICAgICAgICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvUnVudGltZUhpbnREZXRhaWxzXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPkEgbGlzdCBvZiB0aGUgc2xvdHMgaW4gdGhlIGludGVudCB0aGF0IHNob3VsZCBoYXZlIHJ1bnRpbWUgaGludHMgYWRkZWQsIGFuZCB0aGUgcGhyYXNlcyB0aGF0IHNob3VsZCBiZSBhZGRlZCBmb3IgZWFjaCBzbG90LjwvcD4gPHA+VGhlIGZpcnN0IGxldmVsIG9mIHRoZSA8Y29kZT5zbG90SGludHM8L2NvZGU+IG1hcCBpcyB0aGUgbmFtZSBvZiB0aGUgaW50ZW50LiBUaGUgc2Vjb25kIGxldmVsIGlzIHRoZSBuYW1lIG9mIHRoZSBzbG90IHdpdGhpbiB0aGUgaW50ZW50LiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlIDxhIGhyZWY9XFxcImh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9sZXh2Mi9sYXRlc3QvZGcvdXNpbmctaGludHMuaHRtbFxcXCI+VXNpbmcgaGludHMgdG8gaW1wcm92ZSBhY2N1cmFjeTwvYT4uPC9wPiA8cD5UaGUgaW50ZW50IG5hbWUgYW5kIHNsb3QgbmFtZSBtdXN0IGV4aXN0LjwvcD5cIixcbiAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIlxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCJcbiAgICB9LFxuICAgIFwiU2hhcGVcIjoge1xuICAgICAgXCJlbnVtXCI6IFtcbiAgICAgICAgXCJDb21wb3NpdGVcIixcbiAgICAgICAgXCJMaXN0XCIsXG4gICAgICAgIFwiU2NhbGFyXCJcbiAgICAgIF0sXG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgIH0sXG4gICAgXCJTbG90XCI6IHtcbiAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogZmFsc2UsXG4gICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICBcInNoYXBlXCI6IHtcbiAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL1NoYXBlXCIsXG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPldoZW4gdGhlIDxjb2RlPnNoYXBlPC9jb2RlPiB2YWx1ZSBpcyA8Y29kZT5MaXN0PC9jb2RlPiwgaXQgaW5kaWNhdGVzIHRoYXQgdGhlIDxjb2RlPnZhbHVlczwvY29kZT4gZmllbGQgY29udGFpbnMgYSBsaXN0IG9mIHNsb3QgdmFsdWVzLiBXaGVuIHRoZSB2YWx1ZSBpcyA8Y29kZT5TY2FsYXI8L2NvZGU+LCBpdCBpbmRpY2F0ZXMgdGhhdCB0aGUgPGNvZGU+dmFsdWU8L2NvZGU+IGZpZWxkIGNvbnRhaW5zIGEgc2luZ2xlIHZhbHVlLjwvcD5cIlxuICAgICAgICB9LFxuICAgICAgICBcInN1YlNsb3RzXCI6IHtcbiAgICAgICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgICAgIFwiJHJlZlwiOiBcIiMvZGVmaW5pdGlvbnMvU2xvdFwiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+VGhlIGNvbnN0aXR1ZW50IHN1YiBzbG90cyBvZiBhIGNvbXBvc2l0ZSBzbG90LjwvcD5cIixcbiAgICAgICAgICBcInR5cGVcIjogXCJvYmplY3RcIlxuICAgICAgICB9LFxuICAgICAgICBcInZhbHVlXCI6IHtcbiAgICAgICAgICBcIiRyZWZcIjogXCIjL2RlZmluaXRpb25zL1ZhbHVlXCIsXG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPlRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBzbG90LjwvcD5cIlxuICAgICAgICB9LFxuICAgICAgICBcInZhbHVlc1wiOiB7XG4gICAgICAgICAgXCJkZXNjcmlwdGlvblwiOiBcIjxwPkEgbGlzdCBvZiBvbmUgb3IgbW9yZSB2YWx1ZXMgdGhhdCB0aGUgdXNlciBwcm92aWRlZCBmb3IgdGhlIHNsb3QuIEZvciBleGFtcGxlLCBpZiBhIGZvciBhIHNsb3QgdGhhdCBlbGljaXRzIHBpenphIHRvcHBpbmdzLCB0aGUgdmFsdWVzIG1pZ2h0IGJlIFxcXCJwZXBwZXJvbmlcXFwiIGFuZCBcXFwicGluZWFwcGxlLlxcXCIgPC9wPlwiLFxuICAgICAgICAgIFwiaXRlbXNcIjoge1xuICAgICAgICAgICAgXCIkcmVmXCI6IFwiIy9kZWZpbml0aW9ucy9TbG90XCJcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwidHlwZVwiOiBcImFycmF5XCJcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIFwidHlwZVwiOiBbXCJvYmplY3RcIiwgXCJudWxsXCJdXG4gICAgfSxcbiAgICBcIlN0eWxlVHlwZVwiOiB7XG4gICAgICBcImVudW1cIjogW1xuICAgICAgICBcIkRlZmF1bHRcIixcbiAgICAgICAgXCJTcGVsbEJ5TGV0dGVyXCIsXG4gICAgICAgIFwiU3BlbGxCeVdvcmRcIlxuICAgICAgXSxcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiXG4gICAgfSxcbiAgICBcIlZhbHVlXCI6IHtcbiAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjogZmFsc2UsXG4gICAgICBcInByb3BlcnRpZXNcIjoge1xuICAgICAgICBcImludGVycHJldGVkVmFsdWVcIjoge1xuICAgICAgICAgIFwiZGVzY3JpcHRpb25cIjogXCI8cD5UaGUgdmFsdWUgdGhhdCBBbWF6b24gTGV4IFYyIGRldGVybWluZXMgZm9yIHRoZSBzbG90LiBUaGUgYWN0dWFsIHZhbHVlIGRlcGVuZHMgb24gdGhlIHNldHRpbmcgb2YgdGhlIHZhbHVlIHNlbGVjdGlvbiBzdHJhdGVneSBmb3IgdGhlIGJvdC4gWW91IGNhbiBjaG9vc2UgdG8gdXNlIHRoZSB2YWx1ZSBlbnRlcmVkIGJ5IHRoZSB1c2VyLCBvciB5b3UgY2FuIGhhdmUgQW1hem9uIExleCBWMiBjaG9vc2UgdGhlIGZpcnN0IHZhbHVlIGluIHRoZSA8Y29kZT5yZXNvbHZlZFZhbHVlczwvY29kZT4gbGlzdC48L3A+XCIsXG4gICAgICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCJcbiAgICAgICAgfSxcbiAgICAgICAgXCJvcmlnaW5hbFZhbHVlXCI6IHtcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+VGhlIHRleHQgb2YgdGhlIHV0dGVyYW5jZSBmcm9tIHRoZSB1c2VyIHRoYXQgd2FzIGVudGVyZWQgZm9yIHRoZSBzbG90LjwvcD5cIixcbiAgICAgICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgICAgICB9LFxuICAgICAgICBcInJlc29sdmVkVmFsdWVzXCI6IHtcbiAgICAgICAgICBcImRlc2NyaXB0aW9uXCI6IFwiPHA+QSBsaXN0IG9mIGFkZGl0aW9uYWwgdmFsdWVzIHRoYXQgaGF2ZSBiZWVuIHJlY29nbml6ZWQgZm9yIHRoZSBzbG90LjwvcD5cIixcbiAgICAgICAgICBcIml0ZW1zXCI6IHtcbiAgICAgICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiXG4gICAgICAgICAgfSxcbiAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBcInR5cGVcIjogXCJvYmplY3RcIlxuICAgIH1cbiAgfVxufVxuIiwiLyogZXNsaW50LWRpc2FibGUgKi9cbi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVC0wXG5cbmNvbnN0IEFqdjIwMTkgPSByZXF1aXJlKFwiYWp2L2Rpc3QvMjAxOVwiKVxuY29uc3Qgc2NoZW1hID0gcmVxdWlyZShcIi4vTGV4Q29kZUhvb2tSZXNwb25zZVNjaGVtYS5qc29uXCIpXG5jb25zdCBhanYgPSBuZXcgQWp2MjAxOSh7IGFsbEVycm9yczogdHJ1ZSB9KVxuXG5leHBvcnRzLnZhbGlkYXRlSW5wdXQgPSBmdW5jdGlvbiAoaW5wdXREYXRhKSB7XG4gIGxldCByZXNwb25zZSA9IFtdXG5cbiAgY29uc3QgZXJyb3JzID0gdmFsaWRhdGVMZXhMYW1iZGFSZXNwb25zZShpbnB1dERhdGEpXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZXJyb3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGVycm9yc1tpXS5rZXl3b3JkICE9PSBcImlmXCIgJiYgZXJyb3JzW2ldLmtleXdvcmQgIT09IFwiZWxzZVwiICYmIGVycm9yc1tpXS5rZXl3b3JkICE9PSBcInRoZW5cIikge1xuICAgICAgbGV0IG1lc3NhZ2UgPSBgYFxuXG4gICAgICBpZiAoZXJyb3JzW2ldLmluc3RhbmNlUGF0aCA9PT0gXCJcIikge1xuICAgICAgICBtZXNzYWdlICs9IGVycm9yc1tpXS5tZXNzYWdlXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtZXNzYWdlICs9IGAke2Vycm9yc1tpXS5pbnN0YW5jZVBhdGh9ICR7ZXJyb3JzW2ldLm1lc3NhZ2V9YFxuICAgICAgfVxuXG4gICAgICBpZiAoZXJyb3JzW2ldLnBhcmFtcy5hbGxvd2VkVmFsdWVzKSB7XG4gICAgICAgIG1lc3NhZ2UgKz0gYC4gQWxsb3dlZCB2YWx1ZXM6ICR7ZXJyb3JzW2ldLnBhcmFtcy5hbGxvd2VkVmFsdWVzLmpvaW4oXCIsIFwiKX1gXG4gICAgICB9XG4gICAgICByZXNwb25zZS5wdXNoKG1lc3NhZ2UpXG4gICAgfVxuICB9XG4gIHJldHVybiByZXNwb25zZVxufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUxleExhbWJkYVJlc3BvbnNlKGlucHV0RGF0YSkge1xuICBjb25zdCB2YWxpZGF0ZSA9IGFqdi5jb21waWxlKHNjaGVtYSlcbiAgdmFsaWRhdGUoaW5wdXREYXRhKVxuICBjb25zb2xlLmRlYnVnKFwiVmFsaWRhdGlvbiBlcnJvcnM6XCIsIHZhbGlkYXRlLmVycm9ycylcbiAgcmV0dXJuIHZhbGlkYXRlLmVycm9ycyB8fCBbXVxufVxuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leHBvcnRzLk1pc3NpbmdSZWZFcnJvciA9IGV4cG9ydHMuVmFsaWRhdGlvbkVycm9yID0gZXhwb3J0cy5Db2RlR2VuID0gZXhwb3J0cy5OYW1lID0gZXhwb3J0cy5uaWwgPSBleHBvcnRzLnN0cmluZ2lmeSA9IGV4cG9ydHMuc3RyID0gZXhwb3J0cy5fID0gZXhwb3J0cy5LZXl3b3JkQ3h0ID0gdm9pZCAwO1xuY29uc3QgY29yZV8xID0gcmVxdWlyZShcIi4vY29yZVwiKTtcbmNvbnN0IGRyYWZ0N18xID0gcmVxdWlyZShcIi4vdm9jYWJ1bGFyaWVzL2RyYWZ0N1wiKTtcbmNvbnN0IGR5bmFtaWNfMSA9IHJlcXVpcmUoXCIuL3ZvY2FidWxhcmllcy9keW5hbWljXCIpO1xuY29uc3QgbmV4dF8xID0gcmVxdWlyZShcIi4vdm9jYWJ1bGFyaWVzL25leHRcIik7XG5jb25zdCB1bmV2YWx1YXRlZF8xID0gcmVxdWlyZShcIi4vdm9jYWJ1bGFyaWVzL3VuZXZhbHVhdGVkXCIpO1xuY29uc3QgZGlzY3JpbWluYXRvcl8xID0gcmVxdWlyZShcIi4vdm9jYWJ1bGFyaWVzL2Rpc2NyaW1pbmF0b3JcIik7XG5jb25zdCBqc29uX3NjaGVtYV8yMDE5XzA5XzEgPSByZXF1aXJlKFwiLi9yZWZzL2pzb24tc2NoZW1hLTIwMTktMDlcIik7XG5jb25zdCBNRVRBX1NDSEVNQV9JRCA9IFwiaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQvMjAxOS0wOS9zY2hlbWFcIjtcbmNsYXNzIEFqdjIwMTkgZXh0ZW5kcyBjb3JlXzEuZGVmYXVsdCB7XG4gICAgY29uc3RydWN0b3Iob3B0cyA9IHt9KSB7XG4gICAgICAgIHN1cGVyKHtcbiAgICAgICAgICAgIC4uLm9wdHMsXG4gICAgICAgICAgICBkeW5hbWljUmVmOiB0cnVlLFxuICAgICAgICAgICAgbmV4dDogdHJ1ZSxcbiAgICAgICAgICAgIHVuZXZhbHVhdGVkOiB0cnVlLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgX2FkZFZvY2FidWxhcmllcygpIHtcbiAgICAgICAgc3VwZXIuX2FkZFZvY2FidWxhcmllcygpO1xuICAgICAgICB0aGlzLmFkZFZvY2FidWxhcnkoZHluYW1pY18xLmRlZmF1bHQpO1xuICAgICAgICBkcmFmdDdfMS5kZWZhdWx0LmZvckVhY2goKHYpID0+IHRoaXMuYWRkVm9jYWJ1bGFyeSh2KSk7XG4gICAgICAgIHRoaXMuYWRkVm9jYWJ1bGFyeShuZXh0XzEuZGVmYXVsdCk7XG4gICAgICAgIHRoaXMuYWRkVm9jYWJ1bGFyeSh1bmV2YWx1YXRlZF8xLmRlZmF1bHQpO1xuICAgICAgICBpZiAodGhpcy5vcHRzLmRpc2NyaW1pbmF0b3IpXG4gICAgICAgICAgICB0aGlzLmFkZEtleXdvcmQoZGlzY3JpbWluYXRvcl8xLmRlZmF1bHQpO1xuICAgIH1cbiAgICBfYWRkRGVmYXVsdE1ldGFTY2hlbWEoKSB7XG4gICAgICAgIHN1cGVyLl9hZGREZWZhdWx0TWV0YVNjaGVtYSgpO1xuICAgICAgICBjb25zdCB7ICRkYXRhLCBtZXRhIH0gPSB0aGlzLm9wdHM7XG4gICAgICAgIGlmICghbWV0YSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAganNvbl9zY2hlbWFfMjAxOV8wOV8xLmRlZmF1bHQuY2FsbCh0aGlzLCAkZGF0YSk7XG4gICAgICAgIHRoaXMucmVmc1tcImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvc2NoZW1hXCJdID0gTUVUQV9TQ0hFTUFfSUQ7XG4gICAgfVxuICAgIGRlZmF1bHRNZXRhKCkge1xuICAgICAgICByZXR1cm4gKHRoaXMub3B0cy5kZWZhdWx0TWV0YSA9XG4gICAgICAgICAgICBzdXBlci5kZWZhdWx0TWV0YSgpIHx8ICh0aGlzLmdldFNjaGVtYShNRVRBX1NDSEVNQV9JRCkgPyBNRVRBX1NDSEVNQV9JRCA6IHVuZGVmaW5lZCkpO1xuICAgIH1cbn1cbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0cyA9IEFqdjIwMTk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leHBvcnRzLmRlZmF1bHQgPSBBanYyMDE5O1xudmFyIHZhbGlkYXRlXzEgPSByZXF1aXJlKFwiLi9jb21waWxlL3ZhbGlkYXRlXCIpO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiS2V5d29yZEN4dFwiLCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdmFsaWRhdGVfMS5LZXl3b3JkQ3h0OyB9IH0pO1xudmFyIGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuL2NvbXBpbGUvY29kZWdlblwiKTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9cIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvZGVnZW5fMS5fOyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwic3RyXCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2RlZ2VuXzEuc3RyOyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwic3RyaW5naWZ5XCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2RlZ2VuXzEuc3RyaW5naWZ5OyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwibmlsXCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2RlZ2VuXzEubmlsOyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiTmFtZVwiLCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gY29kZWdlbl8xLk5hbWU7IH0gfSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJDb2RlR2VuXCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2RlZ2VuXzEuQ29kZUdlbjsgfSB9KTtcbnZhciB2YWxpZGF0aW9uX2Vycm9yXzEgPSByZXF1aXJlKFwiLi9ydW50aW1lL3ZhbGlkYXRpb25fZXJyb3JcIik7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJWYWxpZGF0aW9uRXJyb3JcIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHZhbGlkYXRpb25fZXJyb3JfMS5kZWZhdWx0OyB9IH0pO1xudmFyIHJlZl9lcnJvcl8xID0gcmVxdWlyZShcIi4vY29tcGlsZS9yZWZfZXJyb3JcIik7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJNaXNzaW5nUmVmRXJyb3JcIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHJlZl9lcnJvcl8xLmRlZmF1bHQ7IH0gfSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD0yMDE5LmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXhwb3J0cy5yZWdleHBDb2RlID0gZXhwb3J0cy5nZXRFc21FeHBvcnROYW1lID0gZXhwb3J0cy5nZXRQcm9wZXJ0eSA9IGV4cG9ydHMuc2FmZVN0cmluZ2lmeSA9IGV4cG9ydHMuc3RyaW5naWZ5ID0gZXhwb3J0cy5zdHJDb25jYXQgPSBleHBvcnRzLmFkZENvZGVBcmcgPSBleHBvcnRzLnN0ciA9IGV4cG9ydHMuXyA9IGV4cG9ydHMubmlsID0gZXhwb3J0cy5fQ29kZSA9IGV4cG9ydHMuTmFtZSA9IGV4cG9ydHMuSURFTlRJRklFUiA9IGV4cG9ydHMuX0NvZGVPck5hbWUgPSB2b2lkIDA7XG5jbGFzcyBfQ29kZU9yTmFtZSB7XG59XG5leHBvcnRzLl9Db2RlT3JOYW1lID0gX0NvZGVPck5hbWU7XG5leHBvcnRzLklERU5USUZJRVIgPSAvXlthLXokX11bYS16JF8wLTldKiQvaTtcbmNsYXNzIE5hbWUgZXh0ZW5kcyBfQ29kZU9yTmFtZSB7XG4gICAgY29uc3RydWN0b3Iocykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICBpZiAoIWV4cG9ydHMuSURFTlRJRklFUi50ZXN0KHMpKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ29kZUdlbjogbmFtZSBtdXN0IGJlIGEgdmFsaWQgaWRlbnRpZmllclwiKTtcbiAgICAgICAgdGhpcy5zdHIgPSBzO1xuICAgIH1cbiAgICB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RyO1xuICAgIH1cbiAgICBlbXB0eVN0cigpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBnZXQgbmFtZXMoKSB7XG4gICAgICAgIHJldHVybiB7IFt0aGlzLnN0cl06IDEgfTtcbiAgICB9XG59XG5leHBvcnRzLk5hbWUgPSBOYW1lO1xuY2xhc3MgX0NvZGUgZXh0ZW5kcyBfQ29kZU9yTmFtZSB7XG4gICAgY29uc3RydWN0b3IoY29kZSkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLl9pdGVtcyA9IHR5cGVvZiBjb2RlID09PSBcInN0cmluZ1wiID8gW2NvZGVdIDogY29kZTtcbiAgICB9XG4gICAgdG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0cjtcbiAgICB9XG4gICAgZW1wdHlTdHIoKSB7XG4gICAgICAgIGlmICh0aGlzLl9pdGVtcy5sZW5ndGggPiAxKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBjb25zdCBpdGVtID0gdGhpcy5faXRlbXNbMF07XG4gICAgICAgIHJldHVybiBpdGVtID09PSBcIlwiIHx8IGl0ZW0gPT09ICdcIlwiJztcbiAgICB9XG4gICAgZ2V0IHN0cigpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICByZXR1cm4gKChfYSA9IHRoaXMuX3N0cikgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogKHRoaXMuX3N0ciA9IHRoaXMuX2l0ZW1zLnJlZHVjZSgocywgYykgPT4gYCR7c30ke2N9YCwgXCJcIikpKTtcbiAgICB9XG4gICAgZ2V0IG5hbWVzKCkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHJldHVybiAoKF9hID0gdGhpcy5fbmFtZXMpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6ICh0aGlzLl9uYW1lcyA9IHRoaXMuX2l0ZW1zLnJlZHVjZSgobmFtZXMsIGMpID0+IHtcbiAgICAgICAgICAgIGlmIChjIGluc3RhbmNlb2YgTmFtZSlcbiAgICAgICAgICAgICAgICBuYW1lc1tjLnN0cl0gPSAobmFtZXNbYy5zdHJdIHx8IDApICsgMTtcbiAgICAgICAgICAgIHJldHVybiBuYW1lcztcbiAgICAgICAgfSwge30pKSk7XG4gICAgfVxufVxuZXhwb3J0cy5fQ29kZSA9IF9Db2RlO1xuZXhwb3J0cy5uaWwgPSBuZXcgX0NvZGUoXCJcIik7XG5mdW5jdGlvbiBfKHN0cnMsIC4uLmFyZ3MpIHtcbiAgICBjb25zdCBjb2RlID0gW3N0cnNbMF1dO1xuICAgIGxldCBpID0gMDtcbiAgICB3aGlsZSAoaSA8IGFyZ3MubGVuZ3RoKSB7XG4gICAgICAgIGFkZENvZGVBcmcoY29kZSwgYXJnc1tpXSk7XG4gICAgICAgIGNvZGUucHVzaChzdHJzWysraV0pO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IF9Db2RlKGNvZGUpO1xufVxuZXhwb3J0cy5fID0gXztcbmNvbnN0IHBsdXMgPSBuZXcgX0NvZGUoXCIrXCIpO1xuZnVuY3Rpb24gc3RyKHN0cnMsIC4uLmFyZ3MpIHtcbiAgICBjb25zdCBleHByID0gW3NhZmVTdHJpbmdpZnkoc3Ryc1swXSldO1xuICAgIGxldCBpID0gMDtcbiAgICB3aGlsZSAoaSA8IGFyZ3MubGVuZ3RoKSB7XG4gICAgICAgIGV4cHIucHVzaChwbHVzKTtcbiAgICAgICAgYWRkQ29kZUFyZyhleHByLCBhcmdzW2ldKTtcbiAgICAgICAgZXhwci5wdXNoKHBsdXMsIHNhZmVTdHJpbmdpZnkoc3Ryc1srK2ldKSk7XG4gICAgfVxuICAgIG9wdGltaXplKGV4cHIpO1xuICAgIHJldHVybiBuZXcgX0NvZGUoZXhwcik7XG59XG5leHBvcnRzLnN0ciA9IHN0cjtcbmZ1bmN0aW9uIGFkZENvZGVBcmcoY29kZSwgYXJnKSB7XG4gICAgaWYgKGFyZyBpbnN0YW5jZW9mIF9Db2RlKVxuICAgICAgICBjb2RlLnB1c2goLi4uYXJnLl9pdGVtcyk7XG4gICAgZWxzZSBpZiAoYXJnIGluc3RhbmNlb2YgTmFtZSlcbiAgICAgICAgY29kZS5wdXNoKGFyZyk7XG4gICAgZWxzZVxuICAgICAgICBjb2RlLnB1c2goaW50ZXJwb2xhdGUoYXJnKSk7XG59XG5leHBvcnRzLmFkZENvZGVBcmcgPSBhZGRDb2RlQXJnO1xuZnVuY3Rpb24gb3B0aW1pemUoZXhwcikge1xuICAgIGxldCBpID0gMTtcbiAgICB3aGlsZSAoaSA8IGV4cHIubGVuZ3RoIC0gMSkge1xuICAgICAgICBpZiAoZXhwcltpXSA9PT0gcGx1cykge1xuICAgICAgICAgICAgY29uc3QgcmVzID0gbWVyZ2VFeHBySXRlbXMoZXhwcltpIC0gMV0sIGV4cHJbaSArIDFdKTtcbiAgICAgICAgICAgIGlmIChyZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGV4cHIuc3BsaWNlKGkgLSAxLCAzLCByZXMpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZXhwcltpKytdID0gXCIrXCI7XG4gICAgICAgIH1cbiAgICAgICAgaSsrO1xuICAgIH1cbn1cbmZ1bmN0aW9uIG1lcmdlRXhwckl0ZW1zKGEsIGIpIHtcbiAgICBpZiAoYiA9PT0gJ1wiXCInKVxuICAgICAgICByZXR1cm4gYTtcbiAgICBpZiAoYSA9PT0gJ1wiXCInKVxuICAgICAgICByZXR1cm4gYjtcbiAgICBpZiAodHlwZW9mIGEgPT0gXCJzdHJpbmdcIikge1xuICAgICAgICBpZiAoYiBpbnN0YW5jZW9mIE5hbWUgfHwgYVthLmxlbmd0aCAtIDFdICE9PSAnXCInKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBpZiAodHlwZW9mIGIgIT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgIHJldHVybiBgJHthLnNsaWNlKDAsIC0xKX0ke2J9XCJgO1xuICAgICAgICBpZiAoYlswXSA9PT0gJ1wiJylcbiAgICAgICAgICAgIHJldHVybiBhLnNsaWNlKDAsIC0xKSArIGIuc2xpY2UoMSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBiID09IFwic3RyaW5nXCIgJiYgYlswXSA9PT0gJ1wiJyAmJiAhKGEgaW5zdGFuY2VvZiBOYW1lKSlcbiAgICAgICAgcmV0dXJuIGBcIiR7YX0ke2Iuc2xpY2UoMSl9YDtcbiAgICByZXR1cm47XG59XG5mdW5jdGlvbiBzdHJDb25jYXQoYzEsIGMyKSB7XG4gICAgcmV0dXJuIGMyLmVtcHR5U3RyKCkgPyBjMSA6IGMxLmVtcHR5U3RyKCkgPyBjMiA6IHN0ciBgJHtjMX0ke2MyfWA7XG59XG5leHBvcnRzLnN0ckNvbmNhdCA9IHN0ckNvbmNhdDtcbi8vIFRPRE8gZG8gbm90IGFsbG93IGFycmF5cyBoZXJlXG5mdW5jdGlvbiBpbnRlcnBvbGF0ZSh4KSB7XG4gICAgcmV0dXJuIHR5cGVvZiB4ID09IFwibnVtYmVyXCIgfHwgdHlwZW9mIHggPT0gXCJib29sZWFuXCIgfHwgeCA9PT0gbnVsbFxuICAgICAgICA/IHhcbiAgICAgICAgOiBzYWZlU3RyaW5naWZ5KEFycmF5LmlzQXJyYXkoeCkgPyB4LmpvaW4oXCIsXCIpIDogeCk7XG59XG5mdW5jdGlvbiBzdHJpbmdpZnkoeCkge1xuICAgIHJldHVybiBuZXcgX0NvZGUoc2FmZVN0cmluZ2lmeSh4KSk7XG59XG5leHBvcnRzLnN0cmluZ2lmeSA9IHN0cmluZ2lmeTtcbmZ1bmN0aW9uIHNhZmVTdHJpbmdpZnkoeCkge1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh4KVxuICAgICAgICAucmVwbGFjZSgvXFx1MjAyOC9nLCBcIlxcXFx1MjAyOFwiKVxuICAgICAgICAucmVwbGFjZSgvXFx1MjAyOS9nLCBcIlxcXFx1MjAyOVwiKTtcbn1cbmV4cG9ydHMuc2FmZVN0cmluZ2lmeSA9IHNhZmVTdHJpbmdpZnk7XG5mdW5jdGlvbiBnZXRQcm9wZXJ0eShrZXkpIHtcbiAgICByZXR1cm4gdHlwZW9mIGtleSA9PSBcInN0cmluZ1wiICYmIGV4cG9ydHMuSURFTlRJRklFUi50ZXN0KGtleSkgPyBuZXcgX0NvZGUoYC4ke2tleX1gKSA6IF8gYFske2tleX1dYDtcbn1cbmV4cG9ydHMuZ2V0UHJvcGVydHkgPSBnZXRQcm9wZXJ0eTtcbi8vRG9lcyBiZXN0IGVmZm9ydCB0byBmb3JtYXQgdGhlIG5hbWUgcHJvcGVybHlcbmZ1bmN0aW9uIGdldEVzbUV4cG9ydE5hbWUoa2V5KSB7XG4gICAgaWYgKHR5cGVvZiBrZXkgPT0gXCJzdHJpbmdcIiAmJiBleHBvcnRzLklERU5USUZJRVIudGVzdChrZXkpKSB7XG4gICAgICAgIHJldHVybiBuZXcgX0NvZGUoYCR7a2V5fWApO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYENvZGVHZW46IGludmFsaWQgZXhwb3J0IG5hbWU6ICR7a2V5fSwgdXNlIGV4cGxpY2l0ICRpZCBuYW1lIG1hcHBpbmdgKTtcbn1cbmV4cG9ydHMuZ2V0RXNtRXhwb3J0TmFtZSA9IGdldEVzbUV4cG9ydE5hbWU7XG5mdW5jdGlvbiByZWdleHBDb2RlKHJ4KSB7XG4gICAgcmV0dXJuIG5ldyBfQ29kZShyeC50b1N0cmluZygpKTtcbn1cbmV4cG9ydHMucmVnZXhwQ29kZSA9IHJlZ2V4cENvZGU7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jb2RlLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXhwb3J0cy5vciA9IGV4cG9ydHMuYW5kID0gZXhwb3J0cy5ub3QgPSBleHBvcnRzLkNvZGVHZW4gPSBleHBvcnRzLm9wZXJhdG9ycyA9IGV4cG9ydHMudmFyS2luZHMgPSBleHBvcnRzLlZhbHVlU2NvcGVOYW1lID0gZXhwb3J0cy5WYWx1ZVNjb3BlID0gZXhwb3J0cy5TY29wZSA9IGV4cG9ydHMuTmFtZSA9IGV4cG9ydHMucmVnZXhwQ29kZSA9IGV4cG9ydHMuc3RyaW5naWZ5ID0gZXhwb3J0cy5nZXRQcm9wZXJ0eSA9IGV4cG9ydHMubmlsID0gZXhwb3J0cy5zdHJDb25jYXQgPSBleHBvcnRzLnN0ciA9IGV4cG9ydHMuXyA9IHZvaWQgMDtcbmNvbnN0IGNvZGVfMSA9IHJlcXVpcmUoXCIuL2NvZGVcIik7XG5jb25zdCBzY29wZV8xID0gcmVxdWlyZShcIi4vc2NvcGVcIik7XG52YXIgY29kZV8yID0gcmVxdWlyZShcIi4vY29kZVwiKTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9cIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvZGVfMi5fOyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwic3RyXCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2RlXzIuc3RyOyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwic3RyQ29uY2F0XCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2RlXzIuc3RyQ29uY2F0OyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwibmlsXCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2RlXzIubmlsOyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiZ2V0UHJvcGVydHlcIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvZGVfMi5nZXRQcm9wZXJ0eTsgfSB9KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcInN0cmluZ2lmeVwiLCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gY29kZV8yLnN0cmluZ2lmeTsgfSB9KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcInJlZ2V4cENvZGVcIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvZGVfMi5yZWdleHBDb2RlOyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiTmFtZVwiLCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gY29kZV8yLk5hbWU7IH0gfSk7XG52YXIgc2NvcGVfMiA9IHJlcXVpcmUoXCIuL3Njb3BlXCIpO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiU2NvcGVcIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHNjb3BlXzIuU2NvcGU7IH0gfSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJWYWx1ZVNjb3BlXCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBzY29wZV8yLlZhbHVlU2NvcGU7IH0gfSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJWYWx1ZVNjb3BlTmFtZVwiLCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gc2NvcGVfMi5WYWx1ZVNjb3BlTmFtZTsgfSB9KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcInZhcktpbmRzXCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBzY29wZV8yLnZhcktpbmRzOyB9IH0pO1xuZXhwb3J0cy5vcGVyYXRvcnMgPSB7XG4gICAgR1Q6IG5ldyBjb2RlXzEuX0NvZGUoXCI+XCIpLFxuICAgIEdURTogbmV3IGNvZGVfMS5fQ29kZShcIj49XCIpLFxuICAgIExUOiBuZXcgY29kZV8xLl9Db2RlKFwiPFwiKSxcbiAgICBMVEU6IG5ldyBjb2RlXzEuX0NvZGUoXCI8PVwiKSxcbiAgICBFUTogbmV3IGNvZGVfMS5fQ29kZShcIj09PVwiKSxcbiAgICBORVE6IG5ldyBjb2RlXzEuX0NvZGUoXCIhPT1cIiksXG4gICAgTk9UOiBuZXcgY29kZV8xLl9Db2RlKFwiIVwiKSxcbiAgICBPUjogbmV3IGNvZGVfMS5fQ29kZShcInx8XCIpLFxuICAgIEFORDogbmV3IGNvZGVfMS5fQ29kZShcIiYmXCIpLFxuICAgIEFERDogbmV3IGNvZGVfMS5fQ29kZShcIitcIiksXG59O1xuY2xhc3MgTm9kZSB7XG4gICAgb3B0aW1pemVOb2RlcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIG9wdGltaXplTmFtZXMoX25hbWVzLCBfY29uc3RhbnRzKSB7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbn1cbmNsYXNzIERlZiBleHRlbmRzIE5vZGUge1xuICAgIGNvbnN0cnVjdG9yKHZhcktpbmQsIG5hbWUsIHJocykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnZhcktpbmQgPSB2YXJLaW5kO1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLnJocyA9IHJocztcbiAgICB9XG4gICAgcmVuZGVyKHsgZXM1LCBfbiB9KSB7XG4gICAgICAgIGNvbnN0IHZhcktpbmQgPSBlczUgPyBzY29wZV8xLnZhcktpbmRzLnZhciA6IHRoaXMudmFyS2luZDtcbiAgICAgICAgY29uc3QgcmhzID0gdGhpcy5yaHMgPT09IHVuZGVmaW5lZCA/IFwiXCIgOiBgID0gJHt0aGlzLnJoc31gO1xuICAgICAgICByZXR1cm4gYCR7dmFyS2luZH0gJHt0aGlzLm5hbWV9JHtyaHN9O2AgKyBfbjtcbiAgICB9XG4gICAgb3B0aW1pemVOYW1lcyhuYW1lcywgY29uc3RhbnRzKSB7XG4gICAgICAgIGlmICghbmFtZXNbdGhpcy5uYW1lLnN0cl0pXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmICh0aGlzLnJocylcbiAgICAgICAgICAgIHRoaXMucmhzID0gb3B0aW1pemVFeHByKHRoaXMucmhzLCBuYW1lcywgY29uc3RhbnRzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGdldCBuYW1lcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmhzIGluc3RhbmNlb2YgY29kZV8xLl9Db2RlT3JOYW1lID8gdGhpcy5yaHMubmFtZXMgOiB7fTtcbiAgICB9XG59XG5jbGFzcyBBc3NpZ24gZXh0ZW5kcyBOb2RlIHtcbiAgICBjb25zdHJ1Y3RvcihsaHMsIHJocywgc2lkZUVmZmVjdHMpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5saHMgPSBsaHM7XG4gICAgICAgIHRoaXMucmhzID0gcmhzO1xuICAgICAgICB0aGlzLnNpZGVFZmZlY3RzID0gc2lkZUVmZmVjdHM7XG4gICAgfVxuICAgIHJlbmRlcih7IF9uIH0pIHtcbiAgICAgICAgcmV0dXJuIGAke3RoaXMubGhzfSA9ICR7dGhpcy5yaHN9O2AgKyBfbjtcbiAgICB9XG4gICAgb3B0aW1pemVOYW1lcyhuYW1lcywgY29uc3RhbnRzKSB7XG4gICAgICAgIGlmICh0aGlzLmxocyBpbnN0YW5jZW9mIGNvZGVfMS5OYW1lICYmICFuYW1lc1t0aGlzLmxocy5zdHJdICYmICF0aGlzLnNpZGVFZmZlY3RzKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB0aGlzLnJocyA9IG9wdGltaXplRXhwcih0aGlzLnJocywgbmFtZXMsIGNvbnN0YW50cyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBnZXQgbmFtZXMoKSB7XG4gICAgICAgIGNvbnN0IG5hbWVzID0gdGhpcy5saHMgaW5zdGFuY2VvZiBjb2RlXzEuTmFtZSA/IHt9IDogeyAuLi50aGlzLmxocy5uYW1lcyB9O1xuICAgICAgICByZXR1cm4gYWRkRXhwck5hbWVzKG5hbWVzLCB0aGlzLnJocyk7XG4gICAgfVxufVxuY2xhc3MgQXNzaWduT3AgZXh0ZW5kcyBBc3NpZ24ge1xuICAgIGNvbnN0cnVjdG9yKGxocywgb3AsIHJocywgc2lkZUVmZmVjdHMpIHtcbiAgICAgICAgc3VwZXIobGhzLCByaHMsIHNpZGVFZmZlY3RzKTtcbiAgICAgICAgdGhpcy5vcCA9IG9wO1xuICAgIH1cbiAgICByZW5kZXIoeyBfbiB9KSB7XG4gICAgICAgIHJldHVybiBgJHt0aGlzLmxoc30gJHt0aGlzLm9wfT0gJHt0aGlzLnJoc307YCArIF9uO1xuICAgIH1cbn1cbmNsYXNzIExhYmVsIGV4dGVuZHMgTm9kZSB7XG4gICAgY29uc3RydWN0b3IobGFiZWwpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5sYWJlbCA9IGxhYmVsO1xuICAgICAgICB0aGlzLm5hbWVzID0ge307XG4gICAgfVxuICAgIHJlbmRlcih7IF9uIH0pIHtcbiAgICAgICAgcmV0dXJuIGAke3RoaXMubGFiZWx9OmAgKyBfbjtcbiAgICB9XG59XG5jbGFzcyBCcmVhayBleHRlbmRzIE5vZGUge1xuICAgIGNvbnN0cnVjdG9yKGxhYmVsKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMubGFiZWwgPSBsYWJlbDtcbiAgICAgICAgdGhpcy5uYW1lcyA9IHt9O1xuICAgIH1cbiAgICByZW5kZXIoeyBfbiB9KSB7XG4gICAgICAgIGNvbnN0IGxhYmVsID0gdGhpcy5sYWJlbCA/IGAgJHt0aGlzLmxhYmVsfWAgOiBcIlwiO1xuICAgICAgICByZXR1cm4gYGJyZWFrJHtsYWJlbH07YCArIF9uO1xuICAgIH1cbn1cbmNsYXNzIFRocm93IGV4dGVuZHMgTm9kZSB7XG4gICAgY29uc3RydWN0b3IoZXJyb3IpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5lcnJvciA9IGVycm9yO1xuICAgIH1cbiAgICByZW5kZXIoeyBfbiB9KSB7XG4gICAgICAgIHJldHVybiBgdGhyb3cgJHt0aGlzLmVycm9yfTtgICsgX247XG4gICAgfVxuICAgIGdldCBuYW1lcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZXJyb3IubmFtZXM7XG4gICAgfVxufVxuY2xhc3MgQW55Q29kZSBleHRlbmRzIE5vZGUge1xuICAgIGNvbnN0cnVjdG9yKGNvZGUpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5jb2RlID0gY29kZTtcbiAgICB9XG4gICAgcmVuZGVyKHsgX24gfSkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy5jb2RlfTtgICsgX247XG4gICAgfVxuICAgIG9wdGltaXplTm9kZXMoKSB7XG4gICAgICAgIHJldHVybiBgJHt0aGlzLmNvZGV9YCA/IHRoaXMgOiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIG9wdGltaXplTmFtZXMobmFtZXMsIGNvbnN0YW50cykge1xuICAgICAgICB0aGlzLmNvZGUgPSBvcHRpbWl6ZUV4cHIodGhpcy5jb2RlLCBuYW1lcywgY29uc3RhbnRzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGdldCBuYW1lcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29kZSBpbnN0YW5jZW9mIGNvZGVfMS5fQ29kZU9yTmFtZSA/IHRoaXMuY29kZS5uYW1lcyA6IHt9O1xuICAgIH1cbn1cbmNsYXNzIFBhcmVudE5vZGUgZXh0ZW5kcyBOb2RlIHtcbiAgICBjb25zdHJ1Y3Rvcihub2RlcyA9IFtdKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMubm9kZXMgPSBub2RlcztcbiAgICB9XG4gICAgcmVuZGVyKG9wdHMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubm9kZXMucmVkdWNlKChjb2RlLCBuKSA9PiBjb2RlICsgbi5yZW5kZXIob3B0cyksIFwiXCIpO1xuICAgIH1cbiAgICBvcHRpbWl6ZU5vZGVzKCkge1xuICAgICAgICBjb25zdCB7IG5vZGVzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgaSA9IG5vZGVzLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgY29uc3QgbiA9IG5vZGVzW2ldLm9wdGltaXplTm9kZXMoKTtcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KG4pKVxuICAgICAgICAgICAgICAgIG5vZGVzLnNwbGljZShpLCAxLCAuLi5uKTtcbiAgICAgICAgICAgIGVsc2UgaWYgKG4pXG4gICAgICAgICAgICAgICAgbm9kZXNbaV0gPSBuO1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIG5vZGVzLnNwbGljZShpLCAxKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbm9kZXMubGVuZ3RoID4gMCA/IHRoaXMgOiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIG9wdGltaXplTmFtZXMobmFtZXMsIGNvbnN0YW50cykge1xuICAgICAgICBjb25zdCB7IG5vZGVzIH0gPSB0aGlzO1xuICAgICAgICBsZXQgaSA9IG5vZGVzLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgLy8gaXRlcmF0aW5nIGJhY2t3YXJkcyBpbXByb3ZlcyAxLXBhc3Mgb3B0aW1pemF0aW9uXG4gICAgICAgICAgICBjb25zdCBuID0gbm9kZXNbaV07XG4gICAgICAgICAgICBpZiAobi5vcHRpbWl6ZU5hbWVzKG5hbWVzLCBjb25zdGFudHMpKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgc3VidHJhY3ROYW1lcyhuYW1lcywgbi5uYW1lcyk7XG4gICAgICAgICAgICBub2Rlcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5vZGVzLmxlbmd0aCA+IDAgPyB0aGlzIDogdW5kZWZpbmVkO1xuICAgIH1cbiAgICBnZXQgbmFtZXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm5vZGVzLnJlZHVjZSgobmFtZXMsIG4pID0+IGFkZE5hbWVzKG5hbWVzLCBuLm5hbWVzKSwge30pO1xuICAgIH1cbn1cbmNsYXNzIEJsb2NrTm9kZSBleHRlbmRzIFBhcmVudE5vZGUge1xuICAgIHJlbmRlcihvcHRzKSB7XG4gICAgICAgIHJldHVybiBcIntcIiArIG9wdHMuX24gKyBzdXBlci5yZW5kZXIob3B0cykgKyBcIn1cIiArIG9wdHMuX247XG4gICAgfVxufVxuY2xhc3MgUm9vdCBleHRlbmRzIFBhcmVudE5vZGUge1xufVxuY2xhc3MgRWxzZSBleHRlbmRzIEJsb2NrTm9kZSB7XG59XG5FbHNlLmtpbmQgPSBcImVsc2VcIjtcbmNsYXNzIElmIGV4dGVuZHMgQmxvY2tOb2RlIHtcbiAgICBjb25zdHJ1Y3Rvcihjb25kaXRpb24sIG5vZGVzKSB7XG4gICAgICAgIHN1cGVyKG5vZGVzKTtcbiAgICAgICAgdGhpcy5jb25kaXRpb24gPSBjb25kaXRpb247XG4gICAgfVxuICAgIHJlbmRlcihvcHRzKSB7XG4gICAgICAgIGxldCBjb2RlID0gYGlmKCR7dGhpcy5jb25kaXRpb259KWAgKyBzdXBlci5yZW5kZXIob3B0cyk7XG4gICAgICAgIGlmICh0aGlzLmVsc2UpXG4gICAgICAgICAgICBjb2RlICs9IFwiZWxzZSBcIiArIHRoaXMuZWxzZS5yZW5kZXIob3B0cyk7XG4gICAgICAgIHJldHVybiBjb2RlO1xuICAgIH1cbiAgICBvcHRpbWl6ZU5vZGVzKCkge1xuICAgICAgICBzdXBlci5vcHRpbWl6ZU5vZGVzKCk7XG4gICAgICAgIGNvbnN0IGNvbmQgPSB0aGlzLmNvbmRpdGlvbjtcbiAgICAgICAgaWYgKGNvbmQgPT09IHRydWUpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ub2RlczsgLy8gZWxzZSBpcyBpZ25vcmVkIGhlcmVcbiAgICAgICAgbGV0IGUgPSB0aGlzLmVsc2U7XG4gICAgICAgIGlmIChlKSB7XG4gICAgICAgICAgICBjb25zdCBucyA9IGUub3B0aW1pemVOb2RlcygpO1xuICAgICAgICAgICAgZSA9IHRoaXMuZWxzZSA9IEFycmF5LmlzQXJyYXkobnMpID8gbmV3IEVsc2UobnMpIDogbnM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGUpIHtcbiAgICAgICAgICAgIGlmIChjb25kID09PSBmYWxzZSlcbiAgICAgICAgICAgICAgICByZXR1cm4gZSBpbnN0YW5jZW9mIElmID8gZSA6IGUubm9kZXM7XG4gICAgICAgICAgICBpZiAodGhpcy5ub2Rlcy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICByZXR1cm4gbmV3IElmKG5vdChjb25kKSwgZSBpbnN0YW5jZW9mIElmID8gW2VdIDogZS5ub2Rlcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbmQgPT09IGZhbHNlIHx8ICF0aGlzLm5vZGVzLmxlbmd0aClcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBvcHRpbWl6ZU5hbWVzKG5hbWVzLCBjb25zdGFudHMpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB0aGlzLmVsc2UgPSAoX2EgPSB0aGlzLmVsc2UpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5vcHRpbWl6ZU5hbWVzKG5hbWVzLCBjb25zdGFudHMpO1xuICAgICAgICBpZiAoIShzdXBlci5vcHRpbWl6ZU5hbWVzKG5hbWVzLCBjb25zdGFudHMpIHx8IHRoaXMuZWxzZSkpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHRoaXMuY29uZGl0aW9uID0gb3B0aW1pemVFeHByKHRoaXMuY29uZGl0aW9uLCBuYW1lcywgY29uc3RhbnRzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGdldCBuYW1lcygpIHtcbiAgICAgICAgY29uc3QgbmFtZXMgPSBzdXBlci5uYW1lcztcbiAgICAgICAgYWRkRXhwck5hbWVzKG5hbWVzLCB0aGlzLmNvbmRpdGlvbik7XG4gICAgICAgIGlmICh0aGlzLmVsc2UpXG4gICAgICAgICAgICBhZGROYW1lcyhuYW1lcywgdGhpcy5lbHNlLm5hbWVzKTtcbiAgICAgICAgcmV0dXJuIG5hbWVzO1xuICAgIH1cbn1cbklmLmtpbmQgPSBcImlmXCI7XG5jbGFzcyBGb3IgZXh0ZW5kcyBCbG9ja05vZGUge1xufVxuRm9yLmtpbmQgPSBcImZvclwiO1xuY2xhc3MgRm9yTG9vcCBleHRlbmRzIEZvciB7XG4gICAgY29uc3RydWN0b3IoaXRlcmF0aW9uKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuaXRlcmF0aW9uID0gaXRlcmF0aW9uO1xuICAgIH1cbiAgICByZW5kZXIob3B0cykge1xuICAgICAgICByZXR1cm4gYGZvcigke3RoaXMuaXRlcmF0aW9ufSlgICsgc3VwZXIucmVuZGVyKG9wdHMpO1xuICAgIH1cbiAgICBvcHRpbWl6ZU5hbWVzKG5hbWVzLCBjb25zdGFudHMpIHtcbiAgICAgICAgaWYgKCFzdXBlci5vcHRpbWl6ZU5hbWVzKG5hbWVzLCBjb25zdGFudHMpKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB0aGlzLml0ZXJhdGlvbiA9IG9wdGltaXplRXhwcih0aGlzLml0ZXJhdGlvbiwgbmFtZXMsIGNvbnN0YW50cyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBnZXQgbmFtZXMoKSB7XG4gICAgICAgIHJldHVybiBhZGROYW1lcyhzdXBlci5uYW1lcywgdGhpcy5pdGVyYXRpb24ubmFtZXMpO1xuICAgIH1cbn1cbmNsYXNzIEZvclJhbmdlIGV4dGVuZHMgRm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih2YXJLaW5kLCBuYW1lLCBmcm9tLCB0bykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnZhcktpbmQgPSB2YXJLaW5kO1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLmZyb20gPSBmcm9tO1xuICAgICAgICB0aGlzLnRvID0gdG87XG4gICAgfVxuICAgIHJlbmRlcihvcHRzKSB7XG4gICAgICAgIGNvbnN0IHZhcktpbmQgPSBvcHRzLmVzNSA/IHNjb3BlXzEudmFyS2luZHMudmFyIDogdGhpcy52YXJLaW5kO1xuICAgICAgICBjb25zdCB7IG5hbWUsIGZyb20sIHRvIH0gPSB0aGlzO1xuICAgICAgICByZXR1cm4gYGZvcigke3ZhcktpbmR9ICR7bmFtZX09JHtmcm9tfTsgJHtuYW1lfTwke3RvfTsgJHtuYW1lfSsrKWAgKyBzdXBlci5yZW5kZXIob3B0cyk7XG4gICAgfVxuICAgIGdldCBuYW1lcygpIHtcbiAgICAgICAgY29uc3QgbmFtZXMgPSBhZGRFeHByTmFtZXMoc3VwZXIubmFtZXMsIHRoaXMuZnJvbSk7XG4gICAgICAgIHJldHVybiBhZGRFeHByTmFtZXMobmFtZXMsIHRoaXMudG8pO1xuICAgIH1cbn1cbmNsYXNzIEZvckl0ZXIgZXh0ZW5kcyBGb3Ige1xuICAgIGNvbnN0cnVjdG9yKGxvb3AsIHZhcktpbmQsIG5hbWUsIGl0ZXJhYmxlKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMubG9vcCA9IGxvb3A7XG4gICAgICAgIHRoaXMudmFyS2luZCA9IHZhcktpbmQ7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMuaXRlcmFibGUgPSBpdGVyYWJsZTtcbiAgICB9XG4gICAgcmVuZGVyKG9wdHMpIHtcbiAgICAgICAgcmV0dXJuIGBmb3IoJHt0aGlzLnZhcktpbmR9ICR7dGhpcy5uYW1lfSAke3RoaXMubG9vcH0gJHt0aGlzLml0ZXJhYmxlfSlgICsgc3VwZXIucmVuZGVyKG9wdHMpO1xuICAgIH1cbiAgICBvcHRpbWl6ZU5hbWVzKG5hbWVzLCBjb25zdGFudHMpIHtcbiAgICAgICAgaWYgKCFzdXBlci5vcHRpbWl6ZU5hbWVzKG5hbWVzLCBjb25zdGFudHMpKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB0aGlzLml0ZXJhYmxlID0gb3B0aW1pemVFeHByKHRoaXMuaXRlcmFibGUsIG5hbWVzLCBjb25zdGFudHMpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgZ2V0IG5hbWVzKCkge1xuICAgICAgICByZXR1cm4gYWRkTmFtZXMoc3VwZXIubmFtZXMsIHRoaXMuaXRlcmFibGUubmFtZXMpO1xuICAgIH1cbn1cbmNsYXNzIEZ1bmMgZXh0ZW5kcyBCbG9ja05vZGUge1xuICAgIGNvbnN0cnVjdG9yKG5hbWUsIGFyZ3MsIGFzeW5jKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMuYXJncyA9IGFyZ3M7XG4gICAgICAgIHRoaXMuYXN5bmMgPSBhc3luYztcbiAgICB9XG4gICAgcmVuZGVyKG9wdHMpIHtcbiAgICAgICAgY29uc3QgX2FzeW5jID0gdGhpcy5hc3luYyA/IFwiYXN5bmMgXCIgOiBcIlwiO1xuICAgICAgICByZXR1cm4gYCR7X2FzeW5jfWZ1bmN0aW9uICR7dGhpcy5uYW1lfSgke3RoaXMuYXJnc30pYCArIHN1cGVyLnJlbmRlcihvcHRzKTtcbiAgICB9XG59XG5GdW5jLmtpbmQgPSBcImZ1bmNcIjtcbmNsYXNzIFJldHVybiBleHRlbmRzIFBhcmVudE5vZGUge1xuICAgIHJlbmRlcihvcHRzKSB7XG4gICAgICAgIHJldHVybiBcInJldHVybiBcIiArIHN1cGVyLnJlbmRlcihvcHRzKTtcbiAgICB9XG59XG5SZXR1cm4ua2luZCA9IFwicmV0dXJuXCI7XG5jbGFzcyBUcnkgZXh0ZW5kcyBCbG9ja05vZGUge1xuICAgIHJlbmRlcihvcHRzKSB7XG4gICAgICAgIGxldCBjb2RlID0gXCJ0cnlcIiArIHN1cGVyLnJlbmRlcihvcHRzKTtcbiAgICAgICAgaWYgKHRoaXMuY2F0Y2gpXG4gICAgICAgICAgICBjb2RlICs9IHRoaXMuY2F0Y2gucmVuZGVyKG9wdHMpO1xuICAgICAgICBpZiAodGhpcy5maW5hbGx5KVxuICAgICAgICAgICAgY29kZSArPSB0aGlzLmZpbmFsbHkucmVuZGVyKG9wdHMpO1xuICAgICAgICByZXR1cm4gY29kZTtcbiAgICB9XG4gICAgb3B0aW1pemVOb2RlcygpIHtcbiAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgc3VwZXIub3B0aW1pemVOb2RlcygpO1xuICAgICAgICAoX2EgPSB0aGlzLmNhdGNoKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Eub3B0aW1pemVOb2RlcygpO1xuICAgICAgICAoX2IgPSB0aGlzLmZpbmFsbHkpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5vcHRpbWl6ZU5vZGVzKCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBvcHRpbWl6ZU5hbWVzKG5hbWVzLCBjb25zdGFudHMpIHtcbiAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgc3VwZXIub3B0aW1pemVOYW1lcyhuYW1lcywgY29uc3RhbnRzKTtcbiAgICAgICAgKF9hID0gdGhpcy5jYXRjaCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLm9wdGltaXplTmFtZXMobmFtZXMsIGNvbnN0YW50cyk7XG4gICAgICAgIChfYiA9IHRoaXMuZmluYWxseSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLm9wdGltaXplTmFtZXMobmFtZXMsIGNvbnN0YW50cyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBnZXQgbmFtZXMoKSB7XG4gICAgICAgIGNvbnN0IG5hbWVzID0gc3VwZXIubmFtZXM7XG4gICAgICAgIGlmICh0aGlzLmNhdGNoKVxuICAgICAgICAgICAgYWRkTmFtZXMobmFtZXMsIHRoaXMuY2F0Y2gubmFtZXMpO1xuICAgICAgICBpZiAodGhpcy5maW5hbGx5KVxuICAgICAgICAgICAgYWRkTmFtZXMobmFtZXMsIHRoaXMuZmluYWxseS5uYW1lcyk7XG4gICAgICAgIHJldHVybiBuYW1lcztcbiAgICB9XG59XG5jbGFzcyBDYXRjaCBleHRlbmRzIEJsb2NrTm9kZSB7XG4gICAgY29uc3RydWN0b3IoZXJyb3IpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5lcnJvciA9IGVycm9yO1xuICAgIH1cbiAgICByZW5kZXIob3B0cykge1xuICAgICAgICByZXR1cm4gYGNhdGNoKCR7dGhpcy5lcnJvcn0pYCArIHN1cGVyLnJlbmRlcihvcHRzKTtcbiAgICB9XG59XG5DYXRjaC5raW5kID0gXCJjYXRjaFwiO1xuY2xhc3MgRmluYWxseSBleHRlbmRzIEJsb2NrTm9kZSB7XG4gICAgcmVuZGVyKG9wdHMpIHtcbiAgICAgICAgcmV0dXJuIFwiZmluYWxseVwiICsgc3VwZXIucmVuZGVyKG9wdHMpO1xuICAgIH1cbn1cbkZpbmFsbHkua2luZCA9IFwiZmluYWxseVwiO1xuY2xhc3MgQ29kZUdlbiB7XG4gICAgY29uc3RydWN0b3IoZXh0U2NvcGUsIG9wdHMgPSB7fSkge1xuICAgICAgICB0aGlzLl92YWx1ZXMgPSB7fTtcbiAgICAgICAgdGhpcy5fYmxvY2tTdGFydHMgPSBbXTtcbiAgICAgICAgdGhpcy5fY29uc3RhbnRzID0ge307XG4gICAgICAgIHRoaXMub3B0cyA9IHsgLi4ub3B0cywgX246IG9wdHMubGluZXMgPyBcIlxcblwiIDogXCJcIiB9O1xuICAgICAgICB0aGlzLl9leHRTY29wZSA9IGV4dFNjb3BlO1xuICAgICAgICB0aGlzLl9zY29wZSA9IG5ldyBzY29wZV8xLlNjb3BlKHsgcGFyZW50OiBleHRTY29wZSB9KTtcbiAgICAgICAgdGhpcy5fbm9kZXMgPSBbbmV3IFJvb3QoKV07XG4gICAgfVxuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcm9vdC5yZW5kZXIodGhpcy5vcHRzKTtcbiAgICB9XG4gICAgLy8gcmV0dXJucyB1bmlxdWUgbmFtZSBpbiB0aGUgaW50ZXJuYWwgc2NvcGVcbiAgICBuYW1lKHByZWZpeCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2NvcGUubmFtZShwcmVmaXgpO1xuICAgIH1cbiAgICAvLyByZXNlcnZlcyB1bmlxdWUgbmFtZSBpbiB0aGUgZXh0ZXJuYWwgc2NvcGVcbiAgICBzY29wZU5hbWUocHJlZml4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9leHRTY29wZS5uYW1lKHByZWZpeCk7XG4gICAgfVxuICAgIC8vIHJlc2VydmVzIHVuaXF1ZSBuYW1lIGluIHRoZSBleHRlcm5hbCBzY29wZSBhbmQgYXNzaWducyB2YWx1ZSB0byBpdFxuICAgIHNjb3BlVmFsdWUocHJlZml4T3JOYW1lLCB2YWx1ZSkge1xuICAgICAgICBjb25zdCBuYW1lID0gdGhpcy5fZXh0U2NvcGUudmFsdWUocHJlZml4T3JOYW1lLCB2YWx1ZSk7XG4gICAgICAgIGNvbnN0IHZzID0gdGhpcy5fdmFsdWVzW25hbWUucHJlZml4XSB8fCAodGhpcy5fdmFsdWVzW25hbWUucHJlZml4XSA9IG5ldyBTZXQoKSk7XG4gICAgICAgIHZzLmFkZChuYW1lKTtcbiAgICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfVxuICAgIGdldFNjb3BlVmFsdWUocHJlZml4LCBrZXlPclJlZikge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXh0U2NvcGUuZ2V0VmFsdWUocHJlZml4LCBrZXlPclJlZik7XG4gICAgfVxuICAgIC8vIHJldHVybiBjb2RlIHRoYXQgYXNzaWducyB2YWx1ZXMgaW4gdGhlIGV4dGVybmFsIHNjb3BlIHRvIHRoZSBuYW1lcyB0aGF0IGFyZSB1c2VkIGludGVybmFsbHlcbiAgICAvLyAoc2FtZSBuYW1lcyB0aGF0IHdlcmUgcmV0dXJuZWQgYnkgZ2VuLnNjb3BlTmFtZSBvciBnZW4uc2NvcGVWYWx1ZSlcbiAgICBzY29wZVJlZnMoc2NvcGVOYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9leHRTY29wZS5zY29wZVJlZnMoc2NvcGVOYW1lLCB0aGlzLl92YWx1ZXMpO1xuICAgIH1cbiAgICBzY29wZUNvZGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9leHRTY29wZS5zY29wZUNvZGUodGhpcy5fdmFsdWVzKTtcbiAgICB9XG4gICAgX2RlZih2YXJLaW5kLCBuYW1lT3JQcmVmaXgsIHJocywgY29uc3RhbnQpIHtcbiAgICAgICAgY29uc3QgbmFtZSA9IHRoaXMuX3Njb3BlLnRvTmFtZShuYW1lT3JQcmVmaXgpO1xuICAgICAgICBpZiAocmhzICE9PSB1bmRlZmluZWQgJiYgY29uc3RhbnQpXG4gICAgICAgICAgICB0aGlzLl9jb25zdGFudHNbbmFtZS5zdHJdID0gcmhzO1xuICAgICAgICB0aGlzLl9sZWFmTm9kZShuZXcgRGVmKHZhcktpbmQsIG5hbWUsIHJocykpO1xuICAgICAgICByZXR1cm4gbmFtZTtcbiAgICB9XG4gICAgLy8gYGNvbnN0YCBkZWNsYXJhdGlvbiAoYHZhcmAgaW4gZXM1IG1vZGUpXG4gICAgY29uc3QobmFtZU9yUHJlZml4LCByaHMsIF9jb25zdGFudCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGVmKHNjb3BlXzEudmFyS2luZHMuY29uc3QsIG5hbWVPclByZWZpeCwgcmhzLCBfY29uc3RhbnQpO1xuICAgIH1cbiAgICAvLyBgbGV0YCBkZWNsYXJhdGlvbiB3aXRoIG9wdGlvbmFsIGFzc2lnbm1lbnQgKGB2YXJgIGluIGVzNSBtb2RlKVxuICAgIGxldChuYW1lT3JQcmVmaXgsIHJocywgX2NvbnN0YW50KSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kZWYoc2NvcGVfMS52YXJLaW5kcy5sZXQsIG5hbWVPclByZWZpeCwgcmhzLCBfY29uc3RhbnQpO1xuICAgIH1cbiAgICAvLyBgdmFyYCBkZWNsYXJhdGlvbiB3aXRoIG9wdGlvbmFsIGFzc2lnbm1lbnRcbiAgICB2YXIobmFtZU9yUHJlZml4LCByaHMsIF9jb25zdGFudCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGVmKHNjb3BlXzEudmFyS2luZHMudmFyLCBuYW1lT3JQcmVmaXgsIHJocywgX2NvbnN0YW50KTtcbiAgICB9XG4gICAgLy8gYXNzaWdubWVudCBjb2RlXG4gICAgYXNzaWduKGxocywgcmhzLCBzaWRlRWZmZWN0cykge1xuICAgICAgICByZXR1cm4gdGhpcy5fbGVhZk5vZGUobmV3IEFzc2lnbihsaHMsIHJocywgc2lkZUVmZmVjdHMpKTtcbiAgICB9XG4gICAgLy8gYCs9YCBjb2RlXG4gICAgYWRkKGxocywgcmhzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sZWFmTm9kZShuZXcgQXNzaWduT3AobGhzLCBleHBvcnRzLm9wZXJhdG9ycy5BREQsIHJocykpO1xuICAgIH1cbiAgICAvLyBhcHBlbmRzIHBhc3NlZCBTYWZlRXhwciB0byBjb2RlIG9yIGV4ZWN1dGVzIEJsb2NrXG4gICAgY29kZShjKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYyA9PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgICAgICBjKCk7XG4gICAgICAgIGVsc2UgaWYgKGMgIT09IGNvZGVfMS5uaWwpXG4gICAgICAgICAgICB0aGlzLl9sZWFmTm9kZShuZXcgQW55Q29kZShjKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvLyByZXR1cm5zIGNvZGUgZm9yIG9iamVjdCBsaXRlcmFsIGZvciB0aGUgcGFzc2VkIGFyZ3VtZW50IGxpc3Qgb2Yga2V5LXZhbHVlIHBhaXJzXG4gICAgb2JqZWN0KC4uLmtleVZhbHVlcykge1xuICAgICAgICBjb25zdCBjb2RlID0gW1wie1wiXTtcbiAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2Yga2V5VmFsdWVzKSB7XG4gICAgICAgICAgICBpZiAoY29kZS5sZW5ndGggPiAxKVxuICAgICAgICAgICAgICAgIGNvZGUucHVzaChcIixcIik7XG4gICAgICAgICAgICBjb2RlLnB1c2goa2V5KTtcbiAgICAgICAgICAgIGlmIChrZXkgIT09IHZhbHVlIHx8IHRoaXMub3B0cy5lczUpIHtcbiAgICAgICAgICAgICAgICBjb2RlLnB1c2goXCI6XCIpO1xuICAgICAgICAgICAgICAgICgwLCBjb2RlXzEuYWRkQ29kZUFyZykoY29kZSwgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvZGUucHVzaChcIn1cIik7XG4gICAgICAgIHJldHVybiBuZXcgY29kZV8xLl9Db2RlKGNvZGUpO1xuICAgIH1cbiAgICAvLyBgaWZgIGNsYXVzZSAob3Igc3RhdGVtZW50IGlmIGB0aGVuQm9keWAgYW5kLCBvcHRpb25hbGx5LCBgZWxzZUJvZHlgIGFyZSBwYXNzZWQpXG4gICAgaWYoY29uZGl0aW9uLCB0aGVuQm9keSwgZWxzZUJvZHkpIHtcbiAgICAgICAgdGhpcy5fYmxvY2tOb2RlKG5ldyBJZihjb25kaXRpb24pKTtcbiAgICAgICAgaWYgKHRoZW5Cb2R5ICYmIGVsc2VCb2R5KSB7XG4gICAgICAgICAgICB0aGlzLmNvZGUodGhlbkJvZHkpLmVsc2UoKS5jb2RlKGVsc2VCb2R5KS5lbmRJZigpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoZW5Cb2R5KSB7XG4gICAgICAgICAgICB0aGlzLmNvZGUodGhlbkJvZHkpLmVuZElmKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZWxzZUJvZHkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ29kZUdlbjogXCJlbHNlXCIgYm9keSB3aXRob3V0IFwidGhlblwiIGJvZHknKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLy8gYGVsc2UgaWZgIGNsYXVzZSAtIGludmFsaWQgd2l0aG91dCBgaWZgIG9yIGFmdGVyIGBlbHNlYCBjbGF1c2VzXG4gICAgZWxzZUlmKGNvbmRpdGlvbikge1xuICAgICAgICByZXR1cm4gdGhpcy5fZWxzZU5vZGUobmV3IElmKGNvbmRpdGlvbikpO1xuICAgIH1cbiAgICAvLyBgZWxzZWAgY2xhdXNlIC0gb25seSB2YWxpZCBhZnRlciBgaWZgIG9yIGBlbHNlIGlmYCBjbGF1c2VzXG4gICAgZWxzZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Vsc2VOb2RlKG5ldyBFbHNlKCkpO1xuICAgIH1cbiAgICAvLyBlbmQgYGlmYCBzdGF0ZW1lbnQgKG5lZWRlZCBpZiBnZW4uaWYgd2FzIHVzZWQgb25seSB3aXRoIGNvbmRpdGlvbilcbiAgICBlbmRJZigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VuZEJsb2NrTm9kZShJZiwgRWxzZSk7XG4gICAgfVxuICAgIF9mb3Iobm9kZSwgZm9yQm9keSkge1xuICAgICAgICB0aGlzLl9ibG9ja05vZGUobm9kZSk7XG4gICAgICAgIGlmIChmb3JCb2R5KVxuICAgICAgICAgICAgdGhpcy5jb2RlKGZvckJvZHkpLmVuZEZvcigpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLy8gYSBnZW5lcmljIGBmb3JgIGNsYXVzZSAob3Igc3RhdGVtZW50IGlmIGBmb3JCb2R5YCBpcyBwYXNzZWQpXG4gICAgZm9yKGl0ZXJhdGlvbiwgZm9yQm9keSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZm9yKG5ldyBGb3JMb29wKGl0ZXJhdGlvbiksIGZvckJvZHkpO1xuICAgIH1cbiAgICAvLyBgZm9yYCBzdGF0ZW1lbnQgZm9yIGEgcmFuZ2Ugb2YgdmFsdWVzXG4gICAgZm9yUmFuZ2UobmFtZU9yUHJlZml4LCBmcm9tLCB0bywgZm9yQm9keSwgdmFyS2luZCA9IHRoaXMub3B0cy5lczUgPyBzY29wZV8xLnZhcktpbmRzLnZhciA6IHNjb3BlXzEudmFyS2luZHMubGV0KSB7XG4gICAgICAgIGNvbnN0IG5hbWUgPSB0aGlzLl9zY29wZS50b05hbWUobmFtZU9yUHJlZml4KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ZvcihuZXcgRm9yUmFuZ2UodmFyS2luZCwgbmFtZSwgZnJvbSwgdG8pLCAoKSA9PiBmb3JCb2R5KG5hbWUpKTtcbiAgICB9XG4gICAgLy8gYGZvci1vZmAgc3RhdGVtZW50IChpbiBlczUgbW9kZSByZXBsYWNlIHdpdGggYSBub3JtYWwgZm9yIGxvb3ApXG4gICAgZm9yT2YobmFtZU9yUHJlZml4LCBpdGVyYWJsZSwgZm9yQm9keSwgdmFyS2luZCA9IHNjb3BlXzEudmFyS2luZHMuY29uc3QpIHtcbiAgICAgICAgY29uc3QgbmFtZSA9IHRoaXMuX3Njb3BlLnRvTmFtZShuYW1lT3JQcmVmaXgpO1xuICAgICAgICBpZiAodGhpcy5vcHRzLmVzNSkge1xuICAgICAgICAgICAgY29uc3QgYXJyID0gaXRlcmFibGUgaW5zdGFuY2VvZiBjb2RlXzEuTmFtZSA/IGl0ZXJhYmxlIDogdGhpcy52YXIoXCJfYXJyXCIsIGl0ZXJhYmxlKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZvclJhbmdlKFwiX2lcIiwgMCwgKDAsIGNvZGVfMS5fKSBgJHthcnJ9Lmxlbmd0aGAsIChpKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy52YXIobmFtZSwgKDAsIGNvZGVfMS5fKSBgJHthcnJ9WyR7aX1dYCk7XG4gICAgICAgICAgICAgICAgZm9yQm9keShuYW1lKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9mb3IobmV3IEZvckl0ZXIoXCJvZlwiLCB2YXJLaW5kLCBuYW1lLCBpdGVyYWJsZSksICgpID0+IGZvckJvZHkobmFtZSkpO1xuICAgIH1cbiAgICAvLyBgZm9yLWluYCBzdGF0ZW1lbnQuXG4gICAgLy8gV2l0aCBvcHRpb24gYG93blByb3BlcnRpZXNgIHJlcGxhY2VkIHdpdGggYSBgZm9yLW9mYCBsb29wIGZvciBvYmplY3Qga2V5c1xuICAgIGZvckluKG5hbWVPclByZWZpeCwgb2JqLCBmb3JCb2R5LCB2YXJLaW5kID0gdGhpcy5vcHRzLmVzNSA/IHNjb3BlXzEudmFyS2luZHMudmFyIDogc2NvcGVfMS52YXJLaW5kcy5jb25zdCkge1xuICAgICAgICBpZiAodGhpcy5vcHRzLm93blByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZvck9mKG5hbWVPclByZWZpeCwgKDAsIGNvZGVfMS5fKSBgT2JqZWN0LmtleXMoJHtvYmp9KWAsIGZvckJvZHkpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG5hbWUgPSB0aGlzLl9zY29wZS50b05hbWUobmFtZU9yUHJlZml4KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ZvcihuZXcgRm9ySXRlcihcImluXCIsIHZhcktpbmQsIG5hbWUsIG9iaiksICgpID0+IGZvckJvZHkobmFtZSkpO1xuICAgIH1cbiAgICAvLyBlbmQgYGZvcmAgbG9vcFxuICAgIGVuZEZvcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VuZEJsb2NrTm9kZShGb3IpO1xuICAgIH1cbiAgICAvLyBgbGFiZWxgIHN0YXRlbWVudFxuICAgIGxhYmVsKGxhYmVsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sZWFmTm9kZShuZXcgTGFiZWwobGFiZWwpKTtcbiAgICB9XG4gICAgLy8gYGJyZWFrYCBzdGF0ZW1lbnRcbiAgICBicmVhayhsYWJlbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbGVhZk5vZGUobmV3IEJyZWFrKGxhYmVsKSk7XG4gICAgfVxuICAgIC8vIGByZXR1cm5gIHN0YXRlbWVudFxuICAgIHJldHVybih2YWx1ZSkge1xuICAgICAgICBjb25zdCBub2RlID0gbmV3IFJldHVybigpO1xuICAgICAgICB0aGlzLl9ibG9ja05vZGUobm9kZSk7XG4gICAgICAgIHRoaXMuY29kZSh2YWx1ZSk7XG4gICAgICAgIGlmIChub2RlLm5vZGVzLmxlbmd0aCAhPT0gMSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ29kZUdlbjogXCJyZXR1cm5cIiBzaG91bGQgaGF2ZSBvbmUgbm9kZScpO1xuICAgICAgICByZXR1cm4gdGhpcy5fZW5kQmxvY2tOb2RlKFJldHVybik7XG4gICAgfVxuICAgIC8vIGB0cnlgIHN0YXRlbWVudFxuICAgIHRyeSh0cnlCb2R5LCBjYXRjaENvZGUsIGZpbmFsbHlDb2RlKSB7XG4gICAgICAgIGlmICghY2F0Y2hDb2RlICYmICFmaW5hbGx5Q29kZSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ29kZUdlbjogXCJ0cnlcIiB3aXRob3V0IFwiY2F0Y2hcIiBhbmQgXCJmaW5hbGx5XCInKTtcbiAgICAgICAgY29uc3Qgbm9kZSA9IG5ldyBUcnkoKTtcbiAgICAgICAgdGhpcy5fYmxvY2tOb2RlKG5vZGUpO1xuICAgICAgICB0aGlzLmNvZGUodHJ5Qm9keSk7XG4gICAgICAgIGlmIChjYXRjaENvZGUpIHtcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gdGhpcy5uYW1lKFwiZVwiKTtcbiAgICAgICAgICAgIHRoaXMuX2N1cnJOb2RlID0gbm9kZS5jYXRjaCA9IG5ldyBDYXRjaChlcnJvcik7XG4gICAgICAgICAgICBjYXRjaENvZGUoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmaW5hbGx5Q29kZSkge1xuICAgICAgICAgICAgdGhpcy5fY3Vyck5vZGUgPSBub2RlLmZpbmFsbHkgPSBuZXcgRmluYWxseSgpO1xuICAgICAgICAgICAgdGhpcy5jb2RlKGZpbmFsbHlDb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fZW5kQmxvY2tOb2RlKENhdGNoLCBGaW5hbGx5KTtcbiAgICB9XG4gICAgLy8gYHRocm93YCBzdGF0ZW1lbnRcbiAgICB0aHJvdyhlcnJvcikge1xuICAgICAgICByZXR1cm4gdGhpcy5fbGVhZk5vZGUobmV3IFRocm93KGVycm9yKSk7XG4gICAgfVxuICAgIC8vIHN0YXJ0IHNlbGYtYmFsYW5jaW5nIGJsb2NrXG4gICAgYmxvY2soYm9keSwgbm9kZUNvdW50KSB7XG4gICAgICAgIHRoaXMuX2Jsb2NrU3RhcnRzLnB1c2godGhpcy5fbm9kZXMubGVuZ3RoKTtcbiAgICAgICAgaWYgKGJvZHkpXG4gICAgICAgICAgICB0aGlzLmNvZGUoYm9keSkuZW5kQmxvY2sobm9kZUNvdW50KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8vIGVuZCB0aGUgY3VycmVudCBzZWxmLWJhbGFuY2luZyBibG9ja1xuICAgIGVuZEJsb2NrKG5vZGVDb3VudCkge1xuICAgICAgICBjb25zdCBsZW4gPSB0aGlzLl9ibG9ja1N0YXJ0cy5wb3AoKTtcbiAgICAgICAgaWYgKGxlbiA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ29kZUdlbjogbm90IGluIHNlbGYtYmFsYW5jaW5nIGJsb2NrXCIpO1xuICAgICAgICBjb25zdCB0b0Nsb3NlID0gdGhpcy5fbm9kZXMubGVuZ3RoIC0gbGVuO1xuICAgICAgICBpZiAodG9DbG9zZSA8IDAgfHwgKG5vZGVDb3VudCAhPT0gdW5kZWZpbmVkICYmIHRvQ2xvc2UgIT09IG5vZGVDb3VudCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ29kZUdlbjogd3JvbmcgbnVtYmVyIG9mIG5vZGVzOiAke3RvQ2xvc2V9IHZzICR7bm9kZUNvdW50fSBleHBlY3RlZGApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX25vZGVzLmxlbmd0aCA9IGxlbjtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8vIGBmdW5jdGlvbmAgaGVhZGluZyAob3IgZGVmaW5pdGlvbiBpZiBmdW5jQm9keSBpcyBwYXNzZWQpXG4gICAgZnVuYyhuYW1lLCBhcmdzID0gY29kZV8xLm5pbCwgYXN5bmMsIGZ1bmNCb2R5KSB7XG4gICAgICAgIHRoaXMuX2Jsb2NrTm9kZShuZXcgRnVuYyhuYW1lLCBhcmdzLCBhc3luYykpO1xuICAgICAgICBpZiAoZnVuY0JvZHkpXG4gICAgICAgICAgICB0aGlzLmNvZGUoZnVuY0JvZHkpLmVuZEZ1bmMoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8vIGVuZCBmdW5jdGlvbiBkZWZpbml0aW9uXG4gICAgZW5kRnVuYygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VuZEJsb2NrTm9kZShGdW5jKTtcbiAgICB9XG4gICAgb3B0aW1pemUobiA9IDEpIHtcbiAgICAgICAgd2hpbGUgKG4tLSA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuX3Jvb3Qub3B0aW1pemVOb2RlcygpO1xuICAgICAgICAgICAgdGhpcy5fcm9vdC5vcHRpbWl6ZU5hbWVzKHRoaXMuX3Jvb3QubmFtZXMsIHRoaXMuX2NvbnN0YW50cyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgX2xlYWZOb2RlKG5vZGUpIHtcbiAgICAgICAgdGhpcy5fY3Vyck5vZGUubm9kZXMucHVzaChub2RlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIF9ibG9ja05vZGUobm9kZSkge1xuICAgICAgICB0aGlzLl9jdXJyTm9kZS5ub2Rlcy5wdXNoKG5vZGUpO1xuICAgICAgICB0aGlzLl9ub2Rlcy5wdXNoKG5vZGUpO1xuICAgIH1cbiAgICBfZW5kQmxvY2tOb2RlKE4xLCBOMikge1xuICAgICAgICBjb25zdCBuID0gdGhpcy5fY3Vyck5vZGU7XG4gICAgICAgIGlmIChuIGluc3RhbmNlb2YgTjEgfHwgKE4yICYmIG4gaW5zdGFuY2VvZiBOMikpIHtcbiAgICAgICAgICAgIHRoaXMuX25vZGVzLnBvcCgpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb2RlR2VuOiBub3QgaW4gYmxvY2sgXCIke04yID8gYCR7TjEua2luZH0vJHtOMi5raW5kfWAgOiBOMS5raW5kfVwiYCk7XG4gICAgfVxuICAgIF9lbHNlTm9kZShub2RlKSB7XG4gICAgICAgIGNvbnN0IG4gPSB0aGlzLl9jdXJyTm9kZTtcbiAgICAgICAgaWYgKCEobiBpbnN0YW5jZW9mIElmKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDb2RlR2VuOiBcImVsc2VcIiB3aXRob3V0IFwiaWZcIicpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2N1cnJOb2RlID0gbi5lbHNlID0gbm9kZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGdldCBfcm9vdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX25vZGVzWzBdO1xuICAgIH1cbiAgICBnZXQgX2N1cnJOb2RlKCkge1xuICAgICAgICBjb25zdCBucyA9IHRoaXMuX25vZGVzO1xuICAgICAgICByZXR1cm4gbnNbbnMubGVuZ3RoIC0gMV07XG4gICAgfVxuICAgIHNldCBfY3Vyck5vZGUobm9kZSkge1xuICAgICAgICBjb25zdCBucyA9IHRoaXMuX25vZGVzO1xuICAgICAgICBuc1tucy5sZW5ndGggLSAxXSA9IG5vZGU7XG4gICAgfVxufVxuZXhwb3J0cy5Db2RlR2VuID0gQ29kZUdlbjtcbmZ1bmN0aW9uIGFkZE5hbWVzKG5hbWVzLCBmcm9tKSB7XG4gICAgZm9yIChjb25zdCBuIGluIGZyb20pXG4gICAgICAgIG5hbWVzW25dID0gKG5hbWVzW25dIHx8IDApICsgKGZyb21bbl0gfHwgMCk7XG4gICAgcmV0dXJuIG5hbWVzO1xufVxuZnVuY3Rpb24gYWRkRXhwck5hbWVzKG5hbWVzLCBmcm9tKSB7XG4gICAgcmV0dXJuIGZyb20gaW5zdGFuY2VvZiBjb2RlXzEuX0NvZGVPck5hbWUgPyBhZGROYW1lcyhuYW1lcywgZnJvbS5uYW1lcykgOiBuYW1lcztcbn1cbmZ1bmN0aW9uIG9wdGltaXplRXhwcihleHByLCBuYW1lcywgY29uc3RhbnRzKSB7XG4gICAgaWYgKGV4cHIgaW5zdGFuY2VvZiBjb2RlXzEuTmFtZSlcbiAgICAgICAgcmV0dXJuIHJlcGxhY2VOYW1lKGV4cHIpO1xuICAgIGlmICghY2FuT3B0aW1pemUoZXhwcikpXG4gICAgICAgIHJldHVybiBleHByO1xuICAgIHJldHVybiBuZXcgY29kZV8xLl9Db2RlKGV4cHIuX2l0ZW1zLnJlZHVjZSgoaXRlbXMsIGMpID0+IHtcbiAgICAgICAgaWYgKGMgaW5zdGFuY2VvZiBjb2RlXzEuTmFtZSlcbiAgICAgICAgICAgIGMgPSByZXBsYWNlTmFtZShjKTtcbiAgICAgICAgaWYgKGMgaW5zdGFuY2VvZiBjb2RlXzEuX0NvZGUpXG4gICAgICAgICAgICBpdGVtcy5wdXNoKC4uLmMuX2l0ZW1zKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgaXRlbXMucHVzaChjKTtcbiAgICAgICAgcmV0dXJuIGl0ZW1zO1xuICAgIH0sIFtdKSk7XG4gICAgZnVuY3Rpb24gcmVwbGFjZU5hbWUobikge1xuICAgICAgICBjb25zdCBjID0gY29uc3RhbnRzW24uc3RyXTtcbiAgICAgICAgaWYgKGMgPT09IHVuZGVmaW5lZCB8fCBuYW1lc1tuLnN0cl0gIT09IDEpXG4gICAgICAgICAgICByZXR1cm4gbjtcbiAgICAgICAgZGVsZXRlIG5hbWVzW24uc3RyXTtcbiAgICAgICAgcmV0dXJuIGM7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNhbk9wdGltaXplKGUpIHtcbiAgICAgICAgcmV0dXJuIChlIGluc3RhbmNlb2YgY29kZV8xLl9Db2RlICYmXG4gICAgICAgICAgICBlLl9pdGVtcy5zb21lKChjKSA9PiBjIGluc3RhbmNlb2YgY29kZV8xLk5hbWUgJiYgbmFtZXNbYy5zdHJdID09PSAxICYmIGNvbnN0YW50c1tjLnN0cl0gIT09IHVuZGVmaW5lZCkpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHN1YnRyYWN0TmFtZXMobmFtZXMsIGZyb20pIHtcbiAgICBmb3IgKGNvbnN0IG4gaW4gZnJvbSlcbiAgICAgICAgbmFtZXNbbl0gPSAobmFtZXNbbl0gfHwgMCkgLSAoZnJvbVtuXSB8fCAwKTtcbn1cbmZ1bmN0aW9uIG5vdCh4KSB7XG4gICAgcmV0dXJuIHR5cGVvZiB4ID09IFwiYm9vbGVhblwiIHx8IHR5cGVvZiB4ID09IFwibnVtYmVyXCIgfHwgeCA9PT0gbnVsbCA/ICF4IDogKDAsIGNvZGVfMS5fKSBgISR7cGFyKHgpfWA7XG59XG5leHBvcnRzLm5vdCA9IG5vdDtcbmNvbnN0IGFuZENvZGUgPSBtYXBwZW5kKGV4cG9ydHMub3BlcmF0b3JzLkFORCk7XG4vLyBib29sZWFuIEFORCAoJiYpIGV4cHJlc3Npb24gd2l0aCB0aGUgcGFzc2VkIGFyZ3VtZW50c1xuZnVuY3Rpb24gYW5kKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gYXJncy5yZWR1Y2UoYW5kQ29kZSk7XG59XG5leHBvcnRzLmFuZCA9IGFuZDtcbmNvbnN0IG9yQ29kZSA9IG1hcHBlbmQoZXhwb3J0cy5vcGVyYXRvcnMuT1IpO1xuLy8gYm9vbGVhbiBPUiAofHwpIGV4cHJlc3Npb24gd2l0aCB0aGUgcGFzc2VkIGFyZ3VtZW50c1xuZnVuY3Rpb24gb3IoLi4uYXJncykge1xuICAgIHJldHVybiBhcmdzLnJlZHVjZShvckNvZGUpO1xufVxuZXhwb3J0cy5vciA9IG9yO1xuZnVuY3Rpb24gbWFwcGVuZChvcCkge1xuICAgIHJldHVybiAoeCwgeSkgPT4gKHggPT09IGNvZGVfMS5uaWwgPyB5IDogeSA9PT0gY29kZV8xLm5pbCA/IHggOiAoMCwgY29kZV8xLl8pIGAke3Bhcih4KX0gJHtvcH0gJHtwYXIoeSl9YCk7XG59XG5mdW5jdGlvbiBwYXIoeCkge1xuICAgIHJldHVybiB4IGluc3RhbmNlb2YgY29kZV8xLk5hbWUgPyB4IDogKDAsIGNvZGVfMS5fKSBgKCR7eH0pYDtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWluZGV4LmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXhwb3J0cy5WYWx1ZVNjb3BlID0gZXhwb3J0cy5WYWx1ZVNjb3BlTmFtZSA9IGV4cG9ydHMuU2NvcGUgPSBleHBvcnRzLnZhcktpbmRzID0gZXhwb3J0cy5Vc2VkVmFsdWVTdGF0ZSA9IHZvaWQgMDtcbmNvbnN0IGNvZGVfMSA9IHJlcXVpcmUoXCIuL2NvZGVcIik7XG5jbGFzcyBWYWx1ZUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKG5hbWUpIHtcbiAgICAgICAgc3VwZXIoYENvZGVHZW46IFwiY29kZVwiIGZvciAke25hbWV9IG5vdCBkZWZpbmVkYCk7XG4gICAgICAgIHRoaXMudmFsdWUgPSBuYW1lLnZhbHVlO1xuICAgIH1cbn1cbnZhciBVc2VkVmFsdWVTdGF0ZTtcbihmdW5jdGlvbiAoVXNlZFZhbHVlU3RhdGUpIHtcbiAgICBVc2VkVmFsdWVTdGF0ZVtVc2VkVmFsdWVTdGF0ZVtcIlN0YXJ0ZWRcIl0gPSAwXSA9IFwiU3RhcnRlZFwiO1xuICAgIFVzZWRWYWx1ZVN0YXRlW1VzZWRWYWx1ZVN0YXRlW1wiQ29tcGxldGVkXCJdID0gMV0gPSBcIkNvbXBsZXRlZFwiO1xufSkoVXNlZFZhbHVlU3RhdGUgPSBleHBvcnRzLlVzZWRWYWx1ZVN0YXRlIHx8IChleHBvcnRzLlVzZWRWYWx1ZVN0YXRlID0ge30pKTtcbmV4cG9ydHMudmFyS2luZHMgPSB7XG4gICAgY29uc3Q6IG5ldyBjb2RlXzEuTmFtZShcImNvbnN0XCIpLFxuICAgIGxldDogbmV3IGNvZGVfMS5OYW1lKFwibGV0XCIpLFxuICAgIHZhcjogbmV3IGNvZGVfMS5OYW1lKFwidmFyXCIpLFxufTtcbmNsYXNzIFNjb3BlIHtcbiAgICBjb25zdHJ1Y3Rvcih7IHByZWZpeGVzLCBwYXJlbnQgfSA9IHt9KSB7XG4gICAgICAgIHRoaXMuX25hbWVzID0ge307XG4gICAgICAgIHRoaXMuX3ByZWZpeGVzID0gcHJlZml4ZXM7XG4gICAgICAgIHRoaXMuX3BhcmVudCA9IHBhcmVudDtcbiAgICB9XG4gICAgdG9OYW1lKG5hbWVPclByZWZpeCkge1xuICAgICAgICByZXR1cm4gbmFtZU9yUHJlZml4IGluc3RhbmNlb2YgY29kZV8xLk5hbWUgPyBuYW1lT3JQcmVmaXggOiB0aGlzLm5hbWUobmFtZU9yUHJlZml4KTtcbiAgICB9XG4gICAgbmFtZShwcmVmaXgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBjb2RlXzEuTmFtZSh0aGlzLl9uZXdOYW1lKHByZWZpeCkpO1xuICAgIH1cbiAgICBfbmV3TmFtZShwcmVmaXgpIHtcbiAgICAgICAgY29uc3QgbmcgPSB0aGlzLl9uYW1lc1twcmVmaXhdIHx8IHRoaXMuX25hbWVHcm91cChwcmVmaXgpO1xuICAgICAgICByZXR1cm4gYCR7cHJlZml4fSR7bmcuaW5kZXgrK31gO1xuICAgIH1cbiAgICBfbmFtZUdyb3VwKHByZWZpeCkge1xuICAgICAgICB2YXIgX2EsIF9iO1xuICAgICAgICBpZiAoKChfYiA9IChfYSA9IHRoaXMuX3BhcmVudCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLl9wcmVmaXhlcykgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLmhhcyhwcmVmaXgpKSB8fCAodGhpcy5fcHJlZml4ZXMgJiYgIXRoaXMuX3ByZWZpeGVzLmhhcyhwcmVmaXgpKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb2RlR2VuOiBwcmVmaXggXCIke3ByZWZpeH1cIiBpcyBub3QgYWxsb3dlZCBpbiB0aGlzIHNjb3BlYCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICh0aGlzLl9uYW1lc1twcmVmaXhdID0geyBwcmVmaXgsIGluZGV4OiAwIH0pO1xuICAgIH1cbn1cbmV4cG9ydHMuU2NvcGUgPSBTY29wZTtcbmNsYXNzIFZhbHVlU2NvcGVOYW1lIGV4dGVuZHMgY29kZV8xLk5hbWUge1xuICAgIGNvbnN0cnVjdG9yKHByZWZpeCwgbmFtZVN0cikge1xuICAgICAgICBzdXBlcihuYW1lU3RyKTtcbiAgICAgICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gICAgfVxuICAgIHNldFZhbHVlKHZhbHVlLCB7IHByb3BlcnR5LCBpdGVtSW5kZXggfSkge1xuICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgIHRoaXMuc2NvcGVQYXRoID0gKDAsIGNvZGVfMS5fKSBgLiR7bmV3IGNvZGVfMS5OYW1lKHByb3BlcnR5KX1bJHtpdGVtSW5kZXh9XWA7XG4gICAgfVxufVxuZXhwb3J0cy5WYWx1ZVNjb3BlTmFtZSA9IFZhbHVlU2NvcGVOYW1lO1xuY29uc3QgbGluZSA9ICgwLCBjb2RlXzEuXykgYFxcbmA7XG5jbGFzcyBWYWx1ZVNjb3BlIGV4dGVuZHMgU2NvcGUge1xuICAgIGNvbnN0cnVjdG9yKG9wdHMpIHtcbiAgICAgICAgc3VwZXIob3B0cyk7XG4gICAgICAgIHRoaXMuX3ZhbHVlcyA9IHt9O1xuICAgICAgICB0aGlzLl9zY29wZSA9IG9wdHMuc2NvcGU7XG4gICAgICAgIHRoaXMub3B0cyA9IHsgLi4ub3B0cywgX246IG9wdHMubGluZXMgPyBsaW5lIDogY29kZV8xLm5pbCB9O1xuICAgIH1cbiAgICBnZXQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zY29wZTtcbiAgICB9XG4gICAgbmFtZShwcmVmaXgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBWYWx1ZVNjb3BlTmFtZShwcmVmaXgsIHRoaXMuX25ld05hbWUocHJlZml4KSk7XG4gICAgfVxuICAgIHZhbHVlKG5hbWVPclByZWZpeCwgdmFsdWUpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICBpZiAodmFsdWUucmVmID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb2RlR2VuOiByZWYgbXVzdCBiZSBwYXNzZWQgaW4gdmFsdWVcIik7XG4gICAgICAgIGNvbnN0IG5hbWUgPSB0aGlzLnRvTmFtZShuYW1lT3JQcmVmaXgpO1xuICAgICAgICBjb25zdCB7IHByZWZpeCB9ID0gbmFtZTtcbiAgICAgICAgY29uc3QgdmFsdWVLZXkgPSAoX2EgPSB2YWx1ZS5rZXkpICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IHZhbHVlLnJlZjtcbiAgICAgICAgbGV0IHZzID0gdGhpcy5fdmFsdWVzW3ByZWZpeF07XG4gICAgICAgIGlmICh2cykge1xuICAgICAgICAgICAgY29uc3QgX25hbWUgPSB2cy5nZXQodmFsdWVLZXkpO1xuICAgICAgICAgICAgaWYgKF9uYW1lKVxuICAgICAgICAgICAgICAgIHJldHVybiBfbmFtZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZzID0gdGhpcy5fdmFsdWVzW3ByZWZpeF0gPSBuZXcgTWFwKCk7XG4gICAgICAgIH1cbiAgICAgICAgdnMuc2V0KHZhbHVlS2V5LCBuYW1lKTtcbiAgICAgICAgY29uc3QgcyA9IHRoaXMuX3Njb3BlW3ByZWZpeF0gfHwgKHRoaXMuX3Njb3BlW3ByZWZpeF0gPSBbXSk7XG4gICAgICAgIGNvbnN0IGl0ZW1JbmRleCA9IHMubGVuZ3RoO1xuICAgICAgICBzW2l0ZW1JbmRleF0gPSB2YWx1ZS5yZWY7XG4gICAgICAgIG5hbWUuc2V0VmFsdWUodmFsdWUsIHsgcHJvcGVydHk6IHByZWZpeCwgaXRlbUluZGV4IH0pO1xuICAgICAgICByZXR1cm4gbmFtZTtcbiAgICB9XG4gICAgZ2V0VmFsdWUocHJlZml4LCBrZXlPclJlZikge1xuICAgICAgICBjb25zdCB2cyA9IHRoaXMuX3ZhbHVlc1twcmVmaXhdO1xuICAgICAgICBpZiAoIXZzKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICByZXR1cm4gdnMuZ2V0KGtleU9yUmVmKTtcbiAgICB9XG4gICAgc2NvcGVSZWZzKHNjb3BlTmFtZSwgdmFsdWVzID0gdGhpcy5fdmFsdWVzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZWR1Y2VWYWx1ZXModmFsdWVzLCAobmFtZSkgPT4ge1xuICAgICAgICAgICAgaWYgKG5hbWUuc2NvcGVQYXRoID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb2RlR2VuOiBuYW1lIFwiJHtuYW1lfVwiIGhhcyBubyB2YWx1ZWApO1xuICAgICAgICAgICAgcmV0dXJuICgwLCBjb2RlXzEuXykgYCR7c2NvcGVOYW1lfSR7bmFtZS5zY29wZVBhdGh9YDtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHNjb3BlQ29kZSh2YWx1ZXMgPSB0aGlzLl92YWx1ZXMsIHVzZWRWYWx1ZXMsIGdldENvZGUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlZHVjZVZhbHVlcyh2YWx1ZXMsIChuYW1lKSA9PiB7XG4gICAgICAgICAgICBpZiAobmFtZS52YWx1ZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ29kZUdlbjogbmFtZSBcIiR7bmFtZX1cIiBoYXMgbm8gdmFsdWVgKTtcbiAgICAgICAgICAgIHJldHVybiBuYW1lLnZhbHVlLmNvZGU7XG4gICAgICAgIH0sIHVzZWRWYWx1ZXMsIGdldENvZGUpO1xuICAgIH1cbiAgICBfcmVkdWNlVmFsdWVzKHZhbHVlcywgdmFsdWVDb2RlLCB1c2VkVmFsdWVzID0ge30sIGdldENvZGUpIHtcbiAgICAgICAgbGV0IGNvZGUgPSBjb2RlXzEubmlsO1xuICAgICAgICBmb3IgKGNvbnN0IHByZWZpeCBpbiB2YWx1ZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZzID0gdmFsdWVzW3ByZWZpeF07XG4gICAgICAgICAgICBpZiAoIXZzKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgY29uc3QgbmFtZVNldCA9ICh1c2VkVmFsdWVzW3ByZWZpeF0gPSB1c2VkVmFsdWVzW3ByZWZpeF0gfHwgbmV3IE1hcCgpKTtcbiAgICAgICAgICAgIHZzLmZvckVhY2goKG5hbWUpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAobmFtZVNldC5oYXMobmFtZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICBuYW1lU2V0LnNldChuYW1lLCBVc2VkVmFsdWVTdGF0ZS5TdGFydGVkKTtcbiAgICAgICAgICAgICAgICBsZXQgYyA9IHZhbHVlQ29kZShuYW1lKTtcbiAgICAgICAgICAgICAgICBpZiAoYykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWYgPSB0aGlzLm9wdHMuZXM1ID8gZXhwb3J0cy52YXJLaW5kcy52YXIgOiBleHBvcnRzLnZhcktpbmRzLmNvbnN0O1xuICAgICAgICAgICAgICAgICAgICBjb2RlID0gKDAsIGNvZGVfMS5fKSBgJHtjb2RlfSR7ZGVmfSAke25hbWV9ID0gJHtjfTske3RoaXMub3B0cy5fbn1gO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICgoYyA9IGdldENvZGUgPT09IG51bGwgfHwgZ2V0Q29kZSA9PT0gdm9pZCAwID8gdm9pZCAwIDogZ2V0Q29kZShuYW1lKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29kZSA9ICgwLCBjb2RlXzEuXykgYCR7Y29kZX0ke2N9JHt0aGlzLm9wdHMuX259YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBWYWx1ZUVycm9yKG5hbWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBuYW1lU2V0LnNldChuYW1lLCBVc2VkVmFsdWVTdGF0ZS5Db21wbGV0ZWQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvZGU7XG4gICAgfVxufVxuZXhwb3J0cy5WYWx1ZVNjb3BlID0gVmFsdWVTY29wZTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNjb3BlLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXhwb3J0cy5leHRlbmRFcnJvcnMgPSBleHBvcnRzLnJlc2V0RXJyb3JzQ291bnQgPSBleHBvcnRzLnJlcG9ydEV4dHJhRXJyb3IgPSBleHBvcnRzLnJlcG9ydEVycm9yID0gZXhwb3J0cy5rZXl3b3JkJERhdGFFcnJvciA9IGV4cG9ydHMua2V5d29yZEVycm9yID0gdm9pZCAwO1xuY29uc3QgY29kZWdlbl8xID0gcmVxdWlyZShcIi4vY29kZWdlblwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuL3V0aWxcIik7XG5jb25zdCBuYW1lc18xID0gcmVxdWlyZShcIi4vbmFtZXNcIik7XG5leHBvcnRzLmtleXdvcmRFcnJvciA9IHtcbiAgICBtZXNzYWdlOiAoeyBrZXl3b3JkIH0pID0+ICgwLCBjb2RlZ2VuXzEuc3RyKSBgbXVzdCBwYXNzIFwiJHtrZXl3b3JkfVwiIGtleXdvcmQgdmFsaWRhdGlvbmAsXG59O1xuZXhwb3J0cy5rZXl3b3JkJERhdGFFcnJvciA9IHtcbiAgICBtZXNzYWdlOiAoeyBrZXl3b3JkLCBzY2hlbWFUeXBlIH0pID0+IHNjaGVtYVR5cGVcbiAgICAgICAgPyAoMCwgY29kZWdlbl8xLnN0cikgYFwiJHtrZXl3b3JkfVwiIGtleXdvcmQgbXVzdCBiZSAke3NjaGVtYVR5cGV9ICgkZGF0YSlgXG4gICAgICAgIDogKDAsIGNvZGVnZW5fMS5zdHIpIGBcIiR7a2V5d29yZH1cIiBrZXl3b3JkIGlzIGludmFsaWQgKCRkYXRhKWAsXG59O1xuZnVuY3Rpb24gcmVwb3J0RXJyb3IoY3h0LCBlcnJvciA9IGV4cG9ydHMua2V5d29yZEVycm9yLCBlcnJvclBhdGhzLCBvdmVycmlkZUFsbEVycm9ycykge1xuICAgIGNvbnN0IHsgaXQgfSA9IGN4dDtcbiAgICBjb25zdCB7IGdlbiwgY29tcG9zaXRlUnVsZSwgYWxsRXJyb3JzIH0gPSBpdDtcbiAgICBjb25zdCBlcnJPYmogPSBlcnJvck9iamVjdENvZGUoY3h0LCBlcnJvciwgZXJyb3JQYXRocyk7XG4gICAgaWYgKG92ZXJyaWRlQWxsRXJyb3JzICE9PSBudWxsICYmIG92ZXJyaWRlQWxsRXJyb3JzICE9PSB2b2lkIDAgPyBvdmVycmlkZUFsbEVycm9ycyA6IChjb21wb3NpdGVSdWxlIHx8IGFsbEVycm9ycykpIHtcbiAgICAgICAgYWRkRXJyb3IoZ2VuLCBlcnJPYmopO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuRXJyb3JzKGl0LCAoMCwgY29kZWdlbl8xLl8pIGBbJHtlcnJPYmp9XWApO1xuICAgIH1cbn1cbmV4cG9ydHMucmVwb3J0RXJyb3IgPSByZXBvcnRFcnJvcjtcbmZ1bmN0aW9uIHJlcG9ydEV4dHJhRXJyb3IoY3h0LCBlcnJvciA9IGV4cG9ydHMua2V5d29yZEVycm9yLCBlcnJvclBhdGhzKSB7XG4gICAgY29uc3QgeyBpdCB9ID0gY3h0O1xuICAgIGNvbnN0IHsgZ2VuLCBjb21wb3NpdGVSdWxlLCBhbGxFcnJvcnMgfSA9IGl0O1xuICAgIGNvbnN0IGVyck9iaiA9IGVycm9yT2JqZWN0Q29kZShjeHQsIGVycm9yLCBlcnJvclBhdGhzKTtcbiAgICBhZGRFcnJvcihnZW4sIGVyck9iaik7XG4gICAgaWYgKCEoY29tcG9zaXRlUnVsZSB8fCBhbGxFcnJvcnMpKSB7XG4gICAgICAgIHJldHVybkVycm9ycyhpdCwgbmFtZXNfMS5kZWZhdWx0LnZFcnJvcnMpO1xuICAgIH1cbn1cbmV4cG9ydHMucmVwb3J0RXh0cmFFcnJvciA9IHJlcG9ydEV4dHJhRXJyb3I7XG5mdW5jdGlvbiByZXNldEVycm9yc0NvdW50KGdlbiwgZXJyc0NvdW50KSB7XG4gICAgZ2VuLmFzc2lnbihuYW1lc18xLmRlZmF1bHQuZXJyb3JzLCBlcnJzQ291bnQpO1xuICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLl8pIGAke25hbWVzXzEuZGVmYXVsdC52RXJyb3JzfSAhPT0gbnVsbGAsICgpID0+IGdlbi5pZihlcnJzQ291bnQsICgpID0+IGdlbi5hc3NpZ24oKDAsIGNvZGVnZW5fMS5fKSBgJHtuYW1lc18xLmRlZmF1bHQudkVycm9yc30ubGVuZ3RoYCwgZXJyc0NvdW50KSwgKCkgPT4gZ2VuLmFzc2lnbihuYW1lc18xLmRlZmF1bHQudkVycm9ycywgbnVsbCkpKTtcbn1cbmV4cG9ydHMucmVzZXRFcnJvcnNDb3VudCA9IHJlc2V0RXJyb3JzQ291bnQ7XG5mdW5jdGlvbiBleHRlbmRFcnJvcnMoeyBnZW4sIGtleXdvcmQsIHNjaGVtYVZhbHVlLCBkYXRhLCBlcnJzQ291bnQsIGl0LCB9KSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKGVycnNDb3VudCA9PT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJhanYgaW1wbGVtZW50YXRpb24gZXJyb3JcIik7XG4gICAgY29uc3QgZXJyID0gZ2VuLm5hbWUoXCJlcnJcIik7XG4gICAgZ2VuLmZvclJhbmdlKFwiaVwiLCBlcnJzQ291bnQsIG5hbWVzXzEuZGVmYXVsdC5lcnJvcnMsIChpKSA9PiB7XG4gICAgICAgIGdlbi5jb25zdChlcnIsICgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LnZFcnJvcnN9WyR7aX1dYCk7XG4gICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLl8pIGAke2Vycn0uaW5zdGFuY2VQYXRoID09PSB1bmRlZmluZWRgLCAoKSA9PiBnZW4uYXNzaWduKCgwLCBjb2RlZ2VuXzEuXykgYCR7ZXJyfS5pbnN0YW5jZVBhdGhgLCAoMCwgY29kZWdlbl8xLnN0ckNvbmNhdCkobmFtZXNfMS5kZWZhdWx0Lmluc3RhbmNlUGF0aCwgaXQuZXJyb3JQYXRoKSkpO1xuICAgICAgICBnZW4uYXNzaWduKCgwLCBjb2RlZ2VuXzEuXykgYCR7ZXJyfS5zY2hlbWFQYXRoYCwgKDAsIGNvZGVnZW5fMS5zdHIpIGAke2l0LmVyclNjaGVtYVBhdGh9LyR7a2V5d29yZH1gKTtcbiAgICAgICAgaWYgKGl0Lm9wdHMudmVyYm9zZSkge1xuICAgICAgICAgICAgZ2VuLmFzc2lnbigoMCwgY29kZWdlbl8xLl8pIGAke2Vycn0uc2NoZW1hYCwgc2NoZW1hVmFsdWUpO1xuICAgICAgICAgICAgZ2VuLmFzc2lnbigoMCwgY29kZWdlbl8xLl8pIGAke2Vycn0uZGF0YWAsIGRhdGEpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5leHBvcnRzLmV4dGVuZEVycm9ycyA9IGV4dGVuZEVycm9ycztcbmZ1bmN0aW9uIGFkZEVycm9yKGdlbiwgZXJyT2JqKSB7XG4gICAgY29uc3QgZXJyID0gZ2VuLmNvbnN0KFwiZXJyXCIsIGVyck9iaik7XG4gICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LnZFcnJvcnN9ID09PSBudWxsYCwgKCkgPT4gZ2VuLmFzc2lnbihuYW1lc18xLmRlZmF1bHQudkVycm9ycywgKDAsIGNvZGVnZW5fMS5fKSBgWyR7ZXJyfV1gKSwgKDAsIGNvZGVnZW5fMS5fKSBgJHtuYW1lc18xLmRlZmF1bHQudkVycm9yc30ucHVzaCgke2Vycn0pYCk7XG4gICAgZ2VuLmNvZGUoKDAsIGNvZGVnZW5fMS5fKSBgJHtuYW1lc18xLmRlZmF1bHQuZXJyb3JzfSsrYCk7XG59XG5mdW5jdGlvbiByZXR1cm5FcnJvcnMoaXQsIGVycnMpIHtcbiAgICBjb25zdCB7IGdlbiwgdmFsaWRhdGVOYW1lLCBzY2hlbWFFbnYgfSA9IGl0O1xuICAgIGlmIChzY2hlbWFFbnYuJGFzeW5jKSB7XG4gICAgICAgIGdlbi50aHJvdygoMCwgY29kZWdlbl8xLl8pIGBuZXcgJHtpdC5WYWxpZGF0aW9uRXJyb3J9KCR7ZXJyc30pYCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBnZW4uYXNzaWduKCgwLCBjb2RlZ2VuXzEuXykgYCR7dmFsaWRhdGVOYW1lfS5lcnJvcnNgLCBlcnJzKTtcbiAgICAgICAgZ2VuLnJldHVybihmYWxzZSk7XG4gICAgfVxufVxuY29uc3QgRSA9IHtcbiAgICBrZXl3b3JkOiBuZXcgY29kZWdlbl8xLk5hbWUoXCJrZXl3b3JkXCIpLFxuICAgIHNjaGVtYVBhdGg6IG5ldyBjb2RlZ2VuXzEuTmFtZShcInNjaGVtYVBhdGhcIiksXG4gICAgcGFyYW1zOiBuZXcgY29kZWdlbl8xLk5hbWUoXCJwYXJhbXNcIiksXG4gICAgcHJvcGVydHlOYW1lOiBuZXcgY29kZWdlbl8xLk5hbWUoXCJwcm9wZXJ0eU5hbWVcIiksXG4gICAgbWVzc2FnZTogbmV3IGNvZGVnZW5fMS5OYW1lKFwibWVzc2FnZVwiKSxcbiAgICBzY2hlbWE6IG5ldyBjb2RlZ2VuXzEuTmFtZShcInNjaGVtYVwiKSxcbiAgICBwYXJlbnRTY2hlbWE6IG5ldyBjb2RlZ2VuXzEuTmFtZShcInBhcmVudFNjaGVtYVwiKSxcbn07XG5mdW5jdGlvbiBlcnJvck9iamVjdENvZGUoY3h0LCBlcnJvciwgZXJyb3JQYXRocykge1xuICAgIGNvbnN0IHsgY3JlYXRlRXJyb3JzIH0gPSBjeHQuaXQ7XG4gICAgaWYgKGNyZWF0ZUVycm9ycyA9PT0gZmFsc2UpXG4gICAgICAgIHJldHVybiAoMCwgY29kZWdlbl8xLl8pIGB7fWA7XG4gICAgcmV0dXJuIGVycm9yT2JqZWN0KGN4dCwgZXJyb3IsIGVycm9yUGF0aHMpO1xufVxuZnVuY3Rpb24gZXJyb3JPYmplY3QoY3h0LCBlcnJvciwgZXJyb3JQYXRocyA9IHt9KSB7XG4gICAgY29uc3QgeyBnZW4sIGl0IH0gPSBjeHQ7XG4gICAgY29uc3Qga2V5VmFsdWVzID0gW1xuICAgICAgICBlcnJvckluc3RhbmNlUGF0aChpdCwgZXJyb3JQYXRocyksXG4gICAgICAgIGVycm9yU2NoZW1hUGF0aChjeHQsIGVycm9yUGF0aHMpLFxuICAgIF07XG4gICAgZXh0cmFFcnJvclByb3BzKGN4dCwgZXJyb3IsIGtleVZhbHVlcyk7XG4gICAgcmV0dXJuIGdlbi5vYmplY3QoLi4ua2V5VmFsdWVzKTtcbn1cbmZ1bmN0aW9uIGVycm9ySW5zdGFuY2VQYXRoKHsgZXJyb3JQYXRoIH0sIHsgaW5zdGFuY2VQYXRoIH0pIHtcbiAgICBjb25zdCBpbnN0UGF0aCA9IGluc3RhbmNlUGF0aFxuICAgICAgICA/ICgwLCBjb2RlZ2VuXzEuc3RyKSBgJHtlcnJvclBhdGh9JHsoMCwgdXRpbF8xLmdldEVycm9yUGF0aCkoaW5zdGFuY2VQYXRoLCB1dGlsXzEuVHlwZS5TdHIpfWBcbiAgICAgICAgOiBlcnJvclBhdGg7XG4gICAgcmV0dXJuIFtuYW1lc18xLmRlZmF1bHQuaW5zdGFuY2VQYXRoLCAoMCwgY29kZWdlbl8xLnN0ckNvbmNhdCkobmFtZXNfMS5kZWZhdWx0Lmluc3RhbmNlUGF0aCwgaW5zdFBhdGgpXTtcbn1cbmZ1bmN0aW9uIGVycm9yU2NoZW1hUGF0aCh7IGtleXdvcmQsIGl0OiB7IGVyclNjaGVtYVBhdGggfSB9LCB7IHNjaGVtYVBhdGgsIHBhcmVudFNjaGVtYSB9KSB7XG4gICAgbGV0IHNjaFBhdGggPSBwYXJlbnRTY2hlbWEgPyBlcnJTY2hlbWFQYXRoIDogKDAsIGNvZGVnZW5fMS5zdHIpIGAke2VyclNjaGVtYVBhdGh9LyR7a2V5d29yZH1gO1xuICAgIGlmIChzY2hlbWFQYXRoKSB7XG4gICAgICAgIHNjaFBhdGggPSAoMCwgY29kZWdlbl8xLnN0cikgYCR7c2NoUGF0aH0keygwLCB1dGlsXzEuZ2V0RXJyb3JQYXRoKShzY2hlbWFQYXRoLCB1dGlsXzEuVHlwZS5TdHIpfWA7XG4gICAgfVxuICAgIHJldHVybiBbRS5zY2hlbWFQYXRoLCBzY2hQYXRoXTtcbn1cbmZ1bmN0aW9uIGV4dHJhRXJyb3JQcm9wcyhjeHQsIHsgcGFyYW1zLCBtZXNzYWdlIH0sIGtleVZhbHVlcykge1xuICAgIGNvbnN0IHsga2V5d29yZCwgZGF0YSwgc2NoZW1hVmFsdWUsIGl0IH0gPSBjeHQ7XG4gICAgY29uc3QgeyBvcHRzLCBwcm9wZXJ0eU5hbWUsIHRvcFNjaGVtYVJlZiwgc2NoZW1hUGF0aCB9ID0gaXQ7XG4gICAga2V5VmFsdWVzLnB1c2goW0Uua2V5d29yZCwga2V5d29yZF0sIFtFLnBhcmFtcywgdHlwZW9mIHBhcmFtcyA9PSBcImZ1bmN0aW9uXCIgPyBwYXJhbXMoY3h0KSA6IHBhcmFtcyB8fCAoMCwgY29kZWdlbl8xLl8pIGB7fWBdKTtcbiAgICBpZiAob3B0cy5tZXNzYWdlcykge1xuICAgICAgICBrZXlWYWx1ZXMucHVzaChbRS5tZXNzYWdlLCB0eXBlb2YgbWVzc2FnZSA9PSBcImZ1bmN0aW9uXCIgPyBtZXNzYWdlKGN4dCkgOiBtZXNzYWdlXSk7XG4gICAgfVxuICAgIGlmIChvcHRzLnZlcmJvc2UpIHtcbiAgICAgICAga2V5VmFsdWVzLnB1c2goW0Uuc2NoZW1hLCBzY2hlbWFWYWx1ZV0sIFtFLnBhcmVudFNjaGVtYSwgKDAsIGNvZGVnZW5fMS5fKSBgJHt0b3BTY2hlbWFSZWZ9JHtzY2hlbWFQYXRofWBdLCBbbmFtZXNfMS5kZWZhdWx0LmRhdGEsIGRhdGFdKTtcbiAgICB9XG4gICAgaWYgKHByb3BlcnR5TmFtZSlcbiAgICAgICAga2V5VmFsdWVzLnB1c2goW0UucHJvcGVydHlOYW1lLCBwcm9wZXJ0eU5hbWVdKTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWVycm9ycy5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmV4cG9ydHMucmVzb2x2ZVNjaGVtYSA9IGV4cG9ydHMuZ2V0Q29tcGlsaW5nU2NoZW1hID0gZXhwb3J0cy5yZXNvbHZlUmVmID0gZXhwb3J0cy5jb21waWxlU2NoZW1hID0gZXhwb3J0cy5TY2hlbWFFbnYgPSB2b2lkIDA7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi9jb2RlZ2VuXCIpO1xuY29uc3QgdmFsaWRhdGlvbl9lcnJvcl8xID0gcmVxdWlyZShcIi4uL3J1bnRpbWUvdmFsaWRhdGlvbl9lcnJvclwiKTtcbmNvbnN0IG5hbWVzXzEgPSByZXF1aXJlKFwiLi9uYW1lc1wiKTtcbmNvbnN0IHJlc29sdmVfMSA9IHJlcXVpcmUoXCIuL3Jlc29sdmVcIik7XG5jb25zdCB1dGlsXzEgPSByZXF1aXJlKFwiLi91dGlsXCIpO1xuY29uc3QgdmFsaWRhdGVfMSA9IHJlcXVpcmUoXCIuL3ZhbGlkYXRlXCIpO1xuY2xhc3MgU2NoZW1hRW52IHtcbiAgICBjb25zdHJ1Y3RvcihlbnYpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB0aGlzLnJlZnMgPSB7fTtcbiAgICAgICAgdGhpcy5keW5hbWljQW5jaG9ycyA9IHt9O1xuICAgICAgICBsZXQgc2NoZW1hO1xuICAgICAgICBpZiAodHlwZW9mIGVudi5zY2hlbWEgPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgIHNjaGVtYSA9IGVudi5zY2hlbWE7XG4gICAgICAgIHRoaXMuc2NoZW1hID0gZW52LnNjaGVtYTtcbiAgICAgICAgdGhpcy5zY2hlbWFJZCA9IGVudi5zY2hlbWFJZDtcbiAgICAgICAgdGhpcy5yb290ID0gZW52LnJvb3QgfHwgdGhpcztcbiAgICAgICAgdGhpcy5iYXNlSWQgPSAoX2EgPSBlbnYuYmFzZUlkKSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiAoMCwgcmVzb2x2ZV8xLm5vcm1hbGl6ZUlkKShzY2hlbWEgPT09IG51bGwgfHwgc2NoZW1hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBzY2hlbWFbZW52LnNjaGVtYUlkIHx8IFwiJGlkXCJdKTtcbiAgICAgICAgdGhpcy5zY2hlbWFQYXRoID0gZW52LnNjaGVtYVBhdGg7XG4gICAgICAgIHRoaXMubG9jYWxSZWZzID0gZW52LmxvY2FsUmVmcztcbiAgICAgICAgdGhpcy5tZXRhID0gZW52Lm1ldGE7XG4gICAgICAgIHRoaXMuJGFzeW5jID0gc2NoZW1hID09PSBudWxsIHx8IHNjaGVtYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogc2NoZW1hLiRhc3luYztcbiAgICAgICAgdGhpcy5yZWZzID0ge307XG4gICAgfVxufVxuZXhwb3J0cy5TY2hlbWFFbnYgPSBTY2hlbWFFbnY7XG4vLyBsZXQgY29kZVNpemUgPSAwXG4vLyBsZXQgbm9kZUNvdW50ID0gMFxuLy8gQ29tcGlsZXMgc2NoZW1hIGluIFNjaGVtYUVudlxuZnVuY3Rpb24gY29tcGlsZVNjaGVtYShzY2gpIHtcbiAgICAvLyBUT0RPIHJlZmFjdG9yIC0gcmVtb3ZlIGNvbXBpbGF0aW9uc1xuICAgIGNvbnN0IF9zY2ggPSBnZXRDb21waWxpbmdTY2hlbWEuY2FsbCh0aGlzLCBzY2gpO1xuICAgIGlmIChfc2NoKVxuICAgICAgICByZXR1cm4gX3NjaDtcbiAgICBjb25zdCByb290SWQgPSAoMCwgcmVzb2x2ZV8xLmdldEZ1bGxQYXRoKSh0aGlzLm9wdHMudXJpUmVzb2x2ZXIsIHNjaC5yb290LmJhc2VJZCk7IC8vIFRPRE8gaWYgZ2V0RnVsbFBhdGggcmVtb3ZlZCAxIHRlc3RzIGZhaWxzXG4gICAgY29uc3QgeyBlczUsIGxpbmVzIH0gPSB0aGlzLm9wdHMuY29kZTtcbiAgICBjb25zdCB7IG93blByb3BlcnRpZXMgfSA9IHRoaXMub3B0cztcbiAgICBjb25zdCBnZW4gPSBuZXcgY29kZWdlbl8xLkNvZGVHZW4odGhpcy5zY29wZSwgeyBlczUsIGxpbmVzLCBvd25Qcm9wZXJ0aWVzIH0pO1xuICAgIGxldCBfVmFsaWRhdGlvbkVycm9yO1xuICAgIGlmIChzY2guJGFzeW5jKSB7XG4gICAgICAgIF9WYWxpZGF0aW9uRXJyb3IgPSBnZW4uc2NvcGVWYWx1ZShcIkVycm9yXCIsIHtcbiAgICAgICAgICAgIHJlZjogdmFsaWRhdGlvbl9lcnJvcl8xLmRlZmF1bHQsXG4gICAgICAgICAgICBjb2RlOiAoMCwgY29kZWdlbl8xLl8pIGByZXF1aXJlKFwiYWp2L2Rpc3QvcnVudGltZS92YWxpZGF0aW9uX2Vycm9yXCIpLmRlZmF1bHRgLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgY29uc3QgdmFsaWRhdGVOYW1lID0gZ2VuLnNjb3BlTmFtZShcInZhbGlkYXRlXCIpO1xuICAgIHNjaC52YWxpZGF0ZU5hbWUgPSB2YWxpZGF0ZU5hbWU7XG4gICAgY29uc3Qgc2NoZW1hQ3h0ID0ge1xuICAgICAgICBnZW4sXG4gICAgICAgIGFsbEVycm9yczogdGhpcy5vcHRzLmFsbEVycm9ycyxcbiAgICAgICAgZGF0YTogbmFtZXNfMS5kZWZhdWx0LmRhdGEsXG4gICAgICAgIHBhcmVudERhdGE6IG5hbWVzXzEuZGVmYXVsdC5wYXJlbnREYXRhLFxuICAgICAgICBwYXJlbnREYXRhUHJvcGVydHk6IG5hbWVzXzEuZGVmYXVsdC5wYXJlbnREYXRhUHJvcGVydHksXG4gICAgICAgIGRhdGFOYW1lczogW25hbWVzXzEuZGVmYXVsdC5kYXRhXSxcbiAgICAgICAgZGF0YVBhdGhBcnI6IFtjb2RlZ2VuXzEubmlsXSxcbiAgICAgICAgZGF0YUxldmVsOiAwLFxuICAgICAgICBkYXRhVHlwZXM6IFtdLFxuICAgICAgICBkZWZpbmVkUHJvcGVydGllczogbmV3IFNldCgpLFxuICAgICAgICB0b3BTY2hlbWFSZWY6IGdlbi5zY29wZVZhbHVlKFwic2NoZW1hXCIsIHRoaXMub3B0cy5jb2RlLnNvdXJjZSA9PT0gdHJ1ZVxuICAgICAgICAgICAgPyB7IHJlZjogc2NoLnNjaGVtYSwgY29kZTogKDAsIGNvZGVnZW5fMS5zdHJpbmdpZnkpKHNjaC5zY2hlbWEpIH1cbiAgICAgICAgICAgIDogeyByZWY6IHNjaC5zY2hlbWEgfSksXG4gICAgICAgIHZhbGlkYXRlTmFtZSxcbiAgICAgICAgVmFsaWRhdGlvbkVycm9yOiBfVmFsaWRhdGlvbkVycm9yLFxuICAgICAgICBzY2hlbWE6IHNjaC5zY2hlbWEsXG4gICAgICAgIHNjaGVtYUVudjogc2NoLFxuICAgICAgICByb290SWQsXG4gICAgICAgIGJhc2VJZDogc2NoLmJhc2VJZCB8fCByb290SWQsXG4gICAgICAgIHNjaGVtYVBhdGg6IGNvZGVnZW5fMS5uaWwsXG4gICAgICAgIGVyclNjaGVtYVBhdGg6IHNjaC5zY2hlbWFQYXRoIHx8ICh0aGlzLm9wdHMuanRkID8gXCJcIiA6IFwiI1wiKSxcbiAgICAgICAgZXJyb3JQYXRoOiAoMCwgY29kZWdlbl8xLl8pIGBcIlwiYCxcbiAgICAgICAgb3B0czogdGhpcy5vcHRzLFxuICAgICAgICBzZWxmOiB0aGlzLFxuICAgIH07XG4gICAgbGV0IHNvdXJjZUNvZGU7XG4gICAgdHJ5IHtcbiAgICAgICAgdGhpcy5fY29tcGlsYXRpb25zLmFkZChzY2gpO1xuICAgICAgICAoMCwgdmFsaWRhdGVfMS52YWxpZGF0ZUZ1bmN0aW9uQ29kZSkoc2NoZW1hQ3h0KTtcbiAgICAgICAgZ2VuLm9wdGltaXplKHRoaXMub3B0cy5jb2RlLm9wdGltaXplKTtcbiAgICAgICAgLy8gZ2VuLm9wdGltaXplKDEpXG4gICAgICAgIGNvbnN0IHZhbGlkYXRlQ29kZSA9IGdlbi50b1N0cmluZygpO1xuICAgICAgICBzb3VyY2VDb2RlID0gYCR7Z2VuLnNjb3BlUmVmcyhuYW1lc18xLmRlZmF1bHQuc2NvcGUpfXJldHVybiAke3ZhbGlkYXRlQ29kZX1gO1xuICAgICAgICAvLyBjb25zb2xlLmxvZygoY29kZVNpemUgKz0gc291cmNlQ29kZS5sZW5ndGgpLCAobm9kZUNvdW50ICs9IGdlbi5ub2RlQ291bnQpKVxuICAgICAgICBpZiAodGhpcy5vcHRzLmNvZGUucHJvY2VzcylcbiAgICAgICAgICAgIHNvdXJjZUNvZGUgPSB0aGlzLm9wdHMuY29kZS5wcm9jZXNzKHNvdXJjZUNvZGUsIHNjaCk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiXFxuXFxuXFxuICoqKiBcXG5cIiwgc291cmNlQ29kZSlcbiAgICAgICAgY29uc3QgbWFrZVZhbGlkYXRlID0gbmV3IEZ1bmN0aW9uKGAke25hbWVzXzEuZGVmYXVsdC5zZWxmfWAsIGAke25hbWVzXzEuZGVmYXVsdC5zY29wZX1gLCBzb3VyY2VDb2RlKTtcbiAgICAgICAgY29uc3QgdmFsaWRhdGUgPSBtYWtlVmFsaWRhdGUodGhpcywgdGhpcy5zY29wZS5nZXQoKSk7XG4gICAgICAgIHRoaXMuc2NvcGUudmFsdWUodmFsaWRhdGVOYW1lLCB7IHJlZjogdmFsaWRhdGUgfSk7XG4gICAgICAgIHZhbGlkYXRlLmVycm9ycyA9IG51bGw7XG4gICAgICAgIHZhbGlkYXRlLnNjaGVtYSA9IHNjaC5zY2hlbWE7XG4gICAgICAgIHZhbGlkYXRlLnNjaGVtYUVudiA9IHNjaDtcbiAgICAgICAgaWYgKHNjaC4kYXN5bmMpXG4gICAgICAgICAgICB2YWxpZGF0ZS4kYXN5bmMgPSB0cnVlO1xuICAgICAgICBpZiAodGhpcy5vcHRzLmNvZGUuc291cmNlID09PSB0cnVlKSB7XG4gICAgICAgICAgICB2YWxpZGF0ZS5zb3VyY2UgPSB7IHZhbGlkYXRlTmFtZSwgdmFsaWRhdGVDb2RlLCBzY29wZVZhbHVlczogZ2VuLl92YWx1ZXMgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5vcHRzLnVuZXZhbHVhdGVkKSB7XG4gICAgICAgICAgICBjb25zdCB7IHByb3BzLCBpdGVtcyB9ID0gc2NoZW1hQ3h0O1xuICAgICAgICAgICAgdmFsaWRhdGUuZXZhbHVhdGVkID0ge1xuICAgICAgICAgICAgICAgIHByb3BzOiBwcm9wcyBpbnN0YW5jZW9mIGNvZGVnZW5fMS5OYW1lID8gdW5kZWZpbmVkIDogcHJvcHMsXG4gICAgICAgICAgICAgICAgaXRlbXM6IGl0ZW1zIGluc3RhbmNlb2YgY29kZWdlbl8xLk5hbWUgPyB1bmRlZmluZWQgOiBpdGVtcyxcbiAgICAgICAgICAgICAgICBkeW5hbWljUHJvcHM6IHByb3BzIGluc3RhbmNlb2YgY29kZWdlbl8xLk5hbWUsXG4gICAgICAgICAgICAgICAgZHluYW1pY0l0ZW1zOiBpdGVtcyBpbnN0YW5jZW9mIGNvZGVnZW5fMS5OYW1lLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmICh2YWxpZGF0ZS5zb3VyY2UpXG4gICAgICAgICAgICAgICAgdmFsaWRhdGUuc291cmNlLmV2YWx1YXRlZCA9ICgwLCBjb2RlZ2VuXzEuc3RyaW5naWZ5KSh2YWxpZGF0ZS5ldmFsdWF0ZWQpO1xuICAgICAgICB9XG4gICAgICAgIHNjaC52YWxpZGF0ZSA9IHZhbGlkYXRlO1xuICAgICAgICByZXR1cm4gc2NoO1xuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICBkZWxldGUgc2NoLnZhbGlkYXRlO1xuICAgICAgICBkZWxldGUgc2NoLnZhbGlkYXRlTmFtZTtcbiAgICAgICAgaWYgKHNvdXJjZUNvZGUpXG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihcIkVycm9yIGNvbXBpbGluZyBzY2hlbWEsIGZ1bmN0aW9uIGNvZGU6XCIsIHNvdXJjZUNvZGUpO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlxcblxcblxcbiAqKiogXFxuXCIsIHNvdXJjZUNvZGUsIHRoaXMub3B0cylcbiAgICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIHRoaXMuX2NvbXBpbGF0aW9ucy5kZWxldGUoc2NoKTtcbiAgICB9XG59XG5leHBvcnRzLmNvbXBpbGVTY2hlbWEgPSBjb21waWxlU2NoZW1hO1xuZnVuY3Rpb24gcmVzb2x2ZVJlZihyb290LCBiYXNlSWQsIHJlZikge1xuICAgIHZhciBfYTtcbiAgICByZWYgPSAoMCwgcmVzb2x2ZV8xLnJlc29sdmVVcmwpKHRoaXMub3B0cy51cmlSZXNvbHZlciwgYmFzZUlkLCByZWYpO1xuICAgIGNvbnN0IHNjaE9yRnVuYyA9IHJvb3QucmVmc1tyZWZdO1xuICAgIGlmIChzY2hPckZ1bmMpXG4gICAgICAgIHJldHVybiBzY2hPckZ1bmM7XG4gICAgbGV0IF9zY2ggPSByZXNvbHZlLmNhbGwodGhpcywgcm9vdCwgcmVmKTtcbiAgICBpZiAoX3NjaCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnN0IHNjaGVtYSA9IChfYSA9IHJvb3QubG9jYWxSZWZzKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2FbcmVmXTsgLy8gVE9ETyBtYXliZSBsb2NhbFJlZnMgc2hvdWxkIGhvbGQgU2NoZW1hRW52XG4gICAgICAgIGNvbnN0IHsgc2NoZW1hSWQgfSA9IHRoaXMub3B0cztcbiAgICAgICAgaWYgKHNjaGVtYSlcbiAgICAgICAgICAgIF9zY2ggPSBuZXcgU2NoZW1hRW52KHsgc2NoZW1hLCBzY2hlbWFJZCwgcm9vdCwgYmFzZUlkIH0pO1xuICAgIH1cbiAgICBpZiAoX3NjaCA9PT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm47XG4gICAgcmV0dXJuIChyb290LnJlZnNbcmVmXSA9IGlubGluZU9yQ29tcGlsZS5jYWxsKHRoaXMsIF9zY2gpKTtcbn1cbmV4cG9ydHMucmVzb2x2ZVJlZiA9IHJlc29sdmVSZWY7XG5mdW5jdGlvbiBpbmxpbmVPckNvbXBpbGUoc2NoKSB7XG4gICAgaWYgKCgwLCByZXNvbHZlXzEuaW5saW5lUmVmKShzY2guc2NoZW1hLCB0aGlzLm9wdHMuaW5saW5lUmVmcykpXG4gICAgICAgIHJldHVybiBzY2guc2NoZW1hO1xuICAgIHJldHVybiBzY2gudmFsaWRhdGUgPyBzY2ggOiBjb21waWxlU2NoZW1hLmNhbGwodGhpcywgc2NoKTtcbn1cbi8vIEluZGV4IG9mIHNjaGVtYSBjb21waWxhdGlvbiBpbiB0aGUgY3VycmVudGx5IGNvbXBpbGVkIGxpc3RcbmZ1bmN0aW9uIGdldENvbXBpbGluZ1NjaGVtYShzY2hFbnYpIHtcbiAgICBmb3IgKGNvbnN0IHNjaCBvZiB0aGlzLl9jb21waWxhdGlvbnMpIHtcbiAgICAgICAgaWYgKHNhbWVTY2hlbWFFbnYoc2NoLCBzY2hFbnYpKVxuICAgICAgICAgICAgcmV0dXJuIHNjaDtcbiAgICB9XG59XG5leHBvcnRzLmdldENvbXBpbGluZ1NjaGVtYSA9IGdldENvbXBpbGluZ1NjaGVtYTtcbmZ1bmN0aW9uIHNhbWVTY2hlbWFFbnYoczEsIHMyKSB7XG4gICAgcmV0dXJuIHMxLnNjaGVtYSA9PT0gczIuc2NoZW1hICYmIHMxLnJvb3QgPT09IHMyLnJvb3QgJiYgczEuYmFzZUlkID09PSBzMi5iYXNlSWQ7XG59XG4vLyByZXNvbHZlIGFuZCBjb21waWxlIHRoZSByZWZlcmVuY2VzICgkcmVmKVxuLy8gVE9ETyByZXR1cm5zIEFueVNjaGVtYU9iamVjdCAoaWYgdGhlIHNjaGVtYSBjYW4gYmUgaW5saW5lZCkgb3IgdmFsaWRhdGlvbiBmdW5jdGlvblxuZnVuY3Rpb24gcmVzb2x2ZShyb290LCAvLyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcm9vdCBzY2hlbWEgZm9yIHRoZSBjdXJyZW50IHNjaGVtYVxucmVmIC8vIHJlZmVyZW5jZSB0byByZXNvbHZlXG4pIHtcbiAgICBsZXQgc2NoO1xuICAgIHdoaWxlICh0eXBlb2YgKHNjaCA9IHRoaXMucmVmc1tyZWZdKSA9PSBcInN0cmluZ1wiKVxuICAgICAgICByZWYgPSBzY2g7XG4gICAgcmV0dXJuIHNjaCB8fCB0aGlzLnNjaGVtYXNbcmVmXSB8fCByZXNvbHZlU2NoZW1hLmNhbGwodGhpcywgcm9vdCwgcmVmKTtcbn1cbi8vIFJlc29sdmUgc2NoZW1hLCBpdHMgcm9vdCBhbmQgYmFzZUlkXG5mdW5jdGlvbiByZXNvbHZlU2NoZW1hKHJvb3QsIC8vIHJvb3Qgb2JqZWN0IHdpdGggcHJvcGVydGllcyBzY2hlbWEsIHJlZnMgVE9ETyBiZWxvdyBTY2hlbWFFbnYgaXMgYXNzaWduZWQgdG8gaXRcbnJlZiAvLyByZWZlcmVuY2UgdG8gcmVzb2x2ZVxuKSB7XG4gICAgY29uc3QgcCA9IHRoaXMub3B0cy51cmlSZXNvbHZlci5wYXJzZShyZWYpO1xuICAgIGNvbnN0IHJlZlBhdGggPSAoMCwgcmVzb2x2ZV8xLl9nZXRGdWxsUGF0aCkodGhpcy5vcHRzLnVyaVJlc29sdmVyLCBwKTtcbiAgICBsZXQgYmFzZUlkID0gKDAsIHJlc29sdmVfMS5nZXRGdWxsUGF0aCkodGhpcy5vcHRzLnVyaVJlc29sdmVyLCByb290LmJhc2VJZCwgdW5kZWZpbmVkKTtcbiAgICAvLyBUT0RPIGBPYmplY3Qua2V5cyhyb290LnNjaGVtYSkubGVuZ3RoID4gMGAgc2hvdWxkIG5vdCBiZSBuZWVkZWQgLSBidXQgcmVtb3ZpbmcgYnJlYWtzIDIgdGVzdHNcbiAgICBpZiAoT2JqZWN0LmtleXMocm9vdC5zY2hlbWEpLmxlbmd0aCA+IDAgJiYgcmVmUGF0aCA9PT0gYmFzZUlkKSB7XG4gICAgICAgIHJldHVybiBnZXRKc29uUG9pbnRlci5jYWxsKHRoaXMsIHAsIHJvb3QpO1xuICAgIH1cbiAgICBjb25zdCBpZCA9ICgwLCByZXNvbHZlXzEubm9ybWFsaXplSWQpKHJlZlBhdGgpO1xuICAgIGNvbnN0IHNjaE9yUmVmID0gdGhpcy5yZWZzW2lkXSB8fCB0aGlzLnNjaGVtYXNbaWRdO1xuICAgIGlmICh0eXBlb2Ygc2NoT3JSZWYgPT0gXCJzdHJpbmdcIikge1xuICAgICAgICBjb25zdCBzY2ggPSByZXNvbHZlU2NoZW1hLmNhbGwodGhpcywgcm9vdCwgc2NoT3JSZWYpO1xuICAgICAgICBpZiAodHlwZW9mIChzY2ggPT09IG51bGwgfHwgc2NoID09PSB2b2lkIDAgPyB2b2lkIDAgOiBzY2guc2NoZW1hKSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgcmV0dXJuIGdldEpzb25Qb2ludGVyLmNhbGwodGhpcywgcCwgc2NoKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiAoc2NoT3JSZWYgPT09IG51bGwgfHwgc2NoT3JSZWYgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHNjaE9yUmVmLnNjaGVtYSkgIT09IFwib2JqZWN0XCIpXG4gICAgICAgIHJldHVybjtcbiAgICBpZiAoIXNjaE9yUmVmLnZhbGlkYXRlKVxuICAgICAgICBjb21waWxlU2NoZW1hLmNhbGwodGhpcywgc2NoT3JSZWYpO1xuICAgIGlmIChpZCA9PT0gKDAsIHJlc29sdmVfMS5ub3JtYWxpemVJZCkocmVmKSkge1xuICAgICAgICBjb25zdCB7IHNjaGVtYSB9ID0gc2NoT3JSZWY7XG4gICAgICAgIGNvbnN0IHsgc2NoZW1hSWQgfSA9IHRoaXMub3B0cztcbiAgICAgICAgY29uc3Qgc2NoSWQgPSBzY2hlbWFbc2NoZW1hSWRdO1xuICAgICAgICBpZiAoc2NoSWQpXG4gICAgICAgICAgICBiYXNlSWQgPSAoMCwgcmVzb2x2ZV8xLnJlc29sdmVVcmwpKHRoaXMub3B0cy51cmlSZXNvbHZlciwgYmFzZUlkLCBzY2hJZCk7XG4gICAgICAgIHJldHVybiBuZXcgU2NoZW1hRW52KHsgc2NoZW1hLCBzY2hlbWFJZCwgcm9vdCwgYmFzZUlkIH0pO1xuICAgIH1cbiAgICByZXR1cm4gZ2V0SnNvblBvaW50ZXIuY2FsbCh0aGlzLCBwLCBzY2hPclJlZik7XG59XG5leHBvcnRzLnJlc29sdmVTY2hlbWEgPSByZXNvbHZlU2NoZW1hO1xuY29uc3QgUFJFVkVOVF9TQ09QRV9DSEFOR0UgPSBuZXcgU2V0KFtcbiAgICBcInByb3BlcnRpZXNcIixcbiAgICBcInBhdHRlcm5Qcm9wZXJ0aWVzXCIsXG4gICAgXCJlbnVtXCIsXG4gICAgXCJkZXBlbmRlbmNpZXNcIixcbiAgICBcImRlZmluaXRpb25zXCIsXG5dKTtcbmZ1bmN0aW9uIGdldEpzb25Qb2ludGVyKHBhcnNlZFJlZiwgeyBiYXNlSWQsIHNjaGVtYSwgcm9vdCB9KSB7XG4gICAgdmFyIF9hO1xuICAgIGlmICgoKF9hID0gcGFyc2VkUmVmLmZyYWdtZW50KSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2FbMF0pICE9PSBcIi9cIilcbiAgICAgICAgcmV0dXJuO1xuICAgIGZvciAoY29uc3QgcGFydCBvZiBwYXJzZWRSZWYuZnJhZ21lbnQuc2xpY2UoMSkuc3BsaXQoXCIvXCIpKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2NoZW1hID09PSBcImJvb2xlYW5cIilcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgcGFydFNjaGVtYSA9IHNjaGVtYVsoMCwgdXRpbF8xLnVuZXNjYXBlRnJhZ21lbnQpKHBhcnQpXTtcbiAgICAgICAgaWYgKHBhcnRTY2hlbWEgPT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgc2NoZW1hID0gcGFydFNjaGVtYTtcbiAgICAgICAgLy8gVE9ETyBQUkVWRU5UX1NDT1BFX0NIQU5HRSBjb3VsZCBiZSBkZWZpbmVkIGluIGtleXdvcmQgZGVmP1xuICAgICAgICBjb25zdCBzY2hJZCA9IHR5cGVvZiBzY2hlbWEgPT09IFwib2JqZWN0XCIgJiYgc2NoZW1hW3RoaXMub3B0cy5zY2hlbWFJZF07XG4gICAgICAgIGlmICghUFJFVkVOVF9TQ09QRV9DSEFOR0UuaGFzKHBhcnQpICYmIHNjaElkKSB7XG4gICAgICAgICAgICBiYXNlSWQgPSAoMCwgcmVzb2x2ZV8xLnJlc29sdmVVcmwpKHRoaXMub3B0cy51cmlSZXNvbHZlciwgYmFzZUlkLCBzY2hJZCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgbGV0IGVudjtcbiAgICBpZiAodHlwZW9mIHNjaGVtYSAhPSBcImJvb2xlYW5cIiAmJiBzY2hlbWEuJHJlZiAmJiAhKDAsIHV0aWxfMS5zY2hlbWFIYXNSdWxlc0J1dFJlZikoc2NoZW1hLCB0aGlzLlJVTEVTKSkge1xuICAgICAgICBjb25zdCAkcmVmID0gKDAsIHJlc29sdmVfMS5yZXNvbHZlVXJsKSh0aGlzLm9wdHMudXJpUmVzb2x2ZXIsIGJhc2VJZCwgc2NoZW1hLiRyZWYpO1xuICAgICAgICBlbnYgPSByZXNvbHZlU2NoZW1hLmNhbGwodGhpcywgcm9vdCwgJHJlZik7XG4gICAgfVxuICAgIC8vIGV2ZW4gdGhvdWdoIHJlc29sdXRpb24gZmFpbGVkIHdlIG5lZWQgdG8gcmV0dXJuIFNjaGVtYUVudiB0byB0aHJvdyBleGNlcHRpb25cbiAgICAvLyBzbyB0aGF0IGNvbXBpbGVBc3luYyBsb2FkcyBtaXNzaW5nIHNjaGVtYS5cbiAgICBjb25zdCB7IHNjaGVtYUlkIH0gPSB0aGlzLm9wdHM7XG4gICAgZW52ID0gZW52IHx8IG5ldyBTY2hlbWFFbnYoeyBzY2hlbWEsIHNjaGVtYUlkLCByb290LCBiYXNlSWQgfSk7XG4gICAgaWYgKGVudi5zY2hlbWEgIT09IGVudi5yb290LnNjaGVtYSlcbiAgICAgICAgcmV0dXJuIGVudjtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi9jb2RlZ2VuXCIpO1xuY29uc3QgbmFtZXMgPSB7XG4gICAgLy8gdmFsaWRhdGlvbiBmdW5jdGlvbiBhcmd1bWVudHNcbiAgICBkYXRhOiBuZXcgY29kZWdlbl8xLk5hbWUoXCJkYXRhXCIpLFxuICAgIC8vIGFyZ3MgcGFzc2VkIGZyb20gcmVmZXJlbmNpbmcgc2NoZW1hXG4gICAgdmFsQ3h0OiBuZXcgY29kZWdlbl8xLk5hbWUoXCJ2YWxDeHRcIiksXG4gICAgaW5zdGFuY2VQYXRoOiBuZXcgY29kZWdlbl8xLk5hbWUoXCJpbnN0YW5jZVBhdGhcIiksXG4gICAgcGFyZW50RGF0YTogbmV3IGNvZGVnZW5fMS5OYW1lKFwicGFyZW50RGF0YVwiKSxcbiAgICBwYXJlbnREYXRhUHJvcGVydHk6IG5ldyBjb2RlZ2VuXzEuTmFtZShcInBhcmVudERhdGFQcm9wZXJ0eVwiKSxcbiAgICByb290RGF0YTogbmV3IGNvZGVnZW5fMS5OYW1lKFwicm9vdERhdGFcIiksXG4gICAgZHluYW1pY0FuY2hvcnM6IG5ldyBjb2RlZ2VuXzEuTmFtZShcImR5bmFtaWNBbmNob3JzXCIpLFxuICAgIC8vIGZ1bmN0aW9uIHNjb3BlZCB2YXJpYWJsZXNcbiAgICB2RXJyb3JzOiBuZXcgY29kZWdlbl8xLk5hbWUoXCJ2RXJyb3JzXCIpLFxuICAgIGVycm9yczogbmV3IGNvZGVnZW5fMS5OYW1lKFwiZXJyb3JzXCIpLFxuICAgIHRoaXM6IG5ldyBjb2RlZ2VuXzEuTmFtZShcInRoaXNcIiksXG4gICAgLy8gXCJnbG9iYWxzXCJcbiAgICBzZWxmOiBuZXcgY29kZWdlbl8xLk5hbWUoXCJzZWxmXCIpLFxuICAgIHNjb3BlOiBuZXcgY29kZWdlbl8xLk5hbWUoXCJzY29wZVwiKSxcbiAgICAvLyBKVEQgc2VyaWFsaXplL3BhcnNlIG5hbWUgZm9yIEpTT04gc3RyaW5nIGFuZCBwb3NpdGlvblxuICAgIGpzb246IG5ldyBjb2RlZ2VuXzEuTmFtZShcImpzb25cIiksXG4gICAganNvblBvczogbmV3IGNvZGVnZW5fMS5OYW1lKFwianNvblBvc1wiKSxcbiAgICBqc29uTGVuOiBuZXcgY29kZWdlbl8xLk5hbWUoXCJqc29uTGVuXCIpLFxuICAgIGpzb25QYXJ0OiBuZXcgY29kZWdlbl8xLk5hbWUoXCJqc29uUGFydFwiKSxcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBuYW1lcztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPW5hbWVzLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgcmVzb2x2ZV8xID0gcmVxdWlyZShcIi4vcmVzb2x2ZVwiKTtcbmNsYXNzIE1pc3NpbmdSZWZFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3RvcihyZXNvbHZlciwgYmFzZUlkLCByZWYsIG1zZykge1xuICAgICAgICBzdXBlcihtc2cgfHwgYGNhbid0IHJlc29sdmUgcmVmZXJlbmNlICR7cmVmfSBmcm9tIGlkICR7YmFzZUlkfWApO1xuICAgICAgICB0aGlzLm1pc3NpbmdSZWYgPSAoMCwgcmVzb2x2ZV8xLnJlc29sdmVVcmwpKHJlc29sdmVyLCBiYXNlSWQsIHJlZik7XG4gICAgICAgIHRoaXMubWlzc2luZ1NjaGVtYSA9ICgwLCByZXNvbHZlXzEubm9ybWFsaXplSWQpKCgwLCByZXNvbHZlXzEuZ2V0RnVsbFBhdGgpKHJlc29sdmVyLCB0aGlzLm1pc3NpbmdSZWYpKTtcbiAgICB9XG59XG5leHBvcnRzLmRlZmF1bHQgPSBNaXNzaW5nUmVmRXJyb3I7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1yZWZfZXJyb3IuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leHBvcnRzLmdldFNjaGVtYVJlZnMgPSBleHBvcnRzLnJlc29sdmVVcmwgPSBleHBvcnRzLm5vcm1hbGl6ZUlkID0gZXhwb3J0cy5fZ2V0RnVsbFBhdGggPSBleHBvcnRzLmdldEZ1bGxQYXRoID0gZXhwb3J0cy5pbmxpbmVSZWYgPSB2b2lkIDA7XG5jb25zdCB1dGlsXzEgPSByZXF1aXJlKFwiLi91dGlsXCIpO1xuY29uc3QgZXF1YWwgPSByZXF1aXJlKFwiZmFzdC1kZWVwLWVxdWFsXCIpO1xuY29uc3QgdHJhdmVyc2UgPSByZXF1aXJlKFwianNvbi1zY2hlbWEtdHJhdmVyc2VcIik7XG4vLyBUT0RPIHJlZmFjdG9yIHRvIHVzZSBrZXl3b3JkIGRlZmluaXRpb25zXG5jb25zdCBTSU1QTEVfSU5MSU5FRCA9IG5ldyBTZXQoW1xuICAgIFwidHlwZVwiLFxuICAgIFwiZm9ybWF0XCIsXG4gICAgXCJwYXR0ZXJuXCIsXG4gICAgXCJtYXhMZW5ndGhcIixcbiAgICBcIm1pbkxlbmd0aFwiLFxuICAgIFwibWF4UHJvcGVydGllc1wiLFxuICAgIFwibWluUHJvcGVydGllc1wiLFxuICAgIFwibWF4SXRlbXNcIixcbiAgICBcIm1pbkl0ZW1zXCIsXG4gICAgXCJtYXhpbXVtXCIsXG4gICAgXCJtaW5pbXVtXCIsXG4gICAgXCJ1bmlxdWVJdGVtc1wiLFxuICAgIFwibXVsdGlwbGVPZlwiLFxuICAgIFwicmVxdWlyZWRcIixcbiAgICBcImVudW1cIixcbiAgICBcImNvbnN0XCIsXG5dKTtcbmZ1bmN0aW9uIGlubGluZVJlZihzY2hlbWEsIGxpbWl0ID0gdHJ1ZSkge1xuICAgIGlmICh0eXBlb2Ygc2NoZW1hID09IFwiYm9vbGVhblwiKVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICBpZiAobGltaXQgPT09IHRydWUpXG4gICAgICAgIHJldHVybiAhaGFzUmVmKHNjaGVtYSk7XG4gICAgaWYgKCFsaW1pdClcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiBjb3VudEtleXMoc2NoZW1hKSA8PSBsaW1pdDtcbn1cbmV4cG9ydHMuaW5saW5lUmVmID0gaW5saW5lUmVmO1xuY29uc3QgUkVGX0tFWVdPUkRTID0gbmV3IFNldChbXG4gICAgXCIkcmVmXCIsXG4gICAgXCIkcmVjdXJzaXZlUmVmXCIsXG4gICAgXCIkcmVjdXJzaXZlQW5jaG9yXCIsXG4gICAgXCIkZHluYW1pY1JlZlwiLFxuICAgIFwiJGR5bmFtaWNBbmNob3JcIixcbl0pO1xuZnVuY3Rpb24gaGFzUmVmKHNjaGVtYSkge1xuICAgIGZvciAoY29uc3Qga2V5IGluIHNjaGVtYSkge1xuICAgICAgICBpZiAoUkVGX0tFWVdPUkRTLmhhcyhrZXkpKVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIGNvbnN0IHNjaCA9IHNjaGVtYVtrZXldO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShzY2gpICYmIHNjaC5zb21lKGhhc1JlZikpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgaWYgKHR5cGVvZiBzY2ggPT0gXCJvYmplY3RcIiAmJiBoYXNSZWYoc2NoKSlcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5mdW5jdGlvbiBjb3VudEtleXMoc2NoZW1hKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleSBpbiBzY2hlbWEpIHtcbiAgICAgICAgaWYgKGtleSA9PT0gXCIkcmVmXCIpXG4gICAgICAgICAgICByZXR1cm4gSW5maW5pdHk7XG4gICAgICAgIGNvdW50Kys7XG4gICAgICAgIGlmIChTSU1QTEVfSU5MSU5FRC5oYXMoa2V5KSlcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICBpZiAodHlwZW9mIHNjaGVtYVtrZXldID09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICgwLCB1dGlsXzEuZWFjaEl0ZW0pKHNjaGVtYVtrZXldLCAoc2NoKSA9PiAoY291bnQgKz0gY291bnRLZXlzKHNjaCkpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY291bnQgPT09IEluZmluaXR5KVxuICAgICAgICAgICAgcmV0dXJuIEluZmluaXR5O1xuICAgIH1cbiAgICByZXR1cm4gY291bnQ7XG59XG5mdW5jdGlvbiBnZXRGdWxsUGF0aChyZXNvbHZlciwgaWQgPSBcIlwiLCBub3JtYWxpemUpIHtcbiAgICBpZiAobm9ybWFsaXplICE9PSBmYWxzZSlcbiAgICAgICAgaWQgPSBub3JtYWxpemVJZChpZCk7XG4gICAgY29uc3QgcCA9IHJlc29sdmVyLnBhcnNlKGlkKTtcbiAgICByZXR1cm4gX2dldEZ1bGxQYXRoKHJlc29sdmVyLCBwKTtcbn1cbmV4cG9ydHMuZ2V0RnVsbFBhdGggPSBnZXRGdWxsUGF0aDtcbmZ1bmN0aW9uIF9nZXRGdWxsUGF0aChyZXNvbHZlciwgcCkge1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSByZXNvbHZlci5zZXJpYWxpemUocCk7XG4gICAgcmV0dXJuIHNlcmlhbGl6ZWQuc3BsaXQoXCIjXCIpWzBdICsgXCIjXCI7XG59XG5leHBvcnRzLl9nZXRGdWxsUGF0aCA9IF9nZXRGdWxsUGF0aDtcbmNvbnN0IFRSQUlMSU5HX1NMQVNIX0hBU0ggPSAvI1xcLz8kLztcbmZ1bmN0aW9uIG5vcm1hbGl6ZUlkKGlkKSB7XG4gICAgcmV0dXJuIGlkID8gaWQucmVwbGFjZShUUkFJTElOR19TTEFTSF9IQVNILCBcIlwiKSA6IFwiXCI7XG59XG5leHBvcnRzLm5vcm1hbGl6ZUlkID0gbm9ybWFsaXplSWQ7XG5mdW5jdGlvbiByZXNvbHZlVXJsKHJlc29sdmVyLCBiYXNlSWQsIGlkKSB7XG4gICAgaWQgPSBub3JtYWxpemVJZChpZCk7XG4gICAgcmV0dXJuIHJlc29sdmVyLnJlc29sdmUoYmFzZUlkLCBpZCk7XG59XG5leHBvcnRzLnJlc29sdmVVcmwgPSByZXNvbHZlVXJsO1xuY29uc3QgQU5DSE9SID0gL15bYS16X11bLWEtejAtOS5fXSokL2k7XG5mdW5jdGlvbiBnZXRTY2hlbWFSZWZzKHNjaGVtYSwgYmFzZUlkKSB7XG4gICAgaWYgKHR5cGVvZiBzY2hlbWEgPT0gXCJib29sZWFuXCIpXG4gICAgICAgIHJldHVybiB7fTtcbiAgICBjb25zdCB7IHNjaGVtYUlkLCB1cmlSZXNvbHZlciB9ID0gdGhpcy5vcHRzO1xuICAgIGNvbnN0IHNjaElkID0gbm9ybWFsaXplSWQoc2NoZW1hW3NjaGVtYUlkXSB8fCBiYXNlSWQpO1xuICAgIGNvbnN0IGJhc2VJZHMgPSB7IFwiXCI6IHNjaElkIH07XG4gICAgY29uc3QgcGF0aFByZWZpeCA9IGdldEZ1bGxQYXRoKHVyaVJlc29sdmVyLCBzY2hJZCwgZmFsc2UpO1xuICAgIGNvbnN0IGxvY2FsUmVmcyA9IHt9O1xuICAgIGNvbnN0IHNjaGVtYVJlZnMgPSBuZXcgU2V0KCk7XG4gICAgdHJhdmVyc2Uoc2NoZW1hLCB7IGFsbEtleXM6IHRydWUgfSwgKHNjaCwganNvblB0ciwgXywgcGFyZW50SnNvblB0cikgPT4ge1xuICAgICAgICBpZiAocGFyZW50SnNvblB0ciA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGhQcmVmaXggKyBqc29uUHRyO1xuICAgICAgICBsZXQgYmFzZUlkID0gYmFzZUlkc1twYXJlbnRKc29uUHRyXTtcbiAgICAgICAgaWYgKHR5cGVvZiBzY2hbc2NoZW1hSWRdID09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICBiYXNlSWQgPSBhZGRSZWYuY2FsbCh0aGlzLCBzY2hbc2NoZW1hSWRdKTtcbiAgICAgICAgYWRkQW5jaG9yLmNhbGwodGhpcywgc2NoLiRhbmNob3IpO1xuICAgICAgICBhZGRBbmNob3IuY2FsbCh0aGlzLCBzY2guJGR5bmFtaWNBbmNob3IpO1xuICAgICAgICBiYXNlSWRzW2pzb25QdHJdID0gYmFzZUlkO1xuICAgICAgICBmdW5jdGlvbiBhZGRSZWYocmVmKSB7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L3VuYm91bmQtbWV0aG9kXG4gICAgICAgICAgICBjb25zdCBfcmVzb2x2ZSA9IHRoaXMub3B0cy51cmlSZXNvbHZlci5yZXNvbHZlO1xuICAgICAgICAgICAgcmVmID0gbm9ybWFsaXplSWQoYmFzZUlkID8gX3Jlc29sdmUoYmFzZUlkLCByZWYpIDogcmVmKTtcbiAgICAgICAgICAgIGlmIChzY2hlbWFSZWZzLmhhcyhyZWYpKVxuICAgICAgICAgICAgICAgIHRocm93IGFtYmlndW9zKHJlZik7XG4gICAgICAgICAgICBzY2hlbWFSZWZzLmFkZChyZWYpO1xuICAgICAgICAgICAgbGV0IHNjaE9yUmVmID0gdGhpcy5yZWZzW3JlZl07XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNjaE9yUmVmID09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgc2NoT3JSZWYgPSB0aGlzLnJlZnNbc2NoT3JSZWZdO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzY2hPclJlZiA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgY2hlY2tBbWJpZ3Vvc1JlZihzY2gsIHNjaE9yUmVmLnNjaGVtYSwgcmVmKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHJlZiAhPT0gbm9ybWFsaXplSWQoZnVsbFBhdGgpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlZlswXSA9PT0gXCIjXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tBbWJpZ3Vvc1JlZihzY2gsIGxvY2FsUmVmc1tyZWZdLCByZWYpO1xuICAgICAgICAgICAgICAgICAgICBsb2NhbFJlZnNbcmVmXSA9IHNjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVmc1tyZWZdID0gZnVsbFBhdGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlZjtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBhZGRBbmNob3IoYW5jaG9yKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGFuY2hvciA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBTkNIT1IudGVzdChhbmNob3IpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgYW5jaG9yIFwiJHthbmNob3J9XCJgKTtcbiAgICAgICAgICAgICAgICBhZGRSZWYuY2FsbCh0aGlzLCBgIyR7YW5jaG9yfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGxvY2FsUmVmcztcbiAgICBmdW5jdGlvbiBjaGVja0FtYmlndW9zUmVmKHNjaDEsIHNjaDIsIHJlZikge1xuICAgICAgICBpZiAoc2NoMiAhPT0gdW5kZWZpbmVkICYmICFlcXVhbChzY2gxLCBzY2gyKSlcbiAgICAgICAgICAgIHRocm93IGFtYmlndW9zKHJlZik7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGFtYmlndW9zKHJlZikge1xuICAgICAgICByZXR1cm4gbmV3IEVycm9yKGByZWZlcmVuY2UgXCIke3JlZn1cIiByZXNvbHZlcyB0byBtb3JlIHRoYW4gb25lIHNjaGVtYWApO1xuICAgIH1cbn1cbmV4cG9ydHMuZ2V0U2NoZW1hUmVmcyA9IGdldFNjaGVtYVJlZnM7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1yZXNvbHZlLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXhwb3J0cy5nZXRSdWxlcyA9IGV4cG9ydHMuaXNKU09OVHlwZSA9IHZvaWQgMDtcbmNvbnN0IF9qc29uVHlwZXMgPSBbXCJzdHJpbmdcIiwgXCJudW1iZXJcIiwgXCJpbnRlZ2VyXCIsIFwiYm9vbGVhblwiLCBcIm51bGxcIiwgXCJvYmplY3RcIiwgXCJhcnJheVwiXTtcbmNvbnN0IGpzb25UeXBlcyA9IG5ldyBTZXQoX2pzb25UeXBlcyk7XG5mdW5jdGlvbiBpc0pTT05UeXBlKHgpIHtcbiAgICByZXR1cm4gdHlwZW9mIHggPT0gXCJzdHJpbmdcIiAmJiBqc29uVHlwZXMuaGFzKHgpO1xufVxuZXhwb3J0cy5pc0pTT05UeXBlID0gaXNKU09OVHlwZTtcbmZ1bmN0aW9uIGdldFJ1bGVzKCkge1xuICAgIGNvbnN0IGdyb3VwcyA9IHtcbiAgICAgICAgbnVtYmVyOiB7IHR5cGU6IFwibnVtYmVyXCIsIHJ1bGVzOiBbXSB9LFxuICAgICAgICBzdHJpbmc6IHsgdHlwZTogXCJzdHJpbmdcIiwgcnVsZXM6IFtdIH0sXG4gICAgICAgIGFycmF5OiB7IHR5cGU6IFwiYXJyYXlcIiwgcnVsZXM6IFtdIH0sXG4gICAgICAgIG9iamVjdDogeyB0eXBlOiBcIm9iamVjdFwiLCBydWxlczogW10gfSxcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICAgIHR5cGVzOiB7IC4uLmdyb3VwcywgaW50ZWdlcjogdHJ1ZSwgYm9vbGVhbjogdHJ1ZSwgbnVsbDogdHJ1ZSB9LFxuICAgICAgICBydWxlczogW3sgcnVsZXM6IFtdIH0sIGdyb3Vwcy5udW1iZXIsIGdyb3Vwcy5zdHJpbmcsIGdyb3Vwcy5hcnJheSwgZ3JvdXBzLm9iamVjdF0sXG4gICAgICAgIHBvc3Q6IHsgcnVsZXM6IFtdIH0sXG4gICAgICAgIGFsbDoge30sXG4gICAgICAgIGtleXdvcmRzOiB7fSxcbiAgICB9O1xufVxuZXhwb3J0cy5nZXRSdWxlcyA9IGdldFJ1bGVzO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cnVsZXMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leHBvcnRzLmNoZWNrU3RyaWN0TW9kZSA9IGV4cG9ydHMuZ2V0RXJyb3JQYXRoID0gZXhwb3J0cy5UeXBlID0gZXhwb3J0cy51c2VGdW5jID0gZXhwb3J0cy5zZXRFdmFsdWF0ZWQgPSBleHBvcnRzLmV2YWx1YXRlZFByb3BzVG9OYW1lID0gZXhwb3J0cy5tZXJnZUV2YWx1YXRlZCA9IGV4cG9ydHMuZWFjaEl0ZW0gPSBleHBvcnRzLnVuZXNjYXBlSnNvblBvaW50ZXIgPSBleHBvcnRzLmVzY2FwZUpzb25Qb2ludGVyID0gZXhwb3J0cy5lc2NhcGVGcmFnbWVudCA9IGV4cG9ydHMudW5lc2NhcGVGcmFnbWVudCA9IGV4cG9ydHMuc2NoZW1hUmVmT3JWYWwgPSBleHBvcnRzLnNjaGVtYUhhc1J1bGVzQnV0UmVmID0gZXhwb3J0cy5zY2hlbWFIYXNSdWxlcyA9IGV4cG9ydHMuY2hlY2tVbmtub3duUnVsZXMgPSBleHBvcnRzLmFsd2F5c1ZhbGlkU2NoZW1hID0gZXhwb3J0cy50b0hhc2ggPSB2b2lkIDA7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi9jb2RlZ2VuXCIpO1xuY29uc3QgY29kZV8xID0gcmVxdWlyZShcIi4vY29kZWdlbi9jb2RlXCIpO1xuLy8gVE9ETyByZWZhY3RvciB0byB1c2UgU2V0XG5mdW5jdGlvbiB0b0hhc2goYXJyKSB7XG4gICAgY29uc3QgaGFzaCA9IHt9O1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiBhcnIpXG4gICAgICAgIGhhc2hbaXRlbV0gPSB0cnVlO1xuICAgIHJldHVybiBoYXNoO1xufVxuZXhwb3J0cy50b0hhc2ggPSB0b0hhc2g7XG5mdW5jdGlvbiBhbHdheXNWYWxpZFNjaGVtYShpdCwgc2NoZW1hKSB7XG4gICAgaWYgKHR5cGVvZiBzY2hlbWEgPT0gXCJib29sZWFuXCIpXG4gICAgICAgIHJldHVybiBzY2hlbWE7XG4gICAgaWYgKE9iamVjdC5rZXlzKHNjaGVtYSkubGVuZ3RoID09PSAwKVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICBjaGVja1Vua25vd25SdWxlcyhpdCwgc2NoZW1hKTtcbiAgICByZXR1cm4gIXNjaGVtYUhhc1J1bGVzKHNjaGVtYSwgaXQuc2VsZi5SVUxFUy5hbGwpO1xufVxuZXhwb3J0cy5hbHdheXNWYWxpZFNjaGVtYSA9IGFsd2F5c1ZhbGlkU2NoZW1hO1xuZnVuY3Rpb24gY2hlY2tVbmtub3duUnVsZXMoaXQsIHNjaGVtYSA9IGl0LnNjaGVtYSkge1xuICAgIGNvbnN0IHsgb3B0cywgc2VsZiB9ID0gaXQ7XG4gICAgaWYgKCFvcHRzLnN0cmljdFNjaGVtYSlcbiAgICAgICAgcmV0dXJuO1xuICAgIGlmICh0eXBlb2Ygc2NoZW1hID09PSBcImJvb2xlYW5cIilcbiAgICAgICAgcmV0dXJuO1xuICAgIGNvbnN0IHJ1bGVzID0gc2VsZi5SVUxFUy5rZXl3b3JkcztcbiAgICBmb3IgKGNvbnN0IGtleSBpbiBzY2hlbWEpIHtcbiAgICAgICAgaWYgKCFydWxlc1trZXldKVxuICAgICAgICAgICAgY2hlY2tTdHJpY3RNb2RlKGl0LCBgdW5rbm93biBrZXl3b3JkOiBcIiR7a2V5fVwiYCk7XG4gICAgfVxufVxuZXhwb3J0cy5jaGVja1Vua25vd25SdWxlcyA9IGNoZWNrVW5rbm93blJ1bGVzO1xuZnVuY3Rpb24gc2NoZW1hSGFzUnVsZXMoc2NoZW1hLCBydWxlcykge1xuICAgIGlmICh0eXBlb2Ygc2NoZW1hID09IFwiYm9vbGVhblwiKVxuICAgICAgICByZXR1cm4gIXNjaGVtYTtcbiAgICBmb3IgKGNvbnN0IGtleSBpbiBzY2hlbWEpXG4gICAgICAgIGlmIChydWxlc1trZXldKVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuZXhwb3J0cy5zY2hlbWFIYXNSdWxlcyA9IHNjaGVtYUhhc1J1bGVzO1xuZnVuY3Rpb24gc2NoZW1hSGFzUnVsZXNCdXRSZWYoc2NoZW1hLCBSVUxFUykge1xuICAgIGlmICh0eXBlb2Ygc2NoZW1hID09IFwiYm9vbGVhblwiKVxuICAgICAgICByZXR1cm4gIXNjaGVtYTtcbiAgICBmb3IgKGNvbnN0IGtleSBpbiBzY2hlbWEpXG4gICAgICAgIGlmIChrZXkgIT09IFwiJHJlZlwiICYmIFJVTEVTLmFsbFtrZXldKVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuZXhwb3J0cy5zY2hlbWFIYXNSdWxlc0J1dFJlZiA9IHNjaGVtYUhhc1J1bGVzQnV0UmVmO1xuZnVuY3Rpb24gc2NoZW1hUmVmT3JWYWwoeyB0b3BTY2hlbWFSZWYsIHNjaGVtYVBhdGggfSwgc2NoZW1hLCBrZXl3b3JkLCAkZGF0YSkge1xuICAgIGlmICghJGRhdGEpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBzY2hlbWEgPT0gXCJudW1iZXJcIiB8fCB0eXBlb2Ygc2NoZW1hID09IFwiYm9vbGVhblwiKVxuICAgICAgICAgICAgcmV0dXJuIHNjaGVtYTtcbiAgICAgICAgaWYgKHR5cGVvZiBzY2hlbWEgPT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgIHJldHVybiAoMCwgY29kZWdlbl8xLl8pIGAke3NjaGVtYX1gO1xuICAgIH1cbiAgICByZXR1cm4gKDAsIGNvZGVnZW5fMS5fKSBgJHt0b3BTY2hlbWFSZWZ9JHtzY2hlbWFQYXRofSR7KDAsIGNvZGVnZW5fMS5nZXRQcm9wZXJ0eSkoa2V5d29yZCl9YDtcbn1cbmV4cG9ydHMuc2NoZW1hUmVmT3JWYWwgPSBzY2hlbWFSZWZPclZhbDtcbmZ1bmN0aW9uIHVuZXNjYXBlRnJhZ21lbnQoc3RyKSB7XG4gICAgcmV0dXJuIHVuZXNjYXBlSnNvblBvaW50ZXIoZGVjb2RlVVJJQ29tcG9uZW50KHN0cikpO1xufVxuZXhwb3J0cy51bmVzY2FwZUZyYWdtZW50ID0gdW5lc2NhcGVGcmFnbWVudDtcbmZ1bmN0aW9uIGVzY2FwZUZyYWdtZW50KHN0cikge1xuICAgIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQoZXNjYXBlSnNvblBvaW50ZXIoc3RyKSk7XG59XG5leHBvcnRzLmVzY2FwZUZyYWdtZW50ID0gZXNjYXBlRnJhZ21lbnQ7XG5mdW5jdGlvbiBlc2NhcGVKc29uUG9pbnRlcihzdHIpIHtcbiAgICBpZiAodHlwZW9mIHN0ciA9PSBcIm51bWJlclwiKVxuICAgICAgICByZXR1cm4gYCR7c3RyfWA7XG4gICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9+L2csIFwifjBcIikucmVwbGFjZSgvXFwvL2csIFwifjFcIik7XG59XG5leHBvcnRzLmVzY2FwZUpzb25Qb2ludGVyID0gZXNjYXBlSnNvblBvaW50ZXI7XG5mdW5jdGlvbiB1bmVzY2FwZUpzb25Qb2ludGVyKHN0cikge1xuICAgIHJldHVybiBzdHIucmVwbGFjZSgvfjEvZywgXCIvXCIpLnJlcGxhY2UoL34wL2csIFwiflwiKTtcbn1cbmV4cG9ydHMudW5lc2NhcGVKc29uUG9pbnRlciA9IHVuZXNjYXBlSnNvblBvaW50ZXI7XG5mdW5jdGlvbiBlYWNoSXRlbSh4cywgZikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHhzKSkge1xuICAgICAgICBmb3IgKGNvbnN0IHggb2YgeHMpXG4gICAgICAgICAgICBmKHgpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZih4cyk7XG4gICAgfVxufVxuZXhwb3J0cy5lYWNoSXRlbSA9IGVhY2hJdGVtO1xuZnVuY3Rpb24gbWFrZU1lcmdlRXZhbHVhdGVkKHsgbWVyZ2VOYW1lcywgbWVyZ2VUb05hbWUsIG1lcmdlVmFsdWVzLCByZXN1bHRUb05hbWUsIH0pIHtcbiAgICByZXR1cm4gKGdlbiwgZnJvbSwgdG8sIHRvTmFtZSkgPT4ge1xuICAgICAgICBjb25zdCByZXMgPSB0byA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICA/IGZyb21cbiAgICAgICAgICAgIDogdG8gaW5zdGFuY2VvZiBjb2RlZ2VuXzEuTmFtZVxuICAgICAgICAgICAgICAgID8gKGZyb20gaW5zdGFuY2VvZiBjb2RlZ2VuXzEuTmFtZSA/IG1lcmdlTmFtZXMoZ2VuLCBmcm9tLCB0bykgOiBtZXJnZVRvTmFtZShnZW4sIGZyb20sIHRvKSwgdG8pXG4gICAgICAgICAgICAgICAgOiBmcm9tIGluc3RhbmNlb2YgY29kZWdlbl8xLk5hbWVcbiAgICAgICAgICAgICAgICAgICAgPyAobWVyZ2VUb05hbWUoZ2VuLCB0bywgZnJvbSksIGZyb20pXG4gICAgICAgICAgICAgICAgICAgIDogbWVyZ2VWYWx1ZXMoZnJvbSwgdG8pO1xuICAgICAgICByZXR1cm4gdG9OYW1lID09PSBjb2RlZ2VuXzEuTmFtZSAmJiAhKHJlcyBpbnN0YW5jZW9mIGNvZGVnZW5fMS5OYW1lKSA/IHJlc3VsdFRvTmFtZShnZW4sIHJlcykgOiByZXM7XG4gICAgfTtcbn1cbmV4cG9ydHMubWVyZ2VFdmFsdWF0ZWQgPSB7XG4gICAgcHJvcHM6IG1ha2VNZXJnZUV2YWx1YXRlZCh7XG4gICAgICAgIG1lcmdlTmFtZXM6IChnZW4sIGZyb20sIHRvKSA9PiBnZW4uaWYoKDAsIGNvZGVnZW5fMS5fKSBgJHt0b30gIT09IHRydWUgJiYgJHtmcm9tfSAhPT0gdW5kZWZpbmVkYCwgKCkgPT4ge1xuICAgICAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7ZnJvbX0gPT09IHRydWVgLCAoKSA9PiBnZW4uYXNzaWduKHRvLCB0cnVlKSwgKCkgPT4gZ2VuLmFzc2lnbih0bywgKDAsIGNvZGVnZW5fMS5fKSBgJHt0b30gfHwge31gKS5jb2RlKCgwLCBjb2RlZ2VuXzEuXykgYE9iamVjdC5hc3NpZ24oJHt0b30sICR7ZnJvbX0pYCkpO1xuICAgICAgICB9KSxcbiAgICAgICAgbWVyZ2VUb05hbWU6IChnZW4sIGZyb20sIHRvKSA9PiBnZW4uaWYoKDAsIGNvZGVnZW5fMS5fKSBgJHt0b30gIT09IHRydWVgLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoZnJvbSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGdlbi5hc3NpZ24odG8sIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZ2VuLmFzc2lnbih0bywgKDAsIGNvZGVnZW5fMS5fKSBgJHt0b30gfHwge31gKTtcbiAgICAgICAgICAgICAgICBzZXRFdmFsdWF0ZWQoZ2VuLCB0bywgZnJvbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLFxuICAgICAgICBtZXJnZVZhbHVlczogKGZyb20sIHRvKSA9PiAoZnJvbSA9PT0gdHJ1ZSA/IHRydWUgOiB7IC4uLmZyb20sIC4uLnRvIH0pLFxuICAgICAgICByZXN1bHRUb05hbWU6IGV2YWx1YXRlZFByb3BzVG9OYW1lLFxuICAgIH0pLFxuICAgIGl0ZW1zOiBtYWtlTWVyZ2VFdmFsdWF0ZWQoe1xuICAgICAgICBtZXJnZU5hbWVzOiAoZ2VuLCBmcm9tLCB0bykgPT4gZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7dG99ICE9PSB0cnVlICYmICR7ZnJvbX0gIT09IHVuZGVmaW5lZGAsICgpID0+IGdlbi5hc3NpZ24odG8sICgwLCBjb2RlZ2VuXzEuXykgYCR7ZnJvbX0gPT09IHRydWUgPyB0cnVlIDogJHt0b30gPiAke2Zyb219ID8gJHt0b30gOiAke2Zyb219YCkpLFxuICAgICAgICBtZXJnZVRvTmFtZTogKGdlbiwgZnJvbSwgdG8pID0+IGdlbi5pZigoMCwgY29kZWdlbl8xLl8pIGAke3RvfSAhPT0gdHJ1ZWAsICgpID0+IGdlbi5hc3NpZ24odG8sIGZyb20gPT09IHRydWUgPyB0cnVlIDogKDAsIGNvZGVnZW5fMS5fKSBgJHt0b30gPiAke2Zyb219ID8gJHt0b30gOiAke2Zyb219YCkpLFxuICAgICAgICBtZXJnZVZhbHVlczogKGZyb20sIHRvKSA9PiAoZnJvbSA9PT0gdHJ1ZSA/IHRydWUgOiBNYXRoLm1heChmcm9tLCB0bykpLFxuICAgICAgICByZXN1bHRUb05hbWU6IChnZW4sIGl0ZW1zKSA9PiBnZW4udmFyKFwiaXRlbXNcIiwgaXRlbXMpLFxuICAgIH0pLFxufTtcbmZ1bmN0aW9uIGV2YWx1YXRlZFByb3BzVG9OYW1lKGdlbiwgcHMpIHtcbiAgICBpZiAocHMgPT09IHRydWUpXG4gICAgICAgIHJldHVybiBnZW4udmFyKFwicHJvcHNcIiwgdHJ1ZSk7XG4gICAgY29uc3QgcHJvcHMgPSBnZW4udmFyKFwicHJvcHNcIiwgKDAsIGNvZGVnZW5fMS5fKSBge31gKTtcbiAgICBpZiAocHMgIT09IHVuZGVmaW5lZClcbiAgICAgICAgc2V0RXZhbHVhdGVkKGdlbiwgcHJvcHMsIHBzKTtcbiAgICByZXR1cm4gcHJvcHM7XG59XG5leHBvcnRzLmV2YWx1YXRlZFByb3BzVG9OYW1lID0gZXZhbHVhdGVkUHJvcHNUb05hbWU7XG5mdW5jdGlvbiBzZXRFdmFsdWF0ZWQoZ2VuLCBwcm9wcywgcHMpIHtcbiAgICBPYmplY3Qua2V5cyhwcykuZm9yRWFjaCgocCkgPT4gZ2VuLmFzc2lnbigoMCwgY29kZWdlbl8xLl8pIGAke3Byb3BzfSR7KDAsIGNvZGVnZW5fMS5nZXRQcm9wZXJ0eSkocCl9YCwgdHJ1ZSkpO1xufVxuZXhwb3J0cy5zZXRFdmFsdWF0ZWQgPSBzZXRFdmFsdWF0ZWQ7XG5jb25zdCBzbmlwcGV0cyA9IHt9O1xuZnVuY3Rpb24gdXNlRnVuYyhnZW4sIGYpIHtcbiAgICByZXR1cm4gZ2VuLnNjb3BlVmFsdWUoXCJmdW5jXCIsIHtcbiAgICAgICAgcmVmOiBmLFxuICAgICAgICBjb2RlOiBzbmlwcGV0c1tmLmNvZGVdIHx8IChzbmlwcGV0c1tmLmNvZGVdID0gbmV3IGNvZGVfMS5fQ29kZShmLmNvZGUpKSxcbiAgICB9KTtcbn1cbmV4cG9ydHMudXNlRnVuYyA9IHVzZUZ1bmM7XG52YXIgVHlwZTtcbihmdW5jdGlvbiAoVHlwZSkge1xuICAgIFR5cGVbVHlwZVtcIk51bVwiXSA9IDBdID0gXCJOdW1cIjtcbiAgICBUeXBlW1R5cGVbXCJTdHJcIl0gPSAxXSA9IFwiU3RyXCI7XG59KShUeXBlID0gZXhwb3J0cy5UeXBlIHx8IChleHBvcnRzLlR5cGUgPSB7fSkpO1xuZnVuY3Rpb24gZ2V0RXJyb3JQYXRoKGRhdGFQcm9wLCBkYXRhUHJvcFR5cGUsIGpzUHJvcGVydHlTeW50YXgpIHtcbiAgICAvLyBsZXQgcGF0aFxuICAgIGlmIChkYXRhUHJvcCBpbnN0YW5jZW9mIGNvZGVnZW5fMS5OYW1lKSB7XG4gICAgICAgIGNvbnN0IGlzTnVtYmVyID0gZGF0YVByb3BUeXBlID09PSBUeXBlLk51bTtcbiAgICAgICAgcmV0dXJuIGpzUHJvcGVydHlTeW50YXhcbiAgICAgICAgICAgID8gaXNOdW1iZXJcbiAgICAgICAgICAgICAgICA/ICgwLCBjb2RlZ2VuXzEuXykgYFwiW1wiICsgJHtkYXRhUHJvcH0gKyBcIl1cImBcbiAgICAgICAgICAgICAgICA6ICgwLCBjb2RlZ2VuXzEuXykgYFwiWydcIiArICR7ZGF0YVByb3B9ICsgXCInXVwiYFxuICAgICAgICAgICAgOiBpc051bWJlclxuICAgICAgICAgICAgICAgID8gKDAsIGNvZGVnZW5fMS5fKSBgXCIvXCIgKyAke2RhdGFQcm9wfWBcbiAgICAgICAgICAgICAgICA6ICgwLCBjb2RlZ2VuXzEuXykgYFwiL1wiICsgJHtkYXRhUHJvcH0ucmVwbGFjZSgvfi9nLCBcIn4wXCIpLnJlcGxhY2UoL1xcXFwvL2csIFwifjFcIilgOyAvLyBUT0RPIG1heWJlIHVzZSBnbG9iYWwgZXNjYXBlUG9pbnRlclxuICAgIH1cbiAgICByZXR1cm4ganNQcm9wZXJ0eVN5bnRheCA/ICgwLCBjb2RlZ2VuXzEuZ2V0UHJvcGVydHkpKGRhdGFQcm9wKS50b1N0cmluZygpIDogXCIvXCIgKyBlc2NhcGVKc29uUG9pbnRlcihkYXRhUHJvcCk7XG59XG5leHBvcnRzLmdldEVycm9yUGF0aCA9IGdldEVycm9yUGF0aDtcbmZ1bmN0aW9uIGNoZWNrU3RyaWN0TW9kZShpdCwgbXNnLCBtb2RlID0gaXQub3B0cy5zdHJpY3RTY2hlbWEpIHtcbiAgICBpZiAoIW1vZGUpXG4gICAgICAgIHJldHVybjtcbiAgICBtc2cgPSBgc3RyaWN0IG1vZGU6ICR7bXNnfWA7XG4gICAgaWYgKG1vZGUgPT09IHRydWUpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgIGl0LnNlbGYubG9nZ2VyLndhcm4obXNnKTtcbn1cbmV4cG9ydHMuY2hlY2tTdHJpY3RNb2RlID0gY2hlY2tTdHJpY3RNb2RlO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dXRpbC5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmV4cG9ydHMuc2hvdWxkVXNlUnVsZSA9IGV4cG9ydHMuc2hvdWxkVXNlR3JvdXAgPSBleHBvcnRzLnNjaGVtYUhhc1J1bGVzRm9yVHlwZSA9IHZvaWQgMDtcbmZ1bmN0aW9uIHNjaGVtYUhhc1J1bGVzRm9yVHlwZSh7IHNjaGVtYSwgc2VsZiB9LCB0eXBlKSB7XG4gICAgY29uc3QgZ3JvdXAgPSBzZWxmLlJVTEVTLnR5cGVzW3R5cGVdO1xuICAgIHJldHVybiBncm91cCAmJiBncm91cCAhPT0gdHJ1ZSAmJiBzaG91bGRVc2VHcm91cChzY2hlbWEsIGdyb3VwKTtcbn1cbmV4cG9ydHMuc2NoZW1hSGFzUnVsZXNGb3JUeXBlID0gc2NoZW1hSGFzUnVsZXNGb3JUeXBlO1xuZnVuY3Rpb24gc2hvdWxkVXNlR3JvdXAoc2NoZW1hLCBncm91cCkge1xuICAgIHJldHVybiBncm91cC5ydWxlcy5zb21lKChydWxlKSA9PiBzaG91bGRVc2VSdWxlKHNjaGVtYSwgcnVsZSkpO1xufVxuZXhwb3J0cy5zaG91bGRVc2VHcm91cCA9IHNob3VsZFVzZUdyb3VwO1xuZnVuY3Rpb24gc2hvdWxkVXNlUnVsZShzY2hlbWEsIHJ1bGUpIHtcbiAgICB2YXIgX2E7XG4gICAgcmV0dXJuIChzY2hlbWFbcnVsZS5rZXl3b3JkXSAhPT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICgoX2EgPSBydWxlLmRlZmluaXRpb24uaW1wbGVtZW50cykgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnNvbWUoKGt3ZCkgPT4gc2NoZW1hW2t3ZF0gIT09IHVuZGVmaW5lZCkpKTtcbn1cbmV4cG9ydHMuc2hvdWxkVXNlUnVsZSA9IHNob3VsZFVzZVJ1bGU7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1hcHBsaWNhYmlsaXR5LmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXhwb3J0cy5ib29sT3JFbXB0eVNjaGVtYSA9IGV4cG9ydHMudG9wQm9vbE9yRW1wdHlTY2hlbWEgPSB2b2lkIDA7XG5jb25zdCBlcnJvcnNfMSA9IHJlcXVpcmUoXCIuLi9lcnJvcnNcIik7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vY29kZWdlblwiKTtcbmNvbnN0IG5hbWVzXzEgPSByZXF1aXJlKFwiLi4vbmFtZXNcIik7XG5jb25zdCBib29sRXJyb3IgPSB7XG4gICAgbWVzc2FnZTogXCJib29sZWFuIHNjaGVtYSBpcyBmYWxzZVwiLFxufTtcbmZ1bmN0aW9uIHRvcEJvb2xPckVtcHR5U2NoZW1hKGl0KSB7XG4gICAgY29uc3QgeyBnZW4sIHNjaGVtYSwgdmFsaWRhdGVOYW1lIH0gPSBpdDtcbiAgICBpZiAoc2NoZW1hID09PSBmYWxzZSkge1xuICAgICAgICBmYWxzZVNjaGVtYUVycm9yKGl0LCBmYWxzZSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBzY2hlbWEgPT0gXCJvYmplY3RcIiAmJiBzY2hlbWEuJGFzeW5jID09PSB0cnVlKSB7XG4gICAgICAgIGdlbi5yZXR1cm4obmFtZXNfMS5kZWZhdWx0LmRhdGEpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZ2VuLmFzc2lnbigoMCwgY29kZWdlbl8xLl8pIGAke3ZhbGlkYXRlTmFtZX0uZXJyb3JzYCwgbnVsbCk7XG4gICAgICAgIGdlbi5yZXR1cm4odHJ1ZSk7XG4gICAgfVxufVxuZXhwb3J0cy50b3BCb29sT3JFbXB0eVNjaGVtYSA9IHRvcEJvb2xPckVtcHR5U2NoZW1hO1xuZnVuY3Rpb24gYm9vbE9yRW1wdHlTY2hlbWEoaXQsIHZhbGlkKSB7XG4gICAgY29uc3QgeyBnZW4sIHNjaGVtYSB9ID0gaXQ7XG4gICAgaWYgKHNjaGVtYSA9PT0gZmFsc2UpIHtcbiAgICAgICAgZ2VuLnZhcih2YWxpZCwgZmFsc2UpOyAvLyBUT0RPIHZhclxuICAgICAgICBmYWxzZVNjaGVtYUVycm9yKGl0KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGdlbi52YXIodmFsaWQsIHRydWUpOyAvLyBUT0RPIHZhclxuICAgIH1cbn1cbmV4cG9ydHMuYm9vbE9yRW1wdHlTY2hlbWEgPSBib29sT3JFbXB0eVNjaGVtYTtcbmZ1bmN0aW9uIGZhbHNlU2NoZW1hRXJyb3IoaXQsIG92ZXJyaWRlQWxsRXJyb3JzKSB7XG4gICAgY29uc3QgeyBnZW4sIGRhdGEgfSA9IGl0O1xuICAgIC8vIFRPRE8gbWF5YmUgc29tZSBvdGhlciBpbnRlcmZhY2Ugc2hvdWxkIGJlIHVzZWQgZm9yIG5vbi1rZXl3b3JkIHZhbGlkYXRpb24gZXJyb3JzLi4uXG4gICAgY29uc3QgY3h0ID0ge1xuICAgICAgICBnZW4sXG4gICAgICAgIGtleXdvcmQ6IFwiZmFsc2Ugc2NoZW1hXCIsXG4gICAgICAgIGRhdGEsXG4gICAgICAgIHNjaGVtYTogZmFsc2UsXG4gICAgICAgIHNjaGVtYUNvZGU6IGZhbHNlLFxuICAgICAgICBzY2hlbWFWYWx1ZTogZmFsc2UsXG4gICAgICAgIHBhcmFtczoge30sXG4gICAgICAgIGl0LFxuICAgIH07XG4gICAgKDAsIGVycm9yc18xLnJlcG9ydEVycm9yKShjeHQsIGJvb2xFcnJvciwgdW5kZWZpbmVkLCBvdmVycmlkZUFsbEVycm9ycyk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1ib29sU2NoZW1hLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXhwb3J0cy5yZXBvcnRUeXBlRXJyb3IgPSBleHBvcnRzLmNoZWNrRGF0YVR5cGVzID0gZXhwb3J0cy5jaGVja0RhdGFUeXBlID0gZXhwb3J0cy5jb2VyY2VBbmRDaGVja0RhdGFUeXBlID0gZXhwb3J0cy5nZXRKU09OVHlwZXMgPSBleHBvcnRzLmdldFNjaGVtYVR5cGVzID0gZXhwb3J0cy5EYXRhVHlwZSA9IHZvaWQgMDtcbmNvbnN0IHJ1bGVzXzEgPSByZXF1aXJlKFwiLi4vcnVsZXNcIik7XG5jb25zdCBhcHBsaWNhYmlsaXR5XzEgPSByZXF1aXJlKFwiLi9hcHBsaWNhYmlsaXR5XCIpO1xuY29uc3QgZXJyb3JzXzEgPSByZXF1aXJlKFwiLi4vZXJyb3JzXCIpO1xuY29uc3QgY29kZWdlbl8xID0gcmVxdWlyZShcIi4uL2NvZGVnZW5cIik7XG5jb25zdCB1dGlsXzEgPSByZXF1aXJlKFwiLi4vdXRpbFwiKTtcbnZhciBEYXRhVHlwZTtcbihmdW5jdGlvbiAoRGF0YVR5cGUpIHtcbiAgICBEYXRhVHlwZVtEYXRhVHlwZVtcIkNvcnJlY3RcIl0gPSAwXSA9IFwiQ29ycmVjdFwiO1xuICAgIERhdGFUeXBlW0RhdGFUeXBlW1wiV3JvbmdcIl0gPSAxXSA9IFwiV3JvbmdcIjtcbn0pKERhdGFUeXBlID0gZXhwb3J0cy5EYXRhVHlwZSB8fCAoZXhwb3J0cy5EYXRhVHlwZSA9IHt9KSk7XG5mdW5jdGlvbiBnZXRTY2hlbWFUeXBlcyhzY2hlbWEpIHtcbiAgICBjb25zdCB0eXBlcyA9IGdldEpTT05UeXBlcyhzY2hlbWEudHlwZSk7XG4gICAgY29uc3QgaGFzTnVsbCA9IHR5cGVzLmluY2x1ZGVzKFwibnVsbFwiKTtcbiAgICBpZiAoaGFzTnVsbCkge1xuICAgICAgICBpZiAoc2NoZW1hLm51bGxhYmxlID09PSBmYWxzZSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInR5cGU6IG51bGwgY29udHJhZGljdHMgbnVsbGFibGU6IGZhbHNlXCIpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWYgKCF0eXBlcy5sZW5ndGggJiYgc2NoZW1hLm51bGxhYmxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignXCJudWxsYWJsZVwiIGNhbm5vdCBiZSB1c2VkIHdpdGhvdXQgXCJ0eXBlXCInKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2NoZW1hLm51bGxhYmxlID09PSB0cnVlKVxuICAgICAgICAgICAgdHlwZXMucHVzaChcIm51bGxcIik7XG4gICAgfVxuICAgIHJldHVybiB0eXBlcztcbn1cbmV4cG9ydHMuZ2V0U2NoZW1hVHlwZXMgPSBnZXRTY2hlbWFUeXBlcztcbmZ1bmN0aW9uIGdldEpTT05UeXBlcyh0cykge1xuICAgIGNvbnN0IHR5cGVzID0gQXJyYXkuaXNBcnJheSh0cykgPyB0cyA6IHRzID8gW3RzXSA6IFtdO1xuICAgIGlmICh0eXBlcy5ldmVyeShydWxlc18xLmlzSlNPTlR5cGUpKVxuICAgICAgICByZXR1cm4gdHlwZXM7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwidHlwZSBtdXN0IGJlIEpTT05UeXBlIG9yIEpTT05UeXBlW106IFwiICsgdHlwZXMuam9pbihcIixcIikpO1xufVxuZXhwb3J0cy5nZXRKU09OVHlwZXMgPSBnZXRKU09OVHlwZXM7XG5mdW5jdGlvbiBjb2VyY2VBbmRDaGVja0RhdGFUeXBlKGl0LCB0eXBlcykge1xuICAgIGNvbnN0IHsgZ2VuLCBkYXRhLCBvcHRzIH0gPSBpdDtcbiAgICBjb25zdCBjb2VyY2VUbyA9IGNvZXJjZVRvVHlwZXModHlwZXMsIG9wdHMuY29lcmNlVHlwZXMpO1xuICAgIGNvbnN0IGNoZWNrVHlwZXMgPSB0eXBlcy5sZW5ndGggPiAwICYmXG4gICAgICAgICEoY29lcmNlVG8ubGVuZ3RoID09PSAwICYmIHR5cGVzLmxlbmd0aCA9PT0gMSAmJiAoMCwgYXBwbGljYWJpbGl0eV8xLnNjaGVtYUhhc1J1bGVzRm9yVHlwZSkoaXQsIHR5cGVzWzBdKSk7XG4gICAgaWYgKGNoZWNrVHlwZXMpIHtcbiAgICAgICAgY29uc3Qgd3JvbmdUeXBlID0gY2hlY2tEYXRhVHlwZXModHlwZXMsIGRhdGEsIG9wdHMuc3RyaWN0TnVtYmVycywgRGF0YVR5cGUuV3JvbmcpO1xuICAgICAgICBnZW4uaWYod3JvbmdUeXBlLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoY29lcmNlVG8ubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGNvZXJjZURhdGEoaXQsIHR5cGVzLCBjb2VyY2VUbyk7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgcmVwb3J0VHlwZUVycm9yKGl0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBjaGVja1R5cGVzO1xufVxuZXhwb3J0cy5jb2VyY2VBbmRDaGVja0RhdGFUeXBlID0gY29lcmNlQW5kQ2hlY2tEYXRhVHlwZTtcbmNvbnN0IENPRVJDSUJMRSA9IG5ldyBTZXQoW1wic3RyaW5nXCIsIFwibnVtYmVyXCIsIFwiaW50ZWdlclwiLCBcImJvb2xlYW5cIiwgXCJudWxsXCJdKTtcbmZ1bmN0aW9uIGNvZXJjZVRvVHlwZXModHlwZXMsIGNvZXJjZVR5cGVzKSB7XG4gICAgcmV0dXJuIGNvZXJjZVR5cGVzXG4gICAgICAgID8gdHlwZXMuZmlsdGVyKCh0KSA9PiBDT0VSQ0lCTEUuaGFzKHQpIHx8IChjb2VyY2VUeXBlcyA9PT0gXCJhcnJheVwiICYmIHQgPT09IFwiYXJyYXlcIikpXG4gICAgICAgIDogW107XG59XG5mdW5jdGlvbiBjb2VyY2VEYXRhKGl0LCB0eXBlcywgY29lcmNlVG8pIHtcbiAgICBjb25zdCB7IGdlbiwgZGF0YSwgb3B0cyB9ID0gaXQ7XG4gICAgY29uc3QgZGF0YVR5cGUgPSBnZW4ubGV0KFwiZGF0YVR5cGVcIiwgKDAsIGNvZGVnZW5fMS5fKSBgdHlwZW9mICR7ZGF0YX1gKTtcbiAgICBjb25zdCBjb2VyY2VkID0gZ2VuLmxldChcImNvZXJjZWRcIiwgKDAsIGNvZGVnZW5fMS5fKSBgdW5kZWZpbmVkYCk7XG4gICAgaWYgKG9wdHMuY29lcmNlVHlwZXMgPT09IFwiYXJyYXlcIikge1xuICAgICAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhVHlwZX0gPT0gJ29iamVjdCcgJiYgQXJyYXkuaXNBcnJheSgke2RhdGF9KSAmJiAke2RhdGF9Lmxlbmd0aCA9PSAxYCwgKCkgPT4gZ2VuXG4gICAgICAgICAgICAuYXNzaWduKGRhdGEsICgwLCBjb2RlZ2VuXzEuXykgYCR7ZGF0YX1bMF1gKVxuICAgICAgICAgICAgLmFzc2lnbihkYXRhVHlwZSwgKDAsIGNvZGVnZW5fMS5fKSBgdHlwZW9mICR7ZGF0YX1gKVxuICAgICAgICAgICAgLmlmKGNoZWNrRGF0YVR5cGVzKHR5cGVzLCBkYXRhLCBvcHRzLnN0cmljdE51bWJlcnMpLCAoKSA9PiBnZW4uYXNzaWduKGNvZXJjZWQsIGRhdGEpKSk7XG4gICAgfVxuICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLl8pIGAke2NvZXJjZWR9ICE9PSB1bmRlZmluZWRgKTtcbiAgICBmb3IgKGNvbnN0IHQgb2YgY29lcmNlVG8pIHtcbiAgICAgICAgaWYgKENPRVJDSUJMRS5oYXModCkgfHwgKHQgPT09IFwiYXJyYXlcIiAmJiBvcHRzLmNvZXJjZVR5cGVzID09PSBcImFycmF5XCIpKSB7XG4gICAgICAgICAgICBjb2VyY2VTcGVjaWZpY1R5cGUodCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZ2VuLmVsc2UoKTtcbiAgICByZXBvcnRUeXBlRXJyb3IoaXQpO1xuICAgIGdlbi5lbmRJZigpO1xuICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLl8pIGAke2NvZXJjZWR9ICE9PSB1bmRlZmluZWRgLCAoKSA9PiB7XG4gICAgICAgIGdlbi5hc3NpZ24oZGF0YSwgY29lcmNlZCk7XG4gICAgICAgIGFzc2lnblBhcmVudERhdGEoaXQsIGNvZXJjZWQpO1xuICAgIH0pO1xuICAgIGZ1bmN0aW9uIGNvZXJjZVNwZWNpZmljVHlwZSh0KSB7XG4gICAgICAgIHN3aXRjaCAodCkge1xuICAgICAgICAgICAgY2FzZSBcInN0cmluZ1wiOlxuICAgICAgICAgICAgICAgIGdlblxuICAgICAgICAgICAgICAgICAgICAuZWxzZUlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7ZGF0YVR5cGV9ID09IFwibnVtYmVyXCIgfHwgJHtkYXRhVHlwZX0gPT0gXCJib29sZWFuXCJgKVxuICAgICAgICAgICAgICAgICAgICAuYXNzaWduKGNvZXJjZWQsICgwLCBjb2RlZ2VuXzEuXykgYFwiXCIgKyAke2RhdGF9YClcbiAgICAgICAgICAgICAgICAgICAgLmVsc2VJZigoMCwgY29kZWdlbl8xLl8pIGAke2RhdGF9ID09PSBudWxsYClcbiAgICAgICAgICAgICAgICAgICAgLmFzc2lnbihjb2VyY2VkLCAoMCwgY29kZWdlbl8xLl8pIGBcIlwiYCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgY2FzZSBcIm51bWJlclwiOlxuICAgICAgICAgICAgICAgIGdlblxuICAgICAgICAgICAgICAgICAgICAuZWxzZUlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7ZGF0YVR5cGV9ID09IFwiYm9vbGVhblwiIHx8ICR7ZGF0YX0gPT09IG51bGxcbiAgICAgICAgICAgICAgfHwgKCR7ZGF0YVR5cGV9ID09IFwic3RyaW5nXCIgJiYgJHtkYXRhfSAmJiAke2RhdGF9ID09ICske2RhdGF9KWApXG4gICAgICAgICAgICAgICAgICAgIC5hc3NpZ24oY29lcmNlZCwgKDAsIGNvZGVnZW5fMS5fKSBgKyR7ZGF0YX1gKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBjYXNlIFwiaW50ZWdlclwiOlxuICAgICAgICAgICAgICAgIGdlblxuICAgICAgICAgICAgICAgICAgICAuZWxzZUlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7ZGF0YVR5cGV9ID09PSBcImJvb2xlYW5cIiB8fCAke2RhdGF9ID09PSBudWxsXG4gICAgICAgICAgICAgIHx8ICgke2RhdGFUeXBlfSA9PT0gXCJzdHJpbmdcIiAmJiAke2RhdGF9ICYmICR7ZGF0YX0gPT0gKyR7ZGF0YX0gJiYgISgke2RhdGF9ICUgMSkpYClcbiAgICAgICAgICAgICAgICAgICAgLmFzc2lnbihjb2VyY2VkLCAoMCwgY29kZWdlbl8xLl8pIGArJHtkYXRhfWApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIGNhc2UgXCJib29sZWFuXCI6XG4gICAgICAgICAgICAgICAgZ2VuXG4gICAgICAgICAgICAgICAgICAgIC5lbHNlSWYoKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhfSA9PT0gXCJmYWxzZVwiIHx8ICR7ZGF0YX0gPT09IDAgfHwgJHtkYXRhfSA9PT0gbnVsbGApXG4gICAgICAgICAgICAgICAgICAgIC5hc3NpZ24oY29lcmNlZCwgZmFsc2UpXG4gICAgICAgICAgICAgICAgICAgIC5lbHNlSWYoKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhfSA9PT0gXCJ0cnVlXCIgfHwgJHtkYXRhfSA9PT0gMWApXG4gICAgICAgICAgICAgICAgICAgIC5hc3NpZ24oY29lcmNlZCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgY2FzZSBcIm51bGxcIjpcbiAgICAgICAgICAgICAgICBnZW4uZWxzZUlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7ZGF0YX0gPT09IFwiXCIgfHwgJHtkYXRhfSA9PT0gMCB8fCAke2RhdGF9ID09PSBmYWxzZWApO1xuICAgICAgICAgICAgICAgIGdlbi5hc3NpZ24oY29lcmNlZCwgbnVsbCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgY2FzZSBcImFycmF5XCI6XG4gICAgICAgICAgICAgICAgZ2VuXG4gICAgICAgICAgICAgICAgICAgIC5lbHNlSWYoKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhVHlwZX0gPT09IFwic3RyaW5nXCIgfHwgJHtkYXRhVHlwZX0gPT09IFwibnVtYmVyXCJcbiAgICAgICAgICAgICAgfHwgJHtkYXRhVHlwZX0gPT09IFwiYm9vbGVhblwiIHx8ICR7ZGF0YX0gPT09IG51bGxgKVxuICAgICAgICAgICAgICAgICAgICAuYXNzaWduKGNvZXJjZWQsICgwLCBjb2RlZ2VuXzEuXykgYFske2RhdGF9XWApO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gYXNzaWduUGFyZW50RGF0YSh7IGdlbiwgcGFyZW50RGF0YSwgcGFyZW50RGF0YVByb3BlcnR5IH0sIGV4cHIpIHtcbiAgICAvLyBUT0RPIHVzZSBnZW4ucHJvcGVydHlcbiAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5fKSBgJHtwYXJlbnREYXRhfSAhPT0gdW5kZWZpbmVkYCwgKCkgPT4gZ2VuLmFzc2lnbigoMCwgY29kZWdlbl8xLl8pIGAke3BhcmVudERhdGF9WyR7cGFyZW50RGF0YVByb3BlcnR5fV1gLCBleHByKSk7XG59XG5mdW5jdGlvbiBjaGVja0RhdGFUeXBlKGRhdGFUeXBlLCBkYXRhLCBzdHJpY3ROdW1zLCBjb3JyZWN0ID0gRGF0YVR5cGUuQ29ycmVjdCkge1xuICAgIGNvbnN0IEVRID0gY29ycmVjdCA9PT0gRGF0YVR5cGUuQ29ycmVjdCA/IGNvZGVnZW5fMS5vcGVyYXRvcnMuRVEgOiBjb2RlZ2VuXzEub3BlcmF0b3JzLk5FUTtcbiAgICBsZXQgY29uZDtcbiAgICBzd2l0Y2ggKGRhdGFUeXBlKSB7XG4gICAgICAgIGNhc2UgXCJudWxsXCI6XG4gICAgICAgICAgICByZXR1cm4gKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhfSAke0VRfSBudWxsYDtcbiAgICAgICAgY2FzZSBcImFycmF5XCI6XG4gICAgICAgICAgICBjb25kID0gKDAsIGNvZGVnZW5fMS5fKSBgQXJyYXkuaXNBcnJheSgke2RhdGF9KWA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcIm9iamVjdFwiOlxuICAgICAgICAgICAgY29uZCA9ICgwLCBjb2RlZ2VuXzEuXykgYCR7ZGF0YX0gJiYgdHlwZW9mICR7ZGF0YX0gPT0gXCJvYmplY3RcIiAmJiAhQXJyYXkuaXNBcnJheSgke2RhdGF9KWA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcImludGVnZXJcIjpcbiAgICAgICAgICAgIGNvbmQgPSBudW1Db25kKCgwLCBjb2RlZ2VuXzEuXykgYCEoJHtkYXRhfSAlIDEpICYmICFpc05hTigke2RhdGF9KWApO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJudW1iZXJcIjpcbiAgICAgICAgICAgIGNvbmQgPSBudW1Db25kKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiAoMCwgY29kZWdlbl8xLl8pIGB0eXBlb2YgJHtkYXRhfSAke0VRfSAke2RhdGFUeXBlfWA7XG4gICAgfVxuICAgIHJldHVybiBjb3JyZWN0ID09PSBEYXRhVHlwZS5Db3JyZWN0ID8gY29uZCA6ICgwLCBjb2RlZ2VuXzEubm90KShjb25kKTtcbiAgICBmdW5jdGlvbiBudW1Db25kKF9jb25kID0gY29kZWdlbl8xLm5pbCkge1xuICAgICAgICByZXR1cm4gKDAsIGNvZGVnZW5fMS5hbmQpKCgwLCBjb2RlZ2VuXzEuXykgYHR5cGVvZiAke2RhdGF9ID09IFwibnVtYmVyXCJgLCBfY29uZCwgc3RyaWN0TnVtcyA/ICgwLCBjb2RlZ2VuXzEuXykgYGlzRmluaXRlKCR7ZGF0YX0pYCA6IGNvZGVnZW5fMS5uaWwpO1xuICAgIH1cbn1cbmV4cG9ydHMuY2hlY2tEYXRhVHlwZSA9IGNoZWNrRGF0YVR5cGU7XG5mdW5jdGlvbiBjaGVja0RhdGFUeXBlcyhkYXRhVHlwZXMsIGRhdGEsIHN0cmljdE51bXMsIGNvcnJlY3QpIHtcbiAgICBpZiAoZGF0YVR5cGVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4gY2hlY2tEYXRhVHlwZShkYXRhVHlwZXNbMF0sIGRhdGEsIHN0cmljdE51bXMsIGNvcnJlY3QpO1xuICAgIH1cbiAgICBsZXQgY29uZDtcbiAgICBjb25zdCB0eXBlcyA9ICgwLCB1dGlsXzEudG9IYXNoKShkYXRhVHlwZXMpO1xuICAgIGlmICh0eXBlcy5hcnJheSAmJiB0eXBlcy5vYmplY3QpIHtcbiAgICAgICAgY29uc3Qgbm90T2JqID0gKDAsIGNvZGVnZW5fMS5fKSBgdHlwZW9mICR7ZGF0YX0gIT0gXCJvYmplY3RcImA7XG4gICAgICAgIGNvbmQgPSB0eXBlcy5udWxsID8gbm90T2JqIDogKDAsIGNvZGVnZW5fMS5fKSBgISR7ZGF0YX0gfHwgJHtub3RPYmp9YDtcbiAgICAgICAgZGVsZXRlIHR5cGVzLm51bGw7XG4gICAgICAgIGRlbGV0ZSB0eXBlcy5hcnJheTtcbiAgICAgICAgZGVsZXRlIHR5cGVzLm9iamVjdDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGNvbmQgPSBjb2RlZ2VuXzEubmlsO1xuICAgIH1cbiAgICBpZiAodHlwZXMubnVtYmVyKVxuICAgICAgICBkZWxldGUgdHlwZXMuaW50ZWdlcjtcbiAgICBmb3IgKGNvbnN0IHQgaW4gdHlwZXMpXG4gICAgICAgIGNvbmQgPSAoMCwgY29kZWdlbl8xLmFuZCkoY29uZCwgY2hlY2tEYXRhVHlwZSh0LCBkYXRhLCBzdHJpY3ROdW1zLCBjb3JyZWN0KSk7XG4gICAgcmV0dXJuIGNvbmQ7XG59XG5leHBvcnRzLmNoZWNrRGF0YVR5cGVzID0gY2hlY2tEYXRhVHlwZXM7XG5jb25zdCB0eXBlRXJyb3IgPSB7XG4gICAgbWVzc2FnZTogKHsgc2NoZW1hIH0pID0+IGBtdXN0IGJlICR7c2NoZW1hfWAsXG4gICAgcGFyYW1zOiAoeyBzY2hlbWEsIHNjaGVtYVZhbHVlIH0pID0+IHR5cGVvZiBzY2hlbWEgPT0gXCJzdHJpbmdcIiA/ICgwLCBjb2RlZ2VuXzEuXykgYHt0eXBlOiAke3NjaGVtYX19YCA6ICgwLCBjb2RlZ2VuXzEuXykgYHt0eXBlOiAke3NjaGVtYVZhbHVlfX1gLFxufTtcbmZ1bmN0aW9uIHJlcG9ydFR5cGVFcnJvcihpdCkge1xuICAgIGNvbnN0IGN4dCA9IGdldFR5cGVFcnJvckNvbnRleHQoaXQpO1xuICAgICgwLCBlcnJvcnNfMS5yZXBvcnRFcnJvcikoY3h0LCB0eXBlRXJyb3IpO1xufVxuZXhwb3J0cy5yZXBvcnRUeXBlRXJyb3IgPSByZXBvcnRUeXBlRXJyb3I7XG5mdW5jdGlvbiBnZXRUeXBlRXJyb3JDb250ZXh0KGl0KSB7XG4gICAgY29uc3QgeyBnZW4sIGRhdGEsIHNjaGVtYSB9ID0gaXQ7XG4gICAgY29uc3Qgc2NoZW1hQ29kZSA9ICgwLCB1dGlsXzEuc2NoZW1hUmVmT3JWYWwpKGl0LCBzY2hlbWEsIFwidHlwZVwiKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBnZW4sXG4gICAgICAgIGtleXdvcmQ6IFwidHlwZVwiLFxuICAgICAgICBkYXRhLFxuICAgICAgICBzY2hlbWE6IHNjaGVtYS50eXBlLFxuICAgICAgICBzY2hlbWFDb2RlLFxuICAgICAgICBzY2hlbWFWYWx1ZTogc2NoZW1hQ29kZSxcbiAgICAgICAgcGFyZW50U2NoZW1hOiBzY2hlbWEsXG4gICAgICAgIHBhcmFtczoge30sXG4gICAgICAgIGl0LFxuICAgIH07XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhVHlwZS5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmV4cG9ydHMuYXNzaWduRGVmYXVsdHMgPSB2b2lkIDA7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vY29kZWdlblwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuLi91dGlsXCIpO1xuZnVuY3Rpb24gYXNzaWduRGVmYXVsdHMoaXQsIHR5KSB7XG4gICAgY29uc3QgeyBwcm9wZXJ0aWVzLCBpdGVtcyB9ID0gaXQuc2NoZW1hO1xuICAgIGlmICh0eSA9PT0gXCJvYmplY3RcIiAmJiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIGFzc2lnbkRlZmF1bHQoaXQsIGtleSwgcHJvcGVydGllc1trZXldLmRlZmF1bHQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5ID09PSBcImFycmF5XCIgJiYgQXJyYXkuaXNBcnJheShpdGVtcykpIHtcbiAgICAgICAgaXRlbXMuZm9yRWFjaCgoc2NoLCBpKSA9PiBhc3NpZ25EZWZhdWx0KGl0LCBpLCBzY2guZGVmYXVsdCkpO1xuICAgIH1cbn1cbmV4cG9ydHMuYXNzaWduRGVmYXVsdHMgPSBhc3NpZ25EZWZhdWx0cztcbmZ1bmN0aW9uIGFzc2lnbkRlZmF1bHQoaXQsIHByb3AsIGRlZmF1bHRWYWx1ZSkge1xuICAgIGNvbnN0IHsgZ2VuLCBjb21wb3NpdGVSdWxlLCBkYXRhLCBvcHRzIH0gPSBpdDtcbiAgICBpZiAoZGVmYXVsdFZhbHVlID09PSB1bmRlZmluZWQpXG4gICAgICAgIHJldHVybjtcbiAgICBjb25zdCBjaGlsZERhdGEgPSAoMCwgY29kZWdlbl8xLl8pIGAke2RhdGF9JHsoMCwgY29kZWdlbl8xLmdldFByb3BlcnR5KShwcm9wKX1gO1xuICAgIGlmIChjb21wb3NpdGVSdWxlKSB7XG4gICAgICAgICgwLCB1dGlsXzEuY2hlY2tTdHJpY3RNb2RlKShpdCwgYGRlZmF1bHQgaXMgaWdub3JlZCBmb3I6ICR7Y2hpbGREYXRhfWApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBjb25kaXRpb24gPSAoMCwgY29kZWdlbl8xLl8pIGAke2NoaWxkRGF0YX0gPT09IHVuZGVmaW5lZGA7XG4gICAgaWYgKG9wdHMudXNlRGVmYXVsdHMgPT09IFwiZW1wdHlcIikge1xuICAgICAgICBjb25kaXRpb24gPSAoMCwgY29kZWdlbl8xLl8pIGAke2NvbmRpdGlvbn0gfHwgJHtjaGlsZERhdGF9ID09PSBudWxsIHx8ICR7Y2hpbGREYXRhfSA9PT0gXCJcImA7XG4gICAgfVxuICAgIC8vIGAke2NoaWxkRGF0YX0gPT09IHVuZGVmaW5lZGAgK1xuICAgIC8vIChvcHRzLnVzZURlZmF1bHRzID09PSBcImVtcHR5XCIgPyBgIHx8ICR7Y2hpbGREYXRhfSA9PT0gbnVsbCB8fCAke2NoaWxkRGF0YX0gPT09IFwiXCJgIDogXCJcIilcbiAgICBnZW4uaWYoY29uZGl0aW9uLCAoMCwgY29kZWdlbl8xLl8pIGAke2NoaWxkRGF0YX0gPSAkeygwLCBjb2RlZ2VuXzEuc3RyaW5naWZ5KShkZWZhdWx0VmFsdWUpfWApO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGVmYXVsdHMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leHBvcnRzLmdldERhdGEgPSBleHBvcnRzLktleXdvcmRDeHQgPSBleHBvcnRzLnZhbGlkYXRlRnVuY3Rpb25Db2RlID0gdm9pZCAwO1xuY29uc3QgYm9vbFNjaGVtYV8xID0gcmVxdWlyZShcIi4vYm9vbFNjaGVtYVwiKTtcbmNvbnN0IGRhdGFUeXBlXzEgPSByZXF1aXJlKFwiLi9kYXRhVHlwZVwiKTtcbmNvbnN0IGFwcGxpY2FiaWxpdHlfMSA9IHJlcXVpcmUoXCIuL2FwcGxpY2FiaWxpdHlcIik7XG5jb25zdCBkYXRhVHlwZV8yID0gcmVxdWlyZShcIi4vZGF0YVR5cGVcIik7XG5jb25zdCBkZWZhdWx0c18xID0gcmVxdWlyZShcIi4vZGVmYXVsdHNcIik7XG5jb25zdCBrZXl3b3JkXzEgPSByZXF1aXJlKFwiLi9rZXl3b3JkXCIpO1xuY29uc3Qgc3Vic2NoZW1hXzEgPSByZXF1aXJlKFwiLi9zdWJzY2hlbWFcIik7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vY29kZWdlblwiKTtcbmNvbnN0IG5hbWVzXzEgPSByZXF1aXJlKFwiLi4vbmFtZXNcIik7XG5jb25zdCByZXNvbHZlXzEgPSByZXF1aXJlKFwiLi4vcmVzb2x2ZVwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuLi91dGlsXCIpO1xuY29uc3QgZXJyb3JzXzEgPSByZXF1aXJlKFwiLi4vZXJyb3JzXCIpO1xuLy8gc2NoZW1hIGNvbXBpbGF0aW9uIC0gZ2VuZXJhdGVzIHZhbGlkYXRpb24gZnVuY3Rpb24sIHN1YnNjaGVtYUNvZGUgKGJlbG93KSBpcyB1c2VkIGZvciBzdWJzY2hlbWFzXG5mdW5jdGlvbiB2YWxpZGF0ZUZ1bmN0aW9uQ29kZShpdCkge1xuICAgIGlmIChpc1NjaGVtYU9iaihpdCkpIHtcbiAgICAgICAgY2hlY2tLZXl3b3JkcyhpdCk7XG4gICAgICAgIGlmIChzY2hlbWFDeHRIYXNSdWxlcyhpdCkpIHtcbiAgICAgICAgICAgIHRvcFNjaGVtYU9iakNvZGUoaXQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuICAgIHZhbGlkYXRlRnVuY3Rpb24oaXQsICgpID0+ICgwLCBib29sU2NoZW1hXzEudG9wQm9vbE9yRW1wdHlTY2hlbWEpKGl0KSk7XG59XG5leHBvcnRzLnZhbGlkYXRlRnVuY3Rpb25Db2RlID0gdmFsaWRhdGVGdW5jdGlvbkNvZGU7XG5mdW5jdGlvbiB2YWxpZGF0ZUZ1bmN0aW9uKHsgZ2VuLCB2YWxpZGF0ZU5hbWUsIHNjaGVtYSwgc2NoZW1hRW52LCBvcHRzIH0sIGJvZHkpIHtcbiAgICBpZiAob3B0cy5jb2RlLmVzNSkge1xuICAgICAgICBnZW4uZnVuYyh2YWxpZGF0ZU5hbWUsICgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LmRhdGF9LCAke25hbWVzXzEuZGVmYXVsdC52YWxDeHR9YCwgc2NoZW1hRW52LiRhc3luYywgKCkgPT4ge1xuICAgICAgICAgICAgZ2VuLmNvZGUoKDAsIGNvZGVnZW5fMS5fKSBgXCJ1c2Ugc3RyaWN0XCI7ICR7ZnVuY1NvdXJjZVVybChzY2hlbWEsIG9wdHMpfWApO1xuICAgICAgICAgICAgZGVzdHJ1Y3R1cmVWYWxDeHRFUzUoZ2VuLCBvcHRzKTtcbiAgICAgICAgICAgIGdlbi5jb2RlKGJvZHkpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGdlbi5mdW5jKHZhbGlkYXRlTmFtZSwgKDAsIGNvZGVnZW5fMS5fKSBgJHtuYW1lc18xLmRlZmF1bHQuZGF0YX0sICR7ZGVzdHJ1Y3R1cmVWYWxDeHQob3B0cyl9YCwgc2NoZW1hRW52LiRhc3luYywgKCkgPT4gZ2VuLmNvZGUoZnVuY1NvdXJjZVVybChzY2hlbWEsIG9wdHMpKS5jb2RlKGJvZHkpKTtcbiAgICB9XG59XG5mdW5jdGlvbiBkZXN0cnVjdHVyZVZhbEN4dChvcHRzKSB7XG4gICAgcmV0dXJuICgwLCBjb2RlZ2VuXzEuXykgYHske25hbWVzXzEuZGVmYXVsdC5pbnN0YW5jZVBhdGh9PVwiXCIsICR7bmFtZXNfMS5kZWZhdWx0LnBhcmVudERhdGF9LCAke25hbWVzXzEuZGVmYXVsdC5wYXJlbnREYXRhUHJvcGVydHl9LCAke25hbWVzXzEuZGVmYXVsdC5yb290RGF0YX09JHtuYW1lc18xLmRlZmF1bHQuZGF0YX0ke29wdHMuZHluYW1pY1JlZiA/ICgwLCBjb2RlZ2VuXzEuXykgYCwgJHtuYW1lc18xLmRlZmF1bHQuZHluYW1pY0FuY2hvcnN9PXt9YCA6IGNvZGVnZW5fMS5uaWx9fT17fWA7XG59XG5mdW5jdGlvbiBkZXN0cnVjdHVyZVZhbEN4dEVTNShnZW4sIG9wdHMpIHtcbiAgICBnZW4uaWYobmFtZXNfMS5kZWZhdWx0LnZhbEN4dCwgKCkgPT4ge1xuICAgICAgICBnZW4udmFyKG5hbWVzXzEuZGVmYXVsdC5pbnN0YW5jZVBhdGgsICgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LnZhbEN4dH0uJHtuYW1lc18xLmRlZmF1bHQuaW5zdGFuY2VQYXRofWApO1xuICAgICAgICBnZW4udmFyKG5hbWVzXzEuZGVmYXVsdC5wYXJlbnREYXRhLCAoMCwgY29kZWdlbl8xLl8pIGAke25hbWVzXzEuZGVmYXVsdC52YWxDeHR9LiR7bmFtZXNfMS5kZWZhdWx0LnBhcmVudERhdGF9YCk7XG4gICAgICAgIGdlbi52YXIobmFtZXNfMS5kZWZhdWx0LnBhcmVudERhdGFQcm9wZXJ0eSwgKDAsIGNvZGVnZW5fMS5fKSBgJHtuYW1lc18xLmRlZmF1bHQudmFsQ3h0fS4ke25hbWVzXzEuZGVmYXVsdC5wYXJlbnREYXRhUHJvcGVydHl9YCk7XG4gICAgICAgIGdlbi52YXIobmFtZXNfMS5kZWZhdWx0LnJvb3REYXRhLCAoMCwgY29kZWdlbl8xLl8pIGAke25hbWVzXzEuZGVmYXVsdC52YWxDeHR9LiR7bmFtZXNfMS5kZWZhdWx0LnJvb3REYXRhfWApO1xuICAgICAgICBpZiAob3B0cy5keW5hbWljUmVmKVxuICAgICAgICAgICAgZ2VuLnZhcihuYW1lc18xLmRlZmF1bHQuZHluYW1pY0FuY2hvcnMsICgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LnZhbEN4dH0uJHtuYW1lc18xLmRlZmF1bHQuZHluYW1pY0FuY2hvcnN9YCk7XG4gICAgfSwgKCkgPT4ge1xuICAgICAgICBnZW4udmFyKG5hbWVzXzEuZGVmYXVsdC5pbnN0YW5jZVBhdGgsICgwLCBjb2RlZ2VuXzEuXykgYFwiXCJgKTtcbiAgICAgICAgZ2VuLnZhcihuYW1lc18xLmRlZmF1bHQucGFyZW50RGF0YSwgKDAsIGNvZGVnZW5fMS5fKSBgdW5kZWZpbmVkYCk7XG4gICAgICAgIGdlbi52YXIobmFtZXNfMS5kZWZhdWx0LnBhcmVudERhdGFQcm9wZXJ0eSwgKDAsIGNvZGVnZW5fMS5fKSBgdW5kZWZpbmVkYCk7XG4gICAgICAgIGdlbi52YXIobmFtZXNfMS5kZWZhdWx0LnJvb3REYXRhLCBuYW1lc18xLmRlZmF1bHQuZGF0YSk7XG4gICAgICAgIGlmIChvcHRzLmR5bmFtaWNSZWYpXG4gICAgICAgICAgICBnZW4udmFyKG5hbWVzXzEuZGVmYXVsdC5keW5hbWljQW5jaG9ycywgKDAsIGNvZGVnZW5fMS5fKSBge31gKTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIHRvcFNjaGVtYU9iakNvZGUoaXQpIHtcbiAgICBjb25zdCB7IHNjaGVtYSwgb3B0cywgZ2VuIH0gPSBpdDtcbiAgICB2YWxpZGF0ZUZ1bmN0aW9uKGl0LCAoKSA9PiB7XG4gICAgICAgIGlmIChvcHRzLiRjb21tZW50ICYmIHNjaGVtYS4kY29tbWVudClcbiAgICAgICAgICAgIGNvbW1lbnRLZXl3b3JkKGl0KTtcbiAgICAgICAgY2hlY2tOb0RlZmF1bHQoaXQpO1xuICAgICAgICBnZW4ubGV0KG5hbWVzXzEuZGVmYXVsdC52RXJyb3JzLCBudWxsKTtcbiAgICAgICAgZ2VuLmxldChuYW1lc18xLmRlZmF1bHQuZXJyb3JzLCAwKTtcbiAgICAgICAgaWYgKG9wdHMudW5ldmFsdWF0ZWQpXG4gICAgICAgICAgICByZXNldEV2YWx1YXRlZChpdCk7XG4gICAgICAgIHR5cGVBbmRLZXl3b3JkcyhpdCk7XG4gICAgICAgIHJldHVyblJlc3VsdHMoaXQpO1xuICAgIH0pO1xuICAgIHJldHVybjtcbn1cbmZ1bmN0aW9uIHJlc2V0RXZhbHVhdGVkKGl0KSB7XG4gICAgLy8gVE9ETyBtYXliZSBzb21lIGhvb2sgdG8gZXhlY3V0ZSBpdCBpbiB0aGUgZW5kIHRvIGNoZWNrIHdoZXRoZXIgcHJvcHMvaXRlbXMgYXJlIE5hbWUsIGFzIGluIGFzc2lnbkV2YWx1YXRlZFxuICAgIGNvbnN0IHsgZ2VuLCB2YWxpZGF0ZU5hbWUgfSA9IGl0O1xuICAgIGl0LmV2YWx1YXRlZCA9IGdlbi5jb25zdChcImV2YWx1YXRlZFwiLCAoMCwgY29kZWdlbl8xLl8pIGAke3ZhbGlkYXRlTmFtZX0uZXZhbHVhdGVkYCk7XG4gICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7aXQuZXZhbHVhdGVkfS5keW5hbWljUHJvcHNgLCAoKSA9PiBnZW4uYXNzaWduKCgwLCBjb2RlZ2VuXzEuXykgYCR7aXQuZXZhbHVhdGVkfS5wcm9wc2AsICgwLCBjb2RlZ2VuXzEuXykgYHVuZGVmaW5lZGApKTtcbiAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5fKSBgJHtpdC5ldmFsdWF0ZWR9LmR5bmFtaWNJdGVtc2AsICgpID0+IGdlbi5hc3NpZ24oKDAsIGNvZGVnZW5fMS5fKSBgJHtpdC5ldmFsdWF0ZWR9Lml0ZW1zYCwgKDAsIGNvZGVnZW5fMS5fKSBgdW5kZWZpbmVkYCkpO1xufVxuZnVuY3Rpb24gZnVuY1NvdXJjZVVybChzY2hlbWEsIG9wdHMpIHtcbiAgICBjb25zdCBzY2hJZCA9IHR5cGVvZiBzY2hlbWEgPT0gXCJvYmplY3RcIiAmJiBzY2hlbWFbb3B0cy5zY2hlbWFJZF07XG4gICAgcmV0dXJuIHNjaElkICYmIChvcHRzLmNvZGUuc291cmNlIHx8IG9wdHMuY29kZS5wcm9jZXNzKSA/ICgwLCBjb2RlZ2VuXzEuXykgYC8qIyBzb3VyY2VVUkw9JHtzY2hJZH0gKi9gIDogY29kZWdlbl8xLm5pbDtcbn1cbi8vIHNjaGVtYSBjb21waWxhdGlvbiAtIHRoaXMgZnVuY3Rpb24gaXMgdXNlZCByZWN1cnNpdmVseSB0byBnZW5lcmF0ZSBjb2RlIGZvciBzdWItc2NoZW1hc1xuZnVuY3Rpb24gc3Vic2NoZW1hQ29kZShpdCwgdmFsaWQpIHtcbiAgICBpZiAoaXNTY2hlbWFPYmooaXQpKSB7XG4gICAgICAgIGNoZWNrS2V5d29yZHMoaXQpO1xuICAgICAgICBpZiAoc2NoZW1hQ3h0SGFzUnVsZXMoaXQpKSB7XG4gICAgICAgICAgICBzdWJTY2hlbWFPYmpDb2RlKGl0LCB2YWxpZCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG4gICAgKDAsIGJvb2xTY2hlbWFfMS5ib29sT3JFbXB0eVNjaGVtYSkoaXQsIHZhbGlkKTtcbn1cbmZ1bmN0aW9uIHNjaGVtYUN4dEhhc1J1bGVzKHsgc2NoZW1hLCBzZWxmIH0pIHtcbiAgICBpZiAodHlwZW9mIHNjaGVtYSA9PSBcImJvb2xlYW5cIilcbiAgICAgICAgcmV0dXJuICFzY2hlbWE7XG4gICAgZm9yIChjb25zdCBrZXkgaW4gc2NoZW1hKVxuICAgICAgICBpZiAoc2VsZi5SVUxFUy5hbGxba2V5XSlcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIGlzU2NoZW1hT2JqKGl0KSB7XG4gICAgcmV0dXJuIHR5cGVvZiBpdC5zY2hlbWEgIT0gXCJib29sZWFuXCI7XG59XG5mdW5jdGlvbiBzdWJTY2hlbWFPYmpDb2RlKGl0LCB2YWxpZCkge1xuICAgIGNvbnN0IHsgc2NoZW1hLCBnZW4sIG9wdHMgfSA9IGl0O1xuICAgIGlmIChvcHRzLiRjb21tZW50ICYmIHNjaGVtYS4kY29tbWVudClcbiAgICAgICAgY29tbWVudEtleXdvcmQoaXQpO1xuICAgIHVwZGF0ZUNvbnRleHQoaXQpO1xuICAgIGNoZWNrQXN5bmNTY2hlbWEoaXQpO1xuICAgIGNvbnN0IGVycnNDb3VudCA9IGdlbi5jb25zdChcIl9lcnJzXCIsIG5hbWVzXzEuZGVmYXVsdC5lcnJvcnMpO1xuICAgIHR5cGVBbmRLZXl3b3JkcyhpdCwgZXJyc0NvdW50KTtcbiAgICAvLyBUT0RPIHZhclxuICAgIGdlbi52YXIodmFsaWQsICgwLCBjb2RlZ2VuXzEuXykgYCR7ZXJyc0NvdW50fSA9PT0gJHtuYW1lc18xLmRlZmF1bHQuZXJyb3JzfWApO1xufVxuZnVuY3Rpb24gY2hlY2tLZXl3b3JkcyhpdCkge1xuICAgICgwLCB1dGlsXzEuY2hlY2tVbmtub3duUnVsZXMpKGl0KTtcbiAgICBjaGVja1JlZnNBbmRLZXl3b3JkcyhpdCk7XG59XG5mdW5jdGlvbiB0eXBlQW5kS2V5d29yZHMoaXQsIGVycnNDb3VudCkge1xuICAgIGlmIChpdC5vcHRzLmp0ZClcbiAgICAgICAgcmV0dXJuIHNjaGVtYUtleXdvcmRzKGl0LCBbXSwgZmFsc2UsIGVycnNDb3VudCk7XG4gICAgY29uc3QgdHlwZXMgPSAoMCwgZGF0YVR5cGVfMS5nZXRTY2hlbWFUeXBlcykoaXQuc2NoZW1hKTtcbiAgICBjb25zdCBjaGVja2VkVHlwZXMgPSAoMCwgZGF0YVR5cGVfMS5jb2VyY2VBbmRDaGVja0RhdGFUeXBlKShpdCwgdHlwZXMpO1xuICAgIHNjaGVtYUtleXdvcmRzKGl0LCB0eXBlcywgIWNoZWNrZWRUeXBlcywgZXJyc0NvdW50KTtcbn1cbmZ1bmN0aW9uIGNoZWNrUmVmc0FuZEtleXdvcmRzKGl0KSB7XG4gICAgY29uc3QgeyBzY2hlbWEsIGVyclNjaGVtYVBhdGgsIG9wdHMsIHNlbGYgfSA9IGl0O1xuICAgIGlmIChzY2hlbWEuJHJlZiAmJiBvcHRzLmlnbm9yZUtleXdvcmRzV2l0aFJlZiAmJiAoMCwgdXRpbF8xLnNjaGVtYUhhc1J1bGVzQnV0UmVmKShzY2hlbWEsIHNlbGYuUlVMRVMpKSB7XG4gICAgICAgIHNlbGYubG9nZ2VyLndhcm4oYCRyZWY6IGtleXdvcmRzIGlnbm9yZWQgaW4gc2NoZW1hIGF0IHBhdGggXCIke2VyclNjaGVtYVBhdGh9XCJgKTtcbiAgICB9XG59XG5mdW5jdGlvbiBjaGVja05vRGVmYXVsdChpdCkge1xuICAgIGNvbnN0IHsgc2NoZW1hLCBvcHRzIH0gPSBpdDtcbiAgICBpZiAoc2NoZW1hLmRlZmF1bHQgIT09IHVuZGVmaW5lZCAmJiBvcHRzLnVzZURlZmF1bHRzICYmIG9wdHMuc3RyaWN0U2NoZW1hKSB7XG4gICAgICAgICgwLCB1dGlsXzEuY2hlY2tTdHJpY3RNb2RlKShpdCwgXCJkZWZhdWx0IGlzIGlnbm9yZWQgaW4gdGhlIHNjaGVtYSByb290XCIpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHVwZGF0ZUNvbnRleHQoaXQpIHtcbiAgICBjb25zdCBzY2hJZCA9IGl0LnNjaGVtYVtpdC5vcHRzLnNjaGVtYUlkXTtcbiAgICBpZiAoc2NoSWQpXG4gICAgICAgIGl0LmJhc2VJZCA9ICgwLCByZXNvbHZlXzEucmVzb2x2ZVVybCkoaXQub3B0cy51cmlSZXNvbHZlciwgaXQuYmFzZUlkLCBzY2hJZCk7XG59XG5mdW5jdGlvbiBjaGVja0FzeW5jU2NoZW1hKGl0KSB7XG4gICAgaWYgKGl0LnNjaGVtYS4kYXN5bmMgJiYgIWl0LnNjaGVtYUVudi4kYXN5bmMpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImFzeW5jIHNjaGVtYSBpbiBzeW5jIHNjaGVtYVwiKTtcbn1cbmZ1bmN0aW9uIGNvbW1lbnRLZXl3b3JkKHsgZ2VuLCBzY2hlbWFFbnYsIHNjaGVtYSwgZXJyU2NoZW1hUGF0aCwgb3B0cyB9KSB7XG4gICAgY29uc3QgbXNnID0gc2NoZW1hLiRjb21tZW50O1xuICAgIGlmIChvcHRzLiRjb21tZW50ID09PSB0cnVlKSB7XG4gICAgICAgIGdlbi5jb2RlKCgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LnNlbGZ9LmxvZ2dlci5sb2coJHttc2d9KWApO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2Ygb3B0cy4kY29tbWVudCA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgY29uc3Qgc2NoZW1hUGF0aCA9ICgwLCBjb2RlZ2VuXzEuc3RyKSBgJHtlcnJTY2hlbWFQYXRofS8kY29tbWVudGA7XG4gICAgICAgIGNvbnN0IHJvb3ROYW1lID0gZ2VuLnNjb3BlVmFsdWUoXCJyb290XCIsIHsgcmVmOiBzY2hlbWFFbnYucm9vdCB9KTtcbiAgICAgICAgZ2VuLmNvZGUoKDAsIGNvZGVnZW5fMS5fKSBgJHtuYW1lc18xLmRlZmF1bHQuc2VsZn0ub3B0cy4kY29tbWVudCgke21zZ30sICR7c2NoZW1hUGF0aH0sICR7cm9vdE5hbWV9LnNjaGVtYSlgKTtcbiAgICB9XG59XG5mdW5jdGlvbiByZXR1cm5SZXN1bHRzKGl0KSB7XG4gICAgY29uc3QgeyBnZW4sIHNjaGVtYUVudiwgdmFsaWRhdGVOYW1lLCBWYWxpZGF0aW9uRXJyb3IsIG9wdHMgfSA9IGl0O1xuICAgIGlmIChzY2hlbWFFbnYuJGFzeW5jKSB7XG4gICAgICAgIC8vIFRPRE8gYXNzaWduIHVuZXZhbHVhdGVkXG4gICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLl8pIGAke25hbWVzXzEuZGVmYXVsdC5lcnJvcnN9ID09PSAwYCwgKCkgPT4gZ2VuLnJldHVybihuYW1lc18xLmRlZmF1bHQuZGF0YSksICgpID0+IGdlbi50aHJvdygoMCwgY29kZWdlbl8xLl8pIGBuZXcgJHtWYWxpZGF0aW9uRXJyb3J9KCR7bmFtZXNfMS5kZWZhdWx0LnZFcnJvcnN9KWApKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGdlbi5hc3NpZ24oKDAsIGNvZGVnZW5fMS5fKSBgJHt2YWxpZGF0ZU5hbWV9LmVycm9yc2AsIG5hbWVzXzEuZGVmYXVsdC52RXJyb3JzKTtcbiAgICAgICAgaWYgKG9wdHMudW5ldmFsdWF0ZWQpXG4gICAgICAgICAgICBhc3NpZ25FdmFsdWF0ZWQoaXQpO1xuICAgICAgICBnZW4ucmV0dXJuKCgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LmVycm9yc30gPT09IDBgKTtcbiAgICB9XG59XG5mdW5jdGlvbiBhc3NpZ25FdmFsdWF0ZWQoeyBnZW4sIGV2YWx1YXRlZCwgcHJvcHMsIGl0ZW1zIH0pIHtcbiAgICBpZiAocHJvcHMgaW5zdGFuY2VvZiBjb2RlZ2VuXzEuTmFtZSlcbiAgICAgICAgZ2VuLmFzc2lnbigoMCwgY29kZWdlbl8xLl8pIGAke2V2YWx1YXRlZH0ucHJvcHNgLCBwcm9wcyk7XG4gICAgaWYgKGl0ZW1zIGluc3RhbmNlb2YgY29kZWdlbl8xLk5hbWUpXG4gICAgICAgIGdlbi5hc3NpZ24oKDAsIGNvZGVnZW5fMS5fKSBgJHtldmFsdWF0ZWR9Lml0ZW1zYCwgaXRlbXMpO1xufVxuZnVuY3Rpb24gc2NoZW1hS2V5d29yZHMoaXQsIHR5cGVzLCB0eXBlRXJyb3JzLCBlcnJzQ291bnQpIHtcbiAgICBjb25zdCB7IGdlbiwgc2NoZW1hLCBkYXRhLCBhbGxFcnJvcnMsIG9wdHMsIHNlbGYgfSA9IGl0O1xuICAgIGNvbnN0IHsgUlVMRVMgfSA9IHNlbGY7XG4gICAgaWYgKHNjaGVtYS4kcmVmICYmIChvcHRzLmlnbm9yZUtleXdvcmRzV2l0aFJlZiB8fCAhKDAsIHV0aWxfMS5zY2hlbWFIYXNSdWxlc0J1dFJlZikoc2NoZW1hLCBSVUxFUykpKSB7XG4gICAgICAgIGdlbi5ibG9jaygoKSA9PiBrZXl3b3JkQ29kZShpdCwgXCIkcmVmXCIsIFJVTEVTLmFsbC4kcmVmLmRlZmluaXRpb24pKTsgLy8gVE9ETyB0eXBlY2FzdFxuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghb3B0cy5qdGQpXG4gICAgICAgIGNoZWNrU3RyaWN0VHlwZXMoaXQsIHR5cGVzKTtcbiAgICBnZW4uYmxvY2soKCkgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IGdyb3VwIG9mIFJVTEVTLnJ1bGVzKVxuICAgICAgICAgICAgZ3JvdXBLZXl3b3Jkcyhncm91cCk7XG4gICAgICAgIGdyb3VwS2V5d29yZHMoUlVMRVMucG9zdCk7XG4gICAgfSk7XG4gICAgZnVuY3Rpb24gZ3JvdXBLZXl3b3Jkcyhncm91cCkge1xuICAgICAgICBpZiAoISgwLCBhcHBsaWNhYmlsaXR5XzEuc2hvdWxkVXNlR3JvdXApKHNjaGVtYSwgZ3JvdXApKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBpZiAoZ3JvdXAudHlwZSkge1xuICAgICAgICAgICAgZ2VuLmlmKCgwLCBkYXRhVHlwZV8yLmNoZWNrRGF0YVR5cGUpKGdyb3VwLnR5cGUsIGRhdGEsIG9wdHMuc3RyaWN0TnVtYmVycykpO1xuICAgICAgICAgICAgaXRlcmF0ZUtleXdvcmRzKGl0LCBncm91cCk7XG4gICAgICAgICAgICBpZiAodHlwZXMubGVuZ3RoID09PSAxICYmIHR5cGVzWzBdID09PSBncm91cC50eXBlICYmIHR5cGVFcnJvcnMpIHtcbiAgICAgICAgICAgICAgICBnZW4uZWxzZSgpO1xuICAgICAgICAgICAgICAgICgwLCBkYXRhVHlwZV8yLnJlcG9ydFR5cGVFcnJvcikoaXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ2VuLmVuZElmKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpdGVyYXRlS2V5d29yZHMoaXQsIGdyb3VwKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUT0RPIG1ha2UgaXQgXCJva1wiIGNhbGw/XG4gICAgICAgIGlmICghYWxsRXJyb3JzKVxuICAgICAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LmVycm9yc30gPT09ICR7ZXJyc0NvdW50IHx8IDB9YCk7XG4gICAgfVxufVxuZnVuY3Rpb24gaXRlcmF0ZUtleXdvcmRzKGl0LCBncm91cCkge1xuICAgIGNvbnN0IHsgZ2VuLCBzY2hlbWEsIG9wdHM6IHsgdXNlRGVmYXVsdHMgfSwgfSA9IGl0O1xuICAgIGlmICh1c2VEZWZhdWx0cylcbiAgICAgICAgKDAsIGRlZmF1bHRzXzEuYXNzaWduRGVmYXVsdHMpKGl0LCBncm91cC50eXBlKTtcbiAgICBnZW4uYmxvY2soKCkgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IHJ1bGUgb2YgZ3JvdXAucnVsZXMpIHtcbiAgICAgICAgICAgIGlmICgoMCwgYXBwbGljYWJpbGl0eV8xLnNob3VsZFVzZVJ1bGUpKHNjaGVtYSwgcnVsZSkpIHtcbiAgICAgICAgICAgICAgICBrZXl3b3JkQ29kZShpdCwgcnVsZS5rZXl3b3JkLCBydWxlLmRlZmluaXRpb24sIGdyb3VwLnR5cGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG59XG5mdW5jdGlvbiBjaGVja1N0cmljdFR5cGVzKGl0LCB0eXBlcykge1xuICAgIGlmIChpdC5zY2hlbWFFbnYubWV0YSB8fCAhaXQub3B0cy5zdHJpY3RUeXBlcylcbiAgICAgICAgcmV0dXJuO1xuICAgIGNoZWNrQ29udGV4dFR5cGVzKGl0LCB0eXBlcyk7XG4gICAgaWYgKCFpdC5vcHRzLmFsbG93VW5pb25UeXBlcylcbiAgICAgICAgY2hlY2tNdWx0aXBsZVR5cGVzKGl0LCB0eXBlcyk7XG4gICAgY2hlY2tLZXl3b3JkVHlwZXMoaXQsIGl0LmRhdGFUeXBlcyk7XG59XG5mdW5jdGlvbiBjaGVja0NvbnRleHRUeXBlcyhpdCwgdHlwZXMpIHtcbiAgICBpZiAoIXR5cGVzLmxlbmd0aClcbiAgICAgICAgcmV0dXJuO1xuICAgIGlmICghaXQuZGF0YVR5cGVzLmxlbmd0aCkge1xuICAgICAgICBpdC5kYXRhVHlwZXMgPSB0eXBlcztcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0eXBlcy5mb3JFYWNoKCh0KSA9PiB7XG4gICAgICAgIGlmICghaW5jbHVkZXNUeXBlKGl0LmRhdGFUeXBlcywgdCkpIHtcbiAgICAgICAgICAgIHN0cmljdFR5cGVzRXJyb3IoaXQsIGB0eXBlIFwiJHt0fVwiIG5vdCBhbGxvd2VkIGJ5IGNvbnRleHQgXCIke2l0LmRhdGFUeXBlcy5qb2luKFwiLFwiKX1cImApO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgbmFycm93U2NoZW1hVHlwZXMoaXQsIHR5cGVzKTtcbn1cbmZ1bmN0aW9uIGNoZWNrTXVsdGlwbGVUeXBlcyhpdCwgdHMpIHtcbiAgICBpZiAodHMubGVuZ3RoID4gMSAmJiAhKHRzLmxlbmd0aCA9PT0gMiAmJiB0cy5pbmNsdWRlcyhcIm51bGxcIikpKSB7XG4gICAgICAgIHN0cmljdFR5cGVzRXJyb3IoaXQsIFwidXNlIGFsbG93VW5pb25UeXBlcyB0byBhbGxvdyB1bmlvbiB0eXBlIGtleXdvcmRcIik7XG4gICAgfVxufVxuZnVuY3Rpb24gY2hlY2tLZXl3b3JkVHlwZXMoaXQsIHRzKSB7XG4gICAgY29uc3QgcnVsZXMgPSBpdC5zZWxmLlJVTEVTLmFsbDtcbiAgICBmb3IgKGNvbnN0IGtleXdvcmQgaW4gcnVsZXMpIHtcbiAgICAgICAgY29uc3QgcnVsZSA9IHJ1bGVzW2tleXdvcmRdO1xuICAgICAgICBpZiAodHlwZW9mIHJ1bGUgPT0gXCJvYmplY3RcIiAmJiAoMCwgYXBwbGljYWJpbGl0eV8xLnNob3VsZFVzZVJ1bGUpKGl0LnNjaGVtYSwgcnVsZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgdHlwZSB9ID0gcnVsZS5kZWZpbml0aW9uO1xuICAgICAgICAgICAgaWYgKHR5cGUubGVuZ3RoICYmICF0eXBlLnNvbWUoKHQpID0+IGhhc0FwcGxpY2FibGVUeXBlKHRzLCB0KSkpIHtcbiAgICAgICAgICAgICAgICBzdHJpY3RUeXBlc0Vycm9yKGl0LCBgbWlzc2luZyB0eXBlIFwiJHt0eXBlLmpvaW4oXCIsXCIpfVwiIGZvciBrZXl3b3JkIFwiJHtrZXl3b3JkfVwiYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiBoYXNBcHBsaWNhYmxlVHlwZShzY2hUcywga3dkVCkge1xuICAgIHJldHVybiBzY2hUcy5pbmNsdWRlcyhrd2RUKSB8fCAoa3dkVCA9PT0gXCJudW1iZXJcIiAmJiBzY2hUcy5pbmNsdWRlcyhcImludGVnZXJcIikpO1xufVxuZnVuY3Rpb24gaW5jbHVkZXNUeXBlKHRzLCB0KSB7XG4gICAgcmV0dXJuIHRzLmluY2x1ZGVzKHQpIHx8ICh0ID09PSBcImludGVnZXJcIiAmJiB0cy5pbmNsdWRlcyhcIm51bWJlclwiKSk7XG59XG5mdW5jdGlvbiBuYXJyb3dTY2hlbWFUeXBlcyhpdCwgd2l0aFR5cGVzKSB7XG4gICAgY29uc3QgdHMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IHQgb2YgaXQuZGF0YVR5cGVzKSB7XG4gICAgICAgIGlmIChpbmNsdWRlc1R5cGUod2l0aFR5cGVzLCB0KSlcbiAgICAgICAgICAgIHRzLnB1c2godCk7XG4gICAgICAgIGVsc2UgaWYgKHdpdGhUeXBlcy5pbmNsdWRlcyhcImludGVnZXJcIikgJiYgdCA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgIHRzLnB1c2goXCJpbnRlZ2VyXCIpO1xuICAgIH1cbiAgICBpdC5kYXRhVHlwZXMgPSB0cztcbn1cbmZ1bmN0aW9uIHN0cmljdFR5cGVzRXJyb3IoaXQsIG1zZykge1xuICAgIGNvbnN0IHNjaGVtYVBhdGggPSBpdC5zY2hlbWFFbnYuYmFzZUlkICsgaXQuZXJyU2NoZW1hUGF0aDtcbiAgICBtc2cgKz0gYCBhdCBcIiR7c2NoZW1hUGF0aH1cIiAoc3RyaWN0VHlwZXMpYDtcbiAgICAoMCwgdXRpbF8xLmNoZWNrU3RyaWN0TW9kZSkoaXQsIG1zZywgaXQub3B0cy5zdHJpY3RUeXBlcyk7XG59XG5jbGFzcyBLZXl3b3JkQ3h0IHtcbiAgICBjb25zdHJ1Y3RvcihpdCwgZGVmLCBrZXl3b3JkKSB7XG4gICAgICAgICgwLCBrZXl3b3JkXzEudmFsaWRhdGVLZXl3b3JkVXNhZ2UpKGl0LCBkZWYsIGtleXdvcmQpO1xuICAgICAgICB0aGlzLmdlbiA9IGl0LmdlbjtcbiAgICAgICAgdGhpcy5hbGxFcnJvcnMgPSBpdC5hbGxFcnJvcnM7XG4gICAgICAgIHRoaXMua2V5d29yZCA9IGtleXdvcmQ7XG4gICAgICAgIHRoaXMuZGF0YSA9IGl0LmRhdGE7XG4gICAgICAgIHRoaXMuc2NoZW1hID0gaXQuc2NoZW1hW2tleXdvcmRdO1xuICAgICAgICB0aGlzLiRkYXRhID0gZGVmLiRkYXRhICYmIGl0Lm9wdHMuJGRhdGEgJiYgdGhpcy5zY2hlbWEgJiYgdGhpcy5zY2hlbWEuJGRhdGE7XG4gICAgICAgIHRoaXMuc2NoZW1hVmFsdWUgPSAoMCwgdXRpbF8xLnNjaGVtYVJlZk9yVmFsKShpdCwgdGhpcy5zY2hlbWEsIGtleXdvcmQsIHRoaXMuJGRhdGEpO1xuICAgICAgICB0aGlzLnNjaGVtYVR5cGUgPSBkZWYuc2NoZW1hVHlwZTtcbiAgICAgICAgdGhpcy5wYXJlbnRTY2hlbWEgPSBpdC5zY2hlbWE7XG4gICAgICAgIHRoaXMucGFyYW1zID0ge307XG4gICAgICAgIHRoaXMuaXQgPSBpdDtcbiAgICAgICAgdGhpcy5kZWYgPSBkZWY7XG4gICAgICAgIGlmICh0aGlzLiRkYXRhKSB7XG4gICAgICAgICAgICB0aGlzLnNjaGVtYUNvZGUgPSBpdC5nZW4uY29uc3QoXCJ2U2NoZW1hXCIsIGdldERhdGEodGhpcy4kZGF0YSwgaXQpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc2NoZW1hQ29kZSA9IHRoaXMuc2NoZW1hVmFsdWU7XG4gICAgICAgICAgICBpZiAoISgwLCBrZXl3b3JkXzEudmFsaWRTY2hlbWFUeXBlKSh0aGlzLnNjaGVtYSwgZGVmLnNjaGVtYVR5cGUsIGRlZi5hbGxvd1VuZGVmaW5lZCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7a2V5d29yZH0gdmFsdWUgbXVzdCBiZSAke0pTT04uc3RyaW5naWZ5KGRlZi5zY2hlbWFUeXBlKX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoXCJjb2RlXCIgaW4gZGVmID8gZGVmLnRyYWNrRXJyb3JzIDogZGVmLmVycm9ycyAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHRoaXMuZXJyc0NvdW50ID0gaXQuZ2VuLmNvbnN0KFwiX2VycnNcIiwgbmFtZXNfMS5kZWZhdWx0LmVycm9ycyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmVzdWx0KGNvbmRpdGlvbiwgc3VjY2Vzc0FjdGlvbiwgZmFpbEFjdGlvbikge1xuICAgICAgICB0aGlzLmZhaWxSZXN1bHQoKDAsIGNvZGVnZW5fMS5ub3QpKGNvbmRpdGlvbiksIHN1Y2Nlc3NBY3Rpb24sIGZhaWxBY3Rpb24pO1xuICAgIH1cbiAgICBmYWlsUmVzdWx0KGNvbmRpdGlvbiwgc3VjY2Vzc0FjdGlvbiwgZmFpbEFjdGlvbikge1xuICAgICAgICB0aGlzLmdlbi5pZihjb25kaXRpb24pO1xuICAgICAgICBpZiAoZmFpbEFjdGlvbilcbiAgICAgICAgICAgIGZhaWxBY3Rpb24oKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhpcy5lcnJvcigpO1xuICAgICAgICBpZiAoc3VjY2Vzc0FjdGlvbikge1xuICAgICAgICAgICAgdGhpcy5nZW4uZWxzZSgpO1xuICAgICAgICAgICAgc3VjY2Vzc0FjdGlvbigpO1xuICAgICAgICAgICAgaWYgKHRoaXMuYWxsRXJyb3JzKVxuICAgICAgICAgICAgICAgIHRoaXMuZ2VuLmVuZElmKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hbGxFcnJvcnMpXG4gICAgICAgICAgICAgICAgdGhpcy5nZW4uZW5kSWYoKTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0aGlzLmdlbi5lbHNlKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcGFzcyhjb25kaXRpb24sIGZhaWxBY3Rpb24pIHtcbiAgICAgICAgdGhpcy5mYWlsUmVzdWx0KCgwLCBjb2RlZ2VuXzEubm90KShjb25kaXRpb24pLCB1bmRlZmluZWQsIGZhaWxBY3Rpb24pO1xuICAgIH1cbiAgICBmYWlsKGNvbmRpdGlvbikge1xuICAgICAgICBpZiAoY29uZGl0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZXJyb3IoKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5hbGxFcnJvcnMpXG4gICAgICAgICAgICAgICAgdGhpcy5nZW4uaWYoZmFsc2UpOyAvLyB0aGlzIGJyYW5jaCB3aWxsIGJlIHJlbW92ZWQgYnkgZ2VuLm9wdGltaXplXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5nZW4uaWYoY29uZGl0aW9uKTtcbiAgICAgICAgdGhpcy5lcnJvcigpO1xuICAgICAgICBpZiAodGhpcy5hbGxFcnJvcnMpXG4gICAgICAgICAgICB0aGlzLmdlbi5lbmRJZigpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aGlzLmdlbi5lbHNlKCk7XG4gICAgfVxuICAgIGZhaWwkZGF0YShjb25kaXRpb24pIHtcbiAgICAgICAgaWYgKCF0aGlzLiRkYXRhKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmFpbChjb25kaXRpb24pO1xuICAgICAgICBjb25zdCB7IHNjaGVtYUNvZGUgfSA9IHRoaXM7XG4gICAgICAgIHRoaXMuZmFpbCgoMCwgY29kZWdlbl8xLl8pIGAke3NjaGVtYUNvZGV9ICE9PSB1bmRlZmluZWQgJiYgKCR7KDAsIGNvZGVnZW5fMS5vcikodGhpcy5pbnZhbGlkJGRhdGEoKSwgY29uZGl0aW9uKX0pYCk7XG4gICAgfVxuICAgIGVycm9yKGFwcGVuZCwgZXJyb3JQYXJhbXMsIGVycm9yUGF0aHMpIHtcbiAgICAgICAgaWYgKGVycm9yUGFyYW1zKSB7XG4gICAgICAgICAgICB0aGlzLnNldFBhcmFtcyhlcnJvclBhcmFtcyk7XG4gICAgICAgICAgICB0aGlzLl9lcnJvcihhcHBlbmQsIGVycm9yUGF0aHMpO1xuICAgICAgICAgICAgdGhpcy5zZXRQYXJhbXMoe30pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2Vycm9yKGFwcGVuZCwgZXJyb3JQYXRocyk7XG4gICAgfVxuICAgIF9lcnJvcihhcHBlbmQsIGVycm9yUGF0aHMpIHtcbiAgICAgICAgO1xuICAgICAgICAoYXBwZW5kID8gZXJyb3JzXzEucmVwb3J0RXh0cmFFcnJvciA6IGVycm9yc18xLnJlcG9ydEVycm9yKSh0aGlzLCB0aGlzLmRlZi5lcnJvciwgZXJyb3JQYXRocyk7XG4gICAgfVxuICAgICRkYXRhRXJyb3IoKSB7XG4gICAgICAgICgwLCBlcnJvcnNfMS5yZXBvcnRFcnJvcikodGhpcywgdGhpcy5kZWYuJGRhdGFFcnJvciB8fCBlcnJvcnNfMS5rZXl3b3JkJERhdGFFcnJvcik7XG4gICAgfVxuICAgIHJlc2V0KCkge1xuICAgICAgICBpZiAodGhpcy5lcnJzQ291bnQgPT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignYWRkIFwidHJhY2tFcnJvcnNcIiB0byBrZXl3b3JkIGRlZmluaXRpb24nKTtcbiAgICAgICAgKDAsIGVycm9yc18xLnJlc2V0RXJyb3JzQ291bnQpKHRoaXMuZ2VuLCB0aGlzLmVycnNDb3VudCk7XG4gICAgfVxuICAgIG9rKGNvbmQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmFsbEVycm9ycylcbiAgICAgICAgICAgIHRoaXMuZ2VuLmlmKGNvbmQpO1xuICAgIH1cbiAgICBzZXRQYXJhbXMob2JqLCBhc3NpZ24pIHtcbiAgICAgICAgaWYgKGFzc2lnbilcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odGhpcy5wYXJhbXMsIG9iaik7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRoaXMucGFyYW1zID0gb2JqO1xuICAgIH1cbiAgICBibG9jayRkYXRhKHZhbGlkLCBjb2RlQmxvY2ssICRkYXRhVmFsaWQgPSBjb2RlZ2VuXzEubmlsKSB7XG4gICAgICAgIHRoaXMuZ2VuLmJsb2NrKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuY2hlY2skZGF0YSh2YWxpZCwgJGRhdGFWYWxpZCk7XG4gICAgICAgICAgICBjb2RlQmxvY2soKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGNoZWNrJGRhdGEodmFsaWQgPSBjb2RlZ2VuXzEubmlsLCAkZGF0YVZhbGlkID0gY29kZWdlbl8xLm5pbCkge1xuICAgICAgICBpZiAoIXRoaXMuJGRhdGEpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IHsgZ2VuLCBzY2hlbWFDb2RlLCBzY2hlbWFUeXBlLCBkZWYgfSA9IHRoaXM7XG4gICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLm9yKSgoMCwgY29kZWdlbl8xLl8pIGAke3NjaGVtYUNvZGV9ID09PSB1bmRlZmluZWRgLCAkZGF0YVZhbGlkKSk7XG4gICAgICAgIGlmICh2YWxpZCAhPT0gY29kZWdlbl8xLm5pbClcbiAgICAgICAgICAgIGdlbi5hc3NpZ24odmFsaWQsIHRydWUpO1xuICAgICAgICBpZiAoc2NoZW1hVHlwZS5sZW5ndGggfHwgZGVmLnZhbGlkYXRlU2NoZW1hKSB7XG4gICAgICAgICAgICBnZW4uZWxzZUlmKHRoaXMuaW52YWxpZCRkYXRhKCkpO1xuICAgICAgICAgICAgdGhpcy4kZGF0YUVycm9yKCk7XG4gICAgICAgICAgICBpZiAodmFsaWQgIT09IGNvZGVnZW5fMS5uaWwpXG4gICAgICAgICAgICAgICAgZ2VuLmFzc2lnbih2YWxpZCwgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIGdlbi5lbHNlKCk7XG4gICAgfVxuICAgIGludmFsaWQkZGF0YSgpIHtcbiAgICAgICAgY29uc3QgeyBnZW4sIHNjaGVtYUNvZGUsIHNjaGVtYVR5cGUsIGRlZiwgaXQgfSA9IHRoaXM7XG4gICAgICAgIHJldHVybiAoMCwgY29kZWdlbl8xLm9yKSh3cm9uZyREYXRhVHlwZSgpLCBpbnZhbGlkJERhdGFTY2hlbWEoKSk7XG4gICAgICAgIGZ1bmN0aW9uIHdyb25nJERhdGFUeXBlKCkge1xuICAgICAgICAgICAgaWYgKHNjaGVtYVR5cGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgICAgICAgICAgaWYgKCEoc2NoZW1hQ29kZSBpbnN0YW5jZW9mIGNvZGVnZW5fMS5OYW1lKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYWp2IGltcGxlbWVudGF0aW9uIGVycm9yXCIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ID0gQXJyYXkuaXNBcnJheShzY2hlbWFUeXBlKSA/IHNjaGVtYVR5cGUgOiBbc2NoZW1hVHlwZV07XG4gICAgICAgICAgICAgICAgcmV0dXJuICgwLCBjb2RlZ2VuXzEuXykgYCR7KDAsIGRhdGFUeXBlXzIuY2hlY2tEYXRhVHlwZXMpKHN0LCBzY2hlbWFDb2RlLCBpdC5vcHRzLnN0cmljdE51bWJlcnMsIGRhdGFUeXBlXzIuRGF0YVR5cGUuV3JvbmcpfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29kZWdlbl8xLm5pbDtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBpbnZhbGlkJERhdGFTY2hlbWEoKSB7XG4gICAgICAgICAgICBpZiAoZGVmLnZhbGlkYXRlU2NoZW1hKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsaWRhdGVTY2hlbWFSZWYgPSBnZW4uc2NvcGVWYWx1ZShcInZhbGlkYXRlJGRhdGFcIiwgeyByZWY6IGRlZi52YWxpZGF0ZVNjaGVtYSB9KTsgLy8gVE9ETyB2YWx1ZS5jb2RlIGZvciBzdGFuZGFsb25lXG4gICAgICAgICAgICAgICAgcmV0dXJuICgwLCBjb2RlZ2VuXzEuXykgYCEke3ZhbGlkYXRlU2NoZW1hUmVmfSgke3NjaGVtYUNvZGV9KWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29kZWdlbl8xLm5pbDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBzdWJzY2hlbWEoYXBwbCwgdmFsaWQpIHtcbiAgICAgICAgY29uc3Qgc3Vic2NoZW1hID0gKDAsIHN1YnNjaGVtYV8xLmdldFN1YnNjaGVtYSkodGhpcy5pdCwgYXBwbCk7XG4gICAgICAgICgwLCBzdWJzY2hlbWFfMS5leHRlbmRTdWJzY2hlbWFEYXRhKShzdWJzY2hlbWEsIHRoaXMuaXQsIGFwcGwpO1xuICAgICAgICAoMCwgc3Vic2NoZW1hXzEuZXh0ZW5kU3Vic2NoZW1hTW9kZSkoc3Vic2NoZW1hLCBhcHBsKTtcbiAgICAgICAgY29uc3QgbmV4dENvbnRleHQgPSB7IC4uLnRoaXMuaXQsIC4uLnN1YnNjaGVtYSwgaXRlbXM6IHVuZGVmaW5lZCwgcHJvcHM6IHVuZGVmaW5lZCB9O1xuICAgICAgICBzdWJzY2hlbWFDb2RlKG5leHRDb250ZXh0LCB2YWxpZCk7XG4gICAgICAgIHJldHVybiBuZXh0Q29udGV4dDtcbiAgICB9XG4gICAgbWVyZ2VFdmFsdWF0ZWQoc2NoZW1hQ3h0LCB0b05hbWUpIHtcbiAgICAgICAgY29uc3QgeyBpdCwgZ2VuIH0gPSB0aGlzO1xuICAgICAgICBpZiAoIWl0Lm9wdHMudW5ldmFsdWF0ZWQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmIChpdC5wcm9wcyAhPT0gdHJ1ZSAmJiBzY2hlbWFDeHQucHJvcHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaXQucHJvcHMgPSB1dGlsXzEubWVyZ2VFdmFsdWF0ZWQucHJvcHMoZ2VuLCBzY2hlbWFDeHQucHJvcHMsIGl0LnByb3BzLCB0b05hbWUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpdC5pdGVtcyAhPT0gdHJ1ZSAmJiBzY2hlbWFDeHQuaXRlbXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaXQuaXRlbXMgPSB1dGlsXzEubWVyZ2VFdmFsdWF0ZWQuaXRlbXMoZ2VuLCBzY2hlbWFDeHQuaXRlbXMsIGl0Lml0ZW1zLCB0b05hbWUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIG1lcmdlVmFsaWRFdmFsdWF0ZWQoc2NoZW1hQ3h0LCB2YWxpZCkge1xuICAgICAgICBjb25zdCB7IGl0LCBnZW4gfSA9IHRoaXM7XG4gICAgICAgIGlmIChpdC5vcHRzLnVuZXZhbHVhdGVkICYmIChpdC5wcm9wcyAhPT0gdHJ1ZSB8fCBpdC5pdGVtcyAhPT0gdHJ1ZSkpIHtcbiAgICAgICAgICAgIGdlbi5pZih2YWxpZCwgKCkgPT4gdGhpcy5tZXJnZUV2YWx1YXRlZChzY2hlbWFDeHQsIGNvZGVnZW5fMS5OYW1lKSk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbn1cbmV4cG9ydHMuS2V5d29yZEN4dCA9IEtleXdvcmRDeHQ7XG5mdW5jdGlvbiBrZXl3b3JkQ29kZShpdCwga2V5d29yZCwgZGVmLCBydWxlVHlwZSkge1xuICAgIGNvbnN0IGN4dCA9IG5ldyBLZXl3b3JkQ3h0KGl0LCBkZWYsIGtleXdvcmQpO1xuICAgIGlmIChcImNvZGVcIiBpbiBkZWYpIHtcbiAgICAgICAgZGVmLmNvZGUoY3h0LCBydWxlVHlwZSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGN4dC4kZGF0YSAmJiBkZWYudmFsaWRhdGUpIHtcbiAgICAgICAgKDAsIGtleXdvcmRfMS5mdW5jS2V5d29yZENvZGUpKGN4dCwgZGVmKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoXCJtYWNyb1wiIGluIGRlZikge1xuICAgICAgICAoMCwga2V5d29yZF8xLm1hY3JvS2V5d29yZENvZGUpKGN4dCwgZGVmKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZGVmLmNvbXBpbGUgfHwgZGVmLnZhbGlkYXRlKSB7XG4gICAgICAgICgwLCBrZXl3b3JkXzEuZnVuY0tleXdvcmRDb2RlKShjeHQsIGRlZik7XG4gICAgfVxufVxuY29uc3QgSlNPTl9QT0lOVEVSID0gL15cXC8oPzpbXn5dfH4wfH4xKSokLztcbmNvbnN0IFJFTEFUSVZFX0pTT05fUE9JTlRFUiA9IC9eKFswLTldKykoI3xcXC8oPzpbXn5dfH4wfH4xKSopPyQvO1xuZnVuY3Rpb24gZ2V0RGF0YSgkZGF0YSwgeyBkYXRhTGV2ZWwsIGRhdGFOYW1lcywgZGF0YVBhdGhBcnIgfSkge1xuICAgIGxldCBqc29uUG9pbnRlcjtcbiAgICBsZXQgZGF0YTtcbiAgICBpZiAoJGRhdGEgPT09IFwiXCIpXG4gICAgICAgIHJldHVybiBuYW1lc18xLmRlZmF1bHQucm9vdERhdGE7XG4gICAgaWYgKCRkYXRhWzBdID09PSBcIi9cIikge1xuICAgICAgICBpZiAoIUpTT05fUE9JTlRFUi50ZXN0KCRkYXRhKSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBKU09OLXBvaW50ZXI6ICR7JGRhdGF9YCk7XG4gICAgICAgIGpzb25Qb2ludGVyID0gJGRhdGE7XG4gICAgICAgIGRhdGEgPSBuYW1lc18xLmRlZmF1bHQucm9vdERhdGE7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBjb25zdCBtYXRjaGVzID0gUkVMQVRJVkVfSlNPTl9QT0lOVEVSLmV4ZWMoJGRhdGEpO1xuICAgICAgICBpZiAoIW1hdGNoZXMpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgSlNPTi1wb2ludGVyOiAkeyRkYXRhfWApO1xuICAgICAgICBjb25zdCB1cCA9ICttYXRjaGVzWzFdO1xuICAgICAgICBqc29uUG9pbnRlciA9IG1hdGNoZXNbMl07XG4gICAgICAgIGlmIChqc29uUG9pbnRlciA9PT0gXCIjXCIpIHtcbiAgICAgICAgICAgIGlmICh1cCA+PSBkYXRhTGV2ZWwpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yTXNnKFwicHJvcGVydHkvaW5kZXhcIiwgdXApKTtcbiAgICAgICAgICAgIHJldHVybiBkYXRhUGF0aEFycltkYXRhTGV2ZWwgLSB1cF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHVwID4gZGF0YUxldmVsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yTXNnKFwiZGF0YVwiLCB1cCkpO1xuICAgICAgICBkYXRhID0gZGF0YU5hbWVzW2RhdGFMZXZlbCAtIHVwXTtcbiAgICAgICAgaWYgKCFqc29uUG9pbnRlcilcbiAgICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbiAgICBsZXQgZXhwciA9IGRhdGE7XG4gICAgY29uc3Qgc2VnbWVudHMgPSBqc29uUG9pbnRlci5zcGxpdChcIi9cIik7XG4gICAgZm9yIChjb25zdCBzZWdtZW50IG9mIHNlZ21lbnRzKSB7XG4gICAgICAgIGlmIChzZWdtZW50KSB7XG4gICAgICAgICAgICBkYXRhID0gKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhfSR7KDAsIGNvZGVnZW5fMS5nZXRQcm9wZXJ0eSkoKDAsIHV0aWxfMS51bmVzY2FwZUpzb25Qb2ludGVyKShzZWdtZW50KSl9YDtcbiAgICAgICAgICAgIGV4cHIgPSAoMCwgY29kZWdlbl8xLl8pIGAke2V4cHJ9ICYmICR7ZGF0YX1gO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBleHByO1xuICAgIGZ1bmN0aW9uIGVycm9yTXNnKHBvaW50ZXJUeXBlLCB1cCkge1xuICAgICAgICByZXR1cm4gYENhbm5vdCBhY2Nlc3MgJHtwb2ludGVyVHlwZX0gJHt1cH0gbGV2ZWxzIHVwLCBjdXJyZW50IGxldmVsIGlzICR7ZGF0YUxldmVsfWA7XG4gICAgfVxufVxuZXhwb3J0cy5nZXREYXRhID0gZ2V0RGF0YTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWluZGV4LmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXhwb3J0cy52YWxpZGF0ZUtleXdvcmRVc2FnZSA9IGV4cG9ydHMudmFsaWRTY2hlbWFUeXBlID0gZXhwb3J0cy5mdW5jS2V5d29yZENvZGUgPSBleHBvcnRzLm1hY3JvS2V5d29yZENvZGUgPSB2b2lkIDA7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vY29kZWdlblwiKTtcbmNvbnN0IG5hbWVzXzEgPSByZXF1aXJlKFwiLi4vbmFtZXNcIik7XG5jb25zdCBjb2RlXzEgPSByZXF1aXJlKFwiLi4vLi4vdm9jYWJ1bGFyaWVzL2NvZGVcIik7XG5jb25zdCBlcnJvcnNfMSA9IHJlcXVpcmUoXCIuLi9lcnJvcnNcIik7XG5mdW5jdGlvbiBtYWNyb0tleXdvcmRDb2RlKGN4dCwgZGVmKSB7XG4gICAgY29uc3QgeyBnZW4sIGtleXdvcmQsIHNjaGVtYSwgcGFyZW50U2NoZW1hLCBpdCB9ID0gY3h0O1xuICAgIGNvbnN0IG1hY3JvU2NoZW1hID0gZGVmLm1hY3JvLmNhbGwoaXQuc2VsZiwgc2NoZW1hLCBwYXJlbnRTY2hlbWEsIGl0KTtcbiAgICBjb25zdCBzY2hlbWFSZWYgPSB1c2VLZXl3b3JkKGdlbiwga2V5d29yZCwgbWFjcm9TY2hlbWEpO1xuICAgIGlmIChpdC5vcHRzLnZhbGlkYXRlU2NoZW1hICE9PSBmYWxzZSlcbiAgICAgICAgaXQuc2VsZi52YWxpZGF0ZVNjaGVtYShtYWNyb1NjaGVtYSwgdHJ1ZSk7XG4gICAgY29uc3QgdmFsaWQgPSBnZW4ubmFtZShcInZhbGlkXCIpO1xuICAgIGN4dC5zdWJzY2hlbWEoe1xuICAgICAgICBzY2hlbWE6IG1hY3JvU2NoZW1hLFxuICAgICAgICBzY2hlbWFQYXRoOiBjb2RlZ2VuXzEubmlsLFxuICAgICAgICBlcnJTY2hlbWFQYXRoOiBgJHtpdC5lcnJTY2hlbWFQYXRofS8ke2tleXdvcmR9YCxcbiAgICAgICAgdG9wU2NoZW1hUmVmOiBzY2hlbWFSZWYsXG4gICAgICAgIGNvbXBvc2l0ZVJ1bGU6IHRydWUsXG4gICAgfSwgdmFsaWQpO1xuICAgIGN4dC5wYXNzKHZhbGlkLCAoKSA9PiBjeHQuZXJyb3IodHJ1ZSkpO1xufVxuZXhwb3J0cy5tYWNyb0tleXdvcmRDb2RlID0gbWFjcm9LZXl3b3JkQ29kZTtcbmZ1bmN0aW9uIGZ1bmNLZXl3b3JkQ29kZShjeHQsIGRlZikge1xuICAgIHZhciBfYTtcbiAgICBjb25zdCB7IGdlbiwga2V5d29yZCwgc2NoZW1hLCBwYXJlbnRTY2hlbWEsICRkYXRhLCBpdCB9ID0gY3h0O1xuICAgIGNoZWNrQXN5bmNLZXl3b3JkKGl0LCBkZWYpO1xuICAgIGNvbnN0IHZhbGlkYXRlID0gISRkYXRhICYmIGRlZi5jb21waWxlID8gZGVmLmNvbXBpbGUuY2FsbChpdC5zZWxmLCBzY2hlbWEsIHBhcmVudFNjaGVtYSwgaXQpIDogZGVmLnZhbGlkYXRlO1xuICAgIGNvbnN0IHZhbGlkYXRlUmVmID0gdXNlS2V5d29yZChnZW4sIGtleXdvcmQsIHZhbGlkYXRlKTtcbiAgICBjb25zdCB2YWxpZCA9IGdlbi5sZXQoXCJ2YWxpZFwiKTtcbiAgICBjeHQuYmxvY2skZGF0YSh2YWxpZCwgdmFsaWRhdGVLZXl3b3JkKTtcbiAgICBjeHQub2soKF9hID0gZGVmLnZhbGlkKSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiB2YWxpZCk7XG4gICAgZnVuY3Rpb24gdmFsaWRhdGVLZXl3b3JkKCkge1xuICAgICAgICBpZiAoZGVmLmVycm9ycyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGFzc2lnblZhbGlkKCk7XG4gICAgICAgICAgICBpZiAoZGVmLm1vZGlmeWluZylcbiAgICAgICAgICAgICAgICBtb2RpZnlEYXRhKGN4dCk7XG4gICAgICAgICAgICByZXBvcnRFcnJzKCgpID0+IGN4dC5lcnJvcigpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHJ1bGVFcnJzID0gZGVmLmFzeW5jID8gdmFsaWRhdGVBc3luYygpIDogdmFsaWRhdGVTeW5jKCk7XG4gICAgICAgICAgICBpZiAoZGVmLm1vZGlmeWluZylcbiAgICAgICAgICAgICAgICBtb2RpZnlEYXRhKGN4dCk7XG4gICAgICAgICAgICByZXBvcnRFcnJzKCgpID0+IGFkZEVycnMoY3h0LCBydWxlRXJycykpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHZhbGlkYXRlQXN5bmMoKSB7XG4gICAgICAgIGNvbnN0IHJ1bGVFcnJzID0gZ2VuLmxldChcInJ1bGVFcnJzXCIsIG51bGwpO1xuICAgICAgICBnZW4udHJ5KCgpID0+IGFzc2lnblZhbGlkKCgwLCBjb2RlZ2VuXzEuXykgYGF3YWl0IGApLCAoZSkgPT4gZ2VuLmFzc2lnbih2YWxpZCwgZmFsc2UpLmlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7ZX0gaW5zdGFuY2VvZiAke2l0LlZhbGlkYXRpb25FcnJvcn1gLCAoKSA9PiBnZW4uYXNzaWduKHJ1bGVFcnJzLCAoMCwgY29kZWdlbl8xLl8pIGAke2V9LmVycm9yc2ApLCAoKSA9PiBnZW4udGhyb3coZSkpKTtcbiAgICAgICAgcmV0dXJuIHJ1bGVFcnJzO1xuICAgIH1cbiAgICBmdW5jdGlvbiB2YWxpZGF0ZVN5bmMoKSB7XG4gICAgICAgIGNvbnN0IHZhbGlkYXRlRXJycyA9ICgwLCBjb2RlZ2VuXzEuXykgYCR7dmFsaWRhdGVSZWZ9LmVycm9yc2A7XG4gICAgICAgIGdlbi5hc3NpZ24odmFsaWRhdGVFcnJzLCBudWxsKTtcbiAgICAgICAgYXNzaWduVmFsaWQoY29kZWdlbl8xLm5pbCk7XG4gICAgICAgIHJldHVybiB2YWxpZGF0ZUVycnM7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGFzc2lnblZhbGlkKF9hd2FpdCA9IGRlZi5hc3luYyA/ICgwLCBjb2RlZ2VuXzEuXykgYGF3YWl0IGAgOiBjb2RlZ2VuXzEubmlsKSB7XG4gICAgICAgIGNvbnN0IHBhc3NDeHQgPSBpdC5vcHRzLnBhc3NDb250ZXh0ID8gbmFtZXNfMS5kZWZhdWx0LnRoaXMgOiBuYW1lc18xLmRlZmF1bHQuc2VsZjtcbiAgICAgICAgY29uc3QgcGFzc1NjaGVtYSA9ICEoKFwiY29tcGlsZVwiIGluIGRlZiAmJiAhJGRhdGEpIHx8IGRlZi5zY2hlbWEgPT09IGZhbHNlKTtcbiAgICAgICAgZ2VuLmFzc2lnbih2YWxpZCwgKDAsIGNvZGVnZW5fMS5fKSBgJHtfYXdhaXR9JHsoMCwgY29kZV8xLmNhbGxWYWxpZGF0ZUNvZGUpKGN4dCwgdmFsaWRhdGVSZWYsIHBhc3NDeHQsIHBhc3NTY2hlbWEpfWAsIGRlZi5tb2RpZnlpbmcpO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXBvcnRFcnJzKGVycm9ycykge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLm5vdCkoKF9hID0gZGVmLnZhbGlkKSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiB2YWxpZCksIGVycm9ycyk7XG4gICAgfVxufVxuZXhwb3J0cy5mdW5jS2V5d29yZENvZGUgPSBmdW5jS2V5d29yZENvZGU7XG5mdW5jdGlvbiBtb2RpZnlEYXRhKGN4dCkge1xuICAgIGNvbnN0IHsgZ2VuLCBkYXRhLCBpdCB9ID0gY3h0O1xuICAgIGdlbi5pZihpdC5wYXJlbnREYXRhLCAoKSA9PiBnZW4uYXNzaWduKGRhdGEsICgwLCBjb2RlZ2VuXzEuXykgYCR7aXQucGFyZW50RGF0YX1bJHtpdC5wYXJlbnREYXRhUHJvcGVydHl9XWApKTtcbn1cbmZ1bmN0aW9uIGFkZEVycnMoY3h0LCBlcnJzKSB7XG4gICAgY29uc3QgeyBnZW4gfSA9IGN4dDtcbiAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5fKSBgQXJyYXkuaXNBcnJheSgke2VycnN9KWAsICgpID0+IHtcbiAgICAgICAgZ2VuXG4gICAgICAgICAgICAuYXNzaWduKG5hbWVzXzEuZGVmYXVsdC52RXJyb3JzLCAoMCwgY29kZWdlbl8xLl8pIGAke25hbWVzXzEuZGVmYXVsdC52RXJyb3JzfSA9PT0gbnVsbCA/ICR7ZXJyc30gOiAke25hbWVzXzEuZGVmYXVsdC52RXJyb3JzfS5jb25jYXQoJHtlcnJzfSlgKVxuICAgICAgICAgICAgLmFzc2lnbihuYW1lc18xLmRlZmF1bHQuZXJyb3JzLCAoMCwgY29kZWdlbl8xLl8pIGAke25hbWVzXzEuZGVmYXVsdC52RXJyb3JzfS5sZW5ndGhgKTtcbiAgICAgICAgKDAsIGVycm9yc18xLmV4dGVuZEVycm9ycykoY3h0KTtcbiAgICB9LCAoKSA9PiBjeHQuZXJyb3IoKSk7XG59XG5mdW5jdGlvbiBjaGVja0FzeW5jS2V5d29yZCh7IHNjaGVtYUVudiB9LCBkZWYpIHtcbiAgICBpZiAoZGVmLmFzeW5jICYmICFzY2hlbWFFbnYuJGFzeW5jKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJhc3luYyBrZXl3b3JkIGluIHN5bmMgc2NoZW1hXCIpO1xufVxuZnVuY3Rpb24gdXNlS2V5d29yZChnZW4sIGtleXdvcmQsIHJlc3VsdCkge1xuICAgIGlmIChyZXN1bHQgPT09IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBrZXl3b3JkIFwiJHtrZXl3b3JkfVwiIGZhaWxlZCB0byBjb21waWxlYCk7XG4gICAgcmV0dXJuIGdlbi5zY29wZVZhbHVlKFwia2V5d29yZFwiLCB0eXBlb2YgcmVzdWx0ID09IFwiZnVuY3Rpb25cIiA/IHsgcmVmOiByZXN1bHQgfSA6IHsgcmVmOiByZXN1bHQsIGNvZGU6ICgwLCBjb2RlZ2VuXzEuc3RyaW5naWZ5KShyZXN1bHQpIH0pO1xufVxuZnVuY3Rpb24gdmFsaWRTY2hlbWFUeXBlKHNjaGVtYSwgc2NoZW1hVHlwZSwgYWxsb3dVbmRlZmluZWQgPSBmYWxzZSkge1xuICAgIC8vIFRPRE8gYWRkIHRlc3RzXG4gICAgcmV0dXJuICghc2NoZW1hVHlwZS5sZW5ndGggfHxcbiAgICAgICAgc2NoZW1hVHlwZS5zb21lKChzdCkgPT4gc3QgPT09IFwiYXJyYXlcIlxuICAgICAgICAgICAgPyBBcnJheS5pc0FycmF5KHNjaGVtYSlcbiAgICAgICAgICAgIDogc3QgPT09IFwib2JqZWN0XCJcbiAgICAgICAgICAgICAgICA/IHNjaGVtYSAmJiB0eXBlb2Ygc2NoZW1hID09IFwib2JqZWN0XCIgJiYgIUFycmF5LmlzQXJyYXkoc2NoZW1hKVxuICAgICAgICAgICAgICAgIDogdHlwZW9mIHNjaGVtYSA9PSBzdCB8fCAoYWxsb3dVbmRlZmluZWQgJiYgdHlwZW9mIHNjaGVtYSA9PSBcInVuZGVmaW5lZFwiKSkpO1xufVxuZXhwb3J0cy52YWxpZFNjaGVtYVR5cGUgPSB2YWxpZFNjaGVtYVR5cGU7XG5mdW5jdGlvbiB2YWxpZGF0ZUtleXdvcmRVc2FnZSh7IHNjaGVtYSwgb3B0cywgc2VsZiwgZXJyU2NoZW1hUGF0aCB9LCBkZWYsIGtleXdvcmQpIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAoQXJyYXkuaXNBcnJheShkZWYua2V5d29yZCkgPyAhZGVmLmtleXdvcmQuaW5jbHVkZXMoa2V5d29yZCkgOiBkZWYua2V5d29yZCAhPT0ga2V5d29yZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJhanYgaW1wbGVtZW50YXRpb24gZXJyb3JcIik7XG4gICAgfVxuICAgIGNvbnN0IGRlcHMgPSBkZWYuZGVwZW5kZW5jaWVzO1xuICAgIGlmIChkZXBzID09PSBudWxsIHx8IGRlcHMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGRlcHMuc29tZSgoa3dkKSA9PiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNjaGVtYSwga3dkKSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBwYXJlbnQgc2NoZW1hIG11c3QgaGF2ZSBkZXBlbmRlbmNpZXMgb2YgJHtrZXl3b3JkfTogJHtkZXBzLmpvaW4oXCIsXCIpfWApO1xuICAgIH1cbiAgICBpZiAoZGVmLnZhbGlkYXRlU2NoZW1hKSB7XG4gICAgICAgIGNvbnN0IHZhbGlkID0gZGVmLnZhbGlkYXRlU2NoZW1hKHNjaGVtYVtrZXl3b3JkXSk7XG4gICAgICAgIGlmICghdmFsaWQpIHtcbiAgICAgICAgICAgIGNvbnN0IG1zZyA9IGBrZXl3b3JkIFwiJHtrZXl3b3JkfVwiIHZhbHVlIGlzIGludmFsaWQgYXQgcGF0aCBcIiR7ZXJyU2NoZW1hUGF0aH1cIjogYCArXG4gICAgICAgICAgICAgICAgc2VsZi5lcnJvcnNUZXh0KGRlZi52YWxpZGF0ZVNjaGVtYS5lcnJvcnMpO1xuICAgICAgICAgICAgaWYgKG9wdHMudmFsaWRhdGVTY2hlbWEgPT09IFwibG9nXCIpXG4gICAgICAgICAgICAgICAgc2VsZi5sb2dnZXIuZXJyb3IobXNnKTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbmV4cG9ydHMudmFsaWRhdGVLZXl3b3JkVXNhZ2UgPSB2YWxpZGF0ZUtleXdvcmRVc2FnZTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWtleXdvcmQuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leHBvcnRzLmV4dGVuZFN1YnNjaGVtYU1vZGUgPSBleHBvcnRzLmV4dGVuZFN1YnNjaGVtYURhdGEgPSBleHBvcnRzLmdldFN1YnNjaGVtYSA9IHZvaWQgMDtcbmNvbnN0IGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuLi9jb2RlZ2VuXCIpO1xuY29uc3QgdXRpbF8xID0gcmVxdWlyZShcIi4uL3V0aWxcIik7XG5mdW5jdGlvbiBnZXRTdWJzY2hlbWEoaXQsIHsga2V5d29yZCwgc2NoZW1hUHJvcCwgc2NoZW1hLCBzY2hlbWFQYXRoLCBlcnJTY2hlbWFQYXRoLCB0b3BTY2hlbWFSZWYgfSkge1xuICAgIGlmIChrZXl3b3JkICE9PSB1bmRlZmluZWQgJiYgc2NoZW1hICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdib3RoIFwia2V5d29yZFwiIGFuZCBcInNjaGVtYVwiIHBhc3NlZCwgb25seSBvbmUgYWxsb3dlZCcpO1xuICAgIH1cbiAgICBpZiAoa2V5d29yZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnN0IHNjaCA9IGl0LnNjaGVtYVtrZXl3b3JkXTtcbiAgICAgICAgcmV0dXJuIHNjaGVtYVByb3AgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgc2NoZW1hOiBzY2gsXG4gICAgICAgICAgICAgICAgc2NoZW1hUGF0aDogKDAsIGNvZGVnZW5fMS5fKSBgJHtpdC5zY2hlbWFQYXRofSR7KDAsIGNvZGVnZW5fMS5nZXRQcm9wZXJ0eSkoa2V5d29yZCl9YCxcbiAgICAgICAgICAgICAgICBlcnJTY2hlbWFQYXRoOiBgJHtpdC5lcnJTY2hlbWFQYXRofS8ke2tleXdvcmR9YCxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgIHNjaGVtYTogc2NoW3NjaGVtYVByb3BdLFxuICAgICAgICAgICAgICAgIHNjaGVtYVBhdGg6ICgwLCBjb2RlZ2VuXzEuXykgYCR7aXQuc2NoZW1hUGF0aH0keygwLCBjb2RlZ2VuXzEuZ2V0UHJvcGVydHkpKGtleXdvcmQpfSR7KDAsIGNvZGVnZW5fMS5nZXRQcm9wZXJ0eSkoc2NoZW1hUHJvcCl9YCxcbiAgICAgICAgICAgICAgICBlcnJTY2hlbWFQYXRoOiBgJHtpdC5lcnJTY2hlbWFQYXRofS8ke2tleXdvcmR9LyR7KDAsIHV0aWxfMS5lc2NhcGVGcmFnbWVudCkoc2NoZW1hUHJvcCl9YCxcbiAgICAgICAgICAgIH07XG4gICAgfVxuICAgIGlmIChzY2hlbWEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoc2NoZW1hUGF0aCA9PT0gdW5kZWZpbmVkIHx8IGVyclNjaGVtYVBhdGggPT09IHVuZGVmaW5lZCB8fCB0b3BTY2hlbWFSZWYgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInNjaGVtYVBhdGhcIiwgXCJlcnJTY2hlbWFQYXRoXCIgYW5kIFwidG9wU2NoZW1hUmVmXCIgYXJlIHJlcXVpcmVkIHdpdGggXCJzY2hlbWFcIicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzY2hlbWEsXG4gICAgICAgICAgICBzY2hlbWFQYXRoLFxuICAgICAgICAgICAgdG9wU2NoZW1hUmVmLFxuICAgICAgICAgICAgZXJyU2NoZW1hUGF0aCxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKCdlaXRoZXIgXCJrZXl3b3JkXCIgb3IgXCJzY2hlbWFcIiBtdXN0IGJlIHBhc3NlZCcpO1xufVxuZXhwb3J0cy5nZXRTdWJzY2hlbWEgPSBnZXRTdWJzY2hlbWE7XG5mdW5jdGlvbiBleHRlbmRTdWJzY2hlbWFEYXRhKHN1YnNjaGVtYSwgaXQsIHsgZGF0YVByb3AsIGRhdGFQcm9wVHlwZTogZHBUeXBlLCBkYXRhLCBkYXRhVHlwZXMsIHByb3BlcnR5TmFtZSB9KSB7XG4gICAgaWYgKGRhdGEgIT09IHVuZGVmaW5lZCAmJiBkYXRhUHJvcCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYm90aCBcImRhdGFcIiBhbmQgXCJkYXRhUHJvcFwiIHBhc3NlZCwgb25seSBvbmUgYWxsb3dlZCcpO1xuICAgIH1cbiAgICBjb25zdCB7IGdlbiB9ID0gaXQ7XG4gICAgaWYgKGRhdGFQcm9wICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3QgeyBlcnJvclBhdGgsIGRhdGFQYXRoQXJyLCBvcHRzIH0gPSBpdDtcbiAgICAgICAgY29uc3QgbmV4dERhdGEgPSBnZW4ubGV0KFwiZGF0YVwiLCAoMCwgY29kZWdlbl8xLl8pIGAke2l0LmRhdGF9JHsoMCwgY29kZWdlbl8xLmdldFByb3BlcnR5KShkYXRhUHJvcCl9YCwgdHJ1ZSk7XG4gICAgICAgIGRhdGFDb250ZXh0UHJvcHMobmV4dERhdGEpO1xuICAgICAgICBzdWJzY2hlbWEuZXJyb3JQYXRoID0gKDAsIGNvZGVnZW5fMS5zdHIpIGAke2Vycm9yUGF0aH0keygwLCB1dGlsXzEuZ2V0RXJyb3JQYXRoKShkYXRhUHJvcCwgZHBUeXBlLCBvcHRzLmpzUHJvcGVydHlTeW50YXgpfWA7XG4gICAgICAgIHN1YnNjaGVtYS5wYXJlbnREYXRhUHJvcGVydHkgPSAoMCwgY29kZWdlbl8xLl8pIGAke2RhdGFQcm9wfWA7XG4gICAgICAgIHN1YnNjaGVtYS5kYXRhUGF0aEFyciA9IFsuLi5kYXRhUGF0aEFyciwgc3Vic2NoZW1hLnBhcmVudERhdGFQcm9wZXJ0eV07XG4gICAgfVxuICAgIGlmIChkYXRhICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3QgbmV4dERhdGEgPSBkYXRhIGluc3RhbmNlb2YgY29kZWdlbl8xLk5hbWUgPyBkYXRhIDogZ2VuLmxldChcImRhdGFcIiwgZGF0YSwgdHJ1ZSk7IC8vIHJlcGxhY2VhYmxlIGlmIHVzZWQgb25jZT9cbiAgICAgICAgZGF0YUNvbnRleHRQcm9wcyhuZXh0RGF0YSk7XG4gICAgICAgIGlmIChwcm9wZXJ0eU5hbWUgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIHN1YnNjaGVtYS5wcm9wZXJ0eU5hbWUgPSBwcm9wZXJ0eU5hbWU7XG4gICAgICAgIC8vIFRPRE8gc29tZXRoaW5nIGlzIHBvc3NpYmx5IHdyb25nIGhlcmUgd2l0aCBub3QgY2hhbmdpbmcgcGFyZW50RGF0YVByb3BlcnR5IGFuZCBub3QgYXBwZW5kaW5nIGRhdGFQYXRoQXJyXG4gICAgfVxuICAgIGlmIChkYXRhVHlwZXMpXG4gICAgICAgIHN1YnNjaGVtYS5kYXRhVHlwZXMgPSBkYXRhVHlwZXM7XG4gICAgZnVuY3Rpb24gZGF0YUNvbnRleHRQcm9wcyhfbmV4dERhdGEpIHtcbiAgICAgICAgc3Vic2NoZW1hLmRhdGEgPSBfbmV4dERhdGE7XG4gICAgICAgIHN1YnNjaGVtYS5kYXRhTGV2ZWwgPSBpdC5kYXRhTGV2ZWwgKyAxO1xuICAgICAgICBzdWJzY2hlbWEuZGF0YVR5cGVzID0gW107XG4gICAgICAgIGl0LmRlZmluZWRQcm9wZXJ0aWVzID0gbmV3IFNldCgpO1xuICAgICAgICBzdWJzY2hlbWEucGFyZW50RGF0YSA9IGl0LmRhdGE7XG4gICAgICAgIHN1YnNjaGVtYS5kYXRhTmFtZXMgPSBbLi4uaXQuZGF0YU5hbWVzLCBfbmV4dERhdGFdO1xuICAgIH1cbn1cbmV4cG9ydHMuZXh0ZW5kU3Vic2NoZW1hRGF0YSA9IGV4dGVuZFN1YnNjaGVtYURhdGE7XG5mdW5jdGlvbiBleHRlbmRTdWJzY2hlbWFNb2RlKHN1YnNjaGVtYSwgeyBqdGREaXNjcmltaW5hdG9yLCBqdGRNZXRhZGF0YSwgY29tcG9zaXRlUnVsZSwgY3JlYXRlRXJyb3JzLCBhbGxFcnJvcnMgfSkge1xuICAgIGlmIChjb21wb3NpdGVSdWxlICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHN1YnNjaGVtYS5jb21wb3NpdGVSdWxlID0gY29tcG9zaXRlUnVsZTtcbiAgICBpZiAoY3JlYXRlRXJyb3JzICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHN1YnNjaGVtYS5jcmVhdGVFcnJvcnMgPSBjcmVhdGVFcnJvcnM7XG4gICAgaWYgKGFsbEVycm9ycyAhPT0gdW5kZWZpbmVkKVxuICAgICAgICBzdWJzY2hlbWEuYWxsRXJyb3JzID0gYWxsRXJyb3JzO1xuICAgIHN1YnNjaGVtYS5qdGREaXNjcmltaW5hdG9yID0ganRkRGlzY3JpbWluYXRvcjsgLy8gbm90IGluaGVyaXRlZFxuICAgIHN1YnNjaGVtYS5qdGRNZXRhZGF0YSA9IGp0ZE1ldGFkYXRhOyAvLyBub3QgaW5oZXJpdGVkXG59XG5leHBvcnRzLmV4dGVuZFN1YnNjaGVtYU1vZGUgPSBleHRlbmRTdWJzY2hlbWFNb2RlO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c3Vic2NoZW1hLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXhwb3J0cy5Db2RlR2VuID0gZXhwb3J0cy5OYW1lID0gZXhwb3J0cy5uaWwgPSBleHBvcnRzLnN0cmluZ2lmeSA9IGV4cG9ydHMuc3RyID0gZXhwb3J0cy5fID0gZXhwb3J0cy5LZXl3b3JkQ3h0ID0gdm9pZCAwO1xudmFyIHZhbGlkYXRlXzEgPSByZXF1aXJlKFwiLi9jb21waWxlL3ZhbGlkYXRlXCIpO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiS2V5d29yZEN4dFwiLCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdmFsaWRhdGVfMS5LZXl3b3JkQ3h0OyB9IH0pO1xudmFyIGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuL2NvbXBpbGUvY29kZWdlblwiKTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9cIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvZGVnZW5fMS5fOyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwic3RyXCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2RlZ2VuXzEuc3RyOyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwic3RyaW5naWZ5XCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2RlZ2VuXzEuc3RyaW5naWZ5OyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwibmlsXCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2RlZ2VuXzEubmlsOyB9IH0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiTmFtZVwiLCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gY29kZWdlbl8xLk5hbWU7IH0gfSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJDb2RlR2VuXCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2RlZ2VuXzEuQ29kZUdlbjsgfSB9KTtcbmNvbnN0IHZhbGlkYXRpb25fZXJyb3JfMSA9IHJlcXVpcmUoXCIuL3J1bnRpbWUvdmFsaWRhdGlvbl9lcnJvclwiKTtcbmNvbnN0IHJlZl9lcnJvcl8xID0gcmVxdWlyZShcIi4vY29tcGlsZS9yZWZfZXJyb3JcIik7XG5jb25zdCBydWxlc18xID0gcmVxdWlyZShcIi4vY29tcGlsZS9ydWxlc1wiKTtcbmNvbnN0IGNvbXBpbGVfMSA9IHJlcXVpcmUoXCIuL2NvbXBpbGVcIik7XG5jb25zdCBjb2RlZ2VuXzIgPSByZXF1aXJlKFwiLi9jb21waWxlL2NvZGVnZW5cIik7XG5jb25zdCByZXNvbHZlXzEgPSByZXF1aXJlKFwiLi9jb21waWxlL3Jlc29sdmVcIik7XG5jb25zdCBkYXRhVHlwZV8xID0gcmVxdWlyZShcIi4vY29tcGlsZS92YWxpZGF0ZS9kYXRhVHlwZVwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuL2NvbXBpbGUvdXRpbFwiKTtcbmNvbnN0ICRkYXRhUmVmU2NoZW1hID0gcmVxdWlyZShcIi4vcmVmcy9kYXRhLmpzb25cIik7XG5jb25zdCB1cmlfMSA9IHJlcXVpcmUoXCIuL3J1bnRpbWUvdXJpXCIpO1xuY29uc3QgZGVmYXVsdFJlZ0V4cCA9IChzdHIsIGZsYWdzKSA9PiBuZXcgUmVnRXhwKHN0ciwgZmxhZ3MpO1xuZGVmYXVsdFJlZ0V4cC5jb2RlID0gXCJuZXcgUmVnRXhwXCI7XG5jb25zdCBNRVRBX0lHTk9SRV9PUFRJT05TID0gW1wicmVtb3ZlQWRkaXRpb25hbFwiLCBcInVzZURlZmF1bHRzXCIsIFwiY29lcmNlVHlwZXNcIl07XG5jb25zdCBFWFRfU0NPUEVfTkFNRVMgPSBuZXcgU2V0KFtcbiAgICBcInZhbGlkYXRlXCIsXG4gICAgXCJzZXJpYWxpemVcIixcbiAgICBcInBhcnNlXCIsXG4gICAgXCJ3cmFwcGVyXCIsXG4gICAgXCJyb290XCIsXG4gICAgXCJzY2hlbWFcIixcbiAgICBcImtleXdvcmRcIixcbiAgICBcInBhdHRlcm5cIixcbiAgICBcImZvcm1hdHNcIixcbiAgICBcInZhbGlkYXRlJGRhdGFcIixcbiAgICBcImZ1bmNcIixcbiAgICBcIm9ialwiLFxuICAgIFwiRXJyb3JcIixcbl0pO1xuY29uc3QgcmVtb3ZlZE9wdGlvbnMgPSB7XG4gICAgZXJyb3JEYXRhUGF0aDogXCJcIixcbiAgICBmb3JtYXQ6IFwiYHZhbGlkYXRlRm9ybWF0czogZmFsc2VgIGNhbiBiZSB1c2VkIGluc3RlYWQuXCIsXG4gICAgbnVsbGFibGU6ICdcIm51bGxhYmxlXCIga2V5d29yZCBpcyBzdXBwb3J0ZWQgYnkgZGVmYXVsdC4nLFxuICAgIGpzb25Qb2ludGVyczogXCJEZXByZWNhdGVkIGpzUHJvcGVydHlTeW50YXggY2FuIGJlIHVzZWQgaW5zdGVhZC5cIixcbiAgICBleHRlbmRSZWZzOiBcIkRlcHJlY2F0ZWQgaWdub3JlS2V5d29yZHNXaXRoUmVmIGNhbiBiZSB1c2VkIGluc3RlYWQuXCIsXG4gICAgbWlzc2luZ1JlZnM6IFwiUGFzcyBlbXB0eSBzY2hlbWEgd2l0aCAkaWQgdGhhdCBzaG91bGQgYmUgaWdub3JlZCB0byBhanYuYWRkU2NoZW1hLlwiLFxuICAgIHByb2Nlc3NDb2RlOiBcIlVzZSBvcHRpb24gYGNvZGU6IHtwcm9jZXNzOiAoY29kZSwgc2NoZW1hRW52OiBvYmplY3QpID0+IHN0cmluZ31gXCIsXG4gICAgc291cmNlQ29kZTogXCJVc2Ugb3B0aW9uIGBjb2RlOiB7c291cmNlOiB0cnVlfWBcIixcbiAgICBzdHJpY3REZWZhdWx0czogXCJJdCBpcyBkZWZhdWx0IG5vdywgc2VlIG9wdGlvbiBgc3RyaWN0YC5cIixcbiAgICBzdHJpY3RLZXl3b3JkczogXCJJdCBpcyBkZWZhdWx0IG5vdywgc2VlIG9wdGlvbiBgc3RyaWN0YC5cIixcbiAgICB1bmlxdWVJdGVtczogJ1widW5pcXVlSXRlbXNcIiBrZXl3b3JkIGlzIGFsd2F5cyB2YWxpZGF0ZWQuJyxcbiAgICB1bmtub3duRm9ybWF0czogXCJEaXNhYmxlIHN0cmljdCBtb2RlIG9yIHBhc3MgYHRydWVgIHRvIGBhanYuYWRkRm9ybWF0YCAob3IgYGZvcm1hdHNgIG9wdGlvbikuXCIsXG4gICAgY2FjaGU6IFwiTWFwIGlzIHVzZWQgYXMgY2FjaGUsIHNjaGVtYSBvYmplY3QgYXMga2V5LlwiLFxuICAgIHNlcmlhbGl6ZTogXCJNYXAgaXMgdXNlZCBhcyBjYWNoZSwgc2NoZW1hIG9iamVjdCBhcyBrZXkuXCIsXG4gICAgYWp2RXJyb3JzOiBcIkl0IGlzIGRlZmF1bHQgbm93LlwiLFxufTtcbmNvbnN0IGRlcHJlY2F0ZWRPcHRpb25zID0ge1xuICAgIGlnbm9yZUtleXdvcmRzV2l0aFJlZjogXCJcIixcbiAgICBqc1Byb3BlcnR5U3ludGF4OiBcIlwiLFxuICAgIHVuaWNvZGU6ICdcIm1pbkxlbmd0aFwiL1wibWF4TGVuZ3RoXCIgYWNjb3VudCBmb3IgdW5pY29kZSBjaGFyYWN0ZXJzIGJ5IGRlZmF1bHQuJyxcbn07XG5jb25zdCBNQVhfRVhQUkVTU0lPTiA9IDIwMDtcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5mdW5jdGlvbiByZXF1aXJlZE9wdGlvbnMobykge1xuICAgIHZhciBfYSwgX2IsIF9jLCBfZCwgX2UsIF9mLCBfZywgX2gsIF9qLCBfaywgX2wsIF9tLCBfbywgX3AsIF9xLCBfciwgX3MsIF90LCBfdSwgX3YsIF93LCBfeCwgX3ksIF96LCBfMDtcbiAgICBjb25zdCBzID0gby5zdHJpY3Q7XG4gICAgY29uc3QgX29wdHogPSAoX2EgPSBvLmNvZGUpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5vcHRpbWl6ZTtcbiAgICBjb25zdCBvcHRpbWl6ZSA9IF9vcHR6ID09PSB0cnVlIHx8IF9vcHR6ID09PSB1bmRlZmluZWQgPyAxIDogX29wdHogfHwgMDtcbiAgICBjb25zdCByZWdFeHAgPSAoX2MgPSAoX2IgPSBvLmNvZGUpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5yZWdFeHApICE9PSBudWxsICYmIF9jICE9PSB2b2lkIDAgPyBfYyA6IGRlZmF1bHRSZWdFeHA7XG4gICAgY29uc3QgdXJpUmVzb2x2ZXIgPSAoX2QgPSBvLnVyaVJlc29sdmVyKSAhPT0gbnVsbCAmJiBfZCAhPT0gdm9pZCAwID8gX2QgOiB1cmlfMS5kZWZhdWx0O1xuICAgIHJldHVybiB7XG4gICAgICAgIHN0cmljdFNjaGVtYTogKF9mID0gKF9lID0gby5zdHJpY3RTY2hlbWEpICE9PSBudWxsICYmIF9lICE9PSB2b2lkIDAgPyBfZSA6IHMpICE9PSBudWxsICYmIF9mICE9PSB2b2lkIDAgPyBfZiA6IHRydWUsXG4gICAgICAgIHN0cmljdE51bWJlcnM6IChfaCA9IChfZyA9IG8uc3RyaWN0TnVtYmVycykgIT09IG51bGwgJiYgX2cgIT09IHZvaWQgMCA/IF9nIDogcykgIT09IG51bGwgJiYgX2ggIT09IHZvaWQgMCA/IF9oIDogdHJ1ZSxcbiAgICAgICAgc3RyaWN0VHlwZXM6IChfayA9IChfaiA9IG8uc3RyaWN0VHlwZXMpICE9PSBudWxsICYmIF9qICE9PSB2b2lkIDAgPyBfaiA6IHMpICE9PSBudWxsICYmIF9rICE9PSB2b2lkIDAgPyBfayA6IFwibG9nXCIsXG4gICAgICAgIHN0cmljdFR1cGxlczogKF9tID0gKF9sID0gby5zdHJpY3RUdXBsZXMpICE9PSBudWxsICYmIF9sICE9PSB2b2lkIDAgPyBfbCA6IHMpICE9PSBudWxsICYmIF9tICE9PSB2b2lkIDAgPyBfbSA6IFwibG9nXCIsXG4gICAgICAgIHN0cmljdFJlcXVpcmVkOiAoX3AgPSAoX28gPSBvLnN0cmljdFJlcXVpcmVkKSAhPT0gbnVsbCAmJiBfbyAhPT0gdm9pZCAwID8gX28gOiBzKSAhPT0gbnVsbCAmJiBfcCAhPT0gdm9pZCAwID8gX3AgOiBmYWxzZSxcbiAgICAgICAgY29kZTogby5jb2RlID8geyAuLi5vLmNvZGUsIG9wdGltaXplLCByZWdFeHAgfSA6IHsgb3B0aW1pemUsIHJlZ0V4cCB9LFxuICAgICAgICBsb29wUmVxdWlyZWQ6IChfcSA9IG8ubG9vcFJlcXVpcmVkKSAhPT0gbnVsbCAmJiBfcSAhPT0gdm9pZCAwID8gX3EgOiBNQVhfRVhQUkVTU0lPTixcbiAgICAgICAgbG9vcEVudW06IChfciA9IG8ubG9vcEVudW0pICE9PSBudWxsICYmIF9yICE9PSB2b2lkIDAgPyBfciA6IE1BWF9FWFBSRVNTSU9OLFxuICAgICAgICBtZXRhOiAoX3MgPSBvLm1ldGEpICE9PSBudWxsICYmIF9zICE9PSB2b2lkIDAgPyBfcyA6IHRydWUsXG4gICAgICAgIG1lc3NhZ2VzOiAoX3QgPSBvLm1lc3NhZ2VzKSAhPT0gbnVsbCAmJiBfdCAhPT0gdm9pZCAwID8gX3QgOiB0cnVlLFxuICAgICAgICBpbmxpbmVSZWZzOiAoX3UgPSBvLmlubGluZVJlZnMpICE9PSBudWxsICYmIF91ICE9PSB2b2lkIDAgPyBfdSA6IHRydWUsXG4gICAgICAgIHNjaGVtYUlkOiAoX3YgPSBvLnNjaGVtYUlkKSAhPT0gbnVsbCAmJiBfdiAhPT0gdm9pZCAwID8gX3YgOiBcIiRpZFwiLFxuICAgICAgICBhZGRVc2VkU2NoZW1hOiAoX3cgPSBvLmFkZFVzZWRTY2hlbWEpICE9PSBudWxsICYmIF93ICE9PSB2b2lkIDAgPyBfdyA6IHRydWUsXG4gICAgICAgIHZhbGlkYXRlU2NoZW1hOiAoX3ggPSBvLnZhbGlkYXRlU2NoZW1hKSAhPT0gbnVsbCAmJiBfeCAhPT0gdm9pZCAwID8gX3ggOiB0cnVlLFxuICAgICAgICB2YWxpZGF0ZUZvcm1hdHM6IChfeSA9IG8udmFsaWRhdGVGb3JtYXRzKSAhPT0gbnVsbCAmJiBfeSAhPT0gdm9pZCAwID8gX3kgOiB0cnVlLFxuICAgICAgICB1bmljb2RlUmVnRXhwOiAoX3ogPSBvLnVuaWNvZGVSZWdFeHApICE9PSBudWxsICYmIF96ICE9PSB2b2lkIDAgPyBfeiA6IHRydWUsXG4gICAgICAgIGludDMycmFuZ2U6IChfMCA9IG8uaW50MzJyYW5nZSkgIT09IG51bGwgJiYgXzAgIT09IHZvaWQgMCA/IF8wIDogdHJ1ZSxcbiAgICAgICAgdXJpUmVzb2x2ZXI6IHVyaVJlc29sdmVyLFxuICAgIH07XG59XG5jbGFzcyBBanYge1xuICAgIGNvbnN0cnVjdG9yKG9wdHMgPSB7fSkge1xuICAgICAgICB0aGlzLnNjaGVtYXMgPSB7fTtcbiAgICAgICAgdGhpcy5yZWZzID0ge307XG4gICAgICAgIHRoaXMuZm9ybWF0cyA9IHt9O1xuICAgICAgICB0aGlzLl9jb21waWxhdGlvbnMgPSBuZXcgU2V0KCk7XG4gICAgICAgIHRoaXMuX2xvYWRpbmcgPSB7fTtcbiAgICAgICAgdGhpcy5fY2FjaGUgPSBuZXcgTWFwKCk7XG4gICAgICAgIG9wdHMgPSB0aGlzLm9wdHMgPSB7IC4uLm9wdHMsIC4uLnJlcXVpcmVkT3B0aW9ucyhvcHRzKSB9O1xuICAgICAgICBjb25zdCB7IGVzNSwgbGluZXMgfSA9IHRoaXMub3B0cy5jb2RlO1xuICAgICAgICB0aGlzLnNjb3BlID0gbmV3IGNvZGVnZW5fMi5WYWx1ZVNjb3BlKHsgc2NvcGU6IHt9LCBwcmVmaXhlczogRVhUX1NDT1BFX05BTUVTLCBlczUsIGxpbmVzIH0pO1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGdldExvZ2dlcihvcHRzLmxvZ2dlcik7XG4gICAgICAgIGNvbnN0IGZvcm1hdE9wdCA9IG9wdHMudmFsaWRhdGVGb3JtYXRzO1xuICAgICAgICBvcHRzLnZhbGlkYXRlRm9ybWF0cyA9IGZhbHNlO1xuICAgICAgICB0aGlzLlJVTEVTID0gKDAsIHJ1bGVzXzEuZ2V0UnVsZXMpKCk7XG4gICAgICAgIGNoZWNrT3B0aW9ucy5jYWxsKHRoaXMsIHJlbW92ZWRPcHRpb25zLCBvcHRzLCBcIk5PVCBTVVBQT1JURURcIik7XG4gICAgICAgIGNoZWNrT3B0aW9ucy5jYWxsKHRoaXMsIGRlcHJlY2F0ZWRPcHRpb25zLCBvcHRzLCBcIkRFUFJFQ0FURURcIiwgXCJ3YXJuXCIpO1xuICAgICAgICB0aGlzLl9tZXRhT3B0cyA9IGdldE1ldGFTY2hlbWFPcHRpb25zLmNhbGwodGhpcyk7XG4gICAgICAgIGlmIChvcHRzLmZvcm1hdHMpXG4gICAgICAgICAgICBhZGRJbml0aWFsRm9ybWF0cy5jYWxsKHRoaXMpO1xuICAgICAgICB0aGlzLl9hZGRWb2NhYnVsYXJpZXMoKTtcbiAgICAgICAgdGhpcy5fYWRkRGVmYXVsdE1ldGFTY2hlbWEoKTtcbiAgICAgICAgaWYgKG9wdHMua2V5d29yZHMpXG4gICAgICAgICAgICBhZGRJbml0aWFsS2V5d29yZHMuY2FsbCh0aGlzLCBvcHRzLmtleXdvcmRzKTtcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRzLm1ldGEgPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgIHRoaXMuYWRkTWV0YVNjaGVtYShvcHRzLm1ldGEpO1xuICAgICAgICBhZGRJbml0aWFsU2NoZW1hcy5jYWxsKHRoaXMpO1xuICAgICAgICBvcHRzLnZhbGlkYXRlRm9ybWF0cyA9IGZvcm1hdE9wdDtcbiAgICB9XG4gICAgX2FkZFZvY2FidWxhcmllcygpIHtcbiAgICAgICAgdGhpcy5hZGRLZXl3b3JkKFwiJGFzeW5jXCIpO1xuICAgIH1cbiAgICBfYWRkRGVmYXVsdE1ldGFTY2hlbWEoKSB7XG4gICAgICAgIGNvbnN0IHsgJGRhdGEsIG1ldGEsIHNjaGVtYUlkIH0gPSB0aGlzLm9wdHM7XG4gICAgICAgIGxldCBfZGF0YVJlZlNjaGVtYSA9ICRkYXRhUmVmU2NoZW1hO1xuICAgICAgICBpZiAoc2NoZW1hSWQgPT09IFwiaWRcIikge1xuICAgICAgICAgICAgX2RhdGFSZWZTY2hlbWEgPSB7IC4uLiRkYXRhUmVmU2NoZW1hIH07XG4gICAgICAgICAgICBfZGF0YVJlZlNjaGVtYS5pZCA9IF9kYXRhUmVmU2NoZW1hLiRpZDtcbiAgICAgICAgICAgIGRlbGV0ZSBfZGF0YVJlZlNjaGVtYS4kaWQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGEgJiYgJGRhdGEpXG4gICAgICAgICAgICB0aGlzLmFkZE1ldGFTY2hlbWEoX2RhdGFSZWZTY2hlbWEsIF9kYXRhUmVmU2NoZW1hW3NjaGVtYUlkXSwgZmFsc2UpO1xuICAgIH1cbiAgICBkZWZhdWx0TWV0YSgpIHtcbiAgICAgICAgY29uc3QgeyBtZXRhLCBzY2hlbWFJZCB9ID0gdGhpcy5vcHRzO1xuICAgICAgICByZXR1cm4gKHRoaXMub3B0cy5kZWZhdWx0TWV0YSA9IHR5cGVvZiBtZXRhID09IFwib2JqZWN0XCIgPyBtZXRhW3NjaGVtYUlkXSB8fCBtZXRhIDogdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgdmFsaWRhdGUoc2NoZW1hS2V5UmVmLCAvLyBrZXksIHJlZiBvciBzY2hlbWEgb2JqZWN0XG4gICAgZGF0YSAvLyB0byBiZSB2YWxpZGF0ZWRcbiAgICApIHtcbiAgICAgICAgbGV0IHY7XG4gICAgICAgIGlmICh0eXBlb2Ygc2NoZW1hS2V5UmVmID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHYgPSB0aGlzLmdldFNjaGVtYShzY2hlbWFLZXlSZWYpO1xuICAgICAgICAgICAgaWYgKCF2KVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgbm8gc2NoZW1hIHdpdGgga2V5IG9yIHJlZiBcIiR7c2NoZW1hS2V5UmVmfVwiYCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2ID0gdGhpcy5jb21waWxlKHNjaGVtYUtleVJlZik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdmFsaWQgPSB2KGRhdGEpO1xuICAgICAgICBpZiAoIShcIiRhc3luY1wiIGluIHYpKVxuICAgICAgICAgICAgdGhpcy5lcnJvcnMgPSB2LmVycm9ycztcbiAgICAgICAgcmV0dXJuIHZhbGlkO1xuICAgIH1cbiAgICBjb21waWxlKHNjaGVtYSwgX21ldGEpIHtcbiAgICAgICAgY29uc3Qgc2NoID0gdGhpcy5fYWRkU2NoZW1hKHNjaGVtYSwgX21ldGEpO1xuICAgICAgICByZXR1cm4gKHNjaC52YWxpZGF0ZSB8fCB0aGlzLl9jb21waWxlU2NoZW1hRW52KHNjaCkpO1xuICAgIH1cbiAgICBjb21waWxlQXN5bmMoc2NoZW1hLCBtZXRhKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5vcHRzLmxvYWRTY2hlbWEgIT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvcHRpb25zLmxvYWRTY2hlbWEgc2hvdWxkIGJlIGEgZnVuY3Rpb25cIik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyBsb2FkU2NoZW1hIH0gPSB0aGlzLm9wdHM7XG4gICAgICAgIHJldHVybiBydW5Db21waWxlQXN5bmMuY2FsbCh0aGlzLCBzY2hlbWEsIG1ldGEpO1xuICAgICAgICBhc3luYyBmdW5jdGlvbiBydW5Db21waWxlQXN5bmMoX3NjaGVtYSwgX21ldGEpIHtcbiAgICAgICAgICAgIGF3YWl0IGxvYWRNZXRhU2NoZW1hLmNhbGwodGhpcywgX3NjaGVtYS4kc2NoZW1hKTtcbiAgICAgICAgICAgIGNvbnN0IHNjaCA9IHRoaXMuX2FkZFNjaGVtYShfc2NoZW1hLCBfbWV0YSk7XG4gICAgICAgICAgICByZXR1cm4gc2NoLnZhbGlkYXRlIHx8IF9jb21waWxlQXN5bmMuY2FsbCh0aGlzLCBzY2gpO1xuICAgICAgICB9XG4gICAgICAgIGFzeW5jIGZ1bmN0aW9uIGxvYWRNZXRhU2NoZW1hKCRyZWYpIHtcbiAgICAgICAgICAgIGlmICgkcmVmICYmICF0aGlzLmdldFNjaGVtYSgkcmVmKSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHJ1bkNvbXBpbGVBc3luYy5jYWxsKHRoaXMsIHsgJHJlZiB9LCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhc3luYyBmdW5jdGlvbiBfY29tcGlsZUFzeW5jKHNjaCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fY29tcGlsZVNjaGVtYUVudihzY2gpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgcmVmX2Vycm9yXzEuZGVmYXVsdCkpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICAgICAgY2hlY2tMb2FkZWQuY2FsbCh0aGlzLCBlKTtcbiAgICAgICAgICAgICAgICBhd2FpdCBsb2FkTWlzc2luZ1NjaGVtYS5jYWxsKHRoaXMsIGUubWlzc2luZ1NjaGVtYSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9jb21waWxlQXN5bmMuY2FsbCh0aGlzLCBzY2gpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGNoZWNrTG9hZGVkKHsgbWlzc2luZ1NjaGVtYTogcmVmLCBtaXNzaW5nUmVmIH0pIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlZnNbcmVmXSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQW55U2NoZW1hICR7cmVmfSBpcyBsb2FkZWQgYnV0ICR7bWlzc2luZ1JlZn0gY2Fubm90IGJlIHJlc29sdmVkYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYXN5bmMgZnVuY3Rpb24gbG9hZE1pc3NpbmdTY2hlbWEocmVmKSB7XG4gICAgICAgICAgICBjb25zdCBfc2NoZW1hID0gYXdhaXQgX2xvYWRTY2hlbWEuY2FsbCh0aGlzLCByZWYpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLnJlZnNbcmVmXSlcbiAgICAgICAgICAgICAgICBhd2FpdCBsb2FkTWV0YVNjaGVtYS5jYWxsKHRoaXMsIF9zY2hlbWEuJHNjaGVtYSk7XG4gICAgICAgICAgICBpZiAoIXRoaXMucmVmc1tyZWZdKVxuICAgICAgICAgICAgICAgIHRoaXMuYWRkU2NoZW1hKF9zY2hlbWEsIHJlZiwgbWV0YSk7XG4gICAgICAgIH1cbiAgICAgICAgYXN5bmMgZnVuY3Rpb24gX2xvYWRTY2hlbWEocmVmKSB7XG4gICAgICAgICAgICBjb25zdCBwID0gdGhpcy5fbG9hZGluZ1tyZWZdO1xuICAgICAgICAgICAgaWYgKHApXG4gICAgICAgICAgICAgICAgcmV0dXJuIHA7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhd2FpdCAodGhpcy5fbG9hZGluZ1tyZWZdID0gbG9hZFNjaGVtYShyZWYpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9sb2FkaW5nW3JlZl07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkcyBzY2hlbWEgdG8gdGhlIGluc3RhbmNlXG4gICAgYWRkU2NoZW1hKHNjaGVtYSwgLy8gSWYgYXJyYXkgaXMgcGFzc2VkLCBga2V5YCB3aWxsIGJlIGlnbm9yZWRcbiAgICBrZXksIC8vIE9wdGlvbmFsIHNjaGVtYSBrZXkuIENhbiBiZSBwYXNzZWQgdG8gYHZhbGlkYXRlYCBtZXRob2QgaW5zdGVhZCBvZiBzY2hlbWEgb2JqZWN0IG9yIGlkL3JlZi4gT25lIHNjaGVtYSBwZXIgaW5zdGFuY2UgY2FuIGhhdmUgZW1wdHkgYGlkYCBhbmQgYGtleWAuXG4gICAgX21ldGEsIC8vIHRydWUgaWYgc2NoZW1hIGlzIGEgbWV0YS1zY2hlbWEuIFVzZWQgaW50ZXJuYWxseSwgYWRkTWV0YVNjaGVtYSBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkLlxuICAgIF92YWxpZGF0ZVNjaGVtYSA9IHRoaXMub3B0cy52YWxpZGF0ZVNjaGVtYSAvLyBmYWxzZSB0byBza2lwIHNjaGVtYSB2YWxpZGF0aW9uLiBVc2VkIGludGVybmFsbHksIG9wdGlvbiB2YWxpZGF0ZVNjaGVtYSBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkLlxuICAgICkge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShzY2hlbWEpKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHNjaCBvZiBzY2hlbWEpXG4gICAgICAgICAgICAgICAgdGhpcy5hZGRTY2hlbWEoc2NoLCB1bmRlZmluZWQsIF9tZXRhLCBfdmFsaWRhdGVTY2hlbWEpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGlkO1xuICAgICAgICBpZiAodHlwZW9mIHNjaGVtYSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgY29uc3QgeyBzY2hlbWFJZCB9ID0gdGhpcy5vcHRzO1xuICAgICAgICAgICAgaWQgPSBzY2hlbWFbc2NoZW1hSWRdO1xuICAgICAgICAgICAgaWYgKGlkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIGlkICE9IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHNjaGVtYSAke3NjaGVtYUlkfSBtdXN0IGJlIHN0cmluZ2ApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGtleSA9ICgwLCByZXNvbHZlXzEubm9ybWFsaXplSWQpKGtleSB8fCBpZCk7XG4gICAgICAgIHRoaXMuX2NoZWNrVW5pcXVlKGtleSk7XG4gICAgICAgIHRoaXMuc2NoZW1hc1trZXldID0gdGhpcy5fYWRkU2NoZW1hKHNjaGVtYSwgX21ldGEsIGtleSwgX3ZhbGlkYXRlU2NoZW1hLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8vIEFkZCBzY2hlbWEgdGhhdCB3aWxsIGJlIHVzZWQgdG8gdmFsaWRhdGUgb3RoZXIgc2NoZW1hc1xuICAgIC8vIG9wdGlvbnMgaW4gTUVUQV9JR05PUkVfT1BUSU9OUyBhcmUgYWx3YXkgc2V0IHRvIGZhbHNlXG4gICAgYWRkTWV0YVNjaGVtYShzY2hlbWEsIGtleSwgLy8gc2NoZW1hIGtleVxuICAgIF92YWxpZGF0ZVNjaGVtYSA9IHRoaXMub3B0cy52YWxpZGF0ZVNjaGVtYSAvLyBmYWxzZSB0byBza2lwIHNjaGVtYSB2YWxpZGF0aW9uLCBjYW4gYmUgdXNlZCB0byBvdmVycmlkZSB2YWxpZGF0ZVNjaGVtYSBvcHRpb24gZm9yIG1ldGEtc2NoZW1hXG4gICAgKSB7XG4gICAgICAgIHRoaXMuYWRkU2NoZW1hKHNjaGVtYSwga2V5LCB0cnVlLCBfdmFsaWRhdGVTY2hlbWEpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLy8gIFZhbGlkYXRlIHNjaGVtYSBhZ2FpbnN0IGl0cyBtZXRhLXNjaGVtYVxuICAgIHZhbGlkYXRlU2NoZW1hKHNjaGVtYSwgdGhyb3dPckxvZ0Vycm9yKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2NoZW1hID09IFwiYm9vbGVhblwiKVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIGxldCAkc2NoZW1hO1xuICAgICAgICAkc2NoZW1hID0gc2NoZW1hLiRzY2hlbWE7XG4gICAgICAgIGlmICgkc2NoZW1hICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mICRzY2hlbWEgIT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiJHNjaGVtYSBtdXN0IGJlIGEgc3RyaW5nXCIpO1xuICAgICAgICB9XG4gICAgICAgICRzY2hlbWEgPSAkc2NoZW1hIHx8IHRoaXMub3B0cy5kZWZhdWx0TWV0YSB8fCB0aGlzLmRlZmF1bHRNZXRhKCk7XG4gICAgICAgIGlmICghJHNjaGVtYSkge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIud2FybihcIm1ldGEtc2NoZW1hIG5vdCBhdmFpbGFibGVcIik7XG4gICAgICAgICAgICB0aGlzLmVycm9ycyA9IG51bGw7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2YWxpZCA9IHRoaXMudmFsaWRhdGUoJHNjaGVtYSwgc2NoZW1hKTtcbiAgICAgICAgaWYgKCF2YWxpZCAmJiB0aHJvd09yTG9nRXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBcInNjaGVtYSBpcyBpbnZhbGlkOiBcIiArIHRoaXMuZXJyb3JzVGV4dCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMub3B0cy52YWxpZGF0ZVNjaGVtYSA9PT0gXCJsb2dcIilcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihtZXNzYWdlKTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbGlkO1xuICAgIH1cbiAgICAvLyBHZXQgY29tcGlsZWQgc2NoZW1hIGJ5IGBrZXlgIG9yIGByZWZgLlxuICAgIC8vIChga2V5YCB0aGF0IHdhcyBwYXNzZWQgdG8gYGFkZFNjaGVtYWAgb3IgZnVsbCBzY2hlbWEgcmVmZXJlbmNlIC0gYHNjaGVtYS4kaWRgIG9yIHJlc29sdmVkIGlkKVxuICAgIGdldFNjaGVtYShrZXlSZWYpIHtcbiAgICAgICAgbGV0IHNjaDtcbiAgICAgICAgd2hpbGUgKHR5cGVvZiAoc2NoID0gZ2V0U2NoRW52LmNhbGwodGhpcywga2V5UmVmKSkgPT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgIGtleVJlZiA9IHNjaDtcbiAgICAgICAgaWYgKHNjaCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjb25zdCB7IHNjaGVtYUlkIH0gPSB0aGlzLm9wdHM7XG4gICAgICAgICAgICBjb25zdCByb290ID0gbmV3IGNvbXBpbGVfMS5TY2hlbWFFbnYoeyBzY2hlbWE6IHt9LCBzY2hlbWFJZCB9KTtcbiAgICAgICAgICAgIHNjaCA9IGNvbXBpbGVfMS5yZXNvbHZlU2NoZW1hLmNhbGwodGhpcywgcm9vdCwga2V5UmVmKTtcbiAgICAgICAgICAgIGlmICghc2NoKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIHRoaXMucmVmc1trZXlSZWZdID0gc2NoO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoc2NoLnZhbGlkYXRlIHx8IHRoaXMuX2NvbXBpbGVTY2hlbWFFbnYoc2NoKSk7XG4gICAgfVxuICAgIC8vIFJlbW92ZSBjYWNoZWQgc2NoZW1hKHMpLlxuICAgIC8vIElmIG5vIHBhcmFtZXRlciBpcyBwYXNzZWQgYWxsIHNjaGVtYXMgYnV0IG1ldGEtc2NoZW1hcyBhcmUgcmVtb3ZlZC5cbiAgICAvLyBJZiBSZWdFeHAgaXMgcGFzc2VkIGFsbCBzY2hlbWFzIHdpdGgga2V5L2lkIG1hdGNoaW5nIHBhdHRlcm4gYnV0IG1ldGEtc2NoZW1hcyBhcmUgcmVtb3ZlZC5cbiAgICAvLyBFdmVuIGlmIHNjaGVtYSBpcyByZWZlcmVuY2VkIGJ5IG90aGVyIHNjaGVtYXMgaXQgc3RpbGwgY2FuIGJlIHJlbW92ZWQgYXMgb3RoZXIgc2NoZW1hcyBoYXZlIGxvY2FsIHJlZmVyZW5jZXMuXG4gICAgcmVtb3ZlU2NoZW1hKHNjaGVtYUtleVJlZikge1xuICAgICAgICBpZiAoc2NoZW1hS2V5UmVmIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICB0aGlzLl9yZW1vdmVBbGxTY2hlbWFzKHRoaXMuc2NoZW1hcywgc2NoZW1hS2V5UmVmKTtcbiAgICAgICAgICAgIHRoaXMuX3JlbW92ZUFsbFNjaGVtYXModGhpcy5yZWZzLCBzY2hlbWFLZXlSZWYpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgc3dpdGNoICh0eXBlb2Ygc2NoZW1hS2V5UmVmKSB7XG4gICAgICAgICAgICBjYXNlIFwidW5kZWZpbmVkXCI6XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlQWxsU2NoZW1hcyh0aGlzLnNjaGVtYXMpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUFsbFNjaGVtYXModGhpcy5yZWZzKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9jYWNoZS5jbGVhcigpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgY2FzZSBcInN0cmluZ1wiOiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NoID0gZ2V0U2NoRW52LmNhbGwodGhpcywgc2NoZW1hS2V5UmVmKTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNjaCA9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYWNoZS5kZWxldGUoc2NoLnNjaGVtYSk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuc2NoZW1hc1tzY2hlbWFLZXlSZWZdO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJlZnNbc2NoZW1hS2V5UmVmXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgXCJvYmplY3RcIjoge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNhY2hlS2V5ID0gc2NoZW1hS2V5UmVmO1xuICAgICAgICAgICAgICAgIHRoaXMuX2NhY2hlLmRlbGV0ZShjYWNoZUtleSk7XG4gICAgICAgICAgICAgICAgbGV0IGlkID0gc2NoZW1hS2V5UmVmW3RoaXMub3B0cy5zY2hlbWFJZF07XG4gICAgICAgICAgICAgICAgaWYgKGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlkID0gKDAsIHJlc29sdmVfMS5ub3JtYWxpemVJZCkoaWQpO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5zY2hlbWFzW2lkXTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVmc1tpZF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJhanYucmVtb3ZlU2NoZW1hOiBpbnZhbGlkIHBhcmFtZXRlclwiKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBhZGQgXCJ2b2NhYnVsYXJ5XCIgLSBhIGNvbGxlY3Rpb24gb2Yga2V5d29yZHNcbiAgICBhZGRWb2NhYnVsYXJ5KGRlZmluaXRpb25zKSB7XG4gICAgICAgIGZvciAoY29uc3QgZGVmIG9mIGRlZmluaXRpb25zKVxuICAgICAgICAgICAgdGhpcy5hZGRLZXl3b3JkKGRlZik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBhZGRLZXl3b3JkKGt3ZE9yRGVmLCBkZWYgLy8gZGVwcmVjYXRlZFxuICAgICkge1xuICAgICAgICBsZXQga2V5d29yZDtcbiAgICAgICAgaWYgKHR5cGVvZiBrd2RPckRlZiA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICBrZXl3b3JkID0ga3dkT3JEZWY7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRlZiA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIud2FybihcInRoZXNlIHBhcmFtZXRlcnMgYXJlIGRlcHJlY2F0ZWQsIHNlZSBkb2NzIGZvciBhZGRLZXl3b3JkXCIpO1xuICAgICAgICAgICAgICAgIGRlZi5rZXl3b3JkID0ga2V5d29yZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2Yga3dkT3JEZWYgPT0gXCJvYmplY3RcIiAmJiBkZWYgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgZGVmID0ga3dkT3JEZWY7XG4gICAgICAgICAgICBrZXl3b3JkID0gZGVmLmtleXdvcmQ7XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShrZXl3b3JkKSAmJiAha2V5d29yZC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJhZGRLZXl3b3Jkczoga2V5d29yZCBtdXN0IGJlIHN0cmluZyBvciBub24tZW1wdHkgYXJyYXlcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIGFkZEtleXdvcmRzIHBhcmFtZXRlcnNcIik7XG4gICAgICAgIH1cbiAgICAgICAgY2hlY2tLZXl3b3JkLmNhbGwodGhpcywga2V5d29yZCwgZGVmKTtcbiAgICAgICAgaWYgKCFkZWYpIHtcbiAgICAgICAgICAgICgwLCB1dGlsXzEuZWFjaEl0ZW0pKGtleXdvcmQsIChrd2QpID0+IGFkZFJ1bGUuY2FsbCh0aGlzLCBrd2QpKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGtleXdvcmRNZXRhc2NoZW1hLmNhbGwodGhpcywgZGVmKTtcbiAgICAgICAgY29uc3QgZGVmaW5pdGlvbiA9IHtcbiAgICAgICAgICAgIC4uLmRlZixcbiAgICAgICAgICAgIHR5cGU6ICgwLCBkYXRhVHlwZV8xLmdldEpTT05UeXBlcykoZGVmLnR5cGUpLFxuICAgICAgICAgICAgc2NoZW1hVHlwZTogKDAsIGRhdGFUeXBlXzEuZ2V0SlNPTlR5cGVzKShkZWYuc2NoZW1hVHlwZSksXG4gICAgICAgIH07XG4gICAgICAgICgwLCB1dGlsXzEuZWFjaEl0ZW0pKGtleXdvcmQsIGRlZmluaXRpb24udHlwZS5sZW5ndGggPT09IDBcbiAgICAgICAgICAgID8gKGspID0+IGFkZFJ1bGUuY2FsbCh0aGlzLCBrLCBkZWZpbml0aW9uKVxuICAgICAgICAgICAgOiAoaykgPT4gZGVmaW5pdGlvbi50eXBlLmZvckVhY2goKHQpID0+IGFkZFJ1bGUuY2FsbCh0aGlzLCBrLCBkZWZpbml0aW9uLCB0KSkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgZ2V0S2V5d29yZChrZXl3b3JkKSB7XG4gICAgICAgIGNvbnN0IHJ1bGUgPSB0aGlzLlJVTEVTLmFsbFtrZXl3b3JkXTtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBydWxlID09IFwib2JqZWN0XCIgPyBydWxlLmRlZmluaXRpb24gOiAhIXJ1bGU7XG4gICAgfVxuICAgIC8vIFJlbW92ZSBrZXl3b3JkXG4gICAgcmVtb3ZlS2V5d29yZChrZXl3b3JkKSB7XG4gICAgICAgIC8vIFRPRE8gcmV0dXJuIHR5cGUgc2hvdWxkIGJlIEFqdlxuICAgICAgICBjb25zdCB7IFJVTEVTIH0gPSB0aGlzO1xuICAgICAgICBkZWxldGUgUlVMRVMua2V5d29yZHNba2V5d29yZF07XG4gICAgICAgIGRlbGV0ZSBSVUxFUy5hbGxba2V5d29yZF07XG4gICAgICAgIGZvciAoY29uc3QgZ3JvdXAgb2YgUlVMRVMucnVsZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGkgPSBncm91cC5ydWxlcy5maW5kSW5kZXgoKHJ1bGUpID0+IHJ1bGUua2V5d29yZCA9PT0ga2V5d29yZCk7XG4gICAgICAgICAgICBpZiAoaSA+PSAwKVxuICAgICAgICAgICAgICAgIGdyb3VwLnJ1bGVzLnNwbGljZShpLCAxKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLy8gQWRkIGZvcm1hdFxuICAgIGFkZEZvcm1hdChuYW1lLCBmb3JtYXQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBmb3JtYXQgPT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgIGZvcm1hdCA9IG5ldyBSZWdFeHAoZm9ybWF0KTtcbiAgICAgICAgdGhpcy5mb3JtYXRzW25hbWVdID0gZm9ybWF0O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgZXJyb3JzVGV4dChlcnJvcnMgPSB0aGlzLmVycm9ycywgLy8gb3B0aW9uYWwgYXJyYXkgb2YgdmFsaWRhdGlvbiBlcnJvcnNcbiAgICB7IHNlcGFyYXRvciA9IFwiLCBcIiwgZGF0YVZhciA9IFwiZGF0YVwiIH0gPSB7fSAvLyBvcHRpb25hbCBvcHRpb25zIHdpdGggcHJvcGVydGllcyBgc2VwYXJhdG9yYCBhbmQgYGRhdGFWYXJgXG4gICAgKSB7XG4gICAgICAgIGlmICghZXJyb3JzIHx8IGVycm9ycy5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm4gXCJObyBlcnJvcnNcIjtcbiAgICAgICAgcmV0dXJuIGVycm9yc1xuICAgICAgICAgICAgLm1hcCgoZSkgPT4gYCR7ZGF0YVZhcn0ke2UuaW5zdGFuY2VQYXRofSAke2UubWVzc2FnZX1gKVxuICAgICAgICAgICAgLnJlZHVjZSgodGV4dCwgbXNnKSA9PiB0ZXh0ICsgc2VwYXJhdG9yICsgbXNnKTtcbiAgICB9XG4gICAgJGRhdGFNZXRhU2NoZW1hKG1ldGFTY2hlbWEsIGtleXdvcmRzSnNvblBvaW50ZXJzKSB7XG4gICAgICAgIGNvbnN0IHJ1bGVzID0gdGhpcy5SVUxFUy5hbGw7XG4gICAgICAgIG1ldGFTY2hlbWEgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KG1ldGFTY2hlbWEpKTtcbiAgICAgICAgZm9yIChjb25zdCBqc29uUG9pbnRlciBvZiBrZXl3b3Jkc0pzb25Qb2ludGVycykge1xuICAgICAgICAgICAgY29uc3Qgc2VnbWVudHMgPSBqc29uUG9pbnRlci5zcGxpdChcIi9cIikuc2xpY2UoMSk7IC8vIGZpcnN0IHNlZ21lbnQgaXMgYW4gZW1wdHkgc3RyaW5nXG4gICAgICAgICAgICBsZXQga2V5d29yZHMgPSBtZXRhU2NoZW1hO1xuICAgICAgICAgICAgZm9yIChjb25zdCBzZWcgb2Ygc2VnbWVudHMpXG4gICAgICAgICAgICAgICAga2V5d29yZHMgPSBrZXl3b3Jkc1tzZWddO1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gcnVsZXMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBydWxlID0gcnVsZXNba2V5XTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHJ1bGUgIT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgY29uc3QgeyAkZGF0YSB9ID0gcnVsZS5kZWZpbml0aW9uO1xuICAgICAgICAgICAgICAgIGNvbnN0IHNjaGVtYSA9IGtleXdvcmRzW2tleV07XG4gICAgICAgICAgICAgICAgaWYgKCRkYXRhICYmIHNjaGVtYSlcbiAgICAgICAgICAgICAgICAgICAga2V5d29yZHNba2V5XSA9IHNjaGVtYU9yRGF0YShzY2hlbWEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXRhU2NoZW1hO1xuICAgIH1cbiAgICBfcmVtb3ZlQWxsU2NoZW1hcyhzY2hlbWFzLCByZWdleCkge1xuICAgICAgICBmb3IgKGNvbnN0IGtleVJlZiBpbiBzY2hlbWFzKSB7XG4gICAgICAgICAgICBjb25zdCBzY2ggPSBzY2hlbWFzW2tleVJlZl07XG4gICAgICAgICAgICBpZiAoIXJlZ2V4IHx8IHJlZ2V4LnRlc3Qoa2V5UmVmKSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc2NoID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNjaGVtYXNba2V5UmVmXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoc2NoICYmICFzY2gubWV0YSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYWNoZS5kZWxldGUoc2NoLnNjaGVtYSk7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzY2hlbWFzW2tleVJlZl07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIF9hZGRTY2hlbWEoc2NoZW1hLCBtZXRhLCBiYXNlSWQsIHZhbGlkYXRlU2NoZW1hID0gdGhpcy5vcHRzLnZhbGlkYXRlU2NoZW1hLCBhZGRTY2hlbWEgPSB0aGlzLm9wdHMuYWRkVXNlZFNjaGVtYSkge1xuICAgICAgICBsZXQgaWQ7XG4gICAgICAgIGNvbnN0IHsgc2NoZW1hSWQgfSA9IHRoaXMub3B0cztcbiAgICAgICAgaWYgKHR5cGVvZiBzY2hlbWEgPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgaWQgPSBzY2hlbWFbc2NoZW1hSWRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMub3B0cy5qdGQpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwic2NoZW1hIG11c3QgYmUgb2JqZWN0XCIpO1xuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIHNjaGVtYSAhPSBcImJvb2xlYW5cIilcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJzY2hlbWEgbXVzdCBiZSBvYmplY3Qgb3IgYm9vbGVhblwiKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgc2NoID0gdGhpcy5fY2FjaGUuZ2V0KHNjaGVtYSk7XG4gICAgICAgIGlmIChzY2ggIT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIHJldHVybiBzY2g7XG4gICAgICAgIGJhc2VJZCA9ICgwLCByZXNvbHZlXzEubm9ybWFsaXplSWQpKGlkIHx8IGJhc2VJZCk7XG4gICAgICAgIGNvbnN0IGxvY2FsUmVmcyA9IHJlc29sdmVfMS5nZXRTY2hlbWFSZWZzLmNhbGwodGhpcywgc2NoZW1hLCBiYXNlSWQpO1xuICAgICAgICBzY2ggPSBuZXcgY29tcGlsZV8xLlNjaGVtYUVudih7IHNjaGVtYSwgc2NoZW1hSWQsIG1ldGEsIGJhc2VJZCwgbG9jYWxSZWZzIH0pO1xuICAgICAgICB0aGlzLl9jYWNoZS5zZXQoc2NoLnNjaGVtYSwgc2NoKTtcbiAgICAgICAgaWYgKGFkZFNjaGVtYSAmJiAhYmFzZUlkLnN0YXJ0c1dpdGgoXCIjXCIpKSB7XG4gICAgICAgICAgICAvLyBUT0RPIGF0bSBpdCBpcyBhbGxvd2VkIHRvIG92ZXJ3cml0ZSBzY2hlbWFzIHdpdGhvdXQgaWQgKGluc3RlYWQgb2Ygbm90IGFkZGluZyB0aGVtKVxuICAgICAgICAgICAgaWYgKGJhc2VJZClcbiAgICAgICAgICAgICAgICB0aGlzLl9jaGVja1VuaXF1ZShiYXNlSWQpO1xuICAgICAgICAgICAgdGhpcy5yZWZzW2Jhc2VJZF0gPSBzY2g7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbGlkYXRlU2NoZW1hKVxuICAgICAgICAgICAgdGhpcy52YWxpZGF0ZVNjaGVtYShzY2hlbWEsIHRydWUpO1xuICAgICAgICByZXR1cm4gc2NoO1xuICAgIH1cbiAgICBfY2hlY2tVbmlxdWUoaWQpIHtcbiAgICAgICAgaWYgKHRoaXMuc2NoZW1hc1tpZF0gfHwgdGhpcy5yZWZzW2lkXSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBzY2hlbWEgd2l0aCBrZXkgb3IgaWQgXCIke2lkfVwiIGFscmVhZHkgZXhpc3RzYCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgX2NvbXBpbGVTY2hlbWFFbnYoc2NoKSB7XG4gICAgICAgIGlmIChzY2gubWV0YSlcbiAgICAgICAgICAgIHRoaXMuX2NvbXBpbGVNZXRhU2NoZW1hKHNjaCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGNvbXBpbGVfMS5jb21waWxlU2NoZW1hLmNhbGwodGhpcywgc2NoKTtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgIGlmICghc2NoLnZhbGlkYXRlKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYWp2IGltcGxlbWVudGF0aW9uIGVycm9yXCIpO1xuICAgICAgICByZXR1cm4gc2NoLnZhbGlkYXRlO1xuICAgIH1cbiAgICBfY29tcGlsZU1ldGFTY2hlbWEoc2NoKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRPcHRzID0gdGhpcy5vcHRzO1xuICAgICAgICB0aGlzLm9wdHMgPSB0aGlzLl9tZXRhT3B0cztcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbXBpbGVfMS5jb21waWxlU2NoZW1hLmNhbGwodGhpcywgc2NoKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRoaXMub3B0cyA9IGN1cnJlbnRPcHRzO1xuICAgICAgICB9XG4gICAgfVxufVxuZXhwb3J0cy5kZWZhdWx0ID0gQWp2O1xuQWp2LlZhbGlkYXRpb25FcnJvciA9IHZhbGlkYXRpb25fZXJyb3JfMS5kZWZhdWx0O1xuQWp2Lk1pc3NpbmdSZWZFcnJvciA9IHJlZl9lcnJvcl8xLmRlZmF1bHQ7XG5mdW5jdGlvbiBjaGVja09wdGlvbnMoY2hlY2tPcHRzLCBvcHRpb25zLCBtc2csIGxvZyA9IFwiZXJyb3JcIikge1xuICAgIGZvciAoY29uc3Qga2V5IGluIGNoZWNrT3B0cykge1xuICAgICAgICBjb25zdCBvcHQgPSBrZXk7XG4gICAgICAgIGlmIChvcHQgaW4gb3B0aW9ucylcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyW2xvZ10oYCR7bXNnfTogb3B0aW9uICR7a2V5fS4gJHtjaGVja09wdHNbb3B0XX1gKTtcbiAgICB9XG59XG5mdW5jdGlvbiBnZXRTY2hFbnYoa2V5UmVmKSB7XG4gICAga2V5UmVmID0gKDAsIHJlc29sdmVfMS5ub3JtYWxpemVJZCkoa2V5UmVmKTsgLy8gVE9ETyB0ZXN0cyBmYWlsIHdpdGhvdXQgdGhpcyBsaW5lXG4gICAgcmV0dXJuIHRoaXMuc2NoZW1hc1trZXlSZWZdIHx8IHRoaXMucmVmc1trZXlSZWZdO1xufVxuZnVuY3Rpb24gYWRkSW5pdGlhbFNjaGVtYXMoKSB7XG4gICAgY29uc3Qgb3B0c1NjaGVtYXMgPSB0aGlzLm9wdHMuc2NoZW1hcztcbiAgICBpZiAoIW9wdHNTY2hlbWFzKVxuICAgICAgICByZXR1cm47XG4gICAgaWYgKEFycmF5LmlzQXJyYXkob3B0c1NjaGVtYXMpKVxuICAgICAgICB0aGlzLmFkZFNjaGVtYShvcHRzU2NoZW1hcyk7XG4gICAgZWxzZVxuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBvcHRzU2NoZW1hcylcbiAgICAgICAgICAgIHRoaXMuYWRkU2NoZW1hKG9wdHNTY2hlbWFzW2tleV0sIGtleSk7XG59XG5mdW5jdGlvbiBhZGRJbml0aWFsRm9ybWF0cygpIHtcbiAgICBmb3IgKGNvbnN0IG5hbWUgaW4gdGhpcy5vcHRzLmZvcm1hdHMpIHtcbiAgICAgICAgY29uc3QgZm9ybWF0ID0gdGhpcy5vcHRzLmZvcm1hdHNbbmFtZV07XG4gICAgICAgIGlmIChmb3JtYXQpXG4gICAgICAgICAgICB0aGlzLmFkZEZvcm1hdChuYW1lLCBmb3JtYXQpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGFkZEluaXRpYWxLZXl3b3JkcyhkZWZzKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZGVmcykpIHtcbiAgICAgICAgdGhpcy5hZGRWb2NhYnVsYXJ5KGRlZnMpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMubG9nZ2VyLndhcm4oXCJrZXl3b3JkcyBvcHRpb24gYXMgbWFwIGlzIGRlcHJlY2F0ZWQsIHBhc3MgYXJyYXlcIik7XG4gICAgZm9yIChjb25zdCBrZXl3b3JkIGluIGRlZnMpIHtcbiAgICAgICAgY29uc3QgZGVmID0gZGVmc1trZXl3b3JkXTtcbiAgICAgICAgaWYgKCFkZWYua2V5d29yZClcbiAgICAgICAgICAgIGRlZi5rZXl3b3JkID0ga2V5d29yZDtcbiAgICAgICAgdGhpcy5hZGRLZXl3b3JkKGRlZik7XG4gICAgfVxufVxuZnVuY3Rpb24gZ2V0TWV0YVNjaGVtYU9wdGlvbnMoKSB7XG4gICAgY29uc3QgbWV0YU9wdHMgPSB7IC4uLnRoaXMub3B0cyB9O1xuICAgIGZvciAoY29uc3Qgb3B0IG9mIE1FVEFfSUdOT1JFX09QVElPTlMpXG4gICAgICAgIGRlbGV0ZSBtZXRhT3B0c1tvcHRdO1xuICAgIHJldHVybiBtZXRhT3B0cztcbn1cbmNvbnN0IG5vTG9ncyA9IHsgbG9nKCkgeyB9LCB3YXJuKCkgeyB9LCBlcnJvcigpIHsgfSB9O1xuZnVuY3Rpb24gZ2V0TG9nZ2VyKGxvZ2dlcikge1xuICAgIGlmIChsb2dnZXIgPT09IGZhbHNlKVxuICAgICAgICByZXR1cm4gbm9Mb2dzO1xuICAgIGlmIChsb2dnZXIgPT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuIGNvbnNvbGU7XG4gICAgaWYgKGxvZ2dlci5sb2cgJiYgbG9nZ2VyLndhcm4gJiYgbG9nZ2VyLmVycm9yKVxuICAgICAgICByZXR1cm4gbG9nZ2VyO1xuICAgIHRocm93IG5ldyBFcnJvcihcImxvZ2dlciBtdXN0IGltcGxlbWVudCBsb2csIHdhcm4gYW5kIGVycm9yIG1ldGhvZHNcIik7XG59XG5jb25zdCBLRVlXT1JEX05BTUUgPSAvXlthLXpfJF1bYS16MC05XyQ6LV0qJC9pO1xuZnVuY3Rpb24gY2hlY2tLZXl3b3JkKGtleXdvcmQsIGRlZikge1xuICAgIGNvbnN0IHsgUlVMRVMgfSA9IHRoaXM7XG4gICAgKDAsIHV0aWxfMS5lYWNoSXRlbSkoa2V5d29yZCwgKGt3ZCkgPT4ge1xuICAgICAgICBpZiAoUlVMRVMua2V5d29yZHNba3dkXSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgS2V5d29yZCAke2t3ZH0gaXMgYWxyZWFkeSBkZWZpbmVkYCk7XG4gICAgICAgIGlmICghS0VZV09SRF9OQU1FLnRlc3Qoa3dkKSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgS2V5d29yZCAke2t3ZH0gaGFzIGludmFsaWQgbmFtZWApO1xuICAgIH0pO1xuICAgIGlmICghZGVmKVxuICAgICAgICByZXR1cm47XG4gICAgaWYgKGRlZi4kZGF0YSAmJiAhKFwiY29kZVwiIGluIGRlZiB8fCBcInZhbGlkYXRlXCIgaW4gZGVmKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJyRkYXRhIGtleXdvcmQgbXVzdCBoYXZlIFwiY29kZVwiIG9yIFwidmFsaWRhdGVcIiBmdW5jdGlvbicpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGFkZFJ1bGUoa2V5d29yZCwgZGVmaW5pdGlvbiwgZGF0YVR5cGUpIHtcbiAgICB2YXIgX2E7XG4gICAgY29uc3QgcG9zdCA9IGRlZmluaXRpb24gPT09IG51bGwgfHwgZGVmaW5pdGlvbiA9PT0gdm9pZCAwID8gdm9pZCAwIDogZGVmaW5pdGlvbi5wb3N0O1xuICAgIGlmIChkYXRhVHlwZSAmJiBwb3N0KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2tleXdvcmQgd2l0aCBcInBvc3RcIiBmbGFnIGNhbm5vdCBoYXZlIFwidHlwZVwiJyk7XG4gICAgY29uc3QgeyBSVUxFUyB9ID0gdGhpcztcbiAgICBsZXQgcnVsZUdyb3VwID0gcG9zdCA/IFJVTEVTLnBvc3QgOiBSVUxFUy5ydWxlcy5maW5kKCh7IHR5cGU6IHQgfSkgPT4gdCA9PT0gZGF0YVR5cGUpO1xuICAgIGlmICghcnVsZUdyb3VwKSB7XG4gICAgICAgIHJ1bGVHcm91cCA9IHsgdHlwZTogZGF0YVR5cGUsIHJ1bGVzOiBbXSB9O1xuICAgICAgICBSVUxFUy5ydWxlcy5wdXNoKHJ1bGVHcm91cCk7XG4gICAgfVxuICAgIFJVTEVTLmtleXdvcmRzW2tleXdvcmRdID0gdHJ1ZTtcbiAgICBpZiAoIWRlZmluaXRpb24pXG4gICAgICAgIHJldHVybjtcbiAgICBjb25zdCBydWxlID0ge1xuICAgICAgICBrZXl3b3JkLFxuICAgICAgICBkZWZpbml0aW9uOiB7XG4gICAgICAgICAgICAuLi5kZWZpbml0aW9uLFxuICAgICAgICAgICAgdHlwZTogKDAsIGRhdGFUeXBlXzEuZ2V0SlNPTlR5cGVzKShkZWZpbml0aW9uLnR5cGUpLFxuICAgICAgICAgICAgc2NoZW1hVHlwZTogKDAsIGRhdGFUeXBlXzEuZ2V0SlNPTlR5cGVzKShkZWZpbml0aW9uLnNjaGVtYVR5cGUpLFxuICAgICAgICB9LFxuICAgIH07XG4gICAgaWYgKGRlZmluaXRpb24uYmVmb3JlKVxuICAgICAgICBhZGRCZWZvcmVSdWxlLmNhbGwodGhpcywgcnVsZUdyb3VwLCBydWxlLCBkZWZpbml0aW9uLmJlZm9yZSk7XG4gICAgZWxzZVxuICAgICAgICBydWxlR3JvdXAucnVsZXMucHVzaChydWxlKTtcbiAgICBSVUxFUy5hbGxba2V5d29yZF0gPSBydWxlO1xuICAgIChfYSA9IGRlZmluaXRpb24uaW1wbGVtZW50cykgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmZvckVhY2goKGt3ZCkgPT4gdGhpcy5hZGRLZXl3b3JkKGt3ZCkpO1xufVxuZnVuY3Rpb24gYWRkQmVmb3JlUnVsZShydWxlR3JvdXAsIHJ1bGUsIGJlZm9yZSkge1xuICAgIGNvbnN0IGkgPSBydWxlR3JvdXAucnVsZXMuZmluZEluZGV4KChfcnVsZSkgPT4gX3J1bGUua2V5d29yZCA9PT0gYmVmb3JlKTtcbiAgICBpZiAoaSA+PSAwKSB7XG4gICAgICAgIHJ1bGVHcm91cC5ydWxlcy5zcGxpY2UoaSwgMCwgcnVsZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBydWxlR3JvdXAucnVsZXMucHVzaChydWxlKTtcbiAgICAgICAgdGhpcy5sb2dnZXIud2FybihgcnVsZSAke2JlZm9yZX0gaXMgbm90IGRlZmluZWRgKTtcbiAgICB9XG59XG5mdW5jdGlvbiBrZXl3b3JkTWV0YXNjaGVtYShkZWYpIHtcbiAgICBsZXQgeyBtZXRhU2NoZW1hIH0gPSBkZWY7XG4gICAgaWYgKG1ldGFTY2hlbWEgPT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuO1xuICAgIGlmIChkZWYuJGRhdGEgJiYgdGhpcy5vcHRzLiRkYXRhKVxuICAgICAgICBtZXRhU2NoZW1hID0gc2NoZW1hT3JEYXRhKG1ldGFTY2hlbWEpO1xuICAgIGRlZi52YWxpZGF0ZVNjaGVtYSA9IHRoaXMuY29tcGlsZShtZXRhU2NoZW1hLCB0cnVlKTtcbn1cbmNvbnN0ICRkYXRhUmVmID0ge1xuICAgICRyZWY6IFwiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2Fqdi12YWxpZGF0b3IvYWp2L21hc3Rlci9saWIvcmVmcy9kYXRhLmpzb24jXCIsXG59O1xuZnVuY3Rpb24gc2NoZW1hT3JEYXRhKHNjaGVtYSkge1xuICAgIHJldHVybiB7IGFueU9mOiBbc2NoZW1hLCAkZGF0YVJlZl0gfTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWNvcmUuanMubWFwIiwibW9kdWxlLmV4cG9ydHM9e1xuICBcIiRpZFwiOiBcImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9hanYtdmFsaWRhdG9yL2Fqdi9tYXN0ZXIvbGliL3JlZnMvZGF0YS5qc29uI1wiLFxuICBcImRlc2NyaXB0aW9uXCI6IFwiTWV0YS1zY2hlbWEgZm9yICRkYXRhIHJlZmVyZW5jZSAoSlNPTiBBbnlTY2hlbWEgZXh0ZW5zaW9uIHByb3Bvc2FsKVwiLFxuICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgXCJyZXF1aXJlZFwiOiBbXCIkZGF0YVwiXSxcbiAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICBcIiRkYXRhXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgXCJhbnlPZlwiOiBbe1wiZm9ybWF0XCI6IFwicmVsYXRpdmUtanNvbi1wb2ludGVyXCJ9LCB7XCJmb3JtYXRcIjogXCJqc29uLXBvaW50ZXJcIn1dXG4gICAgfVxuICB9LFxuICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IGZhbHNlXG59XG4iLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IG1ldGFTY2hlbWEgPSByZXF1aXJlKFwiLi9zY2hlbWEuanNvblwiKTtcbmNvbnN0IGFwcGxpY2F0b3IgPSByZXF1aXJlKFwiLi9tZXRhL2FwcGxpY2F0b3IuanNvblwiKTtcbmNvbnN0IGNvbnRlbnQgPSByZXF1aXJlKFwiLi9tZXRhL2NvbnRlbnQuanNvblwiKTtcbmNvbnN0IGNvcmUgPSByZXF1aXJlKFwiLi9tZXRhL2NvcmUuanNvblwiKTtcbmNvbnN0IGZvcm1hdCA9IHJlcXVpcmUoXCIuL21ldGEvZm9ybWF0Lmpzb25cIik7XG5jb25zdCBtZXRhZGF0YSA9IHJlcXVpcmUoXCIuL21ldGEvbWV0YS1kYXRhLmpzb25cIik7XG5jb25zdCB2YWxpZGF0aW9uID0gcmVxdWlyZShcIi4vbWV0YS92YWxpZGF0aW9uLmpzb25cIik7XG5jb25zdCBNRVRBX1NVUFBPUlRfREFUQSA9IFtcIi9wcm9wZXJ0aWVzXCJdO1xuZnVuY3Rpb24gYWRkTWV0YVNjaGVtYTIwMTkoJGRhdGEpIHtcbiAgICA7XG4gICAgW1xuICAgICAgICBtZXRhU2NoZW1hLFxuICAgICAgICBhcHBsaWNhdG9yLFxuICAgICAgICBjb250ZW50LFxuICAgICAgICBjb3JlLFxuICAgICAgICB3aXRoJGRhdGEodGhpcywgZm9ybWF0KSxcbiAgICAgICAgbWV0YWRhdGEsXG4gICAgICAgIHdpdGgkZGF0YSh0aGlzLCB2YWxpZGF0aW9uKSxcbiAgICBdLmZvckVhY2goKHNjaCkgPT4gdGhpcy5hZGRNZXRhU2NoZW1hKHNjaCwgdW5kZWZpbmVkLCBmYWxzZSkpO1xuICAgIHJldHVybiB0aGlzO1xuICAgIGZ1bmN0aW9uIHdpdGgkZGF0YShhanYsIHNjaCkge1xuICAgICAgICByZXR1cm4gJGRhdGEgPyBhanYuJGRhdGFNZXRhU2NoZW1hKHNjaCwgTUVUQV9TVVBQT1JUX0RBVEEpIDogc2NoO1xuICAgIH1cbn1cbmV4cG9ydHMuZGVmYXVsdCA9IGFkZE1ldGFTY2hlbWEyMDE5O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwIiwibW9kdWxlLmV4cG9ydHM9e1xuICBcIiRzY2hlbWFcIjogXCJodHRwczovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC8yMDE5LTA5L3NjaGVtYVwiLFxuICBcIiRpZFwiOiBcImh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMTktMDkvbWV0YS9hcHBsaWNhdG9yXCIsXG4gIFwiJHZvY2FidWxhcnlcIjoge1xuICAgIFwiaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQvMjAxOS0wOS92b2NhYi9hcHBsaWNhdG9yXCI6IHRydWVcbiAgfSxcbiAgXCIkcmVjdXJzaXZlQW5jaG9yXCI6IHRydWUsXG5cbiAgXCJ0aXRsZVwiOiBcIkFwcGxpY2F0b3Igdm9jYWJ1bGFyeSBtZXRhLXNjaGVtYVwiLFxuICBcInR5cGVcIjogW1wib2JqZWN0XCIsIFwiYm9vbGVhblwiXSxcbiAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICBcImFkZGl0aW9uYWxJdGVtc1wiOiB7XCIkcmVjdXJzaXZlUmVmXCI6IFwiI1wifSxcbiAgICBcInVuZXZhbHVhdGVkSXRlbXNcIjoge1wiJHJlY3Vyc2l2ZVJlZlwiOiBcIiNcIn0sXG4gICAgXCJpdGVtc1wiOiB7XG4gICAgICBcImFueU9mXCI6IFt7XCIkcmVjdXJzaXZlUmVmXCI6IFwiI1wifSwge1wiJHJlZlwiOiBcIiMvJGRlZnMvc2NoZW1hQXJyYXlcIn1dXG4gICAgfSxcbiAgICBcImNvbnRhaW5zXCI6IHtcIiRyZWN1cnNpdmVSZWZcIjogXCIjXCJ9LFxuICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1wiJHJlY3Vyc2l2ZVJlZlwiOiBcIiNcIn0sXG4gICAgXCJ1bmV2YWx1YXRlZFByb3BlcnRpZXNcIjoge1wiJHJlY3Vyc2l2ZVJlZlwiOiBcIiNcIn0sXG4gICAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XCIkcmVjdXJzaXZlUmVmXCI6IFwiI1wifSxcbiAgICAgIFwiZGVmYXVsdFwiOiB7fVxuICAgIH0sXG4gICAgXCJwYXR0ZXJuUHJvcGVydGllc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1wiJHJlY3Vyc2l2ZVJlZlwiOiBcIiNcIn0sXG4gICAgICBcInByb3BlcnR5TmFtZXNcIjoge1wiZm9ybWF0XCI6IFwicmVnZXhcIn0sXG4gICAgICBcImRlZmF1bHRcIjoge31cbiAgICB9LFxuICAgIFwiZGVwZW5kZW50U2NoZW1hc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1xuICAgICAgICBcIiRyZWN1cnNpdmVSZWZcIjogXCIjXCJcbiAgICAgIH1cbiAgICB9LFxuICAgIFwicHJvcGVydHlOYW1lc1wiOiB7XCIkcmVjdXJzaXZlUmVmXCI6IFwiI1wifSxcbiAgICBcImlmXCI6IHtcIiRyZWN1cnNpdmVSZWZcIjogXCIjXCJ9LFxuICAgIFwidGhlblwiOiB7XCIkcmVjdXJzaXZlUmVmXCI6IFwiI1wifSxcbiAgICBcImVsc2VcIjoge1wiJHJlY3Vyc2l2ZVJlZlwiOiBcIiNcIn0sXG4gICAgXCJhbGxPZlwiOiB7XCIkcmVmXCI6IFwiIy8kZGVmcy9zY2hlbWFBcnJheVwifSxcbiAgICBcImFueU9mXCI6IHtcIiRyZWZcIjogXCIjLyRkZWZzL3NjaGVtYUFycmF5XCJ9LFxuICAgIFwib25lT2ZcIjoge1wiJHJlZlwiOiBcIiMvJGRlZnMvc2NoZW1hQXJyYXlcIn0sXG4gICAgXCJub3RcIjoge1wiJHJlY3Vyc2l2ZVJlZlwiOiBcIiNcIn1cbiAgfSxcbiAgXCIkZGVmc1wiOiB7XG4gICAgXCJzY2hlbWFBcnJheVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJtaW5JdGVtc1wiOiAxLFxuICAgICAgXCJpdGVtc1wiOiB7XCIkcmVjdXJzaXZlUmVmXCI6IFwiI1wifVxuICAgIH1cbiAgfVxufVxuIiwibW9kdWxlLmV4cG9ydHM9e1xuICBcIiRzY2hlbWFcIjogXCJodHRwczovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC8yMDE5LTA5L3NjaGVtYVwiLFxuICBcIiRpZFwiOiBcImh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMTktMDkvbWV0YS9jb250ZW50XCIsXG4gIFwiJHZvY2FidWxhcnlcIjoge1xuICAgIFwiaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQvMjAxOS0wOS92b2NhYi9jb250ZW50XCI6IHRydWVcbiAgfSxcbiAgXCIkcmVjdXJzaXZlQW5jaG9yXCI6IHRydWUsXG5cbiAgXCJ0aXRsZVwiOiBcIkNvbnRlbnQgdm9jYWJ1bGFyeSBtZXRhLXNjaGVtYVwiLFxuXG4gIFwidHlwZVwiOiBbXCJvYmplY3RcIiwgXCJib29sZWFuXCJdLFxuICBcInByb3BlcnRpZXNcIjoge1xuICAgIFwiY29udGVudE1lZGlhVHlwZVwiOiB7XCJ0eXBlXCI6IFwic3RyaW5nXCJ9LFxuICAgIFwiY29udGVudEVuY29kaW5nXCI6IHtcInR5cGVcIjogXCJzdHJpbmdcIn0sXG4gICAgXCJjb250ZW50U2NoZW1hXCI6IHtcIiRyZWN1cnNpdmVSZWZcIjogXCIjXCJ9XG4gIH1cbn1cbiIsIm1vZHVsZS5leHBvcnRzPXtcbiAgXCIkc2NoZW1hXCI6IFwiaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQvMjAxOS0wOS9zY2hlbWFcIixcbiAgXCIkaWRcIjogXCJodHRwczovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC8yMDE5LTA5L21ldGEvY29yZVwiLFxuICBcIiR2b2NhYnVsYXJ5XCI6IHtcbiAgICBcImh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMTktMDkvdm9jYWIvY29yZVwiOiB0cnVlXG4gIH0sXG4gIFwiJHJlY3Vyc2l2ZUFuY2hvclwiOiB0cnVlLFxuXG4gIFwidGl0bGVcIjogXCJDb3JlIHZvY2FidWxhcnkgbWV0YS1zY2hlbWFcIixcbiAgXCJ0eXBlXCI6IFtcIm9iamVjdFwiLCBcImJvb2xlYW5cIl0sXG4gIFwicHJvcGVydGllc1wiOiB7XG4gICAgXCIkaWRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImZvcm1hdFwiOiBcInVyaS1yZWZlcmVuY2VcIixcbiAgICAgIFwiJGNvbW1lbnRcIjogXCJOb24tZW1wdHkgZnJhZ21lbnRzIG5vdCBhbGxvd2VkLlwiLFxuICAgICAgXCJwYXR0ZXJuXCI6IFwiXlteI10qIz8kXCJcbiAgICB9LFxuICAgIFwiJHNjaGVtYVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZm9ybWF0XCI6IFwidXJpXCJcbiAgICB9LFxuICAgIFwiJGFuY2hvclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwicGF0dGVyblwiOiBcIl5bQS1aYS16XVstQS1aYS16MC05LjpfXSokXCJcbiAgICB9LFxuICAgIFwiJHJlZlwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIixcbiAgICAgIFwiZm9ybWF0XCI6IFwidXJpLXJlZmVyZW5jZVwiXG4gICAgfSxcbiAgICBcIiRyZWN1cnNpdmVSZWZcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImZvcm1hdFwiOiBcInVyaS1yZWZlcmVuY2VcIlxuICAgIH0sXG4gICAgXCIkcmVjdXJzaXZlQW5jaG9yXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZVxuICAgIH0sXG4gICAgXCIkdm9jYWJ1bGFyeVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgIFwicHJvcGVydHlOYW1lc1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcInN0cmluZ1wiLFxuICAgICAgICBcImZvcm1hdFwiOiBcInVyaVwiXG4gICAgICB9LFxuICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XG4gICAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIlxuICAgICAgfVxuICAgIH0sXG4gICAgXCIkY29tbWVudFwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgIH0sXG4gICAgXCIkZGVmc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1wiJHJlY3Vyc2l2ZVJlZlwiOiBcIiNcIn0sXG4gICAgICBcImRlZmF1bHRcIjoge31cbiAgICB9XG4gIH1cbn1cbiIsIm1vZHVsZS5leHBvcnRzPXtcbiAgXCIkc2NoZW1hXCI6IFwiaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQvMjAxOS0wOS9zY2hlbWFcIixcbiAgXCIkaWRcIjogXCJodHRwczovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC8yMDE5LTA5L21ldGEvZm9ybWF0XCIsXG4gIFwiJHZvY2FidWxhcnlcIjoge1xuICAgIFwiaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQvMjAxOS0wOS92b2NhYi9mb3JtYXRcIjogdHJ1ZVxuICB9LFxuICBcIiRyZWN1cnNpdmVBbmNob3JcIjogdHJ1ZSxcblxuICBcInRpdGxlXCI6IFwiRm9ybWF0IHZvY2FidWxhcnkgbWV0YS1zY2hlbWFcIixcbiAgXCJ0eXBlXCI6IFtcIm9iamVjdFwiLCBcImJvb2xlYW5cIl0sXG4gIFwicHJvcGVydGllc1wiOiB7XG4gICAgXCJmb3JtYXRcIjoge1widHlwZVwiOiBcInN0cmluZ1wifVxuICB9XG59XG4iLCJtb2R1bGUuZXhwb3J0cz17XG4gIFwiJHNjaGVtYVwiOiBcImh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMTktMDkvc2NoZW1hXCIsXG4gIFwiJGlkXCI6IFwiaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQvMjAxOS0wOS9tZXRhL21ldGEtZGF0YVwiLFxuICBcIiR2b2NhYnVsYXJ5XCI6IHtcbiAgICBcImh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMTktMDkvdm9jYWIvbWV0YS1kYXRhXCI6IHRydWVcbiAgfSxcbiAgXCIkcmVjdXJzaXZlQW5jaG9yXCI6IHRydWUsXG5cbiAgXCJ0aXRsZVwiOiBcIk1ldGEtZGF0YSB2b2NhYnVsYXJ5IG1ldGEtc2NoZW1hXCIsXG5cbiAgXCJ0eXBlXCI6IFtcIm9iamVjdFwiLCBcImJvb2xlYW5cIl0sXG4gIFwicHJvcGVydGllc1wiOiB7XG4gICAgXCJ0aXRsZVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgIH0sXG4gICAgXCJkZXNjcmlwdGlvblwiOiB7XG4gICAgICBcInR5cGVcIjogXCJzdHJpbmdcIlxuICAgIH0sXG4gICAgXCJkZWZhdWx0XCI6IHRydWUsXG4gICAgXCJkZXByZWNhdGVkXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZVxuICAgIH0sXG4gICAgXCJyZWFkT25seVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2VcbiAgICB9LFxuICAgIFwid3JpdGVPbmx5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImJvb2xlYW5cIixcbiAgICAgIFwiZGVmYXVsdFwiOiBmYWxzZVxuICAgIH0sXG4gICAgXCJleGFtcGxlc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgXCJpdGVtc1wiOiB0cnVlXG4gICAgfVxuICB9XG59XG4iLCJtb2R1bGUuZXhwb3J0cz17XG4gIFwiJHNjaGVtYVwiOiBcImh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMTktMDkvc2NoZW1hXCIsXG4gIFwiJGlkXCI6IFwiaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQvMjAxOS0wOS9tZXRhL3ZhbGlkYXRpb25cIixcbiAgXCIkdm9jYWJ1bGFyeVwiOiB7XG4gICAgXCJodHRwczovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC8yMDE5LTA5L3ZvY2FiL3ZhbGlkYXRpb25cIjogdHJ1ZVxuICB9LFxuICBcIiRyZWN1cnNpdmVBbmNob3JcIjogdHJ1ZSxcblxuICBcInRpdGxlXCI6IFwiVmFsaWRhdGlvbiB2b2NhYnVsYXJ5IG1ldGEtc2NoZW1hXCIsXG4gIFwidHlwZVwiOiBbXCJvYmplY3RcIiwgXCJib29sZWFuXCJdLFxuICBcInByb3BlcnRpZXNcIjoge1xuICAgIFwibXVsdGlwbGVPZlwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIixcbiAgICAgIFwiZXhjbHVzaXZlTWluaW11bVwiOiAwXG4gICAgfSxcbiAgICBcIm1heGltdW1cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCJcbiAgICB9LFxuICAgIFwiZXhjbHVzaXZlTWF4aW11bVwiOiB7XG4gICAgICBcInR5cGVcIjogXCJudW1iZXJcIlxuICAgIH0sXG4gICAgXCJtaW5pbXVtXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcIm51bWJlclwiXG4gICAgfSxcbiAgICBcImV4Y2x1c2l2ZU1pbmltdW1cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwibnVtYmVyXCJcbiAgICB9LFxuICAgIFwibWF4TGVuZ3RoXCI6IHtcIiRyZWZcIjogXCIjLyRkZWZzL25vbk5lZ2F0aXZlSW50ZWdlclwifSxcbiAgICBcIm1pbkxlbmd0aFwiOiB7XCIkcmVmXCI6IFwiIy8kZGVmcy9ub25OZWdhdGl2ZUludGVnZXJEZWZhdWx0MFwifSxcbiAgICBcInBhdHRlcm5cIjoge1xuICAgICAgXCJ0eXBlXCI6IFwic3RyaW5nXCIsXG4gICAgICBcImZvcm1hdFwiOiBcInJlZ2V4XCJcbiAgICB9LFxuICAgIFwibWF4SXRlbXNcIjoge1wiJHJlZlwiOiBcIiMvJGRlZnMvbm9uTmVnYXRpdmVJbnRlZ2VyXCJ9LFxuICAgIFwibWluSXRlbXNcIjoge1wiJHJlZlwiOiBcIiMvJGRlZnMvbm9uTmVnYXRpdmVJbnRlZ2VyRGVmYXVsdDBcIn0sXG4gICAgXCJ1bmlxdWVJdGVtc1wiOiB7XG4gICAgICBcInR5cGVcIjogXCJib29sZWFuXCIsXG4gICAgICBcImRlZmF1bHRcIjogZmFsc2VcbiAgICB9LFxuICAgIFwibWF4Q29udGFpbnNcIjoge1wiJHJlZlwiOiBcIiMvJGRlZnMvbm9uTmVnYXRpdmVJbnRlZ2VyXCJ9LFxuICAgIFwibWluQ29udGFpbnNcIjoge1xuICAgICAgXCIkcmVmXCI6IFwiIy8kZGVmcy9ub25OZWdhdGl2ZUludGVnZXJcIixcbiAgICAgIFwiZGVmYXVsdFwiOiAxXG4gICAgfSxcbiAgICBcIm1heFByb3BlcnRpZXNcIjoge1wiJHJlZlwiOiBcIiMvJGRlZnMvbm9uTmVnYXRpdmVJbnRlZ2VyXCJ9LFxuICAgIFwibWluUHJvcGVydGllc1wiOiB7XCIkcmVmXCI6IFwiIy8kZGVmcy9ub25OZWdhdGl2ZUludGVnZXJEZWZhdWx0MFwifSxcbiAgICBcInJlcXVpcmVkXCI6IHtcIiRyZWZcIjogXCIjLyRkZWZzL3N0cmluZ0FycmF5XCJ9LFxuICAgIFwiZGVwZW5kZW50UmVxdWlyZWRcIjoge1xuICAgICAgXCJ0eXBlXCI6IFwib2JqZWN0XCIsXG4gICAgICBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCI6IHtcbiAgICAgICAgXCIkcmVmXCI6IFwiIy8kZGVmcy9zdHJpbmdBcnJheVwiXG4gICAgICB9XG4gICAgfSxcbiAgICBcImNvbnN0XCI6IHRydWUsXG4gICAgXCJlbnVtXCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcIml0ZW1zXCI6IHRydWVcbiAgICB9LFxuICAgIFwidHlwZVwiOiB7XG4gICAgICBcImFueU9mXCI6IFtcbiAgICAgICAge1wiJHJlZlwiOiBcIiMvJGRlZnMvc2ltcGxlVHlwZXNcIn0sXG4gICAgICAgIHtcbiAgICAgICAgICBcInR5cGVcIjogXCJhcnJheVwiLFxuICAgICAgICAgIFwiaXRlbXNcIjoge1wiJHJlZlwiOiBcIiMvJGRlZnMvc2ltcGxlVHlwZXNcIn0sXG4gICAgICAgICAgXCJtaW5JdGVtc1wiOiAxLFxuICAgICAgICAgIFwidW5pcXVlSXRlbXNcIjogdHJ1ZVxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9LFxuICBcIiRkZWZzXCI6IHtcbiAgICBcIm5vbk5lZ2F0aXZlSW50ZWdlclwiOiB7XG4gICAgICBcInR5cGVcIjogXCJpbnRlZ2VyXCIsXG4gICAgICBcIm1pbmltdW1cIjogMFxuICAgIH0sXG4gICAgXCJub25OZWdhdGl2ZUludGVnZXJEZWZhdWx0MFwiOiB7XG4gICAgICBcIiRyZWZcIjogXCIjLyRkZWZzL25vbk5lZ2F0aXZlSW50ZWdlclwiLFxuICAgICAgXCJkZWZhdWx0XCI6IDBcbiAgICB9LFxuICAgIFwic2ltcGxlVHlwZXNcIjoge1xuICAgICAgXCJlbnVtXCI6IFtcImFycmF5XCIsIFwiYm9vbGVhblwiLCBcImludGVnZXJcIiwgXCJudWxsXCIsIFwibnVtYmVyXCIsIFwib2JqZWN0XCIsIFwic3RyaW5nXCJdXG4gICAgfSxcbiAgICBcInN0cmluZ0FycmF5XCI6IHtcbiAgICAgIFwidHlwZVwiOiBcImFycmF5XCIsXG4gICAgICBcIml0ZW1zXCI6IHtcInR5cGVcIjogXCJzdHJpbmdcIn0sXG4gICAgICBcInVuaXF1ZUl0ZW1zXCI6IHRydWUsXG4gICAgICBcImRlZmF1bHRcIjogW11cbiAgICB9XG4gIH1cbn1cbiIsIm1vZHVsZS5leHBvcnRzPXtcbiAgXCIkc2NoZW1hXCI6IFwiaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQvMjAxOS0wOS9zY2hlbWFcIixcbiAgXCIkaWRcIjogXCJodHRwczovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC8yMDE5LTA5L3NjaGVtYVwiLFxuICBcIiR2b2NhYnVsYXJ5XCI6IHtcbiAgICBcImh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMTktMDkvdm9jYWIvY29yZVwiOiB0cnVlLFxuICAgIFwiaHR0cHM6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQvMjAxOS0wOS92b2NhYi9hcHBsaWNhdG9yXCI6IHRydWUsXG4gICAgXCJodHRwczovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC8yMDE5LTA5L3ZvY2FiL3ZhbGlkYXRpb25cIjogdHJ1ZSxcbiAgICBcImh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMTktMDkvdm9jYWIvbWV0YS1kYXRhXCI6IHRydWUsXG4gICAgXCJodHRwczovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC8yMDE5LTA5L3ZvY2FiL2Zvcm1hdFwiOiBmYWxzZSxcbiAgICBcImh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMTktMDkvdm9jYWIvY29udGVudFwiOiB0cnVlXG4gIH0sXG4gIFwiJHJlY3Vyc2l2ZUFuY2hvclwiOiB0cnVlLFxuXG4gIFwidGl0bGVcIjogXCJDb3JlIGFuZCBWYWxpZGF0aW9uIHNwZWNpZmljYXRpb25zIG1ldGEtc2NoZW1hXCIsXG4gIFwiYWxsT2ZcIjogW1xuICAgIHtcIiRyZWZcIjogXCJtZXRhL2NvcmVcIn0sXG4gICAge1wiJHJlZlwiOiBcIm1ldGEvYXBwbGljYXRvclwifSxcbiAgICB7XCIkcmVmXCI6IFwibWV0YS92YWxpZGF0aW9uXCJ9LFxuICAgIHtcIiRyZWZcIjogXCJtZXRhL21ldGEtZGF0YVwifSxcbiAgICB7XCIkcmVmXCI6IFwibWV0YS9mb3JtYXRcIn0sXG4gICAge1wiJHJlZlwiOiBcIm1ldGEvY29udGVudFwifVxuICBdLFxuICBcInR5cGVcIjogW1wib2JqZWN0XCIsIFwiYm9vbGVhblwiXSxcbiAgXCJwcm9wZXJ0aWVzXCI6IHtcbiAgICBcImRlZmluaXRpb25zXCI6IHtcbiAgICAgIFwiJGNvbW1lbnRcIjogXCJXaGlsZSBubyBsb25nZXIgYW4gb2ZmaWNpYWwga2V5d29yZCBhcyBpdCBpcyByZXBsYWNlZCBieSAkZGVmcywgdGhpcyBrZXl3b3JkIGlzIHJldGFpbmVkIGluIHRoZSBtZXRhLXNjaGVtYSB0byBwcmV2ZW50IGluY29tcGF0aWJsZSBleHRlbnNpb25zIGFzIGl0IHJlbWFpbnMgaW4gY29tbW9uIHVzZS5cIixcbiAgICAgIFwidHlwZVwiOiBcIm9iamVjdFwiLFxuICAgICAgXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiOiB7XCIkcmVjdXJzaXZlUmVmXCI6IFwiI1wifSxcbiAgICAgIFwiZGVmYXVsdFwiOiB7fVxuICAgIH0sXG4gICAgXCJkZXBlbmRlbmNpZXNcIjoge1xuICAgICAgXCIkY29tbWVudFwiOiBcIlxcXCJkZXBlbmRlbmNpZXNcXFwiIGlzIG5vIGxvbmdlciBhIGtleXdvcmQsIGJ1dCBzY2hlbWEgYXV0aG9ycyBzaG91bGQgYXZvaWQgcmVkZWZpbmluZyBpdCB0byBmYWNpbGl0YXRlIGEgc21vb3RoIHRyYW5zaXRpb24gdG8gXFxcImRlcGVuZGVudFNjaGVtYXNcXFwiIGFuZCBcXFwiZGVwZW5kZW50UmVxdWlyZWRcXFwiXCIsXG4gICAgICBcInR5cGVcIjogXCJvYmplY3RcIixcbiAgICAgIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIjoge1xuICAgICAgICBcImFueU9mXCI6IFt7XCIkcmVjdXJzaXZlUmVmXCI6IFwiI1wifSwge1wiJHJlZlwiOiBcIm1ldGEvdmFsaWRhdGlvbiMvJGRlZnMvc3RyaW5nQXJyYXlcIn1dXG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hanYtdmFsaWRhdG9yL2Fqdi9pc3N1ZXMvODg5XG5jb25zdCBlcXVhbCA9IHJlcXVpcmUoXCJmYXN0LWRlZXAtZXF1YWxcIik7XG5lcXVhbC5jb2RlID0gJ3JlcXVpcmUoXCJhanYvZGlzdC9ydW50aW1lL2VxdWFsXCIpLmRlZmF1bHQnO1xuZXhwb3J0cy5kZWZhdWx0ID0gZXF1YWw7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1lcXVhbC5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbi8vIGh0dHBzOi8vbWF0aGlhc2J5bmVucy5iZS9ub3Rlcy9qYXZhc2NyaXB0LWVuY29kaW5nXG4vLyBodHRwczovL2dpdGh1Yi5jb20vYmVzdGllanMvcHVueWNvZGUuanMgLSBwdW55Y29kZS51Y3MyLmRlY29kZVxuZnVuY3Rpb24gdWNzMmxlbmd0aChzdHIpIHtcbiAgICBjb25zdCBsZW4gPSBzdHIubGVuZ3RoO1xuICAgIGxldCBsZW5ndGggPSAwO1xuICAgIGxldCBwb3MgPSAwO1xuICAgIGxldCB2YWx1ZTtcbiAgICB3aGlsZSAocG9zIDwgbGVuKSB7XG4gICAgICAgIGxlbmd0aCsrO1xuICAgICAgICB2YWx1ZSA9IHN0ci5jaGFyQ29kZUF0KHBvcysrKTtcbiAgICAgICAgaWYgKHZhbHVlID49IDB4ZDgwMCAmJiB2YWx1ZSA8PSAweGRiZmYgJiYgcG9zIDwgbGVuKSB7XG4gICAgICAgICAgICAvLyBoaWdoIHN1cnJvZ2F0ZSwgYW5kIHRoZXJlIGlzIGEgbmV4dCBjaGFyYWN0ZXJcbiAgICAgICAgICAgIHZhbHVlID0gc3RyLmNoYXJDb2RlQXQocG9zKTtcbiAgICAgICAgICAgIGlmICgodmFsdWUgJiAweGZjMDApID09PSAweGRjMDApXG4gICAgICAgICAgICAgICAgcG9zKys7IC8vIGxvdyBzdXJyb2dhdGVcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbGVuZ3RoO1xufVxuZXhwb3J0cy5kZWZhdWx0ID0gdWNzMmxlbmd0aDtcbnVjczJsZW5ndGguY29kZSA9ICdyZXF1aXJlKFwiYWp2L2Rpc3QvcnVudGltZS91Y3MybGVuZ3RoXCIpLmRlZmF1bHQnO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dWNzMmxlbmd0aC5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IHVyaSA9IHJlcXVpcmUoXCJ1cmktanNcIik7XG51cmkuY29kZSA9ICdyZXF1aXJlKFwiYWp2L2Rpc3QvcnVudGltZS91cmlcIikuZGVmYXVsdCc7XG5leHBvcnRzLmRlZmF1bHQgPSB1cmk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD11cmkuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jbGFzcyBWYWxpZGF0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IoZXJyb3JzKSB7XG4gICAgICAgIHN1cGVyKFwidmFsaWRhdGlvbiBmYWlsZWRcIik7XG4gICAgICAgIHRoaXMuZXJyb3JzID0gZXJyb3JzO1xuICAgICAgICB0aGlzLmFqdiA9IHRoaXMudmFsaWRhdGlvbiA9IHRydWU7XG4gICAgfVxufVxuZXhwb3J0cy5kZWZhdWx0ID0gVmFsaWRhdGlvbkVycm9yO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dmFsaWRhdGlvbl9lcnJvci5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmV4cG9ydHMudmFsaWRhdGVBZGRpdGlvbmFsSXRlbXMgPSB2b2lkIDA7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9jb2RlZ2VuXCIpO1xuY29uc3QgdXRpbF8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdXRpbFwiKTtcbmNvbnN0IGVycm9yID0ge1xuICAgIG1lc3NhZ2U6ICh7IHBhcmFtczogeyBsZW4gfSB9KSA9PiAoMCwgY29kZWdlbl8xLnN0cikgYG11c3QgTk9UIGhhdmUgbW9yZSB0aGFuICR7bGVufSBpdGVtc2AsXG4gICAgcGFyYW1zOiAoeyBwYXJhbXM6IHsgbGVuIH0gfSkgPT4gKDAsIGNvZGVnZW5fMS5fKSBge2xpbWl0OiAke2xlbn19YCxcbn07XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogXCJhZGRpdGlvbmFsSXRlbXNcIixcbiAgICB0eXBlOiBcImFycmF5XCIsXG4gICAgc2NoZW1hVHlwZTogW1wiYm9vbGVhblwiLCBcIm9iamVjdFwiXSxcbiAgICBiZWZvcmU6IFwidW5pcXVlSXRlbXNcIixcbiAgICBlcnJvcixcbiAgICBjb2RlKGN4dCkge1xuICAgICAgICBjb25zdCB7IHBhcmVudFNjaGVtYSwgaXQgfSA9IGN4dDtcbiAgICAgICAgY29uc3QgeyBpdGVtcyB9ID0gcGFyZW50U2NoZW1hO1xuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoaXRlbXMpKSB7XG4gICAgICAgICAgICAoMCwgdXRpbF8xLmNoZWNrU3RyaWN0TW9kZSkoaXQsICdcImFkZGl0aW9uYWxJdGVtc1wiIGlzIGlnbm9yZWQgd2hlbiBcIml0ZW1zXCIgaXMgbm90IGFuIGFycmF5IG9mIHNjaGVtYXMnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YWxpZGF0ZUFkZGl0aW9uYWxJdGVtcyhjeHQsIGl0ZW1zKTtcbiAgICB9LFxufTtcbmZ1bmN0aW9uIHZhbGlkYXRlQWRkaXRpb25hbEl0ZW1zKGN4dCwgaXRlbXMpIHtcbiAgICBjb25zdCB7IGdlbiwgc2NoZW1hLCBkYXRhLCBrZXl3b3JkLCBpdCB9ID0gY3h0O1xuICAgIGl0Lml0ZW1zID0gdHJ1ZTtcbiAgICBjb25zdCBsZW4gPSBnZW4uY29uc3QoXCJsZW5cIiwgKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhfS5sZW5ndGhgKTtcbiAgICBpZiAoc2NoZW1hID09PSBmYWxzZSkge1xuICAgICAgICBjeHQuc2V0UGFyYW1zKHsgbGVuOiBpdGVtcy5sZW5ndGggfSk7XG4gICAgICAgIGN4dC5wYXNzKCgwLCBjb2RlZ2VuXzEuXykgYCR7bGVufSA8PSAke2l0ZW1zLmxlbmd0aH1gKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIHNjaGVtYSA9PSBcIm9iamVjdFwiICYmICEoMCwgdXRpbF8xLmFsd2F5c1ZhbGlkU2NoZW1hKShpdCwgc2NoZW1hKSkge1xuICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi52YXIoXCJ2YWxpZFwiLCAoMCwgY29kZWdlbl8xLl8pIGAke2xlbn0gPD0gJHtpdGVtcy5sZW5ndGh9YCk7IC8vIFRPRE8gdmFyXG4gICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLm5vdCkodmFsaWQpLCAoKSA9PiB2YWxpZGF0ZUl0ZW1zKHZhbGlkKSk7XG4gICAgICAgIGN4dC5vayh2YWxpZCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHZhbGlkYXRlSXRlbXModmFsaWQpIHtcbiAgICAgICAgZ2VuLmZvclJhbmdlKFwiaVwiLCBpdGVtcy5sZW5ndGgsIGxlbiwgKGkpID0+IHtcbiAgICAgICAgICAgIGN4dC5zdWJzY2hlbWEoeyBrZXl3b3JkLCBkYXRhUHJvcDogaSwgZGF0YVByb3BUeXBlOiB1dGlsXzEuVHlwZS5OdW0gfSwgdmFsaWQpO1xuICAgICAgICAgICAgaWYgKCFpdC5hbGxFcnJvcnMpXG4gICAgICAgICAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEubm90KSh2YWxpZCksICgpID0+IGdlbi5icmVhaygpKTtcbiAgICAgICAgfSk7XG4gICAgfVxufVxuZXhwb3J0cy52YWxpZGF0ZUFkZGl0aW9uYWxJdGVtcyA9IHZhbGlkYXRlQWRkaXRpb25hbEl0ZW1zO1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9YWRkaXRpb25hbEl0ZW1zLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgY29kZV8xID0gcmVxdWlyZShcIi4uL2NvZGVcIik7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9jb2RlZ2VuXCIpO1xuY29uc3QgbmFtZXNfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL25hbWVzXCIpO1xuY29uc3QgdXRpbF8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdXRpbFwiKTtcbmNvbnN0IGVycm9yID0ge1xuICAgIG1lc3NhZ2U6IFwibXVzdCBOT1QgaGF2ZSBhZGRpdGlvbmFsIHByb3BlcnRpZXNcIixcbiAgICBwYXJhbXM6ICh7IHBhcmFtcyB9KSA9PiAoMCwgY29kZWdlbl8xLl8pIGB7YWRkaXRpb25hbFByb3BlcnR5OiAke3BhcmFtcy5hZGRpdGlvbmFsUHJvcGVydHl9fWAsXG59O1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIixcbiAgICB0eXBlOiBbXCJvYmplY3RcIl0sXG4gICAgc2NoZW1hVHlwZTogW1wiYm9vbGVhblwiLCBcIm9iamVjdFwiXSxcbiAgICBhbGxvd1VuZGVmaW5lZDogdHJ1ZSxcbiAgICB0cmFja0Vycm9yczogdHJ1ZSxcbiAgICBlcnJvcixcbiAgICBjb2RlKGN4dCkge1xuICAgICAgICBjb25zdCB7IGdlbiwgc2NoZW1hLCBwYXJlbnRTY2hlbWEsIGRhdGEsIGVycnNDb3VudCwgaXQgfSA9IGN4dDtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgIGlmICghZXJyc0NvdW50KVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYWp2IGltcGxlbWVudGF0aW9uIGVycm9yXCIpO1xuICAgICAgICBjb25zdCB7IGFsbEVycm9ycywgb3B0cyB9ID0gaXQ7XG4gICAgICAgIGl0LnByb3BzID0gdHJ1ZTtcbiAgICAgICAgaWYgKG9wdHMucmVtb3ZlQWRkaXRpb25hbCAhPT0gXCJhbGxcIiAmJiAoMCwgdXRpbF8xLmFsd2F5c1ZhbGlkU2NoZW1hKShpdCwgc2NoZW1hKSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgcHJvcHMgPSAoMCwgY29kZV8xLmFsbFNjaGVtYVByb3BlcnRpZXMpKHBhcmVudFNjaGVtYS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgY29uc3QgcGF0UHJvcHMgPSAoMCwgY29kZV8xLmFsbFNjaGVtYVByb3BlcnRpZXMpKHBhcmVudFNjaGVtYS5wYXR0ZXJuUHJvcGVydGllcyk7XG4gICAgICAgIGNoZWNrQWRkaXRpb25hbFByb3BlcnRpZXMoKTtcbiAgICAgICAgY3h0Lm9rKCgwLCBjb2RlZ2VuXzEuXykgYCR7ZXJyc0NvdW50fSA9PT0gJHtuYW1lc18xLmRlZmF1bHQuZXJyb3JzfWApO1xuICAgICAgICBmdW5jdGlvbiBjaGVja0FkZGl0aW9uYWxQcm9wZXJ0aWVzKCkge1xuICAgICAgICAgICAgZ2VuLmZvckluKFwia2V5XCIsIGRhdGEsIChrZXkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIXByb3BzLmxlbmd0aCAmJiAhcGF0UHJvcHMubGVuZ3RoKVxuICAgICAgICAgICAgICAgICAgICBhZGRpdGlvbmFsUHJvcGVydHlDb2RlKGtleSk7XG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBnZW4uaWYoaXNBZGRpdGlvbmFsKGtleSksICgpID0+IGFkZGl0aW9uYWxQcm9wZXJ0eUNvZGUoa2V5KSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBpc0FkZGl0aW9uYWwoa2V5KSB7XG4gICAgICAgICAgICBsZXQgZGVmaW5lZFByb3A7XG4gICAgICAgICAgICBpZiAocHJvcHMubGVuZ3RoID4gOCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE8gbWF5YmUgYW4gb3B0aW9uIGluc3RlYWQgb2YgaGFyZC1jb2RlZCA4P1xuICAgICAgICAgICAgICAgIGNvbnN0IHByb3BzU2NoZW1hID0gKDAsIHV0aWxfMS5zY2hlbWFSZWZPclZhbCkoaXQsIHBhcmVudFNjaGVtYS5wcm9wZXJ0aWVzLCBcInByb3BlcnRpZXNcIik7XG4gICAgICAgICAgICAgICAgZGVmaW5lZFByb3AgPSAoMCwgY29kZV8xLmlzT3duUHJvcGVydHkpKGdlbiwgcHJvcHNTY2hlbWEsIGtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChwcm9wcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBkZWZpbmVkUHJvcCA9ICgwLCBjb2RlZ2VuXzEub3IpKC4uLnByb3BzLm1hcCgocCkgPT4gKDAsIGNvZGVnZW5fMS5fKSBgJHtrZXl9ID09PSAke3B9YCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVmaW5lZFByb3AgPSBjb2RlZ2VuXzEubmlsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhdFByb3BzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGRlZmluZWRQcm9wID0gKDAsIGNvZGVnZW5fMS5vcikoZGVmaW5lZFByb3AsIC4uLnBhdFByb3BzLm1hcCgocCkgPT4gKDAsIGNvZGVnZW5fMS5fKSBgJHsoMCwgY29kZV8xLnVzZVBhdHRlcm4pKGN4dCwgcCl9LnRlc3QoJHtrZXl9KWApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAoMCwgY29kZWdlbl8xLm5vdCkoZGVmaW5lZFByb3ApO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGRlbGV0ZUFkZGl0aW9uYWwoa2V5KSB7XG4gICAgICAgICAgICBnZW4uY29kZSgoMCwgY29kZWdlbl8xLl8pIGBkZWxldGUgJHtkYXRhfVske2tleX1dYCk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gYWRkaXRpb25hbFByb3BlcnR5Q29kZShrZXkpIHtcbiAgICAgICAgICAgIGlmIChvcHRzLnJlbW92ZUFkZGl0aW9uYWwgPT09IFwiYWxsXCIgfHwgKG9wdHMucmVtb3ZlQWRkaXRpb25hbCAmJiBzY2hlbWEgPT09IGZhbHNlKSkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZUFkZGl0aW9uYWwoa2V5KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2NoZW1hID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIGN4dC5zZXRQYXJhbXMoeyBhZGRpdGlvbmFsUHJvcGVydHk6IGtleSB9KTtcbiAgICAgICAgICAgICAgICBjeHQuZXJyb3IoKTtcbiAgICAgICAgICAgICAgICBpZiAoIWFsbEVycm9ycylcbiAgICAgICAgICAgICAgICAgICAgZ2VuLmJyZWFrKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzY2hlbWEgPT0gXCJvYmplY3RcIiAmJiAhKDAsIHV0aWxfMS5hbHdheXNWYWxpZFNjaGVtYSkoaXQsIHNjaGVtYSkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi5uYW1lKFwidmFsaWRcIik7XG4gICAgICAgICAgICAgICAgaWYgKG9wdHMucmVtb3ZlQWRkaXRpb25hbCA9PT0gXCJmYWlsaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgYXBwbHlBZGRpdGlvbmFsU2NoZW1hKGtleSwgdmFsaWQsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEubm90KSh2YWxpZCksICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN4dC5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlQWRkaXRpb25hbChrZXkpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5QWRkaXRpb25hbFNjaGVtYShrZXksIHZhbGlkKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFhbGxFcnJvcnMpXG4gICAgICAgICAgICAgICAgICAgICAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5ub3QpKHZhbGlkKSwgKCkgPT4gZ2VuLmJyZWFrKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBhcHBseUFkZGl0aW9uYWxTY2hlbWEoa2V5LCB2YWxpZCwgZXJyb3JzKSB7XG4gICAgICAgICAgICBjb25zdCBzdWJzY2hlbWEgPSB7XG4gICAgICAgICAgICAgICAga2V5d29yZDogXCJhZGRpdGlvbmFsUHJvcGVydGllc1wiLFxuICAgICAgICAgICAgICAgIGRhdGFQcm9wOiBrZXksXG4gICAgICAgICAgICAgICAgZGF0YVByb3BUeXBlOiB1dGlsXzEuVHlwZS5TdHIsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKGVycm9ycyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKHN1YnNjaGVtYSwge1xuICAgICAgICAgICAgICAgICAgICBjb21wb3NpdGVSdWxlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBjcmVhdGVFcnJvcnM6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBhbGxFcnJvcnM6IGZhbHNlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3h0LnN1YnNjaGVtYShzdWJzY2hlbWEsIHZhbGlkKTtcbiAgICAgICAgfVxuICAgIH0sXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9YWRkaXRpb25hbFByb3BlcnRpZXMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCB1dGlsXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS91dGlsXCIpO1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwiYWxsT2ZcIixcbiAgICBzY2hlbWFUeXBlOiBcImFycmF5XCIsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgeyBnZW4sIHNjaGVtYSwgaXQgfSA9IGN4dDtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShzY2hlbWEpKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYWp2IGltcGxlbWVudGF0aW9uIGVycm9yXCIpO1xuICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi5uYW1lKFwidmFsaWRcIik7XG4gICAgICAgIHNjaGVtYS5mb3JFYWNoKChzY2gsIGkpID0+IHtcbiAgICAgICAgICAgIGlmICgoMCwgdXRpbF8xLmFsd2F5c1ZhbGlkU2NoZW1hKShpdCwgc2NoKSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBjb25zdCBzY2hDeHQgPSBjeHQuc3Vic2NoZW1hKHsga2V5d29yZDogXCJhbGxPZlwiLCBzY2hlbWFQcm9wOiBpIH0sIHZhbGlkKTtcbiAgICAgICAgICAgIGN4dC5vayh2YWxpZCk7XG4gICAgICAgICAgICBjeHQubWVyZ2VFdmFsdWF0ZWQoc2NoQ3h0KTtcbiAgICAgICAgfSk7XG4gICAgfSxcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBkZWY7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1hbGxPZi5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGNvZGVfMSA9IHJlcXVpcmUoXCIuLi9jb2RlXCIpO1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwiYW55T2ZcIixcbiAgICBzY2hlbWFUeXBlOiBcImFycmF5XCIsXG4gICAgdHJhY2tFcnJvcnM6IHRydWUsXG4gICAgY29kZTogY29kZV8xLnZhbGlkYXRlVW5pb24sXG4gICAgZXJyb3I6IHsgbWVzc2FnZTogXCJtdXN0IG1hdGNoIGEgc2NoZW1hIGluIGFueU9mXCIgfSxcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBkZWY7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1hbnlPZi5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL2NvZGVnZW5cIik7XG5jb25zdCB1dGlsXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS91dGlsXCIpO1xuY29uc3QgZXJyb3IgPSB7XG4gICAgbWVzc2FnZTogKHsgcGFyYW1zOiB7IG1pbiwgbWF4IH0gfSkgPT4gbWF4ID09PSB1bmRlZmluZWRcbiAgICAgICAgPyAoMCwgY29kZWdlbl8xLnN0cikgYG11c3QgY29udGFpbiBhdCBsZWFzdCAke21pbn0gdmFsaWQgaXRlbShzKWBcbiAgICAgICAgOiAoMCwgY29kZWdlbl8xLnN0cikgYG11c3QgY29udGFpbiBhdCBsZWFzdCAke21pbn0gYW5kIG5vIG1vcmUgdGhhbiAke21heH0gdmFsaWQgaXRlbShzKWAsXG4gICAgcGFyYW1zOiAoeyBwYXJhbXM6IHsgbWluLCBtYXggfSB9KSA9PiBtYXggPT09IHVuZGVmaW5lZCA/ICgwLCBjb2RlZ2VuXzEuXykgYHttaW5Db250YWluczogJHttaW59fWAgOiAoMCwgY29kZWdlbl8xLl8pIGB7bWluQ29udGFpbnM6ICR7bWlufSwgbWF4Q29udGFpbnM6ICR7bWF4fX1gLFxufTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBcImNvbnRhaW5zXCIsXG4gICAgdHlwZTogXCJhcnJheVwiLFxuICAgIHNjaGVtYVR5cGU6IFtcIm9iamVjdFwiLCBcImJvb2xlYW5cIl0sXG4gICAgYmVmb3JlOiBcInVuaXF1ZUl0ZW1zXCIsXG4gICAgdHJhY2tFcnJvcnM6IHRydWUsXG4gICAgZXJyb3IsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgeyBnZW4sIHNjaGVtYSwgcGFyZW50U2NoZW1hLCBkYXRhLCBpdCB9ID0gY3h0O1xuICAgICAgICBsZXQgbWluO1xuICAgICAgICBsZXQgbWF4O1xuICAgICAgICBjb25zdCB7IG1pbkNvbnRhaW5zLCBtYXhDb250YWlucyB9ID0gcGFyZW50U2NoZW1hO1xuICAgICAgICBpZiAoaXQub3B0cy5uZXh0KSB7XG4gICAgICAgICAgICBtaW4gPSBtaW5Db250YWlucyA9PT0gdW5kZWZpbmVkID8gMSA6IG1pbkNvbnRhaW5zO1xuICAgICAgICAgICAgbWF4ID0gbWF4Q29udGFpbnM7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBtaW4gPSAxO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGxlbiA9IGdlbi5jb25zdChcImxlblwiLCAoMCwgY29kZWdlbl8xLl8pIGAke2RhdGF9Lmxlbmd0aGApO1xuICAgICAgICBjeHQuc2V0UGFyYW1zKHsgbWluLCBtYXggfSk7XG4gICAgICAgIGlmIChtYXggPT09IHVuZGVmaW5lZCAmJiBtaW4gPT09IDApIHtcbiAgICAgICAgICAgICgwLCB1dGlsXzEuY2hlY2tTdHJpY3RNb2RlKShpdCwgYFwibWluQ29udGFpbnNcIiA9PSAwIHdpdGhvdXQgXCJtYXhDb250YWluc1wiOiBcImNvbnRhaW5zXCIga2V5d29yZCBpZ25vcmVkYCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1heCAhPT0gdW5kZWZpbmVkICYmIG1pbiA+IG1heCkge1xuICAgICAgICAgICAgKDAsIHV0aWxfMS5jaGVja1N0cmljdE1vZGUpKGl0LCBgXCJtaW5Db250YWluc1wiID4gXCJtYXhDb250YWluc1wiIGlzIGFsd2F5cyBpbnZhbGlkYCk7XG4gICAgICAgICAgICBjeHQuZmFpbCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICgoMCwgdXRpbF8xLmFsd2F5c1ZhbGlkU2NoZW1hKShpdCwgc2NoZW1hKSkge1xuICAgICAgICAgICAgbGV0IGNvbmQgPSAoMCwgY29kZWdlbl8xLl8pIGAke2xlbn0gPj0gJHttaW59YDtcbiAgICAgICAgICAgIGlmIChtYXggIT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgICAgICBjb25kID0gKDAsIGNvZGVnZW5fMS5fKSBgJHtjb25kfSAmJiAke2xlbn0gPD0gJHttYXh9YDtcbiAgICAgICAgICAgIGN4dC5wYXNzKGNvbmQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGl0Lml0ZW1zID0gdHJ1ZTtcbiAgICAgICAgY29uc3QgdmFsaWQgPSBnZW4ubmFtZShcInZhbGlkXCIpO1xuICAgICAgICBpZiAobWF4ID09PSB1bmRlZmluZWQgJiYgbWluID09PSAxKSB7XG4gICAgICAgICAgICB2YWxpZGF0ZUl0ZW1zKHZhbGlkLCAoKSA9PiBnZW4uaWYodmFsaWQsICgpID0+IGdlbi5icmVhaygpKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAobWluID09PSAwKSB7XG4gICAgICAgICAgICBnZW4ubGV0KHZhbGlkLCB0cnVlKTtcbiAgICAgICAgICAgIGlmIChtYXggIT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgICAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhfS5sZW5ndGggPiAwYCwgdmFsaWRhdGVJdGVtc1dpdGhDb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBnZW4ubGV0KHZhbGlkLCBmYWxzZSk7XG4gICAgICAgICAgICB2YWxpZGF0ZUl0ZW1zV2l0aENvdW50KCk7XG4gICAgICAgIH1cbiAgICAgICAgY3h0LnJlc3VsdCh2YWxpZCwgKCkgPT4gY3h0LnJlc2V0KCkpO1xuICAgICAgICBmdW5jdGlvbiB2YWxpZGF0ZUl0ZW1zV2l0aENvdW50KCkge1xuICAgICAgICAgICAgY29uc3Qgc2NoVmFsaWQgPSBnZW4ubmFtZShcIl92YWxpZFwiKTtcbiAgICAgICAgICAgIGNvbnN0IGNvdW50ID0gZ2VuLmxldChcImNvdW50XCIsIDApO1xuICAgICAgICAgICAgdmFsaWRhdGVJdGVtcyhzY2hWYWxpZCwgKCkgPT4gZ2VuLmlmKHNjaFZhbGlkLCAoKSA9PiBjaGVja0xpbWl0cyhjb3VudCkpKTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiB2YWxpZGF0ZUl0ZW1zKF92YWxpZCwgYmxvY2spIHtcbiAgICAgICAgICAgIGdlbi5mb3JSYW5nZShcImlcIiwgMCwgbGVuLCAoaSkgPT4ge1xuICAgICAgICAgICAgICAgIGN4dC5zdWJzY2hlbWEoe1xuICAgICAgICAgICAgICAgICAgICBrZXl3b3JkOiBcImNvbnRhaW5zXCIsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFQcm9wOiBpLFxuICAgICAgICAgICAgICAgICAgICBkYXRhUHJvcFR5cGU6IHV0aWxfMS5UeXBlLk51bSxcbiAgICAgICAgICAgICAgICAgICAgY29tcG9zaXRlUnVsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICB9LCBfdmFsaWQpO1xuICAgICAgICAgICAgICAgIGJsb2NrKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBjaGVja0xpbWl0cyhjb3VudCkge1xuICAgICAgICAgICAgZ2VuLmNvZGUoKDAsIGNvZGVnZW5fMS5fKSBgJHtjb3VudH0rK2ApO1xuICAgICAgICAgICAgaWYgKG1heCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7Y291bnR9ID49ICR7bWlufWAsICgpID0+IGdlbi5hc3NpZ24odmFsaWQsIHRydWUpLmJyZWFrKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7Y291bnR9ID4gJHttYXh9YCwgKCkgPT4gZ2VuLmFzc2lnbih2YWxpZCwgZmFsc2UpLmJyZWFrKCkpO1xuICAgICAgICAgICAgICAgIGlmIChtaW4gPT09IDEpXG4gICAgICAgICAgICAgICAgICAgIGdlbi5hc3NpZ24odmFsaWQsIHRydWUpO1xuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7Y291bnR9ID49ICR7bWlufWAsICgpID0+IGdlbi5hc3NpZ24odmFsaWQsIHRydWUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29udGFpbnMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leHBvcnRzLnZhbGlkYXRlU2NoZW1hRGVwcyA9IGV4cG9ydHMudmFsaWRhdGVQcm9wZXJ0eURlcHMgPSBleHBvcnRzLmVycm9yID0gdm9pZCAwO1xuY29uc3QgY29kZWdlbl8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvY29kZWdlblwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL3V0aWxcIik7XG5jb25zdCBjb2RlXzEgPSByZXF1aXJlKFwiLi4vY29kZVwiKTtcbmV4cG9ydHMuZXJyb3IgPSB7XG4gICAgbWVzc2FnZTogKHsgcGFyYW1zOiB7IHByb3BlcnR5LCBkZXBzQ291bnQsIGRlcHMgfSB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHByb3BlcnR5X2llcyA9IGRlcHNDb3VudCA9PT0gMSA/IFwicHJvcGVydHlcIiA6IFwicHJvcGVydGllc1wiO1xuICAgICAgICByZXR1cm4gKDAsIGNvZGVnZW5fMS5zdHIpIGBtdXN0IGhhdmUgJHtwcm9wZXJ0eV9pZXN9ICR7ZGVwc30gd2hlbiBwcm9wZXJ0eSAke3Byb3BlcnR5fSBpcyBwcmVzZW50YDtcbiAgICB9LFxuICAgIHBhcmFtczogKHsgcGFyYW1zOiB7IHByb3BlcnR5LCBkZXBzQ291bnQsIGRlcHMsIG1pc3NpbmdQcm9wZXJ0eSB9IH0pID0+ICgwLCBjb2RlZ2VuXzEuXykgYHtwcm9wZXJ0eTogJHtwcm9wZXJ0eX0sXG4gICAgbWlzc2luZ1Byb3BlcnR5OiAke21pc3NpbmdQcm9wZXJ0eX0sXG4gICAgZGVwc0NvdW50OiAke2RlcHNDb3VudH0sXG4gICAgZGVwczogJHtkZXBzfX1gLCAvLyBUT0RPIGNoYW5nZSB0byByZWZlcmVuY2Vcbn07XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogXCJkZXBlbmRlbmNpZXNcIixcbiAgICB0eXBlOiBcIm9iamVjdFwiLFxuICAgIHNjaGVtYVR5cGU6IFwib2JqZWN0XCIsXG4gICAgZXJyb3I6IGV4cG9ydHMuZXJyb3IsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgW3Byb3BEZXBzLCBzY2hEZXBzXSA9IHNwbGl0RGVwZW5kZW5jaWVzKGN4dCk7XG4gICAgICAgIHZhbGlkYXRlUHJvcGVydHlEZXBzKGN4dCwgcHJvcERlcHMpO1xuICAgICAgICB2YWxpZGF0ZVNjaGVtYURlcHMoY3h0LCBzY2hEZXBzKTtcbiAgICB9LFxufTtcbmZ1bmN0aW9uIHNwbGl0RGVwZW5kZW5jaWVzKHsgc2NoZW1hIH0pIHtcbiAgICBjb25zdCBwcm9wZXJ0eURlcHMgPSB7fTtcbiAgICBjb25zdCBzY2hlbWFEZXBzID0ge307XG4gICAgZm9yIChjb25zdCBrZXkgaW4gc2NoZW1hKSB7XG4gICAgICAgIGlmIChrZXkgPT09IFwiX19wcm90b19fXCIpXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgY29uc3QgZGVwcyA9IEFycmF5LmlzQXJyYXkoc2NoZW1hW2tleV0pID8gcHJvcGVydHlEZXBzIDogc2NoZW1hRGVwcztcbiAgICAgICAgZGVwc1trZXldID0gc2NoZW1hW2tleV07XG4gICAgfVxuICAgIHJldHVybiBbcHJvcGVydHlEZXBzLCBzY2hlbWFEZXBzXTtcbn1cbmZ1bmN0aW9uIHZhbGlkYXRlUHJvcGVydHlEZXBzKGN4dCwgcHJvcGVydHlEZXBzID0gY3h0LnNjaGVtYSkge1xuICAgIGNvbnN0IHsgZ2VuLCBkYXRhLCBpdCB9ID0gY3h0O1xuICAgIGlmIChPYmplY3Qua2V5cyhwcm9wZXJ0eURlcHMpLmxlbmd0aCA9PT0gMClcbiAgICAgICAgcmV0dXJuO1xuICAgIGNvbnN0IG1pc3NpbmcgPSBnZW4ubGV0KFwibWlzc2luZ1wiKTtcbiAgICBmb3IgKGNvbnN0IHByb3AgaW4gcHJvcGVydHlEZXBzKSB7XG4gICAgICAgIGNvbnN0IGRlcHMgPSBwcm9wZXJ0eURlcHNbcHJvcF07XG4gICAgICAgIGlmIChkZXBzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICBjb25zdCBoYXNQcm9wZXJ0eSA9ICgwLCBjb2RlXzEucHJvcGVydHlJbkRhdGEpKGdlbiwgZGF0YSwgcHJvcCwgaXQub3B0cy5vd25Qcm9wZXJ0aWVzKTtcbiAgICAgICAgY3h0LnNldFBhcmFtcyh7XG4gICAgICAgICAgICBwcm9wZXJ0eTogcHJvcCxcbiAgICAgICAgICAgIGRlcHNDb3VudDogZGVwcy5sZW5ndGgsXG4gICAgICAgICAgICBkZXBzOiBkZXBzLmpvaW4oXCIsIFwiKSxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChpdC5hbGxFcnJvcnMpIHtcbiAgICAgICAgICAgIGdlbi5pZihoYXNQcm9wZXJ0eSwgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZGVwUHJvcCBvZiBkZXBzKSB7XG4gICAgICAgICAgICAgICAgICAgICgwLCBjb2RlXzEuY2hlY2tSZXBvcnRNaXNzaW5nUHJvcCkoY3h0LCBkZXBQcm9wKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLl8pIGAke2hhc1Byb3BlcnR5fSAmJiAoJHsoMCwgY29kZV8xLmNoZWNrTWlzc2luZ1Byb3ApKGN4dCwgZGVwcywgbWlzc2luZyl9KWApO1xuICAgICAgICAgICAgKDAsIGNvZGVfMS5yZXBvcnRNaXNzaW5nUHJvcCkoY3h0LCBtaXNzaW5nKTtcbiAgICAgICAgICAgIGdlbi5lbHNlKCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5leHBvcnRzLnZhbGlkYXRlUHJvcGVydHlEZXBzID0gdmFsaWRhdGVQcm9wZXJ0eURlcHM7XG5mdW5jdGlvbiB2YWxpZGF0ZVNjaGVtYURlcHMoY3h0LCBzY2hlbWFEZXBzID0gY3h0LnNjaGVtYSkge1xuICAgIGNvbnN0IHsgZ2VuLCBkYXRhLCBrZXl3b3JkLCBpdCB9ID0gY3h0O1xuICAgIGNvbnN0IHZhbGlkID0gZ2VuLm5hbWUoXCJ2YWxpZFwiKTtcbiAgICBmb3IgKGNvbnN0IHByb3AgaW4gc2NoZW1hRGVwcykge1xuICAgICAgICBpZiAoKDAsIHV0aWxfMS5hbHdheXNWYWxpZFNjaGVtYSkoaXQsIHNjaGVtYURlcHNbcHJvcF0pKVxuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIGdlbi5pZigoMCwgY29kZV8xLnByb3BlcnR5SW5EYXRhKShnZW4sIGRhdGEsIHByb3AsIGl0Lm9wdHMub3duUHJvcGVydGllcyksICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHNjaEN4dCA9IGN4dC5zdWJzY2hlbWEoeyBrZXl3b3JkLCBzY2hlbWFQcm9wOiBwcm9wIH0sIHZhbGlkKTtcbiAgICAgICAgICAgIGN4dC5tZXJnZVZhbGlkRXZhbHVhdGVkKHNjaEN4dCwgdmFsaWQpO1xuICAgICAgICB9LCAoKSA9PiBnZW4udmFyKHZhbGlkLCB0cnVlKSAvLyBUT0RPIHZhclxuICAgICAgICApO1xuICAgICAgICBjeHQub2sodmFsaWQpO1xuICAgIH1cbn1cbmV4cG9ydHMudmFsaWRhdGVTY2hlbWFEZXBzID0gdmFsaWRhdGVTY2hlbWFEZXBzO1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGVwZW5kZW5jaWVzLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgZGVwZW5kZW5jaWVzXzEgPSByZXF1aXJlKFwiLi9kZXBlbmRlbmNpZXNcIik7XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogXCJkZXBlbmRlbnRTY2hlbWFzXCIsXG4gICAgdHlwZTogXCJvYmplY3RcIixcbiAgICBzY2hlbWFUeXBlOiBcIm9iamVjdFwiLFxuICAgIGNvZGU6IChjeHQpID0+ICgwLCBkZXBlbmRlbmNpZXNfMS52YWxpZGF0ZVNjaGVtYURlcHMpKGN4dCksXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGVwZW5kZW50U2NoZW1hcy5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL2NvZGVnZW5cIik7XG5jb25zdCB1dGlsXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS91dGlsXCIpO1xuY29uc3QgZXJyb3IgPSB7XG4gICAgbWVzc2FnZTogKHsgcGFyYW1zIH0pID0+ICgwLCBjb2RlZ2VuXzEuc3RyKSBgbXVzdCBtYXRjaCBcIiR7cGFyYW1zLmlmQ2xhdXNlfVwiIHNjaGVtYWAsXG4gICAgcGFyYW1zOiAoeyBwYXJhbXMgfSkgPT4gKDAsIGNvZGVnZW5fMS5fKSBge2ZhaWxpbmdLZXl3b3JkOiAke3BhcmFtcy5pZkNsYXVzZX19YCxcbn07XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogXCJpZlwiLFxuICAgIHNjaGVtYVR5cGU6IFtcIm9iamVjdFwiLCBcImJvb2xlYW5cIl0sXG4gICAgdHJhY2tFcnJvcnM6IHRydWUsXG4gICAgZXJyb3IsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgeyBnZW4sIHBhcmVudFNjaGVtYSwgaXQgfSA9IGN4dDtcbiAgICAgICAgaWYgKHBhcmVudFNjaGVtYS50aGVuID09PSB1bmRlZmluZWQgJiYgcGFyZW50U2NoZW1hLmVsc2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgKDAsIHV0aWxfMS5jaGVja1N0cmljdE1vZGUpKGl0LCAnXCJpZlwiIHdpdGhvdXQgXCJ0aGVuXCIgYW5kIFwiZWxzZVwiIGlzIGlnbm9yZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBoYXNUaGVuID0gaGFzU2NoZW1hKGl0LCBcInRoZW5cIik7XG4gICAgICAgIGNvbnN0IGhhc0Vsc2UgPSBoYXNTY2hlbWEoaXQsIFwiZWxzZVwiKTtcbiAgICAgICAgaWYgKCFoYXNUaGVuICYmICFoYXNFbHNlKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi5sZXQoXCJ2YWxpZFwiLCB0cnVlKTtcbiAgICAgICAgY29uc3Qgc2NoVmFsaWQgPSBnZW4ubmFtZShcIl92YWxpZFwiKTtcbiAgICAgICAgdmFsaWRhdGVJZigpO1xuICAgICAgICBjeHQucmVzZXQoKTtcbiAgICAgICAgaWYgKGhhc1RoZW4gJiYgaGFzRWxzZSkge1xuICAgICAgICAgICAgY29uc3QgaWZDbGF1c2UgPSBnZW4ubGV0KFwiaWZDbGF1c2VcIik7XG4gICAgICAgICAgICBjeHQuc2V0UGFyYW1zKHsgaWZDbGF1c2UgfSk7XG4gICAgICAgICAgICBnZW4uaWYoc2NoVmFsaWQsIHZhbGlkYXRlQ2xhdXNlKFwidGhlblwiLCBpZkNsYXVzZSksIHZhbGlkYXRlQ2xhdXNlKFwiZWxzZVwiLCBpZkNsYXVzZSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGhhc1RoZW4pIHtcbiAgICAgICAgICAgIGdlbi5pZihzY2hWYWxpZCwgdmFsaWRhdGVDbGF1c2UoXCJ0aGVuXCIpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLm5vdCkoc2NoVmFsaWQpLCB2YWxpZGF0ZUNsYXVzZShcImVsc2VcIikpO1xuICAgICAgICB9XG4gICAgICAgIGN4dC5wYXNzKHZhbGlkLCAoKSA9PiBjeHQuZXJyb3IodHJ1ZSkpO1xuICAgICAgICBmdW5jdGlvbiB2YWxpZGF0ZUlmKCkge1xuICAgICAgICAgICAgY29uc3Qgc2NoQ3h0ID0gY3h0LnN1YnNjaGVtYSh7XG4gICAgICAgICAgICAgICAga2V5d29yZDogXCJpZlwiLFxuICAgICAgICAgICAgICAgIGNvbXBvc2l0ZVJ1bGU6IHRydWUsXG4gICAgICAgICAgICAgICAgY3JlYXRlRXJyb3JzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBhbGxFcnJvcnM6IGZhbHNlLFxuICAgICAgICAgICAgfSwgc2NoVmFsaWQpO1xuICAgICAgICAgICAgY3h0Lm1lcmdlRXZhbHVhdGVkKHNjaEN4dCk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gdmFsaWRhdGVDbGF1c2Uoa2V5d29yZCwgaWZDbGF1c2UpIHtcbiAgICAgICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NoQ3h0ID0gY3h0LnN1YnNjaGVtYSh7IGtleXdvcmQgfSwgc2NoVmFsaWQpO1xuICAgICAgICAgICAgICAgIGdlbi5hc3NpZ24odmFsaWQsIHNjaFZhbGlkKTtcbiAgICAgICAgICAgICAgICBjeHQubWVyZ2VWYWxpZEV2YWx1YXRlZChzY2hDeHQsIHZhbGlkKTtcbiAgICAgICAgICAgICAgICBpZiAoaWZDbGF1c2UpXG4gICAgICAgICAgICAgICAgICAgIGdlbi5hc3NpZ24oaWZDbGF1c2UsICgwLCBjb2RlZ2VuXzEuXykgYCR7a2V5d29yZH1gKTtcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIGN4dC5zZXRQYXJhbXMoeyBpZkNsYXVzZToga2V5d29yZCB9KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9LFxufTtcbmZ1bmN0aW9uIGhhc1NjaGVtYShpdCwga2V5d29yZCkge1xuICAgIGNvbnN0IHNjaGVtYSA9IGl0LnNjaGVtYVtrZXl3b3JkXTtcbiAgICByZXR1cm4gc2NoZW1hICE9PSB1bmRlZmluZWQgJiYgISgwLCB1dGlsXzEuYWx3YXlzVmFsaWRTY2hlbWEpKGl0LCBzY2hlbWEpO1xufVxuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aWYuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBhZGRpdGlvbmFsSXRlbXNfMSA9IHJlcXVpcmUoXCIuL2FkZGl0aW9uYWxJdGVtc1wiKTtcbmNvbnN0IHByZWZpeEl0ZW1zXzEgPSByZXF1aXJlKFwiLi9wcmVmaXhJdGVtc1wiKTtcbmNvbnN0IGl0ZW1zXzEgPSByZXF1aXJlKFwiLi9pdGVtc1wiKTtcbmNvbnN0IGl0ZW1zMjAyMF8xID0gcmVxdWlyZShcIi4vaXRlbXMyMDIwXCIpO1xuY29uc3QgY29udGFpbnNfMSA9IHJlcXVpcmUoXCIuL2NvbnRhaW5zXCIpO1xuY29uc3QgZGVwZW5kZW5jaWVzXzEgPSByZXF1aXJlKFwiLi9kZXBlbmRlbmNpZXNcIik7XG5jb25zdCBwcm9wZXJ0eU5hbWVzXzEgPSByZXF1aXJlKFwiLi9wcm9wZXJ0eU5hbWVzXCIpO1xuY29uc3QgYWRkaXRpb25hbFByb3BlcnRpZXNfMSA9IHJlcXVpcmUoXCIuL2FkZGl0aW9uYWxQcm9wZXJ0aWVzXCIpO1xuY29uc3QgcHJvcGVydGllc18xID0gcmVxdWlyZShcIi4vcHJvcGVydGllc1wiKTtcbmNvbnN0IHBhdHRlcm5Qcm9wZXJ0aWVzXzEgPSByZXF1aXJlKFwiLi9wYXR0ZXJuUHJvcGVydGllc1wiKTtcbmNvbnN0IG5vdF8xID0gcmVxdWlyZShcIi4vbm90XCIpO1xuY29uc3QgYW55T2ZfMSA9IHJlcXVpcmUoXCIuL2FueU9mXCIpO1xuY29uc3Qgb25lT2ZfMSA9IHJlcXVpcmUoXCIuL29uZU9mXCIpO1xuY29uc3QgYWxsT2ZfMSA9IHJlcXVpcmUoXCIuL2FsbE9mXCIpO1xuY29uc3QgaWZfMSA9IHJlcXVpcmUoXCIuL2lmXCIpO1xuY29uc3QgdGhlbkVsc2VfMSA9IHJlcXVpcmUoXCIuL3RoZW5FbHNlXCIpO1xuZnVuY3Rpb24gZ2V0QXBwbGljYXRvcihkcmFmdDIwMjAgPSBmYWxzZSkge1xuICAgIGNvbnN0IGFwcGxpY2F0b3IgPSBbXG4gICAgICAgIC8vIGFueVxuICAgICAgICBub3RfMS5kZWZhdWx0LFxuICAgICAgICBhbnlPZl8xLmRlZmF1bHQsXG4gICAgICAgIG9uZU9mXzEuZGVmYXVsdCxcbiAgICAgICAgYWxsT2ZfMS5kZWZhdWx0LFxuICAgICAgICBpZl8xLmRlZmF1bHQsXG4gICAgICAgIHRoZW5FbHNlXzEuZGVmYXVsdCxcbiAgICAgICAgLy8gb2JqZWN0XG4gICAgICAgIHByb3BlcnR5TmFtZXNfMS5kZWZhdWx0LFxuICAgICAgICBhZGRpdGlvbmFsUHJvcGVydGllc18xLmRlZmF1bHQsXG4gICAgICAgIGRlcGVuZGVuY2llc18xLmRlZmF1bHQsXG4gICAgICAgIHByb3BlcnRpZXNfMS5kZWZhdWx0LFxuICAgICAgICBwYXR0ZXJuUHJvcGVydGllc18xLmRlZmF1bHQsXG4gICAgXTtcbiAgICAvLyBhcnJheVxuICAgIGlmIChkcmFmdDIwMjApXG4gICAgICAgIGFwcGxpY2F0b3IucHVzaChwcmVmaXhJdGVtc18xLmRlZmF1bHQsIGl0ZW1zMjAyMF8xLmRlZmF1bHQpO1xuICAgIGVsc2VcbiAgICAgICAgYXBwbGljYXRvci5wdXNoKGFkZGl0aW9uYWxJdGVtc18xLmRlZmF1bHQsIGl0ZW1zXzEuZGVmYXVsdCk7XG4gICAgYXBwbGljYXRvci5wdXNoKGNvbnRhaW5zXzEuZGVmYXVsdCk7XG4gICAgcmV0dXJuIGFwcGxpY2F0b3I7XG59XG5leHBvcnRzLmRlZmF1bHQgPSBnZXRBcHBsaWNhdG9yO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leHBvcnRzLnZhbGlkYXRlVHVwbGUgPSB2b2lkIDA7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9jb2RlZ2VuXCIpO1xuY29uc3QgdXRpbF8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdXRpbFwiKTtcbmNvbnN0IGNvZGVfMSA9IHJlcXVpcmUoXCIuLi9jb2RlXCIpO1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwiaXRlbXNcIixcbiAgICB0eXBlOiBcImFycmF5XCIsXG4gICAgc2NoZW1hVHlwZTogW1wib2JqZWN0XCIsIFwiYXJyYXlcIiwgXCJib29sZWFuXCJdLFxuICAgIGJlZm9yZTogXCJ1bmlxdWVJdGVtc1wiLFxuICAgIGNvZGUoY3h0KSB7XG4gICAgICAgIGNvbnN0IHsgc2NoZW1hLCBpdCB9ID0gY3h0O1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShzY2hlbWEpKVxuICAgICAgICAgICAgcmV0dXJuIHZhbGlkYXRlVHVwbGUoY3h0LCBcImFkZGl0aW9uYWxJdGVtc1wiLCBzY2hlbWEpO1xuICAgICAgICBpdC5pdGVtcyA9IHRydWU7XG4gICAgICAgIGlmICgoMCwgdXRpbF8xLmFsd2F5c1ZhbGlkU2NoZW1hKShpdCwgc2NoZW1hKSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY3h0Lm9rKCgwLCBjb2RlXzEudmFsaWRhdGVBcnJheSkoY3h0KSk7XG4gICAgfSxcbn07XG5mdW5jdGlvbiB2YWxpZGF0ZVR1cGxlKGN4dCwgZXh0cmFJdGVtcywgc2NoQXJyID0gY3h0LnNjaGVtYSkge1xuICAgIGNvbnN0IHsgZ2VuLCBwYXJlbnRTY2hlbWEsIGRhdGEsIGtleXdvcmQsIGl0IH0gPSBjeHQ7XG4gICAgY2hlY2tTdHJpY3RUdXBsZShwYXJlbnRTY2hlbWEpO1xuICAgIGlmIChpdC5vcHRzLnVuZXZhbHVhdGVkICYmIHNjaEFyci5sZW5ndGggJiYgaXQuaXRlbXMgIT09IHRydWUpIHtcbiAgICAgICAgaXQuaXRlbXMgPSB1dGlsXzEubWVyZ2VFdmFsdWF0ZWQuaXRlbXMoZ2VuLCBzY2hBcnIubGVuZ3RoLCBpdC5pdGVtcyk7XG4gICAgfVxuICAgIGNvbnN0IHZhbGlkID0gZ2VuLm5hbWUoXCJ2YWxpZFwiKTtcbiAgICBjb25zdCBsZW4gPSBnZW4uY29uc3QoXCJsZW5cIiwgKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhfS5sZW5ndGhgKTtcbiAgICBzY2hBcnIuZm9yRWFjaCgoc2NoLCBpKSA9PiB7XG4gICAgICAgIGlmICgoMCwgdXRpbF8xLmFsd2F5c1ZhbGlkU2NoZW1hKShpdCwgc2NoKSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7bGVufSA+ICR7aX1gLCAoKSA9PiBjeHQuc3Vic2NoZW1hKHtcbiAgICAgICAgICAgIGtleXdvcmQsXG4gICAgICAgICAgICBzY2hlbWFQcm9wOiBpLFxuICAgICAgICAgICAgZGF0YVByb3A6IGksXG4gICAgICAgIH0sIHZhbGlkKSk7XG4gICAgICAgIGN4dC5vayh2YWxpZCk7XG4gICAgfSk7XG4gICAgZnVuY3Rpb24gY2hlY2tTdHJpY3RUdXBsZShzY2gpIHtcbiAgICAgICAgY29uc3QgeyBvcHRzLCBlcnJTY2hlbWFQYXRoIH0gPSBpdDtcbiAgICAgICAgY29uc3QgbCA9IHNjaEFyci5sZW5ndGg7XG4gICAgICAgIGNvbnN0IGZ1bGxUdXBsZSA9IGwgPT09IHNjaC5taW5JdGVtcyAmJiAobCA9PT0gc2NoLm1heEl0ZW1zIHx8IHNjaFtleHRyYUl0ZW1zXSA9PT0gZmFsc2UpO1xuICAgICAgICBpZiAob3B0cy5zdHJpY3RUdXBsZXMgJiYgIWZ1bGxUdXBsZSkge1xuICAgICAgICAgICAgY29uc3QgbXNnID0gYFwiJHtrZXl3b3JkfVwiIGlzICR7bH0tdHVwbGUsIGJ1dCBtaW5JdGVtcyBvciBtYXhJdGVtcy8ke2V4dHJhSXRlbXN9IGFyZSBub3Qgc3BlY2lmaWVkIG9yIGRpZmZlcmVudCBhdCBwYXRoIFwiJHtlcnJTY2hlbWFQYXRofVwiYDtcbiAgICAgICAgICAgICgwLCB1dGlsXzEuY2hlY2tTdHJpY3RNb2RlKShpdCwgbXNnLCBvcHRzLnN0cmljdFR1cGxlcyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5leHBvcnRzLnZhbGlkYXRlVHVwbGUgPSB2YWxpZGF0ZVR1cGxlO1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aXRlbXMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9jb2RlZ2VuXCIpO1xuY29uc3QgdXRpbF8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdXRpbFwiKTtcbmNvbnN0IGNvZGVfMSA9IHJlcXVpcmUoXCIuLi9jb2RlXCIpO1xuY29uc3QgYWRkaXRpb25hbEl0ZW1zXzEgPSByZXF1aXJlKFwiLi9hZGRpdGlvbmFsSXRlbXNcIik7XG5jb25zdCBlcnJvciA9IHtcbiAgICBtZXNzYWdlOiAoeyBwYXJhbXM6IHsgbGVuIH0gfSkgPT4gKDAsIGNvZGVnZW5fMS5zdHIpIGBtdXN0IE5PVCBoYXZlIG1vcmUgdGhhbiAke2xlbn0gaXRlbXNgLFxuICAgIHBhcmFtczogKHsgcGFyYW1zOiB7IGxlbiB9IH0pID0+ICgwLCBjb2RlZ2VuXzEuXykgYHtsaW1pdDogJHtsZW59fWAsXG59O1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwiaXRlbXNcIixcbiAgICB0eXBlOiBcImFycmF5XCIsXG4gICAgc2NoZW1hVHlwZTogW1wib2JqZWN0XCIsIFwiYm9vbGVhblwiXSxcbiAgICBiZWZvcmU6IFwidW5pcXVlSXRlbXNcIixcbiAgICBlcnJvcixcbiAgICBjb2RlKGN4dCkge1xuICAgICAgICBjb25zdCB7IHNjaGVtYSwgcGFyZW50U2NoZW1hLCBpdCB9ID0gY3h0O1xuICAgICAgICBjb25zdCB7IHByZWZpeEl0ZW1zIH0gPSBwYXJlbnRTY2hlbWE7XG4gICAgICAgIGl0Lml0ZW1zID0gdHJ1ZTtcbiAgICAgICAgaWYgKCgwLCB1dGlsXzEuYWx3YXlzVmFsaWRTY2hlbWEpKGl0LCBzY2hlbWEpKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBpZiAocHJlZml4SXRlbXMpXG4gICAgICAgICAgICAoMCwgYWRkaXRpb25hbEl0ZW1zXzEudmFsaWRhdGVBZGRpdGlvbmFsSXRlbXMpKGN4dCwgcHJlZml4SXRlbXMpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICBjeHQub2soKDAsIGNvZGVfMS52YWxpZGF0ZUFycmF5KShjeHQpKTtcbiAgICB9LFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWl0ZW1zMjAyMC5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL3V0aWxcIik7XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogXCJub3RcIixcbiAgICBzY2hlbWFUeXBlOiBbXCJvYmplY3RcIiwgXCJib29sZWFuXCJdLFxuICAgIHRyYWNrRXJyb3JzOiB0cnVlLFxuICAgIGNvZGUoY3h0KSB7XG4gICAgICAgIGNvbnN0IHsgZ2VuLCBzY2hlbWEsIGl0IH0gPSBjeHQ7XG4gICAgICAgIGlmICgoMCwgdXRpbF8xLmFsd2F5c1ZhbGlkU2NoZW1hKShpdCwgc2NoZW1hKSkge1xuICAgICAgICAgICAgY3h0LmZhaWwoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi5uYW1lKFwidmFsaWRcIik7XG4gICAgICAgIGN4dC5zdWJzY2hlbWEoe1xuICAgICAgICAgICAga2V5d29yZDogXCJub3RcIixcbiAgICAgICAgICAgIGNvbXBvc2l0ZVJ1bGU6IHRydWUsXG4gICAgICAgICAgICBjcmVhdGVFcnJvcnM6IGZhbHNlLFxuICAgICAgICAgICAgYWxsRXJyb3JzOiBmYWxzZSxcbiAgICAgICAgfSwgdmFsaWQpO1xuICAgICAgICBjeHQuZmFpbFJlc3VsdCh2YWxpZCwgKCkgPT4gY3h0LnJlc2V0KCksICgpID0+IGN4dC5lcnJvcigpKTtcbiAgICB9LFxuICAgIGVycm9yOiB7IG1lc3NhZ2U6IFwibXVzdCBOT1QgYmUgdmFsaWRcIiB9LFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPW5vdC5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL2NvZGVnZW5cIik7XG5jb25zdCB1dGlsXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS91dGlsXCIpO1xuY29uc3QgZXJyb3IgPSB7XG4gICAgbWVzc2FnZTogXCJtdXN0IG1hdGNoIGV4YWN0bHkgb25lIHNjaGVtYSBpbiBvbmVPZlwiLFxuICAgIHBhcmFtczogKHsgcGFyYW1zIH0pID0+ICgwLCBjb2RlZ2VuXzEuXykgYHtwYXNzaW5nU2NoZW1hczogJHtwYXJhbXMucGFzc2luZ319YCxcbn07XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogXCJvbmVPZlwiLFxuICAgIHNjaGVtYVR5cGU6IFwiYXJyYXlcIixcbiAgICB0cmFja0Vycm9yczogdHJ1ZSxcbiAgICBlcnJvcixcbiAgICBjb2RlKGN4dCkge1xuICAgICAgICBjb25zdCB7IGdlbiwgc2NoZW1hLCBwYXJlbnRTY2hlbWEsIGl0IH0gPSBjeHQ7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoc2NoZW1hKSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImFqdiBpbXBsZW1lbnRhdGlvbiBlcnJvclwiKTtcbiAgICAgICAgaWYgKGl0Lm9wdHMuZGlzY3JpbWluYXRvciAmJiBwYXJlbnRTY2hlbWEuZGlzY3JpbWluYXRvcilcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3Qgc2NoQXJyID0gc2NoZW1hO1xuICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi5sZXQoXCJ2YWxpZFwiLCBmYWxzZSk7XG4gICAgICAgIGNvbnN0IHBhc3NpbmcgPSBnZW4ubGV0KFwicGFzc2luZ1wiLCBudWxsKTtcbiAgICAgICAgY29uc3Qgc2NoVmFsaWQgPSBnZW4ubmFtZShcIl92YWxpZFwiKTtcbiAgICAgICAgY3h0LnNldFBhcmFtcyh7IHBhc3NpbmcgfSk7XG4gICAgICAgIC8vIFRPRE8gcG9zc2libHkgZmFpbCBzdHJhaWdodCBhd2F5ICh3aXRoIHdhcm5pbmcgb3IgZXhjZXB0aW9uKSBpZiB0aGVyZSBhcmUgdHdvIGVtcHR5IGFsd2F5cyB2YWxpZCBzY2hlbWFzXG4gICAgICAgIGdlbi5ibG9jayh2YWxpZGF0ZU9uZU9mKTtcbiAgICAgICAgY3h0LnJlc3VsdCh2YWxpZCwgKCkgPT4gY3h0LnJlc2V0KCksICgpID0+IGN4dC5lcnJvcih0cnVlKSk7XG4gICAgICAgIGZ1bmN0aW9uIHZhbGlkYXRlT25lT2YoKSB7XG4gICAgICAgICAgICBzY2hBcnIuZm9yRWFjaCgoc2NoLCBpKSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IHNjaEN4dDtcbiAgICAgICAgICAgICAgICBpZiAoKDAsIHV0aWxfMS5hbHdheXNWYWxpZFNjaGVtYSkoaXQsIHNjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2VuLnZhcihzY2hWYWxpZCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzY2hDeHQgPSBjeHQuc3Vic2NoZW1hKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXdvcmQ6IFwib25lT2ZcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjaGVtYVByb3A6IGksXG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wb3NpdGVSdWxlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICB9LCBzY2hWYWxpZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBnZW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC5pZigoMCwgY29kZWdlbl8xLl8pIGAke3NjaFZhbGlkfSAmJiAke3ZhbGlkfWApXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXNzaWduKHZhbGlkLCBmYWxzZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5hc3NpZ24ocGFzc2luZywgKDAsIGNvZGVnZW5fMS5fKSBgWyR7cGFzc2luZ30sICR7aX1dYClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5lbHNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGdlbi5pZihzY2hWYWxpZCwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBnZW4uYXNzaWduKHZhbGlkLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgZ2VuLmFzc2lnbihwYXNzaW5nLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNjaEN4dClcbiAgICAgICAgICAgICAgICAgICAgICAgIGN4dC5tZXJnZUV2YWx1YXRlZChzY2hDeHQsIGNvZGVnZW5fMS5OYW1lKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSxcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBkZWY7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1vbmVPZi5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGNvZGVfMSA9IHJlcXVpcmUoXCIuLi9jb2RlXCIpO1xuY29uc3QgY29kZWdlbl8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvY29kZWdlblwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL3V0aWxcIik7XG5jb25zdCB1dGlsXzIgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS91dGlsXCIpO1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwicGF0dGVyblByb3BlcnRpZXNcIixcbiAgICB0eXBlOiBcIm9iamVjdFwiLFxuICAgIHNjaGVtYVR5cGU6IFwib2JqZWN0XCIsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgeyBnZW4sIHNjaGVtYSwgZGF0YSwgcGFyZW50U2NoZW1hLCBpdCB9ID0gY3h0O1xuICAgICAgICBjb25zdCB7IG9wdHMgfSA9IGl0O1xuICAgICAgICBjb25zdCBwYXR0ZXJucyA9ICgwLCBjb2RlXzEuYWxsU2NoZW1hUHJvcGVydGllcykoc2NoZW1hKTtcbiAgICAgICAgY29uc3QgYWx3YXlzVmFsaWRQYXR0ZXJucyA9IHBhdHRlcm5zLmZpbHRlcigocCkgPT4gKDAsIHV0aWxfMS5hbHdheXNWYWxpZFNjaGVtYSkoaXQsIHNjaGVtYVtwXSkpO1xuICAgICAgICBpZiAocGF0dGVybnMubGVuZ3RoID09PSAwIHx8XG4gICAgICAgICAgICAoYWx3YXlzVmFsaWRQYXR0ZXJucy5sZW5ndGggPT09IHBhdHRlcm5zLmxlbmd0aCAmJlxuICAgICAgICAgICAgICAgICghaXQub3B0cy51bmV2YWx1YXRlZCB8fCBpdC5wcm9wcyA9PT0gdHJ1ZSkpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2hlY2tQcm9wZXJ0aWVzID0gb3B0cy5zdHJpY3RTY2hlbWEgJiYgIW9wdHMuYWxsb3dNYXRjaGluZ1Byb3BlcnRpZXMgJiYgcGFyZW50U2NoZW1hLnByb3BlcnRpZXM7XG4gICAgICAgIGNvbnN0IHZhbGlkID0gZ2VuLm5hbWUoXCJ2YWxpZFwiKTtcbiAgICAgICAgaWYgKGl0LnByb3BzICE9PSB0cnVlICYmICEoaXQucHJvcHMgaW5zdGFuY2VvZiBjb2RlZ2VuXzEuTmFtZSkpIHtcbiAgICAgICAgICAgIGl0LnByb3BzID0gKDAsIHV0aWxfMi5ldmFsdWF0ZWRQcm9wc1RvTmFtZSkoZ2VuLCBpdC5wcm9wcyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyBwcm9wcyB9ID0gaXQ7XG4gICAgICAgIHZhbGlkYXRlUGF0dGVyblByb3BlcnRpZXMoKTtcbiAgICAgICAgZnVuY3Rpb24gdmFsaWRhdGVQYXR0ZXJuUHJvcGVydGllcygpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcGF0IG9mIHBhdHRlcm5zKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNoZWNrUHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tNYXRjaGluZ1Byb3BlcnRpZXMocGF0KTtcbiAgICAgICAgICAgICAgICBpZiAoaXQuYWxsRXJyb3JzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRlUHJvcGVydGllcyhwYXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZ2VuLnZhcih2YWxpZCwgdHJ1ZSk7IC8vIFRPRE8gdmFyXG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRlUHJvcGVydGllcyhwYXQpO1xuICAgICAgICAgICAgICAgICAgICBnZW4uaWYodmFsaWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBjaGVja01hdGNoaW5nUHJvcGVydGllcyhwYXQpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcHJvcCBpbiBjaGVja1Byb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAobmV3IFJlZ0V4cChwYXQpLnRlc3QocHJvcCkpIHtcbiAgICAgICAgICAgICAgICAgICAgKDAsIHV0aWxfMS5jaGVja1N0cmljdE1vZGUpKGl0LCBgcHJvcGVydHkgJHtwcm9wfSBtYXRjaGVzIHBhdHRlcm4gJHtwYXR9ICh1c2UgYWxsb3dNYXRjaGluZ1Byb3BlcnRpZXMpYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIHZhbGlkYXRlUHJvcGVydGllcyhwYXQpIHtcbiAgICAgICAgICAgIGdlbi5mb3JJbihcImtleVwiLCBkYXRhLCAoa2V5KSA9PiB7XG4gICAgICAgICAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7KDAsIGNvZGVfMS51c2VQYXR0ZXJuKShjeHQsIHBhdCl9LnRlc3QoJHtrZXl9KWAsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYWx3YXlzVmFsaWQgPSBhbHdheXNWYWxpZFBhdHRlcm5zLmluY2x1ZGVzKHBhdCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghYWx3YXlzVmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN4dC5zdWJzY2hlbWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleXdvcmQ6IFwicGF0dGVyblByb3BlcnRpZXNcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2hlbWFQcm9wOiBwYXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVByb3A6IGtleSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhUHJvcFR5cGU6IHV0aWxfMi5UeXBlLlN0cixcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIHZhbGlkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoaXQub3B0cy51bmV2YWx1YXRlZCAmJiBwcm9wcyAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2VuLmFzc2lnbigoMCwgY29kZWdlbl8xLl8pIGAke3Byb3BzfVske2tleX1dYCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIWFsd2F5c1ZhbGlkICYmICFpdC5hbGxFcnJvcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNhbiBzaG9ydC1jaXJjdWl0IGlmIGB1bmV2YWx1YXRlZFByb3BlcnRpZXNgIGlzIG5vdCBzdXBwb3J0ZWQgKG9wdHMubmV4dCA9PT0gZmFsc2UpXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBvciBpZiBhbGwgcHJvcGVydGllcyB3ZXJlIGV2YWx1YXRlZCAocHJvcHMgPT09IHRydWUpXG4gICAgICAgICAgICAgICAgICAgICAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5ub3QpKHZhbGlkKSwgKCkgPT4gZ2VuLmJyZWFrKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0sXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cGF0dGVyblByb3BlcnRpZXMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBpdGVtc18xID0gcmVxdWlyZShcIi4vaXRlbXNcIik7XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogXCJwcmVmaXhJdGVtc1wiLFxuICAgIHR5cGU6IFwiYXJyYXlcIixcbiAgICBzY2hlbWFUeXBlOiBbXCJhcnJheVwiXSxcbiAgICBiZWZvcmU6IFwidW5pcXVlSXRlbXNcIixcbiAgICBjb2RlOiAoY3h0KSA9PiAoMCwgaXRlbXNfMS52YWxpZGF0ZVR1cGxlKShjeHQsIFwiaXRlbXNcIiksXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cHJlZml4SXRlbXMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCB2YWxpZGF0ZV8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdmFsaWRhdGVcIik7XG5jb25zdCBjb2RlXzEgPSByZXF1aXJlKFwiLi4vY29kZVwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL3V0aWxcIik7XG5jb25zdCBhZGRpdGlvbmFsUHJvcGVydGllc18xID0gcmVxdWlyZShcIi4vYWRkaXRpb25hbFByb3BlcnRpZXNcIik7XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogXCJwcm9wZXJ0aWVzXCIsXG4gICAgdHlwZTogXCJvYmplY3RcIixcbiAgICBzY2hlbWFUeXBlOiBcIm9iamVjdFwiLFxuICAgIGNvZGUoY3h0KSB7XG4gICAgICAgIGNvbnN0IHsgZ2VuLCBzY2hlbWEsIHBhcmVudFNjaGVtYSwgZGF0YSwgaXQgfSA9IGN4dDtcbiAgICAgICAgaWYgKGl0Lm9wdHMucmVtb3ZlQWRkaXRpb25hbCA9PT0gXCJhbGxcIiAmJiBwYXJlbnRTY2hlbWEuYWRkaXRpb25hbFByb3BlcnRpZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgYWRkaXRpb25hbFByb3BlcnRpZXNfMS5kZWZhdWx0LmNvZGUobmV3IHZhbGlkYXRlXzEuS2V5d29yZEN4dChpdCwgYWRkaXRpb25hbFByb3BlcnRpZXNfMS5kZWZhdWx0LCBcImFkZGl0aW9uYWxQcm9wZXJ0aWVzXCIpKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhbGxQcm9wcyA9ICgwLCBjb2RlXzEuYWxsU2NoZW1hUHJvcGVydGllcykoc2NoZW1hKTtcbiAgICAgICAgZm9yIChjb25zdCBwcm9wIG9mIGFsbFByb3BzKSB7XG4gICAgICAgICAgICBpdC5kZWZpbmVkUHJvcGVydGllcy5hZGQocHJvcCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGl0Lm9wdHMudW5ldmFsdWF0ZWQgJiYgYWxsUHJvcHMubGVuZ3RoICYmIGl0LnByb3BzICE9PSB0cnVlKSB7XG4gICAgICAgICAgICBpdC5wcm9wcyA9IHV0aWxfMS5tZXJnZUV2YWx1YXRlZC5wcm9wcyhnZW4sICgwLCB1dGlsXzEudG9IYXNoKShhbGxQcm9wcyksIGl0LnByb3BzKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwcm9wZXJ0aWVzID0gYWxsUHJvcHMuZmlsdGVyKChwKSA9PiAhKDAsIHV0aWxfMS5hbHdheXNWYWxpZFNjaGVtYSkoaXQsIHNjaGVtYVtwXSkpO1xuICAgICAgICBpZiAocHJvcGVydGllcy5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNvbnN0IHZhbGlkID0gZ2VuLm5hbWUoXCJ2YWxpZFwiKTtcbiAgICAgICAgZm9yIChjb25zdCBwcm9wIG9mIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIGlmIChoYXNEZWZhdWx0KHByb3ApKSB7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0eVNjaGVtYShwcm9wKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGdlbi5pZigoMCwgY29kZV8xLnByb3BlcnR5SW5EYXRhKShnZW4sIGRhdGEsIHByb3AsIGl0Lm9wdHMub3duUHJvcGVydGllcykpO1xuICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydHlTY2hlbWEocHJvcCk7XG4gICAgICAgICAgICAgICAgaWYgKCFpdC5hbGxFcnJvcnMpXG4gICAgICAgICAgICAgICAgICAgIGdlbi5lbHNlKCkudmFyKHZhbGlkLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBnZW4uZW5kSWYoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN4dC5pdC5kZWZpbmVkUHJvcGVydGllcy5hZGQocHJvcCk7XG4gICAgICAgICAgICBjeHQub2sodmFsaWQpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGhhc0RlZmF1bHQocHJvcCkge1xuICAgICAgICAgICAgcmV0dXJuIGl0Lm9wdHMudXNlRGVmYXVsdHMgJiYgIWl0LmNvbXBvc2l0ZVJ1bGUgJiYgc2NoZW1hW3Byb3BdLmRlZmF1bHQgIT09IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnR5U2NoZW1hKHByb3ApIHtcbiAgICAgICAgICAgIGN4dC5zdWJzY2hlbWEoe1xuICAgICAgICAgICAgICAgIGtleXdvcmQ6IFwicHJvcGVydGllc1wiLFxuICAgICAgICAgICAgICAgIHNjaGVtYVByb3A6IHByb3AsXG4gICAgICAgICAgICAgICAgZGF0YVByb3A6IHByb3AsXG4gICAgICAgICAgICB9LCB2YWxpZCk7XG4gICAgICAgIH1cbiAgICB9LFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXByb3BlcnRpZXMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9jb2RlZ2VuXCIpO1xuY29uc3QgdXRpbF8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdXRpbFwiKTtcbmNvbnN0IGVycm9yID0ge1xuICAgIG1lc3NhZ2U6IFwicHJvcGVydHkgbmFtZSBtdXN0IGJlIHZhbGlkXCIsXG4gICAgcGFyYW1zOiAoeyBwYXJhbXMgfSkgPT4gKDAsIGNvZGVnZW5fMS5fKSBge3Byb3BlcnR5TmFtZTogJHtwYXJhbXMucHJvcGVydHlOYW1lfX1gLFxufTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBcInByb3BlcnR5TmFtZXNcIixcbiAgICB0eXBlOiBcIm9iamVjdFwiLFxuICAgIHNjaGVtYVR5cGU6IFtcIm9iamVjdFwiLCBcImJvb2xlYW5cIl0sXG4gICAgZXJyb3IsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgeyBnZW4sIHNjaGVtYSwgZGF0YSwgaXQgfSA9IGN4dDtcbiAgICAgICAgaWYgKCgwLCB1dGlsXzEuYWx3YXlzVmFsaWRTY2hlbWEpKGl0LCBzY2hlbWEpKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi5uYW1lKFwidmFsaWRcIik7XG4gICAgICAgIGdlbi5mb3JJbihcImtleVwiLCBkYXRhLCAoa2V5KSA9PiB7XG4gICAgICAgICAgICBjeHQuc2V0UGFyYW1zKHsgcHJvcGVydHlOYW1lOiBrZXkgfSk7XG4gICAgICAgICAgICBjeHQuc3Vic2NoZW1hKHtcbiAgICAgICAgICAgICAgICBrZXl3b3JkOiBcInByb3BlcnR5TmFtZXNcIixcbiAgICAgICAgICAgICAgICBkYXRhOiBrZXksXG4gICAgICAgICAgICAgICAgZGF0YVR5cGVzOiBbXCJzdHJpbmdcIl0sXG4gICAgICAgICAgICAgICAgcHJvcGVydHlOYW1lOiBrZXksXG4gICAgICAgICAgICAgICAgY29tcG9zaXRlUnVsZTogdHJ1ZSxcbiAgICAgICAgICAgIH0sIHZhbGlkKTtcbiAgICAgICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLm5vdCkodmFsaWQpLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY3h0LmVycm9yKHRydWUpO1xuICAgICAgICAgICAgICAgIGlmICghaXQuYWxsRXJyb3JzKVxuICAgICAgICAgICAgICAgICAgICBnZW4uYnJlYWsoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgY3h0Lm9rKHZhbGlkKTtcbiAgICB9LFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXByb3BlcnR5TmFtZXMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCB1dGlsXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS91dGlsXCIpO1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFtcInRoZW5cIiwgXCJlbHNlXCJdLFxuICAgIHNjaGVtYVR5cGU6IFtcIm9iamVjdFwiLCBcImJvb2xlYW5cIl0sXG4gICAgY29kZSh7IGtleXdvcmQsIHBhcmVudFNjaGVtYSwgaXQgfSkge1xuICAgICAgICBpZiAocGFyZW50U2NoZW1hLmlmID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICAoMCwgdXRpbF8xLmNoZWNrU3RyaWN0TW9kZSkoaXQsIGBcIiR7a2V5d29yZH1cIiB3aXRob3V0IFwiaWZcIiBpcyBpZ25vcmVkYCk7XG4gICAgfSxcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBkZWY7XG4vLyMgc291cmNlTWFwcGluZ1VSTD10aGVuRWxzZS5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmV4cG9ydHMudmFsaWRhdGVVbmlvbiA9IGV4cG9ydHMudmFsaWRhdGVBcnJheSA9IGV4cG9ydHMudXNlUGF0dGVybiA9IGV4cG9ydHMuY2FsbFZhbGlkYXRlQ29kZSA9IGV4cG9ydHMuc2NoZW1hUHJvcGVydGllcyA9IGV4cG9ydHMuYWxsU2NoZW1hUHJvcGVydGllcyA9IGV4cG9ydHMubm9Qcm9wZXJ0eUluRGF0YSA9IGV4cG9ydHMucHJvcGVydHlJbkRhdGEgPSBleHBvcnRzLmlzT3duUHJvcGVydHkgPSBleHBvcnRzLmhhc1Byb3BGdW5jID0gZXhwb3J0cy5yZXBvcnRNaXNzaW5nUHJvcCA9IGV4cG9ydHMuY2hlY2tNaXNzaW5nUHJvcCA9IGV4cG9ydHMuY2hlY2tSZXBvcnRNaXNzaW5nUHJvcCA9IHZvaWQgMDtcbmNvbnN0IGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuLi9jb21waWxlL2NvZGVnZW5cIik7XG5jb25zdCB1dGlsXzEgPSByZXF1aXJlKFwiLi4vY29tcGlsZS91dGlsXCIpO1xuY29uc3QgbmFtZXNfMSA9IHJlcXVpcmUoXCIuLi9jb21waWxlL25hbWVzXCIpO1xuY29uc3QgdXRpbF8yID0gcmVxdWlyZShcIi4uL2NvbXBpbGUvdXRpbFwiKTtcbmZ1bmN0aW9uIGNoZWNrUmVwb3J0TWlzc2luZ1Byb3AoY3h0LCBwcm9wKSB7XG4gICAgY29uc3QgeyBnZW4sIGRhdGEsIGl0IH0gPSBjeHQ7XG4gICAgZ2VuLmlmKG5vUHJvcGVydHlJbkRhdGEoZ2VuLCBkYXRhLCBwcm9wLCBpdC5vcHRzLm93blByb3BlcnRpZXMpLCAoKSA9PiB7XG4gICAgICAgIGN4dC5zZXRQYXJhbXMoeyBtaXNzaW5nUHJvcGVydHk6ICgwLCBjb2RlZ2VuXzEuXykgYCR7cHJvcH1gIH0sIHRydWUpO1xuICAgICAgICBjeHQuZXJyb3IoKTtcbiAgICB9KTtcbn1cbmV4cG9ydHMuY2hlY2tSZXBvcnRNaXNzaW5nUHJvcCA9IGNoZWNrUmVwb3J0TWlzc2luZ1Byb3A7XG5mdW5jdGlvbiBjaGVja01pc3NpbmdQcm9wKHsgZ2VuLCBkYXRhLCBpdDogeyBvcHRzIH0gfSwgcHJvcGVydGllcywgbWlzc2luZykge1xuICAgIHJldHVybiAoMCwgY29kZWdlbl8xLm9yKSguLi5wcm9wZXJ0aWVzLm1hcCgocHJvcCkgPT4gKDAsIGNvZGVnZW5fMS5hbmQpKG5vUHJvcGVydHlJbkRhdGEoZ2VuLCBkYXRhLCBwcm9wLCBvcHRzLm93blByb3BlcnRpZXMpLCAoMCwgY29kZWdlbl8xLl8pIGAke21pc3Npbmd9ID0gJHtwcm9wfWApKSk7XG59XG5leHBvcnRzLmNoZWNrTWlzc2luZ1Byb3AgPSBjaGVja01pc3NpbmdQcm9wO1xuZnVuY3Rpb24gcmVwb3J0TWlzc2luZ1Byb3AoY3h0LCBtaXNzaW5nKSB7XG4gICAgY3h0LnNldFBhcmFtcyh7IG1pc3NpbmdQcm9wZXJ0eTogbWlzc2luZyB9LCB0cnVlKTtcbiAgICBjeHQuZXJyb3IoKTtcbn1cbmV4cG9ydHMucmVwb3J0TWlzc2luZ1Byb3AgPSByZXBvcnRNaXNzaW5nUHJvcDtcbmZ1bmN0aW9uIGhhc1Byb3BGdW5jKGdlbikge1xuICAgIHJldHVybiBnZW4uc2NvcGVWYWx1ZShcImZ1bmNcIiwge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L3VuYm91bmQtbWV0aG9kXG4gICAgICAgIHJlZjogT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eSxcbiAgICAgICAgY29kZTogKDAsIGNvZGVnZW5fMS5fKSBgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eWAsXG4gICAgfSk7XG59XG5leHBvcnRzLmhhc1Byb3BGdW5jID0gaGFzUHJvcEZ1bmM7XG5mdW5jdGlvbiBpc093blByb3BlcnR5KGdlbiwgZGF0YSwgcHJvcGVydHkpIHtcbiAgICByZXR1cm4gKDAsIGNvZGVnZW5fMS5fKSBgJHtoYXNQcm9wRnVuYyhnZW4pfS5jYWxsKCR7ZGF0YX0sICR7cHJvcGVydHl9KWA7XG59XG5leHBvcnRzLmlzT3duUHJvcGVydHkgPSBpc093blByb3BlcnR5O1xuZnVuY3Rpb24gcHJvcGVydHlJbkRhdGEoZ2VuLCBkYXRhLCBwcm9wZXJ0eSwgb3duUHJvcGVydGllcykge1xuICAgIGNvbnN0IGNvbmQgPSAoMCwgY29kZWdlbl8xLl8pIGAke2RhdGF9JHsoMCwgY29kZWdlbl8xLmdldFByb3BlcnR5KShwcm9wZXJ0eSl9ICE9PSB1bmRlZmluZWRgO1xuICAgIHJldHVybiBvd25Qcm9wZXJ0aWVzID8gKDAsIGNvZGVnZW5fMS5fKSBgJHtjb25kfSAmJiAke2lzT3duUHJvcGVydHkoZ2VuLCBkYXRhLCBwcm9wZXJ0eSl9YCA6IGNvbmQ7XG59XG5leHBvcnRzLnByb3BlcnR5SW5EYXRhID0gcHJvcGVydHlJbkRhdGE7XG5mdW5jdGlvbiBub1Byb3BlcnR5SW5EYXRhKGdlbiwgZGF0YSwgcHJvcGVydHksIG93blByb3BlcnRpZXMpIHtcbiAgICBjb25zdCBjb25kID0gKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhfSR7KDAsIGNvZGVnZW5fMS5nZXRQcm9wZXJ0eSkocHJvcGVydHkpfSA9PT0gdW5kZWZpbmVkYDtcbiAgICByZXR1cm4gb3duUHJvcGVydGllcyA/ICgwLCBjb2RlZ2VuXzEub3IpKGNvbmQsICgwLCBjb2RlZ2VuXzEubm90KShpc093blByb3BlcnR5KGdlbiwgZGF0YSwgcHJvcGVydHkpKSkgOiBjb25kO1xufVxuZXhwb3J0cy5ub1Byb3BlcnR5SW5EYXRhID0gbm9Qcm9wZXJ0eUluRGF0YTtcbmZ1bmN0aW9uIGFsbFNjaGVtYVByb3BlcnRpZXMoc2NoZW1hTWFwKSB7XG4gICAgcmV0dXJuIHNjaGVtYU1hcCA/IE9iamVjdC5rZXlzKHNjaGVtYU1hcCkuZmlsdGVyKChwKSA9PiBwICE9PSBcIl9fcHJvdG9fX1wiKSA6IFtdO1xufVxuZXhwb3J0cy5hbGxTY2hlbWFQcm9wZXJ0aWVzID0gYWxsU2NoZW1hUHJvcGVydGllcztcbmZ1bmN0aW9uIHNjaGVtYVByb3BlcnRpZXMoaXQsIHNjaGVtYU1hcCkge1xuICAgIHJldHVybiBhbGxTY2hlbWFQcm9wZXJ0aWVzKHNjaGVtYU1hcCkuZmlsdGVyKChwKSA9PiAhKDAsIHV0aWxfMS5hbHdheXNWYWxpZFNjaGVtYSkoaXQsIHNjaGVtYU1hcFtwXSkpO1xufVxuZXhwb3J0cy5zY2hlbWFQcm9wZXJ0aWVzID0gc2NoZW1hUHJvcGVydGllcztcbmZ1bmN0aW9uIGNhbGxWYWxpZGF0ZUNvZGUoeyBzY2hlbWFDb2RlLCBkYXRhLCBpdDogeyBnZW4sIHRvcFNjaGVtYVJlZiwgc2NoZW1hUGF0aCwgZXJyb3JQYXRoIH0sIGl0IH0sIGZ1bmMsIGNvbnRleHQsIHBhc3NTY2hlbWEpIHtcbiAgICBjb25zdCBkYXRhQW5kU2NoZW1hID0gcGFzc1NjaGVtYSA/ICgwLCBjb2RlZ2VuXzEuXykgYCR7c2NoZW1hQ29kZX0sICR7ZGF0YX0sICR7dG9wU2NoZW1hUmVmfSR7c2NoZW1hUGF0aH1gIDogZGF0YTtcbiAgICBjb25zdCB2YWxDeHQgPSBbXG4gICAgICAgIFtuYW1lc18xLmRlZmF1bHQuaW5zdGFuY2VQYXRoLCAoMCwgY29kZWdlbl8xLnN0ckNvbmNhdCkobmFtZXNfMS5kZWZhdWx0Lmluc3RhbmNlUGF0aCwgZXJyb3JQYXRoKV0sXG4gICAgICAgIFtuYW1lc18xLmRlZmF1bHQucGFyZW50RGF0YSwgaXQucGFyZW50RGF0YV0sXG4gICAgICAgIFtuYW1lc18xLmRlZmF1bHQucGFyZW50RGF0YVByb3BlcnR5LCBpdC5wYXJlbnREYXRhUHJvcGVydHldLFxuICAgICAgICBbbmFtZXNfMS5kZWZhdWx0LnJvb3REYXRhLCBuYW1lc18xLmRlZmF1bHQucm9vdERhdGFdLFxuICAgIF07XG4gICAgaWYgKGl0Lm9wdHMuZHluYW1pY1JlZilcbiAgICAgICAgdmFsQ3h0LnB1c2goW25hbWVzXzEuZGVmYXVsdC5keW5hbWljQW5jaG9ycywgbmFtZXNfMS5kZWZhdWx0LmR5bmFtaWNBbmNob3JzXSk7XG4gICAgY29uc3QgYXJncyA9ICgwLCBjb2RlZ2VuXzEuXykgYCR7ZGF0YUFuZFNjaGVtYX0sICR7Z2VuLm9iamVjdCguLi52YWxDeHQpfWA7XG4gICAgcmV0dXJuIGNvbnRleHQgIT09IGNvZGVnZW5fMS5uaWwgPyAoMCwgY29kZWdlbl8xLl8pIGAke2Z1bmN9LmNhbGwoJHtjb250ZXh0fSwgJHthcmdzfSlgIDogKDAsIGNvZGVnZW5fMS5fKSBgJHtmdW5jfSgke2FyZ3N9KWA7XG59XG5leHBvcnRzLmNhbGxWYWxpZGF0ZUNvZGUgPSBjYWxsVmFsaWRhdGVDb2RlO1xuY29uc3QgbmV3UmVnRXhwID0gKDAsIGNvZGVnZW5fMS5fKSBgbmV3IFJlZ0V4cGA7XG5mdW5jdGlvbiB1c2VQYXR0ZXJuKHsgZ2VuLCBpdDogeyBvcHRzIH0gfSwgcGF0dGVybikge1xuICAgIGNvbnN0IHUgPSBvcHRzLnVuaWNvZGVSZWdFeHAgPyBcInVcIiA6IFwiXCI7XG4gICAgY29uc3QgeyByZWdFeHAgfSA9IG9wdHMuY29kZTtcbiAgICBjb25zdCByeCA9IHJlZ0V4cChwYXR0ZXJuLCB1KTtcbiAgICByZXR1cm4gZ2VuLnNjb3BlVmFsdWUoXCJwYXR0ZXJuXCIsIHtcbiAgICAgICAga2V5OiByeC50b1N0cmluZygpLFxuICAgICAgICByZWY6IHJ4LFxuICAgICAgICBjb2RlOiAoMCwgY29kZWdlbl8xLl8pIGAke3JlZ0V4cC5jb2RlID09PSBcIm5ldyBSZWdFeHBcIiA/IG5ld1JlZ0V4cCA6ICgwLCB1dGlsXzIudXNlRnVuYykoZ2VuLCByZWdFeHApfSgke3BhdHRlcm59LCAke3V9KWAsXG4gICAgfSk7XG59XG5leHBvcnRzLnVzZVBhdHRlcm4gPSB1c2VQYXR0ZXJuO1xuZnVuY3Rpb24gdmFsaWRhdGVBcnJheShjeHQpIHtcbiAgICBjb25zdCB7IGdlbiwgZGF0YSwga2V5d29yZCwgaXQgfSA9IGN4dDtcbiAgICBjb25zdCB2YWxpZCA9IGdlbi5uYW1lKFwidmFsaWRcIik7XG4gICAgaWYgKGl0LmFsbEVycm9ycykge1xuICAgICAgICBjb25zdCB2YWxpZEFyciA9IGdlbi5sZXQoXCJ2YWxpZFwiLCB0cnVlKTtcbiAgICAgICAgdmFsaWRhdGVJdGVtcygoKSA9PiBnZW4uYXNzaWduKHZhbGlkQXJyLCBmYWxzZSkpO1xuICAgICAgICByZXR1cm4gdmFsaWRBcnI7XG4gICAgfVxuICAgIGdlbi52YXIodmFsaWQsIHRydWUpO1xuICAgIHZhbGlkYXRlSXRlbXMoKCkgPT4gZ2VuLmJyZWFrKCkpO1xuICAgIHJldHVybiB2YWxpZDtcbiAgICBmdW5jdGlvbiB2YWxpZGF0ZUl0ZW1zKG5vdFZhbGlkKSB7XG4gICAgICAgIGNvbnN0IGxlbiA9IGdlbi5jb25zdChcImxlblwiLCAoMCwgY29kZWdlbl8xLl8pIGAke2RhdGF9Lmxlbmd0aGApO1xuICAgICAgICBnZW4uZm9yUmFuZ2UoXCJpXCIsIDAsIGxlbiwgKGkpID0+IHtcbiAgICAgICAgICAgIGN4dC5zdWJzY2hlbWEoe1xuICAgICAgICAgICAgICAgIGtleXdvcmQsXG4gICAgICAgICAgICAgICAgZGF0YVByb3A6IGksXG4gICAgICAgICAgICAgICAgZGF0YVByb3BUeXBlOiB1dGlsXzEuVHlwZS5OdW0sXG4gICAgICAgICAgICB9LCB2YWxpZCk7XG4gICAgICAgICAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5ub3QpKHZhbGlkKSwgbm90VmFsaWQpO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5leHBvcnRzLnZhbGlkYXRlQXJyYXkgPSB2YWxpZGF0ZUFycmF5O1xuZnVuY3Rpb24gdmFsaWRhdGVVbmlvbihjeHQpIHtcbiAgICBjb25zdCB7IGdlbiwgc2NoZW1hLCBrZXl3b3JkLCBpdCB9ID0gY3h0O1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmICghQXJyYXkuaXNBcnJheShzY2hlbWEpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJhanYgaW1wbGVtZW50YXRpb24gZXJyb3JcIik7XG4gICAgY29uc3QgYWx3YXlzVmFsaWQgPSBzY2hlbWEuc29tZSgoc2NoKSA9PiAoMCwgdXRpbF8xLmFsd2F5c1ZhbGlkU2NoZW1hKShpdCwgc2NoKSk7XG4gICAgaWYgKGFsd2F5c1ZhbGlkICYmICFpdC5vcHRzLnVuZXZhbHVhdGVkKVxuICAgICAgICByZXR1cm47XG4gICAgY29uc3QgdmFsaWQgPSBnZW4ubGV0KFwidmFsaWRcIiwgZmFsc2UpO1xuICAgIGNvbnN0IHNjaFZhbGlkID0gZ2VuLm5hbWUoXCJfdmFsaWRcIik7XG4gICAgZ2VuLmJsb2NrKCgpID0+IHNjaGVtYS5mb3JFYWNoKChfc2NoLCBpKSA9PiB7XG4gICAgICAgIGNvbnN0IHNjaEN4dCA9IGN4dC5zdWJzY2hlbWEoe1xuICAgICAgICAgICAga2V5d29yZCxcbiAgICAgICAgICAgIHNjaGVtYVByb3A6IGksXG4gICAgICAgICAgICBjb21wb3NpdGVSdWxlOiB0cnVlLFxuICAgICAgICB9LCBzY2hWYWxpZCk7XG4gICAgICAgIGdlbi5hc3NpZ24odmFsaWQsICgwLCBjb2RlZ2VuXzEuXykgYCR7dmFsaWR9IHx8ICR7c2NoVmFsaWR9YCk7XG4gICAgICAgIGNvbnN0IG1lcmdlZCA9IGN4dC5tZXJnZVZhbGlkRXZhbHVhdGVkKHNjaEN4dCwgc2NoVmFsaWQpO1xuICAgICAgICAvLyBjYW4gc2hvcnQtY2lyY3VpdCBpZiBgdW5ldmFsdWF0ZWRQcm9wZXJ0aWVzL0l0ZW1zYCBub3Qgc3VwcG9ydGVkIChvcHRzLnVuZXZhbHVhdGVkICE9PSB0cnVlKVxuICAgICAgICAvLyBvciBpZiBhbGwgcHJvcGVydGllcyBhbmQgaXRlbXMgd2VyZSBldmFsdWF0ZWQgKGl0LnByb3BzID09PSB0cnVlICYmIGl0Lml0ZW1zID09PSB0cnVlKVxuICAgICAgICBpZiAoIW1lcmdlZClcbiAgICAgICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLm5vdCkodmFsaWQpKTtcbiAgICB9KSk7XG4gICAgY3h0LnJlc3VsdCh2YWxpZCwgKCkgPT4gY3h0LnJlc2V0KCksICgpID0+IGN4dC5lcnJvcih0cnVlKSk7XG59XG5leHBvcnRzLnZhbGlkYXRlVW5pb24gPSB2YWxpZGF0ZVVuaW9uO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29kZS5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBcImlkXCIsXG4gICAgY29kZSgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOT1QgU1VQUE9SVEVEOiBrZXl3b3JkIFwiaWRcIiwgdXNlIFwiJGlkXCIgZm9yIHNjaGVtYSBJRCcpO1xuICAgIH0sXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aWQuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBpZF8xID0gcmVxdWlyZShcIi4vaWRcIik7XG5jb25zdCByZWZfMSA9IHJlcXVpcmUoXCIuL3JlZlwiKTtcbmNvbnN0IGNvcmUgPSBbXG4gICAgXCIkc2NoZW1hXCIsXG4gICAgXCIkaWRcIixcbiAgICBcIiRkZWZzXCIsXG4gICAgXCIkdm9jYWJ1bGFyeVwiLFxuICAgIHsga2V5d29yZDogXCIkY29tbWVudFwiIH0sXG4gICAgXCJkZWZpbml0aW9uc1wiLFxuICAgIGlkXzEuZGVmYXVsdCxcbiAgICByZWZfMS5kZWZhdWx0LFxuXTtcbmV4cG9ydHMuZGVmYXVsdCA9IGNvcmU7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmV4cG9ydHMuY2FsbFJlZiA9IGV4cG9ydHMuZ2V0VmFsaWRhdGUgPSB2b2lkIDA7XG5jb25zdCByZWZfZXJyb3JfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL3JlZl9lcnJvclwiKTtcbmNvbnN0IGNvZGVfMSA9IHJlcXVpcmUoXCIuLi9jb2RlXCIpO1xuY29uc3QgY29kZWdlbl8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvY29kZWdlblwiKTtcbmNvbnN0IG5hbWVzXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9uYW1lc1wiKTtcbmNvbnN0IGNvbXBpbGVfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlXCIpO1xuY29uc3QgdXRpbF8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdXRpbFwiKTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBcIiRyZWZcIixcbiAgICBzY2hlbWFUeXBlOiBcInN0cmluZ1wiLFxuICAgIGNvZGUoY3h0KSB7XG4gICAgICAgIGNvbnN0IHsgZ2VuLCBzY2hlbWE6ICRyZWYsIGl0IH0gPSBjeHQ7XG4gICAgICAgIGNvbnN0IHsgYmFzZUlkLCBzY2hlbWFFbnY6IGVudiwgdmFsaWRhdGVOYW1lLCBvcHRzLCBzZWxmIH0gPSBpdDtcbiAgICAgICAgY29uc3QgeyByb290IH0gPSBlbnY7XG4gICAgICAgIGlmICgoJHJlZiA9PT0gXCIjXCIgfHwgJHJlZiA9PT0gXCIjL1wiKSAmJiBiYXNlSWQgPT09IHJvb3QuYmFzZUlkKVxuICAgICAgICAgICAgcmV0dXJuIGNhbGxSb290UmVmKCk7XG4gICAgICAgIGNvbnN0IHNjaE9yRW52ID0gY29tcGlsZV8xLnJlc29sdmVSZWYuY2FsbChzZWxmLCByb290LCBiYXNlSWQsICRyZWYpO1xuICAgICAgICBpZiAoc2NoT3JFbnYgPT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIHRocm93IG5ldyByZWZfZXJyb3JfMS5kZWZhdWx0KGl0Lm9wdHMudXJpUmVzb2x2ZXIsIGJhc2VJZCwgJHJlZik7XG4gICAgICAgIGlmIChzY2hPckVudiBpbnN0YW5jZW9mIGNvbXBpbGVfMS5TY2hlbWFFbnYpXG4gICAgICAgICAgICByZXR1cm4gY2FsbFZhbGlkYXRlKHNjaE9yRW52KTtcbiAgICAgICAgcmV0dXJuIGlubGluZVJlZlNjaGVtYShzY2hPckVudik7XG4gICAgICAgIGZ1bmN0aW9uIGNhbGxSb290UmVmKCkge1xuICAgICAgICAgICAgaWYgKGVudiA9PT0gcm9vdClcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbFJlZihjeHQsIHZhbGlkYXRlTmFtZSwgZW52LCBlbnYuJGFzeW5jKTtcbiAgICAgICAgICAgIGNvbnN0IHJvb3ROYW1lID0gZ2VuLnNjb3BlVmFsdWUoXCJyb290XCIsIHsgcmVmOiByb290IH0pO1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxSZWYoY3h0LCAoMCwgY29kZWdlbl8xLl8pIGAke3Jvb3ROYW1lfS52YWxpZGF0ZWAsIHJvb3QsIHJvb3QuJGFzeW5jKTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBjYWxsVmFsaWRhdGUoc2NoKSB7XG4gICAgICAgICAgICBjb25zdCB2ID0gZ2V0VmFsaWRhdGUoY3h0LCBzY2gpO1xuICAgICAgICAgICAgY2FsbFJlZihjeHQsIHYsIHNjaCwgc2NoLiRhc3luYyk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gaW5saW5lUmVmU2NoZW1hKHNjaCkge1xuICAgICAgICAgICAgY29uc3Qgc2NoTmFtZSA9IGdlbi5zY29wZVZhbHVlKFwic2NoZW1hXCIsIG9wdHMuY29kZS5zb3VyY2UgPT09IHRydWUgPyB7IHJlZjogc2NoLCBjb2RlOiAoMCwgY29kZWdlbl8xLnN0cmluZ2lmeSkoc2NoKSB9IDogeyByZWY6IHNjaCB9KTtcbiAgICAgICAgICAgIGNvbnN0IHZhbGlkID0gZ2VuLm5hbWUoXCJ2YWxpZFwiKTtcbiAgICAgICAgICAgIGNvbnN0IHNjaEN4dCA9IGN4dC5zdWJzY2hlbWEoe1xuICAgICAgICAgICAgICAgIHNjaGVtYTogc2NoLFxuICAgICAgICAgICAgICAgIGRhdGFUeXBlczogW10sXG4gICAgICAgICAgICAgICAgc2NoZW1hUGF0aDogY29kZWdlbl8xLm5pbCxcbiAgICAgICAgICAgICAgICB0b3BTY2hlbWFSZWY6IHNjaE5hbWUsXG4gICAgICAgICAgICAgICAgZXJyU2NoZW1hUGF0aDogJHJlZixcbiAgICAgICAgICAgIH0sIHZhbGlkKTtcbiAgICAgICAgICAgIGN4dC5tZXJnZUV2YWx1YXRlZChzY2hDeHQpO1xuICAgICAgICAgICAgY3h0Lm9rKHZhbGlkKTtcbiAgICAgICAgfVxuICAgIH0sXG59O1xuZnVuY3Rpb24gZ2V0VmFsaWRhdGUoY3h0LCBzY2gpIHtcbiAgICBjb25zdCB7IGdlbiB9ID0gY3h0O1xuICAgIHJldHVybiBzY2gudmFsaWRhdGVcbiAgICAgICAgPyBnZW4uc2NvcGVWYWx1ZShcInZhbGlkYXRlXCIsIHsgcmVmOiBzY2gudmFsaWRhdGUgfSlcbiAgICAgICAgOiAoMCwgY29kZWdlbl8xLl8pIGAke2dlbi5zY29wZVZhbHVlKFwid3JhcHBlclwiLCB7IHJlZjogc2NoIH0pfS52YWxpZGF0ZWA7XG59XG5leHBvcnRzLmdldFZhbGlkYXRlID0gZ2V0VmFsaWRhdGU7XG5mdW5jdGlvbiBjYWxsUmVmKGN4dCwgdiwgc2NoLCAkYXN5bmMpIHtcbiAgICBjb25zdCB7IGdlbiwgaXQgfSA9IGN4dDtcbiAgICBjb25zdCB7IGFsbEVycm9ycywgc2NoZW1hRW52OiBlbnYsIG9wdHMgfSA9IGl0O1xuICAgIGNvbnN0IHBhc3NDeHQgPSBvcHRzLnBhc3NDb250ZXh0ID8gbmFtZXNfMS5kZWZhdWx0LnRoaXMgOiBjb2RlZ2VuXzEubmlsO1xuICAgIGlmICgkYXN5bmMpXG4gICAgICAgIGNhbGxBc3luY1JlZigpO1xuICAgIGVsc2VcbiAgICAgICAgY2FsbFN5bmNSZWYoKTtcbiAgICBmdW5jdGlvbiBjYWxsQXN5bmNSZWYoKSB7XG4gICAgICAgIGlmICghZW52LiRhc3luYylcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImFzeW5jIHNjaGVtYSByZWZlcmVuY2VkIGJ5IHN5bmMgc2NoZW1hXCIpO1xuICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi5sZXQoXCJ2YWxpZFwiKTtcbiAgICAgICAgZ2VuLnRyeSgoKSA9PiB7XG4gICAgICAgICAgICBnZW4uY29kZSgoMCwgY29kZWdlbl8xLl8pIGBhd2FpdCAkeygwLCBjb2RlXzEuY2FsbFZhbGlkYXRlQ29kZSkoY3h0LCB2LCBwYXNzQ3h0KX1gKTtcbiAgICAgICAgICAgIGFkZEV2YWx1YXRlZEZyb20odik7IC8vIFRPRE8gd2lsbCBub3Qgd29yayB3aXRoIGFzeW5jLCBpdCBoYXMgdG8gYmUgcmV0dXJuZWQgd2l0aCB0aGUgcmVzdWx0XG4gICAgICAgICAgICBpZiAoIWFsbEVycm9ycylcbiAgICAgICAgICAgICAgICBnZW4uYXNzaWduKHZhbGlkLCB0cnVlKTtcbiAgICAgICAgfSwgKGUpID0+IHtcbiAgICAgICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLl8pIGAhKCR7ZX0gaW5zdGFuY2VvZiAke2l0LlZhbGlkYXRpb25FcnJvcn0pYCwgKCkgPT4gZ2VuLnRocm93KGUpKTtcbiAgICAgICAgICAgIGFkZEVycm9yc0Zyb20oZSk7XG4gICAgICAgICAgICBpZiAoIWFsbEVycm9ycylcbiAgICAgICAgICAgICAgICBnZW4uYXNzaWduKHZhbGlkLCBmYWxzZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBjeHQub2sodmFsaWQpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjYWxsU3luY1JlZigpIHtcbiAgICAgICAgY3h0LnJlc3VsdCgoMCwgY29kZV8xLmNhbGxWYWxpZGF0ZUNvZGUpKGN4dCwgdiwgcGFzc0N4dCksICgpID0+IGFkZEV2YWx1YXRlZEZyb20odiksICgpID0+IGFkZEVycm9yc0Zyb20odikpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhZGRFcnJvcnNGcm9tKHNvdXJjZSkge1xuICAgICAgICBjb25zdCBlcnJzID0gKDAsIGNvZGVnZW5fMS5fKSBgJHtzb3VyY2V9LmVycm9yc2A7XG4gICAgICAgIGdlbi5hc3NpZ24obmFtZXNfMS5kZWZhdWx0LnZFcnJvcnMsICgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LnZFcnJvcnN9ID09PSBudWxsID8gJHtlcnJzfSA6ICR7bmFtZXNfMS5kZWZhdWx0LnZFcnJvcnN9LmNvbmNhdCgke2VycnN9KWApOyAvLyBUT0RPIHRhZ2dlZFxuICAgICAgICBnZW4uYXNzaWduKG5hbWVzXzEuZGVmYXVsdC5lcnJvcnMsICgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LnZFcnJvcnN9Lmxlbmd0aGApO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhZGRFdmFsdWF0ZWRGcm9tKHNvdXJjZSkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIGlmICghaXQub3B0cy51bmV2YWx1YXRlZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3Qgc2NoRXZhbHVhdGVkID0gKF9hID0gc2NoID09PSBudWxsIHx8IHNjaCA9PT0gdm9pZCAwID8gdm9pZCAwIDogc2NoLnZhbGlkYXRlKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZXZhbHVhdGVkO1xuICAgICAgICAvLyBUT0RPIHJlZmFjdG9yXG4gICAgICAgIGlmIChpdC5wcm9wcyAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgaWYgKHNjaEV2YWx1YXRlZCAmJiAhc2NoRXZhbHVhdGVkLmR5bmFtaWNQcm9wcykge1xuICAgICAgICAgICAgICAgIGlmIChzY2hFdmFsdWF0ZWQucHJvcHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBpdC5wcm9wcyA9IHV0aWxfMS5tZXJnZUV2YWx1YXRlZC5wcm9wcyhnZW4sIHNjaEV2YWx1YXRlZC5wcm9wcywgaXQucHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IHByb3BzID0gZ2VuLnZhcihcInByb3BzXCIsICgwLCBjb2RlZ2VuXzEuXykgYCR7c291cmNlfS5ldmFsdWF0ZWQucHJvcHNgKTtcbiAgICAgICAgICAgICAgICBpdC5wcm9wcyA9IHV0aWxfMS5tZXJnZUV2YWx1YXRlZC5wcm9wcyhnZW4sIHByb3BzLCBpdC5wcm9wcywgY29kZWdlbl8xLk5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChpdC5pdGVtcyAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgaWYgKHNjaEV2YWx1YXRlZCAmJiAhc2NoRXZhbHVhdGVkLmR5bmFtaWNJdGVtcykge1xuICAgICAgICAgICAgICAgIGlmIChzY2hFdmFsdWF0ZWQuaXRlbXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBpdC5pdGVtcyA9IHV0aWxfMS5tZXJnZUV2YWx1YXRlZC5pdGVtcyhnZW4sIHNjaEV2YWx1YXRlZC5pdGVtcywgaXQuaXRlbXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGl0ZW1zID0gZ2VuLnZhcihcIml0ZW1zXCIsICgwLCBjb2RlZ2VuXzEuXykgYCR7c291cmNlfS5ldmFsdWF0ZWQuaXRlbXNgKTtcbiAgICAgICAgICAgICAgICBpdC5pdGVtcyA9IHV0aWxfMS5tZXJnZUV2YWx1YXRlZC5pdGVtcyhnZW4sIGl0ZW1zLCBpdC5pdGVtcywgY29kZWdlbl8xLk5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuZXhwb3J0cy5jYWxsUmVmID0gY2FsbFJlZjtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXJlZi5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL2NvZGVnZW5cIik7XG5jb25zdCB0eXBlc18xID0gcmVxdWlyZShcIi4uL2Rpc2NyaW1pbmF0b3IvdHlwZXNcIik7XG5jb25zdCBjb21waWxlXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZVwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL3V0aWxcIik7XG5jb25zdCBlcnJvciA9IHtcbiAgICBtZXNzYWdlOiAoeyBwYXJhbXM6IHsgZGlzY3JFcnJvciwgdGFnTmFtZSB9IH0pID0+IGRpc2NyRXJyb3IgPT09IHR5cGVzXzEuRGlzY3JFcnJvci5UYWdcbiAgICAgICAgPyBgdGFnIFwiJHt0YWdOYW1lfVwiIG11c3QgYmUgc3RyaW5nYFxuICAgICAgICA6IGB2YWx1ZSBvZiB0YWcgXCIke3RhZ05hbWV9XCIgbXVzdCBiZSBpbiBvbmVPZmAsXG4gICAgcGFyYW1zOiAoeyBwYXJhbXM6IHsgZGlzY3JFcnJvciwgdGFnLCB0YWdOYW1lIH0gfSkgPT4gKDAsIGNvZGVnZW5fMS5fKSBge2Vycm9yOiAke2Rpc2NyRXJyb3J9LCB0YWc6ICR7dGFnTmFtZX0sIHRhZ1ZhbHVlOiAke3RhZ319YCxcbn07XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogXCJkaXNjcmltaW5hdG9yXCIsXG4gICAgdHlwZTogXCJvYmplY3RcIixcbiAgICBzY2hlbWFUeXBlOiBcIm9iamVjdFwiLFxuICAgIGVycm9yLFxuICAgIGNvZGUoY3h0KSB7XG4gICAgICAgIGNvbnN0IHsgZ2VuLCBkYXRhLCBzY2hlbWEsIHBhcmVudFNjaGVtYSwgaXQgfSA9IGN4dDtcbiAgICAgICAgY29uc3QgeyBvbmVPZiB9ID0gcGFyZW50U2NoZW1hO1xuICAgICAgICBpZiAoIWl0Lm9wdHMuZGlzY3JpbWluYXRvcikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZGlzY3JpbWluYXRvcjogcmVxdWlyZXMgZGlzY3JpbWluYXRvciBvcHRpb25cIik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGFnTmFtZSA9IHNjaGVtYS5wcm9wZXJ0eU5hbWU7XG4gICAgICAgIGlmICh0eXBlb2YgdGFnTmFtZSAhPSBcInN0cmluZ1wiKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZGlzY3JpbWluYXRvcjogcmVxdWlyZXMgcHJvcGVydHlOYW1lXCIpO1xuICAgICAgICBpZiAoc2NoZW1hLm1hcHBpbmcpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJkaXNjcmltaW5hdG9yOiBtYXBwaW5nIGlzIG5vdCBzdXBwb3J0ZWRcIik7XG4gICAgICAgIGlmICghb25lT2YpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJkaXNjcmltaW5hdG9yOiByZXF1aXJlcyBvbmVPZiBrZXl3b3JkXCIpO1xuICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi5sZXQoXCJ2YWxpZFwiLCBmYWxzZSk7XG4gICAgICAgIGNvbnN0IHRhZyA9IGdlbi5jb25zdChcInRhZ1wiLCAoMCwgY29kZWdlbl8xLl8pIGAke2RhdGF9JHsoMCwgY29kZWdlbl8xLmdldFByb3BlcnR5KSh0YWdOYW1lKX1gKTtcbiAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYHR5cGVvZiAke3RhZ30gPT0gXCJzdHJpbmdcImAsICgpID0+IHZhbGlkYXRlTWFwcGluZygpLCAoKSA9PiBjeHQuZXJyb3IoZmFsc2UsIHsgZGlzY3JFcnJvcjogdHlwZXNfMS5EaXNjckVycm9yLlRhZywgdGFnLCB0YWdOYW1lIH0pKTtcbiAgICAgICAgY3h0Lm9rKHZhbGlkKTtcbiAgICAgICAgZnVuY3Rpb24gdmFsaWRhdGVNYXBwaW5nKCkge1xuICAgICAgICAgICAgY29uc3QgbWFwcGluZyA9IGdldE1hcHBpbmcoKTtcbiAgICAgICAgICAgIGdlbi5pZihmYWxzZSk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHRhZ1ZhbHVlIGluIG1hcHBpbmcpIHtcbiAgICAgICAgICAgICAgICBnZW4uZWxzZUlmKCgwLCBjb2RlZ2VuXzEuXykgYCR7dGFnfSA9PT0gJHt0YWdWYWx1ZX1gKTtcbiAgICAgICAgICAgICAgICBnZW4uYXNzaWduKHZhbGlkLCBhcHBseVRhZ1NjaGVtYShtYXBwaW5nW3RhZ1ZhbHVlXSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ2VuLmVsc2UoKTtcbiAgICAgICAgICAgIGN4dC5lcnJvcihmYWxzZSwgeyBkaXNjckVycm9yOiB0eXBlc18xLkRpc2NyRXJyb3IuTWFwcGluZywgdGFnLCB0YWdOYW1lIH0pO1xuICAgICAgICAgICAgZ2VuLmVuZElmKCk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gYXBwbHlUYWdTY2hlbWEoc2NoZW1hUHJvcCkge1xuICAgICAgICAgICAgY29uc3QgX3ZhbGlkID0gZ2VuLm5hbWUoXCJ2YWxpZFwiKTtcbiAgICAgICAgICAgIGNvbnN0IHNjaEN4dCA9IGN4dC5zdWJzY2hlbWEoeyBrZXl3b3JkOiBcIm9uZU9mXCIsIHNjaGVtYVByb3AgfSwgX3ZhbGlkKTtcbiAgICAgICAgICAgIGN4dC5tZXJnZUV2YWx1YXRlZChzY2hDeHQsIGNvZGVnZW5fMS5OYW1lKTtcbiAgICAgICAgICAgIHJldHVybiBfdmFsaWQ7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZ2V0TWFwcGluZygpIHtcbiAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgIGNvbnN0IG9uZU9mTWFwcGluZyA9IHt9O1xuICAgICAgICAgICAgY29uc3QgdG9wUmVxdWlyZWQgPSBoYXNSZXF1aXJlZChwYXJlbnRTY2hlbWEpO1xuICAgICAgICAgICAgbGV0IHRhZ1JlcXVpcmVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb25lT2YubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgc2NoID0gb25lT2ZbaV07XG4gICAgICAgICAgICAgICAgaWYgKChzY2ggPT09IG51bGwgfHwgc2NoID09PSB2b2lkIDAgPyB2b2lkIDAgOiBzY2guJHJlZikgJiYgISgwLCB1dGlsXzEuc2NoZW1hSGFzUnVsZXNCdXRSZWYpKHNjaCwgaXQuc2VsZi5SVUxFUykpIHtcbiAgICAgICAgICAgICAgICAgICAgc2NoID0gY29tcGlsZV8xLnJlc29sdmVSZWYuY2FsbChpdC5zZWxmLCBpdC5zY2hlbWFFbnYucm9vdCwgaXQuYmFzZUlkLCBzY2ggPT09IG51bGwgfHwgc2NoID09PSB2b2lkIDAgPyB2b2lkIDAgOiBzY2guJHJlZik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzY2ggaW5zdGFuY2VvZiBjb21waWxlXzEuU2NoZW1hRW52KVxuICAgICAgICAgICAgICAgICAgICAgICAgc2NoID0gc2NoLnNjaGVtYTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgcHJvcFNjaCA9IChfYSA9IHNjaCA9PT0gbnVsbCB8fCBzY2ggPT09IHZvaWQgMCA/IHZvaWQgMCA6IHNjaC5wcm9wZXJ0aWVzKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2FbdGFnTmFtZV07XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwcm9wU2NoICE9IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBkaXNjcmltaW5hdG9yOiBvbmVPZiBzdWJzY2hlbWFzIChvciByZWZlcmVuY2VkIHNjaGVtYXMpIG11c3QgaGF2ZSBcInByb3BlcnRpZXMvJHt0YWdOYW1lfVwiYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRhZ1JlcXVpcmVkID0gdGFnUmVxdWlyZWQgJiYgKHRvcFJlcXVpcmVkIHx8IGhhc1JlcXVpcmVkKHNjaCkpO1xuICAgICAgICAgICAgICAgIGFkZE1hcHBpbmdzKHByb3BTY2gsIGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0YWdSZXF1aXJlZClcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGRpc2NyaW1pbmF0b3I6IFwiJHt0YWdOYW1lfVwiIG11c3QgYmUgcmVxdWlyZWRgKTtcbiAgICAgICAgICAgIHJldHVybiBvbmVPZk1hcHBpbmc7XG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNSZXF1aXJlZCh7IHJlcXVpcmVkIH0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gQXJyYXkuaXNBcnJheShyZXF1aXJlZCkgJiYgcmVxdWlyZWQuaW5jbHVkZXModGFnTmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRNYXBwaW5ncyhzY2gsIGkpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2NoLmNvbnN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZE1hcHBpbmcoc2NoLmNvbnN0LCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoc2NoLmVudW0pIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCB0YWdWYWx1ZSBvZiBzY2guZW51bSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkTWFwcGluZyh0YWdWYWx1ZSwgaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgZGlzY3JpbWluYXRvcjogXCJwcm9wZXJ0aWVzLyR7dGFnTmFtZX1cIiBtdXN0IGhhdmUgXCJjb25zdFwiIG9yIFwiZW51bVwiYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkTWFwcGluZyh0YWdWYWx1ZSwgaSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGFnVmFsdWUgIT0gXCJzdHJpbmdcIiB8fCB0YWdWYWx1ZSBpbiBvbmVPZk1hcHBpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBkaXNjcmltaW5hdG9yOiBcIiR7dGFnTmFtZX1cIiB2YWx1ZXMgbXVzdCBiZSB1bmlxdWUgc3RyaW5nc2ApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvbmVPZk1hcHBpbmdbdGFnVmFsdWVdID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leHBvcnRzLkRpc2NyRXJyb3IgPSB2b2lkIDA7XG52YXIgRGlzY3JFcnJvcjtcbihmdW5jdGlvbiAoRGlzY3JFcnJvcikge1xuICAgIERpc2NyRXJyb3JbXCJUYWdcIl0gPSBcInRhZ1wiO1xuICAgIERpc2NyRXJyb3JbXCJNYXBwaW5nXCJdID0gXCJtYXBwaW5nXCI7XG59KShEaXNjckVycm9yID0gZXhwb3J0cy5EaXNjckVycm9yIHx8IChleHBvcnRzLkRpc2NyRXJyb3IgPSB7fSkpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dHlwZXMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBjb3JlXzEgPSByZXF1aXJlKFwiLi9jb3JlXCIpO1xuY29uc3QgdmFsaWRhdGlvbl8xID0gcmVxdWlyZShcIi4vdmFsaWRhdGlvblwiKTtcbmNvbnN0IGFwcGxpY2F0b3JfMSA9IHJlcXVpcmUoXCIuL2FwcGxpY2F0b3JcIik7XG5jb25zdCBmb3JtYXRfMSA9IHJlcXVpcmUoXCIuL2Zvcm1hdFwiKTtcbmNvbnN0IG1ldGFkYXRhXzEgPSByZXF1aXJlKFwiLi9tZXRhZGF0YVwiKTtcbmNvbnN0IGRyYWZ0N1ZvY2FidWxhcmllcyA9IFtcbiAgICBjb3JlXzEuZGVmYXVsdCxcbiAgICB2YWxpZGF0aW9uXzEuZGVmYXVsdCxcbiAgICAoMCwgYXBwbGljYXRvcl8xLmRlZmF1bHQpKCksXG4gICAgZm9ybWF0XzEuZGVmYXVsdCxcbiAgICBtZXRhZGF0YV8xLm1ldGFkYXRhVm9jYWJ1bGFyeSxcbiAgICBtZXRhZGF0YV8xLmNvbnRlbnRWb2NhYnVsYXJ5LFxuXTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRyYWZ0N1ZvY2FidWxhcmllcztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRyYWZ0Ny5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmV4cG9ydHMuZHluYW1pY0FuY2hvciA9IHZvaWQgMDtcbmNvbnN0IGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL2NvZGVnZW5cIik7XG5jb25zdCBuYW1lc18xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvbmFtZXNcIik7XG5jb25zdCBjb21waWxlXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZVwiKTtcbmNvbnN0IHJlZl8xID0gcmVxdWlyZShcIi4uL2NvcmUvcmVmXCIpO1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwiJGR5bmFtaWNBbmNob3JcIixcbiAgICBzY2hlbWFUeXBlOiBcInN0cmluZ1wiLFxuICAgIGNvZGU6IChjeHQpID0+IGR5bmFtaWNBbmNob3IoY3h0LCBjeHQuc2NoZW1hKSxcbn07XG5mdW5jdGlvbiBkeW5hbWljQW5jaG9yKGN4dCwgYW5jaG9yKSB7XG4gICAgY29uc3QgeyBnZW4sIGl0IH0gPSBjeHQ7XG4gICAgaXQuc2NoZW1hRW52LnJvb3QuZHluYW1pY0FuY2hvcnNbYW5jaG9yXSA9IHRydWU7XG4gICAgY29uc3QgdiA9ICgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LmR5bmFtaWNBbmNob3JzfSR7KDAsIGNvZGVnZW5fMS5nZXRQcm9wZXJ0eSkoYW5jaG9yKX1gO1xuICAgIGNvbnN0IHZhbGlkYXRlID0gaXQuZXJyU2NoZW1hUGF0aCA9PT0gXCIjXCIgPyBpdC52YWxpZGF0ZU5hbWUgOiBfZ2V0VmFsaWRhdGUoY3h0KTtcbiAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5fKSBgISR7dn1gLCAoKSA9PiBnZW4uYXNzaWduKHYsIHZhbGlkYXRlKSk7XG59XG5leHBvcnRzLmR5bmFtaWNBbmNob3IgPSBkeW5hbWljQW5jaG9yO1xuZnVuY3Rpb24gX2dldFZhbGlkYXRlKGN4dCkge1xuICAgIGNvbnN0IHsgc2NoZW1hRW52LCBzY2hlbWEsIHNlbGYgfSA9IGN4dC5pdDtcbiAgICBjb25zdCB7IHJvb3QsIGJhc2VJZCwgbG9jYWxSZWZzLCBtZXRhIH0gPSBzY2hlbWFFbnYucm9vdDtcbiAgICBjb25zdCB7IHNjaGVtYUlkIH0gPSBzZWxmLm9wdHM7XG4gICAgY29uc3Qgc2NoID0gbmV3IGNvbXBpbGVfMS5TY2hlbWFFbnYoeyBzY2hlbWEsIHNjaGVtYUlkLCByb290LCBiYXNlSWQsIGxvY2FsUmVmcywgbWV0YSB9KTtcbiAgICBjb21waWxlXzEuY29tcGlsZVNjaGVtYS5jYWxsKHNlbGYsIHNjaCk7XG4gICAgcmV0dXJuICgwLCByZWZfMS5nZXRWYWxpZGF0ZSkoY3h0LCBzY2gpO1xufVxuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZHluYW1pY0FuY2hvci5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmV4cG9ydHMuZHluYW1pY1JlZiA9IHZvaWQgMDtcbmNvbnN0IGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL2NvZGVnZW5cIik7XG5jb25zdCBuYW1lc18xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvbmFtZXNcIik7XG5jb25zdCByZWZfMSA9IHJlcXVpcmUoXCIuLi9jb3JlL3JlZlwiKTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBcIiRkeW5hbWljUmVmXCIsXG4gICAgc2NoZW1hVHlwZTogXCJzdHJpbmdcIixcbiAgICBjb2RlOiAoY3h0KSA9PiBkeW5hbWljUmVmKGN4dCwgY3h0LnNjaGVtYSksXG59O1xuZnVuY3Rpb24gZHluYW1pY1JlZihjeHQsIHJlZikge1xuICAgIGNvbnN0IHsgZ2VuLCBrZXl3b3JkLCBpdCB9ID0gY3h0O1xuICAgIGlmIChyZWZbMF0gIT09IFwiI1wiKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFwiJHtrZXl3b3JkfVwiIG9ubHkgc3VwcG9ydHMgaGFzaCBmcmFnbWVudCByZWZlcmVuY2VgKTtcbiAgICBjb25zdCBhbmNob3IgPSByZWYuc2xpY2UoMSk7XG4gICAgaWYgKGl0LmFsbEVycm9ycykge1xuICAgICAgICBfZHluYW1pY1JlZigpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgY29uc3QgdmFsaWQgPSBnZW4ubGV0KFwidmFsaWRcIiwgZmFsc2UpO1xuICAgICAgICBfZHluYW1pY1JlZih2YWxpZCk7XG4gICAgICAgIGN4dC5vayh2YWxpZCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIF9keW5hbWljUmVmKHZhbGlkKSB7XG4gICAgICAgIC8vIFRPRE8gdGhlIGFzc3VtcHRpb24gaGVyZSBpcyB0aGF0IGByZWN1cnNpdmVSZWY6ICNgIGFsd2F5cyBwb2ludHMgdG8gdGhlIHJvb3RcbiAgICAgICAgLy8gb2YgdGhlIHNjaGVtYSBvYmplY3QsIHdoaWNoIGlzIG5vdCBjb3JyZWN0LCBiZWNhdXNlIHRoZXJlIG1heSBiZSAkaWQgdGhhdFxuICAgICAgICAvLyBtYWtlcyAjIHBvaW50IHRvIGl0LCBhbmQgdGhlIHRhcmdldCBzY2hlbWEgbWF5IG5vdCBjb250YWluIGR5bmFtaWMvcmVjdXJzaXZlQW5jaG9yLlxuICAgICAgICAvLyBCZWNhdXNlIG9mIHRoYXQgMiB0ZXN0cyBpbiByZWN1cnNpdmVSZWYuanNvbiBmYWlsLlxuICAgICAgICAvLyBUaGlzIGlzIGEgc2ltaWxhciBwcm9ibGVtIHRvICM4MTUgKGAkaWRgIGRvZXNuJ3QgYWx0ZXIgcmVzb2x1dGlvbiBzY29wZSBmb3IgYHsgXCIkcmVmXCI6IFwiI1wiIH1gKS5cbiAgICAgICAgLy8gKFRoaXMgcHJvYmxlbSBpcyBub3QgdGVzdGVkIGluIEpTT04tU2NoZW1hLVRlc3QtU3VpdGUpXG4gICAgICAgIGlmIChpdC5zY2hlbWFFbnYucm9vdC5keW5hbWljQW5jaG9yc1thbmNob3JdKSB7XG4gICAgICAgICAgICBjb25zdCB2ID0gZ2VuLmxldChcIl92XCIsICgwLCBjb2RlZ2VuXzEuXykgYCR7bmFtZXNfMS5kZWZhdWx0LmR5bmFtaWNBbmNob3JzfSR7KDAsIGNvZGVnZW5fMS5nZXRQcm9wZXJ0eSkoYW5jaG9yKX1gKTtcbiAgICAgICAgICAgIGdlbi5pZih2LCBfY2FsbFJlZih2LCB2YWxpZCksIF9jYWxsUmVmKGl0LnZhbGlkYXRlTmFtZSwgdmFsaWQpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIF9jYWxsUmVmKGl0LnZhbGlkYXRlTmFtZSwgdmFsaWQpKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gX2NhbGxSZWYodmFsaWRhdGUsIHZhbGlkKSB7XG4gICAgICAgIHJldHVybiB2YWxpZFxuICAgICAgICAgICAgPyAoKSA9PiBnZW4uYmxvY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgICgwLCByZWZfMS5jYWxsUmVmKShjeHQsIHZhbGlkYXRlKTtcbiAgICAgICAgICAgICAgICBnZW4ubGV0KHZhbGlkLCB0cnVlKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICA6ICgpID0+ICgwLCByZWZfMS5jYWxsUmVmKShjeHQsIHZhbGlkYXRlKTtcbiAgICB9XG59XG5leHBvcnRzLmR5bmFtaWNSZWYgPSBkeW5hbWljUmVmO1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZHluYW1pY1JlZi5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGR5bmFtaWNBbmNob3JfMSA9IHJlcXVpcmUoXCIuL2R5bmFtaWNBbmNob3JcIik7XG5jb25zdCBkeW5hbWljUmVmXzEgPSByZXF1aXJlKFwiLi9keW5hbWljUmVmXCIpO1xuY29uc3QgcmVjdXJzaXZlQW5jaG9yXzEgPSByZXF1aXJlKFwiLi9yZWN1cnNpdmVBbmNob3JcIik7XG5jb25zdCByZWN1cnNpdmVSZWZfMSA9IHJlcXVpcmUoXCIuL3JlY3Vyc2l2ZVJlZlwiKTtcbmNvbnN0IGR5bmFtaWMgPSBbZHluYW1pY0FuY2hvcl8xLmRlZmF1bHQsIGR5bmFtaWNSZWZfMS5kZWZhdWx0LCByZWN1cnNpdmVBbmNob3JfMS5kZWZhdWx0LCByZWN1cnNpdmVSZWZfMS5kZWZhdWx0XTtcbmV4cG9ydHMuZGVmYXVsdCA9IGR5bmFtaWM7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGR5bmFtaWNBbmNob3JfMSA9IHJlcXVpcmUoXCIuL2R5bmFtaWNBbmNob3JcIik7XG5jb25zdCB1dGlsXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS91dGlsXCIpO1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwiJHJlY3Vyc2l2ZUFuY2hvclwiLFxuICAgIHNjaGVtYVR5cGU6IFwiYm9vbGVhblwiLFxuICAgIGNvZGUoY3h0KSB7XG4gICAgICAgIGlmIChjeHQuc2NoZW1hKVxuICAgICAgICAgICAgKDAsIGR5bmFtaWNBbmNob3JfMS5keW5hbWljQW5jaG9yKShjeHQsIFwiXCIpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICAoMCwgdXRpbF8xLmNoZWNrU3RyaWN0TW9kZSkoY3h0Lml0LCBcIiRyZWN1cnNpdmVBbmNob3I6IGZhbHNlIGlzIGlnbm9yZWRcIik7XG4gICAgfSxcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBkZWY7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1yZWN1cnNpdmVBbmNob3IuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBkeW5hbWljUmVmXzEgPSByZXF1aXJlKFwiLi9keW5hbWljUmVmXCIpO1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwiJHJlY3Vyc2l2ZVJlZlwiLFxuICAgIHNjaGVtYVR5cGU6IFwic3RyaW5nXCIsXG4gICAgY29kZTogKGN4dCkgPT4gKDAsIGR5bmFtaWNSZWZfMS5keW5hbWljUmVmKShjeHQsIGN4dC5zY2hlbWEpLFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXJlY3Vyc2l2ZVJlZi5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL2NvZGVnZW5cIik7XG5jb25zdCBlcnJvciA9IHtcbiAgICBtZXNzYWdlOiAoeyBzY2hlbWFDb2RlIH0pID0+ICgwLCBjb2RlZ2VuXzEuc3RyKSBgbXVzdCBtYXRjaCBmb3JtYXQgXCIke3NjaGVtYUNvZGV9XCJgLFxuICAgIHBhcmFtczogKHsgc2NoZW1hQ29kZSB9KSA9PiAoMCwgY29kZWdlbl8xLl8pIGB7Zm9ybWF0OiAke3NjaGVtYUNvZGV9fWAsXG59O1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwiZm9ybWF0XCIsXG4gICAgdHlwZTogW1wibnVtYmVyXCIsIFwic3RyaW5nXCJdLFxuICAgIHNjaGVtYVR5cGU6IFwic3RyaW5nXCIsXG4gICAgJGRhdGE6IHRydWUsXG4gICAgZXJyb3IsXG4gICAgY29kZShjeHQsIHJ1bGVUeXBlKSB7XG4gICAgICAgIGNvbnN0IHsgZ2VuLCBkYXRhLCAkZGF0YSwgc2NoZW1hLCBzY2hlbWFDb2RlLCBpdCB9ID0gY3h0O1xuICAgICAgICBjb25zdCB7IG9wdHMsIGVyclNjaGVtYVBhdGgsIHNjaGVtYUVudiwgc2VsZiB9ID0gaXQ7XG4gICAgICAgIGlmICghb3B0cy52YWxpZGF0ZUZvcm1hdHMpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmICgkZGF0YSlcbiAgICAgICAgICAgIHZhbGlkYXRlJERhdGFGb3JtYXQoKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdmFsaWRhdGVGb3JtYXQoKTtcbiAgICAgICAgZnVuY3Rpb24gdmFsaWRhdGUkRGF0YUZvcm1hdCgpIHtcbiAgICAgICAgICAgIGNvbnN0IGZtdHMgPSBnZW4uc2NvcGVWYWx1ZShcImZvcm1hdHNcIiwge1xuICAgICAgICAgICAgICAgIHJlZjogc2VsZi5mb3JtYXRzLFxuICAgICAgICAgICAgICAgIGNvZGU6IG9wdHMuY29kZS5mb3JtYXRzLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCBmRGVmID0gZ2VuLmNvbnN0KFwiZkRlZlwiLCAoMCwgY29kZWdlbl8xLl8pIGAke2ZtdHN9WyR7c2NoZW1hQ29kZX1dYCk7XG4gICAgICAgICAgICBjb25zdCBmVHlwZSA9IGdlbi5sZXQoXCJmVHlwZVwiKTtcbiAgICAgICAgICAgIGNvbnN0IGZvcm1hdCA9IGdlbi5sZXQoXCJmb3JtYXRcIik7XG4gICAgICAgICAgICAvLyBUT0RPIHNpbXBsaWZ5XG4gICAgICAgICAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5fKSBgdHlwZW9mICR7ZkRlZn0gPT0gXCJvYmplY3RcIiAmJiAhKCR7ZkRlZn0gaW5zdGFuY2VvZiBSZWdFeHApYCwgKCkgPT4gZ2VuLmFzc2lnbihmVHlwZSwgKDAsIGNvZGVnZW5fMS5fKSBgJHtmRGVmfS50eXBlIHx8IFwic3RyaW5nXCJgKS5hc3NpZ24oZm9ybWF0LCAoMCwgY29kZWdlbl8xLl8pIGAke2ZEZWZ9LnZhbGlkYXRlYCksICgpID0+IGdlbi5hc3NpZ24oZlR5cGUsICgwLCBjb2RlZ2VuXzEuXykgYFwic3RyaW5nXCJgKS5hc3NpZ24oZm9ybWF0LCBmRGVmKSk7XG4gICAgICAgICAgICBjeHQuZmFpbCRkYXRhKCgwLCBjb2RlZ2VuXzEub3IpKHVua25vd25GbXQoKSwgaW52YWxpZEZtdCgpKSk7XG4gICAgICAgICAgICBmdW5jdGlvbiB1bmtub3duRm10KCkge1xuICAgICAgICAgICAgICAgIGlmIChvcHRzLnN0cmljdFNjaGVtYSA9PT0gZmFsc2UpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb2RlZ2VuXzEubmlsO1xuICAgICAgICAgICAgICAgIHJldHVybiAoMCwgY29kZWdlbl8xLl8pIGAke3NjaGVtYUNvZGV9ICYmICEke2Zvcm1hdH1gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gaW52YWxpZEZtdCgpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjYWxsRm9ybWF0ID0gc2NoZW1hRW52LiRhc3luY1xuICAgICAgICAgICAgICAgICAgICA/ICgwLCBjb2RlZ2VuXzEuXykgYCgke2ZEZWZ9LmFzeW5jID8gYXdhaXQgJHtmb3JtYXR9KCR7ZGF0YX0pIDogJHtmb3JtYXR9KCR7ZGF0YX0pKWBcbiAgICAgICAgICAgICAgICAgICAgOiAoMCwgY29kZWdlbl8xLl8pIGAke2Zvcm1hdH0oJHtkYXRhfSlgO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbGlkRGF0YSA9ICgwLCBjb2RlZ2VuXzEuXykgYCh0eXBlb2YgJHtmb3JtYXR9ID09IFwiZnVuY3Rpb25cIiA/ICR7Y2FsbEZvcm1hdH0gOiAke2Zvcm1hdH0udGVzdCgke2RhdGF9KSlgO1xuICAgICAgICAgICAgICAgIHJldHVybiAoMCwgY29kZWdlbl8xLl8pIGAke2Zvcm1hdH0gJiYgJHtmb3JtYXR9ICE9PSB0cnVlICYmICR7ZlR5cGV9ID09PSAke3J1bGVUeXBlfSAmJiAhJHt2YWxpZERhdGF9YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiB2YWxpZGF0ZUZvcm1hdCgpIHtcbiAgICAgICAgICAgIGNvbnN0IGZvcm1hdERlZiA9IHNlbGYuZm9ybWF0c1tzY2hlbWFdO1xuICAgICAgICAgICAgaWYgKCFmb3JtYXREZWYpIHtcbiAgICAgICAgICAgICAgICB1bmtub3duRm9ybWF0KCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZvcm1hdERlZiA9PT0gdHJ1ZSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICBjb25zdCBbZm10VHlwZSwgZm9ybWF0LCBmbXRSZWZdID0gZ2V0Rm9ybWF0KGZvcm1hdERlZik7XG4gICAgICAgICAgICBpZiAoZm10VHlwZSA9PT0gcnVsZVR5cGUpXG4gICAgICAgICAgICAgICAgY3h0LnBhc3ModmFsaWRDb25kaXRpb24oKSk7XG4gICAgICAgICAgICBmdW5jdGlvbiB1bmtub3duRm9ybWF0KCkge1xuICAgICAgICAgICAgICAgIGlmIChvcHRzLnN0cmljdFNjaGVtYSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5sb2dnZXIud2Fybih1bmtub3duTXNnKCkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih1bmtub3duTXNnKCkpO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHVua25vd25Nc2coKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBgdW5rbm93biBmb3JtYXQgXCIke3NjaGVtYX1cIiBpZ25vcmVkIGluIHNjaGVtYSBhdCBwYXRoIFwiJHtlcnJTY2hlbWFQYXRofVwiYDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRGb3JtYXQoZm10RGVmKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29kZSA9IGZtdERlZiBpbnN0YW5jZW9mIFJlZ0V4cFxuICAgICAgICAgICAgICAgICAgICA/ICgwLCBjb2RlZ2VuXzEucmVnZXhwQ29kZSkoZm10RGVmKVxuICAgICAgICAgICAgICAgICAgICA6IG9wdHMuY29kZS5mb3JtYXRzXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICgwLCBjb2RlZ2VuXzEuXykgYCR7b3B0cy5jb2RlLmZvcm1hdHN9JHsoMCwgY29kZWdlbl8xLmdldFByb3BlcnR5KShzY2hlbWEpfWBcbiAgICAgICAgICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZtdCA9IGdlbi5zY29wZVZhbHVlKFwiZm9ybWF0c1wiLCB7IGtleTogc2NoZW1hLCByZWY6IGZtdERlZiwgY29kZSB9KTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGZtdERlZiA9PSBcIm9iamVjdFwiICYmICEoZm10RGVmIGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gW2ZtdERlZi50eXBlIHx8IFwic3RyaW5nXCIsIGZtdERlZi52YWxpZGF0ZSwgKDAsIGNvZGVnZW5fMS5fKSBgJHtmbXR9LnZhbGlkYXRlYF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBbXCJzdHJpbmdcIiwgZm10RGVmLCBmbXRdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gdmFsaWRDb25kaXRpb24oKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBmb3JtYXREZWYgPT0gXCJvYmplY3RcIiAmJiAhKGZvcm1hdERlZiBpbnN0YW5jZW9mIFJlZ0V4cCkgJiYgZm9ybWF0RGVmLmFzeW5jKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2NoZW1hRW52LiRhc3luYylcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImFzeW5jIGZvcm1hdCBpbiBzeW5jIHNjaGVtYVwiKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgwLCBjb2RlZ2VuXzEuXykgYGF3YWl0ICR7Zm10UmVmfSgke2RhdGF9KWA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgZm9ybWF0ID09IFwiZnVuY3Rpb25cIiA/ICgwLCBjb2RlZ2VuXzEuXykgYCR7Zm10UmVmfSgke2RhdGF9KWAgOiAoMCwgY29kZWdlbl8xLl8pIGAke2ZtdFJlZn0udGVzdCgke2RhdGF9KWA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWZvcm1hdC5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGZvcm1hdF8xID0gcmVxdWlyZShcIi4vZm9ybWF0XCIpO1xuY29uc3QgZm9ybWF0ID0gW2Zvcm1hdF8xLmRlZmF1bHRdO1xuZXhwb3J0cy5kZWZhdWx0ID0gZm9ybWF0O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leHBvcnRzLmNvbnRlbnRWb2NhYnVsYXJ5ID0gZXhwb3J0cy5tZXRhZGF0YVZvY2FidWxhcnkgPSB2b2lkIDA7XG5leHBvcnRzLm1ldGFkYXRhVm9jYWJ1bGFyeSA9IFtcbiAgICBcInRpdGxlXCIsXG4gICAgXCJkZXNjcmlwdGlvblwiLFxuICAgIFwiZGVmYXVsdFwiLFxuICAgIFwiZGVwcmVjYXRlZFwiLFxuICAgIFwicmVhZE9ubHlcIixcbiAgICBcIndyaXRlT25seVwiLFxuICAgIFwiZXhhbXBsZXNcIixcbl07XG5leHBvcnRzLmNvbnRlbnRWb2NhYnVsYXJ5ID0gW1xuICAgIFwiY29udGVudE1lZGlhVHlwZVwiLFxuICAgIFwiY29udGVudEVuY29kaW5nXCIsXG4gICAgXCJjb250ZW50U2NoZW1hXCIsXG5dO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bWV0YWRhdGEuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBkZXBlbmRlbnRSZXF1aXJlZF8xID0gcmVxdWlyZShcIi4vdmFsaWRhdGlvbi9kZXBlbmRlbnRSZXF1aXJlZFwiKTtcbmNvbnN0IGRlcGVuZGVudFNjaGVtYXNfMSA9IHJlcXVpcmUoXCIuL2FwcGxpY2F0b3IvZGVwZW5kZW50U2NoZW1hc1wiKTtcbmNvbnN0IGxpbWl0Q29udGFpbnNfMSA9IHJlcXVpcmUoXCIuL3ZhbGlkYXRpb24vbGltaXRDb250YWluc1wiKTtcbmNvbnN0IG5leHQgPSBbZGVwZW5kZW50UmVxdWlyZWRfMS5kZWZhdWx0LCBkZXBlbmRlbnRTY2hlbWFzXzEuZGVmYXVsdCwgbGltaXRDb250YWluc18xLmRlZmF1bHRdO1xuZXhwb3J0cy5kZWZhdWx0ID0gbmV4dDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPW5leHQuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCB1bmV2YWx1YXRlZFByb3BlcnRpZXNfMSA9IHJlcXVpcmUoXCIuL3VuZXZhbHVhdGVkUHJvcGVydGllc1wiKTtcbmNvbnN0IHVuZXZhbHVhdGVkSXRlbXNfMSA9IHJlcXVpcmUoXCIuL3VuZXZhbHVhdGVkSXRlbXNcIik7XG5jb25zdCB1bmV2YWx1YXRlZCA9IFt1bmV2YWx1YXRlZFByb3BlcnRpZXNfMS5kZWZhdWx0LCB1bmV2YWx1YXRlZEl0ZW1zXzEuZGVmYXVsdF07XG5leHBvcnRzLmRlZmF1bHQgPSB1bmV2YWx1YXRlZDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWluZGV4LmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgY29kZWdlbl8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvY29kZWdlblwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL3V0aWxcIik7XG5jb25zdCBlcnJvciA9IHtcbiAgICBtZXNzYWdlOiAoeyBwYXJhbXM6IHsgbGVuIH0gfSkgPT4gKDAsIGNvZGVnZW5fMS5zdHIpIGBtdXN0IE5PVCBoYXZlIG1vcmUgdGhhbiAke2xlbn0gaXRlbXNgLFxuICAgIHBhcmFtczogKHsgcGFyYW1zOiB7IGxlbiB9IH0pID0+ICgwLCBjb2RlZ2VuXzEuXykgYHtsaW1pdDogJHtsZW59fWAsXG59O1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwidW5ldmFsdWF0ZWRJdGVtc1wiLFxuICAgIHR5cGU6IFwiYXJyYXlcIixcbiAgICBzY2hlbWFUeXBlOiBbXCJib29sZWFuXCIsIFwib2JqZWN0XCJdLFxuICAgIGVycm9yLFxuICAgIGNvZGUoY3h0KSB7XG4gICAgICAgIGNvbnN0IHsgZ2VuLCBzY2hlbWEsIGRhdGEsIGl0IH0gPSBjeHQ7XG4gICAgICAgIGNvbnN0IGl0ZW1zID0gaXQuaXRlbXMgfHwgMDtcbiAgICAgICAgaWYgKGl0ZW1zID09PSB0cnVlKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCBsZW4gPSBnZW4uY29uc3QoXCJsZW5cIiwgKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhfS5sZW5ndGhgKTtcbiAgICAgICAgaWYgKHNjaGVtYSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGN4dC5zZXRQYXJhbXMoeyBsZW46IGl0ZW1zIH0pO1xuICAgICAgICAgICAgY3h0LmZhaWwoKDAsIGNvZGVnZW5fMS5fKSBgJHtsZW59ID4gJHtpdGVtc31gKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2Ygc2NoZW1hID09IFwib2JqZWN0XCIgJiYgISgwLCB1dGlsXzEuYWx3YXlzVmFsaWRTY2hlbWEpKGl0LCBzY2hlbWEpKSB7XG4gICAgICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi52YXIoXCJ2YWxpZFwiLCAoMCwgY29kZWdlbl8xLl8pIGAke2xlbn0gPD0gJHtpdGVtc31gKTtcbiAgICAgICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLm5vdCkodmFsaWQpLCAoKSA9PiB2YWxpZGF0ZUl0ZW1zKHZhbGlkLCBpdGVtcykpO1xuICAgICAgICAgICAgY3h0Lm9rKHZhbGlkKTtcbiAgICAgICAgfVxuICAgICAgICBpdC5pdGVtcyA9IHRydWU7XG4gICAgICAgIGZ1bmN0aW9uIHZhbGlkYXRlSXRlbXModmFsaWQsIGZyb20pIHtcbiAgICAgICAgICAgIGdlbi5mb3JSYW5nZShcImlcIiwgZnJvbSwgbGVuLCAoaSkgPT4ge1xuICAgICAgICAgICAgICAgIGN4dC5zdWJzY2hlbWEoeyBrZXl3b3JkOiBcInVuZXZhbHVhdGVkSXRlbXNcIiwgZGF0YVByb3A6IGksIGRhdGFQcm9wVHlwZTogdXRpbF8xLlR5cGUuTnVtIH0sIHZhbGlkKTtcbiAgICAgICAgICAgICAgICBpZiAoIWl0LmFsbEVycm9ycylcbiAgICAgICAgICAgICAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEubm90KSh2YWxpZCksICgpID0+IGdlbi5icmVhaygpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSxcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBkZWY7XG4vLyMgc291cmNlTWFwcGluZ1VSTD11bmV2YWx1YXRlZEl0ZW1zLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgY29kZWdlbl8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvY29kZWdlblwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL3V0aWxcIik7XG5jb25zdCBuYW1lc18xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvbmFtZXNcIik7XG5jb25zdCBlcnJvciA9IHtcbiAgICBtZXNzYWdlOiBcIm11c3QgTk9UIGhhdmUgdW5ldmFsdWF0ZWQgcHJvcGVydGllc1wiLFxuICAgIHBhcmFtczogKHsgcGFyYW1zIH0pID0+ICgwLCBjb2RlZ2VuXzEuXykgYHt1bmV2YWx1YXRlZFByb3BlcnR5OiAke3BhcmFtcy51bmV2YWx1YXRlZFByb3BlcnR5fX1gLFxufTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBcInVuZXZhbHVhdGVkUHJvcGVydGllc1wiLFxuICAgIHR5cGU6IFwib2JqZWN0XCIsXG4gICAgc2NoZW1hVHlwZTogW1wiYm9vbGVhblwiLCBcIm9iamVjdFwiXSxcbiAgICB0cmFja0Vycm9yczogdHJ1ZSxcbiAgICBlcnJvcixcbiAgICBjb2RlKGN4dCkge1xuICAgICAgICBjb25zdCB7IGdlbiwgc2NoZW1hLCBkYXRhLCBlcnJzQ291bnQsIGl0IH0gPSBjeHQ7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgICBpZiAoIWVycnNDb3VudClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImFqdiBpbXBsZW1lbnRhdGlvbiBlcnJvclwiKTtcbiAgICAgICAgY29uc3QgeyBhbGxFcnJvcnMsIHByb3BzIH0gPSBpdDtcbiAgICAgICAgaWYgKHByb3BzIGluc3RhbmNlb2YgY29kZWdlbl8xLk5hbWUpIHtcbiAgICAgICAgICAgIGdlbi5pZigoMCwgY29kZWdlbl8xLl8pIGAke3Byb3BzfSAhPT0gdHJ1ZWAsICgpID0+IGdlbi5mb3JJbihcImtleVwiLCBkYXRhLCAoa2V5KSA9PiBnZW4uaWYodW5ldmFsdWF0ZWREeW5hbWljKHByb3BzLCBrZXkpLCAoKSA9PiB1bmV2YWx1YXRlZFByb3BDb2RlKGtleSkpKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAocHJvcHMgIT09IHRydWUpIHtcbiAgICAgICAgICAgIGdlbi5mb3JJbihcImtleVwiLCBkYXRhLCAoa2V5KSA9PiBwcm9wcyA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgPyB1bmV2YWx1YXRlZFByb3BDb2RlKGtleSlcbiAgICAgICAgICAgICAgICA6IGdlbi5pZih1bmV2YWx1YXRlZFN0YXRpYyhwcm9wcywga2V5KSwgKCkgPT4gdW5ldmFsdWF0ZWRQcm9wQ29kZShrZXkpKSk7XG4gICAgICAgIH1cbiAgICAgICAgaXQucHJvcHMgPSB0cnVlO1xuICAgICAgICBjeHQub2soKDAsIGNvZGVnZW5fMS5fKSBgJHtlcnJzQ291bnR9ID09PSAke25hbWVzXzEuZGVmYXVsdC5lcnJvcnN9YCk7XG4gICAgICAgIGZ1bmN0aW9uIHVuZXZhbHVhdGVkUHJvcENvZGUoa2V5KSB7XG4gICAgICAgICAgICBpZiAoc2NoZW1hID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIGN4dC5zZXRQYXJhbXMoeyB1bmV2YWx1YXRlZFByb3BlcnR5OiBrZXkgfSk7XG4gICAgICAgICAgICAgICAgY3h0LmVycm9yKCk7XG4gICAgICAgICAgICAgICAgaWYgKCFhbGxFcnJvcnMpXG4gICAgICAgICAgICAgICAgICAgIGdlbi5icmVhaygpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghKDAsIHV0aWxfMS5hbHdheXNWYWxpZFNjaGVtYSkoaXQsIHNjaGVtYSkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi5uYW1lKFwidmFsaWRcIik7XG4gICAgICAgICAgICAgICAgY3h0LnN1YnNjaGVtYSh7XG4gICAgICAgICAgICAgICAgICAgIGtleXdvcmQ6IFwidW5ldmFsdWF0ZWRQcm9wZXJ0aWVzXCIsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFQcm9wOiBrZXksXG4gICAgICAgICAgICAgICAgICAgIGRhdGFQcm9wVHlwZTogdXRpbF8xLlR5cGUuU3RyLFxuICAgICAgICAgICAgICAgIH0sIHZhbGlkKTtcbiAgICAgICAgICAgICAgICBpZiAoIWFsbEVycm9ycylcbiAgICAgICAgICAgICAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEubm90KSh2YWxpZCksICgpID0+IGdlbi5icmVhaygpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiB1bmV2YWx1YXRlZER5bmFtaWMoZXZhbHVhdGVkUHJvcHMsIGtleSkge1xuICAgICAgICAgICAgcmV0dXJuICgwLCBjb2RlZ2VuXzEuXykgYCEke2V2YWx1YXRlZFByb3BzfSB8fCAhJHtldmFsdWF0ZWRQcm9wc31bJHtrZXl9XWA7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gdW5ldmFsdWF0ZWRTdGF0aWMoZXZhbHVhdGVkUHJvcHMsIGtleSkge1xuICAgICAgICAgICAgY29uc3QgcHMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcCBpbiBldmFsdWF0ZWRQcm9wcykge1xuICAgICAgICAgICAgICAgIGlmIChldmFsdWF0ZWRQcm9wc1twXSA9PT0gdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgcHMucHVzaCgoMCwgY29kZWdlbl8xLl8pIGAke2tleX0gIT09ICR7cH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAoMCwgY29kZWdlbl8xLmFuZCkoLi4ucHMpO1xuICAgICAgICB9XG4gICAgfSxcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBkZWY7XG4vLyMgc291cmNlTWFwcGluZ1VSTD11bmV2YWx1YXRlZFByb3BlcnRpZXMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9jb2RlZ2VuXCIpO1xuY29uc3QgdXRpbF8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdXRpbFwiKTtcbmNvbnN0IGVxdWFsXzEgPSByZXF1aXJlKFwiLi4vLi4vcnVudGltZS9lcXVhbFwiKTtcbmNvbnN0IGVycm9yID0ge1xuICAgIG1lc3NhZ2U6IFwibXVzdCBiZSBlcXVhbCB0byBjb25zdGFudFwiLFxuICAgIHBhcmFtczogKHsgc2NoZW1hQ29kZSB9KSA9PiAoMCwgY29kZWdlbl8xLl8pIGB7YWxsb3dlZFZhbHVlOiAke3NjaGVtYUNvZGV9fWAsXG59O1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwiY29uc3RcIixcbiAgICAkZGF0YTogdHJ1ZSxcbiAgICBlcnJvcixcbiAgICBjb2RlKGN4dCkge1xuICAgICAgICBjb25zdCB7IGdlbiwgZGF0YSwgJGRhdGEsIHNjaGVtYUNvZGUsIHNjaGVtYSB9ID0gY3h0O1xuICAgICAgICBpZiAoJGRhdGEgfHwgKHNjaGVtYSAmJiB0eXBlb2Ygc2NoZW1hID09IFwib2JqZWN0XCIpKSB7XG4gICAgICAgICAgICBjeHQuZmFpbCRkYXRhKCgwLCBjb2RlZ2VuXzEuXykgYCEkeygwLCB1dGlsXzEudXNlRnVuYykoZ2VuLCBlcXVhbF8xLmRlZmF1bHQpfSgke2RhdGF9LCAke3NjaGVtYUNvZGV9KWApO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY3h0LmZhaWwoKDAsIGNvZGVnZW5fMS5fKSBgJHtzY2hlbWF9ICE9PSAke2RhdGF9YCk7XG4gICAgICAgIH1cbiAgICB9LFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWNvbnN0LmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgZGVwZW5kZW5jaWVzXzEgPSByZXF1aXJlKFwiLi4vYXBwbGljYXRvci9kZXBlbmRlbmNpZXNcIik7XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogXCJkZXBlbmRlbnRSZXF1aXJlZFwiLFxuICAgIHR5cGU6IFwib2JqZWN0XCIsXG4gICAgc2NoZW1hVHlwZTogXCJvYmplY3RcIixcbiAgICBlcnJvcjogZGVwZW5kZW5jaWVzXzEuZXJyb3IsXG4gICAgY29kZTogKGN4dCkgPT4gKDAsIGRlcGVuZGVuY2llc18xLnZhbGlkYXRlUHJvcGVydHlEZXBzKShjeHQpLFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRlcGVuZGVudFJlcXVpcmVkLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgY29kZWdlbl8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvY29kZWdlblwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL3V0aWxcIik7XG5jb25zdCBlcXVhbF8xID0gcmVxdWlyZShcIi4uLy4uL3J1bnRpbWUvZXF1YWxcIik7XG5jb25zdCBlcnJvciA9IHtcbiAgICBtZXNzYWdlOiBcIm11c3QgYmUgZXF1YWwgdG8gb25lIG9mIHRoZSBhbGxvd2VkIHZhbHVlc1wiLFxuICAgIHBhcmFtczogKHsgc2NoZW1hQ29kZSB9KSA9PiAoMCwgY29kZWdlbl8xLl8pIGB7YWxsb3dlZFZhbHVlczogJHtzY2hlbWFDb2RlfX1gLFxufTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBcImVudW1cIixcbiAgICBzY2hlbWFUeXBlOiBcImFycmF5XCIsXG4gICAgJGRhdGE6IHRydWUsXG4gICAgZXJyb3IsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgeyBnZW4sIGRhdGEsICRkYXRhLCBzY2hlbWEsIHNjaGVtYUNvZGUsIGl0IH0gPSBjeHQ7XG4gICAgICAgIGlmICghJGRhdGEgJiYgc2NoZW1hLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImVudW0gbXVzdCBoYXZlIG5vbi1lbXB0eSBhcnJheVwiKTtcbiAgICAgICAgY29uc3QgdXNlTG9vcCA9IHNjaGVtYS5sZW5ndGggPj0gaXQub3B0cy5sb29wRW51bTtcbiAgICAgICAgbGV0IGVxbDtcbiAgICAgICAgY29uc3QgZ2V0RXFsID0gKCkgPT4gKGVxbCAhPT0gbnVsbCAmJiBlcWwgIT09IHZvaWQgMCA/IGVxbCA6IChlcWwgPSAoMCwgdXRpbF8xLnVzZUZ1bmMpKGdlbiwgZXF1YWxfMS5kZWZhdWx0KSkpO1xuICAgICAgICBsZXQgdmFsaWQ7XG4gICAgICAgIGlmICh1c2VMb29wIHx8ICRkYXRhKSB7XG4gICAgICAgICAgICB2YWxpZCA9IGdlbi5sZXQoXCJ2YWxpZFwiKTtcbiAgICAgICAgICAgIGN4dC5ibG9jayRkYXRhKHZhbGlkLCBsb29wRW51bSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShzY2hlbWEpKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImFqdiBpbXBsZW1lbnRhdGlvbiBlcnJvclwiKTtcbiAgICAgICAgICAgIGNvbnN0IHZTY2hlbWEgPSBnZW4uY29uc3QoXCJ2U2NoZW1hXCIsIHNjaGVtYUNvZGUpO1xuICAgICAgICAgICAgdmFsaWQgPSAoMCwgY29kZWdlbl8xLm9yKSguLi5zY2hlbWEubWFwKChfeCwgaSkgPT4gZXF1YWxDb2RlKHZTY2hlbWEsIGkpKSk7XG4gICAgICAgIH1cbiAgICAgICAgY3h0LnBhc3ModmFsaWQpO1xuICAgICAgICBmdW5jdGlvbiBsb29wRW51bSgpIHtcbiAgICAgICAgICAgIGdlbi5hc3NpZ24odmFsaWQsIGZhbHNlKTtcbiAgICAgICAgICAgIGdlbi5mb3JPZihcInZcIiwgc2NoZW1hQ29kZSwgKHYpID0+IGdlbi5pZigoMCwgY29kZWdlbl8xLl8pIGAke2dldEVxbCgpfSgke2RhdGF9LCAke3Z9KWAsICgpID0+IGdlbi5hc3NpZ24odmFsaWQsIHRydWUpLmJyZWFrKCkpKTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBlcXVhbENvZGUodlNjaGVtYSwgaSkge1xuICAgICAgICAgICAgY29uc3Qgc2NoID0gc2NoZW1hW2ldO1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBzY2ggPT09IFwib2JqZWN0XCIgJiYgc2NoICE9PSBudWxsXG4gICAgICAgICAgICAgICAgPyAoMCwgY29kZWdlbl8xLl8pIGAke2dldEVxbCgpfSgke2RhdGF9LCAke3ZTY2hlbWF9WyR7aX1dKWBcbiAgICAgICAgICAgICAgICA6ICgwLCBjb2RlZ2VuXzEuXykgYCR7ZGF0YX0gPT09ICR7c2NofWA7XG4gICAgICAgIH1cbiAgICB9LFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWVudW0uanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBsaW1pdE51bWJlcl8xID0gcmVxdWlyZShcIi4vbGltaXROdW1iZXJcIik7XG5jb25zdCBtdWx0aXBsZU9mXzEgPSByZXF1aXJlKFwiLi9tdWx0aXBsZU9mXCIpO1xuY29uc3QgbGltaXRMZW5ndGhfMSA9IHJlcXVpcmUoXCIuL2xpbWl0TGVuZ3RoXCIpO1xuY29uc3QgcGF0dGVybl8xID0gcmVxdWlyZShcIi4vcGF0dGVyblwiKTtcbmNvbnN0IGxpbWl0UHJvcGVydGllc18xID0gcmVxdWlyZShcIi4vbGltaXRQcm9wZXJ0aWVzXCIpO1xuY29uc3QgcmVxdWlyZWRfMSA9IHJlcXVpcmUoXCIuL3JlcXVpcmVkXCIpO1xuY29uc3QgbGltaXRJdGVtc18xID0gcmVxdWlyZShcIi4vbGltaXRJdGVtc1wiKTtcbmNvbnN0IHVuaXF1ZUl0ZW1zXzEgPSByZXF1aXJlKFwiLi91bmlxdWVJdGVtc1wiKTtcbmNvbnN0IGNvbnN0XzEgPSByZXF1aXJlKFwiLi9jb25zdFwiKTtcbmNvbnN0IGVudW1fMSA9IHJlcXVpcmUoXCIuL2VudW1cIik7XG5jb25zdCB2YWxpZGF0aW9uID0gW1xuICAgIC8vIG51bWJlclxuICAgIGxpbWl0TnVtYmVyXzEuZGVmYXVsdCxcbiAgICBtdWx0aXBsZU9mXzEuZGVmYXVsdCxcbiAgICAvLyBzdHJpbmdcbiAgICBsaW1pdExlbmd0aF8xLmRlZmF1bHQsXG4gICAgcGF0dGVybl8xLmRlZmF1bHQsXG4gICAgLy8gb2JqZWN0XG4gICAgbGltaXRQcm9wZXJ0aWVzXzEuZGVmYXVsdCxcbiAgICByZXF1aXJlZF8xLmRlZmF1bHQsXG4gICAgLy8gYXJyYXlcbiAgICBsaW1pdEl0ZW1zXzEuZGVmYXVsdCxcbiAgICB1bmlxdWVJdGVtc18xLmRlZmF1bHQsXG4gICAgLy8gYW55XG4gICAgeyBrZXl3b3JkOiBcInR5cGVcIiwgc2NoZW1hVHlwZTogW1wic3RyaW5nXCIsIFwiYXJyYXlcIl0gfSxcbiAgICB7IGtleXdvcmQ6IFwibnVsbGFibGVcIiwgc2NoZW1hVHlwZTogXCJib29sZWFuXCIgfSxcbiAgICBjb25zdF8xLmRlZmF1bHQsXG4gICAgZW51bV8xLmRlZmF1bHQsXG5dO1xuZXhwb3J0cy5kZWZhdWx0ID0gdmFsaWRhdGlvbjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWluZGV4LmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgdXRpbF8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdXRpbFwiKTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBbXCJtYXhDb250YWluc1wiLCBcIm1pbkNvbnRhaW5zXCJdLFxuICAgIHR5cGU6IFwiYXJyYXlcIixcbiAgICBzY2hlbWFUeXBlOiBcIm51bWJlclwiLFxuICAgIGNvZGUoeyBrZXl3b3JkLCBwYXJlbnRTY2hlbWEsIGl0IH0pIHtcbiAgICAgICAgaWYgKHBhcmVudFNjaGVtYS5jb250YWlucyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAoMCwgdXRpbF8xLmNoZWNrU3RyaWN0TW9kZSkoaXQsIGBcIiR7a2V5d29yZH1cIiB3aXRob3V0IFwiY29udGFpbnNcIiBpcyBpZ25vcmVkYCk7XG4gICAgICAgIH1cbiAgICB9LFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWxpbWl0Q29udGFpbnMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9jb2RlZ2VuXCIpO1xuY29uc3QgZXJyb3IgPSB7XG4gICAgbWVzc2FnZSh7IGtleXdvcmQsIHNjaGVtYUNvZGUgfSkge1xuICAgICAgICBjb25zdCBjb21wID0ga2V5d29yZCA9PT0gXCJtYXhJdGVtc1wiID8gXCJtb3JlXCIgOiBcImZld2VyXCI7XG4gICAgICAgIHJldHVybiAoMCwgY29kZWdlbl8xLnN0cikgYG11c3QgTk9UIGhhdmUgJHtjb21wfSB0aGFuICR7c2NoZW1hQ29kZX0gaXRlbXNgO1xuICAgIH0sXG4gICAgcGFyYW1zOiAoeyBzY2hlbWFDb2RlIH0pID0+ICgwLCBjb2RlZ2VuXzEuXykgYHtsaW1pdDogJHtzY2hlbWFDb2RlfX1gLFxufTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBbXCJtYXhJdGVtc1wiLCBcIm1pbkl0ZW1zXCJdLFxuICAgIHR5cGU6IFwiYXJyYXlcIixcbiAgICBzY2hlbWFUeXBlOiBcIm51bWJlclwiLFxuICAgICRkYXRhOiB0cnVlLFxuICAgIGVycm9yLFxuICAgIGNvZGUoY3h0KSB7XG4gICAgICAgIGNvbnN0IHsga2V5d29yZCwgZGF0YSwgc2NoZW1hQ29kZSB9ID0gY3h0O1xuICAgICAgICBjb25zdCBvcCA9IGtleXdvcmQgPT09IFwibWF4SXRlbXNcIiA/IGNvZGVnZW5fMS5vcGVyYXRvcnMuR1QgOiBjb2RlZ2VuXzEub3BlcmF0b3JzLkxUO1xuICAgICAgICBjeHQuZmFpbCRkYXRhKCgwLCBjb2RlZ2VuXzEuXykgYCR7ZGF0YX0ubGVuZ3RoICR7b3B9ICR7c2NoZW1hQ29kZX1gKTtcbiAgICB9LFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWxpbWl0SXRlbXMuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9jb2RlZ2VuXCIpO1xuY29uc3QgdXRpbF8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdXRpbFwiKTtcbmNvbnN0IHVjczJsZW5ndGhfMSA9IHJlcXVpcmUoXCIuLi8uLi9ydW50aW1lL3VjczJsZW5ndGhcIik7XG5jb25zdCBlcnJvciA9IHtcbiAgICBtZXNzYWdlKHsga2V5d29yZCwgc2NoZW1hQ29kZSB9KSB7XG4gICAgICAgIGNvbnN0IGNvbXAgPSBrZXl3b3JkID09PSBcIm1heExlbmd0aFwiID8gXCJtb3JlXCIgOiBcImZld2VyXCI7XG4gICAgICAgIHJldHVybiAoMCwgY29kZWdlbl8xLnN0cikgYG11c3QgTk9UIGhhdmUgJHtjb21wfSB0aGFuICR7c2NoZW1hQ29kZX0gY2hhcmFjdGVyc2A7XG4gICAgfSxcbiAgICBwYXJhbXM6ICh7IHNjaGVtYUNvZGUgfSkgPT4gKDAsIGNvZGVnZW5fMS5fKSBge2xpbWl0OiAke3NjaGVtYUNvZGV9fWAsXG59O1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFtcIm1heExlbmd0aFwiLCBcIm1pbkxlbmd0aFwiXSxcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIHNjaGVtYVR5cGU6IFwibnVtYmVyXCIsXG4gICAgJGRhdGE6IHRydWUsXG4gICAgZXJyb3IsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgeyBrZXl3b3JkLCBkYXRhLCBzY2hlbWFDb2RlLCBpdCB9ID0gY3h0O1xuICAgICAgICBjb25zdCBvcCA9IGtleXdvcmQgPT09IFwibWF4TGVuZ3RoXCIgPyBjb2RlZ2VuXzEub3BlcmF0b3JzLkdUIDogY29kZWdlbl8xLm9wZXJhdG9ycy5MVDtcbiAgICAgICAgY29uc3QgbGVuID0gaXQub3B0cy51bmljb2RlID09PSBmYWxzZSA/ICgwLCBjb2RlZ2VuXzEuXykgYCR7ZGF0YX0ubGVuZ3RoYCA6ICgwLCBjb2RlZ2VuXzEuXykgYCR7KDAsIHV0aWxfMS51c2VGdW5jKShjeHQuZ2VuLCB1Y3MybGVuZ3RoXzEuZGVmYXVsdCl9KCR7ZGF0YX0pYDtcbiAgICAgICAgY3h0LmZhaWwkZGF0YSgoMCwgY29kZWdlbl8xLl8pIGAke2xlbn0gJHtvcH0gJHtzY2hlbWFDb2RlfWApO1xuICAgIH0sXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bGltaXRMZW5ndGguanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9jb2RlZ2VuXCIpO1xuY29uc3Qgb3BzID0gY29kZWdlbl8xLm9wZXJhdG9ycztcbmNvbnN0IEtXRHMgPSB7XG4gICAgbWF4aW11bTogeyBva1N0cjogXCI8PVwiLCBvazogb3BzLkxURSwgZmFpbDogb3BzLkdUIH0sXG4gICAgbWluaW11bTogeyBva1N0cjogXCI+PVwiLCBvazogb3BzLkdURSwgZmFpbDogb3BzLkxUIH0sXG4gICAgZXhjbHVzaXZlTWF4aW11bTogeyBva1N0cjogXCI8XCIsIG9rOiBvcHMuTFQsIGZhaWw6IG9wcy5HVEUgfSxcbiAgICBleGNsdXNpdmVNaW5pbXVtOiB7IG9rU3RyOiBcIj5cIiwgb2s6IG9wcy5HVCwgZmFpbDogb3BzLkxURSB9LFxufTtcbmNvbnN0IGVycm9yID0ge1xuICAgIG1lc3NhZ2U6ICh7IGtleXdvcmQsIHNjaGVtYUNvZGUgfSkgPT4gKDAsIGNvZGVnZW5fMS5zdHIpIGBtdXN0IGJlICR7S1dEc1trZXl3b3JkXS5va1N0cn0gJHtzY2hlbWFDb2RlfWAsXG4gICAgcGFyYW1zOiAoeyBrZXl3b3JkLCBzY2hlbWFDb2RlIH0pID0+ICgwLCBjb2RlZ2VuXzEuXykgYHtjb21wYXJpc29uOiAke0tXRHNba2V5d29yZF0ub2tTdHJ9LCBsaW1pdDogJHtzY2hlbWFDb2RlfX1gLFxufTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBPYmplY3Qua2V5cyhLV0RzKSxcbiAgICB0eXBlOiBcIm51bWJlclwiLFxuICAgIHNjaGVtYVR5cGU6IFwibnVtYmVyXCIsXG4gICAgJGRhdGE6IHRydWUsXG4gICAgZXJyb3IsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgeyBrZXl3b3JkLCBkYXRhLCBzY2hlbWFDb2RlIH0gPSBjeHQ7XG4gICAgICAgIGN4dC5mYWlsJGRhdGEoKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhfSAke0tXRHNba2V5d29yZF0uZmFpbH0gJHtzY2hlbWFDb2RlfSB8fCBpc05hTigke2RhdGF9KWApO1xuICAgIH0sXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bGltaXROdW1iZXIuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9jb2RlZ2VuXCIpO1xuY29uc3QgZXJyb3IgPSB7XG4gICAgbWVzc2FnZSh7IGtleXdvcmQsIHNjaGVtYUNvZGUgfSkge1xuICAgICAgICBjb25zdCBjb21wID0ga2V5d29yZCA9PT0gXCJtYXhQcm9wZXJ0aWVzXCIgPyBcIm1vcmVcIiA6IFwiZmV3ZXJcIjtcbiAgICAgICAgcmV0dXJuICgwLCBjb2RlZ2VuXzEuc3RyKSBgbXVzdCBOT1QgaGF2ZSAke2NvbXB9IHRoYW4gJHtzY2hlbWFDb2RlfSBwcm9wZXJ0aWVzYDtcbiAgICB9LFxuICAgIHBhcmFtczogKHsgc2NoZW1hQ29kZSB9KSA9PiAoMCwgY29kZWdlbl8xLl8pIGB7bGltaXQ6ICR7c2NoZW1hQ29kZX19YCxcbn07XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogW1wibWF4UHJvcGVydGllc1wiLCBcIm1pblByb3BlcnRpZXNcIl0sXG4gICAgdHlwZTogXCJvYmplY3RcIixcbiAgICBzY2hlbWFUeXBlOiBcIm51bWJlclwiLFxuICAgICRkYXRhOiB0cnVlLFxuICAgIGVycm9yLFxuICAgIGNvZGUoY3h0KSB7XG4gICAgICAgIGNvbnN0IHsga2V5d29yZCwgZGF0YSwgc2NoZW1hQ29kZSB9ID0gY3h0O1xuICAgICAgICBjb25zdCBvcCA9IGtleXdvcmQgPT09IFwibWF4UHJvcGVydGllc1wiID8gY29kZWdlbl8xLm9wZXJhdG9ycy5HVCA6IGNvZGVnZW5fMS5vcGVyYXRvcnMuTFQ7XG4gICAgICAgIGN4dC5mYWlsJGRhdGEoKDAsIGNvZGVnZW5fMS5fKSBgT2JqZWN0LmtleXMoJHtkYXRhfSkubGVuZ3RoICR7b3B9ICR7c2NoZW1hQ29kZX1gKTtcbiAgICB9LFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGRlZjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWxpbWl0UHJvcGVydGllcy5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGNvZGVnZW5fMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL2NvZGVnZW5cIik7XG5jb25zdCBlcnJvciA9IHtcbiAgICBtZXNzYWdlOiAoeyBzY2hlbWFDb2RlIH0pID0+ICgwLCBjb2RlZ2VuXzEuc3RyKSBgbXVzdCBiZSBtdWx0aXBsZSBvZiAke3NjaGVtYUNvZGV9YCxcbiAgICBwYXJhbXM6ICh7IHNjaGVtYUNvZGUgfSkgPT4gKDAsIGNvZGVnZW5fMS5fKSBge211bHRpcGxlT2Y6ICR7c2NoZW1hQ29kZX19YCxcbn07XG5jb25zdCBkZWYgPSB7XG4gICAga2V5d29yZDogXCJtdWx0aXBsZU9mXCIsXG4gICAgdHlwZTogXCJudW1iZXJcIixcbiAgICBzY2hlbWFUeXBlOiBcIm51bWJlclwiLFxuICAgICRkYXRhOiB0cnVlLFxuICAgIGVycm9yLFxuICAgIGNvZGUoY3h0KSB7XG4gICAgICAgIGNvbnN0IHsgZ2VuLCBkYXRhLCBzY2hlbWFDb2RlLCBpdCB9ID0gY3h0O1xuICAgICAgICAvLyBjb25zdCBiZHQgPSBiYWQkRGF0YVR5cGUoc2NoZW1hQ29kZSwgPHN0cmluZz5kZWYuc2NoZW1hVHlwZSwgJGRhdGEpXG4gICAgICAgIGNvbnN0IHByZWMgPSBpdC5vcHRzLm11bHRpcGxlT2ZQcmVjaXNpb247XG4gICAgICAgIGNvbnN0IHJlcyA9IGdlbi5sZXQoXCJyZXNcIik7XG4gICAgICAgIGNvbnN0IGludmFsaWQgPSBwcmVjXG4gICAgICAgICAgICA/ICgwLCBjb2RlZ2VuXzEuXykgYE1hdGguYWJzKE1hdGgucm91bmQoJHtyZXN9KSAtICR7cmVzfSkgPiAxZS0ke3ByZWN9YFxuICAgICAgICAgICAgOiAoMCwgY29kZWdlbl8xLl8pIGAke3Jlc30gIT09IHBhcnNlSW50KCR7cmVzfSlgO1xuICAgICAgICBjeHQuZmFpbCRkYXRhKCgwLCBjb2RlZ2VuXzEuXykgYCgke3NjaGVtYUNvZGV9ID09PSAwIHx8ICgke3Jlc30gPSAke2RhdGF9LyR7c2NoZW1hQ29kZX0sICR7aW52YWxpZH0pKWApO1xuICAgIH0sXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bXVsdGlwbGVPZi5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGNvZGVfMSA9IHJlcXVpcmUoXCIuLi9jb2RlXCIpO1xuY29uc3QgY29kZWdlbl8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvY29kZWdlblwiKTtcbmNvbnN0IGVycm9yID0ge1xuICAgIG1lc3NhZ2U6ICh7IHNjaGVtYUNvZGUgfSkgPT4gKDAsIGNvZGVnZW5fMS5zdHIpIGBtdXN0IG1hdGNoIHBhdHRlcm4gXCIke3NjaGVtYUNvZGV9XCJgLFxuICAgIHBhcmFtczogKHsgc2NoZW1hQ29kZSB9KSA9PiAoMCwgY29kZWdlbl8xLl8pIGB7cGF0dGVybjogJHtzY2hlbWFDb2RlfX1gLFxufTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBcInBhdHRlcm5cIixcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIHNjaGVtYVR5cGU6IFwic3RyaW5nXCIsXG4gICAgJGRhdGE6IHRydWUsXG4gICAgZXJyb3IsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgeyBkYXRhLCAkZGF0YSwgc2NoZW1hLCBzY2hlbWFDb2RlLCBpdCB9ID0gY3h0O1xuICAgICAgICAvLyBUT0RPIHJlZ2V4cCBzaG91bGQgYmUgd3JhcHBlZCBpbiB0cnkvY2F0Y2hzXG4gICAgICAgIGNvbnN0IHUgPSBpdC5vcHRzLnVuaWNvZGVSZWdFeHAgPyBcInVcIiA6IFwiXCI7XG4gICAgICAgIGNvbnN0IHJlZ0V4cCA9ICRkYXRhID8gKDAsIGNvZGVnZW5fMS5fKSBgKG5ldyBSZWdFeHAoJHtzY2hlbWFDb2RlfSwgJHt1fSkpYCA6ICgwLCBjb2RlXzEudXNlUGF0dGVybikoY3h0LCBzY2hlbWEpO1xuICAgICAgICBjeHQuZmFpbCRkYXRhKCgwLCBjb2RlZ2VuXzEuXykgYCEke3JlZ0V4cH0udGVzdCgke2RhdGF9KWApO1xuICAgIH0sXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cGF0dGVybi5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGNvZGVfMSA9IHJlcXVpcmUoXCIuLi9jb2RlXCIpO1xuY29uc3QgY29kZWdlbl8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvY29kZWdlblwiKTtcbmNvbnN0IHV0aWxfMSA9IHJlcXVpcmUoXCIuLi8uLi9jb21waWxlL3V0aWxcIik7XG5jb25zdCBlcnJvciA9IHtcbiAgICBtZXNzYWdlOiAoeyBwYXJhbXM6IHsgbWlzc2luZ1Byb3BlcnR5IH0gfSkgPT4gKDAsIGNvZGVnZW5fMS5zdHIpIGBtdXN0IGhhdmUgcmVxdWlyZWQgcHJvcGVydHkgJyR7bWlzc2luZ1Byb3BlcnR5fSdgLFxuICAgIHBhcmFtczogKHsgcGFyYW1zOiB7IG1pc3NpbmdQcm9wZXJ0eSB9IH0pID0+ICgwLCBjb2RlZ2VuXzEuXykgYHttaXNzaW5nUHJvcGVydHk6ICR7bWlzc2luZ1Byb3BlcnR5fX1gLFxufTtcbmNvbnN0IGRlZiA9IHtcbiAgICBrZXl3b3JkOiBcInJlcXVpcmVkXCIsXG4gICAgdHlwZTogXCJvYmplY3RcIixcbiAgICBzY2hlbWFUeXBlOiBcImFycmF5XCIsXG4gICAgJGRhdGE6IHRydWUsXG4gICAgZXJyb3IsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgeyBnZW4sIHNjaGVtYSwgc2NoZW1hQ29kZSwgZGF0YSwgJGRhdGEsIGl0IH0gPSBjeHQ7XG4gICAgICAgIGNvbnN0IHsgb3B0cyB9ID0gaXQ7XG4gICAgICAgIGlmICghJGRhdGEgJiYgc2NoZW1hLmxlbmd0aCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY29uc3QgdXNlTG9vcCA9IHNjaGVtYS5sZW5ndGggPj0gb3B0cy5sb29wUmVxdWlyZWQ7XG4gICAgICAgIGlmIChpdC5hbGxFcnJvcnMpXG4gICAgICAgICAgICBhbGxFcnJvcnNNb2RlKCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGV4aXRPbkVycm9yTW9kZSgpO1xuICAgICAgICBpZiAob3B0cy5zdHJpY3RSZXF1aXJlZCkge1xuICAgICAgICAgICAgY29uc3QgcHJvcHMgPSBjeHQucGFyZW50U2NoZW1hLnByb3BlcnRpZXM7XG4gICAgICAgICAgICBjb25zdCB7IGRlZmluZWRQcm9wZXJ0aWVzIH0gPSBjeHQuaXQ7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHJlcXVpcmVkS2V5IG9mIHNjaGVtYSkge1xuICAgICAgICAgICAgICAgIGlmICgocHJvcHMgPT09IG51bGwgfHwgcHJvcHMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHByb3BzW3JlcXVpcmVkS2V5XSkgPT09IHVuZGVmaW5lZCAmJiAhZGVmaW5lZFByb3BlcnRpZXMuaGFzKHJlcXVpcmVkS2V5KSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzY2hlbWFQYXRoID0gaXQuc2NoZW1hRW52LmJhc2VJZCArIGl0LmVyclNjaGVtYVBhdGg7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG1zZyA9IGByZXF1aXJlZCBwcm9wZXJ0eSBcIiR7cmVxdWlyZWRLZXl9XCIgaXMgbm90IGRlZmluZWQgYXQgXCIke3NjaGVtYVBhdGh9XCIgKHN0cmljdFJlcXVpcmVkKWA7XG4gICAgICAgICAgICAgICAgICAgICgwLCB1dGlsXzEuY2hlY2tTdHJpY3RNb2RlKShpdCwgbXNnLCBpdC5vcHRzLnN0cmljdFJlcXVpcmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gYWxsRXJyb3JzTW9kZSgpIHtcbiAgICAgICAgICAgIGlmICh1c2VMb29wIHx8ICRkYXRhKSB7XG4gICAgICAgICAgICAgICAgY3h0LmJsb2NrJGRhdGEoY29kZWdlbl8xLm5pbCwgbG9vcEFsbFJlcXVpcmVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcHJvcCBvZiBzY2hlbWEpIHtcbiAgICAgICAgICAgICAgICAgICAgKDAsIGNvZGVfMS5jaGVja1JlcG9ydE1pc3NpbmdQcm9wKShjeHQsIHByb3ApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBleGl0T25FcnJvck1vZGUoKSB7XG4gICAgICAgICAgICBjb25zdCBtaXNzaW5nID0gZ2VuLmxldChcIm1pc3NpbmdcIik7XG4gICAgICAgICAgICBpZiAodXNlTG9vcCB8fCAkZGF0YSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbGlkID0gZ2VuLmxldChcInZhbGlkXCIsIHRydWUpO1xuICAgICAgICAgICAgICAgIGN4dC5ibG9jayRkYXRhKHZhbGlkLCAoKSA9PiBsb29wVW50aWxNaXNzaW5nKG1pc3NpbmcsIHZhbGlkKSk7XG4gICAgICAgICAgICAgICAgY3h0Lm9rKHZhbGlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGdlbi5pZigoMCwgY29kZV8xLmNoZWNrTWlzc2luZ1Byb3ApKGN4dCwgc2NoZW1hLCBtaXNzaW5nKSk7XG4gICAgICAgICAgICAgICAgKDAsIGNvZGVfMS5yZXBvcnRNaXNzaW5nUHJvcCkoY3h0LCBtaXNzaW5nKTtcbiAgICAgICAgICAgICAgICBnZW4uZWxzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGxvb3BBbGxSZXF1aXJlZCgpIHtcbiAgICAgICAgICAgIGdlbi5mb3JPZihcInByb3BcIiwgc2NoZW1hQ29kZSwgKHByb3ApID0+IHtcbiAgICAgICAgICAgICAgICBjeHQuc2V0UGFyYW1zKHsgbWlzc2luZ1Byb3BlcnR5OiBwcm9wIH0pO1xuICAgICAgICAgICAgICAgIGdlbi5pZigoMCwgY29kZV8xLm5vUHJvcGVydHlJbkRhdGEpKGdlbiwgZGF0YSwgcHJvcCwgb3B0cy5vd25Qcm9wZXJ0aWVzKSwgKCkgPT4gY3h0LmVycm9yKCkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gbG9vcFVudGlsTWlzc2luZyhtaXNzaW5nLCB2YWxpZCkge1xuICAgICAgICAgICAgY3h0LnNldFBhcmFtcyh7IG1pc3NpbmdQcm9wZXJ0eTogbWlzc2luZyB9KTtcbiAgICAgICAgICAgIGdlbi5mb3JPZihtaXNzaW5nLCBzY2hlbWFDb2RlLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgZ2VuLmFzc2lnbih2YWxpZCwgKDAsIGNvZGVfMS5wcm9wZXJ0eUluRGF0YSkoZ2VuLCBkYXRhLCBtaXNzaW5nLCBvcHRzLm93blByb3BlcnRpZXMpKTtcbiAgICAgICAgICAgICAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5ub3QpKHZhbGlkKSwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjeHQuZXJyb3IoKTtcbiAgICAgICAgICAgICAgICAgICAgZ2VuLmJyZWFrKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LCBjb2RlZ2VuXzEubmlsKTtcbiAgICAgICAgfVxuICAgIH0sXG59O1xuZXhwb3J0cy5kZWZhdWx0ID0gZGVmO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cmVxdWlyZWQuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBkYXRhVHlwZV8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdmFsaWRhdGUvZGF0YVR5cGVcIik7XG5jb25zdCBjb2RlZ2VuXzEgPSByZXF1aXJlKFwiLi4vLi4vY29tcGlsZS9jb2RlZ2VuXCIpO1xuY29uc3QgdXRpbF8xID0gcmVxdWlyZShcIi4uLy4uL2NvbXBpbGUvdXRpbFwiKTtcbmNvbnN0IGVxdWFsXzEgPSByZXF1aXJlKFwiLi4vLi4vcnVudGltZS9lcXVhbFwiKTtcbmNvbnN0IGVycm9yID0ge1xuICAgIG1lc3NhZ2U6ICh7IHBhcmFtczogeyBpLCBqIH0gfSkgPT4gKDAsIGNvZGVnZW5fMS5zdHIpIGBtdXN0IE5PVCBoYXZlIGR1cGxpY2F0ZSBpdGVtcyAoaXRlbXMgIyMgJHtqfSBhbmQgJHtpfSBhcmUgaWRlbnRpY2FsKWAsXG4gICAgcGFyYW1zOiAoeyBwYXJhbXM6IHsgaSwgaiB9IH0pID0+ICgwLCBjb2RlZ2VuXzEuXykgYHtpOiAke2l9LCBqOiAke2p9fWAsXG59O1xuY29uc3QgZGVmID0ge1xuICAgIGtleXdvcmQ6IFwidW5pcXVlSXRlbXNcIixcbiAgICB0eXBlOiBcImFycmF5XCIsXG4gICAgc2NoZW1hVHlwZTogXCJib29sZWFuXCIsXG4gICAgJGRhdGE6IHRydWUsXG4gICAgZXJyb3IsXG4gICAgY29kZShjeHQpIHtcbiAgICAgICAgY29uc3QgeyBnZW4sIGRhdGEsICRkYXRhLCBzY2hlbWEsIHBhcmVudFNjaGVtYSwgc2NoZW1hQ29kZSwgaXQgfSA9IGN4dDtcbiAgICAgICAgaWYgKCEkZGF0YSAmJiAhc2NoZW1hKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjb25zdCB2YWxpZCA9IGdlbi5sZXQoXCJ2YWxpZFwiKTtcbiAgICAgICAgY29uc3QgaXRlbVR5cGVzID0gcGFyZW50U2NoZW1hLml0ZW1zID8gKDAsIGRhdGFUeXBlXzEuZ2V0U2NoZW1hVHlwZXMpKHBhcmVudFNjaGVtYS5pdGVtcykgOiBbXTtcbiAgICAgICAgY3h0LmJsb2NrJGRhdGEodmFsaWQsIHZhbGlkYXRlVW5pcXVlSXRlbXMsICgwLCBjb2RlZ2VuXzEuXykgYCR7c2NoZW1hQ29kZX0gPT09IGZhbHNlYCk7XG4gICAgICAgIGN4dC5vayh2YWxpZCk7XG4gICAgICAgIGZ1bmN0aW9uIHZhbGlkYXRlVW5pcXVlSXRlbXMoKSB7XG4gICAgICAgICAgICBjb25zdCBpID0gZ2VuLmxldChcImlcIiwgKDAsIGNvZGVnZW5fMS5fKSBgJHtkYXRhfS5sZW5ndGhgKTtcbiAgICAgICAgICAgIGNvbnN0IGogPSBnZW4ubGV0KFwialwiKTtcbiAgICAgICAgICAgIGN4dC5zZXRQYXJhbXMoeyBpLCBqIH0pO1xuICAgICAgICAgICAgZ2VuLmFzc2lnbih2YWxpZCwgdHJ1ZSk7XG4gICAgICAgICAgICBnZW4uaWYoKDAsIGNvZGVnZW5fMS5fKSBgJHtpfSA+IDFgLCAoKSA9PiAoY2FuT3B0aW1pemUoKSA/IGxvb3BOIDogbG9vcE4yKShpLCBqKSk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gY2FuT3B0aW1pemUoKSB7XG4gICAgICAgICAgICByZXR1cm4gaXRlbVR5cGVzLmxlbmd0aCA+IDAgJiYgIWl0ZW1UeXBlcy5zb21lKCh0KSA9PiB0ID09PSBcIm9iamVjdFwiIHx8IHQgPT09IFwiYXJyYXlcIik7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gbG9vcE4oaSwgaikge1xuICAgICAgICAgICAgY29uc3QgaXRlbSA9IGdlbi5uYW1lKFwiaXRlbVwiKTtcbiAgICAgICAgICAgIGNvbnN0IHdyb25nVHlwZSA9ICgwLCBkYXRhVHlwZV8xLmNoZWNrRGF0YVR5cGVzKShpdGVtVHlwZXMsIGl0ZW0sIGl0Lm9wdHMuc3RyaWN0TnVtYmVycywgZGF0YVR5cGVfMS5EYXRhVHlwZS5Xcm9uZyk7XG4gICAgICAgICAgICBjb25zdCBpbmRpY2VzID0gZ2VuLmNvbnN0KFwiaW5kaWNlc1wiLCAoMCwgY29kZWdlbl8xLl8pIGB7fWApO1xuICAgICAgICAgICAgZ2VuLmZvcigoMCwgY29kZWdlbl8xLl8pIGA7JHtpfS0tO2AsICgpID0+IHtcbiAgICAgICAgICAgICAgICBnZW4ubGV0KGl0ZW0sICgwLCBjb2RlZ2VuXzEuXykgYCR7ZGF0YX1bJHtpfV1gKTtcbiAgICAgICAgICAgICAgICBnZW4uaWYod3JvbmdUeXBlLCAoMCwgY29kZWdlbl8xLl8pIGBjb250aW51ZWApO1xuICAgICAgICAgICAgICAgIGlmIChpdGVtVHlwZXMubGVuZ3RoID4gMSlcbiAgICAgICAgICAgICAgICAgICAgZ2VuLmlmKCgwLCBjb2RlZ2VuXzEuXykgYHR5cGVvZiAke2l0ZW19ID09IFwic3RyaW5nXCJgLCAoMCwgY29kZWdlbl8xLl8pIGAke2l0ZW19ICs9IFwiX1wiYCk7XG4gICAgICAgICAgICAgICAgZ2VuXG4gICAgICAgICAgICAgICAgICAgIC5pZigoMCwgY29kZWdlbl8xLl8pIGB0eXBlb2YgJHtpbmRpY2VzfVske2l0ZW19XSA9PSBcIm51bWJlclwiYCwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBnZW4uYXNzaWduKGosICgwLCBjb2RlZ2VuXzEuXykgYCR7aW5kaWNlc31bJHtpdGVtfV1gKTtcbiAgICAgICAgICAgICAgICAgICAgY3h0LmVycm9yKCk7XG4gICAgICAgICAgICAgICAgICAgIGdlbi5hc3NpZ24odmFsaWQsIGZhbHNlKS5icmVhaygpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jb2RlKCgwLCBjb2RlZ2VuXzEuXykgYCR7aW5kaWNlc31bJHtpdGVtfV0gPSAke2l9YCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBsb29wTjIoaSwgaikge1xuICAgICAgICAgICAgY29uc3QgZXFsID0gKDAsIHV0aWxfMS51c2VGdW5jKShnZW4sIGVxdWFsXzEuZGVmYXVsdCk7XG4gICAgICAgICAgICBjb25zdCBvdXRlciA9IGdlbi5uYW1lKFwib3V0ZXJcIik7XG4gICAgICAgICAgICBnZW4ubGFiZWwob3V0ZXIpLmZvcigoMCwgY29kZWdlbl8xLl8pIGA7JHtpfS0tO2AsICgpID0+IGdlbi5mb3IoKDAsIGNvZGVnZW5fMS5fKSBgJHtqfSA9ICR7aX07ICR7an0tLTtgLCAoKSA9PiBnZW4uaWYoKDAsIGNvZGVnZW5fMS5fKSBgJHtlcWx9KCR7ZGF0YX1bJHtpfV0sICR7ZGF0YX1bJHtqfV0pYCwgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGN4dC5lcnJvcigpO1xuICAgICAgICAgICAgICAgIGdlbi5hc3NpZ24odmFsaWQsIGZhbHNlKS5icmVhayhvdXRlcik7XG4gICAgICAgICAgICB9KSkpO1xuICAgICAgICB9XG4gICAgfSxcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBkZWY7XG4vLyMgc291cmNlTWFwcGluZ1VSTD11bmlxdWVJdGVtcy5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbi8vIGRvIG5vdCBlZGl0IC5qcyBmaWxlcyBkaXJlY3RseSAtIGVkaXQgc3JjL2luZGV4LmpzdFxuXG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBlcXVhbChhLCBiKSB7XG4gIGlmIChhID09PSBiKSByZXR1cm4gdHJ1ZTtcblxuICBpZiAoYSAmJiBiICYmIHR5cGVvZiBhID09ICdvYmplY3QnICYmIHR5cGVvZiBiID09ICdvYmplY3QnKSB7XG4gICAgaWYgKGEuY29uc3RydWN0b3IgIT09IGIuY29uc3RydWN0b3IpIHJldHVybiBmYWxzZTtcblxuICAgIHZhciBsZW5ndGgsIGksIGtleXM7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoYSkpIHtcbiAgICAgIGxlbmd0aCA9IGEubGVuZ3RoO1xuICAgICAgaWYgKGxlbmd0aCAhPSBiLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuICAgICAgZm9yIChpID0gbGVuZ3RoOyBpLS0gIT09IDA7KVxuICAgICAgICBpZiAoIWVxdWFsKGFbaV0sIGJbaV0pKSByZXR1cm4gZmFsc2U7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cblxuXG4gICAgaWYgKGEuY29uc3RydWN0b3IgPT09IFJlZ0V4cCkgcmV0dXJuIGEuc291cmNlID09PSBiLnNvdXJjZSAmJiBhLmZsYWdzID09PSBiLmZsYWdzO1xuICAgIGlmIChhLnZhbHVlT2YgIT09IE9iamVjdC5wcm90b3R5cGUudmFsdWVPZikgcmV0dXJuIGEudmFsdWVPZigpID09PSBiLnZhbHVlT2YoKTtcbiAgICBpZiAoYS50b1N0cmluZyAhPT0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZykgcmV0dXJuIGEudG9TdHJpbmcoKSA9PT0gYi50b1N0cmluZygpO1xuXG4gICAga2V5cyA9IE9iamVjdC5rZXlzKGEpO1xuICAgIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgIGlmIChsZW5ndGggIT09IE9iamVjdC5rZXlzKGIpLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yIChpID0gbGVuZ3RoOyBpLS0gIT09IDA7KVxuICAgICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwga2V5c1tpXSkpIHJldHVybiBmYWxzZTtcblxuICAgIGZvciAoaSA9IGxlbmd0aDsgaS0tICE9PSAwOykge1xuICAgICAgdmFyIGtleSA9IGtleXNbaV07XG5cbiAgICAgIGlmICghZXF1YWwoYVtrZXldLCBiW2tleV0pKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvLyB0cnVlIGlmIGJvdGggTmFOLCBmYWxzZSBvdGhlcndpc2VcbiAgcmV0dXJuIGEhPT1hICYmIGIhPT1iO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHRyYXZlcnNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoc2NoZW1hLCBvcHRzLCBjYikge1xuICAvLyBMZWdhY3kgc3VwcG9ydCBmb3IgdjAuMy4xIGFuZCBlYXJsaWVyLlxuICBpZiAodHlwZW9mIG9wdHMgPT0gJ2Z1bmN0aW9uJykge1xuICAgIGNiID0gb3B0cztcbiAgICBvcHRzID0ge307XG4gIH1cblxuICBjYiA9IG9wdHMuY2IgfHwgY2I7XG4gIHZhciBwcmUgPSAodHlwZW9mIGNiID09ICdmdW5jdGlvbicpID8gY2IgOiBjYi5wcmUgfHwgZnVuY3Rpb24oKSB7fTtcbiAgdmFyIHBvc3QgPSBjYi5wb3N0IHx8IGZ1bmN0aW9uKCkge307XG5cbiAgX3RyYXZlcnNlKG9wdHMsIHByZSwgcG9zdCwgc2NoZW1hLCAnJywgc2NoZW1hKTtcbn07XG5cblxudHJhdmVyc2Uua2V5d29yZHMgPSB7XG4gIGFkZGl0aW9uYWxJdGVtczogdHJ1ZSxcbiAgaXRlbXM6IHRydWUsXG4gIGNvbnRhaW5zOiB0cnVlLFxuICBhZGRpdGlvbmFsUHJvcGVydGllczogdHJ1ZSxcbiAgcHJvcGVydHlOYW1lczogdHJ1ZSxcbiAgbm90OiB0cnVlLFxuICBpZjogdHJ1ZSxcbiAgdGhlbjogdHJ1ZSxcbiAgZWxzZTogdHJ1ZVxufTtcblxudHJhdmVyc2UuYXJyYXlLZXl3b3JkcyA9IHtcbiAgaXRlbXM6IHRydWUsXG4gIGFsbE9mOiB0cnVlLFxuICBhbnlPZjogdHJ1ZSxcbiAgb25lT2Y6IHRydWVcbn07XG5cbnRyYXZlcnNlLnByb3BzS2V5d29yZHMgPSB7XG4gICRkZWZzOiB0cnVlLFxuICBkZWZpbml0aW9uczogdHJ1ZSxcbiAgcHJvcGVydGllczogdHJ1ZSxcbiAgcGF0dGVyblByb3BlcnRpZXM6IHRydWUsXG4gIGRlcGVuZGVuY2llczogdHJ1ZVxufTtcblxudHJhdmVyc2Uuc2tpcEtleXdvcmRzID0ge1xuICBkZWZhdWx0OiB0cnVlLFxuICBlbnVtOiB0cnVlLFxuICBjb25zdDogdHJ1ZSxcbiAgcmVxdWlyZWQ6IHRydWUsXG4gIG1heGltdW06IHRydWUsXG4gIG1pbmltdW06IHRydWUsXG4gIGV4Y2x1c2l2ZU1heGltdW06IHRydWUsXG4gIGV4Y2x1c2l2ZU1pbmltdW06IHRydWUsXG4gIG11bHRpcGxlT2Y6IHRydWUsXG4gIG1heExlbmd0aDogdHJ1ZSxcbiAgbWluTGVuZ3RoOiB0cnVlLFxuICBwYXR0ZXJuOiB0cnVlLFxuICBmb3JtYXQ6IHRydWUsXG4gIG1heEl0ZW1zOiB0cnVlLFxuICBtaW5JdGVtczogdHJ1ZSxcbiAgdW5pcXVlSXRlbXM6IHRydWUsXG4gIG1heFByb3BlcnRpZXM6IHRydWUsXG4gIG1pblByb3BlcnRpZXM6IHRydWVcbn07XG5cblxuZnVuY3Rpb24gX3RyYXZlcnNlKG9wdHMsIHByZSwgcG9zdCwgc2NoZW1hLCBqc29uUHRyLCByb290U2NoZW1hLCBwYXJlbnRKc29uUHRyLCBwYXJlbnRLZXl3b3JkLCBwYXJlbnRTY2hlbWEsIGtleUluZGV4KSB7XG4gIGlmIChzY2hlbWEgJiYgdHlwZW9mIHNjaGVtYSA9PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShzY2hlbWEpKSB7XG4gICAgcHJlKHNjaGVtYSwganNvblB0ciwgcm9vdFNjaGVtYSwgcGFyZW50SnNvblB0ciwgcGFyZW50S2V5d29yZCwgcGFyZW50U2NoZW1hLCBrZXlJbmRleCk7XG4gICAgZm9yICh2YXIga2V5IGluIHNjaGVtYSkge1xuICAgICAgdmFyIHNjaCA9IHNjaGVtYVtrZXldO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoc2NoKSkge1xuICAgICAgICBpZiAoa2V5IGluIHRyYXZlcnNlLmFycmF5S2V5d29yZHMpIHtcbiAgICAgICAgICBmb3IgKHZhciBpPTA7IGk8c2NoLmxlbmd0aDsgaSsrKVxuICAgICAgICAgICAgX3RyYXZlcnNlKG9wdHMsIHByZSwgcG9zdCwgc2NoW2ldLCBqc29uUHRyICsgJy8nICsga2V5ICsgJy8nICsgaSwgcm9vdFNjaGVtYSwganNvblB0ciwga2V5LCBzY2hlbWEsIGkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGtleSBpbiB0cmF2ZXJzZS5wcm9wc0tleXdvcmRzKSB7XG4gICAgICAgIGlmIChzY2ggJiYgdHlwZW9mIHNjaCA9PSAnb2JqZWN0Jykge1xuICAgICAgICAgIGZvciAodmFyIHByb3AgaW4gc2NoKVxuICAgICAgICAgICAgX3RyYXZlcnNlKG9wdHMsIHByZSwgcG9zdCwgc2NoW3Byb3BdLCBqc29uUHRyICsgJy8nICsga2V5ICsgJy8nICsgZXNjYXBlSnNvblB0cihwcm9wKSwgcm9vdFNjaGVtYSwganNvblB0ciwga2V5LCBzY2hlbWEsIHByb3ApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGtleSBpbiB0cmF2ZXJzZS5rZXl3b3JkcyB8fCAob3B0cy5hbGxLZXlzICYmICEoa2V5IGluIHRyYXZlcnNlLnNraXBLZXl3b3JkcykpKSB7XG4gICAgICAgIF90cmF2ZXJzZShvcHRzLCBwcmUsIHBvc3QsIHNjaCwganNvblB0ciArICcvJyArIGtleSwgcm9vdFNjaGVtYSwganNvblB0ciwga2V5LCBzY2hlbWEpO1xuICAgICAgfVxuICAgIH1cbiAgICBwb3N0KHNjaGVtYSwganNvblB0ciwgcm9vdFNjaGVtYSwgcGFyZW50SnNvblB0ciwgcGFyZW50S2V5d29yZCwgcGFyZW50U2NoZW1hLCBrZXlJbmRleCk7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBlc2NhcGVKc29uUHRyKHN0cikge1xuICByZXR1cm4gc3RyLnJlcGxhY2UoL34vZywgJ34wJykucmVwbGFjZSgvXFwvL2csICd+MScpO1xufVxuIiwiLyoqIEBsaWNlbnNlIFVSSS5qcyB2NC40LjEgKGMpIDIwMTEgR2FyeSBDb3VydC4gTGljZW5zZTogaHR0cDovL2dpdGh1Yi5jb20vZ2FyeWNvdXJ0L3VyaS1qcyAqL1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLlVSSSA9IGdsb2JhbC5VUkkgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIG1lcmdlKCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBzZXRzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICAgIHNldHNbX2tleV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgfVxuXG4gICAgaWYgKHNldHMubGVuZ3RoID4gMSkge1xuICAgICAgICBzZXRzWzBdID0gc2V0c1swXS5zbGljZSgwLCAtMSk7XG4gICAgICAgIHZhciB4bCA9IHNldHMubGVuZ3RoIC0gMTtcbiAgICAgICAgZm9yICh2YXIgeCA9IDE7IHggPCB4bDsgKyt4KSB7XG4gICAgICAgICAgICBzZXRzW3hdID0gc2V0c1t4XS5zbGljZSgxLCAtMSk7XG4gICAgICAgIH1cbiAgICAgICAgc2V0c1t4bF0gPSBzZXRzW3hsXS5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHNldHMuam9pbignJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHNldHNbMF07XG4gICAgfVxufVxuZnVuY3Rpb24gc3ViZXhwKHN0cikge1xuICAgIHJldHVybiBcIig/OlwiICsgc3RyICsgXCIpXCI7XG59XG5mdW5jdGlvbiB0eXBlT2Yobykge1xuICAgIHJldHVybiBvID09PSB1bmRlZmluZWQgPyBcInVuZGVmaW5lZFwiIDogbyA9PT0gbnVsbCA/IFwibnVsbFwiIDogT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG8pLnNwbGl0KFwiIFwiKS5wb3AoKS5zcGxpdChcIl1cIikuc2hpZnQoKS50b0xvd2VyQ2FzZSgpO1xufVxuZnVuY3Rpb24gdG9VcHBlckNhc2Uoc3RyKSB7XG4gICAgcmV0dXJuIHN0ci50b1VwcGVyQ2FzZSgpO1xufVxuZnVuY3Rpb24gdG9BcnJheShvYmopIHtcbiAgICByZXR1cm4gb2JqICE9PSB1bmRlZmluZWQgJiYgb2JqICE9PSBudWxsID8gb2JqIGluc3RhbmNlb2YgQXJyYXkgPyBvYmogOiB0eXBlb2Ygb2JqLmxlbmd0aCAhPT0gXCJudW1iZXJcIiB8fCBvYmouc3BsaXQgfHwgb2JqLnNldEludGVydmFsIHx8IG9iai5jYWxsID8gW29ial0gOiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChvYmopIDogW107XG59XG5mdW5jdGlvbiBhc3NpZ24odGFyZ2V0LCBzb3VyY2UpIHtcbiAgICB2YXIgb2JqID0gdGFyZ2V0O1xuICAgIGlmIChzb3VyY2UpIHtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIHNvdXJjZSkge1xuICAgICAgICAgICAgb2JqW2tleV0gPSBzb3VyY2Vba2V5XTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gb2JqO1xufVxuXG5mdW5jdGlvbiBidWlsZEV4cHMoaXNJUkkpIHtcbiAgICB2YXIgQUxQSEEkJCA9IFwiW0EtWmEtel1cIixcbiAgICAgICAgQ1IkID0gXCJbXFxcXHgwRF1cIixcbiAgICAgICAgRElHSVQkJCA9IFwiWzAtOV1cIixcbiAgICAgICAgRFFVT1RFJCQgPSBcIltcXFxceDIyXVwiLFxuICAgICAgICBIRVhESUckJCA9IG1lcmdlKERJR0lUJCQsIFwiW0EtRmEtZl1cIiksXG4gICAgICAgIC8vY2FzZS1pbnNlbnNpdGl2ZVxuICAgIExGJCQgPSBcIltcXFxceDBBXVwiLFxuICAgICAgICBTUCQkID0gXCJbXFxcXHgyMF1cIixcbiAgICAgICAgUENUX0VOQ09ERUQkID0gc3ViZXhwKHN1YmV4cChcIiVbRUZlZl1cIiArIEhFWERJRyQkICsgXCIlXCIgKyBIRVhESUckJCArIEhFWERJRyQkICsgXCIlXCIgKyBIRVhESUckJCArIEhFWERJRyQkKSArIFwifFwiICsgc3ViZXhwKFwiJVs4OUEtRmEtZl1cIiArIEhFWERJRyQkICsgXCIlXCIgKyBIRVhESUckJCArIEhFWERJRyQkKSArIFwifFwiICsgc3ViZXhwKFwiJVwiICsgSEVYRElHJCQgKyBIRVhESUckJCkpLFxuICAgICAgICAvL2V4cGFuZGVkXG4gICAgR0VOX0RFTElNUyQkID0gXCJbXFxcXDpcXFxcL1xcXFw/XFxcXCNcXFxcW1xcXFxdXFxcXEBdXCIsXG4gICAgICAgIFNVQl9ERUxJTVMkJCA9IFwiW1xcXFwhXFxcXCRcXFxcJlxcXFwnXFxcXChcXFxcKVxcXFwqXFxcXCtcXFxcLFxcXFw7XFxcXD1dXCIsXG4gICAgICAgIFJFU0VSVkVEJCQgPSBtZXJnZShHRU5fREVMSU1TJCQsIFNVQl9ERUxJTVMkJCksXG4gICAgICAgIFVDU0NIQVIkJCA9IGlzSVJJID8gXCJbXFxcXHhBMC1cXFxcdTIwMERcXFxcdTIwMTAtXFxcXHUyMDI5XFxcXHUyMDJGLVxcXFx1RDdGRlxcXFx1RjkwMC1cXFxcdUZEQ0ZcXFxcdUZERjAtXFxcXHVGRkVGXVwiIDogXCJbXVwiLFxuICAgICAgICAvL3N1YnNldCwgZXhjbHVkZXMgYmlkaSBjb250cm9sIGNoYXJhY3RlcnNcbiAgICBJUFJJVkFURSQkID0gaXNJUkkgPyBcIltcXFxcdUUwMDAtXFxcXHVGOEZGXVwiIDogXCJbXVwiLFxuICAgICAgICAvL3N1YnNldFxuICAgIFVOUkVTRVJWRUQkJCA9IG1lcmdlKEFMUEhBJCQsIERJR0lUJCQsIFwiW1xcXFwtXFxcXC5cXFxcX1xcXFx+XVwiLCBVQ1NDSEFSJCQpLFxuICAgICAgICBTQ0hFTUUkID0gc3ViZXhwKEFMUEhBJCQgKyBtZXJnZShBTFBIQSQkLCBESUdJVCQkLCBcIltcXFxcK1xcXFwtXFxcXC5dXCIpICsgXCIqXCIpLFxuICAgICAgICBVU0VSSU5GTyQgPSBzdWJleHAoc3ViZXhwKFBDVF9FTkNPREVEJCArIFwifFwiICsgbWVyZ2UoVU5SRVNFUlZFRCQkLCBTVUJfREVMSU1TJCQsIFwiW1xcXFw6XVwiKSkgKyBcIipcIiksXG4gICAgICAgIERFQ19PQ1RFVCQgPSBzdWJleHAoc3ViZXhwKFwiMjVbMC01XVwiKSArIFwifFwiICsgc3ViZXhwKFwiMlswLTRdXCIgKyBESUdJVCQkKSArIFwifFwiICsgc3ViZXhwKFwiMVwiICsgRElHSVQkJCArIERJR0lUJCQpICsgXCJ8XCIgKyBzdWJleHAoXCJbMS05XVwiICsgRElHSVQkJCkgKyBcInxcIiArIERJR0lUJCQpLFxuICAgICAgICBERUNfT0NURVRfUkVMQVhFRCQgPSBzdWJleHAoc3ViZXhwKFwiMjVbMC01XVwiKSArIFwifFwiICsgc3ViZXhwKFwiMlswLTRdXCIgKyBESUdJVCQkKSArIFwifFwiICsgc3ViZXhwKFwiMVwiICsgRElHSVQkJCArIERJR0lUJCQpICsgXCJ8XCIgKyBzdWJleHAoXCIwP1sxLTldXCIgKyBESUdJVCQkKSArIFwifDA/MD9cIiArIERJR0lUJCQpLFxuICAgICAgICAvL3JlbGF4ZWQgcGFyc2luZyBydWxlc1xuICAgIElQVjRBRERSRVNTJCA9IHN1YmV4cChERUNfT0NURVRfUkVMQVhFRCQgKyBcIlxcXFwuXCIgKyBERUNfT0NURVRfUkVMQVhFRCQgKyBcIlxcXFwuXCIgKyBERUNfT0NURVRfUkVMQVhFRCQgKyBcIlxcXFwuXCIgKyBERUNfT0NURVRfUkVMQVhFRCQpLFxuICAgICAgICBIMTYkID0gc3ViZXhwKEhFWERJRyQkICsgXCJ7MSw0fVwiKSxcbiAgICAgICAgTFMzMiQgPSBzdWJleHAoc3ViZXhwKEgxNiQgKyBcIlxcXFw6XCIgKyBIMTYkKSArIFwifFwiICsgSVBWNEFERFJFU1MkKSxcbiAgICAgICAgSVBWNkFERFJFU1MxJCA9IHN1YmV4cChzdWJleHAoSDE2JCArIFwiXFxcXDpcIikgKyBcIns2fVwiICsgTFMzMiQpLFxuICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgIDYoIGgxNiBcIjpcIiApIGxzMzJcbiAgICBJUFY2QUREUkVTUzIkID0gc3ViZXhwKFwiXFxcXDpcXFxcOlwiICsgc3ViZXhwKEgxNiQgKyBcIlxcXFw6XCIpICsgXCJ7NX1cIiArIExTMzIkKSxcbiAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgXCI6OlwiIDUoIGgxNiBcIjpcIiApIGxzMzJcbiAgICBJUFY2QUREUkVTUzMkID0gc3ViZXhwKHN1YmV4cChIMTYkKSArIFwiP1xcXFw6XFxcXDpcIiArIHN1YmV4cChIMTYkICsgXCJcXFxcOlwiKSArIFwiezR9XCIgKyBMUzMyJCksXG4gICAgICAgIC8vWyAgICAgICAgICAgICAgIGgxNiBdIFwiOjpcIiA0KCBoMTYgXCI6XCIgKSBsczMyXG4gICAgSVBWNkFERFJFU1M0JCA9IHN1YmV4cChzdWJleHAoc3ViZXhwKEgxNiQgKyBcIlxcXFw6XCIpICsgXCJ7MCwxfVwiICsgSDE2JCkgKyBcIj9cXFxcOlxcXFw6XCIgKyBzdWJleHAoSDE2JCArIFwiXFxcXDpcIikgKyBcInszfVwiICsgTFMzMiQpLFxuICAgICAgICAvL1sgKjEoIGgxNiBcIjpcIiApIGgxNiBdIFwiOjpcIiAzKCBoMTYgXCI6XCIgKSBsczMyXG4gICAgSVBWNkFERFJFU1M1JCA9IHN1YmV4cChzdWJleHAoc3ViZXhwKEgxNiQgKyBcIlxcXFw6XCIpICsgXCJ7MCwyfVwiICsgSDE2JCkgKyBcIj9cXFxcOlxcXFw6XCIgKyBzdWJleHAoSDE2JCArIFwiXFxcXDpcIikgKyBcInsyfVwiICsgTFMzMiQpLFxuICAgICAgICAvL1sgKjIoIGgxNiBcIjpcIiApIGgxNiBdIFwiOjpcIiAyKCBoMTYgXCI6XCIgKSBsczMyXG4gICAgSVBWNkFERFJFU1M2JCA9IHN1YmV4cChzdWJleHAoc3ViZXhwKEgxNiQgKyBcIlxcXFw6XCIpICsgXCJ7MCwzfVwiICsgSDE2JCkgKyBcIj9cXFxcOlxcXFw6XCIgKyBIMTYkICsgXCJcXFxcOlwiICsgTFMzMiQpLFxuICAgICAgICAvL1sgKjMoIGgxNiBcIjpcIiApIGgxNiBdIFwiOjpcIiAgICBoMTYgXCI6XCIgICBsczMyXG4gICAgSVBWNkFERFJFU1M3JCA9IHN1YmV4cChzdWJleHAoc3ViZXhwKEgxNiQgKyBcIlxcXFw6XCIpICsgXCJ7MCw0fVwiICsgSDE2JCkgKyBcIj9cXFxcOlxcXFw6XCIgKyBMUzMyJCksXG4gICAgICAgIC8vWyAqNCggaDE2IFwiOlwiICkgaDE2IF0gXCI6OlwiICAgICAgICAgICAgICBsczMyXG4gICAgSVBWNkFERFJFU1M4JCA9IHN1YmV4cChzdWJleHAoc3ViZXhwKEgxNiQgKyBcIlxcXFw6XCIpICsgXCJ7MCw1fVwiICsgSDE2JCkgKyBcIj9cXFxcOlxcXFw6XCIgKyBIMTYkKSxcbiAgICAgICAgLy9bICo1KCBoMTYgXCI6XCIgKSBoMTYgXSBcIjo6XCIgICAgICAgICAgICAgIGgxNlxuICAgIElQVjZBRERSRVNTOSQgPSBzdWJleHAoc3ViZXhwKHN1YmV4cChIMTYkICsgXCJcXFxcOlwiKSArIFwiezAsNn1cIiArIEgxNiQpICsgXCI/XFxcXDpcXFxcOlwiKSxcbiAgICAgICAgLy9bICo2KCBoMTYgXCI6XCIgKSBoMTYgXSBcIjo6XCJcbiAgICBJUFY2QUREUkVTUyQgPSBzdWJleHAoW0lQVjZBRERSRVNTMSQsIElQVjZBRERSRVNTMiQsIElQVjZBRERSRVNTMyQsIElQVjZBRERSRVNTNCQsIElQVjZBRERSRVNTNSQsIElQVjZBRERSRVNTNiQsIElQVjZBRERSRVNTNyQsIElQVjZBRERSRVNTOCQsIElQVjZBRERSRVNTOSRdLmpvaW4oXCJ8XCIpKSxcbiAgICAgICAgWk9ORUlEJCA9IHN1YmV4cChzdWJleHAoVU5SRVNFUlZFRCQkICsgXCJ8XCIgKyBQQ1RfRU5DT0RFRCQpICsgXCIrXCIpLFxuICAgICAgICAvL1JGQyA2ODc0XG4gICAgSVBWNkFERFJaJCA9IHN1YmV4cChJUFY2QUREUkVTUyQgKyBcIlxcXFwlMjVcIiArIFpPTkVJRCQpLFxuICAgICAgICAvL1JGQyA2ODc0XG4gICAgSVBWNkFERFJaX1JFTEFYRUQkID0gc3ViZXhwKElQVjZBRERSRVNTJCArIHN1YmV4cChcIlxcXFwlMjV8XFxcXCUoPyFcIiArIEhFWERJRyQkICsgXCJ7Mn0pXCIpICsgWk9ORUlEJCksXG4gICAgICAgIC8vUkZDIDY4NzQsIHdpdGggcmVsYXhlZCBwYXJzaW5nIHJ1bGVzXG4gICAgSVBWRlVUVVJFJCA9IHN1YmV4cChcIlt2Vl1cIiArIEhFWERJRyQkICsgXCIrXFxcXC5cIiArIG1lcmdlKFVOUkVTRVJWRUQkJCwgU1VCX0RFTElNUyQkLCBcIltcXFxcOl1cIikgKyBcIitcIiksXG4gICAgICAgIElQX0xJVEVSQUwkID0gc3ViZXhwKFwiXFxcXFtcIiArIHN1YmV4cChJUFY2QUREUlpfUkVMQVhFRCQgKyBcInxcIiArIElQVjZBRERSRVNTJCArIFwifFwiICsgSVBWRlVUVVJFJCkgKyBcIlxcXFxdXCIpLFxuICAgICAgICAvL1JGQyA2ODc0XG4gICAgUkVHX05BTUUkID0gc3ViZXhwKHN1YmV4cChQQ1RfRU5DT0RFRCQgKyBcInxcIiArIG1lcmdlKFVOUkVTRVJWRUQkJCwgU1VCX0RFTElNUyQkKSkgKyBcIipcIiksXG4gICAgICAgIEhPU1QkID0gc3ViZXhwKElQX0xJVEVSQUwkICsgXCJ8XCIgKyBJUFY0QUREUkVTUyQgKyBcIig/IVwiICsgUkVHX05BTUUkICsgXCIpXCIgKyBcInxcIiArIFJFR19OQU1FJCksXG4gICAgICAgIFBPUlQkID0gc3ViZXhwKERJR0lUJCQgKyBcIipcIiksXG4gICAgICAgIEFVVEhPUklUWSQgPSBzdWJleHAoc3ViZXhwKFVTRVJJTkZPJCArIFwiQFwiKSArIFwiP1wiICsgSE9TVCQgKyBzdWJleHAoXCJcXFxcOlwiICsgUE9SVCQpICsgXCI/XCIpLFxuICAgICAgICBQQ0hBUiQgPSBzdWJleHAoUENUX0VOQ09ERUQkICsgXCJ8XCIgKyBtZXJnZShVTlJFU0VSVkVEJCQsIFNVQl9ERUxJTVMkJCwgXCJbXFxcXDpcXFxcQF1cIikpLFxuICAgICAgICBTRUdNRU5UJCA9IHN1YmV4cChQQ0hBUiQgKyBcIipcIiksXG4gICAgICAgIFNFR01FTlRfTlokID0gc3ViZXhwKFBDSEFSJCArIFwiK1wiKSxcbiAgICAgICAgU0VHTUVOVF9OWl9OQyQgPSBzdWJleHAoc3ViZXhwKFBDVF9FTkNPREVEJCArIFwifFwiICsgbWVyZ2UoVU5SRVNFUlZFRCQkLCBTVUJfREVMSU1TJCQsIFwiW1xcXFxAXVwiKSkgKyBcIitcIiksXG4gICAgICAgIFBBVEhfQUJFTVBUWSQgPSBzdWJleHAoc3ViZXhwKFwiXFxcXC9cIiArIFNFR01FTlQkKSArIFwiKlwiKSxcbiAgICAgICAgUEFUSF9BQlNPTFVURSQgPSBzdWJleHAoXCJcXFxcL1wiICsgc3ViZXhwKFNFR01FTlRfTlokICsgUEFUSF9BQkVNUFRZJCkgKyBcIj9cIiksXG4gICAgICAgIC8vc2ltcGxpZmllZFxuICAgIFBBVEhfTk9TQ0hFTUUkID0gc3ViZXhwKFNFR01FTlRfTlpfTkMkICsgUEFUSF9BQkVNUFRZJCksXG4gICAgICAgIC8vc2ltcGxpZmllZFxuICAgIFBBVEhfUk9PVExFU1MkID0gc3ViZXhwKFNFR01FTlRfTlokICsgUEFUSF9BQkVNUFRZJCksXG4gICAgICAgIC8vc2ltcGxpZmllZFxuICAgIFBBVEhfRU1QVFkkID0gXCIoPyFcIiArIFBDSEFSJCArIFwiKVwiLFxuICAgICAgICBQQVRIJCA9IHN1YmV4cChQQVRIX0FCRU1QVFkkICsgXCJ8XCIgKyBQQVRIX0FCU09MVVRFJCArIFwifFwiICsgUEFUSF9OT1NDSEVNRSQgKyBcInxcIiArIFBBVEhfUk9PVExFU1MkICsgXCJ8XCIgKyBQQVRIX0VNUFRZJCksXG4gICAgICAgIFFVRVJZJCA9IHN1YmV4cChzdWJleHAoUENIQVIkICsgXCJ8XCIgKyBtZXJnZShcIltcXFxcL1xcXFw/XVwiLCBJUFJJVkFURSQkKSkgKyBcIipcIiksXG4gICAgICAgIEZSQUdNRU5UJCA9IHN1YmV4cChzdWJleHAoUENIQVIkICsgXCJ8W1xcXFwvXFxcXD9dXCIpICsgXCIqXCIpLFxuICAgICAgICBISUVSX1BBUlQkID0gc3ViZXhwKHN1YmV4cChcIlxcXFwvXFxcXC9cIiArIEFVVEhPUklUWSQgKyBQQVRIX0FCRU1QVFkkKSArIFwifFwiICsgUEFUSF9BQlNPTFVURSQgKyBcInxcIiArIFBBVEhfUk9PVExFU1MkICsgXCJ8XCIgKyBQQVRIX0VNUFRZJCksXG4gICAgICAgIFVSSSQgPSBzdWJleHAoU0NIRU1FJCArIFwiXFxcXDpcIiArIEhJRVJfUEFSVCQgKyBzdWJleHAoXCJcXFxcP1wiICsgUVVFUlkkKSArIFwiP1wiICsgc3ViZXhwKFwiXFxcXCNcIiArIEZSQUdNRU5UJCkgKyBcIj9cIiksXG4gICAgICAgIFJFTEFUSVZFX1BBUlQkID0gc3ViZXhwKHN1YmV4cChcIlxcXFwvXFxcXC9cIiArIEFVVEhPUklUWSQgKyBQQVRIX0FCRU1QVFkkKSArIFwifFwiICsgUEFUSF9BQlNPTFVURSQgKyBcInxcIiArIFBBVEhfTk9TQ0hFTUUkICsgXCJ8XCIgKyBQQVRIX0VNUFRZJCksXG4gICAgICAgIFJFTEFUSVZFJCA9IHN1YmV4cChSRUxBVElWRV9QQVJUJCArIHN1YmV4cChcIlxcXFw/XCIgKyBRVUVSWSQpICsgXCI/XCIgKyBzdWJleHAoXCJcXFxcI1wiICsgRlJBR01FTlQkKSArIFwiP1wiKSxcbiAgICAgICAgVVJJX1JFRkVSRU5DRSQgPSBzdWJleHAoVVJJJCArIFwifFwiICsgUkVMQVRJVkUkKSxcbiAgICAgICAgQUJTT0xVVEVfVVJJJCA9IHN1YmV4cChTQ0hFTUUkICsgXCJcXFxcOlwiICsgSElFUl9QQVJUJCArIHN1YmV4cChcIlxcXFw/XCIgKyBRVUVSWSQpICsgXCI/XCIpLFxuICAgICAgICBHRU5FUklDX1JFRiQgPSBcIl4oXCIgKyBTQ0hFTUUkICsgXCIpXFxcXDpcIiArIHN1YmV4cChzdWJleHAoXCJcXFxcL1xcXFwvKFwiICsgc3ViZXhwKFwiKFwiICsgVVNFUklORk8kICsgXCIpQFwiKSArIFwiPyhcIiArIEhPU1QkICsgXCIpXCIgKyBzdWJleHAoXCJcXFxcOihcIiArIFBPUlQkICsgXCIpXCIpICsgXCI/KVwiKSArIFwiPyhcIiArIFBBVEhfQUJFTVBUWSQgKyBcInxcIiArIFBBVEhfQUJTT0xVVEUkICsgXCJ8XCIgKyBQQVRIX1JPT1RMRVNTJCArIFwifFwiICsgUEFUSF9FTVBUWSQgKyBcIilcIikgKyBzdWJleHAoXCJcXFxcPyhcIiArIFFVRVJZJCArIFwiKVwiKSArIFwiP1wiICsgc3ViZXhwKFwiXFxcXCMoXCIgKyBGUkFHTUVOVCQgKyBcIilcIikgKyBcIj8kXCIsXG4gICAgICAgIFJFTEFUSVZFX1JFRiQgPSBcIl4oKXswfVwiICsgc3ViZXhwKHN1YmV4cChcIlxcXFwvXFxcXC8oXCIgKyBzdWJleHAoXCIoXCIgKyBVU0VSSU5GTyQgKyBcIilAXCIpICsgXCI/KFwiICsgSE9TVCQgKyBcIilcIiArIHN1YmV4cChcIlxcXFw6KFwiICsgUE9SVCQgKyBcIilcIikgKyBcIj8pXCIpICsgXCI/KFwiICsgUEFUSF9BQkVNUFRZJCArIFwifFwiICsgUEFUSF9BQlNPTFVURSQgKyBcInxcIiArIFBBVEhfTk9TQ0hFTUUkICsgXCJ8XCIgKyBQQVRIX0VNUFRZJCArIFwiKVwiKSArIHN1YmV4cChcIlxcXFw/KFwiICsgUVVFUlkkICsgXCIpXCIpICsgXCI/XCIgKyBzdWJleHAoXCJcXFxcIyhcIiArIEZSQUdNRU5UJCArIFwiKVwiKSArIFwiPyRcIixcbiAgICAgICAgQUJTT0xVVEVfUkVGJCA9IFwiXihcIiArIFNDSEVNRSQgKyBcIilcXFxcOlwiICsgc3ViZXhwKHN1YmV4cChcIlxcXFwvXFxcXC8oXCIgKyBzdWJleHAoXCIoXCIgKyBVU0VSSU5GTyQgKyBcIilAXCIpICsgXCI/KFwiICsgSE9TVCQgKyBcIilcIiArIHN1YmV4cChcIlxcXFw6KFwiICsgUE9SVCQgKyBcIilcIikgKyBcIj8pXCIpICsgXCI/KFwiICsgUEFUSF9BQkVNUFRZJCArIFwifFwiICsgUEFUSF9BQlNPTFVURSQgKyBcInxcIiArIFBBVEhfUk9PVExFU1MkICsgXCJ8XCIgKyBQQVRIX0VNUFRZJCArIFwiKVwiKSArIHN1YmV4cChcIlxcXFw/KFwiICsgUVVFUlkkICsgXCIpXCIpICsgXCI/JFwiLFxuICAgICAgICBTQU1FRE9DX1JFRiQgPSBcIl5cIiArIHN1YmV4cChcIlxcXFwjKFwiICsgRlJBR01FTlQkICsgXCIpXCIpICsgXCI/JFwiLFxuICAgICAgICBBVVRIT1JJVFlfUkVGJCA9IFwiXlwiICsgc3ViZXhwKFwiKFwiICsgVVNFUklORk8kICsgXCIpQFwiKSArIFwiPyhcIiArIEhPU1QkICsgXCIpXCIgKyBzdWJleHAoXCJcXFxcOihcIiArIFBPUlQkICsgXCIpXCIpICsgXCI/JFwiO1xuICAgIHJldHVybiB7XG4gICAgICAgIE5PVF9TQ0hFTUU6IG5ldyBSZWdFeHAobWVyZ2UoXCJbXl1cIiwgQUxQSEEkJCwgRElHSVQkJCwgXCJbXFxcXCtcXFxcLVxcXFwuXVwiKSwgXCJnXCIpLFxuICAgICAgICBOT1RfVVNFUklORk86IG5ldyBSZWdFeHAobWVyZ2UoXCJbXlxcXFwlXFxcXDpdXCIsIFVOUkVTRVJWRUQkJCwgU1VCX0RFTElNUyQkKSwgXCJnXCIpLFxuICAgICAgICBOT1RfSE9TVDogbmV3IFJlZ0V4cChtZXJnZShcIlteXFxcXCVcXFxcW1xcXFxdXFxcXDpdXCIsIFVOUkVTRVJWRUQkJCwgU1VCX0RFTElNUyQkKSwgXCJnXCIpLFxuICAgICAgICBOT1RfUEFUSDogbmV3IFJlZ0V4cChtZXJnZShcIlteXFxcXCVcXFxcL1xcXFw6XFxcXEBdXCIsIFVOUkVTRVJWRUQkJCwgU1VCX0RFTElNUyQkKSwgXCJnXCIpLFxuICAgICAgICBOT1RfUEFUSF9OT1NDSEVNRTogbmV3IFJlZ0V4cChtZXJnZShcIlteXFxcXCVcXFxcL1xcXFxAXVwiLCBVTlJFU0VSVkVEJCQsIFNVQl9ERUxJTVMkJCksIFwiZ1wiKSxcbiAgICAgICAgTk9UX1FVRVJZOiBuZXcgUmVnRXhwKG1lcmdlKFwiW15cXFxcJV1cIiwgVU5SRVNFUlZFRCQkLCBTVUJfREVMSU1TJCQsIFwiW1xcXFw6XFxcXEBcXFxcL1xcXFw/XVwiLCBJUFJJVkFURSQkKSwgXCJnXCIpLFxuICAgICAgICBOT1RfRlJBR01FTlQ6IG5ldyBSZWdFeHAobWVyZ2UoXCJbXlxcXFwlXVwiLCBVTlJFU0VSVkVEJCQsIFNVQl9ERUxJTVMkJCwgXCJbXFxcXDpcXFxcQFxcXFwvXFxcXD9dXCIpLCBcImdcIiksXG4gICAgICAgIEVTQ0FQRTogbmV3IFJlZ0V4cChtZXJnZShcIlteXVwiLCBVTlJFU0VSVkVEJCQsIFNVQl9ERUxJTVMkJCksIFwiZ1wiKSxcbiAgICAgICAgVU5SRVNFUlZFRDogbmV3IFJlZ0V4cChVTlJFU0VSVkVEJCQsIFwiZ1wiKSxcbiAgICAgICAgT1RIRVJfQ0hBUlM6IG5ldyBSZWdFeHAobWVyZ2UoXCJbXlxcXFwlXVwiLCBVTlJFU0VSVkVEJCQsIFJFU0VSVkVEJCQpLCBcImdcIiksXG4gICAgICAgIFBDVF9FTkNPREVEOiBuZXcgUmVnRXhwKFBDVF9FTkNPREVEJCwgXCJnXCIpLFxuICAgICAgICBJUFY0QUREUkVTUzogbmV3IFJlZ0V4cChcIl4oXCIgKyBJUFY0QUREUkVTUyQgKyBcIikkXCIpLFxuICAgICAgICBJUFY2QUREUkVTUzogbmV3IFJlZ0V4cChcIl5cXFxcWz8oXCIgKyBJUFY2QUREUkVTUyQgKyBcIilcIiArIHN1YmV4cChzdWJleHAoXCJcXFxcJTI1fFxcXFwlKD8hXCIgKyBIRVhESUckJCArIFwiezJ9KVwiKSArIFwiKFwiICsgWk9ORUlEJCArIFwiKVwiKSArIFwiP1xcXFxdPyRcIikgLy9SRkMgNjg3NCwgd2l0aCByZWxheGVkIHBhcnNpbmcgcnVsZXNcbiAgICB9O1xufVxudmFyIFVSSV9QUk9UT0NPTCA9IGJ1aWxkRXhwcyhmYWxzZSk7XG5cbnZhciBJUklfUFJPVE9DT0wgPSBidWlsZEV4cHModHJ1ZSk7XG5cbnZhciBzbGljZWRUb0FycmF5ID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBzbGljZUl0ZXJhdG9yKGFyciwgaSkge1xuICAgIHZhciBfYXJyID0gW107XG4gICAgdmFyIF9uID0gdHJ1ZTtcbiAgICB2YXIgX2QgPSBmYWxzZTtcbiAgICB2YXIgX2UgPSB1bmRlZmluZWQ7XG5cbiAgICB0cnkge1xuICAgICAgZm9yICh2YXIgX2kgPSBhcnJbU3ltYm9sLml0ZXJhdG9yXSgpLCBfczsgIShfbiA9IChfcyA9IF9pLm5leHQoKSkuZG9uZSk7IF9uID0gdHJ1ZSkge1xuICAgICAgICBfYXJyLnB1c2goX3MudmFsdWUpO1xuXG4gICAgICAgIGlmIChpICYmIF9hcnIubGVuZ3RoID09PSBpKSBicmVhaztcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIF9kID0gdHJ1ZTtcbiAgICAgIF9lID0gZXJyO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoIV9uICYmIF9pW1wicmV0dXJuXCJdKSBfaVtcInJldHVyblwiXSgpO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgaWYgKF9kKSB0aHJvdyBfZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX2FycjtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAoYXJyLCBpKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkge1xuICAgICAgcmV0dXJuIGFycjtcbiAgICB9IGVsc2UgaWYgKFN5bWJvbC5pdGVyYXRvciBpbiBPYmplY3QoYXJyKSkge1xuICAgICAgcmV0dXJuIHNsaWNlSXRlcmF0b3IoYXJyLCBpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgYXR0ZW1wdCB0byBkZXN0cnVjdHVyZSBub24taXRlcmFibGUgaW5zdGFuY2VcIik7XG4gICAgfVxuICB9O1xufSgpO1xuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG52YXIgdG9Db25zdW1hYmxlQXJyYXkgPSBmdW5jdGlvbiAoYXJyKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGFycikpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgYXJyMiA9IEFycmF5KGFyci5sZW5ndGgpOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBhcnIyW2ldID0gYXJyW2ldO1xuXG4gICAgcmV0dXJuIGFycjI7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEFycmF5LmZyb20oYXJyKTtcbiAgfVxufTtcblxuLyoqIEhpZ2hlc3QgcG9zaXRpdmUgc2lnbmVkIDMyLWJpdCBmbG9hdCB2YWx1ZSAqL1xuXG52YXIgbWF4SW50ID0gMjE0NzQ4MzY0NzsgLy8gYWthLiAweDdGRkZGRkZGIG9yIDJeMzEtMVxuXG4vKiogQm9vdHN0cmluZyBwYXJhbWV0ZXJzICovXG52YXIgYmFzZSA9IDM2O1xudmFyIHRNaW4gPSAxO1xudmFyIHRNYXggPSAyNjtcbnZhciBza2V3ID0gMzg7XG52YXIgZGFtcCA9IDcwMDtcbnZhciBpbml0aWFsQmlhcyA9IDcyO1xudmFyIGluaXRpYWxOID0gMTI4OyAvLyAweDgwXG52YXIgZGVsaW1pdGVyID0gJy0nOyAvLyAnXFx4MkQnXG5cbi8qKiBSZWd1bGFyIGV4cHJlc3Npb25zICovXG52YXIgcmVnZXhQdW55Y29kZSA9IC9eeG4tLS87XG52YXIgcmVnZXhOb25BU0NJSSA9IC9bXlxcMC1cXHg3RV0vOyAvLyBub24tQVNDSUkgY2hhcnNcbnZhciByZWdleFNlcGFyYXRvcnMgPSAvW1xceDJFXFx1MzAwMlxcdUZGMEVcXHVGRjYxXS9nOyAvLyBSRkMgMzQ5MCBzZXBhcmF0b3JzXG5cbi8qKiBFcnJvciBtZXNzYWdlcyAqL1xudmFyIGVycm9ycyA9IHtcblx0J292ZXJmbG93JzogJ092ZXJmbG93OiBpbnB1dCBuZWVkcyB3aWRlciBpbnRlZ2VycyB0byBwcm9jZXNzJyxcblx0J25vdC1iYXNpYyc6ICdJbGxlZ2FsIGlucHV0ID49IDB4ODAgKG5vdCBhIGJhc2ljIGNvZGUgcG9pbnQpJyxcblx0J2ludmFsaWQtaW5wdXQnOiAnSW52YWxpZCBpbnB1dCdcbn07XG5cbi8qKiBDb252ZW5pZW5jZSBzaG9ydGN1dHMgKi9cbnZhciBiYXNlTWludXNUTWluID0gYmFzZSAtIHRNaW47XG52YXIgZmxvb3IgPSBNYXRoLmZsb29yO1xudmFyIHN0cmluZ0Zyb21DaGFyQ29kZSA9IFN0cmluZy5mcm9tQ2hhckNvZGU7XG5cbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4vKipcbiAqIEEgZ2VuZXJpYyBlcnJvciB1dGlsaXR5IGZ1bmN0aW9uLlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlIFRoZSBlcnJvciB0eXBlLlxuICogQHJldHVybnMge0Vycm9yfSBUaHJvd3MgYSBgUmFuZ2VFcnJvcmAgd2l0aCB0aGUgYXBwbGljYWJsZSBlcnJvciBtZXNzYWdlLlxuICovXG5mdW5jdGlvbiBlcnJvciQxKHR5cGUpIHtcblx0dGhyb3cgbmV3IFJhbmdlRXJyb3IoZXJyb3JzW3R5cGVdKTtcbn1cblxuLyoqXG4gKiBBIGdlbmVyaWMgYEFycmF5I21hcGAgdXRpbGl0eSBmdW5jdGlvbi5cbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRoYXQgZ2V0cyBjYWxsZWQgZm9yIGV2ZXJ5IGFycmF5XG4gKiBpdGVtLlxuICogQHJldHVybnMge0FycmF5fSBBIG5ldyBhcnJheSBvZiB2YWx1ZXMgcmV0dXJuZWQgYnkgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiBtYXAoYXJyYXksIGZuKSB7XG5cdHZhciByZXN1bHQgPSBbXTtcblx0dmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblx0d2hpbGUgKGxlbmd0aC0tKSB7XG5cdFx0cmVzdWx0W2xlbmd0aF0gPSBmbihhcnJheVtsZW5ndGhdKTtcblx0fVxuXHRyZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIEEgc2ltcGxlIGBBcnJheSNtYXBgLWxpa2Ugd3JhcHBlciB0byB3b3JrIHdpdGggZG9tYWluIG5hbWUgc3RyaW5ncyBvciBlbWFpbFxuICogYWRkcmVzc2VzLlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7U3RyaW5nfSBkb21haW4gVGhlIGRvbWFpbiBuYW1lIG9yIGVtYWlsIGFkZHJlc3MuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdGhhdCBnZXRzIGNhbGxlZCBmb3IgZXZlcnlcbiAqIGNoYXJhY3Rlci5cbiAqIEByZXR1cm5zIHtBcnJheX0gQSBuZXcgc3RyaW5nIG9mIGNoYXJhY3RlcnMgcmV0dXJuZWQgYnkgdGhlIGNhbGxiYWNrXG4gKiBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gbWFwRG9tYWluKHN0cmluZywgZm4pIHtcblx0dmFyIHBhcnRzID0gc3RyaW5nLnNwbGl0KCdAJyk7XG5cdHZhciByZXN1bHQgPSAnJztcblx0aWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcblx0XHQvLyBJbiBlbWFpbCBhZGRyZXNzZXMsIG9ubHkgdGhlIGRvbWFpbiBuYW1lIHNob3VsZCBiZSBwdW55Y29kZWQuIExlYXZlXG5cdFx0Ly8gdGhlIGxvY2FsIHBhcnQgKGkuZS4gZXZlcnl0aGluZyB1cCB0byBgQGApIGludGFjdC5cblx0XHRyZXN1bHQgPSBwYXJ0c1swXSArICdAJztcblx0XHRzdHJpbmcgPSBwYXJ0c1sxXTtcblx0fVxuXHQvLyBBdm9pZCBgc3BsaXQocmVnZXgpYCBmb3IgSUU4IGNvbXBhdGliaWxpdHkuIFNlZSAjMTcuXG5cdHN0cmluZyA9IHN0cmluZy5yZXBsYWNlKHJlZ2V4U2VwYXJhdG9ycywgJ1xceDJFJyk7XG5cdHZhciBsYWJlbHMgPSBzdHJpbmcuc3BsaXQoJy4nKTtcblx0dmFyIGVuY29kZWQgPSBtYXAobGFiZWxzLCBmbikuam9pbignLicpO1xuXHRyZXR1cm4gcmVzdWx0ICsgZW5jb2RlZDtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIG51bWVyaWMgY29kZSBwb2ludHMgb2YgZWFjaCBVbmljb2RlXG4gKiBjaGFyYWN0ZXIgaW4gdGhlIHN0cmluZy4gV2hpbGUgSmF2YVNjcmlwdCB1c2VzIFVDUy0yIGludGVybmFsbHksXG4gKiB0aGlzIGZ1bmN0aW9uIHdpbGwgY29udmVydCBhIHBhaXIgb2Ygc3Vycm9nYXRlIGhhbHZlcyAoZWFjaCBvZiB3aGljaFxuICogVUNTLTIgZXhwb3NlcyBhcyBzZXBhcmF0ZSBjaGFyYWN0ZXJzKSBpbnRvIGEgc2luZ2xlIGNvZGUgcG9pbnQsXG4gKiBtYXRjaGluZyBVVEYtMTYuXG4gKiBAc2VlIGBwdW55Y29kZS51Y3MyLmVuY29kZWBcbiAqIEBzZWUgPGh0dHBzOi8vbWF0aGlhc2J5bmVucy5iZS9ub3Rlcy9qYXZhc2NyaXB0LWVuY29kaW5nPlxuICogQG1lbWJlck9mIHB1bnljb2RlLnVjczJcbiAqIEBuYW1lIGRlY29kZVxuICogQHBhcmFtIHtTdHJpbmd9IHN0cmluZyBUaGUgVW5pY29kZSBpbnB1dCBzdHJpbmcgKFVDUy0yKS5cbiAqIEByZXR1cm5zIHtBcnJheX0gVGhlIG5ldyBhcnJheSBvZiBjb2RlIHBvaW50cy5cbiAqL1xuZnVuY3Rpb24gdWNzMmRlY29kZShzdHJpbmcpIHtcblx0dmFyIG91dHB1dCA9IFtdO1xuXHR2YXIgY291bnRlciA9IDA7XG5cdHZhciBsZW5ndGggPSBzdHJpbmcubGVuZ3RoO1xuXHR3aGlsZSAoY291bnRlciA8IGxlbmd0aCkge1xuXHRcdHZhciB2YWx1ZSA9IHN0cmluZy5jaGFyQ29kZUF0KGNvdW50ZXIrKyk7XG5cdFx0aWYgKHZhbHVlID49IDB4RDgwMCAmJiB2YWx1ZSA8PSAweERCRkYgJiYgY291bnRlciA8IGxlbmd0aCkge1xuXHRcdFx0Ly8gSXQncyBhIGhpZ2ggc3Vycm9nYXRlLCBhbmQgdGhlcmUgaXMgYSBuZXh0IGNoYXJhY3Rlci5cblx0XHRcdHZhciBleHRyYSA9IHN0cmluZy5jaGFyQ29kZUF0KGNvdW50ZXIrKyk7XG5cdFx0XHRpZiAoKGV4dHJhICYgMHhGQzAwKSA9PSAweERDMDApIHtcblx0XHRcdFx0Ly8gTG93IHN1cnJvZ2F0ZS5cblx0XHRcdFx0b3V0cHV0LnB1c2goKCh2YWx1ZSAmIDB4M0ZGKSA8PCAxMCkgKyAoZXh0cmEgJiAweDNGRikgKyAweDEwMDAwKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIEl0J3MgYW4gdW5tYXRjaGVkIHN1cnJvZ2F0ZTsgb25seSBhcHBlbmQgdGhpcyBjb2RlIHVuaXQsIGluIGNhc2UgdGhlXG5cdFx0XHRcdC8vIG5leHQgY29kZSB1bml0IGlzIHRoZSBoaWdoIHN1cnJvZ2F0ZSBvZiBhIHN1cnJvZ2F0ZSBwYWlyLlxuXHRcdFx0XHRvdXRwdXQucHVzaCh2YWx1ZSk7XG5cdFx0XHRcdGNvdW50ZXItLTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0b3V0cHV0LnB1c2godmFsdWUpO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gb3V0cHV0O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBzdHJpbmcgYmFzZWQgb24gYW4gYXJyYXkgb2YgbnVtZXJpYyBjb2RlIHBvaW50cy5cbiAqIEBzZWUgYHB1bnljb2RlLnVjczIuZGVjb2RlYFxuICogQG1lbWJlck9mIHB1bnljb2RlLnVjczJcbiAqIEBuYW1lIGVuY29kZVxuICogQHBhcmFtIHtBcnJheX0gY29kZVBvaW50cyBUaGUgYXJyYXkgb2YgbnVtZXJpYyBjb2RlIHBvaW50cy5cbiAqIEByZXR1cm5zIHtTdHJpbmd9IFRoZSBuZXcgVW5pY29kZSBzdHJpbmcgKFVDUy0yKS5cbiAqL1xudmFyIHVjczJlbmNvZGUgPSBmdW5jdGlvbiB1Y3MyZW5jb2RlKGFycmF5KSB7XG5cdHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludC5hcHBseShTdHJpbmcsIHRvQ29uc3VtYWJsZUFycmF5KGFycmF5KSk7XG59O1xuXG4vKipcbiAqIENvbnZlcnRzIGEgYmFzaWMgY29kZSBwb2ludCBpbnRvIGEgZGlnaXQvaW50ZWdlci5cbiAqIEBzZWUgYGRpZ2l0VG9CYXNpYygpYFxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBjb2RlUG9pbnQgVGhlIGJhc2ljIG51bWVyaWMgY29kZSBwb2ludCB2YWx1ZS5cbiAqIEByZXR1cm5zIHtOdW1iZXJ9IFRoZSBudW1lcmljIHZhbHVlIG9mIGEgYmFzaWMgY29kZSBwb2ludCAoZm9yIHVzZSBpblxuICogcmVwcmVzZW50aW5nIGludGVnZXJzKSBpbiB0aGUgcmFuZ2UgYDBgIHRvIGBiYXNlIC0gMWAsIG9yIGBiYXNlYCBpZlxuICogdGhlIGNvZGUgcG9pbnQgZG9lcyBub3QgcmVwcmVzZW50IGEgdmFsdWUuXG4gKi9cbnZhciBiYXNpY1RvRGlnaXQgPSBmdW5jdGlvbiBiYXNpY1RvRGlnaXQoY29kZVBvaW50KSB7XG5cdGlmIChjb2RlUG9pbnQgLSAweDMwIDwgMHgwQSkge1xuXHRcdHJldHVybiBjb2RlUG9pbnQgLSAweDE2O1xuXHR9XG5cdGlmIChjb2RlUG9pbnQgLSAweDQxIDwgMHgxQSkge1xuXHRcdHJldHVybiBjb2RlUG9pbnQgLSAweDQxO1xuXHR9XG5cdGlmIChjb2RlUG9pbnQgLSAweDYxIDwgMHgxQSkge1xuXHRcdHJldHVybiBjb2RlUG9pbnQgLSAweDYxO1xuXHR9XG5cdHJldHVybiBiYXNlO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0cyBhIGRpZ2l0L2ludGVnZXIgaW50byBhIGJhc2ljIGNvZGUgcG9pbnQuXG4gKiBAc2VlIGBiYXNpY1RvRGlnaXQoKWBcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gZGlnaXQgVGhlIG51bWVyaWMgdmFsdWUgb2YgYSBiYXNpYyBjb2RlIHBvaW50LlxuICogQHJldHVybnMge051bWJlcn0gVGhlIGJhc2ljIGNvZGUgcG9pbnQgd2hvc2UgdmFsdWUgKHdoZW4gdXNlZCBmb3JcbiAqIHJlcHJlc2VudGluZyBpbnRlZ2VycykgaXMgYGRpZ2l0YCwgd2hpY2ggbmVlZHMgdG8gYmUgaW4gdGhlIHJhbmdlXG4gKiBgMGAgdG8gYGJhc2UgLSAxYC4gSWYgYGZsYWdgIGlzIG5vbi16ZXJvLCB0aGUgdXBwZXJjYXNlIGZvcm0gaXNcbiAqIHVzZWQ7IGVsc2UsIHRoZSBsb3dlcmNhc2UgZm9ybSBpcyB1c2VkLiBUaGUgYmVoYXZpb3IgaXMgdW5kZWZpbmVkXG4gKiBpZiBgZmxhZ2AgaXMgbm9uLXplcm8gYW5kIGBkaWdpdGAgaGFzIG5vIHVwcGVyY2FzZSBmb3JtLlxuICovXG52YXIgZGlnaXRUb0Jhc2ljID0gZnVuY3Rpb24gZGlnaXRUb0Jhc2ljKGRpZ2l0LCBmbGFnKSB7XG5cdC8vICAwLi4yNSBtYXAgdG8gQVNDSUkgYS4ueiBvciBBLi5aXG5cdC8vIDI2Li4zNSBtYXAgdG8gQVNDSUkgMC4uOVxuXHRyZXR1cm4gZGlnaXQgKyAyMiArIDc1ICogKGRpZ2l0IDwgMjYpIC0gKChmbGFnICE9IDApIDw8IDUpO1xufTtcblxuLyoqXG4gKiBCaWFzIGFkYXB0YXRpb24gZnVuY3Rpb24gYXMgcGVyIHNlY3Rpb24gMy40IG9mIFJGQyAzNDkyLlxuICogaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzM0OTIjc2VjdGlvbi0zLjRcbiAqIEBwcml2YXRlXG4gKi9cbnZhciBhZGFwdCA9IGZ1bmN0aW9uIGFkYXB0KGRlbHRhLCBudW1Qb2ludHMsIGZpcnN0VGltZSkge1xuXHR2YXIgayA9IDA7XG5cdGRlbHRhID0gZmlyc3RUaW1lID8gZmxvb3IoZGVsdGEgLyBkYW1wKSA6IGRlbHRhID4+IDE7XG5cdGRlbHRhICs9IGZsb29yKGRlbHRhIC8gbnVtUG9pbnRzKTtcblx0Zm9yICg7IC8qIG5vIGluaXRpYWxpemF0aW9uICovZGVsdGEgPiBiYXNlTWludXNUTWluICogdE1heCA+PiAxOyBrICs9IGJhc2UpIHtcblx0XHRkZWx0YSA9IGZsb29yKGRlbHRhIC8gYmFzZU1pbnVzVE1pbik7XG5cdH1cblx0cmV0dXJuIGZsb29yKGsgKyAoYmFzZU1pbnVzVE1pbiArIDEpICogZGVsdGEgLyAoZGVsdGEgKyBza2V3KSk7XG59O1xuXG4vKipcbiAqIENvbnZlcnRzIGEgUHVueWNvZGUgc3RyaW5nIG9mIEFTQ0lJLW9ubHkgc3ltYm9scyB0byBhIHN0cmluZyBvZiBVbmljb2RlXG4gKiBzeW1ib2xzLlxuICogQG1lbWJlck9mIHB1bnljb2RlXG4gKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgVGhlIFB1bnljb2RlIHN0cmluZyBvZiBBU0NJSS1vbmx5IHN5bWJvbHMuXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgcmVzdWx0aW5nIHN0cmluZyBvZiBVbmljb2RlIHN5bWJvbHMuXG4gKi9cbnZhciBkZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUoaW5wdXQpIHtcblx0Ly8gRG9uJ3QgdXNlIFVDUy0yLlxuXHR2YXIgb3V0cHV0ID0gW107XG5cdHZhciBpbnB1dExlbmd0aCA9IGlucHV0Lmxlbmd0aDtcblx0dmFyIGkgPSAwO1xuXHR2YXIgbiA9IGluaXRpYWxOO1xuXHR2YXIgYmlhcyA9IGluaXRpYWxCaWFzO1xuXG5cdC8vIEhhbmRsZSB0aGUgYmFzaWMgY29kZSBwb2ludHM6IGxldCBgYmFzaWNgIGJlIHRoZSBudW1iZXIgb2YgaW5wdXQgY29kZVxuXHQvLyBwb2ludHMgYmVmb3JlIHRoZSBsYXN0IGRlbGltaXRlciwgb3IgYDBgIGlmIHRoZXJlIGlzIG5vbmUsIHRoZW4gY29weVxuXHQvLyB0aGUgZmlyc3QgYmFzaWMgY29kZSBwb2ludHMgdG8gdGhlIG91dHB1dC5cblxuXHR2YXIgYmFzaWMgPSBpbnB1dC5sYXN0SW5kZXhPZihkZWxpbWl0ZXIpO1xuXHRpZiAoYmFzaWMgPCAwKSB7XG5cdFx0YmFzaWMgPSAwO1xuXHR9XG5cblx0Zm9yICh2YXIgaiA9IDA7IGogPCBiYXNpYzsgKytqKSB7XG5cdFx0Ly8gaWYgaXQncyBub3QgYSBiYXNpYyBjb2RlIHBvaW50XG5cdFx0aWYgKGlucHV0LmNoYXJDb2RlQXQoaikgPj0gMHg4MCkge1xuXHRcdFx0ZXJyb3IkMSgnbm90LWJhc2ljJyk7XG5cdFx0fVxuXHRcdG91dHB1dC5wdXNoKGlucHV0LmNoYXJDb2RlQXQoaikpO1xuXHR9XG5cblx0Ly8gTWFpbiBkZWNvZGluZyBsb29wOiBzdGFydCBqdXN0IGFmdGVyIHRoZSBsYXN0IGRlbGltaXRlciBpZiBhbnkgYmFzaWMgY29kZVxuXHQvLyBwb2ludHMgd2VyZSBjb3BpZWQ7IHN0YXJ0IGF0IHRoZSBiZWdpbm5pbmcgb3RoZXJ3aXNlLlxuXG5cdGZvciAodmFyIGluZGV4ID0gYmFzaWMgPiAwID8gYmFzaWMgKyAxIDogMDsgaW5kZXggPCBpbnB1dExlbmd0aDspIC8qIG5vIGZpbmFsIGV4cHJlc3Npb24gKi97XG5cblx0XHQvLyBgaW5kZXhgIGlzIHRoZSBpbmRleCBvZiB0aGUgbmV4dCBjaGFyYWN0ZXIgdG8gYmUgY29uc3VtZWQuXG5cdFx0Ly8gRGVjb2RlIGEgZ2VuZXJhbGl6ZWQgdmFyaWFibGUtbGVuZ3RoIGludGVnZXIgaW50byBgZGVsdGFgLFxuXHRcdC8vIHdoaWNoIGdldHMgYWRkZWQgdG8gYGlgLiBUaGUgb3ZlcmZsb3cgY2hlY2tpbmcgaXMgZWFzaWVyXG5cdFx0Ly8gaWYgd2UgaW5jcmVhc2UgYGlgIGFzIHdlIGdvLCB0aGVuIHN1YnRyYWN0IG9mZiBpdHMgc3RhcnRpbmdcblx0XHQvLyB2YWx1ZSBhdCB0aGUgZW5kIHRvIG9idGFpbiBgZGVsdGFgLlxuXHRcdHZhciBvbGRpID0gaTtcblx0XHRmb3IgKHZhciB3ID0gMSwgayA9IGJhc2U7OyAvKiBubyBjb25kaXRpb24gKi9rICs9IGJhc2UpIHtcblxuXHRcdFx0aWYgKGluZGV4ID49IGlucHV0TGVuZ3RoKSB7XG5cdFx0XHRcdGVycm9yJDEoJ2ludmFsaWQtaW5wdXQnKTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGRpZ2l0ID0gYmFzaWNUb0RpZ2l0KGlucHV0LmNoYXJDb2RlQXQoaW5kZXgrKykpO1xuXG5cdFx0XHRpZiAoZGlnaXQgPj0gYmFzZSB8fCBkaWdpdCA+IGZsb29yKChtYXhJbnQgLSBpKSAvIHcpKSB7XG5cdFx0XHRcdGVycm9yJDEoJ292ZXJmbG93Jyk7XG5cdFx0XHR9XG5cblx0XHRcdGkgKz0gZGlnaXQgKiB3O1xuXHRcdFx0dmFyIHQgPSBrIDw9IGJpYXMgPyB0TWluIDogayA+PSBiaWFzICsgdE1heCA/IHRNYXggOiBrIC0gYmlhcztcblxuXHRcdFx0aWYgKGRpZ2l0IDwgdCkge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0dmFyIGJhc2VNaW51c1QgPSBiYXNlIC0gdDtcblx0XHRcdGlmICh3ID4gZmxvb3IobWF4SW50IC8gYmFzZU1pbnVzVCkpIHtcblx0XHRcdFx0ZXJyb3IkMSgnb3ZlcmZsb3cnKTtcblx0XHRcdH1cblxuXHRcdFx0dyAqPSBiYXNlTWludXNUO1xuXHRcdH1cblxuXHRcdHZhciBvdXQgPSBvdXRwdXQubGVuZ3RoICsgMTtcblx0XHRiaWFzID0gYWRhcHQoaSAtIG9sZGksIG91dCwgb2xkaSA9PSAwKTtcblxuXHRcdC8vIGBpYCB3YXMgc3VwcG9zZWQgdG8gd3JhcCBhcm91bmQgZnJvbSBgb3V0YCB0byBgMGAsXG5cdFx0Ly8gaW5jcmVtZW50aW5nIGBuYCBlYWNoIHRpbWUsIHNvIHdlJ2xsIGZpeCB0aGF0IG5vdzpcblx0XHRpZiAoZmxvb3IoaSAvIG91dCkgPiBtYXhJbnQgLSBuKSB7XG5cdFx0XHRlcnJvciQxKCdvdmVyZmxvdycpO1xuXHRcdH1cblxuXHRcdG4gKz0gZmxvb3IoaSAvIG91dCk7XG5cdFx0aSAlPSBvdXQ7XG5cblx0XHQvLyBJbnNlcnQgYG5gIGF0IHBvc2l0aW9uIGBpYCBvZiB0aGUgb3V0cHV0LlxuXHRcdG91dHB1dC5zcGxpY2UoaSsrLCAwLCBuKTtcblx0fVxuXG5cdHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludC5hcHBseShTdHJpbmcsIG91dHB1dCk7XG59O1xuXG4vKipcbiAqIENvbnZlcnRzIGEgc3RyaW5nIG9mIFVuaWNvZGUgc3ltYm9scyAoZS5nLiBhIGRvbWFpbiBuYW1lIGxhYmVsKSB0byBhXG4gKiBQdW55Y29kZSBzdHJpbmcgb2YgQVNDSUktb25seSBzeW1ib2xzLlxuICogQG1lbWJlck9mIHB1bnljb2RlXG4gKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgVGhlIHN0cmluZyBvZiBVbmljb2RlIHN5bWJvbHMuXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgcmVzdWx0aW5nIFB1bnljb2RlIHN0cmluZyBvZiBBU0NJSS1vbmx5IHN5bWJvbHMuXG4gKi9cbnZhciBlbmNvZGUgPSBmdW5jdGlvbiBlbmNvZGUoaW5wdXQpIHtcblx0dmFyIG91dHB1dCA9IFtdO1xuXG5cdC8vIENvbnZlcnQgdGhlIGlucHV0IGluIFVDUy0yIHRvIGFuIGFycmF5IG9mIFVuaWNvZGUgY29kZSBwb2ludHMuXG5cdGlucHV0ID0gdWNzMmRlY29kZShpbnB1dCk7XG5cblx0Ly8gQ2FjaGUgdGhlIGxlbmd0aC5cblx0dmFyIGlucHV0TGVuZ3RoID0gaW5wdXQubGVuZ3RoO1xuXG5cdC8vIEluaXRpYWxpemUgdGhlIHN0YXRlLlxuXHR2YXIgbiA9IGluaXRpYWxOO1xuXHR2YXIgZGVsdGEgPSAwO1xuXHR2YXIgYmlhcyA9IGluaXRpYWxCaWFzO1xuXG5cdC8vIEhhbmRsZSB0aGUgYmFzaWMgY29kZSBwb2ludHMuXG5cdHZhciBfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uID0gdHJ1ZTtcblx0dmFyIF9kaWRJdGVyYXRvckVycm9yID0gZmFsc2U7XG5cdHZhciBfaXRlcmF0b3JFcnJvciA9IHVuZGVmaW5lZDtcblxuXHR0cnkge1xuXHRcdGZvciAodmFyIF9pdGVyYXRvciA9IGlucHV0W1N5bWJvbC5pdGVyYXRvcl0oKSwgX3N0ZXA7ICEoX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbiA9IChfc3RlcCA9IF9pdGVyYXRvci5uZXh0KCkpLmRvbmUpOyBfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uID0gdHJ1ZSkge1xuXHRcdFx0dmFyIF9jdXJyZW50VmFsdWUyID0gX3N0ZXAudmFsdWU7XG5cblx0XHRcdGlmIChfY3VycmVudFZhbHVlMiA8IDB4ODApIHtcblx0XHRcdFx0b3V0cHV0LnB1c2goc3RyaW5nRnJvbUNoYXJDb2RlKF9jdXJyZW50VmFsdWUyKSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9IGNhdGNoIChlcnIpIHtcblx0XHRfZGlkSXRlcmF0b3JFcnJvciA9IHRydWU7XG5cdFx0X2l0ZXJhdG9yRXJyb3IgPSBlcnI7XG5cdH0gZmluYWxseSB7XG5cdFx0dHJ5IHtcblx0XHRcdGlmICghX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbiAmJiBfaXRlcmF0b3IucmV0dXJuKSB7XG5cdFx0XHRcdF9pdGVyYXRvci5yZXR1cm4oKTtcblx0XHRcdH1cblx0XHR9IGZpbmFsbHkge1xuXHRcdFx0aWYgKF9kaWRJdGVyYXRvckVycm9yKSB7XG5cdFx0XHRcdHRocm93IF9pdGVyYXRvckVycm9yO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHZhciBiYXNpY0xlbmd0aCA9IG91dHB1dC5sZW5ndGg7XG5cdHZhciBoYW5kbGVkQ1BDb3VudCA9IGJhc2ljTGVuZ3RoO1xuXG5cdC8vIGBoYW5kbGVkQ1BDb3VudGAgaXMgdGhlIG51bWJlciBvZiBjb2RlIHBvaW50cyB0aGF0IGhhdmUgYmVlbiBoYW5kbGVkO1xuXHQvLyBgYmFzaWNMZW5ndGhgIGlzIHRoZSBudW1iZXIgb2YgYmFzaWMgY29kZSBwb2ludHMuXG5cblx0Ly8gRmluaXNoIHRoZSBiYXNpYyBzdHJpbmcgd2l0aCBhIGRlbGltaXRlciB1bmxlc3MgaXQncyBlbXB0eS5cblx0aWYgKGJhc2ljTGVuZ3RoKSB7XG5cdFx0b3V0cHV0LnB1c2goZGVsaW1pdGVyKTtcblx0fVxuXG5cdC8vIE1haW4gZW5jb2RpbmcgbG9vcDpcblx0d2hpbGUgKGhhbmRsZWRDUENvdW50IDwgaW5wdXRMZW5ndGgpIHtcblxuXHRcdC8vIEFsbCBub24tYmFzaWMgY29kZSBwb2ludHMgPCBuIGhhdmUgYmVlbiBoYW5kbGVkIGFscmVhZHkuIEZpbmQgdGhlIG5leHRcblx0XHQvLyBsYXJnZXIgb25lOlxuXHRcdHZhciBtID0gbWF4SW50O1xuXHRcdHZhciBfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uMiA9IHRydWU7XG5cdFx0dmFyIF9kaWRJdGVyYXRvckVycm9yMiA9IGZhbHNlO1xuXHRcdHZhciBfaXRlcmF0b3JFcnJvcjIgPSB1bmRlZmluZWQ7XG5cblx0XHR0cnkge1xuXHRcdFx0Zm9yICh2YXIgX2l0ZXJhdG9yMiA9IGlucHV0W1N5bWJvbC5pdGVyYXRvcl0oKSwgX3N0ZXAyOyAhKF9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24yID0gKF9zdGVwMiA9IF9pdGVyYXRvcjIubmV4dCgpKS5kb25lKTsgX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbjIgPSB0cnVlKSB7XG5cdFx0XHRcdHZhciBjdXJyZW50VmFsdWUgPSBfc3RlcDIudmFsdWU7XG5cblx0XHRcdFx0aWYgKGN1cnJlbnRWYWx1ZSA+PSBuICYmIGN1cnJlbnRWYWx1ZSA8IG0pIHtcblx0XHRcdFx0XHRtID0gY3VycmVudFZhbHVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIEluY3JlYXNlIGBkZWx0YWAgZW5vdWdoIHRvIGFkdmFuY2UgdGhlIGRlY29kZXIncyA8bixpPiBzdGF0ZSB0byA8bSwwPixcblx0XHRcdC8vIGJ1dCBndWFyZCBhZ2FpbnN0IG92ZXJmbG93LlxuXHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0X2RpZEl0ZXJhdG9yRXJyb3IyID0gdHJ1ZTtcblx0XHRcdF9pdGVyYXRvckVycm9yMiA9IGVycjtcblx0XHR9IGZpbmFsbHkge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0aWYgKCFfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uMiAmJiBfaXRlcmF0b3IyLnJldHVybikge1xuXHRcdFx0XHRcdF9pdGVyYXRvcjIucmV0dXJuKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdGlmIChfZGlkSXRlcmF0b3JFcnJvcjIpIHtcblx0XHRcdFx0XHR0aHJvdyBfaXRlcmF0b3JFcnJvcjI7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHR2YXIgaGFuZGxlZENQQ291bnRQbHVzT25lID0gaGFuZGxlZENQQ291bnQgKyAxO1xuXHRcdGlmIChtIC0gbiA+IGZsb29yKChtYXhJbnQgLSBkZWx0YSkgLyBoYW5kbGVkQ1BDb3VudFBsdXNPbmUpKSB7XG5cdFx0XHRlcnJvciQxKCdvdmVyZmxvdycpO1xuXHRcdH1cblxuXHRcdGRlbHRhICs9IChtIC0gbikgKiBoYW5kbGVkQ1BDb3VudFBsdXNPbmU7XG5cdFx0biA9IG07XG5cblx0XHR2YXIgX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbjMgPSB0cnVlO1xuXHRcdHZhciBfZGlkSXRlcmF0b3JFcnJvcjMgPSBmYWxzZTtcblx0XHR2YXIgX2l0ZXJhdG9yRXJyb3IzID0gdW5kZWZpbmVkO1xuXG5cdFx0dHJ5IHtcblx0XHRcdGZvciAodmFyIF9pdGVyYXRvcjMgPSBpbnB1dFtTeW1ib2wuaXRlcmF0b3JdKCksIF9zdGVwMzsgIShfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uMyA9IChfc3RlcDMgPSBfaXRlcmF0b3IzLm5leHQoKSkuZG9uZSk7IF9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24zID0gdHJ1ZSkge1xuXHRcdFx0XHR2YXIgX2N1cnJlbnRWYWx1ZSA9IF9zdGVwMy52YWx1ZTtcblxuXHRcdFx0XHRpZiAoX2N1cnJlbnRWYWx1ZSA8IG4gJiYgKytkZWx0YSA+IG1heEludCkge1xuXHRcdFx0XHRcdGVycm9yJDEoJ292ZXJmbG93Jyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKF9jdXJyZW50VmFsdWUgPT0gbikge1xuXHRcdFx0XHRcdC8vIFJlcHJlc2VudCBkZWx0YSBhcyBhIGdlbmVyYWxpemVkIHZhcmlhYmxlLWxlbmd0aCBpbnRlZ2VyLlxuXHRcdFx0XHRcdHZhciBxID0gZGVsdGE7XG5cdFx0XHRcdFx0Zm9yICh2YXIgayA9IGJhc2U7OyAvKiBubyBjb25kaXRpb24gKi9rICs9IGJhc2UpIHtcblx0XHRcdFx0XHRcdHZhciB0ID0gayA8PSBiaWFzID8gdE1pbiA6IGsgPj0gYmlhcyArIHRNYXggPyB0TWF4IDogayAtIGJpYXM7XG5cdFx0XHRcdFx0XHRpZiAocSA8IHQpIHtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR2YXIgcU1pbnVzVCA9IHEgLSB0O1xuXHRcdFx0XHRcdFx0dmFyIGJhc2VNaW51c1QgPSBiYXNlIC0gdDtcblx0XHRcdFx0XHRcdG91dHB1dC5wdXNoKHN0cmluZ0Zyb21DaGFyQ29kZShkaWdpdFRvQmFzaWModCArIHFNaW51c1QgJSBiYXNlTWludXNULCAwKSkpO1xuXHRcdFx0XHRcdFx0cSA9IGZsb29yKHFNaW51c1QgLyBiYXNlTWludXNUKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRvdXRwdXQucHVzaChzdHJpbmdGcm9tQ2hhckNvZGUoZGlnaXRUb0Jhc2ljKHEsIDApKSk7XG5cdFx0XHRcdFx0YmlhcyA9IGFkYXB0KGRlbHRhLCBoYW5kbGVkQ1BDb3VudFBsdXNPbmUsIGhhbmRsZWRDUENvdW50ID09IGJhc2ljTGVuZ3RoKTtcblx0XHRcdFx0XHRkZWx0YSA9IDA7XG5cdFx0XHRcdFx0KytoYW5kbGVkQ1BDb3VudDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0X2RpZEl0ZXJhdG9yRXJyb3IzID0gdHJ1ZTtcblx0XHRcdF9pdGVyYXRvckVycm9yMyA9IGVycjtcblx0XHR9IGZpbmFsbHkge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0aWYgKCFfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uMyAmJiBfaXRlcmF0b3IzLnJldHVybikge1xuXHRcdFx0XHRcdF9pdGVyYXRvcjMucmV0dXJuKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdGlmIChfZGlkSXRlcmF0b3JFcnJvcjMpIHtcblx0XHRcdFx0XHR0aHJvdyBfaXRlcmF0b3JFcnJvcjM7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQrK2RlbHRhO1xuXHRcdCsrbjtcblx0fVxuXHRyZXR1cm4gb3V0cHV0LmpvaW4oJycpO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0cyBhIFB1bnljb2RlIHN0cmluZyByZXByZXNlbnRpbmcgYSBkb21haW4gbmFtZSBvciBhbiBlbWFpbCBhZGRyZXNzXG4gKiB0byBVbmljb2RlLiBPbmx5IHRoZSBQdW55Y29kZWQgcGFydHMgb2YgdGhlIGlucHV0IHdpbGwgYmUgY29udmVydGVkLCBpLmUuXG4gKiBpdCBkb2Vzbid0IG1hdHRlciBpZiB5b3UgY2FsbCBpdCBvbiBhIHN0cmluZyB0aGF0IGhhcyBhbHJlYWR5IGJlZW5cbiAqIGNvbnZlcnRlZCB0byBVbmljb2RlLlxuICogQG1lbWJlck9mIHB1bnljb2RlXG4gKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgVGhlIFB1bnljb2RlZCBkb21haW4gbmFtZSBvciBlbWFpbCBhZGRyZXNzIHRvXG4gKiBjb252ZXJ0IHRvIFVuaWNvZGUuXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgVW5pY29kZSByZXByZXNlbnRhdGlvbiBvZiB0aGUgZ2l2ZW4gUHVueWNvZGVcbiAqIHN0cmluZy5cbiAqL1xudmFyIHRvVW5pY29kZSA9IGZ1bmN0aW9uIHRvVW5pY29kZShpbnB1dCkge1xuXHRyZXR1cm4gbWFwRG9tYWluKGlucHV0LCBmdW5jdGlvbiAoc3RyaW5nKSB7XG5cdFx0cmV0dXJuIHJlZ2V4UHVueWNvZGUudGVzdChzdHJpbmcpID8gZGVjb2RlKHN0cmluZy5zbGljZSg0KS50b0xvd2VyQ2FzZSgpKSA6IHN0cmluZztcblx0fSk7XG59O1xuXG4vKipcbiAqIENvbnZlcnRzIGEgVW5pY29kZSBzdHJpbmcgcmVwcmVzZW50aW5nIGEgZG9tYWluIG5hbWUgb3IgYW4gZW1haWwgYWRkcmVzcyB0b1xuICogUHVueWNvZGUuIE9ubHkgdGhlIG5vbi1BU0NJSSBwYXJ0cyBvZiB0aGUgZG9tYWluIG5hbWUgd2lsbCBiZSBjb252ZXJ0ZWQsXG4gKiBpLmUuIGl0IGRvZXNuJ3QgbWF0dGVyIGlmIHlvdSBjYWxsIGl0IHdpdGggYSBkb21haW4gdGhhdCdzIGFscmVhZHkgaW5cbiAqIEFTQ0lJLlxuICogQG1lbWJlck9mIHB1bnljb2RlXG4gKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgVGhlIGRvbWFpbiBuYW1lIG9yIGVtYWlsIGFkZHJlc3MgdG8gY29udmVydCwgYXMgYVxuICogVW5pY29kZSBzdHJpbmcuXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgUHVueWNvZGUgcmVwcmVzZW50YXRpb24gb2YgdGhlIGdpdmVuIGRvbWFpbiBuYW1lIG9yXG4gKiBlbWFpbCBhZGRyZXNzLlxuICovXG52YXIgdG9BU0NJSSA9IGZ1bmN0aW9uIHRvQVNDSUkoaW5wdXQpIHtcblx0cmV0dXJuIG1hcERvbWFpbihpbnB1dCwgZnVuY3Rpb24gKHN0cmluZykge1xuXHRcdHJldHVybiByZWdleE5vbkFTQ0lJLnRlc3Qoc3RyaW5nKSA/ICd4bi0tJyArIGVuY29kZShzdHJpbmcpIDogc3RyaW5nO1xuXHR9KTtcbn07XG5cbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4vKiogRGVmaW5lIHRoZSBwdWJsaWMgQVBJICovXG52YXIgcHVueWNvZGUgPSB7XG5cdC8qKlxuICAqIEEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgY3VycmVudCBQdW55Y29kZS5qcyB2ZXJzaW9uIG51bWJlci5cbiAgKiBAbWVtYmVyT2YgcHVueWNvZGVcbiAgKiBAdHlwZSBTdHJpbmdcbiAgKi9cblx0J3ZlcnNpb24nOiAnMi4xLjAnLFxuXHQvKipcbiAgKiBBbiBvYmplY3Qgb2YgbWV0aG9kcyB0byBjb252ZXJ0IGZyb20gSmF2YVNjcmlwdCdzIGludGVybmFsIGNoYXJhY3RlclxuICAqIHJlcHJlc2VudGF0aW9uIChVQ1MtMikgdG8gVW5pY29kZSBjb2RlIHBvaW50cywgYW5kIGJhY2suXG4gICogQHNlZSA8aHR0cHM6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2phdmFzY3JpcHQtZW5jb2Rpbmc+XG4gICogQG1lbWJlck9mIHB1bnljb2RlXG4gICogQHR5cGUgT2JqZWN0XG4gICovXG5cdCd1Y3MyJzoge1xuXHRcdCdkZWNvZGUnOiB1Y3MyZGVjb2RlLFxuXHRcdCdlbmNvZGUnOiB1Y3MyZW5jb2RlXG5cdH0sXG5cdCdkZWNvZGUnOiBkZWNvZGUsXG5cdCdlbmNvZGUnOiBlbmNvZGUsXG5cdCd0b0FTQ0lJJzogdG9BU0NJSSxcblx0J3RvVW5pY29kZSc6IHRvVW5pY29kZVxufTtcblxuLyoqXG4gKiBVUkkuanNcbiAqXG4gKiBAZmlsZW92ZXJ2aWV3IEFuIFJGQyAzOTg2IGNvbXBsaWFudCwgc2NoZW1lIGV4dGVuZGFibGUgVVJJIHBhcnNpbmcvdmFsaWRhdGluZy9yZXNvbHZpbmcgbGlicmFyeSBmb3IgSmF2YVNjcmlwdC5cbiAqIEBhdXRob3IgPGEgaHJlZj1cIm1haWx0bzpnYXJ5LmNvdXJ0QGdtYWlsLmNvbVwiPkdhcnkgQ291cnQ8L2E+XG4gKiBAc2VlIGh0dHA6Ly9naXRodWIuY29tL2dhcnljb3VydC91cmktanNcbiAqL1xuLyoqXG4gKiBDb3B5cmlnaHQgMjAxMSBHYXJ5IENvdXJ0LiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICpcbiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sIGFyZVxuICogcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG4gKlxuICogICAgMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2ZcbiAqICAgICAgIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAqXG4gKiAgICAyLiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXMgbGlzdFxuICogICAgICAgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHNcbiAqICAgICAgIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cbiAqXG4gKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIEdBUlkgQ09VUlQgYGBBUyBJUycnIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEXG4gKiBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EXG4gKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgR0FSWSBDT1VSVCBPUlxuICogQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1JcbiAqIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1JcbiAqIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cbiAqIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkdcbiAqIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRlxuICogQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG4gKlxuICogVGhlIHZpZXdzIGFuZCBjb25jbHVzaW9ucyBjb250YWluZWQgaW4gdGhlIHNvZnR3YXJlIGFuZCBkb2N1bWVudGF0aW9uIGFyZSB0aG9zZSBvZiB0aGVcbiAqIGF1dGhvcnMgYW5kIHNob3VsZCBub3QgYmUgaW50ZXJwcmV0ZWQgYXMgcmVwcmVzZW50aW5nIG9mZmljaWFsIHBvbGljaWVzLCBlaXRoZXIgZXhwcmVzc2VkXG4gKiBvciBpbXBsaWVkLCBvZiBHYXJ5IENvdXJ0LlxuICovXG52YXIgU0NIRU1FUyA9IHt9O1xuZnVuY3Rpb24gcGN0RW5jQ2hhcihjaHIpIHtcbiAgICB2YXIgYyA9IGNoci5jaGFyQ29kZUF0KDApO1xuICAgIHZhciBlID0gdm9pZCAwO1xuICAgIGlmIChjIDwgMTYpIGUgPSBcIiUwXCIgKyBjLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO2Vsc2UgaWYgKGMgPCAxMjgpIGUgPSBcIiVcIiArIGMudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCk7ZWxzZSBpZiAoYyA8IDIwNDgpIGUgPSBcIiVcIiArIChjID4+IDYgfCAxOTIpLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpICsgXCIlXCIgKyAoYyAmIDYzIHwgMTI4KS50b1N0cmluZygxNikudG9VcHBlckNhc2UoKTtlbHNlIGUgPSBcIiVcIiArIChjID4+IDEyIHwgMjI0KS50b1N0cmluZygxNikudG9VcHBlckNhc2UoKSArIFwiJVwiICsgKGMgPj4gNiAmIDYzIHwgMTI4KS50b1N0cmluZygxNikudG9VcHBlckNhc2UoKSArIFwiJVwiICsgKGMgJiA2MyB8IDEyOCkudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCk7XG4gICAgcmV0dXJuIGU7XG59XG5mdW5jdGlvbiBwY3REZWNDaGFycyhzdHIpIHtcbiAgICB2YXIgbmV3U3RyID0gXCJcIjtcbiAgICB2YXIgaSA9IDA7XG4gICAgdmFyIGlsID0gc3RyLmxlbmd0aDtcbiAgICB3aGlsZSAoaSA8IGlsKSB7XG4gICAgICAgIHZhciBjID0gcGFyc2VJbnQoc3RyLnN1YnN0cihpICsgMSwgMiksIDE2KTtcbiAgICAgICAgaWYgKGMgPCAxMjgpIHtcbiAgICAgICAgICAgIG5ld1N0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGMpO1xuICAgICAgICAgICAgaSArPSAzO1xuICAgICAgICB9IGVsc2UgaWYgKGMgPj0gMTk0ICYmIGMgPCAyMjQpIHtcbiAgICAgICAgICAgIGlmIChpbCAtIGkgPj0gNikge1xuICAgICAgICAgICAgICAgIHZhciBjMiA9IHBhcnNlSW50KHN0ci5zdWJzdHIoaSArIDQsIDIpLCAxNik7XG4gICAgICAgICAgICAgICAgbmV3U3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGMgJiAzMSkgPDwgNiB8IGMyICYgNjMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuZXdTdHIgKz0gc3RyLnN1YnN0cihpLCA2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGkgKz0gNjtcbiAgICAgICAgfSBlbHNlIGlmIChjID49IDIyNCkge1xuICAgICAgICAgICAgaWYgKGlsIC0gaSA+PSA5KSB7XG4gICAgICAgICAgICAgICAgdmFyIF9jID0gcGFyc2VJbnQoc3RyLnN1YnN0cihpICsgNCwgMiksIDE2KTtcbiAgICAgICAgICAgICAgICB2YXIgYzMgPSBwYXJzZUludChzdHIuc3Vic3RyKGkgKyA3LCAyKSwgMTYpO1xuICAgICAgICAgICAgICAgIG5ld1N0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKChjICYgMTUpIDw8IDEyIHwgKF9jICYgNjMpIDw8IDYgfCBjMyAmIDYzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbmV3U3RyICs9IHN0ci5zdWJzdHIoaSwgOSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpICs9IDk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuZXdTdHIgKz0gc3RyLnN1YnN0cihpLCAzKTtcbiAgICAgICAgICAgIGkgKz0gMztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmV3U3RyO1xufVxuZnVuY3Rpb24gX25vcm1hbGl6ZUNvbXBvbmVudEVuY29kaW5nKGNvbXBvbmVudHMsIHByb3RvY29sKSB7XG4gICAgZnVuY3Rpb24gZGVjb2RlVW5yZXNlcnZlZChzdHIpIHtcbiAgICAgICAgdmFyIGRlY1N0ciA9IHBjdERlY0NoYXJzKHN0cik7XG4gICAgICAgIHJldHVybiAhZGVjU3RyLm1hdGNoKHByb3RvY29sLlVOUkVTRVJWRUQpID8gc3RyIDogZGVjU3RyO1xuICAgIH1cbiAgICBpZiAoY29tcG9uZW50cy5zY2hlbWUpIGNvbXBvbmVudHMuc2NoZW1lID0gU3RyaW5nKGNvbXBvbmVudHMuc2NoZW1lKS5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCBkZWNvZGVVbnJlc2VydmVkKS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UocHJvdG9jb2wuTk9UX1NDSEVNRSwgXCJcIik7XG4gICAgaWYgKGNvbXBvbmVudHMudXNlcmluZm8gIT09IHVuZGVmaW5lZCkgY29tcG9uZW50cy51c2VyaW5mbyA9IFN0cmluZyhjb21wb25lbnRzLnVzZXJpbmZvKS5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCBkZWNvZGVVbnJlc2VydmVkKS5yZXBsYWNlKHByb3RvY29sLk5PVF9VU0VSSU5GTywgcGN0RW5jQ2hhcikucmVwbGFjZShwcm90b2NvbC5QQ1RfRU5DT0RFRCwgdG9VcHBlckNhc2UpO1xuICAgIGlmIChjb21wb25lbnRzLmhvc3QgIT09IHVuZGVmaW5lZCkgY29tcG9uZW50cy5ob3N0ID0gU3RyaW5nKGNvbXBvbmVudHMuaG9zdCkucmVwbGFjZShwcm90b2NvbC5QQ1RfRU5DT0RFRCwgZGVjb2RlVW5yZXNlcnZlZCkudG9Mb3dlckNhc2UoKS5yZXBsYWNlKHByb3RvY29sLk5PVF9IT1NULCBwY3RFbmNDaGFyKS5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCB0b1VwcGVyQ2FzZSk7XG4gICAgaWYgKGNvbXBvbmVudHMucGF0aCAhPT0gdW5kZWZpbmVkKSBjb21wb25lbnRzLnBhdGggPSBTdHJpbmcoY29tcG9uZW50cy5wYXRoKS5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCBkZWNvZGVVbnJlc2VydmVkKS5yZXBsYWNlKGNvbXBvbmVudHMuc2NoZW1lID8gcHJvdG9jb2wuTk9UX1BBVEggOiBwcm90b2NvbC5OT1RfUEFUSF9OT1NDSEVNRSwgcGN0RW5jQ2hhcikucmVwbGFjZShwcm90b2NvbC5QQ1RfRU5DT0RFRCwgdG9VcHBlckNhc2UpO1xuICAgIGlmIChjb21wb25lbnRzLnF1ZXJ5ICE9PSB1bmRlZmluZWQpIGNvbXBvbmVudHMucXVlcnkgPSBTdHJpbmcoY29tcG9uZW50cy5xdWVyeSkucmVwbGFjZShwcm90b2NvbC5QQ1RfRU5DT0RFRCwgZGVjb2RlVW5yZXNlcnZlZCkucmVwbGFjZShwcm90b2NvbC5OT1RfUVVFUlksIHBjdEVuY0NoYXIpLnJlcGxhY2UocHJvdG9jb2wuUENUX0VOQ09ERUQsIHRvVXBwZXJDYXNlKTtcbiAgICBpZiAoY29tcG9uZW50cy5mcmFnbWVudCAhPT0gdW5kZWZpbmVkKSBjb21wb25lbnRzLmZyYWdtZW50ID0gU3RyaW5nKGNvbXBvbmVudHMuZnJhZ21lbnQpLnJlcGxhY2UocHJvdG9jb2wuUENUX0VOQ09ERUQsIGRlY29kZVVucmVzZXJ2ZWQpLnJlcGxhY2UocHJvdG9jb2wuTk9UX0ZSQUdNRU5ULCBwY3RFbmNDaGFyKS5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCB0b1VwcGVyQ2FzZSk7XG4gICAgcmV0dXJuIGNvbXBvbmVudHM7XG59XG5cbmZ1bmN0aW9uIF9zdHJpcExlYWRpbmdaZXJvcyhzdHIpIHtcbiAgICByZXR1cm4gc3RyLnJlcGxhY2UoL14wKiguKikvLCBcIiQxXCIpIHx8IFwiMFwiO1xufVxuZnVuY3Rpb24gX25vcm1hbGl6ZUlQdjQoaG9zdCwgcHJvdG9jb2wpIHtcbiAgICB2YXIgbWF0Y2hlcyA9IGhvc3QubWF0Y2gocHJvdG9jb2wuSVBWNEFERFJFU1MpIHx8IFtdO1xuXG4gICAgdmFyIF9tYXRjaGVzID0gc2xpY2VkVG9BcnJheShtYXRjaGVzLCAyKSxcbiAgICAgICAgYWRkcmVzcyA9IF9tYXRjaGVzWzFdO1xuXG4gICAgaWYgKGFkZHJlc3MpIHtcbiAgICAgICAgcmV0dXJuIGFkZHJlc3Muc3BsaXQoXCIuXCIpLm1hcChfc3RyaXBMZWFkaW5nWmVyb3MpLmpvaW4oXCIuXCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBob3N0O1xuICAgIH1cbn1cbmZ1bmN0aW9uIF9ub3JtYWxpemVJUHY2KGhvc3QsIHByb3RvY29sKSB7XG4gICAgdmFyIG1hdGNoZXMgPSBob3N0Lm1hdGNoKHByb3RvY29sLklQVjZBRERSRVNTKSB8fCBbXTtcblxuICAgIHZhciBfbWF0Y2hlczIgPSBzbGljZWRUb0FycmF5KG1hdGNoZXMsIDMpLFxuICAgICAgICBhZGRyZXNzID0gX21hdGNoZXMyWzFdLFxuICAgICAgICB6b25lID0gX21hdGNoZXMyWzJdO1xuXG4gICAgaWYgKGFkZHJlc3MpIHtcbiAgICAgICAgdmFyIF9hZGRyZXNzJHRvTG93ZXJDYXNlJCA9IGFkZHJlc3MudG9Mb3dlckNhc2UoKS5zcGxpdCgnOjonKS5yZXZlcnNlKCksXG4gICAgICAgICAgICBfYWRkcmVzcyR0b0xvd2VyQ2FzZSQyID0gc2xpY2VkVG9BcnJheShfYWRkcmVzcyR0b0xvd2VyQ2FzZSQsIDIpLFxuICAgICAgICAgICAgbGFzdCA9IF9hZGRyZXNzJHRvTG93ZXJDYXNlJDJbMF0sXG4gICAgICAgICAgICBmaXJzdCA9IF9hZGRyZXNzJHRvTG93ZXJDYXNlJDJbMV07XG5cbiAgICAgICAgdmFyIGZpcnN0RmllbGRzID0gZmlyc3QgPyBmaXJzdC5zcGxpdChcIjpcIikubWFwKF9zdHJpcExlYWRpbmdaZXJvcykgOiBbXTtcbiAgICAgICAgdmFyIGxhc3RGaWVsZHMgPSBsYXN0LnNwbGl0KFwiOlwiKS5tYXAoX3N0cmlwTGVhZGluZ1plcm9zKTtcbiAgICAgICAgdmFyIGlzTGFzdEZpZWxkSVB2NEFkZHJlc3MgPSBwcm90b2NvbC5JUFY0QUREUkVTUy50ZXN0KGxhc3RGaWVsZHNbbGFzdEZpZWxkcy5sZW5ndGggLSAxXSk7XG4gICAgICAgIHZhciBmaWVsZENvdW50ID0gaXNMYXN0RmllbGRJUHY0QWRkcmVzcyA/IDcgOiA4O1xuICAgICAgICB2YXIgbGFzdEZpZWxkc1N0YXJ0ID0gbGFzdEZpZWxkcy5sZW5ndGggLSBmaWVsZENvdW50O1xuICAgICAgICB2YXIgZmllbGRzID0gQXJyYXkoZmllbGRDb3VudCk7XG4gICAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgZmllbGRDb3VudDsgKyt4KSB7XG4gICAgICAgICAgICBmaWVsZHNbeF0gPSBmaXJzdEZpZWxkc1t4XSB8fCBsYXN0RmllbGRzW2xhc3RGaWVsZHNTdGFydCArIHhdIHx8ICcnO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0xhc3RGaWVsZElQdjRBZGRyZXNzKSB7XG4gICAgICAgICAgICBmaWVsZHNbZmllbGRDb3VudCAtIDFdID0gX25vcm1hbGl6ZUlQdjQoZmllbGRzW2ZpZWxkQ291bnQgLSAxXSwgcHJvdG9jb2wpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhbGxaZXJvRmllbGRzID0gZmllbGRzLnJlZHVjZShmdW5jdGlvbiAoYWNjLCBmaWVsZCwgaW5kZXgpIHtcbiAgICAgICAgICAgIGlmICghZmllbGQgfHwgZmllbGQgPT09IFwiMFwiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxhc3RMb25nZXN0ID0gYWNjW2FjYy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICBpZiAobGFzdExvbmdlc3QgJiYgbGFzdExvbmdlc3QuaW5kZXggKyBsYXN0TG9uZ2VzdC5sZW5ndGggPT09IGluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGxhc3RMb25nZXN0Lmxlbmd0aCsrO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFjYy5wdXNoKHsgaW5kZXg6IGluZGV4LCBsZW5ndGg6IDEgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgICAgfSwgW10pO1xuICAgICAgICB2YXIgbG9uZ2VzdFplcm9GaWVsZHMgPSBhbGxaZXJvRmllbGRzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiBiLmxlbmd0aCAtIGEubGVuZ3RoO1xuICAgICAgICB9KVswXTtcbiAgICAgICAgdmFyIG5ld0hvc3QgPSB2b2lkIDA7XG4gICAgICAgIGlmIChsb25nZXN0WmVyb0ZpZWxkcyAmJiBsb25nZXN0WmVyb0ZpZWxkcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICB2YXIgbmV3Rmlyc3QgPSBmaWVsZHMuc2xpY2UoMCwgbG9uZ2VzdFplcm9GaWVsZHMuaW5kZXgpO1xuICAgICAgICAgICAgdmFyIG5ld0xhc3QgPSBmaWVsZHMuc2xpY2UobG9uZ2VzdFplcm9GaWVsZHMuaW5kZXggKyBsb25nZXN0WmVyb0ZpZWxkcy5sZW5ndGgpO1xuICAgICAgICAgICAgbmV3SG9zdCA9IG5ld0ZpcnN0LmpvaW4oXCI6XCIpICsgXCI6OlwiICsgbmV3TGFzdC5qb2luKFwiOlwiKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld0hvc3QgPSBmaWVsZHMuam9pbihcIjpcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHpvbmUpIHtcbiAgICAgICAgICAgIG5ld0hvc3QgKz0gXCIlXCIgKyB6b25lO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXdIb3N0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBob3N0O1xuICAgIH1cbn1cbnZhciBVUklfUEFSU0UgPSAvXig/OihbXjpcXC8/I10rKTopPyg/OlxcL1xcLygoPzooW15cXC8/I0BdKilAKT8oXFxbW15cXC8/I1xcXV0rXFxdfFteXFwvPyM6XSopKD86XFw6KFxcZCopKT8pKT8oW14/I10qKSg/OlxcPyhbXiNdKikpPyg/OiMoKD86LnxcXG58XFxyKSopKT8vaTtcbnZhciBOT19NQVRDSF9JU19VTkRFRklORUQgPSBcIlwiLm1hdGNoKC8oKXswfS8pWzFdID09PSB1bmRlZmluZWQ7XG5mdW5jdGlvbiBwYXJzZSh1cmlTdHJpbmcpIHtcbiAgICB2YXIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICB2YXIgY29tcG9uZW50cyA9IHt9O1xuICAgIHZhciBwcm90b2NvbCA9IG9wdGlvbnMuaXJpICE9PSBmYWxzZSA/IElSSV9QUk9UT0NPTCA6IFVSSV9QUk9UT0NPTDtcbiAgICBpZiAob3B0aW9ucy5yZWZlcmVuY2UgPT09IFwic3VmZml4XCIpIHVyaVN0cmluZyA9IChvcHRpb25zLnNjaGVtZSA/IG9wdGlvbnMuc2NoZW1lICsgXCI6XCIgOiBcIlwiKSArIFwiLy9cIiArIHVyaVN0cmluZztcbiAgICB2YXIgbWF0Y2hlcyA9IHVyaVN0cmluZy5tYXRjaChVUklfUEFSU0UpO1xuICAgIGlmIChtYXRjaGVzKSB7XG4gICAgICAgIGlmIChOT19NQVRDSF9JU19VTkRFRklORUQpIHtcbiAgICAgICAgICAgIC8vc3RvcmUgZWFjaCBjb21wb25lbnRcbiAgICAgICAgICAgIGNvbXBvbmVudHMuc2NoZW1lID0gbWF0Y2hlc1sxXTtcbiAgICAgICAgICAgIGNvbXBvbmVudHMudXNlcmluZm8gPSBtYXRjaGVzWzNdO1xuICAgICAgICAgICAgY29tcG9uZW50cy5ob3N0ID0gbWF0Y2hlc1s0XTtcbiAgICAgICAgICAgIGNvbXBvbmVudHMucG9ydCA9IHBhcnNlSW50KG1hdGNoZXNbNV0sIDEwKTtcbiAgICAgICAgICAgIGNvbXBvbmVudHMucGF0aCA9IG1hdGNoZXNbNl0gfHwgXCJcIjtcbiAgICAgICAgICAgIGNvbXBvbmVudHMucXVlcnkgPSBtYXRjaGVzWzddO1xuICAgICAgICAgICAgY29tcG9uZW50cy5mcmFnbWVudCA9IG1hdGNoZXNbOF07XG4gICAgICAgICAgICAvL2ZpeCBwb3J0IG51bWJlclxuICAgICAgICAgICAgaWYgKGlzTmFOKGNvbXBvbmVudHMucG9ydCkpIHtcbiAgICAgICAgICAgICAgICBjb21wb25lbnRzLnBvcnQgPSBtYXRjaGVzWzVdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy9JRSBGSVggZm9yIGltcHJvcGVyIFJlZ0V4cCBtYXRjaGluZ1xuICAgICAgICAgICAgLy9zdG9yZSBlYWNoIGNvbXBvbmVudFxuICAgICAgICAgICAgY29tcG9uZW50cy5zY2hlbWUgPSBtYXRjaGVzWzFdIHx8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGNvbXBvbmVudHMudXNlcmluZm8gPSB1cmlTdHJpbmcuaW5kZXhPZihcIkBcIikgIT09IC0xID8gbWF0Y2hlc1szXSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGNvbXBvbmVudHMuaG9zdCA9IHVyaVN0cmluZy5pbmRleE9mKFwiLy9cIikgIT09IC0xID8gbWF0Y2hlc1s0XSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGNvbXBvbmVudHMucG9ydCA9IHBhcnNlSW50KG1hdGNoZXNbNV0sIDEwKTtcbiAgICAgICAgICAgIGNvbXBvbmVudHMucGF0aCA9IG1hdGNoZXNbNl0gfHwgXCJcIjtcbiAgICAgICAgICAgIGNvbXBvbmVudHMucXVlcnkgPSB1cmlTdHJpbmcuaW5kZXhPZihcIj9cIikgIT09IC0xID8gbWF0Y2hlc1s3XSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGNvbXBvbmVudHMuZnJhZ21lbnQgPSB1cmlTdHJpbmcuaW5kZXhPZihcIiNcIikgIT09IC0xID8gbWF0Y2hlc1s4XSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIC8vZml4IHBvcnQgbnVtYmVyXG4gICAgICAgICAgICBpZiAoaXNOYU4oY29tcG9uZW50cy5wb3J0KSkge1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudHMucG9ydCA9IHVyaVN0cmluZy5tYXRjaCgvXFwvXFwvKD86LnxcXG4pKlxcOig/OlxcL3xcXD98XFwjfCQpLykgPyBtYXRjaGVzWzRdIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChjb21wb25lbnRzLmhvc3QpIHtcbiAgICAgICAgICAgIC8vbm9ybWFsaXplIElQIGhvc3RzXG4gICAgICAgICAgICBjb21wb25lbnRzLmhvc3QgPSBfbm9ybWFsaXplSVB2Nihfbm9ybWFsaXplSVB2NChjb21wb25lbnRzLmhvc3QsIHByb3RvY29sKSwgcHJvdG9jb2wpO1xuICAgICAgICB9XG4gICAgICAgIC8vZGV0ZXJtaW5lIHJlZmVyZW5jZSB0eXBlXG4gICAgICAgIGlmIChjb21wb25lbnRzLnNjaGVtZSA9PT0gdW5kZWZpbmVkICYmIGNvbXBvbmVudHMudXNlcmluZm8gPT09IHVuZGVmaW5lZCAmJiBjb21wb25lbnRzLmhvc3QgPT09IHVuZGVmaW5lZCAmJiBjb21wb25lbnRzLnBvcnQgPT09IHVuZGVmaW5lZCAmJiAhY29tcG9uZW50cy5wYXRoICYmIGNvbXBvbmVudHMucXVlcnkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29tcG9uZW50cy5yZWZlcmVuY2UgPSBcInNhbWUtZG9jdW1lbnRcIjtcbiAgICAgICAgfSBlbHNlIGlmIChjb21wb25lbnRzLnNjaGVtZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjb21wb25lbnRzLnJlZmVyZW5jZSA9IFwicmVsYXRpdmVcIjtcbiAgICAgICAgfSBlbHNlIGlmIChjb21wb25lbnRzLmZyYWdtZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbXBvbmVudHMucmVmZXJlbmNlID0gXCJhYnNvbHV0ZVwiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29tcG9uZW50cy5yZWZlcmVuY2UgPSBcInVyaVwiO1xuICAgICAgICB9XG4gICAgICAgIC8vY2hlY2sgZm9yIHJlZmVyZW5jZSBlcnJvcnNcbiAgICAgICAgaWYgKG9wdGlvbnMucmVmZXJlbmNlICYmIG9wdGlvbnMucmVmZXJlbmNlICE9PSBcInN1ZmZpeFwiICYmIG9wdGlvbnMucmVmZXJlbmNlICE9PSBjb21wb25lbnRzLnJlZmVyZW5jZSkge1xuICAgICAgICAgICAgY29tcG9uZW50cy5lcnJvciA9IGNvbXBvbmVudHMuZXJyb3IgfHwgXCJVUkkgaXMgbm90IGEgXCIgKyBvcHRpb25zLnJlZmVyZW5jZSArIFwiIHJlZmVyZW5jZS5cIjtcbiAgICAgICAgfVxuICAgICAgICAvL2ZpbmQgc2NoZW1lIGhhbmRsZXJcbiAgICAgICAgdmFyIHNjaGVtZUhhbmRsZXIgPSBTQ0hFTUVTWyhvcHRpb25zLnNjaGVtZSB8fCBjb21wb25lbnRzLnNjaGVtZSB8fCBcIlwiKS50b0xvd2VyQ2FzZSgpXTtcbiAgICAgICAgLy9jaGVjayBpZiBzY2hlbWUgY2FuJ3QgaGFuZGxlIElSSXNcbiAgICAgICAgaWYgKCFvcHRpb25zLnVuaWNvZGVTdXBwb3J0ICYmICghc2NoZW1lSGFuZGxlciB8fCAhc2NoZW1lSGFuZGxlci51bmljb2RlU3VwcG9ydCkpIHtcbiAgICAgICAgICAgIC8vaWYgaG9zdCBjb21wb25lbnQgaXMgYSBkb21haW4gbmFtZVxuICAgICAgICAgICAgaWYgKGNvbXBvbmVudHMuaG9zdCAmJiAob3B0aW9ucy5kb21haW5Ib3N0IHx8IHNjaGVtZUhhbmRsZXIgJiYgc2NoZW1lSGFuZGxlci5kb21haW5Ib3N0KSkge1xuICAgICAgICAgICAgICAgIC8vY29udmVydCBVbmljb2RlIElETiAtPiBBU0NJSSBJRE5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRzLmhvc3QgPSBwdW55Y29kZS50b0FTQ0lJKGNvbXBvbmVudHMuaG9zdC5yZXBsYWNlKHByb3RvY29sLlBDVF9FTkNPREVELCBwY3REZWNDaGFycykudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRzLmVycm9yID0gY29tcG9uZW50cy5lcnJvciB8fCBcIkhvc3QncyBkb21haW4gbmFtZSBjYW4gbm90IGJlIGNvbnZlcnRlZCB0byBBU0NJSSB2aWEgcHVueWNvZGU6IFwiICsgZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvL2NvbnZlcnQgSVJJIC0+IFVSSVxuICAgICAgICAgICAgX25vcm1hbGl6ZUNvbXBvbmVudEVuY29kaW5nKGNvbXBvbmVudHMsIFVSSV9QUk9UT0NPTCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvL25vcm1hbGl6ZSBlbmNvZGluZ3NcbiAgICAgICAgICAgIF9ub3JtYWxpemVDb21wb25lbnRFbmNvZGluZyhjb21wb25lbnRzLCBwcm90b2NvbCk7XG4gICAgICAgIH1cbiAgICAgICAgLy9wZXJmb3JtIHNjaGVtZSBzcGVjaWZpYyBwYXJzaW5nXG4gICAgICAgIGlmIChzY2hlbWVIYW5kbGVyICYmIHNjaGVtZUhhbmRsZXIucGFyc2UpIHtcbiAgICAgICAgICAgIHNjaGVtZUhhbmRsZXIucGFyc2UoY29tcG9uZW50cywgb3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBjb21wb25lbnRzLmVycm9yID0gY29tcG9uZW50cy5lcnJvciB8fCBcIlVSSSBjYW4gbm90IGJlIHBhcnNlZC5cIjtcbiAgICB9XG4gICAgcmV0dXJuIGNvbXBvbmVudHM7XG59XG5cbmZ1bmN0aW9uIF9yZWNvbXBvc2VBdXRob3JpdHkoY29tcG9uZW50cywgb3B0aW9ucykge1xuICAgIHZhciBwcm90b2NvbCA9IG9wdGlvbnMuaXJpICE9PSBmYWxzZSA/IElSSV9QUk9UT0NPTCA6IFVSSV9QUk9UT0NPTDtcbiAgICB2YXIgdXJpVG9rZW5zID0gW107XG4gICAgaWYgKGNvbXBvbmVudHMudXNlcmluZm8gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB1cmlUb2tlbnMucHVzaChjb21wb25lbnRzLnVzZXJpbmZvKTtcbiAgICAgICAgdXJpVG9rZW5zLnB1c2goXCJAXCIpO1xuICAgIH1cbiAgICBpZiAoY29tcG9uZW50cy5ob3N0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy9ub3JtYWxpemUgSVAgaG9zdHMsIGFkZCBicmFja2V0cyBhbmQgZXNjYXBlIHpvbmUgc2VwYXJhdG9yIGZvciBJUHY2XG4gICAgICAgIHVyaVRva2Vucy5wdXNoKF9ub3JtYWxpemVJUHY2KF9ub3JtYWxpemVJUHY0KFN0cmluZyhjb21wb25lbnRzLmhvc3QpLCBwcm90b2NvbCksIHByb3RvY29sKS5yZXBsYWNlKHByb3RvY29sLklQVjZBRERSRVNTLCBmdW5jdGlvbiAoXywgJDEsICQyKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJbXCIgKyAkMSArICgkMiA/IFwiJTI1XCIgKyAkMiA6IFwiXCIpICsgXCJdXCI7XG4gICAgICAgIH0pKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBjb21wb25lbnRzLnBvcnQgPT09IFwibnVtYmVyXCIgfHwgdHlwZW9mIGNvbXBvbmVudHMucG9ydCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICB1cmlUb2tlbnMucHVzaChcIjpcIik7XG4gICAgICAgIHVyaVRva2Vucy5wdXNoKFN0cmluZyhjb21wb25lbnRzLnBvcnQpKTtcbiAgICB9XG4gICAgcmV0dXJuIHVyaVRva2Vucy5sZW5ndGggPyB1cmlUb2tlbnMuam9pbihcIlwiKSA6IHVuZGVmaW5lZDtcbn1cblxudmFyIFJEUzEgPSAvXlxcLlxcLj9cXC8vO1xudmFyIFJEUzIgPSAvXlxcL1xcLihcXC98JCkvO1xudmFyIFJEUzMgPSAvXlxcL1xcLlxcLihcXC98JCkvO1xudmFyIFJEUzUgPSAvXlxcLz8oPzoufFxcbikqPyg/PVxcL3wkKS87XG5mdW5jdGlvbiByZW1vdmVEb3RTZWdtZW50cyhpbnB1dCkge1xuICAgIHZhciBvdXRwdXQgPSBbXTtcbiAgICB3aGlsZSAoaW5wdXQubGVuZ3RoKSB7XG4gICAgICAgIGlmIChpbnB1dC5tYXRjaChSRFMxKSkge1xuICAgICAgICAgICAgaW5wdXQgPSBpbnB1dC5yZXBsYWNlKFJEUzEsIFwiXCIpO1xuICAgICAgICB9IGVsc2UgaWYgKGlucHV0Lm1hdGNoKFJEUzIpKSB7XG4gICAgICAgICAgICBpbnB1dCA9IGlucHV0LnJlcGxhY2UoUkRTMiwgXCIvXCIpO1xuICAgICAgICB9IGVsc2UgaWYgKGlucHV0Lm1hdGNoKFJEUzMpKSB7XG4gICAgICAgICAgICBpbnB1dCA9IGlucHV0LnJlcGxhY2UoUkRTMywgXCIvXCIpO1xuICAgICAgICAgICAgb3V0cHV0LnBvcCgpO1xuICAgICAgICB9IGVsc2UgaWYgKGlucHV0ID09PSBcIi5cIiB8fCBpbnB1dCA9PT0gXCIuLlwiKSB7XG4gICAgICAgICAgICBpbnB1dCA9IFwiXCI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgaW0gPSBpbnB1dC5tYXRjaChSRFM1KTtcbiAgICAgICAgICAgIGlmIChpbSkge1xuICAgICAgICAgICAgICAgIHZhciBzID0gaW1bMF07XG4gICAgICAgICAgICAgICAgaW5wdXQgPSBpbnB1dC5zbGljZShzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgb3V0cHV0LnB1c2gocyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuZXhwZWN0ZWQgZG90IHNlZ21lbnQgY29uZGl0aW9uXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvdXRwdXQuam9pbihcIlwiKTtcbn1cblxuZnVuY3Rpb24gc2VyaWFsaXplKGNvbXBvbmVudHMpIHtcbiAgICB2YXIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICB2YXIgcHJvdG9jb2wgPSBvcHRpb25zLmlyaSA/IElSSV9QUk9UT0NPTCA6IFVSSV9QUk9UT0NPTDtcbiAgICB2YXIgdXJpVG9rZW5zID0gW107XG4gICAgLy9maW5kIHNjaGVtZSBoYW5kbGVyXG4gICAgdmFyIHNjaGVtZUhhbmRsZXIgPSBTQ0hFTUVTWyhvcHRpb25zLnNjaGVtZSB8fCBjb21wb25lbnRzLnNjaGVtZSB8fCBcIlwiKS50b0xvd2VyQ2FzZSgpXTtcbiAgICAvL3BlcmZvcm0gc2NoZW1lIHNwZWNpZmljIHNlcmlhbGl6YXRpb25cbiAgICBpZiAoc2NoZW1lSGFuZGxlciAmJiBzY2hlbWVIYW5kbGVyLnNlcmlhbGl6ZSkgc2NoZW1lSGFuZGxlci5zZXJpYWxpemUoY29tcG9uZW50cywgb3B0aW9ucyk7XG4gICAgaWYgKGNvbXBvbmVudHMuaG9zdCkge1xuICAgICAgICAvL2lmIGhvc3QgY29tcG9uZW50IGlzIGFuIElQdjYgYWRkcmVzc1xuICAgICAgICBpZiAocHJvdG9jb2wuSVBWNkFERFJFU1MudGVzdChjb21wb25lbnRzLmhvc3QpKSB7fVxuICAgICAgICAvL1RPRE86IG5vcm1hbGl6ZSBJUHY2IGFkZHJlc3MgYXMgcGVyIFJGQyA1OTUyXG5cbiAgICAgICAgLy9pZiBob3N0IGNvbXBvbmVudCBpcyBhIGRvbWFpbiBuYW1lXG4gICAgICAgIGVsc2UgaWYgKG9wdGlvbnMuZG9tYWluSG9zdCB8fCBzY2hlbWVIYW5kbGVyICYmIHNjaGVtZUhhbmRsZXIuZG9tYWluSG9zdCkge1xuICAgICAgICAgICAgICAgIC8vY29udmVydCBJRE4gdmlhIHB1bnljb2RlXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50cy5ob3N0ID0gIW9wdGlvbnMuaXJpID8gcHVueWNvZGUudG9BU0NJSShjb21wb25lbnRzLmhvc3QucmVwbGFjZShwcm90b2NvbC5QQ1RfRU5DT0RFRCwgcGN0RGVjQ2hhcnMpLnRvTG93ZXJDYXNlKCkpIDogcHVueWNvZGUudG9Vbmljb2RlKGNvbXBvbmVudHMuaG9zdCk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRzLmVycm9yID0gY29tcG9uZW50cy5lcnJvciB8fCBcIkhvc3QncyBkb21haW4gbmFtZSBjYW4gbm90IGJlIGNvbnZlcnRlZCB0byBcIiArICghb3B0aW9ucy5pcmkgPyBcIkFTQ0lJXCIgOiBcIlVuaWNvZGVcIikgKyBcIiB2aWEgcHVueWNvZGU6IFwiICsgZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgfVxuICAgIC8vbm9ybWFsaXplIGVuY29kaW5nXG4gICAgX25vcm1hbGl6ZUNvbXBvbmVudEVuY29kaW5nKGNvbXBvbmVudHMsIHByb3RvY29sKTtcbiAgICBpZiAob3B0aW9ucy5yZWZlcmVuY2UgIT09IFwic3VmZml4XCIgJiYgY29tcG9uZW50cy5zY2hlbWUpIHtcbiAgICAgICAgdXJpVG9rZW5zLnB1c2goY29tcG9uZW50cy5zY2hlbWUpO1xuICAgICAgICB1cmlUb2tlbnMucHVzaChcIjpcIik7XG4gICAgfVxuICAgIHZhciBhdXRob3JpdHkgPSBfcmVjb21wb3NlQXV0aG9yaXR5KGNvbXBvbmVudHMsIG9wdGlvbnMpO1xuICAgIGlmIChhdXRob3JpdHkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAob3B0aW9ucy5yZWZlcmVuY2UgIT09IFwic3VmZml4XCIpIHtcbiAgICAgICAgICAgIHVyaVRva2Vucy5wdXNoKFwiLy9cIik7XG4gICAgICAgIH1cbiAgICAgICAgdXJpVG9rZW5zLnB1c2goYXV0aG9yaXR5KTtcbiAgICAgICAgaWYgKGNvbXBvbmVudHMucGF0aCAmJiBjb21wb25lbnRzLnBhdGguY2hhckF0KDApICE9PSBcIi9cIikge1xuICAgICAgICAgICAgdXJpVG9rZW5zLnB1c2goXCIvXCIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChjb21wb25lbnRzLnBhdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB2YXIgcyA9IGNvbXBvbmVudHMucGF0aDtcbiAgICAgICAgaWYgKCFvcHRpb25zLmFic29sdXRlUGF0aCAmJiAoIXNjaGVtZUhhbmRsZXIgfHwgIXNjaGVtZUhhbmRsZXIuYWJzb2x1dGVQYXRoKSkge1xuICAgICAgICAgICAgcyA9IHJlbW92ZURvdFNlZ21lbnRzKHMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhdXRob3JpdHkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcyA9IHMucmVwbGFjZSgvXlxcL1xcLy8sIFwiLyUyRlwiKTsgLy9kb24ndCBhbGxvdyB0aGUgcGF0aCB0byBzdGFydCB3aXRoIFwiLy9cIlxuICAgICAgICB9XG4gICAgICAgIHVyaVRva2Vucy5wdXNoKHMpO1xuICAgIH1cbiAgICBpZiAoY29tcG9uZW50cy5xdWVyeSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHVyaVRva2Vucy5wdXNoKFwiP1wiKTtcbiAgICAgICAgdXJpVG9rZW5zLnB1c2goY29tcG9uZW50cy5xdWVyeSk7XG4gICAgfVxuICAgIGlmIChjb21wb25lbnRzLmZyYWdtZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdXJpVG9rZW5zLnB1c2goXCIjXCIpO1xuICAgICAgICB1cmlUb2tlbnMucHVzaChjb21wb25lbnRzLmZyYWdtZW50KTtcbiAgICB9XG4gICAgcmV0dXJuIHVyaVRva2Vucy5qb2luKFwiXCIpOyAvL21lcmdlIHRva2VucyBpbnRvIGEgc3RyaW5nXG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDb21wb25lbnRzKGJhc2UsIHJlbGF0aXZlKSB7XG4gICAgdmFyIG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IHt9O1xuICAgIHZhciBza2lwTm9ybWFsaXphdGlvbiA9IGFyZ3VtZW50c1szXTtcblxuICAgIHZhciB0YXJnZXQgPSB7fTtcbiAgICBpZiAoIXNraXBOb3JtYWxpemF0aW9uKSB7XG4gICAgICAgIGJhc2UgPSBwYXJzZShzZXJpYWxpemUoYmFzZSwgb3B0aW9ucyksIG9wdGlvbnMpOyAvL25vcm1hbGl6ZSBiYXNlIGNvbXBvbmVudHNcbiAgICAgICAgcmVsYXRpdmUgPSBwYXJzZShzZXJpYWxpemUocmVsYXRpdmUsIG9wdGlvbnMpLCBvcHRpb25zKTsgLy9ub3JtYWxpemUgcmVsYXRpdmUgY29tcG9uZW50c1xuICAgIH1cbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICBpZiAoIW9wdGlvbnMudG9sZXJhbnQgJiYgcmVsYXRpdmUuc2NoZW1lKSB7XG4gICAgICAgIHRhcmdldC5zY2hlbWUgPSByZWxhdGl2ZS5zY2hlbWU7XG4gICAgICAgIC8vdGFyZ2V0LmF1dGhvcml0eSA9IHJlbGF0aXZlLmF1dGhvcml0eTtcbiAgICAgICAgdGFyZ2V0LnVzZXJpbmZvID0gcmVsYXRpdmUudXNlcmluZm87XG4gICAgICAgIHRhcmdldC5ob3N0ID0gcmVsYXRpdmUuaG9zdDtcbiAgICAgICAgdGFyZ2V0LnBvcnQgPSByZWxhdGl2ZS5wb3J0O1xuICAgICAgICB0YXJnZXQucGF0aCA9IHJlbW92ZURvdFNlZ21lbnRzKHJlbGF0aXZlLnBhdGggfHwgXCJcIik7XG4gICAgICAgIHRhcmdldC5xdWVyeSA9IHJlbGF0aXZlLnF1ZXJ5O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChyZWxhdGl2ZS51c2VyaW5mbyAhPT0gdW5kZWZpbmVkIHx8IHJlbGF0aXZlLmhvc3QgIT09IHVuZGVmaW5lZCB8fCByZWxhdGl2ZS5wb3J0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vdGFyZ2V0LmF1dGhvcml0eSA9IHJlbGF0aXZlLmF1dGhvcml0eTtcbiAgICAgICAgICAgIHRhcmdldC51c2VyaW5mbyA9IHJlbGF0aXZlLnVzZXJpbmZvO1xuICAgICAgICAgICAgdGFyZ2V0Lmhvc3QgPSByZWxhdGl2ZS5ob3N0O1xuICAgICAgICAgICAgdGFyZ2V0LnBvcnQgPSByZWxhdGl2ZS5wb3J0O1xuICAgICAgICAgICAgdGFyZ2V0LnBhdGggPSByZW1vdmVEb3RTZWdtZW50cyhyZWxhdGl2ZS5wYXRoIHx8IFwiXCIpO1xuICAgICAgICAgICAgdGFyZ2V0LnF1ZXJ5ID0gcmVsYXRpdmUucXVlcnk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoIXJlbGF0aXZlLnBhdGgpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXQucGF0aCA9IGJhc2UucGF0aDtcbiAgICAgICAgICAgICAgICBpZiAocmVsYXRpdmUucXVlcnkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXQucXVlcnkgPSByZWxhdGl2ZS5xdWVyeTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXQucXVlcnkgPSBiYXNlLnF1ZXJ5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlbGF0aXZlLnBhdGguY2hhckF0KDApID09PSBcIi9cIikge1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXQucGF0aCA9IHJlbW92ZURvdFNlZ21lbnRzKHJlbGF0aXZlLnBhdGgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICgoYmFzZS51c2VyaW5mbyAhPT0gdW5kZWZpbmVkIHx8IGJhc2UuaG9zdCAhPT0gdW5kZWZpbmVkIHx8IGJhc2UucG9ydCAhPT0gdW5kZWZpbmVkKSAmJiAhYmFzZS5wYXRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQucGF0aCA9IFwiL1wiICsgcmVsYXRpdmUucGF0aDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghYmFzZS5wYXRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQucGF0aCA9IHJlbGF0aXZlLnBhdGg7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQucGF0aCA9IGJhc2UucGF0aC5zbGljZSgwLCBiYXNlLnBhdGgubGFzdEluZGV4T2YoXCIvXCIpICsgMSkgKyByZWxhdGl2ZS5wYXRoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldC5wYXRoID0gcmVtb3ZlRG90U2VnbWVudHModGFyZ2V0LnBhdGgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0YXJnZXQucXVlcnkgPSByZWxhdGl2ZS5xdWVyeTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vdGFyZ2V0LmF1dGhvcml0eSA9IGJhc2UuYXV0aG9yaXR5O1xuICAgICAgICAgICAgdGFyZ2V0LnVzZXJpbmZvID0gYmFzZS51c2VyaW5mbztcbiAgICAgICAgICAgIHRhcmdldC5ob3N0ID0gYmFzZS5ob3N0O1xuICAgICAgICAgICAgdGFyZ2V0LnBvcnQgPSBiYXNlLnBvcnQ7XG4gICAgICAgIH1cbiAgICAgICAgdGFyZ2V0LnNjaGVtZSA9IGJhc2Uuc2NoZW1lO1xuICAgIH1cbiAgICB0YXJnZXQuZnJhZ21lbnQgPSByZWxhdGl2ZS5mcmFnbWVudDtcbiAgICByZXR1cm4gdGFyZ2V0O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlKGJhc2VVUkksIHJlbGF0aXZlVVJJLCBvcHRpb25zKSB7XG4gICAgdmFyIHNjaGVtZWxlc3NPcHRpb25zID0gYXNzaWduKHsgc2NoZW1lOiAnbnVsbCcgfSwgb3B0aW9ucyk7XG4gICAgcmV0dXJuIHNlcmlhbGl6ZShyZXNvbHZlQ29tcG9uZW50cyhwYXJzZShiYXNlVVJJLCBzY2hlbWVsZXNzT3B0aW9ucyksIHBhcnNlKHJlbGF0aXZlVVJJLCBzY2hlbWVsZXNzT3B0aW9ucyksIHNjaGVtZWxlc3NPcHRpb25zLCB0cnVlKSwgc2NoZW1lbGVzc09wdGlvbnMpO1xufVxuXG5mdW5jdGlvbiBub3JtYWxpemUodXJpLCBvcHRpb25zKSB7XG4gICAgaWYgKHR5cGVvZiB1cmkgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgdXJpID0gc2VyaWFsaXplKHBhcnNlKHVyaSwgb3B0aW9ucyksIG9wdGlvbnMpO1xuICAgIH0gZWxzZSBpZiAodHlwZU9mKHVyaSkgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgdXJpID0gcGFyc2Uoc2VyaWFsaXplKHVyaSwgb3B0aW9ucyksIG9wdGlvbnMpO1xuICAgIH1cbiAgICByZXR1cm4gdXJpO1xufVxuXG5mdW5jdGlvbiBlcXVhbCh1cmlBLCB1cmlCLCBvcHRpb25zKSB7XG4gICAgaWYgKHR5cGVvZiB1cmlBID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHVyaUEgPSBzZXJpYWxpemUocGFyc2UodXJpQSwgb3B0aW9ucyksIG9wdGlvbnMpO1xuICAgIH0gZWxzZSBpZiAodHlwZU9mKHVyaUEpID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHVyaUEgPSBzZXJpYWxpemUodXJpQSwgb3B0aW9ucyk7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdXJpQiA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICB1cmlCID0gc2VyaWFsaXplKHBhcnNlKHVyaUIsIG9wdGlvbnMpLCBvcHRpb25zKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVPZih1cmlCKSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICB1cmlCID0gc2VyaWFsaXplKHVyaUIsIG9wdGlvbnMpO1xuICAgIH1cbiAgICByZXR1cm4gdXJpQSA9PT0gdXJpQjtcbn1cblxuZnVuY3Rpb24gZXNjYXBlQ29tcG9uZW50KHN0ciwgb3B0aW9ucykge1xuICAgIHJldHVybiBzdHIgJiYgc3RyLnRvU3RyaW5nKCkucmVwbGFjZSghb3B0aW9ucyB8fCAhb3B0aW9ucy5pcmkgPyBVUklfUFJPVE9DT0wuRVNDQVBFIDogSVJJX1BST1RPQ09MLkVTQ0FQRSwgcGN0RW5jQ2hhcik7XG59XG5cbmZ1bmN0aW9uIHVuZXNjYXBlQ29tcG9uZW50KHN0ciwgb3B0aW9ucykge1xuICAgIHJldHVybiBzdHIgJiYgc3RyLnRvU3RyaW5nKCkucmVwbGFjZSghb3B0aW9ucyB8fCAhb3B0aW9ucy5pcmkgPyBVUklfUFJPVE9DT0wuUENUX0VOQ09ERUQgOiBJUklfUFJPVE9DT0wuUENUX0VOQ09ERUQsIHBjdERlY0NoYXJzKTtcbn1cblxudmFyIGhhbmRsZXIgPSB7XG4gICAgc2NoZW1lOiBcImh0dHBcIixcbiAgICBkb21haW5Ib3N0OiB0cnVlLFxuICAgIHBhcnNlOiBmdW5jdGlvbiBwYXJzZShjb21wb25lbnRzLCBvcHRpb25zKSB7XG4gICAgICAgIC8vcmVwb3J0IG1pc3NpbmcgaG9zdFxuICAgICAgICBpZiAoIWNvbXBvbmVudHMuaG9zdCkge1xuICAgICAgICAgICAgY29tcG9uZW50cy5lcnJvciA9IGNvbXBvbmVudHMuZXJyb3IgfHwgXCJIVFRQIFVSSXMgbXVzdCBoYXZlIGEgaG9zdC5cIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29tcG9uZW50cztcbiAgICB9LFxuICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gc2VyaWFsaXplKGNvbXBvbmVudHMsIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHNlY3VyZSA9IFN0cmluZyhjb21wb25lbnRzLnNjaGVtZSkudG9Mb3dlckNhc2UoKSA9PT0gXCJodHRwc1wiO1xuICAgICAgICAvL25vcm1hbGl6ZSB0aGUgZGVmYXVsdCBwb3J0XG4gICAgICAgIGlmIChjb21wb25lbnRzLnBvcnQgPT09IChzZWN1cmUgPyA0NDMgOiA4MCkgfHwgY29tcG9uZW50cy5wb3J0ID09PSBcIlwiKSB7XG4gICAgICAgICAgICBjb21wb25lbnRzLnBvcnQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLy9ub3JtYWxpemUgdGhlIGVtcHR5IHBhdGhcbiAgICAgICAgaWYgKCFjb21wb25lbnRzLnBhdGgpIHtcbiAgICAgICAgICAgIGNvbXBvbmVudHMucGF0aCA9IFwiL1wiO1xuICAgICAgICB9XG4gICAgICAgIC8vTk9URTogV2UgZG8gbm90IHBhcnNlIHF1ZXJ5IHN0cmluZ3MgZm9yIEhUVFAgVVJJc1xuICAgICAgICAvL2FzIFdXVyBGb3JtIFVybCBFbmNvZGVkIHF1ZXJ5IHN0cmluZ3MgYXJlIHBhcnQgb2YgdGhlIEhUTUw0KyBzcGVjLFxuICAgICAgICAvL2FuZCBub3QgdGhlIEhUVFAgc3BlYy5cbiAgICAgICAgcmV0dXJuIGNvbXBvbmVudHM7XG4gICAgfVxufTtcblxudmFyIGhhbmRsZXIkMSA9IHtcbiAgICBzY2hlbWU6IFwiaHR0cHNcIixcbiAgICBkb21haW5Ib3N0OiBoYW5kbGVyLmRvbWFpbkhvc3QsXG4gICAgcGFyc2U6IGhhbmRsZXIucGFyc2UsXG4gICAgc2VyaWFsaXplOiBoYW5kbGVyLnNlcmlhbGl6ZVxufTtcblxuZnVuY3Rpb24gaXNTZWN1cmUod3NDb21wb25lbnRzKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB3c0NvbXBvbmVudHMuc2VjdXJlID09PSAnYm9vbGVhbicgPyB3c0NvbXBvbmVudHMuc2VjdXJlIDogU3RyaW5nKHdzQ29tcG9uZW50cy5zY2hlbWUpLnRvTG93ZXJDYXNlKCkgPT09IFwid3NzXCI7XG59XG4vL1JGQyA2NDU1XG52YXIgaGFuZGxlciQyID0ge1xuICAgIHNjaGVtZTogXCJ3c1wiLFxuICAgIGRvbWFpbkhvc3Q6IHRydWUsXG4gICAgcGFyc2U6IGZ1bmN0aW9uIHBhcnNlKGNvbXBvbmVudHMsIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHdzQ29tcG9uZW50cyA9IGNvbXBvbmVudHM7XG4gICAgICAgIC8vaW5kaWNhdGUgaWYgdGhlIHNlY3VyZSBmbGFnIGlzIHNldFxuICAgICAgICB3c0NvbXBvbmVudHMuc2VjdXJlID0gaXNTZWN1cmUod3NDb21wb25lbnRzKTtcbiAgICAgICAgLy9jb25zdHJ1Y3QgcmVzb3VjZSBuYW1lXG4gICAgICAgIHdzQ29tcG9uZW50cy5yZXNvdXJjZU5hbWUgPSAod3NDb21wb25lbnRzLnBhdGggfHwgJy8nKSArICh3c0NvbXBvbmVudHMucXVlcnkgPyAnPycgKyB3c0NvbXBvbmVudHMucXVlcnkgOiAnJyk7XG4gICAgICAgIHdzQ29tcG9uZW50cy5wYXRoID0gdW5kZWZpbmVkO1xuICAgICAgICB3c0NvbXBvbmVudHMucXVlcnkgPSB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiB3c0NvbXBvbmVudHM7XG4gICAgfSxcbiAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIHNlcmlhbGl6ZSh3c0NvbXBvbmVudHMsIG9wdGlvbnMpIHtcbiAgICAgICAgLy9ub3JtYWxpemUgdGhlIGRlZmF1bHQgcG9ydFxuICAgICAgICBpZiAod3NDb21wb25lbnRzLnBvcnQgPT09IChpc1NlY3VyZSh3c0NvbXBvbmVudHMpID8gNDQzIDogODApIHx8IHdzQ29tcG9uZW50cy5wb3J0ID09PSBcIlwiKSB7XG4gICAgICAgICAgICB3c0NvbXBvbmVudHMucG9ydCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICAvL2Vuc3VyZSBzY2hlbWUgbWF0Y2hlcyBzZWN1cmUgZmxhZ1xuICAgICAgICBpZiAodHlwZW9mIHdzQ29tcG9uZW50cy5zZWN1cmUgPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgd3NDb21wb25lbnRzLnNjaGVtZSA9IHdzQ29tcG9uZW50cy5zZWN1cmUgPyAnd3NzJyA6ICd3cyc7XG4gICAgICAgICAgICB3c0NvbXBvbmVudHMuc2VjdXJlID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIC8vcmVjb25zdHJ1Y3QgcGF0aCBmcm9tIHJlc291cmNlIG5hbWVcbiAgICAgICAgaWYgKHdzQ29tcG9uZW50cy5yZXNvdXJjZU5hbWUpIHtcbiAgICAgICAgICAgIHZhciBfd3NDb21wb25lbnRzJHJlc291cmMgPSB3c0NvbXBvbmVudHMucmVzb3VyY2VOYW1lLnNwbGl0KCc/JyksXG4gICAgICAgICAgICAgICAgX3dzQ29tcG9uZW50cyRyZXNvdXJjMiA9IHNsaWNlZFRvQXJyYXkoX3dzQ29tcG9uZW50cyRyZXNvdXJjLCAyKSxcbiAgICAgICAgICAgICAgICBwYXRoID0gX3dzQ29tcG9uZW50cyRyZXNvdXJjMlswXSxcbiAgICAgICAgICAgICAgICBxdWVyeSA9IF93c0NvbXBvbmVudHMkcmVzb3VyYzJbMV07XG5cbiAgICAgICAgICAgIHdzQ29tcG9uZW50cy5wYXRoID0gcGF0aCAmJiBwYXRoICE9PSAnLycgPyBwYXRoIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgd3NDb21wb25lbnRzLnF1ZXJ5ID0gcXVlcnk7XG4gICAgICAgICAgICB3c0NvbXBvbmVudHMucmVzb3VyY2VOYW1lID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIC8vZm9yYmlkIGZyYWdtZW50IGNvbXBvbmVudFxuICAgICAgICB3c0NvbXBvbmVudHMuZnJhZ21lbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiB3c0NvbXBvbmVudHM7XG4gICAgfVxufTtcblxudmFyIGhhbmRsZXIkMyA9IHtcbiAgICBzY2hlbWU6IFwid3NzXCIsXG4gICAgZG9tYWluSG9zdDogaGFuZGxlciQyLmRvbWFpbkhvc3QsXG4gICAgcGFyc2U6IGhhbmRsZXIkMi5wYXJzZSxcbiAgICBzZXJpYWxpemU6IGhhbmRsZXIkMi5zZXJpYWxpemVcbn07XG5cbnZhciBPID0ge307XG52YXIgaXNJUkkgPSB0cnVlO1xuLy9SRkMgMzk4NlxudmFyIFVOUkVTRVJWRUQkJCA9IFwiW0EtWmEtejAtOVxcXFwtXFxcXC5cXFxcX1xcXFx+XCIgKyAoaXNJUkkgPyBcIlxcXFx4QTAtXFxcXHUyMDBEXFxcXHUyMDEwLVxcXFx1MjAyOVxcXFx1MjAyRi1cXFxcdUQ3RkZcXFxcdUY5MDAtXFxcXHVGRENGXFxcXHVGREYwLVxcXFx1RkZFRlwiIDogXCJcIikgKyBcIl1cIjtcbnZhciBIRVhESUckJCA9IFwiWzAtOUEtRmEtZl1cIjsgLy9jYXNlLWluc2Vuc2l0aXZlXG52YXIgUENUX0VOQ09ERUQkID0gc3ViZXhwKHN1YmV4cChcIiVbRUZlZl1cIiArIEhFWERJRyQkICsgXCIlXCIgKyBIRVhESUckJCArIEhFWERJRyQkICsgXCIlXCIgKyBIRVhESUckJCArIEhFWERJRyQkKSArIFwifFwiICsgc3ViZXhwKFwiJVs4OUEtRmEtZl1cIiArIEhFWERJRyQkICsgXCIlXCIgKyBIRVhESUckJCArIEhFWERJRyQkKSArIFwifFwiICsgc3ViZXhwKFwiJVwiICsgSEVYRElHJCQgKyBIRVhESUckJCkpOyAvL2V4cGFuZGVkXG4vL1JGQyA1MzIyLCBleGNlcHQgdGhlc2Ugc3ltYm9scyBhcyBwZXIgUkZDIDYwNjg6IEAgOiAvID8gIyBbIF0gJiA7ID1cbi8vY29uc3QgQVRFWFQkJCA9IFwiW0EtWmEtejAtOVxcXFwhXFxcXCNcXFxcJFxcXFwlXFxcXCZcXFxcJ1xcXFwqXFxcXCtcXFxcLVxcXFwvXFxcXD1cXFxcP1xcXFxeXFxcXF9cXFxcYFxcXFx7XFxcXHxcXFxcfVxcXFx+XVwiO1xuLy9jb25zdCBXU1AkJCA9IFwiW1xcXFx4MjBcXFxceDA5XVwiO1xuLy9jb25zdCBPQlNfUVRFWFQkJCA9IFwiW1xcXFx4MDEtXFxcXHgwOFxcXFx4MEJcXFxceDBDXFxcXHgwRS1cXFxceDFGXFxcXHg3Rl1cIjsgIC8vKCVkMS04IC8gJWQxMS0xMiAvICVkMTQtMzEgLyAlZDEyNylcbi8vY29uc3QgUVRFWFQkJCA9IG1lcmdlKFwiW1xcXFx4MjFcXFxceDIzLVxcXFx4NUJcXFxceDVELVxcXFx4N0VdXCIsIE9CU19RVEVYVCQkKTsgIC8vJWQzMyAvICVkMzUtOTEgLyAlZDkzLTEyNiAvIG9icy1xdGV4dFxuLy9jb25zdCBWQ0hBUiQkID0gXCJbXFxcXHgyMS1cXFxceDdFXVwiO1xuLy9jb25zdCBXU1AkJCA9IFwiW1xcXFx4MjBcXFxceDA5XVwiO1xuLy9jb25zdCBPQlNfUVAkID0gc3ViZXhwKFwiXFxcXFxcXFxcIiArIG1lcmdlKFwiW1xcXFx4MDBcXFxceDBEXFxcXHgwQV1cIiwgT0JTX1FURVhUJCQpKTsgIC8vJWQwIC8gQ1IgLyBMRiAvIG9icy1xdGV4dFxuLy9jb25zdCBGV1MkID0gc3ViZXhwKHN1YmV4cChXU1AkJCArIFwiKlwiICsgXCJcXFxceDBEXFxcXHgwQVwiKSArIFwiP1wiICsgV1NQJCQgKyBcIitcIik7XG4vL2NvbnN0IFFVT1RFRF9QQUlSJCA9IHN1YmV4cChzdWJleHAoXCJcXFxcXFxcXFwiICsgc3ViZXhwKFZDSEFSJCQgKyBcInxcIiArIFdTUCQkKSkgKyBcInxcIiArIE9CU19RUCQpO1xuLy9jb25zdCBRVU9URURfU1RSSU5HJCA9IHN1YmV4cCgnXFxcXFwiJyArIHN1YmV4cChGV1MkICsgXCI/XCIgKyBRQ09OVEVOVCQpICsgXCIqXCIgKyBGV1MkICsgXCI/XCIgKyAnXFxcXFwiJyk7XG52YXIgQVRFWFQkJCA9IFwiW0EtWmEtejAtOVxcXFwhXFxcXCRcXFxcJVxcXFwnXFxcXCpcXFxcK1xcXFwtXFxcXF5cXFxcX1xcXFxgXFxcXHtcXFxcfFxcXFx9XFxcXH5dXCI7XG52YXIgUVRFWFQkJCA9IFwiW1xcXFwhXFxcXCRcXFxcJVxcXFwnXFxcXChcXFxcKVxcXFwqXFxcXCtcXFxcLFxcXFwtXFxcXC4wLTlcXFxcPFxcXFw+QS1aXFxcXHg1RS1cXFxceDdFXVwiO1xudmFyIFZDSEFSJCQgPSBtZXJnZShRVEVYVCQkLCBcIltcXFxcXFxcIlxcXFxcXFxcXVwiKTtcbnZhciBTT01FX0RFTElNUyQkID0gXCJbXFxcXCFcXFxcJFxcXFwnXFxcXChcXFxcKVxcXFwqXFxcXCtcXFxcLFxcXFw7XFxcXDpcXFxcQF1cIjtcbnZhciBVTlJFU0VSVkVEID0gbmV3IFJlZ0V4cChVTlJFU0VSVkVEJCQsIFwiZ1wiKTtcbnZhciBQQ1RfRU5DT0RFRCA9IG5ldyBSZWdFeHAoUENUX0VOQ09ERUQkLCBcImdcIik7XG52YXIgTk9UX0xPQ0FMX1BBUlQgPSBuZXcgUmVnRXhwKG1lcmdlKFwiW15dXCIsIEFURVhUJCQsIFwiW1xcXFwuXVwiLCAnW1xcXFxcIl0nLCBWQ0hBUiQkKSwgXCJnXCIpO1xudmFyIE5PVF9IRk5BTUUgPSBuZXcgUmVnRXhwKG1lcmdlKFwiW15dXCIsIFVOUkVTRVJWRUQkJCwgU09NRV9ERUxJTVMkJCksIFwiZ1wiKTtcbnZhciBOT1RfSEZWQUxVRSA9IE5PVF9IRk5BTUU7XG5mdW5jdGlvbiBkZWNvZGVVbnJlc2VydmVkKHN0cikge1xuICAgIHZhciBkZWNTdHIgPSBwY3REZWNDaGFycyhzdHIpO1xuICAgIHJldHVybiAhZGVjU3RyLm1hdGNoKFVOUkVTRVJWRUQpID8gc3RyIDogZGVjU3RyO1xufVxudmFyIGhhbmRsZXIkNCA9IHtcbiAgICBzY2hlbWU6IFwibWFpbHRvXCIsXG4gICAgcGFyc2U6IGZ1bmN0aW9uIHBhcnNlJCQxKGNvbXBvbmVudHMsIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIG1haWx0b0NvbXBvbmVudHMgPSBjb21wb25lbnRzO1xuICAgICAgICB2YXIgdG8gPSBtYWlsdG9Db21wb25lbnRzLnRvID0gbWFpbHRvQ29tcG9uZW50cy5wYXRoID8gbWFpbHRvQ29tcG9uZW50cy5wYXRoLnNwbGl0KFwiLFwiKSA6IFtdO1xuICAgICAgICBtYWlsdG9Db21wb25lbnRzLnBhdGggPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChtYWlsdG9Db21wb25lbnRzLnF1ZXJ5KSB7XG4gICAgICAgICAgICB2YXIgdW5rbm93bkhlYWRlcnMgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBoZWFkZXJzID0ge307XG4gICAgICAgICAgICB2YXIgaGZpZWxkcyA9IG1haWx0b0NvbXBvbmVudHMucXVlcnkuc3BsaXQoXCImXCIpO1xuICAgICAgICAgICAgZm9yICh2YXIgeCA9IDAsIHhsID0gaGZpZWxkcy5sZW5ndGg7IHggPCB4bDsgKyt4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGhmaWVsZCA9IGhmaWVsZHNbeF0uc3BsaXQoXCI9XCIpO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoaGZpZWxkWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0b1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRvQWRkcnMgPSBoZmllbGRbMV0uc3BsaXQoXCIsXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX3ggPSAwLCBfeGwgPSB0b0FkZHJzLmxlbmd0aDsgX3ggPCBfeGw7ICsrX3gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0by5wdXNoKHRvQWRkcnNbX3hdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwic3ViamVjdFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgbWFpbHRvQ29tcG9uZW50cy5zdWJqZWN0ID0gdW5lc2NhcGVDb21wb25lbnQoaGZpZWxkWzFdLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiYm9keVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgbWFpbHRvQ29tcG9uZW50cy5ib2R5ID0gdW5lc2NhcGVDb21wb25lbnQoaGZpZWxkWzFdLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgdW5rbm93bkhlYWRlcnMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyc1t1bmVzY2FwZUNvbXBvbmVudChoZmllbGRbMF0sIG9wdGlvbnMpXSA9IHVuZXNjYXBlQ29tcG9uZW50KGhmaWVsZFsxXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodW5rbm93bkhlYWRlcnMpIG1haWx0b0NvbXBvbmVudHMuaGVhZGVycyA9IGhlYWRlcnM7XG4gICAgICAgIH1cbiAgICAgICAgbWFpbHRvQ29tcG9uZW50cy5xdWVyeSA9IHVuZGVmaW5lZDtcbiAgICAgICAgZm9yICh2YXIgX3gyID0gMCwgX3hsMiA9IHRvLmxlbmd0aDsgX3gyIDwgX3hsMjsgKytfeDIpIHtcbiAgICAgICAgICAgIHZhciBhZGRyID0gdG9bX3gyXS5zcGxpdChcIkBcIik7XG4gICAgICAgICAgICBhZGRyWzBdID0gdW5lc2NhcGVDb21wb25lbnQoYWRkclswXSk7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMudW5pY29kZVN1cHBvcnQpIHtcbiAgICAgICAgICAgICAgICAvL2NvbnZlcnQgVW5pY29kZSBJRE4gLT4gQVNDSUkgSUROXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgYWRkclsxXSA9IHB1bnljb2RlLnRvQVNDSUkodW5lc2NhcGVDb21wb25lbnQoYWRkclsxXSwgb3B0aW9ucykudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBtYWlsdG9Db21wb25lbnRzLmVycm9yID0gbWFpbHRvQ29tcG9uZW50cy5lcnJvciB8fCBcIkVtYWlsIGFkZHJlc3MncyBkb21haW4gbmFtZSBjYW4gbm90IGJlIGNvbnZlcnRlZCB0byBBU0NJSSB2aWEgcHVueWNvZGU6IFwiICsgZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFkZHJbMV0gPSB1bmVzY2FwZUNvbXBvbmVudChhZGRyWzFdLCBvcHRpb25zKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdG9bX3gyXSA9IGFkZHIuam9pbihcIkBcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1haWx0b0NvbXBvbmVudHM7XG4gICAgfSxcbiAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIHNlcmlhbGl6ZSQkMShtYWlsdG9Db21wb25lbnRzLCBvcHRpb25zKSB7XG4gICAgICAgIHZhciBjb21wb25lbnRzID0gbWFpbHRvQ29tcG9uZW50cztcbiAgICAgICAgdmFyIHRvID0gdG9BcnJheShtYWlsdG9Db21wb25lbnRzLnRvKTtcbiAgICAgICAgaWYgKHRvKSB7XG4gICAgICAgICAgICBmb3IgKHZhciB4ID0gMCwgeGwgPSB0by5sZW5ndGg7IHggPCB4bDsgKyt4KSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvQWRkciA9IFN0cmluZyh0b1t4XSk7XG4gICAgICAgICAgICAgICAgdmFyIGF0SWR4ID0gdG9BZGRyLmxhc3RJbmRleE9mKFwiQFwiKTtcbiAgICAgICAgICAgICAgICB2YXIgbG9jYWxQYXJ0ID0gdG9BZGRyLnNsaWNlKDAsIGF0SWR4KS5yZXBsYWNlKFBDVF9FTkNPREVELCBkZWNvZGVVbnJlc2VydmVkKS5yZXBsYWNlKFBDVF9FTkNPREVELCB0b1VwcGVyQ2FzZSkucmVwbGFjZShOT1RfTE9DQUxfUEFSVCwgcGN0RW5jQ2hhcik7XG4gICAgICAgICAgICAgICAgdmFyIGRvbWFpbiA9IHRvQWRkci5zbGljZShhdElkeCArIDEpO1xuICAgICAgICAgICAgICAgIC8vY29udmVydCBJRE4gdmlhIHB1bnljb2RlXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgZG9tYWluID0gIW9wdGlvbnMuaXJpID8gcHVueWNvZGUudG9BU0NJSSh1bmVzY2FwZUNvbXBvbmVudChkb21haW4sIG9wdGlvbnMpLnRvTG93ZXJDYXNlKCkpIDogcHVueWNvZGUudG9Vbmljb2RlKGRvbWFpbik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRzLmVycm9yID0gY29tcG9uZW50cy5lcnJvciB8fCBcIkVtYWlsIGFkZHJlc3MncyBkb21haW4gbmFtZSBjYW4gbm90IGJlIGNvbnZlcnRlZCB0byBcIiArICghb3B0aW9ucy5pcmkgPyBcIkFTQ0lJXCIgOiBcIlVuaWNvZGVcIikgKyBcIiB2aWEgcHVueWNvZGU6IFwiICsgZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdG9beF0gPSBsb2NhbFBhcnQgKyBcIkBcIiArIGRvbWFpbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbXBvbmVudHMucGF0aCA9IHRvLmpvaW4oXCIsXCIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBoZWFkZXJzID0gbWFpbHRvQ29tcG9uZW50cy5oZWFkZXJzID0gbWFpbHRvQ29tcG9uZW50cy5oZWFkZXJzIHx8IHt9O1xuICAgICAgICBpZiAobWFpbHRvQ29tcG9uZW50cy5zdWJqZWN0KSBoZWFkZXJzW1wic3ViamVjdFwiXSA9IG1haWx0b0NvbXBvbmVudHMuc3ViamVjdDtcbiAgICAgICAgaWYgKG1haWx0b0NvbXBvbmVudHMuYm9keSkgaGVhZGVyc1tcImJvZHlcIl0gPSBtYWlsdG9Db21wb25lbnRzLmJvZHk7XG4gICAgICAgIHZhciBmaWVsZHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgbmFtZSBpbiBoZWFkZXJzKSB7XG4gICAgICAgICAgICBpZiAoaGVhZGVyc1tuYW1lXSAhPT0gT1tuYW1lXSkge1xuICAgICAgICAgICAgICAgIGZpZWxkcy5wdXNoKG5hbWUucmVwbGFjZShQQ1RfRU5DT0RFRCwgZGVjb2RlVW5yZXNlcnZlZCkucmVwbGFjZShQQ1RfRU5DT0RFRCwgdG9VcHBlckNhc2UpLnJlcGxhY2UoTk9UX0hGTkFNRSwgcGN0RW5jQ2hhcikgKyBcIj1cIiArIGhlYWRlcnNbbmFtZV0ucmVwbGFjZShQQ1RfRU5DT0RFRCwgZGVjb2RlVW5yZXNlcnZlZCkucmVwbGFjZShQQ1RfRU5DT0RFRCwgdG9VcHBlckNhc2UpLnJlcGxhY2UoTk9UX0hGVkFMVUUsIHBjdEVuY0NoYXIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZmllbGRzLmxlbmd0aCkge1xuICAgICAgICAgICAgY29tcG9uZW50cy5xdWVyeSA9IGZpZWxkcy5qb2luKFwiJlwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29tcG9uZW50cztcbiAgICB9XG59O1xuXG52YXIgVVJOX1BBUlNFID0gL14oW15cXDpdKylcXDooLiopLztcbi8vUkZDIDIxNDFcbnZhciBoYW5kbGVyJDUgPSB7XG4gICAgc2NoZW1lOiBcInVyblwiLFxuICAgIHBhcnNlOiBmdW5jdGlvbiBwYXJzZSQkMShjb21wb25lbnRzLCBvcHRpb25zKSB7XG4gICAgICAgIHZhciBtYXRjaGVzID0gY29tcG9uZW50cy5wYXRoICYmIGNvbXBvbmVudHMucGF0aC5tYXRjaChVUk5fUEFSU0UpO1xuICAgICAgICB2YXIgdXJuQ29tcG9uZW50cyA9IGNvbXBvbmVudHM7XG4gICAgICAgIGlmIChtYXRjaGVzKSB7XG4gICAgICAgICAgICB2YXIgc2NoZW1lID0gb3B0aW9ucy5zY2hlbWUgfHwgdXJuQ29tcG9uZW50cy5zY2hlbWUgfHwgXCJ1cm5cIjtcbiAgICAgICAgICAgIHZhciBuaWQgPSBtYXRjaGVzWzFdLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICB2YXIgbnNzID0gbWF0Y2hlc1syXTtcbiAgICAgICAgICAgIHZhciB1cm5TY2hlbWUgPSBzY2hlbWUgKyBcIjpcIiArIChvcHRpb25zLm5pZCB8fCBuaWQpO1xuICAgICAgICAgICAgdmFyIHNjaGVtZUhhbmRsZXIgPSBTQ0hFTUVTW3VyblNjaGVtZV07XG4gICAgICAgICAgICB1cm5Db21wb25lbnRzLm5pZCA9IG5pZDtcbiAgICAgICAgICAgIHVybkNvbXBvbmVudHMubnNzID0gbnNzO1xuICAgICAgICAgICAgdXJuQ29tcG9uZW50cy5wYXRoID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKHNjaGVtZUhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgICB1cm5Db21wb25lbnRzID0gc2NoZW1lSGFuZGxlci5wYXJzZSh1cm5Db21wb25lbnRzLCBvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHVybkNvbXBvbmVudHMuZXJyb3IgPSB1cm5Db21wb25lbnRzLmVycm9yIHx8IFwiVVJOIGNhbiBub3QgYmUgcGFyc2VkLlwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1cm5Db21wb25lbnRzO1xuICAgIH0sXG4gICAgc2VyaWFsaXplOiBmdW5jdGlvbiBzZXJpYWxpemUkJDEodXJuQ29tcG9uZW50cywgb3B0aW9ucykge1xuICAgICAgICB2YXIgc2NoZW1lID0gb3B0aW9ucy5zY2hlbWUgfHwgdXJuQ29tcG9uZW50cy5zY2hlbWUgfHwgXCJ1cm5cIjtcbiAgICAgICAgdmFyIG5pZCA9IHVybkNvbXBvbmVudHMubmlkO1xuICAgICAgICB2YXIgdXJuU2NoZW1lID0gc2NoZW1lICsgXCI6XCIgKyAob3B0aW9ucy5uaWQgfHwgbmlkKTtcbiAgICAgICAgdmFyIHNjaGVtZUhhbmRsZXIgPSBTQ0hFTUVTW3VyblNjaGVtZV07XG4gICAgICAgIGlmIChzY2hlbWVIYW5kbGVyKSB7XG4gICAgICAgICAgICB1cm5Db21wb25lbnRzID0gc2NoZW1lSGFuZGxlci5zZXJpYWxpemUodXJuQ29tcG9uZW50cywgb3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHVyaUNvbXBvbmVudHMgPSB1cm5Db21wb25lbnRzO1xuICAgICAgICB2YXIgbnNzID0gdXJuQ29tcG9uZW50cy5uc3M7XG4gICAgICAgIHVyaUNvbXBvbmVudHMucGF0aCA9IChuaWQgfHwgb3B0aW9ucy5uaWQpICsgXCI6XCIgKyBuc3M7XG4gICAgICAgIHJldHVybiB1cmlDb21wb25lbnRzO1xuICAgIH1cbn07XG5cbnZhciBVVUlEID0gL15bMC05QS1GYS1mXXs4fSg/OlxcLVswLTlBLUZhLWZdezR9KXszfVxcLVswLTlBLUZhLWZdezEyfSQvO1xuLy9SRkMgNDEyMlxudmFyIGhhbmRsZXIkNiA9IHtcbiAgICBzY2hlbWU6IFwidXJuOnV1aWRcIixcbiAgICBwYXJzZTogZnVuY3Rpb24gcGFyc2UodXJuQ29tcG9uZW50cywgb3B0aW9ucykge1xuICAgICAgICB2YXIgdXVpZENvbXBvbmVudHMgPSB1cm5Db21wb25lbnRzO1xuICAgICAgICB1dWlkQ29tcG9uZW50cy51dWlkID0gdXVpZENvbXBvbmVudHMubnNzO1xuICAgICAgICB1dWlkQ29tcG9uZW50cy5uc3MgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmICghb3B0aW9ucy50b2xlcmFudCAmJiAoIXV1aWRDb21wb25lbnRzLnV1aWQgfHwgIXV1aWRDb21wb25lbnRzLnV1aWQubWF0Y2goVVVJRCkpKSB7XG4gICAgICAgICAgICB1dWlkQ29tcG9uZW50cy5lcnJvciA9IHV1aWRDb21wb25lbnRzLmVycm9yIHx8IFwiVVVJRCBpcyBub3QgdmFsaWQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHV1aWRDb21wb25lbnRzO1xuICAgIH0sXG4gICAgc2VyaWFsaXplOiBmdW5jdGlvbiBzZXJpYWxpemUodXVpZENvbXBvbmVudHMsIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHVybkNvbXBvbmVudHMgPSB1dWlkQ29tcG9uZW50cztcbiAgICAgICAgLy9ub3JtYWxpemUgVVVJRFxuICAgICAgICB1cm5Db21wb25lbnRzLm5zcyA9ICh1dWlkQ29tcG9uZW50cy51dWlkIHx8IFwiXCIpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHJldHVybiB1cm5Db21wb25lbnRzO1xuICAgIH1cbn07XG5cblNDSEVNRVNbaGFuZGxlci5zY2hlbWVdID0gaGFuZGxlcjtcblNDSEVNRVNbaGFuZGxlciQxLnNjaGVtZV0gPSBoYW5kbGVyJDE7XG5TQ0hFTUVTW2hhbmRsZXIkMi5zY2hlbWVdID0gaGFuZGxlciQyO1xuU0NIRU1FU1toYW5kbGVyJDMuc2NoZW1lXSA9IGhhbmRsZXIkMztcblNDSEVNRVNbaGFuZGxlciQ0LnNjaGVtZV0gPSBoYW5kbGVyJDQ7XG5TQ0hFTUVTW2hhbmRsZXIkNS5zY2hlbWVdID0gaGFuZGxlciQ1O1xuU0NIRU1FU1toYW5kbGVyJDYuc2NoZW1lXSA9IGhhbmRsZXIkNjtcblxuZXhwb3J0cy5TQ0hFTUVTID0gU0NIRU1FUztcbmV4cG9ydHMucGN0RW5jQ2hhciA9IHBjdEVuY0NoYXI7XG5leHBvcnRzLnBjdERlY0NoYXJzID0gcGN0RGVjQ2hhcnM7XG5leHBvcnRzLnBhcnNlID0gcGFyc2U7XG5leHBvcnRzLnJlbW92ZURvdFNlZ21lbnRzID0gcmVtb3ZlRG90U2VnbWVudHM7XG5leHBvcnRzLnNlcmlhbGl6ZSA9IHNlcmlhbGl6ZTtcbmV4cG9ydHMucmVzb2x2ZUNvbXBvbmVudHMgPSByZXNvbHZlQ29tcG9uZW50cztcbmV4cG9ydHMucmVzb2x2ZSA9IHJlc29sdmU7XG5leHBvcnRzLm5vcm1hbGl6ZSA9IG5vcm1hbGl6ZTtcbmV4cG9ydHMuZXF1YWwgPSBlcXVhbDtcbmV4cG9ydHMuZXNjYXBlQ29tcG9uZW50ID0gZXNjYXBlQ29tcG9uZW50O1xuZXhwb3J0cy51bmVzY2FwZUNvbXBvbmVudCA9IHVuZXNjYXBlQ29tcG9uZW50O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dXJpLmFsbC5qcy5tYXBcbiJdfQ==
diff --git a/utilities/lambdaResponseValidator/src/LexCodeHookResponseSchema.json b/utilities/lambdaResponseValidator/src/LexCodeHookResponseSchema.json
new file mode 100644
index 0000000..38d5ef0
--- /dev/null
+++ b/utilities/lambdaResponseValidator/src/LexCodeHookResponseSchema.json
@@ -0,0 +1,457 @@
+{
+ "$ref": "#/definitions/LexCodeHookResponse",
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "definitions": {
+ "ActiveContext": {
+ "additionalProperties": false,
+ "properties": {
+ "contextAttributes": {
+ "additionalProperties": {
+ "type": "string"
+ },
+ "description": "A list of contexts active for the request. A context can be activated when a previous intent is fulfilled, or by including the context in the request.
If you don't specify a list of contexts, Amazon Lex V2 will use the current list of contexts for the session. If you specify an empty list, all contexts for the session are cleared.
",
+ "type": "object"
+ },
+ "name": {
+ "description": "The name of the context.
",
+ "type": "string"
+ },
+ "timeToLive": {
+ "$ref": "#/definitions/ActiveContextTimeToLive",
+ "description": "Indicates the number of turns or seconds that the context is active. Once the time to live expires, the context is no longer returned in a response.
"
+ }
+ },
+ "required": [
+ "name",
+ "timeToLive"
+ ],
+ "type": "object"
+ },
+ "ActiveContextTimeToLive": {
+ "additionalProperties": false,
+ "properties": {
+ "timeToLiveInSeconds": {
+ "description": "The number of seconds that the context is active. You can specify between 5 and 86400 seconds (24 hours).
",
+ "type": "number"
+ },
+ "turnsToLive": {
+ "description": "The number of turns that the context is active. You can specify up to 20 turns. Each request and response from the bot is a turn.
",
+ "type": "number"
+ }
+ },
+ "required": [
+ "turnsToLive",
+ "timeToLiveInSeconds"
+ ],
+ "type": "object"
+ },
+ "Attributes": {
+ "additionalProperties": {
+ "type": "string"
+ },
+ "description": "Map of key/value pairs",
+ "type": "object"
+ },
+ "Button": {
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "description": "The text that is displayed on the button.
",
+ "type": "string"
+ },
+ "value": {
+ "description": "The value returned to Amazon Lex V2 when a user chooses the button.
",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "ConfirmationState": {
+ "enum": [
+ "Confirmed",
+ "Denied",
+ "None"
+ ],
+ "type": "string"
+ },
+ "DialogAction": {
+ "additionalProperties": false,
+ "properties": {
+ "slotElicitationStyle": {
+ "$ref": "#/definitions/StyleType",
+ "description": "Configures the slot to use spell-by-letter or spell-by-word style. When you use a style on a slot, users can spell out their input to make it clear to your bot.
For more information, see Using spelling to enter slot values .
"
+ },
+ "slotToElicit": {
+ "description": "The name of the slot that should be elicited from the user. Required if the type of dialogAction is ElicitSlot
",
+ "type": "string"
+ },
+ "subSlotToElicit": {
+ "$ref": "#/definitions/ElicitSubSlot",
+ "description": "The name of the constituent sub slot of the composite slot specified in slotToElicit that should be elicited from the user.
"
+ },
+ "type": {
+ "$ref": "#/definitions/DialogActionType",
+ "description": "The next action that the bot should take in its interaction with the user. The possible values are:
Close
- Indicates that there will not be a response from the user. For example, the statement \"Your order has been placed\" does not require a response.
ConfirmIntent
- The next action is asking the user if the intent is complete and ready to be fulfilled. This is a yes/no question such as \"Place the order?\"
Delegate
- The next action is determined by Amazon Lex V2.
ElicitIntent
- The next action is to elicit an intent from the user.
ElicitSlot
- The next action is to elicit a slot value from the user.
"
+ }
+ },
+ "required": [
+ "type"
+ ],
+ "if": {
+ "anyOf": [
+ {
+ "properties": {
+ "type": {
+ "const": "ElicitSlot"
+ }
+ }
+ }
+ ]
+ },
+ "then": {
+ "required": [
+ "slotToElicit"
+ ],
+ "properties": {
+ "slotToElicit": {
+ "minLength": 1
+ }
+ }
+ },
+ "type": "object"
+ },
+ "DialogActionType": {
+ "enum": [
+ "Close",
+ "ConfirmIntent",
+ "Delegate",
+ "ElicitIntent",
+ "ElicitSlot",
+ "None"
+ ],
+ "type": "string"
+ },
+ "ElicitSubSlot": {
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "description": "The name of the slot that should be elicited from the user.
",
+ "type": "string"
+ },
+ "subSlotToElicit": {
+ "$ref": "#/definitions/ElicitSubSlot",
+ "description": "The field is not supported.
"
+ }
+ },
+ "type": "object"
+ },
+ "ImageResponseCard": {
+ "additionalProperties": false,
+ "properties": {
+ "buttons": {
+ "description": "A list of buttons that should be displayed on the response card. The arrangement of the buttons is determined by the platform that displays the button.
",
+ "items": {
+ "$ref": "#/definitions/Button"
+ },
+ "type": "array"
+ },
+ "imageUrl": {
+ "description": "The URL of an image to display on the response card. The image URL must be publicly available so that the platform displaying the response card has access to the image.
",
+ "type": "string"
+ },
+ "subtitle": {
+ "description": "The subtitle to display on the response card. The format of the subtitle is determined by the platform displaying the response card.
",
+ "type": "string"
+ },
+ "title": {
+ "description": "The title to display on the response card. The format of the title is determined by the platform displaying the response card.
",
+ "type": "string"
+ }
+ },
+ "required": [
+ "title"
+ ],
+ "type": "object"
+ },
+ "Intent": {
+ "additionalProperties": false,
+ "properties": {
+ "confirmationState": {
+ "$ref": "#/definitions/ConfirmationState",
+ "description": "Contains information about whether fulfillment of the intent has been confirmed.
"
+ },
+ "name": {
+ "description": "The name of the intent.
",
+ "type": "string"
+ },
+ "slots": {
+ "additionalProperties": {
+ "$ref": "#/definitions/Slot"
+ },
+ "description": "A map of all of the slots for the intent. The name of the slot maps to the value of the slot. If a slot has not been filled, the value is null.
",
+ "type": "object"
+ },
+ "state": {
+ "$ref": "#/definitions/IntentState",
+ "description": "Contains fulfillment information for the intent.
"
+ }
+ },
+ "type": "object"
+ },
+ "IntentState": {
+ "enum": [
+ "Failed",
+ "Fulfilled",
+ "InProgress",
+ "ReadyForFulfillment"
+ ],
+ "type": "string"
+ },
+ "LambdaCodeHookSessionState": {
+ "additionalProperties": false,
+ "description": "The Lambda function event Session state differs from the API_runtime_SessionState because of the format of the Intent",
+ "properties": {
+ "activeContexts": {
+ "description": "One or more contexts that indicate to Amazon Lex V2 the context of a request. When a context is active, Amazon Lex V2 considers intents with the matching context as a trigger as the next intent in a session.
",
+ "items": {
+ "$ref": "#/definitions/ActiveContext"
+ },
+ "type": "array"
+ },
+ "dialogAction": {
+ "$ref": "#/definitions/DialogAction",
+ "description": "The next step that Amazon Lex V2 should take in the conversation with a user.
"
+ },
+ "intent": {
+ "$ref": "#/definitions/Intent",
+ "description": "The active intent that Amazon Lex V2 is processing.
"
+ },
+ "originatingRequestId": {
+ "description": "A unique identifier for a specific request.
",
+ "type": "string"
+ },
+ "runtimeHints": {
+ "$ref": "#/definitions/RuntimeHints",
+ "description": "Hints for phrases that a customer is likely to use for a slot. Amazon Lex V2 uses the hints to help determine the correct value of a slot.
"
+ },
+ "sessionAttributes": {
+ "$ref": "#/definitions/Attributes",
+ "description": "Map of key/value pairs representing session-specific context information. It contains application information passed between Amazon Lex V2 and a client application.
"
+ }
+ },
+ "required": [
+ "sessionAttributes",
+ "dialogAction"
+ ],
+ "type": "object"
+ },
+ "LexCodeHookResponse": {
+ "additionalProperties": false,
+ "properties": {
+ "messages": {
+ "description": "One or more messages that Amazon Lex V2 shows to the customer to perform the next turn of the conversation. If you don't supply messages, Amazon Lex V2 uses the appropriate message defined when the bot was created\n\nRequired if dialogAction.type is ElicitIntent.",
+ "items": {
+ "$ref": "#/definitions/Message"
+ },
+ "type": "array"
+ },
+ "requestAttributes": {
+ "$ref": "#/definitions/Attributes",
+ "description": "Request-specific attributes"
+ },
+ "sessionState": {
+ "$ref": "#/definitions/LambdaCodeHookSessionState",
+ "description": "The current state of the conversation with the user.\n\nThe actual contents of the structure depends on the type of dialog action."
+ }
+ },
+ "required": [
+ "sessionState"
+ ],
+ "if": {
+ "properties": {
+ "sessionState": {
+ "properties": {
+ "dialogAction": {
+ "properties" : {
+ "type": {
+ "const": "ElicitIntent"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "then": {
+ "required": ["messages"],
+ "properties": {
+ "messages": {
+ "minItems": 1
+ }
+ }
+ },
+ "else" : {
+ "required":[]
+ },
+ "type": "object"
+ },
+ "Message": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "content": {
+ "description": "The text of the message.
",
+ "type": "string"
+ },
+ "contentType": {
+ "$ref": "#/definitions/MessageContentType",
+ "description": "Indicates the type of response.
"
+ },
+ "imageResponseCard": {
+ "$ref": "#/definitions/ImageResponseCard",
+ "description": "A card that is shown to the user by a messaging platform. You define the contents of the card, the card is displayed by the platform.
When you use a response card, the response from the user is constrained to the text associated with a button on the card.
"
+ }
+ },
+ "required": [
+ "contentType"
+ ],
+ "if": {
+ "properties": {
+ "contentType": {
+ "const": "ImageResponseCard"
+ }
+ }
+ },
+ "then": {
+ "required": [
+ "imageResponseCard"
+ ]
+ },
+ "else": {
+ "required": [
+ "content"
+ ]
+ }
+ },
+ "MessageContentType": {
+ "enum": [
+ "CustomPayload",
+ "ImageResponseCard",
+ "PlainText",
+ "SSML"
+ ],
+ "type": "string"
+ },
+ "RuntimeHintDetails": {
+ "additionalProperties": false,
+ "properties": {
+ "runtimeHintValues": {
+ "description": "One or more strings that Amazon Lex V2 should look for in the input to the bot. Each phrase is given preference when deciding on slot values.
",
+ "items": {
+ "$ref": "#/definitions/RuntimeHintValue"
+ },
+ "type": "array"
+ },
+ "subSlotHints": {
+ "additionalProperties": {
+ "$ref": "#/definitions/RuntimeHintDetails"
+ },
+ "description": "A map of constituent sub slot names inside a composite slot in the intent and the phrases that should be added for each sub slot. Inside each composite slot hints, this structure provides a mechanism to add granular sub slot phrases. Only sub slot hints are supported for composite slots. The intent name, composite slot name and the constituent sub slot names must exist.
",
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "RuntimeHintValue": {
+ "additionalProperties": false,
+ "properties": {
+ "phrase": {
+ "description": "The phrase that Amazon Lex V2 should look for in the user's input to the bot.
",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "RuntimeHints": {
+ "additionalProperties": false,
+ "properties": {
+ "slotHints": {
+ "additionalProperties": {
+ "additionalProperties": {
+ "$ref": "#/definitions/RuntimeHintDetails"
+ },
+ "type": "object"
+ },
+ "description": "A list of the slots in the intent that should have runtime hints added, and the phrases that should be added for each slot.
The first level of the slotHints
map is the name of the intent. The second level is the name of the slot within the intent. For more information, see Using hints to improve accuracy .
The intent name and slot name must exist.
",
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "Shape": {
+ "enum": [
+ "Composite",
+ "List",
+ "Scalar"
+ ],
+ "type": "string"
+ },
+ "Slot": {
+ "additionalProperties": false,
+ "properties": {
+ "shape": {
+ "$ref": "#/definitions/Shape",
+ "description": "When the shape
value is List
, it indicates that the values
field contains a list of slot values. When the value is Scalar
, it indicates that the value
field contains a single value.
"
+ },
+ "subSlots": {
+ "additionalProperties": {
+ "$ref": "#/definitions/Slot"
+ },
+ "description": "The constituent sub slots of a composite slot.
",
+ "type": "object"
+ },
+ "value": {
+ "$ref": "#/definitions/Value",
+ "description": "The current value of the slot.
"
+ },
+ "values": {
+ "description": "A list of one or more values that the user provided for the slot. For example, if a for a slot that elicits pizza toppings, the values might be \"pepperoni\" and \"pineapple.\"
",
+ "items": {
+ "$ref": "#/definitions/Slot"
+ },
+ "type": "array"
+ }
+ },
+ "type": ["object", "null"]
+ },
+ "StyleType": {
+ "enum": [
+ "Default",
+ "SpellByLetter",
+ "SpellByWord"
+ ],
+ "type": "string"
+ },
+ "Value": {
+ "additionalProperties": false,
+ "properties": {
+ "interpretedValue": {
+ "description": "The value that Amazon Lex V2 determines for the slot. The actual value depends on the setting of the value selection strategy for the bot. You can choose to use the value entered by the user, or you can have Amazon Lex V2 choose the first value in the resolvedValues
list.
",
+ "type": "string"
+ },
+ "originalValue": {
+ "description": "The text of the utterance from the user that was entered for the slot.
",
+ "type": "string"
+ },
+ "resolvedValues": {
+ "description": "A list of additional values that have been recognized for the slot.
",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ }
+ }
+}
diff --git a/utilities/lambdaResponseValidator/src/ValidateLambdaResponse.js b/utilities/lambdaResponseValidator/src/ValidateLambdaResponse.js
new file mode 100644
index 0000000..67b643a
--- /dev/null
+++ b/utilities/lambdaResponseValidator/src/ValidateLambdaResponse.js
@@ -0,0 +1,37 @@
+/* eslint-disable */
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: MIT-0
+
+const Ajv2019 = require("ajv/dist/2019")
+const schema = require("./LexCodeHookResponseSchema.json")
+const ajv = new Ajv2019({ allErrors: true })
+
+exports.validateInput = function (inputData) {
+ let response = []
+
+ const errors = validateLexLambdaResponse(inputData)
+ for (let i = 0; i < errors.length; i++) {
+ if (errors[i].keyword !== "if" && errors[i].keyword !== "else" && errors[i].keyword !== "then") {
+ let message = ``
+
+ if (errors[i].instancePath === "") {
+ message += errors[i].message
+ } else {
+ message += `${errors[i].instancePath} ${errors[i].message}`
+ }
+
+ if (errors[i].params.allowedValues) {
+ message += `. Allowed values: ${errors[i].params.allowedValues.join(", ")}`
+ }
+ response.push(message)
+ }
+ }
+ return response
+}
+
+function validateLexLambdaResponse(inputData) {
+ const validate = ajv.compile(schema)
+ validate(inputData)
+ console.debug("Validation errors:", validate.errors)
+ return validate.errors || []
+}
diff --git a/utilities/lambdaResponseValidator/src/package-lock.json b/utilities/lambdaResponseValidator/src/package-lock.json
new file mode 100644
index 0000000..93739cd
--- /dev/null
+++ b/utilities/lambdaResponseValidator/src/package-lock.json
@@ -0,0 +1,2104 @@
+{
+ "name": "lambdaresponsevalidator",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "lambdaresponsevalidator",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "ajv": "^8.12.0"
+ },
+ "devDependencies": {
+ "browserify": "^17.0.0",
+ "watchify": "^4.0.0"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-node": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
+ "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^7.0.0",
+ "acorn-walk": "^7.0.0",
+ "xtend": "^4.0.2"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
+ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/asn1.js": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
+ "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "node_modules/asn1.js/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/assert": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.1.tgz",
+ "integrity": "sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A==",
+ "dev": true,
+ "dependencies": {
+ "object.assign": "^4.1.4",
+ "util": "^0.10.4"
+ }
+ },
+ "node_modules/assert/node_modules/inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
+ "dev": true
+ },
+ "node_modules/assert/node_modules/util": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
+ "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "2.0.3"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/bn.js": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
+ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
+ "dev": true
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==",
+ "dev": true
+ },
+ "node_modules/browser-pack": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz",
+ "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==",
+ "dev": true,
+ "dependencies": {
+ "combine-source-map": "~0.8.0",
+ "defined": "^1.0.0",
+ "JSONStream": "^1.0.3",
+ "safe-buffer": "^5.1.1",
+ "through2": "^2.0.0",
+ "umd": "^3.0.0"
+ },
+ "bin": {
+ "browser-pack": "bin/cmd.js"
+ }
+ },
+ "node_modules/browser-resolve": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz",
+ "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==",
+ "dev": true,
+ "dependencies": {
+ "resolve": "^1.17.0"
+ }
+ },
+ "node_modules/browserify": {
+ "version": "17.0.0",
+ "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz",
+ "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==",
+ "dev": true,
+ "dependencies": {
+ "assert": "^1.4.0",
+ "browser-pack": "^6.0.1",
+ "browser-resolve": "^2.0.0",
+ "browserify-zlib": "~0.2.0",
+ "buffer": "~5.2.1",
+ "cached-path-relative": "^1.0.0",
+ "concat-stream": "^1.6.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "~1.0.0",
+ "crypto-browserify": "^3.0.0",
+ "defined": "^1.0.0",
+ "deps-sort": "^2.0.1",
+ "domain-browser": "^1.2.0",
+ "duplexer2": "~0.1.2",
+ "events": "^3.0.0",
+ "glob": "^7.1.0",
+ "has": "^1.0.0",
+ "htmlescape": "^1.1.0",
+ "https-browserify": "^1.0.0",
+ "inherits": "~2.0.1",
+ "insert-module-globals": "^7.2.1",
+ "JSONStream": "^1.0.3",
+ "labeled-stream-splicer": "^2.0.0",
+ "mkdirp-classic": "^0.5.2",
+ "module-deps": "^6.2.3",
+ "os-browserify": "~0.3.0",
+ "parents": "^1.0.1",
+ "path-browserify": "^1.0.0",
+ "process": "~0.11.0",
+ "punycode": "^1.3.2",
+ "querystring-es3": "~0.2.0",
+ "read-only-stream": "^2.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.1.4",
+ "shasum-object": "^1.0.0",
+ "shell-quote": "^1.6.1",
+ "stream-browserify": "^3.0.0",
+ "stream-http": "^3.0.0",
+ "string_decoder": "^1.1.1",
+ "subarg": "^1.0.0",
+ "syntax-error": "^1.1.1",
+ "through2": "^2.0.0",
+ "timers-browserify": "^1.0.1",
+ "tty-browserify": "0.0.1",
+ "url": "~0.11.0",
+ "util": "~0.12.0",
+ "vm-browserify": "^1.0.0",
+ "xtend": "^4.0.0"
+ },
+ "bin": {
+ "browserify": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+ "dev": true,
+ "dependencies": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+ "dev": true,
+ "dependencies": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "node_modules/browserify-des": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+ "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+ "dev": true,
+ "dependencies": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "node_modules/browserify-rsa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
+ "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^5.0.0",
+ "randombytes": "^2.0.1"
+ }
+ },
+ "node_modules/browserify-sign": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz",
+ "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^5.2.1",
+ "browserify-rsa": "^4.1.0",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "elliptic": "^6.5.4",
+ "inherits": "^2.0.4",
+ "parse-asn1": "^5.1.6",
+ "readable-stream": "^3.6.2",
+ "safe-buffer": "^5.2.1"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/browserify-sign/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "dev": true,
+ "dependencies": {
+ "pako": "~1.0.5"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz",
+ "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==",
+ "dev": true,
+ "dependencies": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "node_modules/buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==",
+ "dev": true
+ },
+ "node_modules/builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==",
+ "dev": true
+ },
+ "node_modules/cached-path-relative": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz",
+ "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==",
+ "dev": true
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
+ "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.1",
+ "set-function-length": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/combine-source-map": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz",
+ "integrity": "sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg==",
+ "dev": true,
+ "dependencies": {
+ "convert-source-map": "~1.1.0",
+ "inline-source-map": "~0.6.0",
+ "lodash.memoize": "~3.0.3",
+ "source-map": "~0.5.3"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "dev": true,
+ "engines": [
+ "node >= 0.8"
+ ],
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "node_modules/console-browserify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
+ "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==",
+ "dev": true
+ },
+ "node_modules/constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==",
+ "dev": true
+ },
+ "node_modules/convert-source-map": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz",
+ "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==",
+ "dev": true
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "node_modules/create-ecdh": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
+ "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.5.3"
+ }
+ },
+ "node_modules/create-ecdh/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+ "dev": true,
+ "dependencies": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "node_modules/create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+ "dev": true,
+ "dependencies": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "node_modules/crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "dev": true,
+ "dependencies": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/dash-ast": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz",
+ "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==",
+ "dev": true
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
+ "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.1",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/defined": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz",
+ "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/deps-sort": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz",
+ "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==",
+ "dev": true,
+ "dependencies": {
+ "JSONStream": "^1.0.3",
+ "shasum-object": "^1.0.0",
+ "subarg": "^1.0.0",
+ "through2": "^2.0.0"
+ },
+ "bin": {
+ "deps-sort": "bin/cmd.js"
+ }
+ },
+ "node_modules/des.js": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz",
+ "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "node_modules/detective": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz",
+ "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==",
+ "dev": true,
+ "dependencies": {
+ "acorn-node": "^1.8.2",
+ "defined": "^1.0.0",
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "detective": "bin/detective.js"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ }
+ },
+ "node_modules/diffie-hellman/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4",
+ "npm": ">=1.2"
+ }
+ },
+ "node_modules/duplexer2": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+ "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "node_modules/elliptic": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
+ "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.11.9",
+ "brorand": "^1.1.0",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.1",
+ "inherits": "^2.0.4",
+ "minimalistic-assert": "^1.0.1",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "node_modules/elliptic/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "dev": true,
+ "dependencies": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "node_modules/fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
+ "dev": true
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-assigned-identifiers": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz",
+ "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==",
+ "dev": true
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
+ "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
+ "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
+ "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hash-base": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+ "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hash-base/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
+ "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
+ "dev": true,
+ "dependencies": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "node_modules/htmlescape": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz",
+ "integrity": "sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+ "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==",
+ "dev": true
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/inline-source-map": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz",
+ "integrity": "sha512-0mVWSSbNDvedDWIN4wxLsdPM4a7cIPcpyMxj3QZ406QRwQ6ePGB1YIHxVPjqpcUGbWQ5C+nHTwGNWAGvt7ggVA==",
+ "dev": true,
+ "dependencies": {
+ "source-map": "~0.5.3"
+ }
+ },
+ "node_modules/insert-module-globals": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz",
+ "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==",
+ "dev": true,
+ "dependencies": {
+ "acorn-node": "^1.5.2",
+ "combine-source-map": "^0.8.0",
+ "concat-stream": "^1.6.1",
+ "is-buffer": "^1.1.0",
+ "JSONStream": "^1.0.3",
+ "path-is-absolute": "^1.0.1",
+ "process": "~0.11.0",
+ "through2": "^2.0.0",
+ "undeclared-identifiers": "^1.1.2",
+ "xtend": "^4.0.0"
+ },
+ "bin": {
+ "insert-module-globals": "bin/cmd.js"
+ }
+ },
+ "node_modules/is-arguments": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+ "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+ "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
+ "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
+ "dev": true,
+ "dependencies": {
+ "which-typed-array": "^1.1.11"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+ },
+ "node_modules/jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
+ "dev": true,
+ "engines": [
+ "node >= 0.2.0"
+ ]
+ },
+ "node_modules/JSONStream": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+ "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+ "dev": true,
+ "dependencies": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ },
+ "bin": {
+ "JSONStream": "bin.js"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/labeled-stream-splicer": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz",
+ "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "stream-splicer": "^2.0.0"
+ }
+ },
+ "node_modules/lodash.memoize": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
+ "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==",
+ "dev": true
+ },
+ "node_modules/md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "dev": true,
+ "dependencies": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "node_modules/miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ },
+ "bin": {
+ "miller-rabin": "bin/miller-rabin"
+ }
+ },
+ "node_modules/miller-rabin/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "node_modules/minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==",
+ "dev": true
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "dev": true
+ },
+ "node_modules/module-deps": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz",
+ "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==",
+ "dev": true,
+ "dependencies": {
+ "browser-resolve": "^2.0.0",
+ "cached-path-relative": "^1.0.2",
+ "concat-stream": "~1.6.0",
+ "defined": "^1.0.0",
+ "detective": "^5.2.0",
+ "duplexer2": "^0.1.2",
+ "inherits": "^2.0.1",
+ "JSONStream": "^1.0.3",
+ "parents": "^1.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.4.0",
+ "stream-combiner2": "^1.1.1",
+ "subarg": "^1.0.0",
+ "through2": "^2.0.0",
+ "xtend": "^4.0.0"
+ },
+ "bin": {
+ "module-deps": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
+ "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
+ "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+ "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==",
+ "dev": true
+ },
+ "node_modules/outpipe": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/outpipe/-/outpipe-1.1.1.tgz",
+ "integrity": "sha512-BnNY/RwnDrkmQdUa9U+OfN/Y7AWmKuUPCCd+hbRclZnnANvYpO72zp/a6Q4n829hPbdqEac31XCcsvlEvb+rtA==",
+ "dev": true,
+ "dependencies": {
+ "shell-quote": "^1.4.2"
+ }
+ },
+ "node_modules/pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+ "dev": true
+ },
+ "node_modules/parents": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz",
+ "integrity": "sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==",
+ "dev": true,
+ "dependencies": {
+ "path-platform": "~0.11.15"
+ }
+ },
+ "node_modules/parse-asn1": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
+ "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
+ "dev": true,
+ "dependencies": {
+ "asn1.js": "^5.2.0",
+ "browserify-aes": "^1.0.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node_modules/path-browserify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
+ "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+ "dev": true
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-platform": {
+ "version": "0.11.15",
+ "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz",
+ "integrity": "sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/pbkdf2": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
+ "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
+ "dev": true,
+ "dependencies": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "node_modules/public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+ "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "node_modules/public-encrypt/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==",
+ "dev": true
+ },
+ "node_modules/qs": {
+ "version": "6.11.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz",
+ "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==",
+ "dev": true,
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/read-only-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz",
+ "integrity": "sha512-3ALe0bjBVZtkdWKIcThYpQCLbBMd/+Tbh2CDSrAIDO3UsZ4Xs+tnyjv2MjCOMMgBG+AsUOeuP1cgtY1INISc8w==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dev": true,
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/readable-stream/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "node_modules/readable-stream/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+ "dev": true,
+ "dependencies": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "node_modules/set-function-length": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
+ "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.1.1",
+ "get-intrinsic": "^1.2.1",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/sha.js": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ },
+ "bin": {
+ "sha.js": "bin.js"
+ }
+ },
+ "node_modules/shasum-object": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz",
+ "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==",
+ "dev": true,
+ "dependencies": {
+ "fast-safe-stringify": "^2.0.7"
+ }
+ },
+ "node_modules/shell-quote": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
+ "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stream-browserify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
+ "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "~2.0.4",
+ "readable-stream": "^3.5.0"
+ }
+ },
+ "node_modules/stream-browserify/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/stream-combiner2": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz",
+ "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==",
+ "dev": true,
+ "dependencies": {
+ "duplexer2": "~0.1.0",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "node_modules/stream-http": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz",
+ "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==",
+ "dev": true,
+ "dependencies": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "xtend": "^4.0.2"
+ }
+ },
+ "node_modules/stream-http/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/stream-splicer": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz",
+ "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/subarg": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz",
+ "integrity": "sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.1.0"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/syntax-error": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz",
+ "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==",
+ "dev": true,
+ "dependencies": {
+ "acorn-node": "^1.2.0"
+ }
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+ "dev": true
+ },
+ "node_modules/through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "node_modules/timers-browserify": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz",
+ "integrity": "sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q==",
+ "dev": true,
+ "dependencies": {
+ "process": "~0.11.0"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/tty-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
+ "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==",
+ "dev": true
+ },
+ "node_modules/typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
+ "dev": true
+ },
+ "node_modules/umd": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz",
+ "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==",
+ "dev": true,
+ "bin": {
+ "umd": "bin/cli.js"
+ }
+ },
+ "node_modules/undeclared-identifiers": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz",
+ "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==",
+ "dev": true,
+ "dependencies": {
+ "acorn-node": "^1.3.0",
+ "dash-ast": "^1.0.0",
+ "get-assigned-identifiers": "^1.2.0",
+ "simple-concat": "^1.0.0",
+ "xtend": "^4.0.1"
+ },
+ "bin": {
+ "undeclared-identifiers": "bin.js"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/uri-js/node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/url": {
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz",
+ "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^1.4.1",
+ "qs": "^6.11.2"
+ }
+ },
+ "node_modules/util": {
+ "version": "0.12.5",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
+ "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "is-arguments": "^1.0.4",
+ "is-generator-function": "^1.0.7",
+ "is-typed-array": "^1.1.3",
+ "which-typed-array": "^1.1.2"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/vm-browserify": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
+ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
+ "dev": true
+ },
+ "node_modules/watchify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/watchify/-/watchify-4.0.0.tgz",
+ "integrity": "sha512-2Z04dxwoOeNxa11qzWumBTgSAohTC0+ScuY7XMenPnH+W2lhTcpEOJP4g2EIG/SWeLadPk47x++Yh+8BqPM/lA==",
+ "dev": true,
+ "dependencies": {
+ "anymatch": "^3.1.0",
+ "browserify": "^17.0.0",
+ "chokidar": "^3.4.0",
+ "defined": "^1.0.0",
+ "outpipe": "^1.1.0",
+ "through2": "^4.0.2",
+ "xtend": "^4.0.2"
+ },
+ "bin": {
+ "watchify": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ }
+ },
+ "node_modules/watchify/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/watchify/node_modules/through2": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
+ "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "3"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz",
+ "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.4",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4"
+ }
+ }
+ }
+}
diff --git a/utilities/lambdaResponseValidator/src/package.json b/utilities/lambdaResponseValidator/src/package.json
new file mode 100644
index 0000000..8799c62
--- /dev/null
+++ b/utilities/lambdaResponseValidator/src/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "lambdaresponsevalidator",
+ "version": "1.0.0",
+ "description": "",
+ "main": "ValidateLambdaResponse.js",
+ "scripts": {
+ "package": "browserify ValidateLambdaResponse.js --s validation -o ../build/validation-bundle.js",
+ "watch": "watchify ValidateLambdaResponse.js --s validation -o ../build/validation-bundle.js --debug --verbose"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "ajv": "^8.12.0"
+ },
+ "devDependencies": {
+ "browserify": "^17.0.0",
+ "watchify": "^4.0.0"
+ }
+}