UNPKG

62.5 kBJavaScriptView Raw
1"use strict";
2var _a, _b;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.QualifiedFunctionBase = exports.FunctionBase = void 0;
5const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const crypto_1 = require("crypto");
8const iam = require("@aws-cdk/aws-iam");
9const core_1 = require("@aws-cdk/core");
10const event_invoke_config_1 = require("./event-invoke-config");
11const event_source_mapping_1 = require("./event-source-mapping");
12const function_url_1 = require("./function-url");
13const lambda_generated_1 = require("./lambda.generated");
14const util_1 = require("./util");
15class FunctionBase extends core_1.Resource {
16 constructor() {
17 super(...arguments);
18 /**
19 * Flag to delay adding a warning message until current version is invoked.
20 * @internal
21 */
22 this._warnIfCurrentVersionCalled = false;
23 /**
24 * Mapping of invocation principals to grants. Used to de-dupe `grantInvoke()` calls.
25 * @internal
26 */
27 this._invocationGrants = {};
28 /**
29 * Mapping of fucntion URL invocation principals to grants. Used to de-dupe `grantInvokeUrl()` calls.
30 * @internal
31 */
32 this._functionUrlInvocationGrants = {};
33 }
34 /**
35 * A warning will be added to functions under the following conditions:
36 * - permissions that include `lambda:InvokeFunction` are added to the unqualified function.
37 * - function.currentVersion is invoked before or after the permission is created.
38 *
39 * This applies only to permissions on Lambda functions, not versions or aliases.
40 * This function is overridden as a noOp for QualifiedFunctionBase.
41 */
42 considerWarningOnInvokeFunctionPermissions(scope, action) {
43 const affectedPermissions = ['lambda:InvokeFunction', 'lambda:*', 'lambda:Invoke*'];
44 if (affectedPermissions.includes(action)) {
45 if (scope.node.tryFindChild('CurrentVersion')) {
46 this.warnInvokeFunctionPermissions(scope);
47 }
48 else {
49 this._warnIfCurrentVersionCalled = true;
50 }
51 }
52 }
53 warnInvokeFunctionPermissions(scope) {
54 core_1.Annotations.of(scope).addWarning([
55 "AWS Lambda has changed their authorization strategy, which may cause client invocations using the 'Qualifier' parameter of the lambda function to fail with Access Denied errors.",
56 "If you are using a lambda Version or Alias, make sure to call 'grantInvoke' or 'addPermission' on the Version or Alias, not the underlying Function",
57 'See: https://github.com/aws/aws-cdk/issues/19273',
58 ].join('\n'));
59 }
60 /**
61 * Adds a permission to the Lambda resource policy.
62 * @param id The id for the permission construct
63 * @param permission The permission to grant to this Lambda function. @see Permission for details.
64 */
65 addPermission(id, permission) {
66 try {
67 jsiiDeprecationWarnings._aws_cdk_aws_lambda_Permission(permission);
68 }
69 catch (error) {
70 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
71 Error.captureStackTrace(error, this.addPermission);
72 }
73 throw error;
74 }
75 if (!this.canCreatePermissions) {
76 // FIXME: @deprecated(v2) - throw an error if calling `addPermission` on a resource that doesn't support it.
77 return;
78 }
79 const principal = this.parsePermissionPrincipal(permission.principal);
80 const { sourceAccount, sourceArn } = this.parseConditions(permission.principal) ?? {};
81 const action = permission.action ?? 'lambda:InvokeFunction';
82 const scope = permission.scope ?? this;
83 this.considerWarningOnInvokeFunctionPermissions(scope, action);
84 new lambda_generated_1.CfnPermission(scope, id, {
85 action,
86 principal,
87 functionName: this.functionArn,
88 eventSourceToken: permission.eventSourceToken,
89 sourceAccount: permission.sourceAccount ?? sourceAccount,
90 sourceArn: permission.sourceArn ?? sourceArn,
91 functionUrlAuthType: permission.functionUrlAuthType,
92 });
93 }
94 /**
95 * Adds a statement to the IAM role assumed by the instance.
96 */
97 addToRolePolicy(statement) {
98 if (!this.role) {
99 return;
100 }
101 this.role.addToPrincipalPolicy(statement);
102 }
103 /**
104 * Access the Connections object
105 *
106 * Will fail if not a VPC-enabled Lambda Function
107 */
108 get connections() {
109 if (!this._connections) {
110 // eslint-disable-next-line max-len
111 throw new Error('Only VPC-associated Lambda Functions have security groups to manage. Supply the "vpc" parameter when creating the Lambda, or "securityGroupId" when importing it.');
112 }
113 return this._connections;
114 }
115 get latestVersion() {
116 if (!this._latestVersion) {
117 this._latestVersion = new LatestVersion(this);
118 }
119 return this._latestVersion;
120 }
121 /**
122 * Whether or not this Lambda function was bound to a VPC
123 *
124 * If this is is `false`, trying to access the `connections` object will fail.
125 */
126 get isBoundToVpc() {
127 return !!this._connections;
128 }
129 addEventSourceMapping(id, options) {
130 try {
131 jsiiDeprecationWarnings._aws_cdk_aws_lambda_EventSourceMappingOptions(options);
132 }
133 catch (error) {
134 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
135 Error.captureStackTrace(error, this.addEventSourceMapping);
136 }
137 throw error;
138 }
139 return new event_source_mapping_1.EventSourceMapping(this, id, {
140 target: this,
141 ...options,
142 });
143 }
144 /**
145 * Grant the given identity permissions to invoke this Lambda
146 */
147 grantInvoke(grantee) {
148 const hash = crypto_1.createHash('sha256')
149 .update(JSON.stringify({
150 principal: grantee.grantPrincipal.toString(),
151 conditions: grantee.grantPrincipal.policyFragment.conditions,
152 }), 'utf8')
153 .digest('base64');
154 const identifier = `Invoke${hash}`;
155 // Memoize the result so subsequent grantInvoke() calls are idempotent
156 let grant = this._invocationGrants[identifier];
157 if (!grant) {
158 grant = this.grant(grantee, identifier, 'lambda:InvokeFunction', this.resourceArnsForGrantInvoke);
159 this._invocationGrants[identifier] = grant;
160 }
161 return grant;
162 }
163 /**
164 * Grant the given identity permissions to invoke this Lambda Function URL
165 */
166 grantInvokeUrl(grantee) {
167 const identifier = `InvokeFunctionUrl${grantee.grantPrincipal}`; // calls the .toString() of the principal
168 // Memoize the result so subsequent grantInvoke() calls are idempotent
169 let grant = this._functionUrlInvocationGrants[identifier];
170 if (!grant) {
171 grant = this.grant(grantee, identifier, 'lambda:InvokeFunctionUrl', [this.functionArn], {
172 functionUrlAuthType: function_url_1.FunctionUrlAuthType.AWS_IAM,
173 });
174 this._functionUrlInvocationGrants[identifier] = grant;
175 }
176 return grant;
177 }
178 addEventSource(source) {
179 try {
180 jsiiDeprecationWarnings._aws_cdk_aws_lambda_IEventSource(source);
181 }
182 catch (error) {
183 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
184 Error.captureStackTrace(error, this.addEventSource);
185 }
186 throw error;
187 }
188 source.bind(this);
189 }
190 configureAsyncInvoke(options) {
191 try {
192 jsiiDeprecationWarnings._aws_cdk_aws_lambda_EventInvokeConfigOptions(options);
193 }
194 catch (error) {
195 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
196 Error.captureStackTrace(error, this.configureAsyncInvoke);
197 }
198 throw error;
199 }
200 if (this.node.tryFindChild('EventInvokeConfig') !== undefined) {
201 throw new Error(`An EventInvokeConfig has already been configured for the function at ${this.node.path}`);
202 }
203 new event_invoke_config_1.EventInvokeConfig(this, 'EventInvokeConfig', {
204 function: this,
205 ...options,
206 });
207 }
208 addFunctionUrl(options) {
209 try {
210 jsiiDeprecationWarnings._aws_cdk_aws_lambda_FunctionUrlOptions(options);
211 }
212 catch (error) {
213 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
214 Error.captureStackTrace(error, this.addFunctionUrl);
215 }
216 throw error;
217 }
218 return new function_url_1.FunctionUrl(this, 'FunctionUrl', {
219 function: this,
220 ...options,
221 });
222 }
223 /**
224 * Returns the construct tree node that corresponds to the lambda function.
225 * For use internally for constructs, when the tree is set up in non-standard ways. Ex: SingletonFunction.
226 * @internal
227 */
228 _functionNode() {
229 return this.node;
230 }
231 /**
232 * Given the function arn, check if the account id matches this account
233 *
234 * Function ARNs look like this:
235 *
236 * arn:aws:lambda:region:account-id:function:function-name
237 *
238 * ..which means that in order to extract the `account-id` component from the ARN, we can
239 * split the ARN using ":" and select the component in index 4.
240 *
241 * @returns true if account id of function matches the account specified on the stack, false otherwise.
242 *
243 * @internal
244 */
245 _isStackAccount() {
246 if (core_1.Token.isUnresolved(this.stack.account) || core_1.Token.isUnresolved(this.functionArn)) {
247 return false;
248 }
249 return this.stack.splitArn(this.functionArn, core_1.ArnFormat.SLASH_RESOURCE_NAME).account === this.stack.account;
250 }
251 grant(grantee, identifier, action, resourceArns, permissionOverrides) {
252 const grant = iam.Grant.addToPrincipalOrResource({
253 grantee,
254 actions: [action],
255 resourceArns,
256 // Fake resource-like object on which to call addToResourcePolicy(), which actually
257 // calls addPermission()
258 resource: {
259 addToResourcePolicy: (_statement) => {
260 // Couldn't add permissions to the principal, so add them locally.
261 this.addPermission(identifier, {
262 principal: grantee.grantPrincipal,
263 action: action,
264 ...permissionOverrides,
265 });
266 const permissionNode = this._functionNode().tryFindChild(identifier);
267 if (!permissionNode && !this._skipPermissions) {
268 throw new Error('Cannot modify permission to lambda function. Function is either imported or $LATEST version.\n'
269 + 'If the function is imported from the same account use `fromFunctionAttributes()` API with the `sameEnvironment` flag.\n'
270 + 'If the function is imported from a different account and already has the correct permissions use `fromFunctionAttributes()` API with the `skipPermissions` flag.');
271 }
272 return { statementAdded: true, policyDependable: permissionNode };
273 },
274 node: this.node,
275 stack: this.stack,
276 env: this.env,
277 applyRemovalPolicy: this.applyRemovalPolicy,
278 },
279 });
280 return grant;
281 }
282 /**
283 * Translate IPrincipal to something we can pass to AWS::Lambda::Permissions
284 *
285 * Do some nasty things because `Permission` supports a subset of what the
286 * full IAM principal language supports, and we may not be able to parse strings
287 * outright because they may be tokens.
288 *
289 * Try to recognize some specific Principal classes first, then try a generic
290 * fallback.
291 */
292 parsePermissionPrincipal(principal) {
293 // Try some specific common classes first.
294 // use duck-typing, not instance of
295 // @deprecated: after v2, we can change these to 'instanceof'
296 if ('wrapped' in principal) {
297 // eslint-disable-next-line dot-notation
298 principal = principal['wrapped'];
299 }
300 if ('accountId' in principal) {
301 return principal.accountId;
302 }
303 if ('service' in principal) {
304 return principal.service;
305 }
306 if ('arn' in principal) {
307 return principal.arn;
308 }
309 // Try a best-effort approach to support simple principals that are not any of the predefined
310 // classes, but are simple enough that they will fit into the Permission model. Main target
311 // here: imported Roles, Users, Groups.
312 //
313 // The principal cannot have conditions and must have a single { AWS: [arn] } entry.
314 const json = principal.policyFragment.principalJson;
315 if (Object.keys(principal.policyFragment.conditions).length === 0 && json.AWS) {
316 if (typeof json.AWS === 'string') {
317 return json.AWS;
318 }
319 if (Array.isArray(json.AWS) && json.AWS.length === 1 && typeof json.AWS[0] === 'string') {
320 return json.AWS[0];
321 }
322 }
323 throw new Error(`Invalid principal type for Lambda permission statement: ${principal.constructor.name}. ` +
324 'Supported: AccountPrincipal, ArnPrincipal, ServicePrincipal');
325 }
326 parseConditions(principal) {
327 if (this.isPrincipalWithConditions(principal)) {
328 const conditions = principal.policyFragment.conditions;
329 const conditionPairs = util_1.flatMap(Object.entries(conditions), ([operator, conditionObjs]) => Object.keys(conditionObjs).map(key => { return { operator, key }; }));
330 const supportedPrincipalConditions = [{ operator: 'ArnLike', key: 'aws:SourceArn' }, { operator: 'StringEquals', key: 'aws:SourceAccount' }];
331 const unsupportedConditions = conditionPairs.filter((condition) => !supportedPrincipalConditions.some((supportedCondition) => supportedCondition.operator === condition.operator && supportedCondition.key === condition.key));
332 if (unsupportedConditions.length == 0) {
333 return {
334 sourceAccount: conditions.StringEquals['aws:SourceAccount'],
335 sourceArn: conditions.ArnLike['aws:SourceArn'],
336 };
337 }
338 else {
339 throw new Error(`PrincipalWithConditions had unsupported conditions for Lambda permission statement: ${JSON.stringify(unsupportedConditions)}. ` +
340 `Supported operator/condition pairs: ${JSON.stringify(supportedPrincipalConditions)}`);
341 }
342 }
343 else {
344 return null;
345 }
346 }
347 isPrincipalWithConditions(principal) {
348 return 'conditions' in principal;
349 }
350}
351exports.FunctionBase = FunctionBase;
352_a = JSII_RTTI_SYMBOL_1;
353FunctionBase[_a] = { fqn: "@aws-cdk/aws-lambda.FunctionBase", version: "1.190.0" };
354class QualifiedFunctionBase extends FunctionBase {
355 constructor() {
356 super(...arguments);
357 this.permissionsNode = this.node;
358 }
359 get latestVersion() {
360 return this.lambda.latestVersion;
361 }
362 get resourceArnsForGrantInvoke() {
363 return [this.functionArn];
364 }
365 configureAsyncInvoke(options) {
366 try {
367 jsiiDeprecationWarnings._aws_cdk_aws_lambda_EventInvokeConfigOptions(options);
368 }
369 catch (error) {
370 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
371 Error.captureStackTrace(error, this.configureAsyncInvoke);
372 }
373 throw error;
374 }
375 if (this.node.tryFindChild('EventInvokeConfig') !== undefined) {
376 throw new Error(`An EventInvokeConfig has already been configured for the qualified function at ${this.node.path}`);
377 }
378 new event_invoke_config_1.EventInvokeConfig(this, 'EventInvokeConfig', {
379 function: this.lambda,
380 qualifier: this.qualifier,
381 ...options,
382 });
383 }
384 considerWarningOnInvokeFunctionPermissions(_scope, _action) {
385 // noOp
386 return;
387 }
388}
389exports.QualifiedFunctionBase = QualifiedFunctionBase;
390_b = JSII_RTTI_SYMBOL_1;
391QualifiedFunctionBase[_b] = { fqn: "@aws-cdk/aws-lambda.QualifiedFunctionBase", version: "1.190.0" };
392/**
393 * The $LATEST version of a function, useful when attempting to create aliases.
394 */
395class LatestVersion extends FunctionBase {
396 constructor(lambda) {
397 super(lambda, '$LATEST');
398 this.version = '$LATEST';
399 this.permissionsNode = this.node;
400 this.canCreatePermissions = false;
401 this.lambda = lambda;
402 }
403 get functionArn() {
404 return `${this.lambda.functionArn}:${this.version}`;
405 }
406 get functionName() {
407 return `${this.lambda.functionName}:${this.version}`;
408 }
409 get architecture() {
410 return this.lambda.architecture;
411 }
412 get grantPrincipal() {
413 return this.lambda.grantPrincipal;
414 }
415 get latestVersion() {
416 return this;
417 }
418 get role() {
419 return this.lambda.role;
420 }
421 get edgeArn() {
422 throw new Error('$LATEST function version cannot be used for Lambda@Edge');
423 }
424 get resourceArnsForGrantInvoke() {
425 return [this.functionArn];
426 }
427 addAlias(aliasName, options = {}) {
428 return util_1.addAlias(this, this, aliasName, options);
429 }
430}
431//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVuY3Rpb24tYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImZ1bmN0aW9uLWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsbUNBQW9DO0FBR3BDLHdDQUF3QztBQUN4Qyx3Q0FBa0c7QUFHbEcsK0RBQW9GO0FBRXBGLGlFQUF1RjtBQUN2RixpREFBc0Y7QUFFdEYseURBQW1EO0FBRW5ELGlDQUEyQztBQXFOM0MsTUFBc0IsWUFBYSxTQUFRLGVBQVE7SUFBbkQ7O1FBaUVFOzs7V0FHRztRQUNPLGdDQUEyQixHQUFZLEtBQUssQ0FBQztRQUV2RDs7O1dBR0c7UUFDTyxzQkFBaUIsR0FBOEIsRUFBRSxDQUFDO1FBRTVEOzs7V0FHRztRQUNPLGlDQUE0QixHQUE4QixFQUFFLENBQUM7S0E0VHhFO0lBMVRDOzs7Ozs7O09BT0c7SUFDSSwwQ0FBMEMsQ0FBQyxLQUFnQixFQUFFLE1BQWM7UUFDaEYsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLHVCQUF1QixFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3BGLElBQUksbUJBQW1CLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQ3hDLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLENBQUMsRUFBRTtnQkFDN0MsSUFBSSxDQUFDLDZCQUE2QixDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQzNDO2lCQUFNO2dCQUNMLElBQUksQ0FBQywyQkFBMkIsR0FBRyxJQUFJLENBQUM7YUFDekM7U0FDRjtLQUNGO0lBRVMsNkJBQTZCLENBQUMsS0FBZ0I7UUFDdEQsa0JBQVcsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsVUFBVSxDQUFDO1lBQy9CLG1MQUFtTDtZQUNuTCxxSkFBcUo7WUFDckosa0RBQWtEO1NBQ25ELENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7S0FDZjtJQUVEOzs7O09BSUc7SUFDSSxhQUFhLENBQUMsRUFBVSxFQUFFLFVBQXNCOzs7Ozs7Ozs7O1FBQ3JELElBQUksQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUU7WUFDOUIsNEdBQTRHO1lBQzVHLE9BQU87U0FDUjtRQUVELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDdEUsTUFBTSxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdEYsTUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLE1BQU0sSUFBSSx1QkFBdUIsQ0FBQztRQUM1RCxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQztRQUV2QyxJQUFJLENBQUMsMENBQTBDLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRS9ELElBQUksZ0NBQWEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQzNCLE1BQU07WUFDTixTQUFTO1lBQ1QsWUFBWSxFQUFFLElBQUksQ0FBQyxXQUFXO1lBQzlCLGdCQUFnQixFQUFFLFVBQVUsQ0FBQyxnQkFBZ0I7WUFDN0MsYUFBYSxFQUFFLFVBQVUsQ0FBQyxhQUFhLElBQUksYUFBYTtZQUN4RCxTQUFTLEVBQUUsVUFBVSxDQUFDLFNBQVMsSUFBSSxTQUFTO1lBQzVDLG1CQUFtQixFQUFFLFVBQVUsQ0FBQyxtQkFBbUI7U0FDcEQsQ0FBQyxDQUFDO0tBQ0o7SUFFRDs7T0FFRztJQUNJLGVBQWUsQ0FBQyxTQUE4QjtRQUNuRCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNkLE9BQU87U0FDUjtRQUVELElBQUksQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsU0FBUyxDQUFDLENBQUM7S0FDM0M7SUFFRDs7OztPQUlHO0lBQ0gsSUFBVyxXQUFXO1FBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3RCLG1DQUFtQztZQUNuQyxNQUFNLElBQUksS0FBSyxDQUFDLG1LQUFtSyxDQUFDLENBQUM7U0FDdEw7UUFDRCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7S0FDMUI7SUFFRCxJQUFXLGFBQWE7UUFDdEIsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUU7WUFDeEIsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUMvQztRQUNELE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztLQUM1QjtJQUVEOzs7O09BSUc7SUFDSCxJQUFXLFlBQVk7UUFDckIsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQztLQUM1QjtJQUVNLHFCQUFxQixDQUFDLEVBQVUsRUFBRSxPQUFrQzs7Ozs7Ozs7OztRQUN6RSxPQUFPLElBQUkseUNBQWtCLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRTtZQUN0QyxNQUFNLEVBQUUsSUFBSTtZQUNaLEdBQUcsT0FBTztTQUNYLENBQUMsQ0FBQztLQUNKO0lBRUQ7O09BRUc7SUFDSSxXQUFXLENBQUMsT0FBdUI7UUFDeEMsTUFBTSxJQUFJLEdBQUcsbUJBQVUsQ0FBQyxRQUFRLENBQUM7YUFDOUIsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDckIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxjQUFjLENBQUMsUUFBUSxFQUFFO1lBQzVDLFVBQVUsRUFBRSxPQUFPLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxVQUFVO1NBQzdELENBQUMsRUFBRSxNQUFNLENBQUM7YUFDVixNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDcEIsTUFBTSxVQUFVLEdBQUcsU0FBUyxJQUFJLEVBQUUsQ0FBQztRQUVuQyxzRUFBc0U7UUFDdEUsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQy9DLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDVixLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLHVCQUF1QixFQUFFLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1lBQ2xHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsR0FBRyxLQUFLLENBQUM7U0FDNUM7UUFDRCxPQUFPLEtBQUssQ0FBQztLQUNkO0lBRUQ7O09BRUc7SUFDSSxjQUFjLENBQUMsT0FBdUI7UUFDM0MsTUFBTSxVQUFVLEdBQUcsb0JBQW9CLE9BQU8sQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLHlDQUF5QztRQUUxRyxzRUFBc0U7UUFDdEUsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLDRCQUE0QixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDVixLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLDBCQUEwQixFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFO2dCQUN0RixtQkFBbUIsRUFBRSxrQ0FBbUIsQ0FBQyxPQUFPO2FBQ2pELENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxVQUFVLENBQUMsR0FBRyxLQUFLLENBQUM7U0FDdkQ7UUFDRCxPQUFPLEtBQUssQ0FBQztLQUNkO0lBRU0sY0FBYyxDQUFDLE1BQW9COzs7Ozs7Ozs7O1FBQ3hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDbkI7SUFFTSxvQkFBb0IsQ0FBQyxPQUFpQzs7Ozs7Ozs7OztRQUMzRCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLG1CQUFtQixDQUFDLEtBQUssU0FBUyxFQUFFO1lBQzdELE1BQU0sSUFBSSxLQUFLLENBQUMsd0VBQXdFLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUMzRztRQUVELElBQUksdUNBQWlCLENBQUMsSUFBSSxFQUFFLG1CQUFtQixFQUFFO1lBQy9DLFFBQVEsRUFBRSxJQUFJO1lBQ2QsR0FBRyxPQUFPO1NBQ1gsQ0FBQyxDQUFDO0tBQ0o7SUFFTSxjQUFjLENBQUMsT0FBNEI7Ozs7Ozs7Ozs7UUFDaEQsT0FBTyxJQUFJLDBCQUFXLENBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRTtZQUMxQyxRQUFRLEVBQUUsSUFBSTtZQUNkLEdBQUcsT0FBTztTQUNYLENBQUMsQ0FBQztLQUNKO0lBRUQ7Ozs7T0FJRztJQUNPLGFBQWE7UUFDckIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDO0tBQ2xCO0lBRUQ7Ozs7Ozs7Ozs7Ozs7T0FhRztJQUNPLGVBQWU7UUFDdkIsSUFBSSxZQUFLLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksWUFBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUU7WUFDbEYsT0FBTyxLQUFLLENBQUM7U0FDZDtRQUNELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxnQkFBUyxDQUFDLG1CQUFtQixDQUFDLENBQUMsT0FBTyxLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDO0tBQzVHO0lBRU8sS0FBSyxDQUNYLE9BQXVCLEVBQ3ZCLFVBQWlCLEVBQ2pCLE1BQWMsRUFDZCxZQUFzQixFQUN0QixtQkFBeUM7UUFFekMsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQztZQUMvQyxPQUFPO1lBQ1AsT0FBTyxFQUFFLENBQUMsTUFBTSxDQUFDO1lBQ2pCLFlBQVk7WUFFWixtRkFBbUY7WUFDbkYsd0JBQXdCO1lBQ3hCLFFBQVEsRUFBRTtnQkFDUixtQkFBbUIsRUFBRSxDQUFDLFVBQVUsRUFBRSxFQUFFO29CQUNsQyxrRUFBa0U7b0JBQ2xFLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxFQUFFO3dCQUM3QixTQUFTLEVBQUUsT0FBTyxDQUFDLGNBQWU7d0JBQ2xDLE1BQU0sRUFBRSxNQUFNO3dCQUNkLEdBQUcsbUJBQW1CO3FCQUN2QixDQUFDLENBQUM7b0JBRUgsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsQ0FBQztvQkFDckUsSUFBSSxDQUFDLGNBQWMsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTt3QkFDN0MsTUFBTSxJQUFJLEtBQUssQ0FBQyxnR0FBZ0c7OEJBQzVHLHlIQUF5SDs4QkFDekgsa0tBQWtLLENBQUMsQ0FBQztxQkFDeks7b0JBQ0QsT0FBTyxFQUFFLGNBQWMsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLENBQUM7Z0JBQ3BFLENBQUM7Z0JBQ0QsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO2dCQUNmLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztnQkFDakIsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO2dCQUNiLGtCQUFrQixFQUFFLElBQUksQ0FBQyxrQkFBa0I7YUFDNUM7U0FDRixDQUFDLENBQUM7UUFFSCxPQUFPLEtBQUssQ0FBQztLQUNkO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0ssd0JBQXdCLENBQUMsU0FBeUI7UUFDeEQsMENBQTBDO1FBQzFDLG1DQUFtQztRQUNuQyw2REFBNkQ7UUFDN0QsSUFBSSxTQUFTLElBQUksU0FBUyxFQUFFO1lBQzFCLHdDQUF3QztZQUN4QyxTQUFTLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQ2xDO1FBRUQsSUFBSSxXQUFXLElBQUksU0FBUyxFQUFFO1lBQzVCLE9BQVEsU0FBa0MsQ0FBQyxTQUFTLENBQUM7U0FDdEQ7UUFFRCxJQUFJLFNBQVMsSUFBSSxTQUFTLEVBQUU7WUFDMUIsT0FBUSxTQUFrQyxDQUFDLE9BQU8sQ0FBQztTQUNwRDtRQUVELElBQUksS0FBSyxJQUFJLFNBQVMsRUFBRTtZQUN0QixPQUFRLFNBQThCLENBQUMsR0FBRyxDQUFDO1NBQzVDO1FBRUQsNkZBQTZGO1FBQzdGLDJGQUEyRjtRQUMzRix1Q0FBdUM7UUFDdkMsRUFBRTtRQUNGLG9GQUFvRjtRQUNwRixNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQztRQUNwRCxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUU7WUFDN0UsSUFBSSxPQUFPLElBQUksQ0FBQyxHQUFHLEtBQUssUUFBUSxFQUFFO2dCQUFFLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQzthQUFFO1lBQ3RELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQUU7Z0JBQ3ZGLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUNwQjtTQUNGO1FBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQywyREFBMkQsU0FBUyxDQUFDLFdBQVcsQ0FBQyxJQUFJLElBQUk7WUFDdkcsNkRBQTZELENBQUMsQ0FBQztLQUNsRTtJQUVPLGVBQWUsQ0FBQyxTQUF5QjtRQUMvQyxJQUFJLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUM3QyxNQUFNLFVBQVUsR0FBbUIsU0FBUyxDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUM7WUFDdkUsTUFBTSxjQUFjLEdBQUcsY0FBTyxDQUM1QixNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUMxQixDQUFDLENBQUMsUUFBUSxFQUFFLGFBQWEsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQXVCLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxPQUFPLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQzlHLENBQUM7WUFDRixNQUFNLDRCQUE0QixHQUFHLENBQUMsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxlQUFlLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxjQUFjLEVBQUUsR0FBRyxFQUFFLG1CQUFtQixFQUFFLENBQUMsQ0FBQztZQUU3SSxNQUFNLHFCQUFxQixHQUFHLGNBQWMsQ0FBQyxNQUFNLENBQ2pELENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDLDRCQUE0QixDQUFDLElBQUksQ0FDL0MsQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLENBQUMsa0JBQWtCLENBQUMsUUFBUSxLQUFLLFNBQVMsQ0FBQyxRQUFRLElBQUksa0JBQWtCLENBQUMsR0FBRyxLQUFLLFNBQVMsQ0FBQyxHQUFHLENBQ3ZILENBQ0YsQ0FBQztZQUVGLElBQUkscUJBQXFCLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRTtnQkFDckMsT0FBTztvQkFDTCxhQUFhLEVBQUUsVUFBVSxDQUFDLFlBQVksQ0FBQyxtQkFBbUIsQ0FBQztvQkFDM0QsU0FBUyxFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDO2lCQUMvQyxDQUFDO2FBQ0g7aUJBQU07Z0JBQ0wsTUFBTSxJQUFJLEtBQUssQ0FBQyx1RkFBdUYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJO29CQUM5SSx1Q0FBdUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyw0QkFBNEIsQ0FBQyxFQUFFLENBQUMsQ0FBQzthQUMxRjtTQUNGO2FBQU07WUFDTCxPQUFPLElBQUksQ0FBQztTQUNiO0tBQ0Y7SUFFTyx5QkFBeUIsQ0FBQyxTQUF5QjtRQUN6RCxPQUFPLFlBQVksSUFBSSxTQUFTLENBQUM7S0FDbEM7O0FBNVlILG9DQTZZQzs7O0FBRUQsTUFBc0IscUJBQXNCLFNBQVEsWUFBWTtJQUFoRTs7UUFHa0Isb0JBQWUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO0tBaUM3QztJQXhCQyxJQUFXLGFBQWE7UUFDdEIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQztLQUNsQztJQUVELElBQVcsMEJBQTBCO1FBQ25DLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7S0FDM0I7SUFFTSxvQkFBb0IsQ0FBQyxPQUFpQzs7Ozs7Ozs7OztRQUMzRCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLG1CQUFtQixDQUFDLEtBQUssU0FBUyxFQUFFO1lBQzdELE1BQU0sSUFBSSxLQUFLLENBQUMsa0ZBQWtGLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUNySDtRQUVELElBQUksdUNBQWlCLENBQUMsSUFBSSxFQUFFLG1CQUFtQixFQUFFO1lBQy9DLFFBQVEsRUFBRSxJQUFJLENBQUMsTUFBTTtZQUNyQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7WUFDekIsR0FBRyxPQUFPO1NBQ1gsQ0FBQyxDQUFDO0tBQ0o7SUFFTSwwQ0FBMEMsQ0FBQyxNQUFpQixFQUFFLE9BQWU7UUFDbEYsT0FBTztRQUNQLE9BQU87S0FDUjs7QUFuQ0gsc0RBb0NDOzs7QUFFRDs7R0FFRztBQUNILE1BQU0sYUFBYyxTQUFRLFlBQVk7SUFPdEMsWUFBWSxNQUFvQjtRQUM5QixLQUFLLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBTlgsWUFBTyxHQUFHLFNBQVMsQ0FBQztRQUNwQixvQkFBZSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFFekIseUJBQW9CLEdBQUcsS0FBSyxDQUFDO1FBSTlDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0tBQ3RCO0lBRUQsSUFBVyxXQUFXO1FBQ3BCLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7S0FDckQ7SUFFRCxJQUFXLFlBQVk7UUFDckIsT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUN0RDtJQUVELElBQVcsWUFBWTtRQUNyQixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDO0tBQ2pDO0lBRUQsSUFBVyxjQUFjO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUM7S0FDbkM7SUFFRCxJQUFXLGFBQWE7UUFDdEIsT0FBTyxJQUFJLENBQUM7S0FDYjtJQUVELElBQVcsSUFBSTtRQUNiLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUM7S0FDekI7SUFFRCxJQUFXLE9BQU87UUFDaEIsTUFBTSxJQUFJLEtBQUssQ0FBQyx5REFBeUQsQ0FBQyxDQUFDO0tBQzVFO0lBRUQsSUFBVywwQkFBMEI7UUFDbkMsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztLQUMzQjtJQUVNLFFBQVEsQ0FBQyxTQUFpQixFQUFFLFVBQXdCLEVBQUU7UUFDM0QsT0FBTyxlQUFRLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7S0FDakQ7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tICdAYXdzLWNkay9hd3MtY2xvdWR3YXRjaCc7XG5pbXBvcnQgKiBhcyBlYzIgZnJvbSAnQGF3cy1jZGsvYXdzLWVjMic7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnQGF3cy1jZGsvYXdzLWlhbSc7XG5pbXBvcnQgeyBBbm5vdGF0aW9ucywgQXJuRm9ybWF0LCBDb25zdHJ1Y3ROb2RlLCBJUmVzb3VyY2UsIFJlc291cmNlLCBUb2tlbiB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgQWxpYXNPcHRpb25zIH0gZnJvbSAnLi9hbGlhcyc7XG5pbXBvcnQgeyBBcmNoaXRlY3R1cmUgfSBmcm9tICcuL2FyY2hpdGVjdHVyZSc7XG5pbXBvcnQgeyBFdmVudEludm9rZUNvbmZpZywgRXZlbnRJbnZva2VDb25maWdPcHRpb25zIH0gZnJvbSAnLi9ldmVudC1pbnZva2UtY29uZmlnJztcbmltcG9ydCB7IElFdmVudFNvdXJjZSB9IGZyb20gJy4vZXZlbnQtc291cmNlJztcbmltcG9ydCB7IEV2ZW50U291cmNlTWFwcGluZywgRXZlbnRTb3VyY2VNYXBwaW5nT3B0aW9ucyB9IGZyb20gJy4vZXZlbnQtc291cmNlLW1hcHBpbmcnO1xuaW1wb3J0IHsgRnVuY3Rpb25VcmxBdXRoVHlwZSwgRnVuY3Rpb25VcmxPcHRpb25zLCBGdW5jdGlvblVybCB9IGZyb20gJy4vZnVuY3Rpb24tdXJsJztcbmltcG9ydCB7IElWZXJzaW9uIH0gZnJvbSAnLi9sYW1iZGEtdmVyc2lvbic7XG5pbXBvcnQgeyBDZm5QZXJtaXNzaW9uIH0gZnJvbSAnLi9sYW1iZGEuZ2VuZXJhdGVkJztcbmltcG9ydCB7IFBlcm1pc3Npb24gfSBmcm9tICcuL3Blcm1pc3Npb24nO1xuaW1wb3J0IHsgYWRkQWxpYXMsIGZsYXRNYXAgfSBmcm9tICcuL3V0aWwnO1xuXG4vLyBrZWVwIHRoaXMgaW1wb3J0IHNlcGFyYXRlIGZyb20gb3RoZXIgaW1wb3J0cyB0byByZWR1Y2UgY2hhbmNlIGZvciBtZXJnZSBjb25mbGljdHMgd2l0aCB2Mi1tYWluXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZHVwbGljYXRlLWltcG9ydHMsIGltcG9ydC9vcmRlclxuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUZ1bmN0aW9uIGV4dGVuZHMgSVJlc291cmNlLCBlYzIuSUNvbm5lY3RhYmxlLCBpYW0uSUdyYW50YWJsZSB7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBmdW5jdGlvbi5cbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgZnVuY3Rpb25OYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvbkFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgSUFNIHJvbGUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgZnVuY3Rpb24uXG4gICAqL1xuICByZWFkb25seSByb2xlPzogaWFtLklSb2xlO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0aGlzIExhbWJkYSBmdW5jdGlvbiB3YXMgYm91bmQgdG8gYSBWUENcbiAgICpcbiAgICogSWYgdGhpcyBpcyBpcyBgZmFsc2VgLCB0cnlpbmcgdG8gYWNjZXNzIHRoZSBgY29ubmVjdGlvbnNgIG9iamVjdCB3aWxsIGZhaWwuXG4gICAqL1xuICByZWFkb25seSBpc0JvdW5kVG9WcGM6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBgJExBVEVTVGAgdmVyc2lvbiBvZiB0aGlzIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBOb3RlIHRoYXQgdGhpcyBpcyByZWZlcmVuY2UgdG8gYSBub24tc3BlY2lmaWMgQVdTIExhbWJkYSB2ZXJzaW9uLCB3aGljaFxuICAgKiBtZWFucyB0aGUgZnVuY3Rpb24gdGhpcyB2ZXJzaW9uIHJlZmVycyB0byBjYW4gcmV0dXJuIGRpZmZlcmVudCByZXN1bHRzIGluXG4gICAqIGRpZmZlcmVudCBpbnZvY2F0aW9ucy5cbiAgICpcbiAgICogVG8gb2J0YWluIGEgcmVmZXJlbmNlIHRvIGFuIGV4cGxpY2l0IHZlcnNpb24gd2hpY2ggcmVmZXJlbmNlcyB0aGUgY3VycmVudFxuICAgKiBmdW5jdGlvbiBjb25maWd1cmF0aW9uLCB1c2UgYGxhbWJkYUZ1bmN0aW9uLmN1cnJlbnRWZXJzaW9uYCBpbnN0ZWFkLlxuICAgKi9cbiAgcmVhZG9ubHkgbGF0ZXN0VmVyc2lvbjogSVZlcnNpb247XG5cbiAgLyoqXG4gICAqIFRoZSBjb25zdHJ1Y3Qgbm9kZSB3aGVyZSBwZXJtaXNzaW9ucyBhcmUgYXR0YWNoZWQuXG4gICAqL1xuICByZWFkb25seSBwZXJtaXNzaW9uc05vZGU6IENvbnN0cnVjdE5vZGU7XG5cbiAgLyoqXG4gICAqIFRoZSBzeXN0ZW0gYXJjaGl0ZWN0dXJlcyBjb21wYXRpYmxlIHdpdGggdGhpcyBsYW1iZGEgZnVuY3Rpb24uXG4gICAqL1xuICByZWFkb25seSBhcmNoaXRlY3R1cmU6IEFyY2hpdGVjdHVyZTtcblxuICAvKipcbiAgICogVGhlIEFSTihzKSB0byBwdXQgaW50byB0aGUgcmVzb3VyY2UgZmllbGQgb2YgdGhlIGdlbmVyYXRlZCBJQU0gcG9saWN5IGZvciBncmFudEludm9rZSgpLlxuICAgKlxuICAgKiBUaGlzIHByb3BlcnR5IGlzIGZvciBjZGsgbW9kdWxlcyB0byBjb25zdW1lIG9ubHkuIFlvdSBzaG91bGQgbm90IG5lZWQgdG8gdXNlIHRoaXMgcHJvcGVydHkuXG4gICAqIEluc3RlYWQsIHVzZSBncmFudEludm9rZSgpIGRpcmVjdGx5LlxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VBcm5zRm9yR3JhbnRJbnZva2U6IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBBZGRzIGFuIGV2ZW50IHNvdXJjZSB0aGF0IG1hcHMgdG8gdGhpcyBBV1MgTGFtYmRhIGZ1bmN0aW9uLlxuICAgKiBAcGFyYW0gaWQgY29uc3RydWN0IElEXG4gICAqIEBwYXJhbSBvcHRpb25zIG1hcHBpbmcgb3B0aW9uc1xuICAgKi9cbiAgYWRkRXZlbnRTb3VyY2VNYXBwaW5nKGlkOiBzdHJpbmcsIG9wdGlvbnM6IEV2ZW50U291cmNlTWFwcGluZ09wdGlvbnMpOiBFdmVudFNvdXJjZU1hcHBpbmc7XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBwZXJtaXNzaW9uIHRvIHRoZSBMYW1iZGEgcmVzb3VyY2UgcG9saWN5LlxuICAgKiBAcGFyYW0gaWQgVGhlIGlkIGZvciB0aGUgcGVybWlzc2lvbiBjb25zdHJ1Y3RcbiAgICogQHBhcmFtIHBlcm1pc3Npb24gVGhlIHBlcm1pc3Npb24gdG8gZ3JhbnQgdG8gdGhpcyBMYW1iZGEgZnVuY3Rpb24uIEBzZWUgUGVybWlzc2lvbiBmb3IgZGV0YWlscy5cbiAgICovXG4gIGFkZFBlcm1pc3Npb24oaWQ6IHN0cmluZywgcGVybWlzc2lvbjogUGVybWlzc2lvbik6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBzdGF0ZW1lbnQgdG8gdGhlIElBTSByb2xlIGFzc3VtZWQgYnkgdGhlIGluc3RhbmNlLlxuICAgKi9cbiAgYWRkVG9Sb2xlUG9saWN5KHN0YXRlbWVudDogaWFtLlBvbGljeVN0YXRlbWVudCk6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIEdyYW50IHRoZSBnaXZlbiBpZGVudGl0eSBwZXJtaXNzaW9ucyB0byBpbnZva2UgdGhpcyBMYW1iZGFcbiAgICovXG4gIGdyYW50SW52b2tlKGlkZW50aXR5OiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudDtcblxuICAvKipcbiAgICogR3JhbnQgdGhlIGdpdmVuIGlkZW50aXR5IHBlcm1pc3Npb25zIHRvIGludm9rZSB0aGlzIExhbWJkYSBGdW5jdGlvbiBVUkxcbiAgICovXG4gIGdyYW50SW52b2tlVXJsKGlkZW50aXR5OiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudDtcblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBnaXZlbiBuYW1lZCBtZXRyaWMgZm9yIHRoaXMgTGFtYmRhXG4gICAqL1xuICBtZXRyaWMobWV0cmljTmFtZTogc3RyaW5nLCBwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljO1xuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBEdXJhdGlvbiBvZiB0aGlzIExhbWJkYVxuICAgKlxuICAgKiBAZGVmYXVsdCBhdmVyYWdlIG92ZXIgNSBtaW51dGVzXG4gICAqL1xuICBtZXRyaWNEdXJhdGlvbihwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljO1xuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBudW1iZXIgb2YgaW52b2NhdGlvbnMgb2YgdGhpcyBMYW1iZGFcbiAgICpcbiAgICogQGRlZmF1bHQgc3VtIG92ZXIgNSBtaW51dGVzXG4gICAqL1xuICBtZXRyaWNJbnZvY2F0aW9ucyhwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljO1xuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBudW1iZXIgb2YgdGhyb3R0bGVkIGludm9jYXRpb25zIG9mIHRoaXMgTGFtYmRhXG4gICAqXG4gICAqIEBkZWZhdWx0IHN1bSBvdmVyIDUgbWludXRlc1xuICAgKi9cbiAgbWV0cmljVGhyb3R0bGVzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWM7XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gZXZlbnQgc291cmNlIHRvIHRoaXMgZnVuY3Rpb24uXG4gICAqXG4gICAqIEV2ZW50IHNvdXJjZXMgYXJlIGltcGxlbWVudGVkIGluIHRoZSBAYXdzLWNkay9hd3MtbGFtYmRhLWV2ZW50LXNvdXJjZXMgbW9kdWxlLlxuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGV4YW1wbGUgYWRkcyBhbiBTUVMgUXVldWUgYXMgYW4gZXZlbnQgc291cmNlOlxuICAgKiBgYGBcbiAgICogaW1wb3J0IHsgU3FzRXZlbnRTb3VyY2UgfSBmcm9tICdAYXdzLWNkay9hd3MtbGFtYmRhLWV2ZW50LXNvdXJjZXMnO1xuICAgKiBteUZ1bmN0aW9uLmFkZEV2ZW50U291cmNlKG5ldyBTcXNFdmVudFNvdXJjZShteVF1ZXVlKSk7XG4gICAqIGBgYFxuICAgKi9cbiAgYWRkRXZlbnRTb3VyY2Uoc291cmNlOiBJRXZlbnRTb3VyY2UpOiB2b2lkO1xuXG4gIC8qKlxuICAgKiBDb25maWd1cmVzIG9wdGlvbnMgZm9yIGFzeW5jaHJvbm91cyBpbnZvY2F0aW9uLlxuICAgKi9cbiAgY29uZmlndXJlQXN5bmNJbnZva2Uob3B0aW9uczogRXZlbnRJbnZva2VDb25maWdPcHRpb25zKTogdm9pZDtcblxuICAvKipcbiAgICogQWRkcyBhIHVybCB0byB0aGlzIGxhbWJkYSBmdW5jdGlvbi5cbiAgICovXG4gIGFkZEZ1bmN0aW9uVXJsKG9wdGlvbnM/OiBGdW5jdGlvblVybE9wdGlvbnMpOiBGdW5jdGlvblVybDtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgTGFtYmRhIGZ1bmN0aW9uIGRlZmluZWQgb3V0c2lkZSBvZiB0aGlzIHN0YWNrLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEZ1bmN0aW9uQXR0cmlidXRlcyB7XG4gIC8qKlxuICAgKiBUaGUgQVJOIG9mIHRoZSBMYW1iZGEgZnVuY3Rpb24uXG4gICAqXG4gICAqIEZvcm1hdDogYXJuOjxwYXJ0aXRpb24+OmxhbWJkYTo8cmVnaW9uPjo8YWNjb3VudC1pZD46ZnVuY3Rpb246PGZ1bmN0aW9uLW5hbWU+XG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvbkFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgSUFNIGV4ZWN1dGlvbiByb2xlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBJZiB0aGUgcm9sZSBpcyBub3Qgc3BlY2lmaWVkLCBhbnkgcm9sZS1yZWxhdGVkIG9wZXJhdGlvbnMgd2lsbCBuby1vcC5cbiAgICovXG4gIHJlYWRvbmx5IHJvbGU/OiBpYW0uSVJvbGU7XG5cbiAgLyoqXG4gICAqIElkIG9mIHRoZSBzZWN1cml0eSBncm91cCBvZiB0aGlzIExhbWJkYSwgaWYgaW4gYSBWUEMuXG4gICAqXG4gICAqIFRoaXMgbmVlZHMgdG8gYmUgZ2l2ZW4gaW4gb3JkZXIgdG8gc3VwcG9ydCBhbGxvd2luZyBjb25uZWN0aW9uc1xuICAgKiB0byB0aGlzIExhbWJkYS5cbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBzZWN1cml0eUdyb3VwYCBpbnN0ZWFkXG4gICAqL1xuICByZWFkb25seSBzZWN1cml0eUdyb3VwSWQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzZWN1cml0eSBncm91cCBvZiB0aGlzIExhbWJkYSwgaWYgaW4gYSBWUEMuXG4gICAqXG4gICAqIFRoaXMgbmVlZHMgdG8gYmUgZ2l2ZW4gaW4gb3JkZXIgdG8gc3VwcG9ydCBhbGxvd2luZyBjb25uZWN0aW9uc1xuICAgKiB0byB0aGlzIExhbWJkYS5cbiAgICovXG4gIHJlYWRvbmx5IHNlY3VyaXR5R3JvdXA/OiBlYzIuSVNlY3VyaXR5R3JvdXA7XG5cbiAgLyoqXG4gICAqIFNldHRpbmcgdGhpcyBwcm9wZXJ0eSBpbmZvcm1zIHRoZSBDREsgdGhhdCB0aGUgaW1wb3J0ZWQgZnVuY3Rpb24gaXMgaW4gdGhlIHNhbWUgZW52aXJvbm1lbnQgYXMgdGhlIHN0YWNrLlxuICAgKiBUaGlzIGFmZmVjdHMgY2VydGFpbiBiZWhhdmlvdXJzIHN1Y2ggYXMsIHdoZXRoZXIgdGhpcyBmdW5jdGlvbidzIHBlcm1pc3Npb24gY2FuIGJlIG1vZGlmaWVkLlxuICAgKiBXaGVuIG5vdCBjb25maWd1cmVkLCB0aGUgQ0RLIGF0dGVtcHRzIHRvIGF1dG8tZGV0ZXJtaW5lIHRoaXMuIEZvciBlbnZpcm9ubWVudCBhZ25vc3RpYyBzdGFja3MsIGkuZS4sIHN0YWNrc1xuICAgKiB3aGVyZSB0aGUgYWNjb3VudCBpcyBub3Qgc3BlY2lmaWVkIHdpdGggdGhlIGBlbnZgIHByb3BlcnR5LCB0aGlzIGlzIGRldGVybWluZWQgdG8gYmUgZmFsc2UuXG4gICAqXG4gICAqIFNldCB0aGlzIHRvIHByb3BlcnR5ICpPTkxZIElGKiB0aGUgaW1wb3J0ZWQgZnVuY3Rpb24gaXMgaW4gdGhlIHNhbWUgYWNjb3VudCBhcyB0aGUgc3RhY2tcbiAgICogaXQncyBpbXBvcnRlZCBpbi5cbiAgICogQGRlZmF1bHQgLSBkZXBlbmRzOiB0cnVlLCBpZiB0aGUgU3RhY2sgaXMgY29uZmlndXJlZCB3aXRoIGFuIGV4cGxpY2l0IGBlbnZgIChhY2NvdW50IGFuZCByZWdpb24pIGFuZCB0aGUgYWNjb3VudCBpcyB0aGUgc2FtZSBhcyB0aGlzIGZ1bmN0aW9uLlxuICAgKiBGb3IgZW52aXJvbm1lbnQtYWdub3N0aWMgc3RhY2tzIHRoaXMgd2lsbCBkZWZhdWx0IHRvIGBmYWxzZWAuXG4gICAqL1xuICByZWFkb25seSBzYW1lRW52aXJvbm1lbnQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBTZXR0aW5nIHRoaXMgcHJvcGVydHkgaW5mb3JtcyB0aGUgQ0RLIHRoYXQgdGhlIGltcG9ydGVkIGZ1bmN0aW9uIEFMUkVBRFkgSEFTIHRoZSBuZWNlc3NhcnkgcGVybWlzc2lvbnNcbiAgICogZm9yIHdoYXQgeW91IGFyZSB0cnlpbmcgdG8gZG8uIFdoZW4gbm90IGNvbmZpZ3VyZWQsIHRoZSBDREsgYXR0ZW1wdHMgdG8gYXV0by1kZXRlcm1pbmUgd2hldGhlciBvciBub3RcbiAgICogYWRkaXRpb25hbCBwZXJtaXNzaW9ucyBhcmUgbmVjZXNzYXJ5IG9uIHRoZSBmdW5jdGlvbiB3aGVuIGdyYW50IEFQSXMgYXJlIHVzZWQuIElmIHRoZSBDREsgdHJpZWQgdG8gYWRkXG4gICAqIHBlcm1pc3Npb25zIG9uIGFuIGltcG9ydGVkIGxhbWJkYSwgaXQgd2lsbCBmYWlsLlxuICAgKlxuICAgKiBTZXQgdGhpcyBwcm9wZXJ0eSAqT05MWSBJRiogeW91IGFyZSBjb21taXR0aW5nIHRvIG1hbmFnZSB0aGUgaW1wb3J0ZWQgZnVuY3Rpb24ncyBwZXJtaXNzaW9ucyBvdXRzaWRlIG9mXG4gICAqIENESy4gWW91IGFyZSBhY2tub3dsZWRnaW5nIHRoYXQgeW91ciBDREsgY29kZSBhbG9uZSB3aWxsIGhhdmUgaW5zdWZmaWNpZW50IHBlcm1pc3Npb25zIHRvIGFjY2VzcyB0aGVcbiAgICogaW1wb3J0ZWQgZnVuY3Rpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBza2lwUGVybWlzc2lvbnM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgYXJjaGl0ZWN0dXJlIG9mIHRoaXMgTGFtYmRhIEZ1bmN0aW9uICh0aGlzIGlzIGFuIG9wdGlvbmFsIGF0dHJpYnV0ZSBhbmQgZGVmYXVsdHMgdG8gWDg2XzY0KS5cbiAgICogQGRlZmF1bHQgLSBBcmNoaXRlY3R1cmUuWDg2XzY0XG4gICAqL1xuICByZWFkb25seSBhcmNoaXRlY3R1cmU/OiBBcmNoaXRlY3R1cmU7XG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBGdW5jdGlvbkJhc2UgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElGdW5jdGlvbiwgZWMyLklDbGllbnRWcG5Db25uZWN0aW9uSGFuZGxlciB7XG4gIC8qKlxuICAgKiBUaGUgcHJpbmNpcGFsIHRoaXMgTGFtYmRhIEZ1bmN0aW9uIGlzIHJ1bm5pbmcgYXNcbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBncmFudFByaW5jaXBhbDogaWFtLklQcmluY2lwYWw7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBmdW5jdGlvbi5cbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBmdW5jdGlvbk5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIEFSTiBmbyB0aGUgZnVuY3Rpb24uXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgZnVuY3Rpb25Bcm46IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIElBTSByb2xlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBVbmRlZmluZWQgaWYgdGhlIGZ1bmN0aW9uIHdhcyBpbXBvcnRlZCB3aXRob3V0IGEgcm9sZS5cbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSByb2xlPzogaWFtLklSb2xlO1xuXG4gIC8qKlxuICAgKiBUaGUgY29uc3RydWN0IG5vZGUgd2hlcmUgcGVybWlzc2lvbnMgYXJlIGF0dGFjaGVkLlxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHBlcm1pc3Npb25zTm9kZTogQ29uc3RydWN0Tm9kZTtcblxuICAvKipcbiAgICogVGhlIGFyY2hpdGVjdHVyZSBvZiB0aGlzIExhbWJkYSBGdW5jdGlvbi5cbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBhcmNoaXRlY3R1cmU6IEFyY2hpdGVjdHVyZTtcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgYWRkUGVybWlzc2lvbigpIGNhbGwgYWRkcyBhbnkgcGVybWlzc2lvbnNcbiAgICpcbiAgICogVHJ1ZSBmb3IgbmV3IExhbWJkYXMsIGZhbHNlIGZvciB2ZXJzaW9uICRMQVRFU1QgYW5kIGltcG9ydGVkIExhbWJkYXNcbiAgICogZnJvbSBkaWZmZXJlbnQgYWNjb3VudHMuXG4gICAqL1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgcmVhZG9ubHkgY2FuQ3JlYXRlUGVybWlzc2lvbnM6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBBUk4ocykgdG8gcHV0IGludG8gdGhlIHJlc291cmNlIGZpZWxkIG9mIHRoZSBnZW5lcmF0ZWQgSUFNIHBvbGljeSBmb3IgZ3JhbnRJbnZva2UoKVxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHJlc291cmNlQXJuc0ZvckdyYW50SW52b2tlOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgdXNlciBkZWNpZGVzIHRvIHNraXAgYWRkaW5nIHBlcm1pc3Npb25zLlxuICAgKiBUaGUgb25seSB1c2UgY2FzZSBpcyBmb3IgY3Jvc3MtYWNjb3VudCwgaW1wb3J0ZWQgbGFtYmRhc1xuICAgKiB3aGVyZSB0aGUgdXNlciBjb21taXRzIHRvIG1vZGlmeWluZyB0aGUgcGVybWlzc3Npb25zXG4gICAqIG9uIHRoZSBpbXBvcnRlZCBsYW1iZGEgb3V0c2lkZSBDREsuXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IF9za2lwUGVybWlzc2lvbnM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBBY3R1YWwgY29ubmVjdGlvbnMgb2JqZWN0IGZvciB0aGlzIExhbWJkYVxuICAgKlxuICAgKiBNYXkgYmUgdW5zZXQsIGluIHdoaWNoIGNhc2UgdGhpcyBMYW1iZGEgaXMgbm90IGNvbmZpZ3VyZWQgdXNlIGluIGEgVlBDLlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByb3RlY3RlZCBfY29ubmVjdGlvbnM/OiBlYzIuQ29ubmVjdGlvbnM7XG5cbiAgcHJpdmF0ZSBfbGF0ZXN0VmVyc2lvbj86IExhdGVzdFZlcnNpb247XG5cbiAgLyoqXG4gICAqIEZsYWcgdG8gZGVsYXkgYWRkaW5nIGEgd2FybmluZyBtZXNzYWdlIHVudGlsIGN1cnJlbnQgdmVyc2lvbiBpcyBpbnZva2VkLlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByb3RlY3RlZCBfd2FybklmQ3VycmVudFZlcnNpb25DYWxsZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKipcbiAgICogTWFwcGluZyBvZiBpbnZvY2F0aW9uIHByaW5jaXBhbHMgdG8gZ3JhbnRzLiBVc2VkIHRvIGRlLWR1cGUgYGdyYW50SW52b2tlKClgIGNhbGxzLlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByb3RlY3RlZCBfaW52b2NhdGlvbkdyYW50czogUmVjb3JkPHN0cmluZywgaWFtLkdyYW50PiA9IHt9O1xuXG4gIC8qKlxuICAgKiBNYXBwaW5nIG9mIGZ1Y250aW9uIFVSTCBpbnZvY2F0aW9uIHByaW5jaXBhbHMgdG8gZ3JhbnRzLiBVc2VkIHRvIGRlLWR1cGUgYGdyYW50SW52b2tlVXJsKClgIGNhbGxzLlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByb3RlY3RlZCBfZnVuY3Rpb25VcmxJbnZvY2F0aW9uR3JhbnRzOiBSZWNvcmQ8c3RyaW5nLCBpYW0uR3JhbnQ+ID0ge307XG5cbiAgLyoqXG4gICAqIEEgd2FybmluZyB3aWxsIGJlIGFkZGVkIHRvIGZ1bmN0aW9ucyB1bmRlciB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gICAqIC0gcGVybWlzc2lvbnMgdGhhdCBpbmNsdWRlIGBsYW1iZGE6SW52b2tlRnVuY3Rpb25gIGFyZSBhZGRlZCB0byB0aGUgdW5xdWFsaWZpZWQgZnVuY3Rpb24uXG4gICAqIC0gZnVuY3Rpb24uY3VycmVudFZlcnNpb24gaXMgaW52b2tlZCBiZWZvcmUgb3IgYWZ0ZXIgdGhlIHBlcm1pc3Npb24gaXMgY3JlYXRlZC5cbiAgICpcbiAgICogVGhpcyBhcHBsaWVzIG9ubHkgdG8gcGVybWlzc2lvbnMgb24gTGFtYmRhIGZ1bmN0aW9ucywgbm90IHZlcnNpb25zIG9yIGFsaWFzZXMuXG4gICAqIFRoaXMgZnVuY3Rpb24gaXMgb3ZlcnJpZGRlbiBhcyBhIG5vT3AgZm9yIFF1YWxpZmllZEZ1bmN0aW9uQmFzZS5cbiAgICovXG4gIHB1YmxpYyBjb25zaWRlcldhcm5pbmdPbkludm9rZUZ1bmN0aW9uUGVybWlzc2lvbnMoc2NvcGU6IENvbnN0cnVjdCwgYWN0aW9uOiBzdHJpbmcpIHtcbiAgICBjb25zdCBhZmZlY3RlZFBlcm1pc3Npb25zID0gWydsYW1iZGE6SW52b2tlRnVuY3Rpb24nLCAnbGFtYmRhOionLCAnbGFtYmRhOkludm9rZSonXTtcbiAgICBpZiAoYWZmZWN0ZWRQZXJtaXNzaW9ucy5pbmNsdWRlcyhhY3Rpb24pKSB7XG4gICAgICBpZiAoc2NvcGUubm9kZS50cnlGaW5kQ2hpbGQoJ0N1cnJlbnRWZXJzaW9uJykpIHtcbiAgICAgICAgdGhpcy53YXJuSW52b2tlRnVuY3Rpb25QZXJtaXNzaW9ucyhzY29wZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl93YXJuSWZDdXJyZW50VmVyc2lvbkNhbGxlZCA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIHdhcm5JbnZva2VGdW5jdGlvblBlcm1pc3Npb25zKHNjb3BlOiBDb25zdHJ1Y3QpOiB2b2lkIHtcbiAgICBBbm5vdGF0aW9ucy5vZihzY29wZSkuYWRkV2FybmluZyhbXG4gICAgICBcIkFXUyBMYW1iZGEgaGFzIGNoYW5nZWQgdGhlaXIgYXV0aG9yaXphdGlvbiBzdHJhdGVneSwgd2hpY2ggbWF5IGNhdXNlIGNsaWVudCBpbnZvY2F0aW9ucyB1c2luZyB0aGUgJ1F1YWxpZmllcicgcGFyYW1ldGVyIG9mIHRoZSBsYW1iZGEgZnVuY3Rpb24gdG8gZmFpbCB3aXRoIEFjY2VzcyBEZW5pZWQgZXJyb3JzLlwiLFxuICAgICAgXCJJZiB5b3UgYXJlIHVzaW5nIGEgbGFtYmRhIFZlcnNpb24gb3IgQWxpYXMsIG1ha2Ugc3VyZSB0byBjYWxsICdncmFudEludm9rZScgb3IgJ2FkZFBlcm1pc3Npb24nIG9uIHRoZSBWZXJzaW9uIG9yIEFsaWFzLCBub3QgdGhlIHVuZGVybHlpbmcgRnVuY3Rpb25cIixcbiAgICAgICdTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9pc3N1ZXMvMTkyNzMnLFxuICAgIF0uam9pbignXFxuJykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBwZXJtaXNzaW9uIHRvIHRoZSBMYW1iZGEgcmVzb3VyY2UgcG9saWN5LlxuICAgKiBAcGFyYW0gaWQgVGhlIGlkIGZvciB0aGUgcGVybWlzc2lvbiBjb25zdHJ1Y3RcbiAgICogQHBhcmFtIHBlcm1pc3Npb24gVGhlIHBlcm1pc3Npb24gdG8gZ3JhbnQgdG8gdGhpcyBMYW1iZGEgZnVuY3Rpb24uIEBzZWUgUGVybWlzc2lvbiBmb3IgZGV0YWlscy5cbiAgICovXG4gIHB1YmxpYyBhZGRQZXJtaXNzaW9uKGlkOiBzdHJpbmcsIHBlcm1pc3Npb246IFBlcm1pc3Npb24pIHtcbiAgICBpZiAoIXRoaXMuY2FuQ3JlYXRlUGVybWlzc2lvbnMpIHtcbiAgICAgIC8vIEZJWE1FOiBAZGVwcmVjYXRlZCh2MikgLSB0aHJvdyBhbiBlcnJvciBpZiBjYWxsaW5nIGBhZGRQZXJtaXNzaW9uYCBvbiBhIHJlc291cmNlIHRoYXQgZG9lc24ndCBzdXBwb3J0IGl0LlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHByaW5jaXBhbCA9IHRoaXMucGFyc2VQZXJtaXNzaW9uUHJpbmNpcGFsKHBlcm1pc3Npb24ucHJpbmNpcGFsKTtcbiAgICBjb25zdCB7IHNvdXJjZUFjY291bnQsIHNvdXJjZUFybiB9ID0gdGhpcy5wYXJzZUNvbmRpdGlvbnMocGVybWlzc2lvbi5wcmluY2lwYWwpID8/IHt9O1xuICAgIGNvbnN0IGFjdGlvbiA9IHBlcm1pc3Npb24uYWN0aW9uID8/ICdsYW1iZGE6SW52b2tlRnVuY3Rpb24nO1xuICAgIGNvbnN0IHNjb3BlID0gcGVybWlzc2lvbi5zY29wZSA/PyB0aGlzO1xuXG4gICAgdGhpcy5jb25zaWRlcldhcm5pbmdPbkludm9rZUZ1bmN0aW9uUGVybWlzc2lvbnMoc2NvcGUsIGFjdGlvbik7XG5cbiAgICBuZXcgQ2ZuUGVybWlzc2lvbihzY29wZSwgaWQsIHtcbiAgICAgIGFjdGlvbixcbiAgICAgIHByaW5jaXBhbCxcbiAgICAgIGZ1bmN0aW9uTmFtZTogdGhpcy5mdW5jdGlvbkFybixcbiAgICAgIGV2ZW50U291cmNlVG9rZW46IHBlcm1pc3Npb24uZXZlbnRTb3VyY2VUb2tlbixcbiAgICAgIHNvdXJjZUFjY291bnQ6IHBlcm1pc3Npb24uc291cmNlQWNjb3VudCA/PyBzb3VyY2VBY2NvdW50LFxuICAgICAgc291cmNlQXJuOiBwZXJtaXNzaW9uLnNvdXJjZUFybiA/PyBzb3VyY2VBcm4sXG4gICAgICBmdW5jdGlvblVybEF1dGhUeXBlOiBwZXJtaXNzaW9uLmZ1bmN0aW9uVXJsQXV0aFR5cGUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHN0YXRlbWVudCB0byB0aGUgSUFNIHJvbGUgYXNzdW1lZCBieSB0aGUgaW5zdGFuY2UuXG4gICAqL1xuICBwdWJsaWMgYWRkVG9Sb2xlUG9saWN5KHN0YXRlbWVudDogaWFtLlBvbGljeVN0YXRlbWVudCkge1xuICAgIGlmICghdGhpcy5yb2xlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5yb2xlLmFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudCk7XG4gIH1cblxuICAvKipcbiAgICogQWNjZXNzIHRoZSBDb25uZWN0aW9ucyBvYmplY3RcbiAgICpcbiAgICogV2lsbCBmYWlsIGlmIG5vdCBhIFZQQy1lbmFibGVkIExhbWJkYSBGdW5jdGlvblxuICAgKi9cbiAgcHVibGljIGdldCBjb25uZWN0aW9ucygpOiBlYzIuQ29ubmVjdGlvbnMge1xuICAgIGlmICghdGhpcy5fY29ubmVjdGlvbnMpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtbGVuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ09ubHkgVlBDLWFzc29jaWF0ZWQgTGFtYmRhIEZ1bmN0aW9ucyBoYXZlIHNlY3VyaXR5IGdyb3VwcyB0byBtYW5hZ2UuIFN1cHBseSB0aGUgXCJ2cGNcIiBwYXJhbWV0ZXIgd2hlbiBjcmVhdGluZyB0aGUgTGFtYmRhLCBvciBcInNlY3VyaXR5R3JvdXBJZFwiIHdoZW4gaW1wb3J0aW5nIGl0LicpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fY29ubmVjdGlvbnM7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGxhdGVzdFZlcnNpb24oKTogSVZlcnNpb24ge1xuICAgIGlmICghdGhpcy5fbGF0ZXN0VmVyc2lvbikge1xuICAgICAgdGhpcy5fbGF0ZXN0VmVyc2lvbiA9IG5ldyBMYXRlc3RWZXJzaW9uKHRoaXMpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fbGF0ZXN0VmVyc2lvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0aGlzIExhbWJkYSBmdW5jdGlvbiB3YXMgYm91bmQgdG8gYSBWUENcbiAgICpcbiAgICogSWYgdGhpcyBpcyBpcyBgZmFsc2VgLCB0cnlpbmcgdG8gYWNjZXNzIHRoZSBgY29ubmVjdGlvbnNgIG9iamVjdCB3aWxsIGZhaWwuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGlzQm91bmRUb1ZwYygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLl9jb25uZWN0aW9ucztcbiAgfVxuXG4gIHB1YmxpYyBhZGRFdmVudFNvdXJjZU1hcHBpbmcoaWQ6IHN0cmluZywgb3B0aW9uczogRXZlbnRTb3VyY2VNYXBwaW5nT3B0aW9ucyk6IEV2ZW50U291cmNlTWFwcGluZyB7XG4gICAgcmV0dXJuIG5ldyBFdmVudFNvdXJjZU1hcHBpbmcodGhpcywgaWQsIHtcbiAgICAgIHRhcmdldDogdGhpcyxcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnQgdGhlIGdpdmVuIGlkZW50aXR5IHBlcm1pc3Npb25zIHRvIGludm9rZSB0aGlzIExhbWJkYVxuICAgKi9cbiAgcHVibGljIGdyYW50SW52b2tlKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICBjb25zdCBoYXNoID0gY3JlYXRlSGFzaCgnc2hhMjU2JylcbiAgICAgIC51cGRhdGUoSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBwcmluY2lwYWw6IGdyYW50ZWUuZ3JhbnRQcmluY2lwYWwudG9TdHJpbmcoKSxcbiAgICAgICAgY29uZGl0aW9uczogZ3JhbnRlZS5ncmFudFByaW5jaXBhbC5wb2xpY3lGcmFnbWVudC5jb25kaXRpb25zLFxuICAgICAgfSksICd1dGY4JylcbiAgICAgIC5kaWdlc3QoJ2Jhc2U2NCcpO1xuICAgIGNvbnN0IGlkZW50aWZpZXIgPSBgSW52b2tlJHtoYXNofWA7XG5cbiAgICAvLyBNZW1vaXplIHRoZSByZXN1bHQgc28gc3Vic2VxdWVudCBncmFudEludm9rZSgpIGNhbGxzIGFyZSBpZGVtcG90ZW50XG4gICAgbGV0IGdyYW50ID0gdGhpcy5faW52b2NhdGlvbkdyYW50c1tpZGVudGlmaWVyXTtcbiAgICBpZiAoIWdyYW50KSB7XG4gICAgICBncmFudCA9IHRoaXMuZ3JhbnQoZ3JhbnRlZSwgaWRlbnRpZmllciwgJ2xhbWJkYTpJbnZva2VGdW5jdGlvbicsIHRoaXMucmVzb3VyY2VBcm5zRm9yR3JhbnRJbnZva2UpO1xuICAgICAgdGhpcy5faW52b2NhdGlvbkdyYW50c1tpZGVudGlmaWVyXSA9IGdyYW50O1xuICAgIH1cbiAgICByZXR1cm4gZ3JhbnQ7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnQgdGhlIGdpdmVuIGlkZW50aXR5IHBlcm1pc3Npb25zIHRvIGludm9rZSB0aGlzIExhbWJkYSBGdW5jdGlvbiBVUkxcbiAgICovXG4gIHB1YmxpYyBncmFudEludm9rZVVybChncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudCB7XG4gICAgY29uc3QgaWRlbnRpZmllciA9IGBJbnZva2VGdW5jdGlvblVybCR7Z3JhbnRlZS5ncmFudFByaW5jaXBhbH1gOyAvLyBjYWxscyB0aGUgLnRvU3RyaW5nKCkgb2YgdGhlIHByaW5jaXBhbFxuXG4gICAgLy8gTWVtb2l6ZSB0aGUgcmVzdWx0IHNvIHN1YnNlcXVlbnQgZ3JhbnRJbnZva2UoKSBjYWxscyBhcmUgaWRlbXBvdGVudFxuICAgIGxldCBncmFudCA9IHRoaXMuX2Z1bmN0aW9uVXJsSW52b2NhdGlvbkdyYW50c1tpZGVudGlmaWVyXTtcbiAgICBpZiAoIWdyYW50KSB7XG4gICAgICBncmFudCA9IHRoaXMuZ3JhbnQoZ3JhbnRlZSwgaWRlbnRpZmllciwgJ2xhbWJkYTpJbnZva2VGdW5jdGlvblVybCcsIFt0aGlzLmZ1bmN0aW9uQXJuXSwge1xuICAgICAgICBmdW5jdGlvblVybEF1dGhUeXBlOiBGdW5jdGlvblVybEF1dGhUeXBlLkFXU19JQU0sXG4gICAgICB9KTtcbiAgICAgIHRoaXMuX2Z1bmN0aW9uVXJsSW52b2NhdGlvbkdyYW50c1tpZGVudGlmaWVyXSA9IGdyYW50O1xuICAgIH1cbiAgICByZXR1cm4gZ3JhbnQ7XG4gIH1cblxuICBwdWJsaWMgYWRkRXZlbnRTb3VyY2Uoc291cmNlOiBJRXZlbnRTb3VyY2UpIHtcbiAgICBzb3VyY2UuYmluZCh0aGlzKTtcbiAgfVxuXG4gIHB1YmxpYyBjb25maWd1cmVBc3luY0ludm9rZShvcHRpb25zOiBFdmVudEludm9rZUNvbmZpZ09wdGlvbnMpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5ub2RlLnRyeUZpbmRDaGlsZCgnRXZlbnRJbnZva2VDb25maWcnKSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEFuIEV2ZW50SW52b2tlQ29uZmlnIGhhcyBhbHJlYWR5IGJlZW4gY29uZmlndXJlZCBmb3IgdGhlIGZ1bmN0aW9uIGF0ICR7dGhpcy5ub2RlLnBhdGh9YCk7XG4gICAgfVxuXG4gICAgbmV3IEV2ZW50SW52b2tlQ29uZmlnKHRoaXMsICdFdmVudEludm9rZUNvbmZpZycsIHtcbiAgICAgIGZ1bmN0aW9uOiB0aGlzLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRGdW5jdGlvblVybChvcHRpb25zPzogRnVuY3Rpb25VcmxPcHRpb25zKTogRnVuY3Rpb25Vcmwge1xuICAgIHJldHVybiBuZXcgRnVuY3Rpb25VcmwodGhpcywgJ0Z1bmN0aW9uVXJsJywge1xuICAgICAgZnVuY3Rpb246IHRoaXMsXG4gICAgICAuLi5vcHRpb25zLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGNvbnN0cnVjdCB0cmVlIG5vZGUgdGhhdCBjb3JyZXNwb25kcyB0byB0aGUgbGFtYmRhIGZ1bmN0aW9uLlxuICAgKiBGb3IgdXNlIGludGVybmFsbHkgZm9yIGNvbnN0cnVjdHMsIHdoZW4gdGhlIHRyZWUgaXMgc2V0IHVwIGluIG5vbi1zdGFuZGFyZCB3YXlzLiBFeDogU2luZ2xldG9uRnVuY3Rpb24uXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHJvdGVjdGVkIF9mdW5jdGlvbk5vZGUoKTogQ29uc3RydWN0Tm9kZSB7XG4gICAgcmV0dXJuIHRoaXMubm9kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiB0aGUgZnVuY3Rpb24gYXJuLCBjaGVjayBpZiB0aGUgYWNjb3VudCBpZCBtYXRjaGVzIHRoaXMgYWNjb3VudFxuICAgKlxuICAgKiBGdW5jdGlvbiBBUk5zIGxvb2sgbGlrZSB0aGlzOlxuICAgKlxuICAgKiAgIGFybjphd3M6bGFtYmRhOnJlZ2lvbjphY2NvdW50LWlkOmZ1bmN0aW9uOmZ1bmN0aW9uLW5hbWVcbiAgICpcbiAgICogLi53aGljaCBtZWFucyB0aGF0IGluIG9yZGVyIHRvIGV4dHJhY3QgdGhlIGBhY2NvdW50LWlkYCBjb21wb25lbnQgZnJvbSB0aGUgQVJOLCB3ZSBjYW5cbiAgICogc3BsaXQgdGhlIEFSTiB1c2luZyBcIjpcIiBhbmQgc2VsZWN0IHRoZSBjb21wb25lbnQgaW4gaW5kZXggNC5cbiAgICpcbiAgICogQHJldHVybnMgdHJ1ZSBpZiBhY2NvdW50IGlkIG9mIGZ1bmN0aW9uIG1hdGNoZXMgdGhlIGFjY291bnQgc3BlY2lmaWVkIG9uIHRoZSBzdGFjaywgZmFsc2Ugb3RoZXJ3aXNlLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByb3RlY3RlZCBfaXNTdGFja0FjY291bnQoKTogYm9vbGVhbiB7XG4gICAgaWYgKFRva2VuLmlzVW5yZXNvbHZlZCh0aGlzLnN0YWNrLmFjY291bnQpIHx8IFRva2VuLmlzVW5yZXNvbHZlZCh0aGlzLmZ1bmN0aW9uQXJuKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zdGFjay5zcGxpdEFybih0aGlzLmZ1bmN0aW9uQXJuLCBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfTkFNRSkuYWNjb3VudCA9PT0gdGhpcy5zdGFjay5hY2NvdW50O1xuICB9XG5cbiAgcHJpdmF0ZSBncmFudChcbiAgICBncmFudGVlOiBpYW0uSUdyYW50YWJsZSxcbiAgICBpZGVudGlmaWVyOnN0cmluZyxcbiAgICBhY3Rpb246IHN0cmluZyxcbiAgICByZXNvdXJjZUFybnM6IHN0cmluZ1tdLFxuICAgIHBlcm1pc3Npb25PdmVycmlkZXM/OiBQYXJ0aWFsPFBlcm1pc3Npb24+LFxuICApOiBpYW0uR3JhbnQge1xuICAgIGNvbnN0IGdyYW50ID0gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsT3JSZXNvdXJjZSh7XG4gICAgICBncmFudGVlLFxuICAgICAgYWN0aW9uczogW2FjdGlvbl0sXG4gICAgICByZXNvdXJjZUFybnMsXG5cbiAgICAgIC8vIEZha2UgcmVzb3VyY2UtbGlrZSBvYmplY3Qgb24gd2hpY2ggdG8gY2FsbCBhZGRUb1Jlc291cmNlUG9saWN5KCksIHdoaWNoIGFjdHVhbGx5XG4gICAgICAvLyBjYWxscyBhZGRQZXJtaXNzaW9uKClcbiAgICAgIHJlc291cmNlOiB7XG4gICAgICAgIGFkZFRvUmVzb3VyY2VQb2xpY3k6IChfc3RhdGVtZW50KSA9PiB7XG4gICAgICAgICAgLy8gQ291bGRuJ3QgYWRkIHBlcm1pc3Npb25zIHRvIHRoZSBwcmluY2lwYWwsIHNvIGFkZCB0aGVtIGxvY2FsbHkuXG4gICAgICAgICAgdGhpcy5hZGRQZXJtaXNzaW9uKGlkZW50aWZpZXIsIHtcbiAgICAgICAgICAgIHByaW5jaXBhbDogZ3JhbnRlZS5ncmFudFByaW5jaXBhbCEsXG4gICAgICAgICAgICBhY3Rpb246IGFjdGlvbixcbiAgICAgICAgICAgIC4uLnBlcm1pc3Npb25PdmVycmlkZXMsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjb25zdCBwZXJtaXNzaW9uTm9kZSA9IHRoaXMuX2Z1bmN0aW9uTm9kZSgpLnRyeUZpbmRDaGlsZChpZGVudGlmaWVyKTtcbiAgICAgICAgICBpZiAoIXBlcm1pc3Npb25Ob2RlICYmICF0aGlzLl9za2lwUGVybWlzc2lvbnMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IG1vZGlmeSBwZXJtaXNzaW9uIHRvIGxhbWJkYSBmdW5jdGlvbi4gRnVuY3Rpb24gaXMgZWl0aGVyIGltcG9ydGVkIG9yICRMQVRFU1QgdmVyc2lvbi5cXG4nXG4gICAgICAgICAgICAgICsgJ0lmIHRoZSBmdW5jdGlvbiBpcyBpbXBvcnRlZCBmcm9tIHRoZSBzYW1lIGFjY291bnQgdXNlIGBmcm9tRnVuY3Rpb25BdHRyaWJ1dGVzKClgIEFQSSB3aXRoIHRoZSBgc2FtZUVudmlyb25tZW50YCBmbGFnLlxcbidcbiAgICAgICAgICAgICAgKyAnSWYgdGhlIGZ1bmN0aW9uIGlzIGltcG9ydGVkIGZyb20gYSBkaWZmZXJlbnQgYWNjb3VudCBhbmQgYWxyZWFkeSBoYXMgdGhlIGNvcnJlY3QgcGVybWlzc2lvbnMgdXNlIGBmcm9tRnVuY3Rpb25BdHRyaWJ1dGVzKClgIEFQSSB3aXRoIHRoZSBgc2tpcFBlcm1pc3Npb25zYCBmbGFnLicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4geyBzdGF0ZW1lbnRBZGRlZDogdHJ1ZSwgcG9saWN5RGVwZW5kYWJsZTogcGVybWlzc2lvbk5vZGUgfTtcbiAgICAgICAgfSxcbiAgICAgICAgbm9kZTogdGhpcy5ub2RlLFxuICAgICAgICBzdGFjazogdGhpcy5zdGFjayxcbiAgICAgICAgZW52OiB0aGlzLmVudixcbiAgICAgICAgYXBwbHlSZW1vdmFsUG9saWN5OiB0aGlzLmFwcGx5UmVtb3ZhbFBvbGljeSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICByZXR1cm4gZ3JhbnQ7XG4gIH1cblxuICAvKipcbiAgICogVHJhbnNsYXRlIElQcmluY2lwYWwgdG8gc29tZXRoaW5nIHdlIGNhbiBwYXNzIHRvIEFXUzo6TGFtYmRhOjpQZXJtaXNzaW9uc1xuICAgKlxuICAgKiBEbyBzb21lIG5hc3R5IHRoaW5ncyBiZWNhdXNlIGBQZXJtaXNzaW9uYCBzdXBwb3J0cyBhIHN1YnNldCBvZiB3aGF0IHRoZVxuICAgKiBmdWxsIElBTSBwcmluY2lwYWwgbGFuZ3VhZ2Ugc3VwcG9ydHMsIGFuZCB3ZSBtYXkgbm90IGJlIGFibGUgdG8gcGFyc2Ugc3RyaW5nc1xuICAgKiBvdXRyaWdodCBiZWNhdXNlIHRoZXkgbWF5IGJlIHRva2Vucy5cbiAgICpcbiAgICogVHJ5IHRvIHJlY29nbml6ZSBzb21lIHNwZWNpZmljIFByaW5jaXBhbCBjbGFzc2VzIGZpcnN0LCB0aGVuIHRyeSBhIGdlbmVyaWNcbiAgICogZmFsbGJhY2suXG4gICAqL1xuICBwcml2YXRlIHBhcnNlUGVybWlzc2lvblByaW5jaXBhbChwcmluY2lwYWw6IGlhbS5JUHJpbmNpcGFsKSB7XG4gICAgLy8gVHJ5IHNvbWUgc3BlY2lmaWMgY29tbW9uIGNsYXNzZXMgZmlyc3QuXG4gICAgLy8gdXNlIGR1Y2stdHlwaW5nLCBub3QgaW5zdGFuY2Ugb2ZcbiAgICAvLyBAZGVwcmVjYXRlZDogYWZ0ZXIgdjIsIHdlIGNhbiBjaGFuZ2UgdGhlc2UgdG8gJ2luc3RhbmNlb2YnXG4gICAgaWYgKCd3cmFwcGVkJyBpbiBwcmluY2lwYWwpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkb3Qtbm90YXRpb25cbiAgICAgIHByaW5jaXBhbCA9IHByaW5jaXBhbFsnd3JhcHBlZCddO1xuICAgIH1cblxuICAgIGlmICgnYWNjb3VudElkJyBpbiBwcmluY2lwYWwpIHtcbiAgICAgIHJldHVybiAocHJpbmNpcGFsIGFzIGlhbS5BY2NvdW50UHJpbmNpcGFsKS5hY2NvdW50SWQ7XG4gICAgfVxuXG4gICAgaWYgKCdzZXJ2aWNlJyBpbiBwcmluY2lwYWwpIHtcbiAgICAgIHJldHVybiAocHJpbmNpcGFsIGFzIGlhbS5TZXJ2aWNlUHJpbmNpcGFsKS5zZXJ2aWNlO1xuICAgIH1cblxuICAgIGlmICgnYXJuJyBpbiBwcmluY2lwYWwpIHtcbiAgICAgIHJldHVybiAocHJpbmNpcGFsIGFzIGlhbS5Bcm5QcmluY2lwYWwpLmFybjtcbiAgICB9XG5cbiAgICAvLyBUcnkgYSBiZXN0LWVmZm9ydCBhcHByb2FjaCB0byBzdXBwb3J0IHNpbXBsZSBwcmluY2lwYWxzIHRoYXQgYXJlIG5vdCBhbnkgb2YgdGhlIHByZWRlZmluZWRcbiAgICAvLyBjbGFzc2VzLCBidXQgYXJlIHNpbXBsZSBlbm91Z2ggdGhhdCB0aGV5IHdpbGwgZml0IGludG8gdGhlIFBlcm1pc3Npb24gbW9kZWwuIE1haW4gdGFyZ2V0XG4gICAgLy8gaGVyZTogaW1wb3J0ZWQgUm9sZXMsIFVzZXJzLCBHcm91cHMuXG4gICAgLy9cbiAgICAvLyBUaGUgcHJpbmNpcGFsIGNhbm5vdCBoYXZlIGNvbmRpdGlvbnMgYW5kIG11c3QgaGF2ZSBhIHNpbmdsZSB7IEFXUzogW2Fybl0gfSBlbnRyeS5cbiAgICBjb25zdCBqc29uID0gcHJpbmNpcGFsLnBvbGljeUZyYWdtZW50LnByaW5jaXBhbEpzb247XG4gICAgaWYgKE9iamVjdC5rZXlzKHByaW5jaXBhbC5wb2xpY3lGcmFnbWVudC5jb25kaXRpb25zKS5sZW5ndGggPT09IDAgJiYganNvbi5BV1MpIHtcbiAgICAgIGlmICh0eXBlb2YganNvbi5BV1MgPT09ICdzdHJpbmcnKSB7IHJldHVybiBqc29uLkFXUzsgfVxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoanNvbi5BV1MpICYmIGpzb24uQVdTLmxlbmd0aCA9PT0gMSAmJiB0eXBlb2YganNvbi5BV1NbMF0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBqc29uLkFXU1swXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcHJpbmNpcGFsIHR5cGUgZm9yIExhbWJkYSBwZXJtaXNzaW9uIHN0YXRlbWVudDogJHtwcmluY2lwYWwuY29uc3RydWN0b3IubmFtZX0uIGAgK1xuICAgICAgJ1N1cHBvcnRlZDogQWNjb3VudFByaW5jaXBhbCwgQXJuUHJpbmNpcGFsLCBTZXJ2aWNlUHJpbmNpcGFsJyk7XG4gIH1cblxuICBwcml2YXRlIHBhcnNlQ29uZGl0aW9ucyhwcmluY2lwYWw6IGlhbS5JUHJpbmNpcGFsKTogeyBzb3VyY2VBY2NvdW50OiBzdHJpbmcsIHNvdXJjZUFybjogc3RyaW5nIH0gfCBudWxsIHtcbiAgICBpZiAodGhpcy5pc1ByaW5jaXBhbFdpdGhDb25kaXRpb25zKHByaW5jaXBhbCkpIHtcbiAgICAgIGNvbnN0IGNvbmRpdGlvbnM6IGlhbS5Db25kaXRpb25zID0gcHJpbmNpcGFsLnBvbGljeUZyYWdtZW50LmNvbmRpdGlvbnM7XG4gICAgICBjb25zdCBjb25kaXRpb25QYWlycyA9IGZsYXRNYXAoXG4gICAgICAgIE9iamVjdC5lbnRyaWVzKGNvbmRpdGlvbnMpLFxuICAgICAgICAoW29wZXJhdG9yLCBjb25kaXRpb25PYmpzXSkgPT4gT2JqZWN0LmtleXMoY29uZGl0aW9uT2JqcyBhcyBvYmplY3QpLm1hcChrZXkgPT4geyByZXR1cm4geyBvcGVyYXRvciwga2V5IH07IH0pLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHN1cHBvcnRlZFByaW5jaXBhbENvbmRpdGlvbnMgPSBbeyBvcGVyYXRvcjogJ0Fybkxpa2UnLCBrZXk6ICdhd3M6U291cmNlQXJuJyB9LCB7IG9wZXJhdG9yOiAnU3RyaW5nRXF1YWxzJywga2V5OiAnYXdzOlNvdXJjZUFjY291bnQnIH1dO1xuXG4gICAgICBjb25zdCB1bnN1cHBvcnRlZENvbmRpdGlvbnMgPSBjb25kaXRpb25QYWlycy5maWx0ZXIoXG4gICAgICAgIChjb25kaXRpb24pID0+ICFzdXBwb3J0ZWRQcmluY2lwYWxDb25kaXRpb25zLnNvbWUoXG4gICAgICAgICAgKHN1cHBvcnRlZENvbmRpdGlvbikgPT4gc3VwcG9ydGVkQ29uZGl0aW9uLm9wZXJhdG9yID09PSBjb25kaXRpb24ub3BlcmF0b3IgJiYgc3VwcG9ydGVkQ29uZGl0aW9uLmtleSA9PT0gY29uZGl0aW9uLmtleSxcbiAgICAgICAgKSxcbiAgICAgICk7XG5cbiAgICAgIGlmICh1bnN1cHBvcnRlZENvbmRpdGlvbnMubGVuZ3RoID09IDApIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzb3VyY2VBY2NvdW50OiBjb25kaXRpb25zLlN0cmluZ0VxdWFsc1snYXdzOlNvdXJjZUFjY291bnQnXSxcbiAgICAgICAgICBzb3VyY2VBcm46IGNvbmRpdGlvbnMuQXJuTGlrZVsnYXdzOlNvdXJjZUFybiddLFxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQcmluY2lwYWxXaXRoQ29uZGl0aW9ucyBoYWQgdW5zdXBwb3J0ZWQgY29uZGl0aW9ucyBmb3IgTGFtYmRhIHBlcm1pc3Npb24gc3RhdGVtZW50OiAke0pTT04uc3RyaW5naWZ5KHVuc3VwcG9ydGVkQ29uZGl0aW9ucyl9LiBgICtcbiAgICAgICAgICBgU3VwcG9ydGVkIG9wZXJhdG9yL2NvbmRpdGlvbiBwYWlyczogJHtKU09OLnN0cmluZ2lmeShzdXBwb3J0ZWRQcmluY2lwYWxDb25kaXRpb25zKX1gKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpc1ByaW5jaXBhbFdpdGhDb25kaXRpb25zKHByaW5jaXBhbDogaWFtLklQcmluY2lwYWwpOiBwcmluY2lwYWwgaXMgaWFtLlByaW5jaXBhbFdpdGhDb25kaXRpb25zIHtcbiAgICByZXR1cm4gJ2NvbmRpdGlvbnMnIGluIHByaW5jaXBhbDtcbiAgfVxufVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUXVhbGlmaWVkRnVuY3Rpb25CYXNlIGV4dGVuZHMgRnVuY3Rpb25CYXNlIHtcbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IGxhbWJkYTogSUZ1bmN0aW9uO1xuXG4gIHB1YmxpYyByZWFkb25seSBwZXJtaXNzaW9uc05vZGUgPSB0aGlzLm5vZGU7XG5cbiAgLyoqXG4gICAqIFRoZSBxdWFsaWZpZXIgb2YgdGhlIHZlcnNpb24gb3IgYWxpYXMgb2YgdGhpcyBmdW5jdGlvbi5cbiAgICogQSBxdWFsaWZpZXIgaXMgdGhlIGlkZW50aWZpZXIgdGhhdCdzIGFwcGVuZGVkIHRvIGEgdmVyc2lvbiBvciBhbGlhcyBBUk4uXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2xhbWJkYS9sYXRlc3QvZGcvQVBJX0dldEZ1bmN0aW9uQ29uZmlndXJhdGlvbi5odG1sI0FQSV9HZXRGdW5jdGlvbkNvbmZpZ3VyYXRpb25fUmVxdWVzdFBhcmFtZXRlcnNcbiAgICovXG4gIHByb3RlY3RlZCBhYnN0cmFjdCByZWFkb25seSBxdWFsaWZpZXI6IHN0cmluZztcblxuICBwdWJsaWMgZ2V0IGxhdGVzdFZlcnNpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMubGFtYmRhLmxhdGVzdFZlcnNpb247XG4gIH1cblxuICBwdWJsaWMgZ2V0IHJlc291cmNlQXJuc0ZvckdyYW50SW52b2tlKCkge1xuICAgIHJldHVybiBbdGhpcy5mdW5jdGlvbkFybl07XG4gIH1cblxuICBwdWJsaWMgY29uZmlndXJlQXN5bmNJbnZva2Uob3B0aW9uczogRXZlbnRJbnZva2VDb25maWdPcHRpb25zKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubm9kZS50cnlGaW5kQ2hpbGQoJ0V2ZW50SW52b2tlQ29uZmlnJykgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBBbiBFdmVudEludm9rZUNvbmZpZyBoYXMgYWxyZWFkeSBiZWVuIGNvbmZpZ3VyZWQgZm9yIHRoZSBxdWFsaWZpZWQgZnVuY3Rpb24gYXQgJHt0aGlzLm5vZGUucGF0aH1gKTtcbiAgICB9XG5cbiAgICBuZXcgRXZlbnRJbnZva2VDb25maWcodGhpcywgJ0V2ZW50SW52b2tlQ29uZmlnJywge1xuICAgICAgZnVuY3Rpb246IHRoaXMubGFtYmRhLFxuICAgICAgcXVhbGlmaWVyOiB0aGlzLnF1YWxpZmllcixcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgY29uc2lkZXJXYXJuaW5nT25JbnZva2VGdW5jdGlvblBlcm1pc3Npb25zKF9zY29wZTogQ29uc3RydWN0LCBfYWN0aW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAvLyBub09wXG4gICAgcmV0dXJuO1xuICB9XG59XG5cbi8qKlxuICogVGhlICRMQVRFU1QgdmVyc2lvbiBvZiBhIGZ1bmN0aW9uLCB1c2VmdWwgd2hlbiBhdHRlbXB0aW5nIHRvIGNyZWF0ZSBhbGlhc2VzLlxuICovXG5jbGFzcyBMYXRlc3RWZXJzaW9uIGV4dGVuZHMgRnVuY3Rpb25CYXNlIGltcGxlbWVudHMgSVZlcnNpb24ge1xuICBwdWJsaWMgcmVhZG9ubHkgbGFtYmRhOiBJRnVuY3Rpb247XG4gIHB1YmxpYyByZWFkb25seSB2ZXJzaW9uID0gJyRMQVRFU1QnO1xuICBwdWJsaWMgcmVhZG9ubHkgcGVybWlzc2lvbnNOb2RlID0gdGhpcy5ub2RlO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBjYW5DcmVhdGVQZXJtaXNzaW9ucyA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKGxhbWJkYTogRnVuY3Rpb25CYXNlKSB7XG4gICAgc3VwZXIobGFtYmRhLCAnJExBVEVTVCcpO1xuICAgIHRoaXMubGFtYmRhID0gbGFtYmRhO1xuICB9XG5cbiAgcHVibGljIGdldCBmdW5jdGlvbkFybigpIHtcbiAgICByZXR1cm4gYCR7dGhpcy5sYW1iZGEuZnVuY3Rpb25Bcm59OiR7dGhpcy52ZXJzaW9ufWA7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGZ1bmN0aW9uTmFtZSgpIHtcbiAgICByZXR1cm4gYCR7dGhpcy5sYW1iZGEuZnVuY3Rpb25OYW1lfToke3RoaXMudmVyc2lvbn1gO1xuICB9XG5cbiAgcHVibGljIGdldCBhcmNoaXRlY3R1cmUoKSB7XG4gICAgcmV0dXJuIHRoaXMubGFtYmRhLmFyY2hpdGVjdHVyZTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgZ3JhbnRQcmluY2lwYWwoKSB7XG4gICAgcmV0dXJuIHRoaXMubGFtYmRhLmdyYW50UHJpbmNpcGFsO1xuICB9XG5cbiAgcHVibGljIGdldCBsYXRlc3RWZXJzaW9uKCkge1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHVibGljIGdldCByb2xlKCkge1xuICAgIHJldHVybiB0aGlzLmxhbWJkYS5yb2xlO1xuICB9XG5cbiAgcHVibGljIGdldCBlZGdlQXJuKCk6IG5ldmVyIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJyRMQVRFU1QgZnVuY3Rpb24gdmVyc2lvbiBjYW5ub3QgYmUgdXNlZCBmb3IgTGFtYmRhQEVkZ2UnKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgcmVzb3VyY2VBcm5zRm9yR3JhbnRJbnZva2UoKSB7XG4gICAgcmV0dXJuIFt0aGlzLmZ1bmN0aW9uQXJuXTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRBbGlhcyhhbGlhc05hbWU6IHN0cmluZywgb3B0aW9uczogQWxpYXNPcHRpb25zID0ge30pIHtcbiAgICByZXR1cm4gYWRkQWxpYXModGhpcywgdGhpcywgYWxpYXNOYW1lLCBvcHRpb25zKTtcbiAgfVxufVxuIl19
\No newline at end of file