UNPKG

73.4 kBJavaScriptView Raw
1"use strict";
2var _a;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.deriveEstimateSizeOptions = exports.Effect = exports.PolicyStatement = void 0;
5const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const cdk = require("@aws-cdk/core");
8const group_1 = require("./group");
9const principals_1 = require("./principals");
10const postprocess_policy_document_1 = require("./private/postprocess-policy-document");
11const util_1 = require("./util");
12const ensureArrayOrUndefined = (field) => {
13 if (field === undefined) {
14 return undefined;
15 }
16 if (typeof (field) !== 'string' && !Array.isArray(field)) {
17 throw new Error('Fields must be either a string or an array of strings');
18 }
19 if (Array.isArray(field) && !!field.find((f) => typeof (f) !== 'string')) {
20 throw new Error('Fields must be either a string or an array of strings');
21 }
22 return Array.isArray(field) ? field : [field];
23};
24/**
25 * An estimate on how long ARNs typically are
26 *
27 * This is used to decide when to start splitting statements into new Managed Policies.
28 * Because we often can't know the length of an ARN (it may be a token and only
29 * available at deployment time) we'll have to estimate it.
30 *
31 * The estimate can be overridden by setting the `@aws-cdk/aws-iam.arnSizeEstimate` context key.
32 */
33const DEFAULT_ARN_SIZE_ESTIMATE = 150;
34/**
35 * Context key which can be used to override the estimated length of unresolved ARNs.
36 */
37const ARN_SIZE_ESTIMATE_CONTEXT_KEY = '@aws-cdk/aws-iam.arnSizeEstimate';
38/**
39 * Represents a statement in an IAM policy document.
40 */
41class PolicyStatement {
42 constructor(props = {}) {
43 this._action = new Array();
44 this._notAction = new Array();
45 this._principal = {};
46 this._notPrincipal = {};
47 this._resource = new Array();
48 this._notResource = new Array();
49 this._condition = {};
50 // Hold on to those principals
51 this._principals = new Array();
52 this._notPrincipals = new Array();
53 try {
54 jsiiDeprecationWarnings._aws_cdk_aws_iam_PolicyStatementProps(props);
55 }
56 catch (error) {
57 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
58 Error.captureStackTrace(error, PolicyStatement);
59 }
60 throw error;
61 }
62 // Validate actions
63 for (const action of [...props.actions || [], ...props.notActions || []]) {
64 if (!/^(\*|[a-zA-Z0-9-]+:[a-zA-Z0-9*]+)$/.test(action) && !cdk.Token.isUnresolved(action)) {
65 throw new Error(`Action '${action}' is invalid. An action string consists of a service namespace, a colon, and the name of an action. Action names can include wildcards.`);
66 }
67 }
68 this.sid = props.sid;
69 this.effect = props.effect || Effect.ALLOW;
70 this.addActions(...props.actions || []);
71 this.addNotActions(...props.notActions || []);
72 this.addPrincipals(...props.principals || []);
73 this.addNotPrincipals(...props.notPrincipals || []);
74 this.addResources(...props.resources || []);
75 this.addNotResources(...props.notResources || []);
76 if (props.conditions !== undefined) {
77 this.addConditions(props.conditions);
78 }
79 }
80 /**
81 * Creates a new PolicyStatement based on the object provided.
82 * This will accept an object created from the `.toJSON()` call
83 * @param obj the PolicyStatement in object form.
84 */
85 static fromJson(obj) {
86 const ret = new PolicyStatement({
87 sid: obj.Sid,
88 actions: ensureArrayOrUndefined(obj.Action),
89 resources: ensureArrayOrUndefined(obj.Resource),
90 conditions: obj.Condition,
91 effect: obj.Effect,
92 notActions: ensureArrayOrUndefined(obj.NotAction),
93 notResources: ensureArrayOrUndefined(obj.NotResource),
94 principals: obj.Principal ? [new JsonPrincipal(obj.Principal)] : undefined,
95 notPrincipals: obj.NotPrincipal ? [new JsonPrincipal(obj.NotPrincipal)] : undefined,
96 });
97 // validate that the PolicyStatement has the correct shape
98 const errors = ret.validateForAnyPolicy();
99 if (errors.length > 0) {
100 throw new Error('Incorrect Policy Statement: ' + errors.join('\n'));
101 }
102 return ret;
103 }
104 //
105 // Actions
106 //
107 /**
108 * Specify allowed actions into the "Action" section of the policy statement.
109 *
110 * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_action.html
111 *
112 * @param actions actions that will be allowed.
113 */
114 addActions(...actions) {
115 if (actions.length > 0 && this._notAction.length > 0) {
116 throw new Error('Cannot add \'Actions\' to policy statement if \'NotActions\' have been added');
117 }
118 this._action.push(...actions);
119 }
120 /**
121 * Explicitly allow all actions except the specified list of actions into the "NotAction" section
122 * of the policy document.
123 *
124 * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html
125 *
126 * @param notActions actions that will be denied. All other actions will be permitted.
127 */
128 addNotActions(...notActions) {
129 if (notActions.length > 0 && this._action.length > 0) {
130 throw new Error('Cannot add \'NotActions\' to policy statement if \'Actions\' have been added');
131 }
132 this._notAction.push(...notActions);
133 }
134 //
135 // Principal
136 //
137 /**
138 * Indicates if this permission has a "Principal" section.
139 */
140 get hasPrincipal() {
141 return this._principals.length + this._notPrincipals.length > 0;
142 }
143 /**
144 * Adds principals to the "Principal" section of a policy statement.
145 *
146 * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html
147 *
148 * @param principals IAM principals that will be added
149 */
150 addPrincipals(...principals) {
151 try {
152 jsiiDeprecationWarnings._aws_cdk_aws_iam_IPrincipal(principals);
153 }
154 catch (error) {
155 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
156 Error.captureStackTrace(error, this.addPrincipals);
157 }
158 throw error;
159 }
160 this._principals.push(...principals);
161 if (Object.keys(principals).length > 0 && Object.keys(this._notPrincipal).length > 0) {
162 throw new Error('Cannot add \'Principals\' to policy statement if \'NotPrincipals\' have been added');
163 }
164 for (const principal of principals) {
165 this.validatePolicyPrincipal(principal);
166 const fragment = principal.policyFragment;
167 util_1.mergePrincipal(this._principal, fragment.principalJson);
168 this.addPrincipalConditions(fragment.conditions);
169 }
170 }
171 /**
172 * Specify principals that is not allowed or denied access to the "NotPrincipal" section of
173 * a policy statement.
174 *
175 * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notprincipal.html
176 *
177 * @param notPrincipals IAM principals that will be denied access
178 */
179 addNotPrincipals(...notPrincipals) {
180 try {
181 jsiiDeprecationWarnings._aws_cdk_aws_iam_IPrincipal(notPrincipals);
182 }
183 catch (error) {
184 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
185 Error.captureStackTrace(error, this.addNotPrincipals);
186 }
187 throw error;
188 }
189 this._notPrincipals.push(...notPrincipals);
190 if (Object.keys(notPrincipals).length > 0 && Object.keys(this._principal).length > 0) {
191 throw new Error('Cannot add \'NotPrincipals\' to policy statement if \'Principals\' have been added');
192 }
193 for (const notPrincipal of notPrincipals) {
194 this.validatePolicyPrincipal(notPrincipal);
195 const fragment = notPrincipal.policyFragment;
196 util_1.mergePrincipal(this._notPrincipal, fragment.principalJson);
197 this.addPrincipalConditions(fragment.conditions);
198 }
199 }
200 validatePolicyPrincipal(principal) {
201 if (principal instanceof group_1.Group) {
202 throw new Error('Cannot use an IAM Group as the \'Principal\' or \'NotPrincipal\' in an IAM Policy');
203 }
204 }
205 /**
206 * Specify AWS account ID as the principal entity to the "Principal" section of a policy statement.
207 */
208 addAwsAccountPrincipal(accountId) {
209 this.addPrincipals(new principals_1.AccountPrincipal(accountId));
210 }
211 /**
212 * Specify a principal using the ARN identifier of the principal.
213 * You cannot specify IAM groups and instance profiles as principals.
214 *
215 * @param arn ARN identifier of AWS account, IAM user, or IAM role (i.e. arn:aws:iam::123456789012:user/user-name)
216 */
217 addArnPrincipal(arn) {
218 this.addPrincipals(new principals_1.ArnPrincipal(arn));
219 }
220 /**
221 * Adds a service principal to this policy statement.
222 *
223 * @param service the service name for which a service principal is requested (e.g: `s3.amazonaws.com`).
224 * @param opts options for adding the service principal (such as specifying a principal in a different region)
225 */
226 addServicePrincipal(service, opts) {
227 try {
228 jsiiDeprecationWarnings._aws_cdk_aws_iam_ServicePrincipalOpts(opts);
229 }
230 catch (error) {
231 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
232 Error.captureStackTrace(error, this.addServicePrincipal);
233 }
234 throw error;
235 }
236 this.addPrincipals(new principals_1.ServicePrincipal(service, opts));
237 }
238 /**
239 * Adds a federated identity provider such as Amazon Cognito to this policy statement.
240 *
241 * @param federated federated identity provider (i.e. 'cognito-identity.amazonaws.com')
242 * @param conditions The conditions under which the policy is in effect.
243 * See [the IAM documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html).
244 */
245 addFederatedPrincipal(federated, conditions) {
246 this.addPrincipals(new principals_1.FederatedPrincipal(federated, conditions));
247 }
248 /**
249 * Adds an AWS account root user principal to this policy statement
250 */
251 addAccountRootPrincipal() {
252 this.addPrincipals(new principals_1.AccountRootPrincipal());
253 }
254 /**
255 * Adds a canonical user ID principal to this policy document
256 *
257 * @param canonicalUserId unique identifier assigned by AWS for every account
258 */
259 addCanonicalUserPrincipal(canonicalUserId) {
260 this.addPrincipals(new principals_1.CanonicalUserPrincipal(canonicalUserId));
261 }
262 /**
263 * Adds all identities in all accounts ("*") to this policy statement
264 */
265 addAnyPrincipal() {
266 this.addPrincipals(new principals_1.AnyPrincipal());
267 }
268 //
269 // Resources
270 //
271 /**
272 * Specify resources that this policy statement applies into the "Resource" section of
273 * this policy statement.
274 *
275 * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_resource.html
276 *
277 * @param arns Amazon Resource Names (ARNs) of the resources that this policy statement applies to
278 */
279 addResources(...arns) {
280 if (arns.length > 0 && this._notResource.length > 0) {
281 throw new Error('Cannot add \'Resources\' to policy statement if \'NotResources\' have been added');
282 }
283 this._resource.push(...arns);
284 }
285 /**
286 * Specify resources that this policy statement will not apply to in the "NotResource" section
287 * of this policy statement. All resources except the specified list will be matched.
288 *
289 * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notresource.html
290 *
291 * @param arns Amazon Resource Names (ARNs) of the resources that this policy statement does not apply to
292 */
293 addNotResources(...arns) {
294 if (arns.length > 0 && this._resource.length > 0) {
295 throw new Error('Cannot add \'NotResources\' to policy statement if \'Resources\' have been added');
296 }
297 this._notResource.push(...arns);
298 }
299 /**
300 * Adds a ``"*"`` resource to this statement.
301 */
302 addAllResources() {
303 this.addResources('*');
304 }
305 /**
306 * Indicates if this permission has at least one resource associated with it.
307 */
308 get hasResource() {
309 return this._resource && this._resource.length > 0;
310 }
311 //
312 // Condition
313 //
314 /**
315 * Add a condition to the Policy
316 *
317 * If multiple calls are made to add a condition with the same operator and field, only
318 * the last one wins. For example:
319 *
320 * ```ts
321 * declare const stmt: iam.PolicyStatement;
322 *
323 * stmt.addCondition('StringEquals', { 'aws:SomeField': '1' });
324 * stmt.addCondition('StringEquals', { 'aws:SomeField': '2' });
325 * ```
326 *
327 * Will end up with the single condition `StringEquals: { 'aws:SomeField': '2' }`.
328 *
329 * If you meant to add a condition to say that the field can be *either* `1` or `2`, write
330 * this:
331 *
332 * ```ts
333 * declare const stmt: iam.PolicyStatement;
334 *
335 * stmt.addCondition('StringEquals', { 'aws:SomeField': ['1', '2'] });
336 * ```
337 */
338 addCondition(key, value) {
339 const existingValue = this._condition[key];
340 this._condition[key] = existingValue ? { ...existingValue, ...value } : value;
341 }
342 /**
343 * Add multiple conditions to the Policy
344 *
345 * See the `addCondition` function for a caveat on calling this method multiple times.
346 */
347 addConditions(conditions) {
348 Object.keys(conditions).map(key => {
349 this.addCondition(key, conditions[key]);
350 });
351 }
352 /**
353 * Add a condition that limits to a given account
354 *
355 * This method can only be called once: subsequent calls will overwrite earlier calls.
356 */
357 addAccountCondition(accountId) {
358 this.addCondition('StringEquals', { 'sts:ExternalId': accountId });
359 }
360 /**
361 * Create a new `PolicyStatement` with the same exact properties
362 * as this one, except for the overrides
363 */
364 copy(overrides = {}) {
365 try {
366 jsiiDeprecationWarnings._aws_cdk_aws_iam_PolicyStatementProps(overrides);
367 }
368 catch (error) {
369 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
370 Error.captureStackTrace(error, this.copy);
371 }
372 throw error;
373 }
374 return new PolicyStatement({
375 sid: overrides.sid ?? this.sid,
376 effect: overrides.effect ?? this.effect,
377 actions: overrides.actions ?? this.actions,
378 notActions: overrides.notActions ?? this.notActions,
379 principals: overrides.principals ?? this.principals,
380 notPrincipals: overrides.notPrincipals ?? this.notPrincipals,
381 resources: overrides.resources ?? this.resources,
382 notResources: overrides.notResources ?? this.notResources,
383 conditions: overrides.conditions ?? this.conditions,
384 });
385 }
386 /**
387 * JSON-ify the policy statement
388 *
389 * Used when JSON.stringify() is called
390 */
391 toStatementJson() {
392 return postprocess_policy_document_1.normalizeStatement({
393 Action: this._action,
394 NotAction: this._notAction,
395 Condition: this._condition,
396 Effect: this.effect,
397 Principal: this._principal,
398 NotPrincipal: this._notPrincipal,
399 Resource: this._resource,
400 NotResource: this._notResource,
401 Sid: this.sid,
402 });
403 }
404 /**
405 * String representation of this policy statement
406 */
407 toString() {
408 return cdk.Token.asString(this, {
409 displayHint: 'PolicyStatement',
410 });
411 }
412 /**
413 * JSON-ify the statement
414 *
415 * Used when JSON.stringify() is called
416 */
417 toJSON() {
418 return this.toStatementJson();
419 }
420 /**
421 * Add a principal's conditions
422 *
423 * For convenience, principals have been modeled as both a principal
424 * and a set of conditions. This makes it possible to have a single
425 * object represent e.g. an "SNS Topic" (SNS service principal + aws:SourcArn
426 * condition) or an Organization member (* + aws:OrgId condition).
427 *
428 * However, when using multiple principals in the same policy statement,
429 * they must all have the same conditions or the OR samentics
430 * implied by a list of principals cannot be guaranteed (user needs to
431 * add multiple statements in that case).
432 */
433 addPrincipalConditions(conditions) {
434 // Stringifying the conditions is an easy way to do deep equality
435 const theseConditions = JSON.stringify(conditions);
436 if (this.principalConditionsJson === undefined) {
437 // First principal, anything goes
438 this.principalConditionsJson = theseConditions;
439 }
440 else {
441 if (this.principalConditionsJson !== theseConditions) {
442 throw new Error(`All principals in a PolicyStatement must have the same Conditions (got '${this.principalConditionsJson}' and '${theseConditions}'). Use multiple statements instead.`);
443 }
444 }
445 this.addConditions(conditions);
446 }
447 /**
448 * Validate that the policy statement satisfies base requirements for a policy.
449 *
450 * @returns An array of validation error messages, or an empty array if the statement is valid.
451 */
452 validateForAnyPolicy() {
453 const errors = new Array();
454 if (this._action.length === 0 && this._notAction.length === 0) {
455 errors.push('A PolicyStatement must specify at least one \'action\' or \'notAction\'.');
456 }
457 return errors;
458 }
459 /**
460 * Validate that the policy statement satisfies all requirements for a resource-based policy.
461 *
462 * @returns An array of validation error messages, or an empty array if the statement is valid.
463 */
464 validateForResourcePolicy() {
465 const errors = this.validateForAnyPolicy();
466 if (Object.keys(this._principal).length === 0 && Object.keys(this._notPrincipal).length === 0) {
467 errors.push('A PolicyStatement used in a resource-based policy must specify at least one IAM principal.');
468 }
469 return errors;
470 }
471 /**
472 * Validate that the policy statement satisfies all requirements for an identity-based policy.
473 *
474 * @returns An array of validation error messages, or an empty array if the statement is valid.
475 */
476 validateForIdentityPolicy() {
477 const errors = this.validateForAnyPolicy();
478 if (Object.keys(this._principal).length > 0 || Object.keys(this._notPrincipal).length > 0) {
479 errors.push('A PolicyStatement used in an identity-based policy cannot specify any IAM principals.');
480 }
481 if (Object.keys(this._resource).length === 0 && Object.keys(this._notResource).length === 0) {
482 errors.push('A PolicyStatement used in an identity-based policy must specify at least one resource.');
483 }
484 return errors;
485 }
486 /**
487 * The Actions added to this statement
488 */
489 get actions() {
490 return [...this._action];
491 }
492 /**
493 * The NotActions added to this statement
494 */
495 get notActions() {
496 return [...this._notAction];
497 }
498 /**
499 * The Principals added to this statement
500 */
501 get principals() {
502 return [...this._principals];
503 }
504 /**
505 * The NotPrincipals added to this statement
506 */
507 get notPrincipals() {
508 return [...this._notPrincipals];
509 }
510 /**
511 * The Resources added to this statement
512 */
513 get resources() {
514 return [...this._resource];
515 }
516 /**
517 * The NotResources added to this statement
518 */
519 get notResources() {
520 return [...this._notResource];
521 }
522 /**
523 * The conditions added to this statement
524 */
525 get conditions() {
526 return { ...this._condition };
527 }
528 /**
529 * Estimate the size of this policy statement
530 *
531 * By necessity, this will not be accurate. We'll do our best to overestimate
532 * so we won't have nasty surprises.
533 *
534 * @internal
535 */
536 _estimateSize(options) {
537 let ret = 0;
538 const { actionEstimate, arnEstimate } = options;
539 ret += `"Effect": "${this.effect}",`.length;
540 count('Action', this.actions, actionEstimate);
541 count('NotAction', this.notActions, actionEstimate);
542 count('Resource', this.resources, arnEstimate);
543 count('NotResource', this.notResources, arnEstimate);
544 ret += this.principals.length * arnEstimate;
545 ret += this.notPrincipals.length * arnEstimate;
546 ret += JSON.stringify(this.conditions).length;
547 return ret;
548 function count(key, values, tokenSize) {
549 if (values.length > 0) {
550 ret += key.length + 5 /* quotes, colon, brackets */ +
551 util_1.sum(values.map(v => (cdk.Token.isUnresolved(v) ? tokenSize : v.length) + 3 /* quotes, separator */));
552 }
553 }
554 }
555}
556exports.PolicyStatement = PolicyStatement;
557_a = JSII_RTTI_SYMBOL_1;
558PolicyStatement[_a] = { fqn: "@aws-cdk/aws-iam.PolicyStatement", version: "1.161.0" };
559/**
560 * The Effect element of an IAM policy
561 *
562 * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_effect.html
563 */
564var Effect;
565(function (Effect) {
566 /**
567 * Allows access to a resource in an IAM policy statement. By default, access to resources are denied.
568 */
569 Effect["ALLOW"] = "Allow";
570 /**
571 * Explicitly deny access to a resource. By default, all requests are denied implicitly.
572 *
573 * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html
574 */
575 Effect["DENY"] = "Deny";
576})(Effect = exports.Effect || (exports.Effect = {}));
577class JsonPrincipal extends principals_1.PrincipalBase {
578 constructor(json = {}) {
579 super();
580 // special case: if principal is a string, turn it into a "LiteralString" principal,
581 // so we render the exact same string back out.
582 if (typeof (json) === 'string') {
583 json = { [util_1.LITERAL_STRING_KEY]: [json] };
584 }
585 if (typeof (json) !== 'object') {
586 throw new Error(`JSON IAM principal should be an object, got ${JSON.stringify(json)}`);
587 }
588 this.policyFragment = {
589 principalJson: json,
590 conditions: {},
591 };
592 }
593 dedupeString() {
594 return JSON.stringify(this.policyFragment);
595 }
596}
597/**
598 * Derive the size estimation options from context
599 *
600 * @internal
601 */
602function deriveEstimateSizeOptions(scope) {
603 const actionEstimate = 20;
604 const arnEstimate = scope.node.tryGetContext(ARN_SIZE_ESTIMATE_CONTEXT_KEY) ?? DEFAULT_ARN_SIZE_ESTIMATE;
605 if (typeof arnEstimate !== 'number') {
606 throw new Error(`Context value ${ARN_SIZE_ESTIMATE_CONTEXT_KEY} should be a number, got ${JSON.stringify(arnEstimate)}`);
607 }
608 return { actionEstimate, arnEstimate };
609}
610exports.deriveEstimateSizeOptions = deriveEstimateSizeOptions;
611//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9saWN5LXN0YXRlbWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInBvbGljeS1zdGF0ZW1lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEscUNBQXFDO0FBRXJDLG1DQUFnQztBQUNoQyw2Q0FHc0I7QUFDdEIsdUZBQTJFO0FBQzNFLGlDQUFpRTtBQUVqRSxNQUFNLHNCQUFzQixHQUFHLENBQUMsS0FBVSxFQUFFLEVBQUU7SUFDNUMsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFO1FBQ3ZCLE9BQU8sU0FBUyxDQUFDO0tBQ2xCO0lBQ0QsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtRQUN4RCxNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7S0FDMUU7SUFDRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLENBQUMsRUFBRTtRQUM3RSxNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7S0FDMUU7SUFDRCxPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNoRCxDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7R0FRRztBQUNILE1BQU0seUJBQXlCLEdBQUcsR0FBRyxDQUFDO0FBRXRDOztHQUVHO0FBQ0gsTUFBTSw2QkFBNkIsR0FBRyxrQ0FBa0MsQ0FBQztBQUV6RTs7R0FFRztBQUNILE1BQWEsZUFBZTtJQW9EMUIsWUFBWSxRQUE4QixFQUFFO1FBYjNCLFlBQU8sR0FBRyxJQUFJLEtBQUssRUFBVSxDQUFD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QUM7QUFSRCw4REFRQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNkayBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IElDb25zdHJ1Y3QgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IEdyb3VwIH0gZnJvbSAnLi9ncm91cCc7XG5pbXBvcnQge1xuICBBY2NvdW50UHJpbmNpcGFsLCBBY2NvdW50Um9vdFByaW5jaXBhbCwgQW55UHJpbmNpcGFsLCBBcm5QcmluY2lwYWwsIENhbm9uaWNhbFVzZXJQcmluY2lwYWwsXG4gIEZlZGVyYXRlZFByaW5jaXBhbCwgSVByaW5jaXBhbCwgUHJpbmNpcGFsQmFzZSwgUHJpbmNpcGFsUG9saWN5RnJhZ21lbnQsIFNlcnZpY2VQcmluY2lwYWwsIFNlcnZpY2VQcmluY2lwYWxPcHRzLFxufSBmcm9tICcuL3ByaW5jaXBhbHMnO1xuaW1wb3J0IHsgbm9ybWFsaXplU3RhdGVtZW50IH0gZnJvbSAnLi9wcml2YXRlL3Bvc3Rwcm9jZXNzLXBvbGljeS1kb2N1bWVudCc7XG5pbXBvcnQgeyBMSVRFUkFMX1NUUklOR19LRVksIG1lcmdlUHJpbmNpcGFsLCBzdW0gfSBmcm9tICcuL3V0aWwnO1xuXG5jb25zdCBlbnN1cmVBcnJheU9yVW5kZWZpbmVkID0gKGZpZWxkOiBhbnkpID0+IHtcbiAgaWYgKGZpZWxkID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIGlmICh0eXBlb2YgKGZpZWxkKSAhPT0gJ3N0cmluZycgJiYgIUFycmF5LmlzQXJyYXkoZmllbGQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGaWVsZHMgbXVzdCBiZSBlaXRoZXIgYSBzdHJpbmcgb3IgYW4gYXJyYXkgb2Ygc3RyaW5ncycpO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KGZpZWxkKSAmJiAhIWZpZWxkLmZpbmQoKGY6IGFueSkgPT4gdHlwZW9mIChmKSAhPT0gJ3N0cmluZycpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGaWVsZHMgbXVzdCBiZSBlaXRoZXIgYSBzdHJpbmcgb3IgYW4gYXJyYXkgb2Ygc3RyaW5ncycpO1xuICB9XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGZpZWxkKSA/IGZpZWxkIDogW2ZpZWxkXTtcbn07XG5cbi8qKlxuICogQW4gZXN0aW1hdGUgb24gaG93IGxvbmcgQVJOcyB0eXBpY2FsbHkgYXJlXG4gKlxuICogVGhpcyBpcyB1c2VkIHRvIGRlY2lkZSB3aGVuIHRvIHN0YXJ0IHNwbGl0dGluZyBzdGF0ZW1lbnRzIGludG8gbmV3IE1hbmFnZWQgUG9saWNpZXMuXG4gKiBCZWNhdXNlIHdlIG9mdGVuIGNhbid0IGtub3cgdGhlIGxlbmd0aCBvZiBhbiBBUk4gKGl0IG1heSBiZSBhIHRva2VuIGFuZCBvbmx5XG4gKiBhdmFpbGFibGUgYXQgZGVwbG95bWVudCB0aW1lKSB3ZSdsbCBoYXZlIHRvIGVzdGltYXRlIGl0LlxuICpcbiAqIFRoZSBlc3RpbWF0ZSBjYW4gYmUgb3ZlcnJpZGRlbiBieSBzZXR0aW5nIHRoZSBgQGF3cy1jZGsvYXdzLWlhbS5hcm5TaXplRXN0aW1hdGVgIGNvbnRleHQga2V5LlxuICovXG5jb25zdCBERUZBVUxUX0FSTl9TSVpFX0VTVElNQVRFID0gMTUwO1xuXG4vKipcbiAqIENvbnRleHQga2V5IHdoaWNoIGNhbiBiZSB1c2VkIHRvIG92ZXJyaWRlIHRoZSBlc3RpbWF0ZWQgbGVuZ3RoIG9mIHVucmVzb2x2ZWQgQVJOcy5cbiAqL1xuY29uc3QgQVJOX1NJWkVfRVNUSU1BVEVfQ09OVEVYVF9LRVkgPSAnQGF3cy1jZGsvYXdzLWlhbS5hcm5TaXplRXN0aW1hdGUnO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBzdGF0ZW1lbnQgaW4gYW4gSUFNIHBvbGljeSBkb2N1bWVudC5cbiAqL1xuZXhwb3J0IGNsYXNzIFBvbGljeVN0YXRlbWVudCB7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgUG9saWN5U3RhdGVtZW50IGJhc2VkIG9uIHRoZSBvYmplY3QgcHJvdmlkZWQuXG4gICAqIFRoaXMgd2lsbCBhY2NlcHQgYW4gb2JqZWN0IGNyZWF0ZWQgZnJvbSB0aGUgYC50b0pTT04oKWAgY2FsbFxuICAgKiBAcGFyYW0gb2JqIHRoZSBQb2xpY3lTdGF0ZW1lbnQgaW4gb2JqZWN0IGZvcm0uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21Kc29uKG9iajogYW55KSB7XG4gICAgY29uc3QgcmV0ID0gbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICBzaWQ6IG9iai5TaWQsXG4gICAgICBhY3Rpb25zOiBlbnN1cmVBcnJheU9yVW5kZWZpbmVkKG9iai5BY3Rpb24pLFxuICAgICAgcmVzb3VyY2VzOiBlbnN1cmVBcnJheU9yVW5kZWZpbmVkKG9iai5SZXNvdXJjZSksXG4gICAgICBjb25kaXRpb25zOiBvYmouQ29uZGl0aW9uLFxuICAgICAgZWZmZWN0OiBvYmouRWZmZWN0LFxuICAgICAgbm90QWN0aW9uczogZW5zdXJlQXJyYXlPclVuZGVmaW5lZChvYmouTm90QWN0aW9uKSxcbiAgICAgIG5vdFJlc291cmNlczogZW5zdXJlQXJyYXlPclVuZGVmaW5lZChvYmouTm90UmVzb3VyY2UpLFxuICAgICAgcHJpbmNpcGFsczogb2JqLlByaW5jaXBhbCA/IFtuZXcgSnNvblByaW5jaXBhbChvYmouUHJpbmNpcGFsKV0gOiB1bmRlZmluZWQsXG4gICAgICBub3RQcmluY2lwYWxzOiBvYmouTm90UHJpbmNpcGFsID8gW25ldyBKc29uUHJpbmNpcGFsKG9iai5Ob3RQcmluY2lwYWwpXSA6IHVuZGVmaW5lZCxcbiAgICB9KTtcblxuICAgIC8vIHZhbGlkYXRlIHRoYXQgdGhlIFBvbGljeVN0YXRlbWVudCBoYXMgdGhlIGNvcnJlY3Qgc2hhcGVcbiAgICBjb25zdCBlcnJvcnMgPSByZXQudmFsaWRhdGVGb3JBbnlQb2xpY3koKTtcbiAgICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5jb3JyZWN0IFBvbGljeSBTdGF0ZW1lbnQ6ICcgKyBlcnJvcnMuam9pbignXFxuJykpO1xuICAgIH1cblxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvKipcbiAgICogU3RhdGVtZW50IElEIGZvciB0aGlzIHN0YXRlbWVudFxuICAgKi9cbiAgcHVibGljIHNpZD86IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB0byBhbGxvdyBvciBkZW55IHRoZSBhY3Rpb25zIGluIHRoaXMgc3RhdGVtZW50XG4gICAqL1xuICBwdWJsaWMgZWZmZWN0OiBFZmZlY3Q7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfYWN0aW9uID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfbm90QWN0aW9uID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfcHJpbmNpcGFsOiB7IFtrZXk6IHN0cmluZ106IGFueVtdIH0gPSB7fTtcbiAgcHJpdmF0ZSByZWFkb25seSBfbm90UHJpbmNpcGFsOiB7IFtrZXk6IHN0cmluZ106IGFueVtdIH0gPSB7fTtcbiAgcHJpdmF0ZSByZWFkb25seSBfcmVzb3VyY2UgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9ub3RSZXNvdXJjZSA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2NvbmRpdGlvbjogeyBba2V5OiBzdHJpbmddOiBhbnkgfSA9IHsgfTtcbiAgcHJpdmF0ZSBwcmluY2lwYWxDb25kaXRpb25zSnNvbj86IHN0cmluZztcblxuICAvLyBIb2xkIG9uIHRvIHRob3NlIHByaW5jaXBhbHNcbiAgcHJpdmF0ZSByZWFkb25seSBfcHJpbmNpcGFscyA9IG5ldyBBcnJheTxJUHJpbmNpcGFsPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9ub3RQcmluY2lwYWxzID0gbmV3IEFycmF5PElQcmluY2lwYWw+KCk7XG5cbiAgY29uc3RydWN0b3IocHJvcHM6IFBvbGljeVN0YXRlbWVudFByb3BzID0ge30pIHtcbiAgICAvLyBWYWxpZGF0ZSBhY3Rpb25zXG4gICAgZm9yIChjb25zdCBhY3Rpb24gb2YgWy4uLnByb3BzLmFjdGlvbnMgfHwgW10sIC4uLnByb3BzLm5vdEFjdGlvbnMgfHwgW11dKSB7XG5cbiAgICAgIGlmICghL14oXFwqfFthLXpBLVowLTktXSs6W2EtekEtWjAtOSpdKykkLy50ZXN0KGFjdGlvbikgJiYgIWNkay5Ub2tlbi5pc1VucmVzb2x2ZWQoYWN0aW9uKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFjdGlvbiAnJHthY3Rpb259JyBpcyBpbnZhbGlkLiBBbiBhY3Rpb24gc3RyaW5nIGNvbnNpc3RzIG9mIGEgc2VydmljZSBuYW1lc3BhY2UsIGEgY29sb24sIGFuZCB0aGUgbmFtZSBvZiBhbiBhY3Rpb24uIEFjdGlvbiBuYW1lcyBjYW4gaW5jbHVkZSB3aWxkY2FyZHMuYCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5zaWQgPSBwcm9wcy5zaWQ7XG4gICAgdGhpcy5lZmZlY3QgPSBwcm9wcy5lZmZlY3QgfHwgRWZmZWN0LkFMTE9XO1xuXG4gICAgdGhpcy5hZGRBY3Rpb25zKC4uLnByb3BzLmFjdGlvbnMgfHwgW10pO1xuICAgIHRoaXMuYWRkTm90QWN0aW9ucyguLi5wcm9wcy5ub3RBY3Rpb25zIHx8IFtdKTtcbiAgICB0aGlzLmFkZFByaW5jaXBhbHMoLi4ucHJvcHMucHJpbmNpcGFscyB8fCBbXSk7XG4gICAgdGhpcy5hZGROb3RQcmluY2lwYWxzKC4uLnByb3BzLm5vdFByaW5jaXBhbHMgfHwgW10pO1xuICAgIHRoaXMuYWRkUmVzb3VyY2VzKC4uLnByb3BzLnJlc291cmNlcyB8fCBbXSk7XG4gICAgdGhpcy5hZGROb3RSZXNvdXJjZXMoLi4ucHJvcHMubm90UmVzb3VyY2VzIHx8IFtdKTtcbiAgICBpZiAocHJvcHMuY29uZGl0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmFkZENvbmRpdGlvbnMocHJvcHMuY29uZGl0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgLy9cbiAgLy8gQWN0aW9uc1xuICAvL1xuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IGFsbG93ZWQgYWN0aW9ucyBpbnRvIHRoZSBcIkFjdGlvblwiIHNlY3Rpb24gb2YgdGhlIHBvbGljeSBzdGF0ZW1lbnQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL3JlZmVyZW5jZV9wb2xpY2llc19lbGVtZW50c19hY3Rpb24uaHRtbFxuICAgKlxuICAgKiBAcGFyYW0gYWN0aW9ucyBhY3Rpb25zIHRoYXQgd2lsbCBiZSBhbGxvd2VkLlxuICAgKi9cbiAgcHVibGljIGFkZEFjdGlvbnMoLi4uYWN0aW9uczogc3RyaW5nW10pIHtcbiAgICBpZiAoYWN0aW9ucy5sZW5ndGggPiAwICYmIHRoaXMuX25vdEFjdGlvbi5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBhZGQgXFwnQWN0aW9uc1xcJyB0byBwb2xpY3kgc3RhdGVtZW50IGlmIFxcJ05vdEFjdGlvbnNcXCcgaGF2ZSBiZWVuIGFkZGVkJyk7XG4gICAgfVxuICAgIHRoaXMuX2FjdGlvbi5wdXNoKC4uLmFjdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4cGxpY2l0bHkgYWxsb3cgYWxsIGFjdGlvbnMgZXhjZXB0IHRoZSBzcGVjaWZpZWQgbGlzdCBvZiBhY3Rpb25zIGludG8gdGhlIFwiTm90QWN0aW9uXCIgc2VjdGlvblxuICAgKiBvZiB0aGUgcG9saWN5IGRvY3VtZW50LlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9yZWZlcmVuY2VfcG9saWNpZXNfZWxlbWVudHNfbm90YWN0aW9uLmh0bWxcbiAgICpcbiAgICogQHBhcmFtIG5vdEFjdGlvbnMgYWN0aW9ucyB0aGF0IHdpbGwgYmUgZGVuaWVkLiBBbGwgb3RoZXIgYWN0aW9ucyB3aWxsIGJlIHBlcm1pdHRlZC5cbiAgICovXG4gIHB1YmxpYyBhZGROb3RBY3Rpb25zKC4uLm5vdEFjdGlvbnM6IHN0cmluZ1tdKSB7XG4gICAgaWYgKG5vdEFjdGlvbnMubGVuZ3RoID4gMCAmJiB0aGlzLl9hY3Rpb24ubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYWRkIFxcJ05vdEFjdGlvbnNcXCcgdG8gcG9saWN5IHN0YXRlbWVudCBpZiBcXCdBY3Rpb25zXFwnIGhhdmUgYmVlbiBhZGRlZCcpO1xuICAgIH1cbiAgICB0aGlzLl9ub3RBY3Rpb24ucHVzaCguLi5ub3RBY3Rpb25zKTtcbiAgfVxuXG4gIC8vXG4gIC8vIFByaW5jaXBhbFxuICAvL1xuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgaWYgdGhpcyBwZXJtaXNzaW9uIGhhcyBhIFwiUHJpbmNpcGFsXCIgc2VjdGlvbi5cbiAgICovXG4gIHB1YmxpYyBnZXQgaGFzUHJpbmNpcGFsKCkge1xuICAgIHJldHVybiB0aGlzLl9wcmluY2lwYWxzLmxlbmd0aCArIHRoaXMuX25vdFByaW5jaXBhbHMubGVuZ3RoID4gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIHByaW5jaXBhbHMgdG8gdGhlIFwiUHJpbmNpcGFsXCIgc2VjdGlvbiBvZiBhIHBvbGljeSBzdGF0ZW1lbnQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL3JlZmVyZW5jZV9wb2xpY2llc19lbGVtZW50c19wcmluY2lwYWwuaHRtbFxuICAgKlxuICAgKiBAcGFyYW0gcHJpbmNpcGFscyBJQU0gcHJpbmNpcGFscyB0aGF0IHdpbGwgYmUgYWRkZWRcbiAgICovXG4gIHB1YmxpYyBhZGRQcmluY2lwYWxzKC4uLnByaW5jaXBhbHM6IElQcmluY2lwYWxbXSkge1xuICAgIHRoaXMuX3ByaW5jaXBhbHMucHVzaCguLi5wcmluY2lwYWxzKTtcbiAgICBpZiAoT2JqZWN0LmtleXMocHJpbmNpcGFscykubGVuZ3RoID4gMCAmJiBPYmplY3Qua2V5cyh0aGlzLl9ub3RQcmluY2lwYWwpLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGFkZCBcXCdQcmluY2lwYWxzXFwnIHRvIHBvbGljeSBzdGF0ZW1lbnQgaWYgXFwnTm90UHJpbmNpcGFsc1xcJyBoYXZlIGJlZW4gYWRkZWQnKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBwcmluY2lwYWwgb2YgcHJpbmNpcGFscykge1xuICAgICAgdGhpcy52YWxpZGF0ZVBvbGljeVByaW5jaXBhbChwcmluY2lwYWwpO1xuICAgICAgY29uc3QgZnJhZ21lbnQgPSBwcmluY2lwYWwucG9saWN5RnJhZ21lbnQ7XG4gICAgICBtZXJnZVByaW5jaXBhbCh0aGlzLl9wcmluY2lwYWwsIGZyYWdtZW50LnByaW5jaXBhbEpzb24pO1xuICAgICAgdGhpcy5hZGRQcmluY2lwYWxDb25kaXRpb25zKGZyYWdtZW50LmNvbmRpdGlvbnMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IHByaW5jaXBhbHMgdGhhdCBpcyBub3QgYWxsb3dlZCBvciBkZW5pZWQgYWNjZXNzIHRvIHRoZSBcIk5vdFByaW5jaXBhbFwiIHNlY3Rpb24gb2ZcbiAgICogYSBwb2xpY3kgc3RhdGVtZW50LlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9yZWZlcmVuY2VfcG9saWNpZXNfZWxlbWVudHNfbm90cHJpbmNpcGFsLmh0bWxcbiAgICpcbiAgICogQHBhcmFtIG5vdFByaW5jaXBhbHMgSUFNIHByaW5jaXBhbHMgdGhhdCB3aWxsIGJlIGRlbmllZCBhY2Nlc3NcbiAgICovXG4gIHB1YmxpYyBhZGROb3RQcmluY2lwYWxzKC4uLm5vdFByaW5jaXBhbHM6IElQcmluY2lwYWxbXSkge1xuICAgIHRoaXMuX25vdFByaW5jaXBhbHMucHVzaCguLi5ub3RQcmluY2lwYWxzKTtcbiAgICBpZiAoT2JqZWN0LmtleXMobm90UHJpbmNpcGFscykubGVuZ3RoID4gMCAmJiBPYmplY3Qua2V5cyh0aGlzLl9wcmluY2lwYWwpLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGFkZCBcXCdOb3RQcmluY2lwYWxzXFwnIHRvIHBvbGljeSBzdGF0ZW1lbnQgaWYgXFwnUHJpbmNpcGFsc1xcJyBoYXZlIGJlZW4gYWRkZWQnKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBub3RQcmluY2lwYWwgb2Ygbm90UHJpbmNpcGFscykge1xuICAgICAgdGhpcy52YWxpZGF0ZVBvbGljeVByaW5jaXBhbChub3RQcmluY2lwYWwpO1xuICAgICAgY29uc3QgZnJhZ21lbnQgPSBub3RQcmluY2lwYWwucG9saWN5RnJhZ21lbnQ7XG4gICAgICBtZXJnZVByaW5jaXBhbCh0aGlzLl9ub3RQcmluY2lwYWwsIGZyYWdtZW50LnByaW5jaXBhbEpzb24pO1xuICAgICAgdGhpcy5hZGRQcmluY2lwYWxDb25kaXRpb25zKGZyYWdtZW50LmNvbmRpdGlvbnMpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVQb2xpY3lQcmluY2lwYWwocHJpbmNpcGFsOiBJUHJpbmNpcGFsKSB7XG4gICAgaWYgKHByaW5jaXBhbCBpbnN0YW5jZW9mIEdyb3VwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1c2UgYW4gSUFNIEdyb3VwIGFzIHRoZSBcXCdQcmluY2lwYWxcXCcgb3IgXFwnTm90UHJpbmNpcGFsXFwnIGluIGFuIElBTSBQb2xpY3knKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3BlY2lmeSBBV1MgYWNjb3VudCBJRCBhcyB0aGUgcHJpbmNpcGFsIGVudGl0eSB0byB0aGUgXCJQcmluY2lwYWxcIiBzZWN0aW9uIG9mIGEgcG9saWN5IHN0YXRlbWVudC5cbiAgICovXG4gIHB1YmxpYyBhZGRBd3NBY2NvdW50UHJpbmNpcGFsKGFjY291bnRJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5hZGRQcmluY2lwYWxzKG5ldyBBY2NvdW50UHJpbmNpcGFsKGFjY291bnRJZCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgYSBwcmluY2lwYWwgdXNpbmcgdGhlIEFSTiAgaWRlbnRpZmllciBvZiB0aGUgcHJpbmNpcGFsLlxuICAgKiBZb3UgY2Fubm90IHNwZWNpZnkgSUFNIGdyb3VwcyBhbmQgaW5zdGFuY2UgcHJvZmlsZXMgYXMgcHJpbmNpcGFscy5cbiAgICpcbiAgICogQHBhcmFtIGFybiBBUk4gaWRlbnRpZmllciBvZiBBV1MgYWNjb3VudCwgSUFNIHVzZXIsIG9yIElBTSByb2xlIChpLmUuIGFybjphd3M6aWFtOjoxMjM0NTY3ODkwMTI6dXNlci91c2VyLW5hbWUpXG4gICAqL1xuICBwdWJsaWMgYWRkQXJuUHJpbmNpcGFsKGFybjogc3RyaW5nKSB7XG4gICAgdGhpcy5hZGRQcmluY2lwYWxzKG5ldyBBcm5QcmluY2lwYWwoYXJuKSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHNlcnZpY2UgcHJpbmNpcGFsIHRvIHRoaXMgcG9saWN5IHN0YXRlbWVudC5cbiAgICpcbiAgICogQHBhcmFtIHNlcnZpY2UgdGhlIHNlcnZpY2UgbmFtZSBmb3Igd2hpY2ggYSBzZXJ2aWNlIHByaW5jaXBhbCBpcyByZXF1ZXN0ZWQgKGUuZzogYHMzLmFtYXpvbmF3cy5jb21gKS5cbiAgICogQHBhcmFtIG9wdHMgICAgb3B0aW9ucyBmb3IgYWRkaW5nIHRoZSBzZXJ2aWNlIHByaW5jaXBhbCAoc3VjaCBhcyBzcGVjaWZ5aW5nIGEgcHJpbmNpcGFsIGluIGEgZGlmZmVyZW50IHJlZ2lvbilcbiAgICovXG4gIHB1YmxpYyBhZGRTZXJ2aWNlUHJpbmNpcGFsKHNlcnZpY2U6IHN0cmluZywgb3B0cz86IFNlcnZpY2VQcmluY2lwYWxPcHRzKSB7XG4gICAgdGhpcy5hZGRQcmluY2lwYWxzKG5ldyBTZXJ2aWNlUHJpbmNpcGFsKHNlcnZpY2UsIG9wdHMpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgZmVkZXJhdGVkIGlkZW50aXR5IHByb3ZpZGVyIHN1Y2ggYXMgQW1hem9uIENvZ25pdG8gdG8gdGhpcyBwb2xpY3kgc3RhdGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gZmVkZXJhdGVkIGZlZGVyYXRlZCBpZGVudGl0eSBwcm92aWRlciAoaS5lLiAnY29nbml0by1pZGVudGl0eS5hbWF6b25hd3MuY29tJylcbiAgICogQHBhcmFtIGNvbmRpdGlvbnMgVGhlIGNvbmRpdGlvbnMgdW5kZXIgd2hpY2ggdGhlIHBvbGljeSBpcyBpbiBlZmZlY3QuXG4gICAqICAgU2VlIFt0aGUgSUFNIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9yZWZlcmVuY2VfcG9saWNpZXNfZWxlbWVudHNfY29uZGl0aW9uLmh0bWwpLlxuICAgKi9cbiAgcHVibGljIGFkZEZlZGVyYXRlZFByaW5jaXBhbChmZWRlcmF0ZWQ6IGFueSwgY29uZGl0aW9uczogQ29uZGl0aW9ucykge1xuICAgIHRoaXMuYWRkUHJpbmNpcGFscyhuZXcgRmVkZXJhdGVkUHJpbmNpcGFsKGZlZGVyYXRlZCwgY29uZGl0aW9ucykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gQVdTIGFjY291bnQgcm9vdCB1c2VyIHByaW5jaXBhbCB0byB0aGlzIHBvbGljeSBzdGF0ZW1lbnRcbiAgICovXG4gIHB1YmxpYyBhZGRBY2NvdW50Um9vdFByaW5jaXBhbCgpIHtcbiAgICB0aGlzLmFkZFByaW5jaXBhbHMobmV3IEFjY291bnRSb290UHJpbmNpcGFsKCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBjYW5vbmljYWwgdXNlciBJRCBwcmluY2lwYWwgdG8gdGhpcyBwb2xpY3kgZG9jdW1lbnRcbiAgICpcbiAgICogQHBhcmFtIGNhbm9uaWNhbFVzZXJJZCB1bmlxdWUgaWRlbnRpZmllciBhc3NpZ25lZCBieSBBV1MgZm9yIGV2ZXJ5IGFjY291bnRcbiAgICovXG4gIHB1YmxpYyBhZGRDYW5vbmljYWxVc2VyUHJpbmNpcGFsKGNhbm9uaWNhbFVzZXJJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5hZGRQcmluY2lwYWxzKG5ldyBDYW5vbmljYWxVc2VyUHJpbmNpcGFsKGNhbm9uaWNhbFVzZXJJZCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYWxsIGlkZW50aXRpZXMgaW4gYWxsIGFjY291bnRzIChcIipcIikgdG8gdGhpcyBwb2xpY3kgc3RhdGVtZW50XG4gICAqL1xuICBwdWJsaWMgYWRkQW55UHJpbmNpcGFsKCkge1xuICAgIHRoaXMuYWRkUHJpbmNpcGFscyhuZXcgQW55UHJpbmNpcGFsKCkpO1xuICB9XG5cbiAgLy9cbiAgLy8gUmVzb3VyY2VzXG4gIC8vXG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgcmVzb3VyY2VzIHRoYXQgdGhpcyBwb2xpY3kgc3RhdGVtZW50IGFwcGxpZXMgaW50byB0aGUgXCJSZXNvdXJjZVwiIHNlY3Rpb24gb2ZcbiAgICogdGhpcyBwb2xpY3kgc3RhdGVtZW50LlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9yZWZlcmVuY2VfcG9saWNpZXNfZWxlbWVudHNfcmVzb3VyY2UuaHRtbFxuICAgKlxuICAgKiBAcGFyYW0gYXJucyBBbWF6b24gUmVzb3VyY2UgTmFtZXMgKEFSTnMpIG9mIHRoZSByZXNvdXJjZXMgdGhhdCB0aGlzIHBvbGljeSBzdGF0ZW1lbnQgYXBwbGllcyB0b1xuICAgKi9cbiAgcHVibGljIGFkZFJlc291cmNlcyguLi5hcm5zOiBzdHJpbmdbXSkge1xuICAgIGlmIChhcm5zLmxlbmd0aCA+IDAgJiYgdGhpcy5fbm90UmVzb3VyY2UubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYWRkIFxcJ1Jlc291cmNlc1xcJyB0byBwb2xpY3kgc3RhdGVtZW50IGlmIFxcJ05vdFJlc291cmNlc1xcJyBoYXZlIGJlZW4gYWRkZWQnKTtcbiAgICB9XG4gICAgdGhpcy5fcmVzb3VyY2UucHVzaCguLi5hcm5zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IHJlc291cmNlcyB0aGF0IHRoaXMgcG9saWN5IHN0YXRlbWVudCB3aWxsIG5vdCBhcHBseSB0byBpbiB0aGUgXCJOb3RSZXNvdXJjZVwiIHNlY3Rpb25cbiAgICogb2YgdGhpcyBwb2xpY3kgc3RhdGVtZW50LiBBbGwgcmVzb3VyY2VzIGV4Y2VwdCB0aGUgc3BlY2lmaWVkIGxpc3Qgd2lsbCBiZSBtYXRjaGVkLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9yZWZlcmVuY2VfcG9saWNpZXNfZWxlbWVudHNfbm90cmVzb3VyY2UuaHRtbFxuICAgKlxuICAgKiBAcGFyYW0gYXJucyBBbWF6b24gUmVzb3VyY2UgTmFtZXMgKEFSTnMpIG9mIHRoZSByZXNvdXJjZXMgdGhhdCB0aGlzIHBvbGljeSBzdGF0ZW1lbnQgZG9lcyBub3QgYXBwbHkgdG9cbiAgICovXG4gIHB1YmxpYyBhZGROb3RSZXNvdXJjZXMoLi4uYXJuczogc3RyaW5nW10pIHtcbiAgICBpZiAoYXJucy5sZW5ndGggPiAwICYmIHRoaXMuX3Jlc291cmNlLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGFkZCBcXCdOb3RSZXNvdXJjZXNcXCcgdG8gcG9saWN5IHN0YXRlbWVudCBpZiBcXCdSZXNvdXJjZXNcXCcgaGF2ZSBiZWVuIGFkZGVkJyk7XG4gICAgfVxuICAgIHRoaXMuX25vdFJlc291cmNlLnB1c2goLi4uYXJucyk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIGBgXCIqXCJgYCByZXNvdXJjZSB0byB0aGlzIHN0YXRlbWVudC5cbiAgICovXG4gIHB1YmxpYyBhZGRBbGxSZXNvdXJjZXMoKSB7XG4gICAgdGhpcy5hZGRSZXNvdXJjZXMoJyonKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgaWYgdGhpcyBwZXJtaXNzaW9uIGhhcyBhdCBsZWFzdCBvbmUgcmVzb3VyY2UgYXNzb2NpYXRlZCB3aXRoIGl0LlxuICAgKi9cbiAgcHVibGljIGdldCBoYXNSZXNvdXJjZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fcmVzb3VyY2UgJiYgdGhpcy5fcmVzb3VyY2UubGVuZ3RoID4gMDtcbiAgfVxuXG4gIC8vXG4gIC8vIENvbmRpdGlvblxuICAvL1xuXG4gIC8qKlxuICAgKiBBZGQgYSBjb25kaXRpb24gdG8gdGhlIFBvbGljeVxuICAgKlxuICAgKiBJZiBtdWx0aXBsZSBjYWxscyBhcmUgbWFkZSB0byBhZGQgYSBjb25kaXRpb24gd2l0aCB0aGUgc2FtZSBvcGVyYXRvciBhbmQgZmllbGQsIG9ubHlcbiAgICogdGhlIGxhc3Qgb25lIHdpbnMuIEZvciBleGFtcGxlOlxuICAgKlxuICAgKiBgYGB0c1xuICAgKiBkZWNsYXJlIGNvbnN0IHN0bXQ6IGlhbS5Qb2xpY3lTdGF0ZW1lbnQ7XG4gICAqXG4gICAqIHN0bXQuYWRkQ29uZGl0aW9uKCdTdHJpbmdFcXVhbHMnLCB7ICdhd3M6U29tZUZpZWxkJzogJzEnIH0pO1xuICAgKiBzdG10LmFkZENvbmRpdGlvbignU3RyaW5nRXF1YWxzJywgeyAnYXdzOlNvbWVGaWVsZCc6ICcyJyB9KTtcbiAgICogYGBgXG4gICAqXG4gICAqIFdpbGwgZW5kIHVwIHdpdGggdGhlIHNpbmdsZSBjb25kaXRpb24gYFN0cmluZ0VxdWFsczogeyAnYXdzOlNvbWVGaWVsZCc6ICcyJyB9YC5cbiAgICpcbiAgICogSWYgeW91IG1lYW50IHRvIGFkZCBhIGNvbmRpdGlvbiB0byBzYXkgdGhhdCB0aGUgZmllbGQgY2FuIGJlICplaXRoZXIqIGAxYCBvciBgMmAsIHdyaXRlXG4gICAqIHRoaXM6XG4gICAqXG4gICAqIGBgYHRzXG4gICAqIGRlY2xhcmUgY29uc3Qgc3RtdDogaWFtLlBvbGljeVN0YXRlbWVudDtcbiAgICpcbiAgICogc3RtdC5hZGRDb25kaXRpb24oJ1N0cmluZ0VxdWFscycsIHsgJ2F3czpTb21lRmllbGQnOiBbJzEnLCAnMiddIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIHB1YmxpYyBhZGRDb25kaXRpb24oa2V5OiBzdHJpbmcsIHZhbHVlOiBDb25kaXRpb24pIHtcbiAgICBjb25zdCBleGlzdGluZ1ZhbHVlID0gdGhpcy5fY29uZGl0aW9uW2tleV07XG4gICAgdGhpcy5fY29uZGl0aW9uW2tleV0gPSBleGlzdGluZ1ZhbHVlID8geyAuLi5leGlzdGluZ1ZhbHVlLCAuLi52YWx1ZSB9IDogdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQWRkIG11bHRpcGxlIGNvbmRpdGlvbnMgdG8gdGhlIFBvbGljeVxuICAgKlxuICAgKiBTZWUgdGhlIGBhZGRDb25kaXRpb25gIGZ1bmN0aW9uIGZvciBhIGNhdmVhdCBvbiBjYWxsaW5nIHRoaXMgbWV0aG9kIG11bHRpcGxlIHRpbWVzLlxuICAgKi9cbiAgcHVibGljIGFkZENvbmRpdGlvbnMoY29uZGl0aW9uczogQ29uZGl0aW9ucykge1xuICAgIE9iamVjdC5rZXlzKGNvbmRpdGlvbnMpLm1hcChrZXkgPT4ge1xuICAgICAgdGhpcy5hZGRDb25kaXRpb24oa2V5LCBjb25kaXRpb25zW2tleV0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIGNvbmRpdGlvbiB0aGF0IGxpbWl0cyB0byBhIGdpdmVuIGFjY291bnRcbiAgICpcbiAgICogVGhpcyBtZXRob2QgY2FuIG9ubHkgYmUgY2FsbGVkIG9uY2U6IHN1YnNlcXVlbnQgY2FsbHMgd2lsbCBvdmVyd3JpdGUgZWFybGllciBjYWxscy5cbiAgICovXG4gIHB1YmxpYyBhZGRBY2NvdW50Q29uZGl0aW9uKGFjY291bnRJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5hZGRDb25kaXRpb24oJ1N0cmluZ0VxdWFscycsIHsgJ3N0czpFeHRlcm5hbElkJzogYWNjb3VudElkIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBgUG9saWN5U3RhdGVtZW50YCB3aXRoIHRoZSBzYW1lIGV4YWN0IHByb3BlcnRpZXNcbiAgICogYXMgdGhpcyBvbmUsIGV4Y2VwdCBmb3IgdGhlIG92ZXJyaWRlc1xuICAgKi9cbiAgcHVibGljIGNvcHkob3ZlcnJpZGVzOiBQb2xpY3lTdGF0ZW1lbnRQcm9wcyA9IHt9KSB7XG4gICAgcmV0dXJuIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgc2lkOiBvdmVycmlkZXMuc2lkID8/IHRoaXMuc2lkLFxuICAgICAgZWZmZWN0OiBvdmVycmlkZXMuZWZmZWN0ID8/IHRoaXMuZWZmZWN0LFxuICAgICAgYWN0aW9uczogb3ZlcnJpZGVzLmFjdGlvbnMgPz8gdGhpcy5hY3Rpb25zLFxuICAgICAgbm90QWN0aW9uczogb3ZlcnJpZGVzLm5vdEFjdGlvbnMgPz8gdGhpcy5ub3RBY3Rpb25zLFxuXG4gICAgICBwcmluY2lwYWxzOiBvdmVycmlkZXMucHJpbmNpcGFscyA/PyB0aGlzLnByaW5jaXBhbHMsXG4gICAgICBub3RQcmluY2lwYWxzOiBvdmVycmlkZXMubm90UHJpbmNpcGFscyA/PyB0aGlzLm5vdFByaW5jaXBhbHMsXG5cbiAgICAgIHJlc291cmNlczogb3ZlcnJpZGVzLnJlc291cmNlcyA/PyB0aGlzLnJlc291cmNlcyxcbiAgICAgIG5vdFJlc291cmNlczogb3ZlcnJpZGVzLm5vdFJlc291cmNlcyA/PyB0aGlzLm5vdFJlc291cmNlcyxcblxuICAgICAgY29uZGl0aW9uczogb3ZlcnJpZGVzLmNvbmRpdGlvbnMgPz8gdGhpcy5jb25kaXRpb25zLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEpTT04taWZ5IHRoZSBwb2xpY3kgc3RhdGVtZW50XG4gICAqXG4gICAqIFVzZWQgd2hlbiBKU09OLnN0cmluZ2lmeSgpIGlzIGNhbGxlZFxuICAgKi9cbiAgcHVibGljIHRvU3RhdGVtZW50SnNvbigpOiBhbnkge1xuICAgIHJldHVybiBub3JtYWxpemVTdGF0ZW1lbnQoe1xuICAgICAgQWN0aW9uOiB0aGlzLl9hY3Rpb24sXG4gICAgICBOb3RBY3Rpb246IHRoaXMuX25vdEFjdGlvbixcbiAgICAgIENvbmRpdGlvbjogdGhpcy5fY29uZGl0aW9uLFxuICAgICAgRWZmZWN0OiB0aGlzLmVmZmVjdCxcbiAgICAgIFByaW5jaXBhbDogdGhpcy5fcHJpbmNpcGFsLFxuICAgICAgTm90UHJpbmNpcGFsOiB0aGlzLl9ub3RQcmluY2lwYWwsXG4gICAgICBSZXNvdXJjZTogdGhpcy5fcmVzb3VyY2UsXG4gICAgICBOb3RSZXNvdXJjZTogdGhpcy5fbm90UmVzb3VyY2UsXG4gICAgICBTaWQ6IHRoaXMuc2lkLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGlzIHBvbGljeSBzdGF0ZW1lbnRcbiAgICovXG4gIHB1YmxpYyB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gY2RrLlRva2VuLmFzU3RyaW5nKHRoaXMsIHtcbiAgICAgIGRpc3BsYXlIaW50OiAnUG9saWN5U3RhdGVtZW50JyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBKU09OLWlmeSB0aGUgc3RhdGVtZW50XG4gICAqXG4gICAqIFVzZWQgd2hlbiBKU09OLnN0cmluZ2lmeSgpIGlzIGNhbGxlZFxuICAgKi9cbiAgcHVibGljIHRvSlNPTigpIHtcbiAgICByZXR1cm4gdGhpcy50b1N0YXRlbWVudEpzb24oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBwcmluY2lwYWwncyBjb25kaXRpb25zXG4gICAqXG4gICAqIEZvciBjb252ZW5pZW5jZSwgcHJpbmNpcGFscyBoYXZlIGJlZW4gbW9kZWxlZCBhcyBib3RoIGEgcHJpbmNpcGFsXG4gICAqIGFuZCBhIHNldCBvZiBjb25kaXRpb25zLiBUaGlzIG1ha2VzIGl0IHBvc3NpYmxlIHRvIGhhdmUgYSBzaW5nbGVcbiAgICogb2JqZWN0IHJlcHJlc2VudCBlLmcuIGFuIFwiU05TIFRvcGljXCIgKFNOUyBzZXJ2aWNlIHByaW5jaXBhbCArIGF3czpTb3VyY0FyblxuICAgKiBjb25kaXRpb24pIG9yIGFuIE9yZ2FuaXphdGlvbiBtZW1iZXIgKCogKyBhd3M6T3JnSWQgY29uZGl0aW9uKS5cbiAgICpcbiAgICogSG93ZXZlciwgd2hlbiB1c2luZyBtdWx0aXBsZSBwcmluY2lwYWxzIGluIHRoZSBzYW1lIHBvbGljeSBzdGF0ZW1lbnQsXG4gICAqIHRoZXkgbXVzdCBhbGwgaGF2ZSB0aGUgc2FtZSBjb25kaXRpb25zIG9yIHRoZSBPUiBzYW1lbnRpY3NcbiAgICogaW1wbGllZCBieSBhIGxpc3Qgb2YgcHJpbmNpcGFscyBjYW5ub3QgYmUgZ3VhcmFudGVlZCAodXNlciBuZWVkcyB0b1xuICAgKiBhZGQgbXVsdGlwbGUgc3RhdGVtZW50cyBpbiB0aGF0IGNhc2UpLlxuICAgKi9cbiAgcHJpdmF0ZSBhZGRQcmluY2lwYWxDb25kaXRpb25zKGNvbmRpdGlvbnM6IENvbmRpdGlvbnMpIHtcbiAgICAvLyBTdHJpbmdpZnlpbmcgdGhlIGNvbmRpdGlvbnMgaXMgYW4gZWFzeSB3YXkgdG8gZG8gZGVlcCBlcXVhbGl0eVxuICAgIGNvbnN0IHRoZXNlQ29uZGl0aW9ucyA9IEpTT04uc3RyaW5naWZ5KGNvbmRpdGlvbnMpO1xuICAgIGlmICh0aGlzLnByaW5jaXBhbENvbmRpdGlvbnNKc29uID09PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIEZpcnN0IHByaW5jaXBhbCwgYW55dGhpbmcgZ29lc1xuICAgICAgdGhpcy5wcmluY2lwYWxDb25kaXRpb25zSnNvbiA9IHRoZXNlQ29uZGl0aW9ucztcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMucHJpbmNpcGFsQ29uZGl0aW9uc0pzb24gIT09IHRoZXNlQ29uZGl0aW9ucykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFsbCBwcmluY2lwYWxzIGluIGEgUG9saWN5U3RhdGVtZW50IG11c3QgaGF2ZSB0aGUgc2FtZSBDb25kaXRpb25zIChnb3QgJyR7dGhpcy5wcmluY2lwYWxDb25kaXRpb25zSnNvbn0nIGFuZCAnJHt0aGVzZUNvbmRpdGlvbnN9JykuIFVzZSBtdWx0aXBsZSBzdGF0ZW1lbnRzIGluc3RlYWQuYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuYWRkQ29uZGl0aW9ucyhjb25kaXRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0aGF0IHRoZSBwb2xpY3kgc3RhdGVtZW50IHNhdGlzZmllcyBiYXNlIHJlcXVpcmVtZW50cyBmb3IgYSBwb2xpY3kuXG4gICAqXG4gICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIHZhbGlkYXRpb24gZXJyb3IgbWVzc2FnZXMsIG9yIGFuIGVtcHR5IGFycmF5IGlmIHRoZSBzdGF0ZW1lbnQgaXMgdmFsaWQuXG4gICAqL1xuICBwdWJsaWMgdmFsaWRhdGVGb3JBbnlQb2xpY3koKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGVycm9ycyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG4gICAgaWYgKHRoaXMuX2FjdGlvbi5sZW5ndGggPT09IDAgJiYgdGhpcy5fbm90QWN0aW9uLmxlbmd0aCA9PT0gMCkge1xuICAgICAgZXJyb3JzLnB1c2goJ0EgUG9saWN5U3RhdGVtZW50IG11c3Qgc3BlY2lmeSBhdCBsZWFzdCBvbmUgXFwnYWN0aW9uXFwnIG9yIFxcJ25vdEFjdGlvblxcJy4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9ycztcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0aGF0IHRoZSBwb2xpY3kgc3RhdGVtZW50IHNhdGlzZmllcyBhbGwgcmVxdWlyZW1lbnRzIGZvciBhIHJlc291cmNlLWJhc2VkIHBvbGljeS5cbiAgICpcbiAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgdmFsaWRhdGlvbiBlcnJvciBtZXNzYWdlcywgb3IgYW4gZW1wdHkgYXJyYXkgaWYgdGhlIHN0YXRlbWVudCBpcyB2YWxpZC5cbiAgICovXG4gIHB1YmxpYyB2YWxpZGF0ZUZvclJlc291cmNlUG9saWN5KCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBlcnJvcnMgPSB0aGlzLnZhbGlkYXRlRm9yQW55UG9saWN5KCk7XG4gICAgaWYgKE9iamVjdC5rZXlzKHRoaXMuX3ByaW5jaXBhbCkubGVuZ3RoID09PSAwICYmIE9iamVjdC5rZXlzKHRoaXMuX25vdFByaW5jaXBhbCkubGVuZ3RoID09PSAwKSB7XG4gICAgICBlcnJvcnMucHVzaCgnQSBQb2xpY3lTdGF0ZW1lbnQgdXNlZCBpbiBhIHJlc291cmNlLWJhc2VkIHBvbGljeSBtdXN0IHNwZWNpZnkgYXQgbGVhc3Qgb25lIElBTSBwcmluY2lwYWwuJyk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcnM7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhhdCB0aGUgcG9saWN5IHN0YXRlbWVudCBzYXRpc2ZpZXMgYWxsIHJlcXVpcmVtZW50cyBmb3IgYW4gaWRlbnRpdHktYmFzZWQgcG9saWN5LlxuICAgKlxuICAgKiBAcmV0dXJucyBBbiBhcnJheSBvZiB2YWxpZGF0aW9uIGVycm9yIG1lc3NhZ2VzLCBvciBhbiBlbXB0eSBhcnJheSBpZiB0aGUgc3RhdGVtZW50IGlzIHZhbGlkLlxuICAgKi9cbiAgcHVibGljIHZhbGlkYXRlRm9ySWRlbnRpdHlQb2xpY3koKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGVycm9ycyA9IHRoaXMudmFsaWRhdGVGb3JBbnlQb2xpY3koKTtcbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5fcHJpbmNpcGFsKS5sZW5ndGggPiAwIHx8IE9iamVjdC5rZXlzKHRoaXMuX25vdFByaW5jaXBhbCkubGVuZ3RoID4gMCkge1xuICAgICAgZXJyb3JzLnB1c2goJ0EgUG9saWN5U3RhdGVtZW50IHVzZWQgaW4gYW4gaWRlbnRpdHktYmFzZWQgcG9saWN5IGNhbm5vdCBzcGVjaWZ5IGFueSBJQU0gcHJpbmNpcGFscy4nKTtcbiAgICB9XG4gICAgaWYgKE9iamVjdC5rZXlzKHRoaXMuX3Jlc291cmNlKS5sZW5ndGggPT09IDAgJiYgT2JqZWN0LmtleXModGhpcy5fbm90UmVzb3VyY2UpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgZXJyb3JzLnB1c2goJ0EgUG9saWN5U3RhdGVtZW50IHVzZWQgaW4gYW4gaWRlbnRpdHktYmFzZWQgcG9saWN5IG11c3Qgc3BlY2lmeSBhdCBsZWFzdCBvbmUgcmVzb3VyY2UuJyk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcnM7XG4gIH1cblxuICAvKipcbiAgICogVGhlIEFjdGlvbnMgYWRkZWQgdG8gdGhpcyBzdGF0ZW1lbnRcbiAgICovXG4gIHB1YmxpYyBnZXQgYWN0aW9ucygpIHtcbiAgICByZXR1cm4gWy4uLnRoaXMuX2FjdGlvbl07XG4gIH1cblxuICAvKipcbiAgICogVGhlIE5vdEFjdGlvbnMgYWRkZWQgdG8gdGhpcyBzdGF0ZW1lbnRcbiAgICovXG4gIHB1YmxpYyBnZXQgbm90QWN0aW9ucygpIHtcbiAgICByZXR1cm4gWy4uLnRoaXMuX25vdEFjdGlvbl07XG4gIH1cblxuICAvKipcbiAgICogVGhlIFByaW5jaXBhbHMgYWRkZWQgdG8gdGhpcyBzdGF0ZW1lbnRcbiAgICovXG4gIHB1YmxpYyBnZXQgcHJpbmNpcGFscygpOiBJUHJpbmNpcGFsW10ge1xuICAgIHJldHVybiBbLi4udGhpcy5fcHJpbmNpcGFsc107XG4gIH1cblxuICAvKipcbiAgICogVGhlIE5vdFByaW5jaXBhbHMgYWRkZWQgdG8gdGhpcyBzdGF0ZW1lbnRcbiAgICovXG4gIHB1YmxpYyBnZXQgbm90UHJpbmNpcGFscygpOiBJUHJpbmNpcGFsW10ge1xuICAgIHJldHVybiBbLi4udGhpcy5fbm90UHJpbmNpcGFsc107XG4gIH1cblxuICAvKipcbiAgICogVGhlIFJlc291cmNlcyBhZGRlZCB0byB0aGlzIHN0YXRlbWVudFxuICAgKi9cbiAgcHVibGljIGdldCByZXNvdXJjZXMoKSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLl9yZXNvdXJjZV07XG4gIH1cblxuICAvKipcbiAgICogVGhlIE5vdFJlc291cmNlcyBhZGRlZCB0byB0aGlzIHN0YXRlbWVudFxuICAgKi9cbiAgcHVibGljIGdldCBub3RSZXNvdXJjZXMoKSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLl9ub3RSZXNvdXJjZV07XG4gIH1cblxuICAvKipcbiAgICogVGhlIGNvbmRpdGlvbnMgYWRkZWQgdG8gdGhpcyBzdGF0ZW1lbnRcbiAgICovXG4gIHB1YmxpYyBnZXQgY29uZGl0aW9ucygpOiBhbnkge1xuICAgIHJldHVybiB7IC4uLnRoaXMuX2NvbmRpdGlvbiB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEVzdGltYXRlIHRoZSBzaXplIG9mIHRoaXMgcG9saWN5IHN0YXRlbWVudFxuICAgKlxuICAgKiBCeSBuZWNlc3NpdHksIHRoaXMgd2lsbCBub3QgYmUgYWNjdXJhdGUuIFdlJ2xsIGRvIG91ciBiZXN0IHRvIG92ZXJlc3RpbWF0ZVxuICAgKiBzbyB3ZSB3b24ndCBoYXZlIG5hc3R5IHN1cnByaXNlcy5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX2VzdGltYXRlU2l6ZShvcHRpb25zOiBFc3RpbWF0ZVNpemVPcHRpb25zKTogbnVtYmVyIHtcbiAgICBsZXQgcmV0ID0gMDtcblxuICAgIGNvbnN0IHsgYWN0aW9uRXN0aW1hdGUsIGFybkVzdGltYXRlIH0gPSBvcHRpb25zO1xuXG4gICAgcmV0ICs9IGBcIkVmZmVjdFwiOiBcIiR7dGhpcy5lZmZlY3R9XCIsYC5sZW5ndGg7XG5cbiAgICBjb3VudCgnQWN0aW9uJywgdGhpcy5hY3Rpb25zLCBhY3Rpb25Fc3RpbWF0ZSk7XG4gICAgY291bnQoJ05vdEFjdGlvbicsIHRoaXMubm90QWN0aW9ucywgYWN0aW9uRXN0aW1hdGUpO1xuICAgIGNvdW50KCdSZXNvdXJjZScsIHRoaXMucmVzb3VyY2VzLCBhcm5Fc3RpbWF0ZSk7XG4gICAgY291bnQoJ05vdFJlc291cmNlJywgdGhpcy5ub3RSZXNvdXJjZXMsIGFybkVzdGltYXRlKTtcblxuICAgIHJldCArPSB0aGlzLnByaW5jaXBhbHMubGVuZ3RoICogYXJuRXN0aW1hdGU7XG4gICAgcmV0ICs9IHRoaXMubm90UHJpbmNpcGFscy5sZW5ndGggKiBhcm5Fc3RpbWF0ZTtcblxuICAgIHJldCArPSBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbmRpdGlvbnMpLmxlbmd0aDtcbiAgICByZXR1cm4gcmV0O1xuXG4gICAgZnVuY3Rpb24gY291bnQoa2V5OiBzdHJpbmcsIHZhbHVlczogc3RyaW5nW10sIHRva2VuU2l6ZTogbnVtYmVyKSB7XG4gICAgICBpZiAodmFsdWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmV0ICs9IGtleS5sZW5ndGggKyA1IC8qIHF1b3RlcywgY29sb24sIGJyYWNrZXRzICovICtcbiAgICAgICAgICBzdW0odmFsdWVzLm1hcCh2ID0+IChjZGsuVG9rZW4uaXNVbnJlc29sdmVkKHYpID8gdG9rZW5TaXplIDogdi5sZW5ndGgpICsgMyAvKiBxdW90ZXMsIHNlcGFyYXRvciAqLykpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFRoZSBFZmZlY3QgZWxlbWVudCBvZiBhbiBJQU0gcG9saWN5XG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2VsZW1lbnRzX2VmZmVjdC5odG1sXG4gKi9cbmV4cG9ydCBlbnVtIEVmZmVjdCB7XG4gIC8qKlxuICAgKiBBbGxvd3MgYWNjZXNzIHRvIGEgcmVzb3VyY2UgaW4gYW4gSUFNIHBvbGljeSBzdGF0ZW1lbnQuIEJ5IGRlZmF1bHQsIGFjY2VzcyB0byByZXNvdXJjZXMgYXJlIGRlbmllZC5cbiAgICovXG4gIEFMTE9XID0gJ0FsbG93JyxcblxuICAvKipcbiAgICogRXhwbGljaXRseSBkZW55IGFjY2VzcyB0byBhIHJlc291cmNlLiBCeSBkZWZhdWx0LCBhbGwgcmVxdWVzdHMgYXJlIGRlbmllZCBpbXBsaWNpdGx5LlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9yZWZlcmVuY2VfcG9saWNpZXNfZXZhbHVhdGlvbi1sb2dpYy5odG1sXG4gICAqL1xuICBERU5ZID0gJ0RlbnknLFxufVxuXG4vKipcbiAqIENvbmRpdGlvbiBmb3Igd2hlbiBhbiBJQU0gcG9saWN5IGlzIGluIGVmZmVjdC4gTWFwcyBmcm9tIHRoZSBrZXlzIGluIGEgcmVxdWVzdCdzIGNvbnRleHQgdG9cbiAqIGEgc3RyaW5nIHZhbHVlIG9yIGFycmF5IG9mIHN0cmluZyB2YWx1ZXMuIFNlZSB0aGUgQ29uZGl0aW9ucyBpbnRlcmZhY2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqL1xuZXhwb3J0IHR5cGUgQ29uZGl0aW9uID0gYW55O1xuXG4vLyBOT1RFISBXZSdkIGlkZWFsbHkgbGlrZSB0byB0eXBlIHRoaXMgYXMgYFJlY29yZDxzdHJpbmcsIGFueT5gLCBiZWNhdXNlIHRoZVxuLy8gQVBJIGV4cGVjdHMgYSBtYXAgd2hpY2ggY2FuIHRha2UgZWl0aGVyIHN0cmluZ3Mgb3IgbGlzdHMgb2Ygc3RyaW5ncy5cbi8vXG4vLyBIb3dldmVyLCBpZiB3ZSB3ZXJlIHRvIGNoYW5nZSB0aGlzIHJpZ2h0IG5vdywgdGhlIEphdmEgYmluZGluZ3MgZm9yIENESyB3b3VsZFxuLy8gZW1pdCBhIHR5cGUgb2YgYE1hcDxTdHJpbmcsIE9iamVjdD5gLCBidXQgdGhlIG1vc3QgY29tbW9uIHR5cGVzIHBlb3BsZSB3b3VsZFxuLy8gaW5zdGFudGlhdGUgd291bGQgYmUgYW4gYEltbXV0YWJsZU1hcDxTdHJpbmcsIFN0cmluZz5gIHdoaWNoIHdvdWxkIG5vdCBiZVxuLy8gYXNzaWduYWJsZSB0byBgTWFwPFN0cmluZywgT2JqZWN0PmAuIFRoZSB0eXBlcyBkb24ndCBoYXZlIGEgYnVpbHQtaW4gbm90aW9uXG4vLyBvZiBjby1jb250cmF2YXJpYW5jZSwgeW91IGhhdmUgdG8gaW5kaWNhdGUgdGhhdCBvbiB0aGUgdHlwZS4gU28ganNpaSB3b3VsZCBmaXJzdFxuLy8gbmVlZCB0byBlbWl0IHRoZSB0eXBlIGFzIGBNYXA8U3RyaW5nLCA/IGV4dGVuZHMgT2JqZWN0PmAuXG4vL1xuLy8gRmVhdHVyZSByZXF1ZXN0IGluIGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvanNpaS9pc3N1ZXMvMTUxN1xuXG4vKipcbiAqIENvbmRpdGlvbnMgZm9yIHdoZW4gYW4gSUFNIFBvbGljeSBpcyBpbiBlZmZlY3QsIHNwZWNpZmllZCBpbiB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZTpcbiAqXG4gKiBgeyBcIk9wZXJhdG9yXCI6IHsgXCJrZXlJblJlcXVlc3RDb250ZXh0XCI6IFwidmFsdWVcIiB9IH1gXG4gKlxuICogVGhlIHZhbHVlIGNhbiBiZSBlaXRoZXIgYSBzaW5nbGUgc3RyaW5nIHZhbHVlIG9yIGFuIGFycmF5IG9mIHN0cmluZyB2YWx1ZXMuXG4gKlxuICogRm9yIG1vcmUgaW5mb3JtYXRpb24sIGluY2x1ZGluZyB3aGljaCBvcGVyYXRvcnMgYXJlIHN1cHBvcnRlZCwgc2VlIFt0aGUgSUFNXG4gKiBkb2N1bWVudGF0aW9uXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2VsZW1lbnRzX2NvbmRpdGlvbi5odG1sKS5cbiAqL1xuZXhwb3J0IHR5cGUgQ29uZGl0aW9ucyA9IFJlY29yZDxzdHJpbmcsIENvbmRpdGlvbj47XG5cbi8qKlxuICogSW50ZXJmYWNlIGZvciBjcmVhdGluZyBhIHBvbGljeSBzdGF0ZW1lbnRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQb2xpY3lTdGF0ZW1lbnRQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgU2lkIChzdGF0ZW1lbnQgSUQpIGlzIGFuIG9wdGlvbmFsIGlkZW50aWZpZXIgdGhhdCB5b3UgcHJvdmlkZSBmb3IgdGhlXG4gICAqIHBvbGljeSBzdGF0ZW1lbnQuIFlvdSBjYW4gYXNzaWduIGEgU2lkIHZhbHVlIHRvIGVhY2ggc3RhdGVtZW50IGluIGFcbiAgICogc3RhdGVtZW50IGFycmF5LiBJbiBzZXJ2aWNlcyB0aGF0IGxldCB5b3Ugc3BlY2lmeSBhbiBJRCBlbGVtZW50LCBzdWNoIGFzXG4gICAqIFNRUyBhbmQgU05TLCB0aGUgU2lkIHZhbHVlIGlzIGp1c3QgYSBzdWItSUQgb2YgdGhlIHBvbGljeSBkb2N1bWVudCdzIElELiBJblxuICAgKiBJQU0sIHRoZSBTaWQgdmFsdWUgbXVzdCBiZSB1bmlxdWUgd2l0aGluIGEgSlNPTiBwb2xpY3kuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gc2lkXG4gICAqL1xuICByZWFkb25seSBzaWQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIExpc3Qgb2YgYWN0aW9ucyB0byBhZGQgdG8gdGhlIHN0YXRlbWVudFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGFjdGlvbnNcbiAgICovXG4gIHJlYWRvbmx5IGFjdGlvbnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTGlzdCBvZiBub3QgYWN0aW9ucyB0byBhZGQgdG8gdGhlIHN0YXRlbWVudFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIG5vdC1hY3Rpb25zXG4gICAqL1xuICByZWFkb25seSBub3RBY3Rpb25zPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIExpc3Qgb2YgcHJpbmNpcGFscyB0byBhZGQgdG8gdGhlIHN0YXRlbWVudFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHByaW5jaXBhbHNcbiAgICovXG4gIHJlYWRvbmx5IHByaW5jaXBhbHM/OiBJUHJpbmNpcGFsW107XG5cbiAgLyoqXG4gICAqIExpc3Qgb2Ygbm90IHByaW5jaXBhbHMgdG8gYWRkIHRvIHRoZSBzdGF0ZW1lbnRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBub3QgcHJpbmNpcGFsc1xuICAgKi9cbiAgcmVhZG9ubHkgbm90UHJpbmNpcGFscz86IElQcmluY2lwYWxbXTtcblxuICAvKipcbiAgICogUmVzb3VyY2UgQVJOcyB0byBhZGQgdG8gdGhlIHN0YXRlbWVudFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHJlc291cmNlc1xuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIE5vdFJlc291cmNlIEFSTnMgdG8gYWRkIHRvIHRoZSBzdGF0ZW1lbnRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBub3QtcmVzb3VyY2VzXG4gICAqL1xuICByZWFkb25seSBub3RSZXNvdXJjZXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogQ29uZGl0aW9ucyB0byBhZGQgdG8gdGhlIHN0YXRlbWVudFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGNvbmRpdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgY29uZGl0aW9ucz86IHtba2V5OiBzdHJpbmddOiBhbnl9O1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGFsbG93IG9yIGRlbnkgdGhlIGFjdGlvbnMgaW4gdGhpcyBzdGF0ZW1lbnRcbiAgICpcbiAgICogQGRlZmF1bHQgRWZmZWN0LkFMTE9XXG4gICAqL1xuICByZWFkb25seSBlZmZlY3Q/OiBFZmZlY3Q7XG59XG5cbmNsYXNzIEpzb25QcmluY2lwYWwgZXh0ZW5kcyBQcmluY2lwYWxCYXNlIHtcbiAgcHVibGljIHJlYWRvbmx5IHBvbGljeUZyYWdtZW50OiBQcmluY2lwYWxQb2xpY3lGcmFnbWVudDtcblxuICBjb25zdHJ1Y3Rvcihqc29uOiBhbnkgPSB7IH0pIHtcbiAgICBzdXBlcigpO1xuXG4gICAgLy8gc3BlY2lhbCBjYXNlOiBpZiBwcmluY2lwYWwgaXMgYSBzdHJpbmcsIHR1cm4gaXQgaW50byBhIFwiTGl0ZXJhbFN0cmluZ1wiIHByaW5jaXBhbCxcbiAgICAvLyBzbyB3ZSByZW5kZXIgdGhlIGV4YWN0IHNhbWUgc3RyaW5nIGJhY2sgb3V0LlxuICAgIGlmICh0eXBlb2YoanNvbikgPT09ICdzdHJpbmcnKSB7XG4gICAgICBqc29uID0geyBbTElURVJBTF9TVFJJTkdfS0VZXTogW2pzb25dIH07XG4gICAgfVxuICAgIGlmICh0eXBlb2YoanNvbikgIT09ICdvYmplY3QnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEpTT04gSUFNIHByaW5jaXBhbCBzaG91bGQgYmUgYW4gb2JqZWN0LCBnb3QgJHtKU09OLnN0cmluZ2lmeShqc29uKX1gKTtcbiAgICB9XG5cbiAgICB0aGlzLnBvbGljeUZyYWdtZW50ID0ge1xuICAgICAgcHJpbmNpcGFsSnNvbjoganNvbixcbiAgICAgIGNvbmRpdGlvbnM6IHt9LFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgZGVkdXBlU3RyaW5nKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMucG9saWN5RnJhZ21lbnQpO1xuICB9XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgX2VzdGltYXRlU2l6ZVxuICpcbiAqIFRoZXNlIGNhbiBvcHRpb25hbGx5IGNvbWUgZnJvbSBjb250ZXh0LCBidXQgaXQncyB0b28gZXhwZW5zaXZlIHRvIGxvb2tcbiAqIHRoZW0gdXAgZXZlcnkgdGltZSBzbyB3ZSBidW5kbGUgdGhlbSBpbnRvIGEgc3RydWN0IGZpcnN0LlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVzdGltYXRlU2l6ZU9wdGlvbnMge1xuICAvKipcbiAgICogRXN0aW1hdGVkIHNpemUgb2YgYW4gdW5yZXNvbHZlZCBBUk5cbiAgICovXG4gIHJlYWRvbmx5IGFybkVzdGltYXRlOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEVzdGltYXRlZCBzaXplIG9mIGFuIHVucmVzb2x2ZWQgYWN0aW9uXG4gICAqL1xuICByZWFkb25seSBhY3Rpb25Fc3RpbWF0ZTogbnVtYmVyO1xufVxuXG4vKipcbiAqIERlcml2ZSB0aGUgc2l6ZSBlc3RpbWF0aW9uIG9wdGlvbnMgZnJvbSBjb250ZXh0XG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXJpdmVFc3RpbWF0ZVNpemVPcHRpb25zKHNjb3BlOiBJQ29uc3RydWN0KTogRXN0aW1hdGVTaXplT3B0aW9ucyB7XG4gIGNvbnN0IGFjdGlvbkVzdGltYXRlID0gMjA7XG4gIGNvbnN0IGFybkVzdGltYXRlID0gc2NvcGUubm9kZS50cnlHZXRDb250ZXh0KEFSTl9TSVpFX0VTVElNQVRFX0NPTlRFWFRfS0VZKSA/PyBERUZBVUxUX0FSTl9TSVpFX0VTVElNQVRFO1xuICBpZiAodHlwZW9mIGFybkVzdGltYXRlICE9PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ29udGV4dCB2YWx1ZSAke0FSTl9TSVpFX0VTVElNQVRFX0NPTlRFWFRfS0VZfSBzaG91bGQgYmUgYSBudW1iZXIsIGdvdCAke0pTT04uc3RyaW5naWZ5KGFybkVzdGltYXRlKX1gKTtcbiAgfVxuXG4gIHJldHVybiB7IGFjdGlvbkVzdGltYXRlLCBhcm5Fc3RpbWF0ZSB9O1xufSJdfQ==
\No newline at end of file